summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS4
-rw-r--r--Documentation/00-INDEX204
-rw-r--r--Documentation/ABI/README2
-rw-r--r--Documentation/ABI/testing/sysfs-block42
-rw-r--r--Documentation/ABI/testing/sysfs-bus-vfio-mdev111
-rw-r--r--Documentation/ABI/testing/sysfs-class-led14
-rw-r--r--Documentation/ABI/testing/sysfs-class-remoteproc50
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-slab2
-rw-r--r--Documentation/ABI/testing/sysfs-power45
-rw-r--r--Documentation/BUG-HUNTING246
-rw-r--r--Documentation/CodingStyle1063
-rw-r--r--Documentation/DocBook/Makefile7
-rw-r--r--Documentation/DocBook/alsa-driver-api.tmpl142
-rw-r--r--Documentation/DocBook/debugobjects.tmpl443
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl4
-rw-r--r--Documentation/DocBook/tracepoint.tmpl112
-rw-r--r--Documentation/DocBook/uio-howto.tmpl62
-rw-r--r--Documentation/DocBook/usb.tmpl992
-rw-r--r--Documentation/DocBook/writing-an-alsa-driver.tmpl6206
-rw-r--r--Documentation/Makefile.sphinx22
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.html25
-rw-r--r--Documentation/RCU/whatisRCU.txt2
-rw-r--r--Documentation/SubmittingPatches842
-rw-r--r--Documentation/VGA-softcursor.txt39
-rw-r--r--Documentation/acpi/gpio-properties.txt62
-rw-r--r--Documentation/acpi/video_extension.txt2
-rw-r--r--Documentation/admin-guide/README.rst411
-rw-r--r--Documentation/admin-guide/binfmt-misc.rst151
-rw-r--r--Documentation/admin-guide/braille-console.rst38
-rw-r--r--Documentation/admin-guide/bug-bisect.rst76
-rw-r--r--Documentation/admin-guide/bug-hunting.rst369
-rw-r--r--Documentation/admin-guide/conf.py10
-rw-r--r--Documentation/admin-guide/devices.rst268
-rw-r--r--Documentation/admin-guide/devices.txt (renamed from Documentation/devices.txt)1176
-rw-r--r--Documentation/admin-guide/dynamic-debug-howto.rst353
-rw-r--r--Documentation/admin-guide/index.rst68
-rw-r--r--Documentation/admin-guide/init.rst (renamed from Documentation/init.txt)29
-rw-r--r--Documentation/admin-guide/initrd.rst (renamed from Documentation/initrd.txt)199
-rw-r--r--Documentation/admin-guide/java.rst (renamed from Documentation/java.txt)297
-rw-r--r--Documentation/admin-guide/kernel-parameters.rst209
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt (renamed from Documentation/kernel-parameters.txt)269
-rw-r--r--Documentation/admin-guide/md.rst (renamed from Documentation/md.txt)528
-rw-r--r--Documentation/admin-guide/module-signing.rst (renamed from Documentation/module-signing.txt)128
-rw-r--r--Documentation/admin-guide/mono.rst (renamed from Documentation/mono.txt)44
-rw-r--r--Documentation/admin-guide/parport.rst286
-rw-r--r--Documentation/admin-guide/ramoops.rst (renamed from Documentation/ramoops.txt)88
-rw-r--r--Documentation/admin-guide/reporting-bugs.rst (renamed from REPORTING-BUGS)70
-rw-r--r--Documentation/admin-guide/security-bugs.rst (renamed from Documentation/SecurityBugs)14
-rw-r--r--Documentation/admin-guide/serial-console.rst (renamed from Documentation/serial-console.txt)68
-rw-r--r--Documentation/admin-guide/sysfs-rules.rst192
-rw-r--r--Documentation/admin-guide/sysrq.rst289
-rw-r--r--Documentation/admin-guide/tainted-kernels.rst59
-rw-r--r--Documentation/admin-guide/unicode.rst (renamed from Documentation/unicode.txt)24
-rw-r--r--Documentation/admin-guide/vga-softcursor.rst66
-rw-r--r--Documentation/arm/Booting2
-rw-r--r--Documentation/assoc_array.txt574
-rw-r--r--Documentation/bad_memory.txt45
-rw-r--r--Documentation/basic_profiling.txt56
-rw-r--r--Documentation/binfmt_misc.txt131
-rw-r--r--Documentation/block/biodoc.txt6
-rw-r--r--Documentation/block/cfq-iosched.txt32
-rw-r--r--Documentation/block/null_blk.txt2
-rw-r--r--Documentation/block/queue-sysfs.txt23
-rw-r--r--Documentation/blockdev/cciss.txt2
-rw-r--r--Documentation/blockdev/ramdisk.txt2
-rw-r--r--Documentation/braille-console.txt34
-rw-r--r--Documentation/cgroup-v1/00-INDEX2
-rw-r--r--Documentation/circular-buffers.txt4
-rw-r--r--Documentation/conf.py22
-rw-r--r--Documentation/core-api/assoc_array.rst551
-rw-r--r--Documentation/core-api/atomic_ops.rst (renamed from Documentation/atomic_ops.txt)340
-rw-r--r--Documentation/core-api/conf.py10
-rw-r--r--Documentation/core-api/debug-objects.rst310
-rw-r--r--Documentation/core-api/index.rst33
-rw-r--r--Documentation/core-api/local_ops.rst206
-rw-r--r--Documentation/core-api/tracepoint.rst55
-rw-r--r--Documentation/core-api/workqueue.rst (renamed from Documentation/workqueue.txt)260
-rw-r--r--Documentation/cpu-freq/cpufreq-stats.txt6
-rw-r--r--Documentation/cpu-freq/intel-pstate.txt54
-rw-r--r--Documentation/cpu-hotplug.txt32
-rw-r--r--Documentation/dev-tools/conf.py10
-rw-r--r--Documentation/dev-tools/gcov.rst8
-rw-r--r--Documentation/dev-tools/index.rst (renamed from Documentation/dev-tools/tools.rst)8
-rw-r--r--Documentation/dev-tools/kcov.rst4
-rw-r--r--Documentation/development-process/index.rst9
-rw-r--r--Documentation/device-mapper/dm-raid.txt8
-rw-r--r--Documentation/devicetree/bindings/arm/arch_timer.txt5
-rw-r--r--Documentation/devicetree/bindings/clock/exynos5433-clock.txt13
-rw-r--r--Documentation/devicetree/bindings/clock/hisi-crg.txt (renamed from Documentation/devicetree/bindings/clock/hi3519-crg.txt)12
-rw-r--r--Documentation/devicetree/bindings/clock/oxnas,stdclk.txt19
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmcc.txt37
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt5
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt59
-rw-r--r--Documentation/devicetree/bindings/clock/st,stm32-rcc.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi-ccu.txt1
-rw-r--r--Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt78
-rw-r--r--Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt112
-rw-r--r--Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt14
-rw-r--r--Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt2
-rw-r--r--Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt4
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt (renamed from Documentation/devicetree/bindings/display/ti/ti,tfp410.txt)9
-rw-r--r--Documentation/devicetree/bindings/display/mxsfb.txt53
-rw-r--r--Documentation/devicetree/bindings/display/panel/auo,g133han01.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/auo,g185han01.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/display-timing.txt8
-rw-r--r--Documentation/devicetree/bindings/display/panel/nvd,9128.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt36
-rw-r--r--Documentation/devicetree/bindings/display/renesas,du.txt12
-rw-r--r--Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt10
-rw-r--r--Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt6
-rw-r--r--Documentation/devicetree/bindings/display/zte,vou.txt84
-rw-r--r--Documentation/devicetree/bindings/dma/st_fdma.txt87
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-sx150x.txt41
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio_oxnas.txt2
-rw-r--r--Documentation/devicetree/bindings/leds/pca963x.txt3
-rw-r--r--Documentation/devicetree/bindings/mfd/lp873x.txt8
-rw-r--r--Documentation/devicetree/bindings/mfd/max77620.txt12
-rw-r--r--Documentation/devicetree/bindings/mfd/tps65086.txt2
-rw-r--r--Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt32
-rw-r--r--Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt9
-rw-r--r--Documentation/devicetree/bindings/mmc/renesas,mmcif.txt3
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-cadence.txt30
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.txt1
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci.txt13
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt8
-rw-r--r--Documentation/devicetree/bindings/mmc/tmio_mmc.txt2
-rw-r--r--Documentation/devicetree/bindings/net/brcm,amac.txt16
-rw-r--r--Documentation/devicetree/bindings/net/can/rcar_can.txt12
-rw-r--r--Documentation/devicetree/bindings/net/can/rcar_canfd.txt14
-rw-r--r--Documentation/devicetree/bindings/net/cpsw.txt8
-rw-r--r--Documentation/devicetree/bindings/net/dsa/marvell.txt24
-rw-r--r--Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt27
-rw-r--r--Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt8
-rw-r--r--Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt7
-rw-r--r--Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt4
-rw-r--r--Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt51
-rw-r--r--Documentation/devicetree/bindings/net/oxnas-dwmac.txt39
-rw-r--r--Documentation/devicetree/bindings/net/phy.txt6
-rw-r--r--Documentation/devicetree/bindings/net/smsc-lan91c111.txt2
-rw-r--r--Documentation/devicetree/bindings/net/stmmac.txt14
-rw-r--r--Documentation/devicetree/bindings/net/ti,dp83867.txt12
-rw-r--r--Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt (renamed from Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt)8
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt48
-rw-r--r--Documentation/devicetree/bindings/opp/opp.txt27
-rw-r--r--Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt30
-rw-r--r--Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt44
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt9
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt74
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt177
-rw-r--r--Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt9
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt19
-rw-r--r--Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt55
-rw-r--r--Documentation/devicetree/bindings/power/domain-idle-state.txt33
-rw-r--r--Documentation/devicetree/bindings/power/power_domain.txt43
-rw-r--r--Documentation/devicetree/bindings/regulator/pwm-regulator.txt4
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt98
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt30
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/ramoops.txt3
-rw-r--r--Documentation/devicetree/bindings/reset/renesas,rst.txt37
-rw-r--r--Documentation/devicetree/bindings/rtc/maxim,ds3231.txt2
-rw-r--r--Documentation/devicetree/bindings/rtc/pcf8563.txt2
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/guts.txt (renamed from Documentation/devicetree/bindings/powerpc/fsl/guts.txt)3
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt7
-rw-r--r--Documentation/devicetree/bindings/submitting-patches.txt2
-rw-r--r--Documentation/devicetree/bindings/thermal/rockchip-thermal.txt3
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt33
-rw-r--r--Documentation/devicetree/booting-without-of.txt7
-rw-r--r--Documentation/doc-guide/conf.py10
-rw-r--r--Documentation/doc-guide/docbook.rst90
-rw-r--r--Documentation/doc-guide/index.rst20
-rw-r--r--Documentation/doc-guide/kernel-doc.rst (renamed from Documentation/kernel-documentation.rst)323
-rw-r--r--Documentation/doc-guide/parse-headers.rst192
-rw-r--r--Documentation/doc-guide/sphinx.rst219
-rw-r--r--Documentation/driver-api/80211/cfg80211.rst (renamed from Documentation/80211/cfg80211.rst)0
-rw-r--r--Documentation/driver-api/80211/conf.py (renamed from Documentation/80211/conf.py)5
-rw-r--r--Documentation/driver-api/80211/index.rst (renamed from Documentation/80211/index.rst)2
-rw-r--r--Documentation/driver-api/80211/introduction.rst (renamed from Documentation/80211/introduction.rst)0
-rw-r--r--Documentation/driver-api/80211/mac80211-advanced.rst (renamed from Documentation/80211/mac80211-advanced.rst)0
-rw-r--r--Documentation/driver-api/80211/mac80211.rst (renamed from Documentation/80211/mac80211.rst)0
-rw-r--r--Documentation/driver-api/conf.py10
-rw-r--r--Documentation/driver-api/device_link.rst279
-rw-r--r--Documentation/driver-api/dma-buf.rst73
-rw-r--r--Documentation/driver-api/index.rst12
-rw-r--r--Documentation/driver-api/infrastructure.rst70
-rw-r--r--Documentation/driver-api/usb.rst748
-rw-r--r--Documentation/driver-api/vme.rst (renamed from Documentation/vme_api.txt)115
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/dynamic-debug-howto.txt340
-rw-r--r--Documentation/filesystems/locks.txt2
-rw-r--r--Documentation/filesystems/nfs/nfsroot.txt4
-rw-r--r--Documentation/filesystems/proc.txt13
-rw-r--r--Documentation/frv/booting.txt2
-rw-r--r--Documentation/gpio/driver.txt62
-rw-r--r--Documentation/gpu/conf.py5
-rw-r--r--Documentation/gpu/drm-internals.rst20
-rw-r--r--Documentation/gpu/drm-kms-helpers.rst11
-rw-r--r--Documentation/gpu/drm-kms.rst97
-rw-r--r--Documentation/gpu/drm-mm.rst2
-rw-r--r--Documentation/gpu/drm-uapi.rst6
-rw-r--r--Documentation/gpu/i915.rst17
-rw-r--r--Documentation/gpu/index.rst2
-rw-r--r--Documentation/hwmon/submitting-patches8
-rw-r--r--Documentation/index.rst62
-rw-r--r--Documentation/isdn/README2
-rw-r--r--Documentation/kbuild/kconfig-language.txt29
-rw-r--r--Documentation/kernel-doc-nano-HOWTO.txt2
-rw-r--r--Documentation/kernel-per-CPU-kthreads.txt2
-rw-r--r--Documentation/kselftest.txt11
-rw-r--r--Documentation/leds/leds-lp5523.txt4
-rw-r--r--Documentation/leds/uleds.txt36
-rw-r--r--Documentation/local_ops.txt191
-rw-r--r--Documentation/lockup-watchdogs.txt4
-rw-r--r--Documentation/m68k/kernel-options.txt2
-rw-r--r--Documentation/magic-number.txt158
-rw-r--r--Documentation/media/.gitignore3
-rw-r--r--Documentation/media/Makefile74
-rw-r--r--Documentation/media/dvb-drivers/intro.rst4
-rw-r--r--Documentation/media/index.rst5
-rw-r--r--Documentation/media/intro.rst4
-rw-r--r--Documentation/media/media_api_files/typical_media_device.pdfbin52895 -> 0 bytes
-rw-r--r--Documentation/media/typical_media_device.svg (renamed from Documentation/media/media_api_files/typical_media_device.svg)0
-rw-r--r--Documentation/media/uapi/dvb/dvbstb.svg651
-rw-r--r--Documentation/media/uapi/dvb/intro.rst4
-rw-r--r--Documentation/media/uapi/dvb/intro_files/dvbstb.pdfbin1881 -> 0 bytes
-rw-r--r--Documentation/media/uapi/dvb/intro_files/dvbstb.pngbin22655 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/bayer.svg984
-rw-r--r--Documentation/media/uapi/v4l/constraints.svg346
-rw-r--r--Documentation/media/uapi/v4l/crop.rst4
-rw-r--r--Documentation/media/uapi/v4l/crop.svg281
-rw-r--r--Documentation/media/uapi/v4l/crop_files/crop.gifbin5967 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/crop_files/crop.pdfbin5846 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi.rst12
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gifbin4741 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdfbin3706 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gifbin5095 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdfbin3996 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gifbin2400 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdfbin7405 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev.rst16
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdfbin20276 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pngbin12130 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdfbin20729 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg63
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdfbin46311 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg163
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdfbin36714 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg116
-rw-r--r--Documentation/media/uapi/v4l/diff-v4l.rst4
-rw-r--r--Documentation/media/uapi/v4l/field-order.rst8
-rw-r--r--Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gifbin25430 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdfbin9185 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gifbin25323 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdfbin9173 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/fieldseq_bt.svg2613
-rw-r--r--Documentation/media/uapi/v4l/fieldseq_tb.svg2607
-rw-r--r--Documentation/media/uapi/v4l/nv12mt.svg450
-rw-r--r--Documentation/media/uapi/v4l/nv12mt_example.svg1589
-rw-r--r--Documentation/media/uapi/v4l/pipeline.dot12
-rw-r--r--Documentation/media/uapi/v4l/pixfmt-nv12mt.rst8
-rw-r--r--Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.pngbin1920 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.pngbin5261 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/selection-api-003.rst4
-rw-r--r--Documentation/media/uapi/v4l/selection-api-003_files/selection.pngbin11716 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/selection.svg5812
-rw-r--r--Documentation/media/uapi/v4l/subdev-formats.rst19
-rw-r--r--Documentation/media/uapi/v4l/subdev-formats_files/bayer.pngbin9725 -> 0 bytes
-rw-r--r--Documentation/media/uapi/v4l/subdev-image-processing-crop.svg313
-rw-r--r--Documentation/media/uapi/v4l/subdev-image-processing-full.svg769
-rw-r--r--Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg560
-rw-r--r--Documentation/media/uapi/v4l/vbi_525.svg811
-rw-r--r--Documentation/media/uapi/v4l/vbi_625.svg858
-rw-r--r--Documentation/media/uapi/v4l/vbi_hsync.svg313
-rw-r--r--Documentation/media/uapi/v4l/vidioc-g-selection.rst4
-rw-r--r--Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.pngbin3313 -> 0 bytes
-rw-r--r--Documentation/media/v4l-drivers/bttv.rst4
-rw-r--r--Documentation/media/v4l-drivers/cafe_ccic.rst4
-rw-r--r--Documentation/memory-hotplug.txt2
-rw-r--r--Documentation/networking/batman-adv.txt35
-rw-r--r--Documentation/networking/ieee802154.txt26
-rw-r--r--Documentation/networking/ip-sysctl.txt33
-rw-r--r--Documentation/networking/l2tp.txt8
-rw-r--r--Documentation/networking/mac80211_hwsim/README2
-rw-r--r--Documentation/networking/netconsole.txt2
-rw-r--r--Documentation/networking/netdev-FAQ.txt8
-rw-r--r--Documentation/networking/nf_conntrack-sysctl.txt11
-rw-r--r--Documentation/networking/phy.txt149
-rw-r--r--Documentation/networking/seg6-sysctl.txt18
-rw-r--r--Documentation/networking/stmmac.txt71
-rw-r--r--Documentation/networking/timestamping.txt10
-rw-r--r--Documentation/networking/vortex.txt2
-rw-r--r--Documentation/oops-tracing.txt279
-rw-r--r--Documentation/parport.txt267
-rw-r--r--Documentation/power/00-INDEX2
-rw-r--r--Documentation/power/devices.txt14
-rw-r--r--Documentation/power/pci.txt10
-rw-r--r--Documentation/power/runtime_pm.txt2
-rw-r--r--Documentation/power/states.txt62
-rw-r--r--Documentation/power/swsusp-dmcrypt.txt2
-rw-r--r--Documentation/process/1.Intro.rst (renamed from Documentation/development-process/1.Intro.rst)4
-rw-r--r--Documentation/process/2.Process.rst (renamed from Documentation/development-process/2.Process.rst)0
-rw-r--r--Documentation/process/3.Early-stage.rst (renamed from Documentation/development-process/3.Early-stage.rst)0
-rw-r--r--Documentation/process/4.Coding.rst (renamed from Documentation/development-process/4.Coding.rst)8
-rw-r--r--Documentation/process/5.Posting.rst (renamed from Documentation/development-process/5.Posting.rst)12
-rw-r--r--Documentation/process/6.Followthrough.rst (renamed from Documentation/development-process/6.Followthrough.rst)0
-rw-r--r--Documentation/process/7.AdvancedTopics.rst (renamed from Documentation/development-process/7.AdvancedTopics.rst)2
-rw-r--r--Documentation/process/8.Conclusion.rst (renamed from Documentation/development-process/8.Conclusion.rst)6
-rw-r--r--Documentation/process/adding-syscalls.rst (renamed from Documentation/adding-syscalls.txt)269
-rw-r--r--Documentation/process/applying-patches.rst (renamed from Documentation/applying-patches.txt)7
-rw-r--r--Documentation/process/changes.rst (renamed from Documentation/Changes)2
-rw-r--r--Documentation/process/code-of-conflict.rst (renamed from Documentation/CodeOfConflict)3
-rw-r--r--Documentation/process/coding-style.rst1062
-rw-r--r--Documentation/process/conf.py (renamed from Documentation/development-process/conf.py)2
-rw-r--r--Documentation/process/development-process.rst (renamed from Documentation/development-process/development-process.rst)1
-rw-r--r--Documentation/process/email-clients.rst (renamed from Documentation/email-clients.txt)0
-rw-r--r--Documentation/process/howto.rst (renamed from Documentation/HOWTO)58
-rw-r--r--Documentation/process/index.rst57
-rw-r--r--Documentation/process/kernel-docs.rst (renamed from Documentation/kernel-docs.txt)0
-rw-r--r--Documentation/process/magic-number.rst164
-rw-r--r--Documentation/process/management-style.rst (renamed from Documentation/ManagementStyle)2
-rw-r--r--Documentation/process/stable-api-nonsense.rst (renamed from Documentation/stable_api_nonsense.txt)0
-rw-r--r--Documentation/process/stable-kernel-rules.rst (renamed from Documentation/stable_kernel_rules.txt)4
-rw-r--r--Documentation/process/submit-checklist.rst (renamed from Documentation/SubmitChecklist)6
-rw-r--r--Documentation/process/submitting-drivers.rst (renamed from Documentation/SubmittingDrivers)16
-rw-r--r--Documentation/process/submitting-patches.rst836
-rw-r--r--Documentation/process/volatile-considered-harmful.rst (renamed from Documentation/volatile-considered-harmful.txt)22
-rw-r--r--Documentation/rfkill.txt2
-rw-r--r--Documentation/scheduler/completion.txt3
-rw-r--r--Documentation/scsi/scsi-parameters.txt2
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt2
-rw-r--r--Documentation/scsi/sym53c8xx_2.txt2
-rw-r--r--Documentation/security/conf.py8
-rw-r--r--Documentation/security/index.rst7
-rw-r--r--Documentation/security/tpm/index.rst7
-rw-r--r--Documentation/security/tpm/tpm_vtpm_proxy.rst (renamed from Documentation/tpm/tpm_vtpm_proxy.txt)55
-rw-r--r--Documentation/security/tpm/xen-tpmfront.txt (renamed from Documentation/tpm/xen-tpmfront.txt)0
-rw-r--r--Documentation/sound/alsa-configuration.rst2683
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2330
-rw-r--r--Documentation/sound/alsa/ControlNames.txt107
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt324
-rw-r--r--Documentation/sound/alsa/VIA82xx-mixer.txt8
-rw-r--r--Documentation/sound/alsa/alsa-parameters.txt135
-rw-r--r--Documentation/sound/alsa/seq_oss.html409
-rw-r--r--Documentation/sound/cards/audigy-mixer.rst (renamed from Documentation/sound/alsa/Audigy-mixer.txt)297
-rw-r--r--Documentation/sound/cards/audiophile-usb.rst (renamed from Documentation/sound/alsa/Audiophile-Usb.txt)258
-rw-r--r--Documentation/sound/cards/bt87x.rst (renamed from Documentation/sound/alsa/Bt87x.txt)23
-rw-r--r--Documentation/sound/cards/cmipci.rst (renamed from Documentation/sound/alsa/CMIPCI.txt)62
-rw-r--r--Documentation/sound/cards/emu10k1-jack.rst (renamed from Documentation/sound/alsa/emu10k1-jack.txt)20
-rw-r--r--Documentation/sound/cards/hdspm.rst (renamed from Documentation/sound/alsa/hdspm.txt)253
-rw-r--r--Documentation/sound/cards/img-spdif-in.rst (renamed from Documentation/sound/alsa/img,spdif-in.txt)24
-rw-r--r--Documentation/sound/cards/index.rst19
-rw-r--r--Documentation/sound/cards/joystick.rst (renamed from Documentation/sound/alsa/Joystick.txt)71
-rw-r--r--Documentation/sound/cards/maya44.rst (renamed from Documentation/sound/alsa/README.maya44)137
-rw-r--r--Documentation/sound/cards/mixart.rst (renamed from Documentation/sound/alsa/MIXART.txt)26
-rw-r--r--Documentation/sound/cards/sb-live-mixer.rst (renamed from Documentation/sound/alsa/SB-Live-mixer.txt)337
-rw-r--r--Documentation/sound/cards/serial-u16550.rst (renamed from Documentation/sound/alsa/serial-u16550.txt)21
-rw-r--r--Documentation/sound/cards/via82xx-mixer.rst8
-rw-r--r--Documentation/sound/designs/channel-mapping-api.rst (renamed from Documentation/sound/alsa/Channel-Mapping-API.txt)77
-rw-r--r--Documentation/sound/designs/compress-offload.rst (renamed from Documentation/sound/alsa/compress_offload.txt)127
-rw-r--r--Documentation/sound/designs/control-names.rst142
-rw-r--r--Documentation/sound/designs/index.rst15
-rw-r--r--Documentation/sound/designs/jack-controls.rst (renamed from Documentation/sound/alsa/Jack-Controls.txt)13
-rw-r--r--Documentation/sound/designs/oss-emulation.rst (renamed from Documentation/sound/alsa/OSS-Emulation.txt)169
-rw-r--r--Documentation/sound/designs/powersave.rst (renamed from Documentation/sound/alsa/powersave.txt)16
-rw-r--r--Documentation/sound/designs/procfile.rst (renamed from Documentation/sound/alsa/Procfile.txt)106
-rw-r--r--Documentation/sound/designs/seq-oss.rst371
-rw-r--r--Documentation/sound/designs/timestamping.rst (renamed from Documentation/sound/alsa/timestamping.txt)143
-rw-r--r--Documentation/sound/hd-audio/controls.rst (renamed from Documentation/sound/alsa/HD-Audio-Controls.txt)33
-rw-r--r--Documentation/sound/hd-audio/dp-mst.rst (renamed from Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt)30
-rw-r--r--Documentation/sound/hd-audio/index.rst10
-rw-r--r--Documentation/sound/hd-audio/models.rst518
-rw-r--r--Documentation/sound/hd-audio/notes.rst (renamed from Documentation/sound/alsa/HD-Audio.txt)635
-rw-r--r--Documentation/sound/index.rst20
-rw-r--r--Documentation/sound/kernel-api/alsa-driver-api.rst134
-rw-r--r--Documentation/sound/kernel-api/index.rst8
-rw-r--r--Documentation/sound/kernel-api/writing-an-alsa-driver.rst4219
-rw-r--r--Documentation/sound/oss/oss-parameters.txt2
-rw-r--r--Documentation/sound/soc/clocking.rst (renamed from Documentation/sound/alsa/soc/clocking.txt)13
-rw-r--r--Documentation/sound/soc/codec-to-codec.rst108
-rw-r--r--Documentation/sound/soc/codec.rst (renamed from Documentation/sound/alsa/soc/codec.txt)75
-rw-r--r--Documentation/sound/soc/dai.rst (renamed from Documentation/sound/alsa/soc/DAI.txt)28
-rw-r--r--Documentation/sound/soc/dapm.rst (renamed from Documentation/sound/alsa/soc/dapm.txt)249
-rw-r--r--Documentation/sound/soc/dpcm.rst (renamed from Documentation/sound/alsa/soc/DPCM.txt)280
-rw-r--r--Documentation/sound/soc/index.rst20
-rw-r--r--Documentation/sound/soc/jack.rst (renamed from Documentation/sound/alsa/soc/jack.txt)1
-rw-r--r--Documentation/sound/soc/machine.rst (renamed from Documentation/sound/alsa/soc/machine.txt)22
-rw-r--r--Documentation/sound/soc/overview.rst (renamed from Documentation/sound/alsa/soc/overview.txt)32
-rw-r--r--Documentation/sound/soc/platform.rst (renamed from Documentation/sound/alsa/soc/platform.txt)31
-rw-r--r--Documentation/sound/soc/pops-clicks.rst (renamed from Documentation/sound/alsa/soc/pops_clicks.txt)15
-rw-r--r--Documentation/sphinx/kerneldoc.py (renamed from Documentation/sphinx/kernel-doc.py)0
-rwxr-xr-xDocumentation/sphinx/parse-headers.pl95
-rw-r--r--Documentation/sync_file.txt14
-rw-r--r--Documentation/sysctl/kernel.txt12
-rw-r--r--Documentation/sysfs-rules.txt184
-rw-r--r--Documentation/sysrq.txt257
-rw-r--r--Documentation/trace/ftrace.txt20
-rw-r--r--Documentation/trace/uprobetracer.txt6
-rw-r--r--Documentation/translations/ja_JP/HOWTO (renamed from Documentation/ja_JP/HOWTO)24
-rw-r--r--Documentation/translations/ja_JP/SubmitChecklist (renamed from Documentation/ja_JP/SubmitChecklist)8
-rw-r--r--Documentation/translations/ja_JP/SubmittingPatches (renamed from Documentation/ja_JP/SubmittingPatches)18
-rw-r--r--Documentation/translations/ja_JP/stable_api_nonsense.txt (renamed from Documentation/ja_JP/stable_api_nonsense.txt)4
-rw-r--r--Documentation/translations/ja_JP/stable_kernel_rules.txt (renamed from Documentation/ja_JP/stable_kernel_rules.txt)6
-rw-r--r--Documentation/translations/ko_KR/howto.rst (renamed from Documentation/ko_KR/HOWTO)172
-rw-r--r--Documentation/translations/ko_KR/index.rst12
-rw-r--r--Documentation/translations/ko_KR/memory-barriers.txt (renamed from Documentation/ko_KR/memory-barriers.txt)36
-rw-r--r--Documentation/translations/ko_KR/stable_api_nonsense.txt (renamed from Documentation/ko_KR/stable_api_nonsense.txt)4
-rw-r--r--Documentation/translations/zh_CN/CodingStyle (renamed from Documentation/zh_CN/CodingStyle)8
-rw-r--r--Documentation/translations/zh_CN/HOWTO (renamed from Documentation/zh_CN/HOWTO)30
-rw-r--r--Documentation/translations/zh_CN/IRQ.txt (renamed from Documentation/zh_CN/IRQ.txt)0
-rw-r--r--Documentation/translations/zh_CN/SecurityBugs (renamed from Documentation/zh_CN/SecurityBugs)6
-rw-r--r--Documentation/translations/zh_CN/SubmittingDrivers (renamed from Documentation/zh_CN/SubmittingDrivers)12
-rw-r--r--Documentation/translations/zh_CN/SubmittingPatches (renamed from Documentation/zh_CN/SubmittingPatches)14
-rw-r--r--Documentation/translations/zh_CN/arm/Booting (renamed from Documentation/zh_CN/arm/Booting)2
-rw-r--r--Documentation/translations/zh_CN/arm/kernel_user_helpers.txt (renamed from Documentation/zh_CN/arm/kernel_user_helpers.txt)0
-rw-r--r--Documentation/translations/zh_CN/arm64/booting.txt (renamed from Documentation/zh_CN/arm64/booting.txt)0
-rw-r--r--Documentation/translations/zh_CN/arm64/legacy_instructions.txt (renamed from Documentation/zh_CN/arm64/legacy_instructions.txt)0
-rw-r--r--Documentation/translations/zh_CN/arm64/memory.txt (renamed from Documentation/zh_CN/arm64/memory.txt)0
-rw-r--r--Documentation/translations/zh_CN/arm64/silicon-errata.txt (renamed from Documentation/zh_CN/arm64/silicon-errata.txt)0
-rw-r--r--Documentation/translations/zh_CN/arm64/tagged-pointers.txt (renamed from Documentation/zh_CN/arm64/tagged-pointers.txt)0
-rw-r--r--Documentation/translations/zh_CN/basic_profiling.txt (renamed from Documentation/zh_CN/basic_profiling.txt)0
-rw-r--r--Documentation/translations/zh_CN/email-clients.txt (renamed from Documentation/zh_CN/email-clients.txt)4
-rw-r--r--Documentation/translations/zh_CN/filesystems/sysfs.txt (renamed from Documentation/zh_CN/filesystems/sysfs.txt)0
-rw-r--r--Documentation/translations/zh_CN/gpio.txt (renamed from Documentation/zh_CN/gpio.txt)0
-rw-r--r--Documentation/translations/zh_CN/io_ordering.txt (renamed from Documentation/zh_CN/io_ordering.txt)0
-rw-r--r--Documentation/translations/zh_CN/magic-number.txt (renamed from Documentation/zh_CN/magic-number.txt)0
-rw-r--r--Documentation/translations/zh_CN/oops-tracing.txt (renamed from Documentation/zh_CN/oops-tracing.txt)6
-rw-r--r--Documentation/translations/zh_CN/sparse.txt (renamed from Documentation/zh_CN/sparse.txt)0
-rw-r--r--Documentation/translations/zh_CN/stable_api_nonsense.txt (renamed from Documentation/zh_CN/stable_api_nonsense.txt)4
-rw-r--r--Documentation/translations/zh_CN/stable_kernel_rules.txt (renamed from Documentation/zh_CN/stable_kernel_rules.txt)6
-rw-r--r--Documentation/translations/zh_CN/video4linux/omap3isp.txt (renamed from Documentation/zh_CN/video4linux/omap3isp.txt)0
-rw-r--r--Documentation/translations/zh_CN/video4linux/v4l2-framework.txt (renamed from Documentation/zh_CN/video4linux/v4l2-framework.txt)0
-rw-r--r--Documentation/translations/zh_CN/volatile-considered-harmful.txt (renamed from Documentation/zh_CN/volatile-considered-harmful.txt)4
-rw-r--r--Documentation/vfio-mediated-device.txt398
-rw-r--r--Documentation/virtual/kvm/msr.txt9
-rw-r--r--Documentation/virtual/kvm/review-checklist.txt4
-rw-r--r--Documentation/vm/numa2
-rw-r--r--Documentation/vm/transhuge.txt5
-rw-r--r--Documentation/watchdog/convert_drivers_to_kernel_api.txt2
-rw-r--r--Documentation/watchdog/watchdog-parameters.txt2
-rw-r--r--Documentation/x86/boot.txt2
-rw-r--r--Documentation/x86/x86_64/boot-options.txt4
-rw-r--r--MAINTAINERS174
-rw-r--r--README408
-rw-r--r--arch/Kconfig11
-rw-r--r--arch/alpha/include/asm/mutex.h9
-rw-r--r--arch/alpha/include/asm/processor.h1
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/alpha/kernel/osf_sys.c8
-rw-r--r--arch/arc/include/asm/mutex.h18
-rw-r--r--arch/arc/include/asm/processor.h3
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/dra72-evm-revc.dts10
-rw-r--r--arch/arm/boot/dts/hisi-x5hd2.dtsi6
-rw-r--r--arch/arm/boot/dts/r8a7778.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7779.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7790.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7791.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7792.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7793.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7794.dtsi5
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev-rev-b.dts51
-rw-r--r--arch/arm/common/bL_switcher.c34
-rw-r--r--arch/arm/configs/multi_v7_defconfig8
-rw-r--r--arch/arm/configs/pxa_defconfig1
-rw-r--r--arch/arm/configs/qcom_defconfig1
-rw-r--r--arch/arm/include/asm/arch_gicv3.h54
-rw-r--r--arch/arm/include/asm/efi.h3
-rw-r--r--arch/arm/include/asm/io.h1
-rw-r--r--arch/arm/include/asm/mutex.h21
-rw-r--r--arch/arm/include/asm/processor.h2
-rw-r--r--arch/arm/include/asm/tlb.h21
-rw-r--r--arch/arm/kernel/hw_breakpoint.c47
-rw-r--r--arch/arm/mach-imx/gpc.c17
-rw-r--r--arch/arm/mach-integrator/impd1.c1
-rw-r--r--arch/arm/mach-pxa/idp.c1
-rw-r--r--arch/arm/mach-pxa/mainstone.c1
-rw-r--r--arch/arm/mach-pxa/stargate2.c1
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7778.c15
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c27
-rw-r--r--arch/arm/mach-shmobile/setup-rcar-gen2.c5
-rw-r--r--arch/arm64/boot/dts/broadcom/ns2-svk.dts5
-rw-r--r--arch/arm64/boot/dts/broadcom/ns2.dtsi12
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi6
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-db.dts23
-rw-r--r--arch/arm64/boot/dts/marvell/armada-37xx.dtsi23
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796.dtsi5
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399.dtsi1
-rw-r--r--arch/arm64/configs/defconfig1
-rw-r--r--arch/arm64/include/asm/Kbuild1
-rw-r--r--arch/arm64/include/asm/arch_gicv3.h61
-rw-r--r--arch/arm64/include/asm/efi.h3
-rw-r--r--arch/arm64/include/asm/io.h1
-rw-r--r--arch/arm64/include/asm/processor.h2
-rw-r--r--arch/arm64/kernel/cpuinfo.c36
-rw-r--r--arch/avr32/include/asm/mutex.h9
-rw-r--r--arch/avr32/include/asm/processor.h1
-rw-r--r--arch/avr32/include/uapi/asm/socket.h2
-rw-r--r--arch/avr32/include/uapi/asm/unistd.h3
-rw-r--r--arch/avr32/kernel/syscall_table.S3
-rw-r--r--arch/avr32/mach-at32ap/clock.c33
-rw-r--r--arch/avr32/mach-at32ap/pio.c6
-rw-r--r--arch/blackfin/include/asm/Kbuild1
-rw-r--r--arch/blackfin/include/asm/processor.h1
-rw-r--r--arch/c6x/include/asm/mutex.h6
-rw-r--r--arch/c6x/include/asm/processor.h1
-rw-r--r--arch/cris/boot/compressed/Makefile3
-rw-r--r--arch/cris/boot/rescue/Makefile9
-rw-r--r--arch/cris/include/asm/mutex.h9
-rw-r--r--arch/cris/include/asm/processor.h1
-rw-r--r--arch/frv/include/asm/mutex.h9
-rw-r--r--arch/frv/include/asm/processor.h1
-rw-r--r--arch/frv/include/uapi/asm/socket.h2
-rw-r--r--arch/h8300/include/asm/mutex.h9
-rw-r--r--arch/h8300/include/asm/processor.h1
-rw-r--r--arch/hexagon/include/asm/mutex.h8
-rw-r--r--arch/hexagon/include/asm/processor.h1
-rw-r--r--arch/ia64/include/asm/mutex.h90
-rw-r--r--arch/ia64/include/asm/processor.h1
-rw-r--r--arch/ia64/include/asm/tlb.h25
-rw-r--r--arch/ia64/include/uapi/asm/socket.h2
-rw-r--r--arch/ia64/kernel/err_inject.c74
-rw-r--r--arch/ia64/kernel/palinfo.c60
-rw-r--r--arch/ia64/kernel/salinfo.c83
-rw-r--r--arch/ia64/kernel/time.c4
-rw-r--r--arch/ia64/kernel/topology.c54
-rw-r--r--arch/m32r/Kconfig2
-rw-r--r--arch/m32r/include/asm/device.h6
-rw-r--r--arch/m32r/include/asm/dma-mapping.h32
-rw-r--r--arch/m32r/include/asm/mutex.h9
-rw-r--r--arch/m32r/include/asm/processor.h1
-rw-r--r--arch/m32r/include/uapi/asm/socket.h2
-rw-r--r--arch/m32r/platforms/m32700ut/setup.c2
-rw-r--r--arch/m68k/Kconfig.machine6
-rw-r--r--arch/m68k/amiga/config.c3
-rw-r--r--arch/m68k/atari/config.c2
-rw-r--r--arch/m68k/coldfire/Makefile1
-rw-r--r--arch/m68k/coldfire/amcore.c156
-rw-r--r--arch/m68k/coldfire/device.c159
-rw-r--r--arch/m68k/coldfire/m5206.c12
-rw-r--r--arch/m68k/coldfire/m520x.c24
-rw-r--r--arch/m68k/coldfire/m523x.c18
-rw-r--r--arch/m68k/coldfire/m5249.c25
-rw-r--r--arch/m68k/coldfire/m525x.c10
-rw-r--r--arch/m68k/coldfire/m527x.c28
-rw-r--r--arch/m68k/coldfire/m528x.c18
-rw-r--r--arch/m68k/coldfire/m5307.c14
-rw-r--r--arch/m68k/coldfire/m53xx.c20
-rw-r--r--arch/m68k/coldfire/m5407.c14
-rw-r--r--arch/m68k/coldfire/m5441x.c12
-rw-r--r--arch/m68k/coldfire/m54xx.c17
-rw-r--r--arch/m68k/configs/amcore_defconfig118
-rw-r--r--arch/m68k/emu/nfeth.c1
-rw-r--r--arch/m68k/include/asm/Kbuild1
-rw-r--r--arch/m68k/include/asm/m5206sim.h8
-rw-r--r--arch/m68k/include/asm/m520xsim.h8
-rw-r--r--arch/m68k/include/asm/m523xsim.h10
-rw-r--r--arch/m68k/include/asm/m527xsim.h8
-rw-r--r--arch/m68k/include/asm/m528xsim.h9
-rw-r--r--arch/m68k/include/asm/m5307sim.h9
-rw-r--r--arch/m68k/include/asm/m53xxsim.h8
-rw-r--r--arch/m68k/include/asm/m5407sim.h8
-rw-r--r--arch/m68k/include/asm/m54xxsim.h11
-rw-r--r--arch/m68k/include/asm/processor.h1
-rw-r--r--arch/metag/include/asm/Kbuild1
-rw-r--r--arch/metag/include/asm/processor.h1
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/include/asm/irq.h2
-rw-r--r--arch/microblaze/include/asm/mutex.h1
-rw-r--r--arch/microblaze/include/asm/processor.h1
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/intc.c196
-rw-r--r--arch/microblaze/kernel/irq.c4
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/mips/include/asm/processor.h1
-rw-r--r--arch/mips/include/uapi/asm/socket.h2
-rw-r--r--arch/mn10300/include/asm/mutex.h16
-rw-r--r--arch/mn10300/include/asm/processor.h1
-rw-r--r--arch/mn10300/include/uapi/asm/socket.h2
-rw-r--r--arch/mn10300/unit-asb2303/include/unit/smc91111.h2
-rw-r--r--arch/nios2/include/asm/mutex.h1
-rw-r--r--arch/nios2/include/asm/processor.h1
-rw-r--r--arch/openrisc/Kconfig4
-rw-r--r--arch/openrisc/README.openrisc8
-rw-r--r--arch/openrisc/TODO.openrisc3
-rw-r--r--arch/openrisc/include/asm/mutex.h27
-rw-r--r--arch/openrisc/include/asm/pgalloc.h1
-rw-r--r--arch/openrisc/include/asm/pgtable.h2
-rw-r--r--arch/openrisc/include/asm/processor.h1
-rw-r--r--arch/openrisc/kernel/entry.S12
-rw-r--r--arch/openrisc/kernel/process.c13
-rw-r--r--arch/openrisc/kernel/setup.c48
-rw-r--r--arch/openrisc/kernel/vmlinux.lds.S8
-rw-r--r--arch/openrisc/mm/init.c4
-rw-r--r--arch/openrisc/mm/ioremap.c4
-rw-r--r--arch/parisc/include/asm/Kbuild1
-rw-r--r--arch/parisc/include/asm/processor.h1
-rw-r--r--arch/parisc/include/uapi/asm/socket.h2
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/configs/dpaa.config3
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable.h13
-rw-r--r--arch/powerpc/include/asm/cputime.h14
-rw-r--r--arch/powerpc/include/asm/mutex.h132
-rw-r--r--arch/powerpc/include/asm/processor.h2
-rw-r--r--arch/powerpc/include/asm/spinlock.h8
-rw-r--r--arch/powerpc/include/asm/tlb.h16
-rw-r--r--arch/powerpc/include/asm/xilinx_intc.h2
-rw-r--r--arch/powerpc/include/uapi/asm/socket.h2
-rw-r--r--arch/powerpc/kernel/sysfs.c50
-rw-r--r--arch/powerpc/kernel/time.c8
-rw-r--r--arch/powerpc/kvm/book3s_hv.c48
-rw-r--r--arch/powerpc/mm/numa.c13
-rw-r--r--arch/powerpc/net/bpf_jit_comp64.c4
-rw-r--r--arch/powerpc/platforms/40x/Kconfig1
-rw-r--r--arch/powerpc/platforms/40x/virtex.c2
-rw-r--r--arch/powerpc/platforms/44x/Kconfig1
-rw-r--r--arch/powerpc/platforms/44x/virtex.c2
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c211
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/include/asm/mutex.h9
-rw-r--r--arch/s390/include/asm/processor.h5
-rw-r--r--arch/s390/include/asm/spinlock.h8
-rw-r--r--arch/s390/include/asm/tlb.h14
-rw-r--r--arch/s390/include/uapi/asm/socket.h2
-rw-r--r--arch/s390/kernel/processor.c4
-rw-r--r--arch/s390/kernel/smp.c45
-rw-r--r--arch/s390/kernel/vtime.c9
-rw-r--r--arch/s390/lib/spinlock.c25
-rw-r--r--arch/s390/mm/gmap.c2
-rw-r--r--arch/s390/net/bpf_jit_comp.c2
-rw-r--r--arch/score/include/asm/mutex.h6
-rw-r--r--arch/score/include/asm/processor.h1
-rw-r--r--arch/sh/include/asm/mutex-llsc.h109
-rw-r--r--arch/sh/include/asm/mutex.h12
-rw-r--r--arch/sh/include/asm/processor.h1
-rw-r--r--arch/sh/include/asm/tlb.h15
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/configs/sparc64_defconfig1
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/kdebug_64.h2
-rw-r--r--arch/sparc/include/asm/pgtable_64.h2
-rw-r--r--arch/sparc/include/asm/processor_32.h1
-rw-r--r--arch/sparc/include/asm/processor_64.h1
-rw-r--r--arch/sparc/include/asm/ptrace.h35
-rw-r--r--arch/sparc/include/asm/thread_info_64.h6
-rw-r--r--arch/sparc/include/asm/topology_64.h1
-rw-r--r--arch/sparc/include/asm/ttable.h6
-rw-r--r--arch/sparc/include/asm/uprobes.h59
-rw-r--r--arch/sparc/include/uapi/asm/socket.h2
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/leon_kernel.c56
-rw-r--r--arch/sparc/kernel/pci_sun4v.c7
-rw-r--r--arch/sparc/kernel/power.c7
-rw-r--r--arch/sparc/kernel/ptrace_64.c54
-rw-r--r--arch/sparc/kernel/signal_64.c2
-rw-r--r--arch/sparc/kernel/sysfs.c45
-rw-r--r--arch/sparc/kernel/traps_64.c4
-rw-r--r--arch/sparc/kernel/ttable_64.S2
-rw-r--r--arch/sparc/kernel/uprobes.c331
-rw-r--r--arch/tile/include/asm/Kbuild1
-rw-r--r--arch/tile/include/asm/processor.h2
-rw-r--r--arch/um/drivers/net_kern.c8
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/tlb.h15
-rw-r--r--arch/unicore32/include/asm/mutex.h20
-rw-r--r--arch/unicore32/include/asm/processor.h1
-rw-r--r--arch/x86/Kconfig93
-rw-r--r--arch/x86/boot/Makefile2
-rw-r--r--arch/x86/boot/compressed/eboot.c65
-rw-r--r--arch/x86/boot/compressed/head_64.S3
-rw-r--r--arch/x86/crypto/crc32c-intel_glue.c22
-rw-r--r--arch/x86/entry/calling.h33
-rw-r--r--arch/x86/entry/entry_32.S141
-rw-r--r--arch/x86/entry/entry_64.S16
-rw-r--r--arch/x86/entry/vdso/vma.c10
-rw-r--r--arch/x86/events/core.c10
-rw-r--r--arch/x86/events/intel/pt.c45
-rw-r--r--arch/x86/events/perf_event.h2
-rw-r--r--arch/x86/include/asm/Kbuild4
-rw-r--r--arch/x86/include/asm/acpi.h2
-rw-r--r--arch/x86/include/asm/amd_nb.h23
-rw-r--r--arch/x86/include/asm/apic.h5
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/include/asm/cpufeatures.h7
-rw-r--r--arch/x86/include/asm/efi.h16
-rw-r--r--arch/x86/include/asm/fpu/api.h10
-rw-r--r--arch/x86/include/asm/fpu/internal.h139
-rw-r--r--arch/x86/include/asm/fpu/types.h34
-rw-r--r--arch/x86/include/asm/fpu/xstate.h17
-rw-r--r--arch/x86/include/asm/idle.h22
-rw-r--r--arch/x86/include/asm/kdebug.h1
-rw-r--r--arch/x86/include/asm/kvm_page_track.h14
-rw-r--r--arch/x86/include/asm/lguest_hcall.h1
-rw-r--r--arch/x86/include/asm/mce.h34
-rw-r--r--arch/x86/include/asm/microcode.h18
-rw-r--r--arch/x86/include/asm/microcode_amd.h30
-rw-r--r--arch/x86/include/asm/microcode_intel.h4
-rw-r--r--arch/x86/include/asm/mmu_context.h2
-rw-r--r--arch/x86/include/asm/msr-index.h4
-rw-r--r--arch/x86/include/asm/msr.h46
-rw-r--r--arch/x86/include/asm/mutex.h5
-rw-r--r--arch/x86/include/asm/mutex_32.h110
-rw-r--r--arch/x86/include/asm/mutex_64.h127
-rw-r--r--arch/x86/include/asm/paravirt.h10
-rw-r--r--arch/x86/include/asm/paravirt_types.h18
-rw-r--r--arch/x86/include/asm/percpu.h11
-rw-r--r--arch/x86/include/asm/preempt.h8
-rw-r--r--arch/x86/include/asm/processor.h19
-rw-r--r--arch/x86/include/asm/qspinlock.h6
-rw-r--r--arch/x86/include/asm/special_insns.h13
-rw-r--r--arch/x86/include/asm/stacktrace.h8
-rw-r--r--arch/x86/include/asm/topology.h32
-rw-r--r--arch/x86/include/asm/trace/fpu.h5
-rw-r--r--arch/x86/include/asm/uaccess.h13
-rw-r--r--arch/x86/include/asm/unwind.h16
-rw-r--r--arch/x86/include/asm/vgtod.h7
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h1
-rw-r--r--arch/x86/include/uapi/asm/kvm_para.h4
-rw-r--r--arch/x86/include/uapi/asm/mce.h1
-rw-r--r--arch/x86/include/uapi/asm/prctl.h8
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/acpi/boot.c2
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S9
-rw-r--r--arch/x86/kernel/amd_nb.c164
-rw-r--r--arch/x86/kernel/apic/apic.c4
-rw-r--r--arch/x86/kernel/apic/io_apic.c1
-rw-r--r--arch/x86/kernel/apm_32.c4
-rw-r--r--arch/x86/kernel/cpu/Makefile4
-rw-r--r--arch/x86/kernel/cpu/amd.c51
-rw-r--r--arch/x86/kernel/cpu/bugs.c26
-rw-r--r--arch/x86/kernel/cpu/bugs_64.c33
-rw-r--r--arch/x86/kernel/cpu/common.c61
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c200
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c357
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c41
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c57
-rw-r--r--arch/x86/kernel/cpu/mcheck/threshold.c1
-rw-r--r--arch/x86/kernel/cpu/microcode/Makefile2
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c421
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c83
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c834
-rw-r--r--arch/x86/kernel/cpu/microcode/intel_lib.c184
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c1
-rw-r--r--arch/x86/kernel/cpu/scattered.c57
-rw-r--r--arch/x86/kernel/cpu/vmware.c86
-rw-r--r--arch/x86/kernel/cpuid.c73
-rw-r--r--arch/x86/kernel/dumpstack.c68
-rw-r--r--arch/x86/kernel/dumpstack_32.c56
-rw-r--r--arch/x86/kernel/dumpstack_64.c79
-rw-r--r--arch/x86/kernel/fpu/bugs.c7
-rw-r--r--arch/x86/kernel/fpu/core.c74
-rw-r--r--arch/x86/kernel/fpu/init.c107
-rw-r--r--arch/x86/kernel/fpu/signal.c8
-rw-r--r--arch/x86/kernel/fpu/xstate.c11
-rw-r--r--arch/x86/kernel/head_32.S49
-rw-r--r--arch/x86/kernel/head_64.S60
-rw-r--r--arch/x86/kernel/irq.c1
-rw-r--r--arch/x86/kernel/irq_64.c1
-rw-r--r--arch/x86/kernel/itmt.c215
-rw-r--r--arch/x86/kernel/kvm.c20
-rw-r--r--arch/x86/kernel/ldt.c14
-rw-r--r--arch/x86/kernel/msr.c69
-rw-r--r--arch/x86/kernel/paravirt-spinlocks.c14
-rw-r--r--arch/x86/kernel/paravirt.c1
-rw-r--r--arch/x86/kernel/paravirt_patch_32.c14
-rw-r--r--arch/x86/kernel/paravirt_patch_64.c14
-rw-r--r--arch/x86/kernel/process.c149
-rw-r--r--arch/x86/kernel/process_32.c13
-rw-r--r--arch/x86/kernel/process_64.c19
-rw-r--r--arch/x86/kernel/rtc.c9
-rw-r--r--arch/x86/kernel/setup.c24
-rw-r--r--arch/x86/kernel/setup_percpu.c3
-rw-r--r--arch/x86/kernel/smp.c2
-rw-r--r--arch/x86/kernel/smpboot.c57
-rw-r--r--arch/x86/kernel/traps.c20
-rw-r--r--arch/x86/kernel/unwind_frame.c161
-rw-r--r--arch/x86/kernel/vmlinux.lds.S2
-rw-r--r--arch/x86/kvm/cpuid.c4
-rw-r--r--arch/x86/kvm/mmu.c11
-rw-r--r--arch/x86/kvm/page_track.c31
-rw-r--r--arch/x86/kvm/vmx.c12
-rw-r--r--arch/x86/kvm/x86.c37
-rw-r--r--arch/x86/lguest/boot.c29
-rw-r--r--arch/x86/lib/copy_user_64.S47
-rw-r--r--arch/x86/lib/msr.c4
-rw-r--r--arch/x86/lib/usercopy.c49
-rw-r--r--arch/x86/lib/usercopy_32.c49
-rw-r--r--arch/x86/mm/fault.c3
-rw-r--r--arch/x86/mm/pat.c7
-rw-r--r--arch/x86/mm/pkeys.c3
-rw-r--r--arch/x86/net/bpf_jit_comp.c2
-rw-r--r--arch/x86/oprofile/nmi_int.c71
-rw-r--r--arch/x86/pci/amd_bus.c34
-rw-r--r--arch/x86/platform/intel-mid/pwr.c1
-rw-r--r--arch/x86/platform/uv/tlb_uv.c1
-rw-r--r--arch/x86/platform/uv/uv_nmi.c4
-rw-r--r--arch/x86/power/hibernate_64.c94
-rw-r--r--arch/x86/ras/mce_amd_inj.c2
-rw-r--r--arch/x86/realmode/rm/Makefile2
-rw-r--r--arch/x86/tools/insn_sanity.c3
-rw-r--r--arch/x86/tools/test_get_len.c2
-rw-r--r--arch/x86/um/asm/processor.h1
-rw-r--r--arch/x86/xen/enlighten.c13
-rw-r--r--arch/x86/xen/spinlock.c2
-rw-r--r--arch/xtensa/include/asm/mutex.h9
-rw-r--r--arch/xtensa/include/asm/processor.h1
-rw-r--r--arch/xtensa/include/uapi/asm/socket.h2
-rw-r--r--block/Kconfig35
-rw-r--r--block/Makefile4
-rw-r--r--block/bio-integrity.c2
-rw-r--r--block/bio.c68
-rw-r--r--block/blk-cgroup.c9
-rw-r--r--block/blk-core.c261
-rw-r--r--block/blk-exec.c2
-rw-r--r--block/blk-flush.c27
-rw-r--r--block/blk-lib.c177
-rw-r--r--block/blk-map.c6
-rw-r--r--block/blk-merge.c89
-rw-r--r--block/blk-mq-sysfs.c47
-rw-r--r--block/blk-mq.c543
-rw-r--r--block/blk-mq.h9
-rw-r--r--block/blk-settings.c39
-rw-r--r--block/blk-stat.c256
-rw-r--r--block/blk-stat.h42
-rw-r--r--block/blk-sysfs.c191
-rw-r--r--block/blk-tag.c6
-rw-r--r--block/blk-throttle.c10
-rw-r--r--block/blk-wbt.c750
-rw-r--r--block/blk-wbt.h171
-rw-r--r--block/blk-zoned.c348
-rw-r--r--block/blk.h5
-rw-r--r--block/bsg-lib.c2
-rw-r--r--block/bsg.c4
-rw-r--r--block/cfq-iosched.c109
-rw-r--r--block/elevator.c44
-rw-r--r--block/ioctl.c4
-rw-r--r--block/partition-generic.c65
-rw-r--r--crypto/algif_aead.c9
-rw-r--r--crypto/algif_skcipher.c18
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/bus.c10
-rw-r--r--drivers/acpi/event.c6
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/processor_perflib.c55
-rw-r--r--drivers/acpi/sleep.c8
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/atm/solos-pci.c2
-rw-r--r--drivers/base/Kconfig7
-rw-r--r--drivers/base/cacheinfo.c59
-rw-r--r--drivers/base/devres.c66
-rw-r--r--drivers/base/power/domain.c363
-rw-r--r--drivers/base/power/main.c2
-rw-r--r--drivers/base/power/opp/core.c521
-rw-r--r--drivers/base/power/opp/debugfs.c52
-rw-r--r--drivers/base/power/opp/of.c111
-rw-r--r--drivers/base/power/opp/opp.h23
-rw-r--r--drivers/base/power/power.h19
-rw-r--r--drivers/base/power/qos.c6
-rw-r--r--drivers/base/power/runtime.c62
-rw-r--r--drivers/base/power/sysfs.c6
-rw-r--r--drivers/base/power/trace.c27
-rw-r--r--drivers/base/power/wakeirq.c76
-rw-r--r--drivers/base/power/wakeup.c6
-rw-r--r--drivers/base/regmap/regcache-lzo.c8
-rw-r--r--drivers/base/soc.c79
-rw-r--r--drivers/base/topology.c42
-rw-r--r--drivers/bcma/host_pci.c1
-rw-r--r--drivers/block/Kconfig5
-rw-r--r--drivers/block/brd.c39
-rw-r--r--drivers/block/drbd/drbd_actlog.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c16
-rw-r--r--drivers/block/floppy.c10
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c18
-rw-r--r--drivers/block/nbd.c443
-rw-r--r--drivers/block/null_blk.c1
-rw-r--r--drivers/block/pktcdvd.c49
-rw-r--r--drivers/block/skd_main.c238
-rw-r--r--drivers/block/umem.c2
-rw-r--r--drivers/block/xen-blkback/blkback.c10
-rw-r--r--drivers/block/xen-blkfront.c3
-rw-r--r--drivers/block/zram/zcomp.c76
-rw-r--r--drivers/block/zram/zcomp.h5
-rw-r--r--drivers/block/zram/zram_drv.c9
-rw-r--r--drivers/bluetooth/btmrvl_drv.h1
-rw-r--r--drivers/bluetooth/hci_bcsp.c4
-rw-r--r--drivers/bluetooth/hci_h5.c4
-rw-r--r--drivers/bluetooth/hci_qca.c9
-rw-r--r--drivers/char/Kconfig1
-rw-r--r--drivers/char/hw_random/via-rng.c8
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c4
-rw-r--r--drivers/char/pcmcia/synclink_cs.c1
-rw-r--r--drivers/clk/Kconfig4
-rw-r--r--drivers/clk/bcm/Kconfig16
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c80
-rw-r--r--drivers/clk/clk-cdce925.c2
-rw-r--r--drivers/clk/clk-devres.c21
-rw-r--r--drivers/clk/clk-gate.c4
-rw-r--r--drivers/clk/clk-oxnas.c232
-rw-r--r--drivers/clk/clk-qoriq.c60
-rw-r--r--drivers/clk/clk-stm32f4.c435
-rw-r--r--drivers/clk/clk-wm831x.c2
-rw-r--r--drivers/clk/hisilicon/Kconfig17
-rw-r--r--drivers/clk/hisilicon/Makefile2
-rw-r--r--drivers/clk/hisilicon/crg-hi3516cv300.c330
-rw-r--r--drivers/clk/hisilicon/crg-hi3798cv200.c337
-rw-r--r--drivers/clk/hisilicon/crg.h34
-rw-r--r--drivers/clk/imx/clk-imx6q.c283
-rw-r--r--drivers/clk/imx/clk-imx6ul.c72
-rw-r--r--drivers/clk/imx/clk-pllv3.c8
-rw-r--r--drivers/clk/imx/clk.h8
-rw-r--r--drivers/clk/keystone/pll.c13
-rw-r--r--drivers/clk/mediatek/Kconfig43
-rw-r--r--drivers/clk/mediatek/Makefile7
-rw-r--r--drivers/clk/mediatek/clk-gate.c52
-rw-r--r--drivers/clk/mediatek/clk-gate.h2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-bdp.c138
-rw-r--r--drivers/clk/mediatek/clk-mt2701-eth.c80
-rw-r--r--drivers/clk/mediatek/clk-mt2701-hif.c81
-rw-r--r--drivers/clk/mediatek/clk-mt2701-img.c80
-rw-r--r--drivers/clk/mediatek/clk-mt2701-mm.c123
-rw-r--r--drivers/clk/mediatek/clk-mt2701-vdec.c91
-rw-r--r--drivers/clk/mediatek/clk-mt2701.c1035
-rw-r--r--drivers/clk/mediatek/clk-mtk.c40
-rw-r--r--drivers/clk/mediatek/clk-mtk.h41
-rw-r--r--drivers/clk/mediatek/clk-pll.c1
-rw-r--r--drivers/clk/mmp/clk-of-mmp2.c15
-rw-r--r--drivers/clk/mmp/clk-of-pxa1928.c3
-rw-r--r--drivers/clk/mmp/clk-of-pxa910.c19
-rw-r--r--drivers/clk/mvebu/ap806-system-controller.c23
-rw-r--r--drivers/clk/mvebu/cp110-system-controller.c167
-rw-r--r--drivers/clk/nxp/clk-lpc18xx-ccu.c5
-rw-r--r--drivers/clk/nxp/clk-lpc32xx.c32
-rw-r--r--drivers/clk/pxa/clk-pxa.c145
-rw-r--r--drivers/clk/pxa/clk-pxa.h59
-rw-r--r--drivers/clk/pxa/clk-pxa25x.c114
-rw-r--r--drivers/clk/pxa/clk-pxa27x.c168
-rw-r--r--drivers/clk/qcom/Kconfig37
-rw-r--r--drivers/clk/qcom/Makefile3
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c187
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h25
-rw-r--r--drivers/clk/qcom/clk-pll.c31
-rw-r--r--drivers/clk/qcom/clk-rcg.h1
-rw-r--r--drivers/clk/qcom/clk-rcg2.c76
-rw-r--r--drivers/clk/qcom/clk-rpm.c497
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c578
-rw-r--r--drivers/clk/qcom/common.c52
-rw-r--r--drivers/clk/qcom/common.h11
-rw-r--r--drivers/clk/qcom/gcc-apq8084.c8
-rw-r--r--drivers/clk/qcom/gcc-ipq4019.c3
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c4
-rw-r--r--drivers/clk/qcom/gcc-msm8916.c4
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c8
-rw-r--r--drivers/clk/qcom/gcc-msm8994.c2300
-rw-r--r--drivers/clk/qcom/gcc-msm8996.c33
-rw-r--r--drivers/clk/qcom/gdsc.c44
-rw-r--r--drivers/clk/qcom/gdsc.h3
-rw-r--r--drivers/clk/qcom/lcc-ipq806x.c2
-rw-r--r--drivers/clk/qcom/mmcc-msm8996.c26
-rw-r--r--drivers/clk/renesas/Kconfig2
-rw-r--r--drivers/clk/renesas/Makefile2
-rw-r--r--drivers/clk/renesas/clk-r8a7778.c26
-rw-r--r--drivers/clk/renesas/clk-r8a7779.c18
-rw-r--r--drivers/clk/renesas/clk-rcar-gen2.c32
-rw-r--r--drivers/clk/renesas/r8a7743-cpg-mssr.c270
-rw-r--r--drivers/clk/renesas/r8a7745-cpg-mssr.c259
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c10
-rw-r--r--drivers/clk/renesas/r8a7796-cpg-mssr.c65
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.c371
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.h43
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c31
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.h1
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c29
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.h2
-rw-r--r--drivers/clk/rockchip/Makefile1
-rw-r--r--drivers/clk/rockchip/clk-cpu.c9
-rw-r--r--drivers/clk/rockchip/clk-pll.c6
-rw-r--r--drivers/clk/rockchip/clk-rk1108.c531
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c13
-rw-r--r--drivers/clk/rockchip/clk-rk3399.c31
-rw-r--r--drivers/clk/rockchip/clk.h15
-rw-r--r--drivers/clk/samsung/clk-exynos5433.c30
-rw-r--r--drivers/clk/st/clk-flexgen.c5
-rw-r--r--drivers/clk/sunxi-ng/Kconfig14
-rw-r--r--drivers/clk/sunxi-ng/Makefile1
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.c915
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.h72
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a23.c6
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-h3.c10
-rw-r--r--drivers/clk/sunxi-ng/ccu_div.h6
-rw-r--r--drivers/clk/sunxi-ng/ccu_frac.c12
-rw-r--r--drivers/clk/sunxi-ng/ccu_frac.h14
-rw-r--r--drivers/clk/sunxi-ng/ccu_mp.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu_mult.c33
-rw-r--r--drivers/clk/sunxi-ng/ccu_mult.h17
-rw-r--r--drivers/clk/sunxi-ng/ccu_nk.c43
-rw-r--r--drivers/clk/sunxi-ng/ccu_nk.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkm.c45
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkm.h6
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkmp.c55
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkmp.h8
-rw-r--r--drivers/clk/sunxi-ng/ccu_nm.c58
-rw-r--r--drivers/clk/sunxi-ng/ccu_nm.h6
-rw-r--r--drivers/clk/sunxi/clk-mod0.c2
-rw-r--r--drivers/clk/tegra/clk-tegra124-dfll-fcpu.c21
-rw-r--r--drivers/clk/tegra/cvb.c10
-rw-r--r--drivers/clk/ti/clk-3xxx.c20
-rw-r--r--drivers/clk/ti/clk-7xx.c1
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c20
-rw-r--r--drivers/clk/ti/clock.h9
-rw-r--r--drivers/clk/ti/dpll.c19
-rw-r--r--drivers/clk/ti/dpll3xxx.c67
-rw-r--r--drivers/clk/uniphier/Makefile3
-rw-r--r--drivers/clk/uniphier/clk-uniphier-core.c3
-rw-r--r--drivers/clk/uniphier/clk-uniphier-cpugear.c115
-rw-r--r--drivers/clk/uniphier/clk-uniphier-sys.c32
-rw-r--r--drivers/clk/uniphier/clk-uniphier.h45
-rw-r--r--drivers/clocksource/arm_arch_timer.c14
-rw-r--r--drivers/clocksource/bcm2835_timer.c14
-rw-r--r--drivers/cpufreq/Kconfig.arm29
-rw-r--r--drivers/cpufreq/Kconfig.x861
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c117
-rw-r--r--drivers/cpufreq/brcmstb-avs-cpufreq.c1057
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c7
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c15
-rw-r--r--drivers/cpufreq/cpufreq-dt.c12
-rw-r--r--drivers/cpufreq/cpufreq.c25
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c46
-rw-r--r--drivers/cpufreq/cpufreq_governor.c30
-rw-r--r--drivers/cpufreq/cpufreq_governor.h5
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c17
-rw-r--r--drivers/cpufreq/cpufreq_stats.c22
-rw-r--r--drivers/cpufreq/integrator-cpufreq.c239
-rw-r--r--drivers/cpufreq/intel_pstate.c882
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c65
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c2
-rw-r--r--drivers/cpuidle/cpuidle.c19
-rw-r--r--drivers/cpuidle/dt_idle_states.c6
-rw-r--r--drivers/cpuidle/governor.c4
-rw-r--r--drivers/cpuidle/governors/ladder.c2
-rw-r--r--drivers/cpuidle/governors/menu.c2
-rw-r--r--drivers/cpuidle/sysfs.c4
-rw-r--r--drivers/crypto/chelsio/chcr_algo.c16
-rw-r--r--drivers/crypto/chelsio/chcr_core.c3
-rw-r--r--drivers/crypto/padlock-aes.c23
-rw-r--r--drivers/crypto/padlock-sha.c18
-rw-r--r--drivers/devfreq/devfreq.c2
-rw-r--r--drivers/devfreq/event/exynos-nocp.c1
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c6
-rw-r--r--drivers/devfreq/event/rockchip-dfi.c1
-rw-r--r--drivers/devfreq/exynos-bus.c29
-rw-r--r--drivers/devfreq/rk3399_dmc.c15
-rw-r--r--drivers/dma-buf/Kconfig2
-rw-r--r--drivers/dma-buf/Makefile2
-rw-r--r--drivers/dma-buf/dma-buf.c28
-rw-r--r--drivers/dma-buf/dma-fence-array.c (renamed from drivers/dma-buf/fence-array.c)91
-rw-r--r--drivers/dma-buf/dma-fence.c (renamed from drivers/dma-buf/fence.c)221
-rw-r--r--drivers/dma-buf/reservation.c197
-rw-r--r--drivers/dma-buf/seqno-fence.c18
-rw-r--r--drivers/dma-buf/sw_sync.c50
-rw-r--r--drivers/dma-buf/sync_debug.c13
-rw-r--r--drivers/dma-buf/sync_debug.h9
-rw-r--r--drivers/dma-buf/sync_file.c66
-rw-r--r--drivers/dma/Kconfig14
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/ioat/registers.h2
-rw-r--r--drivers/dma/st_fdma.c889
-rw-r--r--drivers/dma/st_fdma.h249
-rw-r--r--drivers/edac/altera_edac.c4
-rw-r--r--drivers/edac/amd64_edac.c692
-rw-r--r--drivers/edac/amd64_edac.h56
-rw-r--r--drivers/edac/edac_mc.c49
-rw-r--r--drivers/edac/mce_amd.c44
-rw-r--r--drivers/edac/mpc85xx_edac.c17
-rw-r--r--drivers/edac/sb_edac.c14
-rw-r--r--drivers/edac/skx_edac.c7
-rw-r--r--drivers/edac/xgene_edac.c6
-rw-r--r--drivers/firewire/net.c21
-rw-r--r--drivers/firmware/efi/Kconfig18
-rw-r--r--drivers/firmware/efi/Makefile2
-rw-r--r--drivers/firmware/efi/apple-properties.c248
-rw-r--r--drivers/firmware/efi/arm-init.c4
-rw-r--r--drivers/firmware/efi/dev-path-parser.c203
-rw-r--r--drivers/firmware/efi/efi.c76
-rw-r--r--drivers/firmware/efi/libstub/Makefile4
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c2
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c33
-rw-r--r--drivers/firmware/efi/libstub/efistub.h11
-rw-r--r--drivers/firmware/efi/libstub/random.c67
-rw-r--r--drivers/firmware/efi/test/efi_test.c15
-rw-r--r--drivers/gpio/Kconfig38
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/gpio-adnp.c12
-rw-r--r--drivers/gpio/gpio-altera-a10sr.c130
-rw-r--r--drivers/gpio/gpio-arizona.c9
-rw-r--r--drivers/gpio/gpio-axp209.c8
-rw-r--r--drivers/gpio/gpio-crystalcove.c6
-rw-r--r--drivers/gpio/gpio-davinci.c7
-rw-r--r--drivers/gpio/gpio-dln2.c1
-rw-r--r--drivers/gpio/gpio-etraxfs.c7
-rw-r--r--drivers/gpio/gpio-htc-egpio.c54
-rw-r--r--drivers/gpio/gpio-intel-mid.c7
-rw-r--r--drivers/gpio/gpio-max732x.c17
-rw-r--r--drivers/gpio/gpio-max77620.c11
-rw-r--r--drivers/gpio/gpio-mb86s7x.c6
-rw-r--r--drivers/gpio/gpio-mcp23s08.c17
-rw-r--r--drivers/gpio/gpio-merrifield.c33
-rw-r--r--drivers/gpio/gpio-mxs.c45
-rw-r--r--drivers/gpio/gpio-pca953x.c18
-rw-r--r--drivers/gpio/gpio-pcf857x.c11
-rw-r--r--drivers/gpio/gpio-pl061.c208
-rw-r--r--drivers/gpio/gpio-stmpe.c19
-rw-r--r--drivers/gpio/gpio-sx150x.c792
-rw-r--r--drivers/gpio/gpio-tc3589x.c17
-rw-r--r--drivers/gpio/gpio-vf610.c6
-rw-r--r--drivers/gpio/gpio-wcove.c6
-rw-r--r--drivers/gpio/gpiolib-acpi.c107
-rw-r--r--drivers/gpio/gpiolib-devprop.c67
-rw-r--r--drivers/gpio/gpiolib-of.c51
-rw-r--r--drivers/gpio/gpiolib.c107
-rw-r--r--drivers/gpio/gpiolib.h2
-rw-r--r--drivers/gpu/drm/Kconfig21
-rw-r--r--drivers/gpu/drm/Makefile9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ObjectID.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h896
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c95
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c57
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c93
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c307
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c40
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c555
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h450
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c97
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c89
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c128
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c103
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h186
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h56
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_test.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c276
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c80
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c134
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c450
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h205
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c222
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_crtc.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c120
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c834
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_ih.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cikd.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_ih.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c168
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c168
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c804
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c328
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.c435
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c858
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c182
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c603
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c356
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/iceland_ih.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/iceland_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c59
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c68
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c162
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dpm.c67
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_enums.h272
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_ih.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/tonga_ih.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/tonga_ih.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c61
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c149
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c205
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c76
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c997
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.h2
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h23
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h661
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h8127
-rw-r--r--[-rwxr-xr-x]drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h0
-rw-r--r--[-rwxr-xr-x]drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h0
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h4457
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h9836
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h1784
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h12821
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h1274
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h11895
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h275
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h1079
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h148
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h715
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h96
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h795
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h64
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h99
-rw-r--r--[-rwxr-xr-x]drivers/gpu/drm/amd/include/cgs_common.h6
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c93
-rw-r--r--drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c4
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c12
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c13
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c31
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c1
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c18
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c73
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c5
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h4
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h22
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/power_state.h9
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h9
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c12
-rw-r--r--[-rwxr-xr-x]drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c18
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c5
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c28
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c3
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h4
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.c67
-rw-r--r--drivers/gpu/drm/amd/scheduler/gpu_scheduler.h26
-rw-r--r--drivers/gpu/drm/amd/scheduler/sched_fence.c48
-rw-r--r--drivers/gpu/drm/arc/arcpgu_drv.c2
-rw-r--r--drivers/gpu/drm/arc/arcpgu_sim.c7
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c5
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c24
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c43
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h3
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c12
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h9
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c99
-rw-r--r--drivers/gpu/drm/armada/Makefile2
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c121
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h10
-rw-r--r--drivers/gpu/drm/armada/armada_debugfs.c2
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h1
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c238
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c8
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c10
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c65
-rw-r--r--drivers/gpu/drm/armada/armada_trace.c4
-rw-r--r--drivers/gpu/drm/armada/armada_trace.h66
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c2
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c2
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c7
-rw-r--r--drivers/gpu/drm/ast/ast_ttm.c1
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c5
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c41
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c2
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c6
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c7
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c1
-rw-r--r--drivers/gpu/drm/bridge/Kconfig23
-rw-r--r--drivers/gpu/drm/bridge/Makefile3
-rw-r--r--drivers/gpu/drm/bridge/adv7511/Kconfig8
-rw-r--r--drivers/gpu/drm/bridge/adv7511/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h16
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_audio.c213
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c4
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7533.c1
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c4
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c2
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c33
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi-audio.h7
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c141
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c301
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.h39
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c7
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c7
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c1564
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.h1517
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c9
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c317
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.c2
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c6
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c4
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c7
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_ttm.c1
-rw-r--r--drivers/gpu/drm/drm_atomic.c583
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c205
-rw-r--r--drivers/gpu/drm/drm_blend.c39
-rw-r--r--drivers/gpu/drm/drm_color_mgmt.c12
-rw-r--r--drivers/gpu/drm/drm_connector.c148
-rw-r--r--drivers/gpu/drm/drm_crtc.c776
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h36
-rw-r--r--drivers/gpu/drm/drm_debugfs.c52
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c352
-rw-r--r--drivers/gpu/drm/drm_dp_dual_mode_helper.c121
-rw-r--r--drivers/gpu/drm/drm_drv.c130
-rw-r--r--drivers/gpu/drm/drm_dumb_buffers.c128
-rw-r--r--drivers/gpu/drm/drm_edid.c207
-rw-r--r--drivers/gpu/drm/drm_encoder.c9
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c67
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c155
-rw-r--r--drivers/gpu/drm/drm_fops.c21
-rw-r--r--drivers/gpu/drm/drm_fourcc.c293
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c123
-rw-r--r--drivers/gpu/drm/drm_internal.h28
-rw-r--r--drivers/gpu/drm/drm_ioctl.c33
-rw-r--r--drivers/gpu/drm/drm_irq.c164
-rw-r--r--drivers/gpu/drm/drm_lock.c3
-rw-r--r--drivers/gpu/drm/drm_mm.c99
-rw-r--r--drivers/gpu/drm/drm_mode_config.c494
-rw-r--r--drivers/gpu/drm/drm_modes.c16
-rw-r--r--drivers/gpu/drm/drm_modeset_helper.c25
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c23
-rw-r--r--drivers/gpu/drm/drm_of.c28
-rw-r--r--drivers/gpu/drm/drm_plane.c16
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c11
-rw-r--r--drivers/gpu/drm/drm_prime.c12
-rw-r--r--drivers/gpu/drm/drm_print.c59
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c20
-rw-r--r--drivers/gpu/drm/drm_property.c54
-rw-r--r--drivers/gpu/drm/drm_rect.c11
-rw-r--r--drivers/gpu/drm/etnaviv/cmdstream.xml.h60
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c8
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.h2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_dump.c3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.c28
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c19
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c50
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h4
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c141
-rw-r--r--drivers/gpu/drm/exynos/regs-hdmi.h2
-rw-r--r--drivers/gpu/drm/fsl-dcu/Makefile1
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c28
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h1
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c23
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c7
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c14
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c35
-rw-r--r--drivers/gpu/drm/gma500/gtt.c4
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h4
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c14
-rw-r--r--drivers/gpu/drm/hisilicon/Kconfig1
-rw-r--r--drivers/gpu/drm/hisilicon/Makefile1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/Kconfig9
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/Makefile4
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c477
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c456
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h114
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c267
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h196
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c140
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c558
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c7
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c9
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c863
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c2
-rw-r--r--drivers/gpu/drm/i810/i810_drv.c2
-rw-r--r--drivers/gpu/drm/i915/Kconfig64
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug1
-rw-r--r--drivers/gpu/drm/i915/Makefile11
-rw-r--r--drivers/gpu/drm/i915/gvt/Makefile11
-rw-r--r--drivers/gpu/drm/i915/gvt/aperture_gm.c352
-rw-r--r--drivers/gpu/drm/i915/gvt/cfg_space.c284
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c2831
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.h49
-rw-r--r--drivers/gpu/drm/i915/gvt/debug.h29
-rw-r--r--drivers/gpu/drm/i915/gvt/display.c330
-rw-r--r--drivers/gpu/drm/i915/gvt/display.h163
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.c531
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.h150
-rw-r--r--drivers/gpu/drm/i915/gvt/execlist.c858
-rw-r--r--drivers/gpu/drm/i915/gvt/execlist.h188
-rw-r--r--drivers/gpu/drm/i915/gvt/firmware.c312
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c2244
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.h306
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.c205
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.h382
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c2848
-rw-r--r--drivers/gpu/drm/i915/gvt/hypercall.h26
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.c741
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.h233
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c597
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.c304
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.h106
-rw-r--r--drivers/gpu/drm/i915/gvt/mpt.h259
-rw-r--r--drivers/gpu/drm/i915/gvt/opregion.c320
-rw-r--r--drivers/gpu/drm/i915/gvt/reg.h80
-rw-r--r--drivers/gpu/drm/i915/gvt/render.c310
-rw-r--r--drivers/gpu/drm/i915/gvt/render.h43
-rw-r--r--drivers/gpu/drm/i915/gvt/sched_policy.c292
-rw-r--r--drivers/gpu/drm/i915/gvt/sched_policy.h58
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c583
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.h139
-rw-r--r--drivers/gpu/drm/i915/gvt/trace.h286
-rw-r--r--drivers/gpu/drm/i915/gvt/trace_points.c (renamed from drivers/gpu/drm/i915/i915_gem_dmabuf.h)37
-rw-r--r--drivers/gpu/drm/i915/gvt/vgpu.c409
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c5
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c676
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c248
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1147
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c3024
-rw-r--r--drivers/gpu/drm/i915/i915_gem.h4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_batch_pool.c39
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c109
-rw-r--r--drivers/gpu/drm/i915/i915_gem_dmabuf.c150
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c21
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c168
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence_reg.c (renamed from drivers/gpu/drm/i915/i915_gem_fence.c)54
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence_reg.h51
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c1089
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h250
-rw-r--r--drivers/gpu/drm/i915/i915_gem_internal.c170
-rw-r--r--drivers/gpu/drm/i915/i915_gem_object.h338
-rw-r--r--drivers/gpu/drm/i915/i915_gem_render_state.c186
-rw-r--r--drivers/gpu/drm/i915/i915_gem_render_state.h4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.c766
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.h212
-rw-r--r--drivers/gpu/drm/i915/i915_gem_shrinker.c111
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c107
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c64
-rw-r--r--drivers/gpu/drm/i915/i915_gem_timeline.c90
-rw-r--r--drivers/gpu/drm/i915/i915_gem_timeline.h73
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c124
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c727
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c675
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c838
-rw-r--r--drivers/gpu/drm/i915/i915_params.c18
-rw-r--r--drivers/gpu/drm/i915/i915_params.h3
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c13
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h285
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c32
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c88
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.h38
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c25
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h10
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c638
-rw-r--r--drivers/gpu/drm/i915/i915_vma.h341
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c26
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c412
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c53
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c76
-rw-r--r--drivers/gpu/drm/i915/intel_color.c52
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c141
-rw-r--r--drivers/gpu/drm/i915/intel_csr.c11
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c534
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c21
-rw-r--r--drivers/gpu/drm/i915/intel_display.c2026
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c526
-rw-r--r--drivers/gpu/drm/i915/intel_dp_link_training.c3
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c2
-rw-r--r--drivers/gpu/drm/i915/intel_dpio_phy.c559
-rw-r--r--drivers/gpu/drm/i915/intel_dpll_mgr.c99
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h199
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c45
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_panel_vbt.c56
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_pll.c26
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c22
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c203
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c148
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c17
-rw-r--r--drivers/gpu/drm/i915/intel_fifo_underrun.c33
-rw-r--r--drivers/gpu/drm/i915/intel_frontbuffer.h5
-rw-r--r--drivers/gpu/drm/i915/intel_guc.h32
-rw-r--r--drivers/gpu/drm/i915/intel_guc_fwif.h82
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c56
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.c10
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.h2
-rw-r--r--drivers/gpu/drm/i915/intel_hangcheck.c450
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c111
-rw-r--r--drivers/gpu/drm/i915/intel_hotplug.c2
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c14
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c420
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.h1
-rw-r--r--drivers/gpu/drm/i915/intel_lspcon.c185
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c45
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c139
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c10
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c12
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c1408
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c28
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c371
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h147
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c169
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c45
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c207
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c63
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c695
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c30
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c19
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c7
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c177
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c7
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c11
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c7
-rw-r--r--drivers/gpu/drm/meson/Kconfig9
-rw-r--r--drivers/gpu/drm/meson/Makefile4
-rw-r--r--drivers/gpu/drm/meson/meson_canvas.c68
-rw-r--r--drivers/gpu/drm/meson/meson_canvas.h42
-rw-r--r--drivers/gpu/drm/meson/meson_crtc.c208
-rw-r--r--drivers/gpu/drm/meson/meson_crtc.h32
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c343
-rw-r--r--drivers/gpu/drm/meson/meson_drv.h59
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c230
-rw-r--r--drivers/gpu/drm/meson/meson_plane.h30
-rw-r--r--drivers/gpu/drm/meson/meson_registers.h1395
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.c167
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.h34
-rw-r--r--drivers/gpu/drm/meson/meson_venc.c254
-rw-r--r--drivers/gpu/drm/meson/meson_venc.h72
-rw-r--r--drivers/gpu/drm/meson/meson_venc_cvbs.c293
-rw-r--r--drivers/gpu/drm/meson/meson_venc_cvbs.h41
-rw-r--r--drivers/gpu/drm/meson/meson_viu.c331
-rw-r--r--drivers/gpu/drm/meson/meson_viu.h64
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.c162
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.h35
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c7
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ttm.c1
-rw-r--r--drivers/gpu/drm/msm/Makefile4
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h27
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h38
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c112
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h111
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c119
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx.xml.h3757
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c888
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.h60
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c344
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h21
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c32
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c39
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h162
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h300
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h2
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h2
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c10
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c38
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h14
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c40
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c13
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c267
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h53
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c133
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h56
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c297
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c306
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h70
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h2
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c37
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c17
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c47
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h42
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c4
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c9
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c28
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c60
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h25
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c27
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c17
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c90
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c68
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h45
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c12
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h19
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h4
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c4
-rw-r--r--drivers/gpu/drm/mxsfb/Kconfig19
-rw-r--r--drivers/gpu/drm/mxsfb/Makefile2
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c241
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c444
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.h54
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_out.c131
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_regs.h114
-rw-r--r--drivers/gpu/drm/nouveau/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/overlay.c2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl5070.h17
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/object.h29
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h10
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h24
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h18
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c81
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c650
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h98
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c349
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c19
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c97
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c82
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_led.c139
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_led.h57
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.c7
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv17_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c4190
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.h7
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fence.c22
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/firmware.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c)6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c37
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c)4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c)14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c37
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c)29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c46
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c)12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c37
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c33
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c)4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c)22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c34
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c147
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c)6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c132
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c227
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c216
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c141
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h4
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c47
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-dvi.c50
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-hdmi.c49
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-opa362.c20
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c31
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c33
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dpi.c30
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c25
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c59
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c52
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c58
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c53
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c57
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c54
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c228
-rw-r--r--drivers/gpu/drm/omapdrm/dss/display.c78
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c40
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c160
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h5
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi.h8
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c31
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4_core.c8
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c31
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5_core.c85
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_wp.c73
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h98
-rw-r--r--drivers/gpu/drm/omapdrm/dss/output.c5
-rw-r--r--drivers/gpu/drm/omapdrm/dss/rfbi.c49
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c33
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c97
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c87
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c43
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c70
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h10
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.c10
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c5
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c56
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c207
-rw-r--r--drivers/gpu/drm/qxl/qxl_cmd.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_debugfs.c6
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c69
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h12
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c10
-rw-r--r--drivers/gpu/drm/qxl/qxl_gem.c3
-rw-r--r--drivers/gpu/drm/qxl/qxl_kms.c3
-rw-r--r--drivers/gpu/drm/qxl/qxl_release.c37
-rw-r--r--drivers/gpu/drm/qxl/qxl_ttm.c1
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c14
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c1
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c1
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon.h10
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_clocks.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c73
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_dp_mst.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c28
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c56
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_sync.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c2
-rw-r--r--drivers/gpu/drm/radeon/si.c3
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c6
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c85
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c22
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c20
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c9
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c19
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig1
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi.c7
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c6
-rw-r--r--drivers/gpu/drm/savage/savage_drv.c2
-rw-r--r--drivers/gpu/drm/savage/savage_state.c1
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c7
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.c2
-rw-r--r--drivers/gpu/drm/sis/sis_drv.c2
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c10
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c23
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c10
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c6
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_rgb.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c45
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.h11
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tv.c9
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_drc.c4
-rw-r--r--drivers/gpu/drm/tdfx/tdfx_drv.c2
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c4
-rw-r--r--drivers/gpu/drm/tegra/drm.c5
-rw-r--r--drivers/gpu/drm/tegra/fb.c6
-rw-r--r--drivers/gpu/drm/tegra/gem.c41
-rw-r--r--drivers/gpu/drm/tegra/gr3d.c4
-rw-r--r--drivers/gpu/drm/tegra/sor.c2
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c598
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c214
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h11
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_external.c260
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_external.h5
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c10
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_plane.c7
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_regs.h15
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c68
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c22
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_execbuf_util.c3
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c8
-rw-r--r--drivers/gpu/drm/vc4/Makefile1
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c46
-rw-r--r--drivers/gpu/drm/vc4/vc4_debugfs.c1
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c18
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h9
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c15
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c36
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h3
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_validate.c24
-rw-r--r--drivers/gpu/drm/vc4/vc4_validate_shaders.c82
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c657
-rw-r--r--drivers/gpu/drm/vgem/vgem_fence.c58
-rw-r--r--drivers/gpu/drm/via/via_drv.c2
-rw-r--r--drivers/gpu/drm/virtio/Kconfig6
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drm_bus.c23
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fb.c8
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fence.c26
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c12
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_plane.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ttm.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c19
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c44
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c107
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c4
-rw-r--r--drivers/gpu/drm/zte/Kconfig8
-rw-r--r--drivers/gpu/drm/zte/Makefile7
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.c267
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.h36
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi.c624
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi_regs.h56
-rw-r--r--drivers/gpu/drm/zte/zx_plane.c299
-rw-r--r--drivers/gpu/drm/zte/zx_plane.h26
-rw-r--r--drivers/gpu/drm/zte/zx_plane_regs.h91
-rw-r--r--drivers/gpu/drm/zte/zx_vou.c661
-rw-r--r--drivers/gpu/drm/zte/zx_vou.h46
-rw-r--r--drivers/gpu/drm/zte/zx_vou_regs.h157
-rw-r--r--drivers/gpu/host1x/dev.h3
-rw-r--r--drivers/gpu/host1x/job.c9
-rw-r--r--drivers/gpu/host1x/syncpt.c23
-rw-r--r--drivers/gpu/ipu-v3/Kconfig1
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c7
-rw-r--r--drivers/gpu/ipu-v3/ipu-cpmem.c43
-rw-r--r--drivers/gpu/ipu-v3/ipu-csi.c16
-rw-r--r--drivers/gpu/ipu-v3/ipu-di.c2
-rw-r--r--drivers/gpu/vga/vgaarb.c80
-rw-r--r--drivers/hsi/clients/ssi_protocol.c14
-rw-r--r--drivers/ide/ide-atapi.c6
-rw-r--r--drivers/ide/ide-cd.c46
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-cd_ioctl.c6
-rw-r--r--drivers/ide/ide-io.c6
-rw-r--r--drivers/ide/ide-pm.c4
-rw-r--r--drivers/idle/Kconfig17
-rw-r--r--drivers/idle/Makefile1
-rw-r--r--drivers/idle/i7300_idle.c612
-rw-r--r--drivers/idle/intel_idle.c154
-rw-r--r--drivers/infiniband/core/cma.c2
-rw-r--r--drivers/infiniband/core/core_priv.h9
-rw-r--r--drivers/infiniband/core/roce_gid_mgmt.c42
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c1
-rw-r--r--drivers/infiniband/hw/mlx5/main.c26
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h2
-rw-r--r--drivers/infiniband/hw/nes/nes.c1
-rw-r--r--drivers/infiniband/hw/nes/nes.h4
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c38
-rw-r--r--drivers/iommu/intel-iommu.c24
-rw-r--r--drivers/irqchip/Kconfig4
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-bcm7038-l1.c26
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c75
-rw-r--r--drivers/irqchip/irq-xilinx-intc.c241
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c1
-rw-r--r--drivers/leds/Kconfig21
-rw-r--r--drivers/leds/Makefile4
-rw-r--r--drivers/leds/led-class.c4
-rw-r--r--drivers/leds/led-core.c62
-rw-r--r--drivers/leds/leds-cobalt-raq.c6
-rw-r--r--drivers/leds/leds-lp3952.c1
-rw-r--r--drivers/leds/leds-mc13783.c5
-rw-r--r--drivers/leds/leds-mlxcpld.c5
-rw-r--r--drivers/leds/leds-netxbig.c1
-rw-r--r--drivers/leds/leds-nic78bx.c209
-rw-r--r--drivers/leds/leds-pca9532.c2
-rw-r--r--drivers/leds/leds-pca955x.c24
-rw-r--r--drivers/leds/leds-pca963x.c80
-rw-r--r--drivers/leds/trigger/ledtrig-cpu.c2
-rw-r--r--drivers/leds/uleds.c235
-rw-r--r--drivers/lguest/hypercalls.c4
-rw-r--r--drivers/lguest/lg.h1
-rw-r--r--drivers/lguest/x86/core.c19
-rw-r--r--drivers/lightnvm/Makefile2
-rw-r--r--drivers/lightnvm/core.c377
-rw-r--r--drivers/lightnvm/gennvm.c645
-rw-r--r--drivers/lightnvm/gennvm.h34
-rw-r--r--drivers/lightnvm/lightnvm.h35
-rw-r--r--drivers/lightnvm/rrpc.c514
-rw-r--r--drivers/lightnvm/rrpc.h65
-rw-r--r--drivers/lightnvm/sysblk.c98
-rw-r--r--drivers/lightnvm/sysfs.c198
-rw-r--r--drivers/md/bcache/btree.c4
-rw-r--r--drivers/md/bcache/debug.c15
-rw-r--r--drivers/md/bcache/io.c4
-rw-r--r--drivers/md/bcache/journal.c4
-rw-r--r--drivers/md/bcache/movinggc.c6
-rw-r--r--drivers/md/bcache/request.c8
-rw-r--r--drivers/md/bcache/super.c16
-rw-r--r--drivers/md/bcache/writeback.c5
-rw-r--r--drivers/md/bcache/writeback.h3
-rw-r--r--drivers/md/dm-bufio.c6
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-raid1.c4
-rw-r--r--drivers/md/dm-rq.c52
-rw-r--r--drivers/md/dm-snap-persistent.c4
-rw-r--r--drivers/md/dm.c4
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/multipath.c2
-rw-r--r--drivers/md/raid5-cache.c6
-rw-r--r--drivers/md/raid5.c11
-rw-r--r--drivers/media/dvb-core/dvb_net.c2
-rw-r--r--drivers/memstick/core/ms_block.c2
-rw-r--r--drivers/memstick/core/mspro_block.c2
-rw-r--r--drivers/message/fusion/mptlan.c15
-rw-r--r--drivers/mfd/Kconfig14
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/qcom-pm8xxx.c (renamed from drivers/mfd/pm8921-core.c)42
-rw-r--r--drivers/misc/lkdtm.h2
-rw-r--r--drivers/misc/lkdtm_bugs.c68
-rw-r--r--drivers/misc/lkdtm_core.c2
-rw-r--r--drivers/misc/sgi-xp/xpnet.c21
-rw-r--r--drivers/mmc/card/block.c501
-rw-r--r--drivers/mmc/card/mmc_test.c58
-rw-r--r--drivers/mmc/card/queue.c316
-rw-r--r--drivers/mmc/card/queue.h29
-rw-r--r--drivers/mmc/card/sdio_uart.c2
-rw-r--r--drivers/mmc/core/core.c97
-rw-r--r--drivers/mmc/core/debugfs.c6
-rw-r--r--drivers/mmc/core/mmc.c113
-rw-r--r--drivers/mmc/core/mmc_ops.c220
-rw-r--r--drivers/mmc/core/mmc_ops.h7
-rw-r--r--drivers/mmc/core/sd.c14
-rw-r--r--drivers/mmc/core/sd_ops.c27
-rw-r--r--drivers/mmc/core/sdio.c17
-rw-r--r--drivers/mmc/core/sdio_cis.c3
-rw-r--r--drivers/mmc/core/sdio_irq.c12
-rw-r--r--drivers/mmc/core/slot-gpio.c8
-rw-r--r--drivers/mmc/host/Kconfig23
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/davinci_mmc.c130
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c52
-rw-r--r--drivers/mmc/host/dw_mmc-k3.c39
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c29
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c28
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c42
-rw-r--r--drivers/mmc/host/dw_mmc.c181
-rw-r--r--drivers/mmc/host/dw_mmc.h7
-rw-r--r--drivers/mmc/host/jz4740_mmc.c3
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c851
-rw-r--r--drivers/mmc/host/mmci.c128
-rw-r--r--drivers/mmc/host/mmci.h71
-rw-r--r--drivers/mmc/host/mtk-sd.c4
-rw-r--r--drivers/mmc/host/omap_hsmmc.c3
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c3
-rw-r--r--drivers/mmc/host/rtsx_usb_sdmmc.c3
-rw-r--r--drivers/mmc/host/s3cmci.c15
-rw-r--r--drivers/mmc/host/sdhci-acpi.c1
-rw-r--r--drivers/mmc/host/sdhci-cadence.c283
-rw-r--r--drivers/mmc/host/sdhci-iproc.c35
-rw-r--r--drivers/mmc/host/sdhci-msm.c694
-rw-r--r--drivers/mmc/host/sdhci-of-at91.c1
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c20
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c98
-rw-r--r--drivers/mmc/host/sdhci-pci.h3
-rw-r--r--drivers/mmc/host/sdhci-pltfm.h2
-rw-r--r--drivers/mmc/host/sdhci-s3c.c2
-rw-r--r--drivers/mmc/host/sdhci.c362
-rw-r--r--drivers/mmc/host/sdhci.h4
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c274
-rw-r--r--drivers/mmc/host/sunxi-mmc.c15
-rw-r--r--drivers/mmc/host/tmio_mmc.h32
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c119
-rw-r--r--drivers/mmc/host/wbsd.c11
-rw-r--r--drivers/net/appletalk/ipddp.c1
-rw-r--r--drivers/net/bonding/bond_alb.c82
-rw-r--r--drivers/net/bonding/bond_main.c35
-rw-r--r--drivers/net/can/grcan.c2
-rw-r--r--drivers/net/can/usb/kvaser_usb.c4
-rw-r--r--drivers/net/cris/eth_v10.c12
-rw-r--r--drivers/net/dsa/mv88e6xxx/Kconfig1
-rw-r--r--drivers/net/dsa/mv88e6xxx/Makefile1
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c2017
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.c367
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.h18
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c186
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.h17
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h244
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c729
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h71
-rw-r--r--drivers/net/dummy.c3
-rw-r--r--drivers/net/ethernet/3com/3c509.c56
-rw-r--r--drivers/net/ethernet/3com/3c515.c1
-rw-r--r--drivers/net/ethernet/3com/3c574_cs.c1
-rw-r--r--drivers/net/ethernet/3com/3c589_cs.c1
-rw-r--r--drivers/net/ethernet/3com/3c59x.c16
-rw-r--r--drivers/net/ethernet/3com/typhoon.c66
-rw-r--r--drivers/net/ethernet/8390/8390.c1
-rw-r--r--drivers/net/ethernet/8390/8390p.c1
-rw-r--r--drivers/net/ethernet/8390/ax88796.c1
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c1
-rw-r--r--drivers/net/ethernet/8390/etherh.c1
-rw-r--r--drivers/net/ethernet/8390/hydra.c1
-rw-r--r--drivers/net/ethernet/8390/mac8390.c1
-rw-r--r--drivers/net/ethernet/8390/mcf8390.c1
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c1
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c1
-rw-r--r--drivers/net/ethernet/8390/smc-ultra.c1
-rw-r--r--drivers/net/ethernet/8390/wd.c1
-rw-r--r--drivers/net/ethernet/8390/zorro8390.c1
-rw-r--r--drivers/net/ethernet/Kconfig2
-rw-r--r--drivers/net/ethernet/Makefile2
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c15
-rw-r--r--drivers/net/ethernet/adi/Kconfig2
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c1
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c9
-rw-r--r--drivers/net/ethernet/agere/et131x.c7
-rw-r--r--drivers/net/ethernet/alacritech/Kconfig28
-rw-r--r--drivers/net/ethernet/alacritech/Makefile4
-rw-r--r--drivers/net/ethernet/alacritech/slic.h575
-rw-r--r--drivers/net/ethernet/alacritech/slicoss.c1871
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c26
-rw-r--r--drivers/net/ethernet/alteon/acenic.c70
-rw-r--r--drivers/net/ethernet/altera/altera_tse.h12
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c107
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c18
-rw-r--r--drivers/net/ethernet/amd/Kconfig12
-rw-r--r--drivers/net/ethernet/amd/a2065.c1
-rw-r--r--drivers/net/ethernet/amd/am79c961a.c1
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c19
-rw-r--r--drivers/net/ethernet/amd/ariadne.c1
-rw-r--r--drivers/net/ethernet/amd/atarilance.c9
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c1
-rw-r--r--drivers/net/ethernet/amd/declance.c1
-rw-r--r--drivers/net/ethernet/amd/hplance.c1
-rw-r--r--drivers/net/ethernet/amd/lance.c1
-rw-r--r--drivers/net/ethernet/amd/mvme147.c1
-rw-r--r--drivers/net/ethernet/amd/ni65.c1
-rw-r--r--drivers/net/ethernet/amd/nmclan_cs.c1
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c15
-rw-r--r--drivers/net/ethernet/amd/sun3lance.c1
-rw-r--r--drivers/net/ethernet/amd/sunlance.c1
-rw-r--r--drivers/net/ethernet/amd/xgbe/Makefile5
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-common.h385
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c154
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c1054
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c349
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c87
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-i2c.c492
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-main.c705
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-mdio.c1130
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-pci.c529
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c845
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c3084
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-platform.c642
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe.h386
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_cle.c704
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_cle.h5
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c70
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c140
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h27
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c350
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h31
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c1
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c146
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c140
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h9
-rw-r--r--drivers/net/ethernet/apple/bmac.c1
-rw-r--r--drivers/net/ethernet/apple/mace.c1
-rw-r--r--drivers/net/ethernet/apple/macmace.c1
-rw-r--r--drivers/net/ethernet/arc/Kconfig5
-rw-r--r--drivers/net/ethernet/arc/emac_main.c2
-rw-r--r--drivers/net/ethernet/atheros/alx/alx.h36
-rw-r--r--drivers/net/ethernet/atheros/alx/ethtool.c59
-rw-r--r--drivers/net/ethernet/atheros/alx/hw.h1
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c564
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c54
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c41
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c62
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c12
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c81
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c82
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.h3
-rw-r--r--drivers/net/ethernet/aurora/nb8800.c17
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig14
-rw-r--r--drivers/net/ethernet/broadcom/b44.c9
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c42
-rw-r--r--drivers/net/ethernet/broadcom/bgmac-bcma.c22
-rw-r--r--drivers/net/ethernet/broadcom/bgmac-platform.c74
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c32
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.h9
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c107
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c25
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c22
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c7
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/Makefile2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c474
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h48
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c502
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h41
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c190
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h1622
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c22
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c346
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h93
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c9
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c12
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c9
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c7
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c54
-rw-r--r--drivers/net/ethernet/cadence/macb.c329
-rw-r--r--drivers/net/ethernet/cadence/macb.h17
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c37
-rw-r--r--drivers/net/ethernet/cavium/Kconfig14
-rw-r--r--drivers/net/ethernet/cavium/liquidio/Makefile24
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c322
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h44
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h51
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c722
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h50
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h274
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn66xx_device.c49
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn66xx_device.h41
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h49
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn68xx_device.c38
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn68xx_device.h37
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h37
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_core.c74
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_ethtool.c577
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c450
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_main.c3251
-rw-r--r--drivers/net/ethernet/cavium/liquidio/liquidio_common.h101
-rw-r--r--drivers/net/ethernet/cavium/liquidio/liquidio_image.h36
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_config.h46
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_console.c156
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c150
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.h147
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_droq.c101
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_droq.h18
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_iq.h25
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c318
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h115
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_main.h47
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c7
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_network.h14
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_nic.c5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_nic.h7
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c51
-rw-r--r--drivers/net/ethernet/cavium/liquidio/response_manager.c14
-rw-r--r--drivers/net/ethernet/cavium/liquidio/response_manager.h6
-rw-r--r--drivers/net/ethernet/cavium/octeon/octeon_mgmt.c13
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h19
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_main.c37
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c117
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c74
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c33
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.h27
-rw-r--r--drivers/net/ethernet/cavium/thunder/q_struct.h8
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c74
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.h12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/common.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cxgb2.c18
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/pm3393.c8
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/vsc7326.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h19
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c111
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c114
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h17
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c121
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c15
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c1
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c1
-rw-r--r--drivers/net/ethernet/cirrus/mac89x0.c1
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c25
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.h2
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c1
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c22
-rw-r--r--drivers/net/ethernet/dlink/sundance.c6
-rw-r--r--drivers/net/ethernet/dnet.c1
-rw-r--r--drivers/net/ethernet/ec_bhf.c1
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c22
-rw-r--r--drivers/net/ethernet/ethoc.c45
-rw-r--r--drivers/net/ethernet/fealnx.c1
-rw-r--r--drivers/net/ethernet/freescale/Kconfig8
-rw-r--r--drivers/net/ethernet/freescale/Makefile1
-rw-r--r--drivers/net/ethernet/freescale/dpaa/Kconfig10
-rw-r--r--drivers/net/ethernet/freescale/dpaa/Makefile12
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c2753
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.h185
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c165
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h141
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c417
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c38
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c1
-rw-r--r--drivers/net/ethernet/freescale/fman/mac.c8
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c51
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet.h1
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c9
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c25
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c1
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c9
-rw-r--r--drivers/net/ethernet/fujitsu/fmvj18x_cs.c1
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_eth.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hisi_femac.c1
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c352
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.h19
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c38
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c73
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h17
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c411
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h31
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c31
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h13
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c41
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c117
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ethtool.c3
-rw-r--r--drivers/net/ethernet/hp/hp100.c2
-rw-r--r--drivers/net/ethernet/i825xx/82596.c1
-rw-r--r--drivers/net/ethernet/i825xx/ether1.c1
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c1
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c1
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c14
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c10
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c6
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c16
-rw-r--r--drivers/net/ethernet/intel/Kconfig10
-rw-r--r--drivers/net/ethernet/intel/e100.c9
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c16
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c22
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_netdev.c15
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h85
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h51
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_client.c85
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_client.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c316
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c113
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_devids.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c168
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_fcoe.c12
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c1484
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h19
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c158
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c219
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.h48
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_type.h106
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl.h4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c141
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.c4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h51
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_common.c2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_devids.h2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_prototype.h4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.c156
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.h46
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_type.h87
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf.h3
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c8
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c260
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c3
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h3
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c15
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c16
-rw-r--r--drivers/net/ethernet/intel/igbvf/defines.h3
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c14
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c16
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c62
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c179
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c240
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h12
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h70
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c751
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c42
-rw-r--r--drivers/net/ethernet/jme.c12
-rw-r--r--drivers/net/ethernet/korina.c1
-rw-r--r--drivers/net/ethernet/lantiq_etop.c26
-rw-r--r--drivers/net/ethernet/marvell/Kconfig20
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c177
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c388
-rw-r--r--drivers/net/ethernet/marvell/mvpp2.c37
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c8
-rw-r--r--drivers/net/ethernet/marvell/skge.c13
-rw-r--r--drivers/net/ethernet/marvell/skge.h4
-rw-r--r--drivers/net/ethernet/marvell/sky2.c18
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Kconfig2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c103
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c431
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_port.c83
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c139
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_selftest.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c74
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h71
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Kconfig2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/alloc.c66
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c163
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h108
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c47
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_clock.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_common.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c457
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c105
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c62
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c27
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c314
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c173
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c352
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.h50
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c583
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c251
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h63
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c237
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c46
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c405
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c40
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/port.c120
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/rl.c65
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/vport.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/wq.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/wq.h18
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Kconfig45
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Makefile7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/cmd.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c336
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h165
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_thermal.c442
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c582
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.h60
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/ib.h39
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/item.h50
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/minimal.c97
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c199
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.h208
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci_hw.h229
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/port.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h888
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/resources.h127
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c532
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c136
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/switchib.c605
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/switchx2.c650
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/trap.h1
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c1
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c1
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c33
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c1
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c1
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c22
-rw-r--r--drivers/net/ethernet/natsemi/jazzsonic.c1
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c1
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c7
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c13
-rw-r--r--drivers/net/ethernet/natsemi/xtsonic.c1
-rw-r--r--drivers/net/ethernet/neterion/s2io.c9
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.h2
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c9
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_bpf.h1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c92
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c3
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h73
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c1255
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h13
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c50
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c94
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_offload.c9
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c45
-rw-r--r--drivers/net/ethernet/netx-eth.c1
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c1
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c9
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c1
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c13
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c1
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c1
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c12
-rw-r--r--drivers/net/ethernet/qlogic/Kconfig3
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c12
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c7
-rw-r--r--drivers/net/ethernet/qlogic/qed/Makefile1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed.h37
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c437
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hsi.h121
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.c32
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.c1277
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.h52
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c611
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.h133
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ll2.c555
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ll2.h9
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c105
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c441
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.h158
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ooo.c501
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ooo.h176
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_reg_addr.h2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_roce.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_selftest.c101
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_selftest.h10
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp.h4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp_commands.c4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_spq.c121
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.c398
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.h22
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.c101
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.h54
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede.h170
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_ethtool.c268
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c1501
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c7
-rw-r--r--drivers/net/ethernet/qualcomm/emac/Makefile4
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii-fsm9900.c245
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2400.c217
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2432.c210
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.c569
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.h6
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c13
-rw-r--r--drivers/net/ethernet/qualcomm/qca_framing.h6
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.c16
-rw-r--r--drivers/net/ethernet/rdc/r6040.c1
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c8
-rw-r--r--drivers/net/ethernet/realtek/8139too.c13
-rw-r--r--drivers/net/ethernet/realtek/atp.c1
-rw-r--r--drivers/net/ethernet/realtek/r8169.c16
-rw-r--r--drivers/net/ethernet/renesas/Kconfig2
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c1
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c2
-rw-r--r--drivers/net/ethernet/rocker/rocker.h1
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c130
-rw-r--r--drivers/net/ethernet/rocker/rocker_ofdpa.c1
-rw-r--r--drivers/net/ethernet/samsung/Kconfig2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h1
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c44
-rw-r--r--drivers/net/ethernet/seeq/ether3.c1
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c1
-rw-r--r--drivers/net/ethernet/sfc/Kconfig9
-rw-r--r--drivers/net/ethernet/sfc/Makefile7
-rw-r--r--drivers/net/ethernet/sfc/ef10.c242
-rw-r--r--drivers/net/ethernet/sfc/ef10_regs.h103
-rw-r--r--drivers/net/ethernet/sfc/efx.c89
-rw-r--r--drivers/net/ethernet/sfc/enum.h5
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c33
-rw-r--r--drivers/net/ethernet/sfc/falcon/Kconfig21
-rw-r--r--drivers/net/ethernet/sfc/falcon/Makefile6
-rw-r--r--drivers/net/ethernet/sfc/falcon/bitfield.h542
-rw-r--r--drivers/net/ethernet/sfc/falcon/efx.c3350
-rw-r--r--drivers/net/ethernet/sfc/falcon/efx.h277
-rw-r--r--drivers/net/ethernet/sfc/falcon/enum.h171
-rw-r--r--drivers/net/ethernet/sfc/falcon/ethtool.c1343
-rw-r--r--drivers/net/ethernet/sfc/falcon/falcon.c (renamed from drivers/net/ethernet/sfc/falcon.c)1040
-rw-r--r--drivers/net/ethernet/sfc/falcon/falcon_boards.c (renamed from drivers/net/ethernet/sfc/falcon_boards.c)94
-rw-r--r--drivers/net/ethernet/sfc/falcon/farch.c2892
-rw-r--r--drivers/net/ethernet/sfc/falcon/farch_regs.h2932
-rw-r--r--drivers/net/ethernet/sfc/falcon/filter.h272
-rw-r--r--drivers/net/ethernet/sfc/falcon/io.h290
-rw-r--r--drivers/net/ethernet/sfc/falcon/mdio_10g.c (renamed from drivers/net/ethernet/sfc/mdio_10g.c)86
-rw-r--r--drivers/net/ethernet/sfc/falcon/mdio_10g.h (renamed from drivers/net/ethernet/sfc/mdio_10g.h)54
-rw-r--r--drivers/net/ethernet/sfc/falcon/mtd.c133
-rw-r--r--drivers/net/ethernet/sfc/falcon/net_driver.h1464
-rw-r--r--drivers/net/ethernet/sfc/falcon/nic.c527
-rw-r--r--drivers/net/ethernet/sfc/falcon/nic.h513
-rw-r--r--drivers/net/ethernet/sfc/falcon/phy.h (renamed from drivers/net/ethernet/sfc/phy.h)18
-rw-r--r--drivers/net/ethernet/sfc/falcon/qt202x_phy.c (renamed from drivers/net/ethernet/sfc/qt202x_phy.c)140
-rw-r--r--drivers/net/ethernet/sfc/falcon/rx.c974
-rw-r--r--drivers/net/ethernet/sfc/falcon/selftest.c808
-rw-r--r--drivers/net/ethernet/sfc/falcon/selftest.h55
-rw-r--r--drivers/net/ethernet/sfc/falcon/tenxpress.c (renamed from drivers/net/ethernet/sfc/tenxpress.c)108
-rw-r--r--drivers/net/ethernet/sfc/falcon/tx.c649
-rw-r--r--drivers/net/ethernet/sfc/falcon/tx.h27
-rw-r--r--drivers/net/ethernet/sfc/falcon/txc43128_phy.c (renamed from drivers/net/ethernet/sfc/txc43128_phy.c)134
-rw-r--r--drivers/net/ethernet/sfc/falcon/workarounds.h44
-rw-r--r--drivers/net/ethernet/sfc/farch.c182
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c1
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h4
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mon.c4
-rw-r--r--drivers/net/ethernet/sfc/mcdi_pcol.h483
-rw-r--r--drivers/net/ethernet/sfc/mcdi_port.c3
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h78
-rw-r--r--drivers/net/ethernet/sfc/nic.h174
-rw-r--r--drivers/net/ethernet/sfc/ptp.c2
-rw-r--r--drivers/net/ethernet/sfc/rx.c27
-rw-r--r--drivers/net/ethernet/sfc/siena.c4
-rw-r--r--drivers/net/ethernet/sfc/tx.c1055
-rw-r--r--drivers/net/ethernet/sfc/tx.h27
-rw-r--r--drivers/net/ethernet/sfc/tx_tso.c451
-rw-r--r--drivers/net/ethernet/sfc/workarounds.h21
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c1
-rw-r--r--drivers/net/ethernet/sgi/meth.c1
-rw-r--r--drivers/net/ethernet/silan/sc92031.c1
-rw-r--r--drivers/net/ethernet/sis/sis190.c1
-rw-r--r--drivers/net/ethernet/sis/sis900.c1
-rw-r--r--drivers/net/ethernet/smsc/epic100.c1
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c1
-rw-r--r--drivers/net/ethernet/smsc/smc9194.c1
-rw-r--r--drivers/net/ethernet/smsc/smc91c92_cs.c1
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c6
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h80
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c14
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/chain_mode.c55
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs.h20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs_com.h48
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c217
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c95
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c83
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c26
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c62
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c37
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c55
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c48
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/ring_mode.c39
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c122
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c384
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c137
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c41
-rw-r--r--drivers/net/ethernet/sun/cassini.c7
-rw-r--r--drivers/net/ethernet/sun/ldmvsw.c5
-rw-r--r--drivers/net/ethernet/sun/niu.c7
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c1
-rw-r--r--drivers/net/ethernet/sun/sungem.c11
-rw-r--r--drivers/net/ethernet/sun/sunhme.c1
-rw-r--r--drivers/net/ethernet/sun/sunqe.c1
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c5
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.c26
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.h3
-rw-r--r--drivers/net/ethernet/synopsys/dwc_eth_qos.c2
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c14
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.h3
-rw-r--r--drivers/net/ethernet/ti/Kconfig11
-rw-r--r--drivers/net/ethernet/ti/Makefile3
-rw-r--r--drivers/net/ethernet/ti/cpmac.c1
-rw-r--r--drivers/net/ethernet/ti/cpsw.c441
-rw-r--r--drivers/net/ethernet/ti/cpsw.h2
-rw-r--r--drivers/net/ethernet/ti/cpts.c233
-rw-r--r--drivers/net/ethernet/ti/cpts.h80
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c561
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.h6
-rw-r--r--drivers/net/ethernet/ti/netcp.h2
-rw-r--r--drivers/net/ethernet/ti/netcp_core.c52
-rw-r--r--drivers/net/ethernet/ti/netcp_ethss.c479
-rw-r--r--drivers/net/ethernet/ti/tlan.c1
-rw-r--r--drivers/net/ethernet/tile/Kconfig2
-rw-r--r--drivers/net/ethernet/tile/tilegx.c21
-rw-r--r--drivers/net/ethernet/tile/tilepro.c27
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.c23
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.h1
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c1
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c24
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c1
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c1
-rw-r--r--drivers/net/ethernet/via/via-rhine.c1
-rw-r--r--drivers/net/ethernet/via/via-velocity.c11
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c1
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c1
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c18
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c20
-rw-r--r--drivers/net/ethernet/xircom/xirc2ps_cs.c1
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c8
-rw-r--r--drivers/net/fddi/skfp/skfddi.c1
-rw-r--r--drivers/net/fjes/Makefile2
-rw-r--r--drivers/net/fjes/fjes.h16
-rw-r--r--drivers/net/fjes/fjes_debugfs.c117
-rw-r--r--drivers/net/fjes/fjes_ethtool.c181
-rw-r--r--drivers/net/fjes/fjes_hw.c171
-rw-r--r--drivers/net/fjes/fjes_hw.h34
-rw-r--r--drivers/net/fjes/fjes_main.c65
-rw-r--r--drivers/net/fjes/fjes_trace.c30
-rw-r--r--drivers/net/fjes/fjes_trace.h380
-rw-r--r--drivers/net/geneve.c713
-rw-r--r--drivers/net/gtp.c24
-rw-r--r--drivers/net/hippi/rrunner.c1
-rw-r--r--drivers/net/hyperv/hyperv_net.h4
-rw-r--r--drivers/net/hyperv/netvsc.c15
-rw-r--r--drivers/net/hyperv/netvsc_drv.c14
-rw-r--r--drivers/net/hyperv/rndis_filter.c6
-rw-r--r--drivers/net/ieee802154/adf7242.c2
-rw-r--r--drivers/net/ieee802154/at86rf230.c16
-rw-r--r--drivers/net/ieee802154/atusb.c81
-rw-r--r--drivers/net/ieee802154/atusb.h11
-rw-r--r--drivers/net/ieee802154/fakelb.c2
-rw-r--r--drivers/net/ipvlan/ipvlan.h2
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c8
-rw-r--r--drivers/net/irda/w83977af_ir.c671
-rw-r--r--drivers/net/macsec.c49
-rw-r--r--drivers/net/macvlan.c24
-rw-r--r--drivers/net/macvtap.c7
-rw-r--r--drivers/net/mii.c197
-rw-r--r--drivers/net/nlmon.c20
-rw-r--r--drivers/net/ntb_netdev.c3
-rw-r--r--drivers/net/phy/Kconfig22
-rw-r--r--drivers/net/phy/Makefile2
-rw-r--r--drivers/net/phy/aquantia.c28
-rw-r--r--drivers/net/phy/at803x.c13
-rw-r--r--drivers/net/phy/bcm-cygnus.c5
-rw-r--r--drivers/net/phy/bcm-phy-lib.c187
-rw-r--r--drivers/net/phy/bcm-phy-lib.h15
-rw-r--r--drivers/net/phy/bcm7xxx.c92
-rw-r--r--drivers/net/phy/broadcom.c139
-rw-r--r--drivers/net/phy/dp83640.c14
-rw-r--r--drivers/net/phy/dp83867.c28
-rw-r--r--drivers/net/phy/icplus.c6
-rw-r--r--drivers/net/phy/intel-xway.c24
-rw-r--r--drivers/net/phy/marvell.c10
-rw-r--r--drivers/net/phy/mdio-mux-mmioreg.c60
-rw-r--r--drivers/net/phy/mdio_bus.c11
-rw-r--r--drivers/net/phy/mdio_device.c2
-rw-r--r--drivers/net/phy/meson-gxl.c81
-rw-r--r--drivers/net/phy/micrel.c30
-rw-r--r--drivers/net/phy/microchip.c39
-rw-r--r--drivers/net/phy/mscc.c358
-rw-r--r--drivers/net/phy/national.c2
-rw-r--r--drivers/net/phy/phy.c136
-rw-r--r--drivers/net/phy/phy_device.c159
-rw-r--r--drivers/net/phy/phy_led_triggers.c134
-rw-r--r--drivers/net/phy/smsc.c18
-rw-r--r--drivers/net/phy/vitesse.c14
-rw-r--r--drivers/net/plip/plip.c1
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/ppp/pppoe.c2
-rw-r--r--drivers/net/rionet.c15
-rw-r--r--drivers/net/sb1000.c1
-rw-r--r--drivers/net/slip/slip.c11
-rw-r--r--drivers/net/team/team.c25
-rw-r--r--drivers/net/tun.c52
-rw-r--r--drivers/net/usb/Kconfig5
-rw-r--r--drivers/net/usb/asix_devices.c4
-rw-r--r--drivers/net/usb/ax88172a.c10
-rw-r--r--drivers/net/usb/ax88179_178a.c4
-rw-r--r--drivers/net/usb/catc.c1
-rw-r--r--drivers/net/usb/cdc-phonet.c12
-rw-r--r--drivers/net/usb/cdc_ether.c28
-rw-r--r--drivers/net/usb/cdc_ncm.c5
-rw-r--r--drivers/net/usb/kaweth.c1
-rw-r--r--drivers/net/usb/lan78xx.c462
-rw-r--r--drivers/net/usb/lan78xx.h14
-rw-r--r--drivers/net/usb/pegasus.c1
-rw-r--r--drivers/net/usb/r8152.c24
-rw-r--r--drivers/net/usb/rtl8150.c1
-rw-r--r--drivers/net/usb/sierra_net.c13
-rw-r--r--drivers/net/usb/smsc75xx.c4
-rw-r--r--drivers/net/usb/usbnet.c4
-rw-r--r--drivers/net/veth.c17
-rw-r--r--drivers/net/virtio_net.c34
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c7
-rw-r--r--drivers/net/vrf.c23
-rw-r--r--drivers/net/vxlan.c350
-rw-r--r--drivers/net/wan/c101.c1
-rw-r--r--drivers/net/wan/cosa.c1
-rw-r--r--drivers/net/wan/dscc4.c1
-rw-r--r--drivers/net/wan/farsync.c1
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c1
-rw-r--r--drivers/net/wan/hdlc.c11
-rw-r--r--drivers/net/wan/hdlc_fr.c3
-rw-r--r--drivers/net/wan/hostess_sv11.c1
-rw-r--r--drivers/net/wan/ixp4xx_hss.c1
-rw-r--r--drivers/net/wan/lmc/lmc_main.c1
-rw-r--r--drivers/net/wan/n2.c1
-rw-r--r--drivers/net/wan/pc300too.c1
-rw-r--r--drivers/net/wan/pci200syn.c1
-rw-r--r--drivers/net/wan/sbni.c1
-rw-r--r--drivers/net/wan/sealevel.c1
-rw-r--r--drivers/net/wan/wanxl.c1
-rw-r--r--drivers/net/wan/x25_asy.c5
-rw-r--r--drivers/net/wimax/i2400m/netdev.c22
-rw-r--r--drivers/net/wireless/Kconfig13
-rw-r--r--drivers/net/wireless/ath/ath.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c21
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h44
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h22
-rw-r--r--drivers/net/wireless/ath/ath10k/debugfs_sta.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h31
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c137
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c129
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c142
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h28
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c192
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c77
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c62
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h18
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c1
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c15
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug_sta.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c50
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/rng.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c338
-rw-r--r--drivers/net/wireless/ath/main.c7
-rw-r--r--drivers/net/wireless/ath/regd.c3
-rw-r--r--drivers/net/wireless/ath/regd.h1
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c129
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c100
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c19
-rw-r--r--drivers/net/wireless/ath/wil6210/p2p.c160
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c55
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c110
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h25
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_crash_dump.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c160
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h586
-rw-r--r--drivers/net/wireless/atmel/atmel.c13
-rw-r--r--drivers/net/wireless/broadcom/b43/main.c2
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/main.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile3
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c12
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c411
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h23
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c15
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c44
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c171
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c242
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h40
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h9
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h1
-rw-r--r--drivers/net/wireless/cisco/airo.c14
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c3
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c8
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw.h1
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_module.c9
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_rx.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c100
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c86
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_80211_rx.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_main.c15
-rw-r--r--drivers/net/wireless/intersil/orinoco/main.c6
-rw-r--r--drivers/net/wireless/intersil/p54/fwio.c2
-rw-r--r--drivers/net/wireless/intersil/prism54/islpci_dev.c1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c111
-rw-r--r--drivers/net/wireless/marvell/libertas/main.c1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/README23
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c24
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c116
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h45
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c183
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c157
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.h9
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmd.c87
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_cmd.c8
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.c63
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/wmm.c31
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/init.c14
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/regs.h3
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2400pci.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500pci.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500usb.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c67
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800usb.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00dev.c25
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt61pci.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt73usb.c5
-rw-r--r--drivers/net/wireless/ray_cs.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h27
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c111
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c18
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.c36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.h4
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c175
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c134
-rw-r--r--drivers/net/wireless/rsi/rsi_main.h4
-rw-r--r--drivers/net/wireless/rsi/rsi_mgmt.h32
-rw-r--r--drivers/net/wireless/st/cw1200/wsm.c24
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.c28
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h1
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.c5
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c9
-rw-r--r--drivers/net/wireless/wl3501_cs.c1
-rw-r--r--drivers/net/wireless/zydas/zd1201.c1
-rw-r--r--drivers/net/xen-netback/interface.c5
-rw-r--r--drivers/net/xen-netback/xenbus.c12
-rw-r--r--drivers/net/xen-netfront.c2
-rw-r--r--drivers/nvdimm/Kconfig2
-rw-r--r--drivers/nvme/host/Kconfig17
-rw-r--r--drivers/nvme/host/Makefile3
-rw-r--r--drivers/nvme/host/core.c150
-rw-r--r--drivers/nvme/host/fabrics.c33
-rw-r--r--drivers/nvme/host/fc.c2586
-rw-r--r--drivers/nvme/host/lightnvm.c223
-rw-r--r--drivers/nvme/host/nvme.h51
-rw-r--r--drivers/nvme/host/pci.c47
-rw-r--r--drivers/nvme/host/rdma.c43
-rw-r--r--drivers/nvme/host/scsi.c11
-rw-r--r--drivers/nvme/target/Kconfig24
-rw-r--r--drivers/nvme/target/Makefile4
-rw-r--r--drivers/nvme/target/admin-cmd.c3
-rw-r--r--drivers/nvme/target/configfs.c20
-rw-r--r--drivers/nvme/target/core.c22
-rw-r--r--drivers/nvme/target/fabrics-cmd.c14
-rw-r--r--drivers/nvme/target/fc.c2288
-rw-r--r--drivers/nvme/target/fcloop.c1148
-rw-r--r--drivers/nvme/target/io-cmd.c39
-rw-r--r--drivers/nvme/target/loop.c26
-rw-r--r--drivers/nvme/target/nvmet.h8
-rw-r--r--drivers/nvme/target/rdma.c8
-rw-r--r--drivers/of/fdt.c19
-rw-r--r--drivers/oprofile/nmi_timer_int.c58
-rw-r--r--drivers/pci/host/pci-xgene-msi.c69
-rw-r--r--drivers/pci/msi.c78
-rw-r--r--drivers/pcmcia/m32r_pcc.c41
-rw-r--r--drivers/pinctrl/Kconfig26
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/bcm/Kconfig1
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c165
-rw-r--r--drivers/pinctrl/devicetree.c144
-rw-r--r--drivers/pinctrl/devicetree.h23
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c8
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c41
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt6397.c6
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h2
-rw-r--r--drivers/pinctrl/meson/Makefile3
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-gxl.c589
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c8
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.h2
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c23
-rw-r--r--drivers/pinctrl/pinconf-generic.c2
-rw-r--r--drivers/pinctrl/pinctrl-at91.c21
-rw-r--r--drivers/pinctrl/pinctrl-da850-pupd.c210
-rw-r--r--drivers/pinctrl/pinctrl-oxnas.c605
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c86
-rw-r--r--drivers/pinctrl/pinctrl-single.c217
-rw-r--r--drivers/pinctrl/pinctrl-st.c4
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c1275
-rw-r--r--drivers/pinctrl/pinctrl-zynq.c6
-rw-r--r--drivers/pinctrl/qcom/Kconfig9
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8994.c1379
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c45
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h11
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c24xx.c37
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c64xx.c40
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c40
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h10
-rw-r--r--drivers/pinctrl/sh-pfc/core.c15
-rw-r--r--drivers/pinctrl/sh-pfc/core.h4
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7778.c342
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795.c616
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7796.c576
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c3
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h14
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32f429.c6
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-gr8.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c10
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c11
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c10
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c9
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c506
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.h8
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-vt8500.c17
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8505.c17
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8650.c17
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8750.c17
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8850.c17
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c10
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.h1
-rw-r--r--drivers/power/avs/rockchip-io-domain.c2
-rw-r--r--drivers/powercap/intel_rapl.c389
-rw-r--r--drivers/ptp/Kconfig10
-rw-r--r--drivers/ptp/ptp_clock.c5
-rw-r--r--drivers/ptp/ptp_sysfs.c2
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/arizona-ldo1.c2
-rw-r--r--drivers/regulator/axp20x-regulator.c12
-rw-r--r--drivers/regulator/core.c38
-rw-r--r--drivers/regulator/fixed.c46
-rw-r--r--drivers/regulator/gpio-regulator.c9
-rw-r--r--drivers/regulator/helpers.c6
-rw-r--r--drivers/regulator/lp873x-regulator.c1
-rw-r--r--drivers/regulator/max77620-regulator.c47
-rw-r--r--drivers/regulator/stw481x-vmmc.c3
-rw-r--r--drivers/regulator/tps6507x-regulator.c2
-rw-r--r--drivers/regulator/tps65086-regulator.c51
-rw-r--r--drivers/regulator/twl-regulator.c673
-rw-r--r--drivers/regulator/twl6030-regulator.c793
-rw-r--r--drivers/remoteproc/Kconfig52
-rw-r--r--drivers/remoteproc/Makefile9
-rw-r--r--drivers/remoteproc/qcom_adsp_pil.c428
-rw-r--r--drivers/remoteproc/qcom_mdt_loader.c1
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c1
-rw-r--r--drivers/remoteproc/qcom_wcnss.c53
-rw-r--r--drivers/remoteproc/qcom_wcnss.h2
-rw-r--r--drivers/remoteproc/qcom_wcnss_iris.c9
-rw-r--r--drivers/remoteproc/remoteproc_core.c247
-rw-r--r--drivers/remoteproc/remoteproc_debugfs.c71
-rw-r--r--drivers/remoteproc/remoteproc_internal.h6
-rw-r--r--drivers/remoteproc/remoteproc_sysfs.c151
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c17
-rw-r--r--drivers/remoteproc/st_remoteproc.c4
-rw-r--r--drivers/remoteproc/st_slim_rproc.c364
-rw-r--r--drivers/remoteproc/ste_modem_rproc.c342
-rw-r--r--drivers/rpmsg/qcom_smd.c18
-rw-r--r--drivers/rpmsg/rpmsg_core.c74
-rw-r--r--drivers/rtc/rtc-cmos.c7
-rw-r--r--drivers/s390/net/ctcm_main.c5
-rw-r--r--drivers/s390/net/lcs.c2
-rw-r--r--drivers/s390/net/netiucv.c41
-rw-r--r--drivers/s390/net/qeth_core_main.c4
-rw-r--r--drivers/s390/net/qeth_l2_main.c2
-rw-r--r--drivers/s390/net/qeth_l3_main.c2
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c1
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c8
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c2
-rw-r--r--drivers/scsi/osd/osd_initiator.c2
-rw-r--r--drivers/scsi/osst.c2
-rw-r--r--drivers/scsi/pmcraid.c11
-rw-r--r--drivers/scsi/scsi.c3
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_lib.c92
-rw-r--r--drivers/scsi/sd.c181
-rw-r--r--drivers/scsi/sd.h70
-rw-r--r--drivers/scsi/sd_zbc.c648
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/ufs/ufshcd.c6
-rw-r--r--drivers/sh/intc/virq.c2
-rw-r--r--drivers/soc/Kconfig3
-rw-r--r--drivers/soc/fsl/Kconfig18
-rw-r--r--drivers/soc/fsl/Makefile1
-rw-r--r--drivers/soc/fsl/guts.c239
-rw-r--r--drivers/soc/fsl/qbman/bman_portal.c46
-rw-r--r--drivers/soc/fsl/qbman/qman_portal.c39
-rw-r--r--drivers/soc/renesas/Makefile5
-rw-r--r--drivers/soc/renesas/rcar-rst.c92
-rw-r--r--drivers/ssb/pci.c1
-rw-r--r--drivers/staging/lustre/include/linux/lnet/types.h1
-rw-r--r--drivers/staging/lustre/lustre/llite/rw.c1
-rw-r--r--drivers/staging/octeon/ethernet.c22
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mon.c1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c1
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c1
-rw-r--r--drivers/staging/slicoss/slicoss.c1
-rw-r--r--drivers/staging/unisys/include/iochannel.h10
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c4
-rw-r--r--drivers/staging/vme/devices/vme_user.c2
-rw-r--r--drivers/staging/wilc1000/linux_mon.c4
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c18
-rw-r--r--drivers/target/iscsi/cxgbit/cxgbit_main.c1
-rw-r--r--drivers/target/target_core_iblock.c8
-rw-r--r--drivers/target/target_core_pscsi.c8
-rw-r--r--drivers/target/target_core_user.c4
-rw-r--r--drivers/thermal/Kconfig4
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/db8500_thermal.c1
-rw-r--r--drivers/thermal/devfreq_cooling.c5
-rw-r--r--drivers/thermal/int340x_thermal/int3400_thermal.c2
-rw-r--r--drivers/thermal/intel_pch_thermal.c64
-rw-r--r--drivers/thermal/intel_powerclamp.c360
-rw-r--r--drivers/thermal/max77620_thermal.c1
-rw-r--r--drivers/thermal/qcom-spmi-temp-alarm.c6
-rw-r--r--drivers/thermal/rockchip_thermal.c7
-rw-r--r--drivers/thermal/tango_thermal.c1
-rw-r--r--drivers/thermal/thermal_core.c1450
-rw-r--r--drivers/thermal/thermal_core.h26
-rw-r--r--drivers/thermal/thermal_helpers.c226
-rw-r--r--drivers/thermal/thermal_hwmon.c4
-rw-r--r--drivers/thermal/thermal_sysfs.c771
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c5
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c587
-rw-r--r--drivers/thunderbolt/Kconfig2
-rw-r--r--drivers/thunderbolt/eeprom.c43
-rw-r--r--drivers/thunderbolt/switch.c2
-rw-r--r--drivers/tty/n_gsm.c12
-rw-r--r--drivers/tty/serial/crisv10.c6
-rw-r--r--drivers/tty/synclink.c1
-rw-r--r--drivers/tty/synclink_gt.c1
-rw-r--r--drivers/tty/synclinkmp.c1
-rw-r--r--drivers/usb/gadget/function/f_phonet.c11
-rw-r--r--drivers/usb/gadget/function/u_ether.c14
-rw-r--r--drivers/vfio/Kconfig1
-rw-r--r--drivers/vfio/Makefile1
-rw-r--r--drivers/vfio/mdev/Kconfig17
-rw-r--r--drivers/vfio/mdev/Makefile5
-rw-r--r--drivers/vfio/mdev/mdev_core.c385
-rw-r--r--drivers/vfio/mdev/mdev_driver.c119
-rw-r--r--drivers/vfio/mdev/mdev_private.h41
-rw-r--r--drivers/vfio/mdev/mdev_sysfs.c286
-rw-r--r--drivers/vfio/mdev/vfio_mdev.c148
-rw-r--r--drivers/vfio/pci/vfio_pci.c83
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c10
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c31
-rw-r--r--drivers/vfio/vfio.c461
-rw-r--r--drivers/vfio/vfio_iommu_type1.c885
-rw-r--r--drivers/vhost/net.c4
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--drivers/vhost/vsock.c3
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/fbdev/efifb.c59
-rw-r--r--drivers/video/fbdev/skeletonfb.c8
-rw-r--r--drivers/video/hdmi.c4
-rw-r--r--drivers/video/of_display_timing.c15
-rw-r--r--drivers/virtio/Kconfig2
-rw-r--r--drivers/watchdog/octeon-wdt-main.c62
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--fs/9p/vfs_addr.c1
-rw-r--r--fs/Kconfig.binfmt4
-rw-r--r--fs/binfmt_elf.c6
-rw-r--r--fs/block_dev.c272
-rw-r--r--fs/btrfs/disk-io.c8
-rw-r--r--fs/btrfs/extent_io.c16
-rw-r--r--fs/btrfs/inode.c11
-rw-r--r--fs/btrfs/scrub.c2
-rw-r--r--fs/btrfs/super.c26
-rw-r--r--fs/btrfs/volumes.c4
-rw-r--r--fs/btrfs/volumes.h2
-rw-r--r--fs/buffer.c26
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/transport.c1
-rw-r--r--fs/dax.c10
-rw-r--r--fs/direct-io.c4
-rw-r--r--fs/dlm/netlink.c16
-rw-r--r--fs/exec.c2
-rw-r--r--fs/ext4/mmp.c6
-rw-r--r--fs/ext4/page-io.c2
-rw-r--r--fs/ext4/super.c2
-rw-r--r--fs/f2fs/checkpoint.c4
-rw-r--r--fs/f2fs/data.c16
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/gc.c6
-rw-r--r--fs/f2fs/inline.c2
-rw-r--r--fs/f2fs/node.c4
-rw-r--r--fs/f2fs/segment.c8
-rw-r--r--fs/f2fs/super.c2
-rw-r--r--fs/fs-writeback.c16
-rw-r--r--fs/gfs2/dir.c1
-rw-r--r--fs/gfs2/log.c4
-rw-r--r--fs/gfs2/lops.c2
-rw-r--r--fs/gfs2/meta_io.c7
-rw-r--r--fs/gfs2/ops_fstype.c2
-rw-r--r--fs/hfsplus/super.c4
-rw-r--r--fs/isofs/compress.c1
-rw-r--r--fs/jbd2/checkpoint.c2
-rw-r--r--fs/jbd2/commit.c9
-rw-r--r--fs/jbd2/journal.c15
-rw-r--r--fs/jbd2/revoke.c2
-rw-r--r--fs/jfs/jfs_logmgr.c4
-rw-r--r--fs/lockd/netns.h2
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/logfs/dev_bdev.c106
-rw-r--r--fs/mpage.c6
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/netns.h2
-rw-r--r--fs/nfs_common/grace.c2
-rw-r--r--fs/nfsd/netns.h2
-rw-r--r--fs/nfsd/nfsctl.c2
-rw-r--r--fs/nilfs2/super.c2
-rw-r--r--fs/nsfs.c2
-rw-r--r--fs/ntfs/aops.c1
-rw-r--r--fs/ntfs/logfile.c1
-rw-r--r--fs/ntfs/mft.c1
-rw-r--r--fs/ocfs2/aops.c7
-rw-r--r--fs/ocfs2/aops.h3
-rw-r--r--fs/ocfs2/buffer_head_io.c1
-rw-r--r--fs/ocfs2/cluster/heartbeat.c4
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c11
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c2
-rw-r--r--fs/ocfs2/inode.c2
-rw-r--r--fs/ocfs2/journal.c4
-rw-r--r--fs/ocfs2/mmap.c3
-rw-r--r--fs/ocfs2/namei.c6
-rw-r--r--fs/ocfs2/ocfs2.h2
-rw-r--r--fs/ocfs2/refcounttree.c1
-rw-r--r--fs/ocfs2/super.c2
-rw-r--r--fs/orangefs/inode.c1
-rw-r--r--fs/proc/array.c7
-rw-r--r--fs/proc/base.c31
-rw-r--r--fs/proc/inode.c37
-rw-r--r--fs/proc/internal.h3
-rw-r--r--fs/proc/root.c1
-rw-r--r--fs/proc/task_mmu.c1
-rw-r--r--fs/pstore/Kconfig2
-rw-r--r--fs/pstore/ftrace.c11
-rw-r--r--fs/pstore/inode.c15
-rw-r--r--fs/pstore/internal.h34
-rw-r--r--fs/pstore/platform.c5
-rw-r--r--fs/pstore/ram.c327
-rw-r--r--fs/pstore/ram_core.c27
-rw-r--r--fs/quota/netlink.c10
-rw-r--r--fs/reiserfs/inode.c1
-rw-r--r--fs/reiserfs/journal.c6
-rw-r--r--fs/reiserfs/stree.c1
-rw-r--r--fs/splice.c1
-rw-r--r--fs/squashfs/block.c1
-rw-r--r--fs/udf/dir.c1
-rw-r--r--fs/udf/directory.c1
-rw-r--r--fs/udf/inode.c1
-rw-r--r--fs/ufs/balloc.c1
-rw-r--r--fs/xfs/xfs_aops.c7
-rw-r--r--fs/xfs/xfs_buf.c2
-rw-r--r--include/acpi/processor.h3
-rw-r--r--include/asm-generic/cputime_jiffies.h1
-rw-r--r--include/asm-generic/cputime_nsecs.h1
-rw-r--r--include/asm-generic/mutex-dec.h88
-rw-r--r--include/asm-generic/mutex-null.h19
-rw-r--r--include/asm-generic/mutex-xchg.h120
-rw-r--r--include/asm-generic/mutex.h9
-rw-r--r--include/asm-generic/pgtable.h22
-rw-r--r--include/asm-generic/tlb.h83
-rw-r--r--include/drm/bridge/mhl.h291
-rw-r--r--include/drm/drmP.h335
-rw-r--r--include/drm/drm_atomic.h55
-rw-r--r--include/drm/drm_blend.h10
-rw-r--r--include/drm/drm_connector.h72
-rw-r--r--include/drm/drm_crtc.h734
-rw-r--r--include/drm/drm_debugfs_crc.h73
-rw-r--r--include/drm/drm_dp_dual_mode_helper.h27
-rw-r--r--include/drm/drm_dp_helper.h6
-rw-r--r--include/drm/drm_drv.h435
-rw-r--r--include/drm/drm_edid.h1
-rw-r--r--include/drm/drm_encoder.h2
-rw-r--r--include/drm/drm_fb_cma_helper.h5
-rw-r--r--include/drm/drm_fb_helper.h4
-rw-r--r--include/drm/drm_fourcc.h33
-rw-r--r--include/drm/drm_framebuffer.h22
-rw-r--r--include/drm/drm_irq.h63
-rw-r--r--include/drm/drm_mm.h28
-rw-r--r--include/drm/drm_mode_config.h663
-rw-r--r--include/drm/drm_modeset_helper_vtables.h28
-rw-r--r--include/drm/drm_modeset_lock.h12
-rw-r--r--include/drm/drm_of.h13
-rw-r--r--include/drm/drm_plane.h100
-rw-r--r--include/drm/drm_print.h112
-rw-r--r--include/drm/i915_component.h6
-rw-r--r--include/drm/ttm/ttm_bo_api.h15
-rw-r--r--include/drm/ttm/ttm_bo_driver.h48
-rw-r--r--include/drm/ttm/ttm_execbuf_util.h2
-rw-r--r--include/dt-bindings/clock/hi3516cv300-clock.h48
-rw-r--r--include/dt-bindings/clock/histb-clock.h66
-rw-r--r--include/dt-bindings/clock/imx6ul-clock.h15
-rw-r--r--include/dt-bindings/clock/oxsemi,ox810se.h30
-rw-r--r--include/dt-bindings/clock/oxsemi,ox820.h40
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msm8994.h137
-rw-r--r--include/dt-bindings/clock/qcom,rpmcc.h69
-rw-r--r--include/dt-bindings/clock/r8a7743-cpg-mssr.h43
-rw-r--r--include/dt-bindings/clock/r8a7745-cpg-mssr.h44
-rw-r--r--include/dt-bindings/clock/rk1108-cru.h269
-rw-r--r--include/dt-bindings/clock/rk3188-cru-common.h8
-rw-r--r--include/dt-bindings/clock/sun50i-a64-ccu.h134
-rw-r--r--include/dt-bindings/gpio/meson-gxl-gpio.h131
-rw-r--r--include/dt-bindings/net/mdio.h19
-rw-r--r--include/dt-bindings/net/mscc-phy-vsc8531.h21
-rw-r--r--include/dt-bindings/pinctrl/at91.h2
-rw-r--r--include/dt-bindings/reset/sun50i-a64-ccu.h98
-rw-r--r--include/linux/acpi.h1
-rw-r--r--include/linux/alarmtimer.h5
-rw-r--r--include/linux/amba/pl061.h16
-rw-r--r--include/linux/backing-dev-defs.h5
-rw-r--r--include/linux/bio.h49
-rw-r--r--include/linux/blk-cgroup.h11
-rw-r--r--include/linux/blk-mq.h11
-rw-r--r--include/linux/blk_types.h188
-rw-r--r--include/linux/blkdev.h231
-rw-r--r--include/linux/blktrace_api.h2
-rw-r--r--include/linux/bpf-cgroup.h92
-rw-r--r--include/linux/bpf.h19
-rw-r--r--include/linux/bpf_verifier.h14
-rw-r--r--include/linux/brcmphy.h27
-rw-r--r--include/linux/bug.h17
-rw-r--r--include/linux/ceph/messenger.h2
-rw-r--r--include/linux/cgroup-defs.h4
-rw-r--r--include/linux/clk.h29
-rw-r--r--include/linux/clk/renesas.h4
-rw-r--r--include/linux/clocksource.h5
-rw-r--r--include/linux/cma.h3
-rw-r--r--include/linux/compiler-gcc.h2
-rw-r--r--include/linux/cpu.h17
-rw-r--r--include/linux/cpufreq.h6
-rw-r--r--include/linux/cpuhotplug.h21
-rw-r--r--include/linux/cpuidle.h9
-rw-r--r--include/linux/debugfs.h3
-rw-r--r--include/linux/devfreq_cooling.h9
-rw-r--r--include/linux/device.h21
-rw-r--r--include/linux/dm-io.h2
-rw-r--r--include/linux/dma-buf.h4
-rw-r--r--include/linux/dma-fence-array.h86
-rw-r--r--include/linux/dma-fence.h438
-rw-r--r--include/linux/drbd_genl.h2
-rw-r--r--include/linux/edac.h8
-rw-r--r--include/linux/efi.h46
-rw-r--r--include/linux/elevator.h9
-rw-r--r--include/linux/fddidevice.h1
-rw-r--r--include/linux/fence-array.h83
-rw-r--r--include/linux/fence.h378
-rw-r--r--include/linux/filter.h37
-rw-r--r--include/linux/fs.h68
-rw-r--r--include/linux/fsl/guts.h125
-rw-r--r--include/linux/ftrace.h2
-rw-r--r--include/linux/genl_magic_func.h29
-rw-r--r--include/linux/gpio/driver.h34
-rw-r--r--include/linux/hdlc.h2
-rw-r--r--include/linux/hdmi.h2
-rw-r--r--include/linux/hippidevice.h1
-rw-r--r--include/linux/huge_mm.h2
-rw-r--r--include/linux/ieee80211.h26
-rw-r--r--include/linux/if_arp.h16
-rw-r--r--include/linux/if_vlan.h16
-rw-r--r--include/linux/interrupt.h20
-rw-r--r--include/linux/ipv6.h10
-rw-r--r--include/linux/irqchip/arm-gic-v3.h4
-rw-r--r--include/linux/kernel.h4
-rw-r--r--include/linux/kernel_stat.h4
-rw-r--r--include/linux/kthread.h3
-rw-r--r--include/linux/kvm_host.h3
-rw-r--r--include/linux/leds.h25
-rw-r--r--include/linux/lightnvm.h244
-rw-r--r--include/linux/list.h37
-rw-r--r--include/linux/mbus.h8
-rw-r--r--include/linux/mc146818rtc.h1
-rw-r--r--include/linux/mdev.h168
-rw-r--r--include/linux/mempolicy.h8
-rw-r--r--include/linux/mfd/max77620.h2
-rw-r--r--include/linux/mfd/tmio.h5
-rw-r--r--include/linux/mii.h4
-rw-r--r--include/linux/mlx5/device.h16
-rw-r--r--include/linux/mlx5/driver.h60
-rw-r--r--include/linux/mlx5/fs.h43
-rw-r--r--include/linux/mlx5/mlx5_ifc.h319
-rw-r--r--include/linux/mlx5/port.h9
-rw-r--r--include/linux/mlx5/srq.h2
-rw-r--r--include/linux/mlx5/vport.h10
-rw-r--r--include/linux/mmc/card.h14
-rw-r--r--include/linux/mmc/core.h16
-rw-r--r--include/linux/mmc/dw_mmc.h6
-rw-r--r--include/linux/mmc/host.h17
-rw-r--r--include/linux/mmc/mmc.h17
-rw-r--r--include/linux/mmc/slot-gpio.h1
-rw-r--r--include/linux/mutex-debug.h24
-rw-r--r--include/linux/mutex.h77
-rw-r--r--include/linux/netdevice.h210
-rw-r--r--include/linux/netfilter.h89
-rw-r--r--include/linux/netfilter/ipset/ip_set.h136
-rw-r--r--include/linux/netfilter/ipset/ip_set_bitmap.h2
-rw-r--r--include/linux/netfilter/ipset/ip_set_comment.h11
-rw-r--r--include/linux/netfilter/ipset/ip_set_counter.h75
-rw-r--r--include/linux/netfilter/ipset/ip_set_skbinfo.h46
-rw-r--r--include/linux/netfilter/ipset/ip_set_timeout.h4
-rw-r--r--include/linux/netfilter/nf_conntrack_dccp.h2
-rw-r--r--include/linux/netfilter/x_tables.h86
-rw-r--r--include/linux/netfilter_ingress.h9
-rw-r--r--include/linux/netpoll.h13
-rw-r--r--include/linux/nvme-fc-driver.h851
-rw-r--r--include/linux/nvme-fc.h268
-rw-r--r--include/linux/nvme.h43
-rw-r--r--include/linux/of_fdt.h1
-rw-r--r--include/linux/parser.h1
-rw-r--r--include/linux/pci.h25
-rw-r--r--include/linux/phy.h44
-rw-r--r--include/linux/phy_led_triggers.h51
-rw-r--r--include/linux/pim.h81
-rw-r--r--include/linux/pm-trace.h9
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/pm_domain.h28
-rw-r--r--include/linux/pm_opp.h72
-rw-r--r--include/linux/pm_runtime.h11
-rw-r--r--include/linux/preempt.h21
-rw-r--r--include/linux/printk.h17
-rw-r--r--include/linux/proc_fs.h4
-rw-r--r--include/linux/pstore.h76
-rw-r--r--include/linux/pstore_ram.h14
-rw-r--r--include/linux/ptp_clock_kernel.h73
-rw-r--r--include/linux/qed/qed_chain.h144
-rw-r--r--include/linux/qed/qed_eth_if.h61
-rw-r--r--include/linux/qed/qed_if.h49
-rw-r--r--include/linux/qed/qed_iscsi_if.h229
-rw-r--r--include/linux/radix-tree.h34
-rw-r--r--include/linux/rculist.h8
-rw-r--r--include/linux/regulator/consumer.h27
-rw-r--r--include/linux/regulator/driver.h4
-rw-r--r--include/linux/remoteproc.h36
-rw-r--r--include/linux/remoteproc/st_slim_rproc.h58
-rw-r--r--include/linux/reservation.h41
-rw-r--r--include/linux/ring_buffer.h6
-rw-r--r--include/linux/rmap.h10
-rw-r--r--include/linux/rpmsg.h125
-rw-r--r--include/linux/rpmsg/qcom_smd.h33
-rw-r--r--include/linux/sched.h118
-rw-r--r--include/linux/sched/sysctl.h1
-rw-r--r--include/linux/seg6.h6
-rw-r--r--include/linux/seg6_genl.h6
-rw-r--r--include/linux/seg6_hmac.h6
-rw-r--r--include/linux/seg6_iptunnel.h6
-rw-r--r--include/linux/seqno-fence.h20
-rw-r--r--include/linux/skbuff.h23
-rw-r--r--include/linux/smc91x.h1
-rw-r--r--include/linux/soc/renesas/rcar-rst.h6
-rw-r--r--include/linux/stmmac.h5
-rw-r--r--include/linux/suspend.h2
-rw-r--r--include/linux/swap.h37
-rw-r--r--include/linux/sync_file.h14
-rw-r--r--include/linux/sys_soc.h9
-rw-r--r--include/linux/tcp.h24
-rw-r--r--include/linux/thermal.h2
-rw-r--r--include/linux/time.h2
-rw-r--r--include/linux/timekeeping.h1
-rw-r--r--include/linux/udp.h3
-rw-r--r--include/linux/uio.h2
-rw-r--r--include/linux/uprobes.h1
-rw-r--r--include/linux/vfio.h48
-rw-r--r--include/linux/virtio_net.h4
-rw-r--r--include/linux/vmalloc.h1
-rw-r--r--include/linux/workqueue.h35
-rw-r--r--include/linux/writeback.h13
-rw-r--r--include/linux/ww_mutex.h2
-rw-r--r--include/net/act_api.h5
-rw-r--r--include/net/bluetooth/bluetooth.h25
-rw-r--r--include/net/bonding.h2
-rw-r--r--include/net/busy_poll.h33
-rw-r--r--include/net/cfg80211.h161
-rw-r--r--include/net/devlink.h2
-rw-r--r--include/net/dst_metadata.h10
-rw-r--r--include/net/fib_rules.h9
-rw-r--r--include/net/flow.h10
-rw-r--r--include/net/flow_dissector.h22
-rw-r--r--include/net/flowcache.h2
-rw-r--r--include/net/gen_stats.h17
-rw-r--r--include/net/genetlink.h107
-rw-r--r--include/net/ieee80211_radiotap.h4
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--include/net/inet_connection_sock.h5
-rw-r--r--include/net/inet_sock.h1
-rw-r--r--include/net/ip.h6
-rw-r--r--include/net/ip6_route.h5
-rw-r--r--include/net/ip_fib.h8
-rw-r--r--include/net/ip_tunnels.h6
-rw-r--r--include/net/ipv6.h3
-rw-r--r--include/net/lwtunnel.h13
-rw-r--r--include/net/mac80211.h19
-rw-r--r--include/net/ndisc.h5
-rw-r--r--include/net/net_namespace.h2
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h9
-rw-r--r--include/net/netfilter/ipv4/nf_defrag_ipv4.h3
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_ipv6.h9
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h4
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h16
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h20
-rw-r--r--include/net/netfilter/nf_conntrack_synproxy.h2
-rw-r--r--include/net/netfilter/nf_dup_netdev.h1
-rw-r--r--include/net/netfilter/nf_log.h7
-rw-r--r--include/net/netfilter/nf_nat_l4proto.h9
-rw-r--r--include/net/netfilter/nf_queue.h1
-rw-r--r--include/net/netfilter/nf_socket.h27
-rw-r--r--include/net/netfilter/nf_tables.h137
-rw-r--r--include/net/netfilter/nf_tables_core.h34
-rw-r--r--include/net/netfilter/nft_fib.h31
-rw-r--r--include/net/netfilter/xt_rateest.h10
-rw-r--r--include/net/netlink.h15
-rw-r--r--include/net/netns/conntrack.h44
-rw-r--r--include/net/netns/generic.h16
-rw-r--r--include/net/netns/ipv4.h3
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--include/net/netns/netfilter.h6
-rw-r--r--include/net/pkt_cls.h21
-rw-r--r--include/net/pkt_sched.h2
-rw-r--r--include/net/raw.h6
-rw-r--r--include/net/rawv6.h7
-rw-r--r--include/net/route.h5
-rw-r--r--include/net/sch_generic.h2
-rw-r--r--include/net/sctp/sctp.h2
-rw-r--r--include/net/sctp/structs.h7
-rw-r--r--include/net/secure_seq.h8
-rw-r--r--include/net/seg6.h62
-rw-r--r--include/net/seg6_hmac.h62
-rw-r--r--include/net/sock.h126
-rw-r--r--include/net/tc_act/tc_mirred.h6
-rw-r--r--include/net/tc_act/tc_skbedit.h1
-rw-r--r--include/net/tc_act/tc_tunnel_key.h37
-rw-r--r--include/net/tcp.h23
-rw-r--r--include/net/udp.h20
-rw-r--r--include/net/udplite.h1
-rw-r--r--include/net/vxlan.h10
-rw-r--r--include/scsi/scsi_device.h4
-rw-r--r--include/scsi/scsi_proto.h17
-rw-r--r--include/sound/hda_i915.h11
-rw-r--r--include/trace/events/alarmtimer.h96
-rw-r--r--include/trace/events/bcache.h12
-rw-r--r--include/trace/events/block.h31
-rw-r--r--include/trace/events/dma_fence.h (renamed from include/trace/events/fence.h)44
-rw-r--r--include/trace/events/f2fs.h12
-rw-r--r--include/trace/events/mdio.h42
-rw-r--r--include/trace/events/rcu.h5
-rw-r--r--include/trace/events/wbt.h153
-rw-r--r--include/uapi/asm-generic/socket.h2
-rw-r--r--include/uapi/drm/amdgpu_drm.h92
-rw-r--r--include/uapi/drm/drm_mode.h59
-rw-r--r--include/uapi/drm/i915_drm.h5
-rw-r--r--include/uapi/drm/msm_drm.h25
-rw-r--r--include/uapi/drm/vc4_drm.h2
-rw-r--r--include/uapi/linux/Kbuild2
-rw-r--r--include/uapi/linux/blkzoned.h143
-rw-r--r--include/uapi/linux/bpf.h642
-rw-r--r--include/uapi/linux/devlink.h8
-rw-r--r--include/uapi/linux/ethtool.h18
-rw-r--r--include/uapi/linux/fib_rules.h6
-rw-r--r--include/uapi/linux/fs.h4
-rw-r--r--include/uapi/linux/genetlink.h3
-rw-r--r--include/uapi/linux/if_ether.h3
-rw-r--r--include/uapi/linux/if_link.h6
-rw-r--r--include/uapi/linux/if_pppol2tp.h13
-rw-r--r--include/uapi/linux/in.h1
-rw-r--r--include/uapi/linux/in6.h1
-rw-r--r--include/uapi/linux/inet_diag.h17
-rw-r--r--include/uapi/linux/ipv6.h4
-rw-r--r--include/uapi/linux/l2tp.h21
-rw-r--r--include/uapi/linux/lwtunnel.h24
-rw-r--r--include/uapi/linux/major.h2
-rw-r--r--include/uapi/linux/mmc/ioctl.h2
-rw-r--r--include/uapi/linux/nbd.h9
-rw-r--r--include/uapi/linux/net_tstamp.h3
-rw-r--r--include/uapi/linux/netfilter.h2
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_tuple_common.h3
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h133
-rw-r--r--include/uapi/linux/netfilter/xt_bpf.h21
-rw-r--r--include/uapi/linux/nl80211.h76
-rw-r--r--include/uapi/linux/openvswitch.h15
-rw-r--r--include/uapi/linux/pkt_cls.h28
-rw-r--r--include/uapi/linux/rtnetlink.h1
-rw-r--r--include/uapi/linux/seg6.h54
-rw-r--r--include/uapi/linux/seg6_genl.h32
-rw-r--r--include/uapi/linux/seg6_hmac.h21
-rw-r--r--include/uapi/linux/seg6_iptunnel.h44
-rw-r--r--include/uapi/linux/sockios.h3
-rw-r--r--include/uapi/linux/tc_act/tc_bpf.h1
-rw-r--r--include/uapi/linux/tc_act/tc_skbedit.h2
-rw-r--r--include/uapi/linux/tc_act/tc_tunnel_key.h1
-rw-r--r--include/uapi/linux/tcp.h12
-rw-r--r--include/uapi/linux/uleds.h24
-rw-r--r--include/uapi/linux/vfio.h10
-rw-r--r--include/uapi/scsi/fc/fc_fs.h2
-rw-r--r--include/video/display_timing.h4
-rw-r--r--include/video/imx-ipu-v3.h3
-rw-r--r--include/video/of_display_timing.h15
-rw-r--r--init/Kconfig31
-rw-r--r--init/do_mounts.c2
-rw-r--r--init/main.c5
-rw-r--r--ipc/mqueue.c4
-rw-r--r--ipc/msg.c8
-rw-r--r--kernel/Kconfig.locks2
-rw-r--r--kernel/audit.c5
-rw-r--r--kernel/bpf/Makefile3
-rw-r--r--kernel/bpf/bpf_lru_list.c695
-rw-r--r--kernel/bpf/bpf_lru_list.h84
-rw-r--r--kernel/bpf/cgroup.c200
-rw-r--r--kernel/bpf/core.c68
-rw-r--r--kernel/bpf/hashtab.c438
-rw-r--r--kernel/bpf/helpers.c12
-rw-r--r--kernel/bpf/inode.c99
-rw-r--r--kernel/bpf/syscall.c182
-rw-r--r--kernel/bpf/verifier.c130
-rw-r--r--kernel/cgroup.c18
-rw-r--r--kernel/compat.c8
-rw-r--r--kernel/cpu.c2
-rw-r--r--kernel/debug/kdb/kdb_io.c2
-rw-r--r--kernel/events/core.c2
-rw-r--r--kernel/exit.c15
-rw-r--r--kernel/fork.c10
-rw-r--r--kernel/futex.c8
-rw-r--r--kernel/hung_task.c3
-rw-r--r--kernel/irq/affinity.c72
-rw-r--r--kernel/irq/msi.c4
-rw-r--r--kernel/kthread.c149
-rw-r--r--kernel/locking/lockdep.c10
-rw-r--r--kernel/locking/mcs_spinlock.h4
-rw-r--r--kernel/locking/mutex-debug.c13
-rw-r--r--kernel/locking/mutex-debug.h10
-rw-r--r--kernel/locking/mutex.c588
-rw-r--r--kernel/locking/mutex.h26
-rw-r--r--kernel/locking/osq_lock.c15
-rw-r--r--kernel/locking/qrwlock.c6
-rw-r--r--kernel/locking/rtmutex.c18
-rw-r--r--kernel/locking/rtmutex_common.h3
-rw-r--r--kernel/locking/rwsem-xadd.c28
-rw-r--r--kernel/power/main.c88
-rw-r--r--kernel/power/power.h6
-rw-r--r--kernel/power/suspend.c69
-rw-r--r--kernel/power/swap.c19
-rw-r--r--kernel/printk/nmi.c83
-rw-r--r--kernel/printk/printk.c25
-rw-r--r--kernel/rcu/rcutorture.c11
-rw-r--r--kernel/rcu/tree.c17
-rw-r--r--kernel/rcu/tree.h1
-rw-r--r--kernel/rcu/tree_exp.h12
-rw-r--r--kernel/sched/core.c37
-rw-r--r--kernel/sched/cpuacct.c2
-rw-r--r--kernel/sched/cpufreq_schedutil.c119
-rw-r--r--kernel/sched/cputime.c124
-rw-r--r--kernel/sched/deadline.c4
-rw-r--r--kernel/sched/fair.c665
-rw-r--r--kernel/sched/idle.c175
-rw-r--r--kernel/sched/sched.h11
-rw-r--r--kernel/seccomp.c2
-rw-r--r--kernel/signal.c6
-rw-r--r--kernel/smp.c18
-rw-r--r--kernel/stop_machine.c2
-rw-r--r--kernel/sys.c13
-rw-r--r--kernel/sysctl.c14
-rw-r--r--kernel/taskstats.c18
-rw-r--r--kernel/time/Makefile10
-rw-r--r--kernel/time/alarmtimer.c59
-rw-r--r--kernel/time/clocksource.c1
-rw-r--r--kernel/time/hrtimer.c20
-rw-r--r--kernel/time/itimer.c15
-rw-r--r--kernel/time/posix-cpu-timers.c8
-rw-r--r--kernel/time/posix-stubs.c123
-rw-r--r--kernel/time/tick-sched.c33
-rw-r--r--kernel/time/timekeeping.c90
-rw-r--r--kernel/time/timer.c48
-rw-r--r--kernel/trace/blktrace.c14
-rw-r--r--kernel/trace/bpf_trace.c2
-rw-r--r--kernel/trace/ftrace.c17
-rw-r--r--kernel/trace/ring_buffer.c137
-rw-r--r--kernel/trace/trace.c16
-rw-r--r--lib/Kconfig.debug38
-rw-r--r--lib/idr.c11
-rw-r--r--lib/iov_iter.c1
-rw-r--r--lib/list_debug.c99
-rw-r--r--lib/lockref.c2
-rw-r--r--lib/nlattr.c2
-rw-r--r--lib/parser.c47
-rw-r--r--lib/percpu_counter.c25
-rw-r--r--lib/radix-tree.c322
-rw-r--r--lib/rbtree.c23
-rw-r--r--mm/Kconfig8
-rw-r--r--mm/backing-dev.c1
-rw-r--r--mm/compaction.c56
-rw-r--r--mm/debug.c4
-rw-r--r--mm/filemap.c68
-rw-r--r--mm/gup.c19
-rw-r--r--mm/huge_memory.c58
-rw-r--r--mm/hugetlb.c25
-rw-r--r--mm/kasan/kasan.c9
-rw-r--r--mm/kasan/quarantine.c94
-rw-r--r--mm/kasan/report.c2
-rw-r--r--mm/khugepaged.c37
-rw-r--r--mm/kmemleak.c2
-rw-r--r--mm/madvise.c1
-rw-r--r--mm/memcontrol.c39
-rw-r--r--mm/memory.c100
-rw-r--r--mm/memory_hotplug.c20
-rw-r--r--mm/mempolicy.c30
-rw-r--r--mm/migrate.c19
-rw-r--r--mm/mprotect.c19
-rw-r--r--mm/page-writeback.c1
-rw-r--r--mm/page_alloc.c128
-rw-r--r--mm/page_io.c5
-rw-r--r--mm/percpu.c16
-rw-r--r--mm/readahead.c39
-rw-r--r--mm/rmap.c69
-rw-r--r--mm/shmem.c15
-rw-r--r--mm/slab.c129
-rw-r--r--mm/slab.h20
-rw-r--r--mm/slab_common.c33
-rw-r--r--mm/slob.c2
-rw-r--r--mm/slub.c21
-rw-r--r--mm/swapfile.c13
-rw-r--r--mm/truncate.c21
-rw-r--r--mm/vmalloc.c196
-rw-r--r--mm/vmscan.c42
-rw-r--r--mm/vmstat.c95
-rw-r--r--mm/workingset.c114
-rw-r--r--mm/zsmalloc.c67
-rw-r--r--mm/zswap.c172
-rw-r--r--net/802/fddi.c11
-rw-r--r--net/802/hippi.c14
-rw-r--r--net/8021q/vlan.c9
-rw-r--r--net/8021q/vlan.h2
-rw-r--r--net/8021q/vlan_dev.c3
-rw-r--r--net/Kconfig8
-rw-r--r--net/atm/br2684.c6
-rw-r--r--net/atm/lec.c11
-rw-r--r--net/batman-adv/Kconfig2
-rw-r--r--net/batman-adv/bat_iv_ogm.c58
-rw-r--r--net/batman-adv/bat_v.c8
-rw-r--r--net/batman-adv/bat_v_elp.c71
-rw-r--r--net/batman-adv/bat_v_ogm.c75
-rw-r--r--net/batman-adv/debugfs.c26
-rw-r--r--net/batman-adv/distributed-arp-table.c84
-rw-r--r--net/batman-adv/fragmentation.c82
-rw-r--r--net/batman-adv/fragmentation.h2
-rw-r--r--net/batman-adv/gateway_client.c9
-rw-r--r--net/batman-adv/hard-interface.c225
-rw-r--r--net/batman-adv/hard-interface.h21
-rw-r--r--net/batman-adv/hash.h30
-rw-r--r--net/batman-adv/icmp_socket.c5
-rw-r--r--net/batman-adv/log.c4
-rw-r--r--net/batman-adv/log.h12
-rw-r--r--net/batman-adv/main.c16
-rw-r--r--net/batman-adv/main.h28
-rw-r--r--net/batman-adv/multicast.c70
-rw-r--r--net/batman-adv/multicast.h6
-rw-r--r--net/batman-adv/netlink.c31
-rw-r--r--net/batman-adv/network-coding.c43
-rw-r--r--net/batman-adv/originator.c23
-rw-r--r--net/batman-adv/packet.h12
-rw-r--r--net/batman-adv/routing.c180
-rw-r--r--net/batman-adv/send.c419
-rw-r--r--net/batman-adv/send.h11
-rw-r--r--net/batman-adv/soft-interface.c27
-rw-r--r--net/batman-adv/sysfs.c53
-rw-r--r--net/batman-adv/tp_meter.c6
-rw-r--r--net/batman-adv/translation-table.c39
-rw-r--r--net/batman-adv/tvlv.c5
-rw-r--r--net/batman-adv/types.h45
-rw-r--r--net/bluetooth/bnep/netdev.c3
-rw-r--r--net/bluetooth/smp.c85
-rw-r--r--net/bluetooth/smp.h1
-rw-r--r--net/bridge/br_device.c5
-rw-r--r--net/bridge/br_fdb.c10
-rw-r--r--net/bridge/br_multicast.c188
-rw-r--r--net/bridge/br_netfilter_hooks.c26
-rw-r--r--net/bridge/br_netlink.c34
-rw-r--r--net/bridge/br_private.h11
-rw-r--r--net/bridge/br_private_stp.h1
-rw-r--r--net/bridge/br_stp.c65
-rw-r--r--net/bridge/br_stp_if.c14
-rw-r--r--net/bridge/br_stp_timer.c2
-rw-r--r--net/bridge/br_sysfs_br.c40
-rw-r--r--net/bridge/netfilter/Kconfig1
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c3
-rw-r--r--net/bridge/netfilter/ebt_log.c11
-rw-r--r--net/bridge/netfilter/ebt_nflog.c6
-rw-r--r--net/bridge/netfilter/ebt_redirect.c6
-rw-r--r--net/bridge/netfilter/ebtable_broute.c2
-rw-r--r--net/bridge/netfilter/ebtables.c6
-rw-r--r--net/bridge/netfilter/nf_log_bridge.c17
-rw-r--r--net/bridge/netfilter/nft_meta_bridge.c2
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c30
-rw-r--r--net/caif/caif_dev.c2
-rw-r--r--net/caif/cfcnfg.c9
-rw-r--r--net/core/Makefile1
-rw-r--r--net/core/datagram.c72
-rw-r--r--net/core/dev.c886
-rw-r--r--net/core/devlink.c100
-rw-r--r--net/core/drop_monitor.c21
-rw-r--r--net/core/ethtool.c97
-rw-r--r--net/core/fib_rules.c78
-rw-r--r--net/core/filter.c336
-rw-r--r--net/core/flow.c60
-rw-r--r--net/core/flow_dissector.c33
-rw-r--r--net/core/gen_estimator.c294
-rw-r--r--net/core/gen_stats.c20
-rw-r--r--net/core/lwt_bpf.c396
-rw-r--r--net/core/lwtunnel.c17
-rw-r--r--net/core/neighbour.c15
-rw-r--r--net/core/net-sysfs.c65
-rw-r--r--net/core/net_namespace.c42
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/core/rtnetlink.c20
-rw-r--r--net/core/secure_seq.c11
-rw-r--r--net/core/skbuff.c70
-rw-r--r--net/core/sock.c84
-rw-r--r--net/core/stream.c28
-rw-r--r--net/core/sysctl_net_core.c5
-rw-r--r--net/dccp/ipv4.c8
-rw-r--r--net/dccp/ipv6.c2
-rw-r--r--net/decnet/af_decnet.c16
-rw-r--r--net/dsa/slave.c16
-rw-r--r--net/ethernet/eth.c8
-rw-r--r--net/hsr/hsr_device.c1
-rw-r--r--net/hsr/hsr_netlink.c23
-rw-r--r--net/ieee802154/netlink.c24
-rw-r--r--net/ieee802154/nl-phy.c6
-rw-r--r--net/ieee802154/nl802154.c44
-rw-r--r--net/ipv4/Kconfig8
-rw-r--r--net/ipv4/Makefile1
-rw-r--r--net/ipv4/af_inet.c12
-rw-r--r--net/ipv4/fib_frontend.c3
-rw-r--r--net/ipv4/fib_semantics.c1
-rw-r--r--net/ipv4/fib_trie.c155
-rw-r--r--net/ipv4/fou.c23
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/inet_connection_sock.c4
-rw-r--r--net/ipv4/inet_diag.c73
-rw-r--r--net/ipv4/ip_gre.c4
-rw-r--r--net/ipv4/ip_output.c31
-rw-r--r--net/ipv4/ip_sockglue.c32
-rw-r--r--net/ipv4/ip_tunnel.c10
-rw-r--r--net/ipv4/ip_vti.c2
-rw-r--r--net/ipv4/ipip.c2
-rw-r--r--net/ipv4/ipmr.c15
-rw-r--r--net/ipv4/netfilter/Kconfig14
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/arp_tables.c42
-rw-r--r--net/ipv4/netfilter/ip_tables.c42
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c6
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c11
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c4
-rw-r--r--net/ipv4/netfilter/ipt_SYNPROXY.c8
-rw-r--r--net/ipv4/netfilter/ipt_rpfilter.c10
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c145
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c41
-rw-r--r--net/ipv4/netfilter/nf_socket_ipv4.c163
-rw-r--r--net/ipv4/netfilter/nft_dup_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nft_fib_ipv4.c241
-rw-r--r--net/ipv4/netfilter/nft_masq_ipv4.c15
-rw-r--r--net/ipv4/netfilter/nft_redir_ipv4.c14
-rw-r--r--net/ipv4/netfilter/nft_reject_ipv4.c4
-rw-r--r--net/ipv4/ping.c3
-rw-r--r--net/ipv4/raw.c33
-rw-r--r--net/ipv4/raw_diag.c266
-rw-r--r--net/ipv4/route.c116
-rw-r--r--net/ipv4/syncookies.c3
-rw-r--r--net/ipv4/tcp.c116
-rw-r--r--net/ipv4/tcp_bbr.c32
-rw-r--r--net/ipv4/tcp_cong.c14
-rw-r--r--net/ipv4/tcp_dctcp.c1
-rw-r--r--net/ipv4/tcp_highspeed.c11
-rw-r--r--net/ipv4/tcp_hybla.c1
-rw-r--r--net/ipv4/tcp_illinois.c10
-rw-r--r--net/ipv4/tcp_input.c33
-rw-r--r--net/ipv4/tcp_ipv4.c26
-rw-r--r--net/ipv4/tcp_lp.c1
-rw-r--r--net/ipv4/tcp_metrics.c23
-rw-r--r--net/ipv4/tcp_minisocks.c4
-rw-r--r--net/ipv4/tcp_output.c185
-rw-r--r--net/ipv4/tcp_scalable.c15
-rw-r--r--net/ipv4/tcp_timer.c4
-rw-r--r--net/ipv4/tcp_vegas.c1
-rw-r--r--net/ipv4/tcp_veno.c10
-rw-r--r--net/ipv4/tcp_westwood.c1
-rw-r--r--net/ipv4/tcp_yeah.c10
-rw-r--r--net/ipv4/udp.c254
-rw-r--r--net/ipv4/udplite.c3
-rw-r--r--net/ipv6/Kconfig35
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/addrconf.c50
-rw-r--r--net/ipv6/af_inet6.c18
-rw-r--r--net/ipv6/ah6.c5
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/esp6.c5
-rw-r--r--net/ipv6/exthdrs.c268
-rw-r--r--net/ipv6/icmp.c7
-rw-r--r--net/ipv6/ila/ila_lwt.c92
-rw-r--r--net/ipv6/ila/ila_xlat.c43
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/ip6_gre.c6
-rw-r--r--net/ipv6/ip6_output.c16
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/ip6_vti.c28
-rw-r--r--net/ipv6/ip6mr.c2
-rw-r--r--net/ipv6/ipcomp6.c5
-rw-r--r--net/ipv6/ipv6_sockglue.c18
-rw-r--r--net/ipv6/ndisc.c29
-rw-r--r--net/ipv6/netfilter.c1
-rw-r--r--net/ipv6/netfilter/Kconfig14
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6_tables.c43
-rw-r--r--net/ipv6/netfilter/ip6t_MASQUERADE.c2
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c23
-rw-r--r--net/ipv6/netfilter/ip6t_SYNPROXY.c8
-rw-r--r--net/ipv6/netfilter/ip6t_rpfilter.c3
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c146
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c42
-rw-r--r--net/ipv6/netfilter/nf_socket_ipv6.c151
-rw-r--r--net/ipv6/netfilter/nft_dup_ipv6.c2
-rw-r--r--net/ipv6/netfilter/nft_fib_ipv6.c275
-rw-r--r--net/ipv6/netfilter/nft_masq_ipv6.c14
-rw-r--r--net/ipv6/netfilter/nft_redir_ipv6.c14
-rw-r--r--net/ipv6/netfilter/nft_reject_ipv6.c6
-rw-r--r--net/ipv6/ping.c1
-rw-r--r--net/ipv6/raw.c8
-rw-r--r--net/ipv6/reassembly.c7
-rw-r--r--net/ipv6/route.c27
-rw-r--r--net/ipv6/seg6.c495
-rw-r--r--net/ipv6/seg6_hmac.c484
-rw-r--r--net/ipv6/seg6_iptunnel.c431
-rw-r--r--net/ipv6/sit.c16
-rw-r--r--net/ipv6/syncookies.c2
-rw-r--r--net/ipv6/tcp_ipv6.c14
-rw-r--r--net/ipv6/udp.c48
-rw-r--r--net/ipv6/udplite.c3
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/irda/irlan/irlan_eth.c4
-rw-r--r--net/irda/irnetlink.c22
-rw-r--r--net/iucv/af_iucv.c34
-rw-r--r--net/iucv/iucv.c124
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/l2tp/l2tp_core.c2
-rw-r--r--net/l2tp/l2tp_core.h10
-rw-r--r--net/l2tp/l2tp_eth.c2
-rw-r--r--net/l2tp/l2tp_ip6.c1
-rw-r--r--net/l2tp/l2tp_netlink.c59
-rw-r--r--net/l2tp/l2tp_ppp.c60
-rw-r--r--net/llc/af_llc.c24
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/aes_cmac.c8
-rw-r--r--net/mac80211/aes_cmac.h4
-rw-r--r--net/mac80211/agg-rx.c8
-rw-r--r--net/mac80211/cfg.c35
-rw-r--r--net/mac80211/debugfs.c1
-rw-r--r--net/mac80211/debugfs_netdev.c11
-rw-r--r--net/mac80211/debugfs_sta.c9
-rw-r--r--net/mac80211/fils_aead.c342
-rw-r--r--net/mac80211/fils_aead.h19
-rw-r--r--net/mac80211/ieee80211_i.h26
-rw-r--r--net/mac80211/iface.c31
-rw-r--r--net/mac80211/main.c5
-rw-r--r--net/mac80211/mlme.c81
-rw-r--r--net/mac80211/rx.c11
-rw-r--r--net/mac80211/sta_info.c23
-rw-r--r--net/mac80211/sta_info.h4
-rw-r--r--net/mac80211/tx.c55
-rw-r--r--net/mac80211/util.c61
-rw-r--r--net/mac80211/wme.c23
-rw-r--r--net/mac80211/wpa.c2
-rw-r--r--net/mpls/mpls_iptunnel.c5
-rw-r--r--net/netfilter/Kconfig56
-rw-r--r--net/netfilter/Makefile24
-rw-r--r--net/netfilter/core.c100
-rw-r--r--net/netfilter/ipset/Kconfig9
-rw-r--r--net/netfilter/ipset/Makefile1
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_gen.h31
-rw-r--r--net/netfilter/ipset/ip_set_core.c22
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h254
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipmac.c315
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipmark.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c8
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_netnet.c8
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_netportnet.c10
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c37
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c25
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c54
-rw-r--r--net/netfilter/nf_conntrack_core.c19
-rw-r--r--net/netfilter/nf_conntrack_proto.c158
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c101
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c13
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c100
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c103
-rw-r--r--net/netfilter/nf_conntrack_standalone.c10
-rw-r--r--net/netfilter/nf_dup_netdev.c35
-rw-r--r--net/netfilter/nf_internals.h5
-rw-r--r--net/netfilter/nf_log_common.c28
-rw-r--r--net/netfilter/nf_log_netdev.c81
-rw-r--r--net/netfilter/nf_nat_core.c12
-rw-r--r--net/netfilter/nf_nat_proto_dccp.c36
-rw-r--r--net/netfilter/nf_nat_proto_sctp.c40
-rw-r--r--net/netfilter/nf_nat_proto_udplite.c35
-rw-r--r--net/netfilter/nf_queue.c36
-rw-r--r--net/netfilter/nf_synproxy_core.c2
-rw-r--r--net/netfilter/nf_tables_api.c718
-rw-r--r--net/netfilter/nf_tables_core.c91
-rw-r--r--net/netfilter/nf_tables_trace.c8
-rw-r--r--net/netfilter/nfnetlink_log.c5
-rw-r--r--net/netfilter/nfnetlink_queue.c6
-rw-r--r--net/netfilter/nft_bitwise.c13
-rw-r--r--net/netfilter/nft_byteorder.c13
-rw-r--r--net/netfilter/nft_cmp.c16
-rw-r--r--net/netfilter/nft_counter.c223
-rw-r--r--net/netfilter/nft_ct.c76
-rw-r--r--net/netfilter/nft_dynset.c13
-rw-r--r--net/netfilter/nft_fib.c159
-rw-r--r--net/netfilter/nft_fib_inet.c82
-rw-r--r--net/netfilter/nft_fwd_netdev.c4
-rw-r--r--net/netfilter/nft_hash.c6
-rw-r--r--net/netfilter/nft_immediate.c16
-rw-r--r--net/netfilter/nft_log.c5
-rw-r--r--net/netfilter/nft_lookup.c18
-rw-r--r--net/netfilter/nft_masq.c6
-rw-r--r--net/netfilter/nft_meta.c11
-rw-r--r--net/netfilter/nft_nat.c11
-rw-r--r--net/netfilter/nft_numgen.c2
-rw-r--r--net/netfilter/nft_objref.c226
-rw-r--r--net/netfilter/nft_payload.c120
-rw-r--r--net/netfilter/nft_queue.c2
-rw-r--r--net/netfilter/nft_quota.c158
-rw-r--r--net/netfilter/nft_range.c13
-rw-r--r--net/netfilter/nft_redir.c6
-rw-r--r--net/netfilter/nft_reject_inet.c18
-rw-r--r--net/netfilter/nft_rt.c153
-rw-r--r--net/netfilter/nft_set_hash.c25
-rw-r--r--net/netfilter/nft_set_rbtree.c12
-rw-r--r--net/netfilter/x_tables.c60
-rw-r--r--net/netfilter/xt_AUDIT.c10
-rw-r--r--net/netfilter/xt_CONNSECMARK.c4
-rw-r--r--net/netfilter/xt_CT.c6
-rw-r--r--net/netfilter/xt_LOG.c6
-rw-r--r--net/netfilter/xt_NETMAP.c31
-rw-r--r--net/netfilter/xt_NFLOG.c6
-rw-r--r--net/netfilter/xt_NFQUEUE.c4
-rw-r--r--net/netfilter/xt_RATEEST.c4
-rw-r--r--net/netfilter/xt_REDIRECT.c16
-rw-r--r--net/netfilter/xt_TCPMSS.c4
-rw-r--r--net/netfilter/xt_TEE.c4
-rw-r--r--net/netfilter/xt_TPROXY.c31
-rw-r--r--net/netfilter/xt_addrtype.c10
-rw-r--r--net/netfilter/xt_bpf.c96
-rw-r--r--net/netfilter/xt_cluster.c2
-rw-r--r--net/netfilter/xt_connbytes.c4
-rw-r--r--net/netfilter/xt_connlabel.c6
-rw-r--r--net/netfilter/xt_connlimit.c14
-rw-r--r--net/netfilter/xt_connmark.c8
-rw-r--r--net/netfilter/xt_conntrack.c12
-rw-r--r--net/netfilter/xt_devgroup.c4
-rw-r--r--net/netfilter/xt_dscp.c2
-rw-r--r--net/netfilter/xt_hashlimit.c2
-rw-r--r--net/netfilter/xt_helper.c4
-rw-r--r--net/netfilter/xt_ipvs.c4
-rw-r--r--net/netfilter/xt_multiport.c52
-rw-r--r--net/netfilter/xt_nat.c18
-rw-r--r--net/netfilter/xt_nfacct.c2
-rw-r--r--net/netfilter/xt_osf.c10
-rw-r--r--net/netfilter/xt_owner.c2
-rw-r--r--net/netfilter/xt_pkttype.c4
-rw-r--r--net/netfilter/xt_policy.c4
-rw-r--r--net/netfilter/xt_rateest.c28
-rw-r--r--net/netfilter/xt_recent.c12
-rw-r--r--net/netfilter/xt_set.c38
-rw-r--r--net/netfilter/xt_socket.c336
-rw-r--r--net/netfilter/xt_state.c4
-rw-r--r--net/netlabel/netlabel_calipso.c21
-rw-r--r--net/netlabel/netlabel_cipso_v4.c22
-rw-r--r--net/netlabel/netlabel_mgmt.c21
-rw-r--r--net/netlabel/netlabel_unlabeled.c21
-rw-r--r--net/netlink/af_netlink.c8
-rw-r--r--net/netlink/genetlink.c323
-rw-r--r--net/nfc/netlink.c34
-rw-r--r--net/openvswitch/actions.c129
-rw-r--r--net/openvswitch/conntrack.c8
-rw-r--r--net/openvswitch/datapath.c35
-rw-r--r--net/openvswitch/datapath.h2
-rw-r--r--net/openvswitch/flow.c105
-rw-r--r--net/openvswitch/flow.h22
-rw-r--r--net/openvswitch/flow_netlink.c179
-rw-r--r--net/openvswitch/vport-internal_dev.c10
-rw-r--r--net/openvswitch/vport-netdev.c10
-rw-r--r--net/openvswitch/vport.c48
-rw-r--r--net/openvswitch/vport.h3
-rw-r--r--net/packet/af_packet.c69
-rw-r--r--net/phonet/pep-gprs.c12
-rw-r--r--net/phonet/pep.c9
-rw-r--r--net/phonet/pn_dev.c2
-rw-r--r--net/rds/af_rds.c4
-rw-r--r--net/rds/connection.c18
-rw-r--r--net/rds/message.c1
-rw-r--r--net/rds/rds.h12
-rw-r--r--net/rds/recv.c36
-rw-r--r--net/rds/send.c9
-rw-r--r--net/rds/tcp.c22
-rw-r--r--net/rds/tcp_connect.c14
-rw-r--r--net/rds/tcp_listen.c31
-rw-r--r--net/rds/tcp_send.c3
-rw-r--r--net/rds/threads.c3
-rw-r--r--net/rxrpc/input.c7
-rw-r--r--net/sched/act_api.c9
-rw-r--r--net/sched/act_bpf.c20
-rw-r--r--net/sched/act_connmark.c2
-rw-r--r--net/sched/act_csum.c2
-rw-r--r--net/sched/act_gact.c2
-rw-r--r--net/sched/act_ife.c2
-rw-r--r--net/sched/act_ipt.c16
-rw-r--r--net/sched/act_mirred.c85
-rw-r--r--net/sched/act_nat.c2
-rw-r--r--net/sched/act_pedit.c2
-rw-r--r--net/sched/act_police.c23
-rw-r--r--net/sched/act_simple.c2
-rw-r--r--net/sched/act_skbedit.c23
-rw-r--r--net/sched/act_skbmod.c2
-rw-r--r--net/sched/act_tunnel_key.c17
-rw-r--r--net/sched/act_vlan.c2
-rw-r--r--net/sched/cls_api.c24
-rw-r--r--net/sched/cls_bpf.c49
-rw-r--r--net/sched/cls_flower.c296
-rw-r--r--net/sched/em_ipset.c17
-rw-r--r--net/sched/em_meta.c9
-rw-r--r--net/sched/sch_api.c13
-rw-r--r--net/sched/sch_cbq.c6
-rw-r--r--net/sched/sch_drr.c6
-rw-r--r--net/sched/sch_fq.c4
-rw-r--r--net/sched/sch_generic.c2
-rw-r--r--net/sched/sch_hfsc.c6
-rw-r--r--net/sched/sch_htb.c6
-rw-r--r--net/sched/sch_qfq.c8
-rw-r--r--net/sched/sch_teql.c5
-rw-r--r--net/sctp/associola.c8
-rw-r--r--net/sctp/chunk.c32
-rw-r--r--net/sctp/input.c93
-rw-r--r--net/sctp/output.c441
-rw-r--r--net/sctp/outqueue.c4
-rw-r--r--net/sctp/socket.c7
-rw-r--r--net/socket.c36
-rw-r--r--net/sunrpc/netns.h2
-rw-r--r--net/sunrpc/sunrpc_syms.c2
-rw-r--r--net/sunrpc/svcsock.c22
-rw-r--r--net/sunrpc/xprtsock.c4
-rw-r--r--net/switchdev/switchdev.c5
-rw-r--r--net/tipc/core.c2
-rw-r--r--net/tipc/core.h2
-rw-r--r--net/tipc/msg.h2
-rw-r--r--net/tipc/netlink.c27
-rw-r--r--net/tipc/netlink_compat.c25
-rw-r--r--net/tipc/socket.c498
-rw-r--r--net/unix/af_unix.c4
-rw-r--r--net/vmw_vsock/virtio_transport.c56
-rw-r--r--net/vmw_vsock/virtio_transport_common.c10
-rw-r--r--net/wimax/stack.c22
-rw-r--r--net/wireless/core.c33
-rw-r--r--net/wireless/core.h5
-rw-r--r--net/wireless/lib80211_crypt_tkip.c2
-rw-r--r--net/wireless/mesh.c2
-rw-r--r--net/wireless/mlme.c18
-rw-r--r--net/wireless/nl80211.c551
-rw-r--r--net/wireless/rdev-ops.h24
-rw-r--r--net/wireless/sme.c16
-rw-r--r--net/wireless/trace.h37
-rw-r--r--net/wireless/util.c125
-rw-r--r--net/xfrm/xfrm_policy.c1
-rw-r--r--net/xfrm/xfrm_state.c8
-rw-r--r--samples/bpf/Makefile28
-rw-r--r--samples/bpf/bpf_helpers.h6
-rw-r--r--samples/bpf/bpf_load.c112
-rw-r--r--samples/bpf/bpf_load.h2
-rw-r--r--samples/bpf/cgroup_helpers.c177
-rw-r--r--samples/bpf/cgroup_helpers.h16
-rw-r--r--samples/bpf/libbpf.c21
-rw-r--r--samples/bpf/libbpf.h5
-rw-r--r--samples/bpf/lwt_len_hist.sh37
-rw-r--r--samples/bpf/lwt_len_hist_kern.c82
-rw-r--r--samples/bpf/lwt_len_hist_user.c76
-rw-r--r--samples/bpf/map_perf_test_kern.c39
-rw-r--r--samples/bpf/map_perf_test_user.c32
-rw-r--r--samples/bpf/sock_flags_kern.c44
-rw-r--r--samples/bpf/sockex2_kern.c2
-rw-r--r--samples/bpf/test_cgrp2_attach.c167
-rw-r--r--samples/bpf/test_cgrp2_attach2.c132
-rw-r--r--samples/bpf/test_cgrp2_sock.c83
-rwxr-xr-xsamples/bpf/test_cgrp2_sock.sh47
-rw-r--r--samples/bpf/test_cgrp2_sock2.c66
-rwxr-xr-xsamples/bpf/test_cgrp2_sock2.sh81
-rw-r--r--samples/bpf/test_current_task_under_cgroup_user.c108
-rw-r--r--samples/bpf/test_lru_dist.c541
-rw-r--r--samples/bpf/test_lwt_bpf.c253
-rw-r--r--samples/bpf/test_lwt_bpf.sh399
-rw-r--r--samples/bpf/test_maps.c503
-rw-r--r--samples/bpf/tracex2_user.c4
-rw-r--r--samples/bpf/tracex3_user.c6
-rw-r--r--samples/bpf/xdp1_user.c97
-rw-r--r--samples/bpf/xdp_tx_iptunnel_common.h37
-rw-r--r--samples/bpf/xdp_tx_iptunnel_kern.c236
-rw-r--r--samples/bpf/xdp_tx_iptunnel_user.c256
-rw-r--r--samples/vfio-mdev/Makefile13
-rw-r--r--samples/vfio-mdev/mtty.c1503
-rw-r--r--scripts/Makefile.kasan2
-rwxr-xr-xscripts/bloat-o-meter25
-rwxr-xr-xscripts/check_00index.sh66
-rwxr-xr-xscripts/checkpatch.pl62
-rwxr-xr-xscripts/decode_stacktrace.sh3
-rwxr-xr-xscripts/faddr2line33
-rwxr-xr-xscripts/get_maintainer.pl12
-rw-r--r--scripts/kconfig/expr.h2
-rw-r--r--scripts/kconfig/menu.c55
-rw-r--r--scripts/kconfig/symbol.c24
-rw-r--r--scripts/kconfig/zconf.gperf1
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped30
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped1581
-rw-r--r--scripts/kconfig/zconf.y16
-rwxr-xr-xscripts/kernel-doc20
-rw-r--r--[-rwxr-xr-x]scripts/sign-file.c0
-rwxr-xr-xscripts/tags.sh19
-rw-r--r--security/selinux/hooks.c11
-rw-r--r--sound/core/misc.c20
-rw-r--r--sound/hda/hdac_i915.c18
-rw-r--r--sound/pci/hda/patch_hdmi.c7
-rw-r--r--sound/soc/codecs/hdac_hdmi.c2
-rw-r--r--tools/Makefile7
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h1
-rw-r--r--tools/build/Build.include22
-rw-r--r--tools/build/Documentation/Build.txt6
-rw-r--r--tools/build/Makefile.feature138
-rw-r--r--tools/build/feature/Makefile126
-rw-r--r--tools/build/feature/test-clang.cpp21
-rw-r--r--tools/build/feature/test-jvmti.c13
-rw-r--r--tools/build/feature/test-llvm-version.cpp11
-rw-r--r--tools/build/feature/test-llvm.cpp13
-rw-r--r--tools/build/fixdep.c5
-rw-r--r--tools/gpio/gpio-hammer.c67
-rw-r--r--tools/gpio/gpio-utils.c256
-rw-r--r--tools/gpio/gpio-utils.h16
-rwxr-xr-xtools/hv/bondvf.sh4
-rw-r--r--tools/include/asm-generic/bitops.h1
-rw-r--r--tools/include/asm-generic/bitops/__ffz.h12
-rw-r--r--tools/include/asm-generic/bitops/find.h28
-rw-r--r--tools/include/linux/bitops.h5
-rw-r--r--tools/include/linux/filter.h24
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h5
-rw-r--r--tools/leds/.gitignore1
-rw-r--r--tools/leds/Makefile13
-rw-r--r--tools/leds/uledmon.c63
-rw-r--r--tools/lib/bpf/bpf.c56
-rw-r--r--tools/lib/bpf/bpf.h7
-rw-r--r--tools/lib/bpf/libbpf.c177
-rw-r--r--tools/lib/bpf/libbpf.h13
-rw-r--r--tools/lib/find_bit.c25
-rw-r--r--tools/lib/subcmd/parse-options.c14
-rw-r--r--tools/lib/subcmd/parse-options.h2
-rw-r--r--tools/lib/traceevent/Makefile40
-rw-r--r--tools/lib/traceevent/event-parse.c41
-rw-r--r--tools/lib/traceevent/event-parse.h5
-rw-r--r--tools/perf/Build1
-rw-r--r--tools/perf/Documentation/intel-pt.txt19
-rw-r--r--tools/perf/Documentation/jitdump-specification.txt170
-rw-r--r--tools/perf/Documentation/perf-c2c.txt290
-rw-r--r--tools/perf/Documentation/perf-config.txt35
-rw-r--r--tools/perf/Documentation/perf-kmem.txt7
-rw-r--r--tools/perf/Documentation/perf-record.txt9
-rw-r--r--tools/perf/Documentation/perf-report.txt10
-rw-r--r--tools/perf/Documentation/perf-sched.txt78
-rw-r--r--tools/perf/Documentation/perf-script.txt16
-rw-r--r--tools/perf/Documentation/perf-top.txt1
-rw-r--r--tools/perf/Documentation/perf-trace.txt5
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile.config94
-rw-r--r--tools/perf/Makefile.perf150
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c59
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c2
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c62
-rw-r--r--tools/perf/arch/powerpc/annotate/instructions.c58
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c78
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl7
-rw-r--r--tools/perf/arch/x86/tests/arch-tests.c10
-rw-r--r--tools/perf/bench/futex-hash.c10
-rw-r--r--tools/perf/bench/futex-lock-pi.c7
-rw-r--r--tools/perf/bench/futex-requeue.c2
-rw-r--r--tools/perf/bench/futex-wake-parallel.c4
-rw-r--r--tools/perf/bench/futex-wake.c3
-rw-r--r--tools/perf/bench/futex.h4
-rw-r--r--tools/perf/bench/mem-functions.c77
-rw-r--r--tools/perf/builtin-c2c.c2780
-rw-r--r--tools/perf/builtin-config.c137
-rw-r--r--tools/perf/builtin-kmem.c36
-rw-r--r--tools/perf/builtin-record.c11
-rw-r--r--tools/perf/builtin-report.c29
-rw-r--r--tools/perf/builtin-sched.c1118
-rw-r--r--tools/perf/builtin-script.c51
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c68
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/jvmti/Build8
-rw-r--r--tools/perf/jvmti/Makefile89
-rw-r--r--tools/perf/jvmti/jvmti_agent.c38
-rw-r--r--tools/perf/jvmti/libjvmti.c39
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/pmu-events/arch/powerpc/mapfile.csv21
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/cache.json176
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/floating-point.json14
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/frontend.json470
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/marked.json794
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/memory.json212
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/other.json4064
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/pipeline.json350
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/pmc.json140
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power8/translation.json176
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/cache.json746
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/floating-point.json261
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/frontend.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/memory.json154
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/other.json450
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/pipeline.json364
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/virtual-memory.json124
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/cache.json3198
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/floating-point.json171
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/frontend.json286
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/memory.json2845
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/other.json44
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/pipeline.json1417
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/virtual-memory.json388
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/cache.json774
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/floating-point.json171
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/frontend.json286
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/memory.json433
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/other.json44
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/pipeline.json1417
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/virtual-memory.json388
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/cache.json942
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/floating-point.json171
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/frontend.json286
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/memory.json649
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/other.json44
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/pipeline.json1417
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/virtual-memory.json388
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/cache.json1127
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/frontend.json52
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/memory.json34
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/other.json52
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/pipeline.json433
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmont/virtual-memory.json75
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/cache.json1041
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/floating-point.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/frontend.json294
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/memory.json655
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/other.json43
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/pipeline.json1329
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/virtual-memory.json484
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/cache.json1077
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/floating-point.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/frontend.json294
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/memory.json739
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/other.json43
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/pipeline.json1329
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/virtual-memory.json484
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/cache.json1123
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json151
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/frontend.json305
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/memory.json236
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/other.json44
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/pipeline.json1307
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/virtual-memory.json180
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/cache.json1272
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/floating-point.json151
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/frontend.json305
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/memory.json503
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/other.json44
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/pipeline.json1307
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/virtual-memory.json198
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/cache.json1290
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/floating-point.json138
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/frontend.json305
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/memory.json422
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/other.json58
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/pipeline.json1220
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/virtual-memory.json149
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/cache.json2305
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/frontend.json34
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/memory.json1110
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json435
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json65
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv35
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/cache.json3229
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json229
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/memory.json739
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/other.json210
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/pipeline.json881
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/virtual-memory.json109
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/cache.json3184
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json229
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/memory.json739
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/other.json210
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/pipeline.json881
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/virtual-memory.json109
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/cache.json1879
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/floating-point.json138
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/frontend.json305
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/memory.json445
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/other.json58
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/pipeline.json1220
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/virtual-memory.json149
-rw-r--r--tools/perf/pmu-events/arch/x86/silvermont/cache.json811
-rw-r--r--tools/perf/pmu-events/arch/x86/silvermont/frontend.json47
-rw-r--r--tools/perf/pmu-events/arch/x86/silvermont/memory.json11
-rw-r--r--tools/perf/pmu-events/arch/x86/silvermont/pipeline.json359
-rw-r--r--tools/perf/pmu-events/arch/x86/silvermont/virtual-memory.json69
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/cache.json4299
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/floating-point.json68
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/frontend.json472
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/memory.json2309
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/other.json12
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/pipeline.json939
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/virtual-memory.json272
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/cache.json2817
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json229
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/memory.json758
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/other.json287
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/pipeline.json899
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/virtual-memory.json173
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json3233
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json229
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/memory.json739
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/other.json287
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/pipeline.json899
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/virtual-memory.json149
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/cache.json3225
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/floating-point.json229
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/frontend.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/memory.json747
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/other.json287
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/pipeline.json905
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/virtual-memory.json173
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/backward-ring-buffer.c2
-rw-r--r--tools/perf/tests/bpf.c8
-rw-r--r--tools/perf/tests/builtin-test.c105
-rw-r--r--tools/perf/tests/clang.c46
-rw-r--r--tools/perf/tests/llvm.c8
-rw-r--r--tools/perf/tests/llvm.h7
-rw-r--r--tools/perf/tests/make6
-rw-r--r--tools/perf/tests/perf-hooks.c48
-rw-r--r--tools/perf/tests/tests.h4
-rw-r--r--tools/perf/ui/browsers/annotate.c26
-rw-r--r--tools/perf/ui/browsers/hists.c27
-rw-r--r--tools/perf/ui/browsers/hists.h1
-rw-r--r--tools/perf/ui/gtk/annotate.c2
-rw-r--r--tools/perf/ui/helpline.c10
-rw-r--r--tools/perf/ui/helpline.h1
-rw-r--r--tools/perf/ui/stdio/hist.c35
-rw-r--r--tools/perf/util/Build7
-rw-r--r--tools/perf/util/annotate.c392
-rw-r--r--tools/perf/util/annotate.h23
-rw-r--r--tools/perf/util/bpf-loader.c33
-rw-r--r--tools/perf/util/c++/Build2
-rw-r--r--tools/perf/util/c++/clang-c.h43
-rw-r--r--tools/perf/util/c++/clang-test.cpp62
-rw-r--r--tools/perf/util/c++/clang.cpp195
-rw-r--r--tools/perf/util/c++/clang.h26
-rw-r--r--tools/perf/util/callchain.c232
-rw-r--r--tools/perf/util/callchain.h29
-rw-r--r--tools/perf/util/config.c20
-rw-r--r--tools/perf/util/config.h4
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/evsel.c15
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/evsel_fprintf.c25
-rw-r--r--tools/perf/util/genelf.c113
-rw-r--r--tools/perf/util/genelf.h5
-rw-r--r--tools/perf/util/header.c19
-rw-r--r--tools/perf/util/hist.c1
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/intel-bts.c9
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h1
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c13
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h6
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.c4
-rw-r--r--tools/perf/util/intel-pt.c19
-rw-r--r--tools/perf/util/jitdump.c82
-rw-r--r--tools/perf/util/jitdump.h12
-rw-r--r--tools/perf/util/llvm-utils.c78
-rw-r--r--tools/perf/util/llvm-utils.h6
-rw-r--r--tools/perf/util/machine.c82
-rw-r--r--tools/perf/util/map.c17
-rw-r--r--tools/perf/util/mem-events.c136
-rw-r--r--tools/perf/util/mem-events.h38
-rw-r--r--tools/perf/util/parse-branch-options.c85
-rw-r--r--tools/perf/util/parse-branch-options.h3
-rw-r--r--tools/perf/util/parse-events.c15
-rw-r--r--tools/perf/util/perf-hooks-list.h3
-rw-r--r--tools/perf/util/perf-hooks.c88
-rw-r--r--tools/perf/util/perf-hooks.h39
-rw-r--r--tools/perf/util/pmu.c14
-rw-r--r--tools/perf/util/probe-event.h2
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/quote.c2
-rw-r--r--tools/perf/util/session.c10
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/string.c21
-rw-r--r--tools/perf/util/symbol.c10
-rw-r--r--tools/perf/util/symbol.h11
-rw-r--r--tools/perf/util/symbol_fprintf.c11
-rw-r--r--tools/perf/util/time-utils.c119
-rw-r--r--tools/perf/util/time-utils.h14
-rw-r--r--tools/perf/util/trace-event-scripting.c39
-rw-r--r--tools/perf/util/unwind-libunwind-local.c4
-rw-r--r--tools/perf/util/util-cxx.h26
-rw-r--r--tools/perf/util/util.c88
-rw-r--r--tools/perf/util/util.h6
-rw-r--r--tools/perf/util/values.c81
-rw-r--r--tools/perf/util/values.h4
-rw-r--r--tools/testing/radix-tree/multiorder.c2
-rw-r--r--tools/testing/selftests/Makefile3
-rw-r--r--tools/testing/selftests/bpf/.gitignore3
-rw-r--r--tools/testing/selftests/bpf/Makefile13
-rw-r--r--tools/testing/selftests/bpf/bpf_sys.h108
-rw-r--r--tools/testing/selftests/bpf/bpf_util.h38
-rw-r--r--tools/testing/selftests/bpf/config5
-rwxr-xr-xtools/testing/selftests/bpf/test_kmod.sh39
-rw-r--r--tools/testing/selftests/bpf/test_lru_map.c587
-rw-r--r--tools/testing/selftests/bpf/test_maps.c526
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c (renamed from samples/bpf/test_verifier.c)1030
-rw-r--r--tools/testing/selftests/futex/README2
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile11
-rw-r--r--tools/testing/selftests/net/reuseport_bpf_numa.c255
-rw-r--r--tools/testing/selftests/rcutorture/.gitignore2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh5
-rw-r--r--tools/testing/selftests/timers/skew_consistency.c2
-rw-r--r--tools/testing/selftests/x86/Makefile2
-rw-r--r--tools/testing/selftests/x86/test_vdso.c123
-rw-r--r--virt/kvm/kvm_main.c20
-rw-r--r--virt/kvm/vfio.c18
4807 files changed, 441299 insertions, 100445 deletions
diff --git a/CREDITS b/CREDITS
index d7ebdfbc4d4f..10a9eee807b6 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2775,6 +2775,10 @@ S: C/ Mieses 20, 9-B
S: Valladolid 47009
S: Spain
+N: Peter Oruba
+D: AMD Microcode loader driver
+S: Germany
+
N: Jens Osterkamp
E: jens@de.ibm.com
D: Maintainer of Spidernet network driver for Cell
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 3acc4f1a6f84..5bd4b07c2f90 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -14,13 +14,8 @@ Following translations are available on the WWW:
- this file.
ABI/
- info on kernel <-> userspace ABI and relative interface stability.
-
-BUG-HUNTING
- - brute force method of doing binary search of patches to find bug.
-Changes
- - list of changes that break older software packages.
CodingStyle
- - how the maintainers expect the C code in the kernel to look.
+ - nothing here, just a pointer to process/coding-style.rst.
DMA-API.txt
- DMA API, pci_ API & extensions for non-consistent memory machines.
DMA-API-HOWTO.txt
@@ -33,8 +28,6 @@ DocBook/
- directory with DocBook templates etc. for kernel documentation.
EDID/
- directory with info on customizing EDID for broken gfx/displays.
-HOWTO
- - the process and procedures of how to do Linux kernel development.
IPMI.txt
- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
IRQ-affinity.txt
@@ -46,62 +39,43 @@ IRQ.txt
Intel-IOMMU.txt
- basic info on the Intel IOMMU virtualization support.
Makefile
- - This file does nothing. Removing it breaks make htmldocs and
- make distclean.
-ManagementStyle
- - how to (attempt to) manage kernel hackers.
+ - It's not of interest for those who aren't touching the build system.
+Makefile.sphinx
+ - It's not of interest for those who aren't touching the build system.
+PCI/
+ - info related to PCI drivers.
RCU/
- directory with info on RCU (read-copy update).
SAK.txt
- info on Secure Attention Keys.
SM501.txt
- Silicon Motion SM501 multimedia companion chip
-SecurityBugs
- - procedure for reporting security bugs found in the kernel.
-SubmitChecklist
- - Linux kernel patch submission checklist.
-SubmittingDrivers
- - procedure to get a new driver source included into the kernel tree.
SubmittingPatches
- - procedure to get a source patch included into the kernel tree.
-VGA-softcursor.txt
- - how to change your VGA cursor from a blinking underscore.
+ - nothing here, just a pointer to process/coding-style.rst.
accounting/
- documentation on accounting and taskstats.
acpi/
- info on ACPI-specific hooks in the kernel.
+admin-guide/
+ - info related to Linux users and system admins.
aoe/
- description of AoE (ATA over Ethernet) along with config examples.
-applying-patches.txt
- - description of various trees and how to apply their patches.
arm/
- directory with info about Linux on the ARM architecture.
arm64/
- directory with info about Linux on the 64 bit ARM architecture.
-assoc_array.txt
- - generic associative array intro.
-atomic_ops.txt
- - semantics and behavior of atomic and bitmask operations.
auxdisplay/
- misc. LCD driver documentation (cfag12864b, ks0108).
backlight/
- directory with info on controlling backlights in flat panel displays
-bad_memory.txt
- - how to use kernel parameters to exclude bad RAM regions.
-basic_profiling.txt
- - basic instructions for those who wants to profile Linux kernel.
bcache.txt
- Block-layer cache on fast SSDs to improve slow (raid) I/O performance.
-binfmt_misc.txt
- - info on the kernel support for extra binary formats.
blackfin/
- directory with documentation for the Blackfin arch.
block/
- info on the Block I/O (BIO) layer.
blockdev/
- info on block devices & drivers
-braille-console.txt
- - info on how to use serial devices for Braille support.
bt8xxgpio.txt
- info on how to modify a bt8xx video card for GPIO usage.
btmrvl.txt
@@ -114,18 +88,24 @@ cachetlb.txt
- describes the cache/TLB flushing interfaces Linux uses.
cdrom/
- directory with information on the CD-ROM drivers that Linux has.
-cgroups/
- - cgroups features, including cpusets and memory controller.
+cgroup-v1/
+ - cgroups v1 features, including cpusets and memory controller.
+cgroup-v2.txt
+ - cgroups v2 features, including cpusets and memory controller.
circular-buffers.txt
- how to make use of the existing circular buffer infrastructure
clk.txt
- info on the common clock framework
-coccinelle.txt
- - info on how to get and use the Coccinelle code checking tool.
+cma/
+ - Continuous Memory Area (CMA) debugfs interface.
+conf.py
+ - It's not of interest for those who aren't touching the build system.
connector/
- docs on the netlink based userspace<->kernel space communication mod.
console/
- documentation on Linux console drivers.
+core-api/
+ - documentation on kernel core components.
cpu-freq/
- info on CPU frequency and voltage scaling.
cpu-hotplug.txt
@@ -150,26 +130,26 @@ debugging-via-ohci1394.txt
- how to use firewire like a hardware debugger memory reader.
dell_rbu.txt
- document demonstrating the use of the Dell Remote BIOS Update driver.
-development-process/
- - how to work with the mainline kernel development process.
+dev-tools/
+ - directory with info on development tools for the kernel.
device-mapper/
- directory with info on Device Mapper.
-devices.txt
- - plain ASCII listing of all the nodes in /dev/ with major minor #'s.
+dmaengine/
+ - the DMA engine and controller API guides.
devicetree/
- directory with info on device tree files used by OF/PowerPC/ARM
digsig.txt
-info on the Digital Signature Verification API
dma-buf-sharing.txt
- the DMA Buffer Sharing API Guide
+docutils.conf
+ - nothing here. Just a configuration file for docutils.
dontdiff
- file containing a list of files that should never be diff'ed.
+driver-api/
+ - the Linux driver implementer's API guide.
driver-model/
- directory with info about Linux driver model.
-dvb/
- - info on Linux Digital Video Broadcast (DVB) subsystem.
-dynamic-debug-howto.txt
- - how to use the dynamic debug (dyndbg) feature.
early-userspace/
- info about initramfs, klibc, and userspace early during boot.
edac.txt
@@ -178,14 +158,16 @@ efi-stub.txt
- How to use the EFI boot stub to bypass GRUB or elilo on EFI systems.
eisa.txt
- info on EISA bus support.
-email-clients.txt
- - info on how to use e-mail to send un-mangled (git) patches.
extcon/
- directory with porting guide for Android kernel switch driver.
+isa.txt
+ - info on EISA bus support.
fault-injection/
- dir with docs about the fault injection capabilities infrastructure.
fb/
- directory with info on the frame buffer graphics abstraction layer.
+features/
+ - status of feature implementation on different architectures.
filesystems/
- info on the vfs and the various filesystems that Linux supports.
firmware_class/
@@ -194,20 +176,22 @@ flexible-arrays.txt
- how to make use of flexible sized arrays in linux
fmc/
- information about the FMC bus abstraction
+fpga/
+ - FPGA Manager Core.
frv/
- Fujitsu FR-V Linux documentation.
futex-requeue-pi.txt
- info on requeueing of tasks from a non-PI futex to a PI futex
-gcov.txt
- - use of GCC's coverage testing tool "gcov" with the Linux kernel
+gcc-plugins.txt
+ - GCC plugin infrastructure.
gpio/
- gpio related documentation
+gpu/
+ - directory with information on GPU driver developer's guide.
hid/
- directory with information on human interface devices
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
-hsi.txt
- - HSI subsystem overview.
hwspinlock.txt
- hardware spinlock provides hardware assistance for synchronization
timers/
@@ -218,18 +202,18 @@ hwmon/
- directory with docs on various hardware monitoring drivers.
i2c/
- directory with info about the I2C bus/protocol (2 wire, kHz speed).
-i2o/
- - directory with info about the Linux I2O subsystem.
x86/i386/
- directory with info about Linux on Intel 32 bit architecture.
ia64/
- directory with info about Linux on Intel 64 bit architecture.
+ide/
+ - Information regarding the Enhanced IDE drive.
+iio/
+ - info on industrial IIO configfs support.
+index.rst
+ - main index for the documentation at ReST format.
infiniband/
- directory with documents concerning Linux InfiniBand support.
-init.txt
- - what to do when the kernel can't find the 1st process to run.
-initrd.txt
- - how to use the RAM disk as an initial/temporary root filesystem.
input/
- info on Linux input device support.
intel_txt.txt
@@ -248,28 +232,16 @@ isapnp.txt
- info on Linux ISA Plug & Play support.
isdn/
- directory with info on the Linux ISDN support, and supported cards.
-java.txt
- - info on the in-kernel binary support for Java(tm).
-ja_JP/
- - directory with Japanese translations of various documents
kbuild/
- directory with info about the kernel build process.
+kernel-doc-nano-HOWTO.txt
+ - outdated info about kernel-doc documentation.
kdump/
- directory with mini HowTo on getting the crash dump code to work.
-kernel-docs.txt
- - listing of various WWW + books that document kernel internals.
-kernel-documentation.rst
+doc-guide/
- how to write and format reStructuredText kernel documentation
-kernel-parameters.txt
- - summary listing of command line / boot prompt args for the kernel.
kernel-per-CPU-kthreads.txt
- List of all per-CPU kthreads and how they introduce jitter.
-kmemcheck.txt
- - info on dynamic checker that detects uses of uninitialized memory.
-kmemleak.txt
- - info on how to make use of the kernel memory leak detection system
-ko_KR/
- - directory with Korean translations of various documents
kobject.txt
- info of the kobject infrastructure of the Linux kernel.
kprobes.txt
@@ -284,8 +256,8 @@ ldm.txt
- a brief description of LDM (Windows Dynamic Disks).
leds/
- directory with info about LED handling under Linux.
-local_ops.txt
- - semantics and behavior of local atomic operations.
+livepatch/
+ - info on kernel live patching.
locking/
- directory with info about kernel locking primitives
lockup-watchdogs.txt
@@ -298,22 +270,24 @@ lzo.txt
- kernel LZO decompressor input formats
m68k/
- directory with info about Linux on Motorola 68k architecture.
-magic-number.txt
- - list of magic numbers used to mark/protect kernel data structures.
mailbox.txt
- How to write drivers for the common mailbox framework (IPC).
-md.txt
- - info on boot arguments for the multiple devices driver.
-media-framework.txt
- - info on media framework, its data structures, functions and usage.
+md-cluster.txt
+ - info on shared-device RAID MD cluster.
+media/
+ - info on media drivers: uAPI, kAPI and driver documentation.
memory-barriers.txt
- info on Linux kernel memory barriers.
memory-devices/
- directory with info on parts like the Texas Instruments EMIF driver
memory-hotplug.txt
- Hotpluggable memory support, how to use and current status.
+men-chameleon-bus.txt
+ - info on MEN chameleon bus.
metag/
- directory with info about Linux on Meta architecture.
+mic/
+ - Intel Many Integrated Core (MIC) architecture device driver.
mips/
- directory with info about Linux on MIPS architecture.
misc-devices/
@@ -322,12 +296,8 @@ mmc/
- directory with info about the MMC subsystem
mn10300/
- directory with info about the mn10300 architecture port
-module-signing.txt
- - Kernel module signing for increased security when loading modules.
mtd/
- directory with info about memory technology devices (flash)
-mono.txt
- - how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
namespaces/
- directory with various information about namespaces
netlabel/
@@ -336,30 +306,42 @@ networking/
- directory with info on various aspects of networking with Linux.
nfc/
- directory relating info about Near Field Communications support.
+nios2/
+ - Linux on the Nios II architecture.
nommu-mmap.txt
- documentation about no-mmu memory mapping support.
numastat.txt
- info on how to read Numa policy hit/miss statistics in sysfs.
-oops-tracing.txt
- - how to decode those nasty internal kernel error dump messages.
+ntb.txt
+ - info on Non-Transparent Bridge (NTB) drivers.
+nvdimm/
+ - info on non-volatile devices.
+nvmem/
+ - info on non volatile memory framework.
+output/
+ - default directory where html/LaTeX/pdf files will be written.
padata.txt
- An introduction to the "padata" parallel execution API
parisc/
- directory with info on using Linux on PA-RISC architecture.
-parport.txt
- - how to use the parallel-port driver.
parport-lowlevel.txt
- description and usage of the low level parallel port functions.
pcmcia/
- info on the Linux PCMCIA driver.
percpu-rw-semaphore.txt
- RCU based read-write semaphore optimized for locking for reading
+perf/
+ - info about the APM X-Gene SoC Performance Monitoring Unit (PMU).
+phy/
+ - ino on Samsung USB 2.0 PHY adaptation layer.
phy.txt
- Description of the generic PHY framework.
pi-futex.txt
- documentation on lightweight priority inheritance futexes.
pinctrl.txt
- info on pinctrl subsystem and the PINMUX/PINCONF and drivers
+platform/
+ - List of supported hardware by compal and Dell laptop.
pnp.txt
- Linux Plug and Play documentation.
power/
@@ -372,14 +354,16 @@ preempt-locking.txt
- info on locking under a preemptive kernel.
printk-formats.txt
- how to get printk format specifiers right
+process/
+ - how to work with the mainline kernel development process.
pps/
- directory with information on the pulse-per-second support
+pti/
+ - directory with info on Intel MID PTI.
ptp/
- directory with info on support for IEEE 1588 PTP clocks in Linux.
pwm.txt
- info on the pulse width modulation driver subsystem
-ramoops.txt
- - documentation of the ramoops oops/panic logging module.
rapidio/
- directory with info on RapidIO packet-based fabric interconnect
rbtree.txt
@@ -406,8 +390,6 @@ security/
- directory that contains security-related info
serial/
- directory with info on the low level serial API.
-serial-console.txt
- - how to set up Linux with a serial line console as the default.
sgi-ioc4.txt
- description of the SGI IOC4 PCI (multi function) device.
sh/
@@ -416,24 +398,20 @@ smsc_ece1099.txt
-info on the smsc Keyboard Scan Expansion/GPIO Expansion device.
sound/
- directory with info on sound card support.
-sparse.txt
- - info on how to obtain and use the sparse tool for typechecking.
spi/
- overview of Linux kernel Serial Peripheral Interface (SPI) support.
-stable_api_nonsense.txt
- - info on why the kernel does not have a stable in-kernel api or abi.
-stable_kernel_rules.txt
- - rules and procedures for the -stable kernel releases.
+sphinx/
+ - no documentation here, just files required by Sphinx toolchain.
+sphinx-static/
+ - no documentation here, just files required by Sphinx toolchain.
static-keys.txt
- info on how static keys allow debug code in hotpaths via patching
svga.txt
- short guide on selecting video modes at boot via VGA BIOS.
-sysfs-rules.txt
- - How not to use sysfs.
+sync_file.txt
+ - Sync file API guide.
sysctl/
- directory with info on the /proc/sys/* files.
-sysrq.txt
- - info on the magic SysRq key.
target/
- directory with info on generating TCM v4 fabric .ko modules
this_cpu_ops.txt
@@ -442,39 +420,29 @@ thermal/
- directory with information on managing thermal issues (CPU/temp)
trace/
- directory with info on tracing technologies within linux
+translations/
+ - translations of this document from English to another language
unaligned-memory-access.txt
- info on how to avoid arch breaking unaligned memory access in code.
-unicode.txt
- - info on the Unicode character/font mapping used in Linux.
unshare.txt
- description of the Linux unshare system call.
usb/
- directory with info regarding the Universal Serial Bus.
-vDSO/
- - directory with info regarding virtual dynamic shared objects
vfio.txt
- info on Virtual Function I/O used in guest/hypervisor instances.
-vgaarbiter.txt
- - info on enable/disable the legacy decoding on different VGA devices
video-output.txt
- sysfs class driver interface to enable/disable a video output device.
-video4linux/
- - directory with info regarding video/TV/radio cards and linux.
virtual/
- directory with information on the various linux virtualizations.
vm/
- directory with info on the Linux vm code.
-vme_api.txt
- - file relating info on the VME bus API in linux
-volatile-considered-harmful.txt
- - Why the "volatile" type class should not be used
w1/
- directory with documents regarding the 1-wire (w1) subsystem.
watchdog/
- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
wimax/
- directory with info about Intel Wireless Wimax Connections
-workqueue.txt
+core-api/workqueue.rst
- information on the Concurrency Managed Workqueue implementation
x86/x86_64/
- directory with info on Linux support for AMD x86-64 (Hammer) machines.
@@ -484,7 +452,5 @@ xtensa/
- directory with documents relating to arch/xtensa port/implementation
xz.txt
- how to make use of the XZ data compression within linux kernel
-zh_CN/
- - directory with Chinese translations of various documents
zorro.txt
- info on writing drivers for Zorro bus devices found on Amigas.
diff --git a/Documentation/ABI/README b/Documentation/ABI/README
index 1fafc4b0753b..3121029dce21 100644
--- a/Documentation/ABI/README
+++ b/Documentation/ABI/README
@@ -84,4 +84,4 @@ stable:
- Kernel-internal symbols. Do not rely on the presence, absence, location, or
type of any kernel symbol, either in System.map files or the kernel binary
- itself. See Documentation/stable_api_nonsense.txt.
+ itself. See Documentation/process/stable-api-nonsense.rst.
diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block
index 71d184dbb70d..2da04ce6aeef 100644
--- a/Documentation/ABI/testing/sysfs-block
+++ b/Documentation/ABI/testing/sysfs-block
@@ -235,3 +235,45 @@ Description:
write_same_max_bytes is 0, write same is not supported
by the device.
+What: /sys/block/<disk>/queue/write_zeroes_max_bytes
+Date: November 2016
+Contact: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
+Description:
+ Devices that support write zeroes operation in which a
+ single request can be issued to zero out the range of
+ contiguous blocks on storage without having any payload
+ in the request. This can be used to optimize writing zeroes
+ to the devices. write_zeroes_max_bytes indicates how many
+ bytes can be written in a single write zeroes command. If
+ write_zeroes_max_bytes is 0, write zeroes is not supported
+ by the device.
+
+What: /sys/block/<disk>/queue/zoned
+Date: September 2016
+Contact: Damien Le Moal <damien.lemoal@hgst.com>
+Description:
+ zoned indicates if the device is a zoned block device
+ and the zone model of the device if it is indeed zoned.
+ The possible values indicated by zoned are "none" for
+ regular block devices and "host-aware" or "host-managed"
+ for zoned block devices. The characteristics of
+ host-aware and host-managed zoned block devices are
+ described in the ZBC (Zoned Block Commands) and ZAC
+ (Zoned Device ATA Command Set) standards. These standards
+ also define the "drive-managed" zone model. However,
+ since drive-managed zoned block devices do not support
+ zone commands, they will be treated as regular block
+ devices and zoned will report "none".
+
+What: /sys/block/<disk>/queue/chunk_sectors
+Date: September 2016
+Contact: Hannes Reinecke <hare@suse.com>
+Description:
+ chunk_sectors has different meaning depending on the type
+ of the disk. For a RAID device (dm-raid), chunk_sectors
+ indicates the size in 512B sectors of the RAID volume
+ stripe segment. For a zoned block device, either
+ host-aware or host-managed, chunk_sectors indicates the
+ size of 512B sectors of the zones of the device, with
+ the eventual exception of the last zone of the device
+ which may be smaller.
diff --git a/Documentation/ABI/testing/sysfs-bus-vfio-mdev b/Documentation/ABI/testing/sysfs-bus-vfio-mdev
new file mode 100644
index 000000000000..452dbe39270e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-vfio-mdev
@@ -0,0 +1,111 @@
+What: /sys/.../<device>/mdev_supported_types/
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ This directory contains list of directories of currently
+ supported mediated device types and their details for
+ <device>. Supported type attributes are defined by the
+ vendor driver who registers with Mediated device framework.
+ Each supported type is a directory whose name is created
+ by adding the device driver string as a prefix to the
+ string provided by the vendor driver.
+
+What: /sys/.../<device>/mdev_supported_types/<type-id>/
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ This directory gives details of supported type, like name,
+ description, available_instances, device_api etc.
+ 'device_api' and 'available_instances' are mandatory
+ attributes to be provided by vendor driver. 'name',
+ 'description' and other vendor driver specific attributes
+ are optional.
+
+What: /sys/.../mdev_supported_types/<type-id>/create
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Writing UUID to this file will create mediated device of
+ type <type-id> for parent device <device>. This is a
+ write-only file.
+ For example:
+ # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" > \
+ /sys/devices/foo/mdev_supported_types/foo-1/create
+
+What: /sys/.../mdev_supported_types/<type-id>/devices/
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ This directory contains symbolic links pointing to mdev
+ devices sysfs entries which are created of this <type-id>.
+
+What: /sys/.../mdev_supported_types/<type-id>/available_instances
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Reading this attribute will show the number of mediated
+ devices of type <type-id> that can be created. This is a
+ readonly file.
+Users:
+ Userspace applications interested in creating mediated
+ device of that type. Userspace application should check
+ the number of available instances could be created before
+ creating mediated device of this type.
+
+What: /sys/.../mdev_supported_types/<type-id>/device_api
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Reading this attribute will show VFIO device API supported
+ by this type. For example, "vfio-pci" for a PCI device,
+ "vfio-platform" for platform device.
+
+What: /sys/.../mdev_supported_types/<type-id>/name
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Reading this attribute will show human readable name of the
+ mediated device that will get created of type <type-id>.
+ This is optional attribute. For example: "Grid M60-0Q"
+Users:
+ Userspace applications interested in knowing the name of
+ a particular <type-id> that can help in understanding the
+ type of mediated device.
+
+What: /sys/.../mdev_supported_types/<type-id>/description
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Reading this attribute will show description of the type of
+ mediated device that will get created of type <type-id>.
+ This is optional attribute. For example:
+ "2 heads, 512M FB, 2560x1600 maximum resolution"
+Users:
+ Userspace applications interested in knowing the details of
+ a particular <type-id> that can help in understanding the
+ features provided by that type of mediated device.
+
+What: /sys/.../<device>/<UUID>/
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ This directory represents device directory of mediated
+ device. It contains all the attributes related to mediated
+ device.
+
+What: /sys/.../<device>/<UUID>/mdev_type
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ This is symbolic link pointing to supported type, <type-id>
+ directory of which this mediated device is created.
+
+What: /sys/.../<device>/<UUID>/remove
+Date: October 2016
+Contact: Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+ Writing '1' to this file destroys the mediated device. The
+ vendor driver can fail the remove() callback if that device
+ is active and the vendor driver doesn't support hot unplug.
+ Example:
+ # echo 1 > /sys/bus/mdev/devices/<UUID>/remove
diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led
index 86ace287d48b..491cdeedc195 100644
--- a/Documentation/ABI/testing/sysfs-class-led
+++ b/Documentation/ABI/testing/sysfs-class-led
@@ -4,16 +4,24 @@ KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the brightness of the LED. Most LEDs don't
- have hardware brightness support so will just be turned on for
+ have hardware brightness support, so will just be turned on for
non-zero brightness settings. The value is between 0 and
/sys/class/leds/<led>/max_brightness.
+ Writing 0 to this file clears active trigger.
+
+ Writing non-zero to this file while trigger is active changes the
+ top brightness trigger is going to use.
+
What: /sys/class/leds/<led>/max_brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
- Maximum brightness level for this led, default is 255 (LED_FULL).
+ Maximum brightness level for this LED, default is 255 (LED_FULL).
+
+ If the LED does not support different brightness levels, this
+ should be 1.
What: /sys/class/leds/<led>/trigger
Date: March 2006
@@ -21,7 +29,7 @@ KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the trigger for this LED. A trigger is a kernel based source
- of led events.
+ of LED events.
You can change triggers in a similar manner to the way an IO
scheduler is chosen. Trigger specific parameters can appear in
/sys/class/leds/<led> once a given trigger is selected. For
diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc b/Documentation/ABI/testing/sysfs-class-remoteproc
new file mode 100644
index 000000000000..d188afebc8ba
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -0,0 +1,50 @@
+What: /sys/class/remoteproc/.../firmware
+Date: October 2016
+Contact: Matt Redfearn <matt.redfearn@imgtec.com>
+Description: Remote processor firmware
+
+ Reports the name of the firmware currently loaded to the
+ remote processor.
+
+ To change the running firmware, ensure the remote processor is
+ stopped (using /sys/class/remoteproc/.../state) and write a new filename.
+
+What: /sys/class/remoteproc/.../state
+Date: October 2016
+Contact: Matt Redfearn <matt.redfearn@imgtec.com>
+Description: Remote processor state
+
+ Reports the state of the remote processor, which will be one of:
+
+ "offline"
+ "suspended"
+ "running"
+ "crashed"
+ "invalid"
+
+ "offline" means the remote processor is powered off.
+
+ "suspended" means that the remote processor is suspended and
+ must be woken to receive messages.
+
+ "running" is the normal state of an available remote processor
+
+ "crashed" indicates that a problem/crash has been detected on
+ the remote processor.
+
+ "invalid" is returned if the remote processor is in an
+ unknown state.
+
+ Writing this file controls the state of the remote processor.
+ The following states can be written:
+
+ "start"
+ "stop"
+
+ Writing "start" will attempt to start the processor running the
+ firmware indicated by, or written to,
+ /sys/class/remoteproc/.../firmware. The remote processor should
+ transition to "running" state.
+
+ Writing "stop" will attempt to halt the remote processor and
+ return it to the "offline" state.
diff --git a/Documentation/ABI/testing/sysfs-kernel-slab b/Documentation/ABI/testing/sysfs-kernel-slab
index 91bd6ca5440f..2cc0a72b64be 100644
--- a/Documentation/ABI/testing/sysfs-kernel-slab
+++ b/Documentation/ABI/testing/sysfs-kernel-slab
@@ -347,7 +347,7 @@ Description:
because of fragmentation, SLUB will retry with the minimum order
possible depending on its characteristics.
When debug_guardpage_minorder=N (N > 0) parameter is specified
- (see Documentation/kernel-parameters.txt), the minimum possible
+ (see Documentation/admin-guide/kernel-parameters.rst), the minimum possible
order is used and this sysfs entry can not be used to change
the order at run time.
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 50b368d490b5..f523e5a3ac33 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -7,30 +7,35 @@ Description:
subsystem.
What: /sys/power/state
-Date: May 2014
+Date: November 2016
Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
Description:
The /sys/power/state file controls system sleep states.
Reading from this file returns the available sleep state
- labels, which may be "mem", "standby", "freeze" and "disk"
- (hibernation). The meanings of the first three labels depend on
- the relative_sleep_states command line argument as follows:
- 1) relative_sleep_states = 1
- "mem", "standby", "freeze" represent non-hibernation sleep
- states from the deepest ("mem", always present) to the
- shallowest ("freeze"). "standby" and "freeze" may or may
- not be present depending on the capabilities of the
- platform. "freeze" can only be present if "standby" is
- present.
- 2) relative_sleep_states = 0 (default)
- "mem" - "suspend-to-RAM", present if supported.
- "standby" - "power-on suspend", present if supported.
- "freeze" - "suspend-to-idle", always present.
-
- Writing to this file one of these strings causes the system to
- transition into the corresponding state, if available. See
- Documentation/power/states.txt for a description of what
- "suspend-to-RAM", "power-on suspend" and "suspend-to-idle" mean.
+ labels, which may be "mem" (suspend), "standby" (power-on
+ suspend), "freeze" (suspend-to-idle) and "disk" (hibernation).
+
+ Writing one of the above strings to this file causes the system
+ to transition into the corresponding state, if available.
+
+ See Documentation/power/states.txt for more information.
+
+What: /sys/power/mem_sleep
+Date: November 2016
+Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
+Description:
+ The /sys/power/mem_sleep file controls the operating mode of
+ system suspend. Reading from it returns the available modes
+ as "s2idle" (always present), "shallow" and "deep" (present if
+ supported). The mode that will be used on subsequent attempts
+ to suspend the system (by writing "mem" to the /sys/power/state
+ file described above) is enclosed in square brackets.
+
+ Writing one of the above strings to this file causes the mode
+ represented by it to be used on subsequent attempts to suspend
+ the system.
+
+ See Documentation/power/states.txt for more information.
What: /sys/power/disk
Date: September 2006
diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
deleted file mode 100644
index 65022a87bf17..000000000000
--- a/Documentation/BUG-HUNTING
+++ /dev/null
@@ -1,246 +0,0 @@
-Table of contents
-=================
-
-Last updated: 20 December 2005
-
-Contents
-========
-
-- Introduction
-- Devices not appearing
-- Finding patch that caused a bug
--- Finding using git-bisect
--- Finding it the old way
-- Fixing the bug
-
-Introduction
-============
-
-Always try the latest kernel from kernel.org and build from source. If you are
-not confident in doing that please report the bug to your distribution vendor
-instead of to a kernel developer.
-
-Finding bugs is not always easy. Have a go though. If you can't find it don't
-give up. Report as much as you have found to the relevant maintainer. See
-MAINTAINERS for who that is for the subsystem you have worked on.
-
-Before you submit a bug report read REPORTING-BUGS.
-
-Devices not appearing
-=====================
-
-Often this is caused by udev. Check that first before blaming it on the
-kernel.
-
-Finding patch that caused a bug
-===============================
-
-
-
-Finding using git-bisect
-------------------------
-
-Using the provided tools with git makes finding bugs easy provided the bug is
-reproducible.
-
-Steps to do it:
-- start using git for the kernel source
-- read the man page for git-bisect
-- have fun
-
-Finding it the old way
-----------------------
-
-[Sat Mar 2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm@sgi.com (Larry McVoy)]
-
-This is how to track down a bug if you know nothing about kernel hacking.
-It's a brute force approach but it works pretty well.
-
-You need:
-
- . A reproducible bug - it has to happen predictably (sorry)
- . All the kernel tar files from a revision that worked to the
- revision that doesn't
-
-You will then do:
-
- . Rebuild a revision that you believe works, install, and verify that.
- . Do a binary search over the kernels to figure out which one
- introduced the bug. I.e., suppose 1.3.28 didn't have the bug, but
- you know that 1.3.69 does. Pick a kernel in the middle and build
- that, like 1.3.50. Build & test; if it works, pick the mid point
- between .50 and .69, else the mid point between .28 and .50.
- . You'll narrow it down to the kernel that introduced the bug. You
- can probably do better than this but it gets tricky.
-
- . Narrow it down to a subdirectory
-
- - Copy kernel that works into "test". Let's say that 3.62 works,
- but 3.63 doesn't. So you diff -r those two kernels and come
- up with a list of directories that changed. For each of those
- directories:
-
- Copy the non-working directory next to the working directory
- as "dir.63".
- One directory at time, try moving the working directory to
- "dir.62" and mv dir.63 dir"time, try
-
- mv dir dir.62
- mv dir.63 dir
- find dir -name '*.[oa]' -print | xargs rm -f
-
- And then rebuild and retest. Assuming that all related
- changes were contained in the sub directory, this should
- isolate the change to a directory.
-
- Problems: changes in header files may have occurred; I've
- found in my case that they were self explanatory - you may
- or may not want to give up when that happens.
-
- . Narrow it down to a file
-
- - You can apply the same technique to each file in the directory,
- hoping that the changes in that file are self contained.
-
- . Narrow it down to a routine
-
- - You can take the old file and the new file and manually create
- a merged file that has
-
- #ifdef VER62
- routine()
- {
- ...
- }
- #else
- routine()
- {
- ...
- }
- #endif
-
- And then walk through that file, one routine at a time and
- prefix it with
-
- #define VER62
- /* both routines here */
- #undef VER62
-
- Then recompile, retest, move the ifdefs until you find the one
- that makes the difference.
-
-Finally, you take all the info that you have, kernel revisions, bug
-description, the extent to which you have narrowed it down, and pass
-that off to whomever you believe is the maintainer of that section.
-A post to linux.dev.kernel isn't such a bad idea if you've done some
-work to narrow it down.
-
-If you get it down to a routine, you'll probably get a fix in 24 hours.
-
-My apologies to Linus and the other kernel hackers for describing this
-brute force approach, it's hardly what a kernel hacker would do. However,
-it does work and it lets non-hackers help fix bugs. And it is cool
-because Linux snapshots will let you do this - something that you can't
-do with vendor supplied releases.
-
-Fixing the bug
-==============
-
-Nobody is going to tell you how to fix bugs. Seriously. You need to work it
-out. But below are some hints on how to use the tools.
-
-To debug a kernel, use objdump and look for the hex offset from the crash
-output to find the valid line of code/assembler. Without debug symbols, you
-will see the assembler code for the routine shown, but if your kernel has
-debug symbols the C code will also be available. (Debug symbols can be enabled
-in the kernel hacking menu of the menu configuration.) For example:
-
- objdump -r -S -l --disassemble net/dccp/ipv4.o
-
-NB.: you need to be at the top level of the kernel tree for this to pick up
-your C files.
-
-If you don't have access to the code you can also debug on some crash dumps
-e.g. crash dump output as shown by Dave Miller.
-
-> EIP is at ip_queue_xmit+0x14/0x4c0
-> ...
-> Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
-> 00 00 55 57 56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
-> <8b> 83 3c 01 00 00 89 44 24 14 8b 45 28 85 c0 89 44 24 18 0f 85
->
-> Put the bytes into a "foo.s" file like this:
->
-> .text
-> .globl foo
-> foo:
-> .byte .... /* bytes from Code: part of OOPS dump */
->
-> Compile it with "gcc -c -o foo.o foo.s" then look at the output of
-> "objdump --disassemble foo.o".
->
-> Output:
->
-> ip_queue_xmit:
-> push %ebp
-> push %edi
-> push %esi
-> push %ebx
-> sub $0xbc, %esp
-> mov 0xd0(%esp), %ebp ! %ebp = arg0 (skb)
-> mov 0x8(%ebp), %ebx ! %ebx = skb->sk
-> mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
-
-In addition, you can use GDB to figure out the exact file and line
-number of the OOPS from the vmlinux file. If you have
-CONFIG_DEBUG_INFO enabled, you can simply copy the EIP value from the
-OOPS:
-
- EIP: 0060:[<c021e50e>] Not tainted VLI
-
-And use GDB to translate that to human-readable form:
-
- gdb vmlinux
- (gdb) l *0xc021e50e
-
-If you don't have CONFIG_DEBUG_INFO enabled, you use the function
-offset from the OOPS:
-
- EIP is at vt_ioctl+0xda8/0x1482
-
-And recompile the kernel with CONFIG_DEBUG_INFO enabled:
-
- make vmlinux
- gdb vmlinux
- (gdb) p vt_ioctl
- (gdb) l *(0x<address of vt_ioctl> + 0xda8)
-or, as one command
- (gdb) l *(vt_ioctl + 0xda8)
-
-If you have a call trace, such as :-
->Call Trace:
-> [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
-> [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
-> [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
-> ...
-this shows the problem in the :jbd: module. You can load that module in gdb
-and list the relevant code.
- gdb fs/jbd/jbd.ko
- (gdb) p log_wait_commit
- (gdb) l *(0x<address> + 0xa3)
-or
- (gdb) l *(log_wait_commit + 0xa3)
-
-
-Another very useful option of the Kernel Hacking section in menuconfig is
-Debug memory allocations. This will help you see whether data has been
-initialised and not set before use etc. To see the values that get assigned
-with this look at mm/slab.c and search for POISON_INUSE. When using this an
-Oops will often show the poisoned data instead of zero which is the default.
-
-Once you have worked out a fix please submit it upstream. After all open
-source is about sharing what you do and don't you want to be recognised for
-your genius?
-
-Please do read Documentation/SubmittingPatches though to help your code get
-accepted.
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 9c61c039ccd9..320983ca114e 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -1,1062 +1 @@
-.. _codingstyle:
-
-Linux kernel coding style
-=========================
-
-This is a short document describing the preferred coding style for the
-linux kernel. Coding style is very personal, and I won't **force** my
-views on anybody, but this is what goes for anything that I have to be
-able to maintain, and I'd prefer it for most other things too. Please
-at least consider the points made here.
-
-First off, I'd suggest printing out a copy of the GNU coding standards,
-and NOT read it. Burn them, it's a great symbolic gesture.
-
-Anyway, here goes:
-
-
-1) Indentation
---------------
-
-Tabs are 8 characters, and thus indentations are also 8 characters.
-There are heretic movements that try to make indentations 4 (or even 2!)
-characters deep, and that is akin to trying to define the value of PI to
-be 3.
-
-Rationale: The whole idea behind indentation is to clearly define where
-a block of control starts and ends. Especially when you've been looking
-at your screen for 20 straight hours, you'll find it a lot easier to see
-how the indentation works if you have large indentations.
-
-Now, some people will claim that having 8-character indentations makes
-the code move too far to the right, and makes it hard to read on a
-80-character terminal screen. The answer to that is that if you need
-more than 3 levels of indentation, you're screwed anyway, and should fix
-your program.
-
-In short, 8-char indents make things easier to read, and have the added
-benefit of warning you when you're nesting your functions too deep.
-Heed that warning.
-
-The preferred way to ease multiple indentation levels in a switch statement is
-to align the ``switch`` and its subordinate ``case`` labels in the same column
-instead of ``double-indenting`` the ``case`` labels. E.g.:
-
-.. code-block:: c
-
- switch (suffix) {
- case 'G':
- case 'g':
- mem <<= 30;
- break;
- case 'M':
- case 'm':
- mem <<= 20;
- break;
- case 'K':
- case 'k':
- mem <<= 10;
- /* fall through */
- default:
- break;
- }
-
-Don't put multiple statements on a single line unless you have
-something to hide:
-
-.. code-block:: c
-
- if (condition) do_this;
- do_something_everytime;
-
-Don't put multiple assignments on a single line either. Kernel coding style
-is super simple. Avoid tricky expressions.
-
-Outside of comments, documentation and except in Kconfig, spaces are never
-used for indentation, and the above example is deliberately broken.
-
-Get a decent editor and don't leave whitespace at the end of lines.
-
-
-2) Breaking long lines and strings
-----------------------------------
-
-Coding style is all about readability and maintainability using commonly
-available tools.
-
-The limit on the length of lines is 80 columns and this is a strongly
-preferred limit.
-
-Statements longer than 80 columns will be broken into sensible chunks, unless
-exceeding 80 columns significantly increases readability and does not hide
-information. Descendants are always substantially shorter than the parent and
-are placed substantially to the right. The same applies to function headers
-with a long argument list. However, never break user-visible strings such as
-printk messages, because that breaks the ability to grep for them.
-
-
-3) Placing Braces and Spaces
-----------------------------
-
-The other issue that always comes up in C styling is the placement of
-braces. Unlike the indent size, there are few technical reasons to
-choose one placement strategy over the other, but the preferred way, as
-shown to us by the prophets Kernighan and Ritchie, is to put the opening
-brace last on the line, and put the closing brace first, thusly:
-
-.. code-block:: c
-
- if (x is true) {
- we do y
- }
-
-This applies to all non-function statement blocks (if, switch, for,
-while, do). E.g.:
-
-.. code-block:: c
-
- switch (action) {
- case KOBJ_ADD:
- return "add";
- case KOBJ_REMOVE:
- return "remove";
- case KOBJ_CHANGE:
- return "change";
- default:
- return NULL;
- }
-
-However, there is one special case, namely functions: they have the
-opening brace at the beginning of the next line, thus:
-
-.. code-block:: c
-
- int function(int x)
- {
- body of function
- }
-
-Heretic people all over the world have claimed that this inconsistency
-is ... well ... inconsistent, but all right-thinking people know that
-(a) K&R are **right** and (b) K&R are right. Besides, functions are
-special anyway (you can't nest them in C).
-
-Note that the closing brace is empty on a line of its own, **except** in
-the cases where it is followed by a continuation of the same statement,
-ie a ``while`` in a do-statement or an ``else`` in an if-statement, like
-this:
-
-.. code-block:: c
-
- do {
- body of do-loop
- } while (condition);
-
-and
-
-.. code-block:: c
-
- if (x == y) {
- ..
- } else if (x > y) {
- ...
- } else {
- ....
- }
-
-Rationale: K&R.
-
-Also, note that this brace-placement also minimizes the number of empty
-(or almost empty) lines, without any loss of readability. Thus, as the
-supply of new-lines on your screen is not a renewable resource (think
-25-line terminal screens here), you have more empty lines to put
-comments on.
-
-Do not unnecessarily use braces where a single statement will do.
-
-.. code-block:: c
-
- if (condition)
- action();
-
-and
-
-.. code-block:: none
-
- if (condition)
- do_this();
- else
- do_that();
-
-This does not apply if only one branch of a conditional statement is a single
-statement; in the latter case use braces in both branches:
-
-.. code-block:: c
-
- if (condition) {
- do_this();
- do_that();
- } else {
- otherwise();
- }
-
-3.1) Spaces
-***********
-
-Linux kernel style for use of spaces depends (mostly) on
-function-versus-keyword usage. Use a space after (most) keywords. The
-notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
-somewhat like functions (and are usually used with parentheses in Linux,
-although they are not required in the language, as in: ``sizeof info`` after
-``struct fileinfo info;`` is declared).
-
-So use a space after these keywords::
-
- if, switch, case, for, do, while
-
-but not with sizeof, typeof, alignof, or __attribute__. E.g.,
-
-.. code-block:: c
-
-
- s = sizeof(struct file);
-
-Do not add spaces around (inside) parenthesized expressions. This example is
-**bad**:
-
-.. code-block:: c
-
-
- s = sizeof( struct file );
-
-When declaring pointer data or a function that returns a pointer type, the
-preferred use of ``*`` is adjacent to the data name or function name and not
-adjacent to the type name. Examples:
-
-.. code-block:: c
-
-
- char *linux_banner;
- unsigned long long memparse(char *ptr, char **retptr);
- char *match_strdup(substring_t *s);
-
-Use one space around (on each side of) most binary and ternary operators,
-such as any of these::
-
- = + - < > * / % | & ^ <= >= == != ? :
-
-but no space after unary operators::
-
- & * + - ~ ! sizeof typeof alignof __attribute__ defined
-
-no space before the postfix increment & decrement unary operators::
-
- ++ --
-
-no space after the prefix increment & decrement unary operators::
-
- ++ --
-
-and no space around the ``.`` and ``->`` structure member operators.
-
-Do not leave trailing whitespace at the ends of lines. Some editors with
-``smart`` indentation will insert whitespace at the beginning of new lines as
-appropriate, so you can start typing the next line of code right away.
-However, some such editors do not remove the whitespace if you end up not
-putting a line of code there, such as if you leave a blank line. As a result,
-you end up with lines containing trailing whitespace.
-
-Git will warn you about patches that introduce trailing whitespace, and can
-optionally strip the trailing whitespace for you; however, if applying a series
-of patches, this may make later patches in the series fail by changing their
-context lines.
-
-
-4) Naming
----------
-
-C is a Spartan language, and so should your naming be. Unlike Modula-2
-and Pascal programmers, C programmers do not use cute names like
-ThisVariableIsATemporaryCounter. A C programmer would call that
-variable ``tmp``, which is much easier to write, and not the least more
-difficult to understand.
-
-HOWEVER, while mixed-case names are frowned upon, descriptive names for
-global variables are a must. To call a global function ``foo`` is a
-shooting offense.
-
-GLOBAL variables (to be used only if you **really** need them) need to
-have descriptive names, as do global functions. If you have a function
-that counts the number of active users, you should call that
-``count_active_users()`` or similar, you should **not** call it ``cntusr()``.
-
-Encoding the type of a function into the name (so-called Hungarian
-notation) is brain damaged - the compiler knows the types anyway and can
-check those, and it only confuses the programmer. No wonder MicroSoft
-makes buggy programs.
-
-LOCAL variable names should be short, and to the point. If you have
-some random integer loop counter, it should probably be called ``i``.
-Calling it ``loop_counter`` is non-productive, if there is no chance of it
-being mis-understood. Similarly, ``tmp`` can be just about any type of
-variable that is used to hold a temporary value.
-
-If you are afraid to mix up your local variable names, you have another
-problem, which is called the function-growth-hormone-imbalance syndrome.
-See chapter 6 (Functions).
-
-
-5) Typedefs
------------
-
-Please don't use things like ``vps_t``.
-It's a **mistake** to use typedef for structures and pointers. When you see a
-
-.. code-block:: c
-
-
- vps_t a;
-
-in the source, what does it mean?
-In contrast, if it says
-
-.. code-block:: c
-
- struct virtual_container *a;
-
-you can actually tell what ``a`` is.
-
-Lots of people think that typedefs ``help readability``. Not so. They are
-useful only for:
-
- (a) totally opaque objects (where the typedef is actively used to **hide**
- what the object is).
-
- Example: ``pte_t`` etc. opaque objects that you can only access using
- the proper accessor functions.
-
- .. note::
-
- Opaqueness and ``accessor functions`` are not good in themselves.
- The reason we have them for things like pte_t etc. is that there
- really is absolutely **zero** portably accessible information there.
-
- (b) Clear integer types, where the abstraction **helps** avoid confusion
- whether it is ``int`` or ``long``.
-
- u8/u16/u32 are perfectly fine typedefs, although they fit into
- category (d) better than here.
-
- .. note::
-
- Again - there needs to be a **reason** for this. If something is
- ``unsigned long``, then there's no reason to do
-
- typedef unsigned long myflags_t;
-
- but if there is a clear reason for why it under certain circumstances
- might be an ``unsigned int`` and under other configurations might be
- ``unsigned long``, then by all means go ahead and use a typedef.
-
- (c) when you use sparse to literally create a **new** type for
- type-checking.
-
- (d) New types which are identical to standard C99 types, in certain
- exceptional circumstances.
-
- Although it would only take a short amount of time for the eyes and
- brain to become accustomed to the standard types like ``uint32_t``,
- some people object to their use anyway.
-
- Therefore, the Linux-specific ``u8/u16/u32/u64`` types and their
- signed equivalents which are identical to standard types are
- permitted -- although they are not mandatory in new code of your
- own.
-
- When editing existing code which already uses one or the other set
- of types, you should conform to the existing choices in that code.
-
- (e) Types safe for use in userspace.
-
- In certain structures which are visible to userspace, we cannot
- require C99 types and cannot use the ``u32`` form above. Thus, we
- use __u32 and similar types in all structures which are shared
- with userspace.
-
-Maybe there are other cases too, but the rule should basically be to NEVER
-EVER use a typedef unless you can clearly match one of those rules.
-
-In general, a pointer, or a struct that has elements that can reasonably
-be directly accessed should **never** be a typedef.
-
-
-6) Functions
-------------
-
-Functions should be short and sweet, and do just one thing. They should
-fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
-as we all know), and do one thing and do that well.
-
-The maximum length of a function is inversely proportional to the
-complexity and indentation level of that function. So, if you have a
-conceptually simple function that is just one long (but simple)
-case-statement, where you have to do lots of small things for a lot of
-different cases, it's OK to have a longer function.
-
-However, if you have a complex function, and you suspect that a
-less-than-gifted first-year high-school student might not even
-understand what the function is all about, you should adhere to the
-maximum limits all the more closely. Use helper functions with
-descriptive names (you can ask the compiler to in-line them if you think
-it's performance-critical, and it will probably do a better job of it
-than you would have done).
-
-Another measure of the function is the number of local variables. They
-shouldn't exceed 5-10, or you're doing something wrong. Re-think the
-function, and split it into smaller pieces. A human brain can
-generally easily keep track of about 7 different things, anything more
-and it gets confused. You know you're brilliant, but maybe you'd like
-to understand what you did 2 weeks from now.
-
-In source files, separate functions with one blank line. If the function is
-exported, the **EXPORT** macro for it should follow immediately after the
-closing function brace line. E.g.:
-
-.. code-block:: c
-
- int system_is_up(void)
- {
- return system_state == SYSTEM_RUNNING;
- }
- EXPORT_SYMBOL(system_is_up);
-
-In function prototypes, include parameter names with their data types.
-Although this is not required by the C language, it is preferred in Linux
-because it is a simple way to add valuable information for the reader.
-
-
-7) Centralized exiting of functions
------------------------------------
-
-Albeit deprecated by some people, the equivalent of the goto statement is
-used frequently by compilers in form of the unconditional jump instruction.
-
-The goto statement comes in handy when a function exits from multiple
-locations and some common work such as cleanup has to be done. If there is no
-cleanup needed then just return directly.
-
-Choose label names which say what the goto does or why the goto exists. An
-example of a good name could be ``out_free_buffer:`` if the goto frees ``buffer``.
-Avoid using GW-BASIC names like ``err1:`` and ``err2:``, as you would have to
-renumber them if you ever add or remove exit paths, and they make correctness
-difficult to verify anyway.
-
-The rationale for using gotos is:
-
-- unconditional statements are easier to understand and follow
-- nesting is reduced
-- errors by not updating individual exit points when making
- modifications are prevented
-- saves the compiler work to optimize redundant code away ;)
-
-.. code-block:: c
-
- int fun(int a)
- {
- int result = 0;
- char *buffer;
-
- buffer = kmalloc(SIZE, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- if (condition1) {
- while (loop1) {
- ...
- }
- result = 1;
- goto out_buffer;
- }
- ...
- out_free_buffer:
- kfree(buffer);
- return result;
- }
-
-A common type of bug to be aware of is ``one err bugs`` which look like this:
-
-.. code-block:: c
-
- err:
- kfree(foo->bar);
- kfree(foo);
- return ret;
-
-The bug in this code is that on some exit paths ``foo`` is NULL. Normally the
-fix for this is to split it up into two error labels ``err_free_bar:`` and
-``err_free_foo:``:
-
-.. code-block:: c
-
- err_free_bar:
- kfree(foo->bar);
- err_free_foo:
- kfree(foo);
- return ret;
-
-Ideally you should simulate errors to test all exit paths.
-
-
-8) Commenting
--------------
-
-Comments are good, but there is also a danger of over-commenting. NEVER
-try to explain HOW your code works in a comment: it's much better to
-write the code so that the **working** is obvious, and it's a waste of
-time to explain badly written code.
-
-Generally, you want your comments to tell WHAT your code does, not HOW.
-Also, try to avoid putting comments inside a function body: if the
-function is so complex that you need to separately comment parts of it,
-you should probably go back to chapter 6 for a while. You can make
-small comments to note or warn about something particularly clever (or
-ugly), but try to avoid excess. Instead, put the comments at the head
-of the function, telling people what it does, and possibly WHY it does
-it.
-
-When commenting the kernel API functions, please use the kernel-doc format.
-See the files Documentation/kernel-documentation.rst and scripts/kernel-doc
-for details.
-
-The preferred style for long (multi-line) comments is:
-
-.. code-block:: c
-
- /*
- * This is the preferred style for multi-line
- * comments in the Linux kernel source code.
- * Please use it consistently.
- *
- * Description: A column of asterisks on the left side,
- * with beginning and ending almost-blank lines.
- */
-
-For files in net/ and drivers/net/ the preferred style for long (multi-line)
-comments is a little different.
-
-.. code-block:: c
-
- /* The preferred comment style for files in net/ and drivers/net
- * looks like this.
- *
- * It is nearly the same as the generally preferred comment style,
- * but there is no initial almost-blank line.
- */
-
-It's also important to comment data, whether they are basic types or derived
-types. To this end, use just one data declaration per line (no commas for
-multiple data declarations). This leaves you room for a small comment on each
-item, explaining its use.
-
-
-9) You've made a mess of it
----------------------------
-
-That's OK, we all do. You've probably been told by your long-time Unix
-user helper that ``GNU emacs`` automatically formats the C sources for
-you, and you've noticed that yes, it does do that, but the defaults it
-uses are less than desirable (in fact, they are worse than random
-typing - an infinite number of monkeys typing into GNU emacs would never
-make a good program).
-
-So, you can either get rid of GNU emacs, or change it to use saner
-values. To do the latter, you can stick the following in your .emacs file:
-
-.. code-block:: none
-
- (defun c-lineup-arglist-tabs-only (ignored)
- "Line up argument lists by tabs, not spaces"
- (let* ((anchor (c-langelem-pos c-syntactic-element))
- (column (c-langelem-2nd-pos c-syntactic-element))
- (offset (- (1+ column) anchor))
- (steps (floor offset c-basic-offset)))
- (* (max steps 1)
- c-basic-offset)))
-
- (add-hook 'c-mode-common-hook
- (lambda ()
- ;; Add kernel style
- (c-add-style
- "linux-tabs-only"
- '("linux" (c-offsets-alist
- (arglist-cont-nonempty
- c-lineup-gcc-asm-reg
- c-lineup-arglist-tabs-only))))))
-
- (add-hook 'c-mode-hook
- (lambda ()
- (let ((filename (buffer-file-name)))
- ;; Enable kernel mode for the appropriate files
- (when (and filename
- (string-match (expand-file-name "~/src/linux-trees")
- filename))
- (setq indent-tabs-mode t)
- (setq show-trailing-whitespace t)
- (c-set-style "linux-tabs-only")))))
-
-This will make emacs go better with the kernel coding style for C
-files below ``~/src/linux-trees``.
-
-But even if you fail in getting emacs to do sane formatting, not
-everything is lost: use ``indent``.
-
-Now, again, GNU indent has the same brain-dead settings that GNU emacs
-has, which is why you need to give it a few command line options.
-However, that's not too bad, because even the makers of GNU indent
-recognize the authority of K&R (the GNU people aren't evil, they are
-just severely misguided in this matter), so you just give indent the
-options ``-kr -i8`` (stands for ``K&R, 8 character indents``), or use
-``scripts/Lindent``, which indents in the latest style.
-
-``indent`` has a lot of options, and especially when it comes to comment
-re-formatting you may want to take a look at the man page. But
-remember: ``indent`` is not a fix for bad programming.
-
-
-10) Kconfig configuration files
--------------------------------
-
-For all of the Kconfig* configuration files throughout the source tree,
-the indentation is somewhat different. Lines under a ``config`` definition
-are indented with one tab, while help text is indented an additional two
-spaces. Example::
-
- config AUDIT
- bool "Auditing support"
- depends on NET
- help
- Enable auditing infrastructure that can be used with another
- kernel subsystem, such as SELinux (which requires this for
- logging of avc messages output). Does not do system-call
- auditing without CONFIG_AUDITSYSCALL.
-
-Seriously dangerous features (such as write support for certain
-filesystems) should advertise this prominently in their prompt string::
-
- config ADFS_FS_RW
- bool "ADFS write support (DANGEROUS)"
- depends on ADFS_FS
- ...
-
-For full documentation on the configuration files, see the file
-Documentation/kbuild/kconfig-language.txt.
-
-
-11) Data structures
--------------------
-
-Data structures that have visibility outside the single-threaded
-environment they are created and destroyed in should always have
-reference counts. In the kernel, garbage collection doesn't exist (and
-outside the kernel garbage collection is slow and inefficient), which
-means that you absolutely **have** to reference count all your uses.
-
-Reference counting means that you can avoid locking, and allows multiple
-users to have access to the data structure in parallel - and not having
-to worry about the structure suddenly going away from under them just
-because they slept or did something else for a while.
-
-Note that locking is **not** a replacement for reference counting.
-Locking is used to keep data structures coherent, while reference
-counting is a memory management technique. Usually both are needed, and
-they are not to be confused with each other.
-
-Many data structures can indeed have two levels of reference counting,
-when there are users of different ``classes``. The subclass count counts
-the number of subclass users, and decrements the global count just once
-when the subclass count goes to zero.
-
-Examples of this kind of ``multi-level-reference-counting`` can be found in
-memory management (``struct mm_struct``: mm_users and mm_count), and in
-filesystem code (``struct super_block``: s_count and s_active).
-
-Remember: if another thread can find your data structure, and you don't
-have a reference count on it, you almost certainly have a bug.
-
-
-12) Macros, Enums and RTL
--------------------------
-
-Names of macros defining constants and labels in enums are capitalized.
-
-.. code-block:: c
-
- #define CONSTANT 0x12345
-
-Enums are preferred when defining several related constants.
-
-CAPITALIZED macro names are appreciated but macros resembling functions
-may be named in lower case.
-
-Generally, inline functions are preferable to macros resembling functions.
-
-Macros with multiple statements should be enclosed in a do - while block:
-
-.. code-block:: c
-
- #define macrofun(a, b, c) \
- do { \
- if (a == 5) \
- do_this(b, c); \
- } while (0)
-
-Things to avoid when using macros:
-
-1) macros that affect control flow:
-
-.. code-block:: c
-
- #define FOO(x) \
- do { \
- if (blah(x) < 0) \
- return -EBUGGERED; \
- } while (0)
-
-is a **very** bad idea. It looks like a function call but exits the ``calling``
-function; don't break the internal parsers of those who will read the code.
-
-2) macros that depend on having a local variable with a magic name:
-
-.. code-block:: c
-
- #define FOO(val) bar(index, val)
-
-might look like a good thing, but it's confusing as hell when one reads the
-code and it's prone to breakage from seemingly innocent changes.
-
-3) macros with arguments that are used as l-values: FOO(x) = y; will
-bite you if somebody e.g. turns FOO into an inline function.
-
-4) forgetting about precedence: macros defining constants using expressions
-must enclose the expression in parentheses. Beware of similar issues with
-macros using parameters.
-
-.. code-block:: c
-
- #define CONSTANT 0x4000
- #define CONSTEXP (CONSTANT | 3)
-
-5) namespace collisions when defining local variables in macros resembling
-functions:
-
-.. code-block:: c
-
- #define FOO(x) \
- ({ \
- typeof(x) ret; \
- ret = calc_ret(x); \
- (ret); \
- })
-
-ret is a common name for a local variable - __foo_ret is less likely
-to collide with an existing variable.
-
-The cpp manual deals with macros exhaustively. The gcc internals manual also
-covers RTL which is used frequently with assembly language in the kernel.
-
-
-13) Printing kernel messages
-----------------------------
-
-Kernel developers like to be seen as literate. Do mind the spelling
-of kernel messages to make a good impression. Do not use crippled
-words like ``dont``; use ``do not`` or ``don't`` instead. Make the messages
-concise, clear, and unambiguous.
-
-Kernel messages do not have to be terminated with a period.
-
-Printing numbers in parentheses (%d) adds no value and should be avoided.
-
-There are a number of driver model diagnostic macros in <linux/device.h>
-which you should use to make sure messages are matched to the right device
-and driver, and are tagged with the right level: dev_err(), dev_warn(),
-dev_info(), and so forth. For messages that aren't associated with a
-particular device, <linux/printk.h> defines pr_notice(), pr_info(),
-pr_warn(), pr_err(), etc.
-
-Coming up with good debugging messages can be quite a challenge; and once
-you have them, they can be a huge help for remote troubleshooting. However
-debug message printing is handled differently than printing other non-debug
-messages. While the other pr_XXX() functions print unconditionally,
-pr_debug() does not; it is compiled out by default, unless either DEBUG is
-defined or CONFIG_DYNAMIC_DEBUG is set. That is true for dev_dbg() also,
-and a related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to
-the ones already enabled by DEBUG.
-
-Many subsystems have Kconfig debug options to turn on -DDEBUG in the
-corresponding Makefile; in other cases specific files #define DEBUG. And
-when a debug message should be unconditionally printed, such as if it is
-already inside a debug-related #ifdef section, printk(KERN_DEBUG ...) can be
-used.
-
-
-14) Allocating memory
----------------------
-
-The kernel provides the following general purpose memory allocators:
-kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and
-vzalloc(). Please refer to the API documentation for further information
-about them.
-
-The preferred form for passing a size of a struct is the following:
-
-.. code-block:: c
-
- p = kmalloc(sizeof(*p), ...);
-
-The alternative form where struct name is spelled out hurts readability and
-introduces an opportunity for a bug when the pointer variable type is changed
-but the corresponding sizeof that is passed to a memory allocator is not.
-
-Casting the return value which is a void pointer is redundant. The conversion
-from void pointer to any other pointer type is guaranteed by the C programming
-language.
-
-The preferred form for allocating an array is the following:
-
-.. code-block:: c
-
- p = kmalloc_array(n, sizeof(...), ...);
-
-The preferred form for allocating a zeroed array is the following:
-
-.. code-block:: c
-
- p = kcalloc(n, sizeof(...), ...);
-
-Both forms check for overflow on the allocation size n * sizeof(...),
-and return NULL if that occurred.
-
-
-15) The inline disease
-----------------------
-
-There appears to be a common misperception that gcc has a magic "make me
-faster" speedup option called ``inline``. While the use of inlines can be
-appropriate (for example as a means of replacing macros, see Chapter 12), it
-very often is not. Abundant use of the inline keyword leads to a much bigger
-kernel, which in turn slows the system as a whole down, due to a bigger
-icache footprint for the CPU and simply because there is less memory
-available for the pagecache. Just think about it; a pagecache miss causes a
-disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
-that can go into these 5 milliseconds.
-
-A reasonable rule of thumb is to not put inline at functions that have more
-than 3 lines of code in them. An exception to this rule are the cases where
-a parameter is known to be a compiletime constant, and as a result of this
-constantness you *know* the compiler will be able to optimize most of your
-function away at compile time. For a good example of this later case, see
-the kmalloc() inline function.
-
-Often people argue that adding inline to functions that are static and used
-only once is always a win since there is no space tradeoff. While this is
-technically correct, gcc is capable of inlining these automatically without
-help, and the maintenance issue of removing the inline when a second user
-appears outweighs the potential value of the hint that tells gcc to do
-something it would have done anyway.
-
-
-16) Function return values and names
-------------------------------------
-
-Functions can return values of many different kinds, and one of the
-most common is a value indicating whether the function succeeded or
-failed. Such a value can be represented as an error-code integer
-(-Exxx = failure, 0 = success) or a ``succeeded`` boolean (0 = failure,
-non-zero = success).
-
-Mixing up these two sorts of representations is a fertile source of
-difficult-to-find bugs. If the C language included a strong distinction
-between integers and booleans then the compiler would find these mistakes
-for us... but it doesn't. To help prevent such bugs, always follow this
-convention::
-
- If the name of a function is an action or an imperative command,
- the function should return an error-code integer. If the name
- is a predicate, the function should return a "succeeded" boolean.
-
-For example, ``add work`` is a command, and the add_work() function returns 0
-for success or -EBUSY for failure. In the same way, ``PCI device present`` is
-a predicate, and the pci_dev_present() function returns 1 if it succeeds in
-finding a matching device or 0 if it doesn't.
-
-All EXPORTed functions must respect this convention, and so should all
-public functions. Private (static) functions need not, but it is
-recommended that they do.
-
-Functions whose return value is the actual result of a computation, rather
-than an indication of whether the computation succeeded, are not subject to
-this rule. Generally they indicate failure by returning some out-of-range
-result. Typical examples would be functions that return pointers; they use
-NULL or the ERR_PTR mechanism to report failure.
-
-
-17) Don't re-invent the kernel macros
--------------------------------------
-
-The header file include/linux/kernel.h contains a number of macros that
-you should use, rather than explicitly coding some variant of them yourself.
-For example, if you need to calculate the length of an array, take advantage
-of the macro
-
-.. code-block:: c
-
- #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-Similarly, if you need to calculate the size of some structure member, use
-
-.. code-block:: c
-
- #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
-
-There are also min() and max() macros that do strict type checking if you
-need them. Feel free to peruse that header file to see what else is already
-defined that you shouldn't reproduce in your code.
-
-
-18) Editor modelines and other cruft
-------------------------------------
-
-Some editors can interpret configuration information embedded in source files,
-indicated with special markers. For example, emacs interprets lines marked
-like this:
-
-.. code-block:: c
-
- -*- mode: c -*-
-
-Or like this:
-
-.. code-block:: c
-
- /*
- Local Variables:
- compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
- End:
- */
-
-Vim interprets markers that look like this:
-
-.. code-block:: c
-
- /* vim:set sw=8 noet */
-
-Do not include any of these in source files. People have their own personal
-editor configurations, and your source files should not override them. This
-includes markers for indentation and mode configuration. People may use their
-own custom mode, or may have some other magic method for making indentation
-work correctly.
-
-
-19) Inline assembly
--------------------
-
-In architecture-specific code, you may need to use inline assembly to interface
-with CPU or platform functionality. Don't hesitate to do so when necessary.
-However, don't use inline assembly gratuitously when C can do the job. You can
-and should poke hardware from C when possible.
-
-Consider writing simple helper functions that wrap common bits of inline
-assembly, rather than repeatedly writing them with slight variations. Remember
-that inline assembly can use C parameters.
-
-Large, non-trivial assembly functions should go in .S files, with corresponding
-C prototypes defined in C header files. The C prototypes for assembly
-functions should use ``asmlinkage``.
-
-You may need to mark your asm statement as volatile, to prevent GCC from
-removing it if GCC doesn't notice any side effects. You don't always need to
-do so, though, and doing so unnecessarily can limit optimization.
-
-When writing a single inline assembly statement containing multiple
-instructions, put each instruction on a separate line in a separate quoted
-string, and end each string except the last with \n\t to properly indent the
-next instruction in the assembly output:
-
-.. code-block:: c
-
- asm ("magic %reg1, #42\n\t"
- "more_magic %reg2, %reg3"
- : /* outputs */ : /* inputs */ : /* clobbers */);
-
-
-20) Conditional Compilation
----------------------------
-
-Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
-files; doing so makes code harder to read and logic harder to follow. Instead,
-use such conditionals in a header file defining functions for use in those .c
-files, providing no-op stub versions in the #else case, and then call those
-functions unconditionally from .c files. The compiler will avoid generating
-any code for the stub calls, producing identical results, but the logic will
-remain easy to follow.
-
-Prefer to compile out entire functions, rather than portions of functions or
-portions of expressions. Rather than putting an ifdef in an expression, factor
-out part or all of the expression into a separate helper function and apply the
-conditional to that function.
-
-If you have a function or variable which may potentially go unused in a
-particular configuration, and the compiler would warn about its definition
-going unused, mark the definition as __maybe_unused rather than wrapping it in
-a preprocessor conditional. (However, if a function or variable *always* goes
-unused, delete it.)
-
-Within code, where possible, use the IS_ENABLED macro to convert a Kconfig
-symbol into a C boolean expression, and use it in a normal C conditional:
-
-.. code-block:: c
-
- if (IS_ENABLED(CONFIG_SOMETHING)) {
- ...
- }
-
-The compiler will constant-fold the conditional away, and include or exclude
-the block of code just as with an #ifdef, so this will not add any runtime
-overhead. However, this approach still allows the C compiler to see the code
-inside the block, and check it for correctness (syntax, types, symbol
-references, etc). Thus, you still have to use an #ifdef if the code inside the
-block references symbols that will not exist if the condition is not met.
-
-At the end of any non-trivial #if or #ifdef block (more than a few lines),
-place a comment after the #endif on the same line, noting the conditional
-expression used. For instance:
-
-.. code-block:: c
-
- #ifdef CONFIG_SOMETHING
- ...
- #endif /* CONFIG_SOMETHING */
-
-
-Appendix I) References
-----------------------
-
-The C Programming Language, Second Edition
-by Brian W. Kernighan and Dennis M. Ritchie.
-Prentice Hall, Inc., 1988.
-ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
-
-The Practice of Programming
-by Brian W. Kernighan and Rob Pike.
-Addison-Wesley, Inc., 1999.
-ISBN 0-201-61586-X.
-
-GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
-gcc internals and indent, all available from http://www.gnu.org/manual/
-
-WG14 is the international standardization working group for the programming
-language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
-
-Kernel CodingStyle, by greg@kroah.com at OLS 2002:
-http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+This file has moved to process/coding-style.rst
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index fdf8232d0eeb..caab9039362f 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -9,12 +9,10 @@
DOCBOOKS := z8530book.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
writing_usb_driver.xml networking.xml \
- kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
+ kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
- debugobjects.xml sh.xml regulator.xml \
- alsa-driver-api.xml writing-an-alsa-driver.xml \
- tracepoint.xml w1.xml \
+ 80211.xml sh.xml regulator.xml w1.xml \
writing_musb_glue_layer.xml crypto-API.xml iio.xml
ifeq ($(DOCBOOKS),)
@@ -264,6 +262,7 @@ clean-files := $(DOCBOOKS) \
$(patsubst %.xml, %.aux.xml, $(DOCBOOKS)) \
$(patsubst %.xml, %.xml.db, $(DOCBOOKS)) \
$(patsubst %.xml, %.xml, $(DOCBOOKS)) \
+ $(patsubst %.xml, .%.xml.cmd, $(DOCBOOKS)) \
$(index)
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
diff --git a/Documentation/DocBook/alsa-driver-api.tmpl b/Documentation/DocBook/alsa-driver-api.tmpl
deleted file mode 100644
index 53f439dcc94b..000000000000
--- a/Documentation/DocBook/alsa-driver-api.tmpl
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header -->
-<!-- ****************************************************** -->
-<book id="ALSA-Driver-API">
- <bookinfo>
- <title>The ALSA Driver API</title>
-
- <legalnotice>
- <para>
- This document is free; 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.
- </para>
-
- <para>
- This document is distributed in the hope that it will be useful,
- but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
- implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
- for more details.
- </para>
-
- <para>
- 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
- </para>
- </legalnotice>
-
- </bookinfo>
-
-<toc></toc>
-
- <chapter><title>Management of Cards and Devices</title>
- <sect1><title>Card Management</title>
-!Esound/core/init.c
- </sect1>
- <sect1><title>Device Components</title>
-!Esound/core/device.c
- </sect1>
- <sect1><title>Module requests and Device File Entries</title>
-!Esound/core/sound.c
- </sect1>
- <sect1><title>Memory Management Helpers</title>
-!Esound/core/memory.c
-!Esound/core/memalloc.c
- </sect1>
- </chapter>
- <chapter><title>PCM API</title>
- <sect1><title>PCM Core</title>
-!Esound/core/pcm.c
-!Esound/core/pcm_lib.c
-!Esound/core/pcm_native.c
-!Iinclude/sound/pcm.h
- </sect1>
- <sect1><title>PCM Format Helpers</title>
-!Esound/core/pcm_misc.c
- </sect1>
- <sect1><title>PCM Memory Management</title>
-!Esound/core/pcm_memory.c
- </sect1>
- <sect1><title>PCM DMA Engine API</title>
-!Esound/core/pcm_dmaengine.c
-!Iinclude/sound/dmaengine_pcm.h
- </sect1>
- </chapter>
- <chapter><title>Control/Mixer API</title>
- <sect1><title>General Control Interface</title>
-!Esound/core/control.c
- </sect1>
- <sect1><title>AC97 Codec API</title>
-!Esound/pci/ac97/ac97_codec.c
-!Esound/pci/ac97/ac97_pcm.c
- </sect1>
- <sect1><title>Virtual Master Control API</title>
-!Esound/core/vmaster.c
-!Iinclude/sound/control.h
- </sect1>
- </chapter>
- <chapter><title>MIDI API</title>
- <sect1><title>Raw MIDI API</title>
-!Esound/core/rawmidi.c
- </sect1>
- <sect1><title>MPU401-UART API</title>
-!Esound/drivers/mpu401/mpu401_uart.c
- </sect1>
- </chapter>
- <chapter><title>Proc Info API</title>
- <sect1><title>Proc Info Interface</title>
-!Esound/core/info.c
- </sect1>
- </chapter>
- <chapter><title>Compress Offload</title>
- <sect1><title>Compress Offload API</title>
-!Esound/core/compress_offload.c
-!Iinclude/uapi/sound/compress_offload.h
-!Iinclude/uapi/sound/compress_params.h
-!Iinclude/sound/compress_driver.h
- </sect1>
- </chapter>
- <chapter><title>ASoC</title>
- <sect1><title>ASoC Core API</title>
-!Iinclude/sound/soc.h
-!Esound/soc/soc-core.c
-<!-- !Esound/soc/soc-cache.c no docbook comments here -->
-!Esound/soc/soc-devres.c
-!Esound/soc/soc-io.c
-!Esound/soc/soc-pcm.c
-!Esound/soc/soc-ops.c
-!Esound/soc/soc-compress.c
- </sect1>
- <sect1><title>ASoC DAPM API</title>
-!Esound/soc/soc-dapm.c
- </sect1>
- <sect1><title>ASoC DMA Engine API</title>
-!Esound/soc/soc-generic-dmaengine-pcm.c
- </sect1>
- </chapter>
- <chapter><title>Miscellaneous Functions</title>
- <sect1><title>Hardware-Dependent Devices API</title>
-!Esound/core/hwdep.c
- </sect1>
- <sect1><title>Jack Abstraction Layer API</title>
-!Iinclude/sound/jack.h
-!Esound/core/jack.c
-!Esound/soc/soc-jack.c
- </sect1>
- <sect1><title>ISA DMA Helpers</title>
-!Esound/core/isadma.c
- </sect1>
- <sect1><title>Other Helper Macros</title>
-!Iinclude/sound/core.h
- </sect1>
- </chapter>
-
-</book>
diff --git a/Documentation/DocBook/debugobjects.tmpl b/Documentation/DocBook/debugobjects.tmpl
deleted file mode 100644
index 7e4f34fde697..000000000000
--- a/Documentation/DocBook/debugobjects.tmpl
+++ /dev/null
@@ -1,443 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="debug-objects-guide">
- <bookinfo>
- <title>Debug objects life time</title>
-
- <authorgroup>
- <author>
- <firstname>Thomas</firstname>
- <surname>Gleixner</surname>
- <affiliation>
- <address>
- <email>tglx@linutronix.de</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
-
- <copyright>
- <year>2008</year>
- <holder>Thomas Gleixner</holder>
- </copyright>
-
- <legalnotice>
- <para>
- This documentation 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.
- </para>
-
- <para>
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- 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
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
- </para>
- </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
- <chapter id="intro">
- <title>Introduction</title>
- <para>
- debugobjects is a generic infrastructure to track the life time
- of kernel objects and validate the operations on those.
- </para>
- <para>
- debugobjects is useful to check for the following error patterns:
- <itemizedlist>
- <listitem><para>Activation of uninitialized objects</para></listitem>
- <listitem><para>Initialization of active objects</para></listitem>
- <listitem><para>Usage of freed/destroyed objects</para></listitem>
- </itemizedlist>
- </para>
- <para>
- debugobjects is not changing the data structure of the real
- object so it can be compiled in with a minimal runtime impact
- and enabled on demand with a kernel command line option.
- </para>
- </chapter>
-
- <chapter id="howto">
- <title>Howto use debugobjects</title>
- <para>
- A kernel subsystem needs to provide a data structure which
- describes the object type and add calls into the debug code at
- appropriate places. The data structure to describe the object
- type needs at minimum the name of the object type. Optional
- functions can and should be provided to fixup detected problems
- so the kernel can continue to work and the debug information can
- be retrieved from a live system instead of hard core debugging
- with serial consoles and stack trace transcripts from the
- monitor.
- </para>
- <para>
- The debug calls provided by debugobjects are:
- <itemizedlist>
- <listitem><para>debug_object_init</para></listitem>
- <listitem><para>debug_object_init_on_stack</para></listitem>
- <listitem><para>debug_object_activate</para></listitem>
- <listitem><para>debug_object_deactivate</para></listitem>
- <listitem><para>debug_object_destroy</para></listitem>
- <listitem><para>debug_object_free</para></listitem>
- <listitem><para>debug_object_assert_init</para></listitem>
- </itemizedlist>
- Each of these functions takes the address of the real object and
- a pointer to the object type specific debug description
- structure.
- </para>
- <para>
- Each detected error is reported in the statistics and a limited
- number of errors are printk'ed including a full stack trace.
- </para>
- <para>
- The statistics are available via /sys/kernel/debug/debug_objects/stats.
- They provide information about the number of warnings and the
- number of successful fixups along with information about the
- usage of the internal tracking objects and the state of the
- internal tracking objects pool.
- </para>
- </chapter>
- <chapter id="debugfunctions">
- <title>Debug functions</title>
- <sect1 id="prototypes">
- <title>Debug object function reference</title>
-!Elib/debugobjects.c
- </sect1>
- <sect1 id="debug_object_init">
- <title>debug_object_init</title>
- <para>
- This function is called whenever the initialization function
- of a real object is called.
- </para>
- <para>
- When the real object is already tracked by debugobjects it is
- checked, whether the object can be initialized. Initializing
- is not allowed for active and destroyed objects. When
- debugobjects detects an error, then it calls the fixup_init
- function of the object type description structure if provided
- by the caller. The fixup function can correct the problem
- before the real initialization of the object happens. E.g. it
- can deactivate an active object in order to prevent damage to
- the subsystem.
- </para>
- <para>
- When the real object is not yet tracked by debugobjects,
- debugobjects allocates a tracker object for the real object
- and sets the tracker object state to ODEBUG_STATE_INIT. It
- verifies that the object is not on the callers stack. If it is
- on the callers stack then a limited number of warnings
- including a full stack trace is printk'ed. The calling code
- must use debug_object_init_on_stack() and remove the object
- before leaving the function which allocated it. See next
- section.
- </para>
- </sect1>
-
- <sect1 id="debug_object_init_on_stack">
- <title>debug_object_init_on_stack</title>
- <para>
- This function is called whenever the initialization function
- of a real object which resides on the stack is called.
- </para>
- <para>
- When the real object is already tracked by debugobjects it is
- checked, whether the object can be initialized. Initializing
- is not allowed for active and destroyed objects. When
- debugobjects detects an error, then it calls the fixup_init
- function of the object type description structure if provided
- by the caller. The fixup function can correct the problem
- before the real initialization of the object happens. E.g. it
- can deactivate an active object in order to prevent damage to
- the subsystem.
- </para>
- <para>
- When the real object is not yet tracked by debugobjects
- debugobjects allocates a tracker object for the real object
- and sets the tracker object state to ODEBUG_STATE_INIT. It
- verifies that the object is on the callers stack.
- </para>
- <para>
- An object which is on the stack must be removed from the
- tracker by calling debug_object_free() before the function
- which allocates the object returns. Otherwise we keep track of
- stale objects.
- </para>
- </sect1>
-
- <sect1 id="debug_object_activate">
- <title>debug_object_activate</title>
- <para>
- This function is called whenever the activation function of a
- real object is called.
- </para>
- <para>
- When the real object is already tracked by debugobjects it is
- checked, whether the object can be activated. Activating is
- not allowed for active and destroyed objects. When
- debugobjects detects an error, then it calls the
- fixup_activate function of the object type description
- structure if provided by the caller. The fixup function can
- correct the problem before the real activation of the object
- happens. E.g. it can deactivate an active object in order to
- prevent damage to the subsystem.
- </para>
- <para>
- When the real object is not yet tracked by debugobjects then
- the fixup_activate function is called if available. This is
- necessary to allow the legitimate activation of statically
- allocated and initialized objects. The fixup function checks
- whether the object is valid and calls the debug_objects_init()
- function to initialize the tracking of this object.
- </para>
- <para>
- When the activation is legitimate, then the state of the
- associated tracker object is set to ODEBUG_STATE_ACTIVE.
- </para>
- </sect1>
-
- <sect1 id="debug_object_deactivate">
- <title>debug_object_deactivate</title>
- <para>
- This function is called whenever the deactivation function of
- a real object is called.
- </para>
- <para>
- When the real object is tracked by debugobjects it is checked,
- whether the object can be deactivated. Deactivating is not
- allowed for untracked or destroyed objects.
- </para>
- <para>
- When the deactivation is legitimate, then the state of the
- associated tracker object is set to ODEBUG_STATE_INACTIVE.
- </para>
- </sect1>
-
- <sect1 id="debug_object_destroy">
- <title>debug_object_destroy</title>
- <para>
- This function is called to mark an object destroyed. This is
- useful to prevent the usage of invalid objects, which are
- still available in memory: either statically allocated objects
- or objects which are freed later.
- </para>
- <para>
- When the real object is tracked by debugobjects it is checked,
- whether the object can be destroyed. Destruction is not
- allowed for active and destroyed objects. When debugobjects
- detects an error, then it calls the fixup_destroy function of
- the object type description structure if provided by the
- caller. The fixup function can correct the problem before the
- real destruction of the object happens. E.g. it can deactivate
- an active object in order to prevent damage to the subsystem.
- </para>
- <para>
- When the destruction is legitimate, then the state of the
- associated tracker object is set to ODEBUG_STATE_DESTROYED.
- </para>
- </sect1>
-
- <sect1 id="debug_object_free">
- <title>debug_object_free</title>
- <para>
- This function is called before an object is freed.
- </para>
- <para>
- When the real object is tracked by debugobjects it is checked,
- whether the object can be freed. Free is not allowed for
- active objects. When debugobjects detects an error, then it
- calls the fixup_free function of the object type description
- structure if provided by the caller. The fixup function can
- correct the problem before the real free of the object
- happens. E.g. it can deactivate an active object in order to
- prevent damage to the subsystem.
- </para>
- <para>
- Note that debug_object_free removes the object from the
- tracker. Later usage of the object is detected by the other
- debug checks.
- </para>
- </sect1>
-
- <sect1 id="debug_object_assert_init">
- <title>debug_object_assert_init</title>
- <para>
- This function is called to assert that an object has been
- initialized.
- </para>
- <para>
- When the real object is not tracked by debugobjects, it calls
- fixup_assert_init of the object type description structure
- provided by the caller, with the hardcoded object state
- ODEBUG_NOT_AVAILABLE. The fixup function can correct the problem
- by calling debug_object_init and other specific initializing
- functions.
- </para>
- <para>
- When the real object is already tracked by debugobjects it is
- ignored.
- </para>
- </sect1>
- </chapter>
- <chapter id="fixupfunctions">
- <title>Fixup functions</title>
- <sect1 id="debug_obj_descr">
- <title>Debug object type description structure</title>
-!Iinclude/linux/debugobjects.h
- </sect1>
- <sect1 id="fixup_init">
- <title>fixup_init</title>
- <para>
- This function is called from the debug code whenever a problem
- in debug_object_init is detected. The function takes the
- address of the object and the state which is currently
- recorded in the tracker.
- </para>
- <para>
- Called from debug_object_init when the object state is:
- <itemizedlist>
- <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
- </itemizedlist>
- </para>
- <para>
- The function returns true when the fixup was successful,
- otherwise false. The return value is used to update the
- statistics.
- </para>
- <para>
- Note, that the function needs to call the debug_object_init()
- function again, after the damage has been repaired in order to
- keep the state consistent.
- </para>
- </sect1>
-
- <sect1 id="fixup_activate">
- <title>fixup_activate</title>
- <para>
- This function is called from the debug code whenever a problem
- in debug_object_activate is detected.
- </para>
- <para>
- Called from debug_object_activate when the object state is:
- <itemizedlist>
- <listitem><para>ODEBUG_STATE_NOTAVAILABLE</para></listitem>
- <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
- </itemizedlist>
- </para>
- <para>
- The function returns true when the fixup was successful,
- otherwise false. The return value is used to update the
- statistics.
- </para>
- <para>
- Note that the function needs to call the debug_object_activate()
- function again after the damage has been repaired in order to
- keep the state consistent.
- </para>
- <para>
- The activation of statically initialized objects is a special
- case. When debug_object_activate() has no tracked object for
- this object address then fixup_activate() is called with
- object state ODEBUG_STATE_NOTAVAILABLE. The fixup function
- needs to check whether this is a legitimate case of a
- statically initialized object or not. In case it is it calls
- debug_object_init() and debug_object_activate() to make the
- object known to the tracker and marked active. In this case
- the function should return false because this is not a real
- fixup.
- </para>
- </sect1>
-
- <sect1 id="fixup_destroy">
- <title>fixup_destroy</title>
- <para>
- This function is called from the debug code whenever a problem
- in debug_object_destroy is detected.
- </para>
- <para>
- Called from debug_object_destroy when the object state is:
- <itemizedlist>
- <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
- </itemizedlist>
- </para>
- <para>
- The function returns true when the fixup was successful,
- otherwise false. The return value is used to update the
- statistics.
- </para>
- </sect1>
- <sect1 id="fixup_free">
- <title>fixup_free</title>
- <para>
- This function is called from the debug code whenever a problem
- in debug_object_free is detected. Further it can be called
- from the debug checks in kfree/vfree, when an active object is
- detected from the debug_check_no_obj_freed() sanity checks.
- </para>
- <para>
- Called from debug_object_free() or debug_check_no_obj_freed()
- when the object state is:
- <itemizedlist>
- <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
- </itemizedlist>
- </para>
- <para>
- The function returns true when the fixup was successful,
- otherwise false. The return value is used to update the
- statistics.
- </para>
- </sect1>
- <sect1 id="fixup_assert_init">
- <title>fixup_assert_init</title>
- <para>
- This function is called from the debug code whenever a problem
- in debug_object_assert_init is detected.
- </para>
- <para>
- Called from debug_object_assert_init() with a hardcoded state
- ODEBUG_STATE_NOTAVAILABLE when the object is not found in the
- debug bucket.
- </para>
- <para>
- The function returns true when the fixup was successful,
- otherwise false. The return value is used to update the
- statistics.
- </para>
- <para>
- Note, this function should make sure debug_object_init() is
- called before returning.
- </para>
- <para>
- The handling of statically initialized objects is a special
- case. The fixup function should check if this is a legitimate
- case of a statically initialized object or not. In this case only
- debug_object_init() should be called to make the object known to
- the tracker. Then the function should return false because this
- is not
- a real fixup.
- </para>
- </sect1>
- </chapter>
- <chapter id="bugs">
- <title>Known Bugs And Assumptions</title>
- <para>
- None (knock on wood).
- </para>
- </chapter>
-</book>
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 2a272275c81b..da5c087462b1 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -1208,8 +1208,8 @@ static struct block_device_operations opt_fops = {
<listitem>
<para>
- Finally, don't forget to read <filename>Documentation/SubmittingPatches</filename>
- and possibly <filename>Documentation/SubmittingDrivers</filename>.
+ Finally, don't forget to read <filename>Documentation/process/submitting-patches.rst</filename>
+ and possibly <filename>Documentation/process/submitting-drivers.rst</filename>.
</para>
</listitem>
</itemizedlist>
diff --git a/Documentation/DocBook/tracepoint.tmpl b/Documentation/DocBook/tracepoint.tmpl
deleted file mode 100644
index b57a9ede3224..000000000000
--- a/Documentation/DocBook/tracepoint.tmpl
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="Tracepoints">
- <bookinfo>
- <title>The Linux Kernel Tracepoint API</title>
-
- <authorgroup>
- <author>
- <firstname>Jason</firstname>
- <surname>Baron</surname>
- <affiliation>
- <address>
- <email>jbaron@redhat.com</email>
- </address>
- </affiliation>
- </author>
- <author>
- <firstname>William</firstname>
- <surname>Cohen</surname>
- <affiliation>
- <address>
- <email>wcohen@redhat.com</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
-
- <legalnotice>
- <para>
- This documentation 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.
- </para>
-
- <para>
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- 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
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
- </para>
- </legalnotice>
- </bookinfo>
-
- <toc></toc>
- <chapter id="intro">
- <title>Introduction</title>
- <para>
- Tracepoints are static probe points that are located in strategic points
- throughout the kernel. 'Probes' register/unregister with tracepoints
- via a callback mechanism. The 'probes' are strictly typed functions that
- are passed a unique set of parameters defined by each tracepoint.
- </para>
-
- <para>
- From this simple callback mechanism, 'probes' can be used to profile, debug,
- and understand kernel behavior. There are a number of tools that provide a
- framework for using 'probes'. These tools include Systemtap, ftrace, and
- LTTng.
- </para>
-
- <para>
- Tracepoints are defined in a number of header files via various macros. Thus,
- the purpose of this document is to provide a clear accounting of the available
- tracepoints. The intention is to understand not only what tracepoints are
- available but also to understand where future tracepoints might be added.
- </para>
-
- <para>
- The API presented has functions of the form:
- <function>trace_tracepointname(function parameters)</function>. These are the
- tracepoints callbacks that are found throughout the code. Registering and
- unregistering probes with these callback sites is covered in the
- <filename>Documentation/trace/*</filename> directory.
- </para>
- </chapter>
-
- <chapter id="irq">
- <title>IRQ</title>
-!Iinclude/trace/events/irq.h
- </chapter>
-
- <chapter id="signal">
- <title>SIGNAL</title>
-!Iinclude/trace/events/signal.h
- </chapter>
-
- <chapter id="block">
- <title>Block IO</title>
-!Iinclude/trace/events/block.h
- </chapter>
-
- <chapter id="workqueue">
- <title>Workqueue</title>
-!Iinclude/trace/events/workqueue.h
- </chapter>
-</book>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index cd0e452dfed5..5210f8a577c6 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -46,6 +46,13 @@ GPL version 2.
<revhistory>
<revision>
+ <revnumber>0.10</revnumber>
+ <date>2016-10-17</date>
+ <authorinitials>sch</authorinitials>
+ <revremark>Added generic hyperv driver
+ </revremark>
+ </revision>
+ <revision>
<revnumber>0.9</revnumber>
<date>2009-07-16</date>
<authorinitials>mst</authorinitials>
@@ -1033,6 +1040,61 @@ int main()
</chapter>
+<chapter id="uio_hv_generic" xreflabel="Using Generic driver for Hyper-V VMBUS">
+<?dbhtml filename="uio_hv_generic.html"?>
+<title>Generic Hyper-V UIO driver</title>
+ <para>
+ The generic driver is a kernel module named uio_hv_generic.
+ It supports devices on the Hyper-V VMBus similar to uio_pci_generic
+ on PCI bus.
+ </para>
+
+<sect1 id="uio_hv_generic_binding">
+<title>Making the driver recognize the device</title>
+ <para>
+Since the driver does not declare any device GUID's, it will not get loaded
+automatically and will not automatically bind to any devices, you must load it
+and allocate id to the driver yourself. For example, to use the network device
+GUID:
+ <programlisting>
+ modprobe uio_hv_generic
+ echo &quot;f8615163-df3e-46c5-913f-f2d2f965ed0e&quot; &gt; /sys/bus/vmbus/drivers/uio_hv_generic/new_id
+ </programlisting>
+ </para>
+ <para>
+If there already is a hardware specific kernel driver for the device, the
+generic driver still won't bind to it, in this case if you want to use the
+generic driver (why would you?) you'll have to manually unbind the hardware
+specific driver and bind the generic driver, like this:
+ <programlisting>
+ echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 &gt; /sys/bus/vmbus/drivers/hv_netvsc/unbind
+ echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 &gt; /sys/bus/vmbus/drivers/uio_hv_generic/bind
+ </programlisting>
+ </para>
+ <para>
+You can verify that the device has been bound to the driver
+by looking for it in sysfs, for example like the following:
+ <programlisting>
+ ls -l /sys/bus/vmbus/devices/vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver
+ </programlisting>
+Which if successful should print
+ <programlisting>
+ .../vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver -&gt; ../../../bus/vmbus/drivers/uio_hv_generic
+ </programlisting>
+ </para>
+</sect1>
+
+<sect1 id="uio_hv_generic_internals">
+<title>Things to know about uio_hv_generic</title>
+ <para>
+On each interrupt, uio_hv_generic sets the Interrupt Disable bit.
+This prevents the device from generating further interrupts
+until the bit is cleared. The userspace driver should clear this
+bit before blocking and waiting for more interrupts.
+ </para>
+</sect1>
+</chapter>
+
<appendix id="app1">
<title>Further information</title>
<itemizedlist>
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
deleted file mode 100644
index bc776be0f19c..000000000000
--- a/Documentation/DocBook/usb.tmpl
+++ /dev/null
@@ -1,992 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="Linux-USB-API">
- <bookinfo>
- <title>The Linux-USB Host Side API</title>
-
- <legalnotice>
- <para>
- This documentation 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.
- </para>
-
- <para>
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- 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
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
- </para>
- </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-<chapter id="intro">
- <title>Introduction to USB on Linux</title>
-
- <para>A Universal Serial Bus (USB) is used to connect a host,
- such as a PC or workstation, to a number of peripheral
- devices. USB uses a tree structure, with the host as the
- root (the system's master), hubs as interior nodes, and
- peripherals as leaves (and slaves).
- Modern PCs support several such trees of USB devices, usually
- one USB 2.0 tree (480 Mbit/sec each) with
- a few USB 1.1 trees (12 Mbit/sec each) that are used when you
- connect a USB 1.1 device directly to the machine's "root hub".
- </para>
-
- <para>That master/slave asymmetry was designed-in for a number of
- reasons, one being ease of use. It is not physically possible to
- assemble (legal) USB cables incorrectly: all upstream "to the host"
- connectors are the rectangular type (matching the sockets on
- root hubs), and all downstream connectors are the squarish type
- (or they are built into the peripheral).
- Also, the host software doesn't need to deal with distributed
- auto-configuration since the pre-designated master node manages all that.
- And finally, at the electrical level, bus protocol overhead is reduced by
- eliminating arbitration and moving scheduling into the host software.
- </para>
-
- <para>USB 1.0 was announced in January 1996 and was revised
- as USB 1.1 (with improvements in hub specification and
- support for interrupt-out transfers) in September 1998.
- USB 2.0 was released in April 2000, adding high-speed
- transfers and transaction-translating hubs (used for USB 1.1
- and 1.0 backward compatibility).
- </para>
-
- <para>Kernel developers added USB support to Linux early in the 2.2 kernel
- series, shortly before 2.3 development forked. Updates from 2.3 were
- regularly folded back into 2.2 releases, which improved reliability and
- brought <filename>/sbin/hotplug</filename> support as well more drivers.
- Such improvements were continued in the 2.5 kernel series, where they added
- USB 2.0 support, improved performance, and made the host controller drivers
- (HCDs) more consistent. They also simplified the API (to make bugs less
- likely) and added internal "kerneldoc" documentation.
- </para>
-
- <para>Linux can run inside USB devices as well as on
- the hosts that control the devices.
- But USB device drivers running inside those peripherals
- don't do the same things as the ones running inside hosts,
- so they've been given a different name:
- <emphasis>gadget drivers</emphasis>.
- This document does not cover gadget drivers.
- </para>
-
- </chapter>
-
-<chapter id="host">
- <title>USB Host-Side API Model</title>
-
- <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
- There are two. One is intended for
- <emphasis>general-purpose</emphasis> drivers (exposed through
- driver frameworks), and the other is for drivers that are
- <emphasis>part of the core</emphasis>.
- Such core drivers include the <emphasis>hub</emphasis> driver
- (which manages trees of USB devices) and several different kinds
- of <emphasis>host controller drivers</emphasis>,
- which control individual busses.
- </para>
-
- <para>The device model seen by USB drivers is relatively complex.
- </para>
-
- <itemizedlist>
-
- <listitem><para>USB supports four kinds of data transfers
- (control, bulk, interrupt, and isochronous). Two of them (control
- and bulk) use bandwidth as it's available,
- while the other two (interrupt and isochronous)
- are scheduled to provide guaranteed bandwidth.
- </para></listitem>
-
- <listitem><para>The device description model includes one or more
- "configurations" per device, only one of which is active at a time.
- Devices that are capable of high-speed operation must also support
- full-speed configurations, along with a way to ask about the
- "other speed" configurations which might be used.
- </para></listitem>
-
- <listitem><para>Configurations have one or more "interfaces", each
- of which may have "alternate settings". Interfaces may be
- standardized by USB "Class" specifications, or may be specific to
- a vendor or device.</para>
-
- <para>USB device drivers actually bind to interfaces, not devices.
- Think of them as "interface drivers", though you
- may not see many devices where the distinction is important.
- <emphasis>Most USB devices are simple, with only one configuration,
- one interface, and one alternate setting.</emphasis>
- </para></listitem>
-
- <listitem><para>Interfaces have one or more "endpoints", each of
- which supports one type and direction of data transfer such as
- "bulk out" or "interrupt in". The entire configuration may have
- up to sixteen endpoints in each direction, allocated as needed
- among all the interfaces.
- </para></listitem>
-
- <listitem><para>Data transfer on USB is packetized; each endpoint
- has a maximum packet size.
- Drivers must often be aware of conventions such as flagging the end
- of bulk transfers using "short" (including zero length) packets.
- </para></listitem>
-
- <listitem><para>The Linux USB API supports synchronous calls for
- control and bulk messages.
- It also supports asynchronous calls for all kinds of data transfer,
- using request structures called "URBs" (USB Request Blocks).
- </para></listitem>
-
- </itemizedlist>
-
- <para>Accordingly, the USB Core API exposed to device drivers
- covers quite a lot of territory. You'll probably need to consult
- the USB 2.0 specification, available online from www.usb.org at
- no cost, as well as class or device specifications.
- </para>
-
- <para>The only host-side drivers that actually touch hardware
- (reading/writing registers, handling IRQs, and so on) are the HCDs.
- In theory, all HCDs provide the same functionality through the same
- API. In practice, that's becoming more true on the 2.5 kernels,
- but there are still differences that crop up especially with
- fault handling. Different controllers don't necessarily report
- the same aspects of failures, and recovery from faults (including
- software-induced ones like unlinking an URB) isn't yet fully
- consistent.
- Device driver authors should make a point of doing disconnect
- testing (while the device is active) with each different host
- controller driver, to make sure drivers don't have bugs of
- their own as well as to make sure they aren't relying on some
- HCD-specific behavior.
- (You will need external USB 1.1 and/or
- USB 2.0 hubs to perform all those tests.)
- </para>
-
- </chapter>
-
-<chapter id="types"><title>USB-Standard Types</title>
-
- <para>In <filename>&lt;linux/usb/ch9.h&gt;</filename> you will find
- the USB data types defined in chapter 9 of the USB specification.
- These data types are used throughout USB, and in APIs including
- this host side API, gadget APIs, and usbfs.
- </para>
-
-!Iinclude/linux/usb/ch9.h
-
- </chapter>
-
-<chapter id="hostside"><title>Host-Side Data Types and Macros</title>
-
- <para>The host side API exposes several layers to drivers, some of
- which are more necessary than others.
- These support lifecycle models for host side drivers
- and devices, and support passing buffers through usbcore to
- some HCD that performs the I/O for the device driver.
- </para>
-
-
-!Iinclude/linux/usb.h
-
- </chapter>
-
- <chapter id="usbcore"><title>USB Core APIs</title>
-
- <para>There are two basic I/O models in the USB API.
- The most elemental one is asynchronous: drivers submit requests
- in the form of an URB, and the URB's completion callback
- handle the next step.
- All USB transfer types support that model, although there
- are special cases for control URBs (which always have setup
- and status stages, but may not have a data stage) and
- isochronous URBs (which allow large packets and include
- per-packet fault reports).
- Built on top of that is synchronous API support, where a
- driver calls a routine that allocates one or more URBs,
- submits them, and waits until they complete.
- There are synchronous wrappers for single-buffer control
- and bulk transfers (which are awkward to use in some
- driver disconnect scenarios), and for scatterlist based
- streaming i/o (bulk or interrupt).
- </para>
-
- <para>USB drivers need to provide buffers that can be
- used for DMA, although they don't necessarily need to
- provide the DMA mapping themselves.
- There are APIs to use used when allocating DMA buffers,
- which can prevent use of bounce buffers on some systems.
- In some cases, drivers may be able to rely on 64bit DMA
- to eliminate another kind of bounce buffer.
- </para>
-
-!Edrivers/usb/core/urb.c
-!Edrivers/usb/core/message.c
-!Edrivers/usb/core/file.c
-!Edrivers/usb/core/driver.c
-!Edrivers/usb/core/usb.c
-!Edrivers/usb/core/hub.c
- </chapter>
-
- <chapter id="hcd"><title>Host Controller APIs</title>
-
- <para>These APIs are only for use by host controller drivers,
- most of which implement standard register interfaces such as
- EHCI, OHCI, or UHCI.
- UHCI was one of the first interfaces, designed by Intel and
- also used by VIA; it doesn't do much in hardware.
- OHCI was designed later, to have the hardware do more work
- (bigger transfers, tracking protocol state, and so on).
- EHCI was designed with USB 2.0; its design has features that
- resemble OHCI (hardware does much more work) as well as
- UHCI (some parts of ISO support, TD list processing).
- </para>
-
- <para>There are host controllers other than the "big three",
- although most PCI based controllers (and a few non-PCI based
- ones) use one of those interfaces.
- Not all host controllers use DMA; some use PIO, and there
- is also a simulator.
- </para>
-
- <para>The same basic APIs are available to drivers for all
- those controllers.
- For historical reasons they are in two layers:
- <structname>struct usb_bus</structname> is a rather thin
- layer that became available in the 2.2 kernels, while
- <structname>struct usb_hcd</structname> is a more featureful
- layer (available in later 2.4 kernels and in 2.5) that
- lets HCDs share common code, to shrink driver size
- and significantly reduce hcd-specific behaviors.
- </para>
-
-!Edrivers/usb/core/hcd.c
-!Edrivers/usb/core/hcd-pci.c
-!Idrivers/usb/core/buffer.c
- </chapter>
-
- <chapter id="usbfs">
- <title>The USB Filesystem (usbfs)</title>
-
- <para>This chapter presents the Linux <emphasis>usbfs</emphasis>.
- You may prefer to avoid writing new kernel code for your
- USB driver; that's the problem that usbfs set out to solve.
- User mode device drivers are usually packaged as applications
- or libraries, and may use usbfs through some programming library
- that wraps it. Such libraries include
- <ulink url="http://libusb.sourceforge.net">libusb</ulink>
- for C/C++, and
- <ulink url="http://jUSB.sourceforge.net">jUSB</ulink> for Java.
- </para>
-
- <note><title>Unfinished</title>
- <para>This particular documentation is incomplete,
- especially with respect to the asynchronous mode.
- As of kernel 2.5.66 the code and this (new) documentation
- need to be cross-reviewed.
- </para>
- </note>
-
- <para>Configure usbfs into Linux kernels by enabling the
- <emphasis>USB filesystem</emphasis> option (CONFIG_USB_DEVICEFS),
- and you get basic support for user mode USB device drivers.
- Until relatively recently it was often (confusingly) called
- <emphasis>usbdevfs</emphasis> although it wasn't solving what
- <emphasis>devfs</emphasis> was.
- Every USB device will appear in usbfs, regardless of whether or
- not it has a kernel driver.
- </para>
-
- <sect1 id="usbfs-files">
- <title>What files are in "usbfs"?</title>
-
- <para>Conventionally mounted at
- <filename>/proc/bus/usb</filename>, usbfs
- features include:
- <itemizedlist>
- <listitem><para><filename>/proc/bus/usb/devices</filename>
- ... a text file
- showing each of the USB devices on known to the kernel,
- and their configuration descriptors.
- You can also poll() this to learn about new devices.
- </para></listitem>
- <listitem><para><filename>/proc/bus/usb/BBB/DDD</filename>
- ... magic files
- exposing the each device's configuration descriptors, and
- supporting a series of ioctls for making device requests,
- including I/O to devices. (Purely for access by programs.)
- </para></listitem>
- </itemizedlist>
- </para>
-
- <para> Each bus is given a number (BBB) based on when it was
- enumerated; within each bus, each device is given a similar
- number (DDD).
- Those BBB/DDD paths are not "stable" identifiers;
- expect them to change even if you always leave the devices
- plugged in to the same hub port.
- <emphasis>Don't even think of saving these in application
- configuration files.</emphasis>
- Stable identifiers are available, for user mode applications
- that want to use them. HID and networking devices expose
- these stable IDs, so that for example you can be sure that
- you told the right UPS to power down its second server.
- "usbfs" doesn't (yet) expose those IDs.
- </para>
-
- </sect1>
-
- <sect1 id="usbfs-fstab">
- <title>Mounting and Access Control</title>
-
- <para>There are a number of mount options for usbfs, which will
- be of most interest to you if you need to override the default
- access control policy.
- That policy is that only root may read or write device files
- (<filename>/proc/bus/BBB/DDD</filename>) although anyone may read
- the <filename>devices</filename>
- or <filename>drivers</filename> files.
- I/O requests to the device also need the CAP_SYS_RAWIO capability,
- </para>
-
- <para>The significance of that is that by default, all user mode
- device drivers need super-user privileges.
- You can change modes or ownership in a driver setup
- when the device hotplugs, or maye just start the
- driver right then, as a privileged server (or some activity
- within one).
- That's the most secure approach for multi-user systems,
- but for single user systems ("trusted" by that user)
- it's more convenient just to grant everyone all access
- (using the <emphasis>devmode=0666</emphasis> option)
- so the driver can start whenever it's needed.
- </para>
-
- <para>The mount options for usbfs, usable in /etc/fstab or
- in command line invocations of <emphasis>mount</emphasis>, are:
-
- <variablelist>
- <varlistentry>
- <term><emphasis>busgid</emphasis>=NNNNN</term>
- <listitem><para>Controls the GID used for the
- /proc/bus/usb/BBB
- directories. (Default: 0)</para></listitem></varlistentry>
- <varlistentry><term><emphasis>busmode</emphasis>=MMM</term>
- <listitem><para>Controls the file mode used for the
- /proc/bus/usb/BBB
- directories. (Default: 0555)
- </para></listitem></varlistentry>
- <varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term>
- <listitem><para>Controls the UID used for the
- /proc/bus/usb/BBB
- directories. (Default: 0)</para></listitem></varlistentry>
-
- <varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term>
- <listitem><para>Controls the GID used for the
- /proc/bus/usb/BBB/DDD
- files. (Default: 0)</para></listitem></varlistentry>
- <varlistentry><term><emphasis>devmode</emphasis>=MMM</term>
- <listitem><para>Controls the file mode used for the
- /proc/bus/usb/BBB/DDD
- files. (Default: 0644)</para></listitem></varlistentry>
- <varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term>
- <listitem><para>Controls the UID used for the
- /proc/bus/usb/BBB/DDD
- files. (Default: 0)</para></listitem></varlistentry>
-
- <varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term>
- <listitem><para>Controls the GID used for the
- /proc/bus/usb/devices and drivers files.
- (Default: 0)</para></listitem></varlistentry>
- <varlistentry><term><emphasis>listmode</emphasis>=MMM</term>
- <listitem><para>Controls the file mode used for the
- /proc/bus/usb/devices and drivers files.
- (Default: 0444)</para></listitem></varlistentry>
- <varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term>
- <listitem><para>Controls the UID used for the
- /proc/bus/usb/devices and drivers files.
- (Default: 0)</para></listitem></varlistentry>
- </variablelist>
-
- </para>
-
- <para>Note that many Linux distributions hard-wire the mount options
- for usbfs in their init scripts, such as
- <filename>/etc/rc.d/rc.sysinit</filename>,
- rather than making it easy to set this per-system
- policy in <filename>/etc/fstab</filename>.
- </para>
-
- </sect1>
-
- <sect1 id="usbfs-devices">
- <title>/proc/bus/usb/devices</title>
-
- <para>This file is handy for status viewing tools in user
- mode, which can scan the text format and ignore most of it.
- More detailed device status (including class and vendor
- status) is available from device-specific files.
- For information about the current format of this file,
- see the
- <filename>Documentation/usb/proc_usb_info.txt</filename>
- file in your Linux kernel sources.
- </para>
-
- <para>This file, in combination with the poll() system call, can
- also be used to detect when devices are added or removed:
-<programlisting>int fd;
-struct pollfd pfd;
-
-fd = open("/proc/bus/usb/devices", O_RDONLY);
-pfd = { fd, POLLIN, 0 };
-for (;;) {
- /* The first time through, this call will return immediately. */
- poll(&amp;pfd, 1, -1);
-
- /* To see what's changed, compare the file's previous and current
- contents or scan the filesystem. (Scanning is more precise.) */
-}</programlisting>
- Note that this behavior is intended to be used for informational
- and debug purposes. It would be more appropriate to use programs
- such as udev or HAL to initialize a device or start a user-mode
- helper program, for instance.
- </para>
- </sect1>
-
- <sect1 id="usbfs-bbbddd">
- <title>/proc/bus/usb/BBB/DDD</title>
-
- <para>Use these files in one of these basic ways:
- </para>
-
- <para><emphasis>They can be read,</emphasis>
- producing first the device descriptor
- (18 bytes) and then the descriptors for the current configuration.
- See the USB 2.0 spec for details about those binary data formats.
- You'll need to convert most multibyte values from little endian
- format to your native host byte order, although a few of the
- fields in the device descriptor (both of the BCD-encoded fields,
- and the vendor and product IDs) will be byteswapped for you.
- Note that configuration descriptors include descriptors for
- interfaces, altsettings, endpoints, and maybe additional
- class descriptors.
- </para>
-
- <para><emphasis>Perform USB operations</emphasis> using
- <emphasis>ioctl()</emphasis> requests to make endpoint I/O
- requests (synchronously or asynchronously) or manage
- the device.
- These requests need the CAP_SYS_RAWIO capability,
- as well as filesystem access permissions.
- Only one ioctl request can be made on one of these
- device files at a time.
- This means that if you are synchronously reading an endpoint
- from one thread, you won't be able to write to a different
- endpoint from another thread until the read completes.
- This works for <emphasis>half duplex</emphasis> protocols,
- but otherwise you'd use asynchronous i/o requests.
- </para>
-
- </sect1>
-
-
- <sect1 id="usbfs-lifecycle">
- <title>Life Cycle of User Mode Drivers</title>
-
- <para>Such a driver first needs to find a device file
- for a device it knows how to handle.
- Maybe it was told about it because a
- <filename>/sbin/hotplug</filename> event handling agent
- chose that driver to handle the new device.
- Or maybe it's an application that scans all the
- /proc/bus/usb device files, and ignores most devices.
- In either case, it should <function>read()</function> all
- the descriptors from the device file,
- and check them against what it knows how to handle.
- It might just reject everything except a particular
- vendor and product ID, or need a more complex policy.
- </para>
-
- <para>Never assume there will only be one such device
- on the system at a time!
- If your code can't handle more than one device at
- a time, at least detect when there's more than one, and
- have your users choose which device to use.
- </para>
-
- <para>Once your user mode driver knows what device to use,
- it interacts with it in either of two styles.
- The simple style is to make only control requests; some
- devices don't need more complex interactions than those.
- (An example might be software using vendor-specific control
- requests for some initialization or configuration tasks,
- with a kernel driver for the rest.)
- </para>
-
- <para>More likely, you need a more complex style driver:
- one using non-control endpoints, reading or writing data
- and claiming exclusive use of an interface.
- <emphasis>Bulk</emphasis> transfers are easiest to use,
- but only their sibling <emphasis>interrupt</emphasis> transfers
- work with low speed devices.
- Both interrupt and <emphasis>isochronous</emphasis> transfers
- offer service guarantees because their bandwidth is reserved.
- Such "periodic" transfers are awkward to use through usbfs,
- unless you're using the asynchronous calls. However, interrupt
- transfers can also be used in a synchronous "one shot" style.
- </para>
-
- <para>Your user-mode driver should never need to worry
- about cleaning up request state when the device is
- disconnected, although it should close its open file
- descriptors as soon as it starts seeing the ENODEV
- errors.
- </para>
-
- </sect1>
-
- <sect1 id="usbfs-ioctl"><title>The ioctl() Requests</title>
-
- <para>To use these ioctls, you need to include the following
- headers in your userspace program:
-<programlisting>#include &lt;linux/usb.h&gt;
-#include &lt;linux/usbdevice_fs.h&gt;
-#include &lt;asm/byteorder.h&gt;</programlisting>
- The standard USB device model requests, from "Chapter 9" of
- the USB 2.0 specification, are automatically included from
- the <filename>&lt;linux/usb/ch9.h&gt;</filename> header.
- </para>
-
- <para>Unless noted otherwise, the ioctl requests
- described here will
- update the modification time on the usbfs file to which
- they are applied (unless they fail).
- A return of zero indicates success; otherwise, a
- standard USB error code is returned. (These are
- documented in
- <filename>Documentation/usb/error-codes.txt</filename>
- in your kernel sources.)
- </para>
-
- <para>Each of these files multiplexes access to several
- I/O streams, one per endpoint.
- Each device has one control endpoint (endpoint zero)
- which supports a limited RPC style RPC access.
- Devices are configured
- by hub_wq (in the kernel) setting a device-wide
- <emphasis>configuration</emphasis> that affects things
- like power consumption and basic functionality.
- The endpoints are part of USB <emphasis>interfaces</emphasis>,
- which may have <emphasis>altsettings</emphasis>
- affecting things like which endpoints are available.
- Many devices only have a single configuration and interface,
- so drivers for them will ignore configurations and altsettings.
- </para>
-
-
- <sect2 id="usbfs-mgmt">
- <title>Management/Status Requests</title>
-
- <para>A number of usbfs requests don't deal very directly
- with device I/O.
- They mostly relate to device management and status.
- These are all synchronous requests.
- </para>
-
- <variablelist>
-
- <varlistentry><term>USBDEVFS_CLAIMINTERFACE</term>
- <listitem><para>This is used to force usbfs to
- claim a specific interface,
- which has not previously been claimed by usbfs or any other
- kernel driver.
- The ioctl parameter is an integer holding the number of
- the interface (bInterfaceNumber from descriptor).
- </para><para>
- Note that if your driver doesn't claim an interface
- before trying to use one of its endpoints, and no
- other driver has bound to it, then the interface is
- automatically claimed by usbfs.
- </para><para>
- This claim will be released by a RELEASEINTERFACE ioctl,
- or by closing the file descriptor.
- File modification time is not updated by this request.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_CONNECTINFO</term>
- <listitem><para>Says whether the device is lowspeed.
- The ioctl parameter points to a structure like this:
-<programlisting>struct usbdevfs_connectinfo {
- unsigned int devnum;
- unsigned char slow;
-}; </programlisting>
- File modification time is not updated by this request.
- </para><para>
- <emphasis>You can't tell whether a "not slow"
- device is connected at high speed (480 MBit/sec)
- or just full speed (12 MBit/sec).</emphasis>
- You should know the devnum value already,
- it's the DDD value of the device file name.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_GETDRIVER</term>
- <listitem><para>Returns the name of the kernel driver
- bound to a given interface (a string). Parameter
- is a pointer to this structure, which is modified:
-<programlisting>struct usbdevfs_getdriver {
- unsigned int interface;
- char driver[USBDEVFS_MAXDRIVERNAME + 1];
-};</programlisting>
- File modification time is not updated by this request.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_IOCTL</term>
- <listitem><para>Passes a request from userspace through
- to a kernel driver that has an ioctl entry in the
- <emphasis>struct usb_driver</emphasis> it registered.
-<programlisting>struct usbdevfs_ioctl {
- int ifno;
- int ioctl_code;
- void *data;
-};
-
-/* user mode call looks like this.
- * 'request' becomes the driver->ioctl() 'code' parameter.
- * the size of 'param' is encoded in 'request', and that data
- * is copied to or from the driver->ioctl() 'buf' parameter.
- */
-static int
-usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
-{
- struct usbdevfs_ioctl wrapper;
-
- wrapper.ifno = ifno;
- wrapper.ioctl_code = request;
- wrapper.data = param;
-
- return ioctl (fd, USBDEVFS_IOCTL, &amp;wrapper);
-} </programlisting>
- File modification time is not updated by this request.
- </para><para>
- This request lets kernel drivers talk to user mode code
- through filesystem operations even when they don't create
- a character or block special device.
- It's also been used to do things like ask devices what
- device special file should be used.
- Two pre-defined ioctls are used
- to disconnect and reconnect kernel drivers, so
- that user mode code can completely manage binding
- and configuration of devices.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_RELEASEINTERFACE</term>
- <listitem><para>This is used to release the claim usbfs
- made on interface, either implicitly or because of a
- USBDEVFS_CLAIMINTERFACE call, before the file
- descriptor is closed.
- The ioctl parameter is an integer holding the number of
- the interface (bInterfaceNumber from descriptor);
- File modification time is not updated by this request.
- </para><warning><para>
- <emphasis>No security check is made to ensure
- that the task which made the claim is the one
- which is releasing it.
- This means that user mode driver may interfere
- other ones. </emphasis>
- </para></warning></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_RESETEP</term>
- <listitem><para>Resets the data toggle value for an endpoint
- (bulk or interrupt) to DATA0.
- The ioctl parameter is an integer endpoint number
- (1 to 15, as identified in the endpoint descriptor),
- with USB_DIR_IN added if the device's endpoint sends
- data to the host.
- </para><warning><para>
- <emphasis>Avoid using this request.
- It should probably be removed.</emphasis>
- Using it typically means the device and driver will lose
- toggle synchronization. If you really lost synchronization,
- you likely need to completely handshake with the device,
- using a request like CLEAR_HALT
- or SET_INTERFACE.
- </para></warning></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_DROP_PRIVILEGES</term>
- <listitem><para>This is used to relinquish the ability
- to do certain operations which are considered to be
- privileged on a usbfs file descriptor.
- This includes claiming arbitrary interfaces, resetting
- a device on which there are currently claimed interfaces
- from other users, and issuing USBDEVFS_IOCTL calls.
- The ioctl parameter is a 32 bit mask of interfaces
- the user is allowed to claim on this file descriptor.
- You may issue this ioctl more than one time to narrow
- said mask.
- </para></listitem></varlistentry>
- </variablelist>
-
- </sect2>
-
- <sect2 id="usbfs-sync">
- <title>Synchronous I/O Support</title>
-
- <para>Synchronous requests involve the kernel blocking
- until the user mode request completes, either by
- finishing successfully or by reporting an error.
- In most cases this is the simplest way to use usbfs,
- although as noted above it does prevent performing I/O
- to more than one endpoint at a time.
- </para>
-
- <variablelist>
-
- <varlistentry><term>USBDEVFS_BULK</term>
- <listitem><para>Issues a bulk read or write request to the
- device.
- The ioctl parameter is a pointer to this structure:
-<programlisting>struct usbdevfs_bulktransfer {
- unsigned int ep;
- unsigned int len;
- unsigned int timeout; /* in milliseconds */
- void *data;
-};</programlisting>
- </para><para>The "ep" value identifies a
- bulk endpoint number (1 to 15, as identified in an endpoint
- descriptor),
- masked with USB_DIR_IN when referring to an endpoint which
- sends data to the host from the device.
- The length of the data buffer is identified by "len";
- Recent kernels support requests up to about 128KBytes.
- <emphasis>FIXME say how read length is returned,
- and how short reads are handled.</emphasis>.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_CLEAR_HALT</term>
- <listitem><para>Clears endpoint halt (stall) and
- resets the endpoint toggle. This is only
- meaningful for bulk or interrupt endpoints.
- The ioctl parameter is an integer endpoint number
- (1 to 15, as identified in an endpoint descriptor),
- masked with USB_DIR_IN when referring to an endpoint which
- sends data to the host from the device.
- </para><para>
- Use this on bulk or interrupt endpoints which have
- stalled, returning <emphasis>-EPIPE</emphasis> status
- to a data transfer request.
- Do not issue the control request directly, since
- that could invalidate the host's record of the
- data toggle.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_CONTROL</term>
- <listitem><para>Issues a control request to the device.
- The ioctl parameter points to a structure like this:
-<programlisting>struct usbdevfs_ctrltransfer {
- __u8 bRequestType;
- __u8 bRequest;
- __u16 wValue;
- __u16 wIndex;
- __u16 wLength;
- __u32 timeout; /* in milliseconds */
- void *data;
-};</programlisting>
- </para><para>
- The first eight bytes of this structure are the contents
- of the SETUP packet to be sent to the device; see the
- USB 2.0 specification for details.
- The bRequestType value is composed by combining a
- USB_TYPE_* value, a USB_DIR_* value, and a
- USB_RECIP_* value (from
- <emphasis>&lt;linux/usb.h&gt;</emphasis>).
- If wLength is nonzero, it describes the length of the data
- buffer, which is either written to the device
- (USB_DIR_OUT) or read from the device (USB_DIR_IN).
- </para><para>
- At this writing, you can't transfer more than 4 KBytes
- of data to or from a device; usbfs has a limit, and
- some host controller drivers have a limit.
- (That's not usually a problem.)
- <emphasis>Also</emphasis> there's no way to say it's
- not OK to get a short read back from the device.
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_RESET</term>
- <listitem><para>Does a USB level device reset.
- The ioctl parameter is ignored.
- After the reset, this rebinds all device interfaces.
- File modification time is not updated by this request.
- </para><warning><para>
- <emphasis>Avoid using this call</emphasis>
- until some usbcore bugs get fixed,
- since it does not fully synchronize device, interface,
- and driver (not just usbfs) state.
- </para></warning></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_SETINTERFACE</term>
- <listitem><para>Sets the alternate setting for an
- interface. The ioctl parameter is a pointer to a
- structure like this:
-<programlisting>struct usbdevfs_setinterface {
- unsigned int interface;
- unsigned int altsetting;
-}; </programlisting>
- File modification time is not updated by this request.
- </para><para>
- Those struct members are from some interface descriptor
- applying to the current configuration.
- The interface number is the bInterfaceNumber value, and
- the altsetting number is the bAlternateSetting value.
- (This resets each endpoint in the interface.)
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_SETCONFIGURATION</term>
- <listitem><para>Issues the
- <function>usb_set_configuration</function> call
- for the device.
- The parameter is an integer holding the number of
- a configuration (bConfigurationValue from descriptor).
- File modification time is not updated by this request.
- </para><warning><para>
- <emphasis>Avoid using this call</emphasis>
- until some usbcore bugs get fixed,
- since it does not fully synchronize device, interface,
- and driver (not just usbfs) state.
- </para></warning></listitem></varlistentry>
-
- </variablelist>
- </sect2>
-
- <sect2 id="usbfs-async">
- <title>Asynchronous I/O Support</title>
-
- <para>As mentioned above, there are situations where it may be
- important to initiate concurrent operations from user mode code.
- This is particularly important for periodic transfers
- (interrupt and isochronous), but it can be used for other
- kinds of USB requests too.
- In such cases, the asynchronous requests described here
- are essential. Rather than submitting one request and having
- the kernel block until it completes, the blocking is separate.
- </para>
-
- <para>These requests are packaged into a structure that
- resembles the URB used by kernel device drivers.
- (No POSIX Async I/O support here, sorry.)
- It identifies the endpoint type (USBDEVFS_URB_TYPE_*),
- endpoint (number, masked with USB_DIR_IN as appropriate),
- buffer and length, and a user "context" value serving to
- uniquely identify each request.
- (It's usually a pointer to per-request data.)
- Flags can modify requests (not as many as supported for
- kernel drivers).
- </para>
-
- <para>Each request can specify a realtime signal number
- (between SIGRTMIN and SIGRTMAX, inclusive) to request a
- signal be sent when the request completes.
- </para>
-
- <para>When usbfs returns these urbs, the status value
- is updated, and the buffer may have been modified.
- Except for isochronous transfers, the actual_length is
- updated to say how many bytes were transferred; if the
- USBDEVFS_URB_DISABLE_SPD flag is set
- ("short packets are not OK"), if fewer bytes were read
- than were requested then you get an error report.
- </para>
-
-<programlisting>struct usbdevfs_iso_packet_desc {
- unsigned int length;
- unsigned int actual_length;
- unsigned int status;
-};
-
-struct usbdevfs_urb {
- unsigned char type;
- unsigned char endpoint;
- int status;
- unsigned int flags;
- void *buffer;
- int buffer_length;
- int actual_length;
- int start_frame;
- int number_of_packets;
- int error_count;
- unsigned int signr;
- void *usercontext;
- struct usbdevfs_iso_packet_desc iso_frame_desc[];
-};</programlisting>
-
- <para> For these asynchronous requests, the file modification
- time reflects when the request was initiated.
- This contrasts with their use with the synchronous requests,
- where it reflects when requests complete.
- </para>
-
- <variablelist>
-
- <varlistentry><term>USBDEVFS_DISCARDURB</term>
- <listitem><para>
- <emphasis>TBS</emphasis>
- File modification time is not updated by this request.
- </para><para>
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_DISCSIGNAL</term>
- <listitem><para>
- <emphasis>TBS</emphasis>
- File modification time is not updated by this request.
- </para><para>
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_REAPURB</term>
- <listitem><para>
- <emphasis>TBS</emphasis>
- File modification time is not updated by this request.
- </para><para>
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_REAPURBNDELAY</term>
- <listitem><para>
- <emphasis>TBS</emphasis>
- File modification time is not updated by this request.
- </para><para>
- </para></listitem></varlistentry>
-
- <varlistentry><term>USBDEVFS_SUBMITURB</term>
- <listitem><para>
- <emphasis>TBS</emphasis>
- </para><para>
- </para></listitem></varlistentry>
-
- </variablelist>
- </sect2>
-
- </sect1>
-
- </chapter>
-
-</book>
-<!-- vim:syntax=sgml:sw=4
--->
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
deleted file mode 100644
index a27ab9f53fb6..000000000000
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ /dev/null
@@ -1,6206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header -->
-<!-- ****************************************************** -->
-<book id="Writing-an-ALSA-Driver">
- <bookinfo>
- <title>Writing an ALSA Driver</title>
- <author>
- <firstname>Takashi</firstname>
- <surname>Iwai</surname>
- <affiliation>
- <address>
- <email>tiwai@suse.de</email>
- </address>
- </affiliation>
- </author>
-
- <date>Oct 15, 2007</date>
- <edition>0.3.7</edition>
-
- <abstract>
- <para>
- This document describes how to write an ALSA (Advanced Linux
- Sound Architecture) driver.
- </para>
- </abstract>
-
- <legalnotice>
- <para>
- Copyright (c) 2002-2005 Takashi Iwai <email>tiwai@suse.de</email>
- </para>
-
- <para>
- This document is free; 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.
- </para>
-
- <para>
- This document is distributed in the hope that it will be useful,
- but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
- implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
- for more details.
- </para>
-
- <para>
- 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
- </para>
- </legalnotice>
-
- </bookinfo>
-
-<!-- ****************************************************** -->
-<!-- Preface -->
-<!-- ****************************************************** -->
- <preface id="preface">
- <title>Preface</title>
- <para>
- This document describes how to write an
- <ulink url="http://www.alsa-project.org/"><citetitle>
- ALSA (Advanced Linux Sound Architecture)</citetitle></ulink>
- driver. The document focuses mainly on PCI soundcards.
- In the case of other device types, the API might
- be different, too. However, at least the ALSA kernel API is
- consistent, and therefore it would be still a bit help for
- writing them.
- </para>
-
- <para>
- This document targets people who already have enough
- C language skills and have basic linux kernel programming
- knowledge. This document doesn't explain the general
- topic of linux kernel coding and doesn't cover low-level
- driver implementation details. It only describes
- the standard way to write a PCI sound driver on ALSA.
- </para>
-
- <para>
- If you are already familiar with the older ALSA ver.0.5.x API, you
- can check the drivers such as <filename>sound/pci/es1938.c</filename> or
- <filename>sound/pci/maestro3.c</filename> which have also almost the same
- code-base in the ALSA 0.5.x tree, so you can compare the differences.
- </para>
-
- <para>
- This document is still a draft version. Any feedback and
- corrections, please!!
- </para>
- </preface>
-
-
-<!-- ****************************************************** -->
-<!-- File Tree Structure -->
-<!-- ****************************************************** -->
- <chapter id="file-tree">
- <title>File Tree Structure</title>
-
- <section id="file-tree-general">
- <title>General</title>
- <para>
- The ALSA drivers are provided in two ways.
- </para>
-
- <para>
- One is the trees provided as a tarball or via cvs from the
- ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
- tree. To synchronize both, the ALSA driver tree is split into
- two different trees: alsa-kernel and alsa-driver. The former
- contains purely the source code for the Linux 2.6 (or later)
- tree. This tree is designed only for compilation on 2.6 or
- later environment. The latter, alsa-driver, contains many subtle
- files for compiling ALSA drivers outside of the Linux kernel tree,
- wrapper functions for older 2.2 and 2.4 kernels, to adapt the latest kernel API,
- and additional drivers which are still in development or in
- tests. The drivers in alsa-driver tree will be moved to
- alsa-kernel (and eventually to the 2.6 kernel tree) when they are
- finished and confirmed to work fine.
- </para>
-
- <para>
- The file tree structure of ALSA driver is depicted below. Both
- alsa-kernel and alsa-driver have almost the same file
- structure, except for <quote>core</quote> directory. It's
- named as <quote>acore</quote> in alsa-driver tree.
-
- <example>
- <title>ALSA File Tree Structure</title>
- <literallayout>
- sound
- /core
- /oss
- /seq
- /oss
- /instr
- /ioctl32
- /include
- /drivers
- /mpu401
- /opl3
- /i2c
- /l3
- /synth
- /emux
- /pci
- /(cards)
- /isa
- /(cards)
- /arm
- /ppc
- /sparc
- /usb
- /pcmcia /(cards)
- /oss
- </literallayout>
- </example>
- </para>
- </section>
-
- <section id="file-tree-core-directory">
- <title>core directory</title>
- <para>
- This directory contains the middle layer which is the heart
- of ALSA drivers. In this directory, the native ALSA modules are
- stored. The sub-directories contain different modules and are
- dependent upon the kernel config.
- </para>
-
- <section id="file-tree-core-directory-oss">
- <title>core/oss</title>
-
- <para>
- The codes for PCM and mixer OSS emulation modules are stored
- in this directory. The rawmidi OSS emulation is included in
- the ALSA rawmidi code since it's quite small. The sequencer
- code is stored in <filename>core/seq/oss</filename> directory (see
- <link linkend="file-tree-core-directory-seq-oss"><citetitle>
- below</citetitle></link>).
- </para>
- </section>
-
- <section id="file-tree-core-directory-ioctl32">
- <title>core/ioctl32</title>
-
- <para>
- This directory contains the 32bit-ioctl wrappers for 64bit
- architectures such like x86-64, ppc64 and sparc64. For 32bit
- and alpha architectures, these are not compiled.
- </para>
- </section>
-
- <section id="file-tree-core-directory-seq">
- <title>core/seq</title>
- <para>
- This directory and its sub-directories are for the ALSA
- sequencer. This directory contains the sequencer core and
- primary sequencer modules such like snd-seq-midi,
- snd-seq-virmidi, etc. They are compiled only when
- <constant>CONFIG_SND_SEQUENCER</constant> is set in the kernel
- config.
- </para>
- </section>
-
- <section id="file-tree-core-directory-seq-oss">
- <title>core/seq/oss</title>
- <para>
- This contains the OSS sequencer emulation codes.
- </para>
- </section>
-
- <section id="file-tree-core-directory-deq-instr">
- <title>core/seq/instr</title>
- <para>
- This directory contains the modules for the sequencer
- instrument layer.
- </para>
- </section>
- </section>
-
- <section id="file-tree-include-directory">
- <title>include directory</title>
- <para>
- This is the place for the public header files of ALSA drivers,
- which are to be exported to user-space, or included by
- several files at different directories. Basically, the private
- header files should not be placed in this directory, but you may
- still find files there, due to historical reasons :)
- </para>
- </section>
-
- <section id="file-tree-drivers-directory">
- <title>drivers directory</title>
- <para>
- This directory contains code shared among different drivers
- on different architectures. They are hence supposed not to be
- architecture-specific.
- For example, the dummy pcm driver and the serial MIDI
- driver are found in this directory. In the sub-directories,
- there is code for components which are independent from
- bus and cpu architectures.
- </para>
-
- <section id="file-tree-drivers-directory-mpu401">
- <title>drivers/mpu401</title>
- <para>
- The MPU401 and MPU401-UART modules are stored here.
- </para>
- </section>
-
- <section id="file-tree-drivers-directory-opl3">
- <title>drivers/opl3 and opl4</title>
- <para>
- The OPL3 and OPL4 FM-synth stuff is found here.
- </para>
- </section>
- </section>
-
- <section id="file-tree-i2c-directory">
- <title>i2c directory</title>
- <para>
- This contains the ALSA i2c components.
- </para>
-
- <para>
- Although there is a standard i2c layer on Linux, ALSA has its
- own i2c code for some cards, because the soundcard needs only a
- simple operation and the standard i2c API is too complicated for
- such a purpose.
- </para>
-
- <section id="file-tree-i2c-directory-l3">
- <title>i2c/l3</title>
- <para>
- This is a sub-directory for ARM L3 i2c.
- </para>
- </section>
- </section>
-
- <section id="file-tree-synth-directory">
- <title>synth directory</title>
- <para>
- This contains the synth middle-level modules.
- </para>
-
- <para>
- So far, there is only Emu8000/Emu10k1 synth driver under
- the <filename>synth/emux</filename> sub-directory.
- </para>
- </section>
-
- <section id="file-tree-pci-directory">
- <title>pci directory</title>
- <para>
- This directory and its sub-directories hold the top-level card modules
- for PCI soundcards and the code specific to the PCI BUS.
- </para>
-
- <para>
- The drivers compiled from a single file are stored directly
- in the pci directory, while the drivers with several source files are
- stored on their own sub-directory (e.g. emu10k1, ice1712).
- </para>
- </section>
-
- <section id="file-tree-isa-directory">
- <title>isa directory</title>
- <para>
- This directory and its sub-directories hold the top-level card modules
- for ISA soundcards.
- </para>
- </section>
-
- <section id="file-tree-arm-ppc-sparc-directories">
- <title>arm, ppc, and sparc directories</title>
- <para>
- They are used for top-level card modules which are
- specific to one of these architectures.
- </para>
- </section>
-
- <section id="file-tree-usb-directory">
- <title>usb directory</title>
- <para>
- This directory contains the USB-audio driver. In the latest version, the
- USB MIDI driver is integrated in the usb-audio driver.
- </para>
- </section>
-
- <section id="file-tree-pcmcia-directory">
- <title>pcmcia directory</title>
- <para>
- The PCMCIA, especially PCCard drivers will go here. CardBus
- drivers will be in the pci directory, because their API is identical
- to that of standard PCI cards.
- </para>
- </section>
-
- <section id="file-tree-oss-directory">
- <title>oss directory</title>
- <para>
- The OSS/Lite source files are stored here in Linux 2.6 (or
- later) tree. In the ALSA driver tarball, this directory is empty,
- of course :)
- </para>
- </section>
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Basic Flow for PCI Drivers -->
-<!-- ****************************************************** -->
- <chapter id="basic-flow">
- <title>Basic Flow for PCI Drivers</title>
-
- <section id="basic-flow-outline">
- <title>Outline</title>
- <para>
- The minimum flow for PCI soundcards is as follows:
-
- <itemizedlist>
- <listitem><para>define the PCI ID table (see the section
- <link linkend="pci-resource-entries"><citetitle>PCI Entries
- </citetitle></link>).</para></listitem>
- <listitem><para>create <function>probe()</function> callback.</para></listitem>
- <listitem><para>create <function>remove()</function> callback.</para></listitem>
- <listitem><para>create a <structname>pci_driver</structname> structure
- containing the three pointers above.</para></listitem>
- <listitem><para>create an <function>init()</function> function just calling
- the <function>pci_register_driver()</function> to register the pci_driver table
- defined above.</para></listitem>
- <listitem><para>create an <function>exit()</function> function to call
- the <function>pci_unregister_driver()</function> function.</para></listitem>
- </itemizedlist>
- </para>
- </section>
-
- <section id="basic-flow-example">
- <title>Full Code Example</title>
- <para>
- The code example is shown below. Some parts are kept
- unimplemented at this moment but will be filled in the
- next sections. The numbers in the comment lines of the
- <function>snd_mychip_probe()</function> function
- refer to details explained in the following section.
-
- <example>
- <title>Basic Flow for PCI Drivers - Example</title>
- <programlisting>
-<![CDATA[
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/slab.h>
- #include <sound/core.h>
- #include <sound/initval.h>
-
- /* module parameters (see "Module Parameters") */
- /* SNDRV_CARDS: maximum number of cards supported by this module */
- static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
- static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
- static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-
- /* definition of the chip-specific record */
- struct mychip {
- struct snd_card *card;
- /* the rest of the implementation will be in section
- * "PCI Resource Management"
- */
- };
-
- /* chip-specific destructor
- * (see "PCI Resource Management")
- */
- static int snd_mychip_free(struct mychip *chip)
- {
- .... /* will be implemented later... */
- }
-
- /* component-destructor
- * (see "Management of Cards and Components")
- */
- static int snd_mychip_dev_free(struct snd_device *device)
- {
- return snd_mychip_free(device->device_data);
- }
-
- /* chip-specific constructor
- * (see "Management of Cards and Components")
- */
- static int snd_mychip_create(struct snd_card *card,
- struct pci_dev *pci,
- struct mychip **rchip)
- {
- struct mychip *chip;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_mychip_dev_free,
- };
-
- *rchip = NULL;
-
- /* check PCI availability here
- * (see "PCI Resource Management")
- */
- ....
-
- /* allocate a chip-specific data with zero filled */
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
-
- chip->card = card;
-
- /* rest of initialization here; will be implemented
- * later, see "PCI Resource Management"
- */
- ....
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_mychip_free(chip);
- return err;
- }
-
- *rchip = chip;
- return 0;
- }
-
- /* constructor -- see "Constructor" sub-section */
- static int snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
- {
- static int dev;
- struct snd_card *card;
- struct mychip *chip;
- int err;
-
- /* (1) */
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
- }
-
- /* (2) */
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
- if (err < 0)
- return err;
-
- /* (3) */
- err = snd_mychip_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
-
- /* (4) */
- strcpy(card->driver, "My Chip");
- strcpy(card->shortname, "My Own Chip 123");
- sprintf(card->longname, "%s at 0x%lx irq %i",
- card->shortname, chip->ioport, chip->irq);
-
- /* (5) */
- .... /* implemented later */
-
- /* (6) */
- err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
-
- /* (7) */
- pci_set_drvdata(pci, card);
- dev++;
- return 0;
- }
-
- /* destructor -- see the "Destructor" sub-section */
- static void snd_mychip_remove(struct pci_dev *pci)
- {
- snd_card_free(pci_get_drvdata(pci));
- pci_set_drvdata(pci, NULL);
- }
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="basic-flow-constructor">
- <title>Constructor</title>
- <para>
- The real constructor of PCI drivers is the <function>probe</function> callback.
- The <function>probe</function> callback and other component-constructors which are called
- from the <function>probe</function> callback cannot be used with
- the <parameter>__init</parameter> prefix
- because any PCI device could be a hotplug device.
- </para>
-
- <para>
- In the <function>probe</function> callback, the following scheme is often used.
- </para>
-
- <section id="basic-flow-constructor-device-index">
- <title>1) Check and increment the device index.</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int dev;
- ....
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
- }
-]]>
- </programlisting>
- </informalexample>
-
- where enable[dev] is the module option.
- </para>
-
- <para>
- Each time the <function>probe</function> callback is called, check the
- availability of the device. If not available, simply increment
- the device index and returns. dev will be incremented also
- later (<link
- linkend="basic-flow-constructor-set-pci"><citetitle>step
- 7</citetitle></link>).
- </para>
- </section>
-
- <section id="basic-flow-constructor-create-card">
- <title>2) Create a card instance</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_card *card;
- int err;
- ....
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The details will be explained in the section
- <link linkend="card-management-card-instance"><citetitle>
- Management of Cards and Components</citetitle></link>.
- </para>
- </section>
-
- <section id="basic-flow-constructor-create-main">
- <title>3) Create a main component</title>
- <para>
- In this part, the PCI resources are allocated.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip *chip;
- ....
- err = snd_mychip_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
-]]>
- </programlisting>
- </informalexample>
-
- The details will be explained in the section <link
- linkend="pci-resource"><citetitle>PCI Resource
- Management</citetitle></link>.
- </para>
- </section>
-
- <section id="basic-flow-constructor-main-component">
- <title>4) Set the driver ID and name strings.</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- strcpy(card->driver, "My Chip");
- strcpy(card->shortname, "My Own Chip 123");
- sprintf(card->longname, "%s at 0x%lx irq %i",
- card->shortname, chip->ioport, chip->irq);
-]]>
- </programlisting>
- </informalexample>
-
- The driver field holds the minimal ID string of the
- chip. This is used by alsa-lib's configurator, so keep it
- simple but unique.
- Even the same driver can have different driver IDs to
- distinguish the functionality of each chip type.
- </para>
-
- <para>
- The shortname field is a string shown as more verbose
- name. The longname field contains the information
- shown in <filename>/proc/asound/cards</filename>.
- </para>
- </section>
-
- <section id="basic-flow-constructor-create-other">
- <title>5) Create other components, such as mixer, MIDI, etc.</title>
- <para>
- Here you define the basic components such as
- <link linkend="pcm-interface"><citetitle>PCM</citetitle></link>,
- mixer (e.g. <link linkend="api-ac97"><citetitle>AC97</citetitle></link>),
- MIDI (e.g. <link linkend="midi-interface"><citetitle>MPU-401</citetitle></link>),
- and other interfaces.
- Also, if you want a <link linkend="proc-interface"><citetitle>proc
- file</citetitle></link>, define it here, too.
- </para>
- </section>
-
- <section id="basic-flow-constructor-register-card">
- <title>6) Register the card instance.</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Will be explained in the section <link
- linkend="card-management-registration"><citetitle>Management
- of Cards and Components</citetitle></link>, too.
- </para>
- </section>
-
- <section id="basic-flow-constructor-set-pci">
- <title>7) Set the PCI driver data and return zero.</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- pci_set_drvdata(pci, card);
- dev++;
- return 0;
-]]>
- </programlisting>
- </informalexample>
-
- In the above, the card record is stored. This pointer is
- used in the remove callback and power-management
- callbacks, too.
- </para>
- </section>
- </section>
-
- <section id="basic-flow-destructor">
- <title>Destructor</title>
- <para>
- The destructor, remove callback, simply releases the card
- instance. Then the ALSA middle layer will release all the
- attached components automatically.
- </para>
-
- <para>
- It would be typically like the following:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void snd_mychip_remove(struct pci_dev *pci)
- {
- snd_card_free(pci_get_drvdata(pci));
- pci_set_drvdata(pci, NULL);
- }
-]]>
- </programlisting>
- </informalexample>
-
- The above code assumes that the card pointer is set to the PCI
- driver data.
- </para>
- </section>
-
- <section id="basic-flow-header-files">
- <title>Header Files</title>
- <para>
- For the above example, at least the following include files
- are necessary.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/slab.h>
- #include <sound/core.h>
- #include <sound/initval.h>
-]]>
- </programlisting>
- </informalexample>
-
- where the last one is necessary only when module options are
- defined in the source file. If the code is split into several
- files, the files without module options don't need them.
- </para>
-
- <para>
- In addition to these headers, you'll need
- <filename>&lt;linux/interrupt.h&gt;</filename> for interrupt
- handling, and <filename>&lt;asm/io.h&gt;</filename> for I/O
- access. If you use the <function>mdelay()</function> or
- <function>udelay()</function> functions, you'll need to include
- <filename>&lt;linux/delay.h&gt;</filename> too.
- </para>
-
- <para>
- The ALSA interfaces like the PCM and control APIs are defined in other
- <filename>&lt;sound/xxx.h&gt;</filename> header files.
- They have to be included after
- <filename>&lt;sound/core.h&gt;</filename>.
- </para>
-
- </section>
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Management of Cards and Components -->
-<!-- ****************************************************** -->
- <chapter id="card-management">
- <title>Management of Cards and Components</title>
-
- <section id="card-management-card-instance">
- <title>Card Instance</title>
- <para>
- For each soundcard, a <quote>card</quote> record must be allocated.
- </para>
-
- <para>
- A card record is the headquarters of the soundcard. It manages
- the whole list of devices (components) on the soundcard, such as
- PCM, mixers, MIDI, synthesizer, and so on. Also, the card
- record holds the ID and the name strings of the card, manages
- the root of proc files, and controls the power-management states
- and hotplug disconnections. The component list on the card
- record is used to manage the correct release of resources at
- destruction.
- </para>
-
- <para>
- As mentioned above, to create a card instance, call
- <function>snd_card_new()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_card *card;
- int err;
- err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The function takes six arguments: the parent device pointer,
- the card-index number, the id string, the module pointer (usually
- <constant>THIS_MODULE</constant>),
- the size of extra-data space, and the pointer to return the
- card instance. The extra_size argument is used to
- allocate card-&gt;private_data for the
- chip-specific data. Note that these data
- are allocated by <function>snd_card_new()</function>.
- </para>
-
- <para>
- The first argument, the pointer of struct
- <structname>device</structname>, specifies the parent device.
- For PCI devices, typically &amp;pci-&gt; is passed there.
- </para>
- </section>
-
- <section id="card-management-component">
- <title>Components</title>
- <para>
- After the card is created, you can attach the components
- (devices) to the card instance. In an ALSA driver, a component is
- represented as a struct <structname>snd_device</structname> object.
- A component can be a PCM instance, a control interface, a raw
- MIDI interface, etc. Each such instance has one component
- entry.
- </para>
-
- <para>
- A component can be created via
- <function>snd_device_new()</function> function.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- This takes the card pointer, the device-level
- (<constant>SNDRV_DEV_XXX</constant>), the data pointer, and the
- callback pointers (<parameter>&amp;ops</parameter>). The
- device-level defines the type of components and the order of
- registration and de-registration. For most components, the
- device-level is already defined. For a user-defined component,
- you can use <constant>SNDRV_DEV_LOWLEVEL</constant>.
- </para>
-
- <para>
- This function itself doesn't allocate the data space. The data
- must be allocated manually beforehand, and its pointer is passed
- as the argument. This pointer (<parameter>chip</parameter> in the
- above example) is used as the identifier for the instance.
- </para>
-
- <para>
- Each pre-defined ALSA component such as ac97 and pcm calls
- <function>snd_device_new()</function> inside its
- constructor. The destructor for each component is defined in the
- callback pointers. Hence, you don't need to take care of
- calling a destructor for such a component.
- </para>
-
- <para>
- If you wish to create your own component, you need to
- set the destructor function to the dev_free callback in
- the <parameter>ops</parameter>, so that it can be released
- automatically via <function>snd_card_free()</function>.
- The next example will show an implementation of chip-specific
- data.
- </para>
- </section>
-
- <section id="card-management-chip-specific">
- <title>Chip-Specific Data</title>
- <para>
- Chip-specific information, e.g. the I/O port address, its
- resource pointer, or the irq number, is stored in the
- chip-specific record.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip {
- ....
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- In general, there are two ways of allocating the chip record.
- </para>
-
- <section id="card-management-chip-specific-snd-card-new">
- <title>1. Allocating via <function>snd_card_new()</function>.</title>
- <para>
- As mentioned above, you can pass the extra-data-length
- to the 5th argument of <function>snd_card_new()</function>, i.e.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct mychip), &card);
-]]>
- </programlisting>
- </informalexample>
-
- struct <structname>mychip</structname> is the type of the chip record.
- </para>
-
- <para>
- In return, the allocated record can be accessed as
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip *chip = card->private_data;
-]]>
- </programlisting>
- </informalexample>
-
- With this method, you don't have to allocate twice.
- The record is released together with the card instance.
- </para>
- </section>
-
- <section id="card-management-chip-specific-allocate-extra">
- <title>2. Allocating an extra device.</title>
-
- <para>
- After allocating a card instance via
- <function>snd_card_new()</function> (with
- <constant>0</constant> on the 4th arg), call
- <function>kzalloc()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_card *card;
- struct mychip *chip;
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
- .....
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The chip record should have the field to hold the card
- pointer at least,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip {
- struct snd_card *card;
- ....
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Then, set the card pointer in the returned chip instance.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- chip->card = card;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Next, initialize the fields, and register this chip
- record as a low-level device with a specified
- <parameter>ops</parameter>,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct snd_device_ops ops = {
- .dev_free = snd_mychip_dev_free,
- };
- ....
- snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-]]>
- </programlisting>
- </informalexample>
-
- <function>snd_mychip_dev_free()</function> is the
- device-destructor function, which will call the real
- destructor.
- </para>
-
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_mychip_dev_free(struct snd_device *device)
- {
- return snd_mychip_free(device->device_data);
- }
-]]>
- </programlisting>
- </informalexample>
-
- where <function>snd_mychip_free()</function> is the real destructor.
- </para>
- </section>
- </section>
-
- <section id="card-management-registration">
- <title>Registration and Release</title>
- <para>
- After all components are assigned, register the card instance
- by calling <function>snd_card_register()</function>. Access
- to the device files is enabled at this point. That is, before
- <function>snd_card_register()</function> is called, the
- components are safely inaccessible from external side. If this
- call fails, exit the probe function after releasing the card via
- <function>snd_card_free()</function>.
- </para>
-
- <para>
- For releasing the card instance, you can call simply
- <function>snd_card_free()</function>. As mentioned earlier, all
- components are released automatically by this call.
- </para>
-
- <para>
- For a device which allows hotplugging, you can use
- <function>snd_card_free_when_closed</function>. This one will
- postpone the destruction until all devices are closed.
- </para>
-
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCI Resource Management -->
-<!-- ****************************************************** -->
- <chapter id="pci-resource">
- <title>PCI Resource Management</title>
-
- <section id="pci-resource-example">
- <title>Full Code Example</title>
- <para>
- In this section, we'll complete the chip-specific constructor,
- destructor and PCI entries. Example code is shown first,
- below.
-
- <example>
- <title>PCI Resource Management Example</title>
- <programlisting>
-<![CDATA[
- struct mychip {
- struct snd_card *card;
- struct pci_dev *pci;
-
- unsigned long port;
- int irq;
- };
-
- static int snd_mychip_free(struct mychip *chip)
- {
- /* disable hardware here if any */
- .... /* (not implemented in this document) */
-
- /* release the irq */
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- /* release the I/O ports & memory */
- pci_release_regions(chip->pci);
- /* disable the PCI entry */
- pci_disable_device(chip->pci);
- /* release the data */
- kfree(chip);
- return 0;
- }
-
- /* chip-specific constructor */
- static int snd_mychip_create(struct snd_card *card,
- struct pci_dev *pci,
- struct mychip **rchip)
- {
- struct mychip *chip;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_mychip_dev_free,
- };
-
- *rchip = NULL;
-
- /* initialize the PCI entry */
- err = pci_enable_device(pci);
- if (err < 0)
- return err;
- /* check PCI availability (28bit DMA) */
- if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
- pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
- printk(KERN_ERR "error to set 28bit mask DMA\n");
- pci_disable_device(pci);
- return -ENXIO;
- }
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
- /* initialize the stuff */
- chip->card = card;
- chip->pci = pci;
- chip->irq = -1;
-
- /* (1) PCI resource allocation */
- err = pci_request_regions(pci, "My Chip");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
- return err;
- }
- chip->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
- printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
- snd_mychip_free(chip);
- return -EBUSY;
- }
- chip->irq = pci->irq;
-
- /* (2) initialization of the chip hardware */
- .... /* (not implemented in this document) */
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_mychip_free(chip);
- return err;
- }
-
- *rchip = chip;
- return 0;
- }
-
- /* PCI IDs */
- static struct pci_device_id snd_mychip_ids[] = {
- { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
- ....
- { 0, }
- };
- MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-
- /* pci_driver definition */
- static struct pci_driver driver = {
- .name = KBUILD_MODNAME,
- .id_table = snd_mychip_ids,
- .probe = snd_mychip_probe,
- .remove = snd_mychip_remove,
- };
-
- /* module initialization */
- static int __init alsa_card_mychip_init(void)
- {
- return pci_register_driver(&driver);
- }
-
- /* module clean up */
- static void __exit alsa_card_mychip_exit(void)
- {
- pci_unregister_driver(&driver);
- }
-
- module_init(alsa_card_mychip_init)
- module_exit(alsa_card_mychip_exit)
-
- EXPORT_NO_SYMBOLS; /* for old kernels only */
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="pci-resource-some-haftas">
- <title>Some Hafta's</title>
- <para>
- The allocation of PCI resources is done in the
- <function>probe()</function> function, and usually an extra
- <function>xxx_create()</function> function is written for this
- purpose.
- </para>
-
- <para>
- In the case of PCI devices, you first have to call
- the <function>pci_enable_device()</function> function before
- allocating resources. Also, you need to set the proper PCI DMA
- mask to limit the accessed I/O range. In some cases, you might
- need to call <function>pci_set_master()</function> function,
- too.
- </para>
-
- <para>
- Suppose the 28bit mask, and the code to be added would be like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- err = pci_enable_device(pci);
- if (err < 0)
- return err;
- if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
- pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
- printk(KERN_ERR "error to set 28bit mask DMA\n");
- pci_disable_device(pci);
- return -ENXIO;
- }
-
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- <section id="pci-resource-resource-allocation">
- <title>Resource Allocation</title>
- <para>
- The allocation of I/O ports and irqs is done via standard kernel
- functions. Unlike ALSA ver.0.5.x., there are no helpers for
- that. And these resources must be released in the destructor
- function (see below). Also, on ALSA 0.9.x, you don't need to
- allocate (pseudo-)DMA for PCI like in ALSA 0.5.x.
- </para>
-
- <para>
- Now assume that the PCI device has an I/O port with 8 bytes
- and an interrupt. Then struct <structname>mychip</structname> will have the
- following fields:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip {
- struct snd_card *card;
-
- unsigned long port;
- int irq;
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- For an I/O port (and also a memory region), you need to have
- the resource pointer for the standard resource management. For
- an irq, you have to keep only the irq number (integer). But you
- need to initialize this number as -1 before actual allocation,
- since irq 0 is valid. The port address and its resource pointer
- can be initialized as null by
- <function>kzalloc()</function> automatically, so you
- don't have to take care of resetting them.
- </para>
-
- <para>
- The allocation of an I/O port is done like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- err = pci_request_regions(pci, "My Chip");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
- return err;
- }
- chip->port = pci_resource_start(pci, 0);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- <!-- obsolete -->
- It will reserve the I/O port region of 8 bytes of the given
- PCI device. The returned value, chip-&gt;res_port, is allocated
- via <function>kmalloc()</function> by
- <function>request_region()</function>. The pointer must be
- released via <function>kfree()</function>, but there is a
- problem with this. This issue will be explained later.
- </para>
-
- <para>
- The allocation of an interrupt source is done like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
- printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
- snd_mychip_free(chip);
- return -EBUSY;
- }
- chip->irq = pci->irq;
-]]>
- </programlisting>
- </informalexample>
-
- where <function>snd_mychip_interrupt()</function> is the
- interrupt handler defined <link
- linkend="pcm-interface-interrupt-handler"><citetitle>later</citetitle></link>.
- Note that chip-&gt;irq should be defined
- only when <function>request_irq()</function> succeeded.
- </para>
-
- <para>
- On the PCI bus, interrupts can be shared. Thus,
- <constant>IRQF_SHARED</constant> is used as the interrupt flag of
- <function>request_irq()</function>.
- </para>
-
- <para>
- The last argument of <function>request_irq()</function> is the
- data pointer passed to the interrupt handler. Usually, the
- chip-specific record is used for that, but you can use what you
- like, too.
- </para>
-
- <para>
- I won't give details about the interrupt handler at this
- point, but at least its appearance can be explained now. The
- interrupt handler looks usually like the following:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
- {
- struct mychip *chip = dev_id;
- ....
- return IRQ_HANDLED;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Now let's write the corresponding destructor for the resources
- above. The role of destructor is simple: disable the hardware
- (if already activated) and release the resources. So far, we
- have no hardware part, so the disabling code is not written here.
- </para>
-
- <para>
- To release the resources, the <quote>check-and-release</quote>
- method is a safer way. For the interrupt, do like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-]]>
- </programlisting>
- </informalexample>
-
- Since the irq number can start from 0, you should initialize
- chip-&gt;irq with a negative value (e.g. -1), so that you can
- check the validity of the irq number as above.
- </para>
-
- <para>
- When you requested I/O ports or memory regions via
- <function>pci_request_region()</function> or
- <function>pci_request_regions()</function> like in this example,
- release the resource(s) using the corresponding function,
- <function>pci_release_region()</function> or
- <function>pci_release_regions()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- pci_release_regions(chip->pci);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- When you requested manually via <function>request_region()</function>
- or <function>request_mem_region</function>, you can release it via
- <function>release_resource()</function>. Suppose that you keep
- the resource pointer returned from <function>request_region()</function>
- in chip-&gt;res_port, the release procedure looks like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- release_and_free_resource(chip->res_port);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Don't forget to call <function>pci_disable_device()</function>
- before the end.
- </para>
-
- <para>
- And finally, release the chip-specific record.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- kfree(chip);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- We didn't implement the hardware disabling part in the above.
- If you need to do this, please note that the destructor may be
- called even before the initialization of the chip is completed.
- It would be better to have a flag to skip hardware disabling
- if the hardware was not initialized yet.
- </para>
-
- <para>
- When the chip-data is assigned to the card using
- <function>snd_device_new()</function> with
- <constant>SNDRV_DEV_LOWLELVEL</constant> , its destructor is
- called at the last. That is, it is assured that all other
- components like PCMs and controls have already been released.
- You don't have to stop PCMs, etc. explicitly, but just
- call low-level hardware stopping.
- </para>
-
- <para>
- The management of a memory-mapped region is almost as same as
- the management of an I/O port. You'll need three fields like
- the following:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mychip {
- ....
- unsigned long iobase_phys;
- void __iomem *iobase_virt;
- };
-]]>
- </programlisting>
- </informalexample>
-
- and the allocation would be like below:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- if ((err = pci_request_regions(pci, "My Chip")) < 0) {
- kfree(chip);
- return err;
- }
- chip->iobase_phys = pci_resource_start(pci, 0);
- chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
- pci_resource_len(pci, 0));
-]]>
- </programlisting>
- </informalexample>
-
- and the corresponding destructor would be:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_mychip_free(struct mychip *chip)
- {
- ....
- if (chip->iobase_virt)
- iounmap(chip->iobase_virt);
- ....
- pci_release_regions(chip->pci);
- ....
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- </section>
-
- <section id="pci-resource-entries">
- <title>PCI Entries</title>
- <para>
- So far, so good. Let's finish the missing PCI
- stuff. At first, we need a
- <structname>pci_device_id</structname> table for this
- chipset. It's a table of PCI vendor/device ID number, and some
- masks.
- </para>
-
- <para>
- For example,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct pci_device_id snd_mychip_ids[] = {
- { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
- ....
- { 0, }
- };
- MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The first and second fields of
- the <structname>pci_device_id</structname> structure are the vendor and
- device IDs. If you have no reason to filter the matching
- devices, you can leave the remaining fields as above. The last
- field of the <structname>pci_device_id</structname> struct contains
- private data for this entry. You can specify any value here, for
- example, to define specific operations for supported device IDs.
- Such an example is found in the intel8x0 driver.
- </para>
-
- <para>
- The last entry of this list is the terminator. You must
- specify this all-zero entry.
- </para>
-
- <para>
- Then, prepare the <structname>pci_driver</structname> record:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct pci_driver driver = {
- .name = KBUILD_MODNAME,
- .id_table = snd_mychip_ids,
- .probe = snd_mychip_probe,
- .remove = snd_mychip_remove,
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The <structfield>probe</structfield> and
- <structfield>remove</structfield> functions have already
- been defined in the previous sections.
- The <structfield>name</structfield>
- field is the name string of this device. Note that you must not
- use a slash <quote>/</quote> in this string.
- </para>
-
- <para>
- And at last, the module entries:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int __init alsa_card_mychip_init(void)
- {
- return pci_register_driver(&driver);
- }
-
- static void __exit alsa_card_mychip_exit(void)
- {
- pci_unregister_driver(&driver);
- }
-
- module_init(alsa_card_mychip_init)
- module_exit(alsa_card_mychip_exit)
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Note that these module entries are tagged with
- <parameter>__init</parameter> and
- <parameter>__exit</parameter> prefixes.
- </para>
-
- <para>
- Oh, one thing was forgotten. If you have no exported symbols,
- you need to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
-
- <informalexample>
- <programlisting>
-<![CDATA[
- EXPORT_NO_SYMBOLS;
-]]>
- </programlisting>
- </informalexample>
-
- That's all!
- </para>
- </section>
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCM Interface -->
-<!-- ****************************************************** -->
- <chapter id="pcm-interface">
- <title>PCM Interface</title>
-
- <section id="pcm-interface-general">
- <title>General</title>
- <para>
- The PCM middle layer of ALSA is quite powerful and it is only
- necessary for each driver to implement the low-level functions
- to access its hardware.
- </para>
-
- <para>
- For accessing to the PCM layer, you need to include
- <filename>&lt;sound/pcm.h&gt;</filename> first. In addition,
- <filename>&lt;sound/pcm_params.h&gt;</filename> might be needed
- if you access to some functions related with hw_param.
- </para>
-
- <para>
- Each card device can have up to four pcm instances. A pcm
- instance corresponds to a pcm device file. The limitation of
- number of instances comes only from the available bit size of
- the Linux's device numbers. Once when 64bit device number is
- used, we'll have more pcm instances available.
- </para>
-
- <para>
- A pcm instance consists of pcm playback and capture streams,
- and each pcm stream consists of one or more pcm substreams. Some
- soundcards support multiple playback functions. For example,
- emu10k1 has a PCM playback of 32 stereo substreams. In this case, at
- each open, a free substream is (usually) automatically chosen
- and opened. Meanwhile, when only one substream exists and it was
- already opened, the successful open will either block
- or error with <constant>EAGAIN</constant> according to the
- file open mode. But you don't have to care about such details in your
- driver. The PCM middle layer will take care of such work.
- </para>
- </section>
-
- <section id="pcm-interface-example">
- <title>Full Code Example</title>
- <para>
- The example code below does not include any hardware access
- routines but shows only the skeleton, how to build up the PCM
- interfaces.
-
- <example>
- <title>PCM Example Code</title>
- <programlisting>
-<![CDATA[
- #include <sound/pcm.h>
- ....
-
- /* hardware definition */
- static struct snd_pcm_hardware snd_mychip_playback_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 32768,
- .period_bytes_min = 4096,
- .period_bytes_max = 32768,
- .periods_min = 1,
- .periods_max = 1024,
- };
-
- /* hardware definition */
- static struct snd_pcm_hardware snd_mychip_capture_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 32768,
- .period_bytes_min = 4096,
- .period_bytes_max = 32768,
- .periods_min = 1,
- .periods_max = 1024,
- };
-
- /* open callback */
- static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- runtime->hw = snd_mychip_playback_hw;
- /* more hardware-initialization will be done here */
- ....
- return 0;
- }
-
- /* close callback */
- static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- /* the hardware-specific codes will be here */
- ....
- return 0;
-
- }
-
- /* open callback */
- static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- runtime->hw = snd_mychip_capture_hw;
- /* more hardware-initialization will be done here */
- ....
- return 0;
- }
-
- /* close callback */
- static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- /* the hardware-specific codes will be here */
- ....
- return 0;
-
- }
-
- /* hw_params callback */
- static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
- {
- return snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- }
-
- /* hw_free callback */
- static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
- {
- return snd_pcm_lib_free_pages(substream);
- }
-
- /* prepare callback */
- static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- /* set up the hardware with the current configuration
- * for example...
- */
- mychip_set_sample_format(chip, runtime->format);
- mychip_set_sample_rate(chip, runtime->rate);
- mychip_set_channels(chip, runtime->channels);
- mychip_set_dma_setup(chip, runtime->dma_addr,
- chip->buffer_size,
- chip->period_size);
- return 0;
- }
-
- /* trigger callback */
- static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
- {
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- /* do something to start the PCM engine */
- ....
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- /* do something to stop the PCM engine */
- ....
- break;
- default:
- return -EINVAL;
- }
- }
-
- /* pointer callback */
- static snd_pcm_uframes_t
- snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- unsigned int current_ptr;
-
- /* get the current hardware pointer */
- current_ptr = mychip_get_hw_pointer(chip);
- return current_ptr;
- }
-
- /* operators */
- static struct snd_pcm_ops snd_mychip_playback_ops = {
- .open = snd_mychip_playback_open,
- .close = snd_mychip_playback_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_mychip_pcm_hw_params,
- .hw_free = snd_mychip_pcm_hw_free,
- .prepare = snd_mychip_pcm_prepare,
- .trigger = snd_mychip_pcm_trigger,
- .pointer = snd_mychip_pcm_pointer,
- };
-
- /* operators */
- static struct snd_pcm_ops snd_mychip_capture_ops = {
- .open = snd_mychip_capture_open,
- .close = snd_mychip_capture_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_mychip_pcm_hw_params,
- .hw_free = snd_mychip_pcm_hw_free,
- .prepare = snd_mychip_pcm_prepare,
- .trigger = snd_mychip_pcm_trigger,
- .pointer = snd_mychip_pcm_pointer,
- };
-
- /*
- * definitions of capture are omitted here...
- */
-
- /* create a pcm device */
- static int snd_mychip_new_pcm(struct mychip *chip)
- {
- struct snd_pcm *pcm;
- int err;
-
- err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
- if (err < 0)
- return err;
- pcm->private_data = chip;
- strcpy(pcm->name, "My Chip");
- chip->pcm = pcm;
- /* set operators */
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &snd_mychip_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &snd_mychip_capture_ops);
- /* pre-allocation of buffers */
- /* NOTE: this may fail */
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- 64*1024, 64*1024);
- return 0;
- }
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="pcm-interface-constructor">
- <title>Constructor</title>
- <para>
- A pcm instance is allocated by the <function>snd_pcm_new()</function>
- function. It would be better to create a constructor for pcm,
- namely,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_mychip_new_pcm(struct mychip *chip)
- {
- struct snd_pcm *pcm;
- int err;
-
- err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
- if (err < 0)
- return err;
- pcm->private_data = chip;
- strcpy(pcm->name, "My Chip");
- chip->pcm = pcm;
- ....
- return 0;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The <function>snd_pcm_new()</function> function takes four
- arguments. The first argument is the card pointer to which this
- pcm is assigned, and the second is the ID string.
- </para>
-
- <para>
- The third argument (<parameter>index</parameter>, 0 in the
- above) is the index of this new pcm. It begins from zero. If
- you create more than one pcm instances, specify the
- different numbers in this argument. For example,
- <parameter>index</parameter> = 1 for the second PCM device.
- </para>
-
- <para>
- The fourth and fifth arguments are the number of substreams
- for playback and capture, respectively. Here 1 is used for
- both arguments. When no playback or capture substreams are available,
- pass 0 to the corresponding argument.
- </para>
-
- <para>
- If a chip supports multiple playbacks or captures, you can
- specify more numbers, but they must be handled properly in
- open/close, etc. callbacks. When you need to know which
- substream you are referring to, then it can be obtained from
- struct <structname>snd_pcm_substream</structname> data passed to each callback
- as follows:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_pcm_substream *substream;
- int index = substream->number;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- After the pcm is created, you need to set operators for each
- pcm stream.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &snd_mychip_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &snd_mychip_capture_ops);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The operators are defined typically like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct snd_pcm_ops snd_mychip_playback_ops = {
- .open = snd_mychip_pcm_open,
- .close = snd_mychip_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_mychip_pcm_hw_params,
- .hw_free = snd_mychip_pcm_hw_free,
- .prepare = snd_mychip_pcm_prepare,
- .trigger = snd_mychip_pcm_trigger,
- .pointer = snd_mychip_pcm_pointer,
- };
-]]>
- </programlisting>
- </informalexample>
-
- All the callbacks are described in the
- <link linkend="pcm-interface-operators"><citetitle>
- Operators</citetitle></link> subsection.
- </para>
-
- <para>
- After setting the operators, you probably will want to
- pre-allocate the buffer. For the pre-allocation, simply call
- the following:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- 64*1024, 64*1024);
-]]>
- </programlisting>
- </informalexample>
-
- It will allocate a buffer up to 64kB as default.
- Buffer management details will be described in the later section <link
- linkend="buffer-and-memory"><citetitle>Buffer and Memory
- Management</citetitle></link>.
- </para>
-
- <para>
- Additionally, you can set some extra information for this pcm
- in pcm-&gt;info_flags.
- The available values are defined as
- <constant>SNDRV_PCM_INFO_XXX</constant> in
- <filename>&lt;sound/asound.h&gt;</filename>, which is used for
- the hardware definition (described later). When your soundchip
- supports only half-duplex, specify like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- <section id="pcm-interface-destructor">
- <title>... And the Destructor?</title>
- <para>
- The destructor for a pcm instance is not always
- necessary. Since the pcm device will be released by the middle
- layer code automatically, you don't have to call the destructor
- explicitly.
- </para>
-
- <para>
- The destructor would be necessary if you created
- special records internally and needed to release them. In such a
- case, set the destructor function to
- pcm-&gt;private_free:
-
- <example>
- <title>PCM Instance with a Destructor</title>
- <programlisting>
-<![CDATA[
- static void mychip_pcm_free(struct snd_pcm *pcm)
- {
- struct mychip *chip = snd_pcm_chip(pcm);
- /* free your own data */
- kfree(chip->my_private_pcm_data);
- /* do what you like else */
- ....
- }
-
- static int snd_mychip_new_pcm(struct mychip *chip)
- {
- struct snd_pcm *pcm;
- ....
- /* allocate your own data */
- chip->my_private_pcm_data = kmalloc(...);
- /* set the destructor */
- pcm->private_data = chip;
- pcm->private_free = mychip_pcm_free;
- ....
- }
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="pcm-interface-runtime">
- <title>Runtime Pointer - The Chest of PCM Information</title>
- <para>
- When the PCM substream is opened, a PCM runtime instance is
- allocated and assigned to the substream. This pointer is
- accessible via <constant>substream-&gt;runtime</constant>.
- This runtime pointer holds most information you need
- to control the PCM: the copy of hw_params and sw_params configurations, the buffer
- pointers, mmap records, spinlocks, etc.
- </para>
-
- <para>
- The definition of runtime instance is found in
- <filename>&lt;sound/pcm.h&gt;</filename>. Here are
- the contents of this file:
- <informalexample>
- <programlisting>
-<![CDATA[
-struct _snd_pcm_runtime {
- /* -- Status -- */
- struct snd_pcm_substream *trigger_master;
- snd_timestamp_t trigger_tstamp; /* trigger timestamp */
- int overrange;
- snd_pcm_uframes_t avail_max;
- snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
- snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
-
- /* -- HW params -- */
- snd_pcm_access_t access; /* access mode */
- snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */
- snd_pcm_subformat_t subformat; /* subformat */
- unsigned int rate; /* rate in Hz */
- unsigned int channels; /* channels */
- snd_pcm_uframes_t period_size; /* period size */
- unsigned int periods; /* periods */
- snd_pcm_uframes_t buffer_size; /* buffer size */
- unsigned int tick_time; /* tick time */
- snd_pcm_uframes_t min_align; /* Min alignment for the format */
- size_t byte_align;
- unsigned int frame_bits;
- unsigned int sample_bits;
- unsigned int info;
- unsigned int rate_num;
- unsigned int rate_den;
-
- /* -- SW params -- */
- struct timespec tstamp_mode; /* mmap timestamp is updated */
- unsigned int period_step;
- unsigned int sleep_min; /* min ticks to sleep */
- snd_pcm_uframes_t start_threshold;
- snd_pcm_uframes_t stop_threshold;
- snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
- noise is nearest than this */
- snd_pcm_uframes_t silence_size; /* Silence filling size */
- snd_pcm_uframes_t boundary; /* pointers wrap point */
-
- snd_pcm_uframes_t silenced_start;
- snd_pcm_uframes_t silenced_size;
-
- snd_pcm_sync_id_t sync; /* hardware synchronization ID */
-
- /* -- mmap -- */
- volatile struct snd_pcm_mmap_status *status;
- volatile struct snd_pcm_mmap_control *control;
- atomic_t mmap_count;
-
- /* -- locking / scheduling -- */
- spinlock_t lock;
- wait_queue_head_t sleep;
- struct timer_list tick_timer;
- struct fasync_struct *fasync;
-
- /* -- private section -- */
- void *private_data;
- void (*private_free)(struct snd_pcm_runtime *runtime);
-
- /* -- hardware description -- */
- struct snd_pcm_hardware hw;
- struct snd_pcm_hw_constraints hw_constraints;
-
- /* -- timer -- */
- unsigned int timer_resolution; /* timer resolution */
-
- /* -- DMA -- */
- unsigned char *dma_area; /* DMA area */
- dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */
- size_t dma_bytes; /* size of DMA area */
-
- struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
-
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- /* -- OSS things -- */
- struct snd_pcm_oss_runtime oss;
-#endif
-};
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- For the operators (callbacks) of each sound driver, most of
- these records are supposed to be read-only. Only the PCM
- middle-layer changes / updates them. The exceptions are
- the hardware description (hw) DMA buffer information and the
- private data. Besides, if you use the standard buffer allocation
- method via <function>snd_pcm_lib_malloc_pages()</function>,
- you don't need to set the DMA buffer information by yourself.
- </para>
-
- <para>
- In the sections below, important records are explained.
- </para>
-
- <section id="pcm-interface-runtime-hw">
- <title>Hardware Description</title>
- <para>
- The hardware descriptor (struct <structname>snd_pcm_hardware</structname>)
- contains the definitions of the fundamental hardware
- configuration. Above all, you'll need to define this in
- <link linkend="pcm-interface-operators-open-callback"><citetitle>
- the open callback</citetitle></link>.
- Note that the runtime instance holds the copy of the
- descriptor, not the pointer to the existing descriptor. That
- is, in the open callback, you can modify the copied descriptor
- (<constant>runtime-&gt;hw</constant>) as you need. For example, if the maximum
- number of channels is 1 only on some chip models, you can
- still use the same hardware descriptor and change the
- channels_max later:
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_pcm_runtime *runtime = substream->runtime;
- ...
- runtime->hw = snd_mychip_playback_hw; /* common definition */
- if (chip->model == VERY_OLD_ONE)
- runtime->hw.channels_max = 1;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Typically, you'll have a hardware descriptor as below:
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct snd_pcm_hardware snd_mychip_playback_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 32768,
- .period_bytes_min = 4096,
- .period_bytes_max = 32768,
- .periods_min = 1,
- .periods_max = 1024,
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- <itemizedlist>
- <listitem><para>
- The <structfield>info</structfield> field contains the type and
- capabilities of this pcm. The bit flags are defined in
- <filename>&lt;sound/asound.h&gt;</filename> as
- <constant>SNDRV_PCM_INFO_XXX</constant>. Here, at least, you
- have to specify whether the mmap is supported and which
- interleaved format is supported.
- When the hardware supports mmap, add the
- <constant>SNDRV_PCM_INFO_MMAP</constant> flag here. When the
- hardware supports the interleaved or the non-interleaved
- formats, <constant>SNDRV_PCM_INFO_INTERLEAVED</constant> or
- <constant>SNDRV_PCM_INFO_NONINTERLEAVED</constant> flag must
- be set, respectively. If both are supported, you can set both,
- too.
- </para>
-
- <para>
- In the above example, <constant>MMAP_VALID</constant> and
- <constant>BLOCK_TRANSFER</constant> are specified for the OSS mmap
- mode. Usually both are set. Of course,
- <constant>MMAP_VALID</constant> is set only if the mmap is
- really supported.
- </para>
-
- <para>
- The other possible flags are
- <constant>SNDRV_PCM_INFO_PAUSE</constant> and
- <constant>SNDRV_PCM_INFO_RESUME</constant>. The
- <constant>PAUSE</constant> bit means that the pcm supports the
- <quote>pause</quote> operation, while the
- <constant>RESUME</constant> bit means that the pcm supports
- the full <quote>suspend/resume</quote> operation.
- If the <constant>PAUSE</constant> flag is set,
- the <structfield>trigger</structfield> callback below
- must handle the corresponding (pause push/release) commands.
- The suspend/resume trigger commands can be defined even without
- the <constant>RESUME</constant> flag. See <link
- linkend="power-management"><citetitle>
- Power Management</citetitle></link> section for details.
- </para>
-
- <para>
- When the PCM substreams can be synchronized (typically,
- synchronized start/stop of a playback and a capture streams),
- you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
- too. In this case, you'll need to check the linked-list of
- PCM substreams in the trigger callback. This will be
- described in the later section.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <structfield>formats</structfield> field contains the bit-flags
- of supported formats (<constant>SNDRV_PCM_FMTBIT_XXX</constant>).
- If the hardware supports more than one format, give all or'ed
- bits. In the example above, the signed 16bit little-endian
- format is specified.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <structfield>rates</structfield> field contains the bit-flags of
- supported rates (<constant>SNDRV_PCM_RATE_XXX</constant>).
- When the chip supports continuous rates, pass
- <constant>CONTINUOUS</constant> bit additionally.
- The pre-defined rate bits are provided only for typical
- rates. If your chip supports unconventional rates, you need to add
- the <constant>KNOT</constant> bit and set up the hardware
- constraint manually (explained later).
- </para>
- </listitem>
-
- <listitem>
- <para>
- <structfield>rate_min</structfield> and
- <structfield>rate_max</structfield> define the minimum and
- maximum sample rate. This should correspond somehow to
- <structfield>rates</structfield> bits.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <structfield>channel_min</structfield> and
- <structfield>channel_max</structfield>
- define, as you might already expected, the minimum and maximum
- number of channels.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <structfield>buffer_bytes_max</structfield> defines the
- maximum buffer size in bytes. There is no
- <structfield>buffer_bytes_min</structfield> field, since
- it can be calculated from the minimum period size and the
- minimum number of periods.
- Meanwhile, <structfield>period_bytes_min</structfield> and
- define the minimum and maximum size of the period in bytes.
- <structfield>periods_max</structfield> and
- <structfield>periods_min</structfield> define the maximum and
- minimum number of periods in the buffer.
- </para>
-
- <para>
- The <quote>period</quote> is a term that corresponds to
- a fragment in the OSS world. The period defines the size at
- which a PCM interrupt is generated. This size strongly
- depends on the hardware.
- Generally, the smaller period size will give you more
- interrupts, that is, more controls.
- In the case of capture, this size defines the input latency.
- On the other hand, the whole buffer size defines the
- output latency for the playback direction.
- </para>
- </listitem>
-
- <listitem>
- <para>
- There is also a field <structfield>fifo_size</structfield>.
- This specifies the size of the hardware FIFO, but currently it
- is neither used in the driver nor in the alsa-lib. So, you
- can ignore this field.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </section>
-
- <section id="pcm-interface-runtime-config">
- <title>PCM Configurations</title>
- <para>
- Ok, let's go back again to the PCM runtime records.
- The most frequently referred records in the runtime instance are
- the PCM configurations.
- The PCM configurations are stored in the runtime instance
- after the application sends <type>hw_params</type> data via
- alsa-lib. There are many fields copied from hw_params and
- sw_params structs. For example,
- <structfield>format</structfield> holds the format type
- chosen by the application. This field contains the enum value
- <constant>SNDRV_PCM_FORMAT_XXX</constant>.
- </para>
-
- <para>
- One thing to be noted is that the configured buffer and period
- sizes are stored in <quote>frames</quote> in the runtime.
- In the ALSA world, 1 frame = channels * samples-size.
- For conversion between frames and bytes, you can use the
- <function>frames_to_bytes()</function> and
- <function>bytes_to_frames()</function> helper functions.
- <informalexample>
- <programlisting>
-<![CDATA[
- period_bytes = frames_to_bytes(runtime, runtime->period_size);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Also, many software parameters (sw_params) are
- stored in frames, too. Please check the type of the field.
- <type>snd_pcm_uframes_t</type> is for the frames as unsigned
- integer while <type>snd_pcm_sframes_t</type> is for the frames
- as signed integer.
- </para>
- </section>
-
- <section id="pcm-interface-runtime-dma">
- <title>DMA Buffer Information</title>
- <para>
- The DMA buffer is defined by the following four fields,
- <structfield>dma_area</structfield>,
- <structfield>dma_addr</structfield>,
- <structfield>dma_bytes</structfield> and
- <structfield>dma_private</structfield>.
- The <structfield>dma_area</structfield> holds the buffer
- pointer (the logical address). You can call
- <function>memcpy</function> from/to
- this pointer. Meanwhile, <structfield>dma_addr</structfield>
- holds the physical address of the buffer. This field is
- specified only when the buffer is a linear buffer.
- <structfield>dma_bytes</structfield> holds the size of buffer
- in bytes. <structfield>dma_private</structfield> is used for
- the ALSA DMA allocator.
- </para>
-
- <para>
- If you use a standard ALSA function,
- <function>snd_pcm_lib_malloc_pages()</function>, for
- allocating the buffer, these fields are set by the ALSA middle
- layer, and you should <emphasis>not</emphasis> change them by
- yourself. You can read them but not write them.
- On the other hand, if you want to allocate the buffer by
- yourself, you'll need to manage it in hw_params callback.
- At least, <structfield>dma_bytes</structfield> is mandatory.
- <structfield>dma_area</structfield> is necessary when the
- buffer is mmapped. If your driver doesn't support mmap, this
- field is not necessary. <structfield>dma_addr</structfield>
- is also optional. You can use
- <structfield>dma_private</structfield> as you like, too.
- </para>
- </section>
-
- <section id="pcm-interface-runtime-status">
- <title>Running Status</title>
- <para>
- The running status can be referred via <constant>runtime-&gt;status</constant>.
- This is the pointer to the struct <structname>snd_pcm_mmap_status</structname>
- record. For example, you can get the current DMA hardware
- pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
- </para>
-
- <para>
- The DMA application pointer can be referred via
- <constant>runtime-&gt;control</constant>, which points to the
- struct <structname>snd_pcm_mmap_control</structname> record.
- However, accessing directly to this value is not recommended.
- </para>
- </section>
-
- <section id="pcm-interface-runtime-private">
- <title>Private Data</title>
- <para>
- You can allocate a record for the substream and store it in
- <constant>runtime-&gt;private_data</constant>. Usually, this
- is done in
- <link linkend="pcm-interface-operators-open-callback"><citetitle>
- the open callback</citetitle></link>.
- Don't mix this with <constant>pcm-&gt;private_data</constant>.
- The <constant>pcm-&gt;private_data</constant> usually points to the
- chip instance assigned statically at the creation of PCM, while the
- <constant>runtime-&gt;private_data</constant> points to a dynamic
- data structure created at the PCM open callback.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_open(struct snd_pcm_substream *substream)
- {
- struct my_pcm_data *data;
- ....
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- substream->runtime->private_data = data;
- ....
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The allocated object must be released in
- <link linkend="pcm-interface-operators-open-callback"><citetitle>
- the close callback</citetitle></link>.
- </para>
- </section>
-
- </section>
-
- <section id="pcm-interface-operators">
- <title>Operators</title>
- <para>
- OK, now let me give details about each pcm callback
- (<parameter>ops</parameter>). In general, every callback must
- return 0 if successful, or a negative error number
- such as <constant>-EINVAL</constant>. To choose an appropriate
- error number, it is advised to check what value other parts of
- the kernel return when the same kind of request fails.
- </para>
-
- <para>
- The callback function takes at least the argument with
- <structname>snd_pcm_substream</structname> pointer. To retrieve
- the chip record from the given substream instance, you can use the
- following macro.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- int xxx() {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- ....
- }
-]]>
- </programlisting>
- </informalexample>
-
- The macro reads <constant>substream-&gt;private_data</constant>,
- which is a copy of <constant>pcm-&gt;private_data</constant>.
- You can override the former if you need to assign different data
- records per PCM substream. For example, the cmi8330 driver assigns
- different private_data for playback and capture directions,
- because it uses two different codecs (SB- and AD-compatible) for
- different directions.
- </para>
-
- <section id="pcm-interface-operators-open-callback">
- <title>open callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_open(struct snd_pcm_substream *substream);
-]]>
- </programlisting>
- </informalexample>
-
- This is called when a pcm substream is opened.
- </para>
-
- <para>
- At least, here you have to initialize the runtime-&gt;hw
- record. Typically, this is done by like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_open(struct snd_pcm_substream *substream)
- {
- struct mychip *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- runtime->hw = snd_mychip_playback_hw;
- return 0;
- }
-]]>
- </programlisting>
- </informalexample>
-
- where <parameter>snd_mychip_playback_hw</parameter> is the
- pre-defined hardware description.
- </para>
-
- <para>
- You can allocate a private data in this callback, as described
- in <link linkend="pcm-interface-runtime-private"><citetitle>
- Private Data</citetitle></link> section.
- </para>
-
- <para>
- If the hardware configuration needs more constraints, set the
- hardware constraints here, too.
- See <link linkend="pcm-interface-constraints"><citetitle>
- Constraints</citetitle></link> for more details.
- </para>
- </section>
-
- <section id="pcm-interface-operators-close-callback">
- <title>close callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_close(struct snd_pcm_substream *substream);
-]]>
- </programlisting>
- </informalexample>
-
- Obviously, this is called when a pcm substream is closed.
- </para>
-
- <para>
- Any private instance for a pcm substream allocated in the
- open callback will be released here.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_close(struct snd_pcm_substream *substream)
- {
- ....
- kfree(substream->runtime->private_data);
- ....
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- <section id="pcm-interface-operators-ioctl-callback">
- <title>ioctl callback</title>
- <para>
- This is used for any special call to pcm ioctls. But
- usually you can pass a generic ioctl callback,
- <function>snd_pcm_lib_ioctl</function>.
- </para>
- </section>
-
- <section id="pcm-interface-operators-hw-params-callback">
- <title>hw_params callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- This is called when the hardware parameter
- (<structfield>hw_params</structfield>) is set
- up by the application,
- that is, once when the buffer size, the period size, the
- format, etc. are defined for the pcm substream.
- </para>
-
- <para>
- Many hardware setups should be done in this callback,
- including the allocation of buffers.
- </para>
-
- <para>
- Parameters to be initialized are retrieved by
- <function>params_xxx()</function> macros. To allocate
- buffer, you can call a helper function,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-]]>
- </programlisting>
- </informalexample>
-
- <function>snd_pcm_lib_malloc_pages()</function> is available
- only when the DMA buffers have been pre-allocated.
- See the section <link
- linkend="buffer-and-memory-buffer-types"><citetitle>
- Buffer Types</citetitle></link> for more details.
- </para>
-
- <para>
- Note that this and <structfield>prepare</structfield> callbacks
- may be called multiple times per initialization.
- For example, the OSS emulation may
- call these callbacks at each change via its ioctl.
- </para>
-
- <para>
- Thus, you need to be careful not to allocate the same buffers
- many times, which will lead to memory leaks! Calling the
- helper function above many times is OK. It will release the
- previous buffer automatically when it was already allocated.
- </para>
-
- <para>
- Another note is that this callback is non-atomic
- (schedulable) as default, i.e. when no
- <structfield>nonatomic</structfield> flag set.
- This is important, because the
- <structfield>trigger</structfield> callback
- is atomic (non-schedulable). That is, mutexes or any
- schedule-related functions are not available in
- <structfield>trigger</structfield> callback.
- Please see the subsection
- <link linkend="pcm-interface-atomicity"><citetitle>
- Atomicity</citetitle></link> for details.
- </para>
- </section>
-
- <section id="pcm-interface-operators-hw-free-callback">
- <title>hw_free callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- This is called to release the resources allocated via
- <structfield>hw_params</structfield>. For example, releasing the
- buffer via
- <function>snd_pcm_lib_malloc_pages()</function> is done by
- calling the following:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_lib_free_pages(substream);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- This function is always called before the close callback is called.
- Also, the callback may be called multiple times, too.
- Keep track whether the resource was already released.
- </para>
- </section>
-
- <section id="pcm-interface-operators-prepare-callback">
- <title>prepare callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_prepare(struct snd_pcm_substream *substream);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- This callback is called when the pcm is
- <quote>prepared</quote>. You can set the format type, sample
- rate, etc. here. The difference from
- <structfield>hw_params</structfield> is that the
- <structfield>prepare</structfield> callback will be called each
- time
- <function>snd_pcm_prepare()</function> is called, i.e. when
- recovering after underruns, etc.
- </para>
-
- <para>
- Note that this callback is now non-atomic.
- You can use schedule-related functions safely in this callback.
- </para>
-
- <para>
- In this and the following callbacks, you can refer to the
- values via the runtime record,
- substream-&gt;runtime.
- For example, to get the current
- rate, format or channels, access to
- runtime-&gt;rate,
- runtime-&gt;format or
- runtime-&gt;channels, respectively.
- The physical address of the allocated buffer is set to
- runtime-&gt;dma_area. The buffer and period sizes are
- in runtime-&gt;buffer_size and runtime-&gt;period_size,
- respectively.
- </para>
-
- <para>
- Be careful that this callback will be called many times at
- each setup, too.
- </para>
- </section>
-
- <section id="pcm-interface-operators-trigger-callback">
- <title>trigger callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
-]]>
- </programlisting>
- </informalexample>
-
- This is called when the pcm is started, stopped or paused.
- </para>
-
- <para>
- Which action is specified in the second argument,
- <constant>SNDRV_PCM_TRIGGER_XXX</constant> in
- <filename>&lt;sound/pcm.h&gt;</filename>. At least,
- the <constant>START</constant> and <constant>STOP</constant>
- commands must be defined in this callback.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- /* do something to start the PCM engine */
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- /* do something to stop the PCM engine */
- break;
- default:
- return -EINVAL;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- When the pcm supports the pause operation (given in the info
- field of the hardware table), the <constant>PAUSE_PUSH</constant>
- and <constant>PAUSE_RELEASE</constant> commands must be
- handled here, too. The former is the command to pause the pcm,
- and the latter to restart the pcm again.
- </para>
-
- <para>
- When the pcm supports the suspend/resume operation,
- regardless of full or partial suspend/resume support,
- the <constant>SUSPEND</constant> and <constant>RESUME</constant>
- commands must be handled, too.
- These commands are issued when the power-management status is
- changed. Obviously, the <constant>SUSPEND</constant> and
- <constant>RESUME</constant> commands
- suspend and resume the pcm substream, and usually, they
- are identical to the <constant>STOP</constant> and
- <constant>START</constant> commands, respectively.
- See the <link linkend="power-management"><citetitle>
- Power Management</citetitle></link> section for details.
- </para>
-
- <para>
- As mentioned, this callback is atomic as default unless
- <structfield>nonatomic</structfield> flag set, and
- you cannot call functions which may sleep.
- The trigger callback should be as minimal as possible,
- just really triggering the DMA. The other stuff should be
- initialized hw_params and prepare callbacks properly
- beforehand.
- </para>
- </section>
-
- <section id="pcm-interface-operators-pointer-callback">
- <title>pointer callback</title>
- <para>
- <informalexample>
- <programlisting>
-<![CDATA[
- static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
-]]>
- </programlisting>
- </informalexample>
-
- This callback is called when the PCM middle layer inquires
- the current hardware position on the buffer. The position must
- be returned in frames,
- ranging from 0 to buffer_size - 1.
- </para>
-
- <para>
- This is called usually from the buffer-update routine in the
- pcm middle layer, which is invoked when
- <function>snd_pcm_period_elapsed()</function> is called in the
- interrupt routine. Then the pcm middle layer updates the
- position and calculates the available space, and wakes up the
- sleeping poll threads, etc.
- </para>
-
- <para>
- This callback is also atomic as default.
- </para>
- </section>
-
- <section id="pcm-interface-operators-copy-silence">
- <title>copy and silence callbacks</title>
- <para>
- These callbacks are not mandatory, and can be omitted in
- most cases. These callbacks are used when the hardware buffer
- cannot be in the normal memory space. Some chips have their
- own buffer on the hardware which is not mappable. In such a
- case, you have to transfer the data manually from the memory
- buffer to the hardware buffer. Or, if the buffer is
- non-contiguous on both physical and virtual memory spaces,
- these callbacks must be defined, too.
- </para>
-
- <para>
- If these two callbacks are defined, copy and set-silence
- operations are done by them. The detailed will be described in
- the later section <link
- linkend="buffer-and-memory"><citetitle>Buffer and Memory
- Management</citetitle></link>.
- </para>
- </section>
-
- <section id="pcm-interface-operators-ack">
- <title>ack callback</title>
- <para>
- This callback is also not mandatory. This callback is called
- when the appl_ptr is updated in read or write operations.
- Some drivers like emu10k1-fx and cs46xx need to track the
- current appl_ptr for the internal buffer, and this callback
- is useful only for such a purpose.
- </para>
- <para>
- This callback is atomic as default.
- </para>
- </section>
-
- <section id="pcm-interface-operators-page-callback">
- <title>page callback</title>
-
- <para>
- This callback is optional too. This callback is used
- mainly for non-contiguous buffers. The mmap calls this
- callback to get the page address. Some examples will be
- explained in the later section <link
- linkend="buffer-and-memory"><citetitle>Buffer and Memory
- Management</citetitle></link>, too.
- </para>
- </section>
- </section>
-
- <section id="pcm-interface-interrupt-handler">
- <title>Interrupt Handler</title>
- <para>
- The rest of pcm stuff is the PCM interrupt handler. The
- role of PCM interrupt handler in the sound driver is to update
- the buffer position and to tell the PCM middle layer when the
- buffer position goes across the prescribed period size. To
- inform this, call the <function>snd_pcm_period_elapsed()</function>
- function.
- </para>
-
- <para>
- There are several types of sound chips to generate the interrupts.
- </para>
-
- <section id="pcm-interface-interrupt-handler-boundary">
- <title>Interrupts at the period (fragment) boundary</title>
- <para>
- This is the most frequently found type: the hardware
- generates an interrupt at each period boundary.
- In this case, you can call
- <function>snd_pcm_period_elapsed()</function> at each
- interrupt.
- </para>
-
- <para>
- <function>snd_pcm_period_elapsed()</function> takes the
- substream pointer as its argument. Thus, you need to keep the
- substream pointer accessible from the chip instance. For
- example, define substream field in the chip record to hold the
- current running substream pointer, and set the pointer value
- at open callback (and reset at close callback).
- </para>
-
- <para>
- If you acquire a spinlock in the interrupt handler, and the
- lock is used in other pcm callbacks, too, then you have to
- release the lock before calling
- <function>snd_pcm_period_elapsed()</function>, because
- <function>snd_pcm_period_elapsed()</function> calls other pcm
- callbacks inside.
- </para>
-
- <para>
- Typical code would be like:
-
- <example>
- <title>Interrupt Handler Case #1</title>
- <programlisting>
-<![CDATA[
- static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
- {
- struct mychip *chip = dev_id;
- spin_lock(&chip->lock);
- ....
- if (pcm_irq_invoked(chip)) {
- /* call updater, unlock before it */
- spin_unlock(&chip->lock);
- snd_pcm_period_elapsed(chip->substream);
- spin_lock(&chip->lock);
- /* acknowledge the interrupt if necessary */
- }
- ....
- spin_unlock(&chip->lock);
- return IRQ_HANDLED;
- }
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="pcm-interface-interrupt-handler-timer">
- <title>High frequency timer interrupts</title>
- <para>
- This happens when the hardware doesn't generate interrupts
- at the period boundary but issues timer interrupts at a fixed
- timer rate (e.g. es1968 or ymfpci drivers).
- In this case, you need to check the current hardware
- position and accumulate the processed sample length at each
- interrupt. When the accumulated size exceeds the period
- size, call
- <function>snd_pcm_period_elapsed()</function> and reset the
- accumulator.
- </para>
-
- <para>
- Typical code would be like the following.
-
- <example>
- <title>Interrupt Handler Case #2</title>
- <programlisting>
-<![CDATA[
- static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
- {
- struct mychip *chip = dev_id;
- spin_lock(&chip->lock);
- ....
- if (pcm_irq_invoked(chip)) {
- unsigned int last_ptr, size;
- /* get the current hardware pointer (in frames) */
- last_ptr = get_hw_ptr(chip);
- /* calculate the processed frames since the
- * last update
- */
- if (last_ptr < chip->last_ptr)
- size = runtime->buffer_size + last_ptr
- - chip->last_ptr;
- else
- size = last_ptr - chip->last_ptr;
- /* remember the last updated point */
- chip->last_ptr = last_ptr;
- /* accumulate the size */
- chip->size += size;
- /* over the period boundary? */
- if (chip->size >= runtime->period_size) {
- /* reset the accumulator */
- chip->size %= runtime->period_size;
- /* call updater */
- spin_unlock(&chip->lock);
- snd_pcm_period_elapsed(substream);
- spin_lock(&chip->lock);
- }
- /* acknowledge the interrupt if necessary */
- }
- ....
- spin_unlock(&chip->lock);
- return IRQ_HANDLED;
- }
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="pcm-interface-interrupt-handler-both">
- <title>On calling <function>snd_pcm_period_elapsed()</function></title>
- <para>
- In both cases, even if more than one period are elapsed, you
- don't have to call
- <function>snd_pcm_period_elapsed()</function> many times. Call
- only once. And the pcm layer will check the current hardware
- pointer and update to the latest status.
- </para>
- </section>
- </section>
-
- <section id="pcm-interface-atomicity">
- <title>Atomicity</title>
- <para>
- One of the most important (and thus difficult to debug) problems
- in kernel programming are race conditions.
- In the Linux kernel, they are usually avoided via spin-locks, mutexes
- or semaphores. In general, if a race condition can happen
- in an interrupt handler, it has to be managed atomically, and you
- have to use a spinlock to protect the critical session. If the
- critical section is not in interrupt handler code and
- if taking a relatively long time to execute is acceptable, you
- should use mutexes or semaphores instead.
- </para>
-
- <para>
- As already seen, some pcm callbacks are atomic and some are
- not. For example, the <parameter>hw_params</parameter> callback is
- non-atomic, while <parameter>trigger</parameter> callback is
- atomic. This means, the latter is called already in a spinlock
- held by the PCM middle layer. Please take this atomicity into
- account when you choose a locking scheme in the callbacks.
- </para>
-
- <para>
- In the atomic callbacks, you cannot use functions which may call
- <function>schedule</function> or go to
- <function>sleep</function>. Semaphores and mutexes can sleep,
- and hence they cannot be used inside the atomic callbacks
- (e.g. <parameter>trigger</parameter> callback).
- To implement some delay in such a callback, please use
- <function>udelay()</function> or <function>mdelay()</function>.
- </para>
-
- <para>
- All three atomic callbacks (trigger, pointer, and ack) are
- called with local interrupts disabled.
- </para>
-
- <para>
- The recent changes in PCM core code, however, allow all PCM
- operations to be non-atomic. This assumes that the all caller
- sides are in non-atomic contexts. For example, the function
- <function>snd_pcm_period_elapsed()</function> is called
- typically from the interrupt handler. But, if you set up the
- driver to use a threaded interrupt handler, this call can be in
- non-atomic context, too. In such a case, you can set
- <structfield>nonatomic</structfield> filed of
- <structname>snd_pcm</structname> object after creating it.
- When this flag is set, mutex and rwsem are used internally in
- the PCM core instead of spin and rwlocks, so that you can call
- all PCM functions safely in a non-atomic context.
- </para>
-
- </section>
- <section id="pcm-interface-constraints">
- <title>Constraints</title>
- <para>
- If your chip supports unconventional sample rates, or only the
- limited samples, you need to set a constraint for the
- condition.
- </para>
-
- <para>
- For example, in order to restrict the sample rates in the some
- supported values, use
- <function>snd_pcm_hw_constraint_list()</function>.
- You need to call this function in the open callback.
-
- <example>
- <title>Example of Hardware Constraints</title>
- <programlisting>
-<![CDATA[
- static unsigned int rates[] =
- {4000, 10000, 22050, 44100};
- static struct snd_pcm_hw_constraint_list constraints_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
- };
-
- static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
- {
- int err;
- ....
- err = snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &constraints_rates);
- if (err < 0)
- return err;
- ....
- }
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- There are many different constraints.
- Look at <filename>sound/pcm.h</filename> for a complete list.
- You can even define your own constraint rules.
- For example, let's suppose my_chip can manage a substream of 1 channel
- if and only if the format is S16_LE, otherwise it supports any format
- specified in the <structname>snd_pcm_hardware</structname> structure (or in any
- other constraint_list). You can build a rule like this:
-
- <example>
- <title>Example of Hardware Constraints for Channels</title>
- <programlisting>
-<![CDATA[
- static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
- {
- struct snd_interval *c = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- struct snd_interval ch;
-
- snd_interval_any(&ch);
- if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
- ch.min = ch.max = 1;
- ch.integer = 1;
- return snd_interval_refine(c, &ch);
- }
- return 0;
- }
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- Then you need to call this function to add your rule:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- hw_rule_channels_by_format, NULL,
- SNDRV_PCM_HW_PARAM_FORMAT, -1);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The rule function is called when an application sets the PCM
- format, and it refines the number of channels accordingly.
- But an application may set the number of channels before
- setting the format. Thus you also need to define the inverse rule:
-
- <example>
- <title>Example of Hardware Constraints for Formats</title>
- <programlisting>
-<![CDATA[
- static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule)
- {
- struct snd_interval *c = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
- struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- struct snd_mask fmt;
-
- snd_mask_any(&fmt); /* Init the struct */
- if (c->min < 2) {
- fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
- return snd_mask_refine(f, &fmt);
- }
- return 0;
- }
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- ...and in the open callback:
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
- hw_rule_format_by_channels, NULL,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- I won't give more details here, rather I
- would like to say, <quote>Luke, use the source.</quote>
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Control Interface -->
-<!-- ****************************************************** -->
- <chapter id="control-interface">
- <title>Control Interface</title>
-
- <section id="control-interface-general">
- <title>General</title>
- <para>
- The control interface is used widely for many switches,
- sliders, etc. which are accessed from user-space. Its most
- important use is the mixer interface. In other words, since ALSA
- 0.9.x, all the mixer stuff is implemented on the control kernel API.
- </para>
-
- <para>
- ALSA has a well-defined AC97 control module. If your chip
- supports only the AC97 and nothing else, you can skip this
- section.
- </para>
-
- <para>
- The control API is defined in
- <filename>&lt;sound/control.h&gt;</filename>.
- Include this file if you want to add your own controls.
- </para>
- </section>
-
- <section id="control-interface-definition">
- <title>Definition of Controls</title>
- <para>
- To create a new control, you need to define the
- following three
- callbacks: <structfield>info</structfield>,
- <structfield>get</structfield> and
- <structfield>put</structfield>. Then, define a
- struct <structname>snd_kcontrol_new</structname> record, such as:
-
- <example>
- <title>Definition of a Control</title>
- <programlisting>
-<![CDATA[
- static struct snd_kcontrol_new my_control = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Switch",
- .index = 0,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .private_value = 0xffff,
- .info = my_control_info,
- .get = my_control_get,
- .put = my_control_put
- };
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- The <structfield>iface</structfield> field specifies the control
- type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
- is usually <constant>MIXER</constant>.
- Use <constant>CARD</constant> for global controls that are not
- logically part of the mixer.
- If the control is closely associated with some specific device on
- the sound card, use <constant>HWDEP</constant>,
- <constant>PCM</constant>, <constant>RAWMIDI</constant>,
- <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
- specify the device number with the
- <structfield>device</structfield> and
- <structfield>subdevice</structfield> fields.
- </para>
-
- <para>
- The <structfield>name</structfield> is the name identifier
- string. Since ALSA 0.9.x, the control name is very important,
- because its role is classified from its name. There are
- pre-defined standard control names. The details are described in
- the <link linkend="control-interface-control-names"><citetitle>
- Control Names</citetitle></link> subsection.
- </para>
-
- <para>
- The <structfield>index</structfield> field holds the index number
- of this control. If there are several different controls with
- the same name, they can be distinguished by the index
- number. This is the case when
- several codecs exist on the card. If the index is zero, you can
- omit the definition above.
- </para>
-
- <para>
- The <structfield>access</structfield> field contains the access
- type of this control. Give the combination of bit masks,
- <constant>SNDRV_CTL_ELEM_ACCESS_XXX</constant>, there.
- The details will be explained in
- the <link linkend="control-interface-access-flags"><citetitle>
- Access Flags</citetitle></link> subsection.
- </para>
-
- <para>
- The <structfield>private_value</structfield> field contains
- an arbitrary long integer value for this record. When using
- the generic <structfield>info</structfield>,
- <structfield>get</structfield> and
- <structfield>put</structfield> callbacks, you can pass a value
- through this field. If several small numbers are necessary, you can
- combine them in bitwise. Or, it's possible to give a pointer
- (casted to unsigned long) of some record to this field, too.
- </para>
-
- <para>
- The <structfield>tlv</structfield> field can be used to provide
- metadata about the control; see the
- <link linkend="control-interface-tlv">
- <citetitle>Metadata</citetitle></link> subsection.
- </para>
-
- <para>
- The other three are
- <link linkend="control-interface-callbacks"><citetitle>
- callback functions</citetitle></link>.
- </para>
- </section>
-
- <section id="control-interface-control-names">
- <title>Control Names</title>
- <para>
- There are some standards to define the control names. A
- control is usually defined from the three parts as
- <quote>SOURCE DIRECTION FUNCTION</quote>.
- </para>
-
- <para>
- The first, <constant>SOURCE</constant>, specifies the source
- of the control, and is a string such as <quote>Master</quote>,
- <quote>PCM</quote>, <quote>CD</quote> and
- <quote>Line</quote>. There are many pre-defined sources.
- </para>
-
- <para>
- The second, <constant>DIRECTION</constant>, is one of the
- following strings according to the direction of the control:
- <quote>Playback</quote>, <quote>Capture</quote>, <quote>Bypass
- Playback</quote> and <quote>Bypass Capture</quote>. Or, it can
- be omitted, meaning both playback and capture directions.
- </para>
-
- <para>
- The third, <constant>FUNCTION</constant>, is one of the
- following strings according to the function of the control:
- <quote>Switch</quote>, <quote>Volume</quote> and
- <quote>Route</quote>.
- </para>
-
- <para>
- The example of control names are, thus, <quote>Master Capture
- Switch</quote> or <quote>PCM Playback Volume</quote>.
- </para>
-
- <para>
- There are some exceptions:
- </para>
-
- <section id="control-interface-control-names-global">
- <title>Global capture and playback</title>
- <para>
- <quote>Capture Source</quote>, <quote>Capture Switch</quote>
- and <quote>Capture Volume</quote> are used for the global
- capture (input) source, switch and volume. Similarly,
- <quote>Playback Switch</quote> and <quote>Playback
- Volume</quote> are used for the global output gain switch and
- volume.
- </para>
- </section>
-
- <section id="control-interface-control-names-tone">
- <title>Tone-controls</title>
- <para>
- tone-control switch and volumes are specified like
- <quote>Tone Control - XXX</quote>, e.g. <quote>Tone Control -
- Switch</quote>, <quote>Tone Control - Bass</quote>,
- <quote>Tone Control - Center</quote>.
- </para>
- </section>
-
- <section id="control-interface-control-names-3d">
- <title>3D controls</title>
- <para>
- 3D-control switches and volumes are specified like <quote>3D
- Control - XXX</quote>, e.g. <quote>3D Control -
- Switch</quote>, <quote>3D Control - Center</quote>, <quote>3D
- Control - Space</quote>.
- </para>
- </section>
-
- <section id="control-interface-control-names-mic">
- <title>Mic boost</title>
- <para>
- Mic-boost switch is set as <quote>Mic Boost</quote> or
- <quote>Mic Boost (6dB)</quote>.
- </para>
-
- <para>
- More precise information can be found in
- <filename>Documentation/sound/alsa/ControlNames.txt</filename>.
- </para>
- </section>
- </section>
-
- <section id="control-interface-access-flags">
- <title>Access Flags</title>
-
- <para>
- The access flag is the bitmask which specifies the access type
- of the given control. The default access type is
- <constant>SNDRV_CTL_ELEM_ACCESS_READWRITE</constant>,
- which means both read and write are allowed to this control.
- When the access flag is omitted (i.e. = 0), it is
- considered as <constant>READWRITE</constant> access as default.
- </para>
-
- <para>
- When the control is read-only, pass
- <constant>SNDRV_CTL_ELEM_ACCESS_READ</constant> instead.
- In this case, you don't have to define
- the <structfield>put</structfield> callback.
- Similarly, when the control is write-only (although it's a rare
- case), you can use the <constant>WRITE</constant> flag instead, and
- you don't need the <structfield>get</structfield> callback.
- </para>
-
- <para>
- If the control value changes frequently (e.g. the VU meter),
- <constant>VOLATILE</constant> flag should be given. This means
- that the control may be changed without
- <link linkend="control-interface-change-notification"><citetitle>
- notification</citetitle></link>. Applications should poll such
- a control constantly.
- </para>
-
- <para>
- When the control is inactive, set
- the <constant>INACTIVE</constant> flag, too.
- There are <constant>LOCK</constant> and
- <constant>OWNER</constant> flags to change the write
- permissions.
- </para>
-
- </section>
-
- <section id="control-interface-callbacks">
- <title>Callbacks</title>
-
- <section id="control-interface-callbacks-info">
- <title>info callback</title>
- <para>
- The <structfield>info</structfield> callback is used to get
- detailed information on this control. This must store the
- values of the given struct <structname>snd_ctl_elem_info</structname>
- object. For example, for a boolean control with a single
- element:
-
- <example>
- <title>Example of info callback</title>
- <programlisting>
-<![CDATA[
- static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
- {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
- }
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- The <structfield>type</structfield> field specifies the type
- of the control. There are <constant>BOOLEAN</constant>,
- <constant>INTEGER</constant>, <constant>ENUMERATED</constant>,
- <constant>BYTES</constant>, <constant>IEC958</constant> and
- <constant>INTEGER64</constant>. The
- <structfield>count</structfield> field specifies the
- number of elements in this control. For example, a stereo
- volume would have count = 2. The
- <structfield>value</structfield> field is a union, and
- the values stored are depending on the type. The boolean and
- integer types are identical.
- </para>
-
- <para>
- The enumerated type is a bit different from others. You'll
- need to set the string for the currently given item index.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
- {
- static char *texts[4] = {
- "First", "Second", "Third", "Fourth"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item > 3)
- uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The above callback can be simplified with a helper function,
- <function>snd_ctl_enum_info</function>. The final code
- looks like below.
- (You can pass ARRAY_SIZE(texts) instead of 4 in the third
- argument; it's a matter of taste.)
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
- {
- static char *texts[4] = {
- "First", "Second", "Third", "Fourth"
- };
- return snd_ctl_enum_info(uinfo, 1, 4, texts);
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Some common info callbacks are available for your convenience:
- <function>snd_ctl_boolean_mono_info()</function> and
- <function>snd_ctl_boolean_stereo_info()</function>.
- Obviously, the former is an info callback for a mono channel
- boolean item, just like <function>snd_myctl_mono_info</function>
- above, and the latter is for a stereo channel boolean item.
- </para>
-
- </section>
-
- <section id="control-interface-callbacks-get">
- <title>get callback</title>
-
- <para>
- This callback is used to read the current value of the
- control and to return to user-space.
- </para>
-
- <para>
- For example,
-
- <example>
- <title>Example of get callback</title>
- <programlisting>
-<![CDATA[
- static int snd_myctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- struct mychip *chip = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = get_some_value(chip);
- return 0;
- }
-]]>
- </programlisting>
- </example>
- </para>
-
- <para>
- The <structfield>value</structfield> field depends on
- the type of control as well as on the info callback. For example,
- the sb driver uses this field to store the register offset,
- the bit-shift and the bit-mask. The
- <structfield>private_value</structfield> field is set as follows:
- <informalexample>
- <programlisting>
-<![CDATA[
- .private_value = reg | (shift << 16) | (mask << 24)
-]]>
- </programlisting>
- </informalexample>
- and is retrieved in callbacks like
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 16) & 0xff;
- int mask = (kcontrol->private_value >> 24) & 0xff;
- ....
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- In the <structfield>get</structfield> callback,
- you have to fill all the elements if the
- control has more than one elements,
- i.e. <structfield>count</structfield> &gt; 1.
- In the example above, we filled only one element
- (<structfield>value.integer.value[0]</structfield>) since it's
- assumed as <structfield>count</structfield> = 1.
- </para>
- </section>
-
- <section id="control-interface-callbacks-put">
- <title>put callback</title>
-
- <para>
- This callback is used to write a value from user-space.
- </para>
-
- <para>
- For example,
-
- <example>
- <title>Example of put callback</title>
- <programlisting>
-<![CDATA[
- static int snd_myctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
- struct mychip *chip = snd_kcontrol_chip(kcontrol);
- int changed = 0;
- if (chip->current_value !=
- ucontrol->value.integer.value[0]) {
- change_current_value(chip,
- ucontrol->value.integer.value[0]);
- changed = 1;
- }
- return changed;
- }
-]]>
- </programlisting>
- </example>
-
- As seen above, you have to return 1 if the value is
- changed. If the value is not changed, return 0 instead.
- If any fatal error happens, return a negative error code as
- usual.
- </para>
-
- <para>
- As in the <structfield>get</structfield> callback,
- when the control has more than one elements,
- all elements must be evaluated in this callback, too.
- </para>
- </section>
-
- <section id="control-interface-callbacks-all">
- <title>Callbacks are not atomic</title>
- <para>
- All these three callbacks are basically not atomic.
- </para>
- </section>
- </section>
-
- <section id="control-interface-constructor">
- <title>Constructor</title>
- <para>
- When everything is ready, finally we can create a new
- control. To create a control, there are two functions to be
- called, <function>snd_ctl_new1()</function> and
- <function>snd_ctl_add()</function>.
- </para>
-
- <para>
- In the simplest way, you can do like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
- if (err < 0)
- return err;
-]]>
- </programlisting>
- </informalexample>
-
- where <parameter>my_control</parameter> is the
- struct <structname>snd_kcontrol_new</structname> object defined above, and chip
- is the object pointer to be passed to
- kcontrol-&gt;private_data
- which can be referred to in callbacks.
- </para>
-
- <para>
- <function>snd_ctl_new1()</function> allocates a new
- <structname>snd_kcontrol</structname> instance,
- and <function>snd_ctl_add</function> assigns the given
- control component to the card.
- </para>
- </section>
-
- <section id="control-interface-change-notification">
- <title>Change Notification</title>
- <para>
- If you need to change and update a control in the interrupt
- routine, you can call <function>snd_ctl_notify()</function>. For
- example,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
-]]>
- </programlisting>
- </informalexample>
-
- This function takes the card pointer, the event-mask, and the
- control id pointer for the notification. The event-mask
- specifies the types of notification, for example, in the above
- example, the change of control values is notified.
- The id pointer is the pointer of struct <structname>snd_ctl_elem_id</structname>
- to be notified.
- You can find some examples in <filename>es1938.c</filename> or
- <filename>es1968.c</filename> for hardware volume interrupts.
- </para>
- </section>
-
- <section id="control-interface-tlv">
- <title>Metadata</title>
- <para>
- To provide information about the dB values of a mixer control, use
- on of the <constant>DECLARE_TLV_xxx</constant> macros from
- <filename>&lt;sound/tlv.h&gt;</filename> to define a variable
- containing this information, set the<structfield>tlv.p
- </structfield> field to point to this variable, and include the
- <constant>SNDRV_CTL_ELEM_ACCESS_TLV_READ</constant> flag in the
- <structfield>access</structfield> field; like this:
- <informalexample>
- <programlisting>
-<![CDATA[
- static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
-
- static struct snd_kcontrol_new my_control = {
- ...
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ,
- ...
- .tlv.p = db_scale_my_control,
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The <function>DECLARE_TLV_DB_SCALE</function> macro defines
- information about a mixer control where each step in the control's
- value changes the dB value by a constant dB amount.
- The first parameter is the name of the variable to be defined.
- The second parameter is the minimum value, in units of 0.01 dB.
- The third parameter is the step size, in units of 0.01 dB.
- Set the fourth parameter to 1 if the minimum value actually mutes
- the control.
- </para>
-
- <para>
- The <function>DECLARE_TLV_DB_LINEAR</function> macro defines
- information about a mixer control where the control's value affects
- the output linearly.
- The first parameter is the name of the variable to be defined.
- The second parameter is the minimum value, in units of 0.01 dB.
- The third parameter is the maximum value, in units of 0.01 dB.
- If the minimum value mutes the control, set the second parameter to
- <constant>TLV_DB_GAIN_MUTE</constant>.
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- API for AC97 Codec -->
-<!-- ****************************************************** -->
- <chapter id="api-ac97">
- <title>API for AC97 Codec</title>
-
- <section>
- <title>General</title>
- <para>
- The ALSA AC97 codec layer is a well-defined one, and you don't
- have to write much code to control it. Only low-level control
- routines are necessary. The AC97 codec API is defined in
- <filename>&lt;sound/ac97_codec.h&gt;</filename>.
- </para>
- </section>
-
- <section id="api-ac97-example">
- <title>Full Code Example</title>
- <para>
- <example>
- <title>Example of AC97 Interface</title>
- <programlisting>
-<![CDATA[
- struct mychip {
- ....
- struct snd_ac97 *ac97;
- ....
- };
-
- static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
- unsigned short reg)
- {
- struct mychip *chip = ac97->private_data;
- ....
- /* read a register value here from the codec */
- return the_register_value;
- }
-
- static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
- unsigned short reg, unsigned short val)
- {
- struct mychip *chip = ac97->private_data;
- ....
- /* write the given register value to the codec */
- }
-
- static int snd_mychip_ac97(struct mychip *chip)
- {
- struct snd_ac97_bus *bus;
- struct snd_ac97_template ac97;
- int err;
- static struct snd_ac97_bus_ops ops = {
- .write = snd_mychip_ac97_write,
- .read = snd_mychip_ac97_read,
- };
-
- err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
- if (err < 0)
- return err;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
- return snd_ac97_mixer(bus, &ac97, &chip->ac97);
- }
-
-]]>
- </programlisting>
- </example>
- </para>
- </section>
-
- <section id="api-ac97-constructor">
- <title>Constructor</title>
- <para>
- To create an ac97 instance, first call <function>snd_ac97_bus</function>
- with an <type>ac97_bus_ops_t</type> record with callback functions.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_ac97_bus *bus;
- static struct snd_ac97_bus_ops ops = {
- .write = snd_mychip_ac97_write,
- .read = snd_mychip_ac97_read,
- };
-
- snd_ac97_bus(card, 0, &ops, NULL, &pbus);
-]]>
- </programlisting>
- </informalexample>
-
- The bus record is shared among all belonging ac97 instances.
- </para>
-
- <para>
- And then call <function>snd_ac97_mixer()</function> with an
- struct <structname>snd_ac97_template</structname>
- record together with the bus pointer created above.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_ac97_template ac97;
- int err;
-
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
- snd_ac97_mixer(bus, &ac97, &chip->ac97);
-]]>
- </programlisting>
- </informalexample>
-
- where chip-&gt;ac97 is a pointer to a newly created
- <type>ac97_t</type> instance.
- In this case, the chip pointer is set as the private data, so that
- the read/write callback functions can refer to this chip instance.
- This instance is not necessarily stored in the chip
- record. If you need to change the register values from the
- driver, or need the suspend/resume of ac97 codecs, keep this
- pointer to pass to the corresponding functions.
- </para>
- </section>
-
- <section id="api-ac97-callbacks">
- <title>Callbacks</title>
- <para>
- The standard callbacks are <structfield>read</structfield> and
- <structfield>write</structfield>. Obviously they
- correspond to the functions for read and write accesses to the
- hardware low-level codes.
- </para>
-
- <para>
- The <structfield>read</structfield> callback returns the
- register value specified in the argument.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
- unsigned short reg)
- {
- struct mychip *chip = ac97->private_data;
- ....
- return the_register_value;
- }
-]]>
- </programlisting>
- </informalexample>
-
- Here, the chip can be cast from ac97-&gt;private_data.
- </para>
-
- <para>
- Meanwhile, the <structfield>write</structfield> callback is
- used to set the register value.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
- unsigned short reg, unsigned short val)
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- These callbacks are non-atomic like the control API callbacks.
- </para>
-
- <para>
- There are also other callbacks:
- <structfield>reset</structfield>,
- <structfield>wait</structfield> and
- <structfield>init</structfield>.
- </para>
-
- <para>
- The <structfield>reset</structfield> callback is used to reset
- the codec. If the chip requires a special kind of reset, you can
- define this callback.
- </para>
-
- <para>
- The <structfield>wait</structfield> callback is used to
- add some waiting time in the standard initialization of the codec. If the
- chip requires the extra waiting time, define this callback.
- </para>
-
- <para>
- The <structfield>init</structfield> callback is used for
- additional initialization of the codec.
- </para>
- </section>
-
- <section id="api-ac97-updating-registers">
- <title>Updating Registers in The Driver</title>
- <para>
- If you need to access to the codec from the driver, you can
- call the following functions:
- <function>snd_ac97_write()</function>,
- <function>snd_ac97_read()</function>,
- <function>snd_ac97_update()</function> and
- <function>snd_ac97_update_bits()</function>.
- </para>
-
- <para>
- Both <function>snd_ac97_write()</function> and
- <function>snd_ac97_update()</function> functions are used to
- set a value to the given register
- (<constant>AC97_XXX</constant>). The difference between them is
- that <function>snd_ac97_update()</function> doesn't write a
- value if the given value has been already set, while
- <function>snd_ac97_write()</function> always rewrites the
- value.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_ac97_write(ac97, AC97_MASTER, 0x8080);
- snd_ac97_update(ac97, AC97_MASTER, 0x8080);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- <function>snd_ac97_read()</function> is used to read the value
- of the given register. For example,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- value = snd_ac97_read(ac97, AC97_MASTER);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- <function>snd_ac97_update_bits()</function> is used to update
- some bits in the given register.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_ac97_update_bits(ac97, reg, mask, value);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Also, there is a function to change the sample rate (of a
- given register such as
- <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA or
- DRA is supported by the codec:
- <function>snd_ac97_set_rate()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The following registers are available to set the rate:
- <constant>AC97_PCM_MIC_ADC_RATE</constant>,
- <constant>AC97_PCM_FRONT_DAC_RATE</constant>,
- <constant>AC97_PCM_LR_ADC_RATE</constant>,
- <constant>AC97_SPDIF</constant>. When
- <constant>AC97_SPDIF</constant> is specified, the register is
- not really changed but the corresponding IEC958 status bits will
- be updated.
- </para>
- </section>
-
- <section id="api-ac97-clock-adjustment">
- <title>Clock Adjustment</title>
- <para>
- In some chips, the clock of the codec isn't 48000 but using a
- PCI clock (to save a quartz!). In this case, change the field
- bus-&gt;clock to the corresponding
- value. For example, intel8x0
- and es1968 drivers have their own function to read from the clock.
- </para>
- </section>
-
- <section id="api-ac97-proc-files">
- <title>Proc Files</title>
- <para>
- The ALSA AC97 interface will create a proc file such as
- <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
- <filename>ac97#0-0+regs</filename>. You can refer to these files to
- see the current status and registers of the codec.
- </para>
- </section>
-
- <section id="api-ac97-multiple-codecs">
- <title>Multiple Codecs</title>
- <para>
- When there are several codecs on the same card, you need to
- call <function>snd_ac97_mixer()</function> multiple times with
- ac97.num=1 or greater. The <structfield>num</structfield> field
- specifies the codec number.
- </para>
-
- <para>
- If you set up multiple codecs, you either need to write
- different callbacks for each codec or check
- ac97-&gt;num in the callback routines.
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- MIDI (MPU401-UART) Interface -->
-<!-- ****************************************************** -->
- <chapter id="midi-interface">
- <title>MIDI (MPU401-UART) Interface</title>
-
- <section id="midi-interface-general">
- <title>General</title>
- <para>
- Many soundcards have built-in MIDI (MPU401-UART)
- interfaces. When the soundcard supports the standard MPU401-UART
- interface, most likely you can use the ALSA MPU401-UART API. The
- MPU401-UART API is defined in
- <filename>&lt;sound/mpu401.h&gt;</filename>.
- </para>
-
- <para>
- Some soundchips have a similar but slightly different
- implementation of mpu401 stuff. For example, emu10k1 has its own
- mpu401 routines.
- </para>
- </section>
-
- <section id="midi-interface-constructor">
- <title>Constructor</title>
- <para>
- To create a rawmidi object, call
- <function>snd_mpu401_uart_new()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_rawmidi *rmidi;
- snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
- irq, &rmidi);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The first argument is the card pointer, and the second is the
- index of this component. You can create up to 8 rawmidi
- devices.
- </para>
-
- <para>
- The third argument is the type of the hardware,
- <constant>MPU401_HW_XXX</constant>. If it's not a special one,
- you can use <constant>MPU401_HW_MPU401</constant>.
- </para>
-
- <para>
- The 4th argument is the I/O port address. Many
- backward-compatible MPU401 have an I/O port such as 0x330. Or, it
- might be a part of its own PCI I/O region. It depends on the
- chip design.
- </para>
-
- <para>
- The 5th argument is a bitflag for additional information.
- When the I/O port address above is part of the PCI I/O
- region, the MPU401 I/O port might have been already allocated
- (reserved) by the driver itself. In such a case, pass a bit flag
- <constant>MPU401_INFO_INTEGRATED</constant>,
- and the mpu401-uart layer will allocate the I/O ports by itself.
- </para>
-
- <para>
- When the controller supports only the input or output MIDI stream,
- pass the <constant>MPU401_INFO_INPUT</constant> or
- <constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
- Then the rawmidi instance is created as a single stream.
- </para>
-
- <para>
- <constant>MPU401_INFO_MMIO</constant> bitflag is used to change
- the access method to MMIO (via readb and writeb) instead of
- iob and outb. In this case, you have to pass the iomapped address
- to <function>snd_mpu401_uart_new()</function>.
- </para>
-
- <para>
- When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
- stream isn't checked in the default interrupt handler. The driver
- needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
- by itself to start processing the output stream in the irq handler.
- </para>
-
- <para>
- If the MPU-401 interface shares its interrupt with the other logical
- devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
- (see <link linkend="midi-interface-interrupt-handler"><citetitle>
- below</citetitle></link>).
- </para>
-
- <para>
- Usually, the port address corresponds to the command port and
- port + 1 corresponds to the data port. If not, you may change
- the <structfield>cport</structfield> field of
- struct <structname>snd_mpu401</structname> manually
- afterward. However, <structname>snd_mpu401</structname> pointer is not
- returned explicitly by
- <function>snd_mpu401_uart_new()</function>. You need to cast
- rmidi-&gt;private_data to
- <structname>snd_mpu401</structname> explicitly,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_mpu401 *mpu;
- mpu = rmidi->private_data;
-]]>
- </programlisting>
- </informalexample>
-
- and reset the cport as you like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- mpu->cport = my_own_control_port;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The 6th argument specifies the ISA irq number that will be
- allocated. If no interrupt is to be allocated (because your
- code is already allocating a shared interrupt, or because the
- device does not use interrupts), pass -1 instead.
- For a MPU-401 device without an interrupt, a polling timer
- will be used instead.
- </para>
- </section>
-
- <section id="midi-interface-interrupt-handler">
- <title>Interrupt Handler</title>
- <para>
- When the interrupt is allocated in
- <function>snd_mpu401_uart_new()</function>, an exclusive ISA
- interrupt handler is automatically used, hence you don't have
- anything else to do than creating the mpu401 stuff. Otherwise, you
- have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
- <function>snd_mpu401_uart_interrupt()</function> explicitly from your
- own interrupt handler when it has determined that a UART interrupt
- has occurred.
- </para>
-
- <para>
- In this case, you need to pass the private_data of the
- returned rawmidi object from
- <function>snd_mpu401_uart_new()</function> as the second
- argument of <function>snd_mpu401_uart_interrupt()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- RawMIDI Interface -->
-<!-- ****************************************************** -->
- <chapter id="rawmidi-interface">
- <title>RawMIDI Interface</title>
-
- <section id="rawmidi-interface-overview">
- <title>Overview</title>
-
- <para>
- The raw MIDI interface is used for hardware MIDI ports that can
- be accessed as a byte stream. It is not used for synthesizer
- chips that do not directly understand MIDI.
- </para>
-
- <para>
- ALSA handles file and buffer management. All you have to do is
- to write some code to move data between the buffer and the
- hardware.
- </para>
-
- <para>
- The rawmidi API is defined in
- <filename>&lt;sound/rawmidi.h&gt;</filename>.
- </para>
- </section>
-
- <section id="rawmidi-interface-constructor">
- <title>Constructor</title>
-
- <para>
- To create a rawmidi device, call the
- <function>snd_rawmidi_new</function> function:
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_rawmidi *rmidi;
- err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
- if (err < 0)
- return err;
- rmidi->private_data = chip;
- strcpy(rmidi->name, "My MIDI");
- rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
- SNDRV_RAWMIDI_INFO_INPUT |
- SNDRV_RAWMIDI_INFO_DUPLEX;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The first argument is the card pointer, the second argument is
- the ID string.
- </para>
-
- <para>
- The third argument is the index of this component. You can
- create up to 8 rawmidi devices.
- </para>
-
- <para>
- The fourth and fifth arguments are the number of output and
- input substreams, respectively, of this device (a substream is
- the equivalent of a MIDI port).
- </para>
-
- <para>
- Set the <structfield>info_flags</structfield> field to specify
- the capabilities of the device.
- Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
- at least one output port,
- <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
- least one input port,
- and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
- can handle output and input at the same time.
- </para>
-
- <para>
- After the rawmidi device is created, you need to set the
- operators (callbacks) for each substream. There are helper
- functions to set the operators for all the substreams of a device:
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The operators are usually defined like this:
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct snd_rawmidi_ops snd_mymidi_output_ops = {
- .open = snd_mymidi_output_open,
- .close = snd_mymidi_output_close,
- .trigger = snd_mymidi_output_trigger,
- };
-]]>
- </programlisting>
- </informalexample>
- These callbacks are explained in the <link
- linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
- section.
- </para>
-
- <para>
- If there are more than one substream, you should give a
- unique name to each of them:
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_rawmidi_substream *substream;
- list_for_each_entry(substream,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
- list {
- sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
- }
- /* same for SNDRV_RAWMIDI_STREAM_INPUT */
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- <section id="rawmidi-interface-callbacks">
- <title>Callbacks</title>
-
- <para>
- In all the callbacks, the private data that you've set for the
- rawmidi device can be accessed as
- substream-&gt;rmidi-&gt;private_data.
- <!-- <code> isn't available before DocBook 4.3 -->
- </para>
-
- <para>
- If there is more than one port, your callbacks can determine the
- port index from the struct snd_rawmidi_substream data passed to each
- callback:
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_rawmidi_substream *substream;
- int index = substream->number;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <section id="rawmidi-interface-op-open">
- <title><function>open</function> callback</title>
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_open(struct snd_rawmidi_substream *substream);
-]]>
- </programlisting>
- </informalexample>
-
- <para>
- This is called when a substream is opened.
- You can initialize the hardware here, but you shouldn't
- start transmitting/receiving data yet.
- </para>
- </section>
-
- <section id="rawmidi-interface-op-close">
- <title><function>close</function> callback</title>
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_xxx_close(struct snd_rawmidi_substream *substream);
-]]>
- </programlisting>
- </informalexample>
-
- <para>
- Guess what.
- </para>
-
- <para>
- The <function>open</function> and <function>close</function>
- callbacks of a rawmidi device are serialized with a mutex,
- and can sleep.
- </para>
- </section>
-
- <section id="rawmidi-interface-op-trigger-out">
- <title><function>trigger</function> callback for output
- substreams</title>
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
- </programlisting>
- </informalexample>
-
- <para>
- This is called with a nonzero <parameter>up</parameter>
- parameter when there is some data in the substream buffer that
- must be transmitted.
- </para>
-
- <para>
- To read data from the buffer, call
- <function>snd_rawmidi_transmit_peek</function>. It will
- return the number of bytes that have been read; this will be
- less than the number of bytes requested when there are no more
- data in the buffer.
- After the data have been transmitted successfully, call
- <function>snd_rawmidi_transmit_ack</function> to remove the
- data from the substream buffer:
- <informalexample>
- <programlisting>
-<![CDATA[
- unsigned char data;
- while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
- if (snd_mychip_try_to_transmit(data))
- snd_rawmidi_transmit_ack(substream, 1);
- else
- break; /* hardware FIFO full */
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- If you know beforehand that the hardware will accept data, you
- can use the <function>snd_rawmidi_transmit</function> function
- which reads some data and removes them from the buffer at once:
- <informalexample>
- <programlisting>
-<![CDATA[
- while (snd_mychip_transmit_possible()) {
- unsigned char data;
- if (snd_rawmidi_transmit(substream, &data, 1) != 1)
- break; /* no more data */
- snd_mychip_transmit(data);
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- If you know beforehand how many bytes you can accept, you can
- use a buffer size greater than one with the
- <function>snd_rawmidi_transmit*</function> functions.
- </para>
-
- <para>
- The <function>trigger</function> callback must not sleep. If
- the hardware FIFO is full before the substream buffer has been
- emptied, you have to continue transmitting data later, either
- in an interrupt handler, or with a timer if the hardware
- doesn't have a MIDI transmit interrupt.
- </para>
-
- <para>
- The <function>trigger</function> callback is called with a
- zero <parameter>up</parameter> parameter when the transmission
- of data should be aborted.
- </para>
- </section>
-
- <section id="rawmidi-interface-op-trigger-in">
- <title><function>trigger</function> callback for input
- substreams</title>
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
- </programlisting>
- </informalexample>
-
- <para>
- This is called with a nonzero <parameter>up</parameter>
- parameter to enable receiving data, or with a zero
- <parameter>up</parameter> parameter do disable receiving data.
- </para>
-
- <para>
- The <function>trigger</function> callback must not sleep; the
- actual reading of data from the device is usually done in an
- interrupt handler.
- </para>
-
- <para>
- When data reception is enabled, your interrupt handler should
- call <function>snd_rawmidi_receive</function> for all received
- data:
- <informalexample>
- <programlisting>
-<![CDATA[
- void snd_mychip_midi_interrupt(...)
- {
- while (mychip_midi_available()) {
- unsigned char data;
- data = mychip_midi_read();
- snd_rawmidi_receive(substream, &data, 1);
- }
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- <section id="rawmidi-interface-op-drain">
- <title><function>drain</function> callback</title>
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
-]]>
- </programlisting>
- </informalexample>
-
- <para>
- This is only used with output substreams. This function should wait
- until all data read from the substream buffer have been transmitted.
- This ensures that the device can be closed and the driver unloaded
- without losing data.
- </para>
-
- <para>
- This callback is optional. If you do not set
- <structfield>drain</structfield> in the struct snd_rawmidi_ops
- structure, ALSA will simply wait for 50&nbsp;milliseconds
- instead.
- </para>
- </section>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Miscellaneous Devices -->
-<!-- ****************************************************** -->
- <chapter id="misc-devices">
- <title>Miscellaneous Devices</title>
-
- <section id="misc-devices-opl3">
- <title>FM OPL3</title>
- <para>
- The FM OPL3 is still used in many chips (mainly for backward
- compatibility). ALSA has a nice OPL3 FM control layer, too. The
- OPL3 API is defined in
- <filename>&lt;sound/opl3.h&gt;</filename>.
- </para>
-
- <para>
- FM registers can be directly accessed through the direct-FM API,
- defined in <filename>&lt;sound/asound_fm.h&gt;</filename>. In
- ALSA native mode, FM registers are accessed through
- the Hardware-Dependent Device direct-FM extension API, whereas in
- OSS compatible mode, FM registers can be accessed with the OSS
- direct-FM compatible API in <filename>/dev/dmfmX</filename> device.
- </para>
-
- <para>
- To create the OPL3 component, you have two functions to
- call. The first one is a constructor for the <type>opl3_t</type>
- instance.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_opl3 *opl3;
- snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
- integrated, &opl3);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The first argument is the card pointer, the second one is the
- left port address, and the third is the right port address. In
- most cases, the right port is placed at the left port + 2.
- </para>
-
- <para>
- The fourth argument is the hardware type.
- </para>
-
- <para>
- When the left and right ports have been already allocated by
- the card driver, pass non-zero to the fifth argument
- (<parameter>integrated</parameter>). Otherwise, the opl3 module will
- allocate the specified ports by itself.
- </para>
-
- <para>
- When the accessing the hardware requires special method
- instead of the standard I/O access, you can create opl3 instance
- separately with <function>snd_opl3_new()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_opl3 *opl3;
- snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Then set <structfield>command</structfield>,
- <structfield>private_data</structfield> and
- <structfield>private_free</structfield> for the private
- access function, the private data and the destructor.
- The l_port and r_port are not necessarily set. Only the
- command must be set properly. You can retrieve the data
- from the opl3-&gt;private_data field.
- </para>
-
- <para>
- After creating the opl3 instance via <function>snd_opl3_new()</function>,
- call <function>snd_opl3_init()</function> to initialize the chip to the
- proper state. Note that <function>snd_opl3_create()</function> always
- calls it internally.
- </para>
-
- <para>
- If the opl3 instance is created successfully, then create a
- hwdep device for this opl3.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_hwdep *opl3hwdep;
- snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The first argument is the <type>opl3_t</type> instance you
- created, and the second is the index number, usually 0.
- </para>
-
- <para>
- The third argument is the index-offset for the sequencer
- client assigned to the OPL3 port. When there is an MPU401-UART,
- give 1 for here (UART always takes 0).
- </para>
- </section>
-
- <section id="misc-devices-hardware-dependent">
- <title>Hardware-Dependent Devices</title>
- <para>
- Some chips need user-space access for special
- controls or for loading the micro code. In such a case, you can
- create a hwdep (hardware-dependent) device. The hwdep API is
- defined in <filename>&lt;sound/hwdep.h&gt;</filename>. You can
- find examples in opl3 driver or
- <filename>isa/sb/sb16_csp.c</filename>.
- </para>
-
- <para>
- The creation of the <type>hwdep</type> instance is done via
- <function>snd_hwdep_new()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_hwdep *hw;
- snd_hwdep_new(card, "My HWDEP", 0, &hw);
-]]>
- </programlisting>
- </informalexample>
-
- where the third argument is the index number.
- </para>
-
- <para>
- You can then pass any pointer value to the
- <parameter>private_data</parameter>.
- If you assign a private data, you should define the
- destructor, too. The destructor function is set in
- the <structfield>private_free</structfield> field.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
- hw->private_data = p;
- hw->private_free = mydata_free;
-]]>
- </programlisting>
- </informalexample>
-
- and the implementation of the destructor would be:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void mydata_free(struct snd_hwdep *hw)
- {
- struct mydata *p = hw->private_data;
- kfree(p);
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The arbitrary file operations can be defined for this
- instance. The file operators are defined in
- the <parameter>ops</parameter> table. For example, assume that
- this chip needs an ioctl.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- hw->ops.open = mydata_open;
- hw->ops.ioctl = mydata_ioctl;
- hw->ops.release = mydata_release;
-]]>
- </programlisting>
- </informalexample>
-
- And implement the callback functions as you like.
- </para>
- </section>
-
- <section id="misc-devices-IEC958">
- <title>IEC958 (S/PDIF)</title>
- <para>
- Usually the controls for IEC958 devices are implemented via
- the control interface. There is a macro to compose a name string for
- IEC958 controls, <function>SNDRV_CTL_NAME_IEC958()</function>
- defined in <filename>&lt;include/asound.h&gt;</filename>.
- </para>
-
- <para>
- There are some standard controls for IEC958 status bits. These
- controls use the type <type>SNDRV_CTL_ELEM_TYPE_IEC958</type>,
- and the size of element is fixed as 4 bytes array
- (value.iec958.status[x]). For the <structfield>info</structfield>
- callback, you don't specify
- the value field for this type (the count field must be set,
- though).
- </para>
-
- <para>
- <quote>IEC958 Playback Con Mask</quote> is used to return the
- bit-mask for the IEC958 status bits of consumer mode. Similarly,
- <quote>IEC958 Playback Pro Mask</quote> returns the bitmask for
- professional mode. They are read-only controls, and are defined
- as MIXER controls (iface =
- <constant>SNDRV_CTL_ELEM_IFACE_MIXER</constant>).
- </para>
-
- <para>
- Meanwhile, <quote>IEC958 Playback Default</quote> control is
- defined for getting and setting the current default IEC958
- bits. Note that this one is usually defined as a PCM control
- (iface = <constant>SNDRV_CTL_ELEM_IFACE_PCM</constant>),
- although in some places it's defined as a MIXER control.
- </para>
-
- <para>
- In addition, you can define the control switches to
- enable/disable or to set the raw bit mode. The implementation
- will depend on the chip, but the control should be named as
- <quote>IEC958 xxx</quote>, preferably using
- the <function>SNDRV_CTL_NAME_IEC958()</function> macro.
- </para>
-
- <para>
- You can find several cases, for example,
- <filename>pci/emu10k1</filename>,
- <filename>pci/ice1712</filename>, or
- <filename>pci/cmipci.c</filename>.
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Buffer and Memory Management -->
-<!-- ****************************************************** -->
- <chapter id="buffer-and-memory">
- <title>Buffer and Memory Management</title>
-
- <section id="buffer-and-memory-buffer-types">
- <title>Buffer Types</title>
- <para>
- ALSA provides several different buffer allocation functions
- depending on the bus and the architecture. All these have a
- consistent API. The allocation of physically-contiguous pages is
- done via
- <function>snd_malloc_xxx_pages()</function> function, where xxx
- is the bus type.
- </para>
-
- <para>
- The allocation of pages with fallback is
- <function>snd_malloc_xxx_pages_fallback()</function>. This
- function tries to allocate the specified pages but if the pages
- are not available, it tries to reduce the page sizes until
- enough space is found.
- </para>
-
- <para>
- The release the pages, call
- <function>snd_free_xxx_pages()</function> function.
- </para>
-
- <para>
- Usually, ALSA drivers try to allocate and reserve
- a large contiguous physical space
- at the time the module is loaded for the later use.
- This is called <quote>pre-allocation</quote>.
- As already written, you can call the following function at
- pcm instance construction time (in the case of PCI bus).
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(pci), size, max);
-]]>
- </programlisting>
- </informalexample>
-
- where <parameter>size</parameter> is the byte size to be
- pre-allocated and the <parameter>max</parameter> is the maximum
- size to be changed via the <filename>prealloc</filename> proc file.
- The allocator will try to get an area as large as possible
- within the given size.
- </para>
-
- <para>
- The second argument (type) and the third argument (device pointer)
- are dependent on the bus.
- In the case of the ISA bus, pass <function>snd_dma_isa_data()</function>
- as the third argument with <constant>SNDRV_DMA_TYPE_DEV</constant> type.
- For the continuous buffer unrelated to the bus can be pre-allocated
- with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the
- <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer,
- where <constant>GFP_KERNEL</constant> is the kernel allocation flag to
- use.
- For the PCI scatter-gather buffers, use
- <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with
- <function>snd_dma_pci_data(pci)</function>
- (see the
- <link linkend="buffer-and-memory-non-contiguous"><citetitle>Non-Contiguous Buffers
- </citetitle></link> section).
- </para>
-
- <para>
- Once the buffer is pre-allocated, you can use the
- allocator in the <structfield>hw_params</structfield> callback:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_pcm_lib_malloc_pages(substream, size);
-]]>
- </programlisting>
- </informalexample>
-
- Note that you have to pre-allocate to use this function.
- </para>
- </section>
-
- <section id="buffer-and-memory-external-hardware">
- <title>External Hardware Buffers</title>
- <para>
- Some chips have their own hardware buffers and the DMA
- transfer from the host memory is not available. In such a case,
- you need to either 1) copy/set the audio data directly to the
- external hardware buffer, or 2) make an intermediate buffer and
- copy/set the data from it to the external hardware buffer in
- interrupts (or in tasklets, preferably).
- </para>
-
- <para>
- The first case works fine if the external hardware buffer is large
- enough. This method doesn't need any extra buffers and thus is
- more effective. You need to define the
- <structfield>copy</structfield> and
- <structfield>silence</structfield> callbacks for
- the data transfer. However, there is a drawback: it cannot
- be mmapped. The examples are GUS's GF1 PCM or emu8000's
- wavetable PCM.
- </para>
-
- <para>
- The second case allows for mmap on the buffer, although you have
- to handle an interrupt or a tasklet to transfer the data
- from the intermediate buffer to the hardware buffer. You can find an
- example in the vxpocket driver.
- </para>
-
- <para>
- Another case is when the chip uses a PCI memory-map
- region for the buffer instead of the host memory. In this case,
- mmap is available only on certain architectures like the Intel one.
- In non-mmap mode, the data cannot be transferred as in the normal
- way. Thus you need to define the <structfield>copy</structfield> and
- <structfield>silence</structfield> callbacks as well,
- as in the cases above. The examples are found in
- <filename>rme32.c</filename> and <filename>rme96.c</filename>.
- </para>
-
- <para>
- The implementation of the <structfield>copy</structfield> and
- <structfield>silence</structfield> callbacks depends upon
- whether the hardware supports interleaved or non-interleaved
- samples. The <structfield>copy</structfield> callback is
- defined like below, a bit
- differently depending whether the direction is playback or
- capture:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int playback_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
- static int capture_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- In the case of interleaved samples, the second argument
- (<parameter>channel</parameter>) is not used. The third argument
- (<parameter>pos</parameter>) points the
- current position offset in frames.
- </para>
-
- <para>
- The meaning of the fourth argument is different between
- playback and capture. For playback, it holds the source data
- pointer, and for capture, it's the destination data pointer.
- </para>
-
- <para>
- The last argument is the number of frames to be copied.
- </para>
-
- <para>
- What you have to do in this callback is again different
- between playback and capture directions. In the
- playback case, you copy the given amount of data
- (<parameter>count</parameter>) at the specified pointer
- (<parameter>src</parameter>) to the specified offset
- (<parameter>pos</parameter>) on the hardware buffer. When
- coded like memcpy-like way, the copy would be like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
- frames_to_bytes(runtime, count));
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- For the capture direction, you copy the given amount of
- data (<parameter>count</parameter>) at the specified offset
- (<parameter>pos</parameter>) on the hardware buffer to the
- specified pointer (<parameter>dst</parameter>).
-
- <informalexample>
- <programlisting>
-<![CDATA[
- my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
- frames_to_bytes(runtime, count));
-]]>
- </programlisting>
- </informalexample>
-
- Note that both the position and the amount of data are given
- in frames.
- </para>
-
- <para>
- In the case of non-interleaved samples, the implementation
- will be a bit more complicated.
- </para>
-
- <para>
- You need to check the channel argument, and if it's -1, copy
- the whole channels. Otherwise, you have to copy only the
- specified channel. Please check
- <filename>isa/gus/gus_pcm.c</filename> as an example.
- </para>
-
- <para>
- The <structfield>silence</structfield> callback is also
- implemented in a similar way.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int silence(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The meanings of arguments are the same as in the
- <structfield>copy</structfield>
- callback, although there is no <parameter>src/dst</parameter>
- argument. In the case of interleaved samples, the channel
- argument has no meaning, as well as on
- <structfield>copy</structfield> callback.
- </para>
-
- <para>
- The role of <structfield>silence</structfield> callback is to
- set the given amount
- (<parameter>count</parameter>) of silence data at the
- specified offset (<parameter>pos</parameter>) on the hardware
- buffer. Suppose that the data format is signed (that is, the
- silent-data is 0), and the implementation using a memset-like
- function would be like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
- frames_to_bytes(runtime, count));
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- In the case of non-interleaved samples, again, the
- implementation becomes a bit more complicated. See, for example,
- <filename>isa/gus/gus_pcm.c</filename>.
- </para>
- </section>
-
- <section id="buffer-and-memory-non-contiguous">
- <title>Non-Contiguous Buffers</title>
- <para>
- If your hardware supports the page table as in emu10k1 or the
- buffer descriptors as in via82xx, you can use the scatter-gather
- (SG) DMA. ALSA provides an interface for handling SG-buffers.
- The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>.
- </para>
-
- <para>
- For creating the SG-buffer handler, call
- <function>snd_pcm_lib_preallocate_pages()</function> or
- <function>snd_pcm_lib_preallocate_pages_for_all()</function>
- with <constant>SNDRV_DMA_TYPE_DEV_SG</constant>
- in the PCM constructor like other PCI pre-allocator.
- You need to pass <function>snd_dma_pci_data(pci)</function>,
- where pci is the struct <structname>pci_dev</structname> pointer
- of the chip as well.
- The <type>struct snd_sg_buf</type> instance is created as
- substream-&gt;dma_private. You can cast
- the pointer like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Then call <function>snd_pcm_lib_malloc_pages()</function>
- in the <structfield>hw_params</structfield> callback
- as well as in the case of normal PCI buffer.
- The SG-buffer handler will allocate the non-contiguous kernel
- pages of the given size and map them onto the virtually contiguous
- memory. The virtual pointer is addressed in runtime-&gt;dma_area.
- The physical address (runtime-&gt;dma_addr) is set to zero,
- because the buffer is physically non-contiguous.
- The physical address table is set up in sgbuf-&gt;table.
- You can get the physical address at a certain offset via
- <function>snd_pcm_sgbuf_get_addr()</function>.
- </para>
-
- <para>
- When a SG-handler is used, you need to set
- <function>snd_pcm_sgbuf_ops_page</function> as
- the <structfield>page</structfield> callback.
- (See <link linkend="pcm-interface-operators-page-callback">
- <citetitle>page callback section</citetitle></link>.)
- </para>
-
- <para>
- To release the data, call
- <function>snd_pcm_lib_free_pages()</function> in the
- <structfield>hw_free</structfield> callback as usual.
- </para>
- </section>
-
- <section id="buffer-and-memory-vmalloced">
- <title>Vmalloc'ed Buffers</title>
- <para>
- It's possible to use a buffer allocated via
- <function>vmalloc</function>, for example, for an intermediate
- buffer. Since the allocated pages are not contiguous, you need
- to set the <structfield>page</structfield> callback to obtain
- the physical address at every offset.
- </para>
-
- <para>
- The implementation of <structfield>page</structfield> callback
- would be like this:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- #include <linux/vmalloc.h>
-
- /* get the physical page pointer on the given offset */
- static struct page *mychip_page(struct snd_pcm_substream *substream,
- unsigned long offset)
- {
- void *pageptr = substream->runtime->dma_area + offset;
- return vmalloc_to_page(pageptr);
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Proc Interface -->
-<!-- ****************************************************** -->
- <chapter id="proc-interface">
- <title>Proc Interface</title>
- <para>
- ALSA provides an easy interface for procfs. The proc files are
- very useful for debugging. I recommend you set up proc files if
- you write a driver and want to get a running status or register
- dumps. The API is found in
- <filename>&lt;sound/info.h&gt;</filename>.
- </para>
-
- <para>
- To create a proc file, call
- <function>snd_card_proc_new()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- struct snd_info_entry *entry;
- int err = snd_card_proc_new(card, "my-file", &entry);
-]]>
- </programlisting>
- </informalexample>
-
- where the second argument specifies the name of the proc file to be
- created. The above example will create a file
- <filename>my-file</filename> under the card directory,
- e.g. <filename>/proc/asound/card0/my-file</filename>.
- </para>
-
- <para>
- Like other components, the proc entry created via
- <function>snd_card_proc_new()</function> will be registered and
- released automatically in the card registration and release
- functions.
- </para>
-
- <para>
- When the creation is successful, the function stores a new
- instance in the pointer given in the third argument.
- It is initialized as a text proc file for read only. To use
- this proc file as a read-only text file as it is, set the read
- callback with a private data via
- <function>snd_info_set_text_ops()</function>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_info_set_text_ops(entry, chip, my_proc_read);
-]]>
- </programlisting>
- </informalexample>
-
- where the second argument (<parameter>chip</parameter>) is the
- private data to be used in the callbacks. The third parameter
- specifies the read buffer size and the fourth
- (<parameter>my_proc_read</parameter>) is the callback function, which
- is defined like
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void my_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer);
-]]>
- </programlisting>
- </informalexample>
-
- </para>
-
- <para>
- In the read callback, use <function>snd_iprintf()</function> for
- output strings, which works just like normal
- <function>printf()</function>. For example,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static void my_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
- {
- struct my_chip *chip = entry->private_data;
-
- snd_iprintf(buffer, "This is my chip!\n");
- snd_iprintf(buffer, "Port = %ld\n", chip->port);
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The file permissions can be changed afterwards. As default, it's
- set as read only for all users. If you want to add write
- permission for the user (root as default), do as follows:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-]]>
- </programlisting>
- </informalexample>
-
- and set the write buffer size and the callback
-
- <informalexample>
- <programlisting>
-<![CDATA[
- entry->c.text.write = my_proc_write;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- For the write callback, you can use
- <function>snd_info_get_line()</function> to get a text line, and
- <function>snd_info_get_str()</function> to retrieve a string from
- the line. Some examples are found in
- <filename>core/oss/mixer_oss.c</filename>, core/oss/and
- <filename>pcm_oss.c</filename>.
- </para>
-
- <para>
- For a raw-data proc-file, set the attributes as follows:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct snd_info_entry_ops my_file_io_ops = {
- .read = my_file_io_read,
- };
-
- entry->content = SNDRV_INFO_CONTENT_DATA;
- entry->private_data = chip;
- entry->c.ops = &my_file_io_ops;
- entry->size = 4096;
- entry->mode = S_IFREG | S_IRUGO;
-]]>
- </programlisting>
- </informalexample>
-
- For the raw data, <structfield>size</structfield> field must be
- set properly. This specifies the maximum size of the proc file access.
- </para>
-
- <para>
- The read/write callbacks of raw mode are more direct than the text mode.
- You need to use a low-level I/O functions such as
- <function>copy_from/to_user()</function> to transfer the
- data.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static ssize_t my_file_io_read(struct snd_info_entry *entry,
- void *file_private_data,
- struct file *file,
- char *buf,
- size_t count,
- loff_t pos)
- {
- if (copy_to_user(buf, local_data + pos, count))
- return -EFAULT;
- return count;
- }
-]]>
- </programlisting>
- </informalexample>
-
- If the size of the info entry has been set up properly,
- <structfield>count</structfield> and <structfield>pos</structfield> are
- guaranteed to fit within 0 and the given size.
- You don't have to check the range in the callbacks unless any
- other condition is required.
-
- </para>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Power Management -->
-<!-- ****************************************************** -->
- <chapter id="power-management">
- <title>Power Management</title>
- <para>
- If the chip is supposed to work with suspend/resume
- functions, you need to add power-management code to the
- driver. The additional code for power-management should be
- <function>ifdef</function>'ed with
- <constant>CONFIG_PM</constant>.
- </para>
-
- <para>
- If the driver <emphasis>fully</emphasis> supports suspend/resume
- that is, the device can be
- properly resumed to its state when suspend was called,
- you can set the <constant>SNDRV_PCM_INFO_RESUME</constant> flag
- in the pcm info field. Usually, this is possible when the
- registers of the chip can be safely saved and restored to
- RAM. If this is set, the trigger callback is called with
- <constant>SNDRV_PCM_TRIGGER_RESUME</constant> after the resume
- callback completes.
- </para>
-
- <para>
- Even if the driver doesn't support PM fully but
- partial suspend/resume is still possible, it's still worthy to
- implement suspend/resume callbacks. In such a case, applications
- would reset the status by calling
- <function>snd_pcm_prepare()</function> and restart the stream
- appropriately. Hence, you can define suspend/resume callbacks
- below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant>
- info flag to the PCM.
- </para>
-
- <para>
- Note that the trigger with SUSPEND can always be called when
- <function>snd_pcm_suspend_all</function> is called,
- regardless of the <constant>SNDRV_PCM_INFO_RESUME</constant> flag.
- The <constant>RESUME</constant> flag affects only the behavior
- of <function>snd_pcm_resume()</function>.
- (Thus, in theory,
- <constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed
- to be handled in the trigger callback when no
- <constant>SNDRV_PCM_INFO_RESUME</constant> flag is set. But,
- it's better to keep it for compatibility reasons.)
- </para>
- <para>
- In the earlier version of ALSA drivers, a common
- power-management layer was provided, but it has been removed.
- The driver needs to define the suspend/resume hooks according to
- the bus the device is connected to. In the case of PCI drivers, the
- callbacks look like below:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- #ifdef CONFIG_PM
- static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
- {
- .... /* do things for suspend */
- return 0;
- }
- static int snd_my_resume(struct pci_dev *pci)
- {
- .... /* do things for suspend */
- return 0;
- }
- #endif
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The scheme of the real suspend job is as follows.
-
- <orderedlist>
- <listitem><para>Retrieve the card and the chip data.</para></listitem>
- <listitem><para>Call <function>snd_power_change_state()</function> with
- <constant>SNDRV_CTL_POWER_D3hot</constant> to change the
- power status.</para></listitem>
- <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
- <listitem><para>If AC97 codecs are used, call
- <function>snd_ac97_suspend()</function> for each codec.</para></listitem>
- <listitem><para>Save the register values if necessary.</para></listitem>
- <listitem><para>Stop the hardware if necessary.</para></listitem>
- <listitem><para>Disable the PCI device by calling
- <function>pci_disable_device()</function>. Then, call
- <function>pci_save_state()</function> at last.</para></listitem>
- </orderedlist>
- </para>
-
- <para>
- A typical code would be like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
- {
- /* (1) */
- struct snd_card *card = pci_get_drvdata(pci);
- struct mychip *chip = card->private_data;
- /* (2) */
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- /* (3) */
- snd_pcm_suspend_all(chip->pcm);
- /* (4) */
- snd_ac97_suspend(chip->ac97);
- /* (5) */
- snd_mychip_save_registers(chip);
- /* (6) */
- snd_mychip_stop_hardware(chip);
- /* (7) */
- pci_disable_device(pci);
- pci_save_state(pci);
- return 0;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- The scheme of the real resume job is as follows.
-
- <orderedlist>
- <listitem><para>Retrieve the card and the chip data.</para></listitem>
- <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>.
- Then enable the pci device again by calling <function>pci_enable_device()</function>.
- Call <function>pci_set_master()</function> if necessary, too.</para></listitem>
- <listitem><para>Re-initialize the chip.</para></listitem>
- <listitem><para>Restore the saved registers if necessary.</para></listitem>
- <listitem><para>Resume the mixer, e.g. calling
- <function>snd_ac97_resume()</function>.</para></listitem>
- <listitem><para>Restart the hardware (if any).</para></listitem>
- <listitem><para>Call <function>snd_power_change_state()</function> with
- <constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem>
- </orderedlist>
- </para>
-
- <para>
- A typical code would be like:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int mychip_resume(struct pci_dev *pci)
- {
- /* (1) */
- struct snd_card *card = pci_get_drvdata(pci);
- struct mychip *chip = card->private_data;
- /* (2) */
- pci_restore_state(pci);
- pci_enable_device(pci);
- pci_set_master(pci);
- /* (3) */
- snd_mychip_reinit_chip(chip);
- /* (4) */
- snd_mychip_restore_registers(chip);
- /* (5) */
- snd_ac97_resume(chip->ac97);
- /* (6) */
- snd_mychip_restart_chip(chip);
- /* (7) */
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- return 0;
- }
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- As shown in the above, it's better to save registers after
- suspending the PCM operations via
- <function>snd_pcm_suspend_all()</function> or
- <function>snd_pcm_suspend()</function>. It means that the PCM
- streams are already stopped when the register snapshot is
- taken. But, remember that you don't have to restart the PCM
- stream in the resume callback. It'll be restarted via
- trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant>
- when necessary.
- </para>
-
- <para>
- OK, we have all callbacks now. Let's set them up. In the
- initialization of the card, make sure that you can get the chip
- data from the card instance, typically via
- <structfield>private_data</structfield> field, in case you
- created the chip data individually.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
- {
- ....
- struct snd_card *card;
- struct mychip *chip;
- int err;
- ....
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
- ....
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- ....
- card->private_data = chip;
- ....
- }
-]]>
- </programlisting>
- </informalexample>
-
- When you created the chip data with
- <function>snd_card_new()</function>, it's anyway accessible
- via <structfield>private_data</structfield> field.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
- {
- ....
- struct snd_card *card;
- struct mychip *chip;
- int err;
- ....
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct mychip), &card);
- ....
- chip = card->private_data;
- ....
- }
-]]>
- </programlisting>
- </informalexample>
-
- </para>
-
- <para>
- If you need a space to save the registers, allocate the
- buffer for it here, too, since it would be fatal
- if you cannot allocate a memory in the suspend phase.
- The allocated buffer should be released in the corresponding
- destructor.
- </para>
-
- <para>
- And next, set suspend/resume callbacks to the pci_driver.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static struct pci_driver driver = {
- .name = KBUILD_MODNAME,
- .id_table = snd_my_ids,
- .probe = snd_my_probe,
- .remove = snd_my_remove,
- #ifdef CONFIG_PM
- .suspend = snd_my_suspend,
- .resume = snd_my_resume,
- #endif
- };
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Module Parameters -->
-<!-- ****************************************************** -->
- <chapter id="module-parameters">
- <title>Module Parameters</title>
- <para>
- There are standard module options for ALSA. At least, each
- module should have the <parameter>index</parameter>,
- <parameter>id</parameter> and <parameter>enable</parameter>
- options.
- </para>
-
- <para>
- If the module supports multiple cards (usually up to
- 8 = <constant>SNDRV_CARDS</constant> cards), they should be
- arrays. The default initial values are defined already as
- constants for easier programming:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
- static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
- static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- If the module supports only a single card, they could be single
- variables, instead. <parameter>enable</parameter> option is not
- always necessary in this case, but it would be better to have a
- dummy option for compatibility.
- </para>
-
- <para>
- The module parameters must be declared with the standard
- <function>module_param()()</function>,
- <function>module_param_array()()</function> and
- <function>MODULE_PARM_DESC()</function> macros.
- </para>
-
- <para>
- The typical coding would be like below:
-
- <informalexample>
- <programlisting>
-<![CDATA[
- #define CARD_NAME "My Chip"
-
- module_param_array(index, int, NULL, 0444);
- MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
- module_param_array(id, charp, NULL, 0444);
- MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
- module_param_array(enable, bool, NULL, 0444);
- MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- Also, don't forget to define the module description, classes,
- license and devices. Especially, the recent modprobe requires to
- define the module license as GPL, etc., otherwise the system is
- shown as <quote>tainted</quote>.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- MODULE_DESCRIPTION("My Chip");
- MODULE_LICENSE("GPL");
- MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- How To Put Your Driver -->
-<!-- ****************************************************** -->
- <chapter id="how-to-put-your-driver">
- <title>How To Put Your Driver Into ALSA Tree</title>
- <section>
- <title>General</title>
- <para>
- So far, you've learned how to write the driver codes.
- And you might have a question now: how to put my own
- driver into the ALSA driver tree?
- Here (finally :) the standard procedure is described briefly.
- </para>
-
- <para>
- Suppose that you create a new PCI driver for the card
- <quote>xyz</quote>. The card module name would be
- snd-xyz. The new driver is usually put into the alsa-driver
- tree, <filename>alsa-driver/pci</filename> directory in
- the case of PCI cards.
- Then the driver is evaluated, audited and tested
- by developers and users. After a certain time, the driver
- will go to the alsa-kernel tree (to the corresponding directory,
- such as <filename>alsa-kernel/pci</filename>) and eventually
- will be integrated into the Linux 2.6 tree (the directory would be
- <filename>linux/sound/pci</filename>).
- </para>
-
- <para>
- In the following sections, the driver code is supposed
- to be put into alsa-driver tree. The two cases are covered:
- a driver consisting of a single source file and one consisting
- of several source files.
- </para>
- </section>
-
- <section>
- <title>Driver with A Single Source File</title>
- <para>
- <orderedlist>
- <listitem>
- <para>
- Modify alsa-driver/pci/Makefile
- </para>
-
- <para>
- Suppose you have a file xyz.c. Add the following
- two lines
- <informalexample>
- <programlisting>
-<![CDATA[
- snd-xyz-objs := xyz.o
- obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-]]>
- </programlisting>
- </informalexample>
- </para>
- </listitem>
-
- <listitem>
- <para>
- Create the Kconfig entry
- </para>
-
- <para>
- Add the new entry of Kconfig for your xyz driver.
- <informalexample>
- <programlisting>
-<![CDATA[
- config SND_XYZ
- tristate "Foobar XYZ"
- depends on SND
- select SND_PCM
- help
- Say Y here to include support for Foobar XYZ soundcard.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-xyz.
-]]>
- </programlisting>
- </informalexample>
-
- the line, select SND_PCM, specifies that the driver xyz supports
- PCM. In addition to SND_PCM, the following components are
- supported for select command:
- SND_RAWMIDI, SND_TIMER, SND_HWDEP, SND_MPU401_UART,
- SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, SND_AC97_CODEC.
- Add the select command for each supported component.
- </para>
-
- <para>
- Note that some selections imply the lowlevel selections.
- For example, PCM includes TIMER, MPU401_UART includes RAWMIDI,
- AC97_CODEC includes PCM, and OPL3_LIB includes HWDEP.
- You don't need to give the lowlevel selections again.
- </para>
-
- <para>
- For the details of Kconfig script, refer to the kbuild
- documentation.
- </para>
-
- </listitem>
-
- <listitem>
- <para>
- Run cvscompile script to re-generate the configure script and
- build the whole stuff again.
- </para>
- </listitem>
- </orderedlist>
- </para>
- </section>
-
- <section>
- <title>Drivers with Several Source Files</title>
- <para>
- Suppose that the driver snd-xyz have several source files.
- They are located in the new subdirectory,
- pci/xyz.
-
- <orderedlist>
- <listitem>
- <para>
- Add a new directory (<filename>xyz</filename>) in
- <filename>alsa-driver/pci/Makefile</filename> as below
-
- <informalexample>
- <programlisting>
-<![CDATA[
- obj-$(CONFIG_SND) += xyz/
-]]>
- </programlisting>
- </informalexample>
- </para>
- </listitem>
-
- <listitem>
- <para>
- Under the directory <filename>xyz</filename>, create a Makefile
-
- <example>
- <title>Sample Makefile for a driver xyz</title>
- <programlisting>
-<![CDATA[
- ifndef SND_TOPDIR
- SND_TOPDIR=../..
- endif
-
- include $(SND_TOPDIR)/toplevel.config
- include $(SND_TOPDIR)/Makefile.conf
-
- snd-xyz-objs := xyz.o abc.o def.o
-
- obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-
- include $(SND_TOPDIR)/Rules.make
-]]>
- </programlisting>
- </example>
- </para>
- </listitem>
-
- <listitem>
- <para>
- Create the Kconfig entry
- </para>
-
- <para>
- This procedure is as same as in the last section.
- </para>
- </listitem>
-
- <listitem>
- <para>
- Run cvscompile script to re-generate the configure script and
- build the whole stuff again.
- </para>
- </listitem>
- </orderedlist>
- </para>
- </section>
-
- </chapter>
-
-<!-- ****************************************************** -->
-<!-- Useful Functions -->
-<!-- ****************************************************** -->
- <chapter id="useful-functions">
- <title>Useful Functions</title>
-
- <section id="useful-functions-snd-printk">
- <title><function>snd_printk()</function> and friends</title>
- <para>
- ALSA provides a verbose version of the
- <function>printk()</function> function. If a kernel config
- <constant>CONFIG_SND_VERBOSE_PRINTK</constant> is set, this
- function prints the given message together with the file name
- and the line of the caller. The <constant>KERN_XXX</constant>
- prefix is processed as
- well as the original <function>printk()</function> does, so it's
- recommended to add this prefix, e.g.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\n");
-]]>
- </programlisting>
- </informalexample>
- </para>
-
- <para>
- There are also <function>printk()</function>'s for
- debugging. <function>snd_printd()</function> can be used for
- general debugging purposes. If
- <constant>CONFIG_SND_DEBUG</constant> is set, this function is
- compiled, and works just like
- <function>snd_printk()</function>. If the ALSA is compiled
- without the debugging flag, it's ignored.
- </para>
-
- <para>
- <function>snd_printdd()</function> is compiled in only when
- <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
- that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
- even if you configure the alsa-driver with
- <option>--with-debug=full</option> option. You need to give
- explicitly <option>--with-debug=detect</option> option instead.
- </para>
- </section>
-
- <section id="useful-functions-snd-bug">
- <title><function>snd_BUG()</function></title>
- <para>
- It shows the <computeroutput>BUG?</computeroutput> message and
- stack trace as well as <function>snd_BUG_ON</function> at the point.
- It's useful to show that a fatal error happens there.
- </para>
- <para>
- When no debug flag is set, this macro is ignored.
- </para>
- </section>
-
- <section id="useful-functions-snd-bug-on">
- <title><function>snd_BUG_ON()</function></title>
- <para>
- <function>snd_BUG_ON()</function> macro is similar with
- <function>WARN_ON()</function> macro. For example,
-
- <informalexample>
- <programlisting>
-<![CDATA[
- snd_BUG_ON(!pointer);
-]]>
- </programlisting>
- </informalexample>
-
- or it can be used as the condition,
- <informalexample>
- <programlisting>
-<![CDATA[
- if (snd_BUG_ON(non_zero_is_bug))
- return -EINVAL;
-]]>
- </programlisting>
- </informalexample>
-
- </para>
-
- <para>
- The macro takes an conditional expression to evaluate.
- When <constant>CONFIG_SND_DEBUG</constant>, is set, if the
- expression is non-zero, it shows the warning message such as
- <computeroutput>BUG? (xxx)</computeroutput>
- normally followed by stack trace.
-
- In both cases it returns the evaluated value.
- </para>
-
- </section>
-
- </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Acknowledgments -->
-<!-- ****************************************************** -->
- <chapter id="acknowledgments">
- <title>Acknowledgments</title>
- <para>
- I would like to thank Phil Kerr for his help for improvement and
- corrections of this document.
- </para>
- <para>
- Kevin Conder reformatted the original plain-text to the
- DocBook format.
- </para>
- <para>
- Giuliano Pochini corrected typos and contributed the example codes
- in the hardware constraints section.
- </para>
- </chapter>
-</book>
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx
index 92deea30b183..707c65337ebf 100644
--- a/Documentation/Makefile.sphinx
+++ b/Documentation/Makefile.sphinx
@@ -10,6 +10,8 @@ _SPHINXDIRS = $(patsubst $(srctree)/Documentation/%/conf.py,%,$(wildcard $(src
SPHINX_CONF = conf.py
PAPER =
BUILDDIR = $(obj)/output
+PDFLATEX = xelatex
+LATEXOPTS = -interaction=batchmode
# User-friendly check for sphinx-build
HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
@@ -29,7 +31,7 @@ else ifneq ($(DOCBOOKS),)
else # HAVE_SPHINX
# User-friendly check for pdflatex
-HAVE_PDFLATEX := $(shell if which xelatex >/dev/null 2>&1; then echo 1; else echo 0; fi)
+HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi)
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
@@ -51,8 +53,8 @@ loop_cmd = $(echo-cmd) $(cmd_$(1))
# $5 reST source folder relative to $(srctree)/$(src),
# e.g. "media" for the linux-tv book-set at ./Documentation/media
-quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4);
- cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media all;\
+quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
+ cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2;\
BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
$(SPHINXBUILD) \
-b $2 \
@@ -67,16 +69,19 @@ htmldocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
latexdocs:
+ @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
+
ifeq ($(HAVE_PDFLATEX),0)
- $(warning The 'xelatex' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
+
+pdfdocs:
+ $(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
@echo " SKIP Sphinx $@ target."
+
else # HAVE_PDFLATEX
- @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
-endif # HAVE_PDFLATEX
pdfdocs: latexdocs
-ifneq ($(HAVE_PDFLATEX),0)
- $(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=xelatex LATEXOPTS="-interaction=nonstopmode" -C $(BUILDDIR)/$(var)/latex)
+ $(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex;)
+
endif # HAVE_PDFLATEX
epubdocs:
@@ -93,6 +98,7 @@ installmandocs:
cleandocs:
$(Q)rm -rf $(BUILDDIR)
+ $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) -C Documentation/media clean
endif # HAVE_SPHINX
diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index a4d3838130e4..39bcb74ea733 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -547,7 +547,7 @@ The <tt>rcu_access_pointer()</tt> on line&nbsp;6 is similar to
It could reuse a value formerly fetched from this same pointer.
It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
- mash-up of two distince pointer values.
+ mash-up of two distinct pointer values.
It might even use value-speculation optimizations, where it makes
a wrong guess, but by the time it gets around to checking the
value, an update has changed the pointer to match the wrong guess.
@@ -659,6 +659,29 @@ systems with more than one CPU:
In other words, a given instance of <tt>synchronize_rcu()</tt>
can avoid waiting on a given RCU read-side critical section only
if it can prove that <tt>synchronize_rcu()</tt> started first.
+
+ <p>
+ A related question is &ldquo;When <tt>rcu_read_lock()</tt>
+ doesn't generate any code, why does it matter how it relates
+ to a grace period?&rdquo;
+ The answer is that it is not the relationship of
+ <tt>rcu_read_lock()</tt> itself that is important, but rather
+ the relationship of the code within the enclosed RCU read-side
+ critical section to the code preceding and following the
+ grace period.
+ If we take this viewpoint, then a given RCU read-side critical
+ section begins before a given grace period when some access
+ preceding the grace period observes the effect of some access
+ within the critical section, in which case none of the accesses
+ within the critical section may observe the effects of any
+ access following the grace period.
+
+ <p>
+ As of late 2016, mathematical models of RCU take this
+ viewpoint, for example, see slides&nbsp;62 and&nbsp;63
+ of the
+ <a href="http://www2.rdrop.com/users/paulmck/scalability/paper/LinuxMM.2016.10.04c.LCE.pdf">2016 LinuxCon EU</a>
+ presentation.
</font></td></tr>
<tr><td>&nbsp;</td></tr>
</table>
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 204422719197..5cbd8b2395b8 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -237,7 +237,7 @@ rcu_dereference()
The reader uses rcu_dereference() to fetch an RCU-protected
pointer, which returns a value that may then be safely
- dereferenced. Note that rcu_deference() does not actually
+ dereferenced. Note that rcu_dereference() does not actually
dereference the pointer, instead, it protects the pointer for
later dereferencing. It also executes any needed memory-barrier
instructions for a given CPU architecture. Currently, only Alpha
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 36f1dedc944c..81455705e4a6 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -1,841 +1 @@
-.. _submittingpatches:
-
-How to Get Your Change Into the Linux Kernel or Care And Operation Of Your Linus Torvalds
-=========================================================================================
-
-For a person or company who wishes to submit a change to the Linux
-kernel, the process can sometimes be daunting if you're not familiar
-with "the system." This text is a collection of suggestions which
-can greatly increase the chances of your change being accepted.
-
-This document contains a large number of suggestions in a relatively terse
-format. For detailed information on how the kernel development process
-works, see :ref:`Documentation/development-process <development_process_main>`.
-Also, read :ref:`Documentation/SubmitChecklist <submitchecklist>`
-for a list of items to check before
-submitting code. If you are submitting a driver, also read
-:ref:`Documentation/SubmittingDrivers <submittingdrivers>`;
-for device tree binding patches, read
-Documentation/devicetree/bindings/submitting-patches.txt.
-
-Many of these steps describe the default behavior of the ``git`` version
-control system; if you use ``git`` to prepare your patches, you'll find much
-of the mechanical work done for you, though you'll still need to prepare
-and document a sensible set of patches. In general, use of ``git`` will make
-your life as a kernel developer easier.
-
-Creating and Sending your Change
-********************************
-
-
-0) Obtain a current source tree
--------------------------------
-
-If you do not have a repository with the current kernel source handy, use
-``git`` to obtain one. You'll want to start with the mainline repository,
-which can be grabbed with::
-
- git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-
-Note, however, that you may not want to develop against the mainline tree
-directly. Most subsystem maintainers run their own trees and want to see
-patches prepared against those trees. See the **T:** entry for the subsystem
-in the MAINTAINERS file to find that tree, or simply ask the maintainer if
-the tree is not listed there.
-
-It is still possible to download kernel releases via tarballs (as described
-in the next section), but that is the hard way to do kernel development.
-
-1) ``diff -up``
----------------
-
-If you must generate your patches by hand, use ``diff -up`` or ``diff -uprN``
-to create patches. Git generates patches in this form by default; if
-you're using ``git``, you can skip this section entirely.
-
-All changes to the Linux kernel occur in the form of patches, as
-generated by :manpage:`diff(1)`. When creating your patch, make sure to
-create it in "unified diff" format, as supplied by the ``-u`` argument
-to :manpage:`diff(1)`.
-Also, please use the ``-p`` argument which shows which C function each
-change is in - that makes the resultant ``diff`` a lot easier to read.
-Patches should be based in the root kernel source directory,
-not in any lower subdirectory.
-
-To create a patch for a single file, it is often sufficient to do::
-
- SRCTREE= linux
- MYFILE= drivers/net/mydriver.c
-
- cd $SRCTREE
- cp $MYFILE $MYFILE.orig
- vi $MYFILE # make your change
- cd ..
- diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
-
-To create a patch for multiple files, you should unpack a "vanilla",
-or unmodified kernel source tree, and generate a ``diff`` against your
-own source tree. For example::
-
- MYSRC= /devel/linux
-
- tar xvfz linux-3.19.tar.gz
- mv linux-3.19 linux-3.19-vanilla
- diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
- linux-3.19-vanilla $MYSRC > /tmp/patch
-
-``dontdiff`` is a list of files which are generated by the kernel during
-the build process, and should be ignored in any :manpage:`diff(1)`-generated
-patch.
-
-Make sure your patch does not include any extra files which do not
-belong in a patch submission. Make sure to review your patch -after-
-generating it with :manpage:`diff(1)`, to ensure accuracy.
-
-If your changes produce a lot of deltas, you need to split them into
-individual patches which modify things in logical stages; see
-:ref:`split_changes`. This will facilitate review by other kernel developers,
-very important if you want your patch accepted.
-
-If you're using ``git``, ``git rebase -i`` can help you with this process. If
-you're not using ``git``, ``quilt`` <http://savannah.nongnu.org/projects/quilt>
-is another popular alternative.
-
-.. _describe_changes:
-
-2) Describe your changes
-------------------------
-
-Describe your problem. Whether your patch is a one-line bug fix or
-5000 lines of a new feature, there must be an underlying problem that
-motivated you to do this work. Convince the reviewer that there is a
-problem worth fixing and that it makes sense for them to read past the
-first paragraph.
-
-Describe user-visible impact. Straight up crashes and lockups are
-pretty convincing, but not all bugs are that blatant. Even if the
-problem was spotted during code review, describe the impact you think
-it can have on users. Keep in mind that the majority of Linux
-installations run kernels from secondary stable trees or
-vendor/product-specific trees that cherry-pick only specific patches
-from upstream, so include anything that could help route your change
-downstream: provoking circumstances, excerpts from dmesg, crash
-descriptions, performance regressions, latency spikes, lockups, etc.
-
-Quantify optimizations and trade-offs. If you claim improvements in
-performance, memory consumption, stack footprint, or binary size,
-include numbers that back them up. But also describe non-obvious
-costs. Optimizations usually aren't free but trade-offs between CPU,
-memory, and readability; or, when it comes to heuristics, between
-different workloads. Describe the expected downsides of your
-optimization so that the reviewer can weigh costs against benefits.
-
-Once the problem is established, describe what you are actually doing
-about it in technical detail. It's important to describe the change
-in plain English for the reviewer to verify that the code is behaving
-as you intend it to.
-
-The maintainer will thank you if you write your patch description in a
-form which can be easily pulled into Linux's source code management
-system, ``git``, as a "commit log". See :ref:`explicit_in_reply_to`.
-
-Solve only one problem per patch. If your description starts to get
-long, that's a sign that you probably need to split up your patch.
-See :ref:`split_changes`.
-
-When you submit or resubmit a patch or patch series, include the
-complete patch description and justification for it. Don't just
-say that this is version N of the patch (series). Don't expect the
-subsystem maintainer to refer back to earlier patch versions or referenced
-URLs to find the patch description and put that into the patch.
-I.e., the patch (series) and its description should be self-contained.
-This benefits both the maintainers and reviewers. Some reviewers
-probably didn't even receive earlier versions of the patch.
-
-Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
-instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
-to do frotz", as if you are giving orders to the codebase to change
-its behaviour.
-
-If the patch fixes a logged bug entry, refer to that bug entry by
-number and URL. If the patch follows from a mailing list discussion,
-give a URL to the mailing list archive; use the https://lkml.kernel.org/
-redirector with a ``Message-Id``, to ensure that the links cannot become
-stale.
-
-However, try to make your explanation understandable without external
-resources. In addition to giving a URL to a mailing list archive or
-bug, summarize the relevant points of the discussion that led to the
-patch as submitted.
-
-If you want to refer to a specific commit, don't just refer to the
-SHA-1 ID of the commit. Please also include the oneline summary of
-the commit, to make it easier for reviewers to know what it is about.
-Example::
-
- Commit e21d2170f36602ae2708 ("video: remove unnecessary
- platform_set_drvdata()") removed the unnecessary
- platform_set_drvdata(), but left the variable "dev" unused,
- delete it.
-
-You should also be sure to use at least the first twelve characters of the
-SHA-1 ID. The kernel repository holds a *lot* of objects, making
-collisions with shorter IDs a real possibility. Bear in mind that, even if
-there is no collision with your six-character ID now, that condition may
-change five years from now.
-
-If your patch fixes a bug in a specific commit, e.g. you found an issue using
-``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
-the SHA-1 ID, and the one line summary. For example::
-
- Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
-
-The following ``git config`` settings can be used to add a pretty format for
-outputting the above style in the ``git log`` or ``git show`` commands::
-
- [core]
- abbrev = 12
- [pretty]
- fixes = Fixes: %h (\"%s\")
-
-.. _split_changes:
-
-3) Separate your changes
-------------------------
-
-Separate each **logical change** into a separate patch.
-
-For example, if your changes include both bug fixes and performance
-enhancements for a single driver, separate those changes into two
-or more patches. If your changes include an API update, and a new
-driver which uses that new API, separate those into two patches.
-
-On the other hand, if you make a single change to numerous files,
-group those changes into a single patch. Thus a single logical change
-is contained within a single patch.
-
-The point to remember is that each patch should make an easily understood
-change that can be verified by reviewers. Each patch should be justifiable
-on its own merits.
-
-If one patch depends on another patch in order for a change to be
-complete, that is OK. Simply note **"this patch depends on patch X"**
-in your patch description.
-
-When dividing your change into a series of patches, take special care to
-ensure that the kernel builds and runs properly after each patch in the
-series. Developers using ``git bisect`` to track down a problem can end up
-splitting your patch series at any point; they will not thank you if you
-introduce bugs in the middle.
-
-If you cannot condense your patch set into a smaller set of patches,
-then only post say 15 or so at a time and wait for review and integration.
-
-
-
-4) Style-check your changes
----------------------------
-
-Check your patch for basic style violations, details of which can be
-found in
-:ref:`Documentation/CodingStyle <codingstyle>`.
-Failure to do so simply wastes
-the reviewers time and will get your patch rejected, probably
-without even being read.
-
-One significant exception is when moving code from one file to
-another -- in this case you should not modify the moved code at all in
-the same patch which moves it. This clearly delineates the act of
-moving the code and your changes. This greatly aids review of the
-actual differences and allows tools to better track the history of
-the code itself.
-
-Check your patches with the patch style checker prior to submission
-(scripts/checkpatch.pl). Note, though, that the style checker should be
-viewed as a guide, not as a replacement for human judgment. If your code
-looks better with a violation then its probably best left alone.
-
-The checker reports at three levels:
- - ERROR: things that are very likely to be wrong
- - WARNING: things requiring careful review
- - CHECK: things requiring thought
-
-You should be able to justify all violations that remain in your
-patch.
-
-
-5) Select the recipients for your patch
----------------------------------------
-
-You should always copy the appropriate subsystem maintainer(s) on any patch
-to code that they maintain; look through the MAINTAINERS file and the
-source code revision history to see who those maintainers are. The
-script scripts/get_maintainer.pl can be very useful at this step. If you
-cannot find a maintainer for the subsystem you are working on, Andrew
-Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
-
-You should also normally choose at least one mailing list to receive a copy
-of your patch set. linux-kernel@vger.kernel.org functions as a list of
-last resort, but the volume on that list has caused a number of developers
-to tune it out. Look in the MAINTAINERS file for a subsystem-specific
-list; your patch will probably get more attention there. Please do not
-spam unrelated lists, though.
-
-Many kernel-related lists are hosted on vger.kernel.org; you can find a
-list of them at http://vger.kernel.org/vger-lists.html. There are
-kernel-related lists hosted elsewhere as well, though.
-
-Do not send more than 15 patches at once to the vger mailing lists!!!
-
-Linus Torvalds is the final arbiter of all changes accepted into the
-Linux kernel. His e-mail address is <torvalds@linux-foundation.org>.
-He gets a lot of e-mail, and, at this point, very few patches go through
-Linus directly, so typically you should do your best to -avoid-
-sending him e-mail.
-
-If you have a patch that fixes an exploitable security bug, send that patch
-to security@kernel.org. For severe bugs, a short embargo may be considered
-to allow distributors to get the patch out to users; in such cases,
-obviously, the patch should not be sent to any public lists.
-
-Patches that fix a severe bug in a released kernel should be directed
-toward the stable maintainers by putting a line like this::
-
- Cc: stable@vger.kernel.org
-
-into the sign-off area of your patch (note, NOT an email recipient). You
-should also read
-:ref:`Documentation/stable_kernel_rules.txt <stable_kernel_rules>`
-in addition to this file.
-
-Note, however, that some subsystem maintainers want to come to their own
-conclusions on which patches should go to the stable trees. The networking
-maintainer, in particular, would rather not see individual developers
-adding lines like the above to their patches.
-
-If changes affect userland-kernel interfaces, please send the MAN-PAGES
-maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at
-least a notification of the change, so that some information makes its way
-into the manual pages. User-space API changes should also be copied to
-linux-api@vger.kernel.org.
-
-For small patches you may want to CC the Trivial Patch Monkey
-trivial@kernel.org which collects "trivial" patches. Have a look
-into the MAINTAINERS file for its current manager.
-
-Trivial patches must qualify for one of the following rules:
-
-- Spelling fixes in documentation
-- Spelling fixes for errors which could break :manpage:`grep(1)`
-- Warning fixes (cluttering with useless warnings is bad)
-- Compilation fixes (only if they are actually correct)
-- Runtime fixes (only if they actually fix things)
-- Removing use of deprecated functions/macros
-- Contact detail and documentation fixes
-- Non-portable code replaced by portable code (even in arch-specific,
- since people copy, as long as it's trivial)
-- Any fix by the author/maintainer of the file (ie. patch monkey
- in re-transmission mode)
-
-
-
-6) No MIME, no links, no compression, no attachments. Just plain text
-----------------------------------------------------------------------
-
-Linus and other kernel developers need to be able to read and comment
-on the changes you are submitting. It is important for a kernel
-developer to be able to "quote" your changes, using standard e-mail
-tools, so that they may comment on specific portions of your code.
-
-For this reason, all patches should be submitted by e-mail "inline".
-
-.. warning::
-
- Be wary of your editor's word-wrap corrupting your patch,
- if you choose to cut-n-paste your patch.
-
-Do not attach the patch as a MIME attachment, compressed or not.
-Many popular e-mail applications will not always transmit a MIME
-attachment as plain text, making it impossible to comment on your
-code. A MIME attachment also takes Linus a bit more time to process,
-decreasing the likelihood of your MIME-attached change being accepted.
-
-Exception: If your mailer is mangling patches then someone may ask
-you to re-send them using MIME.
-
-See :ref:`Documentation/email-clients.txt <email_clients>`
-for hints about configuring your e-mail client so that it sends your patches
-untouched.
-
-7) E-mail size
---------------
-
-Large changes are not appropriate for mailing lists, and some
-maintainers. If your patch, uncompressed, exceeds 300 kB in size,
-it is preferred that you store your patch on an Internet-accessible
-server, and provide instead a URL (link) pointing to your patch. But note
-that if your patch exceeds 300 kB, it almost certainly needs to be broken up
-anyway.
-
-8) Respond to review comments
------------------------------
-
-Your patch will almost certainly get comments from reviewers on ways in
-which the patch can be improved. You must respond to those comments;
-ignoring reviewers is a good way to get ignored in return. Review comments
-or questions that do not lead to a code change should almost certainly
-bring about a comment or changelog entry so that the next reviewer better
-understands what is going on.
-
-Be sure to tell the reviewers what changes you are making and to thank them
-for their time. Code review is a tiring and time-consuming process, and
-reviewers sometimes get grumpy. Even in that case, though, respond
-politely and address the problems they have pointed out.
-
-
-9) Don't get discouraged - or impatient
----------------------------------------
-
-After you have submitted your change, be patient and wait. Reviewers are
-busy people and may not get to your patch right away.
-
-Once upon a time, patches used to disappear into the void without comment,
-but the development process works more smoothly than that now. You should
-receive comments within a week or so; if that does not happen, make sure
-that you have sent your patches to the right place. Wait for a minimum of
-one week before resubmitting or pinging reviewers - possibly longer during
-busy times like merge windows.
-
-
-10) Include PATCH in the subject
---------------------------------
-
-Due to high e-mail traffic to Linus, and to linux-kernel, it is common
-convention to prefix your subject line with [PATCH]. This lets Linus
-and other kernel developers more easily distinguish patches from other
-e-mail discussions.
-
-
-
-11) Sign your work
-------------------
-
-To improve tracking of who did what, especially with patches that can
-percolate to their final resting place in the kernel through several
-layers of maintainers, we've introduced a "sign-off" procedure on
-patches that are being emailed around.
-
-The sign-off is a simple line at the end of the explanation for the
-patch, which certifies that you wrote it or otherwise have the right to
-pass it on as an open-source patch. The rules are pretty simple: if you
-can certify the below:
-
-Developer's Certificate of Origin 1.1
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By making a contribution to this project, I certify that:
-
- (a) The contribution was created in whole or in part by me and I
- have the right to submit it under the open source license
- indicated in the file; or
-
- (b) The contribution is based upon previous work that, to the best
- of my knowledge, is covered under an appropriate open source
- license and I have the right under that license to submit that
- work with modifications, whether created in whole or in part
- by me, under the same open source license (unless I am
- permitted to submit under a different license), as indicated
- in the file; or
-
- (c) The contribution was provided directly to me by some other
- person who certified (a), (b) or (c) and I have not modified
- it.
-
- (d) I understand and agree that this project and the contribution
- are public and that a record of the contribution (including all
- personal information I submit with it, including my sign-off) is
- maintained indefinitely and may be redistributed consistent with
- this project or the open source license(s) involved.
-
-then you just add a line saying::
-
- Signed-off-by: Random J Developer <random@developer.example.org>
-
-using your real name (sorry, no pseudonyms or anonymous contributions.)
-
-Some people also put extra tags at the end. They'll just be ignored for
-now, but you can do this to mark internal company procedures or just
-point out some special detail about the sign-off.
-
-If you are a subsystem or branch maintainer, sometimes you need to slightly
-modify patches you receive in order to merge them, because the code is not
-exactly the same in your tree and the submitters'. If you stick strictly to
-rule (c), you should ask the submitter to rediff, but this is a totally
-counter-productive waste of time and energy. Rule (b) allows you to adjust
-the code, but then it is very impolite to change one submitter's code and
-make him endorse your bugs. To solve this problem, it is recommended that
-you add a line between the last Signed-off-by header and yours, indicating
-the nature of your changes. While there is nothing mandatory about this, it
-seems like prepending the description with your mail and/or name, all
-enclosed in square brackets, is noticeable enough to make it obvious that
-you are responsible for last-minute changes. Example::
-
- Signed-off-by: Random J Developer <random@developer.example.org>
- [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
- Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
-
-This practice is particularly helpful if you maintain a stable branch and
-want at the same time to credit the author, track changes, merge the fix,
-and protect the submitter from complaints. Note that under no circumstances
-can you change the author's identity (the From header), as it is the one
-which appears in the changelog.
-
-Special note to back-porters: It seems to be a common and useful practice
-to insert an indication of the origin of a patch at the top of the commit
-message (just after the subject line) to facilitate tracking. For instance,
-here's what we see in a 3.x-stable release::
-
- Date: Tue Oct 7 07:26:38 2014 -0400
-
- libata: Un-break ATA blacklist
-
- commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
-
-And here's what might appear in an older kernel once a patch is backported::
-
- Date: Tue May 13 22:12:27 2008 +0200
-
- wireless, airo: waitbusy() won't delay
-
- [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
-
-Whatever the format, this information provides a valuable help to people
-tracking your trees, and to people trying to troubleshoot bugs in your
-tree.
-
-
-12) When to use Acked-by: and Cc:
----------------------------------
-
-The Signed-off-by: tag indicates that the signer was involved in the
-development of the patch, or that he/she was in the patch's delivery path.
-
-If a person was not directly involved in the preparation or handling of a
-patch but wishes to signify and record their approval of it then they can
-ask to have an Acked-by: line added to the patch's changelog.
-
-Acked-by: is often used by the maintainer of the affected code when that
-maintainer neither contributed to nor forwarded the patch.
-
-Acked-by: is not as formal as Signed-off-by:. It is a record that the acker
-has at least reviewed the patch and has indicated acceptance. Hence patch
-mergers will sometimes manually convert an acker's "yep, looks good to me"
-into an Acked-by: (but note that it is usually better to ask for an
-explicit ack).
-
-Acked-by: does not necessarily indicate acknowledgement of the entire patch.
-For example, if a patch affects multiple subsystems and has an Acked-by: from
-one subsystem maintainer then this usually indicates acknowledgement of just
-the part which affects that maintainer's code. Judgement should be used here.
-When in doubt people should refer to the original discussion in the mailing
-list archives.
-
-If a person has had the opportunity to comment on a patch, but has not
-provided such comments, you may optionally add a ``Cc:`` tag to the patch.
-This is the only tag which might be added without an explicit action by the
-person it names - but it should indicate that this person was copied on the
-patch. This tag documents that potentially interested parties
-have been included in the discussion.
-
-
-13) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
---------------------------------------------------------------------------
-
-The Reported-by tag gives credit to people who find bugs and report them and it
-hopefully inspires them to help us again in the future. Please note that if
-the bug was reported in private, then ask for permission first before using the
-Reported-by tag.
-
-A Tested-by: tag indicates that the patch has been successfully tested (in
-some environment) by the person named. This tag informs maintainers that
-some testing has been performed, provides a means to locate testers for
-future patches, and ensures credit for the testers.
-
-Reviewed-by:, instead, indicates that the patch has been reviewed and found
-acceptable according to the Reviewer's Statement:
-
-Reviewer's statement of oversight
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By offering my Reviewed-by: tag, I state that:
-
- (a) I have carried out a technical review of this patch to
- evaluate its appropriateness and readiness for inclusion into
- the mainline kernel.
-
- (b) Any problems, concerns, or questions relating to the patch
- have been communicated back to the submitter. I am satisfied
- with the submitter's response to my comments.
-
- (c) While there may be things that could be improved with this
- submission, I believe that it is, at this time, (1) a
- worthwhile modification to the kernel, and (2) free of known
- issues which would argue against its inclusion.
-
- (d) While I have reviewed the patch and believe it to be sound, I
- do not (unless explicitly stated elsewhere) make any
- warranties or guarantees that it will achieve its stated
- purpose or function properly in any given situation.
-
-A Reviewed-by tag is a statement of opinion that the patch is an
-appropriate modification of the kernel without any remaining serious
-technical issues. Any interested reviewer (who has done the work) can
-offer a Reviewed-by tag for a patch. This tag serves to give credit to
-reviewers and to inform maintainers of the degree of review which has been
-done on the patch. Reviewed-by: tags, when supplied by reviewers known to
-understand the subject area and to perform thorough reviews, will normally
-increase the likelihood of your patch getting into the kernel.
-
-A Suggested-by: tag indicates that the patch idea is suggested by the person
-named and ensures credit to the person for the idea. Please note that this
-tag should not be added without the reporter's permission, especially if the
-idea was not posted in a public forum. That said, if we diligently credit our
-idea reporters, they will, hopefully, be inspired to help us again in the
-future.
-
-A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
-is used to make it easy to determine where a bug originated, which can help
-review a bug fix. This tag also assists the stable kernel team in determining
-which stable kernel versions should receive your fix. This is the preferred
-method for indicating a bug fixed by the patch. See :ref:`describe_changes`
-for more details.
-
-
-14) The canonical patch format
-------------------------------
-
-This section describes how the patch itself should be formatted. Note
-that, if you have your patches stored in a ``git`` repository, proper patch
-formatting can be had with ``git format-patch``. The tools cannot create
-the necessary text, though, so read the instructions below anyway.
-
-The canonical patch subject line is::
-
- Subject: [PATCH 001/123] subsystem: summary phrase
-
-The canonical patch message body contains the following:
-
- - A ``from`` line specifying the patch author (only needed if the person
- sending the patch is not the author).
-
- - An empty line.
-
- - The body of the explanation, line wrapped at 75 columns, which will
- be copied to the permanent changelog to describe this patch.
-
- - The ``Signed-off-by:`` lines, described above, which will
- also go in the changelog.
-
- - A marker line containing simply ``---``.
-
- - Any additional comments not suitable for the changelog.
-
- - The actual patch (``diff`` output).
-
-The Subject line format makes it very easy to sort the emails
-alphabetically by subject line - pretty much any email reader will
-support that - since because the sequence number is zero-padded,
-the numerical and alphabetic sort is the same.
-
-The ``subsystem`` in the email's Subject should identify which
-area or subsystem of the kernel is being patched.
-
-The ``summary phrase`` in the email's Subject should concisely
-describe the patch which that email contains. The ``summary
-phrase`` should not be a filename. Do not use the same ``summary
-phrase`` for every patch in a whole patch series (where a ``patch
-series`` is an ordered sequence of multiple, related patches).
-
-Bear in mind that the ``summary phrase`` of your email becomes a
-globally-unique identifier for that patch. It propagates all the way
-into the ``git`` changelog. The ``summary phrase`` may later be used in
-developer discussions which refer to the patch. People will want to
-google for the ``summary phrase`` to read discussion regarding that
-patch. It will also be the only thing that people may quickly see
-when, two or three months later, they are going through perhaps
-thousands of patches using tools such as ``gitk`` or ``git log
---oneline``.
-
-For these reasons, the ``summary`` must be no more than 70-75
-characters, and it must describe both what the patch changes, as well
-as why the patch might be necessary. It is challenging to be both
-succinct and descriptive, but that is what a well-written summary
-should do.
-
-The ``summary phrase`` may be prefixed by tags enclosed in square
-brackets: "Subject: [PATCH <tag>...] <summary phrase>". The tags are
-not considered part of the summary phrase, but describe how the patch
-should be treated. Common tags might include a version descriptor if
-the multiple versions of the patch have been sent out in response to
-comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
-comments. If there are four patches in a patch series the individual
-patches may be numbered like this: 1/4, 2/4, 3/4, 4/4. This assures
-that developers understand the order in which the patches should be
-applied and that they have reviewed or applied all of the patches in
-the patch series.
-
-A couple of example Subjects::
-
- Subject: [PATCH 2/5] ext2: improve scalability of bitmap searching
- Subject: [PATCH v2 01/27] x86: fix eflags tracking
-
-The ``from`` line must be the very first line in the message body,
-and has the form:
-
- From: Original Author <author@example.com>
-
-The ``from`` line specifies who will be credited as the author of the
-patch in the permanent changelog. If the ``from`` line is missing,
-then the ``From:`` line from the email header will be used to determine
-the patch author in the changelog.
-
-The explanation body will be committed to the permanent source
-changelog, so should make sense to a competent reader who has long
-since forgotten the immediate details of the discussion that might
-have led to this patch. Including symptoms of the failure which the
-patch addresses (kernel log messages, oops messages, etc.) is
-especially useful for people who might be searching the commit logs
-looking for the applicable patch. If a patch fixes a compile failure,
-it may not be necessary to include _all_ of the compile failures; just
-enough that it is likely that someone searching for the patch can find
-it. As in the ``summary phrase``, it is important to be both succinct as
-well as descriptive.
-
-The ``---`` marker line serves the essential purpose of marking for patch
-handling tools where the changelog message ends.
-
-One good use for the additional comments after the ``---`` marker is for
-a ``diffstat``, to show what files have changed, and the number of
-inserted and deleted lines per file. A ``diffstat`` is especially useful
-on bigger patches. Other comments relevant only to the moment or the
-maintainer, not suitable for the permanent changelog, should also go
-here. A good example of such comments might be ``patch changelogs``
-which describe what has changed between the v1 and v2 version of the
-patch.
-
-If you are going to include a ``diffstat`` after the ``---`` marker, please
-use ``diffstat`` options ``-p 1 -w 70`` so that filenames are listed from
-the top of the kernel source tree and don't use too much horizontal
-space (easily fit in 80 columns, maybe with some indentation). (``git``
-generates appropriate diffstats by default.)
-
-See more details on the proper patch format in the following
-references.
-
-.. _explicit_in_reply_to:
-
-15) Explicit In-Reply-To headers
---------------------------------
-
-It can be helpful to manually add In-Reply-To: headers to a patch
-(e.g., when using ``git send-email``) to associate the patch with
-previous relevant discussion, e.g. to link a bug fix to the email with
-the bug report. However, for a multi-patch series, it is generally
-best to avoid using In-Reply-To: to link to older versions of the
-series. This way multiple versions of the patch don't become an
-unmanageable forest of references in email clients. If a link is
-helpful, you can use the https://lkml.kernel.org/ redirector (e.g., in
-the cover email text) to link to an earlier version of the patch series.
-
-
-16) Sending ``git pull`` requests
----------------------------------
-
-If you have a series of patches, it may be most convenient to have the
-maintainer pull them directly into the subsystem repository with a
-``git pull`` operation. Note, however, that pulling patches from a developer
-requires a higher degree of trust than taking patches from a mailing list.
-As a result, many subsystem maintainers are reluctant to take pull
-requests, especially from new, unknown developers. If in doubt you can use
-the pull request as the cover letter for a normal posting of the patch
-series, giving the maintainer the option of using either.
-
-A pull request should have [GIT] or [PULL] in the subject line. The
-request itself should include the repository name and the branch of
-interest on a single line; it should look something like::
-
- Please pull from
-
- git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
-
- to get these changes:
-
-A pull request should also include an overall message saying what will be
-included in the request, a ``git shortlog`` listing of the patches
-themselves, and a ``diffstat`` showing the overall effect of the patch series.
-The easiest way to get all this information together is, of course, to let
-``git`` do it for you with the ``git request-pull`` command.
-
-Some maintainers (including Linus) want to see pull requests from signed
-commits; that increases their confidence that the request actually came
-from you. Linus, in particular, will not pull from public hosting sites
-like GitHub in the absence of a signed tag.
-
-The first step toward creating such tags is to make a GNUPG key and get it
-signed by one or more core kernel developers. This step can be hard for
-new developers, but there is no way around it. Attending conferences can
-be a good way to find developers who can sign your key.
-
-Once you have prepared a patch series in ``git`` that you wish to have somebody
-pull, create a signed tag with ``git tag -s``. This will create a new tag
-identifying the last commit in the series and containing a signature
-created with your private key. You will also have the opportunity to add a
-changelog-style message to the tag; this is an ideal place to describe the
-effects of the pull request as a whole.
-
-If the tree the maintainer will be pulling from is not the repository you
-are working from, don't forget to push the signed tag explicitly to the
-public tree.
-
-When generating your pull request, use the signed tag as the target. A
-command like this will do the trick::
-
- git request-pull master git://my.public.tree/linux.git my-signed-tag
-
-
-REFERENCES
-**********
-
-Andrew Morton, "The perfect patch" (tpp).
- <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
-
-Jeff Garzik, "Linux kernel patch submission format".
- <http://linux.yyz.us/patch-format.html>
-
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
- <http://www.kroah.com/log/linux/maintainer.html>
-
- <http://www.kroah.com/log/linux/maintainer-02.html>
-
- <http://www.kroah.com/log/linux/maintainer-03.html>
-
- <http://www.kroah.com/log/linux/maintainer-04.html>
-
- <http://www.kroah.com/log/linux/maintainer-05.html>
-
- <http://www.kroah.com/log/linux/maintainer-06.html>
-
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
- <https://lkml.org/lkml/2005/7/11/336>
-
-Kernel Documentation/CodingStyle:
- :ref:`Documentation/CodingStyle <codingstyle>`
-
-Linus Torvalds's mail on the canonical patch format:
- <http://lkml.org/lkml/2005/4/7/183>
-
-Andi Kleen, "On submitting kernel patches"
- Some strategies to get difficult or controversial changes in.
-
- http://halobates.de/on-submitting-patches.pdf
-
+This file has moved to process/submitting-patches.rst
diff --git a/Documentation/VGA-softcursor.txt b/Documentation/VGA-softcursor.txt
deleted file mode 100644
index 70acfbf399eb..000000000000
--- a/Documentation/VGA-softcursor.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Software cursor for VGA by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
-======================= and Martin Mares <mj@atrey.karlin.mff.cuni.cz>
-
- Linux now has some ability to manipulate cursor appearance. Normally, you
-can set the size of hardware cursor (and also work around some ugly bugs in
-those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/
-vgacon.c). You can now play a few new tricks: you can make your cursor look
-like a non-blinking red block, make it inverse background of the character it's
-over or to highlight that character and still choose whether the original
-hardware cursor should remain visible or not. There may be other things I have
-never thought of.
-
- The cursor appearance is controlled by a "<ESC>[?1;2;3c" escape sequence
-where 1, 2 and 3 are parameters described below. If you omit any of them,
-they will default to zeroes.
-
- Parameter 1 specifies cursor size (0=default, 1=invisible, 2=underline, ...,
-8=full block) + 16 if you want the software cursor to be applied + 32 if you
-want to always change the background color + 64 if you dislike having the
-background the same as the foreground. Highlights are ignored for the last two
-flags.
-
- The second parameter selects character attribute bits you want to change
-(by simply XORing them with the value of this parameter). On standard VGA,
-the high four bits specify background and the low four the foreground. In both
-groups, low three bits set color (as in normal color codes used by the console)
-and the most significant one turns on highlight (or sometimes blinking--it
-depends on the configuration of your VGA).
-
- The third parameter consists of character attribute bits you want to set.
-Bit setting takes place before bit toggling, so you can simply clear a bit by
-including it in both the set mask and the toggle mask.
-
-Examples:
-=========
-
-To get normal blinking underline, use: echo -e '\033[?2c'
-To get blinking block, use: echo -e '\033[?6c'
-To get red non-blinking block, use: echo -e '\033[?17;0;64c'
diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt
index 5aafe0b351a1..2aff0349facd 100644
--- a/Documentation/acpi/gpio-properties.txt
+++ b/Documentation/acpi/gpio-properties.txt
@@ -51,6 +51,68 @@ it to 1 marks the GPIO as active low.
In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.
+It is possible to leave holes in the array of GPIOs. This is useful in
+cases like with SPI host controllers where some chip selects may be
+implemented as GPIOs and some as native signals. For example a SPI host
+controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
+native:
+
+ Package () {
+ "cs-gpios",
+ Package () {
+ ^GPIO, 19, 0, 0, // chip select 0: GPIO
+ 0, // chip select 1: native signal
+ ^GPIO, 20, 0, 0, // chip select 2: GPIO
+ }
+ }
+
+Other supported properties
+--------------------------
+
+Following Device Tree compatible device properties are also supported by
+_DSD device properties for GPIO controllers:
+
+- gpio-hog
+- output-high
+- output-low
+- input
+- line-name
+
+Example:
+
+ Name (_DSD, Package () {
+ // _DSD Hierarchical Properties Extension UUID
+ ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+ Package () {
+ Package () {"hog-gpio8", "G8PU"}
+ }
+ })
+
+ Name (G8PU, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () {"gpio-hog", 1},
+ Package () {"gpios", Package () {8, 0}},
+ Package () {"output-high", 1},
+ Package () {"line-name", "gpio8-pullup"},
+ }
+ })
+
+- gpio-line-names
+
+Example:
+
+ Package () {
+ "gpio-line-names",
+ Package () {
+ "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD", "MUX7_IO",
+ "LVL_C_A1", "MUX0_IO", "SPI1_MISO"
+ }
+ }
+
+See Documentation/devicetree/bindings/gpio/gpio.txt for more information
+about these properties.
+
ACPI GPIO Mappings Provided by Drivers
--------------------------------------
diff --git a/Documentation/acpi/video_extension.txt b/Documentation/acpi/video_extension.txt
index 78b32ac02466..79bf6a4921be 100644
--- a/Documentation/acpi/video_extension.txt
+++ b/Documentation/acpi/video_extension.txt
@@ -101,6 +101,6 @@ received a notification, it will set the backlight level accordingly. This does
not affect the sending of event to user space, they are always sent to user
space regardless of whether or not the video module controls the backlight level
directly. This behaviour can be controlled through the brightness_switch_enabled
-module parameter as documented in kernel-parameters.txt. It is recommended to
+module parameter as documented in admin-guide/kernel-parameters.rst. It is recommended to
disable this behaviour once a GUI environment starts up and wants to have full
control of the backlight level.
diff --git a/Documentation/admin-guide/README.rst b/Documentation/admin-guide/README.rst
new file mode 100644
index 000000000000..1b6dfb2b3adb
--- /dev/null
+++ b/Documentation/admin-guide/README.rst
@@ -0,0 +1,411 @@
+Linux kernel release 4.x <http://kernel.org/>
+=============================================
+
+These are the release notes for Linux version 4. Read them carefully,
+as they tell you what this is all about, explain how to install the
+kernel, and what to do if something goes wrong.
+
+What is Linux?
+--------------
+
+ Linux is a clone of the operating system Unix, written from scratch by
+ Linus Torvalds with assistance from a loosely-knit team of hackers across
+ the Net. It aims towards POSIX and Single UNIX Specification compliance.
+
+ It has all the features you would expect in a modern fully-fledged Unix,
+ including true multitasking, virtual memory, shared libraries, demand
+ loading, shared copy-on-write executables, proper memory management,
+ and multistack networking including IPv4 and IPv6.
+
+ It is distributed under the GNU General Public License - see the
+ accompanying COPYING file for more details.
+
+On what hardware does it run?
+-----------------------------
+
+ Although originally developed first for 32-bit x86-based PCs (386 or higher),
+ today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
+ UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
+ IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
+ Xtensa, Tilera TILE, AVR32, ARC and Renesas M32R architectures.
+
+ Linux is easily portable to most general-purpose 32- or 64-bit architectures
+ as long as they have a paged memory management unit (PMMU) and a port of the
+ GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
+ also been ported to a number of architectures without a PMMU, although
+ functionality is then obviously somewhat limited.
+ Linux has also been ported to itself. You can now run the kernel as a
+ userspace application - this is called UserMode Linux (UML).
+
+Documentation
+-------------
+
+ - There is a lot of documentation available both in electronic form on
+ the Internet and in books, both Linux-specific and pertaining to
+ general UNIX questions. I'd recommend looking into the documentation
+ subdirectories on any Linux FTP site for the LDP (Linux Documentation
+ Project) books. This README is not meant to be documentation on the
+ system: there are much better sources available.
+
+ - There are various README files in the Documentation/ subdirectory:
+ these typically contain kernel-specific installation notes for some
+ drivers for example. See Documentation/00-INDEX for a list of what
+ is contained in each file. Please read the
+ :ref:`Documentation/process/changes.rst <changes>` file, as it
+ contains information about the problems, which may result by upgrading
+ your kernel.
+
+ - The Documentation/DocBook/ subdirectory contains several guides for
+ kernel developers and users. These guides can be rendered in a
+ number of formats: PostScript (.ps), PDF, HTML, & man-pages, among others.
+ After installation, ``make psdocs``, ``make pdfdocs``, ``make htmldocs``,
+ or ``make mandocs`` will render the documentation in the requested format.
+
+Installing the kernel source
+----------------------------
+
+ - If you install the full sources, put the kernel tarball in a
+ directory where you have permissions (e.g. your home directory) and
+ unpack it::
+
+ xz -cd linux-4.X.tar.xz | tar xvf -
+
+ Replace "X" with the version number of the latest kernel.
+
+ Do NOT use the /usr/src/linux area! This area has a (usually
+ incomplete) set of kernel headers that are used by the library header
+ files. They should match the library, and not get messed up by
+ whatever the kernel-du-jour happens to be.
+
+ - You can also upgrade between 4.x releases by patching. Patches are
+ distributed in the xz format. To install by patching, get all the
+ newer patch files, enter the top level directory of the kernel source
+ (linux-4.X) and execute::
+
+ xz -cd ../patch-4.x.xz | patch -p1
+
+ Replace "x" for all versions bigger than the version "X" of your current
+ source tree, **in_order**, and you should be ok. You may want to remove
+ the backup files (some-file-name~ or some-file-name.orig), and make sure
+ that there are no failed patches (some-file-name# or some-file-name.rej).
+ If there are, either you or I have made a mistake.
+
+ Unlike patches for the 4.x kernels, patches for the 4.x.y kernels
+ (also known as the -stable kernels) are not incremental but instead apply
+ directly to the base 4.x kernel. For example, if your base kernel is 4.0
+ and you want to apply the 4.0.3 patch, you must not first apply the 4.0.1
+ and 4.0.2 patches. Similarly, if you are running kernel version 4.0.2 and
+ want to jump to 4.0.3, you must first reverse the 4.0.2 patch (that is,
+ patch -R) **before** applying the 4.0.3 patch. You can read more on this in
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
+
+ Alternatively, the script patch-kernel can be used to automate this
+ process. It determines the current kernel version and applies any
+ patches found::
+
+ linux/scripts/patch-kernel linux
+
+ The first argument in the command above is the location of the
+ kernel source. Patches are applied from the current directory, but
+ an alternative directory can be specified as the second argument.
+
+ - Make sure you have no stale .o files and dependencies lying around::
+
+ cd linux
+ make mrproper
+
+ You should now have the sources correctly installed.
+
+Software requirements
+---------------------
+
+ Compiling and running the 4.x kernels requires up-to-date
+ versions of various software packages. Consult
+ :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
+ required and how to get updates for these packages. Beware that using
+ excessively old versions of these packages can cause indirect
+ errors that are very difficult to track down, so don't assume that
+ you can just update packages when obvious problems arise during
+ build or operation.
+
+Build directory for the kernel
+------------------------------
+
+ When compiling the kernel, all output files will per default be
+ stored together with the kernel source code.
+ Using the option ``make O=output/dir`` allows you to specify an alternate
+ place for the output files (including .config).
+ Example::
+
+ kernel source code: /usr/src/linux-4.X
+ build directory: /home/name/build/kernel
+
+ To configure and build the kernel, use::
+
+ cd /usr/src/linux-4.X
+ make O=/home/name/build/kernel menuconfig
+ make O=/home/name/build/kernel
+ sudo make O=/home/name/build/kernel modules_install install
+
+ Please note: If the ``O=output/dir`` option is used, then it must be
+ used for all invocations of make.
+
+Configuring the kernel
+----------------------
+
+ Do not skip this step even if you are only upgrading one minor
+ version. New configuration options are added in each release, and
+ odd problems will turn up if the configuration files are not set up
+ as expected. If you want to carry your existing configuration to a
+ new version with minimal work, use ``make oldconfig``, which will
+ only ask you for the answers to new questions.
+
+ - Alternative configuration commands are::
+
+ "make config" Plain text interface.
+
+ "make menuconfig" Text based color menus, radiolists & dialogs.
+
+ "make nconfig" Enhanced text based color menus.
+
+ "make xconfig" Qt based configuration tool.
+
+ "make gconfig" GTK+ based configuration tool.
+
+ "make oldconfig" Default all questions based on the contents of
+ your existing ./.config file and asking about
+ new config symbols.
+
+ "make silentoldconfig"
+ Like above, but avoids cluttering the screen
+ with questions already answered.
+ Additionally updates the dependencies.
+
+ "make olddefconfig"
+ Like above, but sets new symbols to their default
+ values without prompting.
+
+ "make defconfig" Create a ./.config file by using the default
+ symbol values from either arch/$ARCH/defconfig
+ or arch/$ARCH/configs/${PLATFORM}_defconfig,
+ depending on the architecture.
+
+ "make ${PLATFORM}_defconfig"
+ Create a ./.config file by using the default
+ symbol values from
+ arch/$ARCH/configs/${PLATFORM}_defconfig.
+ Use "make help" to get a list of all available
+ platforms of your architecture.
+
+ "make allyesconfig"
+ Create a ./.config file by setting symbol
+ values to 'y' as much as possible.
+
+ "make allmodconfig"
+ Create a ./.config file by setting symbol
+ values to 'm' as much as possible.
+
+ "make allnoconfig" Create a ./.config file by setting symbol
+ values to 'n' as much as possible.
+
+ "make randconfig" Create a ./.config file by setting symbol
+ values to random values.
+
+ "make localmodconfig" Create a config based on current config and
+ loaded modules (lsmod). Disables any module
+ option that is not needed for the loaded modules.
+
+ To create a localmodconfig for another machine,
+ store the lsmod of that machine into a file
+ and pass it in as a LSMOD parameter.
+
+ target$ lsmod > /tmp/mylsmod
+ target$ scp /tmp/mylsmod host:/tmp
+
+ host$ make LSMOD=/tmp/mylsmod localmodconfig
+
+ The above also works when cross compiling.
+
+ "make localyesconfig" Similar to localmodconfig, except it will convert
+ all module options to built in (=y) options.
+
+ You can find more information on using the Linux kernel config tools
+ in Documentation/kbuild/kconfig.txt.
+
+ - NOTES on ``make config``:
+
+ - Having unnecessary drivers will make the kernel bigger, and can
+ under some circumstances lead to problems: probing for a
+ nonexistent controller card may confuse your other controllers
+
+ - A kernel with math-emulation compiled in will still use the
+ coprocessor if one is present: the math emulation will just
+ never get used in that case. The kernel will be slightly larger,
+ but will work on different machines regardless of whether they
+ have a math coprocessor or not.
+
+ - The "kernel hacking" configuration details usually result in a
+ bigger or slower kernel (or both), and can even make the kernel
+ less stable by configuring some routines to actively try to
+ break bad code to find kernel problems (kmalloc()). Thus you
+ should probably answer 'n' to the questions for "development",
+ "experimental", or "debugging" features.
+
+Compiling the kernel
+--------------------
+
+ - Make sure you have at least gcc 3.2 available.
+ For more information, refer to :ref:`Documentation/process/changes.rst <changes>`.
+
+ Please note that you can still run a.out user programs with this kernel.
+
+ - Do a ``make`` to create a compressed kernel image. It is also
+ possible to do ``make install`` if you have lilo installed to suit the
+ kernel makefiles, but you may want to check your particular lilo setup first.
+
+ To do the actual install, you have to be root, but none of the normal
+ build should require that. Don't take the name of root in vain.
+
+ - If you configured any of the parts of the kernel as ``modules``, you
+ will also have to do ``make modules_install``.
+
+ - Verbose kernel compile/build output:
+
+ Normally, the kernel build system runs in a fairly quiet mode (but not
+ totally silent). However, sometimes you or other kernel developers need
+ to see compile, link, or other commands exactly as they are executed.
+ For this, use "verbose" build mode. This is done by passing
+ ``V=1`` to the ``make`` command, e.g.::
+
+ make V=1 all
+
+ To have the build system also tell the reason for the rebuild of each
+ target, use ``V=2``. The default is ``V=0``.
+
+ - Keep a backup kernel handy in case something goes wrong. This is
+ especially true for the development releases, since each new release
+ contains new code which has not been debugged. Make sure you keep a
+ backup of the modules corresponding to that kernel, as well. If you
+ are installing a new kernel with the same version number as your
+ working kernel, make a backup of your modules directory before you
+ do a ``make modules_install``.
+
+ Alternatively, before compiling, use the kernel config option
+ "LOCALVERSION" to append a unique suffix to the regular kernel version.
+ LOCALVERSION can be set in the "General Setup" menu.
+
+ - In order to boot your new kernel, you'll need to copy the kernel
+ image (e.g. .../linux/arch/x86/boot/bzImage after compilation)
+ to the place where your regular bootable kernel is found.
+
+ - Booting a kernel directly from a floppy without the assistance of a
+ bootloader such as LILO, is no longer supported.
+
+ If you boot Linux from the hard drive, chances are you use LILO, which
+ uses the kernel image as specified in the file /etc/lilo.conf. The
+ kernel image file is usually /vmlinuz, /boot/vmlinuz, /bzImage or
+ /boot/bzImage. To use the new kernel, save a copy of the old image
+ and copy the new image over the old one. Then, you MUST RERUN LILO
+ to update the loading map! If you don't, you won't be able to boot
+ the new kernel image.
+
+ Reinstalling LILO is usually a matter of running /sbin/lilo.
+ You may wish to edit /etc/lilo.conf to specify an entry for your
+ old kernel image (say, /vmlinux.old) in case the new one does not
+ work. See the LILO docs for more information.
+
+ After reinstalling LILO, you should be all set. Shutdown the system,
+ reboot, and enjoy!
+
+ If you ever need to change the default root device, video mode,
+ ramdisk size, etc. in the kernel image, use the ``rdev`` program (or
+ alternatively the LILO boot options when appropriate). No need to
+ recompile the kernel to change these parameters.
+
+ - Reboot with the new kernel and enjoy.
+
+If something goes wrong
+-----------------------
+
+ - If you have problems that seem to be due to kernel bugs, please check
+ the file MAINTAINERS to see if there is a particular person associated
+ with the part of the kernel that you are having trouble with. If there
+ isn't anyone listed there, then the second best thing is to mail
+ them to me (torvalds@linux-foundation.org), and possibly to any other
+ relevant mailing-list or to the newsgroup.
+
+ - In all bug-reports, *please* tell what kernel you are talking about,
+ how to duplicate the problem, and what your setup is (use your common
+ sense). If the problem is new, tell me so, and if the problem is
+ old, please try to tell me when you first noticed it.
+
+ - If the bug results in a message like::
+
+ unable to handle kernel paging request at address C0000010
+ Oops: 0002
+ EIP: 0010:XXXXXXXX
+ eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
+ esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
+ ds: xxxx es: xxxx fs: xxxx gs: xxxx
+ Pid: xx, process nr: xx
+ xx xx xx xx xx xx xx xx xx xx
+
+ or similar kernel debugging information on your screen or in your
+ system log, please duplicate it *exactly*. The dump may look
+ incomprehensible to you, but it does contain information that may
+ help debugging the problem. The text above the dump is also
+ important: it tells something about why the kernel dumped code (in
+ the above example, it's due to a bad kernel pointer). More information
+ on making sense of the dump is in Documentation/admin-guide/oops-tracing.rst
+
+ - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
+ as is, otherwise you will have to use the ``ksymoops`` program to make
+ sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
+ This utility can be downloaded from
+ ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
+ Alternatively, you can do the dump lookup by hand:
+
+ - In debugging dumps like the above, it helps enormously if you can
+ look up what the EIP value means. The hex value as such doesn't help
+ me or anybody else very much: it will depend on your particular
+ kernel setup. What you should do is take the hex value from the EIP
+ line (ignore the ``0010:``), and look it up in the kernel namelist to
+ see which kernel function contains the offending address.
+
+ To find out the kernel function name, you'll need to find the system
+ binary associated with the kernel that exhibited the symptom. This is
+ the file 'linux/vmlinux'. To extract the namelist and match it against
+ the EIP from the kernel crash, do::
+
+ nm vmlinux | sort | less
+
+ This will give you a list of kernel addresses sorted in ascending
+ order, from which it is simple to find the function that contains the
+ offending address. Note that the address given by the kernel
+ debugging messages will not necessarily match exactly with the
+ function addresses (in fact, that is very unlikely), so you can't
+ just 'grep' the list: the list will, however, give you the starting
+ point of each kernel function, so by looking for the function that
+ has a starting address lower than the one you are searching for but
+ is followed by a function with a higher address you will find the one
+ you want. In fact, it may be a good idea to include a bit of
+ "context" in your problem report, giving a few lines around the
+ interesting one.
+
+ If you for some reason cannot do the above (you have a pre-compiled
+ kernel image or similar), telling me as much about your setup as
+ possible will help. Please read the :ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+ document for details.
+
+ - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you
+ cannot change values or set break points.) To do this, first compile the
+ kernel with -g; edit arch/x86/Makefile appropriately, then do a ``make
+ clean``. You'll also need to enable CONFIG_PROC_FS (via ``make config``).
+
+ After you've rebooted with the new kernel, do ``gdb vmlinux /proc/kcore``.
+ You can now use all the usual gdb commands. The command to look up the
+ point where your system crashed is ``l *0xXXXXXXXX``. (Replace the XXXes
+ with the EIP value.)
+
+ gdb'ing a non-running kernel currently fails because ``gdb`` (wrongly)
+ disregards the starting offset for which the kernel is compiled.
diff --git a/Documentation/admin-guide/binfmt-misc.rst b/Documentation/admin-guide/binfmt-misc.rst
new file mode 100644
index 000000000000..97b0d7927078
--- /dev/null
+++ b/Documentation/admin-guide/binfmt-misc.rst
@@ -0,0 +1,151 @@
+Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
+=====================================================================
+
+This Kernel feature allows you to invoke almost (for restrictions see below)
+every program by simply typing its name in the shell.
+This includes for example compiled Java(TM), Python or Emacs programs.
+
+To achieve this you must tell binfmt_misc which interpreter has to be invoked
+with which binary. Binfmt_misc recognises the binary-type by matching some bytes
+at the beginning of the file with a magic byte sequence (masking out specified
+bits) you have supplied. Binfmt_misc can also recognise a filename extension
+aka ``.com`` or ``.exe``.
+
+First you must mount binfmt_misc::
+
+ mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
+
+To actually register a new binary type, you have to set up a string looking like
+``:name:type:offset:magic:mask:interpreter:flags`` (where you can choose the
+``:`` upon your needs) and echo it to ``/proc/sys/fs/binfmt_misc/register``.
+
+Here is what the fields mean:
+
+- ``name``
+ is an identifier string. A new /proc file will be created with this
+ ``name below /proc/sys/fs/binfmt_misc``; cannot contain slashes ``/`` for
+ obvious reasons.
+- ``type``
+ is the type of recognition. Give ``M`` for magic and ``E`` for extension.
+- ``offset``
+ is the offset of the magic/mask in the file, counted in bytes. This
+ defaults to 0 if you omit it (i.e. you write ``:name:type::magic...``).
+ Ignored when using filename extension matching.
+- ``magic``
+ is the byte sequence binfmt_misc is matching for. The magic string
+ may contain hex-encoded characters like ``\x0a`` or ``\xA4``. Note that you
+ must escape any NUL bytes; parsing halts at the first one. In a shell
+ environment you might have to write ``\\x0a`` to prevent the shell from
+ eating your ``\``.
+ If you chose filename extension matching, this is the extension to be
+ recognised (without the ``.``, the ``\x0a`` specials are not allowed).
+ Extension matching is case sensitive, and slashes ``/`` are not allowed!
+- ``mask``
+ is an (optional, defaults to all 0xff) mask. You can mask out some
+ bits from matching by supplying a string like magic and as long as magic.
+ The mask is anded with the byte sequence of the file. Note that you must
+ escape any NUL bytes; parsing halts at the first one. Ignored when using
+ filename extension matching.
+- ``interpreter``
+ is the program that should be invoked with the binary as first
+ argument (specify the full path)
+- ``flags``
+ is an optional field that controls several aspects of the invocation
+ of the interpreter. It is a string of capital letters, each controls a
+ certain aspect. The following flags are supported:
+
+ ``P`` - preserve-argv[0]
+ Legacy behavior of binfmt_misc is to overwrite
+ the original argv[0] with the full path to the binary. When this
+ flag is included, binfmt_misc will add an argument to the argument
+ vector for this purpose, thus preserving the original ``argv[0]``.
+ e.g. If your interp is set to ``/bin/foo`` and you run ``blah``
+ (which is in ``/usr/local/bin``), then the kernel will execute
+ ``/bin/foo`` with ``argv[]`` set to ``["/bin/foo", "/usr/local/bin/blah", "blah"]``. The interp has to be aware of this so it can
+ execute ``/usr/local/bin/blah``
+ with ``argv[]`` set to ``["blah"]``.
+ ``O`` - open-binary
+ Legacy behavior of binfmt_misc is to pass the full path
+ of the binary to the interpreter as an argument. When this flag is
+ included, binfmt_misc will open the file for reading and pass its
+ descriptor as an argument, instead of the full path, thus allowing
+ the interpreter to execute non-readable binaries. This feature
+ should be used with care - the interpreter has to be trusted not to
+ emit the contents of the non-readable binary.
+ ``C`` - credentials
+ Currently, the behavior of binfmt_misc is to calculate
+ the credentials and security token of the new process according to
+ the interpreter. When this flag is included, these attributes are
+ calculated according to the binary. It also implies the ``O`` flag.
+ This feature should be used with care as the interpreter
+ will run with root permissions when a setuid binary owned by root
+ is run with binfmt_misc.
+ ``F`` - fix binary
+ The usual behaviour of binfmt_misc is to spawn the
+ binary lazily when the misc format file is invoked. However,
+ this doesn``t work very well in the face of mount namespaces and
+ changeroots, so the ``F`` mode opens the binary as soon as the
+ emulation is installed and uses the opened image to spawn the
+ emulator, meaning it is always available once installed,
+ regardless of how the environment changes.
+
+
+There are some restrictions:
+
+ - the whole register string may not exceed 1920 characters
+ - the magic must reside in the first 128 bytes of the file, i.e.
+ offset+size(magic) has to be less than 128
+ - the interpreter string may not exceed 127 characters
+
+To use binfmt_misc you have to mount it first. You can mount it with
+``mount -t binfmt_misc none /proc/sys/fs/binfmt_misc`` command, or you can add
+a line ``none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0`` to your
+``/etc/fstab`` so it auto mounts on boot.
+
+You may want to add the binary formats in one of your ``/etc/rc`` scripts during
+boot-up. Read the manual of your init program to figure out how to do this
+right.
+
+Think about the order of adding entries! Later added entries are matched first!
+
+
+A few examples (assumed you are in ``/proc/sys/fs/binfmt_misc``):
+
+- enable support for em86 (like binfmt_em86, for Alpha AXP only)::
+
+ echo ':i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
+ echo ':i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
+
+- enable support for packed DOS applications (pre-configured dosemu hdimages)::
+
+ echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
+
+- enable support for Windows executables using wine::
+
+ echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
+
+For java support see Documentation/admin-guide/java.rst
+
+
+You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
+or 1 (to enable) to ``/proc/sys/fs/binfmt_misc/status`` or
+``/proc/.../the_name``.
+Catting the file tells you the current status of ``binfmt_misc/the_entry``.
+
+You can remove one entry or all entries by echoing -1 to ``/proc/.../the_name``
+or ``/proc/sys/fs/binfmt_misc/status``.
+
+
+Hints
+-----
+
+If you want to pass special arguments to your interpreter, you can
+write a wrapper script for it. See Documentation/admin-guide/java.rst for an
+example.
+
+Your interpreter should NOT look in the PATH for the filename; the kernel
+passes it the full filename (or the file descriptor) to use. Using ``$PATH`` can
+cause unexpected behaviour and can be a security hazard.
+
+
+Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
diff --git a/Documentation/admin-guide/braille-console.rst b/Documentation/admin-guide/braille-console.rst
new file mode 100644
index 000000000000..18e79337dcfd
--- /dev/null
+++ b/Documentation/admin-guide/braille-console.rst
@@ -0,0 +1,38 @@
+Linux Braille Console
+=====================
+
+To get early boot messages on a braille device (before userspace screen
+readers can start), you first need to compile the support for the usual serial
+console (see :ref:`Documentation/admin-guide/serial-console.rst <serial_console>`), and
+for braille device
+(in :menuselection:`Device Drivers --> Accessibility support --> Console on braille device`).
+
+Then you need to specify a ``console=brl``, option on the kernel command line, the
+format is::
+
+ console=brl,serial_options...
+
+where ``serial_options...`` are the same as described in
+:ref:`Documentation/admin-guide/serial-console.rst <serial_console>`.
+
+So for instance you can use ``console=brl,ttyS0`` if the braille device is connected to the first serial port, and ``console=brl,ttyS0,115200`` to
+override the baud rate to 115200, etc.
+
+By default, the braille device will just show the last kernel message (console
+mode). To review previous messages, press the Insert key to switch to the VT
+review mode. In review mode, the arrow keys permit to browse in the VT content,
+:kbd:`PAGE-UP`/:kbd:`PAGE-DOWN` keys go at the top/bottom of the screen, and
+the :kbd:`HOME` key goes back
+to the cursor, hence providing very basic screen reviewing facility.
+
+Sound feedback can be obtained by adding the ``braille_console.sound=1`` kernel
+parameter.
+
+For simplicity, only one braille console can be enabled, other uses of
+``console=brl,...`` will be discarded. Also note that it does not interfere with
+the console selection mechanism described in
+:ref:`Documentation/admin-guide/serial-console.rst <serial_console>`.
+
+For now, only the VisioBraille device is supported.
+
+Samuel Thibault <samuel.thibault@ens-lyon.org>
diff --git a/Documentation/admin-guide/bug-bisect.rst b/Documentation/admin-guide/bug-bisect.rst
new file mode 100644
index 000000000000..59567da344e8
--- /dev/null
+++ b/Documentation/admin-guide/bug-bisect.rst
@@ -0,0 +1,76 @@
+Bisecting a bug
++++++++++++++++
+
+Last updated: 28 October 2016
+
+Introduction
+============
+
+Always try the latest kernel from kernel.org and build from source. If you are
+not confident in doing that please report the bug to your distribution vendor
+instead of to a kernel developer.
+
+Finding bugs is not always easy. Have a go though. If you can't find it don't
+give up. Report as much as you have found to the relevant maintainer. See
+MAINTAINERS for who that is for the subsystem you have worked on.
+
+Before you submit a bug report read
+:ref:`Documentation/admin-guide/reporting-bugs.rst <reportingbugs>`.
+
+Devices not appearing
+=====================
+
+Often this is caused by udev/systemd. Check that first before blaming it
+on the kernel.
+
+Finding patch that caused a bug
+===============================
+
+Using the provided tools with ``git`` makes finding bugs easy provided the bug
+is reproducible.
+
+Steps to do it:
+
+- build the Kernel from its git source
+- start bisect with [#f1]_::
+
+ $ git bisect start
+
+- mark the broken changeset with::
+
+ $ git bisect bad [commit]
+
+- mark a changeset where the code is known to work with::
+
+ $ git bisect good [commit]
+
+- rebuild the Kernel and test
+- interact with git bisect by using either::
+
+ $ git bisect good
+
+ or::
+
+ $ git bisect bad
+
+ depending if the bug happened on the changeset you're testing
+- After some interactions, git bisect will give you the changeset that
+ likely caused the bug.
+
+- For example, if you know that the current version is bad, and version
+ 4.8 is good, you could do::
+
+ $ git bisect start
+ $ git bisect bad # Current version is bad
+ $ git bisect good v4.8
+
+
+.. [#f1] You can, optionally, provide both good and bad arguments at git
+ start with ``git bisect start [BAD] [GOOD]``
+
+For further references, please read:
+
+- The man page for ``git-bisect``
+- `Fighting regressions with git bisect <https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
+- `Fully automated bisecting with "git bisect run" <https://lwn.net/Articles/317154>`_
+- `Using Git bisect to figure out when brokenness was introduced <http://webchick.net/node/99>`_
diff --git a/Documentation/admin-guide/bug-hunting.rst b/Documentation/admin-guide/bug-hunting.rst
new file mode 100644
index 000000000000..08c4b1308189
--- /dev/null
+++ b/Documentation/admin-guide/bug-hunting.rst
@@ -0,0 +1,369 @@
+Bug hunting
+===========
+
+Kernel bug reports often come with a stack dump like the one below::
+
+ ------------[ cut here ]------------
+ WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
+ Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
+ CPU: 1 PID: 28102 Comm: rmmod Tainted: P WC O 4.8.4-build.1 #1
+ Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
+ 00000000 c12ba080 00000000 00000000 c103ed6a c1616014 00000001 00006dc6
+ c1615862 00000454 c109e8a7 c109e8a7 00000009 ffffffff 00000000 f13f6a10
+ f5f5a600 c103ee33 00000009 00000000 00000000 c109e8a7 f80ca4d0 c109f617
+ Call Trace:
+ [<c12ba080>] ? dump_stack+0x44/0x64
+ [<c103ed6a>] ? __warn+0xfa/0x120
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<c103ee33>] ? warn_slowpath_null+0x23/0x30
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<f80ca4d0>] ? gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
+ [<c109f617>] ? symbol_put_addr+0x27/0x50
+ [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+ [<f80bb3bf>] ? dvb_usb_exit+0x2f/0xd0 [dvb_usb]
+ [<c13d03bc>] ? usb_disable_endpoint+0x7c/0xb0
+ [<f80bb48a>] ? dvb_usb_device_exit+0x2a/0x50 [dvb_usb]
+ [<c13d2882>] ? usb_unbind_interface+0x62/0x250
+ [<c136b514>] ? __pm_runtime_idle+0x44/0x70
+ [<c13620d8>] ? __device_release_driver+0x78/0x120
+ [<c1362907>] ? driver_detach+0x87/0x90
+ [<c1361c48>] ? bus_remove_driver+0x38/0x90
+ [<c13d1c18>] ? usb_deregister+0x58/0xb0
+ [<c109fbb0>] ? SyS_delete_module+0x130/0x1f0
+ [<c1055654>] ? task_work_run+0x64/0x80
+ [<c1000fa5>] ? exit_to_usermode_loop+0x85/0x90
+ [<c10013f0>] ? do_fast_syscall_32+0x80/0x130
+ [<c1549f43>] ? sysenter_past_esp+0x40/0x6a
+ ---[ end trace 6ebc60ef3981792f ]---
+
+Such stack traces provide enough information to identify the line inside the
+Kernel's source code where the bug happened. Depending on the severity of
+the issue, it may also contain the word **Oops**, as on this one::
+
+ BUG: unable to handle kernel NULL pointer dereference at (null)
+ IP: [<c06969d4>] iret_exc+0x7d0/0xa59
+ *pdpt = 000000002258a001 *pde = 0000000000000000
+ Oops: 0002 [#1] PREEMPT SMP
+ ...
+
+Despite being an **Oops** or some other sort of stack trace, the offended
+line is usually required to identify and handle the bug. Along this chapter,
+we'll refer to "Oops" for all kinds of stack traces that need to be analized.
+
+.. note::
+
+ ``ksymoops`` is useless on 2.6 or upper. Please use the Oops in its original
+ format (from ``dmesg``, etc). Ignore any references in this or other docs to
+ "decoding the Oops" or "running it through ksymoops".
+ If you post an Oops from 2.6+ that has been run through ``ksymoops``,
+ people will just tell you to repost it.
+
+Where is the Oops message is located?
+-------------------------------------
+
+Normally the Oops text is read from the kernel buffers by klogd and
+handed to ``syslogd`` which writes it to a syslog file, typically
+``/var/log/messages`` (depends on ``/etc/syslog.conf``). On systems with
+systemd, it may also be stored by the ``journald`` daemon, and accessed
+by running ``journalctl`` command.
+
+Sometimes ``klogd`` dies, in which case you can run ``dmesg > file`` to
+read the data from the kernel buffers and save it. Or you can
+``cat /proc/kmsg > file``, however you have to break in to stop the transfer,
+``kmsg`` is a "never ending file".
+
+If the machine has crashed so badly that you cannot enter commands or
+the disk is not available then you have three options:
+
+(1) Hand copy the text from the screen and type it in after the machine
+ has restarted. Messy but it is the only option if you have not
+ planned for a crash. Alternatively, you can take a picture of
+ the screen with a digital camera - not nice, but better than
+ nothing. If the messages scroll off the top of the console, you
+ may find that booting with a higher resolution (eg, ``vga=791``)
+ will allow you to read more of the text. (Caveat: This needs ``vesafb``,
+ so won't help for 'early' oopses)
+
+(2) Boot with a serial console (see
+ :ref:`Documentation/admin-guide/serial-console.rst <serial_console>`),
+ run a null modem to a second machine and capture the output there
+ using your favourite communication program. Minicom works well.
+
+(3) Use Kdump (see Documentation/kdump/kdump.txt),
+ extract the kernel ring buffer from old memory with using dmesg
+ gdbmacro in Documentation/kdump/gdbmacros.txt.
+
+Finding the bug's location
+--------------------------
+
+Reporting a bug works best if you point the location of the bug at the
+Kernel source file. There are two methods for doing that. Usually, using
+``gdb`` is easier, but the Kernel should be pre-compiled with debug info.
+
+gdb
+^^^
+
+The GNU debug (``gdb``) is the best way to figure out the exact file and line
+number of the OOPS from the ``vmlinux`` file.
+
+The usage of gdb works best on a kernel compiled with ``CONFIG_DEBUG_INFO``.
+This can be set by running::
+
+ $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+
+On a kernel compiled with ``CONFIG_DEBUG_INFO``, you can simply copy the
+EIP value from the OOPS::
+
+ EIP: 0060:[<c021e50e>] Not tainted VLI
+
+And use GDB to translate that to human-readable form::
+
+ $ gdb vmlinux
+ (gdb) l *0xc021e50e
+
+If you don't have ``CONFIG_DEBUG_INFO`` enabled, you use the function
+offset from the OOPS::
+
+ EIP is at vt_ioctl+0xda8/0x1482
+
+And recompile the kernel with ``CONFIG_DEBUG_INFO`` enabled::
+
+ $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+ $ make vmlinux
+ $ gdb vmlinux
+ (gdb) l *vt_ioctl+0xda8
+ 0x1888 is in vt_ioctl (drivers/tty/vt/vt_ioctl.c:293).
+ 288 {
+ 289 struct vc_data *vc = NULL;
+ 290 int ret = 0;
+ 291
+ 292 console_lock();
+ 293 if (VT_BUSY(vc_num))
+ 294 ret = -EBUSY;
+ 295 else if (vc_num)
+ 296 vc = vc_deallocate(vc_num);
+ 297 console_unlock();
+
+or, if you want to be more verbose::
+
+ (gdb) p vt_ioctl
+ $1 = {int (struct tty_struct *, unsigned int, unsigned long)} 0xae0 <vt_ioctl>
+ (gdb) l *0xae0+0xda8
+
+You could, instead, use the object file::
+
+ $ make drivers/tty/
+ $ gdb drivers/tty/vt/vt_ioctl.o
+ (gdb) l *vt_ioctl+0xda8
+
+If you have a call trace, such as::
+
+ Call Trace:
+ [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
+ [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
+ [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
+ ...
+
+this shows the problem likely in the :jbd: module. You can load that module
+in gdb and list the relevant code::
+
+ $ gdb fs/jbd/jbd.ko
+ (gdb) l *log_wait_commit+0xa3
+
+.. note::
+
+ You can also do the same for any function call at the stack trace,
+ like this one::
+
+ [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+
+ The position where the above call happened can be seen with::
+
+ $ gdb drivers/media/usb/dvb-usb/dvb-usb.o
+ (gdb) l *dvb_usb_adapter_frontend_exit+0x3a
+
+objdump
+^^^^^^^
+
+To debug a kernel, use objdump and look for the hex offset from the crash
+output to find the valid line of code/assembler. Without debug symbols, you
+will see the assembler code for the routine shown, but if your kernel has
+debug symbols the C code will also be available. (Debug symbols can be enabled
+in the kernel hacking menu of the menu configuration.) For example::
+
+ $ objdump -r -S -l --disassemble net/dccp/ipv4.o
+
+.. note::
+
+ You need to be at the top level of the kernel tree for this to pick up
+ your C files.
+
+If you don't have access to the code you can also debug on some crash dumps
+e.g. crash dump output as shown by Dave Miller::
+
+ EIP is at +0x14/0x4c0
+ ...
+ Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
+ 00 00 55 57 56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
+ <8b> 83 3c 01 00 00 89 44 24 14 8b 45 28 85 c0 89 44 24 18 0f 85
+
+ Put the bytes into a "foo.s" file like this:
+
+ .text
+ .globl foo
+ foo:
+ .byte .... /* bytes from Code: part of OOPS dump */
+
+ Compile it with "gcc -c -o foo.o foo.s" then look at the output of
+ "objdump --disassemble foo.o".
+
+ Output:
+
+ ip_queue_xmit:
+ push %ebp
+ push %edi
+ push %esi
+ push %ebx
+ sub $0xbc, %esp
+ mov 0xd0(%esp), %ebp ! %ebp = arg0 (skb)
+ mov 0x8(%ebp), %ebx ! %ebx = skb->sk
+ mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
+
+Reporting the bug
+-----------------
+
+Once you find where the bug happened, by inspecting its location,
+you could either try to fix it yourself or report it upstream.
+
+In order to report it upstream, you should identify the mailing list
+used for the development of the affected code. This can be done by using
+the ``get_maintainer.pl`` script.
+
+For example, if you find a bug at the gspca's conex.c file, you can get
+their maintainers with::
+
+ $ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c
+ Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%)
+ Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%)
+ Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%)
+ Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%)
+ linux-media@vger.kernel.org (open list:GSPCA USB WEBCAM DRIVER)
+ linux-kernel@vger.kernel.org (open list)
+
+Please notice that it will point to:
+
+- The last developers that touched on the source code. On the above example,
+ Tejun and Bhaktipriya (in this specific case, none really envolved on the
+ development of this file);
+- The driver maintainer (Hans Verkuil);
+- The subsystem maintainer (Mauro Carvalho Chehab)
+- The driver and/or subsystem mailing list (linux-media@vger.kernel.org);
+- the Linux Kernel mailing list (linux-kernel@vger.kernel.org).
+
+Usually, the fastest way to have your bug fixed is to report it to mailing
+list used for the development of the code (linux-media ML) copying the driver maintainer (Hans).
+
+If you are totally stumped as to whom to send the report, and
+``get_maintainer.pl`` didn't provide you anything useful, send it to
+linux-kernel@vger.kernel.org.
+
+Thanks for your help in making Linux as stable as humanly possible.
+
+Fixing the bug
+--------------
+
+If you know programming, you could help us by not only reporting the bug,
+but also providing us with a solution. After all open source is about
+sharing what you do and don't you want to be recognised for your genius?
+
+If you decide to take this way, once you have worked out a fix please submit
+it upstream.
+
+Please do read
+ref:`Documentation/process/submitting-patches.rst <submittingpatches>` though
+to help your code get accepted.
+
+
+---------------------------------------------------------------------------
+
+Notes on Oops tracing with ``klogd``
+------------------------------------
+
+In order to help Linus and the other kernel developers there has been
+substantial support incorporated into ``klogd`` for processing protection
+faults. In order to have full support for address resolution at least
+version 1.3-pl3 of the ``sysklogd`` package should be used.
+
+When a protection fault occurs the ``klogd`` daemon automatically
+translates important addresses in the kernel log messages to their
+symbolic equivalents. This translated kernel message is then
+forwarded through whatever reporting mechanism ``klogd`` is using. The
+protection fault message can be simply cut out of the message files
+and forwarded to the kernel developers.
+
+Two types of address resolution are performed by ``klogd``. The first is
+static translation and the second is dynamic translation. Static
+translation uses the System.map file in much the same manner that
+ksymoops does. In order to do static translation the ``klogd`` daemon
+must be able to find a system map file at daemon initialization time.
+See the klogd man page for information on how ``klogd`` searches for map
+files.
+
+Dynamic address translation is important when kernel loadable modules
+are being used. Since memory for kernel modules is allocated from the
+kernel's dynamic memory pools there are no fixed locations for either
+the start of the module or for functions and symbols in the module.
+
+The kernel supports system calls which allow a program to determine
+which modules are loaded and their location in memory. Using these
+system calls the klogd daemon builds a symbol table which can be used
+to debug a protection fault which occurs in a loadable kernel module.
+
+At the very minimum klogd will provide the name of the module which
+generated the protection fault. There may be additional symbolic
+information available if the developer of the loadable module chose to
+export symbol information from the module.
+
+Since the kernel module environment can be dynamic there must be a
+mechanism for notifying the ``klogd`` daemon when a change in module
+environment occurs. There are command line options available which
+allow klogd to signal the currently executing daemon that symbol
+information should be refreshed. See the ``klogd`` manual page for more
+information.
+
+A patch is included with the sysklogd distribution which modifies the
+``modules-2.0.0`` package to automatically signal klogd whenever a module
+is loaded or unloaded. Applying this patch provides essentially
+seamless support for debugging protection faults which occur with
+kernel loadable modules.
+
+The following is an example of a protection fault in a loadable module
+processed by ``klogd``::
+
+ Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
+ Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
+ Aug 29 09:51:01 blizard kernel: *pde = 00000000
+ Aug 29 09:51:01 blizard kernel: Oops: 0002
+ Aug 29 09:51:01 blizard kernel: CPU: 0
+ Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
+ Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
+ Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
+ Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
+ Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
+ Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
+ Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
+ Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
+ Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
+ Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
+ Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
+
+---------------------------------------------------------------------------
+
+::
+
+ Dr. G.W. Wettstein Oncology Research Div. Computing Facility
+ Roger Maris Cancer Center INTERNET: greg@wind.rmcc.com
+ 820 4th St. N.
+ Fargo, ND 58122
+ Phone: 701-234-7556
diff --git a/Documentation/admin-guide/conf.py b/Documentation/admin-guide/conf.py
new file mode 100644
index 000000000000..86f738953799
--- /dev/null
+++ b/Documentation/admin-guide/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel User Documentation'
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'linux-user.tex', 'Linux Kernel User Documentation',
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/admin-guide/devices.rst b/Documentation/admin-guide/devices.rst
new file mode 100644
index 000000000000..7fadc05330dd
--- /dev/null
+++ b/Documentation/admin-guide/devices.rst
@@ -0,0 +1,268 @@
+
+Linux allocated devices (4.x+ version)
+======================================
+
+This list is the Linux Device List, the official registry of allocated
+device numbers and ``/dev`` directory nodes for the Linux operating
+system.
+
+The LaTeX version of this document is no longer maintained, nor is
+the document that used to reside at lanana.org. This version in the
+mainline Linux kernel is the master document. Updates shall be sent
+as patches to the kernel maintainers (see the
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` document).
+Specifically explore the sections titled "CHAR and MISC DRIVERS", and
+"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers
+to involve for character and block devices.
+
+This document is included by reference into the Filesystem Hierarchy
+Standard (FHS). The FHS is available from http://www.pathname.com/fhs/.
+
+Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
+platform only. Allocations marked (68k/Atari) apply to Linux/68k on
+the Atari platform only.
+
+This document is in the public domain. The authors requests, however,
+that semantically altered versions are not distributed without
+permission of the authors, assuming the authors can be contacted without
+an unreasonable effort.
+
+
+.. attention::
+
+ DEVICE DRIVERS AUTHORS PLEASE READ THIS
+
+ Linux now has extensive support for dynamic allocation of device numbering
+ and can use ``sysfs`` and ``udev`` (``systemd``) to handle the naming needs.
+ There are still some exceptions in the serial and boot device area. Before
+ asking for a device number make sure you actually need one.
+
+ To have a major number allocated, or a minor number in situations
+ where that applies (e.g. busmice), please submit a patch and send to
+ the authors as indicated above.
+
+ Keep the description of the device *in the same format
+ as this list*. The reason for this is that it is the only way we have
+ found to ensure we have all the requisite information to publish your
+ device and avoid conflicts.
+
+ Finally, sometimes we have to play "namespace police." Please don't be
+ offended. We often get submissions for ``/dev`` names that would be bound
+ to cause conflicts down the road. We are trying to avoid getting in a
+ situation where we would have to suffer an incompatible forward
+ change. Therefore, please consult with us **before** you make your
+ device names and numbers in any way public, at least to the point
+ where it would be at all difficult to get them changed.
+
+ Your cooperation is appreciated.
+
+.. include:: devices.txt
+ :literal:
+
+Additional ``/dev/`` directory entries
+--------------------------------------
+
+This section details additional entries that should or may exist in
+the /dev directory. It is preferred that symbolic links use the same
+form (absolute or relative) as is indicated here. Links are
+classified as "hard" or "symbolic" depending on the preferred type of
+link; if possible, the indicated type of link should be used.
+
+Compulsory links
+++++++++++++++++
+
+These links should exist on all systems:
+
+=============== =============== =============== ===============================
+/dev/fd /proc/self/fd symbolic File descriptors
+/dev/stdin fd/0 symbolic stdin file descriptor
+/dev/stdout fd/1 symbolic stdout file descriptor
+/dev/stderr fd/2 symbolic stderr file descriptor
+/dev/nfsd socksys symbolic Required by iBCS-2
+/dev/X0R null symbolic Required by iBCS-2
+=============== =============== =============== ===============================
+
+Note: ``/dev/X0R`` is <letter X>-<digit 0>-<letter R>.
+
+Recommended links
++++++++++++++++++
+
+It is recommended that these links exist on all systems:
+
+
+=============== =============== =============== ===============================
+/dev/core /proc/kcore symbolic Backward compatibility
+/dev/ramdisk ram0 symbolic Backward compatibility
+/dev/ftape qft0 symbolic Backward compatibility
+/dev/bttv0 video0 symbolic Backward compatibility
+/dev/radio radio0 symbolic Backward compatibility
+/dev/i2o* /dev/i2o/* symbolic Backward compatibility
+/dev/scd? sr? hard Alternate SCSI CD-ROM name
+=============== =============== =============== ===============================
+
+Locally defined links
++++++++++++++++++++++
+
+The following links may be established locally to conform to the
+configuration of the system. This is merely a tabulation of existing
+practice, and does not constitute a recommendation. However, if they
+exist, they should have the following uses.
+
+=============== =============== =============== ===============================
+/dev/mouse mouse port symbolic Current mouse device
+/dev/tape tape device symbolic Current tape device
+/dev/cdrom CD-ROM device symbolic Current CD-ROM device
+/dev/cdwriter CD-writer symbolic Current CD-writer device
+/dev/scanner scanner symbolic Current scanner device
+/dev/modem modem port symbolic Current dialout device
+/dev/root root device symbolic Current root filesystem
+/dev/swap swap device symbolic Current swap device
+=============== =============== =============== ===============================
+
+``/dev/modem`` should not be used for a modem which supports dialin as
+well as dialout, as it tends to cause lock file problems. If it
+exists, ``/dev/modem`` should point to the appropriate primary TTY device
+(the use of the alternate callout devices is deprecated).
+
+For SCSI devices, ``/dev/tape`` and ``/dev/cdrom`` should point to the
+*cooked* devices (``/dev/st*`` and ``/dev/sr*``, respectively), whereas
+``/dev/cdwriter`` and /dev/scanner should point to the appropriate generic
+SCSI devices (/dev/sg*).
+
+``/dev/mouse`` may point to a primary serial TTY device, a hardware mouse
+device, or a socket for a mouse driver program (e.g. ``/dev/gpmdata``).
+
+Sockets and pipes
++++++++++++++++++
+
+Non-transient sockets and named pipes may exist in /dev. Common entries are:
+
+=============== =============== ===============================================
+/dev/printer socket lpd local socket
+/dev/log socket syslog local socket
+/dev/gpmdata socket gpm mouse multiplexer
+=============== =============== ===============================================
+
+Mount points
+++++++++++++
+
+The following names are reserved for mounting special filesystems
+under /dev. These special filesystems provide kernel interfaces that
+cannot be provided with standard device nodes.
+
+=============== =============== ===============================================
+/dev/pts devpts PTY slave filesystem
+/dev/shm tmpfs POSIX shared memory maintenance access
+=============== =============== ===============================================
+
+Terminal devices
+----------------
+
+Terminal, or TTY devices are a special class of character devices. A
+terminal device is any device that could act as a controlling terminal
+for a session; this includes virtual consoles, serial ports, and
+pseudoterminals (PTYs).
+
+All terminal devices share a common set of capabilities known as line
+disciplines; these include the common terminal line discipline as well
+as SLIP and PPP modes.
+
+All terminal devices are named similarly; this section explains the
+naming and use of the various types of TTYs. Note that the naming
+conventions include several historical warts; some of these are
+Linux-specific, some were inherited from other systems, and some
+reflect Linux outgrowing a borrowed convention.
+
+A hash mark (``#``) in a device name is used here to indicate a decimal
+number without leading zeroes.
+
+Virtual consoles and the console device
++++++++++++++++++++++++++++++++++++++++
+
+Virtual consoles are full-screen terminal displays on the system video
+monitor. Virtual consoles are named ``/dev/tty#``, with numbering
+starting at ``/dev/tty1``; ``/dev/tty0`` is the current virtual console.
+``/dev/tty0`` is the device that should be used to access the system video
+card on those architectures for which the frame buffer devices
+(``/dev/fb*``) are not applicable. Do not use ``/dev/console``
+for this purpose.
+
+The console device, ``/dev/console``, is the device to which system
+messages should be sent, and on which logins should be permitted in
+single-user mode. Starting with Linux 2.1.71, ``/dev/console`` is managed
+by the kernel; for previous versions it should be a symbolic link to
+either ``/dev/tty0``, a specific virtual console such as ``/dev/tty1``, or to
+a serial port primary (``tty*``, not ``cu*``) device, depending on the
+configuration of the system.
+
+Serial ports
+++++++++++++
+
+Serial ports are RS-232 serial ports and any device which simulates
+one, either in hardware (such as internal modems) or in software (such
+as the ISDN driver.) Under Linux, each serial ports has two device
+names, the primary or callin device and the alternate or callout one.
+Each kind of device is indicated by a different letter. For any
+letter X, the names of the devices are ``/dev/ttyX#`` and ``/dev/cux#``,
+respectively; for historical reasons, ``/dev/ttyS#`` and ``/dev/ttyC#``
+correspond to ``/dev/cua#`` and ``/dev/cub#``. In the future, it should be
+expected that multiple letters will be used; all letters will be upper
+case for the "tty" device (e.g. ``/dev/ttyDP#``) and lower case for the
+"cu" device (e.g. ``/dev/cudp#``).
+
+The names ``/dev/ttyQ#`` and ``/dev/cuq#`` are reserved for local use.
+
+The alternate devices provide for kernel-based exclusion and somewhat
+different defaults than the primary devices. Their main purpose is to
+allow the use of serial ports with programs with no inherent or broken
+support for serial ports. Their use is deprecated, and they may be
+removed from a future version of Linux.
+
+Arbitration of serial ports is provided by the use of lock files with
+the names ``/var/lock/LCK..ttyX#``. The contents of the lock file should
+be the PID of the locking process as an ASCII number.
+
+It is common practice to install links such as /dev/modem
+which point to serial ports. In order to ensure proper locking in the
+presence of these links, it is recommended that software chase
+symlinks and lock all possible names; additionally, it is recommended
+that a lock file be installed with the corresponding alternate
+device. In order to avoid deadlocks, it is recommended that the locks
+are acquired in the following order, and released in the reverse:
+
+ 1. The symbolic link name, if any (``/var/lock/LCK..modem``)
+ 2. The "tty" name (``/var/lock/LCK..ttyS2``)
+ 3. The alternate device name (``/var/lock/LCK..cua2``)
+
+In the case of nested symbolic links, the lock files should be
+installed in the order the symlinks are resolved.
+
+Under no circumstances should an application hold a lock while waiting
+for another to be released. In addition, applications which attempt
+to create lock files for the corresponding alternate device names
+should take into account the possibility of being used on a non-serial
+port TTY, for which no alternate device would exist.
+
+Pseudoterminals (PTYs)
+++++++++++++++++++++++
+
+Pseudoterminals, or PTYs, are used to create login sessions or provide
+other capabilities requiring a TTY line discipline (including SLIP or
+PPP capability) to arbitrary data-generation processes. Each PTY has
+a master side, named ``/dev/pty[p-za-e][0-9a-f]``, and a slave side, named
+``/dev/tty[p-za-e][0-9a-f]``. The kernel arbitrates the use of PTYs by
+allowing each master side to be opened only once.
+
+Once the master side has been opened, the corresponding slave device
+can be used in the same manner as any TTY device. The master and
+slave devices are connected by the kernel, generating the equivalent
+of a bidirectional pipe with TTY capabilities.
+
+Recent versions of the Linux kernels and GNU libc contain support for
+the System V/Unix98 naming scheme for PTYs, which assigns a common
+device, ``/dev/ptmx``, to all the masters (opening it will automatically
+give you a previously unassigned PTY) and a subdirectory, ``/dev/pts``,
+for the slaves; the slaves are named with decimal integers (``/dev/pts/#``
+in our notation). This removes the problem of exhausting the
+namespace and enables the kernel to automatically create the device
+nodes for the slaves on demand using the "devpts" filesystem.
diff --git a/Documentation/devices.txt b/Documentation/admin-guide/devices.txt
index 4035eca87144..c9cea2e39c21 100644
--- a/Documentation/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -1,63 +1,8 @@
-
- LINUX ALLOCATED DEVICES (4.x+ version)
-
-This list is the Linux Device List, the official registry of allocated
-device numbers and /dev directory nodes for the Linux operating
-system.
-
-The LaTeX version of this document is no longer maintained, nor is
-the document that used to reside at lanana.org. This version in the
-mainline Linux kernel is the master document. Updates shall be sent
-as patches to the kernel maintainers (see the SubmittingPatches document).
-Specifically explore the sections titled "CHAR and MISC DRIVERS", and
-"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers
-to involve for character and block devices.
-
-This document is included by reference into the Filesystem Hierarchy
-Standard (FHS). The FHS is available from http://www.pathname.com/fhs/.
-
-Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
-platform only. Allocations marked (68k/Atari) apply to Linux/68k on
-the Atari platform only.
-
-This document is in the public domain. The authors requests, however,
-that semantically altered versions are not distributed without
-permission of the authors, assuming the authors can be contacted without
-an unreasonable effort.
-
-
- **** DEVICE DRIVERS AUTHORS PLEASE READ THIS ****
-
-Linux now has extensive support for dynamic allocation of device numbering
-and can use sysfs and udev (systemd) to handle the naming needs. There are
-still some exceptions in the serial and boot device area. Before asking
-for a device number make sure you actually need one.
-
-To have a major number allocated, or a minor number in situations
-where that applies (e.g. busmice), please submit a patch and send to
-the authors as indicated above.
-
-Keep the description of the device *in the same format
-as this list*. The reason for this is that it is the only way we have
-found to ensure we have all the requisite information to publish your
-device and avoid conflicts.
-
-Finally, sometimes we have to play "namespace police." Please don't be
-offended. We often get submissions for /dev names that would be bound
-to cause conflicts down the road. We are trying to avoid getting in a
-situation where we would have to suffer an incompatible forward
-change. Therefore, please consult with us *before* you make your
-device names and numbers in any way public, at least to the point
-where it would be at all difficult to get them changed.
-
-Your cooperation is appreciated.
-
-
- 0 Unnamed devices (e.g. non-device mounts)
+ 0 Unnamed devices (e.g. non-device mounts)
0 = reserved as null device number
See block major 144, 145, 146 for expansion areas.
- 1 char Memory devices
+ 1 char Memory devices
1 = /dev/mem Physical memory access
2 = /dev/kmem Kernel virtual memory access
3 = /dev/null Null device
@@ -72,7 +17,7 @@ Your cooperation is appreciated.
export the buffered printk records.
12 = /dev/oldmem OBSOLETE - replaced by /proc/vmcore
- 1 block RAM disk
+ 1 block RAM disk
0 = /dev/ram0 First RAM disk
1 = /dev/ram1 Second RAM disk
...
@@ -83,7 +28,7 @@ Your cooperation is appreciated.
by the boot loader; newer kernels use /dev/ram0 for
the initrd.
- 2 char Pseudo-TTY masters
+ 2 char Pseudo-TTY masters
0 = /dev/ptyp0 First PTY master
1 = /dev/ptyp1 Second PTY master
...
@@ -101,7 +46,7 @@ Your cooperation is appreciated.
master multiplex (/dev/ptmx) to acquire a PTY on
demand.
- 2 block Floppy disks
+ 2 block Floppy disks
0 = /dev/fd0 Controller 0, drive 0, autodetect
1 = /dev/fd1 Controller 0, drive 1, autodetect
2 = /dev/fd2 Controller 0, drive 2, autodetect
@@ -158,7 +103,7 @@ Your cooperation is appreciated.
and E for the 3.5" models have been deprecated, since
the drive type is insignificant for these devices.
- 3 char Pseudo-TTY slaves
+ 3 char Pseudo-TTY slaves
0 = /dev/ttyp0 First PTY slave
1 = /dev/ttyp1 Second PTY slave
...
@@ -167,7 +112,7 @@ Your cooperation is appreciated.
These are the old-style (BSD) PTY devices; Unix98
devices are on major 136 and above.
- 3 block First MFM, RLL and IDE hard disk/CD-ROM interface
+ 3 block First MFM, RLL and IDE hard disk/CD-ROM interface
0 = /dev/hda Master: whole disk (or CD-ROM)
64 = /dev/hdb Slave: whole disk (or CD-ROM)
@@ -183,7 +128,7 @@ Your cooperation is appreciated.
Other versions of Linux use partitioning schemes
appropriate to their respective architectures.
- 4 char TTY devices
+ 4 char TTY devices
0 = /dev/tty0 Current virtual console
1 = /dev/tty1 First virtual console
@@ -199,13 +144,13 @@ Your cooperation is appreciated.
number for BSD PTY devices. As of Linux 2.1.115, this
is no longer supported. Use major numbers 2 and 3.
- 4 block Aliases for dynamically allocated major devices to be used
+ 4 block Aliases for dynamically allocated major devices to be used
when its not possible to create the real device nodes
because the root filesystem is mounted read-only.
- 0 = /dev/root
+ 0 = /dev/root
- 5 char Alternate TTY devices
+ 5 char Alternate TTY devices
0 = /dev/tty Current TTY device
1 = /dev/console System console
2 = /dev/ptmx PTY master multiplex
@@ -218,7 +163,7 @@ Your cooperation is appreciated.
the section on terminal devices for more information
on /dev/console.
- 6 char Parallel printer devices
+ 6 char Parallel printer devices
0 = /dev/lp0 Parallel printer on parport0
1 = /dev/lp1 Parallel printer on parport1
...
@@ -227,7 +172,7 @@ Your cooperation is appreciated.
between parallel ports and I/O addresses. Instead,
they are redirected through the parport multiplex layer.
- 7 char Virtual console capture devices
+ 7 char Virtual console capture devices
0 = /dev/vcs Current vc text contents
1 = /dev/vcs1 tty1 text contents
...
@@ -239,7 +184,7 @@ Your cooperation is appreciated.
NOTE: These devices permit both read and write access.
- 7 block Loopback devices
+ 7 block Loopback devices
0 = /dev/loop0 First loop device
1 = /dev/loop1 Second loop device
...
@@ -248,7 +193,7 @@ Your cooperation is appreciated.
associated with block devices. The binding to the
loop devices is handled by mount(8) or losetup(8).
- 8 block SCSI disk devices (0-15)
+ 8 block SCSI disk devices (0-15)
0 = /dev/sda First SCSI disk whole disk
16 = /dev/sdb Second SCSI disk whole disk
32 = /dev/sdc Third SCSI disk whole disk
@@ -259,7 +204,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 9 char SCSI tape devices
+ 9 char SCSI tape devices
0 = /dev/st0 First SCSI tape, mode 0
1 = /dev/st1 Second SCSI tape, mode 0
...
@@ -290,7 +235,7 @@ Your cooperation is appreciated.
ioctl()'s can be used to rewind the tape regardless of
the device used to access it.
- 9 block Metadisk (RAID) devices
+ 9 block Metadisk (RAID) devices
0 = /dev/md0 First metadisk group
1 = /dev/md1 Second metadisk group
...
@@ -298,7 +243,7 @@ Your cooperation is appreciated.
The metadisk driver is used to span a
filesystem across multiple physical disks.
- 10 char Non-serial mice, misc features
+ 10 char Non-serial mice, misc features
0 = /dev/logibm Logitech bus mouse
1 = /dev/psaux PS/2-style mouse port
2 = /dev/inportbm Microsoft Inport bus mouse
@@ -428,22 +373,22 @@ Your cooperation is appreciated.
240-254 Reserved for local use
255 Reserved for MISC_DYNAMIC_MINOR
- 11 char Raw keyboard device (Linux/SPARC only)
+ 11 char Raw keyboard device (Linux/SPARC only)
0 = /dev/kbd Raw keyboard device
- 11 char Serial Mux device (Linux/PA-RISC only)
+ 11 char Serial Mux device (Linux/PA-RISC only)
0 = /dev/ttyB0 First mux port
1 = /dev/ttyB1 Second mux port
...
- 11 block SCSI CD-ROM devices
+ 11 block SCSI CD-ROM devices
0 = /dev/scd0 First SCSI CD-ROM
1 = /dev/scd1 Second SCSI CD-ROM
...
The prefix /dev/sr (instead of /dev/scd) has been deprecated.
- 12 char QIC-02 tape
+ 12 char QIC-02 tape
2 = /dev/ntpqic11 QIC-11, no rewind-on-close
3 = /dev/tpqic11 QIC-11, rewind-on-close
4 = /dev/ntpqic24 QIC-24, no rewind-on-close
@@ -456,9 +401,9 @@ Your cooperation is appreciated.
The device names specified are proposed -- if there
are "standard" names for these devices, please let me know.
- 12 block
+ 12 block
- 13 char Input core
+ 13 char Input core
0 = /dev/input/js0 First joystick
1 = /dev/input/js1 Second joystick
...
@@ -472,10 +417,10 @@ Your cooperation is appreciated.
Each device type has 5 bits (32 minors).
- 13 block Previously used for the XT disk (/dev/xdN)
+ 13 block Previously used for the XT disk (/dev/xdN)
Deleted in kernel v3.9.
- 14 char Open Sound System (OSS)
+ 14 char Open Sound System (OSS)
0 = /dev/mixer Mixer control
1 = /dev/sequencer Audio sequencer
2 = /dev/midi00 First MIDI port
@@ -493,44 +438,44 @@ Your cooperation is appreciated.
34 = /dev/midi02 Third MIDI port
50 = /dev/midi03 Fourth MIDI port
- 14 block
+ 14 block
- 15 char Joystick
+ 15 char Joystick
0 = /dev/js0 First analog joystick
1 = /dev/js1 Second analog joystick
...
128 = /dev/djs0 First digital joystick
129 = /dev/djs1 Second digital joystick
...
- 15 block Sony CDU-31A/CDU-33A CD-ROM
+ 15 block Sony CDU-31A/CDU-33A CD-ROM
0 = /dev/sonycd Sony CDU-31a CD-ROM
- 16 char Non-SCSI scanners
+ 16 char Non-SCSI scanners
0 = /dev/gs4500 Genius 4500 handheld scanner
- 16 block GoldStar CD-ROM
+ 16 block GoldStar CD-ROM
0 = /dev/gscd GoldStar CD-ROM
- 17 char OBSOLETE (was Chase serial card)
+ 17 char OBSOLETE (was Chase serial card)
0 = /dev/ttyH0 First Chase port
1 = /dev/ttyH1 Second Chase port
...
- 17 block Optics Storage CD-ROM
+ 17 block Optics Storage CD-ROM
0 = /dev/optcd Optics Storage CD-ROM
- 18 char OBSOLETE (was Chase serial card - alternate devices)
+ 18 char OBSOLETE (was Chase serial card - alternate devices)
0 = /dev/cuh0 Callout device for ttyH0
1 = /dev/cuh1 Callout device for ttyH1
...
- 18 block Sanyo CD-ROM
+ 18 block Sanyo CD-ROM
0 = /dev/sjcd Sanyo CD-ROM
- 19 char Cyclades serial card
+ 19 char Cyclades serial card
0 = /dev/ttyC0 First Cyclades port
...
31 = /dev/ttyC31 32nd Cyclades port
- 19 block "Double" compressed disk
+ 19 block "Double" compressed disk
0 = /dev/double0 First compressed disk
...
7 = /dev/double7 Eighth compressed disk
@@ -541,15 +486,15 @@ Your cooperation is appreciated.
See the Double documentation for the meaning of the
mirror devices.
- 20 char Cyclades serial card - alternate devices
+ 20 char Cyclades serial card - alternate devices
0 = /dev/cub0 Callout device for ttyC0
...
31 = /dev/cub31 Callout device for ttyC31
- 20 block Hitachi CD-ROM (under development)
+ 20 block Hitachi CD-ROM (under development)
0 = /dev/hitcd Hitachi CD-ROM
- 21 char Generic SCSI access
+ 21 char Generic SCSI access
0 = /dev/sg0 First generic SCSI device
1 = /dev/sg1 Second generic SCSI device
...
@@ -559,7 +504,7 @@ Your cooperation is appreciated.
the system and is counter to standard Linux
device-naming practice.
- 21 block Acorn MFM hard drive interface
+ 21 block Acorn MFM hard drive interface
0 = /dev/mfma First MFM drive whole disk
64 = /dev/mfmb Second MFM drive whole disk
@@ -567,25 +512,25 @@ Your cooperation is appreciated.
Partitions are handled the same way as for IDE disks
(see major number 3).
- 22 char Digiboard serial card
+ 22 char Digiboard serial card
0 = /dev/ttyD0 First Digiboard port
1 = /dev/ttyD1 Second Digiboard port
...
- 22 block Second IDE hard disk/CD-ROM interface
+ 22 block Second IDE hard disk/CD-ROM interface
0 = /dev/hdc Master: whole disk (or CD-ROM)
64 = /dev/hdd Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 23 char Digiboard serial card - alternate devices
+ 23 char Digiboard serial card - alternate devices
0 = /dev/cud0 Callout device for ttyD0
1 = /dev/cud1 Callout device for ttyD1
...
- 23 block Mitsumi proprietary CD-ROM
+ 23 block Mitsumi proprietary CD-ROM
0 = /dev/mcd Mitsumi CD-ROM
- 24 char Stallion serial card
+ 24 char Stallion serial card
0 = /dev/ttyE0 Stallion port 0 card 0
1 = /dev/ttyE1 Stallion port 1 card 0
...
@@ -598,10 +543,10 @@ Your cooperation is appreciated.
192 = /dev/ttyE192 Stallion port 0 card 3
193 = /dev/ttyE193 Stallion port 1 card 3
...
- 24 block Sony CDU-535 CD-ROM
+ 24 block Sony CDU-535 CD-ROM
0 = /dev/cdu535 Sony CDU-535 CD-ROM
- 25 char Stallion serial card - alternate devices
+ 25 char Stallion serial card - alternate devices
0 = /dev/cue0 Callout device for ttyE0
1 = /dev/cue1 Callout device for ttyE1
...
@@ -614,21 +559,21 @@ Your cooperation is appreciated.
192 = /dev/cue192 Callout device for ttyE192
193 = /dev/cue193 Callout device for ttyE193
...
- 25 block First Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 25 block First Matsushita (Panasonic/SoundBlaster) CD-ROM
0 = /dev/sbpcd0 Panasonic CD-ROM controller 0 unit 0
1 = /dev/sbpcd1 Panasonic CD-ROM controller 0 unit 1
2 = /dev/sbpcd2 Panasonic CD-ROM controller 0 unit 2
3 = /dev/sbpcd3 Panasonic CD-ROM controller 0 unit 3
- 26 char
+ 26 char
- 26 block Second Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 26 block Second Matsushita (Panasonic/SoundBlaster) CD-ROM
0 = /dev/sbpcd4 Panasonic CD-ROM controller 1 unit 0
1 = /dev/sbpcd5 Panasonic CD-ROM controller 1 unit 1
2 = /dev/sbpcd6 Panasonic CD-ROM controller 1 unit 2
3 = /dev/sbpcd7 Panasonic CD-ROM controller 1 unit 3
- 27 char QIC-117 tape
+ 27 char QIC-117 tape
0 = /dev/qft0 Unit 0, rewind-on-close
1 = /dev/qft1 Unit 1, rewind-on-close
2 = /dev/qft2 Unit 2, rewind-on-close
@@ -654,29 +599,29 @@ Your cooperation is appreciated.
38 = /dev/nrawqft2 Unit 2, no rewind-on-close, no file marks
39 = /dev/nrawqft3 Unit 3, no rewind-on-close, no file marks
- 27 block Third Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 27 block Third Matsushita (Panasonic/SoundBlaster) CD-ROM
0 = /dev/sbpcd8 Panasonic CD-ROM controller 2 unit 0
1 = /dev/sbpcd9 Panasonic CD-ROM controller 2 unit 1
2 = /dev/sbpcd10 Panasonic CD-ROM controller 2 unit 2
3 = /dev/sbpcd11 Panasonic CD-ROM controller 2 unit 3
- 28 char Stallion serial card - card programming
+ 28 char Stallion serial card - card programming
0 = /dev/staliomem0 First Stallion card I/O memory
1 = /dev/staliomem1 Second Stallion card I/O memory
2 = /dev/staliomem2 Third Stallion card I/O memory
3 = /dev/staliomem3 Fourth Stallion card I/O memory
- 28 char Atari SLM ACSI laser printer (68k/Atari)
+ 28 char Atari SLM ACSI laser printer (68k/Atari)
0 = /dev/slm0 First SLM laser printer
1 = /dev/slm1 Second SLM laser printer
...
- 28 block Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 28 block Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
0 = /dev/sbpcd12 Panasonic CD-ROM controller 3 unit 0
1 = /dev/sbpcd13 Panasonic CD-ROM controller 3 unit 1
2 = /dev/sbpcd14 Panasonic CD-ROM controller 3 unit 2
3 = /dev/sbpcd15 Panasonic CD-ROM controller 3 unit 3
- 28 block ACSI disk (68k/Atari)
+ 28 block ACSI disk (68k/Atari)
0 = /dev/ada First ACSI disk whole disk
16 = /dev/adb Second ACSI disk whole disk
32 = /dev/adc Third ACSI disk whole disk
@@ -687,16 +632,16 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15, like SCSI.
- 29 char Universal frame buffer
+ 29 char Universal frame buffer
0 = /dev/fb0 First frame buffer
1 = /dev/fb1 Second frame buffer
...
31 = /dev/fb31 32nd frame buffer
- 29 block Aztech/Orchid/Okano/Wearnes CD-ROM
+ 29 block Aztech/Orchid/Okano/Wearnes CD-ROM
0 = /dev/aztcd Aztech CD-ROM
- 30 char iBCS-2 compatibility devices
+ 30 char iBCS-2 compatibility devices
0 = /dev/socksys Socket access
1 = /dev/spx SVR3 local X interface
32 = /dev/inet/ip Network access
@@ -727,17 +672,17 @@ Your cooperation is appreciated.
/dev/nfsd -> /dev/socksys
/dev/X0R -> /dev/null (? apparently not required ?)
- 30 block Philips LMS CM-205 CD-ROM
+ 30 block Philips LMS CM-205 CD-ROM
0 = /dev/cm205cd Philips LMS CM-205 CD-ROM
/dev/lmscd is an older name for this device. This
driver does not work with the CM-205MS CD-ROM.
- 31 char MPU-401 MIDI
+ 31 char MPU-401 MIDI
0 = /dev/mpu401data MPU-401 data port
1 = /dev/mpu401stat MPU-401 status port
- 31 block ROM/flash memory card
+ 31 block ROM/flash memory card
0 = /dev/rom0 First ROM card (rw)
...
7 = /dev/rom7 Eighth ROM card (rw)
@@ -756,25 +701,25 @@ Your cooperation is appreciated.
devices. The read-only devices (ro) support reading
only.
- 32 char Specialix serial card
+ 32 char Specialix serial card
0 = /dev/ttyX0 First Specialix port
1 = /dev/ttyX1 Second Specialix port
...
- 32 block Philips LMS CM-206 CD-ROM
+ 32 block Philips LMS CM-206 CD-ROM
0 = /dev/cm206cd Philips LMS CM-206 CD-ROM
- 33 char Specialix serial card - alternate devices
+ 33 char Specialix serial card - alternate devices
0 = /dev/cux0 Callout device for ttyX0
1 = /dev/cux1 Callout device for ttyX1
...
- 33 block Third IDE hard disk/CD-ROM interface
+ 33 block Third IDE hard disk/CD-ROM interface
0 = /dev/hde Master: whole disk (or CD-ROM)
64 = /dev/hdf Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 34 char Z8530 HDLC driver
+ 34 char Z8530 HDLC driver
0 = /dev/scc0 First Z8530, first port
1 = /dev/scc1 First Z8530, second port
2 = /dev/scc2 Second Z8530, first port
@@ -785,14 +730,14 @@ Your cooperation is appreciated.
/dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so
on.
- 34 block Fourth IDE hard disk/CD-ROM interface
+ 34 block Fourth IDE hard disk/CD-ROM interface
0 = /dev/hdg Master: whole disk (or CD-ROM)
64 = /dev/hdh Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 35 char tclmidi MIDI driver
+ 35 char tclmidi MIDI driver
0 = /dev/midi0 First MIDI port, kernel timed
1 = /dev/midi1 Second MIDI port, kernel timed
2 = /dev/midi2 Third MIDI port, kernel timed
@@ -806,10 +751,10 @@ Your cooperation is appreciated.
130 = /dev/smpte2 Third MIDI port, SMPTE timed
131 = /dev/smpte3 Fourth MIDI port, SMPTE timed
- 35 block Slow memory ramdisk
+ 35 block Slow memory ramdisk
0 = /dev/slram Slow memory ramdisk
- 36 char Netlink support
+ 36 char Netlink support
0 = /dev/route Routing, device updates, kernel to user
1 = /dev/skip enSKIP security cache control
3 = /dev/fwmonitor Firewall packet copies
@@ -817,9 +762,9 @@ Your cooperation is appreciated.
...
31 = /dev/tap15 16th Ethertap device
- 36 block OBSOLETE (was MCA ESDI hard disk)
+ 36 block OBSOLETE (was MCA ESDI hard disk)
- 37 char IDE tape
+ 37 char IDE tape
0 = /dev/ht0 First IDE tape
1 = /dev/ht1 Second IDE tape
...
@@ -829,10 +774,10 @@ Your cooperation is appreciated.
Currently, only one IDE tape drive is supported.
- 37 block Zorro II ramdisk
+ 37 block Zorro II ramdisk
0 = /dev/z2ram Zorro II ramdisk
- 38 char Myricom PCI Myrinet board
+ 38 char Myricom PCI Myrinet board
0 = /dev/mlanai0 First Myrinet board
1 = /dev/mlanai1 Second Myrinet board
...
@@ -841,9 +786,9 @@ Your cooperation is appreciated.
and "user level packet I/O." This board is also
accessible as a standard networking "eth" device.
- 38 block OBSOLETE (was Linux/AP+)
+ 38 block OBSOLETE (was Linux/AP+)
- 39 char ML-16P experimental I/O board
+ 39 char ML-16P experimental I/O board
0 = /dev/ml16pa-a0 First card, first analog channel
1 = /dev/ml16pa-a1 First card, second analog channel
...
@@ -861,20 +806,20 @@ Your cooperation is appreciated.
50 = /dev/ml16pb-c1 Second card, second counter/timer
51 = /dev/ml16pb-c2 Second card, third counter/timer
...
- 39 block
+ 39 block
- 40 char
+ 40 char
- 40 block
+ 40 block
- 41 char Yet Another Micro Monitor
+ 41 char Yet Another Micro Monitor
0 = /dev/yamm Yet Another Micro Monitor
- 41 block
+ 41 block
- 42 char Demo/sample use
+ 42 char Demo/sample use
- 42 block Demo/sample use
+ 42 block Demo/sample use
This number is intended for use in sample code, as
well as a general "example" device number. It
@@ -887,12 +832,12 @@ Your cooperation is appreciated.
IN PARTICULAR, ANY DISTRIBUTION WHICH CONTAINS A
DEVICE DRIVER USING MAJOR NUMBER 42 IS NONCOMPLIANT.
- 43 char isdn4linux virtual modem
+ 43 char isdn4linux virtual modem
0 = /dev/ttyI0 First virtual modem
...
63 = /dev/ttyI63 64th virtual modem
- 43 block Network block devices
+ 43 block Network block devices
0 = /dev/nb0 First network block device
1 = /dev/nb1 Second network block device
...
@@ -904,12 +849,12 @@ Your cooperation is appreciated.
to mounting filesystems over the net, swapping over
the net, implementing block device in userland etc.
- 44 char isdn4linux virtual modem - alternate devices
+ 44 char isdn4linux virtual modem - alternate devices
0 = /dev/cui0 Callout device for ttyI0
...
63 = /dev/cui63 Callout device for ttyI63
- 44 block Flash Translation Layer (FTL) filesystems
+ 44 block Flash Translation Layer (FTL) filesystems
0 = /dev/ftla FTL on first Memory Technology Device
16 = /dev/ftlb FTL on second Memory Technology Device
32 = /dev/ftlc FTL on third Memory Technology Device
@@ -920,7 +865,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the partition
limit is 15 rather than 63 per disk (same as SCSI.)
- 45 char isdn4linux ISDN BRI driver
+ 45 char isdn4linux ISDN BRI driver
0 = /dev/isdn0 First virtual B channel raw data
...
63 = /dev/isdn63 64th virtual B channel raw data
@@ -934,7 +879,7 @@ Your cooperation is appreciated.
255 = /dev/isdninfo ISDN monitor interface
- 45 block Parallel port IDE disk devices
+ 45 block Parallel port IDE disk devices
0 = /dev/pda First parallel port IDE disk
16 = /dev/pdb Second parallel port IDE disk
32 = /dev/pdc Third parallel port IDE disk
@@ -944,21 +889,21 @@ Your cooperation is appreciated.
disks (see major number 3) except that the partition
limit is 15 rather than 63 per disk.
- 46 char Comtrol Rocketport serial card
+ 46 char Comtrol Rocketport serial card
0 = /dev/ttyR0 First Rocketport port
1 = /dev/ttyR1 Second Rocketport port
...
- 46 block Parallel port ATAPI CD-ROM devices
+ 46 block Parallel port ATAPI CD-ROM devices
0 = /dev/pcd0 First parallel port ATAPI CD-ROM
1 = /dev/pcd1 Second parallel port ATAPI CD-ROM
2 = /dev/pcd2 Third parallel port ATAPI CD-ROM
3 = /dev/pcd3 Fourth parallel port ATAPI CD-ROM
- 47 char Comtrol Rocketport serial card - alternate devices
+ 47 char Comtrol Rocketport serial card - alternate devices
0 = /dev/cur0 Callout device for ttyR0
1 = /dev/cur1 Callout device for ttyR1
...
- 47 block Parallel port ATAPI disk devices
+ 47 block Parallel port ATAPI disk devices
0 = /dev/pf0 First parallel port ATAPI disk
1 = /dev/pf1 Second parallel port ATAPI disk
2 = /dev/pf2 Third parallel port ATAPI disk
@@ -967,11 +912,11 @@ Your cooperation is appreciated.
This driver is intended for floppy disks and similar
devices and hence does not support partitioning.
- 48 char SDL RISCom serial card
+ 48 char SDL RISCom serial card
0 = /dev/ttyL0 First RISCom port
1 = /dev/ttyL1 Second RISCom port
...
- 48 block Mylex DAC960 PCI RAID controller; first controller
+ 48 block Mylex DAC960 PCI RAID controller; first controller
0 = /dev/rd/c0d0 First disk, whole disk
8 = /dev/rd/c0d1 Second disk, whole disk
...
@@ -983,11 +928,11 @@ Your cooperation is appreciated.
...
7 = /dev/rd/c?d?p7 Seventh partition
- 49 char SDL RISCom serial card - alternate devices
+ 49 char SDL RISCom serial card - alternate devices
0 = /dev/cul0 Callout device for ttyL0
1 = /dev/cul1 Callout device for ttyL1
...
- 49 block Mylex DAC960 PCI RAID controller; second controller
+ 49 block Mylex DAC960 PCI RAID controller; second controller
0 = /dev/rd/c1d0 First disk, whole disk
8 = /dev/rd/c1d1 Second disk, whole disk
...
@@ -995,19 +940,19 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 50 char Reserved for GLINT
+ 50 char Reserved for GLINT
- 50 block Mylex DAC960 PCI RAID controller; third controller
+ 50 block Mylex DAC960 PCI RAID controller; third controller
0 = /dev/rd/c2d0 First disk, whole disk
8 = /dev/rd/c2d1 Second disk, whole disk
...
248 = /dev/rd/c2d31 32nd disk, whole disk
- 51 char Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem
+ 51 char Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem
0 = /dev/bc0 First Baycom radio modem
1 = /dev/bc1 Second Baycom radio modem
...
- 51 block Mylex DAC960 PCI RAID controller; fourth controller
+ 51 block Mylex DAC960 PCI RAID controller; fourth controller
0 = /dev/rd/c3d0 First disk, whole disk
8 = /dev/rd/c3d1 Second disk, whole disk
...
@@ -1015,13 +960,13 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 52 char Spellcaster DataComm/BRI ISDN card
+ 52 char Spellcaster DataComm/BRI ISDN card
0 = /dev/dcbri0 First DataComm card
1 = /dev/dcbri1 Second DataComm card
2 = /dev/dcbri2 Third DataComm card
3 = /dev/dcbri3 Fourth DataComm card
- 52 block Mylex DAC960 PCI RAID controller; fifth controller
+ 52 block Mylex DAC960 PCI RAID controller; fifth controller
0 = /dev/rd/c4d0 First disk, whole disk
8 = /dev/rd/c4d1 Second disk, whole disk
...
@@ -1029,7 +974,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 53 char BDM interface for remote debugging MC683xx microcontrollers
+ 53 char BDM interface for remote debugging MC683xx microcontrollers
0 = /dev/pd_bdm0 PD BDM interface on lp0
1 = /dev/pd_bdm1 PD BDM interface on lp1
2 = /dev/pd_bdm2 PD BDM interface on lp2
@@ -1043,7 +988,7 @@ Your cooperation is appreciated.
Domain Interface and ICD is the commercial interface
by P&E.
- 53 block Mylex DAC960 PCI RAID controller; sixth controller
+ 53 block Mylex DAC960 PCI RAID controller; sixth controller
0 = /dev/rd/c5d0 First disk, whole disk
8 = /dev/rd/c5d1 Second disk, whole disk
...
@@ -1051,7 +996,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 54 char Electrocardiognosis Holter serial card
+ 54 char Electrocardiognosis Holter serial card
0 = /dev/holter0 First Holter port
1 = /dev/holter1 Second Holter port
2 = /dev/holter2 Third Holter port
@@ -1060,7 +1005,7 @@ Your cooperation is appreciated.
<mseritan@ottonel.pub.ro> to transfer data from Holter
24-hour heart monitoring equipment.
- 54 block Mylex DAC960 PCI RAID controller; seventh controller
+ 54 block Mylex DAC960 PCI RAID controller; seventh controller
0 = /dev/rd/c6d0 First disk, whole disk
8 = /dev/rd/c6d1 Second disk, whole disk
...
@@ -1068,10 +1013,10 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 55 char DSP56001 digital signal processor
+ 55 char DSP56001 digital signal processor
0 = /dev/dsp56k First DSP56001
- 55 block Mylex DAC960 PCI RAID controller; eighth controller
+ 55 block Mylex DAC960 PCI RAID controller; eighth controller
0 = /dev/rd/c7d0 First disk, whole disk
8 = /dev/rd/c7d1 Second disk, whole disk
...
@@ -1079,42 +1024,42 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
- 56 char Apple Desktop Bus
+ 56 char Apple Desktop Bus
0 = /dev/adb ADB bus control
Additional devices will be added to this number, all
starting with /dev/adb.
- 56 block Fifth IDE hard disk/CD-ROM interface
+ 56 block Fifth IDE hard disk/CD-ROM interface
0 = /dev/hdi Master: whole disk (or CD-ROM)
64 = /dev/hdj Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 57 char Hayes ESP serial card
+ 57 char Hayes ESP serial card
0 = /dev/ttyP0 First ESP port
1 = /dev/ttyP1 Second ESP port
...
- 57 block Sixth IDE hard disk/CD-ROM interface
+ 57 block Sixth IDE hard disk/CD-ROM interface
0 = /dev/hdk Master: whole disk (or CD-ROM)
64 = /dev/hdl Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 58 char Hayes ESP serial card - alternate devices
+ 58 char Hayes ESP serial card - alternate devices
0 = /dev/cup0 Callout device for ttyP0
1 = /dev/cup1 Callout device for ttyP1
...
- 58 block Reserved for logical volume manager
+ 58 block Reserved for logical volume manager
- 59 char sf firewall package
+ 59 char sf firewall package
0 = /dev/firewall Communication with sf kernel module
- 59 block Generic PDA filesystem device
+ 59 block Generic PDA filesystem device
0 = /dev/pda0 First PDA device
1 = /dev/pda1 Second PDA device
...
@@ -1127,17 +1072,17 @@ Your cooperation is appreciated.
NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc
- 60-63 char LOCAL/EXPERIMENTAL USE
+ 60-63 char LOCAL/EXPERIMENTAL USE
- 60-63 block LOCAL/EXPERIMENTAL USE
+ 60-63 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
- 64 char ENskip kernel encryption package
+ 64 char ENskip kernel encryption package
0 = /dev/enskip Communication with ENskip kernel module
- 64 block Scramdisk/DriveCrypt encrypted devices
+ 64 block Scramdisk/DriveCrypt encrypted devices
0 = /dev/scramdisk/master Master node for ioctls
1 = /dev/scramdisk/1 First encrypted device
2 = /dev/scramdisk/2 Second encrypted device
@@ -1152,7 +1097,7 @@ Your cooperation is appreciated.
Requested by: andy@scramdisklinux.org
- 65 char Sundance "plink" Transputer boards (obsolete, unused)
+ 65 char Sundance "plink" Transputer boards (obsolete, unused)
0 = /dev/plink0 First plink device
1 = /dev/plink1 Second plink device
2 = /dev/plink2 Third plink device
@@ -1173,7 +1118,7 @@ Your cooperation is appreciated.
This is a commercial driver; contact James Howes
<jth@prosig.demon.co.uk> for information.
- 65 block SCSI disk devices (16-31)
+ 65 block SCSI disk devices (16-31)
0 = /dev/sdq 17th SCSI disk whole disk
16 = /dev/sdr 18th SCSI disk whole disk
32 = /dev/sds 19th SCSI disk whole disk
@@ -1184,12 +1129,12 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 66 char YARC PowerPC PCI coprocessor card
+ 66 char YARC PowerPC PCI coprocessor card
0 = /dev/yppcpci0 First YARC card
1 = /dev/yppcpci1 Second YARC card
...
- 66 block SCSI disk devices (32-47)
+ 66 block SCSI disk devices (32-47)
0 = /dev/sdag 33th SCSI disk whole disk
16 = /dev/sdah 34th SCSI disk whole disk
32 = /dev/sdai 35th SCSI disk whole disk
@@ -1200,12 +1145,12 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 67 char Coda network file system
+ 67 char Coda network file system
0 = /dev/cfs0 Coda cache manager
See http://www.coda.cs.cmu.edu for information about Coda.
- 67 block SCSI disk devices (48-63)
+ 67 block SCSI disk devices (48-63)
0 = /dev/sdaw 49th SCSI disk whole disk
16 = /dev/sdax 50th SCSI disk whole disk
32 = /dev/sday 51st SCSI disk whole disk
@@ -1216,7 +1161,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 68 char CAPI 2.0 interface
+ 68 char CAPI 2.0 interface
0 = /dev/capi20 Control device
1 = /dev/capi20.00 First CAPI 2.0 application
2 = /dev/capi20.01 Second CAPI 2.0 application
@@ -1226,7 +1171,7 @@ Your cooperation is appreciated.
ISDN CAPI 2.0 driver for use with CAPI 2.0
applications; currently supports the AVM B1 card.
- 68 block SCSI disk devices (64-79)
+ 68 block SCSI disk devices (64-79)
0 = /dev/sdbm 65th SCSI disk whole disk
16 = /dev/sdbn 66th SCSI disk whole disk
32 = /dev/sdbo 67th SCSI disk whole disk
@@ -1237,10 +1182,10 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 69 char MA16 numeric accelerator card
+ 69 char MA16 numeric accelerator card
0 = /dev/ma16 Board memory access
- 69 block SCSI disk devices (80-95)
+ 69 block SCSI disk devices (80-95)
0 = /dev/sdcc 81st SCSI disk whole disk
16 = /dev/sdcd 82nd SCSI disk whole disk
32 = /dev/sdce 83th SCSI disk whole disk
@@ -1251,7 +1196,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 70 char SpellCaster Protocol Services Interface
+ 70 char SpellCaster Protocol Services Interface
0 = /dev/apscfg Configuration interface
1 = /dev/apsauth Authentication interface
2 = /dev/apslog Logging interface
@@ -1260,7 +1205,7 @@ Your cooperation is appreciated.
65 = /dev/apsasync Async command interface
128 = /dev/apsmon Monitor interface
- 70 block SCSI disk devices (96-111)
+ 70 block SCSI disk devices (96-111)
0 = /dev/sdcs 97th SCSI disk whole disk
16 = /dev/sdct 98th SCSI disk whole disk
32 = /dev/sdcu 99th SCSI disk whole disk
@@ -1271,7 +1216,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 71 char Computone IntelliPort II serial card
+ 71 char Computone IntelliPort II serial card
0 = /dev/ttyF0 IntelliPort II board 0, port 0
1 = /dev/ttyF1 IntelliPort II board 0, port 1
...
@@ -1289,7 +1234,7 @@ Your cooperation is appreciated.
...
255 = /dev/ttyF255 IntelliPort II board 3, port 63
- 71 block SCSI disk devices (112-127)
+ 71 block SCSI disk devices (112-127)
0 = /dev/sddi 113th SCSI disk whole disk
16 = /dev/sddj 114th SCSI disk whole disk
32 = /dev/sddk 115th SCSI disk whole disk
@@ -1300,7 +1245,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 72 char Computone IntelliPort II serial card - alternate devices
+ 72 char Computone IntelliPort II serial card - alternate devices
0 = /dev/cuf0 Callout device for ttyF0
1 = /dev/cuf1 Callout device for ttyF1
...
@@ -1318,7 +1263,7 @@ Your cooperation is appreciated.
...
255 = /dev/cuf255 Callout device for ttyF255
- 72 block Compaq Intelligent Drive Array, first controller
+ 72 block Compaq Intelligent Drive Array, first controller
0 = /dev/ida/c0d0 First logical drive whole disk
16 = /dev/ida/c0d1 Second logical drive whole disk
...
@@ -1328,7 +1273,7 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 73 char Computone IntelliPort II serial card - control devices
+ 73 char Computone IntelliPort II serial card - control devices
0 = /dev/ip2ipl0 Loadware device for board 0
1 = /dev/ip2stat0 Status device for board 0
4 = /dev/ip2ipl1 Loadware device for board 1
@@ -1338,7 +1283,7 @@ Your cooperation is appreciated.
12 = /dev/ip2ipl3 Loadware device for board 3
13 = /dev/ip2stat3 Status device for board 3
- 73 block Compaq Intelligent Drive Array, second controller
+ 73 block Compaq Intelligent Drive Array, second controller
0 = /dev/ida/c1d0 First logical drive whole disk
16 = /dev/ida/c1d1 Second logical drive whole disk
...
@@ -1348,7 +1293,7 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 74 char SCI bridge
+ 74 char SCI bridge
0 = /dev/SCI/0 SCI device 0
1 = /dev/SCI/1 SCI device 1
...
@@ -1356,7 +1301,7 @@ Your cooperation is appreciated.
Currently for Dolphin Interconnect Solutions' PCI-SCI
bridge.
- 74 block Compaq Intelligent Drive Array, third controller
+ 74 block Compaq Intelligent Drive Array, third controller
0 = /dev/ida/c2d0 First logical drive whole disk
16 = /dev/ida/c2d1 Second logical drive whole disk
...
@@ -1366,14 +1311,14 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 75 char Specialix IO8+ serial card
+ 75 char Specialix IO8+ serial card
0 = /dev/ttyW0 First IO8+ port, first card
1 = /dev/ttyW1 Second IO8+ port, first card
...
8 = /dev/ttyW8 First IO8+ port, second card
...
- 75 block Compaq Intelligent Drive Array, fourth controller
+ 75 block Compaq Intelligent Drive Array, fourth controller
0 = /dev/ida/c3d0 First logical drive whole disk
16 = /dev/ida/c3d1 Second logical drive whole disk
...
@@ -1383,14 +1328,14 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 76 char Specialix IO8+ serial card - alternate devices
+ 76 char Specialix IO8+ serial card - alternate devices
0 = /dev/cuw0 Callout device for ttyW0
1 = /dev/cuw1 Callout device for ttyW1
...
8 = /dev/cuw8 Callout device for ttyW8
...
- 76 block Compaq Intelligent Drive Array, fifth controller
+ 76 block Compaq Intelligent Drive Array, fifth controller
0 = /dev/ida/c4d0 First logical drive whole disk
16 = /dev/ida/c4d1 Second logical drive whole disk
...
@@ -1401,10 +1346,10 @@ Your cooperation is appreciated.
partitions is 15.
- 77 char ComScire Quantum Noise Generator
+ 77 char ComScire Quantum Noise Generator
0 = /dev/qng ComScire Quantum Noise Generator
- 77 block Compaq Intelligent Drive Array, sixth controller
+ 77 block Compaq Intelligent Drive Array, sixth controller
0 = /dev/ida/c5d0 First logical drive whole disk
16 = /dev/ida/c5d1 Second logical drive whole disk
...
@@ -1414,12 +1359,12 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 78 char PAM Software's multimodem boards
+ 78 char PAM Software's multimodem boards
0 = /dev/ttyM0 First PAM modem
1 = /dev/ttyM1 Second PAM modem
...
- 78 block Compaq Intelligent Drive Array, seventh controller
+ 78 block Compaq Intelligent Drive Array, seventh controller
0 = /dev/ida/c6d0 First logical drive whole disk
16 = /dev/ida/c6d1 Second logical drive whole disk
...
@@ -1429,12 +1374,12 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 79 char PAM Software's multimodem boards - alternate devices
+ 79 char PAM Software's multimodem boards - alternate devices
0 = /dev/cum0 Callout device for ttyM0
1 = /dev/cum1 Callout device for ttyM1
...
- 79 block Compaq Intelligent Drive Array, eighth controller
+ 79 block Compaq Intelligent Drive Array, eighth controller
0 = /dev/ida/c7d0 First logical drive whole disk
16 = /dev/ida/c7d1 Second logical drive whole disk
...
@@ -1444,10 +1389,10 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
- 80 char Photometrics AT200 CCD camera
+ 80 char Photometrics AT200 CCD camera
0 = /dev/at200 Photometrics AT200 CCD camera
- 80 block I2O hard disk
+ 80 block I2O hard disk
0 = /dev/i2o/hda First I2O hard disk, whole disk
16 = /dev/i2o/hdb Second I2O hard disk, whole disk
...
@@ -1457,7 +1402,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 81 char video4linux
+ 81 char video4linux
0 = /dev/video0 Video capture/overlay device
...
63 = /dev/video63 Video capture/overlay device
@@ -1475,7 +1420,7 @@ Your cooperation is appreciated.
CONFIG_VIDEO_FIXED_MINOR_RANGES (default n)
configuration option is set.
- 81 block I2O hard disk
+ 81 block I2O hard disk
0 = /dev/i2o/hdq 17th I2O hard disk, whole disk
16 = /dev/i2o/hdr 18th I2O hard disk, whole disk
...
@@ -1485,7 +1430,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 82 char WiNRADiO communications receiver card
+ 82 char WiNRADiO communications receiver card
0 = /dev/winradio0 First WiNRADiO card
1 = /dev/winradio1 Second WiNRADiO card
...
@@ -1493,7 +1438,7 @@ Your cooperation is appreciated.
The driver and documentation may be obtained from
http://www.winradio.com/
- 82 block I2O hard disk
+ 82 block I2O hard disk
0 = /dev/i2o/hdag 33rd I2O hard disk, whole disk
16 = /dev/i2o/hdah 34th I2O hard disk, whole disk
...
@@ -1503,14 +1448,14 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 83 char Matrox mga_vid video driver
- 0 = /dev/mga_vid0 1st video card
+ 83 char Matrox mga_vid video driver
+ 0 = /dev/mga_vid0 1st video card
1 = /dev/mga_vid1 2nd video card
2 = /dev/mga_vid2 3rd video card
...
- 15 = /dev/mga_vid15 16th video card
+ 15 = /dev/mga_vid15 16th video card
- 83 block I2O hard disk
+ 83 block I2O hard disk
0 = /dev/i2o/hdaw 49th I2O hard disk, whole disk
16 = /dev/i2o/hdax 50th I2O hard disk, whole disk
...
@@ -1520,11 +1465,11 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 84 char Ikon 1011[57] Versatec Greensheet Interface
+ 84 char Ikon 1011[57] Versatec Greensheet Interface
0 = /dev/ihcp0 First Greensheet port
1 = /dev/ihcp1 Second Greensheet port
- 84 block I2O hard disk
+ 84 block I2O hard disk
0 = /dev/i2o/hdbm 65th I2O hard disk, whole disk
16 = /dev/i2o/hdbn 66th I2O hard disk, whole disk
...
@@ -1534,13 +1479,13 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 85 char Linux/SGI shared memory input queue
+ 85 char Linux/SGI shared memory input queue
0 = /dev/shmiq Master shared input queue
1 = /dev/qcntl0 First device pushed
2 = /dev/qcntl1 Second device pushed
...
- 85 block I2O hard disk
+ 85 block I2O hard disk
0 = /dev/i2o/hdcc 81st I2O hard disk, whole disk
16 = /dev/i2o/hdcd 82nd I2O hard disk, whole disk
...
@@ -1550,12 +1495,12 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 86 char SCSI media changer
+ 86 char SCSI media changer
0 = /dev/sch0 First SCSI media changer
1 = /dev/sch1 Second SCSI media changer
...
- 86 block I2O hard disk
+ 86 block I2O hard disk
0 = /dev/i2o/hdcs 97th I2O hard disk, whole disk
16 = /dev/i2o/hdct 98th I2O hard disk, whole disk
...
@@ -1565,12 +1510,12 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 87 char Sony Control-A1 stereo control bus
+ 87 char Sony Control-A1 stereo control bus
0 = /dev/controla0 First device on chain
1 = /dev/controla1 Second device on chain
...
- 87 block I2O hard disk
+ 87 block I2O hard disk
0 = /dev/i2o/hddi 113rd I2O hard disk, whole disk
16 = /dev/i2o/hddj 114th I2O hard disk, whole disk
...
@@ -1580,59 +1525,59 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 88 char COMX synchronous serial card
+ 88 char COMX synchronous serial card
0 = /dev/comx0 COMX channel 0
1 = /dev/comx1 COMX channel 1
...
- 88 block Seventh IDE hard disk/CD-ROM interface
+ 88 block Seventh IDE hard disk/CD-ROM interface
0 = /dev/hdm Master: whole disk (or CD-ROM)
64 = /dev/hdn Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 89 char I2C bus interface
+ 89 char I2C bus interface
0 = /dev/i2c-0 First I2C adapter
1 = /dev/i2c-1 Second I2C adapter
...
- 89 block Eighth IDE hard disk/CD-ROM interface
+ 89 block Eighth IDE hard disk/CD-ROM interface
0 = /dev/hdo Master: whole disk (or CD-ROM)
64 = /dev/hdp Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 90 char Memory Technology Device (RAM, ROM, Flash)
+ 90 char Memory Technology Device (RAM, ROM, Flash)
0 = /dev/mtd0 First MTD (rw)
1 = /dev/mtdr0 First MTD (ro)
...
30 = /dev/mtd15 16th MTD (rw)
31 = /dev/mtdr15 16th MTD (ro)
- 90 block Ninth IDE hard disk/CD-ROM interface
+ 90 block Ninth IDE hard disk/CD-ROM interface
0 = /dev/hdq Master: whole disk (or CD-ROM)
64 = /dev/hdr Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 91 char CAN-Bus devices
+ 91 char CAN-Bus devices
0 = /dev/can0 First CAN-Bus controller
1 = /dev/can1 Second CAN-Bus controller
...
- 91 block Tenth IDE hard disk/CD-ROM interface
+ 91 block Tenth IDE hard disk/CD-ROM interface
0 = /dev/hds Master: whole disk (or CD-ROM)
64 = /dev/hdt Slave: whole disk (or CD-ROM)
Partitions are handled the same way as for the first
interface (see major number 3).
- 92 char Reserved for ith Kommunikationstechnik MIC ISDN card
+ 92 char Reserved for ith Kommunikationstechnik MIC ISDN card
- 92 block PPDD encrypted disk driver
+ 92 block PPDD encrypted disk driver
0 = /dev/ppdd0 First encrypted disk
1 = /dev/ppdd1 Second encrypted disk
...
@@ -1641,35 +1586,35 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
- 93 char
+ 93 char
- 93 block NAND Flash Translation Layer filesystem
+ 93 block NAND Flash Translation Layer filesystem
0 = /dev/nftla First NFTL layer
16 = /dev/nftlb Second NFTL layer
...
240 = /dev/nftlp 16th NTFL layer
- 94 char
+ 94 char
- 94 block IBM S/390 DASD block storage
- 0 = /dev/dasda First DASD device, major
- 1 = /dev/dasda1 First DASD device, block 1
- 2 = /dev/dasda2 First DASD device, block 2
- 3 = /dev/dasda3 First DASD device, block 3
- 4 = /dev/dasdb Second DASD device, major
- 5 = /dev/dasdb1 Second DASD device, block 1
- 6 = /dev/dasdb2 Second DASD device, block 2
- 7 = /dev/dasdb3 Second DASD device, block 3
+ 94 block IBM S/390 DASD block storage
+ 0 = /dev/dasda First DASD device, major
+ 1 = /dev/dasda1 First DASD device, block 1
+ 2 = /dev/dasda2 First DASD device, block 2
+ 3 = /dev/dasda3 First DASD device, block 3
+ 4 = /dev/dasdb Second DASD device, major
+ 5 = /dev/dasdb1 Second DASD device, block 1
+ 6 = /dev/dasdb2 Second DASD device, block 2
+ 7 = /dev/dasdb3 Second DASD device, block 3
...
- 95 char IP filter
+ 95 char IP filter
0 = /dev/ipl Filter control device/log file
1 = /dev/ipnat NAT control device/log file
2 = /dev/ipstate State information log file
3 = /dev/ipauth Authentication control device/log file
...
- 96 char Parallel port ATAPI tape devices
+ 96 char Parallel port ATAPI tape devices
0 = /dev/pt0 First parallel port ATAPI tape
1 = /dev/pt1 Second parallel port ATAPI tape
...
@@ -1677,13 +1622,13 @@ Your cooperation is appreciated.
129 = /dev/npt1 Second p.p. ATAPI tape, no rewind
...
- 96 block Inverse NAND Flash Translation Layer
+ 96 block Inverse NAND Flash Translation Layer
0 = /dev/inftla First INFTL layer
16 = /dev/inftlb Second INFTL layer
...
240 = /dev/inftlp 16th INTFL layer
- 97 char Parallel port generic ATAPI interface
+ 97 char Parallel port generic ATAPI interface
0 = /dev/pg0 First parallel port ATAPI device
1 = /dev/pg1 Second parallel port ATAPI device
2 = /dev/pg2 Third parallel port ATAPI device
@@ -1692,14 +1637,14 @@ Your cooperation is appreciated.
These devices support the same API as the generic SCSI
devices.
- 98 char Control and Measurement Device (comedi)
+ 98 char Control and Measurement Device (comedi)
0 = /dev/comedi0 First comedi device
1 = /dev/comedi1 Second comedi device
...
See http://stm.lbl.gov/comedi.
- 98 block User-mode virtual block device
+ 98 block User-mode virtual block device
0 = /dev/ubda First user-mode block device
16 = /dev/udbb Second user-mode block device
...
@@ -1710,26 +1655,26 @@ Your cooperation is appreciated.
This device is used by the user-mode virtual kernel port.
- 99 char Raw parallel ports
+ 99 char Raw parallel ports
0 = /dev/parport0 First parallel port
1 = /dev/parport1 Second parallel port
...
- 99 block JavaStation flash disk
+ 99 block JavaStation flash disk
0 = /dev/jsfd JavaStation flash disk
-100 char Telephony for Linux
+ 100 char Telephony for Linux
0 = /dev/phone0 First telephony device
1 = /dev/phone1 Second telephony device
...
-101 char Motorola DSP 56xxx board
+ 101 char Motorola DSP 56xxx board
0 = /dev/mdspstat Status information
1 = /dev/mdsp1 First DSP board I/O controls
...
16 = /dev/mdsp16 16th DSP board I/O controls
-101 block AMI HyperDisk RAID controller
+ 101 block AMI HyperDisk RAID controller
0 = /dev/amiraid/ar0 First array whole disk
16 = /dev/amiraid/ar1 Second array whole disk
...
@@ -1742,9 +1687,9 @@ Your cooperation is appreciated.
...
15 = /dev/amiraid/ar?p15 15th partition
-102 char
+ 102 char
-102 block Compressed block device
+ 102 block Compressed block device
0 = /dev/cbd/a First compressed block device, whole device
16 = /dev/cbd/b Second compressed block device, whole device
...
@@ -1754,7 +1699,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
-103 char Arla network file system
+ 103 char Arla network file system
0 = /dev/nnpfs0 First NNPFS device
1 = /dev/nnpfs1 Second NNPFS device
@@ -1765,12 +1710,12 @@ Your cooperation is appreciated.
write to <arla-drinkers@stacken.kth.se> or see
http://www.stacken.kth.se/project/arla/
-103 block Audit device
+ 103 block Audit device
0 = /dev/audit Audit device
-104 char Flash BIOS support
+ 104 char Flash BIOS support
-104 block Compaq Next Generation Drive Array, first controller
+ 104 block Compaq Next Generation Drive Array, first controller
0 = /dev/cciss/c0d0 First logical drive, whole disk
16 = /dev/cciss/c0d1 Second logical drive, whole disk
...
@@ -1780,12 +1725,12 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-105 char Comtrol VS-1000 serial controller
+ 105 char Comtrol VS-1000 serial controller
0 = /dev/ttyV0 First VS-1000 port
1 = /dev/ttyV1 Second VS-1000 port
...
-105 block Compaq Next Generation Drive Array, second controller
+ 105 block Compaq Next Generation Drive Array, second controller
0 = /dev/cciss/c1d0 First logical drive, whole disk
16 = /dev/cciss/c1d1 Second logical drive, whole disk
...
@@ -1795,12 +1740,12 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-106 char Comtrol VS-1000 serial controller - alternate devices
+ 106 char Comtrol VS-1000 serial controller - alternate devices
0 = /dev/cuv0 First VS-1000 port
1 = /dev/cuv1 Second VS-1000 port
...
-106 block Compaq Next Generation Drive Array, third controller
+ 106 block Compaq Next Generation Drive Array, third controller
0 = /dev/cciss/c2d0 First logical drive, whole disk
16 = /dev/cciss/c2d1 Second logical drive, whole disk
...
@@ -1810,10 +1755,10 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-107 char 3Dfx Voodoo Graphics device
+ 107 char 3Dfx Voodoo Graphics device
0 = /dev/3dfx Primary 3Dfx graphics device
-107 block Compaq Next Generation Drive Array, fourth controller
+ 107 block Compaq Next Generation Drive Array, fourth controller
0 = /dev/cciss/c3d0 First logical drive, whole disk
16 = /dev/cciss/c3d1 Second logical drive, whole disk
...
@@ -1823,10 +1768,10 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-108 char Device independent PPP interface
+ 108 char Device independent PPP interface
0 = /dev/ppp Device independent PPP interface
-108 block Compaq Next Generation Drive Array, fifth controller
+ 108 block Compaq Next Generation Drive Array, fifth controller
0 = /dev/cciss/c4d0 First logical drive, whole disk
16 = /dev/cciss/c4d1 Second logical drive, whole disk
...
@@ -1836,9 +1781,9 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-109 char Reserved for logical volume manager
+ 109 char Reserved for logical volume manager
-109 block Compaq Next Generation Drive Array, sixth controller
+ 109 block Compaq Next Generation Drive Array, sixth controller
0 = /dev/cciss/c5d0 First logical drive, whole disk
16 = /dev/cciss/c5d1 Second logical drive, whole disk
...
@@ -1848,12 +1793,12 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-110 char miroMEDIA Surround board
+ 110 char miroMEDIA Surround board
0 = /dev/srnd0 First miroMEDIA Surround board
1 = /dev/srnd1 Second miroMEDIA Surround board
...
-110 block Compaq Next Generation Drive Array, seventh controller
+ 110 block Compaq Next Generation Drive Array, seventh controller
0 = /dev/cciss/c6d0 First logical drive, whole disk
16 = /dev/cciss/c6d1 Second logical drive, whole disk
...
@@ -1863,9 +1808,9 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-111 char
+ 111 char
-111 block Compaq Next Generation Drive Array, eighth controller
+ 111 block Compaq Next Generation Drive Array, eighth controller
0 = /dev/cciss/c7d0 First logical drive, whole disk
16 = /dev/cciss/c7d1 Second logical drive, whole disk
...
@@ -1875,7 +1820,7 @@ Your cooperation is appreciated.
DAC960 (see major number 48) except that the limit on
partitions is 15.
-112 char ISI serial card
+ 112 char ISI serial card
0 = /dev/ttyM0 First ISI port
1 = /dev/ttyM1 Second ISI port
...
@@ -1883,7 +1828,7 @@ Your cooperation is appreciated.
There is currently a device-naming conflict between
these and PAM multimodems (major 78).
-112 block IBM iSeries virtual disk
+ 112 block IBM iSeries virtual disk
0 = /dev/iseries/vda First virtual disk, whole disk
8 = /dev/iseries/vdb Second virtual disk, whole disk
...
@@ -1896,17 +1841,17 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 7.
-113 char ISI serial card - alternate devices
+ 113 char ISI serial card - alternate devices
0 = /dev/cum0 Callout device for ttyM0
1 = /dev/cum1 Callout device for ttyM1
...
-113 block IBM iSeries virtual CD-ROM
+ 113 block IBM iSeries virtual CD-ROM
0 = /dev/iseries/vcda First virtual CD-ROM
1 = /dev/iseries/vcdb Second virtual CD-ROM
...
-114 char Picture Elements ISE board
+ 114 char Picture Elements ISE board
0 = /dev/ise0 First ISE board
1 = /dev/ise1 Second ISE board
...
@@ -1919,24 +1864,24 @@ Your cooperation is appreciated.
I/O access to the board, the /dev/isex0 nodes command
nodes used to control the board.
-114 block IDE BIOS powered software RAID interfaces such as the
- Promise Fastrak
+ 114 block IDE BIOS powered software RAID interfaces such as the
+ Promise Fastrak
- 0 = /dev/ataraid/d0
- 1 = /dev/ataraid/d0p1
- 2 = /dev/ataraid/d0p2
- ...
- 16 = /dev/ataraid/d1
- 17 = /dev/ataraid/d1p1
- 18 = /dev/ataraid/d1p2
- ...
- 255 = /dev/ataraid/d15p15
+ 0 = /dev/ataraid/d0
+ 1 = /dev/ataraid/d0p1
+ 2 = /dev/ataraid/d0p2
+ ...
+ 16 = /dev/ataraid/d1
+ 17 = /dev/ataraid/d1p1
+ 18 = /dev/ataraid/d1p2
+ ...
+ 255 = /dev/ataraid/d15p15
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-115 char TI link cable devices (115 was formerly the console driver speaker)
+ 115 char TI link cable devices (115 was formerly the console driver speaker)
0 = /dev/tipar0 Parallel cable on first parallel port
...
7 = /dev/tipar7 Parallel cable on seventh parallel port
@@ -1949,28 +1894,28 @@ Your cooperation is appreciated.
...
47 = /dev/tiusb31 32nd USB cable
-115 block NetWare (NWFS) Devices (0-255)
+ 115 block NetWare (NWFS) Devices (0-255)
- The NWFS (NetWare) devices are used to present a
- collection of NetWare Mirror Groups or NetWare
- Partitions as a logical storage segment for
- use in mounting NetWare volumes. A maximum of
- 256 NetWare volumes can be supported in a single
- machine.
+ The NWFS (NetWare) devices are used to present a
+ collection of NetWare Mirror Groups or NetWare
+ Partitions as a logical storage segment for
+ use in mounting NetWare volumes. A maximum of
+ 256 NetWare volumes can be supported in a single
+ machine.
- http://cgfa.telepac.pt/ftp2/kernel.org/linux/kernel/people/jmerkey/nwfs/
+ http://cgfa.telepac.pt/ftp2/kernel.org/linux/kernel/people/jmerkey/nwfs/
- 0 = /dev/nwfs/v0 First NetWare (NWFS) Logical Volume
- 1 = /dev/nwfs/v1 Second NetWare (NWFS) Logical Volume
- 2 = /dev/nwfs/v2 Third NetWare (NWFS) Logical Volume
- ...
- 255 = /dev/nwfs/v255 Last NetWare (NWFS) Logical Volume
+ 0 = /dev/nwfs/v0 First NetWare (NWFS) Logical Volume
+ 1 = /dev/nwfs/v1 Second NetWare (NWFS) Logical Volume
+ 2 = /dev/nwfs/v2 Third NetWare (NWFS) Logical Volume
+ ...
+ 255 = /dev/nwfs/v255 Last NetWare (NWFS) Logical Volume
-116 char Advanced Linux Sound Driver (ALSA)
+ 116 char Advanced Linux Sound Driver (ALSA)
-116 block MicroMemory battery backed RAM adapter (NVRAM)
- Supports 16 boards, 15 partitions each.
- Requested by neilb at cse.unsw.edu.au.
+ 116 block MicroMemory battery backed RAM adapter (NVRAM)
+ Supports 16 boards, 15 partitions each.
+ Requested by neilb at cse.unsw.edu.au.
0 = /dev/umem/d0 Whole of first board
1 = /dev/umem/d0p1 First partition of first board
@@ -1982,7 +1927,7 @@ Your cooperation is appreciated.
...
255= /dev/umem/d15p15 15th partition of 16th board.
-117 char COSA/SRP synchronous serial card
+ 117 char COSA/SRP synchronous serial card
0 = /dev/cosa0c0 1st board, 1st channel
1 = /dev/cosa0c1 1st board, 2nd channel
...
@@ -1990,147 +1935,147 @@ Your cooperation is appreciated.
17 = /dev/cosa1c1 2nd board, 2nd channel
...
-117 block Enterprise Volume Management System (EVMS)
+ 117 block Enterprise Volume Management System (EVMS)
- The EVMS driver uses a layered, plug-in model to provide
- unparalleled flexibility and extensibility in managing
- storage. This allows for easy expansion or customization
- of various levels of volume management. Requested by
- Mark Peloquin (peloquin at us.ibm.com).
+ The EVMS driver uses a layered, plug-in model to provide
+ unparalleled flexibility and extensibility in managing
+ storage. This allows for easy expansion or customization
+ of various levels of volume management. Requested by
+ Mark Peloquin (peloquin at us.ibm.com).
- Note: EVMS populates and manages all the devnodes in
- /dev/evms.
+ Note: EVMS populates and manages all the devnodes in
+ /dev/evms.
- http://sf.net/projects/evms
+ http://sf.net/projects/evms
- 0 = /dev/evms/block_device EVMS block device
- 1 = /dev/evms/legacyname1 First EVMS legacy device
- 2 = /dev/evms/legacyname2 Second EVMS legacy device
- ...
- Both ranges can grow (down or up) until they meet.
- ...
- 254 = /dev/evms/EVMSname2 Second EVMS native device
- 255 = /dev/evms/EVMSname1 First EVMS native device
+ 0 = /dev/evms/block_device EVMS block device
+ 1 = /dev/evms/legacyname1 First EVMS legacy device
+ 2 = /dev/evms/legacyname2 Second EVMS legacy device
+ ...
+ Both ranges can grow (down or up) until they meet.
+ ...
+ 254 = /dev/evms/EVMSname2 Second EVMS native device
+ 255 = /dev/evms/EVMSname1 First EVMS native device
- Note: legacyname(s) are derived from the normal legacy
- device names. For example, /dev/hda5 would become
- /dev/evms/hda5.
+ Note: legacyname(s) are derived from the normal legacy
+ device names. For example, /dev/hda5 would become
+ /dev/evms/hda5.
-118 char IBM Cryptographic Accelerator
+ 118 char IBM Cryptographic Accelerator
0 = /dev/ica Virtual interface to all IBM Crypto Accelerators
1 = /dev/ica0 IBMCA Device 0
2 = /dev/ica1 IBMCA Device 1
...
-119 char VMware virtual network control
+ 119 char VMware virtual network control
0 = /dev/vnet0 1st virtual network
1 = /dev/vnet1 2nd virtual network
...
-120-127 char LOCAL/EXPERIMENTAL USE
+ 120-127 char LOCAL/EXPERIMENTAL USE
-120-127 block LOCAL/EXPERIMENTAL USE
+ 120-127 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
-128-135 char Unix98 PTY masters
+ 128-135 char Unix98 PTY masters
These devices should not have corresponding device
nodes; instead they should be accessed through the
/dev/ptmx cloning interface.
-128 block SCSI disk devices (128-143)
- 0 = /dev/sddy 129th SCSI disk whole disk
- 16 = /dev/sddz 130th SCSI disk whole disk
- 32 = /dev/sdea 131th SCSI disk whole disk
- ...
- 240 = /dev/sden 144th SCSI disk whole disk
+ 128 block SCSI disk devices (128-143)
+ 0 = /dev/sddy 129th SCSI disk whole disk
+ 16 = /dev/sddz 130th SCSI disk whole disk
+ 32 = /dev/sdea 131th SCSI disk whole disk
+ ...
+ 240 = /dev/sden 144th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-129 block SCSI disk devices (144-159)
- 0 = /dev/sdeo 145th SCSI disk whole disk
- 16 = /dev/sdep 146th SCSI disk whole disk
- 32 = /dev/sdeq 147th SCSI disk whole disk
- ...
- 240 = /dev/sdfd 160th SCSI disk whole disk
+ 129 block SCSI disk devices (144-159)
+ 0 = /dev/sdeo 145th SCSI disk whole disk
+ 16 = /dev/sdep 146th SCSI disk whole disk
+ 32 = /dev/sdeq 147th SCSI disk whole disk
+ ...
+ 240 = /dev/sdfd 160th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-130 char (Misc devices)
+ 130 char (Misc devices)
-130 block SCSI disk devices (160-175)
- 0 = /dev/sdfe 161st SCSI disk whole disk
- 16 = /dev/sdff 162nd SCSI disk whole disk
- 32 = /dev/sdfg 163rd SCSI disk whole disk
- ...
- 240 = /dev/sdft 176th SCSI disk whole disk
+ 130 block SCSI disk devices (160-175)
+ 0 = /dev/sdfe 161st SCSI disk whole disk
+ 16 = /dev/sdff 162nd SCSI disk whole disk
+ 32 = /dev/sdfg 163rd SCSI disk whole disk
+ ...
+ 240 = /dev/sdft 176th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-131 block SCSI disk devices (176-191)
- 0 = /dev/sdfu 177th SCSI disk whole disk
- 16 = /dev/sdfv 178th SCSI disk whole disk
- 32 = /dev/sdfw 179th SCSI disk whole disk
- ...
- 240 = /dev/sdgj 192nd SCSI disk whole disk
+ 131 block SCSI disk devices (176-191)
+ 0 = /dev/sdfu 177th SCSI disk whole disk
+ 16 = /dev/sdfv 178th SCSI disk whole disk
+ 32 = /dev/sdfw 179th SCSI disk whole disk
+ ...
+ 240 = /dev/sdgj 192nd SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-132 block SCSI disk devices (192-207)
- 0 = /dev/sdgk 193rd SCSI disk whole disk
- 16 = /dev/sdgl 194th SCSI disk whole disk
- 32 = /dev/sdgm 195th SCSI disk whole disk
- ...
- 240 = /dev/sdgz 208th SCSI disk whole disk
+ 132 block SCSI disk devices (192-207)
+ 0 = /dev/sdgk 193rd SCSI disk whole disk
+ 16 = /dev/sdgl 194th SCSI disk whole disk
+ 32 = /dev/sdgm 195th SCSI disk whole disk
+ ...
+ 240 = /dev/sdgz 208th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-133 block SCSI disk devices (208-223)
- 0 = /dev/sdha 209th SCSI disk whole disk
- 16 = /dev/sdhb 210th SCSI disk whole disk
- 32 = /dev/sdhc 211th SCSI disk whole disk
- ...
- 240 = /dev/sdhp 224th SCSI disk whole disk
+ 133 block SCSI disk devices (208-223)
+ 0 = /dev/sdha 209th SCSI disk whole disk
+ 16 = /dev/sdhb 210th SCSI disk whole disk
+ 32 = /dev/sdhc 211th SCSI disk whole disk
+ ...
+ 240 = /dev/sdhp 224th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-134 block SCSI disk devices (224-239)
- 0 = /dev/sdhq 225th SCSI disk whole disk
- 16 = /dev/sdhr 226th SCSI disk whole disk
- 32 = /dev/sdhs 227th SCSI disk whole disk
- ...
- 240 = /dev/sdif 240th SCSI disk whole disk
+ 134 block SCSI disk devices (224-239)
+ 0 = /dev/sdhq 225th SCSI disk whole disk
+ 16 = /dev/sdhr 226th SCSI disk whole disk
+ 32 = /dev/sdhs 227th SCSI disk whole disk
+ ...
+ 240 = /dev/sdif 240th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-135 block SCSI disk devices (240-255)
- 0 = /dev/sdig 241st SCSI disk whole disk
- 16 = /dev/sdih 242nd SCSI disk whole disk
- 32 = /dev/sdih 243rd SCSI disk whole disk
- ...
- 240 = /dev/sdiv 256th SCSI disk whole disk
+ 135 block SCSI disk devices (240-255)
+ 0 = /dev/sdig 241st SCSI disk whole disk
+ 16 = /dev/sdih 242nd SCSI disk whole disk
+ 32 = /dev/sdih 243rd SCSI disk whole disk
+ ...
+ 240 = /dev/sdiv 256th SCSI disk whole disk
Partitions are handled in the same way as for IDE
disks (see major number 3) except that the limit on
partitions is 15.
-136-143 char Unix98 PTY slaves
+ 136-143 char Unix98 PTY slaves
0 = /dev/pts/0 First Unix98 pseudo-TTY
1 = /dev/pts/1 Second Unix98 pseudo-TTY
...
@@ -2142,7 +2087,7 @@ Your cooperation is appreciated.
*most* distributions the appropriate options are
"mode=0620,gid=<gid of the "tty" group>".)
-136 block Mylex DAC960 PCI RAID controller; ninth controller
+ 136 block Mylex DAC960 PCI RAID controller; ninth controller
0 = /dev/rd/c8d0 First disk, whole disk
8 = /dev/rd/c8d1 Second disk, whole disk
...
@@ -2150,7 +2095,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-137 block Mylex DAC960 PCI RAID controller; tenth controller
+ 137 block Mylex DAC960 PCI RAID controller; tenth controller
0 = /dev/rd/c9d0 First disk, whole disk
8 = /dev/rd/c9d1 Second disk, whole disk
...
@@ -2158,7 +2103,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-138 block Mylex DAC960 PCI RAID controller; eleventh controller
+ 138 block Mylex DAC960 PCI RAID controller; eleventh controller
0 = /dev/rd/c10d0 First disk, whole disk
8 = /dev/rd/c10d1 Second disk, whole disk
...
@@ -2166,7 +2111,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-139 block Mylex DAC960 PCI RAID controller; twelfth controller
+ 139 block Mylex DAC960 PCI RAID controller; twelfth controller
0 = /dev/rd/c11d0 First disk, whole disk
8 = /dev/rd/c11d1 Second disk, whole disk
...
@@ -2174,7 +2119,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-140 block Mylex DAC960 PCI RAID controller; thirteenth controller
+ 140 block Mylex DAC960 PCI RAID controller; thirteenth controller
0 = /dev/rd/c12d0 First disk, whole disk
8 = /dev/rd/c12d1 Second disk, whole disk
...
@@ -2182,7 +2127,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-141 block Mylex DAC960 PCI RAID controller; fourteenth controller
+ 141 block Mylex DAC960 PCI RAID controller; fourteenth controller
0 = /dev/rd/c13d0 First disk, whole disk
8 = /dev/rd/c13d1 Second disk, whole disk
...
@@ -2190,7 +2135,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-142 block Mylex DAC960 PCI RAID controller; fifteenth controller
+ 142 block Mylex DAC960 PCI RAID controller; fifteenth controller
0 = /dev/rd/c14d0 First disk, whole disk
8 = /dev/rd/c14d1 Second disk, whole disk
...
@@ -2198,7 +2143,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-143 block Mylex DAC960 PCI RAID controller; sixteenth controller
+ 143 block Mylex DAC960 PCI RAID controller; sixteenth controller
0 = /dev/rd/c15d0 First disk, whole disk
8 = /dev/rd/c15d1 Second disk, whole disk
...
@@ -2206,7 +2151,7 @@ Your cooperation is appreciated.
Partitions are handled as for major 48.
-144 char Encapsulated PPP
+ 144 char Encapsulated PPP
0 = /dev/pppox0 First PPP over Ethernet
...
63 = /dev/pppox63 64th PPP over Ethernet
@@ -2216,11 +2161,11 @@ Your cooperation is appreciated.
The SST 5136-DN DeviceNet interface driver has been
relocated to major 183 due to an unfortunate conflict.
-144 block Expansion Area #1 for more non-device (e.g. NFS) mounts
+ 144 block Expansion Area #1 for more non-device (e.g. NFS) mounts
0 = mounted device 256
255 = mounted device 511
-145 char SAM9407-based soundcard
+ 145 char SAM9407-based soundcard
0 = /dev/sam0_mixer
1 = /dev/sam0_sequencer
2 = /dev/sam0_midi00
@@ -2241,66 +2186,66 @@ Your cooperation is appreciated.
addons, which are sam9407 specific. OSS can be
operated simultaneously, taking care of the codec.
-145 block Expansion Area #2 for more non-device (e.g. NFS) mounts
+ 145 block Expansion Area #2 for more non-device (e.g. NFS) mounts
0 = mounted device 512
255 = mounted device 767
-146 char SYSTRAM SCRAMNet mirrored-memory network
+ 146 char SYSTRAM SCRAMNet mirrored-memory network
0 = /dev/scramnet0 First SCRAMNet device
1 = /dev/scramnet1 Second SCRAMNet device
...
-146 block Expansion Area #3 for more non-device (e.g. NFS) mounts
+ 146 block Expansion Area #3 for more non-device (e.g. NFS) mounts
0 = mounted device 768
255 = mounted device 1023
-147 char Aureal Semiconductor Vortex Audio device
+ 147 char Aureal Semiconductor Vortex Audio device
0 = /dev/aureal0 First Aureal Vortex
1 = /dev/aureal1 Second Aureal Vortex
...
-147 block Distributed Replicated Block Device (DRBD)
+ 147 block Distributed Replicated Block Device (DRBD)
0 = /dev/drbd0 First DRBD device
1 = /dev/drbd1 Second DRBD device
...
-148 char Technology Concepts serial card
+ 148 char Technology Concepts serial card
0 = /dev/ttyT0 First TCL port
1 = /dev/ttyT1 Second TCL port
...
-149 char Technology Concepts serial card - alternate devices
+ 149 char Technology Concepts serial card - alternate devices
0 = /dev/cut0 Callout device for ttyT0
1 = /dev/cut0 Callout device for ttyT1
...
-150 char Real-Time Linux FIFOs
+ 150 char Real-Time Linux FIFOs
0 = /dev/rtf0 First RTLinux FIFO
1 = /dev/rtf1 Second RTLinux FIFO
...
-151 char DPT I2O SmartRaid V controller
+ 151 char DPT I2O SmartRaid V controller
0 = /dev/dpti0 First DPT I2O adapter
1 = /dev/dpti1 Second DPT I2O adapter
...
-152 char EtherDrive Control Device
+ 152 char EtherDrive Control Device
0 = /dev/etherd/ctl Connect/Disconnect an EtherDrive
1 = /dev/etherd/err Monitor errors
2 = /dev/etherd/raw Raw AoE packet monitor
-152 block EtherDrive Block Devices
+ 152 block EtherDrive Block Devices
0 = /dev/etherd/0 EtherDrive 0
...
255 = /dev/etherd/255 EtherDrive 255
-153 char SPI Bus Interface (sometimes referred to as MicroWire)
+ 153 char SPI Bus Interface (sometimes referred to as MicroWire)
0 = /dev/spi0 First SPI device on the bus
1 = /dev/spi1 Second SPI device on the bus
...
15 = /dev/spi15 Sixteenth SPI device on the bus
-153 block Enhanced Metadisk RAID (EMD) storage units
+ 153 block Enhanced Metadisk RAID (EMD) storage units
0 = /dev/emd/0 First unit
1 = /dev/emd/0p1 Partition 1 on First unit
2 = /dev/emd/0p2 Partition 2 on First unit
@@ -2316,41 +2261,41 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 15.
-154 char Specialix RIO serial card
+ 154 char Specialix RIO serial card
0 = /dev/ttySR0 First RIO port
...
255 = /dev/ttySR255 256th RIO port
-155 char Specialix RIO serial card - alternate devices
+ 155 char Specialix RIO serial card - alternate devices
0 = /dev/cusr0 Callout device for ttySR0
...
255 = /dev/cusr255 Callout device for ttySR255
-156 char Specialix RIO serial card
+ 156 char Specialix RIO serial card
0 = /dev/ttySR256 257th RIO port
...
255 = /dev/ttySR511 512th RIO port
-157 char Specialix RIO serial card - alternate devices
+ 157 char Specialix RIO serial card - alternate devices
0 = /dev/cusr256 Callout device for ttySR256
...
255 = /dev/cusr511 Callout device for ttySR511
-158 char Dialogic GammaLink fax driver
+ 158 char Dialogic GammaLink fax driver
0 = /dev/gfax0 GammaLink channel 0
1 = /dev/gfax1 GammaLink channel 1
...
-159 char RESERVED
+ 159 char RESERVED
-159 block RESERVED
+ 159 block RESERVED
-160 char General Purpose Instrument Bus (GPIB)
+ 160 char General Purpose Instrument Bus (GPIB)
0 = /dev/gpib0 First GPIB bus
1 = /dev/gpib1 Second GPIB bus
...
-160 block Carmel 8-port SATA Disks on First Controller
+ 160 block Carmel 8-port SATA Disks on First Controller
0 = /dev/carmel/0 SATA disk 0 whole disk
1 = /dev/carmel/0p1 SATA disk 0 partition 1
...
@@ -2365,7 +2310,7 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 31.
-161 char IrCOMM devices (IrDA serial/parallel emulation)
+ 161 char IrCOMM devices (IrDA serial/parallel emulation)
0 = /dev/ircomm0 First IrCOMM device
1 = /dev/ircomm1 Second IrCOMM device
...
@@ -2373,7 +2318,7 @@ Your cooperation is appreciated.
17 = /dev/irlpt1 Second IrLPT device
...
-161 block Carmel 8-port SATA Disks on Second Controller
+ 161 block Carmel 8-port SATA Disks on Second Controller
0 = /dev/carmel/8 SATA disk 8 whole disk
1 = /dev/carmel/8p1 SATA disk 8 partition 1
...
@@ -2388,17 +2333,17 @@ Your cooperation is appreciated.
disks (see major number 3) except that the limit on
partitions is 31.
-162 char Raw block device interface
+ 162 char Raw block device interface
0 = /dev/rawctl Raw I/O control device
1 = /dev/raw/raw1 First raw I/O device
2 = /dev/raw/raw2 Second raw I/O device
...
- max minor number of raw device is set by kernel config
- MAX_RAW_DEVS or raw module parameter 'max_raw_devs'
+ max minor number of raw device is set by kernel config
+ MAX_RAW_DEVS or raw module parameter 'max_raw_devs'
-163 char
+ 163 char
-164 char Chase Research AT/PCI-Fast serial card
+ 164 char Chase Research AT/PCI-Fast serial card
0 = /dev/ttyCH0 AT/PCI-Fast board 0, port 0
...
15 = /dev/ttyCH15 AT/PCI-Fast board 0, port 15
@@ -2412,67 +2357,67 @@ Your cooperation is appreciated.
...
63 = /dev/ttyCH63 AT/PCI-Fast board 3, port 15
-165 char Chase Research AT/PCI-Fast serial card - alternate devices
+ 165 char Chase Research AT/PCI-Fast serial card - alternate devices
0 = /dev/cuch0 Callout device for ttyCH0
...
63 = /dev/cuch63 Callout device for ttyCH63
-166 char ACM USB modems
+ 166 char ACM USB modems
0 = /dev/ttyACM0 First ACM modem
1 = /dev/ttyACM1 Second ACM modem
...
-167 char ACM USB modems - alternate devices
+ 167 char ACM USB modems - alternate devices
0 = /dev/cuacm0 Callout device for ttyACM0
1 = /dev/cuacm1 Callout device for ttyACM1
...
-168 char Eracom CSA7000 PCI encryption adaptor
+ 168 char Eracom CSA7000 PCI encryption adaptor
0 = /dev/ecsa0 First CSA7000
1 = /dev/ecsa1 Second CSA7000
...
-169 char Eracom CSA8000 PCI encryption adaptor
+ 169 char Eracom CSA8000 PCI encryption adaptor
0 = /dev/ecsa8-0 First CSA8000
1 = /dev/ecsa8-1 Second CSA8000
...
-170 char AMI MegaRAC remote access controller
+ 170 char AMI MegaRAC remote access controller
0 = /dev/megarac0 First MegaRAC card
1 = /dev/megarac1 Second MegaRAC card
...
-171 char Reserved for IEEE 1394 (Firewire)
+ 171 char Reserved for IEEE 1394 (Firewire)
-172 char Moxa Intellio serial card
+ 172 char Moxa Intellio serial card
0 = /dev/ttyMX0 First Moxa port
1 = /dev/ttyMX1 Second Moxa port
...
127 = /dev/ttyMX127 128th Moxa port
128 = /dev/moxactl Moxa control port
-173 char Moxa Intellio serial card - alternate devices
+ 173 char Moxa Intellio serial card - alternate devices
0 = /dev/cumx0 Callout device for ttyMX0
1 = /dev/cumx1 Callout device for ttyMX1
...
127 = /dev/cumx127 Callout device for ttyMX127
-174 char SmartIO serial card
+ 174 char SmartIO serial card
0 = /dev/ttySI0 First SmartIO port
1 = /dev/ttySI1 Second SmartIO port
...
-175 char SmartIO serial card - alternate devices
+ 175 char SmartIO serial card - alternate devices
0 = /dev/cusi0 Callout device for ttySI0
1 = /dev/cusi1 Callout device for ttySI1
...
-176 char nCipher nFast PCI crypto accelerator
+ 176 char nCipher nFast PCI crypto accelerator
0 = /dev/nfastpci0 First nFast PCI device
1 = /dev/nfastpci1 First nFast PCI device
...
-177 char TI PCILynx memory spaces
+ 177 char TI PCILynx memory spaces
0 = /dev/pcilynx/aux0 AUX space of first PCILynx card
...
15 = /dev/pcilynx/aux15 AUX space of 16th PCILynx card
@@ -2483,12 +2428,12 @@ Your cooperation is appreciated.
...
47 = /dev/pcilynx/ram15 RAM space of 16th PCILynx card
-178 char Giganet cLAN1xxx virtual interface adapter
+ 178 char Giganet cLAN1xxx virtual interface adapter
0 = /dev/clanvi0 First cLAN adapter
1 = /dev/clanvi1 Second cLAN adapter
...
-179 block MMC block devices
+ 179 block MMC block devices
0 = /dev/mmcblk0 First SD/MMC card
1 = /dev/mmcblk0p1 First partition on first MMC card
8 = /dev/mmcblk1 Second SD/MMC card
@@ -2500,12 +2445,12 @@ Your cooperation is appreciated.
bump the offset between each card to be the configured
value instead of the default 8.
-179 char CCube DVXChip-based PCI products
+ 179 char CCube DVXChip-based PCI products
0 = /dev/dvxirq0 First DVX device
1 = /dev/dvxirq1 Second DVX device
...
-180 char USB devices
+ 180 char USB devices
0 = /dev/usb/lp0 First USB printer
...
15 = /dev/usb/lp15 16th USB printer
@@ -2539,23 +2484,23 @@ Your cooperation is appreciated.
...
209 = /dev/usb/yurex16 16th USB Yurex device
-180 block USB block devices
+ 180 block USB block devices
0 = /dev/uba First USB block device
8 = /dev/ubb Second USB block device
16 = /dev/ubc Third USB block device
- ...
+ ...
-181 char Conrad Electronic parallel port radio clocks
+ 181 char Conrad Electronic parallel port radio clocks
0 = /dev/pcfclock0 First Conrad radio clock
1 = /dev/pcfclock1 Second Conrad radio clock
...
-182 char Picture Elements THR2 binarizer
+ 182 char Picture Elements THR2 binarizer
0 = /dev/pethr0 First THR2 board
1 = /dev/pethr1 Second THR2 board
...
-183 char SST 5136-DN DeviceNet interface
+ 183 char SST 5136-DN DeviceNet interface
0 = /dev/ss5136dn0 First DeviceNet interface
1 = /dev/ss5136dn1 Second DeviceNet interface
...
@@ -2563,12 +2508,12 @@ Your cooperation is appreciated.
This device used to be assigned to major number 144.
It had to be moved due to an unfortunate conflict.
-184 char Picture Elements' video simulator/sender
+ 184 char Picture Elements' video simulator/sender
0 = /dev/pevss0 First sender board
1 = /dev/pevss1 Second sender board
...
-185 char InterMezzo high availability file system
+ 185 char InterMezzo high availability file system
0 = /dev/intermezzo0 First cache manager
1 = /dev/intermezzo1 Second cache manager
...
@@ -2576,48 +2521,48 @@ Your cooperation is appreciated.
See http://web.archive.org/web/20080115195241/
http://inter-mezzo.org/index.html
-186 char Object-based storage control device
+ 186 char Object-based storage control device
0 = /dev/obd0 First obd control device
1 = /dev/obd1 Second obd control device
...
See ftp://ftp.lustre.org/pub/obd for code and information.
-187 char DESkey hardware encryption device
+ 187 char DESkey hardware encryption device
0 = /dev/deskey0 First DES key
1 = /dev/deskey1 Second DES key
...
-188 char USB serial converters
+ 188 char USB serial converters
0 = /dev/ttyUSB0 First USB serial converter
1 = /dev/ttyUSB1 Second USB serial converter
...
-189 char USB serial converters - alternate devices
+ 189 char USB serial converters - alternate devices
0 = /dev/cuusb0 Callout device for ttyUSB0
1 = /dev/cuusb1 Callout device for ttyUSB1
...
-190 char Kansas City tracker/tuner card
+ 190 char Kansas City tracker/tuner card
0 = /dev/kctt0 First KCT/T card
1 = /dev/kctt1 Second KCT/T card
...
-191 char Reserved for PCMCIA
+ 191 char Reserved for PCMCIA
-192 char Kernel profiling interface
+ 192 char Kernel profiling interface
0 = /dev/profile Profiling control device
1 = /dev/profile0 Profiling device for CPU 0
2 = /dev/profile1 Profiling device for CPU 1
...
-193 char Kernel event-tracing interface
+ 193 char Kernel event-tracing interface
0 = /dev/trace Tracing control device
1 = /dev/trace0 Tracing device for CPU 0
2 = /dev/trace1 Tracing device for CPU 1
...
-194 char linVideoStreams (LINVS)
+ 194 char linVideoStreams (LINVS)
0 = /dev/mvideo/status0 Video compression status
1 = /dev/mvideo/stream0 Video stream
2 = /dev/mvideo/frame0 Single compressed frame
@@ -2633,13 +2578,13 @@ Your cooperation is appreciated.
240 = /dev/mvideo/status15 16th device
...
-195 char Nvidia graphics devices
+ 195 char Nvidia graphics devices
0 = /dev/nvidia0 First Nvidia card
1 = /dev/nvidia1 Second Nvidia card
...
255 = /dev/nvidiactl Nvidia card control device
-196 char Tormenta T1 card
+ 196 char Tormenta T1 card
0 = /dev/tor/0 Master control channel for all cards
1 = /dev/tor/1 First DS0
2 = /dev/tor/2 Second DS0
@@ -2649,24 +2594,24 @@ Your cooperation is appreciated.
50 = /dev/tor/50 Second pseudo-channel
...
-197 char OpenTNF tracing facility
+ 197 char OpenTNF tracing facility
0 = /dev/tnf/t0 Trace 0 data extraction
1 = /dev/tnf/t1 Trace 1 data extraction
...
128 = /dev/tnf/status Tracing facility status
130 = /dev/tnf/trace Tracing device
-198 char Total Impact TPMP2 quad coprocessor PCI card
+ 198 char Total Impact TPMP2 quad coprocessor PCI card
0 = /dev/tpmp2/0 First card
1 = /dev/tpmp2/1 Second card
...
-199 char Veritas volume manager (VxVM) volumes
+ 199 char Veritas volume manager (VxVM) volumes
0 = /dev/vx/rdsk/*/* First volume
1 = /dev/vx/rdsk/*/* Second volume
...
-199 block Veritas volume manager (VxVM) volumes
+ 199 block Veritas volume manager (VxVM) volumes
0 = /dev/vx/dsk/*/* First volume
1 = /dev/vx/dsk/*/* Second volume
...
@@ -2674,19 +2619,19 @@ Your cooperation is appreciated.
The namespace in these directories is maintained by
the user space VxVM software.
-200 char Veritas VxVM configuration interface
- 0 = /dev/vx/config Configuration access node
- 1 = /dev/vx/trace Volume i/o trace access node
- 2 = /dev/vx/iod Volume i/o daemon access node
- 3 = /dev/vx/info Volume information access node
- 4 = /dev/vx/task Volume tasks access node
- 5 = /dev/vx/taskmon Volume tasks monitor daemon
+ 200 char Veritas VxVM configuration interface
+ 0 = /dev/vx/config Configuration access node
+ 1 = /dev/vx/trace Volume i/o trace access node
+ 2 = /dev/vx/iod Volume i/o daemon access node
+ 3 = /dev/vx/info Volume information access node
+ 4 = /dev/vx/task Volume tasks access node
+ 5 = /dev/vx/taskmon Volume tasks monitor daemon
-201 char Veritas VxVM dynamic multipathing driver
+ 201 char Veritas VxVM dynamic multipathing driver
0 = /dev/vx/rdmp/* First multipath device
1 = /dev/vx/rdmp/* Second multipath device
...
-201 block Veritas VxVM dynamic multipathing driver
+ 201 block Veritas VxVM dynamic multipathing driver
0 = /dev/vx/dmp/* First multipath device
1 = /dev/vx/dmp/* Second multipath device
...
@@ -2694,28 +2639,28 @@ Your cooperation is appreciated.
The namespace in these directories is maintained by
the user space VxVM software.
-202 char CPU model-specific registers
+ 202 char CPU model-specific registers
0 = /dev/cpu/0/msr MSRs on CPU 0
1 = /dev/cpu/1/msr MSRs on CPU 1
...
-202 block Xen Virtual Block Device
+ 202 block Xen Virtual Block Device
0 = /dev/xvda First Xen VBD whole disk
16 = /dev/xvdb Second Xen VBD whole disk
32 = /dev/xvdc Third Xen VBD whole disk
...
240 = /dev/xvdp Sixteenth Xen VBD whole disk
- Partitions are handled in the same way as for IDE
- disks (see major number 3) except that the limit on
- partitions is 15.
+ Partitions are handled in the same way as for IDE
+ disks (see major number 3) except that the limit on
+ partitions is 15.
-203 char CPU CPUID information
+ 203 char CPU CPUID information
0 = /dev/cpu/0/cpuid CPUID on CPU 0
1 = /dev/cpu/1/cpuid CPUID on CPU 1
...
-204 char Low-density serial ports
+ 204 char Low-density serial ports
0 = /dev/ttyLU0 LinkUp Systems L72xx UART - port 0
1 = /dev/ttyLU1 LinkUp Systems L72xx UART - port 1
2 = /dev/ttyLU2 LinkUp Systems L72xx UART - port 2
@@ -2787,7 +2732,7 @@ Your cooperation is appreciated.
211 = /dev/ttyMAX2 MAX3100 serial port 2
212 = /dev/ttyMAX3 MAX3100 serial port 3
-205 char Low-density serial ports (alternate device)
+ 205 char Low-density serial ports (alternate device)
0 = /dev/culu0 Callout device for ttyLU0
1 = /dev/culu1 Callout device for ttyLU1
2 = /dev/culu2 Callout device for ttyLU2
@@ -2823,7 +2768,7 @@ Your cooperation is appreciated.
82 = /dev/cuvr0 Callout device for ttyVR0
83 = /dev/cuvr1 Callout device for ttyVR1
-206 char OnStream SC-x0 tape devices
+ 206 char OnStream SC-x0 tape devices
0 = /dev/osst0 First OnStream SCSI tape, mode 0
1 = /dev/osst1 Second OnStream SCSI tape, mode 0
...
@@ -2857,7 +2802,7 @@ Your cooperation is appreciated.
driver as well. The ADR-x0 drives are QIC-157
compliant and don't need osst.
-207 char Compaq ProLiant health feature indicate
+ 207 char Compaq ProLiant health feature indicate
0 = /dev/cpqhealth/cpqw Redirector interface
1 = /dev/cpqhealth/crom EISA CROM
2 = /dev/cpqhealth/cdt Data Table
@@ -2871,17 +2816,17 @@ Your cooperation is appreciated.
10 = /dev/cpqhealth/cram CMOS interface
11 = /dev/cpqhealth/cpci PCI IRQ interface
-208 char User space serial ports
+ 208 char User space serial ports
0 = /dev/ttyU0 First user space serial port
1 = /dev/ttyU1 Second user space serial port
...
-209 char User space serial ports (alternate devices)
+ 209 char User space serial ports (alternate devices)
0 = /dev/cuu0 Callout device for ttyU0
1 = /dev/cuu1 Callout device for ttyU1
...
-210 char SBE, Inc. sync/async serial card
+ 210 char SBE, Inc. sync/async serial card
0 = /dev/sbei/wxcfg0 Configuration device for board 0
1 = /dev/sbei/dld0 Download device for board 0
2 = /dev/sbei/wan00 WAN device, port 0, board 0
@@ -2906,12 +2851,12 @@ Your cooperation is appreciated.
Yes, each board is really spaced 10 (decimal) apart.
-211 char Addinum CPCI1500 digital I/O card
+ 211 char Addinum CPCI1500 digital I/O card
0 = /dev/addinum/cpci1500/0 First CPCI1500 card
1 = /dev/addinum/cpci1500/1 Second CPCI1500 card
...
-212 char LinuxTV.org DVB driver subsystem
+ 212 char LinuxTV.org DVB driver subsystem
0 = /dev/dvb/adapter0/video0 first video decoder of first card
1 = /dev/dvb/adapter0/audio0 first audio decoder of first card
2 = /dev/dvb/adapter0/sec0 (obsolete/unused)
@@ -2929,34 +2874,34 @@ Your cooperation is appreciated.
...
196 = /dev/dvb/adapter3/video0 first video decoder of fourth card
-216 char Bluetooth RFCOMM TTY devices
+ 216 char Bluetooth RFCOMM TTY devices
0 = /dev/rfcomm0 First Bluetooth RFCOMM TTY device
1 = /dev/rfcomm1 Second Bluetooth RFCOMM TTY device
...
-217 char Bluetooth RFCOMM TTY devices (alternate devices)
+ 217 char Bluetooth RFCOMM TTY devices (alternate devices)
0 = /dev/curf0 Callout device for rfcomm0
1 = /dev/curf1 Callout device for rfcomm1
...
-218 char The Logical Company bus Unibus/Qbus adapters
+ 218 char The Logical Company bus Unibus/Qbus adapters
0 = /dev/logicalco/bci/0 First bus adapter
1 = /dev/logicalco/bci/1 First bus adapter
...
-219 char The Logical Company DCI-1300 digital I/O card
+ 219 char The Logical Company DCI-1300 digital I/O card
0 = /dev/logicalco/dci1300/0 First DCI-1300 card
1 = /dev/logicalco/dci1300/1 Second DCI-1300 card
...
-220 char Myricom Myrinet "GM" board
+ 220 char Myricom Myrinet "GM" board
0 = /dev/myricom/gm0 First Myrinet GM board
1 = /dev/myricom/gmp0 First board "root access"
2 = /dev/myricom/gm1 Second Myrinet GM board
3 = /dev/myricom/gmp1 Second board "root access"
...
-221 char VME bus
+ 221 char VME bus
0 = /dev/bus/vme/m0 First master image
1 = /dev/bus/vme/m1 Second master image
2 = /dev/bus/vme/m2 Third master image
@@ -2971,38 +2916,38 @@ Your cooperation is appreciated.
same interface. For interface documentation see
http://www.vmelinux.org/.
-224 char A2232 serial card
+ 224 char A2232 serial card
0 = /dev/ttyY0 First A2232 port
1 = /dev/ttyY1 Second A2232 port
...
-225 char A2232 serial card (alternate devices)
+ 225 char A2232 serial card (alternate devices)
0 = /dev/cuy0 Callout device for ttyY0
1 = /dev/cuy1 Callout device for ttyY1
...
-226 char Direct Rendering Infrastructure (DRI)
+ 226 char Direct Rendering Infrastructure (DRI)
0 = /dev/dri/card0 First graphics card
1 = /dev/dri/card1 Second graphics card
...
-227 char IBM 3270 terminal Unix tty access
+ 227 char IBM 3270 terminal Unix tty access
1 = /dev/3270/tty1 First 3270 terminal
2 = /dev/3270/tty2 Seconds 3270 terminal
...
-228 char IBM 3270 terminal block-mode access
+ 228 char IBM 3270 terminal block-mode access
0 = /dev/3270/tub Controlling interface
1 = /dev/3270/tub1 First 3270 terminal
2 = /dev/3270/tub2 Second 3270 terminal
...
-229 char IBM iSeries/pSeries virtual console
+ 229 char IBM iSeries/pSeries virtual console
0 = /dev/hvc0 First console port
1 = /dev/hvc1 Second console port
...
-230 char IBM iSeries virtual tape
+ 230 char IBM iSeries virtual tape
0 = /dev/iseries/vt0 First virtual tape, mode 0
1 = /dev/iseries/vt1 Second virtual tape, mode 0
...
@@ -3033,7 +2978,7 @@ Your cooperation is appreciated.
ioctl()'s can be used to rewind the tape regardless of
the device used to access it.
-231 char InfiniBand
+ 231 char InfiniBand
0 = /dev/infiniband/umad0
1 = /dev/infiniband/umad1
...
@@ -3047,7 +2992,7 @@ Your cooperation is appreciated.
...
159 = /dev/infiniband/uverbs31 31st InfiniBand verbs device
-232 char Biometric Devices
+ 232 char Biometric Devices
0 = /dev/biometric/sensor0/fingerprint first fingerprint sensor on first device
1 = /dev/biometric/sensor0/iris first iris sensor on first device
2 = /dev/biometric/sensor0/retina first retina sensor on first device
@@ -3060,7 +3005,7 @@ Your cooperation is appreciated.
20 = /dev/biometric/sensor2/fingerprint first fingerprint sensor on third device
...
-233 char PathScale InfiniPath interconnect
+ 233 char PathScale InfiniPath interconnect
0 = /dev/ipath Primary device for programs (any unit)
1 = /dev/ipath0 Access specifically to unit 0
2 = /dev/ipath1 Access specifically to unit 1
@@ -3069,18 +3014,18 @@ Your cooperation is appreciated.
129 = /dev/ipath_sma Device used by Subnet Management Agent
130 = /dev/ipath_diag Device used by diagnostics programs
-234-254 char RESERVED FOR DYNAMIC ASSIGNMENT
+ 234-254 char RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major number will
take numbers starting from 254 and downward.
-240-254 block LOCAL/EXPERIMENTAL USE
+ 240-254 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
-255 char RESERVED
+ 255 char RESERVED
-255 block RESERVED
+ 255 block RESERVED
This major is reserved to assist the expansion to a
larger number space. No device nodes with this major
@@ -3088,25 +3033,25 @@ Your cooperation is appreciated.
(This is probably not true anymore, but I'll leave it
for now /Torben)
----LARGE MAJORS!!!!!---
+ ---LARGE MAJORS!!!!!---
-256 char Equinox SST multi-port serial boards
+ 256 char Equinox SST multi-port serial boards
0 = /dev/ttyEQ0 First serial port on first Equinox SST board
127 = /dev/ttyEQ127 Last serial port on first Equinox SST board
128 = /dev/ttyEQ128 First serial port on second Equinox SST board
...
1027 = /dev/ttyEQ1027 Last serial port on eighth Equinox SST board
-256 block Resident Flash Disk Flash Translation Layer
+ 256 block Resident Flash Disk Flash Translation Layer
0 = /dev/rfda First RFD FTL layer
16 = /dev/rfdb Second RFD FTL layer
...
240 = /dev/rfdp 16th RFD FTL layer
-257 char Phoenix Technologies Cryptographic Services Driver
+ 257 char Phoenix Technologies Cryptographic Services Driver
0 = /dev/ptlsec Crypto Services Driver
-257 block SSFDC Flash Translation Layer filesystem
+ 257 block SSFDC Flash Translation Layer filesystem
0 = /dev/ssfdca First SSFDC layer
8 = /dev/ssfdcb Second SSFDC layer
16 = /dev/ssfdcc Third SSFDC layer
@@ -3116,210 +3061,21 @@ Your cooperation is appreciated.
48 = /dev/ssfdcg 7th SSFDC layer
56 = /dev/ssfdch 8th SSFDC layer
-258 block ROM/Flash read-only translation layer
+ 258 block ROM/Flash read-only translation layer
0 = /dev/blockrom0 First ROM card's translation layer interface
1 = /dev/blockrom1 Second ROM card's translation layer interface
...
-259 block Block Extended Major
+ 259 block Block Extended Major
Used dynamically to hold additional partition minor
numbers and allow large numbers of partitions per device
-259 char FPGA configuration interfaces
+ 259 char FPGA configuration interfaces
0 = /dev/icap0 First Xilinx internal configuration
1 = /dev/icap1 Second Xilinx internal configuration
-260 char OSD (Object-based-device) SCSI Device
+ 260 char OSD (Object-based-device) SCSI Device
0 = /dev/osd0 First OSD Device
1 = /dev/osd1 Second OSD Device
...
255 = /dev/osd255 256th OSD Device
-
- **** ADDITIONAL /dev DIRECTORY ENTRIES
-
-This section details additional entries that should or may exist in
-the /dev directory. It is preferred that symbolic links use the same
-form (absolute or relative) as is indicated here. Links are
-classified as "hard" or "symbolic" depending on the preferred type of
-link; if possible, the indicated type of link should be used.
-
-
- Compulsory links
-
-These links should exist on all systems:
-
-/dev/fd /proc/self/fd symbolic File descriptors
-/dev/stdin fd/0 symbolic stdin file descriptor
-/dev/stdout fd/1 symbolic stdout file descriptor
-/dev/stderr fd/2 symbolic stderr file descriptor
-/dev/nfsd socksys symbolic Required by iBCS-2
-/dev/X0R null symbolic Required by iBCS-2
-
-Note: /dev/X0R is <letter X>-<digit 0>-<letter R>.
-
- Recommended links
-
-It is recommended that these links exist on all systems:
-
-/dev/core /proc/kcore symbolic Backward compatibility
-/dev/ramdisk ram0 symbolic Backward compatibility
-/dev/ftape qft0 symbolic Backward compatibility
-/dev/bttv0 video0 symbolic Backward compatibility
-/dev/radio radio0 symbolic Backward compatibility
-/dev/i2o* /dev/i2o/* symbolic Backward compatibility
-/dev/scd? sr? hard Alternate SCSI CD-ROM name
-
- Locally defined links
-
-The following links may be established locally to conform to the
-configuration of the system. This is merely a tabulation of existing
-practice, and does not constitute a recommendation. However, if they
-exist, they should have the following uses.
-
-/dev/mouse mouse port symbolic Current mouse device
-/dev/tape tape device symbolic Current tape device
-/dev/cdrom CD-ROM device symbolic Current CD-ROM device
-/dev/cdwriter CD-writer symbolic Current CD-writer device
-/dev/scanner scanner symbolic Current scanner device
-/dev/modem modem port symbolic Current dialout device
-/dev/root root device symbolic Current root filesystem
-/dev/swap swap device symbolic Current swap device
-
-/dev/modem should not be used for a modem which supports dialin as
-well as dialout, as it tends to cause lock file problems. If it
-exists, /dev/modem should point to the appropriate primary TTY device
-(the use of the alternate callout devices is deprecated).
-
-For SCSI devices, /dev/tape and /dev/cdrom should point to the
-``cooked'' devices (/dev/st* and /dev/sr*, respectively), whereas
-/dev/cdwriter and /dev/scanner should point to the appropriate generic
-SCSI devices (/dev/sg*).
-
-/dev/mouse may point to a primary serial TTY device, a hardware mouse
-device, or a socket for a mouse driver program (e.g. /dev/gpmdata).
-
- Sockets and pipes
-
-Non-transient sockets and named pipes may exist in /dev. Common entries are:
-
-/dev/printer socket lpd local socket
-/dev/log socket syslog local socket
-/dev/gpmdata socket gpm mouse multiplexer
-
- Mount points
-
-The following names are reserved for mounting special filesystems
-under /dev. These special filesystems provide kernel interfaces that
-cannot be provided with standard device nodes.
-
-/dev/pts devpts PTY slave filesystem
-/dev/shm tmpfs POSIX shared memory maintenance access
-
- **** TERMINAL DEVICES
-
-Terminal, or TTY devices are a special class of character devices. A
-terminal device is any device that could act as a controlling terminal
-for a session; this includes virtual consoles, serial ports, and
-pseudoterminals (PTYs).
-
-All terminal devices share a common set of capabilities known as line
-disciplines; these include the common terminal line discipline as well
-as SLIP and PPP modes.
-
-All terminal devices are named similarly; this section explains the
-naming and use of the various types of TTYs. Note that the naming
-conventions include several historical warts; some of these are
-Linux-specific, some were inherited from other systems, and some
-reflect Linux outgrowing a borrowed convention.
-
-A hash mark (#) in a device name is used here to indicate a decimal
-number without leading zeroes.
-
- Virtual consoles and the console device
-
-Virtual consoles are full-screen terminal displays on the system video
-monitor. Virtual consoles are named /dev/tty#, with numbering
-starting at /dev/tty1; /dev/tty0 is the current virtual console.
-/dev/tty0 is the device that should be used to access the system video
-card on those architectures for which the frame buffer devices
-(/dev/fb*) are not applicable. Do not use /dev/console
-for this purpose.
-
-The console device, /dev/console, is the device to which system
-messages should be sent, and on which logins should be permitted in
-single-user mode. Starting with Linux 2.1.71, /dev/console is managed
-by the kernel; for previous versions it should be a symbolic link to
-either /dev/tty0, a specific virtual console such as /dev/tty1, or to
-a serial port primary (tty*, not cu*) device, depending on the
-configuration of the system.
-
- Serial ports
-
-Serial ports are RS-232 serial ports and any device which simulates
-one, either in hardware (such as internal modems) or in software (such
-as the ISDN driver.) Under Linux, each serial ports has two device
-names, the primary or callin device and the alternate or callout one.
-Each kind of device is indicated by a different letter. For any
-letter X, the names of the devices are /dev/ttyX# and /dev/cux#,
-respectively; for historical reasons, /dev/ttyS# and /dev/ttyC#
-correspond to /dev/cua# and /dev/cub#. In the future, it should be
-expected that multiple letters will be used; all letters will be upper
-case for the "tty" device (e.g. /dev/ttyDP#) and lower case for the
-"cu" device (e.g. /dev/cudp#).
-
-The names /dev/ttyQ# and /dev/cuq# are reserved for local use.
-
-The alternate devices provide for kernel-based exclusion and somewhat
-different defaults than the primary devices. Their main purpose is to
-allow the use of serial ports with programs with no inherent or broken
-support for serial ports. Their use is deprecated, and they may be
-removed from a future version of Linux.
-
-Arbitration of serial ports is provided by the use of lock files with
-the names /var/lock/LCK..ttyX#. The contents of the lock file should
-be the PID of the locking process as an ASCII number.
-
-It is common practice to install links such as /dev/modem
-which point to serial ports. In order to ensure proper locking in the
-presence of these links, it is recommended that software chase
-symlinks and lock all possible names; additionally, it is recommended
-that a lock file be installed with the corresponding alternate
-device. In order to avoid deadlocks, it is recommended that the locks
-are acquired in the following order, and released in the reverse:
-
- 1. The symbolic link name, if any (/var/lock/LCK..modem)
- 2. The "tty" name (/var/lock/LCK..ttyS2)
- 3. The alternate device name (/var/lock/LCK..cua2)
-
-In the case of nested symbolic links, the lock files should be
-installed in the order the symlinks are resolved.
-
-Under no circumstances should an application hold a lock while waiting
-for another to be released. In addition, applications which attempt
-to create lock files for the corresponding alternate device names
-should take into account the possibility of being used on a non-serial
-port TTY, for which no alternate device would exist.
-
- Pseudoterminals (PTYs)
-
-Pseudoterminals, or PTYs, are used to create login sessions or provide
-other capabilities requiring a TTY line discipline (including SLIP or
-PPP capability) to arbitrary data-generation processes. Each PTY has
-a master side, named /dev/pty[p-za-e][0-9a-f], and a slave side, named
-/dev/tty[p-za-e][0-9a-f]. The kernel arbitrates the use of PTYs by
-allowing each master side to be opened only once.
-
-Once the master side has been opened, the corresponding slave device
-can be used in the same manner as any TTY device. The master and
-slave devices are connected by the kernel, generating the equivalent
-of a bidirectional pipe with TTY capabilities.
-
-Recent versions of the Linux kernels and GNU libc contain support for
-the System V/Unix98 naming scheme for PTYs, which assigns a common
-device, /dev/ptmx, to all the masters (opening it will automatically
-give you a previously unassigned PTY) and a subdirectory, /dev/pts,
-for the slaves; the slaves are named with decimal integers (/dev/pts/#
-in our notation). This removes the problem of exhausting the
-namespace and enables the kernel to automatically create the device
-nodes for the slaves on demand using the "devpts" filesystem.
-
diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
new file mode 100644
index 000000000000..88adcfdf5b2b
--- /dev/null
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -0,0 +1,353 @@
+Dynamic debug
++++++++++++++
+
+
+Introduction
+============
+
+This document describes how to use the dynamic debug (dyndbg) feature.
+
+Dynamic debug is designed to allow you to dynamically enable/disable
+kernel code to obtain additional kernel information. Currently, if
+``CONFIG_DYNAMIC_DEBUG`` is set, then all ``pr_debug()``/``dev_dbg()`` and
+``print_hex_dump_debug()``/``print_hex_dump_bytes()`` calls can be dynamically
+enabled per-callsite.
+
+If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is just
+shortcut for ``print_hex_dump(KERN_DEBUG)``.
+
+For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
+its ``prefix_str`` argument, if it is constant string; or ``hexdump``
+in case ``prefix_str`` is build dynamically.
+
+Dynamic debug has even more useful features:
+
+ * Simple query language allows turning on and off debugging
+ statements by matching any combination of 0 or 1 of:
+
+ - source filename
+ - function name
+ - line number (including ranges of line numbers)
+ - module name
+ - format string
+
+ * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
+ which can be read to display the complete list of known debug
+ statements, to help guide you
+
+Controlling dynamic debug Behaviour
+===================================
+
+The behaviour of ``pr_debug()``/``dev_dbg()`` are controlled via writing to a
+control file in the 'debugfs' filesystem. Thus, you must first mount
+the debugfs filesystem, in order to make use of this feature.
+Subsequently, we refer to the control file as:
+``<debugfs>/dynamic_debug/control``. For example, if you want to enable
+printing from source file ``svcsock.c``, line 1603 you simply do::
+
+ nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
+ <debugfs>/dynamic_debug/control
+
+If you make a mistake with the syntax, the write will fail thus::
+
+ nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
+ <debugfs>/dynamic_debug/control
+ -bash: echo: write error: Invalid argument
+
+Viewing Dynamic Debug Behaviour
+===============================
+
+You can view the currently configured behaviour of all the debug
+statements via::
+
+ nullarbor:~ # cat <debugfs>/dynamic_debug/control
+ # filename:lineno [module]function flags format
+ /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
+ /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012"
+ /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012"
+ /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012"
+ ...
+
+
+You can also apply standard Unix text manipulation filters to this
+data, e.g.::
+
+ nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l
+ 62
+
+ nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
+ 42
+
+The third column shows the currently enabled flags for each debug
+statement callsite (see below for definitions of the flags). The
+default value, with no flags enabled, is ``=_``. So you can view all
+the debug statement callsites with any non-default flags::
+
+ nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
+ # filename:lineno [module]function flags format
+ /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
+
+Command Language Reference
+==========================
+
+At the lexical level, a command comprises a sequence of words separated
+by spaces or tabs. So these are all equivalent::
+
+ nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
+ <debugfs>/dynamic_debug/control
+ nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' >
+ <debugfs>/dynamic_debug/control
+ nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+ <debugfs>/dynamic_debug/control
+
+Command submissions are bounded by a write() system call.
+Multiple commands can be written together, separated by ``;`` or ``\n``::
+
+ ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \
+ > <debugfs>/dynamic_debug/control
+
+If your query set is big, you can batch them too::
+
+ ~# cat query-batch-file > <debugfs>/dynamic_debug/control
+
+A another way is to use wildcard. The match rule support ``*`` (matches
+zero or more characters) and ``?`` (matches exactly one character).For
+example, you can match all usb drivers::
+
+ ~# echo "file drivers/usb/* +p" > <debugfs>/dynamic_debug/control
+
+At the syntactical level, a command comprises a sequence of match
+specifications, followed by a flags change specification::
+
+ command ::= match-spec* flags-spec
+
+The match-spec's are used to choose a subset of the known pr_debug()
+callsites to which to apply the flags-spec. Think of them as a query
+with implicit ANDs between each pair. Note that an empty list of
+match-specs will select all debug statement callsites.
+
+A match specification comprises a keyword, which controls the
+attribute of the callsite to be compared, and a value to compare
+against. Possible keywords are:::
+
+ match-spec ::= 'func' string |
+ 'file' string |
+ 'module' string |
+ 'format' string |
+ 'line' line-range
+
+ line-range ::= lineno |
+ '-'lineno |
+ lineno'-' |
+ lineno'-'lineno
+
+ lineno ::= unsigned-int
+
+.. note::
+
+ ``line-range`` cannot contain space, e.g.
+ "1-30" is valid range but "1 - 30" is not.
+
+
+The meanings of each keyword are:
+
+func
+ The given string is compared against the function name
+ of each callsite. Example::
+
+ func svc_tcp_accept
+
+file
+ The given string is compared against either the full pathname, the
+ src-root relative pathname, or the basename of the source file of
+ each callsite. Examples::
+
+ file svcsock.c
+ file kernel/freezer.c
+ file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
+
+module
+ The given string is compared against the module name
+ of each callsite. The module name is the string as
+ seen in ``lsmod``, i.e. without the directory or the ``.ko``
+ suffix and with ``-`` changed to ``_``. Examples::
+
+ module sunrpc
+ module nfsd
+
+format
+ The given string is searched for in the dynamic debug format
+ string. Note that the string does not need to match the
+ entire format, only some part. Whitespace and other
+ special characters can be escaped using C octal character
+ escape ``\ooo`` notation, e.g. the space character is ``\040``.
+ Alternatively, the string can be enclosed in double quote
+ characters (``"``) or single quote characters (``'``).
+ Examples::
+
+ format svcrdma: // many of the NFS/RDMA server pr_debugs
+ format readahead // some pr_debugs in the readahead cache
+ format nfsd:\040SETATTR // one way to match a format with whitespace
+ format "nfsd: SETATTR" // a neater way to match a format with whitespace
+ format 'nfsd: SETATTR' // yet another way to match a format with whitespace
+
+line
+ The given line number or range of line numbers is compared
+ against the line number of each ``pr_debug()`` callsite. A single
+ line number matches the callsite line number exactly. A
+ range of line numbers matches any callsite between the first
+ and last line number inclusive. An empty first number means
+ the first line in the file, an empty line number means the
+ last number in the file. Examples::
+
+ line 1603 // exactly line 1603
+ line 1600-1605 // the six lines from line 1600 to line 1605
+ line -1605 // the 1605 lines from line 1 to line 1605
+ line 1600- // all lines from line 1600 to the end of the file
+
+The flags specification comprises a change operation followed
+by one or more flag characters. The change operation is one
+of the characters::
+
+ - remove the given flags
+ + add the given flags
+ = set the flags to the given flags
+
+The flags are::
+
+ p enables the pr_debug() callsite.
+ f Include the function name in the printed message
+ l Include line number in the printed message
+ m Include module name in the printed message
+ t Include thread ID in messages not generated from interrupt context
+ _ No flags are set. (Or'd with others on input)
+
+For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only ``p`` flag
+have meaning, other flags ignored.
+
+For display, the flags are preceded by ``=``
+(mnemonic: what the flags are currently equal to).
+
+Note the regexp ``^[-+=][flmpt_]+$`` matches a flags specification.
+To clear all flags at once, use ``=_`` or ``-flmpt``.
+
+
+Debug messages during Boot Process
+==================================
+
+To activate debug messages for core code and built-in modules during
+the boot process, even before userspace and debugfs exists, use
+``dyndbg="QUERY"``, ``module.dyndbg="QUERY"``, or ``ddebug_query="QUERY"``
+(``ddebug_query`` is obsoleted by ``dyndbg``, and deprecated). QUERY follows
+the syntax described above, but must not exceed 1023 characters. Your
+bootloader may impose lower limits.
+
+These ``dyndbg`` params are processed just after the ddebug tables are
+processed, as part of the arch_initcall. Thus you can enable debug
+messages in all code run after this arch_initcall via this boot
+parameter.
+
+On an x86 system for example ACPI enablement is a subsys_initcall and::
+
+ dyndbg="file ec.c +p"
+
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+If ``foo`` module is not built-in, ``foo.dyndbg`` will still be processed at
+boot time, without effect, but will be reprocessed when module is
+loaded later. ``dyndbg_query=`` and bare ``dyndbg=`` are only processed at
+boot.
+
+
+Debug Messages at Module Initialization Time
+============================================
+
+When ``modprobe foo`` is called, modprobe scans ``/proc/cmdline`` for
+``foo.params``, strips ``foo.``, and passes them to the kernel along with
+params given in modprobe args or ``/etc/modprob.d/*.conf`` files,
+in the following order:
+
+1. parameters given via ``/etc/modprobe.d/*.conf``::
+
+ options foo dyndbg=+pt
+ options foo dyndbg # defaults to +p
+
+2. ``foo.dyndbg`` as given in boot args, ``foo.`` is stripped and passed::
+
+ foo.dyndbg=" func bar +p; func buz +mp"
+
+3. args to modprobe::
+
+ modprobe foo dyndbg==pmf # override previous settings
+
+These ``dyndbg`` queries are applied in order, with last having final say.
+This allows boot args to override or modify those from ``/etc/modprobe.d``
+(sensible, since 1 is system wide, 2 is kernel or boot specific), and
+modprobe args to override both.
+
+In the ``foo.dyndbg="QUERY"`` form, the query must exclude ``module foo``.
+``foo`` is extracted from the param-name, and applied to each query in
+``QUERY``, and only 1 match-spec of each type is allowed.
+
+The ``dyndbg`` option is a "fake" module parameter, which means:
+
+- modules do not need to define it explicitly
+- every module gets it tacitly, whether they use pr_debug or not
+- it doesn't appear in ``/sys/module/$module/parameters/``
+ To see it, grep the control file, or inspect ``/proc/cmdline.``
+
+For ``CONFIG_DYNAMIC_DEBUG`` kernels, any settings given at boot-time (or
+enabled by ``-DDEBUG`` flag during compilation) can be disabled later via
+the sysfs interface if the debug messages are no longer needed::
+
+ echo "module module_name -p" > <debugfs>/dynamic_debug/control
+
+Examples
+========
+
+::
+
+ // enable the message at line 1603 of file svcsock.c
+ nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+ <debugfs>/dynamic_debug/control
+
+ // enable all the messages in file svcsock.c
+ nullarbor:~ # echo -n 'file svcsock.c +p' >
+ <debugfs>/dynamic_debug/control
+
+ // enable all the messages in the NFS server module
+ nullarbor:~ # echo -n 'module nfsd +p' >
+ <debugfs>/dynamic_debug/control
+
+ // enable all 12 messages in the function svc_process()
+ nullarbor:~ # echo -n 'func svc_process +p' >
+ <debugfs>/dynamic_debug/control
+
+ // disable all 12 messages in the function svc_process()
+ nullarbor:~ # echo -n 'func svc_process -p' >
+ <debugfs>/dynamic_debug/control
+
+ // enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
+ nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
+ <debugfs>/dynamic_debug/control
+
+ // enable messages in files of which the paths include string "usb"
+ nullarbor:~ # echo -n '*usb* +p' > <debugfs>/dynamic_debug/control
+
+ // enable all messages
+ nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
+
+ // add module, function to all enabled messages
+ nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
+
+ // boot-args example, with newlines and comments for readability
+ Kernel command line: ...
+ // see whats going on in dyndbg=value processing
+ dynamic_debug.verbose=1
+ // enable pr_debugs in 2 builtins, #cmt is stripped
+ dyndbg="module params +p #cmt ; module sys +p"
+ // enable pr_debugs in 2 functions in a module loaded later
+ pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
new file mode 100644
index 000000000000..2681cbd24cdd
--- /dev/null
+++ b/Documentation/admin-guide/index.rst
@@ -0,0 +1,68 @@
+The Linux kernel user's and administrator's guide
+=================================================
+
+The following is a collection of user-oriented documents that have been
+added to the kernel over time. There is, as yet, little overall order or
+organization here — this material was not written to be a single, coherent
+document! With luck things will improve quickly over time.
+
+This initial section contains overall information, including the README
+file describing the kernel as a whole, documentation on kernel parameters,
+etc.
+
+.. toctree::
+ :maxdepth: 1
+
+ README
+ kernel-parameters
+ devices
+
+Here is a set of documents aimed at users who are trying to track down
+problems and bugs in particular.
+
+.. toctree::
+ :maxdepth: 1
+
+ reporting-bugs
+ security-bugs
+ bug-hunting
+ bug-bisect
+ tainted-kernels
+ ramoops
+ dynamic-debug-howto
+ init
+
+This is the beginning of a section with information of interest to
+application developers. Documents covering various aspects of the kernel
+ABI will be found here.
+
+.. toctree::
+ :maxdepth: 1
+
+ sysfs-rules
+
+The rest of this manual consists of various unordered guides on how to
+configure specific aspects of kernel behavior to your liking.
+
+.. toctree::
+ :maxdepth: 1
+
+ initrd
+ serial-console
+ braille-console
+ parport
+ md
+ module-signing
+ sysrq
+ unicode
+ vga-softcursor
+ binfmt-misc
+ mono
+ java
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/init.txt b/Documentation/admin-guide/init.rst
index 535ad5e82b98..e89d97f31eaf 100644
--- a/Documentation/init.txt
+++ b/Documentation/admin-guide/init.rst
@@ -5,6 +5,7 @@ OK, so you've got this pretty unintuitive message (currently located
in init/main.c) and are wondering what the H*** went wrong.
Some high-level reasons for failure (listed roughly in order of execution)
to load the init binary are:
+
A) Unable to mount root FS
B) init binary doesn't exist on rootfs
C) broken console device
@@ -12,37 +13,39 @@ D) binary exists but dependencies not available
E) binary cannot be loaded
Detailed explanations:
-0) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
+
+A) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
to get more detailed kernel messages.
-A) make sure you have the correct root FS type
- (and root= kernel parameter points to the correct partition),
+B) make sure you have the correct root FS type
+ (and ``root=`` kernel parameter points to the correct partition),
required drivers such as storage hardware (such as SCSI or USB!)
and filesystem (ext3, jffs2 etc.) are builtin (alternatively as modules,
to be pre-loaded by an initrd)
-C) Possibly a conflict in console= setup --> initial console unavailable.
+C) Possibly a conflict in ``console= setup`` --> initial console unavailable.
E.g. some serial consoles are unreliable due to serial IRQ issues (e.g.
missing interrupt-based configuration).
- Try using a different console= device or e.g. netconsole= .
+ Try using a different ``console= device`` or e.g. ``netconsole=``.
D) e.g. required library dependencies of the init binary such as
- /lib/ld-linux.so.2 missing or broken. Use readelf -d <INIT>|grep NEEDED
- to find out which libraries are required.
+ ``/lib/ld-linux.so.2`` missing or broken. Use
+ ``readelf -d <INIT>|grep NEEDED`` to find out which libraries are required.
E) make sure the binary's architecture matches your hardware.
E.g. i386 vs. x86_64 mismatch, or trying to load x86 on ARM hardware.
In case you tried loading a non-binary file here (shell script?),
you should make sure that the script specifies an interpreter in its shebang
- header line (#!/...) that is fully working (including its library
+ header line (``#!/...``) that is fully working (including its library
dependencies). And before tackling scripts, better first test a simple
- non-script binary such as /bin/sh and confirm its successful execution.
- To find out more, add code to init/main.c to display kernel_execve()s
+ non-script binary such as ``/bin/sh`` and confirm its successful execution.
+ To find out more, add code ``to init/main.c`` to display kernel_execve()s
return values.
Please extend this explanation whenever you find new failure causes
(after all loading the init binary is a CRITICAL and hard transition step
which needs to be made as painless as possible), then submit patch to LKML.
Further TODOs:
-- Implement the various run_init_process() invocations via a struct array
- which can then store the kernel_execve() result value and on failure
- log it all by iterating over _all_ results (very important usability fix).
+
+- Implement the various ``run_init_process()`` invocations via a struct array
+ which can then store the ``kernel_execve()`` result value and on failure
+ log it all by iterating over **all** results (very important usability fix).
- try to make the implementation itself more helpful in general,
e.g. by providing additional error messages at affected places.
diff --git a/Documentation/initrd.txt b/Documentation/admin-guide/initrd.rst
index 4e1839ccb555..a03dabaaf3a3 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/admin-guide/initrd.rst
@@ -2,7 +2,7 @@ Using the initial RAM disk (initrd)
===================================
Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
- Hans Lermen <lermen@fgan.de>
+Hans Lermen <lermen@fgan.de>
initrd provides the capability to load a RAM disk by the boot loader.
@@ -16,7 +16,7 @@ where the kernel comes up with a minimum set of compiled-in drivers, and
where additional modules are loaded from initrd.
This document gives a brief overview of the use of initrd. A more detailed
-discussion of the boot process can be found in [1].
+discussion of the boot process can be found in [#f1]_.
Operation
@@ -27,10 +27,10 @@ When using initrd, the system typically boots as follows:
1) the boot loader loads the kernel and the initial RAM disk
2) the kernel converts initrd into a "normal" RAM disk and
frees the memory used by initrd
- 3) if the root device is not /dev/ram0, the old (deprecated)
+ 3) if the root device is not ``/dev/ram0``, the old (deprecated)
change_root procedure is followed. see the "Obsolete root change
mechanism" section below.
- 4) root device is mounted. if it is /dev/ram0, the initrd image is
+ 4) root device is mounted. if it is ``/dev/ram0``, the initrd image is
then mounted as root
5) /sbin/init is executed (this can be any valid executable, including
shell scripts; it is run with uid 0 and can do basically everything
@@ -38,7 +38,7 @@ When using initrd, the system typically boots as follows:
6) init mounts the "real" root file system
7) init places the root file system at the root directory using the
pivot_root system call
- 8) init execs the /sbin/init on the new root filesystem, performing
+ 8) init execs the ``/sbin/init`` on the new root filesystem, performing
the usual boot sequence
9) the initrd file system is removed
@@ -51,7 +51,7 @@ be accessible.
Boot command-line options
-------------------------
-initrd adds the following new options:
+initrd adds the following new options::
initrd=<path> (e.g. LOADLIN)
@@ -83,36 +83,36 @@ Recent kernels have support for populating a ramdisk from a compressed cpio
archive. On such systems, the creation of a ramdisk image doesn't need to
involve special block devices or loopbacks; you merely create a directory on
disk with the desired initrd content, cd to that directory, and run (as an
-example):
+example)::
-find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
+ find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
-Examining the contents of an existing image file is just as simple:
+Examining the contents of an existing image file is just as simple::
-mkdir /tmp/imagefile
-cd /tmp/imagefile
-gzip -cd /boot/imagefile.img | cpio -imd --quiet
+ mkdir /tmp/imagefile
+ cd /tmp/imagefile
+ gzip -cd /boot/imagefile.img | cpio -imd --quiet
Installation
------------
First, a directory for the initrd file system has to be created on the
-"normal" root file system, e.g.
+"normal" root file system, e.g.::
-# mkdir /initrd
+ # mkdir /initrd
-The name is not relevant. More details can be found on the pivot_root(2)
-man page.
+The name is not relevant. More details can be found on the
+:manpage:`pivot_root(2)` man page.
If the root file system is created during the boot procedure (i.e. if
you're building an install floppy), the root file system creation
-procedure should create the /initrd directory.
+procedure should create the ``/initrd`` directory.
If initrd will not be mounted in some cases, its content is still
-accessible if the following device has been created:
+accessible if the following device has been created::
-# mknod /dev/initrd b 1 250
-# chmod 400 /dev/initrd
+ # mknod /dev/initrd b 1 250
+ # chmod 400 /dev/initrd
Second, the kernel has to be compiled with RAM disk support and with
support for the initial RAM disk enabled. Also, at least all components
@@ -131,60 +131,76 @@ kernels, at least three types of devices are suitable for that:
We'll describe the loopback device method:
1) make sure loopback block devices are configured into the kernel
- 2) create an empty file system of the appropriate size, e.g.
- # dd if=/dev/zero of=initrd bs=300k count=1
- # mke2fs -F -m0 initrd
+ 2) create an empty file system of the appropriate size, e.g.::
+
+ # dd if=/dev/zero of=initrd bs=300k count=1
+ # mke2fs -F -m0 initrd
+
(if space is critical, you may want to use the Minix FS instead of Ext2)
- 3) mount the file system, e.g.
- # mount -t ext2 -o loop initrd /mnt
- 4) create the console device:
+ 3) mount the file system, e.g.::
+
+ # mount -t ext2 -o loop initrd /mnt
+
+ 4) create the console device::
+
# mkdir /mnt/dev
# mknod /mnt/dev/console c 5 1
+
5) copy all the files that are needed to properly use the initrd
- environment. Don't forget the most important file, /sbin/init
- Note that /sbin/init's permissions must include "x" (execute).
+ environment. Don't forget the most important file, ``/sbin/init``
+
+ .. note:: ``/sbin/init`` permissions must include "x" (execute).
+
6) correct operation the initrd environment can frequently be tested
- even without rebooting with the command
- # chroot /mnt /sbin/init
+ even without rebooting with the command::
+
+ # chroot /mnt /sbin/init
+
This is of course limited to initrds that do not interfere with the
general system state (e.g. by reconfiguring network interfaces,
overwriting mounted devices, trying to start already running demons,
etc. Note however that it is usually possible to use pivot_root in
such a chroot'ed initrd environment.)
- 7) unmount the file system
- # umount /mnt
+ 7) unmount the file system::
+
+ # umount /mnt
+
8) the initrd is now in the file "initrd". Optionally, it can now be
- compressed
- # gzip -9 initrd
+ compressed::
+
+ # gzip -9 initrd
For experimenting with initrd, you may want to take a rescue floppy and
-only add a symbolic link from /sbin/init to /bin/sh. Alternatively, you
-can try the experimental newlib environment [2] to create a small
+only add a symbolic link from ``/sbin/init`` to ``/bin/sh``. Alternatively, you
+can try the experimental newlib environment [#f2]_ to create a small
initrd.
Finally, you have to boot the kernel and load initrd. Almost all Linux
boot loaders support initrd. Since the boot process is still compatible
with an older mechanism, the following boot command line parameters
-have to be given:
+have to be given::
root=/dev/ram0 rw
(rw is only necessary if writing to the initrd file system.)
-With LOADLIN, you simply execute
+With LOADLIN, you simply execute::
LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
-With LILO, you add the option INITRD=<path> to either the global section
-or to the section of the respective kernel in /etc/lilo.conf, and pass
-the options using APPEND, e.g.
+e.g.::
+
+ LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
+
+With LILO, you add the option ``INITRD=<path>`` to either the global section
+or to the section of the respective kernel in ``/etc/lilo.conf``, and pass
+the options using APPEND, e.g.::
image = /bzImage
initrd = /boot/initrd.gz
append = "root=/dev/ram0 rw"
-and run /sbin/lilo
+and run ``/sbin/lilo``
For other boot loaders, please refer to the respective documentation.
@@ -204,33 +220,33 @@ The procedure involves the following steps:
- unmounting the initrd file system and de-allocating the RAM disk
Mounting the new root file system is easy: it just needs to be mounted on
-a directory under the current root. Example:
+a directory under the current root. Example::
-# mkdir /new-root
-# mount -o ro /dev/hda1 /new-root
+ # mkdir /new-root
+ # mount -o ro /dev/hda1 /new-root
The root change is accomplished with the pivot_root system call, which
-is also available via the pivot_root utility (see pivot_root(8) man
-page; pivot_root is distributed with util-linux version 2.10h or higher
-[3]). pivot_root moves the current root to a directory under the new
+is also available via the ``pivot_root`` utility (see :manpage:`pivot_root(8)`
+man page; ``pivot_root`` is distributed with util-linux version 2.10h or higher
+[#f3]_). ``pivot_root`` moves the current root to a directory under the new
root, and puts the new root at its place. The directory for the old root
-must exist before calling pivot_root. Example:
+must exist before calling ``pivot_root``. Example::
-# cd /new-root
-# mkdir initrd
-# pivot_root . initrd
+ # cd /new-root
+ # mkdir initrd
+ # pivot_root . initrd
Now, the init process may still access the old root via its
executable, shared libraries, standard input/output/error, and its
current root directory. All these references are dropped by the
-following command:
+following command::
-# exec chroot . what-follows <dev/console >dev/console 2>&1
+ # exec chroot . what-follows <dev/console >dev/console 2>&1
-Where what-follows is a program under the new root, e.g. /sbin/init
+Where what-follows is a program under the new root, e.g. ``/sbin/init``
If the new root file system will be used with udev and has no valid
-/dev directory, udev must be initialized before invoking chroot in order
-to provide /dev/console.
+``/dev`` directory, udev must be initialized before invoking chroot in order
+to provide ``/dev/console``.
Note: implementation details of pivot_root may change with time. In order
to ensure compatibility, the following points should be observed:
@@ -244,13 +260,13 @@ to ensure compatibility, the following points should be observed:
- use relative paths for dev/console in the exec command
Now, the initrd can be unmounted and the memory allocated by the RAM
-disk can be freed:
+disk can be freed::
-# umount /initrd
-# blockdev --flushbufs /dev/ram0
+ # umount /initrd
+ # blockdev --flushbufs /dev/ram0
It is also possible to use initrd with an NFS-mounted root, see the
-pivot_root(8) man page for details.
+:manpage:`pivot_root(8)` man page for details.
Usage scenarios
@@ -263,21 +279,21 @@ as follows:
1) system boots from floppy or other media with a minimal kernel
(e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
loads initrd
- 2) /sbin/init determines what is needed to (1) mount the "real" root FS
+ 2) ``/sbin/init`` determines what is needed to (1) mount the "real" root FS
(i.e. device type, device drivers, file system) and (2) the
distribution media (e.g. CD-ROM, network, tape, ...). This can be
done by asking the user, by auto-probing, or by using a hybrid
approach.
- 3) /sbin/init loads the necessary kernel modules
- 4) /sbin/init creates and populates the root file system (this doesn't
+ 3) ``/sbin/init`` loads the necessary kernel modules
+ 4) ``/sbin/init`` creates and populates the root file system (this doesn't
have to be a very usable system yet)
- 5) /sbin/init invokes pivot_root to change the root file system and
+ 5) ``/sbin/init`` invokes ``pivot_root`` to change the root file system and
execs - via chroot - a program that continues the installation
6) the boot loader is installed
7) the boot loader is configured to load an initrd with the set of
- modules that was used to bring up the system (e.g. /initrd can be
+ modules that was used to bring up the system (e.g. ``/initrd`` can be
modified, then unmounted, and finally, the image is written from
- /dev/ram0 or /dev/rd/0 to a file)
+ ``/dev/ram0`` or ``/dev/rd/0`` to a file)
8) now the system is bootable and additional installation tasks can be
performed
@@ -290,7 +306,7 @@ different hardware configurations in a single administrative domain. In
such cases, it is desirable to generate only a small set of kernels
(ideally only one) and to keep the system-specific part of configuration
information as small as possible. In this case, a common initrd could be
-generated with all the necessary modules. Then, only /sbin/init or a file
+generated with all the necessary modules. Then, only ``/sbin/init`` or a file
read by it would have to be different.
A third scenario is more convenient recovery disks, because information
@@ -301,9 +317,9 @@ auto-detection).
Last not least, CD-ROM distributors may use it for better installation
from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk
-via initrd from CD; or by booting via a loader like LOADLIN or directly
+via initrd from CD; or by booting via a loader like ``LOADLIN`` or directly
from the CD-ROM, and loading the RAM disk from CD without need of
-floppies.
+floppies.
Obsolete root change mechanism
@@ -316,51 +332,52 @@ continued availability.
It works by mounting the "real" root device (i.e. the one set with rdev
in the kernel image or with root=... at the boot command line) as the
root file system when linuxrc exits. The initrd file system is then
-unmounted, or, if it is still busy, moved to a directory /initrd, if
+unmounted, or, if it is still busy, moved to a directory ``/initrd``, if
such a directory exists on the new root file system.
In order to use this mechanism, you do not have to specify the boot
command options root, init, or rw. (If specified, they will affect
the real root file system, not the initrd environment.)
-
+
If /proc is mounted, the "real" root device can be changed from within
linuxrc by writing the number of the new root FS device to the special
-file /proc/sys/kernel/real-root-dev, e.g.
+file /proc/sys/kernel/real-root-dev, e.g.::
# echo 0x301 >/proc/sys/kernel/real-root-dev
Note that the mechanism is incompatible with NFS and similar file
systems.
-This old, deprecated mechanism is commonly called "change_root", while
-the new, supported mechanism is called "pivot_root".
+This old, deprecated mechanism is commonly called ``change_root``, while
+the new, supported mechanism is called ``pivot_root``.
Mixed change_root and pivot_root mechanism
------------------------------------------
-In case you did not want to use root=/dev/ram0 to trigger the pivot_root
-mechanism, you may create both /linuxrc and /sbin/init in your initrd image.
+In case you did not want to use ``root=/dev/ram0`` to trigger the pivot_root
+mechanism, you may create both ``/linuxrc`` and ``/sbin/init`` in your initrd
+image.
-/linuxrc would contain only the following:
+``/linuxrc`` would contain only the following::
-#! /bin/sh
-mount -n -t proc proc /proc
-echo 0x0100 >/proc/sys/kernel/real-root-dev
-umount -n /proc
+ #! /bin/sh
+ mount -n -t proc proc /proc
+ echo 0x0100 >/proc/sys/kernel/real-root-dev
+ umount -n /proc
Once linuxrc exited, the kernel would mount again your initrd as root,
-this time executing /sbin/init. Again, it would be the duty of this init
-to build the right environment (maybe using the root= device passed on
-the cmdline) before the final execution of the real /sbin/init.
+this time executing ``/sbin/init``. Again, it would be the duty of this init
+to build the right environment (maybe using the ``root= device`` passed on
+the cmdline) before the final execution of the real ``/sbin/init``.
Resources
---------
-[1] Almesberger, Werner; "Booting Linux: The History and the Future"
+.. [#f1] Almesberger, Werner; "Booting Linux: The History and the Future"
http://www.almesberger.net/cv/papers/ols2k-9.ps.gz
-[2] newlib package (experimental), with initrd example
- http://sources.redhat.com/newlib/
-[3] util-linux: Miscellaneous utilities for Linux
- http://www.kernel.org/pub/linux/utils/util-linux/
+.. [#f2] newlib package (experimental), with initrd example
+ https://www.sourceware.org/newlib/
+.. [#f3] util-linux: Miscellaneous utilities for Linux
+ https://www.kernel.org/pub/linux/utils/util-linux/
diff --git a/Documentation/java.txt b/Documentation/admin-guide/java.rst
index 418020584ccc..8744e272e6f8 100644
--- a/Documentation/java.txt
+++ b/Documentation/admin-guide/java.rst
@@ -1,5 +1,5 @@
- Java(tm) Binary Kernel Support for Linux v1.03
- ----------------------------------------------
+Java(tm) Binary Kernel Support for Linux v1.03
+----------------------------------------------
Linux beats them ALL! While all other OS's are TALKING about direct
support of Java Binaries in the OS, Linux is doing it!
@@ -19,70 +19,82 @@ other program after you have done the following:
as the application itself).
2) You have to compile BINFMT_MISC either as a module or into
- the kernel (CONFIG_BINFMT_MISC) and set it up properly.
+ the kernel (``CONFIG_BINFMT_MISC``) and set it up properly.
If you choose to compile it as a module, you will have
to insert it manually with modprobe/insmod, as kmod
- cannot easily be supported with binfmt_misc.
+ cannot easily be supported with binfmt_misc.
Read the file 'binfmt_misc.txt' in this directory to know
more about the configuration process.
3) Add the following configuration items to binfmt_misc
- (you should really have read binfmt_misc.txt now):
- support for Java applications:
+ (you should really have read ``binfmt_misc.txt`` now):
+ support for Java applications::
+
':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:'
- support for executable Jar files:
+
+ support for executable Jar files::
+
':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:'
- support for Java Applets:
+
+ support for Java Applets::
+
':Applet:E::html::/usr/bin/appletviewer:'
- or the following, if you want to be more selective:
+
+ or the following, if you want to be more selective::
+
':Applet:M::<!--applet::/usr/bin/appletviewer:'
Of course you have to fix the path names. The path/file names given in this
- document match the Debian 2.1 system. (i.e. jdk installed in /usr,
- custom wrappers from this document in /usr/local)
+ document match the Debian 2.1 system. (i.e. jdk installed in ``/usr``,
+ custom wrappers from this document in ``/usr/local``)
Note, that for the more selective applet support you have to modify
- existing html-files to contain <!--applet--> in the first line
- ('<' has to be the first character!) to let this work!
+ existing html-files to contain ``<!--applet-->`` in the first line
+ (``<`` has to be the first character!) to let this work!
For the compiled Java programs you need a wrapper script like the
following (this is because Java is broken in case of the filename
handling), again fix the path names, both in the script and in the
above given configuration string.
- You, too, need the little program after the script. Compile like
- gcc -O2 -o javaclassname javaclassname.c
- and stick it to /usr/local/bin.
+ You, too, need the little program after the script. Compile like::
+
+ gcc -O2 -o javaclassname javaclassname.c
+
+ and stick it to ``/usr/local/bin``.
Both the javawrapper shellscript and the javaclassname program
were supplied by Colin J. Watson <cjw44@cam.ac.uk>.
-====================== Cut here ===================
-#!/bin/bash
-# /usr/local/bin/javawrapper - the wrapper for binfmt_misc/java
+Javawrapper shell script:
+
+.. code-block:: sh
-if [ -z "$1" ]; then
+ #!/bin/bash
+ # /usr/local/bin/javawrapper - the wrapper for binfmt_misc/java
+
+ if [ -z "$1" ]; then
exec 1>&2
echo Usage: $0 class-file
exit 1
-fi
+ fi
-CLASS=$1
-FQCLASS=`/usr/local/bin/javaclassname $1`
-FQCLASSN=`echo $FQCLASS | sed -e 's/^.*\.\([^.]*\)$/\1/'`
-FQCLASSP=`echo $FQCLASS | sed -e 's-\.-/-g' -e 's-^[^/]*$--' -e 's-/[^/]*$--'`
+ CLASS=$1
+ FQCLASS=`/usr/local/bin/javaclassname $1`
+ FQCLASSN=`echo $FQCLASS | sed -e 's/^.*\.\([^.]*\)$/\1/'`
+ FQCLASSP=`echo $FQCLASS | sed -e 's-\.-/-g' -e 's-^[^/]*$--' -e 's-/[^/]*$--'`
-# for example:
-# CLASS=Test.class
-# FQCLASS=foo.bar.Test
-# FQCLASSN=Test
-# FQCLASSP=foo/bar
+ # for example:
+ # CLASS=Test.class
+ # FQCLASS=foo.bar.Test
+ # FQCLASSN=Test
+ # FQCLASSP=foo/bar
-unset CLASSBASE
+ unset CLASSBASE
-declare -i LINKLEVEL=0
+ declare -i LINKLEVEL=0
-while :; do
+ while :; do
if [ "`basename $CLASS .class`" == "$FQCLASSN" ]; then
# See if this directory works straight off
cd -L `dirname $CLASS`
@@ -119,9 +131,9 @@ while :; do
exit 1
fi
CLASS=`ls --color=no -l $CLASS | sed -e 's/^.* \([^ ]*\)$/\1/'`
-done
+ done
-if [ -z "$CLASSBASE" ]; then
+ if [ -z "$CLASSBASE" ]; then
if [ -z "$FQCLASSP" ]; then
GOODNAME=$FQCLASSN.class
else
@@ -131,96 +143,97 @@ if [ -z "$CLASSBASE" ]; then
echo $0:
echo " $FQCLASS should be in a file called $GOODNAME"
exit 1
-fi
+ fi
-if ! echo $CLASSPATH | grep -q "^\(.*:\)*$CLASSBASE\(:.*\)*"; then
+ if ! echo $CLASSPATH | grep -q "^\(.*:\)*$CLASSBASE\(:.*\)*"; then
# class is not in CLASSPATH, so prepend dir of class to CLASSPATH
if [ -z "${CLASSPATH}" ] ; then
export CLASSPATH=$CLASSBASE
else
export CLASSPATH=$CLASSBASE:$CLASSPATH
fi
-fi
-
-shift
-/usr/bin/java $FQCLASS "$@"
-====================== Cut here ===================
-
-
-====================== Cut here ===================
-/* javaclassname.c
- *
- * Extracts the class name from a Java class file; intended for use in a Java
- * wrapper of the type supported by the binfmt_misc option in the Linux kernel.
- *
- * Copyright (C) 1999 Colin J. Watson <cjw44@cam.ac.uk>.
- *
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <sys/types.h>
-
-/* From Sun's Java VM Specification, as tag entries in the constant pool. */
-
-#define CP_UTF8 1
-#define CP_INTEGER 3
-#define CP_FLOAT 4
-#define CP_LONG 5
-#define CP_DOUBLE 6
-#define CP_CLASS 7
-#define CP_STRING 8
-#define CP_FIELDREF 9
-#define CP_METHODREF 10
-#define CP_INTERFACEMETHODREF 11
-#define CP_NAMEANDTYPE 12
-#define CP_METHODHANDLE 15
-#define CP_METHODTYPE 16
-#define CP_INVOKEDYNAMIC 18
-
-/* Define some commonly used error messages */
-
-#define seek_error() error("%s: Cannot seek\n", program)
-#define corrupt_error() error("%s: Class file corrupt\n", program)
-#define eof_error() error("%s: Unexpected end of file\n", program)
-#define utf8_error() error("%s: Only ASCII 1-255 supported\n", program);
-
-char *program;
-
-long *pool;
-
-u_int8_t read_8(FILE *classfile);
-u_int16_t read_16(FILE *classfile);
-void skip_constant(FILE *classfile, u_int16_t *cur);
-void error(const char *format, ...);
-int main(int argc, char **argv);
-
-/* Reads in an unsigned 8-bit integer. */
-u_int8_t read_8(FILE *classfile)
-{
+ fi
+
+ shift
+ /usr/bin/java $FQCLASS "$@"
+
+javaclassname.c:
+
+.. code-block:: c
+
+ /* javaclassname.c
+ *
+ * Extracts the class name from a Java class file; intended for use in a Java
+ * wrapper of the type supported by the binfmt_misc option in the Linux kernel.
+ *
+ * Copyright (C) 1999 Colin J. Watson <cjw44@cam.ac.uk>.
+ *
+ * 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 <stdlib.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <sys/types.h>
+
+ /* From Sun's Java VM Specification, as tag entries in the constant pool. */
+
+ #define CP_UTF8 1
+ #define CP_INTEGER 3
+ #define CP_FLOAT 4
+ #define CP_LONG 5
+ #define CP_DOUBLE 6
+ #define CP_CLASS 7
+ #define CP_STRING 8
+ #define CP_FIELDREF 9
+ #define CP_METHODREF 10
+ #define CP_INTERFACEMETHODREF 11
+ #define CP_NAMEANDTYPE 12
+ #define CP_METHODHANDLE 15
+ #define CP_METHODTYPE 16
+ #define CP_INVOKEDYNAMIC 18
+
+ /* Define some commonly used error messages */
+
+ #define seek_error() error("%s: Cannot seek\n", program)
+ #define corrupt_error() error("%s: Class file corrupt\n", program)
+ #define eof_error() error("%s: Unexpected end of file\n", program)
+ #define utf8_error() error("%s: Only ASCII 1-255 supported\n", program);
+
+ char *program;
+
+ long *pool;
+
+ u_int8_t read_8(FILE *classfile);
+ u_int16_t read_16(FILE *classfile);
+ void skip_constant(FILE *classfile, u_int16_t *cur);
+ void error(const char *format, ...);
+ int main(int argc, char **argv);
+
+ /* Reads in an unsigned 8-bit integer. */
+ u_int8_t read_8(FILE *classfile)
+ {
int b = fgetc(classfile);
if(b == EOF)
eof_error();
return (u_int8_t)b;
-}
+ }
-/* Reads in an unsigned 16-bit integer. */
-u_int16_t read_16(FILE *classfile)
-{
+ /* Reads in an unsigned 16-bit integer. */
+ u_int16_t read_16(FILE *classfile)
+ {
int b1, b2;
b1 = fgetc(classfile);
if(b1 == EOF)
@@ -229,11 +242,11 @@ u_int16_t read_16(FILE *classfile)
if(b2 == EOF)
eof_error();
return (u_int16_t)((b1 << 8) | b2);
-}
+ }
-/* Reads in a value from the constant pool. */
-void skip_constant(FILE *classfile, u_int16_t *cur)
-{
+ /* Reads in a value from the constant pool. */
+ void skip_constant(FILE *classfile, u_int16_t *cur)
+ {
u_int16_t len;
int seekerr = 1;
pool[*cur] = ftell(classfile);
@@ -270,19 +283,19 @@ void skip_constant(FILE *classfile, u_int16_t *cur)
}
if(seekerr)
seek_error();
-}
+ }
-void error(const char *format, ...)
-{
+ void error(const char *format, ...)
+ {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
exit(1);
-}
+ }
-int main(int argc, char **argv)
-{
+ int main(int argc, char **argv)
+ {
FILE *classfile;
u_int16_t cp_count, i, this_class, classinfo_ptr;
u_int8_t length;
@@ -349,19 +362,19 @@ int main(int argc, char **argv)
free(pool);
fclose(classfile);
return 0;
-}
-====================== Cut here ===================
+ }
+
+jarwrapper::
+ #!/bin/bash
+ # /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
-====================== Cut here ===================
-#!/bin/bash
-# /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
+ java -jar $1
-java -jar $1
-====================== Cut here ===================
+Now simply ``chmod +x`` the ``.class``, ``.jar`` and/or ``.html`` files you
+want to execute.
-Now simply chmod +x the .class, .jar and/or .html files you want to execute.
To add a Java program to your path best put a symbolic link to the main
.class file into /usr/bin (or another place you like) omitting the .class
extension. The directory containing the original .class file will be
@@ -371,29 +384,36 @@ added to your CLASSPATH during execution.
To test your new setup, enter in the following simple Java app, and name
it "HelloWorld.java":
+.. code-block:: java
+
class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World!");
}
}
-Now compile the application with:
+Now compile the application with::
+
javac HelloWorld.java
-Set the executable permissions of the binary file, with:
+Set the executable permissions of the binary file, with::
+
chmod 755 HelloWorld.class
-And then execute it:
+And then execute it::
+
./HelloWorld.class
-To execute Java Jar files, simple chmod the *.jar files to include
-the execution bit, then just do
+To execute Java Jar files, simple chmod the ``*.jar`` files to include
+the execution bit, then just do::
+
./Application.jar
-To execute Java Applets, simple chmod the *.html files to include
-the execution bit, then just do
+To execute Java Applets, simple chmod the ``*.html`` files to include
+the execution bit, then just do::
+
./Applet.html
@@ -401,4 +421,3 @@ originally by Brian A. Lantz, brian@lantz.com
heavily edited for binfmt_misc by Richard Günther
new scripts by Colin J. Watson <cjw44@cam.ac.uk>
added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>
-
diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst
new file mode 100644
index 000000000000..b516164999a8
--- /dev/null
+++ b/Documentation/admin-guide/kernel-parameters.rst
@@ -0,0 +1,209 @@
+The kernel's command-line parameters
+====================================
+
+The following is a consolidated list of the kernel parameters as
+implemented by the __setup(), core_param() and module_param() macros
+and sorted into English Dictionary order (defined as ignoring all
+punctuation and sorting digits before letters in a case insensitive
+manner), and with descriptions where known.
+
+The kernel parses parameters from the kernel command line up to "--";
+if it doesn't recognize a parameter and it doesn't contain a '.', the
+parameter gets passed to init: parameters with '=' go into init's
+environment, others are passed as command line arguments to init.
+Everything after "--" is passed as an argument to init.
+
+Module parameters can be specified in two ways: via the kernel command
+line with a module name prefix, or via modprobe, e.g.::
+
+ (kernel command line) usbcore.blinkenlights=1
+ (modprobe command line) modprobe usbcore blinkenlights=1
+
+Parameters for modules which are built into the kernel need to be
+specified on the kernel command line. modprobe looks through the
+kernel command line (/proc/cmdline) and collects module parameters
+when it loads a module, so the kernel command line can be used for
+loadable modules too.
+
+Hyphens (dashes) and underscores are equivalent in parameter names, so::
+
+ log_buf_len=1M print-fatal-signals=1
+
+can also be entered as::
+
+ log-buf-len=1M print_fatal_signals=1
+
+Double-quotes can be used to protect spaces in values, e.g.::
+
+ param="spaces in here"
+
+cpu lists:
+----------
+
+Some kernel parameters take a list of CPUs as a value, e.g. isolcpus,
+nohz_full, irqaffinity, rcu_nocbs. The format of this list is:
+
+ <cpu number>,...,<cpu number>
+
+or
+
+ <cpu number>-<cpu number>
+ (must be a positive range in ascending order)
+
+or a mixture
+
+<cpu number>,...,<cpu number>-<cpu number>
+
+Note that for the special case of a range one can split the range into equal
+sized groups and for each group use some amount from the beginning of that
+group:
+
+ <cpu number>-cpu number>:<used size>/<group size>
+
+For example one can add to the command line following parameter:
+
+ isolcpus=1,2,10-20,100-2000:2/25
+
+where the final item represents CPUs 100,101,125,126,150,151,...
+
+
+
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+``echo -n ${value} > /sys/module/${modulename}/parameters/${parm}``.
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable::
+
+ ACPI ACPI support is enabled.
+ AGP AGP (Accelerated Graphics Port) is enabled.
+ ALSA ALSA sound support is enabled.
+ APIC APIC support is enabled.
+ APM Advanced Power Management support is enabled.
+ ARM ARM architecture is enabled.
+ AVR32 AVR32 architecture is enabled.
+ AX25 Appropriate AX.25 support is enabled.
+ BLACKFIN Blackfin architecture is enabled.
+ CLK Common clock infrastructure is enabled.
+ CMA Contiguous Memory Area support is enabled.
+ DRM Direct Rendering Management support is enabled.
+ DYNAMIC_DEBUG Build in debug messages and enable them at runtime
+ EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
+ EFI EFI Partitioning (GPT) is enabled
+ EIDE EIDE/ATAPI support is enabled.
+ EVM Extended Verification Module
+ FB The frame buffer device is enabled.
+ FTRACE Function tracing enabled.
+ GCOV GCOV profiling is enabled.
+ HW Appropriate hardware is enabled.
+ IA-64 IA-64 architecture is enabled.
+ IMA Integrity measurement architecture is enabled.
+ IOSCHED More than one I/O scheduler is enabled.
+ IP_PNP IP DHCP, BOOTP, or RARP is enabled.
+ IPV6 IPv6 support is enabled.
+ ISAPNP ISA PnP code is enabled.
+ ISDN Appropriate ISDN support is enabled.
+ JOY Appropriate joystick support is enabled.
+ KGDB Kernel debugger support is enabled.
+ KVM Kernel Virtual Machine support is enabled.
+ LIBATA Libata driver is enabled
+ LP Printer support is enabled.
+ LOOP Loopback device support is enabled.
+ M68k M68k architecture is enabled.
+ These options have more detailed description inside of
+ Documentation/m68k/kernel-options.txt.
+ MDA MDA console support is enabled.
+ MIPS MIPS architecture is enabled.
+ MOUSE Appropriate mouse support is enabled.
+ MSI Message Signaled Interrupts (PCI).
+ MTD MTD (Memory Technology Device) support is enabled.
+ NET Appropriate network support is enabled.
+ NUMA NUMA support is enabled.
+ NFS Appropriate NFS support is enabled.
+ OSS OSS sound support is enabled.
+ PV_OPS A paravirtualized kernel is enabled.
+ PARIDE The ParIDE (parallel port IDE) subsystem is enabled.
+ PARISC The PA-RISC architecture is enabled.
+ PCI PCI bus support is enabled.
+ PCIE PCI Express support is enabled.
+ PCMCIA The PCMCIA subsystem is enabled.
+ PNP Plug & Play support is enabled.
+ PPC PowerPC architecture is enabled.
+ PPT Parallel port support is enabled.
+ PS2 Appropriate PS/2 support is enabled.
+ RAM RAM disk support is enabled.
+ S390 S390 architecture is enabled.
+ SCSI Appropriate SCSI support is enabled.
+ A lot of drivers have their options described inside
+ the Documentation/scsi/ sub-directory.
+ SECURITY Different security models are enabled.
+ SELINUX SELinux support is enabled.
+ APPARMOR AppArmor support is enabled.
+ SERIAL Serial support is enabled.
+ SH SuperH architecture is enabled.
+ SMP The kernel is an SMP kernel.
+ SPARC Sparc architecture is enabled.
+ SWSUSP Software suspend (hibernation) is enabled.
+ SUSPEND System suspend states are enabled.
+ TPM TPM drivers are enabled.
+ TS Appropriate touchscreen support is enabled.
+ UMS USB Mass Storage support is enabled.
+ USB USB support is enabled.
+ USBHID USB Human Interface Device support is enabled.
+ V4L Video For Linux support is enabled.
+ VMMIO Driver for memory mapped virtio devices is enabled.
+ VGA The VGA console has been enabled.
+ VT Virtual terminal support is enabled.
+ WDT Watchdog support is enabled.
+ XT IBM PC/XT MFM hard disk support is enabled.
+ X86-32 X86-32, aka i386 architecture is enabled.
+ X86-64 X86-64 architecture is enabled.
+ More X86-64 boot options can be found in
+ Documentation/x86/x86_64/boot-options.txt .
+ X86 Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
+ X86_UV SGI UV support is enabled.
+ XEN Xen support is enabled
+
+In addition, the following text indicates that the option::
+
+ BUGS= Relates to possible processor bugs on the said processor.
+ KNL Is a kernel start-up parameter.
+ BOOT Is a boot loader parameter.
+
+Parameters denoted with BOOT are actually interpreted by the boot
+loader, and have no meaning to the kernel directly.
+Do not modify the syntax of boot loader parameters without extreme
+need or coordination with <Documentation/x86/boot.txt>.
+
+There are also arch-specific kernel-parameters not documented here.
+See for example <Documentation/x86/x86_64/boot-options.txt>.
+
+Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
+a trailing = on the name of any parameter states that that parameter will
+be entered as an environment variable, whereas its absence indicates that
+it will appear as a kernel argument readable via /proc/cmdline by programs
+running once the system is up.
+
+The number of kernel parameters is not limited, but the length of the
+complete command line (parameters including spaces etc.) is limited to
+a fixed number of characters. This limit depends on the architecture
+and is between 256 and 4096 characters. It is defined in the file
+./include/asm/setup.h as COMMAND_LINE_SIZE.
+
+Finally, the [KMG] suffix is commonly described after a number of kernel
+parameter values. These 'K', 'M', and 'G' letters represent the _binary_
+multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
+bytes respectively. Such letter suffixes can also be entirely omitted:
+
+.. include:: kernel-parameters.txt
+ :literal:
+
+Todo
+----
+
+ Add more DRM drivers.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 37babf91f2cb..be2d6d0a03a4 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1,202 +1,3 @@
- Kernel Parameters
- ~~~~~~~~~~~~~~~~~
-
-The following is a consolidated list of the kernel parameters as
-implemented by the __setup(), core_param() and module_param() macros
-and sorted into English Dictionary order (defined as ignoring all
-punctuation and sorting digits before letters in a case insensitive
-manner), and with descriptions where known.
-
-The kernel parses parameters from the kernel command line up to "--";
-if it doesn't recognize a parameter and it doesn't contain a '.', the
-parameter gets passed to init: parameters with '=' go into init's
-environment, others are passed as command line arguments to init.
-Everything after "--" is passed as an argument to init.
-
-Module parameters can be specified in two ways: via the kernel command
-line with a module name prefix, or via modprobe, e.g.:
-
- (kernel command line) usbcore.blinkenlights=1
- (modprobe command line) modprobe usbcore blinkenlights=1
-
-Parameters for modules which are built into the kernel need to be
-specified on the kernel command line. modprobe looks through the
-kernel command line (/proc/cmdline) and collects module parameters
-when it loads a module, so the kernel command line can be used for
-loadable modules too.
-
-Hyphens (dashes) and underscores are equivalent in parameter names, so
- log_buf_len=1M print-fatal-signals=1
-can also be entered as
- log-buf-len=1M print_fatal_signals=1
-
-Double-quotes can be used to protect spaces in values, e.g.:
- param="spaces in here"
-
-cpu lists:
-----------
-
-Some kernel parameters take a list of CPUs as a value, e.g. isolcpus,
-nohz_full, irqaffinity, rcu_nocbs. The format of this list is:
-
- <cpu number>,...,<cpu number>
-
-or
-
- <cpu number>-<cpu number>
- (must be a positive range in ascending order)
-
-or a mixture
-
-<cpu number>,...,<cpu number>-<cpu number>
-
-Note that for the special case of a range one can split the range into equal
-sized groups and for each group use some amount from the beginning of that
-group:
-
- <cpu number>-cpu number>:<used size>/<group size>
-
-For example one can add to the command line following parameter:
-
- isolcpus=1,2,10-20,100-2000:2/25
-
-where the final item represents CPUs 100,101,125,126,150,151,...
-
-
-
-This document may not be entirely up to date and comprehensive. The command
-"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
-module. Loadable modules, after being loaded into the running kernel, also
-reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
-parameters may be changed at runtime by the command
-"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
-
-The parameters listed below are only valid if certain kernel build options were
-enabled and if respective hardware is present. The text in square brackets at
-the beginning of each description states the restrictions within which a
-parameter is applicable:
-
- ACPI ACPI support is enabled.
- AGP AGP (Accelerated Graphics Port) is enabled.
- ALSA ALSA sound support is enabled.
- APIC APIC support is enabled.
- APM Advanced Power Management support is enabled.
- ARM ARM architecture is enabled.
- AVR32 AVR32 architecture is enabled.
- AX25 Appropriate AX.25 support is enabled.
- BLACKFIN Blackfin architecture is enabled.
- CLK Common clock infrastructure is enabled.
- CMA Contiguous Memory Area support is enabled.
- DRM Direct Rendering Management support is enabled.
- DYNAMIC_DEBUG Build in debug messages and enable them at runtime
- EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
- EFI EFI Partitioning (GPT) is enabled
- EIDE EIDE/ATAPI support is enabled.
- EVM Extended Verification Module
- FB The frame buffer device is enabled.
- FTRACE Function tracing enabled.
- GCOV GCOV profiling is enabled.
- HW Appropriate hardware is enabled.
- IA-64 IA-64 architecture is enabled.
- IMA Integrity measurement architecture is enabled.
- IOSCHED More than one I/O scheduler is enabled.
- IP_PNP IP DHCP, BOOTP, or RARP is enabled.
- IPV6 IPv6 support is enabled.
- ISAPNP ISA PnP code is enabled.
- ISDN Appropriate ISDN support is enabled.
- JOY Appropriate joystick support is enabled.
- KGDB Kernel debugger support is enabled.
- KVM Kernel Virtual Machine support is enabled.
- LIBATA Libata driver is enabled
- LP Printer support is enabled.
- LOOP Loopback device support is enabled.
- M68k M68k architecture is enabled.
- These options have more detailed description inside of
- Documentation/m68k/kernel-options.txt.
- MDA MDA console support is enabled.
- MIPS MIPS architecture is enabled.
- MOUSE Appropriate mouse support is enabled.
- MSI Message Signaled Interrupts (PCI).
- MTD MTD (Memory Technology Device) support is enabled.
- NET Appropriate network support is enabled.
- NUMA NUMA support is enabled.
- NFS Appropriate NFS support is enabled.
- OSS OSS sound support is enabled.
- PV_OPS A paravirtualized kernel is enabled.
- PARIDE The ParIDE (parallel port IDE) subsystem is enabled.
- PARISC The PA-RISC architecture is enabled.
- PCI PCI bus support is enabled.
- PCIE PCI Express support is enabled.
- PCMCIA The PCMCIA subsystem is enabled.
- PNP Plug & Play support is enabled.
- PPC PowerPC architecture is enabled.
- PPT Parallel port support is enabled.
- PS2 Appropriate PS/2 support is enabled.
- RAM RAM disk support is enabled.
- S390 S390 architecture is enabled.
- SCSI Appropriate SCSI support is enabled.
- A lot of drivers have their options described inside
- the Documentation/scsi/ sub-directory.
- SECURITY Different security models are enabled.
- SELINUX SELinux support is enabled.
- APPARMOR AppArmor support is enabled.
- SERIAL Serial support is enabled.
- SH SuperH architecture is enabled.
- SMP The kernel is an SMP kernel.
- SPARC Sparc architecture is enabled.
- SWSUSP Software suspend (hibernation) is enabled.
- SUSPEND System suspend states are enabled.
- TPM TPM drivers are enabled.
- TS Appropriate touchscreen support is enabled.
- UMS USB Mass Storage support is enabled.
- USB USB support is enabled.
- USBHID USB Human Interface Device support is enabled.
- V4L Video For Linux support is enabled.
- VMMIO Driver for memory mapped virtio devices is enabled.
- VGA The VGA console has been enabled.
- VT Virtual terminal support is enabled.
- WDT Watchdog support is enabled.
- XT IBM PC/XT MFM hard disk support is enabled.
- X86-32 X86-32, aka i386 architecture is enabled.
- X86-64 X86-64 architecture is enabled.
- More X86-64 boot options can be found in
- Documentation/x86/x86_64/boot-options.txt .
- X86 Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
- X86_UV SGI UV support is enabled.
- XEN Xen support is enabled
-
-In addition, the following text indicates that the option:
-
- BUGS= Relates to possible processor bugs on the said processor.
- KNL Is a kernel start-up parameter.
- BOOT Is a boot loader parameter.
-
-Parameters denoted with BOOT are actually interpreted by the boot
-loader, and have no meaning to the kernel directly.
-Do not modify the syntax of boot loader parameters without extreme
-need or coordination with <Documentation/x86/boot.txt>.
-
-There are also arch-specific kernel-parameters not documented here.
-See for example <Documentation/x86/x86_64/boot-options.txt>.
-
-Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
-a trailing = on the name of any parameter states that that parameter will
-be entered as an environment variable, whereas its absence indicates that
-it will appear as a kernel argument readable via /proc/cmdline by programs
-running once the system is up.
-
-The number of kernel parameters is not limited, but the length of the
-complete command line (parameters including spaces etc.) is limited to
-a fixed number of characters. This limit depends on the architecture
-and is between 256 and 4096 characters. It is defined in the file
-./include/asm/setup.h as COMMAND_LINE_SIZE.
-
-Finally, the [KMG] suffix is commonly described after a number of kernel
-parameter values. These 'K', 'M', and 'G' letters represent the _binary_
-multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
-bytes respectively. Such letter suffixes can also be entirely omitted.
-
-
acpi= [HW,ACPI,X86,ARM64]
Advanced Configuration and Power Interface
Format: { force | on | off | strict | noirq | rsdt |
@@ -811,7 +612,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bits, and "f" is flow control ("r" for RTS or
omit it). Default is "9600n8".
- See Documentation/serial-console.txt for more
+ See Documentation/admin-guide/serial-console.rst for more
information. See
Documentation/networking/netconsole.txt for an
alternative.
@@ -1062,6 +863,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
dscc4.setup= [NET]
+ dump_apple_properties [X86]
+ Dump name and content of EFI device properties on
+ x86 Macs. Useful for driver authors to determine
+ what data is available or for reverse-engineering.
+
dyndbg[="val"] [KNL,DYNAMIC_DEBUG]
module.dyndbg[="val"]
Enable debug messages at boot time. See
@@ -1074,12 +880,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
nopku [X86] Disable Memory Protection Keys CPU feature found
in some Intel CPUs.
- eagerfpu= [X86]
- on enable eager fpu restore
- off disable eager fpu restore
- auto selects the default scheme, which automatically
- enables eagerfpu restore for xsaveopt.
-
module.async_probe [KNL]
Enable asynchronous probe on this module.
@@ -1760,6 +1560,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
disable
Do not enable intel_pstate as the default
scaling driver for the supported processors
+ passive
+ Use intel_pstate as a scaling driver, but configure it
+ to work with generic cpufreq governors (instead of
+ enabling its internal governor). This mode cannot be
+ used along with the hardware-managed P-states (HWP)
+ feature.
force
Enable intel_pstate on systems that prohibit it by default
in favor of acpi-cpufreq. Forcing the intel_pstate driver
@@ -1780,6 +1586,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Description Table, specifies preferred power management
profile as "Enterprise Server" or "Performance Server",
then this feature is turned on by default.
+ per_cpu_perf_limits
+ Allow per-logical-CPU P-State performance control limits using
+ cpufreq sysfs interface
intremap= [X86-64, Intel-IOMMU]
on enable Interrupt Remapping (default)
@@ -1958,9 +1767,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
kmemcheck=2 (one-shot mode)
Default: 2 (one-shot mode)
- kstack=N [X86] Print N words from the kernel stack
- in oops dumps.
-
kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
Default is 0 (don't ignore, but inject #GP)
@@ -2235,7 +2041,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
mce=option [X86-64] See Documentation/x86/x86_64/boot-options.txt
md= [HW] RAID subsystems devices and level
- See Documentation/md.txt.
+ See Documentation/admin-guide/md.rst.
mdacon= [MDA]
Format: <first>,<last>
@@ -2325,6 +2131,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
memory contents and reserves bad memory
regions that are detected.
+ mem_sleep_default= [SUSPEND] Default system suspend mode:
+ s2idle - Suspend-To-Idle
+ shallow - Power-On Suspend or equivalent (if supported)
+ deep - Suspend-To-RAM or equivalent (if supported)
+ See Documentation/power/states.txt.
+
meye.*= [HW] Set MotionEye Camera parameters
See Documentation/video4linux/meye.txt.
@@ -2401,7 +2213,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
that the amount of memory usable for all allocations
is not too small.
- movable_node [KNL,X86] Boot-time switch to enable the effects
+ movable_node [KNL] Boot-time switch to enable the effects
of CONFIG_MOVABLE_NODE=y. See mm/Kconfig for details.
MTD_Partition= [MTD]
@@ -2545,7 +2357,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
will be sent.
The default is to send the implementation identification
information.
-
+
nfs.recover_lost_locks =
[NFSv4] Attempt to recover locks that were lost due
to a lease timeout on the server. Please note that
@@ -2754,6 +2566,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
no-kvmapf [X86,KVM] Disable paravirtualized asynchronous page
fault handling.
+ no-vmw-sched-clock
+ [X86,PV_OPS] Disable paravirtualized VMware scheduler
+ clock and use the default one.
+
no-steal-acc [X86,KVM] Disable paravirtualized steal time accounting.
steal time is computed, but won't influence scheduler
behaviour
@@ -3235,6 +3051,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
may be specified.
Format: <port>,<port>....
+ powersave=off [PPC] This option disables power saving features.
+ It specifically disables cpuidle and sets the
+ platform machine description specific power_save
+ function to NULL. On Idle the CPU just reduces
+ execution priority.
+
ppc_strict_facility_enable
[PPC] This option catches any kernel floating point,
Altivec, VSX and SPE outside of regions specifically
@@ -3318,7 +3140,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
r128= [HW,DRM]
raid= [HW,RAID]
- See Documentation/md.txt.
+ See Documentation/admin-guide/md.rst.
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
See Documentation/blockdev/ramdisk.txt.
@@ -3668,13 +3490,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[KNL, SMP] Set scheduler's default relax_domain_level.
See Documentation/cgroup-v1/cpusets.txt.
- relative_sleep_states=
- [SUSPEND] Use sleep state labeling where the deepest
- state available other than hibernation is always "mem".
- Format: { "0" | "1" }
- 0 -- Traditional sleep state labels.
- 1 -- Relative sleep state labels.
-
reserve= [KNL,BUGS] Force the kernel to ignore some iomem area
reservetop= [X86-32]
@@ -3824,12 +3639,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
shapers= [NET]
Maximal number of shapers.
- show_msr= [x86] show boot-time MSR settings
- Format: { <integer> }
- Show boot-time (BIOS-initialized) MSR settings.
- The parameter means the number of CPUs to show,
- for example 1 means boot CPU only.
-
simeth= [IA-64]
simscsi=
@@ -4197,7 +4006,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
See also Documentation/input/joystick-parport.txt
udbg-immortal [PPC] When debugging early kernel crashes that
- happen after console_init() and before a proper
+ happen after console_init() and before a proper
console driver takes over, this boot options might
help "seeing" what's going on.
@@ -4564,9 +4373,3 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
xirc2ps_cs= [NET,PCMCIA]
Format:
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
-
-______________________________________________________________________
-
-TODO:
-
- Add more DRM drivers.
diff --git a/Documentation/md.txt b/Documentation/admin-guide/md.rst
index d6e2fcf27337..e449fb5f277c 100644
--- a/Documentation/md.txt
+++ b/Documentation/admin-guide/md.rst
@@ -1,42 +1,77 @@
-Tools that manage md devices can be found at
- http://www.kernel.org/pub/linux/utils/raid/
-
+RAID arrays
+===========
Boot time assembly of RAID arrays
---------------------------------
+Tools that manage md devices can be found at
+ http://www.kernel.org/pub/linux/utils/raid/
+
+
You can boot with your md device with the following kernel command
lines:
-for old raid arrays without persistent superblocks:
+for old raid arrays without persistent superblocks::
+
md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
-for raid arrays with persistent superblocks
+for raid arrays with persistent superblocks::
+
md=<md device no.>,dev0,dev1,...,devn
-or, to assemble a partitionable array:
+
+or, to assemble a partitionable array::
+
md=d<md device no.>,dev0,dev1,...,devn
-
-md device no. = the number of the md device ...
- 0 means md0,
- 1 md1,
- 2 md2,
- 3 md3,
- 4 md4
-
-raid level = -1 linear mode
- 0 striped mode
- other modes are only supported with persistent super blocks
-
-chunk size factor = (raid-0 and raid-1 only)
- Set the chunk size as 4k << n.
-
-fault level = totally ignored
-
-dev0-devn: e.g. /dev/hda1,/dev/hdc1,/dev/sda1,/dev/sdb1
-
-A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>) looks like this:
-
-e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
+
+``md device no.``
++++++++++++++++++
+
+The number of the md device
+
+================= =========
+``md device no.`` device
+================= =========
+ 0 md0
+ 1 md1
+ 2 md2
+ 3 md3
+ 4 md4
+================= =========
+
+``raid level``
+++++++++++++++
+
+level of the RAID array
+
+=============== =============
+``raid level`` level
+=============== =============
+-1 linear mode
+0 striped mode
+=============== =============
+
+other modes are only supported with persistent super blocks
+
+``chunk size factor``
++++++++++++++++++++++
+
+(raid-0 and raid-1 only)
+
+Set the chunk size as 4k << n.
+
+``fault level``
++++++++++++++++
+
+Totally ignored
+
+``dev0`` to ``devn``
+++++++++++++++++++++
+
+e.g. ``/dev/hda1``, ``/dev/hdc1``, ``/dev/sda1``, ``/dev/sdb1``
+
+A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>) looks like this::
+
+ e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
Boot time autodetection of RAID arrays
@@ -45,10 +80,10 @@ Boot time autodetection of RAID arrays
When md is compiled into the kernel (not as module), partitions of
type 0xfd are scanned and automatically assembled into RAID arrays.
This autodetection may be suppressed with the kernel parameter
-"raid=noautodetect". As of kernel 2.6.9, only drives with a type 0
+``raid=noautodetect``. As of kernel 2.6.9, only drives with a type 0
superblock can be autodetected and run at boot time.
-The kernel parameter "raid=partitionable" (or "raid=part") means
+The kernel parameter ``raid=partitionable`` (or ``raid=part``) means
that all auto-detected arrays are assembled as partitionable.
Boot time assembly of degraded/dirty arrays
@@ -56,22 +91,23 @@ Boot time assembly of degraded/dirty arrays
If a raid5 or raid6 array is both dirty and degraded, it could have
undetectable data corruption. This is because the fact that it is
-'dirty' means that the parity cannot be trusted, and the fact that it
+``dirty`` means that the parity cannot be trusted, and the fact that it
is degraded means that some datablocks are missing and cannot reliably
be reconstructed (due to no parity).
For this reason, md will normally refuse to start such an array. This
requires the sysadmin to take action to explicitly start the array
-despite possible corruption. This is normally done with
+despite possible corruption. This is normally done with::
+
mdadm --assemble --force ....
This option is not really available if the array has the root
filesystem on it. In order to support this booting from such an
-array, md supports a module parameter "start_dirty_degraded" which,
+array, md supports a module parameter ``start_dirty_degraded`` which,
when set to 1, bypassed the checks and will allows dirty degraded
arrays to be started.
-So, to boot with a root filesystem of a dirty degraded raid[56], use
+So, to boot with a root filesystem of a dirty degraded raid 5 or 6, use::
md-mod.start_dirty_degraded=1
@@ -80,30 +116,30 @@ Superblock formats
------------------
The md driver can support a variety of different superblock formats.
-Currently, it supports superblock formats "0.90.0" and the "md-1" format
+Currently, it supports superblock formats ``0.90.0`` and the ``md-1`` format
introduced in the 2.5 development series.
The kernel will autodetect which format superblock is being used.
-Superblock format '0' is treated differently to others for legacy
+Superblock format ``0`` is treated differently to others for legacy
reasons - it is the original superblock format.
General Rules - apply for all superblock formats
------------------------------------------------
-An array is 'created' by writing appropriate superblocks to all
+An array is ``created`` by writing appropriate superblocks to all
devices.
-It is 'assembled' by associating each of these devices with an
+It is ``assembled`` by associating each of these devices with an
particular md virtual device. Once it is completely assembled, it can
be accessed.
An array should be created by a user-space tool. This will write
superblocks to all devices. It will usually mark the array as
-'unclean', or with some devices missing so that the kernel md driver
-can create appropriate redundancy (copying in raid1, parity
-calculation in raid4/5).
+``unclean``, or with some devices missing so that the kernel md driver
+can create appropriate redundancy (copying in raid 1, parity
+calculation in raid 4/5).
When an array is assembled, it is first initialized with the
SET_ARRAY_INFO ioctl. This contains, in particular, a major and minor
@@ -126,13 +162,12 @@ Devices that have failed or are not yet active can be detached from an
array using HOT_REMOVE_DISK.
-Specific Rules that apply to format-0 super block arrays, and
- arrays with no superblock (non-persistent).
--------------------------------------------------------------
+Specific Rules that apply to format-0 super block arrays, and arrays with no superblock (non-persistent)
+--------------------------------------------------------------------------------------------------------
-An array can be 'created' by describing the array (level, chunksize
-etc) in a SET_ARRAY_INFO ioctl. This must have major_version==0 and
-raid_disks != 0.
+An array can be ``created`` by describing the array (level, chunksize
+etc) in a SET_ARRAY_INFO ioctl. This must have ``major_version==0`` and
+``raid_disks != 0``.
Then uninitialized devices can be added with ADD_NEW_DISK. The
structure passed to ADD_NEW_DISK must specify the state of the device
@@ -142,24 +177,26 @@ Once started with RUN_ARRAY, uninitialized spares can be added with
HOT_ADD_DISK.
-
MD devices in sysfs
-------------------
-md devices appear in sysfs (/sys) as regular block devices,
-e.g.
+
+md devices appear in sysfs (``/sys``) as regular block devices,
+e.g.::
+
/sys/block/md0
-Each 'md' device will contain a subdirectory called 'md' which
+Each ``md`` device will contain a subdirectory called ``md`` which
contains further md-specific information about the device.
All md devices contain:
+
level
- a text file indicating the 'raid level'. e.g. raid0, raid1,
+ a text file indicating the ``raid level``. e.g. raid0, raid1,
raid5, linear, multipath, faulty.
If no raid level has been set yet (array is still being
assembled), the value will reflect whatever has been written
to it, which may be a name like the above, or may be a number
- such as '0', '5', etc.
+ such as ``0``, ``5``, etc.
raid_disks
a text file with a simple number indicating the number of devices
@@ -172,10 +209,10 @@ All md devices contain:
A change to this attribute will not be permitted if it would
reduce the size of the array. To reduce the number of drives
in an e.g. raid5, the array size must first be reduced by
- setting the 'array_size' attribute.
+ setting the ``array_size`` attribute.
chunk_size
- This is the size in bytes for 'chunks' and is only relevant to
+ This is the size in bytes for ``chunks`` and is only relevant to
raid levels that involve striping (0,4,5,6,10). The address space
of the array is conceptually divided into chunks and consecutive
chunks are striped onto neighbouring devices.
@@ -183,7 +220,7 @@ All md devices contain:
of 2. This can only be set while assembling an array
layout
- The "layout" for the array for the particular level. This is
+ The ``layout`` for the array for the particular level. This is
simply a number that is interpretted differently by different
levels. It can be written while assembling an array.
@@ -193,22 +230,24 @@ All md devices contain:
devices. Writing a number (in Kilobytes) which is less than
the available size will set the size. Any reconfiguration of the
array (e.g. adding devices) will not cause the size to change.
- Writing the word 'default' will cause the effective size of the
+ Writing the word ``default`` will cause the effective size of the
array to be whatever size is actually available based on
- 'level', 'chunk_size' and 'component_size'.
+ ``level``, ``chunk_size`` and ``component_size``.
This can be used to reduce the size of the array before reducing
the number of devices in a raid4/5/6, or to support external
metadata formats which mandate such clipping.
reshape_position
- This is either "none" or a sector number within the devices of
- the array where "reshape" is up to. If this is set, the three
+ This is either ``none`` or a sector number within the devices of
+ the array where ``reshape`` is up to. If this is set, the three
attributes mentioned above (raid_disks, chunk_size, layout) can
potentially have 2 values, an old and a new value. If these
- values differ, reading the attribute returns
+ values differ, reading the attribute returns::
+
new (old)
- and writing will effect the 'new' value, leaving the 'old'
+
+ and writing will effect the ``new`` value, leaving the ``old``
unchanged.
component_size
@@ -223,9 +262,9 @@ All md devices contain:
metadata_version
This indicates the format that is being used to record metadata
about the array. It can be 0.90 (traditional format), 1.0, 1.1,
- 1.2 (newer format in varying locations) or "none" indicating that
+ 1.2 (newer format in varying locations) or ``none`` indicating that
the kernel isn't managing metadata at all.
- Alternately it can be "external:" followed by a string which
+ Alternately it can be ``external:`` followed by a string which
is set by user-space. This indicates that metadata is managed
by a user-space program. Any device failure or other event that
requires a metadata update will cause array activity to be
@@ -233,9 +272,9 @@ All md devices contain:
resync_start
The point at which resync should start. If no resync is needed,
- this will be a very large number (or 'none' since 2.6.30-rc1). At
+ this will be a very large number (or ``none`` since 2.6.30-rc1). At
array creation it will default to 0, though starting the array as
- 'clean' will set it much larger.
+ ``clean`` will set it much larger.
new_dev
This file can be written but not read. The value written should
@@ -246,10 +285,10 @@ All md devices contain:
safe_mode_delay
When an md array has seen no write requests for a certain period
- of time, it will be marked as 'clean'. When another write
- request arrives, the array is marked as 'dirty' before the write
- commences. This is known as 'safe_mode'.
- The 'certain period' is controlled by this file which stores the
+ of time, it will be marked as ``clean``. When another write
+ request arrives, the array is marked as ``dirty`` before the write
+ commences. This is known as ``safe_mode``.
+ The ``certain period`` is controlled by this file which stores the
period as a number of seconds. The default is 200msec (0.200).
Writing a value of 0 disables safemode.
@@ -260,38 +299,50 @@ All md devices contain:
cannot be explicitly set, and some transitions are not allowed.
Select/poll works on this file. All changes except between
- active_idle and active (which can be frequent and are not
- very interesting) are notified. active->active_idle is
- reported if the metadata is externally managed.
+ Active_idle and active (which can be frequent and are not
+ very interesting) are notified. active->active_idle is
+ reported if the metadata is externally managed.
clear
No devices, no size, no level
+
Writing is equivalent to STOP_ARRAY ioctl
+
inactive
May have some settings, but array is not active
- all IO results in error
+ all IO results in error
+
When written, doesn't tear down array, but just stops it
+
suspended (not supported yet)
All IO requests will block. The array can be reconfigured.
+
Writing this, if accepted, will block until array is quiessent
+
readonly
no resync can happen. no superblocks get written.
- write requests fail
+
+ Write requests fail
+
read-auto
- like readonly, but behaves like 'clean' on a write request.
+ like readonly, but behaves like ``clean`` on a write request.
+
+ clean
+ no pending writes, but otherwise active.
- clean - no pending writes, but otherwise active.
When written to inactive array, starts without resync
+
If a write request arrives then
- if metadata is known, mark 'dirty' and switch to 'active'.
- if not known, block and switch to write-pending
+ if metadata is known, mark ``dirty`` and switch to ``active``.
+ if not known, block and switch to write-pending
+
If written to an active array that has pending writes, then fails.
active
fully active: IO and resync can be happening.
When written to inactive array, starts with resync
write-pending
- clean, but writes are blocked waiting for 'active' to be written.
+ clean, but writes are blocked waiting for ``active`` to be written.
active-idle
like active, but no writes have been seen for a while (safe_mode_delay).
@@ -299,57 +350,71 @@ All md devices contain:
bitmap/location
This indicates where the write-intent bitmap for the array is
stored.
- It can be one of "none", "file" or "[+-]N".
- "file" may later be extended to "file:/file/name"
- "[+-]N" means that many sectors from the start of the metadata.
- This is replicated on all devices. For arrays with externally
- managed metadata, the offset is from the beginning of the
- device.
+
+ It can be one of ``none``, ``file`` or ``[+-]N``.
+ ``file`` may later be extended to ``file:/file/name``
+ ``[+-]N`` means that many sectors from the start of the metadata.
+
+ This is replicated on all devices. For arrays with externally
+ managed metadata, the offset is from the beginning of the
+ device.
+
bitmap/chunksize
The size, in bytes, of the chunk which will be represented by a
single bit. For RAID456, it is a portion of an individual
device. For RAID10, it is a portion of the array. For RAID1, it
is both (they come to the same thing).
+
bitmap/time_base
The time, in seconds, between looking for bits in the bitmap to
be cleared. In the current implementation, a bit will be cleared
- between 2 and 3 times "time_base" after all the covered blocks
+ between 2 and 3 times ``time_base`` after all the covered blocks
are known to be in-sync.
+
bitmap/backlog
When write-mostly devices are active in a RAID1, write requests
to those devices proceed in the background - the filesystem (or
other user of the device) does not have to wait for them.
- 'backlog' sets a limit on the number of concurrent background
+ ``backlog`` sets a limit on the number of concurrent background
writes. If there are more than this, new writes will by
synchronous.
+
bitmap/metadata
- This can be either 'internal' or 'external'.
- 'internal' is the default and means the metadata for the bitmap
- is stored in the first 256 bytes of the allocated space and is
- managed by the md module.
- 'external' means that bitmap metadata is managed externally to
- the kernel (i.e. by some userspace program)
+ This can be either ``internal`` or ``external``.
+
+ ``internal``
+ is the default and means the metadata for the bitmap
+ is stored in the first 256 bytes of the allocated space and is
+ managed by the md module.
+
+ ``external``
+ means that bitmap metadata is managed externally to
+ the kernel (i.e. by some userspace program)
+
bitmap/can_clear
- This is either 'true' or 'false'. If 'true', then bits in the
+ This is either ``true`` or ``false``. If ``true``, then bits in the
bitmap will be cleared when the corresponding blocks are thought
- to be in-sync. If 'false', bits will never be cleared.
- This is automatically set to 'false' if a write happens on a
+ to be in-sync. If ``false``, bits will never be cleared.
+ This is automatically set to ``false`` if a write happens on a
degraded array, or if the array becomes degraded during a write.
When metadata is managed externally, it should be set to true
once the array becomes non-degraded, and this fact has been
recorded in the metadata.
-
-
-
-As component devices are added to an md array, they appear in the 'md'
-directory as new directories named
+
+
+
+As component devices are added to an md array, they appear in the ``md``
+directory as new directories named::
+
dev-XXX
-where XXX is a name that the kernel knows for the device, e.g. hdb1.
+
+where ``XXX`` is a name that the kernel knows for the device, e.g. hdb1.
Each directory contains:
block
- a symlink to the block device in /sys/block, e.g.
+ a symlink to the block device in /sys/block, e.g.::
+
/sys/block/md0/md/dev-hdb1/block -> ../../../../block/hdb/hdb1
super
@@ -358,51 +423,83 @@ Each directory contains:
state
A file recording the current state of the device in the array
- which can be a comma separated list of
- faulty - device has been kicked from active use due to
- a detected fault, or it has unacknowledged bad
- blocks
- in_sync - device is a fully in-sync member of the array
- writemostly - device will only be subject to read
- requests if there are no other options.
- This applies only to raid1 arrays.
- blocked - device has failed, and the failure hasn't been
- acknowledged yet by the metadata handler.
- Writes that would write to this device if
- it were not faulty are blocked.
- spare - device is working, but not a full member.
- This includes spares that are in the process
- of being recovered to
- write_error - device has ever seen a write error.
- want_replacement - device is (mostly) working but probably
- should be replaced, either due to errors or
- due to user request.
- replacement - device is a replacement for another active
- device with same raid_disk.
+ which can be a comma separated list of:
+
+ faulty
+ device has been kicked from active use due to
+ a detected fault, or it has unacknowledged bad
+ blocks
+
+ in_sync
+ device is a fully in-sync member of the array
+
+ writemostly
+ device will only be subject to read
+ requests if there are no other options.
+
+ This applies only to raid1 arrays.
+
+ blocked
+ device has failed, and the failure hasn't been
+ acknowledged yet by the metadata handler.
+
+ Writes that would write to this device if
+ it were not faulty are blocked.
+
+ spare
+ device is working, but not a full member.
+
+ This includes spares that are in the process
+ of being recovered to
+
+ write_error
+ device has ever seen a write error.
+
+ want_replacement
+ device is (mostly) working but probably
+ should be replaced, either due to errors or
+ due to user request.
+
+ replacement
+ device is a replacement for another active
+ device with same raid_disk.
This list may grow in future.
+
This can be written to.
- Writing "faulty" simulates a failure on the device.
- Writing "remove" removes the device from the array.
- Writing "writemostly" sets the writemostly flag.
- Writing "-writemostly" clears the writemostly flag.
- Writing "blocked" sets the "blocked" flag.
- Writing "-blocked" clears the "blocked" flags and allows writes
- to complete and possibly simulates an error.
- Writing "in_sync" sets the in_sync flag.
- Writing "write_error" sets writeerrorseen flag.
- Writing "-write_error" clears writeerrorseen flag.
- Writing "want_replacement" is allowed at any time except to a
- replacement device or a spare. It sets the flag.
- Writing "-want_replacement" is allowed at any time. It clears
- the flag.
- Writing "replacement" or "-replacement" is only allowed before
- starting the array. It sets or clears the flag.
-
-
- This file responds to select/poll. Any change to 'faulty'
- or 'blocked' causes an event.
+
+ Writing ``faulty`` simulates a failure on the device.
+
+ Writing ``remove`` removes the device from the array.
+
+ Writing ``writemostly`` sets the writemostly flag.
+
+ Writing ``-writemostly`` clears the writemostly flag.
+
+ Writing ``blocked`` sets the ``blocked`` flag.
+
+ Writing ``-blocked`` clears the ``blocked`` flags and allows writes
+ to complete and possibly simulates an error.
+
+ Writing ``in_sync`` sets the in_sync flag.
+
+ Writing ``write_error`` sets writeerrorseen flag.
+
+ Writing ``-write_error`` clears writeerrorseen flag.
+
+ Writing ``want_replacement`` is allowed at any time except to a
+ replacement device or a spare. It sets the flag.
+
+ Writing ``-want_replacement`` is allowed at any time. It clears
+ the flag.
+
+ Writing ``replacement`` or ``-replacement`` is only allowed before
+ starting the array. It sets or clears the flag.
+
+
+ This file responds to select/poll. Any change to ``faulty``
+ or ``blocked`` causes an event.
errors
An approximate count of read errors that have been detected on
@@ -417,9 +514,9 @@ Each directory contains:
slot
This gives the role that the device has in the array. It will
- either be 'none' if the device is not active in the array
+ either be ``none`` if the device is not active in the array
(i.e. is a spare or has failed) or an integer less than the
- 'raid_disks' number for the array indicating which position
+ ``raid_disks`` number for the array indicating which position
it currently fills. This can only be set while assembling an
array. A device for which this is set is assumed to be working.
@@ -437,7 +534,7 @@ Each directory contains:
written, it will be rejected.
recovery_start
- When the device is not 'in_sync', this records the number of
+ When the device is not ``in_sync``, this records the number of
sectors from the start of the device which are known to be
correct. This is normally zero, but during a recovery
operation it will steadily increase, and if the recovery is
@@ -447,21 +544,21 @@ Each directory contains:
This can be set whenever the device is not an active member of
the array, either before the array is activated, or before
- the 'slot' is set.
+ the ``slot`` is set.
+
+ Setting this to ``none`` is equivalent to setting ``in_sync``.
+ Setting to any other value also clears the ``in_sync`` flag.
- Setting this to 'none' is equivalent to setting 'in_sync'.
- Setting to any other value also clears the 'in_sync' flag.
-
bad_blocks
This gives the list of all known bad blocks in the form of
start address and length (in sectors respectively). If output
is too big to fit in a page, it will be truncated. Writing
- "sector length" to this file adds new acknowledged (i.e.
+ ``sector length`` to this file adds new acknowledged (i.e.
recorded to disk safely) bad blocks.
unacknowledged_bad_blocks
This gives the list of known-but-not-yet-saved-to-disk bad
- blocks in the same form of 'bad_blocks'. If output is too big
+ blocks in the same form of ``bad_blocks``. If output is too big
to fit in a page, it will be truncated. Writing to this file
adds bad blocks without acknowledging them. This is largely
for testing.
@@ -469,16 +566,18 @@ Each directory contains:
An active md device will also contain an entry for each active device
-in the array. These are named
+in the array. These are named::
rdNN
-where 'NN' is the position in the array, starting from 0.
+where ``NN`` is the position in the array, starting from 0.
So for a 3 drive array there will be rd0, rd1, rd2.
-These are symbolic links to the appropriate 'dev-XXX' entry.
-Thus, for example,
+These are symbolic links to the appropriate ``dev-XXX`` entry.
+Thus, for example::
+
cat /sys/block/md*/md/rd*/state
-will show 'in_sync' on every line.
+
+will show ``in_sync`` on every line.
@@ -488,50 +587,62 @@ also have
sync_action
a text file that can be used to monitor and control the rebuild
process. It contains one word which can be one of:
- resync - redundancy is being recalculated after unclean
- shutdown or creation
- recover - a hot spare is being built to replace a
- failed/missing device
- idle - nothing is happening
- check - A full check of redundancy was requested and is
- happening. This reads all blocks and checks
- them. A repair may also happen for some raid
- levels.
- repair - A full check and repair is happening. This is
- similar to 'resync', but was requested by the
- user, and the write-intent bitmap is NOT used to
- optimise the process.
+
+ resync
+ redundancy is being recalculated after unclean
+ shutdown or creation
+
+ recover
+ a hot spare is being built to replace a
+ failed/missing device
+
+ idle
+ nothing is happening
+ check
+ A full check of redundancy was requested and is
+ happening. This reads all blocks and checks
+ them. A repair may also happen for some raid
+ levels.
+
+ repair
+ A full check and repair is happening. This is
+ similar to ``resync``, but was requested by the
+ user, and the write-intent bitmap is NOT used to
+ optimise the process.
This file is writable, and each of the strings that could be
read are meaningful for writing.
- 'idle' will stop an active resync/recovery etc. There is no
- guarantee that another resync/recovery may not be automatically
- started again, though some event will be needed to trigger
- this.
- 'resync' or 'recovery' can be used to restart the
- corresponding operation if it was stopped with 'idle'.
- 'check' and 'repair' will start the appropriate process
- providing the current state is 'idle'.
+ ``idle`` will stop an active resync/recovery etc. There is no
+ guarantee that another resync/recovery may not be automatically
+ started again, though some event will be needed to trigger
+ this.
+
+ ``resync`` or ``recovery`` can be used to restart the
+ corresponding operation if it was stopped with ``idle``.
+
+ ``check`` and ``repair`` will start the appropriate process
+ providing the current state is ``idle``.
This file responds to select/poll. Any important change in the value
triggers a poll event. Sometimes the value will briefly be
- "recover" if a recovery seems to be needed, but cannot be
- achieved. In that case, the transition to "recover" isn't
+ ``recover`` if a recovery seems to be needed, but cannot be
+ achieved. In that case, the transition to ``recover`` isn't
notified, but the transition away is.
degraded
This contains a count of the number of devices by which the
- arrays is degraded. So an optimal array will show '0'. A
- single failed/missing drive will show '1', etc.
+ arrays is degraded. So an optimal array will show ``0``. A
+ single failed/missing drive will show ``1``, etc.
+
This file responds to select/poll, any increase or decrease
in the count of missing devices will trigger an event.
mismatch_count
- When performing 'check' and 'repair', and possibly when
- performing 'resync', md will count the number of errors that are
- found. The count in 'mismatch_cnt' is the number of sectors
- that were re-written, or (for 'check') would have been
+ When performing ``check`` and ``repair``, and possibly when
+ performing ``resync``, md will count the number of errors that are
+ found. The count in ``mismatch_cnt`` is the number of sectors
+ that were re-written, or (for ``check``) would have been
re-written. As most raid levels work in units of pages rather
than sectors, this may be larger than the number of actual errors
by a factor of the number of sectors in a page.
@@ -542,27 +653,30 @@ also have
would need to check the corresponding blocks. Either individual
numbers or start-end pairs can be written. Multiple numbers
can be separated by a space.
- Note that the numbers are 'bit' numbers, not 'block' numbers.
+
+ Note that the numbers are ``bit`` numbers, not ``block`` numbers.
They should be scaled by the bitmap_chunksize.
- sync_speed_min
- sync_speed_max
- This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
+ sync_speed_min, sync_speed_max
+ This are similar to ``/proc/sys/dev/raid/speed_limit_{min,max}``
however they only apply to the particular array.
- If no value has been written to these, or if the word 'system'
+
+ If no value has been written to these, or if the word ``system``
is written, then the system-wide value is used. If a value,
in kibibytes-per-second is written, then it is used.
+
When the files are read, they show the currently active value
- followed by "(local)" or "(system)" depending on whether it is
+ followed by ``(local)`` or ``(system)`` depending on whether it is
a locally set or system-wide value.
sync_completed
This shows the number of sectors that have been completed of
whatever the current sync_action is, followed by the number of
sectors in total that could need to be processed. The two
- numbers are separated by a '/' thus effectively showing one
+ numbers are separated by a ``/`` thus effectively showing one
value, a fraction of the process that is complete.
- A 'select' on this attribute will return when resync completes,
+
+ A ``select`` on this attribute will return when resync completes,
when it reaches the current sync_max (below) and possibly at
other times.
@@ -570,26 +684,24 @@ also have
This shows the current actual speed, in K/sec, of the current
sync_action. It is averaged over the last 30 seconds.
- suspend_lo
- suspend_hi
+ suspend_lo, suspend_hi
The two values, given as numbers of sectors, indicate a range
within the array where IO will be blocked. This is currently
only supported for raid4/5/6.
- sync_min
- sync_max
+ sync_min, sync_max
The two values, given as numbers of sectors, indicate a range
- within the array where 'check'/'repair' will operate. Must be
- a multiple of chunk_size. When it reaches "sync_max" it will
+ within the array where ``check``/``repair`` will operate. Must be
+ a multiple of chunk_size. When it reaches ``sync_max`` it will
pause, rather than complete.
- You can use 'select' or 'poll' on "sync_completed" to wait for
+ You can use ``select`` or ``poll`` on ``sync_completed`` to wait for
that number to reach sync_max. Then you can either increase
- "sync_max", or can write 'idle' to "sync_action".
+ ``sync_max``, or can write ``idle`` to ``sync_action``.
- The value of 'max' for "sync_max" effectively disables the limit.
+ The value of ``max`` for ``sync_max`` effectively disables the limit.
When a resync is active, the value can only ever be increased,
never decreased.
- The value of '0' is the minimum for "sync_min".
+ The value of ``0`` is the minimum for ``sync_min``.
@@ -598,13 +710,15 @@ personality module that manages it.
These are specific to the implementation of the module and could
change substantially if the implementation changes.
-These currently include
+These currently include:
stripe_cache_size (currently raid5 only)
number of entries in the stripe cache. This is writable, but
there are upper and lower limits (32768, 17). Default is 256.
+
strip_cache_active (currently raid5 only)
number of active entries in the stripe cache
+
preread_bypass_threshold (currently raid5 only)
number of times a stripe requiring preread will be bypassed by
a stripe that does not require preread. For fairness defaults
diff --git a/Documentation/module-signing.txt b/Documentation/admin-guide/module-signing.rst
index f0e3361db20c..27e59498b487 100644
--- a/Documentation/module-signing.txt
+++ b/Documentation/admin-guide/module-signing.rst
@@ -1,22 +1,21 @@
- ==============================
- KERNEL MODULE SIGNING FACILITY
- ==============================
-
-CONTENTS
-
- - Overview.
- - Configuring module signing.
- - Generating signing keys.
- - Public keys in the kernel.
- - Manually signing modules.
- - Signed modules and stripping.
- - Loading signed modules.
- - Non-valid signatures and unsigned modules.
- - Administering/protecting the private key.
+Kernel module signing facility
+------------------------------
+
+.. CONTENTS
+..
+.. - Overview.
+.. - Configuring module signing.
+.. - Generating signing keys.
+.. - Public keys in the kernel.
+.. - Manually signing modules.
+.. - Signed modules and stripping.
+.. - Loading signed modules.
+.. - Non-valid signatures and unsigned modules.
+.. - Administering/protecting the private key.
========
-OVERVIEW
+Overview
========
The kernel module signing facility cryptographically signs modules during
@@ -36,17 +35,19 @@ SHA-512 (the algorithm is selected by data in the signature).
==========================
-CONFIGURING MODULE SIGNING
+Configuring module signing
==========================
-The module signing facility is enabled by going to the "Enable Loadable Module
-Support" section of the kernel configuration and turning on
+The module signing facility is enabled by going to the
+:menuselection:`Enable Loadable Module Support` section of
+the kernel configuration and turning on::
CONFIG_MODULE_SIG "Module signature verification"
This has a number of options available:
- (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+ (1) :menuselection:`Require modules to be validly signed`
+ (``CONFIG_MODULE_SIG_FORCE``)
This specifies how the kernel should deal with a module that has a
signature for which the key is not known or a module that is unsigned.
@@ -64,35 +65,39 @@ This has a number of options available:
cannot be parsed, it will be rejected out of hand.
- (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+ (2) :menuselection:`Automatically sign all modules`
+ (``CONFIG_MODULE_SIG_ALL``)
If this is on then modules will be automatically signed during the
modules_install phase of a build. If this is off, then the modules must
- be signed manually using:
+ be signed manually using::
scripts/sign-file
- (3) "Which hash algorithm should modules be signed with?"
+ (3) :menuselection:`Which hash algorithm should modules be signed with?`
This presents a choice of which hash algorithm the installation phase will
sign the modules with:
- CONFIG_MODULE_SIG_SHA1 "Sign modules with SHA-1"
- CONFIG_MODULE_SIG_SHA224 "Sign modules with SHA-224"
- CONFIG_MODULE_SIG_SHA256 "Sign modules with SHA-256"
- CONFIG_MODULE_SIG_SHA384 "Sign modules with SHA-384"
- CONFIG_MODULE_SIG_SHA512 "Sign modules with SHA-512"
+ =============================== ==========================================
+ ``CONFIG_MODULE_SIG_SHA1`` :menuselection:`Sign modules with SHA-1`
+ ``CONFIG_MODULE_SIG_SHA224`` :menuselection:`Sign modules with SHA-224`
+ ``CONFIG_MODULE_SIG_SHA256`` :menuselection:`Sign modules with SHA-256`
+ ``CONFIG_MODULE_SIG_SHA384`` :menuselection:`Sign modules with SHA-384`
+ ``CONFIG_MODULE_SIG_SHA512`` :menuselection:`Sign modules with SHA-512`
+ =============================== ==========================================
The algorithm selected here will also be built into the kernel (rather
than being a module) so that modules signed with that algorithm can have
their signatures checked without causing a dependency loop.
- (4) "File name or PKCS#11 URI of module signing key" (CONFIG_MODULE_SIG_KEY)
+ (4) :menuselection:`File name or PKCS#11 URI of module signing key`
+ (``CONFIG_MODULE_SIG_KEY``)
Setting this option to something other than its default of
- "certs/signing_key.pem" will disable the autogeneration of signing keys
+ ``certs/signing_key.pem`` will disable the autogeneration of signing keys
and allow the kernel modules to be signed with a key of your choosing.
The string provided should identify a file containing both a private key
and its corresponding X.509 certificate in PEM form, or — on systems where
@@ -102,10 +107,11 @@ This has a number of options available:
If the PEM file containing the private key is encrypted, or if the
PKCS#11 token requries a PIN, this can be provided at build time by
- means of the KBUILD_SIGN_PIN variable.
+ means of the ``KBUILD_SIGN_PIN`` variable.
- (5) "Additional X.509 keys for default system keyring" (CONFIG_SYSTEM_TRUSTED_KEYS)
+ (5) :menuselection:`Additional X.509 keys for default system keyring`
+ (``CONFIG_SYSTEM_TRUSTED_KEYS``)
This option can be set to the filename of a PEM-encoded file containing
additional certificates which will be included in the system keyring by
@@ -116,7 +122,7 @@ packages to the kernel build processes for the tool that does the signing.
=======================
-GENERATING SIGNING KEYS
+Generating signing keys
=======================
Cryptographic keypairs are required to generate and check signatures. A
@@ -126,14 +132,14 @@ it can be deleted or stored securely. The public key gets built into the
kernel so that it can be used to check the signatures as the modules are
loaded.
-Under normal conditions, when CONFIG_MODULE_SIG_KEY is unchanged from its
+Under normal conditions, when ``CONFIG_MODULE_SIG_KEY`` is unchanged from its
default, the kernel build will automatically generate a new keypair using
-openssl if one does not exist in the file:
+openssl if one does not exist in the file::
certs/signing_key.pem
during the building of vmlinux (the public part of the key needs to be built
-into vmlinux) using parameters in the:
+into vmlinux) using parameters in the::
certs/x509.genkey
@@ -142,14 +148,14 @@ file (which is also generated if it does not already exist).
It is strongly recommended that you provide your own x509.genkey file.
Most notably, in the x509.genkey file, the req_distinguished_name section
-should be altered from the default:
+should be altered from the default::
[ req_distinguished_name ]
#O = Unspecified company
CN = Build time autogenerated kernel key
#emailAddress = unspecified.user@unspecified.company
-The generated RSA key size can also be set with:
+The generated RSA key size can also be set with::
[ req ]
default_bits = 4096
@@ -158,23 +164,23 @@ The generated RSA key size can also be set with:
It is also possible to manually generate the key private/public files using the
x509.genkey key generation configuration file in the root node of the Linux
kernel sources tree and the openssl command. The following is an example to
-generate the public/private key files:
+generate the public/private key files::
openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
-config x509.genkey -outform PEM -out kernel_key.pem \
-keyout kernel_key.pem
The full pathname for the resulting kernel_key.pem file can then be specified
-in the CONFIG_MODULE_SIG_KEY option, and the certificate and key therein will
+in the ``CONFIG_MODULE_SIG_KEY`` option, and the certificate and key therein will
be used instead of an autogenerated keypair.
=========================
-PUBLIC KEYS IN THE KERNEL
+Public keys in the kernel
=========================
The kernel contains a ring of public keys that can be viewed by root. They're
-in a keyring called ".system_keyring" that can be seen by:
+in a keyring called ".system_keyring" that can be seen by::
[root@deneb ~]# cat /proc/keys
...
@@ -184,27 +190,27 @@ in a keyring called ".system_keyring" that can be seen by:
Beyond the public key generated specifically for module signing, additional
trusted certificates can be provided in a PEM-encoded file referenced by the
-CONFIG_SYSTEM_TRUSTED_KEYS configuration option.
+``CONFIG_SYSTEM_TRUSTED_KEYS`` configuration option.
Further, the architecture code may take public keys from a hardware store and
add those in also (e.g. from the UEFI key database).
-Finally, it is possible to add additional public keys by doing:
+Finally, it is possible to add additional public keys by doing::
keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
-e.g.:
+e.g.::
keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
Note, however, that the kernel will only permit keys to be added to
-.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+``.system_keyring _if_`` the new key's X.509 wrapper is validly signed by a key
that is already resident in the .system_keyring at the time the key was added.
-=========================
-MANUALLY SIGNING MODULES
-=========================
+========================
+Manually signing modules
+========================
To manually sign a module, use the scripts/sign-file tool available in
the Linux kernel source tree. The script requires 4 arguments:
@@ -214,7 +220,7 @@ the Linux kernel source tree. The script requires 4 arguments:
3. The public key filename
4. The kernel module to be signed
-The following is an example to sign a kernel module:
+The following is an example to sign a kernel module::
scripts/sign-file sha512 kernel-signkey.priv \
kernel-signkey.x509 module.ko
@@ -228,11 +234,11 @@ $KBUILD_SIGN_PIN environment variable.
============================
-SIGNED MODULES AND STRIPPING
+Signed modules and stripping
============================
A signed module has a digital signature simply appended at the end. The string
-"~Module signature appended~." at the end of the module's file confirms that a
+``~Module signature appended~.`` at the end of the module's file confirms that a
signature is present but it does not confirm that the signature is valid!
Signed modules are BRITTLE as the signature is outside of the defined ELF
@@ -242,19 +248,19 @@ debug information present at the time of signing.
======================
-LOADING SIGNED MODULES
+Loading signed modules
======================
-Modules are loaded with insmod, modprobe, init_module() or finit_module(),
-exactly as for unsigned modules as no processing is done in userspace. The
-signature checking is all done within the kernel.
+Modules are loaded with insmod, modprobe, ``init_module()`` or
+``finit_module()``, exactly as for unsigned modules as no processing is
+done in userspace. The signature checking is all done within the kernel.
=========================================
-NON-VALID SIGNATURES AND UNSIGNED MODULES
+Non-valid signatures and unsigned modules
=========================================
-If CONFIG_MODULE_SIG_FORCE is enabled or module.sig_enforce=1 is supplied on
+If ``CONFIG_MODULE_SIG_FORCE`` is enabled or module.sig_enforce=1 is supplied on
the kernel command line, the kernel will only load validly signed modules
for which it has a public key. Otherwise, it will also load modules that are
unsigned. Any module for which the kernel has a key, but which proves to have
@@ -264,7 +270,7 @@ Any module that has an unparseable signature will be rejected.
=========================================
-ADMINISTERING/PROTECTING THE PRIVATE KEY
+Administering/protecting the private key
=========================================
Since the private key is used to sign modules, viruses and malware could use
@@ -275,5 +281,5 @@ in the root node of the kernel source tree.
If you use the same private key to sign modules for multiple kernel
configurations, you must ensure that the module version information is
sufficient to prevent loading a module into a different kernel. Either
-set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
-kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
+set ``CONFIG_MODVERSIONS=y`` or ensure that each configuration has a different
+kernel release string by changing ``EXTRAVERSION`` or ``CONFIG_LOCALVERSION``.
diff --git a/Documentation/mono.txt b/Documentation/admin-guide/mono.rst
index d01ac6052194..cdddc099af64 100644
--- a/Documentation/mono.txt
+++ b/Documentation/admin-guide/mono.rst
@@ -1,5 +1,5 @@
- Mono(tm) Binary Kernel Support for Linux
- -----------------------------------------
+Mono(tm) Binary Kernel Support for Linux
+-----------------------------------------
To configure Linux to automatically execute Mono-based .NET binaries
(in the form of .exe files) without the need to use the mono CLR
@@ -19,22 +19,24 @@ other program after you have done the following:
http://www.go-mono.com/compiling.html
Once the Mono CLR support has been installed, just check that
- /usr/bin/mono (which could be located elsewhere, for example
- /usr/local/bin/mono) is working.
+ ``/usr/bin/mono`` (which could be located elsewhere, for example
+ ``/usr/local/bin/mono``) is working.
2) You have to compile BINFMT_MISC either as a module or into
- the kernel (CONFIG_BINFMT_MISC) and set it up properly.
+ the kernel (``CONFIG_BINFMT_MISC``) and set it up properly.
If you choose to compile it as a module, you will have
to insert it manually with modprobe/insmod, as kmod
- cannot be easily supported with binfmt_misc.
- Read the file 'binfmt_misc.txt' in this directory to know
+ cannot be easily supported with binfmt_misc.
+ Read the file ``binfmt_misc.txt`` in this directory to know
more about the configuration process.
-3) Add the following entries to /etc/rc.local or similar script
+3) Add the following entries to ``/etc/rc.local`` or similar script
to be run at system startup:
-# Insert BINFMT_MISC module into the kernel
-if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
+ .. code-block:: sh
+
+ # Insert BINFMT_MISC module into the kernel
+ if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
/sbin/modprobe binfmt_misc
# Some distributions, like Fedora Core, perform
# the following command automatically when the
@@ -43,24 +45,26 @@ if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
# Thus, it is possible that the following line
# is not needed at all.
mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
-fi
+ fi
-# Register support for .NET CLR binaries
-if [ -e /proc/sys/fs/binfmt_misc/register ]; then
+ # Register support for .NET CLR binaries
+ if [ -e /proc/sys/fs/binfmt_misc/register ]; then
# Replace /usr/bin/mono with the correct pathname to
# the Mono CLR runtime (usually /usr/local/bin/mono
# when compiling from sources or CVS).
echo ':CLR:M::MZ::/usr/bin/mono:' > /proc/sys/fs/binfmt_misc/register
-else
+ else
echo "No binfmt_misc support"
exit 1
-fi
+ fi
-4) Check that .exe binaries can be ran without the need of a
- wrapper script, simply by launching the .exe file directly
- from a command prompt, for example:
+4) Check that ``.exe`` binaries can be ran without the need of a
+ wrapper script, simply by launching the ``.exe`` file directly
+ from a command prompt, for example::
/usr/bin/xsd.exe
- NOTE: If this fails with a permission denied error, check
- that the .exe file has execute permissions.
+ .. note::
+
+ If this fails with a permission denied error, check
+ that the ``.exe`` file has execute permissions.
diff --git a/Documentation/admin-guide/parport.rst b/Documentation/admin-guide/parport.rst
new file mode 100644
index 000000000000..ad3f9b8a11e1
--- /dev/null
+++ b/Documentation/admin-guide/parport.rst
@@ -0,0 +1,286 @@
+Parport
++++++++
+
+The ``parport`` code provides parallel-port support under Linux. This
+includes the ability to share one port between multiple device
+drivers.
+
+You can pass parameters to the ``parport`` code to override its automatic
+detection of your hardware. This is particularly useful if you want
+to use IRQs, since in general these can't be autoprobed successfully.
+By default IRQs are not used even if they **can** be probed. This is
+because there are a lot of people using the same IRQ for their
+parallel port and a sound card or network card.
+
+The ``parport`` code is split into two parts: generic (which deals with
+port-sharing) and architecture-dependent (which deals with actually
+using the port).
+
+
+Parport as modules
+==================
+
+If you load the `parport`` code as a module, say::
+
+ # insmod parport
+
+to load the generic ``parport`` code. You then must load the
+architecture-dependent code with (for example)::
+
+ # insmod parport_pc io=0x3bc,0x378,0x278 irq=none,7,auto
+
+to tell the ``parport`` code that you want three PC-style ports, one at
+0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
+auto-detected IRQ. Currently, PC-style (``parport_pc``), Sun ``bpp``,
+Amiga, Atari, and MFC3 hardware is supported.
+
+PCI parallel I/O card support comes from ``parport_pc``. Base I/O
+addresses should not be specified for supported PCI cards since they
+are automatically detected.
+
+
+modprobe
+--------
+
+If you use modprobe , you will find it useful to add lines as below to a
+configuration file in /etc/modprobe.d/ directory::
+
+ alias parport_lowlevel parport_pc
+ options parport_pc io=0x378,0x278 irq=7,auto
+
+modprobe will load ``parport_pc`` (with the options ``io=0x378,0x278 irq=7,auto``)
+whenever a parallel port device driver (such as ``lp``) is loaded.
+
+Note that these are example lines only! You shouldn't in general need
+to specify any options to ``parport_pc`` in order to be able to use a
+parallel port.
+
+
+Parport probe [optional]
+------------------------
+
+In 2.2 kernels there was a module called ``parport_probe``, which was used
+for collecting IEEE 1284 device ID information. This has now been
+enhanced and now lives with the IEEE 1284 support. When a parallel
+port is detected, the devices that are connected to it are analysed,
+and information is logged like this::
+
+ parport0: Printer, BJC-210 (Canon)
+
+The probe information is available from files in ``/proc/sys/dev/parport/``.
+
+
+Parport linked into the kernel statically
+=========================================
+
+If you compile the ``parport`` code into the kernel, then you can use
+kernel boot parameters to get the same effect. Add something like the
+following to your LILO command line::
+
+ parport=0x3bc parport=0x378,7 parport=0x278,auto,nofifo
+
+You can have many ``parport=...`` statements, one for each port you want
+to add. Adding ``parport=0`` to the kernel command-line will disable
+parport support entirely. Adding ``parport=auto`` to the kernel
+command-line will make ``parport`` use any IRQ lines or DMA channels that
+it auto-detects.
+
+
+Files in /proc
+==============
+
+If you have configured the ``/proc`` filesystem into your kernel, you will
+see a new directory entry: ``/proc/sys/dev/parport``. In there will be a
+directory entry for each parallel port for which parport is
+configured. In each of those directories are a collection of files
+describing that parallel port.
+
+The ``/proc/sys/dev/parport`` directory tree looks like::
+
+ parport
+ |-- default
+ | |-- spintime
+ | `-- timeslice
+ |-- parport0
+ | |-- autoprobe
+ | |-- autoprobe0
+ | |-- autoprobe1
+ | |-- autoprobe2
+ | |-- autoprobe3
+ | |-- devices
+ | | |-- active
+ | | `-- lp
+ | | `-- timeslice
+ | |-- base-addr
+ | |-- irq
+ | |-- dma
+ | |-- modes
+ | `-- spintime
+ `-- parport1
+ |-- autoprobe
+ |-- autoprobe0
+ |-- autoprobe1
+ |-- autoprobe2
+ |-- autoprobe3
+ |-- devices
+ | |-- active
+ | `-- ppa
+ | `-- timeslice
+ |-- base-addr
+ |-- irq
+ |-- dma
+ |-- modes
+ `-- spintime
+
+.. tabularcolumns:: |p{4.0cm}|p{13.5cm}|
+
+======================= =======================================================
+File Contents
+======================= =======================================================
+``devices/active`` A list of the device drivers using that port. A "+"
+ will appear by the name of the device currently using
+ the port (it might not appear against any). The
+ string "none" means that there are no device drivers
+ using that port.
+
+``base-addr`` Parallel port's base address, or addresses if the port
+ has more than one in which case they are separated
+ with tabs. These values might not have any sensible
+ meaning for some ports.
+
+``irq`` Parallel port's IRQ, or -1 if none is being used.
+
+``dma`` Parallel port's DMA channel, or -1 if none is being
+ used.
+
+``modes`` Parallel port's hardware modes, comma-separated,
+ meaning:
+
+ - PCSPP
+ PC-style SPP registers are available.
+
+ - TRISTATE
+ Port is bidirectional.
+
+ - COMPAT
+ Hardware acceleration for printers is
+ available and will be used.
+
+ - EPP
+ Hardware acceleration for EPP protocol
+ is available and will be used.
+
+ - ECP
+ Hardware acceleration for ECP protocol
+ is available and will be used.
+
+ - DMA
+ DMA is available and will be used.
+
+ Note that the current implementation will only take
+ advantage of COMPAT and ECP modes if it has an IRQ
+ line to use.
+
+``autoprobe`` Any IEEE-1284 device ID information that has been
+ acquired from the (non-IEEE 1284.3) device.
+
+``autoprobe[0-3]`` IEEE 1284 device ID information retrieved from
+ daisy-chain devices that conform to IEEE 1284.3.
+
+``spintime`` The number of microseconds to busy-loop while waiting
+ for the peripheral to respond. You might find that
+ adjusting this improves performance, depending on your
+ peripherals. This is a port-wide setting, i.e. it
+ applies to all devices on a particular port.
+
+``timeslice`` The number of milliseconds that a device driver is
+ allowed to keep a port claimed for. This is advisory,
+ and driver can ignore it if it must.
+
+``default/*`` The defaults for spintime and timeslice. When a new
+ port is registered, it picks up the default spintime.
+ When a new device is registered, it picks up the
+ default timeslice.
+======================= =======================================================
+
+Device drivers
+==============
+
+Once the parport code is initialised, you can attach device drivers to
+specific ports. Normally this happens automatically; if the lp driver
+is loaded it will create one lp device for each port found. You can
+override this, though, by using parameters either when you load the lp
+driver::
+
+ # insmod lp parport=0,2
+
+or on the LILO command line::
+
+ lp=parport0 lp=parport2
+
+Both the above examples would inform lp that you want ``/dev/lp0`` to be
+the first parallel port, and /dev/lp1 to be the **third** parallel port,
+with no lp device associated with the second port (parport1). Note
+that this is different to the way older kernels worked; there used to
+be a static association between the I/O port address and the device
+name, so ``/dev/lp0`` was always the port at 0x3bc. This is no longer the
+case - if you only have one port, it will default to being ``/dev/lp0``,
+regardless of base address.
+
+Also:
+
+ * If you selected the IEEE 1284 support at compile time, you can say
+ ``lp=auto`` on the kernel command line, and lp will create devices
+ only for those ports that seem to have printers attached.
+
+ * If you give PLIP the ``timid`` parameter, either with ``plip=timid`` on
+ the command line, or with ``insmod plip timid=1`` when using modules,
+ it will avoid any ports that seem to be in use by other devices.
+
+ * IRQ autoprobing works only for a few port types at the moment.
+
+Reporting printer problems with parport
+=======================================
+
+If you are having problems printing, please go through these steps to
+try to narrow down where the problem area is.
+
+When reporting problems with parport, really you need to give all of
+the messages that ``parport_pc`` spits out when it initialises. There are
+several code paths:
+
+- polling
+- interrupt-driven, protocol in software
+- interrupt-driven, protocol in hardware using PIO
+- interrupt-driven, protocol in hardware using DMA
+
+The kernel messages that ``parport_pc`` logs give an indication of which
+code path is being used. (They could be a lot better actually..)
+
+For normal printer protocol, having IEEE 1284 modes enabled or not
+should not make a difference.
+
+To turn off the 'protocol in hardware' code paths, disable
+``CONFIG_PARPORT_PC_FIFO``. Note that when they are enabled they are not
+necessarily **used**; it depends on whether the hardware is available,
+enabled by the BIOS, and detected by the driver.
+
+So, to start with, disable ``CONFIG_PARPORT_PC_FIFO``, and load ``parport_pc``
+with ``irq=none``. See if printing works then. It really should,
+because this is the simplest code path.
+
+If that works fine, try with ``io=0x378 irq=7`` (adjust for your
+hardware), to make it use interrupt-driven in-software protocol.
+
+If **that** works fine, then one of the hardware modes isn't working
+right. Enable ``CONFIG_FIFO`` (no, it isn't a module option,
+and yes, it should be), set the port to ECP mode in the BIOS and note
+the DMA channel, and try with::
+
+ io=0x378 irq=7 dma=none (for PIO)
+ io=0x378 irq=7 dma=3 (for DMA)
+
+----------
+
+philb@gnu.org
+tim@cyberelk.net
diff --git a/Documentation/ramoops.txt b/Documentation/admin-guide/ramoops.rst
index 26b9f31cf65a..4efd7ce77565 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/admin-guide/ramoops.rst
@@ -5,34 +5,37 @@ Sergiu Iordache <sergiu@chromium.org>
Updated: 17 November 2011
-0. Introduction
+Introduction
+------------
Ramoops is an oops/panic logger that writes its logs to RAM before the system
crashes. It works by logging oopses and panics in a circular buffer. Ramoops
needs a system with persistent RAM so that the content of that area can
survive after a restart.
-1. Ramoops concepts
+Ramoops concepts
+----------------
Ramoops uses a predefined memory area to store the dump. The start and size
and type of the memory area are set using three variables:
- * "mem_address" for the start
- * "mem_size" for the size. The memory size will be rounded down to a
- power of two.
- * "mem_type" to specifiy if the memory type (default is pgprot_writecombine).
-
-Typically the default value of mem_type=0 should be used as that sets the pstore
-mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
-pgprot_noncached, which only works on some platforms. This is because pstore
+
+ * ``mem_address`` for the start
+ * ``mem_size`` for the size. The memory size will be rounded down to a
+ power of two.
+ * ``mem_type`` to specifiy if the memory type (default is pgprot_writecombine).
+
+Typically the default value of ``mem_type=0`` should be used as that sets the pstore
+mapping to pgprot_writecombine. Setting ``mem_type=1`` attempts to use
+``pgprot_noncached``, which only works on some platforms. This is because pstore
depends on atomic operations. At least on ARM, pgprot_noncached causes the
memory to be mapped strongly ordered, and atomic operations on strongly ordered
memory are implementation defined, and won't work on many ARMs such as omaps.
-The memory area is divided into "record_size" chunks (also rounded down to
-power of two) and each oops/panic writes a "record_size" chunk of
+The memory area is divided into ``record_size`` chunks (also rounded down to
+power of two) and each oops/panic writes a ``record_size`` chunk of
information.
-Dumping both oopses and panics can be done by setting 1 in the "dump_oops"
+Dumping both oopses and panics can be done by setting 1 in the ``dump_oops``
variable while setting 0 in that variable dumps only the panics.
The module uses a counter to record multiple dumps but the counter gets reset
@@ -43,7 +46,8 @@ This might be useful when a hardware reset was used to bring the machine back
to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
corrupt, but usually it is restorable.
-2. Setting the parameters
+Setting the parameters
+----------------------
Setting the ramoops parameters can be done in several different manners:
@@ -52,12 +56,13 @@ Setting the ramoops parameters can be done in several different manners:
boot and then use the reserved memory for ramoops. For example, assuming a
machine with > 128 MB of memory, the following kernel command line will tell
the kernel to use only the first 128 MB of memory, and place ECC-protected
- ramoops region at 128 MB boundary:
- "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
+ ramoops region at 128 MB boundary::
+
+ mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1
B. Use Device Tree bindings, as described in
- Documentation/device-tree/bindings/reserved-memory/ramoops.txt.
- For example:
+ ``Documentation/device-tree/bindings/reserved-memory/admin-guide/ramoops.rst``.
+ For example::
reserved-memory {
#address-cells = <2>;
@@ -75,58 +80,63 @@ Setting the ramoops parameters can be done in several different manners:
C. Use a platform device and set the platform data. The parameters can then
be set through that platform data. An example of doing that is:
-#include <linux/pstore_ram.h>
-[...]
+ .. code-block:: c
+
+ #include <linux/pstore_ram.h>
+ [...]
-static struct ramoops_platform_data ramoops_data = {
+ static struct ramoops_platform_data ramoops_data = {
.mem_size = <...>,
.mem_address = <...>,
.mem_type = <...>,
.record_size = <...>,
.dump_oops = <...>,
.ecc = <...>,
-};
+ };
-static struct platform_device ramoops_dev = {
+ static struct platform_device ramoops_dev = {
.name = "ramoops",
.dev = {
.platform_data = &ramoops_data,
},
-};
+ };
-[... inside a function ...]
-int ret;
+ [... inside a function ...]
+ int ret;
-ret = platform_device_register(&ramoops_dev);
-if (ret) {
+ ret = platform_device_register(&ramoops_dev);
+ if (ret) {
printk(KERN_ERR "unable to register platform device\n");
return ret;
-}
+ }
You can specify either RAM memory or peripheral devices' memory. However, when
specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
-very early in the architecture code, e.g.:
+very early in the architecture code, e.g.::
-#include <linux/memblock.h>
+ #include <linux/memblock.h>
-memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
+ memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
-3. Dump format
+Dump format
+-----------
-The data dump begins with a header, currently defined as "====" followed by a
+The data dump begins with a header, currently defined as ``====`` followed by a
timestamp and a new line. The dump then continues with the actual data.
-4. Reading the data
+Reading the data
+----------------
The dump data can be read from the pstore filesystem. The format for these
-files is "dmesg-ramoops-N", where N is the record number in memory. To delete
+files is ``dmesg-ramoops-N``, where N is the record number in memory. To delete
a stored record from RAM, simply unlink the respective pstore file.
-5. Persistent function tracing
+Persistent function tracing
+---------------------------
Persistent function tracing might be useful for debugging software or hardware
-related hangs. The functions call chain log is stored in a "ftrace-ramoops"
-file. Here is an example of usage:
+related hangs. The functions call chain log is stored in a ``ftrace-ramoops``
+file. Here is an example of usage::
# mount -t debugfs debugfs /sys/kernel/debug/
# echo 1 > /sys/kernel/debug/pstore/record_ftrace
diff --git a/REPORTING-BUGS b/Documentation/admin-guide/reporting-bugs.rst
index 914baf9cf5fa..26b60b419652 100644
--- a/REPORTING-BUGS
+++ b/Documentation/admin-guide/reporting-bugs.rst
@@ -1,3 +1,8 @@
+.. _reportingbugs:
+
+Reporting bugs
+++++++++++++++
+
Background
==========
@@ -50,12 +55,13 @@ maintainer replies to you, make sure to 'Reply-all' in order to keep the
public mailing list(s) in the email thread.
If you know which driver is causing issues, you can pass one of the driver
-files to the get_maintainer.pl script:
+files to the get_maintainer.pl script::
+
perl scripts/get_maintainer.pl -f <filename>
If it is a security bug, please copy the Security Contact listed in the
MAINTAINERS file. They can help coordinate bugfix and disclosure. See
-Documentation/SecurityBugs for more information.
+:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>` for more information.
If you can't figure out which subsystem caused the issue, you should file
a bug in kernel.org bugzilla and send email to
@@ -69,8 +75,9 @@ Tips for reporting bugs
If you haven't reported a bug before, please read:
-http://www.chiark.greenend.org.uk/~sgtatham/bugs.html
-http://www.catb.org/esr/faqs/smart-questions.html
+ http://www.chiark.greenend.org.uk/~sgtatham/bugs.html
+
+ http://www.catb.org/esr/faqs/smart-questions.html
It's REALLY important to report bugs that seem unrelated as separate email
threads or separate bugzilla entries. If you report several unrelated
@@ -87,7 +94,7 @@ step-by-step instructions for how a user can trigger the bug.
If the failure includes an "OOPS:", take a picture of the screen, capture
a netconsole trace, or type the message from your screen into the bug
-report. Please read "Documentation/oops-tracing.txt" before posting your
+report. Please read "Documentation/admin-guide/oops-tracing.rst" before posting your
bug report. This explains what you should do with the "Oops" information
to make it useful to the recipient.
@@ -99,34 +106,34 @@ relevant to your bug, feel free to exclude it.
First run the ver_linux script included as scripts/ver_linux, which
reports the version of some important subsystems. Run this script with
-the command "sh scripts/ver_linux".
+the command ``awk -f scripts/ver_linux``.
Use that information to fill in all fields of the bug report form, and
post it to the mailing list with a subject of "PROBLEM: <one line
-summary from [1.]>" for easy identification by the developers.
-
-[1.] One line summary of the problem:
-[2.] Full description of the problem/report:
-[3.] Keywords (i.e., modules, networking, kernel):
-[4.] Kernel information
-[4.1.] Kernel version (from /proc/version):
-[4.2.] Kernel .config file:
-[5.] Most recent kernel version which did not have the bug:
-[6.] Output of Oops.. message (if applicable) with symbolic information
- resolved (see Documentation/oops-tracing.txt)
-[7.] A small shell script or example program which triggers the
- problem (if possible)
-[8.] Environment
-[8.1.] Software (add the output of the ver_linux script here)
-[8.2.] Processor information (from /proc/cpuinfo):
-[8.3.] Module information (from /proc/modules):
-[8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
-[8.5.] PCI information ('lspci -vvv' as root)
-[8.6.] SCSI information (from /proc/scsi/scsi)
-[8.7.] Other information that might be relevant to the problem
- (please look in /proc and include all information that you
- think to be relevant):
-[X.] Other notes, patches, fixes, workarounds:
+summary from [1.]>" for easy identification by the developers::
+
+ [1.] One line summary of the problem:
+ [2.] Full description of the problem/report:
+ [3.] Keywords (i.e., modules, networking, kernel):
+ [4.] Kernel information
+ [4.1.] Kernel version (from /proc/version):
+ [4.2.] Kernel .config file:
+ [5.] Most recent kernel version which did not have the bug:
+ [6.] Output of Oops.. message (if applicable) with symbolic information
+ resolved (see Documentation/admin-guide/oops-tracing.rst)
+ [7.] A small shell script or example program which triggers the
+ problem (if possible)
+ [8.] Environment
+ [8.1.] Software (add the output of the ver_linux script here)
+ [8.2.] Processor information (from /proc/cpuinfo):
+ [8.3.] Module information (from /proc/modules):
+ [8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
+ [8.5.] PCI information ('lspci -vvv' as root)
+ [8.6.] SCSI information (from /proc/scsi/scsi)
+ [8.7.] Other information that might be relevant to the problem
+ (please look in /proc and include all information that you
+ think to be relevant):
+ [X.] Other notes, patches, fixes, workarounds:
Follow up
@@ -153,7 +160,8 @@ Expectations for kernel maintainers
Linux kernel maintainers are busy, overworked human beings. Some times
they may not be able to address your bug in a day, a week, or two weeks.
If they don't answer your email, they may be on vacation, or at a Linux
-conference. Check the conference schedule at LWN.net for more info:
+conference. Check the conference schedule at https://LWN.net for more info:
+
https://lwn.net/Calendar/
In general, kernel maintainers take 1 to 5 business days to respond to
diff --git a/Documentation/SecurityBugs b/Documentation/admin-guide/security-bugs.rst
index 342d769834f6..4f7414cad586 100644
--- a/Documentation/SecurityBugs
+++ b/Documentation/admin-guide/security-bugs.rst
@@ -8,8 +8,8 @@ like to know when a security bug is found so that it can be fixed and
disclosed as quickly as possible. Please report security bugs to the
Linux kernel security team.
-1) Contact
-----------
+Contact
+-------
The Linux kernel security team can be contacted by email at
<security@kernel.org>. This is a private list of security officers
@@ -19,12 +19,12 @@ area maintainers to understand and fix the security vulnerability.
As it is with any bug, the more information provided the easier it
will be to diagnose and fix. Please review the procedure outlined in
-REPORTING-BUGS if you are unclear about what information is helpful.
+admin-guide/reporting-bugs.rst if you are unclear about what information is helpful.
Any exploit code is very helpful and will not be released without
consent from the reporter unless it has already been made public.
-2) Disclosure
--------------
+Disclosure
+----------
The goal of the Linux kernel security team is to work with the
bug submitter to bug resolution as well as disclosure. We prefer
@@ -39,8 +39,8 @@ disclosure is from immediate (esp. if it's already publicly known)
to a few weeks. As a basic default policy, we expect report date to
disclosure date to be on the order of 7 days.
-3) Non-disclosure agreements
-----------------------------
+Non-disclosure agreements
+-------------------------
The Linux kernel security team is not a formal body and therefore unable
to enter any non-disclosure agreements.
diff --git a/Documentation/serial-console.txt b/Documentation/admin-guide/serial-console.rst
index 9a7bc8b3f479..a8d1e36b627a 100644
--- a/Documentation/serial-console.txt
+++ b/Documentation/admin-guide/serial-console.rst
@@ -1,15 +1,21 @@
- Linux Serial Console
+.. _serial_console:
+
+Linux Serial Console
+====================
To use a serial port as console you need to compile the support into your
kernel - by default it is not compiled in. For PC style serial ports
-it's the config option next to "Standard/generic (dumb) serial support".
+it's the config option next to menu option:
+
+:menuselection:`Character devices --> Serial drivers --> 8250/16550 and compatible serial support --> Console on 8250/16550 and compatible serial port`
+
You must compile serial support into the kernel and not as a module.
It is possible to specify multiple devices for console output. You can
define a new kernel command line option to select which device(s) to
use for console output.
-The format of this option is:
+The format of this option is::
console=device,options
@@ -28,11 +34,11 @@ The format of this option is:
You can specify multiple console= options on the kernel command line.
Output will appear on all of them. The last device will be used when
-you open /dev/console. So, for example:
+you open ``/dev/console``. So, for example::
console=ttyS1,9600 console=tty0
-defines that opening /dev/console will get you the current foreground
+defines that opening ``/dev/console`` will get you the current foreground
virtual console, and kernel messages will appear on both the VGA
console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
@@ -44,61 +50,61 @@ first looks for a VGA card and then for a serial port. So if you don't
have a VGA card in your system the first serial port will automatically
become the console.
-You will need to create a new device to use /dev/console. The official
-/dev/console is now character device 5,1.
+You will need to create a new device to use ``/dev/console``. The official
+``/dev/console`` is now character device 5,1.
(You can also use a network device as a console. See
-Documentation/networking/netconsole.txt for information on that.)
+``Documentation/networking/netconsole.txt`` for information on that.)
-Here's an example that will use /dev/ttyS1 (COM2) as the console.
+Here's an example that will use ``/dev/ttyS1`` (COM2) as the console.
Replace the sample values as needed.
-1. Create /dev/console (real console) and /dev/tty0 (master virtual
- console):
+1. Create ``/dev/console`` (real console) and ``/dev/tty0`` (master virtual
+ console)::
- cd /dev
- rm -f console tty0
- mknod -m 622 console c 5 1
- mknod -m 622 tty0 c 4 0
+ cd /dev
+ rm -f console tty0
+ mknod -m 622 console c 5 1
+ mknod -m 622 tty0 c 4 0
2. LILO can also take input from a serial device. This is a very
useful option. To tell LILO to use the serial port:
- In lilo.conf (global section):
+ In lilo.conf (global section)::
- serial = 1,9600n8 (ttyS1, 9600 bd, no parity, 8 bits)
+ serial = 1,9600n8 (ttyS1, 9600 bd, no parity, 8 bits)
3. Adjust to kernel flags for the new kernel,
- again in lilo.conf (kernel section)
+ again in lilo.conf (kernel section)::
- append = "console=ttyS1,9600"
+ append = "console=ttyS1,9600"
4. Make sure a getty runs on the serial port so that you can login to
it once the system is done booting. This is done by adding a line
- like this to /etc/inittab (exact syntax depends on your getty):
+ like this to ``/etc/inittab`` (exact syntax depends on your getty)::
- S1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
+ S1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
-5. Init and /etc/ioctl.save
+5. Init and ``/etc/ioctl.save``
- Sysvinit remembers its stty settings in a file in /etc, called
- `/etc/ioctl.save'. REMOVE THIS FILE before using the serial
+ Sysvinit remembers its stty settings in a file in ``/etc``, called
+ ``/etc/ioctl.save``. REMOVE THIS FILE before using the serial
console for the first time, because otherwise init will probably
set the baudrate to 38400 (baudrate of the virtual console).
-6. /dev/console and X
+6. ``/dev/console`` and X
Programs that want to do something with the virtual console usually
- open /dev/console. If you have created the new /dev/console device,
+ open ``/dev/console``. If you have created the new ``/dev/console`` device,
and your console is NOT the virtual console some programs will fail.
Those are programs that want to access the VT interface, and use
- /dev/console instead of /dev/tty0. Some of those programs are:
+ ``/dev/console instead of /dev/tty0``. Some of those programs are::
- Xfree86, svgalib, gpm, SVGATextMode
+ Xfree86, svgalib, gpm, SVGATextMode
It should be fixed in modern versions of these programs though.
- Note that if you boot without a console= option (or with
- console=/dev/tty0), /dev/console is the same as /dev/tty0. In that
- case everything will still work.
+ Note that if you boot without a ``console=`` option (or with
+ ``console=/dev/tty0``), ``/dev/console`` is the same as ``/dev/tty0``.
+ In that case everything will still work.
7. Thanks
diff --git a/Documentation/admin-guide/sysfs-rules.rst b/Documentation/admin-guide/sysfs-rules.rst
new file mode 100644
index 000000000000..abad33526aca
--- /dev/null
+++ b/Documentation/admin-guide/sysfs-rules.rst
@@ -0,0 +1,192 @@
+Rules on how to access information in sysfs
+===========================================
+
+The kernel-exported sysfs exports internal kernel implementation details
+and depends on internal kernel structures and layout. It is agreed upon
+by the kernel developers that the Linux kernel does not provide a stable
+internal API. Therefore, there are aspects of the sysfs interface that
+may not be stable across kernel releases.
+
+To minimize the risk of breaking users of sysfs, which are in most cases
+low-level userspace applications, with a new kernel release, the users
+of sysfs must follow some rules to use an as-abstract-as-possible way to
+access this filesystem. The current udev and HAL programs already
+implement this and users are encouraged to plug, if possible, into the
+abstractions these programs provide instead of accessing sysfs directly.
+
+But if you really do want or need to access sysfs directly, please follow
+the following rules and then your programs should work with future
+versions of the sysfs interface.
+
+- Do not use libsysfs
+ It makes assumptions about sysfs which are not true. Its API does not
+ offer any abstraction, it exposes all the kernel driver-core
+ implementation details in its own API. Therefore it is not better than
+ reading directories and opening the files yourself.
+ Also, it is not actively maintained, in the sense of reflecting the
+ current kernel development. The goal of providing a stable interface
+ to sysfs has failed; it causes more problems than it solves. It
+ violates many of the rules in this document.
+
+- sysfs is always at ``/sys``
+ Parsing ``/proc/mounts`` is a waste of time. Other mount points are a
+ system configuration bug you should not try to solve. For test cases,
+ possibly support a ``SYSFS_PATH`` environment variable to overwrite the
+ application's behavior, but never try to search for sysfs. Never try
+ to mount it, if you are not an early boot script.
+
+- devices are only "devices"
+ There is no such thing like class-, bus-, physical devices,
+ interfaces, and such that you can rely on in userspace. Everything is
+ just simply a "device". Class-, bus-, physical, ... types are just
+ kernel implementation details which should not be expected by
+ applications that look for devices in sysfs.
+
+ The properties of a device are:
+
+ - devpath (``/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0``)
+
+ - identical to the DEVPATH value in the event sent from the kernel
+ at device creation and removal
+ - the unique key to the device at that point in time
+ - the kernel's path to the device directory without the leading
+ ``/sys``, and always starting with a slash
+ - all elements of a devpath must be real directories. Symlinks
+ pointing to /sys/devices must always be resolved to their real
+ target and the target path must be used to access the device.
+ That way the devpath to the device matches the devpath of the
+ kernel used at event time.
+ - using or exposing symlink values as elements in a devpath string
+ is a bug in the application
+
+ - kernel name (``sda``, ``tty``, ``0000:00:1f.2``, ...)
+
+ - a directory name, identical to the last element of the devpath
+ - applications need to handle spaces and characters like ``!`` in
+ the name
+
+ - subsystem (``block``, ``tty``, ``pci``, ...)
+
+ - simple string, never a path or a link
+ - retrieved by reading the "subsystem"-link and using only the
+ last element of the target path
+
+ - driver (``tg3``, ``ata_piix``, ``uhci_hcd``)
+
+ - a simple string, which may contain spaces, never a path or a
+ link
+ - it is retrieved by reading the "driver"-link and using only the
+ last element of the target path
+ - devices which do not have "driver"-link just do not have a
+ driver; copying the driver value in a child device context is a
+ bug in the application
+
+ - attributes
+
+ - the files in the device directory or files below subdirectories
+ of the same device directory
+ - accessing attributes reached by a symlink pointing to another device,
+ like the "device"-link, is a bug in the application
+
+ Everything else is just a kernel driver-core implementation detail
+ that should not be assumed to be stable across kernel releases.
+
+- Properties of parent devices never belong into a child device.
+ Always look at the parent devices themselves for determining device
+ context properties. If the device ``eth0`` or ``sda`` does not have a
+ "driver"-link, then this device does not have a driver. Its value is empty.
+ Never copy any property of the parent-device into a child-device. Parent
+ device properties may change dynamically without any notice to the
+ child device.
+
+- Hierarchy in a single device tree
+ There is only one valid place in sysfs where hierarchy can be examined
+ and this is below: ``/sys/devices.``
+ It is planned that all device directories will end up in the tree
+ below this directory.
+
+- Classification by subsystem
+ There are currently three places for classification of devices:
+ ``/sys/block,`` ``/sys/class`` and ``/sys/bus.`` It is planned that these will
+ not contain any device directories themselves, but only flat lists of
+ symlinks pointing to the unified ``/sys/devices`` tree.
+ All three places have completely different rules on how to access
+ device information. It is planned to merge all three
+ classification directories into one place at ``/sys/subsystem``,
+ following the layout of the bus directories. All buses and
+ classes, including the converted block subsystem, will show up
+ there.
+ The devices belonging to a subsystem will create a symlink in the
+ "devices" directory at ``/sys/subsystem/<name>/devices``,
+
+ If ``/sys/subsystem`` exists, ``/sys/bus``, ``/sys/class`` and ``/sys/block``
+ can be ignored. If it does not exist, you always have to scan all three
+ places, as the kernel is free to move a subsystem from one place to
+ the other, as long as the devices are still reachable by the same
+ subsystem name.
+
+ Assuming ``/sys/class/<subsystem>`` and ``/sys/bus/<subsystem>``, or
+ ``/sys/block`` and ``/sys/class/block`` are not interchangeable is a bug in
+ the application.
+
+- Block
+ The converted block subsystem at ``/sys/class/block`` or
+ ``/sys/subsystem/block`` will contain the links for disks and partitions
+ at the same level, never in a hierarchy. Assuming the block subsystem to
+ contain only disks and not partition devices in the same flat list is
+ a bug in the application.
+
+- "device"-link and <subsystem>:<kernel name>-links
+ Never depend on the "device"-link. The "device"-link is a workaround
+ for the old layout, where class devices are not created in
+ ``/sys/devices/`` like the bus devices. If the link-resolving of a
+ device directory does not end in ``/sys/devices/``, you can use the
+ "device"-link to find the parent devices in ``/sys/devices/``, That is the
+ single valid use of the "device"-link; it must never appear in any
+ path as an element. Assuming the existence of the "device"-link for
+ a device in ``/sys/devices/`` is a bug in the application.
+ Accessing ``/sys/class/net/eth0/device`` is a bug in the application.
+
+ Never depend on the class-specific links back to the ``/sys/class``
+ directory. These links are also a workaround for the design mistake
+ that class devices are not created in ``/sys/devices.`` If a device
+ directory does not contain directories for child devices, these links
+ may be used to find the child devices in ``/sys/class.`` That is the single
+ valid use of these links; they must never appear in any path as an
+ element. Assuming the existence of these links for devices which are
+ real child device directories in the ``/sys/devices`` tree is a bug in
+ the application.
+
+ It is planned to remove all these links when all class device
+ directories live in ``/sys/devices.``
+
+- Position of devices along device chain can change.
+ Never depend on a specific parent device position in the devpath,
+ or the chain of parent devices. The kernel is free to insert devices into
+ the chain. You must always request the parent device you are looking for
+ by its subsystem value. You need to walk up the chain until you find
+ the device that matches the expected subsystem. Depending on a specific
+ position of a parent device or exposing relative paths using ``../`` to
+ access the chain of parents is a bug in the application.
+
+- When reading and writing sysfs device attribute files, avoid dependency
+ on specific error codes wherever possible. This minimizes coupling to
+ the error handling implementation within the kernel.
+
+ In general, failures to read or write sysfs device attributes shall
+ propagate errors wherever possible. Common errors include, but are not
+ limited to:
+
+ ``-EIO``: The read or store operation is not supported, typically
+ returned by the sysfs system itself if the read or store pointer
+ is ``NULL``.
+
+ ``-ENXIO``: The read or store operation failed
+
+ Error codes will not be changed without good reason, and should a change
+ to error codes result in user-space breakage, it will be fixed, or the
+ the offending change will be reverted.
+
+ Userspace applications can, however, expect the format and contents of
+ the attribute files to remain consistent in the absence of a version
+ attribute change in the context of a given attribute.
diff --git a/Documentation/admin-guide/sysrq.rst b/Documentation/admin-guide/sysrq.rst
new file mode 100644
index 000000000000..d1712ea2d314
--- /dev/null
+++ b/Documentation/admin-guide/sysrq.rst
@@ -0,0 +1,289 @@
+Linux Magic System Request Key Hacks
+====================================
+
+Documentation for sysrq.c
+
+What is the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is a 'magical' key combo you can hit which the kernel will respond to
+regardless of whatever else it is doing, unless it is completely locked up.
+
+How do I enable the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. When running a kernel with SysRq compiled in,
+/proc/sys/kernel/sysrq controls the functions allowed to be invoked via
+the SysRq key. The default value in this file is set by the
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
+to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
+
+ - 0 - disable sysrq completely
+ - 1 - enable all functions of sysrq
+ - >1 - bitmask of allowed sysrq functions (see below for detailed function
+ description)::
+
+ 2 = 0x2 - enable control of console logging level
+ 4 = 0x4 - enable control of keyboard (SAK, unraw)
+ 8 = 0x8 - enable debugging dumps of processes etc.
+ 16 = 0x10 - enable sync command
+ 32 = 0x20 - enable remount read-only
+ 64 = 0x40 - enable signalling of processes (term, kill, oom-kill)
+ 128 = 0x80 - allow reboot/poweroff
+ 256 = 0x100 - allow nicing of all RT tasks
+
+You can set the value in the file by the following command::
+
+ echo "number" >/proc/sys/kernel/sysrq
+
+The number may be written here either as decimal or as hexadecimal
+with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
+written in hexadecimal.
+
+Note that the value of ``/proc/sys/kernel/sysrq`` influences only the invocation
+via a keyboard. Invocation of any operation via ``/proc/sysrq-trigger`` is
+always allowed (by a user with admin privileges).
+
+How do I use the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On x86 - You press the key combo :kbd:`ALT-SysRq-<command key>`.
+
+.. note::
+ Some
+ keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
+ also known as the 'Print Screen' key. Also some keyboards cannot
+ handle so many keys being pressed at the same time, so you might
+ have better luck with press :kbd:`Alt`, press :kbd:`SysRq`,
+ release :kbd:`SysRq`, press :kbd:`<command key>`, release everything.
+
+On SPARC - You press :kbd:`ALT-STOP-<command key>`, I believe.
+
+On the serial console (PC style standard serial ports only)
+ You send a ``BREAK``, then within 5 seconds a command key. Sending
+ ``BREAK`` twice is interpreted as a normal BREAK.
+
+On PowerPC
+ Press :kbd:`ALT - Print Screen` (or :kbd:`F13`) - :kbd:`<command key>`,
+ :kbd:`Print Screen` (or :kbd:`F13`) - :kbd:`<command key>` may suffice.
+
+On other
+ If you know of the key combos for other architectures, please
+ let me know so I can add them to this section.
+
+On all
+ write a character to /proc/sysrq-trigger. e.g.::
+
+ echo t > /proc/sysrq-trigger
+
+What are the 'command' keys?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+=========== ===================================================================
+Command Function
+=========== ===================================================================
+``b`` Will immediately reboot the system without syncing or unmounting
+ your disks.
+
+``c`` Will perform a system crash by a NULL pointer dereference.
+ A crashdump will be taken if configured.
+
+``d`` Shows all locks that are held.
+
+``e`` Send a SIGTERM to all processes, except for init.
+
+``f`` Will call the oom killer to kill a memory hog process, but do not
+ panic if nothing can be killed.
+
+``g`` Used by kgdb (kernel debugger)
+
+``h`` Will display help (actually any other key than those listed
+ here will display help. but ``h`` is easy to remember :-)
+
+``i`` Send a SIGKILL to all processes, except for init.
+
+``j`` Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl.
+
+``k`` Secure Access Key (SAK) Kills all programs on the current virtual
+ console. NOTE: See important comments below in SAK section.
+
+``l`` Shows a stack backtrace for all active CPUs.
+
+``m`` Will dump current memory info to your console.
+
+``n`` Used to make RT tasks nice-able
+
+``o`` Will shut your system off (if configured and supported).
+
+``p`` Will dump the current registers and flags to your console.
+
+``q`` Will dump per CPU lists of all armed hrtimers (but NOT regular
+ timer_list timers) and detailed information about all
+ clockevent devices.
+
+``r`` Turns off keyboard raw mode and sets it to XLATE.
+
+``s`` Will attempt to sync all mounted filesystems.
+
+``t`` Will dump a list of current tasks and their information to your
+ console.
+
+``u`` Will attempt to remount all mounted filesystems read-only.
+
+``v`` Forcefully restores framebuffer console
+``v`` Causes ETM buffer dump [ARM-specific]
+
+``w`` Dumps tasks that are in uninterruptable (blocked) state.
+
+``x`` Used by xmon interface on ppc/powerpc platforms.
+ Show global PMU Registers on sparc64.
+ Dump all TLB entries on MIPS.
+
+``y`` Show global CPU Registers [SPARC-64 specific]
+
+``z`` Dump the ftrace buffer
+
+``0``-``9`` Sets the console log level, controlling which kernel messages
+ will be printed to your console. (``0``, for example would make
+ it so that only emergency messages like PANICs or OOPSes would
+ make it to your console.)
+=========== ===================================================================
+
+Okay, so what can I use them for?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Well, unraw(r) is very handy when your X server or a svgalib program crashes.
+
+sak(k) (Secure Access Key) is useful when you want to be sure there is no
+trojan program running at console which could grab your password
+when you would try to login. It will kill all programs on given console,
+thus letting you make sure that the login prompt you see is actually
+the one from init, not some trojan program.
+
+.. important::
+
+ In its true form it is not a true SAK like the one in a
+ c2 compliant system, and it should not be mistaken as
+ such.
+
+It seems others find it useful as (System Attention Key) which is
+useful when you want to exit a program that will not let you switch consoles.
+(For example, X or a svgalib program.)
+
+``reboot(b)`` is good when you're unable to shut down. But you should also
+``sync(s)`` and ``umount(u)`` first.
+
+``crash(c)`` can be used to manually trigger a crashdump when the system is hung.
+Note that this just triggers a crash if there is no dump mechanism available.
+
+``sync(s)`` is great when your system is locked up, it allows you to sync your
+disks and will certainly lessen the chance of data loss and fscking. Note
+that the sync hasn't taken place until you see the "OK" and "Done" appear
+on the screen. (If the kernel is really in strife, you may not ever get the
+OK or Done message...)
+
+``umount(u)`` is basically useful in the same ways as ``sync(s)``. I generally
+``sync(s)``, ``umount(u)``, then ``reboot(b)`` when my system locks. It's saved
+me many a fsck. Again, the unmount (remount read-only) hasn't taken place until
+you see the "OK" and "Done" message appear on the screen.
+
+The loglevels ``0``-``9`` are useful when your console is being flooded with
+kernel messages you do not want to see. Selecting ``0`` will prevent all but
+the most urgent kernel messages from reaching your console. (They will
+still be logged if syslogd/klogd are alive, though.)
+
+``term(e)`` and ``kill(i)`` are useful if you have some sort of runaway process
+you are unable to kill any other way, especially if it's spawning other
+processes.
+
+"just thaw ``it(j)``" is useful if your system becomes unresponsive due to a
+frozen (probably root) filesystem via the FIFREEZE ioctl.
+
+Sometimes SysRq seems to get 'stuck' after using it, what can I do?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+That happens to me, also. I've found that tapping shift, alt, and control
+on both sides of the keyboard, and hitting an invalid sysrq sequence again
+will fix the problem. (i.e., something like :kbd:`alt-sysrq-z`). Switching to
+another virtual console (:kbd:`ALT+Fn`) and then back again should also help.
+
+I hit SysRq, but nothing seems to happen, what's wrong?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are some keyboards that produce a different keycode for SysRq than the
+pre-defined value of 99 (see ``KEY_SYSRQ`` in ``include/linux/input.h``), or
+which don't have a SysRq key at all. In these cases, run ``showkey -s`` to find
+an appropriate scancode sequence, and use ``setkeycodes <sequence> 99`` to map
+this sequence to the usual SysRq code (e.g., ``setkeycodes e05b 99``). It's
+probably best to put this command in a boot script. Oh, and by the way, you
+exit ``showkey`` by not typing anything for ten seconds.
+
+I want to add SysRQ key events to a module, how does it work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to register a basic function with the table, you must first include
+the header ``include/linux/sysrq.h``, this will define everything else you need.
+Next, you must create a ``sysrq_key_op`` struct, and populate it with A) the key
+handler function you will use, B) a help_msg string, that will print when SysRQ
+prints help, and C) an action_msg string, that will print right before your
+handler is called. Your handler must conform to the prototype in 'sysrq.h'.
+
+After the ``sysrq_key_op`` is created, you can call the kernel function
+``register_sysrq_key(int key, struct sysrq_key_op *op_p);`` this will
+register the operation pointed to by ``op_p`` at table key 'key',
+if that slot in the table is blank. At module unload time, you must call
+the function ``unregister_sysrq_key(int key, struct sysrq_key_op *op_p)``, which
+will remove the key op pointed to by 'op_p' from the key 'key', if and only if
+it is currently registered in that slot. This is in case the slot has been
+overwritten since you registered it.
+
+The Magic SysRQ system works by registering key operations against a key op
+lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
+a number of operations registered into it at compile time, but is mutable,
+and 2 functions are exported for interface to it::
+
+ register_sysrq_key and unregister_sysrq_key.
+
+Of course, never ever leave an invalid pointer in the table. I.e., when
+your module that called register_sysrq_key() exits, it must call
+unregister_sysrq_key() to clean up the sysrq key table entry that it used.
+Null pointers in the table are always safe. :)
+
+If for some reason you feel the need to call the handle_sysrq function from
+within a function called by handle_sysrq, you must be aware that you are in
+a lock (you are also in an interrupt handler, which means don't sleep!), so
+you must call ``__handle_sysrq_nolock`` instead.
+
+When I hit a SysRq key combination only the header appears on the console?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sysrq output is subject to the same console loglevel control as all
+other console output. This means that if the kernel was booted 'quiet'
+as is common on distro kernels the output may not appear on the actual
+console, even though it will appear in the dmesg buffer, and be accessible
+via the dmesg command and to the consumers of ``/proc/kmsg``. As a specific
+exception the header line from the sysrq command is passed to all console
+consumers as if the current loglevel was maximum. If only the header
+is emitted it is almost certain that the kernel loglevel is too low.
+Should you require the output on the console channel then you will need
+to temporarily up the console loglevel using :kbd:`alt-sysrq-8` or::
+
+ echo 8 > /proc/sysrq-trigger
+
+Remember to return the loglevel to normal after triggering the sysrq
+command you are interested in.
+
+I have more questions, who can I ask?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Just ask them on the linux-kernel mailing list:
+ linux-kernel@vger.kernel.org
+
+Credits
+~~~~~~~
+
+Written by Mydraal <vulpyne@vulpyne.net>
+Updated by Adam Sulmicki <adam@cfar.umd.edu>
+Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
+Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst
new file mode 100644
index 000000000000..1df03b5cb02f
--- /dev/null
+++ b/Documentation/admin-guide/tainted-kernels.rst
@@ -0,0 +1,59 @@
+Tainted kernels
+---------------
+
+Some oops reports contain the string **'Tainted: '** after the program
+counter. This indicates that the kernel has been tainted by some
+mechanism. The string is followed by a series of position-sensitive
+characters, each representing a particular tainted value.
+
+ 1) 'G' if all modules loaded have a GPL or compatible license, 'P' if
+ any proprietary module has been loaded. Modules without a
+ MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
+ insmod as GPL compatible are assumed to be proprietary.
+
+ 2) ``F`` if any module was force loaded by ``insmod -f``, ``' '`` if all
+ modules were loaded normally.
+
+ 3) ``S`` if the oops occurred on an SMP kernel running on hardware that
+ hasn't been certified as safe to run multiprocessor.
+ Currently this occurs only on various Athlons that are not
+ SMP capable.
+
+ 4) ``R`` if a module was force unloaded by ``rmmod -f``, ``' '`` if all
+ modules were unloaded normally.
+
+ 5) ``M`` if any processor has reported a Machine Check Exception,
+ ``' '`` if no Machine Check Exceptions have occurred.
+
+ 6) ``B`` if a page-release function has found a bad page reference or
+ some unexpected page flags.
+
+ 7) ``U`` if a user or user application specifically requested that the
+ Tainted flag be set, ``' '`` otherwise.
+
+ 8) ``D`` if the kernel has died recently, i.e. there was an OOPS or BUG.
+
+ 9) ``A`` if the ACPI table has been overridden.
+
+ 10) ``W`` if a warning has previously been issued by the kernel.
+ (Though some warnings may set more specific taint flags.)
+
+ 11) ``C`` if a staging driver has been loaded.
+
+ 12) ``I`` if the kernel is working around a severe bug in the platform
+ firmware (BIOS or similar).
+
+ 13) ``O`` if an externally-built ("out-of-tree") module has been loaded.
+
+ 14) ``E`` if an unsigned module has been loaded in a kernel supporting
+ module signature.
+
+ 15) ``L`` if a soft lockup has previously occurred on the system.
+
+ 16) ``K`` if the kernel has been live patched.
+
+The primary reason for the **'Tainted: '** string is to tell kernel
+debuggers if this is a clean kernel or if anything unusual has
+occurred. Tainting is permanent: even if an offending module is
+unloaded, the tainted value remains to indicate that the kernel is not
+trustworthy.
diff --git a/Documentation/unicode.txt b/Documentation/admin-guide/unicode.rst
index 4a33f81cadb1..7425a3351321 100644
--- a/Documentation/unicode.txt
+++ b/Documentation/admin-guide/unicode.rst
@@ -1,12 +1,16 @@
+Unicode support
+===============
+
Last update: 2005-01-17, version 1.4
This file is maintained by H. Peter Anvin <unicode@lanana.org> as part
of the Linux Assigned Names And Numbers Authority (LANANA) project.
The current version can be found at:
- http://www.lanana.org/docs/unicode/unicode.txt
+ http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
- ------------------------
+Introduction
+------------
The Linux kernel code has been rewritten to use Unicode to map
characters to fonts. By downloading a single Unicode-to-font table,
@@ -16,12 +20,14 @@ the font as indicated.
This changes the semantics of the eight-bit character tables subtly.
The four character tables are now:
+=============== =============================== ================
Map symbol Map name Escape code (G0)
-
+=============== =============================== ================
LAT1_MAP Latin-1 (ISO 8859-1) ESC ( B
GRAF_MAP DEC VT100 pseudographics ESC ( 0
IBMPC_MAP IBM code page 437 ESC ( U
USER_MAP User defined ESC ( K
+=============== =============================== ================
In particular, ESC ( U is no longer "straight to font", since the font
might be completely different than the IBM character set. This
@@ -55,10 +61,12 @@ In addition, the following characters not present in Unicode 1.1.4
have been defined; these are used by the DEC VT graphics map. [v1.2]
THIS USE IS OBSOLETE AND SHOULD NO LONGER BE USED; PLEASE SEE BELOW.
+====== ======================================
U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
+====== ======================================
The DEC VT220 uses a 6x10 character matrix, and these characters form
a smooth progression in the DEC VT graphics character set. I have
@@ -74,10 +82,12 @@ keyboard symbols that are unlikely to ever be added to Unicode proper
since they are horribly vendor-specific. This, of course, is an
excellent example of horrible design.
+====== ======================================
U+F810 KEYBOARD SYMBOL FLYING FLAG
U+F811 KEYBOARD SYMBOL PULLDOWN MENU
U+F812 KEYBOARD SYMBOL OPEN APPLE
U+F813 KEYBOARD SYMBOL SOLID APPLE
+====== ======================================
Klingon language support
------------------------
@@ -99,8 +109,10 @@ of the dingbats/symbols/forms type and this is a language, I have
located it at the end, on a 16-cell boundary in keeping with standard
Unicode practice.
-NOTE: This range is now officially managed by the ConScript Unicode
-Registry. The normative reference is at:
+.. note::
+
+ This range is now officially managed by the ConScript Unicode
+ Registry. The normative reference is at:
http://www.evertype.com/standards/csur/klingon.html
@@ -112,6 +124,7 @@ However, since the set of symbols appear to be consistent throughout,
with only the actual shapes being different, in keeping with standard
Unicode practice these differences are considered font variants.
+====== =======================================================
U+F8D0 KLINGON LETTER A
U+F8D1 KLINGON LETTER B
U+F8D2 KLINGON LETTER CH
@@ -155,6 +168,7 @@ U+F8F9 KLINGON DIGIT NINE
U+F8FD KLINGON COMMA
U+F8FE KLINGON FULL STOP
U+F8FF KLINGON SYMBOL FOR EMPIRE
+====== =======================================================
Other Fictional and Artificial Scripts
--------------------------------------
diff --git a/Documentation/admin-guide/vga-softcursor.rst b/Documentation/admin-guide/vga-softcursor.rst
new file mode 100644
index 000000000000..a663a745cff4
--- /dev/null
+++ b/Documentation/admin-guide/vga-softcursor.rst
@@ -0,0 +1,66 @@
+Software cursor for VGA
+=======================
+
+by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+and Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+Linux now has some ability to manipulate cursor appearance. Normally, you
+can set the size of hardware cursor (and also work around some ugly bugs in
+those miserable Trident cards [#f1]_. You can now play a few new tricks:
+you can make your cursor look
+
+like a non-blinking red block, make it inverse background of the character it's
+over or to highlight that character and still choose whether the original
+hardware cursor should remain visible or not. There may be other things I have
+never thought of.
+
+The cursor appearance is controlled by a ``<ESC>[?1;2;3c`` escape sequence
+where 1, 2 and 3 are parameters described below. If you omit any of them,
+they will default to zeroes.
+
+first Parameter
+ specifies cursor size::
+
+ 0=default
+ 1=invisible
+ 2=underline,
+ ...
+ 8=full block
+ + 16 if you want the software cursor to be applied
+ + 32 if you want to always change the background color
+ + 64 if you dislike having the background the same as the
+ foreground.
+
+ Highlights are ignored for the last two flags.
+
+second parameter
+ selects character attribute bits you want to change
+ (by simply XORing them with the value of this parameter). On standard
+ VGA, the high four bits specify background and the low four the
+ foreground. In both groups, low three bits set color (as in normal
+ color codes used by the console) and the most significant one turns
+ on highlight (or sometimes blinking -- it depends on the configuration
+ of your VGA).
+
+third parameter
+ consists of character attribute bits you want to set.
+
+ Bit setting takes place before bit toggling, so you can simply clear a
+ bit by including it in both the set mask and the toggle mask.
+
+.. [#f1] see ``#define TRIDENT_GLITCH`` in ``drivers/video/vgacon.c``.
+
+Examples
+--------
+
+To get normal blinking underline, use::
+
+ echo -e '\033[?2c'
+
+To get blinking block, use::
+
+ echo -e '\033[?6c'
+
+To get red non-blinking block, use::
+
+ echo -e '\033[?17;0;64c'
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index 83c1df2fc758..259f00af3ab3 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -51,7 +51,7 @@ As an alternative, the boot loader can pass the relevant 'console='
option to the kernel via the tagged lists specifying the port, and
serial format options as described in
- Documentation/kernel-parameters.txt.
+ Documentation/admin-guide/kernel-parameters.rst.
3. Detect the machine type
diff --git a/Documentation/assoc_array.txt b/Documentation/assoc_array.txt
deleted file mode 100644
index 2f2c6cdd73c0..000000000000
--- a/Documentation/assoc_array.txt
+++ /dev/null
@@ -1,574 +0,0 @@
- ========================================
- GENERIC ASSOCIATIVE ARRAY IMPLEMENTATION
- ========================================
-
-Contents:
-
- - Overview.
-
- - The public API.
- - Edit script.
- - Operations table.
- - Manipulation functions.
- - Access functions.
- - Index key form.
-
- - Internal workings.
- - Basic internal tree layout.
- - Shortcuts.
- - Splitting and collapsing nodes.
- - Non-recursive iteration.
- - Simultaneous alteration and iteration.
-
-
-========
-OVERVIEW
-========
-
-This associative array implementation is an object container with the following
-properties:
-
- (1) Objects are opaque pointers. The implementation does not care where they
- point (if anywhere) or what they point to (if anything).
-
- [!] NOTE: Pointers to objects _must_ be zero in the least significant bit.
-
- (2) Objects do not need to contain linkage blocks for use by the array. This
- permits an object to be located in multiple arrays simultaneously.
- Rather, the array is made up of metadata blocks that point to objects.
-
- (3) Objects require index keys to locate them within the array.
-
- (4) Index keys must be unique. Inserting an object with the same key as one
- already in the array will replace the old object.
-
- (5) Index keys can be of any length and can be of different lengths.
-
- (6) Index keys should encode the length early on, before any variation due to
- length is seen.
-
- (7) Index keys can include a hash to scatter objects throughout the array.
-
- (8) The array can iterated over. The objects will not necessarily come out in
- key order.
-
- (9) The array can be iterated over whilst it is being modified, provided the
- RCU readlock is being held by the iterator. Note, however, under these
- circumstances, some objects may be seen more than once. If this is a
- problem, the iterator should lock against modification. Objects will not
- be missed, however, unless deleted.
-
-(10) Objects in the array can be looked up by means of their index key.
-
-(11) Objects can be looked up whilst the array is being modified, provided the
- RCU readlock is being held by the thread doing the look up.
-
-The implementation uses a tree of 16-pointer nodes internally that are indexed
-on each level by nibbles from the index key in the same manner as in a radix
-tree. To improve memory efficiency, shortcuts can be emplaced to skip over
-what would otherwise be a series of single-occupancy nodes. Further, nodes
-pack leaf object pointers into spare space in the node rather than making an
-extra branch until as such time an object needs to be added to a full node.
-
-
-==============
-THE PUBLIC API
-==============
-
-The public API can be found in <linux/assoc_array.h>. The associative array is
-rooted on the following structure:
-
- struct assoc_array {
- ...
- };
-
-The code is selected by enabling CONFIG_ASSOCIATIVE_ARRAY.
-
-
-EDIT SCRIPT
------------
-
-The insertion and deletion functions produce an 'edit script' that can later be
-applied to effect the changes without risking ENOMEM. This retains the
-preallocated metadata blocks that will be installed in the internal tree and
-keeps track of the metadata blocks that will be removed from the tree when the
-script is applied.
-
-This is also used to keep track of dead blocks and dead objects after the
-script has been applied so that they can be freed later. The freeing is done
-after an RCU grace period has passed - thus allowing access functions to
-proceed under the RCU read lock.
-
-The script appears as outside of the API as a pointer of the type:
-
- struct assoc_array_edit;
-
-There are two functions for dealing with the script:
-
- (1) Apply an edit script.
-
- void assoc_array_apply_edit(struct assoc_array_edit *edit);
-
- This will perform the edit functions, interpolating various write barriers
- to permit accesses under the RCU read lock to continue. The edit script
- will then be passed to call_rcu() to free it and any dead stuff it points
- to.
-
- (2) Cancel an edit script.
-
- void assoc_array_cancel_edit(struct assoc_array_edit *edit);
-
- This frees the edit script and all preallocated memory immediately. If
- this was for insertion, the new object is _not_ released by this function,
- but must rather be released by the caller.
-
-These functions are guaranteed not to fail.
-
-
-OPERATIONS TABLE
-----------------
-
-Various functions take a table of operations:
-
- struct assoc_array_ops {
- ...
- };
-
-This points to a number of methods, all of which need to be provided:
-
- (1) Get a chunk of index key from caller data:
-
- unsigned long (*get_key_chunk)(const void *index_key, int level);
-
- This should return a chunk of caller-supplied index key starting at the
- *bit* position given by the level argument. The level argument will be a
- multiple of ASSOC_ARRAY_KEY_CHUNK_SIZE and the function should return
- ASSOC_ARRAY_KEY_CHUNK_SIZE bits. No error is possible.
-
-
- (2) Get a chunk of an object's index key.
-
- unsigned long (*get_object_key_chunk)(const void *object, int level);
-
- As the previous function, but gets its data from an object in the array
- rather than from a caller-supplied index key.
-
-
- (3) See if this is the object we're looking for.
-
- bool (*compare_object)(const void *object, const void *index_key);
-
- Compare the object against an index key and return true if it matches and
- false if it doesn't.
-
-
- (4) Diff the index keys of two objects.
-
- int (*diff_objects)(const void *object, const void *index_key);
-
- Return the bit position at which the index key of the specified object
- differs from the given index key or -1 if they are the same.
-
-
- (5) Free an object.
-
- void (*free_object)(void *object);
-
- Free the specified object. Note that this may be called an RCU grace
- period after assoc_array_apply_edit() was called, so synchronize_rcu() may
- be necessary on module unloading.
-
-
-MANIPULATION FUNCTIONS
-----------------------
-
-There are a number of functions for manipulating an associative array:
-
- (1) Initialise an associative array.
-
- void assoc_array_init(struct assoc_array *array);
-
- This initialises the base structure for an associative array. It can't
- fail.
-
-
- (2) Insert/replace an object in an associative array.
-
- struct assoc_array_edit *
- assoc_array_insert(struct assoc_array *array,
- const struct assoc_array_ops *ops,
- const void *index_key,
- void *object);
-
- This inserts the given object into the array. Note that the least
- significant bit of the pointer must be zero as it's used to type-mark
- pointers internally.
-
- If an object already exists for that key then it will be replaced with the
- new object and the old one will be freed automatically.
-
- The index_key argument should hold index key information and is
- passed to the methods in the ops table when they are called.
-
- This function makes no alteration to the array itself, but rather returns
- an edit script that must be applied. -ENOMEM is returned in the case of
- an out-of-memory error.
-
- The caller should lock exclusively against other modifiers of the array.
-
-
- (3) Delete an object from an associative array.
-
- struct assoc_array_edit *
- assoc_array_delete(struct assoc_array *array,
- const struct assoc_array_ops *ops,
- const void *index_key);
-
- This deletes an object that matches the specified data from the array.
-
- The index_key argument should hold index key information and is
- passed to the methods in the ops table when they are called.
-
- This function makes no alteration to the array itself, but rather returns
- an edit script that must be applied. -ENOMEM is returned in the case of
- an out-of-memory error. NULL will be returned if the specified object is
- not found within the array.
-
- The caller should lock exclusively against other modifiers of the array.
-
-
- (4) Delete all objects from an associative array.
-
- struct assoc_array_edit *
- assoc_array_clear(struct assoc_array *array,
- const struct assoc_array_ops *ops);
-
- This deletes all the objects from an associative array and leaves it
- completely empty.
-
- This function makes no alteration to the array itself, but rather returns
- an edit script that must be applied. -ENOMEM is returned in the case of
- an out-of-memory error.
-
- The caller should lock exclusively against other modifiers of the array.
-
-
- (5) Destroy an associative array, deleting all objects.
-
- void assoc_array_destroy(struct assoc_array *array,
- const struct assoc_array_ops *ops);
-
- This destroys the contents of the associative array and leaves it
- completely empty. It is not permitted for another thread to be traversing
- the array under the RCU read lock at the same time as this function is
- destroying it as no RCU deferral is performed on memory release -
- something that would require memory to be allocated.
-
- The caller should lock exclusively against other modifiers and accessors
- of the array.
-
-
- (6) Garbage collect an associative array.
-
- int assoc_array_gc(struct assoc_array *array,
- const struct assoc_array_ops *ops,
- bool (*iterator)(void *object, void *iterator_data),
- void *iterator_data);
-
- This iterates over the objects in an associative array and passes each one
- to iterator(). If iterator() returns true, the object is kept. If it
- returns false, the object will be freed. If the iterator() function
- returns true, it must perform any appropriate refcount incrementing on the
- object before returning.
-
- The internal tree will be packed down if possible as part of the iteration
- to reduce the number of nodes in it.
-
- The iterator_data is passed directly to iterator() and is otherwise
- ignored by the function.
-
- The function will return 0 if successful and -ENOMEM if there wasn't
- enough memory.
-
- It is possible for other threads to iterate over or search the array under
- the RCU read lock whilst this function is in progress. The caller should
- lock exclusively against other modifiers of the array.
-
-
-ACCESS FUNCTIONS
-----------------
-
-There are two functions for accessing an associative array:
-
- (1) Iterate over all the objects in an associative array.
-
- int assoc_array_iterate(const struct assoc_array *array,
- int (*iterator)(const void *object,
- void *iterator_data),
- void *iterator_data);
-
- This passes each object in the array to the iterator callback function.
- iterator_data is private data for that function.
-
- This may be used on an array at the same time as the array is being
- modified, provided the RCU read lock is held. Under such circumstances,
- it is possible for the iteration function to see some objects twice. If
- this is a problem, then modification should be locked against. The
- iteration algorithm should not, however, miss any objects.
-
- The function will return 0 if no objects were in the array or else it will
- return the result of the last iterator function called. Iteration stops
- immediately if any call to the iteration function results in a non-zero
- return.
-
-
- (2) Find an object in an associative array.
-
- void *assoc_array_find(const struct assoc_array *array,
- const struct assoc_array_ops *ops,
- const void *index_key);
-
- This walks through the array's internal tree directly to the object
- specified by the index key..
-
- This may be used on an array at the same time as the array is being
- modified, provided the RCU read lock is held.
-
- The function will return the object if found (and set *_type to the object
- type) or will return NULL if the object was not found.
-
-
-INDEX KEY FORM
---------------
-
-The index key can be of any form, but since the algorithms aren't told how long
-the key is, it is strongly recommended that the index key includes its length
-very early on before any variation due to the length would have an effect on
-comparisons.
-
-This will cause leaves with different length keys to scatter away from each
-other - and those with the same length keys to cluster together.
-
-It is also recommended that the index key begin with a hash of the rest of the
-key to maximise scattering throughout keyspace.
-
-The better the scattering, the wider and lower the internal tree will be.
-
-Poor scattering isn't too much of a problem as there are shortcuts and nodes
-can contain mixtures of leaves and metadata pointers.
-
-The index key is read in chunks of machine word. Each chunk is subdivided into
-one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
-on a 64-bit CPU, 16 levels. Unless the scattering is really poor, it is
-unlikely that more than one word of any particular index key will have to be
-used.
-
-
-=================
-INTERNAL WORKINGS
-=================
-
-The associative array data structure has an internal tree. This tree is
-constructed of two types of metadata blocks: nodes and shortcuts.
-
-A node is an array of slots. Each slot can contain one of four things:
-
- (*) A NULL pointer, indicating that the slot is empty.
-
- (*) A pointer to an object (a leaf).
-
- (*) A pointer to a node at the next level.
-
- (*) A pointer to a shortcut.
-
-
-BASIC INTERNAL TREE LAYOUT
---------------------------
-
-Ignoring shortcuts for the moment, the nodes form a multilevel tree. The index
-key space is strictly subdivided by the nodes in the tree and nodes occur on
-fixed levels. For example:
-
- Level: 0 1 2 3
- =============== =============== =============== ===============
- NODE D
- NODE B NODE C +------>+---+
- +------>+---+ +------>+---+ | | 0 |
- NODE A | | 0 | | | 0 | | +---+
- +---+ | +---+ | +---+ | : :
- | 0 | | : : | : : | +---+
- +---+ | +---+ | +---+ | | f |
- | 1 |---+ | 3 |---+ | 7 |---+ +---+
- +---+ +---+ +---+
- : : : : | 8 |---+
- +---+ +---+ +---+ | NODE E
- | e |---+ | f | : : +------>+---+
- +---+ | +---+ +---+ | 0 |
- | f | | | f | +---+
- +---+ | +---+ : :
- | NODE F +---+
- +------>+---+ | f |
- | 0 | NODE G +---+
- +---+ +------>+---+
- : : | | 0 |
- +---+ | +---+
- | 6 |---+ : :
- +---+ +---+
- : : | f |
- +---+ +---+
- | f |
- +---+
-
-In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
-Assuming no other meta data nodes in the tree, the key space is divided thusly:
-
- KEY PREFIX NODE
- ========== ====
- 137* D
- 138* E
- 13[0-69-f]* C
- 1[0-24-f]* B
- e6* G
- e[0-57-f]* F
- [02-df]* A
-
-So, for instance, keys with the following example index keys will be found in
-the appropriate nodes:
-
- INDEX KEY PREFIX NODE
- =============== ======= ====
- 13694892892489 13 C
- 13795289025897 137 D
- 13889dde88793 138 E
- 138bbb89003093 138 E
- 1394879524789 12 C
- 1458952489 1 B
- 9431809de993ba - A
- b4542910809cd - A
- e5284310def98 e F
- e68428974237 e6 G
- e7fffcbd443 e F
- f3842239082 - A
-
-To save memory, if a node can hold all the leaves in its portion of keyspace,
-then the node will have all those leaves in it and will not have any metadata
-pointers - even if some of those leaves would like to be in the same slot.
-
-A node can contain a heterogeneous mix of leaves and metadata pointers.
-Metadata pointers must be in the slots that match their subdivisions of key
-space. The leaves can be in any slot not occupied by a metadata pointer. It
-is guaranteed that none of the leaves in a node will match a slot occupied by a
-metadata pointer. If the metadata pointer is there, any leaf whose key matches
-the metadata key prefix must be in the subtree that the metadata pointer points
-to.
-
-In the above example list of index keys, node A will contain:
-
- SLOT CONTENT INDEX KEY (PREFIX)
- ==== =============== ==================
- 1 PTR TO NODE B 1*
- any LEAF 9431809de993ba
- any LEAF b4542910809cd
- e PTR TO NODE F e*
- any LEAF f3842239082
-
-and node B:
-
- 3 PTR TO NODE C 13*
- any LEAF 1458952489
-
-
-SHORTCUTS
----------
-
-Shortcuts are metadata records that jump over a piece of keyspace. A shortcut
-is a replacement for a series of single-occupancy nodes ascending through the
-levels. Shortcuts exist to save memory and to speed up traversal.
-
-It is possible for the root of the tree to be a shortcut - say, for example,
-the tree contains at least 17 nodes all with key prefix '1111'. The insertion
-algorithm will insert a shortcut to skip over the '1111' keyspace in a single
-bound and get to the fourth level where these actually become different.
-
-
-SPLITTING AND COLLAPSING NODES
-------------------------------
-
-Each node has a maximum capacity of 16 leaves and metadata pointers. If the
-insertion algorithm finds that it is trying to insert a 17th object into a
-node, that node will be split such that at least two leaves that have a common
-key segment at that level end up in a separate node rooted on that slot for
-that common key segment.
-
-If the leaves in a full node and the leaf that is being inserted are
-sufficiently similar, then a shortcut will be inserted into the tree.
-
-When the number of objects in the subtree rooted at a node falls to 16 or
-fewer, then the subtree will be collapsed down to a single node - and this will
-ripple towards the root if possible.
-
-
-NON-RECURSIVE ITERATION
------------------------
-
-Each node and shortcut contains a back pointer to its parent and the number of
-slot in that parent that points to it. None-recursive iteration uses these to
-proceed rootwards through the tree, going to the parent node, slot N + 1 to
-make sure progress is made without the need for a stack.
-
-The backpointers, however, make simultaneous alteration and iteration tricky.
-
-
-SIMULTANEOUS ALTERATION AND ITERATION
--------------------------------------
-
-There are a number of cases to consider:
-
- (1) Simple insert/replace. This involves simply replacing a NULL or old
- matching leaf pointer with the pointer to the new leaf after a barrier.
- The metadata blocks don't change otherwise. An old leaf won't be freed
- until after the RCU grace period.
-
- (2) Simple delete. This involves just clearing an old matching leaf. The
- metadata blocks don't change otherwise. The old leaf won't be freed until
- after the RCU grace period.
-
- (3) Insertion replacing part of a subtree that we haven't yet entered. This
- may involve replacement of part of that subtree - but that won't affect
- the iteration as we won't have reached the pointer to it yet and the
- ancestry blocks are not replaced (the layout of those does not change).
-
- (4) Insertion replacing nodes that we're actively processing. This isn't a
- problem as we've passed the anchoring pointer and won't switch onto the
- new layout until we follow the back pointers - at which point we've
- already examined the leaves in the replaced node (we iterate over all the
- leaves in a node before following any of its metadata pointers).
-
- We might, however, re-see some leaves that have been split out into a new
- branch that's in a slot further along than we were at.
-
- (5) Insertion replacing nodes that we're processing a dependent branch of.
- This won't affect us until we follow the back pointers. Similar to (4).
-
- (6) Deletion collapsing a branch under us. This doesn't affect us because the
- back pointers will get us back to the parent of the new node before we
- could see the new node. The entire collapsed subtree is thrown away
- unchanged - and will still be rooted on the same slot, so we shouldn't
- process it a second time as we'll go back to slot + 1.
-
-Note:
-
- (*) Under some circumstances, we need to simultaneously change the parent
- pointer and the parent slot pointer on a node (say, for example, we
- inserted another node before it and moved it up a level). We cannot do
- this without locking against a read - so we have to replace that node too.
-
- However, when we're changing a shortcut into a node this isn't a problem
- as shortcuts only have one slot and so the parent slot number isn't used
- when traversing backwards over one. This means that it's okay to change
- the slot number first - provided suitable barriers are used to make sure
- the parent slot number is read after the back pointer.
-
-Obsolete blocks and leaves are freed up after an RCU grace period has passed,
-so as long as anyone doing walking or iteration holds the RCU read lock, the
-old superstructure should not go away on them.
diff --git a/Documentation/bad_memory.txt b/Documentation/bad_memory.txt
deleted file mode 100644
index df8416213202..000000000000
--- a/Documentation/bad_memory.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-March 2008
-Jan-Simon Moeller, dl9pf@gmx.de
-
-
-How to deal with bad memory e.g. reported by memtest86+ ?
-#########################################################
-
-There are three possibilities I know of:
-
-1) Reinsert/swap the memory modules
-
-2) Buy new modules (best!) or try to exchange the memory
- if you have spare-parts
-
-3) Use BadRAM or memmap
-
-This Howto is about number 3) .
-
-
-BadRAM
-######
-BadRAM is the actively developed and available as kernel-patch
-here: http://rick.vanrein.org/linux/badram/
-
-For more details see the BadRAM documentation.
-
-memmap
-######
-
-memmap is already in the kernel and usable as kernel-parameter at
-boot-time. Its syntax is slightly strange and you may need to
-calculate the values by yourself!
-
-Syntax to exclude a memory area (see kernel-parameters.txt for details):
-memmap=<size>$<address>
-
-Example: memtest86+ reported here errors at address 0x18691458, 0x18698424 and
- some others. All had 0x1869xxxx in common, so I chose a pattern of
- 0x18690000,0xffff0000.
-
-With the numbers of the example above:
-memmap=64K$0x18690000
- or
-memmap=0x10000$0x18690000
-
diff --git a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
deleted file mode 100644
index 8764e9f70821..000000000000
--- a/Documentation/basic_profiling.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-These instructions are deliberately very basic. If you want something clever,
-go read the real docs ;-) Please don't add more stuff, but feel free to
-correct my mistakes ;-) (mbligh@aracnet.com)
-Thanks to John Levon, Dave Hansen, et al. for help writing this.
-
-<test> is the thing you're trying to measure.
-Make sure you have the correct System.map / vmlinux referenced!
-
-It is probably easiest to use "make install" for linux and hack
-/sbin/installkernel to copy vmlinux to /boot, in addition to vmlinuz,
-config, System.map, which are usually installed by default.
-
-Readprofile
------------
-A recent readprofile command is needed for 2.6, such as found in util-linux
-2.12a, which can be downloaded from:
-
-http://www.kernel.org/pub/linux/utils/util-linux/
-
-Most distributions will ship it already.
-
-Add "profile=2" to the kernel command line.
-
-clear readprofile -r
- <test>
-dump output readprofile -m /boot/System.map > captured_profile
-
-Oprofile
---------
-
-Get the source (see Changes for required version) from
-http://oprofile.sourceforge.net/ and add "idle=poll" to the kernel command
-line.
-
-Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
-
-./configure --with-kernel-support
-make install
-
-For superior results, be sure to enable the local APIC. If opreport sees
-a 0Hz CPU, APIC was not on. Be aware that idle=poll may mean a performance
-penalty.
-
-One time setup:
- opcontrol --setup --vmlinux=/boot/vmlinux
-
-clear opcontrol --reset
-start opcontrol --start
- <test>
-stop opcontrol --stop
-dump output opreport > output_file
-
-To only report on the kernel, run opreport -l /boot/vmlinux > output_file
-
-A reset is needed to clear old statistics, which survive a reboot.
-
diff --git a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt
deleted file mode 100644
index ec83bbce547a..000000000000
--- a/Documentation/binfmt_misc.txt
+++ /dev/null
@@ -1,131 +0,0 @@
- Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
- =====================================================================
-
-This Kernel feature allows you to invoke almost (for restrictions see below)
-every program by simply typing its name in the shell.
-This includes for example compiled Java(TM), Python or Emacs programs.
-
-To achieve this you must tell binfmt_misc which interpreter has to be invoked
-with which binary. Binfmt_misc recognises the binary-type by matching some bytes
-at the beginning of the file with a magic byte sequence (masking out specified
-bits) you have supplied. Binfmt_misc can also recognise a filename extension
-aka '.com' or '.exe'.
-
-First you must mount binfmt_misc:
- mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
-
-To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
-upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
-
-Here is what the fields mean:
- - 'name' is an identifier string. A new /proc file will be created with this
- name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
- reasons.
- - 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
- - 'offset' is the offset of the magic/mask in the file, counted in bytes. This
- defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
- when using filename extension matching.
- - 'magic' is the byte sequence binfmt_misc is matching for. The magic string
- may contain hex-encoded characters like \x0a or \xA4. Note that you must
- escape any NUL bytes; parsing halts at the first one. In a shell environment
- you might have to write \\x0a to prevent the shell from eating your \.
- If you chose filename extension matching, this is the extension to be
- recognised (without the '.', the \x0a specials are not allowed). Extension
- matching is case sensitive, and slashes '/' are not allowed!
- - 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
- bits from matching by supplying a string like magic and as long as magic.
- The mask is anded with the byte sequence of the file. Note that you must
- escape any NUL bytes; parsing halts at the first one. Ignored when using
- filename extension matching.
- - 'interpreter' is the program that should be invoked with the binary as first
- argument (specify the full path)
- - 'flags' is an optional field that controls several aspects of the invocation
- of the interpreter. It is a string of capital letters, each controls a
- certain aspect. The following flags are supported -
- 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
- the original argv[0] with the full path to the binary. When this
- flag is included, binfmt_misc will add an argument to the argument
- vector for this purpose, thus preserving the original argv[0].
- e.g. If your interp is set to /bin/foo and you run `blah` (which is
- in /usr/local/bin), then the kernel will execute /bin/foo with
- argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"]. The
- interp has to be aware of this so it can execute /usr/local/bin/blah
- with argv[] set to ["blah"].
- 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
- of the binary to the interpreter as an argument. When this flag is
- included, binfmt_misc will open the file for reading and pass its
- descriptor as an argument, instead of the full path, thus allowing
- the interpreter to execute non-readable binaries. This feature
- should be used with care - the interpreter has to be trusted not to
- emit the contents of the non-readable binary.
- 'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
- the credentials and security token of the new process according to
- the interpreter. When this flag is included, these attributes are
- calculated according to the binary. It also implies the 'O' flag.
- This feature should be used with care as the interpreter
- will run with root permissions when a setuid binary owned by root
- is run with binfmt_misc.
- 'F' - fix binary. The usual behaviour of binfmt_misc is to spawn the
- binary lazily when the misc format file is invoked. However,
- this doesn't work very well in the face of mount namespaces and
- changeroots, so the F mode opens the binary as soon as the
- emulation is installed and uses the opened image to spawn the
- emulator, meaning it is always available once installed,
- regardless of how the environment changes.
-
-
-There are some restrictions:
- - the whole register string may not exceed 1920 characters
- - the magic must reside in the first 128 bytes of the file, i.e.
- offset+size(magic) has to be less than 128
- - the interpreter string may not exceed 127 characters
-
-To use binfmt_misc you have to mount it first. You can mount it with
-"mount -t binfmt_misc none /proc/sys/fs/binfmt_misc" command, or you can add
-a line "none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0" to your
-/etc/fstab so it auto mounts on boot.
-
-You may want to add the binary formats in one of your /etc/rc scripts during
-boot-up. Read the manual of your init program to figure out how to do this
-right.
-
-Think about the order of adding entries! Later added entries are matched first!
-
-
-A few examples (assumed you are in /proc/sys/fs/binfmt_misc):
-
-- enable support for em86 (like binfmt_em86, for Alpha AXP only):
- echo ':i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
- echo ':i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
-
-- enable support for packed DOS applications (pre-configured dosemu hdimages):
- echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
-
-- enable support for Windows executables using wine:
- echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
-
-For java support see Documentation/java.txt
-
-
-You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
-or 1 (to enable) to /proc/sys/fs/binfmt_misc/status or /proc/.../the_name.
-Catting the file tells you the current status of binfmt_misc/the entry.
-
-You can remove one entry or all entries by echoing -1 to /proc/.../the_name
-or /proc/sys/fs/binfmt_misc/status.
-
-
-HINTS:
-======
-
-If you want to pass special arguments to your interpreter, you can
-write a wrapper script for it. See Documentation/java.txt for an
-example.
-
-Your interpreter should NOT look in the PATH for the filename; the kernel
-passes it the full filename (or the file descriptor) to use. Using $PATH can
-cause unexpected behaviour and can be a security hazard.
-
-
-Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 918e1e0d0e78..01ddeaf64b0f 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -348,7 +348,7 @@ Drivers can now specify a request prepare function (q->prep_rq_fn) that the
block layer would invoke to pre-build device commands for a given request,
or perform other preparatory processing for the request. This is routine is
called by elv_next_request(), i.e. typically just before servicing a request.
-(The prepare function would not be called for requests that have REQ_DONTPREP
+(The prepare function would not be called for requests that have RQF_DONTPREP
enabled)
Aside:
@@ -553,8 +553,8 @@ struct request {
struct request_list *rl;
}
-See the rq_flag_bits definitions for an explanation of the various flags
-available. Some bits are used by the block layer or i/o scheduler.
+See the req_ops and req_flag_bits definitions for an explanation of the various
+flags available. Some bits are used by the block layer or i/o scheduler.
The behaviour of the various sector counts are almost the same as before,
except that since we have multi-segment bios, current_nr_sectors refers
diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt
index 1e4f835a659d..895bd3813115 100644
--- a/Documentation/block/cfq-iosched.txt
+++ b/Documentation/block/cfq-iosched.txt
@@ -240,11 +240,11 @@ All cfq queues doing synchronous sequential IO go on to sync-idle tree.
On this tree we idle on each queue individually.
All synchronous non-sequential queues go on sync-noidle tree. Also any
-request which are marked with REQ_NOIDLE go on this service tree. On this
-tree we do not idle on individual queues instead idle on the whole group
-of queues or the tree. So if there are 4 queues waiting for IO to dispatch
-we will idle only once last queue has dispatched the IO and there is
-no more IO on this service tree.
+synchronous write request which is not marked with REQ_IDLE goes on this
+service tree. On this tree we do not idle on individual queues instead idle
+on the whole group of queues or the tree. So if there are 4 queues waiting
+for IO to dispatch we will idle only once last queue has dispatched the IO
+and there is no more IO on this service tree.
All async writes go on async service tree. There is no idling on async
queues.
@@ -257,17 +257,17 @@ tree idling provides isolation with buffered write queues on async tree.
FAQ
===
-Q1. Why to idle at all on queues marked with REQ_NOIDLE.
+Q1. Why to idle at all on queues not marked with REQ_IDLE.
-A1. We only do tree idle (all queues on sync-noidle tree) on queues marked
- with REQ_NOIDLE. This helps in providing isolation with all the sync-idle
+A1. We only do tree idle (all queues on sync-noidle tree) on queues not marked
+ with REQ_IDLE. This helps in providing isolation with all the sync-idle
queues. Otherwise in presence of many sequential readers, other
synchronous IO might not get fair share of disk.
For example, if there are 10 sequential readers doing IO and they get
- 100ms each. If a REQ_NOIDLE request comes in, it will be scheduled
- roughly after 1 second. If after completion of REQ_NOIDLE request we
- do not idle, and after a couple of milli seconds a another REQ_NOIDLE
+ 100ms each. If a !REQ_IDLE request comes in, it will be scheduled
+ roughly after 1 second. If after completion of !REQ_IDLE request we
+ do not idle, and after a couple of milli seconds a another !REQ_IDLE
request comes in, again it will be scheduled after 1second. Repeat it
and notice how a workload can lose its disk share and suffer due to
multiple sequential readers.
@@ -276,16 +276,16 @@ A1. We only do tree idle (all queues on sync-noidle tree) on queues marked
context of fsync, and later some journaling data is written. Journaling
data comes in only after fsync has finished its IO (atleast for ext4
that seemed to be the case). Now if one decides not to idle on fsync
- thread due to REQ_NOIDLE, then next journaling write will not get
+ thread due to !REQ_IDLE, then next journaling write will not get
scheduled for another second. A process doing small fsync, will suffer
badly in presence of multiple sequential readers.
- Hence doing tree idling on threads using REQ_NOIDLE flag on requests
+ Hence doing tree idling on threads using !REQ_IDLE flag on requests
provides isolation from multiple sequential readers and at the same
time we do not idle on individual threads.
-Q2. When to specify REQ_NOIDLE
-A2. I would think whenever one is doing synchronous write and not expecting
+Q2. When to specify REQ_IDLE
+A2. I would think whenever one is doing synchronous write and expecting
more writes to be dispatched from same context soon, should be able
- to specify REQ_NOIDLE on writes and that probably should work well for
+ to specify REQ_IDLE on writes and that probably should work well for
most of the cases.
diff --git a/Documentation/block/null_blk.txt b/Documentation/block/null_blk.txt
index d8880ca30af4..3140dbd860d8 100644
--- a/Documentation/block/null_blk.txt
+++ b/Documentation/block/null_blk.txt
@@ -72,4 +72,4 @@ use_per_node_hctx=[0/1]: Default: 0
queue for each CPU node in the system.
use_lightnvm=[0/1]: Default: 0
- Register device with LightNVM. Requires blk-mq to be used.
+ Register device with LightNVM. Requires blk-mq and CONFIG_NVM to be enabled.
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
index 2a3904030dea..51642159aedb 100644
--- a/Documentation/block/queue-sysfs.txt
+++ b/Documentation/block/queue-sysfs.txt
@@ -58,6 +58,20 @@ When read, this file shows the total number of block IO polls and how
many returned success. Writing '0' to this file will disable polling
for this device. Writing any non-zero value will enable this feature.
+io_poll_delay (RW)
+------------------
+If polling is enabled, this controls what kind of polling will be
+performed. It defaults to -1, which is classic polling. In this mode,
+the CPU will repeatedly ask for completions without giving up any time.
+If set to 0, a hybrid polling mode is used, where the kernel will attempt
+to make an educated guess at when the IO will complete. Based on this
+guess, the kernel will put the process issuing IO to sleep for an amount
+of time, before entering a classic poll loop. This mode might be a
+little slower than pure classic polling, but it will be more efficient.
+If set to a value larger than 0, the kernel will put the process issuing
+IO to sleep for this amont of microseconds before entering classic
+polling.
+
iostats (RW)
-------------
This file is used to control (on/off) the iostats accounting of the
@@ -169,5 +183,14 @@ This is the number of bytes the device can write in a single write-same
command. A value of '0' means write-same is not supported by this
device.
+wb_lat_usec (RW)
+----------------
+If the device is registered for writeback throttling, then this file shows
+the target minimum read latency. If this latency is exceeded in a given
+window of time (see wb_window_usec), then the writeback throttling will start
+scaling back writes. Writing a value of '0' to this file disables the
+feature. Writing a value of '-1' to this file resets the value to the
+default setting.
+
Jens Axboe <jens.axboe@oracle.com>, February 2009
diff --git a/Documentation/blockdev/cciss.txt b/Documentation/blockdev/cciss.txt
index b79d0a13e7cd..3a5477cc456e 100644
--- a/Documentation/blockdev/cciss.txt
+++ b/Documentation/blockdev/cciss.txt
@@ -184,7 +184,7 @@ infrequently used and the primary purpose of Smart Array controllers is to
act as a RAID controller for disk drives, so the vast majority of commands
are allocated for disk devices. However, if you have more than a few tape
drives attached to a smart array, the default number of commands may not be
-enought (for example, if you have 8 tape drives, you could only rewind 6
+enough (for example, if you have 8 tape drives, you could only rewind 6
at one time with the default number of commands.) The cciss_tape_cmds module
parameter allows more commands (up to 16 more) to be allocated for use by
tape drives. For example:
diff --git a/Documentation/blockdev/ramdisk.txt b/Documentation/blockdev/ramdisk.txt
index fe2ef978d85a..501e12e0323e 100644
--- a/Documentation/blockdev/ramdisk.txt
+++ b/Documentation/blockdev/ramdisk.txt
@@ -14,7 +14,7 @@ Contents:
The RAM disk driver is a way to use main system memory as a block device. It
is required for initrd, an initial filesystem used if you need to load modules
-in order to access the root filesystem (see Documentation/initrd.txt). It can
+in order to access the root filesystem (see Documentation/admin-guide/initrd.rst). It can
also be used for a temporary filesystem for crypto work, since the contents
are erased on reboot.
diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt
deleted file mode 100644
index d0d042c2fd5e..000000000000
--- a/Documentation/braille-console.txt
+++ /dev/null
@@ -1,34 +0,0 @@
- Linux Braille Console
-
-To get early boot messages on a braille device (before userspace screen
-readers can start), you first need to compile the support for the usual serial
-console (see serial-console.txt), and for braille device (in Device Drivers -
-Accessibility).
-
-Then you need to specify a console=brl, option on the kernel command line, the
-format is:
-
- console=brl,serial_options...
-
-where serial_options... are the same as described in serial-console.txt
-
-So for instance you can use console=brl,ttyS0 if the braille device is connected
-to the first serial port, and console=brl,ttyS0,115200 to override the baud rate
-to 115200, etc.
-
-By default, the braille device will just show the last kernel message (console
-mode). To review previous messages, press the Insert key to switch to the VT
-review mode. In review mode, the arrow keys permit to browse in the VT content,
-page up/down keys go at the top/bottom of the screen, and the home key goes back
-to the cursor, hence providing very basic screen reviewing facility.
-
-Sound feedback can be obtained by adding the braille_console.sound=1 kernel
-parameter.
-
-For simplicity, only one braille console can be enabled, other uses of
-console=brl,... will be discarded. Also note that it does not interfere with
-the console selection mechanism described in serial-console.txt
-
-For now, only the VisioBraille device is supported.
-
-Samuel Thibault <samuel.thibault@ens-lyon.org>
diff --git a/Documentation/cgroup-v1/00-INDEX b/Documentation/cgroup-v1/00-INDEX
index 106885ad670d..13e0c85e7b35 100644
--- a/Documentation/cgroup-v1/00-INDEX
+++ b/Documentation/cgroup-v1/00-INDEX
@@ -8,7 +8,7 @@ cpuacct.txt
- CPU Accounting Controller; account CPU usage for groups of tasks.
cpusets.txt
- documents the cpusets feature; assign CPUs and Mem to a set of tasks.
-devices.txt
+admin-guide/devices.rst
- Device Whitelist Controller; description, interface and security.
freezer-subsystem.txt
- checkpointing; rationale to not use signals, interface.
diff --git a/Documentation/circular-buffers.txt b/Documentation/circular-buffers.txt
index 88951b179262..4a824d232472 100644
--- a/Documentation/circular-buffers.txt
+++ b/Documentation/circular-buffers.txt
@@ -161,7 +161,7 @@ The producer will look something like this:
unsigned long head = buffer->head;
/* The spin_unlock() and next spin_lock() provide needed ordering. */
- unsigned long tail = ACCESS_ONCE(buffer->tail);
+ unsigned long tail = READ_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* insert one item into the buffer */
@@ -222,7 +222,7 @@ This will instruct the CPU to make sure the index is up to date before reading
the new item, and then it shall make sure the CPU has finished reading the item
before it writes the new tail pointer, which will erase the item.
-Note the use of ACCESS_ONCE() and smp_load_acquire() to read the
+Note the use of READ_ONCE() and smp_load_acquire() to read the
opposition index. This prevents the compiler from discarding and
reloading its cached value - which some compilers will do across
smp_read_barrier_depends(). This isn't strictly needed if you can
diff --git a/Documentation/conf.py b/Documentation/conf.py
index bf6f310e5170..1ac958c0333d 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -34,10 +34,10 @@ from load_config import loadConfig
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['kernel-doc', 'rstFlatTable', 'kernel_include', 'cdomain']
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain']
# The name of the math extension changed on Sphinx 1.4
-if minor > 3:
+if major == 1 and minor > 3:
extensions.append("sphinx.ext.imgmath")
else:
extensions.append("sphinx.ext.pngmath")
@@ -136,7 +136,7 @@ pygments_style = 'sphinx'
todo_include_todos = False
primary_domain = 'C'
-highlight_language = 'guess'
+highlight_language = 'none'
# -- Options for HTML output ----------------------------------------------
@@ -332,18 +332,32 @@ latex_elements = {
'''
}
+# Fix reference escape troubles with Sphinx 1.4.x
+if major == 1 and minor > 3:
+ latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
+
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
+ ('doc-guide/index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
+ 'The kernel development community', 'manual'),
+ ('admin-guide/index', 'linux-user.tex', 'Linux Kernel User Documentation',
+ 'The kernel development community', 'manual'),
+ ('core-api/index', 'core-api.tex', 'The kernel core API manual',
+ 'The kernel development community', 'manual'),
+ ('driver-api/index', 'driver-api.tex', 'The kernel driver API manual',
+ 'The kernel development community', 'manual'),
('kernel-documentation', 'kernel-documentation.tex', 'The Linux Kernel Documentation',
'The kernel development community', 'manual'),
- ('development-process/index', 'development-process.tex', 'Linux Kernel Development Documentation',
+ ('process/index', 'development-process.tex', 'Linux Kernel Development Documentation',
'The kernel development community', 'manual'),
('gpu/index', 'gpu.tex', 'Linux GPU Driver Developer\'s Guide',
'The kernel development community', 'manual'),
('media/index', 'media.tex', 'Linux Media Subsystem Documentation',
'The kernel development community', 'manual'),
+ ('security/index', 'security.tex', 'The kernel security subsystem manual',
+ 'The kernel development community', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
diff --git a/Documentation/core-api/assoc_array.rst b/Documentation/core-api/assoc_array.rst
new file mode 100644
index 000000000000..d83cfff9ea43
--- /dev/null
+++ b/Documentation/core-api/assoc_array.rst
@@ -0,0 +1,551 @@
+========================================
+Generic Associative Array Implementation
+========================================
+
+Overview
+========
+
+This associative array implementation is an object container with the following
+properties:
+
+1. Objects are opaque pointers. The implementation does not care where they
+ point (if anywhere) or what they point to (if anything).
+.. note:: Pointers to objects _must_ be zero in the least significant bit.
+
+2. Objects do not need to contain linkage blocks for use by the array. This
+ permits an object to be located in multiple arrays simultaneously.
+ Rather, the array is made up of metadata blocks that point to objects.
+
+3. Objects require index keys to locate them within the array.
+
+4. Index keys must be unique. Inserting an object with the same key as one
+ already in the array will replace the old object.
+
+5. Index keys can be of any length and can be of different lengths.
+
+6. Index keys should encode the length early on, before any variation due to
+ length is seen.
+
+7. Index keys can include a hash to scatter objects throughout the array.
+
+8. The array can iterated over. The objects will not necessarily come out in
+ key order.
+
+9. The array can be iterated over whilst it is being modified, provided the
+ RCU readlock is being held by the iterator. Note, however, under these
+ circumstances, some objects may be seen more than once. If this is a
+ problem, the iterator should lock against modification. Objects will not
+ be missed, however, unless deleted.
+
+10. Objects in the array can be looked up by means of their index key.
+
+11. Objects can be looked up whilst the array is being modified, provided the
+ RCU readlock is being held by the thread doing the look up.
+
+The implementation uses a tree of 16-pointer nodes internally that are indexed
+on each level by nibbles from the index key in the same manner as in a radix
+tree. To improve memory efficiency, shortcuts can be emplaced to skip over
+what would otherwise be a series of single-occupancy nodes. Further, nodes
+pack leaf object pointers into spare space in the node rather than making an
+extra branch until as such time an object needs to be added to a full node.
+
+
+The Public API
+==============
+
+The public API can be found in ``<linux/assoc_array.h>``. The associative
+array is rooted on the following structure::
+
+ struct assoc_array {
+ ...
+ };
+
+The code is selected by enabling ``CONFIG_ASSOCIATIVE_ARRAY`` with::
+
+ ./script/config -e ASSOCIATIVE_ARRAY
+
+
+Edit Script
+-----------
+
+The insertion and deletion functions produce an 'edit script' that can later be
+applied to effect the changes without risking ``ENOMEM``. This retains the
+preallocated metadata blocks that will be installed in the internal tree and
+keeps track of the metadata blocks that will be removed from the tree when the
+script is applied.
+
+This is also used to keep track of dead blocks and dead objects after the
+script has been applied so that they can be freed later. The freeing is done
+after an RCU grace period has passed - thus allowing access functions to
+proceed under the RCU read lock.
+
+The script appears as outside of the API as a pointer of the type::
+
+ struct assoc_array_edit;
+
+There are two functions for dealing with the script:
+
+1. Apply an edit script::
+
+ void assoc_array_apply_edit(struct assoc_array_edit *edit);
+
+This will perform the edit functions, interpolating various write barriers
+to permit accesses under the RCU read lock to continue. The edit script
+will then be passed to ``call_rcu()`` to free it and any dead stuff it points
+to.
+
+2. Cancel an edit script::
+
+ void assoc_array_cancel_edit(struct assoc_array_edit *edit);
+
+This frees the edit script and all preallocated memory immediately. If
+this was for insertion, the new object is _not_ released by this function,
+but must rather be released by the caller.
+
+These functions are guaranteed not to fail.
+
+
+Operations Table
+----------------
+
+Various functions take a table of operations::
+
+ struct assoc_array_ops {
+ ...
+ };
+
+This points to a number of methods, all of which need to be provided:
+
+1. Get a chunk of index key from caller data::
+
+ unsigned long (*get_key_chunk)(const void *index_key, int level);
+
+This should return a chunk of caller-supplied index key starting at the
+*bit* position given by the level argument. The level argument will be a
+multiple of ``ASSOC_ARRAY_KEY_CHUNK_SIZE`` and the function should return
+``ASSOC_ARRAY_KEY_CHUNK_SIZE bits``. No error is possible.
+
+
+2. Get a chunk of an object's index key::
+
+ unsigned long (*get_object_key_chunk)(const void *object, int level);
+
+As the previous function, but gets its data from an object in the array
+rather than from a caller-supplied index key.
+
+
+3. See if this is the object we're looking for::
+
+ bool (*compare_object)(const void *object, const void *index_key);
+
+Compare the object against an index key and return ``true`` if it matches and
+``false`` if it doesn't.
+
+
+4. Diff the index keys of two objects::
+
+ int (*diff_objects)(const void *object, const void *index_key);
+
+Return the bit position at which the index key of the specified object
+differs from the given index key or -1 if they are the same.
+
+
+5. Free an object::
+
+ void (*free_object)(void *object);
+
+Free the specified object. Note that this may be called an RCU grace period
+after ``assoc_array_apply_edit()`` was called, so ``synchronize_rcu()`` may be
+necessary on module unloading.
+
+
+Manipulation Functions
+----------------------
+
+There are a number of functions for manipulating an associative array:
+
+1. Initialise an associative array::
+
+ void assoc_array_init(struct assoc_array *array);
+
+This initialises the base structure for an associative array. It can't fail.
+
+
+2. Insert/replace an object in an associative array::
+
+ struct assoc_array_edit *
+ assoc_array_insert(struct assoc_array *array,
+ const struct assoc_array_ops *ops,
+ const void *index_key,
+ void *object);
+
+This inserts the given object into the array. Note that the least
+significant bit of the pointer must be zero as it's used to type-mark
+pointers internally.
+
+If an object already exists for that key then it will be replaced with the
+new object and the old one will be freed automatically.
+
+The ``index_key`` argument should hold index key information and is
+passed to the methods in the ops table when they are called.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied. ``-ENOMEM`` is returned in the case of
+an out-of-memory error.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+3. Delete an object from an associative array::
+
+ struct assoc_array_edit *
+ assoc_array_delete(struct assoc_array *array,
+ const struct assoc_array_ops *ops,
+ const void *index_key);
+
+This deletes an object that matches the specified data from the array.
+
+The ``index_key`` argument should hold index key information and is
+passed to the methods in the ops table when they are called.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied. ``-ENOMEM`` is returned in the case of
+an out-of-memory error. ``NULL`` will be returned if the specified object is
+not found within the array.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+4. Delete all objects from an associative array::
+
+ struct assoc_array_edit *
+ assoc_array_clear(struct assoc_array *array,
+ const struct assoc_array_ops *ops);
+
+This deletes all the objects from an associative array and leaves it
+completely empty.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied. ``-ENOMEM`` is returned in the case of
+an out-of-memory error.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+5. Destroy an associative array, deleting all objects::
+
+ void assoc_array_destroy(struct assoc_array *array,
+ const struct assoc_array_ops *ops);
+
+This destroys the contents of the associative array and leaves it
+completely empty. It is not permitted for another thread to be traversing
+the array under the RCU read lock at the same time as this function is
+destroying it as no RCU deferral is performed on memory release -
+something that would require memory to be allocated.
+
+The caller should lock exclusively against other modifiers and accessors
+of the array.
+
+
+6. Garbage collect an associative array::
+
+ int assoc_array_gc(struct assoc_array *array,
+ const struct assoc_array_ops *ops,
+ bool (*iterator)(void *object, void *iterator_data),
+ void *iterator_data);
+
+This iterates over the objects in an associative array and passes each one to
+``iterator()``. If ``iterator()`` returns ``true``, the object is kept. If it
+returns ``false``, the object will be freed. If the ``iterator()`` function
+returns ``true``, it must perform any appropriate refcount incrementing on the
+object before returning.
+
+The internal tree will be packed down if possible as part of the iteration
+to reduce the number of nodes in it.
+
+The ``iterator_data`` is passed directly to ``iterator()`` and is otherwise
+ignored by the function.
+
+The function will return ``0`` if successful and ``-ENOMEM`` if there wasn't
+enough memory.
+
+It is possible for other threads to iterate over or search the array under
+the RCU read lock whilst this function is in progress. The caller should
+lock exclusively against other modifiers of the array.
+
+
+Access Functions
+----------------
+
+There are two functions for accessing an associative array:
+
+1. Iterate over all the objects in an associative array::
+
+ int assoc_array_iterate(const struct assoc_array *array,
+ int (*iterator)(const void *object,
+ void *iterator_data),
+ void *iterator_data);
+
+This passes each object in the array to the iterator callback function.
+``iterator_data`` is private data for that function.
+
+This may be used on an array at the same time as the array is being
+modified, provided the RCU read lock is held. Under such circumstances,
+it is possible for the iteration function to see some objects twice. If
+this is a problem, then modification should be locked against. The
+iteration algorithm should not, however, miss any objects.
+
+The function will return ``0`` if no objects were in the array or else it will
+return the result of the last iterator function called. Iteration stops
+immediately if any call to the iteration function results in a non-zero
+return.
+
+
+2. Find an object in an associative array::
+
+ void *assoc_array_find(const struct assoc_array *array,
+ const struct assoc_array_ops *ops,
+ const void *index_key);
+
+This walks through the array's internal tree directly to the object
+specified by the index key..
+
+This may be used on an array at the same time as the array is being
+modified, provided the RCU read lock is held.
+
+The function will return the object if found (and set ``*_type`` to the object
+type) or will return ``NULL`` if the object was not found.
+
+
+Index Key Form
+--------------
+
+The index key can be of any form, but since the algorithms aren't told how long
+the key is, it is strongly recommended that the index key includes its length
+very early on before any variation due to the length would have an effect on
+comparisons.
+
+This will cause leaves with different length keys to scatter away from each
+other - and those with the same length keys to cluster together.
+
+It is also recommended that the index key begin with a hash of the rest of the
+key to maximise scattering throughout keyspace.
+
+The better the scattering, the wider and lower the internal tree will be.
+
+Poor scattering isn't too much of a problem as there are shortcuts and nodes
+can contain mixtures of leaves and metadata pointers.
+
+The index key is read in chunks of machine word. Each chunk is subdivided into
+one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
+on a 64-bit CPU, 16 levels. Unless the scattering is really poor, it is
+unlikely that more than one word of any particular index key will have to be
+used.
+
+
+Internal Workings
+=================
+
+The associative array data structure has an internal tree. This tree is
+constructed of two types of metadata blocks: nodes and shortcuts.
+
+A node is an array of slots. Each slot can contain one of four things:
+
+* A NULL pointer, indicating that the slot is empty.
+* A pointer to an object (a leaf).
+* A pointer to a node at the next level.
+* A pointer to a shortcut.
+
+
+Basic Internal Tree Layout
+--------------------------
+
+Ignoring shortcuts for the moment, the nodes form a multilevel tree. The index
+key space is strictly subdivided by the nodes in the tree and nodes occur on
+fixed levels. For example::
+
+ Level: 0 1 2 3
+ =============== =============== =============== ===============
+ NODE D
+ NODE B NODE C +------>+---+
+ +------>+---+ +------>+---+ | | 0 |
+ NODE A | | 0 | | | 0 | | +---+
+ +---+ | +---+ | +---+ | : :
+ | 0 | | : : | : : | +---+
+ +---+ | +---+ | +---+ | | f |
+ | 1 |---+ | 3 |---+ | 7 |---+ +---+
+ +---+ +---+ +---+
+ : : : : | 8 |---+
+ +---+ +---+ +---+ | NODE E
+ | e |---+ | f | : : +------>+---+
+ +---+ | +---+ +---+ | 0 |
+ | f | | | f | +---+
+ +---+ | +---+ : :
+ | NODE F +---+
+ +------>+---+ | f |
+ | 0 | NODE G +---+
+ +---+ +------>+---+
+ : : | | 0 |
+ +---+ | +---+
+ | 6 |---+ : :
+ +---+ +---+
+ : : | f |
+ +---+ +---+
+ | f |
+ +---+
+
+In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
+Assuming no other meta data nodes in the tree, the key space is divided
+thusly::
+
+ KEY PREFIX NODE
+ ========== ====
+ 137* D
+ 138* E
+ 13[0-69-f]* C
+ 1[0-24-f]* B
+ e6* G
+ e[0-57-f]* F
+ [02-df]* A
+
+So, for instance, keys with the following example index keys will be found in
+the appropriate nodes::
+
+ INDEX KEY PREFIX NODE
+ =============== ======= ====
+ 13694892892489 13 C
+ 13795289025897 137 D
+ 13889dde88793 138 E
+ 138bbb89003093 138 E
+ 1394879524789 12 C
+ 1458952489 1 B
+ 9431809de993ba - A
+ b4542910809cd - A
+ e5284310def98 e F
+ e68428974237 e6 G
+ e7fffcbd443 e F
+ f3842239082 - A
+
+To save memory, if a node can hold all the leaves in its portion of keyspace,
+then the node will have all those leaves in it and will not have any metadata
+pointers - even if some of those leaves would like to be in the same slot.
+
+A node can contain a heterogeneous mix of leaves and metadata pointers.
+Metadata pointers must be in the slots that match their subdivisions of key
+space. The leaves can be in any slot not occupied by a metadata pointer. It
+is guaranteed that none of the leaves in a node will match a slot occupied by a
+metadata pointer. If the metadata pointer is there, any leaf whose key matches
+the metadata key prefix must be in the subtree that the metadata pointer points
+to.
+
+In the above example list of index keys, node A will contain::
+
+ SLOT CONTENT INDEX KEY (PREFIX)
+ ==== =============== ==================
+ 1 PTR TO NODE B 1*
+ any LEAF 9431809de993ba
+ any LEAF b4542910809cd
+ e PTR TO NODE F e*
+ any LEAF f3842239082
+
+and node B::
+
+ 3 PTR TO NODE C 13*
+ any LEAF 1458952489
+
+
+Shortcuts
+---------
+
+Shortcuts are metadata records that jump over a piece of keyspace. A shortcut
+is a replacement for a series of single-occupancy nodes ascending through the
+levels. Shortcuts exist to save memory and to speed up traversal.
+
+It is possible for the root of the tree to be a shortcut - say, for example,
+the tree contains at least 17 nodes all with key prefix ``1111``. The
+insertion algorithm will insert a shortcut to skip over the ``1111`` keyspace
+in a single bound and get to the fourth level where these actually become
+different.
+
+
+Splitting And Collapsing Nodes
+------------------------------
+
+Each node has a maximum capacity of 16 leaves and metadata pointers. If the
+insertion algorithm finds that it is trying to insert a 17th object into a
+node, that node will be split such that at least two leaves that have a common
+key segment at that level end up in a separate node rooted on that slot for
+that common key segment.
+
+If the leaves in a full node and the leaf that is being inserted are
+sufficiently similar, then a shortcut will be inserted into the tree.
+
+When the number of objects in the subtree rooted at a node falls to 16 or
+fewer, then the subtree will be collapsed down to a single node - and this will
+ripple towards the root if possible.
+
+
+Non-Recursive Iteration
+-----------------------
+
+Each node and shortcut contains a back pointer to its parent and the number of
+slot in that parent that points to it. None-recursive iteration uses these to
+proceed rootwards through the tree, going to the parent node, slot N + 1 to
+make sure progress is made without the need for a stack.
+
+The backpointers, however, make simultaneous alteration and iteration tricky.
+
+
+Simultaneous Alteration And Iteration
+-------------------------------------
+
+There are a number of cases to consider:
+
+1. Simple insert/replace. This involves simply replacing a NULL or old
+ matching leaf pointer with the pointer to the new leaf after a barrier.
+ The metadata blocks don't change otherwise. An old leaf won't be freed
+ until after the RCU grace period.
+
+2. Simple delete. This involves just clearing an old matching leaf. The
+ metadata blocks don't change otherwise. The old leaf won't be freed until
+ after the RCU grace period.
+
+3. Insertion replacing part of a subtree that we haven't yet entered. This
+ may involve replacement of part of that subtree - but that won't affect
+ the iteration as we won't have reached the pointer to it yet and the
+ ancestry blocks are not replaced (the layout of those does not change).
+
+4. Insertion replacing nodes that we're actively processing. This isn't a
+ problem as we've passed the anchoring pointer and won't switch onto the
+ new layout until we follow the back pointers - at which point we've
+ already examined the leaves in the replaced node (we iterate over all the
+ leaves in a node before following any of its metadata pointers).
+
+ We might, however, re-see some leaves that have been split out into a new
+ branch that's in a slot further along than we were at.
+
+5. Insertion replacing nodes that we're processing a dependent branch of.
+ This won't affect us until we follow the back pointers. Similar to (4).
+
+6. Deletion collapsing a branch under us. This doesn't affect us because the
+ back pointers will get us back to the parent of the new node before we
+ could see the new node. The entire collapsed subtree is thrown away
+ unchanged - and will still be rooted on the same slot, so we shouldn't
+ process it a second time as we'll go back to slot + 1.
+
+.. note::
+
+ Under some circumstances, we need to simultaneously change the parent
+ pointer and the parent slot pointer on a node (say, for example, we
+ inserted another node before it and moved it up a level). We cannot do
+ this without locking against a read - so we have to replace that node too.
+
+ However, when we're changing a shortcut into a node this isn't a problem
+ as shortcuts only have one slot and so the parent slot number isn't used
+ when traversing backwards over one. This means that it's okay to change
+ the slot number first - provided suitable barriers are used to make sure
+ the parent slot number is read after the back pointer.
+
+Obsolete blocks and leaves are freed up after an RCU grace period has passed,
+so as long as anyone doing walking or iteration holds the RCU read lock, the
+old superstructure should not go away on them.
diff --git a/Documentation/atomic_ops.txt b/Documentation/core-api/atomic_ops.rst
index c9d1cacb4395..55e43f1c80de 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/core-api/atomic_ops.rst
@@ -1,36 +1,42 @@
- Semantics and Behavior of Atomic and
- Bitmask Operations
+=======================================================
+Semantics and Behavior of Atomic and Bitmask Operations
+=======================================================
- David S. Miller
+:Author: David S. Miller
- This document is intended to serve as a guide to Linux port
+This document is intended to serve as a guide to Linux port
maintainers on how to implement atomic counter, bitops, and spinlock
interfaces properly.
- The atomic_t type should be defined as a signed integer and
+Atomic Type And Operations
+==========================
+
+The atomic_t type should be defined as a signed integer and
the atomic_long_t type as a signed long integer. Also, they should
be made opaque such that any kind of cast to a normal C integer type
-will fail. Something like the following should suffice:
+will fail. Something like the following should suffice::
typedef struct { int counter; } atomic_t;
typedef struct { long counter; } atomic_long_t;
Historically, counter has been declared volatile. This is now discouraged.
-See Documentation/volatile-considered-harmful.txt for the complete rationale.
+See :ref:`Documentation/process/volatile-considered-harmful.rst
+<volatile_considered_harmful>` for the complete rationale.
local_t is very similar to atomic_t. If the counter is per CPU and only
updated by one CPU, local_t is probably more appropriate. Please see
-Documentation/local_ops.txt for the semantics of local_t.
+:ref:`Documentation/core-api/local_ops.rst <local_ops>` for the semantics of
+local_t.
The first operations to implement for atomic_t's are the initializers and
-plain reads.
+plain reads. ::
#define ATOMIC_INIT(i) { (i) }
#define atomic_set(v, i) ((v)->counter = (i))
-The first macro is used in definitions, such as:
+The first macro is used in definitions, such as::
-static atomic_t my_counter = ATOMIC_INIT(1);
+ static atomic_t my_counter = ATOMIC_INIT(1);
The initializer is atomic in that the return values of the atomic operations
are guaranteed to be correct reflecting the initialized value if the
@@ -38,10 +44,10 @@ initializer is used before runtime. If the initializer is used at runtime, a
proper implicit or explicit read memory barrier is needed before reading the
value with atomic_read from another thread.
-As with all of the atomic_ interfaces, replace the leading "atomic_"
-with "atomic_long_" to operate on atomic_long_t.
+As with all of the ``atomic_`` interfaces, replace the leading ``atomic_``
+with ``atomic_long_`` to operate on atomic_long_t.
-The second interface can be used at runtime, as in:
+The second interface can be used at runtime, as in::
struct foo { atomic_t counter; };
...
@@ -59,7 +65,7 @@ been set with this operation or set with another operation. A proper implicit
or explicit memory barrier is needed before the value set with the operation
is guaranteed to be readable with atomic_read from another thread.
-Next, we have:
+Next, we have::
#define atomic_read(v) ((v)->counter)
@@ -73,36 +79,37 @@ initialization by any other thread is visible yet, so the user of the
interface must take care of that with a proper implicit or explicit memory
barrier.
-*** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***
+.. warning::
-Some architectures may choose to use the volatile keyword, barriers, or inline
-assembly to guarantee some degree of immediacy for atomic_read() and
-atomic_set(). This is not uniformly guaranteed, and may change in the future,
-so all users of atomic_t should treat atomic_read() and atomic_set() as simple
-C statements that may be reordered or optimized away entirely by the compiler
-or processor, and explicitly invoke the appropriate compiler and/or memory
-barrier for each use case. Failure to do so will result in code that may
-suddenly break when used with different architectures or compiler
-optimizations, or even changes in unrelated code which changes how the
-compiler optimizes the section accessing atomic_t variables.
+ ``atomic_read()`` and ``atomic_set()`` DO NOT IMPLY BARRIERS!
-*** YOU HAVE BEEN WARNED! ***
+ Some architectures may choose to use the volatile keyword, barriers, or
+ inline assembly to guarantee some degree of immediacy for atomic_read()
+ and atomic_set(). This is not uniformly guaranteed, and may change in
+ the future, so all users of atomic_t should treat atomic_read() and
+ atomic_set() as simple C statements that may be reordered or optimized
+ away entirely by the compiler or processor, and explicitly invoke the
+ appropriate compiler and/or memory barrier for each use case. Failure
+ to do so will result in code that may suddenly break when used with
+ different architectures or compiler optimizations, or even changes in
+ unrelated code which changes how the compiler optimizes the section
+ accessing atomic_t variables.
Properly aligned pointers, longs, ints, and chars (and unsigned
equivalents) may be atomically loaded from and stored to in the same
-sense as described for atomic_read() and atomic_set(). The ACCESS_ONCE()
-macro should be used to prevent the compiler from using optimizations
-that might otherwise optimize accesses out of existence on the one hand,
-or that might create unsolicited accesses on the other.
+sense as described for atomic_read() and atomic_set(). The READ_ONCE()
+and WRITE_ONCE() macros should be used to prevent the compiler from using
+optimizations that might otherwise optimize accesses out of existence on
+the one hand, or that might create unsolicited accesses on the other.
-For example consider the following code:
+For example consider the following code::
while (a > 0)
do_something();
If the compiler can prove that do_something() does not store to the
variable a, then the compiler is within its rights transforming this to
-the following:
+the following::
tmp = a;
if (a > 0)
@@ -110,14 +117,14 @@ the following:
do_something();
If you don't want the compiler to do this (and you probably don't), then
-you should use something like the following:
+you should use something like the following::
- while (ACCESS_ONCE(a) < 0)
+ while (READ_ONCE(a) < 0)
do_something();
Alternatively, you could place a barrier() call in the loop.
-For another example, consider the following code:
+For another example, consider the following code::
tmp_a = a;
do_something_with(tmp_a);
@@ -125,7 +132,7 @@ For another example, consider the following code:
If the compiler can prove that do_something_with() does not store to the
variable a, then the compiler is within its rights to manufacture an
-additional load as follows:
+additional load as follows::
tmp_a = a;
do_something_with(tmp_a);
@@ -139,15 +146,15 @@ The compiler would be likely to manufacture this additional load if
do_something_with() was an inline function that made very heavy use
of registers: reloading from variable a could save a flush to the
stack and later reload. To prevent the compiler from attacking your
-code in this manner, write the following:
+code in this manner, write the following::
- tmp_a = ACCESS_ONCE(a);
+ tmp_a = READ_ONCE(a);
do_something_with(tmp_a);
do_something_else_with(tmp_a);
For a final example, consider the following code, assuming that the
variable a is set at boot time before the second CPU is brought online
-and never changed later, so that memory barriers are not needed:
+and never changed later, so that memory barriers are not needed::
if (a)
b = 9;
@@ -155,7 +162,7 @@ and never changed later, so that memory barriers are not needed:
b = 42;
The compiler is within its rights to manufacture an additional store
-by transforming the above code into the following:
+by transforming the above code into the following::
b = 42;
if (a)
@@ -163,20 +170,22 @@ by transforming the above code into the following:
This could come as a fatal surprise to other code running concurrently
that expected b to never have the value 42 if a was zero. To prevent
-the compiler from doing this, write something like:
+the compiler from doing this, write something like::
if (a)
- ACCESS_ONCE(b) = 9;
+ WRITE_ONCE(b, 9);
else
- ACCESS_ONCE(b) = 42;
+ WRITE_ONCE(b, 42);
Don't even -think- about doing this without proper use of memory barriers,
locks, or atomic operations if variable a can change at runtime!
-*** WARNING: ACCESS_ONCE() DOES NOT IMPLY A BARRIER! ***
+.. warning::
+
+ ``READ_ONCE()`` OR ``WRITE_ONCE()`` DO NOT IMPLY A BARRIER!
Now, we move onto the atomic operation interfaces typically implemented with
-the help of assembly code.
+the help of assembly code. ::
void atomic_add(int i, atomic_t *v);
void atomic_sub(int i, atomic_t *v);
@@ -192,7 +201,7 @@ One very important aspect of these two routines is that they DO NOT
require any explicit memory barriers. They need only perform the
atomic_t counter update in an SMP safe manner.
-Next, we have:
+Next, we have::
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
@@ -214,7 +223,7 @@ If the atomic instructions used in an implementation provide explicit
memory barrier semantics which satisfy the above requirements, that is
fine as well.
-Let's move on:
+Let's move on::
int atomic_add_return(int i, atomic_t *v);
int atomic_sub_return(int i, atomic_t *v);
@@ -224,7 +233,7 @@ explicit counter adjustment is given instead of the implicit "1".
This means that like atomic_{inc,dec}_return(), the memory barrier
semantics are required.
-Next:
+Next::
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
@@ -234,13 +243,13 @@ given atomic counter. They return a boolean indicating whether the
resulting counter value was zero or not.
Again, these primitives provide explicit memory barrier semantics around
-the atomic operation.
+the atomic operation::
int atomic_sub_and_test(int i, atomic_t *v);
This is identical to atomic_dec_and_test() except that an explicit
decrement is given instead of the implicit "1". This primitive must
-provide explicit memory barrier semantics around the operation.
+provide explicit memory barrier semantics around the operation::
int atomic_add_negative(int i, atomic_t *v);
@@ -249,7 +258,7 @@ is return which indicates whether the resulting counter value is negative.
This primitive must provide explicit memory barrier semantics around
the operation.
-Then:
+Then::
int atomic_xchg(atomic_t *v, int new);
@@ -257,14 +266,14 @@ This performs an atomic exchange operation on the atomic variable v, setting
the given new value. It returns the old value that the atomic variable v had
just before the operation.
-atomic_xchg must provide explicit memory barriers around the operation.
+atomic_xchg must provide explicit memory barriers around the operation. ::
int atomic_cmpxchg(atomic_t *v, int old, int new);
This performs an atomic compare exchange operation on the atomic value v,
with the given old and new values. Like all atomic_xxx operations,
atomic_cmpxchg will only satisfy its atomicity semantics as long as all
-other accesses of *v are performed through atomic_xxx operations.
+other accesses of \*v are performed through atomic_xxx operations.
atomic_cmpxchg must provide explicit memory barriers around the operation,
although if the comparison fails then no memory ordering guarantees are
@@ -273,7 +282,7 @@ required.
The semantics for atomic_cmpxchg are the same as those defined for 'cas'
below.
-Finally:
+Finally::
int atomic_add_unless(atomic_t *v, int a, int u);
@@ -289,12 +298,12 @@ atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
If a caller requires memory barrier semantics around an atomic_t
operation which does not return a value, a set of interfaces are
-defined which accomplish this:
+defined which accomplish this::
void smp_mb__before_atomic(void);
void smp_mb__after_atomic(void);
-For example, smp_mb__before_atomic() can be used like so:
+For example, smp_mb__before_atomic() can be used like so::
obj->dead = 1;
smp_mb__before_atomic();
@@ -315,67 +324,69 @@ atomic_t implementation above can have disastrous results. Here is
an example, which follows a pattern occurring frequently in the Linux
kernel. It is the use of atomic counters to implement reference
counting, and it works such that once the counter falls to zero it can
-be guaranteed that no other entity can be accessing the object:
-
-static void obj_list_add(struct obj *obj, struct list_head *head)
-{
- obj->active = 1;
- list_add(&obj->list, head);
-}
-
-static void obj_list_del(struct obj *obj)
-{
- list_del(&obj->list);
- obj->active = 0;
-}
-
-static void obj_destroy(struct obj *obj)
-{
- BUG_ON(obj->active);
- kfree(obj);
-}
-
-struct obj *obj_list_peek(struct list_head *head)
-{
- if (!list_empty(head)) {
- struct obj *obj;
+be guaranteed that no other entity can be accessing the object::
+
+ static void obj_list_add(struct obj *obj, struct list_head *head)
+ {
+ obj->active = 1;
+ list_add(&obj->list, head);
+ }
+
+ static void obj_list_del(struct obj *obj)
+ {
+ list_del(&obj->list);
+ obj->active = 0;
+ }
- obj = list_entry(head->next, struct obj, list);
- atomic_inc(&obj->refcnt);
- return obj;
+ static void obj_destroy(struct obj *obj)
+ {
+ BUG_ON(obj->active);
+ kfree(obj);
}
- return NULL;
-}
-void obj_poke(void)
-{
- struct obj *obj;
+ struct obj *obj_list_peek(struct list_head *head)
+ {
+ if (!list_empty(head)) {
+ struct obj *obj;
+
+ obj = list_entry(head->next, struct obj, list);
+ atomic_inc(&obj->refcnt);
+ return obj;
+ }
+ return NULL;
+ }
+
+ void obj_poke(void)
+ {
+ struct obj *obj;
+
+ spin_lock(&global_list_lock);
+ obj = obj_list_peek(&global_list);
+ spin_unlock(&global_list_lock);
- spin_lock(&global_list_lock);
- obj = obj_list_peek(&global_list);
- spin_unlock(&global_list_lock);
+ if (obj) {
+ obj->ops->poke(obj);
+ if (atomic_dec_and_test(&obj->refcnt))
+ obj_destroy(obj);
+ }
+ }
+
+ void obj_timeout(struct obj *obj)
+ {
+ spin_lock(&global_list_lock);
+ obj_list_del(obj);
+ spin_unlock(&global_list_lock);
- if (obj) {
- obj->ops->poke(obj);
if (atomic_dec_and_test(&obj->refcnt))
obj_destroy(obj);
}
-}
-
-void obj_timeout(struct obj *obj)
-{
- spin_lock(&global_list_lock);
- obj_list_del(obj);
- spin_unlock(&global_list_lock);
- if (atomic_dec_and_test(&obj->refcnt))
- obj_destroy(obj);
-}
+.. note::
-(This is a simplification of the ARP queue management in the
- generic neighbour discover code of the networking. Olaf Kirch
- found a bug wrt. memory barriers in kfree_skb() that exposed
- the atomic_t memory barrier requirements quite clearly.)
+ This is a simplification of the ARP queue management in the generic
+ neighbour discover code of the networking. Olaf Kirch found a bug wrt.
+ memory barriers in kfree_skb() that exposed the atomic_t memory barrier
+ requirements quite clearly.
Given the above scheme, it must be the case that the obj->active
update done by the obj list deletion be visible to other processors
@@ -383,7 +394,7 @@ before the atomic counter decrement is performed.
Otherwise, the counter could fall to zero, yet obj->active would still
be set, thus triggering the assertion in obj_destroy(). The error
-sequence looks like this:
+sequence looks like this::
cpu 0 cpu 1
obj_poke() obj_timeout()
@@ -420,6 +431,10 @@ same scheme.
Another note is that the atomic_t operations returning values are
extremely slow on an old 386.
+
+Atomic Bitmask
+==============
+
We will now cover the atomic bitmask operations. You will find that
their SMP and memory barrier semantics are similar in shape and scope
to the atomic_t ops above.
@@ -427,7 +442,7 @@ to the atomic_t ops above.
Native atomic bit operations are defined to operate on objects aligned
to the size of an "unsigned long" C data type, and are least of that
size. The endianness of the bits within each "unsigned long" are the
-native endianness of the cpu.
+native endianness of the cpu. ::
void set_bit(unsigned long nr, volatile unsigned long *addr);
void clear_bit(unsigned long nr, volatile unsigned long *addr);
@@ -437,7 +452,7 @@ These routines set, clear, and change, respectively, the bit number
indicated by "nr" on the bit mask pointed to by "ADDR".
They must execute atomically, yet there are no implicit memory barrier
-semantics required of these interfaces.
+semantics required of these interfaces. ::
int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
@@ -466,7 +481,7 @@ must provide explicit memory barrier semantics around their execution.
All memory operations before the atomic bit operation call must be
made visible globally before the atomic bit operation is made visible.
Likewise, the atomic bit operation must be visible globally before any
-subsequent memory operation is made visible. For example:
+subsequent memory operation is made visible. For example::
obj->dead = 1;
if (test_and_set_bit(0, &obj->flags))
@@ -479,7 +494,7 @@ done by test_and_set_bit() becomes visible. Likewise, the atomic
memory operation done by test_and_set_bit() must become visible before
"obj->killed = 1;" is visible.
-Finally there is the basic operation:
+Finally there is the basic operation::
int test_bit(unsigned long nr, __const__ volatile unsigned long *addr);
@@ -488,13 +503,13 @@ pointed to by "addr".
If explicit memory barriers are required around {set,clear}_bit() (which do
not return a value, and thus does not need to provide memory barrier
-semantics), two interfaces are provided:
+semantics), two interfaces are provided::
void smp_mb__before_atomic(void);
void smp_mb__after_atomic(void);
They are used as follows, and are akin to their atomic_t operation
-brothers:
+brothers::
/* All memory operations before this call will
* be globally visible before the clear_bit().
@@ -511,7 +526,7 @@ There are two special bitops with lock barrier semantics (acquire/release,
same as spinlocks). These operate in the same way as their non-_lock/unlock
postfixed variants, except that they are to provide acquire/release semantics,
respectively. This means they can be used for bit_spin_trylock and
-bit_spin_unlock type operations without specifying any more barriers.
+bit_spin_unlock type operations without specifying any more barriers. ::
int test_and_set_bit_lock(unsigned long nr, unsigned long *addr);
void clear_bit_unlock(unsigned long nr, unsigned long *addr);
@@ -526,7 +541,7 @@ provided. They are used in contexts where some other higher-level SMP
locking scheme is being used to protect the bitmask, and thus less
expensive non-atomic operations may be used in the implementation.
They have names similar to the above bitmask operation interfaces,
-except that two underscores are prefixed to the interface name.
+except that two underscores are prefixed to the interface name. ::
void __set_bit(unsigned long nr, volatile unsigned long *addr);
void __clear_bit(unsigned long nr, volatile unsigned long *addr);
@@ -542,9 +557,11 @@ The routines xchg() and cmpxchg() must provide the same exact
memory-barrier semantics as the atomic and bit operations returning
values.
-Note: If someone wants to use xchg(), cmpxchg() and their variants,
-linux/atomic.h should be included rather than asm/cmpxchg.h, unless
-the code is in arch/* and can take care of itself.
+.. note::
+
+ If someone wants to use xchg(), cmpxchg() and their variants,
+ linux/atomic.h should be included rather than asm/cmpxchg.h, unless the
+ code is in arch/* and can take care of itself.
Spinlocks and rwlocks have memory barrier expectations as well.
The rule to follow is simple:
@@ -558,7 +575,7 @@ The rule to follow is simple:
Which finally brings us to _atomic_dec_and_lock(). There is an
architecture-neutral version implemented in lib/dec_and_lock.c,
-but most platforms will wish to optimize this in assembler.
+but most platforms will wish to optimize this in assembler. ::
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
@@ -573,7 +590,7 @@ sure the spinlock operation is globally visible before any
subsequent memory operation.
We can demonstrate this operation more clearly if we define
-an abstract atomic operation:
+an abstract atomic operation::
long cas(long *mem, long old, long new);
@@ -584,48 +601,48 @@ an abstract atomic operation:
3) Regardless, the current value at "mem" is returned.
As an example usage, here is what an atomic counter update
-might look like:
+might look like::
-void example_atomic_inc(long *counter)
-{
- long old, new, ret;
+ void example_atomic_inc(long *counter)
+ {
+ long old, new, ret;
- while (1) {
- old = *counter;
- new = old + 1;
+ while (1) {
+ old = *counter;
+ new = old + 1;
- ret = cas(counter, old, new);
- if (ret == old)
- break;
- }
-}
-
-Let's use cas() in order to build a pseudo-C atomic_dec_and_lock():
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- long old, new, ret;
- int went_to_zero;
-
- went_to_zero = 0;
- while (1) {
- old = atomic_read(atomic);
- new = old - 1;
- if (new == 0) {
- went_to_zero = 1;
- spin_lock(lock);
- }
- ret = cas(atomic, old, new);
- if (ret == old)
- break;
- if (went_to_zero) {
- spin_unlock(lock);
- went_to_zero = 0;
+ ret = cas(counter, old, new);
+ if (ret == old)
+ break;
}
}
- return went_to_zero;
-}
+Let's use cas() in order to build a pseudo-C atomic_dec_and_lock()::
+
+ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+ {
+ long old, new, ret;
+ int went_to_zero;
+
+ went_to_zero = 0;
+ while (1) {
+ old = atomic_read(atomic);
+ new = old - 1;
+ if (new == 0) {
+ went_to_zero = 1;
+ spin_lock(lock);
+ }
+ ret = cas(atomic, old, new);
+ if (ret == old)
+ break;
+ if (went_to_zero) {
+ spin_unlock(lock);
+ went_to_zero = 0;
+ }
+ }
+
+ return went_to_zero;
+ }
Now, as far as memory barriers go, as long as spin_lock()
strictly orders all subsequent memory operations (including
@@ -635,6 +652,7 @@ Said another way, _atomic_dec_and_lock() must guarantee that
a counter dropping to zero is never made visible before the
spinlock being acquired.
-Note that this also means that for the case where the counter
-is not dropping to zero, there are no memory ordering
-requirements.
+.. note::
+
+ Note that this also means that for the case where the counter is not
+ dropping to zero, there are no memory ordering requirements.
diff --git a/Documentation/core-api/conf.py b/Documentation/core-api/conf.py
new file mode 100644
index 000000000000..db1f7659f3da
--- /dev/null
+++ b/Documentation/core-api/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Core-API Documentation"
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'core-api.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/core-api/debug-objects.rst b/Documentation/core-api/debug-objects.rst
new file mode 100644
index 000000000000..ac926fd55a64
--- /dev/null
+++ b/Documentation/core-api/debug-objects.rst
@@ -0,0 +1,310 @@
+============================================
+The object-lifetime debugging infrastructure
+============================================
+
+:Author: Thomas Gleixner
+
+Introduction
+============
+
+debugobjects is a generic infrastructure to track the life time of
+kernel objects and validate the operations on those.
+
+debugobjects is useful to check for the following error patterns:
+
+- Activation of uninitialized objects
+
+- Initialization of active objects
+
+- Usage of freed/destroyed objects
+
+debugobjects is not changing the data structure of the real object so it
+can be compiled in with a minimal runtime impact and enabled on demand
+with a kernel command line option.
+
+Howto use debugobjects
+======================
+
+A kernel subsystem needs to provide a data structure which describes the
+object type and add calls into the debug code at appropriate places. The
+data structure to describe the object type needs at minimum the name of
+the object type. Optional functions can and should be provided to fixup
+detected problems so the kernel can continue to work and the debug
+information can be retrieved from a live system instead of hard core
+debugging with serial consoles and stack trace transcripts from the
+monitor.
+
+The debug calls provided by debugobjects are:
+
+- debug_object_init
+
+- debug_object_init_on_stack
+
+- debug_object_activate
+
+- debug_object_deactivate
+
+- debug_object_destroy
+
+- debug_object_free
+
+- debug_object_assert_init
+
+Each of these functions takes the address of the real object and a
+pointer to the object type specific debug description structure.
+
+Each detected error is reported in the statistics and a limited number
+of errors are printk'ed including a full stack trace.
+
+The statistics are available via /sys/kernel/debug/debug_objects/stats.
+They provide information about the number of warnings and the number of
+successful fixups along with information about the usage of the internal
+tracking objects and the state of the internal tracking objects pool.
+
+Debug functions
+===============
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_init
+
+This function is called whenever the initialization function of a real
+object is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be initialized. Initializing is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_init function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real initialization of the object happens. E.g. it
+can deactivate an active object in order to prevent damage to the
+subsystem.
+
+When the real object is not yet tracked by debugobjects, debugobjects
+allocates a tracker object for the real object and sets the tracker
+object state to ODEBUG_STATE_INIT. It verifies that the object is not
+on the callers stack. If it is on the callers stack then a limited
+number of warnings including a full stack trace is printk'ed. The
+calling code must use debug_object_init_on_stack() and remove the
+object before leaving the function which allocated it. See next section.
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_init_on_stack
+
+This function is called whenever the initialization function of a real
+object which resides on the stack is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be initialized. Initializing is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_init function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real initialization of the object happens. E.g. it
+can deactivate an active object in order to prevent damage to the
+subsystem.
+
+When the real object is not yet tracked by debugobjects debugobjects
+allocates a tracker object for the real object and sets the tracker
+object state to ODEBUG_STATE_INIT. It verifies that the object is on
+the callers stack.
+
+An object which is on the stack must be removed from the tracker by
+calling debug_object_free() before the function which allocates the
+object returns. Otherwise we keep track of stale objects.
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_activate
+
+This function is called whenever the activation function of a real
+object is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be activated. Activating is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_activate function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real activation of the object happens. E.g. it can
+deactivate an active object in order to prevent damage to the subsystem.
+
+When the real object is not yet tracked by debugobjects then the
+fixup_activate function is called if available. This is necessary to
+allow the legitimate activation of statically allocated and initialized
+objects. The fixup function checks whether the object is valid and calls
+the debug_objects_init() function to initialize the tracking of this
+object.
+
+When the activation is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_ACTIVE.
+
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_deactivate
+
+This function is called whenever the deactivation function of a real
+object is called.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be deactivated. Deactivating is not allowed for untracked
+or destroyed objects.
+
+When the deactivation is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_INACTIVE.
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_destroy
+
+This function is called to mark an object destroyed. This is useful to
+prevent the usage of invalid objects, which are still available in
+memory: either statically allocated objects or objects which are freed
+later.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be destroyed. Destruction is not allowed for active and
+destroyed objects. When debugobjects detects an error, then it calls the
+fixup_destroy function of the object type description structure if
+provided by the caller. The fixup function can correct the problem
+before the real destruction of the object happens. E.g. it can
+deactivate an active object in order to prevent damage to the subsystem.
+
+When the destruction is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_DESTROYED.
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_free
+
+This function is called before an object is freed.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be freed. Free is not allowed for active objects. When
+debugobjects detects an error, then it calls the fixup_free function of
+the object type description structure if provided by the caller. The
+fixup function can correct the problem before the real free of the
+object happens. E.g. it can deactivate an active object in order to
+prevent damage to the subsystem.
+
+Note that debug_object_free removes the object from the tracker. Later
+usage of the object is detected by the other debug checks.
+
+
+.. kernel-doc:: lib/debugobjects.c
+ :functions: debug_object_assert_init
+
+This function is called to assert that an object has been initialized.
+
+When the real object is not tracked by debugobjects, it calls
+fixup_assert_init of the object type description structure provided by
+the caller, with the hardcoded object state ODEBUG_NOT_AVAILABLE. The
+fixup function can correct the problem by calling debug_object_init
+and other specific initializing functions.
+
+When the real object is already tracked by debugobjects it is ignored.
+
+Fixup functions
+===============
+
+Debug object type description structure
+---------------------------------------
+
+.. kernel-doc:: include/linux/debugobjects.h
+ :internal:
+
+fixup_init
+-----------
+
+This function is called from the debug code whenever a problem in
+debug_object_init is detected. The function takes the address of the
+object and the state which is currently recorded in the tracker.
+
+Called from debug_object_init when the object state is:
+
+- ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note, that the function needs to call the debug_object_init() function
+again, after the damage has been repaired in order to keep the state
+consistent.
+
+fixup_activate
+---------------
+
+This function is called from the debug code whenever a problem in
+debug_object_activate is detected.
+
+Called from debug_object_activate when the object state is:
+
+- ODEBUG_STATE_NOTAVAILABLE
+
+- ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note that the function needs to call the debug_object_activate()
+function again after the damage has been repaired in order to keep the
+state consistent.
+
+The activation of statically initialized objects is a special case. When
+debug_object_activate() has no tracked object for this object address
+then fixup_activate() is called with object state
+ODEBUG_STATE_NOTAVAILABLE. The fixup function needs to check whether
+this is a legitimate case of a statically initialized object or not. In
+case it is it calls debug_object_init() and debug_object_activate()
+to make the object known to the tracker and marked active. In this case
+the function should return false because this is not a real fixup.
+
+fixup_destroy
+--------------
+
+This function is called from the debug code whenever a problem in
+debug_object_destroy is detected.
+
+Called from debug_object_destroy when the object state is:
+
+- ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+fixup_free
+-----------
+
+This function is called from the debug code whenever a problem in
+debug_object_free is detected. Further it can be called from the debug
+checks in kfree/vfree, when an active object is detected from the
+debug_check_no_obj_freed() sanity checks.
+
+Called from debug_object_free() or debug_check_no_obj_freed() when
+the object state is:
+
+- ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+fixup_assert_init
+-------------------
+
+This function is called from the debug code whenever a problem in
+debug_object_assert_init is detected.
+
+Called from debug_object_assert_init() with a hardcoded state
+ODEBUG_STATE_NOTAVAILABLE when the object is not found in the debug
+bucket.
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note, this function should make sure debug_object_init() is called
+before returning.
+
+The handling of statically initialized objects is a special case. The
+fixup function should check if this is a legitimate case of a statically
+initialized object or not. In this case only debug_object_init()
+should be called to make the object known to the tracker. Then the
+function should return false because this is not a real fixup.
+
+Known Bugs And Assumptions
+==========================
+
+None (knock on wood).
diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
new file mode 100644
index 000000000000..2872ca1a52f1
--- /dev/null
+++ b/Documentation/core-api/index.rst
@@ -0,0 +1,33 @@
+======================
+Core API Documentation
+======================
+
+This is the beginning of a manual for core kernel APIs. The conversion
+(and writing!) of documents for this manual is much appreciated!
+
+Core utilities
+==============
+
+.. toctree::
+ :maxdepth: 1
+
+ assoc_array
+ atomic_ops
+ local_ops
+ workqueue
+
+Interfaces for kernel debugging
+===============================
+
+.. toctree::
+ :maxdepth: 1
+
+ debug-objects
+ tracepoint
+
+.. only:: subproject
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/core-api/local_ops.rst b/Documentation/core-api/local_ops.rst
new file mode 100644
index 000000000000..1062ddba62c7
--- /dev/null
+++ b/Documentation/core-api/local_ops.rst
@@ -0,0 +1,206 @@
+
+.. _local_ops:
+
+=================================================
+Semantics and Behavior of Local Atomic Operations
+=================================================
+
+:Author: Mathieu Desnoyers
+
+
+This document explains the purpose of the local atomic operations, how
+to implement them for any given architecture and shows how they can be used
+properly. It also stresses on the precautions that must be taken when reading
+those local variables across CPUs when the order of memory writes matters.
+
+.. note::
+
+ Note that ``local_t`` based operations are not recommended for general
+ kernel use. Please use the ``this_cpu`` operations instead unless there is
+ really a special purpose. Most uses of ``local_t`` in the kernel have been
+ replaced by ``this_cpu`` operations. ``this_cpu`` operations combine the
+ relocation with the ``local_t`` like semantics in a single instruction and
+ yield more compact and faster executing code.
+
+
+Purpose of local atomic operations
+==================================
+
+Local atomic operations are meant to provide fast and highly reentrant per CPU
+counters. They minimize the performance cost of standard atomic operations by
+removing the LOCK prefix and memory barriers normally required to synchronize
+across CPUs.
+
+Having fast per CPU atomic counters is interesting in many cases: it does not
+require disabling interrupts to protect from interrupt handlers and it permits
+coherent counters in NMI handlers. It is especially useful for tracing purposes
+and for various performance monitoring counters.
+
+Local atomic operations only guarantee variable modification atomicity wrt the
+CPU which owns the data. Therefore, care must taken to make sure that only one
+CPU writes to the ``local_t`` data. This is done by using per cpu data and
+making sure that we modify it from within a preemption safe context. It is
+however permitted to read ``local_t`` data from any CPU: it will then appear to
+be written out of order wrt other memory writes by the owner CPU.
+
+
+Implementation for a given architecture
+=======================================
+
+It can be done by slightly modifying the standard atomic operations: only
+their UP variant must be kept. It typically means removing LOCK prefix (on
+i386 and x86_64) and any SMP synchronization barrier. If the architecture does
+not have a different behavior between SMP and UP, including
+``asm-generic/local.h`` in your architecture's ``local.h`` is sufficient.
+
+The ``local_t`` type is defined as an opaque ``signed long`` by embedding an
+``atomic_long_t`` inside a structure. This is made so a cast from this type to
+a ``long`` fails. The definition looks like::
+
+ typedef struct { atomic_long_t a; } local_t;
+
+
+Rules to follow when using local atomic operations
+==================================================
+
+* Variables touched by local ops must be per cpu variables.
+* *Only* the CPU owner of these variables must write to them.
+* This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
+ to update its ``local_t`` variables.
+* Preemption (or interrupts) must be disabled when using local ops in
+ process context to make sure the process won't be migrated to a
+ different CPU between getting the per-cpu variable and doing the
+ actual local op.
+* When using local ops in interrupt context, no special care must be
+ taken on a mainline kernel, since they will run on the local CPU with
+ preemption already disabled. I suggest, however, to explicitly
+ disable preemption anyway to make sure it will still work correctly on
+ -rt kernels.
+* Reading the local cpu variable will provide the current copy of the
+ variable.
+* Reads of these variables can be done from any CPU, because updates to
+ "``long``", aligned, variables are always atomic. Since no memory
+ synchronization is done by the writer CPU, an outdated copy of the
+ variable can be read when reading some *other* cpu's variables.
+
+
+How to use local atomic operations
+==================================
+
+::
+
+ #include <linux/percpu.h>
+ #include <asm/local.h>
+
+ static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+
+Counting
+========
+
+Counting is done on all the bits of a signed long.
+
+In preemptible context, use ``get_cpu_var()`` and ``put_cpu_var()`` around
+local atomic operations: it makes sure that preemption is disabled around write
+access to the per cpu variable. For instance::
+
+ local_inc(&get_cpu_var(counters));
+ put_cpu_var(counters);
+
+If you are already in a preemption-safe context, you can use
+``this_cpu_ptr()`` instead::
+
+ local_inc(this_cpu_ptr(&counters));
+
+
+
+Reading the counters
+====================
+
+Those local counters can be read from foreign CPUs to sum the count. Note that
+the data seen by local_read across CPUs must be considered to be out of order
+relatively to other memory writes happening on the CPU that owns the data::
+
+ long sum = 0;
+ for_each_online_cpu(cpu)
+ sum += local_read(&per_cpu(counters, cpu));
+
+If you want to use a remote local_read to synchronize access to a resource
+between CPUs, explicit ``smp_wmb()`` and ``smp_rmb()`` memory barriers must be used
+respectively on the writer and the reader CPUs. It would be the case if you use
+the ``local_t`` variable as a counter of bytes written in a buffer: there should
+be a ``smp_wmb()`` between the buffer write and the counter increment and also a
+``smp_rmb()`` between the counter read and the buffer read.
+
+
+Here is a sample module which implements a basic per cpu counter using
+``local.h``::
+
+ /* test-local.c
+ *
+ * Sample module for local.h usage.
+ */
+
+
+ #include <asm/local.h>
+ #include <linux/module.h>
+ #include <linux/timer.h>
+
+ static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+ static struct timer_list test_timer;
+
+ /* IPI called on each CPU. */
+ static void test_each(void *info)
+ {
+ /* Increment the counter from a non preemptible context */
+ printk("Increment on cpu %d\n", smp_processor_id());
+ local_inc(this_cpu_ptr(&counters));
+
+ /* This is what incrementing the variable would look like within a
+ * preemptible context (it disables preemption) :
+ *
+ * local_inc(&get_cpu_var(counters));
+ * put_cpu_var(counters);
+ */
+ }
+
+ static void do_test_timer(unsigned long data)
+ {
+ int cpu;
+
+ /* Increment the counters */
+ on_each_cpu(test_each, NULL, 1);
+ /* Read all the counters */
+ printk("Counters read from CPU %d\n", smp_processor_id());
+ for_each_online_cpu(cpu) {
+ printk("Read : CPU %d, count %ld\n", cpu,
+ local_read(&per_cpu(counters, cpu)));
+ }
+ del_timer(&test_timer);
+ test_timer.expires = jiffies + 1000;
+ add_timer(&test_timer);
+ }
+
+ static int __init test_init(void)
+ {
+ /* initialize the timer that will increment the counter */
+ init_timer(&test_timer);
+ test_timer.function = do_test_timer;
+ test_timer.expires = jiffies + 1;
+ add_timer(&test_timer);
+
+ return 0;
+ }
+
+ static void __exit test_exit(void)
+ {
+ del_timer_sync(&test_timer);
+ }
+
+ module_init(test_init);
+ module_exit(test_exit);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Mathieu Desnoyers");
+ MODULE_DESCRIPTION("Local Atomic Ops");
diff --git a/Documentation/core-api/tracepoint.rst b/Documentation/core-api/tracepoint.rst
new file mode 100644
index 000000000000..6b44bec0de43
--- /dev/null
+++ b/Documentation/core-api/tracepoint.rst
@@ -0,0 +1,55 @@
+===============================
+The Linux Kernel Tracepoint API
+===============================
+
+:Author: Jason Baron
+:Author: William Cohen
+
+Introduction
+============
+
+Tracepoints are static probe points that are located in strategic points
+throughout the kernel. 'Probes' register/unregister with tracepoints via
+a callback mechanism. The 'probes' are strictly typed functions that are
+passed a unique set of parameters defined by each tracepoint.
+
+From this simple callback mechanism, 'probes' can be used to profile,
+debug, and understand kernel behavior. There are a number of tools that
+provide a framework for using 'probes'. These tools include Systemtap,
+ftrace, and LTTng.
+
+Tracepoints are defined in a number of header files via various macros.
+Thus, the purpose of this document is to provide a clear accounting of
+the available tracepoints. The intention is to understand not only what
+tracepoints are available but also to understand where future
+tracepoints might be added.
+
+The API presented has functions of the form:
+``trace_tracepointname(function parameters)``. These are the tracepoints
+callbacks that are found throughout the code. Registering and
+unregistering probes with these callback sites is covered in the
+``Documentation/trace/*`` directory.
+
+IRQ
+===
+
+.. kernel-doc:: include/trace/events/irq.h
+ :internal:
+
+SIGNAL
+======
+
+.. kernel-doc:: include/trace/events/signal.h
+ :internal:
+
+Block IO
+========
+
+.. kernel-doc:: include/trace/events/block.h
+ :internal:
+
+Workqueue
+=========
+
+.. kernel-doc:: include/trace/events/workqueue.h
+ :internal:
diff --git a/Documentation/workqueue.txt b/Documentation/core-api/workqueue.rst
index c49e3178178d..ffdec94fbca1 100644
--- a/Documentation/workqueue.txt
+++ b/Documentation/core-api/workqueue.rst
@@ -1,21 +1,14 @@
-
+====================================
Concurrency Managed Workqueue (cmwq)
+====================================
-September, 2010 Tejun Heo <tj@kernel.org>
- Florian Mickler <florian@mickler.org>
-
-CONTENTS
-
-1. Introduction
-2. Why cmwq?
-3. The Design
-4. Application Programming Interface (API)
-5. Example Execution Scenarios
-6. Guidelines
-7. Debugging
+:Date: September, 2010
+:Author: Tejun Heo <tj@kernel.org>
+:Author: Florian Mickler <florian@mickler.org>
-1. Introduction
+Introduction
+============
There are many cases where an asynchronous process execution context
is needed and the workqueue (wq) API is the most commonly used
@@ -32,7 +25,8 @@ there is no work item left on the workqueue the worker becomes idle.
When a new work item gets queued, the worker begins executing again.
-2. Why cmwq?
+Why cmwq?
+=========
In the original wq implementation, a multi threaded (MT) wq had one
worker thread per CPU and a single threaded (ST) wq had one worker
@@ -71,7 +65,8 @@ focus on the following goals.
the API users don't need to worry about such details.
-3. The Design
+The Design
+==========
In order to ease the asynchronous execution of functions a new
abstraction, the work item, is introduced.
@@ -102,7 +97,7 @@ aspects of the way the work items are executed by setting flags on the
workqueue they are putting the work item on. These flags include
things like CPU locality, concurrency limits, priority and more. To
get a detailed overview refer to the API description of
-alloc_workqueue() below.
+``alloc_workqueue()`` below.
When a work item is queued to a workqueue, the target worker-pool is
determined according to the queue parameters and workqueue attributes
@@ -136,7 +131,7 @@ them.
For unbound workqueues, the number of backing pools is dynamic.
Unbound workqueue can be assigned custom attributes using
-apply_workqueue_attrs() and workqueue will automatically create
+``apply_workqueue_attrs()`` and workqueue will automatically create
backing worker pools matching the attributes. The responsibility of
regulating concurrency level is on the users. There is also a flag to
mark a bound wq to ignore the concurrency management. Please refer to
@@ -151,94 +146,95 @@ pressure. Else it is possible that the worker-pool deadlocks waiting
for execution contexts to free up.
-4. Application Programming Interface (API)
+Application Programming Interface (API)
+=======================================
-alloc_workqueue() allocates a wq. The original create_*workqueue()
-functions are deprecated and scheduled for removal. alloc_workqueue()
-takes three arguments - @name, @flags and @max_active. @name is the
-name of the wq and also used as the name of the rescuer thread if
-there is one.
+``alloc_workqueue()`` allocates a wq. The original
+``create_*workqueue()`` functions are deprecated and scheduled for
+removal. ``alloc_workqueue()`` takes three arguments - @``name``,
+``@flags`` and ``@max_active``. ``@name`` is the name of the wq and
+also used as the name of the rescuer thread if there is one.
A wq no longer manages execution resources but serves as a domain for
-forward progress guarantee, flush and work item attributes. @flags
-and @max_active control how work items are assigned execution
+forward progress guarantee, flush and work item attributes. ``@flags``
+and ``@max_active`` control how work items are assigned execution
resources, scheduled and executed.
-@flags:
-
- WQ_UNBOUND
-
- Work items queued to an unbound wq are served by the special
- worker-pools which host workers which are not bound to any
- specific CPU. This makes the wq behave as a simple execution
- context provider without concurrency management. The unbound
- worker-pools try to start execution of work items as soon as
- possible. Unbound wq sacrifices locality but is useful for
- the following cases.
-
- * Wide fluctuation in the concurrency level requirement is
- expected and using bound wq may end up creating large number
- of mostly unused workers across different CPUs as the issuer
- hops through different CPUs.
-
- * Long running CPU intensive workloads which can be better
- managed by the system scheduler.
-
- WQ_FREEZABLE
-
- A freezable wq participates in the freeze phase of the system
- suspend operations. Work items on the wq are drained and no
- new work item starts execution until thawed.
-
- WQ_MEM_RECLAIM
-
- All wq which might be used in the memory reclaim paths _MUST_
- have this flag set. The wq is guaranteed to have at least one
- execution context regardless of memory pressure.
-
- WQ_HIGHPRI
- Work items of a highpri wq are queued to the highpri
- worker-pool of the target cpu. Highpri worker-pools are
- served by worker threads with elevated nice level.
-
- Note that normal and highpri worker-pools don't interact with
- each other. Each maintain its separate pool of workers and
- implements concurrency management among its workers.
-
- WQ_CPU_INTENSIVE
-
- Work items of a CPU intensive wq do not contribute to the
- concurrency level. In other words, runnable CPU intensive
- work items will not prevent other work items in the same
- worker-pool from starting execution. This is useful for bound
- work items which are expected to hog CPU cycles so that their
- execution is regulated by the system scheduler.
-
- Although CPU intensive work items don't contribute to the
- concurrency level, start of their executions is still
- regulated by the concurrency management and runnable
- non-CPU-intensive work items can delay execution of CPU
- intensive work items.
-
- This flag is meaningless for unbound wq.
-
-Note that the flag WQ_NON_REENTRANT no longer exists as all workqueues
-are now non-reentrant - any work item is guaranteed to be executed by
-at most one worker system-wide at any given time.
-
-@max_active:
-
-@max_active determines the maximum number of execution contexts per
-CPU which can be assigned to the work items of a wq. For example,
-with @max_active of 16, at most 16 work items of the wq can be
+``flags``
+---------
+
+``WQ_UNBOUND``
+ Work items queued to an unbound wq are served by the special
+ worker-pools which host workers which are not bound to any
+ specific CPU. This makes the wq behave as a simple execution
+ context provider without concurrency management. The unbound
+ worker-pools try to start execution of work items as soon as
+ possible. Unbound wq sacrifices locality but is useful for
+ the following cases.
+
+ * Wide fluctuation in the concurrency level requirement is
+ expected and using bound wq may end up creating large number
+ of mostly unused workers across different CPUs as the issuer
+ hops through different CPUs.
+
+ * Long running CPU intensive workloads which can be better
+ managed by the system scheduler.
+
+``WQ_FREEZABLE``
+ A freezable wq participates in the freeze phase of the system
+ suspend operations. Work items on the wq are drained and no
+ new work item starts execution until thawed.
+
+``WQ_MEM_RECLAIM``
+ All wq which might be used in the memory reclaim paths **MUST**
+ have this flag set. The wq is guaranteed to have at least one
+ execution context regardless of memory pressure.
+
+``WQ_HIGHPRI``
+ Work items of a highpri wq are queued to the highpri
+ worker-pool of the target cpu. Highpri worker-pools are
+ served by worker threads with elevated nice level.
+
+ Note that normal and highpri worker-pools don't interact with
+ each other. Each maintain its separate pool of workers and
+ implements concurrency management among its workers.
+
+``WQ_CPU_INTENSIVE``
+ Work items of a CPU intensive wq do not contribute to the
+ concurrency level. In other words, runnable CPU intensive
+ work items will not prevent other work items in the same
+ worker-pool from starting execution. This is useful for bound
+ work items which are expected to hog CPU cycles so that their
+ execution is regulated by the system scheduler.
+
+ Although CPU intensive work items don't contribute to the
+ concurrency level, start of their executions is still
+ regulated by the concurrency management and runnable
+ non-CPU-intensive work items can delay execution of CPU
+ intensive work items.
+
+ This flag is meaningless for unbound wq.
+
+Note that the flag ``WQ_NON_REENTRANT`` no longer exists as all
+workqueues are now non-reentrant - any work item is guaranteed to be
+executed by at most one worker system-wide at any given time.
+
+
+``max_active``
+--------------
+
+``@max_active`` determines the maximum number of execution contexts
+per CPU which can be assigned to the work items of a wq. For example,
+with ``@max_active`` of 16, at most 16 work items of the wq can be
executing at the same time per CPU.
-Currently, for a bound wq, the maximum limit for @max_active is 512
-and the default value used when 0 is specified is 256. For an unbound
-wq, the limit is higher of 512 and 4 * num_possible_cpus(). These
-values are chosen sufficiently high such that they are not the
-limiting factor while providing protection in runaway cases.
+Currently, for a bound wq, the maximum limit for ``@max_active`` is
+512 and the default value used when 0 is specified is 256. For an
+unbound wq, the limit is higher of 512 and 4 *
+``num_possible_cpus()``. These values are chosen sufficiently high
+such that they are not the limiting factor while providing protection
+in runaway cases.
The number of active work items of a wq is usually regulated by the
users of the wq, more specifically, by how many work items the users
@@ -247,13 +243,14 @@ throttling the number of active work items, specifying '0' is
recommended.
Some users depend on the strict execution ordering of ST wq. The
-combination of @max_active of 1 and WQ_UNBOUND is used to achieve this
-behavior. Work items on such wq are always queued to the unbound
-worker-pools and only one work item can be active at any given time thus
-achieving the same ordering property as ST wq.
+combination of ``@max_active`` of 1 and ``WQ_UNBOUND`` is used to
+achieve this behavior. Work items on such wq are always queued to the
+unbound worker-pools and only one work item can be active at any given
+time thus achieving the same ordering property as ST wq.
-5. Example Execution Scenarios
+Example Execution Scenarios
+===========================
The following example execution scenarios try to illustrate how cmwq
behave under different configurations.
@@ -265,7 +262,7 @@ behave under different configurations.
Ignoring all other tasks, works and processing overhead, and assuming
simple FIFO scheduling, the following is one highly simplified version
-of possible sequences of events with the original wq.
+of possible sequences of events with the original wq. ::
TIME IN MSECS EVENT
0 w0 starts and burns CPU
@@ -279,7 +276,7 @@ of possible sequences of events with the original wq.
40 w2 sleeps
50 w2 wakes up and finishes
-And with cmwq with @max_active >= 3,
+And with cmwq with ``@max_active`` >= 3, ::
TIME IN MSECS EVENT
0 w0 starts and burns CPU
@@ -293,7 +290,7 @@ And with cmwq with @max_active >= 3,
20 w1 wakes up and finishes
25 w2 wakes up and finishes
-If @max_active == 2,
+If ``@max_active`` == 2, ::
TIME IN MSECS EVENT
0 w0 starts and burns CPU
@@ -308,7 +305,7 @@ If @max_active == 2,
35 w2 wakes up and finishes
Now, let's assume w1 and w2 are queued to a different wq q1 which has
-WQ_CPU_INTENSIVE set,
+``WQ_CPU_INTENSIVE`` set, ::
TIME IN MSECS EVENT
0 w0 starts and burns CPU
@@ -322,13 +319,15 @@ WQ_CPU_INTENSIVE set,
25 w2 wakes up and finishes
-6. Guidelines
+Guidelines
+==========
-* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
- which are used during memory reclaim. Each wq with WQ_MEM_RECLAIM
- set has an execution context reserved for it. If there is
- dependency among multiple work items used during memory reclaim,
- they should be queued to separate wq each with WQ_MEM_RECLAIM.
+* Do not forget to use ``WQ_MEM_RECLAIM`` if a wq may process work
+ items which are used during memory reclaim. Each wq with
+ ``WQ_MEM_RECLAIM`` set has an execution context reserved for it. If
+ there is dependency among multiple work items used during memory
+ reclaim, they should be queued to separate wq each with
+ ``WQ_MEM_RECLAIM``.
* Unless strict ordering is required, there is no need to use ST wq.
@@ -337,30 +336,31 @@ WQ_CPU_INTENSIVE set,
well under the default limit.
* A wq serves as a domain for forward progress guarantee
- (WQ_MEM_RECLAIM, flush and work item attributes. Work items which
- are not involved in memory reclaim and don't need to be flushed as a
- part of a group of work items, and don't require any special
- attribute, can use one of the system wq. There is no difference in
- execution characteristics between using a dedicated wq and a system
- wq.
+ (``WQ_MEM_RECLAIM``, flush and work item attributes. Work items
+ which are not involved in memory reclaim and don't need to be
+ flushed as a part of a group of work items, and don't require any
+ special attribute, can use one of the system wq. There is no
+ difference in execution characteristics between using a dedicated wq
+ and a system wq.
* Unless work items are expected to consume a huge amount of CPU
cycles, using a bound wq is usually beneficial due to the increased
level of locality in wq operations and work item execution.
-7. Debugging
+Debugging
+=========
Because the work functions are executed by generic worker threads
there are a few tricks needed to shed some light on misbehaving
workqueue users.
-Worker threads show up in the process list as:
+Worker threads show up in the process list as: ::
-root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]
-root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]
-root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]
-root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]
+ root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]
+ root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]
+ root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]
+ root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]
If kworkers are going crazy (using too much cpu), there are two types
of possible problems:
@@ -368,7 +368,7 @@ of possible problems:
1. Something being scheduled in rapid succession
2. A single work item that consumes lots of cpu cycles
-The first one can be tracked using tracing:
+The first one can be tracked using tracing: ::
$ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
$ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
@@ -380,9 +380,15 @@ the output and the offender can be determined with the work item
function.
For the second type of problems it should be possible to just check
-the stack trace of the offending worker thread.
+the stack trace of the offending worker thread. ::
$ cat /proc/THE_OFFENDING_KWORKER/stack
The work item's function should be trivially visible in the stack
trace.
+
+
+Kernel Inline Documentations Reference
+======================================
+
+.. kernel-doc:: include/linux/workqueue.h
diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt
index 8d9773f23550..3c355f6ad834 100644
--- a/Documentation/cpu-freq/cpufreq-stats.txt
+++ b/Documentation/cpu-freq/cpufreq-stats.txt
@@ -44,11 +44,17 @@ the stats driver insertion.
total 0
drwxr-xr-x 2 root root 0 May 14 16:06 .
drwxr-xr-x 3 root root 0 May 14 15:58 ..
+--w------- 1 root root 4096 May 14 16:06 reset
-r--r--r-- 1 root root 4096 May 14 16:06 time_in_state
-r--r--r-- 1 root root 4096 May 14 16:06 total_trans
-r--r--r-- 1 root root 4096 May 14 16:06 trans_table
--------------------------------------------------------------------------------
+- reset
+Write-only attribute that can be used to reset the stat counters. This can be
+useful for evaluating system behaviour under different governors without the
+need for a reboot.
+
- time_in_state
This gives the amount of time spent in each of the frequencies supported by
this CPU. The cat output will have "<frequency> <time>" pair in each line, which
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt
index e6bd1e6512a5..1953994ef5e6 100644
--- a/Documentation/cpu-freq/intel-pstate.txt
+++ b/Documentation/cpu-freq/intel-pstate.txt
@@ -48,7 +48,7 @@ In addition to the frequency-controlling interfaces provided by the cpufreq
core, the driver provides its own sysfs files to control the P-State selection.
These files have been added to /sys/devices/system/cpu/intel_pstate/.
Any changes made to these files are applicable to all CPUs (even in a
-multi-package system).
+multi-package system, Refer to later section on placing "Per-CPU limits").
max_perf_pct: Limits the maximum P-State that will be requested by
the driver. It states it as a percentage of the available performance. The
@@ -120,13 +120,57 @@ frequency is fictional for Intel Core processors. Even if the scaling
driver selects a single P-State, the actual frequency the processor
will run at is selected by the processor itself.
+Per-CPU limits
+
+The kernel command line option "intel_pstate=per_cpu_perf_limits" forces
+the intel_pstate driver to use per-CPU performance limits. When it is set,
+the sysfs control interface described above is subject to limitations.
+- The following controls are not available for both read and write
+ /sys/devices/system/cpu/intel_pstate/max_perf_pct
+ /sys/devices/system/cpu/intel_pstate/min_perf_pct
+- The following controls can be used to set performance limits, as far as the
+architecture of the processor permits:
+ /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq
+ /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq
+ /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+- User can still observe turbo percent and number of P-States from
+ /sys/devices/system/cpu/intel_pstate/turbo_pct
+ /sys/devices/system/cpu/intel_pstate/num_pstates
+- User can read write system wide turbo status
+ /sys/devices/system/cpu/no_turbo
+
+Support of energy performance hints
+It is possible to provide hints to the HWP algorithms in the processor
+to be more performance centric to more energy centric. When the driver
+is using HWP, two additional cpufreq sysfs attributes are presented for
+each logical CPU.
+These attributes are:
+ - energy_performance_available_preferences
+ - energy_performance_preference
+
+To get list of supported hints:
+$ cat energy_performance_available_preferences
+ default performance balance_performance balance_power power
+
+The current preference can be read or changed via cpufreq sysfs
+attribute "energy_performance_preference". Reading from this attribute
+will display current effective setting. User can write any of the valid
+preference string to this attribute. User can always restore to power-on
+default by writing "default".
+
+Since threads can migrate to different CPUs, this is possible that the
+new CPU may have different energy performance preference than the previous
+one. To avoid such issues, either threads can be pinned to specific CPUs
+or set the same energy performance preference value to all CPUs.
+
Tuning Intel P-State driver
-When HWP mode is not used, debugfs files have also been added to allow the
-tuning of the internal governor algorithm. These files are located at
-/sys/kernel/debug/pstate_snb/. The algorithm uses a PID (Proportional
-Integral Derivative) controller. The PID tunable parameters are:
+When the performance can be tuned using PID (Proportional Integral
+Derivative) controller, debugfs files are provided for adjusting performance.
+They are presented under:
+/sys/kernel/debug/pstate_snb/
+The PID tunable parameters are:
deadband
d_gain_pct
i_gain_pct
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index dd68821c22d4..d02e8a451872 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -84,9 +84,9 @@ are added or removed anytime. Trimming it accurately for your system needs
upfront can save some boot time memory. See below for how we use heuristics
in x86_64 case to keep this under check.
-cpu_online_mask: Bitmap of all CPUs currently online. Its set in __cpu_up()
-after a cpu is available for kernel scheduling and ready to receive
-interrupts from devices. Its cleared when a cpu is brought down using
+cpu_online_mask: Bitmap of all CPUs currently online. It's set in __cpu_up()
+after a CPU is available for kernel scheduling and ready to receive
+interrupts from devices. It's cleared when a CPU is brought down using
__cpu_disable(), before which all OS services including interrupts are
migrated to another target CPU.
@@ -181,7 +181,7 @@ To support physical addition/removal, one would need some BIOS hooks and
the platform should have something like an attention button in PCI hotplug.
CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs.
-Q: How do i logically offline a CPU?
+Q: How do I logically offline a CPU?
A: Do the following.
#echo 0 > /sys/devices/system/cpu/cpuX/online
@@ -191,15 +191,15 @@ Once the logical offline is successful, check
#cat /proc/interrupts
You should now not see the CPU that you removed. Also online file will report
-the state as 0 when a cpu if offline and 1 when its online.
+the state as 0 when a CPU is offline and 1 when it's online.
#To display the current cpu state.
#cat /sys/devices/system/cpu/cpuX/online
-Q: Why can't i remove CPU0 on some systems?
+Q: Why can't I remove CPU0 on some systems?
A: Some architectures may have some special dependency on a certain CPU.
-For e.g in IA64 platforms we have ability to sent platform interrupts to the
+For e.g in IA64 platforms we have ability to send platform interrupts to the
OS. a.k.a Corrected Platform Error Interrupts (CPEI). In current ACPI
specifications, we didn't have a way to change the target CPU. Hence if the
current ACPI version doesn't support such re-direction, we disable that CPU
@@ -231,7 +231,7 @@ either by CONFIG_BOOTPARAM_HOTPLUG_CPU0 or by kernel parameter cpu0_hotplug.
--Fenghua Yu <fenghua.yu@intel.com>
-Q: How do i find out if a particular CPU is not removable?
+Q: How do I find out if a particular CPU is not removable?
A: Depending on the implementation, some architectures may show this by the
absence of the "online" file. This is done if it can be determined ahead of
time that this CPU cannot be removed.
@@ -250,7 +250,7 @@ A: The following happen, listed in no particular order :-)
- All processes are migrated away from this outgoing CPU to new CPUs.
The new CPU is chosen from each process' current cpuset, which may be
a subset of all online CPUs.
-- All interrupts targeted to this CPU is migrated to a new CPU
+- All interrupts targeted to this CPU are migrated to a new CPU
- timers/bottom half/task lets are also migrated to a new CPU
- Once all services are migrated, kernel calls an arch specific routine
__cpu_disable() to perform arch specific cleanup.
@@ -259,10 +259,10 @@ A: The following happen, listed in no particular order :-)
CPU is being offlined).
"It is expected that each service cleans up when the CPU_DOWN_PREPARE
- notifier is called, when CPU_DEAD is called its expected there is nothing
+ notifier is called, when CPU_DEAD is called it's expected there is nothing
running on behalf of this CPU that was offlined"
-Q: If i have some kernel code that needs to be aware of CPU arrival and
+Q: If I have some kernel code that needs to be aware of CPU arrival and
departure, how to i arrange for proper notification?
A: This is what you would need in your kernel code to receive notifications.
@@ -311,7 +311,7 @@ things will happen if a notifier in path sent a BAD notify code.
Q: I don't see my action being called for all CPUs already up and running?
A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
- If you need to perform some action for each cpu already in the system, then
+ If you need to perform some action for each CPU already in the system, then
do this:
for_each_online_cpu(i) {
@@ -363,8 +363,8 @@ A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
callbacks as well as initialize the already online CPUs.
-Q: If i would like to develop cpu hotplug support for a new architecture,
- what do i need at a minimum?
+Q: If I would like to develop CPU hotplug support for a new architecture,
+ what do I need at a minimum?
A: The following are what is required for CPU hotplug infrastructure to work
correctly.
@@ -382,8 +382,8 @@ A: The following are what is required for CPU hotplug infrastructure to work
per_cpu state to be set, to ensure the processor
dead routine is called to be sure positively.
-Q: I need to ensure that a particular cpu is not removed when there is some
- work specific to this cpu is in progress.
+Q: I need to ensure that a particular CPU is not removed when there is some
+ work specific to this CPU in progress.
A: There are two ways. If your code can be run in interrupt context, use
smp_call_function_single(), otherwise use work_on_cpu(). Note that
work_on_cpu() is slow, and can fail due to out of memory:
diff --git a/Documentation/dev-tools/conf.py b/Documentation/dev-tools/conf.py
new file mode 100644
index 000000000000..7faafa3f7888
--- /dev/null
+++ b/Documentation/dev-tools/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Development tools for the kernel"
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'dev-tools.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/dev-tools/gcov.rst b/Documentation/dev-tools/gcov.rst
index 19eedfea8800..69a7d90c320a 100644
--- a/Documentation/dev-tools/gcov.rst
+++ b/Documentation/dev-tools/gcov.rst
@@ -201,7 +201,9 @@ Appendix A: gather_on_build.sh
------------------------------
Sample script to gather coverage meta files on the build machine
-(see 6a)::
+(see 6a):
+
+.. code-block:: sh
#!/bin/bash
@@ -232,7 +234,9 @@ Appendix B: gather_on_test.sh
-----------------------------
Sample script to gather coverage data files on the test machine
-(see 6b)::
+(see 6b):
+
+.. code-block:: sh
#!/bin/bash -e
diff --git a/Documentation/dev-tools/tools.rst b/Documentation/dev-tools/index.rst
index 824ae8e54dd5..07d881147ef3 100644
--- a/Documentation/dev-tools/tools.rst
+++ b/Documentation/dev-tools/index.rst
@@ -23,3 +23,11 @@ whole; patches welcome!
kmemleak
kmemcheck
gdb-kernel-debugging
+
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index aca0e27ca197..2c41b713841f 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -24,7 +24,9 @@ Profiling data will only become accessible once debugfs has been mounted::
mount -t debugfs none /sys/kernel/debug
-The following program demonstrates kcov usage from within a test program::
+The following program demonstrates kcov usage from within a test program:
+
+.. code-block:: c
#include <stdio.h>
#include <stddef.h>
diff --git a/Documentation/development-process/index.rst b/Documentation/development-process/index.rst
deleted file mode 100644
index c37475d91090..000000000000
--- a/Documentation/development-process/index.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-Linux Kernel Development Documentation
-======================================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- development-process
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt
index c75b64a85859..9bd531aa2279 100644
--- a/Documentation/device-mapper/dm-raid.txt
+++ b/Documentation/device-mapper/dm-raid.txt
@@ -17,7 +17,7 @@ The target is named "raid" and it accepts the following parameters:
raid0 RAID0 striping (no resilience)
raid1 RAID1 mirroring
raid4 RAID4 with dedicated last parity disk
- raid5_n RAID5 with dedicated last parity disk suporting takeover
+ raid5_n RAID5 with dedicated last parity disk supporting takeover
Same as raid4
-Transitory layout
raid5_la RAID5 left asymmetric
@@ -36,7 +36,7 @@ The target is named "raid" and it accepts the following parameters:
- rotating parity N (right-to-left) with data continuation
raid6_n_6 RAID6 with dedicate parity disks
- parity and Q-syndrome on the last 2 disks;
- laylout for takeover from/to raid4/raid5_n
+ layout for takeover from/to raid4/raid5_n
raid6_la_6 Same as "raid_la" plus dedicated last Q-syndrome disk
- layout for takeover from raid5_la from/to raid6
raid6_ra_6 Same as "raid5_ra" dedicated last Q-syndrome disk
@@ -137,8 +137,8 @@ The target is named "raid" and it accepts the following parameters:
device removal (negative value) or device addition (positive
value) to any reshape supporting raid levels 4/5/6 and 10.
RAID levels 4/5/6 allow for addition of devices (metadata
- and data device tupel), raid10_near and raid10_offset only
- allow for device addtion. raid10_far does not support any
+ and data device tuple), raid10_near and raid10_offset only
+ allow for device addition. raid10_far does not support any
reshaping at all.
A minimum of devices have to be kept to enforce resilience,
which is 3 devices for raid4/5 and 4 devices for raid6.
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index ef5fbe9a77c7..ad440a2b8051 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -38,6 +38,11 @@ to deliver its interrupts via SPIs.
architecturally-defined reset values. Only supported for 32-bit
systems which follow the ARMv7 architected reset values.
+- arm,no-tick-in-suspend : The main counter does not tick when the system is in
+ low-power system suspend on some SoCs. This behavior does not match the
+ Architecture Reference Manual's specification that the system counter "must
+ be implemented in an always-on power domain."
+
Example:
diff --git a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
index 63379b04e052..1dc80f8811fe 100644
--- a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
@@ -79,7 +79,7 @@ Required Properties:
Input clocks for fsys clock controller:
- oscclk
- sclk_ufs_mphy
- - div_aclk_fsys_200
+ - aclk_fsys_200
- sclk_pcie_100_fsys
- sclk_ufsunipro_fsys
- sclk_mmc2_fsys
@@ -104,6 +104,10 @@ Required Properties:
- sclk_decon_tv_vclk_disp
- aclk_disp_333
+ Input clocks for audio clock controller:
+ - oscclk
+ - fout_aud_pll
+
Input clocks for bus0 clock controller:
- aclk_bus0_400
@@ -235,7 +239,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk",
"sclk_ufs_mphy",
- "div_aclk_fsys_200",
+ "aclk_fsys_200",
"sclk_pcie_100_fsys",
"sclk_ufsunipro_fsys",
"sclk_mmc2_fsys",
@@ -245,7 +249,7 @@ Example 2: Examples of clock controller nodes are listed below.
"sclk_usbdrd30_fsys";
clocks = <&xxti>,
<&cmu_cpif CLK_SCLK_UFS_MPHY>,
- <&cmu_top CLK_DIV_ACLK_FSYS_200>,
+ <&cmu_top CLK_ACLK_FSYS_200>,
<&cmu_top CLK_SCLK_PCIE_100_FSYS>,
<&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>,
<&cmu_top CLK_SCLK_MMC2_FSYS>,
@@ -297,6 +301,9 @@ Example 2: Examples of clock controller nodes are listed below.
compatible = "samsung,exynos5433-cmu-aud";
reg = <0x114c0000 0x0b04>;
#clock-cells = <1>;
+
+ clock-names = "oscclk", "fout_aud_pll";
+ clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
};
cmu_bus0: clock-controller@13600000 {
diff --git a/Documentation/devicetree/bindings/clock/hi3519-crg.txt b/Documentation/devicetree/bindings/clock/hisi-crg.txt
index acd1f235d548..cc60b3d423f3 100644
--- a/Documentation/devicetree/bindings/clock/hi3519-crg.txt
+++ b/Documentation/devicetree/bindings/clock/hisi-crg.txt
@@ -1,7 +1,7 @@
-* Hisilicon Hi3519 Clock and Reset Generator(CRG)
+* HiSilicon Clock and Reset Generator(CRG)
-The Hi3519 CRG module provides clock and reset signals to various
-controllers within the SoC.
+The CRG module provides clock and reset signals to various
+modules within the SoC.
This binding uses the following bindings:
Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -10,7 +10,11 @@ This binding uses the following bindings:
Required Properties:
- compatible: should be one of the following.
- - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC.
+ - "hisilicon,hi3516cv300-crg"
+ - "hisilicon,hi3516cv300-sysctrl"
+ - "hisilicon,hi3519-crg"
+ - "hisilicon,hi3798cv200-crg"
+ - "hisilicon,hi3798cv200-sysctrl"
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
index 208cca6ac4ec..b652f3fb7796 100644
--- a/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
+++ b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
@@ -5,22 +5,15 @@ Please also refer to clock-bindings.txt in this directory for common clock
bindings usage.
Required properties:
-- compatible: Should be "oxsemi,ox810se-stdclk"
+- compatible: For OX810SE, should be "oxsemi,ox810se-stdclk"
+ For OX820, should be "oxsemi,ox820-stdclk"
- #clock-cells: 1, see below
Parent node should have the following properties :
-- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
-
-For OX810SE, the clock indices are :
- - 0: LEON
- - 1: DMA_SGDMA
- - 2: CIPHER
- - 3: SATA
- - 4: AUDIO
- - 5: USBMPH
- - 6: ETHA
- - 7: PCIA
- - 8: NAND
+- compatible: For OX810SE, should be
+ "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+ For OX820, should be
+ "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"
example:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 3cf44217068e..5b4dfc1ea54f 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -14,6 +14,7 @@ Required properties :
"qcom,gcc-msm8974"
"qcom,gcc-msm8974pro"
"qcom,gcc-msm8974pro-ac"
+ "qcom,gcc-msm8994"
"qcom,gcc-msm8996"
"qcom,gcc-mdm9615"
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
new file mode 100644
index 000000000000..87d3714b956a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
@@ -0,0 +1,37 @@
+Qualcomm RPM Clock Controller Binding
+------------------------------------------------
+The RPM is a dedicated hardware engine for managing the shared
+SoC resources in order to keep the lowest power profile. It
+communicates with other hardware subsystems via shared memory
+and accepts clock requests, aggregates the requests and turns
+the clocks on/off or scales them on demand.
+
+Required properties :
+- compatible : shall contain only one of the following. The generic
+ compatible "qcom,rpmcc" should be also included.
+
+ "qcom,rpmcc-msm8916", "qcom,rpmcc"
+ "qcom,rpmcc-apq8064", "qcom,rpmcc"
+
+- #clock-cells : shall contain 1
+
+Example:
+ smd {
+ compatible = "qcom,smd";
+
+ rpm {
+ interrupts = <0 168 1>;
+ qcom,ipc = <&apcs 8 0>;
+ qcom,smd-edge = <15>;
+
+ rpm_requests {
+ compatible = "qcom,rpm-msm8916";
+ qcom,smd-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc";
+ #clock-cells = <1>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
index 394d725ac7e0..c46919412953 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
@@ -13,6 +13,8 @@ They provide the following functionalities:
Required Properties:
- compatible: Must be one of:
+ - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
+ - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
- "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
- "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
@@ -22,8 +24,9 @@ Required Properties:
- clocks: References to external parent clocks, one entry for each entry in
clock-names
- clock-names: List of external parent clock names. Valid names are:
- - "extal" (r8a7795, r8a7796)
+ - "extal" (r8a7743, r8a7745, r8a7795, r8a7796)
- "extalr" (r8a7795, r8a7796)
+ - "usb_extal" (r8a7743, r8a7745)
- #clock-cells: Must be 2
- For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
new file mode 100644
index 000000000000..4da126116cf0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
@@ -0,0 +1,59 @@
+* Rockchip RK1108 Clock and Reset Unit
+
+The RK1108 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk1108-cru"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+ If missing pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk1108-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_vip" - external VIP clock - optional
+ - "ext_i2s" - external I2S clock - optional
+ - "ext_gmac" - external GMAC clock - optional
+ - "hdmiphy" - external clock input derived from HDMI PHY - optional
+ - "usbphy" - external clock input derived from USB PHY - optional
+
+Example: Clock controller node:
+
+ cru: cru@20200000 {
+ compatible = "rockchip,rk1108-cru";
+ reg = <0x20200000 0x1000>;
+ rockchip,grf = <&grf>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart0: serial@10230000 {
+ compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+ reg = <0x10230000 0x100>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART0>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index c209de6cfadb..0532d815dae3 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for common clock controller binding usage.
Please also refer to reset.txt for common reset controller binding usage.
Required properties:
-- compatible: Should be "st,stm32f42xx-rcc"
+- compatible: Should be:
+ "st,stm32f42xx-rcc"
+ "st,stm32f469-rcc"
- reg: should be register base and length as documented in the
datasheet
- #reset-cells: 1, see below
diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt
index 3868458a5feb..74d44a4273f2 100644
--- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt
@@ -7,6 +7,7 @@ Required properties :
- "allwinner,sun8i-a23-ccu"
- "allwinner,sun8i-a33-ccu"
- "allwinner,sun8i-h3-ccu"
+ - "allwinner,sun50i-a64-ccu"
- reg: Must contain the registers base address and length
- clocks: phandle to the oscillators feeding the CCU. Two are needed:
diff --git a/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt b/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
new file mode 100644
index 000000000000..af2385795d78
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
@@ -0,0 +1,78 @@
+Broadcom AVS mail box and interrupt register bindings
+=====================================================
+
+A total of three DT nodes are required. One node (brcm,avs-cpu-data-mem)
+references the mailbox register used to communicate with the AVS CPU[1]. The
+second node (brcm,avs-cpu-l2-intr) is required to trigger an interrupt on
+the AVS CPU. The interrupt tells the AVS CPU that it needs to process a
+command sent to it by a driver. Interrupting the AVS CPU is mandatory for
+commands to be processed.
+
+The interface also requires a reference to the AVS host interrupt controller,
+so a driver can react to interrupts generated by the AVS CPU whenever a command
+has been processed. See [2] for more information on the brcm,l2-intc node.
+
+[1] The AVS CPU is an independent co-processor that runs proprietary
+firmware. On some SoCs, this firmware supports DFS and DVFS in addition to
+Adaptive Voltage Scaling.
+
+[2] Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.txt
+
+
+Node brcm,avs-cpu-data-mem
+--------------------------
+
+Required properties:
+- compatible: must include: brcm,avs-cpu-data-mem and
+ should include: one of brcm,bcm7271-avs-cpu-data-mem or
+ brcm,bcm7268-avs-cpu-data-mem
+- reg: Specifies base physical address and size of the registers.
+- interrupts: The interrupt that the AVS CPU will use to interrupt the host
+ when a command completed.
+- interrupt-parent: The interrupt controller the above interrupt is routed
+ through.
+- interrupt-names: The name of the interrupt used to interrupt the host.
+
+Optional properties:
+- None
+
+Node brcm,avs-cpu-l2-intr
+-------------------------
+
+Required properties:
+- compatible: must include: brcm,avs-cpu-l2-intr and
+ should include: one of brcm,bcm7271-avs-cpu-l2-intr or
+ brcm,bcm7268-avs-cpu-l2-intr
+- reg: Specifies base physical address and size of the registers.
+
+Optional properties:
+- None
+
+
+Example
+=======
+
+ avs_host_l2_intc: interrupt-controller@f04d1200 {
+ #interrupt-cells = <1>;
+ compatible = "brcm,l2-intc";
+ interrupt-parent = <&intc>;
+ reg = <0xf04d1200 0x48>;
+ interrupt-controller;
+ interrupts = <0x0 0x19 0x0>;
+ interrupt-names = "avs";
+ };
+
+ avs-cpu-data-mem@f04c4000 {
+ compatible = "brcm,bcm7271-avs-cpu-data-mem",
+ "brcm,avs-cpu-data-mem";
+ reg = <0xf04c4000 0x60>;
+ interrupts = <0x1a>;
+ interrupt-parent = <&avs_host_l2_intc>;
+ interrupt-names = "sw_intr";
+ };
+
+ avs-cpu-l2-intr@f04d1100 {
+ compatible = "brcm,bcm7271-avs-cpu-l2-intr",
+ "brcm,avs-cpu-l2-intr";
+ reg = <0xf04d1100 0x10>;
+ };
diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
new file mode 100644
index 000000000000..00f74bad1e95
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
@@ -0,0 +1,112 @@
+Amlogic Meson Display Controller
+================================
+
+The Amlogic Meson Display controller is composed of several components
+that are going to be documented below:
+
+DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
+ | vd1 _______ _____________ _________________ | |
+D |-------| |----| | | | | HDMI PLL |
+D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK |
+R |-------| |----| Processing | | | | |
+ | osd2 | | | |---| Enci ----------|----|-----VDAC------|
+R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----|
+A | osd1 | | | Blenders | | Encl ----------|----|---------------|
+M |-------|______|----|____________| |________________| | |
+___|__________________________________________________________|_______________|
+
+
+VIU: Video Input Unit
+---------------------
+
+The Video Input Unit is in charge of the pixel scanout from the DDR memory.
+It fetches the frames addresses, stride and parameters from the "Canvas" memory.
+This part is also in charge of the CSC (Colorspace Conversion).
+It can handle 2 OSD Planes and 2 Video Planes.
+
+VPP: Video Post Processing
+--------------------------
+
+The Video Post Processing is in charge of the scaling and blending of the
+various planes into a single pixel stream.
+There is a special "pre-blending" used by the video planes with a dedicated
+scaler and a "post-blending" to merge with the OSD Planes.
+The OSD planes also have a dedicated scaler for one of the OSD.
+
+VENC: Video Encoders
+--------------------
+
+The VENC is composed of the multiple pixel encoders :
+ - ENCI : Interlace Video encoder for CVBS and Interlace HDMI
+ - ENCP : Progressive Video Encoder for HDMI
+ - ENCL : LCD LVDS Encoder
+The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock
+tree and provides the scanout clock to the VPP and VIU.
+The ENCI is connected to a single VDAC for Composite Output.
+The ENCI and ENCP are connected to an on-chip HDMI Transceiver.
+
+Device Tree Bindings:
+---------------------
+
+VPU: Video Processing Unit
+--------------------------
+
+Required properties:
+- compatible: value should be different for each SoC family as :
+ - GXBB (S905) : "amlogic,meson-gxbb-vpu"
+ - GXL (S905X, S905D) : "amlogic,meson-gxl-vpu"
+ - GXM (S912) : "amlogic,meson-gxm-vpu"
+ followed by the common "amlogic,meson-gx-vpu"
+- reg: base address and size of he following memory-mapped regions :
+ - vpu
+ - hhi
+ - dmc
+- reg-names: should contain the names of the previous memory regions
+- interrupts: should contain the VENC Vsync interrupt number
+
+Required nodes:
+
+The connections to the VPU output video ports are modeled using the OF graph
+bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+The following table lists for each supported model the port number
+corresponding to each VPU output.
+
+ Port 0 Port 1
+-----------------------------------------
+ S905 (GXBB) CVBS VDAC HDMI-TX
+ S905X (GXL) CVBS VDAC HDMI-TX
+ S905D (GXL) CVBS VDAC HDMI-TX
+ S912 (GXM) CVBS VDAC HDMI-TX
+
+Example:
+
+tv-connector {
+ compatible = "composite-video-connector";
+
+ port {
+ tv_connector_in: endpoint {
+ remote-endpoint = <&cvbs_vdac_out>;
+ };
+ };
+};
+
+vpu: vpu@d0100000 {
+ compatible = "amlogic,meson-gxbb-vpu";
+ reg = <0x0 0xd0100000 0x0 0x100000>,
+ <0x0 0xc883c000 0x0 0x1000>,
+ <0x0 0xc8838000 0x0 0x1000>;
+ reg-names = "vpu", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* CVBS VDAC output port */
+ port@0 {
+ reg = <0>;
+
+ cvbs_vdac_out: endpoint {
+ remote-endpoint = <&tv_connector_in>;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
index a5ea451e67fc..e2768703ac2b 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
+++ b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
@@ -43,6 +43,13 @@ Required properties for DPI:
- port: Port node with a single endpoint connecting to the panel
device, as defined in [1]
+Required properties for VEC:
+- compatible: Should be "brcm,bcm2835-vec"
+- reg: Physical base address and length of the registers
+- clocks: The core clock the unit runs on
+- interrupts: The interrupt number
+ See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+
Required properties for V3D:
- compatible: Should be "brcm,bcm2835-v3d"
- reg: Physical base address and length of the V3D's registers
@@ -92,6 +99,13 @@ dpi: dpi@7e208000 {
};
};
+vec: vec@7e806000 {
+ compatible = "brcm,bcm2835-vec";
+ reg = <0x7e806000 0x1000>;
+ clocks = <&clocks BCM2835_CLOCK_VEC>;
+ interrupts = <2 27>;
+};
+
v3d: v3d@7ec00000 {
compatible = "brcm,bcm2835-v3d";
reg = <0x7ec00000 0x1000>;
diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
index 003bc246a270..164cbb15f04c 100644
--- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
+++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
@@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
- Video port 0 for RGB input
- Video port 1 for VGA output
+Optional properties:
+- vdd-supply: Power supply for DAC
Example
-------
diff --git a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
index dc1452f0d5d8..5e9a84d6e5f1 100644
--- a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
@@ -19,7 +19,9 @@ Required properties:
Optional properties
- reg-io-width: the width of the reg:1,4, default set to 1 if not present
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing,
+ if the property is omitted, a functionally reduced I2C bus
+ controller on DW HDMI is probed
- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
Example:
diff --git a/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt
index 2cbe32a3d0bb..54d7e31525ec 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt
+++ b/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt
@@ -6,10 +6,15 @@ Required properties:
Optional properties:
- powerdown-gpios: power-down gpio
+- reg: I2C address. If and only if present the device node
+ should be placed into the i2c controller node where the
+ tfp410 i2c is connected to.
Required nodes:
-- Video port 0 for DPI input
-- Video port 1 for DVI output
+- Video port 0 for DPI input [1].
+- Video port 1 for DVI output [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
Example
-------
diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt b/Documentation/devicetree/bindings/display/mxsfb.txt
index 96ec5179c8a0..472e1ea6c591 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -1,20 +1,57 @@
* Freescale MXS LCD Interface (LCDIF)
+New bindings:
+=============
Required properties:
-- compatible: Should be "fsl,<chip>-lcdif". Supported chips include
- imx23 and imx28.
-- reg: Address and length of the register set for lcdif
-- interrupts: Should contain lcdif interrupts
-- display : phandle to display node (see below for details)
+- compatible: Should be "fsl,imx23-lcdif" for i.MX23.
+ Should be "fsl,imx28-lcdif" for i.MX28.
+ Should be "fsl,imx6sx-lcdif" for i.MX6SX.
+- reg: Address and length of the register set for LCDIF
+- interrupts: Should contain LCDIF interrupt
+- clocks: A list of phandle + clock-specifier pairs, one for each
+ entry in 'clock-names'.
+- clock-names: A list of clock names. For MXSFB it should contain:
+ - "pix" for the LCDIF block clock
+ - (MX6SX-only) "axi", "disp_axi" for the bus interface clock
+
+Required sub-nodes:
+ - port: The connection to an encoder chip.
+
+Example:
+
+ lcdif1: display-controller@2220000 {
+ compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif";
+ reg = <0x02220000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>,
+ <&clks IMX6SX_CLK_LCDIF_APB>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pix", "axi", "disp_axi";
+
+ port {
+ parallel_out: endpoint {
+ remote-endpoint = <&panel_in_parallel>;
+ };
+ };
+ };
+
+Deprecated bindings:
+====================
+Required properties:
+- compatible: Should be "fsl,imx23-lcdif" for i.MX23.
+ Should be "fsl,imx28-lcdif" for i.MX28.
+- reg: Address and length of the register set for LCDIF
+- interrupts: Should contain LCDIF interrupts
+- display: phandle to display node (see below for details)
* display node
Required properties:
-- bits-per-pixel : <16> for RGB565, <32> for RGB888/666.
-- bus-width : number of data lines. Could be <8>, <16>, <18> or <24>.
+- bits-per-pixel: <16> for RGB565, <32> for RGB888/666.
+- bus-width: number of data lines. Could be <8>, <16>, <18> or <24>.
Required sub-node:
-- display-timings : Refer to binding doc display-timing.txt for details.
+- display-timings: Refer to binding doc display-timing.txt for details.
Examples:
diff --git a/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt b/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt
new file mode 100644
index 000000000000..3afc76747824
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt
@@ -0,0 +1,7 @@
+AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,g133han01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt b/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt
new file mode 100644
index 000000000000..ed657c2141d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt
@@ -0,0 +1,7 @@
+AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,g185han01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt
new file mode 100644
index 000000000000..cbd9da3f03b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt
@@ -0,0 +1,7 @@
+AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,t215hvn01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt b/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt
new file mode 100644
index 000000000000..dd22685d2adc
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 7" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa070wp03xg"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/display-timing.txt b/Documentation/devicetree/bindings/display/panel/display-timing.txt
index e1d4a0b59612..81a75893d1b8 100644
--- a/Documentation/devicetree/bindings/display/panel/display-timing.txt
+++ b/Documentation/devicetree/bindings/display/panel/display-timing.txt
@@ -32,6 +32,14 @@ optional properties:
- active low = drive pixel data on falling edge/
sample data on rising edge
- ignored = ignored
+ - syncclk-active: with
+ - active high = drive sync on rising edge/
+ sample sync on falling edge of pixel
+ clock
+ - active low = drive sync on falling edge/
+ sample sync on rising edge of pixel
+ clock
+ - omitted = same configuration as pixelclk-active
- interlaced (bool): boolean to enable interlaced mode
- doublescan (bool): boolean to enable doublescan mode
- doubleclk (bool): boolean to enable doubleclock mode
diff --git a/Documentation/devicetree/bindings/display/panel/nvd,9128.txt b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
new file mode 100644
index 000000000000..17bcd017c678
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
@@ -0,0 +1,7 @@
+New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
+
+Required properties:
+- compatible: should be "nvd,9128"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt
new file mode 100644
index 000000000000..0f57c3143506
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt
@@ -0,0 +1,36 @@
+Sharp 15" LQ150X1LG11 XGA TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,lq150x1lg11"
+- power-supply: regulator to provide the VCC supply voltage (3.3 volts)
+
+Optional properties:
+- backlight: phandle of the backlight device
+- rlud-gpios: a single GPIO for the RL/UD (rotate 180 degrees) pin.
+- sellvds-gpios: a single GPIO for the SELLVDS pin.
+
+If rlud-gpios and/or sellvds-gpios are not specified, the RL/UD and/or SELLVDS
+pins are assumed to be handled appropriately by the hardware.
+
+Example:
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 100000>; /* VBR */
+
+ brightness-levels = <0 20 40 60 80 100>;
+ default-brightness-level = <2>;
+
+ power-supply = <&vdd_12v_reg>; /* VDD */
+ enable-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; /* XSTABY */
+ };
+
+ panel {
+ compatible = "sharp,lq150x1lg11";
+
+ power-supply = <&vcc_3v3_reg>; /* VCC */
+
+ backlight = <&backlight>;
+ rlud-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; /* RL/UD */
+ sellvds-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; /* SELLVDS */
+ };
diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
index 0d30e42e40be..1a02f099a0ff 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.txt
+++ b/Documentation/devicetree/bindings/display/renesas,du.txt
@@ -6,9 +6,11 @@ Required Properties:
- "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
- "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
- "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
+ - "renesas,du-r8a7792" for R8A7792 (R-Car V2H) compatible DU
- "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
- "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
+ - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
- reg: A list of base address and length of each memory resource, one for
each entry in the reg-names property.
@@ -25,10 +27,10 @@ Required Properties:
- clock-names: Name of the clocks. This property is model-dependent.
- R8A7779 uses a single functional clock. The clock doesn't need to be
named.
- - R8A779[01345] use one functional clock per channel and one clock per LVDS
- encoder (if available). The functional clocks must be named "du.x" with
- "x" being the channel numerical index. The LVDS clocks must be named
- "lvds.x" with "x" being the LVDS encoder numerical index.
+ - R8A779[0123456] use one functional clock per channel and one clock per
+ LVDS encoder (if available). The functional clocks must be named "du.x"
+ with "x" being the channel numerical index. The LVDS clocks must be
+ named "lvds.x" with "x" being the LVDS encoder numerical index.
- In addition to the functional and encoder clocks, all DU versions also
support externally supplied pixel clocks. Those clocks are optional.
When supplied they must be named "dclkin.x" with "x" being the input
@@ -47,9 +49,11 @@ corresponding to each DU output.
R8A7779 (H1) DPAD 0 DPAD 1 - -
R8A7790 (H2) DPAD LVDS 0 LVDS 1 -
R8A7791 (M2-W) DPAD LVDS 0 - -
+ R8A7792 (V2H) DPAD 0 DPAD 1 - -
R8A7793 (M2-N) DPAD LVDS 0 - -
R8A7794 (E2) DPAD 0 DPAD 1 - -
R8A7795 (H3) DPAD HDMI 0 HDMI 1 LVDS
+ R8A7796 (M3-W) DPAD HDMI LVDS -
Example: R8A7790 (R-Car H2) DU
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b95696d748c7..b82c00449468 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -28,6 +28,8 @@ The TCON acts as a timing controller for RGB, LVDS and TV interfaces.
Required properties:
- compatible: value must be either:
* allwinner,sun5i-a13-tcon
+ * allwinner,sun6i-a31-tcon
+ * allwinner,sun6i-a31s-tcon
* allwinner,sun8i-a33-tcon
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
@@ -50,7 +52,7 @@ Required properties:
second the block connected to the TCON channel 1 (usually the TV
encoder)
-On the A13, there is one more clock required:
+On SoCs other than the A33, there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
DRC
@@ -64,6 +66,8 @@ adaptive backlight control.
Required properties:
- compatible: value must be one of:
+ * allwinner,sun6i-a31-drc
+ * allwinner,sun6i-a31s-drc
* allwinner,sun8i-a33-drc
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
@@ -87,6 +91,7 @@ system.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-backend
+ * allwinner,sun6i-a31-display-backend
* allwinner,sun8i-a33-display-backend
- reg: base address and size of the memory-mapped region.
- clocks: phandles to the clocks feeding the frontend and backend
@@ -117,6 +122,7 @@ deinterlacing and color space conversion.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-frontend
+ * allwinner,sun6i-a31-display-frontend
* allwinner,sun8i-a33-display-frontend
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
@@ -142,6 +148,8 @@ extra node.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-engine
+ * allwinner,sun6i-a31-display-engine
+ * allwinner,sun6i-a31s-display-engine
* allwinner,sun8i-a33-display-engine
- allwinner,pipelines: list of phandle to the display engine
diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
index a83abd79c55c..6fddb4f4f71a 100644
--- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
+++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
@@ -1,7 +1,9 @@
Device-Tree bindings for tilcdc DRM driver
Required properties:
- - compatible: value should be "ti,am33xx-tilcdc".
+ - compatible: value should be one of the following:
+ - "ti,am33xx-tilcdc" for AM335x based boards
+ - "ti,da850-tilcdc" for DA850/AM18x/OMAP-L138 based boards
- interrupts: the interrupt number
- reg: base address and size of the LCDC device
@@ -51,7 +53,7 @@ Optional nodes:
Example:
fb: fb@4830e000 {
- compatible = "ti,am33xx-tilcdc";
+ compatible = "ti,am33xx-tilcdc", "ti,da850-tilcdc";
reg = <0x4830e000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <36>;
diff --git a/Documentation/devicetree/bindings/display/zte,vou.txt b/Documentation/devicetree/bindings/display/zte,vou.txt
new file mode 100644
index 000000000000..740e5bd2e4f7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/zte,vou.txt
@@ -0,0 +1,84 @@
+ZTE VOU Display Controller
+
+This is a display controller found on ZTE ZX296718 SoC. It includes multiple
+Graphic Layer (GL) and Video Layer (VL), two Mixers/Channels, and a few blocks
+handling scaling, color space conversion etc. VOU also integrates the support
+for typical output devices, like HDMI, TV Encoder, VGA, and RGB LCD.
+
+* Master VOU node
+
+It must be the parent node of all the sub-device nodes.
+
+Required properties:
+ - compatible: should be "zte,zx296718-vou"
+ - #address-cells: should be <1>
+ - #size-cells: should be <1>
+ - ranges: list of address translations between VOU and sub-devices
+
+* VOU DPC device
+
+Required properties:
+ - compatible: should be "zte,zx296718-dpc"
+ - reg: Physical base address and length of DPC register regions, one for each
+ entry in 'reg-names'
+ - reg-names: The names of register regions. The following regions are required:
+ "osd"
+ "timing_ctrl"
+ "dtrc"
+ "vou_ctrl"
+ "otfppu"
+ - interrupts: VOU DPC interrupt number to CPU
+ - clocks: A list of phandle + clock-specifier pairs, one for each entry
+ in 'clock-names'
+ - clock-names: A list of clock names. The following clocks are required:
+ "aclk"
+ "ppu_wclk"
+ "main_wclk"
+ "aux_wclk"
+
+* HDMI output device
+
+Required properties:
+ - compatible: should be "zte,zx296718-hdmi"
+ - reg: Physical base address and length of the HDMI device IO region
+ - interrupts : HDMI interrupt number to CPU
+ - clocks: A list of phandle + clock-specifier pairs, one for each entry
+ in 'clock-names'
+ - clock-names: A list of clock names. The following clocks are required:
+ "osc_cec"
+ "osc_clk"
+ "xclk"
+
+Example:
+
+vou: vou@1440000 {
+ compatible = "zte,zx296718-vou";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1440000 0x10000>;
+
+ dpc: dpc@0 {
+ compatible = "zte,zx296718-dpc";
+ reg = <0x0000 0x1000>, <0x1000 0x1000>,
+ <0x5000 0x1000>, <0x6000 0x1000>,
+ <0xa000 0x1000>;
+ reg-names = "osd", "timing_ctrl",
+ "dtrc", "vou_ctrl",
+ "otfppu";
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topcrm VOU_ACLK>, <&topcrm VOU_PPU_WCLK>,
+ <&topcrm VOU_MAIN_WCLK>, <&topcrm VOU_AUX_WCLK>;
+ clock-names = "aclk", "ppu_wclk",
+ "main_wclk", "aux_wclk";
+ };
+
+ hdmi: hdmi@c000 {
+ compatible = "zte,zx296718-hdmi";
+ reg = <0xc000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&topcrm HDMI_OSC_CEC>,
+ <&topcrm HDMI_OSC_CLK>,
+ <&topcrm HDMI_XCLK>;
+ clock-names = "osc_cec", "osc_clk", "xclk";
+ };
+};
diff --git a/Documentation/devicetree/bindings/dma/st_fdma.txt b/Documentation/devicetree/bindings/dma/st_fdma.txt
new file mode 100644
index 000000000000..495d853c569b
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/st_fdma.txt
@@ -0,0 +1,87 @@
+* STMicroelectronics Flexible Direct Memory Access Device Tree bindings
+
+The FDMA is a general-purpose direct memory access controller capable of
+supporting 16 independent DMA channels. It accepts up to 32 DMA requests.
+The FDMA is based on a Slim processor which requires a firmware.
+
+* FDMA Controller
+
+Required properties:
+- compatible : Should be one of
+ - st,stih407-fdma-mpe31-11, "st,slim-rproc";
+ - st,stih407-fdma-mpe31-12, "st,slim-rproc";
+ - st,stih407-fdma-mpe31-13, "st,slim-rproc";
+- reg : Should contain an entry for each name in reg-names
+- reg-names : Must contain "slimcore", "dmem", "peripherals", "imem" entries
+- interrupts : Should contain one interrupt shared by all channels
+- dma-channels : Number of channels supported by the controller
+- #dma-cells : Must be <3>. See DMA client section below
+- clocks : Must contain an entry for each clock
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+
+Example:
+
+ fdma0: dma-controller@8e20000 {
+ compatible = "st,stih407-fdma-mpe31-11", "st,slim-rproc";
+ reg = <0x8e20000 0x8000>,
+ <0x8e30000 0x3000>,
+ <0x8e37000 0x1000>,
+ <0x8e38000 0x8000>;
+ reg-names = "slimcore", "dmem", "peripherals", "imem";
+ clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+ <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+ <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+ <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>;
+ dma-channels = <16>;
+ #dma-cells = <3>;
+ };
+
+* DMA client
+
+Required properties:
+- dmas: Comma separated list of dma channel requests
+- dma-names: Names of the aforementioned requested channels
+
+Each dmas request consists of 4 cells:
+1. A phandle pointing to the FDMA controller
+2. The request line number
+3. A 32bit mask specifying (see include/linux/platform_data/dma-st-fdma.h)
+ -bit 2-0: Holdoff value, dreq will be masked for
+ 0x0: 0-0.5us
+ 0x1: 0.5-1us
+ 0x2: 1-1.5us
+ -bit 17: data swap
+ 0x0: disabled
+ 0x1: enabled
+ -bit 21: Increment Address
+ 0x0: no address increment between transfers
+ 0x1: increment address between transfers
+ -bit 22: 2 STBus Initiator Coprocessor interface
+ 0x0: high priority port
+ 0x1: low priority port
+4. transfers type
+ 0 free running
+ 1 paced
+
+Example:
+
+ sti_uni_player2: sti-uni-player@2 {
+ compatible = "st,sti-uni-player";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ st,syscfg = <&syscfg_core>;
+ clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+ assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+ assigned-clock-parents = <&clk_s_d0_quadfs 2>;
+ assigned-clock-rates = <50000000>;
+ reg = <0x8D82000 0x158>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+ dmas = <&fdma0 4 0 1>;
+ dai-name = "Uni Player #1 (DAC)";
+ dma-names = "tx";
+ st,uniperiph-id = <2>;
+ st,version = <5>;
+ st,mode = "PCM";
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt b/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt
deleted file mode 100644
index c809acb9c71b..000000000000
--- a/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-SEMTECH SX150x GPIO expander bindings
-
-
-Required properties:
-
-- compatible: should be "semtech,sx1506q",
- "semtech,sx1508q",
- "semtech,sx1509q",
- "semtech,sx1502q".
-
-- reg: The I2C slave address for this device.
-
-- interrupt-parent: phandle of the parent interrupt controller.
-
-- interrupts: Interrupt specifier for the controllers interrupt.
-
-- #gpio-cells: Should be 2. The first cell is the GPIO number and the
- second cell is used to specify optional parameters:
- bit 0: polarity (0: normal, 1: inverted)
-
-- gpio-controller: Marks the device as a GPIO controller.
-
-- interrupt-controller: Marks the device as a interrupt controller.
-
-The GPIO expander can optionally be used as an interrupt controller, in
-which case it uses the default two cell specifier as described in
-Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
-
-Example:
-
- i2c_gpio_expander@20{
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- compatible = "semtech,sx1506q";
- reg = <0x20>;
- interrupt-parent = <&gpio_1>;
- interrupts = <16 0>;
-
- gpio-controller;
- interrupt-controller;
- };
diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
index 928ed4f43907..966514744df4 100644
--- a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -3,7 +3,7 @@
Please refer to gpio.txt for generic information regarding GPIO bindings.
Required properties:
- - compatible: "oxsemi,ox810se-gpio"
+ - compatible: "oxsemi,ox810se-gpio" or "oxsemi,ox820-gpio"
- reg: Base address and length for the device.
- interrupts: The port interrupt shared by all pins.
- gpio-controller: Marks the port as GPIO controller.
diff --git a/Documentation/devicetree/bindings/leds/pca963x.txt b/Documentation/devicetree/bindings/leds/pca963x.txt
index dafbe9931c2b..dfbdb123a9bf 100644
--- a/Documentation/devicetree/bindings/leds/pca963x.txt
+++ b/Documentation/devicetree/bindings/leds/pca963x.txt
@@ -7,6 +7,9 @@ Optional properties:
- nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults
to open-drain, newer chips to totem pole)
- nxp,hw-blink : use hardware blinking instead of software blinking
+- nxp,period-scale : In some configurations, the chip blinks faster than expected.
+ This parameter provides a scaling ratio (fixed point, decimal divided
+ by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x.
Each led is represented as a sub-node of the nxp,pca963x device.
diff --git a/Documentation/devicetree/bindings/mfd/lp873x.txt b/Documentation/devicetree/bindings/mfd/lp873x.txt
index 52766c2035f7..ae9cf39bd101 100644
--- a/Documentation/devicetree/bindings/mfd/lp873x.txt
+++ b/Documentation/devicetree/bindings/mfd/lp873x.txt
@@ -7,6 +7,9 @@ Required properties:
- #gpio-cells: Should be two. The first cell is the pin number and
the second cell is used to specify flags.
See ../gpio/gpio.txt for more information.
+ - xxx-in-supply: Phandle to parent supply node of each regulator
+ populated under regulators node. xxx can be
+ buck0, buck1, ldo0 or ldo1.
- regulators: List of child nodes that specify the regulator
initialization data.
Example:
@@ -17,6 +20,11 @@ pmic: lp8733@60 {
gpio-controller;
#gpio-cells = <2>;
+ buck0-in-supply = <&vsys_3v3>;
+ buck1-in-supply = <&vsys_3v3>;
+ ldo0-in-supply = <&vsys_3v3>;
+ ldo1-in-supply = <&vsys_3v3>;
+
regulators {
lp8733_buck0: buck0 {
regulator-name = "lp8733-buck0";
diff --git a/Documentation/devicetree/bindings/mfd/max77620.txt b/Documentation/devicetree/bindings/mfd/max77620.txt
index 2ad44f7e4880..9c16d51cc15b 100644
--- a/Documentation/devicetree/bindings/mfd/max77620.txt
+++ b/Documentation/devicetree/bindings/mfd/max77620.txt
@@ -106,6 +106,18 @@ Here supported time periods by device in microseconds are as follows:
MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds.
MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
+-maxim,power-ok-control: configure map power ok bit
+ 1: Enables POK(Power OK) to control nRST_IO and GPIO1
+ POK function.
+ 0: Disables POK control.
+ if property missing, do not configure MPOK bit.
+ If POK mapping is enabled for GPIO1/nRST_IO then,
+ GPIO1/nRST_IO pins are HIGH only if all rails
+ that have POK control enabled are HIGH.
+ If any of the rails goes down(which are enabled for POK
+ control) then, GPIO1/nRST_IO goes LOW.
+ this property is valid for max20024 only.
+
For DT binding details of different sub modules like GPIO, pincontrol,
regulator, power, please refer respective device-tree binding document
under their respective sub-system directories.
diff --git a/Documentation/devicetree/bindings/mfd/tps65086.txt b/Documentation/devicetree/bindings/mfd/tps65086.txt
index d3705612a846..9cfa886fe99f 100644
--- a/Documentation/devicetree/bindings/mfd/tps65086.txt
+++ b/Documentation/devicetree/bindings/mfd/tps65086.txt
@@ -23,7 +23,7 @@ Required properties:
defined below.
Optional regulator properties:
- - ti,regulator-step-size-25mv : This is applicable for buck[1,2,6], set this
+ - ti,regulator-step-size-25mv : This is applicable for buck[1-6], set this
if the regulator is factory set with a 25mv
step voltage mapping.
- ti,regulator-decay : This is applicable for buck[1-6], set this if
diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
new file mode 100644
index 000000000000..7f95ec400863
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
@@ -0,0 +1,32 @@
+Amlogic SD / eMMC controller for S905/GXBB family SoCs
+
+The MMC 5.1 compliant host controller on Amlogic provides the
+interface for SD, eMMC and SDIO devices.
+
+This file documents the properties in addition to those available in
+the MMC core bindings, documented by mmc.txt.
+
+Required properties:
+- compatible : contains one of:
+ - "amlogic,meson-gx-mmc"
+ - "amlogic,meson-gxbb-mmc"
+ - "amlogic,meson-gxl-mmc"
+ - "amlogic,meson-gxm-mmc"
+- clocks : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
+- clock-names: Should contain the following:
+ "core" - Main peripheral bus clock
+ "clkin0" - Parent clock of internal mux
+ "clkin1" - Other parent clock of internal mux
+ The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
+ clock rate requested by the MMC core.
+
+Example:
+
+ sd_emmc_a: mmc@70000 {
+ compatible = "amlogic,meson-gxbb-mmc";
+ reg = <0x0 0x70000 0x0 0x2000>;
+ interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ pinctrl-0 = <&emmc_pins>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt b/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
index be56d2bd474a..954561d09a8e 100644
--- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
+++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
@@ -7,6 +7,15 @@ Required properties:
- compatible : Should be one of the following
"brcm,bcm2835-sdhci"
"brcm,sdhci-iproc-cygnus"
+ "brcm,sdhci-iproc"
+
+Use brcm2835-sdhci for Rasperry PI.
+
+Use sdhci-iproc-cygnus for Broadcom SDHCI Controllers
+restricted to 32bit host accesses to SDHCI registers.
+
+Use sdhci-iproc for Broadcom SDHCI Controllers that allow standard
+8, 16, 32-bit host access to SDHCI register.
- clocks : The clock feeding the SDHCI controller.
diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
index ff611fa66871..e4ba92aa035e 100644
--- a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
+++ b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
@@ -8,11 +8,14 @@ Required properties:
- compatible: should be "renesas,mmcif-<soctype>", "renesas,sh-mmcif" as a
fallback. Examples with <soctype> are:
+ - "renesas,mmcif-r8a73a4" for the MMCIF found in r8a73a4 SoCs
- "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
+ - "renesas,mmcif-r8a7778" for the MMCIF found in r8a7778 SoCs
- "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
- "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
- "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs
- "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs
+ - "renesas,mmcif-sh73a0" for the MMCIF found in sh73a0 SoCs
- clocks: reference to the functional clock
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
new file mode 100644
index 000000000000..750374fc9d94
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -0,0 +1,30 @@
+* Cadence SD/SDIO/eMMC Host Controller
+
+Required properties:
+- compatible: should be "cdns,sd4hc".
+- reg: offset and length of the register set for the device.
+- interrupts: a single interrupt specifier.
+- clocks: phandle to the input clock.
+
+Optional properties:
+For eMMC configuration, supported speed modes are not indicated by the SDHCI
+Capabilities Register. Instead, the following properties should be specified
+if supported. See mmc.txt for details.
+- mmc-ddr-1_8v
+- mmc-ddr-1_2v
+- mmc-hs200-1_8v
+- mmc-hs200-1_2v
+- mmc-hs400-1_8v
+- mmc-hs400-1_2v
+
+Example:
+ emmc: sdhci@5a000000 {
+ compatible = "cdns,sd4hc";
+ reg = <0x5a000000 0x400>;
+ interrupts = <0 78 4>;
+ clocks = <&clk 4>;
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 485483a63d8c..0576264eab5e 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -17,6 +17,7 @@ Required properties:
"iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
"core" - SDC MMC clock (MCLK) (required)
"bus" - SDCC bus voter clock (optional)
+ "xo" - TCXO clock (optional)
Example:
diff --git a/Documentation/devicetree/bindings/mmc/sdhci.txt b/Documentation/devicetree/bindings/mmc/sdhci.txt
new file mode 100644
index 000000000000..1c95a1a555c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci.txt
@@ -0,0 +1,13 @@
+The properties specific for SD host controllers. For properties shared by MMC
+host controllers refer to the mmc[1] bindings.
+
+ [1] Documentation/devicetree/bindings/mmc/mmc.txt
+
+Optional properties:
+- sdhci-caps-mask: The sdhci capabilities register is incorrect. This 64bit
+ property corresponds to the bits in the sdhci capabilty register. If the bit
+ is on in the mask then the bit is incorrect in the register and should be
+ turned off, before applying sdhci-caps.
+- sdhci-caps: The sdhci capabilities register is incorrect. This 64bit
+ property corresponds to the bits in the sdhci capability register. If the
+ bit is on in the property then the bit should be turned on.
diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
index bfa461aaac99..7fd17c3da116 100644
--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
@@ -59,8 +59,9 @@ Optional properties:
is specified and the ciu clock is specified then we'll try to set the ciu
clock to this at probe time.
-* clock-freq-min-max: Minimum and Maximum clock frequency for card output
+* clock-freq-min-max (DEPRECATED): Minimum and Maximum clock frequency for card output
clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
+ (Use the "max-frequency" instead of "clock-freq-min-max".)
* num-slots: specifies the number of slots supported by the controller.
The number of physical slots actually used could be equal or less than the
@@ -74,11 +75,6 @@ Optional properties:
* card-detect-delay: Delay in milli-seconds before detecting card after card
insert event. The default value is 0.
-* supports-highspeed (DEPRECATED): Enables support for high speed cards (up to 50MHz)
- (use "cap-mmc-highspeed" or "cap-sd-highspeed" instead)
-
-* broken-cd: as documented in mmc core bindings.
-
* vmmc-supply: The phandle to the regulator to use for vmmc. If this is
specified we'll defer probe until we can find this regulator.
diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
index 13df9c2399c3..a1650edfd2b7 100644
--- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
@@ -11,8 +11,8 @@ optional bindings can be used.
Required properties:
- compatible: "renesas,sdhi-shmobile" - a generic sh-mobile SDHI unit
- "renesas,sdhi-sh7372" - SDHI IP on SH7372 SoC
"renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC
+ "renesas,sdhi-r7s72100" - SDHI IP on R7S72100 SoC
"renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC
"renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC
"renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
diff --git a/Documentation/devicetree/bindings/net/brcm,amac.txt b/Documentation/devicetree/bindings/net/brcm,amac.txt
index ba5ecc1041a5..2fefa1a44afd 100644
--- a/Documentation/devicetree/bindings/net/brcm,amac.txt
+++ b/Documentation/devicetree/bindings/net/brcm,amac.txt
@@ -2,11 +2,17 @@ Broadcom AMAC Ethernet Controller Device Tree Bindings
-------------------------------------------------------------
Required properties:
- - compatible: "brcm,amac" or "brcm,nsp-amac"
- - reg: Address and length of the GMAC registers,
- Address and length of the GMAC IDM registers
- - reg-names: Names of the registers. Must have both "amac_base" and
- "idm_base"
+ - compatible: "brcm,amac"
+ "brcm,nsp-amac"
+ "brcm,ns2-amac"
+ - reg: Address and length of the register set for the device. It
+ contains the information of registers in the same order as
+ described by reg-names
+ - reg-names: Names of the registers.
+ "amac_base": Address and length of the GMAC registers
+ "idm_base": Address and length of the GMAC IDM registers
+ "nicpm_base": Address and length of the NIC Port Manager
+ registers (required for Northstar2)
- interrupts: Interrupt number
Optional properties:
diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt
index 8d40ab27bc8c..06bb7cc334c8 100644
--- a/Documentation/devicetree/bindings/net/can/rcar_can.txt
+++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt
@@ -10,6 +10,7 @@ Required properties:
"renesas,can-r8a7793" if CAN controller is a part of R8A7793 SoC.
"renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC.
"renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
+ "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
"renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-can" for a generic R-Car Gen2 compatible device.
"renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device.
@@ -24,11 +25,12 @@ Required properties:
- pinctrl-0: pin control group to be used for this controller.
- pinctrl-names: must be "default".
-Required properties for "renesas,can-r8a7795" compatible:
-In R8A7795 SoC, "clkp2" can be CANFD clock. This is a div6 clock and can be
-used by both CAN and CAN FD controller at the same time. It needs to be scaled
-to maximum frequency if any of these controllers use it. This is done using
-the below properties.
+Required properties for "renesas,can-r8a7795" and "renesas,can-r8a7796"
+compatible:
+In R8A7795 and R8A7796 SoCs, "clkp2" can be CANFD clock. This is a div6 clock
+and can be used by both CAN and CAN FD controller at the same time. It needs to
+be scaled to maximum frequency if any of these controllers use it. This is done
+using the below properties:
- assigned-clocks: phandle of clkp2(CANFD) clock.
- assigned-clock-rates: maximum frequency of this clock.
diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
index 22a6f10bab05..93c3a6ae32f9 100644
--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
+++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
@@ -5,13 +5,14 @@ Required properties:
- compatible: Must contain one or more of the following:
- "renesas,rcar-gen3-canfd" for R-Car Gen3 compatible controller.
- "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller.
+ - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3) compatible controller.
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first, followed by the
family-specific and/or generic versions.
- reg: physical base address and size of the R-Car CAN FD register map.
-- interrupts: interrupt specifier for the Global & Channel interrupts
+- interrupts: interrupt specifiers for the Channel & Global interrupts
- clocks: phandles and clock specifiers for 3 clock inputs.
- clock-names: 3 clock input name strings: "fck", "canfd", "can_clk".
- pinctrl-0: pin control group to be used for this controller.
@@ -23,11 +24,12 @@ The name of the child nodes are "channel0" and "channel1" respectively. Each
child node supports the "status" property only, which is used to
enable/disable the respective channel.
-Required properties for "renesas,r8a7795-canfd" compatible:
-In R8A7795 SoC, canfd clock is a div6 clock and can be used by both CAN
-and CAN FD controller at the same time. It needs to be scaled to maximum
-frequency if any of these controllers use it. This is done using the
-below properties.
+Required properties for "renesas,r8a7795-canfd" and "renesas,r8a7796-canfd"
+compatible:
+In R8A7795 and R8A7796 SoCs, canfd clock is a div6 clock and can be used by both
+CAN and CAN FD controller at the same time. It needs to be scaled to maximum
+frequency if any of these controllers use it. This is done using the below
+properties:
- assigned-clocks: phandle of canfd clock.
- assigned-clock-rates: maximum frequency of this clock.
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 5ad439f30135..ebda7c93453a 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -20,8 +20,6 @@ Required properties:
- slaves : Specifies number for slaves
- active_slave : Specifies the slave to use for time stamping,
ethtool and SIOCGMIIPHY
-- cpts_clock_mult : Numerator to convert input clock ticks into nanoseconds
-- cpts_clock_shift : Denominator to convert input clock ticks into nanoseconds
Optional properties:
- ti,hwmods : Must be "cpgmac0"
@@ -35,7 +33,11 @@ Optional properties:
For example in dra72x-evm, pcf gpio has to be
driven low so that cpsw slave 0 and phy data
lines are connected via mux.
-
+- cpts_clock_mult : Numerator to convert input clock ticks into nanoseconds
+- cpts_clock_shift : Denominator to convert input clock ticks into nanoseconds
+ Mult and shift will be calculated basing on CPTS
+ rftclk frequency if both cpts_clock_shift and
+ cpts_clock_mult properties are not provided.
Slave Properties:
Required properties:
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 7629189398aa..b3dd6b40e0de 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -14,22 +14,42 @@ The properties described here are those specific to Marvell devices.
Additional required and optional properties can be found in dsa.txt.
Required properties:
-- compatible : Should be one of "marvell,mv88e6085",
+- compatible : Should be one of "marvell,mv88e6085" or
+ "marvell,mv88e6190"
- reg : Address on the MII bus for the switch.
Optional properties:
- reset-gpios : Should be a gpio specifier for a reset line
-
+- interrupt-parent : Parent interrupt controller
+- interrupts : Interrupt from the switch
+- interrupt-controller : Indicates the switch is itself an interrupt
+ controller. This is used for the PHY interrupts.
+#interrupt-cells = <2> : Controller uses two cells, number and flag
+- mdio : container of PHY and devices on the switches MDIO
+ bus
Example:
mdio {
#address-cells = <1>;
#size-cells = <0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
switch0: switch@0 {
compatible = "marvell,mv88e6085";
reg = <0>;
reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
};
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ switch1phy0: switch1phy0@0 {
+ reg = <0>;
+ interrupt-parent = <&switch0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
};
diff --git a/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt b/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt
index 75d398bb1fbb..063c02da018a 100644
--- a/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt
+++ b/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt
@@ -1,7 +1,12 @@
Hisilicon hix5hd2 gmac controller
Required properties:
-- compatible: should be "hisilicon,hix5hd2-gmac".
+- compatible: should contain one of the following SoC strings:
+ * "hisilicon,hix5hd2-gemac"
+ * "hisilicon,hi3798cv200-gemac"
+ and one of the following version string:
+ * "hisilicon,hisi-gemac-v1"
+ * "hisilicon,hisi-gemac-v2"
- reg: specifies base physical address(s) and size of the device registers.
The first region is the MAC register base and size.
The second region is external interface control register.
@@ -12,6 +17,16 @@ Required properties:
- phy-handle: see ethernet.txt [1].
- mac-address: see ethernet.txt [1].
- clocks: clock phandle and specifier pair.
+- clock-names: contain the clock name "mac_core"(required) and "mac_ifc"(optional).
+- resets: should contain the phandle to the MAC core reset signal(optional),
+ the MAC interface reset signal(optional)
+ and the PHY reset signal(optional).
+- reset-names: contain the reset signal name "mac_core"(optional),
+ "mac_ifc"(optional) and "phy"(optional).
+- hisilicon,phy-reset-delays-us: triplet of delays if PHY reset signal given.
+ The 1st cell is reset pre-delay in micro seconds.
+ The 2nd cell is reset pulse in micro seconds.
+ The 3rd cell is reset post-delay in micro seconds.
- PHY subnode: inherits from phy binding [2]
@@ -20,15 +35,19 @@ Required properties:
Example:
gmac0: ethernet@f9840000 {
- compatible = "hisilicon,hix5hd2-gmac";
+ compatible = "hisilicon,hi3798cv200-gemac", "hisilicon,hisi-gemac-v2";
reg = <0xf9840000 0x1000>,<0xf984300c 0x4>;
interrupts = <0 71 4>;
#address-cells = <1>;
#size-cells = <0>;
- phy-mode = "mii";
+ phy-mode = "rgmii";
phy-handle = <&phy2>;
mac-address = [00 00 00 00 00 00];
- clocks = <&clock HIX5HD2_MAC0_CLK>;
+ clocks = <&crg HISTB_ETH0_MAC_CLK>, <&crg HISTB_ETH0_MACIF_CLK>;
+ clock-names = "mac_core", "mac_ifc";
+ resets = <&crg 0xcc 8>, <&crg 0xcc 10>, <&crg 0xcc 12>;
+ reset-names = "mac_core", "mac_ifc", "phy";
+ hisilicon,phy-reset-delays-us = <10000 10000 30000>;
phy2: ethernet-phy@2 {
reg = <2>;
diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
index d4b7f2e49984..abfbeecbcf39 100644
--- a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
+++ b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
@@ -45,6 +45,12 @@ Required properties:
depends on the hardware user manual.
- port-mode-offset: is offset of port mode field for each port in dsaf. Its
value depends on the hardware user manual.
+- mc-mac-mask: mask of multicast address, determines bit in multicast address
+ to set:
+ 1 stands for this bit will be precisely matched, TCAM will check this bit of
+ MAC address.
+ 0 stands for this bit will be fuzzy matched, TCAM won't care about this bit
+ of MAC address.
[1] Documentation/devicetree/bindings/net/phy.txt
@@ -74,10 +80,12 @@ dsaf0: dsa@c7000000 {
reg = 0;
phy-handle = <&phy0>;
serdes-syscon = <&serdes>;
+ mc-mac-mask = [ff f0 00 00 00 00];
};
port@1 {
reg = 1;
serdes-syscon = <&serdes>;
+ mc-mac-mask = [ff f0 00 00 00 00];
};
};
diff --git a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
index 73be8970815e..7aa840c8768d 100644
--- a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
+++ b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
@@ -1,7 +1,10 @@
-* Marvell Armada 370 / Armada XP Ethernet Controller (NETA)
+* Marvell Armada 370 / Armada XP / Armada 3700 Ethernet Controller (NETA)
Required properties:
-- compatible: "marvell,armada-370-neta" or "marvell,armada-xp-neta".
+- compatible: could be one of the followings
+ "marvell,armada-370-neta"
+ "marvell,armada-xp-neta"
+ "marvell,armada-3700-neta"
- reg: address and length of the register set for the device.
- interrupts: interrupt for the device
- phy: See ethernet.txt file in the same directory.
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
index 8516929c7251..065e8bdb957d 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
+++ b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
@@ -3,7 +3,7 @@ Properties for an MDIO bus multiplexer controlled by a memory-mapped device
This is a special case of a MDIO bus multiplexer. A memory-mapped device,
like an FPGA, is used to control which child bus is connected. The mdio-mux
node must be a child of the memory-mapped device. The driver currently only
-supports devices with eight-bit registers.
+supports devices with 8, 16 or 32-bit registers.
Required properties in addition to the generic multiplexer properties:
@@ -11,7 +11,7 @@ Required properties in addition to the generic multiplexer properties:
- reg : integer, contains the offset of the register that controls the bus
multiplexer. The size field in the 'reg' property is the size of
- register, and must therefore be 1.
+ register, and must therefore be 1, 2, or 4.
- mux-mask : integer, contains an eight-bit mask that specifies which
bits in the register control the actual bus multiplexer. The
diff --git a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
index 99c7eb0a00c8..bdefefc66594 100644
--- a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
+++ b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
@@ -6,22 +6,27 @@ Required properties:
Documentation/devicetree/bindings/net/phy.txt
Optional properties:
-- vsc8531,vddmac : The vddmac in mV.
+- vsc8531,vddmac : The vddmac in mV. Allowed values is listed
+ in the first row of Table 1 (below).
+ This property is only used in combination
+ with the 'edge-slowdown' property.
+ Default value is 3300.
- vsc8531,edge-slowdown : % the edge should be slowed down relative to
- the fastest possible edge time. Native sign
- need not enter.
+ the fastest possible edge time.
Edge rate sets the drive strength of the MAC
- interface output signals. Changing the drive
- strength will affect the edge rate of the output
- signal. The goal of this setting is to help
- reduce electrical emission (EMI) by being able
- to reprogram drive strength and in effect slow
- down the edge rate if desired. Table 1 shows the
- impact to the edge rate per VDDMAC supply for each
- drive strength setting.
- Ref: Table:1 - Edge rate change below.
-
-Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values
+ interface output signals. Changing the
+ drive strength will affect the edge rate of
+ the output signal. The goal of this setting
+ is to help reduce electrical emission (EMI)
+ by being able to reprogram drive strength
+ and in effect slow down the edge rate if
+ desired.
+ To adjust the edge-slowdown, the 'vddmac'
+ must be specified. Table 1 lists the
+ supported edge-slowdown values for a given
+ 'vddmac'.
+ Default value is 0%.
+ Ref: Table:1 - Edge rate change (below).
Table: 1 - Edge rate change
----------------------------------------------------------------|
@@ -29,23 +34,23 @@ Table: 1 - Edge rate change
| |
| 3300 mV 2500 mV 1800 mV 1500 mV |
|---------------------------------------------------------------|
-| Default Deafult Default Default |
+| 0% 0% 0% 0% |
| (Fastest) (recommended) (recommended) |
|---------------------------------------------------------------|
-| -2% -3% -5% -6% |
+| 2% 3% 5% 6% |
|---------------------------------------------------------------|
-| -4% -6% -9% -14% |
+| 4% 6% 9% 14% |
|---------------------------------------------------------------|
-| -7% -10% -16% -21% |
+| 7% 10% 16% 21% |
|(recommended) (recommended) |
|---------------------------------------------------------------|
-| -10% -14% -23% -29% |
+| 10% 14% 23% 29% |
|---------------------------------------------------------------|
-| -17% -23% -35% -42% |
+| 17% 23% 35% 42% |
|---------------------------------------------------------------|
-| -29% -37% -52% -58% |
+| 29% 37% 52% 58% |
|---------------------------------------------------------------|
-| -53% -63% -76% -77% |
+| 53% 63% 76% 77% |
| (slowest) |
|---------------------------------------------------------------|
@@ -54,5 +59,5 @@ Example:
vsc8531_0: ethernet-phy@0 {
compatible = "ethernet-phy-id0007.0570";
vsc8531,vddmac = <3300>;
- vsc8531,edge-slowdown = <21>;
+ vsc8531,edge-slowdown = <7>;
};
diff --git a/Documentation/devicetree/bindings/net/oxnas-dwmac.txt b/Documentation/devicetree/bindings/net/oxnas-dwmac.txt
new file mode 100644
index 000000000000..df0534e2eda1
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/oxnas-dwmac.txt
@@ -0,0 +1,39 @@
+* Oxford Semiconductor OXNAS DWMAC Ethernet controller
+
+The device inherits all the properties of the dwmac/stmmac devices
+described in the file stmmac.txt in the current directory with the
+following changes.
+
+Required properties on all platforms:
+
+- compatible: For the OX820 SoC, it should be :
+ - "oxsemi,ox820-dwmac" to select glue
+ - "snps,dwmac-3.512" to select IP version.
+
+- clocks: Should contain phandles to the following clocks
+- clock-names: Should contain the following:
+ - "stmmaceth" for the host clock - see stmmac.txt
+ - "gmac" for the peripheral gate clock
+
+- oxsemi,sys-ctrl: a phandle to the system controller syscon node
+
+Example :
+
+etha: ethernet@40400000 {
+ compatible = "oxsemi,ox820-dwmac", "snps,dwmac-3.512";
+ reg = <0x40400000 0x2000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ mac-address = [000000000000]; /* Filled in by U-Boot */
+ phy-mode = "rgmii";
+
+ clocks = <&stdclk CLK_820_ETHA>, <&gmacclk>;
+ clock-names = "gmac", "stmmaceth";
+ resets = <&reset RESET_MAC>;
+
+ /* Regmap for sys registers */
+ oxsemi,sys-ctrl = <&sys>;
+
+ status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index bc1c3c8bf8fa..54749b60a466 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -35,6 +35,12 @@ Optional Properties:
- broken-turn-around: If set, indicates the PHY device does not correctly
release the turn around line low at the end of a MDIO transaction.
+- enet-phy-lane-swap: If set, indicates the PHY will swap the TX/RX lanes to
+ compensate for the board being designed with the lanes swapped.
+
+- eee-broken-modes: Bits to clear in the MDIO_AN_EEE_ADV register to
+ disable EEE broken modes.
+
Example:
ethernet-phy@0 {
diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
index e77e167593db..309e37eb7c7c 100644
--- a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
+++ b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
@@ -13,3 +13,5 @@ Optional properties:
16-bit access only.
- power-gpios: GPIO to control the PWRDWN pin
- reset-gpios: GPIO to control the RESET pin
+- pxa-u16-align4 : Boolean, put in place the workaround the force all
+ u16 writes to be 32 bits aligned
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index 41b49e6075f5..128da752fec9 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -1,7 +1,7 @@
* STMicroelectronics 10/100/1000 Ethernet driver (GMAC)
Required properties:
-- compatible: Should be "snps,dwmac-<ip_version>" "snps,dwmac"
+- compatible: Should be "snps,dwmac-<ip_version>", "snps,dwmac"
For backwards compatibility: "st,spear600-gmac" is also supported.
- reg: Address and length of the register set for the device
- interrupt-parent: Should be the phandle for the interrupt controller
@@ -34,7 +34,13 @@ Optional properties:
platforms.
- tx-fifo-depth: See ethernet.txt file in the same directory
- rx-fifo-depth: See ethernet.txt file in the same directory
-- snps,pbl Programmable Burst Length
+- snps,pbl Programmable Burst Length (tx and rx)
+- snps,txpbl Tx Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA tx will use this value rather than snps,pbl.
+- snps,rxpbl Rx Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA rx will use this value rather than snps,pbl.
+- snps,no-pbl-x8 Don't multiply the pbl/txpbl/rxpbl values by 8.
+ For core rev < 3.50, don't multiply the values by 4.
- snps,aal Address-Aligned Beats
- snps,fixed-burst Program the DMA to use the fixed burst mode
- snps,mixed-burst Program the DMA to use the mixed burst mode
@@ -50,6 +56,8 @@ Optional properties:
- snps,ps-speed: port selection speed that can be passed to the core when
PCS is supported. For example, this is used in case of SGMII
and MAC2MAC connection.
+- snps,tso: this enables the TSO feature otherwise it will be managed by
+ MAC HW capability register. Only for GMAC4 and newer.
- AXI BUS Mode parameters: below the list of all the parameters to program the
AXI register inside the DMA module:
- snps,lpi_en: enable Low Power Interface
@@ -62,8 +70,6 @@ Optional properties:
- snps,fb: fixed-burst
- snps,mb: mixed-burst
- snps,rb: rebuild INCRx Burst
- - snps,tso: this enables the TSO feature otherwise it will be managed by
- MAC HW capability register.
- mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
Examples:
diff --git a/Documentation/devicetree/bindings/net/ti,dp83867.txt b/Documentation/devicetree/bindings/net/ti,dp83867.txt
index 5d21141a68b5..85bf945b898f 100644
--- a/Documentation/devicetree/bindings/net/ti,dp83867.txt
+++ b/Documentation/devicetree/bindings/net/ti,dp83867.txt
@@ -9,6 +9,18 @@ Required properties:
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
for applicable values
+Optional property:
+ - ti,min-output-impedance - MAC Interface Impedance control to set
+ the programmable output impedance to
+ minimum value (35 ohms).
+ - ti,max-output-impedance - MAC Interface Impedance control to set
+ the programmable output impedance to
+ maximum value (70 ohms).
+
+Note: ti,min-output-impedance and ti,max-output-impedance are mutually
+ exclusive. When both properties are present ti,max-output-impedance
+ takes precedence.
+
Default child nodes are standard Ethernet PHY device
nodes as described in Documentation/devicetree/bindings/net/phy.txt
diff --git a/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
index c421aba0a5bc..980b16df74c3 100644
--- a/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt
+++ b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
@@ -1,8 +1,8 @@
-Marvell 8897/8997 (sd8897/sd8997) SDIO devices
+Marvell 8897/8997 (sd8897/sd8997/pcie8997) SDIO/PCIE devices
------
-This node provides properties for controlling the marvell sdio wireless device.
-The node is expected to be specified as a child node to the SDIO controller that
+This node provides properties for controlling the Marvell SDIO/PCIE wireless device.
+The node is expected to be specified as a child node to the SDIO/PCIE controller that
connects the device to the system.
Required properties:
@@ -10,6 +10,8 @@ Required properties:
- compatible : should be one of the following:
* "marvell,sd8897"
* "marvell,sd8997"
+ * "pci11ab,2b42"
+ * "pci1b4b,2b42"
Optional properties:
diff --git a/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
new file mode 100644
index 000000000000..b7396c8c271c
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
@@ -0,0 +1,48 @@
+* Qualcomm Atheros ath9k wireless devices
+
+This node provides properties for configuring the ath9k wireless device. The
+node is expected to be specified as a child node of the PCI controller to
+which the wireless chip is connected.
+
+Required properties:
+- compatible: For PCI and PCIe devices this should be an identifier following
+ the format as defined in "PCI Bus Binding to Open Firmware"
+ Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
+ where VVVV is the PCI vendor ID and DDDD is PCI device ID.
+ Typically QCA's PCI vendor ID 168c is used while the PCI device
+ ID depends on the chipset - see the following (possibly
+ incomplete) list:
+ - 0023 for AR5416
+ - 0024 for AR5418
+ - 0027 for AR9160
+ - 0029 for AR9220 and AR9223
+ - 002a for AR9280 and AR9283
+ - 002b for AR9285
+ - 002c for AR2427
+ - 002d for AR9227
+ - 002e for AR9287
+ - 0030 for AR9380, AR9381 and AR9382
+ - 0032 for AR9485
+ - 0033 for AR9580 and AR9590
+ - 0034 for AR9462
+ - 0036 for AR9565
+ - 0037 for AR9485
+- reg: Address and length of the register set for the device.
+
+Optional properties:
+- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
+ ath9k wireless chip (in this case the calibration /
+ EEPROM data will be loaded from userspace using the
+ kernel firmware loader).
+- mac-address: See ethernet.txt in the parent directory
+- local-mac-address: See ethernet.txt in the parent directory
+
+
+In this example, the node is defined as child node of the PCI controller:
+&pci0 {
+ wifi@168c,002d {
+ compatible = "pci168c,002d";
+ reg = <0x7000 0 0 0 0x1000>;
+ qca,no-eeprom;
+ };
+};
diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
index ee91cbdd95ee..9f5ca4457b5f 100644
--- a/Documentation/devicetree/bindings/opp/opp.txt
+++ b/Documentation/devicetree/bindings/opp/opp.txt
@@ -86,8 +86,14 @@ Optional properties:
Single entry is for target voltage and three entries are for <target min max>
voltages.
- Entries for multiple regulators must be present in the same order as
- regulators are specified in device's DT node.
+ Entries for multiple regulators shall be provided in the same field separated
+ by angular brackets <>. The OPP binding doesn't provide any provisions to
+ relate the values to their power supplies or the order in which the supplies
+ need to be configured and that is left for the implementation specific
+ binding.
+
+ Entries for all regulators shall be of the same size, i.e. either all use a
+ single value or triplets.
- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
the above opp-microvolt property, but allows multiple voltage ranges to be
@@ -104,10 +110,13 @@ Optional properties:
Should only be set if opp-microvolt is set for the OPP.
- Entries for multiple regulators must be present in the same order as
- regulators are specified in device's DT node. If this property isn't required
- for few regulators, then this should be marked as zero for them. If it isn't
- required for any regulator, then this property need not be present.
+ Entries for multiple regulators shall be provided in the same field separated
+ by angular brackets <>. If current values aren't required for a regulator,
+ then it shall be filled with 0. If current values aren't required for any of
+ the regulators, then this field is not required. The OPP binding doesn't
+ provide any provisions to relate the values to their power supplies or the
+ order in which the supplies need to be configured and that is left for the
+ implementation specific binding.
- opp-microamp-<name>: Named opp-microamp property. Similar to
opp-microvolt-<name> property, but for microamp instead.
@@ -386,10 +395,12 @@ Example 4: Handling multiple regulators
/ {
cpus {
cpu@0 {
- compatible = "arm,cortex-a7";
+ compatible = "vendor,cpu-type";
...
- cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
+ vcc0-supply = <&cpu_supply0>;
+ vcc1-supply = <&cpu_supply1>;
+ vcc2-supply = <&cpu_supply2>;
operating-points-v2 = <&cpu0_opp_table>;
};
};
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index 1685821eea41..de1378b4efad 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -28,6 +28,20 @@ Required properties:
- reg: Should contain the register physical address and length for the
pin controller.
+- clocks: phandle to the clocks feeding the pin controller:
+ - "apb": the gated APB parent clock
+ - "hosc": the high frequency oscillator in the system
+ - "losc": the low frequency oscillator in the system
+
+Note: For backward compatibility reasons, the hosc and losc clocks are only
+required if you need to use the optional input-debounce property. Any new
+device tree should set them.
+
+Optional properties:
+ - input-debounce: Array of debouncing periods in microseconds. One period per
+ irq bank found in the controller. 0 if no setup required.
+
+
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices.
@@ -37,6 +51,22 @@ pins it needs, and how they should be configured, with regard to muxer
configuration, drive strength and pullups. If one of these options is
not set, its actual value will be unspecified.
+This driver supports the generic pin multiplexing and configuration
+bindings. For details on each properties, you can refer to
+./pinctrl-bindings.txt.
+
+Required sub-node properties:
+ - pins
+ - function
+
+Optional sub-node properties:
+ - bias-disable
+ - bias-pull-up
+ - bias-pull-down
+ - drive-strength
+
+*** Deprecated pin configuration and multiplexing binding
+
Required subnode-properties:
- allwinner,pins: List of strings containing the pin name.
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
index b7a93e80a302..9a8a45d9d8ab 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -98,6 +98,8 @@ DRIVE_STRENGTH (3 << 5): indicate the drive strength of the pin using the
01 - Low
10 - Medium
11 - High
+OUTPUT (1 << 7): indicate this pin need to be configured as an output.
+OUTPUT_VAL (1 << 8): output val (1 = high, 0 = low)
DEBOUNCE (1 << 16): indicate this pin needs debounce.
DEBOUNCE_VAL (0x3fff << 17): debounce value.
diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
index fe7fe0b03cfb..2392557ede27 100644
--- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
@@ -7,6 +7,8 @@ Required properties for the root node:
"amlogic,meson8b-aobus-pinctrl"
"amlogic,meson-gxbb-periphs-pinctrl"
"amlogic,meson-gxbb-aobus-pinctrl"
+ "amlogic,meson-gxl-periphs-pinctrl"
+ "amlogic,meson-gxl-aobus-pinctrl"
- reg: address and size of registers controlling irq functionality
=== GPIO sub-nodes ===
diff --git a/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
index d6074321f730..09e81a95bbfd 100644
--- a/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
@@ -9,7 +9,7 @@ used for a specific device or function. This node represents configurations of
pins, optional function, and optional mux related configuration.
Required properties for pin controller node:
- - compatible: "oxsemi,ox810se-pinctrl"
+ - compatible: "oxsemi,ox810se-pinctrl" or "oxsemi,ox820-pinctrl"
- oxsemi,sys-ctrl: a phandle to the system controller syscon node
Required properties for pin configuration sub-nodes:
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
index b73c96d24f59..bf3f7b014724 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -97,6 +97,11 @@ For example:
};
== Pin controller devices ==
+Required properties: See the pin controller driver specific documentation
+
+Optional properties:
+#pinctrl-cells: Number of pin control cells in addition to the index within the
+ pin controller device instance
Pin controller devices should contain the pin configuration nodes that client
devices reference.
@@ -119,7 +124,8 @@ For example:
The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
-exists no common standard for this content.
+exists no common standard for this content. The pinctrl framework only
+provides generic helper bindings that the pin controller driver can use.
The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
@@ -156,6 +162,42 @@ state_2_node_a {
pins = "mfio29", "mfio30";
};
+Optionally an altenative binding can be used if more suitable depending on the
+pin controller hardware. For hardaware where there is a large number of identical
+pin controller instances, naming each pin and function can easily become
+unmaintainable. This is especially the case if the same controller is used for
+different pins and functions depending on the SoC revision and packaging.
+
+For cases like this, the pin controller driver may use pinctrl-pin-array helper
+binding with a hardware based index and a number of pin configuration values:
+
+pincontroller {
+ ... /* Standard DT properties for the device itself elided */
+ #pinctrl-cells = <2>;
+
+ state_0_node_a {
+ pinctrl-pin-array = <
+ 0 A_DELAY_PS(0) G_DELAY_PS(120)
+ 4 A_DELAY_PS(0) G_DELAY_PS(360)
+ ...
+ >;
+ };
+ ...
+};
+
+Above #pinctrl-cells specifies the number of value cells in addition to the
+index of the registers. This is similar to the interrupts-extended binding with
+one exception. There is no need to specify the phandle for each entry as that
+is already known as the defined pins are always children of the pin controller
+node. Further having the phandle pointing to another pin controller would not
+currently work as the pinctrl framework uses named modes to group pins for each
+pin control device.
+
+The index for pinctrl-pin-array must relate to the hardware for the pinctrl
+registers, and must not be a virtual index of pin instances. The reason for
+this is to avoid mapping of the index in the dts files and the pin controller
+driver as it can change.
+
== Generic pin configuration node content ==
Many data items that are represented in a pin configuration node are common
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
index caf297bee1fb..c28d4eb83b76 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
@@ -35,6 +35,15 @@ Optional properties:
- ti,palmas-enable-dvfs2: Enable DVFS2. Configure pins for DVFS2 mode.
Selection primary or secondary function associated to GPADC_START
and SYSEN2 pin/pad for DVFS2 interface
+- ti,palmas-override-powerhold: This is applicable for PMICs for which
+ GPIO7 is configured in POWERHOLD mode which has higher priority
+ over DEV_ON bit and keeps the PMIC supplies on even after the DEV_ON
+ bit is turned off. This property enables driver to over ride the
+ POWERHOLD value to GPIO7 so as to turn off the PMIC in power off
+ scenarios. So for GPIO7 if ti,palmas-override-powerhold is set
+ then the GPIO_7 field should never be muxed to anything else.
+ It should be set to POWERHOLD by default and only in case of
+ power off scenarios the driver will over ride the mux value.
This binding uses the following generic properties as defined in
pinctrl-bindings.txt:
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt
new file mode 100644
index 000000000000..bf76867168e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt
@@ -0,0 +1,74 @@
+SEMTECH SX150x GPIO expander bindings
+
+Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
+../interrupt-controller/interrupts.txt for generic information regarding
+pin controller, GPIO, and interrupt bindings.
+
+Required properties:
+- compatible: should be one of :
+ "semtech,sx1501q",
+ "semtech,sx1502q",
+ "semtech,sx1503q",
+ "semtech,sx1504q",
+ "semtech,sx1505q",
+ "semtech,sx1506q",
+ "semtech,sx1507q",
+ "semtech,sx1508q",
+ "semtech,sx1509q".
+
+- reg: The I2C slave address for this device.
+
+- #gpio-cells: Should be 2. The first cell is the GPIO number and the
+ second cell is used to specify optional parameters:
+ bit 0: polarity (0: normal, 1: inverted)
+
+- gpio-controller: Marks the device as a GPIO controller.
+
+Optional properties :
+- interrupt-parent: phandle of the parent interrupt controller.
+
+- interrupts: Interrupt specifier for the controllers interrupt.
+
+- interrupt-controller: Marks the device as a interrupt controller.
+
+- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe,
+ only for sx1507q, sx1508q and sx1509q
+
+The GPIO expander can optionally be used as an interrupt controller, in
+which case it uses the default two cell specifier.
+
+Required properties for pin configuration sub-nodes:
+ - pins: List of pins to which the configuration applies.
+
+Optional properties for pin configuration sub-nodes:
+----------------------------------------------------
+ - bias-disable: disable any pin bias, except the OSCIO pin
+ - bias-pull-up: pull up the pin, except the OSCIO pin
+ - bias-pull-down: pull down the pin, except the OSCIO pin
+ - bias-pull-pin-default: use pin-default pull state, except the OSCIO pin
+ - drive-push-pull: drive actively high and low
+ - drive-open-drain: drive with open drain only for sx1507q, sx1508q and sx1509q and except the OSCIO pin
+ - output-low: set the pin to output mode with low level
+ - output-high: set the pin to output mode with high level
+
+Example:
+
+ i2c0gpio-expander@20{
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ compatible = "semtech,sx1506q";
+ reg = <0x20>;
+ interrupt-parent = <&gpio_1>;
+ interrupts = <16 0>;
+
+ gpio-controller;
+ interrupt-controller;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio1_cfg_pins>;
+
+ gpio1_cfg_pins: gpio1-cfg {
+ pins = "gpio1";
+ bias-pull-up;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
new file mode 100644
index 000000000000..13cd629f896e
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
@@ -0,0 +1,177 @@
+Qualcomm MSM8994 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8994 platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should contain one of:
+ "qcom,msm8992-pinctrl",
+ "qcom,msm8994-pinctrl".
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+ Usage: required
+ Value type: <string-array>
+ Definition: List of gpio pins affected by the properties specified in
+ this subnode.
+
+ Valid pins are:
+ gpio0-gpio145
+ Supports mux, bias and drive-strength
+
+ sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
+ sdc2_cmd, sdc2_data
+ Supports bias and drive-strength
+
+- function:
+ Usage: required
+ Value type: <string>
+ Definition: Specify the alternative function to be configured for the
+ specified pins. Functions are only valid for gpio pins.
+ Valid values are:
+
+ audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
+ blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
+ blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
+ blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
+ blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
+ blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
+ blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
+ blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
+ blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
+ blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
+ blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
+ blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
+ cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
+ cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
+ gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a,
+ gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
+ gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv,
+ mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a,
+ qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d,
+ qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c,
+ qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
+ qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0,
+ pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1,
+ tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio
+
+- bias-disable:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull up.
+
+- output-high:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ high.
+ Not valid for sdc pins.
+
+- output-low:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ low.
+ Not valid for sdc pins.
+
+- drive-strength:
+ Usage: optional
+ Value type: <u32>
+ Definition: Selects the drive strength for the specified pins, in mA.
+ Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+ msmgpio: pinctrl@fd510000 {
+ compatible = "qcom,msm8994-pinctrl";
+ reg = <0xfd510000 0x4000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1_uart2_default: blsp1_uart2_default {
+ pinmux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+ pinconf {
+ pins = "gpio4", "gpio5";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
index c68b9554561f..4722bc61a1a2 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -19,10 +19,11 @@ The pins are grouped into up to 5 individual pin banks which need to be
defined as gpio sub-nodes of the pinmux controller.
Required properties for iomux controller:
- - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
- "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
- "rockchip,rk3228-pinctrl", "rockchip,rk3288-pinctrl"
- "rockchip,rk3368-pinctrl", "rockchip,rk3399-pinctrl"
+ - compatible: one of "rockchip,rk1108-pinctrl", "rockchip,rk2928-pinctrl"
+ "rockchip,rk3066a-pinctrl", "rockchip,rk3066b-pinctrl"
+ "rockchip,rk3188-pinctrl", "rockchip,rk3228-pinctrl"
+ "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
+ "rockchip,rk3399-pinctrl"
- rockchip,grf: phandle referencing a syscon providing the
"general register files"
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index d49e22d2a8b5..1baf19eecabf 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -19,11 +19,30 @@ Required Properties:
- "samsung,exynos5260-pinctrl": for Exynos5260 compatible pin-controller.
- "samsung,exynos5410-pinctrl": for Exynos5410 compatible pin-controller.
- "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller.
+ - "samsung,exynos5433-pinctrl": for Exynos5433 compatible pin-controller.
- "samsung,exynos7-pinctrl": for Exynos7 compatible pin-controller.
- reg: Base address of the pin controller hardware module and length of
the address space it occupies.
+ - reg: Second base address of the pin controller if the specific registers
+ of the pin controller are separated into the different base address.
+
+ Eg: GPF[1-5] of Exynos5433 are separated into the two base address.
+ - First base address is for GPAx and GPF[1-5] external interrupt
+ registers.
+ - Second base address is for GPF[1-5] pinctrl registers.
+
+ pinctrl_0: pinctrl@10580000 {
+ compatible = "samsung,exynos5433-pinctrl";
+ reg = <0x10580000 0x1a20>, <0x11090000 0x100>;
+
+ wakeup-interrupt-controller {
+ compatible = "samsung,exynos7-wakeup-eint";
+ interrupts = <0 16 0>;
+ };
+ };
+
- Pin banks as child nodes: Pin banks of the controller are represented by child
nodes of the controller node. Bank name is taken from name of the node. Each
bank node must contain following properties:
diff --git a/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt b/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt
new file mode 100644
index 000000000000..7f2980567c9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt
@@ -0,0 +1,55 @@
+* Pin configuration for TI DA850/OMAP-L138/AM18x
+
+These SoCs have a separate controller for setting bias (internal pullup/down).
+Bias can only be selected for groups rather than individual pins.
+
+Required Properties:
+
+ - compatible: Must be "ti,da850-pupd"
+ - reg: Base address and length of the memory resource used by the pullup/down
+ controller hardware module.
+
+The controller node also acts as a container for pin group configuration nodes.
+The names of these groups are ignored.
+
+Pin Group Node Properties:
+
+- groups: An array of strings, each string containing the name of a pin group.
+ Valid names are "cp0".."cp31".
+
+The pin configuration parameters use the generic pinconf bindings defined in
+pinctrl-bindings.txt in this directory. The supported parameters are
+bias-disable, bias-pull-up, bias-pull-down.
+
+
+Example
+-------
+
+In common dtsi file:
+
+ pinconf: pin-controller@22c00c {
+ compatible = "ti,da850-pupd";
+ reg = <0x22c00c 0x8>;
+ };
+
+In board-specific file:
+
+ &pinconf {
+ pinctrl-0 = <&pinconf_bias_groups>;
+ pinctrl-names = "default";
+
+ pinconf_bias_groups: bias-groups {
+ pull-up {
+ groups = "cp30", "cp31";
+ bias-pull-up;
+ };
+ pull-down {
+ groups = "cp29", "cp28";
+ bias-pull-down;
+ };
+ disable {
+ groups = "cp27", "cp26";
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.txt b/Documentation/devicetree/bindings/power/domain-idle-state.txt
new file mode 100644
index 000000000000..eefc7ed22ca2
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/domain-idle-state.txt
@@ -0,0 +1,33 @@
+PM Domain Idle State Node:
+
+A domain idle state node represents the state parameters that will be used to
+select the state when there are no active components in the domain.
+
+The state node has the following parameters -
+
+- compatible:
+ Usage: Required
+ Value type: <string>
+ Definition: Must be "domain-idle-state".
+
+- entry-latency-us
+ Usage: Required
+ Value type: <prop-encoded-array>
+ Definition: u32 value representing worst case latency in
+ microseconds required to enter the idle state.
+ The exit-latency-us duration may be guaranteed
+ only after entry-latency-us has passed.
+
+- exit-latency-us
+ Usage: Required
+ Value type: <prop-encoded-array>
+ Definition: u32 value representing worst case latency
+ in microseconds required to exit the idle state.
+
+- min-residency-us
+ Usage: Required
+ Value type: <prop-encoded-array>
+ Definition: u32 value representing minimum residency duration
+ in microseconds after which the idle state will yield
+ power benefits after overcoming the overhead in entering
+i the idle state.
diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
index 025b5e7df61c..723e1ad937da 100644
--- a/Documentation/devicetree/bindings/power/power_domain.txt
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -29,6 +29,15 @@ Optional properties:
specified by this binding. More details about power domain specifier are
available in the next section.
+- domain-idle-states : A phandle of an idle-state that shall be soaked into a
+ generic domain power state. The idle state definitions are
+ compatible with domain-idle-state specified in [1].
+ The domain-idle-state property reflects the idle state of this PM domain and
+ not the idle states of the devices or sub-domains in the PM domain. Devices
+ and sub-domains have their own idle-states independent of the parent
+ domain's idle states. In the absence of this property, the domain would be
+ considered as capable of being powered-on or powered-off.
+
Example:
power: power-controller@12340000 {
@@ -59,6 +68,38 @@ The nodes above define two power controllers: 'parent' and 'child'.
Domains created by the 'child' power controller are subdomains of '0' power
domain provided by the 'parent' power controller.
+Example 3:
+ parent: power-controller@12340000 {
+ compatible = "foo,power-controller";
+ reg = <0x12340000 0x1000>;
+ #power-domain-cells = <0>;
+ domain-idle-states = <&DOMAIN_RET>, <&DOMAIN_PWR_DN>;
+ };
+
+ child: power-controller@12341000 {
+ compatible = "foo,power-controller";
+ reg = <0x12341000 0x1000>;
+ power-domains = <&parent 0>;
+ #power-domain-cells = <0>;
+ domain-idle-states = <&DOMAIN_PWR_DN>;
+ };
+
+ DOMAIN_RET: state@0 {
+ compatible = "domain-idle-state";
+ reg = <0x0>;
+ entry-latency-us = <1000>;
+ exit-latency-us = <2000>;
+ min-residency-us = <10000>;
+ };
+
+ DOMAIN_PWR_DN: state@1 {
+ compatible = "domain-idle-state";
+ reg = <0x1>;
+ entry-latency-us = <5000>;
+ exit-latency-us = <8000>;
+ min-residency-us = <7000>;
+ };
+
==PM domain consumers==
Required properties:
@@ -76,3 +117,5 @@ Example:
The node above defines a typical PM domain consumer device, which is located
inside a PM domain with index 0 of a power controller represented by a node
with the label "power".
+
+[1]. Documentation/devicetree/bindings/power/domain-idle-state.txt
diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
index 3aeba9f86ed8..bf85aa9ad6a7 100644
--- a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
@@ -59,7 +59,7 @@ Any property defined as part of the core regulator binding can also be used.
Continuous Voltage With Enable GPIO Example:
pwm_regulator {
- compatible = "pwm-regulator;
+ compatible = "pwm-regulator";
pwms = <&pwm1 0 8448 0>;
enable-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
regulator-min-microvolt = <1016000>;
@@ -76,7 +76,7 @@ Continuous Voltage With Enable GPIO Example:
Voltage Table Example:
pwm_regulator {
- compatible = "pwm-regulator;
+ compatible = "pwm-regulator";
pwms = <&pwm1 0 8448 0>;
regulator-min-microvolt = <1016000>;
regulator-max-microvolt = <1114000>;
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
new file mode 100644
index 000000000000..b85885a298d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
@@ -0,0 +1,98 @@
+Qualcomm ADSP Peripheral Image Loader
+
+This document defines the binding for a component that loads and boots firmware
+on the Qualcomm ADSP Hexagon core.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be one of:
+ "qcom,msm8974-adsp-pil"
+ "qcom,msm8996-adsp-pil"
+
+- interrupts-extended:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: must list the watchdog, fatal IRQs ready, handover and
+ stop-ack IRQs
+
+- interrupt-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack"
+
+- clocks:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: reference to the xo clock to be held on behalf of the
+ booting Hexagon core
+
+- clock-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: must be "xo"
+
+- cx-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: reference to the regulator to be held on behalf of the
+ booting Hexagon core
+
+- memory-region:
+ Usage: required
+ Value type: <phandle>
+ Definition: reference to the reserved-memory for the ADSP
+
+- qcom,smem-states:
+ Usage: required
+ Value type: <phandle>
+ Definition: reference to the smem state for requesting the ADSP to
+ shut down
+
+- qcom,smem-state-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: must be "stop"
+
+
+= SUBNODES
+The adsp node may have an subnode named "smd-edge" that describes the SMD edge,
+channels and devices related to the ADSP. See ../soc/qcom/qcom,smd.txt for
+details on how to describe the SMD edge.
+
+
+= EXAMPLE
+The following example describes the resources needed to boot control the
+ADSP, as it is found on MSM8974 boards.
+
+ adsp {
+ compatible = "qcom,msm8974-adsp-pil";
+
+ interrupts-extended = <&intc 0 162 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ clocks = <&rpmcc RPM_CXO_CLK>;
+ clock-names = "xo";
+
+ cx-supply = <&pm8841_s2>;
+
+ memory-region = <&adsp_region>;
+
+ qcom,smem-states = <&adsp_smp2p_out 0>;
+ qcom,smem-state-names = "stop";
+
+ smd-edge {
+ interrupts = <0 156 IRQ_TYPE_EDGE_RISING>;
+
+ qcom,ipc = <&apcs 8 8>;
+ qcom,smd-edge = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
index 0d2361ebe3d7..d420f84ddfb0 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
@@ -60,8 +60,8 @@ on the Qualcomm WCNSS core.
see ../reserved-memory/reserved-memory.txt
= SUBNODES
-A single subnode of the WCNSS PIL describes the attached rf module and its
-resource dependencies.
+A required subnode of the WCNSS PIL is used to describe the attached rf module
+and its resource dependencies. It is described by the following properties:
- compatible:
Usage: required
@@ -90,6 +90,11 @@ resource dependencies.
Definition: reference to the regulators to be held on behalf of the
booting of the WCNSS core
+
+The wcnss node can also have an subnode named "smd-edge" that describes the SMD
+edge, channels and devices related to the WCNSS.
+See ../soc/qcom/qcom,smd.txt for details on how to describe the SMD edge.
+
= EXAMPLE
The following example describes the resources needed to boot control the WCNSS,
with attached WCN3680, as it is commonly found on MSM8974 boards.
@@ -129,4 +134,25 @@ pronto@fb204000 {
vddpa-supply = <&pm8941_l19>;
vdddig-supply = <&pm8941_s3>;
};
+
+ smd-edge {
+ interrupts = <0 142 1>;
+
+ qcom,ipc = <&apcs 8 17>;
+ qcom,smd-edge = <6>;
+ qcom,remote-pid = <4>;
+
+ label = "pronto";
+
+ wcnss {
+ compatible = "qcom,wcnss";
+ qcom,smd-channels = "WCNSS_CTRL";
+
+ qcom,mmio = <&pronto>;
+
+ bt {
+ compatible = "qcom,wcnss-bt";
+ };
+ };
+ };
};
diff --git a/Documentation/devicetree/bindings/reserved-memory/ramoops.txt b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
index e81f821a2135..0eba562fe5c6 100644
--- a/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
@@ -46,3 +46,6 @@ Optional properties:
(defaults to buffered mappings)
- no-dump-oops: if present, only dump panics (defaults to panics and oops)
+
+- flags: if present, pass ramoops behavioral flags (defaults to 0,
+ see include/linux/pstore_ram.h RAMOOPS_FLAG_* for flag values).
diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt
new file mode 100644
index 000000000000..fe5e0f37b3c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/renesas,rst.txt
@@ -0,0 +1,37 @@
+DT bindings for the Renesas R-Car and RZ/G Reset Controllers
+
+The R-Car and RZ/G Reset Controllers provide reset control, and implement the
+following functions:
+ - Latching of the levels on mode pins when PRESET# is negated,
+ - Mode monitoring register,
+ - Reset control of peripheral devices (on R-Car Gen1),
+ - Watchdog timer (on R-Car Gen1),
+ - Register-based reset control and boot address registers for the various CPU
+ cores (on R-Car Gen2 and Gen3, and on RZ/G).
+
+
+Required properties:
+ - compatible: Should be
+ - "renesas,<soctype>-reset-wdt" for R-Car Gen1,
+ - "renesas,<soctype>-rst" for R-Car Gen2 and Gen3, and RZ/G
+ Examples with soctypes are:
+ - "renesas,r8a7743-rst" (RZ/G1M)
+ - "renesas,r8a7745-rst" (RZ/G1E)
+ - "renesas,r8a7778-reset-wdt" (R-Car M1A)
+ - "renesas,r8a7779-reset-wdt" (R-Car H1)
+ - "renesas,r8a7790-rst" (R-Car H2)
+ - "renesas,r8a7791-rst" (R-Car M2-W)
+ - "renesas,r8a7792-rst" (R-Car V2H
+ - "renesas,r8a7793-rst" (R-Car M2-N)
+ - "renesas,r8a7794-rst" (R-Car E2)
+ - "renesas,r8a7795-rst" (R-Car H3)
+ - "renesas,r8a7796-rst" (R-Car M3-W)
+ - reg: Address start and address range for the device.
+
+
+Example:
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7795-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
index ddef330d2709..1ad4c1c2b3b3 100644
--- a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
+++ b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
@@ -1,7 +1,7 @@
* Maxim DS3231 Real Time Clock
Required properties:
-see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
Optional property:
- #clock-cells: Should be 1.
diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt
index 72f6d2c9665e..086c998c5561 100644
--- a/Documentation/devicetree/bindings/rtc/pcf8563.txt
+++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt
@@ -3,7 +3,7 @@
Philips PCF8563/Epson RTC8564 Real Time Clock
Required properties:
-see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
Optional property:
- #clock-cells: Should be 0.
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt
index b71b2039e112..07adca914d3d 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt
@@ -25,6 +25,9 @@ Recommended properties:
- fsl,liodn-bits : Indicates the number of defined bits in the LIODN
registers, for those SOCs that have a PAMU device.
+ - little-endian : Indicates that the global utilities block is little
+ endian. The default is big endian.
+
Examples:
global-utilities@e0000 { /* global utilities block */
compatible = "fsl,mpc8548-guts";
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
index 97d9b3e1bf39..ea1dc75ec9ea 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
@@ -43,6 +43,13 @@ The edge is described by the following properties:
Definition: the identifier for the remote processor as known by the rest
of the system.
+- label:
+ Usage: optional
+ Value type: <string>
+ Definition: name of the edge, used for debugging and identification
+ purposes. The node name will be used if this is not
+ present.
+
= SMD DEVICES
In turn, subnodes of the "edges" represent devices tied to SMD channels on that
diff --git a/Documentation/devicetree/bindings/submitting-patches.txt b/Documentation/devicetree/bindings/submitting-patches.txt
index 7d44eae7ab0b..274058c583dd 100644
--- a/Documentation/devicetree/bindings/submitting-patches.txt
+++ b/Documentation/devicetree/bindings/submitting-patches.txt
@@ -3,7 +3,7 @@
I. For patch submitters
- 0) Normal patch submission rules from Documentation/SubmittingPatches
+ 0) Normal patch submission rules from Documentation/process/submitting-patches.rst
applies.
1) The Documentation/ portion of the patch should be a separate patch.
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
index 08efe6bc2193..43003aec94bd 100644
--- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
@@ -22,10 +22,13 @@ Required properties:
TSADC controller.
- pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+
+Optional properties:
- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
- rockchip,hw-tshut-polarity : The hardware-controlled active polarity 0:LOW
1:HIGH.
+- rockchip,grf : The phandle of the syscon node for the general register file.
Exiample:
tsadc: tsadc@ff280000 {
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index f0a48ea78659..d9c51d7f4aac 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -187,6 +187,7 @@ netgear NETGEAR
netlogic Broadcom Corporation (formerly NetLogic Microsystems)
netxeon Shenzhen Netxeon Technology CO., LTD
newhaven Newhaven Display International
+nvd New Vision Display
nintendo Nintendo
nokia Nokia
nuvoton Nuvoton Technology Corporation
diff --git a/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt b/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt
new file mode 100644
index 000000000000..9409d9c6a260
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt
@@ -0,0 +1,33 @@
+Silicon Image SiI8620 HDMI/MHL bridge bindings
+
+Required properties:
+ - compatible: "sil,sii8620"
+ - reg: i2c address of the bridge
+ - cvcc10-supply: Digital Core Supply Voltage (1.0V)
+ - iovcc18-supply: I/O Supply Voltage (1.8V)
+ - interrupts, interrupt-parent: interrupt specifier of INT pin
+ - reset-gpios: gpio specifier of RESET pin
+ - clocks, clock-names: specification and name of "xtal" clock
+ - video interfaces: Device node can contain video interface port
+ node for HDMI encoder according to [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+ sii8620@39 {
+ reg = <0x39>;
+ compatible = "sil,sii8620";
+ cvcc10-supply = <&ldo36_reg>;
+ iovcc18-supply = <&ldo34_reg>;
+ interrupt-parent = <&gpf0>;
+ interrupts = <2 0>;
+ reset-gpio = <&gpv7 0 0>;
+ clocks = <&pmu_system_controller 0>;
+ clock-names = "xtal";
+
+ port {
+ mhl_to_hdmi: endpoint {
+ remote-endpoint = <&hdmi_to_mhl>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
index 3f1437fbca6b..280d283304bb 100644
--- a/Documentation/devicetree/booting-without-of.txt
+++ b/Documentation/devicetree/booting-without-of.txt
@@ -974,6 +974,13 @@ compatibility.
4Gb. Some vendors prefer splitting those ranges into smaller
segments, but the kernel doesn't care.
+ Additional properties:
+
+ - hotpluggable : The presence of this property provides an explicit
+ hint to the operating system that this memory may potentially be
+ removed later. The kernel can take this into consideration when
+ doing nonmovable allocations and when laying out memory zones.
+
e) The /chosen node
This node is a bit "special". Normally, that's where Open Firmware
diff --git a/Documentation/doc-guide/conf.py b/Documentation/doc-guide/conf.py
new file mode 100644
index 000000000000..fd3731182d5a
--- /dev/null
+++ b/Documentation/doc-guide/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel Documentation Guide'
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/doc-guide/docbook.rst b/Documentation/doc-guide/docbook.rst
new file mode 100644
index 000000000000..d8bf04308b43
--- /dev/null
+++ b/Documentation/doc-guide/docbook.rst
@@ -0,0 +1,90 @@
+DocBook XML [DEPRECATED]
+========================
+
+.. attention::
+
+ This section describes the deprecated DocBook XML toolchain. Please do not
+ create new DocBook XML template files. Please consider converting existing
+ DocBook XML templates files to Sphinx/reStructuredText.
+
+Converting DocBook to Sphinx
+----------------------------
+
+Over time, we expect all of the documents under ``Documentation/DocBook`` to be
+converted to Sphinx and reStructuredText. For most DocBook XML documents, a good
+enough solution is to use the simple ``Documentation/sphinx/tmplcvt`` script,
+which uses ``pandoc`` under the hood. For example::
+
+ $ cd Documentation/sphinx
+ $ ./tmplcvt ../DocBook/in.tmpl ../out.rst
+
+Then edit the resulting rst files to fix any remaining issues, and add the
+document in the ``toctree`` in ``Documentation/index.rst``.
+
+Components of the kernel-doc system
+-----------------------------------
+
+Many places in the source tree have extractable documentation in the form of
+block comments above functions. The components of this system are:
+
+- ``scripts/kernel-doc``
+
+ This is a perl script that hunts for the block comments and can mark them up
+ directly into reStructuredText, DocBook, man, text, and HTML. (No, not
+ texinfo.)
+
+- ``Documentation/DocBook/*.tmpl``
+
+ These are XML template files, which are normal XML files with special
+ place-holders for where the extracted documentation should go.
+
+- ``scripts/docproc.c``
+
+ This is a program for converting XML template files into XML files. When a
+ file is referenced it is searched for symbols exported (EXPORT_SYMBOL), to be
+ able to distinguish between internal and external functions.
+
+ It invokes kernel-doc, giving it the list of functions that are to be
+ documented.
+
+ Additionally it is used to scan the XML template files to locate all the files
+ referenced herein. This is used to generate dependency information as used by
+ make.
+
+- ``Makefile``
+
+ The targets 'xmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used to build
+ DocBook XML files, PostScript files, PDF files, and html files in
+ Documentation/DocBook. The older target 'sgmldocs' is equivalent to 'xmldocs'.
+
+- ``Documentation/DocBook/Makefile``
+
+ This is where C files are associated with SGML templates.
+
+How to use kernel-doc comments in DocBook XML template files
+------------------------------------------------------------
+
+DocBook XML template files (\*.tmpl) are like normal XML files, except that they
+can contain escape sequences where extracted documentation should be inserted.
+
+``!E<filename>`` is replaced by the documentation, in ``<filename>``, for
+functions that are exported using ``EXPORT_SYMBOL``: the function list is
+collected from files listed in ``Documentation/DocBook/Makefile``.
+
+``!I<filename>`` is replaced by the documentation for functions that are **not**
+exported using ``EXPORT_SYMBOL``.
+
+``!D<filename>`` is used to name additional files to search for functions
+exported using ``EXPORT_SYMBOL``.
+
+``!F<filename> <function [functions...]>`` is replaced by the documentation, in
+``<filename>``, for the functions listed.
+
+``!P<filename> <section title>`` is replaced by the contents of the ``DOC:``
+section titled ``<section title>`` from ``<filename>``. Spaces are allowed in
+``<section title>``; do not quote the ``<section title>``.
+
+``!C<filename>`` is replaced by nothing, but makes the tools check that all DOC:
+sections and documented functions, symbols, etc. are used. This makes sense to
+use when you use ``!F`` or ``!P`` only and want to verify that all documentation
+is included.
diff --git a/Documentation/doc-guide/index.rst b/Documentation/doc-guide/index.rst
new file mode 100644
index 000000000000..6fff4024606e
--- /dev/null
+++ b/Documentation/doc-guide/index.rst
@@ -0,0 +1,20 @@
+.. _doc_guide:
+
+=================================
+How to write kernel documentation
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ sphinx.rst
+ kernel-doc.rst
+ parse-headers.rst
+ docbook.rst
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/kernel-documentation.rst b/Documentation/doc-guide/kernel-doc.rst
index 10cc7ddb6235..b32e4813ff6f 100644
--- a/Documentation/kernel-documentation.rst
+++ b/Documentation/doc-guide/kernel-doc.rst
@@ -1,228 +1,3 @@
-==========================
-Linux Kernel Documentation
-==========================
-
-Introduction
-============
-
-The Linux kernel uses `Sphinx`_ to generate pretty documentation from
-`reStructuredText`_ files under ``Documentation``. To build the documentation in
-HTML or PDF formats, use ``make htmldocs`` or ``make pdfdocs``. The generated
-documentation is placed in ``Documentation/output``.
-
-.. _Sphinx: http://www.sphinx-doc.org/
-.. _reStructuredText: http://docutils.sourceforge.net/rst.html
-
-The reStructuredText files may contain directives to include structured
-documentation comments, or kernel-doc comments, from source files. Usually these
-are used to describe the functions and types and design of the code. The
-kernel-doc comments have some special structure and formatting, but beyond that
-they are also treated as reStructuredText.
-
-There is also the deprecated DocBook toolchain to generate documentation from
-DocBook XML template files under ``Documentation/DocBook``. The DocBook files
-are to be converted to reStructuredText, and the toolchain is slated to be
-removed.
-
-Finally, there are thousands of plain text documentation files scattered around
-``Documentation``. Some of these will likely be converted to reStructuredText
-over time, but the bulk of them will remain in plain text.
-
-Sphinx Build
-============
-
-The usual way to generate the documentation is to run ``make htmldocs`` or
-``make pdfdocs``. There are also other formats available, see the documentation
-section of ``make help``. The generated documentation is placed in
-format-specific subdirectories under ``Documentation/output``.
-
-To generate documentation, Sphinx (``sphinx-build``) must obviously be
-installed. For prettier HTML output, the Read the Docs Sphinx theme
-(``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also
-needed. All of these are widely available and packaged in distributions.
-
-To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
-variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
-output.
-
-To remove the generated documentation, run ``make cleandocs``.
-
-Writing Documentation
-=====================
-
-Adding new documentation can be as simple as:
-
-1. Add a new ``.rst`` file somewhere under ``Documentation``.
-2. Refer to it from the Sphinx main `TOC tree`_ in ``Documentation/index.rst``.
-
-.. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html
-
-This is usually good enough for simple documentation (like the one you're
-reading right now), but for larger documents it may be advisable to create a
-subdirectory (or use an existing one). For example, the graphics subsystem
-documentation is under ``Documentation/gpu``, split to several ``.rst`` files,
-and has a separate ``index.rst`` (with a ``toctree`` of its own) referenced from
-the main index.
-
-See the documentation for `Sphinx`_ and `reStructuredText`_ on what you can do
-with them. In particular, the Sphinx `reStructuredText Primer`_ is a good place
-to get started with reStructuredText. There are also some `Sphinx specific
-markup constructs`_.
-
-.. _reStructuredText Primer: http://www.sphinx-doc.org/en/stable/rest.html
-.. _Sphinx specific markup constructs: http://www.sphinx-doc.org/en/stable/markup/index.html
-
-Specific guidelines for the kernel documentation
-------------------------------------------------
-
-Here are some specific guidelines for the kernel documentation:
-
-* Please don't go overboard with reStructuredText markup. Keep it simple.
-
-* Please stick to this order of heading adornments:
-
- 1. ``=`` with overline for document title::
-
- ==============
- Document title
- ==============
-
- 2. ``=`` for chapters::
-
- Chapters
- ========
-
- 3. ``-`` for sections::
-
- Section
- -------
-
- 4. ``~`` for subsections::
-
- Subsection
- ~~~~~~~~~~
-
- Although RST doesn't mandate a specific order ("Rather than imposing a fixed
- number and order of section title adornment styles, the order enforced will be
- the order as encountered."), having the higher levels the same overall makes
- it easier to follow the documents.
-
-
-the C domain
-------------
-
-The `Sphinx C Domain`_ (name c) is suited for documentation of C API. E.g. a
-function prototype:
-
-.. code-block:: rst
-
- .. c:function:: int ioctl( int fd, int request )
-
-The C domain of the kernel-doc has some additional features. E.g. you can
-*rename* the reference name of a function with a common name like ``open`` or
-``ioctl``:
-
-.. code-block:: rst
-
- .. c:function:: int ioctl( int fd, int request )
- :name: VIDIOC_LOG_STATUS
-
-The func-name (e.g. ioctl) remains in the output but the ref-name changed from
-``ioctl`` to ``VIDIOC_LOG_STATUS``. The index entry for this function is also
-changed to ``VIDIOC_LOG_STATUS`` and the function can now referenced by:
-
-.. code-block:: rst
-
- :c:func:`VIDIOC_LOG_STATUS`
-
-
-list tables
------------
-
-We recommend the use of *list table* formats. The *list table* formats are
-double-stage lists. Compared to the ASCII-art they might not be as
-comfortable for
-readers of the text files. Their advantage is that they are easy to
-create or modify and that the diff of a modification is much more meaningful,
-because it is limited to the modified content.
-
-The ``flat-table`` is a double-stage list similar to the ``list-table`` with
-some additional features:
-
-* column-span: with the role ``cspan`` a cell can be extended through
- additional columns
-
-* row-span: with the role ``rspan`` a cell can be extended through
- additional rows
-
-* auto span rightmost cell of a table row over the missing cells on the right
- side of that table-row. With Option ``:fill-cells:`` this behavior can
- changed from *auto span* to *auto fill*, which automatically inserts (empty)
- cells instead of spanning the last cell.
-
-options:
-
-* ``:header-rows:`` [int] count of header rows
-* ``:stub-columns:`` [int] count of stub columns
-* ``:widths:`` [[int] [int] ... ] widths of columns
-* ``:fill-cells:`` instead of auto-spanning missing cells, insert missing cells
-
-roles:
-
-* ``:cspan:`` [int] additional columns (*morecols*)
-* ``:rspan:`` [int] additional rows (*morerows*)
-
-The example below shows how to use this markup. The first level of the staged
-list is the *table-row*. In the *table-row* there is only one markup allowed,
-the list of the cells in this *table-row*. Exceptions are *comments* ( ``..`` )
-and *targets* (e.g. a ref to ``:ref:`last row <last row>``` / :ref:`last row
-<last row>`).
-
-.. code-block:: rst
-
- .. flat-table:: table title
- :widths: 2 1 1 3
-
- * - head col 1
- - head col 2
- - head col 3
- - head col 4
-
- * - column 1
- - field 1.1
- - field 1.2 with autospan
-
- * - column 2
- - field 2.1
- - :rspan:`1` :cspan:`1` field 2.2 - 3.3
-
- * .. _`last row`:
-
- - column 3
-
-Rendered as:
-
- .. flat-table:: table title
- :widths: 2 1 1 3
-
- * - head col 1
- - head col 2
- - head col 3
- - head col 4
-
- * - column 1
- - field 1.1
- - field 1.2 with autospan
-
- * - column 2
- - field 2.1
- - :rspan:`1` :cspan:`1` field 2.2 - 3.3
-
- * .. _`last row`:
-
- - column 3
-
-
Including kernel-doc comments
=============================
@@ -484,7 +259,10 @@ span multiple lines. The continuation lines may contain indentation.
In-line member documentation comments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The structure members may also be documented in-line within the definition::
+The structure members may also be documented in-line within the definition.
+There are two styles, single-line comments where both the opening ``/**`` and
+closing ``*/`` are on the same line, and multi-line comments where they are each
+on a line of their own, like all other kernel-doc comments::
/**
* struct foo - Brief description.
@@ -502,6 +280,8 @@ The structure members may also be documented in-line within the definition::
* Here, the member description may contain several paragraphs.
*/
int baz;
+ /** @foobar: Single line description. */
+ int foobar;
}
Private members
@@ -586,94 +366,3 @@ file.
Data structures visible in kernel include files should also be documented using
kernel-doc formatted comments.
-
-DocBook XML [DEPRECATED]
-========================
-
-.. attention::
-
- This section describes the deprecated DocBook XML toolchain. Please do not
- create new DocBook XML template files. Please consider converting existing
- DocBook XML templates files to Sphinx/reStructuredText.
-
-Converting DocBook to Sphinx
-----------------------------
-
-Over time, we expect all of the documents under ``Documentation/DocBook`` to be
-converted to Sphinx and reStructuredText. For most DocBook XML documents, a good
-enough solution is to use the simple ``Documentation/sphinx/tmplcvt`` script,
-which uses ``pandoc`` under the hood. For example::
-
- $ cd Documentation/sphinx
- $ ./tmplcvt ../DocBook/in.tmpl ../out.rst
-
-Then edit the resulting rst files to fix any remaining issues, and add the
-document in the ``toctree`` in ``Documentation/index.rst``.
-
-Components of the kernel-doc system
------------------------------------
-
-Many places in the source tree have extractable documentation in the form of
-block comments above functions. The components of this system are:
-
-- ``scripts/kernel-doc``
-
- This is a perl script that hunts for the block comments and can mark them up
- directly into reStructuredText, DocBook, man, text, and HTML. (No, not
- texinfo.)
-
-- ``Documentation/DocBook/*.tmpl``
-
- These are XML template files, which are normal XML files with special
- place-holders for where the extracted documentation should go.
-
-- ``scripts/docproc.c``
-
- This is a program for converting XML template files into XML files. When a
- file is referenced it is searched for symbols exported (EXPORT_SYMBOL), to be
- able to distinguish between internal and external functions.
-
- It invokes kernel-doc, giving it the list of functions that are to be
- documented.
-
- Additionally it is used to scan the XML template files to locate all the files
- referenced herein. This is used to generate dependency information as used by
- make.
-
-- ``Makefile``
-
- The targets 'xmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used to build
- DocBook XML files, PostScript files, PDF files, and html files in
- Documentation/DocBook. The older target 'sgmldocs' is equivalent to 'xmldocs'.
-
-- ``Documentation/DocBook/Makefile``
-
- This is where C files are associated with SGML templates.
-
-How to use kernel-doc comments in DocBook XML template files
-------------------------------------------------------------
-
-DocBook XML template files (\*.tmpl) are like normal XML files, except that they
-can contain escape sequences where extracted documentation should be inserted.
-
-``!E<filename>`` is replaced by the documentation, in ``<filename>``, for
-functions that are exported using ``EXPORT_SYMBOL``: the function list is
-collected from files listed in ``Documentation/DocBook/Makefile``.
-
-``!I<filename>`` is replaced by the documentation for functions that are **not**
-exported using ``EXPORT_SYMBOL``.
-
-``!D<filename>`` is used to name additional files to search for functions
-exported using ``EXPORT_SYMBOL``.
-
-``!F<filename> <function [functions...]>`` is replaced by the documentation, in
-``<filename>``, for the functions listed.
-
-``!P<filename> <section title>`` is replaced by the contents of the ``DOC:``
-section titled ``<section title>`` from ``<filename>``. Spaces are allowed in
-``<section title>``; do not quote the ``<section title>``.
-
-``!C<filename>`` is replaced by nothing, but makes the tools check that all DOC:
-sections and documented functions, symbols, etc. are used. This makes sense to
-use when you use ``!F`` or ``!P`` only and want to verify that all documentation
-is included.
diff --git a/Documentation/doc-guide/parse-headers.rst b/Documentation/doc-guide/parse-headers.rst
new file mode 100644
index 000000000000..96a0423d5dba
--- /dev/null
+++ b/Documentation/doc-guide/parse-headers.rst
@@ -0,0 +1,192 @@
+===========================
+Including uAPI header files
+===========================
+
+Sometimes, it is useful to include header files and C example codes in
+order to describe the userspace API and to generate cross-references
+between the code and the documentation. Adding cross-references for
+userspace API files has an additional vantage: Sphinx will generate warnings
+if a symbol is not found at the documentation. That helps to keep the
+uAPI documentation in sync with the Kernel changes.
+The :ref:`parse_headers.pl <parse_headers>` provide a way to generate such
+cross-references. It has to be called via Makefile, while building the
+documentation. Please see ``Documentation/media/Makefile`` for an example
+about how to use it inside the Kernel tree.
+
+.. _parse_headers:
+
+parse_headers.pl
+^^^^^^^^^^^^^^^^
+
+NAME
+****
+
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+
+SYNOPSIS
+********
+
+
+\ **parse_headers.pl**\ [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+
+OPTIONS
+*******
+
+
+
+\ **--debug**\
+
+ Put the script in verbose mode, useful for debugging.
+
+
+
+\ **--usage**\
+
+ Prints a brief help message and exits.
+
+
+
+\ **--help**\
+
+ Prints a more detailed help message and exits.
+
+
+DESCRIPTION
+***********
+
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two types of statements: \ **ignore**\ or \ **replace**\ .
+
+The syntax for the ignore tag is:
+
+
+ignore \ **type**\ \ **name**\
+
+The \ **ignore**\ means that it won't generate cross references for a
+\ **name**\ symbol of type \ **type**\ .
+
+The syntax for the replace tag is:
+
+
+replace \ **type**\ \ **name**\ \ **new_value**\
+
+The \ **replace**\ means that it will generate cross references for a
+\ **name**\ symbol of type \ **type**\ , but, instead of using the default
+replacement rule, it will use \ **new_value**\ .
+
+For both statements, \ **type**\ can be either one of the following:
+
+
+\ **ioctl**\
+
+ The ignore or replace statement will apply to ioctl definitions like:
+
+ #define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
+
+
+
+\ **define**\
+
+ The ignore or replace statement will apply to any other #define found
+ at C_FILE.
+
+
+
+\ **typedef**\
+
+ The ignore or replace statement will apply to typedef statements at C_FILE.
+
+
+
+\ **struct**\
+
+ The ignore or replace statement will apply to the name of struct statements
+ at C_FILE.
+
+
+
+\ **enum**\
+
+ The ignore or replace statement will apply to the name of enum statements
+ at C_FILE.
+
+
+
+\ **symbol**\
+
+ The ignore or replace statement will apply to the name of enum statements
+ at C_FILE.
+
+ For replace statements, \ **new_value**\ will automatically use :c:type:
+ references for \ **typedef**\ , \ **enum**\ and \ **struct**\ types. It will use :ref:
+ for \ **ioctl**\ , \ **define**\ and \ **symbol**\ types. The type of reference can
+ also be explicitly defined at the replace statement.
+
+
+
+EXAMPLES
+********
+
+
+ignore define _VIDEODEV2_H
+
+
+Ignore a #define _VIDEODEV2_H at the C_FILE.
+
+ignore symbol PRIVATE
+
+
+On a struct like:
+
+enum foo { BAR1, BAR2, PRIVATE };
+
+It won't generate cross-references for \ **PRIVATE**\ .
+
+replace symbol BAR1 :c:type:\`foo\`
+replace symbol BAR2 :c:type:\`foo\`
+
+
+On a struct like:
+
+enum foo { BAR1, BAR2, PRIVATE };
+
+It will make the BAR1 and BAR2 enum symbols to cross reference the foo
+symbol at the C domain.
+
+
+BUGS
+****
+
+
+Report bugs to Mauro Carvalho Chehab <mchehab@s-opensource.com>
+
+
+COPYRIGHT
+*********
+
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff --git a/Documentation/doc-guide/sphinx.rst b/Documentation/doc-guide/sphinx.rst
new file mode 100644
index 000000000000..96fe7ccb2c67
--- /dev/null
+++ b/Documentation/doc-guide/sphinx.rst
@@ -0,0 +1,219 @@
+Introduction
+============
+
+The Linux kernel uses `Sphinx`_ to generate pretty documentation from
+`reStructuredText`_ files under ``Documentation``. To build the documentation in
+HTML or PDF formats, use ``make htmldocs`` or ``make pdfdocs``. The generated
+documentation is placed in ``Documentation/output``.
+
+.. _Sphinx: http://www.sphinx-doc.org/
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+
+The reStructuredText files may contain directives to include structured
+documentation comments, or kernel-doc comments, from source files. Usually these
+are used to describe the functions and types and design of the code. The
+kernel-doc comments have some special structure and formatting, but beyond that
+they are also treated as reStructuredText.
+
+There is also the deprecated DocBook toolchain to generate documentation from
+DocBook XML template files under ``Documentation/DocBook``. The DocBook files
+are to be converted to reStructuredText, and the toolchain is slated to be
+removed.
+
+Finally, there are thousands of plain text documentation files scattered around
+``Documentation``. Some of these will likely be converted to reStructuredText
+over time, but the bulk of them will remain in plain text.
+
+Sphinx Build
+============
+
+The usual way to generate the documentation is to run ``make htmldocs`` or
+``make pdfdocs``. There are also other formats available, see the documentation
+section of ``make help``. The generated documentation is placed in
+format-specific subdirectories under ``Documentation/output``.
+
+To generate documentation, Sphinx (``sphinx-build``) must obviously be
+installed. For prettier HTML output, the Read the Docs Sphinx theme
+(``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also
+needed. All of these are widely available and packaged in distributions.
+
+To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
+variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
+output.
+
+To remove the generated documentation, run ``make cleandocs``.
+
+Writing Documentation
+=====================
+
+Adding new documentation can be as simple as:
+
+1. Add a new ``.rst`` file somewhere under ``Documentation``.
+2. Refer to it from the Sphinx main `TOC tree`_ in ``Documentation/index.rst``.
+
+.. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html
+
+This is usually good enough for simple documentation (like the one you're
+reading right now), but for larger documents it may be advisable to create a
+subdirectory (or use an existing one). For example, the graphics subsystem
+documentation is under ``Documentation/gpu``, split to several ``.rst`` files,
+and has a separate ``index.rst`` (with a ``toctree`` of its own) referenced from
+the main index.
+
+See the documentation for `Sphinx`_ and `reStructuredText`_ on what you can do
+with them. In particular, the Sphinx `reStructuredText Primer`_ is a good place
+to get started with reStructuredText. There are also some `Sphinx specific
+markup constructs`_.
+
+.. _reStructuredText Primer: http://www.sphinx-doc.org/en/stable/rest.html
+.. _Sphinx specific markup constructs: http://www.sphinx-doc.org/en/stable/markup/index.html
+
+Specific guidelines for the kernel documentation
+------------------------------------------------
+
+Here are some specific guidelines for the kernel documentation:
+
+* Please don't go overboard with reStructuredText markup. Keep it simple.
+
+* Please stick to this order of heading adornments:
+
+ 1. ``=`` with overline for document title::
+
+ ==============
+ Document title
+ ==============
+
+ 2. ``=`` for chapters::
+
+ Chapters
+ ========
+
+ 3. ``-`` for sections::
+
+ Section
+ -------
+
+ 4. ``~`` for subsections::
+
+ Subsection
+ ~~~~~~~~~~
+
+ Although RST doesn't mandate a specific order ("Rather than imposing a fixed
+ number and order of section title adornment styles, the order enforced will be
+ the order as encountered."), having the higher levels the same overall makes
+ it easier to follow the documents.
+
+
+the C domain
+------------
+
+The `Sphinx C Domain`_ (name c) is suited for documentation of C API. E.g. a
+function prototype:
+
+.. code-block:: rst
+
+ .. c:function:: int ioctl( int fd, int request )
+
+The C domain of the kernel-doc has some additional features. E.g. you can
+*rename* the reference name of a function with a common name like ``open`` or
+``ioctl``:
+
+.. code-block:: rst
+
+ .. c:function:: int ioctl( int fd, int request )
+ :name: VIDIOC_LOG_STATUS
+
+The func-name (e.g. ioctl) remains in the output but the ref-name changed from
+``ioctl`` to ``VIDIOC_LOG_STATUS``. The index entry for this function is also
+changed to ``VIDIOC_LOG_STATUS`` and the function can now referenced by:
+
+.. code-block:: rst
+
+ :c:func:`VIDIOC_LOG_STATUS`
+
+
+list tables
+-----------
+
+We recommend the use of *list table* formats. The *list table* formats are
+double-stage lists. Compared to the ASCII-art they might not be as
+comfortable for
+readers of the text files. Their advantage is that they are easy to
+create or modify and that the diff of a modification is much more meaningful,
+because it is limited to the modified content.
+
+The ``flat-table`` is a double-stage list similar to the ``list-table`` with
+some additional features:
+
+* column-span: with the role ``cspan`` a cell can be extended through
+ additional columns
+
+* row-span: with the role ``rspan`` a cell can be extended through
+ additional rows
+
+* auto span rightmost cell of a table row over the missing cells on the right
+ side of that table-row. With Option ``:fill-cells:`` this behavior can
+ changed from *auto span* to *auto fill*, which automatically inserts (empty)
+ cells instead of spanning the last cell.
+
+options:
+
+* ``:header-rows:`` [int] count of header rows
+* ``:stub-columns:`` [int] count of stub columns
+* ``:widths:`` [[int] [int] ... ] widths of columns
+* ``:fill-cells:`` instead of auto-spanning missing cells, insert missing cells
+
+roles:
+
+* ``:cspan:`` [int] additional columns (*morecols*)
+* ``:rspan:`` [int] additional rows (*morerows*)
+
+The example below shows how to use this markup. The first level of the staged
+list is the *table-row*. In the *table-row* there is only one markup allowed,
+the list of the cells in this *table-row*. Exceptions are *comments* ( ``..`` )
+and *targets* (e.g. a ref to ``:ref:`last row <last row>``` / :ref:`last row
+<last row>`).
+
+.. code-block:: rst
+
+ .. flat-table:: table title
+ :widths: 2 1 1 3
+
+ * - head col 1
+ - head col 2
+ - head col 3
+ - head col 4
+
+ * - column 1
+ - field 1.1
+ - field 1.2 with autospan
+
+ * - column 2
+ - field 2.1
+ - :rspan:`1` :cspan:`1` field 2.2 - 3.3
+
+ * .. _`last row`:
+
+ - column 3
+
+Rendered as:
+
+ .. flat-table:: table title
+ :widths: 2 1 1 3
+
+ * - head col 1
+ - head col 2
+ - head col 3
+ - head col 4
+
+ * - column 1
+ - field 1.1
+ - field 1.2 with autospan
+
+ * - column 2
+ - field 2.1
+ - :rspan:`1` :cspan:`1` field 2.2 - 3.3
+
+ * .. _`last row`:
+
+ - column 3
diff --git a/Documentation/80211/cfg80211.rst b/Documentation/driver-api/80211/cfg80211.rst
index b1e149ea6fee..b1e149ea6fee 100644
--- a/Documentation/80211/cfg80211.rst
+++ b/Documentation/driver-api/80211/cfg80211.rst
diff --git a/Documentation/80211/conf.py b/Documentation/driver-api/80211/conf.py
index 20c7c275ef4a..4424b4b0b9c3 100644
--- a/Documentation/80211/conf.py
+++ b/Documentation/driver-api/80211/conf.py
@@ -3,3 +3,8 @@
project = "Linux 802.11 Driver Developer's Guide"
tags.add("subproject")
+
+latex_documents = [
+ ('index', '80211.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/80211/index.rst b/Documentation/driver-api/80211/index.rst
index 90bba476f442..af210859d3e1 100644
--- a/Documentation/80211/index.rst
+++ b/Documentation/driver-api/80211/index.rst
@@ -9,7 +9,7 @@ Linux 802.11 Driver Developer's Guide
mac80211
mac80211-advanced
-.. only:: subproject
+.. only:: subproject and html
Indices
=======
diff --git a/Documentation/80211/introduction.rst b/Documentation/driver-api/80211/introduction.rst
index 4938fa87691c..4938fa87691c 100644
--- a/Documentation/80211/introduction.rst
+++ b/Documentation/driver-api/80211/introduction.rst
diff --git a/Documentation/80211/mac80211-advanced.rst b/Documentation/driver-api/80211/mac80211-advanced.rst
index 70a89b2163c2..70a89b2163c2 100644
--- a/Documentation/80211/mac80211-advanced.rst
+++ b/Documentation/driver-api/80211/mac80211-advanced.rst
diff --git a/Documentation/80211/mac80211.rst b/Documentation/driver-api/80211/mac80211.rst
index 85a8335e80b6..85a8335e80b6 100644
--- a/Documentation/80211/mac80211.rst
+++ b/Documentation/driver-api/80211/mac80211.rst
diff --git a/Documentation/driver-api/conf.py b/Documentation/driver-api/conf.py
new file mode 100644
index 000000000000..202726d20088
--- /dev/null
+++ b/Documentation/driver-api/conf.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "The Linux driver implementer's API guide"
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'driver-api.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst
new file mode 100644
index 000000000000..5f5713448703
--- /dev/null
+++ b/Documentation/driver-api/device_link.rst
@@ -0,0 +1,279 @@
+============
+Device links
+============
+
+By default, the driver core only enforces dependencies between devices
+that are borne out of a parent/child relationship within the device
+hierarchy: When suspending, resuming or shutting down the system, devices
+are ordered based on this relationship, i.e. children are always suspended
+before their parent, and the parent is always resumed before its children.
+
+Sometimes there is a need to represent device dependencies beyond the
+mere parent/child relationship, e.g. between siblings, and have the
+driver core automatically take care of them.
+
+Secondly, the driver core by default does not enforce any driver presence
+dependencies, i.e. that one device must be bound to a driver before
+another one can probe or function correctly.
+
+Often these two dependency types come together, so a device depends on
+another one both with regards to driver presence *and* with regards to
+suspend/resume and shutdown ordering.
+
+Device links allow representation of such dependencies in the driver core.
+
+In its standard form, a device link combines *both* dependency types:
+It guarantees correct suspend/resume and shutdown ordering between a
+"supplier" device and its "consumer" devices, and it guarantees driver
+presence on the supplier. The consumer devices are not probed before the
+supplier is bound to a driver, and they're unbound before the supplier
+is unbound.
+
+When driver presence on the supplier is irrelevant and only correct
+suspend/resume and shutdown ordering is needed, the device link may
+simply be set up with the ``DL_FLAG_STATELESS`` flag. In other words,
+enforcing driver presence on the supplier is optional.
+
+Another optional feature is runtime PM integration: By setting the
+``DL_FLAG_PM_RUNTIME`` flag on addition of the device link, the PM core
+is instructed to runtime resume the supplier and keep it active
+whenever and for as long as the consumer is runtime resumed.
+
+Usage
+=====
+
+The earliest point in time when device links can be added is after
+:c:func:`device_add()` has been called for the supplier and
+:c:func:`device_initialize()` has been called for the consumer.
+
+It is legal to add them later, but care must be taken that the system
+remains in a consistent state: E.g. a device link cannot be added in
+the midst of a suspend/resume transition, so either commencement of
+such a transition needs to be prevented with :c:func:`lock_system_sleep()`,
+or the device link needs to be added from a function which is guaranteed
+not to run in parallel to a suspend/resume transition, such as from a
+device ``->probe`` callback or a boot-time PCI quirk.
+
+Another example for an inconsistent state would be a device link that
+represents a driver presence dependency, yet is added from the consumer's
+``->probe`` callback while the supplier hasn't probed yet: Had the driver
+core known about the device link earlier, it wouldn't have probed the
+consumer in the first place. The onus is thus on the consumer to check
+presence of the supplier after adding the link, and defer probing on
+non-presence.
+
+If a device link is added in the ``->probe`` callback of the supplier or
+consumer driver, it is typically deleted in its ``->remove`` callback for
+symmetry. That way, if the driver is compiled as a module, the device
+link is added on module load and orderly deleted on unload. The same
+restrictions that apply to device link addition (e.g. exclusion of a
+parallel suspend/resume transition) apply equally to deletion.
+
+Several flags may be specified on device link addition, two of which
+have already been mentioned above: ``DL_FLAG_STATELESS`` to express that no
+driver presence dependency is needed (but only correct suspend/resume and
+shutdown ordering) and ``DL_FLAG_PM_RUNTIME`` to express that runtime PM
+integration is desired.
+
+Two other flags are specifically targeted at use cases where the device
+link is added from the consumer's ``->probe`` callback: ``DL_FLAG_RPM_ACTIVE``
+can be specified to runtime resume the supplier upon addition of the
+device link. ``DL_FLAG_AUTOREMOVE`` causes the device link to be automatically
+purged when the consumer fails to probe or later unbinds. This obviates
+the need to explicitly delete the link in the ``->remove`` callback or in
+the error path of the ``->probe`` callback.
+
+Limitations
+===========
+
+Driver authors should be aware that a driver presence dependency (i.e. when
+``DL_FLAG_STATELESS`` is not specified on link addition) may cause probing of
+the consumer to be deferred indefinitely. This can become a problem if the
+consumer is required to probe before a certain initcall level is reached.
+Worse, if the supplier driver is blacklisted or missing, the consumer will
+never be probed.
+
+Sometimes drivers depend on optional resources. They are able to operate
+in a degraded mode (reduced feature set or performance) when those resources
+are not present. An example is an SPI controller that can use a DMA engine
+or work in PIO mode. The controller can determine presence of the optional
+resources at probe time but on non-presence there is no way to know whether
+they will become available in the near future (due to a supplier driver
+probing) or never. Consequently it cannot be determined whether to defer
+probing or not. It would be possible to notify drivers when optional
+resources become available after probing, but it would come at a high cost
+for drivers as switching between modes of operation at runtime based on the
+availability of such resources would be much more complex than a mechanism
+based on probe deferral. In any case optional resources are beyond the
+scope of device links.
+
+Examples
+========
+
+* An MMU device exists alongside a busmaster device, both are in the same
+ power domain. The MMU implements DMA address translation for the busmaster
+ device and shall be runtime resumed and kept active whenever and as long
+ as the busmaster device is active. The busmaster device's driver shall
+ not bind before the MMU is bound. To achieve this, a device link with
+ runtime PM integration is added from the busmaster device (consumer)
+ to the MMU device (supplier). The effect with regards to runtime PM
+ is the same as if the MMU was the parent of the master device.
+
+ The fact that both devices share the same power domain would normally
+ suggest usage of a :c:type:`struct dev_pm_domain` or :c:type:`struct
+ generic_pm_domain`, however these are not independent devices that
+ happen to share a power switch, but rather the MMU device serves the
+ busmaster device and is useless without it. A device link creates a
+ synthetic hierarchical relationship between the devices and is thus
+ more apt.
+
+* A Thunderbolt host controller comprises a number of PCIe hotplug ports
+ and an NHI device to manage the PCIe switch. On resume from system sleep,
+ the NHI device needs to re-establish PCI tunnels to attached devices
+ before the hotplug ports can resume. If the hotplug ports were children
+ of the NHI, this resume order would automatically be enforced by the
+ PM core, but unfortunately they're aunts. The solution is to add
+ device links from the hotplug ports (consumers) to the NHI device
+ (supplier). A driver presence dependency is not necessary for this
+ use case.
+
+* Discrete GPUs in hybrid graphics laptops often feature an HDA controller
+ for HDMI/DP audio. In the device hierarchy the HDA controller is a sibling
+ of the VGA device, yet both share the same power domain and the HDA
+ controller is only ever needed when an HDMI/DP display is attached to the
+ VGA device. A device link from the HDA controller (consumer) to the
+ VGA device (supplier) aptly represents this relationship.
+
+* ACPI allows definition of a device start order by way of _DEP objects.
+ A classical example is when ACPI power management methods on one device
+ are implemented in terms of I\ :sup:`2`\ C accesses and require a specific
+ I\ :sup:`2`\ C controller to be present and functional for the power
+ management of the device in question to work.
+
+* In some SoCs a functional dependency exists from display, video codec and
+ video processing IP cores on transparent memory access IP cores that handle
+ burst access and compression/decompression.
+
+Alternatives
+============
+
+* A :c:type:`struct dev_pm_domain` can be used to override the bus,
+ class or device type callbacks. It is intended for devices sharing
+ a single on/off switch, however it does not guarantee a specific
+ suspend/resume ordering, this needs to be implemented separately.
+ It also does not by itself track the runtime PM status of the involved
+ devices and turn off the power switch only when all of them are runtime
+ suspended. Furthermore it cannot be used to enforce a specific shutdown
+ ordering or a driver presence dependency.
+
+* A :c:type:`struct generic_pm_domain` is a lot more heavyweight than a
+ device link and does not allow for shutdown ordering or driver presence
+ dependencies. It also cannot be used on ACPI systems.
+
+Implementation
+==============
+
+The device hierarchy, which -- as the name implies -- is a tree,
+becomes a directed acyclic graph once device links are added.
+
+Ordering of these devices during suspend/resume is determined by the
+dpm_list. During shutdown it is determined by the devices_kset. With
+no device links present, the two lists are a flattened, one-dimensional
+representations of the device tree such that a device is placed behind
+all its ancestors. That is achieved by traversing the ACPI namespace
+or OpenFirmware device tree top-down and appending devices to the lists
+as they are discovered.
+
+Once device links are added, the lists need to satisfy the additional
+constraint that a device is placed behind all its suppliers, recursively.
+To ensure this, upon addition of the device link the consumer and the
+entire sub-graph below it (all children and consumers of the consumer)
+are moved to the end of the list. (Call to :c:func:`device_reorder_to_tail()`
+from :c:func:`device_link_add()`.)
+
+To prevent introduction of dependency loops into the graph, it is
+verified upon device link addition that the supplier is not dependent
+on the consumer or any children or consumers of the consumer.
+(Call to :c:func:`device_is_dependent()` from :c:func:`device_link_add()`.)
+If that constraint is violated, :c:func:`device_link_add()` will return
+``NULL`` and a ``WARNING`` will be logged.
+
+Notably this also prevents the addition of a device link from a parent
+device to a child. However the converse is allowed, i.e. a device link
+from a child to a parent. Since the driver core already guarantees
+correct suspend/resume and shutdown ordering between parent and child,
+such a device link only makes sense if a driver presence dependency is
+needed on top of that. In this case driver authors should weigh
+carefully if a device link is at all the right tool for the purpose.
+A more suitable approach might be to simply use deferred probing or
+add a device flag causing the parent driver to be probed before the
+child one.
+
+State machine
+=============
+
+.. kernel-doc:: include/linux/device.h
+ :functions: device_link_state
+
+::
+
+ .=============================.
+ | |
+ v |
+ DORMANT <=> AVAILABLE <=> CONSUMER_PROBE => ACTIVE
+ ^ |
+ | |
+ '============ SUPPLIER_UNBIND <============'
+
+* The initial state of a device link is automatically determined by
+ :c:func:`device_link_add()` based on the driver presence on the supplier
+ and consumer. If the link is created before any devices are probed, it
+ is set to ``DL_STATE_DORMANT``.
+
+* When a supplier device is bound to a driver, links to its consumers
+ progress to ``DL_STATE_AVAILABLE``.
+ (Call to :c:func:`device_links_driver_bound()` from
+ :c:func:`driver_bound()`.)
+
+* Before a consumer device is probed, presence of supplier drivers is
+ verified by checking that links to suppliers are in ``DL_STATE_AVAILABLE``
+ state. The state of the links is updated to ``DL_STATE_CONSUMER_PROBE``.
+ (Call to :c:func:`device_links_check_suppliers()` from
+ :c:func:`really_probe()`.)
+ This prevents the supplier from unbinding.
+ (Call to :c:func:`wait_for_device_probe()` from
+ :c:func:`device_links_unbind_consumers()`.)
+
+* If the probe fails, links to suppliers revert back to ``DL_STATE_AVAILABLE``.
+ (Call to :c:func:`device_links_no_driver()` from :c:func:`really_probe()`.)
+
+* If the probe succeeds, links to suppliers progress to ``DL_STATE_ACTIVE``.
+ (Call to :c:func:`device_links_driver_bound()` from :c:func:`driver_bound()`.)
+
+* When the consumer's driver is later on removed, links to suppliers revert
+ back to ``DL_STATE_AVAILABLE``.
+ (Call to :c:func:`__device_links_no_driver()` from
+ :c:func:`device_links_driver_cleanup()`, which in turn is called from
+ :c:func:`__device_release_driver()`.)
+
+* Before a supplier's driver is removed, links to consumers that are not
+ bound to a driver are updated to ``DL_STATE_SUPPLIER_UNBIND``.
+ (Call to :c:func:`device_links_busy()` from
+ :c:func:`__device_release_driver()`.)
+ This prevents the consumers from binding.
+ (Call to :c:func:`device_links_check_suppliers()` from
+ :c:func:`really_probe()`.)
+ Consumers that are bound are freed from their driver; consumers that are
+ probing are waited for until they are done.
+ (Call to :c:func:`device_links_unbind_consumers()` from
+ :c:func:`__device_release_driver()`.)
+ Once all links to consumers are in ``DL_STATE_SUPPLIER_UNBIND`` state,
+ the supplier driver is released and the links revert to ``DL_STATE_DORMANT``.
+ (Call to :c:func:`device_links_driver_cleanup()` from
+ :c:func:`__device_release_driver()`.)
+
+API
+===
+
+.. kernel-doc:: drivers/base/core.c
+ :functions: device_link_add device_link_del
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
new file mode 100644
index 000000000000..a9b457a4b949
--- /dev/null
+++ b/Documentation/driver-api/dma-buf.rst
@@ -0,0 +1,73 @@
+Buffer Sharing and Synchronization
+==================================
+
+The dma-buf subsystem provides the framework for sharing buffers for
+hardware (DMA) access across multiple device drivers and subsystems, and
+for synchronizing asynchronous hardware access.
+
+This is used, for example, by drm "prime" multi-GPU support, but is of
+course not limited to GPU use cases.
+
+The three main components of this are: (1) dma-buf, representing a
+sg_table and exposed to userspace as a file descriptor to allow passing
+between devices, (2) fence, which provides a mechanism to signal when
+one device as finished access, and (3) reservation, which manages the
+shared or exclusive fence(s) associated with the buffer.
+
+Shared DMA Buffers
+------------------
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+ :export:
+
+.. kernel-doc:: include/linux/dma-buf.h
+ :internal:
+
+Reservation Objects
+-------------------
+
+.. kernel-doc:: drivers/dma-buf/reservation.c
+ :doc: Reservation Object Overview
+
+.. kernel-doc:: drivers/dma-buf/reservation.c
+ :export:
+
+.. kernel-doc:: include/linux/reservation.h
+ :internal:
+
+DMA Fences
+----------
+
+.. kernel-doc:: drivers/dma-buf/dma-fence.c
+ :export:
+
+.. kernel-doc:: include/linux/dma-fence.h
+ :internal:
+
+Seqno Hardware Fences
+~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/seqno-fence.c
+ :export:
+
+.. kernel-doc:: include/linux/seqno-fence.h
+ :internal:
+
+DMA Fence Array
+~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-fence-array.c
+ :export:
+
+.. kernel-doc:: include/linux/dma-fence-array.h
+ :internal:
+
+DMA Fence uABI/Sync File
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/sync_file.c
+ :export:
+
+.. kernel-doc:: include/linux/sync_file.h
+ :internal:
+
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index 8e259c5d0322..a528178a54a5 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -16,11 +16,23 @@ available subsections can be seen below.
basics
infrastructure
+ dma-buf
+ device_link
message-based
sound
frame-buffer
input
+ usb
spi
i2c
hsi
miscellaneous
+ vme
+ 80211/index
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/driver-api/infrastructure.rst b/Documentation/driver-api/infrastructure.rst
index 5d50d6733db3..0bb0b5fc9512 100644
--- a/Documentation/driver-api/infrastructure.rst
+++ b/Documentation/driver-api/infrastructure.rst
@@ -46,76 +46,6 @@ Device Drivers Base
.. kernel-doc:: drivers/base/bus.c
:export:
-Buffer Sharing and Synchronization
-----------------------------------
-
-The dma-buf subsystem provides the framework for sharing buffers for
-hardware (DMA) access across multiple device drivers and subsystems, and
-for synchronizing asynchronous hardware access.
-
-This is used, for example, by drm "prime" multi-GPU support, but is of
-course not limited to GPU use cases.
-
-The three main components of this are: (1) dma-buf, representing a
-sg_table and exposed to userspace as a file descriptor to allow passing
-between devices, (2) fence, which provides a mechanism to signal when
-one device as finished access, and (3) reservation, which manages the
-shared or exclusive fence(s) associated with the buffer.
-
-dma-buf
-~~~~~~~
-
-.. kernel-doc:: drivers/dma-buf/dma-buf.c
- :export:
-
-.. kernel-doc:: include/linux/dma-buf.h
- :internal:
-
-reservation
-~~~~~~~~~~~
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
- :doc: Reservation Object Overview
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
- :export:
-
-.. kernel-doc:: include/linux/reservation.h
- :internal:
-
-fence
-~~~~~
-
-.. kernel-doc:: drivers/dma-buf/fence.c
- :export:
-
-.. kernel-doc:: include/linux/fence.h
- :internal:
-
-.. kernel-doc:: drivers/dma-buf/seqno-fence.c
- :export:
-
-.. kernel-doc:: include/linux/seqno-fence.h
- :internal:
-
-.. kernel-doc:: drivers/dma-buf/fence-array.c
- :export:
-
-.. kernel-doc:: include/linux/fence-array.h
- :internal:
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
- :export:
-
-.. kernel-doc:: include/linux/reservation.h
- :internal:
-
-.. kernel-doc:: drivers/dma-buf/sync_file.c
- :export:
-
-.. kernel-doc:: include/linux/sync_file.h
- :internal:
-
Device Drivers DMA Management
-----------------------------
diff --git a/Documentation/driver-api/usb.rst b/Documentation/driver-api/usb.rst
new file mode 100644
index 000000000000..851cc40b66b5
--- /dev/null
+++ b/Documentation/driver-api/usb.rst
@@ -0,0 +1,748 @@
+===========================
+The Linux-USB Host Side API
+===========================
+
+Introduction to USB on Linux
+============================
+
+A Universal Serial Bus (USB) is used to connect a host, such as a PC or
+workstation, to a number of peripheral devices. USB uses a tree
+structure, with the host as the root (the system's master), hubs as
+interior nodes, and peripherals as leaves (and slaves). Modern PCs
+support several such trees of USB devices, usually
+a few USB 3.0 (5 GBit/s) or USB 3.1 (10 GBit/s) and some legacy
+USB 2.0 (480 MBit/s) busses just in case.
+
+That master/slave asymmetry was designed-in for a number of reasons, one
+being ease of use. It is not physically possible to mistake upstream and
+downstream or it does not matter with a type C plug (or they are built into the
+peripheral). Also, the host software doesn't need to deal with
+distributed auto-configuration since the pre-designated master node
+manages all that.
+
+Kernel developers added USB support to Linux early in the 2.2 kernel
+series and have been developing it further since then. Besides support
+for each new generation of USB, various host controllers gained support,
+new drivers for peripherals have been added and advanced features for latency
+measurement and improved power management introduced.
+
+Linux can run inside USB devices as well as on the hosts that control
+the devices. But USB device drivers running inside those peripherals
+don't do the same things as the ones running inside hosts, so they've
+been given a different name: *gadget drivers*. This document does not
+cover gadget drivers.
+
+USB Host-Side API Model
+=======================
+
+Host-side drivers for USB devices talk to the "usbcore" APIs. There are
+two. One is intended for *general-purpose* drivers (exposed through
+driver frameworks), and the other is for drivers that are *part of the
+core*. Such core drivers include the *hub* driver (which manages trees
+of USB devices) and several different kinds of *host controller
+drivers*, which control individual busses.
+
+The device model seen by USB drivers is relatively complex.
+
+- USB supports four kinds of data transfers (control, bulk, interrupt,
+ and isochronous). Two of them (control and bulk) use bandwidth as
+ it's available, while the other two (interrupt and isochronous) are
+ scheduled to provide guaranteed bandwidth.
+
+- The device description model includes one or more "configurations"
+ per device, only one of which is active at a time. Devices are supposed
+ to be capable of operating at lower than their top
+ speeds and may provide a BOS descriptor showing the lowest speed they
+ remain fully operational at.
+
+- From USB 3.0 on configurations have one or more "functions", which
+ provide a common functionality and are grouped together for purposes
+ of power management.
+
+- Configurations or functions have one or more "interfaces", each of which may have
+ "alternate settings". Interfaces may be standardized by USB "Class"
+ specifications, or may be specific to a vendor or device.
+
+ USB device drivers actually bind to interfaces, not devices. Think of
+ them as "interface drivers", though you may not see many devices
+ where the distinction is important. *Most USB devices are simple,
+ with only one function, one configuration, one interface, and one alternate
+ setting.*
+
+- Interfaces have one or more "endpoints", each of which supports one
+ type and direction of data transfer such as "bulk out" or "interrupt
+ in". The entire configuration may have up to sixteen endpoints in
+ each direction, allocated as needed among all the interfaces.
+
+- Data transfer on USB is packetized; each endpoint has a maximum
+ packet size. Drivers must often be aware of conventions such as
+ flagging the end of bulk transfers using "short" (including zero
+ length) packets.
+
+- The Linux USB API supports synchronous calls for control and bulk
+ messages. It also supports asynchronous calls for all kinds of data
+ transfer, using request structures called "URBs" (USB Request
+ Blocks).
+
+Accordingly, the USB Core API exposed to device drivers covers quite a
+lot of territory. You'll probably need to consult the USB 3.0
+specification, available online from www.usb.org at no cost, as well as
+class or device specifications.
+
+The only host-side drivers that actually touch hardware (reading/writing
+registers, handling IRQs, and so on) are the HCDs. In theory, all HCDs
+provide the same functionality through the same API. In practice, that's
+becoming more true, but there are still differences
+that crop up especially with fault handling on the less common controllers.
+Different controllers don't
+necessarily report the same aspects of failures, and recovery from
+faults (including software-induced ones like unlinking an URB) isn't yet
+fully consistent. Device driver authors should make a point of doing
+disconnect testing (while the device is active) with each different host
+controller driver, to make sure drivers don't have bugs of their own as
+well as to make sure they aren't relying on some HCD-specific behavior.
+
+USB-Standard Types
+==================
+
+In ``<linux/usb/ch9.h>`` you will find the USB data types defined in
+chapter 9 of the USB specification. These data types are used throughout
+USB, and in APIs including this host side API, gadget APIs, and usbfs.
+
+.. kernel-doc:: include/linux/usb/ch9.h
+ :internal:
+
+Host-Side Data Types and Macros
+===============================
+
+The host side API exposes several layers to drivers, some of which are
+more necessary than others. These support lifecycle models for host side
+drivers and devices, and support passing buffers through usbcore to some
+HCD that performs the I/O for the device driver.
+
+.. kernel-doc:: include/linux/usb.h
+ :internal:
+
+USB Core APIs
+=============
+
+There are two basic I/O models in the USB API. The most elemental one is
+asynchronous: drivers submit requests in the form of an URB, and the
+URB's completion callback handles the next step. All USB transfer types
+support that model, although there are special cases for control URBs
+(which always have setup and status stages, but may not have a data
+stage) and isochronous URBs (which allow large packets and include
+per-packet fault reports). Built on top of that is synchronous API
+support, where a driver calls a routine that allocates one or more URBs,
+submits them, and waits until they complete. There are synchronous
+wrappers for single-buffer control and bulk transfers (which are awkward
+to use in some driver disconnect scenarios), and for scatterlist based
+streaming i/o (bulk or interrupt).
+
+USB drivers need to provide buffers that can be used for DMA, although
+they don't necessarily need to provide the DMA mapping themselves. There
+are APIs to use used when allocating DMA buffers, which can prevent use
+of bounce buffers on some systems. In some cases, drivers may be able to
+rely on 64bit DMA to eliminate another kind of bounce buffer.
+
+.. kernel-doc:: drivers/usb/core/urb.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/message.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/file.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/driver.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/usb.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/hub.c
+ :export:
+
+Host Controller APIs
+====================
+
+These APIs are only for use by host controller drivers, most of which
+implement standard register interfaces such as XHCI, EHCI, OHCI, or UHCI. UHCI
+was one of the first interfaces, designed by Intel and also used by VIA;
+it doesn't do much in hardware. OHCI was designed later, to have the
+hardware do more work (bigger transfers, tracking protocol state, and so
+on). EHCI was designed with USB 2.0; its design has features that
+resemble OHCI (hardware does much more work) as well as UHCI (some parts
+of ISO support, TD list processing). XHCI was designed with USB 3.0. It
+continues to shift support for functionality into hardware.
+
+There are host controllers other than the "big three", although most PCI
+based controllers (and a few non-PCI based ones) use one of those
+interfaces. Not all host controllers use DMA; some use PIO, and there is
+also a simulator and a virtual host controller to pipe USB over the network.
+
+The same basic APIs are available to drivers for all those controllers.
+For historical reasons they are in two layers: :c:type:`struct
+usb_bus <usb_bus>` is a rather thin layer that became available
+in the 2.2 kernels, while :c:type:`struct usb_hcd <usb_hcd>`
+is a more featureful layer
+that lets HCDs share common code, to shrink driver size and
+significantly reduce hcd-specific behaviors.
+
+.. kernel-doc:: drivers/usb/core/hcd.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/hcd-pci.c
+ :export:
+
+.. kernel-doc:: drivers/usb/core/buffer.c
+ :internal:
+
+The USB Filesystem (usbfs)
+==========================
+
+This chapter presents the Linux *usbfs*. You may prefer to avoid writing
+new kernel code for your USB driver; that's the problem that usbfs set
+out to solve. User mode device drivers are usually packaged as
+applications or libraries, and may use usbfs through some programming
+library that wraps it. Such libraries include
+`libusb <http://libusb.sourceforge.net>`__ for C/C++, and
+`jUSB <http://jUSB.sourceforge.net>`__ for Java.
+
+ **Note**
+
+ This particular documentation is incomplete, especially with respect
+ to the asynchronous mode. As of kernel 2.5.66 the code and this
+ (new) documentation need to be cross-reviewed.
+
+Configure usbfs into Linux kernels by enabling the *USB filesystem*
+option (CONFIG_USB_DEVICEFS), and you get basic support for user mode
+USB device drivers. Until relatively recently it was often (confusingly)
+called *usbdevfs* although it wasn't solving what *devfs* was. Every USB
+device will appear in usbfs, regardless of whether or not it has a
+kernel driver.
+
+What files are in "usbfs"?
+--------------------------
+
+Conventionally mounted at ``/proc/bus/usb``, usbfs features include:
+
+- ``/proc/bus/usb/devices`` ... a text file showing each of the USB
+ devices on known to the kernel, and their configuration descriptors.
+ You can also poll() this to learn about new devices.
+
+- ``/proc/bus/usb/BBB/DDD`` ... magic files exposing the each device's
+ configuration descriptors, and supporting a series of ioctls for
+ making device requests, including I/O to devices. (Purely for access
+ by programs.)
+
+Each bus is given a number (BBB) based on when it was enumerated; within
+each bus, each device is given a similar number (DDD). Those BBB/DDD
+paths are not "stable" identifiers; expect them to change even if you
+always leave the devices plugged in to the same hub port. *Don't even
+think of saving these in application configuration files.* Stable
+identifiers are available, for user mode applications that want to use
+them. HID and networking devices expose these stable IDs, so that for
+example you can be sure that you told the right UPS to power down its
+second server. "usbfs" doesn't (yet) expose those IDs.
+
+Mounting and Access Control
+---------------------------
+
+There are a number of mount options for usbfs, which will be of most
+interest to you if you need to override the default access control
+policy. That policy is that only root may read or write device files
+(``/proc/bus/BBB/DDD``) although anyone may read the ``devices`` or
+``drivers`` files. I/O requests to the device also need the
+CAP_SYS_RAWIO capability,
+
+The significance of that is that by default, all user mode device
+drivers need super-user privileges. You can change modes or ownership in
+a driver setup when the device hotplugs, or maye just start the driver
+right then, as a privileged server (or some activity within one). That's
+the most secure approach for multi-user systems, but for single user
+systems ("trusted" by that user) it's more convenient just to grant
+everyone all access (using the *devmode=0666* option) so the driver can
+start whenever it's needed.
+
+The mount options for usbfs, usable in /etc/fstab or in command line
+invocations of *mount*, are:
+
+*busgid*\ =NNNNN
+ Controls the GID used for the /proc/bus/usb/BBB directories.
+ (Default: 0)
+
+*busmode*\ =MMM
+ Controls the file mode used for the /proc/bus/usb/BBB directories.
+ (Default: 0555)
+
+*busuid*\ =NNNNN
+ Controls the UID used for the /proc/bus/usb/BBB directories.
+ (Default: 0)
+
+*devgid*\ =NNNNN
+ Controls the GID used for the /proc/bus/usb/BBB/DDD files. (Default:
+ 0)
+
+*devmode*\ =MMM
+ Controls the file mode used for the /proc/bus/usb/BBB/DDD files.
+ (Default: 0644)
+
+*devuid*\ =NNNNN
+ Controls the UID used for the /proc/bus/usb/BBB/DDD files. (Default:
+ 0)
+
+*listgid*\ =NNNNN
+ Controls the GID used for the /proc/bus/usb/devices and drivers
+ files. (Default: 0)
+
+*listmode*\ =MMM
+ Controls the file mode used for the /proc/bus/usb/devices and
+ drivers files. (Default: 0444)
+
+*listuid*\ =NNNNN
+ Controls the UID used for the /proc/bus/usb/devices and drivers
+ files. (Default: 0)
+
+Note that many Linux distributions hard-wire the mount options for usbfs
+in their init scripts, such as ``/etc/rc.d/rc.sysinit``, rather than
+making it easy to set this per-system policy in ``/etc/fstab``.
+
+/proc/bus/usb/devices
+---------------------
+
+This file is handy for status viewing tools in user mode, which can scan
+the text format and ignore most of it. More detailed device status
+(including class and vendor status) is available from device-specific
+files. For information about the current format of this file, see the
+``Documentation/usb/proc_usb_info.txt`` file in your Linux kernel
+sources.
+
+This file, in combination with the poll() system call, can also be used
+to detect when devices are added or removed:
+
+::
+
+ int fd;
+ struct pollfd pfd;
+
+ fd = open("/proc/bus/usb/devices", O_RDONLY);
+ pfd = { fd, POLLIN, 0 };
+ for (;;) {
+ /* The first time through, this call will return immediately. */
+ poll(&pfd, 1, -1);
+
+ /* To see what's changed, compare the file's previous and current
+ contents or scan the filesystem. (Scanning is more precise.) */
+ }
+
+Note that this behavior is intended to be used for informational and
+debug purposes. It would be more appropriate to use programs such as
+udev or HAL to initialize a device or start a user-mode helper program,
+for instance.
+
+/proc/bus/usb/BBB/DDD
+---------------------
+
+Use these files in one of these basic ways:
+
+*They can be read,* producing first the device descriptor (18 bytes) and
+then the descriptors for the current configuration. See the USB 2.0 spec
+for details about those binary data formats. You'll need to convert most
+multibyte values from little endian format to your native host byte
+order, although a few of the fields in the device descriptor (both of
+the BCD-encoded fields, and the vendor and product IDs) will be
+byteswapped for you. Note that configuration descriptors include
+descriptors for interfaces, altsettings, endpoints, and maybe additional
+class descriptors.
+
+*Perform USB operations* using *ioctl()* requests to make endpoint I/O
+requests (synchronously or asynchronously) or manage the device. These
+requests need the CAP_SYS_RAWIO capability, as well as filesystem
+access permissions. Only one ioctl request can be made on one of these
+device files at a time. This means that if you are synchronously reading
+an endpoint from one thread, you won't be able to write to a different
+endpoint from another thread until the read completes. This works for
+*half duplex* protocols, but otherwise you'd use asynchronous i/o
+requests.
+
+Life Cycle of User Mode Drivers
+-------------------------------
+
+Such a driver first needs to find a device file for a device it knows
+how to handle. Maybe it was told about it because a ``/sbin/hotplug``
+event handling agent chose that driver to handle the new device. Or
+maybe it's an application that scans all the /proc/bus/usb device files,
+and ignores most devices. In either case, it should :c:func:`read()`
+all the descriptors from the device file, and check them against what it
+knows how to handle. It might just reject everything except a particular
+vendor and product ID, or need a more complex policy.
+
+Never assume there will only be one such device on the system at a time!
+If your code can't handle more than one device at a time, at least
+detect when there's more than one, and have your users choose which
+device to use.
+
+Once your user mode driver knows what device to use, it interacts with
+it in either of two styles. The simple style is to make only control
+requests; some devices don't need more complex interactions than those.
+(An example might be software using vendor-specific control requests for
+some initialization or configuration tasks, with a kernel driver for the
+rest.)
+
+More likely, you need a more complex style driver: one using non-control
+endpoints, reading or writing data and claiming exclusive use of an
+interface. *Bulk* transfers are easiest to use, but only their sibling
+*interrupt* transfers work with low speed devices. Both interrupt and
+*isochronous* transfers offer service guarantees because their bandwidth
+is reserved. Such "periodic" transfers are awkward to use through usbfs,
+unless you're using the asynchronous calls. However, interrupt transfers
+can also be used in a synchronous "one shot" style.
+
+Your user-mode driver should never need to worry about cleaning up
+request state when the device is disconnected, although it should close
+its open file descriptors as soon as it starts seeing the ENODEV errors.
+
+The ioctl() Requests
+--------------------
+
+To use these ioctls, you need to include the following headers in your
+userspace program:
+
+::
+
+ #include <linux/usb.h>
+ #include <linux/usbdevice_fs.h>
+ #include <asm/byteorder.h>
+
+The standard USB device model requests, from "Chapter 9" of the USB 2.0
+specification, are automatically included from the ``<linux/usb/ch9.h>``
+header.
+
+Unless noted otherwise, the ioctl requests described here will update
+the modification time on the usbfs file to which they are applied
+(unless they fail). A return of zero indicates success; otherwise, a
+standard USB error code is returned. (These are documented in
+``Documentation/usb/error-codes.txt`` in your kernel sources.)
+
+Each of these files multiplexes access to several I/O streams, one per
+endpoint. Each device has one control endpoint (endpoint zero) which
+supports a limited RPC style RPC access. Devices are configured by
+hub_wq (in the kernel) setting a device-wide *configuration* that
+affects things like power consumption and basic functionality. The
+endpoints are part of USB *interfaces*, which may have *altsettings*
+affecting things like which endpoints are available. Many devices only
+have a single configuration and interface, so drivers for them will
+ignore configurations and altsettings.
+
+Management/Status Requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A number of usbfs requests don't deal very directly with device I/O.
+They mostly relate to device management and status. These are all
+synchronous requests.
+
+USBDEVFS_CLAIMINTERFACE
+ This is used to force usbfs to claim a specific interface, which has
+ not previously been claimed by usbfs or any other kernel driver. The
+ ioctl parameter is an integer holding the number of the interface
+ (bInterfaceNumber from descriptor).
+
+ Note that if your driver doesn't claim an interface before trying to
+ use one of its endpoints, and no other driver has bound to it, then
+ the interface is automatically claimed by usbfs.
+
+ This claim will be released by a RELEASEINTERFACE ioctl, or by
+ closing the file descriptor. File modification time is not updated
+ by this request.
+
+USBDEVFS_CONNECTINFO
+ Says whether the device is lowspeed. The ioctl parameter points to a
+ structure like this:
+
+ ::
+
+ struct usbdevfs_connectinfo {
+ unsigned int devnum;
+ unsigned char slow;
+ };
+
+ File modification time is not updated by this request.
+
+ *You can't tell whether a "not slow" device is connected at high
+ speed (480 MBit/sec) or just full speed (12 MBit/sec).* You should
+ know the devnum value already, it's the DDD value of the device file
+ name.
+
+USBDEVFS_GETDRIVER
+ Returns the name of the kernel driver bound to a given interface (a
+ string). Parameter is a pointer to this structure, which is
+ modified:
+
+ ::
+
+ struct usbdevfs_getdriver {
+ unsigned int interface;
+ char driver[USBDEVFS_MAXDRIVERNAME + 1];
+ };
+
+ File modification time is not updated by this request.
+
+USBDEVFS_IOCTL
+ Passes a request from userspace through to a kernel driver that has
+ an ioctl entry in the *struct usb_driver* it registered.
+
+ ::
+
+ struct usbdevfs_ioctl {
+ int ifno;
+ int ioctl_code;
+ void *data;
+ };
+
+ /* user mode call looks like this.
+ * 'request' becomes the driver->ioctl() 'code' parameter.
+ * the size of 'param' is encoded in 'request', and that data
+ * is copied to or from the driver->ioctl() 'buf' parameter.
+ */
+ static int
+ usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
+ {
+ struct usbdevfs_ioctl wrapper;
+
+ wrapper.ifno = ifno;
+ wrapper.ioctl_code = request;
+ wrapper.data = param;
+
+ return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
+ }
+
+ File modification time is not updated by this request.
+
+ This request lets kernel drivers talk to user mode code through
+ filesystem operations even when they don't create a character or
+ block special device. It's also been used to do things like ask
+ devices what device special file should be used. Two pre-defined
+ ioctls are used to disconnect and reconnect kernel drivers, so that
+ user mode code can completely manage binding and configuration of
+ devices.
+
+USBDEVFS_RELEASEINTERFACE
+ This is used to release the claim usbfs made on interface, either
+ implicitly or because of a USBDEVFS_CLAIMINTERFACE call, before the
+ file descriptor is closed. The ioctl parameter is an integer holding
+ the number of the interface (bInterfaceNumber from descriptor); File
+ modification time is not updated by this request.
+
+ **Warning**
+
+ *No security check is made to ensure that the task which made
+ the claim is the one which is releasing it. This means that user
+ mode driver may interfere other ones.*
+
+USBDEVFS_RESETEP
+ Resets the data toggle value for an endpoint (bulk or interrupt) to
+ DATA0. The ioctl parameter is an integer endpoint number (1 to 15,
+ as identified in the endpoint descriptor), with USB_DIR_IN added
+ if the device's endpoint sends data to the host.
+
+ **Warning**
+
+ *Avoid using this request. It should probably be removed.* Using
+ it typically means the device and driver will lose toggle
+ synchronization. If you really lost synchronization, you likely
+ need to completely handshake with the device, using a request
+ like CLEAR_HALT or SET_INTERFACE.
+
+USBDEVFS_DROP_PRIVILEGES
+ This is used to relinquish the ability to do certain operations
+ which are considered to be privileged on a usbfs file descriptor.
+ This includes claiming arbitrary interfaces, resetting a device on
+ which there are currently claimed interfaces from other users, and
+ issuing USBDEVFS_IOCTL calls. The ioctl parameter is a 32 bit mask
+ of interfaces the user is allowed to claim on this file descriptor.
+ You may issue this ioctl more than one time to narrow said mask.
+
+Synchronous I/O Support
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Synchronous requests involve the kernel blocking until the user mode
+request completes, either by finishing successfully or by reporting an
+error. In most cases this is the simplest way to use usbfs, although as
+noted above it does prevent performing I/O to more than one endpoint at
+a time.
+
+USBDEVFS_BULK
+ Issues a bulk read or write request to the device. The ioctl
+ parameter is a pointer to this structure:
+
+ ::
+
+ struct usbdevfs_bulktransfer {
+ unsigned int ep;
+ unsigned int len;
+ unsigned int timeout; /* in milliseconds */
+ void *data;
+ };
+
+ The "ep" value identifies a bulk endpoint number (1 to 15, as
+ identified in an endpoint descriptor), masked with USB_DIR_IN when
+ referring to an endpoint which sends data to the host from the
+ device. The length of the data buffer is identified by "len"; Recent
+ kernels support requests up to about 128KBytes. *FIXME say how read
+ length is returned, and how short reads are handled.*.
+
+USBDEVFS_CLEAR_HALT
+ Clears endpoint halt (stall) and resets the endpoint toggle. This is
+ only meaningful for bulk or interrupt endpoints. The ioctl parameter
+ is an integer endpoint number (1 to 15, as identified in an endpoint
+ descriptor), masked with USB_DIR_IN when referring to an endpoint
+ which sends data to the host from the device.
+
+ Use this on bulk or interrupt endpoints which have stalled,
+ returning *-EPIPE* status to a data transfer request. Do not issue
+ the control request directly, since that could invalidate the host's
+ record of the data toggle.
+
+USBDEVFS_CONTROL
+ Issues a control request to the device. The ioctl parameter points
+ to a structure like this:
+
+ ::
+
+ struct usbdevfs_ctrltransfer {
+ __u8 bRequestType;
+ __u8 bRequest;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+ __u32 timeout; /* in milliseconds */
+ void *data;
+ };
+
+ The first eight bytes of this structure are the contents of the
+ SETUP packet to be sent to the device; see the USB 2.0 specification
+ for details. The bRequestType value is composed by combining a
+ USB_TYPE_\* value, a USB_DIR_\* value, and a USB_RECIP_\*
+ value (from *<linux/usb.h>*). If wLength is nonzero, it describes
+ the length of the data buffer, which is either written to the device
+ (USB_DIR_OUT) or read from the device (USB_DIR_IN).
+
+ At this writing, you can't transfer more than 4 KBytes of data to or
+ from a device; usbfs has a limit, and some host controller drivers
+ have a limit. (That's not usually a problem.) *Also* there's no way
+ to say it's not OK to get a short read back from the device.
+
+USBDEVFS_RESET
+ Does a USB level device reset. The ioctl parameter is ignored. After
+ the reset, this rebinds all device interfaces. File modification
+ time is not updated by this request.
+
+ **Warning**
+
+ *Avoid using this call* until some usbcore bugs get fixed, since
+ it does not fully synchronize device, interface, and driver (not
+ just usbfs) state.
+
+USBDEVFS_SETINTERFACE
+ Sets the alternate setting for an interface. The ioctl parameter is
+ a pointer to a structure like this:
+
+ ::
+
+ struct usbdevfs_setinterface {
+ unsigned int interface;
+ unsigned int altsetting;
+ };
+
+ File modification time is not updated by this request.
+
+ Those struct members are from some interface descriptor applying to
+ the current configuration. The interface number is the
+ bInterfaceNumber value, and the altsetting number is the
+ bAlternateSetting value. (This resets each endpoint in the
+ interface.)
+
+USBDEVFS_SETCONFIGURATION
+ Issues the :c:func:`usb_set_configuration()` call for the
+ device. The parameter is an integer holding the number of a
+ configuration (bConfigurationValue from descriptor). File
+ modification time is not updated by this request.
+
+ **Warning**
+
+ *Avoid using this call* until some usbcore bugs get fixed, since
+ it does not fully synchronize device, interface, and driver (not
+ just usbfs) state.
+
+Asynchronous I/O Support
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+As mentioned above, there are situations where it may be important to
+initiate concurrent operations from user mode code. This is particularly
+important for periodic transfers (interrupt and isochronous), but it can
+be used for other kinds of USB requests too. In such cases, the
+asynchronous requests described here are essential. Rather than
+submitting one request and having the kernel block until it completes,
+the blocking is separate.
+
+These requests are packaged into a structure that resembles the URB used
+by kernel device drivers. (No POSIX Async I/O support here, sorry.) It
+identifies the endpoint type (USBDEVFS_URB_TYPE_\*), endpoint
+(number, masked with USB_DIR_IN as appropriate), buffer and length,
+and a user "context" value serving to uniquely identify each request.
+(It's usually a pointer to per-request data.) Flags can modify requests
+(not as many as supported for kernel drivers).
+
+Each request can specify a realtime signal number (between SIGRTMIN and
+SIGRTMAX, inclusive) to request a signal be sent when the request
+completes.
+
+When usbfs returns these urbs, the status value is updated, and the
+buffer may have been modified. Except for isochronous transfers, the
+actual_length is updated to say how many bytes were transferred; if the
+USBDEVFS_URB_DISABLE_SPD flag is set ("short packets are not OK"), if
+fewer bytes were read than were requested then you get an error report.
+
+::
+
+ struct usbdevfs_iso_packet_desc {
+ unsigned int length;
+ unsigned int actual_length;
+ unsigned int status;
+ };
+
+ struct usbdevfs_urb {
+ unsigned char type;
+ unsigned char endpoint;
+ int status;
+ unsigned int flags;
+ void *buffer;
+ int buffer_length;
+ int actual_length;
+ int start_frame;
+ int number_of_packets;
+ int error_count;
+ unsigned int signr;
+ void *usercontext;
+ struct usbdevfs_iso_packet_desc iso_frame_desc[];
+ };
+
+For these asynchronous requests, the file modification time reflects
+when the request was initiated. This contrasts with their use with the
+synchronous requests, where it reflects when requests complete.
+
+USBDEVFS_DISCARDURB
+ *TBS* File modification time is not updated by this request.
+
+USBDEVFS_DISCSIGNAL
+ *TBS* File modification time is not updated by this request.
+
+USBDEVFS_REAPURB
+ *TBS* File modification time is not updated by this request.
+
+USBDEVFS_REAPURBNDELAY
+ *TBS* File modification time is not updated by this request.
+
+USBDEVFS_SUBMITURB
+ *TBS*
diff --git a/Documentation/vme_api.txt b/Documentation/driver-api/vme.rst
index 90006550f485..89776fb3c8bd 100644
--- a/Documentation/vme_api.txt
+++ b/Documentation/driver-api/vme.rst
@@ -1,13 +1,15 @@
- VME Device Driver API
- =====================
+VME Device Drivers
+==================
Driver registration
-===================
+-------------------
As with other subsystems within the Linux kernel, VME device drivers register
with the VME subsystem, typically called from the devices init routine. This is
achieved via a call to the following function:
+.. code-block:: c
+
int vme_register_driver (struct vme_driver *driver, unsigned int ndevs);
If driver registration is successful this function returns zero, if an error
@@ -17,6 +19,8 @@ A pointer to a structure of type 'vme_driver' must be provided to the
registration function. Along with ndevs, which is the number of devices your
driver is able to support. The structure is as follows:
+.. code-block:: c
+
struct vme_driver {
struct list_head node;
const char *name;
@@ -38,6 +42,8 @@ with the driver. The match function should return 1 if a device should be
probed and 0 otherwise. This example match function (from vme_user.c) limits
the number of devices probed to one:
+.. code-block:: c
+
#define USER_BUS_MAX 1
...
static int vme_user_match(struct vme_dev *vdev)
@@ -51,6 +57,8 @@ The '.probe' element should contain a pointer to the probe routine. The
probe routine is passed a 'struct vme_dev' pointer as an argument. The
'struct vme_dev' structure looks like the following:
+.. code-block:: c
+
struct vme_dev {
int num;
struct vme_bridge *bridge;
@@ -66,11 +74,13 @@ dev->bridge->num.
A function is also provided to unregister the driver from the VME core and is
usually called from the device driver's exit routine:
+.. code-block:: c
+
void vme_unregister_driver (struct vme_driver *driver);
Resource management
-===================
+-------------------
Once a driver has registered with the VME core the provided match routine will
be called the number of times specified during the registration. If a match
@@ -86,6 +96,8 @@ specific window or DMA channel (which may be used by a different driver) this
driver allows a resource to be assigned based on the required attributes of the
driver in question:
+.. code-block:: c
+
struct vme_resource * vme_master_request(struct vme_dev *dev,
u32 aspace, u32 cycle, u32 width);
@@ -112,6 +124,8 @@ Functions are also provided to free window allocations once they are no longer
required. These functions should be passed the pointer to the resource provided
during resource allocation:
+.. code-block:: c
+
void vme_master_free(struct vme_resource *res);
void vme_slave_free(struct vme_resource *res);
@@ -120,7 +134,7 @@ during resource allocation:
Master windows
-==============
+--------------
Master windows provide access from the local processor[s] out onto the VME bus.
The number of windows available and the available access modes is dependent on
@@ -128,11 +142,13 @@ the underlying chipset. A window must be configured before it can be used.
Master window configuration
----------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once a master window has been assigned the following functions can be used to
configure it and retrieve the current settings:
+.. code-block:: c
+
int vme_master_set (struct vme_resource *res, int enabled,
unsigned long long base, unsigned long long size, u32 aspace,
u32 cycle, u32 width);
@@ -149,11 +165,13 @@ These functions return 0 on success or an error code should the call fail.
Master window access
---------------------
+~~~~~~~~~~~~~~~~~~~~
The following functions can be used to read from and write to configured master
windows. These functions return the number of bytes copied:
+.. code-block:: c
+
ssize_t vme_master_read(struct vme_resource *res, void *buf,
size_t count, loff_t offset);
@@ -164,6 +182,8 @@ In addition to simple reads and writes, a function is provided to do a
read-modify-write transaction. This function returns the original value of the
VME bus location :
+.. code-block:: c
+
unsigned int vme_master_rmw (struct vme_resource *res,
unsigned int mask, unsigned int compare, unsigned int swap,
loff_t offset);
@@ -175,12 +195,14 @@ the value of swap is written the specified offset.
Parts of a VME window can be mapped into user space memory using the following
function:
+.. code-block:: c
+
int vme_master_mmap(struct vme_resource *resource,
struct vm_area_struct *vma)
Slave windows
-=============
+-------------
Slave windows provide devices on the VME bus access into mapped portions of the
local memory. The number of windows available and the access modes that can be
@@ -189,11 +211,13 @@ it can be used.
Slave window configuration
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
Once a slave window has been assigned the following functions can be used to
configure it and retrieve the current settings:
+.. code-block:: c
+
int vme_slave_set (struct vme_resource *res, int enabled,
unsigned long long base, unsigned long long size,
dma_addr_t mem, u32 aspace, u32 cycle);
@@ -210,13 +234,15 @@ These functions return 0 on success or an error code should the call fail.
Slave window buffer allocation
-------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions are provided to allow the user to allocate and free a contiguous
buffers which will be accessible by the VME bridge. These functions do not have
to be used, other methods can be used to allocate a buffer, though care must be
taken to ensure that they are contiguous and accessible by the VME bridge:
+.. code-block:: c
+
void * vme_alloc_consistent(struct vme_resource *res, size_t size,
dma_addr_t *mem);
@@ -225,14 +251,14 @@ taken to ensure that they are contiguous and accessible by the VME bridge:
Slave window access
--------------------
+~~~~~~~~~~~~~~~~~~~
Slave windows map local memory onto the VME bus, the standard methods for
accessing memory should be used.
DMA channels
-============
+------------
The VME DMA transfer provides the ability to run link-list DMA transfers. The
API introduces the concept of DMA lists. Each DMA list is a link-list which can
@@ -241,29 +267,35 @@ executed, reused and destroyed.
List Management
----------------
+~~~~~~~~~~~~~~~
The following functions are provided to create and destroy DMA lists. Execution
of a list will not automatically destroy the list, thus enabling a list to be
reused for repetitive tasks:
+.. code-block:: c
+
struct vme_dma_list *vme_new_dma_list(struct vme_resource *res);
int vme_dma_list_free(struct vme_dma_list *list);
List Population
----------------
+~~~~~~~~~~~~~~~
An item can be added to a list using the following function ( the source and
destination attributes need to be created before calling this function, this is
covered under "Transfer Attributes"):
+.. code-block:: c
+
int vme_dma_list_add(struct vme_dma_list *list,
struct vme_dma_attr *src, struct vme_dma_attr *dest,
size_t count);
-NOTE: The detailed attributes of the transfers source and destination
+.. note::
+
+ The detailed attributes of the transfers source and destination
are not checked until an entry is added to a DMA list, the request
for a DMA channel purely checks the directions in which the
controller is expected to transfer data. As a result it is
@@ -271,7 +303,7 @@ NOTE: The detailed attributes of the transfers source and destination
source or destination is in an unsupported VME address space.
Transfer Attributes
--------------------
+~~~~~~~~~~~~~~~~~~~
The attributes for the source and destination are handled separately from adding
an item to a list. This is due to the diverse attributes required for each type
@@ -280,33 +312,43 @@ and pattern sources and destinations (where appropriate):
Pattern source:
+.. code-block:: c
+
struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type);
PCI source or destination:
+.. code-block:: c
+
struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem);
VME source or destination:
+.. code-block:: c
+
struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base,
u32 aspace, u32 cycle, u32 width);
The following function should be used to free an attribute:
+.. code-block:: c
+
void vme_dma_free_attribute(struct vme_dma_attr *attr);
List Execution
---------------
+~~~~~~~~~~~~~~
The following function queues a list for execution. The function will return
once the list has been executed:
+.. code-block:: c
+
int vme_dma_list_exec(struct vme_dma_list *list);
Interrupts
-==========
+----------
The VME API provides functions to attach and detach callbacks to specific VME
level and status ID combinations and for the generation of VME interrupts with
@@ -314,13 +356,15 @@ specific VME level and status IDs.
Attaching Interrupt Handlers
-----------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following functions can be used to attach and free a specific VME level and
status ID combination. Any given combination can only be assigned a single
callback function. A void pointer parameter is provided, the value of which is
passed to the callback function, the use of this pointer is user undefined:
+.. code-block:: c
+
int vme_irq_request(struct vme_dev *dev, int level, int statid,
void (*callback)(int, int, void *), void *priv);
@@ -329,31 +373,37 @@ passed to the callback function, the use of this pointer is user undefined:
The callback parameters are as follows. Care must be taken in writing a callback
function, callback functions run in interrupt context:
+.. code-block:: c
+
void callback(int level, int statid, void *priv);
Interrupt Generation
---------------------
+~~~~~~~~~~~~~~~~~~~~
The following function can be used to generate a VME interrupt at a given VME
level and VME status ID:
+.. code-block:: c
+
int vme_irq_generate(struct vme_dev *dev, int level, int statid);
Location monitors
-=================
+-----------------
The VME API provides the following functionality to configure the location
monitor.
Location Monitor Management
----------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following functions are provided to request the use of a block of location
monitors and to free them after they are no longer required:
+.. code-block:: c
+
struct vme_resource * vme_lm_request(struct vme_dev *dev);
void vme_lm_free(struct vme_resource * res);
@@ -362,15 +412,19 @@ Each block may provide a number of location monitors, monitoring adjacent
locations. The following function can be used to determine how many locations
are provided:
+.. code-block:: c
+
int vme_lm_count(struct vme_resource * res);
Location Monitor Configuration
-------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once a bank of location monitors has been allocated, the following functions
are provided to configure the location and mode of the location monitor:
+.. code-block:: c
+
int vme_lm_set(struct vme_resource *res, unsigned long long base,
u32 aspace, u32 cycle);
@@ -379,12 +433,14 @@ are provided to configure the location and mode of the location monitor:
Location Monitor Use
---------------------
+~~~~~~~~~~~~~~~~~~~~
The following functions allow a callback to be attached and detached from each
location monitor location. Each location monitor can monitor a number of
adjacent locations:
+.. code-block:: c
+
int vme_lm_attach(struct vme_resource *res, int num,
void (*callback)(void *));
@@ -392,22 +448,27 @@ adjacent locations:
The callback function is declared as follows.
+.. code-block:: c
+
void callback(void *data);
Slot Detection
-==============
+--------------
This function returns the slot ID of the provided bridge.
+.. code-block:: c
+
int vme_slot_num(struct vme_dev *dev);
Bus Detection
-=============
+-------------
This function returns the bus ID of the provided bridge.
- int vme_bus_num(struct vme_dev *dev);
+.. code-block:: c
+ int vme_bus_num(struct vme_dev *dev);
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 167070895498..ca9d1eb46bc0 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -332,6 +332,10 @@ MEM
MFD
devm_mfd_add_devices()
+PER-CPU MEM
+ devm_alloc_percpu()
+ devm_free_percpu()
+
PCI
pcim_enable_device() : after success, all PCI ops become managed
pcim_pin_device() : keep PCI device enabled after release
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
deleted file mode 100644
index 9417871b8758..000000000000
--- a/Documentation/dynamic-debug-howto.txt
+++ /dev/null
@@ -1,340 +0,0 @@
-
-Introduction
-============
-
-This document describes how to use the dynamic debug (dyndbg) feature.
-
-Dynamic debug is designed to allow you to dynamically enable/disable
-kernel code to obtain additional kernel information. Currently, if
-CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() and
-print_hex_dump_debug()/print_hex_dump_bytes() calls can be dynamically
-enabled per-callsite.
-
-If CONFIG_DYNAMIC_DEBUG is not set, print_hex_dump_debug() is just
-shortcut for print_hex_dump(KERN_DEBUG).
-
-For print_hex_dump_debug()/print_hex_dump_bytes(), format string is
-its 'prefix_str' argument, if it is constant string; or "hexdump"
-in case 'prefix_str' is build dynamically.
-
-Dynamic debug has even more useful features:
-
- * Simple query language allows turning on and off debugging
- statements by matching any combination of 0 or 1 of:
-
- - source filename
- - function name
- - line number (including ranges of line numbers)
- - module name
- - format string
-
- * Provides a debugfs control file: <debugfs>/dynamic_debug/control
- which can be read to display the complete list of known debug
- statements, to help guide you
-
-Controlling dynamic debug Behaviour
-===================================
-
-The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a
-control file in the 'debugfs' filesystem. Thus, you must first mount
-the debugfs filesystem, in order to make use of this feature.
-Subsequently, we refer to the control file as:
-<debugfs>/dynamic_debug/control. For example, if you want to enable
-printing from source file 'svcsock.c', line 1603 you simply do:
-
-nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
- <debugfs>/dynamic_debug/control
-
-If you make a mistake with the syntax, the write will fail thus:
-
-nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
- <debugfs>/dynamic_debug/control
--bash: echo: write error: Invalid argument
-
-Viewing Dynamic Debug Behaviour
-===========================
-
-You can view the currently configured behaviour of all the debug
-statements via:
-
-nullarbor:~ # cat <debugfs>/dynamic_debug/control
-# filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012"
-...
-
-
-You can also apply standard Unix text manipulation filters to this
-data, e.g.
-
-nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l
-62
-
-nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
-42
-
-The third column shows the currently enabled flags for each debug
-statement callsite (see below for definitions of the flags). The
-default value, with no flags enabled, is "=_". So you can view all
-the debug statement callsites with any non-default flags:
-
-nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
-# filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
-
-
-Command Language Reference
-==========================
-
-At the lexical level, a command comprises a sequence of words separated
-by spaces or tabs. So these are all equivalent:
-
-nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
- <debugfs>/dynamic_debug/control
-nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' >
- <debugfs>/dynamic_debug/control
-nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
- <debugfs>/dynamic_debug/control
-
-Command submissions are bounded by a write() system call.
-Multiple commands can be written together, separated by ';' or '\n'.
-
- ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \
- > <debugfs>/dynamic_debug/control
-
-If your query set is big, you can batch them too:
-
- ~# cat query-batch-file > <debugfs>/dynamic_debug/control
-
-A another way is to use wildcard. The match rule support '*' (matches
-zero or more characters) and '?' (matches exactly one character).For
-example, you can match all usb drivers:
-
- ~# echo "file drivers/usb/* +p" > <debugfs>/dynamic_debug/control
-
-At the syntactical level, a command comprises a sequence of match
-specifications, followed by a flags change specification.
-
-command ::= match-spec* flags-spec
-
-The match-spec's are used to choose a subset of the known pr_debug()
-callsites to which to apply the flags-spec. Think of them as a query
-with implicit ANDs between each pair. Note that an empty list of
-match-specs will select all debug statement callsites.
-
-A match specification comprises a keyword, which controls the
-attribute of the callsite to be compared, and a value to compare
-against. Possible keywords are:
-
-match-spec ::= 'func' string |
- 'file' string |
- 'module' string |
- 'format' string |
- 'line' line-range
-
-line-range ::= lineno |
- '-'lineno |
- lineno'-' |
- lineno'-'lineno
-// Note: line-range cannot contain space, e.g.
-// "1-30" is valid range but "1 - 30" is not.
-
-lineno ::= unsigned-int
-
-The meanings of each keyword are:
-
-func
- The given string is compared against the function name
- of each callsite. Example:
-
- func svc_tcp_accept
-
-file
- The given string is compared against either the full pathname, the
- src-root relative pathname, or the basename of the source file of
- each callsite. Examples:
-
- file svcsock.c
- file kernel/freezer.c
- file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
-
-module
- The given string is compared against the module name
- of each callsite. The module name is the string as
- seen in "lsmod", i.e. without the directory or the .ko
- suffix and with '-' changed to '_'. Examples:
-
- module sunrpc
- module nfsd
-
-format
- The given string is searched for in the dynamic debug format
- string. Note that the string does not need to match the
- entire format, only some part. Whitespace and other
- special characters can be escaped using C octal character
- escape \ooo notation, e.g. the space character is \040.
- Alternatively, the string can be enclosed in double quote
- characters (") or single quote characters (').
- Examples:
-
- format svcrdma: // many of the NFS/RDMA server pr_debugs
- format readahead // some pr_debugs in the readahead cache
- format nfsd:\040SETATTR // one way to match a format with whitespace
- format "nfsd: SETATTR" // a neater way to match a format with whitespace
- format 'nfsd: SETATTR' // yet another way to match a format with whitespace
-
-line
- The given line number or range of line numbers is compared
- against the line number of each pr_debug() callsite. A single
- line number matches the callsite line number exactly. A
- range of line numbers matches any callsite between the first
- and last line number inclusive. An empty first number means
- the first line in the file, an empty line number means the
- last number in the file. Examples:
-
- line 1603 // exactly line 1603
- line 1600-1605 // the six lines from line 1600 to line 1605
- line -1605 // the 1605 lines from line 1 to line 1605
- line 1600- // all lines from line 1600 to the end of the file
-
-The flags specification comprises a change operation followed
-by one or more flag characters. The change operation is one
-of the characters:
-
- - remove the given flags
- + add the given flags
- = set the flags to the given flags
-
-The flags are:
-
- p enables the pr_debug() callsite.
- f Include the function name in the printed message
- l Include line number in the printed message
- m Include module name in the printed message
- t Include thread ID in messages not generated from interrupt context
- _ No flags are set. (Or'd with others on input)
-
-For print_hex_dump_debug() and print_hex_dump_bytes(), only 'p' flag
-have meaning, other flags ignored.
-
-For display, the flags are preceded by '='
-(mnemonic: what the flags are currently equal to).
-
-Note the regexp ^[-+=][flmpt_]+$ matches a flags specification.
-To clear all flags at once, use "=_" or "-flmpt".
-
-
-Debug messages during Boot Process
-==================================
-
-To activate debug messages for core code and built-in modules during
-the boot process, even before userspace and debugfs exists, use
-dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY"
-(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows
-the syntax described above, but must not exceed 1023 characters. Your
-bootloader may impose lower limits.
-
-These dyndbg params are processed just after the ddebug tables are
-processed, as part of the arch_initcall. Thus you can enable debug
-messages in all code run after this arch_initcall via this boot
-parameter.
-
-On an x86 system for example ACPI enablement is a subsys_initcall and
- dyndbg="file ec.c +p"
-will show early Embedded Controller transactions during ACPI setup if
-your machine (typically a laptop) has an Embedded Controller.
-PCI (or other devices) initialization also is a hot candidate for using
-this boot parameter for debugging purposes.
-
-If foo module is not built-in, foo.dyndbg will still be processed at
-boot time, without effect, but will be reprocessed when module is
-loaded later. dyndbg_query= and bare dyndbg= are only processed at
-boot.
-
-
-Debug Messages at Module Initialization Time
-============================================
-
-When "modprobe foo" is called, modprobe scans /proc/cmdline for
-foo.params, strips "foo.", and passes them to the kernel along with
-params given in modprobe args or /etc/modprob.d/*.conf files,
-in the following order:
-
-1. # parameters given via /etc/modprobe.d/*.conf
- options foo dyndbg=+pt
- options foo dyndbg # defaults to +p
-
-2. # foo.dyndbg as given in boot args, "foo." is stripped and passed
- foo.dyndbg=" func bar +p; func buz +mp"
-
-3. # args to modprobe
- modprobe foo dyndbg==pmf # override previous settings
-
-These dyndbg queries are applied in order, with last having final say.
-This allows boot args to override or modify those from /etc/modprobe.d
-(sensible, since 1 is system wide, 2 is kernel or boot specific), and
-modprobe args to override both.
-
-In the foo.dyndbg="QUERY" form, the query must exclude "module foo".
-"foo" is extracted from the param-name, and applied to each query in
-"QUERY", and only 1 match-spec of each type is allowed.
-
-The dyndbg option is a "fake" module parameter, which means:
-
-- modules do not need to define it explicitly
-- every module gets it tacitly, whether they use pr_debug or not
-- it doesn't appear in /sys/module/$module/parameters/
- To see it, grep the control file, or inspect /proc/cmdline.
-
-For CONFIG_DYNAMIC_DEBUG kernels, any settings given at boot-time (or
-enabled by -DDEBUG flag during compilation) can be disabled later via
-the sysfs interface if the debug messages are no longer needed:
-
- echo "module module_name -p" > <debugfs>/dynamic_debug/control
-
-Examples
-========
-
-// enable the message at line 1603 of file svcsock.c
-nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
- <debugfs>/dynamic_debug/control
-
-// enable all the messages in file svcsock.c
-nullarbor:~ # echo -n 'file svcsock.c +p' >
- <debugfs>/dynamic_debug/control
-
-// enable all the messages in the NFS server module
-nullarbor:~ # echo -n 'module nfsd +p' >
- <debugfs>/dynamic_debug/control
-
-// enable all 12 messages in the function svc_process()
-nullarbor:~ # echo -n 'func svc_process +p' >
- <debugfs>/dynamic_debug/control
-
-// disable all 12 messages in the function svc_process()
-nullarbor:~ # echo -n 'func svc_process -p' >
- <debugfs>/dynamic_debug/control
-
-// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
-nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
- <debugfs>/dynamic_debug/control
-
-// enable messages in files of which the paths include string "usb"
-nullarbor:~ # echo -n '*usb* +p' > <debugfs>/dynamic_debug/control
-
-// enable all messages
-nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
-
-// add module, function to all enabled messages
-nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
-
-// boot-args example, with newlines and comments for readability
-Kernel command line: ...
- // see whats going on in dyndbg=value processing
- dynamic_debug.verbose=1
- // enable pr_debugs in 2 builtins, #cmt is stripped
- dyndbg="module params +p #cmt ; module sys +p"
- // enable pr_debugs in 2 functions in a module loaded later
- pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
diff --git a/Documentation/filesystems/locks.txt b/Documentation/filesystems/locks.txt
index 2cf81082581d..5368690f412e 100644
--- a/Documentation/filesystems/locks.txt
+++ b/Documentation/filesystems/locks.txt
@@ -19,7 +19,7 @@ forever.
This should not cause problems for anybody, since everybody using a
2.1.x kernel should have updated their C library to a suitable version
-anyway (see the file "Documentation/Changes".)
+anyway (see the file "Documentation/process/changes.rst".)
1.2 Allow Mixed Locks Again
---------------------------
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index 0b2883b17d4c..5efae00f6c7f 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -11,7 +11,7 @@ Updated 2006 by Horms <horms@verge.net.au>
In order to use a diskless system, such as an X-terminal or printer server
for example, it is necessary for the root filesystem to be present on a
non-disk device. This may be an initramfs (see Documentation/filesystems/
-ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/initrd.txt) or a
+ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/admin-guide/initrd.rst) or a
filesystem mounted via NFS. The following text describes on how to use NFS
for the root filesystem. For the rest of this text 'client' means the
diskless system, and 'server' means the NFS server.
@@ -284,7 +284,7 @@ They depend on various facilities being available:
"kernel <relative-path-below /tftpboot>". The nfsroot parameters
are passed to the kernel by adding them to the "append" line.
It is common to use serial console in conjunction with pxeliunx,
- see Documentation/serial-console.txt for more information.
+ see Documentation/admin-guide/serial-console.rst for more information.
For more information on isolinux, including how to create bootdisks
for prebuilt kernels, see http://syslinux.zytor.com/
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 74329fd0add2..72624a16b792 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -191,6 +191,7 @@ read the file /proc/PID/status:
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
+ NoNewPrivs: 0
Seccomp: 0
voluntary_ctxt_switches: 0
nonvoluntary_ctxt_switches: 1
@@ -262,6 +263,7 @@ Table 1-2: Contents of the status files (as of 4.1)
CapPrm bitmap of permitted capabilities
CapEff bitmap of effective capabilities
CapBnd bitmap of capabilities bounding set
+ NoNewPrivs no_new_privs, like prctl(PR_GET_NO_NEW_PRIV, ...)
Seccomp seccomp mode, like prctl(PR_GET_SECCOMP, ...)
Cpus_allowed mask of CPUs on which this process may run
Cpus_allowed_list Same as previous, but in "list format"
@@ -1305,7 +1307,16 @@ second). The meanings of the columns are as follows, from left to right:
- nice: niced processes executing in user mode
- system: processes executing in kernel mode
- idle: twiddling thumbs
-- iowait: waiting for I/O to complete
+- iowait: In a word, iowait stands for waiting for I/O to complete. But there
+ are several problems:
+ 1. Cpu will not wait for I/O to complete, iowait is the time that a task is
+ waiting for I/O to complete. When cpu goes into idle state for
+ outstanding task io, another task will be scheduled on this CPU.
+ 2. In a multi-core CPU, the task waiting for I/O to complete is not running
+ on any CPU, so the iowait of each CPU is difficult to calculate.
+ 3. The value of iowait field in /proc/stat will decrease in certain
+ conditions.
+ So, the iowait is not reliable by reading from /proc/stat.
- irq: servicing interrupts
- softirq: servicing softirqs
- steal: involuntary wait
diff --git a/Documentation/frv/booting.txt b/Documentation/frv/booting.txt
index 9bdf4b46e741..cd9dc1dfb144 100644
--- a/Documentation/frv/booting.txt
+++ b/Documentation/frv/booting.txt
@@ -119,7 +119,7 @@ separated by spaces:
253:0 Device with major 253 and minor 0
Authoritative information can be found in
- "Documentation/kernel-parameters.txt".
+ "Documentation/admin-guide/kernel-parameters.rst".
(*) rw
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index 368d5a294d89..747c721776ed 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -175,8 +175,8 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
the header <linux/irq.h>. So basically such a driver is utilizing two sub-
systems simultaneously: gpio and irq.
-RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
-(like PM runtime) as part of its irq_chip implementation on -RT.
+RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any
+sleepable APIs (like PM runtime) as part of its irq_chip implementation.
- spinlock_t should be replaced with raw_spinlock_t [1].
- If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
@@ -185,33 +185,32 @@ RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
GPIO irqchips usually fall in one of two categories:
* CHAINED GPIO irqchips: these are usually the type that is embedded on
- an SoC. This means that there is a fast IRQ handler for the GPIOs that
+ an SoC. This means that there is a fast IRQ flow handler for the GPIOs that
gets called in a chain from the parent IRQ handler, most typically the
- system interrupt controller. This means the GPIO irqchip is registered
- using irq_set_chained_handler() or the corresponding
- gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
- handler will be called immediately from the parent irqchip, while
- holding the IRQs disabled. The GPIO irqchip will then end up calling
- something like this sequence in its interrupt handler:
-
- static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+ system interrupt controller. This means that the GPIO irqchip handler will
+ be called immediately from the parent irqchip, while holding the IRQs
+ disabled. The GPIO irqchip will then end up calling something like this
+ sequence in its interrupt handler:
+
+ static irqreturn_t foo_gpio_irq(int irq, void *data)
chained_irq_enter(...);
generic_handle_irq(...);
chained_irq_exit(...);
Chained GPIO irqchips typically can NOT set the .can_sleep flag on
- struct gpio_chip, as everything happens directly in the callbacks.
+ struct gpio_chip, as everything happens directly in the callbacks: no
+ slow bus traffic like I2C can be used.
RT_FULL: Note, chained IRQ handlers will not be forced threaded on -RT.
As result, spinlock_t or any sleepable APIs (like PM runtime) can't be used
in chained IRQ handler.
- if required (and if it can't be converted to the nested threaded GPIO irqchip)
- - chained IRQ handler can be converted to generic irq handler and this way
- it will be threaded IRQ handler on -RT and hard IRQ handler on non-RT
+ If required (and if it can't be converted to the nested threaded GPIO irqchip)
+ a chained IRQ handler can be converted to generic irq handler and this way
+ it will be a threaded IRQ handler on -RT and a hard IRQ handler on non-RT
(for example, see [3]).
Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled,
- so IRQ core will complain if it will be called from IRQ handler which is
- forced thread. The "fake?" raw lock can be used to W/A this problem:
+ so the IRQ core will complain if it is called from an IRQ handler which is
+ forced to a thread. The "fake?" raw lock can be used to W/A this problem:
raw_spinlock_t wa_lock;
static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
@@ -243,7 +242,7 @@ GPIO irqchips usually fall in one of two categories:
by the driver. The hallmark of this driver is to call something like
this in its interrupt handler:
- static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+ static irqreturn_t foo_gpio_irq(int irq, void *data)
...
handle_nested_irq(irq);
@@ -256,23 +255,31 @@ associated irqdomain and resource allocation callbacks, the gpiolib has
some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
symbol:
-* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
+* gpiochip_irqchip_add(): adds a chained irqchip to a gpiochip. It will pass
the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
need to embed the gpio_chip in its state container and obtain a pointer
to the container using container_of().
(See Documentation/driver-model/design-patterns.txt)
- If there is a need to exclude certain GPIOs from the IRQ domain, one can
- set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
- called. This allocates .irq_valid_mask with as many bits set as there are
- GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
- mask. The mask must be filled in before gpiochip_irqchip_add() is called.
+* gpiochip_irqchip_add_nested(): adds a nested irqchip to a gpiochip.
+ Apart from that it works exactly like the chained irqchip.
* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
data. (Notice handler data, since the irqchip data is likely used by the
- parent irqchip!) This is for the chained type of chip. This is also used
- to set up a nested irqchip if NULL is passed as handler.
+ parent irqchip!).
+
+* gpiochip_set_nested_irqchip(): sets up a nested irq handler for a
+ gpio_chip from a parent IRQ. As the parent IRQ has usually been
+ explicitly requested by the driver, this does very little more than
+ mark all the child IRQs as having the other IRQ as parent.
+
+If there is a need to exclude certain GPIOs from the IRQ domain, you can
+set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
+called. This allocates an .irq_valid_mask with as many bits set as there
+are GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
+mask. The mask must be filled in before gpiochip_irqchip_add() or
+gpiochip_irqchip_add_nested() is called.
To use the helpers please keep the following in mind:
@@ -323,6 +330,9 @@ When implementing an irqchip inside a GPIO driver, these two functions should
typically be called in the .startup() and .shutdown() callbacks from the
irqchip.
+When using the gpiolib irqchip helpers, these callback are automatically
+assigned.
+
Real-Time compliance for GPIO IRQ chips
---------------------------------------
diff --git a/Documentation/gpu/conf.py b/Documentation/gpu/conf.py
index 6314d1708230..1757b040fb32 100644
--- a/Documentation/gpu/conf.py
+++ b/Documentation/gpu/conf.py
@@ -3,3 +3,8 @@
project = "Linux GPU Driver Developer's Guide"
tags.add("subproject")
+
+latex_documents = [
+ ('index', 'gpu.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 37284bcc7764..e35920db1f4c 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -143,6 +143,9 @@ Device Instance and Driver Handling
.. kernel-doc:: drivers/gpu/drm/drm_drv.c
:export:
+.. kernel-doc:: include/drm/drm_drv.h
+ :internal:
+
Driver Load
-----------
@@ -350,6 +353,23 @@ how the ioctl is allowed to be called.
.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
:export:
+
+Misc Utilities
+==============
+
+Printer
+-------
+
+.. kernel-doc:: include/drm/drm_print.h
+ :doc: print
+
+.. kernel-doc:: include/drm/drm_print.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_print.c
+ :export:
+
+
Legacy Support Code
===================
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index bb4254d19cbb..03040aa14fe8 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -63,6 +63,9 @@ Atomic State Reset and Initialization
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
:doc: atomic state reset and initialization
+Helper Functions Reference
+--------------------------
+
.. kernel-doc:: include/drm/drm_atomic_helper.h
:internal:
@@ -261,14 +264,6 @@ Plane Helper Reference
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
:export:
-Tile group
-==========
-
-# FIXME: This should probably be moved into a property documentation section
-
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
- :doc: Tile group
-
Auxiliary Modeset Helpers
=========================
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 53b872c105d2..0c9abdc0ee31 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -15,25 +15,24 @@ be setup by initializing the following fields.
- struct drm_mode_config_funcs \*funcs;
Mode setting functions.
-Modeset Base Object Abstraction
-===============================
+Mode Configuration
-.. kernel-doc:: include/drm/drm_mode_object.h
- :internal:
+KMS Core Structures and Functions
+=================================
-.. kernel-doc:: drivers/gpu/drm/drm_mode_object.c
+.. kernel-doc:: drivers/gpu/drm/drm_mode_config.c
:export:
-KMS Data Structures
-===================
-
-.. kernel-doc:: include/drm/drm_crtc.h
+.. kernel-doc:: include/drm/drm_mode_config.h
:internal:
-KMS API Functions
-=================
+Modeset Base Object Abstraction
+===============================
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+.. kernel-doc:: include/drm/drm_mode_object.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_mode_object.c
:export:
Atomic Mode Setting Function Reference
@@ -45,6 +44,15 @@ Atomic Mode Setting Function Reference
.. kernel-doc:: include/drm/drm_atomic.h
:internal:
+CRTC Abstraction
+================
+
+.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+ :export:
+
+.. kernel-doc:: include/drm/drm_crtc.h
+ :internal:
+
Frame Buffer Abstraction
========================
@@ -63,52 +71,17 @@ Frame Buffer Functions Reference
DRM Format Handling
===================
+.. kernel-doc:: include/drm/drm_fourcc.h
+ :internal:
+
.. kernel-doc:: drivers/gpu/drm/drm_fourcc.c
:export:
Dumb Buffer Objects
===================
-The KMS API doesn't standardize backing storage object creation and
-leaves it to driver-specific ioctls. Furthermore actually creating a
-buffer object even for GEM-based drivers is done through a
-driver-specific ioctl - GEM only has a common userspace interface for
-sharing and destroying objects. While not an issue for full-fledged
-graphics stacks that include device-specific userspace components (in
-libdrm for instance), this limit makes DRM-based early boot graphics
-unnecessarily complex.
-
-Dumb objects partly alleviate the problem by providing a standard API to
-create dumb buffers suitable for scanout, which can then be used to
-create KMS frame buffers.
-
-To support dumb objects drivers must implement the dumb_create,
-dumb_destroy and dumb_map_offset operations.
-
-- int (\*dumb_create)(struct drm_file \*file_priv, struct
- drm_device \*dev, struct drm_mode_create_dumb \*args);
- The dumb_create operation creates a driver object (GEM or TTM
- handle) suitable for scanout based on the width, height and depth
- from the struct :c:type:`struct drm_mode_create_dumb
- <drm_mode_create_dumb>` argument. It fills the argument's
- handle, pitch and size fields with a handle for the newly created
- object and its line pitch and size in bytes.
-
-- int (\*dumb_destroy)(struct drm_file \*file_priv, struct
- drm_device \*dev, uint32_t handle);
- The dumb_destroy operation destroys a dumb object created by
- dumb_create.
-
-- int (\*dumb_map_offset)(struct drm_file \*file_priv, struct
- drm_device \*dev, uint32_t handle, uint64_t \*offset);
- The dumb_map_offset operation associates an mmap fake offset with
- the object given by the handle and returns it. Drivers must use the
- :c:func:`drm_gem_create_mmap_offset()` function to associate
- the fake offset as described in ?.
-
-Note that dumb objects may not be used for gpu acceleration, as has been
-attempted on some ARM embedded platforms. Such drivers really must have
-a hardware-specific ioctl to allocate suitable buffer objects.
+.. kernel-doc:: drivers/gpu/drm/drm_dumb_buffers.c
+ :doc: overview
Plane Abstraction
=================
@@ -215,7 +188,7 @@ Connectors state change detection must be cleanup up with a call to
Output discovery and initialization example
-------------------------------------------
-::
+.. code-block:: c
void intel_crt_init(struct drm_device *dev)
{
@@ -287,6 +260,12 @@ Property Types and Blob Property Support
.. kernel-doc:: drivers/gpu/drm/drm_property.c
:export:
+Standard Connector Properties
+-----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+ :doc: standard connector properties
+
Plane Composition Properties
----------------------------
@@ -308,6 +287,18 @@ Color Management Properties
.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
:export:
+Tile Group Property
+-------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+ :doc: Tile group
+
+Explicit Fencing Properties
+---------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
+ :doc: explicit fencing properties
+
Existing KMS Properties
-----------------------
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index bca808535dfd..cb5daffcd6be 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -45,7 +45,7 @@ the radeon_ttm.c file for an example of usage.
The ttm_global_reference structure is made up of several fields:
-::
+.. code-block:: c
struct ttm_global_reference {
enum ttm_global_types global_type;
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 1ba301cebe16..de3ac9f90f8f 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -216,3 +216,9 @@ interfaces. Especially since all hardware-acceleration interfaces to
userspace are driver specific for efficiency and other reasons these
interfaces can be rather substantial. Hence every driver has its own
chapter.
+
+Testing and validation
+======================
+
+.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
+ :doc: CRC ABI
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 87aaffc22920..117d2ab7a5f7 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -49,6 +49,15 @@ Intel GVT-g Guest Support(vGPU)
.. kernel-doc:: drivers/gpu/drm/i915/i915_vgpu.c
:internal:
+Intel GVT-g Host Support(vGPU device model)
+-------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c
+ :doc: Intel GVT-g host support
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c
+ :internal:
+
Display Hardware Handling
=========================
@@ -180,7 +189,7 @@ Display Refresh Rate Switching (DRRS)
DPIO
----
-.. kernel-doc:: drivers/gpu/drm/i915/i915_reg.h
+.. kernel-doc:: drivers/gpu/drm/i915/intel_dpio_phy.c
:doc: DPIO
CSR firmware support for DMC
@@ -249,19 +258,19 @@ Global GTT views
GTT Fences and Swizzling
------------------------
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
:internal:
Global GTT Fence Handling
~~~~~~~~~~~~~~~~~~~~~~~~~
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
:doc: fence register handling
Hardware Tiling and Swizzling Details
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
:doc: tiling swizzling details
Object Tiling IOCTLs
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index be0dafcf5556..367d7c36b8e9 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -14,7 +14,7 @@ Linux GPU Driver Developer's Guide
vga-switcheroo
vgaarbiter
-.. only:: subproject
+.. only:: subproject and html
Indices
=======
diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches
index 57f60307accc..f88221b46153 100644
--- a/Documentation/hwmon/submitting-patches
+++ b/Documentation/hwmon/submitting-patches
@@ -10,10 +10,10 @@ increase the chances of your change being accepted.
----------
* It should be unnecessary to mention, but please read and follow
- Documentation/SubmitChecklist
- Documentation/SubmittingDrivers
- Documentation/SubmittingPatches
- Documentation/CodingStyle
+ Documentation/process/submit-checklist.rst
+ Documentation/process/submitting-drivers.rst
+ Documentation/process/submitting-patches.rst
+ Documentation/process/coding-style.rst
* Please run your patch through 'checkpatch --strict'. There should be no
errors, no warnings, and few if any check messages. If there are any
diff --git a/Documentation/index.rst b/Documentation/index.rst
index c53d089455a4..2bd8fdc9207c 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -3,21 +3,69 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
-Welcome to The Linux Kernel's documentation!
-============================================
+Welcome to The Linux Kernel's documentation
+===========================================
-Contents:
+This is the top level of the kernel's documentation tree. Kernel
+documentation, like the kernel itself, is very much a work in progress;
+that is especially true as we work to integrate our many scattered
+documents into a coherent whole. Please note that improvements to the
+documentation are welcome; join the linux-doc list at vger.kernel.org if
+you want to help out.
+
+User-oriented documentation
+---------------------------
+
+The following manuals are written for *users* of the kernel — those who are
+trying to get it to work optimally on a given system.
+
+.. toctree::
+ :maxdepth: 2
+
+ admin-guide/index
+
+Introduction to kernel development
+----------------------------------
+
+These manuals contain overall information about how to develop the kernel.
+The kernel community is quite large, with thousands of developers
+contributing over the course of a year. As with any large community,
+knowing how things are done will make the process of getting your changes
+merged much easier.
+
+.. toctree::
+ :maxdepth: 2
+
+ process/index
+ dev-tools/index
+ doc-guide/index
+
+Kernel API documentation
+------------------------
+
+These books get into the details of how specific kernel subsystems work
+from the point of view of a kernel developer. Much of the information here
+is taken directly from the kernel source, with supplemental material added
+as needed (or at least as we managed to add it — probably *not* all that is
+needed).
.. toctree::
:maxdepth: 2
- kernel-documentation
- development-process/index
- dev-tools/tools
driver-api/index
+ core-api/index
media/index
gpu/index
- 80211/index
+ security/index
+ sound/index
+
+Korean translations
+-------------------
+
+.. toctree::
+ :maxdepth: 1
+
+ translations/ko_KR/index
Indices and tables
==================
diff --git a/Documentation/isdn/README b/Documentation/isdn/README
index cfb1884342ee..32d4e80c2c03 100644
--- a/Documentation/isdn/README
+++ b/Documentation/isdn/README
@@ -332,7 +332,7 @@ README for the ISDN-subsystem
4. Device-inodes
The major and minor numbers and their names are described in
- Documentation/devices.txt. The major numbers are:
+ Documentation/admin-guide/devices.rst. The major numbers are:
43 for the ISDN-tty's.
44 for the ISDN-callout-tty's.
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 069fcb3eef6e..262722d8867b 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -113,6 +113,34 @@ applicable everywhere (see syntax).
That will limit the usefulness but on the other hand avoid
the illegal configurations all over.
+- weak reverse dependencies: "imply" <symbol> ["if" <expr>]
+ This is similar to "select" as it enforces a lower limit on another
+ symbol except that the "implied" symbol's value may still be set to n
+ from a direct dependency or with a visible prompt.
+
+ Given the following example:
+
+ config FOO
+ tristate
+ imply BAZ
+
+ config BAZ
+ tristate
+ depends on BAR
+
+ The following values are possible:
+
+ FOO BAR BAZ's default choice for BAZ
+ --- --- ------------- --------------
+ n y n N/m/y
+ m y m M/y/n
+ y y y Y/n
+ y n * N
+
+ This is useful e.g. with multiple drivers that want to indicate their
+ ability to hook into a secondary subsystem while allowing the user to
+ configure that subsystem out without also having to unset these drivers.
+
- limiting menu display: "visible if" <expr>
This attribute is only applicable to menu blocks, if the condition is
false, the menu block is not displayed to the user (the symbols
@@ -481,6 +509,7 @@ historical issues resolved through these different solutions.
b) Match dependency semantics:
b1) Swap all "select FOO" to "depends on FOO" or,
b2) Swap all "depends on FOO" to "select FOO"
+ c) Consider the use of "imply" instead of "select"
The resolution to a) can be tested with the sample Kconfig file
Documentation/kbuild/Kconfig.recursion-issue-01 through the removal
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 062e3af271b7..104740ea0041 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -1,5 +1,5 @@
NOTE: this document is outdated and will eventually be removed. See
-Documentation/kernel-documentation.rst for current information.
+Documentation/doc-guide/ for current information.
kernel-doc nano-HOWTO
=====================
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index bbc3a8b8cff4..df31e30b6a02 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -264,7 +264,7 @@ To reduce its OS jitter, do at least one of the following:
kthreads from being created in the first place.
2. Boot with "nosoftlockup=0", which will also prevent these kthreads
from being created. Other related watchdog and softlockup boot
- parameters may be found in Documentation/kernel-parameters.txt
+ parameters may be found in Documentation/admin-guide/kernel-parameters.rst
and Documentation/watchdog/watchdog-parameters.txt.
3. Echo a zero to /proc/sys/kernel/watchdog to disable the
watchdog timer.
diff --git a/Documentation/kselftest.txt b/Documentation/kselftest.txt
index 54bee77fa728..e5c7254e73d7 100644
--- a/Documentation/kselftest.txt
+++ b/Documentation/kselftest.txt
@@ -70,6 +70,17 @@ To install selftests in an user specified location:
$ cd tools/testing/selftests
$ ./kselftest_install.sh install_dir
+Running installed selftests
+===========================
+
+Kselftest install as well as the Kselftest tarball provide a script
+named "run_kselftest.sh" to run the tests.
+
+You can simply do the following to run the installed Kselftests. Please
+note some tests will require root privileges.
+
+cd kselftest
+./run_kselftest.sh
Contributing new tests
======================
diff --git a/Documentation/leds/leds-lp5523.txt b/Documentation/leds/leds-lp5523.txt
index 0dbbd279c9b9..0961a060fc4d 100644
--- a/Documentation/leds/leds-lp5523.txt
+++ b/Documentation/leds/leds-lp5523.txt
@@ -34,8 +34,8 @@ There are two ways to run LED patterns.
Control interface for the engines:
x is 1 .. 3
enginex_mode : disabled, load, run
- enginex_load : microcode load (visible only in load mode)
- enginex_leds : led mux control (visible only in load mode)
+ enginex_load : microcode load
+ enginex_leds : led mux control
cd /sys/class/leds/lp5523:channel2/device
echo "load" > engine3_mode
diff --git a/Documentation/leds/uleds.txt b/Documentation/leds/uleds.txt
new file mode 100644
index 000000000000..13e375a580f9
--- /dev/null
+++ b/Documentation/leds/uleds.txt
@@ -0,0 +1,36 @@
+Userspace LEDs
+==============
+
+The uleds driver supports userspace LEDs. This can be useful for testing
+triggers and can also be used to implement virtual LEDs.
+
+
+Usage
+=====
+
+When the driver is loaded, a character device is created at /dev/uleds. To
+create a new LED class device, open /dev/uleds and write a uleds_user_dev
+structure to it (found in kernel public header file linux/uleds.h).
+
+ #define LED_MAX_NAME_SIZE 64
+
+ struct uleds_user_dev {
+ char name[LED_MAX_NAME_SIZE];
+ };
+
+A new LED class device will be created with the name given. The name can be
+any valid sysfs device node name, but consider using the LED class naming
+convention of "devicename:color:function".
+
+The current brightness is found by reading a single byte from the character
+device. Values are unsigned: 0 to 255. Reading will block until the brightness
+changes. The device node can also be polled to notify when the brightness value
+changes.
+
+The LED class device will be removed when the open file handle to /dev/uleds
+is closed.
+
+Multiple LED class devices are created by opening additional file handles to
+/dev/uleds.
+
+See tools/leds/uledmon.c for an example userspace program.
diff --git a/Documentation/local_ops.txt b/Documentation/local_ops.txt
deleted file mode 100644
index 407576a23317..000000000000
--- a/Documentation/local_ops.txt
+++ /dev/null
@@ -1,191 +0,0 @@
- Semantics and Behavior of Local Atomic Operations
-
- Mathieu Desnoyers
-
-
- This document explains the purpose of the local atomic operations, how
-to implement them for any given architecture and shows how they can be used
-properly. It also stresses on the precautions that must be taken when reading
-those local variables across CPUs when the order of memory writes matters.
-
-Note that local_t based operations are not recommended for general kernel use.
-Please use the this_cpu operations instead unless there is really a special purpose.
-Most uses of local_t in the kernel have been replaced by this_cpu operations.
-this_cpu operations combine the relocation with the local_t like semantics in
-a single instruction and yield more compact and faster executing code.
-
-
-* Purpose of local atomic operations
-
-Local atomic operations are meant to provide fast and highly reentrant per CPU
-counters. They minimize the performance cost of standard atomic operations by
-removing the LOCK prefix and memory barriers normally required to synchronize
-across CPUs.
-
-Having fast per CPU atomic counters is interesting in many cases : it does not
-require disabling interrupts to protect from interrupt handlers and it permits
-coherent counters in NMI handlers. It is especially useful for tracing purposes
-and for various performance monitoring counters.
-
-Local atomic operations only guarantee variable modification atomicity wrt the
-CPU which owns the data. Therefore, care must taken to make sure that only one
-CPU writes to the local_t data. This is done by using per cpu data and making
-sure that we modify it from within a preemption safe context. It is however
-permitted to read local_t data from any CPU : it will then appear to be written
-out of order wrt other memory writes by the owner CPU.
-
-
-* Implementation for a given architecture
-
-It can be done by slightly modifying the standard atomic operations : only
-their UP variant must be kept. It typically means removing LOCK prefix (on
-i386 and x86_64) and any SMP synchronization barrier. If the architecture does
-not have a different behavior between SMP and UP, including asm-generic/local.h
-in your architecture's local.h is sufficient.
-
-The local_t type is defined as an opaque signed long by embedding an
-atomic_long_t inside a structure. This is made so a cast from this type to a
-long fails. The definition looks like :
-
-typedef struct { atomic_long_t a; } local_t;
-
-
-* Rules to follow when using local atomic operations
-
-- Variables touched by local ops must be per cpu variables.
-- _Only_ the CPU owner of these variables must write to them.
-- This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
- to update its local_t variables.
-- Preemption (or interrupts) must be disabled when using local ops in
- process context to make sure the process won't be migrated to a
- different CPU between getting the per-cpu variable and doing the
- actual local op.
-- When using local ops in interrupt context, no special care must be
- taken on a mainline kernel, since they will run on the local CPU with
- preemption already disabled. I suggest, however, to explicitly
- disable preemption anyway to make sure it will still work correctly on
- -rt kernels.
-- Reading the local cpu variable will provide the current copy of the
- variable.
-- Reads of these variables can be done from any CPU, because updates to
- "long", aligned, variables are always atomic. Since no memory
- synchronization is done by the writer CPU, an outdated copy of the
- variable can be read when reading some _other_ cpu's variables.
-
-
-* How to use local atomic operations
-
-#include <linux/percpu.h>
-#include <asm/local.h>
-
-static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
-
-
-* Counting
-
-Counting is done on all the bits of a signed long.
-
-In preemptible context, use get_cpu_var() and put_cpu_var() around local atomic
-operations : it makes sure that preemption is disabled around write access to
-the per cpu variable. For instance :
-
- local_inc(&get_cpu_var(counters));
- put_cpu_var(counters);
-
-If you are already in a preemption-safe context, you can use
-this_cpu_ptr() instead.
-
- local_inc(this_cpu_ptr(&counters));
-
-
-
-* Reading the counters
-
-Those local counters can be read from foreign CPUs to sum the count. Note that
-the data seen by local_read across CPUs must be considered to be out of order
-relatively to other memory writes happening on the CPU that owns the data.
-
- long sum = 0;
- for_each_online_cpu(cpu)
- sum += local_read(&per_cpu(counters, cpu));
-
-If you want to use a remote local_read to synchronize access to a resource
-between CPUs, explicit smp_wmb() and smp_rmb() memory barriers must be used
-respectively on the writer and the reader CPUs. It would be the case if you use
-the local_t variable as a counter of bytes written in a buffer : there should
-be a smp_wmb() between the buffer write and the counter increment and also a
-smp_rmb() between the counter read and the buffer read.
-
-
-Here is a sample module which implements a basic per cpu counter using local.h.
-
---- BEGIN ---
-/* test-local.c
- *
- * Sample module for local.h usage.
- */
-
-
-#include <asm/local.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-
-static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
-
-static struct timer_list test_timer;
-
-/* IPI called on each CPU. */
-static void test_each(void *info)
-{
- /* Increment the counter from a non preemptible context */
- printk("Increment on cpu %d\n", smp_processor_id());
- local_inc(this_cpu_ptr(&counters));
-
- /* This is what incrementing the variable would look like within a
- * preemptible context (it disables preemption) :
- *
- * local_inc(&get_cpu_var(counters));
- * put_cpu_var(counters);
- */
-}
-
-static void do_test_timer(unsigned long data)
-{
- int cpu;
-
- /* Increment the counters */
- on_each_cpu(test_each, NULL, 1);
- /* Read all the counters */
- printk("Counters read from CPU %d\n", smp_processor_id());
- for_each_online_cpu(cpu) {
- printk("Read : CPU %d, count %ld\n", cpu,
- local_read(&per_cpu(counters, cpu)));
- }
- del_timer(&test_timer);
- test_timer.expires = jiffies + 1000;
- add_timer(&test_timer);
-}
-
-static int __init test_init(void)
-{
- /* initialize the timer that will increment the counter */
- init_timer(&test_timer);
- test_timer.function = do_test_timer;
- test_timer.expires = jiffies + 1;
- add_timer(&test_timer);
-
- return 0;
-}
-
-static void __exit test_exit(void)
-{
- del_timer_sync(&test_timer);
-}
-
-module_init(test_init);
-module_exit(test_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("Local Atomic Ops");
---- END ---
diff --git a/Documentation/lockup-watchdogs.txt b/Documentation/lockup-watchdogs.txt
index 4a6e33e1af61..c8b8378513d6 100644
--- a/Documentation/lockup-watchdogs.txt
+++ b/Documentation/lockup-watchdogs.txt
@@ -11,7 +11,7 @@ details), without giving other tasks a chance to run. The current
stack trace is displayed upon detection and, by default, the system
will stay locked up. Alternatively, the kernel can be configured to
panic; a sysctl, "kernel.softlockup_panic", a kernel parameter,
-"softlockup_panic" (see "Documentation/kernel-parameters.txt" for
+"softlockup_panic" (see "Documentation/admin-guide/kernel-parameters.rst" for
details), and a compile option, "BOOTPARAM_SOFTLOCKUP_PANIC", are
provided for this.
@@ -23,7 +23,7 @@ upon detection and the system will stay locked up unless the default
behavior is changed, which can be done through a sysctl,
'hardlockup_panic', a compile time knob, "BOOTPARAM_HARDLOCKUP_PANIC",
and a kernel parameter, "nmi_watchdog"
-(see "Documentation/kernel-parameters.txt" for details).
+(see "Documentation/admin-guide/kernel-parameters.rst" for details).
The panic option can be used in combination with panic_timeout (this
timeout is set through the confusingly named "kernel.panic" sysctl),
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index eaf32a1fd0b1..79d21246c75a 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -139,7 +139,7 @@ follows:
PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2
Authoritative information can be found in
-"Documentation/kernel-parameters.txt".
+"Documentation/admin-guide/kernel-parameters.rst".
2.2) ro, rw
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
deleted file mode 100644
index 28befed9f610..000000000000
--- a/Documentation/magic-number.txt
+++ /dev/null
@@ -1,158 +0,0 @@
-This file is a registry of magic numbers which are in use. When you
-add a magic number to a structure, you should also add it to this
-file, since it is best if the magic numbers used by various structures
-are unique.
-
-It is a *very* good idea to protect kernel data structures with magic
-numbers. This allows you to check at run time whether (a) a structure
-has been clobbered, or (b) you've passed the wrong structure to a
-routine. This last is especially useful --- particularly when you are
-passing pointers to structures via a void * pointer. The tty code,
-for example, does this frequently to pass driver-specific and line
-discipline-specific structures back and forth.
-
-The way to use magic numbers is to declare then at the beginning of
-the structure, like so:
-
-struct tty_ldisc {
- int magic;
- ...
-};
-
-Please follow this discipline when you are adding future enhancements
-to the kernel! It has saved me countless hours of debugging,
-especially in the screwy cases where an array has been overrun and
-structures following the array have been overwritten. Using this
-discipline, these cases get detected quickly and safely.
-
- Theodore Ts'o
- 31 Mar 94
-
-The magic table is current to Linux 2.1.55.
-
- Michael Chastain
- <mailto:mec@shout.net>
- 22 Sep 1997
-
-Now it should be up to date with Linux 2.1.112. Because
-we are in feature freeze time it is very unlikely that
-something will change before 2.2.x. The entries are
-sorted by number field.
-
- Krzysztof G. Baranowski
- <mailto: kgb@knm.org.pl>
- 29 Jul 1998
-
-Updated the magic table to Linux 2.5.45. Right over the feature freeze,
-but it is possible that some new magic numbers will sneak into the
-kernel before 2.6.x yet.
-
- Petr Baudis
- <pasky@ucw.cz>
- 03 Nov 2002
-
-Updated the magic table to Linux 2.5.74.
-
- Fabian Frederick
- <ffrederick@users.sourceforge.net>
- 09 Jul 2003
-
-
-Magic Name Number Structure File
-===========================================================================
-PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h
-CMAGIC 0x0111 user include/linux/a.out.h
-MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
-HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c
-APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c
-CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
-DB_MAGIC 0x4442 fc_info drivers/net/iph5526_novram.c
-DL_MAGIC 0x444d fc_info drivers/net/iph5526_novram.c
-FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h
-FF_MAGIC 0x4646 fc_info drivers/net/iph5526_novram.c
-ISICOM_MAGIC 0x4d54 isi_port include/linux/isicom.h
-PTY_MAGIC 0x5001 drivers/char/pty.c
-PPP_MAGIC 0x5002 ppp include/linux/if_pppvar.h
-SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h
-SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h
-SLIP_MAGIC 0x5302 slip drivers/net/slip.h
-STRIP_MAGIC 0x5303 strip drivers/net/strip.c
-X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h
-SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h
-AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h
-TTY_MAGIC 0x5401 tty_struct include/linux/tty.h
-MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c
-TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h
-MGSLPC_MAGIC 0x5402 mgslpc_info drivers/char/pcmcia/synclink_cs.c
-TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h
-USB_SERIAL_MAGIC 0x6702 usb_serial drivers/usb/serial/usb-serial.h
-FULL_DUPLEX_MAGIC 0x6969 drivers/net/ethernet/dec/tulip/de2104x.c
-USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c
-RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c
-USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h
-CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h
-RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h
-LSEMAGIC 0x05091998 lse drivers/fc4/fc.c
-GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h
-RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c
-NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h
-RED_MAGIC2 0x170fc2a5 (any) mm/slab.c
-BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c
-ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data
- drivers/isdn/isdn_x25iface.h
-ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h
-LSOMAGIC 0x27091997 lso drivers/fc4/fc.c
-LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c
-WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h
-CS_CARD_MAGIC 0x43525553 cs_card sound/oss/cs46xx.c
-LABELCL_MAGIC 0x4857434c labelcl_info_s include/asm/ia64/sn/labelcl.h
-ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h
-CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c
-ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h
-SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c
-CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c
-SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
-COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
-I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c
-TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c
-ROUTER_MAGIC 0x524d4157 wan_device [in wanrouter.h pre 3.9]
-SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
-GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
-RED_MAGIC1 0x5a2cf071 (any) mm/slab.c
-EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c
-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h
-PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h
-KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h
-I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c
-TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c
-M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c
-FW_HEADER_MAGIC 0x65726F66 fw_header drivers/atm/fore200e.h
-SLOT_MAGIC 0x67267321 slot drivers/hotplug/cpqphp.h
-SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h
-LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h
-OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h
-M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c
-VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c
-KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c
-PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h
-NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h
-ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h
-CODA_MAGIC 0xC0DAC0DA coda_file_info fs/coda/coda_fs_i.h
-DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h
-YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c
-CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c
-QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c
-QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c
-HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c
-NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h
-
-Note that there are also defined special per-driver magic numbers in sound
-memory management. See include/sound/sndmagic.h for complete list of them. Many
-OSS sound drivers have their magic numbers constructed from the soundcard PCI
-ID - these are not listed here as well.
-
-IrDA subsystem also uses large number of own magic numbers, see
-include/net/irda/irda.h for a complete list of them.
-
-HFS is another larger user of magic numbers - you can find them in
-fs/hfs/hfs.h.
diff --git a/Documentation/media/.gitignore b/Documentation/media/.gitignore
new file mode 100644
index 000000000000..08b21de3ef94
--- /dev/null
+++ b/Documentation/media/.gitignore
@@ -0,0 +1,3 @@
+*.pdf
+# Files generated from *.dot
+uapi/v4l/pipeline.svg
diff --git a/Documentation/media/Makefile b/Documentation/media/Makefile
index a7fb35291f6c..4d8e2ff378c4 100644
--- a/Documentation/media/Makefile
+++ b/Documentation/media/Makefile
@@ -1,23 +1,60 @@
-# Generate the *.h.rst files from uAPI headers
+# Rules to convert DOT and SVG to Sphinx images
+
+SRC_DIR=$(srctree)/Documentation/media
+
+DOTS = \
+ uapi/v4l/pipeline.dot \
+
+IMAGES = \
+ typical_media_device.svg \
+ uapi/dvb/dvbstb.svg \
+ uapi/v4l/bayer.svg \
+ uapi/v4l/constraints.svg \
+ uapi/v4l/crop.svg \
+ uapi/v4l/fieldseq_bt.svg \
+ uapi/v4l/fieldseq_tb.svg \
+ uapi/v4l/nv12mt.svg \
+ uapi/v4l/nv12mt_example.svg \
+ uapi/v4l/pipeline.svg \
+ uapi/v4l/selection.svg \
+ uapi/v4l/subdev-image-processing-full.svg \
+ uapi/v4l/subdev-image-processing-scaling-multi-source.svg \
+ uapi/v4l/subdev-image-processing-crop.svg \
+ uapi/v4l/vbi_525.svg \
+ uapi/v4l/vbi_625.svg \
+ uapi/v4l/vbi_hsync.svg \
+
+DOTTGT := $(patsubst %.dot,%.svg,$(DOTS))
+IMGDOT := $(patsubst %,$(SRC_DIR)/%,$(DOTTGT))
+
+IMGTGT := $(patsubst %.svg,%.pdf,$(IMAGES))
+IMGPDF := $(patsubst %,$(SRC_DIR)/%,$(IMGTGT))
+
+cmd = $(echo-cmd) $(cmd_$(1))
+
+quiet_cmd_genpdf = GENPDF $2
+ cmd_genpdf = convert $2 $3
+
+quiet_cmd_gendot = DOT $2
+ cmd_gendot = dot -Tsvg $2 > $3
+
+%.pdf: %.svg
+ @$(call cmd,genpdf,$<,$@)
+
+%.svg: %.dot
+ @$(call cmd,gendot,$<,$@)
+
+# Rules to convert a .h file to inline RST documentation
PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
UAPI = $(srctree)/include/uapi/linux
KAPI = $(srctree)/include/linux
-SRC_DIR=$(srctree)/Documentation/media
FILES = audio.h.rst ca.h.rst dmx.h.rst frontend.h.rst net.h.rst video.h.rst \
videodev2.h.rst media.h.rst cec.h.rst lirc.h.rst
TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
-.PHONY: all
-all: $(BUILDDIR) ${TARGETS}
-
-$(BUILDDIR):
- $(Q)mkdir -p $@
-
-# Rule to convert a .h file to inline RST documentation
-
gen_rst = \
echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
@@ -57,5 +94,18 @@ $(BUILDDIR)/cec.h.rst: ${KAPI}/cec.h ${PARSER} $(SRC_DIR)/cec.h.rst.exceptions
$(BUILDDIR)/lirc.h.rst: ${UAPI}/lirc.h ${PARSER} $(SRC_DIR)/lirc.h.rst.exceptions
@$($(quiet)gen_rst)
-cleandocs:
- -rm ${TARGETS}
+# Media build rules
+
+.PHONY: all html epub xml latex
+
+all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
+html: all
+epub: all
+xml: all
+latex: $(IMGPDF) all
+
+clean:
+ -rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
+
+$(BUILDDIR):
+ $(Q)mkdir -p $@
diff --git a/Documentation/media/dvb-drivers/intro.rst b/Documentation/media/dvb-drivers/intro.rst
index 7681835ea76d..d6eeb2708b9b 100644
--- a/Documentation/media/dvb-drivers/intro.rst
+++ b/Documentation/media/dvb-drivers/intro.rst
@@ -1,5 +1,5 @@
-Introdution
-===========
+Introduction
+============
The main development site and GIT repository for these
drivers is https://linuxtv.org.
diff --git a/Documentation/media/index.rst b/Documentation/media/index.rst
index e347a3e7bdef..7f8f0af620ce 100644
--- a/Documentation/media/index.rst
+++ b/Documentation/media/index.rst
@@ -1,11 +1,6 @@
Linux Media Subsystem Documentation
===================================
-.. Sphinx 1.4.x has a definition for DUrole that doesn't work on alltt blocks
-.. raw:: latex
-
- \renewcommand*{\DUrole}[2]{ #2 }
-
Contents:
.. toctree::
diff --git a/Documentation/media/intro.rst b/Documentation/media/intro.rst
index f6086c159772..8f7490c9a8ef 100644
--- a/Documentation/media/intro.rst
+++ b/Documentation/media/intro.rst
@@ -13,8 +13,8 @@ A typical media device hardware is shown at :ref:`typical_media_device`.
.. _typical_media_device:
-.. figure:: media_api_files/typical_media_device.*
- :alt: typical_media_device.svg
+.. figure:: typical_media_device.*
+ :alt: typical_media_device.pdf / typical_media_device.svg
:align: center
Typical Media Device
diff --git a/Documentation/media/media_api_files/typical_media_device.pdf b/Documentation/media/media_api_files/typical_media_device.pdf
deleted file mode 100644
index d000d802b20f..000000000000
--- a/Documentation/media/media_api_files/typical_media_device.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/media_api_files/typical_media_device.svg b/Documentation/media/typical_media_device.svg
index f0c82f72c4b6..f0c82f72c4b6 100644
--- a/Documentation/media/media_api_files/typical_media_device.svg
+++ b/Documentation/media/typical_media_device.svg
diff --git a/Documentation/media/uapi/dvb/dvbstb.svg b/Documentation/media/uapi/dvb/dvbstb.svg
new file mode 100644
index 000000000000..c4140fb518af
--- /dev/null
+++ b/Documentation/media/uapi/dvb/dvbstb.svg
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.2"
+ width="237.70221mm"
+ height="126.28221mm"
+ viewBox="0 0 23770.221 12628.221"
+ preserveAspectRatio="xMidYMid"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="dvbstb.svg"
+ style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+ id="metadata519"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview517"
+ showgrid="false"
+ inkscape:zoom="1.0818519"
+ inkscape:cx="411.31718"
+ inkscape:cy="274.87517"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" /><defs
+ class="ClipPathGroup"
+ id="defs4" /><defs
+ id="defs9" /><defs
+ id="defs90" /><defs
+ id="defs113" /><defs
+ class="TextShapeIndex"
+ id="defs124" /><defs
+ class="EmbeddedBulletChars"
+ id="defs128" /><defs
+ class="TextEmbeddedBitmaps"
+ id="defs157" /><rect
+ class="BoundingBox"
+ x="5355.1108"
+ y="13.111"
+ width="18403"
+ height="9603"
+ id="rect197"
+ style="fill:none;stroke:none" /><path
+ d="m 14556.111,9614.111 -9200,0 0,-9600 18400,0 0,9600 -9200,0 z"
+ id="path199"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 14556.111,9614.111 -9200,0 0,-9600 18400,0 0,9600 -9200,0 z"
+ id="path201"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><rect
+ class="BoundingBox"
+ x="13.111"
+ y="4013.1111"
+ width="4544"
+ height="2403"
+ id="rect206"
+ style="fill:none;stroke:none" /><path
+ d="m 2285.111,6414.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path208"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 2285.111,6414.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path210"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text212"
+ y="-4585.8892"
+ x="-2443.8889"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan214"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="1281.111"
+ y="5435.1108"
+ id="tspan216"><tspan
+ id="tspan218"
+ style="fill:#000000;stroke:none">Antena</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="6213.1108"
+ y="1813.111"
+ width="4544"
+ height="2403"
+ id="rect223"
+ style="fill:none;stroke:none" /><path
+ d="m 8485.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path225"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 8485.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path227"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text229"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan231"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="7217.1108"
+ y="3235.1111"
+ id="tspan233"><tspan
+ id="tspan235"
+ style="fill:#000000;stroke:none">Frontend</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="12113.111"
+ y="1813.111"
+ width="4544"
+ height="2403"
+ id="rect240"
+ style="fill:none;stroke:none" /><path
+ d="m 14385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path242"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 14385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path244"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text246"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan248"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="13944.111"
+ y="3235.1111"
+ id="tspan250"><tspan
+ id="tspan252"
+ style="fill:#000000;stroke:none">CA</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="18113.111"
+ y="1813.111"
+ width="4544"
+ height="2403"
+ id="rect257"
+ style="fill:none;stroke:none" /><path
+ d="m 20385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path259"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 20385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path261"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text263"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan265"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="19384.111"
+ y="3235.1111"
+ id="tspan267"><tspan
+ id="tspan269"
+ style="fill:#000000;stroke:none">Demux</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="6113.1108"
+ y="5813.1108"
+ width="4544"
+ height="2403"
+ id="rect274"
+ style="fill:none;stroke:none" /><path
+ d="m 8385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path276"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 8385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path278"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text280"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan282"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="7733.1108"
+ y="7235.1108"
+ id="tspan284"><tspan
+ id="tspan286"
+ style="fill:#000000;stroke:none">SEC</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="12213.111"
+ y="5813.1108"
+ width="4544"
+ height="2403"
+ id="rect291"
+ style="fill:none;stroke:none" /><path
+ d="m 14485.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path293"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 14485.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path295"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text297"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan299"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="13676.111"
+ y="7235.1108"
+ id="tspan301"><tspan
+ id="tspan303"
+ style="fill:#000000;stroke:none">Audio</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="18113.111"
+ y="5813.1108"
+ width="4544"
+ height="2403"
+ id="rect308"
+ style="fill:none;stroke:none" /><path
+ d="m 20385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path310"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 20385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path312"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text314"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan316"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="19583.111"
+ y="7235.1108"
+ id="tspan318"><tspan
+ id="tspan320"
+ style="fill:#000000;stroke:none">Video</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="15213.111"
+ y="10213.111"
+ width="4544"
+ height="2403"
+ id="rect325"
+ style="fill:none;stroke:none" /><path
+ d="m 17485.111,12614.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path327"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 17485.111,12614.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+ id="path329"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><text
+ class="TextShape"
+ id="text331"
+ x="-2443.8889"
+ y="-4585.8892"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan333"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="17076.111"
+ y="11635.111"
+ id="tspan335"><tspan
+ id="tspan337"
+ style="fill:#000000;stroke:none">TV</tspan></tspan></tspan></text>
+<rect
+ class="BoundingBox"
+ x="4555.1108"
+ y="3014.1111"
+ width="1661"
+ height="2202"
+ id="rect342"
+ style="fill:none;stroke:none" /><path
+ d="m 4556.111,5214.111 1400,-1857"
+ id="path344"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 6215.111,3014.111 -391,269 240,181 151,-450 z"
+ id="path346"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="4555.1108"
+ y="5213.1108"
+ width="1561"
+ height="1802"
+ id="rect351"
+ style="fill:none;stroke:none" /><path
+ d="m 4556.111,5214.111 1277,1475"
+ id="path353"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 6115.111,7014.111 -181,-438 -227,196 408,242 z"
+ id="path355"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="10755.111"
+ y="2864.1111"
+ width="1361"
+ height="301"
+ id="rect360"
+ style="fill:none;stroke:none" /><path
+ d="m 10756.111,3014.111 929,0"
+ id="path362"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 12115.111,3014.111 -450,-150 0,300 450,-150 z"
+ id="path364"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="16655.111"
+ y="2864.1111"
+ width="1461"
+ height="301"
+ id="rect369"
+ style="fill:none;stroke:none" /><path
+ d="m 16656.111,3014.111 1029,0"
+ id="path371"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18115.111,3014.111 -450,-150 0,300 450,-150 z"
+ id="path373"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="20235.111"
+ y="4213.1108"
+ width="301"
+ height="1602"
+ id="rect378"
+ style="fill:none;stroke:none" /><path
+ d="m 20385.111,4214.111 0,1170"
+ id="path380"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 20385.111,5814.111 150,-450 -300,0 150,450 z"
+ id="path382"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="17485.111"
+ y="8213.1113"
+ width="2902"
+ height="2002"
+ id="rect387"
+ style="fill:none;stroke:none" /><path
+ d="m 20385.111,8214.111 -2546,1756"
+ id="path389"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17485.111,10214.111 456,-132 -171,-247 -285,379 z"
+ id="path391"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="14484.111"
+ y="8213.1113"
+ width="3002"
+ height="2002"
+ id="rect396"
+ style="fill:none;stroke:none" /><path
+ d="m 14485.111,8214.111 2642,1761"
+ id="path398"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17485.111,10214.111 -291,-374 -167,249 458,125 z"
+ id="path400"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /><rect
+ class="BoundingBox"
+ x="14485.111"
+ y="4213.1108"
+ width="5902"
+ height="1629"
+ id="rect405"
+ style="fill:none;stroke:none" /><path
+ d="m 20385.111,4214.111 -51,14"
+ id="path407"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 20283.111,4242.111 -52,14"
+ id="path409"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 20180.111,4270.111 -51,13"
+ id="path411"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 20078.111,4297.111 -52,14"
+ id="path413"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19975.111,4325.111 -51,14"
+ id="path415"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19873.111,4353.111 -52,14"
+ id="path417"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19770.111,4381.111 -51,14"
+ id="path419"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19668.111,4409.111 -52,13"
+ id="path421"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19565.111,4436.111 -51,14"
+ id="path423"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19463.111,4464.111 -52,14"
+ id="path425"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19360.111,4492.111 -51,14"
+ id="path427"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19258.111,4520.111 -52,14"
+ id="path429"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19155.111,4547.111 -51,14"
+ id="path431"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 19053.111,4575.111 -52,14"
+ id="path433"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18950.111,4603.111 -51,14"
+ id="path435"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18848.111,4631.111 -51,14"
+ id="path437"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18745.111,4659.111 -51,14"
+ id="path439"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18643.111,4686.111 -51,14"
+ id="path441"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18540.111,4714.111 -51,14"
+ id="path443"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18438.111,4742.111 -51,14"
+ id="path445"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18335.111,4770.111 -51,14"
+ id="path447"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18233.111,4798.111 -51,14"
+ id="path449"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18130.111,4825.111 -51,14"
+ id="path451"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 18028.111,4853.111 -51,14"
+ id="path453"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17925.111,4881.111 -51,14"
+ id="path455"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17823.111,4909.111 -51,14"
+ id="path457"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17720.111,4937.111 -51,13"
+ id="path459"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17618.111,4964.111 -51,14"
+ id="path461"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17516.111,4992.111 -52,14"
+ id="path463"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17413.111,5020.111 -51,14"
+ id="path465"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17311.111,5048.111 -52,14"
+ id="path467"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17208.111,5076.111 -51,13"
+ id="path469"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17106.111,5103.111 -52,14"
+ id="path471"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 17003.111,5131.111 -51,14"
+ id="path473"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16901.111,5159.111 -52,14"
+ id="path475"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16798.111,5187.111 -51,14"
+ id="path477"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16696.111,5214.111 -52,14"
+ id="path479"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16593.111,5242.111 -51,14"
+ id="path481"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16491.111,5270.111 -52,14"
+ id="path483"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16388.111,5298.111 -51,14"
+ id="path485"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16286.111,5326.111 -52,14"
+ id="path487"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16183.111,5353.111 -51,14"
+ id="path489"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 16081.111,5381.111 -51,14"
+ id="path491"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15978.111,5409.111 -51,14"
+ id="path493"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15876.111,5437.111 -51,14"
+ id="path495"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15773.111,5465.111 -51,14"
+ id="path497"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15671.111,5492.111 -51,14"
+ id="path499"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15568.111,5520.111 -51,14"
+ id="path501"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15466.111,5548.111 -51,14"
+ id="path503"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15363.111,5576.111 -51,14"
+ id="path505"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15261.111,5604.111 -51,13"
+ id="path507"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15158.111,5631.111 -51,14"
+ id="path509"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 15056.111,5659.111 -51,14"
+ id="path511"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 14953.111,5687.111 -51,14"
+ id="path513"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000" /><path
+ d="m 14485.111,5814.111 474,27 -79,-290 -395,263 z"
+ id="path515"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke:none" /></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/dvb/intro.rst b/Documentation/media/uapi/dvb/intro.rst
index b61081d00a9f..2ed5c23102b4 100644
--- a/Documentation/media/uapi/dvb/intro.rst
+++ b/Documentation/media/uapi/dvb/intro.rst
@@ -55,8 +55,8 @@ Overview
.. _stb_components:
-.. figure:: intro_files/dvbstb.*
- :alt: dvbstb.pdf / dvbstb.png
+.. figure:: dvbstb.*
+ :alt: dvbstb.pdf / dvbstb.svg
:align: center
Components of a DVB card/STB
diff --git a/Documentation/media/uapi/dvb/intro_files/dvbstb.pdf b/Documentation/media/uapi/dvb/intro_files/dvbstb.pdf
deleted file mode 100644
index 0fa75d90c3eb..000000000000
--- a/Documentation/media/uapi/dvb/intro_files/dvbstb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/dvb/intro_files/dvbstb.png b/Documentation/media/uapi/dvb/intro_files/dvbstb.png
deleted file mode 100644
index 9b8f372e7afd..000000000000
--- a/Documentation/media/uapi/dvb/intro_files/dvbstb.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/bayer.svg b/Documentation/media/uapi/v4l/bayer.svg
new file mode 100644
index 000000000000..fbd4cfb5e6bf
--- /dev/null
+++ b/Documentation/media/uapi/v4l/bayer.svg
@@ -0,0 +1,984 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.2"
+ width="164.15334mm"
+ height="46.771107mm"
+ viewBox="0 0 16415.333 4677.1107"
+ preserveAspectRatio="xMidYMid"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="bayer.svg"
+ style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+ id="metadata652"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview650"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="2.4000866"
+ inkscape:cx="290.82284"
+ inkscape:cy="82.862197"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ class="ClipPathGroup"
+ id="defs4" /><defs
+ id="defs9" /><defs
+ id="defs82" /><defs
+ id="defs105" /><defs
+ class="TextShapeIndex"
+ id="defs116" /><defs
+ class="EmbeddedBulletChars"
+ id="defs120" /><defs
+ class="TextEmbeddedBitmaps"
+ id="defs149" /><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g186"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id6"><rect
+ class="BoundingBox"
+ x="3299"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect189"
+ style="fill:none;stroke:none" /><path
+ d="m 3950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path191"
+ inkscape:connector-curvature="0"
+ style="fill:#0000ff;stroke:none" /><path
+ d="m 3950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path193"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text195"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan197"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="3739"
+ y="4021"
+ id="tspan199"><tspan
+ id="tspan201"
+ style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g203"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id7"><rect
+ class="BoundingBox"
+ x="4599"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect206"
+ style="fill:none;stroke:none" /><path
+ d="m 5250,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path208"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 5250,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path210"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text212"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan214"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="5003"
+ y="4021"
+ id="tspan216"><tspan
+ id="tspan218"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g220"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id8"><rect
+ class="BoundingBox"
+ x="3299"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect223"
+ style="fill:none;stroke:none" /><path
+ d="m 3950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path225"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 3950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path227"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text229"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan231"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="3703"
+ y="5221"
+ id="tspan233"><tspan
+ id="tspan235"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g237"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id9"><rect
+ class="BoundingBox"
+ x="4599"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect240"
+ style="fill:none;stroke:none" /><path
+ d="m 5250,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path242"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:none" /><path
+ d="m 5250,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path244"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text246"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan248"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="5022"
+ y="5221"
+ id="tspan250"><tspan
+ id="tspan252"
+ style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g254"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id10"><rect
+ class="BoundingBox"
+ x="5999"
+ y="3299"
+ width="1003"
+ height="1003"
+ id="rect257"
+ style="fill:none;stroke:none" /><path
+ d="m 6500,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path259"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0000ff" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g261"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id11"><rect
+ class="BoundingBox"
+ x="4699"
+ y="5699"
+ width="1003"
+ height="1003"
+ id="rect264"
+ style="fill:none;stroke:none" /><path
+ d="m 5200,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path266"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.TextShape"
+ id="g268"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id12"><rect
+ class="BoundingBox"
+ x="4000"
+ y="6900"
+ width="2374"
+ height="963"
+ id="rect271"
+ style="fill:none;stroke:none" /><text
+ class="TextShape"
+ id="text273"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan275"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="4250"
+ y="7601"
+ id="tspan277"><tspan
+ id="tspan279"
+ style="fill:#000000;stroke:none">BGGR</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g281"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id13"><rect
+ class="BoundingBox"
+ x="8799"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect284"
+ style="fill:none;stroke:none" /><path
+ d="m 9450,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path286"
+ inkscape:connector-curvature="0"
+ style="fill:#0000ff;stroke:none" /><path
+ d="m 9450,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path288"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text290"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan292"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="9239"
+ y="4021"
+ id="tspan294"><tspan
+ id="tspan296"
+ style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g298"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id14"><rect
+ class="BoundingBox"
+ x="7499"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect301"
+ style="fill:none;stroke:none" /><path
+ d="m 8150,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path303"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 8150,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path305"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text307"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan309"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="7903"
+ y="4021"
+ id="tspan311"><tspan
+ id="tspan313"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g315"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id15"><rect
+ class="BoundingBox"
+ x="8799"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect318"
+ style="fill:none;stroke:none" /><path
+ d="m 9450,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path320"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 9450,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path322"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text324"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan326"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="9203"
+ y="5221"
+ id="tspan328"><tspan
+ id="tspan330"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g332"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id16"><rect
+ class="BoundingBox"
+ x="7499"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect335"
+ style="fill:none;stroke:none" /><path
+ d="m 8150,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path337"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:none" /><path
+ d="m 8150,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path339"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text341"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan343"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="7922"
+ y="5221"
+ id="tspan345"><tspan
+ id="tspan347"
+ style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.TextShape"
+ id="g349"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id17"><rect
+ class="BoundingBox"
+ x="8200"
+ y="6900"
+ width="2374"
+ height="963"
+ id="rect352"
+ style="fill:none;stroke:none" /><text
+ class="TextShape"
+ id="text354"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan356"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="8450"
+ y="7601"
+ id="tspan358"><tspan
+ id="tspan360"
+ style="fill:#000000;stroke:none">GBRG</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g362"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id18"><rect
+ class="BoundingBox"
+ x="17299"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect365"
+ style="fill:none;stroke:none" /><path
+ d="m 17950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path367"
+ inkscape:connector-curvature="0"
+ style="fill:#0000ff;stroke:none" /><path
+ d="m 17950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path369"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text371"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan373"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="17739"
+ y="5221"
+ id="tspan375"><tspan
+ id="tspan377"
+ style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g379"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id19"><rect
+ class="BoundingBox"
+ x="17299"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect382"
+ style="fill:none;stroke:none" /><path
+ d="m 17950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path384"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 17950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path386"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text388"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan390"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="17703"
+ y="4021"
+ id="tspan392"><tspan
+ id="tspan394"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g396"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id20"><rect
+ class="BoundingBox"
+ x="15999"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect399"
+ style="fill:none;stroke:none" /><path
+ d="m 16650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path401"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 16650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path403"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text405"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan407"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="16403"
+ y="5221"
+ id="tspan409"><tspan
+ id="tspan411"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g413"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id21"><rect
+ class="BoundingBox"
+ x="15999"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect416"
+ style="fill:none;stroke:none" /><path
+ d="m 16650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path418"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:none" /><path
+ d="m 16650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path420"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text422"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan424"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="16422"
+ y="4021"
+ id="tspan426"><tspan
+ id="tspan428"
+ style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.TextShape"
+ id="g430"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id22"><rect
+ class="BoundingBox"
+ x="16700"
+ y="6900"
+ width="2374"
+ height="963"
+ id="rect433"
+ style="fill:none;stroke:none" /><text
+ class="TextShape"
+ id="text435"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan437"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="16950"
+ y="7601"
+ id="tspan439"><tspan
+ id="tspan441"
+ style="fill:#000000;stroke:none">RGGB</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g443"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id23"><rect
+ class="BoundingBox"
+ x="11699"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect446"
+ style="fill:none;stroke:none" /><path
+ d="m 12350,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path448"
+ inkscape:connector-curvature="0"
+ style="fill:#0000ff;stroke:none" /><path
+ d="m 12350,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path450"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text452"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan454"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="12139"
+ y="5221"
+ id="tspan456"><tspan
+ id="tspan458"
+ style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g460"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id24"><rect
+ class="BoundingBox"
+ x="11699"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect463"
+ style="fill:none;stroke:none" /><path
+ d="m 12350,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path465"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 12350,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path467"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text469"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan471"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="12103"
+ y="4021"
+ id="tspan473"><tspan
+ id="tspan475"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g477"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id25"><rect
+ class="BoundingBox"
+ x="12999"
+ y="4399"
+ width="1303"
+ height="1203"
+ id="rect480"
+ style="fill:none;stroke:none" /><path
+ d="m 13650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path482"
+ inkscape:connector-curvature="0"
+ style="fill:#00cc00;stroke:none" /><path
+ d="m 13650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path484"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text486"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan488"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="13403"
+ y="5221"
+ id="tspan490"><tspan
+ id="tspan492"
+ style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g494"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id26"><rect
+ class="BoundingBox"
+ x="12999"
+ y="3199"
+ width="1303"
+ height="1203"
+ id="rect497"
+ style="fill:none;stroke:none" /><path
+ d="m 13650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path499"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:none" /><path
+ d="m 13650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+ id="path501"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text503"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan505"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="13422"
+ y="4021"
+ id="tspan507"><tspan
+ id="tspan509"
+ style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.TextShape"
+ id="g511"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id27"><rect
+ class="BoundingBox"
+ x="12400"
+ y="6900"
+ width="2374"
+ height="963"
+ id="rect514"
+ style="fill:none;stroke:none" /><text
+ class="TextShape"
+ id="text516"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan518"
+ style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="12650"
+ y="7601"
+ id="tspan520"><tspan
+ id="tspan522"
+ style="fill:#000000;stroke:none">GRBG</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g524"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id28"><rect
+ class="BoundingBox"
+ x="5999"
+ y="5699"
+ width="1003"
+ height="1003"
+ id="rect527"
+ style="fill:none;stroke:none" /><path
+ d="m 6500,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path529"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0000ff" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g531"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id29"><rect
+ class="BoundingBox"
+ x="3399"
+ y="5699"
+ width="1003"
+ height="1003"
+ id="rect534"
+ style="fill:none;stroke:none" /><path
+ d="m 3900,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path536"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0000ff" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g538"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id30"><rect
+ class="BoundingBox"
+ x="5999"
+ y="4499"
+ width="1003"
+ height="1003"
+ id="rect541"
+ style="fill:none;stroke:none" /><path
+ d="m 6500,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path543"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g545"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id31"><rect
+ class="BoundingBox"
+ x="7599"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect548"
+ style="fill:none;stroke:none" /><path
+ d="m 8100,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path550"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g552"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id32"><rect
+ class="BoundingBox"
+ x="10199"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect555"
+ style="fill:none;stroke:none" /><path
+ d="m 10700,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path557"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g559"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id33"><rect
+ class="BoundingBox"
+ x="8899"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect562"
+ style="fill:none;stroke:none" /><path
+ d="m 9400,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path564"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0000ff" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g566"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id34"><rect
+ class="BoundingBox"
+ x="10199"
+ y="4499"
+ width="1003"
+ height="1003"
+ id="rect569"
+ style="fill:none;stroke:none" /><path
+ d="m 10700,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path571"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g573"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id35"><rect
+ class="BoundingBox"
+ x="10199"
+ y="3299"
+ width="1003"
+ height="1003"
+ id="rect576"
+ style="fill:none;stroke:none" /><path
+ d="m 10700,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path578"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g580"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id36"><rect
+ class="BoundingBox"
+ x="14399"
+ y="3299"
+ width="1003"
+ height="1003"
+ id="rect583"
+ style="fill:none;stroke:none" /><path
+ d="m 14900,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path585"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g587"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id37"><rect
+ class="BoundingBox"
+ x="14399"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect590"
+ style="fill:none;stroke:none" /><path
+ d="m 14900,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path592"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g594"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id38"><rect
+ class="BoundingBox"
+ x="11799"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect597"
+ style="fill:none;stroke:none" /><path
+ d="m 12300,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path599"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g601"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id39"><rect
+ class="BoundingBox"
+ x="14399"
+ y="4499"
+ width="1003"
+ height="1003"
+ id="rect604"
+ style="fill:none;stroke:none" /><path
+ d="m 14900,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path606"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0000ff" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g608"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id40"><rect
+ class="BoundingBox"
+ x="13099"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect611"
+ style="fill:none;stroke:none" /><path
+ d="m 13600,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path613"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g615"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id41"><rect
+ class="BoundingBox"
+ x="16099"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect618"
+ style="fill:none;stroke:none" /><path
+ d="m 16600,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path620"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g622"
+ transform="translate(-3398.7778,-3185.889)"><g
+ id="id42"><rect
+ class="BoundingBox"
+ x="18799"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect625"
+ style="fill:none;stroke:none" /><path
+ d="m 19300,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path627"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g629"
+ transform="translate(-3398.7778,-3185.889)"><g
+ id="id43"><rect
+ class="BoundingBox"
+ x="18799"
+ y="3299"
+ width="1003"
+ height="1003"
+ id="rect632"
+ style="fill:none;stroke:none" /><path
+ d="m 19300,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path634"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g636"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id44"><rect
+ class="BoundingBox"
+ x="17399"
+ y="5799"
+ width="1003"
+ height="1003"
+ id="rect639"
+ style="fill:none;stroke:none" /><path
+ d="m 17900,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path641"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g643"
+ transform="translate(-3398.7778,-3185.889)"><g
+ id="id45"><rect
+ class="BoundingBox"
+ x="18799"
+ y="4499"
+ width="1003"
+ height="1003"
+ id="rect646"
+ style="fill:none;stroke:none" /><path
+ d="m 19300,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+ id="path648"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#00cc00" /></g></g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/constraints.svg b/Documentation/media/uapi/v4l/constraints.svg
new file mode 100644
index 000000000000..f710ee46b1f8
--- /dev/null
+++ b/Documentation/media/uapi/v4l/constraints.svg
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.2"
+ width="249.00998mm"
+ height="143.00999mm"
+ viewBox="0 0 24900.998 14300.999"
+ preserveAspectRatio="xMidYMid"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="constraints.svg"
+ style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+ id="metadata325"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview323"
+ showgrid="false"
+ inkscape:zoom="1.0818519"
+ inkscape:cx="270.29272"
+ inkscape:cy="249.83854"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" /><defs
+ class="ClipPathGroup"
+ id="defs4"><marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker6261"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"><path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ id="path6263"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker6125"
+ style="overflow:visible"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ id="path6127"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker6001"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:collect="always"><path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ id="path6003"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker5693"
+ style="overflow:visible"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ id="path5695"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker5575"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:collect="always"><path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ id="path5577"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker5469"
+ style="overflow:visible"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ id="path5471"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker5259"
+ style="overflow:visible"
+ inkscape:isstock="true"><path
+ id="path5261"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" /></marker><marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible"
+ inkscape:isstock="true"><path
+ id="path4241"
+ style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6,-0.6)"
+ inkscape:connector-curvature="0" /></marker></defs><defs
+ id="defs9" /><defs
+ id="defs100" /><defs
+ id="defs123" /><defs
+ class="TextShapeIndex"
+ id="defs134" /><defs
+ class="EmbeddedBulletChars"
+ id="defs138" /><defs
+ class="TextEmbeddedBitmaps"
+ id="defs167" /><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g204"
+ transform="translate(-1350,-3250)"><g
+ id="id6"><rect
+ class="BoundingBox"
+ x="1350"
+ y="3250"
+ width="24901"
+ height="14301"
+ id="rect207"
+ style="fill:none;stroke:none" /><path
+ d="m 13800,17500 -12400,0 0,-14200 24800,0 0,14200 -12400,0 z"
+ id="path209"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 13800,17500 -12400,0 0,-14200 24800,0 0,14200 -12400,0 z"
+ id="path211"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:100;stroke-linejoin:round" /><text
+ class="TextShape"
+ id="text213"><tspan
+ class="TextParagraph"
+ font-size="846px"
+ font-weight="400"
+ id="tspan215"
+ style="font-weight:400;font-size:846px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="1652"
+ y="17093"
+ id="tspan217"><tspan
+ id="tspan219"
+ style="fill:#ff0000;stroke:none" /><tspan
+ id="tspan221"
+ style="fill:#ff0000;stroke:none">V4L2_SEL_FLAG_GE</tspan></tspan></tspan></text>
+</g></g><rect
+ class="BoundingBox"
+ x="3000"
+ y="2200"
+ width="18101"
+ height="10101"
+ id="rect226"
+ style="fill:none;stroke:none" /><path
+ d="m 12050,12250 -9000,0 0,-10000 18000,0 0,10000 -9000,0 z"
+ id="path228"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 12050,12250 -9000,0 0,-10000 18000,0 0,10000 -9000,0 z"
+ id="path230"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:100;stroke-linejoin:round" /><text
+ class="TextShape"
+ id="text232"
+ x="-1350"
+ y="-3250"><tspan
+ class="TextParagraph"
+ font-size="987px"
+ font-weight="400"
+ id="tspan234"
+ style="font-weight:400;font-size:987px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="3227"
+ y="11503"
+ id="tspan236"><tspan
+ id="tspan238"
+ style="fill:#000000;stroke:none" /><tspan
+ id="tspan240"
+ style="fill:#000000;stroke:none">ORIGINAL</tspan></tspan></tspan></text>
+<g
+ class="com.sun.star.drawing.CustomShape"
+ id="g242"
+ transform="translate(-1350,-3250)"><g
+ id="id8"><rect
+ class="BoundingBox"
+ x="7050"
+ y="7950"
+ width="7901"
+ height="5501"
+ id="rect245"
+ style="fill:none;stroke:none" /><path
+ d="m 11000,13400 -3900,0 0,-5400 7800,0 0,5400 -3900,0 z"
+ id="path247"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;stroke:none" /><path
+ d="m 11000,13400 -3900,0 0,-5400 7800,0 0,5400 -3900,0 z"
+ id="path249"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4;stroke-width:100;stroke-linejoin:round" /><text
+ class="TextShape"
+ id="text251"><tspan
+ class="TextParagraph"
+ font-size="776px"
+ font-weight="400"
+ id="tspan253"
+ style="font-weight:400;font-size:776px;font-family:'Liberation Sans', sans-serif"><tspan
+ class="TextPosition"
+ x="7228"
+ y="10969"
+ id="tspan255"><tspan
+ id="tspan257"
+ style="fill:#000080;stroke:none">V4L2_SEL_FLAG_LE</tspan></tspan></tspan></text>
+</g></g><rect
+ class="BoundingBox"
+ x="13700"
+ y="7100"
+ width="7101"
+ height="101"
+ id="rect262"
+ style="fill:none;stroke:none" /><path
+ d="m 20750,7150 -7000,0"
+ id="path264"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000080;stroke-width:99.99134064;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" /><rect
+ class="BoundingBox"
+ x="3400"
+ y="7100"
+ width="2101"
+ height="101"
+ id="rect269"
+ style="fill:none;stroke:none" /><path
+ d="m 3450,7150 2000,0"
+ id="path271"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5575)" /><rect
+ class="BoundingBox"
+ x="9800"
+ y="2900"
+ width="101"
+ height="1501"
+ id="rect276"
+ style="fill:none;stroke:none" /><path
+ d="m 9850,2950 0,1400"
+ id="path278"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5259)" /><rect
+ class="BoundingBox"
+ x="9600"
+ y="10600"
+ width="101"
+ height="1301"
+ id="rect283"
+ style="fill:none;stroke:none" /><path
+ d="m 9650,11850 0,-1200"
+ id="path285"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5469)" /><rect
+ class="BoundingBox"
+ x="450"
+ y="6850"
+ width="2051"
+ height="601"
+ id="rect290"
+ style="fill:none;stroke:none" /><path
+ d="m 2450,7150 -2000.8696,0"
+ id="path292"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:132.48202515;stroke-linejoin:round;marker-end:url(#marker6125)" /><rect
+ class="BoundingBox"
+ x="21600"
+ y="6750"
+ width="2651"
+ height="601"
+ id="rect299"
+ style="fill:none;stroke:none" /><path
+ d="m 21650,7050 2522.609,0"
+ id="path301"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:120.40660858;stroke-linejoin:round;marker-end:url(#marker6001)" /><rect
+ class="BoundingBox"
+ x="9550"
+ y="550"
+ width="601"
+ height="1451"
+ id="rect308"
+ style="fill:none;stroke:none" /><path
+ d="m 9836.957,1950 0,-1453.0435"
+ id="path310"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:164.03721619;stroke-linejoin:round;marker-end:url(#marker6261)" /><rect
+ class="BoundingBox"
+ x="9350"
+ y="12500"
+ width="601"
+ height="1451"
+ id="rect317"
+ style="fill:none;stroke:none" /><path
+ d="m 9650,12550 0,1505.217"
+ id="path319"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:166.95626831;stroke-linejoin:round;marker-end:url(#marker5693)" /></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/crop.rst b/Documentation/media/uapi/v4l/crop.rst
index 3ea733a8eef8..be58894c9c89 100644
--- a/Documentation/media/uapi/v4l/crop.rst
+++ b/Documentation/media/uapi/v4l/crop.rst
@@ -53,8 +53,8 @@ Cropping Structures
.. _crop-scale:
-.. figure:: crop_files/crop.*
- :alt: crop.pdf / crop.gif
+.. figure:: crop.*
+ :alt: crop.pdf / crop.svg
:align: center
Image Cropping, Insertion and Scaling
diff --git a/Documentation/media/uapi/v4l/crop.svg b/Documentation/media/uapi/v4l/crop.svg
new file mode 100644
index 000000000000..dc9a471bae6b
--- /dev/null
+++ b/Documentation/media/uapi/v4l/crop.svg
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="208.59436mm"
+ height="95.859146mm"
+ viewBox="0 0 739.11388 339.6584"
+ sodipodi:docname="crop.svg"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath44"><path
+ d="m 0,0 0,1895 4118,0 L 4118,0 0,0 Z m 3051.62,250.48 8.19,17.01 -46.93,23.31 29.61,-25.515 -38.12,8.505 47.25,-23.31 z m -1559.25,800.73 -8.5,-17.01 46.93,-23.31 -29.29,25.2 37.8,-8.19 -46.94,23.31 z"
+ id="path46"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath64"><path
+ d="m 0,0 0,1895 4118,0 0,-1626 -1,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 -4,0 0,1 -5,0 0,1 -4,0 0,1 -5,0 0,1 -4,0 0,1 -4,0 0,1 -4,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 1,0 0,3 1,0 0,2 1,0 0,2 1,0 L 4118,0 0,0 Z m 4074,272 0,-1 1,0 0,1 -1,0 z m -1486,743 0,-1 1,0 0,1 -1,0 z m -2,1 0,-1 1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,2 2,0 0,-1 4,0 0,-1 5,0 0,-1 4,0 0,-1 5,0 0,-1 5,0 0,-1 4,0 0,-1 3,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -3,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 z"
+ id="path66"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath84"><path
+ d="m 0,0 0,1895 4118,0 0,-136 -3,0 0,-1 -11,0 0,-1 -11,0 0,-1 -11,0 0,-1 -11,0 0,-1 5,0 0,-1 6,0 0,-1 7,0 0,-1 6,0 0,-1 6,0 0,-1 4,0 0,-1 -1,0 0,-1 -3,0 0,-1 -3,0 0,-1 -2,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 7,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 3,0 L 4118,0 0,0 Z m 2552,1599 0,-1 2,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 -4,0 0,1 -7,0 0,1 -6,0 0,1 -7,0 0,1 -6,0 0,1 -3,0 0,1 2,0 0,1 2,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 2,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 -7,0 0,-1 -12,0 0,-1 -11,0 0,-1 -11,0 0,-1 -4,0 0,-1 1,0 0,-12 1,0 0,-4 z"
+ id="path86"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath104"><path
+ d="m 0,0 0,1895 4118,0 L 4118,0 0,0 Z m 3056.98,1740.43 -1.58,18.9 -52.6,-4.72 38.74,-6.3 -36.85,-12.6 52.29,4.72 z m -1570.28,-123.79 1.58,-18.9 52.6,4.72 -38.43,5.99 36.54,12.91 -52.29,-4.72 z"
+ id="path106"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath></defs><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview4"
+ showgrid="false"
+ inkscape:zoom="0.99625351"
+ inkscape:cx="-73.227122"
+ inkscape:cy="114.17568"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g10"
+ units="mm"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" /><g
+ id="g10"
+ inkscape:groupmode="layer"
+ inkscape:label="crop"
+ transform="matrix(1.25,0,0,-1.25,-0.35237428,339.91141)"><path
+ d="m 411.08474,0.37218832 0,271.38551168 -37.17867,0 0,-1.94649 -205.3611,1.94649 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,-264.3219406 -17.977663,0 0,-2.58119108 193.135216,0 0,2.58119108 -137.934309,0 0,264.3219406 333.650679,0 0,-264.3219406 -177.10547,0 0,-1.947197 149.52695,0 0,-0.63399408"
+ style="fill:#7f7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path16"
+ inkscape:connector-curvature="0" /><path
+ d="m 411.08474,0.37218832 0,271.38551168 -37.17867,0 0,-1.94649 -205.3611,1.94649 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,-264.3219406 -17.977663,0 0,-2.58119108 193.135216,0 0,2.58119108 -137.934309,0 0,264.3219406 333.650679,0 0,-264.3219406 -177.10547,0 0,-1.947197 149.52695,0 0,-0.63399408 37.17867,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path18"
+ inkscape:connector-curvature="0" /><path
+ d="m 40.256106,6.8024838 366.979524,0 0,253.4078762 -366.979524,0 0,-253.4078762 z"
+ style="fill:none;stroke:#ff0000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path20"
+ inkscape:connector-curvature="0" /><path
+ d="m 77.434066,7.4364707 316.352284,0 0,244.4416893 -316.352284,0 0,-244.4416893 z"
+ style="fill:none;stroke:#0000ff;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path22"
+ inkscape:connector-curvature="0" /><path
+ d="m 214.41669,149.49157 152.83195,0 0,81.51075 -152.83195,0 0,-81.51075 z"
+ style="fill:none;stroke:#00b000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path24"
+ inkscape:connector-curvature="0" /><path
+ d="m 438.57126,37.414285 152.83194,0 0,213.966445 -152.83194,0 0,-213.966445 z"
+ style="fill:none;stroke:#d100d1;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path26"
+ inkscape:connector-curvature="0" /><path
+ d="m 0.45168907,271.7577 168.09328093,0 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,0 0,-264.3219406 -17.977663,0 0,-2.58119108 -12.18131493,0"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path28"
+ inkscape:connector-curvature="0" /><path
+ d="m 0.45168907,271.7577 168.09328093,0 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,0 0,-264.3219406 -17.977663,0 0,-2.58119108 -12.18131493,0 0,271.38551168 z"
+ style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path30"
+ inkscape:connector-curvature="0" /><path
+ d="m 373.90607,0.37218832 0,0.63399408 -149.52695,0 0,1.947197 -18.6109,0 0,-2.58119108"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path32"
+ inkscape:connector-curvature="0" /><path
+ d="m 373.90607,0.37218832 0,0.63399408 -149.52695,0 0,1.947197 -18.6109,0 0,-2.58119108 168.13785,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path34"
+ inkscape:connector-curvature="0" /><path
+ d="m 205.76822,271.7577 168.13785,0 0,-1.94649 -149.52695,0 0,-2.53589 -18.6109,0"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path36"
+ inkscape:connector-curvature="0" /><path
+ d="m 205.76822,271.7577 168.13785,0 0,-1.94649 -149.52695,0 0,-2.53589 -18.6109,0 0,4.48238 z"
+ style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path38"
+ inkscape:connector-curvature="0" /><g
+ id="g40"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+ clip-path="url(#clipPath44)"
+ id="g42"><path
+ inkscape:connector-curvature="0"
+ id="path48"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="M 1492.37,1040.5 3051.62,260.875" /></g></g><g
+ id="g50"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+ inkscape:connector-curvature="0"
+ id="path52"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1539.31,1027.9 -37.8,8.19 29.29,-25.2 8.51,17.01" /><path
+ inkscape:connector-curvature="0"
+ id="path54"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1539.31,1027.9 -37.8,8.19 29.29,-25.2 8.51,17.01 z" /><path
+ inkscape:connector-curvature="0"
+ id="path56"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 3004.37,273.79 38.12,-8.505 -29.61,25.515 -8.51,-17.01" /><path
+ inkscape:connector-curvature="0"
+ id="path58"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3004.37,273.79 38.12,-8.505 -29.61,25.515 -8.51,-17.01 z" /></g><g
+ id="g60"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+ clip-path="url(#clipPath64)"
+ id="g62"><path
+ inkscape:connector-curvature="0"
+ id="path68"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="M 2555.5,1040.5 4114.75,260.875" /></g></g><g
+ id="g70"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+ inkscape:connector-curvature="0"
+ id="path72"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2602.43,1027.9 -37.8,8.19 29.3,-25.2 8.5,17.01" /><path
+ inkscape:connector-curvature="0"
+ id="path74"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2602.43,1027.9 -37.8,8.19 29.3,-25.2 8.5,17.01 z" /><path
+ inkscape:connector-curvature="0"
+ id="path76"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 4067.5,273.79 38.11,-8.505 -29.61,25.515 -8.5,-17.01" /><path
+ inkscape:connector-curvature="0"
+ id="path78"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4067.5,273.79 38.11,-8.505 -29.61,25.515 -8.5,-17.01 z" /></g><g
+ id="g80"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+ clip-path="url(#clipPath84)"
+ id="g82"><path
+ inkscape:connector-curvature="0"
+ id="path88"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2555.5,1607.5 1559.25,141.75" /></g></g><g
+ id="g90"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+ inkscape:connector-curvature="0"
+ id="path92"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2602.12,1621.36 -36.54,-12.91 38.43,-5.99 -1.89,18.9" /><path
+ inkscape:connector-curvature="0"
+ id="path94"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2602.12,1621.36 -36.54,-12.91 38.43,-5.99 -1.89,18.9 z" /><path
+ inkscape:connector-curvature="0"
+ id="path96"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 4067.81,1735.71 36.86,12.6 -38.75,6.3 1.89,-18.9" /><path
+ inkscape:connector-curvature="0"
+ id="path98"
+ style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4067.81,1735.71 36.86,12.6 -38.75,6.3 1.89,-18.9 z" /></g><g
+ id="g100"
+ transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+ clip-path="url(#clipPath104)"
+ id="g102"><path
+ inkscape:connector-curvature="0"
+ id="path108"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1492.37,1607.5 1559.25,141.75" /></g></g><path
+ d="m 221.11869,232.99481 -5.25292,-1.85592 5.52462,-0.86111 -0.2717,2.71703"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path112"
+ inkscape:connector-curvature="0" /><path
+ d="m 221.11869,232.99481 -5.25292,-1.85592 5.52462,-0.86111 -0.2717,2.71703 z"
+ style="fill:none;stroke:#000000;stroke-width:0.67925626;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path114"
+ inkscape:connector-curvature="0" /><path
+ d="m 431.8247,249.43353 5.29748,1.81135 -5.56918,0.90567 0.2717,-2.71702"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path116"
+ inkscape:connector-curvature="0" /><path
+ d="m 431.8247,249.43353 5.29748,1.81135 -5.56918,0.90567 0.2717,-2.71702 z"
+ style="fill:none;stroke:#000000;stroke-width:0.67925626;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path118"
+ inkscape:connector-curvature="0" /><g
+ id="g120"
+ transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+ transform="matrix(1,0,0,-1,204.52,9.07751)"
+ style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#d10000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="text122"><tspan
+ x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 31.983524 35.661465 39.339405 41.178375 44.856316 48.534256 52.212196 55.890137 59.568073"
+ y="0"
+ sodipodi:role="line"
+ id="tspan124">v4l2_cropcap.bounds</tspan></text>
+</g><g
+ id="g126"
+ transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+ transform="matrix(1,0,0,-1,58.5175,166.42)"
+ style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#0000d1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="text128"><tspan
+ x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 31.983524 35.661465 39.339405 41.178375 44.856316 48.534256 50.373226 52.576019 56.25396 59.561459"
+ y="0"
+ sodipodi:role="line"
+ id="tspan130">v4l2_cropcap.defrect</tspan></text>
+</g><g
+ id="g132"
+ transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+ transform="matrix(1,0,0,-1,153.49,152.245)"
+ style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#008f00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="text134"><tspan
+ x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 30.514996"
+ y="0"
+ sodipodi:role="line"
+ id="tspan136">v4l2_crop.c</tspan></text>
+</g><g
+ id="g138"
+ transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+ transform="matrix(1,0,0,-1,309.415,30.34)"
+ style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#b000b0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="text140"><tspan
+ x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 17.648821 21.326759 23.529554 29.03985 32.717789"
+ y="0"
+ sodipodi:role="line"
+ id="tspan142">v4l2_format</tspan></text>
+</g><text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="-99.291145"
+ y="-239.49893"
+ id="text3396"
+ sodipodi:linespacing="125%"
+ transform="scale(1,-1)"><tspan
+ sodipodi:role="line"
+ id="tspan3398"
+ x="-99.291145"
+ y="-239.49893"></tspan><tspan
+ sodipodi:role="line"
+ x="-99.291145"
+ y="-199.49893"
+ id="tspan3400" /></text>
+</g></svg>
diff --git a/Documentation/media/uapi/v4l/crop_files/crop.gif b/Documentation/media/uapi/v4l/crop_files/crop.gif
deleted file mode 100644
index 3b9e7d836d4b..000000000000
--- a/Documentation/media/uapi/v4l/crop_files/crop.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/crop_files/crop.pdf b/Documentation/media/uapi/v4l/crop_files/crop.pdf
deleted file mode 100644
index c9fb81cd32f3..000000000000
--- a/Documentation/media/uapi/v4l/crop_files/crop.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi.rst b/Documentation/media/uapi/v4l/dev-raw-vbi.rst
index b82d837e4ff1..baf5f2483927 100644
--- a/Documentation/media/uapi/v4l/dev-raw-vbi.rst
+++ b/Documentation/media/uapi/v4l/dev-raw-vbi.rst
@@ -221,8 +221,8 @@ and always returns default parameters as :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` does
.. _vbi-hsync:
-.. figure:: dev-raw-vbi_files/vbi_hsync.*
- :alt: vbi_hsync.pdf / vbi_hsync.gif
+.. figure:: vbi_hsync.*
+ :alt: vbi_hsync.pdf / vbi_hsync.svg
:align: center
**Figure 4.1. Line synchronization**
@@ -230,8 +230,8 @@ and always returns default parameters as :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` does
.. _vbi-525:
-.. figure:: dev-raw-vbi_files/vbi_525.*
- :alt: vbi_525.pdf / vbi_525.gif
+.. figure:: vbi_525.*
+ :alt: vbi_525.pdf / vbi_525.svg
:align: center
**Figure 4.2. ITU-R 525 line numbering (M/NTSC and M/PAL)**
@@ -240,8 +240,8 @@ and always returns default parameters as :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` does
.. _vbi-625:
-.. figure:: dev-raw-vbi_files/vbi_625.*
- :alt: vbi_625.pdf / vbi_625.gif
+.. figure:: vbi_625.*
+ :alt: vbi_625.pdf / vbi_625.svg
:align: center
**Figure 4.3. ITU-R 625 line numbering**
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gif b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gif
deleted file mode 100644
index 5580b690d504..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdf b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdf
deleted file mode 100644
index 0bae28385dfa..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gif b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gif
deleted file mode 100644
index 34e3251983c4..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdf b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdf
deleted file mode 100644
index bf29b95dcd08..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gif b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gif
deleted file mode 100644
index b02434d3b356..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdf b/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdf
deleted file mode 100644
index 200b668189bf..000000000000
--- a/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev.rst b/Documentation/media/uapi/v4l/dev-subdev.rst
index fb4d0d45b216..cd2870180208 100644
--- a/Documentation/media/uapi/v4l/dev-subdev.rst
+++ b/Documentation/media/uapi/v4l/dev-subdev.rst
@@ -99,8 +99,8 @@ the video sensor and the host image processing hardware.
.. _pipeline-scaling:
-.. figure:: dev-subdev_files/pipeline.*
- :alt: pipeline.pdf / pipeline.png
+.. figure:: pipeline.*
+ :alt: pipeline.pdf / pipeline.svg
:align: center
Image Format Negotiation on Pipelines
@@ -404,8 +404,8 @@ selection will refer to the sink pad format dimensions instead.
.. _subdev-image-processing-crop:
-.. figure:: dev-subdev_files/subdev-image-processing-crop.*
- :alt: subdev-image-processing-crop.svg
+.. figure:: subdev-image-processing-crop.*
+ :alt: subdev-image-processing-crop.pdf / subdev-image-processing-crop.svg
:align: center
**Figure 4.5. Image processing in subdevs: simple crop example**
@@ -421,8 +421,8 @@ pad.
.. _subdev-image-processing-scaling-multi-source:
-.. figure:: dev-subdev_files/subdev-image-processing-scaling-multi-source.*
- :alt: subdev-image-processing-scaling-multi-source.svg
+.. figure:: subdev-image-processing-scaling-multi-source.*
+ :alt: subdev-image-processing-scaling-multi-source.pdf / subdev-image-processing-scaling-multi-source.svg
:align: center
**Figure 4.6. Image processing in subdevs: scaling with multiple sources**
@@ -437,8 +437,8 @@ an area at location specified by the source crop rectangle from it.
.. _subdev-image-processing-full:
-.. figure:: dev-subdev_files/subdev-image-processing-full.*
- :alt: subdev-image-processing-full.svg
+.. figure:: subdev-image-processing-full.*
+ :alt: subdev-image-processing-full.pdf / subdev-image-processing-full.svg
:align: center
**Figure 4.7. Image processing in subdevs: scaling and composition with multiple sinks and sources**
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdf b/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdf
deleted file mode 100644
index ee3e37f04b6a..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.png b/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.png
deleted file mode 100644
index f19b86c2c24d..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdf b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdf
deleted file mode 100644
index 29a806f839b4..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg
deleted file mode 100644
index 18b0f5de9ed2..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="43cm" height="10cm" viewBox="-194 128 844 196" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="469.774" height="193"/>
- <g>
- <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="63.5" y="211" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="63.5" y="211" width="94" height="77"/>
- </g>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="74.5" y="227.75">
- <tspan x="74.5" y="227.75">sink</tspan>
- <tspan x="74.5" y="243.75">crop</tspan>
- <tspan x="74.5" y="259.75">selection</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
- <tspan x="29.5" y="158"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
- <tspan x="8.53836" y="157.914">sink media</tspan>
- <tspan x="8.53836" y="173.914">bus format</tspan>
- </text>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="349.774" y="155">
- <tspan x="349.774" y="155">source media</tspan>
- <tspan x="349.774" y="171">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="350.488" y="190.834" width="93.2863" height="75.166"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="350.488" y="190.834" width="93.2863" height="75.166"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="266" x2="63.5" y2="288"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="190.834" x2="63.5" y2="211"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="266" x2="157.5" y2="288"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="190.834" x2="157.5" y2="211"/>
- <g>
- <ellipse style="fill: #ffffff" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="481.6" y1="219.984" x2="637.934" y2="220.012"/>
- <polygon style="fill: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="506.908" y="209.8">
- <tspan x="506.908" y="209.8">pad 1 (source)</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
- <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
- <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
- </text>
-</svg>
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdf b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdf
deleted file mode 100644
index b78a8e8f6b35..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg
deleted file mode 100644
index 3322cf4c0093..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="18cm" viewBox="-186 71 1178 346" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <g>
- <rect style="fill: #ffffff" x="318.9" y="129" width="208.1" height="249"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff765a" x="318.9" y="129" width="208.1" height="249"/>
- </g>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-2" y="73" width="806" height="343"/>
- <g>
- <ellipse style="fill: #ffffff" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <ellipse style="fill: #ffffff" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.5" y1="167" x2="-30.7361" y2="166.729"/>
- <polygon style="fill: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.732" y1="205.184" x2="980.066" y2="205.212"/>
- <polygon style="fill: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139.96" y="155">
- <tspan x="-139.96" y="155">pad 0 (sink)</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.04" y="195">
- <tspan x="849.04" y="195">pad 2 (source)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="5.5" y="120" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="5.5" y="120" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="62.5" y="136" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="62.5" y="136" width="94" height="77"/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="30.5" y="89">
- <tspan x="30.5" y="89"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="9.53836" y="88.9138">
- <tspan x="9.53836" y="88.9138">sink media</tspan>
- <tspan x="9.53836" y="104.914">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="62.5" y2="213"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="62.5" y2="136"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="156.5" y2="213"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="156.5" y2="136"/>
- <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
- <tspan x="334.704" y="149.442">sink compose</tspan>
- <tspan x="334.704" y="165.442">selection (scaling)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="409.322" y="194.565" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="409.322" y="194.565" width="100.186" height="71.4523"/>
- </g>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="689.5" y="105.128">
- <tspan x="689.5" y="105.128">source media</tspan>
- <tspan x="689.5" y="121.128">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="688.488" y="173.834" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="688.488" y="173.834" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="245.286" x2="409.322" y2="266.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="173.834" x2="409.322" y2="194.565"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="245.286" x2="509.508" y2="266.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="173.834" x2="509.508" y2="194.565"/>
- <text style="fill: #ff765a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="325" y="103">
- <tspan x="325" y="103">sink compose</tspan>
- <tspan x="325" y="119">bounds selection</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.098" y1="341.8" x2="-30.3343" y2="341.529"/>
- <polygon style="fill: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139" y="329">
- <tspan x="-139" y="329">pad 1 (sink)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="7.80824" y="292.8" width="112.092" height="82.2"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="7.80824" y="292.8" width="112.092" height="82.2"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="52.9" y="314.8" width="58.1" height="50.2"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="52.9" y="314.8" width="58.1" height="50.2"/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="31.9" y="259.8">
- <tspan x="31.9" y="259.8"></tspan>
- </text>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="251.9" x2="52.9" y2="314.8"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="316" x2="52.9" y2="365"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="316" x2="111" y2="365"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="251.9" x2="111" y2="314.8"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="358.9" y="251.9" width="75.1" height="64.1"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="443.262" y="284.466" width="64.738" height="48.534"/>
- <g>
- <rect style="fill: #ffffff" x="693.428" y="324.734" width="63.572" height="49.266"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="693.428" y="324.734" width="63.572" height="49.266"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="374" x2="443.262" y2="333"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="324.734" x2="443.262" y2="284.466"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="374" x2="508" y2="333"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="324.734" x2="508" y2="284.466"/>
- <g>
- <ellipse style="fill: #ffffff" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.94" y1="343.984" x2="980.274" y2="344.012"/>
- <polygon style="fill: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.248" y="333.8">
- <tspan x="849.248" y="333.8">pad 3 (source)</tspan>
- </text>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="197" y="91">
- <tspan x="197" y="91">sink</tspan>
- <tspan x="197" y="107">crop</tspan>
- <tspan x="197" y="123">selection</tspan>
- </text>
- <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="553" y="95">
- <tspan x="553" y="95">source</tspan>
- <tspan x="553" y="111">crop</tspan>
- <tspan x="553" y="127">selection</tspan>
- </text>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="211" y1="132" x2="166.21" y2="135.287"/>
- <polygon style="fill: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="209" y1="131" x2="115.581" y2="306.209"/>
- <polygon style="fill: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.492" y1="133.214" x2="514.916" y2="186.469"/>
- <polygon style="fill: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.072" y1="133.787" x2="510.618" y2="275.089"/>
- <polygon style="fill: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
- </g>
-</svg>
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdf b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdf
deleted file mode 100644
index 8f7a95b6eb4d..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg b/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg
deleted file mode 100644
index 2340c0f8bc92..000000000000
--- a/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="17cm" viewBox="-194 128 1179 330" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="806" height="327"/>
- <g>
- <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="49.5" y="204" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="49.5" y="204" width="94" height="77"/>
- </g>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="60" y="224">
- <tspan x="60" y="224">sink</tspan>
- <tspan x="60" y="240">crop</tspan>
- <tspan x="60" y="256">selection</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
- <tspan x="29.5" y="158"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
- <tspan x="8.53836" y="157.914">sink media</tspan>
- <tspan x="8.53836" y="173.914">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="49.5" y2="281"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="49.5" y2="204"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="143.5" y2="281"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="143.5" y2="204"/>
- <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
- <tspan x="334.704" y="149.442">sink compose</tspan>
- <tspan x="334.704" y="165.442">selection (scaling)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="382.322" y="199.565" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="382.322" y="199.565" width="100.186" height="71.4523"/>
- </g>
- <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="543.322" y="149.442">
- <tspan x="543.322" y="149.442">source</tspan>
- <tspan x="543.322" y="165.442">crop</tspan>
- <tspan x="543.322" y="181.442">selection</tspan>
- </text>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="691.5" y="157.128">
- <tspan x="691.5" y="157.128">source media</tspan>
- <tspan x="691.5" y="173.128">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="690.488" y="225.834" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="690.488" y="225.834" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="297.286" x2="382.322" y2="271.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="225.834" x2="382.322" y2="199.565"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="297.286" x2="482.508" y2="271.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="225.834" x2="482.508" y2="199.565"/>
- <g>
- <ellipse style="fill: #ffffff" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="816.6" y1="249.984" x2="972.934" y2="250.012"/>
- <polygon style="fill: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="841.908" y="239.8">
- <tspan x="841.908" y="239.8">pad 1 (source)</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
- <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
- <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
- </text>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="389.822" y="276.666" width="100.186" height="71.4523"/>
- <g>
- <rect style="fill: #ffffff" x="689.988" y="345.934" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="689.988" y="345.934" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="417.386" x2="389.822" y2="348.118"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="345.934" x2="389.822" y2="276.666"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="417.386" x2="490.008" y2="348.118"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="345.934" x2="490.008" y2="276.666"/>
- <g>
- <ellipse style="fill: #ffffff" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="814.1" y1="384.084" x2="970.434" y2="384.112"/>
- <polygon style="fill: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="839.408" y="373.9">
- <tspan x="839.408" y="373.9">pad 2 (source)</tspan>
- </text>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546" y1="191" x2="492.157" y2="198.263"/>
- <polygon style="fill: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546.908" y1="190.725" x2="495.383" y2="268.548"/>
- <polygon style="fill: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
- </g>
-</svg>
diff --git a/Documentation/media/uapi/v4l/diff-v4l.rst b/Documentation/media/uapi/v4l/diff-v4l.rst
index 76b2ecab8657..8209eeb63dd2 100644
--- a/Documentation/media/uapi/v4l/diff-v4l.rst
+++ b/Documentation/media/uapi/v4l/diff-v4l.rst
@@ -648,12 +648,12 @@ microcode programming. A new interface for MPEG compression and playback
devices is documented in :ref:`extended-controls`.
.. [#f1]
- According to Documentation/devices.txt these should be symbolic links
+ According to Documentation/admin-guide/devices.rst these should be symbolic links
to ``/dev/video0``. Note the original bttv interface is not
compatible with V4L or V4L2.
.. [#f2]
- According to ``Documentation/devices.txt`` a symbolic link to
+ According to ``Documentation/admin-guide/devices.rst`` a symbolic link to
``/dev/radio0``.
.. [#f3]
diff --git a/Documentation/media/uapi/v4l/field-order.rst b/Documentation/media/uapi/v4l/field-order.rst
index 50779a67c3fd..e05fb1041363 100644
--- a/Documentation/media/uapi/v4l/field-order.rst
+++ b/Documentation/media/uapi/v4l/field-order.rst
@@ -141,8 +141,8 @@ enum v4l2_field
Field Order, Top Field First Transmitted
========================================
-.. figure:: field-order_files/fieldseq_tb.*
- :alt: fieldseq_tb.pdf / fieldseq_tb.gif
+.. figure:: fieldseq_tb.*
+ :alt: fieldseq_tb.pdf / fieldseq_tb.svg
:align: center
@@ -151,7 +151,7 @@ Field Order, Top Field First Transmitted
Field Order, Bottom Field First Transmitted
===========================================
-.. figure:: field-order_files/fieldseq_bt.*
- :alt: fieldseq_bt.pdf / fieldseq_bt.gif
+.. figure:: fieldseq_bt.*
+ :alt: fieldseq_bt.pdf / fieldseq_bt.svg
:align: center
diff --git a/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gif b/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gif
deleted file mode 100644
index 60e8569a76c9..000000000000
--- a/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdf b/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdf
deleted file mode 100644
index 26598b23f80d..000000000000
--- a/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gif b/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gif
deleted file mode 100644
index 718492f1cfc7..000000000000
--- a/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gif
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf b/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf
deleted file mode 100644
index 4965b22ddb3a..000000000000
--- a/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/fieldseq_bt.svg b/Documentation/media/uapi/v4l/fieldseq_bt.svg
new file mode 100644
index 000000000000..b195301771ce
--- /dev/null
+++ b/Documentation/media/uapi/v4l/fieldseq_bt.svg
@@ -0,0 +1,2613 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg3619"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="198.48296mm"
+ height="211.89406mm"
+ viewBox="0 0 703.28606 750.80571"
+ sodipodi:docname="fieldseq_bt.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview3621"
+ showgrid="false"
+ units="mm"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="1.0721815"
+ inkscape:cx="8.4175633"
+ inkscape:cy="371.67214"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g3627" /><metadata
+ id="metadata3625"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3623"><clipPath
+ id="clipPath4301"
+ clipPathUnits="userSpaceOnUse"><path
+ style="clip-rule:evenodd"
+ inkscape:connector-curvature="0"
+ id="path4303"
+ d="M 0,6040 0,0 l 5650,0 0,6040 -5650,0 z m 4786.76,-99.89 103.92,0 0,56.69 -103.92,0 0,0 85.03,-28.35 -85.03,-28.34 z" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,-1.0537,751.94632)"
+ inkscape:label="fieldseq_bt"
+ inkscape:groupmode="layer"
+ id="g3627"><path
+ d="m 188.622,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3631"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3633"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,346.001 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3635"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3637"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3639"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3641"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,482.052 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3643"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,482.052 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3645"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3647"
+ inkscape:connector-curvature="0" /><path
+ d="m 188.622,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3649"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3651"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,214.201 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3653"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3655"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3657"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3659"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3661"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3663"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3665"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3667"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3669"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3671"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3673"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3675"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3677"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3679"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3681"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3683"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3685"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,482.052 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3687"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3689"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3691"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3693"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3695"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3697"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3699"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3701"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3703"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3705"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3707"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3709"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3711"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3713"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3715"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3717"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3719"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3721"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3723"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3725"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3727"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3729"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3731"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3733"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3735"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3737"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3739"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3741"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3743"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3745"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3747"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3749"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3751"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3753"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3755"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3757"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3759"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3761"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3763"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3765"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3767"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3769"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3771"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3773"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3775"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3777"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3779"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3781"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3783"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3785"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3787"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3789"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3791"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3793"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3795"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3797"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3799"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3801"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3803"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3805"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3807"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3809"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3811"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3813"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3815"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3817"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3819"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3821"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3823"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3825"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3827"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3829"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3831"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3833"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3835"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3837"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3839"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3841"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3843"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3845"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3847"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,380.014 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3849"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,380.014 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3851"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,371.511 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3853"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,371.511 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3855"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,363.007 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3857"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,363.007 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3859"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,354.504 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3861"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,354.504 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3863"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,358.755 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3865"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,358.755 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3867"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,350.252 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3869"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,350.252 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3871"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,367.259 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3873"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,367.259 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3875"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,375.762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3877"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,375.762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3879"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3881"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3883"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3885"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3887"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3889"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3891"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3893"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3895"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3897"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3899"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3901"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3903"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3905"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3907"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3909"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3911"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3913"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3915"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3917"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3919"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3921"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3923"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3925"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3927"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3929"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3931"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3933"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3935"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3937"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3939"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3941"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3943"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3945"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3947"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3949"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3951"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3953"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3955"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3957"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3959"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3961"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3963"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3965"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3967"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3969"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3971"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3973"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3975"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3977"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3979"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3981"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3983"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3985"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3987"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3989"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3991"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3993"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3995"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path3997"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path3999"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4001"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4003"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4005"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4007"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4009"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4011"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4013"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4015"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4017"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4019"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4021"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4023"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4025"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4027"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4029"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4031"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4033"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4035"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4037"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4039"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4041"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4043"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4045"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4047"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4049"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4051"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4053"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4055"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4057"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4059"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4061"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4063"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4065"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4067"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4069"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4071"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,516.065 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4073"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,516.065 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4075"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,507.562 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4077"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,507.562 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4079"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,499.059 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4081"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,499.059 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4083"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,490.555 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4085"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,490.555 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4087"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,494.807 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4089"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,494.807 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4091"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,486.304 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4093"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,486.304 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4095"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,503.31 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4097"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,503.31 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4099"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,511.813 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4101"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,511.813 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4103"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4105"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4107"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4109"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4111"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4113"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4115"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4117"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4119"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4121"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4123"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4125"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4127"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4129"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4131"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4133"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4135"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4137"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4139"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4141"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4143"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4145"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4147"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4149"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4151"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4153"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4155"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4157"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4159"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4161"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4163"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4165"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4167"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,579.839 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4169"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,579.839 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4171"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,571.336 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4173"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,571.336 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4175"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,562.832 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4177"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,562.832 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4179"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,554.329 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4181"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,554.329 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4183"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,558.581 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4185"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,558.581 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4187"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,550.078 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4189"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,550.078 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4191"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,567.084 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4193"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,567.084 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4195"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,575.587 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4197"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,575.587 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4199"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4201"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4203"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4205"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4207"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4209"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4211"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4213"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4215"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4217"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4219"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4221"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4223"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4225"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4227"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4229"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4231"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4233"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4235"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4237"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4239"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4241"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4243"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4245"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4247"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4249"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4251"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4253"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4255"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4257"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4259"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4261"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4263"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4265"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4267"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4269"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4271"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4273"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4275"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4277"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4279"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4281"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4283"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4285"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4287"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4289"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4291"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4293"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4295"
+ inkscape:connector-curvature="0" /><g
+ transform="scale(0.1,0.1)"
+ id="g4297"
+ style=""><g
+ id="g4299"
+ clip-path="url(#clipPath4301)"
+ style=""><path
+ d="m 3778.18,5968.45 1105.42,0"
+ style="fill:none;stroke:#000000;stroke-width:14.17199993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4305"
+ inkscape:connector-curvature="0" /></g></g><path
+ d="m 478.676,594.011 8.503,2.834 -8.503,2.835 0,-5.669"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4307"
+ inkscape:connector-curvature="0" /><path
+ d="m 478.676,594.011 8.503,2.834 -8.503,2.835 0,-5.669 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4309"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,1.62109 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4311"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,1.62109 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4313"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,1.62109 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4315"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4317"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4319"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4321"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4323"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4325"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4327"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4329"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4331"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4333"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4335"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4337"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4339"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4341"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4343"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4345"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4347"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4349"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4351"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4353"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4355"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4357"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4359"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4361"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4363"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4365"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4367"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4369"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4371"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4373"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4375"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4377"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4379"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,69.6469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4381"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,69.6469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4383"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,65.3953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4385"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,65.3953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4387"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,61.1438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4389"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,61.1438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4391"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,56.8922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4393"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,56.8922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4395"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,52.6402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4397"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,52.6402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4399"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,48.3887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4401"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,48.3887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4403"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,44.1371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4405"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,44.1371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4407"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,5.87266 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4409"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,5.87266 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4411"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,10.1242 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4413"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,10.1242 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4415"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,14.3762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4417"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,14.3762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4419"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,18.6277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4421"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,18.6277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4423"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,22.8793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4425"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,22.8793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4427"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,27.1309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4429"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,27.1309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4431"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,31.3824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4433"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,31.3824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4435"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,39.8855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4437"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,39.8855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4439"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,35.634 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4441"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,35.634 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4443"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4445"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4447"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4449"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4451"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4453"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4455"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4457"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4459"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4461"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4463"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4465"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4467"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4469"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4471"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4473"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4475"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4477"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4479"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4481"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4483"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4485"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4487"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4489"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4491"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4493"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4495"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4497"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4499"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4501"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4503"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4505"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4507"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4509"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4511"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4513"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4515"
+ inkscape:connector-curvature="0" /><path
+ d="m 188.622,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4517"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4519"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4521"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4523"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4525"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4527"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4529"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4531"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4533"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4535"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4537"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4539"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4541"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4543"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4545"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4547"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4549"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4551"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4553"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4555"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4557"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4559"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4561"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4563"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4565"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4567"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4569"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4571"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4573"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4575"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4577"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4579"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4581"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4583"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4585"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4587"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4589"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4591"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4593"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4595"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4597"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4599"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4601"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4603"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4605"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4607"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4609"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4611"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4613"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4615"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4617"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4619"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4621"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4623"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4625"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4627"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4629"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4631"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4633"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4635"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4637"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4639"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4641"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4643"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4645"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4647"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4649"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4651"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4653"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4655"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4657"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4659"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4661"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4663"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4665"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4667"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4669"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4671"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4673"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4675"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4677"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4679"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4681"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4683"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4685"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4687"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4689"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4691"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4693"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4695"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4697"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4699"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4701"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4703"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4705"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,214.201 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4707"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4709"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4711"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4713"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4715"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4717"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4719"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4721"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4723"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4725"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4727"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4729"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4731"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4733"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4735"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4737"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4739"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4741"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4743"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4745"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4747"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4749"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4751"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4753"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4755"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4757"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4759"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4761"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4763"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4765"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4767"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4769"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4771"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,214.201 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4773"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,277.975 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4775"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,277.975 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4777"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,282.227 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4779"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,282.227 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4781"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,273.723 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4783"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,273.723 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4785"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,248.214 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4787"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,248.214 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4789"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,239.711 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4791"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,239.711 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4793"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,231.207 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4795"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,231.207 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4797"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,222.704 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4799"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,222.704 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4801"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,269.472 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4803"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,269.472 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4805"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,256.717 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4807"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,256.717 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4809"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,265.22 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4811"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,265.22 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4813"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,260.969 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4815"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,260.969 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4817"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,252.466 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4819"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,252.466 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4821"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,243.962 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4823"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,243.962 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4825"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,235.459 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4827"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,235.459 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4829"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,226.956 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4831"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,226.956 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4833"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,218.453 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path4835"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,218.453 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path4837"
+ inkscape:connector-curvature="0" /><text
+ y="-533.07098"
+ x="5.8031301"
+ id="text4841"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4843"
+ sodipodi:role="line"
+ y="-533.07098"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan><tspan
+ id="tspan4845"
+ sodipodi:role="line"
+ y="-465.04559"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan><tspan
+ id="tspan4847"
+ sodipodi:role="line"
+ y="-397.0202"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+ y="-316.23969"
+ x="103.58983"
+ id="text4849"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4851"
+ sodipodi:role="line"
+ y="-316.23969"
+ x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOM</tspan><tspan
+ id="tspan4853"
+ sodipodi:role="line"
+ y="-328.99481"
+ x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322">v4l2_buffer.field:</tspan></text>
+<text
+ y="-592.59381"
+ x="5.8034"
+ id="text4855"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4857"
+ sodipodi:role="line"
+ y="-592.59381"
+ x="5.8034 13.134789 19.806232 29.801399 36.472843 43.144287 47.139954 53.811398 56.475174 59.810898 66.482346 70.478004 77.149452 83.820892 87.816566 91.152283 94.488007 101.15945 107.83089 111.16662 114.50233 121.17377 131.16895 134.50468 137.84041 140.50418 147.17563 149.8394 156.51085 159.84657 163.1823 165.84607 169.84174 175.84123 179.17696 182.51268 185.8484 189.84407 196.51552 203.18695 209.18646 219.18163 221.8454 225.18112 228.51685 235.18829 241.85973 245.19545 249.19112 255.86256 259.19827 265.86972 269.20544 272.54117 282.53635 285.87207 294.53534 301.86673 309.87006 318.53336">Temporal order, bottom field first transmitted (e.g. M/NTSC)</tspan></text>
+<text
+ y="-316.23981"
+ x="290.6604"
+ id="text4859"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4861"
+ sodipodi:role="line"
+ y="-316.23981"
+ x="290.6604 296.16284 300.74957 305.3363 309.92303 314.50977 319.55023 321.8436 327.34601 331.93274 337.88889 342.47565 347.51608 353.9342 477.73062 483.23306 487.81979 492.40652 496.99326 501.57999 506.62045 508.91382 514.41626 519.00299 524.95911 529.5459 534.5863 541.00446">V4L2_FIELD_TOPV4L2_FIELD_TOP</tspan></text>
+<text
+ y="-299.23349"
+ x="5.8034"
+ id="text4863"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4865"
+ sodipodi:role="line"
+ y="-299.23349"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_BT</tspan><tspan
+ id="tspan4867"
+ sodipodi:role="line"
+ y="-192.9435"
+ x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001">V4L2_FIELD_INTERLACED_TB (misaligned)</tspan><tspan
+ id="tspan4869"
+ sodipodi:role="line"
+ y="-86.653496"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579">V4L2_FIELD_SEQ_BT</tspan></text>
+<text
+ y="-533.07098"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464"
+ id="text4592"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4594"
+ sodipodi:role="line"
+ y="-533.07098"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan></text>
+<text
+ y="-465.04559"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054"
+ id="text4596"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4598"
+ sodipodi:role="line"
+ y="-465.04559"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan></text>
+<text
+ y="-397.0202"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963"
+ id="text4600"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4602"
+ sodipodi:role="line"
+ y="-397.0202"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+ y="-299.23349"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012"
+ id="text5862"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5864"
+ sodipodi:role="line"
+ y="-299.23349"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_BT</tspan></text>
+<text
+ y="-192.9435"
+ x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001"
+ id="text5866"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5868"
+ sodipodi:role="line"
+ y="-192.9435"
+ x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001">V4L2_FIELD_INTERLACED_TB (misaligned)</tspan></text>
+<text
+ y="-86.653496"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579"
+ id="text5870"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5872"
+ sodipodi:role="line"
+ y="-86.653496"
+ x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579">V4L2_FIELD_SEQ_BT</tspan></text>
+<text
+ y="-316.23969"
+ x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659"
+ id="text7144"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan7146"
+ sodipodi:role="line"
+ y="-316.23969"
+ x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOM</tspan></text>
+<text
+ y="-328.99481"
+ x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322"
+ id="text7148"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan7150"
+ sodipodi:role="line"
+ y="-328.99481"
+ x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322">v4l2_buffer.field:</tspan></text>
+</g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/fieldseq_tb.svg b/Documentation/media/uapi/v4l/fieldseq_tb.svg
new file mode 100644
index 000000000000..6a7b10ad4ab8
--- /dev/null
+++ b/Documentation/media/uapi/v4l/fieldseq_tb.svg
@@ -0,0 +1,2607 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg5543"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="198.48296mm"
+ height="210.39415mm"
+ viewBox="0 0 703.28607 745.49109"
+ sodipodi:docname="fieldseq_tb.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview5545"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ units="mm"
+ inkscape:zoom="1.0733333"
+ inkscape:cx="9.8391479"
+ inkscape:cy="370.19322"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g5551" /><metadata
+ id="metadata5549"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs5547"><clipPath
+ id="clipPath6753"
+ clipPathUnits="userSpaceOnUse"><path
+ style="clip-rule:evenodd"
+ inkscape:connector-curvature="0"
+ id="path6755"
+ d="M 0,6000 0,0 l 5660,0 0,6000 -5660,0 z m 4786.76,-102.89 103.92,0 0,56.69 -103.92,0 0,0 85.03,-28.35 -85.03,-28.34 z" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,-1.0537,746.57119)"
+ inkscape:label="fieldseq_tb"
+ inkscape:groupmode="layer"
+ id="g5551"><path
+ d="m 379.944,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5555"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5557"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5559"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5561"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5563"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5565"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5567"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5569"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5571"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5573"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5575"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5577"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5579"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5581"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5583"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5585"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5587"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5589"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5591"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5593"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5595"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5597"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5599"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5601"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5603"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5605"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5607"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5609"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5611"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5613"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5615"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5617"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5619"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5621"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5623"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5625"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5627"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5629"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5631"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5633"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5635"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5637"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5639"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5641"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5643"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5645"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5647"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5649"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5651"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5653"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5655"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5657"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5659"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5661"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5663"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5665"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5667"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5669"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5671"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5673"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5675"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5677"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5679"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5681"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5683"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5685"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5687"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5689"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5691"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5693"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5695"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5697"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5699"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5701"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5703"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5705"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5707"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5709"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5711"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5713"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5715"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5717"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5719"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5721"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5723"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5725"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5727"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5729"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5731"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5733"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5735"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5737"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5739"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5741"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5743"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5745"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5747"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5749"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5751"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5753"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5755"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5757"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5759"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5761"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5763"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5765"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5767"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5769"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5771"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5773"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5775"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5777"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5779"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5781"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5783"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5785"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5787"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5789"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5791"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5793"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5795"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5797"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5799"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5801"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5803"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5805"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5807"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5809"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5811"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5813"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5815"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5817"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5819"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5821"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5823"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5825"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5827"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5829"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5831"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5833"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5835"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5837"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5839"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5841"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5843"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5845"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5847"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5849"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5851"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5853"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5855"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5857"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5859"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5861"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5863"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5865"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5867"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5869"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5871"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5873"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5875"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5877"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5879"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5881"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5883"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5885"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5887"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5889"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5891"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5893"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5895"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5897"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5899"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5901"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5903"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5905"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5907"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5909"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5911"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5913"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5915"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5917"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5919"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5921"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5923"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5925"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5927"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5929"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5931"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5933"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5935"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5937"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,409.727 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5939"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,409.727 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5941"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,409.727 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5943"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,209.901 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5945"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,209.901 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5947"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,209.901 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5949"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5951"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,341.701 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5953"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5955"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5957"
+ inkscape:connector-curvature="0" /><path
+ d="m 188.622,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5959"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5961"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5963"
+ inkscape:connector-curvature="0" /><path
+ d="m 188.622,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5965"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5967"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5969"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5971"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5973"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5975"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5977"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5979"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5981"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5983"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5985"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5987"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5989"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5991"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5993"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5995"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5997"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path5999"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6001"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6003"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6005"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6007"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6009"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6011"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6013"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6015"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6017"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6019"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6021"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6023"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6025"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6027"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6029"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6031"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6033"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6035"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6037"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6039"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6041"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6043"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6045"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6047"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6049"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6051"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6053"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6055"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6057"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6059"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6061"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6063"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6065"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6067"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6069"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6071"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6073"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6075"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6077"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6079"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6081"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6083"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6085"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6087"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6089"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6091"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6093"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6095"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6097"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6099"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,575.539 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6101"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,575.539 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6103"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6105"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6107"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6109"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6111"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6113"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6115"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6117"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6119"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6121"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6123"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6125"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6127"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6129"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6131"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6133"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6135"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6137"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6139"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6141"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6143"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6145"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6147"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6149"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6151"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6153"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6155"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6157"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6159"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6161"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6163"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6165"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6167"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6169"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6171"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6173"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6175"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6177"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6179"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6181"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6183"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6185"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6187"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6189"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6191"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6193"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6195"
+ inkscape:connector-curvature="0" /><path
+ d="m 1.55156,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6197"
+ inkscape:connector-curvature="0" /><path
+ d="m 188.622,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6199"
+ inkscape:connector-curvature="0" /><path
+ d="m 375.693,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6201"
+ inkscape:connector-curvature="0" /><path
+ d="m 95.0867,1.57266 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6203"
+ inkscape:connector-curvature="0" /><path
+ d="m 282.157,1.57266 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6205"
+ inkscape:connector-curvature="0" /><path
+ d="m 469.228,1.57266 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+ style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6207"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6209"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6211"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6213"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6215"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6217"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6219"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6221"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6223"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6225"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6227"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6229"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6231"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6233"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6235"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6237"
+ inkscape:connector-curvature="0" /><path
+ d="m 473.479,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6239"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6241"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6243"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6245"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6247"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6249"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6251"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6253"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6255"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6257"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6259"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6261"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6263"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6265"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6267"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6269"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6271"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,277.927 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6273"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,277.927 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6275"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,269.423 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6277"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,269.423 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6279"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,260.92 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6281"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,260.92 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6283"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,252.417 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6285"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,252.417 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6287"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,243.914 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6289"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,243.914 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6291"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,235.411 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6293"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,235.411 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6295"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,226.907 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6297"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,226.907 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6299"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,218.404 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6301"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,218.404 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6303"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,69.5984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6305"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,69.5984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6307"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,65.3469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6309"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,65.3469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6311"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,61.0953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6313"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,61.0953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6315"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,56.8438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6317"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,56.8438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6319"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,52.5922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6321"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,52.5922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6323"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,48.3402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6325"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,48.3402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6327"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,44.0887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6329"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,44.0887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6331"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,39.8371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6333"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,39.8371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6335"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,571.287 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6337"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,571.287 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6339"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,567.036 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6341"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,567.036 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6343"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,562.784 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6345"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,562.784 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6347"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,558.532 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6349"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,558.532 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6351"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,554.281 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6353"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,554.281 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6355"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,550.029 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6357"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,550.029 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6359"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,545.778 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6361"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,545.778 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6363"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,443.739 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6365"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,443.739 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6367"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,439.488 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6369"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,439.488 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6371"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,435.236 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6373"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,435.236 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6375"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,430.984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6377"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,430.984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6379"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,426.733 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6381"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,426.733 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6383"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,422.481 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6385"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,422.481 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6387"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,418.23 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6389"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,418.23 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6391"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,413.978 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6393"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,413.978 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6395"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,375.714 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6397"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,375.714 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6399"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,371.462 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6401"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,371.462 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6403"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,367.211 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6405"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,367.211 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6407"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,362.959 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6409"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,362.959 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6411"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,358.707 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6413"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,358.707 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6415"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,354.455 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6417"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,354.455 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6419"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,350.204 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6421"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,350.204 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6423"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,345.952 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6425"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,345.952 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6427"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,273.675 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6429"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,273.675 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6431"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,265.172 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6433"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,265.172 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6435"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,256.669 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6437"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,256.669 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6439"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,248.166 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6441"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,248.166 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6443"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,239.662 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6445"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,239.662 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6447"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,231.159 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6449"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,231.159 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6451"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,222.656 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6453"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,222.656 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6455"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,214.153 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6457"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,214.153 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6459"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,35.5855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6461"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,35.5855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6463"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,31.334 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6465"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,31.334 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6467"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,27.0824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6469"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,27.0824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6471"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,22.8309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6473"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,22.8309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6475"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,18.5793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6477"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,18.5793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6479"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,14.3277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6481"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,14.3277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6483"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,10.0762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6485"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,10.0762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6487"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,5.82422 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6489"
+ inkscape:connector-curvature="0" /><path
+ d="m 286.409,5.82422 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6491"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6493"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6495"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6497"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6499"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6501"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6503"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6505"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6507"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6509"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6511"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6513"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6515"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6517"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6519"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6521"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6523"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6525"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6527"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6529"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6531"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6533"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6535"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6537"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6539"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6541"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6543"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6545"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6547"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6549"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6551"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6553"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6555"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6557"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6559"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6561"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6563"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6565"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6567"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6569"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6571"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6573"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6575"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6577"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6579"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6581"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6583"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6585"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6587"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6589"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6591"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6593"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6595"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6597"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6599"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6601"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6603"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6605"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6607"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6609"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6611"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6613"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6615"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6617"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6619"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6621"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6623"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6625"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6627"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6629"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6631"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6633"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6635"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6637"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6639"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6641"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6643"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6645"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6647"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6649"
+ inkscape:connector-curvature="0" /><path
+ d="m 99.3383,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6651"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6653"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6655"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6657"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6659"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6661"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6663"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6665"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6667"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6669"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6671"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6673"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6675"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6677"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6679"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6681"
+ inkscape:connector-curvature="0" /><path
+ d="m 192.873,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6683"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6685"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6687"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6689"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6691"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6693"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6695"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6697"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6699"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6701"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6703"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6705"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6707"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6709"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6711"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6713"
+ inkscape:connector-curvature="0" /><path
+ d="m 379.944,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6715"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6717"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6719"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6721"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6723"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6725"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6727"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6729"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6731"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6733"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6735"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6737"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6739"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6741"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6743"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6745"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.80312,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6747"
+ inkscape:connector-curvature="0" /><g
+ transform="scale(0.1,0.1)"
+ id="g6749"
+ style=""><g
+ id="g6751"
+ clip-path="url(#clipPath6753)"
+ style=""><path
+ d="m 3778.18,5925.45 1105.42,0"
+ style="fill:none;stroke:#000000;stroke-width:14.17199993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6757"
+ inkscape:connector-curvature="0" /></g></g><path
+ d="m 478.676,589.711 8.503,2.834 -8.503,2.835 0,-5.669"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path6759"
+ inkscape:connector-curvature="0" /><path
+ d="m 478.676,589.711 8.503,2.834 -8.503,2.835 0,-5.669 z"
+ style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path6761"
+ inkscape:connector-curvature="0" /><text
+ y="-528.771"
+ x="5.8031301"
+ id="text6765"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan6767"
+ sodipodi:role="line"
+ y="-528.771"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan><tspan
+ id="tspan6769"
+ sodipodi:role="line"
+ y="-460.74561"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan><tspan
+ id="tspan6771"
+ sodipodi:role="line"
+ y="-392.72021"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+ y="-324.69479"
+ x="10.05469"
+ id="text6773"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan6775"
+ sodipodi:role="line"
+ y="-324.69479"
+ x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048">v4l2_buffer.field:</tspan><tspan
+ id="tspan6777"
+ sodipodi:role="line"
+ y="-311.9397"
+ x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOM</tspan></text>
+<text
+ y="-588.2937"
+ x="5.8031301"
+ id="text6779"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan6781"
+ sodipodi:role="line"
+ y="-588.2937"
+ x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096">Temporal order, top field first transmitted (e.g. BG/PAL)</tspan><tspan
+ id="tspan6783"
+ sodipodi:role="line"
+ y="-86.604706"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357">V4L2_FIELD_SEQ_TB</tspan><tspan
+ id="tspan6785"
+ sodipodi:role="line"
+ y="-192.89471"
+ x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286">V4L2_FIELD_INTERLACED_BT (misaligned)</tspan><tspan
+ id="tspan6787"
+ sodipodi:role="line"
+ y="-294.93271"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_TB</tspan></text>
+<text
+ y="-528.771"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464"
+ id="text4583"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4585"
+ sodipodi:role="line"
+ y="-528.771"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan></text>
+<text
+ y="-460.74561"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054"
+ id="text4587"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4589"
+ sodipodi:role="line"
+ y="-460.74561"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan></text>
+<text
+ y="-392.72021"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963"
+ id="text4591"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan4593"
+ sodipodi:role="line"
+ y="-392.72021"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+ y="-588.2937"
+ x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096"
+ id="text5847"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5849"
+ sodipodi:role="line"
+ y="-588.2937"
+ x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096">Temporal order, top field first transmitted (e.g. BG/PAL)</tspan></text>
+<text
+ y="-86.604706"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357"
+ id="text5851"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5853"
+ sodipodi:role="line"
+ y="-86.604706"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357">V4L2_FIELD_SEQ_TB</tspan></text>
+<text
+ y="-192.89471"
+ x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286"
+ id="text5855"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5857"
+ sodipodi:role="line"
+ y="-192.89471"
+ x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286">V4L2_FIELD_INTERLACED_BT (misaligned)</tspan></text>
+<text
+ y="-294.93271"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791"
+ id="text5859"
+ style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan5861"
+ sodipodi:role="line"
+ y="-294.93271"
+ x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_TB</tspan></text>
+<text
+ y="-324.69479"
+ x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048"
+ id="text7131"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan7133"
+ sodipodi:role="line"
+ y="-324.69479"
+ x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048">v4l2_buffer.field:</tspan></text>
+<text
+ y="-311.9397"
+ x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624"
+ id="text7135"
+ style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan7137"
+ sodipodi:role="line"
+ y="-311.9397"
+ x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOM</tspan></text>
+</g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/nv12mt.svg b/Documentation/media/uapi/v4l/nv12mt.svg
new file mode 100644
index 000000000000..21fcccda9723
--- /dev/null
+++ b/Documentation/media/uapi/v4l/nv12mt.svg
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.2"
+ width="96.282211mm"
+ height="28.282219mm"
+ viewBox="0 0 9628.2211 2828.2219"
+ preserveAspectRatio="xMidYMid"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="nv12mt.svg"
+ style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+ id="metadata383"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview381"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="4.0919524"
+ inkscape:cx="170.57872"
+ inkscape:cy="50.106293"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ class="ClipPathGroup"
+ id="defs4"><clipPath
+ id="presentation_clip_path"
+ clipPathUnits="userSpaceOnUse"><rect
+ x="0"
+ y="0"
+ width="28000"
+ height="21000"
+ id="rect7" /></clipPath></defs><defs
+ id="defs9" /><defs
+ id="defs80" /><defs
+ id="defs103" /><defs
+ class="TextShapeIndex"
+ id="defs114" /><defs
+ class="EmbeddedBulletChars"
+ id="defs118" /><defs
+ class="TextEmbeddedBitmaps"
+ id="defs147" /><g
+ class="SlideGroup"
+ id="g177"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="g179"><g
+ id="id1"
+ class="Slide"
+ clip-path="url(#presentation_clip_path)"><g
+ class="Page"
+ id="g182"><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g184"><g
+ id="id6"><rect
+ class="BoundingBox"
+ x="3299"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect187"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path189"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text191"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan193"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4325"
+ y="4121"
+ id="tspan195"><tspan
+ id="tspan197"
+ style="fill:#000000;stroke:none">0</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g199"><g
+ id="id7"><rect
+ class="BoundingBox"
+ x="5699"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect202"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path204"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g206"><g
+ id="id8"><rect
+ class="BoundingBox"
+ x="8099"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect209"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path211"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text213"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan215"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="9125"
+ y="4121"
+ id="tspan217"><tspan
+ id="tspan219"
+ style="fill:#000000;stroke:none">6</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g221"><g
+ id="id9"><rect
+ class="BoundingBox"
+ x="5699"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect224"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path226"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text228"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan230"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6725"
+ y="4121"
+ id="tspan232"><tspan
+ id="tspan234"
+ style="fill:#000000;stroke:none">1</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g236"><g
+ id="id10"><rect
+ class="BoundingBox"
+ x="10499"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect239"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path241"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text243"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan245"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11525"
+ y="4121"
+ id="tspan247"><tspan
+ id="tspan249"
+ style="fill:#000000;stroke:none">7</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g251"><g
+ id="id11"><rect
+ class="BoundingBox"
+ x="3299"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect254"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path256"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text258"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan260"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4325"
+ y="5521"
+ id="tspan262"><tspan
+ id="tspan264"
+ style="fill:#000000;stroke:none">2</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g266"><g
+ id="id12"><rect
+ class="BoundingBox"
+ x="5699"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect269"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path271"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g273"><g
+ id="id13"><rect
+ class="BoundingBox"
+ x="8099"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect276"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path278"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text280"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan282"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="9125"
+ y="5521"
+ id="tspan284"><tspan
+ id="tspan286"
+ style="fill:#000000;stroke:none">4</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g288"><g
+ id="id14"><rect
+ class="BoundingBox"
+ x="5699"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect291"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path293"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text295"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan297"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6725"
+ y="5521"
+ id="tspan299"><tspan
+ id="tspan301"
+ style="fill:#000000;stroke:none">3</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g303"><g
+ id="id15"><rect
+ class="BoundingBox"
+ x="10499"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect306"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path308"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text310"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan312"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11525"
+ y="5521"
+ id="tspan314"><tspan
+ id="tspan316"
+ style="fill:#000000;stroke:none">5</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g318"><g
+ id="id16"><rect
+ class="BoundingBox"
+ x="5199"
+ y="3850"
+ width="1402"
+ height="301"
+ id="rect321"
+ style="fill:none;stroke:none" /><path
+ d="m 5200,4000 970,0"
+ id="path323"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,4000 -450,-150 0,300 450,-150 z"
+ id="path325"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g327"><g
+ id="id17"><rect
+ class="BoundingBox"
+ x="5000"
+ y="4299"
+ width="1202"
+ height="802"
+ id="rect330"
+ style="fill:none;stroke:none" /><path
+ d="m 6200,4300 -842,561"
+ id="path332"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 5000,5100 458,-125 -167,-249 -291,374 z"
+ id="path334"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g336"><g
+ id="id18"><rect
+ class="BoundingBox"
+ x="5399"
+ y="5250"
+ width="1202"
+ height="301"
+ id="rect339"
+ style="fill:none;stroke:none" /><path
+ d="m 5400,5400 770,0"
+ id="path341"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,5400 -450,-150 0,300 450,-150 z"
+ id="path343"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g345"><g
+ id="id19"><rect
+ class="BoundingBox"
+ x="7599"
+ y="5250"
+ width="1202"
+ height="301"
+ id="rect348"
+ style="fill:none;stroke:none" /><path
+ d="m 7600,5400 770,0"
+ id="path350"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 8800,5400 -450,-150 0,300 450,-150 z"
+ id="path352"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g354"><g
+ id="id20"><rect
+ class="BoundingBox"
+ x="9799"
+ y="5250"
+ width="1402"
+ height="301"
+ id="rect357"
+ style="fill:none;stroke:none" /><path
+ d="m 9800,5400 970,0"
+ id="path359"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11200,5400 -450,-150 0,300 450,-150 z"
+ id="path361"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g363"><g
+ id="id21"><rect
+ class="BoundingBox"
+ x="9900"
+ y="4200"
+ width="1202"
+ height="802"
+ id="rect366"
+ style="fill:none;stroke:none" /><path
+ d="m 11100,5000 -842,-561"
+ id="path368"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 9900,4200 291,374 167,-249 -458,-125 z"
+ id="path370"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g372"><g
+ id="id22"><rect
+ class="BoundingBox"
+ x="9999"
+ y="3850"
+ width="1402"
+ height="301"
+ id="rect375"
+ style="fill:none;stroke:none" /><path
+ d="m 10000,4000 970,0"
+ id="path377"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11400,4000 -450,-150 0,300 450,-150 z"
+ id="path379"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g></g></g></g></g></svg>
diff --git a/Documentation/media/uapi/v4l/nv12mt_example.svg b/Documentation/media/uapi/v4l/nv12mt_example.svg
new file mode 100644
index 000000000000..d65d989ee73b
--- /dev/null
+++ b/Documentation/media/uapi/v4l/nv12mt_example.svg
@@ -0,0 +1,1589 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.2"
+ width="144.28223mm"
+ height="70.282227mm"
+ viewBox="0 0 14428.222 7028.2226"
+ preserveAspectRatio="xMidYMid"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="nv12mt_example.svg"
+ style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+ id="metadata953"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview951"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="2.7306359"
+ inkscape:cx="255.61812"
+ inkscape:cy="124.51576"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><defs
+ class="ClipPathGroup"
+ id="defs4" /><defs
+ id="defs9" /><defs
+ id="defs84" /><defs
+ id="defs107" /><defs
+ class="TextShapeIndex"
+ id="defs118" /><defs
+ class="EmbeddedBulletChars"
+ id="defs122" /><defs
+ class="TextEmbeddedBitmaps"
+ id="defs151" /><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g188"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id6"><rect
+ class="BoundingBox"
+ x="3299"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect191"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path193"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text195"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan197"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4325"
+ y="4121"
+ id="tspan199"><tspan
+ id="tspan201"
+ style="fill:#000000;stroke:none">0</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g203"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id7"><rect
+ class="BoundingBox"
+ x="5699"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect206"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path208"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g210"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id8"><rect
+ class="BoundingBox"
+ x="8099"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect213"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path215"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text217"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan219"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="9125"
+ y="4121"
+ id="tspan221"><tspan
+ id="tspan223"
+ style="fill:#000000;stroke:none">6</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g225"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id9"><rect
+ class="BoundingBox"
+ x="5699"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect228"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path230"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text232"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan234"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6725"
+ y="4121"
+ id="tspan236"><tspan
+ id="tspan238"
+ style="fill:#000000;stroke:none">1</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g240"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id10"><rect
+ class="BoundingBox"
+ x="10499"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect243"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path245"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text247"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan249"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11525"
+ y="4121"
+ id="tspan251"><tspan
+ id="tspan253"
+ style="fill:#000000;stroke:none">7</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g255"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id11"><rect
+ class="BoundingBox"
+ x="12899"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect258"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path260"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g262"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id12"><rect
+ class="BoundingBox"
+ x="15299"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect265"
+ style="fill:none;stroke:none" /><path
+ d="m 16500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path267"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text269"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan271"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="16325"
+ y="4121"
+ id="tspan273"><tspan
+ id="tspan275"
+ style="fill:#000000;stroke:none">9</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g277"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id13"><rect
+ class="BoundingBox"
+ x="12899"
+ y="3199"
+ width="2403"
+ height="1403"
+ id="rect280"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path282"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text284"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan286"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="13925"
+ y="4121"
+ id="tspan288"><tspan
+ id="tspan290"
+ style="fill:#000000;stroke:none">8</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g292"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id14"><rect
+ class="BoundingBox"
+ x="3299"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect295"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path297"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text299"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan301"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4325"
+ y="5521"
+ id="tspan303"><tspan
+ id="tspan305"
+ style="fill:#000000;stroke:none">2</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g307"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id15"><rect
+ class="BoundingBox"
+ x="5699"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect310"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path312"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g314"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id16"><rect
+ class="BoundingBox"
+ x="8099"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect317"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path319"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text321"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan323"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="9125"
+ y="5521"
+ id="tspan325"><tspan
+ id="tspan327"
+ style="fill:#000000;stroke:none">4</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g329"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id17"><rect
+ class="BoundingBox"
+ x="5699"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect332"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path334"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text336"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan338"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6725"
+ y="5521"
+ id="tspan340"><tspan
+ id="tspan342"
+ style="fill:#000000;stroke:none">3</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g344"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id18"><rect
+ class="BoundingBox"
+ x="10499"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect347"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path349"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text351"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan353"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11525"
+ y="5521"
+ id="tspan355"><tspan
+ id="tspan357"
+ style="fill:#000000;stroke:none">5</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g359"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id19"><rect
+ class="BoundingBox"
+ x="12899"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect362"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path364"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g366"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id20"><rect
+ class="BoundingBox"
+ x="15299"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect369"
+ style="fill:none;stroke:none" /><path
+ d="m 16500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path371"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text373"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan375"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="16149"
+ y="5521"
+ id="tspan377"><tspan
+ id="tspan379"
+ style="fill:#000000;stroke:none">11</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g381"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id21"><rect
+ class="BoundingBox"
+ x="12899"
+ y="4599"
+ width="2403"
+ height="1403"
+ id="rect384"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path386"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text388"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan390"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="13749"
+ y="5521"
+ id="tspan392"><tspan
+ id="tspan394"
+ style="fill:#000000;stroke:none">10</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g396"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id22"><rect
+ class="BoundingBox"
+ x="3299"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect399"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path401"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text403"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan405"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4149"
+ y="6921"
+ id="tspan407"><tspan
+ id="tspan409"
+ style="fill:#000000;stroke:none">12</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g411"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id23"><rect
+ class="BoundingBox"
+ x="5699"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect414"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path416"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g418"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id24"><rect
+ class="BoundingBox"
+ x="8099"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect421"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path423"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text425"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan427"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="8949"
+ y="6921"
+ id="tspan429"><tspan
+ id="tspan431"
+ style="fill:#000000;stroke:none">18</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g433"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id25"><rect
+ class="BoundingBox"
+ x="5699"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect436"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path438"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text440"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan442"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6549"
+ y="6921"
+ id="tspan444"><tspan
+ id="tspan446"
+ style="fill:#000000;stroke:none">13</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g448"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id26"><rect
+ class="BoundingBox"
+ x="10499"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect451"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path453"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text455"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan457"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11349"
+ y="6921"
+ id="tspan459"><tspan
+ id="tspan461"
+ style="fill:#000000;stroke:none">19</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g463"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id27"><rect
+ class="BoundingBox"
+ x="12899"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect466"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path468"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g470"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id28"><rect
+ class="BoundingBox"
+ x="15299"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect473"
+ style="fill:none;stroke:none" /><path
+ d="m 16500,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path475"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text477"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan479"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="16149"
+ y="6921"
+ id="tspan481"><tspan
+ id="tspan483"
+ style="fill:#000000;stroke:none">21</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g485"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id29"><rect
+ class="BoundingBox"
+ x="12899"
+ y="5999"
+ width="2403"
+ height="1403"
+ id="rect488"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path490"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text492"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan494"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="13749"
+ y="6921"
+ id="tspan496"><tspan
+ id="tspan498"
+ style="fill:#000000;stroke:none">20</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g500"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id30"><rect
+ class="BoundingBox"
+ x="3299"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect503"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path505"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text507"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan509"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4149"
+ y="8321"
+ id="tspan511"><tspan
+ id="tspan513"
+ style="fill:#000000;stroke:none">14</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g515"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id31"><rect
+ class="BoundingBox"
+ x="5699"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect518"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path520"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g522"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id32"><rect
+ class="BoundingBox"
+ x="8099"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect525"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path527"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text529"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan531"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="8949"
+ y="8321"
+ id="tspan533"><tspan
+ id="tspan535"
+ style="fill:#000000;stroke:none">16</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g537"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id33"><rect
+ class="BoundingBox"
+ x="5699"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect540"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path542"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text544"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan546"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6549"
+ y="8321"
+ id="tspan548"><tspan
+ id="tspan550"
+ style="fill:#000000;stroke:none">15</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g552"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id34"><rect
+ class="BoundingBox"
+ x="10499"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect555"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path557"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text559"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan561"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11349"
+ y="8321"
+ id="tspan563"><tspan
+ id="tspan565"
+ style="fill:#000000;stroke:none">17</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g567"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id35"><rect
+ class="BoundingBox"
+ x="12899"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect570"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path572"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g574"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id36"><rect
+ class="BoundingBox"
+ x="15299"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect577"
+ style="fill:none;stroke:none" /><path
+ d="m 16500,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path579"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text581"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan583"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="16149"
+ y="8321"
+ id="tspan585"><tspan
+ id="tspan587"
+ style="fill:#000000;stroke:none">23</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g589"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id37"><rect
+ class="BoundingBox"
+ x="12899"
+ y="7399"
+ width="2403"
+ height="1403"
+ id="rect592"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path594"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text596"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan598"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="13749"
+ y="8321"
+ id="tspan600"><tspan
+ id="tspan602"
+ style="fill:#000000;stroke:none">22</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g604"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id38"><rect
+ class="BoundingBox"
+ x="3299"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect607"
+ style="fill:none;stroke:none" /><path
+ d="m 4500,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path609"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text611"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan613"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="4149"
+ y="9721"
+ id="tspan615"><tspan
+ id="tspan617"
+ style="fill:#000000;stroke:none">24</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g619"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id39"><rect
+ class="BoundingBox"
+ x="5699"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect622"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path624"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g626"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id40"><rect
+ class="BoundingBox"
+ x="8099"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect629"
+ style="fill:none;stroke:none" /><path
+ d="m 9300,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path631"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text633"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan635"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="8949"
+ y="9721"
+ id="tspan637"><tspan
+ id="tspan639"
+ style="fill:#000000;stroke:none">26</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g641"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id41"><rect
+ class="BoundingBox"
+ x="5699"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect644"
+ style="fill:none;stroke:none" /><path
+ d="m 6900,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path646"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text648"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan650"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="6549"
+ y="9721"
+ id="tspan652"><tspan
+ id="tspan654"
+ style="fill:#000000;stroke:none">25</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g656"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id42"><rect
+ class="BoundingBox"
+ x="10499"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect659"
+ style="fill:none;stroke:none" /><path
+ d="m 11700,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path661"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text663"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan665"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="11349"
+ y="9721"
+ id="tspan667"><tspan
+ id="tspan669"
+ style="fill:#000000;stroke:none">27</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g671"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id43"><rect
+ class="BoundingBox"
+ x="12899"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect674"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path676"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /></g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g678"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id44"><rect
+ class="BoundingBox"
+ x="15299"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect681"
+ style="fill:none;stroke:none" /><path
+ d="m 16500,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path683"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text685"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan687"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="16149"
+ y="9721"
+ id="tspan689"><tspan
+ id="tspan691"
+ style="fill:#000000;stroke:none">29</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.CustomShape"
+ id="g693"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id45"><rect
+ class="BoundingBox"
+ x="12899"
+ y="8799"
+ width="2403"
+ height="1403"
+ id="rect696"
+ style="fill:none;stroke:none" /><path
+ d="m 14100,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+ id="path698"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#3465a4" /><text
+ class="TextShape"
+ id="text700"><tspan
+ class="TextParagraph"
+ font-size="635px"
+ font-weight="400"
+ id="tspan702"
+ style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+ class="TextPosition"
+ x="13749"
+ y="9721"
+ id="tspan704"><tspan
+ id="tspan706"
+ style="fill:#000000;stroke:none">28</tspan></tspan></tspan></text>
+</g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g708"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id46"><rect
+ class="BoundingBox"
+ x="5199"
+ y="3850"
+ width="1402"
+ height="301"
+ id="rect711"
+ style="fill:none;stroke:none" /><path
+ d="m 5200,4000 970,0"
+ id="path713"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,4000 -450,-150 0,300 450,-150 z"
+ id="path715"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g717"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id47"><rect
+ class="BoundingBox"
+ x="5000"
+ y="4299"
+ width="1202"
+ height="802"
+ id="rect720"
+ style="fill:none;stroke:none" /><path
+ d="m 6200,4300 -842,561"
+ id="path722"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 5000,5100 458,-125 -167,-249 -291,374 z"
+ id="path724"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g726"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id48"><rect
+ class="BoundingBox"
+ x="5399"
+ y="5250"
+ width="1202"
+ height="301"
+ id="rect729"
+ style="fill:none;stroke:none" /><path
+ d="m 5400,5400 770,0"
+ id="path731"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,5400 -450,-150 0,300 450,-150 z"
+ id="path733"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g735"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id49"><rect
+ class="BoundingBox"
+ x="7599"
+ y="5250"
+ width="1202"
+ height="301"
+ id="rect738"
+ style="fill:none;stroke:none" /><path
+ d="m 7600,5400 770,0"
+ id="path740"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 8800,5400 -450,-150 0,300 450,-150 z"
+ id="path742"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g744"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id50"><rect
+ class="BoundingBox"
+ x="9799"
+ y="5250"
+ width="1402"
+ height="301"
+ id="rect747"
+ style="fill:none;stroke:none" /><path
+ d="m 9800,5400 970,0"
+ id="path749"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11200,5400 -450,-150 0,300 450,-150 z"
+ id="path751"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g753"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id51"><rect
+ class="BoundingBox"
+ x="9900"
+ y="4200"
+ width="1202"
+ height="802"
+ id="rect756"
+ style="fill:none;stroke:none" /><path
+ d="m 11100,5000 -842,-561"
+ id="path758"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 9900,4200 291,374 167,-249 -458,-125 z"
+ id="path760"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g762"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id52"><rect
+ class="BoundingBox"
+ x="9999"
+ y="3850"
+ width="1402"
+ height="301"
+ id="rect765"
+ style="fill:none;stroke:none" /><path
+ d="m 10000,4000 970,0"
+ id="path767"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11400,4000 -450,-150 0,300 450,-150 z"
+ id="path769"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g771"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id53"><rect
+ class="BoundingBox"
+ x="12399"
+ y="3850"
+ width="1202"
+ height="301"
+ id="rect774"
+ style="fill:none;stroke:none" /><path
+ d="m 12400,4000 770,0"
+ id="path776"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 13600,4000 -450,-150 0,300 450,-150 z"
+ id="path778"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g780"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id54"><rect
+ class="BoundingBox"
+ x="14799"
+ y="3850"
+ width="1202"
+ height="301"
+ id="rect783"
+ style="fill:none;stroke:none" /><path
+ d="m 14800,4000 770,0"
+ id="path785"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 16000,4000 -450,-150 0,300 450,-150 z"
+ id="path787"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g789"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id55"><rect
+ class="BoundingBox"
+ x="14400"
+ y="4399"
+ width="1402"
+ height="602"
+ id="rect792"
+ style="fill:none;stroke:none" /><path
+ d="m 15800,4400 -1005,431"
+ id="path794"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 14400,5000 473,-39 -118,-276 -355,315 z"
+ id="path796"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g798"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id56"><rect
+ class="BoundingBox"
+ x="14599"
+ y="5250"
+ width="1402"
+ height="301"
+ id="rect801"
+ style="fill:none;stroke:none" /><path
+ d="m 14600,5400 970,0"
+ id="path803"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 16000,5400 -450,-150 0,300 450,-150 z"
+ id="path805"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g807"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id57"><rect
+ class="BoundingBox"
+ x="5199"
+ y="6550"
+ width="1402"
+ height="301"
+ id="rect810"
+ style="fill:none;stroke:none" /><path
+ d="m 5200,6700 970,0"
+ id="path812"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,6700 -450,-150 0,300 450,-150 z"
+ id="path814"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g816"
+ transform="translate(-3285.889,-3129.4446)"><g
+ id="id58"><rect
+ class="BoundingBox"
+ x="5000"
+ y="6999"
+ width="1202"
+ height="802"
+ id="rect819"
+ style="fill:none;stroke:none" /><path
+ d="m 6200,7000 -842,561"
+ id="path821"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 5000,7800 458,-125 -167,-249 -291,374 z"
+ id="path823"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g825"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id59"><rect
+ class="BoundingBox"
+ x="5399"
+ y="7950"
+ width="1202"
+ height="301"
+ id="rect828"
+ style="fill:none;stroke:none" /><path
+ d="m 5400,8100 770,0"
+ id="path830"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,8100 -450,-150 0,300 450,-150 z"
+ id="path832"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g834"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id60"><rect
+ class="BoundingBox"
+ x="7599"
+ y="7950"
+ width="1202"
+ height="301"
+ id="rect837"
+ style="fill:none;stroke:none" /><path
+ d="m 7600,8100 770,0"
+ id="path839"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 8800,8100 -450,-150 0,300 450,-150 z"
+ id="path841"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g843"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id61"><rect
+ class="BoundingBox"
+ x="9799"
+ y="7950"
+ width="1402"
+ height="301"
+ id="rect846"
+ style="fill:none;stroke:none" /><path
+ d="m 9800,8100 970,0"
+ id="path848"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11200,8100 -450,-150 0,300 450,-150 z"
+ id="path850"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g852"
+ transform="translate(-3285.889,-3129.4446)"><g
+ id="id62"><rect
+ class="BoundingBox"
+ x="9900"
+ y="6900"
+ width="1202"
+ height="802"
+ id="rect855"
+ style="fill:none;stroke:none" /><path
+ d="m 11100,7700 -842,-561"
+ id="path857"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 9900,6900 291,374 167,-249 -458,-125 z"
+ id="path859"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g861"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id63"><rect
+ class="BoundingBox"
+ x="9999"
+ y="6550"
+ width="1402"
+ height="301"
+ id="rect864"
+ style="fill:none;stroke:none" /><path
+ d="m 10000,6700 970,0"
+ id="path866"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11400,6700 -450,-150 0,300 450,-150 z"
+ id="path868"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g870"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id64"><rect
+ class="BoundingBox"
+ x="12399"
+ y="6550"
+ width="1202"
+ height="301"
+ id="rect873"
+ style="fill:none;stroke:none" /><path
+ d="m 12400,6700 770,0"
+ id="path875"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 13600,6700 -450,-150 0,300 450,-150 z"
+ id="path877"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g879"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id65"><rect
+ class="BoundingBox"
+ x="14799"
+ y="6550"
+ width="1202"
+ height="301"
+ id="rect882"
+ style="fill:none;stroke:none" /><path
+ d="m 14800,6700 770,0"
+ id="path884"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 16000,6700 -450,-150 0,300 450,-150 z"
+ id="path886"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g888"
+ transform="translate(-3285.889,-3129.4446)"><g
+ id="id66"><rect
+ class="BoundingBox"
+ x="14400"
+ y="7099"
+ width="1402"
+ height="602"
+ id="rect891"
+ style="fill:none;stroke:none" /><path
+ d="m 15800,7100 -1005,431"
+ id="path893"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 14400,7700 473,-39 -118,-276 -355,315 z"
+ id="path895"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g897"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id67"><rect
+ class="BoundingBox"
+ x="14599"
+ y="7950"
+ width="1402"
+ height="301"
+ id="rect900"
+ style="fill:none;stroke:none" /><path
+ d="m 14600,8100 970,0"
+ id="path902"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 16000,8100 -450,-150 0,300 450,-150 z"
+ id="path904"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g906"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id68"><rect
+ class="BoundingBox"
+ x="5399"
+ y="9450"
+ width="1202"
+ height="301"
+ id="rect909"
+ style="fill:none;stroke:none" /><path
+ d="m 5400,9600 770,0"
+ id="path911"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 6600,9600 -450,-150 0,300 450,-150 z"
+ id="path913"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g915"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id69"><rect
+ class="BoundingBox"
+ x="7599"
+ y="9450"
+ width="1202"
+ height="301"
+ id="rect918"
+ style="fill:none;stroke:none" /><path
+ d="m 7600,9600 770,0"
+ id="path920"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 8800,9600 -450,-150 0,300 450,-150 z"
+ id="path922"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g924"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id70"><rect
+ class="BoundingBox"
+ x="9999"
+ y="9450"
+ width="1202"
+ height="301"
+ id="rect927"
+ style="fill:none;stroke:none" /><path
+ d="m 10000,9600 770,0"
+ id="path929"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 11200,9600 -450,-150 0,300 450,-150 z"
+ id="path931"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g933"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id71"><rect
+ class="BoundingBox"
+ x="12399"
+ y="9450"
+ width="1202"
+ height="301"
+ id="rect936"
+ style="fill:none;stroke:none" /><path
+ d="m 12400,9600 770,0"
+ id="path938"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 13600,9600 -450,-150 0,300 450,-150 z"
+ id="path940"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g><g
+ class="com.sun.star.drawing.LineShape"
+ id="g942"
+ transform="translate(-3285.889,-3185.889)"><g
+ id="id72"><rect
+ class="BoundingBox"
+ x="14799"
+ y="9450"
+ width="1202"
+ height="301"
+ id="rect945"
+ style="fill:none;stroke:none" /><path
+ d="m 14800,9600 770,0"
+ id="path947"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff3333" /><path
+ d="m 16000,9600 -450,-150 0,300 450,-150 z"
+ id="path949"
+ inkscape:connector-curvature="0"
+ style="fill:#ff3333;stroke:none" /></g></g></svg>
diff --git a/Documentation/media/uapi/v4l/pipeline.dot b/Documentation/media/uapi/v4l/pipeline.dot
new file mode 100644
index 000000000000..02d7fcf12b26
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pipeline.dot
@@ -0,0 +1,12 @@
+digraph board {
+ rankdir=TB
+ colorscheme=x11
+ scaler [label="{<scaler_0> 0} | Host\nScaler | {<scaler_1> 1} ", shape=Mrecord, style=filled, fillcolor=lightblue]
+ frontend [label="{<frontend_0> 0} | Host\nFrontend | {<frontend_1> 1}", shape=Mrecord, style=filled, fillcolor=lightblue]
+ sensor [label="Sensor | {<sensor_0> 0}", shape=Mrecord, style=filled, fillcolor=aquamarine]
+ io [label="{<io_0> 0} | V4L I/O", shape=Mrecord, style=filled, fillcolor=aquamarine]
+
+ sensor:sensor_0 -> frontend:frontend_0 [color=blue, label="HQ: 2592x1968\nHS: 1296x984"]
+ frontend:frontend_1 -> scaler:scaler_0 [color=blue, label="HQ: 2592x1968\nHS: 1296x984"]
+ scaler:scaler_1 -> io:io_0 [color=blue, label="HQ: 1280x720\nHS: 1280x720"]
+}
diff --git a/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst b/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst
index 9f250a1df2f6..32d0c8743460 100644
--- a/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst
@@ -33,8 +33,8 @@ Layout of macroblocks in memory is presented in the following figure.
.. _nv12mt:
-.. figure:: pixfmt-nv12mt_files/nv12mt.*
- :alt: nv12mt.png
+.. figure:: nv12mt.*
+ :alt: nv12mt.pdf / nv12mt.svg
:align: center
V4L2_PIX_FMT_NV12MT macroblock Z shape memory layout
@@ -50,8 +50,8 @@ interleaved. Height of the buffer is aligned to 32.
.. _nv12mt_ex:
-.. figure:: pixfmt-nv12mt_files/nv12mt_example.*
- :alt: nv12mt_example.png
+.. figure:: nv12mt_example.*
+ :alt: nv12mt_example.pdf / nv12mt_example.svg
:align: center
Example V4L2_PIX_FMT_NV12MT memory layout of macroblocks
diff --git a/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.png b/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.png
deleted file mode 100644
index 41401860fb73..000000000000
--- a/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.png b/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.png
deleted file mode 100644
index 7775f5d7cc46..000000000000
--- a/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/selection-api-003.rst b/Documentation/media/uapi/v4l/selection-api-003.rst
index 15cb3b79f12c..21686f93c38f 100644
--- a/Documentation/media/uapi/v4l/selection-api-003.rst
+++ b/Documentation/media/uapi/v4l/selection-api-003.rst
@@ -7,8 +7,8 @@ Selection targets
.. _sel-targets-capture:
-.. figure:: selection-api-003_files/selection.*
- :alt: selection.png
+.. figure:: selection.*
+ :alt: selection.pdf / selection.svg
:align: center
Cropping and composing targets
diff --git a/Documentation/media/uapi/v4l/selection-api-003_files/selection.png b/Documentation/media/uapi/v4l/selection-api-003_files/selection.png
deleted file mode 100644
index bfc523eae570..000000000000
--- a/Documentation/media/uapi/v4l/selection-api-003_files/selection.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/selection.svg b/Documentation/media/uapi/v4l/selection.svg
new file mode 100644
index 000000000000..d309187af967
--- /dev/null
+++ b/Documentation/media/uapi/v4l/selection.svg
@@ -0,0 +1,5812 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="4226.3345"
+ height="1686.8481"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="selection.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ style="display:inline;enable-background:new"
+ inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_final.png"
+ inkscape:export-xdpi="100.03588"
+ inkscape:export-ydpi="100.03588">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.32297491"
+ inkscape:cx="2113.1672"
+ inkscape:cy="843.42407"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer16"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ showguides="false"
+ inkscape:guide-bbox="true"
+ units="mm"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <defs
+ id="defs4">
+ <pattern
+ inkscape:collect="always"
+ xlink:href="#Strips1_1"
+ id="pattern5557"
+ patternTransform="matrix(5.4431804,0,0,10.10048,1808.3554,-48.222348)" />
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path7188"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <pattern
+ inkscape:isstock="true"
+ inkscape:stockid="Stripes 1:1"
+ id="Strips1_1"
+ patternTransform="translate(0,0) scale(10,10)"
+ height="1"
+ width="2"
+ patternUnits="userSpaceOnUse"
+ inkscape:collect="always">
+ <rect
+ id="rect5945"
+ height="2"
+ width="1"
+ y="-0.5"
+ x="0"
+ style="fill:#f815bb;stroke:none" />
+ </pattern>
+ <linearGradient
+ id="linearGradient10954"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#d9f90b;stop-opacity:1;"
+ offset="0"
+ id="stop10956" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9165"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.31330472;"
+ offset="0"
+ id="stop9167" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.084654994"
+ width="1.16931"
+ y="-0.36592469"
+ height="1.7318494"
+ id="filter11361">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="4.5740586"
+ id="feGaussianBlur11363" />
+ </filter>
+ <linearGradient
+ id="linearGradient7622">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop7624" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop7626" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4113">
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="0"
+ id="stop4115" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop4117" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3660">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3662" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3664" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3627">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3629" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop3631" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2843">
+ <stop
+ id="stop2845"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0.02188784"
+ id="stop2847" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0.75866222"
+ id="stop2849" />
+ <stop
+ id="stop2851"
+ offset="0.88508981"
+ style="stop-color:#232323;stop-opacity:1;" />
+ <stop
+ id="stop2853"
+ offset="1"
+ style="stop-color:#595959;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient8964">
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1;"
+ offset="0"
+ id="stop8966" />
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:0;"
+ offset="1"
+ id="stop8968" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient8952">
+ <stop
+ style="stop-color:#0a0c0c;stop-opacity:1;"
+ offset="0"
+ id="stop8954" />
+ <stop
+ style="stop-color:#1f2727;stop-opacity:0;"
+ offset="1"
+ id="stop8956" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient8430">
+ <stop
+ style="stop-color:#1e2323;stop-opacity:1;"
+ offset="0"
+ id="stop8432" />
+ <stop
+ id="stop8438"
+ offset="0.55992389"
+ style="stop-color:#181d1d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop8434" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient8398">
+ <stop
+ style="stop-color:#283131;stop-opacity:0;"
+ offset="0"
+ id="stop8400" />
+ <stop
+ id="stop8402"
+ offset="0.5125587"
+ style="stop-color:#1e2424;stop-opacity:0;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop8404" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4870">
+ <stop
+ style="stop-color:#c7bd80;stop-opacity:1;"
+ offset="0"
+ id="stop4872" />
+ <stop
+ style="stop-color:#c7bd80;stop-opacity:0;"
+ offset="1"
+ id="stop4874" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4862">
+ <stop
+ style="stop-color:#e2e2e2;stop-opacity:1;"
+ offset="0"
+ id="stop4864" />
+ <stop
+ style="stop-color:#e2e2e2;stop-opacity:0;"
+ offset="1"
+ id="stop4866" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4478">
+ <stop
+ style="stop-color:#f9eed3;stop-opacity:1;"
+ offset="0"
+ id="stop4480" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4482" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4106">
+ <stop
+ style="stop-color:#d9e002;stop-opacity:1;"
+ offset="0"
+ id="stop4108" />
+ <stop
+ id="stop4114"
+ offset="0.5"
+ style="stop-color:#a9ae01;stop-opacity:1;" />
+ <stop
+ style="stop-color:#717501;stop-opacity:1;"
+ offset="1"
+ id="stop4110" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4084">
+ <stop
+ style="stop-color:#7d7d00;stop-opacity:1;"
+ offset="0"
+ id="stop4086" />
+ <stop
+ id="stop4088"
+ offset="0.3636601"
+ style="stop-color:#c6c700;stop-opacity:1;" />
+ <stop
+ style="stop-color:#f6f800;stop-opacity:1;"
+ offset="1"
+ id="stop4090" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4041">
+ <stop
+ id="stop4043"
+ offset="0"
+ style="stop-color:#ffff00;stop-opacity:1;" />
+ <stop
+ id="stop4045"
+ offset="1"
+ style="stop-color:#ffff00;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4025">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4027" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4031" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4013">
+ <stop
+ style="stop-color:#ffff00;stop-opacity:1;"
+ offset="0"
+ id="stop4015" />
+ <stop
+ style="stop-color:#b2b200;stop-opacity:1;"
+ offset="1"
+ id="stop4017" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3985">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3987" />
+ <stop
+ style="stop-color:#1d1d1d;stop-opacity:1;"
+ offset="1"
+ id="stop3989" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3961">
+ <stop
+ style="stop-color:#283131;stop-opacity:0;"
+ offset="0"
+ id="stop3963" />
+ <stop
+ id="stop3965"
+ offset="0.5"
+ style="stop-color:#1e2424;stop-opacity:1;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop3967" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3951">
+ <stop
+ id="stop3953"
+ offset="0"
+ style="stop-color:#344040;stop-opacity:1;" />
+ <stop
+ style="stop-color:#222929;stop-opacity:1;"
+ offset="0.5"
+ id="stop3955" />
+ <stop
+ id="stop3957"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3909">
+ <stop
+ style="stop-color:#283131;stop-opacity:1;"
+ offset="0"
+ id="stop3911" />
+ <stop
+ id="stop3917"
+ offset="0.5"
+ style="stop-color:#1e2424;stop-opacity:1;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop3913" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3537">
+ <stop
+ style="stop-color:#ada469;stop-opacity:1;"
+ offset="0"
+ id="stop3539" />
+ <stop
+ id="stop3545"
+ offset="0.81132078"
+ style="stop-color:#ada469;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop3541" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3317">
+ <stop
+ style="stop-color:#cfc690;stop-opacity:1"
+ offset="0"
+ id="stop3319" />
+ <stop
+ id="stop3321"
+ offset="0.21161865"
+ style="stop-color:#afa775;stop-opacity:1;" />
+ <stop
+ id="stop3323"
+ offset="0.53408515"
+ style="stop-color:#615c3a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0.76504093"
+ id="stop3325" />
+ <stop
+ id="stop3327"
+ offset="1"
+ style="stop-color:#403518;stop-opacity:1;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3317"
+ id="radialGradient3315"
+ cx="543.6698"
+ cy="147.3131"
+ fx="543.6698"
+ fy="147.3131"
+ r="47.863216"
+ gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3537"
+ id="radialGradient3543"
+ cx="385"
+ cy="237.00504"
+ fx="385"
+ fy="237.00504"
+ r="86.928574"
+ gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3909"
+ id="radialGradient3915"
+ cx="418.30365"
+ cy="342.47794"
+ fx="418.30365"
+ fy="342.47794"
+ r="131.4509"
+ gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3951"
+ id="radialGradient3933"
+ cx="397.16388"
+ cy="336.95245"
+ fx="397.16388"
+ fy="336.95245"
+ r="36.75"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3961"
+ id="linearGradient3959"
+ x1="398.21429"
+ y1="343.52289"
+ x2="379.28571"
+ y2="265.30862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)" />
+ <filter
+ inkscape:collect="always"
+ id="filter3981"
+ x="-0.30000001"
+ width="1.6"
+ y="-0.30000001"
+ height="1.6">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2"
+ id="feGaussianBlur3983" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3985"
+ id="radialGradient3991"
+ cx="402.48898"
+ cy="317.23578"
+ fx="402.48898"
+ fy="317.23578"
+ r="23.714285"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3999">
+ <path
+ style="display:inline;opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 12.61031,-67.04463 3.21429,-93.92857 -9.43424,-26.99328 -34.96741,-59.12448 -66.42857,-69.64285 -31.03327,-10.37532 -65.01776,-4.84837 -84.28571,5.71428 z"
+ id="path4001"
+ sodipodi:nodetypes="czzczzzzc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4013"
+ id="radialGradient4056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+ cx="228.81355"
+ cy="440.26971"
+ fx="228.81355"
+ fy="440.26971"
+ r="119.17509" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4041"
+ id="radialGradient4060"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+ cx="275.4422"
+ cy="335.34866"
+ fx="275.4422"
+ fy="335.34866"
+ r="36.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4025"
+ id="radialGradient4062"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+ cx="275.4422"
+ cy="335.34866"
+ fx="275.4422"
+ fy="335.34866"
+ r="36.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4084"
+ id="linearGradient4082"
+ gradientUnits="userSpaceOnUse"
+ x1="182.35046"
+ y1="256.11136"
+ x2="145.53348"
+ y2="542.20502" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4100">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 265.93541,126.68393 -18.76721,168.86308 174.10543,-73.12068 61.9544,88.65883 57.8844,-31.9903 -37.53442,-180.059677 -237.6426,27.648747 z"
+ id="path4102"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4106"
+ id="radialGradient4112"
+ cx="250.22678"
+ cy="475.09763"
+ fx="250.22678"
+ fy="475.09763"
+ r="95.98877"
+ gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient4484"
+ x1="412.08926"
+ y1="404.91574"
+ x2="417.375"
+ y2="401.82648"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient4486"
+ x1="411.91071"
+ y1="404.91577"
+ x2="417.375"
+ y2="401.82648"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient4488"
+ x1="411.91071"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient4490"
+ x1="412.08926"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient4492"
+ x1="411.73212"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4862"
+ id="radialGradient4868"
+ cx="429.56738"
+ cy="377.42877"
+ fx="429.56738"
+ fy="377.42877"
+ r="72.079735"
+ gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4870"
+ id="radialGradient4876"
+ cx="437.6991"
+ cy="391.21735"
+ fx="437.6991"
+ fy="391.21735"
+ r="36.611931"
+ gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4013"
+ id="radialGradient3585"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+ cx="228.81355"
+ cy="440.26971"
+ fx="228.81355"
+ fy="440.26971"
+ r="119.17509" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4084"
+ id="linearGradient3587"
+ gradientUnits="userSpaceOnUse"
+ x1="182.35046"
+ y1="256.11136"
+ x2="145.53348"
+ y2="542.20502" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8514">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8516"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8604">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8606"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8610">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8612"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8616">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8618"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8622">
+ <path
+ style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 821.64329,477.88997 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+ id="path8624"
+ sodipodi:nodetypes="czzzzzzczczczczzzc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8642">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ id="path8644"
+ sodipodi:nodetypes="czzcczcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8658">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -99.77493,25.9619 -142.85715,35.7143 -43.08222,9.7524 -117.26443,34.816 -156.91262,27.2654 -39.64818,-7.5506 -89.51595,-64.4083 -89.51595,-64.4083 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ id="path8660"
+ sodipodi:nodetypes="czzzcczzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8802"
+ x="-0.35311759"
+ width="1.7062352"
+ y="-0.1817714"
+ height="1.3635428">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="48.038491"
+ id="feGaussianBlur8804" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8806"
+ x="-0.61142862"
+ width="2.2228572"
+ y="-0.14930232"
+ height="1.2986046">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="37.830213"
+ id="feGaussianBlur8808" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8810"
+ x="-0.23519406"
+ width="1.4703881"
+ y="-0.24500646"
+ height="1.4900129">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="58.328041"
+ id="feGaussianBlur8812" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8814"
+ x="-0.20466694"
+ width="1.4093339"
+ y="-0.29007819"
+ height="1.5801564">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="22.300169"
+ id="feGaussianBlur8816" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8818"
+ x="-0.34381232"
+ width="1.6876246"
+ y="-0.18433961"
+ height="1.3686792">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="34.542167"
+ id="feGaussianBlur8820" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8822"
+ x="-0.2742857"
+ width="1.5485713"
+ y="-0.21333334"
+ height="1.4266667">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="11.313708"
+ id="feGaussianBlur8824" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8826"
+ x="-0.25894088"
+ width="1.5178818"
+ y="-0.2236412"
+ height="1.4472824">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.631544"
+ id="feGaussianBlur8828" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8856"
+ x="-0.3253231"
+ width="1.6506462"
+ y="-0.19013336"
+ height="1.3802667">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="28.712591"
+ id="feGaussianBlur8858" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8860"
+ x="-0.38093024"
+ width="1.7618605"
+ y="-0.17518716"
+ height="1.3503743">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.304015"
+ id="feGaussianBlur8862" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8888"
+ x="-0.2112188"
+ width="1.4224375"
+ y="-0.16808605"
+ height="1.3361721">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="8.3693583"
+ id="feGaussianBlur8890" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8892"
+ x="-0.18692794"
+ width="1.3738559"
+ y="-0.23646873"
+ height="1.4729375">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="31.21228"
+ id="feGaussianBlur8894" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8906">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8908"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8940"
+ x="-0.25152978"
+ width="1.5030596"
+ y="-0.053035267"
+ height="1.1060705">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="13.024603"
+ id="feGaussianBlur8942" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8952"
+ id="linearGradient8958"
+ x1="609.31244"
+ y1="239.46866"
+ x2="560.83142"
+ y2="262.86206"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8964"
+ id="linearGradient8970"
+ x1="603.84064"
+ y1="627.85303"
+ x2="616.24396"
+ y2="585.42664"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)" />
+ <filter
+ inkscape:collect="always"
+ id="filter9020"
+ x="-0.32861114"
+ width="1.6572223"
+ y="-0.182"
+ height="1.364">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="20.912684"
+ id="feGaussianBlur9022" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9024"
+ x="-0.55453134"
+ width="2.1090627"
+ y="-0.51434779"
+ height="2.0286956">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="20.912684"
+ id="feGaussianBlur9026" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9044"
+ x="-0.32631579"
+ width="1.6526316"
+ y="-0.84545463"
+ height="2.6909094">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="21.92031"
+ id="feGaussianBlur9046" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9048"
+ x="-0.40879121"
+ width="1.8175824"
+ y="-0.71538466"
+ height="2.4307692">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="21.92031"
+ id="feGaussianBlur9050" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter3587"
+ x="-0.1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="8.881432"
+ id="feGaussianBlur3589" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3602">
+ <path
+ sodipodi:nodetypes="czzzzzzczczczczzzc"
+ id="path3604"
+ d="m 647.61204,540.04601 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+ style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4120"
+ x="-0.2770822"
+ width="1.5541644"
+ y="-0.32482043"
+ height="1.6496409">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.956289"
+ id="feGaussianBlur4122" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3631">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3633"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3665">
+ <path
+ sodipodi:nodetypes="czzcczcc"
+ id="path3667"
+ d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3677">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3679"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter3898">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.892985"
+ id="feGaussianBlur3900" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4130"
+ x="-0.49509686"
+ width="1.9901937"
+ y="-0.26708817"
+ height="1.5341763">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.730622"
+ id="feGaussianBlur4132" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4141"
+ x="-0.40611032"
+ width="1.8122206"
+ y="-0.30260596"
+ height="1.6052119">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="9.8586086"
+ id="feGaussianBlur4143" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4177">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path4179"
+ d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4185">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.6164709"
+ id="feGaussianBlur4187" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4105">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.8640966"
+ id="feGaussianBlur4107" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath2833">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ id="path2835"
+ sodipodi:nodetypes="czzzcczzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2843"
+ id="linearGradient2841"
+ gradientUnits="userSpaceOnUse"
+ x1="347.89655"
+ y1="1070.2124"
+ x2="275.58191"
+ y2="867.97992" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3627"
+ id="linearGradient3688"
+ gradientUnits="userSpaceOnUse"
+ x1="699.32867"
+ y1="269.76755"
+ x2="698.97504"
+ y2="346.1351" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask3684">
+ <ellipse
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path3686"
+ transform="translate(-174.03125,62.156036)"
+ cx="579.474"
+ cy="260.57516"
+ rx="192.6866"
+ ry="164.04877" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3622">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 266.27183,924.57186 c -1.40727,18.80121 -1.1449,32.75103 2.08174,49.30328 3.22665,16.55234 16.40608,45.90736 20.3344,63.18376 3.92622,17.2671 2.69413,38.3096 -12.45944,51.1482 -15.31761,12.9774 -42.05127,21.5989 -67.8323,15.7338 -25.78106,-5.8653 -69.54907,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 24.381071,839.38658 21.334081,813.84027 0.03533552,788.33044 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 c 29.994295,6.08166 50.57936,31.8724 63.979783,72.7125 9.554154,-3.91791 18.237764,-9.37294 30.187414,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.687255,-101.06994 53.441965,5.67033 83.657025,80.63932 78.971425,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24896,-38.34702 -21.04781,-76.8679 -3.65971,-118.64818 0,0 48.28678,65.43687 54.38966,85.80577 6.10287,20.36891 1.51881,38.70052 1.51881,38.70052 0,0 16.95957,31.08529 20.29392,51.09413 3.3731,20.24135 -3.53269,59.10332 -4.94582,77.98324 z"
+ id="path3624"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3636">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3638"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3660"
+ id="linearGradient3666"
+ x1="1255.7386"
+ y1="667.09216"
+ x2="893.69995"
+ y2="858.01099"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter3779"
+ x="-0.087980822"
+ width="1.1759616"
+ y="-0.17728332"
+ height="1.3545666">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="16.340344"
+ id="feGaussianBlur3781" />
+ </filter>
+ <filter
+ id="filter3785"
+ inkscape:label="White Fur">
+ <feTurbulence
+ id="feTurbulence3787"
+ type="fractalNoise"
+ baseFrequency="0.24044943820224721"
+ numOctaves="10"
+ seed="655"
+ result="result0" />
+ <feDisplacementMap
+ id="feDisplacementMap3789"
+ in="SourceGraphic"
+ in2="result0"
+ scale="62"
+ xChannelSelector="B"
+ yChannelSelector="G" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter3677">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.0397518"
+ id="feGaussianBlur3679" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3722">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3724"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3986">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3988"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3992">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3994"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3998">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 178.21428,274.14789 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401287 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.3574 -122.78647,50.053 -187.06988,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path4000"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4002"
+ x="-0.24334238"
+ width="1.4866848"
+ y="-0.39104807"
+ height="1.7820961">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="14.589518"
+ id="feGaussianBlur4004" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4010"
+ x="-0.14577261"
+ width="1.2915452"
+ y="-0.23523259"
+ height="1.4704652">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="4.4442907"
+ id="feGaussianBlur4012" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4053">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.6062947"
+ id="feGaussianBlur4055" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4079">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.5887624"
+ id="feGaussianBlur4081" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4083">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.5052066"
+ id="feGaussianBlur4085" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4113"
+ id="radialGradient4119"
+ cx="296.33783"
+ cy="427.17749"
+ fx="296.33783"
+ fy="427.17749"
+ r="19.704132"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
+ <filter
+ inkscape:collect="always"
+ id="filter6949"
+ x="-0.10294895"
+ width="1.2058979"
+ y="-0.34224695"
+ height="1.6844939">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6951" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6953"
+ x="-0.098320946"
+ width="1.1966419"
+ y="-0.19750816"
+ height="1.3950163">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6955" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6957"
+ x="-0.098213427"
+ width="1.1964267"
+ y="-0.19838208"
+ height="1.3967642">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6959" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6961"
+ x="-0.09919104"
+ width="1.1983821"
+ y="-0.22643611"
+ height="1.4528722">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6963" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6965"
+ x="-0.099081434"
+ width="1.1981629"
+ y="-0.22529824"
+ height="1.4505965">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6967" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6969"
+ x="-0.10450897"
+ width="1.2090179"
+ y="-0.40468886"
+ height="1.8093777">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6971" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6973"
+ x="-0.10330495"
+ width="1.2066098"
+ y="-0.36439717"
+ height="1.7287945">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6975" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6977"
+ x="-0.10224481"
+ width="1.2044896"
+ y="-0.32371372"
+ height="1.6474274">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6979" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6981"
+ x="-0.10052545"
+ width="1.2010509"
+ y="-0.2742162"
+ height="1.5484324">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6983" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6985"
+ x="-0.098428868"
+ width="1.1968577"
+ y="-0.20853186"
+ height="1.4170637">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6987" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6989"
+ x="-0.098428868"
+ width="1.1968577"
+ y="-0.20287035"
+ height="1.4057407">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6991" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6993"
+ x="-0.098213255"
+ width="1.1964265"
+ y="-0.19838208"
+ height="1.3967642">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6995" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6997">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6999" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7001">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur7003" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7285"
+ x="-0.030884685"
+ width="1.0617694"
+ y="-0.10267408"
+ height="1.2053483">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7287" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7289">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7291" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7293">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7295" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7297">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7299" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7301">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7303" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7305">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7307" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7309">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7311" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7313">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7315" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7317">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7319" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7321">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7323" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7325"
+ x="-0.031352691"
+ width="1.0627054"
+ y="-0.12140666"
+ height="1.2428133">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7327" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7329"
+ x="-0.030991485"
+ width="1.061983"
+ y="-0.10931916"
+ height="1.2186383">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7331" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7333">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7335" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7337">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7339" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7345">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.7233839"
+ id="feGaussianBlur7347" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7421">
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="0"
+ inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
+ style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ id="path7423"
+ d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 1.8125,14.71875 c -0.25799,-0.0608 6.1875,3.3125 6.1875,3.3125 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+ transform="translate(0.08004571,-0.03125)" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter7578"
+ x="-0.08160872"
+ width="1.1632174"
+ y="-0.22659944"
+ height="1.4531989">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.437399"
+ id="feGaussianBlur7580" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7594"
+ x="-0.040804356"
+ width="1.0816087"
+ y="-0.11329972"
+ height="1.2265995">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2186995"
+ id="feGaussianBlur7596" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7606">
+ <path
+ id="path7608"
+ d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+ style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter7610"
+ x="-0.021942979"
+ width="1.0438859"
+ y="-0.10017137"
+ height="1.2003427">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.57530213"
+ id="feGaussianBlur7612" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7616">
+ <path
+ id="path7618"
+ d="m 205.47016,-408.97318 -0.0901,0.002 c -1.44563,0.78566 -6.69921,1.14335 -7.27625,9.03857 -0.54134,7.40553 13.78595,18.09566 15.85433,19.24481 1.66964,0.92764 3.48475,1.65551 5.27345,2.09115 l 1.41867,0.31834 c 1.90027,0.34514 3.70042,0.41015 5.15031,0.26563 3.1486,-0.31384 5.16386,-0.57031 7.16789,-0.8152 2.00402,-0.24488 2.5407,-0.86478 3.64319,-1.02999 1.14342,-0.17143 2.25659,0.27414 6.29577,-0.43753 4.03888,-0.71169 5.51507,-1.03768 6.23419,-1.3503 0.74664,-0.32479 1.81806,-0.74575 2.47589,-1.3621 1.95897,0.12471 3.80476,-0.0261 5.2648,-0.47819 3.02376,-0.93627 4.99157,-1.52544 6.8628,-2.27751 1.50138,-0.60342 2.43202,-1.53636 2.66436,-1.81883 0.23254,-0.28245 0.14951,-0.71989 0.17694,-0.73948 0.0453,-0.0322 0.34622,-0.0701 0.52926,-0.40161 0.98557,-1.78276 2.70955,-5.45215 2.87137,-6.12738 0.16094,-0.67257 0.26182,-1.33778 0.34007,-1.73051 0.0453,-0.22691 -0.0855,-0.88701 -0.0594,-0.94393 0.0365,-0.0797 0.30505,-0.22988 0.37769,-0.47485 0.34913,-1.17686 0.24274,-2.19578 0.1278,-3.6249 -0.11463,-1.42909 -0.64781,-4.6711 -1.24013,-5.56865 -0.38017,-0.57646 -0.74215,-0.84625 -1.09026,-0.98459 -0.0657,-0.0219 -0.12035,-0.0553 -0.1827,-0.0754 -0.0207,-0.005 -0.0418,2.3e-4 -0.0623,-0.004 -0.30559,-0.097 -0.59597,-0.20067 -1.13816,-0.29875 -0.97557,-0.1765 -2.40074,-0.42766 -3.94175,-0.52584 -0.51366,-0.0327 -1.0379,-0.0247 -1.56523,-0.0153 -3.57201,0.0636 -9.05695,0.3611 -10.30707,0.90928 -1.60587,-0.44697 -3.89597,-0.88576 -5.89053,-0.8812 -3.07195,0.007 -4.97947,-0.005 -6.92207,-0.0134 -1.94251,-0.009 -1.70908,0.27025 -2.9318,0.26518 -1.32192,-0.005 -1.76701,-0.34717 -5.55562,-0.29393 -3.55782,0.05 -9.02796,0.36522 -10.30706,0.90927 -1.60614,-0.44747 -3.89367,-0.88575 -5.89043,-0.88118 -3.07215,0.007 -4.98175,0.0265 -6.92426,0.0177 -0.66059,-0.003 -1.0485,0.051 -1.35359,0.0934 z"
+ style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7622"
+ id="linearGradient7708"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-19.091883,4.2426407)"
+ x1="774.97668"
+ y1="-211.87105"
+ x2="755.11584"
+ y2="-202.67865" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask7704">
+ <path
+ style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 718.40812,-224.31217 33.25,56 275.99998,-24 159.5,-48.25 -66.5,-82.75 -402.24998,99 z"
+ id="path7706"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8430"
+ id="radialGradient7904"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
+ cx="142.95833"
+ cy="107.09234"
+ fx="142.95833"
+ fy="107.09234"
+ r="66.981766" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3317"
+ id="radialGradient7906"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
+ cx="317.78754"
+ cy="129.65378"
+ fx="317.78754"
+ fy="129.65378"
+ r="47.863216" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8398"
+ id="radialGradient7908"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
+ cx="325.30847"
+ cy="80.909554"
+ fx="325.30847"
+ fy="80.909554"
+ r="26.937988" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8209">
+ <path
+ sodipodi:nodetypes="czcc"
+ id="path8211"
+ d="m 734.03125,519.49186 c 0,0 16.75513,37.01806 28.70141,53.95395 11.94629,16.93589 52.72716,56.04605 52.72716,56.04605 l 0.59717,-138.58975"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8225">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.661912"
+ id="feGaussianBlur8227" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8333">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.18"
+ id="feGaussianBlur8335" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8338">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8340"
+ d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8354">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.82"
+ id="feGaussianBlur8356" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8359">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8361"
+ d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8379"
+ x="-0.14413793"
+ width="1.288276"
+ y="-0.10278689"
+ height="1.2055738">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.389266"
+ id="feGaussianBlur8381" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8392">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8394"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8404"
+ x="-0.090268657"
+ width="1.1805373"
+ y="-0.10250848"
+ height="1.205017">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.3457272"
+ id="feGaussianBlur8406" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8417">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8419"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ x="-0.084654994"
+ width="1.16931"
+ y="-0.36592469"
+ height="1.7318494"
+ id="filter11361-3">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="4.5740586"
+ id="feGaussianBlur11363-6" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8430"
+ id="radialGradient7904-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
+ cx="142.95833"
+ cy="107.09234"
+ fx="142.95833"
+ fy="107.09234"
+ r="66.981766" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3317"
+ id="radialGradient7906-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
+ cx="317.78754"
+ cy="129.65378"
+ fx="317.78754"
+ fy="129.65378"
+ r="47.863216" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8398"
+ id="radialGradient7908-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
+ cx="325.30847"
+ cy="80.909554"
+ fx="325.30847"
+ fy="80.909554"
+ r="26.937988" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8658-06">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -99.77493,25.9619 -142.85715,35.7143 -43.08222,9.7524 -117.26443,34.816 -156.91262,27.2654 -39.64818,-7.5506 -89.51595,-64.4083 -89.51595,-64.4083 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ id="path8660-2"
+ sodipodi:nodetypes="czzzcczzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8888-6"
+ x="-0.2112188"
+ width="1.4224375"
+ y="-0.16808605"
+ height="1.3361721">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="8.3693583"
+ id="feGaussianBlur8890-1" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath2833-2">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ id="path2835-3"
+ sodipodi:nodetypes="czzzcczzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8892-7"
+ x="-0.18692794"
+ width="1.3738559"
+ y="-0.23646873"
+ height="1.4729375">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="31.21228"
+ id="feGaussianBlur8894-5" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3665-9">
+ <path
+ sodipodi:nodetypes="czzcczcc"
+ id="path3667-2"
+ d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8856-2"
+ x="-0.3253231"
+ width="1.6506462"
+ y="-0.19013336"
+ height="1.3802667">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="28.712591"
+ id="feGaussianBlur8858-8" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8642-9">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ id="path8644-7"
+ sodipodi:nodetypes="czzcczcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8860-3"
+ x="-0.38093024"
+ width="1.7618605"
+ y="-0.17518716"
+ height="1.3503743">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.304015"
+ id="feGaussianBlur8862-6" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7616-1">
+ <path
+ id="path7618-2"
+ d="m 205.47016,-408.97318 -0.0901,0.002 c -1.44563,0.78566 -6.69921,1.14335 -7.27625,9.03857 -0.54134,7.40553 13.78595,18.09566 15.85433,19.24481 1.66964,0.92764 3.48475,1.65551 5.27345,2.09115 l 1.41867,0.31834 c 1.90027,0.34514 3.70042,0.41015 5.15031,0.26563 3.1486,-0.31384 5.16386,-0.57031 7.16789,-0.8152 2.00402,-0.24488 2.5407,-0.86478 3.64319,-1.02999 1.14342,-0.17143 2.25659,0.27414 6.29577,-0.43753 4.03888,-0.71169 5.51507,-1.03768 6.23419,-1.3503 0.74664,-0.32479 1.81806,-0.74575 2.47589,-1.3621 1.95897,0.12471 3.80476,-0.0261 5.2648,-0.47819 3.02376,-0.93627 4.99157,-1.52544 6.8628,-2.27751 1.50138,-0.60342 2.43202,-1.53636 2.66436,-1.81883 0.23254,-0.28245 0.14951,-0.71989 0.17694,-0.73948 0.0453,-0.0322 0.34622,-0.0701 0.52926,-0.40161 0.98557,-1.78276 2.70955,-5.45215 2.87137,-6.12738 0.16094,-0.67257 0.26182,-1.33778 0.34007,-1.73051 0.0453,-0.22691 -0.0855,-0.88701 -0.0594,-0.94393 0.0365,-0.0797 0.30505,-0.22988 0.37769,-0.47485 0.34913,-1.17686 0.24274,-2.19578 0.1278,-3.6249 -0.11463,-1.42909 -0.64781,-4.6711 -1.24013,-5.56865 -0.38017,-0.57646 -0.74215,-0.84625 -1.09026,-0.98459 -0.0657,-0.0219 -0.12035,-0.0553 -0.1827,-0.0754 -0.0207,-0.005 -0.0418,2.3e-4 -0.0623,-0.004 -0.30559,-0.097 -0.59597,-0.20067 -1.13816,-0.29875 -0.97557,-0.1765 -2.40074,-0.42766 -3.94175,-0.52584 -0.51366,-0.0327 -1.0379,-0.0247 -1.56523,-0.0153 -3.57201,0.0636 -9.05695,0.3611 -10.30707,0.90928 -1.60587,-0.44697 -3.89597,-0.88576 -5.89053,-0.8812 -3.07195,0.007 -4.97947,-0.005 -6.92207,-0.0134 -1.94251,-0.009 -1.70908,0.27025 -2.9318,0.26518 -1.32192,-0.005 -1.76701,-0.34717 -5.55562,-0.29393 -3.55782,0.05 -9.02796,0.36522 -10.30706,0.90927 -1.60614,-0.44747 -3.89367,-0.88575 -5.89043,-0.88118 -3.07215,0.007 -4.98175,0.0265 -6.92426,0.0177 -0.66059,-0.003 -1.0485,0.051 -1.35359,0.0934 z"
+ style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter7610-9"
+ x="-0.021942979"
+ width="1.0438859"
+ y="-0.10017137"
+ height="1.2003427">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.57530213"
+ id="feGaussianBlur7612-3" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7606-1">
+ <path
+ id="path7608-9"
+ d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+ style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter7578-4"
+ x="-0.08160872"
+ width="1.1632174"
+ y="-0.22659944"
+ height="1.4531989">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.437399"
+ id="feGaussianBlur7580-7" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7594-8"
+ x="-0.040804356"
+ width="1.0816087"
+ y="-0.11329972"
+ height="1.2265995">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2186995"
+ id="feGaussianBlur7596-4" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8616-5">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8618-0"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8940-3"
+ x="-0.25152978"
+ width="1.5030596"
+ y="-0.053035267"
+ height="1.1060705">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="13.024603"
+ id="feGaussianBlur8942-6" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8209-6">
+ <path
+ sodipodi:nodetypes="czcc"
+ id="path8211-3"
+ d="m 734.03125,519.49186 c 0,0 16.75513,37.01806 28.70141,53.95395 11.94629,16.93589 52.72716,56.04605 52.72716,56.04605 l 0.59717,-138.58975"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8822-2"
+ x="-0.2742857"
+ width="1.5485713"
+ y="-0.21333334"
+ height="1.4266667">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="11.313708"
+ id="feGaussianBlur8824-0" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3998-6">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 178.21428,274.14789 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401287 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.3574 -122.78647,50.053 -187.06988,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path4000-1"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter3677-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.0397518"
+ id="feGaussianBlur3679-5" />
+ </filter>
+ <filter
+ id="filter3785-4"
+ inkscape:label="White Fur">
+ <feTurbulence
+ id="feTurbulence3787-7"
+ type="fractalNoise"
+ baseFrequency="0.24044943820224721"
+ numOctaves="10"
+ seed="655"
+ result="result0" />
+ <feDisplacementMap
+ id="feDisplacementMap3789-65"
+ in="SourceGraphic"
+ in2="result0"
+ scale="62"
+ xChannelSelector="B"
+ yChannelSelector="G" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8604-69">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8606-3"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8802-7"
+ x="-0.35311759"
+ width="1.7062352"
+ y="-0.1817714"
+ height="1.3635428">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="48.038491"
+ id="feGaussianBlur8804-4" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3317"
+ id="radialGradient3315-5"
+ cx="543.6698"
+ cy="147.3131"
+ fx="543.6698"
+ fy="147.3131"
+ r="47.863216"
+ gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3537"
+ id="radialGradient3543-4"
+ cx="385"
+ cy="237.00504"
+ fx="385"
+ fy="237.00504"
+ r="86.928574"
+ gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
+ gradientUnits="userSpaceOnUse" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4100-3">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 265.93541,126.68393 -18.76721,168.86308 174.10543,-73.12068 61.9544,88.65883 57.8844,-31.9903 -37.53442,-180.059677 -237.6426,27.648747 z"
+ id="path4102-0"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4120-7"
+ x="-0.2770822"
+ width="1.5541644"
+ y="-0.32482043"
+ height="1.6496409">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.956289"
+ id="feGaussianBlur4122-8" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3961"
+ id="radialGradient3915-6"
+ cx="418.30365"
+ cy="342.47794"
+ fx="418.30365"
+ fy="342.47794"
+ r="131.4509"
+ gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
+ gradientUnits="userSpaceOnUse" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask3684-3">
+ <ellipse
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path3686-1"
+ transform="translate(-174.03125,62.156036)"
+ cx="579.474"
+ cy="260.57516"
+ rx="192.6866"
+ ry="164.04877" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3951"
+ id="radialGradient3933-8"
+ cx="397.16388"
+ cy="336.95245"
+ fx="397.16388"
+ fy="336.95245"
+ r="36.75"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
+ <filter
+ inkscape:collect="always"
+ id="filter8806-6"
+ x="-0.61142862"
+ width="2.2228572"
+ y="-0.14930232"
+ height="1.2986046">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="37.830213"
+ id="feGaussianBlur8808-4" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter8826-9"
+ x="-0.25894088"
+ width="1.5178818"
+ y="-0.2236412"
+ height="1.4472824">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="19.631544"
+ id="feGaussianBlur8828-5" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3985"
+ id="radialGradient3991-0"
+ cx="402.48898"
+ cy="317.23578"
+ fx="402.48898"
+ fy="317.23578"
+ r="23.714285"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
+ <filter
+ inkscape:collect="always"
+ id="filter3981-7"
+ x="-0.30000001"
+ width="1.6"
+ y="-0.30000001"
+ height="1.6">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2"
+ id="feGaussianBlur3983-1" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4106"
+ id="radialGradient4112-7"
+ cx="250.22678"
+ cy="475.09763"
+ fx="250.22678"
+ fy="475.09763"
+ r="95.98877"
+ gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4013"
+ id="radialGradient3585-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+ cx="228.81355"
+ cy="440.26971"
+ fx="228.81355"
+ fy="440.26971"
+ r="119.17509" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3999-0">
+ <path
+ style="display:inline;opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 12.61031,-67.04463 3.21429,-93.92857 -9.43424,-26.99328 -34.96741,-59.12448 -66.42857,-69.64285 -31.03327,-10.37532 -65.01776,-4.84837 -84.28571,5.71428 z"
+ id="path4001-61"
+ sodipodi:nodetypes="czzczzzzc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4041"
+ id="radialGradient4060-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+ cx="275.4422"
+ cy="335.34866"
+ fx="275.4422"
+ fy="335.34866"
+ r="36.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7622"
+ id="radialGradient4062-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+ cx="275.4422"
+ cy="335.34866"
+ fx="275.4422"
+ fy="335.34866"
+ r="36.75" />
+ <filter
+ inkscape:collect="always"
+ id="filter4079-1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.5887624"
+ id="feGaussianBlur4081-1" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4013"
+ id="radialGradient4056-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+ cx="228.81355"
+ cy="440.26971"
+ fx="228.81355"
+ fy="440.26971"
+ r="119.17509" />
+ <filter
+ inkscape:collect="always"
+ id="filter4083-9">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.5052066"
+ id="feGaussianBlur4085-7" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4113"
+ id="radialGradient4119-7"
+ cx="296.33783"
+ cy="427.17749"
+ fx="296.33783"
+ fy="427.17749"
+ r="19.704132"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4862"
+ id="radialGradient4868-3"
+ cx="429.56738"
+ cy="377.42877"
+ fx="429.56738"
+ fy="377.42877"
+ r="72.079735"
+ gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter4002-6"
+ x="-0.24334238"
+ width="1.4866848"
+ y="-0.39104807"
+ height="1.7820961">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="14.589518"
+ id="feGaussianBlur4004-3" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4870"
+ id="radialGradient4876-9"
+ cx="437.6991"
+ cy="391.21735"
+ fx="437.6991"
+ fy="391.21735"
+ r="36.611931"
+ gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter4010-1"
+ x="-0.14577261"
+ width="1.2915452"
+ y="-0.23523259"
+ height="1.4704652">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="4.4442907"
+ id="feGaussianBlur4012-2" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4053-9">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.6062947"
+ id="feGaussianBlur4055-3" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8514-8">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8516-8"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8814-5"
+ x="-0.20466694"
+ width="1.4093339"
+ y="-0.29007819"
+ height="1.5801564">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="22.300169"
+ id="feGaussianBlur8816-0" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8610-9">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8612-6"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8810-3"
+ x="-0.23519406"
+ width="1.4703881"
+ y="-0.24500646"
+ height="1.4900129">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="58.328041"
+ id="feGaussianBlur8812-8" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8622-5">
+ <path
+ style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 821.64329,477.88997 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+ id="path8624-61"
+ sodipodi:nodetypes="czzzzzzczczczczzzc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8818-1"
+ x="-0.34381232"
+ width="1.6876246"
+ y="-0.18433961"
+ height="1.3686792">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="34.542167"
+ id="feGaussianBlur8820-5" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8906-9">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path8908-8"
+ sodipodi:nodetypes="cscccccccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3602-4">
+ <path
+ sodipodi:nodetypes="czzzzzzczczczczzzc"
+ id="path3604-8"
+ d="m 647.61204,540.04601 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+ style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter3587-1"
+ x="-0.1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="8.881432"
+ id="feGaussianBlur3589-0" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3992-4">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3994-4"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter3779-4"
+ x="-0.087980822"
+ width="1.1759616"
+ y="-0.17728332"
+ height="1.3545666">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="16.340344"
+ id="feGaussianBlur3781-4" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3986-7">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3988-6"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3722-3">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+ id="path3724-1"
+ sodipodi:nodetypes="czzzzzzzzcc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8225-7">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.661912"
+ id="feGaussianBlur8227-5" />
+ </filter>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask7704-9">
+ <path
+ style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 718.40812,-224.31217 33.25,56 275.99998,-24 159.5,-48.25 -66.5,-82.75 -402.24998,99 z"
+ id="path7706-6"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7421-7">
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="0"
+ inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
+ style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ id="path7423-8"
+ d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 1.8125,14.71875 c -0.25799,-0.0608 6.1875,3.3125 6.1875,3.3125 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+ transform="translate(0.08004571,-0.03125)" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter7001-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur7003-7" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6949-4"
+ x="-0.10294895"
+ width="1.2058979"
+ y="-0.34224695"
+ height="1.6844939">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6951-1" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6961-8"
+ x="-0.09919104"
+ width="1.1983821"
+ y="-0.22643611"
+ height="1.4528722">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6963-5" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6957-9"
+ x="-0.098213427"
+ width="1.1964267"
+ y="-0.19838208"
+ height="1.3967642">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6959-7" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6997-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6999-3" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6953-8"
+ x="-0.098320946"
+ width="1.1966419"
+ y="-0.19750816"
+ height="1.3950163">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6955-8" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6993-3"
+ x="-0.098213255"
+ width="1.1964265"
+ y="-0.19838208"
+ height="1.3967642">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6995-1" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6989-8"
+ x="-0.098428868"
+ width="1.1968577"
+ y="-0.20287035"
+ height="1.4057407">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6991-9" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6985-6"
+ x="-0.098428868"
+ width="1.1968577"
+ y="-0.20853186"
+ height="1.4170637">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6987-4" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6965-3"
+ x="-0.099081434"
+ width="1.1981629"
+ y="-0.22529824"
+ height="1.4505965">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6967-3" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6981-3"
+ x="-0.10052545"
+ width="1.2010509"
+ y="-0.2742162"
+ height="1.5484324">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6983-8" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6977-6"
+ x="-0.10224481"
+ width="1.2044896"
+ y="-0.32371372"
+ height="1.6474274">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6979-0" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6973-4"
+ x="-0.10330495"
+ width="1.2066098"
+ y="-0.36439717"
+ height="1.7287945">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6975-8" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter6969-8"
+ x="-0.10450897"
+ width="1.2090179"
+ y="-0.40468886"
+ height="1.8093777">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1675612"
+ id="feGaussianBlur6971-8" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7345-9">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.7233839"
+ id="feGaussianBlur7347-7" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7333-7">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7335-6" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7285-4"
+ x="-0.030884685"
+ width="1.0617694"
+ y="-0.10267408"
+ height="1.2053483">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7287-3" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7289-0">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7291-3" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7293-0">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7295-9" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7337-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7339-5" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7297-4">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7299-0" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7301-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7303-9" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7305-4">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7307-6" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7309-9">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7311-2" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7313-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7315-4" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7317-7">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7319-7" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7321-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7323-4" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7329-8"
+ x="-0.030991485"
+ width="1.061983"
+ y="-0.10931916"
+ height="1.2186383">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7331-1" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter7325-2"
+ x="-0.031352691"
+ width="1.0627054"
+ y="-0.12140666"
+ height="1.2428133">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.35026836"
+ id="feGaussianBlur7327-8" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9048-9"
+ x="-0.40879121"
+ width="1.8175824"
+ y="-0.71538466"
+ height="2.4307692">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="21.92031"
+ id="feGaussianBlur9050-3" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3631-6">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3633-8"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3677-0">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3679-2"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter3898-1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.892985"
+ id="feGaussianBlur3900-0" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3622-5">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 266.27183,924.57186 c -1.40727,18.80121 -1.1449,32.75103 2.08174,49.30328 3.22665,16.55234 16.40608,45.90736 20.3344,63.18376 3.92622,17.2671 2.69413,38.3096 -12.45944,51.1482 -15.31761,12.9774 -42.05127,21.5989 -67.8323,15.7338 -25.78106,-5.8653 -69.54907,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 24.381071,839.38658 21.334081,813.84027 0.03533552,788.33044 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 c 29.994295,6.08166 50.57936,31.8724 63.979783,72.7125 9.554154,-3.91791 18.237764,-9.37294 30.187414,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.687255,-101.06994 53.441965,5.67033 83.657025,80.63932 78.971425,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24896,-38.34702 -21.04781,-76.8679 -3.65971,-118.64818 0,0 48.28678,65.43687 54.38966,85.80577 6.10287,20.36891 1.51881,38.70052 1.51881,38.70052 0,0 16.95957,31.08529 20.29392,51.09413 3.3731,20.24135 -3.53269,59.10332 -4.94582,77.98324 z"
+ id="path3624-1"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter9024-1"
+ x="-0.55453134"
+ width="2.1090627"
+ y="-0.51434779"
+ height="2.0286956">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="20.912684"
+ id="feGaussianBlur9026-0" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9020-8"
+ x="-0.32861114"
+ width="1.6572223"
+ y="-0.182"
+ height="1.364">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="20.912684"
+ id="feGaussianBlur9022-5" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter9044-0"
+ x="-0.32631579"
+ width="1.6526316"
+ y="-0.84545463"
+ height="2.6909094">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="21.92031"
+ id="feGaussianBlur9046-6" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4177-4">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path4179-6"
+ d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4105-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.8640966"
+ id="feGaussianBlur4107-5" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4130-8"
+ x="-0.49509686"
+ width="1.9901937"
+ y="-0.26708817"
+ height="1.5341763">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.730622"
+ id="feGaussianBlur4132-6" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4141-2"
+ x="-0.40611032"
+ width="1.8122206"
+ y="-0.30260596"
+ height="1.6052119">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="9.8586086"
+ id="feGaussianBlur4143-8" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8338-4">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8340-7"
+ d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8333-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.18"
+ id="feGaussianBlur8335-4" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8359-0">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8361-6"
+ d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8354-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.82"
+ id="feGaussianBlur8356-9" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3636-90">
+ <path
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ id="path3638-8"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4185-1">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.6164709"
+ id="feGaussianBlur4187-3" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8392-1">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8394-1"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8379-0"
+ x="-0.14413793"
+ width="1.288276"
+ y="-0.10278689"
+ height="1.2055738">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.389266"
+ id="feGaussianBlur8381-3" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8417-4">
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8419-03"
+ d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter8404-9"
+ x="-0.090268657"
+ width="1.1805373"
+ y="-0.10250848"
+ height="1.205017">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.3457272"
+ id="feGaussianBlur8406-1" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2843"
+ id="linearGradient6951"
+ gradientUnits="userSpaceOnUse"
+ x1="347.89655"
+ y1="1070.2124"
+ x2="275.58191"
+ y2="867.97992" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8964"
+ id="linearGradient6953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)"
+ x1="603.84064"
+ y1="627.85303"
+ x2="616.24396"
+ y2="585.42664" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8952"
+ id="linearGradient6955"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)"
+ x1="609.31244"
+ y1="239.46866"
+ x2="560.83142"
+ y2="262.86206" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3961"
+ id="linearGradient6957"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(450.03125,73.843964)"
+ x1="398.21429"
+ y1="343.52289"
+ x2="379.28571"
+ y2="265.30862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4084"
+ id="linearGradient6959"
+ gradientUnits="userSpaceOnUse"
+ x1="182.35046"
+ y1="256.11136"
+ x2="145.53348"
+ y2="542.20502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4084"
+ id="linearGradient6961"
+ gradientUnits="userSpaceOnUse"
+ x1="182.35046"
+ y1="256.11136"
+ x2="145.53348"
+ y2="542.20502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient6963"
+ gradientUnits="userSpaceOnUse"
+ x1="412.08926"
+ y1="404.91574"
+ x2="417.375"
+ y2="401.82648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient6965"
+ gradientUnits="userSpaceOnUse"
+ x1="411.91071"
+ y1="404.91577"
+ x2="417.375"
+ y2="401.82648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient6967"
+ gradientUnits="userSpaceOnUse"
+ x1="411.91071"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient6969"
+ gradientUnits="userSpaceOnUse"
+ x1="412.08926"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4478"
+ id="linearGradient6971"
+ gradientUnits="userSpaceOnUse"
+ x1="411.73212"
+ y1="405.54077"
+ x2="417.375"
+ y2="401.82648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3660"
+ id="linearGradient6973"
+ gradientUnits="userSpaceOnUse"
+ x1="1255.7386"
+ y1="667.09216"
+ x2="893.69995"
+ y2="858.01099" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath6975">
+ <rect
+ id="rect6977"
+ width="440"
+ height="376"
+ x="547.99994"
+ y="205.32277"
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new" />
+ </clipPath>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send-4"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ inkscape:connector-curvature="0"
+ id="path7188-9"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+ style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+ </marker>
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="Shadow"
+ transform="translate(48.571445,195.53053)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer20"
+ inkscape:label="New Ear"
+ transform="translate(48.571445,195.53053)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer21"
+ inkscape:label="Rendered2"
+ style="display:inline"
+ transform="translate(48.571445,195.53053)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer15"
+ inkscape:label="Feet"
+ style="display:inline"
+ transform="translate(48.571445,195.53053)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer16"
+ inkscape:label="Left Foot"
+ style="display:inline"
+ transform="translate(48.571445,195.53053)">
+ <rect
+ style="display:inline;opacity:1;fill:#a8a8a8;fill-opacity:1;stroke:#000000;stroke-width:20.89992332;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+ id="rect6676-3-7-5"
+ width="1876.7191"
+ height="1562.9667"
+ x="-38.121483"
+ y="-86.153076" />
+ <rect
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20.92477036;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+ id="rect6676-3-7"
+ width="1878.7875"
+ height="1564.9603"
+ x="2288.5129"
+ y="-84.10511" />
+ <rect
+ style="display:inline;opacity:1;fill:#a8a8a8;fill-opacity:1;stroke:#f83615;stroke-width:20.39127541;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+ id="rect6676-3"
+ width="1833.4282"
+ height="1522.9458"
+ x="2309.7717"
+ y="-62.567806" />
+ <g
+ id="g4303">
+ <path
+ inkscape:export-ydpi="142.10527"
+ inkscape:export-xdpi="142.10527"
+ inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
+ transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
+ sodipodi:nodetypes="cccccccccsccccccccccc"
+ id="path10326"
+ d="m 304.64285,526.6479 c -10,0.35715 -18.21428,2.85714 -18.21428,2.85714 l 7.5,6.07143 10.35714,3.57143 16.07143,0.35714 22.5,-5.35714 7.85714,1.07143 20.35715,-2.14286 -10.35715,6.78572 c 5.45923,-1.02361 17.39329,3.56911 9.64286,5.35714 -1.74,0.40142 13.92857,-4.64285 13.92857,-4.64285 l 2.5,-4.64287 3.57143,-9.28571 11.42857,0 18.21428,-4.64286 3.57144,-4.99999 -16.07144,1.07142 -12.14285,2.14286 -14.64286,-5 -70.6921,16.70774 -5.37933,-5.27917 z"
+ style="display:inline;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter11361);enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)"
+ id="g7882"
+ style="display:inline;opacity:1;enable-background:new">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7904);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 245.12255,100.05344 c 0,0 -47.12811,-31.646921 -67.21465,-35.800939 -20.03792,-4.143963 -38.4729,-3.317578 -51.93364,13.607323 -13.46074,16.924901 -12.07739,61.265196 -13.53554,86.969546 -1.45815,25.70435 2.54945,70.17701 17.6046,88.66552 15.05516,18.4885 45.88634,13.58502 49.92695,21.4137 2.21283,4.28736 65.15228,-174.85515 65.15228,-174.85515 z"
+ id="path7876"
+ sodipodi:nodetypes="czzzzcc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7906);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 135.37935,82.017807 c 0,0 26.34355,1.938783 37.63307,13.903188 11.41494,12.097335 13.73457,21.331515 15.29586,37.734585 1.56337,16.42499 -0.84957,28.41812 -7.81382,36.03734 -6.96425,7.61922 -1.00429,19.58332 -25.91605,12.07107 -24.91176,-7.51225 -27.03224,-27.78298 -26.51523,-46.30475 0.51721,-18.52898 7.31617,-53.441433 7.31617,-53.441433 z"
+ id="path7878"
+ sodipodi:nodetypes="czzzzzc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:1;fill:url(#radialGradient7908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 135.648,81.927211 c 0,0 -4.64465,16.365075 0.58825,28.563099 5.48794,12.79254 27.22425,44.26007 27.22425,54.65565 l 22.65625,-5 c 2.54218,-6.96644 3.21052,-15.75206 2.1875,-26.5 -1.56129,-16.40307 -3.8663,-25.62141 -15.28125,-37.718749 -9.65488,-10.232047 -31.59311,-13.374857 -37.375,-14 z"
+ id="path7880"
+ sodipodi:nodetypes="czccssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="czzzcczzcc"
+ id="path7917"
+ d="m 845.03125,1154.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.2857 c 0,0 85.88551,-16.2009 112.14285,-33.5714 26.25735,-17.3705 45.58238,-49.66602 59.28572,-71.42861 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="ccccc"
+ clip-path="url(#clipPath8658)"
+ id="path7919"
+ d="m 332.34019,898.38549 -32.73181,-61.29956 -37.61734,45.10646 c 2.17675,1.31711 5.77425,-20.85603 45.6004,-64.41708 l 24.74875,80.61018 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8888);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="cccccc"
+ clip-path="url(#clipPath2833)"
+ id="path7923"
+ d="m 200.81833,863.03015 146.3711,-51.61879 243.95184,226.27414 -241.83052,140.0072 -181.01934,-87.6813 32.52692,-226.98125 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8892);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzcczcc"
+ id="path7921"
+ d="m 642.88839,640.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57145 -62.5,123.57145 l 76.07143,18.2143 c 0,0 11.80712,-12.8234 31.07142,-46.07146 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3665)"
+ sodipodi:nodetypes="ccccccc"
+ id="path7925"
+ d="m 430.28131,381.94122 c -7.07106,2.82843 -236.18124,32.15181 -236.18124,32.15181 l -39.63961,359.83304 90.19849,92.63961 52.3259,-114.5513 100.46804,-186.39192 32.82842,-183.68124 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8856);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzcc"
+ id="path7927"
+ d="m 969.67051,1164.0346 c 0,0 23.25628,11.3937 36.06779,20.4761 12.6974,9.0015 29.4724,24.6491 41.6924,37.3605 12.3055,12.8002 20.1127,22.5987 41.5327,24.1608 21.4322,1.5629 53.2824,-8.7876 73.296,-24.6642 20.0135,-15.8766 45.6469,-69.2328 45.6469,-69.2328 l -127.1608,-143.0717"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="ccccc"
+ clip-path="url(#clipPath8642)"
+ id="path7929"
+ d="M 331.34019,641.50471 216.17367,835.36467 260.2153,925.96265 357.79603,732.21539 331.34019,641.50471 Z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8860);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:transform-center-y="-28.255779"
+ inkscape:transform-center-x="-347.89063"
+ transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+ id="g7931"
+ style="display:inline;opacity:1;enable-background:new">
+ <path
+ id="path7933"
+ d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+ style="display:inline;opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.9975712,-0.06965428,0.06965428,0.9975712,872.72062,140.02502)"
+ id="g7935"
+ style="display:inline;filter:url(#filter7610);enable-background:new"
+ clip-path="url(#clipPath7616)">
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 229.94262,-409.12268 c -3.55781,0.05 -9.0242,0.36009 -10.30334,0.90414 -1.60609,-0.44747 -3.90316,-0.88131 -5.89995,-0.87674 -3.07199,0.007 -4.96469,0.009 -6.90727,0 -0.66047,-0.003 -1.04759,0.0672 -1.35267,0.10959 0,0 0,1.09593 0,1.09593 0.11972,-0.17947 0.39252,-0.69046 0.94975,-0.76715 0.74758,-0.10289 5.16928,-0.15123 7.31019,-0.1096 1.7746,0.0345 4.45523,0.27427 6.38921,0.95895 0.3214,0.11378 0.61925,0.27378 0.89219,0.41097 1.96342,0.98693 7.94336,4.30154 7.94336,4.30154 0,0 -6.63275,-3.94768 -7.48287,-4.43853 -0.20331,-0.11739 -0.57464,-0.25769 -1.03609,-0.41098 1.22063,-0.44779 5.07597,-0.61971 7.82823,-0.71235 3.0245,-0.10182 3.34776,-0.0896 5.41069,0.19179 2.12931,0.29043 3.33851,0.60276 3.33851,0.60276 -1e-5,0 -0.0784,-0.64118 1.03609,-0.79455 0.74757,-0.10289 5.16929,-0.15123 7.31019,-0.1096 2.0695,0.0403 5.36605,0.40716 7.2814,1.36992 1.00332,0.50433 3.03564,1.56863 4.79535,2.53571 l 0.0956,-0.0194 c 0,0 -3.58034,-2.16242 -4.43047,-2.65327 -0.20331,-0.11739 -0.57463,-0.25769 -1.03609,-0.41098 1.22062,-0.44779 5.04719,-0.61971 7.79945,-0.71235 3.0245,-0.10182 3.34775,-0.0896 5.41069,0.19179 1.95316,0.2664 3.01292,0.53006 3.19461,0.57536 0,0 -0.0271,-0.31146 -0.0271,-0.31146 -0.40903,-0.13645 -0.71424,-0.23335 -1.40038,-0.35748 -1.30081,-0.23533 -3.39912,-0.60156 -5.50857,-0.56398 -3.57195,0.0636 -9.05328,0.35596 -10.30334,0.90414 -1.60583,-0.44695 -3.87662,-0.8813 -5.87117,-0.87674 -3.07199,0.007 -4.99348,0.009 -6.93605,0 -1.94256,-0.009 -1.71268,0.27907 -2.93558,0.27398 -1.32191,-0.005 -1.76612,-0.35463 -5.55459,-0.30138 0,0 0,0 0,0"
+ id="path7937"
+ sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssccsscc"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 206.1989,-407.47878 c 1.92021,0.81706 4.57715,2.19283 6.15897,3.39739 1.58184,1.20456 2.90757,1.77368 5.55459,3.91795 0.88557,0.71738 1.74865,1.34985 2.59193,1.92174 l 0.54057,-0.19011 c -0.71323,-0.48339 -1.46776,-1.02031 -2.26909,-1.62203 -2.82223,-2.11921 -3.62655,-2.80973 -6.01507,-4.27414 -2.38854,-1.4644 -4.09948,-2.36576 -6.5619,-3.1508 0,0 0,0 0,0"
+ id="path7939"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csccscc"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 237.79963,-407.47878 c 1.92021,0.81706 4.60594,2.19283 6.18775,3.39739 0.81307,0.61916 1.55849,1.07042 2.45046,1.65401 l 0.649,-0.11666 c -0.79831,-0.57637 -1.57177,-1.09435 -2.69653,-1.78394 -2.38854,-1.4644 -4.12826,-2.36576 -6.59068,-3.1508 0,0 0,0 0,0"
+ id="path7941"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g7943"
+ clip-path="url(#clipPath7606)">
+ <path
+ sodipodi:nodetypes="czzzzzzzzzzzzzz"
+ id="path7945"
+ d="m 1056.25,-278.80481 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+ style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7578);enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzzzzzzzzzzz"
+ id="path7947"
+ d="m 1058.5,-275.42981 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+ style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7594);enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cscccccccccccc"
+ id="path7949"
+ d="m 628.24553,347.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.29583 116.94091,-84.69468 185.93466,-91.46542 86.92239,-11.0168 184.91267,17.94007 233.37138,95.40128 54.124,75.7333 56.6747,172.53912 80.612,259.52795 29.4378,127.1276 54.7791,256.21414 60.3922,386.85035 -3.0634,78.18185 -8.4263,165.18417 -60.5032,228.13417 -48.0265,50.3574 -122.7864,50.053 -187.06985,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94 -95.73019,-113.47867 -97.2794,-186.01962 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8616)"
+ sodipodi:nodetypes="ccccczzzcc"
+ id="path7951"
+ d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 -38.61152,-142.95988 -39.24264,-189.11984 -0.63145,-46.18445 10.83034,-108.60786 30.67767,-158.29647 20.04835,-50.19188 36.89674,-44.84642 42.12489,-92.59293 5.22815,-47.74651 -17.4264,-149.39192 -17.4264,-149.39192 l -55.86144,39.59798 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8940);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czcc"
+ id="path7953"
+ d="m 1010.0312,655.49186 c 0,0 16.7552,37.01806 28.7015,53.95395 11.9462,16.93589 52.7271,56.04605 52.7271,56.04605 l 52.5972,-127.58975"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient8970);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8209)"
+ sodipodi:nodetypes="cccc"
+ id="path7955"
+ d="m 730.31998,536.56864 c 0,8.48528 42.54774,58.46803 42.54774,58.46803 l 12.60659,-28.76954 -55.15433,-29.69849 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8822);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ clip-path="url(#clipPath3998)"
+ id="g7957"
+ style="display:inline;opacity:1;enable-background:new"
+ transform="translate(450.03125,73.843964)">
+ <g
+ id="g7959"
+ style="filter:url(#filter3677)"
+ transform="translate(-174.03125,62.156036)">
+ <g
+ style="filter:url(#filter3785)"
+ id="g7961">
+ <path
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+ id="path7963"
+ sodipodi:nodetypes="czzzzzzzzzz"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect7965"
+ width="381.83765"
+ height="181.01935"
+ x="343.6539"
+ y="412.60312" />
+ </g>
+ <g
+ style="filter:url(#filter3785)"
+ id="g7967">
+ <path
+ transform="translate(174.03125,-62.156036)"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+ id="path7969"
+ sodipodi:nodetypes="czzzcc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect7971"
+ width="207.8894"
+ height="162.63455"
+ x="702.86414"
+ y="344.82138" />
+ </g>
+ </g>
+ <g
+ id="g7973"
+ style="display:inline;opacity:0.18000004;enable-background:new"
+ transform="translate(-174.03125,62.156036)">
+ <g
+ style="filter:url(#filter3785)"
+ id="g7975">
+ <path
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+ id="path7977"
+ sodipodi:nodetypes="czzzzzzzzzz"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect7979"
+ width="381.83765"
+ height="181.01935"
+ x="343.6539"
+ y="412.60312" />
+ </g>
+ <g
+ style="filter:url(#filter3785)"
+ id="g7981">
+ <path
+ transform="translate(174.03125,-62.156036)"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+ id="path7983"
+ sodipodi:nodetypes="czzzcc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect7985"
+ width="207.8894"
+ height="162.63455"
+ x="702.86414"
+ y="344.82138" />
+ </g>
+ </g>
+ </g>
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="cccccscc"
+ clip-path="url(#clipPath8604)"
+ id="path7987"
+ d="M 582.65599,-7.4183011 695.79307,78.848726 804.68752,337.64981 842.87128,545.5392 963.07944,637.46308 c 0,0 -12.72793,-287.08535 -19.799,-313.95541 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 Z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8802);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzzzc"
+ id="path7989"
+ d="m 964.13839,239.599 c 0,0 8.67732,10.89662 24.10715,11.96428 15.42986,1.06766 49.72166,-39.95267 70.17856,-52.14285 20.4793,-12.20353 47.0464,-26.60225 63.9286,-20.35714 16.8821,6.2451 22.1578,26.43609 27.8571,48.03571 5.6994,21.59961 6.7186,61.81389 -2.6785,92.85715 -9.3972,31.04325 -50.5033,73.10375 -65.3572,103.39285 -14.8539,30.2891 -11.6071,39.82143 -11.6071,39.82143"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient8958);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzc"
+ id="path7991"
+ d="m 1124.4955,207.63471 c -15.8928,-0.89286 -49.7188,12.10583 -66.0714,24.28572 -16.4386,12.2439 -29.2209,24.1144 -29.2857,52.14285 -0.065,28.20604 13.1191,39.07641 29.1071,46.96429 15.988,7.88789 33.6862,7.11928 51.9643,-11.78571 18.2782,-18.905 14.2857,-111.60715 14.2857,-111.60715 z"
+ style="display:inline;opacity:1;fill:url(#radialGradient3315);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ clip-path="url(#clipPath4100)"
+ transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
+ id="path7993"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient3543);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4120);enable-background:accumulate"
+ cx="385"
+ cy="237.00504"
+ rx="86.428574"
+ ry="73.928574" />
+ <path
+ mask="url(#mask3684)"
+ sodipodi:nodetypes="csczzc"
+ id="path7995"
+ d="m 527.60588,407.44884 c 0,0 -122.04144,38.40348 -187.51434,9.63181 -65.47289,-28.77166 -74.37725,-124.71847 -74.37725,-124.71847 0,0 73.38158,-80.50393 129.92078,-83.61476 55.82705,-3.07164 90.57386,20.14332 114.87001,65.85171 24.352,45.81348 17.1008,132.84971 17.1008,132.84971 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3915);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czcc"
+ id="path7997"
+ d="m 772.17411,393.349 c 0,0 36.21754,-27.38247 51.60714,-35.89286 15.17734,-8.39301 25.71428,-11.60714 35.89285,-11.60714 l -15.53571,66.96428"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3959);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <circle
+ transform="translate(449.49554,74.915393)"
+ id="path7999"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3933);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ cx="409.28571"
+ cy="306.64789"
+ r="36.25" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8616)"
+ sodipodi:nodetypes="cccccccccc"
+ id="path8001"
+ d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 8.68161,-72.36764 -31.24264,-223.11984 l 17.67767,-69.29647 72.12489,-138.59293 -42.4264,-158.39192 -55.86144,39.59798 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8806);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzcc"
+ id="path8003"
+ d="m 635.21025,581.13004 c -14.14214,12.72792 39.23347,34.58015 76.36753,24.04163 37.13406,-10.53852 104.64487,-35.56437 103.23759,-79.19596 -1.40728,-43.63158 -76.36753,-128.69343 -76.36753,-128.69343 L 635.21025,581.13004 Z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8826);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <circle
+ transform="translate(449.67411,74.915393)"
+ id="path8005"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3991);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ cx="410"
+ cy="306.64789"
+ r="23.214285" />
+ <circle
+ transform="translate(451.99554,73.486821)"
+ id="path8007"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3981);enable-background:accumulate"
+ cx="414.28571"
+ cy="303.07648"
+ r="7.5" />
+ <path
+ sodipodi:nodetypes="czzzczc"
+ id="path8009"
+ d="m 789.31696,478.349 c 0,0 7.02281,19.56859 -1.07143,35 -8.09424,15.43141 -42.32317,38.98822 -67.49999,50 -25.30972,11.06991 -85.473,32.96393 -101.78572,41.96428 -16.46148,9.08243 -18.21428,12.67857 -18.21428,12.67857 0,0 -7.14693,-19.06441 28.74999,-51.7857 36.17211,-32.97214 142.02712,-48.0495 159.82143,-87.85715 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4112);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(780.74553,74.55825)"
+ id="g8011"
+ style="display:inline;opacity:1;enable-background:new">
+ <path
+ style="display:inline;opacity:1;fill:url(#radialGradient3585);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+ id="path8013"
+ sodipodi:nodetypes="czzczzzszc"
+ clip-path="url(#clipPath3999)"
+ transform="translate(-329.81481,0)"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4060);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8015"
+ transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
+ cx="183.57143"
+ cy="338.07648"
+ rx="64.715881"
+ ry="134.00607" />
+ <ellipse
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4062);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8017"
+ transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
+ cx="183.57143"
+ cy="338.07648"
+ rx="64.715881"
+ ry="134.00607" />
+ <path
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3587);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4079);enable-background:new"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+ id="path8019"
+ sodipodi:nodetypes="czzczzzszc"
+ clip-path="url(#clipPath3999)"
+ transform="translate(-329.81481,3e-7)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <circle
+ transform="translate(452.55663,72.581273)"
+ id="path8021"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ cx="310.71429"
+ cy="398.07648"
+ r="19.704132" />
+ <circle
+ transform="translate(450.55663,72.581273)"
+ id="path8023"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4056);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4082);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4083);enable-background:accumulate"
+ cx="310.71429"
+ cy="398.07648"
+ r="19.704132" />
+ <circle
+ transform="translate(450.55663,72.581273)"
+ id="path8025"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4119);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ cx="310.71429"
+ cy="398.07648"
+ r="19.704132" />
+ <ellipse
+ inkscape:transform-center-y="-3.6935079"
+ inkscape:transform-center-x="-47.231976"
+ transform="matrix(0.9969564,-0.07796167,0.07796167,0.9969564,436.61877,125.29509)"
+ id="path8027"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4868);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4002);enable-background:accumulate"
+ cx="429.56738"
+ cy="377.42877"
+ rx="72.079735"
+ ry="44.547726" />
+ <ellipse
+ inkscape:transform-center-y="-13.056625"
+ inkscape:transform-center-x="-20.955902"
+ transform="matrix(1.4357951,-0.06999104,0.06999104,1.4357951,235.18065,-63.86546)"
+ id="path8029"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4876);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4010);enable-background:accumulate"
+ cx="437.6991"
+ cy="391.21735"
+ rx="36.611931"
+ ry="22.627417" />
+ <g
+ style="display:inline;opacity:1;filter:url(#filter4053);enable-background:new"
+ id="g8031"
+ transform="translate(450.03125,73.843964)">
+ <circle
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4484);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8033"
+ cx="413.66071"
+ cy="401.82648"
+ r="3.2142856" />
+ <circle
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4486);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8035"
+ transform="translate(13.125009,8.1249913)"
+ cx="413.66071"
+ cy="401.82648"
+ r="3.2142856" />
+ <circle
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4488);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8037"
+ transform="translate(32.946437,7.4999913)"
+ cx="413.66071"
+ cy="401.82648"
+ r="3.2142856" />
+ <circle
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4490);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8039"
+ transform="translate(24.910723,-10.267866)"
+ cx="413.66071"
+ cy="401.82648"
+ r="3.2142856" />
+ <circle
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4492);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8041"
+ transform="translate(47.589294,-0.6250087)"
+ cx="413.66071"
+ cy="401.82648"
+ r="3.2142856" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path8043"
+ d="m 896.20301,482.92837 c 0.98509,4.35008 4.53707,6.17948 7.38673,7.89182 4.46068,2.51292 6.52016,1.52211 9.15451,-0.75761 1.60195,-1.92117 10.68311,-4.69865 15.59423,-7.07107 4.32961,-1.45891 8.9033,-5.35873 13.38452,-8.33376 3.39514,-1.62724 5.34664,0.35464 7.82868,1.01015 2.94412,0.71661 4.41117,2.17175 6.06092,3.53554 2.39616,1.17519 -0.9279,3.14313 3.283,4.29314 1.19091,0.21794 2.41695,0.57645 3.28299,-0.50507"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path8045"
+ d="m 910.85021,475.35223 c 2.31494,-0.032 3.17778,0.64253 5.49271,-0.82075 3.45564,-3.08113 5.40254,-3.14477 7.95495,-4.41942 3.02657,-1.31523 6.5357,8.15169 10.10153,9.84899 2.39509,-0.82142 1.28914,1.79379 1.45209,2.65165 0.0571,2.64684 2.80694,3.67806 4.35628,5.42957 3.31604,2.25549 7.37523,6.29546 11.11168,5.3033 6.44525,-2.93107 10.27922,-1.28146 16.28871,-7.38674 0.70405,-1.18134 -0.58425,-6.8946 3.09359,-7.19734 2.52399,0.25338 4.16667,0.0502 6.06092,0.56822 5.441,2.11719 7.73778,6.45 14.71034,7.95495 6.1829,0.96639 7.61264,3.79426 13.88959,5.05076"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path8047"
+ d="m 876.98133,483.52197 c 2.39858,-0.7938 6.10613,4.1921 8.17313,7.04568 0.59281,2.67952 1.15377,5.48645 0.75761,12.12183 0.78513,2.41754 2.68049,3.03095 4.79823,3.283 3.11745,-0.53678 5.87669,-1.3243 7.3236,-3.03046 1.8716,-1.94167 5.31253,2.39394 8.08122,4.04061 3.61009,1.91209 7.77378,1.97886 11.8693,2.27284 1.70358,-0.23064 2.3704,4.51515 3.28299,8.08123 0.38414,4.37806 -0.88544,6.89569 -1.76776,9.84898 -0.2943,2.49655 2.9885,3.52974 6.31345,4.54569 3.18244,0.74124 6.54424,1.66184 9.09137,1.76777 5.14186,0.87491 8.08874,2.69052 12.12183,4.04061 2.23914,0.81655 3.26019,2.24216 4.54569,3.53553"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8514)"
+ id="path8049"
+ d="m 332,187.69519 c 0,0 57.5,-25.5 57.5,-28 0,-2.5 5.5,-52 5.5,-52 0,0 91,-48.500001 91.5,-50.500001 0.5,-2 86,-62.0000004 86,-62.0000004 L 386.5,17.195189 311,123.19519 l 21,64.5 z"
+ style="display:inline;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter8814);enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path8051"
+ d="m 1697.2846,722.5514 c 0,0 -115.9655,73.5391 -123.0365,77.78174 -7.0711,4.24264 -230.5169,137.17872 -230.5169,137.17872 l 4.2427,39.59798 216.3747,-100.40917 117.3797,-101.82337 15.5563,-52.3259 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="cccccscccc"
+ clip-path="url(#clipPath8610)"
+ id="path8053"
+ d="m 528.91587,556.85291 c -5.65685,-1.41421 -181.01933,74.95332 -181.01933,74.95332 l -33.94113,181.01934 51.09546,193.94823 257.2031,67.6813 c 0,0 206.47518,152.735 212.13203,148.4924 5.65686,-4.2426 168.2914,-193.7473 168.2914,-193.7473 L 842.87128,845.35248 796.20224,667.16157 528.91587,556.85291 Z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzzzczczczczzzc"
+ id="path8055"
+ d="m 1097.6433,613.88997 c 0,0 22.6195,-6.50681 35.7427,-5.87273 13.1233,0.63409 30.6416,1.93862 43.7089,12.18619 13.0673,10.24756 25.0677,27.14007 34.1124,58.36965 9.0446,31.22958 1.6983,99.25201 -6.1761,143.34735 -7.8743,44.09534 -28.2651,106.11298 -45,140 -16.7348,33.88702 -49.7977,77.49517 -60.5694,89.87617 -11.3642,13.062 -56.2059,36.4262 -79.4306,42.2667 5.3034,-10.6066 48.8998,-50.5889 35,-60.7143 -14.0189,-10.2123 -45.76,45.9824 -84.2931,29.0332 21.38231,-13.1321 41.7794,-51.1861 34.0406,-66.59448 -7.84024,-15.61039 -30.70492,48.75758 -93.53553,37.01288 30.05204,-27.5267 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.2932 -60.46175,54.2932 0,0 -2.8219,-41.70123 13.7732,-68.60737 16.63935,-26.97787 79.65297,-81.61527 99.55308,-111.70342 19.9002,-30.08814 33.6126,-66.00902 42.1355,-92.51794 8.5228,-26.50892 15.8009,-77.09954 15.8009,-77.09954"
+ style="display:inline;opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="cccccccccc"
+ clip-path="url(#clipPath8622)"
+ id="path8057"
+ d="m 770.74639,609.17881 -50.91169,97.58074 -79.90307,111.01576 34.64824,71.41778 42.42641,79.19597 72.12489,-45.25484 14.14214,-192.33305 21.2132,-138.59292 -14.14214,-90.15612 -39.59798,107.12668 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8818);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ sodipodi:nodetypes="cczcccccc"
+ clip-path="url(#clipPath8906)"
+ id="path8059"
+ d="m 295,846.19519 6.64488,-68.92285 c 0,0 90.31951,89.00457 162.35512,122.92285 72.03561,33.91828 308,62 308,62 l 154,-26 -36,162.00001 -286,26 -298,-89 -11,-189.00001 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ clip-path="url(#clipPath3602)"
+ sodipodi:nodetypes="cccccccccccc"
+ id="path8061"
+ d="m 405.79629,845.99023 74.95332,65.05383 2.49963,16.8804 19.40336,10.15891 6.49204,23.05109 31.70905,-8.3711 14.84924,48.08324 c 12.25652,12.7279 89.79344,-113.1097 55.86143,38.1838 l -60.81118,16.2635 -89.20292,-94.69286 -62.82503,-53.79963 7.07106,-60.81118 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3587);enable-background:new"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzzzzzcc"
+ id="path8063"
+ d="m 1159.317,918.349 c 54.2857,-1.42857 126.035,-15.05199 170,-26.78572 44.0527,-11.75714 125.8863,-36.34724 175.357,-57.85714 49.3393,-21.45272 113.6038,-59.2816 154.2859,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7142,-33.57143 8.3691,22.36779 -16.4069,56.32562 -37.8571,81.07143 -21.6042,24.9234 -52.7314,52.70533 -98.9287,89.28571 -46.1973,36.58038 -156.0825,101.58463 -212.8571,128.5714 -57.066,27.1254 -128.2033,58.2385 -172.1428,72.5001 -43.9395,14.2616 -131.4286,31.0714 -131.4286,31.0714 L 1159.317,918.349 Z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ clip-path="url(#clipPath3992)"
+ sodipodi:nodetypes="czczzcc"
+ id="path8065"
+ d="m 1241.5965,652.95007 c 0,0 -64.7215,54.33706 -145.6639,98.99494 -82.0244,45.25484 -284.25704,93.3381 -284.25704,93.3381 0,0 -15.10137,21.05196 45.25489,28.28428 60.35626,7.23232 224.08195,-53.30069 278.60015,-96.16654 54.5182,-42.86585 120.2081,-111.72286 120.2081,-111.72286 l -14.1422,-12.72792 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#linearGradient3666);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3779);enable-background:accumulate"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <g
+ clip-path="url(#clipPath3986)"
+ id="g8067"
+ style="display:inline;opacity:1;enable-background:new"
+ transform="translate(450.03125,73.843964)">
+ <g
+ id="g8069"
+ style="filter:url(#filter3677)"
+ transform="translate(-174.03125,62.156036)">
+ <g
+ id="g8071"
+ style="filter:url(#filter3785)">
+ <path
+ transform="translate(174.03125,-62.156036)"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+ id="path8073"
+ sodipodi:nodetypes="czzccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8075"
+ width="333.75412"
+ height="309.71277"
+ x="1197.8389"
+ y="486.14224" />
+ </g>
+ </g>
+ <g
+ id="g8077"
+ style="display:inline;opacity:0.18000004;enable-background:new"
+ transform="translate(-174.03125,62.156036)">
+ <g
+ id="g8079"
+ style="filter:url(#filter3785)">
+ <path
+ transform="translate(174.03125,-62.156036)"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+ id="path8081"
+ sodipodi:nodetypes="czzccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8083"
+ width="333.75412"
+ height="309.71277"
+ x="1197.8389"
+ y="486.14224" />
+ </g>
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc"
+ clip-path="url(#clipPath3722)"
+ id="path8085"
+ d="m 1264.1875,605 c -4.4911,0.73268 -8.157,3.45509 -11.9375,6.40625 -10.0813,7.86976 -28.1695,34.42524 -48.0312,50.46875 -39.8674,32.20316 -103.996,69.97701 -152.5626,91.09375 -48.614,21.13738 -130.54122,45.81801 -174.31245,57.5 -43.39821,11.58246 -115.04403,25.13107 -168.25,26.53125 l -4.5625,0.125 -2,4.125 -92.84375,192.125 -6.5,13.4688 14.65625,-2.8438 c 0,0 87.26968,-16.6514 132.34375,-31.2812 44.7252,-14.51667 115.79086,-45.66683 173.03125,-72.87505 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 c 46.3608,-36.70982 77.8049,-64.71682 99.9375,-90.25 10.9011,-12.576 22.7448,-27.53144 31.0313,-42.75 8.2864,-15.21856 19.1597,-44.21808 13.6874,-58.84375 -1.2177,-3.25474 -2.5514,-6.0613 -4.5937,-8.5 -2.0423,-2.4387 -8.4747,-1.57199 -8.5625,-5.03125 -0.2098,-8.26482 -3.3155,-0.24423 -4.8125,0 z m 2.1563,15.21875 c 0.4148,0.58574 1.0311,1.55766 1.7812,3.5625 2.8968,7.74213 -1.4407,31.89875 -8.8125,45.4375 -7.3718,13.53875 -22.6384,28.92394 -33.1875,41.09375 -21.0754,24.31356 -51.9037,51.86156 -97.9375,88.3125 -45.0496,35.67159 -155.46033,101.09459 -211.40625,127.6875 -56.89173,27.04249 -128.09616,58.1184 -171.25,72.125 -36.36491,11.8031 -95.84471,23.8338 -115.71875,27.7813 L 714.09375,851.75 c 54.70691,-2.0493 123.79259,-15.21635 167.125,-26.78125 44.33422,-11.83225 126.07865,-36.33633 176.40625,-58.21875 50.112,-21.78871 112.5344,-61.16816 154.0312,-94.6875 20.6464,-16.67721 41.7449,-42.54588 49.8126,-48.84375 2.437,-1.90242 4.0806,-2.6358 4.875,-3 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter8225);enable-background:accumulate"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:transform-center-y="-12.859654"
+ inkscape:transform-center-x="-185.09603"
+ transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+ mask="url(#mask7704)"
+ id="g8087"
+ style="display:inline;opacity:1;enable-background:new">
+ <path
+ sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc"
+ id="path8089"
+ d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 -12.4759,3.49189 7.92966,19.27772 c -0.59163,1.97357 12.54624,-4.73836 12.54624,-4.73836 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+ style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ transform="translate(0.08004571,-0.03125)"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g8091"
+ clip-path="url(#clipPath7421)">
+ <path
+ sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7001);enable-background:new"
+ d="m 1107.409,-284.04961 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88717,-0.50701 -5.875,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0725 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0774 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,10e-6 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 10e-6,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0532 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 10e-6,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0728,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 10e-6,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0773,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.4497,-0.12571 6.375,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -10e-5,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -1e-4,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+ id="path8093"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6949);enable-background:new"
+ d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+ id="path8095"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6961);enable-background:new"
+ d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+ id="path8097"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6957);enable-background:new"
+ d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+ id="path8099"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6997);enable-background:new"
+ d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.4428,3.93956 1.5794,5.38995 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.9442,0.42864 -1.2366,0.49452 0.531,0.18589 0.8908,0.21322 0.9524,1.05768 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.9524,0.18199 -1.288,0.0511 z"
+ id="path8101"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6953);enable-background:new"
+ d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+ id="path8103"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6993);enable-background:new"
+ d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+ id="path8105"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6989);enable-background:new"
+ d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+ id="path8107"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6985);enable-background:new"
+ d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+ id="path8109"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6965);enable-background:new"
+ d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+ id="path8111"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6981);enable-background:new"
+ d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+ id="path8113"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6977);enable-background:new"
+ d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+ id="path8115"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6973);enable-background:new"
+ d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+ id="path8117"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6969);enable-background:new"
+ d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+ id="path8119"
+ inkscape:connector-curvature="0" />
+ <g
+ style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345)"
+ id="g8121">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 744.9375,-212.11731 c 0,0 7.22229,-3.22318 9.0625,-3.5 1.84021,-0.27682 3.35225,-0.003 6,0.5625 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 5.3125,3.5625 5.3125,3.5625 0,0 -7.14644,-2.78019 -10.1875,-3.5625 -3.04106,-0.78231 -7.64461,-2.08374 -10.375,-2.3125 -2.73039,-0.22876 -11,1.875 -11,1.875 z"
+ id="path8123"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 735.46875,-206.95416 c 0,0 3.65979,-2.22318 5.5,-2.5 1.84021,-0.27682 3.66475,0.24677 6.3125,0.8125 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 6.5625,2.125 6.5625,2.125 0,0 -8.39644,-1.34269 -11.4375,-2.125 -3.04106,-0.78231 -7.95711,-2.33374 -10.6875,-2.5625 -2.73039,-0.22876 -7.4375,0.875 -7.4375,0.875 z"
+ id="path8125"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 759.85042,-217.61116 c 0,0 8.5437,-3.29857 10.39778,-3.45786 1.85409,-0.1593 3.64166,0.4792 6.2481,1.21208 2.60644,0.73288 8.57724,2.76594 10.95036,4.07925 2.37312,1.31331 6.41417,2.53782 6.41417,2.53782 0,0 -8.29413,-1.87365 -11.27931,-2.84767 -2.98519,-0.97402 -7.79269,-2.83478 -10.50302,-3.23662 -2.71033,-0.40184 -12.22808,1.713 -12.22808,1.713 z"
+ id="path8127"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 775.19813,-223.2266 c 0,0 7.77133,-2.78244 9.62831,-2.90349 1.85697,-0.12104 3.631,0.55417 6.22178,1.34062 2.59077,0.78645 8.5184,2.94217 10.86394,4.30412 2.34555,1.36195 6.36049,2.6695 6.36049,2.6695 0,0 -8.25373,-2.04423 -11.21821,-3.07958 -2.96447,-1.03535 -7.73259,-2.99481 -10.43406,-3.45243 -2.70147,-0.45763 -11.42225,1.12126 -11.42225,1.12126 z"
+ id="path8129"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 789.64298,-227.95417 c 0,0 8.68256,-3.52031 10.54154,-3.60535 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.3006,1.78871 -12.3006,1.78871 z"
+ id="path8131"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.852145"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 804.49513,-233.32948 c 0,0 7.80756,-2.58281 9.66654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -11.4256,0.85121 -11.4256,0.85121 z"
+ id="path8133"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.852145"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 819.55763,-237.57948 c 0,0 8.55756,-2.58281 10.41654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.1756,0.85121 -12.1756,0.85121 z"
+ id="path8135"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.852145"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 836.23395,-242.60125 c 0,0 6.96702,-1.98723 8.82784,-1.96757 1.86081,0.0197 3.57873,0.82702 6.10265,1.80705 2.52393,0.98 8.27166,3.57758 10.50756,5.11291 2.2359,1.53535 6.14053,3.14261 6.14053,3.14261 0,0 -8.07561,-2.66222 -10.95336,-3.91866 -2.87774,-1.25645 -7.48412,-3.5707 -10.14328,-4.23121 -2.65915,-0.66049 -10.48194,0.0549 -10.48194,0.0549 z"
+ id="path8137"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.64141"
+ inkscape:transform-center-y="-4.9269042"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 850.73028,-246.00461 c 0,0 7.68784,-2.02768 9.54782,-1.96854 1.85997,0.0592 3.56038,0.90279 6.06293,1.93616 2.50255,1.03334 8.19387,3.75232 10.39668,5.33475 2.20282,1.58245 6.07245,3.2722 6.07245,3.2722 0,0 -8.01729,-2.83298 -10.86772,-4.15022 -2.85043,-1.31723 -7.40666,-3.72872 -10.0512,-4.4455 -2.64454,-0.71678 -11.16096,0.0211 -11.16096,0.0211 z"
+ id="path8139"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.55068"
+ inkscape:transform-center-y="-5.1542119"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 864.82496,-249.21081 c 0,0 8.16952,-1.96906 10.02688,-1.85396 1.85735,0.11512 3.53158,1.00956 6.0019,2.11779 2.47031,1.10821 8.0772,3.99727 10.23138,5.64531 2.15418,1.64804 5.9712,3.45352 5.9712,3.45352 0,0 -7.92839,-3.07306 -10.73787,-4.4755 -2.80949,-1.40244 -7.29106,-3.94999 -9.91283,-4.74606 -2.62176,-0.79606 -11.58066,-0.1411 -11.58066,-0.1411 z"
+ id="path8141"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.41151"
+ inkscape:transform-center-y="-5.4740887"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 881.38485,-251.60282 c 0,0 8.08536,-1.90809 9.93837,-1.73664 1.853,0.17147 3.4993,1.11633 5.93482,2.29908 2.43553,1.18271 7.95209,4.2407 10.05523,5.95339 2.10314,1.7127 5.86357,3.63326 5.86357,3.63326 0,0 -7.8314,-3.3124 -10.597,-4.7995 -2.76561,-1.48712 -7.16775,-4.16959 -9.76414,-5.04491 -2.59637,-0.87531 -11.43085,-0.30468 -11.43085,-0.30468 z"
+ id="path8143"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.258805"
+ inkscape:transform-center-y="-5.79376"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 896.58415,-254.34724 c 0,0 7.64166,-1.4277 9.49547,-1.26515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-0.76897 -10.99774,-0.76897 z"
+ id="path8145"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 911.45328,-255.98544 c 0,0 8.64166,-1.5527 10.49547,-1.39015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.99774,-0.64397 -11.99774,-0.64397 z"
+ id="path8147"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 927.70328,-258.29794 c 0,0 7.64166,-0.8652 9.49547,-0.70265 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-1.33147 -10.99774,-1.33147 z"
+ id="path8149"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 942.82828,-259.48544 c 0,0 8.57916,-1.4902 10.43297,-1.32765 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.93524,-0.70647 -11.93524,-0.70647 z"
+ id="path8151"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 959.07828,-261.54794 c 0,0 7.82916,-0.8027 9.68297,-0.64015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.18524,-1.39397 -11.18524,-1.39397 z"
+ id="path8153"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 974.45328,-262.79794 c 0,0 8.39166,-1.1777 10.24547,-1.01515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08376,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.84721,-3.27474 -10.61993,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.74774,-1.01897 -11.74774,-1.01897 z"
+ id="path8155"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 990.64078,-264.86044 c 0,0 6.89166,-0.9902 8.74547,-0.82765 1.85385,0.16256 3.50465,1.0995 5.94575,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.60053,-0.86282 -10.24772,-1.20647 -10.24772,-1.20647 z"
+ id="path8157"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1007.7658,-265.79794 c 0,0 6.8291,-1.1777 8.683,-1.01515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -10.1852,-1.01897 -10.1852,-1.01897 z"
+ id="path8159"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1023.8908,-267.79794 c 0,0 6.0791,-0.4277 7.933,-0.26515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.4352,-1.76897 -9.4352,-1.76897 z"
+ id="path8161"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1039.7033,-269.17294 c 0,0 6.4541,-0.6777 8.308,-0.51515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.8102,-1.51897 -9.8102,-1.51897 z"
+ id="path8163"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.28378"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1055.2718,-271.03319 c 0,0 5.4976,-0.90945 7.3578,-0.85348 1.8601,0.056 3.5619,0.89674 6.0661,1.92586 2.5044,1.0291 8.2003,3.7384 10.4058,5.31709 2.2055,1.57871 6.078,3.2619 6.078,3.2619 0,0 -8.022,-2.81939 -10.8748,-4.13178 -2.8526,-1.31238 -7.4129,-3.71613 -10.0587,-4.42843 -2.6457,-0.71228 -8.9742,-1.09116 -8.9742,-1.09116 z"
+ id="path8165"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.55813"
+ inkscape:transform-center-y="-5.1360724"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1072.7007,-273.48537 c 0,0 4.5472,-1.15581 6.408,-1.18621 1.8607,-0.0304 3.5996,0.73049 6.1489,1.64231 2.5494,0.91177 8.3649,3.35386 10.6414,4.8285 2.2763,1.47468 6.2227,2.97636 6.2227,2.97636 0,0 -8.1442,-2.44411 -11.0547,-3.62272 -2.9105,-1.1786 -7.5774,-3.36815 -10.2534,-3.95691 -2.6759,-0.58875 -8.1129,-0.68133 -8.1129,-0.68133 z"
+ id="path8167"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.74758"
+ inkscape:transform-center-y="-4.6370147"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1087.1585,-276.5244 c 0,0 5.96,-1.77355 7.8202,-1.83024 1.86,-0.0567 3.6096,0.67955 6.1715,1.55525 2.562,0.87566 2.5226,0.85713 5.3335,1.49015 2.7969,0.62986 7.0767,1.51313 7.0767,1.51313 0,0 -3.6155,-0.0163 -6.7923,-0.46614 -3.1155,-0.44119 -7.3743,-1.69825 -10.0584,-2.24913 -2.6839,-0.55088 -9.5512,-0.013 -9.5512,-0.013 z"
+ id="path8169"
+ sodipodi:nodetypes="czzzczzc"
+ inkscape:transform-center-x="13.79933"
+ inkscape:transform-center-y="-4.4842392"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 1099.25,-279.92981 c 0.1612,0.26862 11.2081,-4.60046 12.1875,-4.6875 0.9794,-0.087 2,3.125 2,3.125 0,0 -0.7751,-1.50434 -2.875,-1.0625 -2.0999,0.44184 -11.3009,2.67141 -11.3125,2.625 z"
+ id="path8171"
+ sodipodi:nodetypes="czczc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7333);enable-background:new"
+ d="m 1107.4532,-284.0938 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88718,-0.50701 -5.87501,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0726 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0775 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,1e-5 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 1e-5,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0533 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 1e-5,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0727,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 1e-5,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0772,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.44971,-0.12571 6.37501,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -1e-4,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -10e-5,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+ id="path8173"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7285);enable-background:new"
+ d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+ id="path8175"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7289);enable-background:new"
+ d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+ id="path8177"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7293);enable-background:new"
+ d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+ id="path8179"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7337);enable-background:new"
+ d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.2218,3.85117 1.3584,5.30156 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.7232,0.51703 -1.0156,0.58291 0.531,0.18589 0.6698,0.12483 0.7314,0.96929 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.7314,0.27038 -1.067,0.13944 z"
+ id="path8181"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7297);enable-background:new"
+ d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+ id="path8183"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7301);enable-background:new"
+ d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+ id="path8185"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7305);enable-background:new"
+ d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+ id="path8187"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7309);enable-background:new"
+ d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+ id="path8189"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7313);enable-background:new"
+ d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+ id="path8191"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7317);enable-background:new"
+ d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+ id="path8193"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7321);enable-background:new"
+ d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+ id="path8195"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7329);enable-background:new"
+ d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+ id="path8197"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7325);enable-background:new"
+ d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+ id="path8199"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path8201"
+ d="m 863.87812,475.6679 c 1.64212,-3.218 3.51781,-5.73529 4.86136,-9.84898 0.79872,-3.65789 3.31204,-2.03073 7.26047,-8.3969 1.40193,-2.2395 5.47653,0.39136 8.9651,-2.39911 1.27072,-0.80319 2.88488,-0.40431 4.48256,-0.0631 3.76539,1.31896 5.82576,3.70355 8.33376,5.80837 6.13906,5.97023 20.53414,7.94327 23.48604,6.31346 1.43405,-2.90474 7.88128,-5.40888 12.37437,-11.11168 0.74811,-1.12267 11.72936,-8.74446 14.64721,-6.56599"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path8203"
+ d="m 888.50059,465.25071 c 7.36341,-3.23297 13.8109,-8.9084 20.70813,-13.38452 3.31057,-1.96954 6.86983,3.21601 10.796,3.59866 2.29773,-0.21813 3.7129,1.20259 5.68211,1.6415 5.15636,1.31779 2.39793,3.86488 9.97526,6.43972 6.15561,1.7204 8.9074,-6.79847 14.89975,-7.3236 4.87739,-0.50299 8.09892,-0.31603 11.61675,-0.25254 3.92696,0.13889 4.07855,-3.4976 6.06092,-5.3033 2.98056,-2.80522 7.15561,-1.84972 10.14485,-4.7409 1.01754,-1.38468 1.95458,-3.01085 2.73459,-5.10809 0.88201,-2.00034 3.04006,0.30598 4.79823,1.26269"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path8994"
+ d="m 403.27922,1056.3058 56.56854,-42.4264 72.12489,14.1421 -46.66904,52.3259 -53.74012,7.0711 -28.28427,-31.1127 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9048);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path4189"
+ d="m 542.27183,1060.5719 c -1.40727,18.8012 -1.1449,32.751 2.08174,49.3033 3.22666,16.5523 16.40609,45.9073 20.33441,63.1837 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1483 -15.31761,12.9774 -42.05128,21.5989 -67.83231,15.7337 -25.78105,-5.8652 -69.54907,-49.2234 -88.59019,-70.2283 -19.11214,-21.0833 -63.76086,-93.8506 -77.93853,-124.2758 -14.17767,-30.4251 -12.65961,-36.7186 -8.11972,-45.52972 -9.36672,-24.5205 -12.41371,-50.06681 -33.71245,-75.57664 30.32547,3.11444 43.88028,26.95633 60.12568,47.13975 -5.52989,-48.07603 -18.05471,-64.4165 -28.37395,-90.7243 29.9943,6.08165 50.57936,31.87239 63.97979,72.7125 9.55415,-3.91791 18.23776,-9.37294 30.18741,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.68725,-101.06994 53.44196,5.67033 83.65702,80.63932 78.97142,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34702 -21.04781,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38966,85.80578 6.10287,20.3689 1.51881,38.70051 1.51881,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24138 -3.53269,59.10328 -4.94582,77.98328 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ id="path4191"
+ d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)"
+ sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+ clip-path="url(#clipPath3677)"
+ id="path4193"
+ d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.84562,77.83981 -43.7404,101.4864 -6.60491,13.1304 -18.52833,57.4859 -31.12335,76.2465 -12.59502,18.7605 -28.53137,39.7673 -37.17204,44.4209 -21.49052,11.5742 -44.55594,25.5059 -60.61889,18.0895 -14.37486,-6.637 -23.03969,-21.1927 -23.81407,-37.7433 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898);enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3622)"
+ id="g3617"
+ style="display:inline;enable-background:new">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024);enable-background:accumulate"
+ d="m -15.66751,843.48852 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+ id="path4195"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020);enable-background:accumulate"
+ d="m 118.70648,859.93048 -55.154328,-46.66904 -43.84062,36.76955 33.94113,53.74011 -13.596814,85.46203 -39.44536579,28.29217 -41.01220021,11.3137 -2.82842,46.669 56.56854,25.4559 18.943987,-69.65 23.45655,-58.85663 46.347541,-72.61491 16.62,-39.91188 z"
+ id="path4197"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)"
+ id="path4199"
+ d="m -70.82184,932.58397 60.81118,-26.87005 100.40916,31.1127 -63.63961,31.11269 -82.02438,-16.97056 -15.55635,-18.38478 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)"
+ clip-path="url(#clipPath4177)"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+ id="path4201"
+ d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -7.17516,44.14234 -8.78421,66.21911 -8.78379,2.34171 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 4.66299,24.40472 3.63165,36.35334 -7.06405,45.03355 -22.14231,87.36194 -35.95355,130.6798 -12.07476,32.9493 -27.3742,58.8525 -47.88808,87.2015 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -44.20676,10.8769 -62.59956,0.046 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 4.93886,-28.5121 4.4106,-43.4918 -0.53824,-15.2629 -2.29135,-30.5647 -6.54261,-46.8663 -4.25126,-16.30162 -9.04325,-24.91794 -16.11906,-41.57338 -7.24111,-17.04456 -15.07015,-36.74863 -18.20542,-56.28842 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4105);enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccc"
+ id="path4203"
+ d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccc"
+ id="path4205"
+ d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8338)"
+ style="display:inline;filter:url(#filter8333);enable-background:new"
+ id="g8317">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+ id="path4209"
+ sodipodi:nodetypes="ccccc"
+ clip-path="none"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8315"
+ width="182"
+ height="177"
+ x="-55"
+ y="757.19519" />
+ </g>
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8359)"
+ style="display:inline;filter:url(#filter8354);enable-background:new"
+ id="g8346">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+ id="path4207"
+ sodipodi:nodetypes="ccccccc"
+ clip-path="none"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8344"
+ width="165"
+ height="176"
+ x="-22"
+ y="696.19519" />
+ </g>
+ <path
+ sodipodi:nodetypes="czzzzzzcccccccccczczz"
+ id="path8848"
+ d="m 1036.164,1071.8338 c 6.7941,18.9028 10.4937,33.2997 11.8903,51.2119 1.3966,17.9123 -3.7827,51.8008 -2.9005,70.6561 0.8818,18.8452 8.1337,40.099 27.3446,48.9689 19.4189,8.9658 49.3193,10.2113 74.1199,-3.1456 24.8006,-13.357 57.401,-70.3255 70.9742,-97.3087 13.6239,-27.0839 38.7611,-114.4974 44.6608,-149.76859 5.8998,-35.27121 2.5506,-41.30077 -4.6174,-49.05549 2.6403,-27.84015 -1.4998,-54.93543 13.1096,-87.18618 -30.249,11.8257 -37.3823,40.1607 -48.3189,65.50508 -8.0009,-50.93293 0.2092,-71.27319 3.3189,-101.21936 -29.0647,14.77791 -42.8615,47.11402 -45,92.85714 -10.9239,-1.3042 -21.3914,-4.43423 -33.5714,-0.71429 -0.264,-46.02334 -1.4635,-76.88941 8.9106,-114.20649 -53.2554,21.02686 -62.9472,106.5941 -56.0535,112.77792 -10.8828,0.535 -21.371,-1.2973 -32.8571,2.85715 0.6389,-42.57135 -0.2605,-84.90861 -30,-122.85715 0,0 -30.958,80.92234 -31.4286,103.57143 -0.4705,22.64909 9.4516,40.16588 9.4516,40.16588 0,0 -8.568,36.74051 -6.2986,58.23223 2.2959,21.74142 20.4429,59.67622 27.2655,78.65812 z"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ id="path3635"
+ d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+ clip-path="url(#clipPath3677)"
+ id="path3669"
+ d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.79272,123.1659 -43.6875,146.8125 -6.60491,13.1304 -18.02998,33.8957 -30.625,52.6563 -12.59502,18.7605 -27.35933,35.5338 -36,40.1874 -21.49052,11.5742 -48.7808,10.2602 -64.84375,2.8438 -14.37486,-6.637 -20.53812,-23.4494 -21.3125,-40 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898);enable-background:new"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3636)"
+ id="g3628">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024);enable-background:accumulate"
+ d="m 824.48651,818.48242 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+ id="path8988"
+ inkscape:connector-curvature="0" />
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020);enable-background:accumulate"
+ d="m 964.49365,855.25197 -55.15433,-46.66904 -43.84062,36.76955 33.94113,53.74011 7.07106,66.46804 -50.91168,35.35537 -41.0122,11.3137 -2.82842,46.669 56.56854,25.4559 63.63961,-76.3676 24.04163,-94.75227 8.48528,-57.98276 z"
+ id="path8990"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path8992"
+ d="m 1045.3322,1043.5779 60.8112,-26.8701 100.4091,31.1127 -63.6396,31.1127 -82.0244,-16.9706 -15.5563,-18.3847 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ clip-path="url(#clipPath4177)"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+ id="path4149"
+ d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -3.2972,44.17323 -4.90625,66.25 -1.31238,1.37679 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 3.12294,24.83149 2.0916,36.78011 -7.06405,45.03355 -21.76553,88.37934 -35.57677,131.69714 -12.07476,32.9493 -30.7197,63.08 -51.23358,91.429 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -43.57595,5.1744 -61.96875,-5.6562 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 2.37211,-27.8008 7.91747,-42.8053 5.54535,-15.0045 2.47105,-31.3317 -1.78021,-47.6333 -4.25126,-16.3016 -12.17903,-26.26002 -21.82158,-42.20417 -9.64255,-15.94415 -17.6369,-36.03734 -20.77217,-55.57713 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4185);enable-background:new"
+ transform="translate(450.03125,73.843964)"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccc"
+ id="path3902"
+ d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(276,136)"
+ clip-path="url(#clipPath3631)"
+ sodipodi:nodetypes="cccccccc"
+ id="path4135"
+ d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141);enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8392)"
+ style="filter:url(#filter8379)"
+ id="g8367">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+ id="path4145"
+ sodipodi:nodetypes="ccccccc"
+ clip-path="none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8365"
+ width="123.03658"
+ height="172.53406"
+ x="877.51953"
+ y="650.19098" />
+ </g>
+ <g
+ transform="translate(276,136)"
+ clip-path="url(#clipPath8417)"
+ style="filter:url(#filter8404)"
+ id="g8400">
+ <path
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+ id="path4147"
+ sodipodi:nodetypes="ccccc"
+ clip-path="none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="rect8398"
+ width="142.12846"
+ height="125.1579"
+ x="924.89569"
+ y="677.06104" />
+ </g>
+ </g>
+ <rect
+ id="rect6247"
+ width="440"
+ height="376"
+ x="548"
+ y="205.32275"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#f83615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6676"
+ width="1684"
+ height="1292"
+ x="56"
+ y="53.322754" />
+ <rect
+ style="opacity:1;fill:url(#pattern5557);fill-opacity:1;stroke:#f815bb;stroke-width:13.34657478;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6731"
+ width="522.56604"
+ height="1182.4679"
+ x="3493.3721"
+ y="87.178711" />
+ <g
+ id="g7477"
+ transform="matrix(0.53474256,0,0,1,1882.7509,3.0962157)">
+ <rect
+ y="99.705269"
+ x="3039.4895"
+ height="902.66437"
+ width="818.51605"
+ id="rect6979"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <g
+ clip-path="url(#clipPath6975)"
+ id="g4303-9"
+ style="display:inline;enable-background:new"
+ transform="matrix(1.8806916,0,0,2.3994874,1997.8763,-394.32602)">
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter11361-3);enable-background:new"
+ d="m 304.64285,526.6479 c -10,0.35715 -18.21428,2.85714 -18.21428,2.85714 l 7.5,6.07143 10.35714,3.57143 16.07143,0.35714 22.5,-5.35714 7.85714,1.07143 20.35715,-2.14286 -10.35715,6.78572 c 5.45923,-1.02361 17.39329,3.56911 9.64286,5.35714 -1.74,0.40142 13.92857,-4.64285 13.92857,-4.64285 l 2.5,-4.64287 3.57143,-9.28571 11.42857,0 18.21428,-4.64286 3.57144,-4.99999 -16.07144,1.07142 -12.14285,2.14286 -14.64286,-5 -70.6921,16.70774 -5.37933,-5.27917 z"
+ id="path10326-6"
+ sodipodi:nodetypes="cccccccccsccccccccccc"
+ transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
+ inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
+ inkscape:export-xdpi="142.10527"
+ inkscape:export-ydpi="142.10527" />
+ <g
+ style="display:inline;opacity:1;enable-background:new"
+ id="g7882-9"
+ transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzzcc"
+ id="path7876-3"
+ d="m 245.12255,100.05344 c 0,0 -47.12811,-31.646921 -67.21465,-35.800939 -20.03792,-4.143963 -38.4729,-3.317578 -51.93364,13.607323 -13.46074,16.924901 -12.07739,61.265196 -13.53554,86.969546 -1.45815,25.70435 2.54945,70.17701 17.6046,88.66552 15.05516,18.4885 45.88634,13.58502 49.92695,21.4137 2.21283,4.28736 65.15228,-174.85515 65.15228,-174.85515 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7904-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzzzc"
+ id="path7878-3"
+ d="m 135.37935,82.017807 c 0,0 26.34355,1.938783 37.63307,13.903188 11.41494,12.097335 13.73457,21.331515 15.29586,37.734585 1.56337,16.42499 -0.84957,28.41812 -7.81382,36.03734 -6.96425,7.61922 -1.00429,19.58332 -25.91605,12.07107 -24.91176,-7.51225 -27.03224,-27.78298 -26.51523,-46.30475 0.51721,-18.52898 7.31617,-53.441433 7.31617,-53.441433 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7906-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czccssc"
+ id="path7880-8"
+ d="m 135.648,81.927211 c 0,0 -4.64465,16.365075 0.58825,28.563099 5.48794,12.79254 27.22425,44.26007 27.22425,54.65565 l 22.65625,-5 c 2.54218,-6.96644 3.21052,-15.75206 2.1875,-26.5 -1.56129,-16.40307 -3.8663,-25.62141 -15.28125,-37.718749 -9.65488,-10.232047 -31.59311,-13.374857 -37.375,-14 z"
+ style="display:inline;opacity:1;fill:url(#radialGradient7908-0);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 845.03125,1154.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.2857 c 0,0 85.88551,-16.2009 112.14285,-33.5714 26.25735,-17.3705 45.58238,-49.66602 59.28572,-71.42861 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+ id="path7917-0"
+ sodipodi:nodetypes="czzzcczzcc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8888-6);enable-background:accumulate"
+ d="m 332.34019,898.38549 -32.73181,-61.29956 -37.61734,45.10646 c 2.17675,1.31711 5.77425,-20.85603 45.6004,-64.41708 l 24.74875,80.61018 z"
+ id="path7919-5"
+ clip-path="url(#clipPath8658-06)"
+ sodipodi:nodetypes="ccccc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6951);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8892-7);enable-background:accumulate"
+ d="m 200.81833,863.03015 146.3711,-51.61879 243.95184,226.27414 -241.83052,140.0072 -181.01934,-87.6813 32.52692,-226.98125 z"
+ id="path7923-6"
+ clip-path="url(#clipPath2833-2)"
+ sodipodi:nodetypes="cccccc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 642.88839,640.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57145 -62.5,123.57145 l 76.07143,18.2143 c 0,0 11.80712,-12.8234 31.07142,-46.07146 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+ id="path7921-6"
+ sodipodi:nodetypes="czzcczcc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8856-2);enable-background:accumulate"
+ d="m 430.28131,381.94122 c -7.07106,2.82843 -236.18124,32.15181 -236.18124,32.15181 l -39.63961,359.83304 90.19849,92.63961 52.3259,-114.5513 100.46804,-186.39192 32.82842,-183.68124 z"
+ id="path7925-4"
+ sodipodi:nodetypes="ccccccc"
+ clip-path="url(#clipPath3665-9)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 969.67051,1164.0346 c 0,0 23.25628,11.3937 36.06779,20.4761 12.6974,9.0015 29.4724,24.6491 41.6924,37.3605 12.3055,12.8002 20.1127,22.5987 41.5327,24.1608 21.4322,1.5629 53.2824,-8.7876 73.296,-24.6642 20.0135,-15.8766 45.6469,-69.2328 45.6469,-69.2328 l -127.1608,-143.0717"
+ id="path7927-0"
+ sodipodi:nodetypes="czzzzcc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8860-3);enable-background:accumulate"
+ d="M 331.34019,641.50471 216.17367,835.36467 260.2153,925.96265 357.79603,732.21539 331.34019,641.50471 Z"
+ id="path7929-0"
+ clip-path="url(#clipPath8642-9)"
+ sodipodi:nodetypes="ccccc"
+ transform="translate(276,136)" />
+ <g
+ style="display:inline;opacity:1;enable-background:new"
+ id="g7931-4"
+ transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+ inkscape:transform-center-x="-347.89063"
+ inkscape:transform-center-y="-28.255779">
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+ id="path7933-6" />
+ <g
+ clip-path="url(#clipPath7616-1)"
+ style="display:inline;filter:url(#filter7610-9);enable-background:new"
+ id="g7935-2"
+ transform="matrix(0.9975712,-0.06965428,0.06965428,0.9975712,872.72062,140.02502)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
+ id="path7937-6"
+ d="m 229.94262,-409.12268 c -3.55781,0.05 -9.0242,0.36009 -10.30334,0.90414 -1.60609,-0.44747 -3.90316,-0.88131 -5.89995,-0.87674 -3.07199,0.007 -4.96469,0.009 -6.90727,0 -0.66047,-0.003 -1.04759,0.0672 -1.35267,0.10959 0,0 0,1.09593 0,1.09593 0.11972,-0.17947 0.39252,-0.69046 0.94975,-0.76715 0.74758,-0.10289 5.16928,-0.15123 7.31019,-0.1096 1.7746,0.0345 4.45523,0.27427 6.38921,0.95895 0.3214,0.11378 0.61925,0.27378 0.89219,0.41097 1.96342,0.98693 7.94336,4.30154 7.94336,4.30154 0,0 -6.63275,-3.94768 -7.48287,-4.43853 -0.20331,-0.11739 -0.57464,-0.25769 -1.03609,-0.41098 1.22063,-0.44779 5.07597,-0.61971 7.82823,-0.71235 3.0245,-0.10182 3.34776,-0.0896 5.41069,0.19179 2.12931,0.29043 3.33851,0.60276 3.33851,0.60276 -1e-5,0 -0.0784,-0.64118 1.03609,-0.79455 0.74757,-0.10289 5.16929,-0.15123 7.31019,-0.1096 2.0695,0.0403 5.36605,0.40716 7.2814,1.36992 1.00332,0.50433 3.03564,1.56863 4.79535,2.53571 l 0.0956,-0.0194 c 0,0 -3.58034,-2.16242 -4.43047,-2.65327 -0.20331,-0.11739 -0.57463,-0.25769 -1.03609,-0.41098 1.22062,-0.44779 5.04719,-0.61971 7.79945,-0.71235 3.0245,-0.10182 3.34775,-0.0896 5.41069,0.19179 1.95316,0.2664 3.01292,0.53006 3.19461,0.57536 0,0 -0.0271,-0.31146 -0.0271,-0.31146 -0.40903,-0.13645 -0.71424,-0.23335 -1.40038,-0.35748 -1.30081,-0.23533 -3.39912,-0.60156 -5.50857,-0.56398 -3.57195,0.0636 -9.05328,0.35596 -10.30334,0.90414 -1.60583,-0.44695 -3.87662,-0.8813 -5.87117,-0.87674 -3.07199,0.007 -4.99348,0.009 -6.93605,0 -1.94256,-0.009 -1.71268,0.27907 -2.93558,0.27398 -1.32191,-0.005 -1.76612,-0.35463 -5.55459,-0.30138 0,0 0,0 0,0"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path7939-7"
+ d="m 206.1989,-407.47878 c 1.92021,0.81706 4.57715,2.19283 6.15897,3.39739 1.58184,1.20456 2.90757,1.77368 5.55459,3.91795 0.88557,0.71738 1.74865,1.34985 2.59193,1.92174 l 0.54057,-0.19011 c -0.71323,-0.48339 -1.46776,-1.02031 -2.26909,-1.62203 -2.82223,-2.11921 -3.62655,-2.80973 -6.01507,-4.27414 -2.38854,-1.4644 -4.09948,-2.36576 -6.5619,-3.1508 0,0 0,0 0,0"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ sodipodi:nodetypes="cssccsscc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path7941-5"
+ d="m 237.79963,-407.47878 c 1.92021,0.81706 4.60594,2.19283 6.18775,3.39739 0.81307,0.61916 1.55849,1.07042 2.45046,1.65401 l 0.649,-0.11666 c -0.79831,-0.57637 -1.57177,-1.09435 -2.69653,-1.78394 -2.38854,-1.4644 -4.12826,-2.36576 -6.59068,-3.1508 0,0 0,0 0,0"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ sodipodi:nodetypes="csccscc" />
+ </g>
+ <g
+ clip-path="url(#clipPath7606-1)"
+ id="g7943-6">
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7578-4);enable-background:new"
+ d="m 1056.25,-278.80481 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+ id="path7945-9"
+ sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7594-8);enable-background:new"
+ d="m 1058.5,-275.42981 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+ id="path7947-8"
+ sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 628.24553,347.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.29583 116.94091,-84.69468 185.93466,-91.46542 86.92239,-11.0168 184.91267,17.94007 233.37138,95.40128 54.124,75.7333 56.6747,172.53912 80.612,259.52795 29.4378,127.1276 54.7791,256.21414 60.3922,386.85035 -3.0634,78.18185 -8.4263,165.18417 -60.5032,228.13417 -48.0265,50.3574 -122.7864,50.053 -187.06985,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94 -95.73019,-113.47867 -97.2794,-186.01962 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+ id="path7949-7"
+ sodipodi:nodetypes="cscccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8940-3);enable-background:accumulate"
+ d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 -38.61152,-142.95988 -39.24264,-189.11984 -0.63145,-46.18445 10.83034,-108.60786 30.67767,-158.29647 20.04835,-50.19188 36.89674,-44.84642 42.12489,-92.59293 5.22815,-47.74651 -17.4264,-149.39192 -17.4264,-149.39192 l -55.86144,39.59798 z"
+ id="path7951-2"
+ sodipodi:nodetypes="ccccczzzcc"
+ clip-path="url(#clipPath8616-5)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6953);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 1010.0312,655.49186 c 0,0 16.7552,37.01806 28.7015,53.95395 11.9462,16.93589 52.7271,56.04605 52.7271,56.04605 l 52.5972,-127.58975"
+ id="path7953-8"
+ sodipodi:nodetypes="czcc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8822-2);enable-background:accumulate"
+ d="m 730.31998,536.56864 c 0,8.48528 42.54774,58.46803 42.54774,58.46803 l 12.60659,-28.76954 -55.15433,-29.69849 z"
+ id="path7955-2"
+ sodipodi:nodetypes="cccc"
+ clip-path="url(#clipPath8209-6)"
+ transform="translate(276,136)" />
+ <g
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;opacity:1;enable-background:new"
+ id="g7957-9"
+ clip-path="url(#clipPath3998-6)">
+ <g
+ transform="translate(-174.03125,62.156036)"
+ style="filter:url(#filter3677-5)"
+ id="g7959-9">
+ <g
+ id="g7961-6"
+ style="filter:url(#filter3785-4)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzzzzzzzz"
+ id="path7963-0"
+ d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <rect
+ y="412.60312"
+ x="343.6539"
+ height="181.01935"
+ width="381.83765"
+ id="rect7965-2"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <g
+ id="g7967-7"
+ style="filter:url(#filter3785-4)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzcc"
+ id="path7969-6"
+ d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ transform="translate(174.03125,-62.156036)" />
+ <rect
+ y="344.82138"
+ x="702.86414"
+ height="162.63455"
+ width="207.8894"
+ id="rect7971-1"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ transform="translate(-174.03125,62.156036)"
+ style="display:inline;opacity:0.18000004;enable-background:new"
+ id="g7973-3">
+ <g
+ id="g7975-2"
+ style="filter:url(#filter3785-4)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzzzzzzzz"
+ id="path7977-1"
+ d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <rect
+ y="412.60312"
+ x="343.6539"
+ height="181.01935"
+ width="381.83765"
+ id="rect7979-5"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <g
+ id="g7981-9"
+ style="filter:url(#filter3785-4)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzcc"
+ id="path7983-9"
+ d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ transform="translate(174.03125,-62.156036)" />
+ <rect
+ y="344.82138"
+ x="702.86414"
+ height="162.63455"
+ width="207.8894"
+ id="rect7985-1"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8802-7);enable-background:accumulate"
+ d="M 582.65599,-7.4183011 695.79307,78.848726 804.68752,337.64981 842.87128,545.5392 963.07944,637.46308 c 0,0 -12.72793,-287.08535 -19.799,-313.95541 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 Z"
+ id="path7987-4"
+ clip-path="url(#clipPath8604-69)"
+ sodipodi:nodetypes="cccccscc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6955);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 964.13839,239.599 c 0,0 8.67732,10.89662 24.10715,11.96428 15.42986,1.06766 49.72166,-39.95267 70.17856,-52.14285 20.4793,-12.20353 47.0464,-26.60225 63.9286,-20.35714 16.8821,6.2451 22.1578,26.43609 27.8571,48.03571 5.6994,21.59961 6.7186,61.81389 -2.6785,92.85715 -9.3972,31.04325 -50.5033,73.10375 -65.3572,103.39285 -14.8539,30.2891 -11.6071,39.82143 -11.6071,39.82143"
+ id="path7989-9"
+ sodipodi:nodetypes="czzzzzzc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:url(#radialGradient3315-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1124.4955,207.63471 c -15.8928,-0.89286 -49.7188,12.10583 -66.0714,24.28572 -16.4386,12.2439 -29.2209,24.1144 -29.2857,52.14285 -0.065,28.20604 13.1191,39.07641 29.1071,46.96429 15.988,7.88789 33.6862,7.11928 51.9643,-11.78571 18.2782,-18.905 14.2857,-111.60715 14.2857,-111.60715 z"
+ id="path7991-1"
+ sodipodi:nodetypes="czzzzc" />
+ <ellipse
+ ry="73.928574"
+ rx="86.428574"
+ cy="237.00504"
+ cx="385"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient3543-4);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4120-7);enable-background:accumulate"
+ id="path7993-0"
+ transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
+ clip-path="url(#clipPath4100-3)" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3915-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 527.60588,407.44884 c 0,0 -122.04144,38.40348 -187.51434,9.63181 -65.47289,-28.77166 -74.37725,-124.71847 -74.37725,-124.71847 0,0 73.38158,-80.50393 129.92078,-83.61476 55.82705,-3.07164 90.57386,20.14332 114.87001,65.85171 24.352,45.81348 17.1008,132.84971 17.1008,132.84971 z"
+ id="path7995-7"
+ sodipodi:nodetypes="csczzc"
+ mask="url(#mask3684-3)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6957);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 772.17411,393.349 c 0,0 36.21754,-27.38247 51.60714,-35.89286 15.17734,-8.39301 25.71428,-11.60714 35.89285,-11.60714 l -15.53571,66.96428"
+ id="path7997-5"
+ sodipodi:nodetypes="czcc" />
+ <circle
+ r="36.25"
+ cy="306.64789"
+ cx="409.28571"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3933-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path7999-8"
+ transform="translate(449.49554,74.915393)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8806-6);enable-background:accumulate"
+ d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 8.68161,-72.36764 -31.24264,-223.11984 l 17.67767,-69.29647 72.12489,-138.59293 -42.4264,-158.39192 -55.86144,39.59798 z"
+ id="path8001-7"
+ sodipodi:nodetypes="cccccccccc"
+ clip-path="url(#clipPath8616-5)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8826-9);enable-background:accumulate"
+ d="m 635.21025,581.13004 c -14.14214,12.72792 39.23347,34.58015 76.36753,24.04163 37.13406,-10.53852 104.64487,-35.56437 103.23759,-79.19596 -1.40728,-43.63158 -76.36753,-128.69343 -76.36753,-128.69343 L 635.21025,581.13004 Z"
+ id="path8003-0"
+ sodipodi:nodetypes="czzcc" />
+ <circle
+ r="23.214285"
+ cy="306.64789"
+ cx="410"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3991-0);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8005-4"
+ transform="translate(449.67411,74.915393)" />
+ <circle
+ r="7.5"
+ cy="303.07648"
+ cx="414.28571"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3981-7);enable-background:accumulate"
+ id="path8007-8"
+ transform="translate(451.99554,73.486821)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4112-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 789.31696,478.349 c 0,0 7.02281,19.56859 -1.07143,35 -8.09424,15.43141 -42.32317,38.98822 -67.49999,50 -25.30972,11.06991 -85.473,32.96393 -101.78572,41.96428 -16.46148,9.08243 -18.21428,12.67857 -18.21428,12.67857 0,0 -7.14693,-19.06441 28.74999,-51.7857 36.17211,-32.97214 142.02712,-48.0495 159.82143,-87.85715 z"
+ id="path8009-0"
+ sodipodi:nodetypes="czzzczc" />
+ <g
+ style="display:inline;opacity:1;enable-background:new"
+ id="g8011-4"
+ transform="translate(780.74553,74.55825)">
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(-329.81481,0)"
+ clip-path="url(#clipPath3999-0)"
+ sodipodi:nodetypes="czzczzzszc"
+ id="path8013-2"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+ style="display:inline;opacity:1;fill:url(#radialGradient3585-2);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <ellipse
+ ry="134.00607"
+ rx="64.715881"
+ cy="338.07648"
+ cx="183.57143"
+ transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
+ id="path8015-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4060-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <ellipse
+ ry="134.00607"
+ rx="64.715881"
+ cy="338.07648"
+ cx="183.57143"
+ transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
+ id="path8017-6"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4062-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(-329.81481,3e-7)"
+ clip-path="url(#clipPath3999-0)"
+ sodipodi:nodetypes="czzczzzszc"
+ id="path8019-1"
+ d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6959);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4079-1);enable-background:new" />
+ </g>
+ <circle
+ r="19.704132"
+ cy="398.07648"
+ cx="310.71429"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8021-0"
+ transform="translate(452.55663,72.581273)" />
+ <circle
+ r="19.704132"
+ cy="398.07648"
+ cx="310.71429"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4056-5);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6961);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4083-9);enable-background:accumulate"
+ id="path8023-4"
+ transform="translate(450.55663,72.581273)" />
+ <circle
+ r="19.704132"
+ cy="398.07648"
+ cx="310.71429"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4119-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ id="path8025-2"
+ transform="translate(450.55663,72.581273)" />
+ <ellipse
+ ry="44.547726"
+ rx="72.079735"
+ cy="377.42877"
+ cx="429.56738"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4868-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4002-6);enable-background:accumulate"
+ id="path8027-2"
+ transform="matrix(0.9969564,-0.07796167,0.07796167,0.9969564,436.61877,125.29509)"
+ inkscape:transform-center-x="-47.231976"
+ inkscape:transform-center-y="-3.6935079" />
+ <ellipse
+ ry="22.627417"
+ rx="36.611931"
+ cy="391.21735"
+ cx="437.6991"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4876-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4010-1);enable-background:accumulate"
+ id="path8029-2"
+ transform="matrix(1.4357951,-0.06999104,0.06999104,1.4357951,235.18065,-63.86546)"
+ inkscape:transform-center-x="-20.955902"
+ inkscape:transform-center-y="-13.056625" />
+ <g
+ transform="translate(450.03125,73.843964)"
+ id="g8031-0"
+ style="display:inline;opacity:1;filter:url(#filter4053-9);enable-background:new">
+ <circle
+ r="3.2142856"
+ cy="401.82648"
+ cx="413.66071"
+ id="path8033-5"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6963);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <circle
+ r="3.2142856"
+ cy="401.82648"
+ cx="413.66071"
+ transform="translate(13.125009,8.1249913)"
+ id="path8035-5"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6965);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <circle
+ r="3.2142856"
+ cy="401.82648"
+ cx="413.66071"
+ transform="translate(32.946437,7.4999913)"
+ id="path8037-2"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6967);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <circle
+ r="3.2142856"
+ cy="401.82648"
+ cx="413.66071"
+ transform="translate(24.910723,-10.267866)"
+ id="path8039-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6969);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <circle
+ r="3.2142856"
+ cy="401.82648"
+ cx="413.66071"
+ transform="translate(47.589294,-0.6250087)"
+ id="path8041-0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6971);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 896.20301,482.92837 c 0.98509,4.35008 4.53707,6.17948 7.38673,7.89182 4.46068,2.51292 6.52016,1.52211 9.15451,-0.75761 1.60195,-1.92117 10.68311,-4.69865 15.59423,-7.07107 4.32961,-1.45891 8.9033,-5.35873 13.38452,-8.33376 3.39514,-1.62724 5.34664,0.35464 7.82868,1.01015 2.94412,0.71661 4.41117,2.17175 6.06092,3.53554 2.39616,1.17519 -0.9279,3.14313 3.283,4.29314 1.19091,0.21794 2.41695,0.57645 3.28299,-0.50507"
+ id="path8043-2"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 910.85021,475.35223 c 2.31494,-0.032 3.17778,0.64253 5.49271,-0.82075 3.45564,-3.08113 5.40254,-3.14477 7.95495,-4.41942 3.02657,-1.31523 6.5357,8.15169 10.10153,9.84899 2.39509,-0.82142 1.28914,1.79379 1.45209,2.65165 0.0571,2.64684 2.80694,3.67806 4.35628,5.42957 3.31604,2.25549 7.37523,6.29546 11.11168,5.3033 6.44525,-2.93107 10.27922,-1.28146 16.28871,-7.38674 0.70405,-1.18134 -0.58425,-6.8946 3.09359,-7.19734 2.52399,0.25338 4.16667,0.0502 6.06092,0.56822 5.441,2.11719 7.73778,6.45 14.71034,7.95495 6.1829,0.96639 7.61264,3.79426 13.88959,5.05076"
+ id="path8045-8"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 876.98133,483.52197 c 2.39858,-0.7938 6.10613,4.1921 8.17313,7.04568 0.59281,2.67952 1.15377,5.48645 0.75761,12.12183 0.78513,2.41754 2.68049,3.03095 4.79823,3.283 3.11745,-0.53678 5.87669,-1.3243 7.3236,-3.03046 1.8716,-1.94167 5.31253,2.39394 8.08122,4.04061 3.61009,1.91209 7.77378,1.97886 11.8693,2.27284 1.70358,-0.23064 2.3704,4.51515 3.28299,8.08123 0.38414,4.37806 -0.88544,6.89569 -1.76776,9.84898 -0.2943,2.49655 2.9885,3.52974 6.31345,4.54569 3.18244,0.74124 6.54424,1.66184 9.09137,1.76777 5.14186,0.87491 8.08874,2.69052 12.12183,4.04061 2.23914,0.81655 3.26019,2.24216 4.54569,3.53553"
+ id="path8047-3"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter8814-5);enable-background:new"
+ d="m 332,187.69519 c 0,0 57.5,-25.5 57.5,-28 0,-2.5 5.5,-52 5.5,-52 0,0 91,-48.500001 91.5,-50.500001 0.5,-2 86,-62.0000004 86,-62.0000004 L 386.5,17.195189 311,123.19519 l 21,64.5 z"
+ id="path8049-8"
+ clip-path="url(#clipPath8514-8)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 1697.2846,722.5514 c 0,0 -115.9655,73.5391 -123.0365,77.78174 -7.0711,4.24264 -230.5169,137.17872 -230.5169,137.17872 l 4.2427,39.59798 216.3747,-100.40917 117.3797,-101.82337 15.5563,-52.3259 z"
+ id="path8051-0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810-3);enable-background:accumulate"
+ d="m 528.91587,556.85291 c -5.65685,-1.41421 -181.01933,74.95332 -181.01933,74.95332 l -33.94113,181.01934 51.09546,193.94823 257.2031,67.6813 c 0,0 206.47518,152.735 212.13203,148.4924 5.65686,-4.2426 168.2914,-193.7473 168.2914,-193.7473 L 842.87128,845.35248 796.20224,667.16157 528.91587,556.85291 Z"
+ id="path8053-4"
+ clip-path="url(#clipPath8610-9)"
+ sodipodi:nodetypes="cccccscccc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1097.6433,613.88997 c 0,0 22.6195,-6.50681 35.7427,-5.87273 13.1233,0.63409 30.6416,1.93862 43.7089,12.18619 13.0673,10.24756 25.0677,27.14007 34.1124,58.36965 9.0446,31.22958 1.6983,99.25201 -6.1761,143.34735 -7.8743,44.09534 -28.2651,106.11298 -45,140 -16.7348,33.88702 -49.7977,77.49517 -60.5694,89.87617 -11.3642,13.062 -56.2059,36.4262 -79.4306,42.2667 5.3034,-10.6066 48.8998,-50.5889 35,-60.7143 -14.0189,-10.2123 -45.76,45.9824 -84.2931,29.0332 21.38231,-13.1321 41.7794,-51.1861 34.0406,-66.59448 -7.84024,-15.61039 -30.70492,48.75758 -93.53553,37.01288 30.05204,-27.5267 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.2932 -60.46175,54.2932 0,0 -2.8219,-41.70123 13.7732,-68.60737 16.63935,-26.97787 79.65297,-81.61527 99.55308,-111.70342 19.9002,-30.08814 33.6126,-66.00902 42.1355,-92.51794 8.5228,-26.50892 15.8009,-77.09954 15.8009,-77.09954"
+ id="path8055-0"
+ sodipodi:nodetypes="czzzzzzczczczczzzc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8818-1);enable-background:accumulate"
+ d="m 770.74639,609.17881 -50.91169,97.58074 -79.90307,111.01576 34.64824,71.41778 42.42641,79.19597 72.12489,-45.25484 14.14214,-192.33305 21.2132,-138.59292 -14.14214,-90.15612 -39.59798,107.12668 z"
+ id="path8057-9"
+ clip-path="url(#clipPath8622-5)"
+ sodipodi:nodetypes="cccccccccc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810-3);enable-background:accumulate"
+ d="m 295,846.19519 6.64488,-68.92285 c 0,0 90.31951,89.00457 162.35512,122.92285 72.03561,33.91828 308,62 308,62 l 154,-26 -36,162.00001 -286,26 -298,-89 -11,-189.00001 z"
+ id="path8059-1"
+ clip-path="url(#clipPath8906-9)"
+ sodipodi:nodetypes="cczcccccc"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3587-1);enable-background:new"
+ d="m 405.79629,845.99023 74.95332,65.05383 2.49963,16.8804 19.40336,10.15891 6.49204,23.05109 31.70905,-8.3711 14.84924,48.08324 c 12.25652,12.7279 89.79344,-113.1097 55.86143,38.1838 l -60.81118,16.2635 -89.20292,-94.69286 -62.82503,-53.79963 7.07106,-60.81118 z"
+ id="path8061-9"
+ sodipodi:nodetypes="cccccccccccc"
+ clip-path="url(#clipPath3602-4)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+ d="m 1159.317,918.349 c 54.2857,-1.42857 126.035,-15.05199 170,-26.78572 44.0527,-11.75714 125.8863,-36.34724 175.357,-57.85714 49.3393,-21.45272 113.6038,-59.2816 154.2859,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7142,-33.57143 8.3691,22.36779 -16.4069,56.32562 -37.8571,81.07143 -21.6042,24.9234 -52.7314,52.70533 -98.9287,89.28571 -46.1973,36.58038 -156.0825,101.58463 -212.8571,128.5714 -57.066,27.1254 -128.2033,58.2385 -172.1428,72.5001 -43.9395,14.2616 -131.4286,31.0714 -131.4286,31.0714 L 1159.317,918.349 Z"
+ id="path8063-6"
+ sodipodi:nodetypes="czzzzzzzzcc" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#linearGradient6973);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3779-4);enable-background:accumulate"
+ d="m 1241.5965,652.95007 c 0,0 -64.7215,54.33706 -145.6639,98.99494 -82.0244,45.25484 -284.25704,93.3381 -284.25704,93.3381 0,0 -15.10137,21.05196 45.25489,28.28428 60.35626,7.23232 224.08195,-53.30069 278.60015,-96.16654 54.5182,-42.86585 120.2081,-111.72286 120.2081,-111.72286 l -14.1422,-12.72792 z"
+ id="path8065-2"
+ sodipodi:nodetypes="czczzcc"
+ clip-path="url(#clipPath3992-4)" />
+ <g
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;opacity:1;enable-background:new"
+ id="g8067-5"
+ clip-path="url(#clipPath3986-7)">
+ <g
+ transform="translate(-174.03125,62.156036)"
+ style="filter:url(#filter3677-5)"
+ id="g8069-4">
+ <g
+ style="filter:url(#filter3785-4)"
+ id="g8071-4">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzccccc"
+ id="path8073-9"
+ d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ transform="translate(174.03125,-62.156036)" />
+ <rect
+ y="486.14224"
+ x="1197.8389"
+ height="309.71277"
+ width="333.75412"
+ id="rect8075-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ transform="translate(-174.03125,62.156036)"
+ style="display:inline;opacity:0.18000004;enable-background:new"
+ id="g8077-3">
+ <g
+ style="filter:url(#filter3785-4)"
+ id="g8079-6">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzccccc"
+ id="path8081-0"
+ d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+ style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ transform="translate(174.03125,-62.156036)" />
+ <rect
+ y="486.14224"
+ x="1197.8389"
+ height="309.71277"
+ width="333.75412"
+ id="rect8083-5"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter8225-7);enable-background:accumulate"
+ d="m 1264.1875,605 c -4.4911,0.73268 -8.157,3.45509 -11.9375,6.40625 -10.0813,7.86976 -28.1695,34.42524 -48.0312,50.46875 -39.8674,32.20316 -103.996,69.97701 -152.5626,91.09375 -48.614,21.13738 -130.54122,45.81801 -174.31245,57.5 -43.39821,11.58246 -115.04403,25.13107 -168.25,26.53125 l -4.5625,0.125 -2,4.125 -92.84375,192.125 -6.5,13.4688 14.65625,-2.8438 c 0,0 87.26968,-16.6514 132.34375,-31.2812 44.7252,-14.51667 115.79086,-45.66683 173.03125,-72.87505 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 c 46.3608,-36.70982 77.8049,-64.71682 99.9375,-90.25 10.9011,-12.576 22.7448,-27.53144 31.0313,-42.75 8.2864,-15.21856 19.1597,-44.21808 13.6874,-58.84375 -1.2177,-3.25474 -2.5514,-6.0613 -4.5937,-8.5 -2.0423,-2.4387 -8.4747,-1.57199 -8.5625,-5.03125 -0.2098,-8.26482 -3.3155,-0.24423 -4.8125,0 z m 2.1563,15.21875 c 0.4148,0.58574 1.0311,1.55766 1.7812,3.5625 2.8968,7.74213 -1.4407,31.89875 -8.8125,45.4375 -7.3718,13.53875 -22.6384,28.92394 -33.1875,41.09375 -21.0754,24.31356 -51.9037,51.86156 -97.9375,88.3125 -45.0496,35.67159 -155.46033,101.09459 -211.40625,127.6875 -56.89173,27.04249 -128.09616,58.1184 -171.25,72.125 -36.36491,11.8031 -95.84471,23.8338 -115.71875,27.7813 L 714.09375,851.75 c 54.70691,-2.0493 123.79259,-15.21635 167.125,-26.78125 44.33422,-11.83225 126.07865,-36.33633 176.40625,-58.21875 50.112,-21.78871 112.5344,-61.16816 154.0312,-94.6875 20.6464,-16.67721 41.7449,-42.54588 49.8126,-48.84375 2.437,-1.90242 4.0806,-2.6358 4.875,-3 z"
+ id="path8085-0"
+ clip-path="url(#clipPath3722-3)"
+ sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc" />
+ <g
+ style="display:inline;opacity:1;enable-background:new"
+ id="g8087-2"
+ mask="url(#mask7704-9)"
+ transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+ inkscape:transform-center-x="-185.09603"
+ inkscape:transform-center-y="-12.859654">
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(0.08004571,-0.03125)"
+ style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 -12.4759,3.49189 7.92966,19.27772 c -0.59163,1.97357 12.54624,-4.73836 12.54624,-4.73836 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+ id="path8089-9"
+ sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc" />
+ <g
+ clip-path="url(#clipPath7421-7)"
+ id="g8091-4">
+ <path
+ inkscape:connector-curvature="0"
+ id="path8093-3"
+ d="m 1107.409,-284.04961 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88717,-0.50701 -5.875,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0725 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0774 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,10e-6 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 10e-6,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0532 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 10e-6,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0728,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 10e-6,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0773,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.4497,-0.12571 6.375,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -10e-5,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -1e-4,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7001-5);enable-background:new"
+ sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8095-5"
+ d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6949-4);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8097-1"
+ d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6961-8);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8099-7"
+ d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6957-9);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8101-4"
+ d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.4428,3.93956 1.5794,5.38995 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.9442,0.42864 -1.2366,0.49452 0.531,0.18589 0.8908,0.21322 0.9524,1.05768 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.9524,0.18199 -1.288,0.0511 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6997-5);enable-background:new"
+ sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8103-3"
+ d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6953-8);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8105-1"
+ d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6993-3);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8107-4"
+ d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6989-8);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8109-6"
+ d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6985-6);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8111-9"
+ d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6965-3);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8113-4"
+ d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6981-3);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8115-2"
+ d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6977-6);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8117-2"
+ d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6973-4);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8119-6"
+ d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+ style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6969-8);enable-background:new" />
+ <g
+ id="g8121-4"
+ style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345-9)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8123-1"
+ d="m 744.9375,-212.11731 c 0,0 7.22229,-3.22318 9.0625,-3.5 1.84021,-0.27682 3.35225,-0.003 6,0.5625 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 5.3125,3.5625 5.3125,3.5625 0,0 -7.14644,-2.78019 -10.1875,-3.5625 -3.04106,-0.78231 -7.64461,-2.08374 -10.375,-2.3125 -2.73039,-0.22876 -11,1.875 -11,1.875 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8125-2"
+ d="m 735.46875,-206.95416 c 0,0 3.65979,-2.22318 5.5,-2.5 1.84021,-0.27682 3.66475,0.24677 6.3125,0.8125 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 6.5625,2.125 6.5625,2.125 0,0 -8.39644,-1.34269 -11.4375,-2.125 -3.04106,-0.78231 -7.95711,-2.33374 -10.6875,-2.5625 -2.73039,-0.22876 -7.4375,0.875 -7.4375,0.875 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8127-8"
+ d="m 759.85042,-217.61116 c 0,0 8.5437,-3.29857 10.39778,-3.45786 1.85409,-0.1593 3.64166,0.4792 6.2481,1.21208 2.60644,0.73288 8.57724,2.76594 10.95036,4.07925 2.37312,1.31331 6.41417,2.53782 6.41417,2.53782 0,0 -8.29413,-1.87365 -11.27931,-2.84767 -2.98519,-0.97402 -7.79269,-2.83478 -10.50302,-3.23662 -2.71033,-0.40184 -12.22808,1.713 -12.22808,1.713 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8129-8"
+ d="m 775.19813,-223.2266 c 0,0 7.77133,-2.78244 9.62831,-2.90349 1.85697,-0.12104 3.631,0.55417 6.22178,1.34062 2.59077,0.78645 8.5184,2.94217 10.86394,4.30412 2.34555,1.36195 6.36049,2.6695 6.36049,2.6695 0,0 -8.25373,-2.04423 -11.21821,-3.07958 -2.96447,-1.03535 -7.73259,-2.99481 -10.43406,-3.45243 -2.70147,-0.45763 -11.42225,1.12126 -11.42225,1.12126 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:transform-center-x="13.852145"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8131-9"
+ d="m 789.64298,-227.95417 c 0,0 8.68256,-3.52031 10.54154,-3.60535 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.3006,1.78871 -12.3006,1.78871 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:transform-center-x="13.852145"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8133-2"
+ d="m 804.49513,-233.32948 c 0,0 7.80756,-2.58281 9.66654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -11.4256,0.85121 -11.4256,0.85121 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.3190906"
+ inkscape:transform-center-x="13.852145"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8135-8"
+ d="m 819.55763,-237.57948 c 0,0 8.55756,-2.58281 10.41654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.1756,0.85121 -12.1756,0.85121 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.9269042"
+ inkscape:transform-center-x="13.64141"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8137-8"
+ d="m 836.23395,-242.60125 c 0,0 6.96702,-1.98723 8.82784,-1.96757 1.86081,0.0197 3.57873,0.82702 6.10265,1.80705 2.52393,0.98 8.27166,3.57758 10.50756,5.11291 2.2359,1.53535 6.14053,3.14261 6.14053,3.14261 0,0 -8.07561,-2.66222 -10.95336,-3.91866 -2.87774,-1.25645 -7.48412,-3.5707 -10.14328,-4.23121 -2.65915,-0.66049 -10.48194,0.0549 -10.48194,0.0549 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.1542119"
+ inkscape:transform-center-x="13.55068"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8139-8"
+ d="m 850.73028,-246.00461 c 0,0 7.68784,-2.02768 9.54782,-1.96854 1.85997,0.0592 3.56038,0.90279 6.06293,1.93616 2.50255,1.03334 8.19387,3.75232 10.39668,5.33475 2.20282,1.58245 6.07245,3.2722 6.07245,3.2722 0,0 -8.01729,-2.83298 -10.86772,-4.15022 -2.85043,-1.31723 -7.40666,-3.72872 -10.0512,-4.4455 -2.64454,-0.71678 -11.16096,0.0211 -11.16096,0.0211 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.4740887"
+ inkscape:transform-center-x="13.41151"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8141-6"
+ d="m 864.82496,-249.21081 c 0,0 8.16952,-1.96906 10.02688,-1.85396 1.85735,0.11512 3.53158,1.00956 6.0019,2.11779 2.47031,1.10821 8.0772,3.99727 10.23138,5.64531 2.15418,1.64804 5.9712,3.45352 5.9712,3.45352 0,0 -7.92839,-3.07306 -10.73787,-4.4755 -2.80949,-1.40244 -7.29106,-3.94999 -9.91283,-4.74606 -2.62176,-0.79606 -11.58066,-0.1411 -11.58066,-0.1411 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.79376"
+ inkscape:transform-center-x="13.258805"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8143-8"
+ d="m 881.38485,-251.60282 c 0,0 8.08536,-1.90809 9.93837,-1.73664 1.853,0.17147 3.4993,1.11633 5.93482,2.29908 2.43553,1.18271 7.95209,4.2407 10.05523,5.95339 2.10314,1.7127 5.86357,3.63326 5.86357,3.63326 0,0 -7.8314,-3.3124 -10.597,-4.7995 -2.76561,-1.48712 -7.16775,-4.16959 -9.76414,-5.04491 -2.59637,-0.87531 -11.43085,-0.30468 -11.43085,-0.30468 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8145-3"
+ d="m 896.58415,-254.34724 c 0,0 7.64166,-1.4277 9.49547,-1.26515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-0.76897 -10.99774,-0.76897 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8147-8"
+ d="m 911.45328,-255.98544 c 0,0 8.64166,-1.5527 10.49547,-1.39015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.99774,-0.64397 -11.99774,-0.64397 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8149-3"
+ d="m 927.70328,-258.29794 c 0,0 7.64166,-0.8652 9.49547,-0.70265 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-1.33147 -10.99774,-1.33147 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8151-3"
+ d="m 942.82828,-259.48544 c 0,0 8.57916,-1.4902 10.43297,-1.32765 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.93524,-0.70647 -11.93524,-0.70647 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8153-3"
+ d="m 959.07828,-261.54794 c 0,0 7.82916,-0.8027 9.68297,-0.64015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.18524,-1.39397 -11.18524,-1.39397 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8155-8"
+ d="m 974.45328,-262.79794 c 0,0 8.39166,-1.1777 10.24547,-1.01515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08376,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.84721,-3.27474 -10.61993,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.74774,-1.01897 -11.74774,-1.01897 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8157-0"
+ d="m 990.64078,-264.86044 c 0,0 6.89166,-0.9902 8.74547,-0.82765 1.85385,0.16256 3.50465,1.0995 5.94575,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.60053,-0.86282 -10.24772,-1.20647 -10.24772,-1.20647 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8159-4"
+ d="m 1007.7658,-265.79794 c 0,0 6.8291,-1.1777 8.683,-1.01515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -10.1852,-1.01897 -10.1852,-1.01897 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8161-7"
+ d="m 1023.8908,-267.79794 c 0,0 6.0791,-0.4277 7.933,-0.26515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.4352,-1.76897 -9.4352,-1.76897 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.7433893"
+ inkscape:transform-center-x="13.28378"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8163-6"
+ d="m 1039.7033,-269.17294 c 0,0 6.4541,-0.6777 8.308,-0.51515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.8102,-1.51897 -9.8102,-1.51897 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-5.1360724"
+ inkscape:transform-center-x="13.55813"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8165-8"
+ d="m 1055.2718,-271.03319 c 0,0 5.4976,-0.90945 7.3578,-0.85348 1.8601,0.056 3.5619,0.89674 6.0661,1.92586 2.5044,1.0291 8.2003,3.7384 10.4058,5.31709 2.2055,1.57871 6.078,3.2619 6.078,3.2619 0,0 -8.022,-2.81939 -10.8748,-4.13178 -2.8526,-1.31238 -7.4129,-3.71613 -10.0587,-4.42843 -2.6457,-0.71228 -8.9742,-1.09116 -8.9742,-1.09116 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.6370147"
+ inkscape:transform-center-x="13.74758"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8167-9"
+ d="m 1072.7007,-273.48537 c 0,0 4.5472,-1.15581 6.408,-1.18621 1.8607,-0.0304 3.5996,0.73049 6.1489,1.64231 2.5494,0.91177 8.3649,3.35386 10.6414,4.8285 2.2763,1.47468 6.2227,2.97636 6.2227,2.97636 0,0 -8.1442,-2.44411 -11.0547,-3.62272 -2.9105,-1.1786 -7.5774,-3.36815 -10.2534,-3.95691 -2.6759,-0.58875 -8.1129,-0.68133 -8.1129,-0.68133 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-4.4842392"
+ inkscape:transform-center-x="13.79933"
+ sodipodi:nodetypes="czzzczzc"
+ id="path8169-0"
+ d="m 1087.1585,-276.5244 c 0,0 5.96,-1.77355 7.8202,-1.83024 1.86,-0.0567 3.6096,0.67955 6.1715,1.55525 2.562,0.87566 2.5226,0.85713 5.3335,1.49015 2.7969,0.62986 7.0767,1.51313 7.0767,1.51313 0,0 -3.6155,-0.0163 -6.7923,-0.46614 -3.1155,-0.44119 -7.3743,-1.69825 -10.0584,-2.24913 -2.6839,-0.55088 -9.5512,-0.013 -9.5512,-0.013 z"
+ style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czczc"
+ id="path8171-6"
+ d="m 1099.25,-279.92981 c 0.1612,0.26862 11.2081,-4.60046 12.1875,-4.6875 0.9794,-0.087 2,3.125 2,3.125 0,0 -0.7751,-1.50434 -2.875,-1.0625 -2.0999,0.44184 -11.3009,2.67141 -11.3125,2.625 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path8173-8"
+ d="m 1107.4532,-284.0938 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88718,-0.50701 -5.87501,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0726 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0775 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,1e-5 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 1e-5,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0533 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 1e-5,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0727,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 1e-5,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0772,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.44971,-0.12571 6.37501,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -1e-4,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -10e-5,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7333-7);enable-background:new"
+ sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8175-7"
+ d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7285-4);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8177-9"
+ d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7289-0);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8179-0"
+ d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7293-0);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8181-3"
+ d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.2218,3.85117 1.3584,5.30156 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.7232,0.51703 -1.0156,0.58291 0.531,0.18589 0.6698,0.12483 0.7314,0.96929 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.7314,0.27038 -1.067,0.13944 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7337-2);enable-background:new"
+ sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8183-3"
+ d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7297-4);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8185-3"
+ d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7301-5);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8187-7"
+ d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7305-4);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8189-3"
+ d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7309-9);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8191-2"
+ d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7313-2);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8193-6"
+ d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7317-7);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8195-5"
+ d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7321-5);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8197-2"
+ d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7329-8);enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8199-6"
+ d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+ style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7325-2);enable-background:new" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 863.87812,475.6679 c 1.64212,-3.218 3.51781,-5.73529 4.86136,-9.84898 0.79872,-3.65789 3.31204,-2.03073 7.26047,-8.3969 1.40193,-2.2395 5.47653,0.39136 8.9651,-2.39911 1.27072,-0.80319 2.88488,-0.40431 4.48256,-0.0631 3.76539,1.31896 5.82576,3.70355 8.33376,5.80837 6.13906,5.97023 20.53414,7.94327 23.48604,6.31346 1.43405,-2.90474 7.88128,-5.40888 12.37437,-11.11168 0.74811,-1.12267 11.72936,-8.74446 14.64721,-6.56599"
+ id="path8201-5"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 888.50059,465.25071 c 7.36341,-3.23297 13.8109,-8.9084 20.70813,-13.38452 3.31057,-1.96954 6.86983,3.21601 10.796,3.59866 2.29773,-0.21813 3.7129,1.20259 5.68211,1.6415 5.15636,1.31779 2.39793,3.86488 9.97526,6.43972 6.15561,1.7204 8.9074,-6.79847 14.89975,-7.3236 4.87739,-0.50299 8.09892,-0.31603 11.61675,-0.25254 3.92696,0.13889 4.07855,-3.4976 6.06092,-5.3033 2.98056,-2.80522 7.15561,-1.84972 10.14485,-4.7409 1.01754,-1.38468 1.95458,-3.01085 2.73459,-5.10809 0.88201,-2.00034 3.04006,0.30598 4.79823,1.26269"
+ id="path8203-8"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9048-9);enable-background:accumulate"
+ d="m 403.27922,1056.3058 56.56854,-42.4264 72.12489,14.1421 -46.66904,52.3259 -53.74012,7.0711 -28.28427,-31.1127 z"
+ id="path8994-7" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 542.27183,1060.5719 c -1.40727,18.8012 -1.1449,32.751 2.08174,49.3033 3.22666,16.5523 16.40609,45.9073 20.33441,63.1837 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1483 -15.31761,12.9774 -42.05128,21.5989 -67.83231,15.7337 -25.78105,-5.8652 -69.54907,-49.2234 -88.59019,-70.2283 -19.11214,-21.0833 -63.76086,-93.8506 -77.93853,-124.2758 -14.17767,-30.4251 -12.65961,-36.7186 -8.11972,-45.52972 -9.36672,-24.5205 -12.41371,-50.06681 -33.71245,-75.57664 30.32547,3.11444 43.88028,26.95633 60.12568,47.13975 -5.52989,-48.07603 -18.05471,-64.4165 -28.37395,-90.7243 29.9943,6.08165 50.57936,31.87239 63.97979,72.7125 9.55415,-3.91791 18.23776,-9.37294 30.18741,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.68725,-101.06994 53.44196,5.67033 83.65702,80.63932 78.97142,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34702 -21.04781,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38966,85.80578 6.10287,20.3689 1.51881,38.70051 1.51881,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24138 -3.53269,59.10328 -4.94582,77.98328 z"
+ id="path4189-9"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587-1);enable-background:accumulate"
+ d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+ id="path4191-6"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898-1);enable-background:new"
+ d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.84562,77.83981 -43.7404,101.4864 -6.60491,13.1304 -18.52833,57.4859 -31.12335,76.2465 -12.59502,18.7605 -28.53137,39.7673 -37.17204,44.4209 -21.49052,11.5742 -44.55594,25.5059 -60.61889,18.0895 -14.37486,-6.637 -23.03969,-21.1927 -23.81407,-37.7433 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+ id="path4193-0"
+ clip-path="url(#clipPath3677-0)"
+ sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g3617-4"
+ clip-path="url(#clipPath3622-5)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
+ id="path4195-1"
+ d="m -15.66751,843.48852 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024-1);enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
+ id="path4197-0"
+ d="m 118.70648,859.93048 -55.154328,-46.66904 -43.84062,36.76955 33.94113,53.74011 -13.596814,85.46203 -39.44536579,28.29217 -41.01220021,11.3137 -2.82842,46.669 56.56854,25.4559 18.943987,-69.65 23.45655,-58.85663 46.347541,-72.61491 16.62,-39.91188 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020-8);enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044-0);enable-background:accumulate"
+ d="m -70.82184,932.58397 60.81118,-26.87005 100.40916,31.1127 -63.63961,31.11269 -82.02438,-16.97056 -15.55635,-18.38478 z"
+ id="path4199-4"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4105-2);enable-background:new"
+ d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -7.17516,44.14234 -8.78421,66.21911 -8.78379,2.34171 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 4.66299,24.40472 3.63165,36.35334 -7.06405,45.03355 -22.14231,87.36194 -35.95355,130.6798 -12.07476,32.9493 -27.3742,58.8525 -47.88808,87.2015 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -44.20676,10.8769 -62.59956,0.046 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 4.93886,-28.5121 4.4106,-43.4918 -0.53824,-15.2629 -2.29135,-30.5647 -6.54261,-46.8663 -4.25126,-16.30162 -9.04325,-24.91794 -16.11906,-41.57338 -7.24111,-17.04456 -15.07015,-36.74863 -18.20542,-56.28842 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+ id="path4201-8"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+ clip-path="url(#clipPath4177-4)"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130-8);enable-background:accumulate"
+ d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+ id="path4203-7"
+ sodipodi:nodetypes="cccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141-2);enable-background:accumulate"
+ d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+ id="path4205-0"
+ sodipodi:nodetypes="cccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+ <g
+ id="g8317-8"
+ style="display:inline;filter:url(#filter8333-2);enable-background:new"
+ clip-path="url(#clipPath8338-4)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+ clip-path="none"
+ sodipodi:nodetypes="ccccc"
+ id="path4209-6"
+ d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <rect
+ y="757.19519"
+ x="-55"
+ height="177"
+ width="182"
+ id="rect8315-2"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <g
+ id="g8346-4"
+ style="display:inline;filter:url(#filter8354-2);enable-background:new"
+ clip-path="url(#clipPath8359-0)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+ clip-path="none"
+ sodipodi:nodetypes="ccccccc"
+ id="path4207-7"
+ d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <rect
+ y="696.19519"
+ x="-22"
+ height="176"
+ width="165"
+ id="rect8344-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ d="m 1036.164,1071.8338 c 6.7941,18.9028 10.4937,33.2997 11.8903,51.2119 1.3966,17.9123 -3.7827,51.8008 -2.9005,70.6561 0.8818,18.8452 8.1337,40.099 27.3446,48.9689 19.4189,8.9658 49.3193,10.2113 74.1199,-3.1456 24.8006,-13.357 57.401,-70.3255 70.9742,-97.3087 13.6239,-27.0839 38.7611,-114.4974 44.6608,-149.76859 5.8998,-35.27121 2.5506,-41.30077 -4.6174,-49.05549 2.6403,-27.84015 -1.4998,-54.93543 13.1096,-87.18618 -30.249,11.8257 -37.3823,40.1607 -48.3189,65.50508 -8.0009,-50.93293 0.2092,-71.27319 3.3189,-101.21936 -29.0647,14.77791 -42.8615,47.11402 -45,92.85714 -10.9239,-1.3042 -21.3914,-4.43423 -33.5714,-0.71429 -0.264,-46.02334 -1.4635,-76.88941 8.9106,-114.20649 -53.2554,21.02686 -62.9472,106.5941 -56.0535,112.77792 -10.8828,0.535 -21.371,-1.2973 -32.8571,2.85715 0.6389,-42.57135 -0.2605,-84.90861 -30,-122.85715 0,0 -30.958,80.92234 -31.4286,103.57143 -0.4705,22.64909 9.4516,40.16588 9.4516,40.16588 0,0 -8.568,36.74051 -6.2986,58.23223 2.2959,21.74142 20.4429,59.67622 27.2655,78.65812 z"
+ id="path8848-3"
+ sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587-1);enable-background:accumulate"
+ d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+ id="path3635-9"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898-1);enable-background:new"
+ d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.79272,123.1659 -43.6875,146.8125 -6.60491,13.1304 -18.02998,33.8957 -30.625,52.6563 -12.59502,18.7605 -27.35933,35.5338 -36,40.1874 -21.49052,11.5742 -48.7808,10.2602 -64.84375,2.8438 -14.37486,-6.637 -20.53812,-23.4494 -21.3125,-40 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+ id="path3669-2"
+ clip-path="url(#clipPath3677-0)"
+ sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc" />
+ <g
+ id="g3628-8"
+ clip-path="url(#clipPath3636-90)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path8988-3"
+ d="m 824.48651,818.48242 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024-1);enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path8990-0"
+ d="m 964.49365,855.25197 -55.15433,-46.66904 -43.84062,36.76955 33.94113,53.74011 7.07106,66.46804 -50.91168,35.35537 -41.0122,11.3137 -2.82842,46.669 56.56854,25.4559 63.63961,-76.3676 24.04163,-94.75227 8.48528,-57.98276 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020-8);enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044-0);enable-background:accumulate"
+ d="m 1045.3322,1043.5779 60.8112,-26.8701 100.4091,31.1127 -63.6396,31.1127 -82.0244,-16.9706 -15.5563,-18.3847 z"
+ id="path8992-1" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(450.03125,73.843964)"
+ style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4185-1);enable-background:new"
+ d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -3.2972,44.17323 -4.90625,66.25 -1.31238,1.37679 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 3.12294,24.83149 2.0916,36.78011 -7.06405,45.03355 -21.76553,88.37934 -35.57677,131.69714 -12.07476,32.9493 -30.7197,63.08 -51.23358,91.429 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -43.57595,5.1744 -61.96875,-5.6562 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 2.37211,-27.8008 7.91747,-42.8053 5.54535,-15.0045 2.47105,-31.3317 -1.78021,-47.6333 -4.25126,-16.3016 -12.17903,-26.26002 -21.82158,-42.20417 -9.64255,-15.94415 -17.6369,-36.03734 -20.77217,-55.57713 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+ id="path4149-7"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+ clip-path="url(#clipPath4177-4)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130-8);enable-background:accumulate"
+ d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+ id="path3902-8"
+ sodipodi:nodetypes="cccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="translate(276,136)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141-2);enable-background:accumulate"
+ d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+ id="path4135-9"
+ sodipodi:nodetypes="cccccccc"
+ clip-path="url(#clipPath3631-6)"
+ transform="translate(276,136)" />
+ <g
+ id="g8367-1"
+ style="filter:url(#filter8379-0)"
+ clip-path="url(#clipPath8392-1)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ sodipodi:nodetypes="ccccccc"
+ id="path4145-5"
+ d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <rect
+ y="650.19098"
+ x="877.51953"
+ height="172.53406"
+ width="123.03658"
+ id="rect8365-4"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ <g
+ id="g8400-9"
+ style="filter:url(#filter8404-9)"
+ clip-path="url(#clipPath8417-4)"
+ transform="translate(276,136)">
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ sodipodi:nodetypes="ccccc"
+ id="path4147-2"
+ d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ <rect
+ y="677.06104"
+ x="924.89569"
+ height="125.1579"
+ width="142.12846"
+ id="rect8398-5"
+ style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+ </g>
+ </g>
+ </g>
+ <path
+ style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:17.84425545;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send)"
+ d="M 544.23337,203.09259 3443.746,100.92806"
+ id="path7167"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="display:inline;fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:18;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send-4);enable-background:new"
+ d="M 527.91203,584.39421 3442.4188,1000.8355"
+ id="path7167-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f83615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="80.219048"
+ y="107.38741"
+ id="text8200"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan8202"
+ x="80.219048"
+ y="107.38741"
+ style="font-size:50px;fill:#f83615;fill-opacity:1">CROP_DEFAULT</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f80000;fill-opacity:0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="3861.3669"
+ y="1281.7198"
+ id="text8200-4"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105877,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5"
+ x="3861.3669"
+ y="1281.7198"
+ style="font-size:56.64243317px;fill:#f80000;fill-opacity:0">COMPOSE_PADDED</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f8d615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="3615.1545"
+ y="49.156631"
+ id="text8200-4-9"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105877,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3"
+ x="3615.1545"
+ y="49.156631"
+ style="font-size:50px;fill:#f8d615;fill-opacity:1">COMPOSE_ACTIVE</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f83615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="2429.1526"
+ y="-3.1657715"
+ id="text8200-4-5"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105878,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-7"
+ x="2429.1526"
+ y="-3.1657715"
+ style="font-size:49.99999958px;fill:#f83615;fill-opacity:1">COMPOSE_DEFAULT</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f815bb;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="3681.5449"
+ y="1289.9539"
+ id="text8200-4-9-3"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105877,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6"
+ x="3681.5449"
+ y="1289.9539"
+ style="font-size:50px;fill:#f815bb;fill-opacity:1">COMPOSE_PADDED</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:50px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new;"
+ x="2438.0618"
+ y="1368.4291"
+ id="text8200-4-9-3-5"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105877,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6-3"
+ x="2438.0618"
+ y="1368.4291"
+ style="font-size:50px;fill:#000000;fill-opacity:1;">COMPOSE_BONDS</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="8.0815096"
+ y="1438.8961"
+ id="text8200-4-9-3-5-6"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6-3-2"
+ x="8.0815096"
+ y="1438.8961"
+ style="font-size:50px;fill:#000000;fill-opacity:1">CROP_BONDS</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="1455.4426"
+ y="-26.808125"
+ id="text8200-4-9-3-5-6-9"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6-3-2-1"
+ x="1455.4426"
+ y="-26.808125"
+ style="font-size:50px;fill:#000000;fill-opacity:1">overscan area</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f8d615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="179.63055"
+ y="385.38785"
+ id="text8200-4-9-2"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-7"
+ x="179.63055"
+ y="385.38785"
+ style="font-size:50px;fill:#f8d615;fill-opacity:1">CROP_ACTIVE</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="636.67419"
+ y="-138.84549"
+ id="text8200-4-9-3-5-6-0"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6-3-2-9"
+ x="636.67419"
+ y="-138.84549"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:70px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1">DATA SOURCE</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+ x="3178.7151"
+ y="-129.06131"
+ id="text8200-4-9-3-5-6-0-3"
+ sodipodi:linespacing="125%"
+ transform="scale(0.96105877,1.0405191)"><tspan
+ sodipodi:role="line"
+ id="tspan8202-5-3-6-3-2-9-6"
+ x="3178.7151"
+ y="-129.06131"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:69.99999978px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1">DATA SINK</tspan></text>
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot7469"
+ style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:57.5px;line-height:125%;letter-spacing:0px;word-spacing:0px;"><flowRegion
+ id="flowRegion7471"><rect
+ id="rect7473"
+ width="4297.5474"
+ height="1851.537"
+ x="-52.635666"
+ y="70.623535"
+ style="font-size:57.5px;" /></flowRegion><flowPara
+ id="flowPara7475"></flowPara></flowRoot> </g>
+</svg>
diff --git a/Documentation/media/uapi/v4l/subdev-formats.rst b/Documentation/media/uapi/v4l/subdev-formats.rst
index e144370f62a0..d6152c907b8b 100644
--- a/Documentation/media/uapi/v4l/subdev-formats.rst
+++ b/Documentation/media/uapi/v4l/subdev-formats.rst
@@ -1514,23 +1514,28 @@ be named ``MEDIA_BUS_FMT_SRGGB10_2X8_PADHI_LE``.
.. _bayer-patterns:
-.. figure:: subdev-formats_files/bayer.*
- :alt: bayer.png
+.. figure:: bayer.*
+ :alt: bayer.pdf / bayer.svg
:align: center
**Figure 4.8 Bayer Patterns**
-
-
The following table lists existing packed Bayer formats. The data
organization is given as an example for the first pixel only.
+.. HACK: ideally, we would be using adjustbox here. However, Sphinx
+.. is a very bad behaviored guy: if the table has more than 30 cols,
+.. it switches to long table, and there's no way to override it.
+
+
.. raw:: latex
- \newline\newline\begin{adjustbox}{width=\columnwidth}
+ \begingroup
+ \tiny
+ \setlength{\tabcolsep}{2pt}
-.. tabularcolumns:: |p{7.6cm}|p{1.6cm}|p{0.7cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.3cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
.. _v4l2-mbus-pixelcode-bayer:
@@ -2314,7 +2319,7 @@ organization is given as an example for the first pixel only.
.. raw:: latex
- \end{adjustbox}\newline\newline
+ \endgroup
Packed YUV Formats
diff --git a/Documentation/media/uapi/v4l/subdev-formats_files/bayer.png b/Documentation/media/uapi/v4l/subdev-formats_files/bayer.png
deleted file mode 100644
index 9b15fb22e817..000000000000
--- a/Documentation/media/uapi/v4l/subdev-formats_files/bayer.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg b/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg
new file mode 100644
index 000000000000..ba02e6f6214d
--- /dev/null
+++ b/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="43cm"
+ height="10cm"
+ viewBox="-194 128 844 196"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="subdev-image-processing-crop.svg">
+ <metadata
+ id="metadata100">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs98" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview96"
+ showgrid="false"
+ inkscape:zoom="0.3649199"
+ inkscape:cx="767.29168"
+ inkscape:cy="177.16535"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x="-8"
+ y="130"
+ width="469.774"
+ height="193"
+ id="rect4" />
+ <g
+ id="g6"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="4.5"
+ y="189"
+ width="159"
+ height="104"
+ id="rect8" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a52a2a"
+ x="4.5"
+ y="189"
+ width="159"
+ height="104"
+ id="rect10" />
+ </g>
+ <g
+ id="g12"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="63.5"
+ y="211"
+ width="94"
+ height="77"
+ id="rect14" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x="63.5"
+ y="211"
+ width="94"
+ height="77"
+ id="rect16" />
+ </g>
+ <text
+ style="fill:#0000ff;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="74.5"
+ y="227.75"
+ id="text18">
+ <tspan
+ x="74.5"
+ y="227.75"
+ id="tspan20"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink</tspan>
+ <tspan
+ x="74.5"
+ y="243.75"
+ id="tspan22"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">crop</tspan>
+ <tspan
+ x="74.5"
+ y="259.75"
+ id="tspan24"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection</tspan>
+ </text>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="29.5"
+ y="158"
+ id="text26">
+ <tspan
+ x="29.5"
+ y="158"
+ id="tspan28"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;" />
+ </text>
+ <text
+ style="fill:#a52a2a;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="8.53836"
+ y="157.914"
+ id="text30">
+ <tspan
+ x="8.53836"
+ y="157.914"
+ id="tspan32"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink media</tspan>
+ <tspan
+ x="8.53836"
+ y="173.914"
+ id="tspan34"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <text
+ style="fill:#8b6914;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="349.774"
+ y="155"
+ id="text36">
+ <tspan
+ x="349.774"
+ y="155"
+ id="tspan38"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">source media</tspan>
+ <tspan
+ x="349.774"
+ y="171"
+ id="tspan40"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <g
+ id="g42"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="350.488"
+ y="190.834"
+ width="93.2863"
+ height="75.166"
+ id="rect44" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#8b6914"
+ x="350.488"
+ y="190.834"
+ width="93.2863"
+ height="75.166"
+ id="rect46" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="350.488"
+ y1="266"
+ x2="63.5"
+ y2="288"
+ id="line48" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="350.488"
+ y1="190.834"
+ x2="63.5"
+ y2="211"
+ id="line50" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="443.774"
+ y1="266"
+ x2="157.5"
+ y2="288"
+ id="line52" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="443.774"
+ y1="190.834"
+ x2="157.5"
+ y2="211"
+ id="line54" />
+ <g
+ id="g56"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="473.1"
+ cy="219.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse58" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="473.1"
+ cy="219.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse60" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="473.1"
+ cy="219.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse62" />
+ </g>
+ <g
+ id="g64"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="481.6"
+ y1="219.984"
+ x2="637.934"
+ y2="220.012"
+ id="line66" />
+ <polygon
+ style="fill:#000000"
+ points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "
+ id="polygon68" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "
+ id="polygon70" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="506.908"
+ y="209.8"
+ id="text72">
+ <tspan
+ x="506.908"
+ y="209.8"
+ id="tspan74"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 1 (source)</tspan>
+ </text>
+ <g
+ id="g76"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse78" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse80" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse82" />
+ </g>
+ <g
+ id="g84"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="-192.398"
+ y1="241.8"
+ x2="-38.6343"
+ y2="241.529"
+ id="line86" />
+ <polygon
+ style="fill:#000000"
+ points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "
+ id="polygon88" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "
+ id="polygon90" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="-147.858"
+ y="229.8"
+ id="text92">
+ <tspan
+ x="-147.858"
+ y="229.8"
+ id="tspan94"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 0 (sink)</tspan>
+ </text>
+</svg>
diff --git a/Documentation/media/uapi/v4l/subdev-image-processing-full.svg b/Documentation/media/uapi/v4l/subdev-image-processing-full.svg
new file mode 100644
index 000000000000..c82291a4493e
--- /dev/null
+++ b/Documentation/media/uapi/v4l/subdev-image-processing-full.svg
@@ -0,0 +1,769 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="59cm"
+ height="18cm"
+ viewBox="-186 71 1178 346"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="subdev-image-processing-full.svg">
+ <metadata
+ id="metadata260">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs258" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview256"
+ showgrid="false"
+ inkscape:zoom="0.26595857"
+ inkscape:cx="1052.7956"
+ inkscape:cy="318.89764"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <g
+ id="g4"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="318.9"
+ y="129"
+ width="208.1"
+ height="249"
+ id="rect6" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#ff765a"
+ x="318.9"
+ y="129"
+ width="208.1"
+ height="249"
+ id="rect8" />
+ </g>
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x="-2"
+ y="73"
+ width="806"
+ height="343"
+ id="rect10" />
+ <g
+ id="g12"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="-12.5"
+ cy="166.712"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse14" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-12.5"
+ cy="166.712"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse16" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-12.5"
+ cy="166.712"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse18" />
+ </g>
+ <g
+ id="g20"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="815.232"
+ cy="205.184"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse22" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="815.232"
+ cy="205.184"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse24" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="815.232"
+ cy="205.184"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse26" />
+ </g>
+ <g
+ id="g28"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="-184.5"
+ y1="167"
+ x2="-30.7361"
+ y2="166.729"
+ id="line30" />
+ <polygon
+ style="fill:#000000"
+ points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "
+ id="polygon32" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "
+ id="polygon34" />
+ </g>
+ <g
+ id="g36"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="823.732"
+ y1="205.184"
+ x2="980.066"
+ y2="205.212"
+ id="line38" />
+ <polygon
+ style="fill:#000000"
+ points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "
+ id="polygon40" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "
+ id="polygon42" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="-139.96"
+ y="155"
+ id="text44">
+ <tspan
+ x="-139.96"
+ y="155"
+ id="tspan46"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 0 (sink)</tspan>
+ </text>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="849.04"
+ y="195"
+ id="text48">
+ <tspan
+ x="849.04"
+ y="195"
+ id="tspan50"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 2 (source)</tspan>
+ </text>
+ <g
+ id="g52"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="5.5"
+ y="120"
+ width="159"
+ height="104"
+ id="rect54" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a52a2a"
+ x="5.5"
+ y="120"
+ width="159"
+ height="104"
+ id="rect56" />
+ </g>
+ <g
+ id="g58"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="62.5"
+ y="136"
+ width="94"
+ height="77"
+ id="rect60" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x="62.5"
+ y="136"
+ width="94"
+ height="77"
+ id="rect62" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="30.5"
+ y="89"
+ id="text64">
+ <tspan
+ x="30.5"
+ y="89"
+ id="tspan66"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;" />
+ </text>
+ <text
+ style="fill:#a52a2a;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="9.53836"
+ y="88.9138"
+ id="text68">
+ <tspan
+ x="9.53836"
+ y="88.9138"
+ id="tspan70"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink media</tspan>
+ <tspan
+ x="9.53836"
+ y="104.914"
+ id="tspan72"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <g
+ id="g74"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="333.644"
+ y="185.65"
+ width="165.2"
+ height="172.478"
+ id="rect76" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#00ff00"
+ x="333.644"
+ y="185.65"
+ width="165.2"
+ height="172.478"
+ id="rect78" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="333.644"
+ y1="358.128"
+ x2="62.5"
+ y2="213"
+ id="line80" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="333.644"
+ y1="185.65"
+ x2="62.5"
+ y2="136"
+ id="line82" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="498.844"
+ y1="358.128"
+ x2="156.5"
+ y2="213"
+ id="line84" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="498.844"
+ y1="185.65"
+ x2="156.5"
+ y2="136"
+ id="line86" />
+ <text
+ style="fill:#00ff00;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="334.704"
+ y="149.442"
+ id="text88">
+ <tspan
+ x="334.704"
+ y="149.442"
+ id="tspan90"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink compose</tspan>
+ <tspan
+ x="334.704"
+ y="165.442"
+ id="tspan92"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection (scaling)</tspan>
+ </text>
+ <g
+ id="g94"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="409.322"
+ y="194.565"
+ width="100.186"
+ height="71.4523"
+ id="rect96" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x="409.322"
+ y="194.565"
+ width="100.186"
+ height="71.4523"
+ id="rect98" />
+ </g>
+ <text
+ style="fill:#8b6914;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="689.5"
+ y="105.128"
+ id="text100">
+ <tspan
+ x="689.5"
+ y="105.128"
+ id="tspan102"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">source media</tspan>
+ <tspan
+ x="689.5"
+ y="121.128"
+ id="tspan104"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <g
+ id="g106"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="688.488"
+ y="173.834"
+ width="100.186"
+ height="71.4523"
+ id="rect108" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#8b6914"
+ x="688.488"
+ y="173.834"
+ width="100.186"
+ height="71.4523"
+ id="rect110" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="688.488"
+ y1="245.286"
+ x2="409.322"
+ y2="266.018"
+ id="line112" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="688.488"
+ y1="173.834"
+ x2="409.322"
+ y2="194.565"
+ id="line114" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="788.674"
+ y1="245.286"
+ x2="509.508"
+ y2="266.018"
+ id="line116" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="788.674"
+ y1="173.834"
+ x2="509.508"
+ y2="194.565"
+ id="line118" />
+ <text
+ style="fill:#ff765a;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="325"
+ y="103"
+ id="text120">
+ <tspan
+ x="325"
+ y="103"
+ id="tspan122"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink compose</tspan>
+ <tspan
+ x="325"
+ y="119"
+ id="tspan124"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bounds selection</tspan>
+ </text>
+ <g
+ id="g126"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="-12.0982"
+ cy="341.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse128" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-12.0982"
+ cy="341.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse130" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-12.0982"
+ cy="341.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse132" />
+ </g>
+ <g
+ id="g134"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="-184.098"
+ y1="341.8"
+ x2="-30.3343"
+ y2="341.529"
+ id="line136" />
+ <polygon
+ style="fill:#000000"
+ points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "
+ id="polygon138" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "
+ id="polygon140" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="-139"
+ y="329"
+ id="text142">
+ <tspan
+ x="-139"
+ y="329"
+ id="tspan144"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 1 (sink)</tspan>
+ </text>
+ <g
+ id="g146"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="7.80824"
+ y="292.8"
+ width="112.092"
+ height="82.2"
+ id="rect148" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a52a2a"
+ x="7.80824"
+ y="292.8"
+ width="112.092"
+ height="82.2"
+ id="rect150" />
+ </g>
+ <g
+ id="g152"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="52.9"
+ y="314.8"
+ width="58.1"
+ height="50.2"
+ id="rect154" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x="52.9"
+ y="314.8"
+ width="58.1"
+ height="50.2"
+ id="rect156" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="31.9"
+ y="259.8"
+ id="text158">
+ <tspan
+ x="31.9"
+ y="259.8"
+ id="tspan160"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;" />
+ </text>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="358.9"
+ y1="251.9"
+ x2="52.9"
+ y2="314.8"
+ id="line162" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="358.9"
+ y1="316"
+ x2="52.9"
+ y2="365"
+ id="line164" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="434"
+ y1="316"
+ x2="111"
+ y2="365"
+ id="line166" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="434"
+ y1="251.9"
+ x2="111"
+ y2="314.8"
+ id="line168" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#00ff00"
+ x="358.9"
+ y="251.9"
+ width="75.1"
+ height="64.1"
+ id="rect170" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x="443.262"
+ y="284.466"
+ width="64.738"
+ height="48.534"
+ id="rect172" />
+ <g
+ id="g174"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="693.428"
+ y="324.734"
+ width="63.572"
+ height="49.266"
+ id="rect176" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#8b6914"
+ x="693.428"
+ y="324.734"
+ width="63.572"
+ height="49.266"
+ id="rect178" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="693.428"
+ y1="374"
+ x2="443.262"
+ y2="333"
+ id="line180" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="693.428"
+ y1="324.734"
+ x2="443.262"
+ y2="284.466"
+ id="line182" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="757"
+ y1="374"
+ x2="508"
+ y2="333"
+ id="line184" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="757"
+ y1="324.734"
+ x2="508"
+ y2="284.466"
+ id="line186" />
+ <g
+ id="g188"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="815.44"
+ cy="343.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse190" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="815.44"
+ cy="343.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse192" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="815.44"
+ cy="343.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse194" />
+ </g>
+ <g
+ id="g196"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="823.94"
+ y1="343.984"
+ x2="980.274"
+ y2="344.012"
+ id="line198" />
+ <polygon
+ style="fill:#000000"
+ points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "
+ id="polygon200" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "
+ id="polygon202" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="849.248"
+ y="333.8"
+ id="text204">
+ <tspan
+ x="849.248"
+ y="333.8"
+ id="tspan206"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 3 (source)</tspan>
+ </text>
+ <text
+ style="fill:#0000ff;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="197"
+ y="91"
+ id="text208">
+ <tspan
+ x="197"
+ y="91"
+ id="tspan210"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink</tspan>
+ <tspan
+ x="197"
+ y="107"
+ id="tspan212"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">crop</tspan>
+ <tspan
+ x="197"
+ y="123"
+ id="tspan214"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection</tspan>
+ </text>
+ <text
+ style="fill:#a020f0;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="553"
+ y="95"
+ id="text216">
+ <tspan
+ x="553"
+ y="95"
+ id="tspan218"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">source</tspan>
+ <tspan
+ x="553"
+ y="111"
+ id="tspan220"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">crop</tspan>
+ <tspan
+ x="553"
+ y="127"
+ id="tspan222"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection</tspan>
+ </text>
+ <g
+ id="g224"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x1="211"
+ y1="132"
+ x2="166.21"
+ y2="135.287"
+ id="line226" />
+ <polygon
+ style="fill:#0000ff"
+ points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "
+ id="polygon228" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "
+ id="polygon230" />
+ </g>
+ <g
+ id="g232"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x1="209"
+ y1="131"
+ x2="115.581"
+ y2="306.209"
+ id="line234" />
+ <polygon
+ style="fill:#0000ff"
+ points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "
+ id="polygon236" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "
+ id="polygon238" />
+ </g>
+ <g
+ id="g240"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x1="550.492"
+ y1="133.214"
+ x2="514.916"
+ y2="186.469"
+ id="line242" />
+ <polygon
+ style="fill:#a020f0"
+ points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "
+ id="polygon244" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "
+ id="polygon246" />
+ </g>
+ <g
+ id="g248"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x1="550.072"
+ y1="133.787"
+ x2="510.618"
+ y2="275.089"
+ id="line250" />
+ <polygon
+ style="fill:#a020f0"
+ points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "
+ id="polygon252" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "
+ id="polygon254" />
+ </g>
+</svg>
diff --git a/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg b/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg
new file mode 100644
index 000000000000..e7b3786f8a9b
--- /dev/null
+++ b/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg
@@ -0,0 +1,560 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="59cm"
+ height="17cm"
+ viewBox="-194 128 1179 330"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="subdev-image-processing-scaling-multi-source.svg">
+ <metadata
+ id="metadata186">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs184" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview182"
+ showgrid="false"
+ inkscape:zoom="0.26595857"
+ inkscape:cx="1052.7956"
+ inkscape:cy="301.1811"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x="-8"
+ y="130"
+ width="806"
+ height="327"
+ id="rect4" />
+ <g
+ id="g6"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="4.5"
+ y="189"
+ width="159"
+ height="104"
+ id="rect8" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a52a2a"
+ x="4.5"
+ y="189"
+ width="159"
+ height="104"
+ id="rect10" />
+ </g>
+ <g
+ id="g12"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="49.5"
+ y="204"
+ width="94"
+ height="77"
+ id="rect14" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#0000ff"
+ x="49.5"
+ y="204"
+ width="94"
+ height="77"
+ id="rect16" />
+ </g>
+ <text
+ style="fill:#0000ff;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="60"
+ y="224"
+ id="text18">
+ <tspan
+ x="60"
+ y="224"
+ id="tspan20"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink</tspan>
+ <tspan
+ x="60"
+ y="240"
+ id="tspan22"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">crop</tspan>
+ <tspan
+ x="60"
+ y="256"
+ id="tspan24"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection</tspan>
+ </text>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="29.5"
+ y="158"
+ id="text26">
+ <tspan
+ x="29.5"
+ y="158"
+ id="tspan28"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;" />
+ </text>
+ <text
+ style="fill:#a52a2a;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="8.53836"
+ y="157.914"
+ id="text30">
+ <tspan
+ x="8.53836"
+ y="157.914"
+ id="tspan32"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink media</tspan>
+ <tspan
+ x="8.53836"
+ y="173.914"
+ id="tspan34"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <g
+ id="g36"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="333.644"
+ y="185.65"
+ width="165.2"
+ height="172.478"
+ id="rect38" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#00ff00"
+ x="333.644"
+ y="185.65"
+ width="165.2"
+ height="172.478"
+ id="rect40" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="333.644"
+ y1="358.128"
+ x2="49.5"
+ y2="281"
+ id="line42" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="333.644"
+ y1="185.65"
+ x2="49.5"
+ y2="204"
+ id="line44" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="498.844"
+ y1="358.128"
+ x2="143.5"
+ y2="281"
+ id="line46" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="498.844"
+ y1="185.65"
+ x2="143.5"
+ y2="204"
+ id="line48" />
+ <text
+ style="fill:#00ff00;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="334.704"
+ y="149.442"
+ id="text50">
+ <tspan
+ x="334.704"
+ y="149.442"
+ id="tspan52"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">sink compose</tspan>
+ <tspan
+ x="334.704"
+ y="165.442"
+ id="tspan54"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection (scaling)</tspan>
+ </text>
+ <g
+ id="g56"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="382.322"
+ y="199.565"
+ width="100.186"
+ height="71.4523"
+ id="rect58" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x="382.322"
+ y="199.565"
+ width="100.186"
+ height="71.4523"
+ id="rect60" />
+ </g>
+ <text
+ style="fill:#a020f0;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="543.322"
+ y="149.442"
+ id="text62">
+ <tspan
+ x="543.322"
+ y="149.442"
+ id="tspan64"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">source</tspan>
+ <tspan
+ x="543.322"
+ y="165.442"
+ id="tspan66"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">crop</tspan>
+ <tspan
+ x="543.322"
+ y="181.442"
+ id="tspan68"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">selection</tspan>
+ </text>
+ <text
+ style="fill:#8b6914;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="691.5"
+ y="157.128"
+ id="text70">
+ <tspan
+ x="691.5"
+ y="157.128"
+ id="tspan72"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">source media</tspan>
+ <tspan
+ x="691.5"
+ y="173.128"
+ id="tspan74"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">bus format</tspan>
+ </text>
+ <g
+ id="g76"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="690.488"
+ y="225.834"
+ width="100.186"
+ height="71.4523"
+ id="rect78" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#8b6914"
+ x="690.488"
+ y="225.834"
+ width="100.186"
+ height="71.4523"
+ id="rect80" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="690.488"
+ y1="297.286"
+ x2="382.322"
+ y2="271.018"
+ id="line82" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="690.488"
+ y1="225.834"
+ x2="382.322"
+ y2="199.565"
+ id="line84" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="790.674"
+ y1="297.286"
+ x2="482.508"
+ y2="271.018"
+ id="line86" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="790.674"
+ y1="225.834"
+ x2="482.508"
+ y2="199.565"
+ id="line88" />
+ <g
+ id="g90"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="808.1"
+ cy="249.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse92" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="808.1"
+ cy="249.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse94" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="808.1"
+ cy="249.984"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse96" />
+ </g>
+ <g
+ id="g98"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="816.6"
+ y1="249.984"
+ x2="972.934"
+ y2="250.012"
+ id="line100" />
+ <polygon
+ style="fill:#000000"
+ points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "
+ id="polygon102" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "
+ id="polygon104" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="841.908"
+ y="239.8"
+ id="text106">
+ <tspan
+ x="841.908"
+ y="239.8"
+ id="tspan108"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 1 (source)</tspan>
+ </text>
+ <g
+ id="g110"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse112" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse114" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="-20.3982"
+ cy="241.512"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse116" />
+ </g>
+ <g
+ id="g118"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="-192.398"
+ y1="241.8"
+ x2="-38.6343"
+ y2="241.529"
+ id="line120" />
+ <polygon
+ style="fill:#000000"
+ points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "
+ id="polygon122" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "
+ id="polygon124" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="-147.858"
+ y="229.8"
+ id="text126">
+ <tspan
+ x="-147.858"
+ y="229.8"
+ id="tspan128"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 0 (sink)</tspan>
+ </text>
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x="389.822"
+ y="276.666"
+ width="100.186"
+ height="71.4523"
+ id="rect130" />
+ <g
+ id="g132"
+ style="">
+ <rect
+ style="fill:#ffffff"
+ x="689.988"
+ y="345.934"
+ width="100.186"
+ height="71.4523"
+ id="rect134" />
+ <rect
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#8b6914"
+ x="689.988"
+ y="345.934"
+ width="100.186"
+ height="71.4523"
+ id="rect136" />
+ </g>
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="689.988"
+ y1="417.386"
+ x2="389.822"
+ y2="348.118"
+ id="line138" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="689.988"
+ y1="345.934"
+ x2="389.822"
+ y2="276.666"
+ id="line140" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="790.174"
+ y1="417.386"
+ x2="490.008"
+ y2="348.118"
+ id="line142" />
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke-dasharray:4;stroke:#e60505"
+ x1="790.174"
+ y1="345.934"
+ x2="490.008"
+ y2="276.666"
+ id="line144" />
+ <g
+ id="g146"
+ style="">
+ <ellipse
+ style="fill:#ffffff"
+ cx="805.6"
+ cy="384.084"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse148" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="805.6"
+ cy="384.084"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse150" />
+ <ellipse
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ cx="805.6"
+ cy="384.084"
+ rx="8.5"
+ ry="8.5"
+ id="ellipse152" />
+ </g>
+ <g
+ id="g154"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ x1="814.1"
+ y1="384.084"
+ x2="970.434"
+ y2="384.112"
+ id="line156" />
+ <polygon
+ style="fill:#000000"
+ points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "
+ id="polygon158" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#000000"
+ points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "
+ id="polygon160" />
+ </g>
+ <text
+ style="fill:#000000;text-anchor:start;font-size:12.8;font-family:sans-serif;font-style:normal;font-weight:normal;-inkscape-font-specification:sans-serif;font-stretch:normal;font-variant:normal;"
+ x="839.408"
+ y="373.9"
+ id="text162">
+ <tspan
+ x="839.408"
+ y="373.9"
+ id="tspan164"
+ style="-inkscape-font-specification:sans-serif;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;">pad 2 (source)</tspan>
+ </text>
+ <g
+ id="g166"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x1="546"
+ y1="191"
+ x2="492.157"
+ y2="198.263"
+ id="line168" />
+ <polygon
+ style="fill:#a020f0"
+ points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "
+ id="polygon170" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "
+ id="polygon172" />
+ </g>
+ <g
+ id="g174"
+ style="">
+ <line
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ x1="546.908"
+ y1="190.725"
+ x2="495.383"
+ y2="268.548"
+ id="line176" />
+ <polygon
+ style="fill:#a020f0"
+ points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "
+ id="polygon178" />
+ <polygon
+ style="fill:none;fill-opacity:0;stroke-width:2;stroke:#a020f0"
+ points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "
+ id="polygon180" />
+ </g>
+</svg>
diff --git a/Documentation/media/uapi/v4l/vbi_525.svg b/Documentation/media/uapi/v4l/vbi_525.svg
new file mode 100644
index 000000000000..b05f7777ccf8
--- /dev/null
+++ b/Documentation/media/uapi/v4l/vbi_525.svg
@@ -0,0 +1,811 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="208.73068mm"
+ height="51.395489mm"
+ viewBox="0 0 739.59691 182.11"
+ sodipodi:docname="vbi_525.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview4"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="1.5350601"
+ inkscape:cx="264.23387"
+ inkscape:cy="44.916942"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g10"
+ units="mm" /><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath20"
+ clipPathUnits="userSpaceOnUse"><path
+ inkscape:connector-curvature="0"
+ id="path22"
+ d="m 0,0 5950,0 0,3922 L 0,3922 0,0 Z m 0,3922 5950,0 0,1 -5950,0 0,-1 z m 0,1 1359,0 0,1 -1359,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1363,0 0,1 -1363,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1367,0 0,1 -1367,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1371,0 0,1 -1371,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1375,0 0,1 -1375,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1379,0 0,1 -1379,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1383,0 0,1 -1383,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1387,0 0,1 -1387,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1391,0 0,1 -1391,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1390,0 0,1 -1390,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1386,0 0,1 -1386,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1382,0 0,1 -1382,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1378,0 0,1 -1378,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1374,0 0,1 -1374,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1370,0 0,1 -1370,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1366,0 0,1 -1366,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1362,0 0,1 -1362,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1358,0 0,1 -1358,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,4478 -5950,0 0,-4478 z" /></clipPath><clipPath
+ id="clipPath98"
+ clipPathUnits="userSpaceOnUse"><path
+ inkscape:connector-curvature="0"
+ id="path100"
+ d="m 0,0 5950,0 0,4546 L 0,4546 0,0 Z m 0,4546 5950,0 0,1 -5950,0 0,-1 z m 0,1 1360,0 0,1 -1360,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1364,0 0,1 -1364,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1368,0 0,1 -1368,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1372,0 0,1 -1372,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1376,0 0,1 -1376,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1380,0 0,1 -1380,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1384,0 0,1 -1384,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1388,0 0,1 -1388,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1391,0 0,1 -1391,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1389,0 0,1 -1389,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1385,0 0,1 -1385,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1381,0 0,1 -1381,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1377,0 0,1 -1377,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1373,0 0,1 -1373,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1369,0 0,1 -1369,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1365,0 0,1 -1365,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1361,0 0,1 -1361,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1357,0 0,1 -1357,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,3854 -5950,0 0,-3854 z" /></clipPath></defs><g
+ transform="matrix(0.125,0,0,-0.125,-87.571875,638.05691)"
+ inkscape:label="vbi_525"
+ inkscape:groupmode="layer"
+ id="g10"><g
+ transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+ id="g12"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,3974.45 0,-85.05" /></g><g
+ transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+ id="g16"
+ style=""><g
+ clip-path="url(#clipPath20)"
+ id="g18"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path24"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,3931.93 113.4,0" /></g></g><g
+ transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+ id="g26"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path28"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1352.31,3922.48 37.8,9.45 -37.8,9.45 0,-18.9" /><path
+ inkscape:connector-curvature="0"
+ id="path30"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1352.31,3922.48 37.8,9.45 -37.8,9.45 0,-18.9 z" /><path
+ inkscape:connector-curvature="0"
+ id="path32"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4683.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path34"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4400.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path36"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4116.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path38"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3833.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path40"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3549.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path42"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3266.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path44"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2982.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path46"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2699.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path48"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2415.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path50"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2132.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path52"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1848.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path54"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1565.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path56"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path58"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 998.25,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path60"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 714.75,4059.5 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path62"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4683.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path64"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4400.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path66"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4116.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path68"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3833.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path70"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3549.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path72"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3266.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path74"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2982.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path76"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2699.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path78"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2415.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path80"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2132.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path82"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1848.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path84"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1565.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path86"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path88"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 998.25,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path90"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 714.75,4144.55 0,-56.7" /><path
+ inkscape:connector-curvature="0"
+ id="path92"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,4598.15 0,-85.05" /></g><g
+ transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+ id="g94"
+ style=""><g
+ clip-path="url(#clipPath98)"
+ id="g96"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path102"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1281.75,4555.63 113.4,0" /></g></g><path
+ d="m 1547.8322,4815.7637 49.1401,12.2851 -49.1401,12.285 0,-24.5701"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path106"
+ inkscape:connector-curvature="0" /><path
+ d="m 1547.8322,4815.7637 49.1401,12.2851 -49.1401,12.285 0,-24.5701 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path108"
+ inkscape:connector-curvature="0" /><path
+ d="m 1456.104,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path110"
+ inkscape:connector-curvature="0" /><path
+ d="m 1824.6548,5030.7452 0,73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path112"
+ inkscape:connector-curvature="0" /><path
+ d="m 2193.2055,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path114"
+ inkscape:connector-curvature="0" /><path
+ d="m 2561.7563,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path116"
+ inkscape:connector-curvature="0" /><path
+ d="m 2930.307,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path118"
+ inkscape:connector-curvature="0" /><path
+ d="m 3298.8578,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path120"
+ inkscape:connector-curvature="0" /><path
+ d="m 3667.4085,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path122"
+ inkscape:connector-curvature="0" /><path
+ d="m 4035.9593,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path124"
+ inkscape:connector-curvature="0" /><path
+ d="m 4404.51,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path126"
+ inkscape:connector-curvature="0" /><path
+ d="m 4773.0608,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path128"
+ inkscape:connector-curvature="0" /><path
+ d="m 5141.6115,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path130"
+ inkscape:connector-curvature="0" /><path
+ d="m 5510.1623,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path132"
+ inkscape:connector-curvature="0" /><path
+ d="m 5878.713,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path134"
+ inkscape:connector-curvature="0" /><path
+ d="m 1456.104,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path136"
+ inkscape:connector-curvature="0" /><path
+ d="m 1824.6548,4920.1799 0,73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path138"
+ inkscape:connector-curvature="0" /><path
+ d="m 2193.2055,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path140"
+ inkscape:connector-curvature="0" /><path
+ d="m 2561.7563,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path142"
+ inkscape:connector-curvature="0" /><path
+ d="m 2930.307,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path144"
+ inkscape:connector-curvature="0" /><path
+ d="m 3298.8578,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path146"
+ inkscape:connector-curvature="0" /><path
+ d="m 3667.4085,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path148"
+ inkscape:connector-curvature="0" /><path
+ d="m 4035.9593,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path150"
+ inkscape:connector-curvature="0" /><path
+ d="m 4404.51,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path152"
+ inkscape:connector-curvature="0" /><path
+ d="m 4773.0608,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path154"
+ inkscape:connector-curvature="0" /><path
+ d="m 5141.6115,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path156"
+ inkscape:connector-curvature="0" /><path
+ d="m 5510.1623,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path158"
+ inkscape:connector-curvature="0" /><path
+ d="m 5878.713,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path160"
+ inkscape:connector-curvature="0" /><path
+ d="m 719.00254,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path162"
+ inkscape:connector-curvature="0" /><path
+ d="m 719.00254,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path164"
+ inkscape:connector-curvature="0" /><path
+ d="m 1087.5533,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path166"
+ inkscape:connector-curvature="0" /><path
+ d="m 1087.5533,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path168"
+ inkscape:connector-curvature="0" /><path
+ d="m 700.575,4735.9046 18.42754,0 0,-110.5653 36.85507,0 0,110.5653 18.42754,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path170"
+ inkscape:connector-curvature="0" /><path
+ d="m 774.28515,4680.6285 18.42754,0 0,110.5652 -18.42754,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path172"
+ inkscape:connector-curvature="0" /><path
+ d="m 792.71269,4735.9046 18.42753,0 0,92.1442 18.42754,-18.4341 18.42754,36.8551 18.42754,-36.8551 18.42753,36.8551 18.42754,-55.2761 18.42754,55.2761 18.42754,-18.421 18.42753,55.2761 18.42754,-55.2761 18.42754,18.421 18.4275,36.8551 18.4276,-92.1312 18.4275,55.2761 18.4275,-55.2761 0,-55.2891"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path174"
+ inkscape:connector-curvature="0" /><path
+ d="m 1069.1257,4735.9046 18.4276,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path176"
+ inkscape:connector-curvature="0" /><path
+ d="m 1142.8294,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path178"
+ inkscape:connector-curvature="0" /><path
+ d="m 1456.104,4735.9046 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.855,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.855,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path180"
+ inkscape:connector-curvature="0" /><path
+ d="m 1161.2634,4735.9046 294.8406,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path182"
+ inkscape:connector-curvature="0" /><path
+ d="m 6320.9739,4735.9046 18.421,0 0,92.1442 18.4341,-18.4341 18.421,73.7102 18.4341,-55.2761 18.421,36.855 18.434,-18.434 18.4211,36.8551 18.434,-36.8551 18.421,36.8551 18.4341,-36.8551 18.421,18.434 18.4341,-36.855 18.421,36.855 18.434,-36.855 18.4211,-18.4341 0,-73.7101 18.434,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path184"
+ inkscape:connector-curvature="0" /><path
+ d="m 4828.3369,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path186"
+ inkscape:connector-curvature="0" /><path
+ d="m 4846.7709,4735.9046 294.8406,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path188"
+ inkscape:connector-curvature="0" /><path
+ d="m 5196.8876,4680.6285 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path190"
+ inkscape:connector-curvature="0" /><path
+ d="m 5565.4384,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path192"
+ inkscape:connector-curvature="0" /><path
+ d="m 5933.9891,4680.6285 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path194"
+ inkscape:connector-curvature="0" /><path
+ d="m 5952.4232,4735.9046 294.8406,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path196"
+ inkscape:connector-curvature="0" /><path
+ d="m 6302.5399,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path198"
+ inkscape:connector-curvature="0" /><path
+ d="m 5786.5688,4735.9046 92.1442,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path200"
+ inkscape:connector-curvature="0" /><path
+ d="m 5805.0029,4791.1937 -36.8551,-110.5652"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path202"
+ inkscape:connector-curvature="0" /><path
+ d="m 5583.8724,4735.9046 165.8414,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path204"
+ inkscape:connector-curvature="0" /><path
+ d="m 5768.1478,4791.1937 -36.8551,-110.5652"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path206"
+ inkscape:connector-curvature="0" /><path
+ d="m 5215.3217,4735.9046 294.8406,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path208"
+ inkscape:connector-curvature="0" /><path
+ d="m 6247.2638,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path210"
+ inkscape:connector-curvature="0" /><path
+ d="m 6247.2638,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path212"
+ inkscape:connector-curvature="0" /><path
+ d="m 6615.8145,5104.4553 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path214"
+ inkscape:connector-curvature="0" /><path
+ d="m 6615.8145,4993.8901 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path216"
+ inkscape:connector-curvature="0" /><path
+ d="m 700.575,3925.0929 18.42754,0 0,-110.5652 36.85507,0 0,110.5652 18.42754,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path218"
+ inkscape:connector-curvature="0" /><path
+ d="m 774.28515,3869.8168 18.42754,0 0,110.5652 -18.42754,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path220"
+ inkscape:connector-curvature="0" /><path
+ d="m 1142.8294,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path222"
+ inkscape:connector-curvature="0" /><path
+ d="m 792.71269,3925.0929 18.42753,0 0,110.5652 18.42754,-36.855 18.42754,18.434 18.42754,-36.8551 18.42753,36.8551 0,-92.1442 202.70293,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path224"
+ inkscape:connector-curvature="0" /><path
+ d="m 1161.2634,3925.0929 110.5653,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.855,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.855,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path226"
+ inkscape:connector-curvature="0" /><path
+ d="m 4220.2346,3925.0929 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 55.2891,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path228"
+ inkscape:connector-curvature="0" /><path
+ d="m 4478.2202,3925.0929 294.8406,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path230"
+ inkscape:connector-curvature="0" /><path
+ d="m 5952.4232,3925.0929 128.9862,0 0,73.7102 18.4341,36.855 18.421,-18.421 18.434,36.8551 18.4211,-36.8551 18.434,18.421 18.421,-36.855 18.4341,18.434 18.421,-36.8551 0,-55.2891 18.4341,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path232"
+ inkscape:connector-curvature="0" /><path
+ d="m 6302.5399,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path234"
+ inkscape:connector-curvature="0" /><path
+ d="m 6320.9739,3925.0929 18.421,0 0,73.7102 18.4341,36.855 18.421,-36.855 18.4341,36.855 18.421,-18.421 18.434,0 18.4211,-36.8551 18.434,55.2761 18.421,-18.421 0,36.8551 18.4341,-18.4341 18.421,18.4341 18.4341,-36.8551 18.421,18.421 18.434,-55.2761 18.4211,18.4211 0,-73.7102 18.434,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path236"
+ inkscape:connector-curvature="0" /><path
+ d="m 5933.9891,3869.8168 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path238"
+ inkscape:connector-curvature="0" /><path
+ d="m 5786.5688,3925.0929 92.1442,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path240"
+ inkscape:connector-curvature="0" /><path
+ d="m 5805.0029,3980.382 -36.8551,-110.5652"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path242"
+ inkscape:connector-curvature="0" /><path
+ d="m 5768.1478,3980.382 -36.8551,-110.5652"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path244"
+ inkscape:connector-curvature="0" /><path
+ d="m 4828.3369,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path246"
+ inkscape:connector-curvature="0" /><path
+ d="m 5583.8724,3925.0929 165.8414,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path248"
+ inkscape:connector-curvature="0" /><path
+ d="m 4846.7709,3925.0929 294.8406,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path250"
+ inkscape:connector-curvature="0" /><path
+ d="m 5196.8876,3869.8168 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path252"
+ inkscape:connector-curvature="0" /><path
+ d="m 5215.3217,3925.0929 294.8406,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path254"
+ inkscape:connector-curvature="0" /><path
+ d="m 5565.4384,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path256"
+ inkscape:connector-curvature="0" /><path
+ d="m 6247.2638,4293.6437 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path258"
+ inkscape:connector-curvature="0" /><path
+ d="m 6247.2638,4183.0784 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path260"
+ inkscape:connector-curvature="0" /><path
+ d="m 6615.8145,4293.6437 0,-73.7102"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path262"
+ inkscape:connector-curvature="0" /><path
+ d="m 6615.8145,4183.0784 0,-73.7101"
+ style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path264"
+ inkscape:connector-curvature="0" /><text
+ y="-4035.6582"
+ x="1621.9453"
+ id="text268"
+ style="font-variant:normal;font-weight:normal;font-size:61.42512512px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan270"
+ sodipodi:role="line"
+ y="-4035.6582"
+ x="1621.9453 1642.3999 1676.5522">(1)</tspan></text>
+<text
+ y="-4127.7959"
+ x="4199.7334"
+ id="text272"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan274"
+ sodipodi:role="line"
+ y="-4127.7959"
+ x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732">874569101211322631262</tspan><tspan
+ id="tspan276"
+ sodipodi:role="line"
+ y="-4238.3613"
+ x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732">271270267268269272273275274266265263264262</tspan><tspan
+ id="tspan278"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164">492315610111278</tspan><tspan
+ id="tspan280"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296">492315610111278</tspan><tspan
+ id="tspan282"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="841.81781 882.8006 923.78326">524</tspan><tspan
+ id="tspan284"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="841.81781 882.8006 923.78326">261</tspan><tspan
+ id="tspan286"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="1210.3684 1251.3512 1292.3342">525</tspan><tspan
+ id="tspan288"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="1210.3684 1251.3512 1292.3342">262</tspan><tspan
+ id="tspan290"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="6022.0161 6062.999">22</tspan><tspan
+ id="tspan292"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="6022.0161 6062.999">22</tspan><tspan
+ id="tspan294"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="6390.5669 6431.5498">23</tspan><tspan
+ id="tspan296"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="6390.5669 6431.5498">23</tspan><tspan
+ id="tspan298"
+ sodipodi:role="line"
+ y="-4238.3623"
+ x="6001.5244 6042.5068 6083.4902">285</tspan><tspan
+ id="tspan300"
+ sodipodi:role="line"
+ y="-4127.7964"
+ x="6022.0156 6062.9985">22</tspan><tspan
+ id="tspan302"
+ sodipodi:role="line"
+ y="-4238.3623"
+ x="6370.0747 6411.0571 6452.04">286</tspan><tspan
+ id="tspan304"
+ sodipodi:role="line"
+ y="-4127.7964"
+ x="6390.5664 6431.5493">23</tspan><tspan
+ id="tspan306"
+ sodipodi:role="line"
+ y="-4459.4922"
+ x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365">1st field</tspan><tspan
+ id="tspan308"
+ sodipodi:role="line"
+ y="-3648.6809"
+ x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463">2nd field</tspan></text>
+<text
+ y="-4127.7959"
+ x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732"
+ id="text3632"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3634"
+ sodipodi:role="line"
+ y="-4127.7959"
+ x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732">874569101211322631262</tspan></text>
+<text
+ y="-4238.3613"
+ x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732"
+ id="text3636"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3638"
+ sodipodi:role="line"
+ y="-4238.3613"
+ x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732">271270267268269272273275274266265263264262</tspan></text>
+<text
+ y="-5049.1729"
+ x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164"
+ id="text3640"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3642"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164">492315610111278</tspan></text>
+<text
+ y="-4938.6074"
+ x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296"
+ id="text3644"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3646"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296">492315610111278</tspan></text>
+<text
+ y="-5049.1729"
+ x="841.81781 882.8006 923.78326"
+ id="text3648"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3650"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="841.81781 882.8006 923.78326">524</tspan></text>
+<text
+ y="-4938.6074"
+ x="841.81781 882.8006 923.78326"
+ id="text3652"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3654"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="841.81781 882.8006 923.78326">261</tspan></text>
+<text
+ y="-5049.1729"
+ x="1210.3684 1251.3512 1292.3342"
+ id="text3656"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3658"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="1210.3684 1251.3512 1292.3342">525</tspan></text>
+<text
+ y="-4938.6074"
+ x="1210.3684 1251.3512 1292.3342"
+ id="text3660"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3662"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="1210.3684 1251.3512 1292.3342">262</tspan></text>
+<text
+ y="-5049.1729"
+ x="6022.0161 6062.999"
+ id="text3664"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3666"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="6022.0161 6062.999">22</tspan></text>
+<text
+ y="-4938.6074"
+ x="6022.0161 6062.999"
+ id="text3668"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3670"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="6022.0161 6062.999">22</tspan></text>
+<text
+ y="-5049.1729"
+ x="6390.5669 6431.5498"
+ id="text3672"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3674"
+ sodipodi:role="line"
+ y="-5049.1729"
+ x="6390.5669 6431.5498">23</tspan></text>
+<text
+ y="-4938.6074"
+ x="6390.5669 6431.5498"
+ id="text3676"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3678"
+ sodipodi:role="line"
+ y="-4938.6074"
+ x="6390.5669 6431.5498">23</tspan></text>
+<text
+ y="-4238.3623"
+ x="6001.5244 6042.5068 6083.4902"
+ id="text3680"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3682"
+ sodipodi:role="line"
+ y="-4238.3623"
+ x="6001.5244 6042.5068 6083.4902">285</tspan></text>
+<text
+ y="-4127.7964"
+ x="6022.0156 6062.9985"
+ id="text3684"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3686"
+ sodipodi:role="line"
+ y="-4127.7964"
+ x="6022.0156 6062.9985">22</tspan></text>
+<text
+ y="-4238.3623"
+ x="6370.0747 6411.0571 6452.04"
+ id="text3688"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3690"
+ sodipodi:role="line"
+ y="-4238.3623"
+ x="6370.0747 6411.0571 6452.04">286</tspan></text>
+<text
+ y="-4127.7964"
+ x="6390.5664 6431.5493"
+ id="text3692"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3694"
+ sodipodi:role="line"
+ y="-4127.7964"
+ x="6390.5664 6431.5493">23</tspan></text>
+<text
+ y="-4459.4922"
+ x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365"
+ id="text3696"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3698"
+ sodipodi:role="line"
+ y="-4459.4922"
+ x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365">1st field</tspan></text>
+<text
+ y="-3648.6809"
+ x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463"
+ id="text3700"
+ style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"><tspan
+ id="tspan3702"
+ sodipodi:role="line"
+ y="-3648.6809"
+ x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463">2nd field</tspan></text>
+</g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/vbi_625.svg b/Documentation/media/uapi/v4l/vbi_625.svg
new file mode 100644
index 000000000000..c117ddb7bf7e
--- /dev/null
+++ b/Documentation/media/uapi/v4l/vbi_625.svg
@@ -0,0 +1,858 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="209.46608mm"
+ height="51.576824mm"
+ viewBox="0 0 742.20265 182.75252"
+ sodipodi:docname="vbi_625.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview4"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="1.5350601"
+ inkscape:cx="288.91482"
+ inkscape:cy="170.67667"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g10"
+ units="mm" /><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath20"><path
+ d="m 0,0 5950,0 0,4546 L 0,4546 0,0 Z m 0,4546 5950,0 0,1 -5950,0 0,-1 z m 0,1 2211,0 0,1 -2211,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2215,0 0,1 -2215,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2219,0 0,1 -2219,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2223,0 0,1 -2223,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2227,0 0,1 -2227,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2231,0 0,1 -2231,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2235,0 0,1 -2235,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2239,0 0,1 -2239,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2240,0 0,1 -2240,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2236,0 0,1 -2236,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2232,0 0,1 -2232,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2228,0 0,1 -2228,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2224,0 0,1 -2224,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2220,0 0,1 -2220,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2216,0 0,1 -2216,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2212,0 0,1 -2212,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2208,0 0,1 -2208,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,3854 -5950,0 0,-3854 z"
+ id="path22"
+ inkscape:connector-curvature="0" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath98"><path
+ d="m 0,0 5950,0 0,3922 L 0,3922 0,0 Z m 0,3922 5950,0 0,1 -5950,0 0,-1 z m 0,1 2209,0 0,1 -2209,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2213,0 0,1 -2213,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2217,0 0,1 -2217,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2221,0 0,1 -2221,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2225,0 0,1 -2225,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2229,0 0,1 -2229,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2233,0 0,1 -2233,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2237,0 0,1 -2237,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2237,0 0,1 -2237,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2233,0 0,1 -2233,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2229,0 0,1 -2229,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2225,0 0,1 -2225,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2221,0 0,1 -2221,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2217,0 0,1 -2217,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2213,0 0,1 -2213,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2209,0 0,1 -2209,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,4478 -5950,0 0,-4478 z"
+ id="path100"
+ inkscape:connector-curvature="0" /></clipPath></defs><g
+ id="g10"
+ inkscape:groupmode="layer"
+ inkscape:label="vbi_625"
+ transform="matrix(0.125,0,0,-0.125,-87.571875,638.69874)"><g
+ id="g12"
+ transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+ style=""><path
+ d="m 2132.25,4598.15 0,-85.05"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path14"
+ inkscape:connector-curvature="0" /></g><g
+ id="g16"
+ transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+ style=""><g
+ id="g18"
+ clip-path="url(#clipPath20)"
+ style=""><path
+ d="m 2132.25,4555.63 113.4,0"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path24"
+ inkscape:connector-curvature="0" /></g></g><path
+ inkscape:connector-curvature="0"
+ id="path28"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2660.3649,4819.881 49.3132,12.3283 -49.3132,12.3283 0,-24.6566" /><path
+ inkscape:connector-curvature="0"
+ id="path30"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2660.3649,4819.881 49.3132,12.3283 -49.3132,12.3283 0,-24.6566 z" /><path
+ inkscape:connector-curvature="0"
+ id="path32"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1828.6151,4924.6651 0,73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path34"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2198.4643,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path36"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2568.3136,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path38"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2938.1628,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path40"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3308.012,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path42"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3677.8612,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path44"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4047.7105,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path46"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4417.5597,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path48"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4787.4089,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path50"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5157.2581,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path52"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5527.1073,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path54"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5896.9566,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path56"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1458.7659,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path58"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1828.6151,5035.6199 0,73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path60"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2198.4643,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path62"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2568.3136,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path64"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2938.1628,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path66"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3308.012,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path68"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3677.8612,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path70"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4047.7105,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path72"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4417.5597,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path74"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4787.4089,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path76"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5157.2581,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path78"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5527.1073,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path80"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5896.9566,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path82"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1458.7659,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path84"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 719.06744,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path86"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 719.06744,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path88"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1088.9167,4998.635 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path90"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1088.9167,5109.5897 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path92"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2568.3136,4074.0119 0,-110.9548" /><g
+ id="g94"
+ transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+ style=""><g
+ id="g96"
+ clip-path="url(#clipPath98)"
+ style=""><path
+ d="m 2132.25,3931.93 113.4,0"
+ style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path102"
+ inkscape:connector-curvature="0" /></g></g><path
+ inkscape:connector-curvature="0"
+ id="path106"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2660.365,4006.2129 49.3132,12.3283 -49.3132,12.3283 0,-24.6566" /><path
+ inkscape:connector-curvature="0"
+ id="path108"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2660.365,4006.2129 49.3132,12.3283 -49.3132,12.3283 0,-24.6566 z" /><path
+ inkscape:connector-curvature="0"
+ id="path110"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6266.806,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path112"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5896.9567,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path114"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5527.1075,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path116"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5157.2583,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path118"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4787.409,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path120"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4417.5598,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path122"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4047.7106,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path124"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3677.8613,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path126"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3308.0121,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path128"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2938.1629,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path130"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2568.3136,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path132"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2198.4644,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path134"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1828.6152,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path136"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1458.7659,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path138"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6266.806,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path140"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5896.9567,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path142"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5527.1075,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path144"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5157.2583,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path146"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4787.409,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path148"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4417.5598,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path150"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4047.7106,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path152"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3677.8613,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path154"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 3308.0121,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path156"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2938.1629,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path158"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2568.3136,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path160"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 2198.4644,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path162"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1828.6152,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path164"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1458.7659,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path166"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 719.06746,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path168"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 719.06746,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path170"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1088.9167,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path172"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1088.9167,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path174"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1144.3876,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path176"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1070.4242,4739.7407 18.4925,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path178"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 700.575,4739.7407 18.49246,0 0,-110.9548 36.98492,0 0,110.9548 18.49247,0" /><path
+ inkscape:connector-curvature="0"
+ id="path180"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 809.886,4739.7407 3.28754,0" /><path
+ inkscape:connector-curvature="0"
+ id="path182"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 809.886,4739.7407 3.28754,0" /><path
+ inkscape:connector-curvature="0"
+ id="path184"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 774.54485,4684.2698 18.49246,0 0,110.9548 -18.49246,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path186"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 793.03731,4739.7407 18.49246,0 18.49246,73.9698 18.49246,-36.9849 18.49246,92.4688 18.49247,-55.4839 18.49246,18.499 18.49246,-36.9849 18.49246,55.4708 18.49246,-73.9698 18.49246,55.4839 18.49247,-73.9699 18.49241,110.9548 18.4925,-92.4688 18.4925,55.4839 18.4924,-55.4839 0,-36.9849" /><path
+ inkscape:connector-curvature="0"
+ id="path188"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1162.8865,4739.7407 18.486,0 0,92.4688 18.499,-18.499 18.4859,36.9849 18.499,-36.9849 18.4859,36.9849 18.499,-55.4708 18.4859,55.4708 18.499,-18.4859 18.486,55.4708 18.499,-55.4708 18.4859,18.4859 18.499,36.9849 18.4859,-73.9698 18.499,36.9849 18.4859,-55.4708 0,-55.4839 18.499,0 0,-110.9548 36.985,0 0,110.9548 18.4859,0 0,55.4839 18.499,36.9849 18.4859,-36.9849 18.499,55.4708 18.4859,-18.4859 18.499,55.4708 18.486,-18.4859 0,-129.4537 18.4989,0 0,-110.9548 18.486,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.985,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.486,0 0,110.9548 166.4386,0 0,-110.9548 18.486,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 36.9849,0 0,110.9548 332.8643,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path190"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 700.575,3926.0723 18.49246,0 0,-110.9547 36.98492,0 0,110.9547 18.49247,0" /><path
+ inkscape:connector-curvature="0"
+ id="path192"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 774.54485,3870.6015 18.49246,0 0,110.9547 -18.49246,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path194"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 793.03731,3926.0723 18.49246,0 0,92.4689 18.49246,-36.985 18.49246,73.9699 18.49246,-73.9699 18.49247,73.9699 18.49246,-36.9849 18.49246,18.4859 18.49246,-73.9698 18.49246,55.4839 18.49246,-18.499 18.49247,36.9849 18.49241,-73.9698 18.4925,92.4688 18.4925,-92.4688 18.4924,55.4839 0,-92.4689" /><path
+ inkscape:connector-curvature="0"
+ id="path196"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1070.4242,3926.0723 18.4925,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path198"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1144.3876,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path200"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1162.8865,3926.0723 18.486,0 0,55.4839 18.499,92.4558 18.4859,-55.4708 36.9849,36.9849 18.499,-55.4839 18.4859,18.499 18.499,-36.985 18.486,55.4709 18.499,-18.4859 18.4859,-36.985 18.499,18.486 18.4859,36.9849 18.499,-36.9849 18.4859,36.9849 0,-110.9548 18.499,0 0,-110.9547 18.486,0 0,110.9547 166.4386,0 0,-110.9547 18.486,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.985,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.486,0 0,110.9547 166.4386,0 0,-110.9547 18.486,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 351.3633,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path202"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5453.1376,4795.2246 -36.9849,-110.9548" /><path
+ inkscape:connector-curvature="0"
+ id="path204"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5434.6387,4739.7407 92.4688,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path206"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5582.5784,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path208"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5601.0773,4739.7407 295.8794,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path210"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5952.4276,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path212"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5970.9266,4739.7407 129.4407,0 0,147.9396 18.499,-36.9849 18.4859,36.9849 18.499,-36.9849 18.4859,18.499 18.499,-36.9849 18.4859,36.9849 18.499,-36.9849 18.486,-18.499 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path214"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4842.8799,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path216"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4861.3789,4739.7407 295.8794,0 0,-110.9548 36.9849,0 0,110.9548 18.4859,0" /><path
+ inkscape:connector-curvature="0"
+ id="path218"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5212.7291,4684.2698 18.4925,0 0,110.9548 -18.4925,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path220"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5231.2281,4739.7407 166.4256,0" /><path
+ inkscape:connector-curvature="0"
+ id="path222"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5416.1527,4795.2246 -36.9849,-110.9548" /><path
+ inkscape:connector-curvature="0"
+ id="path224"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4473.0307,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path226"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4491.5296,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path228"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4842.8799,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path230"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4861.3789,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.4859,0" /><path
+ inkscape:connector-curvature="0"
+ id="path232"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5212.7291,3870.6015 18.4925,0 0,110.9547 -18.4925,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path234"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5416.1527,3981.5562 -36.9849,-110.9547" /><path
+ inkscape:connector-curvature="0"
+ id="path236"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5231.2281,3926.0723 166.4256,0" /><path
+ inkscape:connector-curvature="0"
+ id="path238"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5453.1376,3981.5562 -36.9849,-110.9547" /><path
+ inkscape:connector-curvature="0"
+ id="path240"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5434.6387,3926.0723 92.4688,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path242"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5582.5784,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path244"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5601.0773,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+ inkscape:connector-curvature="0"
+ id="path246"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5952.4276,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path248"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 5970.9266,3926.0723 18.4859,0 0,73.9699 18.499,36.9849 18.4859,-36.9849 18.499,36.9849 18.486,-18.4859 18.4989,0 18.486,-36.985 18.499,55.4709 18.4859,-18.4859 0,36.9849 18.499,-18.499 18.4859,18.499 18.499,-36.9849 18.4859,18.4859 18.499,-55.4709 18.486,18.486 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path250"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6248.307,4739.7407 18.499,0 0,-110.9548 36.9849,0 0,110.9548 18.4859,0" /><path
+ inkscape:connector-curvature="0"
+ id="path252"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6248.307,3926.0723 18.499,0 0,-110.9547 36.9849,0 0,110.9547 18.4859,0" /><path
+ inkscape:connector-curvature="0"
+ id="path254"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6322.2768,3870.6015 18.4925,0 0,110.9547 -18.4925,0 0,-110.9547 z" /><path
+ inkscape:connector-curvature="0"
+ id="path256"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6322.2768,4684.2698 18.4925,0 0,110.9548 -18.4925,0 0,-110.9548 z" /><path
+ inkscape:connector-curvature="0"
+ id="path258"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6340.7758,4739.7407 18.4859,0 0,55.4839 18.499,55.4708 18.486,-92.4558 18.4989,55.4709 18.486,0 18.499,55.4839 18.4859,-73.9698 18.499,36.9849 18.4859,-36.9849 36.985,73.9698 18.4989,-36.9849 18.486,36.9849 18.499,-55.4839 18.4859,36.9849 0,-110.9547 18.499,0" /><path
+ inkscape:connector-curvature="0"
+ id="path260"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6340.7758,3926.0723 18.4859,0 0,129.4538 18.499,-18.499 18.486,18.499 18.4989,-36.9849 18.486,18.4859 18.499,-36.9849 18.4859,18.499 18.499,-18.499 18.4859,55.4839 18.499,-18.499 18.486,36.9849 18.4989,-73.9698 18.486,55.4839 18.499,-55.4839 18.4859,36.9849 0,-110.9548 18.499,0" /><path
+ inkscape:connector-curvature="0"
+ id="path262"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6636.6552,4184.9668 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path264"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6636.6552,4295.9216 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path266"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6266.806,4998.6351 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path268"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6266.806,5109.5899 0,-73.9699" /><path
+ inkscape:connector-curvature="0"
+ id="path270"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6636.6552,4998.6351 0,-73.9698" /><path
+ inkscape:connector-curvature="0"
+ id="path272"
+ style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 6636.6552,5109.5899 0,-73.9699" /><text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text276"
+ x="3550.4165"
+ y="-4462.3472"><tspan
+ x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+ y="-4462.3472"
+ sodipodi:role="line"
+ id="tspan278">1st field</tspan><tspan
+ x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan280">1456783231231131022</tspan><tspan
+ x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan282">1456783262562462322</tspan><tspan
+ x="842.29962 883.42694 924.55408"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan284">308</tspan><tspan
+ x="842.29962 883.42694 924.55408"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan286">621</tspan><tspan
+ x="1212.1489 1253.276 1294.4033"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan288">309</tspan><tspan
+ x="1212.1489 1253.276 1294.4033"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan290">622</tspan><tspan
+ x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+ y="-3648.6792"
+ sodipodi:role="line"
+ id="tspan292">2nd field</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:61.64153671px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text294"
+ x="2734.751"
+ y="-4037.021"><tspan
+ x="2734.751 2755.2776 2789.5503"
+ y="-4037.021"
+ sodipodi:role="line"
+ id="tspan296">(1)</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text298"
+ x="4951.772"
+ y="-4129.4834"><tspan
+ x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan300">765432313312311</tspan><tspan
+ x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan302">336335321320319318317316315314313312311</tspan><tspan
+ x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan304">182223309</tspan><tspan
+ x="842.30634 883.43323 924.56055"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan306">309</tspan><tspan
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan308">310</tspan><tspan
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan310">310</tspan><tspan
+ x="6410.605 6451.7319"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan312">24</tspan><tspan
+ x="6390.041 6431.1685 6472.2954"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan314">337</tspan><tspan
+ x="6040.7559 6081.8833"
+ y="-4943.1504"
+ sodipodi:role="line"
+ id="tspan316">23</tspan><tspan
+ x="6040.7559 6081.8833"
+ y="-5054.106"
+ sodipodi:role="line"
+ id="tspan318">23</tspan><tspan
+ x="6410.605 6451.7324"
+ y="-4943.1504"
+ sodipodi:role="line"
+ id="tspan320">24</tspan><tspan
+ x="6410.605 6451.7324"
+ y="-5054.106"
+ sodipodi:role="line"
+ id="tspan322">24</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3671"
+ x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+ y="-4462.3472"><tspan
+ x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+ y="-4462.3472"
+ sodipodi:role="line"
+ id="tspan3673">1st field</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3675"
+ x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+ y="-4943.1509"><tspan
+ x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan3677">1456783231231131022</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3679"
+ x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+ y="-5054.1064"><tspan
+ x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan3681">1456783262562462322</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3683"
+ x="842.29962 883.42694 924.55408"
+ y="-4943.1509"><tspan
+ x="842.29962 883.42694 924.55408"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan3685">308</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3687"
+ x="842.29962 883.42694 924.55408"
+ y="-5054.1064"><tspan
+ x="842.29962 883.42694 924.55408"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan3689">621</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3691"
+ x="1212.1489 1253.276 1294.4033"
+ y="-4943.1509"><tspan
+ x="1212.1489 1253.276 1294.4033"
+ y="-4943.1509"
+ sodipodi:role="line"
+ id="tspan3693">309</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3695"
+ x="1212.1489 1253.276 1294.4033"
+ y="-5054.1064"><tspan
+ x="1212.1489 1253.276 1294.4033"
+ y="-5054.1064"
+ sodipodi:role="line"
+ id="tspan3697">622</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text3699"
+ x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+ y="-3648.6792"><tspan
+ x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+ y="-3648.6792"
+ sodipodi:role="line"
+ id="tspan3701">2nd field</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4083"
+ x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4129.4834"><tspan
+ x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan4085">765432313312311</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4087"
+ x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4240.4385"><tspan
+ x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan4089">336335321320319318317316315314313312311</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4091"
+ x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+ y="-4129.4834"><tspan
+ x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan4093">182223309</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4095"
+ x="842.30634 883.43323 924.56055"
+ y="-4240.4385"><tspan
+ x="842.30634 883.43323 924.56055"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan4097">309</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4099"
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4129.4834"><tspan
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan4101">310</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4103"
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4240.4385"><tspan
+ x="1212.1553 1253.2826 1294.4099"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan4105">310</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4107"
+ x="6410.605 6451.7319"
+ y="-4129.4834"><tspan
+ x="6410.605 6451.7319"
+ y="-4129.4834"
+ sodipodi:role="line"
+ id="tspan4109">24</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4111"
+ x="6390.041 6431.1685 6472.2954"
+ y="-4240.4385"><tspan
+ x="6390.041 6431.1685 6472.2954"
+ y="-4240.4385"
+ sodipodi:role="line"
+ id="tspan4113">337</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4115"
+ x="6040.7559 6081.8833"
+ y="-4943.1504"><tspan
+ x="6040.7559 6081.8833"
+ y="-4943.1504"
+ sodipodi:role="line"
+ id="tspan4117">23</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4119"
+ x="6040.7559 6081.8833"
+ y="-5054.106"><tspan
+ x="6040.7559 6081.8833"
+ y="-5054.106"
+ sodipodi:role="line"
+ id="tspan4121">23</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4123"
+ x="6410.605 6451.7324"
+ y="-4943.1504"><tspan
+ x="6410.605 6451.7324"
+ y="-4943.1504"
+ sodipodi:role="line"
+ id="tspan4125">24</tspan></text>
+<text
+ transform="scale(1,-1)"
+ style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ id="text4127"
+ x="6410.605 6451.7324"
+ y="-5054.106"><tspan
+ x="6410.605 6451.7324"
+ y="-5054.106"
+ sodipodi:role="line"
+ id="tspan4129">24</tspan></text>
+</g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/vbi_hsync.svg b/Documentation/media/uapi/v4l/vbi_hsync.svg
new file mode 100644
index 000000000000..4d5c0b4f146e
--- /dev/null
+++ b/Documentation/media/uapi/v4l/vbi_hsync.svg
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ xml:space="preserve"
+ width="192.39857mm"
+ height="146.83536mm"
+ viewBox="0 0 681.72724 520.28277"
+ sodipodi:docname="vbi_hsync.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="997"
+ id="namedview4"
+ showgrid="false"
+ inkscape:zoom="1.5350601"
+ inkscape:cx="131.95463"
+ inkscape:cy="428.88132"
+ inkscape:window-x="1920"
+ inkscape:window-y="30"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g10"
+ units="mm"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" /><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath30"><path
+ d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 187.184,836.05 0,-19.278 48.517,0 -38.556,9.639 38.556,9.639 -48.517,0 z m 689.189,-19.278 0,19.278 -48.516,0 38.556,-9.639 -38.556,-9.639 48.516,0 z"
+ id="path32"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath52"><path
+ d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 804.08,79.3887 0,19.2778 -48.516,0 38.556,-9.6389 -38.556,-9.6389 48.516,0 z m -703.647,19.2778 0,-19.2778 48.517,0 -38.556,9.6389 38.556,9.6389 -48.517,0 z"
+ id="path54"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath94"><path
+ d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 471.535,195.057 0,19.278 -48.516,0 38.555,-9.639 -38.555,-9.639 48.516,0 z m -284.351,19.278 0,-19.278 48.517,0 -38.556,9.639 38.556,9.639 -48.517,0 z"
+ id="path96"
+ inkscape:connector-curvature="0"
+ style="clip-rule:evenodd" /></clipPath></defs><g
+ id="g10"
+ inkscape:groupmode="layer"
+ inkscape:label="vbi_hsync"
+ transform="matrix(1.25,0,0,-1.25,-0.3625824,520.79867)"><g
+ id="g14"
+ transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path16"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="M 32.9604,580.617 4.04346,493.866" /><path
+ inkscape:connector-curvature="0"
+ id="path18"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 192.004,855.328 0,-665.091" /><path
+ inkscape:connector-curvature="0"
+ id="path20"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 466.715,392.656 0,-202.419" /><path
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 799.261,508.324 0,-433.7549" /><path
+ inkscape:connector-curvature="0"
+ id="path24"
+ style="fill:none;stroke:#000000;stroke-width:4.81949997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 857.095,537.241 231.335,0" /></g><g
+ id="g26"
+ transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+ style=""><g
+ clip-path="url(#clipPath30)"
+ id="g28"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path34"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 871.553,826.411 -679.549,0" /></g></g><g
+ id="g36"
+ transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path38"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 827.857,816.772 38.556,9.639 -38.556,9.639 0,-19.278" /><path
+ inkscape:connector-curvature="0"
+ id="path40"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 827.857,816.772 38.556,9.639 -38.556,9.639 0,-19.278 z" /><path
+ inkscape:connector-curvature="0"
+ id="path42"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 235.701,836.05 -38.556,-9.639 38.556,-9.639 0,19.278" /><path
+ inkscape:connector-curvature="0"
+ id="path44"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 235.701,836.05 -38.556,-9.639 38.556,-9.639 0,19.278 z" /><path
+ inkscape:connector-curvature="0"
+ id="path46"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1073.97,493.866 28.92,86.751" /></g><g
+ id="g48"
+ transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+ style=""><g
+ clip-path="url(#clipPath52)"
+ id="g50"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path56"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 105.253,89.0276 694.008,0" /></g></g><path
+ d="m 52.91205,34.475403 -13.891817,-3.472918 13.891817,-3.472918 0,6.945836"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path60"
+ inkscape:connector-curvature="0" /><path
+ d="m 52.91205,34.475403 -13.891817,-3.472918 13.891817,-3.472918 0,6.945836 z"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path62"
+ inkscape:connector-curvature="0" /><path
+ d="m 271.4765,27.529567 13.89182,3.472918 -13.89182,3.472918 0,-6.945836"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path64"
+ inkscape:connector-curvature="0" /><path
+ d="m 271.4765,27.529567 13.89182,3.472918 -13.89182,3.472918 0,-6.945836 z"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path66"
+ inkscape:connector-curvature="0" /><path
+ d="m 5.9113292,192.49483 31.2565888,0 0,-10.41887 26.046978,0 10.418863,-93.769765 88.560511,0 10.41887,93.769765 10.41886,0"
+ style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path68"
+ inkscape:connector-curvature="0" /><path
+ d="m 162.19427,88.306195 260.47086,0"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path70"
+ inkscape:connector-curvature="0" /><path
+ d="m 37.167918,182.07596 0,-156.282907"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path72"
+ inkscape:connector-curvature="0" /><path
+ d="m 235.12632,182.07596 52.09431,0 0,10.41887 20.83773,0 10.41886,208.3769 83.35162,0"
+ style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path74"
+ inkscape:connector-curvature="0" /><path
+ d="m 391.4089,192.49483 31.25623,0"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path76"
+ inkscape:connector-curvature="0" /><path
+ d="m 401.82884,400.87173 20.83629,0"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path78"
+ inkscape:connector-curvature="0" /><path
+ d="m 328.89608,192.49483 10.41887,208.3769"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path80"
+ inkscape:connector-curvature="0" /><path
+ d="m 349.73381,192.49483 10.41886,208.3769"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path82"
+ inkscape:connector-curvature="0" /><path
+ d="m 370.57262,192.49483 10.41634,208.3769"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path84"
+ inkscape:connector-curvature="0" /><path
+ d="m 396.61887,385.24541 10.41995,31.25623"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path86"
+ inkscape:connector-curvature="0" /><path
+ d="m 183.032,135.19126 52.09432,0 0,93.76977 -52.09432,0 0,-93.76977 z"
+ style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path88"
+ inkscape:connector-curvature="0" /><g
+ id="g90"
+ transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+ style=""><g
+ clip-path="url(#clipPath94)"
+ id="g92"
+ style=""><path
+ inkscape:connector-curvature="0"
+ id="path98"
+ style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ d="m 192.004,204.696 274.711,0" /></g></g><path
+ d="m 84.168639,76.151036 -13.891817,-3.472955 13.891817,-3.472954 0,6.945909"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path102"
+ inkscape:connector-curvature="0" /><path
+ d="m 84.168639,76.151036 -13.891817,-3.472955 13.891817,-3.472954 0,6.945909 z"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path104"
+ inkscape:connector-curvature="0" /><path
+ d="m 151.65975,69.205127 13.89146,3.472954 -13.89146,3.472955 0,-6.945909"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path106"
+ inkscape:connector-curvature="0" /><path
+ d="m 151.65975,69.205127 13.89146,3.472954 -13.89146,3.472955 0,-6.945909 z"
+ style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+ id="path108"
+ inkscape:connector-curvature="0" /><text
+ id="text112"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="438.29504"
+ y="-187.28558"><tspan
+ id="tspan114"
+ sodipodi:role="line"
+ y="-187.28558"
+ x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234">Black Level</tspan><tspan
+ id="tspan116"
+ sodipodi:role="line"
+ y="-83.096947"
+ x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636">Sync Level</tspan><tspan
+ id="tspan118"
+ sodipodi:role="line"
+ y="-395.66284"
+ x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533">White Level</tspan></text>
+<text
+ id="text120"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="159.88258"
+ y="-270.63647"><tspan
+ id="tspan122"
+ sodipodi:role="line"
+ y="-270.63647"
+ x="159.88258 172.61443 179.55339 186.49236 198.07812 209.66391">offset</tspan></text>
+<text
+ id="text124"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="46.973549"
+ y="-46.630745"><tspan
+ id="tspan126"
+ sodipodi:role="line"
+ y="-46.630745"
+ x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319">Line synchr. pulse</tspan><tspan
+ id="tspan128"
+ sodipodi:role="line"
+ y="-4.9552913"
+ x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788">Line blanking</tspan></text>
+<text
+ id="text3473"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319"
+ y="-46.630745"><tspan
+ id="tspan3475"
+ sodipodi:role="line"
+ y="-46.630745"
+ x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319">Line synchr. pulse</tspan></text>
+<text
+ id="text3477"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788"
+ y="-4.9552913"><tspan
+ id="tspan3479"
+ sodipodi:role="line"
+ y="-4.9552913"
+ x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788">Line blanking</tspan></text>
+<text
+ id="text3607"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234"
+ y="-187.28558"><tspan
+ id="tspan3609"
+ sodipodi:role="line"
+ y="-187.28558"
+ x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234">Black Level</tspan></text>
+<text
+ id="text3611"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636"
+ y="-83.096947"><tspan
+ id="tspan3613"
+ sodipodi:role="line"
+ y="-83.096947"
+ x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636">Sync Level</tspan></text>
+<text
+ id="text3615"
+ style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+ transform="scale(1,-1)"
+ x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533"
+ y="-395.66284"><tspan
+ id="tspan3617"
+ sodipodi:role="line"
+ y="-395.66284"
+ x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533">White Level</tspan></text>
+</g></svg> \ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/vidioc-g-selection.rst b/Documentation/media/uapi/v4l/vidioc-g-selection.rst
index 3145a9166bad..deb1f6fb473b 100644
--- a/Documentation/media/uapi/v4l/vidioc-g-selection.rst
+++ b/Documentation/media/uapi/v4l/vidioc-g-selection.rst
@@ -129,8 +129,8 @@ Selection targets and flags are documented in
.. _sel-const-adjust:
-.. figure:: vidioc-g-selection_files/constraints.*
- :alt: constraints.png
+.. figure:: constraints.*
+ :alt: constraints.pdf / constraints.svg
:align: center
Size adjustments with constraint flags.
diff --git a/Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.png b/Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.png
deleted file mode 100644
index 20228d2c5504..000000000000
--- a/Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.png
+++ /dev/null
Binary files differ
diff --git a/Documentation/media/v4l-drivers/bttv.rst b/Documentation/media/v4l-drivers/bttv.rst
index 7abc1c9a261b..bc63b12efafd 100644
--- a/Documentation/media/v4l-drivers/bttv.rst
+++ b/Documentation/media/v4l-drivers/bttv.rst
@@ -304,10 +304,10 @@ bug. It is very helpful if you can tell where exactly it broke
With a hard freeze you probably doesn't find anything in the logfiles.
The only way to capture any kernel messages is to hook up a serial
console and let some terminal application log the messages. /me uses
-screen. See Documentation/serial-console.txt for details on setting
+screen. See Documentation/admin-guide/serial-console.rst for details on setting
up a serial console.
-Read Documentation/oops-tracing.txt to learn how to get any useful
+Read Documentation/admin-guide/oops-tracing.rst to learn how to get any useful
information out of a register+stack dump printed by the kernel on
protection faults (so-called "kernel oops").
diff --git a/Documentation/media/v4l-drivers/cafe_ccic.rst b/Documentation/media/v4l-drivers/cafe_ccic.rst
index b98eb3b7cb4a..94f0f58ebe37 100644
--- a/Documentation/media/v4l-drivers/cafe_ccic.rst
+++ b/Documentation/media/v4l-drivers/cafe_ccic.rst
@@ -3,8 +3,8 @@ The cafe_ccic driver
Author: Jonathan Corbet <corbet@lwn.net>
-Introdution
------------
+Introduction
+------------
"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera
controller. This is the controller found in first-generation OLPC systems,
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 0d7cb955aa01..5de846d3ecc0 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -324,7 +324,7 @@ guarantee that the memory block contains only migratable pages.
Now, a boot option for making a memory block which consists of migratable pages
is supported. By specifying "kernelcore=" or "movablecore=" boot option, you can
create ZONE_MOVABLE...a zone which is just used for movable pages.
-(See also Documentation/kernel-parameters.txt)
+(See also Documentation/admin-guide/kernel-parameters.rst)
Assume the system has "TOTAL" amount of memory at boot time, this boot option
creates ZONE_MOVABLE as following.
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 8a8d3d96f6c6..ccf94677b240 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -32,7 +32,7 @@ compatible interfaces. Once found, it will create subfolders in
the /sys directories of each supported interface, e.g.
# ls /sys/class/net/eth0/batman_adv/
-# iface_status mesh_iface
+# elp_interval iface_status mesh_iface throughput_override
If an interface does not have the "batman_adv" subfolder it prob-
ably is not supported. Not supported interfaces are: loopback,
@@ -71,17 +71,19 @@ All mesh wide settings can be found in batman's own interface
folder:
# ls /sys/class/net/bat0/mesh/
-#aggregated_ogms distributed_arp_table gw_sel_class orig_interval
-#ap_isolation fragmentation hop_penalty routing_algo
-#bonding gw_bandwidth isolation_mark vlan0
-#bridge_loop_avoidance gw_mode log_level
+# aggregated_ogms fragmentation isolation_mark routing_algo
+# ap_isolation gw_bandwidth log_level vlan0
+# bonding gw_mode multicast_mode
+# bridge_loop_avoidance gw_sel_class network_coding
+# distributed_arp_table hop_penalty orig_interval
There is a special folder for debugging information:
# ls /sys/kernel/debug/batman_adv/bat0/
-# bla_backbone_table log transtable_global
-# bla_claim_table originators transtable_local
-# gateways socket
+# bla_backbone_table log neighbors transtable_local
+# bla_claim_table mcast_flags originators
+# dat_cache nc socket
+# gateways nc_nodes transtable_global
Some of the files contain all sort of status information regard-
ing the mesh network. For example, you can view the table of
@@ -159,13 +161,16 @@ file in debugfs
The additional debug output is by default disabled. It can be en-
abled during run time. Following log_levels are defined:
-0 - All debug output disabled
-1 - Enable messages related to routing / flooding / broadcasting
-2 - Enable messages related to route added / changed / deleted
-4 - Enable messages related to translation table operations
-8 - Enable messages related to bridge loop avoidance
-16 - Enable messaged related to DAT, ARP snooping and parsing
-31 - Enable all messages
+ 0 - All debug output disabled
+ 1 - Enable messages related to routing / flooding / broadcasting
+ 2 - Enable messages related to route added / changed / deleted
+ 4 - Enable messages related to translation table operations
+ 8 - Enable messages related to bridge loop avoidance
+ 16 - Enable messages related to DAT, ARP snooping and parsing
+ 32 - Enable messages related to network coding
+ 64 - Enable messages related to multicast
+128 - Enable messages related to throughput meter
+255 - Enable all messages
The debug output can be changed at runtime using the file
/sys/class/net/bat0/mesh/log_level. e.g.
diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt
index aa69ccc481db..c4114346f054 100644
--- a/Documentation/networking/ieee802154.txt
+++ b/Documentation/networking/ieee802154.txt
@@ -4,20 +4,20 @@
Introduction
============
-The IEEE 802.15.4 working group focuses on standardization of bottom
-two layers: Medium Access Control (MAC) and Physical (PHY). And there
+The IEEE 802.15.4 working group focuses on standardization of the bottom
+two layers: Medium Access Control (MAC) and Physical access (PHY). And there
are mainly two options available for upper layers:
- ZigBee - proprietary protocol from the ZigBee Alliance
- 6LoWPAN - IPv6 networking over low rate personal area networks
-The linux-wpan project goal is to provide a complete implementation
+The goal of the Linux-wpan is to provide a complete implementation
of the IEEE 802.15.4 and 6LoWPAN protocols. IEEE 802.15.4 is a stack
of protocols for organizing Low-Rate Wireless Personal Area Networks.
The stack is composed of three main parts:
- IEEE 802.15.4 layer; We have chosen to use plain Berkeley socket API,
- the generic Linux networking stack to transfer IEEE 802.15.4 messages
- and a special protocol over genetlink for configuration/management
+ the generic Linux networking stack to transfer IEEE 802.15.4 data
+ messages and a special protocol over netlink for configuration/management
- MAC - provides access to shared channel and reliable data delivery
- PHY - represents device drivers
@@ -33,15 +33,13 @@ include/net/af_ieee802154.h header or in the special header
in the userspace package (see either http://wpan.cakelab.org/ or the
git tree at https://github.com/linux-wpan/wpan-tools).
-One can use SOCK_RAW for passing raw data towards device xmit function. YMMV.
-
Kernel side
=============
Like with WiFi, there are several types of devices implementing IEEE 802.15.4.
1) 'HardMAC'. The MAC layer is implemented in the device itself, the device
- exports MLME and data API.
+ exports a management (e.g. MLME) and data API.
2) 'SoftMAC' or just radio. These types of devices are just radio transceivers
possibly with some kinds of acceleration like automatic CRC computation and
comparation, automagic ACK handling, address matching, etc.
@@ -106,7 +104,7 @@ Fake drivers
In addition there is a driver available which simulates a real device with
SoftMAC (fakelb - IEEE 802.15.4 loopback driver) interface. This option
-provides possibility to test and debug stack without usage of real hardware.
+provides a possibility to test and debug the stack without usage of real hardware.
See sources in drivers/net/ieee802154 folder for more details.
@@ -125,17 +123,15 @@ to support the IPv6 minimum MTU requirement [RFC2460], and stateless header
compression for IPv6 datagrams (LOWPAN_HC1 and LOWPAN_HC2) to reduce the
relatively large IPv6 and UDP headers down to (in the best case) several bytes.
-In Semptember 2011 the standard update was published - [RFC6282].
+In September 2011 the standard update was published - [RFC6282].
It deprecates HC1 and HC2 compression and defines IPHC encoding format which is
used in this Linux implementation.
All the code related to 6lowpan you may find in files: net/6lowpan/*
and net/ieee802154/6lowpan/*
-To setup 6lowpan interface you need (busybox release > 1.17.0):
-1. Add IEEE802.15.4 interface and initialize PANid;
+To setup a 6LoWPAN interface you need:
+1. Add IEEE802.15.4 interface and set channel and PAN ID;
2. Add 6lowpan interface by command like:
# ip link add link wpan0 name lowpan0 type lowpan
-3. Set MAC (if needs):
- # ip link set lowpan0 address de:ad:be:ef:ca:fe:ba:be
-4. Bring up 'lowpan0' interface
+3. Bring up 'lowpan0' interface
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 3db8c67d2c8d..7dd65c9cf707 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -610,8 +610,13 @@ tcp_syn_retries - INTEGER
with the current initial RTO of 1second. With this the final timeout
for an active TCP connection attempt will happen after 127seconds.
-tcp_timestamps - BOOLEAN
- Enable timestamps as defined in RFC1323.
+tcp_timestamps - INTEGER
+Enable timestamps as defined in RFC1323.
+ 0: Disabled.
+ 1: Enable timestamps as defined in RFC1323 and use random offset for
+ each connection rather than only using the current time.
+ 2: Like 1, but without random offsets.
+ Default: 1
tcp_min_tso_segs - INTEGER
Minimal number of segments per TSO frame.
@@ -967,6 +972,21 @@ igmp_qrv - INTEGER
Default: 2 (as specified by RFC2236 8.1)
Minimum: 1 (as specified by RFC6636 4.5)
+force_igmp_version - INTEGER
+ 0 - (default) No enforcement of a IGMP version, IGMPv1/v2 fallback
+ allowed. Will back to IGMPv3 mode again if all IGMPv1/v2 Querier
+ Present timer expires.
+ 1 - Enforce to use IGMP version 1. Will also reply IGMPv1 report if
+ receive IGMPv2/v3 query.
+ 2 - Enforce to use IGMP version 2. Will fallback to IGMPv1 if receive
+ IGMPv1 query message. Will reply report if receive IGMPv3 query.
+ 3 - Enforce to use IGMP version 3. The same react with default 0.
+
+ Note: this is not the same with force_mld_version because IGMPv3 RFC3376
+ Security Considerations does not have clear description that we could
+ ignore other version messages completely as MLDv2 RFC3810. So make
+ this value as default 0 is recommended.
+
conf/interface/* changes special settings per interface (where
"interface" is the name of your network interface)
@@ -1714,6 +1734,15 @@ drop_unsolicited_na - BOOLEAN
By default this is turned off.
+enhanced_dad - BOOLEAN
+ Include a nonce option in the IPv6 neighbor solicitation messages used for
+ duplicate address detection per RFC7527. A received DAD NS will only signal
+ a duplicate address if the nonce is different. This avoids any false
+ detection of duplicates due to loopback of the NS messages that we send.
+ The nonce option will be sent on an interface unless both of
+ conf/{all,interface}/enhanced_dad are set to FALSE.
+ Default: TRUE
+
icmp/*:
ratelimit - INTEGER
Limit the maximal rates for sending ICMPv6 packets.
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
index 4650a00ed012..9bc271cdc9a8 100644
--- a/Documentation/networking/l2tp.txt
+++ b/Documentation/networking/l2tp.txt
@@ -177,10 +177,10 @@ setsockopt on the PPPoX socket to set a debug mask.
The following debug mask bits are available:
-PPPOL2TP_MSG_DEBUG verbose debug (if compiled in)
-PPPOL2TP_MSG_CONTROL userspace - kernel interface
-PPPOL2TP_MSG_SEQ sequence numbers handling
-PPPOL2TP_MSG_DATA data packets
+L2TP_MSG_DEBUG verbose debug (if compiled in)
+L2TP_MSG_CONTROL userspace - kernel interface
+L2TP_MSG_SEQ sequence numbers handling
+L2TP_MSG_DATA data packets
If enabled, files under a l2tp debugfs directory can be used to dump
kernel state about L2TP tunnels and sessions. To access it, the
diff --git a/Documentation/networking/mac80211_hwsim/README b/Documentation/networking/mac80211_hwsim/README
index 24ac91d56698..3566a725d19c 100644
--- a/Documentation/networking/mac80211_hwsim/README
+++ b/Documentation/networking/mac80211_hwsim/README
@@ -60,7 +60,7 @@ modprobe mac80211_hwsim
hostapd hostapd.conf
# Run wpa_supplicant (station) for wlan1
-wpa_supplicant -Dwext -iwlan1 -c wpa_supplicant.conf
+wpa_supplicant -Dnl80211 -iwlan1 -c wpa_supplicant.conf
More test cases are available in hostap.git:
diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index 30409a36e95d..296ea00fd3eb 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -200,7 +200,7 @@ priority messages to the console. You can change this at runtime using:
or by specifying "debug" on the kernel command line at boot, to send
all kernel messages to the console. A specific value for this parameter
can also be set using the "loglevel" kernel boot option. See the
-dmesg(8) man page and Documentation/kernel-parameters.txt for details.
+dmesg(8) man page and Documentation/admin-guide/kernel-parameters.rst for details.
Netconsole was designed to be as instantaneous as possible, to
enable the logging of even the most critical kernel bugs. It works
diff --git a/Documentation/networking/netdev-FAQ.txt b/Documentation/networking/netdev-FAQ.txt
index a20b2fae942b..247a30ba8e17 100644
--- a/Documentation/networking/netdev-FAQ.txt
+++ b/Documentation/networking/netdev-FAQ.txt
@@ -136,14 +136,14 @@ A: Normally Greg Kroah-Hartman collects stable commits himself, but
Q: I see a network patch and I think it should be backported to stable.
Should I request it via "stable@vger.kernel.org" like the references in
- the kernel's Documentation/stable_kernel_rules.txt file say?
+ the kernel's Documentation/process/stable-kernel-rules.rst file say?
A: No, not for networking. Check the stable queues as per above 1st to see
if it is already queued. If not, then send a mail to netdev, listing
the upstream commit ID and why you think it should be a stable candidate.
Before you jump to go do the above, do note that the normal stable rules
- in Documentation/stable_kernel_rules.txt still apply. So you need to
+ in Documentation/process/stable-kernel-rules.rst still apply. So you need to
explicitly indicate why it is a critical fix and exactly what users are
impacted. In addition, you need to convince yourself that you _really_
think it has been overlooked, vs. having been considered and rejected.
@@ -165,7 +165,7 @@ A: No. See above answer. In short, if you think it really belongs in
If you think there is some valid information relating to it being in
stable that does _not_ belong in the commit log, then use the three
- dash marker line as described in Documentation/SubmittingPatches to
+ dash marker line as described in Documentation/process/submitting-patches.rst to
temporarily embed that information into the patch that you send.
Q: Someone said that the comment style and coding convention is different
@@ -220,5 +220,5 @@ A: Attention to detail. Re-read your own work as if you were the
If it is your first patch, mail it to yourself so you can test apply
it to an unpatched tree to confirm infrastructure didn't mangle it.
- Finally, go back and read Documentation/SubmittingPatches to be
+ Finally, go back and read Documentation/process/submitting-patches.rst to be
sure you are not repeating some common mistake documented there.
diff --git a/Documentation/networking/nf_conntrack-sysctl.txt b/Documentation/networking/nf_conntrack-sysctl.txt
index 433b6724797a..497d668288f9 100644
--- a/Documentation/networking/nf_conntrack-sysctl.txt
+++ b/Documentation/networking/nf_conntrack-sysctl.txt
@@ -96,6 +96,17 @@ nf_conntrack_max - INTEGER
Size of connection tracking table. Default value is
nf_conntrack_buckets value * 4.
+nf_conntrack_default_on - BOOLEAN
+ 0 - don't register conntrack in new net namespaces
+ 1 - register conntrack in new net namespaces (default)
+
+ This controls wheter newly created network namespaces have connection
+ tracking enabled by default. It will be enabled automatically
+ regardless of this setting if the new net namespace requires
+ connection tracking, e.g. when NAT rules are created.
+ This setting is only visible in initial user namespace, it has no
+ effect on existing namespaces.
+
nf_conntrack_tcp_be_liberal - BOOLEAN
0 - disabled (default)
not 0 - enabled
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 7ab9404a8412..16f90d817224 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -65,6 +65,83 @@ The MDIO bus
drivers/net/ethernet/freescale/fsl_pq_mdio.c and an associated DTS file
for one of the users. (e.g. "git grep fsl,.*-mdio arch/powerpc/boot/dts/")
+(RG)MII/electrical interface considerations
+
+ The Reduced Gigabit Medium Independent Interface (RGMII) is a 12-pin
+ electrical signal interface using a synchronous 125Mhz clock signal and several
+ data lines. Due to this design decision, a 1.5ns to 2ns delay must be added
+ between the clock line (RXC or TXC) and the data lines to let the PHY (clock
+ sink) have enough setup and hold times to sample the data lines correctly. The
+ PHY library offers different types of PHY_INTERFACE_MODE_RGMII* values to let
+ the PHY driver and optionally the MAC driver, implement the required delay. The
+ values of phy_interface_t must be understood from the perspective of the PHY
+ device itself, leading to the following:
+
+ * PHY_INTERFACE_MODE_RGMII: the PHY is not responsible for inserting any
+ internal delay by itself, it assumes that either the Ethernet MAC (if capable
+ or the PCB traces) insert the correct 1.5-2ns delay
+
+ * PHY_INTERFACE_MODE_RGMII_TXID: the PHY should insert an internal delay
+ for the transmit data lines (TXD[3:0]) processed by the PHY device
+
+ * PHY_INTERFACE_MODE_RGMII_RXID: the PHY should insert an internal delay
+ for the receive data lines (RXD[3:0]) processed by the PHY device
+
+ * PHY_INTERFACE_MODE_RGMII_ID: the PHY should insert internal delays for
+ both transmit AND receive data lines from/to the PHY device
+
+ Whenever possible, use the PHY side RGMII delay for these reasons:
+
+ * PHY devices may offer sub-nanosecond granularity in how they allow a
+ receiver/transmitter side delay (e.g: 0.5, 1.0, 1.5ns) to be specified. Such
+ precision may be required to account for differences in PCB trace lengths
+
+ * PHY devices are typically qualified for a large range of applications
+ (industrial, medical, automotive...), and they provide a constant and
+ reliable delay across temperature/pressure/voltage ranges
+
+ * PHY device drivers in PHYLIB being reusable by nature, being able to
+ configure correctly a specified delay enables more designs with similar delay
+ requirements to be operate correctly
+
+ For cases where the PHY is not capable of providing this delay, but the
+ Ethernet MAC driver is capable of doing so, the correct phy_interface_t value
+ should be PHY_INTERFACE_MODE_RGMII, and the Ethernet MAC driver should be
+ configured correctly in order to provide the required transmit and/or receive
+ side delay from the perspective of the PHY device. Conversely, if the Ethernet
+ MAC driver looks at the phy_interface_t value, for any other mode but
+ PHY_INTERFACE_MODE_RGMII, it should make sure that the MAC-level delays are
+ disabled.
+
+ In case neither the Ethernet MAC, nor the PHY are capable of providing the
+ required delays, as defined per the RGMII standard, several options may be
+ available:
+
+ * Some SoCs may offer a pin pad/mux/controller capable of configuring a given
+ set of pins'strength, delays, and voltage; and it may be a suitable
+ option to insert the expected 2ns RGMII delay.
+
+ * Modifying the PCB design to include a fixed delay (e.g: using a specifically
+ designed serpentine), which may not require software configuration at all.
+
+Common problems with RGMII delay mismatch
+
+ When there is a RGMII delay mismatch between the Ethernet MAC and the PHY, this
+ will most likely result in the clock and data line signals to be unstable when
+ the PHY or MAC take a snapshot of these signals to translate them into logical
+ 1 or 0 states and reconstruct the data being transmitted/received. Typical
+ symptoms include:
+
+ * Transmission/reception partially works, and there is frequent or occasional
+ packet loss observed
+
+ * Ethernet MAC may report some or all packets ingressing with a FCS/CRC error,
+ or just discard them all
+
+ * Switching to lower speeds such as 10/100Mbits/sec makes the problem go away
+ (since there is enough setup/hold time in that case)
+
+
Connecting to a PHY
Sometime during startup, the network driver needs to establish a connection
@@ -127,8 +204,9 @@ Letting the PHY Abstraction Layer do Everything
values pruned from them which don't make sense for your controller (a 10/100
controller may be connected to a gigabit capable PHY, so you would need to
mask off SUPPORTED_1000baseT*). See include/linux/ethtool.h for definitions
- for these bitfields. Note that you should not SET any bits, or the PHY may
- get put into an unsupported state.
+ for these bitfields. Note that you should not SET any bits, except the
+ SUPPORTED_Pause and SUPPORTED_AsymPause bits (see below), or the PHY may get
+ put into an unsupported state.
Lastly, once the controller is ready to handle network traffic, you call
phy_start(phydev). This tells the PAL that you are ready, and configures the
@@ -139,6 +217,19 @@ Letting the PHY Abstraction Layer do Everything
When you want to disconnect from the network (even if just briefly), you call
phy_stop(phydev).
+Pause frames / flow control
+
+ The PHY does not participate directly in flow control/pause frames except by
+ making sure that the SUPPORTED_Pause and SUPPORTED_AsymPause bits are set in
+ MII_ADVERTISE to indicate towards the link partner that the Ethernet MAC
+ controller supports such a thing. Since flow control/pause frames generation
+ involves the Ethernet MAC driver, it is recommended that this driver takes care
+ of properly indicating advertisement and support for such features by setting
+ the SUPPORTED_Pause and SUPPORTED_AsymPause bits accordingly. This can be done
+ either before or after phy_connect() and/or as a result of implementing the
+ ethtool::set_pauseparam feature.
+
+
Keeping Close Tabs on the PAL
It is possible that the PAL's built-in state machine needs a little help to
@@ -251,39 +342,8 @@ Writing a PHY driver
PHY_BASIC_FEATURES, but you can look in include/mii.h for other
features.
- Each driver consists of a number of function pointers:
-
- soft_reset: perform a PHY software reset
- config_init: configures PHY into a sane state after a reset.
- For instance, a Davicom PHY requires descrambling disabled.
- probe: Allocate phy->priv, optionally refuse to bind.
- PHY may not have been reset or had fixups run yet.
- suspend/resume: power management
- config_aneg: Changes the speed/duplex/negotiation settings
- aneg_done: Determines the auto-negotiation result
- read_status: Reads the current speed/duplex/negotiation settings
- ack_interrupt: Clear a pending interrupt
- did_interrupt: Checks if the PHY generated an interrupt
- config_intr: Enable or disable interrupts
- remove: Does any driver take-down
- ts_info: Queries about the HW timestamping status
- match_phy_device: used for Clause 45 capable PHYs to match devices
- in package and ensure they are compatible
- hwtstamp: Set the PHY HW timestamping configuration
- rxtstamp: Requests a receive timestamp at the PHY level for a 'skb'
- txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
- set_wol: Enable Wake-on-LAN at the PHY level
- get_wol: Get the Wake-on-LAN status at the PHY level
- link_change_notify: called to inform the core is about to change the
- link state, can be used to work around bogus PHY between state changes
- read_mmd_indirect: Read PHY MMD indirect register
- write_mmd_indirect: Write PHY MMD indirect register
- module_info: Get the size and type of an EEPROM contained in an plug-in
- module
- module_eeprom: Get EEPROM information of a plug-in module
- get_sset_count: Get number of strings sets that get_strings will count
- get_strings: Get strings from requested objects (statistics)
- get_stats: Get the extended statistics from the PHY device
+ Each driver consists of a number of function pointers, documented
+ in include/linux/phy.h under the phy_driver structure.
Of these, only config_aneg and read_status are required to be
assigned by the driver code. The rest are optional. Also, it is
@@ -347,3 +407,22 @@ Board Fixups
The stubs set one of the two matching criteria, and set the other one to
match anything.
+ When phy_register_fixup() or *_for_uid()/*_for_id() is called at module,
+ unregister fixup and free allocate memory are required.
+
+ Call one of following function before unloading module.
+
+ int phy_unregister_fixup(const char *phy_id, u32 phy_uid, u32 phy_uid_mask);
+ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
+ int phy_register_fixup_for_id(const char *phy_id);
+
+Standards
+
+ IEEE Standard 802.3: CSMA/CD Access Method and Physical Layer Specifications, Section Two:
+ http://standards.ieee.org/getieee802/download/802.3-2008_section2.pdf
+
+ RGMII v1.3:
+ http://web.archive.org/web/20160303212629/http://www.hp.com/rnd/pdfs/RGMIIv1_3.pdf
+
+ RGMII v2.0:
+ http://web.archive.org/web/20160303171328/http://www.hp.com/rnd/pdfs/RGMIIv2_0_final_hp.pdf
diff --git a/Documentation/networking/seg6-sysctl.txt b/Documentation/networking/seg6-sysctl.txt
new file mode 100644
index 000000000000..bdbde23b19cb
--- /dev/null
+++ b/Documentation/networking/seg6-sysctl.txt
@@ -0,0 +1,18 @@
+/proc/sys/net/conf/<iface>/seg6_* variables:
+
+seg6_enabled - BOOL
+ Accept or drop SR-enabled IPv6 packets on this interface.
+
+ Relevant packets are those with SRH present and DA = local.
+
+ 0 - disabled (default)
+ not 0 - enabled
+
+seg6_require_hmac - INTEGER
+ Define HMAC policy for ingress SR-enabled packets on this interface.
+
+ -1 - Ignore HMAC field
+ 0 - Accept SR packets without HMAC, validate SR packets with HMAC
+ 1 - Drop SR packets without HMAC, validate SR packets with HMAC
+
+ Default is 0.
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index e226f8925c9e..2bb07078f535 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -28,8 +28,6 @@ CONFIG_STMMAC_PCI: is to enable the pci driver.
2) Driver parameters list:
debug: message level (0: no output, 16: all);
phyaddr: to manually provide the physical address to the PHY device;
- dma_rxsize: DMA rx ring size;
- dma_txsize: DMA tx ring size;
buf_sz: DMA buffer size;
tc: control the HW FIFO threshold;
watchdog: transmit timeout (in milliseconds);
@@ -40,31 +38,31 @@ CONFIG_STMMAC_PCI: is to enable the pci driver.
3) Command line options
Driver parameters can be also passed in command line by using:
- stmmaceth=dma_rxsize:128,dma_txsize:512
+ stmmaceth=watchdog:100,chain_mode=1
4) Driver information and notes
4.1) Transmit process
The xmit method is invoked when the kernel needs to transmit a packet; it sets
-the descriptors in the ring and informs the DMA engine that there is a packet
+the descriptors in the ring and informs the DMA engine, that there is a packet
ready to be transmitted.
By default, the driver sets the NETIF_F_SG bit in the features field of the
-net_device structure enabling the scatter-gather feature. This is true on
+net_device structure, enabling the scatter-gather feature. This is true on
chips and configurations where the checksum can be done in hardware.
-Once the controller has finished transmitting the packet, napi will be
+Once the controller has finished transmitting the packet, timer will be
scheduled to release the transmit resources.
4.2) Receive process
When one or more packets are received, an interrupt happens. The interrupts
-are not queued so the driver has to scan all the descriptors in the ring during
+are not queued, so the driver has to scan all the descriptors in the ring during
the receive process.
-This is based on NAPI so the interrupt handler signals only if there is work
+This is based on NAPI, so the interrupt handler signals only if there is work
to be done, and it exits.
Then the poll method will be scheduled at some future point.
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
buffers in order to avoid the memcpy (zero-copy).
-4.3) Interrupt Mitigation
+4.3) Interrupt mitigation
The driver is able to mitigate the number of its DMA interrupts
using NAPI for the reception on chips older than the 3.50.
New chips have an HW RX-Watchdog used for this mitigation.
@@ -88,19 +86,20 @@ the list, hence creating the explicit chaining in the descriptor itself,
whereas such explicit chaining is not possible in RING mode.
4.5.1) Extended descriptors
- The extended descriptors give us information about the Ethernet payload
- when it is carrying PTP packets or TCP/UDP/ICMP over IP.
- These are not available on GMAC Synopsys chips older than the 3.50.
- At probe time the driver will decide if these can be actually used.
- This support also is mandatory for PTPv2 because the extra descriptors
- are used for saving the hardware timestamps and Extended Status.
+The extended descriptors give us information about the Ethernet payload
+when it is carrying PTP packets or TCP/UDP/ICMP over IP.
+These are not available on GMAC Synopsys chips older than the 3.50.
+At probe time the driver will decide if these can be actually used.
+This support also is mandatory for PTPv2 because the extra descriptors
+are used for saving the hardware timestamps and Extended Status.
4.6) Ethtool support
Ethtool is supported.
For example, driver statistics (including RMON), internal errors can be taken
using:
- # ethtool -S ethX command
+ # ethtool -S ethX
+command
4.7) Jumbo and Segmentation Offloading
Jumbo frames are supported and tested for the GMAC.
@@ -153,8 +152,10 @@ Where:
o dma_cfg: internal DMA parameters
o pbl: the Programmable Burst Length is maximum number of beats to
be transferred in one DMA transaction.
- GMAC also enables the 4xPBL by default.
- o fixed_burst/mixed_burst/burst_len
+ GMAC also enables the 4xPBL by default. (8xPBL for GMAC 3.50 and newer)
+ o txpbl/rxpbl: GMAC and newer supports independent DMA pbl for tx/rx.
+ o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
+ o fixed_burst/mixed_burst/aal
o clk_csr: fixed CSR Clock range selection.
o has_gmac: uses the GMAC core.
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
@@ -206,16 +207,24 @@ tuned according to the HW capabilities.
struct stmmac_dma_cfg {
int pbl;
+ int txpbl;
+ int rxpbl;
+ bool pblx8;
int fixed_burst;
- int burst_len_supported;
+ int mixed_burst;
+ bool aal;
};
Where:
- o pbl: Programmable Burst Length
+ o pbl: Programmable Burst Length (tx and rx)
+ o txpbl: Transmit Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA tx will use this value rather than pbl.
+ o rxpbl: Receive Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA rx will use this value rather than pbl.
+ o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
o fixed_burst: program the DMA to use the fixed burst mode
- o burst_len: this is the value we put in the register
- supported values are provided as macros in
- linux/stmmac.h header file.
+ o mixed_burst: program the DMA to use the mixed burst mode
+ o aal: Address-Aligned Beats
---
@@ -275,11 +284,11 @@ Please see the following document:
Documentation/devicetree/bindings/net/stmmac.txt
4.11) This is a summary of the content of some relevant files:
- o stmmac_main.c: to implement the main network device driver;
- o stmmac_mdio.c: to provide mdio functions;
- o stmmac_pci: this the PCI driver;
- o stmmac_platform.c: this the platform driver (OF supported)
- o stmmac_ethtool.c: to implement the ethtool support;
+ o stmmac_main.c: implements the main network device driver;
+ o stmmac_mdio.c: provides MDIO functions;
+ o stmmac_pci: this is the PCI driver;
+ o stmmac_platform.c: this the platform driver (OF supported);
+ o stmmac_ethtool.c: implements the ethtool support;
o stmmac.h: private driver structure;
o common.h: common definitions and VFTs;
o mmc_core.c/mmc.h: Management MAC Counters;
@@ -381,12 +390,12 @@ In addition to the basic timestamp features mentioned in IEEE 1588-2002
Timestamps, new GMAC cores support the advanced timestamp features.
IEEE 1588-2008 that can be enabled when configure the Kernel.
-8) SGMII/RGMII supports
+8) SGMII/RGMII support
New GMAC devices provide own way to manage RGMII/SGMII.
This information is available at run-time by looking at the
HW capability register. This means that the stmmac can manage
-auto-negotiation and link status w/o using the PHYLIB stuff
+auto-negotiation and link status w/o using the PHYLIB stuff.
In fact, the HW provides a subset of extended registers to
restart the ANE, verify Full/Half duplex mode and Speed.
-Also thanks to these registers it is possible to look at the
+Thanks to these registers, it is possible to look at the
Auto-negotiated Link Parter Ability.
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index 671cccf0dcd2..96f50694a748 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -182,6 +182,16 @@ SOF_TIMESTAMPING_OPT_TSONLY:
the timestamp even if sysctl net.core.tstamp_allow_data is 0.
This option disables SOF_TIMESTAMPING_OPT_CMSG.
+SOF_TIMESTAMPING_OPT_STATS:
+
+ Optional stats that are obtained along with the transmit timestamps.
+ It must be used together with SOF_TIMESTAMPING_OPT_TSONLY. When the
+ transmit timestamp is available, the stats are available in a
+ separate control message of type SCM_TIMESTAMPING_OPT_STATS, as a
+ list of TLVs (struct nlattr) of types. These stats allow the
+ application to associate various transport layer stats with
+ the transmit timestamps, such as how long a certain block of
+ data was limited by peer's receiver window.
New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
index 97282da82b75..ad3dead052a4 100644
--- a/Documentation/networking/vortex.txt
+++ b/Documentation/networking/vortex.txt
@@ -364,7 +364,7 @@ steps you should take:
- The contents of your report will vary a lot depending upon the
problem. If it's a kernel crash then you should refer to the
- REPORTING-BUGS file.
+ admin-guide/reporting-bugs.rst file.
But for most problems it is useful to provide the following:
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
deleted file mode 100644
index f3ac05cc23e4..000000000000
--- a/Documentation/oops-tracing.txt
+++ /dev/null
@@ -1,279 +0,0 @@
-NOTE: ksymoops is useless on 2.6. Please use the Oops in its original format
-(from dmesg, etc). Ignore any references in this or other docs to "decoding
-the Oops" or "running it through ksymoops". If you post an Oops from 2.6 that
-has been run through ksymoops, people will just tell you to repost it.
-
-Quick Summary
--------------
-
-Find the Oops and send it to the maintainer of the kernel area that seems to be
-involved with the problem. Don't worry too much about getting the wrong person.
-If you are unsure send it to the person responsible for the code relevant to
-what you were doing. If it occurs repeatably try and describe how to recreate
-it. That's worth even more than the oops.
-
-If you are totally stumped as to whom to send the report, send it to
-linux-kernel@vger.kernel.org. Thanks for your help in making Linux as
-stable as humanly possible.
-
-Where is the Oops?
-----------------------
-
-Normally the Oops text is read from the kernel buffers by klogd and
-handed to syslogd which writes it to a syslog file, typically
-/var/log/messages (depends on /etc/syslog.conf). Sometimes klogd dies,
-in which case you can run dmesg > file to read the data from the kernel
-buffers and save it. Or you can cat /proc/kmsg > file, however you
-have to break in to stop the transfer, kmsg is a "never ending file".
-If the machine has crashed so badly that you cannot enter commands or
-the disk is not available then you have three options :-
-
-(1) Hand copy the text from the screen and type it in after the machine
- has restarted. Messy but it is the only option if you have not
- planned for a crash. Alternatively, you can take a picture of
- the screen with a digital camera - not nice, but better than
- nothing. If the messages scroll off the top of the console, you
- may find that booting with a higher resolution (eg, vga=791)
- will allow you to read more of the text. (Caveat: This needs vesafb,
- so won't help for 'early' oopses)
-
-(2) Boot with a serial console (see Documentation/serial-console.txt),
- run a null modem to a second machine and capture the output there
- using your favourite communication program. Minicom works well.
-
-(3) Use Kdump (see Documentation/kdump/kdump.txt),
- extract the kernel ring buffer from old memory with using dmesg
- gdbmacro in Documentation/kdump/gdbmacros.txt.
-
-
-Full Information
-----------------
-
-NOTE: the message from Linus below applies to 2.4 kernel. I have preserved it
-for historical reasons, and because some of the information in it still
-applies. Especially, please ignore any references to ksymoops.
-
-From: Linus Torvalds <torvalds@osdl.org>
-
-How to track down an Oops.. [originally a mail to linux-kernel]
-
-The main trick is having 5 years of experience with those pesky oops
-messages ;-)
-
-Actually, there are things you can do that make this easier. I have two
-separate approaches:
-
- gdb /usr/src/linux/vmlinux
- gdb> disassemble <offending_function>
-
-That's the easy way to find the problem, at least if the bug-report is
-well made (like this one was - run through ksymoops to get the
-information of which function and the offset in the function that it
-happened in).
-
-Oh, it helps if the report happens on a kernel that is compiled with the
-same compiler and similar setups.
-
-The other thing to do is disassemble the "Code:" part of the bug report:
-ksymoops will do this too with the correct tools, but if you don't have
-the tools you can just do a silly program:
-
- char str[] = "\xXX\xXX\xXX...";
- main(){}
-
-and compile it with gcc -g and then do "disassemble str" (where the "XX"
-stuff are the values reported by the Oops - you can just cut-and-paste
-and do a replace of spaces to "\x" - that's what I do, as I'm too lazy
-to write a program to automate this all).
-
-Alternatively, you can use the shell script in scripts/decodecode.
-Its usage is: decodecode < oops.txt
-
-The hex bytes that follow "Code:" may (in some architectures) have a series
-of bytes that precede the current instruction pointer as well as bytes at and
-following the current instruction pointer. In some cases, one instruction
-byte or word is surrounded by <> or (), as in "<86>" or "(f00d)". These
-<> or () markings indicate the current instruction pointer. Example from
-i386, split into multiple lines for readability:
-
-Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
-64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
-7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
-
-Finally, if you want to see where the code comes from, you can do
-
- cd /usr/src/linux
- make fs/buffer.s # or whatever file the bug happened in
-
-and then you get a better idea of what happens than with the gdb
-disassembly.
-
-Now, the trick is just then to combine all the data you have: the C
-sources (and general knowledge of what it _should_ do), the assembly
-listing and the code disassembly (and additionally the register dump you
-also get from the "oops" message - that can be useful to see _what_ the
-corrupted pointers were, and when you have the assembler listing you can
-also match the other registers to whatever C expressions they were used
-for).
-
-Essentially, you just look at what doesn't match (in this case it was the
-"Code" disassembly that didn't match with what the compiler generated).
-Then you need to find out _why_ they don't match. Often it's simple - you
-see that the code uses a NULL pointer and then you look at the code and
-wonder how the NULL pointer got there, and if it's a valid thing to do
-you just check against it..
-
-Now, if somebody gets the idea that this is time-consuming and requires
-some small amount of concentration, you're right. Which is why I will
-mostly just ignore any panic reports that don't have the symbol table
-info etc looked up: it simply gets too hard to look it up (I have some
-programs to search for specific patterns in the kernel code segment, and
-sometimes I have been able to look up those kinds of panics too, but
-that really requires pretty good knowledge of the kernel just to be able
-to pick out the right sequences etc..)
-
-_Sometimes_ it happens that I just see the disassembled code sequence
-from the panic, and I know immediately where it's coming from. That's when
-I get worried that I've been doing this for too long ;-)
-
- Linus
-
-
----------------------------------------------------------------------------
-Notes on Oops tracing with klogd:
-
-In order to help Linus and the other kernel developers there has been
-substantial support incorporated into klogd for processing protection
-faults. In order to have full support for address resolution at least
-version 1.3-pl3 of the sysklogd package should be used.
-
-When a protection fault occurs the klogd daemon automatically
-translates important addresses in the kernel log messages to their
-symbolic equivalents. This translated kernel message is then
-forwarded through whatever reporting mechanism klogd is using. The
-protection fault message can be simply cut out of the message files
-and forwarded to the kernel developers.
-
-Two types of address resolution are performed by klogd. The first is
-static translation and the second is dynamic translation. Static
-translation uses the System.map file in much the same manner that
-ksymoops does. In order to do static translation the klogd daemon
-must be able to find a system map file at daemon initialization time.
-See the klogd man page for information on how klogd searches for map
-files.
-
-Dynamic address translation is important when kernel loadable modules
-are being used. Since memory for kernel modules is allocated from the
-kernel's dynamic memory pools there are no fixed locations for either
-the start of the module or for functions and symbols in the module.
-
-The kernel supports system calls which allow a program to determine
-which modules are loaded and their location in memory. Using these
-system calls the klogd daemon builds a symbol table which can be used
-to debug a protection fault which occurs in a loadable kernel module.
-
-At the very minimum klogd will provide the name of the module which
-generated the protection fault. There may be additional symbolic
-information available if the developer of the loadable module chose to
-export symbol information from the module.
-
-Since the kernel module environment can be dynamic there must be a
-mechanism for notifying the klogd daemon when a change in module
-environment occurs. There are command line options available which
-allow klogd to signal the currently executing daemon that symbol
-information should be refreshed. See the klogd manual page for more
-information.
-
-A patch is included with the sysklogd distribution which modifies the
-modules-2.0.0 package to automatically signal klogd whenever a module
-is loaded or unloaded. Applying this patch provides essentially
-seamless support for debugging protection faults which occur with
-kernel loadable modules.
-
-The following is an example of a protection fault in a loadable module
-processed by klogd:
----------------------------------------------------------------------------
-Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
-Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
-Aug 29 09:51:01 blizard kernel: *pde = 00000000
-Aug 29 09:51:01 blizard kernel: Oops: 0002
-Aug 29 09:51:01 blizard kernel: CPU: 0
-Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
-Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
-Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
-Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
-Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
-Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
-Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
-Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
-Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
-Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
-Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
----------------------------------------------------------------------------
-
-Dr. G.W. Wettstein Oncology Research Div. Computing Facility
-Roger Maris Cancer Center INTERNET: greg@wind.rmcc.com
-820 4th St. N.
-Fargo, ND 58122
-Phone: 701-234-7556
-
-
----------------------------------------------------------------------------
-Tainted kernels:
-
-Some oops reports contain the string 'Tainted: ' after the program
-counter. This indicates that the kernel has been tainted by some
-mechanism. The string is followed by a series of position-sensitive
-characters, each representing a particular tainted value.
-
- 1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
- any proprietary module has been loaded. Modules without a
- MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
- insmod as GPL compatible are assumed to be proprietary.
-
- 2: 'F' if any module was force loaded by "insmod -f", ' ' if all
- modules were loaded normally.
-
- 3: 'S' if the oops occurred on an SMP kernel running on hardware that
- hasn't been certified as safe to run multiprocessor.
- Currently this occurs only on various Athlons that are not
- SMP capable.
-
- 4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
- modules were unloaded normally.
-
- 5: 'M' if any processor has reported a Machine Check Exception,
- ' ' if no Machine Check Exceptions have occurred.
-
- 6: 'B' if a page-release function has found a bad page reference or
- some unexpected page flags.
-
- 7: 'U' if a user or user application specifically requested that the
- Tainted flag be set, ' ' otherwise.
-
- 8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
-
- 9: 'A' if the ACPI table has been overridden.
-
- 10: 'W' if a warning has previously been issued by the kernel.
- (Though some warnings may set more specific taint flags.)
-
- 11: 'C' if a staging driver has been loaded.
-
- 12: 'I' if the kernel is working around a severe bug in the platform
- firmware (BIOS or similar).
-
- 13: 'O' if an externally-built ("out-of-tree") module has been loaded.
-
- 14: 'E' if an unsigned module has been loaded in a kernel supporting
- module signature.
-
- 15: 'L' if a soft lockup has previously occurred on the system.
-
- 16: 'K' if the kernel has been live patched.
-
-The primary reason for the 'Tainted: ' string is to tell kernel
-debuggers if this is a clean kernel or if anything unusual has
-occurred. Tainting is permanent: even if an offending module is
-unloaded, the tainted value remains to indicate that the kernel is not
-trustworthy.
diff --git a/Documentation/parport.txt b/Documentation/parport.txt
deleted file mode 100644
index c208e4366c03..000000000000
--- a/Documentation/parport.txt
+++ /dev/null
@@ -1,267 +0,0 @@
-The `parport' code provides parallel-port support under Linux. This
-includes the ability to share one port between multiple device
-drivers.
-
-You can pass parameters to the parport code to override its automatic
-detection of your hardware. This is particularly useful if you want
-to use IRQs, since in general these can't be autoprobed successfully.
-By default IRQs are not used even if they _can_ be probed. This is
-because there are a lot of people using the same IRQ for their
-parallel port and a sound card or network card.
-
-The parport code is split into two parts: generic (which deals with
-port-sharing) and architecture-dependent (which deals with actually
-using the port).
-
-
-Parport as modules
-==================
-
-If you load the parport code as a module, say
-
- # insmod parport
-
-to load the generic parport code. You then must load the
-architecture-dependent code with (for example):
-
- # insmod parport_pc io=0x3bc,0x378,0x278 irq=none,7,auto
-
-to tell the parport code that you want three PC-style ports, one at
-0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
-auto-detected IRQ. Currently, PC-style (parport_pc), Sun `bpp',
-Amiga, Atari, and MFC3 hardware is supported.
-
-PCI parallel I/O card support comes from parport_pc. Base I/O
-addresses should not be specified for supported PCI cards since they
-are automatically detected.
-
-
-modprobe
---------
-
-If you use modprobe , you will find it useful to add lines as below to a
-configuration file in /etc/modprobe.d/ directory:.
-
- alias parport_lowlevel parport_pc
- options parport_pc io=0x378,0x278 irq=7,auto
-
-modprobe will load parport_pc (with the options "io=0x378,0x278 irq=7,auto")
-whenever a parallel port device driver (such as lp) is loaded.
-
-Note that these are example lines only! You shouldn't in general need
-to specify any options to parport_pc in order to be able to use a
-parallel port.
-
-
-Parport probe [optional]
--------------
-
-In 2.2 kernels there was a module called parport_probe, which was used
-for collecting IEEE 1284 device ID information. This has now been
-enhanced and now lives with the IEEE 1284 support. When a parallel
-port is detected, the devices that are connected to it are analysed,
-and information is logged like this:
-
- parport0: Printer, BJC-210 (Canon)
-
-The probe information is available from files in /proc/sys/dev/parport/.
-
-
-Parport linked into the kernel statically
-=========================================
-
-If you compile the parport code into the kernel, then you can use
-kernel boot parameters to get the same effect. Add something like the
-following to your LILO command line:
-
- parport=0x3bc parport=0x378,7 parport=0x278,auto,nofifo
-
-You can have many `parport=...' statements, one for each port you want
-to add. Adding `parport=0' to the kernel command-line will disable
-parport support entirely. Adding `parport=auto' to the kernel
-command-line will make parport use any IRQ lines or DMA channels that
-it auto-detects.
-
-
-Files in /proc
-==============
-
-If you have configured the /proc filesystem into your kernel, you will
-see a new directory entry: /proc/sys/dev/parport. In there will be a
-directory entry for each parallel port for which parport is
-configured. In each of those directories are a collection of files
-describing that parallel port.
-
-The /proc/sys/dev/parport directory tree looks like:
-
-parport
-|-- default
-| |-- spintime
-| `-- timeslice
-|-- parport0
-| |-- autoprobe
-| |-- autoprobe0
-| |-- autoprobe1
-| |-- autoprobe2
-| |-- autoprobe3
-| |-- devices
-| | |-- active
-| | `-- lp
-| | `-- timeslice
-| |-- base-addr
-| |-- irq
-| |-- dma
-| |-- modes
-| `-- spintime
-`-- parport1
- |-- autoprobe
- |-- autoprobe0
- |-- autoprobe1
- |-- autoprobe2
- |-- autoprobe3
- |-- devices
- | |-- active
- | `-- ppa
- | `-- timeslice
- |-- base-addr
- |-- irq
- |-- dma
- |-- modes
- `-- spintime
-
-
-File: Contents:
-
-devices/active A list of the device drivers using that port. A "+"
- will appear by the name of the device currently using
- the port (it might not appear against any). The
- string "none" means that there are no device drivers
- using that port.
-
-base-addr Parallel port's base address, or addresses if the port
- has more than one in which case they are separated
- with tabs. These values might not have any sensible
- meaning for some ports.
-
-irq Parallel port's IRQ, or -1 if none is being used.
-
-dma Parallel port's DMA channel, or -1 if none is being
- used.
-
-modes Parallel port's hardware modes, comma-separated,
- meaning:
-
- PCSPP PC-style SPP registers are available.
- TRISTATE Port is bidirectional.
- COMPAT Hardware acceleration for printers is
- available and will be used.
- EPP Hardware acceleration for EPP protocol
- is available and will be used.
- ECP Hardware acceleration for ECP protocol
- is available and will be used.
- DMA DMA is available and will be used.
-
- Note that the current implementation will only take
- advantage of COMPAT and ECP modes if it has an IRQ
- line to use.
-
-autoprobe Any IEEE-1284 device ID information that has been
- acquired from the (non-IEEE 1284.3) device.
-
-autoprobe[0-3] IEEE 1284 device ID information retrieved from
- daisy-chain devices that conform to IEEE 1284.3.
-
-spintime The number of microseconds to busy-loop while waiting
- for the peripheral to respond. You might find that
- adjusting this improves performance, depending on your
- peripherals. This is a port-wide setting, i.e. it
- applies to all devices on a particular port.
-
-timeslice The number of milliseconds that a device driver is
- allowed to keep a port claimed for. This is advisory,
- and driver can ignore it if it must.
-
-default/* The defaults for spintime and timeslice. When a new
- port is registered, it picks up the default spintime.
- When a new device is registered, it picks up the
- default timeslice.
-
-Device drivers
-==============
-
-Once the parport code is initialised, you can attach device drivers to
-specific ports. Normally this happens automatically; if the lp driver
-is loaded it will create one lp device for each port found. You can
-override this, though, by using parameters either when you load the lp
-driver:
-
- # insmod lp parport=0,2
-
-or on the LILO command line:
-
- lp=parport0 lp=parport2
-
-Both the above examples would inform lp that you want /dev/lp0 to be
-the first parallel port, and /dev/lp1 to be the _third_ parallel port,
-with no lp device associated with the second port (parport1). Note
-that this is different to the way older kernels worked; there used to
-be a static association between the I/O port address and the device
-name, so /dev/lp0 was always the port at 0x3bc. This is no longer the
-case - if you only have one port, it will default to being /dev/lp0,
-regardless of base address.
-
-Also:
-
- * If you selected the IEEE 1284 support at compile time, you can say
- `lp=auto' on the kernel command line, and lp will create devices
- only for those ports that seem to have printers attached.
-
- * If you give PLIP the `timid' parameter, either with `plip=timid' on
- the command line, or with `insmod plip timid=1' when using modules,
- it will avoid any ports that seem to be in use by other devices.
-
- * IRQ autoprobing works only for a few port types at the moment.
-
-Reporting printer problems with parport
-=======================================
-
-If you are having problems printing, please go through these steps to
-try to narrow down where the problem area is.
-
-When reporting problems with parport, really you need to give all of
-the messages that parport_pc spits out when it initialises. There are
-several code paths:
-
-o polling
-o interrupt-driven, protocol in software
-o interrupt-driven, protocol in hardware using PIO
-o interrupt-driven, protocol in hardware using DMA
-
-The kernel messages that parport_pc logs give an indication of which
-code path is being used. (They could be a lot better actually..)
-
-For normal printer protocol, having IEEE 1284 modes enabled or not
-should not make a difference.
-
-To turn off the 'protocol in hardware' code paths, disable
-CONFIG_PARPORT_PC_FIFO. Note that when they are enabled they are not
-necessarily _used_; it depends on whether the hardware is available,
-enabled by the BIOS, and detected by the driver.
-
-So, to start with, disable CONFIG_PARPORT_PC_FIFO, and load parport_pc
-with 'irq=none'. See if printing works then. It really should,
-because this is the simplest code path.
-
-If that works fine, try with 'io=0x378 irq=7' (adjust for your
-hardware), to make it use interrupt-driven in-software protocol.
-
-If _that_ works fine, then one of the hardware modes isn't working
-right. Enable CONFIG_PARPORT_PC_FIFO (no, it isn't a module option,
-and yes, it should be), set the port to ECP mode in the BIOS and note
-the DMA channel, and try with:
-
- io=0x378 irq=7 dma=none (for PIO)
- io=0x378 irq=7 dma=3 (for DMA)
---
-philb@gnu.org
-tim@cyberelk.net
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index ad04cc8097ed..7cb6085839f3 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -6,7 +6,7 @@ basic-pm-debugging.txt
- Debugging suspend and resume
charger-manager.txt
- Battery charger management.
-devices.txt
+admin-guide/devices.rst
- How drivers interact with system-wide power management
drivers-testing.txt
- Testing suspend and resume support in device drivers
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 8ba6625fdd63..73ddea39a9ce 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -607,7 +607,9 @@ individually. Instead, a set of devices sharing a power resource can be put
into a low-power state together at the same time by turning off the shared
power resource. Of course, they also need to be put into the full-power state
together, by turning the shared power resource on. A set of devices with this
-property is often referred to as a power domain.
+property is often referred to as a power domain. A power domain may also be
+nested inside another power domain. The nested domain is referred to as the
+sub-domain of the parent domain.
Support for power domains is provided through the pm_domain field of struct
device. This field is a pointer to an object of type struct dev_pm_domain,
@@ -629,6 +631,16 @@ support for power domains into subsystem-level callbacks, for example by
modifying the platform bus type. Other platforms need not implement it or take
it into account in any way.
+Devices may be defined as IRQ-safe which indicates to the PM core that their
+runtime PM callbacks may be invoked with disabled interrupts (see
+Documentation/power/runtime_pm.txt for more information). If an IRQ-safe
+device belongs to a PM domain, the runtime PM of the domain will be
+disallowed, unless the domain itself is defined as IRQ-safe. However, it
+makes sense to define a PM domain as IRQ-safe only if all the devices in it
+are IRQ-safe. Moreover, if an IRQ-safe domain has a parent domain, the runtime
+PM of the parent is only allowed if the parent itself is IRQ-safe too with the
+additional restriction that all child domains of an IRQ-safe parent must also
+be IRQ-safe.
Device Low Power (suspend) States
---------------------------------
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index 44558882aa60..85c746cbab2c 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -8,7 +8,7 @@ management. Based on previous work by Patrick Mochel <mochel@transmeta.com>
This document only covers the aspects of power management specific to PCI
devices. For general description of the kernel's interfaces related to device
-power management refer to Documentation/power/devices.txt and
+power management refer to Documentation/power/admin-guide/devices.rst and
Documentation/power/runtime_pm.txt.
---------------------------------------------------------------------------
@@ -417,7 +417,7 @@ pm->runtime_idle() callback.
2.4. System-Wide Power Transitions
----------------------------------
There are a few different types of system-wide power transitions, described in
-Documentation/power/devices.txt. Each of them requires devices to be handled
+Documentation/power/admin-guide/devices.rst. Each of them requires devices to be handled
in a specific way and the PM core executes subsystem-level power management
callbacks for this purpose. They are executed in phases such that each phase
involves executing the same subsystem-level callback for every device belonging
@@ -623,7 +623,7 @@ System restore requires a hibernation image to be loaded into memory and the
pre-hibernation memory contents to be restored before the pre-hibernation system
activity can be resumed.
-As described in Documentation/power/devices.txt, the hibernation image is loaded
+As described in Documentation/power/admin-guide/devices.rst, the hibernation image is loaded
into memory by a fresh instance of the kernel, called the boot kernel, which in
turn is loaded and run by a boot loader in the usual way. After the boot kernel
has loaded the image, it needs to replace its own code and data with the code
@@ -677,7 +677,7 @@ controlling the runtime power management of their devices.
At the time of this writing there are two ways to define power management
callbacks for a PCI device driver, the recommended one, based on using a
-dev_pm_ops structure described in Documentation/power/devices.txt, and the
+dev_pm_ops structure described in Documentation/power/admin-guide/devices.rst, and the
"legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and
.resume() callbacks from struct pci_driver are used. The legacy approach,
however, doesn't allow one to define runtime power management callbacks and is
@@ -1046,5 +1046,5 @@ PCI Local Bus Specification, Rev. 3.0
PCI Bus Power Management Interface Specification, Rev. 1.2
Advanced Configuration and Power Interface (ACPI) Specification, Rev. 3.0b
PCI Express Base Specification, Rev. 2.0
-Documentation/power/devices.txt
+Documentation/power/admin-guide/devices.rst
Documentation/power/runtime_pm.txt
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 1fd1fbe9ce95..4870980e967e 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -674,7 +674,7 @@ left in runtime suspend. If that happens, the PM core will not execute any
system suspend and resume callbacks for all of those devices, except for the
complete callback, which is then entirely responsible for handling the device
as appropriate. This only applies to system suspend transitions that are not
-related to hibernation (see Documentation/power/devices.txt for more
+related to hibernation (see Documentation/power/admin-guide/devices.rst for more
information).
The PM core does its best to reduce the probability of race conditions between
diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt
index 50f3ef9177c1..8a39ce45d8a0 100644
--- a/Documentation/power/states.txt
+++ b/Documentation/power/states.txt
@@ -8,25 +8,43 @@ for each state.
The states are represented by strings that can be read or written to the
/sys/power/state file. Those strings may be "mem", "standby", "freeze" and
-"disk", where the last one always represents hibernation (Suspend-To-Disk) and
-the meaning of the remaining ones depends on the relative_sleep_states command
-line argument.
-
-For relative_sleep_states=1, the strings "mem", "standby" and "freeze" label the
-available non-hibernation sleep states from the deepest to the shallowest,
-respectively. In that case, "mem" is always present in /sys/power/state,
-because there is at least one non-hibernation sleep state in every system. If
-the given system supports two non-hibernation sleep states, "standby" is present
-in /sys/power/state in addition to "mem". If the system supports three
-non-hibernation sleep states, "freeze" will be present in /sys/power/state in
-addition to "mem" and "standby".
-
-For relative_sleep_states=0, which is the default, the following descriptions
-apply.
-
-state: Suspend-To-Idle
+"disk", where the last three always represent Power-On Suspend (if supported),
+Suspend-To-Idle and hibernation (Suspend-To-Disk), respectively.
+
+The meaning of the "mem" string is controlled by the /sys/power/mem_sleep file.
+It contains strings representing the available modes of system suspend that may
+be triggered by writing "mem" to /sys/power/state. These modes are "s2idle"
+(Suspend-To-Idle), "shallow" (Power-On Suspend) and "deep" (Suspend-To-RAM).
+The "s2idle" mode is always available, while the other ones are only available
+if supported by the platform (if not supported, the strings representing them
+are not present in /sys/power/mem_sleep). The string representing the suspend
+mode to be used subsequently is enclosed in square brackets. Writing one of
+the other strings present in /sys/power/mem_sleep to it causes the suspend mode
+to be used subsequently to change to the one represented by that string.
+
+Consequently, there are two ways to cause the system to go into the
+Suspend-To-Idle sleep state. The first one is to write "freeze" directly to
+/sys/power/state. The second one is to write "s2idle" to /sys/power/mem_sleep
+and then to wrtie "mem" to /sys/power/state. Similarly, there are two ways
+to cause the system to go into the Power-On Suspend sleep state (the strings to
+write to the control files in that case are "standby" or "shallow" and "mem",
+respectively) if that state is supported by the platform. In turn, there is
+only one way to cause the system to go into the Suspend-To-RAM state (write
+"deep" into /sys/power/mem_sleep and "mem" into /sys/power/state).
+
+The default suspend mode (ie. the one to be used without writing anything into
+/sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
+"s2idle", but it can be overridden by the value of the "mem_sleep_default"
+parameter in the kernel command line. On some ACPI-based systems, depending on
+the information in the FADT, the default may be "s2idle" even if Suspend-To-RAM
+is supported.
+
+The properties of all of the sleep states are described below.
+
+
+State: Suspend-To-Idle
ACPI state: S0
-Label: "freeze"
+Label: "s2idle" ("freeze")
This state is a generic, pure software, light-weight, system sleep state.
It allows more energy to be saved relative to runtime idle by freezing user
@@ -35,13 +53,13 @@ lower-power than available at run time), such that the processors can
spend more time in their idle states.
This state can be used for platforms without Power-On Suspend/Suspend-to-RAM
-support, or it can be used in addition to Suspend-to-RAM (memory sleep)
-to provide reduced resume latency. It is always supported.
+support, or it can be used in addition to Suspend-to-RAM to provide reduced
+resume latency. It is always supported.
State: Standby / Power-On Suspend
ACPI State: S1
-Label: "standby"
+Label: "shallow" ("standby")
This state, if supported, offers moderate, though real, power savings, while
providing a relatively low-latency transition back to a working system. No
@@ -58,7 +76,7 @@ state.
State: Suspend-to-RAM
ACPI State: S3
-Label: "mem"
+Label: "deep"
This state, if supported, offers significant power savings as everything in the
system is put into a low-power state, except for memory, which should be placed
diff --git a/Documentation/power/swsusp-dmcrypt.txt b/Documentation/power/swsusp-dmcrypt.txt
index 59931b46ff7e..b802fbfd95ef 100644
--- a/Documentation/power/swsusp-dmcrypt.txt
+++ b/Documentation/power/swsusp-dmcrypt.txt
@@ -8,7 +8,7 @@ Some prerequisites:
You know how dm-crypt works. If not, visit the following web page:
http://www.saout.de/misc/dm-crypt/
You have read Documentation/power/swsusp.txt and understand it.
-You did read Documentation/initrd.txt and know how an initrd works.
+You did read Documentation/admin-guide/initrd.rst and know how an initrd works.
You know how to create or how to modify an initrd.
Now your system is properly set up, your disk is encrypted except for
diff --git a/Documentation/development-process/1.Intro.rst b/Documentation/process/1.Intro.rst
index 22642b3fe903..e782ae2eef58 100644
--- a/Documentation/development-process/1.Intro.rst
+++ b/Documentation/process/1.Intro.rst
@@ -1,5 +1,5 @@
-Introdution
-===========
+Introduction
+============
Executive summary
-----------------
diff --git a/Documentation/development-process/2.Process.rst b/Documentation/process/2.Process.rst
index ce5561bb3f8e..ce5561bb3f8e 100644
--- a/Documentation/development-process/2.Process.rst
+++ b/Documentation/process/2.Process.rst
diff --git a/Documentation/development-process/3.Early-stage.rst b/Documentation/process/3.Early-stage.rst
index af2c0af931d6..af2c0af931d6 100644
--- a/Documentation/development-process/3.Early-stage.rst
+++ b/Documentation/process/3.Early-stage.rst
diff --git a/Documentation/development-process/4.Coding.rst b/Documentation/process/4.Coding.rst
index 9d5cef996f7f..2a728d898fc5 100644
--- a/Documentation/development-process/4.Coding.rst
+++ b/Documentation/process/4.Coding.rst
@@ -22,7 +22,7 @@ Coding style
************
The kernel has long had a standard coding style, described in
-Documentation/CodingStyle. For much of that time, the policies described
+Documentation/process/coding-style.rst. For much of that time, the policies described
in that file were taken as being, at most, advisory. As a result, there is
a substantial amount of code in the kernel which does not meet the coding
style guidelines. The presence of that code leads to two independent
@@ -343,7 +343,7 @@ user-space developers to know what they are working with. See
Documentation/ABI/README for a description of how this documentation should
be formatted and what information needs to be provided.
-The file Documentation/kernel-parameters.txt describes all of the kernel's
+The file Documentation/admin-guide/kernel-parameters.rst describes all of the kernel's
boot-time parameters. Any patch which adds new parameters should add the
appropriate entries to this file.
@@ -358,8 +358,8 @@ them, as appropriate, for externally-available functions. Even in areas
which have not been so documented, there is no harm in adding kerneldoc
comments for the future; indeed, this can be a useful activity for
beginning kernel developers. The format of these comments, along with some
-information on how to create kerneldoc templates can be found in the file
-Documentation/kernel-documentation.rst.
+information on how to create kerneldoc templates can be found at
+:ref:`Documentation/doc-guide/ <doc_guide>`.
Anybody who reads through a significant amount of existing kernel code will
note that, often, comments are most notable by their absence. Once again,
diff --git a/Documentation/development-process/5.Posting.rst b/Documentation/process/5.Posting.rst
index b511ddf7e82a..1b7728b19ea7 100644
--- a/Documentation/development-process/5.Posting.rst
+++ b/Documentation/process/5.Posting.rst
@@ -9,8 +9,8 @@ kernel. Unsurprisingly, the kernel development community has evolved a set
of conventions and procedures which are used in the posting of patches;
following them will make life much easier for everybody involved. This
document will attempt to cover these expectations in reasonable detail;
-more information can also be found in the files SubmittingPatches,
-SubmittingDrivers, and SubmitChecklist in the kernel documentation
+more information can also be found in the files process/submitting-patches.rst,
+process/submitting-drivers.rst, and process/submit-checklist.rst in the kernel documentation
directory.
@@ -198,7 +198,7 @@ pass it to diff with the "-X" option.
The tags mentioned above are used to describe how various developers have
been associated with the development of this patch. They are described in
-detail in the SubmittingPatches document; what follows here is a brief
+detail in the process/submitting-patches.rst document; what follows here is a brief
summary. Each of these lines has the format:
::
@@ -210,7 +210,7 @@ The tags in common use are:
- Signed-off-by: this is a developer's certification that he or she has
the right to submit the patch for inclusion into the kernel. It is an
agreement to the Developer's Certificate of Origin, the full text of
- which can be found in Documentation/SubmittingPatches. Code without a
+ which can be found in Documentation/process/submitting-patches.rst. Code without a
proper signoff cannot be merged into the mainline.
- Acked-by: indicates an agreement by another developer (often a
@@ -221,7 +221,7 @@ The tags in common use are:
it to work.
- Reviewed-by: the named developer has reviewed the patch for correctness;
- see the reviewer's statement in Documentation/SubmittingPatches for more
+ see the reviewer's statement in Documentation/process/submitting-patches.rst for more
detail.
- Reported-by: names a user who reported a problem which is fixed by this
@@ -248,7 +248,7 @@ take care of:
be examined in any detail. If there is any doubt at all, mail the patch
to yourself and convince yourself that it shows up intact.
- Documentation/email-clients.txt has some helpful hints on making
+ Documentation/process/email-clients.rst has some helpful hints on making
specific mail clients work for sending patches.
- Are you sure your patch is free of silly mistakes? You should always
diff --git a/Documentation/development-process/6.Followthrough.rst b/Documentation/process/6.Followthrough.rst
index a173cd5f93d2..a173cd5f93d2 100644
--- a/Documentation/development-process/6.Followthrough.rst
+++ b/Documentation/process/6.Followthrough.rst
diff --git a/Documentation/development-process/7.AdvancedTopics.rst b/Documentation/process/7.AdvancedTopics.rst
index 81d61c5d62dd..172733cff097 100644
--- a/Documentation/development-process/7.AdvancedTopics.rst
+++ b/Documentation/process/7.AdvancedTopics.rst
@@ -176,5 +176,3 @@ security issues, duplication of code found elsewhere, adequate
documentation, adverse effects on performance, user-space ABI changes, etc.
All types of review, if they lead to better code going into the kernel, are
welcome and worthwhile.
-
-
diff --git a/Documentation/development-process/8.Conclusion.rst b/Documentation/process/8.Conclusion.rst
index 23ec7cbc2d2b..1c7f54cd0261 100644
--- a/Documentation/development-process/8.Conclusion.rst
+++ b/Documentation/process/8.Conclusion.rst
@@ -5,9 +5,9 @@ For more information
There are numerous sources of information on Linux kernel development and
related topics. First among those will always be the Documentation
-directory found in the kernel source distribution. The top-level HOWTO
-file is an important starting point; SubmittingPatches and
-SubmittingDrivers are also something which all kernel developers should
+directory found in the kernel source distribution. The top-level process/howto.rst
+file is an important starting point; process/submitting-patches.rst and
+process/submitting-drivers.rst are also something which all kernel developers should
read. Many internal kernel APIs are documented using the kerneldoc
mechanism; "make htmldocs" or "make pdfdocs" can be used to generate those
documents in HTML or PDF format (though the version of TeX shipped by some
diff --git a/Documentation/adding-syscalls.txt b/Documentation/process/adding-syscalls.rst
index bbb31e091b28..8cc25a06f353 100644
--- a/Documentation/adding-syscalls.txt
+++ b/Documentation/process/adding-syscalls.rst
@@ -3,7 +3,7 @@ Adding a New System Call
This document describes what's involved in adding a new system call to the
Linux kernel, over and above the normal submission advice in
-Documentation/SubmittingPatches.
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
System Call Alternatives
@@ -19,30 +19,33 @@ interface.
object, it may make more sense to create a new filesystem or device. This
also makes it easier to encapsulate the new functionality in a kernel module
rather than requiring it to be built into the main kernel.
+
- If the new functionality involves operations where the kernel notifies
userspace that something has happened, then returning a new file
descriptor for the relevant object allows userspace to use
- poll/select/epoll to receive that notification.
- - However, operations that don't map to read(2)/write(2)-like operations
- have to be implemented as ioctl(2) requests, which can lead to a
- somewhat opaque API.
+ ``poll``/``select``/``epoll`` to receive that notification.
+ - However, operations that don't map to
+ :manpage:`read(2)`/:manpage:`write(2)`-like operations
+ have to be implemented as :manpage:`ioctl(2)` requests, which can lead
+ to a somewhat opaque API.
+
- If you're just exposing runtime system information, a new node in sysfs
- (see Documentation/filesystems/sysfs.txt) or the /proc filesystem may be
- more appropriate. However, access to these mechanisms requires that the
+ (see ``Documentation/filesystems/sysfs.txt``) or the ``/proc`` filesystem may
+ be more appropriate. However, access to these mechanisms requires that the
relevant filesystem is mounted, which might not always be the case (e.g.
in a namespaced/sandboxed/chrooted environment). Avoid adding any API to
debugfs, as this is not considered a 'production' interface to userspace.
- If the operation is specific to a particular file or file descriptor, then
- an additional fcntl(2) command option may be more appropriate. However,
- fcntl(2) is a multiplexing system call that hides a lot of complexity, so
+ an additional :manpage:`fcntl(2)` command option may be more appropriate. However,
+ :manpage:`fcntl(2)` is a multiplexing system call that hides a lot of complexity, so
this option is best for when the new function is closely analogous to
- existing fcntl(2) functionality, or the new functionality is very simple
+ existing :manpage:`fcntl(2)` functionality, or the new functionality is very simple
(for example, getting/setting a simple flag related to a file descriptor).
- If the operation is specific to a particular task or process, then an
- additional prctl(2) command option may be more appropriate. As with
- fcntl(2), this system call is a complicated multiplexor so is best reserved
- for near-analogs of existing prctl() commands or getting/setting a simple
- flag related to a process.
+ additional :manpage:`prctl(2)` command option may be more appropriate. As
+ with :manpage:`fcntl(2)`, this system call is a complicated multiplexor so
+ is best reserved for near-analogs of existing ``prctl()`` commands or
+ getting/setting a simple flag related to a process.
Designing the API: Planning for Extension
@@ -54,15 +57,16 @@ interface on the kernel mailing list, and it's important to plan for future
extensions of the interface.
(The syscall table is littered with historical examples where this wasn't done,
-together with the corresponding follow-up system calls -- eventfd/eventfd2,
-dup2/dup3, inotify_init/inotify_init1, pipe/pipe2, renameat/renameat2 -- so
+together with the corresponding follow-up system calls --
+``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
+``pipe``/``pipe2``, ``renameat``/``renameat2`` -- so
learn from the history of the kernel and plan for extensions from the start.)
For simpler system calls that only take a couple of arguments, the preferred
way to allow for future extensibility is to include a flags argument to the
system call. To make sure that userspace programs can safely use flags
between kernel versions, check whether the flags value holds any unknown
-flags, and reject the system call (with EINVAL) if it does:
+flags, and reject the system call (with ``EINVAL``) if it does::
if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
return -EINVAL;
@@ -72,7 +76,7 @@ flags, and reject the system call (with EINVAL) if it does:
For more sophisticated system calls that involve a larger number of arguments,
it's preferred to encapsulate the majority of the arguments into a structure
that is passed in by pointer. Such a structure can cope with future extension
-by including a size argument in the structure:
+by including a size argument in the structure::
struct xyzzy_params {
u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
@@ -81,19 +85,19 @@ by including a size argument in the structure:
u64 param_3;
};
-As long as any subsequently added field, say param_4, is designed so that a
+As long as any subsequently added field, say ``param_4``, is designed so that a
zero value gives the previous behaviour, then this allows both directions of
version mismatch:
- To cope with a later userspace program calling an older kernel, the kernel
code should check that any memory beyond the size of the structure that it
- expects is zero (effectively checking that param_4 == 0).
+ expects is zero (effectively checking that ``param_4 == 0``).
- To cope with an older userspace program calling a newer kernel, the kernel
code can zero-extend a smaller instance of the structure (effectively
- setting param_4 = 0).
+ setting ``param_4 = 0``).
-See perf_event_open(2) and the perf_copy_attr() function (in
-kernel/events/core.c) for an example of this approach.
+See :manpage:`perf_event_open(2)` and the ``perf_copy_attr()`` function (in
+``kernel/events/core.c``) for an example of this approach.
Designing the API: Other Considerations
@@ -104,57 +108,60 @@ should use a file descriptor as the handle for that object -- don't invent a
new type of userspace object handle when the kernel already has mechanisms and
well-defined semantics for using file descriptors.
-If your new xyzzy(2) system call does return a new file descriptor, then the
-flags argument should include a value that is equivalent to setting O_CLOEXEC
-on the new FD. This makes it possible for userspace to close the timing
-window between xyzzy() and calling fcntl(fd, F_SETFD, FD_CLOEXEC), where an
-unexpected fork() and execve() in another thread could leak a descriptor to
+If your new :manpage:`xyzzy(2)` system call does return a new file descriptor,
+then the flags argument should include a value that is equivalent to setting
+``O_CLOEXEC`` on the new FD. This makes it possible for userspace to close
+the timing window between ``xyzzy()`` and calling
+``fcntl(fd, F_SETFD, FD_CLOEXEC)``, where an unexpected ``fork()`` and
+``execve()`` in another thread could leak a descriptor to
the exec'ed program. (However, resist the temptation to re-use the actual value
-of the O_CLOEXEC constant, as it is architecture-specific and is part of a
-numbering space of O_* flags that is fairly full.)
+of the ``O_CLOEXEC`` constant, as it is architecture-specific and is part of a
+numbering space of ``O_*`` flags that is fairly full.)
If your system call returns a new file descriptor, you should also consider
-what it means to use the poll(2) family of system calls on that file
+what it means to use the :manpage:`poll(2)` family of system calls on that file
descriptor. Making a file descriptor ready for reading or writing is the
normal way for the kernel to indicate to userspace that an event has
occurred on the corresponding kernel object.
-If your new xyzzy(2) system call involves a filename argument:
+If your new :manpage:`xyzzy(2)` system call involves a filename argument::
int sys_xyzzy(const char __user *path, ..., unsigned int flags);
-you should also consider whether an xyzzyat(2) version is more appropriate:
+you should also consider whether an :manpage:`xyzzyat(2)` version is more appropriate::
int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
This allows more flexibility for how userspace specifies the file in question;
in particular it allows userspace to request the functionality for an
-already-opened file descriptor using the AT_EMPTY_PATH flag, effectively giving
-an fxyzzy(3) operation for free:
+already-opened file descriptor using the ``AT_EMPTY_PATH`` flag, effectively
+giving an :manpage:`fxyzzy(3)` operation for free::
- xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...)
- xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)
-(For more details on the rationale of the *at() calls, see the openat(2) man
-page; for an example of AT_EMPTY_PATH, see the fstatat(2) man page.)
-
-If your new xyzzy(2) system call involves a parameter describing an offset
-within a file, make its type loff_t so that 64-bit offsets can be supported
-even on 32-bit architectures.
-
-If your new xyzzy(2) system call involves privileged functionality, it needs
-to be governed by the appropriate Linux capability bit (checked with a call to
-capable()), as described in the capabilities(7) man page. Choose an existing
-capability bit that governs related functionality, but try to avoid combining
-lots of only vaguely related functions together under the same bit, as this
-goes against capabilities' purpose of splitting the power of root. In
-particular, avoid adding new uses of the already overly-general CAP_SYS_ADMIN
-capability.
-
-If your new xyzzy(2) system call manipulates a process other than the calling
-process, it should be restricted (using a call to ptrace_may_access()) so that
-only a calling process with the same permissions as the target process, or
-with the necessary capabilities, can manipulate the target process.
+(For more details on the rationale of the \*at() calls, see the
+:manpage:`openat(2)` man page; for an example of AT_EMPTY_PATH, see the
+:manpage:`fstatat(2)` man page.)
+
+If your new :manpage:`xyzzy(2)` system call involves a parameter describing an
+offset within a file, make its type ``loff_t`` so that 64-bit offsets can be
+supported even on 32-bit architectures.
+
+If your new :manpage:`xyzzy(2)` system call involves privileged functionality,
+it needs to be governed by the appropriate Linux capability bit (checked with
+a call to ``capable()``), as described in the :manpage:`capabilities(7)` man
+page. Choose an existing capability bit that governs related functionality,
+but try to avoid combining lots of only vaguely related functions together
+under the same bit, as this goes against capabilities' purpose of splitting
+the power of root. In particular, avoid adding new uses of the already
+overly-general ``CAP_SYS_ADMIN`` capability.
+
+If your new :manpage:`xyzzy(2)` system call manipulates a process other than
+the calling process, it should be restricted (using a call to
+``ptrace_may_access()``) so that only a calling process with the same
+permissions as the target process, or with the necessary capabilities, can
+manipulate the target process.
Finally, be aware that some non-x86 architectures have an easier time if
system call parameters that are explicitly 64-bit fall on odd-numbered
@@ -175,7 +182,7 @@ distinct commits (each of which is described further below):
- Wiring up of the new system call for one particular architecture, usually
x86 (including all of x86_64, x86_32 and x32).
- A demonstration of the use of the new system call in userspace via a
- selftest in tools/testing/selftests/.
+ selftest in ``tools/testing/selftests/``.
- A draft man-page for the new system call, either as plain text in the
cover letter, or as a patch to the (separate) man-pages repository.
@@ -186,24 +193,24 @@ be cc'ed to linux-api@vger.kernel.org.
Generic System Call Implementation
----------------------------------
-The main entry point for your new xyzzy(2) system call will be called
-sys_xyzzy(), but you add this entry point with the appropriate
-SYSCALL_DEFINEn() macro rather than explicitly. The 'n' indicates the number
-of arguments to the system call, and the macro takes the system call name
+The main entry point for your new :manpage:`xyzzy(2)` system call will be called
+``sys_xyzzy()``, but you add this entry point with the appropriate
+``SYSCALL_DEFINEn()`` macro rather than explicitly. The 'n' indicates the
+number of arguments to the system call, and the macro takes the system call name
followed by the (type, name) pairs for the parameters as arguments. Using
this macro allows metadata about the new system call to be made available for
other tools.
The new entry point also needs a corresponding function prototype, in
-include/linux/syscalls.h, marked as asmlinkage to match the way that system
-calls are invoked:
+``include/linux/syscalls.h``, marked as asmlinkage to match the way that system
+calls are invoked::
asmlinkage long sys_xyzzy(...);
Some architectures (e.g. x86) have their own architecture-specific syscall
tables, but several other architectures share a generic syscall table. Add your
new system call to the generic list by adding an entry to the list in
-include/uapi/asm-generic/unistd.h:
+``include/uapi/asm-generic/unistd.h``::
#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)
@@ -212,30 +219,30 @@ Also update the __NR_syscalls count to reflect the additional system call, and
note that if multiple new system calls are added in the same merge window,
your new syscall number may get adjusted to resolve conflicts.
-The file kernel/sys_ni.c provides a fallback stub implementation of each system
-call, returning -ENOSYS. Add your new system call here too:
+The file ``kernel/sys_ni.c`` provides a fallback stub implementation of each
+system call, returning ``-ENOSYS``. Add your new system call here too::
cond_syscall(sys_xyzzy);
Your new kernel functionality, and the system call that controls it, should
-normally be optional, so add a CONFIG option (typically to init/Kconfig) for
-it. As usual for new CONFIG options:
+normally be optional, so add a ``CONFIG`` option (typically to
+``init/Kconfig``) for it. As usual for new ``CONFIG`` options:
- Include a description of the new functionality and system call controlled
by the option.
- Make the option depend on EXPERT if it should be hidden from normal users.
- Make any new source files implementing the function dependent on the CONFIG
- option in the Makefile (e.g. "obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.c").
+ option in the Makefile (e.g. ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.c``).
- Double check that the kernel still builds with the new CONFIG option turned
off.
To summarize, you need a commit that includes:
- - CONFIG option for the new function, normally in init/Kconfig
- - SYSCALL_DEFINEn(xyzzy, ...) for the entry point
- - corresponding prototype in include/linux/syscalls.h
- - generic table entry in include/uapi/asm-generic/unistd.h
- - fallback stub in kernel/sys_ni.c
+ - ``CONFIG`` option for the new function, normally in ``init/Kconfig``
+ - ``SYSCALL_DEFINEn(xyzzy, ...)`` for the entry point
+ - corresponding prototype in ``include/linux/syscalls.h``
+ - generic table entry in ``include/uapi/asm-generic/unistd.h``
+ - fallback stub in ``kernel/sys_ni.c``
x86 System Call Implementation
@@ -244,11 +251,11 @@ x86 System Call Implementation
To wire up your new system call for x86 platforms, you need to update the
master syscall tables. Assuming your new system call isn't special in some
way (see below), this involves a "common" entry (for x86_64 and x32) in
-arch/x86/entry/syscalls/syscall_64.tbl:
+arch/x86/entry/syscalls/syscall_64.tbl::
333 common xyzzy sys_xyzzy
-and an "i386" entry in arch/x86/entry/syscalls/syscall_32.tbl:
+and an "i386" entry in ``arch/x86/entry/syscalls/syscall_32.tbl``::
380 i386 xyzzy sys_xyzzy
@@ -267,48 +274,49 @@ However, there are a couple of situations where a compatibility layer is
needed to cope with size differences between 32-bit and 64-bit.
The first is if the 64-bit kernel also supports 32-bit userspace programs, and
-so needs to parse areas of (__user) memory that could hold either 32-bit or
+so needs to parse areas of (``__user``) memory that could hold either 32-bit or
64-bit values. In particular, this is needed whenever a system call argument
is:
- a pointer to a pointer
- - a pointer to a struct containing a pointer (e.g. struct iovec __user *)
- - a pointer to a varying sized integral type (time_t, off_t, long, ...)
+ - a pointer to a struct containing a pointer (e.g. ``struct iovec __user *``)
+ - a pointer to a varying sized integral type (``time_t``, ``off_t``,
+ ``long``, ...)
- a pointer to a struct containing a varying sized integral type.
The second situation that requires a compatibility layer is if one of the
system call's arguments has a type that is explicitly 64-bit even on a 32-bit
-architecture, for example loff_t or __u64. In this case, a value that arrives
-at a 64-bit kernel from a 32-bit application will be split into two 32-bit
-values, which then need to be re-assembled in the compatibility layer.
+architecture, for example ``loff_t`` or ``__u64``. In this case, a value that
+arrives at a 64-bit kernel from a 32-bit application will be split into two
+32-bit values, which then need to be re-assembled in the compatibility layer.
(Note that a system call argument that's a pointer to an explicit 64-bit type
-does *not* need a compatibility layer; for example, splice(2)'s arguments of
-type loff_t __user * do not trigger the need for a compat_ system call.)
+does **not** need a compatibility layer; for example, :manpage:`splice(2)`'s arguments of
+type ``loff_t __user *`` do not trigger the need for a ``compat_`` system call.)
-The compatibility version of the system call is called compat_sys_xyzzy(), and
-is added with the COMPAT_SYSCALL_DEFINEn() macro, analogously to
+The compatibility version of the system call is called ``compat_sys_xyzzy()``,
+and is added with the ``COMPAT_SYSCALL_DEFINEn()`` macro, analogously to
SYSCALL_DEFINEn. This version of the implementation runs as part of a 64-bit
kernel, but expects to receive 32-bit parameter values and does whatever is
-needed to deal with them. (Typically, the compat_sys_ version converts the
-values to 64-bit versions and either calls on to the sys_ version, or both of
+needed to deal with them. (Typically, the ``compat_sys_`` version converts the
+values to 64-bit versions and either calls on to the ``sys_`` version, or both of
them call a common inner implementation function.)
The compat entry point also needs a corresponding function prototype, in
-include/linux/compat.h, marked as asmlinkage to match the way that system
-calls are invoked:
+``include/linux/compat.h``, marked as asmlinkage to match the way that system
+calls are invoked::
asmlinkage long compat_sys_xyzzy(...);
If the system call involves a structure that is laid out differently on 32-bit
-and 64-bit systems, say struct xyzzy_args, then the include/linux/compat.h
-header file should also include a compat version of the structure (struct
-compat_xyzzy_args) where each variable-size field has the appropriate compat_
-type that corresponds to the type in struct xyzzy_args. The
-compat_sys_xyzzy() routine can then use this compat_ structure to parse the
-arguments from a 32-bit invocation.
+and 64-bit systems, say ``struct xyzzy_args``, then the include/linux/compat.h
+header file should also include a compat version of the structure (``struct
+compat_xyzzy_args``) where each variable-size field has the appropriate
+``compat_`` type that corresponds to the type in ``struct xyzzy_args``. The
+``compat_sys_xyzzy()`` routine can then use this ``compat_`` structure to
+parse the arguments from a 32-bit invocation.
-For example, if there are fields:
+For example, if there are fields::
struct xyzzy_args {
const char __user *ptr;
@@ -317,7 +325,7 @@ For example, if there are fields:
/* ... */
};
-in struct xyzzy_args, then struct compat_xyzzy_args would have:
+in struct xyzzy_args, then struct compat_xyzzy_args would have::
struct compat_xyzzy_args {
compat_uptr_t ptr;
@@ -327,18 +335,19 @@ in struct xyzzy_args, then struct compat_xyzzy_args would have:
};
The generic system call list also needs adjusting to allow for the compat
-version; the entry in include/uapi/asm-generic/unistd.h should use
-__SC_COMP rather than __SYSCALL:
+version; the entry in ``include/uapi/asm-generic/unistd.h`` should use
+``__SC_COMP`` rather than ``__SYSCALL``::
#define __NR_xyzzy 292
__SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
To summarize, you need:
- - a COMPAT_SYSCALL_DEFINEn(xyzzy, ...) for the compat entry point
- - corresponding prototype in include/linux/compat.h
- - (if needed) 32-bit mapping struct in include/linux/compat.h
- - instance of __SC_COMP not __SYSCALL in include/uapi/asm-generic/unistd.h
+ - a ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` for the compat entry point
+ - corresponding prototype in ``include/linux/compat.h``
+ - (if needed) 32-bit mapping struct in ``include/linux/compat.h``
+ - instance of ``__SC_COMP`` not ``__SYSCALL`` in
+ ``include/uapi/asm-generic/unistd.h``
Compatibility System Calls (x86)
@@ -347,9 +356,9 @@ Compatibility System Calls (x86)
To wire up the x86 architecture of a system call with a compatibility version,
the entries in the syscall tables need to be adjusted.
-First, the entry in arch/x86/entry/syscalls/syscall_32.tbl gets an extra
+First, the entry in ``arch/x86/entry/syscalls/syscall_32.tbl`` gets an extra
column to indicate that a 32-bit userspace program running on a 64-bit kernel
-should hit the compat entry point:
+should hit the compat entry point::
380 i386 xyzzy sys_xyzzy compat_sys_xyzzy
@@ -359,8 +368,8 @@ should either match the 64-bit version or the 32-bit version.
If there's a pointer-to-a-pointer involved, the decision is easy: x32 is
ILP32, so the layout should match the 32-bit version, and the entry in
-arch/x86/entry/syscalls/syscall_64.tbl is split so that x32 programs hit the
-compatibility wrapper:
+``arch/x86/entry/syscalls/syscall_64.tbl`` is split so that x32 programs hit
+the compatibility wrapper::
333 64 xyzzy sys_xyzzy
...
@@ -384,8 +393,9 @@ stack the same and most of the registers the same as before the system call,
and with the same virtual memory space.
However, a few system calls do things differently. They might return to a
-different location (rt_sigreturn) or change the memory space (fork/vfork/clone)
-or even architecture (execve/execveat) of the program.
+different location (``rt_sigreturn``) or change the memory space
+(``fork``/``vfork``/``clone``) or even architecture (``execve``/``execveat``)
+of the program.
To allow for this, the kernel implementation of the system call may need to
save and restore additional registers to the kernel stack, allowing complete
@@ -395,31 +405,31 @@ This is arch-specific, but typically involves defining assembly entry points
that save/restore additional registers and invoke the real system call entry
point.
-For x86_64, this is implemented as a stub_xyzzy entry point in
-arch/x86/entry/entry_64.S, and the entry in the syscall table
-(arch/x86/entry/syscalls/syscall_64.tbl) is adjusted to match:
+For x86_64, this is implemented as a ``stub_xyzzy`` entry point in
+``arch/x86/entry/entry_64.S``, and the entry in the syscall table
+(``arch/x86/entry/syscalls/syscall_64.tbl``) is adjusted to match::
333 common xyzzy stub_xyzzy
The equivalent for 32-bit programs running on a 64-bit kernel is normally
-called stub32_xyzzy and implemented in arch/x86/entry/entry_64_compat.S,
+called ``stub32_xyzzy`` and implemented in ``arch/x86/entry/entry_64_compat.S``,
with the corresponding syscall table adjustment in
-arch/x86/entry/syscalls/syscall_32.tbl:
+``arch/x86/entry/syscalls/syscall_32.tbl``::
380 i386 xyzzy sys_xyzzy stub32_xyzzy
If the system call needs a compatibility layer (as in the previous section)
-then the stub32_ version needs to call on to the compat_sys_ version of the
-system call rather than the native 64-bit version. Also, if the x32 ABI
+then the ``stub32_`` version needs to call on to the ``compat_sys_`` version
+of the system call rather than the native 64-bit version. Also, if the x32 ABI
implementation is not common with the x86_64 version, then its syscall
-table will also need to invoke a stub that calls on to the compat_sys_
+table will also need to invoke a stub that calls on to the ``compat_sys_``
version.
For completeness, it's also nice to set up a mapping so that user-mode Linux
still works -- its syscall table will reference stub_xyzzy, but the UML build
-doesn't include arch/x86/entry/entry_64.S implementation (because UML
+doesn't include ``arch/x86/entry/entry_64.S`` implementation (because UML
simulates registers etc). Fixing this is as simple as adding a #define to
-arch/x86/um/sys_call_table_64.c:
+``arch/x86/um/sys_call_table_64.c``::
#define stub_xyzzy sys_xyzzy
@@ -432,9 +442,9 @@ occasional exception that may need updating for your particular system call.
The audit subsystem is one such special case; it includes (arch-specific)
functions that classify some special types of system call -- specifically
-file open (open/openat), program execution (execve/exeveat) or socket
-multiplexor (socketcall) operations. If your new system call is analogous to
-one of these, then the audit system should be updated.
+file open (``open``/``openat``), program execution (``execve``/``exeveat``) or
+socket multiplexor (``socketcall``) operations. If your new system call is
+analogous to one of these, then the audit system should be updated.
More generally, if there is an existing system call that is analogous to your
new system call, it's worth doing a kernel-wide grep for the existing system
@@ -447,10 +457,10 @@ Testing
A new system call should obviously be tested; it is also useful to provide
reviewers with a demonstration of how user space programs will use the system
call. A good way to combine these aims is to include a simple self-test
-program in a new directory under tools/testing/selftests/.
+program in a new directory under ``tools/testing/selftests/``.
For a new system call, there will obviously be no libc wrapper function and so
-the test will need to invoke it using syscall(); also, if the system call
+the test will need to invoke it using ``syscall()``; also, if the system call
involves a new userspace-visible structure, the corresponding header will need
to be installed to compile the test.
@@ -461,6 +471,7 @@ and x32 (-mx32) ABI program.
For more extensive and thorough testing of new functionality, you should also
consider adding tests to the Linux Test Project, or to the xfstests project
for filesystem-related changes.
+
- https://linux-test-project.github.io/
- git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git
@@ -487,12 +498,14 @@ References and Sources
arguments: https://lwn.net/Articles/311630/
- Pair of LWN articles from David Drysdale that describe the system call
implementation paths in detail for v3.14:
+
- https://lwn.net/Articles/604287/
- https://lwn.net/Articles/604515/
+
- Architecture-specific requirements for system calls are discussed in the
- syscall(2) man-page:
+ :manpage:`syscall(2)` man-page:
http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
- - Collated emails from Linus Torvalds discussing the problems with ioctl():
+ - Collated emails from Linus Torvalds discussing the problems with ``ioctl()``:
http://yarchive.net/comp/linux/ioctl.html
- "How to not invent kernel interfaces", Arnd Bergmann,
http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
@@ -507,17 +520,19 @@ References and Sources
commit: https://lkml.org/lkml/2014/11/19/254
- Suggestion from Greg Kroah-Hartman that it's good for new system calls to
come with a man-page & selftest: https://lkml.org/lkml/2014/3/19/710
- - Discussion from Michael Kerrisk of new system call vs. prctl(2) extension:
+ - Discussion from Michael Kerrisk of new system call vs. :manpage:`prctl(2)` extension:
https://lkml.org/lkml/2014/6/3/411
- Suggestion from Ingo Molnar that system calls that involve multiple
arguments should encapsulate those arguments in a struct, which includes a
size field for future extensibility: https://lkml.org/lkml/2015/7/30/117
- Numbering oddities arising from (re-)use of O_* numbering space flags:
+
- commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
check")
- commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
conflict")
- commit bb458c644a59 ("Safer ABI for O_TMPFILE")
+
- Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
https://lkml.org/lkml/2008/12/12/187
- Recommendation from Greg Kroah-Hartman that unknown flags should be
diff --git a/Documentation/applying-patches.txt b/Documentation/process/applying-patches.rst
index 02ce4924468e..87825cf96f33 100644
--- a/Documentation/applying-patches.txt
+++ b/Documentation/process/applying-patches.rst
@@ -9,6 +9,10 @@ Original by:
Last update:
2016-09-14
+.. note::
+
+ This document is obsolete. In most cases, rather than using ``patch``
+ manually, you'll almost certainly want to look at using Git instead.
A frequently asked question on the Linux Kernel Mailing List is how to apply
a patch to the kernel or, more specifically, what base kernel a patch for
@@ -427,7 +431,7 @@ The -mm patches are experimental patches released by Andrew Morton.
In the past, -mm tree were used to also test subsystem patches, but this
function is now done via the
-:ref:`linux-next <https://www.kernel.org/doc/man-pages/linux-next.html>`
+`linux-next <https://www.kernel.org/doc/man-pages/linux-next.html>`
tree. The Subsystem maintainers push their patches first to linux-next,
and, during the merge window, sends them directly to Linus.
@@ -462,4 +466,3 @@ the kernel.
Thank you's to Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
Johannes Stezenbach, Grant Coady, Pavel Machek and others that I may have
forgotten for their reviews and contributions to this document.
-
diff --git a/Documentation/Changes b/Documentation/process/changes.rst
index 22797a15dc24..56ce66114665 100644
--- a/Documentation/Changes
+++ b/Documentation/process/changes.rst
@@ -1,6 +1,6 @@
.. _changes:
-Minimal requerements to compile the Kernel
+Minimal requirements to compile the Kernel
++++++++++++++++++++++++++++++++++++++++++
Intro
diff --git a/Documentation/CodeOfConflict b/Documentation/process/code-of-conflict.rst
index 49a8ecc157a2..47b6de763203 100644
--- a/Documentation/CodeOfConflict
+++ b/Documentation/process/code-of-conflict.rst
@@ -19,7 +19,8 @@ please contact the Linux Foundation's Technical Advisory Board at
will work to resolve the issue to the best of their ability. For more
information on who is on the Technical Advisory Board and what their
role is, please see:
- http://www.linuxfoundation.org/projects/linux/tab
+
+ - http://www.linuxfoundation.org/projects/linux/tab
As a reviewer of code, please strive to keep things civil and focused on
the technical issues involved. We are all humans, and frustrations can
diff --git a/Documentation/process/coding-style.rst b/Documentation/process/coding-style.rst
new file mode 100644
index 000000000000..d20d52a4d812
--- /dev/null
+++ b/Documentation/process/coding-style.rst
@@ -0,0 +1,1062 @@
+.. _codingstyle:
+
+Linux kernel coding style
+=========================
+
+This is a short document describing the preferred coding style for the
+linux kernel. Coding style is very personal, and I won't **force** my
+views on anybody, but this is what goes for anything that I have to be
+able to maintain, and I'd prefer it for most other things too. Please
+at least consider the points made here.
+
+First off, I'd suggest printing out a copy of the GNU coding standards,
+and NOT read it. Burn them, it's a great symbolic gesture.
+
+Anyway, here goes:
+
+
+1) Indentation
+--------------
+
+Tabs are 8 characters, and thus indentations are also 8 characters.
+There are heretic movements that try to make indentations 4 (or even 2!)
+characters deep, and that is akin to trying to define the value of PI to
+be 3.
+
+Rationale: The whole idea behind indentation is to clearly define where
+a block of control starts and ends. Especially when you've been looking
+at your screen for 20 straight hours, you'll find it a lot easier to see
+how the indentation works if you have large indentations.
+
+Now, some people will claim that having 8-character indentations makes
+the code move too far to the right, and makes it hard to read on a
+80-character terminal screen. The answer to that is that if you need
+more than 3 levels of indentation, you're screwed anyway, and should fix
+your program.
+
+In short, 8-char indents make things easier to read, and have the added
+benefit of warning you when you're nesting your functions too deep.
+Heed that warning.
+
+The preferred way to ease multiple indentation levels in a switch statement is
+to align the ``switch`` and its subordinate ``case`` labels in the same column
+instead of ``double-indenting`` the ``case`` labels. E.g.:
+
+.. code-block:: c
+
+ switch (suffix) {
+ case 'G':
+ case 'g':
+ mem <<= 30;
+ break;
+ case 'M':
+ case 'm':
+ mem <<= 20;
+ break;
+ case 'K':
+ case 'k':
+ mem <<= 10;
+ /* fall through */
+ default:
+ break;
+ }
+
+Don't put multiple statements on a single line unless you have
+something to hide:
+
+.. code-block:: c
+
+ if (condition) do_this;
+ do_something_everytime;
+
+Don't put multiple assignments on a single line either. Kernel coding style
+is super simple. Avoid tricky expressions.
+
+Outside of comments, documentation and except in Kconfig, spaces are never
+used for indentation, and the above example is deliberately broken.
+
+Get a decent editor and don't leave whitespace at the end of lines.
+
+
+2) Breaking long lines and strings
+----------------------------------
+
+Coding style is all about readability and maintainability using commonly
+available tools.
+
+The limit on the length of lines is 80 columns and this is a strongly
+preferred limit.
+
+Statements longer than 80 columns will be broken into sensible chunks, unless
+exceeding 80 columns significantly increases readability and does not hide
+information. Descendants are always substantially shorter than the parent and
+are placed substantially to the right. The same applies to function headers
+with a long argument list. However, never break user-visible strings such as
+printk messages, because that breaks the ability to grep for them.
+
+
+3) Placing Braces and Spaces
+----------------------------
+
+The other issue that always comes up in C styling is the placement of
+braces. Unlike the indent size, there are few technical reasons to
+choose one placement strategy over the other, but the preferred way, as
+shown to us by the prophets Kernighan and Ritchie, is to put the opening
+brace last on the line, and put the closing brace first, thusly:
+
+.. code-block:: c
+
+ if (x is true) {
+ we do y
+ }
+
+This applies to all non-function statement blocks (if, switch, for,
+while, do). E.g.:
+
+.. code-block:: c
+
+ switch (action) {
+ case KOBJ_ADD:
+ return "add";
+ case KOBJ_REMOVE:
+ return "remove";
+ case KOBJ_CHANGE:
+ return "change";
+ default:
+ return NULL;
+ }
+
+However, there is one special case, namely functions: they have the
+opening brace at the beginning of the next line, thus:
+
+.. code-block:: c
+
+ int function(int x)
+ {
+ body of function
+ }
+
+Heretic people all over the world have claimed that this inconsistency
+is ... well ... inconsistent, but all right-thinking people know that
+(a) K&R are **right** and (b) K&R are right. Besides, functions are
+special anyway (you can't nest them in C).
+
+Note that the closing brace is empty on a line of its own, **except** in
+the cases where it is followed by a continuation of the same statement,
+ie a ``while`` in a do-statement or an ``else`` in an if-statement, like
+this:
+
+.. code-block:: c
+
+ do {
+ body of do-loop
+ } while (condition);
+
+and
+
+.. code-block:: c
+
+ if (x == y) {
+ ..
+ } else if (x > y) {
+ ...
+ } else {
+ ....
+ }
+
+Rationale: K&R.
+
+Also, note that this brace-placement also minimizes the number of empty
+(or almost empty) lines, without any loss of readability. Thus, as the
+supply of new-lines on your screen is not a renewable resource (think
+25-line terminal screens here), you have more empty lines to put
+comments on.
+
+Do not unnecessarily use braces where a single statement will do.
+
+.. code-block:: c
+
+ if (condition)
+ action();
+
+and
+
+.. code-block:: none
+
+ if (condition)
+ do_this();
+ else
+ do_that();
+
+This does not apply if only one branch of a conditional statement is a single
+statement; in the latter case use braces in both branches:
+
+.. code-block:: c
+
+ if (condition) {
+ do_this();
+ do_that();
+ } else {
+ otherwise();
+ }
+
+3.1) Spaces
+***********
+
+Linux kernel style for use of spaces depends (mostly) on
+function-versus-keyword usage. Use a space after (most) keywords. The
+notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
+somewhat like functions (and are usually used with parentheses in Linux,
+although they are not required in the language, as in: ``sizeof info`` after
+``struct fileinfo info;`` is declared).
+
+So use a space after these keywords::
+
+ if, switch, case, for, do, while
+
+but not with sizeof, typeof, alignof, or __attribute__. E.g.,
+
+.. code-block:: c
+
+
+ s = sizeof(struct file);
+
+Do not add spaces around (inside) parenthesized expressions. This example is
+**bad**:
+
+.. code-block:: c
+
+
+ s = sizeof( struct file );
+
+When declaring pointer data or a function that returns a pointer type, the
+preferred use of ``*`` is adjacent to the data name or function name and not
+adjacent to the type name. Examples:
+
+.. code-block:: c
+
+
+ char *linux_banner;
+ unsigned long long memparse(char *ptr, char **retptr);
+ char *match_strdup(substring_t *s);
+
+Use one space around (on each side of) most binary and ternary operators,
+such as any of these::
+
+ = + - < > * / % | & ^ <= >= == != ? :
+
+but no space after unary operators::
+
+ & * + - ~ ! sizeof typeof alignof __attribute__ defined
+
+no space before the postfix increment & decrement unary operators::
+
+ ++ --
+
+no space after the prefix increment & decrement unary operators::
+
+ ++ --
+
+and no space around the ``.`` and ``->`` structure member operators.
+
+Do not leave trailing whitespace at the ends of lines. Some editors with
+``smart`` indentation will insert whitespace at the beginning of new lines as
+appropriate, so you can start typing the next line of code right away.
+However, some such editors do not remove the whitespace if you end up not
+putting a line of code there, such as if you leave a blank line. As a result,
+you end up with lines containing trailing whitespace.
+
+Git will warn you about patches that introduce trailing whitespace, and can
+optionally strip the trailing whitespace for you; however, if applying a series
+of patches, this may make later patches in the series fail by changing their
+context lines.
+
+
+4) Naming
+---------
+
+C is a Spartan language, and so should your naming be. Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter. A C programmer would call that
+variable ``tmp``, which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must. To call a global function ``foo`` is a
+shooting offense.
+
+GLOBAL variables (to be used only if you **really** need them) need to
+have descriptive names, as do global functions. If you have a function
+that counts the number of active users, you should call that
+``count_active_users()`` or similar, you should **not** call it ``cntusr()``.
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer. No wonder MicroSoft
+makes buggy programs.
+
+LOCAL variable names should be short, and to the point. If you have
+some random integer loop counter, it should probably be called ``i``.
+Calling it ``loop_counter`` is non-productive, if there is no chance of it
+being mis-understood. Similarly, ``tmp`` can be just about any type of
+variable that is used to hold a temporary value.
+
+If you are afraid to mix up your local variable names, you have another
+problem, which is called the function-growth-hormone-imbalance syndrome.
+See chapter 6 (Functions).
+
+
+5) Typedefs
+-----------
+
+Please don't use things like ``vps_t``.
+It's a **mistake** to use typedef for structures and pointers. When you see a
+
+.. code-block:: c
+
+
+ vps_t a;
+
+in the source, what does it mean?
+In contrast, if it says
+
+.. code-block:: c
+
+ struct virtual_container *a;
+
+you can actually tell what ``a`` is.
+
+Lots of people think that typedefs ``help readability``. Not so. They are
+useful only for:
+
+ (a) totally opaque objects (where the typedef is actively used to **hide**
+ what the object is).
+
+ Example: ``pte_t`` etc. opaque objects that you can only access using
+ the proper accessor functions.
+
+ .. note::
+
+ Opaqueness and ``accessor functions`` are not good in themselves.
+ The reason we have them for things like pte_t etc. is that there
+ really is absolutely **zero** portably accessible information there.
+
+ (b) Clear integer types, where the abstraction **helps** avoid confusion
+ whether it is ``int`` or ``long``.
+
+ u8/u16/u32 are perfectly fine typedefs, although they fit into
+ category (d) better than here.
+
+ .. note::
+
+ Again - there needs to be a **reason** for this. If something is
+ ``unsigned long``, then there's no reason to do
+
+ typedef unsigned long myflags_t;
+
+ but if there is a clear reason for why it under certain circumstances
+ might be an ``unsigned int`` and under other configurations might be
+ ``unsigned long``, then by all means go ahead and use a typedef.
+
+ (c) when you use sparse to literally create a **new** type for
+ type-checking.
+
+ (d) New types which are identical to standard C99 types, in certain
+ exceptional circumstances.
+
+ Although it would only take a short amount of time for the eyes and
+ brain to become accustomed to the standard types like ``uint32_t``,
+ some people object to their use anyway.
+
+ Therefore, the Linux-specific ``u8/u16/u32/u64`` types and their
+ signed equivalents which are identical to standard types are
+ permitted -- although they are not mandatory in new code of your
+ own.
+
+ When editing existing code which already uses one or the other set
+ of types, you should conform to the existing choices in that code.
+
+ (e) Types safe for use in userspace.
+
+ In certain structures which are visible to userspace, we cannot
+ require C99 types and cannot use the ``u32`` form above. Thus, we
+ use __u32 and similar types in all structures which are shared
+ with userspace.
+
+Maybe there are other cases too, but the rule should basically be to NEVER
+EVER use a typedef unless you can clearly match one of those rules.
+
+In general, a pointer, or a struct that has elements that can reasonably
+be directly accessed should **never** be a typedef.
+
+
+6) Functions
+------------
+
+Functions should be short and sweet, and do just one thing. They should
+fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
+as we all know), and do one thing and do that well.
+
+The maximum length of a function is inversely proportional to the
+complexity and indentation level of that function. So, if you have a
+conceptually simple function that is just one long (but simple)
+case-statement, where you have to do lots of small things for a lot of
+different cases, it's OK to have a longer function.
+
+However, if you have a complex function, and you suspect that a
+less-than-gifted first-year high-school student might not even
+understand what the function is all about, you should adhere to the
+maximum limits all the more closely. Use helper functions with
+descriptive names (you can ask the compiler to in-line them if you think
+it's performance-critical, and it will probably do a better job of it
+than you would have done).
+
+Another measure of the function is the number of local variables. They
+shouldn't exceed 5-10, or you're doing something wrong. Re-think the
+function, and split it into smaller pieces. A human brain can
+generally easily keep track of about 7 different things, anything more
+and it gets confused. You know you're brilliant, but maybe you'd like
+to understand what you did 2 weeks from now.
+
+In source files, separate functions with one blank line. If the function is
+exported, the **EXPORT** macro for it should follow immediately after the
+closing function brace line. E.g.:
+
+.. code-block:: c
+
+ int system_is_up(void)
+ {
+ return system_state == SYSTEM_RUNNING;
+ }
+ EXPORT_SYMBOL(system_is_up);
+
+In function prototypes, include parameter names with their data types.
+Although this is not required by the C language, it is preferred in Linux
+because it is a simple way to add valuable information for the reader.
+
+
+7) Centralized exiting of functions
+-----------------------------------
+
+Albeit deprecated by some people, the equivalent of the goto statement is
+used frequently by compilers in form of the unconditional jump instruction.
+
+The goto statement comes in handy when a function exits from multiple
+locations and some common work such as cleanup has to be done. If there is no
+cleanup needed then just return directly.
+
+Choose label names which say what the goto does or why the goto exists. An
+example of a good name could be ``out_free_buffer:`` if the goto frees ``buffer``.
+Avoid using GW-BASIC names like ``err1:`` and ``err2:``, as you would have to
+renumber them if you ever add or remove exit paths, and they make correctness
+difficult to verify anyway.
+
+The rationale for using gotos is:
+
+- unconditional statements are easier to understand and follow
+- nesting is reduced
+- errors by not updating individual exit points when making
+ modifications are prevented
+- saves the compiler work to optimize redundant code away ;)
+
+.. code-block:: c
+
+ int fun(int a)
+ {
+ int result = 0;
+ char *buffer;
+
+ buffer = kmalloc(SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (condition1) {
+ while (loop1) {
+ ...
+ }
+ result = 1;
+ goto out_free_buffer;
+ }
+ ...
+ out_free_buffer:
+ kfree(buffer);
+ return result;
+ }
+
+A common type of bug to be aware of is ``one err bugs`` which look like this:
+
+.. code-block:: c
+
+ err:
+ kfree(foo->bar);
+ kfree(foo);
+ return ret;
+
+The bug in this code is that on some exit paths ``foo`` is NULL. Normally the
+fix for this is to split it up into two error labels ``err_free_bar:`` and
+``err_free_foo:``:
+
+.. code-block:: c
+
+ err_free_bar:
+ kfree(foo->bar);
+ err_free_foo:
+ kfree(foo);
+ return ret;
+
+Ideally you should simulate errors to test all exit paths.
+
+
+8) Commenting
+-------------
+
+Comments are good, but there is also a danger of over-commenting. NEVER
+try to explain HOW your code works in a comment: it's much better to
+write the code so that the **working** is obvious, and it's a waste of
+time to explain badly written code.
+
+Generally, you want your comments to tell WHAT your code does, not HOW.
+Also, try to avoid putting comments inside a function body: if the
+function is so complex that you need to separately comment parts of it,
+you should probably go back to chapter 6 for a while. You can make
+small comments to note or warn about something particularly clever (or
+ugly), but try to avoid excess. Instead, put the comments at the head
+of the function, telling people what it does, and possibly WHY it does
+it.
+
+When commenting the kernel API functions, please use the kernel-doc format.
+See the files at :ref:`Documentation/doc-guide/ <doc_guide>` and
+``scripts/kernel-doc`` for details.
+
+The preferred style for long (multi-line) comments is:
+
+.. code-block:: c
+
+ /*
+ * This is the preferred style for multi-line
+ * comments in the Linux kernel source code.
+ * Please use it consistently.
+ *
+ * Description: A column of asterisks on the left side,
+ * with beginning and ending almost-blank lines.
+ */
+
+For files in net/ and drivers/net/ the preferred style for long (multi-line)
+comments is a little different.
+
+.. code-block:: c
+
+ /* The preferred comment style for files in net/ and drivers/net
+ * looks like this.
+ *
+ * It is nearly the same as the generally preferred comment style,
+ * but there is no initial almost-blank line.
+ */
+
+It's also important to comment data, whether they are basic types or derived
+types. To this end, use just one data declaration per line (no commas for
+multiple data declarations). This leaves you room for a small comment on each
+item, explaining its use.
+
+
+9) You've made a mess of it
+---------------------------
+
+That's OK, we all do. You've probably been told by your long-time Unix
+user helper that ``GNU emacs`` automatically formats the C sources for
+you, and you've noticed that yes, it does do that, but the defaults it
+uses are less than desirable (in fact, they are worse than random
+typing - an infinite number of monkeys typing into GNU emacs would never
+make a good program).
+
+So, you can either get rid of GNU emacs, or change it to use saner
+values. To do the latter, you can stick the following in your .emacs file:
+
+.. code-block:: none
+
+ (defun c-lineup-arglist-tabs-only (ignored)
+ "Line up argument lists by tabs, not spaces"
+ (let* ((anchor (c-langelem-pos c-syntactic-element))
+ (column (c-langelem-2nd-pos c-syntactic-element))
+ (offset (- (1+ column) anchor))
+ (steps (floor offset c-basic-offset)))
+ (* (max steps 1)
+ c-basic-offset)))
+
+ (add-hook 'c-mode-common-hook
+ (lambda ()
+ ;; Add kernel style
+ (c-add-style
+ "linux-tabs-only"
+ '("linux" (c-offsets-alist
+ (arglist-cont-nonempty
+ c-lineup-gcc-asm-reg
+ c-lineup-arglist-tabs-only))))))
+
+ (add-hook 'c-mode-hook
+ (lambda ()
+ (let ((filename (buffer-file-name)))
+ ;; Enable kernel mode for the appropriate files
+ (when (and filename
+ (string-match (expand-file-name "~/src/linux-trees")
+ filename))
+ (setq indent-tabs-mode t)
+ (setq show-trailing-whitespace t)
+ (c-set-style "linux-tabs-only")))))
+
+This will make emacs go better with the kernel coding style for C
+files below ``~/src/linux-trees``.
+
+But even if you fail in getting emacs to do sane formatting, not
+everything is lost: use ``indent``.
+
+Now, again, GNU indent has the same brain-dead settings that GNU emacs
+has, which is why you need to give it a few command line options.
+However, that's not too bad, because even the makers of GNU indent
+recognize the authority of K&R (the GNU people aren't evil, they are
+just severely misguided in this matter), so you just give indent the
+options ``-kr -i8`` (stands for ``K&R, 8 character indents``), or use
+``scripts/Lindent``, which indents in the latest style.
+
+``indent`` has a lot of options, and especially when it comes to comment
+re-formatting you may want to take a look at the man page. But
+remember: ``indent`` is not a fix for bad programming.
+
+
+10) Kconfig configuration files
+-------------------------------
+
+For all of the Kconfig* configuration files throughout the source tree,
+the indentation is somewhat different. Lines under a ``config`` definition
+are indented with one tab, while help text is indented an additional two
+spaces. Example::
+
+ config AUDIT
+ bool "Auditing support"
+ depends on NET
+ help
+ Enable auditing infrastructure that can be used with another
+ kernel subsystem, such as SELinux (which requires this for
+ logging of avc messages output). Does not do system-call
+ auditing without CONFIG_AUDITSYSCALL.
+
+Seriously dangerous features (such as write support for certain
+filesystems) should advertise this prominently in their prompt string::
+
+ config ADFS_FS_RW
+ bool "ADFS write support (DANGEROUS)"
+ depends on ADFS_FS
+ ...
+
+For full documentation on the configuration files, see the file
+Documentation/kbuild/kconfig-language.txt.
+
+
+11) Data structures
+-------------------
+
+Data structures that have visibility outside the single-threaded
+environment they are created and destroyed in should always have
+reference counts. In the kernel, garbage collection doesn't exist (and
+outside the kernel garbage collection is slow and inefficient), which
+means that you absolutely **have** to reference count all your uses.
+
+Reference counting means that you can avoid locking, and allows multiple
+users to have access to the data structure in parallel - and not having
+to worry about the structure suddenly going away from under them just
+because they slept or did something else for a while.
+
+Note that locking is **not** a replacement for reference counting.
+Locking is used to keep data structures coherent, while reference
+counting is a memory management technique. Usually both are needed, and
+they are not to be confused with each other.
+
+Many data structures can indeed have two levels of reference counting,
+when there are users of different ``classes``. The subclass count counts
+the number of subclass users, and decrements the global count just once
+when the subclass count goes to zero.
+
+Examples of this kind of ``multi-level-reference-counting`` can be found in
+memory management (``struct mm_struct``: mm_users and mm_count), and in
+filesystem code (``struct super_block``: s_count and s_active).
+
+Remember: if another thread can find your data structure, and you don't
+have a reference count on it, you almost certainly have a bug.
+
+
+12) Macros, Enums and RTL
+-------------------------
+
+Names of macros defining constants and labels in enums are capitalized.
+
+.. code-block:: c
+
+ #define CONSTANT 0x12345
+
+Enums are preferred when defining several related constants.
+
+CAPITALIZED macro names are appreciated but macros resembling functions
+may be named in lower case.
+
+Generally, inline functions are preferable to macros resembling functions.
+
+Macros with multiple statements should be enclosed in a do - while block:
+
+.. code-block:: c
+
+ #define macrofun(a, b, c) \
+ do { \
+ if (a == 5) \
+ do_this(b, c); \
+ } while (0)
+
+Things to avoid when using macros:
+
+1) macros that affect control flow:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ do { \
+ if (blah(x) < 0) \
+ return -EBUGGERED; \
+ } while (0)
+
+is a **very** bad idea. It looks like a function call but exits the ``calling``
+function; don't break the internal parsers of those who will read the code.
+
+2) macros that depend on having a local variable with a magic name:
+
+.. code-block:: c
+
+ #define FOO(val) bar(index, val)
+
+might look like a good thing, but it's confusing as hell when one reads the
+code and it's prone to breakage from seemingly innocent changes.
+
+3) macros with arguments that are used as l-values: FOO(x) = y; will
+bite you if somebody e.g. turns FOO into an inline function.
+
+4) forgetting about precedence: macros defining constants using expressions
+must enclose the expression in parentheses. Beware of similar issues with
+macros using parameters.
+
+.. code-block:: c
+
+ #define CONSTANT 0x4000
+ #define CONSTEXP (CONSTANT | 3)
+
+5) namespace collisions when defining local variables in macros resembling
+functions:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ ({ \
+ typeof(x) ret; \
+ ret = calc_ret(x); \
+ (ret); \
+ })
+
+ret is a common name for a local variable - __foo_ret is less likely
+to collide with an existing variable.
+
+The cpp manual deals with macros exhaustively. The gcc internals manual also
+covers RTL which is used frequently with assembly language in the kernel.
+
+
+13) Printing kernel messages
+----------------------------
+
+Kernel developers like to be seen as literate. Do mind the spelling
+of kernel messages to make a good impression. Do not use crippled
+words like ``dont``; use ``do not`` or ``don't`` instead. Make the messages
+concise, clear, and unambiguous.
+
+Kernel messages do not have to be terminated with a period.
+
+Printing numbers in parentheses (%d) adds no value and should be avoided.
+
+There are a number of driver model diagnostic macros in <linux/device.h>
+which you should use to make sure messages are matched to the right device
+and driver, and are tagged with the right level: dev_err(), dev_warn(),
+dev_info(), and so forth. For messages that aren't associated with a
+particular device, <linux/printk.h> defines pr_notice(), pr_info(),
+pr_warn(), pr_err(), etc.
+
+Coming up with good debugging messages can be quite a challenge; and once
+you have them, they can be a huge help for remote troubleshooting. However
+debug message printing is handled differently than printing other non-debug
+messages. While the other pr_XXX() functions print unconditionally,
+pr_debug() does not; it is compiled out by default, unless either DEBUG is
+defined or CONFIG_DYNAMIC_DEBUG is set. That is true for dev_dbg() also,
+and a related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to
+the ones already enabled by DEBUG.
+
+Many subsystems have Kconfig debug options to turn on -DDEBUG in the
+corresponding Makefile; in other cases specific files #define DEBUG. And
+when a debug message should be unconditionally printed, such as if it is
+already inside a debug-related #ifdef section, printk(KERN_DEBUG ...) can be
+used.
+
+
+14) Allocating memory
+---------------------
+
+The kernel provides the following general purpose memory allocators:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and
+vzalloc(). Please refer to the API documentation for further information
+about them.
+
+The preferred form for passing a size of a struct is the following:
+
+.. code-block:: c
+
+ p = kmalloc(sizeof(*p), ...);
+
+The alternative form where struct name is spelled out hurts readability and
+introduces an opportunity for a bug when the pointer variable type is changed
+but the corresponding sizeof that is passed to a memory allocator is not.
+
+Casting the return value which is a void pointer is redundant. The conversion
+from void pointer to any other pointer type is guaranteed by the C programming
+language.
+
+The preferred form for allocating an array is the following:
+
+.. code-block:: c
+
+ p = kmalloc_array(n, sizeof(...), ...);
+
+The preferred form for allocating a zeroed array is the following:
+
+.. code-block:: c
+
+ p = kcalloc(n, sizeof(...), ...);
+
+Both forms check for overflow on the allocation size n * sizeof(...),
+and return NULL if that occurred.
+
+
+15) The inline disease
+----------------------
+
+There appears to be a common misperception that gcc has a magic "make me
+faster" speedup option called ``inline``. While the use of inlines can be
+appropriate (for example as a means of replacing macros, see Chapter 12), it
+very often is not. Abundant use of the inline keyword leads to a much bigger
+kernel, which in turn slows the system as a whole down, due to a bigger
+icache footprint for the CPU and simply because there is less memory
+available for the pagecache. Just think about it; a pagecache miss causes a
+disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
+that can go into these 5 milliseconds.
+
+A reasonable rule of thumb is to not put inline at functions that have more
+than 3 lines of code in them. An exception to this rule are the cases where
+a parameter is known to be a compiletime constant, and as a result of this
+constantness you *know* the compiler will be able to optimize most of your
+function away at compile time. For a good example of this later case, see
+the kmalloc() inline function.
+
+Often people argue that adding inline to functions that are static and used
+only once is always a win since there is no space tradeoff. While this is
+technically correct, gcc is capable of inlining these automatically without
+help, and the maintenance issue of removing the inline when a second user
+appears outweighs the potential value of the hint that tells gcc to do
+something it would have done anyway.
+
+
+16) Function return values and names
+------------------------------------
+
+Functions can return values of many different kinds, and one of the
+most common is a value indicating whether the function succeeded or
+failed. Such a value can be represented as an error-code integer
+(-Exxx = failure, 0 = success) or a ``succeeded`` boolean (0 = failure,
+non-zero = success).
+
+Mixing up these two sorts of representations is a fertile source of
+difficult-to-find bugs. If the C language included a strong distinction
+between integers and booleans then the compiler would find these mistakes
+for us... but it doesn't. To help prevent such bugs, always follow this
+convention::
+
+ If the name of a function is an action or an imperative command,
+ the function should return an error-code integer. If the name
+ is a predicate, the function should return a "succeeded" boolean.
+
+For example, ``add work`` is a command, and the add_work() function returns 0
+for success or -EBUSY for failure. In the same way, ``PCI device present`` is
+a predicate, and the pci_dev_present() function returns 1 if it succeeds in
+finding a matching device or 0 if it doesn't.
+
+All EXPORTed functions must respect this convention, and so should all
+public functions. Private (static) functions need not, but it is
+recommended that they do.
+
+Functions whose return value is the actual result of a computation, rather
+than an indication of whether the computation succeeded, are not subject to
+this rule. Generally they indicate failure by returning some out-of-range
+result. Typical examples would be functions that return pointers; they use
+NULL or the ERR_PTR mechanism to report failure.
+
+
+17) Don't re-invent the kernel macros
+-------------------------------------
+
+The header file include/linux/kernel.h contains a number of macros that
+you should use, rather than explicitly coding some variant of them yourself.
+For example, if you need to calculate the length of an array, take advantage
+of the macro
+
+.. code-block:: c
+
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+Similarly, if you need to calculate the size of some structure member, use
+
+.. code-block:: c
+
+ #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+There are also min() and max() macros that do strict type checking if you
+need them. Feel free to peruse that header file to see what else is already
+defined that you shouldn't reproduce in your code.
+
+
+18) Editor modelines and other cruft
+------------------------------------
+
+Some editors can interpret configuration information embedded in source files,
+indicated with special markers. For example, emacs interprets lines marked
+like this:
+
+.. code-block:: c
+
+ -*- mode: c -*-
+
+Or like this:
+
+.. code-block:: c
+
+ /*
+ Local Variables:
+ compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+ End:
+ */
+
+Vim interprets markers that look like this:
+
+.. code-block:: c
+
+ /* vim:set sw=8 noet */
+
+Do not include any of these in source files. People have their own personal
+editor configurations, and your source files should not override them. This
+includes markers for indentation and mode configuration. People may use their
+own custom mode, or may have some other magic method for making indentation
+work correctly.
+
+
+19) Inline assembly
+-------------------
+
+In architecture-specific code, you may need to use inline assembly to interface
+with CPU or platform functionality. Don't hesitate to do so when necessary.
+However, don't use inline assembly gratuitously when C can do the job. You can
+and should poke hardware from C when possible.
+
+Consider writing simple helper functions that wrap common bits of inline
+assembly, rather than repeatedly writing them with slight variations. Remember
+that inline assembly can use C parameters.
+
+Large, non-trivial assembly functions should go in .S files, with corresponding
+C prototypes defined in C header files. The C prototypes for assembly
+functions should use ``asmlinkage``.
+
+You may need to mark your asm statement as volatile, to prevent GCC from
+removing it if GCC doesn't notice any side effects. You don't always need to
+do so, though, and doing so unnecessarily can limit optimization.
+
+When writing a single inline assembly statement containing multiple
+instructions, put each instruction on a separate line in a separate quoted
+string, and end each string except the last with \n\t to properly indent the
+next instruction in the assembly output:
+
+.. code-block:: c
+
+ asm ("magic %reg1, #42\n\t"
+ "more_magic %reg2, %reg3"
+ : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) Conditional Compilation
+---------------------------
+
+Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
+files; doing so makes code harder to read and logic harder to follow. Instead,
+use such conditionals in a header file defining functions for use in those .c
+files, providing no-op stub versions in the #else case, and then call those
+functions unconditionally from .c files. The compiler will avoid generating
+any code for the stub calls, producing identical results, but the logic will
+remain easy to follow.
+
+Prefer to compile out entire functions, rather than portions of functions or
+portions of expressions. Rather than putting an ifdef in an expression, factor
+out part or all of the expression into a separate helper function and apply the
+conditional to that function.
+
+If you have a function or variable which may potentially go unused in a
+particular configuration, and the compiler would warn about its definition
+going unused, mark the definition as __maybe_unused rather than wrapping it in
+a preprocessor conditional. (However, if a function or variable *always* goes
+unused, delete it.)
+
+Within code, where possible, use the IS_ENABLED macro to convert a Kconfig
+symbol into a C boolean expression, and use it in a normal C conditional:
+
+.. code-block:: c
+
+ if (IS_ENABLED(CONFIG_SOMETHING)) {
+ ...
+ }
+
+The compiler will constant-fold the conditional away, and include or exclude
+the block of code just as with an #ifdef, so this will not add any runtime
+overhead. However, this approach still allows the C compiler to see the code
+inside the block, and check it for correctness (syntax, types, symbol
+references, etc). Thus, you still have to use an #ifdef if the code inside the
+block references symbols that will not exist if the condition is not met.
+
+At the end of any non-trivial #if or #ifdef block (more than a few lines),
+place a comment after the #endif on the same line, noting the conditional
+expression used. For instance:
+
+.. code-block:: c
+
+ #ifdef CONFIG_SOMETHING
+ ...
+ #endif /* CONFIG_SOMETHING */
+
+
+Appendix I) References
+----------------------
+
+The C Programming Language, Second Edition
+by Brian W. Kernighan and Dennis M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
+
+The Practice of Programming
+by Brian W. Kernighan and Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
+gcc internals and indent, all available from http://www.gnu.org/manual/
+
+WG14 is the international standardization working group for the programming
+language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff --git a/Documentation/development-process/conf.py b/Documentation/process/conf.py
index 4b4a12dace02..1b01a80ad9ce 100644
--- a/Documentation/development-process/conf.py
+++ b/Documentation/process/conf.py
@@ -5,6 +5,6 @@ project = 'Linux Kernel Development Documentation'
tags.add("subproject")
latex_documents = [
- ('index', 'development-process.tex', 'Linux Kernel Development Documentation',
+ ('index', 'process.tex', 'Linux Kernel Development Documentation',
'The kernel development community', 'manual'),
]
diff --git a/Documentation/development-process/development-process.rst b/Documentation/process/development-process.rst
index bd1399f7202a..61c627e41ba8 100644
--- a/Documentation/development-process/development-process.rst
+++ b/Documentation/process/development-process.rst
@@ -26,4 +26,3 @@ development (or, indeed, free software development in general). While
there is some technical material here, this is very much a process-oriented
discussion which does not require a deep knowledge of kernel programming to
understand.
-
diff --git a/Documentation/email-clients.txt b/Documentation/process/email-clients.rst
index ac892b30815e..ac892b30815e 100644
--- a/Documentation/email-clients.txt
+++ b/Documentation/process/email-clients.rst
diff --git a/Documentation/HOWTO b/Documentation/process/howto.rst
index 5f042349f987..1260f60d4cb9 100644
--- a/Documentation/HOWTO
+++ b/Documentation/process/howto.rst
@@ -90,19 +90,19 @@ required reading:
what is necessary to do to configure and build the kernel. People
who are new to the kernel should start here.
- :ref:`Documentation/Changes <changes>`
+ :ref:`Documentation/process/changes.rst <changes>`
This file gives a list of the minimum levels of various software
packages that are necessary to build and run the kernel
successfully.
- :ref:`Documentation/CodingStyle <codingstyle>`
+ :ref:`Documentation/process/coding-style.rst <codingstyle>`
This describes the Linux kernel coding style, and some of the
rationale behind it. All new code is expected to follow the
guidelines in this document. Most maintainers will only accept
patches if these rules are followed, and many people will only
review code if it is in the proper style.
- :ref:`Documentation/SubmittingPatches <submittingpatches>` and :ref:`Documentation/SubmittingDrivers <submittingdrivers>`
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` and :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
These files describe in explicit detail how to successfully create
and send a patch, including (but not limited to):
@@ -122,7 +122,7 @@ required reading:
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
- :ref:`Documentation/stable_api_nonsense.txt <stable_api_nonsense>`
+ :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
This file describes the rationale behind the conscious decision to
not have a stable API within the kernel, including things like:
@@ -135,29 +135,29 @@ required reading:
philosophy and is very important for people moving to Linux from
development on other Operating Systems.
- :ref:`Documentation/SecurityBugs <securitybugs>`
+ :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
If you feel you have found a security problem in the Linux kernel,
please follow the steps in this document to help notify the kernel
developers, and help solve the issue.
- :ref:`Documentation/ManagementStyle <managementstyle>`
+ :ref:`Documentation/process/management-style.rst <managementstyle>`
This document describes how Linux kernel maintainers operate and the
shared ethos behind their methodologies. This is important reading
for anyone new to kernel development (or anyone simply curious about
it), as it resolves a lot of common misconceptions and confusion
about the unique behavior of kernel maintainers.
- :ref:`Documentation/stable_kernel_rules.txt <stable_kernel_rules>`
+ :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
This file describes the rules on how the stable kernel releases
happen, and what to do if you want to get a change into one of these
releases.
- :ref:`Documentation/kernel-docs.txt <kernel_docs>`
+ :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
A list of external documentation that pertains to kernel
development. Please consult this list if you do not find what you
are looking for within the in-kernel documentation.
- :ref:`Documentation/applying-patches.txt <applying_patches>`
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>`
A good introduction describing exactly what a patch is and how to
apply it to the different development branches of the kernel.
@@ -254,7 +254,8 @@ branches. These different branches are:
- the 4.x -next kernel tree for integration tests
4.x kernel tree
------------------
+~~~~~~~~~~~~~~~
+
4.x kernels are maintained by Linus Torvalds, and can be found on
https://kernel.org in the pub/linux/kernel/v4.x/ directory. Its development
process is as follows:
@@ -266,15 +267,16 @@ process is as follows:
is using git (the kernel's source management tool, more information
can be found at https://git-scm.com/) but plain patches are also just
fine.
- - After two weeks a -rc1 kernel is released it is now possible to push
- only patches that do not include new features that could affect the
- stability of the whole kernel. Please note that a whole new driver
- (or filesystem) might be accepted after -rc1 because there is no
- risk of causing regressions with such a change as long as the change
- is self-contained and does not affect areas outside of the code that
- is being added. git can be used to send patches to Linus after -rc1
- is released, but the patches need to also be sent to a public
- mailing list for review.
+ - After two weeks a -rc1 kernel is released and the focus is on making the
+ new kernel as rock solid as possible. Most of the patches at this point
+ should fix a regression. Bugs that have always existed are not
+ regressions, so only push these kinds of fixes if they are important.
+ Please note that a whole new driver (or filesystem) might be accepted
+ after -rc1 because there is no risk of causing regressions with such a
+ change as long as the change is self-contained and does not affect areas
+ outside of the code that is being added. git can be used to send
+ patches to Linus after -rc1 is released, but the patches need to also be
+ sent to a public mailing list for review.
- A new -rc is released whenever Linus deems the current git tree to
be in a reasonably sane state adequate for testing. The goal is to
release a new -rc kernel every week.
@@ -289,7 +291,8 @@ mailing list about kernel releases:
preconceived timeline."*
4.x.y -stable kernel tree
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
Kernels with 3-part versions are -stable kernels. They contain
relatively small and critical fixes for security problems or significant
regressions discovered in a given 4.x kernel.
@@ -307,12 +310,13 @@ two weeks, but it can be longer if there are no pressing problems. A
security-related problem, instead, can cause a release to happen almost
instantly.
-The file Documentation/stable_kernel_rules.txt in the kernel tree
+The file Documentation/process/stable-kernel-rules.rst in the kernel tree
documents what kinds of changes are acceptable for the -stable tree, and
how the release process works.
4.x -git patches
-----------------
+~~~~~~~~~~~~~~~~
+
These are daily snapshots of Linus' kernel tree which are managed in a
git repository (hence the name.) These patches are usually released
daily and represent the current state of Linus' tree. They are more
@@ -320,7 +324,8 @@ experimental than -rc kernels since they are generated automatically
without even a cursory glance to see if they are sane.
Subsystem Specific kernel trees and patches
--------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
The maintainers of the various kernel subsystems --- and also many
kernel subsystem developers --- expose their current state of
development in source repositories. That way, others can see what is
@@ -344,7 +349,8 @@ accepted, or rejected. Most of these patchwork sites are listed at
https://patchwork.kernel.org/.
4.x -next kernel tree for integration tests
--------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
Before updates from subsystem trees are merged into the mainline 4.x
tree, they need to be integration-tested. For this purpose, a special
testing repository exists into which virtually all subsystem trees are
@@ -366,7 +372,7 @@ tool. For details on how to use the kernel bugzilla, please see:
https://bugzilla.kernel.org/page.cgi?id=faq.html
-The file REPORTING-BUGS in the main kernel source directory has a good
+The file admin-guide/reporting-bugs.rst in the main kernel source directory has a good
template for how to report a possible kernel bug, and details what kind
of information is needed by the kernel developers to help track down the
problem.
@@ -440,7 +446,7 @@ add your statements between the individual quoted sections instead of
writing at the top of the mail.
If you add patches to your mail, make sure they are plain readable text
-as stated in Documentation/SubmittingPatches.
+as stated in Documentation/process/submitting-patches.rst.
Kernel developers don't want to deal with
attachments or compressed patches; they may want to comment on
individual lines of your patch, which works only that way. Make sure you
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
new file mode 100644
index 000000000000..10aa6920709a
--- /dev/null
+++ b/Documentation/process/index.rst
@@ -0,0 +1,57 @@
+.. raw:: latex
+
+ \renewcommand\thesection*
+ \renewcommand\thesubsection*
+
+
+Working with the kernel development community
+=============================================
+
+So you want to be a Linux kernel developer? Welcome! While there is a lot
+to be learned about the kernel in a technical sense, it is also important
+to learn about how our community works. Reading these documents will make
+it much easier for you to get your changes merged with a minimum of
+trouble.
+
+Below are the essential guides that every developer should read.
+
+.. toctree::
+ :maxdepth: 1
+
+ howto
+ code-of-conflict
+ development-process
+ submitting-patches
+ coding-style
+ email-clients
+
+Other guides to the community that are of interest to most developers are:
+
+.. toctree::
+ :maxdepth: 1
+
+ changes
+ submitting-drivers
+ stable-api-nonsense
+ management-style
+ stable-kernel-rules
+ submit-checklist
+ kernel-docs
+
+These are some overall technical guides that have been put here for now for
+lack of a better place.
+
+.. toctree::
+ :maxdepth: 1
+
+ applying-patches
+ adding-syscalls
+ magic-number
+ volatile-considered-harmful
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/kernel-docs.txt b/Documentation/process/kernel-docs.rst
index 05a7857a4a83..05a7857a4a83 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/process/kernel-docs.rst
diff --git a/Documentation/process/magic-number.rst b/Documentation/process/magic-number.rst
new file mode 100644
index 000000000000..c74199f60c6c
--- /dev/null
+++ b/Documentation/process/magic-number.rst
@@ -0,0 +1,164 @@
+Linux magic numbers
+===================
+
+This file is a registry of magic numbers which are in use. When you
+add a magic number to a structure, you should also add it to this
+file, since it is best if the magic numbers used by various structures
+are unique.
+
+It is a **very** good idea to protect kernel data structures with magic
+numbers. This allows you to check at run time whether (a) a structure
+has been clobbered, or (b) you've passed the wrong structure to a
+routine. This last is especially useful --- particularly when you are
+passing pointers to structures via a void * pointer. The tty code,
+for example, does this frequently to pass driver-specific and line
+discipline-specific structures back and forth.
+
+The way to use magic numbers is to declare then at the beginning of
+the structure, like so::
+
+ struct tty_ldisc {
+ int magic;
+ ...
+ };
+
+Please follow this discipline when you are adding future enhancements
+to the kernel! It has saved me countless hours of debugging,
+especially in the screwy cases where an array has been overrun and
+structures following the array have been overwritten. Using this
+discipline, these cases get detected quickly and safely.
+
+Changelog::
+
+ Theodore Ts'o
+ 31 Mar 94
+
+ The magic table is current to Linux 2.1.55.
+
+ Michael Chastain
+ <mailto:mec@shout.net>
+ 22 Sep 1997
+
+ Now it should be up to date with Linux 2.1.112. Because
+ we are in feature freeze time it is very unlikely that
+ something will change before 2.2.x. The entries are
+ sorted by number field.
+
+ Krzysztof G. Baranowski
+ <mailto: kgb@knm.org.pl>
+ 29 Jul 1998
+
+ Updated the magic table to Linux 2.5.45. Right over the feature freeze,
+ but it is possible that some new magic numbers will sneak into the
+ kernel before 2.6.x yet.
+
+ Petr Baudis
+ <pasky@ucw.cz>
+ 03 Nov 2002
+
+ Updated the magic table to Linux 2.5.74.
+
+ Fabian Frederick
+ <ffrederick@users.sourceforge.net>
+ 09 Jul 2003
+
+
+===================== ================ ======================== ==========================================
+Magic Name Number Structure File
+===================== ================ ======================== ==========================================
+PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/pg.h``
+CMAGIC 0x0111 user ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
+HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
+CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
+DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
+DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
+FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
+ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
+PTY_MAGIC 0x5001 ``drivers/char/pty.c``
+PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
+SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h``
+SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
+SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
+STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
+X25_ASY_MAGIC 0x5303 x25_asy ``drivers/net/x25_asy.h``
+SIXPACK_MAGIC 0x5304 sixpack ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC 0x5316 ax_disp ``drivers/net/mkiss.h``
+TTY_MAGIC 0x5401 tty_struct ``include/linux/tty.h``
+MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
+MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
+TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
+USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
+RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
+LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h``
+RED_MAGIC2 0x170fc2a5 (any) ``mm/slab.c``
+BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC 0x21504345 cdkecpsig ``include/linux/cdk.h``
+LSOMAGIC 0x27091997 lso ``drivers/fc4/fc.c``
+LSMAGIC 0x2a3b4d2a ls ``drivers/fc4/fc.c``
+WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} ``include/linux/wanpipe.h``
+CS_CARD_MAGIC 0x43525553 cs_card ``sound/oss/cs46xx.c``
+LABELCL_MAGIC 0x4857434c labelcl_info_s ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC 0x49344C01 modem_info ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg ``arch/*/amiga/config.c``
+CS_STATE_MAGIC 0x4c4f4749 cs_state ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC 0x4f17a36d kmem_cache ``mm/slab.c``
+COW_MAGIC 0x4f4f4f4d cow_header_v1 ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC 0x5072696E i810_card ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC 0x5072696E trident_card ``sound/oss/trident.c``
+ROUTER_MAGIC 0x524d4157 wan_device [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1 0x53415645 savekmsg ``arch/*/amiga/config.c``
+GDA_MAGIC 0x58464552 gda ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1 0x5a2cf071 (any) ``mm/slab.c``
+EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h``
+PCXX_MAGIC 0x5c6df104 channel ``drivers/char/pcxx.h``
+KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC 0x63657373 i810_state ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC 0x63657373 trient_state ``sound/oss/trident.c``
+M3_CARD_MAGIC 0x646e6f50 m3_card ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC 0x65726F66 fw_header ``drivers/atm/fore200e.h``
+SLOT_MAGIC 0x67267321 slot ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC 0x67267322 slot ``drivers/hotplug/acpiphp.h``
+LO_MAGIC 0x68797548 nbd_device ``include/linux/nbd.h``
+OPROFILE_MAGIC 0x6f70726f super_block ``drivers/oprofile/oprofilefs.h``
+M3_STATE_MAGIC 0x734d724d m3_state ``sound/oss/maestro3.c``
+VMALLOC_MAGIC 0x87654320 snd_alloc_track ``sound/core/memory.c``
+KMALLOC_MAGIC 0x87654321 snd_alloc_track ``sound/core/memory.c``
+PWC_MAGIC 0x89DC10AB pwc_device ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC 0x96744668 nbd_reply ``include/linux/nbd.h``
+ENI155_MAGIC 0xa54b872d midway_eprom ``drivers/atm/eni.h``
+CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram ``drivers/scsi/gdth.h``
+YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c``
+CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC 0xFEFAFEF1 htb_class ``net/sched/sch_htb.c``
+NMI_MAGIC 0x48414d4d455201 nmi_s ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+Note that there are also defined special per-driver magic numbers in sound
+memory management. See ``include/sound/sndmagic.h`` for complete list of them. Many
+OSS sound drivers have their magic numbers constructed from the soundcard PCI
+ID - these are not listed here as well.
+
+IrDA subsystem also uses large number of own magic numbers, see
+``include/net/irda/irda.h`` for a complete list of them.
+
+HFS is another larger user of magic numbers - you can find them in
+``fs/hfs/hfs.h``.
diff --git a/Documentation/ManagementStyle b/Documentation/process/management-style.rst
index dea2e66c9a10..45595fd8a66b 100644
--- a/Documentation/ManagementStyle
+++ b/Documentation/process/management-style.rst
@@ -5,7 +5,7 @@ Linux kernel management style
This is a short document describing the preferred (or made up, depending
on who you ask) management style for the linux kernel. It's meant to
-mirror the CodingStyle document to some degree, and mainly written to
+mirror the process/coding-style.rst document to some degree, and mainly written to
avoid answering [#f1]_ the same (or similar) questions over and over again.
Management style is very personal and much harder to quantify than
diff --git a/Documentation/stable_api_nonsense.txt b/Documentation/process/stable-api-nonsense.rst
index 24f5aeecee91..24f5aeecee91 100644
--- a/Documentation/stable_api_nonsense.txt
+++ b/Documentation/process/stable-api-nonsense.rst
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/process/stable-kernel-rules.rst
index 4d82e31b7958..11ec2d93a5e0 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/process/stable-kernel-rules.rst
@@ -27,7 +27,7 @@ Rules on what kind of patches are accepted, and which ones are not, into the
- It cannot contain any "trivial" fixes in it (spelling changes,
whitespace cleanups, etc).
- It must follow the
- :ref:`Documentation/SubmittingPatches <submittingpatches>`
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
rules.
- It or an equivalent fix must already exist in Linus' tree (upstream).
@@ -40,7 +40,7 @@ Procedure for submitting patches to the -stable tree
Documentation/networking/netdev-FAQ.txt
- Security patches should not be handled (solely) by the -stable review
process but should follow the procedures in
- :ref:`Documentation/SecurityBugs <securitybugs>`.
+ :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.
For all other submissions, choose one of the following procedures
-----------------------------------------------------------------
diff --git a/Documentation/SubmitChecklist b/Documentation/process/submit-checklist.rst
index 894289b22b15..a0d9d34bfb6d 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/process/submit-checklist.rst
@@ -7,7 +7,7 @@ Here are some basic things that developers should do if they want to see their
kernel patch submissions accepted more quickly.
These are all above and beyond the documentation that is provided in
-:ref:`Documentation/SubmittingPatches <submittingpatches>`
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
and elsewhere regarding submitting Linux kernel patches.
@@ -31,7 +31,7 @@ and elsewhere regarding submitting Linux kernel patches.
tends to use ``unsigned long`` for 64-bit quantities.
5) Check your patch for general style as detailed in
- :ref:`Documentation/CodingStyle <codingstyle>`.
+ :ref:`Documentation/process/coding-style.rst <codingstyle>`.
Check for trivial violations with the patch style checker prior to
submission (``scripts/checkpatch.pl``).
You should be able to justify all violations that remain in
@@ -78,7 +78,7 @@ and elsewhere regarding submitting Linux kernel patches.
16) All new ``/proc`` entries are documented under ``Documentation/``
17) All new kernel boot parameters are documented in
- ``Documentation/kernel-parameters.txt``.
+ ``Documentation/admin-guide/kernel-parameters.rst``.
18) All new module parameters are documented with ``MODULE_PARM_DESC()``
diff --git a/Documentation/SubmittingDrivers b/Documentation/process/submitting-drivers.rst
index 252b77a23fad..afb82ee0cbea 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/process/submitting-drivers.rst
@@ -8,7 +8,15 @@ various kernel trees. Note that if you are interested in video card drivers
you should probably talk to XFree86 (http://www.xfree86.org/) and/or X.Org
(http://x.org/) instead.
-Also read the Documentation/SubmittingPatches document.
+.. note::
+
+ This document is old and has seen little maintenance in recent years; it
+ should probably be updated or, perhaps better, just deleted. Most of
+ what is here can be found in the other development documents anyway.
+
+ Oh, and we don't really recommend submitting changes to XFree86 :)
+
+Also read the Documentation/process/submitting-patches.rst document.
Allocating Device Numbers
@@ -19,7 +27,7 @@ by the Linux assigned name and number authority (currently this is
Torben Mathiasen). The site is http://www.lanana.org/. This
also deals with allocating numbers for devices that are not going to
be submitted to the mainstream kernel.
-See Documentation/devices.txt for more information on this.
+See Documentation/admin-guide/devices.rst for more information on this.
If you don't use assigned numbers then when your device is submitted it will
be given an assigned number even if that is different from values you may
@@ -73,7 +81,7 @@ Interfaces:
Code:
Please use the Linux style of code formatting as documented
- in :ref:`Documentation/CodingStyle <codingStyle>`.
+ in :ref:`Documentation/process/coding-style.rst <codingStyle>`.
If you have sections of code
that need to be in other formats, for example because they
are shared with a windows driver kit and you want to
@@ -109,7 +117,7 @@ PM support:
anything. For the driver testing instructions see
Documentation/power/drivers-testing.txt and for a relatively
complete overview of the power management issues related to
- drivers see Documentation/power/devices.txt .
+ drivers see Documentation/power/admin-guide/devices.rst .
Control:
In general if there is active maintenance of a driver by
diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst
new file mode 100644
index 000000000000..3e10719fee35
--- /dev/null
+++ b/Documentation/process/submitting-patches.rst
@@ -0,0 +1,836 @@
+.. _submittingpatches:
+
+Submitting patches: the essential guide to getting your code into the kernel
+============================================================================
+
+For a person or company who wishes to submit a change to the Linux
+kernel, the process can sometimes be daunting if you're not familiar
+with "the system." This text is a collection of suggestions which
+can greatly increase the chances of your change being accepted.
+
+This document contains a large number of suggestions in a relatively terse
+format. For detailed information on how the kernel development process
+works, see :ref:`Documentation/process <development_process_main>`.
+Also, read :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+for a list of items to check before
+submitting code. If you are submitting a driver, also read
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`;
+for device tree binding patches, read
+Documentation/devicetree/bindings/submitting-patches.txt.
+
+Many of these steps describe the default behavior of the ``git`` version
+control system; if you use ``git`` to prepare your patches, you'll find much
+of the mechanical work done for you, though you'll still need to prepare
+and document a sensible set of patches. In general, use of ``git`` will make
+your life as a kernel developer easier.
+
+0) Obtain a current source tree
+-------------------------------
+
+If you do not have a repository with the current kernel source handy, use
+``git`` to obtain one. You'll want to start with the mainline repository,
+which can be grabbed with::
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+Note, however, that you may not want to develop against the mainline tree
+directly. Most subsystem maintainers run their own trees and want to see
+patches prepared against those trees. See the **T:** entry for the subsystem
+in the MAINTAINERS file to find that tree, or simply ask the maintainer if
+the tree is not listed there.
+
+It is still possible to download kernel releases via tarballs (as described
+in the next section), but that is the hard way to do kernel development.
+
+1) ``diff -up``
+---------------
+
+If you must generate your patches by hand, use ``diff -up`` or ``diff -uprN``
+to create patches. Git generates patches in this form by default; if
+you're using ``git``, you can skip this section entirely.
+
+All changes to the Linux kernel occur in the form of patches, as
+generated by :manpage:`diff(1)`. When creating your patch, make sure to
+create it in "unified diff" format, as supplied by the ``-u`` argument
+to :manpage:`diff(1)`.
+Also, please use the ``-p`` argument which shows which C function each
+change is in - that makes the resultant ``diff`` a lot easier to read.
+Patches should be based in the root kernel source directory,
+not in any lower subdirectory.
+
+To create a patch for a single file, it is often sufficient to do::
+
+ SRCTREE= linux
+ MYFILE= drivers/net/mydriver.c
+
+ cd $SRCTREE
+ cp $MYFILE $MYFILE.orig
+ vi $MYFILE # make your change
+ cd ..
+ diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+To create a patch for multiple files, you should unpack a "vanilla",
+or unmodified kernel source tree, and generate a ``diff`` against your
+own source tree. For example::
+
+ MYSRC= /devel/linux
+
+ tar xvfz linux-3.19.tar.gz
+ mv linux-3.19 linux-3.19-vanilla
+ diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+ linux-3.19-vanilla $MYSRC > /tmp/patch
+
+``dontdiff`` is a list of files which are generated by the kernel during
+the build process, and should be ignored in any :manpage:`diff(1)`-generated
+patch.
+
+Make sure your patch does not include any extra files which do not
+belong in a patch submission. Make sure to review your patch -after-
+generating it with :manpage:`diff(1)`, to ensure accuracy.
+
+If your changes produce a lot of deltas, you need to split them into
+individual patches which modify things in logical stages; see
+:ref:`split_changes`. This will facilitate review by other kernel developers,
+very important if you want your patch accepted.
+
+If you're using ``git``, ``git rebase -i`` can help you with this process. If
+you're not using ``git``, ``quilt`` <http://savannah.nongnu.org/projects/quilt>
+is another popular alternative.
+
+.. _describe_changes:
+
+2) Describe your changes
+------------------------
+
+Describe your problem. Whether your patch is a one-line bug fix or
+5000 lines of a new feature, there must be an underlying problem that
+motivated you to do this work. Convince the reviewer that there is a
+problem worth fixing and that it makes sense for them to read past the
+first paragraph.
+
+Describe user-visible impact. Straight up crashes and lockups are
+pretty convincing, but not all bugs are that blatant. Even if the
+problem was spotted during code review, describe the impact you think
+it can have on users. Keep in mind that the majority of Linux
+installations run kernels from secondary stable trees or
+vendor/product-specific trees that cherry-pick only specific patches
+from upstream, so include anything that could help route your change
+downstream: provoking circumstances, excerpts from dmesg, crash
+descriptions, performance regressions, latency spikes, lockups, etc.
+
+Quantify optimizations and trade-offs. If you claim improvements in
+performance, memory consumption, stack footprint, or binary size,
+include numbers that back them up. But also describe non-obvious
+costs. Optimizations usually aren't free but trade-offs between CPU,
+memory, and readability; or, when it comes to heuristics, between
+different workloads. Describe the expected downsides of your
+optimization so that the reviewer can weigh costs against benefits.
+
+Once the problem is established, describe what you are actually doing
+about it in technical detail. It's important to describe the change
+in plain English for the reviewer to verify that the code is behaving
+as you intend it to.
+
+The maintainer will thank you if you write your patch description in a
+form which can be easily pulled into Linux's source code management
+system, ``git``, as a "commit log". See :ref:`explicit_in_reply_to`.
+
+Solve only one problem per patch. If your description starts to get
+long, that's a sign that you probably need to split up your patch.
+See :ref:`split_changes`.
+
+When you submit or resubmit a patch or patch series, include the
+complete patch description and justification for it. Don't just
+say that this is version N of the patch (series). Don't expect the
+subsystem maintainer to refer back to earlier patch versions or referenced
+URLs to find the patch description and put that into the patch.
+I.e., the patch (series) and its description should be self-contained.
+This benefits both the maintainers and reviewers. Some reviewers
+probably didn't even receive earlier versions of the patch.
+
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
+instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
+to do frotz", as if you are giving orders to the codebase to change
+its behaviour.
+
+If the patch fixes a logged bug entry, refer to that bug entry by
+number and URL. If the patch follows from a mailing list discussion,
+give a URL to the mailing list archive; use the https://lkml.kernel.org/
+redirector with a ``Message-Id``, to ensure that the links cannot become
+stale.
+
+However, try to make your explanation understandable without external
+resources. In addition to giving a URL to a mailing list archive or
+bug, summarize the relevant points of the discussion that led to the
+patch as submitted.
+
+If you want to refer to a specific commit, don't just refer to the
+SHA-1 ID of the commit. Please also include the oneline summary of
+the commit, to make it easier for reviewers to know what it is about.
+Example::
+
+ Commit e21d2170f36602ae2708 ("video: remove unnecessary
+ platform_set_drvdata()") removed the unnecessary
+ platform_set_drvdata(), but left the variable "dev" unused,
+ delete it.
+
+You should also be sure to use at least the first twelve characters of the
+SHA-1 ID. The kernel repository holds a *lot* of objects, making
+collisions with shorter IDs a real possibility. Bear in mind that, even if
+there is no collision with your six-character ID now, that condition may
+change five years from now.
+
+If your patch fixes a bug in a specific commit, e.g. you found an issue using
+``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
+the SHA-1 ID, and the one line summary. For example::
+
+ Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
+
+The following ``git config`` settings can be used to add a pretty format for
+outputting the above style in the ``git log`` or ``git show`` commands::
+
+ [core]
+ abbrev = 12
+ [pretty]
+ fixes = Fixes: %h (\"%s\")
+
+.. _split_changes:
+
+3) Separate your changes
+------------------------
+
+Separate each **logical change** into a separate patch.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single driver, separate those changes into two
+or more patches. If your changes include an API update, and a new
+driver which uses that new API, separate those into two patches.
+
+On the other hand, if you make a single change to numerous files,
+group those changes into a single patch. Thus a single logical change
+is contained within a single patch.
+
+The point to remember is that each patch should make an easily understood
+change that can be verified by reviewers. Each patch should be justifiable
+on its own merits.
+
+If one patch depends on another patch in order for a change to be
+complete, that is OK. Simply note **"this patch depends on patch X"**
+in your patch description.
+
+When dividing your change into a series of patches, take special care to
+ensure that the kernel builds and runs properly after each patch in the
+series. Developers using ``git bisect`` to track down a problem can end up
+splitting your patch series at any point; they will not thank you if you
+introduce bugs in the middle.
+
+If you cannot condense your patch set into a smaller set of patches,
+then only post say 15 or so at a time and wait for review and integration.
+
+
+
+4) Style-check your changes
+---------------------------
+
+Check your patch for basic style violations, details of which can be
+found in
+:ref:`Documentation/process/coding-style.rst <codingstyle>`.
+Failure to do so simply wastes
+the reviewers time and will get your patch rejected, probably
+without even being read.
+
+One significant exception is when moving code from one file to
+another -- in this case you should not modify the moved code at all in
+the same patch which moves it. This clearly delineates the act of
+moving the code and your changes. This greatly aids review of the
+actual differences and allows tools to better track the history of
+the code itself.
+
+Check your patches with the patch style checker prior to submission
+(scripts/checkpatch.pl). Note, though, that the style checker should be
+viewed as a guide, not as a replacement for human judgment. If your code
+looks better with a violation then its probably best left alone.
+
+The checker reports at three levels:
+ - ERROR: things that are very likely to be wrong
+ - WARNING: things requiring careful review
+ - CHECK: things requiring thought
+
+You should be able to justify all violations that remain in your
+patch.
+
+
+5) Select the recipients for your patch
+---------------------------------------
+
+You should always copy the appropriate subsystem maintainer(s) on any patch
+to code that they maintain; look through the MAINTAINERS file and the
+source code revision history to see who those maintainers are. The
+script scripts/get_maintainer.pl can be very useful at this step. If you
+cannot find a maintainer for the subsystem you are working on, Andrew
+Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
+
+You should also normally choose at least one mailing list to receive a copy
+of your patch set. linux-kernel@vger.kernel.org functions as a list of
+last resort, but the volume on that list has caused a number of developers
+to tune it out. Look in the MAINTAINERS file for a subsystem-specific
+list; your patch will probably get more attention there. Please do not
+spam unrelated lists, though.
+
+Many kernel-related lists are hosted on vger.kernel.org; you can find a
+list of them at http://vger.kernel.org/vger-lists.html. There are
+kernel-related lists hosted elsewhere as well, though.
+
+Do not send more than 15 patches at once to the vger mailing lists!!!
+
+Linus Torvalds is the final arbiter of all changes accepted into the
+Linux kernel. His e-mail address is <torvalds@linux-foundation.org>.
+He gets a lot of e-mail, and, at this point, very few patches go through
+Linus directly, so typically you should do your best to -avoid-
+sending him e-mail.
+
+If you have a patch that fixes an exploitable security bug, send that patch
+to security@kernel.org. For severe bugs, a short embargo may be considered
+to allow distributors to get the patch out to users; in such cases,
+obviously, the patch should not be sent to any public lists.
+
+Patches that fix a severe bug in a released kernel should be directed
+toward the stable maintainers by putting a line like this::
+
+ Cc: stable@vger.kernel.org
+
+into the sign-off area of your patch (note, NOT an email recipient). You
+should also read
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+in addition to this file.
+
+Note, however, that some subsystem maintainers want to come to their own
+conclusions on which patches should go to the stable trees. The networking
+maintainer, in particular, would rather not see individual developers
+adding lines like the above to their patches.
+
+If changes affect userland-kernel interfaces, please send the MAN-PAGES
+maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at
+least a notification of the change, so that some information makes its way
+into the manual pages. User-space API changes should also be copied to
+linux-api@vger.kernel.org.
+
+For small patches you may want to CC the Trivial Patch Monkey
+trivial@kernel.org which collects "trivial" patches. Have a look
+into the MAINTAINERS file for its current manager.
+
+Trivial patches must qualify for one of the following rules:
+
+- Spelling fixes in documentation
+- Spelling fixes for errors which could break :manpage:`grep(1)`
+- Warning fixes (cluttering with useless warnings is bad)
+- Compilation fixes (only if they are actually correct)
+- Runtime fixes (only if they actually fix things)
+- Removing use of deprecated functions/macros
+- Contact detail and documentation fixes
+- Non-portable code replaced by portable code (even in arch-specific,
+ since people copy, as long as it's trivial)
+- Any fix by the author/maintainer of the file (ie. patch monkey
+ in re-transmission mode)
+
+
+
+6) No MIME, no links, no compression, no attachments. Just plain text
+----------------------------------------------------------------------
+
+Linus and other kernel developers need to be able to read and comment
+on the changes you are submitting. It is important for a kernel
+developer to be able to "quote" your changes, using standard e-mail
+tools, so that they may comment on specific portions of your code.
+
+For this reason, all patches should be submitted by e-mail "inline".
+
+.. warning::
+
+ Be wary of your editor's word-wrap corrupting your patch,
+ if you choose to cut-n-paste your patch.
+
+Do not attach the patch as a MIME attachment, compressed or not.
+Many popular e-mail applications will not always transmit a MIME
+attachment as plain text, making it impossible to comment on your
+code. A MIME attachment also takes Linus a bit more time to process,
+decreasing the likelihood of your MIME-attached change being accepted.
+
+Exception: If your mailer is mangling patches then someone may ask
+you to re-send them using MIME.
+
+See :ref:`Documentation/process/email-clients.rst <email_clients>`
+for hints about configuring your e-mail client so that it sends your patches
+untouched.
+
+7) E-mail size
+--------------
+
+Large changes are not appropriate for mailing lists, and some
+maintainers. If your patch, uncompressed, exceeds 300 kB in size,
+it is preferred that you store your patch on an Internet-accessible
+server, and provide instead a URL (link) pointing to your patch. But note
+that if your patch exceeds 300 kB, it almost certainly needs to be broken up
+anyway.
+
+8) Respond to review comments
+-----------------------------
+
+Your patch will almost certainly get comments from reviewers on ways in
+which the patch can be improved. You must respond to those comments;
+ignoring reviewers is a good way to get ignored in return. Review comments
+or questions that do not lead to a code change should almost certainly
+bring about a comment or changelog entry so that the next reviewer better
+understands what is going on.
+
+Be sure to tell the reviewers what changes you are making and to thank them
+for their time. Code review is a tiring and time-consuming process, and
+reviewers sometimes get grumpy. Even in that case, though, respond
+politely and address the problems they have pointed out.
+
+
+9) Don't get discouraged - or impatient
+---------------------------------------
+
+After you have submitted your change, be patient and wait. Reviewers are
+busy people and may not get to your patch right away.
+
+Once upon a time, patches used to disappear into the void without comment,
+but the development process works more smoothly than that now. You should
+receive comments within a week or so; if that does not happen, make sure
+that you have sent your patches to the right place. Wait for a minimum of
+one week before resubmitting or pinging reviewers - possibly longer during
+busy times like merge windows.
+
+
+10) Include PATCH in the subject
+--------------------------------
+
+Due to high e-mail traffic to Linus, and to linux-kernel, it is common
+convention to prefix your subject line with [PATCH]. This lets Linus
+and other kernel developers more easily distinguish patches from other
+e-mail discussions.
+
+
+
+11) Sign your work — the Developer's Certificate of Origin
+----------------------------------------------------------
+
+To improve tracking of who did what, especially with patches that can
+percolate to their final resting place in the kernel through several
+layers of maintainers, we've introduced a "sign-off" procedure on
+patches that are being emailed around.
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as an open-source patch. The rules are pretty simple: if you
+can certify the below:
+
+Developer's Certificate of Origin 1.1
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By making a contribution to this project, I certify that:
+
+ (a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+ (b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+ (c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
+then you just add a line saying::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+using your real name (sorry, no pseudonyms or anonymous contributions.)
+
+Some people also put extra tags at the end. They'll just be ignored for
+now, but you can do this to mark internal company procedures or just
+point out some special detail about the sign-off.
+
+If you are a subsystem or branch maintainer, sometimes you need to slightly
+modify patches you receive in order to merge them, because the code is not
+exactly the same in your tree and the submitters'. If you stick strictly to
+rule (c), you should ask the submitter to rediff, but this is a totally
+counter-productive waste of time and energy. Rule (b) allows you to adjust
+the code, but then it is very impolite to change one submitter's code and
+make him endorse your bugs. To solve this problem, it is recommended that
+you add a line between the last Signed-off-by header and yours, indicating
+the nature of your changes. While there is nothing mandatory about this, it
+seems like prepending the description with your mail and/or name, all
+enclosed in square brackets, is noticeable enough to make it obvious that
+you are responsible for last-minute changes. Example::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+ [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+ Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+This practice is particularly helpful if you maintain a stable branch and
+want at the same time to credit the author, track changes, merge the fix,
+and protect the submitter from complaints. Note that under no circumstances
+can you change the author's identity (the From header), as it is the one
+which appears in the changelog.
+
+Special note to back-porters: It seems to be a common and useful practice
+to insert an indication of the origin of a patch at the top of the commit
+message (just after the subject line) to facilitate tracking. For instance,
+here's what we see in a 3.x-stable release::
+
+ Date: Tue Oct 7 07:26:38 2014 -0400
+
+ libata: Un-break ATA blacklist
+
+ commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+And here's what might appear in an older kernel once a patch is backported::
+
+ Date: Tue May 13 22:12:27 2008 +0200
+
+ wireless, airo: waitbusy() won't delay
+
+ [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+Whatever the format, this information provides a valuable help to people
+tracking your trees, and to people trying to troubleshoot bugs in your
+tree.
+
+
+12) When to use Acked-by: and Cc:
+---------------------------------
+
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+ask to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:. It is a record that the acker
+has at least reviewed the patch and has indicated acceptance. Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by: (but note that it is usually better to ask for an
+explicit ack).
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code. Judgement should be used here.
+When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+If a person has had the opportunity to comment on a patch, but has not
+provided such comments, you may optionally add a ``Cc:`` tag to the patch.
+This is the only tag which might be added without an explicit action by the
+person it names - but it should indicate that this person was copied on the
+patch. This tag documents that potentially interested parties
+have been included in the discussion.
+
+
+13) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
+--------------------------------------------------------------------------
+
+The Reported-by tag gives credit to people who find bugs and report them and it
+hopefully inspires them to help us again in the future. Please note that if
+the bug was reported in private, then ask for permission first before using the
+Reported-by tag.
+
+A Tested-by: tag indicates that the patch has been successfully tested (in
+some environment) by the person named. This tag informs maintainers that
+some testing has been performed, provides a means to locate testers for
+future patches, and ensures credit for the testers.
+
+Reviewed-by:, instead, indicates that the patch has been reviewed and found
+acceptable according to the Reviewer's Statement:
+
+Reviewer's statement of oversight
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By offering my Reviewed-by: tag, I state that:
+
+ (a) I have carried out a technical review of this patch to
+ evaluate its appropriateness and readiness for inclusion into
+ the mainline kernel.
+
+ (b) Any problems, concerns, or questions relating to the patch
+ have been communicated back to the submitter. I am satisfied
+ with the submitter's response to my comments.
+
+ (c) While there may be things that could be improved with this
+ submission, I believe that it is, at this time, (1) a
+ worthwhile modification to the kernel, and (2) free of known
+ issues which would argue against its inclusion.
+
+ (d) While I have reviewed the patch and believe it to be sound, I
+ do not (unless explicitly stated elsewhere) make any
+ warranties or guarantees that it will achieve its stated
+ purpose or function properly in any given situation.
+
+A Reviewed-by tag is a statement of opinion that the patch is an
+appropriate modification of the kernel without any remaining serious
+technical issues. Any interested reviewer (who has done the work) can
+offer a Reviewed-by tag for a patch. This tag serves to give credit to
+reviewers and to inform maintainers of the degree of review which has been
+done on the patch. Reviewed-by: tags, when supplied by reviewers known to
+understand the subject area and to perform thorough reviews, will normally
+increase the likelihood of your patch getting into the kernel.
+
+A Suggested-by: tag indicates that the patch idea is suggested by the person
+named and ensures credit to the person for the idea. Please note that this
+tag should not be added without the reporter's permission, especially if the
+idea was not posted in a public forum. That said, if we diligently credit our
+idea reporters, they will, hopefully, be inspired to help us again in the
+future.
+
+A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
+is used to make it easy to determine where a bug originated, which can help
+review a bug fix. This tag also assists the stable kernel team in determining
+which stable kernel versions should receive your fix. This is the preferred
+method for indicating a bug fixed by the patch. See :ref:`describe_changes`
+for more details.
+
+
+14) The canonical patch format
+------------------------------
+
+This section describes how the patch itself should be formatted. Note
+that, if you have your patches stored in a ``git`` repository, proper patch
+formatting can be had with ``git format-patch``. The tools cannot create
+the necessary text, though, so read the instructions below anyway.
+
+The canonical patch subject line is::
+
+ Subject: [PATCH 001/123] subsystem: summary phrase
+
+The canonical patch message body contains the following:
+
+ - A ``from`` line specifying the patch author (only needed if the person
+ sending the patch is not the author).
+
+ - An empty line.
+
+ - The body of the explanation, line wrapped at 75 columns, which will
+ be copied to the permanent changelog to describe this patch.
+
+ - The ``Signed-off-by:`` lines, described above, which will
+ also go in the changelog.
+
+ - A marker line containing simply ``---``.
+
+ - Any additional comments not suitable for the changelog.
+
+ - The actual patch (``diff`` output).
+
+The Subject line format makes it very easy to sort the emails
+alphabetically by subject line - pretty much any email reader will
+support that - since because the sequence number is zero-padded,
+the numerical and alphabetic sort is the same.
+
+The ``subsystem`` in the email's Subject should identify which
+area or subsystem of the kernel is being patched.
+
+The ``summary phrase`` in the email's Subject should concisely
+describe the patch which that email contains. The ``summary
+phrase`` should not be a filename. Do not use the same ``summary
+phrase`` for every patch in a whole patch series (where a ``patch
+series`` is an ordered sequence of multiple, related patches).
+
+Bear in mind that the ``summary phrase`` of your email becomes a
+globally-unique identifier for that patch. It propagates all the way
+into the ``git`` changelog. The ``summary phrase`` may later be used in
+developer discussions which refer to the patch. People will want to
+google for the ``summary phrase`` to read discussion regarding that
+patch. It will also be the only thing that people may quickly see
+when, two or three months later, they are going through perhaps
+thousands of patches using tools such as ``gitk`` or ``git log
+--oneline``.
+
+For these reasons, the ``summary`` must be no more than 70-75
+characters, and it must describe both what the patch changes, as well
+as why the patch might be necessary. It is challenging to be both
+succinct and descriptive, but that is what a well-written summary
+should do.
+
+The ``summary phrase`` may be prefixed by tags enclosed in square
+brackets: "Subject: [PATCH <tag>...] <summary phrase>". The tags are
+not considered part of the summary phrase, but describe how the patch
+should be treated. Common tags might include a version descriptor if
+the multiple versions of the patch have been sent out in response to
+comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
+comments. If there are four patches in a patch series the individual
+patches may be numbered like this: 1/4, 2/4, 3/4, 4/4. This assures
+that developers understand the order in which the patches should be
+applied and that they have reviewed or applied all of the patches in
+the patch series.
+
+A couple of example Subjects::
+
+ Subject: [PATCH 2/5] ext2: improve scalability of bitmap searching
+ Subject: [PATCH v2 01/27] x86: fix eflags tracking
+
+The ``from`` line must be the very first line in the message body,
+and has the form:
+
+ From: Original Author <author@example.com>
+
+The ``from`` line specifies who will be credited as the author of the
+patch in the permanent changelog. If the ``from`` line is missing,
+then the ``From:`` line from the email header will be used to determine
+the patch author in the changelog.
+
+The explanation body will be committed to the permanent source
+changelog, so should make sense to a competent reader who has long
+since forgotten the immediate details of the discussion that might
+have led to this patch. Including symptoms of the failure which the
+patch addresses (kernel log messages, oops messages, etc.) is
+especially useful for people who might be searching the commit logs
+looking for the applicable patch. If a patch fixes a compile failure,
+it may not be necessary to include _all_ of the compile failures; just
+enough that it is likely that someone searching for the patch can find
+it. As in the ``summary phrase``, it is important to be both succinct as
+well as descriptive.
+
+The ``---`` marker line serves the essential purpose of marking for patch
+handling tools where the changelog message ends.
+
+One good use for the additional comments after the ``---`` marker is for
+a ``diffstat``, to show what files have changed, and the number of
+inserted and deleted lines per file. A ``diffstat`` is especially useful
+on bigger patches. Other comments relevant only to the moment or the
+maintainer, not suitable for the permanent changelog, should also go
+here. A good example of such comments might be ``patch changelogs``
+which describe what has changed between the v1 and v2 version of the
+patch.
+
+If you are going to include a ``diffstat`` after the ``---`` marker, please
+use ``diffstat`` options ``-p 1 -w 70`` so that filenames are listed from
+the top of the kernel source tree and don't use too much horizontal
+space (easily fit in 80 columns, maybe with some indentation). (``git``
+generates appropriate diffstats by default.)
+
+See more details on the proper patch format in the following
+references.
+
+.. _explicit_in_reply_to:
+
+15) Explicit In-Reply-To headers
+--------------------------------
+
+It can be helpful to manually add In-Reply-To: headers to a patch
+(e.g., when using ``git send-email``) to associate the patch with
+previous relevant discussion, e.g. to link a bug fix to the email with
+the bug report. However, for a multi-patch series, it is generally
+best to avoid using In-Reply-To: to link to older versions of the
+series. This way multiple versions of the patch don't become an
+unmanageable forest of references in email clients. If a link is
+helpful, you can use the https://lkml.kernel.org/ redirector (e.g., in
+the cover email text) to link to an earlier version of the patch series.
+
+
+16) Sending ``git pull`` requests
+---------------------------------
+
+If you have a series of patches, it may be most convenient to have the
+maintainer pull them directly into the subsystem repository with a
+``git pull`` operation. Note, however, that pulling patches from a developer
+requires a higher degree of trust than taking patches from a mailing list.
+As a result, many subsystem maintainers are reluctant to take pull
+requests, especially from new, unknown developers. If in doubt you can use
+the pull request as the cover letter for a normal posting of the patch
+series, giving the maintainer the option of using either.
+
+A pull request should have [GIT] or [PULL] in the subject line. The
+request itself should include the repository name and the branch of
+interest on a single line; it should look something like::
+
+ Please pull from
+
+ git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+ to get these changes:
+
+A pull request should also include an overall message saying what will be
+included in the request, a ``git shortlog`` listing of the patches
+themselves, and a ``diffstat`` showing the overall effect of the patch series.
+The easiest way to get all this information together is, of course, to let
+``git`` do it for you with the ``git request-pull`` command.
+
+Some maintainers (including Linus) want to see pull requests from signed
+commits; that increases their confidence that the request actually came
+from you. Linus, in particular, will not pull from public hosting sites
+like GitHub in the absence of a signed tag.
+
+The first step toward creating such tags is to make a GNUPG key and get it
+signed by one or more core kernel developers. This step can be hard for
+new developers, but there is no way around it. Attending conferences can
+be a good way to find developers who can sign your key.
+
+Once you have prepared a patch series in ``git`` that you wish to have somebody
+pull, create a signed tag with ``git tag -s``. This will create a new tag
+identifying the last commit in the series and containing a signature
+created with your private key. You will also have the opportunity to add a
+changelog-style message to the tag; this is an ideal place to describe the
+effects of the pull request as a whole.
+
+If the tree the maintainer will be pulling from is not the repository you
+are working from, don't forget to push the signed tag explicitly to the
+public tree.
+
+When generating your pull request, use the signed tag as the target. A
+command like this will do the trick::
+
+ git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+
+References
+----------
+
+Andrew Morton, "The perfect patch" (tpp).
+ <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+ <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+ <http://www.kroah.com/log/linux/maintainer.html>
+
+ <http://www.kroah.com/log/linux/maintainer-02.html>
+
+ <http://www.kroah.com/log/linux/maintainer-03.html>
+
+ <http://www.kroah.com/log/linux/maintainer-04.html>
+
+ <http://www.kroah.com/log/linux/maintainer-05.html>
+
+ <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+ <https://lkml.org/lkml/2005/7/11/336>
+
+Kernel Documentation/process/coding-style.rst:
+ :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+ <http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+ Some strategies to get difficult or controversial changes in.
+
+ http://halobates.de/on-submitting-patches.pdf
diff --git a/Documentation/volatile-considered-harmful.txt b/Documentation/process/volatile-considered-harmful.rst
index db0cb228d64a..4934e656a6f3 100644
--- a/Documentation/volatile-considered-harmful.txt
+++ b/Documentation/process/volatile-considered-harmful.rst
@@ -1,3 +1,6 @@
+
+.. _volatile_considered_harmful:
+
Why the "volatile" type class should not be used
------------------------------------------------
@@ -22,7 +25,7 @@ need to use volatile as well. If volatile is still necessary, there is
almost certainly a bug in the code somewhere. In properly-written kernel
code, volatile can only serve to slow things down.
-Consider a typical block of kernel code:
+Consider a typical block of kernel code::
spin_lock(&the_lock);
do_something_on(&shared_data);
@@ -57,7 +60,7 @@ optimization, so, once again, volatile is unnecessary.
Another situation where one might be tempted to use volatile is
when the processor is busy-waiting on the value of a variable. The right
-way to perform a busy wait is:
+way to perform a busy wait is::
while (my_variable != what_i_want)
cpu_relax();
@@ -103,17 +106,20 @@ they come with a justification which shows that the concurrency issues have
been properly thought through.
-NOTES
------
+References
+==========
[1] http://lwn.net/Articles/233481/
+
[2] http://lwn.net/Articles/233482/
-CREDITS
--------
+Credits
+=======
Original impetus and research by Randy Dunlap
+
Written by Jonathan Corbet
+
Improvements via comments from Satyam Sharma, Johannes Stezenbach, Jesper
- Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
- Richter.
+Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
+Richter.
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index 1f0c27049340..8c174063b3f0 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -26,7 +26,7 @@ whether they can be changed or not:
the system software.
The rfkill subsystem has two parameters, rfkill.default_state and
-rfkill.master_switch_mode, which are documented in kernel-parameters.txt.
+rfkill.master_switch_mode, which are documented in admin-guide/kernel-parameters.rst.
2. Implementation details
diff --git a/Documentation/scheduler/completion.txt b/Documentation/scheduler/completion.txt
index 2622bc7a188b..656cf803c006 100644
--- a/Documentation/scheduler/completion.txt
+++ b/Documentation/scheduler/completion.txt
@@ -25,8 +25,7 @@ struct completion that tells the waiting threads of execution if they
can continue safely.
As completions are scheduling related, the code is found in
-kernel/sched/completion.c - for details on completion design and
-implementation see completions-design.txt
+kernel/sched/completion.c.
Usage:
diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt
index 8e66dafa41e1..8477655c0e46 100644
--- a/Documentation/scsi/scsi-parameters.txt
+++ b/Documentation/scsi/scsi-parameters.txt
@@ -1,7 +1,7 @@
SCSI Kernel Parameters
~~~~~~~~~~~~~~~~~~~~~~
-See Documentation/kernel-parameters.txt for general information on
+See Documentation/admin-guide/kernel-parameters.rst for general information on
specifying module parameters.
This document may not be entirely up to date and comprehensive. The command
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 255075157511..6338400eed73 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -336,7 +336,7 @@ in parallel by these functions.
Conventions
===========
First, Linus Torvalds's thoughts on C coding style can be found in the
-Documentation/CodingStyle file.
+Documentation/process/coding-style.rst file.
Next, there is a movement to "outlaw" typedefs introducing synonyms for
struct tags. Both can be still found in the SCSI subsystem, but
diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
index 6af8f7a7770f..d28186553fb0 100644
--- a/Documentation/scsi/sym53c8xx_2.txt
+++ b/Documentation/scsi/sym53c8xx_2.txt
@@ -427,7 +427,7 @@ Synchronous transfers frequency (default answer: 80)
10.1 Syntax
Setup commands can be passed to the driver either at boot time or as
-parameters to modprobe, as described in Documentation/kernel-parameters.txt
+parameters to modprobe, as described in Documentation/admin-guide/kernel-parameters.rst
Example of boot setup command under lilo prompt:
diff --git a/Documentation/security/conf.py b/Documentation/security/conf.py
new file mode 100644
index 000000000000..472fc9a8eb67
--- /dev/null
+++ b/Documentation/security/conf.py
@@ -0,0 +1,8 @@
+project = "The kernel security subsystem manual"
+
+tags.add("subproject")
+
+latex_documents = [
+ ('index', 'security.tex', project,
+ 'The kernel development community', 'manual'),
+]
diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
new file mode 100644
index 000000000000..9bae6bb20e7f
--- /dev/null
+++ b/Documentation/security/index.rst
@@ -0,0 +1,7 @@
+======================
+Security documentation
+======================
+
+.. toctree::
+
+ tpm/index
diff --git a/Documentation/security/tpm/index.rst b/Documentation/security/tpm/index.rst
new file mode 100644
index 000000000000..af77a7bbb070
--- /dev/null
+++ b/Documentation/security/tpm/index.rst
@@ -0,0 +1,7 @@
+=====================================
+Trusted Platform Module documentation
+=====================================
+
+.. toctree::
+
+ tpm_vtpm_proxy
diff --git a/Documentation/tpm/tpm_vtpm_proxy.txt b/Documentation/security/tpm/tpm_vtpm_proxy.rst
index 30d19022f869..ea08e76b17f5 100644
--- a/Documentation/tpm/tpm_vtpm_proxy.txt
+++ b/Documentation/security/tpm/tpm_vtpm_proxy.rst
@@ -1,71 +1,50 @@
+=============================================
Virtual TPM Proxy Driver for Linux Containers
+=============================================
-Authors: Stefan Berger (IBM)
+| Authors:
+| Stefan Berger <stefanb@linux.vnet.ibm.com>
This document describes the virtual Trusted Platform Module (vTPM)
proxy device driver for Linux containers.
-INTRODUCTION
-------------
+Introduction
+============
The goal of this work is to provide TPM functionality to each Linux
container. This allows programs to interact with a TPM in a container
the same way they interact with a TPM on the physical system. Each
container gets its own unique, emulated, software TPM.
-
-DESIGN
-------
+Design
+======
To make an emulated software TPM available to each container, the container
management stack needs to create a device pair consisting of a client TPM
-character device /dev/tpmX (with X=0,1,2...) and a 'server side' file
+character device ``/dev/tpmX`` (with X=0,1,2...) and a 'server side' file
descriptor. The former is moved into the container by creating a character
device with the appropriate major and minor numbers while the file descriptor
is passed to the TPM emulator. Software inside the container can then send
TPM commands using the character device and the emulator will receive the
commands via the file descriptor and use it for sending back responses.
-To support this, the virtual TPM proxy driver provides a device /dev/vtpmx
+To support this, the virtual TPM proxy driver provides a device ``/dev/vtpmx``
that is used to create device pairs using an ioctl. The ioctl takes as
an input flags for configuring the device. The flags for example indicate
whether TPM 1.2 or TPM 2 functionality is supported by the TPM emulator.
The result of the ioctl are the file descriptor for the 'server side'
as well as the major and minor numbers of the character device that was created.
-Besides that the number of the TPM character device is return. If for
-example /dev/tpm10 was created, the number (dev_num) 10 is returned.
-
-The following is the data structure of the TPM_PROXY_IOC_NEW_DEV ioctl:
-
-struct vtpm_proxy_new_dev {
- __u32 flags; /* input */
- __u32 tpm_num; /* output */
- __u32 fd; /* output */
- __u32 major; /* output */
- __u32 minor; /* output */
-};
-
-Note that if unsupported flags are passed to the device driver, the ioctl will
-fail and errno will be set to EOPNOTSUPP. Similarly, if an unsupported ioctl is
-called on the device driver, the ioctl will fail and errno will be set to
-ENOTTY.
-
-See /usr/include/linux/vtpm_proxy.h for definitions related to the public interface
-of this vTPM device driver.
+Besides that the number of the TPM character device is returned. If for
+example ``/dev/tpm10`` was created, the number (``dev_num``) 10 is returned.
Once the device has been created, the driver will immediately try to talk
to the TPM. All commands from the driver can be read from the file descriptor
returned by the ioctl. The commands should be responded to immediately.
-Depending on the version of TPM the following commands will be sent by the
-driver:
+UAPI
+====
-- TPM 1.2:
- - the driver will send a TPM_Startup command to the TPM emulator
- - the driver will send commands to read the command durations and
- interface timeouts from the TPM emulator
-- TPM 2:
- - the driver will send a TPM2_Startup command to the TPM emulator
+.. kernel-doc:: include/uapi/linux/vtpm_proxy.h
-The TPM device /dev/tpmX will only appear if all of the relevant commands
-were responded to properly.
+.. kernel-doc:: drivers/char/tpm/tpm_vtpm_proxy.c
+ :functions: vtpmx_ioc_new_dev
diff --git a/Documentation/tpm/xen-tpmfront.txt b/Documentation/security/tpm/xen-tpmfront.txt
index 69346de87ff3..69346de87ff3 100644
--- a/Documentation/tpm/xen-tpmfront.txt
+++ b/Documentation/security/tpm/xen-tpmfront.txt
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
new file mode 100644
index 000000000000..aed6b4fb8e46
--- /dev/null
+++ b/Documentation/sound/alsa-configuration.rst
@@ -0,0 +1,2683 @@
+==============================================================
+Advanced Linux Sound Architecture - Driver Configuration guide
+==============================================================
+
+
+Kernel Configuration
+====================
+
+To enable ALSA support you need at least to build the kernel with
+primary sound card support (``CONFIG_SOUND``). Since ALSA can emulate
+OSS, you don't have to choose any of the OSS modules.
+
+Enable "OSS API emulation" (``CONFIG_SND_OSSEMUL``) and both OSS mixer
+and PCM supports if you want to run OSS applications with ALSA.
+
+If you want to support the WaveTable functionality on cards such as
+SB Live! then you need to enable "Sequencer support"
+(``CONFIG_SND_SEQUENCER``).
+
+To make ALSA debug messages more verbose, enable the "Verbose printk"
+and "Debug" options. To check for memory leaks, turn on "Debug memory"
+too. "Debug detection" will add checks for the detection of cards.
+
+Please note that all the ALSA ISA drivers support the Linux isapnp API
+(if the card supports ISA PnP). You don't need to configure the cards
+using isapnptools.
+
+
+Module parameters
+=================
+
+The user can load modules with options. If the module supports more than
+one card and you have more than one card of the same type then you can
+specify multiple values for the option separated by commas.
+
+
+Module snd
+----------
+
+The core ALSA module. It is used by all ALSA card drivers.
+It takes the following options which have global effects.
+
+major
+ major number for sound driver;
+ Default: 116
+cards_limit
+ limiting card index for auto-loading (1-8);
+ Default: 1;
+ For auto-loading more than one card, specify this option
+ together with snd-card-X aliases.
+slots
+ Reserve the slot index for the given driver;
+ This option takes multiple strings.
+ See `Module Autoloading Support`_ section for details.
+debug
+ Specifies the debug message level;
+ (0 = disable debug prints, 1 = normal debug messages,
+ 2 = verbose debug messages);
+ This option appears only when ``CONFIG_SND_DEBUG=y``.
+ This option can be dynamically changed via sysfs
+ /sys/modules/snd/parameters/debug file.
+
+Module snd-pcm-oss
+------------------
+
+The PCM OSS emulation module.
+This module takes options which change the mapping of devices.
+
+dsp_map
+ PCM device number maps assigned to the 1st OSS device;
+ Default: 0
+adsp_map
+ PCM device number maps assigned to the 2st OSS device;
+ Default: 1
+nonblock_open
+ Don't block opening busy PCM devices;
+ Default: 1
+
+For example, when ``dsp_map=2``, /dev/dsp will be mapped to PCM #2 of
+the card #0. Similarly, when ``adsp_map=0``, /dev/adsp will be mapped
+to PCM #0 of the card #0.
+For changing the second or later card, specify the option with
+commas, such like ``dsp_map=0,1``.
+
+``nonblock_open`` option is used to change the behavior of the PCM
+regarding opening the device. When this option is non-zero,
+opening a busy OSS PCM device won't be blocked but return
+immediately with EAGAIN (just like O_NONBLOCK flag).
+
+Module snd-rawmidi
+------------------
+
+This module takes options which change the mapping of devices.
+similar to those of the snd-pcm-oss module.
+
+midi_map
+ MIDI device number maps assigned to the 1st OSS device;
+ Default: 0
+amidi_map
+ MIDI device number maps assigned to the 2st OSS device;
+ Default: 1
+
+Common parameters for top sound card modules
+--------------------------------------------
+
+Each of top level sound card module takes the following options.
+
+index
+ index (slot #) of sound card;
+ Values: 0 through 31 or negative;
+ If nonnegative, assign that index number;
+ if negative, interpret as a bitmask of permissible indices;
+ the first free permitted index is assigned;
+ Default: -1
+id
+ card ID (identifier or name);
+ Can be up to 15 characters long;
+ Default: the card type;
+ A directory by this name is created under /proc/asound/
+ containing information about the card;
+ This ID can be used instead of the index number in
+ identifying the card
+enable
+ enable card;
+ Default: enabled, for PCI and ISA PnP cards
+
+Module snd-adlib
+----------------
+
+Module for AdLib FM cards.
+
+port
+ port # for OPL chip
+
+This module supports multiple cards. It does not support autoprobe, so
+the port must be specified. For actual AdLib FM cards it will be 0x388.
+Note that this card does not have PCM support and no mixer; only FM
+synthesis.
+
+Make sure you have ``sbiload`` from the alsa-tools package available and,
+after loading the module, find out the assigned ALSA sequencer port
+number through ``sbiload -l``.
+
+Example output:
+::
+
+ Port Client name Port name
+ 64:0 OPL2 FM synth OPL2 FM Port
+
+Load the ``std.sb`` and ``drums.sb`` patches also supplied by ``sbiload``:
+::
+
+ sbiload -p 64:0 std.sb drums.sb
+
+If you use this driver to drive an OPL3, you can use ``std.o3`` and ``drums.o3``
+instead. To have the card produce sound, use ``aplaymidi`` from alsa-utils:
+::
+
+ aplaymidi -p 64:0 foo.mid
+
+Module snd-ad1816a
+------------------
+
+Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
+
+clockfreq
+ Clock frequency for AD1816A chip (default = 0, 33000Hz)
+
+This module supports multiple cards, autoprobe and PnP.
+
+Module snd-ad1848
+-----------------
+
+Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
+
+port
+ port # for AD1848 chip
+irq
+ IRQ # for AD1848 chip
+dma1
+ DMA # for AD1848 chip (0,1,3)
+
+This module supports multiple cards. It does not support autoprobe
+thus main port must be specified!!! Other ports are optional.
+
+The power-management is supported.
+
+Module snd-ad1889
+-----------------
+
+Module for Analog Devices AD1889 chips.
+
+ac97_quirk
+ AC'97 workaround for strange hardware;
+ See the description of intel8x0 module for details.
+
+This module supports multiple cards.
+
+Module snd-ali5451
+------------------
+
+Module for ALi M5451 PCI chip.
+
+pcm_channels
+ Number of hardware channels assigned for PCM
+spdif
+ Support SPDIF I/O;
+ Default: disabled
+
+This module supports one chip and autoprobe.
+
+The power-management is supported.
+
+Module snd-als100
+-----------------
+
+Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
+
+This module supports multiple cards, autoprobe and PnP.
+
+The power-management is supported.
+
+Module snd-als300
+-----------------
+
+Module for Avance Logic ALS300 and ALS300+
+
+This module supports multiple cards.
+
+The power-management is supported.
+
+Module snd-als4000
+------------------
+
+Module for sound cards based on Avance Logic ALS4000 PCI chip.
+
+joystick_port
+ port # for legacy joystick support;
+ 0 = disabled (default), 1 = auto-detect
+
+This module supports multiple cards, autoprobe and PnP.
+
+The power-management is supported.
+
+Module snd-asihpi
+-----------------
+
+Module for AudioScience ASI soundcards
+
+enable_hpi_hwdep
+ enable HPI hwdep for AudioScience soundcard
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-atiixp
+-----------------
+
+Module for ATI IXP 150/200/250/400 AC97 controllers.
+
+ac97_clock
+ AC'97 clock (default = 48000)
+ac97_quirk
+ AC'97 workaround for strange hardware;
+ See `AC97 Quirk Option`_ section below.
+ac97_codec
+ Workaround to specify which AC'97 codec instead of probing.
+ If this works for you file a bug with your `lspci -vn` output.
+ (-2 = Force probing, -1 = Default behavior, 0-2 = Use the
+ specified codec.)
+spdif_aclink
+ S/PDIF transfer over AC-link (default = 1)
+
+This module supports one card and autoprobe.
+
+ATI IXP has two different methods to control SPDIF output. One is
+over AC-link and another is over the "direct" SPDIF output. The
+implementation depends on the motherboard, and you'll need to
+choose the correct one via spdif_aclink module option.
+
+The power-management is supported.
+
+Module snd-atiixp-modem
+-----------------------
+
+Module for ATI IXP 150/200/250 AC97 modem controllers.
+
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-au8810, snd-au8820, snd-au8830
+-----------------------------------------
+
+Module for Aureal Vortex, Vortex2 and Advantage device.
+
+pcifix
+ Control PCI workarounds;
+ 0 = Disable all workarounds,
+ 1 = Force the PCI latency of the Aureal card to 0xff,
+ 2 = Force the Extend PCI#2 Internal Master for Efficient
+ Handling of Dummy Requests on the VIA KT133 AGP Bridge,
+ 3 = Force both settings,
+ 255 = Autodetect what is required (default)
+
+This module supports all ADB PCM channels, ac97 mixer, SPDIF, hardware
+EQ, mpu401, gameport. A3D and wavetable support are still in development.
+Development and reverse engineering work is being coordinated at
+http://savannah.nongnu.org/projects/openvortex/
+SPDIF output has a copy of the AC97 codec output, unless you use the
+``spdif`` pcm device, which allows raw data passthru.
+The hardware EQ hardware and SPDIF is only present in the Vortex2 and
+Advantage.
+
+Note: Some ALSA mixer applications don't handle the SPDIF sample rate
+control correctly. If you have problems regarding this, try
+another ALSA compliant mixer (alsamixer works).
+
+Module snd-azt1605
+------------------
+
+Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
+chipset.
+
+port
+ port # for BASE (0x220,0x240,0x260,0x280)
+wss_port
+ port # for WSS (0x530,0x604,0xe80,0xf40)
+irq
+ IRQ # for WSS (7,9,10,11)
+dma1
+ DMA # for WSS playback (0,1,3)
+dma2
+ DMA # for WSS capture (0,1), -1 = disabled (default)
+mpu_port
+ port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+mpu_irq
+ IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
+fm_port
+ port # for OPL3 (0x388), -1 = disabled (default)
+
+This module supports multiple cards. It does not support autoprobe:
+``port``, ``wss_port``, ``irq`` and ``dma1`` have to be specified.
+The other values are optional.
+
+``port`` needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+or the value stored in the card's EEPROM for cards that have an EEPROM and
+their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+be chosen freely from the options enumerated above.
+
+If ``dma2`` is specified and different from ``dma1``, the card will operate in
+full-duplex mode. When ``dma1=3``, only ``dma2=0`` is valid and the only way to
+enable capture since only channels 0 and 1 are available for capture.
+
+Generic settings are ``port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+mpu_port=0x330 mpu_irq=9 fm_port=0x388``.
+
+Whatever IRQ and DMA channels you pick, be sure to reserve them for
+legacy ISA in your BIOS.
+
+Module snd-azt2316
+------------------
+
+Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
+chipset.
+
+port
+ port # for BASE (0x220,0x240,0x260,0x280)
+wss_port
+ port # for WSS (0x530,0x604,0xe80,0xf40)
+irq
+ IRQ # for WSS (7,9,10,11)
+dma1
+ DMA # for WSS playback (0,1,3)
+dma2
+ DMA # for WSS capture (0,1), -1 = disabled (default)
+mpu_port
+ port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+mpu_irq
+ IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
+fm_port
+ port # for OPL3 (0x388), -1 = disabled (default)
+
+This module supports multiple cards. It does not support autoprobe:
+``port``, ``wss_port``, ``irq`` and ``dma1`` have to be specified.
+The other values are optional.
+
+``port`` needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+or the value stored in the card's EEPROM for cards that have an EEPROM and
+their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+be chosen freely from the options enumerated above.
+
+If ``dma2`` is specified and different from ``dma1``, the card will operate in
+full-duplex mode. When ``dma1=3``, only ``dma2=0`` is valid and the only way to
+enable capture since only channels 0 and 1 are available for capture.
+
+Generic settings are ``port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+mpu_port=0x330 mpu_irq=9 fm_port=0x388``.
+
+Whatever IRQ and DMA channels you pick, be sure to reserve them for
+legacy ISA in your BIOS.
+
+Module snd-aw2
+--------------
+
+Module for Audiowerk2 sound card
+
+This module supports multiple cards.
+
+Module snd-azt2320
+------------------
+
+Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
+
+This module supports multiple cards, PnP and autoprobe.
+
+The power-management is supported.
+
+Module snd-azt3328
+------------------
+
+Module for sound cards based on Aztech AZF3328 PCI chip.
+
+joystick
+ Enable joystick (default off)
+
+This module supports multiple cards.
+
+Module snd-bt87x
+----------------
+
+Module for video cards based on Bt87x chips.
+
+digital_rate
+ Override the default digital rate (Hz)
+load_all
+ Load the driver even if the card model isn't known
+
+This module supports multiple cards.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+Module snd-ca0106
+-----------------
+
+Module for Creative Audigy LS and SB Live 24bit
+
+This module supports multiple cards.
+
+
+Module snd-cmi8330
+------------------
+
+Module for sound cards based on C-Media CMI8330 ISA chips.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+wssport
+ port # for CMI8330 chip (WSS)
+wssirq
+ IRQ # for CMI8330 chip (WSS)
+wssdma
+ first DMA # for CMI8330 chip (WSS)
+sbport
+ port # for CMI8330 chip (SB16)
+sbirq
+ IRQ # for CMI8330 chip (SB16)
+sbdma8
+ 8bit DMA # for CMI8330 chip (SB16)
+sbdma16
+ 16bit DMA # for CMI8330 chip (SB16)
+fmport
+ (optional) OPL3 I/O port
+mpuport
+ (optional) MPU401 I/O port
+mpuirq
+ (optional) MPU401 irq #
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-cmipci
+-----------------
+
+Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
+
+mpu_port
+ port address of MIDI interface (8338 only):
+ 0x300,0x310,0x320,0x330 = legacy port,
+ 0 = disable (default)
+fm_port
+ port address of OPL-3 FM synthesizer (8x38 only):
+ 0x388 = legacy port,
+ 1 = integrated PCI port (default on 8738),
+ 0 = disable
+soft_ac3
+ Software-conversion of raw SPDIF packets (model 033 only) (default = 1)
+joystick_port
+ Joystick port address (0 = disable, 1 = auto-detect)
+
+This module supports autoprobe and multiple cards.
+
+The power-management is supported.
+
+Module snd-cs4231
+-----------------
+
+Module for sound cards based on CS4231 ISA chips.
+
+port
+ port # for CS4231 chip
+mpu_port
+ port # for MPU-401 UART (optional), -1 = disable
+irq
+ IRQ # for CS4231 chip
+mpu_irq
+ IRQ # for MPU-401 UART
+dma1
+ first DMA # for CS4231 chip
+dma2
+ second DMA # for CS4231 chip
+
+This module supports multiple cards. This module does not support autoprobe
+thus main port must be specified!!! Other ports are optional.
+
+The power-management is supported.
+
+Module snd-cs4236
+-----------------
+
+Module for sound cards based on CS4232/CS4232A,
+CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 ISA chips.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for CS4236 chip (PnP setup - 0x534)
+cport
+ control port # for CS4236 chip (PnP setup - 0x120,0x210,0xf00)
+mpu_port
+ port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
+fm_port
+ FM port # for CS4236 chip (PnP setup - 0x388), -1 = disable
+irq
+ IRQ # for CS4236 chip (5,7,9,11,12,15)
+mpu_irq
+ IRQ # for MPU-401 UART (9,11,12,15)
+dma1
+ first DMA # for CS4236 chip (0,1,3)
+dma2
+ second DMA # for CS4236 chip (0,1,3), -1 = disable
+
+This module supports multiple cards. This module does not support autoprobe
+(if ISA PnP is not used) thus main port and control port must be
+specified!!! Other ports are optional.
+
+The power-management is supported.
+
+This module is aliased as snd-cs4232 since it provides the old
+snd-cs4232 functionality, too.
+
+Module snd-cs4281
+-----------------
+
+Module for Cirrus Logic CS4281 soundchip.
+
+dual_codec
+ Secondary codec ID (0 = disable, default)
+
+This module supports multiple cards.
+
+The power-management is supported.
+
+Module snd-cs46xx
+-----------------
+
+Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
+CS4624/CS4630/CS4280 PCI chips.
+
+external_amp
+ Force to enable external amplifier.
+thinkpad
+ Force to enable Thinkpad's CLKRUN control.
+mmap_valid
+ Support OSS mmap mode (default = 0).
+
+This module supports multiple cards and autoprobe.
+Usually external amp and CLKRUN controls are detected automatically
+from PCI sub vendor/device ids. If they don't work, give the options
+above explicitly.
+
+The power-management is supported.
+
+Module snd-cs5530
+-----------------
+
+Module for Cyrix/NatSemi Geode 5530 chip.
+
+Module snd-cs5535audio
+----------------------
+
+Module for multifunction CS5535 companion PCI device
+
+The power-management is supported.
+
+Module snd-ctxfi
+----------------
+
+Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
+
+* Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
+* Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
+* Creative Sound Blaster X-Fi Titanium Professional Audio
+* Creative Sound Blaster X-Fi Titanium
+* Creative Sound Blaster X-Fi Elite Pro
+* Creative Sound Blaster X-Fi Platinum
+* Creative Sound Blaster X-Fi Fatal1ty
+* Creative Sound Blaster X-Fi XtremeGamer
+* Creative Sound Blaster X-Fi XtremeMusic
+
+reference_rate
+ reference sample rate, 44100 or 48000 (default)
+multiple
+ multiple to ref. sample rate, 1 or 2 (default)
+subsystem
+ override the PCI SSID for probing;
+ the value consists of SSVID << 16 | SSDID.
+ The default is zero, which means no override.
+
+This module supports multiple cards.
+
+Module snd-darla20
+------------------
+
+Module for Echoaudio Darla20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-darla24
+------------------
+
+Module for Echoaudio Darla24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-dt019x
+-----------------
+
+Module for Diamond Technologies DT-019X / Avance Logic ALS-007 (PnP
+only)
+
+This module supports multiple cards. This module is enabled only with
+ISA PnP support.
+
+The power-management is supported.
+
+Module snd-dummy
+----------------
+
+Module for the dummy sound card. This "card" doesn't do any output
+or input, but you may use this module for any application which
+requires a sound card (like RealPlayer).
+
+pcm_devs
+ Number of PCM devices assigned to each card (default = 1, up to 4)
+pcm_substreams
+ Number of PCM substreams assigned to each PCM (default = 8, up to 128)
+hrtimer
+ Use hrtimer (=1, default) or system timer (=0)
+fake_buffer
+ Fake buffer allocations (default = 1)
+
+When multiple PCM devices are created, snd-dummy gives different
+behavior to each PCM device:
+* 0 = interleaved with mmap support
+* 1 = non-interleaved with mmap support
+* 2 = interleaved without mmap
+* 3 = non-interleaved without mmap
+
+As default, snd-dummy drivers doesn't allocate the real buffers
+but either ignores read/write or mmap a single dummy page to all
+buffer pages, in order to save the resources. If your apps need
+the read/ written buffer data to be consistent, pass fake_buffer=0
+option.
+
+The power-management is supported.
+
+Module snd-echo3g
+-----------------
+
+Module for Echoaudio 3G cards (Gina3G/Layla3G)
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-emu10k1
+------------------
+
+Module for EMU10K1/EMU10k2 based PCI sound cards.
+
+* Sound Blaster Live!
+* Sound Blaster PCI 512
+* Emu APS (partially supported)
+* Sound Blaster Audigy
+
+extin
+ bitmap of available external inputs for FX8010 (see bellow)
+extout
+ bitmap of available external outputs for FX8010 (see bellow)
+seq_ports
+ allocated sequencer ports (4 by default)
+max_synth_voices
+ limit of voices used for wavetable (64 by default)
+max_buffer_size
+ specifies the maximum size of wavetable/pcm buffers given in MB
+ unit. Default value is 128.
+enable_ir
+ enable IR
+
+This module supports multiple cards and autoprobe.
+
+Input & Output configurations [extin/extout]
+* Creative Card wo/Digital out [0x0003/0x1f03]
+* Creative Card w/Digital out [0x0003/0x1f0f]
+* Creative Card w/Digital CD in [0x000f/0x1f0f]
+* Creative Card wo/Digital out + LiveDrive [0x3fc3/0x1fc3]
+* Creative Card w/Digital out + LiveDrive [0x3fc3/0x1fcf]
+* Creative Card w/Digital CD in + LiveDrive [0x3fcf/0x1fcf]
+* Creative Card wo/Digital out + Digital I/O 2 [0x0fc3/0x1f0f]
+* Creative Card w/Digital out + Digital I/O 2 [0x0fc3/0x1f0f]
+* Creative Card w/Digital CD in + Digital I/O 2 [0x0fcf/0x1f0f]
+* Creative Card 5.1/w Digital out + LiveDrive [0x3fc3/0x1fff]
+* Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff]
+* Creative Card all ins and outs [0x3fff/0x7fff]
+
+The power-management is supported.
+
+Module snd-emu10k1x
+-------------------
+
+Module for Creative Emu10k1X (SB Live Dell OEM version)
+
+This module supports multiple cards.
+
+Module snd-ens1370
+------------------
+
+Module for Ensoniq AudioPCI ES1370 PCI sound cards.
+
+* SoundBlaster PCI 64
+* SoundBlaster PCI 128
+
+joystick
+ Enable joystick (default off)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-ens1371
+------------------
+
+Module for Ensoniq AudioPCI ES1371 PCI sound cards.
+
+* SoundBlaster PCI 64
+* SoundBlaster PCI 128
+* SoundBlaster Vibra PCI
+
+joystick_port
+ port # for joystick (0x200,0x208,0x210,0x218), 0 = disable
+ (default), 1 = auto-detect
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-es1688
+-----------------
+
+Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+mpu_port
+ port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
+mpu_irq
+ IRQ # for MPU-401 port (5,7,9,10)
+fm_port
+ port # for OPL3 (option; share the same port as default)
+
+with ``isapnp=0``, the following additional options are available:
+
+port
+ port # for ES-1688 chip (0x220,0x240,0x260)
+irq
+ IRQ # for ES-1688 chip (5,7,9,10)
+dma8
+ DMA # for ES-1688 chip (0,1,3)
+
+This module supports multiple cards and autoprobe (without MPU-401 port)
+and PnP with the ES968 chip.
+
+Module snd-es18xx
+-----------------
+
+Module for ESS AudioDrive ES-18xx sound cards.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for ES-18xx chip (0x220,0x240,0x260)
+mpu_port
+ port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
+fm_port
+ port # for FM (optional, not used)
+irq
+ IRQ # for ES-18xx chip (5,7,9,10)
+dma1
+ first DMA # for ES-18xx chip (0,1,3)
+dma2
+ first DMA # for ES-18xx chip (0,1,3)
+
+This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
+port if native ISA PnP routines are not used).
+When ``dma2`` is equal with ``dma1``, the driver works as half-duplex.
+
+The power-management is supported.
+
+Module snd-es1938
+-----------------
+
+Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-es1968
+-----------------
+
+Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
+
+total_bufsize
+ total buffer size in kB (1-4096kB)
+pcm_substreams_p
+ playback channels (1-8, default=2)
+pcm_substreams_c
+ capture channels (1-8, default=0)
+clock
+ clock (0 = auto-detection)
+use_pm
+ support the power-management (0 = off, 1 = on, 2 = auto (default))
+enable_mpu
+ enable MPU401 (0 = off, 1 = on, 2 = auto (default))
+joystick
+ enable joystick (default off)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-fm801
+----------------
+
+Module for ForteMedia FM801 based PCI sound cards.
+
+tea575x_tuner
+ Enable TEA575x tuner;
+ 1 = MediaForte 256-PCS,
+ 2 = MediaForte 256-PCPR,
+ 3 = MediaForte 64-PCR
+ High 16-bits are video (radio) device number + 1;
+ example: 0x10002 (MediaForte 256-PCPR, device 1)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-gina20
+-----------------
+
+Module for Echoaudio Gina20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-gina24
+-----------------
+
+Module for Echoaudio Gina24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-gusclassic
+---------------------
+
+Module for Gravis UltraSound Classic sound card.
+
+port
+ port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
+irq
+ IRQ # for GF1 chip (3,5,9,11,12,15)
+dma1
+ DMA # for GF1 chip (1,3,5,6,7)
+dma2
+ DMA # for GF1 chip (1,3,5,6,7,-1=disable)
+joystick_dac
+ 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+ GF1 voices limit (14-32)
+pcm_voices
+ reserved PCM voices
+
+This module supports multiple cards and autoprobe.
+
+Module snd-gusextreme
+---------------------
+
+Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
+
+port
+ port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
+gf1_port
+ port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
+mpu_port
+ port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable
+irq
+ IRQ # for ES-1688 chip (5,7,9,10)
+gf1_irq
+ IRQ # for GF1 chip (3,5,9,11,12,15)
+mpu_irq
+ IRQ # for MPU-401 port (5,7,9,10)
+dma8
+ DMA # for ES-1688 chip (0,1,3)
+dma1
+ DMA # for GF1 chip (1,3,5,6,7)
+joystick_dac
+ 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+ GF1 voices limit (14-32)
+pcm_voices
+ reserved PCM voices
+
+This module supports multiple cards and autoprobe (without MPU-401 port).
+
+Module snd-gusmax
+-----------------
+
+Module for Gravis UltraSound MAX sound card.
+
+port
+ port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
+irq
+ IRQ # for GF1 chip (3,5,9,11,12,15)
+dma1
+ DMA # for GF1 chip (1,3,5,6,7)
+dma2
+ DMA # for GF1 chip (1,3,5,6,7,-1=disable)
+joystick_dac
+ 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+ GF1 voices limit (14-32)
+pcm_voices
+ reserved PCM voices
+
+This module supports multiple cards and autoprobe.
+
+Module snd-hda-intel
+--------------------
+
+Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10,
+PCH, SCH), ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620,
+RV630, RV635, RV670, RV770, VIA VT8251/VT8237A, SIS966, ULI M5461
+
+[Multiple options for each card instance]
+
+model
+ force the model name
+position_fix
+ Fix DMA pointer;
+ -1 = system default: choose appropriate one per controller hardware,
+ 0 = auto: falls back to LPIB when POSBUF doesn't work,
+ 1 = use LPIB,
+ 2 = POSBUF: use position buffer,
+ 3 = VIACOMBO: VIA-specific workaround for capture,
+ 4 = COMBO: use LPIB for playback, auto for capture stream
+probe_mask
+ Bitmask to probe codecs (default = -1, meaning all slots);
+ When the bit 8 (0x100) is set, the lower 8 bits are used
+ as the "fixed" codec slots; i.e. the driver probes the
+ slots regardless what hardware reports back
+probe_only
+ Only probing and no codec initialization (default=off);
+ Useful to check the initial codec status for debugging
+bdl_pos_adj
+ Specifies the DMA IRQ timing delay in samples.
+ Passing -1 will make the driver to choose the appropriate
+ value based on the controller chip.
+patch
+ Specifies the early "patch" files to modify the HD-audio setup
+ before initializing the codecs.
+ This option is available only when ``CONFIG_SND_HDA_PATCH_LOADER=y``
+ is set. See hd-audio/notes.rst for details.
+beep_mode
+ Selects the beep registration mode (0=off, 1=on);
+ default value is set via ``CONFIG_SND_HDA_INPUT_BEEP_MODE`` kconfig.
+
+[Single (global) options]
+
+single_cmd
+ Use single immediate commands to communicate with codecs
+ (for debugging only)
+enable_msi
+ Enable Message Signaled Interrupt (MSI) (default = off)
+power_save
+ Automatic power-saving timeout (in second, 0 = disable)
+power_save_controller
+ Reset HD-audio controller in power-saving mode (default = on)
+align_buffer_size
+ Force rounding of buffer/period sizes to multiples of 128 bytes.
+ This is more efficient in terms of memory access but isn't
+ required by the HDA spec and prevents users from specifying
+ exact period/buffer sizes. (default = on)
+snoop
+ Enable/disable snooping (default = on)
+
+This module supports multiple cards and autoprobe.
+
+See hd-audio/notes.rst for more details about HD-audio driver.
+
+Each codec may have a model table for different configurations.
+If your machine isn't listed there, the default (usually minimal)
+configuration is set up. You can pass ``model=<name>`` option to
+specify a certain model in such a case. There are different
+models depending on the codec chip. The list of available models
+is found in hd-audio/models.rst.
+
+The model name ``generic`` is treated as a special case. When this
+model is given, the driver uses the generic codec parser without
+"codec-patch". It's sometimes good for testing and debugging.
+
+If the default configuration doesn't work and one of the above
+matches with your device, report it together with alsa-info.sh
+output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
+ML (see the section `Links and Addresses`_).
+
+``power_save`` and ``power_save_controller`` options are for power-saving
+mode. See powersave.txt for details.
+
+Note 2: If you get click noises on output, try the module option
+``position_fix=1`` or ``2``. ``position_fix=1`` will use the SD_LPIB
+register value without FIFO size correction as the current
+DMA pointer. ``position_fix=2`` will make the driver to use
+the position buffer instead of reading SD_LPIB register.
+(Usually SD_LPIB register is more accurate than the
+position buffer.)
+
+``position_fix=3`` is specific to VIA devices. The position
+of the capture stream is checked from both LPIB and POSBUF
+values. ``position_fix=4`` is a combination mode, using LPIB
+for playback and POSBUF for capture.
+
+NB: If you get many ``azx_get_response timeout`` messages at
+loading, it's likely a problem of interrupts (e.g. ACPI irq
+routing). Try to boot with options like ``pci=noacpi``. Also, you
+can try ``single_cmd=1`` module option. This will switch the
+communication method between HDA controller and codecs to the
+single immediate commands instead of CORB/RIRB. Basically, the
+single command mode is provided only for BIOS, and you won't get
+unsolicited events, too. But, at least, this works independently
+from the irq. Remember this is a last resort, and should be
+avoided as much as possible...
+
+MORE NOTES ON ``azx_get_response timeout`` PROBLEMS:
+On some hardware, you may need to add a proper probe_mask option
+to avoid the ``azx_get_response timeout`` problem above, instead.
+This occurs when the access to non-existing or non-working codec slot
+(likely a modem one) causes a stall of the communication via HD-audio
+bus. You can see which codec slots are probed by enabling
+``CONFIG_SND_DEBUG_VERBOSE``, or simply from the file name of the codec
+proc files. Then limit the slots to probe by probe_mask option.
+For example, ``probe_mask=1`` means to probe only the first slot, and
+``probe_mask=4`` means only the third slot.
+
+The power-management is supported.
+
+Module snd-hdsp
+---------------
+
+Module for RME Hammerfall DSP audio interface(s)
+
+This module supports multiple cards.
+
+Note: The firmware data can be automatically loaded via hotplug
+when ``CONFIG_FW_LOADER`` is set. Otherwise, you need to load
+the firmware via hdsploader utility included in alsa-tools
+package.
+The firmware data is found in alsa-firmware package.
+
+Note: snd-page-alloc module does the job which snd-hammerfall-mem
+module did formerly. It will allocate the buffers in advance
+when any HDSP cards are found. To make the buffer
+allocation sure, load snd-page-alloc module in the early
+stage of boot sequence. See `Early Buffer Allocation`_
+section.
+
+Module snd-hdspm
+----------------
+
+Module for RME HDSP MADI board.
+
+precise_ptr
+ Enable precise pointer, or disable.
+line_outs_monitor
+ Send playback streams to analog outs by default.
+enable_monitor
+ Enable Analog Out on Channel 63/64 by default.
+
+See hdspm.txt for details.
+
+Module snd-ice1712
+------------------
+
+Module for Envy24 (ICE1712) based PCI sound cards.
+
+* MidiMan M Audio Delta 1010
+* MidiMan M Audio Delta 1010LT
+* MidiMan M Audio Delta DiO 2496
+* MidiMan M Audio Delta 66
+* MidiMan M Audio Delta 44
+* MidiMan M Audio Delta 410
+* MidiMan M Audio Audiophile 2496
+* TerraTec EWS 88MT
+* TerraTec EWS 88D
+* TerraTec EWX 24/96
+* TerraTec DMX 6Fire
+* TerraTec Phase 88
+* Hoontech SoundTrack DSP 24
+* Hoontech SoundTrack DSP 24 Value
+* Hoontech SoundTrack DSP 24 Media 7.1
+* Event Electronics, EZ8
+* Digigram VX442
+* Lionstracs, Mediastaton
+* Terrasoniq TS 88
+
+model
+ Use the given board model, one of the following:
+ delta1010, dio2496, delta66, delta44, audiophile, delta410,
+ delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
+ dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
+ phase88, mediastation
+omni
+ Omni I/O support for MidiMan M-Audio Delta44/66
+cs8427_timeout
+ reset timeout for the CS8427 chip (S/PDIF transceiver) in msec
+ resolution, default value is 500 (0.5 sec)
+
+This module supports multiple cards and autoprobe.
+Note: The consumer part is not used with all Envy24 based cards (for
+example in the MidiMan Delta siree).
+
+Note: The supported board is detected by reading EEPROM or PCI
+SSID (if EEPROM isn't available). You can override the
+model by passing ``model`` module option in case that the
+driver isn't configured properly or you want to try another
+type for testing.
+
+Module snd-ice1724
+------------------
+
+Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
+
+* MidiMan M Audio Revolution 5.1
+* MidiMan M Audio Revolution 7.1
+* MidiMan M Audio Audiophile 192
+* AMP Ltd AUDIO2000
+* TerraTec Aureon 5.1 Sky
+* TerraTec Aureon 7.1 Space
+* TerraTec Aureon 7.1 Universe
+* TerraTec Phase 22
+* TerraTec Phase 28
+* AudioTrak Prodigy 7.1
+* AudioTrak Prodigy 7.1 LT
+* AudioTrak Prodigy 7.1 XT
+* AudioTrak Prodigy 7.1 HIFI
+* AudioTrak Prodigy 7.1 HD2
+* AudioTrak Prodigy 192
+* Pontis MS300
+* Albatron K8X800 Pro II
+* Chaintech ZNF3-150
+* Chaintech ZNF3-250
+* Chaintech 9CJS
+* Chaintech AV-710
+* Shuttle SN25P
+* Onkyo SE-90PCI
+* Onkyo SE-200PCI
+* ESI Juli@
+* ESI Maya44
+* Hercules Fortissimo IV
+* EGO-SYS WaveTerminal 192M
+
+model
+ Use the given board model, one of the following:
+ revo51, revo71, amp2000, prodigy71, prodigy71lt,
+ prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
+ juli, aureon51, aureon71, universe, ap192, k8x800,
+ phase22, phase28, ms300, av710, se200pci, se90pci,
+ fortissimo4, sn25p, WT192M, maya44
+
+This module supports multiple cards and autoprobe.
+
+Note: The supported board is detected by reading EEPROM or PCI
+SSID (if EEPROM isn't available). You can override the
+model by passing ``model`` module option in case that the
+driver isn't configured properly or you want to try another
+type for testing.
+
+Module snd-indigo
+-----------------
+
+Module for Echoaudio Indigo
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-indigodj
+-------------------
+
+Module for Echoaudio Indigo DJ
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-indigoio
+-------------------
+
+Module for Echoaudio Indigo IO
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-intel8x0
+-------------------
+
+Module for AC'97 motherboards from Intel and compatibles.
+
+* Intel i810/810E, i815, i820, i830, i84x, MX440 ICH5, ICH6, ICH7,
+ 6300ESB, ESB2
+* SiS 7012 (SiS 735)
+* NVidia NForce, NForce2, NForce3, MCP04, CK804 CK8, CK8S, MCP501
+* AMD AMD768, AMD8111
+* ALi m5455
+
+ac97_clock
+ AC'97 codec clock base (0 = auto-detect)
+ac97_quirk
+ AC'97 workaround for strange hardware;
+ See `AC97 Quirk Option`_ section below.
+buggy_irq
+ Enable workaround for buggy interrupts on some motherboards
+ (default yes on nForce chips, otherwise off)
+buggy_semaphore
+ Enable workaround for hardware with buggy semaphores (e.g. on some
+ ASUS laptops) (default off)
+spdif_aclink
+ Use S/PDIF over AC-link instead of direct connection from the
+ controller chip (0 = off, 1 = on, -1 = default)
+
+This module supports one chip and autoprobe.
+
+Note: the latest driver supports auto-detection of chip clock.
+if you still encounter too fast playback, specify the clock
+explicitly via the module option ``ac97_clock=41194``.
+
+Joystick/MIDI ports are not supported by this driver. If your
+motherboard has these devices, use the ns558 or snd-mpu401
+modules, respectively.
+
+The power-management is supported.
+
+Module snd-intel8x0m
+--------------------
+
+Module for Intel ICH (i8x0) chipset MC97 modems.
+
+* Intel i810/810E, i815, i820, i830, i84x, MX440 ICH5, ICH6, ICH7
+* SiS 7013 (SiS 735)
+* NVidia NForce, NForce2, NForce2s, NForce3
+* AMD AMD8111
+* ALi m5455
+
+ac97_clock
+ AC'97 codec clock base (0 = auto-detect)
+
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-interwave
+--------------------
+
+Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
+and other sound cards based on AMD InterWave (tm) chip.
+
+joystick_dac
+ 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+midi
+ 1 = MIDI UART enable, 0 = MIDI UART disable (default)
+pcm_voices
+ reserved PCM voices for the synthesizer (default 2)
+effect
+ 1 = InterWave effects enable (default 0); requires 8 voices
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
+irq
+ IRQ # for InterWave chip (3,5,9,11,12,15)
+dma1
+ DMA # for InterWave chip (0,1,3,5,6,7)
+dma2
+ DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Module snd-interwave-stb
+------------------------
+
+Module for UltraSound 32-Pro (sound card from STB used by Compaq)
+and other sound cards based on AMD InterWave (tm) chip with TEA6330T
+circuit for extended control of bass, treble and master volume.
+
+joystick_dac
+ 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+midi
+ 1 = MIDI UART enable, 0 = MIDI UART disable (default)
+pcm_voices
+ reserved PCM voices for the synthesizer (default 2)
+effect
+ 1 = InterWave effects enable (default 0); requires 8 voices
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
+port_tc
+ tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
+irq
+ IRQ # for InterWave chip (3,5,9,11,12,15)
+dma1
+ DMA # for InterWave chip (0,1,3,5,6,7)
+dma2
+ DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Module snd-jazz16
+-------------------
+
+Module for Media Vision Jazz16 chipset. The chipset consists of 3 chips:
+MVD1216 + MVA416 + MVA514.
+
+port
+ port # for SB DSP chip (0x210,0x220,0x230,0x240,0x250,0x260)
+irq
+ IRQ # for SB DSP chip (3,5,7,9,10,15)
+dma8
+ DMA # for SB DSP chip (1,3)
+dma16
+ DMA # for SB DSP chip (5,7)
+mpu_port
+ MPU-401 port # (0x300,0x310,0x320,0x330)
+mpu_irq
+ MPU-401 irq # (2,3,5,7)
+
+This module supports multiple cards.
+
+Module snd-korg1212
+-------------------
+
+Module for Korg 1212 IO PCI card
+
+This module supports multiple cards.
+
+Module snd-layla20
+------------------
+
+Module for Echoaudio Layla20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-layla24
+------------------
+
+Module for Echoaudio Layla24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-lola
+---------------
+
+Module for Digigram Lola PCI-e boards
+
+This module supports multiple cards.
+
+Module snd-lx6464es
+-------------------
+
+Module for Digigram LX6464ES boards
+
+This module supports multiple cards.
+
+Module snd-maestro3
+-------------------
+
+Module for Allegro/Maestro3 chips
+
+external_amp
+ enable external amp (enabled by default)
+amp_gpio
+ GPIO pin number for external amp (0-15) or -1 for default pin (8
+ for allegro, 1 for others)
+
+This module supports autoprobe and multiple chips.
+
+Note: the binding of amplifier is dependent on hardware.
+If there is no sound even though all channels are unmuted, try to
+specify other gpio connection via amp_gpio option.
+For example, a Panasonic notebook might need ``amp_gpio=0x0d``
+option.
+
+The power-management is supported.
+
+Module snd-mia
+---------------
+
+Module for Echoaudio Mia
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-miro
+---------------
+
+Module for Miro soundcards: miroSOUND PCM 1 pro, miroSOUND PCM 12,
+miroSOUND PCM 20 Radio.
+
+port
+ Port # (0x530,0x604,0xe80,0xf40)
+irq
+ IRQ # (5,7,9,10,11)
+dma1
+ 1st dma # (0,1,3)
+dma2
+ 2nd dma # (0,1)
+mpu_port
+ MPU-401 port # (0x300,0x310,0x320,0x330)
+mpu_irq
+ MPU-401 irq # (5,7,9,10)
+fm_port
+ FM Port # (0x388)
+wss
+ enable WSS mode
+ide
+ enable onboard ide support
+
+Module snd-mixart
+-----------------
+
+Module for Digigram miXart8 sound cards.
+
+This module supports multiple cards.
+Note: One miXart8 board will be represented as 4 alsa cards.
+See MIXART.txt for details.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via mixartloader utility in alsa-tools package.
+
+Module snd-mona
+---------------
+
+Module for Echoaudio Mona
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-mpu401
+-----------------
+
+Module for MPU-401 UART devices.
+
+port
+ port number or -1 (disable)
+irq
+ IRQ number or -1 (disable)
+pnp
+ PnP detection - 0 = disable, 1 = enable (default)
+
+This module supports multiple devices and PnP.
+
+Module snd-msnd-classic
+-----------------------
+
+Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
+soundcards.
+
+io
+ Port # for msnd-classic card
+irq
+ IRQ # for msnd-classic card
+mem
+ Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000)
+write_ndelay
+ enable write ndelay (default = 1)
+calibrate_signal
+ calibrate signal (default = 0)
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+digital
+ Digital daughterboard present (default = 0)
+cfg
+ Config port (0x250, 0x260 or 0x270) default = PnP
+reset
+ Reset all devices
+mpu_io
+ MPU401 I/O port
+mpu_irq
+ MPU401 irq#
+ide_io0
+ IDE port #0
+ide_io1
+ IDE port #1
+ide_irq
+ IDE irq#
+joystick_io
+ Joystick I/O port
+
+The driver requires firmware files ``turtlebeach/msndinit.bin`` and
+``turtlebeach/msndperm.bin`` in the proper firmware directory.
+
+See Documentation/sound/oss/MultiSound for important information
+about this driver. Note that it has been discontinued, but the
+Voyetra Turtle Beach knowledge base entry for it is still available
+at
+http://www.turtlebeach.com
+
+Module snd-msnd-pinnacle
+------------------------
+
+Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
+
+io
+ Port # for pinnacle/fiji card
+irq
+ IRQ # for pinnalce/fiji card
+mem
+ Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000)
+write_ndelay
+ enable write ndelay (default = 1)
+calibrate_signal
+ calibrate signal (default = 0)
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+The driver requires firmware files ``turtlebeach/pndspini.bin`` and
+``turtlebeach/pndsperm.bin`` in the proper firmware directory.
+
+Module snd-mtpav
+----------------
+
+Module for MOTU MidiTimePiece AV multiport MIDI (on the parallel
+port).
+
+port
+ I/O port # for MTPAV (0x378,0x278, default=0x378)
+irq
+ IRQ # for MTPAV (7,5, default=7)
+hwports
+ number of supported hardware ports, default=8.
+
+Module supports only 1 card. This module has no enable option.
+
+Module snd-mts64
+----------------
+
+Module for Ego Systems (ESI) Miditerminal 4140
+
+This module supports multiple devices.
+Requires parport (``CONFIG_PARPORT``).
+
+Module snd-nm256
+----------------
+
+Module for NeoMagic NM256AV/ZX chips
+
+playback_bufsize
+ max playback frame size in kB (4-128kB)
+capture_bufsize
+ max capture frame size in kB (4-128kB)
+force_ac97
+ 0 or 1 (disabled by default)
+buffer_top
+ specify buffer top address
+use_cache
+ 0 or 1 (disabled by default)
+vaio_hack
+ alias buffer_top=0x25a800
+reset_workaround
+ enable AC97 RESET workaround for some laptops
+reset_workaround2
+ enable extended AC97 RESET workaround for some other laptops
+
+This module supports one chip and autoprobe.
+
+The power-management is supported.
+
+Note: on some notebooks the buffer address cannot be detected
+automatically, or causes hang-up during initialization.
+In such a case, specify the buffer top address explicitly via
+the buffer_top option.
+For example,
+Sony F250: buffer_top=0x25a800
+Sony F270: buffer_top=0x272800
+The driver supports only ac97 codec. It's possible to force
+to initialize/use ac97 although it's not detected. In such a
+case, use ``force_ac97=1`` option - but *NO* guarantee whether it
+works!
+
+Note: The NM256 chip can be linked internally with non-AC97
+codecs. This driver supports only the AC97 codec, and won't work
+with machines with other (most likely CS423x or OPL3SAx) chips,
+even though the device is detected in lspci. In such a case, try
+other drivers, e.g. snd-cs4232 or snd-opl3sa2. Some has ISA-PnP
+but some doesn't have ISA PnP. You'll need to specify ``isapnp=0``
+and proper hardware parameters in the case without ISA PnP.
+
+Note: some laptops need a workaround for AC97 RESET. For the
+known hardware like Dell Latitude LS and Sony PCG-F305, this
+workaround is enabled automatically. For other laptops with a
+hard freeze, you can try ``reset_workaround=1`` option.
+
+Note: Dell Latitude CSx laptops have another problem regarding
+AC97 RESET. On these laptops, reset_workaround2 option is
+turned on as default. This option is worth to try if the
+previous reset_workaround option doesn't help.
+
+Note: This driver is really crappy. It's a porting from the
+OSS driver, which is a result of black-magic reverse engineering.
+The detection of codec will fail if the driver is loaded *after*
+X-server as described above. You might be able to force to load
+the module, but it may result in hang-up. Hence, make sure that
+you load this module *before* X if you encounter this kind of
+problem.
+
+Module snd-opl3sa2
+------------------
+
+Module for Yamaha OPL3-SA2/SA3 sound cards.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ control port # for OPL3-SA chip (0x370)
+sb_port
+ SB port # for OPL3-SA chip (0x220,0x240)
+wss_port
+ WSS port # for OPL3-SA chip (0x530,0xe80,0xf40,0x604)
+midi_port
+ port # for MPU-401 UART (0x300,0x330), -1 = disable
+fm_port
+ FM port # for OPL3-SA chip (0x388), -1 = disable
+irq
+ IRQ # for OPL3-SA chip (5,7,9,10)
+dma1
+ first DMA # for Yamaha OPL3-SA chip (0,1,3)
+dma2
+ second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
+
+This module supports multiple cards and ISA PnP. It does not support
+autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
+
+The power-management is supported.
+
+Module snd-opti92x-ad1848
+-------------------------
+
+Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
+Module works with OAK Mozart cards as well.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+ port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+ port # for OPL3 device (0x388)
+irq
+ IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+ IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+ first DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-opti92x-cs4231
+-------------------------
+
+Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+ port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+ port # for OPL3 device (0x388)
+irq
+ IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+ IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+ first DMA # for WSS chip (0,1,3)
+dma2
+ second DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-opti93x
+------------------
+
+Module for sound cards based on OPTi 82c93x chips.
+
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+ port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+ port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+ port # for OPL3 device (0x388)
+irq
+ IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+ IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+ first DMA # for WSS chip (0,1,3)
+dma2
+ second DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-oxygen
+-----------------
+
+Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
+
+* Asound A-8788
+* Asus Xonar DG/DGX
+* AuzenTech X-Meridian
+* AuzenTech X-Meridian 2G
+* Bgears b-Enspirer
+* Club3D Theatron DTS
+* HT-Omega Claro (plus)
+* HT-Omega Claro halo (XT)
+* Kuroutoshikou CMI8787-HG2PCI
+* Razer Barracuda AC-1
+* Sondigo Inferno
+* TempoTec HiFier Fantasia
+* TempoTec HiFier Serenade
+
+This module supports autoprobe and multiple cards.
+
+Module snd-pcsp
+---------------
+
+Module for internal PC-Speaker.
+
+nopcm
+ Disable PC-Speaker PCM sound. Only beeps remain.
+nforce_wa
+ enable NForce chipset workaround. Expect bad sound.
+
+This module supports system beeps, some kind of PCM playback and
+even a few mixer controls.
+
+Module snd-pcxhr
+----------------
+
+Module for Digigram PCXHR boards
+
+This module supports multiple cards.
+
+Module snd-portman2x4
+---------------------
+
+Module for Midiman Portman 2x4 parallel port MIDI interface
+
+This module supports multiple cards.
+
+Module snd-powermac (on ppc only)
+---------------------------------
+
+Module for PowerMac, iMac and iBook on-board soundchips
+
+enable_beep
+ enable beep using PCM (enabled as default)
+
+Module supports autoprobe a chip.
+
+Note: the driver may have problems regarding endianness.
+
+The power-management is supported.
+
+Module snd-pxa2xx-ac97 (on arm only)
+------------------------------------
+
+Module for AC97 driver for the Intel PXA2xx chip
+
+For ARM architecture only.
+
+The power-management is supported.
+
+Module snd-riptide
+------------------
+
+Module for Conexant Riptide chip
+
+joystick_port
+ Joystick port # (default: 0x200)
+mpu_port
+ MPU401 port # (default: 0x330)
+opl3_port
+ OPL3 port # (default: 0x388)
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+You need to install the firmware file ``riptide.hex`` to the standard
+firmware path (e.g. /lib/firmware).
+
+Module snd-rme32
+----------------
+
+Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
+Prodif96 and Prodif Gold) sound cards.
+
+This module supports multiple cards.
+
+Module snd-rme96
+----------------
+
+Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
+
+This module supports multiple cards.
+
+Module snd-rme9652
+------------------
+
+Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
+
+precise_ptr
+ Enable precise pointer (doesn't work reliably). (default = 0)
+
+This module supports multiple cards.
+
+Note: snd-page-alloc module does the job which snd-hammerfall-mem
+module did formerly. It will allocate the buffers in advance
+when any RME9652 cards are found. To make the buffer
+allocation sure, load snd-page-alloc module in the early
+stage of boot sequence. See `Early Buffer Allocation`_
+section.
+
+Module snd-sa11xx-uda1341 (on arm only)
+---------------------------------------
+
+Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
+
+Module supports only one card.
+Module has no enable and index options.
+
+The power-management is supported.
+
+Module snd-sb8
+--------------
+
+Module for 8-bit SoundBlaster cards: SoundBlaster 1.0, SoundBlaster 2.0,
+SoundBlaster Pro
+
+port
+ port # for SB DSP chip (0x220,0x240,0x260)
+irq
+ IRQ # for SB DSP chip (5,7,9,10)
+dma8
+ DMA # for SB DSP chip (1,3)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-sb16 and snd-sbawe
+-----------------------------
+
+Module for 16-bit SoundBlaster cards: SoundBlaster 16 (PnP),
+SoundBlaster AWE 32 (PnP), SoundBlaster AWE 64 PnP
+
+mic_agc
+ Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
+csp
+ ASP/CSP chip support - 0 = disable (default), 1 = enable
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with isapnp=0, the following options are available:
+
+port
+ port # for SB DSP 4.x chip (0x220,0x240,0x260)
+mpu_port
+ port # for MPU-401 UART (0x300,0x330), -1 = disable
+awe_port
+ base port # for EMU8000 synthesizer (0x620,0x640,0x660) (snd-sbawe
+ module only)
+irq
+ IRQ # for SB DSP 4.x chip (5,7,9,10)
+dma8
+ 8-bit DMA # for SB DSP 4.x chip (0,1,3)
+dma16
+ 16-bit DMA # for SB DSP 4.x chip (5,6,7)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Note: To use Vibra16X cards in 16-bit half duplex mode, you must
+disable 16bit DMA with dma16 = -1 module parameter.
+Also, all Sound Blaster 16 type cards can operate in 16-bit
+half duplex mode through 8-bit DMA channel by disabling their
+16-bit DMA channel.
+
+The power-management is supported.
+
+Module snd-sc6000
+-----------------
+
+Module for Gallant SC-6000 soundcard and later models: SC-6600 and
+SC-7000.
+
+port
+ Port # (0x220 or 0x240)
+mss_port
+ MSS Port # (0x530 or 0xe80)
+irq
+ IRQ # (5,7,9,10,11)
+mpu_irq
+ MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
+dma
+ DMA # (1,3,0)
+joystick
+ Enable gameport - 0 = disable (default), 1 = enable
+
+This module supports multiple cards.
+
+This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
+
+Module snd-sscape
+-----------------
+
+Module for ENSONIQ SoundScape cards.
+
+port
+ Port # (PnP setup)
+wss_port
+ WSS Port # (PnP setup)
+irq
+ IRQ # (PnP setup)
+mpu_irq
+ MPU-401 IRQ # (PnP setup)
+dma
+ DMA # (PnP setup)
+dma2
+ 2nd DMA # (PnP setup, -1 to disable)
+joystick
+ Enable gameport - 0 = disable (default), 1 = enable
+
+This module supports multiple cards.
+
+The driver requires the firmware loader support on kernel.
+
+Module snd-sun-amd7930 (on sparc only)
+--------------------------------------
+
+Module for AMD7930 sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-sun-cs4231 (on sparc only)
+-------------------------------------
+
+Module for CS4231 sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-sun-dbri (on sparc only)
+-----------------------------------
+
+Module for DBRI sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-wavefront
+--------------------
+
+Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
+
+use_cs4232_midi
+ Use CS4232 MPU-401 interface
+ (inaccessibly located inside your computer)
+isapnp
+ ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with isapnp=0, the following options are available:
+
+cs4232_pcm_port
+ Port # for CS4232 PCM interface.
+cs4232_pcm_irq
+ IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
+cs4232_mpu_port
+ Port # for CS4232 MPU-401 interface.
+cs4232_mpu_irq
+ IRQ # for CS4232 MPU-401 interface (9,11,12,15).
+ics2115_port
+ Port # for ICS2115
+ics2115_irq
+ IRQ # for ICS2115
+fm_port
+ FM OPL-3 Port #
+dma1
+ DMA1 # for CS4232 PCM interface.
+dma2
+ DMA2 # for CS4232 PCM interface.
+
+The below are options for wavefront_synth features:
+
+wf_raw
+ Assume that we need to boot the OS (default:no);
+ If yes, then during driver loading, the state of the board is
+ ignored, and we reset the board and load the firmware anyway.
+fx_raw
+ Assume that the FX process needs help (default:yes);
+ If false, we'll leave the FX processor in whatever state it is
+ when the driver is loaded. The default is to download the
+ microprogram and associated coefficients to set it up for
+ "default" operation, whatever that means.
+debug_default
+ Debug parameters for card initialization
+wait_usecs
+ How long to wait without sleeping, usecs (default:150);
+ This magic number seems to give pretty optimal throughput
+ based on my limited experimentation.
+ If you want to play around with it and find a better value, be
+ my guest. Remember, the idea is to get a number that causes us
+ to just busy wait for as many WaveFront commands as possible,
+ without coming up with a number so large that we hog the whole
+ CPU.
+ Specifically, with this number, out of about 134,000 status
+ waits, only about 250 result in a sleep.
+sleep_interval
+ How long to sleep when waiting for reply (default: 100)
+sleep_tries
+ How many times to try sleeping during a wait (default: 50)
+ospath
+ Pathname to processed ICS2115 OS firmware (default:wavefront.os);
+ The path name of the ISC2115 OS firmware. In the recent
+ version, it's handled via firmware loader framework, so it
+ must be installed in the proper path, typically,
+ /lib/firmware.
+reset_time
+ How long to wait for a reset to take effect (default:2)
+ramcheck_time
+ How many seconds to wait for the RAM test (default:20)
+osrun_time
+ How many seconds to wait for the ICS2115 OS (default:10)
+
+This module supports multiple cards and ISA PnP.
+
+Note: the firmware file ``wavefront.os`` was located in the earlier
+version in /etc. Now it's loaded via firmware loader, and
+must be in the proper firmware path, such as /lib/firmware.
+Copy (or symlink) the file appropriately if you get an error
+regarding firmware downloading after upgrading the kernel.
+
+Module snd-sonicvibes
+---------------------
+
+Module for S3 SonicVibes PCI sound cards.
+* PINE Schubert 32 PCI
+
+reverb
+ Reverb Enable - 1 = enable, 0 = disable (default);
+ SoundCard must have onboard SRAM for this.
+mge
+ Mic Gain Enable - 1 = enable, 0 = disable (default)
+
+This module supports multiple cards and autoprobe.
+
+Module snd-serial-u16550
+------------------------
+
+Module for UART16550A serial MIDI ports.
+
+port
+ port # for UART16550A chip
+irq
+ IRQ # for UART16550A chip, -1 = poll mode
+speed
+ speed in bauds (9600,19200,38400,57600,115200)
+ 38400 = default
+base
+ base for divisor in bauds (57600,115200,230400,460800)
+ 115200 = default
+outs
+ number of MIDI ports in a serial port (1-4)
+ 1 = default
+adaptor
+ Type of adaptor.
+ 0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
+ 3 = MS-124W M/B, 4 = Generic
+
+This module supports multiple cards. This module does not support autoprobe
+thus the main port must be specified!!! Other options are optional.
+
+Module snd-trident
+------------------
+
+Module for Trident 4DWave DX/NX sound cards.
+* Best Union Miss Melody 4DWave PCI
+* HIS 4DWave PCI
+* Warpspeed ONSpeed 4DWave PCI
+* AzTech PCI 64-Q3D
+* Addonics SV 750
+* CHIC True Sound 4Dwave
+* Shark Predator4D-PCI
+* Jaton SonicWave 4D
+* SiS SI7018 PCI Audio
+* Hoontech SoundTrack Digital 4DWave NX
+
+pcm_channels
+ max channels (voices) reserved for PCM
+wavetable_size
+ max wavetable size in kB (4-?kb)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-ua101
+----------------
+
+Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+Module snd-usb-audio
+--------------------
+
+Module for USB audio and USB MIDI devices.
+
+vid
+ Vendor ID for the device (optional)
+pid
+ Product ID for the device (optional)
+nrpacks
+ Max. number of packets per URB (default: 8)
+device_setup
+ Device specific magic number (optional);
+ Influence depends on the device
+ Default: 0x0000
+ignore_ctl_error
+ Ignore any USB-controller regarding mixer interface (default: no)
+autoclock
+ Enable auto-clock selection for UAC2 devices (default: yes)
+quirk_alias
+ Quirk alias list, pass strings like ``0123abcd:5678beef``, which
+ applies the existing quirk for the device 5678:beef to a new
+ device 0123:abcd.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+NB: ``nrpacks`` parameter can be modified dynamically via sysfs.
+Don't put the value over 20. Changing via sysfs has no sanity
+check.
+
+NB: ``ignore_ctl_error=1`` may help when you get an error at accessing
+the mixer element such as URB error -22. This happens on some
+buggy USB device or the controller.
+
+NB: quirk_alias option is provided only for testing / development.
+If you want to have a proper support, contact to upstream for
+adding the matching quirk in the driver code statically.
+
+Module snd-usb-caiaq
+--------------------
+
+Module for caiaq UB audio interfaces,
+
+* Native Instruments RigKontrol2
+* Native Instruments Kore Controller
+* Native Instruments Audio Kontrol 1
+* Native Instruments Audio 8 DJ
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+Module snd-usb-usx2y
+--------------------
+
+Module for Tascam USB US-122, US-224 and US-428 devices.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+Note: you need to load the firmware via ``usx2yloader`` utility included
+in alsa-tools and alsa-firmware packages.
+
+Module snd-via82xx
+------------------
+
+Module for AC'97 motherboards based on VIA 82C686A/686B, 8233, 8233A,
+8233C, 8235, 8237 (south) bridge.
+
+mpu_port
+ 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
+ [VIA686A/686B only]
+joystick
+ Enable joystick (default off) [VIA686A/686B only]
+ac97_clock
+ AC'97 codec clock base (default 48000Hz)
+dxs_support
+ support DXS channels, 0 = auto (default), 1 = enable, 2 = disable,
+ 3 = 48k only, 4 = no VRA, 5 = enable any sample rate and different
+ sample rates on different channels [VIA8233/C, 8235, 8237 only]
+ac97_quirk
+ AC'97 workaround for strange hardware;
+ See `AC97 Quirk Option`_ section below.
+
+This module supports one chip and autoprobe.
+
+Note: on some SMP motherboards like MSI 694D the interrupts might
+not be generated properly. In such a case, please try to
+set the SMP (or MPS) version on BIOS to 1.1 instead of
+default value 1.4. Then the interrupt number will be
+assigned under 15. You might also upgrade your BIOS.
+
+Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
+channels as the first PCM. On these channels, up to 4
+streams can be played at the same time, and the controller
+can perform sample rate conversion with separate rates for
+each channel.
+As default (``dxs_support = 0``), 48k fixed rate is chosen
+except for the known devices since the output is often
+noisy except for 48k on some mother boards due to the
+bug of BIOS.
+Please try once ``dxs_support=5`` and if it works on other
+sample rates (e.g. 44.1kHz of mp3 playback), please let us
+know the PCI subsystem vendor/device id's (output of
+``lspci -nv``).
+If ``dxs_support=5`` does not work, try ``dxs_support=4``; if it
+doesn't work too, try dxs_support=1. (dxs_support=1 is
+usually for old motherboards. The correct implemented
+board should work with 4 or 5.) If it still doesn't
+work and the default setting is ok, ``dxs_support=3`` is the
+right choice. If the default setting doesn't work at all,
+try ``dxs_support=2`` to disable the DXS channels.
+In any cases, please let us know the result and the
+subsystem vendor/device ids. See `Links and Addresses`_
+below.
+
+Note: for the MPU401 on VIA823x, use snd-mpu401 driver
+additionally. The mpu_port option is for VIA686 chips only.
+
+The power-management is supported.
+
+Module snd-via82xx-modem
+------------------------
+
+Module for VIA82xx AC97 modem
+
+ac97_clock
+ AC'97 codec clock base (default 48000Hz)
+
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-virmidi
+------------------
+
+Module for virtual rawmidi devices.
+This module creates virtual rawmidi devices which communicate
+to the corresponding ALSA sequencer ports.
+
+midi_devs
+ MIDI devices # (1-4, default=4)
+
+This module supports multiple cards.
+
+Module snd-virtuoso
+-------------------
+
+Module for sound cards based on the Asus AV66/AV100/AV200 chips,
+i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
+Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+
+This module supports autoprobe and multiple cards.
+
+Module snd-vx222
+----------------
+
+Module for Digigram VX-Pocket VX222, V222 v2 and Mic cards.
+
+mic
+ Enable Microphone on V222 Mic (NYI)
+ibl
+ Capture IBL size. (default = 0, minimum size)
+
+This module supports multiple cards.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via vxloader utility in alsa-tools package. To invoke
+vxloader automatically, add the following to /etc/modprobe.d/alsa.conf
+
+::
+
+ install snd-vx222 /sbin/modprobe --first-time -i snd-vx222\
+ && /usr/bin/vxloader
+
+(for 2.2/2.4 kernels, add ``post-install /usr/bin/vxloader`` to
+/etc/modules.conf, instead.)
+IBL size defines the interrupts period for PCM. The smaller size
+gives smaller latency but leads to more CPU consumption, too.
+The size is usually aligned to 126. As default (=0), the smallest
+size is chosen. The possible IBL values can be found in
+/proc/asound/cardX/vx-status proc file.
+
+The power-management is supported.
+
+Module snd-vxpocket
+-------------------
+
+Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
+
+ibl
+ Capture IBL size. (default = 0, minimum size)
+
+This module supports multiple cards. The module is compiled only when
+PCMCIA is supported on kernel.
+
+With the older 2.6.x kernel, to activate the driver via the card
+manager, you'll need to set up /etc/pcmcia/vxpocket.conf. See the
+sound/pcmcia/vx/vxpocket.c. 2.6.13 or later kernel requires no
+longer require a config file.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via vxloader utility in alsa-tools package.
+
+About capture IBL, see the description of snd-vx222 module.
+
+Note: snd-vxp440 driver is merged to snd-vxpocket driver since
+ALSA 1.0.10.
+
+The power-management is supported.
+
+Module snd-ymfpci
+-----------------
+
+Module for Yamaha PCI chips (YMF72x, YMF74x & YMF75x).
+
+mpu_port
+ 0x300,0x330,0x332,0x334, 0 (disable) by default,
+ 1 (auto-detect for YMF744/754 only)
+fm_port
+ 0x388,0x398,0x3a0,0x3a8, 0 (disable) by default
+ 1 (auto-detect for YMF744/754 only)
+joystick_port
+ 0x201,0x202,0x204,0x205, 0 (disable) by default,
+ 1 (auto-detect)
+rear_switch
+ enable shared rear/line-in switch (bool)
+
+This module supports autoprobe and multiple chips.
+
+The power-management is supported.
+
+Module snd-pdaudiocf
+--------------------
+
+Module for Sound Core PDAudioCF sound card.
+
+The power-management is supported.
+
+
+AC97 Quirk Option
+=================
+
+The ac97_quirk option is used to enable/override the workaround for
+specific devices on drivers for on-board AC'97 controllers like
+snd-intel8x0. Some hardware have swapped output pins between Master
+and Headphone, or Surround (thanks to confusion of AC'97
+specifications from version to version :-)
+
+The driver provides the auto-detection of known problematic devices,
+but some might be unknown or wrongly detected. In such a case, pass
+the proper value with this option.
+
+The following strings are accepted:
+
+default
+ Don't override the default setting
+none
+ Disable the quirk
+hp_only
+ Bind Master and Headphone controls as a single control
+swap_hp
+ Swap headphone and master controls
+swap_surround
+ Swap master and surround controls
+ad_sharing
+ For AD1985, turn on OMS bit and use headphone
+alc_jack
+ For ALC65x, turn on the jack sense mode
+inv_eapd
+ Inverted EAPD implementation
+mute_led
+ Bind EAPD bit for turning on/off mute LED
+
+For backward compatibility, the corresponding integer value -1, 0, ...
+are accepted, too.
+
+For example, if ``Master`` volume control has no effect on your device
+but only ``Headphone`` does, pass ac97_quirk=hp_only module option.
+
+
+Configuring Non-ISAPNP Cards
+============================
+
+When the kernel is configured with ISA-PnP support, the modules
+supporting the isapnp cards will have module options ``isapnp``.
+If this option is set, *only* the ISA-PnP devices will be probed.
+For probing the non ISA-PnP cards, you have to pass ``isapnp=0`` option
+together with the proper i/o and irq configuration.
+
+When the kernel is configured without ISA-PnP support, isapnp option
+will be not built in.
+
+
+Module Autoloading Support
+==========================
+
+The ALSA drivers can be loaded automatically on demand by defining
+module aliases. The string ``snd-card-%1`` is requested for ALSA native
+devices where ``%i`` is sound card number from zero to seven.
+
+To auto-load an ALSA driver for OSS services, define the string
+``sound-slot-%i`` where ``%i`` means the slot number for OSS, which
+corresponds to the card index of ALSA. Usually, define this
+as the same card module.
+
+An example configuration for a single emu10k1 card is like below:
+::
+
+ ----- /etc/modprobe.d/alsa.conf
+ alias snd-card-0 snd-emu10k1
+ alias sound-slot-0 snd-emu10k1
+ ----- /etc/modprobe.d/alsa.conf
+
+The available number of auto-loaded sound cards depends on the module
+option ``cards_limit`` of snd module. As default it's set to 1.
+To enable the auto-loading of multiple cards, specify the number of
+sound cards in that option.
+
+When multiple cards are available, it'd better to specify the index
+number for each card via module option, too, so that the order of
+cards is kept consistent.
+
+An example configuration for two sound cards is like below:
+::
+
+ ----- /etc/modprobe.d/alsa.conf
+ # ALSA portion
+ options snd cards_limit=2
+ alias snd-card-0 snd-interwave
+ alias snd-card-1 snd-ens1371
+ options snd-interwave index=0
+ options snd-ens1371 index=1
+ # OSS/Free portion
+ alias sound-slot-0 snd-interwave
+ alias sound-slot-1 snd-ens1371
+ ----- /etc/modprobe.d/alsa.conf
+
+In this example, the interwave card is always loaded as the first card
+(index 0) and ens1371 as the second (index 1).
+
+Alternative (and new) way to fixate the slot assignment is to use
+``slots`` option of snd module. In the case above, specify like the
+following:
+::
+
+ options snd slots=snd-interwave,snd-ens1371
+
+Then, the first slot (#0) is reserved for snd-interwave driver, and
+the second (#1) for snd-ens1371. You can omit index option in each
+driver if slots option is used (although you can still have them at
+the same time as long as they don't conflict).
+
+The slots option is especially useful for avoiding the possible
+hot-plugging and the resultant slot conflict. For example, in the
+case above again, the first two slots are already reserved. If any
+other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
+snd-ens1371, it will be assigned to the third or later slot.
+
+When a module name is given with '!', the slot will be given for any
+modules but that name. For example, ``slots=!snd-pcsp`` will reserve
+the first slot for any modules but snd-pcsp.
+
+
+ALSA PCM devices to OSS devices mapping
+=======================================
+::
+
+ /dev/snd/pcmC0D0[c|p] -> /dev/audio0 (/dev/audio) -> minor 4
+ /dev/snd/pcmC0D0[c|p] -> /dev/dsp0 (/dev/dsp) -> minor 3
+ /dev/snd/pcmC0D1[c|p] -> /dev/adsp0 (/dev/adsp) -> minor 12
+ /dev/snd/pcmC1D0[c|p] -> /dev/audio1 -> minor 4+16 = 20
+ /dev/snd/pcmC1D0[c|p] -> /dev/dsp1 -> minor 3+16 = 19
+ /dev/snd/pcmC1D1[c|p] -> /dev/adsp1 -> minor 12+16 = 28
+ /dev/snd/pcmC2D0[c|p] -> /dev/audio2 -> minor 4+32 = 36
+ /dev/snd/pcmC2D0[c|p] -> /dev/dsp2 -> minor 3+32 = 39
+ /dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44
+
+The first number from ``/dev/snd/pcmC{X}D{Y}[c|p]`` expression means
+sound card number and second means device number. The ALSA devices
+have either ``c`` or ``p`` suffix indicating the direction, capture and
+playback, respectively.
+
+Please note that the device mapping above may be varied via the module
+options of snd-pcm-oss module.
+
+
+Proc interfaces (/proc/asound)
+==============================
+
+/proc/asound/card#/pcm#[cp]/oss
+-------------------------------
+erase
+ erase all additional information about OSS applications
+
+<app_name> <fragments> <fragment_size> [<options>]
+ <app_name>
+ name of application with (higher priority) or without path
+ <fragments>
+ number of fragments or zero if auto
+ <fragment_size>
+ size of fragment in bytes or zero if auto
+ <options>
+ optional parameters
+
+ disable
+ the application tries to open a pcm device for
+ this channel but does not want to use it.
+ (Cause a bug or mmap needs)
+ It's good for Quake etc...
+ direct
+ don't use plugins
+ block
+ force block mode (rvplayer)
+ non-block
+ force non-block mode
+ whole-frag
+ write only whole fragments (optimization affecting
+ playback only)
+ no-silence
+ do not fill silence ahead to avoid clicks
+ buggy-ptr
+ Returns the whitespace blocks in GETOPTR ioctl
+ instead of filled blocks
+
+Example:
+::
+
+ echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
+ echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
+ echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
+
+
+Early Buffer Allocation
+=======================
+
+Some drivers (e.g. hdsp) require the large contiguous buffers, and
+sometimes it's too late to find such spaces when the driver module is
+actually loaded due to memory fragmentation. You can pre-allocate the
+PCM buffers by loading snd-page-alloc module and write commands to its
+proc file in prior, for example, in the early boot stage like
+``/etc/init.d/*.local`` scripts.
+
+Reading the proc file /proc/drivers/snd-page-alloc shows the current
+usage of page allocation. In writing, you can send the following
+commands to the snd-page-alloc driver:
+
+* add VENDOR DEVICE MASK SIZE BUFFERS
+
+VENDOR and DEVICE are PCI vendor and device IDs. They take
+integer numbers (0x prefix is needed for the hex).
+MASK is the PCI DMA mask. Pass 0 if not restricted.
+SIZE is the size of each buffer to allocate. You can pass
+k and m suffix for KB and MB. The max number is 16MB.
+BUFFERS is the number of buffers to allocate. It must be greater
+than 0. The max number is 4.
+
+* erase
+
+This will erase the all pre-allocated buffers which are not in
+use.
+
+
+Links and Addresses
+===================
+
+ALSA project homepage
+ http://www.alsa-project.org
+Kernel Bugzilla
+ http://bugzilla.kernel.org/
+ALSA Developers ML
+ mailto:alsa-devel@alsa-project.org
+alsa-info.sh script
+ http://www.alsa-project.org/alsa-info.sh
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
deleted file mode 100644
index fc53ccd9a629..000000000000
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ /dev/null
@@ -1,2330 +0,0 @@
-
- Advanced Linux Sound Architecture - Driver
- ==========================================
- Configuration guide
-
-
-Kernel Configuration
-====================
-
-To enable ALSA support you need at least to build the kernel with
-primary sound card support (CONFIG_SOUND). Since ALSA can emulate OSS,
-you don't have to choose any of the OSS modules.
-
-Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
-PCM supports if you want to run OSS applications with ALSA.
-
-If you want to support the WaveTable functionality on cards such as
-SB Live! then you need to enable "Sequencer support"
-(CONFIG_SND_SEQUENCER).
-
-To make ALSA debug messages more verbose, enable the "Verbose printk"
-and "Debug" options. To check for memory leaks, turn on "Debug memory"
-too. "Debug detection" will add checks for the detection of cards.
-
-Please note that all the ALSA ISA drivers support the Linux isapnp API
-(if the card supports ISA PnP). You don't need to configure the cards
-using isapnptools.
-
-
-Creating ALSA devices
-=====================
-
-This depends on your distribution, but normally you use the /dev/MAKEDEV
-script to create the necessary device nodes. On some systems you use a
-script named 'snddevices'.
-
-
-Module parameters
-=================
-
-The user can load modules with options. If the module supports more than
-one card and you have more than one card of the same type then you can
-specify multiple values for the option separated by commas.
-
-Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-
- Module snd
- ----------
-
- The core ALSA module. It is used by all ALSA card drivers.
- It takes the following options which have global effects.
-
- major - major number for sound driver
- - Default: 116
- cards_limit
- - limiting card index for auto-loading (1-8)
- - Default: 1
- - For auto-loading more than one card, specify this
- option together with snd-card-X aliases.
- slots - Reserve the slot index for the given driver.
- This option takes multiple strings.
- See "Module Autoloading Support" section for details.
- debug - Specifies the debug message level
- (0 = disable debug prints, 1 = normal debug messages,
- 2 = verbose debug messages)
- This option appears only when CONFIG_SND_DEBUG=y.
- This option can be dynamically changed via sysfs
- /sys/modules/snd/parameters/debug file.
-
- Module snd-pcm-oss
- ------------------
-
- The PCM OSS emulation module.
- This module takes options which change the mapping of devices.
-
- dsp_map - PCM device number maps assigned to the 1st OSS device.
- - Default: 0
- adsp_map - PCM device number maps assigned to the 2st OSS device.
- - Default: 1
- nonblock_open
- - Don't block opening busy PCM devices. Default: 1
-
- For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
- the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped
- to PCM #0 of the card #0.
- For changing the second or later card, specify the option with
- commas, such like "dsp_map=0,1".
-
- nonblock_open option is used to change the behavior of the PCM
- regarding opening the device. When this option is non-zero,
- opening a busy OSS PCM device won't be blocked but return
- immediately with EAGAIN (just like O_NONBLOCK flag).
-
- Module snd-rawmidi
- ------------------
-
- This module takes options which change the mapping of devices.
- similar to those of the snd-pcm-oss module.
-
- midi_map - MIDI device number maps assigned to the 1st OSS device.
- - Default: 0
- amidi_map - MIDI device number maps assigned to the 2st OSS device.
- - Default: 1
-
- Common parameters for top sound card modules
- --------------------------------------------
-
- Each of top level sound card module takes the following options.
-
- index - index (slot #) of sound card
- - Values: 0 through 31 or negative
- - If nonnegative, assign that index number
- - if negative, interpret as a bitmask of permissible
- indices; the first free permitted index is assigned
- - Default: -1
- id - card ID (identifier or name)
- - Can be up to 15 characters long
- - Default: the card type
- - A directory by this name is created under /proc/asound/
- containing information about the card
- - This ID can be used instead of the index number in
- identifying the card
- enable - enable card
- - Default: enabled, for PCI and ISA PnP cards
-
- Module snd-adlib
- ----------------
-
- Module for AdLib FM cards.
-
- port - port # for OPL chip
-
- This module supports multiple cards. It does not support autoprobe, so
- the port must be specified. For actual AdLib FM cards it will be 0x388.
- Note that this card does not have PCM support and no mixer; only FM
- synthesis.
-
- Make sure you have "sbiload" from the alsa-tools package available and,
- after loading the module, find out the assigned ALSA sequencer port
- number through "sbiload -l". Example output:
-
- Port Client name Port name
- 64:0 OPL2 FM synth OPL2 FM Port
-
- Load the std.sb and drums.sb patches also supplied by sbiload:
-
- sbiload -p 64:0 std.sb drums.sb
-
- If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
- instead. To have the card produce sound, use aplaymidi from alsa-utils:
-
- aplaymidi -p 64:0 foo.mid
-
- Module snd-ad1816a
- ------------------
-
- Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
-
- clockfreq - Clock frequency for AD1816A chip (default = 0, 33000Hz)
-
- This module supports multiple cards, autoprobe and PnP.
-
- Module snd-ad1848
- -----------------
-
- Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
-
- port - port # for AD1848 chip
- irq - IRQ # for AD1848 chip
- dma1 - DMA # for AD1848 chip (0,1,3)
-
- This module supports multiple cards. It does not support autoprobe
- thus main port must be specified!!! Other ports are optional.
-
- The power-management is supported.
-
- Module snd-ad1889
- -----------------
-
- Module for Analog Devices AD1889 chips.
-
- ac97_quirk - AC'97 workaround for strange hardware
- See the description of intel8x0 module for details.
-
- This module supports multiple cards.
-
- Module snd-ali5451
- ------------------
-
- Module for ALi M5451 PCI chip.
-
- pcm_channels - Number of hardware channels assigned for PCM
- spdif - Support SPDIF I/O
- - Default: disabled
-
- This module supports one chip and autoprobe.
-
- The power-management is supported.
-
- Module snd-als100
- -----------------
-
- Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
-
- This module supports multiple cards, autoprobe and PnP.
-
- The power-management is supported.
-
- Module snd-als300
- -----------------
-
- Module for Avance Logic ALS300 and ALS300+
-
- This module supports multiple cards.
-
- The power-management is supported.
-
- Module snd-als4000
- ------------------
-
- Module for sound cards based on Avance Logic ALS4000 PCI chip.
-
- joystick_port - port # for legacy joystick support.
- 0 = disabled (default), 1 = auto-detect
-
- This module supports multiple cards, autoprobe and PnP.
-
- The power-management is supported.
-
- Module snd-asihpi
- -----------------
-
- Module for AudioScience ASI soundcards
-
- enable_hpi_hwdep - enable HPI hwdep for AudioScience soundcard
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-atiixp
- -----------------
-
- Module for ATI IXP 150/200/250/400 AC97 controllers.
-
- ac97_clock - AC'97 clock (default = 48000)
- ac97_quirk - AC'97 workaround for strange hardware
- See "AC97 Quirk Option" section below.
- ac97_codec - Workaround to specify which AC'97 codec
- instead of probing. If this works for you
- file a bug with your `lspci -vn` output.
- -2 -- Force probing.
- -1 -- Default behavior.
- 0-2 -- Use the specified codec.
- spdif_aclink - S/PDIF transfer over AC-link (default = 1)
-
- This module supports one card and autoprobe.
-
- ATI IXP has two different methods to control SPDIF output. One is
- over AC-link and another is over the "direct" SPDIF output. The
- implementation depends on the motherboard, and you'll need to
- choose the correct one via spdif_aclink module option.
-
- The power-management is supported.
-
- Module snd-atiixp-modem
- -----------------------
-
- Module for ATI IXP 150/200/250 AC97 modem controllers.
-
- This module supports one card and autoprobe.
-
- Note: The default index value of this module is -2, i.e. the first
- slot is excluded.
-
- The power-management is supported.
-
- Module snd-au8810, snd-au8820, snd-au8830
- -----------------------------------------
-
- Module for Aureal Vortex, Vortex2 and Advantage device.
-
- pcifix - Control PCI workarounds
- 0 = Disable all workarounds
- 1 = Force the PCI latency of the Aureal card to 0xff
- 2 = Force the Extend PCI#2 Internal Master for Efficient
- Handling of Dummy Requests on the VIA KT133 AGP Bridge
- 3 = Force both settings
- 255 = Autodetect what is required (default)
-
- This module supports all ADB PCM channels, ac97 mixer, SPDIF, hardware
- EQ, mpu401, gameport. A3D and wavetable support are still in development.
- Development and reverse engineering work is being coordinated at
- http://savannah.nongnu.org/projects/openvortex/
- SPDIF output has a copy of the AC97 codec output, unless you use the
- "spdif" pcm device, which allows raw data passthru.
- The hardware EQ hardware and SPDIF is only present in the Vortex2 and
- Advantage.
-
- Note: Some ALSA mixer applications don't handle the SPDIF sample rate
- control correctly. If you have problems regarding this, try
- another ALSA compliant mixer (alsamixer works).
-
- Module snd-azt1605
- ------------------
-
- Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
- chipset.
-
- port - port # for BASE (0x220,0x240,0x260,0x280)
- wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
- irq - IRQ # for WSS (7,9,10,11)
- dma1 - DMA # for WSS playback (0,1,3)
- dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
- mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
- mpu_irq - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
- fm_port - port # for OPL3 (0x388), -1 = disabled (default)
-
- This module supports multiple cards. It does not support autoprobe: port,
- wss_port, irq and dma1 have to be specified. The other values are
- optional.
-
- "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
- or the value stored in the card's EEPROM for cards that have an EEPROM and
- their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
- be chosen freely from the options enumerated above.
-
- If dma2 is specified and different from dma1, the card will operate in
- full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
- enable capture since only channels 0 and 1 are available for capture.
-
- Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
- mpu_port=0x330 mpu_irq=9 fm_port=0x388".
-
- Whatever IRQ and DMA channels you pick, be sure to reserve them for
- legacy ISA in your BIOS.
-
- Module snd-azt2316
- ------------------
-
- Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
- chipset.
-
- port - port # for BASE (0x220,0x240,0x260,0x280)
- wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
- irq - IRQ # for WSS (7,9,10,11)
- dma1 - DMA # for WSS playback (0,1,3)
- dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
- mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
- mpu_irq - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
- fm_port - port # for OPL3 (0x388), -1 = disabled (default)
-
- This module supports multiple cards. It does not support autoprobe: port,
- wss_port, irq and dma1 have to be specified. The other values are
- optional.
-
- "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
- or the value stored in the card's EEPROM for cards that have an EEPROM and
- their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
- be chosen freely from the options enumerated above.
-
- If dma2 is specified and different from dma1, the card will operate in
- full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
- enable capture since only channels 0 and 1 are available for capture.
-
- Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
- mpu_port=0x330 mpu_irq=9 fm_port=0x388".
-
- Whatever IRQ and DMA channels you pick, be sure to reserve them for
- legacy ISA in your BIOS.
-
- Module snd-aw2
- --------------
-
- Module for Audiowerk2 sound card
-
- This module supports multiple cards.
-
- Module snd-azt2320
- ------------------
-
- Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
-
- This module supports multiple cards, PnP and autoprobe.
-
- The power-management is supported.
-
- Module snd-azt3328
- ------------------
-
- Module for sound cards based on Aztech AZF3328 PCI chip.
-
- joystick - Enable joystick (default off)
-
- This module supports multiple cards.
-
- Module snd-bt87x
- ----------------
-
- Module for video cards based on Bt87x chips.
-
- digital_rate - Override the default digital rate (Hz)
- load_all - Load the driver even if the card model isn't known
-
- This module supports multiple cards.
-
- Note: The default index value of this module is -2, i.e. the first
- slot is excluded.
-
- Module snd-ca0106
- -----------------
-
- Module for Creative Audigy LS and SB Live 24bit
-
- This module supports multiple cards.
-
-
- Module snd-cmi8330
- ------------------
-
- Module for sound cards based on C-Media CMI8330 ISA chips.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- wssport - port # for CMI8330 chip (WSS)
- wssirq - IRQ # for CMI8330 chip (WSS)
- wssdma - first DMA # for CMI8330 chip (WSS)
- sbport - port # for CMI8330 chip (SB16)
- sbirq - IRQ # for CMI8330 chip (SB16)
- sbdma8 - 8bit DMA # for CMI8330 chip (SB16)
- sbdma16 - 16bit DMA # for CMI8330 chip (SB16)
- fmport - (optional) OPL3 I/O port
- mpuport - (optional) MPU401 I/O port
- mpuirq - (optional) MPU401 irq #
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-cmipci
- -----------------
-
- Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
-
- mpu_port - port address of MIDI interface (8338 only):
- 0x300,0x310,0x320,0x330 = legacy port,
- 0 = disable (default)
- fm_port - port address of OPL-3 FM synthesizer (8x38 only):
- 0x388 = legacy port,
- 1 = integrated PCI port (default on 8738),
- 0 = disable
- soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only)
- (default = 1)
- joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
-
- This module supports autoprobe and multiple cards.
-
- The power-management is supported.
-
- Module snd-cs4231
- -----------------
-
- Module for sound cards based on CS4231 ISA chips.
-
- port - port # for CS4231 chip
- mpu_port - port # for MPU-401 UART (optional), -1 = disable
- irq - IRQ # for CS4231 chip
- mpu_irq - IRQ # for MPU-401 UART
- dma1 - first DMA # for CS4231 chip
- dma2 - second DMA # for CS4231 chip
-
- This module supports multiple cards. This module does not support autoprobe
- thus main port must be specified!!! Other ports are optional.
-
- The power-management is supported.
-
- Module snd-cs4236
- -----------------
-
- Module for sound cards based on CS4232/CS4232A,
- CS4235/CS4236/CS4236B/CS4237B/
- CS4238B/CS4239 ISA chips.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for CS4236 chip (PnP setup - 0x534)
- cport - control port # for CS4236 chip (PnP setup - 0x120,0x210,0xf00)
- mpu_port - port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
- fm_port - FM port # for CS4236 chip (PnP setup - 0x388), -1 = disable
- irq - IRQ # for CS4236 chip (5,7,9,11,12,15)
- mpu_irq - IRQ # for MPU-401 UART (9,11,12,15)
- dma1 - first DMA # for CS4236 chip (0,1,3)
- dma2 - second DMA # for CS4236 chip (0,1,3), -1 = disable
-
- This module supports multiple cards. This module does not support autoprobe
- (if ISA PnP is not used) thus main port and control port must be
- specified!!! Other ports are optional.
-
- The power-management is supported.
-
- This module is aliased as snd-cs4232 since it provides the old
- snd-cs4232 functionality, too.
-
- Module snd-cs4281
- -----------------
-
- Module for Cirrus Logic CS4281 soundchip.
-
- dual_codec - Secondary codec ID (0 = disable, default)
-
- This module supports multiple cards.
-
- The power-management is supported.
-
- Module snd-cs46xx
- -----------------
-
- Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
- CS4624/CS4630/CS4280 PCI chips.
-
- external_amp - Force to enable external amplifier.
- thinkpad - Force to enable Thinkpad's CLKRUN control.
- mmap_valid - Support OSS mmap mode (default = 0).
-
- This module supports multiple cards and autoprobe.
- Usually external amp and CLKRUN controls are detected automatically
- from PCI sub vendor/device ids. If they don't work, give the options
- above explicitly.
-
- The power-management is supported.
-
- Module snd-cs5530
- _________________
-
- Module for Cyrix/NatSemi Geode 5530 chip.
-
- Module snd-cs5535audio
- ----------------------
-
- Module for multifunction CS5535 companion PCI device
-
- The power-management is supported.
-
- Module snd-ctxfi
- ----------------
-
- Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
- * Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
- * Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
- * Creative Sound Blaster X-Fi Titanium Professional Audio
- * Creative Sound Blaster X-Fi Titanium
- * Creative Sound Blaster X-Fi Elite Pro
- * Creative Sound Blaster X-Fi Platinum
- * Creative Sound Blaster X-Fi Fatal1ty
- * Creative Sound Blaster X-Fi XtremeGamer
- * Creative Sound Blaster X-Fi XtremeMusic
-
- reference_rate - reference sample rate, 44100 or 48000 (default)
- multiple - multiple to ref. sample rate, 1 or 2 (default)
- subsystem - override the PCI SSID for probing; the value
- consists of SSVID << 16 | SSDID. The default is
- zero, which means no override.
-
- This module supports multiple cards.
-
- Module snd-darla20
- ------------------
-
- Module for Echoaudio Darla20
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-darla24
- ------------------
-
- Module for Echoaudio Darla24
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-dt019x
- -----------------
-
- Module for Diamond Technologies DT-019X / Avance Logic ALS-007 (PnP
- only)
-
- This module supports multiple cards. This module is enabled only with
- ISA PnP support.
-
- The power-management is supported.
-
- Module snd-dummy
- ----------------
-
- Module for the dummy sound card. This "card" doesn't do any output
- or input, but you may use this module for any application which
- requires a sound card (like RealPlayer).
-
- pcm_devs - Number of PCM devices assigned to each card
- (default = 1, up to 4)
- pcm_substreams - Number of PCM substreams assigned to each PCM
- (default = 8, up to 128)
- hrtimer - Use hrtimer (=1, default) or system timer (=0)
- fake_buffer - Fake buffer allocations (default = 1)
-
- When multiple PCM devices are created, snd-dummy gives different
- behavior to each PCM device:
- 0 = interleaved with mmap support
- 1 = non-interleaved with mmap support
- 2 = interleaved without mmap
- 3 = non-interleaved without mmap
-
- As default, snd-dummy drivers doesn't allocate the real buffers
- but either ignores read/write or mmap a single dummy page to all
- buffer pages, in order to save the resources. If your apps need
- the read/ written buffer data to be consistent, pass fake_buffer=0
- option.
-
- The power-management is supported.
-
- Module snd-echo3g
- -----------------
-
- Module for Echoaudio 3G cards (Gina3G/Layla3G)
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-emu10k1
- ------------------
-
- Module for EMU10K1/EMU10k2 based PCI sound cards.
- * Sound Blaster Live!
- * Sound Blaster PCI 512
- * Emu APS (partially supported)
- * Sound Blaster Audigy
-
- extin - bitmap of available external inputs for FX8010 (see bellow)
- extout - bitmap of available external outputs for FX8010 (see bellow)
- seq_ports - allocated sequencer ports (4 by default)
- max_synth_voices - limit of voices used for wavetable (64 by default)
- max_buffer_size - specifies the maximum size of wavetable/pcm buffers
- given in MB unit. Default value is 128.
- enable_ir - enable IR
-
- This module supports multiple cards and autoprobe.
-
- Input & Output configurations [extin/extout]
- * Creative Card wo/Digital out [0x0003/0x1f03]
- * Creative Card w/Digital out [0x0003/0x1f0f]
- * Creative Card w/Digital CD in [0x000f/0x1f0f]
- * Creative Card wo/Digital out + LiveDrive [0x3fc3/0x1fc3]
- * Creative Card w/Digital out + LiveDrive [0x3fc3/0x1fcf]
- * Creative Card w/Digital CD in + LiveDrive [0x3fcf/0x1fcf]
- * Creative Card wo/Digital out + Digital I/O 2 [0x0fc3/0x1f0f]
- * Creative Card w/Digital out + Digital I/O 2 [0x0fc3/0x1f0f]
- * Creative Card w/Digital CD in + Digital I/O 2 [0x0fcf/0x1f0f]
- * Creative Card 5.1/w Digital out + LiveDrive [0x3fc3/0x1fff]
- * Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff]
- * Creative Card all ins and outs [0x3fff/0x7fff]
-
- The power-management is supported.
-
- Module snd-emu10k1x
- -------------------
-
- Module for Creative Emu10k1X (SB Live Dell OEM version)
-
- This module supports multiple cards.
-
- Module snd-ens1370
- ------------------
-
- Module for Ensoniq AudioPCI ES1370 PCI sound cards.
- * SoundBlaster PCI 64
- * SoundBlaster PCI 128
-
- joystick - Enable joystick (default off)
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-ens1371
- ------------------
-
- Module for Ensoniq AudioPCI ES1371 PCI sound cards.
- * SoundBlaster PCI 64
- * SoundBlaster PCI 128
- * SoundBlaster Vibra PCI
-
- joystick_port - port # for joystick (0x200,0x208,0x210,0x218),
- 0 = disable (default), 1 = auto-detect
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-es1688
- -----------------
-
- Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
- mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
- fm_port - port # for OPL3 (option; share the same port as default)
-
- with isapnp=0, the following additional options are available:
- port - port # for ES-1688 chip (0x220,0x240,0x260)
- irq - IRQ # for ES-1688 chip (5,7,9,10)
- dma8 - DMA # for ES-1688 chip (0,1,3)
-
- This module supports multiple cards and autoprobe (without MPU-401 port)
- and PnP with the ES968 chip.
-
- Module snd-es18xx
- -----------------
-
- Module for ESS AudioDrive ES-18xx sound cards.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for ES-18xx chip (0x220,0x240,0x260)
- mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
- fm_port - port # for FM (optional, not used)
- irq - IRQ # for ES-18xx chip (5,7,9,10)
- dma1 - first DMA # for ES-18xx chip (0,1,3)
- dma2 - first DMA # for ES-18xx chip (0,1,3)
-
- This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
- port if native ISA PnP routines are not used).
- When dma2 is equal with dma1, the driver works as half-duplex.
-
- The power-management is supported.
-
- Module snd-es1938
- -----------------
-
- Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-es1968
- -----------------
-
- Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
-
- total_bufsize - total buffer size in kB (1-4096kB)
- pcm_substreams_p - playback channels (1-8, default=2)
- pcm_substreams_c - capture channels (1-8, default=0)
- clock - clock (0 = auto-detection)
- use_pm - support the power-management (0 = off, 1 = on,
- 2 = auto (default))
- enable_mpu - enable MPU401 (0 = off, 1 = on, 2 = auto (default))
- joystick - enable joystick (default off)
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-fm801
- ----------------
-
- Module for ForteMedia FM801 based PCI sound cards.
-
- tea575x_tuner - Enable TEA575x tuner
- - 1 = MediaForte 256-PCS
- - 2 = MediaForte 256-PCPR
- - 3 = MediaForte 64-PCR
- - High 16-bits are video (radio) device number + 1
- - example: 0x10002 (MediaForte 256-PCPR, device 1)
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-gina20
- -----------------
-
- Module for Echoaudio Gina20
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-gina24
- -----------------
-
- Module for Echoaudio Gina24
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-gusclassic
- ---------------------
-
- Module for Gravis UltraSound Classic sound card.
-
- port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
- irq - IRQ # for GF1 chip (3,5,9,11,12,15)
- dma1 - DMA # for GF1 chip (1,3,5,6,7)
- dma2 - DMA # for GF1 chip (1,3,5,6,7,-1=disable)
- joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
- voices - GF1 voices limit (14-32)
- pcm_voices - reserved PCM voices
-
- This module supports multiple cards and autoprobe.
-
- Module snd-gusextreme
- ---------------------
-
- Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
-
- port - port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
- gf1_port - port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
- mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable
- irq - IRQ # for ES-1688 chip (5,7,9,10)
- gf1_irq - IRQ # for GF1 chip (3,5,9,11,12,15)
- mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
- dma8 - DMA # for ES-1688 chip (0,1,3)
- dma1 - DMA # for GF1 chip (1,3,5,6,7)
- joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
- voices - GF1 voices limit (14-32)
- pcm_voices - reserved PCM voices
-
- This module supports multiple cards and autoprobe (without MPU-401 port).
-
- Module snd-gusmax
- -----------------
-
- Module for Gravis UltraSound MAX sound card.
-
- port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
- irq - IRQ # for GF1 chip (3,5,9,11,12,15)
- dma1 - DMA # for GF1 chip (1,3,5,6,7)
- dma2 - DMA # for GF1 chip (1,3,5,6,7,-1=disable)
- joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
- voices - GF1 voices limit (14-32)
- pcm_voices - reserved PCM voices
-
- This module supports multiple cards and autoprobe.
-
- Module snd-hda-intel
- --------------------
-
- Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10,
- PCH, SCH),
- ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620,
- RV630, RV635, RV670, RV770,
- VIA VT8251/VT8237A,
- SIS966, ULI M5461
-
- [Multiple options for each card instance]
- model - force the model name
- position_fix - Fix DMA pointer
- -1 = system default: choose appropriate one per controller
- hardware
- 0 = auto: falls back to LPIB when POSBUF doesn't work
- 1 = use LPIB
- 2 = POSBUF: use position buffer
- 3 = VIACOMBO: VIA-specific workaround for capture
- 4 = COMBO: use LPIB for playback, auto for capture stream
- probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
- When the bit 8 (0x100) is set, the lower 8 bits are used
- as the "fixed" codec slots; i.e. the driver probes the
- slots regardless what hardware reports back
- probe_only - Only probing and no codec initialization (default=off);
- Useful to check the initial codec status for debugging
- bdl_pos_adj - Specifies the DMA IRQ timing delay in samples.
- Passing -1 will make the driver to choose the appropriate
- value based on the controller chip.
- patch - Specifies the early "patch" files to modify the HD-audio
- setup before initializing the codecs. This option is
- available only when CONFIG_SND_HDA_PATCH_LOADER=y is set.
- See HD-Audio.txt for details.
- beep_mode - Selects the beep registration mode (0=off, 1=on); default
- value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig.
-
- [Single (global) options]
- single_cmd - Use single immediate commands to communicate with
- codecs (for debugging only)
- enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
- power_save - Automatic power-saving timeout (in second, 0 =
- disable)
- power_save_controller - Reset HD-audio controller in power-saving mode
- (default = on)
- align_buffer_size - Force rounding of buffer/period sizes to multiples
- of 128 bytes. This is more efficient in terms of memory
- access but isn't required by the HDA spec and prevents
- users from specifying exact period/buffer sizes.
- (default = on)
- snoop - Enable/disable snooping (default = on)
-
- This module supports multiple cards and autoprobe.
-
- See Documentation/sound/alsa/HD-Audio.txt for more details about
- HD-audio driver.
-
- Each codec may have a model table for different configurations.
- If your machine isn't listed there, the default (usually minimal)
- configuration is set up. You can pass "model=<name>" option to
- specify a certain model in such a case. There are different
- models depending on the codec chip. The list of available models
- is found in HD-Audio-Models.txt
-
- The model name "generic" is treated as a special case. When this
- model is given, the driver uses the generic codec parser without
- "codec-patch". It's sometimes good for testing and debugging.
-
- If the default configuration doesn't work and one of the above
- matches with your device, report it together with alsa-info.sh
- output (with --no-upload option) to kernel bugzilla or alsa-devel
- ML (see the section "Links and Addresses").
-
- power_save and power_save_controller options are for power-saving
- mode. See powersave.txt for details.
-
- Note 2: If you get click noises on output, try the module option
- position_fix=1 or 2. position_fix=1 will use the SD_LPIB
- register value without FIFO size correction as the current
- DMA pointer. position_fix=2 will make the driver to use
- the position buffer instead of reading SD_LPIB register.
- (Usually SD_LPIB register is more accurate than the
- position buffer.)
-
- position_fix=3 is specific to VIA devices. The position
- of the capture stream is checked from both LPIB and POSBUF
- values. position_fix=4 is a combination mode, using LPIB
- for playback and POSBUF for capture.
-
- NB: If you get many "azx_get_response timeout" messages at
- loading, it's likely a problem of interrupts (e.g. ACPI irq
- routing). Try to boot with options like "pci=noacpi". Also, you
- can try "single_cmd=1" module option. This will switch the
- communication method between HDA controller and codecs to the
- single immediate commands instead of CORB/RIRB. Basically, the
- single command mode is provided only for BIOS, and you won't get
- unsolicited events, too. But, at least, this works independently
- from the irq. Remember this is a last resort, and should be
- avoided as much as possible...
-
- MORE NOTES ON "azx_get_response timeout" PROBLEMS:
- On some hardware, you may need to add a proper probe_mask option
- to avoid the "azx_get_response timeout" problem above, instead.
- This occurs when the access to non-existing or non-working codec slot
- (likely a modem one) causes a stall of the communication via HD-audio
- bus. You can see which codec slots are probed by enabling
- CONFIG_SND_DEBUG_VERBOSE, or simply from the file name of the codec
- proc files. Then limit the slots to probe by probe_mask option.
- For example, probe_mask=1 means to probe only the first slot, and
- probe_mask=4 means only the third slot.
-
- The power-management is supported.
-
- Module snd-hdsp
- ---------------
-
- Module for RME Hammerfall DSP audio interface(s)
-
- This module supports multiple cards.
-
- Note: The firmware data can be automatically loaded via hotplug
- when CONFIG_FW_LOADER is set. Otherwise, you need to load
- the firmware via hdsploader utility included in alsa-tools
- package.
- The firmware data is found in alsa-firmware package.
-
- Note: snd-page-alloc module does the job which snd-hammerfall-mem
- module did formerly. It will allocate the buffers in advance
- when any HDSP cards are found. To make the buffer
- allocation sure, load snd-page-alloc module in the early
- stage of boot sequence. See "Early Buffer Allocation"
- section.
-
- Module snd-hdspm
- ----------------
-
- Module for RME HDSP MADI board.
-
- precise_ptr - Enable precise pointer, or disable.
- line_outs_monitor - Send playback streams to analog outs by default.
- enable_monitor - Enable Analog Out on Channel 63/64 by default.
-
- See hdspm.txt for details.
-
- Module snd-ice1712
- ------------------
-
- Module for Envy24 (ICE1712) based PCI sound cards.
- * MidiMan M Audio Delta 1010
- * MidiMan M Audio Delta 1010LT
- * MidiMan M Audio Delta DiO 2496
- * MidiMan M Audio Delta 66
- * MidiMan M Audio Delta 44
- * MidiMan M Audio Delta 410
- * MidiMan M Audio Audiophile 2496
- * TerraTec EWS 88MT
- * TerraTec EWS 88D
- * TerraTec EWX 24/96
- * TerraTec DMX 6Fire
- * TerraTec Phase 88
- * Hoontech SoundTrack DSP 24
- * Hoontech SoundTrack DSP 24 Value
- * Hoontech SoundTrack DSP 24 Media 7.1
- * Event Electronics, EZ8
- * Digigram VX442
- * Lionstracs, Mediastaton
- * Terrasoniq TS 88
-
- model - Use the given board model, one of the following:
- delta1010, dio2496, delta66, delta44, audiophile, delta410,
- delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
- dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
- phase88, mediastation
- omni - Omni I/O support for MidiMan M-Audio Delta44/66
- cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transceiver)
- in msec resolution, default value is 500 (0.5 sec)
-
- This module supports multiple cards and autoprobe. Note: The consumer part
- is not used with all Envy24 based cards (for example in the MidiMan Delta
- serie).
-
- Note: The supported board is detected by reading EEPROM or PCI
- SSID (if EEPROM isn't available). You can override the
- model by passing "model" module option in case that the
- driver isn't configured properly or you want to try another
- type for testing.
-
- Module snd-ice1724
- ------------------
-
- Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
- * MidiMan M Audio Revolution 5.1
- * MidiMan M Audio Revolution 7.1
- * MidiMan M Audio Audiophile 192
- * AMP Ltd AUDIO2000
- * TerraTec Aureon 5.1 Sky
- * TerraTec Aureon 7.1 Space
- * TerraTec Aureon 7.1 Universe
- * TerraTec Phase 22
- * TerraTec Phase 28
- * AudioTrak Prodigy 7.1
- * AudioTrak Prodigy 7.1 LT
- * AudioTrak Prodigy 7.1 XT
- * AudioTrak Prodigy 7.1 HIFI
- * AudioTrak Prodigy 7.1 HD2
- * AudioTrak Prodigy 192
- * Pontis MS300
- * Albatron K8X800 Pro II
- * Chaintech ZNF3-150
- * Chaintech ZNF3-250
- * Chaintech 9CJS
- * Chaintech AV-710
- * Shuttle SN25P
- * Onkyo SE-90PCI
- * Onkyo SE-200PCI
- * ESI Juli@
- * ESI Maya44
- * Hercules Fortissimo IV
- * EGO-SYS WaveTerminal 192M
-
- model - Use the given board model, one of the following:
- revo51, revo71, amp2000, prodigy71, prodigy71lt,
- prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
- juli, aureon51, aureon71, universe, ap192, k8x800,
- phase22, phase28, ms300, av710, se200pci, se90pci,
- fortissimo4, sn25p, WT192M, maya44
-
- This module supports multiple cards and autoprobe.
-
- Note: The supported board is detected by reading EEPROM or PCI
- SSID (if EEPROM isn't available). You can override the
- model by passing "model" module option in case that the
- driver isn't configured properly or you want to try another
- type for testing.
-
- Module snd-indigo
- -----------------
-
- Module for Echoaudio Indigo
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-indigodj
- -------------------
-
- Module for Echoaudio Indigo DJ
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-indigoio
- -------------------
-
- Module for Echoaudio Indigo IO
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-intel8x0
- -------------------
-
- Module for AC'97 motherboards from Intel and compatibles.
- * Intel i810/810E, i815, i820, i830, i84x, MX440
- ICH5, ICH6, ICH7, 6300ESB, ESB2
- * SiS 7012 (SiS 735)
- * NVidia NForce, NForce2, NForce3, MCP04, CK804
- CK8, CK8S, MCP501
- * AMD AMD768, AMD8111
- * ALi m5455
-
- ac97_clock - AC'97 codec clock base (0 = auto-detect)
- ac97_quirk - AC'97 workaround for strange hardware
- See "AC97 Quirk Option" section below.
- buggy_irq - Enable workaround for buggy interrupts on some
- motherboards (default yes on nForce chips,
- otherwise off)
- buggy_semaphore - Enable workaround for hardware with buggy
- semaphores (e.g. on some ASUS laptops)
- (default off)
- spdif_aclink - Use S/PDIF over AC-link instead of direct connection
- from the controller chip
- (0 = off, 1 = on, -1 = default)
-
- This module supports one chip and autoprobe.
-
- Note: the latest driver supports auto-detection of chip clock.
- if you still encounter too fast playback, specify the clock
- explicitly via the module option "ac97_clock=41194".
-
- Joystick/MIDI ports are not supported by this driver. If your
- motherboard has these devices, use the ns558 or snd-mpu401
- modules, respectively.
-
- The power-management is supported.
-
- Module snd-intel8x0m
- --------------------
-
- Module for Intel ICH (i8x0) chipset MC97 modems.
- * Intel i810/810E, i815, i820, i830, i84x, MX440
- ICH5, ICH6, ICH7
- * SiS 7013 (SiS 735)
- * NVidia NForce, NForce2, NForce2s, NForce3
- * AMD AMD8111
- * ALi m5455
-
- ac97_clock - AC'97 codec clock base (0 = auto-detect)
-
- This module supports one card and autoprobe.
-
- Note: The default index value of this module is -2, i.e. the first
- slot is excluded.
-
- The power-management is supported.
-
- Module snd-interwave
- --------------------
-
- Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
- and other sound cards based on AMD InterWave (tm) chip.
-
- joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
- midi - 1 = MIDI UART enable, 0 = MIDI UART disable (default)
- pcm_voices - reserved PCM voices for the synthesizer (default 2)
- effect - 1 = InterWave effects enable (default 0);
- requires 8 voices
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
- irq - IRQ # for InterWave chip (3,5,9,11,12,15)
- dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
- dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
-
- This module supports multiple cards, autoprobe and ISA PnP.
-
- Module snd-interwave-stb
- ------------------------
-
- Module for UltraSound 32-Pro (sound card from STB used by Compaq)
- and other sound cards based on AMD InterWave (tm) chip with TEA6330T
- circuit for extended control of bass, treble and master volume.
-
- joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
- midi - 1 = MIDI UART enable, 0 = MIDI UART disable (default)
- pcm_voices - reserved PCM voices for the synthesizer (default 2)
- effect - 1 = InterWave effects enable (default 0);
- requires 8 voices
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
- port_tc - tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
- irq - IRQ # for InterWave chip (3,5,9,11,12,15)
- dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
- dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
-
- This module supports multiple cards, autoprobe and ISA PnP.
-
- Module snd-jazz16
- -------------------
-
- Module for Media Vision Jazz16 chipset. The chipset consists of 3 chips:
- MVD1216 + MVA416 + MVA514.
-
- port - port # for SB DSP chip (0x210,0x220,0x230,0x240,0x250,0x260)
- irq - IRQ # for SB DSP chip (3,5,7,9,10,15)
- dma8 - DMA # for SB DSP chip (1,3)
- dma16 - DMA # for SB DSP chip (5,7)
- mpu_port - MPU-401 port # (0x300,0x310,0x320,0x330)
- mpu_irq - MPU-401 irq # (2,3,5,7)
-
- This module supports multiple cards.
-
- Module snd-korg1212
- -------------------
-
- Module for Korg 1212 IO PCI card
-
- This module supports multiple cards.
-
- Module snd-layla20
- ------------------
-
- Module for Echoaudio Layla20
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-layla24
- ------------------
-
- Module for Echoaudio Layla24
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-lola
- ---------------
-
- Module for Digigram Lola PCI-e boards
-
- This module supports multiple cards.
-
- Module snd-lx6464es
- -------------------
-
- Module for Digigram LX6464ES boards
-
- This module supports multiple cards.
-
- Module snd-maestro3
- -------------------
-
- Module for Allegro/Maestro3 chips
-
- external_amp - enable external amp (enabled by default)
- amp_gpio - GPIO pin number for external amp (0-15) or
- -1 for default pin (8 for allegro, 1 for
- others)
-
- This module supports autoprobe and multiple chips.
-
- Note: the binding of amplifier is dependent on hardware.
- If there is no sound even though all channels are unmuted, try to
- specify other gpio connection via amp_gpio option.
- For example, a Panasonic notebook might need "amp_gpio=0x0d"
- option.
-
- The power-management is supported.
-
- Module snd-mia
- ---------------
-
- Module for Echoaudio Mia
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-miro
- ---------------
-
- Module for Miro soundcards: miroSOUND PCM 1 pro,
- miroSOUND PCM 12,
- miroSOUND PCM 20 Radio.
-
- port - Port # (0x530,0x604,0xe80,0xf40)
- irq - IRQ # (5,7,9,10,11)
- dma1 - 1st dma # (0,1,3)
- dma2 - 2nd dma # (0,1)
- mpu_port - MPU-401 port # (0x300,0x310,0x320,0x330)
- mpu_irq - MPU-401 irq # (5,7,9,10)
- fm_port - FM Port # (0x388)
- wss - enable WSS mode
- ide - enable onboard ide support
-
- Module snd-mixart
- -----------------
-
- Module for Digigram miXart8 sound cards.
-
- This module supports multiple cards.
- Note: One miXart8 board will be represented as 4 alsa cards.
- See MIXART.txt for details.
-
- When the driver is compiled as a module and the hotplug firmware
- is supported, the firmware data is loaded via hotplug automatically.
- Install the necessary firmware files in alsa-firmware package.
- When no hotplug fw loader is available, you need to load the
- firmware via mixartloader utility in alsa-tools package.
-
- Module snd-mona
- ---------------
-
- Module for Echoaudio Mona
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
-
- Module snd-mpu401
- -----------------
-
- Module for MPU-401 UART devices.
-
- port - port number or -1 (disable)
- irq - IRQ number or -1 (disable)
- pnp - PnP detection - 0 = disable, 1 = enable (default)
-
- This module supports multiple devices and PnP.
-
- Module snd-msnd-classic
- -----------------------
-
- Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
- soundcards.
-
- io - Port # for msnd-classic card
- irq - IRQ # for msnd-classic card
- mem - Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
- 0xe0000 or 0xe8000)
- write_ndelay - enable write ndelay (default = 1)
- calibrate_signal - calibrate signal (default = 0)
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- digital - Digital daughterboard present (default = 0)
- cfg - Config port (0x250, 0x260 or 0x270) default = PnP
- reset - Reset all devices
- mpu_io - MPU401 I/O port
- mpu_irq - MPU401 irq#
- ide_io0 - IDE port #0
- ide_io1 - IDE port #1
- ide_irq - IDE irq#
- joystick_io - Joystick I/O port
-
- The driver requires firmware files "turtlebeach/msndinit.bin" and
- "turtlebeach/msndperm.bin" in the proper firmware directory.
-
- See Documentation/sound/oss/MultiSound for important information
- about this driver. Note that it has been discontinued, but the
- Voyetra Turtle Beach knowledge base entry for it is still available
- at
- http://www.turtlebeach.com
-
- Module snd-msnd-pinnacle
- ------------------------
-
- Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
-
- io - Port # for pinnacle/fiji card
- irq - IRQ # for pinnalce/fiji card
- mem - Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
- 0xe0000 or 0xe8000)
- write_ndelay - enable write ndelay (default = 1)
- calibrate_signal - calibrate signal (default = 0)
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- The driver requires firmware files "turtlebeach/pndspini.bin" and
- "turtlebeach/pndsperm.bin" in the proper firmware directory.
-
- Module snd-mtpav
- ----------------
-
- Module for MOTU MidiTimePiece AV multiport MIDI (on the parallel
- port).
-
- port - I/O port # for MTPAV (0x378,0x278, default=0x378)
- irq - IRQ # for MTPAV (7,5, default=7)
- hwports - number of supported hardware ports, default=8.
-
- Module supports only 1 card. This module has no enable option.
-
- Module snd-mts64
- ----------------
-
- Module for Ego Systems (ESI) Miditerminal 4140
-
- This module supports multiple devices.
- Requires parport (CONFIG_PARPORT).
-
- Module snd-nm256
- ----------------
-
- Module for NeoMagic NM256AV/ZX chips
-
- playback_bufsize - max playback frame size in kB (4-128kB)
- capture_bufsize - max capture frame size in kB (4-128kB)
- force_ac97 - 0 or 1 (disabled by default)
- buffer_top - specify buffer top address
- use_cache - 0 or 1 (disabled by default)
- vaio_hack - alias buffer_top=0x25a800
- reset_workaround - enable AC97 RESET workaround for some laptops
- reset_workaround2 - enable extended AC97 RESET workaround for some
- other laptops
-
- This module supports one chip and autoprobe.
-
- The power-management is supported.
-
- Note: on some notebooks the buffer address cannot be detected
- automatically, or causes hang-up during initialization.
- In such a case, specify the buffer top address explicitly via
- the buffer_top option.
- For example,
- Sony F250: buffer_top=0x25a800
- Sony F270: buffer_top=0x272800
- The driver supports only ac97 codec. It's possible to force
- to initialize/use ac97 although it's not detected. In such a
- case, use force_ac97=1 option - but *NO* guarantee whether it
- works!
-
- Note: The NM256 chip can be linked internally with non-AC97
- codecs. This driver supports only the AC97 codec, and won't work
- with machines with other (most likely CS423x or OPL3SAx) chips,
- even though the device is detected in lspci. In such a case, try
- other drivers, e.g. snd-cs4232 or snd-opl3sa2. Some has ISA-PnP
- but some doesn't have ISA PnP. You'll need to specify isapnp=0
- and proper hardware parameters in the case without ISA PnP.
-
- Note: some laptops need a workaround for AC97 RESET. For the
- known hardware like Dell Latitude LS and Sony PCG-F305, this
- workaround is enabled automatically. For other laptops with a
- hard freeze, you can try reset_workaround=1 option.
-
- Note: Dell Latitude CSx laptops have another problem regarding
- AC97 RESET. On these laptops, reset_workaround2 option is
- turned on as default. This option is worth to try if the
- previous reset_workaround option doesn't help.
-
- Note: This driver is really crappy. It's a porting from the
- OSS driver, which is a result of black-magic reverse engineering.
- The detection of codec will fail if the driver is loaded *after*
- X-server as described above. You might be able to force to load
- the module, but it may result in hang-up. Hence, make sure that
- you load this module *before* X if you encounter this kind of
- problem.
-
- Module snd-opl3sa2
- ------------------
-
- Module for Yamaha OPL3-SA2/SA3 sound cards.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - control port # for OPL3-SA chip (0x370)
- sb_port - SB port # for OPL3-SA chip (0x220,0x240)
- wss_port - WSS port # for OPL3-SA chip (0x530,0xe80,0xf40,0x604)
- midi_port - port # for MPU-401 UART (0x300,0x330), -1 = disable
- fm_port - FM port # for OPL3-SA chip (0x388), -1 = disable
- irq - IRQ # for OPL3-SA chip (5,7,9,10)
- dma1 - first DMA # for Yamaha OPL3-SA chip (0,1,3)
- dma2 - second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
-
- This module supports multiple cards and ISA PnP. It does not support
- autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
-
- The power-management is supported.
-
- Module snd-opti92x-ad1848
- -------------------------
-
- Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
- Module works with OAK Mozart cards as well.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
- mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
- fm_port - port # for OPL3 device (0x388)
- irq - IRQ # for WSS chip (5,7,9,10,11)
- mpu_irq - IRQ # for MPU-401 UART (5,7,9,10)
- dma1 - first DMA # for WSS chip (0,1,3)
-
- This module supports only one card, autoprobe and PnP.
-
- Module snd-opti92x-cs4231
- -------------------------
-
- Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
- mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
- fm_port - port # for OPL3 device (0x388)
- irq - IRQ # for WSS chip (5,7,9,10,11)
- mpu_irq - IRQ # for MPU-401 UART (5,7,9,10)
- dma1 - first DMA # for WSS chip (0,1,3)
- dma2 - second DMA # for WSS chip (0,1,3)
-
- This module supports only one card, autoprobe and PnP.
-
- Module snd-opti93x
- ------------------
-
- Module for sound cards based on OPTi 82c93x chips.
-
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
- mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
- fm_port - port # for OPL3 device (0x388)
- irq - IRQ # for WSS chip (5,7,9,10,11)
- mpu_irq - IRQ # for MPU-401 UART (5,7,9,10)
- dma1 - first DMA # for WSS chip (0,1,3)
- dma2 - second DMA # for WSS chip (0,1,3)
-
- This module supports only one card, autoprobe and PnP.
-
- Module snd-oxygen
- -----------------
-
- Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
- * Asound A-8788
- * Asus Xonar DG/DGX
- * AuzenTech X-Meridian
- * AuzenTech X-Meridian 2G
- * Bgears b-Enspirer
- * Club3D Theatron DTS
- * HT-Omega Claro (plus)
- * HT-Omega Claro halo (XT)
- * Kuroutoshikou CMI8787-HG2PCI
- * Razer Barracuda AC-1
- * Sondigo Inferno
- * TempoTec HiFier Fantasia
- * TempoTec HiFier Serenade
-
- This module supports autoprobe and multiple cards.
-
- Module snd-pcsp
- -----------------
-
- Module for internal PC-Speaker.
-
- nopcm - Disable PC-Speaker PCM sound. Only beeps remain.
- nforce_wa - enable NForce chipset workaround. Expect bad sound.
-
- This module supports system beeps, some kind of PCM playback and
- even a few mixer controls.
-
- Module snd-pcxhr
- ----------------
-
- Module for Digigram PCXHR boards
-
- This module supports multiple cards.
-
- Module snd-portman2x4
- ---------------------
-
- Module for Midiman Portman 2x4 parallel port MIDI interface
-
- This module supports multiple cards.
-
- Module snd-powermac (on ppc only)
- ---------------------------------
-
- Module for PowerMac, iMac and iBook on-board soundchips
-
- enable_beep - enable beep using PCM (enabled as default)
-
- Module supports autoprobe a chip.
-
- Note: the driver may have problems regarding endianness.
-
- The power-management is supported.
-
- Module snd-pxa2xx-ac97 (on arm only)
- ------------------------------------
-
- Module for AC97 driver for the Intel PXA2xx chip
-
- For ARM architecture only.
-
- The power-management is supported.
-
- Module snd-riptide
- ------------------
-
- Module for Conexant Riptide chip
-
- joystick_port - Joystick port # (default: 0x200)
- mpu_port - MPU401 port # (default: 0x330)
- opl3_port - OPL3 port # (default: 0x388)
-
- This module supports multiple cards.
- The driver requires the firmware loader support on kernel.
- You need to install the firmware file "riptide.hex" to the standard
- firmware path (e.g. /lib/firmware).
-
- Module snd-rme32
- ----------------
-
- Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
- Prodif96 and Prodif Gold) sound cards.
-
- This module supports multiple cards.
-
- Module snd-rme96
- ----------------
-
- Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
-
- This module supports multiple cards.
-
- Module snd-rme9652
- ------------------
-
- Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
-
- precise_ptr - Enable precise pointer (doesn't work reliably).
- (default = 0)
-
- This module supports multiple cards.
-
- Note: snd-page-alloc module does the job which snd-hammerfall-mem
- module did formerly. It will allocate the buffers in advance
- when any RME9652 cards are found. To make the buffer
- allocation sure, load snd-page-alloc module in the early
- stage of boot sequence. See "Early Buffer Allocation"
- section.
-
- Module snd-sa11xx-uda1341 (on arm only)
- ---------------------------------------
-
- Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
-
- Module supports only one card.
- Module has no enable and index options.
-
- The power-management is supported.
-
- Module snd-sb8
- --------------
-
- Module for 8-bit SoundBlaster cards: SoundBlaster 1.0,
- SoundBlaster 2.0,
- SoundBlaster Pro
-
- port - port # for SB DSP chip (0x220,0x240,0x260)
- irq - IRQ # for SB DSP chip (5,7,9,10)
- dma8 - DMA # for SB DSP chip (1,3)
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-sb16 and snd-sbawe
- -----------------------------
-
- Module for 16-bit SoundBlaster cards: SoundBlaster 16 (PnP),
- SoundBlaster AWE 32 (PnP),
- SoundBlaster AWE 64 PnP
-
- mic_agc - Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
- csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- port - port # for SB DSP 4.x chip (0x220,0x240,0x260)
- mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disable
- awe_port - base port # for EMU8000 synthesizer (0x620,0x640,0x660)
- (snd-sbawe module only)
- irq - IRQ # for SB DSP 4.x chip (5,7,9,10)
- dma8 - 8-bit DMA # for SB DSP 4.x chip (0,1,3)
- dma16 - 16-bit DMA # for SB DSP 4.x chip (5,6,7)
-
- This module supports multiple cards, autoprobe and ISA PnP.
-
- Note: To use Vibra16X cards in 16-bit half duplex mode, you must
- disable 16bit DMA with dma16 = -1 module parameter.
- Also, all Sound Blaster 16 type cards can operate in 16-bit
- half duplex mode through 8-bit DMA channel by disabling their
- 16-bit DMA channel.
-
- The power-management is supported.
-
- Module snd-sc6000
- -----------------
-
- Module for Gallant SC-6000 soundcard and later models: SC-6600
- and SC-7000.
-
- port - Port # (0x220 or 0x240)
- mss_port - MSS Port # (0x530 or 0xe80)
- irq - IRQ # (5,7,9,10,11)
- mpu_irq - MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
- dma - DMA # (1,3,0)
- joystick - Enable gameport - 0 = disable (default), 1 = enable
-
- This module supports multiple cards.
-
- This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
-
- Module snd-sscape
- -----------------
-
- Module for ENSONIQ SoundScape cards.
-
- port - Port # (PnP setup)
- wss_port - WSS Port # (PnP setup)
- irq - IRQ # (PnP setup)
- mpu_irq - MPU-401 IRQ # (PnP setup)
- dma - DMA # (PnP setup)
- dma2 - 2nd DMA # (PnP setup, -1 to disable)
- joystick - Enable gameport - 0 = disable (default), 1 = enable
-
- This module supports multiple cards.
-
- The driver requires the firmware loader support on kernel.
-
- Module snd-sun-amd7930 (on sparc only)
- --------------------------------------
-
- Module for AMD7930 sound chips found on Sparcs.
-
- This module supports multiple cards.
-
- Module snd-sun-cs4231 (on sparc only)
- -------------------------------------
-
- Module for CS4231 sound chips found on Sparcs.
-
- This module supports multiple cards.
-
- Module snd-sun-dbri (on sparc only)
- -----------------------------------
-
- Module for DBRI sound chips found on Sparcs.
-
- This module supports multiple cards.
-
- Module snd-wavefront
- --------------------
-
- Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
-
- use_cs4232_midi - Use CS4232 MPU-401 interface
- (inaccessibly located inside your computer)
- isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
-
- with isapnp=0, the following options are available:
-
- cs4232_pcm_port - Port # for CS4232 PCM interface.
- cs4232_pcm_irq - IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
- cs4232_mpu_port - Port # for CS4232 MPU-401 interface.
- cs4232_mpu_irq - IRQ # for CS4232 MPU-401 interface (9,11,12,15).
- ics2115_port - Port # for ICS2115
- ics2115_irq - IRQ # for ICS2115
- fm_port - FM OPL-3 Port #
- dma1 - DMA1 # for CS4232 PCM interface.
- dma2 - DMA2 # for CS4232 PCM interface.
-
- The below are options for wavefront_synth features:
- wf_raw - Assume that we need to boot the OS (default:no)
- If yes, then during driver loading, the state of the board is
- ignored, and we reset the board and load the firmware anyway.
- fx_raw - Assume that the FX process needs help (default:yes)
- If false, we'll leave the FX processor in whatever state it is
- when the driver is loaded. The default is to download the
- microprogram and associated coefficients to set it up for
- "default" operation, whatever that means.
- debug_default - Debug parameters for card initialization
- wait_usecs - How long to wait without sleeping, usecs
- (default:150)
- This magic number seems to give pretty optimal throughput
- based on my limited experimentation.
- If you want to play around with it and find a better value, be
- my guest. Remember, the idea is to get a number that causes us
- to just busy wait for as many WaveFront commands as possible,
- without coming up with a number so large that we hog the whole
- CPU.
- Specifically, with this number, out of about 134,000 status
- waits, only about 250 result in a sleep.
- sleep_interval - How long to sleep when waiting for reply
- (default: 100)
- sleep_tries - How many times to try sleeping during a wait
- (default: 50)
- ospath - Pathname to processed ICS2115 OS firmware
- (default:wavefront.os)
- The path name of the ISC2115 OS firmware. In the recent
- version, it's handled via firmware loader framework, so it
- must be installed in the proper path, typically,
- /lib/firmware.
- reset_time - How long to wait for a reset to take effect
- (default:2)
- ramcheck_time - How many seconds to wait for the RAM test
- (default:20)
- osrun_time - How many seconds to wait for the ICS2115 OS
- (default:10)
-
- This module supports multiple cards and ISA PnP.
-
- Note: the firmware file "wavefront.os" was located in the earlier
- version in /etc. Now it's loaded via firmware loader, and
- must be in the proper firmware path, such as /lib/firmware.
- Copy (or symlink) the file appropriately if you get an error
- regarding firmware downloading after upgrading the kernel.
-
- Module snd-sonicvibes
- ---------------------
-
- Module for S3 SonicVibes PCI sound cards.
- * PINE Schubert 32 PCI
-
- reverb - Reverb Enable - 1 = enable, 0 = disable (default)
- - SoundCard must have onboard SRAM for this.
- mge - Mic Gain Enable - 1 = enable, 0 = disable (default)
-
- This module supports multiple cards and autoprobe.
-
- Module snd-serial-u16550
- ------------------------
-
- Module for UART16550A serial MIDI ports.
-
- port - port # for UART16550A chip
- irq - IRQ # for UART16550A chip, -1 = poll mode
- speed - speed in bauds (9600,19200,38400,57600,115200)
- 38400 = default
- base - base for divisor in bauds (57600,115200,230400,460800)
- 115200 = default
- outs - number of MIDI ports in a serial port (1-4)
- 1 = default
- adaptor - Type of adaptor.
- 0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
- 3 = MS-124W M/B, 4 = Generic
-
- This module supports multiple cards. This module does not support autoprobe
- thus the main port must be specified!!! Other options are optional.
-
- Module snd-trident
- ------------------
-
- Module for Trident 4DWave DX/NX sound cards.
- * Best Union Miss Melody 4DWave PCI
- * HIS 4DWave PCI
- * Warpspeed ONSpeed 4DWave PCI
- * AzTech PCI 64-Q3D
- * Addonics SV 750
- * CHIC True Sound 4Dwave
- * Shark Predator4D-PCI
- * Jaton SonicWave 4D
- * SiS SI7018 PCI Audio
- * Hoontech SoundTrack Digital 4DWave NX
-
- pcm_channels - max channels (voices) reserved for PCM
- wavetable_size - max wavetable size in kB (4-?kb)
-
- This module supports multiple cards and autoprobe.
-
- The power-management is supported.
-
- Module snd-ua101
- ----------------
-
- Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
-
- This module supports multiple devices, autoprobe and hotplugging.
-
- Module snd-usb-audio
- --------------------
-
- Module for USB audio and USB MIDI devices.
-
- vid - Vendor ID for the device (optional)
- pid - Product ID for the device (optional)
- nrpacks - Max. number of packets per URB (default: 8)
- device_setup - Device specific magic number (optional)
- - Influence depends on the device
- - Default: 0x0000
- ignore_ctl_error - Ignore any USB-controller regarding mixer
- interface (default: no)
- autoclock - Enable auto-clock selection for UAC2 devices
- (default: yes)
- quirk_alias - Quirk alias list, pass strings like
- "0123abcd:5678beef", which applies the existing
- quirk for the device 5678:beef to a new device
- 0123:abcd.
-
- This module supports multiple devices, autoprobe and hotplugging.
-
- NB: nrpacks parameter can be modified dynamically via sysfs.
- Don't put the value over 20. Changing via sysfs has no sanity
- check.
- NB: ignore_ctl_error=1 may help when you get an error at accessing
- the mixer element such as URB error -22. This happens on some
- buggy USB device or the controller.
- NB: quirk_alias option is provided only for testing / development.
- If you want to have a proper support, contact to upstream for
- adding the matching quirk in the driver code statically.
-
- Module snd-usb-caiaq
- --------------------
-
- Module for caiaq UB audio interfaces,
- * Native Instruments RigKontrol2
- * Native Instruments Kore Controller
- * Native Instruments Audio Kontrol 1
- * Native Instruments Audio 8 DJ
-
- This module supports multiple devices, autoprobe and hotplugging.
-
- Module snd-usb-usx2y
- --------------------
-
- Module for Tascam USB US-122, US-224 and US-428 devices.
-
- This module supports multiple devices, autoprobe and hotplugging.
-
- Note: you need to load the firmware via usx2yloader utility included
- in alsa-tools and alsa-firmware packages.
-
- Module snd-via82xx
- ------------------
-
- Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
- 8233A, 8233C, 8235, 8237 (south) bridge.
-
- mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
- [VIA686A/686B only]
- joystick - Enable joystick (default off) [VIA686A/686B only]
- ac97_clock - AC'97 codec clock base (default 48000Hz)
- dxs_support - support DXS channels,
- 0 = auto (default), 1 = enable, 2 = disable,
- 3 = 48k only, 4 = no VRA, 5 = enable any sample
- rate and different sample rates on different
- channels
- [VIA8233/C, 8235, 8237 only]
- ac97_quirk - AC'97 workaround for strange hardware
- See "AC97 Quirk Option" section below.
-
- This module supports one chip and autoprobe.
-
- Note: on some SMP motherboards like MSI 694D the interrupts might
- not be generated properly. In such a case, please try to
- set the SMP (or MPS) version on BIOS to 1.1 instead of
- default value 1.4. Then the interrupt number will be
- assigned under 15. You might also upgrade your BIOS.
-
- Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
- channels as the first PCM. On these channels, up to 4
- streams can be played at the same time, and the controller
- can perform sample rate conversion with separate rates for
- each channel.
- As default (dxs_support = 0), 48k fixed rate is chosen
- except for the known devices since the output is often
- noisy except for 48k on some mother boards due to the
- bug of BIOS.
- Please try once dxs_support=5 and if it works on other
- sample rates (e.g. 44.1kHz of mp3 playback), please let us
- know the PCI subsystem vendor/device id's (output of
- "lspci -nv").
- If dxs_support=5 does not work, try dxs_support=4; if it
- doesn't work too, try dxs_support=1. (dxs_support=1 is
- usually for old motherboards. The correct implemented
- board should work with 4 or 5.) If it still doesn't
- work and the default setting is ok, dxs_support=3 is the
- right choice. If the default setting doesn't work at all,
- try dxs_support=2 to disable the DXS channels.
- In any cases, please let us know the result and the
- subsystem vendor/device ids. See "Links and Addresses"
- below.
-
- Note: for the MPU401 on VIA823x, use snd-mpu401 driver
- additionally. The mpu_port option is for VIA686 chips only.
-
- The power-management is supported.
-
- Module snd-via82xx-modem
- ------------------------
-
- Module for VIA82xx AC97 modem
-
- ac97_clock - AC'97 codec clock base (default 48000Hz)
-
- This module supports one card and autoprobe.
-
- Note: The default index value of this module is -2, i.e. the first
- slot is excluded.
-
- The power-management is supported.
-
- Module snd-virmidi
- ------------------
-
- Module for virtual rawmidi devices.
- This module creates virtual rawmidi devices which communicate
- to the corresponding ALSA sequencer ports.
-
- midi_devs - MIDI devices # (1-4, default=4)
-
- This module supports multiple cards.
-
- Module snd-virtuoso
- -------------------
-
- Module for sound cards based on the Asus AV66/AV100/AV200 chips,
- i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
- Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
-
- This module supports autoprobe and multiple cards.
-
- Module snd-vx222
- ----------------
-
- Module for Digigram VX-Pocket VX222, V222 v2 and Mic cards.
-
- mic - Enable Microphone on V222 Mic (NYI)
- ibl - Capture IBL size. (default = 0, minimum size)
-
- This module supports multiple cards.
-
- When the driver is compiled as a module and the hotplug firmware
- is supported, the firmware data is loaded via hotplug automatically.
- Install the necessary firmware files in alsa-firmware package.
- When no hotplug fw loader is available, you need to load the
- firmware via vxloader utility in alsa-tools package. To invoke
- vxloader automatically, add the following to /etc/modprobe.d/alsa.conf
-
- install snd-vx222 /sbin/modprobe --first-time -i snd-vx222 && /usr/bin/vxloader
-
- (for 2.2/2.4 kernels, add "post-install /usr/bin/vxloader" to
- /etc/modules.conf, instead.)
- IBL size defines the interrupts period for PCM. The smaller size
- gives smaller latency but leads to more CPU consumption, too.
- The size is usually aligned to 126. As default (=0), the smallest
- size is chosen. The possible IBL values can be found in
- /proc/asound/cardX/vx-status proc file.
-
- The power-management is supported.
-
- Module snd-vxpocket
- -------------------
-
- Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
-
- ibl - Capture IBL size. (default = 0, minimum size)
-
- This module supports multiple cards. The module is compiled only when
- PCMCIA is supported on kernel.
-
- With the older 2.6.x kernel, to activate the driver via the card
- manager, you'll need to set up /etc/pcmcia/vxpocket.conf. See the
- sound/pcmcia/vx/vxpocket.c. 2.6.13 or later kernel requires no
- longer require a config file.
-
- When the driver is compiled as a module and the hotplug firmware
- is supported, the firmware data is loaded via hotplug automatically.
- Install the necessary firmware files in alsa-firmware package.
- When no hotplug fw loader is available, you need to load the
- firmware via vxloader utility in alsa-tools package.
-
- About capture IBL, see the description of snd-vx222 module.
-
- Note: snd-vxp440 driver is merged to snd-vxpocket driver since
- ALSA 1.0.10.
-
- The power-management is supported.
-
- Module snd-ymfpci
- -----------------
-
- Module for Yamaha PCI chips (YMF72x, YMF74x & YMF75x).
-
- mpu_port - 0x300,0x330,0x332,0x334, 0 (disable) by default,
- 1 (auto-detect for YMF744/754 only)
- fm_port - 0x388,0x398,0x3a0,0x3a8, 0 (disable) by default
- 1 (auto-detect for YMF744/754 only)
- joystick_port - 0x201,0x202,0x204,0x205, 0 (disable) by default,
- 1 (auto-detect)
- rear_switch - enable shared rear/line-in switch (bool)
-
- This module supports autoprobe and multiple chips.
-
- The power-management is supported.
-
- Module snd-pdaudiocf
- --------------------
-
- Module for Sound Core PDAudioCF sound card.
-
- The power-management is supported.
-
-
-AC97 Quirk Option
-=================
-
-The ac97_quirk option is used to enable/override the workaround for
-specific devices on drivers for on-board AC'97 controllers like
-snd-intel8x0. Some hardware have swapped output pins between Master
-and Headphone, or Surround (thanks to confusion of AC'97
-specifications from version to version :-)
-
-The driver provides the auto-detection of known problematic devices,
-but some might be unknown or wrongly detected. In such a case, pass
-the proper value with this option.
-
-The following strings are accepted:
- - default Don't override the default setting
- - none Disable the quirk
- - hp_only Bind Master and Headphone controls as a single control
- - swap_hp Swap headphone and master controls
- - swap_surround Swap master and surround controls
- - ad_sharing For AD1985, turn on OMS bit and use headphone
- - alc_jack For ALC65x, turn on the jack sense mode
- - inv_eapd Inverted EAPD implementation
- - mute_led Bind EAPD bit for turning on/off mute LED
-
-For backward compatibility, the corresponding integer value -1, 0,
-... are accepted, too.
-
-For example, if "Master" volume control has no effect on your device
-but only "Headphone" does, pass ac97_quirk=hp_only module option.
-
-
-Configuring Non-ISAPNP Cards
-============================
-
-When the kernel is configured with ISA-PnP support, the modules
-supporting the isapnp cards will have module options "isapnp".
-If this option is set, *only* the ISA-PnP devices will be probed.
-For probing the non ISA-PnP cards, you have to pass "isapnp=0" option
-together with the proper i/o and irq configuration.
-
-When the kernel is configured without ISA-PnP support, isapnp option
-will be not built in.
-
-
-Module Autoloading Support
-==========================
-
-The ALSA drivers can be loaded automatically on demand by defining
-module aliases. The string 'snd-card-%1' is requested for ALSA native
-devices where %i is sound card number from zero to seven.
-
-To auto-load an ALSA driver for OSS services, define the string
-'sound-slot-%i' where %i means the slot number for OSS, which
-corresponds to the card index of ALSA. Usually, define this
-as the same card module.
-
-An example configuration for a single emu10k1 card is like below:
------ /etc/modprobe.d/alsa.conf
-alias snd-card-0 snd-emu10k1
-alias sound-slot-0 snd-emu10k1
------ /etc/modprobe.d/alsa.conf
-
-The available number of auto-loaded sound cards depends on the module
-option "cards_limit" of snd module. As default it's set to 1.
-To enable the auto-loading of multiple cards, specify the number of
-sound cards in that option.
-
-When multiple cards are available, it'd better to specify the index
-number for each card via module option, too, so that the order of
-cards is kept consistent.
-
-An example configuration for two sound cards is like below:
-
------ /etc/modprobe.d/alsa.conf
-# ALSA portion
-options snd cards_limit=2
-alias snd-card-0 snd-interwave
-alias snd-card-1 snd-ens1371
-options snd-interwave index=0
-options snd-ens1371 index=1
-# OSS/Free portion
-alias sound-slot-0 snd-interwave
-alias sound-slot-1 snd-ens1371
------ /etc/modprobe.d/alsa.conf
-
-In this example, the interwave card is always loaded as the first card
-(index 0) and ens1371 as the second (index 1).
-
-Alternative (and new) way to fixate the slot assignment is to use
-"slots" option of snd module. In the case above, specify like the
-following:
-
-options snd slots=snd-interwave,snd-ens1371
-
-Then, the first slot (#0) is reserved for snd-interwave driver, and
-the second (#1) for snd-ens1371. You can omit index option in each
-driver if slots option is used (although you can still have them at
-the same time as long as they don't conflict).
-
-The slots option is especially useful for avoiding the possible
-hot-plugging and the resultant slot conflict. For example, in the
-case above again, the first two slots are already reserved. If any
-other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
-snd-ens1371, it will be assigned to the third or later slot.
-
-When a module name is given with '!', the slot will be given for any
-modules but that name. For example, "slots=!snd-pcsp" will reserve
-the first slot for any modules but snd-pcsp.
-
-
-ALSA PCM devices to OSS devices mapping
-=======================================
-
-/dev/snd/pcmC0D0[c|p] -> /dev/audio0 (/dev/audio) -> minor 4
-/dev/snd/pcmC0D0[c|p] -> /dev/dsp0 (/dev/dsp) -> minor 3
-/dev/snd/pcmC0D1[c|p] -> /dev/adsp0 (/dev/adsp) -> minor 12
-/dev/snd/pcmC1D0[c|p] -> /dev/audio1 -> minor 4+16 = 20
-/dev/snd/pcmC1D0[c|p] -> /dev/dsp1 -> minor 3+16 = 19
-/dev/snd/pcmC1D1[c|p] -> /dev/adsp1 -> minor 12+16 = 28
-/dev/snd/pcmC2D0[c|p] -> /dev/audio2 -> minor 4+32 = 36
-/dev/snd/pcmC2D0[c|p] -> /dev/dsp2 -> minor 3+32 = 39
-/dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44
-
-The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means
-sound card number and second means device number. The ALSA devices
-have either 'c' or 'p' suffix indicating the direction, capture and
-playback, respectively.
-
-Please note that the device mapping above may be varied via the module
-options of snd-pcm-oss module.
-
-
-Proc interfaces (/proc/asound)
-==============================
-
-/proc/asound/card#/pcm#[cp]/oss
--------------------------------
- String "erase" - erase all additional information about OSS applications
- String "<app_name> <fragments> <fragment_size> [<options>]"
-
- <app_name> - name of application with (higher priority) or without path
- <fragments> - number of fragments or zero if auto
- <fragment_size> - size of fragment in bytes or zero if auto
- <options> - optional parameters
- - disable the application tries to open a pcm device for
- this channel but does not want to use it.
- (Cause a bug or mmap needs)
- It's good for Quake etc...
- - direct don't use plugins
- - block force block mode (rvplayer)
- - non-block force non-block mode
- - whole-frag write only whole fragments (optimization affecting
- playback only)
- - no-silence do not fill silence ahead to avoid clicks
- - buggy-ptr Returns the whitespace blocks in GETOPTR ioctl
- instead of filled blocks
-
- Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
- echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
- echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
-
-
-Early Buffer Allocation
-=======================
-
-Some drivers (e.g. hdsp) require the large contiguous buffers, and
-sometimes it's too late to find such spaces when the driver module is
-actually loaded due to memory fragmentation. You can pre-allocate the
-PCM buffers by loading snd-page-alloc module and write commands to its
-proc file in prior, for example, in the early boot stage like
-/etc/init.d/*.local scripts.
-
-Reading the proc file /proc/drivers/snd-page-alloc shows the current
-usage of page allocation. In writing, you can send the following
-commands to the snd-page-alloc driver:
-
- - add VENDOR DEVICE MASK SIZE BUFFERS
-
- VENDOR and DEVICE are PCI vendor and device IDs. They take
- integer numbers (0x prefix is needed for the hex).
- MASK is the PCI DMA mask. Pass 0 if not restricted.
- SIZE is the size of each buffer to allocate. You can pass
- k and m suffix for KB and MB. The max number is 16MB.
- BUFFERS is the number of buffers to allocate. It must be greater
- than 0. The max number is 4.
-
- - erase
-
- This will erase the all pre-allocated buffers which are not in
- use.
-
-
-Links and Addresses
-===================
-
- ALSA project homepage
- http://www.alsa-project.org
-
- Kernel Bugzilla
- http://bugzilla.kernel.org/
-
- ALSA Developers ML
- mailto:alsa-devel@alsa-project.org
-
- alsa-info.sh script
- http://www.alsa-project.org/alsa-info.sh
diff --git a/Documentation/sound/alsa/ControlNames.txt b/Documentation/sound/alsa/ControlNames.txt
deleted file mode 100644
index 3fc1cf50d28e..000000000000
--- a/Documentation/sound/alsa/ControlNames.txt
+++ /dev/null
@@ -1,107 +0,0 @@
-This document describes standard names of mixer controls.
-
-Syntax: [LOCATION] SOURCE [CHANNEL] [DIRECTION] FUNCTION
-
-DIRECTION:
- <nothing> (both directions)
- Playback
- Capture
- Bypass Playback
- Bypass Capture
-
-FUNCTION:
- Switch (on/off switch)
- Volume
- Route (route control, hardware specific)
-
-CHANNEL:
- <nothing> (channel independent, or applies to all channels)
- Front
- Surround (rear left/right in 4.0/5.1 surround)
- CLFE
- Center
- LFE
- Side (side left/right for 7.1 surround)
-
-LOCATION: (physical location of source)
- Front
- Rear
- Dock (docking station)
- Internal
-
-SOURCE:
- Master
- Master Mono
- Hardware Master
- Speaker (internal speaker)
- Bass Speaker (internal LFE speaker)
- Headphone
- Line Out
- Beep (beep generator)
- Phone
- Phone Input
- Phone Output
- Synth
- FM
- Mic
- Headset Mic (mic part of combined headset jack - 4-pin headphone + mic)
- Headphone Mic (mic part of either/or - 3-pin headphone or mic)
- Line (input only, use "Line Out" for output)
- CD
- Video
- Zoom Video
- Aux
- PCM
- PCM Pan
- Loopback
- Analog Loopback (D/A -> A/D loopback)
- Digital Loopback (playback -> capture loopback - without analog path)
- Mono
- Mono Output
- Multi
- ADC
- Wave
- Music
- I2S
- IEC958
- HDMI
- SPDIF (output only)
- SPDIF In
- Digital In
- HDMI/DP (either HDMI or DisplayPort)
-
-Exceptions (deprecated):
- [Analogue|Digital] Capture Source
- [Analogue|Digital] Capture Switch (aka input gain switch)
- [Analogue|Digital] Capture Volume (aka input gain volume)
- [Analogue|Digital] Playback Switch (aka output gain switch)
- [Analogue|Digital] Playback Volume (aka output gain volume)
- Tone Control - Switch
- Tone Control - Bass
- Tone Control - Treble
- 3D Control - Switch
- 3D Control - Center
- 3D Control - Depth
- 3D Control - Wide
- 3D Control - Space
- 3D Control - Level
- Mic Boost [(?dB)]
-
-PCM interface:
-
- Sample Clock Source { "Word", "Internal", "AutoSync" }
- Clock Sync Status { "Lock", "Sync", "No Lock" }
- External Rate /* external capture rate */
- Capture Rate /* capture rate taken from external source */
-
-IEC958 (S/PDIF) interface:
-
- IEC958 [...] [Playback|Capture] Switch /* turn on/off the IEC958 interface */
- IEC958 [...] [Playback|Capture] Volume /* digital volume control */
- IEC958 [...] [Playback|Capture] Default /* default or global value - read/write */
- IEC958 [...] [Playback|Capture] Mask /* consumer and professional mask */
- IEC958 [...] [Playback|Capture] Con Mask /* consumer mask */
- IEC958 [...] [Playback|Capture] Pro Mask /* professional mask */
- IEC958 [...] [Playback|Capture] PCM Stream /* the settings assigned to a PCM stream */
- IEC958 Q-subcode [Playback|Capture] Default /* Q-subcode bits */
- IEC958 Preamble [Playback|Capture] Default /* burst preamble words (4*16bits) */
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
deleted file mode 100644
index ec099d4343f2..000000000000
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ /dev/null
@@ -1,324 +0,0 @@
- Model name Description
- ---------- -----------
-ALC880
-======
- 3stack 3-jack in back and a headphone out
- 3stack-digout 3-jack in back, a HP out and a SPDIF out
- 5stack 5-jack in back, 2-jack in front
- 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
- 6stack 6-jack in back, 2-jack in front
- 6stack-digout 6-jack with a SPDIF out
-
-ALC260
-======
- gpio1 Enable GPIO1
- coef Enable EAPD via COEF table
- fujitsu Quirk for FSC S7020
- fujitsu-jwse Quirk for FSC S7020 with jack modes and HP mic support
-
-ALC262
-======
- inv-dmic Inverted internal mic workaround
-
-ALC267/268
-==========
- inv-dmic Inverted internal mic workaround
- hp-eapd Disable HP EAPD on NID 0x15
-
-ALC22x/23x/25x/269/27x/28x/29x (and vendor-specific ALC3xxx models)
-======
- laptop-amic Laptops with analog-mic input
- laptop-dmic Laptops with digital-mic input
- alc269-dmic Enable ALC269(VA) digital mic workaround
- alc271-dmic Enable ALC271X digital mic workaround
- inv-dmic Inverted internal mic workaround
- headset-mic Indicates a combined headset (headphone+mic) jack
- headset-mode More comprehensive headset support for ALC269 & co
- headset-mode-no-hp-mic Headset mode support without headphone mic
- lenovo-dock Enables docking station I/O for some Lenovos
- hp-gpio-led GPIO LED support on HP laptops
- dell-headset-multi Headset jack, which can also be used as mic-in
- dell-headset-dock Headset jack (without mic-in), and also dock I/O
- alc283-dac-wcaps Fixups for Chromebook with ALC283
- alc283-sense-combo Combo jack sensing on ALC283
- tpt440-dock Pin configs for Lenovo Thinkpad Dock support
-
-ALC66x/67x/892
-==============
- mario Chromebook mario model fixup
- asus-mode1 ASUS
- asus-mode2 ASUS
- asus-mode3 ASUS
- asus-mode4 ASUS
- asus-mode5 ASUS
- asus-mode6 ASUS
- asus-mode7 ASUS
- asus-mode8 ASUS
- inv-dmic Inverted internal mic workaround
- dell-headset-multi Headset jack, which can also be used as mic-in
-
-ALC680
-======
- N/A
-
-ALC88x/898/1150
-======================
- acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G
- acer-aspire-8930g Acer Aspire 8330G/6935G
- acer-aspire Acer Aspire others
- inv-dmic Inverted internal mic workaround
- no-primary-hp VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC)
-
-ALC861/660
-==========
- N/A
-
-ALC861VD/660VD
-==============
- N/A
-
-CMI9880
-=======
- minimal 3-jack in back
- min_fp 3-jack in back, 2-jack in front
- full 6-jack in back, 2-jack in front
- full_dig 6-jack in back, 2-jack in front, SPDIF I/O
- allout 5-jack in back, 2-jack in front, SPDIF out
- auto auto-config reading BIOS (default)
-
-AD1882 / AD1882A
-================
- 3stack 3-stack mode
- 3stack-automute 3-stack with automute front HP (default)
- 6stack 6-stack mode
-
-AD1884A / AD1883 / AD1984A / AD1984B
-====================================
- desktop 3-stack desktop (default)
- laptop laptop with HP jack sensing
- mobile mobile devices with HP jack sensing
- thinkpad Lenovo Thinkpad X300
- touchsmart HP Touchsmart
-
-AD1884
-======
- N/A
-
-AD1981
-======
- basic 3-jack (default)
- hp HP nx6320
- thinkpad Lenovo Thinkpad T60/X60/Z60
- toshiba Toshiba U205
-
-AD1983
-======
- N/A
-
-AD1984
-======
- basic default configuration
- thinkpad Lenovo Thinkpad T61/X61
- dell_desktop Dell T3400
-
-AD1986A
-=======
- 3stack 3-stack, shared surrounds
- laptop 2-channel only (FSC V2060, Samsung M50)
- laptop-imic 2-channel with built-in mic
- eapd Turn on EAPD constantly
-
-AD1988/AD1988B/AD1989A/AD1989B
-==============================
- 6stack 6-jack
- 6stack-dig ditto with SPDIF
- 3stack 3-jack
- 3stack-dig ditto with SPDIF
- laptop 3-jack with hp-jack automute
- laptop-dig ditto with SPDIF
- auto auto-config reading BIOS (default)
-
-Conexant 5045
-=============
- laptop-hpsense Laptop with HP sense (old model laptop)
- laptop-micsense Laptop with Mic sense (old model fujitsu)
- laptop-hpmicsense Laptop with HP and Mic senses
- benq Benq R55E
- laptop-hp530 HP 530 laptop
- test for testing/debugging purpose, almost all controls
- can be adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
-
-Conexant 5047
-=============
- laptop Basic Laptop config
- laptop-hp Laptop config for some HP models (subdevice 30A5)
- laptop-eapd Laptop config with EAPD support
- test for testing/debugging purpose, almost all controls
- can be adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
-
-Conexant 5051
-=============
- laptop Basic Laptop config (default)
- hp HP Spartan laptop
- hp-dv6736 HP dv6736
- hp-f700 HP Compaq Presario F700
- ideapad Lenovo IdeaPad laptop
- toshiba Toshiba Satellite M300
-
-Conexant 5066
-=============
- laptop Basic Laptop config (default)
- hp-laptop HP laptops, e g G60
- asus Asus K52JU, Lenovo G560
- dell-laptop Dell laptops
- dell-vostro Dell Vostro
- olpc-xo-1_5 OLPC XO 1.5
- ideapad Lenovo IdeaPad U150
- thinkpad Lenovo Thinkpad
-
-STAC9200
-========
- ref Reference board
- oqo OQO Model 2
- dell-d21 Dell (unknown)
- dell-d22 Dell (unknown)
- dell-d23 Dell (unknown)
- dell-m21 Dell Inspiron 630m, Dell Inspiron 640m
- dell-m22 Dell Latitude D620, Dell Latitude D820
- dell-m23 Dell XPS M1710, Dell Precision M90
- dell-m24 Dell Latitude 120L
- dell-m25 Dell Inspiron E1505n
- dell-m26 Dell Inspiron 1501
- dell-m27 Dell Inspiron E1705/9400
- gateway-m4 Gateway laptops with EAPD control
- gateway-m4-2 Gateway laptops with EAPD control
- panasonic Panasonic CF-74
- auto BIOS setup (default)
-
-STAC9205/9254
-=============
- ref Reference board
- dell-m42 Dell (unknown)
- dell-m43 Dell Precision
- dell-m44 Dell Inspiron
- eapd Keep EAPD on (e.g. Gateway T1616)
- auto BIOS setup (default)
-
-STAC9220/9221
-=============
- ref Reference board
- 3stack D945 3stack
- 5stack D945 5stack + SPDIF
- intel-mac-v1 Intel Mac Type 1
- intel-mac-v2 Intel Mac Type 2
- intel-mac-v3 Intel Mac Type 3
- intel-mac-v4 Intel Mac Type 4
- intel-mac-v5 Intel Mac Type 5
- intel-mac-auto Intel Mac (detect type according to subsystem id)
- macmini Intel Mac Mini (equivalent with type 3)
- macbook Intel Mac Book (eq. type 5)
- macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
- macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
- imac-intel Intel iMac (eq. type 2)
- imac-intel-20 Intel iMac (newer version) (eq. type 3)
- ecs202 ECS/PC chips
- dell-d81 Dell (unknown)
- dell-d82 Dell (unknown)
- dell-m81 Dell (unknown)
- dell-m82 Dell XPS M1210
- auto BIOS setup (default)
-
-STAC9202/9250/9251
-==================
- ref Reference board, base config
- m1 Some Gateway MX series laptops (NX560XL)
- m1-2 Some Gateway MX series laptops (MX6453)
- m2 Some Gateway MX series laptops (M255)
- m2-2 Some Gateway MX series laptops
- m3 Some Gateway MX series laptops
- m5 Some Gateway MX series laptops (MP6954)
- m6 Some Gateway NX series laptops
- auto BIOS setup (default)
-
-STAC9227/9228/9229/927x
-=======================
- ref Reference board
- ref-no-jd Reference board without HP/Mic jack detection
- 3stack D965 3stack
- 5stack D965 5stack + SPDIF
- 5stack-no-fp D965 5stack without front panel
- dell-3stack Dell Dimension E520
- dell-bios Fixes with Dell BIOS setup
- dell-bios-amic Fixes with Dell BIOS setup including analog mic
- volknob Fixes with volume-knob widget 0x24
- auto BIOS setup (default)
-
-STAC92HD71B*
-============
- ref Reference board
- dell-m4-1 Dell desktops
- dell-m4-2 Dell desktops
- dell-m4-3 Dell desktops
- hp-m4 HP mini 1000
- hp-dv5 HP dv series
- hp-hdx HP HDX series
- hp-dv4-1222nr HP dv4-1222nr (with LED support)
- auto BIOS setup (default)
-
-STAC92HD73*
-===========
- ref Reference board
- no-jd BIOS setup but without jack-detection
- intel Intel DG45* mobos
- dell-m6-amic Dell desktops/laptops with analog mics
- dell-m6-dmic Dell desktops/laptops with digital mics
- dell-m6 Dell desktops/laptops with both type of mics
- dell-eq Dell desktops/laptops
- alienware Alienware M17x
- auto BIOS setup (default)
-
-STAC92HD83*
-===========
- ref Reference board
- mic-ref Reference board with power management for ports
- dell-s14 Dell laptop
- dell-vostro-3500 Dell Vostro 3500 laptop
- hp-dv7-4000 HP dv-7 4000
- hp_cNB11_intquad HP CNB models with 4 speakers
- hp-zephyr HP Zephyr
- hp-led HP with broken BIOS for mute LED
- hp-inv-led HP with broken BIOS for inverted mute LED
- hp-mic-led HP with mic-mute LED
- headset-jack Dell Latitude with a 4-pin headset jack
- hp-envy-bass Pin fixup for HP Envy bass speaker (NID 0x0f)
- hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
- hp-bnb13-eq Hardware equalizer setup for HP laptops
- auto BIOS setup (default)
-
-STAC92HD95
-==========
- hp-led LED support for HP laptops
- hp-bass Bass HPF setup for HP Spectre 13
-
-STAC9872
-========
- vaio VAIO laptop without SPDIF
- auto BIOS setup (default)
-
-Cirrus Logic CS4206/4207
-========================
- mbp55 MacBook Pro 5,5
- imac27 IMac 27 Inch
- auto BIOS setup (default)
-
-Cirrus Logic CS4208
-===================
- mba6 MacBook Air 6,1 and 6,2
- gpio0 Enable GPIO 0 amp
- auto BIOS setup (default)
-
-VIA VT17xx/VT18xx/VT20xx
-========================
- auto BIOS setup (default)
diff --git a/Documentation/sound/alsa/VIA82xx-mixer.txt b/Documentation/sound/alsa/VIA82xx-mixer.txt
deleted file mode 100644
index 1b0ac06ba95d..000000000000
--- a/Documentation/sound/alsa/VIA82xx-mixer.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-
- VIA82xx mixer
- =============
-
-On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
-Setting it to 'Input2' on such boards will cause recording to hang, or fail
-with EIO (input/output error) via OSS emulation. This control should be left
-at 'Input1' for such cards.
diff --git a/Documentation/sound/alsa/alsa-parameters.txt b/Documentation/sound/alsa/alsa-parameters.txt
deleted file mode 100644
index 0fa40679b080..000000000000
--- a/Documentation/sound/alsa/alsa-parameters.txt
+++ /dev/null
@@ -1,135 +0,0 @@
- ALSA Kernel Parameters
- ~~~~~~~~~~~~~~~~~~~~~~
-
-See Documentation/kernel-parameters.txt for general information on
-specifying module parameters.
-
-This document may not be entirely up to date and comprehensive. The command
-"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
-module. Loadable modules, after being loaded into the running kernel, also
-reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
-parameters may be changed at runtime by the command
-"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
-
-
- snd-ad1816a= [HW,ALSA]
-
- snd-ad1848= [HW,ALSA]
-
- snd-ali5451= [HW,ALSA]
-
- snd-als100= [HW,ALSA]
-
- snd-als4000= [HW,ALSA]
-
- snd-azt2320= [HW,ALSA]
-
- snd-cmi8330= [HW,ALSA]
-
- snd-cmipci= [HW,ALSA]
-
- snd-cs4231= [HW,ALSA]
-
- snd-cs4232= [HW,ALSA]
-
- snd-cs4236= [HW,ALSA]
-
- snd-cs4281= [HW,ALSA]
-
- snd-cs46xx= [HW,ALSA]
-
- snd-dt019x= [HW,ALSA]
-
- snd-dummy= [HW,ALSA]
-
- snd-emu10k1= [HW,ALSA]
-
- snd-ens1370= [HW,ALSA]
-
- snd-ens1371= [HW,ALSA]
-
- snd-es968= [HW,ALSA]
-
- snd-es1688= [HW,ALSA]
-
- snd-es18xx= [HW,ALSA]
-
- snd-es1938= [HW,ALSA]
-
- snd-es1968= [HW,ALSA]
-
- snd-fm801= [HW,ALSA]
-
- snd-gusclassic= [HW,ALSA]
-
- snd-gusextreme= [HW,ALSA]
-
- snd-gusmax= [HW,ALSA]
-
- snd-hdsp= [HW,ALSA]
-
- snd-ice1712= [HW,ALSA]
-
- snd-intel8x0= [HW,ALSA]
-
- snd-interwave= [HW,ALSA]
-
- snd-interwave-stb=
- [HW,ALSA]
-
- snd-korg1212= [HW,ALSA]
-
- snd-maestro3= [HW,ALSA]
-
- snd-mpu401= [HW,ALSA]
-
- snd-mtpav= [HW,ALSA]
-
- snd-nm256= [HW,ALSA]
-
- snd-opl3sa2= [HW,ALSA]
-
- snd-opti92x-ad1848=
- [HW,ALSA]
-
- snd-opti92x-cs4231=
- [HW,ALSA]
-
- snd-opti93x= [HW,ALSA]
-
- snd-pmac= [HW,ALSA]
-
- snd-rme32= [HW,ALSA]
-
- snd-rme96= [HW,ALSA]
-
- snd-rme9652= [HW,ALSA]
-
- snd-sb8= [HW,ALSA]
-
- snd-sb16= [HW,ALSA]
-
- snd-sbawe= [HW,ALSA]
-
- snd-serial= [HW,ALSA]
-
- snd-sgalaxy= [HW,ALSA]
-
- snd-sonicvibes= [HW,ALSA]
-
- snd-sun-amd7930=
- [HW,ALSA]
-
- snd-sun-cs4231= [HW,ALSA]
-
- snd-trident= [HW,ALSA]
-
- snd-usb-audio= [HW,ALSA,USB]
-
- snd-via82xx= [HW,ALSA]
-
- snd-virmidi= [HW,ALSA]
-
- snd-wavefront= [HW,ALSA]
-
- snd-ymfpci= [HW,ALSA]
diff --git a/Documentation/sound/alsa/seq_oss.html b/Documentation/sound/alsa/seq_oss.html
deleted file mode 100644
index 9663b45f6fde..000000000000
--- a/Documentation/sound/alsa/seq_oss.html
+++ /dev/null
@@ -1,409 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
- <TITLE>OSS Sequencer Emulation on ALSA</TITLE>
-</HEAD>
-<BODY>
-
-<CENTER>
-<H1>
-
-<HR WIDTH="100%"></H1></CENTER>
-
-<CENTER>
-<H1>
-OSS Sequencer Emulation on ALSA</H1></CENTER>
-
-<HR WIDTH="100%">
-<P>Copyright (c) 1998,1999 by Takashi Iwai
-<TT><A HREF="mailto:iwai@ww.uni-erlangen.de">&lt;iwai@ww.uni-erlangen.de></A></TT>
-<P>ver.0.1.8; Nov. 16, 1999
-<H2>
-
-<HR WIDTH="100%"></H2>
-
-<H2>
-1. Description</H2>
-This directory contains the OSS sequencer emulation driver on ALSA. Note
-that this program is still in the development state.
-<P>What this does - it provides the emulation of the OSS sequencer, access
-via
-<TT>/dev/sequencer</TT> and <TT>/dev/music</TT> devices.
-The most of applications using OSS can run if the appropriate ALSA
-sequencer is prepared.
-<P>The following features are emulated by this driver:
-<UL>
-<LI>
-Normal sequencer and MIDI events:</LI>
-
-<BR>They are converted to the ALSA sequencer events, and sent to the corresponding
-port.
-<LI>
-Timer events:</LI>
-
-<BR>The timer is not selectable by ioctl. The control rate is fixed to
-100 regardless of HZ. That is, even on Alpha system, a tick is always
-1/100 second. The base rate and tempo can be changed in <TT>/dev/music</TT>.
-
-<LI>
-Patch loading:</LI>
-
-<BR>It purely depends on the synth drivers whether it's supported since
-the patch loading is realized by callback to the synth driver.
-<LI>
-I/O controls:</LI>
-
-<BR>Most of controls are accepted. Some controls
-are dependent on the synth driver, as well as even on original OSS.</UL>
-Furthermore, you can find the following advanced features:
-<UL>
-<LI>
-Better queue mechanism:</LI>
-
-<BR>The events are queued before processing them.
-<LI>
-Multiple applications:</LI>
-
-<BR>You can run two or more applications simultaneously (even for OSS sequencer)!
-However, each MIDI device is exclusive - that is, if a MIDI device is opened
-once by some application, other applications can't use it. No such a restriction
-in synth devices.
-<LI>
-Real-time event processing:</LI>
-
-<BR>The events can be processed in real time without using out of bound
-ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
-events will be processed in real-time without queued. To switch off the
-real-time mode, send RELTIME 0 event.
-<LI>
-<TT>/proc</TT> interface:</LI>
-
-<BR>The status of applications and devices can be shown via <TT>/proc/asound/seq/oss</TT>
-at any time. In the later version, configuration will be changed via <TT>/proc</TT>
-interface, too.</UL>
-
-<H2>
-2. Installation</H2>
-Run configure script with both sequencer support (<TT>--with-sequencer=yes</TT>)
-and OSS emulation (<TT>--with-oss=yes</TT>) options. A module <TT>snd-seq-oss.o</TT>
-will be created. If the synth module of your sound card supports for OSS
-emulation (so far, only Emu8000 driver), this module will be loaded automatically.
-Otherwise, you need to load this module manually.
-<P>At beginning, this module probes all the MIDI ports which have been
-already connected to the sequencer. Once after that, the creation and deletion
-of ports are watched by announcement mechanism of ALSA sequencer.
-<P>The available synth and MIDI devices can be found in proc interface.
-Run "<TT>cat /proc/asound/seq/oss</TT>", and check the devices. For example,
-if you use an AWE64 card, you'll see like the following:
-<PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OSS sequencer emulation version 0.1.8
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA client number 63
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA receiver port 0
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of applications: 0
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of synth devices: 1
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synth 0: [EMU8000]
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type 0x1 : subtype 0x20 : voices 32
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capabilties : ioctl enabled / load_patch enabled
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of MIDI devices: 3
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 0: [Emu8000 Port-0] ALSA port 65:0
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 1: [Emu8000 Port-1] ALSA port 65:1
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 2: [0: MPU-401 (UART)] ALSA port 64:0
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability read/write / opened none</PRE>
-Note that the device number may be different from the information of
-<TT>/proc/asound/oss-devices</TT>
-or ones of the original OSS driver. Use the device number listed in <TT>/proc/asound/seq/oss</TT>
-to play via OSS sequencer emulation.
-<H2>
-3. Using Synthesizer Devices</H2>
-Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
-and xmp-1.1.5. You can load samples via <TT>/dev/sequencer</TT> like sfxload,
-too.
-<P>If the lowlevel driver supports multiple access to synth devices (like
-Emu8000 driver), two or more applications are allowed to run at the same
-time.
-<H2>
-4. Using MIDI Devices</H2>
-So far, only MIDI output was tested. MIDI input was not checked at all,
-but hopefully it will work. Use the device number listed in <TT>/proc/asound/seq/oss</TT>.
-Be aware that these numbers are mostly different from the list in
-<TT>/proc/asound/oss-devices</TT>.
-<H2>
-5. Module Options</H2>
-The following module options are available:
-<UL>
-<LI>
-<TT>maxqlen</TT></LI>
-
-<BR>specifies the maximum read/write queue length. This queue is private
-for OSS sequencer, so that it is independent from the queue length of ALSA
-sequencer. Default value is 1024.
-<LI>
-<TT>seq_oss_debug</TT></LI>
-
-<BR>specifies the debug level and accepts zero (= no debug message) or
-positive integer. Default value is 0.</UL>
-
-<H2>
-6. Queue Mechanism</H2>
-OSS sequencer emulation uses an ALSA priority queue. The
-events from <TT>/dev/sequencer</TT> are processed and put onto the queue
-specified by module option.
-<P>All the events from <TT>/dev/sequencer</TT> are parsed at beginning.
-The timing events are also parsed at this moment, so that the events may
-be processed in real-time. Sending an event ABSTIME 0 switches the operation
-mode to real-time mode, and sending an event RELTIME 0 switches it off.
-In the real-time mode, all events are dispatched immediately.
-<P>The queued events are dispatched to the corresponding ALSA sequencer
-ports after scheduled time by ALSA sequencer dispatcher.
-<P>If the write-queue is full, the application sleeps until a certain amount
-(as default one half) becomes empty in blocking mode. The synchronization
-to write timing was implemented, too.
-<P>The input from MIDI devices or echo-back events are stored on read FIFO
-queue. If application reads <TT>/dev/sequencer</TT> in blocking mode, the
-process will be awaked.
-
-<H2>
-7. Interface to Synthesizer Device</H2>
-
-<H3>
-7.1. Registration</H3>
-To register an OSS synthesizer device, use <TT>snd_seq_oss_synth_register</TT>
-function.
-<PRE>int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_oss_callback_t *oper, void *private_data)</PRE>
-The arguments <TT>name</TT>, <TT>type</TT>, <TT>subtype</TT> and
-<TT>nvoices</TT>
-are used for making the appropriate synth_info structure for ioctl. The
-return value is an index number of this device. This index must be remembered
-for unregister. If registration is failed, -errno will be returned.
-<P>To release this device, call <TT>snd_seq_oss_synth_unregister function</TT>:
-<PRE>int snd_seq_oss_synth_unregister(int index),</PRE>
-where the <TT>index</TT> is the index number returned by register function.
-<H3>
-7.2. Callbacks</H3>
-OSS synthesizer devices have capability for sample downloading and ioctls
-like sample reset. In OSS emulation, these special features are realized
-by using callbacks. The registration argument oper is used to specify these
-callbacks. The following callback functions must be defined:
-<PRE>snd_seq_oss_callback_t:
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*open)(snd_seq_oss_arg_t *p, void *closure);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*close)(snd_seq_oss_arg_t *p);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*reset)(snd_seq_oss_arg_t *p);
-Except for <TT>open</TT> and <TT>close</TT> callbacks, they are allowed
-to be NULL.
-<P>Each callback function takes the argument type snd_seq_oss_arg_t as the
-first argument.
-<PRE>struct snd_seq_oss_arg_t {
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int app_index;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int file_mode;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int seq_mode;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_addr_t addr;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *private_data;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int event_passing;
-};</PRE>
-The first three fields, <TT>app_index</TT>, <TT>file_mode</TT> and
-<TT>seq_mode</TT>
-are initialized by OSS sequencer. The <TT>app_index</TT> is the application
-index which is unique to each application opening OSS sequencer. The
-<TT>file_mode</TT>
-is bit-flags indicating the file operation mode. See
-<TT>seq_oss.h</TT>
-for its meaning. The <TT>seq_mode</TT> is sequencer operation mode. In
-the current version, only <TT>SND_OSSSEQ_MODE_SYNTH</TT> is used.
-<P>The next two fields, <TT>addr</TT> and <TT>private_data</TT>, must be
-filled by the synth driver at open callback. The <TT>addr</TT> contains
-the address of ALSA sequencer port which is assigned to this device. If
-the driver allocates memory for <TT>private_data</TT>, it must be released
-in close callback by itself.
-<P>The last field, <TT>event_passing</TT>, indicates how to translate note-on
-/ off events. In <TT>PROCESS_EVENTS</TT> mode, the note 255 is regarded
-as velocity change, and key pressure event is passed to the port. In <TT>PASS_EVENTS</TT>
-mode, all note on/off events are passed to the port without modified. <TT>PROCESS_KEYPRESS</TT>
-mode checks the note above 128 and regards it as key pressure event (mainly
-for Emu8000 driver).
-<H4>
-7.2.1. Open Callback</H4>
-The <TT>open</TT> is called at each time this device is opened by an application
-using OSS sequencer. This must not be NULL. Typically, the open callback
-does the following procedure:
-<OL>
-<LI>
-Allocate private data record.</LI>
-
-<LI>
-Create an ALSA sequencer port.</LI>
-
-<LI>
-Set the new port address on arg->addr.</LI>
-
-<LI>
-Set the private data record pointer on arg->private_data.</LI>
-</OL>
-Note that the type bit-flags in port_info of this synth port must NOT contain
-<TT>TYPE_MIDI_GENERIC</TT>
-bit. Instead, <TT>TYPE_SPECIFIC</TT> should be used. Also, <TT>CAP_SUBSCRIPTION</TT>
-bit should NOT be included, too. This is necessary to tell it from other
-normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
-return -errno.
-<H4>
-7.2.2 Ioctl Callback</H4>
-The <TT>ioctl</TT> callback is called when the sequencer receives device-specific
-ioctls. The following two ioctls should be processed by this callback:
-<UL>
-<LI>
-<TT>IOCTL_SEQ_RESET_SAMPLES</TT></LI>
-
-<BR>reset all samples on memory -- return 0
-<LI>
-<TT>IOCTL_SYNTH_MEMAVL</TT></LI>
-
-<BR>return the available memory size
-<LI>
-<TT>FM_4OP_ENABLE</TT></LI>
-
-<BR>can be ignored usually</UL>
-The other ioctls are processed inside the sequencer without passing to
-the lowlevel driver.
-<H4>
-7.2.3 Load_Patch Callback</H4>
-The <TT>load_patch</TT> callback is used for sample-downloading. This callback
-must read the data on user-space and transfer to each device. Return 0
-if succeeded, and -errno if failed. The format argument is the patch key
-in patch_info record. The buf is user-space pointer where patch_info record
-is stored. The offs can be ignored. The count is total data size of this
-sample data.
-<H4>
-7.2.4 Close Callback</H4>
-The <TT>close</TT> callback is called when this device is closed by the
-application. If any private data was allocated in open callback, it must
-be released in the close callback. The deletion of ALSA port should be
-done here, too. This callback must not be NULL.
-<H4>
-7.2.5 Reset Callback</H4>
-The <TT>reset</TT> callback is called when sequencer device is reset or
-closed by applications. The callback should turn off the sounds on the
-relevant port immediately, and initialize the status of the port. If this
-callback is undefined, OSS seq sends a <TT>HEARTBEAT</TT> event to the
-port.
-<H3>
-7.3 Events</H3>
-Most of the events are processed by sequencer and translated to the adequate
-ALSA sequencer events, so that each synth device can receive by input_event
-callback of ALSA sequencer port. The following ALSA events should be implemented
-by the driver:
-<BR>&nbsp;
-<TABLE BORDER WIDTH="75%" NOSAVE >
-<TR NOSAVE>
-<TD NOSAVE><B>ALSA event</B></TD>
-
-<TD><B>Original OSS events</B></TD>
-</TR>
-
-<TR>
-<TD>NOTEON</TD>
-
-<TD>SEQ_NOTEON
-<BR>MIDI_NOTEON</TD>
-</TR>
-
-<TR>
-<TD>NOTE</TD>
-
-<TD>SEQ_NOTEOFF
-<BR>MIDI_NOTEOFF</TD>
-</TR>
-
-<TR NOSAVE>
-<TD NOSAVE>KEYPRESS</TD>
-
-<TD>MIDI_KEY_PRESSURE</TD>
-</TR>
-
-<TR NOSAVE>
-<TD>CHANPRESS</TD>
-
-<TD NOSAVE>SEQ_AFTERTOUCH
-<BR>MIDI_CHN_PRESSURE</TD>
-</TR>
-
-<TR NOSAVE>
-<TD NOSAVE>PGMCHANGE</TD>
-
-<TD NOSAVE>SEQ_PGMCHANGE
-<BR>MIDI_PGM_CHANGE</TD>
-</TR>
-
-<TR>
-<TD>PITCHBEND</TD>
-
-<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER)
-<BR>MIDI_PITCH_BEND</TD>
-</TR>
-
-<TR>
-<TD>CONTROLLER</TD>
-
-<TD>MIDI_CTL_CHANGE
-<BR>SEQ_BALANCE (with CTL_PAN)</TD>
-</TR>
-
-<TR>
-<TD>CONTROL14</TD>
-
-<TD>SEQ_CONTROLLER</TD>
-</TR>
-
-<TR>
-<TD>REGPARAM</TD>
-
-<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)</TD>
-</TR>
-
-<TR>
-<TD>SYSEX</TD>
-
-<TD>SEQ_SYSEX</TD>
-</TR>
-</TABLE>
-
-<P>The most of these behavior can be realized by MIDI emulation driver
-included in the Emu8000 lowlevel driver. In the future release, this module
-will be independent.
-<P>Some OSS events (<TT>SEQ_PRIVATE</TT> and <TT>SEQ_VOLUME</TT> events) are passed as event
-type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
-packets without any modification. The lowlevel driver should process these
-events appropriately.
-<H2>
-8. Interface to MIDI Device</H2>
-Since the OSS emulation probes the creation and deletion of ALSA MIDI sequencer
-ports automatically by receiving announcement from ALSA sequencer, the
-MIDI devices don't need to be registered explicitly like synth devices.
-However, the MIDI port_info registered to ALSA sequencer must include a group
-name <TT>SND_SEQ_GROUP_DEVICE</TT> and a capability-bit <TT>CAP_READ</TT> or
-<TT>CAP_WRITE</TT>. Also, subscription capabilities, <TT>CAP_SUBS_READ</TT> or <TT>CAP_SUBS_WRITE</TT>,
-must be defined, too. If these conditions are not satisfied, the port is not
-registered as OSS sequencer MIDI device.
-<P>The events via MIDI devices are parsed in OSS sequencer and converted
-to the corresponding ALSA sequencer events. The input from MIDI sequencer
-is also converted to MIDI byte events by OSS sequencer. This works just
-a reverse way of seq_midi module.
-<H2>
-9. Known Problems / TODO's</H2>
-
-<UL>
-<LI>
-Patch loading via ALSA instrument layer is not implemented yet.</LI>
-</UL>
-
-</BODY>
-</HTML>
diff --git a/Documentation/sound/alsa/Audigy-mixer.txt b/Documentation/sound/cards/audigy-mixer.rst
index 7f10dc6ff28c..86213234435f 100644
--- a/Documentation/sound/alsa/Audigy-mixer.txt
+++ b/Documentation/sound/cards/audigy-mixer.rst
@@ -1,8 +1,8 @@
+=============================================
+Sound Blaster Audigy mixer / default DSP code
+=============================================
- Sound Blaster Audigy mixer / default DSP code
- ===========================================
-
-This is based on SB-Live-mixer.txt.
+This is based on sb-live-mixer.rst.
The EMU10K2 chips have a DSP part which can be programmed to support
various ways of sample processing, which is described here.
@@ -13,8 +13,8 @@ The ALSA driver programs this portion of chip by default code
(can be altered later) which offers the following functionality:
-1) Digital mixer controls
--------------------------
+Digital mixer controls
+======================
These controls are built using the DSP instructions. They offer extended
functionality. Only the default build-in code in the ALSA driver is described
@@ -26,320 +26,343 @@ is mentioned in multiple controls, the signal is accumulated and can be wrapped
Explanation of used abbreviations:
-DAC - digital to analog converter
-ADC - analog to digital converter
-I2S - one-way three wire serial bus for digital sound by Philips Semiconductors
- (this standard is used for connecting standalone DAC and ADC converters)
-LFE - low frequency effects (subwoofer signal)
-AC97 - a chip containing an analog mixer, DAC and ADC converters
-IEC958 - S/PDIF
-FX-bus - the EMU10K2 chip has an effect bus containing 64 accumulators.
- Each of the synthesizer voices can feed its output to these accumulators
- and the DSP microcontroller can operate with the resulting sum.
+DAC
+ digital to analog converter
+ADC
+ analog to digital converter
+I2S
+ one-way three wire serial bus for digital sound by Philips Semiconductors
+ (this standard is used for connecting standalone DAC and ADC converters)
+LFE
+ low frequency effects (subwoofer signal)
+AC97
+ a chip containing an analog mixer, DAC and ADC converters
+IEC958
+ S/PDIF
+FX-bus
+ the EMU10K2 chip has an effect bus containing 64 accumulators.
+ Each of the synthesizer voices can feed its output to these accumulators
+ and the DSP microcontroller can operate with the resulting sum.
name='PCM Front Playback Volume',index=0
-
+----------------------------------------
This control is used to attenuate samples for left and right front PCM FX-bus
accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM
samples for 5.1 playback. The result samples are forwarded to the front DAC PCM
slots of the Philips DAC.
name='PCM Surround Playback Volume',index=0
-
+-------------------------------------------
This control is used to attenuate samples for left and right surround PCM FX-bus
accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM
samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM
slots of the Philips DAC.
name='PCM Center Playback Volume',index=0
-
+-----------------------------------------
This control is used to attenuate samples for center PCM FX-bus accumulator.
ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample
is forwarded to the center DAC PCM slot of the Philips DAC.
name='PCM LFE Playback Volume',index=0
-
+--------------------------------------
This control is used to attenuate sample for LFE PCM FX-bus accumulator.
ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample
is forwarded to the LFE DAC PCM slot of the Philips DAC.
name='PCM Playback Volume',index=0
-
+----------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
stereo playback. The result samples are forwarded to the front DAC PCM slots
of the Philips DAC.
name='PCM Capture Volume',index=0
-
+---------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
name='Music Playback Volume',index=0
-
+------------------------------------
This control is used to attenuate samples for left and right MIDI FX-bus
accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
name='Music Capture Volume',index=0
-
+-----------------------------------
These controls are used to attenuate samples for left and right MIDI FX-bus
accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
name='Mic Playback Volume',index=0
-
+----------------------------------
This control is used to attenuate samples for left and right Mic input.
For Mic input is used AC97 codec. The result samples are forwarded to
the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic
capture FIFO (device 1 - 16bit/8KHz mono) too without volume control.
name='Mic Capture Volume',index=0
-
+---------------------------------
This control is used to attenuate samples for left and right Mic input.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
name='Audigy CD Playback Volume',index=0
-
+----------------------------------------
This control is used to attenuate samples from left and right IEC958 TTL
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the front DAC PCM slots of the Philips DAC.
name='Audigy CD Capture Volume',index=0
-
+---------------------------------------
This control is used to attenuate samples from left and right IEC958 TTL
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
name='IEC958 Optical Playback Volume',index=0
-
+---------------------------------------------
This control is used to attenuate samples from left and right IEC958 optical
digital input. The result samples are forwarded to the front DAC PCM slots
of the Philips DAC.
name='IEC958 Optical Capture Volume',index=0
-
+--------------------------------------------
This control is used to attenuate samples from left and right IEC958 optical
digital inputs. The result samples are forwarded to the ADC capture FIFO
(thus to the standard capture PCM device).
name='Line2 Playback Volume',index=0
-
+------------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the AudigyDrive). The result samples are forwarded to the front
DAC PCM slots of the Philips DAC.
name='Line2 Capture Volume',index=1
-
+-----------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the AudigyDrive). The result samples are forwarded to the ADC
capture FIFO (thus to the standard capture PCM device).
name='Analog Mix Playback Volume',index=0
-
+-----------------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs from Philips ADC. The result samples are forwarded to the front
DAC PCM slots of the Philips DAC. This contains mix from analog sources
like CD, Line In, Aux, ....
name='Analog Mix Capture Volume',index=1
-
+----------------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs Philips ADC. The result samples are forwarded to the ADC
capture FIFO (thus to the standard capture PCM device).
name='Aux2 Playback Volume',index=0
-
+-----------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the AudigyDrive). The result samples are forwarded to the front
DAC PCM slots of the Philips DAC.
name='Aux2 Capture Volume',index=1
-
+----------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the AudigyDrive). The result samples are forwarded to the ADC
capture FIFO (thus to the standard capture PCM device).
name='Front Playback Volume',index=0
-
+------------------------------------
All stereo signals are mixed together and mirrored to surround, center and LFE.
This control is used to attenuate samples for left and right front speakers of
this mix.
name='Surround Playback Volume',index=0
-
+---------------------------------------
All stereo signals are mixed together and mirrored to surround, center and LFE.
This control is used to attenuate samples for left and right surround speakers of
this mix.
name='Center Playback Volume',index=0
-
+-------------------------------------
All stereo signals are mixed together and mirrored to surround, center and LFE.
This control is used to attenuate sample for center speaker of this mix.
name='LFE Playback Volume',index=0
-
+----------------------------------
All stereo signals are mixed together and mirrored to surround, center and LFE.
This control is used to attenuate sample for LFE speaker of this mix.
name='Tone Control - Switch',index=0
-
+------------------------------------
This control turns the tone control on or off. The samples for front, rear
and center / LFE outputs are affected.
name='Tone Control - Bass',index=0
-
+----------------------------------
This control sets the bass intensity. There is no neutral value!!
When the tone control code is activated, the samples are always modified.
The closest value to pure signal is 20.
name='Tone Control - Treble',index=0
-
+------------------------------------
This control sets the treble intensity. There is no neutral value!!
When the tone control code is activated, the samples are always modified.
The closest value to pure signal is 20.
name='Master Playback Volume',index=0
-
+-------------------------------------
This control is used to attenuate samples for front, surround, center and
LFE outputs.
name='IEC958 Optical Raw Playback Switch',index=0
-
+-------------------------------------------------
If this switch is on, then the samples for the IEC958 (S/PDIF) digital
output are taken only from the raw FX8010 PCM, otherwise standard front
PCM samples are taken.
-2) PCM stream related controls
-------------------------------
+PCM stream related controls
+===========================
name='EMU10K1 PCM Volume',index 0-31
-
+------------------------------------
Channel volume attenuation in range 0-0xffff. The maximum value (no
attenuation) is default. The channel mapping for three values is
as follows:
- 0 - mono, default 0xffff (no attenuation)
- 1 - left, default 0xffff (no attenuation)
- 2 - right, default 0xffff (no attenuation)
+* 0 - mono, default 0xffff (no attenuation)
+* 1 - left, default 0xffff (no attenuation)
+* 2 - right, default 0xffff (no attenuation)
name='EMU10K1 PCM Send Routing',index 0-31
-
+------------------------------------------
This control specifies the destination - FX-bus accumulators. There 24
values with this mapping:
- 0 - mono, A destination (FX-bus 0-63), default 0
- 1 - mono, B destination (FX-bus 0-63), default 1
- 2 - mono, C destination (FX-bus 0-63), default 2
- 3 - mono, D destination (FX-bus 0-63), default 3
- 4 - mono, E destination (FX-bus 0-63), default 0
- 5 - mono, F destination (FX-bus 0-63), default 0
- 6 - mono, G destination (FX-bus 0-63), default 0
- 7 - mono, H destination (FX-bus 0-63), default 0
- 8 - left, A destination (FX-bus 0-63), default 0
- 9 - left, B destination (FX-bus 0-63), default 1
- 10 - left, C destination (FX-bus 0-63), default 2
- 11 - left, D destination (FX-bus 0-63), default 3
- 12 - left, E destination (FX-bus 0-63), default 0
- 13 - left, F destination (FX-bus 0-63), default 0
- 14 - left, G destination (FX-bus 0-63), default 0
- 15 - left, H destination (FX-bus 0-63), default 0
- 16 - right, A destination (FX-bus 0-63), default 0
- 17 - right, B destination (FX-bus 0-63), default 1
- 18 - right, C destination (FX-bus 0-63), default 2
- 19 - right, D destination (FX-bus 0-63), default 3
- 20 - right, E destination (FX-bus 0-63), default 0
- 21 - right, F destination (FX-bus 0-63), default 0
- 22 - right, G destination (FX-bus 0-63), default 0
- 23 - right, H destination (FX-bus 0-63), default 0
+* 0 - mono, A destination (FX-bus 0-63), default 0
+* 1 - mono, B destination (FX-bus 0-63), default 1
+* 2 - mono, C destination (FX-bus 0-63), default 2
+* 3 - mono, D destination (FX-bus 0-63), default 3
+* 4 - mono, E destination (FX-bus 0-63), default 0
+* 5 - mono, F destination (FX-bus 0-63), default 0
+* 6 - mono, G destination (FX-bus 0-63), default 0
+* 7 - mono, H destination (FX-bus 0-63), default 0
+* 8 - left, A destination (FX-bus 0-63), default 0
+* 9 - left, B destination (FX-bus 0-63), default 1
+* 10 - left, C destination (FX-bus 0-63), default 2
+* 11 - left, D destination (FX-bus 0-63), default 3
+* 12 - left, E destination (FX-bus 0-63), default 0
+* 13 - left, F destination (FX-bus 0-63), default 0
+* 14 - left, G destination (FX-bus 0-63), default 0
+* 15 - left, H destination (FX-bus 0-63), default 0
+* 16 - right, A destination (FX-bus 0-63), default 0
+* 17 - right, B destination (FX-bus 0-63), default 1
+* 18 - right, C destination (FX-bus 0-63), default 2
+* 19 - right, D destination (FX-bus 0-63), default 3
+* 20 - right, E destination (FX-bus 0-63), default 0
+* 21 - right, F destination (FX-bus 0-63), default 0
+* 22 - right, G destination (FX-bus 0-63), default 0
+* 23 - right, H destination (FX-bus 0-63), default 0
Don't forget that it's illegal to assign a channel to the same FX-bus accumulator
more than once (it means 0=0 && 1=0 is an invalid combination).
name='EMU10K1 PCM Send Volume',index 0-31
-
+-----------------------------------------
It specifies the attenuation (amount) for given destination in range 0-255.
The channel mapping is following:
- 0 - mono, A destination attn, default 255 (no attenuation)
- 1 - mono, B destination attn, default 255 (no attenuation)
- 2 - mono, C destination attn, default 0 (mute)
- 3 - mono, D destination attn, default 0 (mute)
- 4 - mono, E destination attn, default 0 (mute)
- 5 - mono, F destination attn, default 0 (mute)
- 6 - mono, G destination attn, default 0 (mute)
- 7 - mono, H destination attn, default 0 (mute)
- 8 - left, A destination attn, default 255 (no attenuation)
- 9 - left, B destination attn, default 0 (mute)
- 10 - left, C destination attn, default 0 (mute)
- 11 - left, D destination attn, default 0 (mute)
- 12 - left, E destination attn, default 0 (mute)
- 13 - left, F destination attn, default 0 (mute)
- 14 - left, G destination attn, default 0 (mute)
- 15 - left, H destination attn, default 0 (mute)
- 16 - right, A destination attn, default 0 (mute)
- 17 - right, B destination attn, default 255 (no attenuation)
- 18 - right, C destination attn, default 0 (mute)
- 19 - right, D destination attn, default 0 (mute)
- 20 - right, E destination attn, default 0 (mute)
- 21 - right, F destination attn, default 0 (mute)
- 22 - right, G destination attn, default 0 (mute)
- 23 - right, H destination attn, default 0 (mute)
-
-
-
-4) MANUALS/PATENTS:
--------------------
+* 0 - mono, A destination attn, default 255 (no attenuation)
+* 1 - mono, B destination attn, default 255 (no attenuation)
+* 2 - mono, C destination attn, default 0 (mute)
+* 3 - mono, D destination attn, default 0 (mute)
+* 4 - mono, E destination attn, default 0 (mute)
+* 5 - mono, F destination attn, default 0 (mute)
+* 6 - mono, G destination attn, default 0 (mute)
+* 7 - mono, H destination attn, default 0 (mute)
+* 8 - left, A destination attn, default 255 (no attenuation)
+* 9 - left, B destination attn, default 0 (mute)
+* 10 - left, C destination attn, default 0 (mute)
+* 11 - left, D destination attn, default 0 (mute)
+* 12 - left, E destination attn, default 0 (mute)
+* 13 - left, F destination attn, default 0 (mute)
+* 14 - left, G destination attn, default 0 (mute)
+* 15 - left, H destination attn, default 0 (mute)
+* 16 - right, A destination attn, default 0 (mute)
+* 17 - right, B destination attn, default 255 (no attenuation)
+* 18 - right, C destination attn, default 0 (mute)
+* 19 - right, D destination attn, default 0 (mute)
+* 20 - right, E destination attn, default 0 (mute)
+* 21 - right, F destination attn, default 0 (mute)
+* 22 - right, G destination attn, default 0 (mute)
+* 23 - right, H destination attn, default 0 (mute)
+
+
+
+MANUALS/PATENTS
+===============
ftp://opensource.creative.com/pub/doc
-------------------------------------
- Files:
- LM4545.pdf AC97 Codec
+LM4545.pdf
+ AC97 Codec
- m2049.pdf The EMU10K1 Digital Audio Processor
+m2049.pdf
+ The EMU10K1 Digital Audio Processor
- hog63.ps FX8010 - A DSP Chip Architecture for Audio Effects
+hog63.ps
+ FX8010 - A DSP Chip Architecture for Audio Effects
WIPO Patents
------------
- Patent numbers:
- WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
- streams
- WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+WO 9901813 (A1)
+ Audio Effects Processor with multiple asynchronous streams
+ (Jan. 14, 1999)
+
+WO 9901814 (A1)
+ Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
- WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
- Execution and Audio Data Sequencing (Jan. 14, 1999)
+WO 9901953 (A1)
+ Audio Effects Processor having Decoupled Instruction
+ Execution and Audio Data Sequencing (Jan. 14, 1999)
US Patents (http://www.uspto.gov/)
----------------------------------
- US 5925841 Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
-
- US 5928342 Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
- with a multiport memory onto which multiple asynchronous
- digital sound samples can be concurrently loaded
-
- US 5930158 Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
-
- US 6032235 Memory initialization circuit (Tram) (Feb. 29, 2000)
-
- US 6138207 Interpolation looping of audio samples in cache connected to (Oct. 24, 2000)
- system bus with prioritization and modification of bus transfers
- in accordance with loop ends and minimum block sizes
-
- US 6151670 Method for conserving memory storage using a (Nov. 21, 2000)
- pool of short term memory registers
-
- US 6195715 Interrupt control for multiple programs communicating with (Feb. 27, 2001)
- a common interrupt by associating programs to GP registers,
- defining interrupt register, polling GP registers, and invoking
- callback routine associated with defined interrupt register
+US 5925841
+ Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+US 5928342
+ Audio Effects Processor integrated on a single chip
+ with a multiport memory onto which multiple asynchronous
+ digital sound samples can be concurrently loaded
+ (Jul. 27, 1999)
+
+US 5930158
+ Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+US 6032235
+ Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+US 6138207
+ Interpolation looping of audio samples in cache connected to
+ system bus with prioritization and modification of bus transfers
+ in accordance with loop ends and minimum block sizes
+ (Oct. 24, 2000)
+
+US 6151670
+ Method for conserving memory storage using a
+ pool of short term memory registers
+ (Nov. 21, 2000)
+
+US 6195715
+ Interrupt control for multiple programs communicating with
+ a common interrupt by associating programs to GP registers,
+ defining interrupt register, polling GP registers, and invoking
+ callback routine associated with defined interrupt register
+ (Feb. 27, 2001)
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/cards/audiophile-usb.rst
index e7a5ed4dcae8..a7bb5648331f 100644
--- a/Documentation/sound/alsa/Audiophile-Usb.txt
+++ b/Documentation/sound/cards/audiophile-usb.rst
@@ -1,32 +1,41 @@
- Guide to using M-Audio Audiophile USB with ALSA and Jack v1.5
- ========================================================
+========================================================
+Guide to using M-Audio Audiophile USB with ALSA and Jack
+========================================================
- Thibault Le Meur <Thibault.LeMeur@supelec.fr>
+v1.5
+
+Thibault Le Meur <Thibault.LeMeur@supelec.fr>
This document is a guide to using the M-Audio Audiophile USB (tm) device with
ALSA and JACK.
History
=======
+
* v1.4 - Thibault Le Meur (2007-07-11)
- - Added Low Endianness nature of 16bits-modes
- found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se>
- - Modifying document structure
+
+ - Added Low Endianness nature of 16bits-modes
+ found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se>
+ - Modifying document structure
+
* v1.5 - Thibault Le Meur (2007-07-12)
- - Added AC3/DTS passthru info
+ - Added AC3/DTS passthru info
-1 - Audiophile USB Specs and correct usage
-==========================================
+Audiophile USB Specs and correct usage
+======================================
This part is a reminder of important facts about the functions and limitations
of the device.
The device has 4 audio interfaces, and 2 MIDI ports:
+
* Analog Stereo Input (Ai)
+
- This port supports 2 pairs of line-level audio inputs (1/4" TS and RCA)
- When the 1/4" TS (jack) connectors are connected, the RCA connectors
are disabled
+
* Analog Stereo Output (Ao)
* Digital Stereo Input (Di)
* Digital Stereo Output (Do)
@@ -34,56 +43,69 @@ The device has 4 audio interfaces, and 2 MIDI ports:
* Midi Out (Mo)
The internal DAC/ADC has the following characteristics:
+
* sample depth of 16 or 24 bits
* sample rate from 8kHz to 96kHz
* Two interfaces can't use different sample depths at the same time.
+
Moreover, the Audiophile USB documentation gives the following Warning:
-"Please exit any audio application running before switching between bit depths"
+ Please exit any audio application running before switching between bit depths
Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be
activated at the same time depending on the audio mode selected:
+
* 16-bit/48kHz ==> 4 channels in + 4 channels out
+
- Ai+Ao+Di+Do
+
* 24-bit/48kHz ==> 4 channels in + 2 channels out,
- or 2 channels in + 4 channels out
+ or 2 channels in + 4 channels out
+
- Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do
+
* 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only)
+
- Ai or Ao or Di or Do
Important facts about the Digital interface:
--------------------------------------------
+
* The Do port additionally supports surround-encoded AC-3 and DTS passthrough,
-though I haven't tested it under Linux
+ though I haven't tested it under Linux
+
- Note that in this setup only the Do interface can be enabled
+
* Apart from recording an audio digital stream, enabling the Di port is a way
-to synchronize the device to an external sample clock
+ to synchronize the device to an external sample clock
+
- As a consequence, the Di port must be enable only if an active Digital
-source is connected
+ source is connected
- Enabling Di when no digital source is connected can result in a
-synchronization error (for instance sound played at an odd sample rate)
+ synchronization error (for instance sound played at an odd sample rate)
-2 - Audiophile USB MIDI support in ALSA
-=======================================
+Audiophile USB MIDI support in ALSA
+===================================
The Audiophile USB MIDI ports will be automatically supported once the
following modules have been loaded:
+
* snd-usb-audio
* snd-seq-midi
No additional setting is required.
-3 - Audiophile USB Audio support in ALSA
-========================================
+Audiophile USB Audio support in ALSA
+====================================
Audio functions of the Audiophile USB device are handled by the snd-usb-audio
module. This module can work in a default mode (without any device-specific
parameter), or in an "advanced" mode with the device-specific parameter called
-"device_setup".
+``device_setup``.
-3.1 - Default Alsa driver mode
-------------------------------
+Default Alsa driver mode
+------------------------
The default behavior of the snd-usb-audio driver is to list the device
capabilities at startup and activate the required mode when required
@@ -101,6 +123,7 @@ Default Alsa driver mode can lead to device misconfigurations.
Let's get back to the Default Alsa driver mode for now. In this case the
Audiophile interfaces are mapped to alsa pcm devices in the following
way (I suppose the device's index is 1):
+
* hw:1,0 is Ao in playback and Di in capture
* hw:1,1 is Do in playback and Ai in capture
* hw:1,2 is Do in AC3/DTS passthrough mode
@@ -115,20 +138,28 @@ This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface
is reported to be big endian in this default driver mode.
Examples:
- * playing a S24_3BE encoded raw file to the Ao port
+
+ * playing a S24_3BE encoded raw file to the Ao port::
+
% aplay -D hw:1,0 -c2 -t raw -r48000 -fS24_3BE test.raw
- * recording a S24_3BE encoded raw file from the Ai port
+
+ * recording a S24_3BE encoded raw file from the Ai port::
+
% arecord -D hw:1,1 -c2 -t raw -r48000 -fS24_3BE test.raw
- * playing a S16_BE encoded raw file to the Do port
+
+ * playing a S16_BE encoded raw file to the Do port::
+
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
- * playing an ac3 sample file to the Do port
+
+ * playing an ac3 sample file to the Do port::
+
% aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
If you're happy with the default Alsa driver mode and don't experience any
issue with this mode, then you can skip the following chapter.
-3.2 - Advanced module setup
----------------------------
+Advanced module setup
+---------------------
Due to the hardware constraints described above, the device initialization made
by the Alsa driver in default mode may result in a corrupted state of the
@@ -137,34 +168,39 @@ from the Ai interface sounds distorted (as if boosted with an excessive high
volume gain).
For people having this problem, the snd-usb-audio module has a new module
-parameter called "device_setup" (this parameter was introduced in kernel
+parameter called ``device_setup`` (this parameter was introduced in kernel
release 2.6.17)
-3.2.1 - Initializing the working mode of the Audiophile USB
+Initializing the working mode of the Audiophile USB
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As far as the Audiophile USB device is concerned, this value let the user
specify:
+
* the sample depth
* the sample rate
* whether the Di port is used or not
-When initialized with "device_setup=0x00", the snd-usb-audio module has
+When initialized with ``device_setup=0x00``, the snd-usb-audio module has
the same behaviour as when the parameter is omitted (see paragraph "Default
Alsa driver mode" above)
Others modes are described in the following subsections.
-3.2.1.1 - 16-bit modes
+16-bit modes
+~~~~~~~~~~~~
The two supported modes are:
- * device_setup=0x01
+ * ``device_setup=0x01``
+
- 16bits 48kHz mode with Di disabled
- Ai,Ao,Do can be used at the same time
- hw:1,0 is not available in capture mode
- hw:1,2 is not available
- * device_setup=0x11
+ * ``device_setup=0x11``
+
- 16bits 48kHz mode with Di enabled
- Ai,Ao,Di,Do can be used at the same time
- hw:1,0 is available in capture mode
@@ -173,33 +209,43 @@ The two supported modes are:
In this modes the device operates only at 16bits-modes. Before kernel 2.6.23,
the devices where reported to be Big-Endian when in fact they were Little-Endian
so that playing a file was a matter of using:
+::
+
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw
+
where "test_S16_LE.raw" was in fact a little-endian sample file.
Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in
these modes) a fix has been committed (expected in kernel 2.6.23) and
Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as
using:
+::
+
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw
-3.2.1.2 - 24-bit modes
+
+24-bit modes
+~~~~~~~~~~~~
The three supported modes are:
- * device_setup=0x09
+ * ``device_setup=0x09``
+
- 24bits 48kHz mode with Di disabled
- Ai,Ao,Do can be used at the same time
- hw:1,0 is not available in capture mode
- hw:1,2 is not available
- * device_setup=0x19
+ * ``device_setup=0x19``
+
- 24bits 48kHz mode with Di enabled
- 3 ports from {Ai,Ao,Di,Do} can be used at the same time
- hw:1,0 is available in capture mode and an active digital source must be
connected to Di
- hw:1,2 is not available
- * device_setup=0x0D or 0x10
+ * ``device_setup=0x0D`` or ``0x10``
+
- 24bits 96kHz mode
- Di is enabled by default for this mode but does not need to be connected
to an active source
@@ -210,29 +256,35 @@ The three supported modes are:
In these modes the device is only Big-Endian compliant (see "Default Alsa driver
mode" above for an aplay command example)
-3.2.1.3 - AC3 w/ DTS passthru mode
+AC3 w/ DTS passthru mode
+~~~~~~~~~~~~~~~~~~~~~~~~
Thanks to Hakan Lennestal, I now have a report saying that this mode works.
- * device_setup=0x03
+ * ``device_setup=0x03``
+
- 16bits 48kHz mode with only the Do port enabled
- AC3 with DTS passthru
- Caution with this setup the Do port is mapped to the pcm device hw:1,0
The command line used to playback the AC3/DTS encoded .wav-files in this mode:
+::
+
% aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw
-3.2.2 - How to use the device_setup parameter
-----------------------------------------------
+How to use the ``device_setup`` parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The parameter can be given:
- * By manually probing the device (as root):
+ * By manually probing the device (as root):::
+
# modprobe -r snd-usb-audio
# modprobe snd-usb-audio index=1 device_setup=0x09
* Or while configuring the modules options in your modules configuration file
- (typically a .conf file in /etc/modprobe.d/ directory:
+ (typically a .conf file in /etc/modprobe.d/ directory:::
+
alias snd-card-1 snd-usb-audio
options snd-usb-audio index=1 device_setup=0x09
@@ -250,26 +302,31 @@ CAUTION when initializing the device
* If you've correctly initialized the device in a valid mode and then want to switch
to another mode (possibly with another sample-depth), please use also the following
procedure:
+
- first turn off the device
- de-register the snd-usb-audio module (modprobe -r)
- change the device_setup parameter by changing the device_setup
- option in /etc/modprobe.d/*.conf
+ option in ``/etc/modprobe.d/*.conf``
- turn on the device
+
* A workaround for this last issue has been applied to kernel 2.6.23, but it may not
be enough to ensure the 'stability' of the device initialization.
-3.2.3 - Technical details for hackers
--------------------------------------
+Technical details for hackers
+-----------------------------
+
This section is for hackers, wanting to understand details about the device
internals and how Alsa supports it.
-3.2.3.1 - Audiophile USB's device_setup structure
+Audiophile USB's ``device_setup`` structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to understand the device_setup magic numbers for the Audiophile
USB, you need some very basic understanding of binary computation. However,
this is not required to use the parameter and you may skip this section.
The device_setup is one byte long and its structure is the following:
+::
+---+---+---+---+---+---+---+---+
| b7| b6| b5| b4| b3| b2| b1| b0|
@@ -278,38 +335,55 @@ The device_setup is one byte long and its structure is the following:
+---+---+---+---+---+---+---+---+
Where:
- * b0 is the "SET" bit
+
+ * b0 is the ``SET`` bit
+
- it MUST be set if device_setup is initialized
- * b1 is the "DTS" bit
+
+ * b1 is the ``DTS`` bit
+
- it is set only for Digital output with DTS/AC3
- this setup is not tested
+
* b2 is the Rate selection flag
- - When set to "1" the rate range is 48.1-96kHz
+
+ - When set to ``1`` the rate range is 48.1-96kHz
- Otherwise the sample rate range is 8-48kHz
+
* b3 is the bit depth selection flag
- - When set to "1" samples are 24bits long
+
+ - When set to ``1`` samples are 24bits long
- Otherwise they are 16bits long
- Note that b2 implies b3 as the 96kHz mode is only supported for 24 bits
samples
+
* b4 is the Digital input flag
- - When set to "1" the device assumes that an active digital source is
+
+ - When set to ``1`` the device assumes that an active digital source is
connected
- You shouldn't enable Di if no source is seen on the port (this leads to
synchronization issues)
- b4 is implied by b2 (since only one port is enabled at a time no synch
error can occur)
- * b5 to b7 are reserved for future uses, and must be set to "0"
+
+ * b5 to b7 are reserved for future uses, and must be set to ``0``
+
- might become Ao, Do, Ai, for b7, b6, b4 respectively
Caution:
+
* there is no check on the value you will give to device_setup
+
- for instance choosing 0x05 (16bits 96kHz) will fail back to 0x09 since
b2 implies b3. But _there_will_be_no_warning_ in /var/log/messages
+
* Hardware constraints due to the USB bus limitation aren't checked
+
- choosing b2 will prepare all interfaces for 24bits/96kHz but you'll
only be able to use one at the same time
-3.2.3.2 - USB implementation details for this device
+USB implementation details for this device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You may safely skip this section if you're not interested in driver
hacking.
@@ -319,46 +393,72 @@ data I got by usb-snooping the windows and Linux drivers.
The M-Audio Audiophile USB has 7 USB Interfaces:
a "USB interface":
+
* USB Interface nb.0
* USB Interface nb.1
+
- Audio Control function
+
* USB Interface nb.2
+
- Analog Output
+
* USB Interface nb.3
+
- Digital Output
+
* USB Interface nb.4
+
- Analog Input
+
* USB Interface nb.5
+
- Digital Input
+
* USB Interface nb.6
+
- MIDI interface compliant with the MIDIMAN quirk
Each interface has 5 altsettings (AltSet 1,2,3,4,5) except:
+
* Interface 3 (Digital Out) has an extra Alset nb.6
* Interface 5 (Digital In) does not have Alset nb.3 and 5
Here is a short description of the AltSettings capabilities:
- * AltSettings 1 corresponds to
+
+* AltSettings 1 corresponds to
+
- 24-bit depth, 48.1-96kHz sample mode
- Adaptive playback (Ao and Do), Synch capture (Ai), or Asynch capture (Di)
- * AltSettings 2 corresponds to
+
+* AltSettings 2 corresponds to
+
- 24-bit depth, 8-48kHz sample mode
- Asynch capture and playback (Ao,Ai,Do,Di)
- * AltSettings 3 corresponds to
+
+* AltSettings 3 corresponds to
+
- 24-bit depth, 8-48kHz sample mode
- Synch capture (Ai) and Adaptive playback (Ao,Do)
- * AltSettings 4 corresponds to
+
+* AltSettings 4 corresponds to
+
- 16-bit depth, 8-48kHz sample mode
- Asynch capture and playback (Ao,Ai,Do,Di)
- * AltSettings 5 corresponds to
+
+* AltSettings 5 corresponds to
+
- 16-bit depth, 8-48kHz sample mode
- Synch capture (Ai) and Adaptive playback (Ao,Do)
- * AltSettings 6 corresponds to
+
+* AltSettings 6 corresponds to
+
- 16-bit depth, 8-48kHz sample mode
- Synch playback (Do), audio format type III IEC1937_AC-3
In order to ensure a correct initialization of the device, the driver
-_must_know_ how the device will be used:
+*must* *know* how the device will be used:
+
* if DTS is chosen, only Interface 2 with AltSet nb.6 must be
registered
* if 96KHz only AltSets nb.1 of each interface must be selected
@@ -371,20 +471,21 @@ _must_know_ how the device will be used:
When device_setup is given as a parameter to the snd-usb-audio module, the
parse_audio_endpoints function uses a quirk called
-"audiophile_skip_setting_quirk" in order to prevent AltSettings not
+``audiophile_skip_setting_quirk`` in order to prevent AltSettings not
corresponding to device_setup from being registered in the driver.
-4 - Audiophile USB and Jack support
-===================================
+Audiophile USB and Jack support
+===============================
This section deals with support of the Audiophile USB device in Jack.
There are 2 main potential issues when using Jackd with the device:
+
* support for Big-Endian devices in 24-bit modes
* support for 4-in / 4-out channels
-4.1 - Direct support in Jackd
------------------------------
+Direct support in Jackd
+-----------------------
Jack supports big endian devices only in recent versions (thanks to
Andreas Steinmetz for his first big-endian patch). I can't remember
@@ -396,29 +497,35 @@ are now Little Endians ;-) ).
You can run jackd with the following command for playback with Ao and
record with Ai:
+::
+
% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
-4.2 - Using Alsa plughw
------------------------
+Using Alsa plughw
+-----------------
+
If you don't have a recent Jackd installed, you can downgrade to using
-the Alsa "plug" converter.
+the Alsa ``plug`` converter.
For instance here is one way to run Jack with 2 playback channels on Ao and 2
capture channels from Ai:
+::
+
% jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
However you may see the following warning message:
-"You appear to be using the ALSA software "plug" layer, probably a result of
-using the "default" ALSA device. This is less efficient than it could be.
-Consider using a hardware device instead rather than using the plug layer."
+ You appear to be using the ALSA software "plug" layer, probably a result of
+ using the "default" ALSA device. This is less efficient than it could be.
+ Consider using a hardware device instead rather than using the plug layer.
-4.3 - Getting 2 input and/or output interfaces in Jack
-------------------------------------------------------
+Getting 2 input and/or output interfaces in Jack
+------------------------------------------------
As you can see, starting the Jack server this way will only enable 1 stereo
input (Di or Ai) and 1 stereo output (Ao or Do).
This is due to the following restrictions:
+
* Jack can only open one capture device and one playback device at a time
* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
(and optionally hw:1,2)
@@ -432,6 +539,7 @@ It is related to another device (ice1712) but can be adapted to suit
the Audiophile USB.
Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
+
* Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page)
* (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
diff --git a/Documentation/sound/alsa/Bt87x.txt b/Documentation/sound/cards/bt87x.rst
index f158cde8b065..912732d3ef9e 100644
--- a/Documentation/sound/alsa/Bt87x.txt
+++ b/Documentation/sound/cards/bt87x.rst
@@ -1,18 +1,23 @@
+=================
+ALSA BT87x Driver
+=================
+
Intro
=====
You might have noticed that the bt878 grabber cards have actually
-_two_ PCI functions:
+*two* PCI functions:
+::
-$ lspci
-[ ... ]
-00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
-00:0a.1 Multimedia controller: Brooktree Corporation Bt878 (rev 02)
-[ ... ]
+ $ lspci
+ [ ... ]
+ 00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
+ 00:0a.1 Multimedia controller: Brooktree Corporation Bt878 (rev 02)
+ [ ... ]
The first does video, it is backward compatible to the bt848. The second
does audio. snd-bt87x is a driver for the second function. It's a sound
-driver which can be used for recording sound (and _only_ recording, no
+driver which can be used for recording sound (and *only* recording, no
playback). As most TV cards come with a short cable which can be plugged
into your sound card's line-in you probably don't need this driver if all
you want to do is just watching TV...
@@ -30,9 +35,9 @@ The driver is now stable. However, it doesn't know about many TV cards,
and it refuses to load for cards it doesn't know.
If the driver complains ("Unknown TV card found, the audio driver will
-not load"), you can specify the load_all=1 option to force the driver to
+not load"), you can specify the ``load_all=1`` option to force the driver to
try to use the audio capture function of your card. If the frequency of
-recorded data is not right, try to specify the digital_rate option with
+recorded data is not right, try to specify the ``digital_rate`` option with
other values than the default 32000 (often it's 44100 or 64000).
If you have an unknown card, please mail the ID and board name to
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/cards/cmipci.rst
index 4e36e6e809ca..9ea1de6ec4ce 100644
--- a/Documentation/sound/alsa/CMIPCI.txt
+++ b/Documentation/sound/cards/cmipci.rst
@@ -1,7 +1,8 @@
- Brief Notes on C-Media 8338/8738/8768/8770 Driver
- =================================================
+=================================================
+Brief Notes on C-Media 8338/8738/8768/8770 Driver
+=================================================
- Takashi Iwai <tiwai@suse.de>
+Takashi Iwai <tiwai@suse.de>
Front/Rear Multi-channel Playback
@@ -30,19 +31,20 @@ The rear output can be heard only when "Four Channel Mode" switch is
disabled. Otherwise no signal will be routed to the rear speakers.
As default it's turned on.
-*** WARNING ***
-When "Four Channel Mode" switch is off, the output from rear speakers
-will be FULL VOLUME regardless of Master and PCM volumes.
-This might damage your audio equipment. Please disconnect speakers
-before your turn off this switch.
-*** WARNING ***
+.. WARNING::
+ When "Four Channel Mode" switch is off, the output from rear speakers
+ will be FULL VOLUME regardless of Master and PCM volumes [#]_.
+ This might damage your audio equipment. Please disconnect speakers
+ before your turn off this switch.
-[ Well.. I once got the output with correct volume (i.e. same with the
+
+.. [#]
+ Well.. I once got the output with correct volume (i.e. same with the
front one) and was so excited. It was even with "Four Channel" bit
on and "double DAC" mode. Actually I could hear separate 4 channels
from front and rear speakers! But.. after reboot, all was gone.
It's a very pity that I didn't save the register dump at that
- time.. Maybe there is an unknown register to achieve this... ]
+ time.. Maybe there is an unknown register to achieve this...
If your card has an extra output jack for the rear output, the rear
playback should be routed there as default. If not, there is a
@@ -73,12 +75,14 @@ cannot operate with full-duplex.
The 4.0 and 5.1 modes are defined as the pcm "surround40" and "surround51"
in alsa-lib. For example, you can play a WAV file with 6 channels like
+::
% aplay -Dsurround51 sixchannels.wav
For programming the 4/6 channel playback, you need to specify the PCM
channels as you like and set the format S16LE. For example, for playback
with 4 channels,
+::
snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
// or mmap if you like
@@ -89,13 +93,15 @@ and use the interleaved 4 channel data.
There are some control switches affecting to the speaker connections:
-"Line-In Mode" - an enum control to change the behavior of line-in
+Line-In Mode
+ an enum control to change the behavior of line-in
jack. Either "Line-In", "Rear Output" or "Bass Output" can
be selected. The last item is available only with model 039
or newer.
When "Rear Output" is chosen, the surround channels 3 and 4
are output to line-in jack.
-"Mic-In Mode" - an enum control to change the behavior of mic-in
+Mic-In Mode
+ an enum control to change the behavior of mic-in
jack. Either "Mic-In" or "Center/LFE Output" can be
selected.
When "Center/LFE Output" is chosen, the center and bass
@@ -111,11 +117,14 @@ The SPDIF playback and capture are done via the third PCM device
(hw:0,2). Usually this is assigned to the PCM device "spdif".
The available rates are 44100 and 48000 Hz.
For playback with aplay, you can run like below:
+::
% aplay -Dhw:0,2 foo.wav
or
+::
+
% aplay -Dspdif foo.wav
24bit format is also supported experimentally.
@@ -140,31 +149,40 @@ off. (Also don't forget to turn on "IEC958 Output Switch", too.)
Additionally there are relevant control switches:
-"IEC958 Mix Analog" - Mix analog PCM playback and FM-OPL/3 streams and
+IEC958 Mix Analog
+ Mix analog PCM playback and FM-OPL/3 streams and
output through SPDIF. This switch appears only on old chip
models (CM8738 033 and 037).
+
Note: without this control you can output PCM to SPDIF.
This is "mixing" of streams, so e.g. it's not for AC3 output
(see the next section).
-"IEC958 In Select" - Select SPDIF input, the internal CD-in (false)
+IEC958 In Select
+ Select SPDIF input, the internal CD-in (false)
and the external input (true).
-"IEC958 Loop" - SPDIF input data is loop back into SPDIF
+IEC958 Loop
+ SPDIF input data is loop back into SPDIF
output (aka bypass)
-"IEC958 Copyright" - Set the copyright bit.
+IEC958 Copyright
+ Set the copyright bit.
-"IEC958 5V" - Select 0.5V (coax) or 5V (optical) interface.
+IEC958 5V
+ Select 0.5V (coax) or 5V (optical) interface.
On some cards this doesn't work and you need to change the
configuration with hardware dip-switch.
-"IEC958 In Monitor" - SPDIF input is routed to DAC.
+IEC958 In Monitor
+ SPDIF input is routed to DAC.
-"IEC958 In Phase Inverse" - Set SPDIF input format as inverse.
+IEC958 In Phase Inverse
+ Set SPDIF input format as inverse.
[FIXME: this doesn't work on all chips..]
-"IEC958 In Valid" - Set input validity flag detection.
+IEC958 In Valid
+ Set input validity flag detection.
Note: When "PCM Playback Switch" is on, you'll hear the digital output
stream through analog line-out.
@@ -217,7 +235,7 @@ to enable MIDI support. Valid I/O ports are 0x300, 0x310, 0x320 and
With CMI8738 and newer chips, the MIDI interface is enabled by default
and the driver automatically chooses a port address.
-There is _no_ hardware wavetable function on this chip (except for
+There is *no* hardware wavetable function on this chip (except for
OPL3 synth below).
What's said as MIDI synth on Windows is a software synthesizer
emulation. On Linux use TiMidity or other softsynth program for
diff --git a/Documentation/sound/alsa/emu10k1-jack.txt b/Documentation/sound/cards/emu10k1-jack.rst
index 751d45036a05..6597f1ea83f0 100644
--- a/Documentation/sound/alsa/emu10k1-jack.txt
+++ b/Documentation/sound/cards/emu10k1-jack.rst
@@ -1,3 +1,7 @@
+=================================================================
+Low latency, multichannel audio with JACK and the emu10k1/emu10k2
+=================================================================
+
This document is a guide to using the emu10k1 based devices with JACK for low
latency, multichannel recording functionality. All of my recent work to allow
Linux users to use the full capabilities of their hardware has been inspired
@@ -7,8 +11,6 @@ power of this hardware.
http://www.kxproject.com
- Lee Revell, 2005.03.30
-Low latency, multichannel audio with JACK and the emu10k1/emu10k2
------------------------------------------------------------------
Until recently, emu10k1 users on Linux did not have access to the same low
latency, multichannel features offered by the "kX ASIO" feature of their
@@ -23,14 +25,15 @@ select the correct device for JACK to use. Actually, for qjackctl users it's
fairly self explanatory - select Duplex, then for capture and playback select
the multichannel devices, set the in and out channels to 16, and the sample
rate to 48000Hz. The command line looks like this:
+::
-/usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
+ /usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
This will give you 16 input ports and 16 output ports.
The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
Audigy). The mapping from FX bus to physical output is described in
-SB-Live-mixer.txt (or Audigy-mixer.txt).
+sb-live-mixer.rst (or audigy-mixer.rst).
The 16 input ports are connected to the 16 physical inputs. Contrary to
popular belief, all emu10k1 cards are multichannel cards. Which of these
@@ -49,10 +52,11 @@ This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
channels.
-/*JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
---------------------------------------------
+JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
+
+============== ======== ============
JACK Epilog FXBUS2(nr)
---------------------------------------------
+============== ======== ============
capture_1 asio14 FXBUS2(0xe)
capture_2 asio15 FXBUS2(0xf)
capture_3 asio0 FXBUS2(0x0)
@@ -69,6 +73,6 @@ capture_13 asio10 FXBUS2(0xa)
capture_14 asio11 FXBUS2(0xb)
capture_15 asio12 FXBUS2(0xc)
capture_16 asio13 FXBUS2(0xd)
-*/
+============== ======== ============
TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff --git a/Documentation/sound/alsa/hdspm.txt b/Documentation/sound/cards/hdspm.rst
index 7ba31948dea7..5373e51ed076 100644
--- a/Documentation/sound/alsa/hdspm.txt
+++ b/Documentation/sound/cards/hdspm.rst
@@ -1,21 +1,24 @@
+=======================================
Software Interface ALSA-DSP MADI Driver
+=======================================
(translated from German, so no good English ;-),
-2004 - winfried ritsch
-
+2004 - winfried ritsch
- Full functionality has been added to the driver. Since some of
- the Controls and startup-options are ALSA-Standard and only the
- special Controls are described and discussed below.
+Full functionality has been added to the driver. Since some of
+the Controls and startup-options are ALSA-Standard and only the
+special Controls are described and discussed below.
- hardware functionality:
+Hardware functionality
+======================
- Audio transmission:
+Audio transmission
+------------------
- number of channels -- depends on transmission mode
+* number of channels -- depends on transmission mode
The number of channels chosen is from 1..Nmax. The reason to
use for a lower number of channels is only resource allocation,
@@ -23,31 +26,34 @@ Software Interface ALSA-DSP MADI Driver
allocated. So also the throughput of the PCI system can be
scaled. (Only important for low performance boards).
- Single Speed -- 1..64 channels
+* Single Speed -- 1..64 channels
+.. note::
(Note: Choosing the 56channel mode for transmission or as
receiver, only 56 are transmitted/received over the MADI, but
all 64 channels are available for the mixer, so channel count
for the driver)
- Double Speed -- 1..32 channels
+* Double Speed -- 1..32 channels
+.. note::
Note: Choosing the 56-channel mode for
transmission/receive-mode , only 28 are transmitted/received
over the MADI, but all 32 channels are available for the mixer,
so channel count for the driver
- Quad Speed -- 1..16 channels
+* Quad Speed -- 1..16 channels
- Note: Choosing the 56-channel mode for
+.. note::
+ Choosing the 56-channel mode for
transmission/receive-mode , only 14 are transmitted/received
over the MADI, but all 16 channels are available for the mixer,
so channel count for the driver
- Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
+* Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
- Sample Rates --
+* Sample Rates --
Single Speed -- 32000, 44100, 48000
@@ -55,14 +61,13 @@ Software Interface ALSA-DSP MADI Driver
Quad Speed -- 128000, 176400, 192000 (untested)
- access-mode -- MMAP (memory mapped), Not interleaved
- (PCM_NON-INTERLEAVED)
+* access-mode -- MMAP (memory mapped), Not interleaved (PCM_NON-INTERLEAVED)
- buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
+* buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
- fragments -- 2
+* fragments -- 2
- Hardware-pointer -- 2 Modi
+* Hardware-pointer -- 2 Modi
The Card supports the readout of the actual Buffer-pointer,
@@ -74,53 +79,54 @@ Software Interface ALSA-DSP MADI Driver
precise-pointer.
+.. hint::
(Hint: Experimenting I found that the pointer is maximum 64 to
large never to small. So if you subtract 64 you always have a
safe pointer for writing, which is used on this mode inside
ALSA. In theory now you can get now a latency as low as 16
Samples, which is a quarter of the interrupt possibilities.)
- Precise Pointer -- off
+ * Precise Pointer -- off
interrupt used for pointer-calculation
-
- Precise Pointer -- on
+
+ * Precise Pointer -- on
hardware pointer used.
- Controller:
-
+Controller
+----------
- Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
- use the standard mixer-controls, since this would break most of
- (especially graphic) ALSA-Mixer GUIs. So Mixer control has be
- provided by a 2-dimensional controller using the
- hwdep-interface.
+Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
+use the standard mixer-controls, since this would break most of
+(especially graphic) ALSA-Mixer GUIs. So Mixer control has be
+provided by a 2-dimensional controller using the
+hwdep-interface.
- Also all 128+256 Peak and RMS-Meter can be accessed via the
- hwdep-interface. Since it could be a performance problem always
- copying and converting Peak and RMS-Levels even if you just need
- one, I decided to export the hardware structure, so that of
- needed some driver-guru can implement a memory-mapping of mixer
- or peak-meters over ioctl, or also to do only copying and no
- conversion. A test-application shows the usage of the controller.
-
- Latency Controls --- not implemented !!!
+Also all 128+256 Peak and RMS-Meter can be accessed via the
+hwdep-interface. Since it could be a performance problem always
+copying and converting Peak and RMS-Levels even if you just need
+one, I decided to export the hardware structure, so that of
+needed some driver-guru can implement a memory-mapping of mixer
+or peak-meters over ioctl, or also to do only copying and no
+conversion. A test-application shows the usage of the controller.
+* Latency Controls --- not implemented !!!
+.. note::
Note: Within the windows-driver the latency is accessible of a
control-panel, but buffer-sizes are controlled with ALSA from
hwparams-calls and should not be changed in run-state, I did not
implement it here.
- System Clock -- suspended !!!!
-
- Name -- "System Clock Mode"
+* System Clock -- suspended !!!!
- Access -- Read Write
-
- Values -- "Master" "Slave"
+ * Name -- "System Clock Mode"
+ * Access -- Read Write
+
+ * Values -- "Master" "Slave"
+.. note::
!!!! This is a hardware-function but is in conflict with the
Clock-source controller, which is a kind of ALSA-standard. I
makes sense to set the card to a special mode (master at some
@@ -128,106 +134,107 @@ Software Interface ALSA-DSP MADI Driver
a studio should have working synchronisations setup. So use
Clock-source-controller instead !!!!
- Clock Source
+* Clock Source
- Name -- "Sample Clock Source"
+ * Name -- "Sample Clock Source"
- Access -- Read Write
+ * Access -- Read Write
- Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
- "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
- "Internal 96.0 kHz"
+ * Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
+ "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
+ "Internal 96.0 kHz"
Choose between Master at a specific Frequency and so also the
Speed-mode or Slave (Autosync). Also see "Preferred Sync Ref"
-
+.. warning::
!!!! This is no pure hardware function but was implemented by
ALSA by some ALSA-drivers before, so I use it also. !!!
- Preferred Sync Ref
+* Preferred Sync Ref
- Name -- "Preferred Sync Reference"
+ * Name -- "Preferred Sync Reference"
- Access -- Read Write
+ * Access -- Read Write
- Values -- "Word" "MADI"
+ * Values -- "Word" "MADI"
Within the Auto-sync-Mode the preferred Sync Source can be
chosen. If it is not available another is used if possible.
+.. note::
Note: Since MADI has a much higher bit-rate than word-clock, the
card should synchronise better in MADI Mode. But since the
RME-PLL is very good, there are almost no problems with
word-clock too. I never found a difference.
- TX 64 channel ---
+* TX 64 channel
- Name -- "TX 64 channels mode"
+ * Name -- "TX 64 channels mode"
- Access -- Read Write
+ * Access -- Read Write
- Values -- 0 1
+ * Values -- 0 1
Using 64-channel-modus (1) or 56-channel-modus for
MADI-transmission (0).
+.. note::
Note: This control is for output only. Input-mode is detected
automatically from hardware sending MADI.
- Clear TMS ---
+* Clear TMS
- Name -- "Clear Track Marker"
+ * Name -- "Clear Track Marker"
- Access -- Read Write
+ * Access -- Read Write
- Values -- 0 1
+ * Values -- 0 1
Don't use to lower 5 Audio-bits on AES as additional Bits.
- Safe Mode oder Auto Input ---
+* Safe Mode oder Auto Input
- Name -- "Safe Mode"
+ * Name -- "Safe Mode"
- Access -- Read Write
+ * Access -- Read Write
- Values -- 0 1
-
- (default on)
+ * Values -- 0 1 (default on)
If on (1), then if either the optical or coaxial connection
has a failure, there is a takeover to the working one, with no
sample failure. Its only useful if you use the second as a
backup connection.
- Input ---
+* Input
- Name -- "Input Select"
+ * Name -- "Input Select"
- Access -- Read Write
+ * Access -- Read Write
- Values -- optical coaxial
+ * Values -- optical coaxial
Choosing the Input, optical or coaxial. If Safe-mode is active,
this is the preferred Input.
--------------- Mixer ----------------------
+Mixer
+-----
- Mixer
+* Mixer
- Name -- "Mixer"
+ * Name -- "Mixer"
- Access -- Read Write
+ * Access -- Read Write
- Values - <channel-number 0-127> <Value 0-65535>
+ * Values - <channel-number 0-127> <Value 0-65535>
Here as a first value the channel-index is taken to get/set the
@@ -235,40 +242,41 @@ Software Interface ALSA-DSP MADI Driver
fader and 64-127 the playback to outputs fader. Value 0
is channel muted 0 and 32768 an amplification of 1.
- Chn 1-64
+* Chn 1-64
fast mixer for the ALSA-mixer utils. The diagonal of the
mixer-matrix is implemented from playback to output.
- Line Out
+* Line Out
- Name -- "Line Out"
+ * Name -- "Line Out"
- Access -- Read Write
+ * Access -- Read Write
- Values -- 0 1
+ * Values -- 0 1
Switching on and off the analog out, which has nothing to do
with mixing or routing. the analog outs reflects channel 63,64.
---- information (only read access):
+Information (only read access)
+------------------------------
- Sample Rate
+* Sample Rate
- Name -- "System Sample Rate"
+ * Name -- "System Sample Rate"
- Access -- Read-only
+ * Access -- Read-only
getting the sample rate.
- External Rate measured
+* External Rate measured
- Name -- "External Rate"
+ * Name -- "External Rate"
- Access -- Read only
+ * Access -- Read only
Should be "Autosync Rate", but Name used is
@@ -276,79 +284,86 @@ Software Interface ALSA-DSP MADI Driver
reported.
- MADI Sync Status
+* MADI Sync Status
- Name -- "MADI Sync Lock Status"
+ * Name -- "MADI Sync Lock Status"
- Access -- Read
+ * Access -- Read
- Values -- 0,1,2
+ * Values -- 0,1,2
MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
- Word Clock Sync Status
+* Word Clock Sync Status
- Name -- "Word Clock Lock Status"
+ * Name -- "Word Clock Lock Status"
- Access -- Read
+ * Access -- Read
- Values -- 0,1,2
+ * Values -- 0,1,2
Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
- AutoSync
+* AutoSync
- Name -- "AutoSync Reference"
+ * Name -- "AutoSync Reference"
- Access -- Read
+ * Access -- Read
- Values -- "WordClock", "MADI", "None"
+ * Values -- "WordClock", "MADI", "None"
Sync-Reference is either "WordClock", "MADI" or none.
- RX 64ch --- noch nicht implementiert
+* RX 64ch --- noch nicht implementiert
MADI-Receiver is in 64 channel mode oder 56 channel mode.
- AB_inp --- not tested
+* AB_inp --- not tested
Used input for Auto-Input.
- actual Buffer Position --- not implemented
+* actual Buffer Position --- not implemented
!!! this is a ALSA internal function, so no control is used !!!
-Calling Parameter:
+Calling Parameter
+=================
+
+* index int array (min = 1, max = 8)
- index int array (min = 1, max = 8),
- "Index value for RME HDSPM interface." card-index within ALSA
+ Index value for RME HDSPM interface. card-index within ALSA
note: ALSA-standard
- id string array (min = 1, max = 8),
- "ID string for RME HDSPM interface."
+* id string array (min = 1, max = 8)
+
+ ID string for RME HDSPM interface.
note: ALSA-standard
- enable int array (min = 1, max = 8),
- "Enable/disable specific HDSPM sound-cards."
+* enable int array (min = 1, max = 8)
+
+ Enable/disable specific HDSPM sound-cards.
note: ALSA-standard
- precise_ptr int array (min = 1, max = 8),
- "Enable precise pointer, or disable."
+* precise_ptr int array (min = 1, max = 8)
+ Enable precise pointer, or disable.
+
+.. note::
note: Use only when the application supports this (which is a special case).
- line_outs_monitor int array (min = 1, max = 8),
- "Send playback streams to analog outs by default."
+* line_outs_monitor int array (min = 1, max = 8)
+ Send playback streams to analog outs by default.
+.. note::
note: each playback channel is mixed to the same numbered output
channel (routed). This is against the ALSA-convention, where all
channels have to be muted on after loading the driver, but was
@@ -356,7 +371,9 @@ Calling Parameter:
- enable_monitor int array (min = 1, max = 8),
- "Enable Analog Out on Channel 63/64 by default."
+* enable_monitor int array (min = 1, max = 8)
+
+ Enable Analog Out on Channel 63/64 by default.
+.. note ::
note: here the analog output is enabled (but not routed).
diff --git a/Documentation/sound/alsa/img,spdif-in.txt b/Documentation/sound/cards/img-spdif-in.rst
index 8b7505785fa6..7df9f5ae2609 100644
--- a/Documentation/sound/alsa/img,spdif-in.txt
+++ b/Documentation/sound/cards/img-spdif-in.rst
@@ -1,21 +1,25 @@
+================================================
+Imagination Technologies SPDIF Input Controllers
+================================================
+
The Imagination Technologies SPDIF Input controller contains the following
controls:
-name='IEC958 Capture Mask',index=0
+* name='IEC958 Capture Mask',index=0
This control returns a mask that shows which of the IEC958 status bits
can be read using the 'IEC958 Capture Default' control.
-name='IEC958 Capture Default',index=0
+* name='IEC958 Capture Default',index=0
This control returns the status bits contained within the SPDIF stream that
is being received. The 'IEC958 Capture Mask' shows which bits can be read
from this control.
-name='SPDIF In Multi Frequency Acquire',index=0
-name='SPDIF In Multi Frequency Acquire',index=1
-name='SPDIF In Multi Frequency Acquire',index=2
-name='SPDIF In Multi Frequency Acquire',index=3
+* name='SPDIF In Multi Frequency Acquire',index=0
+* name='SPDIF In Multi Frequency Acquire',index=1
+* name='SPDIF In Multi Frequency Acquire',index=2
+* name='SPDIF In Multi Frequency Acquire',index=3
This control is used to attempt acquisition of up to four different sample
rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
@@ -29,21 +33,21 @@ four sample rates set here.
If less than four rates are required, the same rate can be specified more than
once
-name='SPDIF In Lock Frequency',index=0
+* name='SPDIF In Lock Frequency',index=0
This control returns the active capture rate, or 0 if a lock has not been
acquired
-name='SPDIF In Lock TRK',index=0
+* name='SPDIF In Lock TRK',index=0
This control is used to modify the locking/jitter rejection characteristics
of the block. Larger values increase the locking range, but reduce jitter
rejection.
-name='SPDIF In Lock Acquire Threshold',index=0
+* name='SPDIF In Lock Acquire Threshold',index=0
This control is used to change the threshold at which a lock is acquired.
-name='SPDIF In Lock Release Threshold',index=0
+* name='SPDIF In Lock Release Threshold',index=0
This control is used to change the threshold at which a lock is released.
diff --git a/Documentation/sound/cards/index.rst b/Documentation/sound/cards/index.rst
new file mode 100644
index 000000000000..c016f8c3b88b
--- /dev/null
+++ b/Documentation/sound/cards/index.rst
@@ -0,0 +1,19 @@
+Card-Specific Information
+=========================
+
+.. toctree::
+ :maxdepth: 2
+
+ joystick
+ cmipci
+ sb-live-mixer
+ audigy-mixer
+ emu10k1-jack
+ via82xx-mixer
+ audiophile-usb
+ mixart
+ bt87x
+ maya44
+ hdspm
+ serial-u16550
+ img-spdif-in
diff --git a/Documentation/sound/alsa/Joystick.txt b/Documentation/sound/cards/joystick.rst
index ccda41b10f8a..a6e468c81d02 100644
--- a/Documentation/sound/alsa/Joystick.txt
+++ b/Documentation/sound/cards/joystick.rst
@@ -1,7 +1,10 @@
+=======================================
Analog Joystick Support on ALSA Drivers
=======================================
- Oct. 14, 2003
- Takashi Iwai <tiwai@suse.de>
+
+Oct. 14, 2003
+
+Takashi Iwai <tiwai@suse.de>
General
-------
@@ -34,44 +37,46 @@ stability and the resource management.
The following PCI drivers support the joystick natively.
- Driver Module Option Available Values
- ---------------------------------------------------------------------------
- als4000 joystick_port 0 = disable (default), 1 = auto-detect,
- manual: any address (e.g. 0x200)
- au88x0 N/A N/A
- azf3328 joystick 0 = disable, 1 = enable, -1 = auto (default)
- ens1370 joystick 0 = disable (default), 1 = enable
- ens1371 joystick_port 0 = disable (default), 1 = auto-detect,
- manual: 0x200, 0x208, 0x210, 0x218
- cmipci joystick_port 0 = disable (default), 1 = auto-detect,
- manual: any address (e.g. 0x200)
- cs4281 N/A N/A
- cs46xx N/A N/A
- es1938 N/A N/A
- es1968 joystick 0 = disable (default), 1 = enable
- sonicvibes N/A N/A
- trident N/A N/A
- via82xx(*1) joystick 0 = disable (default), 1 = enable
- ymfpci joystick_port 0 = disable (default), 1 = auto-detect,
- manual: 0x201, 0x202, 0x204, 0x205(*2)
- ---------------------------------------------------------------------------
-
- *1) VIA686A/B only
- *2) With YMF744/754 chips, the port address can be chosen arbitrarily
+============== ============= ============================================
+Driver Module Option Available Values
+============== ============= ============================================
+als4000 joystick_port 0 = disable (default), 1 = auto-detect,
+ manual: any address (e.g. 0x200)
+au88x0 N/A N/A
+azf3328 joystick 0 = disable, 1 = enable, -1 = auto (default)
+ens1370 joystick 0 = disable (default), 1 = enable
+ens1371 joystick_port 0 = disable (default), 1 = auto-detect,
+ manual: 0x200, 0x208, 0x210, 0x218
+cmipci joystick_port 0 = disable (default), 1 = auto-detect,
+ manual: any address (e.g. 0x200)
+cs4281 N/A N/A
+cs46xx N/A N/A
+es1938 N/A N/A
+es1968 joystick 0 = disable (default), 1 = enable
+sonicvibes N/A N/A
+trident N/A N/A
+via82xx [#f1]_ joystick 0 = disable (default), 1 = enable
+ymfpci joystick_port 0 = disable (default), 1 = auto-detect,
+ manual: 0x201, 0x202, 0x204, 0x205 [#f2]_
+============== ============= ============================================
+
+.. [#f1] VIA686A/B only
+.. [#f2] With YMF744/754 chips, the port address can be chosen arbitrarily
The following drivers don't support gameport natively, but there are
additional modules. Load the corresponding module to add the gameport
support.
- Driver Additional Module
- -----------------------------
- emu10k1 emu10k1-gp
- fm801 fm801-gp
- -----------------------------
+======= =================
+Driver Additional Module
+======= =================
+emu10k1 emu10k1-gp
+fm801 fm801-gp
+======= =================
Note: the "pcigame" and "cs461x" modules are for the OSS drivers only.
- These ALSA drivers (cs46xx, trident and au88x0) have the
- built-in gameport support.
+These ALSA drivers (cs46xx, trident and au88x0) have the
+built-in gameport support.
As mentioned above, ALSA PCI drivers have the built-in gameport
support, so you don't have to load ns558 module. Just load "joydev"
diff --git a/Documentation/sound/alsa/README.maya44 b/Documentation/sound/cards/maya44.rst
index 67b2ea1cc31d..bf09a584b443 100644
--- a/Documentation/sound/alsa/README.maya44
+++ b/Documentation/sound/cards/maya44.rst
@@ -1,10 +1,18 @@
-NOTE: The following is the original document of Rainer's patch that the
-current maya44 code based on. Some contents might be obsoleted, but I
-keep here as reference -- tiwai
+=================================
+Notes on Maya44 USB Audio Support
+=================================
-----------------------------------------------------------------
+.. note::
+ The following is the original document of Rainer's patch that the
+ current maya44 code based on. Some contents might be obsoleted, but I
+ keep here as reference -- tiwai
+
+Feb 14, 2008
+
+Rainer Zimmermann <mail@lightshed.de>
-STATE OF DEVELOPMENT:
+STATE OF DEVELOPMENT
+====================
This driver is being developed on the initiative of Piotr Makowski (oponek@gmail.com) and financed by Lars Bergmann.
Development is carried out by Rainer Zimmermann (mail@lightshed.de).
@@ -44,16 +52,17 @@ Things that do not seem to work:
- Ardour 2.1 seems to work only via JACK, not using ALSA directly or via OSS. This still needs to be tracked down.
-DRIVER DETAILS:
+DRIVER DETAILS
+==============
the following files were added:
-pci/ice1724/maya44.c - Maya44 specific code
-pci/ice1724/maya44.h
-pci/ice1724/ice1724.patch
-pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
-i2c/other/wm8776.c - low-level access routines for Wolfson WM8776 codecs
-include/wm8776.h
+* pci/ice1724/maya44.c - Maya44 specific code
+* pci/ice1724/maya44.h
+* pci/ice1724/ice1724.patch
+* pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
+* i2c/other/wm8776.c - low-level access routines for Wolfson WM8776 codecs
+* include/wm8776.h
Note that the wm8776.c code is meant to be card-independent and does not actually register the codec with the ALSA infrastructure.
@@ -62,25 +71,26 @@ This is done in maya44.c, mainly because some of the WM8776 controls are used in
the following files were created in pci/ice1724, simply #including the corresponding file from the alsa-kernel tree:
-wtm.h
-vt1720_mobo.h
-revo.h
-prodigy192.h
-pontis.h
-phase.h
-maya44.h
-juli.h
-aureon.h
-amp.h
-envy24ht.h
-se.h
-prodigy_hifi.h
+* wtm.h
+* vt1720_mobo.h
+* revo.h
+* prodigy192.h
+* pontis.h
+* phase.h
+* maya44.h
+* juli.h
+* aureon.h
+* amp.h
+* envy24ht.h
+* se.h
+* prodigy_hifi.h
*I hope this is the correct way to do things.*
-SAMPLING RATES:
+SAMPLING RATES
+==============
The Maya44 card (or more exactly, the Wolfson WM8776 codecs) allow a maximum sampling rate of 192 kHz for playback and 92 kHz for capture.
@@ -98,66 +108,79 @@ I propose some additional code for limiting the sampling rate when setting on a
The proposed code (currently deactivated) is in ice1712.h.patch, ice1724.c and maya44.c (in pci/ice1712).
-SOUND DEVICES:
+SOUND DEVICES
+=============
PCM devices correspond to inputs/outputs as follows (assuming Maya44 is card #0):
-hw:0,0 input - stereo, analog input 1+2
-hw:0,0 output - stereo, analog output 1+2
-hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
-hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
+* hw:0,0 input - stereo, analog input 1+2
+* hw:0,0 output - stereo, analog output 1+2
+* hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
+* hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
-NAMING OF MIXER CONTROLS:
+NAMING OF MIXER CONTROLS
+========================
(for more information about the signal flow, please refer to the block diagram on p.24 of the ESI Maya44 manual, or in the ESI windows software).
-PCM: (digital) output level for channel 1+2
-PCM 1: same for channel 3+4
+PCM
+ (digital) output level for channel 1+2
+PCM 1
+ same for channel 3+4
+
+Mic Phantom+48V
+ switch for +48V phantom power for electrostatic microphones on input 1/2.
-Mic Phantom+48V: switch for +48V phantom power for electrostatic microphones on input 1/2.
Make sure this is not turned on while any other source is connected to input 1/2.
It might damage the source and/or the maya44 card.
-Mic/Line input: if switch is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
+Mic/Line input
+ if switch is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
+
+Bypass
+ analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
+Bypass 1
+ same for channel 3+4.
-Bypass: analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
-Bypass 1: same for channel 3+4.
+Crossmix
+ cross-mixer from channels 1+2 to channels 3+4
+Crossmix 1
+ cross-mixer from channels 3+4 to channels 1+2
-Crossmix: cross-mixer from channels 1+2 to channels 3+4
-Crossmix 1: cross-mixer from channels 3+4 to channels 1+2
+IEC958 Output
+ switch for S/PDIF output.
-IEC958 Output: switch for S/PDIF output.
This is not supported by the ESI windows driver.
S/PDIF should output the same signal as channel 3+4. [untested!]
-Digitial output selectors:
-
+Digitial output selectors
These switches allow a direct digital routing from the ADCs to the DACs.
Each switch determines where the digital input data to one of the DACs comes from.
They are not supported by the ESI windows driver.
For normal operation, they should all be set to "PCM out".
-H/W: Output source channel 1
-H/W 1: Output source channel 2
-H/W 2: Output source channel 3
-H/W 3: Output source channel 4
+H/W
+ Output source channel 1
+H/W 1
+ Output source channel 2
+H/W 2
+ Output source channel 3
+H/W 3
+ Output source channel 4
+
+H/W 4 ... H/W 9
+ unknown function, left in to enable testing.
-H/W 4 ... H/W 9: unknown function, left in to enable testing.
Possibly some of these control S/PDIF output(s).
If these turn out to be unused, they will go away in later driver versions.
Selectable values for each of the digital output selectors are:
- "PCM out" -> DAC output of the corresponding channel (default setting)
- "Input 1"...
- "Input 4" -> direct routing from ADC output of the selected input channel
-
---------
-
-Feb 14, 2008
-Rainer Zimmermann
-mail@lightshed.de
+PCM out
+ DAC output of the corresponding channel (default setting)
+Input 1 ... Input 4
+ direct routing from ADC output of the selected input channel
diff --git a/Documentation/sound/alsa/MIXART.txt b/Documentation/sound/cards/mixart.rst
index 4ee35b4fbe4a..48aba98b088f 100644
--- a/Documentation/sound/alsa/MIXART.txt
+++ b/Documentation/sound/cards/mixart.rst
@@ -1,5 +1,8 @@
- Alsa driver for Digigram miXart8 and miXart8AES/EBU soundcards
- Digigram <alsa@digigram.com>
+==============================================================
+Alsa driver for Digigram miXart8 and miXart8AES/EBU soundcards
+==============================================================
+
+Digigram <alsa@digigram.com>
GENERAL
@@ -48,11 +51,15 @@ formats are supported.
Mixer
-----
-<Master> and <Master Capture> : analog volume control of playback and capture PCM.
-<PCM 0-3> and <PCM Capture> : digital volume control of each analog substream.
-<AES 0-3> and <AES Capture> : digital volume control of each AES/EBU substream.
-<Monitoring> : Loopback from 'pcm0c' to 'pcm0p' with digital volume
-and mute control.
+<Master> and <Master Capture>
+ analog volume control of playback and capture PCM.
+<PCM 0-3> and <PCM Capture>
+ digital volume control of each analog substream.
+<AES 0-3> and <AES Capture>
+ digital volume control of each AES/EBU substream.
+<Monitoring>
+ Loopback from 'pcm0c' to 'pcm0p' with digital volume
+ and mute control.
Rem : for best audio quality try to keep a 0 attenuation on the PCM
and AES volume controls which is set by 219 in the range from 0 to 255
@@ -79,11 +86,14 @@ FIRMWARE
For loading the firmware automatically after the module is loaded, use a
install command. For example, add the following entry to
/etc/modprobe.d/mixart.conf for miXart driver:
+::
install snd-mixart /sbin/modprobe --first-time -i snd-mixart && \
/usr/bin/mixartloader
+
+
(for 2.2/2.4 kernels, add "post-install snd-mixart /usr/bin/vxloader" to
- /etc/modules.conf, instead.)
+/etc/modules.conf, instead.)
The firmware binaries are installed on /usr/share/alsa/firmware
(or /usr/local/share/alsa/firmware, depending to the prefix option of
diff --git a/Documentation/sound/alsa/SB-Live-mixer.txt b/Documentation/sound/cards/sb-live-mixer.rst
index f4b5988f450c..bcb62fc99bbb 100644
--- a/Documentation/sound/alsa/SB-Live-mixer.txt
+++ b/Documentation/sound/cards/sb-live-mixer.rst
@@ -1,6 +1,6 @@
-
- Sound Blaster Live mixer / default DSP code
- ===========================================
+===========================================
+Sound Blaster Live mixer / default DSP code
+===========================================
The EMU10K1 chips have a DSP part which can be programmed to support
@@ -12,8 +12,8 @@ The ALSA driver programs this portion of chip by default code
(can be altered later) which offers the following functionality:
-1) IEC958 (S/PDIF) raw PCM
---------------------------
+IEC958 (S/PDIF) raw PCM
+=======================
This PCM device (it's the 4th PCM device (index 3!) and first subdevice
(index 0) for a given card) allows to forward 48kHz, stereo, 16-bit
@@ -27,8 +27,8 @@ at the time.
Look to tram_poke routines in lowlevel/emu10k1/emufx.c for more details.
-2) Digital mixer controls
--------------------------
+Digital mixer controls
+======================
These controls are built using the DSP instructions. They offer extended
functionality. Only the default build-in code in the ALSA driver is described
@@ -40,317 +40,334 @@ is mentioned in multiple controls, the signal is accumulated and can be wrapped
Explanation of used abbreviations:
-DAC - digital to analog converter
-ADC - analog to digital converter
-I2S - one-way three wire serial bus for digital sound by Philips Semiconductors
- (this standard is used for connecting standalone DAC and ADC converters)
-LFE - low frequency effects (subwoofer signal)
-AC97 - a chip containing an analog mixer, DAC and ADC converters
-IEC958 - S/PDIF
-FX-bus - the EMU10K1 chip has an effect bus containing 16 accumulators.
- Each of the synthesizer voices can feed its output to these accumulators
- and the DSP microcontroller can operate with the resulting sum.
-
-
-name='Wave Playback Volume',index=0
-
+DAC
+ digital to analog converter
+ADC
+ analog to digital converter
+I2S
+ one-way three wire serial bus for digital sound by Philips Semiconductors
+ (this standard is used for connecting standalone DAC and ADC converters)
+LFE
+ low frequency effects (subwoofer signal)
+AC97
+ a chip containing an analog mixer, DAC and ADC converters
+IEC958
+ S/PDIF
+FX-bus
+ the EMU10K1 chip has an effect bus containing 16 accumulators.
+ Each of the synthesizer voices can feed its output to these accumulators
+ and the DSP microcontroller can operate with the resulting sum.
+
+
+``name='Wave Playback Volume',index=0``
+---------------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
-name='Wave Surround Playback Volume',index=0
-
+``name='Wave Surround Playback Volume',index=0``
+------------------------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
The result samples are forwarded to the rear I2S DACs. These DACs operates
separately (they are not inside the AC97 codec).
-name='Wave Center Playback Volume',index=0
-
+``name='Wave Center Playback Volume',index=0``
+----------------------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
The result is mixed to mono signal (single channel) and forwarded to
the ??rear?? right DAC PCM slot of the AC97 codec.
-name='Wave LFE Playback Volume',index=0
-
+``name='Wave LFE Playback Volume',index=0``
+-------------------------------------------
This control is used to attenuate samples for left and right PCM FX-bus
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
The result is mixed to mono signal (single channel) and forwarded to
the ??rear?? left DAC PCM slot of the AC97 codec.
-name='Wave Capture Volume',index=0
-name='Wave Capture Switch',index=0
-
+``name='Wave Capture Volume',index=0``, ``name='Wave Capture Switch',index=0``
+------------------------------------------------------------------------------
These controls are used to attenuate samples for left and right PCM FX-bus
accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
-name='Synth Playback Volume',index=0
-
+``name='Synth Playback Volume',index=0``
+----------------------------------------
This control is used to attenuate samples for left and right MIDI FX-bus
accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
-name='Synth Capture Volume',index=0
-name='Synth Capture Switch',index=0
-
+``name='Synth Capture Volume',index=0``, ``name='Synth Capture Switch',index=0``
+--------------------------------------------------------------------------------
These controls are used to attenuate samples for left and right MIDI FX-bus
accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
-name='Surround Playback Volume',index=0
-
+``name='Surround Playback Volume',index=0``
+-------------------------------------------
This control is used to attenuate samples for left and right rear PCM FX-bus
accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
The result samples are forwarded to the rear I2S DACs. These DACs operate
separately (they are not inside the AC97 codec).
-name='Surround Capture Volume',index=0
-name='Surround Capture Switch',index=0
-
+``name='Surround Capture Volume',index=0``, ``name='Surround Capture Switch',index=0``
+--------------------------------------------------------------------------------------
These controls are used to attenuate samples for left and right rear PCM FX-bus
accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
The result is forwarded to the ADC capture FIFO (thus to the standard capture
PCM device).
-name='Center Playback Volume',index=0
-
+``name='Center Playback Volume',index=0``
+-----------------------------------------
This control is used to attenuate sample for center PCM FX-bus accumulator.
ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
to the ??rear?? right DAC PCM slot of the AC97 codec.
-name='LFE Playback Volume',index=0
-
+``name='LFE Playback Volume',index=0``
+--------------------------------------
This control is used to attenuate sample for center PCM FX-bus accumulator.
ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
to the ??rear?? left DAC PCM slot of the AC97 codec.
-name='AC97 Playback Volume',index=0
-
+``name='AC97 Playback Volume',index=0``
+---------------------------------------
This control is used to attenuate samples for left and right front ADC PCM slots
of the AC97 codec. The result samples are forwarded to the front DAC PCM
slots of the AC97 codec.
-********************************************************************************
-*** Note: This control should be zero for the standard operations, otherwise ***
-*** a digital loopback is activated. ***
-********************************************************************************
-name='AC97 Capture Volume',index=0
+.. note::
+ This control should be zero for the standard operations, otherwise
+ a digital loopback is activated.
+
+``name='AC97 Capture Volume',index=0``
+--------------------------------------
This control is used to attenuate samples for left and right front ADC PCM slots
of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
the standard capture PCM device).
-********************************************************************************
-*** Note: This control should be 100 (maximal value), otherwise no analog ***
-*** inputs of the AC97 codec can be captured (recorded). ***
-********************************************************************************
-name='IEC958 TTL Playback Volume',index=0
+.. note::
+ This control should be 100 (maximal value), otherwise no analog
+ inputs of the AC97 codec can be captured (recorded).
+``name='IEC958 TTL Playback Volume',index=0``
+---------------------------------------------
This control is used to attenuate samples from left and right IEC958 TTL
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the front DAC PCM slots of the AC97 codec.
-name='IEC958 TTL Capture Volume',index=0
-
+``name='IEC958 TTL Capture Volume',index=0``
+--------------------------------------------
This control is used to attenuate samples from left and right IEC958 TTL
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
-name='Zoom Video Playback Volume',index=0
-
+``name='Zoom Video Playback Volume',index=0``
+---------------------------------------------
This control is used to attenuate samples from left and right zoom video
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the front DAC PCM slots of the AC97 codec.
-name='Zoom Video Capture Volume',index=0
-
+``name='Zoom Video Capture Volume',index=0``
+--------------------------------------------
This control is used to attenuate samples from left and right zoom video
digital inputs (usually used by a CDROM drive). The result samples are
forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
-name='IEC958 LiveDrive Playback Volume',index=0
-
+``name='IEC958 LiveDrive Playback Volume',index=0``
+---------------------------------------------------
This control is used to attenuate samples from left and right IEC958 optical
digital input. The result samples are forwarded to the front DAC PCM slots
of the AC97 codec.
-name='IEC958 LiveDrive Capture Volume',index=0
-
+``name='IEC958 LiveDrive Capture Volume',index=0``
+--------------------------------------------------
This control is used to attenuate samples from left and right IEC958 optical
digital inputs. The result samples are forwarded to the ADC capture FIFO
(thus to the standard capture PCM device).
-name='IEC958 Coaxial Playback Volume',index=0
-
+``name='IEC958 Coaxial Playback Volume',index=0``
+-------------------------------------------------
This control is used to attenuate samples from left and right IEC958 coaxial
digital inputs. The result samples are forwarded to the front DAC PCM slots
of the AC97 codec.
-name='IEC958 Coaxial Capture Volume',index=0
-
+``name='IEC958 Coaxial Capture Volume',index=0``
+------------------------------------------------
This control is used to attenuate samples from left and right IEC958 coaxial
digital inputs. The result samples are forwarded to the ADC capture FIFO
(thus to the standard capture PCM device).
-name='Line LiveDrive Playback Volume',index=0
-name='Line LiveDrive Playback Volume',index=1
-
+``name='Line LiveDrive Playback Volume',index=0``, ``name='Line LiveDrive Playback Volume',index=1``
+----------------------------------------------------------------------------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the LiveDrive). The result samples are forwarded to the front
DAC PCM slots of the AC97 codec.
-name='Line LiveDrive Capture Volume',index=1
-name='Line LiveDrive Capture Volume',index=1
-
+``name='Line LiveDrive Capture Volume',index=1``, ``name='Line LiveDrive Capture Volume',index=1``
+--------------------------------------------------------------------------------------------------
This control is used to attenuate samples from left and right I2S ADC
inputs (on the LiveDrive). The result samples are forwarded to the ADC
capture FIFO (thus to the standard capture PCM device).
-name='Tone Control - Switch',index=0
-
+``name='Tone Control - Switch',index=0``
+----------------------------------------
This control turns the tone control on or off. The samples for front, rear
and center / LFE outputs are affected.
-name='Tone Control - Bass',index=0
-
+``name='Tone Control - Bass',index=0``
+--------------------------------------
This control sets the bass intensity. There is no neutral value!!
When the tone control code is activated, the samples are always modified.
The closest value to pure signal is 20.
-name='Tone Control - Treble',index=0
-
+``name='Tone Control - Treble',index=0``
+----------------------------------------
This control sets the treble intensity. There is no neutral value!!
When the tone control code is activated, the samples are always modified.
The closest value to pure signal is 20.
-name='IEC958 Optical Raw Playback Switch',index=0
-
+``name='IEC958 Optical Raw Playback Switch',index=0``
+-----------------------------------------------------
If this switch is on, then the samples for the IEC958 (S/PDIF) digital
output are taken only from the raw FX8010 PCM, otherwise standard front
PCM samples are taken.
-name='Headphone Playback Volume',index=1
-
+``name='Headphone Playback Volume',index=1``
+--------------------------------------------
This control attenuates the samples for the headphone output.
-name='Headphone Center Playback Switch',index=1
-
+``name='Headphone Center Playback Switch',index=1``
+---------------------------------------------------
If this switch is on, then the sample for the center PCM is put to the
left headphone output (useful for SB Live cards without separate center/LFE
output).
-name='Headphone LFE Playback Switch',index=1
-
+``name='Headphone LFE Playback Switch',index=1``
+------------------------------------------------
If this switch is on, then the sample for the center PCM is put to the
right headphone output (useful for SB Live cards without separate center/LFE
output).
-3) PCM stream related controls
-------------------------------
-
-name='EMU10K1 PCM Volume',index 0-31
+PCM stream related controls
+===========================
+``name='EMU10K1 PCM Volume',index 0-31``
+----------------------------------------
Channel volume attenuation in range 0-0xffff. The maximum value (no
attenuation) is default. The channel mapping for three values is
as follows:
- 0 - mono, default 0xffff (no attenuation)
- 1 - left, default 0xffff (no attenuation)
- 2 - right, default 0xffff (no attenuation)
-
-name='EMU10K1 PCM Send Routing',index 0-31
+* 0 - mono, default 0xffff (no attenuation)
+* 1 - left, default 0xffff (no attenuation)
+* 2 - right, default 0xffff (no attenuation)
+``name='EMU10K1 PCM Send Routing',index 0-31``
+----------------------------------------------
This control specifies the destination - FX-bus accumulators. There are
twelve values with this mapping:
- 0 - mono, A destination (FX-bus 0-15), default 0
- 1 - mono, B destination (FX-bus 0-15), default 1
- 2 - mono, C destination (FX-bus 0-15), default 2
- 3 - mono, D destination (FX-bus 0-15), default 3
- 4 - left, A destination (FX-bus 0-15), default 0
- 5 - left, B destination (FX-bus 0-15), default 1
- 6 - left, C destination (FX-bus 0-15), default 2
- 7 - left, D destination (FX-bus 0-15), default 3
- 8 - right, A destination (FX-bus 0-15), default 0
- 9 - right, B destination (FX-bus 0-15), default 1
- 10 - right, C destination (FX-bus 0-15), default 2
- 11 - right, D destination (FX-bus 0-15), default 3
+* 0 - mono, A destination (FX-bus 0-15), default 0
+* 1 - mono, B destination (FX-bus 0-15), default 1
+* 2 - mono, C destination (FX-bus 0-15), default 2
+* 3 - mono, D destination (FX-bus 0-15), default 3
+* 4 - left, A destination (FX-bus 0-15), default 0
+* 5 - left, B destination (FX-bus 0-15), default 1
+* 6 - left, C destination (FX-bus 0-15), default 2
+* 7 - left, D destination (FX-bus 0-15), default 3
+* 8 - right, A destination (FX-bus 0-15), default 0
+* 9 - right, B destination (FX-bus 0-15), default 1
+* 10 - right, C destination (FX-bus 0-15), default 2
+* 11 - right, D destination (FX-bus 0-15), default 3
Don't forget that it's illegal to assign a channel to the same FX-bus accumulator
more than once (it means 0=0 && 1=0 is an invalid combination).
-name='EMU10K1 PCM Send Volume',index 0-31
-
+``name='EMU10K1 PCM Send Volume',index 0-31``
+---------------------------------------------
It specifies the attenuation (amount) for given destination in range 0-255.
The channel mapping is following:
- 0 - mono, A destination attn, default 255 (no attenuation)
- 1 - mono, B destination attn, default 255 (no attenuation)
- 2 - mono, C destination attn, default 0 (mute)
- 3 - mono, D destination attn, default 0 (mute)
- 4 - left, A destination attn, default 255 (no attenuation)
- 5 - left, B destination attn, default 0 (mute)
- 6 - left, C destination attn, default 0 (mute)
- 7 - left, D destination attn, default 0 (mute)
- 8 - right, A destination attn, default 0 (mute)
- 9 - right, B destination attn, default 255 (no attenuation)
- 10 - right, C destination attn, default 0 (mute)
- 11 - right, D destination attn, default 0 (mute)
+* 0 - mono, A destination attn, default 255 (no attenuation)
+* 1 - mono, B destination attn, default 255 (no attenuation)
+* 2 - mono, C destination attn, default 0 (mute)
+* 3 - mono, D destination attn, default 0 (mute)
+* 4 - left, A destination attn, default 255 (no attenuation)
+* 5 - left, B destination attn, default 0 (mute)
+* 6 - left, C destination attn, default 0 (mute)
+* 7 - left, D destination attn, default 0 (mute)
+* 8 - right, A destination attn, default 0 (mute)
+* 9 - right, B destination attn, default 255 (no attenuation)
+* 10 - right, C destination attn, default 0 (mute)
+* 11 - right, D destination attn, default 0 (mute)
-4) MANUALS/PATENTS:
--------------------
+MANUALS/PATENTS
+===============
ftp://opensource.creative.com/pub/doc
-------------------------------------
- Files:
- LM4545.pdf AC97 Codec
-
- m2049.pdf The EMU10K1 Digital Audio Processor
-
- hog63.ps FX8010 - A DSP Chip Architecture for Audio Effects
+LM4545.pdf
+ AC97 Codec
+m2049.pdf
+ The EMU10K1 Digital Audio Processor
+hog63.ps
+ FX8010 - A DSP Chip Architecture for Audio Effects
WIPO Patents
------------
- Patent numbers:
- WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
- streams
- WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+WO 9901813 (A1)
+ Audio Effects Processor with multiple asynchronous streams
+ (Jan. 14, 1999)
+
+WO 9901814 (A1)
+ Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
- WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
- Execution and Audio Data Sequencing (Jan. 14, 1999)
+WO 9901953 (A1)
+ Audio Effects Processor having Decoupled Instruction
+ Execution and Audio Data Sequencing (Jan. 14, 1999)
US Patents (http://www.uspto.gov/)
----------------------------------
- US 5925841 Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
-
- US 5928342 Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
- with a multiport memory onto which multiple asynchronous
- digital sound samples can be concurrently loaded
-
- US 5930158 Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
-
- US 6032235 Memory initialization circuit (Tram) (Feb. 29, 2000)
-
- US 6138207 Interpolation looping of audio samples in cache connected to (Oct. 24, 2000)
- system bus with prioritization and modification of bus transfers
- in accordance with loop ends and minimum block sizes
-
- US 6151670 Method for conserving memory storage using a (Nov. 21, 2000)
- pool of short term memory registers
-
- US 6195715 Interrupt control for multiple programs communicating with (Feb. 27, 2001)
- a common interrupt by associating programs to GP registers,
- defining interrupt register, polling GP registers, and invoking
- callback routine associated with defined interrupt register
+US 5925841
+ Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+US 5928342
+ Audio Effects Processor integrated on a single chip
+ with a multiport memory onto which multiple asynchronous
+ digital sound samples can be concurrently loaded
+ (Jul. 27, 1999)
+
+US 5930158
+ Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+US 6032235
+ Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+US 6138207
+ Interpolation looping of audio samples in cache connected to
+ system bus with prioritization and modification of bus transfers
+ in accordance with loop ends and minimum block sizes
+ (Oct. 24, 2000)
+
+US 6151670
+ Method for conserving memory storage using a
+ pool of short term memory registers
+ (Nov. 21, 2000)
+
+US 6195715
+ Interrupt control for multiple programs communicating with
+ a common interrupt by associating programs to GP registers,
+ defining interrupt register, polling GP registers, and invoking
+ callback routine associated with defined interrupt register
+ (Feb. 27, 2001)
diff --git a/Documentation/sound/alsa/serial-u16550.txt b/Documentation/sound/cards/serial-u16550.rst
index c1919559d509..197aeacea3da 100644
--- a/Documentation/sound/alsa/serial-u16550.txt
+++ b/Documentation/sound/cards/serial-u16550.rst
@@ -1,14 +1,14 @@
-
- Serial UART 16450/16550 MIDI driver
- ===================================
+===================================
+Serial UART 16450/16550 MIDI driver
+===================================
The adaptor module parameter allows you to select either:
- 0 - Roland Soundcanvas support (default)
- 1 - Midiator MS-124T support (1)
- 2 - Midiator MS-124W S/A mode (2)
- 3 - MS-124W M/B mode support (3)
- 4 - Generic device with multiple input support (4)
+* 0 - Roland Soundcanvas support (default)
+* 1 - Midiator MS-124T support (1)
+* 2 - Midiator MS-124W S/A mode (2)
+* 3 - MS-124W M/B mode support (3)
+* 4 - Generic device with multiple input support (4)
For the Midiator MS-124W, you must set the physical M-S and A-B
switches on the Midiator to match the driver mode you select.
@@ -22,11 +22,13 @@ substream. The driver provides no way to send F5 00 (no selection) or to not
send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter:
+::
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports:
+::
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
@@ -37,6 +39,7 @@ all four MIDI Out connectors. Set the A-B switch and the speed module
parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position:
+::
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
@@ -47,6 +50,7 @@ the outs module parameter is automatically set to 1. The driver sends
the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode:
+::
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
@@ -63,6 +67,7 @@ at most one byte every 520 us, as compared with the full MIDI data rate of
one byte every 320 us per port.
Usage example for M/B mode:
+::
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
diff --git a/Documentation/sound/cards/via82xx-mixer.rst b/Documentation/sound/cards/via82xx-mixer.rst
new file mode 100644
index 000000000000..6ee993d4535b
--- /dev/null
+++ b/Documentation/sound/cards/via82xx-mixer.rst
@@ -0,0 +1,8 @@
+=============
+VIA82xx mixer
+=============
+
+On many VIA82xx boards, the ``Input Source Select`` mixer control does not work.
+Setting it to ``Input2`` on such boards will cause recording to hang, or fail
+with EIO (input/output error) via OSS emulation. This control should be left
+at ``Input1`` for such cards.
diff --git a/Documentation/sound/alsa/Channel-Mapping-API.txt b/Documentation/sound/designs/channel-mapping-api.rst
index 3c43d1a4ca0e..58e6312a43c0 100644
--- a/Documentation/sound/alsa/Channel-Mapping-API.txt
+++ b/Documentation/sound/designs/channel-mapping-api.rst
@@ -1,9 +1,11 @@
+============================
ALSA PCM channel-mapping API
============================
- Takashi Iwai <tiwai@suse.de>
-GENERAL
--------
+Takashi Iwai <tiwai@suse.de>
+
+General
+=======
The channel mapping API allows user to query the possible channel maps
and the current channel map, also optionally to modify the channel map
@@ -11,9 +13,9 @@ of the current stream.
A channel map is an array of position for each PCM channel.
Typically, a stereo PCM stream has a channel map of
- { front_left, front_right }
+``{ front_left, front_right }``
while a 4.0 surround PCM stream has a channel map of
- { front left, front right, rear left, rear right }.
+``{ front left, front right, rear left, rear right }.``
The problem, so far, was that we had no standard channel map
explicitly, and applications had no way to know which channel
@@ -29,8 +31,8 @@ specification. These are the main motivations for the new channel
mapping API.
-DESIGN
-------
+Design
+======
Actually, "the channel mapping API" doesn't introduce anything new in
the kernel/user-space ABI perspective. It uses only the existing
@@ -39,10 +41,11 @@ control element features.
As a ground design, each PCM substream may contain a control element
providing the channel mapping information and configuration. This
element is specified by:
- iface = SNDRV_CTL_ELEM_IFACE_PCM
- name = "Playback Channel Map" or "Capture Channel Map"
- device = the same device number for the assigned PCM substream
- index = the same index number for the assigned PCM substream
+
+* iface = SNDRV_CTL_ELEM_IFACE_PCM
+* name = "Playback Channel Map" or "Capture Channel Map"
+* device = the same device number for the assigned PCM substream
+* index = the same index number for the assigned PCM substream
Note the name is different depending on the PCM substream direction.
@@ -50,32 +53,35 @@ Each control element provides at least the TLV read operation and the
read operation. Optionally, the write operation can be provided to
allow user to change the channel map dynamically.
-* TLV
+TLV
+---
The TLV operation gives the list of available channel
maps. A list item of a channel map is usually a TLV of
- type data-bytes ch0 ch1 ch2...
+``type data-bytes ch0 ch1 ch2...``
where type is the TLV type value, the second argument is the total
bytes (not the numbers) of channel values, and the rest are the
position value for each channel.
-As a TLV type, either SNDRV_CTL_TLVT_CHMAP_FIXED,
-SNDRV_CTL_TLV_CHMAP_VAR or SNDRV_CTL_TLVT_CHMAP_PAIRED can be used.
-The _FIXED type is for a channel map with the fixed channel position
-while the latter two are for flexible channel positions. _VAR type is
-for a channel map where all channels are freely swappable and _PAIRED
+As a TLV type, either ``SNDRV_CTL_TLVT_CHMAP_FIXED``,
+``SNDRV_CTL_TLV_CHMAP_VAR`` or ``SNDRV_CTL_TLVT_CHMAP_PAIRED`` can be used.
+The ``_FIXED`` type is for a channel map with the fixed channel position
+while the latter two are for flexible channel positions. ``_VAR`` type is
+for a channel map where all channels are freely swappable and ``_PAIRED``
type is where pair-wise channels are swappable. For example, when you
-have {FL/FR/RL/RR} channel map, _PAIRED type would allow you to swap
-only {RL/RR/FL/FR} while _VAR type would allow even swapping FL and
+have {FL/FR/RL/RR} channel map, ``_PAIRED`` type would allow you to swap
+only {RL/RR/FL/FR} while ``_VAR`` type would allow even swapping FL and
RR.
-These new TLV types are defined in sound/tlv.h.
+These new TLV types are defined in ``sound/tlv.h``.
-The available channel position values are defined in sound/asound.h,
+The available channel position values are defined in ``sound/asound.h``,
here is a cut:
-/* channel positions */
-enum {
+::
+
+ /* channel positions */
+ enum {
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_NA, /* N/A, silent */
SNDRV_CHMAP_MONO, /* mono stream */
@@ -107,11 +113,13 @@ enum {
SNDRV_CHMAP_TRR, /* top rear right */
SNDRV_CHMAP_TRC, /* top rear center */
SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
+ };
When a PCM stream can provide more than one channel map, you can
provide multiple channel maps in a TLV container type. The TLV data
to be returned will contain such as:
+::
+
SNDRV_CTL_TLVT_CONTAINER 96
SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
@@ -120,19 +128,21 @@ to be returned will contain such as:
The channel position is provided in LSB 16bits. The upper bits are
used for bit flags.
+::
-#define SNDRV_CHMAP_POSITION_MASK 0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
+ #define SNDRV_CHMAP_POSITION_MASK 0xffff
+ #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
+ #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
-SNDRV_CHMAP_PHASE_INVERSE indicates the channel is phase inverted,
+``SNDRV_CHMAP_PHASE_INVERSE`` indicates the channel is phase inverted,
(thus summing left and right channels would result in almost silence).
Some digital mic devices have this.
-When SNDRV_CHMAP_DRIVER_SPEC is set, all the channel position values
+When ``SNDRV_CHMAP_DRIVER_SPEC`` is set, all the channel position values
don't follow the standard definition above but driver-specific.
-* READ OPERATION
+Read Operation
+--------------
The control read operation is for providing the current channel map of
the given stream. The control element returns an integer array
@@ -140,9 +150,10 @@ containing the position of each channel.
When this is performed before the number of the channel is specified
(i.e. hw_params is set), it should return all channels set to
-UNKNOWN.
+``UNKNOWN``.
-* WRITE OPERATION
+Write Operation
+---------------
The control write operation is optional, and only for devices that can
change the channel configuration on the fly, such as HDMI. User needs
diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/designs/compress-offload.rst
index 8ba556a131c3..ad4bfbdacc83 100644
--- a/Documentation/sound/alsa/compress_offload.txt
+++ b/Documentation/sound/designs/compress-offload.rst
@@ -1,10 +1,14 @@
- compress_offload.txt
- =====================
- Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
- Vinod Koul <vinod.koul@linux.intel.com>
+=========================
+ALSA Compress-Offload API
+=========================
+
+Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+
+Vinod Koul <vinod.koul@linux.intel.com>
-Overview
+Overview
+========
Since its early days, the ALSA API was defined with PCM support or
constant bitrates payloads such as IEC61937 in mind. Arguments and
returned values in frames are the norm, making it a challenge to
@@ -27,8 +31,9 @@ Intel Moorestown SOC, with many corrections required to upstream the
API in the mainline kernel instead of the staging tree and make it
usable by others.
-Requirements
+Requirements
+============
The main requirements are:
- separation between byte counts and time. Compressed formats may have
@@ -63,7 +68,7 @@ The main requirements are:
streaming compressed data to a DSP, with the assumption that the
decoded samples are routed to a physical output or logical back-end.
- - Complexity hiding. Existing user-space multimedia frameworks all
+- Complexity hiding. Existing user-space multimedia frameworks all
have existing enums/structures for each compressed format. This new
API assumes the existence of a platform-specific compatibility layer
to expose, translate and make use of the capabilities of the audio
@@ -72,7 +77,7 @@ The main requirements are:
Design
-
+======
The new API shares a number of concepts with the PCM API for flow
control. Start, pause, resume, drain and stop commands have the same
semantics no matter what the content is.
@@ -95,43 +100,44 @@ mandatory routines and possibly make use of optional ones.
The main additions are
-- get_caps
-This routine returns the list of audio formats supported. Querying the
-codecs on a capture stream will return encoders, decoders will be
-listed for playback streams.
-
-- get_codec_caps For each codec, this routine returns a list of
-capabilities. The intent is to make sure all the capabilities
-correspond to valid settings, and to minimize the risks of
-configuration failures. For example, for a complex codec such as AAC,
-the number of channels supported may depend on a specific profile. If
-the capabilities were exposed with a single descriptor, it may happen
-that a specific combination of profiles/channels/formats may not be
-supported. Likewise, embedded DSPs have limited memory and cpu cycles,
-it is likely that some implementations make the list of capabilities
-dynamic and dependent on existing workloads. In addition to codec
-settings, this routine returns the minimum buffer size handled by the
-implementation. This information can be a function of the DMA buffer
-sizes, the number of bytes required to synchronize, etc, and can be
-used by userspace to define how much needs to be written in the ring
-buffer before playback can start.
-
-- set_params
-This routine sets the configuration chosen for a specific codec. The
-most important field in the parameters is the codec type; in most
-cases decoders will ignore other fields, while encoders will strictly
-comply to the settings
-
-- get_params
-This routines returns the actual settings used by the DSP. Changes to
-the settings should remain the exception.
-
-- get_timestamp
-The timestamp becomes a multiple field structure. It lists the number
-of bytes transferred, the number of samples processed and the number
-of samples rendered/grabbed. All these values can be used to determine
-the average bitrate, figure out if the ring buffer needs to be
-refilled or the delay due to decoding/encoding/io on the DSP.
+get_caps
+ This routine returns the list of audio formats supported. Querying the
+ codecs on a capture stream will return encoders, decoders will be
+ listed for playback streams.
+
+get_codec_caps
+ For each codec, this routine returns a list of
+ capabilities. The intent is to make sure all the capabilities
+ correspond to valid settings, and to minimize the risks of
+ configuration failures. For example, for a complex codec such as AAC,
+ the number of channels supported may depend on a specific profile. If
+ the capabilities were exposed with a single descriptor, it may happen
+ that a specific combination of profiles/channels/formats may not be
+ supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+ it is likely that some implementations make the list of capabilities
+ dynamic and dependent on existing workloads. In addition to codec
+ settings, this routine returns the minimum buffer size handled by the
+ implementation. This information can be a function of the DMA buffer
+ sizes, the number of bytes required to synchronize, etc, and can be
+ used by userspace to define how much needs to be written in the ring
+ buffer before playback can start.
+
+set_params
+ This routine sets the configuration chosen for a specific codec. The
+ most important field in the parameters is the codec type; in most
+ cases decoders will ignore other fields, while encoders will strictly
+ comply to the settings
+
+get_params
+ This routines returns the actual settings used by the DSP. Changes to
+ the settings should remain the exception.
+
+get_timestamp
+ The timestamp becomes a multiple field structure. It lists the number
+ of bytes transferred, the number of samples processed and the number
+ of samples rendered/grabbed. All these values can be used to determine
+ the average bitrate, figure out if the ring buffer needs to be
+ refilled or the delay due to decoding/encoding/io on the DSP.
Note that the list of codecs/profiles/modes was derived from the
OpenMAX AL specification instead of reinventing the wheel.
@@ -145,6 +151,7 @@ Modifications include:
- Addition of encoding options when required (derived from OpenMAX IL)
- Addition of rateControlSupported (missing in OpenMAX AL)
+
Gapless Playback
================
When playing thru an album, the decoders have the ability to skip the encoder
@@ -162,19 +169,19 @@ switch from one track to another and start using data for second track.
The main additions are:
-- set_metadata
-This routine sets the encoder delay and encoder padding. This can be used by
-decoder to strip the silence. This needs to be set before the data in the track
-is written.
+set_metadata
+ This routine sets the encoder delay and encoder padding. This can be used by
+ decoder to strip the silence. This needs to be set before the data in the track
+ is written.
-- set_next_track
-This routine tells DSP that metadata and write operation sent after this would
-correspond to subsequent track
+set_next_track
+ This routine tells DSP that metadata and write operation sent after this would
+ correspond to subsequent track
-- partial drain
-This is called when end of file is reached. The userspace can inform DSP that
-EOF is reached and now DSP can start skipping padding delay. Also next write
-data would belong to next track
+partial drain
+ This is called when end of file is reached. The userspace can inform DSP that
+ EOF is reached and now DSP can start skipping padding delay. Also next write
+ data would belong to next track
Sequence flow for gapless would be:
- Open
@@ -189,10 +196,12 @@ Sequence flow for gapless would be:
- then call partial_drain to flush most of buffer in DSP
- Fill data of the next track
- DSP switches to second track
+
(note: order for partial_drain and write for next track can be reversed as well)
-Not supported:
+Not supported
+=============
- Support for VoIP/circuit-switched calls is not the target of this
API. Support for dynamic bit-rate changes would require a tight
coupling between the DSP and the host stack, limiting power savings.
@@ -225,7 +234,9 @@ Not supported:
rendered output in time, this does not deal with underrun/overrun and
maybe dealt in user-library
-Credits:
+
+Credits
+=======
- Mark Brown and Liam Girdwood for discussions on the need for this API
- Harsha Priya for her work on intel_sst compressed API
- Rakesh Ughreja for valuable feedback
diff --git a/Documentation/sound/designs/control-names.rst b/Documentation/sound/designs/control-names.rst
new file mode 100644
index 000000000000..7fedd0f33cd9
--- /dev/null
+++ b/Documentation/sound/designs/control-names.rst
@@ -0,0 +1,142 @@
+===========================
+Standard ALSA Control Names
+===========================
+
+This document describes standard names of mixer controls.
+
+Standard Syntax
+---------------
+Syntax: [LOCATION] SOURCE [CHANNEL] [DIRECTION] FUNCTION
+
+
+DIRECTION
+~~~~~~~~~
+================ ===============
+<nothing> both directions
+Playback one direction
+Capture one direction
+Bypass Playback one direction
+Bypass Capture one direction
+================ ===============
+
+FUNCTION
+~~~~~~~~
+======== =================================
+Switch on/off switch
+Volume amplifier
+Route route control, hardware specific
+======== =================================
+
+CHANNEL
+~~~~~~~
+============ ==================================================
+<nothing> channel independent, or applies to all channels
+Front front left/right channels
+Surround rear left/right in 4.0/5.1 surround
+CLFE C/LFE channels
+Center center cannel
+LFE LFE channel
+Side side left/right for 7.1 surround
+============ ==================================================
+
+LOCATION (Physical location of source)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+============ =====================
+Front front position
+Rear rear position
+Dock on docking station
+Internal internal
+============ =====================
+
+SOURCE
+~~~~~~
+=================== =================================================
+Master
+Master Mono
+Hardware Master
+Speaker internal speaker
+Bass Speaker internal LFE speaker
+Headphone
+Line Out
+Beep beep generator
+Phone
+Phone Input
+Phone Output
+Synth
+FM
+Mic
+Headset Mic mic part of combined headset jack - 4-pin
+ headphone + mic
+Headphone Mic mic part of either/or - 3-pin headphone or mic
+Line input only, use "Line Out" for output
+CD
+Video
+Zoom Video
+Aux
+PCM
+PCM Pan
+Loopback
+Analog Loopback D/A -> A/D loopback
+Digital Loopback playback -> capture loopback -
+ without analog path
+Mono
+Mono Output
+Multi
+ADC
+Wave
+Music
+I2S
+IEC958
+HDMI
+SPDIF output only
+SPDIF In
+Digital In
+HDMI/DP either HDMI or DisplayPort
+=================== =================================================
+
+Exceptions (deprecated)
+-----------------------
+
+===================================== =======================
+[Analogue|Digital] Capture Source
+[Analogue|Digital] Capture Switch aka input gain switch
+[Analogue|Digital] Capture Volume aka input gain volume
+[Analogue|Digital] Playback Switch aka output gain switch
+[Analogue|Digital] Playback Volume aka output gain volume
+Tone Control - Switch
+Tone Control - Bass
+Tone Control - Treble
+3D Control - Switch
+3D Control - Center
+3D Control - Depth
+3D Control - Wide
+3D Control - Space
+3D Control - Level
+Mic Boost [(?dB)]
+===================================== =======================
+
+PCM interface
+-------------
+
+=================== ========================================
+Sample Clock Source { "Word", "Internal", "AutoSync" }
+Clock Sync Status { "Lock", "Sync", "No Lock" }
+External Rate external capture rate
+Capture Rate capture rate taken from external source
+=================== ========================================
+
+IEC958 (S/PDIF) interface
+-------------------------
+
+============================================ ======================================
+IEC958 [...] [Playback|Capture] Switch turn on/off the IEC958 interface
+IEC958 [...] [Playback|Capture] Volume digital volume control
+IEC958 [...] [Playback|Capture] Default default or global value - read/write
+IEC958 [...] [Playback|Capture] Mask consumer and professional mask
+IEC958 [...] [Playback|Capture] Con Mask consumer mask
+IEC958 [...] [Playback|Capture] Pro Mask professional mask
+IEC958 [...] [Playback|Capture] PCM Stream the settings assigned to a PCM stream
+IEC958 Q-subcode [Playback|Capture] Default Q-subcode bits
+
+IEC958 Preamble [Playback|Capture] Default burst preamble words (4*16bits)
+============================================ ======================================
diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst
new file mode 100644
index 000000000000..04dcdae3e4f2
--- /dev/null
+++ b/Documentation/sound/designs/index.rst
@@ -0,0 +1,15 @@
+Designs and Implementations
+===========================
+
+.. toctree::
+ :maxdepth: 2
+
+ control-names
+ channel-mapping-api
+ compress-offload
+ timestamping
+ jack-controls
+ procfile
+ powersave
+ oss-emulation
+ seq-oss
diff --git a/Documentation/sound/alsa/Jack-Controls.txt b/Documentation/sound/designs/jack-controls.rst
index fe1c5e0c8555..ae25b1531bb0 100644
--- a/Documentation/sound/alsa/Jack-Controls.txt
+++ b/Documentation/sound/designs/jack-controls.rst
@@ -1,3 +1,7 @@
+==================
+ALSA Jack Controls
+==================
+
Why we need Jack kcontrols
==========================
@@ -29,11 +33,12 @@ How to use jack kcontrols
=========================
In order to keep compatibility, snd_jack_new() has been modified by
-adding two params :-
+adding two params:
- - @initial_kctl: if true, create a kcontrol and add it to the jack
- list.
- - @phantom_jack: Don't create a input device for phantom jacks.
+initial_kctl
+ if true, create a kcontrol and add it to the jack list.
+phantom_jack
+ Don't create a input device for phantom jacks.
HDA jacks can set phantom_jack to true in order to create a phantom
jack and set initial_kctl to true to create an initial kcontrol with
diff --git a/Documentation/sound/alsa/OSS-Emulation.txt b/Documentation/sound/designs/oss-emulation.rst
index 152ca2a3f1bd..e8dcb9633e7b 100644
--- a/Documentation/sound/alsa/OSS-Emulation.txt
+++ b/Documentation/sound/designs/oss-emulation.rst
@@ -1,7 +1,8 @@
- NOTES ON KERNEL OSS-EMULATION
- =============================
+=============================
+Notes on Kernel OSS-Emulation
+=============================
- Jan. 22, 2004 Takashi Iwai <tiwai@suse.de>
+Jan. 22, 2004 Takashi Iwai <tiwai@suse.de>
Modules
@@ -14,18 +15,18 @@ When you need to access the OSS PCM, mixer or sequencer devices, the
corresponding module has to be loaded.
These modules are loaded automatically when the corresponding service
-is called. The alias is defined sound-service-x-y, where x and y are
+is called. The alias is defined ``sound-service-x-y``, where x and y are
the card number and the minor unit number. Usually you don't have to
define these aliases by yourself.
Only necessary step for auto-loading of OSS modules is to define the
-card alias in /etc/modprobe.d/alsa.conf, such as
+card alias in ``/etc/modprobe.d/alsa.conf``, such as::
alias sound-slot-0 snd-emu10k1
-As the second card, define sound-slot-1 as well.
+As the second card, define ``sound-slot-1`` as well.
Note that you can't use the aliased name as the target name (i.e.
-"alias sound-slot-0 snd-card-0" doesn't work any more like the old
+``alias sound-slot-0 snd-card-0`` doesn't work any more like the old
modutils).
The currently available OSS configuration is shown in
@@ -42,6 +43,7 @@ Device Mapping
==============
ALSA supports the following OSS device files:
+::
PCM:
/dev/dspX
@@ -61,48 +63,55 @@ ALSA supports the following OSS device files:
where X is the card number from 0 to 7.
(NOTE: Some distributions have the device files like /dev/midi0 and
- /dev/midi1. They are NOT for OSS but for tclmidi, which is
- a totally different thing.)
+/dev/midi1. They are NOT for OSS but for tclmidi, which is
+a totally different thing.)
Unlike the real OSS, ALSA cannot use the device files more than the
assigned ones. For example, the first card cannot use /dev/dsp1 or
/dev/dsp2, but only /dev/dsp0 and /dev/adsp0.
As seen above, PCM and MIDI may have two devices. Usually, the first
-PCM device (hw:0,0 in ALSA) is mapped to /dev/dsp and the secondary
-device (hw:0,1) to /dev/adsp (if available). For MIDI, /dev/midi and
+PCM device (``hw:0,0`` in ALSA) is mapped to /dev/dsp and the secondary
+device (``hw:0,1``) to /dev/adsp (if available). For MIDI, /dev/midi and
/dev/amidi, respectively.
You can change this device mapping via the module options of
snd-pcm-oss and snd-rawmidi. In the case of PCM, the following
options are available for snd-pcm-oss:
- dsp_map PCM device number assigned to /dev/dspX
- (default = 0)
- adsp_map PCM device number assigned to /dev/adspX
- (default = 1)
+dsp_map
+ PCM device number assigned to /dev/dspX
+ (default = 0)
+adsp_map
+ PCM device number assigned to /dev/adspX
+ (default = 1)
-For example, to map the third PCM device (hw:0,2) to /dev/adsp0,
+For example, to map the third PCM device (``hw:0,2``) to /dev/adsp0,
define like this:
+::
options snd-pcm-oss adsp_map=2
The options take arrays. For configuring the second card, specify
two entries separated by comma. For example, to map the third PCM
device on the second card to /dev/adsp1, define like below:
+::
options snd-pcm-oss adsp_map=0,2
To change the mapping of MIDI devices, the following options are
available for snd-rawmidi:
- midi_map MIDI device number assigned to /dev/midi0X
- (default = 0)
- amidi_map MIDI device number assigned to /dev/amidi0X
- (default = 1)
+midi_map
+ MIDI device number assigned to /dev/midi0X
+ (default = 0)
+amidi_map
+ MIDI device number assigned to /dev/amidi0X
+ (default = 1)
For example, to assign the third MIDI device on the first card to
/dev/midi00, define as follows:
+::
options snd-rawmidi midi_map=2
@@ -118,43 +127,52 @@ wine, especially if they use the card only in the MMAP mode.
In such a case, you can change the behavior of PCM per application by
writing a command to the proc file. There is a proc file for each PCM
-stream, /proc/asound/cardX/pcmY[cp]/oss, where X is the card number
-(zero-based), Y the PCM device number (zero-based), and 'p' is for
-playback and 'c' for capture, respectively. Note that this proc file
+stream, ``/proc/asound/cardX/pcmY[cp]/oss``, where X is the card number
+(zero-based), Y the PCM device number (zero-based), and ``p`` is for
+playback and ``c`` for capture, respectively. Note that this proc file
exists only after snd-pcm-oss module is loaded.
The command sequence has the following syntax:
+::
app_name fragments fragment_size [options]
-app_name is the name of application with (higher priority) or without
+``app_name`` is the name of application with (higher priority) or without
path.
-fragments specifies the number of fragments or zero if no specific
+``fragments`` specifies the number of fragments or zero if no specific
number is given.
-fragment_size is the size of fragment in bytes or zero if not given.
-options is the optional parameters. The following options are
+``fragment_size`` is the size of fragment in bytes or zero if not given.
+``options`` is the optional parameters. The following options are
available:
- disable the application tries to open a pcm device for
- this channel but does not want to use it.
- direct don't use plugins
- block force block open mode
- non-block force non-block open mode
- partial-frag write also partial fragments (affects playback only)
- no-silence do not fill silence ahead to avoid clicks
-
-The disable option is useful when one stream direction (playback or
+disable
+ the application tries to open a pcm device for
+ this channel but does not want to use it.
+direct
+ don't use plugins
+block
+ force block open mode
+non-block
+ force non-block open mode
+partial-frag
+ write also partial fragments (affects playback only)
+no-silence
+ do not fill silence ahead to avoid clicks
+
+The ``disable`` option is useful when one stream direction (playback or
capture) is not handled correctly by the application although the
hardware itself does support both directions.
-The direct option is used, as mentioned above, to bypass the automatic
+The ``direct`` option is used, as mentioned above, to bypass the automatic
conversion and useful for MMAP-applications.
For example, to playback the first PCM device without plugins for
quake, send a command via echo like the following:
+::
% echo "quake 0 0 direct" > /proc/asound/card0/pcm0p/oss
While quake wants only playback, you may append the second command
to notify driver that only this direction is about to be allocated:
+::
% echo "quake 0 0 disable" > /proc/asound/card0/pcm0c/oss
@@ -171,10 +189,11 @@ the file when it's busy. The -EBUSY error is returned in this case.
This blocking behavior can be changed globally via nonblock_open
module option of snd-pcm-oss. For using the blocking mode as default
for OSS devices, define like the following:
+::
options snd-pcm-oss nonblock_open=0
-The partial-frag and no-silence commands have been added recently.
+The ``partial-frag`` and ``no-silence`` commands have been added recently.
Both commands are for optimization use only. The former command
specifies to invoke the write transfer only when the whole fragment is
filled. The latter stops writing the silence data ahead
@@ -183,15 +202,18 @@ automatically. Both are disabled as default.
You can check the currently defined configuration by reading the proc
file. The read image can be sent to the proc file again, hence you
can save the current configuration
+::
% cat /proc/asound/card0/pcm0p/oss > /somewhere/oss-cfg
and restore it like
+::
% cat /somewhere/oss-cfg > /proc/asound/card0/pcm0p/oss
-Also, for clearing all the current configuration, send "erase" command
+Also, for clearing all the current configuration, send ``erase`` command
as below:
+::
% echo "erase" > /proc/asound/card0/pcm0p/oss
@@ -211,40 +233,43 @@ automatically.
As default, ALSA uses the following control for OSS volumes:
- OSS volume ALSA control Index
- -----------------------------------------------------
- SOUND_MIXER_VOLUME Master 0
- SOUND_MIXER_BASS Tone Control - Bass 0
- SOUND_MIXER_TREBLE Tone Control - Treble 0
- SOUND_MIXER_SYNTH Synth 0
- SOUND_MIXER_PCM PCM 0
- SOUND_MIXER_SPEAKER PC Speaker 0
- SOUND_MIXER_LINE Line 0
- SOUND_MIXER_MIC Mic 0
- SOUND_MIXER_CD CD 0
- SOUND_MIXER_IMIX Monitor Mix 0
- SOUND_MIXER_ALTPCM PCM 1
- SOUND_MIXER_RECLEV (not assigned)
- SOUND_MIXER_IGAIN Capture 0
- SOUND_MIXER_OGAIN Playback 0
- SOUND_MIXER_LINE1 Aux 0
- SOUND_MIXER_LINE2 Aux 1
- SOUND_MIXER_LINE3 Aux 2
- SOUND_MIXER_DIGITAL1 Digital 0
- SOUND_MIXER_DIGITAL2 Digital 1
- SOUND_MIXER_DIGITAL3 Digital 2
- SOUND_MIXER_PHONEIN Phone 0
- SOUND_MIXER_PHONEOUT Phone 1
- SOUND_MIXER_VIDEO Video 0
- SOUND_MIXER_RADIO Radio 0
- SOUND_MIXER_MONITOR Monitor 0
+==================== ===================== =====
+OSS volume ALSA control Index
+==================== ===================== =====
+SOUND_MIXER_VOLUME Master 0
+SOUND_MIXER_BASS Tone Control - Bass 0
+SOUND_MIXER_TREBLE Tone Control - Treble 0
+SOUND_MIXER_SYNTH Synth 0
+SOUND_MIXER_PCM PCM 0
+SOUND_MIXER_SPEAKER PC Speaker 0
+SOUND_MIXER_LINE Line 0
+SOUND_MIXER_MIC Mic 0
+SOUND_MIXER_CD CD 0
+SOUND_MIXER_IMIX Monitor Mix 0
+SOUND_MIXER_ALTPCM PCM 1
+SOUND_MIXER_RECLEV (not assigned)
+SOUND_MIXER_IGAIN Capture 0
+SOUND_MIXER_OGAIN Playback 0
+SOUND_MIXER_LINE1 Aux 0
+SOUND_MIXER_LINE2 Aux 1
+SOUND_MIXER_LINE3 Aux 2
+SOUND_MIXER_DIGITAL1 Digital 0
+SOUND_MIXER_DIGITAL2 Digital 1
+SOUND_MIXER_DIGITAL3 Digital 2
+SOUND_MIXER_PHONEIN Phone 0
+SOUND_MIXER_PHONEOUT Phone 1
+SOUND_MIXER_VIDEO Video 0
+SOUND_MIXER_RADIO Radio 0
+SOUND_MIXER_MONITOR Monitor 0
+==================== ===================== =====
The second column is the base-string of the corresponding ALSA
-control. In fact, the controls with "XXX [Playback|Capture]
-[Volume|Switch]" will be checked in addition.
+control. In fact, the controls with ``XXX [Playback|Capture]
+[Volume|Switch]`` will be checked in addition.
The current assignment of these mixer elements is listed in the proc
file, /proc/asound/cardX/oss_mixer, which will be like the following
+::
VOLUME "Master" 0
BASS "" 0
@@ -261,6 +286,7 @@ corresponding OSS control is not available.
For changing the assignment, you can write the configuration to this
proc file. For example, to map "Wave Playback" to the PCM volume,
send the command like the following:
+::
% echo 'VOLUME "Wave Playback" 0' > /proc/asound/card0/oss_mixer
@@ -284,12 +310,18 @@ Duplex Streams
Note that when attempting to use a single device file for playback and
capture, the OSS API provides no way to set the format, sample rate or
number of channels different in each direction. Thus
+::
+
io_handle = open("device", O_RDWR)
+
will only function correctly if the values are the same in each direction.
To use different values in the two directions, use both
+::
+
input_handle = open("device", O_RDONLY)
output_handle = open("device", O_WRONLY)
+
and set the values for the corresponding handle.
@@ -302,4 +334,3 @@ ICE1712 supports only the unconventional format, interleaved
10-channels 24bit (packed in 32bit) format. Therefore you cannot mmap
the buffer as the conventional (mono or 2-channels, 8 or 16bit) format
on OSS.
-
diff --git a/Documentation/sound/alsa/powersave.txt b/Documentation/sound/designs/powersave.rst
index 9657e8099228..138157452eb9 100644
--- a/Documentation/sound/alsa/powersave.txt
+++ b/Documentation/sound/designs/powersave.rst
@@ -1,9 +1,10 @@
+==========================
Notes on Power-Saving Mode
==========================
AC97 and HD-audio drivers have the automatic power-saving mode.
-This feature is enabled via Kconfig CONFIG_SND_AC97_POWER_SAVE
-and CONFIG_SND_HDA_POWER_SAVE options, respectively.
+This feature is enabled via Kconfig ``CONFIG_SND_AC97_POWER_SAVE``
+and ``CONFIG_SND_HDA_POWER_SAVE`` options, respectively.
With the automatic power-saving, the driver turns off the codec power
appropriately when no operation is required. When no applications use
@@ -11,20 +12,21 @@ the device and/or no analog loopback is set, the power disablement is
done fully or partially. It'll save a certain power consumption, thus
good for laptops (even for desktops).
-The time-out for automatic power-off can be specified via power_save
+The time-out for automatic power-off can be specified via ``power_save``
module option of snd-ac97-codec and snd-hda-intel modules. Specify
the time-out value in seconds. 0 means to disable the automatic
power-saving. The default value of timeout is given via
-CONFIG_SND_AC97_POWER_SAVE_DEFAULT and
-CONFIG_SND_HDA_POWER_SAVE_DEFAULT Kconfig options. Setting this to 1
+``CONFIG_SND_AC97_POWER_SAVE_DEFAULT`` and
+``CONFIG_SND_HDA_POWER_SAVE_DEFAULT`` Kconfig options. Setting this to 1
(the minimum value) isn't recommended because many applications try to
reopen the device frequently. 10 would be a good choice for normal
operations.
-The power_save option is exported as writable. This means you can
+The ``power_save`` option is exported as writable. This means you can
adjust the value via sysfs on the fly. For example, to turn on the
automatic power-save mode with 10 seconds, write to
-/sys/modules/snd_ac97_codec/parameters/power_save (usually as root):
+``/sys/modules/snd_ac97_codec/parameters/power_save`` (usually as root):
+::
# echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save
diff --git a/Documentation/sound/alsa/Procfile.txt b/Documentation/sound/designs/procfile.rst
index 7f8a0d325905..29a466851fd2 100644
--- a/Documentation/sound/alsa/Procfile.txt
+++ b/Documentation/sound/designs/procfile.rst
@@ -1,20 +1,22 @@
- Proc Files of ALSA Drivers
- ==========================
- Takashi Iwai <tiwai@suse.de>
+==========================
+Proc Files of ALSA Drivers
+==========================
+
+Takashi Iwai <tiwai@suse.de>
General
--------
+=======
ALSA has its own proc tree, /proc/asound. Many useful information are
found in this tree. When you encounter a problem and need debugging,
check the files listed in the following sections.
Each card has its subtree cardX, where X is from 0 to 7. The
-card-specific files are stored in the card* subdirectories.
+card-specific files are stored in the ``card*`` subdirectories.
Global Information
-------------------
+==================
cards
Shows the list of currently configured ALSA drivers,
@@ -31,15 +33,15 @@ devices
meminfo
Shows the status of allocated pages via ALSA drivers.
- Appears only when CONFIG_SND_DEBUG=y.
+ Appears only when ``CONFIG_SND_DEBUG=y``.
hwdep
Lists the currently available hwdep devices in format of
- <card>-<device>: <name>
+ ``<card>-<device>: <name>``
pcm
Lists the currently available PCM devices in format of
- <card>-<device>: <id>: <name> : <sub-streams>
+ ``<card>-<device>: <id>: <name> : <sub-streams>``
timer
Lists the currently available timer devices
@@ -54,23 +56,23 @@ oss/sndstat
Card Specific Files
--------------------
+===================
-The card-specific files are found in /proc/asound/card* directories.
+The card-specific files are found in ``/proc/asound/card*`` directories.
Some drivers (e.g. cmipci) have their own proc entries for the
-register dump, etc (e.g. /proc/asound/card*/cmipci shows the register
+register dump, etc (e.g. ``/proc/asound/card*/cmipci`` shows the register
dump). These files would be really helpful for debugging.
When PCM devices are available on this card, you can see directories
like pcm0p or pcm1c. They hold the PCM information for each PCM
-stream. The number after 'pcm' is the PCM device number from 0, and
-the last 'p' or 'c' means playback or capture direction. The files in
+stream. The number after ``pcm`` is the PCM device number from 0, and
+the last ``p`` or ``c`` means playback or capture direction. The files in
this subtree is described later.
-The status of MIDI I/O is found in midi* files. It shows the device
+The status of MIDI I/O is found in ``midi*`` files. It shows the device
name and the received/transmitted bytes through the MIDI device.
-When the card is equipped with AC97 codecs, there are codec97#*
+When the card is equipped with AC97 codecs, there are ``codec97#*``
subdirectories (described later).
When the OSS mixer emulation is enabled (and the module is loaded),
@@ -81,26 +83,27 @@ details.
PCM Proc Files
---------------
+==============
-card*/pcm*/info
+``card*/pcm*/info``
The general information of this PCM device: card #, device #,
substreams, etc.
-card*/pcm*/xrun_debug
- This file appears when CONFIG_SND_DEBUG=y and
- CONFIG_PCM_XRUN_DEBUG=y.
+``card*/pcm*/xrun_debug``
+ This file appears when ``CONFIG_SND_DEBUG=y`` and
+ ``CONFIG_PCM_XRUN_DEBUG=y``.
This shows the status of xrun (= buffer overrun/xrun) and
invalid PCM position debug/check of ALSA PCM middle layer.
It takes an integer value, can be changed by writing to this
- file, such as
+ file, such as::
# echo 5 > /proc/asound/card0/pcm0p/xrun_debug
The value consists of the following bit flags:
- bit 0 = Enable XRUN/jiffies debug messages
- bit 1 = Show stack trace at XRUN / jiffies check
- bit 2 = Enable additional jiffies check
+
+ * bit 0 = Enable XRUN/jiffies debug messages
+ * bit 1 = Show stack trace at XRUN / jiffies check
+ * bit 2 = Enable additional jiffies check
When the bit 0 is set, the driver will show the messages to
kernel log when an xrun is detected. The debug message is
@@ -117,72 +120,74 @@ card*/pcm*/xrun_debug
buggy) hardware that doesn't give smooth pointer updates.
This feature is enabled via the bit 2.
-card*/pcm*/sub*/info
+``card*/pcm*/sub*/info``
The general information of this PCM sub-stream.
-card*/pcm*/sub*/status
+``card*/pcm*/sub*/status``
The current status of this PCM sub-stream, elapsed time,
H/W position, etc.
-card*/pcm*/sub*/hw_params
+``card*/pcm*/sub*/hw_params``
The hardware parameters set for this sub-stream.
-card*/pcm*/sub*/sw_params
+``card*/pcm*/sub*/sw_params``
The soft parameters set for this sub-stream.
-card*/pcm*/sub*/prealloc
+``card*/pcm*/sub*/prealloc``
The buffer pre-allocation information.
-card*/pcm*/sub*/xrun_injection
+``card*/pcm*/sub*/xrun_injection``
Triggers an XRUN to the running stream when any value is
written to this proc file. Used for fault injection.
This entry is write-only.
AC97 Codec Information
-----------------------
+======================
-card*/codec97#*/ac97#?-?
+``card*/codec97#*/ac97#?-?``
Shows the general information of this AC97 codec chip, such as
name, capabilities, set up.
-card*/codec97#0/ac97#?-?+regs
+``card*/codec97#0/ac97#?-?+regs``
Shows the AC97 register dump. Useful for debugging.
When CONFIG_SND_DEBUG is enabled, you can write to this file for
changing an AC97 register directly. Pass two hex numbers.
For example,
+::
+
# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
USB Audio Streams
------------------
+=================
-card*/stream*
+``card*/stream*``
Shows the assignment and the current status of each audio stream
of the given card. This information is very useful for debugging.
HD-Audio Codecs
----------------
+===============
-card*/codec#*
+``card*/codec#*``
Shows the general codec information and the attribute of each
widget node.
-card*/eld#*
+``card*/eld#*``
Available for HDMI or DisplayPort interfaces.
Shows ELD(EDID Like Data) info retrieved from the attached HDMI sink,
and describes its audio capabilities and configurations.
- Some ELD fields may be modified by doing `echo name hex_value > eld#*`.
+ Some ELD fields may be modified by doing ``echo name hex_value > eld#*``.
Only do this if you are sure the HDMI sink provided value is wrong.
And if that makes your HDMI audio work, please report to us so that we
can fix it in future kernel releases.
Sequencer Information
----------------------
+=====================
seq/drivers
Lists the currently available ALSA sequencer drivers.
@@ -203,7 +208,7 @@ seq/oss
Help For Debugging?
--------------------
+===================
When the problem is related with PCM, first try to turn on xrun_debug
mode. This will give you the kernel messages when and where xrun
@@ -211,24 +216,23 @@ happened.
If it's really a bug, report it with the following information:
- - the name of the driver/card, show in /proc/asound/cards
- - the register dump, if available (e.g. card*/cmipci)
+- the name of the driver/card, show in ``/proc/asound/cards``
+- the register dump, if available (e.g. ``card*/cmipci``)
when it's a PCM problem,
- - set-up of PCM, shown in hw_parms, sw_params, and status in the PCM
- sub-stream directory
+- set-up of PCM, shown in hw_parms, sw_params, and status in the PCM
+ sub-stream directory
when it's a mixer problem,
- - AC97 proc files, codec97#*/* files
+- AC97 proc files, ``codec97#*/*`` files
for USB audio/midi,
- - output of lsusb -v
- - stream* files in card directory
+- output of ``lsusb -v``
+- ``stream*`` files in card directory
The ALSA bug-tracking system is found at:
-
- https://bugtrack.alsa-project.org/alsa-bug/
+https://bugtrack.alsa-project.org/alsa-bug/
diff --git a/Documentation/sound/designs/seq-oss.rst b/Documentation/sound/designs/seq-oss.rst
new file mode 100644
index 000000000000..e82ffe0e7f43
--- /dev/null
+++ b/Documentation/sound/designs/seq-oss.rst
@@ -0,0 +1,371 @@
+===============================
+OSS Sequencer Emulation on ALSA
+===============================
+
+Copyright (c) 1998,1999 by Takashi Iwai
+
+ver.0.1.8; Nov. 16, 1999
+
+Description
+===========
+
+This directory contains the OSS sequencer emulation driver on ALSA. Note
+that this program is still in the development state.
+
+What this does - it provides the emulation of the OSS sequencer, access
+via ``/dev/sequencer`` and ``/dev/music`` devices.
+The most of applications using OSS can run if the appropriate ALSA
+sequencer is prepared.
+
+The following features are emulated by this driver:
+
+* Normal sequencer and MIDI events:
+
+ They are converted to the ALSA sequencer events, and sent to the
+ corresponding port.
+
+* Timer events:
+
+ The timer is not selectable by ioctl. The control rate is fixed to
+ 100 regardless of HZ. That is, even on Alpha system, a tick is always
+ 1/100 second. The base rate and tempo can be changed in ``/dev/music``.
+
+* Patch loading:
+
+ It purely depends on the synth drivers whether it's supported since
+ the patch loading is realized by callback to the synth driver.
+
+* I/O controls:
+
+ Most of controls are accepted. Some controls
+ are dependent on the synth driver, as well as even on original OSS.
+
+Furthermore, you can find the following advanced features:
+
+* Better queue mechanism:
+
+ The events are queued before processing them.
+
+* Multiple applications:
+
+ You can run two or more applications simultaneously (even for OSS
+ sequencer)!
+ However, each MIDI device is exclusive - that is, if a MIDI device
+ is opened once by some application, other applications can't use
+ it. No such a restriction in synth devices.
+
+* Real-time event processing:
+
+ The events can be processed in real time without using out of bound
+ ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
+ events will be processed in real-time without queued. To switch off the
+ real-time mode, send RELTIME 0 event.
+
+* ``/proc`` interface:
+
+ The status of applications and devices can be shown via
+ ``/proc/asound/seq/oss`` at any time. In the later version,
+ configuration will be changed via ``/proc`` interface, too.
+
+
+Installation
+============
+
+Run configure script with both sequencer support (``--with-sequencer=yes``)
+and OSS emulation (``--with-oss=yes``) options. A module ``snd-seq-oss.o``
+will be created. If the synth module of your sound card supports for OSS
+emulation (so far, only Emu8000 driver), this module will be loaded
+automatically.
+Otherwise, you need to load this module manually.
+
+At beginning, this module probes all the MIDI ports which have been
+already connected to the sequencer. Once after that, the creation and deletion
+of ports are watched by announcement mechanism of ALSA sequencer.
+
+The available synth and MIDI devices can be found in proc interface.
+Run ``cat /proc/asound/seq/oss``, and check the devices. For example,
+if you use an AWE64 card, you'll see like the following:
+::
+
+ OSS sequencer emulation version 0.1.8
+ ALSA client number 63
+ ALSA receiver port 0
+
+ Number of applications: 0
+
+ Number of synth devices: 1
+ synth 0: [EMU8000]
+ type 0x1 : subtype 0x20 : voices 32
+ capabilties : ioctl enabled / load_patch enabled
+
+ Number of MIDI devices: 3
+ midi 0: [Emu8000 Port-0] ALSA port 65:0
+ capability write / opened none
+
+ midi 1: [Emu8000 Port-1] ALSA port 65:1
+ capability write / opened none
+
+ midi 2: [0: MPU-401 (UART)] ALSA port 64:0
+ capability read/write / opened none
+
+Note that the device number may be different from the information of
+``/proc/asound/oss-devices`` or ones of the original OSS driver.
+Use the device number listed in ``/proc/asound/seq/oss``
+to play via OSS sequencer emulation.
+
+Using Synthesizer Devices
+=========================
+
+Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
+and xmp-1.1.5. You can load samples via ``/dev/sequencer`` like sfxload,
+too.
+
+If the lowlevel driver supports multiple access to synth devices (like
+Emu8000 driver), two or more applications are allowed to run at the same
+time.
+
+Using MIDI Devices
+==================
+
+So far, only MIDI output was tested. MIDI input was not checked at all,
+but hopefully it will work. Use the device number listed in
+``/proc/asound/seq/oss``.
+Be aware that these numbers are mostly different from the list in
+``/proc/asound/oss-devices``.
+
+Module Options
+==============
+
+The following module options are available:
+
+maxqlen
+ specifies the maximum read/write queue length. This queue is private
+ for OSS sequencer, so that it is independent from the queue length of ALSA
+ sequencer. Default value is 1024.
+
+seq_oss_debug
+ specifies the debug level and accepts zero (= no debug message) or
+ positive integer. Default value is 0.
+
+Queue Mechanism
+===============
+
+OSS sequencer emulation uses an ALSA priority queue. The
+events from ``/dev/sequencer`` are processed and put onto the queue
+specified by module option.
+
+All the events from ``/dev/sequencer`` are parsed at beginning.
+The timing events are also parsed at this moment, so that the events may
+be processed in real-time. Sending an event ABSTIME 0 switches the operation
+mode to real-time mode, and sending an event RELTIME 0 switches it off.
+In the real-time mode, all events are dispatched immediately.
+
+The queued events are dispatched to the corresponding ALSA sequencer
+ports after scheduled time by ALSA sequencer dispatcher.
+
+If the write-queue is full, the application sleeps until a certain amount
+(as default one half) becomes empty in blocking mode. The synchronization
+to write timing was implemented, too.
+
+The input from MIDI devices or echo-back events are stored on read FIFO
+queue. If application reads ``/dev/sequencer`` in blocking mode, the
+process will be awaked.
+
+Interface to Synthesizer Device
+===============================
+
+Registration
+------------
+
+To register an OSS synthesizer device, use snd_seq_oss_synth_register()
+function:
+::
+
+ int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
+ snd_seq_oss_callback_t *oper, void *private_data)
+
+The arguments ``name``, ``type``, ``subtype`` and ``nvoices``
+are used for making the appropriate synth_info structure for ioctl. The
+return value is an index number of this device. This index must be remembered
+for unregister. If registration is failed, -errno will be returned.
+
+To release this device, call snd_seq_oss_synth_unregister() function:
+::
+
+ int snd_seq_oss_synth_unregister(int index)
+
+where the ``index`` is the index number returned by register function.
+
+Callbacks
+---------
+
+OSS synthesizer devices have capability for sample downloading and ioctls
+like sample reset. In OSS emulation, these special features are realized
+by using callbacks. The registration argument oper is used to specify these
+callbacks. The following callback functions must be defined:
+::
+
+ snd_seq_oss_callback_t:
+ int (*open)(snd_seq_oss_arg_t *p, void *closure);
+ int (*close)(snd_seq_oss_arg_t *p);
+ int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
+ int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
+ int (*reset)(snd_seq_oss_arg_t *p);
+
+Except for ``open`` and ``close`` callbacks, they are allowed to be NULL.
+
+Each callback function takes the argument type ``snd_seq_oss_arg_t`` as the
+first argument.
+::
+
+ struct snd_seq_oss_arg_t {
+ int app_index;
+ int file_mode;
+ int seq_mode;
+ snd_seq_addr_t addr;
+ void *private_data;
+ int event_passing;
+ };
+
+The first three fields, ``app_index``, ``file_mode`` and ``seq_mode``
+are initialized by OSS sequencer. The ``app_index`` is the application
+index which is unique to each application opening OSS sequencer. The
+``file_mode`` is bit-flags indicating the file operation mode. See
+``seq_oss.h`` for its meaning. The ``seq_mode`` is sequencer operation
+mode. In the current version, only ``SND_OSSSEQ_MODE_SYNTH`` is used.
+
+The next two fields, ``addr`` and ``private_data``, must be
+filled by the synth driver at open callback. The ``addr`` contains
+the address of ALSA sequencer port which is assigned to this device. If
+the driver allocates memory for ``private_data``, it must be released
+in close callback by itself.
+
+The last field, ``event_passing``, indicates how to translate note-on
+/ off events. In ``PROCESS_EVENTS`` mode, the note 255 is regarded
+as velocity change, and key pressure event is passed to the port. In
+``PASS_EVENTS`` mode, all note on/off events are passed to the port
+without modified. ``PROCESS_KEYPRESS`` mode checks the note above 128
+and regards it as key pressure event (mainly for Emu8000 driver).
+
+Open Callback
+-------------
+
+The ``open`` is called at each time this device is opened by an application
+using OSS sequencer. This must not be NULL. Typically, the open callback
+does the following procedure:
+
+#. Allocate private data record.
+#. Create an ALSA sequencer port.
+#. Set the new port address on ``arg->addr``.
+#. Set the private data record pointer on ``arg->private_data``.
+
+Note that the type bit-flags in port_info of this synth port must NOT contain
+``TYPE_MIDI_GENERIC``
+bit. Instead, ``TYPE_SPECIFIC`` should be used. Also, ``CAP_SUBSCRIPTION``
+bit should NOT be included, too. This is necessary to tell it from other
+normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
+return -errno.
+
+Ioctl Callback
+--------------
+
+The ``ioctl`` callback is called when the sequencer receives device-specific
+ioctls. The following two ioctls should be processed by this callback:
+
+IOCTL_SEQ_RESET_SAMPLES
+ reset all samples on memory -- return 0
+
+IOCTL_SYNTH_MEMAVL
+ return the available memory size
+
+FM_4OP_ENABLE
+ can be ignored usually
+
+The other ioctls are processed inside the sequencer without passing to
+the lowlevel driver.
+
+Load_Patch Callback
+-------------------
+
+The ``load_patch`` callback is used for sample-downloading. This callback
+must read the data on user-space and transfer to each device. Return 0
+if succeeded, and -errno if failed. The format argument is the patch key
+in patch_info record. The buf is user-space pointer where patch_info record
+is stored. The offs can be ignored. The count is total data size of this
+sample data.
+
+Close Callback
+--------------
+
+The ``close`` callback is called when this device is closed by the
+application. If any private data was allocated in open callback, it must
+be released in the close callback. The deletion of ALSA port should be
+done here, too. This callback must not be NULL.
+
+Reset Callback
+--------------
+
+The ``reset`` callback is called when sequencer device is reset or
+closed by applications. The callback should turn off the sounds on the
+relevant port immediately, and initialize the status of the port. If this
+callback is undefined, OSS seq sends a ``HEARTBEAT`` event to the
+port.
+
+Events
+======
+
+Most of the events are processed by sequencer and translated to the adequate
+ALSA sequencer events, so that each synth device can receive by input_event
+callback of ALSA sequencer port. The following ALSA events should be
+implemented by the driver:
+
+============= ===================
+ALSA event Original OSS events
+============= ===================
+NOTEON SEQ_NOTEON, MIDI_NOTEON
+NOTE SEQ_NOTEOFF, MIDI_NOTEOFF
+KEYPRESS MIDI_KEY_PRESSURE
+CHANPRESS SEQ_AFTERTOUCH, MIDI_CHN_PRESSURE
+PGMCHANGE SEQ_PGMCHANGE, MIDI_PGM_CHANGE
+PITCHBEND SEQ_CONTROLLER(CTRL_PITCH_BENDER),
+ MIDI_PITCH_BEND
+CONTROLLER MIDI_CTL_CHANGE,
+ SEQ_BALANCE (with CTL_PAN)
+CONTROL14 SEQ_CONTROLLER
+REGPARAM SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
+SYSEX SEQ_SYSEX
+============= ===================
+
+The most of these behavior can be realized by MIDI emulation driver
+included in the Emu8000 lowlevel driver. In the future release, this module
+will be independent.
+
+Some OSS events (``SEQ_PRIVATE`` and ``SEQ_VOLUME`` events) are passed as event
+type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
+packets without any modification. The lowlevel driver should process these
+events appropriately.
+
+Interface to MIDI Device
+========================
+
+Since the OSS emulation probes the creation and deletion of ALSA MIDI
+sequencer ports automatically by receiving announcement from ALSA
+sequencer, the MIDI devices don't need to be registered explicitly
+like synth devices.
+However, the MIDI port_info registered to ALSA sequencer must include
+a group name ``SND_SEQ_GROUP_DEVICE`` and a capability-bit
+``CAP_READ`` or ``CAP_WRITE``. Also, subscription capabilities,
+``CAP_SUBS_READ`` or ``CAP_SUBS_WRITE``, must be defined, too. If
+these conditions are not satisfied, the port is not registered as OSS
+sequencer MIDI device.
+
+The events via MIDI devices are parsed in OSS sequencer and converted
+to the corresponding ALSA sequencer events. The input from MIDI sequencer
+is also converted to MIDI byte events by OSS sequencer. This works just
+a reverse way of seq_midi module.
+
+Known Problems / TODO's
+=======================
+
+* Patch loading via ALSA instrument layer is not implemented yet.
+
diff --git a/Documentation/sound/alsa/timestamping.txt b/Documentation/sound/designs/timestamping.rst
index 9d579aefbffd..2b0fff503415 100644
--- a/Documentation/sound/alsa/timestamping.txt
+++ b/Documentation/sound/designs/timestamping.rst
@@ -1,18 +1,22 @@
+=====================
+ALSA PCM Timestamping
+=====================
+
The ALSA API can provide two different system timestamps:
- Trigger_tstamp is the system time snapshot taken when the .trigger
-callback is invoked. This snapshot is taken by the ALSA core in the
-general case, but specific hardware may have synchronization
-capabilities or conversely may only be able to provide a correct
-estimate with a delay. In the latter two cases, the low-level driver
-is responsible for updating the trigger_tstamp at the most appropriate
-and precise moment. Applications should not rely solely on the first
-trigger_tstamp but update their internal calculations if the driver
-provides a refined estimate with a delay.
+ callback is invoked. This snapshot is taken by the ALSA core in the
+ general case, but specific hardware may have synchronization
+ capabilities or conversely may only be able to provide a correct
+ estimate with a delay. In the latter two cases, the low-level driver
+ is responsible for updating the trigger_tstamp at the most appropriate
+ and precise moment. Applications should not rely solely on the first
+ trigger_tstamp but update their internal calculations if the driver
+ provides a refined estimate with a delay.
- tstamp is the current system timestamp updated during the last
-event or application query.
-The difference (tstamp - trigger_tstamp) defines the elapsed time.
+ event or application query.
+ The difference (tstamp - trigger_tstamp) defines the elapsed time.
The ALSA API provides two basic pieces of information, avail
and delay, which combined with the trigger and current system
@@ -22,15 +26,15 @@ the ring buffer and the amount of queued samples.
The use of these different pointers and time information depends on
the application needs:
-- 'avail' reports how much can be written in the ring buffer
-- 'delay' reports the time it will take to hear a new sample after all
-queued samples have been played out.
+- ``avail`` reports how much can be written in the ring buffer
+- ``delay`` reports the time it will take to hear a new sample after all
+ queued samples have been played out.
When timestamps are enabled, the avail/delay information is reported
along with a snapshot of system time. Applications can select from
-CLOCK_REALTIME (NTP corrections including going backwards),
-CLOCK_MONOTONIC (NTP corrections but never going backwards),
-CLOCK_MONOTIC_RAW (without NTP corrections) and change the mode
+``CLOCK_REALTIME`` (NTP corrections including going backwards),
+``CLOCK_MONOTONIC`` (NTP corrections but never going backwards),
+``CLOCK_MONOTIC_RAW`` (without NTP corrections) and change the mode
dynamically with sw_params
@@ -38,17 +42,18 @@ The ALSA API also provide an audio_tstamp which reflects the passage
of time as measured by different components of audio hardware. In
ascii-art, this could be represented as follows (for the playback
case):
+::
+ --------------------------------------------------------------> time
+ ^ ^ ^ ^ ^
+ | | | | |
+ analog link dma app FullBuffer
+ time time time time time
+ | | | | |
+ |< codec delay >|<--hw delay-->|<queued samples>|<---avail->|
+ |<----------------- delay---------------------->| |
+ |<----ring buffer length---->|
---------------------------------------------------------------> time
- ^ ^ ^ ^ ^
- | | | | |
- analog link dma app FullBuffer
- time time time time time
- | | | | |
- |< codec delay >|<--hw delay-->|<queued samples>|<---avail->|
- |<----------------- delay---------------------->| |
- |<----ring buffer length---->|
The analog time is taken at the last stage of the playback, as close
as possible to the actual transducer
@@ -113,11 +118,11 @@ audio applications...
Due to the varied nature of timestamping needs, even for a single
application, the audio_tstamp_config can be changed dynamically. In
-the STATUS ioctl, the parameters are read-only and do not allow for
+the ``STATUS`` ioctl, the parameters are read-only and do not allow for
any application selection. To work around this limitation without
-impacting legacy applications, a new STATUS_EXT ioctl is introduced
+impacting legacy applications, a new ``STATUS_EXT`` ioctl is introduced
with read/write parameters. ALSA-lib will be modified to make use of
-STATUS_EXT and effectively deprecate STATUS.
+``STATUS_EXT`` and effectively deprecate ``STATUS``.
The ALSA API only allows for a single audio timestamp to be reported
at a time. This is a conscious design decision, reading the audio
@@ -135,36 +140,42 @@ the hardware, there is a risk of misalignment with the avail and delay
information. To make sure applications are not confused, a
driver_timestamp field is added in the snd_pcm_status structure; this
timestamp shows when the information is put together by the driver
-before returning from the STATUS and STATUS_EXT ioctl. in most cases
+before returning from the ``STATUS`` and ``STATUS_EXT`` ioctl. in most cases
this driver_timestamp will be identical to the regular system tstamp.
Examples of typestamping with HDaudio:
1. DMA timestamp, no compensation for DMA+analog delay
-$ ./audio_time -p --ts_type=1
-playback: systime: 341121338 nsec, audio time 342000000 nsec, systime delta -878662
-playback: systime: 426236663 nsec, audio time 427187500 nsec, systime delta -950837
-playback: systime: 597080580 nsec, audio time 598000000 nsec, systime delta -919420
-playback: systime: 682059782 nsec, audio time 683020833 nsec, systime delta -961051
-playback: systime: 852896415 nsec, audio time 853854166 nsec, systime delta -957751
-playback: systime: 937903344 nsec, audio time 938854166 nsec, systime delta -950822
+::
+
+ $ ./audio_time -p --ts_type=1
+ playback: systime: 341121338 nsec, audio time 342000000 nsec, systime delta -878662
+ playback: systime: 426236663 nsec, audio time 427187500 nsec, systime delta -950837
+ playback: systime: 597080580 nsec, audio time 598000000 nsec, systime delta -919420
+ playback: systime: 682059782 nsec, audio time 683020833 nsec, systime delta -961051
+ playback: systime: 852896415 nsec, audio time 853854166 nsec, systime delta -957751
+ playback: systime: 937903344 nsec, audio time 938854166 nsec, systime delta -950822
2. DMA timestamp, compensation for DMA+analog delay
-$ ./audio_time -p --ts_type=1 -d
-playback: systime: 341053347 nsec, audio time 341062500 nsec, systime delta -9153
-playback: systime: 426072447 nsec, audio time 426062500 nsec, systime delta 9947
-playback: systime: 596899518 nsec, audio time 596895833 nsec, systime delta 3685
-playback: systime: 681915317 nsec, audio time 681916666 nsec, systime delta -1349
-playback: systime: 852741306 nsec, audio time 852750000 nsec, systime delta -8694
+::
+
+ $ ./audio_time -p --ts_type=1 -d
+ playback: systime: 341053347 nsec, audio time 341062500 nsec, systime delta -9153
+ playback: systime: 426072447 nsec, audio time 426062500 nsec, systime delta 9947
+ playback: systime: 596899518 nsec, audio time 596895833 nsec, systime delta 3685
+ playback: systime: 681915317 nsec, audio time 681916666 nsec, systime delta -1349
+ playback: systime: 852741306 nsec, audio time 852750000 nsec, systime delta -8694
3. link timestamp, compensation for DMA+analog delay
-$ ./audio_time -p --ts_type=2 -d
-playback: systime: 341060004 nsec, audio time 341062791 nsec, systime delta -2787
-playback: systime: 426242074 nsec, audio time 426244875 nsec, systime delta -2801
-playback: systime: 597080992 nsec, audio time 597084583 nsec, systime delta -3591
-playback: systime: 682084512 nsec, audio time 682088291 nsec, systime delta -3779
-playback: systime: 852936229 nsec, audio time 852940916 nsec, systime delta -4687
-playback: systime: 938107562 nsec, audio time 938112708 nsec, systime delta -5146
+::
+
+ $ ./audio_time -p --ts_type=2 -d
+ playback: systime: 341060004 nsec, audio time 341062791 nsec, systime delta -2787
+ playback: systime: 426242074 nsec, audio time 426244875 nsec, systime delta -2801
+ playback: systime: 597080992 nsec, audio time 597084583 nsec, systime delta -3591
+ playback: systime: 682084512 nsec, audio time 682088291 nsec, systime delta -3779
+ playback: systime: 852936229 nsec, audio time 852940916 nsec, systime delta -4687
+ playback: systime: 938107562 nsec, audio time 938112708 nsec, systime delta -5146
Example 1 shows that the timestamp at the DMA level is close to 1ms
ahead of the actual playback time (as a side time this sort of
@@ -181,20 +192,24 @@ shows how compensating for the delay exposes a 1ms accuracy (due to
the use of the frame counter by the driver)
Example 3: DMA timestamp, no compensation for delay, delta of ~5ms
-$ ./audio_time -p -Dhw:1 -t1
-playback: systime: 120174019 nsec, audio time 125000000 nsec, systime delta -4825981
-playback: systime: 245041136 nsec, audio time 250000000 nsec, systime delta -4958864
-playback: systime: 370106088 nsec, audio time 375000000 nsec, systime delta -4893912
-playback: systime: 495040065 nsec, audio time 500000000 nsec, systime delta -4959935
-playback: systime: 620038179 nsec, audio time 625000000 nsec, systime delta -4961821
-playback: systime: 745087741 nsec, audio time 750000000 nsec, systime delta -4912259
-playback: systime: 870037336 nsec, audio time 875000000 nsec, systime delta -4962664
+::
+
+ $ ./audio_time -p -Dhw:1 -t1
+ playback: systime: 120174019 nsec, audio time 125000000 nsec, systime delta -4825981
+ playback: systime: 245041136 nsec, audio time 250000000 nsec, systime delta -4958864
+ playback: systime: 370106088 nsec, audio time 375000000 nsec, systime delta -4893912
+ playback: systime: 495040065 nsec, audio time 500000000 nsec, systime delta -4959935
+ playback: systime: 620038179 nsec, audio time 625000000 nsec, systime delta -4961821
+ playback: systime: 745087741 nsec, audio time 750000000 nsec, systime delta -4912259
+ playback: systime: 870037336 nsec, audio time 875000000 nsec, systime delta -4962664
Example 4: DMA timestamp, compensation for delay, delay of ~1ms
-$ ./audio_time -p -Dhw:1 -t1 -d
-playback: systime: 120190520 nsec, audio time 120000000 nsec, systime delta 190520
-playback: systime: 245036740 nsec, audio time 244000000 nsec, systime delta 1036740
-playback: systime: 370034081 nsec, audio time 369000000 nsec, systime delta 1034081
-playback: systime: 495159907 nsec, audio time 494000000 nsec, systime delta 1159907
-playback: systime: 620098824 nsec, audio time 619000000 nsec, systime delta 1098824
-playback: systime: 745031847 nsec, audio time 744000000 nsec, systime delta 1031847
+::
+
+ $ ./audio_time -p -Dhw:1 -t1 -d
+ playback: systime: 120190520 nsec, audio time 120000000 nsec, systime delta 190520
+ playback: systime: 245036740 nsec, audio time 244000000 nsec, systime delta 1036740
+ playback: systime: 370034081 nsec, audio time 369000000 nsec, systime delta 1034081
+ playback: systime: 495159907 nsec, audio time 494000000 nsec, systime delta 1159907
+ playback: systime: 620098824 nsec, audio time 619000000 nsec, systime delta 1098824
+ playback: systime: 745031847 nsec, audio time 744000000 nsec, systime delta 1031847
diff --git a/Documentation/sound/alsa/HD-Audio-Controls.txt b/Documentation/sound/hd-audio/controls.rst
index e9621e349e17..f2ebc4f79b44 100644
--- a/Documentation/sound/alsa/HD-Audio-Controls.txt
+++ b/Documentation/sound/hd-audio/controls.rst
@@ -1,16 +1,21 @@
+======================================
+HD-Audio Codec-Specific Mixer Controls
+======================================
+
+
This file explains the codec-specific mixer controls.
Realtek codecs
--------------
-* Channel Mode
+Channel Mode
This is an enum control to change the surround-channel setup,
appears only when the surround channels are available.
It gives the number of channels to be used, "2ch", "4ch", "6ch",
and "8ch". According to the configuration, this also controls the
jack-retasking of multi-I/O jacks.
-* Auto-Mute Mode
+Auto-Mute Mode
This is an enum control to change the auto-mute behavior of the
headphone and line-out jacks. If built-in speakers and headphone
and/or line-out jacks are available on a machine, this controls
@@ -30,24 +35,24 @@ Realtek codecs
IDT/Sigmatel codecs
-------------------
-* Analog Loopback
+Analog Loopback
This control enables/disables the analog-loopback circuit. This
appears only when "loopback" is set to true in a codec hint
(see HD-Audio.txt). Note that on some codecs the analog-loopback
and the normal PCM playback are exclusive, i.e. when this is on, you
won't hear any PCM stream.
-* Swap Center/LFE
+Swap Center/LFE
Swaps the center and LFE channel order. Normally, the left
corresponds to the center and the right to the LFE. When this is
ON, the left to the LFE and the right to the center.
-* Headphone as Line Out
+Headphone as Line Out
When this control is ON, treat the headphone jacks as line-out
jacks. That is, the headphone won't auto-mute the other line-outs,
and no HP-amp is set to the pins.
-* Mic Jack Mode, Line Jack Mode, etc
+Mic Jack Mode, Line Jack Mode, etc
These enum controls the direction and the bias of the input jack
pins. Depending on the jack type, it can set as "Mic In" and "Line
In", for determining the input bias, or it can be set to "Line Out"
@@ -57,19 +62,19 @@ IDT/Sigmatel codecs
VIA codecs
----------
-* Smart 5.1
+Smart 5.1
An enum control to re-task the multi-I/O jacks for surround outputs.
When it's ON, the corresponding input jacks (usually a line-in and a
mic-in) are switched as the surround and the CLFE output jacks.
-* Independent HP
+Independent HP
When this enum control is enabled, the headphone output is routed
from an individual stream (the third PCM such as hw:0,2) instead of
the primary stream. In the case the headphone DAC is shared with a
side or a CLFE-channel DAC, the DAC is switched to the headphone
automatically.
-* Loopback Mixing
+Loopback Mixing
An enum control to determine whether the analog-loopback route is
enabled or not. When it's enabled, the analog-loopback is mixed to
the front-channel. Also, the same route is used for the headphone
@@ -78,7 +83,7 @@ VIA codecs
headphones and speakers because there is only one DAC connected to a
mixer widget.
-* Dynamic Power-Control
+Dynamic Power-Control
This control determines whether the dynamic power-control per jack
detection is enabled or not. When enabled, the widgets power state
(D0/D3) are changed dynamically depending on the jack plugging
@@ -86,7 +91,7 @@ VIA codecs
doesn't provide a proper jack-detection, this won't work; in such a
case, turn this control OFF.
-* Jack Detect
+Jack Detect
This control is provided only for VT1708 codec which gives no proper
unsolicited event per jack plug. When this is on, the driver polls
the jack detection so that the headphone auto-mute can work, while
@@ -96,21 +101,21 @@ VIA codecs
Conexant codecs
---------------
-* Auto-Mute Mode
+Auto-Mute Mode
See Reatek codecs.
Analog codecs
--------------
-* Channel Mode
+Channel Mode
This is an enum control to change the surround-channel setup,
appears only when the surround channels are available.
It gives the number of channels to be used, "2ch", "4ch" and "6ch".
According to the configuration, this also controls the
jack-retasking of multi-I/O jacks.
-* Independent HP
+Independent HP
When this enum control is enabled, the headphone output is routed
from an individual stream (the third PCM such as hw:0,2) instead of
the primary stream.
diff --git a/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt b/Documentation/sound/hd-audio/dp-mst.rst
index 82744ac3513d..58b72437e6c3 100644
--- a/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt
+++ b/Documentation/sound/hd-audio/dp-mst.rst
@@ -1,3 +1,7 @@
+=======================
+HD-Audio DP-MST Support
+=======================
+
To support DP MST audio, HD Audio hdmi codec driver introduces virtual pin
and dynamic pcm assignment.
@@ -44,10 +48,12 @@ Build Jack
----------
- dyn_pcm_assign
-Will not use hda_jack but use snd_jack in spec->pcm_rec[pcm_idx].jack directly.
+
+ Will not use hda_jack but use snd_jack in spec->pcm_rec[pcm_idx].jack directly.
- !dyn_pcm_assign
-Use hda_jack and assign spec->pcm_rec[pcm_idx].jack = jack->jack statically.
+
+ Use hda_jack and assign spec->pcm_rec[pcm_idx].jack = jack->jack statically.
Unsolicited Event Enabling
@@ -58,16 +64,20 @@ Enable unsolicited event if !acomp.
Monitor Hotplug Event Handling
------------------------------
- acomp
-pin_eld_notify() -> check_presence_and_report() -> hdmi_present_sense() ->
-sync_eld_via_acomp().
-Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for
-both dyn_pcm_assign and !dyn_pcm_assign
+
+ pin_eld_notify() -> check_presence_and_report() -> hdmi_present_sense() ->
+ sync_eld_via_acomp().
+
+ Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for
+ both dyn_pcm_assign and !dyn_pcm_assign
- !acomp
-Hdmi_unsol_event() -> hdmi_intrinsic_event() -> check_presence_and_report() ->
-hdmi_present_sense() -> hdmi_prepsent_sense_via_verbs()
-Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for dyn_pcm_assign.
-Use hda_jack mechanism to handle jack events.
+
+ hdmi_unsol_event() -> hdmi_intrinsic_event() -> check_presence_and_report() ->
+ hdmi_present_sense() -> hdmi_prepsent_sense_via_verbs()
+
+ Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for dyn_pcm_assign.
+ Use hda_jack mechanism to handle jack events.
Others to be added later
diff --git a/Documentation/sound/hd-audio/index.rst b/Documentation/sound/hd-audio/index.rst
new file mode 100644
index 000000000000..f8a72ffffe66
--- /dev/null
+++ b/Documentation/sound/hd-audio/index.rst
@@ -0,0 +1,10 @@
+HD-Audio
+========
+
+.. toctree::
+ :maxdepth: 2
+
+ notes
+ models
+ controls
+ dp-mst
diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst
new file mode 100644
index 000000000000..5338673c88d9
--- /dev/null
+++ b/Documentation/sound/hd-audio/models.rst
@@ -0,0 +1,518 @@
+==============================
+HD-Audio Codec-Specific Models
+==============================
+
+ALC880
+======
+3stack
+ 3-jack in back and a headphone out
+3stack-digout
+ 3-jack in back, a HP out and a SPDIF out
+5stack
+ 5-jack in back, 2-jack in front
+5stack-digout
+ 5-jack in back, 2-jack in front, a SPDIF out
+6stack
+ 6-jack in back, 2-jack in front
+6stack-digout
+ 6-jack with a SPDIF out
+
+ALC260
+======
+gpio1
+ Enable GPIO1
+coef
+ Enable EAPD via COEF table
+fujitsu
+ Quirk for FSC S7020
+fujitsu-jwse
+ Quirk for FSC S7020 with jack modes and HP mic support
+
+ALC262
+======
+inv-dmic
+ Inverted internal mic workaround
+
+ALC267/268
+==========
+inv-dmic
+ Inverted internal mic workaround
+hp-eapd
+ Disable HP EAPD on NID 0x15
+
+ALC22x/23x/25x/269/27x/28x/29x (and vendor-specific ALC3xxx models)
+===================================================================
+laptop-amic
+ Laptops with analog-mic input
+laptop-dmic
+ Laptops with digital-mic input
+alc269-dmic
+ Enable ALC269(VA) digital mic workaround
+alc271-dmic
+ Enable ALC271X digital mic workaround
+inv-dmic
+ Inverted internal mic workaround
+headset-mic
+ Indicates a combined headset (headphone+mic) jack
+headset-mode
+ More comprehensive headset support for ALC269 & co
+headset-mode-no-hp-mic
+ Headset mode support without headphone mic
+lenovo-dock
+ Enables docking station I/O for some Lenovos
+hp-gpio-led
+ GPIO LED support on HP laptops
+dell-headset-multi
+ Headset jack, which can also be used as mic-in
+dell-headset-dock
+ Headset jack (without mic-in), and also dock I/O
+alc283-dac-wcaps
+ Fixups for Chromebook with ALC283
+alc283-sense-combo
+ Combo jack sensing on ALC283
+tpt440-dock
+ Pin configs for Lenovo Thinkpad Dock support
+
+ALC66x/67x/892
+==============
+mario
+ Chromebook mario model fixup
+asus-mode1
+ ASUS
+asus-mode2
+ ASUS
+asus-mode3
+ ASUS
+asus-mode4
+ ASUS
+asus-mode5
+ ASUS
+asus-mode6
+ ASUS
+asus-mode7
+ ASUS
+asus-mode8
+ ASUS
+inv-dmic
+ Inverted internal mic workaround
+dell-headset-multi
+ Headset jack, which can also be used as mic-in
+
+ALC680
+======
+N/A
+
+ALC88x/898/1150
+======================
+acer-aspire-4930g
+ Acer Aspire 4930G/5930G/6530G/6930G/7730G
+acer-aspire-8930g
+ Acer Aspire 8330G/6935G
+acer-aspire
+ Acer Aspire others
+inv-dmic
+ Inverted internal mic workaround
+no-primary-hp
+ VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC)
+
+ALC861/660
+==========
+N/A
+
+ALC861VD/660VD
+==============
+N/A
+
+CMI9880
+=======
+minimal
+ 3-jack in back
+min_fp
+ 3-jack in back, 2-jack in front
+full
+ 6-jack in back, 2-jack in front
+full_dig
+ 6-jack in back, 2-jack in front, SPDIF I/O
+allout
+ 5-jack in back, 2-jack in front, SPDIF out
+auto
+ auto-config reading BIOS (default)
+
+AD1882 / AD1882A
+================
+3stack
+ 3-stack mode
+3stack-automute
+ 3-stack with automute front HP (default)
+6stack
+ 6-stack mode
+
+AD1884A / AD1883 / AD1984A / AD1984B
+====================================
+desktop 3-stack desktop (default)
+laptop laptop with HP jack sensing
+mobile mobile devices with HP jack sensing
+thinkpad Lenovo Thinkpad X300
+touchsmart HP Touchsmart
+
+AD1884
+======
+N/A
+
+AD1981
+======
+basic 3-jack (default)
+hp HP nx6320
+thinkpad Lenovo Thinkpad T60/X60/Z60
+toshiba Toshiba U205
+
+AD1983
+======
+N/A
+
+AD1984
+======
+basic default configuration
+thinkpad Lenovo Thinkpad T61/X61
+dell_desktop Dell T3400
+
+AD1986A
+=======
+3stack
+ 3-stack, shared surrounds
+laptop
+ 2-channel only (FSC V2060, Samsung M50)
+laptop-imic
+ 2-channel with built-in mic
+eapd
+ Turn on EAPD constantly
+
+AD1988/AD1988B/AD1989A/AD1989B
+==============================
+6stack
+ 6-jack
+6stack-dig
+ ditto with SPDIF
+3stack
+ 3-jack
+3stack-dig
+ ditto with SPDIF
+laptop
+ 3-jack with hp-jack automute
+laptop-dig
+ ditto with SPDIF
+auto
+ auto-config reading BIOS (default)
+
+Conexant 5045
+=============
+laptop-hpsense
+ Laptop with HP sense (old model laptop)
+laptop-micsense
+ Laptop with Mic sense (old model fujitsu)
+laptop-hpmicsense
+ Laptop with HP and Mic senses
+benq
+ Benq R55E
+laptop-hp530
+ HP 530 laptop
+test
+ for testing/debugging purpose, almost all controls can be
+ adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y
+
+Conexant 5047
+=============
+laptop
+ Basic Laptop config
+laptop-hp
+ Laptop config for some HP models (subdevice 30A5)
+laptop-eapd
+ Laptop config with EAPD support
+test
+ for testing/debugging purpose, almost all controls can be
+ adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y
+
+Conexant 5051
+=============
+laptop
+ Basic Laptop config (default)
+hp
+ HP Spartan laptop
+hp-dv6736
+ HP dv6736
+hp-f700
+ HP Compaq Presario F700
+ideapad
+ Lenovo IdeaPad laptop
+toshiba
+ Toshiba Satellite M300
+
+Conexant 5066
+=============
+laptop
+ Basic Laptop config (default)
+hp-laptop
+ HP laptops, e g G60
+asus
+ Asus K52JU, Lenovo G560
+dell-laptop
+ Dell laptops
+dell-vostro
+ Dell Vostro
+olpc-xo-1_5
+ OLPC XO 1.5
+ideapad
+ Lenovo IdeaPad U150
+thinkpad
+ Lenovo Thinkpad
+
+STAC9200
+========
+ref
+ Reference board
+oqo
+ OQO Model 2
+dell-d21
+ Dell (unknown)
+dell-d22
+ Dell (unknown)
+dell-d23
+ Dell (unknown)
+dell-m21
+ Dell Inspiron 630m, Dell Inspiron 640m
+dell-m22
+ Dell Latitude D620, Dell Latitude D820
+dell-m23
+ Dell XPS M1710, Dell Precision M90
+dell-m24
+ Dell Latitude 120L
+dell-m25
+ Dell Inspiron E1505n
+dell-m26
+ Dell Inspiron 1501
+dell-m27
+ Dell Inspiron E1705/9400
+gateway-m4
+ Gateway laptops with EAPD control
+gateway-m4-2
+ Gateway laptops with EAPD control
+panasonic
+ Panasonic CF-74
+auto
+ BIOS setup (default)
+
+STAC9205/9254
+=============
+ref
+ Reference board
+dell-m42
+ Dell (unknown)
+dell-m43
+ Dell Precision
+dell-m44
+ Dell Inspiron
+eapd
+ Keep EAPD on (e.g. Gateway T1616)
+auto
+ BIOS setup (default)
+
+STAC9220/9221
+=============
+ref
+ Reference board
+3stack
+ D945 3stack
+5stack
+ D945 5stack + SPDIF
+intel-mac-v1
+ Intel Mac Type 1
+intel-mac-v2
+ Intel Mac Type 2
+intel-mac-v3
+ Intel Mac Type 3
+intel-mac-v4
+ Intel Mac Type 4
+intel-mac-v5
+ Intel Mac Type 5
+intel-mac-auto
+ Intel Mac (detect type according to subsystem id)
+macmini
+ Intel Mac Mini (equivalent with type 3)
+macbook
+ Intel Mac Book (eq. type 5)
+macbook-pro-v1
+ Intel Mac Book Pro 1st generation (eq. type 3)
+macbook-pro
+ Intel Mac Book Pro 2nd generation (eq. type 3)
+imac-intel
+ Intel iMac (eq. type 2)
+imac-intel-20
+ Intel iMac (newer version) (eq. type 3)
+ecs202
+ ECS/PC chips
+dell-d81
+ Dell (unknown)
+dell-d82
+ Dell (unknown)
+dell-m81
+ Dell (unknown)
+dell-m82
+ Dell XPS M1210
+auto
+ BIOS setup (default)
+
+STAC9202/9250/9251
+==================
+ref
+ Reference board, base config
+m1
+ Some Gateway MX series laptops (NX560XL)
+m1-2
+ Some Gateway MX series laptops (MX6453)
+m2
+ Some Gateway MX series laptops (M255)
+m2-2
+ Some Gateway MX series laptops
+m3
+ Some Gateway MX series laptops
+m5
+ Some Gateway MX series laptops (MP6954)
+m6
+ Some Gateway NX series laptops
+auto
+ BIOS setup (default)
+
+STAC9227/9228/9229/927x
+=======================
+ref
+ Reference board
+ref-no-jd
+ Reference board without HP/Mic jack detection
+3stack
+ D965 3stack
+5stack
+ D965 5stack + SPDIF
+5stack-no-fp
+ D965 5stack without front panel
+dell-3stack
+ Dell Dimension E520
+dell-bios
+ Fixes with Dell BIOS setup
+dell-bios-amic
+ Fixes with Dell BIOS setup including analog mic
+volknob
+ Fixes with volume-knob widget 0x24
+auto
+ BIOS setup (default)
+
+STAC92HD71B*
+============
+ref
+ Reference board
+dell-m4-1
+ Dell desktops
+dell-m4-2
+ Dell desktops
+dell-m4-3
+ Dell desktops
+hp-m4
+ HP mini 1000
+hp-dv5
+ HP dv series
+hp-hdx
+ HP HDX series
+hp-dv4-1222nr
+ HP dv4-1222nr (with LED support)
+auto
+ BIOS setup (default)
+
+STAC92HD73*
+===========
+ref
+ Reference board
+no-jd
+ BIOS setup but without jack-detection
+intel
+ Intel DG45* mobos
+dell-m6-amic
+ Dell desktops/laptops with analog mics
+dell-m6-dmic
+ Dell desktops/laptops with digital mics
+dell-m6
+ Dell desktops/laptops with both type of mics
+dell-eq
+ Dell desktops/laptops
+alienware
+ Alienware M17x
+auto
+ BIOS setup (default)
+
+STAC92HD83*
+===========
+ref
+ Reference board
+mic-ref
+ Reference board with power management for ports
+dell-s14
+ Dell laptop
+dell-vostro-3500
+ Dell Vostro 3500 laptop
+hp-dv7-4000
+ HP dv-7 4000
+hp_cNB11_intquad
+ HP CNB models with 4 speakers
+hp-zephyr
+ HP Zephyr
+hp-led
+ HP with broken BIOS for mute LED
+hp-inv-led
+ HP with broken BIOS for inverted mute LED
+hp-mic-led
+ HP with mic-mute LED
+headset-jack
+ Dell Latitude with a 4-pin headset jack
+hp-envy-bass
+ Pin fixup for HP Envy bass speaker (NID 0x0f)
+hp-envy-ts-bass
+ Pin fixup for HP Envy TS bass speaker (NID 0x10)
+hp-bnb13-eq
+ Hardware equalizer setup for HP laptops
+auto
+ BIOS setup (default)
+
+STAC92HD95
+==========
+hp-led
+ LED support for HP laptops
+hp-bass
+ Bass HPF setup for HP Spectre 13
+
+STAC9872
+========
+vaio
+ VAIO laptop without SPDIF
+auto
+ BIOS setup (default)
+
+Cirrus Logic CS4206/4207
+========================
+mbp55
+ MacBook Pro 5,5
+imac27
+ IMac 27 Inch
+auto
+ BIOS setup (default)
+
+Cirrus Logic CS4208
+===================
+mba6
+ MacBook Air 6,1 and 6,2
+gpio0
+ Enable GPIO 0 amp
+auto
+ BIOS setup (default)
+
+VIA VT17xx/VT18xx/VT20xx
+========================
+auto
+ BIOS setup (default)
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/hd-audio/notes.rst
index d4510ebf2e8c..168d0cfab1ce 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/hd-audio/notes.rst
@@ -1,10 +1,12 @@
-MORE NOTES ON HD-AUDIO DRIVER
=============================
- Takashi Iwai <tiwai@suse.de>
+More Notes on HD-Audio Driver
+=============================
+Takashi Iwai <tiwai@suse.de>
-GENERAL
--------
+
+General
+=======
HD-audio is the new standard on-board audio component on modern PCs
after AC97. Although Linux has been supporting HD-audio since long
@@ -40,28 +42,28 @@ If you are interested in the deep debugging of HD-audio, read the
HD-audio specification at first. The specification is found on
Intel's web page, for example:
-- http://www.intel.com/standards/hdaudio/
+* http://www.intel.com/standards/hdaudio/
-HD-AUDIO CONTROLLER
--------------------
+HD-Audio Controller
+===================
DMA-Position Problem
-~~~~~~~~~~~~~~~~~~~~
+--------------------
The most common problem of the controller is the inaccurate DMA
pointer reporting. The DMA pointer for playback and capture can be
read in two ways, either via a LPIB register or via a position-buffer
map. As default the driver tries to read from the io-mapped
position-buffer, and falls back to LPIB if the position-buffer appears
dead. However, this detection isn't perfect on some devices. In such
-a case, you can change the default method via `position_fix` option.
+a case, you can change the default method via ``position_fix`` option.
-`position_fix=1` means to use LPIB method explicitly.
-`position_fix=2` means to use the position-buffer.
-`position_fix=3` means to use a combination of both methods, needed
+``position_fix=1`` means to use LPIB method explicitly.
+``position_fix=2`` means to use the position-buffer.
+``position_fix=3`` means to use a combination of both methods, needed
for some VIA controllers. The capture stream position is corrected
by comparing both LPIB and position-buffer values.
-`position_fix=4` is another combination available for all controllers,
+``position_fix=4`` is another combination available for all controllers,
and uses LPIB for the playback and the position-buffer for the capture
streams.
0 is the default value for all other
@@ -74,9 +76,9 @@ the wake-up timing. It wakes up a few samples before actually
processing the data on the buffer. This caused a lot of problems, for
example, with ALSA dmix or JACK. Since 2.6.27 kernel, the driver puts
an artificial delay to the wake up timing. This delay is controlled
-via `bdl_pos_adj` option.
+via ``bdl_pos_adj`` option.
-When `bdl_pos_adj` is a negative value (as default), it's assigned to
+When ``bdl_pos_adj`` is a negative value (as default), it's assigned to
an appropriate value depending on the controller chip. For Intel
chips, it'd be 1 while it'd be 32 for others. Usually this works.
Only in case it doesn't work and you get warning messages, you should
@@ -84,19 +86,19 @@ change this parameter to other values.
Codec-Probing Problem
-~~~~~~~~~~~~~~~~~~~~~
+---------------------
A less often but a more severe problem is the codec probing. When
BIOS reports the available codec slots wrongly, the driver gets
confused and tries to access the non-existing codec slot. This often
results in the total screw-up, and destructs the further communication
with the codec chips. The symptom appears usually as error messages
like:
-------------------------------------------------------------------------
- hda_intel: azx_get_response timeout, switching to polling mode:
- last cmd=0x12345678
- hda_intel: azx_get_response timeout, switching to single_cmd mode:
- last cmd=0x12345678
-------------------------------------------------------------------------
+::
+
+ hda_intel: azx_get_response timeout, switching to polling mode:
+ last cmd=0x12345678
+ hda_intel: azx_get_response timeout, switching to single_cmd mode:
+ last cmd=0x12345678
The first line is a warning, and this is usually relatively harmless.
It means that the codec response isn't notified via an IRQ. The
@@ -108,24 +110,24 @@ it means that something is really wrong. Most likely you are
accessing a non-existing codec slot.
Thus, if the second error message appears, try to narrow the probed
-codec slots via `probe_mask` option. It's a bitmask, and each bit
+codec slots via ``probe_mask`` option. It's a bitmask, and each bit
corresponds to the codec slot. For example, to probe only the first
-slot, pass `probe_mask=1`. For the first and the third slots, pass
-`probe_mask=5` (where 5 = 1 | 4), and so on.
+slot, pass ``probe_mask=1``. For the first and the third slots, pass
+``probe_mask=5`` (where 5 = 1 | 4), and so on.
Since 2.6.29 kernel, the driver has a more robust probing method, so
this error might happen rarely, though.
On a machine with a broken BIOS, sometimes you need to force the
driver to probe the codec slots the hardware doesn't report for use.
-In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
+In such a case, turn the bit 8 (0x100) of ``probe_mask`` option on.
Then the rest 8 bits are passed as the codec slots to probe
-unconditionally. For example, `probe_mask=0x103` will force to probe
+unconditionally. For example, ``probe_mask=0x103`` will force to probe
the codec slots 0 and 1 no matter what the hardware reports.
Interrupt Handling
-~~~~~~~~~~~~~~~~~~
+------------------
HD-audio driver uses MSI as default (if available) since 2.6.33
kernel as MSI works better on some machines, and in general, it's
better for performance. However, Nvidia controllers showed bad
@@ -134,17 +136,17 @@ thus we disabled MSI for them.
There seem also still other devices that don't work with MSI. If you
see a regression wrt the sound quality (stuttering, etc) or a lock-up
-in the recent kernel, try to pass `enable_msi=0` option to disable
+in the recent kernel, try to pass ``enable_msi=0`` option to disable
MSI. If it works, you can add the known bad device to the blacklist
defined in hda_intel.c. In such a case, please report and give the
patch back to the upstream developer.
-HD-AUDIO CODEC
---------------
+HD-Audio Codec
+==============
Model Option
-~~~~~~~~~~~~
+------------
The most common problem regarding the HD-audio driver is the
unsupported codec features or the mismatched device configuration.
Most of codec-specific code has several preset models, either to
@@ -153,13 +155,15 @@ override the BIOS setup or to provide more comprehensive features.
The driver checks PCI SSID and looks through the static configuration
table until any matching entry is found. If you have a new machine,
you may see a message like below:
-------------------------------------------------------------------------
+::
+
hda_codec: ALC880: BIOS auto-probing.
-------------------------------------------------------------------------
+
Meanwhile, in the earlier versions, you would see a message like:
-------------------------------------------------------------------------
+::
+
hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
-------------------------------------------------------------------------
+
Even if you see such a message, DON'T PANIC. Take a deep breath and
keep your towel. First of all, it's an informational message, no
warning, no error. This means that the PCI SSID of your device isn't
@@ -182,32 +186,33 @@ model is found in the white-list, the driver assumes the static
configuration of that preset with the correct pin setup, etc.
Thus, if you have a newer machine with a slightly different PCI SSID
(or codec SSID) from the existing one, you may have a good chance to
-re-use the same model. You can pass the `model` option to specify the
+re-use the same model. You can pass the ``model`` option to specify the
preset model instead of PCI (and codec-) SSID look-up.
-What `model` option values are available depends on the codec chip.
+What ``model`` option values are available depends on the codec chip.
Check your codec chip from the codec proc file (see "Codec Proc-File"
section below). It will show the vendor/product name of your codec
-chip. Then, see Documentation/sound/alsa/HD-Audio-Models.txt file,
+chip. Then, see Documentation/sound/HD-Audio-Models.rst file,
the section of HD-audio driver. You can find a list of codecs
-and `model` options belonging to each codec. For example, for Realtek
-ALC262 codec chip, pass `model=ultra` for devices that are compatible
+and ``model`` options belonging to each codec. For example, for Realtek
+ALC262 codec chip, pass ``model=ultra`` for devices that are compatible
with Samsung Q1 Ultra.
Thus, the first thing you can do for any brand-new, unsupported and
non-working HD-audio hardware is to check HD-audio codec and several
-different `model` option values. If you have any luck, some of them
+different ``model`` option values. If you have any luck, some of them
might suit with your device well.
There are a few special model option values:
-- when 'nofixup' is passed, the device-specific fixups in the codec
+
+* when 'nofixup' is passed, the device-specific fixups in the codec
parser are skipped.
-- when `generic` is passed, the codec-specific parser is skipped and
+* when ``generic`` is passed, the codec-specific parser is skipped and
only the generic parser is used.
Speaker and Headphone Output
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------
One of the most frequent (and obvious) bugs with HD-audio is the
silent output from either or both of a built-in speaker and a
headphone jack. In general, you should try a headphone output at
@@ -236,23 +241,23 @@ report. See the bug report section for details.
If you are masochistic enough to debug the driver problem, note the
following:
-- The speaker (and the headphone, too) output often requires the
+* The speaker (and the headphone, too) output often requires the
external amplifier. This can be set usually via EAPD verb or a
certain GPIO. If the codec pin supports EAPD, you have a better
chance via SET_EAPD_BTL verb (0x70c). On others, GPIO pin (mostly
it's either GPIO0 or GPIO1) may turn on/off EAPD.
-- Some Realtek codecs require special vendor-specific coefficients to
+* Some Realtek codecs require special vendor-specific coefficients to
turn on the amplifier. See patch_realtek.c.
-- IDT codecs may have extra power-enable/disable controls on each
+* IDT codecs may have extra power-enable/disable controls on each
analog pin. See patch_sigmatel.c.
-- Very rare but some devices don't accept the pin-detection verb until
+* Very rare but some devices don't accept the pin-detection verb until
triggered. Issuing GET_PIN_SENSE verb (0xf09) may result in the
codec-communication stall. Some examples are found in
patch_realtek.c.
Capture Problems
-~~~~~~~~~~~~~~~~
+----------------
The capture problems are often because of missing setups of mixers.
Thus, before submitting a bug report, make sure that you set up the
mixer correctly. For example, both "Capture Volume" and "Capture
@@ -284,7 +289,7 @@ submit the improvement patch to the author.
Direct Debugging
-~~~~~~~~~~~~~~~~
+----------------
If no model option gives you a better result, and you are a tough guy
to fight against evil, try debugging via hitting the raw HD-audio
codec verbs to the device. Some tools are available: hda-emu and
@@ -293,45 +298,45 @@ below. You'd need to enable hwdep for using these tools. See "Kernel
Configuration" section.
-OTHER ISSUES
-------------
+Other Issues
+============
Kernel Configuration
-~~~~~~~~~~~~~~~~~~~~
+--------------------
In general, I recommend you to enable the sound debug option,
-`CONFIG_SND_DEBUG=y`, no matter whether you are debugging or not.
+``CONFIG_SND_DEBUG=y``, no matter whether you are debugging or not.
This enables snd_printd() macro and others, and you'll get additional
kernel messages at probing.
-In addition, you can enable `CONFIG_SND_DEBUG_VERBOSE=y`. But this
+In addition, you can enable ``CONFIG_SND_DEBUG_VERBOSE=y``. But this
will give you far more messages. Thus turn this on only when you are
sure to want it.
-Don't forget to turn on the appropriate `CONFIG_SND_HDA_CODEC_*`
+Don't forget to turn on the appropriate ``CONFIG_SND_HDA_CODEC_*``
options. Note that each of them corresponds to the codec chip, not
the controller chip. Thus, even if lspci shows the Nvidia controller,
you may need to choose the option for other vendors. If you are
unsure, just select all yes.
-`CONFIG_SND_HDA_HWDEP` is a useful option for debugging the driver.
+``CONFIG_SND_HDA_HWDEP`` is a useful option for debugging the driver.
When this is enabled, the driver creates hardware-dependent devices
(one per each codec), and you have a raw access to the device via
-these device files. For example, `hwC0D2` will be created for the
+these device files. For example, ``hwC0D2`` will be created for the
codec slot #2 of the first card (#0). For debug-tools such as
hda-verb and hda-analyzer, the hwdep device has to be enabled.
Thus, it'd be better to turn this on always.
-`CONFIG_SND_HDA_RECONFIG` is a new option, and this depends on the
+``CONFIG_SND_HDA_RECONFIG`` is a new option, and this depends on the
hwdep option above. When enabled, you'll have some sysfs files under
the corresponding hwdep directory. See "HD-audio reconfiguration"
section below.
-`CONFIG_SND_HDA_POWER_SAVE` option enables the power-saving feature.
+``CONFIG_SND_HDA_POWER_SAVE`` option enables the power-saving feature.
See "Power-saving" section below.
Codec Proc-File
-~~~~~~~~~~~~~~~
+---------------
The codec proc-file is a treasure-chest for debugging HD-audio.
It shows most of useful information of each codec widget.
@@ -351,161 +356,178 @@ will appear as "Realtek ID 0262", instead of "Realtek ALC262".
HD-Audio Reconfiguration
-~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------
This is an experimental feature to allow you re-configure the HD-audio
codec dynamically without reloading the driver. The following sysfs
files are available under each codec-hwdep device directory (e.g.
/sys/class/sound/hwC0D0):
-vendor_id::
- Shows the 32bit codec vendor-id hex number. You can change the
- vendor-id value by writing to this file.
-subsystem_id::
- Shows the 32bit codec subsystem-id hex number. You can change the
- subsystem-id value by writing to this file.
-revision_id::
- Shows the 32bit codec revision-id hex number. You can change the
- revision-id value by writing to this file.
-afg::
- Shows the AFG ID. This is read-only.
-mfg::
- Shows the MFG ID. This is read-only.
-name::
- Shows the codec name string. Can be changed by writing to this
- file.
-modelname::
- Shows the currently set `model` option. Can be changed by writing
- to this file.
-init_verbs::
- The extra verbs to execute at initialization. You can add a verb by
- writing to this file. Pass three numbers: nid, verb and parameter
- (separated with a space).
-hints::
- Shows / stores hint strings for codec parsers for any use.
- Its format is `key = value`. For example, passing `jack_detect = no`
- will disable the jack detection of the machine completely.
-init_pin_configs::
- Shows the initial pin default config values set by BIOS.
-driver_pin_configs::
- Shows the pin default values set by the codec parser explicitly.
- This doesn't show all pin values but only the changed values by
- the parser. That is, if the parser doesn't change the pin default
- config values by itself, this will contain nothing.
-user_pin_configs::
- Shows the pin default config values to override the BIOS setup.
- Writing this (with two numbers, NID and value) appends the new
- value. The given will be used instead of the initial BIOS value at
- the next reconfiguration time. Note that this config will override
- even the driver pin configs, too.
-reconfig::
- Triggers the codec re-configuration. When any value is written to
- this file, the driver re-initialize and parses the codec tree
- again. All the changes done by the sysfs entries above are taken
- into account.
-clear::
- Resets the codec, removes the mixer elements and PCM stuff of the
- specified codec, and clear all init verbs and hints.
+vendor_id
+ Shows the 32bit codec vendor-id hex number. You can change the
+ vendor-id value by writing to this file.
+subsystem_id
+ Shows the 32bit codec subsystem-id hex number. You can change the
+ subsystem-id value by writing to this file.
+revision_id
+ Shows the 32bit codec revision-id hex number. You can change the
+ revision-id value by writing to this file.
+afg
+ Shows the AFG ID. This is read-only.
+mfg
+ Shows the MFG ID. This is read-only.
+name
+ Shows the codec name string. Can be changed by writing to this
+ file.
+modelname
+ Shows the currently set ``model`` option. Can be changed by writing
+ to this file.
+init_verbs
+ The extra verbs to execute at initialization. You can add a verb by
+ writing to this file. Pass three numbers: nid, verb and parameter
+ (separated with a space).
+hints
+ Shows / stores hint strings for codec parsers for any use.
+ Its format is ``key = value``. For example, passing ``jack_detect = no``
+ will disable the jack detection of the machine completely.
+init_pin_configs
+ Shows the initial pin default config values set by BIOS.
+driver_pin_configs
+ Shows the pin default values set by the codec parser explicitly.
+ This doesn't show all pin values but only the changed values by
+ the parser. That is, if the parser doesn't change the pin default
+ config values by itself, this will contain nothing.
+user_pin_configs
+ Shows the pin default config values to override the BIOS setup.
+ Writing this (with two numbers, NID and value) appends the new
+ value. The given will be used instead of the initial BIOS value at
+ the next reconfiguration time. Note that this config will override
+ even the driver pin configs, too.
+reconfig
+ Triggers the codec re-configuration. When any value is written to
+ this file, the driver re-initialize and parses the codec tree
+ again. All the changes done by the sysfs entries above are taken
+ into account.
+clear
+ Resets the codec, removes the mixer elements and PCM stuff of the
+ specified codec, and clear all init verbs and hints.
For example, when you want to change the pin default configuration
value of the pin widget 0x14 to 0x9993013f, and let the driver
re-configure based on that state, run like below:
-------------------------------------------------------------------------
- # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
- # echo 1 > /sys/class/sound/hwC0D0/reconfig
-------------------------------------------------------------------------
+::
+
+ # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
+ # echo 1 > /sys/class/sound/hwC0D0/reconfig
Hint Strings
-~~~~~~~~~~~~
+------------
The codec parser have several switches and adjustment knobs for
matching better with the actual codec or device behavior. Many of
them can be adjusted dynamically via "hints" strings as mentioned in
-the section above. For example, by passing `jack_detect = no` string
+the section above. For example, by passing ``jack_detect = no`` string
via sysfs or a patch file, you can disable the jack detection, thus
the codec parser will skip the features like auto-mute or mic
-auto-switch. As a boolean value, either `yes`, `no`, `true`, `false`,
-`1` or `0` can be passed.
+auto-switch. As a boolean value, either ``yes``, ``no``, ``true``, ``false``,
+``1`` or ``0`` can be passed.
The generic parser supports the following hints:
-- jack_detect (bool): specify whether the jack detection is available
- at all on this machine; default true
-- inv_jack_detect (bool): indicates that the jack detection logic is
- inverted
-- trigger_sense (bool): indicates that the jack detection needs the
- explicit call of AC_VERB_SET_PIN_SENSE verb
-- inv_eapd (bool): indicates that the EAPD is implemented in the
- inverted logic
-- pcm_format_first (bool): sets the PCM format before the stream tag
- and channel ID
-- sticky_stream (bool): keep the PCM format, stream tag and ID as long
- as possible; default true
-- spdif_status_reset (bool): reset the SPDIF status bits at each time
- the SPDIF stream is set up
-- pin_amp_workaround (bool): the output pin may have multiple amp
- values
-- single_adc_amp (bool): ADCs can have only single input amps
-- auto_mute (bool): enable/disable the headphone auto-mute feature;
- default true
-- auto_mic (bool): enable/disable the mic auto-switch feature; default
- true
-- line_in_auto_switch (bool): enable/disable the line-in auto-switch
- feature; default false
-- need_dac_fix (bool): limits the DACs depending on the channel count
-- primary_hp (bool): probe headphone jacks as the primary outputs;
- default true
-- multi_io (bool): try probing multi-I/O config (e.g. shared
- line-in/surround, mic/clfe jacks)
-- multi_cap_vol (bool): provide multiple capture volumes
-- inv_dmic_split (bool): provide split internal mic volume/switch for
- phase-inverted digital mics
-- indep_hp (bool): provide the independent headphone PCM stream and
- the corresponding mixer control, if available
-- add_stereo_mix_input (bool): add the stereo mix (analog-loopback
- mix) to the input mux if available
-- add_jack_modes (bool): add "xxx Jack Mode" enum controls to each
- I/O jack for allowing to change the headphone amp and mic bias VREF
- capabilities
-- power_save_node (bool): advanced power management for each widget,
- controlling the power sate (D0/D3) of each widget node depending on
- the actual pin and stream states
-- power_down_unused (bool): power down the unused widgets, a subset of
- power_save_node, and will be dropped in future
-- add_hp_mic (bool): add the headphone to capture source if possible
-- hp_mic_detect (bool): enable/disable the hp/mic shared input for a
- single built-in mic case; default true
-- mixer_nid (int): specifies the widget NID of the analog-loopback
- mixer
+jack_detect (bool)
+ specify whether the jack detection is available at all on this
+ machine; default true
+inv_jack_detect (bool)
+ indicates that the jack detection logic is inverted
+trigger_sense (bool)
+ indicates that the jack detection needs the explicit call of
+ AC_VERB_SET_PIN_SENSE verb
+inv_eapd (bool)
+ indicates that the EAPD is implemented in the inverted logic
+pcm_format_first (bool)
+ sets the PCM format before the stream tag and channel ID
+sticky_stream (bool)
+ keep the PCM format, stream tag and ID as long as possible;
+ default true
+spdif_status_reset (bool)
+ reset the SPDIF status bits at each time the SPDIF stream is set
+ up
+pin_amp_workaround (bool)
+ the output pin may have multiple amp values
+single_adc_amp (bool)
+ ADCs can have only single input amps
+auto_mute (bool)
+ enable/disable the headphone auto-mute feature; default true
+auto_mic (bool)
+ enable/disable the mic auto-switch feature; default true
+line_in_auto_switch (bool)
+ enable/disable the line-in auto-switch feature; default false
+need_dac_fix (bool)
+ limits the DACs depending on the channel count
+primary_hp (bool)
+ probe headphone jacks as the primary outputs; default true
+multi_io (bool)
+ try probing multi-I/O config (e.g. shared line-in/surround,
+ mic/clfe jacks)
+multi_cap_vol (bool)
+ provide multiple capture volumes
+inv_dmic_split (bool)
+ provide split internal mic volume/switch for phase-inverted
+ digital mics
+indep_hp (bool)
+ provide the independent headphone PCM stream and the corresponding
+ mixer control, if available
+add_stereo_mix_input (bool)
+ add the stereo mix (analog-loopback mix) to the input mux if
+ available
+add_jack_modes (bool)
+ add "xxx Jack Mode" enum controls to each I/O jack for allowing to
+ change the headphone amp and mic bias VREF capabilities
+power_save_node (bool)
+ advanced power management for each widget, controlling the power
+ sate (D0/D3) of each widget node depending on the actual pin and
+ stream states
+power_down_unused (bool)
+ power down the unused widgets, a subset of power_save_node, and
+ will be dropped in future
+add_hp_mic (bool)
+ add the headphone to capture source if possible
+hp_mic_detect (bool)
+ enable/disable the hp/mic shared input for a single built-in mic
+ case; default true
+mixer_nid (int)
+ specifies the widget NID of the analog-loopback mixer
Early Patching
-~~~~~~~~~~~~~~
-When CONFIG_SND_HDA_PATCH_LOADER=y is set, you can pass a "patch" as a
-firmware file for modifying the HD-audio setup before initializing the
-codec. This can work basically like the reconfiguration via sysfs in
-the above, but it does it before the first codec configuration.
+--------------
+When ``CONFIG_SND_HDA_PATCH_LOADER=y`` is set, you can pass a "patch"
+as a firmware file for modifying the HD-audio setup before
+initializing the codec. This can work basically like the
+reconfiguration via sysfs in the above, but it does it before the
+first codec configuration.
A patch file is a plain text file which looks like below:
-------------------------------------------------------------------------
- [codec]
- 0x12345678 0xabcd1234 2
+::
+
+ [codec]
+ 0x12345678 0xabcd1234 2
- [model]
- auto
+ [model]
+ auto
- [pincfg]
- 0x12 0x411111f0
+ [pincfg]
+ 0x12 0x411111f0
- [verb]
- 0x20 0x500 0x03
- 0x20 0x400 0xff
+ [verb]
+ 0x20 0x500 0x03
+ 0x20 0x400 0xff
- [hint]
- jack_detect = no
-------------------------------------------------------------------------
+ [hint]
+ jack_detect = no
-The file needs to have a line `[codec]`. The next line should contain
+
+The file needs to have a line ``[codec]``. The next line should contain
three numbers indicating the codec vendor-id (0x12345678 in the
example), the codec subsystem-id (0xabcd1234) and the address (2) of
the codec. The rest patch entries are applied to this specified codec
@@ -514,66 +536,68 @@ the first or the second value will make the check of the corresponding
field be skipped. It'll be useful for really broken devices that don't
initialize SSID properly.
-The `[model]` line allows to change the model name of the each codec.
+The ``[model]`` line allows to change the model name of the each codec.
In the example above, it will be changed to model=auto.
Note that this overrides the module option.
-After the `[pincfg]` line, the contents are parsed as the initial
-default pin-configurations just like `user_pin_configs` sysfs above.
+After the ``[pincfg]`` line, the contents are parsed as the initial
+default pin-configurations just like ``user_pin_configs`` sysfs above.
The values can be shown in user_pin_configs sysfs file, too.
-Similarly, the lines after `[verb]` are parsed as `init_verbs`
-sysfs entries, and the lines after `[hint]` are parsed as `hints`
+Similarly, the lines after ``[verb]`` are parsed as ``init_verbs``
+sysfs entries, and the lines after ``[hint]`` are parsed as ``hints``
sysfs entries, respectively.
Another example to override the codec vendor id from 0x12345678 to
0xdeadbeef is like below:
-------------------------------------------------------------------------
- [codec]
- 0x12345678 0xabcd1234 2
+::
+
+ [codec]
+ 0x12345678 0xabcd1234 2
+
+ [vendor_id]
+ 0xdeadbeef
- [vendor_id]
- 0xdeadbeef
-------------------------------------------------------------------------
In the similar way, you can override the codec subsystem_id via
-`[subsystem_id]`, the revision id via `[revision_id]` line.
-Also, the codec chip name can be rewritten via `[chip_name]` line.
-------------------------------------------------------------------------
- [codec]
- 0x12345678 0xabcd1234 2
+``[subsystem_id]``, the revision id via ``[revision_id]`` line.
+Also, the codec chip name can be rewritten via ``[chip_name]`` line.
+::
+
+ [codec]
+ 0x12345678 0xabcd1234 2
+
+ [subsystem_id]
+ 0xffff1111
- [subsystem_id]
- 0xffff1111
+ [revision_id]
+ 0x10
- [revision_id]
- 0x10
+ [chip_name]
+ My-own NEWS-0002
- [chip_name]
- My-own NEWS-0002
-------------------------------------------------------------------------
The hd-audio driver reads the file via request_firmware(). Thus,
a patch file has to be located on the appropriate firmware path,
typically, /lib/firmware. For example, when you pass the option
-`patch=hda-init.fw`, the file /lib/firmware/hda-init.fw must be
+``patch=hda-init.fw``, the file /lib/firmware/hda-init.fw must be
present.
The patch module option is specific to each card instance, and you
need to give one file name for each instance, separated by commas.
For example, if you have two cards, one for an on-board analog and one
for an HDMI video board, you may pass patch option like below:
-------------------------------------------------------------------------
+::
+
options snd-hda-intel patch=on-board-patch,hdmi-patch
-------------------------------------------------------------------------
Power-Saving
-~~~~~~~~~~~~
+------------
The power-saving is a kind of auto-suspend of the device. When the
device is inactive for a certain time, the device is automatically
turned off to save the power. The time to go down is specified via
-`power_save` module option, and this option can be changed dynamically
+``power_save`` module option, and this option can be changed dynamically
via sysfs.
The power-saving won't work when the analog loopback is enabled on
@@ -592,63 +616,65 @@ The recent kernel supports the runtime PM for the HD-audio controller
chip, too. It means that the HD-audio controller is also powered up /
down dynamically. The feature is enabled only for certain controller
chips like Intel LynxPoint. You can enable/disable this feature
-forcibly by setting `power_save_controller` option, which is also
+forcibly by setting ``power_save_controller`` option, which is also
available at /sys/module/snd_hda_intel/parameters directory.
Tracepoints
-~~~~~~~~~~~
+-----------
The hd-audio driver gives a few basic tracepoints.
-`hda:hda_send_cmd` traces each CORB write while `hda:hda_get_response`
+``hda:hda_send_cmd`` traces each CORB write while ``hda:hda_get_response``
traces the response from RIRB (only when read from the codec driver).
-`hda:hda_bus_reset` traces the bus-reset due to fatal error, etc,
-`hda:hda_unsol_event` traces the unsolicited events, and
-`hda:hda_power_down` and `hda:hda_power_up` trace the power down/up
+``hda:hda_bus_reset`` traces the bus-reset due to fatal error, etc,
+``hda:hda_unsol_event`` traces the unsolicited events, and
+``hda:hda_power_down`` and ``hda:hda_power_up`` trace the power down/up
via power-saving behavior.
Enabling all tracepoints can be done like
-------------------------------------------------------------------------
- # echo 1 > /sys/kernel/debug/tracing/events/hda/enable
-------------------------------------------------------------------------
+::
+
+ # echo 1 > /sys/kernel/debug/tracing/events/hda/enable
+
then after some commands, you can traces from
/sys/kernel/debug/tracing/trace file. For example, when you want to
trace what codec command is sent, enable the tracepoint like:
-------------------------------------------------------------------------
- # cat /sys/kernel/debug/tracing/trace
- # tracer: nop
- #
- # TASK-PID CPU# TIMESTAMP FUNCTION
- # | | | | |
- <...>-7807 [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
- <...>-7807 [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
- <...>-7807 [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
- <...>-7807 [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
- <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
- <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
- <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
- <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
-------------------------------------------------------------------------
-Here `[0:0]` indicates the card number and the codec address, and
-`val` shows the value sent to the codec, respectively. The value is
+::
+
+ # cat /sys/kernel/debug/tracing/trace
+ # tracer: nop
+ #
+ # TASK-PID CPU# TIMESTAMP FUNCTION
+ # | | | | |
+ <...>-7807 [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
+ <...>-7807 [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
+ <...>-7807 [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
+ <...>-7807 [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
+ <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
+ <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
+ <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
+ <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
+
+Here ``[0:0]`` indicates the card number and the codec address, and
+``val`` shows the value sent to the codec, respectively. The value is
a packed value, and you can decode it via hda-decode-verb program
included in hda-emu package below. For example, the value e3a019 is
to set the left output-amp value to 25.
-------------------------------------------------------------------------
- % hda-decode-verb 0xe3a019
- raw value = 0x00e3a019
- cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
- raw value: verb = 0x3a0, parm = 0x19
- verbname = set_amp_gain_mute
- amp raw val = 0xa019
- output, left, idx=0, mute=0, val=25
-------------------------------------------------------------------------
+::
+
+ % hda-decode-verb 0xe3a019
+ raw value = 0x00e3a019
+ cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
+ raw value: verb = 0x3a0, parm = 0x19
+ verbname = set_amp_gain_mute
+ amp raw val = 0xa019
+ output, left, idx=0, mute=0, val=25
Development Tree
-~~~~~~~~~~~~~~~~
+----------------
The latest development codes for HD-audio are found on sound git tree:
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
+* git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
The master branch or for-next branches can be used as the main
development branches in general while the development for the current
@@ -657,14 +683,14 @@ respectively.
Sending a Bug Report
-~~~~~~~~~~~~~~~~~~~~
+--------------------
If any model or module options don't work for your device, it's time
to send a bug report to the developers. Give the following in your
bug report:
-- Hardware vendor, product and model names
-- Kernel version (and ALSA-driver version if you built externally)
-- `alsa-info.sh` output; run with `--no-upload` option. See the
+* Hardware vendor, product and model names
+* Kernel version (and ALSA-driver version if you built externally)
+* ``alsa-info.sh`` output; run with ``--no-upload`` option. See the
section below about alsa-info
If it's a regression, at best, send alsa-info outputs of both working
@@ -673,60 +699,60 @@ compare the codec registers directly.
Send a bug report either the followings:
-kernel-bugzilla::
- https://bugzilla.kernel.org/
-alsa-devel ML::
- alsa-devel@alsa-project.org
+kernel-bugzilla
+ https://bugzilla.kernel.org/
+alsa-devel ML
+ alsa-devel@alsa-project.org
-DEBUG TOOLS
------------
+Debug Tools
+===========
This section describes some tools available for debugging HD-audio
problems.
alsa-info
-~~~~~~~~~
-The script `alsa-info.sh` is a very useful tool to gather the audio
+---------
+The script ``alsa-info.sh`` is a very useful tool to gather the audio
device information. It's included in alsa-utils package. The latest
version can be found on git repository:
-- git://git.alsa-project.org/alsa-utils.git
+* git://git.alsa-project.org/alsa-utils.git
The script can be fetched directly from the following URL, too:
-- http://www.alsa-project.org/alsa-info.sh
+* http://www.alsa-project.org/alsa-info.sh
Run this script as root, and it will gather the important information
such as the module lists, module parameters, proc file contents
including the codec proc files, mixer outputs and the control
elements. As default, it will store the information onto a web server
on alsa-project.org. But, if you send a bug report, it'd be better to
-run with `--no-upload` option, and attach the generated file.
+run with ``--no-upload`` option, and attach the generated file.
-There are some other useful options. See `--help` option output for
+There are some other useful options. See ``--help`` option output for
details.
When a probe error occurs or when the driver obviously assigns a
mismatched model, it'd be helpful to load the driver with
-`probe_only=1` option (at best after the cold reboot) and run
+``probe_only=1`` option (at best after the cold reboot) and run
alsa-info at this state. With this option, the driver won't configure
the mixer and PCM but just tries to probe the codec slot. After
probing, the proc file is available, so you can get the raw codec
information before modified by the driver. Of course, the driver
-isn't usable with `probe_only=1`. But you can continue the
+isn't usable with ``probe_only=1``. But you can continue the
configuration via hwdep sysfs file if hda-reconfig option is enabled.
-Using `probe_only` mask 2 skips the reset of HDA codecs (use
-`probe_only=3` as module option). The hwdep interface can be used
+Using ``probe_only`` mask 2 skips the reset of HDA codecs (use
+``probe_only=3`` as module option). The hwdep interface can be used
to determine the BIOS codec initialization.
hda-verb
-~~~~~~~~
+--------
hda-verb is a tiny program that allows you to access the HD-audio
codec directly. You can execute a raw HD-audio codec verb with this.
This program accesses the hwdep device, thus you need to enable the
-kernel config `CONFIG_SND_HDA_HWDEP=y` beforehand.
+kernel config ``CONFIG_SND_HDA_HWDEP=y`` beforehand.
The hda-verb program takes four arguments: the hwdep device file, the
widget NID, the verb and the parameter. When you access to the codec
@@ -739,19 +765,20 @@ parameter can be either a hex/digit number or a string corresponding
to a verb. Similarly, the last parameter is the value to write, or
can be a string for the parameter type.
-------------------------------------------------------------------------
- % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
- nid = 0x12, verb = 0x701, param = 0x2
- value = 0x0
+::
+
+ % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
+ nid = 0x12, verb = 0x701, param = 0x2
+ value = 0x0
- % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
- nid = 0x0, verb = 0xf00, param = 0x0
- value = 0x10ec0262
+ % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
+ nid = 0x0, verb = 0xf00, param = 0x0
+ value = 0x10ec0262
+
+ % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
+ nid = 0x2, verb = 0x300, param = 0xb080
+ value = 0x0
- % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
- nid = 0x2, verb = 0x300, param = 0xb080
- value = 0x0
-------------------------------------------------------------------------
Although you can issue any verbs with this program, the driver state
won't be always updated. For example, the volume values are usually
@@ -760,22 +787,22 @@ via hda-verb won't change the mixer value.
The hda-verb program is included now in alsa-tools:
-- git://git.alsa-project.org/alsa-tools.git
+* git://git.alsa-project.org/alsa-tools.git
Also, the old stand-alone package is found in the ftp directory:
-- ftp://ftp.suse.com/pub/people/tiwai/misc/
+* ftp://ftp.suse.com/pub/people/tiwai/misc/
Also a git repository is available:
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
+* git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
See README file in the tarball for more details about hda-verb
program.
hda-analyzer
-~~~~~~~~~~~~
+------------
hda-analyzer provides a graphical interface to access the raw HD-audio
control, based on pyGTK2 binding. It's a more powerful version of
hda-verb. The program gives you an easy-to-use GUI stuff for showing
@@ -784,14 +811,14 @@ proc-compatible output.
The hda-analyzer:
-- http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
+* http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
is a part of alsa.git repository in alsa-project.org:
-- git://git.alsa-project.org/alsa.git
+* git://git.alsa-project.org/alsa.git
Codecgraph
-~~~~~~~~~~
+----------
Codecgraph is a utility program to generate a graph and visualizes the
codec-node connection of a codec chip. It's especially useful when
you analyze or debug a codec without a proper datasheet. The program
@@ -800,11 +827,11 @@ program.
The tarball and GIT trees are found in the web page at:
-- http://helllabs.org/codecgraph/
+* http://helllabs.org/codecgraph/
hda-emu
-~~~~~~~
+-------
hda-emu is an HD-audio emulator. The main purpose of this program is
to debug an HD-audio codec without the real hardware. Thus, it
doesn't emulate the behavior with the real audio I/O, but it just
@@ -817,13 +844,14 @@ codec proc collections in the tarball. Then, run the program with the
proc file, and the hda-emu program will start parsing the codec file
and simulates the HD-audio driver:
-------------------------------------------------------------------------
- % hda-emu codecs/stac9200-dell-d820-laptop
- # Parsing..
- hda_codec: Unknown model for STAC9200, using BIOS defaults
- hda_codec: pin nid 08 bios pin config 40c003fa
- ....
-------------------------------------------------------------------------
+::
+
+ % hda-emu codecs/stac9200-dell-d820-laptop
+ # Parsing..
+ hda_codec: Unknown model for STAC9200, using BIOS defaults
+ hda_codec: pin nid 08 bios pin config 40c003fa
+ ....
+
The program gives you only a very dumb command-line interface. You
can get a proc-file dump at the current state, get a list of control
@@ -832,14 +860,14 @@ operation, the jack plugging simulation, etc.
The program is found in the git repository below:
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
+* git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
See README file in the repository for more details about hda-emu
program.
hda-jack-retask
-~~~~~~~~~~~~~~~
+---------------
hda-jack-retask is a user-friendly GUI program to manipulate the
HD-audio pin control for jack retasking. If you have a problem about
the jack assignment, try this program and check whether you can get
@@ -849,5 +877,4 @@ firmware patch file (see "Early Patching" section).
The program is included in alsa-tools now:
-- git://git.alsa-project.org/alsa-tools.git
-
+* git://git.alsa-project.org/alsa-tools.git
diff --git a/Documentation/sound/index.rst b/Documentation/sound/index.rst
new file mode 100644
index 000000000000..47b89f014e69
--- /dev/null
+++ b/Documentation/sound/index.rst
@@ -0,0 +1,20 @@
+===================================
+Linux Sound Subsystem Documentation
+===================================
+
+.. toctree::
+ :maxdepth: 2
+
+ kernel-api/index
+ designs/index
+ soc/index
+ alsa-configuration
+ hd-audio/index
+ cards/index
+
+.. only:: subproject
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/sound/kernel-api/alsa-driver-api.rst b/Documentation/sound/kernel-api/alsa-driver-api.rst
new file mode 100644
index 000000000000..14cd138989e3
--- /dev/null
+++ b/Documentation/sound/kernel-api/alsa-driver-api.rst
@@ -0,0 +1,134 @@
+===================
+The ALSA Driver API
+===================
+
+Management of Cards and Devices
+===============================
+
+Card Management
+---------------
+.. kernel-doc:: sound/core/init.c
+
+Device Components
+-----------------
+.. kernel-doc:: sound/core/device.c
+
+Module requests and Device File Entries
+---------------------------------------
+.. kernel-doc:: sound/core/sound.c
+
+Memory Management Helpers
+-------------------------
+.. kernel-doc:: sound/core/memory.c
+.. kernel-doc:: sound/core/memalloc.c
+
+
+PCM API
+=======
+
+PCM Core
+--------
+.. kernel-doc:: sound/core/pcm.c
+.. kernel-doc:: sound/core/pcm_lib.c
+.. kernel-doc:: sound/core/pcm_native.c
+.. kernel-doc:: include/sound/pcm.h
+
+PCM Format Helpers
+------------------
+.. kernel-doc:: sound/core/pcm_misc.c
+
+PCM Memory Management
+---------------------
+.. kernel-doc:: sound/core/pcm_memory.c
+
+PCM DMA Engine API
+------------------
+.. kernel-doc:: sound/core/pcm_dmaengine.c
+.. kernel-doc:: include/sound/dmaengine_pcm.h
+
+Control/Mixer API
+=================
+
+General Control Interface
+-------------------------
+.. kernel-doc:: sound/core/control.c
+
+AC97 Codec API
+--------------
+.. kernel-doc:: sound/pci/ac97/ac97_codec.c
+.. kernel-doc:: sound/pci/ac97/ac97_pcm.c
+
+Virtual Master Control API
+--------------------------
+.. kernel-doc:: sound/core/vmaster.c
+.. kernel-doc:: include/sound/control.h
+
+MIDI API
+========
+
+Raw MIDI API
+------------
+.. kernel-doc:: sound/core/rawmidi.c
+
+MPU401-UART API
+---------------
+.. kernel-doc:: sound/drivers/mpu401/mpu401_uart.c
+
+Proc Info API
+=============
+
+Proc Info Interface
+-------------------
+.. kernel-doc:: sound/core/info.c
+
+Compress Offload
+================
+
+Compress Offload API
+--------------------
+.. kernel-doc:: sound/core/compress_offload.c
+.. kernel-doc:: include/uapi/sound/compress_offload.h
+.. kernel-doc:: include/uapi/sound/compress_params.h
+.. kernel-doc:: include/sound/compress_driver.h
+
+ASoC
+====
+
+ASoC Core API
+-------------
+.. kernel-doc:: include/sound/soc.h
+.. kernel-doc:: sound/soc/soc-core.c
+.. kernel-doc:: sound/soc/soc-devres.c
+.. kernel-doc:: sound/soc/soc-io.c
+.. kernel-doc:: sound/soc/soc-pcm.c
+.. kernel-doc:: sound/soc/soc-ops.c
+.. kernel-doc:: sound/soc/soc-compress.c
+
+ASoC DAPM API
+-------------
+.. kernel-doc:: sound/soc/soc-dapm.c
+
+ASoC DMA Engine API
+-------------------
+.. kernel-doc:: sound/soc/soc-generic-dmaengine-pcm.c
+
+Miscellaneous Functions
+=======================
+
+Hardware-Dependent Devices API
+------------------------------
+.. kernel-doc:: sound/core/hwdep.c
+
+Jack Abstraction Layer API
+--------------------------
+.. kernel-doc:: include/sound/jack.h
+.. kernel-doc:: sound/core/jack.c
+.. kernel-doc:: sound/soc/soc-jack.c
+
+ISA DMA Helpers
+---------------
+.. kernel-doc:: sound/core/isadma.c
+
+Other Helper Macros
+-------------------
+.. kernel-doc:: include/sound/core.h
diff --git a/Documentation/sound/kernel-api/index.rst b/Documentation/sound/kernel-api/index.rst
new file mode 100644
index 000000000000..d0e6df35b4b4
--- /dev/null
+++ b/Documentation/sound/kernel-api/index.rst
@@ -0,0 +1,8 @@
+ALSA Kernel API Documentation
+=============================
+
+.. toctree::
+ :maxdepth: 2
+
+ alsa-driver-api
+ writing-an-alsa-driver
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
new file mode 100644
index 000000000000..95c5443eff38
--- /dev/null
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -0,0 +1,4219 @@
+======================
+Writing an ALSA Driver
+======================
+
+:Author: Takashi Iwai <tiwai@suse.de>
+:Date: Oct 15, 2007
+:Edition: 0.3.7
+
+Preface
+=======
+
+This document describes how to write an `ALSA (Advanced Linux Sound
+Architecture) <http://www.alsa-project.org/>`__ driver. The document
+focuses mainly on PCI soundcards. In the case of other device types, the
+API might be different, too. However, at least the ALSA kernel API is
+consistent, and therefore it would be still a bit help for writing them.
+
+This document targets people who already have enough C language skills
+and have basic linux kernel programming knowledge. This document doesn't
+explain the general topic of linux kernel coding and doesn't cover
+low-level driver implementation details. It only describes the standard
+way to write a PCI sound driver on ALSA.
+
+If you are already familiar with the older ALSA ver.0.5.x API, you can
+check the drivers such as ``sound/pci/es1938.c`` or
+``sound/pci/maestro3.c`` which have also almost the same code-base in
+the ALSA 0.5.x tree, so you can compare the differences.
+
+This document is still a draft version. Any feedback and corrections,
+please!!
+
+File Tree Structure
+===================
+
+General
+-------
+
+The ALSA drivers are provided in two ways.
+
+One is the trees provided as a tarball or via cvs from the ALSA's ftp
+site, and another is the 2.6 (or later) Linux kernel tree. To
+synchronize both, the ALSA driver tree is split into two different
+trees: alsa-kernel and alsa-driver. The former contains purely the
+source code for the Linux 2.6 (or later) tree. This tree is designed
+only for compilation on 2.6 or later environment. The latter,
+alsa-driver, contains many subtle files for compiling ALSA drivers
+outside of the Linux kernel tree, wrapper functions for older 2.2 and
+2.4 kernels, to adapt the latest kernel API, and additional drivers
+which are still in development or in tests. The drivers in alsa-driver
+tree will be moved to alsa-kernel (and eventually to the 2.6 kernel
+tree) when they are finished and confirmed to work fine.
+
+The file tree structure of ALSA driver is depicted below. Both
+alsa-kernel and alsa-driver have almost the same file structure, except
+for “core†directory. It's named as “acore†in alsa-driver tree.
+
+::
+
+ sound
+ /core
+ /oss
+ /seq
+ /oss
+ /instr
+ /ioctl32
+ /include
+ /drivers
+ /mpu401
+ /opl3
+ /i2c
+ /l3
+ /synth
+ /emux
+ /pci
+ /(cards)
+ /isa
+ /(cards)
+ /arm
+ /ppc
+ /sparc
+ /usb
+ /pcmcia /(cards)
+ /oss
+
+
+core directory
+--------------
+
+This directory contains the middle layer which is the heart of ALSA
+drivers. In this directory, the native ALSA modules are stored. The
+sub-directories contain different modules and are dependent upon the
+kernel config.
+
+core/oss
+~~~~~~~~
+
+The codes for PCM and mixer OSS emulation modules are stored in this
+directory. The rawmidi OSS emulation is included in the ALSA rawmidi
+code since it's quite small. The sequencer code is stored in
+``core/seq/oss`` directory (see `below <#core-seq-oss>`__).
+
+core/ioctl32
+~~~~~~~~~~~~
+
+This directory contains the 32bit-ioctl wrappers for 64bit architectures
+such like x86-64, ppc64 and sparc64. For 32bit and alpha architectures,
+these are not compiled.
+
+core/seq
+~~~~~~~~
+
+This directory and its sub-directories are for the ALSA sequencer. This
+directory contains the sequencer core and primary sequencer modules such
+like snd-seq-midi, snd-seq-virmidi, etc. They are compiled only when
+``CONFIG_SND_SEQUENCER`` is set in the kernel config.
+
+core/seq/oss
+~~~~~~~~~~~~
+
+This contains the OSS sequencer emulation codes.
+
+core/seq/instr
+~~~~~~~~~~~~~~
+
+This directory contains the modules for the sequencer instrument layer.
+
+include directory
+-----------------
+
+This is the place for the public header files of ALSA drivers, which are
+to be exported to user-space, or included by several files at different
+directories. Basically, the private header files should not be placed in
+this directory, but you may still find files there, due to historical
+reasons :)
+
+drivers directory
+-----------------
+
+This directory contains code shared among different drivers on different
+architectures. They are hence supposed not to be architecture-specific.
+For example, the dummy pcm driver and the serial MIDI driver are found
+in this directory. In the sub-directories, there is code for components
+which are independent from bus and cpu architectures.
+
+drivers/mpu401
+~~~~~~~~~~~~~~
+
+The MPU401 and MPU401-UART modules are stored here.
+
+drivers/opl3 and opl4
+~~~~~~~~~~~~~~~~~~~~~
+
+The OPL3 and OPL4 FM-synth stuff is found here.
+
+i2c directory
+-------------
+
+This contains the ALSA i2c components.
+
+Although there is a standard i2c layer on Linux, ALSA has its own i2c
+code for some cards, because the soundcard needs only a simple operation
+and the standard i2c API is too complicated for such a purpose.
+
+i2c/l3
+~~~~~~
+
+This is a sub-directory for ARM L3 i2c.
+
+synth directory
+---------------
+
+This contains the synth middle-level modules.
+
+So far, there is only Emu8000/Emu10k1 synth driver under the
+``synth/emux`` sub-directory.
+
+pci directory
+-------------
+
+This directory and its sub-directories hold the top-level card modules
+for PCI soundcards and the code specific to the PCI BUS.
+
+The drivers compiled from a single file are stored directly in the pci
+directory, while the drivers with several source files are stored on
+their own sub-directory (e.g. emu10k1, ice1712).
+
+isa directory
+-------------
+
+This directory and its sub-directories hold the top-level card modules
+for ISA soundcards.
+
+arm, ppc, and sparc directories
+-------------------------------
+
+They are used for top-level card modules which are specific to one of
+these architectures.
+
+usb directory
+-------------
+
+This directory contains the USB-audio driver. In the latest version, the
+USB MIDI driver is integrated in the usb-audio driver.
+
+pcmcia directory
+----------------
+
+The PCMCIA, especially PCCard drivers will go here. CardBus drivers will
+be in the pci directory, because their API is identical to that of
+standard PCI cards.
+
+oss directory
+-------------
+
+The OSS/Lite source files are stored here in Linux 2.6 (or later) tree.
+In the ALSA driver tarball, this directory is empty, of course :)
+
+Basic Flow for PCI Drivers
+==========================
+
+Outline
+-------
+
+The minimum flow for PCI soundcards is as follows:
+
+- define the PCI ID table (see the section `PCI Entries`_).
+
+- create ``probe`` callback.
+
+- create ``remove`` callback.
+
+- create a :c:type:`struct pci_driver <pci_driver>` structure
+ containing the three pointers above.
+
+- create an ``init`` function just calling the
+ :c:func:`pci_register_driver()` to register the pci_driver
+ table defined above.
+
+- create an ``exit`` function to call the
+ :c:func:`pci_unregister_driver()` function.
+
+Full Code Example
+-----------------
+
+The code example is shown below. Some parts are kept unimplemented at
+this moment but will be filled in the next sections. The numbers in the
+comment lines of the :c:func:`snd_mychip_probe()` function refer
+to details explained in the following section.
+
+::
+
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
+ #include <sound/initval.h>
+
+ /* module parameters (see "Module Parameters") */
+ /* SNDRV_CARDS: maximum number of cards supported by this module */
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+ /* definition of the chip-specific record */
+ struct mychip {
+ struct snd_card *card;
+ /* the rest of the implementation will be in section
+ * "PCI Resource Management"
+ */
+ };
+
+ /* chip-specific destructor
+ * (see "PCI Resource Management")
+ */
+ static int snd_mychip_free(struct mychip *chip)
+ {
+ .... /* will be implemented later... */
+ }
+
+ /* component-destructor
+ * (see "Management of Cards and Components")
+ */
+ static int snd_mychip_dev_free(struct snd_device *device)
+ {
+ return snd_mychip_free(device->device_data);
+ }
+
+ /* chip-specific constructor
+ * (see "Management of Cards and Components")
+ */
+ static int snd_mychip_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct mychip **rchip)
+ {
+ struct mychip *chip;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_mychip_dev_free,
+ };
+
+ *rchip = NULL;
+
+ /* check PCI availability here
+ * (see "PCI Resource Management")
+ */
+ ....
+
+ /* allocate a chip-specific data with zero filled */
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->card = card;
+
+ /* rest of initialization here; will be implemented
+ * later, see "PCI Resource Management"
+ */
+ ....
+
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
+ snd_mychip_free(chip);
+ return err;
+ }
+
+ *rchip = chip;
+ return 0;
+ }
+
+ /* constructor -- see "Driver Constructor" sub-section */
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+ {
+ static int dev;
+ struct snd_card *card;
+ struct mychip *chip;
+ int err;
+
+ /* (1) */
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ /* (2) */
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
+ if (err < 0)
+ return err;
+
+ /* (3) */
+ err = snd_mychip_create(card, pci, &chip);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ /* (4) */
+ strcpy(card->driver, "My Chip");
+ strcpy(card->shortname, "My Own Chip 123");
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->ioport, chip->irq);
+
+ /* (5) */
+ .... /* implemented later */
+
+ /* (6) */
+ err = snd_card_register(card);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ /* (7) */
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+ }
+
+ /* destructor -- see the "Destructor" sub-section */
+ static void snd_mychip_remove(struct pci_dev *pci)
+ {
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+ }
+
+
+
+Driver Constructor
+------------------
+
+The real constructor of PCI drivers is the ``probe`` callback. The
+``probe`` callback and other component-constructors which are called
+from the ``probe`` callback cannot be used with the ``__init`` prefix
+because any PCI device could be a hotplug device.
+
+In the ``probe`` callback, the following scheme is often used.
+
+1) Check and increment the device index.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static int dev;
+ ....
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+
+where ``enable[dev]`` is the module option.
+
+Each time the ``probe`` callback is called, check the availability of
+the device. If not available, simply increment the device index and
+returns. dev will be incremented also later (`step 7
+<#set-the-pci-driver-data-and-return-zero>`__).
+
+2) Create a card instance
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ struct snd_card *card;
+ int err;
+ ....
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
+
+
+The details will be explained in the section `Management of Cards and
+Components`_.
+
+3) Create a main component
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this part, the PCI resources are allocated.
+
+::
+
+ struct mychip *chip;
+ ....
+ err = snd_mychip_create(card, pci, &chip);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+The details will be explained in the section `PCI Resource
+Management`_.
+
+4) Set the driver ID and name strings.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ strcpy(card->driver, "My Chip");
+ strcpy(card->shortname, "My Own Chip 123");
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->ioport, chip->irq);
+
+The driver field holds the minimal ID string of the chip. This is used
+by alsa-lib's configurator, so keep it simple but unique. Even the
+same driver can have different driver IDs to distinguish the
+functionality of each chip type.
+
+The shortname field is a string shown as more verbose name. The longname
+field contains the information shown in ``/proc/asound/cards``.
+
+5) Create other components, such as mixer, MIDI, etc.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here you define the basic components such as `PCM <#PCM-Interface>`__,
+mixer (e.g. `AC97 <#API-for-AC97-Codec>`__), MIDI (e.g.
+`MPU-401 <#MIDI-MPU401-UART-Interface>`__), and other interfaces.
+Also, if you want a `proc file <#Proc-Interface>`__, define it here,
+too.
+
+6) Register the card instance.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+Will be explained in the section `Management of Cards and
+Components`_, too.
+
+7) Set the PCI driver data and return zero.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+
+In the above, the card record is stored. This pointer is used in the
+remove callback and power-management callbacks, too.
+
+Destructor
+----------
+
+The destructor, remove callback, simply releases the card instance. Then
+the ALSA middle layer will release all the attached components
+automatically.
+
+It would be typically like the following:
+
+::
+
+ static void snd_mychip_remove(struct pci_dev *pci)
+ {
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+ }
+
+
+The above code assumes that the card pointer is set to the PCI driver
+data.
+
+Header Files
+------------
+
+For the above example, at least the following include files are
+necessary.
+
+::
+
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
+ #include <sound/initval.h>
+
+where the last one is necessary only when module options are defined
+in the source file. If the code is split into several files, the files
+without module options don't need them.
+
+In addition to these headers, you'll need ``<linux/interrupt.h>`` for
+interrupt handling, and ``<asm/io.h>`` for I/O access. If you use the
+:c:func:`mdelay()` or :c:func:`udelay()` functions, you'll need
+to include ``<linux/delay.h>`` too.
+
+The ALSA interfaces like the PCM and control APIs are defined in other
+``<sound/xxx.h>`` header files. They have to be included after
+``<sound/core.h>``.
+
+Management of Cards and Components
+==================================
+
+Card Instance
+-------------
+
+For each soundcard, a “card†record must be allocated.
+
+A card record is the headquarters of the soundcard. It manages the whole
+list of devices (components) on the soundcard, such as PCM, mixers,
+MIDI, synthesizer, and so on. Also, the card record holds the ID and the
+name strings of the card, manages the root of proc files, and controls
+the power-management states and hotplug disconnections. The component
+list on the card record is used to manage the correct release of
+resources at destruction.
+
+As mentioned above, to create a card instance, call
+:c:func:`snd_card_new()`.
+
+::
+
+ struct snd_card *card;
+ int err;
+ err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
+
+
+The function takes six arguments: the parent device pointer, the
+card-index number, the id string, the module pointer (usually
+``THIS_MODULE``), the size of extra-data space, and the pointer to
+return the card instance. The extra_size argument is used to allocate
+card->private_data for the chip-specific data. Note that these data are
+allocated by :c:func:`snd_card_new()`.
+
+The first argument, the pointer of struct :c:type:`struct device
+<device>`, specifies the parent device. For PCI devices, typically
+``&pci->`` is passed there.
+
+Components
+----------
+
+After the card is created, you can attach the components (devices) to
+the card instance. In an ALSA driver, a component is represented as a
+:c:type:`struct snd_device <snd_device>` object. A component
+can be a PCM instance, a control interface, a raw MIDI interface, etc.
+Each such instance has one component entry.
+
+A component can be created via :c:func:`snd_device_new()`
+function.
+
+::
+
+ snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
+
+This takes the card pointer, the device-level (``SNDRV_DEV_XXX``), the
+data pointer, and the callback pointers (``&ops``). The device-level
+defines the type of components and the order of registration and
+de-registration. For most components, the device-level is already
+defined. For a user-defined component, you can use
+``SNDRV_DEV_LOWLEVEL``.
+
+This function itself doesn't allocate the data space. The data must be
+allocated manually beforehand, and its pointer is passed as the
+argument. This pointer (``chip`` in the above example) is used as the
+identifier for the instance.
+
+Each pre-defined ALSA component such as ac97 and pcm calls
+:c:func:`snd_device_new()` inside its constructor. The destructor
+for each component is defined in the callback pointers. Hence, you don't
+need to take care of calling a destructor for such a component.
+
+If you wish to create your own component, you need to set the destructor
+function to the dev_free callback in the ``ops``, so that it can be
+released automatically via :c:func:`snd_card_free()`. The next
+example will show an implementation of chip-specific data.
+
+Chip-Specific Data
+------------------
+
+Chip-specific information, e.g. the I/O port address, its resource
+pointer, or the irq number, is stored in the chip-specific record.
+
+::
+
+ struct mychip {
+ ....
+ };
+
+
+In general, there are two ways of allocating the chip record.
+
+1. Allocating via :c:func:`snd_card_new()`.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As mentioned above, you can pass the extra-data-length to the 5th
+argument of :c:func:`snd_card_new()`, i.e.
+
+::
+
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct mychip), &card);
+
+:c:type:`struct mychip <mychip>` is the type of the chip record.
+
+In return, the allocated record can be accessed as
+
+::
+
+ struct mychip *chip = card->private_data;
+
+With this method, you don't have to allocate twice. The record is
+released together with the card instance.
+
+2. Allocating an extra device.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After allocating a card instance via :c:func:`snd_card_new()`
+(with ``0`` on the 4th arg), call :c:func:`kzalloc()`.
+
+::
+
+ struct snd_card *card;
+ struct mychip *chip;
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
+ .....
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+
+The chip record should have the field to hold the card pointer at least,
+
+::
+
+ struct mychip {
+ struct snd_card *card;
+ ....
+ };
+
+
+Then, set the card pointer in the returned chip instance.
+
+::
+
+ chip->card = card;
+
+Next, initialize the fields, and register this chip record as a
+low-level device with a specified ``ops``,
+
+::
+
+ static struct snd_device_ops ops = {
+ .dev_free = snd_mychip_dev_free,
+ };
+ ....
+ snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+
+:c:func:`snd_mychip_dev_free()` is the device-destructor
+function, which will call the real destructor.
+
+::
+
+ static int snd_mychip_dev_free(struct snd_device *device)
+ {
+ return snd_mychip_free(device->device_data);
+ }
+
+where :c:func:`snd_mychip_free()` is the real destructor.
+
+Registration and Release
+------------------------
+
+After all components are assigned, register the card instance by calling
+:c:func:`snd_card_register()`. Access to the device files is
+enabled at this point. That is, before
+:c:func:`snd_card_register()` is called, the components are safely
+inaccessible from external side. If this call fails, exit the probe
+function after releasing the card via :c:func:`snd_card_free()`.
+
+For releasing the card instance, you can call simply
+:c:func:`snd_card_free()`. As mentioned earlier, all components
+are released automatically by this call.
+
+For a device which allows hotplugging, you can use
+:c:func:`snd_card_free_when_closed()`. This one will postpone
+the destruction until all devices are closed.
+
+PCI Resource Management
+=======================
+
+Full Code Example
+-----------------
+
+In this section, we'll complete the chip-specific constructor,
+destructor and PCI entries. Example code is shown first, below.
+
+::
+
+ struct mychip {
+ struct snd_card *card;
+ struct pci_dev *pci;
+
+ unsigned long port;
+ int irq;
+ };
+
+ static int snd_mychip_free(struct mychip *chip)
+ {
+ /* disable hardware here if any */
+ .... /* (not implemented in this document) */
+
+ /* release the irq */
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+ /* release the I/O ports & memory */
+ pci_release_regions(chip->pci);
+ /* disable the PCI entry */
+ pci_disable_device(chip->pci);
+ /* release the data */
+ kfree(chip);
+ return 0;
+ }
+
+ /* chip-specific constructor */
+ static int snd_mychip_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct mychip **rchip)
+ {
+ struct mychip *chip;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_mychip_dev_free,
+ };
+
+ *rchip = NULL;
+
+ /* initialize the PCI entry */
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+ /* check PCI availability (28bit DMA) */
+ if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
+ printk(KERN_ERR "error to set 28bit mask DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ /* initialize the stuff */
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ /* (1) PCI resource allocation */
+ err = pci_request_regions(pci, "My Chip");
+ if (err < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+ chip->port = pci_resource_start(pci, 0);
+ if (request_irq(pci->irq, snd_mychip_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+ snd_mychip_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+ /* (2) initialization of the chip hardware */
+ .... /* (not implemented in this document) */
+
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
+ snd_mychip_free(chip);
+ return err;
+ }
+
+ *rchip = chip;
+ return 0;
+ }
+
+ /* PCI IDs */
+ static struct pci_device_id snd_mychip_ids[] = {
+ { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+ ....
+ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+
+ /* pci_driver definition */
+ static struct pci_driver driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_mychip_ids,
+ .probe = snd_mychip_probe,
+ .remove = snd_mychip_remove,
+ };
+
+ /* module initialization */
+ static int __init alsa_card_mychip_init(void)
+ {
+ return pci_register_driver(&driver);
+ }
+
+ /* module clean up */
+ static void __exit alsa_card_mychip_exit(void)
+ {
+ pci_unregister_driver(&driver);
+ }
+
+ module_init(alsa_card_mychip_init)
+ module_exit(alsa_card_mychip_exit)
+
+ EXPORT_NO_SYMBOLS; /* for old kernels only */
+
+Some Hafta's
+------------
+
+The allocation of PCI resources is done in the ``probe`` function, and
+usually an extra :c:func:`xxx_create()` function is written for this
+purpose.
+
+In the case of PCI devices, you first have to call the
+:c:func:`pci_enable_device()` function before allocating
+resources. Also, you need to set the proper PCI DMA mask to limit the
+accessed I/O range. In some cases, you might need to call
+:c:func:`pci_set_master()` function, too.
+
+Suppose the 28bit mask, and the code to be added would be like:
+
+::
+
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+ if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
+ printk(KERN_ERR "error to set 28bit mask DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+
+Resource Allocation
+-------------------
+
+The allocation of I/O ports and irqs is done via standard kernel
+functions. Unlike ALSA ver.0.5.x., there are no helpers for that. And
+these resources must be released in the destructor function (see below).
+Also, on ALSA 0.9.x, you don't need to allocate (pseudo-)DMA for PCI
+like in ALSA 0.5.x.
+
+Now assume that the PCI device has an I/O port with 8 bytes and an
+interrupt. Then :c:type:`struct mychip <mychip>` will have the
+following fields:
+
+::
+
+ struct mychip {
+ struct snd_card *card;
+
+ unsigned long port;
+ int irq;
+ };
+
+
+For an I/O port (and also a memory region), you need to have the
+resource pointer for the standard resource management. For an irq, you
+have to keep only the irq number (integer). But you need to initialize
+this number as -1 before actual allocation, since irq 0 is valid. The
+port address and its resource pointer can be initialized as null by
+:c:func:`kzalloc()` automatically, so you don't have to take care of
+resetting them.
+
+The allocation of an I/O port is done like this:
+
+::
+
+ err = pci_request_regions(pci, "My Chip");
+ if (err < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+ chip->port = pci_resource_start(pci, 0);
+
+It will reserve the I/O port region of 8 bytes of the given PCI device.
+The returned value, ``chip->res_port``, is allocated via
+:c:func:`kmalloc()` by :c:func:`request_region()`. The pointer
+must be released via :c:func:`kfree()`, but there is a problem with
+this. This issue will be explained later.
+
+The allocation of an interrupt source is done like this:
+
+::
+
+ if (request_irq(pci->irq, snd_mychip_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+ snd_mychip_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+where :c:func:`snd_mychip_interrupt()` is the interrupt handler
+defined `later <#pcm-interface-interrupt-handler>`__. Note that
+``chip->irq`` should be defined only when :c:func:`request_irq()`
+succeeded.
+
+On the PCI bus, interrupts can be shared. Thus, ``IRQF_SHARED`` is used
+as the interrupt flag of :c:func:`request_irq()`.
+
+The last argument of :c:func:`request_irq()` is the data pointer
+passed to the interrupt handler. Usually, the chip-specific record is
+used for that, but you can use what you like, too.
+
+I won't give details about the interrupt handler at this point, but at
+least its appearance can be explained now. The interrupt handler looks
+usually like the following:
+
+::
+
+ static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+ {
+ struct mychip *chip = dev_id;
+ ....
+ return IRQ_HANDLED;
+ }
+
+
+Now let's write the corresponding destructor for the resources above.
+The role of destructor is simple: disable the hardware (if already
+activated) and release the resources. So far, we have no hardware part,
+so the disabling code is not written here.
+
+To release the resources, the “check-and-release†method is a safer way.
+For the interrupt, do like this:
+
+::
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
+Since the irq number can start from 0, you should initialize
+``chip->irq`` with a negative value (e.g. -1), so that you can check
+the validity of the irq number as above.
+
+When you requested I/O ports or memory regions via
+:c:func:`pci_request_region()` or
+:c:func:`pci_request_regions()` like in this example, release the
+resource(s) using the corresponding function,
+:c:func:`pci_release_region()` or
+:c:func:`pci_release_regions()`.
+
+::
+
+ pci_release_regions(chip->pci);
+
+When you requested manually via :c:func:`request_region()` or
+:c:func:`request_mem_region()`, you can release it via
+:c:func:`release_resource()`. Suppose that you keep the resource
+pointer returned from :c:func:`request_region()` in
+chip->res_port, the release procedure looks like:
+
+::
+
+ release_and_free_resource(chip->res_port);
+
+Don't forget to call :c:func:`pci_disable_device()` before the
+end.
+
+And finally, release the chip-specific record.
+
+::
+
+ kfree(chip);
+
+We didn't implement the hardware disabling part in the above. If you
+need to do this, please note that the destructor may be called even
+before the initialization of the chip is completed. It would be better
+to have a flag to skip hardware disabling if the hardware was not
+initialized yet.
+
+When the chip-data is assigned to the card using
+:c:func:`snd_device_new()` with ``SNDRV_DEV_LOWLELVEL`` , its
+destructor is called at the last. That is, it is assured that all other
+components like PCMs and controls have already been released. You don't
+have to stop PCMs, etc. explicitly, but just call low-level hardware
+stopping.
+
+The management of a memory-mapped region is almost as same as the
+management of an I/O port. You'll need three fields like the
+following:
+
+::
+
+ struct mychip {
+ ....
+ unsigned long iobase_phys;
+ void __iomem *iobase_virt;
+ };
+
+and the allocation would be like below:
+
+::
+
+ if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+ kfree(chip);
+ return err;
+ }
+ chip->iobase_phys = pci_resource_start(pci, 0);
+ chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
+ pci_resource_len(pci, 0));
+
+and the corresponding destructor would be:
+
+::
+
+ static int snd_mychip_free(struct mychip *chip)
+ {
+ ....
+ if (chip->iobase_virt)
+ iounmap(chip->iobase_virt);
+ ....
+ pci_release_regions(chip->pci);
+ ....
+ }
+
+PCI Entries
+-----------
+
+So far, so good. Let's finish the missing PCI stuff. At first, we need a
+:c:type:`struct pci_device_id <pci_device_id>` table for
+this chipset. It's a table of PCI vendor/device ID number, and some
+masks.
+
+For example,
+
+::
+
+ static struct pci_device_id snd_mychip_ids[] = {
+ { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+ ....
+ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+
+The first and second fields of the :c:type:`struct pci_device_id
+<pci_device_id>` structure are the vendor and device IDs. If you
+have no reason to filter the matching devices, you can leave the
+remaining fields as above. The last field of the :c:type:`struct
+pci_device_id <pci_device_id>` struct contains private data
+for this entry. You can specify any value here, for example, to define
+specific operations for supported device IDs. Such an example is found
+in the intel8x0 driver.
+
+The last entry of this list is the terminator. You must specify this
+all-zero entry.
+
+Then, prepare the :c:type:`struct pci_driver <pci_driver>`
+record:
+
+::
+
+ static struct pci_driver driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_mychip_ids,
+ .probe = snd_mychip_probe,
+ .remove = snd_mychip_remove,
+ };
+
+The ``probe`` and ``remove`` functions have already been defined in
+the previous sections. The ``name`` field is the name string of this
+device. Note that you must not use a slash “/†in this string.
+
+And at last, the module entries:
+
+::
+
+ static int __init alsa_card_mychip_init(void)
+ {
+ return pci_register_driver(&driver);
+ }
+
+ static void __exit alsa_card_mychip_exit(void)
+ {
+ pci_unregister_driver(&driver);
+ }
+
+ module_init(alsa_card_mychip_init)
+ module_exit(alsa_card_mychip_exit)
+
+Note that these module entries are tagged with ``__init`` and ``__exit``
+prefixes.
+
+Oh, one thing was forgotten. If you have no exported symbols, you need
+to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
+
+::
+
+ EXPORT_NO_SYMBOLS;
+
+That's all!
+
+PCM Interface
+=============
+
+General
+-------
+
+The PCM middle layer of ALSA is quite powerful and it is only necessary
+for each driver to implement the low-level functions to access its
+hardware.
+
+For accessing to the PCM layer, you need to include ``<sound/pcm.h>``
+first. In addition, ``<sound/pcm_params.h>`` might be needed if you
+access to some functions related with hw_param.
+
+Each card device can have up to four pcm instances. A pcm instance
+corresponds to a pcm device file. The limitation of number of instances
+comes only from the available bit size of the Linux's device numbers.
+Once when 64bit device number is used, we'll have more pcm instances
+available.
+
+A pcm instance consists of pcm playback and capture streams, and each
+pcm stream consists of one or more pcm substreams. Some soundcards
+support multiple playback functions. For example, emu10k1 has a PCM
+playback of 32 stereo substreams. In this case, at each open, a free
+substream is (usually) automatically chosen and opened. Meanwhile, when
+only one substream exists and it was already opened, the successful open
+will either block or error with ``EAGAIN`` according to the file open
+mode. But you don't have to care about such details in your driver. The
+PCM middle layer will take care of such work.
+
+Full Code Example
+-----------------
+
+The example code below does not include any hardware access routines but
+shows only the skeleton, how to build up the PCM interfaces.
+
+::
+
+ #include <sound/pcm.h>
+ ....
+
+ /* hardware definition */
+ static struct snd_pcm_hardware snd_mychip_playback_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 32768,
+ .period_bytes_min = 4096,
+ .period_bytes_max = 32768,
+ .periods_min = 1,
+ .periods_max = 1024,
+ };
+
+ /* hardware definition */
+ static struct snd_pcm_hardware snd_mychip_capture_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 32768,
+ .period_bytes_min = 4096,
+ .period_bytes_max = 32768,
+ .periods_min = 1,
+ .periods_max = 1024,
+ };
+
+ /* open callback */
+ static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw = snd_mychip_playback_hw;
+ /* more hardware-initialization will be done here */
+ ....
+ return 0;
+ }
+
+ /* close callback */
+ static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ /* the hardware-specific codes will be here */
+ ....
+ return 0;
+
+ }
+
+ /* open callback */
+ static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw = snd_mychip_capture_hw;
+ /* more hardware-initialization will be done here */
+ ....
+ return 0;
+ }
+
+ /* close callback */
+ static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ /* the hardware-specific codes will be here */
+ ....
+ return 0;
+
+ }
+
+ /* hw_params callback */
+ static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+ {
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ }
+
+ /* hw_free callback */
+ static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+ return snd_pcm_lib_free_pages(substream);
+ }
+
+ /* prepare callback */
+ static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /* set up the hardware with the current configuration
+ * for example...
+ */
+ mychip_set_sample_format(chip, runtime->format);
+ mychip_set_sample_rate(chip, runtime->rate);
+ mychip_set_channels(chip, runtime->channels);
+ mychip_set_dma_setup(chip, runtime->dma_addr,
+ chip->buffer_size,
+ chip->period_size);
+ return 0;
+ }
+
+ /* trigger callback */
+ static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+ {
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* do something to start the PCM engine */
+ ....
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ /* do something to stop the PCM engine */
+ ....
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* pointer callback */
+ static snd_pcm_uframes_t
+ snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ unsigned int current_ptr;
+
+ /* get the current hardware pointer */
+ current_ptr = mychip_get_hw_pointer(chip);
+ return current_ptr;
+ }
+
+ /* operators */
+ static struct snd_pcm_ops snd_mychip_playback_ops = {
+ .open = snd_mychip_playback_open,
+ .close = snd_mychip_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_mychip_pcm_hw_params,
+ .hw_free = snd_mychip_pcm_hw_free,
+ .prepare = snd_mychip_pcm_prepare,
+ .trigger = snd_mychip_pcm_trigger,
+ .pointer = snd_mychip_pcm_pointer,
+ };
+
+ /* operators */
+ static struct snd_pcm_ops snd_mychip_capture_ops = {
+ .open = snd_mychip_capture_open,
+ .close = snd_mychip_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_mychip_pcm_hw_params,
+ .hw_free = snd_mychip_pcm_hw_free,
+ .prepare = snd_mychip_pcm_prepare,
+ .trigger = snd_mychip_pcm_trigger,
+ .pointer = snd_mychip_pcm_pointer,
+ };
+
+ /*
+ * definitions of capture are omitted here...
+ */
+
+ /* create a pcm device */
+ static int snd_mychip_new_pcm(struct mychip *chip)
+ {
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, "My Chip");
+ chip->pcm = pcm;
+ /* set operators */
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_mychip_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_mychip_capture_ops);
+ /* pre-allocation of buffers */
+ /* NOTE: this may fail */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 64*1024);
+ return 0;
+ }
+
+
+PCM Constructor
+---------------
+
+A pcm instance is allocated by the :c:func:`snd_pcm_new()`
+function. It would be better to create a constructor for pcm, namely,
+
+::
+
+ static int snd_mychip_new_pcm(struct mychip *chip)
+ {
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, "My Chip");
+ chip->pcm = pcm;
+ ....
+ return 0;
+ }
+
+The :c:func:`snd_pcm_new()` function takes four arguments. The
+first argument is the card pointer to which this pcm is assigned, and
+the second is the ID string.
+
+The third argument (``index``, 0 in the above) is the index of this new
+pcm. It begins from zero. If you create more than one pcm instances,
+specify the different numbers in this argument. For example, ``index =
+1`` for the second PCM device.
+
+The fourth and fifth arguments are the number of substreams for playback
+and capture, respectively. Here 1 is used for both arguments. When no
+playback or capture substreams are available, pass 0 to the
+corresponding argument.
+
+If a chip supports multiple playbacks or captures, you can specify more
+numbers, but they must be handled properly in open/close, etc.
+callbacks. When you need to know which substream you are referring to,
+then it can be obtained from :c:type:`struct snd_pcm_substream
+<snd_pcm_substream>` data passed to each callback as follows:
+
+::
+
+ struct snd_pcm_substream *substream;
+ int index = substream->number;
+
+
+After the pcm is created, you need to set operators for each pcm stream.
+
+::
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_mychip_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_mychip_capture_ops);
+
+The operators are defined typically like this:
+
+::
+
+ static struct snd_pcm_ops snd_mychip_playback_ops = {
+ .open = snd_mychip_pcm_open,
+ .close = snd_mychip_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_mychip_pcm_hw_params,
+ .hw_free = snd_mychip_pcm_hw_free,
+ .prepare = snd_mychip_pcm_prepare,
+ .trigger = snd_mychip_pcm_trigger,
+ .pointer = snd_mychip_pcm_pointer,
+ };
+
+All the callbacks are described in the Operators_ subsection.
+
+After setting the operators, you probably will want to pre-allocate the
+buffer. For the pre-allocation, simply call the following:
+
+::
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 64*1024);
+
+It will allocate a buffer up to 64kB as default. Buffer management
+details will be described in the later section `Buffer and Memory
+Management`_.
+
+Additionally, you can set some extra information for this pcm in
+``pcm->info_flags``. The available values are defined as
+``SNDRV_PCM_INFO_XXX`` in ``<sound/asound.h>``, which is used for the
+hardware definition (described later). When your soundchip supports only
+half-duplex, specify like this:
+
+::
+
+ pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+
+
+... And the Destructor?
+-----------------------
+
+The destructor for a pcm instance is not always necessary. Since the pcm
+device will be released by the middle layer code automatically, you
+don't have to call the destructor explicitly.
+
+The destructor would be necessary if you created special records
+internally and needed to release them. In such a case, set the
+destructor function to ``pcm->private_free``:
+
+::
+
+ static void mychip_pcm_free(struct snd_pcm *pcm)
+ {
+ struct mychip *chip = snd_pcm_chip(pcm);
+ /* free your own data */
+ kfree(chip->my_private_pcm_data);
+ /* do what you like else */
+ ....
+ }
+
+ static int snd_mychip_new_pcm(struct mychip *chip)
+ {
+ struct snd_pcm *pcm;
+ ....
+ /* allocate your own data */
+ chip->my_private_pcm_data = kmalloc(...);
+ /* set the destructor */
+ pcm->private_data = chip;
+ pcm->private_free = mychip_pcm_free;
+ ....
+ }
+
+
+
+Runtime Pointer - The Chest of PCM Information
+----------------------------------------------
+
+When the PCM substream is opened, a PCM runtime instance is allocated
+and assigned to the substream. This pointer is accessible via
+``substream->runtime``. This runtime pointer holds most information you
+need to control the PCM: the copy of hw_params and sw_params
+configurations, the buffer pointers, mmap records, spinlocks, etc.
+
+The definition of runtime instance is found in ``<sound/pcm.h>``. Here
+are the contents of this file:
+
+::
+
+ struct _snd_pcm_runtime {
+ /* -- Status -- */
+ struct snd_pcm_substream *trigger_master;
+ snd_timestamp_t trigger_tstamp; /* trigger timestamp */
+ int overrange;
+ snd_pcm_uframes_t avail_max;
+ snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
+ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
+
+ /* -- HW params -- */
+ snd_pcm_access_t access; /* access mode */
+ snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */
+ snd_pcm_subformat_t subformat; /* subformat */
+ unsigned int rate; /* rate in Hz */
+ unsigned int channels; /* channels */
+ snd_pcm_uframes_t period_size; /* period size */
+ unsigned int periods; /* periods */
+ snd_pcm_uframes_t buffer_size; /* buffer size */
+ unsigned int tick_time; /* tick time */
+ snd_pcm_uframes_t min_align; /* Min alignment for the format */
+ size_t byte_align;
+ unsigned int frame_bits;
+ unsigned int sample_bits;
+ unsigned int info;
+ unsigned int rate_num;
+ unsigned int rate_den;
+
+ /* -- SW params -- */
+ struct timespec tstamp_mode; /* mmap timestamp is updated */
+ unsigned int period_step;
+ unsigned int sleep_min; /* min ticks to sleep */
+ snd_pcm_uframes_t start_threshold;
+ snd_pcm_uframes_t stop_threshold;
+ snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
+ noise is nearest than this */
+ snd_pcm_uframes_t silence_size; /* Silence filling size */
+ snd_pcm_uframes_t boundary; /* pointers wrap point */
+
+ snd_pcm_uframes_t silenced_start;
+ snd_pcm_uframes_t silenced_size;
+
+ snd_pcm_sync_id_t sync; /* hardware synchronization ID */
+
+ /* -- mmap -- */
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
+ atomic_t mmap_count;
+
+ /* -- locking / scheduling -- */
+ spinlock_t lock;
+ wait_queue_head_t sleep;
+ struct timer_list tick_timer;
+ struct fasync_struct *fasync;
+
+ /* -- private section -- */
+ void *private_data;
+ void (*private_free)(struct snd_pcm_runtime *runtime);
+
+ /* -- hardware description -- */
+ struct snd_pcm_hardware hw;
+ struct snd_pcm_hw_constraints hw_constraints;
+
+ /* -- timer -- */
+ unsigned int timer_resolution; /* timer resolution */
+
+ /* -- DMA -- */
+ unsigned char *dma_area; /* DMA area */
+ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */
+ size_t dma_bytes; /* size of DMA area */
+
+ struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
+
+ #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
+ /* -- OSS things -- */
+ struct snd_pcm_oss_runtime oss;
+ #endif
+ };
+
+
+For the operators (callbacks) of each sound driver, most of these
+records are supposed to be read-only. Only the PCM middle-layer changes
+/ updates them. The exceptions are the hardware description (hw) DMA
+buffer information and the private data. Besides, if you use the
+standard buffer allocation method via
+:c:func:`snd_pcm_lib_malloc_pages()`, you don't need to set the
+DMA buffer information by yourself.
+
+In the sections below, important records are explained.
+
+Hardware Description
+~~~~~~~~~~~~~~~~~~~~
+
+The hardware descriptor (:c:type:`struct snd_pcm_hardware
+<snd_pcm_hardware>`) contains the definitions of the fundamental
+hardware configuration. Above all, you'll need to define this in the
+`PCM open callback`_. Note that the runtime instance holds the copy of
+the descriptor, not the pointer to the existing descriptor. That is,
+in the open callback, you can modify the copied descriptor
+(``runtime->hw``) as you need. For example, if the maximum number of
+channels is 1 only on some chip models, you can still use the same
+hardware descriptor and change the channels_max later:
+
+::
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ ...
+ runtime->hw = snd_mychip_playback_hw; /* common definition */
+ if (chip->model == VERY_OLD_ONE)
+ runtime->hw.channels_max = 1;
+
+Typically, you'll have a hardware descriptor as below:
+
+::
+
+ static struct snd_pcm_hardware snd_mychip_playback_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 32768,
+ .period_bytes_min = 4096,
+ .period_bytes_max = 32768,
+ .periods_min = 1,
+ .periods_max = 1024,
+ };
+
+- The ``info`` field contains the type and capabilities of this
+ pcm. The bit flags are defined in ``<sound/asound.h>`` as
+ ``SNDRV_PCM_INFO_XXX``. Here, at least, you have to specify whether
+ the mmap is supported and which interleaved format is
+ supported. When the hardware supports mmap, add the
+ ``SNDRV_PCM_INFO_MMAP`` flag here. When the hardware supports the
+ interleaved or the non-interleaved formats,
+ ``SNDRV_PCM_INFO_INTERLEAVED`` or ``SNDRV_PCM_INFO_NONINTERLEAVED``
+ flag must be set, respectively. If both are supported, you can set
+ both, too.
+
+ In the above example, ``MMAP_VALID`` and ``BLOCK_TRANSFER`` are
+ specified for the OSS mmap mode. Usually both are set. Of course,
+ ``MMAP_VALID`` is set only if the mmap is really supported.
+
+ The other possible flags are ``SNDRV_PCM_INFO_PAUSE`` and
+ ``SNDRV_PCM_INFO_RESUME``. The ``PAUSE`` bit means that the pcm
+ supports the “pause†operation, while the ``RESUME`` bit means that
+ the pcm supports the full “suspend/resume†operation. If the
+ ``PAUSE`` flag is set, the ``trigger`` callback below must handle
+ the corresponding (pause push/release) commands. The suspend/resume
+ trigger commands can be defined even without the ``RESUME``
+ flag. See `Power Management`_ section for details.
+
+ When the PCM substreams can be synchronized (typically,
+ synchronized start/stop of a playback and a capture streams), you
+ can give ``SNDRV_PCM_INFO_SYNC_START``, too. In this case, you'll
+ need to check the linked-list of PCM substreams in the trigger
+ callback. This will be described in the later section.
+
+- ``formats`` field contains the bit-flags of supported formats
+ (``SNDRV_PCM_FMTBIT_XXX``). If the hardware supports more than one
+ format, give all or'ed bits. In the example above, the signed 16bit
+ little-endian format is specified.
+
+- ``rates`` field contains the bit-flags of supported rates
+ (``SNDRV_PCM_RATE_XXX``). When the chip supports continuous rates,
+ pass ``CONTINUOUS`` bit additionally. The pre-defined rate bits are
+ provided only for typical rates. If your chip supports
+ unconventional rates, you need to add the ``KNOT`` bit and set up
+ the hardware constraint manually (explained later).
+
+- ``rate_min`` and ``rate_max`` define the minimum and maximum sample
+ rate. This should correspond somehow to ``rates`` bits.
+
+- ``channel_min`` and ``channel_max`` define, as you might already
+ expected, the minimum and maximum number of channels.
+
+- ``buffer_bytes_max`` defines the maximum buffer size in
+ bytes. There is no ``buffer_bytes_min`` field, since it can be
+ calculated from the minimum period size and the minimum number of
+ periods. Meanwhile, ``period_bytes_min`` and define the minimum and
+ maximum size of the period in bytes. ``periods_max`` and
+ ``periods_min`` define the maximum and minimum number of periods in
+ the buffer.
+
+ The “period†is a term that corresponds to a fragment in the OSS
+ world. The period defines the size at which a PCM interrupt is
+ generated. This size strongly depends on the hardware. Generally,
+ the smaller period size will give you more interrupts, that is,
+ more controls. In the case of capture, this size defines the input
+ latency. On the other hand, the whole buffer size defines the
+ output latency for the playback direction.
+
+- There is also a field ``fifo_size``. This specifies the size of the
+ hardware FIFO, but currently it is neither used in the driver nor
+ in the alsa-lib. So, you can ignore this field.
+
+PCM Configurations
+~~~~~~~~~~~~~~~~~~
+
+Ok, let's go back again to the PCM runtime records. The most
+frequently referred records in the runtime instance are the PCM
+configurations. The PCM configurations are stored in the runtime
+instance after the application sends ``hw_params`` data via
+alsa-lib. There are many fields copied from hw_params and sw_params
+structs. For example, ``format`` holds the format type chosen by the
+application. This field contains the enum value
+``SNDRV_PCM_FORMAT_XXX``.
+
+One thing to be noted is that the configured buffer and period sizes
+are stored in “frames†in the runtime. In the ALSA world, ``1 frame =
+channels \* samples-size``. For conversion between frames and bytes,
+you can use the :c:func:`frames_to_bytes()` and
+:c:func:`bytes_to_frames()` helper functions.
+
+::
+
+ period_bytes = frames_to_bytes(runtime, runtime->period_size);
+
+Also, many software parameters (sw_params) are stored in frames, too.
+Please check the type of the field. ``snd_pcm_uframes_t`` is for the
+frames as unsigned integer while ``snd_pcm_sframes_t`` is for the
+frames as signed integer.
+
+DMA Buffer Information
+~~~~~~~~~~~~~~~~~~~~~~
+
+The DMA buffer is defined by the following four fields, ``dma_area``,
+``dma_addr``, ``dma_bytes`` and ``dma_private``. The ``dma_area``
+holds the buffer pointer (the logical address). You can call
+:c:func:`memcpy()` from/to this pointer. Meanwhile, ``dma_addr`` holds
+the physical address of the buffer. This field is specified only when
+the buffer is a linear buffer. ``dma_bytes`` holds the size of buffer
+in bytes. ``dma_private`` is used for the ALSA DMA allocator.
+
+If you use a standard ALSA function,
+:c:func:`snd_pcm_lib_malloc_pages()`, for allocating the buffer,
+these fields are set by the ALSA middle layer, and you should *not*
+change them by yourself. You can read them but not write them. On the
+other hand, if you want to allocate the buffer by yourself, you'll
+need to manage it in hw_params callback. At least, ``dma_bytes`` is
+mandatory. ``dma_area`` is necessary when the buffer is mmapped. If
+your driver doesn't support mmap, this field is not
+necessary. ``dma_addr`` is also optional. You can use dma_private as
+you like, too.
+
+Running Status
+~~~~~~~~~~~~~~
+
+The running status can be referred via ``runtime->status``. This is
+the pointer to the :c:type:`struct snd_pcm_mmap_status
+<snd_pcm_mmap_status>` record. For example, you can get the current
+DMA hardware pointer via ``runtime->status->hw_ptr``.
+
+The DMA application pointer can be referred via ``runtime->control``,
+which points to the :c:type:`struct snd_pcm_mmap_control
+<snd_pcm_mmap_control>` record. However, accessing directly to
+this value is not recommended.
+
+Private Data
+~~~~~~~~~~~~
+
+You can allocate a record for the substream and store it in
+``runtime->private_data``. Usually, this is done in the `PCM open
+callback`_. Don't mix this with ``pcm->private_data``. The
+``pcm->private_data`` usually points to the chip instance assigned
+statically at the creation of PCM, while the ``runtime->private_data``
+points to a dynamic data structure created at the PCM open
+callback.
+
+::
+
+ static int snd_xxx_open(struct snd_pcm_substream *substream)
+ {
+ struct my_pcm_data *data;
+ ....
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ substream->runtime->private_data = data;
+ ....
+ }
+
+
+The allocated object must be released in the `close callback`_.
+
+Operators
+---------
+
+OK, now let me give details about each pcm callback (``ops``). In
+general, every callback must return 0 if successful, or a negative
+error number such as ``-EINVAL``. To choose an appropriate error
+number, it is advised to check what value other parts of the kernel
+return when the same kind of request fails.
+
+The callback function takes at least the argument with :c:type:`struct
+snd_pcm_substream <snd_pcm_substream>` pointer. To retrieve the chip
+record from the given substream instance, you can use the following
+macro.
+
+::
+
+ int xxx() {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ ....
+ }
+
+The macro reads ``substream->private_data``, which is a copy of
+``pcm->private_data``. You can override the former if you need to
+assign different data records per PCM substream. For example, the
+cmi8330 driver assigns different ``private_data`` for playback and
+capture directions, because it uses two different codecs (SB- and
+AD-compatible) for different directions.
+
+PCM open callback
+~~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_open(struct snd_pcm_substream *substream);
+
+This is called when a pcm substream is opened.
+
+At least, here you have to initialize the ``runtime->hw``
+record. Typically, this is done by like this:
+
+::
+
+ static int snd_xxx_open(struct snd_pcm_substream *substream)
+ {
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw = snd_mychip_playback_hw;
+ return 0;
+ }
+
+where ``snd_mychip_playback_hw`` is the pre-defined hardware
+description.
+
+You can allocate a private data in this callback, as described in
+`Private Data`_ section.
+
+If the hardware configuration needs more constraints, set the hardware
+constraints here, too. See Constraints_ for more details.
+
+close callback
+~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_close(struct snd_pcm_substream *substream);
+
+
+Obviously, this is called when a pcm substream is closed.
+
+Any private instance for a pcm substream allocated in the ``open``
+callback will be released here.
+
+::
+
+ static int snd_xxx_close(struct snd_pcm_substream *substream)
+ {
+ ....
+ kfree(substream->runtime->private_data);
+ ....
+ }
+
+ioctl callback
+~~~~~~~~~~~~~~
+
+This is used for any special call to pcm ioctls. But usually you can
+pass a generic ioctl callback, :c:func:`snd_pcm_lib_ioctl()`.
+
+hw_params callback
+~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params);
+
+This is called when the hardware parameter (``hw_params``) is set up
+by the application, that is, once when the buffer size, the period
+size, the format, etc. are defined for the pcm substream.
+
+Many hardware setups should be done in this callback, including the
+allocation of buffers.
+
+Parameters to be initialized are retrieved by
+:c:func:`params_xxx()` macros. To allocate buffer, you can call a
+helper function,
+
+::
+
+ snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+
+:c:func:`snd_pcm_lib_malloc_pages()` is available only when the
+DMA buffers have been pre-allocated. See the section `Buffer Types`_
+for more details.
+
+Note that this and ``prepare`` callbacks may be called multiple times
+per initialization. For example, the OSS emulation may call these
+callbacks at each change via its ioctl.
+
+Thus, you need to be careful not to allocate the same buffers many
+times, which will lead to memory leaks! Calling the helper function
+above many times is OK. It will release the previous buffer
+automatically when it was already allocated.
+
+Another note is that this callback is non-atomic (schedulable) as
+default, i.e. when no ``nonatomic`` flag set. This is important,
+because the ``trigger`` callback is atomic (non-schedulable). That is,
+mutexes or any schedule-related functions are not available in
+``trigger`` callback. Please see the subsection Atomicity_ for
+details.
+
+hw_free callback
+~~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
+
+This is called to release the resources allocated via
+``hw_params``. For example, releasing the buffer via
+:c:func:`snd_pcm_lib_malloc_pages()` is done by calling the
+following:
+
+::
+
+ snd_pcm_lib_free_pages(substream);
+
+This function is always called before the close callback is called.
+Also, the callback may be called multiple times, too. Keep track
+whether the resource was already released.
+
+prepare callback
+~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_prepare(struct snd_pcm_substream *substream);
+
+This callback is called when the pcm is “preparedâ€. You can set the
+format type, sample rate, etc. here. The difference from ``hw_params``
+is that the ``prepare`` callback will be called each time
+:c:func:`snd_pcm_prepare()` is called, i.e. when recovering after
+underruns, etc.
+
+Note that this callback is now non-atomic. You can use
+schedule-related functions safely in this callback.
+
+In this and the following callbacks, you can refer to the values via
+the runtime record, ``substream->runtime``. For example, to get the
+current rate, format or channels, access to ``runtime->rate``,
+``runtime->format`` or ``runtime->channels``, respectively. The
+physical address of the allocated buffer is set to
+``runtime->dma_area``. The buffer and period sizes are in
+``runtime->buffer_size`` and ``runtime->period_size``, respectively.
+
+Be careful that this callback will be called many times at each setup,
+too.
+
+trigger callback
+~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
+
+This is called when the pcm is started, stopped or paused.
+
+Which action is specified in the second argument,
+``SNDRV_PCM_TRIGGER_XXX`` in ``<sound/pcm.h>``. At least, the ``START``
+and ``STOP`` commands must be defined in this callback.
+
+::
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* do something to start the PCM engine */
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ /* do something to stop the PCM engine */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+When the pcm supports the pause operation (given in the info field of
+the hardware table), the ``PAUSE_PUSH`` and ``PAUSE_RELEASE`` commands
+must be handled here, too. The former is the command to pause the pcm,
+and the latter to restart the pcm again.
+
+When the pcm supports the suspend/resume operation, regardless of full
+or partial suspend/resume support, the ``SUSPEND`` and ``RESUME``
+commands must be handled, too. These commands are issued when the
+power-management status is changed. Obviously, the ``SUSPEND`` and
+``RESUME`` commands suspend and resume the pcm substream, and usually,
+they are identical to the ``STOP`` and ``START`` commands, respectively.
+See the `Power Management`_ section for details.
+
+As mentioned, this callback is atomic as default unless ``nonatomic``
+flag set, and you cannot call functions which may sleep. The
+``trigger`` callback should be as minimal as possible, just really
+triggering the DMA. The other stuff should be initialized
+``hw_params`` and ``prepare`` callbacks properly beforehand.
+
+pointer callback
+~~~~~~~~~~~~~~~~
+
+::
+
+ static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
+
+This callback is called when the PCM middle layer inquires the current
+hardware position on the buffer. The position must be returned in
+frames, ranging from 0 to ``buffer_size - 1``.
+
+This is called usually from the buffer-update routine in the pcm
+middle layer, which is invoked when :c:func:`snd_pcm_period_elapsed()`
+is called in the interrupt routine. Then the pcm middle layer updates
+the position and calculates the available space, and wakes up the
+sleeping poll threads, etc.
+
+This callback is also atomic as default.
+
+copy and silence callbacks
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These callbacks are not mandatory, and can be omitted in most cases.
+These callbacks are used when the hardware buffer cannot be in the
+normal memory space. Some chips have their own buffer on the hardware
+which is not mappable. In such a case, you have to transfer the data
+manually from the memory buffer to the hardware buffer. Or, if the
+buffer is non-contiguous on both physical and virtual memory spaces,
+these callbacks must be defined, too.
+
+If these two callbacks are defined, copy and set-silence operations
+are done by them. The detailed will be described in the later section
+`Buffer and Memory Management`_.
+
+ack callback
+~~~~~~~~~~~~
+
+This callback is also not mandatory. This callback is called when the
+``appl_ptr`` is updated in read or write operations. Some drivers like
+emu10k1-fx and cs46xx need to track the current ``appl_ptr`` for the
+internal buffer, and this callback is useful only for such a purpose.
+
+This callback is atomic as default.
+
+page callback
+~~~~~~~~~~~~~
+
+This callback is optional too. This callback is used mainly for
+non-contiguous buffers. The mmap calls this callback to get the page
+address. Some examples will be explained in the later section `Buffer
+and Memory Management`_, too.
+
+PCM Interrupt Handler
+---------------------
+
+The rest of pcm stuff is the PCM interrupt handler. The role of PCM
+interrupt handler in the sound driver is to update the buffer position
+and to tell the PCM middle layer when the buffer position goes across
+the prescribed period size. To inform this, call the
+:c:func:`snd_pcm_period_elapsed()` function.
+
+There are several types of sound chips to generate the interrupts.
+
+Interrupts at the period (fragment) boundary
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the most frequently found type: the hardware generates an
+interrupt at each period boundary. In this case, you can call
+:c:func:`snd_pcm_period_elapsed()` at each interrupt.
+
+:c:func:`snd_pcm_period_elapsed()` takes the substream pointer as
+its argument. Thus, you need to keep the substream pointer accessible
+from the chip instance. For example, define ``substream`` field in the
+chip record to hold the current running substream pointer, and set the
+pointer value at ``open`` callback (and reset at ``close`` callback).
+
+If you acquire a spinlock in the interrupt handler, and the lock is used
+in other pcm callbacks, too, then you have to release the lock before
+calling :c:func:`snd_pcm_period_elapsed()`, because
+:c:func:`snd_pcm_period_elapsed()` calls other pcm callbacks
+inside.
+
+Typical code would be like:
+
+::
+
+
+ static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+ {
+ struct mychip *chip = dev_id;
+ spin_lock(&chip->lock);
+ ....
+ if (pcm_irq_invoked(chip)) {
+ /* call updater, unlock before it */
+ spin_unlock(&chip->lock);
+ snd_pcm_period_elapsed(chip->substream);
+ spin_lock(&chip->lock);
+ /* acknowledge the interrupt if necessary */
+ }
+ ....
+ spin_unlock(&chip->lock);
+ return IRQ_HANDLED;
+ }
+
+
+
+High frequency timer interrupts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This happens when the hardware doesn't generate interrupts at the period
+boundary but issues timer interrupts at a fixed timer rate (e.g. es1968
+or ymfpci drivers). In this case, you need to check the current hardware
+position and accumulate the processed sample length at each interrupt.
+When the accumulated size exceeds the period size, call
+:c:func:`snd_pcm_period_elapsed()` and reset the accumulator.
+
+Typical code would be like the following.
+
+::
+
+
+ static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+ {
+ struct mychip *chip = dev_id;
+ spin_lock(&chip->lock);
+ ....
+ if (pcm_irq_invoked(chip)) {
+ unsigned int last_ptr, size;
+ /* get the current hardware pointer (in frames) */
+ last_ptr = get_hw_ptr(chip);
+ /* calculate the processed frames since the
+ * last update
+ */
+ if (last_ptr < chip->last_ptr)
+ size = runtime->buffer_size + last_ptr
+ - chip->last_ptr;
+ else
+ size = last_ptr - chip->last_ptr;
+ /* remember the last updated point */
+ chip->last_ptr = last_ptr;
+ /* accumulate the size */
+ chip->size += size;
+ /* over the period boundary? */
+ if (chip->size >= runtime->period_size) {
+ /* reset the accumulator */
+ chip->size %= runtime->period_size;
+ /* call updater */
+ spin_unlock(&chip->lock);
+ snd_pcm_period_elapsed(substream);
+ spin_lock(&chip->lock);
+ }
+ /* acknowledge the interrupt if necessary */
+ }
+ ....
+ spin_unlock(&chip->lock);
+ return IRQ_HANDLED;
+ }
+
+
+
+On calling :c:func:`snd_pcm_period_elapsed()`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In both cases, even if more than one period are elapsed, you don't have
+to call :c:func:`snd_pcm_period_elapsed()` many times. Call only
+once. And the pcm layer will check the current hardware pointer and
+update to the latest status.
+
+Atomicity
+---------
+
+One of the most important (and thus difficult to debug) problems in
+kernel programming are race conditions. In the Linux kernel, they are
+usually avoided via spin-locks, mutexes or semaphores. In general, if a
+race condition can happen in an interrupt handler, it has to be managed
+atomically, and you have to use a spinlock to protect the critical
+session. If the critical section is not in interrupt handler code and if
+taking a relatively long time to execute is acceptable, you should use
+mutexes or semaphores instead.
+
+As already seen, some pcm callbacks are atomic and some are not. For
+example, the ``hw_params`` callback is non-atomic, while ``trigger``
+callback is atomic. This means, the latter is called already in a
+spinlock held by the PCM middle layer. Please take this atomicity into
+account when you choose a locking scheme in the callbacks.
+
+In the atomic callbacks, you cannot use functions which may call
+:c:func:`schedule()` or go to :c:func:`sleep()`. Semaphores and
+mutexes can sleep, and hence they cannot be used inside the atomic
+callbacks (e.g. ``trigger`` callback). To implement some delay in such a
+callback, please use :c:func:`udelay()` or :c:func:`mdelay()`.
+
+All three atomic callbacks (trigger, pointer, and ack) are called with
+local interrupts disabled.
+
+The recent changes in PCM core code, however, allow all PCM operations
+to be non-atomic. This assumes that the all caller sides are in
+non-atomic contexts. For example, the function
+:c:func:`snd_pcm_period_elapsed()` is called typically from the
+interrupt handler. But, if you set up the driver to use a threaded
+interrupt handler, this call can be in non-atomic context, too. In such
+a case, you can set ``nonatomic`` filed of :c:type:`struct snd_pcm
+<snd_pcm>` object after creating it. When this flag is set, mutex
+and rwsem are used internally in the PCM core instead of spin and
+rwlocks, so that you can call all PCM functions safely in a non-atomic
+context.
+
+Constraints
+-----------
+
+If your chip supports unconventional sample rates, or only the limited
+samples, you need to set a constraint for the condition.
+
+For example, in order to restrict the sample rates in the some supported
+values, use :c:func:`snd_pcm_hw_constraint_list()`. You need to
+call this function in the open callback.
+
+::
+
+ static unsigned int rates[] =
+ {4000, 10000, 22050, 44100};
+ static struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+
+ static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
+ {
+ int err;
+ ....
+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (err < 0)
+ return err;
+ ....
+ }
+
+
+
+There are many different constraints. Look at ``sound/pcm.h`` for a
+complete list. You can even define your own constraint rules. For
+example, let's suppose my_chip can manage a substream of 1 channel if
+and only if the format is ``S16_LE``, otherwise it supports any format
+specified in the :c:type:`struct snd_pcm_hardware
+<snd_pcm_hardware>` structure (or in any other
+constraint_list). You can build a rule like this:
+
+::
+
+ static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+ {
+ struct snd_interval *c = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_interval ch;
+
+ snd_interval_any(&ch);
+ if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
+ ch.min = ch.max = 1;
+ ch.integer = 1;
+ return snd_interval_refine(c, &ch);
+ }
+ return 0;
+ }
+
+
+Then you need to call this function to add your rule:
+
+::
+
+ snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ hw_rule_channels_by_format, NULL,
+ SNDRV_PCM_HW_PARAM_FORMAT, -1);
+
+The rule function is called when an application sets the PCM format, and
+it refines the number of channels accordingly. But an application may
+set the number of channels before setting the format. Thus you also need
+to define the inverse rule:
+
+::
+
+ static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+ {
+ struct snd_interval *c = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_mask fmt;
+
+ snd_mask_any(&fmt); /* Init the struct */
+ if (c->min < 2) {
+ fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
+ return snd_mask_refine(f, &fmt);
+ }
+ return 0;
+ }
+
+
+... and in the open callback:
+
+::
+
+ snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+ hw_rule_format_by_channels, NULL,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+I won't give more details here, rather I would like to say, “Luke, use
+the source.â€
+
+Control Interface
+=================
+
+General
+-------
+
+The control interface is used widely for many switches, sliders, etc.
+which are accessed from user-space. Its most important use is the mixer
+interface. In other words, since ALSA 0.9.x, all the mixer stuff is
+implemented on the control kernel API.
+
+ALSA has a well-defined AC97 control module. If your chip supports only
+the AC97 and nothing else, you can skip this section.
+
+The control API is defined in ``<sound/control.h>``. Include this file
+if you want to add your own controls.
+
+Definition of Controls
+----------------------
+
+To create a new control, you need to define the following three
+callbacks: ``info``, ``get`` and ``put``. Then, define a
+:c:type:`struct snd_kcontrol_new <snd_kcontrol_new>` record, such as:
+
+::
+
+
+ static struct snd_kcontrol_new my_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .private_value = 0xffff,
+ .info = my_control_info,
+ .get = my_control_get,
+ .put = my_control_put
+ };
+
+
+The ``iface`` field specifies the control type,
+``SNDRV_CTL_ELEM_IFACE_XXX``, which is usually ``MIXER``. Use ``CARD``
+for global controls that are not logically part of the mixer. If the
+control is closely associated with some specific device on the sound
+card, use ``HWDEP``, ``PCM``, ``RAWMIDI``, ``TIMER``, or ``SEQUENCER``,
+and specify the device number with the ``device`` and ``subdevice``
+fields.
+
+The ``name`` is the name identifier string. Since ALSA 0.9.x, the
+control name is very important, because its role is classified from
+its name. There are pre-defined standard control names. The details
+are described in the `Control Names`_ subsection.
+
+The ``index`` field holds the index number of this control. If there
+are several different controls with the same name, they can be
+distinguished by the index number. This is the case when several
+codecs exist on the card. If the index is zero, you can omit the
+definition above.
+
+The ``access`` field contains the access type of this control. Give
+the combination of bit masks, ``SNDRV_CTL_ELEM_ACCESS_XXX``,
+there. The details will be explained in the `Access Flags`_
+subsection.
+
+The ``private_value`` field contains an arbitrary long integer value
+for this record. When using the generic ``info``, ``get`` and ``put``
+callbacks, you can pass a value through this field. If several small
+numbers are necessary, you can combine them in bitwise. Or, it's
+possible to give a pointer (casted to unsigned long) of some record to
+this field, too.
+
+The ``tlv`` field can be used to provide metadata about the control;
+see the `Metadata`_ subsection.
+
+The other three are `Control Callbacks`_.
+
+Control Names
+-------------
+
+There are some standards to define the control names. A control is
+usually defined from the three parts as “SOURCE DIRECTION FUNCTIONâ€.
+
+The first, ``SOURCE``, specifies the source of the control, and is a
+string such as “Masterâ€, “PCMâ€, “CD†and “Lineâ€. There are many
+pre-defined sources.
+
+The second, ``DIRECTION``, is one of the following strings according to
+the direction of the control: “Playbackâ€, “Captureâ€, “Bypass Playbackâ€
+and “Bypass Captureâ€. Or, it can be omitted, meaning both playback and
+capture directions.
+
+The third, ``FUNCTION``, is one of the following strings according to
+the function of the control: “Switchâ€, “Volume†and “Routeâ€.
+
+The example of control names are, thus, “Master Capture Switch†or “PCM
+Playback Volumeâ€.
+
+There are some exceptions:
+
+Global capture and playback
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+“Capture Sourceâ€, “Capture Switch†and “Capture Volume†are used for the
+global capture (input) source, switch and volume. Similarly, “Playback
+Switch†and “Playback Volume†are used for the global output gain switch
+and volume.
+
+Tone-controls
+~~~~~~~~~~~~~
+
+tone-control switch and volumes are specified like “Tone Control - XXXâ€,
+e.g. “Tone Control - Switchâ€, “Tone Control - Bassâ€, “Tone Control -
+Centerâ€.
+
+3D controls
+~~~~~~~~~~~
+
+3D-control switches and volumes are specified like “3D Control - XXXâ€,
+e.g. “3D Control - Switchâ€, “3D Control - Centerâ€, “3D Control - Spaceâ€.
+
+Mic boost
+~~~~~~~~~
+
+Mic-boost switch is set as “Mic Boost†or “Mic Boost (6dB)â€.
+
+More precise information can be found in
+``Documentation/sound/alsa/ControlNames.txt``.
+
+Access Flags
+------------
+
+The access flag is the bitmask which specifies the access type of the
+given control. The default access type is
+``SNDRV_CTL_ELEM_ACCESS_READWRITE``, which means both read and write are
+allowed to this control. When the access flag is omitted (i.e. = 0), it
+is considered as ``READWRITE`` access as default.
+
+When the control is read-only, pass ``SNDRV_CTL_ELEM_ACCESS_READ``
+instead. In this case, you don't have to define the ``put`` callback.
+Similarly, when the control is write-only (although it's a rare case),
+you can use the ``WRITE`` flag instead, and you don't need the ``get``
+callback.
+
+If the control value changes frequently (e.g. the VU meter),
+``VOLATILE`` flag should be given. This means that the control may be
+changed without `Change notification`_. Applications should poll such
+a control constantly.
+
+When the control is inactive, set the ``INACTIVE`` flag, too. There are
+``LOCK`` and ``OWNER`` flags to change the write permissions.
+
+Control Callbacks
+-----------------
+
+info callback
+~~~~~~~~~~~~~
+
+The ``info`` callback is used to get detailed information on this
+control. This must store the values of the given :c:type:`struct
+snd_ctl_elem_info <snd_ctl_elem_info>` object. For example,
+for a boolean control with a single element:
+
+::
+
+
+ static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+ }
+
+
+
+The ``type`` field specifies the type of the control. There are
+``BOOLEAN``, ``INTEGER``, ``ENUMERATED``, ``BYTES``, ``IEC958`` and
+``INTEGER64``. The ``count`` field specifies the number of elements in
+this control. For example, a stereo volume would have count = 2. The
+``value`` field is a union, and the values stored are depending on the
+type. The boolean and integer types are identical.
+
+The enumerated type is a bit different from others. You'll need to set
+the string for the currently given item index.
+
+::
+
+ static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+ static char *texts[4] = {
+ "First", "Second", "Third", "Fourth"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item > 3)
+ uinfo->value.enumerated.item = 3;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+ }
+
+The above callback can be simplified with a helper function,
+:c:func:`snd_ctl_enum_info()`. The final code looks like below.
+(You can pass ``ARRAY_SIZE(texts)`` instead of 4 in the third argument;
+it's a matter of taste.)
+
+::
+
+ static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+ static char *texts[4] = {
+ "First", "Second", "Third", "Fourth"
+ };
+ return snd_ctl_enum_info(uinfo, 1, 4, texts);
+ }
+
+
+Some common info callbacks are available for your convenience:
+:c:func:`snd_ctl_boolean_mono_info()` and
+:c:func:`snd_ctl_boolean_stereo_info()`. Obviously, the former
+is an info callback for a mono channel boolean item, just like
+:c:func:`snd_myctl_mono_info()` above, and the latter is for a
+stereo channel boolean item.
+
+get callback
+~~~~~~~~~~~~
+
+This callback is used to read the current value of the control and to
+return to user-space.
+
+For example,
+
+::
+
+
+ static int snd_myctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct mychip *chip = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = get_some_value(chip);
+ return 0;
+ }
+
+
+
+The ``value`` field depends on the type of control as well as on the
+info callback. For example, the sb driver uses this field to store the
+register offset, the bit-shift and the bit-mask. The ``private_value``
+field is set as follows:
+
+::
+
+ .private_value = reg | (shift << 16) | (mask << 24)
+
+and is retrieved in callbacks like
+
+::
+
+ static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 16) & 0xff;
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+ ....
+ }
+
+In the ``get`` callback, you have to fill all the elements if the
+control has more than one elements, i.e. ``count > 1``. In the example
+above, we filled only one element (``value.integer.value[0]``) since
+it's assumed as ``count = 1``.
+
+put callback
+~~~~~~~~~~~~
+
+This callback is used to write a value from user-space.
+
+For example,
+
+::
+
+
+ static int snd_myctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct mychip *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ if (chip->current_value !=
+ ucontrol->value.integer.value[0]) {
+ change_current_value(chip,
+ ucontrol->value.integer.value[0]);
+ changed = 1;
+ }
+ return changed;
+ }
+
+
+
+As seen above, you have to return 1 if the value is changed. If the
+value is not changed, return 0 instead. If any fatal error happens,
+return a negative error code as usual.
+
+As in the ``get`` callback, when the control has more than one
+elements, all elements must be evaluated in this callback, too.
+
+Callbacks are not atomic
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+All these three callbacks are basically not atomic.
+
+Control Constructor
+-------------------
+
+When everything is ready, finally we can create a new control. To create
+a control, there are two functions to be called,
+:c:func:`snd_ctl_new1()` and :c:func:`snd_ctl_add()`.
+
+In the simplest way, you can do like this:
+
+::
+
+ err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
+ if (err < 0)
+ return err;
+
+where ``my_control`` is the :c:type:`struct snd_kcontrol_new
+<snd_kcontrol_new>` object defined above, and chip is the object
+pointer to be passed to kcontrol->private_data which can be referred
+to in callbacks.
+
+:c:func:`snd_ctl_new1()` allocates a new :c:type:`struct
+snd_kcontrol <snd_kcontrol>` instance, and
+:c:func:`snd_ctl_add()` assigns the given control component to the
+card.
+
+Change Notification
+-------------------
+
+If you need to change and update a control in the interrupt routine, you
+can call :c:func:`snd_ctl_notify()`. For example,
+
+::
+
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
+
+This function takes the card pointer, the event-mask, and the control id
+pointer for the notification. The event-mask specifies the types of
+notification, for example, in the above example, the change of control
+values is notified. The id pointer is the pointer of :c:type:`struct
+snd_ctl_elem_id <snd_ctl_elem_id>` to be notified. You can
+find some examples in ``es1938.c`` or ``es1968.c`` for hardware volume
+interrupts.
+
+Metadata
+--------
+
+To provide information about the dB values of a mixer control, use on of
+the ``DECLARE_TLV_xxx`` macros from ``<sound/tlv.h>`` to define a
+variable containing this information, set the ``tlv.p`` field to point to
+this variable, and include the ``SNDRV_CTL_ELEM_ACCESS_TLV_READ`` flag
+in the ``access`` field; like this:
+
+::
+
+ static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
+
+ static struct snd_kcontrol_new my_control = {
+ ...
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ ...
+ .tlv.p = db_scale_my_control,
+ };
+
+
+The :c:func:`DECLARE_TLV_DB_SCALE()` macro defines information
+about a mixer control where each step in the control's value changes the
+dB value by a constant dB amount. The first parameter is the name of the
+variable to be defined. The second parameter is the minimum value, in
+units of 0.01 dB. The third parameter is the step size, in units of 0.01
+dB. Set the fourth parameter to 1 if the minimum value actually mutes
+the control.
+
+The :c:func:`DECLARE_TLV_DB_LINEAR()` macro defines information
+about a mixer control where the control's value affects the output
+linearly. The first parameter is the name of the variable to be defined.
+The second parameter is the minimum value, in units of 0.01 dB. The
+third parameter is the maximum value, in units of 0.01 dB. If the
+minimum value mutes the control, set the second parameter to
+``TLV_DB_GAIN_MUTE``.
+
+API for AC97 Codec
+==================
+
+General
+-------
+
+The ALSA AC97 codec layer is a well-defined one, and you don't have to
+write much code to control it. Only low-level control routines are
+necessary. The AC97 codec API is defined in ``<sound/ac97_codec.h>``.
+
+Full Code Example
+-----------------
+
+::
+
+ struct mychip {
+ ....
+ struct snd_ac97 *ac97;
+ ....
+ };
+
+ static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+ {
+ struct mychip *chip = ac97->private_data;
+ ....
+ /* read a register value here from the codec */
+ return the_register_value;
+ }
+
+ static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+ {
+ struct mychip *chip = ac97->private_data;
+ ....
+ /* write the given register value to the codec */
+ }
+
+ static int snd_mychip_ac97(struct mychip *chip)
+ {
+ struct snd_ac97_bus *bus;
+ struct snd_ac97_template ac97;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_mychip_ac97_write,
+ .read = snd_mychip_ac97_read,
+ };
+
+ err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+ if (err < 0)
+ return err;
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+ }
+
+
+AC97 Constructor
+----------------
+
+To create an ac97 instance, first call :c:func:`snd_ac97_bus()`
+with an ``ac97_bus_ops_t`` record with callback functions.
+
+::
+
+ struct snd_ac97_bus *bus;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_mychip_ac97_write,
+ .read = snd_mychip_ac97_read,
+ };
+
+ snd_ac97_bus(card, 0, &ops, NULL, &pbus);
+
+The bus record is shared among all belonging ac97 instances.
+
+And then call :c:func:`snd_ac97_mixer()` with an :c:type:`struct
+snd_ac97_template <snd_ac97_template>` record together with
+the bus pointer created above.
+
+::
+
+ struct snd_ac97_template ac97;
+ int err;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ snd_ac97_mixer(bus, &ac97, &chip->ac97);
+
+where chip->ac97 is a pointer to a newly created ``ac97_t``
+instance. In this case, the chip pointer is set as the private data,
+so that the read/write callback functions can refer to this chip
+instance. This instance is not necessarily stored in the chip
+record. If you need to change the register values from the driver, or
+need the suspend/resume of ac97 codecs, keep this pointer to pass to
+the corresponding functions.
+
+AC97 Callbacks
+--------------
+
+The standard callbacks are ``read`` and ``write``. Obviously they
+correspond to the functions for read and write accesses to the
+hardware low-level codes.
+
+The ``read`` callback returns the register value specified in the
+argument.
+
+::
+
+ static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+ {
+ struct mychip *chip = ac97->private_data;
+ ....
+ return the_register_value;
+ }
+
+Here, the chip can be cast from ``ac97->private_data``.
+
+Meanwhile, the ``write`` callback is used to set the register
+value
+
+::
+
+ static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+
+
+These callbacks are non-atomic like the control API callbacks.
+
+There are also other callbacks: ``reset``, ``wait`` and ``init``.
+
+The ``reset`` callback is used to reset the codec. If the chip
+requires a special kind of reset, you can define this callback.
+
+The ``wait`` callback is used to add some waiting time in the standard
+initialization of the codec. If the chip requires the extra waiting
+time, define this callback.
+
+The ``init`` callback is used for additional initialization of the
+codec.
+
+Updating Registers in The Driver
+--------------------------------
+
+If you need to access to the codec from the driver, you can call the
+following functions: :c:func:`snd_ac97_write()`,
+:c:func:`snd_ac97_read()`, :c:func:`snd_ac97_update()` and
+:c:func:`snd_ac97_update_bits()`.
+
+Both :c:func:`snd_ac97_write()` and
+:c:func:`snd_ac97_update()` functions are used to set a value to
+the given register (``AC97_XXX``). The difference between them is that
+:c:func:`snd_ac97_update()` doesn't write a value if the given
+value has been already set, while :c:func:`snd_ac97_write()`
+always rewrites the value.
+
+::
+
+ snd_ac97_write(ac97, AC97_MASTER, 0x8080);
+ snd_ac97_update(ac97, AC97_MASTER, 0x8080);
+
+:c:func:`snd_ac97_read()` is used to read the value of the given
+register. For example,
+
+::
+
+ value = snd_ac97_read(ac97, AC97_MASTER);
+
+:c:func:`snd_ac97_update_bits()` is used to update some bits in
+the given register.
+
+::
+
+ snd_ac97_update_bits(ac97, reg, mask, value);
+
+Also, there is a function to change the sample rate (of a given register
+such as ``AC97_PCM_FRONT_DAC_RATE``) when VRA or DRA is supported by the
+codec: :c:func:`snd_ac97_set_rate()`.
+
+::
+
+ snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
+
+
+The following registers are available to set the rate:
+``AC97_PCM_MIC_ADC_RATE``, ``AC97_PCM_FRONT_DAC_RATE``,
+``AC97_PCM_LR_ADC_RATE``, ``AC97_SPDIF``. When ``AC97_SPDIF`` is
+specified, the register is not really changed but the corresponding
+IEC958 status bits will be updated.
+
+Clock Adjustment
+----------------
+
+In some chips, the clock of the codec isn't 48000 but using a PCI clock
+(to save a quartz!). In this case, change the field ``bus->clock`` to
+the corresponding value. For example, intel8x0 and es1968 drivers have
+their own function to read from the clock.
+
+Proc Files
+----------
+
+The ALSA AC97 interface will create a proc file such as
+``/proc/asound/card0/codec97#0/ac97#0-0`` and ``ac97#0-0+regs``. You
+can refer to these files to see the current status and registers of
+the codec.
+
+Multiple Codecs
+---------------
+
+When there are several codecs on the same card, you need to call
+:c:func:`snd_ac97_mixer()` multiple times with ``ac97.num=1`` or
+greater. The ``num`` field specifies the codec number.
+
+If you set up multiple codecs, you either need to write different
+callbacks for each codec or check ``ac97->num`` in the callback
+routines.
+
+MIDI (MPU401-UART) Interface
+============================
+
+General
+-------
+
+Many soundcards have built-in MIDI (MPU401-UART) interfaces. When the
+soundcard supports the standard MPU401-UART interface, most likely you
+can use the ALSA MPU401-UART API. The MPU401-UART API is defined in
+``<sound/mpu401.h>``.
+
+Some soundchips have a similar but slightly different implementation of
+mpu401 stuff. For example, emu10k1 has its own mpu401 routines.
+
+MIDI Constructor
+----------------
+
+To create a rawmidi object, call :c:func:`snd_mpu401_uart_new()`.
+
+::
+
+ struct snd_rawmidi *rmidi;
+ snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
+ irq, &rmidi);
+
+
+The first argument is the card pointer, and the second is the index of
+this component. You can create up to 8 rawmidi devices.
+
+The third argument is the type of the hardware, ``MPU401_HW_XXX``. If
+it's not a special one, you can use ``MPU401_HW_MPU401``.
+
+The 4th argument is the I/O port address. Many backward-compatible
+MPU401 have an I/O port such as 0x330. Or, it might be a part of its own
+PCI I/O region. It depends on the chip design.
+
+The 5th argument is a bitflag for additional information. When the I/O
+port address above is part of the PCI I/O region, the MPU401 I/O port
+might have been already allocated (reserved) by the driver itself. In
+such a case, pass a bit flag ``MPU401_INFO_INTEGRATED``, and the
+mpu401-uart layer will allocate the I/O ports by itself.
+
+When the controller supports only the input or output MIDI stream, pass
+the ``MPU401_INFO_INPUT`` or ``MPU401_INFO_OUTPUT`` bitflag,
+respectively. Then the rawmidi instance is created as a single stream.
+
+``MPU401_INFO_MMIO`` bitflag is used to change the access method to MMIO
+(via readb and writeb) instead of iob and outb. In this case, you have
+to pass the iomapped address to :c:func:`snd_mpu401_uart_new()`.
+
+When ``MPU401_INFO_TX_IRQ`` is set, the output stream isn't checked in
+the default interrupt handler. The driver needs to call
+:c:func:`snd_mpu401_uart_interrupt_tx()` by itself to start
+processing the output stream in the irq handler.
+
+If the MPU-401 interface shares its interrupt with the other logical
+devices on the card, set ``MPU401_INFO_IRQ_HOOK`` (see
+`below <#MIDI-Interrupt-Handler>`__).
+
+Usually, the port address corresponds to the command port and port + 1
+corresponds to the data port. If not, you may change the ``cport``
+field of :c:type:`struct snd_mpu401 <snd_mpu401>` manually afterward.
+However, :c:type:`struct snd_mpu401 <snd_mpu401>` pointer is
+not returned explicitly by :c:func:`snd_mpu401_uart_new()`. You
+need to cast ``rmidi->private_data`` to :c:type:`struct snd_mpu401
+<snd_mpu401>` explicitly,
+
+::
+
+ struct snd_mpu401 *mpu;
+ mpu = rmidi->private_data;
+
+and reset the ``cport`` as you like:
+
+::
+
+ mpu->cport = my_own_control_port;
+
+The 6th argument specifies the ISA irq number that will be allocated. If
+no interrupt is to be allocated (because your code is already allocating
+a shared interrupt, or because the device does not use interrupts), pass
+-1 instead. For a MPU-401 device without an interrupt, a polling timer
+will be used instead.
+
+MIDI Interrupt Handler
+----------------------
+
+When the interrupt is allocated in
+:c:func:`snd_mpu401_uart_new()`, an exclusive ISA interrupt
+handler is automatically used, hence you don't have anything else to do
+than creating the mpu401 stuff. Otherwise, you have to set
+``MPU401_INFO_IRQ_HOOK``, and call
+:c:func:`snd_mpu401_uart_interrupt()` explicitly from your own
+interrupt handler when it has determined that a UART interrupt has
+occurred.
+
+In this case, you need to pass the private_data of the returned rawmidi
+object from :c:func:`snd_mpu401_uart_new()` as the second
+argument of :c:func:`snd_mpu401_uart_interrupt()`.
+
+::
+
+ snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
+
+
+RawMIDI Interface
+=================
+
+Overview
+--------
+
+The raw MIDI interface is used for hardware MIDI ports that can be
+accessed as a byte stream. It is not used for synthesizer chips that do
+not directly understand MIDI.
+
+ALSA handles file and buffer management. All you have to do is to write
+some code to move data between the buffer and the hardware.
+
+The rawmidi API is defined in ``<sound/rawmidi.h>``.
+
+RawMIDI Constructor
+-------------------
+
+To create a rawmidi device, call the :c:func:`snd_rawmidi_new()`
+function:
+
+::
+
+ struct snd_rawmidi *rmidi;
+ err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
+ if (err < 0)
+ return err;
+ rmidi->private_data = chip;
+ strcpy(rmidi->name, "My MIDI");
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+
+The first argument is the card pointer, the second argument is the ID
+string.
+
+The third argument is the index of this component. You can create up to
+8 rawmidi devices.
+
+The fourth and fifth arguments are the number of output and input
+substreams, respectively, of this device (a substream is the equivalent
+of a MIDI port).
+
+Set the ``info_flags`` field to specify the capabilities of the
+device. Set ``SNDRV_RAWMIDI_INFO_OUTPUT`` if there is at least one
+output port, ``SNDRV_RAWMIDI_INFO_INPUT`` if there is at least one
+input port, and ``SNDRV_RAWMIDI_INFO_DUPLEX`` if the device can handle
+output and input at the same time.
+
+After the rawmidi device is created, you need to set the operators
+(callbacks) for each substream. There are helper functions to set the
+operators for all the substreams of a device:
+
+::
+
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
+
+The operators are usually defined like this:
+
+::
+
+ static struct snd_rawmidi_ops snd_mymidi_output_ops = {
+ .open = snd_mymidi_output_open,
+ .close = snd_mymidi_output_close,
+ .trigger = snd_mymidi_output_trigger,
+ };
+
+These callbacks are explained in the `RawMIDI Callbacks`_ section.
+
+If there are more than one substream, you should give a unique name to
+each of them:
+
+::
+
+ struct snd_rawmidi_substream *substream;
+ list_for_each_entry(substream,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+ list {
+ sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
+ }
+ /* same for SNDRV_RAWMIDI_STREAM_INPUT */
+
+RawMIDI Callbacks
+-----------------
+
+In all the callbacks, the private data that you've set for the rawmidi
+device can be accessed as ``substream->rmidi->private_data``.
+
+If there is more than one port, your callbacks can determine the port
+index from the struct snd_rawmidi_substream data passed to each
+callback:
+
+::
+
+ struct snd_rawmidi_substream *substream;
+ int index = substream->number;
+
+RawMIDI open callback
+~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_open(struct snd_rawmidi_substream *substream);
+
+
+This is called when a substream is opened. You can initialize the
+hardware here, but you shouldn't start transmitting/receiving data yet.
+
+RawMIDI close callback
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static int snd_xxx_close(struct snd_rawmidi_substream *substream);
+
+Guess what.
+
+The ``open`` and ``close`` callbacks of a rawmidi device are
+serialized with a mutex, and can sleep.
+
+Rawmidi trigger callback for output substreams
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
+
+
+This is called with a nonzero ``up`` parameter when there is some data
+in the substream buffer that must be transmitted.
+
+To read data from the buffer, call
+:c:func:`snd_rawmidi_transmit_peek()`. It will return the number
+of bytes that have been read; this will be less than the number of bytes
+requested when there are no more data in the buffer. After the data have
+been transmitted successfully, call
+:c:func:`snd_rawmidi_transmit_ack()` to remove the data from the
+substream buffer:
+
+::
+
+ unsigned char data;
+ while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
+ if (snd_mychip_try_to_transmit(data))
+ snd_rawmidi_transmit_ack(substream, 1);
+ else
+ break; /* hardware FIFO full */
+ }
+
+If you know beforehand that the hardware will accept data, you can use
+the :c:func:`snd_rawmidi_transmit()` function which reads some
+data and removes them from the buffer at once:
+
+::
+
+ while (snd_mychip_transmit_possible()) {
+ unsigned char data;
+ if (snd_rawmidi_transmit(substream, &data, 1) != 1)
+ break; /* no more data */
+ snd_mychip_transmit(data);
+ }
+
+If you know beforehand how many bytes you can accept, you can use a
+buffer size greater than one with the
+:c:func:`snd_rawmidi_transmit\*()` functions.
+
+The ``trigger`` callback must not sleep. If the hardware FIFO is full
+before the substream buffer has been emptied, you have to continue
+transmitting data later, either in an interrupt handler, or with a
+timer if the hardware doesn't have a MIDI transmit interrupt.
+
+The ``trigger`` callback is called with a zero ``up`` parameter when
+the transmission of data should be aborted.
+
+RawMIDI trigger callback for input substreams
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
+
+
+This is called with a nonzero ``up`` parameter to enable receiving data,
+or with a zero ``up`` parameter do disable receiving data.
+
+The ``trigger`` callback must not sleep; the actual reading of data
+from the device is usually done in an interrupt handler.
+
+When data reception is enabled, your interrupt handler should call
+:c:func:`snd_rawmidi_receive()` for all received data:
+
+::
+
+ void snd_mychip_midi_interrupt(...)
+ {
+ while (mychip_midi_available()) {
+ unsigned char data;
+ data = mychip_midi_read();
+ snd_rawmidi_receive(substream, &data, 1);
+ }
+ }
+
+
+drain callback
+~~~~~~~~~~~~~~
+
+::
+
+ static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
+
+
+This is only used with output substreams. This function should wait
+until all data read from the substream buffer have been transmitted.
+This ensures that the device can be closed and the driver unloaded
+without losing data.
+
+This callback is optional. If you do not set ``drain`` in the struct
+snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
+instead.
+
+Miscellaneous Devices
+=====================
+
+FM OPL3
+-------
+
+The FM OPL3 is still used in many chips (mainly for backward
+compatibility). ALSA has a nice OPL3 FM control layer, too. The OPL3 API
+is defined in ``<sound/opl3.h>``.
+
+FM registers can be directly accessed through the direct-FM API, defined
+in ``<sound/asound_fm.h>``. In ALSA native mode, FM registers are
+accessed through the Hardware-Dependent Device direct-FM extension API,
+whereas in OSS compatible mode, FM registers can be accessed with the
+OSS direct-FM compatible API in ``/dev/dmfmX`` device.
+
+To create the OPL3 component, you have two functions to call. The first
+one is a constructor for the ``opl3_t`` instance.
+
+::
+
+ struct snd_opl3 *opl3;
+ snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
+ integrated, &opl3);
+
+The first argument is the card pointer, the second one is the left port
+address, and the third is the right port address. In most cases, the
+right port is placed at the left port + 2.
+
+The fourth argument is the hardware type.
+
+When the left and right ports have been already allocated by the card
+driver, pass non-zero to the fifth argument (``integrated``). Otherwise,
+the opl3 module will allocate the specified ports by itself.
+
+When the accessing the hardware requires special method instead of the
+standard I/O access, you can create opl3 instance separately with
+:c:func:`snd_opl3_new()`.
+
+::
+
+ struct snd_opl3 *opl3;
+ snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
+
+Then set ``command``, ``private_data`` and ``private_free`` for the
+private access function, the private data and the destructor. The
+``l_port`` and ``r_port`` are not necessarily set. Only the command
+must be set properly. You can retrieve the data from the
+``opl3->private_data`` field.
+
+After creating the opl3 instance via :c:func:`snd_opl3_new()`,
+call :c:func:`snd_opl3_init()` to initialize the chip to the
+proper state. Note that :c:func:`snd_opl3_create()` always calls
+it internally.
+
+If the opl3 instance is created successfully, then create a hwdep device
+for this opl3.
+
+::
+
+ struct snd_hwdep *opl3hwdep;
+ snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
+
+The first argument is the ``opl3_t`` instance you created, and the
+second is the index number, usually 0.
+
+The third argument is the index-offset for the sequencer client assigned
+to the OPL3 port. When there is an MPU401-UART, give 1 for here (UART
+always takes 0).
+
+Hardware-Dependent Devices
+--------------------------
+
+Some chips need user-space access for special controls or for loading
+the micro code. In such a case, you can create a hwdep
+(hardware-dependent) device. The hwdep API is defined in
+``<sound/hwdep.h>``. You can find examples in opl3 driver or
+``isa/sb/sb16_csp.c``.
+
+The creation of the ``hwdep`` instance is done via
+:c:func:`snd_hwdep_new()`.
+
+::
+
+ struct snd_hwdep *hw;
+ snd_hwdep_new(card, "My HWDEP", 0, &hw);
+
+where the third argument is the index number.
+
+You can then pass any pointer value to the ``private_data``. If you
+assign a private data, you should define the destructor, too. The
+destructor function is set in the ``private_free`` field.
+
+::
+
+ struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ hw->private_data = p;
+ hw->private_free = mydata_free;
+
+and the implementation of the destructor would be:
+
+::
+
+ static void mydata_free(struct snd_hwdep *hw)
+ {
+ struct mydata *p = hw->private_data;
+ kfree(p);
+ }
+
+The arbitrary file operations can be defined for this instance. The file
+operators are defined in the ``ops`` table. For example, assume that
+this chip needs an ioctl.
+
+::
+
+ hw->ops.open = mydata_open;
+ hw->ops.ioctl = mydata_ioctl;
+ hw->ops.release = mydata_release;
+
+And implement the callback functions as you like.
+
+IEC958 (S/PDIF)
+---------------
+
+Usually the controls for IEC958 devices are implemented via the control
+interface. There is a macro to compose a name string for IEC958
+controls, :c:func:`SNDRV_CTL_NAME_IEC958()` defined in
+``<include/asound.h>``.
+
+There are some standard controls for IEC958 status bits. These controls
+use the type ``SNDRV_CTL_ELEM_TYPE_IEC958``, and the size of element is
+fixed as 4 bytes array (value.iec958.status[x]). For the ``info``
+callback, you don't specify the value field for this type (the count
+field must be set, though).
+
+“IEC958 Playback Con Mask†is used to return the bit-mask for the IEC958
+status bits of consumer mode. Similarly, “IEC958 Playback Pro Maskâ€
+returns the bitmask for professional mode. They are read-only controls,
+and are defined as MIXER controls (iface =
+``SNDRV_CTL_ELEM_IFACE_MIXER``).
+
+Meanwhile, “IEC958 Playback Default†control is defined for getting and
+setting the current default IEC958 bits. Note that this one is usually
+defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
+although in some places it's defined as a MIXER control.
+
+In addition, you can define the control switches to enable/disable or to
+set the raw bit mode. The implementation will depend on the chip, but
+the control should be named as “IEC958 xxxâ€, preferably using the
+:c:func:`SNDRV_CTL_NAME_IEC958()` macro.
+
+You can find several cases, for example, ``pci/emu10k1``,
+``pci/ice1712``, or ``pci/cmipci.c``.
+
+Buffer and Memory Management
+============================
+
+Buffer Types
+------------
+
+ALSA provides several different buffer allocation functions depending on
+the bus and the architecture. All these have a consistent API. The
+allocation of physically-contiguous pages is done via
+:c:func:`snd_malloc_xxx_pages()` function, where xxx is the bus
+type.
+
+The allocation of pages with fallback is
+:c:func:`snd_malloc_xxx_pages_fallback()`. This function tries
+to allocate the specified pages but if the pages are not available, it
+tries to reduce the page sizes until enough space is found.
+
+The release the pages, call :c:func:`snd_free_xxx_pages()`
+function.
+
+Usually, ALSA drivers try to allocate and reserve a large contiguous
+physical space at the time the module is loaded for the later use. This
+is called “pre-allocationâ€. As already written, you can call the
+following function at pcm instance construction time (in the case of PCI
+bus).
+
+::
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(pci), size, max);
+
+where ``size`` is the byte size to be pre-allocated and the ``max`` is
+the maximum size to be changed via the ``prealloc`` proc file. The
+allocator will try to get an area as large as possible within the
+given size.
+
+The second argument (type) and the third argument (device pointer) are
+dependent on the bus. In the case of the ISA bus, pass
+:c:func:`snd_dma_isa_data()` as the third argument with
+``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
+bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type and the
+``snd_dma_continuous_data(GFP_KERNEL)`` device pointer, where
+``GFP_KERNEL`` is the kernel allocation flag to use. For the PCI
+scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with
+``snd_dma_pci_data(pci)`` (see the `Non-Contiguous Buffers`_
+section).
+
+Once the buffer is pre-allocated, you can use the allocator in the
+``hw_params`` callback:
+
+::
+
+ snd_pcm_lib_malloc_pages(substream, size);
+
+Note that you have to pre-allocate to use this function.
+
+External Hardware Buffers
+-------------------------
+
+Some chips have their own hardware buffers and the DMA transfer from the
+host memory is not available. In such a case, you need to either 1)
+copy/set the audio data directly to the external hardware buffer, or 2)
+make an intermediate buffer and copy/set the data from it to the
+external hardware buffer in interrupts (or in tasklets, preferably).
+
+The first case works fine if the external hardware buffer is large
+enough. This method doesn't need any extra buffers and thus is more
+effective. You need to define the ``copy`` and ``silence`` callbacks
+for the data transfer. However, there is a drawback: it cannot be
+mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
+
+The second case allows for mmap on the buffer, although you have to
+handle an interrupt or a tasklet to transfer the data from the
+intermediate buffer to the hardware buffer. You can find an example in
+the vxpocket driver.
+
+Another case is when the chip uses a PCI memory-map region for the
+buffer instead of the host memory. In this case, mmap is available only
+on certain architectures like the Intel one. In non-mmap mode, the data
+cannot be transferred as in the normal way. Thus you need to define the
+``copy`` and ``silence`` callbacks as well, as in the cases above. The
+examples are found in ``rme32.c`` and ``rme96.c``.
+
+The implementation of the ``copy`` and ``silence`` callbacks depends
+upon whether the hardware supports interleaved or non-interleaved
+samples. The ``copy`` callback is defined like below, a bit
+differently depending whether the direction is playback or capture:
+
+::
+
+ static int playback_copy(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
+ static int capture_copy(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+
+In the case of interleaved samples, the second argument (``channel``) is
+not used. The third argument (``pos``) points the current position
+offset in frames.
+
+The meaning of the fourth argument is different between playback and
+capture. For playback, it holds the source data pointer, and for
+capture, it's the destination data pointer.
+
+The last argument is the number of frames to be copied.
+
+What you have to do in this callback is again different between playback
+and capture directions. In the playback case, you copy the given amount
+of data (``count``) at the specified pointer (``src``) to the specified
+offset (``pos``) on the hardware buffer. When coded like memcpy-like
+way, the copy would be like:
+
+::
+
+ my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
+ frames_to_bytes(runtime, count));
+
+For the capture direction, you copy the given amount of data (``count``)
+at the specified offset (``pos``) on the hardware buffer to the
+specified pointer (``dst``).
+
+::
+
+ my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
+ frames_to_bytes(runtime, count));
+
+Note that both the position and the amount of data are given in frames.
+
+In the case of non-interleaved samples, the implementation will be a bit
+more complicated.
+
+You need to check the channel argument, and if it's -1, copy the whole
+channels. Otherwise, you have to copy only the specified channel. Please
+check ``isa/gus/gus_pcm.c`` as an example.
+
+The ``silence`` callback is also implemented in a similar way
+
+::
+
+ static int silence(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+
+The meanings of arguments are the same as in the ``copy`` callback,
+although there is no ``src/dst`` argument. In the case of interleaved
+samples, the channel argument has no meaning, as well as on ``copy``
+callback.
+
+The role of ``silence`` callback is to set the given amount
+(``count``) of silence data at the specified offset (``pos``) on the
+hardware buffer. Suppose that the data format is signed (that is, the
+silent-data is 0), and the implementation using a memset-like function
+would be like:
+
+::
+
+ my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
+ frames_to_bytes(runtime, count));
+
+In the case of non-interleaved samples, again, the implementation
+becomes a bit more complicated. See, for example, ``isa/gus/gus_pcm.c``.
+
+Non-Contiguous Buffers
+----------------------
+
+If your hardware supports the page table as in emu10k1 or the buffer
+descriptors as in via82xx, you can use the scatter-gather (SG) DMA. ALSA
+provides an interface for handling SG-buffers. The API is provided in
+``<sound/pcm.h>``.
+
+For creating the SG-buffer handler, call
+:c:func:`snd_pcm_lib_preallocate_pages()` or
+:c:func:`snd_pcm_lib_preallocate_pages_for_all()` with
+``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI
+pre-allocator. You need to pass ``snd_dma_pci_data(pci)``, where pci is
+the :c:type:`struct pci_dev <pci_dev>` pointer of the chip as
+well. The ``struct snd_sg_buf`` instance is created as
+``substream->dma_private``. You can cast the pointer like:
+
+::
+
+ struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
+
+Then call :c:func:`snd_pcm_lib_malloc_pages()` in the ``hw_params``
+callback as well as in the case of normal PCI buffer. The SG-buffer
+handler will allocate the non-contiguous kernel pages of the given size
+and map them onto the virtually contiguous memory. The virtual pointer
+is addressed in runtime->dma_area. The physical address
+(``runtime->dma_addr``) is set to zero, because the buffer is
+physically non-contiguous. The physical address table is set up in
+``sgbuf->table``. You can get the physical address at a certain offset
+via :c:func:`snd_pcm_sgbuf_get_addr()`.
+
+When a SG-handler is used, you need to set
+:c:func:`snd_pcm_sgbuf_ops_page()` as the ``page`` callback. (See
+`page callback`_ section.)
+
+To release the data, call :c:func:`snd_pcm_lib_free_pages()` in
+the ``hw_free`` callback as usual.
+
+Vmalloc'ed Buffers
+------------------
+
+It's possible to use a buffer allocated via :c:func:`vmalloc()`, for
+example, for an intermediate buffer. Since the allocated pages are not
+contiguous, you need to set the ``page`` callback to obtain the physical
+address at every offset.
+
+The implementation of ``page`` callback would be like this:
+
+::
+
+ #include <linux/vmalloc.h>
+
+ /* get the physical page pointer on the given offset */
+ static struct page *mychip_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+ {
+ void *pageptr = substream->runtime->dma_area + offset;
+ return vmalloc_to_page(pageptr);
+ }
+
+Proc Interface
+==============
+
+ALSA provides an easy interface for procfs. The proc files are very
+useful for debugging. I recommend you set up proc files if you write a
+driver and want to get a running status or register dumps. The API is
+found in ``<sound/info.h>``.
+
+To create a proc file, call :c:func:`snd_card_proc_new()`.
+
+::
+
+ struct snd_info_entry *entry;
+ int err = snd_card_proc_new(card, "my-file", &entry);
+
+where the second argument specifies the name of the proc file to be
+created. The above example will create a file ``my-file`` under the
+card directory, e.g. ``/proc/asound/card0/my-file``.
+
+Like other components, the proc entry created via
+:c:func:`snd_card_proc_new()` will be registered and released
+automatically in the card registration and release functions.
+
+When the creation is successful, the function stores a new instance in
+the pointer given in the third argument. It is initialized as a text
+proc file for read only. To use this proc file as a read-only text file
+as it is, set the read callback with a private data via
+:c:func:`snd_info_set_text_ops()`.
+
+::
+
+ snd_info_set_text_ops(entry, chip, my_proc_read);
+
+where the second argument (``chip``) is the private data to be used in
+the callbacks. The third parameter specifies the read buffer size and
+the fourth (``my_proc_read``) is the callback function, which is
+defined like
+
+::
+
+ static void my_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer);
+
+In the read callback, use :c:func:`snd_iprintf()` for output
+strings, which works just like normal :c:func:`printf()`. For
+example,
+
+::
+
+ static void my_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct my_chip *chip = entry->private_data;
+
+ snd_iprintf(buffer, "This is my chip!\n");
+ snd_iprintf(buffer, "Port = %ld\n", chip->port);
+ }
+
+The file permissions can be changed afterwards. As default, it's set as
+read only for all users. If you want to add write permission for the
+user (root as default), do as follows:
+
+::
+
+ entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
+
+and set the write buffer size and the callback
+
+::
+
+ entry->c.text.write = my_proc_write;
+
+For the write callback, you can use :c:func:`snd_info_get_line()`
+to get a text line, and :c:func:`snd_info_get_str()` to retrieve
+a string from the line. Some examples are found in
+``core/oss/mixer_oss.c``, core/oss/and ``pcm_oss.c``.
+
+For a raw-data proc-file, set the attributes as follows:
+
+::
+
+ static struct snd_info_entry_ops my_file_io_ops = {
+ .read = my_file_io_read,
+ };
+
+ entry->content = SNDRV_INFO_CONTENT_DATA;
+ entry->private_data = chip;
+ entry->c.ops = &my_file_io_ops;
+ entry->size = 4096;
+ entry->mode = S_IFREG | S_IRUGO;
+
+For the raw data, ``size`` field must be set properly. This specifies
+the maximum size of the proc file access.
+
+The read/write callbacks of raw mode are more direct than the text mode.
+You need to use a low-level I/O functions such as
+:c:func:`copy_from/to_user()` to transfer the data.
+
+::
+
+ static ssize_t my_file_io_read(struct snd_info_entry *entry,
+ void *file_private_data,
+ struct file *file,
+ char *buf,
+ size_t count,
+ loff_t pos)
+ {
+ if (copy_to_user(buf, local_data + pos, count))
+ return -EFAULT;
+ return count;
+ }
+
+If the size of the info entry has been set up properly, ``count`` and
+``pos`` are guaranteed to fit within 0 and the given size. You don't
+have to check the range in the callbacks unless any other condition is
+required.
+
+Power Management
+================
+
+If the chip is supposed to work with suspend/resume functions, you need
+to add power-management code to the driver. The additional code for
+power-management should be ifdef-ed with ``CONFIG_PM``.
+
+If the driver *fully* supports suspend/resume that is, the device can be
+properly resumed to its state when suspend was called, you can set the
+``SNDRV_PCM_INFO_RESUME`` flag in the pcm info field. Usually, this is
+possible when the registers of the chip can be safely saved and restored
+to RAM. If this is set, the trigger callback is called with
+``SNDRV_PCM_TRIGGER_RESUME`` after the resume callback completes.
+
+Even if the driver doesn't support PM fully but partial suspend/resume
+is still possible, it's still worthy to implement suspend/resume
+callbacks. In such a case, applications would reset the status by
+calling :c:func:`snd_pcm_prepare()` and restart the stream
+appropriately. Hence, you can define suspend/resume callbacks below but
+don't set ``SNDRV_PCM_INFO_RESUME`` info flag to the PCM.
+
+Note that the trigger with SUSPEND can always be called when
+:c:func:`snd_pcm_suspend_all()` is called, regardless of the
+``SNDRV_PCM_INFO_RESUME`` flag. The ``RESUME`` flag affects only the
+behavior of :c:func:`snd_pcm_resume()`. (Thus, in theory,
+``SNDRV_PCM_TRIGGER_RESUME`` isn't needed to be handled in the trigger
+callback when no ``SNDRV_PCM_INFO_RESUME`` flag is set. But, it's better
+to keep it for compatibility reasons.)
+
+In the earlier version of ALSA drivers, a common power-management layer
+was provided, but it has been removed. The driver needs to define the
+suspend/resume hooks according to the bus the device is connected to. In
+the case of PCI drivers, the callbacks look like below:
+
+::
+
+ #ifdef CONFIG_PM
+ static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
+ {
+ .... /* do things for suspend */
+ return 0;
+ }
+ static int snd_my_resume(struct pci_dev *pci)
+ {
+ .... /* do things for suspend */
+ return 0;
+ }
+ #endif
+
+The scheme of the real suspend job is as follows.
+
+1. Retrieve the card and the chip data.
+
+2. Call :c:func:`snd_power_change_state()` with
+ ``SNDRV_CTL_POWER_D3hot`` to change the power status.
+
+3. Call :c:func:`snd_pcm_suspend_all()` to suspend the running
+ PCM streams.
+
+4. If AC97 codecs are used, call :c:func:`snd_ac97_suspend()` for
+ each codec.
+
+5. Save the register values if necessary.
+
+6. Stop the hardware if necessary.
+
+7. Disable the PCI device by calling
+ :c:func:`pci_disable_device()`. Then, call
+ :c:func:`pci_save_state()` at last.
+
+A typical code would be like:
+
+::
+
+ static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
+ {
+ /* (1) */
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
+ /* (2) */
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ /* (3) */
+ snd_pcm_suspend_all(chip->pcm);
+ /* (4) */
+ snd_ac97_suspend(chip->ac97);
+ /* (5) */
+ snd_mychip_save_registers(chip);
+ /* (6) */
+ snd_mychip_stop_hardware(chip);
+ /* (7) */
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+ }
+
+
+The scheme of the real resume job is as follows.
+
+1. Retrieve the card and the chip data.
+
+2. Set up PCI. First, call :c:func:`pci_restore_state()`. Then
+ enable the pci device again by calling
+ :c:func:`pci_enable_device()`. Call
+ :c:func:`pci_set_master()` if necessary, too.
+
+3. Re-initialize the chip.
+
+4. Restore the saved registers if necessary.
+
+5. Resume the mixer, e.g. calling :c:func:`snd_ac97_resume()`.
+
+6. Restart the hardware (if any).
+
+7. Call :c:func:`snd_power_change_state()` with
+ ``SNDRV_CTL_POWER_D0`` to notify the processes.
+
+A typical code would be like:
+
+::
+
+ static int mychip_resume(struct pci_dev *pci)
+ {
+ /* (1) */
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
+ /* (2) */
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
+ /* (3) */
+ snd_mychip_reinit_chip(chip);
+ /* (4) */
+ snd_mychip_restore_registers(chip);
+ /* (5) */
+ snd_ac97_resume(chip->ac97);
+ /* (6) */
+ snd_mychip_restart_chip(chip);
+ /* (7) */
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+ }
+
+As shown in the above, it's better to save registers after suspending
+the PCM operations via :c:func:`snd_pcm_suspend_all()` or
+:c:func:`snd_pcm_suspend()`. It means that the PCM streams are
+already stopped when the register snapshot is taken. But, remember that
+you don't have to restart the PCM stream in the resume callback. It'll
+be restarted via trigger call with ``SNDRV_PCM_TRIGGER_RESUME`` when
+necessary.
+
+OK, we have all callbacks now. Let's set them up. In the initialization
+of the card, make sure that you can get the chip data from the card
+instance, typically via ``private_data`` field, in case you created the
+chip data individually.
+
+::
+
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+ {
+ ....
+ struct snd_card *card;
+ struct mychip *chip;
+ int err;
+ ....
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
+ ....
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ ....
+ card->private_data = chip;
+ ....
+ }
+
+When you created the chip data with :c:func:`snd_card_new()`, it's
+anyway accessible via ``private_data`` field.
+
+::
+
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+ {
+ ....
+ struct snd_card *card;
+ struct mychip *chip;
+ int err;
+ ....
+ err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct mychip), &card);
+ ....
+ chip = card->private_data;
+ ....
+ }
+
+If you need a space to save the registers, allocate the buffer for it
+here, too, since it would be fatal if you cannot allocate a memory in
+the suspend phase. The allocated buffer should be released in the
+corresponding destructor.
+
+And next, set suspend/resume callbacks to the pci_driver.
+
+::
+
+ static struct pci_driver driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_my_ids,
+ .probe = snd_my_probe,
+ .remove = snd_my_remove,
+ #ifdef CONFIG_PM
+ .suspend = snd_my_suspend,
+ .resume = snd_my_resume,
+ #endif
+ };
+
+Module Parameters
+=================
+
+There are standard module options for ALSA. At least, each module should
+have the ``index``, ``id`` and ``enable`` options.
+
+If the module supports multiple cards (usually up to 8 = ``SNDRV_CARDS``
+cards), they should be arrays. The default initial values are defined
+already as constants for easier programming:
+
+::
+
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+If the module supports only a single card, they could be single
+variables, instead. ``enable`` option is not always necessary in this
+case, but it would be better to have a dummy option for compatibility.
+
+The module parameters must be declared with the standard
+``module_param()()``, ``module_param_array()()`` and
+:c:func:`MODULE_PARM_DESC()` macros.
+
+The typical coding would be like below:
+
+::
+
+ #define CARD_NAME "My Chip"
+
+ module_param_array(index, int, NULL, 0444);
+ MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
+ module_param_array(id, charp, NULL, 0444);
+ MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
+ module_param_array(enable, bool, NULL, 0444);
+ MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
+
+Also, don't forget to define the module description, classes, license
+and devices. Especially, the recent modprobe requires to define the
+module license as GPL, etc., otherwise the system is shown as “taintedâ€.
+
+::
+
+ MODULE_DESCRIPTION("My Chip");
+ MODULE_LICENSE("GPL");
+ MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
+
+
+How To Put Your Driver Into ALSA Tree
+=====================================
+
+General
+-------
+
+So far, you've learned how to write the driver codes. And you might have
+a question now: how to put my own driver into the ALSA driver tree? Here
+(finally :) the standard procedure is described briefly.
+
+Suppose that you create a new PCI driver for the card “xyzâ€. The card
+module name would be snd-xyz. The new driver is usually put into the
+alsa-driver tree, ``alsa-driver/pci`` directory in the case of PCI
+cards. Then the driver is evaluated, audited and tested by developers
+and users. After a certain time, the driver will go to the alsa-kernel
+tree (to the corresponding directory, such as ``alsa-kernel/pci``) and
+eventually will be integrated into the Linux 2.6 tree (the directory
+would be ``linux/sound/pci``).
+
+In the following sections, the driver code is supposed to be put into
+alsa-driver tree. The two cases are covered: a driver consisting of a
+single source file and one consisting of several source files.
+
+Driver with A Single Source File
+--------------------------------
+
+1. Modify alsa-driver/pci/Makefile
+
+ Suppose you have a file xyz.c. Add the following two lines
+
+::
+
+ snd-xyz-objs := xyz.o
+ obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+2. Create the Kconfig entry
+
+ Add the new entry of Kconfig for your xyz driver. config SND_XYZ
+ tristate "Foobar XYZ" depends on SND select SND_PCM help Say Y here
+ to include support for Foobar XYZ soundcard. To compile this driver
+ as a module, choose M here: the module will be called snd-xyz. the
+ line, select SND_PCM, specifies that the driver xyz supports PCM. In
+ addition to SND_PCM, the following components are supported for
+ select command: SND_RAWMIDI, SND_TIMER, SND_HWDEP,
+ SND_MPU401_UART, SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB,
+ SND_AC97_CODEC. Add the select command for each supported
+ component.
+
+ Note that some selections imply the lowlevel selections. For example,
+ PCM includes TIMER, MPU401_UART includes RAWMIDI, AC97_CODEC
+ includes PCM, and OPL3_LIB includes HWDEP. You don't need to give
+ the lowlevel selections again.
+
+ For the details of Kconfig script, refer to the kbuild documentation.
+
+3. Run cvscompile script to re-generate the configure script and build
+ the whole stuff again.
+
+Drivers with Several Source Files
+---------------------------------
+
+Suppose that the driver snd-xyz have several source files. They are
+located in the new subdirectory, pci/xyz.
+
+1. Add a new directory (``xyz``) in ``alsa-driver/pci/Makefile`` as
+ below
+
+::
+
+ obj-$(CONFIG_SND) += xyz/
+
+
+2. Under the directory ``xyz``, create a Makefile
+
+::
+
+ ifndef SND_TOPDIR
+ SND_TOPDIR=../..
+ endif
+
+ include $(SND_TOPDIR)/toplevel.config
+ include $(SND_TOPDIR)/Makefile.conf
+
+ snd-xyz-objs := xyz.o abc.o def.o
+
+ obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+ include $(SND_TOPDIR)/Rules.make
+
+3. Create the Kconfig entry
+
+ This procedure is as same as in the last section.
+
+4. Run cvscompile script to re-generate the configure script and build
+ the whole stuff again.
+
+Useful Functions
+================
+
+:c:func:`snd_printk()` and friends
+---------------------------------------
+
+ALSA provides a verbose version of the :c:func:`printk()` function.
+If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function
+prints the given message together with the file name and the line of the
+caller. The ``KERN_XXX`` prefix is processed as well as the original
+:c:func:`printk()` does, so it's recommended to add this prefix,
+e.g. snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\\n");
+
+There are also :c:func:`printk()`'s for debugging.
+:c:func:`snd_printd()` can be used for general debugging purposes.
+If ``CONFIG_SND_DEBUG`` is set, this function is compiled, and works
+just like :c:func:`snd_printk()`. If the ALSA is compiled without
+the debugging flag, it's ignored.
+
+:c:func:`snd_printdd()` is compiled in only when
+``CONFIG_SND_DEBUG_VERBOSE`` is set. Please note that
+``CONFIG_SND_DEBUG_VERBOSE`` is not set as default even if you configure
+the alsa-driver with ``--with-debug=full`` option. You need to give
+explicitly ``--with-debug=detect`` option instead.
+
+:c:func:`snd_BUG()`
+------------------------
+
+It shows the ``BUG?`` message and stack trace as well as
+:c:func:`snd_BUG_ON()` at the point. It's useful to show that a
+fatal error happens there.
+
+When no debug flag is set, this macro is ignored.
+
+:c:func:`snd_BUG_ON()`
+----------------------------
+
+:c:func:`snd_BUG_ON()` macro is similar with
+:c:func:`WARN_ON()` macro. For example, snd_BUG_ON(!pointer); or
+it can be used as the condition, if (snd_BUG_ON(non_zero_is_bug))
+return -EINVAL;
+
+The macro takes an conditional expression to evaluate. When
+``CONFIG_SND_DEBUG``, is set, if the expression is non-zero, it shows
+the warning message such as ``BUG? (xxx)`` normally followed by stack
+trace. In both cases it returns the evaluated value.
+
+Acknowledgments
+===============
+
+I would like to thank Phil Kerr for his help for improvement and
+corrections of this document.
+
+Kevin Conder reformatted the original plain-text to the DocBook format.
+
+Giuliano Pochini corrected typos and contributed the example codes in
+the hardware constraints section.
diff --git a/Documentation/sound/oss/oss-parameters.txt b/Documentation/sound/oss/oss-parameters.txt
index 3ab391e7c295..cc675f25eee4 100644
--- a/Documentation/sound/oss/oss-parameters.txt
+++ b/Documentation/sound/oss/oss-parameters.txt
@@ -1,7 +1,7 @@
OSS Kernel Parameters
~~~~~~~~~~~~~~~~~~~~~
-See Documentation/kernel-parameters.txt for general information on
+See Documentation/admin-guide/kernel-parameters.rst for general information on
specifying module parameters.
This document may not be entirely up to date and comprehensive. The command
diff --git a/Documentation/sound/alsa/soc/clocking.txt b/Documentation/sound/soc/clocking.rst
index b1300162e01c..32122d6877a3 100644
--- a/Documentation/sound/alsa/soc/clocking.txt
+++ b/Documentation/sound/soc/clocking.rst
@@ -1,3 +1,4 @@
+==============
Audio Clocking
==============
@@ -30,15 +31,9 @@ runs at exactly the sample rate (LRC = Rate).
Bit Clock can be generated as follows:-
-BCLK = MCLK / x
-
- or
-
-BCLK = LRC * x
-
- or
-
-BCLK = LRC * Channels * Word Size
+- BCLK = MCLK / x, or
+- BCLK = LRC * x, or
+- BCLK = LRC * Channels * Word Size
This relationship depends on the codec or SoC CPU in particular. In general
it is best to configure BCLK to the lowest possible speed (depending on your
diff --git a/Documentation/sound/soc/codec-to-codec.rst b/Documentation/sound/soc/codec-to-codec.rst
new file mode 100644
index 000000000000..810109d7500d
--- /dev/null
+++ b/Documentation/sound/soc/codec-to-codec.rst
@@ -0,0 +1,108 @@
+==============================================
+Creating codec to codec dai link for ALSA dapm
+==============================================
+
+Mostly the flow of audio is always from CPU to codec so your system
+will look as below:
+::
+
+ --------- ---------
+ | | dai | |
+ CPU -------> codec
+ | | | |
+ --------- ---------
+
+In case your system looks as below:
+::
+
+ ---------
+ | |
+ codec-2
+ | |
+ ---------
+ |
+ dai-2
+ |
+ ---------- ---------
+ | | dai-1 | |
+ CPU -------> codec-1
+ | | | |
+ ---------- ---------
+ |
+ dai-3
+ |
+ ---------
+ | |
+ codec-3
+ | |
+ ---------
+
+Suppose codec-2 is a bluetooth chip and codec-3 is connected to
+a speaker and you have a below scenario:
+codec-2 will receive the audio data and the user wants to play that
+audio through codec-3 without involving the CPU.This
+aforementioned case is the ideal case when codec to codec
+connection should be used.
+
+Your dai_link should appear as below in your machine
+file:
+::
+
+ /*
+ * this pcm stream only supports 24 bit, 2 channel and
+ * 48k sampling rate.
+ */
+ static const struct snd_soc_pcm_stream dsp_codec_params = {
+ .formats = SNDRV_PCM_FMTBIT_S24_LE,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ };
+
+ {
+ .name = "CPU-DSP",
+ .stream_name = "CPU-DSP",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_name = "codec-2,
+ .codec_dai_name = "codec-2-dai_name",
+ .platform_name = "samsung-i2s.0",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ignore_suspend = 1,
+ .params = &dsp_codec_params,
+ },
+ {
+ .name = "DSP-CODEC",
+ .stream_name = "DSP-CODEC",
+ .cpu_dai_name = "wm0010-sdi2",
+ .codec_name = "codec-3,
+ .codec_dai_name = "codec-3-dai_name",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ignore_suspend = 1,
+ .params = &dsp_codec_params,
+ },
+
+Above code snippet is motivated from sound/soc/samsung/speyside.c.
+
+Note the "params" callback which lets the dapm know that this
+dai_link is a codec to codec connection.
+
+In dapm core a route is created between cpu_dai playback widget
+and codec_dai capture widget for playback path and vice-versa is
+true for capture path. In order for this aforementioned route to get
+triggered, DAPM needs to find a valid endpoint which could be either
+a sink or source widget corresponding to playback and capture path
+respectively.
+
+In order to trigger this dai_link widget, a thin codec driver for
+the speaker amp can be created as demonstrated in wm8727.c file, it
+sets appropriate constraints for the device even if it needs no control.
+
+Make sure to name your corresponding cpu and codec playback and capture
+dai names ending with "Playback" and "Capture" respectively as dapm core
+will link and power those dais based on the name.
+
+Note that in current device tree there is no way to mark a dai_link
+as codec to codec. However, it may change in future.
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/soc/codec.rst
index db5f9c9ae149..f87612b94812 100644
--- a/Documentation/sound/alsa/soc/codec.txt
+++ b/Documentation/sound/soc/codec.rst
@@ -1,3 +1,4 @@
+=======================
ASoC Codec Class Driver
=======================
@@ -9,16 +10,16 @@ machine drivers respectively.
Each codec class driver *must* provide the following features:-
- 1) Codec DAI and PCM configuration
- 2) Codec control IO - using RegMap API
- 3) Mixers and audio controls
- 4) Codec audio operations
- 5) DAPM description.
- 6) DAPM event handler.
+1. Codec DAI and PCM configuration
+2. Codec control IO - using RegMap API
+3. Mixers and audio controls
+4. Codec audio operations
+5. DAPM description.
+6. DAPM event handler.
Optionally, codec drivers can also provide:-
- 7) DAC Digital mute control.
+7. DAC Digital mute control.
Its probably best to use this guide in conjunction with the existing codec
driver code in sound/soc/codecs/
@@ -26,24 +27,25 @@ driver code in sound/soc/codecs/
ASoC Codec driver breakdown
===========================
-1 - Codec DAI and PCM configuration
------------------------------------
+Codec DAI and PCM configuration
+-------------------------------
Each codec driver must have a struct snd_soc_dai_driver to define its DAI and
PCM capabilities and operations. This struct is exported so that it can be
registered with the core by your machine driver.
e.g.
+::
-static struct snd_soc_dai_ops wm8731_dai_ops = {
+ static struct snd_soc_dai_ops wm8731_dai_ops = {
.prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,
-};
-
-struct snd_soc_dai_driver wm8731_dai = {
+ };
+
+ struct snd_soc_dai_driver wm8731_dai = {
.name = "wm8731-hifi",
.playback = {
.stream_name = "Playback",
@@ -59,25 +61,27 @@ struct snd_soc_dai_driver wm8731_dai = {
.formats = WM8731_FORMATS,},
.ops = &wm8731_dai_ops,
.symmetric_rates = 1,
-};
+ };
-2 - Codec control IO
---------------------
+Codec control IO
+----------------
The codec can usually be controlled via an I2C or SPI style interface
(AC97 combines control with data in the DAI). The codec driver should use the
Regmap API for all codec IO. Please see include/linux/regmap.h and existing
codec drivers for example regmap usage.
-3 - Mixers and audio controls
------------------------------
+Mixers and audio controls
+-------------------------
All the codec mixers and audio controls can be defined using the convenience
macros defined in soc.h.
+::
#define SOC_SINGLE(xname, reg, shift, mask, invert)
Defines a single control as follows:-
+::
xname = Control name e.g. "Playback Volume"
reg = codec register
@@ -86,18 +90,22 @@ Defines a single control as follows:-
invert = the control is inverted
Other macros include:-
+::
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
A stereo control
+::
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
A stereo control spanning 2 registers
+::
#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
Defines an single enumerated control as follows:-
+::
xreg = register
xshift = control bit(s) offset in register
@@ -109,25 +117,26 @@ Defines an single enumerated control as follows:-
Defines a stereo enumerated control
-4 - Codec Audio Operations
---------------------------
+Codec Audio Operations
+----------------------
The codec driver also supports the following ALSA PCM operations:-
+::
-/* SoC audio ops */
-struct snd_soc_ops {
+ /* SoC audio ops */
+ struct snd_soc_ops {
int (*startup)(struct snd_pcm_substream *);
void (*shutdown)(struct snd_pcm_substream *);
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
int (*hw_free)(struct snd_pcm_substream *);
int (*prepare)(struct snd_pcm_substream *);
-};
+ };
Please refer to the ALSA driver PCM documentation for details.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
-5 - DAPM description.
----------------------
+DAPM description
+----------------
The Dynamic Audio Power Management description describes the codec power
components and their relationships and registers to the ASoC core.
Please read dapm.txt for details of building the description.
@@ -135,13 +144,14 @@ Please read dapm.txt for details of building the description.
Please also see the examples in other codec drivers.
-6 - DAPM event handler
-----------------------
+DAPM event handler
+------------------
This function is a callback that handles codec domain PM calls and system
domain PM calls (e.g. suspend and resume). It is used to put the codec
to sleep when not in use.
Power states:-
+::
SNDRV_CTL_POWER_D0: /* full On */
/* vref/mid, clk and osc on, active */
@@ -155,8 +165,8 @@ Power states:-
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
-7 - Codec DAC digital mute control
-----------------------------------
+Codec DAC digital mute control
+------------------------------
Most codecs have a digital mute before the DACs that can be used to
minimise any system noise. The mute stops any digital data from
entering the DAC.
@@ -165,9 +175,10 @@ A callback can be created that is called by the core for each codec DAI
when the mute is applied or freed.
i.e.
+::
-static int wm8974_mute(struct snd_soc_dai *dai, int mute)
-{
+ static int wm8974_mute(struct snd_soc_dai *dai, int mute)
+ {
struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
@@ -176,4 +187,4 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute)
else
snd_soc_write(codec, WM8974_DAC, mute_reg);
return 0;
-}
+ }
diff --git a/Documentation/sound/alsa/soc/DAI.txt b/Documentation/sound/soc/dai.rst
index c9679264c559..55820e51708f 100644
--- a/Documentation/sound/alsa/soc/DAI.txt
+++ b/Documentation/sound/soc/dai.rst
@@ -1,3 +1,7 @@
+==================================
+ASoC Digital Audio Interface (DAI)
+==================================
+
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
@@ -5,21 +9,21 @@ SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
AC97
====
- AC97 is a five wire interface commonly found on many PC sound cards. It is
+AC97 is a five wire interface commonly found on many PC sound cards. It is
now also popular in many portable devices. This DAI has a reset line and time
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
frame is 21uS long and is divided into 13 time slots.
-The AC97 specification can be found at :-
+The AC97 specification can be found at :
http://www.intel.com/p/en_US/business/design
I2S
===
- I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
+I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
Rx lines are used for audio transmission, whilst the bit clock (BCLK) and
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
@@ -30,13 +34,15 @@ different sample rates.
I2S has several different operating modes:-
- o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
- transition.
+I2S
+ MSB is transmitted on the falling edge of the first BCLK after LRC
+ transition.
- o Left Justified - MSB is transmitted on transition of LRC.
+Left Justified
+ MSB is transmitted on transition of LRC.
- o Right Justified - MSB is transmitted sample size BCLKs before LRC
- transition.
+Right Justified
+ MSB is transmitted sample size BCLKs before LRC transition.
PCM
===
@@ -51,6 +57,8 @@ is sometimes referred to as network mode).
Common PCM operating modes:-
- o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
+Mode A
+ MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
- o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
+Mode B
+ MSB is transmitted on rising edge of FRAME/SYNC.
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/soc/dapm.rst
index c45bd79f291e..a27f42befa4d 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/soc/dapm.rst
@@ -1,8 +1,9 @@
+===================================================
Dynamic Audio Power Management for Portable Devices
===================================================
-1. Description
-==============
+Description
+===========
Dynamic Audio Power Management (DAPM) is designed to allow portable
Linux devices to use the minimum amount of power within the audio
@@ -21,20 +22,28 @@ level power systems.
There are 4 power domains within DAPM
- 1. Codec bias domain - VREF, VMID (core codec and audio power)
+Codec bias domain
+ VREF, VMID (core codec and audio power)
+
Usually controlled at codec probe/remove and suspend/resume, although
can be set at stream time if power is not needed for sidetone, etc.
- 2. Platform/Machine domain - physically connected inputs and outputs
+Platform/Machine domain
+ physically connected inputs and outputs
+
Is platform/machine and user action specific, is configured by the
machine driver and responds to asynchronous events e.g when HP
are inserted
- 3. Path domain - audio subsystem signal paths
+Path domain
+ audio subsystem signal paths
+
Automatically set when mixer and mux settings are changed by the user.
e.g. alsamixer, amixer.
- 4. Stream domain - DACs and ADCs.
+Stream domain
+ DACs and ADCs.
+
Enabled and disabled when stream playback/capture is started and
stopped respectively. e.g. aplay, arecord.
@@ -45,34 +54,57 @@ internal codec components). All audio components that effect power are called
widgets hereafter.
-2. DAPM Widgets
-===============
+DAPM Widgets
+============
Audio DAPM widgets fall into a number of types:-
- o Mixer - Mixes several analog signals into a single analog signal.
- o Mux - An analog switch that outputs only one of many inputs.
- o PGA - A programmable gain amplifier or attenuation widget.
- o ADC - Analog to Digital Converter
- o DAC - Digital to Analog Converter
- o Switch - An analog switch
- o Input - A codec input pin
- o Output - A codec output pin
- o Headphone - Headphone (and optional Jack)
- o Mic - Mic (and optional Jack)
- o Line - Line Input/Output (and optional Jack)
- o Speaker - Speaker
- o Supply - Power or clock supply widget used by other widgets.
- o Regulator - External regulator that supplies power to audio components.
- o Clock - External clock that supplies clock to audio components.
- o AIF IN - Audio Interface Input (with TDM slot mask).
- o AIF OUT - Audio Interface Output (with TDM slot mask).
- o Siggen - Signal Generator.
- o DAI IN - Digital Audio Interface Input.
- o DAI OUT - Digital Audio Interface Output.
- o DAI Link - DAI Link between two DAI structures */
- o Pre - Special PRE widget (exec before all others)
- o Post - Special POST widget (exec after all others)
+Mixer
+ Mixes several analog signals into a single analog signal.
+Mux
+ An analog switch that outputs only one of many inputs.
+PGA
+ A programmable gain amplifier or attenuation widget.
+ADC
+ Analog to Digital Converter
+DAC
+ Digital to Analog Converter
+Switch
+ An analog switch
+Input
+ A codec input pin
+Output
+ A codec output pin
+Headphone
+ Headphone (and optional Jack)
+Mic
+ Mic (and optional Jack)
+Line
+ Line Input/Output (and optional Jack)
+Speaker
+ Speaker
+Supply
+ Power or clock supply widget used by other widgets.
+Regulator
+ External regulator that supplies power to audio components.
+Clock
+ External clock that supplies clock to audio components.
+AIF IN
+ Audio Interface Input (with TDM slot mask).
+AIF OUT
+ Audio Interface Output (with TDM slot mask).
+Siggen
+ Signal Generator.
+DAI IN
+ Digital Audio Interface Input.
+DAI OUT
+ Digital Audio Interface Output.
+DAI Link
+ DAI Link between two DAI structures
+Pre
+ Special PRE widget (exec before all others)
+Post
+ Special POST widget (exec after all others)
(Widgets are defined in include/sound/soc-dapm.h)
@@ -84,52 +116,57 @@ Most widgets have a name, register, shift and invert. Some widgets have extra
parameters for stream name and kcontrols.
-2.1 Stream Domain Widgets
--------------------------
+Stream Domain Widgets
+---------------------
Stream Widgets relate to the stream power domain and only consist of ADCs
(analog to digital converters), DACs (digital to analog converters),
AIF IN and AIF OUT.
Stream widgets have the following format:-
+::
-SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
-SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
+ SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
+ SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
NOTE: the stream name must match the corresponding stream name in your codec
snd_soc_codec_dai.
e.g. stream widgets for HiFi playback and capture
+::
-SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
-SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
+ SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
+ SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
e.g. stream widgets for AIF
+::
-SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-2.2 Path Domain Widgets
------------------------
+Path Domain Widgets
+-------------------
Path domain widgets have a ability to control or affect the audio signal or
audio paths within the audio subsystem. They have the following form:-
+::
-SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
+ SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
Any widget kcontrols can be set using the controls and num_controls members.
e.g. Mixer widget (the kcontrols are declared first)
+::
-/* Output Mixer */
-static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
-SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
-SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
-SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
-};
+ /* Output Mixer */
+ static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
+ SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
+ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
+ };
-SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
+ SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
ARRAY_SIZE(wm8731_output_mixer_controls)),
If you don't want the mixer elements prefixed with the name of the mixer widget,
@@ -137,48 +174,49 @@ you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
as for SND_SOC_DAPM_MIXER.
-2.3 Machine domain Widgets
---------------------------
+Machine domain Widgets
+----------------------
Machine widgets are different from codec widgets in that they don't have a
codec register bit associated with them. A machine widget is assigned to each
machine audio component (non codec or DSP) that can be independently
powered. e.g.
- o Speaker Amp
- o Microphone Bias
- o Jack connectors
+* Speaker Amp
+* Microphone Bias
+* Jack connectors
A machine widget can have an optional call back.
e.g. Jack connector widget for an external Mic that enables Mic Bias
-when the Mic is inserted:-
+when the Mic is inserted:-::
-static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
-{
+ static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
+ {
gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
return 0;
-}
+ }
-SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
+ SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
-2.4 Codec (BIAS) Domain
------------------------
+Codec (BIAS) Domain
+-------------------
The codec bias power domain has no widgets and is handled by the codecs DAPM
event handler. This handler is called when the codec powerstate is changed wrt
to any stream event or by kernel PM events.
-2.5 Virtual Widgets
--------------------
+Virtual Widgets
+---------------
Sometimes widgets exist in the codec or machine audio map that don't have any
corresponding soft power control. In this case it is necessary to create
a virtual widget - a widget with no control bits e.g.
+::
-SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
This can be used to merge to signal paths together in software.
@@ -186,8 +224,8 @@ After all the widgets have been defined, they can then be added to the DAPM
subsystem individually with a call to snd_soc_dapm_new_control().
-3. Codec/DSP Widget Interconnections
-====================================
+Codec/DSP Widget Interconnections
+=================================
Widgets are connected to each other within the codec, platform and machine by
audio paths (called interconnections). Each interconnection must be defined in
@@ -201,13 +239,14 @@ e.g., from the WM8731 output mixer (wm8731.c)
The WM8731 output mixer has 3 inputs (sources)
- 1. Line Bypass Input
- 2. DAC (HiFi playback)
- 3. Mic Sidetone Input
+1. Line Bypass Input
+2. DAC (HiFi playback)
+3. Mic Sidetone Input
Each input in this example has a kcontrol associated with it (defined in example
above) and is connected to the output mixer via its kcontrol name. We can now
connect the destination widget (wrt audio signal) with its source widgets.
+::
/* output mixer */
{"Output Mixer", "Line Bypass Switch", "Line Input"},
@@ -216,22 +255,17 @@ connect the destination widget (wrt audio signal) with its source widgets.
So we have :-
- Destination Widget <=== Path Name <=== Source Widget
-
-Or:-
-
- Sink, Path, Source
-
-Or :-
-
- "Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
+* Destination Widget <=== Path Name <=== Source Widget, or
+* Sink, Path, Source, or
+* ``Output Mixer`` is connected to the ``DAC`` via the ``HiFi Playback Switch``.
When there is no path name connecting widgets (e.g. a direct connection) we
pass NULL for the path name.
Interconnections are created with a call to:-
+::
-snd_soc_dapm_connect_input(codec, sink, path, source);
+ snd_soc_dapm_connect_input(codec, sink, path, source);
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
interconnections have been registered with the core. This causes the core to
@@ -239,12 +273,13 @@ scan the codec and machine so that the internal DAPM state matches the
physical state of the machine.
-3.1 Machine Widget Interconnections
------------------------------------
+Machine Widget Interconnections
+-------------------------------
Machine widget interconnections are created in the same way as codec ones and
directly connect the codec pins to machine level widgets.
e.g. connects the speaker out codec pins to the internal speaker.
+::
/* ext speaker connected to codec pins LOUT2, ROUT2 */
{"Ext Spk", NULL , "ROUT2"},
@@ -254,52 +289,54 @@ This allows the DAPM to power on and off pins that are connected (and in use)
and pins that are NC respectively.
-4 Endpoint Widgets
-===================
+Endpoint Widgets
+================
An endpoint is a start or end point (widget) of an audio signal within the
machine and includes the codec. e.g.
- o Headphone Jack
- o Internal Speaker
- o Internal Mic
- o Mic Jack
- o Codec Pins
+* Headphone Jack
+* Internal Speaker
+* Internal Mic
+* Mic Jack
+* Codec Pins
Endpoints are added to the DAPM graph so that their usage can be determined in
order to save power. e.g. NC codecs pins will be switched OFF, unconnected
jacks can also be switched OFF.
-5 DAPM Widget Events
-====================
+DAPM Widget Events
+==================
Some widgets can register their interest with the DAPM core in PM events.
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
powered only when the spk is in use.
+::
-/* turn speaker amplifier on/off depending on use */
-static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
-{
+ /* turn speaker amplifier on/off depending on use */
+ static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
+ {
gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
return 0;
-}
+ }
-/* corgi machine dapm widgets */
-static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
+ /* corgi machine dapm widgets */
+ static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
Please see soc-dapm.h for all other widgets that support events.
-5.1 Event types
----------------
+Event types
+-----------
The following event types are supported by event widgets.
-
-/* dapm event types */
-#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
-#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
-#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
-#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
-#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
-#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
+::
+
+ /* dapm event types */
+ #define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
+ #define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
+ #define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
+ #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
+ #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
+ #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
diff --git a/Documentation/sound/alsa/soc/DPCM.txt b/Documentation/sound/soc/dpcm.rst
index 0110180b7ac6..395e5a516282 100644
--- a/Documentation/sound/alsa/soc/DPCM.txt
+++ b/Documentation/sound/soc/dpcm.rst
@@ -1,8 +1,9 @@
+===========
Dynamic PCM
===========
-1. Description
-==============
+Description
+===========
Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
@@ -23,22 +24,23 @@ Phone Audio System with SoC based DSP
Consider the following phone audio subsystem. This will be used in this
document for all examples :-
-
-| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
-
- *************
-PCM0 <------------> * * <----DAI0-----> Codec Headset
- * *
-PCM1 <------------> * * <----DAI1-----> Codec Speakers
- * DSP *
-PCM2 <------------> * * <----DAI2-----> MODEM
- * *
-PCM3 <------------> * * <----DAI3-----> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+::
+
+ | Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
+
+ *************
+ PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+ PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+ PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+ PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
FM digital radio, Speakers, Headset Jack, digital microphones and cellular
@@ -55,50 +57,52 @@ Audio is being played to the Headset. After a while the user removes the headset
and audio continues playing on the speakers.
Playback on PCM0 to Headset would look like :-
-
- *************
-PCM0 <============> * * <====DAI0=====> Codec Headset
- * *
-PCM1 <------------> * * <----DAI1-----> Codec Speakers
- * DSP *
-PCM2 <------------> * * <----DAI2-----> MODEM
- * *
-PCM3 <------------> * * <----DAI3-----> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+::
+
+ *************
+ PCM0 <============> * * <====DAI0=====> Codec Headset
+ * *
+ PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+ PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+ PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
The headset is removed from the jack by user so the speakers must now be used :-
-
- *************
-PCM0 <============> * * <----DAI0-----> Codec Headset
- * *
-PCM1 <------------> * * <====DAI1=====> Codec Speakers
- * DSP *
-PCM2 <------------> * * <----DAI2-----> MODEM
- * *
-PCM3 <------------> * * <----DAI3-----> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+::
+
+ *************
+ PCM0 <============> * * <----DAI0-----> Codec Headset
+ * *
+ PCM1 <------------> * * <====DAI1=====> Codec Speakers
+ * DSP *
+ PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+ PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
The audio driver processes this as follows :-
- 1) Machine driver receives Jack removal event.
+1. Machine driver receives Jack removal event.
- 2) Machine driver OR audio HAL disables the Headset path.
+2. Machine driver OR audio HAL disables the Headset path.
- 3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
- for headset since the path is now disabled.
+3. DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
+ for headset since the path is now disabled.
- 4) Machine driver or audio HAL enables the speaker path.
+4. Machine driver or audio HAL enables the speaker path.
- 5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
- trigger(start) for DAI1 Speakers since the path is enabled.
+5. DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
+ trigger(start) for DAI1 Speakers since the path is enabled.
In this example, the machine driver or userspace audio HAL can alter the routing
and then DPCM will take care of managing the DAI PCM operations to either bring
@@ -112,36 +116,38 @@ DPCM machine driver
The DPCM enabled ASoC machine driver is similar to normal machine drivers
except that we also have to :-
- 1) Define the FE and BE DAI links.
+1. Define the FE and BE DAI links.
- 2) Define any FE/BE PCM operations.
+2. Define any FE/BE PCM operations.
- 3) Define widget graph connections.
+3. Define widget graph connections.
-1 FE and BE DAI links
----------------------
+FE and BE DAI links
+-------------------
+::
-| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
-
- *************
-PCM0 <------------> * * <----DAI0-----> Codec Headset
- * *
-PCM1 <------------> * * <----DAI1-----> Codec Speakers
- * DSP *
-PCM2 <------------> * * <----DAI2-----> MODEM
- * *
-PCM3 <------------> * * <----DAI3-----> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+ | Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
+
+ *************
+ PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+ PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+ PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+ PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
FE DAI links are defined as follows :-
+::
-static struct snd_soc_dai_link machine_dais[] = {
+ static struct snd_soc_dai_link machine_dais[] = {
{
.name = "PCM0 System",
.stream_name = "System Playback",
@@ -154,11 +160,11 @@ static struct snd_soc_dai_link machine_dais[] = {
.dpcm_playback = 1,
},
.....< other FE and BE DAI links here >
-};
+ };
This FE DAI link is pretty similar to a regular DAI link except that we also
-set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream
-directions should also be set with the "dpcm_playback" and "dpcm_capture"
+set the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream
+directions should also be set with the ``dpcm_playback`` and ``dpcm_capture``
flags. There is also an option to specify the ordering of the trigger call for
each FE. This allows the ASoC core to trigger the DSP before or after the other
components (as some DSPs have strong requirements for the ordering DAI/DSP
@@ -168,8 +174,9 @@ The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
dynamic and will change depending on runtime config.
The BE DAIs are configured as follows :-
+::
-static struct snd_soc_dai_link machine_dais[] = {
+ static struct snd_soc_dai_link machine_dais[] = {
.....< FE DAI links here >
{
.name = "Codec Headset",
@@ -186,29 +193,30 @@ static struct snd_soc_dai_link machine_dais[] = {
.dpcm_capture = 1,
},
.....< other BE DAI links here >
-};
+ };
This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
-the "no_pcm" flag to mark it has a BE and sets flags for supported stream
-directions using "dpcm_playback" and "dpcm_capture" above.
+the ``no_pcm`` flag to mark it has a BE and sets flags for supported stream
+directions using ``dpcm_playback`` and ``dpcm_capture`` above.
The BE has also flags set for ignoring suspend and PM down time. This allows
the BE to work in a hostless mode where the host CPU is not transferring data
like a BT phone call :-
-
- *************
-PCM0 <------------> * * <----DAI0-----> Codec Headset
- * *
-PCM1 <------------> * * <----DAI1-----> Codec Speakers
- * DSP *
-PCM2 <------------> * * <====DAI2=====> MODEM
- * *
-PCM3 <------------> * * <====DAI3=====> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+::
+
+ *************
+ PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+ PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+ PCM2 <------------> * * <====DAI2=====> MODEM
+ * *
+ PCM3 <------------> * * <====DAI3=====> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
still in operation.
@@ -220,10 +228,10 @@ Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
DSP firmware.
-2 FE/BE PCM operations
-----------------------
+FE/BE PCM operations
+--------------------
-The BE above also exports some PCM operations and a "fixup" callback. The fixup
+The BE above also exports some PCM operations and a ``fixup`` callback. The fixup
callback is used by the machine driver to (re)configure the DAI based upon the
FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
@@ -231,10 +239,11 @@ e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo fo
DAI0. This means all FE hw_params have to be fixed in the machine driver for
DAI0 so that the DAI is running at desired configuration regardless of the FE
configuration.
+::
-static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
+ static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
-{
+ {
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
@@ -249,21 +258,22 @@ static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S16_LE);
return 0;
-}
+ }
The other PCM operation are the same as for regular DAI links. Use as necessary.
-3 Widget graph connections
---------------------------
+Widget graph connections
+------------------------
The BE DAI links will normally be connected to the graph at initialisation time
by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
has to be set explicitly in the driver :-
+::
-/* BE for codec Headset - DAI0 is dummy and managed by DSP FW */
-{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
-{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
+ /* BE for codec Headset - DAI0 is dummy and managed by DSP FW */
+ {"DAI0 CODEC IN", NULL, "AIF1 Capture"},
+ {"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
Writing a DPCM DSP driver
@@ -273,24 +283,25 @@ The DPCM DSP driver looks much like a standard platform class ASoC driver
combined with elements from a codec class driver. A DSP platform driver must
implement :-
- 1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
+1. Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
- 2) DAPM graph showing DSP audio routing from FE DAIs to BEs.
+2. DAPM graph showing DSP audio routing from FE DAIs to BEs.
- 3) DAPM widgets from DSP graph.
+3. DAPM widgets from DSP graph.
- 4) Mixers for gains, routing, etc.
+4. Mixers for gains, routing, etc.
- 5) DMA configuration.
+5. DMA configuration.
- 6) BE AIF widgets.
+6. BE AIF widgets.
Items 6 is important for routing the audio outside of the DSP. AIF need to be
defined for each BE and each stream direction. e.g for BE DAI0 above we would
have :-
+::
-SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
The BE AIF are used to connect the DSP graph to the graphs for the other
component drivers (e.g. codec graph).
@@ -301,33 +312,33 @@ Hostless PCM streams
A hostless PCM stream is a stream that is not routed through the host CPU. An
example of this would be a phone call from handset to modem.
-
-
- *************
-PCM0 <------------> * * <----DAI0-----> Codec Headset
- * *
-PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic
- * DSP *
-PCM2 <------------> * * <====DAI2=====> MODEM
- * *
-PCM3 <------------> * * <----DAI3-----> BT
- * *
- * * <----DAI4-----> DMIC
- * *
- * * <----DAI5-----> FM
- *************
+::
+
+ *************
+ PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+ PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic
+ * DSP *
+ PCM2 <------------> * * <====DAI2=====> MODEM
+ * *
+ PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
In this case the PCM data is routed via the DSP. The host CPU in this use case
is only used for control and can sleep during the runtime of the stream.
The host can control the hostless link either by :-
- 1) Configuring the link as a CODEC <-> CODEC style link. In this case the link
+ 1. Configuring the link as a CODEC <-> CODEC style link. In this case the link
is enabled or disabled by the state of the DAPM graph. This usually means
there is a mixer control that can be used to connect or disconnect the path
between both DAIs.
- 2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
+ 2. Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
graph. Control is then carried out by the FE as regular PCM operations.
This method gives more control over the DAI links, but requires much more
userspace code to control the link. Its recommended to use CODEC<->CODEC
@@ -339,16 +350,17 @@ CODEC <-> CODEC link
This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
The machine driver sets some additional parameters to the DAI link i.e.
+::
-static const struct snd_soc_pcm_stream dai_params = {
+ static const struct snd_soc_pcm_stream dai_params = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.rate_min = 8000,
.rate_max = 8000,
.channels_min = 2,
.channels_max = 2,
-};
+ };
-static struct snd_soc_dai_link dais[] = {
+ static struct snd_soc_dai_link dais[] = {
< ... more DAI links above ... >
{
.name = "MODEM",
diff --git a/Documentation/sound/soc/index.rst b/Documentation/sound/soc/index.rst
new file mode 100644
index 000000000000..e57df2dab2fd
--- /dev/null
+++ b/Documentation/sound/soc/index.rst
@@ -0,0 +1,20 @@
+==============
+ALSA SoC Layer
+==============
+
+The documentation is spilt into the following sections:-
+
+.. toctree::
+ :maxdepth: 2
+
+ overview
+ codec
+ dai
+ dapm
+ platform
+ machine
+ pops-clicks
+ clocking
+ jack
+ dpcm
+ codec-to-codec
diff --git a/Documentation/sound/alsa/soc/jack.txt b/Documentation/sound/soc/jack.rst
index fcf82a417293..644b99ecba35 100644
--- a/Documentation/sound/alsa/soc/jack.txt
+++ b/Documentation/sound/soc/jack.rst
@@ -1,3 +1,4 @@
+===================
ASoC jack detection
===================
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/soc/machine.rst
index 6bf2d2063b52..515c9444deaf 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/soc/machine.rst
@@ -1,3 +1,4 @@
+===================
ASoC Machine Driver
===================
@@ -9,9 +10,10 @@ interrupts, clocking, jacks and voltage regulators.
The machine driver can contain codec and platform specific code. It registers
the audio subsystem with the kernel as a platform device and is represented by
the following struct:-
+::
-/* SoC machine */
-struct snd_soc_card {
+ /* SoC machine */
+ struct snd_soc_card {
char *name;
...
@@ -33,7 +35,7 @@ struct snd_soc_card {
int num_links;
...
-};
+ };
probe()/remove()
----------------
@@ -55,9 +57,10 @@ initialisation e.g. the machine audio map can be connected to the codec audio
map, unconnected codec pins can be set as such.
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
+::
-/* corgi digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link corgi_dai = {
+ /* corgi digital audio interface glue - connects codec <--> CPU */
+ static struct snd_soc_dai_link corgi_dai = {
.name = "WM8731",
.stream_name = "WM8731",
.cpu_dai_name = "pxa-is2-dai",
@@ -66,16 +69,17 @@ static struct snd_soc_dai_link corgi_dai = {
.codec_name = "wm8713-codec.0-001a",
.init = corgi_wm8731_init,
.ops = &corgi_ops,
-};
+ };
struct snd_soc_card then sets up the machine with its DAIs. e.g.
+::
-/* corgi audio machine driver */
-static struct snd_soc_card snd_soc_corgi = {
+ /* corgi audio machine driver */
+ static struct snd_soc_card snd_soc_corgi = {
.name = "Corgi",
.dai_link = &corgi_dai,
.num_links = 1,
-};
+ };
Machine Power Map
diff --git a/Documentation/sound/alsa/soc/overview.txt b/Documentation/sound/soc/overview.rst
index f3f28b7ae242..dc8370bbfff6 100644
--- a/Documentation/sound/alsa/soc/overview.txt
+++ b/Documentation/sound/soc/overview.rst
@@ -1,5 +1,6 @@
-ALSA SoC Layer
-==============
+=======================
+ALSA SoC Layer Overview
+=======================
The overall project goal of the ALSA System on Chip (ASoC) layer is to
provide better ALSA support for embedded system-on-chip processors (e.g.
@@ -66,30 +67,3 @@ multiple re-usable component drivers :-
describes and binds the other component drivers together to form an ALSA
"sound card device". It handles any machine specific controls and
machine level audio events (e.g. turning on an amp at start of playback).
-
-
-Documentation
-=============
-
-The documentation is spilt into the following sections:-
-
-overview.txt: This file.
-
-codec.txt: Codec driver internals.
-
-DAI.txt: Description of Digital Audio Interface standards and how to configure
-a DAI within your codec and CPU DAI drivers.
-
-dapm.txt: Dynamic Audio Power Management
-
-platform.txt: Platform audio DMA and DAI.
-
-machine.txt: Machine driver internals.
-
-pop_clicks.txt: How to minimise audio artifacts.
-
-clocking.txt: ASoC clocking for best power performance.
-
-jack.txt: ASoC jack detection.
-
-DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/soc/platform.rst
index 3a08a2c9150c..d5574904d981 100644
--- a/Documentation/sound/alsa/soc/platform.txt
+++ b/Documentation/sound/soc/platform.rst
@@ -1,3 +1,4 @@
+====================
ASoC Platform Driver
====================
@@ -9,21 +10,23 @@ Audio DMA
=========
The platform DMA driver optionally supports the following ALSA operations:-
+::
-/* SoC audio ops */
-struct snd_soc_ops {
+ /* SoC audio ops */
+ struct snd_soc_ops {
int (*startup)(struct snd_pcm_substream *);
void (*shutdown)(struct snd_pcm_substream *);
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
int (*hw_free)(struct snd_pcm_substream *);
int (*prepare)(struct snd_pcm_substream *);
int (*trigger)(struct snd_pcm_substream *, int);
-};
+ };
The platform driver exports its DMA functionality via struct
snd_soc_platform_driver:-
+::
-struct snd_soc_platform_driver {
+ struct snd_soc_platform_driver {
char *name;
int (*probe)(struct platform_device *pdev);
@@ -44,7 +47,7 @@ struct snd_soc_platform_driver {
/* platform stream ops */
struct snd_pcm_ops *pcm_ops;
-};
+ };
Please refer to the ALSA driver documentation for details of audio DMA.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
@@ -57,11 +60,11 @@ SoC DAI Drivers
Each SoC DAI driver must provide the following features:-
- 1) Digital audio interface (DAI) description
- 2) Digital audio interface configuration
- 3) PCM's description
- 4) SYSCLK configuration
- 5) Suspend and resume (optional)
+1. Digital audio interface (DAI) description
+2. Digital audio interface configuration
+3. PCM's description
+4. SYSCLK configuration
+5. Suspend and resume (optional)
Please see codec.txt for a description of items 1 - 4.
@@ -71,9 +74,9 @@ SoC DSP Drivers
Each SoC DSP driver usually supplies the following features :-
- 1) DAPM graph
- 2) Mixer controls
- 3) DMA IO to/from DSP buffers (if applicable)
- 4) Definition of DSP front end (FE) PCM devices.
+1. DAPM graph
+2. Mixer controls
+3. DMA IO to/from DSP buffers (if applicable)
+4. Definition of DSP front end (FE) PCM devices.
Please see DPCM.txt for a description of item 4.
diff --git a/Documentation/sound/alsa/soc/pops_clicks.txt b/Documentation/sound/soc/pops-clicks.rst
index e1e74daa4497..de7eb2a6604a 100644
--- a/Documentation/sound/alsa/soc/pops_clicks.txt
+++ b/Documentation/sound/soc/pops-clicks.rst
@@ -1,3 +1,4 @@
+=====================
Audio Pops and Clicks
=====================
@@ -20,10 +21,11 @@ currently, however future audio codec hardware will have better pop and click
suppression. Pops can be reduced within playback by powering the audio
components in a specific order. This order is different for startup and
shutdown and follows some basic rules:-
+::
- Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
-
- Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
+ Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
+
+ Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
This assumes that the codec PCM output path from the DAC is via a mixer and then
a PGA (programmable gain amplifier) before being output to the speakers.
@@ -36,10 +38,11 @@ Capture artifacts are somewhat easier to get rid as we can delay activating the
ADC until all the pops have occurred. This follows similar power rules to
playback in that components are powered in a sequence depending upon stream
startup or shutdown.
+::
- Startup Order - Input PGA --> Mixers --> ADC
-
- Shutdown Order - ADC --> Mixers --> Input PGA
+ Startup Order - Input PGA --> Mixers --> ADC
+
+ Shutdown Order - ADC --> Mixers --> Input PGA
Zipper Noise
diff --git a/Documentation/sphinx/kernel-doc.py b/Documentation/sphinx/kerneldoc.py
index d15e07f36881..d15e07f36881 100644
--- a/Documentation/sphinx/kernel-doc.py
+++ b/Documentation/sphinx/kerneldoc.py
diff --git a/Documentation/sphinx/parse-headers.pl b/Documentation/sphinx/parse-headers.pl
index db0186a7618f..a958d8b5e99d 100755
--- a/Documentation/sphinx/parse-headers.pl
+++ b/Documentation/sphinx/parse-headers.pl
@@ -1,22 +1,22 @@
#!/usr/bin/perl
use strict;
use Text::Tabs;
+use Getopt::Long;
+use Pod::Usage;
-my $debug = 0;
+my $debug;
+my $help;
+my $man;
-while ($ARGV[0] =~ m/^-(.*)/) {
- my $cmd = shift @ARGV;
- if ($cmd eq "--debug") {
- require Data::Dumper;
- $debug = 1;
- next;
- }
- die "argument $cmd unknown";
-}
+GetOptions(
+ "debug" => \$debug,
+ 'usage|?' => \$help,
+ 'help' => \$man
+) or pod2usage(2);
-if (scalar @ARGV < 2 || scalar @ARGV > 3) {
- die "Usage:\n\t$0 <file in> <file out> [<exceptions file>]\n";
-}
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
my ($file_in, $file_out, $file_exceptions) = @ARGV;
@@ -28,6 +28,8 @@ my %enums;
my %enum_symbols;
my %structs;
+require Data::Dumper if ($debug);
+
#
# read the file and get identifiers
#
@@ -330,3 +332,70 @@ print OUT "=" x length($title);
print OUT "\n\n.. parsed-literal::\n\n";
print OUT $data;
close OUT;
+
+__END__
+
+=head1 NAME
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+=head1 SYNOPSIS
+
+B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging.
+
+=item B<--usage>
+
+Prints a brief help message and exits.
+
+=item B<--help>
+
+Prints a more detailed help message and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
+to replace the default references by a custom one.
+
+Please read Documentation/doc-guide/parse-headers.rst at the Kernel's
+tree for more details.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab@s-opensource.com>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff --git a/Documentation/sync_file.txt b/Documentation/sync_file.txt
index b63a68531afd..269681a6faec 100644
--- a/Documentation/sync_file.txt
+++ b/Documentation/sync_file.txt
@@ -6,7 +6,7 @@
This document serves as a guide for device drivers writers on what the
sync_file API is, and how drivers can support it. Sync file is the carrier of
-the fences(struct fence) that are needed to synchronize between drivers or
+the fences(struct dma_fence) that are needed to synchronize between drivers or
across process boundaries.
The sync_file API is meant to be used to send and receive fence information
@@ -32,9 +32,9 @@ in-fences and out-fences
Sync files can go either to or from userspace. When a sync_file is sent from
the driver to userspace we call the fences it contains 'out-fences'. They are
related to a buffer that the driver is processing or is going to process, so
-the driver creates an out-fence to be able to notify, through fence_signal(),
-when it has finished using (or processing) that buffer. Out-fences are fences
-that the driver creates.
+the driver creates an out-fence to be able to notify, through
+dma_fence_signal(), when it has finished using (or processing) that buffer.
+Out-fences are fences that the driver creates.
On the other hand if the driver receives fence(s) through a sync_file from
userspace we call these fence(s) 'in-fences'. Receiveing in-fences means that
@@ -47,7 +47,7 @@ Creating Sync Files
When a driver needs to send an out-fence userspace it creates a sync_file.
Interface:
- struct sync_file *sync_file_create(struct fence *fence);
+ struct sync_file *sync_file_create(struct dma_fence *fence);
The caller pass the out-fence and gets back the sync_file. That is just the
first step, next it needs to install an fd on sync_file->file. So it gets an
@@ -72,11 +72,11 @@ of the Sync File to the kernel. The kernel can then retrieve the fences
from it.
Interface:
- struct fence *sync_file_get_fence(int fd);
+ struct dma_fence *sync_file_get_fence(int fd);
The returned reference is owned by the caller and must be disposed of
-afterwards using fence_put(). In case of error, a NULL is returned instead.
+afterwards using dma_fence_put(). In case of error, a NULL is returned instead.
References:
[1] struct sync_file in include/linux/sync_file.h
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index ffab8b5caa60..a32b4b748644 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -40,7 +40,6 @@ show up in /proc/sys/kernel:
- hung_task_warnings
- kexec_load_disabled
- kptr_restrict
-- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
- modprobe ==> Documentation/debugging-modules.txt
- modules_disabled
@@ -71,7 +70,7 @@ show up in /proc/sys/kernel:
- printk_ratelimit_burst
- pty ==> Documentation/filesystems/devpts.txt
- randomize_va_space
-- real-root-dev ==> Documentation/initrd.txt
+- real-root-dev ==> Documentation/admin-guide/initrd.rst
- reboot-cmd [ SPARC only ]
- rtsig-max
- rtsig-nr
@@ -395,13 +394,6 @@ When kptr_restrict is set to (2), kernel pointers printed using
==============================================================
-kstack_depth_to_print: (X86 only)
-
-Controls the number of words to print when dumping the raw
-kernel stack.
-
-==============================================================
-
l2cr: (PPC only)
This flag controls the L2 cache of G3 processor boards. If
@@ -453,7 +445,7 @@ in a KVM virtual machine. This default can be overridden by adding
nmi_watchdog=1
-to the guest kernel command line (see Documentation/kernel-parameters.txt).
+to the guest kernel command line (see Documentation/admin-guide/kernel-parameters.rst).
==============================================================
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
deleted file mode 100644
index ce60ffa94d2d..000000000000
--- a/Documentation/sysfs-rules.txt
+++ /dev/null
@@ -1,184 +0,0 @@
-Rules on how to access information in the Linux kernel sysfs
-
-The kernel-exported sysfs exports internal kernel implementation details
-and depends on internal kernel structures and layout. It is agreed upon
-by the kernel developers that the Linux kernel does not provide a stable
-internal API. Therefore, there are aspects of the sysfs interface that
-may not be stable across kernel releases.
-
-To minimize the risk of breaking users of sysfs, which are in most cases
-low-level userspace applications, with a new kernel release, the users
-of sysfs must follow some rules to use an as-abstract-as-possible way to
-access this filesystem. The current udev and HAL programs already
-implement this and users are encouraged to plug, if possible, into the
-abstractions these programs provide instead of accessing sysfs directly.
-
-But if you really do want or need to access sysfs directly, please follow
-the following rules and then your programs should work with future
-versions of the sysfs interface.
-
-- Do not use libsysfs
- It makes assumptions about sysfs which are not true. Its API does not
- offer any abstraction, it exposes all the kernel driver-core
- implementation details in its own API. Therefore it is not better than
- reading directories and opening the files yourself.
- Also, it is not actively maintained, in the sense of reflecting the
- current kernel development. The goal of providing a stable interface
- to sysfs has failed; it causes more problems than it solves. It
- violates many of the rules in this document.
-
-- sysfs is always at /sys
- Parsing /proc/mounts is a waste of time. Other mount points are a
- system configuration bug you should not try to solve. For test cases,
- possibly support a SYSFS_PATH environment variable to overwrite the
- application's behavior, but never try to search for sysfs. Never try
- to mount it, if you are not an early boot script.
-
-- devices are only "devices"
- There is no such thing like class-, bus-, physical devices,
- interfaces, and such that you can rely on in userspace. Everything is
- just simply a "device". Class-, bus-, physical, ... types are just
- kernel implementation details which should not be expected by
- applications that look for devices in sysfs.
-
- The properties of a device are:
- o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
- - identical to the DEVPATH value in the event sent from the kernel
- at device creation and removal
- - the unique key to the device at that point in time
- - the kernel's path to the device directory without the leading
- /sys, and always starting with a slash
- - all elements of a devpath must be real directories. Symlinks
- pointing to /sys/devices must always be resolved to their real
- target and the target path must be used to access the device.
- That way the devpath to the device matches the devpath of the
- kernel used at event time.
- - using or exposing symlink values as elements in a devpath string
- is a bug in the application
-
- o kernel name (sda, tty, 0000:00:1f.2, ...)
- - a directory name, identical to the last element of the devpath
- - applications need to handle spaces and characters like '!' in
- the name
-
- o subsystem (block, tty, pci, ...)
- - simple string, never a path or a link
- - retrieved by reading the "subsystem"-link and using only the
- last element of the target path
-
- o driver (tg3, ata_piix, uhci_hcd)
- - a simple string, which may contain spaces, never a path or a
- link
- - it is retrieved by reading the "driver"-link and using only the
- last element of the target path
- - devices which do not have "driver"-link just do not have a
- driver; copying the driver value in a child device context is a
- bug in the application
-
- o attributes
- - the files in the device directory or files below subdirectories
- of the same device directory
- - accessing attributes reached by a symlink pointing to another device,
- like the "device"-link, is a bug in the application
-
- Everything else is just a kernel driver-core implementation detail
- that should not be assumed to be stable across kernel releases.
-
-- Properties of parent devices never belong into a child device.
- Always look at the parent devices themselves for determining device
- context properties. If the device 'eth0' or 'sda' does not have a
- "driver"-link, then this device does not have a driver. Its value is empty.
- Never copy any property of the parent-device into a child-device. Parent
- device properties may change dynamically without any notice to the
- child device.
-
-- Hierarchy in a single device tree
- There is only one valid place in sysfs where hierarchy can be examined
- and this is below: /sys/devices.
- It is planned that all device directories will end up in the tree
- below this directory.
-
-- Classification by subsystem
- There are currently three places for classification of devices:
- /sys/block, /sys/class and /sys/bus. It is planned that these will
- not contain any device directories themselves, but only flat lists of
- symlinks pointing to the unified /sys/devices tree.
- All three places have completely different rules on how to access
- device information. It is planned to merge all three
- classification directories into one place at /sys/subsystem,
- following the layout of the bus directories. All buses and
- classes, including the converted block subsystem, will show up
- there.
- The devices belonging to a subsystem will create a symlink in the
- "devices" directory at /sys/subsystem/<name>/devices.
-
- If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
- ignored. If it does not exist, you always have to scan all three
- places, as the kernel is free to move a subsystem from one place to
- the other, as long as the devices are still reachable by the same
- subsystem name.
-
- Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
- /sys/block and /sys/class/block are not interchangeable is a bug in
- the application.
-
-- Block
- The converted block subsystem at /sys/class/block or
- /sys/subsystem/block will contain the links for disks and partitions
- at the same level, never in a hierarchy. Assuming the block subsystem to
- contain only disks and not partition devices in the same flat list is
- a bug in the application.
-
-- "device"-link and <subsystem>:<kernel name>-links
- Never depend on the "device"-link. The "device"-link is a workaround
- for the old layout, where class devices are not created in
- /sys/devices/ like the bus devices. If the link-resolving of a
- device directory does not end in /sys/devices/, you can use the
- "device"-link to find the parent devices in /sys/devices/. That is the
- single valid use of the "device"-link; it must never appear in any
- path as an element. Assuming the existence of the "device"-link for
- a device in /sys/devices/ is a bug in the application.
- Accessing /sys/class/net/eth0/device is a bug in the application.
-
- Never depend on the class-specific links back to the /sys/class
- directory. These links are also a workaround for the design mistake
- that class devices are not created in /sys/devices. If a device
- directory does not contain directories for child devices, these links
- may be used to find the child devices in /sys/class. That is the single
- valid use of these links; they must never appear in any path as an
- element. Assuming the existence of these links for devices which are
- real child device directories in the /sys/devices tree is a bug in
- the application.
-
- It is planned to remove all these links when all class device
- directories live in /sys/devices.
-
-- Position of devices along device chain can change.
- Never depend on a specific parent device position in the devpath,
- or the chain of parent devices. The kernel is free to insert devices into
- the chain. You must always request the parent device you are looking for
- by its subsystem value. You need to walk up the chain until you find
- the device that matches the expected subsystem. Depending on a specific
- position of a parent device or exposing relative paths using "../" to
- access the chain of parents is a bug in the application.
-
-- When reading and writing sysfs device attribute files, avoid dependency
- on specific error codes wherever possible. This minimizes coupling to
- the error handling implementation within the kernel.
-
- In general, failures to read or write sysfs device attributes shall
- propagate errors wherever possible. Common errors include, but are not
- limited to:
-
- -EIO: The read or store operation is not supported, typically returned by
- the sysfs system itself if the read or store pointer is NULL.
-
- -ENXIO: The read or store operation failed
-
- Error codes will not be changed without good reason, and should a change
- to error codes result in user-space breakage, it will be fixed, or the
- the offending change will be reverted.
-
- Userspace applications can, however, expect the format and contents of
- the attribute files to remain consistent in the absence of a version
- attribute change in the context of a given attribute.
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
deleted file mode 100644
index 3a3b30ac2a75..000000000000
--- a/Documentation/sysrq.txt
+++ /dev/null
@@ -1,257 +0,0 @@
-Linux Magic System Request Key Hacks
-Documentation for sysrq.c
-
-* What is the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It is a 'magical' key combo you can hit which the kernel will respond to
-regardless of whatever else it is doing, unless it is completely locked up.
-
-* How do I enable the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. When running a kernel with SysRq compiled in,
-/proc/sys/kernel/sysrq controls the functions allowed to be invoked via
-the SysRq key. The default value in this file is set by the
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
-to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
- 0 - disable sysrq completely
- 1 - enable all functions of sysrq
- >1 - bitmask of allowed sysrq functions (see below for detailed function
- description):
- 2 = 0x2 - enable control of console logging level
- 4 = 0x4 - enable control of keyboard (SAK, unraw)
- 8 = 0x8 - enable debugging dumps of processes etc.
- 16 = 0x10 - enable sync command
- 32 = 0x20 - enable remount read-only
- 64 = 0x40 - enable signalling of processes (term, kill, oom-kill)
- 128 = 0x80 - allow reboot/poweroff
- 256 = 0x100 - allow nicing of all RT tasks
-
-You can set the value in the file by the following command:
- echo "number" >/proc/sys/kernel/sysrq
-
-The number may be written here either as decimal or as hexadecimal
-with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
-written in hexadecimal.
-
-Note that the value of /proc/sys/kernel/sysrq influences only the invocation
-via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
-allowed (by a user with admin privileges).
-
-* How do I use the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-On x86 - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
- keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
- also known as the 'Print Screen' key. Also some keyboards cannot
- handle so many keys being pressed at the same time, so you might
- have better luck with "press Alt", "press SysRq", "release SysRq",
- "press <command key>", release everything.
-
-On SPARC - You press 'ALT-STOP-<command key>', I believe.
-
-On the serial console (PC style standard serial ports only) -
- You send a BREAK, then within 5 seconds a command key. Sending
- BREAK twice is interpreted as a normal BREAK.
-
-On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
- Print Screen (or F13) - <command key> may suffice.
-
-On other - If you know of the key combos for other architectures, please
- let me know so I can add them to this section.
-
-On all - write a character to /proc/sysrq-trigger. e.g.:
-
- echo t > /proc/sysrq-trigger
-
-* What are the 'command' keys?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-'b' - Will immediately reboot the system without syncing or unmounting
- your disks.
-
-'c' - Will perform a system crash by a NULL pointer dereference.
- A crashdump will be taken if configured.
-
-'d' - Shows all locks that are held.
-
-'e' - Send a SIGTERM to all processes, except for init.
-
-'f' - Will call the oom killer to kill a memory hog process, but do not
- panic if nothing can be killed.
-
-'g' - Used by kgdb (kernel debugger)
-
-'h' - Will display help (actually any other key than those listed
- here will display help. but 'h' is easy to remember :-)
-
-'i' - Send a SIGKILL to all processes, except for init.
-
-'j' - Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl.
-
-'k' - Secure Access Key (SAK) Kills all programs on the current virtual
- console. NOTE: See important comments below in SAK section.
-
-'l' - Shows a stack backtrace for all active CPUs.
-
-'m' - Will dump current memory info to your console.
-
-'n' - Used to make RT tasks nice-able
-
-'o' - Will shut your system off (if configured and supported).
-
-'p' - Will dump the current registers and flags to your console.
-
-'q' - Will dump per CPU lists of all armed hrtimers (but NOT regular
- timer_list timers) and detailed information about all
- clockevent devices.
-
-'r' - Turns off keyboard raw mode and sets it to XLATE.
-
-'s' - Will attempt to sync all mounted filesystems.
-
-'t' - Will dump a list of current tasks and their information to your
- console.
-
-'u' - Will attempt to remount all mounted filesystems read-only.
-
-'v' - Forcefully restores framebuffer console
-'v' - Causes ETM buffer dump [ARM-specific]
-
-'w' - Dumps tasks that are in uninterruptable (blocked) state.
-
-'x' - Used by xmon interface on ppc/powerpc platforms.
- Show global PMU Registers on sparc64.
- Dump all TLB entries on MIPS.
-
-'y' - Show global CPU Registers [SPARC-64 specific]
-
-'z' - Dump the ftrace buffer
-
-'0'-'9' - Sets the console log level, controlling which kernel messages
- will be printed to your console. ('0', for example would make
- it so that only emergency messages like PANICs or OOPSes would
- make it to your console.)
-
-* Okay, so what can I use them for?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Well, unraw(r) is very handy when your X server or a svgalib program crashes.
-
-sak(k) (Secure Access Key) is useful when you want to be sure there is no
-trojan program running at console which could grab your password
-when you would try to login. It will kill all programs on given console,
-thus letting you make sure that the login prompt you see is actually
-the one from init, not some trojan program.
-IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
-IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT
-IMPORTANT: such. :IMPORTANT
- It seems others find it useful as (System Attention Key) which is
-useful when you want to exit a program that will not let you switch consoles.
-(For example, X or a svgalib program.)
-
-reboot(b) is good when you're unable to shut down. But you should also
-sync(s) and umount(u) first.
-
-crash(c) can be used to manually trigger a crashdump when the system is hung.
-Note that this just triggers a crash if there is no dump mechanism available.
-
-sync(s) is great when your system is locked up, it allows you to sync your
-disks and will certainly lessen the chance of data loss and fscking. Note
-that the sync hasn't taken place until you see the "OK" and "Done" appear
-on the screen. (If the kernel is really in strife, you may not ever get the
-OK or Done message...)
-
-umount(u) is basically useful in the same ways as sync(s). I generally sync(s),
-umount(u), then reboot(b) when my system locks. It's saved me many a fsck.
-Again, the unmount (remount read-only) hasn't taken place until you see the
-"OK" and "Done" message appear on the screen.
-
-The loglevels '0'-'9' are useful when your console is being flooded with
-kernel messages you do not want to see. Selecting '0' will prevent all but
-the most urgent kernel messages from reaching your console. (They will
-still be logged if syslogd/klogd are alive, though.)
-
-term(e) and kill(i) are useful if you have some sort of runaway process you
-are unable to kill any other way, especially if it's spawning other
-processes.
-
-"just thaw it(j)" is useful if your system becomes unresponsive due to a frozen
-(probably root) filesystem via the FIFREEZE ioctl.
-
-* Sometimes SysRq seems to get 'stuck' after using it, what can I do?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-That happens to me, also. I've found that tapping shift, alt, and control
-on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
-virtual console (ALT+Fn) and then back again should also help.
-
-* I hit SysRq, but nothing seems to happen, what's wrong?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are some keyboards that produce a different keycode for SysRq than the
-pre-defined value of 99 (see KEY_SYSRQ in include/linux/input.h), or which
-don't have a SysRq key at all. In these cases, run 'showkey -s' to find an
-appropriate scancode sequence, and use 'setkeycodes <sequence> 99' to map
-this sequence to the usual SysRq code (e.g., 'setkeycodes e05b 99'). It's
-probably best to put this command in a boot script. Oh, and by the way, you
-exit 'showkey' by not typing anything for ten seconds.
-
-* I want to add SysRQ key events to a module, how does it work?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In order to register a basic function with the table, you must first include
-the header 'include/linux/sysrq.h', this will define everything else you need.
-Next, you must create a sysrq_key_op struct, and populate it with A) the key
-handler function you will use, B) a help_msg string, that will print when SysRQ
-prints help, and C) an action_msg string, that will print right before your
-handler is called. Your handler must conform to the prototype in 'sysrq.h'.
-
-After the sysrq_key_op is created, you can call the kernel function
-register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
-register the operation pointed to by 'op_p' at table key 'key',
-if that slot in the table is blank. At module unload time, you must call
-the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
-will remove the key op pointed to by 'op_p' from the key 'key', if and only if
-it is currently registered in that slot. This is in case the slot has been
-overwritten since you registered it.
-
-The Magic SysRQ system works by registering key operations against a key op
-lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
-a number of operations registered into it at compile time, but is mutable,
-and 2 functions are exported for interface to it:
- register_sysrq_key and unregister_sysrq_key.
-Of course, never ever leave an invalid pointer in the table. I.e., when
-your module that called register_sysrq_key() exits, it must call
-unregister_sysrq_key() to clean up the sysrq key table entry that it used.
-Null pointers in the table are always safe. :)
-
-If for some reason you feel the need to call the handle_sysrq function from
-within a function called by handle_sysrq, you must be aware that you are in
-a lock (you are also in an interrupt handler, which means don't sleep!), so
-you must call __handle_sysrq_nolock instead.
-
-* When I hit a SysRq key combination only the header appears on the console?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sysrq output is subject to the same console loglevel control as all
-other console output. This means that if the kernel was booted 'quiet'
-as is common on distro kernels the output may not appear on the actual
-console, even though it will appear in the dmesg buffer, and be accessible
-via the dmesg command and to the consumers of /proc/kmsg. As a specific
-exception the header line from the sysrq command is passed to all console
-consumers as if the current loglevel was maximum. If only the header
-is emitted it is almost certain that the kernel loglevel is too low.
-Should you require the output on the console channel then you will need
-to temporarily up the console loglevel using alt-sysrq-8 or:
-
- echo 8 > /proc/sysrq-trigger
-
-Remember to return the loglevel to normal after triggering the sysrq
-command you are interested in.
-
-* I have more questions, who can I ask?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Just ask them on the linux-kernel mailing list:
- linux-kernel@vger.kernel.org
-
-* Credits
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Written by Mydraal <vulpyne@vulpyne.net>
-Updated by Adam Sulmicki <adam@cfar.umd.edu>
-Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
-Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index 185c39fea2a0..5596e2d71d6d 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -362,6 +362,26 @@ of ftrace. Here is a list of some of the key files:
to correlate events across hypervisor/guest if
tb_offset is known.
+ mono: This uses the fast monotonic clock (CLOCK_MONOTONIC)
+ which is monotonic and is subject to NTP rate adjustments.
+
+ mono_raw:
+ This is the raw monotonic clock (CLOCK_MONOTONIC_RAW)
+ which is montonic but is not subject to any rate adjustments
+ and ticks at the same rate as the hardware clocksource.
+
+ boot: This is the boot clock (CLOCK_BOOTTIME) and is based on the
+ fast monotonic clock, but also accounts for time spent in
+ suspend. Since the clock access is designed for use in
+ tracing in the suspend path, some side effects are possible
+ if clock is accessed after the suspend time is accounted before
+ the fast mono clock is updated. In this case, the clock update
+ appears to happen slightly sooner than it normally would have.
+ Also on 32-bit systems, it's possible that the 64-bit boot offset
+ sees a partial update. These effects are rare and post
+ processing should be able to handle them. See comments in the
+ ktime_get_boot_fast_ns() function for more information.
+
To set a clock, simply echo the clock name into this file.
echo global > trace_clock
diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt
index 94b6b4581763..fa7b680ee8a0 100644
--- a/Documentation/trace/uprobetracer.txt
+++ b/Documentation/trace/uprobetracer.txt
@@ -76,15 +76,15 @@ Usage examples
* Add a probe as a new uprobe event, write a new definition to uprobe_events
as below: (sets a uprobe at an offset of 0x4245c0 in the executable /bin/bash)
- echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
+ echo 'p /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
* Add a probe as a new uretprobe event:
- echo 'r: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
+ echo 'r /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
* Unset registered event:
- echo '-:bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
+ echo '-:p_bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
* Print out the events that are registered:
diff --git a/Documentation/ja_JP/HOWTO b/Documentation/translations/ja_JP/HOWTO
index 581c14bdd7be..b03fc8047f03 100644
--- a/Documentation/ja_JP/HOWTO
+++ b/Documentation/translations/ja_JP/HOWTO
@@ -127,15 +127,15 @@ linux-api@ver.kernel.org ã«é€ã‚‹ã“ã¨ã‚’勧ã‚ã¾ã™ã€‚
å°é™ã®ãƒ¬ãƒ™ãƒ«ã§å¿…è¦ãªæ•°ã€…ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãƒ‘ッケージã®ä¸€è¦§ã‚’示ã—ã¦ã„
ã¾ã™ã€‚
- Documentation/CodingStyle
+ Documentation/process/coding-style.rst
ã“れ㯠Linux カーãƒãƒ«ã®ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã¨èƒŒæ™¯ã«ã‚ã‚‹ç†ç”±ã‚’記述
ã—ã¦ã„ã¾ã™ã€‚å…¨ã¦ã®æ–°ã—ã„コードã¯ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ã‚るガイドライン
ã«å¾“ã£ã¦ã„ã‚‹ã“ã¨ã‚’期待ã•ã‚Œã¦ã„ã¾ã™ã€‚大部分ã®ãƒ¡ãƒ³ãƒ†ãƒŠã¯ã“れらã®ãƒ«ãƒ¼
ルã«å¾“ã£ã¦ã„ã‚‹ã‚‚ã®ã ã‘ã‚’å—ã‘付ã‘ã€å¤šãã®äººã¯æ­£ã—ã„スタイルã®ã‚³ãƒ¼ãƒ‰
ã ã‘をレビューã—ã¾ã™ã€‚
- Documentation/SubmittingPatches
- Documentation/SubmittingDrivers
+ Documentation/process/submitting-patches.rst
+ Documentation/process/submitting-drivers.rst
ã“れらã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ã¯ã€ã©ã†ã‚„ã£ã¦ã†ã¾ãパッãƒã‚’作ã£ã¦æŠ•ç¨¿ã™ã‚‹ã‹ã«
ã¤ã„ã¦éžå¸¸ã«è©³ã—ã書ã‹ã‚Œã¦ãŠã‚Šã€ä»¥ä¸‹ã‚’å«ã¿ã¾ã™(ã“ã‚Œã ã‘ã«é™ã‚‰ãªã„
ã‘ã‚Œã©ã‚‚)
@@ -153,7 +153,7 @@ linux-api@ver.kernel.org ã«é€ã‚‹ã“ã¨ã‚’勧ã‚ã¾ã™ã€‚
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
- Documentation/stable_api_nonsense.txt
+ Documentation/process/stable-api-nonsense.rst
ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã‚«ãƒ¼ãƒãƒ«ã®ä¸­ã«ä¸å¤‰ã®APIã‚’æŒãŸãªã„ã“ã¨ã«ã—ãŸæ„識的ãª
決断ã®èƒŒæ™¯ã«ã‚ã‚‹ç†ç”±ã«ã¤ã„ã¦æ›¸ã‹ã‚Œã¦ã„ã¾ã™ã€‚以下ã®ã‚ˆã†ãªã“ã¨ã‚’å«
ã‚“ã§ã„ã¾ã™-
@@ -164,29 +164,29 @@ linux-api@ver.kernel.org ã«é€ã‚‹ã“ã¨ã‚’勧ã‚ã¾ã™ã€‚
ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ Linux 開発ã®æ€æƒ³ã‚’ç†è§£ã™ã‚‹ã®ã«éžå¸¸ã«é‡è¦ã§ã™ã€‚
ãã—ã¦ã€ä»–ã®OSã§ã®é–‹ç™ºè€…㌠Linux ã«ç§»ã‚‹æ™‚ã«ã¨ã¦ã‚‚é‡è¦ã§ã™ã€‚
- Documentation/SecurityBugs
+ Documentation/admin-guide/security-bugs.rst
ã‚‚ã— Linux カーãƒãƒ«ã§ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å•é¡Œã‚’発見ã—ãŸã‚ˆã†ã«æ€ã£ãŸã‚‰ã€ã“
ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã®ã‚¹ãƒ†ãƒƒãƒ—ã«å¾“ã£ã¦ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã«é€£çµ¡ã—ã€å•é¡Œè§£æ±ºã‚’
支æ´ã—ã¦ãã ã•ã„。
- Documentation/ManagementStyle
+ Documentation/process/management-style.rst
ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ Linux カーãƒãƒ«ã®ãƒ¡ãƒ³ãƒ†ãƒŠé”ãŒã©ã†è¡Œå‹•ã™ã‚‹ã‹ã€
彼らã®æ‰‹æ³•ã®èƒŒæ™¯ã«ã‚る共有ã•ã‚Œã¦ã„る精神ã«ã¤ã„ã¦è¨˜è¿°ã—ã¦ã„ã¾ã™ã€‚ã“
ã‚Œã¯ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºã®åˆå¿ƒè€…ãªã‚‰ï¼ˆã‚‚ã—ãã¯ã€å˜ã«èˆˆå‘³ãŒã‚ã‚‹ã ã‘ã®äººã§ã‚‚)
é‡è¦ã§ã™ã€‚ãªãœãªã‚‰ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ã€ã‚«ãƒ¼ãƒãƒ«ãƒ¡ãƒ³ãƒ†ãƒŠé”ã®ç‹¬ç‰¹ãª
行動ã«ã¤ã„ã¦ã®å¤šãã®èª¤è§£ã‚„混乱を解消ã™ã‚‹ã‹ã‚‰ã§ã™ã€‚
- Documentation/stable_kernel_rules.txt
+ Documentation/process/stable-kernel-rules.rst
ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã©ã®ã‚ˆã†ã« stable カーãƒãƒ«ã®ãƒªãƒªãƒ¼ã‚¹ãŒè¡Œã‚れるã‹ã®ãƒ«ãƒ¼
ルãŒè¨˜è¿°ã•ã‚Œã¦ã„ã¾ã™ã€‚ãã—ã¦ã“れらã®ãƒªãƒªãƒ¼ã‚¹ã®ä¸­ã®ã©ã“ã‹ã§å¤‰æ›´ã‚’å–
り入れã¦ã‚‚らã„ãŸã„å ´åˆã«ä½•ã‚’ã™ã‚Œã°è‰¯ã„ã‹ãŒç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚
- Documentation/kernel-docs.txt
+ Documentation/process/kernel-docs.rst
  カーãƒãƒ«é–‹ç™ºã«ä»˜éšã™ã‚‹å¤–部ドキュメントã®ãƒªã‚¹ãƒˆã§ã™ã€‚ã‚‚ã—ã‚ãªãŸãŒ
探ã—ã¦ã„ã‚‹ã‚‚ã®ãŒã‚«ãƒ¼ãƒãƒ«å†…ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã§ã¿ã¤ã‹ã‚‰ãªã‹ã£ãŸå ´åˆã€
ã“ã®ãƒªã‚¹ãƒˆã‚’ã‚ãŸã£ã¦ã¿ã¦ãã ã•ã„。
- Documentation/applying-patches.txt
+ Documentation/process/applying-patches.rst
パッãƒã¨ã¯ãªã«ã‹ã€ãƒ‘ッãƒã‚’ã©ã†ã‚„ã£ã¦æ§˜ã€…ãªã‚«ãƒ¼ãƒãƒ«ã®é–‹ç™ºãƒ–ランãƒã«
é©ç”¨ã™ã‚‹ã®ã‹ã«ã¤ã„ã¦æ­£ç¢ºã«è¨˜è¿°ã—ãŸè‰¯ã„入門書ã§ã™ã€‚
@@ -314,7 +314,7 @@ Andrew Morton ㌠Linux-kernel メーリングリストã«ã‚«ãƒ¼ãƒãƒ«ãƒªãƒªãƒ¼ã
ãŸå•é¡ŒãŒãªã‘ã‚Œã°ã‚‚ã†å°‘ã—é•·ããªã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚セキュリティ関連ã®å•é¡Œ
ã®å ´åˆã¯ã“ã‚Œã«å¯¾ã—ã¦ã ã„ãŸã„ã®å ´åˆã€ã™ãã«ãƒªãƒªãƒ¼ã‚¹ãŒã•ã‚Œã¾ã™ã€‚
-カーãƒãƒ«ãƒ„リーã«å…¥ã£ã¦ã„ã‚‹ã€Documentation/stable_kernel_rules.txt ファ
+カーãƒãƒ«ãƒ„リーã«å…¥ã£ã¦ã„ã‚‹ã€Documentation/process/stable-kernel-rules.rst ファ
イルã«ã¯ã©ã®ã‚ˆã†ãªç¨®é¡žã®å¤‰æ›´ãŒ -stable ツリーã«å—ã‘入れå¯èƒ½ã‹ã€ã¾ãŸãƒª
リースプロセスãŒã©ã†å‹•ãã‹ãŒè¨˜è¿°ã•ã‚Œã¦ã„ã¾ã™ã€‚
@@ -372,7 +372,7 @@ bugzilla.kernel.org 㯠Linux カーãƒãƒ«é–‹ç™ºè€…ãŒã‚«ãƒ¼ãƒãƒ«ã®ãƒã‚°ã‚’è¿
場所ã§ã™ã€‚ユーザã¯è¦‹ã¤ã‘ãŸãƒã‚°ã®å…¨ã¦ã‚’ã“ã®ãƒ„ールã§å ±å‘Šã™ã¹ãã§ã™ã€‚
ã©ã† kernel bugzilla を使ã†ã‹ã®è©³ç´°ã¯ã€ä»¥ä¸‹ã‚’å‚ç…§ã—ã¦ãã ã•ã„-
http://bugzilla.kernel.org/page.cgi?id=faq.html
-メインカーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚るファイル REPORTING-BUGS ã¯ã‚«ãƒ¼ãƒ
+メインカーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚るファイル admin-guide/reporting-bugs.rst ã¯ã‚«ãƒ¼ãƒ
ルãƒã‚°ã‚‰ã—ã„ã‚‚ã®ã«ã¤ã„ã¦ã©ã†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã®è‰¯ã„テンプレートã§ã‚ã‚Šã€å•
é¡Œã®è¿½è·¡ã‚’助ã‘ã‚‹ãŸã‚ã«ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã«ã¨ã£ã¦ã©ã‚“ãªæƒ…å ±ãŒå¿…è¦ãªã®ã‹ã®è©³
ç´°ãŒæ›¸ã‹ã‚Œã¦ã„ã¾ã™ã€‚
@@ -438,7 +438,7 @@ MAINTAINERS ファイルã«ãƒªã‚¹ãƒˆãŒã‚ã‚Šã¾ã™ã®ã§å‚ç…§ã—ã¦ãã ã•ã
メールã®å…ˆé ­ã§ãªãã€å„引用行ã®é–“ã«ã‚ãªãŸã®è¨€ã„ãŸã„ã“ã¨ã‚’追加ã™ã‚‹ã¹ãã§
ã™ã€‚
-ã‚‚ã—パッãƒã‚’メールã«ä»˜ã‘ã‚‹å ´åˆã¯ã€Documentation/SubmittingPatches ã«æ
+ã‚‚ã—パッãƒã‚’メールã«ä»˜ã‘ã‚‹å ´åˆã¯ã€Documentation/process/submitting-patches.rst ã«æ
示ã•ã‚Œã¦ã„るよã†ã«ã€ãれ㯠プレーンãªå¯èª­ãƒ†ã‚­ã‚¹ãƒˆã«ã™ã‚‹ã“ã¨ã‚’忘れãªã„
よã†ã«ã—ã¾ã—ょã†ã€‚カーãƒãƒ«é–‹ç™ºè€…㯠添付や圧縮ã—ãŸãƒ‘ッãƒã‚’扱ã„ãŸãŒã‚Šã¾
ã›ã‚“-
diff --git a/Documentation/ja_JP/SubmitChecklist b/Documentation/translations/ja_JP/SubmitChecklist
index cb5507b1ac81..60c7c35ac517 100644
--- a/Documentation/ja_JP/SubmitChecklist
+++ b/Documentation/translations/ja_JP/SubmitChecklist
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/SubmitChecklist into Japanese.
+This is a version of Documentation/process/submit-checklist.rst into Japanese.
This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com>
and the JF Project team <http://www.linux.or.jp/JF/>.
If you find any difference between this document and the original file
@@ -14,7 +14,7 @@ to update the original English file first.
Last Updated: 2008/07/14
==================================
ã“ã‚Œã¯ã€
-linux-2.6.26/Documentation/SubmitChecklist ã®å’Œè¨³ã§ã™ã€‚
+linux-2.6.26/Documentation/process/submit-checklist.rst ã®å’Œè¨³ã§ã™ã€‚
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
翻訳日: 2008/07/14
@@ -27,7 +27,7 @@ Linux カーãƒãƒ«ãƒ‘ッãƒæŠ•ç¨¿è€…å‘ã‘ãƒã‚§ãƒƒã‚¯ãƒªã‚¹ãƒˆ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
本書ã§ã¯ã€ãƒ‘ッãƒã‚’より素早ãå–り込んã§ã‚‚らã„ãŸã„開発者ãŒå®Ÿè·µã™ã¹ã基本的ãªäº‹æŸ„
-ã‚’ã„ãã¤ã‹ç´¹ä»‹ã—ã¾ã™ã€‚ã“ã“ã«ã‚ã‚‹å…¨ã¦ã®äº‹æŸ„ã¯ã€Documentation/SubmittingPatches
+ã‚’ã„ãã¤ã‹ç´¹ä»‹ã—ã¾ã™ã€‚ã“ã“ã«ã‚ã‚‹å…¨ã¦ã®äº‹æŸ„ã¯ã€Documentation/process/submitting-patches.rst
ãªã©ã®Linuxカーãƒãƒ«ãƒ‘ッãƒæŠ•ç¨¿ã«éš›ã—ã¦ã®å¿ƒå¾—を補足ã™ã‚‹ã‚‚ã®ã§ã™ã€‚
1: 妥当ãªCONFIGオプションや変更ã•ã‚ŒãŸCONFIGオプションã€ã¤ã¾ã‚Š =y, =m, =n
@@ -84,7 +84,7 @@ Linux カーãƒãƒ«ãƒ‘ッãƒæŠ•ç¨¿è€…å‘ã‘ãƒã‚§ãƒƒã‚¯ãƒªã‚¹ãƒˆ
å¿…ãšãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’追加ã—ã¦ãã ã•ã„。
17: æ–°ã—ã„ブートパラメータを追加ã—ãŸå ´åˆã«ã¯ã€
- å¿…ãšDocumentation/kernel-parameters.txt ã«èª¬æ˜Žã‚’追加ã—ã¦ãã ã•ã„。
+ å¿…ãšDocumentation/admin-guide/kernel-parameters.rst ã«èª¬æ˜Žã‚’追加ã—ã¦ãã ã•ã„。
18: æ–°ã—ãmoduleã«ãƒ‘ラメータを追加ã—ãŸå ´åˆã«ã¯ã€MODULE_PARM_DESC()ã‚’
利用ã—ã¦å¿…ãšãã®èª¬æ˜Žã‚’記述ã—ã¦ãã ã•ã„。
diff --git a/Documentation/ja_JP/SubmittingPatches b/Documentation/translations/ja_JP/SubmittingPatches
index 5d6ae639bfa0..02139656463e 100644
--- a/Documentation/ja_JP/SubmittingPatches
+++ b/Documentation/translations/ja_JP/SubmittingPatches
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/SubmittingPatches into Japanese.
+This is a version of Documentation/process/submitting-patches.rst into Japanese.
This document is maintained by Keiichi KII <k-keiichi@bx.jp.nec.com>
and the JF Project team <http://www.linux.or.jp/JF/>.
If you find any difference between this document and the original file
@@ -15,7 +15,7 @@ Last Updated: 2011/06/09
==================================
ã“ã‚Œã¯ã€
-linux-2.6.39/Documentation/SubmittingPatches ã®å’Œè¨³
+linux-2.6.39/Documentation/process/submitting-patches.rst ã®å’Œè¨³
ã§ã™ã€‚
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
翻訳日: 2011/06/09
@@ -34,9 +34,9 @@ Linux カーãƒãƒ«ã«å¤‰æ›´ã‚’加ãˆãŸã„ã¨æ€ã£ã¦ã„る個人åˆã¯ä¼šç¤¾ã
ãŠã˜ã‘ã¥ã‹ã›ã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚ã“ã®æ–‡ç« ã¯ã‚ãªãŸã®å¤‰æ›´ã‚’大ã„ã«å—ã‘入れ
ã¦ã‚‚らãˆã‚„ã™ãã™ã‚‹æ案を集ã‚ãŸã‚‚ã®ã§ã™ã€‚
-コードを投稿ã™ã‚‹å‰ã«ã€Documentation/SubmitChecklist ã®é …目リストã«ç›®
+コードを投稿ã™ã‚‹å‰ã«ã€Documentation/process/submit-checklist.rst ã®é …目リストã«ç›®
を通ã—ã¦ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。もã—ã‚ãªãŸãŒãƒ‰ãƒ©ã‚¤ãƒãƒ¼ã‚’投稿ã—よã†ã¨ã—
-ã¦ã„ã‚‹ãªã‚‰ã€Documentation/SubmittingDrivers ã«ã‚‚目を通ã—ã¦ãã ã•ã„。
+ã¦ã„ã‚‹ãªã‚‰ã€Documentation/process/submitting-drivers.rst ã«ã‚‚目を通ã—ã¦ãã ã•ã„。
--------------------------------------------
セクション1 パッãƒã®ä½œã‚Šæ–¹ã¨é€ã‚Šæ–¹
@@ -148,7 +148,7 @@ http://savannah.nongnu.org/projects/quilt
4) パッãƒã®ã‚¹ã‚¿ã‚¤ãƒ«ãƒã‚§ãƒƒã‚¯
ã‚ãªãŸã®ãƒ‘ッãƒãŒåŸºæœ¬çš„ãª( Linux カーãƒãƒ«ã®)コーディングスタイルã«é•åã—
-ã¦ã„ãªã„ã‹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ä¸‹ã•ã„。ãã®è©³ç´°ã‚’ Documentation/CodingStyle ã§
+ã¦ã„ãªã„ã‹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ä¸‹ã•ã„。ãã®è©³ç´°ã‚’ Documentation/process/coding-style.rst ã§
見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚コーディングスタイルã®é•åã¯ãƒ¬ãƒ“ューã™ã‚‹äººã®
時間を無駄ã«ã™ã‚‹ã ã‘ãªã®ã§ã€æらãã‚ãªãŸã®ãƒ‘ッãƒã¯èª­ã¾ã‚Œã‚‹ã“ã¨ã™ã‚‰ãªã
æ‹’å¦ã•ã‚Œã‚‹ã§ã—ょã†ã€‚
@@ -246,7 +246,7 @@ MIME å½¢å¼ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã¯ Linus ã«æ‰‹é–“ã‚’å–らã›ã‚‹ã“ã¨ã«ãªã‚
ã‚ã‚Œã°ã€èª°ã‹ãŒ MIME å½¢å¼ã®ãƒ‘ッãƒã‚’å†é€ã™ã‚‹ã‚ˆã†æ±‚ã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
余計ãªå¤‰æ›´ã‚’加ãˆãšã«ã‚ãªãŸã®ãƒ‘ッãƒã‚’é€ä¿¡ã™ã‚‹ãŸã‚ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®è¨­å®š
-ã®ãƒ’ントã«ã¤ã„ã¦ã¯ Documentation/email-clients.txt ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+ã®ãƒ’ントã«ã¤ã„ã¦ã¯ Documentation/process/email-clients.rst ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
8) é›»å­ãƒ¡ãƒ¼ãƒ«ã®ã‚µã‚¤ã‚º
@@ -609,7 +609,7 @@ diffstat ã®çµæžœã‚’生æˆã™ã‚‹ãŸã‚ã«ã€Œ git diff -M --stat --summary ã€ã‚
ã—例外をé©ç”¨ã™ã‚‹ã«ã¯ã€æœ¬å½“ã«å¦¥å½“ãªç†ç”±ãŒä¸å¯æ¬ ã§ã™ã€‚ã‚ãªãŸã¯æらãã“ã®
セクションを Linus ã®ã‚³ãƒ³ãƒ”ュータ・サイエンス101ã¨å‘¼ã¶ã§ã—ょã†ã€‚
-1) Documentation/CodingStyleã‚’å‚ç…§
+1) Documentation/process/coding-style.rstã‚’å‚ç…§
言ã†ã¾ã§ã‚‚ãªãã€ã‚ãªãŸã®ã‚³ãƒ¼ãƒ‰ãŒã“ã®ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰ã‚ã¾ã‚Šã«
も逸脱ã—ã¦ã„ã‚‹ã¨ã€ãƒ¬ãƒ“ューやコメントãªã—ã«å—ã‘å–ã£ã¦ã‚‚らãˆãªã„ã‹ã‚‚ã—
@@ -704,8 +704,8 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
<https://lkml.org/lkml/2005/7/11/336>
-Kernel Documentation/CodingStyle:
- <http://users.sosdg.org/~qiyong/lxr/source/Documentation/CodingStyle>
+Kernel Documentation/process/coding-style.rst:
+ <http://users.sosdg.org/~qiyong/lxr/source/Documentation/process/coding-style.rst>
Linus Torvalds's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
diff --git a/Documentation/ja_JP/stable_api_nonsense.txt b/Documentation/translations/ja_JP/stable_api_nonsense.txt
index 7653b5cbfed2..a3b40a4bdcfd 100644
--- a/Documentation/ja_JP/stable_api_nonsense.txt
+++ b/Documentation/translations/ja_JP/stable_api_nonsense.txt
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/stable_api_nonsense.txt into Japanese.
+This is a version of Documentation/process/stable-api-nonsense.rst into Japanese.
This document is maintained by IKEDA, Munehiro <m-ikeda@ds.jp.nec.com>
and the JF Project team <http://www.linux.or.jp/JF/>.
If you find any difference between this document and the original file
@@ -14,7 +14,7 @@ to update the original English file first.
Last Updated: 2007/07/18
==================================
ã“ã‚Œã¯ã€
-linux-2.6.22-rc4/Documentation/stable_api_nonsense.txt ã®å’Œè¨³
+linux-2.6.22-rc4/Documentation/process/stable-api-nonsense.rst ã®å’Œè¨³
ã§ã™ã€‚
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
翻訳日 : 2007/06/11
diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/translations/ja_JP/stable_kernel_rules.txt
index 9dbda9b5d21e..f9249aecba64 100644
--- a/Documentation/ja_JP/stable_kernel_rules.txt
+++ b/Documentation/translations/ja_JP/stable_kernel_rules.txt
@@ -1,5 +1,5 @@
NOTE:
-This is Japanese translated version of "Documentation/stable_kernel_rules.txt".
+This is Japanese translated version of "Documentation/process/stable-kernel-rules.rst".
This one is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
and JF Project team <www.linux.or.jp/JF>.
If you find difference with original file or problem in translation,
@@ -12,7 +12,7 @@ file at first.
==================================
ã“ã‚Œã¯ã€
-linux-2.6.29/Documentation/stable_kernel_rules.txt
+linux-2.6.29/Documentation/process/stable-kernel-rules.rst
ã®å’Œè¨³ã§ã™ã€‚
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
@@ -43,7 +43,7 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt
"ç†è«–çš„ã«ã¯ç«¶åˆçŠ¶æ…‹ã«ãªã‚‹"よã†ãªã‚‚ã®ã¯ä¸å¯ã€‚
- ã„ã‹ãªã‚‹äº›ç´°ãªä¿®æ­£ã‚‚å«ã‚ã‚‹ã“ã¨ã¯ã§ããªã„。(スペルã®ä¿®æ­£ã€ç©ºç™½ã®ã‚¯ãƒªãƒ¼
ンアップãªã©)
- - Documentation/SubmittingPatches ã®è¦å‰‡ã«å¾“ã£ãŸã‚‚ã®ã§ãªã‘ã‚Œã°ãªã‚‰ãªã„。
+ - Documentation/process/submitting-patches.rst ã®è¦å‰‡ã«å¾“ã£ãŸã‚‚ã®ã§ãªã‘ã‚Œã°ãªã‚‰ãªã„。
- パッãƒè‡ªä½“ã‹åŒç­‰ã®ä¿®æ­£ãŒ Linus ã®ãƒ„リーã«æ—¢ã«å­˜åœ¨ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„。
  Linus ã®ãƒ„リーã§ã®ã‚³ãƒŸãƒƒãƒˆID ã‚’ -stable ã¸ã®ãƒ‘ッãƒæŠ•ç¨¿ã®éš›ã«å¼•ç”¨ã™
ã‚‹ã“ã¨ã€‚
diff --git a/Documentation/ko_KR/HOWTO b/Documentation/translations/ko_KR/howto.rst
index 9a3e65924d54..3b0c15b277e0 100644
--- a/Documentation/ko_KR/HOWTO
+++ b/Documentation/translations/ko_KR/howto.rst
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/HOWTO translated into korean
+This is a version of Documentation/process/howto.rst translated into korean
This document is maintained by Minchan Kim <minchan@kernel.org>
If you find any difference between this document and the original file or
a problem with the translation, please contact the maintainer of this file.
@@ -9,17 +9,20 @@ read for non English (read: korean) speakers and is not intended as
a fork. So if you have any comments or updates for this file please
try to update the original English file first.
-==================================
+----------------------------------
+
ì´ ë¬¸ì„œëŠ”
-Documentation/HOWTO
+Documentation/process/howto.rst
ì˜ í•œê¸€ 번역입니다.
ì—­ìžï¼š 김민찬 <minchan@kernel.org>
ê°ìˆ˜ï¼š ì´ì œì´ë¯¸ <jamee.lee@samsung.com>
-==================================
+
+----------------------------------
+
어떻게 리눅스 ì»¤ë„ ê°œë°œì„ í•˜ëŠ”ê°€
----------------------------------
+================================
ì´ ë¬¸ì„œëŠ” ì»¤ë„ ê°œë°œì— ìžˆì–´ 가장 중요한 문서ì´ë‹¤. ì´ ë¬¸ì„œëŠ”
리눅스 ì»¤ë„ ê°œë°œìžê°€ ë˜ëŠ” 법과 리눅스 ì»¤ë„ ê°œë°œ 커뮤니티와 ì¼í•˜ëŠ”
@@ -46,6 +49,7 @@ Documentation/HOWTO
어셈블리(특정 아키í…ì³)는 잘 알아야 í•  필요는 없다.
다ìŒì˜ 참고서ì ë“¤ì€ ê¸°ë³¸ì— ì¶©ì‹¤í•œ C êµìœ¡ì´ë‚˜ ìˆ˜ë…„ê°„ì˜ ê²½í—˜ì— ê²¬ì£¼ì§€ëŠ”
못하지만 ì ì–´ë„ 참고 ìš©ë„로는 ì¢‹ì„ ê²ƒì´ë‹¤
+
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
- "Practical C Programming" by Steve Oualline [O'Reilly]
- "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
@@ -79,7 +83,8 @@ Documentation/HOWTO
ê·¸ë“¤ì˜ ë§ì— ì˜ì§€í•´ì„œëŠ” 안ëœë‹¤.
GPLì— ê´€í•œ ìž¦ì€ ì§ˆë¬¸ë“¤ê³¼ ë‹µë³€ë“¤ì€ ë‹¤ìŒì„ 참조하ë¼.
- http://www.gnu.org/licenses/gpl-faq.html
+
+ https://www.gnu.org/licenses/gpl-faq.html
문서
@@ -93,55 +98,61 @@ GPLì— ê´€í•œ ìž¦ì€ ì§ˆë¬¸ë“¤ê³¼ ë‹µë³€ë“¤ì€ ë‹¤ìŒì„ 참조하ë¼.
mtk.manpages@gmail.comì˜ ë©”ì¸í…Œì´ë„ˆì—게 보낼 ê²ƒì„ ê¶Œìž¥í•œë‹¤.
다ìŒì€ ì»¤ë„ ì†ŒìŠ¤ íŠ¸ë¦¬ì— ìžˆëŠ” ì½ì–´ì•¼ í•  파ì¼ë“¤ì˜ 리스트ì´ë‹¤.
+
README
ì´ íŒŒì¼ì€ 리눅스 커ë„ì— ê´€í•˜ì—¬ 간단한 ë°°ê²½ 설명과 커ë„ì„ ì„¤ì •í•˜ê³ 
빌드하기 위해 필요한 ê²ƒì„ ì„¤ëª…í•œë‹¤. 커ë„ì— ìž…ë¬¸í•˜ëŠ” ì‚¬ëžŒë“¤ì€ ì—¬ê¸°ì„œ
시작해야 한다.
- Documentation/Changes
+ :ref:`Documentation/process/changes.rst <changes>`
ì´ íŒŒì¼ì€ 커ë„ì„ ì„±ê³µì ìœ¼ë¡œ 빌드하고 실행시키기 위해 필요한 다양한
소프트웨어 íŒ¨í‚¤ì§€ë“¤ì˜ ìµœì†Œ ë²„ì ¼ì„ ë‚˜ì—´í•œë‹¤.
- Documentation/CodingStyle
+ :ref:`Documentation/process/coding-style.rst <codingstyle>`
ì´ ë¬¸ì„œëŠ” 리눅스 ì»¤ë„ ì½”ë”© 스타ì¼ê³¼ 그렇게 í•œ 몇몇 ì´ìœ ë¥¼ 설명한다.
모든 새로운 코드는 ì´ ë¬¸ì„œì— ê°€ì´ë“œë¼ì¸ë“¤ì„ ë”°ë¼ì•¼ 한다. 대부분ì˜
ë©”ì¸í…Œì´ë„ˆë“¤ì€ ì´ ê·œì¹™ì„ ë”°ë¥´ëŠ” íŒ¨ì¹˜ë“¤ë§Œì„ ë°›ì•„ë“¤ì¼ ê²ƒì´ê³  ë§Žì€ ì‚¬ëžŒë“¤ì´
ê·¸ 패치가 올바른 스타ì¼ì¼ 경우만 코드를 검토할 것ì´ë‹¤.
- Documentation/SubmittingPatches
- Documentation/SubmittingDrivers
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` 와 :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
ì´ íŒŒì¼ë“¤ì€ 성공ì ìœ¼ë¡œ 패치를 만들고 보내는 ë²•ì„ ë‹¤ìŒì˜ 내용들로
굉장히 ìƒì„¸ížˆ 설명하고 있다(그러나 다ìŒìœ¼ë¡œ 한정ë˜ì§„ 않는다).
+
- Email 내용들
- Email ì–‘ì‹
- ê·¸ê²ƒì„ ëˆ„êµ¬ì—게 보낼지
+
ì´ëŸ¬í•œ ê·œì¹™ë“¤ì„ ë”°ë¥´ëŠ” ê²ƒì´ ì„±ê³µ(ì—­ìžì£¼: 패치가 받아들여 지는 것)ì„
보장하진 않는다(왜ëƒí•˜ë©´ 모든 íŒ¨ì¹˜ë“¤ì€ ë‚´ìš©ê³¼ 스타ì¼ì— 관하여
면밀히 검토ë˜ê¸° 때문ì´ë‹¤). 그러나 ê·œì¹™ì„ ë”°ë¥´ì§€ 않는다면 ê±°ì˜
ì„±ê³µí•˜ì§€ë„ ëª»í•  것ì´ë‹¤.
올바른 íŒ¨ì¹˜ë“¤ì„ ë§Œë“œëŠ” ë²•ì— ê´€í•œ 훌륭한 다른 ë¬¸ì„œë“¤ì´ ìžˆë‹¤.
+
"The Perfect Patch"
- http://www.ozlabs.org/~akpm/stuff/tpp.txt
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
- Documentation/stable_api_nonsense.txt
+ :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
ì´ ë¬¸ì„œëŠ” ì˜ë„ì ìœ¼ë¡œ 커ë„ì´ ë¶ˆë³€í•˜ëŠ” API를 갖지 ì•Šë„ë¡ ê²°ì •í•œ
ì´ìœ ë¥¼ 설명하며 다ìŒê³¼ ê°™ì€ ê²ƒë“¤ì„ í¬í•¨í•œë‹¤.
+
- 서브시스템 shim-layer(í˜¸í™˜ì„±ì„ ìœ„í•´?)
- ìš´ì˜ì²´ì œë“¤ê°„ì˜ ë“œë¼ì´ë²„ ì´ì‹ì„±
- ì»¤ë„ ì†ŒìŠ¤ íŠ¸ë¦¬ë‚´ì— ë¹ ë¥¸ 변화를 늦추는 것(ë˜ëŠ” 빠른 변화를 막는 것)
+
ì´ ë¬¸ì„œëŠ” 리눅스 개발 ì² í•™ì„ ì´í•´í•˜ëŠ”ë° í•„ìˆ˜ì ì´ë©° 다른 ìš´ì˜ì²´ì œì—ì„œ
리눅스로 전향하는 사람들ì—게는 매우 중요하다.
- Documentation/SecurityBugs
+ :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
ì—¬ëŸ¬ë¶„ë“¤ì´ ë¦¬ëˆ…ìŠ¤ 커ë„ì˜ ë³´ì•ˆ 문제를 발견했다고 ìƒê°í•œë‹¤ë©´ ì´ ë¬¸ì„œì—
나온 ë‹¨ê³„ì— ë”°ë¼ì„œ ì»¤ë„ ê°œë°œìžë“¤ì—게 알리고 ê·¸ 문제를 í•´ê²°í•  수 있ë„ë¡
ë„와 달ë¼.
- Documentation/ManagementStyle
+ :ref:`Documentation/process/management-style.rst <managementstyle>`
ì´ ë¬¸ì„œëŠ” 리눅스 ì»¤ë„ ë©”ì¸í…Œì´ë„ˆë“¤ì´ ê·¸ë“¤ì˜ ë°©ë²•ë¡ ì— ë…¹ì•„ 있는
ì •ì‹ ì„ ì–´ë–»ê²Œ 공유하고 ìš´ì˜í•˜ëŠ”지를 설명한다. ì´ê²ƒì€ ì»¤ë„ ê°œë°œì— ìž…ë¬¸í•˜ëŠ”
모든 사람들(ë˜ëŠ” ì»¤ë„ ê°œë°œì— ìž‘ì€ í˜¸ê¸°ì‹¬ì´ë¼ë„ 있는 사람들)ì´
@@ -149,38 +160,52 @@ mtk.manpages@gmail.comì˜ ë©”ì¸í…Œì´ë„ˆì—게 보낼 ê²ƒì„ ê¶Œìž¥í•œë‹¤.
ë…특한 í–‰ë™ì— 관하여 í”히 있는 오해들과 í˜¼ëž€ë“¤ì„ í•´ì†Œí•˜ê³  있기
때문ì´ë‹¤.
- Documentation/stable_kernel_rules.txt
+ :ref:`Documentation/process/stable_kernel_rules.rst <stable_kernel_rules>`
ì´ ë¬¸ì„œëŠ” 안정ì ì¸ ì»¤ë„ ë°°í¬ê°€ ì´ë£¨ì–´ì§€ëŠ” ê·œì¹™ì„ ì„¤ëª…í•˜ê³  있으며
ì—¬ëŸ¬ë¶„ë“¤ì´ ì´ëŸ¬í•œ ë°°í¬ë“¤ 중 í•˜ë‚˜ì— ë³€ê²½ì„ í•˜ê¸¸ ì›í•œë‹¤ë©´
ë¬´ì—‡ì„ í•´ì•¼ 하는지를 설명한다.
- Documentation/kernel-docs.txt
+ :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
ì»¤ë„ ê°œë°œì— ê´€ê³„ëœ ì™¸ë¶€ ë¬¸ì„œì˜ ë¦¬ìŠ¤íŠ¸ì´ë‹¤. ì»¤ë„ ë‚´ì˜ í¬í•¨ëœ 문서들
ì¤‘ì— ì—¬ëŸ¬ë¶„ì´ ì°¾ê³  ì‹¶ì€ ë¬¸ì„œë¥¼ 발견하지 못할 경우 ì´ ë¦¬ìŠ¤íŠ¸ë¥¼
살펴보ë¼.
- Documentation/applying-patches.txt
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>`
패치가 무엇ì´ë©° ê·¸ê²ƒì„ ì»¤ë„ì˜ ë‹¤ë¥¸ 개발 ë¸Œëžœì¹˜ë“¤ì— ì–´ë–»ê²Œ
ì ìš©í•˜ëŠ”ì§€ì— ê´€í•˜ì—¬ ìžì„¸ížˆ 설명하고 있는 ì¢‹ì€ ìž…ë¬¸ì„œì´ë‹¤.
-커ë„ì€ ì†ŒìŠ¤ 코드 ê·¸ ìžì²´ì—ì„œ ìžë™ì ìœ¼ë¡œ 만들어질 수 있는 ë§Žì€ ë¬¸ì„œë“¤ì„
-가지고 있다. ì´ê²ƒì€ ì»¤ë„ ë‚´ì˜ APIì— ëŒ€í•œ 모든 설명, 그리고 ë½í‚¹ì„
-올바르게 처리하는 ë²•ì— ê´€í•œ ê·œì¹™ì„ í¬í•¨í•˜ê³  있다. ì´ ë¬¸ì„œëŠ”
-Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, HTML,
-그리고 man 페ì´ì§€ë“¤ë¡œ 다ìŒê³¼ ê°™ì´ ì‹¤í–‰í•˜ì—¬ 만들어 진다.
+커ë„ì€ ì†ŒìŠ¤ 코드 ê·¸ ìžì²´ì—ì„œ ë˜ëŠ” ì´ê²ƒê³¼ ê°™ì€ ReStructuredText 마í¬ì—… (ReST) ì„
+통해 ìžë™ì ìœ¼ë¡œ 만들어질 수 있는 ë§Žì€ ë¬¸ì„œë“¤ì„ ê°€ì§€ê³  있다. ì´ê²ƒì€ ì»¤ë„ ë‚´ì˜
+APIì— ëŒ€í•œ 모든 설명, 그리고 ë½í‚¹ì„ 올바르게 처리하는 ë²•ì— ê´€í•œ ê·œì¹™ì„ í¬í•¨í•˜ê³ 
+있다.
+
+모든 그런 ë¬¸ì„œë“¤ì€ ì»¤ë„ ì†ŒìŠ¤ 디렉토리ì—ì„œ ë‹¤ìŒ ì»¤ë§¨ë“œë¥¼ 실행하는 ê²ƒì„ í†µí•´ PDF
+나 HTML ì˜ í˜•íƒœë¡œ 만들어질 수 있다::
+
make pdfdocs
- make psdocs
make htmldocs
- make mandocs
-ê°ê°ì˜ ëª…ë ¹ì„ ë©”ì¸ ì»¤ë„ ì†ŒìŠ¤ 디렉토리로부터 실행한다.
+ReST 마í¬ì—…ì„ ì‚¬ìš©í•˜ëŠ” ë¬¸ì„œë“¤ì€ Documentation/output ì— ìƒì„±ëœë‹¤. 해당
+ë¬¸ì„œë“¤ì€ ë‹¤ìŒì˜ 커맨드를 사용하면 LaTeX ì´ë‚˜ ePub ë¡œë„ ë§Œë“¤ì–´ì§ˆ 수 있다::
+
+ make latexdocs
+ make epubdocs
+
+현재, ReST ë¡œì˜ ë³€í™˜ì´ ì§„í–‰ì¤‘ì¸, DocBook 으로 ì“°ì¸ ë¬¸ì„œë“¤ì´ ì¡´ìž¬í•œë‹¤. 그런
+ë¬¸ì„œë“¤ì€ Documentation/DocBook/ 디렉토리 ì•ˆì— ìƒì„±ë  것ì´ê³  ë‹¤ìŒ ì»¤ë§¨ë“œë¥¼ 통해
+Postscript 나 man page ë¡œë„ ë§Œë“¤ì–´ì§ˆ 수 있다::
+
+ make psdocs
+ make mandocs
ì»¤ë„ ê°œë°œìžê°€ ë˜ëŠ” 것
---------------------
ì—¬ëŸ¬ë¶„ì´ ë¦¬ëˆ…ìŠ¤ ì»¤ë„ ê°œë°œì— ê´€í•˜ì—¬ ì•„ë¬´ê²ƒë„ ëª¨ë¥¸ë‹¤ë©´ Linux KernelNewbies
프로ì íŠ¸ë¥¼ ë´ì•¼ 한다.
- http://kernelnewbies.org
+
+ https://kernelnewbies.org
+
ê·¸ê³³ì€ ê±°ì˜ ëª¨ë“  ì¢…ë¥˜ì˜ ê¸°ë³¸ì ì¸ ì»¤ë„ ê°œë°œ 질문들(질문하기 ì „ì— ë¨¼ì €
ì•„ì¹´ì´ë¸Œë¥¼ 찾아ë´ë¼. ê³¼ê±°ì— ì´ë¯¸ 답변ë˜ì—ˆì„ ìˆ˜ë„ ìžˆë‹¤)ì„ í•  수 있는 ë„움ì´
ë ë§Œí•œ ë©”ì¼ë§ 리스트가 있다. ë˜í•œ 실시간으로 질문 í•  수 있는 IRC 채ë„ë„
@@ -192,7 +217,9 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
ì—¬ëŸ¬ë¶„ì´ ì–´ë””ì„œ 시작해야 할진 모르지만 ì»¤ë„ ê°œë°œ ì»¤ë®¤ë‹ˆí‹°ì— ì°¸ì—¬í•  수
있는 ì¼ë“¤ì„ 찾길 ì›í•œë‹¤ë©´ 리눅스 ì»¤ë„ Janitor 프로ì íŠ¸ë¥¼ 살펴ë´ë¼.
- http://kernelnewbies.org/KernelJanitors
+
+ https://kernelnewbies.org/KernelJanitors
+
ê·¸ê³³ì€ ì‹œìž‘í•˜ê¸°ì— í›Œë¥­í•œ 장소ì´ë‹¤. ê·¸ê³³ì€ ë¦¬ëˆ…ìŠ¤ ì»¤ë„ ì†ŒìŠ¤ 트리내ì—
간단히 정리ë˜ê³  ìˆ˜ì •ë  ìˆ˜ 있는 ë¬¸ì œë“¤ì— ê´€í•˜ì—¬ 설명한다. ì—¬ëŸ¬ë¶„ì€ ì´
프로ì íŠ¸ë¥¼ 대표하는 개발ìžë“¤ê³¼ ì¼í•˜ë©´ì„œ ìžì‹ ì˜ 패치를 리눅스 ì»¤ë„ íŠ¸ë¦¬ì—
@@ -204,7 +231,8 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
올바른 í¬ë§·ìœ¼ë¡œ í¬ìž¥í•˜ëŠ”ë° ë„ì›€ì´ í•„ìš”í•˜ë‹¤ë©´ 그러한 문제를 ë•ê¸° 위해
만들어진 kernel-mentors 프로ì íŠ¸ê°€ 있다. ê·¸ê³³ì€ ë©”ì¼ë§ 리스트ì´ë©°
다ìŒì—ì„œ 참조할 수 있다.
- http://selenic.com/mailman/listinfo/kernel-mentors
+
+ https://selenic.com/mailman/listinfo/kernel-mentors
리눅스 ì»¤ë„ ì½”ë“œì— ì‹¤ì œ ë³€ê²½ì„ í•˜ê¸° ì „ì— ë°˜ë“œì‹œ ê·¸ 코드가 어떻게
ë™ìž‘하는지 ì´í•´í•˜ê³  있어야 한다. 코드를 분ì„하기 위하여 특정한 툴ì˜
@@ -213,6 +241,7 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
ê²ƒì€ Linux Cross-Reference projectì´ë©° ê·¸ê²ƒì€ ìžê¸° 참조 ë°©ì‹ì´ë©°
소스코드를 ì¸ë±ìŠ¤ëœ 웹 페ì´ì§€ë“¤ì˜ 형태로 보여준다. ìµœì‹ ì˜ ë©‹ì§„ 커ë„
코드 저장소는 다ìŒì„ 통하여 참조할 수 있다.
+
http://lxr.free-electrons.com/
@@ -222,6 +251,7 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
리눅스 ì»¤ë„ ê°œë°œ 프로세스는 현재 몇몇 다른 ë©”ì¸ ì»¤ë„ "브랜치들"ê³¼
ì„œë¸Œì‹œìŠ¤í…œì— íŠ¹í™”ëœ ì»¤ë„ ë¸Œëžœì¹˜ë“¤ë¡œ 구성ëœë‹¤. 몇몇 다른 ë©”ì¸
ë¸Œëžœì¹˜ë“¤ì€ ë‹¤ìŒê³¼ 같다.
+
- main 4.x ì»¤ë„ íŠ¸ë¦¬
- 4.x.y - ì•ˆì •ëœ ì»¤ë„ íŠ¸ë¦¬
- 4.x -git ì»¤ë„ íŒ¨ì¹˜ë“¤
@@ -229,15 +259,16 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
- 4.x - 통합 테스트를 위한 next ì»¤ë„ íŠ¸ë¦¬
4.x ì»¤ë„ íŠ¸ë¦¬
----------------
+~~~~~~~~~~~~~
+
+4.x 커ë„ë“¤ì€ Linus Torvaldsê°€ 관리하며 https://kernel.org ì˜
+pub/linux/kernel/v4.x/ 디렉토리ì—ì„œ ì°¸ì¡°ë  ìˆ˜ 있다.개발 프로세스는 다ìŒê³¼ 같다.
-4.x 커ë„ë“¤ì€ Linux Torvaldsê°€ 관리하며 kernel.orgì˜ pub/linux/kernel/v4.x/
-디렉토리ì—ì„œ ì°¸ì¡°ë  ìˆ˜ 있다.개발 프로세스는 다ìŒê³¼ 같다.
- 새로운 커ë„ì´ ë°°í¬ë˜ìžë§ˆìž 2ì£¼ì˜ ì‹œê°„ì´ ì£¼ì–´ì§„ë‹¤. ì´ ê¸°ê°„ë™ì€
ë©”ì¸í…Œì´ë„ˆë“¤ì€ í° diffë“¤ì„ Linusì—게 제출할 수 있다. 대개 ì´ íŒ¨ì¹˜ë“¤ì€
몇 주 ë™ì•ˆ -next 커ë„ë‚´ì— ì´ë¯¸ ìžˆì—ˆë˜ ê²ƒë“¤ì´ë‹¤. í° ë³€ê²½ë“¤ì„ ì œì¶œí•˜ëŠ” ë°
선호ë˜ëŠ” ë°©ë²•ì€ git(커ë„ì˜ ì†ŒìŠ¤ 관리 툴, ë” ë§Žì€ ì •ë³´ë“¤ì€
- http://git-scm.com/ ì—ì„œ 참조할 수 있다)를 사용하는 것ì´ì§€ë§Œ 순수한
+ https://git-scm.com/ ì—ì„œ 참조할 수 있다)를 사용하는 것ì´ì§€ë§Œ 순수한
패치파ì¼ì˜ 형ì‹ìœ¼ë¡œ 보내는 ê²ƒë„ ë¬´ê´€í•˜ë‹¤.
- 2주 í›„ì— -rc1 커ë„ì´ ë°°í¬ë˜ë©° 지금부터는 ì „ì²´ 커ë„ì˜ ì•ˆì •ì„±ì— ì˜í–¥ì„
미칠수 있는 새로운 ê¸°ëŠ¥ë“¤ì„ í¬í•¨í•˜ì§€ 않는 íŒ¨ì¹˜ë“¤ë§Œì´ ì¶”ê°€ë  ìˆ˜ 있다.
@@ -256,12 +287,13 @@ Documentation/DocBook/ 디렉토리 ë‚´ì—ì„œ 만들어지며 PDF, Postscript, H
ì»¤ë„ ë°°í¬ì— 있어서 언급할만한 가치가 있는 리눅스 ì»¤ë„ ë©”ì¼ë§ 리스트ì˜
Andrew Mortonì˜ ê¸€ì´ ìžˆë‹¤.
- "커ë„ì´ ì–¸ì œ ë°°í¬ë ì§€ëŠ” ì•„ë¬´ë„ ëª¨ë¥¸ë‹¤. 왜ëƒí•˜ë©´ ë°°í¬ëŠ” 알려진
+
+ *"커ë„ì´ ì–¸ì œ ë°°í¬ë ì§€ëŠ” ì•„ë¬´ë„ ëª¨ë¥¸ë‹¤. 왜ëƒí•˜ë©´ ë°°í¬ëŠ” 알려진
ë²„ê·¸ì˜ ìƒí™©ì— ë”°ë¼ ë°°í¬ë˜ëŠ” 것ì´ì§€ 미리정해 ë†“ì€ ì‹œê°„ì— ë”°ë¼
- ë°°í¬ë˜ëŠ” ê²ƒì€ ì•„ë‹ˆê¸° 때문ì´ë‹¤."
+ ë°°í¬ë˜ëŠ” ê²ƒì€ ì•„ë‹ˆê¸° 때문ì´ë‹¤."*
4.x.y - 안정 ì»¤ë„ íŠ¸ë¦¬
-------------------------
+~~~~~~~~~~~~~~~~~~~~~~
3 ìžë¦¬ 숫ìžë¡œ ì´ë£¨ì–´ì§„ ë²„ì ¼ì˜ ì»¤ë„ë“¤ì€ -stable 커ë„들ì´ë‹¤. ê·¸ê²ƒë“¤ì€ 4.x
커ë„ì—ì„œ ë°œê²¬ëœ í° íšŒê·€ë“¤ì´ë‚˜ 보안 문제들 중 비êµì  ìž‘ê³  중요한 수정들ì„
@@ -276,20 +308,21 @@ Andrew Mortonì˜ ê¸€ì´ ìžˆë‹¤.
4.x.y는 "stable" 팀<stable@vger.kernel.org>ì— ì˜í•´ 관리ë˜ë©° ê±°ì˜ ë§¤ë²ˆ 격주로
ë°°í¬ëœë‹¤.
-ì»¤ë„ íŠ¸ë¦¬ 문서들 ë‚´ì— Documentation/stable_kernel_rules.txt 파ì¼ì€ ì–´ë–¤
+ì»¤ë„ íŠ¸ë¦¬ 문서들 ë‚´ì— Documentation/process/stable-kernel-rules.rst 파ì¼ì€ ì–´ë–¤
ì¢…ë¥˜ì˜ ë³€ê²½ë“¤ì´ -stable 트리로 들어왔는지와 ë°°í¬ í”„ë¡œì„¸ìŠ¤ê°€ 어떻게
진행ë˜ëŠ”지를 설명한다.
-
4.x -git 패치들
-------------------
+~~~~~~~~~~~~~~~
+
git 저장소(그러므로 -gitì´ë¼ëŠ” ì´ë¦„ì´ ë¶™ìŒ)ì—는 날마다 관리ë˜ëŠ” Linusì˜
ì»¤ë„ íŠ¸ë¦¬ì˜ snapshot ë“¤ì´ ìžˆë‹¤. ì´ íŒ¨ì¹˜ë“¤ì€ ì¼ë°˜ì ìœ¼ë¡œ 날마다 ë°°í¬ë˜ë©°
Linusì˜ íŠ¸ë¦¬ì˜ í˜„ìž¬ ìƒíƒœë¥¼ 나타낸다. ì´ íŒ¨ì¹˜ë“¤ì€ ì •ìƒì ì¸ì§€ 조금ë„
살펴보지 ì•Šê³  ìžë™ì ìœ¼ë¡œ ìƒì„±ëœ 것ì´ë¯€ë¡œ -rc 커ë„들 ë³´ë‹¤ë„ ë” ì‹¤í—˜ì ì´ë‹¤.
서브시스템 ì»¤ë„ íŠ¸ë¦¬ë“¤ê³¼ 패치들
--------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
다양한 ì»¤ë„ ì„œë¸Œì‹œìŠ¤í…œì˜ ë©”ì¸í…Œì´ë„ˆë“¤ --- 그리고 ë§Žì€ ì»¤ë„ ì„œë¸Œì‹œìŠ¤í…œ 개발ìžë“¤
--- ì€ ê·¸ë“¤ì˜ í˜„ìž¬ 개발 ìƒíƒœë¥¼ 소스 저장소로 노출한다. ì´ë¥¼ 통해 다른 사람들ë„
커ë„ì˜ ë‹¤ë¥¸ ì˜ì—­ì— ì–´ë–¤ 변화가 ì´ë£¨ì–´ì§€ê³  있는지 ì•Œ 수 있다. 급ì†ížˆ 개발ì´
@@ -300,35 +333,39 @@ Linusì˜ íŠ¸ë¦¬ì˜ í˜„ìž¬ ìƒíƒœë¥¼ 나타낸다. ì´ íŒ¨ì¹˜ë“¤ì€ ì •ìƒì ì¸ì
ëŒ€ë¶€ë¶„ì˜ ì´ëŸ¬í•œ 저장소는 git 트리지만, gitì´ ì•„ë‹Œ SCM으로 관리ë˜ê±°ë‚˜, quilt
시리즈로 제공ë˜ëŠ” íŒ¨ì¹˜ë“¤ë„ ì¡´ìž¬í•œë‹¤. ì´ëŸ¬í•œ 서브시스템 ì €ìž¥ì†Œë“¤ì€ MAINTAINERS
-파ì¼ì— 나열ë˜ì–´ 있다. ëŒ€ë¶€ë¶„ì€ http://git.kernel.org ì—ì„œ ë³¼ 수 있다.
+파ì¼ì— 나열ë˜ì–´ 있다. ëŒ€ë¶€ë¶„ì€ https://git.kernel.org ì—ì„œ ë³¼ 수 있다.
ì œì•ˆëœ íŒ¨ì¹˜ëŠ” 서브시스템 íŠ¸ë¦¬ì— ì»¤ë°‹ë˜ê¸° ì „ì— ë©”ì¼ë§ 리스트를 통해
리뷰ëœë‹¤(ì•„ëž˜ì˜ ê´€ë ¨ ì„¹ì…˜ì„ ì°¸ê³ í•˜ê¸° 바란다). ì¼ë¶€ ì»¤ë„ ì„œë¸Œì‹œìŠ¤í…œì˜ ê²½ìš°, ì´
리뷰 프로세스는 patchworkë¼ëŠ” ë„구를 통해 추ì ëœë‹¤. patchworkì€ ë“±ë¡ëœ 패치와
íŒ¨ì¹˜ì— ëŒ€í•œ 코멘트, íŒ¨ì¹˜ì˜ ë²„ì „ì„ ë³¼ 수 있는 웹 ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 제공하고,
ë©”ì¸í…Œì´ë„ˆëŠ” 패치를 리뷰 중, 리뷰 통과, ë˜ëŠ” 반려ë¨ìœ¼ë¡œ 표시할 수 있다.
-ëŒ€ë¶€ë¶„ì˜ ì´ëŸ¬í•œ patchwork 사ì´íŠ¸ëŠ” http://patchwork.kernel.org/ ë˜ëŠ”
+ëŒ€ë¶€ë¶„ì˜ ì´ëŸ¬í•œ patchwork 사ì´íŠ¸ëŠ” https://patchwork.kernel.org/ ë˜ëŠ”
http://patchwork.ozlabs.org/ ì— ë‚˜ì—´ë˜ì–´ 있다.
4.x - 통합 테스트를 위한 next ì»¤ë„ íŠ¸ë¦¬
------------------------------------------
+---------------------------------------
서브시스템 íŠ¸ë¦¬ë“¤ì˜ ë³€ê²½ì‚¬í•­ë“¤ì€ mainline 4.x 트리로 들어오기 ì „ì— í†µí•©
테스트를 ê±°ì³ì•¼ 한다. ì´ëŸ° 목ì ìœ¼ë¡œ, 모든 서브시스템 íŠ¸ë¦¬ì˜ ë³€ê²½ì‚¬í•­ì„ ê±°ì˜
ë§¤ì¼ ë°›ì•„ê°€ëŠ” 특수한 테스트 저장소가 존재한다:
- http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+
+ https://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
ì´ëŸ° ì‹ìœ¼ë¡œ, -next 커ë„ì„ í†µí•´ ë‹¤ìŒ ë¨¸ì§€ ê¸°ê°„ì— ë©”ì¸ë¼ì¸ 커ë„ì— ì–´ë–¤ 변경ì´
가해질 것ì¸ì§€ 간략히 ì•Œ 수 있다. 모험심 ê°•í•œ 테스터ë¼ë©´ -next 커ë„ì—ì„œ 테스트를
수행하는 ê²ƒë„ ì¢‹ì„ ê²ƒì´ë‹¤.
+
버그 보고
---------
-bugzilla.kernel.org는 리눅스 ì»¤ë„ ê°œë°œìžë“¤ì´ 커ë„ì˜ ë²„ê·¸ë¥¼ 추ì í•˜ëŠ” ê³³ì´ë‹¤.
-사용ìžë“¤ì€ 발견한 모든 ë²„ê·¸ë“¤ì„ ë³´ê³ í•˜ê¸° 위하여 ì´ íˆ´ì„ ì‚¬ìš©í•  ê²ƒì„ ê¶Œìž¥í•œë‹¤.
-kernel bugzilla를 사용하는 ìžì„¸í•œ ë°©ë²•ì€ ë‹¤ìŒì„ 참조하ë¼.
- http://test.kernel.org/bugzilla/faq.html
-ë©”ì¸ ì»¤ë„ ì†ŒìŠ¤ ë””ë ‰í† ë¦¬ì— ìžˆëŠ” REPORTING-BUGS 파ì¼ì€ ì»¤ë„ ë²„ê·¸ë¼ê³  ìƒê°ë˜ëŠ”
+https://bugzilla.kernel.org는 리눅스 ì»¤ë„ ê°œë°œìžë“¤ì´ 커ë„ì˜ ë²„ê·¸ë¥¼ 추ì í•˜ëŠ”
+ê³³ì´ë‹¤. 사용ìžë“¤ì€ 발견한 모든 ë²„ê·¸ë“¤ì„ ë³´ê³ í•˜ê¸° 위하여 ì´ íˆ´ì„ ì‚¬ìš©í•  것ì„
+권장한다. kernel bugzilla를 사용하는 ìžì„¸í•œ ë°©ë²•ì€ ë‹¤ìŒì„ 참조하ë¼.
+
+ https://bugzilla.kernel.org/page.cgi?id=faq.html
+
+ë©”ì¸ ì»¤ë„ ì†ŒìŠ¤ ë””ë ‰í† ë¦¬ì— ìžˆëŠ” admin-guide/reporting-bugs.rst 파ì¼ì€ ì»¤ë„ ë²„ê·¸ë¼ê³  ìƒê°ë˜ëŠ”
ê²ƒì„ ë³´ê³ í•˜ëŠ” ë°©ë²•ì— ê´€í•œ ì¢‹ì€ í…œí”Œë¦¿ì´ë©° 문제를 추ì í•˜ê¸° 위해서 커ë„
개발ìžë“¤ì´ 필요로 하는 ì •ë³´ê°€ 무엇들ì¸ì§€ë¥¼ ìƒì„¸ížˆ 설명하고 있다.
@@ -344,13 +381,14 @@ kernel bugzilla를 사용하는 ìžì„¸í•œ ë°©ë²•ì€ ë‹¤ìŒì„ 참조하ë¼.
ì ìˆ˜ë¥¼ ì–»ì„ ìˆ˜ 있는 가장 ì¢‹ì€ ë°©ë²•ì¤‘ì˜ í•˜ë‚˜ì´ë‹¤. 왜ëƒí•˜ë©´ ë§Žì€ ì‚¬ëžŒë“¤ì€
다른 ì‚¬ëžŒë“¤ì˜ ë²„ê·¸ë“¤ì„ ìˆ˜ì •í•˜ê¸° 위하여 ì‹œê°„ì„ ë‚­ë¹„í•˜ì§€ 않기 때문ì´ë‹¤.
-ì´ë¯¸ ë³´ê³ ëœ ë²„ê·¸ 리í¬íŠ¸ë“¤ì„ 가지고 작업하기 위해서 http://bugzilla.kernel.org를
-참조하ë¼. ì—¬ëŸ¬ë¶„ì´ ì•žìœ¼ë¡œ ìƒê²¨ë‚  버그 리í¬íŠ¸ë“¤ì˜ ì¡°ì–¸ìžê°€ ë˜ê¸¸ ì›í•œë‹¤ë©´
+ì´ë¯¸ ë³´ê³ ëœ ë²„ê·¸ 리í¬íŠ¸ë“¤ì„ 가지고 작업하기 위해서 https://bugzilla.kernel.org
+를 참조하ë¼. ì—¬ëŸ¬ë¶„ì´ ì•žìœ¼ë¡œ ìƒê²¨ë‚  버그 리í¬íŠ¸ë“¤ì˜ ì¡°ì–¸ìžê°€ ë˜ê¸¸ ì›í•œë‹¤ë©´
bugme-new ë©”ì¼ë§ 리스트나(새로운 버그 리í¬íŠ¸ë“¤ë§Œì´ ì´ê³³ì—ì„œ ë©”ì¼ë¡œ 전해진다)
bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì¼ë¡œ 전해진다)
ì— ë“±ë¡í•˜ë©´ ëœë‹¤.
https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+
https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
@@ -361,10 +399,14 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
ìœ„ì˜ ëª‡ëª‡ ë¬¸ì„œë“¤ì´ ì„¤ëª…í•˜ì˜€ì§€ë§Œ 핵심 ì»¤ë„ ê°œë°œìžë“¤ì˜ 대다수는
리눅스 ì»¤ë„ ë©”ì¼ë§ ë¦¬ìŠ¤íŠ¸ì— ì°¸ì—¬í•˜ê³  있다. ë¦¬ìŠ¤íŠ¸ì— ë“±ë¡í•˜ê³  해지하는
ë°©ë²•ì— ê´€í•œ ìžì„¸í•œ ì‚¬í•­ì€ ë‹¤ìŒì—ì„œ 참조할 수 있다.
+
http://vger.kernel.org/vger-lists.html#linux-kernel
+
웹ìƒì˜ ë§Žì€ ë‹¤ë¥¸ ê³³ì—ë„ ë©”ì¼ë§ ë¦¬ìŠ¤íŠ¸ì˜ ì•„ì¹´ì´ë¸Œë“¤ì´ 있다.
ì´ëŸ¬í•œ ì•„ì¹´ì´ë¸Œë“¤ì„ 찾으려면 검색 ì—”ì§„ì„ ì‚¬ìš©í•˜ë¼. 예를 들어:
+
http://dir.gmane.org/gmane.linux.kernel
+
ì—¬ëŸ¬ë¶„ì´ ìƒˆë¡œìš´ ë¬¸ì œì— ê´€í•´ ë¦¬ìŠ¤íŠ¸ì— ì˜¬ë¦¬ê¸° ì „ì— ë§í•˜ê³  ì‹¶ì€ ì£¼ì œì— ê´€í•œ
ê²ƒì„ ì•„ì¹´ì´ë¸Œì—ì„œ 먼저 찾아보기를 강력히 권장한다. ì´ë¯¸ ìƒì„¸í•˜ê²Œ í† ë¡ ëœ ë§Žì€
ê²ƒë“¤ì´ ë©”ì¼ë§ ë¦¬ìŠ¤íŠ¸ì˜ ì•„ì¹´ì´ë¸Œì— 기ë¡ë˜ì–´ 있다.
@@ -374,11 +416,13 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
있는지는 MAINTAINERS 파ì¼ì„ 참조하ë¼.
ë§Žì€ ë¦¬ìŠ¤íŠ¸ë“¤ì€ kernel.orgì—ì„œ 호스트ë˜ê³  있다. ê·¸ ì •ë³´ë“¤ì€ ë‹¤ìŒì—ì„œ ì°¸ì¡°ë  ìˆ˜ 있다.
+
http://vger.kernel.org/vger-lists.html
ë¦¬ìŠ¤íŠ¸ë“¤ì„ ì‚¬ìš©í•  때는 올바른 ì˜ˆì ˆì„ ë”°ë¥¼ ê²ƒì„ ìœ ë…í•´ë¼.
대단하진 않지만 ë‹¤ìŒ URLì€ ë¦¬ìŠ¤íŠ¸(í˜¹ì€ ëª¨ë“  리스트)와 대화하는 몇몇 간단한
ê°€ì´ë“œë¼ì¸ì„ 가지고 있다.
+
http://www.albion.com/netiquette/
여러 ì‚¬ëžŒë“¤ì´ ì—¬ëŸ¬ë¶„ì˜ ë©”ì¼ì— ì‘답한다면 CC: 즉 수신 리스트는 꽤 커지게
@@ -391,7 +435,7 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
"John 커ë„해커는 작성했다...."를 유지하며 ì—¬ëŸ¬ë¶„ë“¤ì˜ ì˜ê²¬ì„ ê·¸ ë©”ì¼ì˜ 윗부분ì—
작성하지 ë§ê³  ê° ì¸ìš©í•œ 단ë½ë“¤ 사ì´ì— 넣어ë¼.
-ì—¬ëŸ¬ë¶„ë“¤ì´ íŒ¨ì¹˜ë“¤ì„ ë©”ì¼ì— 넣는다면 ê·¸ê²ƒë“¤ì€ Documentation/SubmittingPatchesì—
+ì—¬ëŸ¬ë¶„ë“¤ì´ íŒ¨ì¹˜ë“¤ì„ ë©”ì¼ì— 넣는다면 ê·¸ê²ƒë“¤ì€ Documentation/process/submitting-patches.rstì—
나와있는ë°ë¡œ 명백히(plain) ì½ì„ 수 있는 í…스트여야 한다. ì»¤ë„ ê°œë°œìžë“¤ì€
첨부파ì¼ì´ë‚˜ ì••ì¶•ëœ íŒ¨ì¹˜ë“¤ì„ ì›í•˜ì§€ 않는다. ê·¸ë“¤ì€ ì—¬ëŸ¬ë¶„ë“¤ì˜ íŒ¨ì¹˜ì˜
ê° ë¼ì¸ 단위로 코멘트를 하길 ì›í•˜ë©° 압축하거나 첨부하지 ì•Šê³  보내는 것ì´
@@ -405,11 +449,12 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
커뮤니티와 협력하는 법
---------------------
+----------------------
ì»¤ë„ ì»¤ë®¤ë‹ˆí‹°ì˜ ëª©ì ì€ 가능한한 가장 ì¢‹ì€ ì»¤ë„ì„ ì œê³µí•˜ëŠ” 것ì´ë‹¤. 여러분ì´
받아들여질 패치를 제출하게 ë˜ë©´ ê·¸ íŒ¨ì¹˜ì˜ ê¸°ìˆ ì ì¸ ì´ì ìœ¼ë¡œ ê²€í† ë  ê²ƒì´ë‹¤.
그럼 ì—¬ëŸ¬ë¶„ë“¤ì€ ë¬´ì—‡ì„ ê¸°ëŒ€í•˜ê³  있어야 하는가?
+
- 비íŒ
- ì˜ê²¬
- ë³€ê²½ì„ ìœ„í•œ 요구
@@ -423,6 +468,7 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
기다려보고 다시 ì‹œë„í•´ë¼. 때론 너무 ë§Žì€ ë©”ì¼ë“¤ ì†ì— ë¬»í˜€ë²„ë¦¬ê¸°ë„ í•œë‹¤.
ì—¬ëŸ¬ë¶„ì€ ë¬´ì—‡ì„ í•´ì„œëŠ” 안ë˜ëŠ”ê°€?
+
- ì—¬ëŸ¬ë¶„ì˜ íŒ¨ì¹˜ê°€ 아무 질문 ì—†ì´ ë°›ì•„ë“¤ì—¬ì§€ê¸°ë¥¼ 기대하는 것
- ë°©ì–´ì ì´ ë˜ëŠ” 것
- ì˜ê²¬ì„ 무시하는 것
@@ -443,10 +489,12 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
ì»¤ë„ ì»¤ë®¤ë‹ˆí‹°ì™€ 기업 ì¡°ì§ê°„ì˜ ì°¨ì´ì 
------------------------------------------------------------------
+------------------------------------
ì»¤ë„ ì»¤ë®¤ë‹ˆí‹°ëŠ” 가장 전통ì ì¸ íšŒì‚¬ì˜ ê°œë°œ 환경과는 다르다. ì—¬ê¸°ì— ì—¬ëŸ¬ë¶„ë“¤ì˜
문제를 피하기 위한 목ë¡ì´ 있다.
+
ì—¬ëŸ¬ë¶„ë“¤ì´ ì œì•ˆí•œ ë³€ê²½ë“¤ì— ê´€í•˜ì—¬ ë§í•  ë•Œ ì¢‹ì€ ê²ƒë“¤ :
+
- "ì´ê²ƒì€ 여러 ë¬¸ì œë“¤ì„ í•´ê²°í•©ë‹ˆë‹¤."
- "ì´ê²ƒì€ 2000 ë¼ì¸ì˜ 코드를 줄입니다."
- "ì´ê²ƒì€ ë‚´ê°€ ë§í•˜ë ¤ëŠ” ê²ƒì— ê´€í•´ 설명하는 패치입니다."
@@ -455,6 +503,7 @@ bugme-janitor ë©”ì¼ë§ 리스트(bugzillaì— ëª¨ë“  ë³€í™”ë“¤ì´ ì—¬ê¸°ì„œ ë©”ì
- "ì´ê²ƒì€ ì¼ë°˜ì ì¸ 머신ì—ì„œ ì„±ëŠ¥ì„ í–¥ìƒí•¨ìœ¼ë¡œ..."
ì—¬ëŸ¬ë¶„ë“¤ì´ ë§í•  ë•Œ 피해야 í•  좋지 ì•Šì€ ê²ƒë“¤ :
+
- "우리는 ê·¸ê²ƒì„ AIX/ptx/Solarisì—ì„œ ì´ëŸ¬í•œ 방법으로 했다. 그러므로 ê·¸ê²ƒì€ ì¢‹ì€ ê²ƒìž„ì— í‹€ë¦¼ì—†ë‹¤..."
- "나는 20ë…„ë™ì•ˆ ì´ê²ƒì„ 해왔다. 그러므로..."
- "ì´ê²ƒì€ ëˆì„ 벌기위해 ë‚˜ì˜ íšŒì‚¬ê°€ 필요로 하는 것ì´ë‹¤."
@@ -514,14 +563,15 @@ Patì´ë¼ëŠ” ì´ë¦„ì„ ê°€ì§„ ì—¬ìžê°€ ìžˆì„ ìˆ˜ë„ ìžˆëŠ” 것ì´ë‹¤. 리눅ìŠ
간단하게(í˜¹ì€ ê°„ë‹¨í•œê²Œ 재배치하여) 하는 ê²ƒë„ ì¤‘ìš”í•˜ë‹¤.
ì—¬ê¸°ì— ì»¤ë„ ê°œë°œìž Al Viroì˜ ì´ì•¼ê¸°ê°€ 있다.
- "í•™ìƒì˜ 수학 숙제를 채ì í•˜ëŠ” ì„ ìƒë‹˜ì„ ìƒê°í•´ë³´ë¼. ì„ ìƒë‹˜ì€ í•™ìƒë“¤ì´
+
+ *"í•™ìƒì˜ 수학 숙제를 채ì í•˜ëŠ” ì„ ìƒë‹˜ì„ ìƒê°í•´ë³´ë¼. ì„ ìƒë‹˜ì€ í•™ìƒë“¤ì´
ë‹µì„ ì–»ì„때까지 ê²ªì€ ì‹œí–‰ì°©ì˜¤ë¥¼ 보길 ì›í•˜ì§€ 않는다. ì„ ìƒë‹˜ë“¤ì€
간결하고 가장 ë›°ì–´ë‚œ ë‹µì„ ë³´ê¸¸ ì›í•œë‹¤. 훌륭한 í•™ìƒì€ ì´ê²ƒì„ 알고
- 마지막으로 ë‹µì„ ì–»ê¸° ì „ 중간 ê³¼ì •ë“¤ì„ ì œì¶œí•˜ì§„ 않는다.
+ 마지막으로 ë‹µì„ ì–»ê¸° ì „ 중간 ê³¼ì •ë“¤ì„ ì œì¶œí•˜ì§„ 않는다.*
- ì»¤ë„ ê°œë°œë„ ë§ˆì°¬ê°€ì§€ì´ë‹¤. ë©”ì¸í…Œì´ë„ˆë“¤ê³¼ 검토하는 ì‚¬ëžŒë“¤ì€ ë¬¸ì œë¥¼
+ *ì»¤ë„ ê°œë°œë„ ë§ˆì°¬ê°€ì§€ì´ë‹¤. ë©”ì¸í…Œì´ë„ˆë“¤ê³¼ 검토하는 ì‚¬ëžŒë“¤ì€ ë¬¸ì œë¥¼
풀어나가는 과정ì†ì— 숨겨진 ê³¼ì •ì„ ë³´ê¸¸ ì›í•˜ì§„ 않는다. 그들ì€
- 간결하고 멋진 ë‹µì„ ë³´ê¸¸ ì›í•œë‹¤."
+ 간결하고 멋진 ë‹µì„ ë³´ê¸¸ ì›í•œë‹¤."*
커뮤니티와 협력하며 ë›°ì–´ë‚œ ë‹µì„ ì°¾ëŠ” 것과 ì—¬ëŸ¬ë¶„ë“¤ì˜ ë마치지 못한 작업들
사ì´ì— ê· í˜•ì„ ìœ ì§€í•´ì•¼ 하는 ê²ƒì€ ì–´ë ¤ìš¸ì§€ë„ ëª¨ë¥¸ë‹¤. 그러므로 프로세스ì˜
@@ -549,16 +599,17 @@ Patì´ë¼ëŠ” ì´ë¦„ì„ ê°€ì§„ ì—¬ìžê°€ ìžˆì„ ìˆ˜ë„ ìžˆëŠ” 것ì´ë‹¤. 리눅ìŠ
ìƒê°í•˜ì—¬ ì´ë©”ì¼ì„ 작성해야 한다. ì´ ì •ë³´ëŠ” 패치를 위한 ChangeLogê°€ ë 
것ì´ë‹¤. 그리고 í•­ìƒ ê·¸ ë‚´ìš©ì„ ë³´ê¸¸ ì›í•˜ëŠ” 모든 ì‚¬ëžŒë“¤ì„ ìœ„í•´ ë³´ì¡´ë 
것ì´ë‹¤. 패치는 완벽하게 다ìŒê³¼ ê°™ì€ ë‚´ìš©ë“¤ì„ í¬í•¨í•˜ì—¬ 설명해야 한다.
+
- ë³€ê²½ì´ ì™œ 필요한지
- íŒ¨ì¹˜ì— ê´€í•œ ì „ì²´ 설계 ì ‘ê·¼(approach)
- 구현 ìƒì„¸ë“¤
- 테스트 결과들
ì´ê²ƒì´ 무엇ì¸ì§€ ë” ìžì„¸í•œ ê²ƒì„ ì•Œê³  싶다면 ë‹¤ìŒ ë¬¸ì„œì˜ ChageLog í•­ì„ ë´ë¼.
- "The Perfect Patch"
- http://www.ozlabs.org/~akpm/stuff/tpp.txt
+ "The Perfect Patch"
+ http://www.ozlabs.org/~akpm/stuff/tpp.txt
ì´ ëª¨ë“  ê²ƒì„ í•˜ëŠ” ê²ƒì€ ë§¤ìš° 어려운 ì¼ì´ë‹¤. 완벽히 소화하는 ë°ëŠ” ì ì–´ë„ 몇년ì´
@@ -570,7 +621,8 @@ Patì´ë¼ëŠ” ì´ë¦„ì„ ê°€ì§„ ì—¬ìžê°€ ìžˆì„ ìˆ˜ë„ ìžˆëŠ” 것ì´ë‹¤. 리눅ìŠ
----------
-"개발 프로세스"(http://lwn.net/Articles/94386/) 섹션ì„
+
+"개발 프로세스"(https://lwn.net/Articles/94386/) 섹션ì„
ìž‘ì„±í•˜ëŠ”ë° ìžˆì–´ 참고할 문서를 사용하ë„ë¡ í—ˆë½í•´ì¤€ Paolo Ciarrocchiì—게
ê°ì‚¬í•œë‹¤. ì—¬ëŸ¬ë¶„ë“¤ì´ ë§í•´ì•¼ í•  것과 ë§í•´ì„œëŠ” 안ë˜ëŠ” ê²ƒì˜ ëª©ë¡ ì¤‘ ì¼ë¶€ë¥¼ 제공해준
Randy Dunlapê³¼ Gerrit Huizengaì—게 ê°ì‚¬í•œë‹¤. ë˜í•œ 검토와 ì˜ê²¬ 그리고
diff --git a/Documentation/translations/ko_KR/index.rst b/Documentation/translations/ko_KR/index.rst
new file mode 100644
index 000000000000..0b695345abc7
--- /dev/null
+++ b/Documentation/translations/ko_KR/index.rst
@@ -0,0 +1,12 @@
+.. raw:: latex
+
+ \renewcommand\thesection*
+ \renewcommand\thesubsection*
+
+Korean translations
+===================
+
+.. toctree::
+ :maxdepth: 1
+
+ howto
diff --git a/Documentation/ko_KR/memory-barriers.txt b/Documentation/translations/ko_KR/memory-barriers.txt
index 34d3d380893d..a3228a676cc1 100644
--- a/Documentation/ko_KR/memory-barriers.txt
+++ b/Documentation/translations/ko_KR/memory-barriers.txt
@@ -823,6 +823,38 @@ CPU 는 b ë¡œë¶€í„°ì˜ ë¡œë“œ 오í¼ë ˆì´ì…˜ì´ a ë¡œë¶€í„°ì˜ ë¡œë“œ 오í¼ë ˆ
오í¼ë ˆì´ì…˜ì„ 위한 코드를 ì •ë§ë¡œ 만들ë„ë¡ í•˜ì§€ë§Œ, 컴파ì¼ëŸ¬ê°€ 그렇게 만들어진
ì½”ë“œì˜ ìˆ˜í–‰ 결과를 사용하ë„ë¡ ê°•ì œí•˜ì§€ëŠ” 않습니다.
+ë˜í•œ, 컨트롤 ì˜ì¡´ì„±ì€ if ë¬¸ì˜ then 절과 else ì ˆì— ëŒ€í•´ì„œë§Œ ì ìš©ë©ë‹ˆë‹¤. ìƒì„¸ížˆ
+ë§í•´ì„œ, 컨트롤 ì˜ì¡´ì„±ì€ if ë¬¸ì„ ë’¤ë”°ë¥´ëŠ” 코드ì—는 ì ìš©ë˜ì§€ 않습니다:
+
+ q = READ_ONCE(a);
+ if (q) {
+ WRITE_ONCE(b, p);
+ } else {
+ WRITE_ONCE(b, r);
+ }
+ WRITE_ONCE(c, 1); /* BUG: No ordering against the read from "a". */
+
+컴파ì¼ëŸ¬ëŠ” volatile íƒ€ìž…ì— ëŒ€í•œ 액세스를 재배치 í•  수 없고 ì´ ì¡°ê±´ í•˜ì˜ "b"
+ë¡œì˜ ì“°ê¸°ë¥¼ 재배치 í•  수 없기 ë•Œë¬¸ì— ì—¬ê¸°ì— ìˆœì„œ ê·œì¹™ì´ ì¡´ìž¬í•œë‹¤ê³  주장하고
+ì‹¶ì„ ê²ë‹ˆë‹¤. ë¶ˆí–‰ížˆë„ ì´ ê²½ìš°ì—, 컴파ì¼ëŸ¬ëŠ” 다ìŒì˜ ê°€ìƒì˜ pseudo-assembly 언어
+코드처럼 "b" ë¡œì˜ ë‘ê°œì˜ ì“°ê¸° 오í¼ë ˆì´ì…˜ì„ conditional-move ì¸ìŠ¤íŠ¸ëŸ­ì…˜ìœ¼ë¡œ
+번역할 수 있습니다:
+
+ ld r1,a
+ ld r2,p
+ ld r3,r
+ cmp r1,$0
+ cmov,ne r4,r2
+ cmov,eq r4,r3
+ st r4,b
+ st $1,c
+
+ì™„í™”ëœ ìˆœì„œ ê·œì¹™ì˜ CPU 는 "a" ë¡œë¶€í„°ì˜ ë¡œë“œì™€ "c" ë¡œì˜ ìŠ¤í† ì–´ 사ì´ì— ì–´ë–¤
+ì¢…ë¥˜ì˜ ì˜ì¡´ì„±ë„ 갖지 ì•Šì„ ê²ë‹ˆë‹¤. ì´ ì»¨íŠ¸ë¡¤ ì˜ì¡´ì„±ì€ ë‘ê°œì˜ cmov ì¸ìŠ¤íŠ¸ëŸ­ì…˜ê³¼
+ê±°ê¸°ì— ì˜ì¡´í•˜ëŠ” 스토어 ì—게만 ì ìš©ë  ê²ë‹ˆë‹¤. 짧게 ë§í•˜ìžë©´, 컨트롤 ì˜ì¡´ì„±ì€
+주어진 if ë¬¸ì˜ then 절과 else ì ˆì—게만 (그리고 ì´ ë‘ ì ˆ ë‚´ì—ì„œ 호출ë˜ëŠ”
+함수들ì—게까지) ì ìš©ë˜ì§€, ì´ if ë¬¸ì„ ë’¤ë”°ë¥´ëŠ” 코드ì—는 ì ìš©ë˜ì§€ 않습니다.
+
마지막으로, 컨트롤 ì˜ì¡´ì„±ì€ ì´í–‰ì„± (transitivity) ì„ ì œê³µí•˜ì§€ -않습니다-. ì´ê±´
x 와 y ê°€ 둘 다 0 ì´ë¼ëŠ” ì´ˆê¸°ê°’ì„ ê°€ì¡Œë‹¤ëŠ” 가정 í•˜ì˜ ë‘ê°œì˜ ì˜ˆì œë¡œ
ë³´ì´ê² ìŠµë‹ˆë‹¤:
@@ -883,6 +915,10 @@ http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf 와
ì˜ì¡´ì„±ì´ 사ë¼ì§€ì§€ 않게 í•˜ëŠ”ë° ë„ì›€ì„ ì¤„ 수 있습니다. ë” ë§Žì€ ì •ë³´ë¥¼
위해선 "컴파ì¼ëŸ¬ 배리어" ì„¹ì…˜ì„ ì°¸ê³ í•˜ì‹œê¸° ë°”ëžë‹ˆë‹¤.
+ (*) 컨트롤 ì˜ì¡´ì„±ì€ 컨트롤 ì˜ì¡´ì„±ì„ 갖는 if ë¬¸ì˜ then 절과 else 절과 ì´ ë‘ ì ˆ
+ ë‚´ì—ì„œ 호출ë˜ëŠ” 함수들ì—만 ì ìš©ë©ë‹ˆë‹¤. 컨트롤 ì˜ì¡´ì„±ì€ 컨트롤 ì˜ì¡´ì„±ì„
+ 갖는 if ë¬¸ì„ ë’¤ë”°ë¥´ëŠ” 코드ì—는 ì ìš©ë˜ì§€ -않습니다-.
+
(*) 컨트롤 ì˜ì¡´ì„±ì€ 보통 다른 íƒ€ìž…ì˜ ë°°ë¦¬ì–´ë“¤ê³¼ ì§ì„ 맞춰 사용ë©ë‹ˆë‹¤.
(*) 컨트롤 ì˜ì¡´ì„±ì€ ì´í–‰ì„±ì„ 제공하지 -않습니다-. ì´í–‰ì„±ì´ 필요하다면,
diff --git a/Documentation/ko_KR/stable_api_nonsense.txt b/Documentation/translations/ko_KR/stable_api_nonsense.txt
index 3ba10b11d556..4d93af1efd61 100644
--- a/Documentation/ko_KR/stable_api_nonsense.txt
+++ b/Documentation/translations/ko_KR/stable_api_nonsense.txt
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/stable_api_nonsense.txt translated
+This is a version of Documentation/process/stable-api-nonsense.rst translated
into korean
This document is maintained by Minchan Kim <minchan@kernel.org>
If you find any difference between this document and the original file or
@@ -12,7 +12,7 @@ try to update the original English file first.
==================================
ì´ ë¬¸ì„œëŠ”
-Documentation/stable_api_nonsense.txt
+Documentation/process/stable-api-nonsense.rst
ì˜ í•œê¸€ 번역입니다.
ì—­ìžï¼š 김민찬 <minchan@kernel.org>
diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/translations/zh_CN/CodingStyle
index 12717791baac..dc101f48e713 100644
--- a/Documentation/zh_CN/CodingStyle
+++ b/Documentation/translations/zh_CN/CodingStyle
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/CodingStyle
+Chinese translated version of Documentation/process/coding-style.rst
If you have any comment or update to the content, please post to LKML directly.
However, if you have problem communicating in English you can also ask the
@@ -7,7 +7,7 @@ translation is outdated or there is problem with translation.
Chinese maintainer: Zhang Le <r0bertz@gentoo.org>
---------------------------------------------------------------------
-Documentation/CodingStyle的中文翻译
+Documentation/process/coding-style.rst的中文翻译
如果想评论或更新本文的内容,请直接å‘信到LKML。如果你使用英文交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯
以å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻译存在问题,请è”系中文版维护者。
@@ -399,7 +399,7 @@ C是一个简朴的语言,你的命å也应该这样。和 Modula-2 å’Œ Pasca
些事情的原因。
当注释内核API函数时,请使用 kernel-doc æ ¼å¼ã€‚请看
-Documentation/kernel-documentation.rstå’Œscripts/kernel-doc 以获得详细信æ¯ã€‚
+Documentation/doc-guide/å’Œscripts/kernel-doc 以获得详细信æ¯ã€‚
Linux的注释风格是 C89 “/* ... */†风格。ä¸è¦ä½¿ç”¨ C99 风格 “// ...†注释。
@@ -809,5 +809,5 @@ GNU 手册 - éµå¾ª K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
WG14是C语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/
-Kernel CodingStyle,作者 greg@kroah.com å‘表于OLS 2002:
+Kernel process/coding-style.rst,作者 greg@kroah.com å‘表于OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff --git a/Documentation/zh_CN/HOWTO b/Documentation/translations/zh_CN/HOWTO
index f0613b92e0be..11be075ba5fa 100644
--- a/Documentation/zh_CN/HOWTO
+++ b/Documentation/translations/zh_CN/HOWTO
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/HOWTO
+Chinese translated version of Documentation/process/howto.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -9,7 +9,7 @@ or if there is a problem with the translation.
Maintainer: Greg Kroah-Hartman <greg@kroah.com>
Chinese maintainer: Li Yang <leoli@freescale.com>
---------------------------------------------------------------------
-Documentation/HOWTO 的中文翻译
+Documentation/process/howto.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -93,16 +93,16 @@ Linux内核代ç ä¸­åŒ…å«æœ‰å¤§é‡çš„文档。这些文档对于学习如何与
文件简è¦ä»‹ç»äº†Linux内核的背景,并且æ述了如何é…置和编译内核。内核的
新用户应该从这里开始。
- Documentation/Changes
+ Documentation/process/changes.rst
文件给出了用æ¥ç¼–译和使用内核所需è¦çš„最å°è½¯ä»¶åŒ…列表。
- Documentation/CodingStyle
+ Documentation/process/coding-style.rst
æè¿°Linux内核的代ç é£Žæ ¼å’Œç†ç”±ã€‚所有新代ç éœ€è¦éµå®ˆè¿™ç¯‡æ–‡æ¡£ä¸­å®šä¹‰çš„规
范。大多数维护者åªä¼šæŽ¥æ”¶ç¬¦åˆè§„定的补ä¸ï¼Œå¾ˆå¤šäººä¹Ÿåªä¼šå¸®å¿™æ£€æŸ¥ç¬¦åˆé£Žæ ¼
的代ç ã€‚
- Documentation/SubmittingPatches
- Documentation/SubmittingDrivers
+ Documentation/process/submitting-patches.rst
+ Documentation/process/submitting-drivers.rst
这两份文档明确æ述如何创建和å‘é€è¡¥ä¸ï¼Œå…¶ä¸­åŒ…括(但ä¸ä»…é™äºŽ):
- 邮件内容
- 邮件格å¼
@@ -116,7 +116,7 @@ Linux内核代ç ä¸­åŒ…å«æœ‰å¤§é‡çš„文档。这些文档对于学习如何与
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
- Documentation/stable_api_nonsense.txt
+ Documentation/process/stable-api-nonsense.rst
论è¯å†…核为什么特æ„ä¸åŒ…括稳定的内核内部API,也就是说ä¸åŒ…括åƒè¿™æ ·çš„特
性:
- å­ç³»ç»Ÿä¸­é—´å±‚(为了兼容性?)
@@ -125,23 +125,23 @@ Linux内核代ç ä¸­åŒ…å«æœ‰å¤§é‡çš„文档。这些文档对于学习如何与
这篇文档对于ç†è§£Linuxçš„å¼€å‘哲学至关é‡è¦ã€‚对于将开å‘å¹³å°ä»Žå…¶ä»–æ“作系
统转移到Linux的人æ¥è¯´ä¹Ÿå¾ˆé‡è¦ã€‚
- Documentation/SecurityBugs
+ Documentation/admin-guide/security-bugs.rst
如果你认为自己å‘现了Linux内核的安全性问题,请根æ®è¿™ç¯‡æ–‡æ¡£ä¸­çš„步骤æ¥
æ醒其他内核开å‘者并帮助解决这个问题。
- Documentation/ManagementStyle
+ Documentation/process/management-style.rst
æ述内核维护者的工作方法åŠå…¶å…±æœ‰ç‰¹ç‚¹ã€‚这对于刚刚接触内核开å‘(或者对
它感到好奇)的人æ¥è¯´å¾ˆé‡è¦ï¼Œå› ä¸ºå®ƒè§£é‡Šäº†å¾ˆå¤šå¯¹äºŽå†…核维护者独特行为的
æ™®é误解与迷惑。
- Documentation/stable_kernel_rules.txt
+ Documentation/process/stable-kernel-rules.rst
解释了稳定版内核å‘布的规则,以åŠå¦‚何将改动放入这些版本的步骤。
- Documentation/kernel-docs.txt
+ Documentation/process/kernel-docs.rst
有助于内核开å‘的外部文档列表。如果你在内核自带的文档中没有找到你想找
的内容,å¯ä»¥æŸ¥çœ‹è¿™äº›æ–‡æ¡£ã€‚
- Documentation/applying-patches.txt
+ Documentation/process/applying-patches.rst
关于补ä¸æ˜¯ä»€ä¹ˆä»¥åŠå¦‚何将它打在ä¸åŒå†…核开å‘分支上的好介ç»
内核还拥有大é‡ä»Žä»£ç è‡ªåŠ¨ç”Ÿæˆçš„文档。它包å«å†…核内部APIçš„å…¨é¢ä»‹ç»ä»¥åŠå¦‚何
@@ -238,7 +238,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开å‘éµå¾ª
2.6.x.y版本由“稳定版â€å°ç»„(邮件地å€<stable@vger.kernel.org>)维护,一般隔周å‘
布新版本。
-内核æºç ä¸­çš„Documentation/stable_kernel_rules.txt文件具体æ述了å¯è¢«ç¨³å®š
+内核æºç ä¸­çš„Documentation/process/stable-kernel-rules.rst文件具体æ述了å¯è¢«ç¨³å®š
版内核接å—的修改类型以åŠå‘布的æµç¨‹ã€‚
@@ -329,7 +329,7 @@ bugzilla.kernel.org是Linux内核开å‘者们用æ¥è·Ÿè¸ªå†…æ ¸Bug的网站。æˆ
户在这个工具中报告找到的所有bug。如何使用内核bugzilla的细节请访问:
http://test.kernel.org/bugzilla/faq.html
-内核æºç ä¸»ç›®å½•ä¸­çš„REPORTING-BUGS文件里有一个很好的模æ¿ã€‚它指导用户如何报
+内核æºç ä¸»ç›®å½•ä¸­çš„admin-guide/reporting-bugs.rst文件里有一个很好的模æ¿ã€‚它指导用户如何报
å‘Šå¯èƒ½çš„内核bug以åŠéœ€è¦æ供哪些信æ¯æ¥å¸®åŠ©å†…核开å‘者们找到问题的根æºã€‚
@@ -380,7 +380,7 @@ MAINTAINERS文件中å¯ä»¥æ‰¾åˆ°ä¸åŒè¯é¢˜å¯¹åº”的邮件列表。
这几行。将你的评论加在被引用的段è½ä¹‹é—´è€Œä¸è¦æ”¾åœ¨é‚®ä»¶çš„顶部。
如果你在邮件中附带补ä¸ï¼Œè¯·ç¡®è®¤å®ƒä»¬æ˜¯å¯ä»¥ç›´æŽ¥é˜…读的纯文本(如
-Documentation/SubmittingPatches文档中所述)。内核开å‘者们ä¸å¸Œæœ›é‡åˆ°é™„件
+Documentation/process/submitting-patches.rst文档中所述)。内核开å‘者们ä¸å¸Œæœ›é‡åˆ°é™„件
或者被压缩了的补ä¸ã€‚åªæœ‰è¿™æ ·æ‰èƒ½ä¿è¯ä»–们å¯ä»¥ç›´æŽ¥è¯„论你的æ¯è¡Œä»£ç ã€‚请确ä¿
你使用的邮件å‘é€ç¨‹åºä¸ä¼šä¿®æ”¹ç©ºæ ¼å’Œåˆ¶è¡¨ç¬¦ã€‚一个防范性的测试方法是先将邮件
å‘é€ç»™è‡ªå·±ï¼Œç„¶åŽè‡ªå·±å°è¯•æ˜¯å¦å¯ä»¥é¡ºåˆ©åœ°æ‰“上收到的补ä¸ã€‚如果测试ä¸æˆåŠŸï¼Œè¯·
diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/translations/zh_CN/IRQ.txt
index 956026d5cf82..956026d5cf82 100644
--- a/Documentation/zh_CN/IRQ.txt
+++ b/Documentation/translations/zh_CN/IRQ.txt
diff --git a/Documentation/zh_CN/SecurityBugs b/Documentation/translations/zh_CN/SecurityBugs
index d21eb07fe943..2d0fffd122ce 100644
--- a/Documentation/zh_CN/SecurityBugs
+++ b/Documentation/translations/zh_CN/SecurityBugs
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/SecurityBugs
+Chinese translated version of Documentation/admin-guide/security-bugs.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
---------------------------------------------------------------------
-Documentation/SecurityBugs 的中文翻译
+Documentation/admin-guide/security-bugs.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -31,7 +31,7 @@ linux内核安全团队å¯ä»¥é€šè¿‡email<security@kernel.org>æ¥è”系。这是
一组独立的安全工作人员,å¯ä»¥å¸®åŠ©æ”¹å–„æ¼æ´žæŠ¥å‘Šå¹¶ä¸”公布和å–消一个修å¤ã€‚安
全团队有å¯èƒ½ä¼šä»Žéƒ¨åˆ†çš„维护者那里引进é¢å¤–的帮助æ¥äº†è§£å¹¶ä¸”ä¿®å¤å®‰å…¨æ¼æ´žã€‚
当é‡åˆ°ä»»ä½•æ¼æ´žï¼Œæ‰€èƒ½æ供的信æ¯è¶Šå¤šå°±è¶Šèƒ½è¯Šæ–­å’Œä¿®å¤ã€‚如果你ä¸æ¸…楚什么
-是有帮助的信æ¯ï¼Œé‚£å°±è¯·é‡æ¸©ä¸€ä¸‹REPORTING-BUGS文件中的概述过程。任
+是有帮助的信æ¯ï¼Œé‚£å°±è¯·é‡æ¸©ä¸€ä¸‹admin-guide/reporting-bugs.rst文件中的概述过程。任
何攻击性的代ç éƒ½æ˜¯éžå¸¸æœ‰ç”¨çš„,未ç»æŠ¥å‘Šè€…çš„åŒæ„ä¸ä¼šè¢«å–消,除éžå®ƒå·²ç»
被公布于众。
diff --git a/Documentation/zh_CN/SubmittingDrivers b/Documentation/translations/zh_CN/SubmittingDrivers
index d313f5d8448d..929385e4b194 100644
--- a/Documentation/zh_CN/SubmittingDrivers
+++ b/Documentation/translations/zh_CN/SubmittingDrivers
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/SubmittingDrivers
+Chinese translated version of Documentation/process/submitting-drivers.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: Li Yang <leo@zh-kernel.org>
---------------------------------------------------------------------
-Documentation/SubmittingDrivers 的中文翻译
+Documentation/process/submitting-drivers.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -30,7 +30,7 @@ Documentation/SubmittingDrivers 的中文翻译
兴趣的是显å¡é©±åŠ¨ç¨‹åºï¼Œä½ ä¹Ÿè®¸åº”该访问 XFree86 项目(http://www.xfree86.org/)
å’Œï¼æˆ– X.org 项目 (http://x.org)。
-å¦è¯·å‚阅 Documentation/SubmittingPatches 文档。
+å¦è¯·å‚阅 Documentation/process/submitting-patches.rst 文档。
分é…设备å·
@@ -39,7 +39,7 @@ Documentation/SubmittingDrivers 的中文翻译
å—设备和字符设备的主设备å·ä¸Žä»Žè®¾å¤‡å·æ˜¯ç”± Linux 命åç¼–å·åˆ†é…æƒå¨ LANANA(
现在是 Torben Mathiasen)负责分é…。申请的网å€æ˜¯ http://www.lanana.org/。
å³ä½¿ä¸å‡†å¤‡æ交到主æµå†…核的设备驱动也需è¦åœ¨è¿™é‡Œåˆ†é…设备å·ã€‚有关详细信æ¯ï¼Œ
-请å‚阅 Documentation/devices.txt。
+请å‚阅 Documentation/admin-guide/devices.rst。
如果你使用的ä¸æ˜¯å·²ç»åˆ†é…的设备å·ï¼Œé‚£ä¹ˆå½“ä½ æ交设备驱动的时候,它将会被强
制分é…一个新的设备å·ï¼Œå³ä¾¿è¿™ä¸ªè®¾å¤‡å·å’Œä½ ä¹‹å‰å‘给客户的截然ä¸åŒã€‚
@@ -81,7 +81,7 @@ Linux 2.6:
如果你需è¦ä¸€ä¸ª Linux å’Œ NT 的通用驱动接å£ï¼Œé‚£ä¹ˆè¯·åœ¨ç”¨
户空间实现它。
-代ç ï¼š 请使用 Documentation/CodingStyle 中所æè¿°çš„ Linux 代ç é£Ž
+代ç ï¼š 请使用 Documentation/process/coding-style.rst 中所æè¿°çš„ Linux 代ç é£Ž
格。如果你的æŸäº›ä»£ç æ®µï¼ˆä¾‹å¦‚那些与 Windows 驱动程åºåŒ…å…±
享的代ç æ®µï¼‰éœ€è¦ä½¿ç”¨å…¶ä»–æ ¼å¼ï¼Œè€Œä½ å´åªå¸Œæœ›ç»´æŠ¤ä¸€ä»½ä»£ç ï¼Œ
那么请将它们很好地区分出æ¥ï¼Œå¹¶ä¸”注明原因。
@@ -107,7 +107,7 @@ Linux 2.6:
程åºæµ‹è¯•çš„指导,请å‚阅
Documentation/power/drivers-testing.txt。有关驱动程åºç”µ
æºç®¡ç†é—®é¢˜ç›¸å¯¹å…¨é¢çš„概述,请å‚阅
- Documentation/power/devices.txt。
+ Documentation/power/admin-guide/devices.rst。
管ç†ï¼š 如果一个驱动程åºçš„作者还在进行有效的维护,那么通常除了那
些明显正确且ä¸éœ€è¦ä»»ä½•æ£€æŸ¥çš„è¡¥ä¸ä»¥å¤–,其他所有的补ä¸éƒ½ä¼š
diff --git a/Documentation/zh_CN/SubmittingPatches b/Documentation/translations/zh_CN/SubmittingPatches
index 1d3a10f8746b..e9098da8f1a4 100644
--- a/Documentation/zh_CN/SubmittingPatches
+++ b/Documentation/translations/zh_CN/SubmittingPatches
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/SubmittingPatches
+Chinese translated version of Documentation/process/submitting-patches.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: TripleX Chung <triplex@zh-kernel.org>
---------------------------------------------------------------------
-Documentation/SubmittingPatches 的中文翻译
+Documentation/process/submitting-patches.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -30,9 +30,9 @@ Documentation/SubmittingPatches 的中文翻译
对于想è¦å°†æ”¹åŠ¨æ交到 Linux 内核的个人或者公å¸æ¥è¯´ï¼Œå¦‚æžœä¸ç†Ÿæ‚‰â€œè§„矩â€ï¼Œ
æ交的æµç¨‹ä¼šè®©äººç•æƒ§ã€‚本文档收集了一系列建议,这些建议å¯ä»¥å¤§å¤§çš„æ高你
的改动被接å—的机会。
-阅读 Documentation/SubmitChecklist æ¥èŽ·å¾—在æ交代ç å‰éœ€è¦æ£€æŸ¥çš„项目的列
+阅读 Documentation/process/submit-checklist.rst æ¥èŽ·å¾—在æ交代ç å‰éœ€è¦æ£€æŸ¥çš„项目的列
表。如果你在æ交一个驱动程åºï¼Œé‚£ä¹ˆåŒæ—¶é˜…读一下
-Documentation/SubmittingDrivers 。
+Documentation/process/submitting-drivers.rst 。
--------------------------
@@ -338,7 +338,7 @@ e-mail 标题中的“一å¥è¯æ¦‚è¿°â€æ‰¼è¦çš„æè¿° e-mail 中的补ä¸ã€‚â€
本节包å«å¾ˆå¤šå’Œæ交到内核的代ç æœ‰å…³çš„通常的"规则"。事情永远有例外...但是
你必须真的有好的ç†ç”±è¿™æ ·åšã€‚ä½ å¯ä»¥æŠŠæœ¬èŠ‚å«åšLinus的计算机科学入门课。
-1) 读 Document/CodingStyle
+1) 读 Document/process/coding-style.rst
Nuff 说过,如果你的代ç å’Œè¿™ä¸ªå离太多,那么它有å¯èƒ½ä¼šè¢«æ‹’ç»ï¼Œæ²¡æœ‰æ›´å¤šçš„
审查,没有更多的评价。
@@ -404,8 +404,8 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
<https://lkml.org/lkml/2005/7/11/336>
-Kernel Documentation/CodingStyle:
- <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
+Kernel Documentation/process/coding-style.rst:
+ <http://sosdg.org/~coywolf/lxr/source/Documentation/process/coding-style.rst>
Linus Torvalds's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
diff --git a/Documentation/zh_CN/arm/Booting b/Documentation/translations/zh_CN/arm/Booting
index 6158a64df80c..1fe866f8218f 100644
--- a/Documentation/zh_CN/arm/Booting
+++ b/Documentation/translations/zh_CN/arm/Booting
@@ -68,7 +68,7 @@ RAM,或å¯èƒ½ä½¿ç”¨å¯¹è¿™ä¸ªè®¾å¤‡å·²çŸ¥çš„ RAM ä¿¡æ¯ï¼Œè¿˜å¯èƒ½ä½¿ç”¨ä»»ä½•
作为替代方案,引导加载程åºä¹Ÿå¯ä»¥é€šè¿‡æ ‡ç­¾åˆ—表传递相关的'console='
选项给内核以指定æŸä¸ªä¸²å£ï¼Œè€Œä¸²å£æ•°æ®æ ¼å¼çš„选项在以下文档中æ述:
- Documentation/kernel-parameters.txt。
+ Documentation/admin-guide/kernel-parameters.rst。
3ã€æ£€æµ‹æœºå™¨ç±»åž‹
diff --git a/Documentation/zh_CN/arm/kernel_user_helpers.txt b/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt
index cd7fc8f34cf9..cd7fc8f34cf9 100644
--- a/Documentation/zh_CN/arm/kernel_user_helpers.txt
+++ b/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt
diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/translations/zh_CN/arm64/booting.txt
index c1dd968c5ee9..c1dd968c5ee9 100644
--- a/Documentation/zh_CN/arm64/booting.txt
+++ b/Documentation/translations/zh_CN/arm64/booting.txt
diff --git a/Documentation/zh_CN/arm64/legacy_instructions.txt b/Documentation/translations/zh_CN/arm64/legacy_instructions.txt
index 68362a1ab717..68362a1ab717 100644
--- a/Documentation/zh_CN/arm64/legacy_instructions.txt
+++ b/Documentation/translations/zh_CN/arm64/legacy_instructions.txt
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/translations/zh_CN/arm64/memory.txt
index 19b3a52d5d94..19b3a52d5d94 100644
--- a/Documentation/zh_CN/arm64/memory.txt
+++ b/Documentation/translations/zh_CN/arm64/memory.txt
diff --git a/Documentation/zh_CN/arm64/silicon-errata.txt b/Documentation/translations/zh_CN/arm64/silicon-errata.txt
index 39477c75c4a4..39477c75c4a4 100644
--- a/Documentation/zh_CN/arm64/silicon-errata.txt
+++ b/Documentation/translations/zh_CN/arm64/silicon-errata.txt
diff --git a/Documentation/zh_CN/arm64/tagged-pointers.txt b/Documentation/translations/zh_CN/arm64/tagged-pointers.txt
index 2664d1bd5a1c..2664d1bd5a1c 100644
--- a/Documentation/zh_CN/arm64/tagged-pointers.txt
+++ b/Documentation/translations/zh_CN/arm64/tagged-pointers.txt
diff --git a/Documentation/zh_CN/basic_profiling.txt b/Documentation/translations/zh_CN/basic_profiling.txt
index 1e6bf0bdf8f5..1e6bf0bdf8f5 100644
--- a/Documentation/zh_CN/basic_profiling.txt
+++ b/Documentation/translations/zh_CN/basic_profiling.txt
diff --git a/Documentation/zh_CN/email-clients.txt b/Documentation/translations/zh_CN/email-clients.txt
index b9a1a3e6c78d..ec31d97e8d0e 100644
--- a/Documentation/zh_CN/email-clients.txt
+++ b/Documentation/translations/zh_CN/email-clients.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/email-clients.txt
+Chinese translated version of Documentation/process/email-clients.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
---------------------------------------------------------------------
-Documentation/email-clients.txt 的中文翻译
+Documentation/process/email-clients.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
diff --git a/Documentation/zh_CN/filesystems/sysfs.txt b/Documentation/translations/zh_CN/filesystems/sysfs.txt
index 7d3b05edb8ce..7d3b05edb8ce 100644
--- a/Documentation/zh_CN/filesystems/sysfs.txt
+++ b/Documentation/translations/zh_CN/filesystems/sysfs.txt
diff --git a/Documentation/zh_CN/gpio.txt b/Documentation/translations/zh_CN/gpio.txt
index bce972521065..bce972521065 100644
--- a/Documentation/zh_CN/gpio.txt
+++ b/Documentation/translations/zh_CN/gpio.txt
diff --git a/Documentation/zh_CN/io_ordering.txt b/Documentation/translations/zh_CN/io_ordering.txt
index e592daf4e014..e592daf4e014 100644
--- a/Documentation/zh_CN/io_ordering.txt
+++ b/Documentation/translations/zh_CN/io_ordering.txt
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/translations/zh_CN/magic-number.txt
index e9db693c0a23..e9db693c0a23 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/translations/zh_CN/magic-number.txt
diff --git a/Documentation/zh_CN/oops-tracing.txt b/Documentation/translations/zh_CN/oops-tracing.txt
index 9312608ffb8d..41ab53cc0e83 100644
--- a/Documentation/zh_CN/oops-tracing.txt
+++ b/Documentation/translations/zh_CN/oops-tracing.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/oops-tracing.txt
+Chinese translated version of Documentation/admin-guide/oops-tracing.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: Dave Young <hidave.darkstar@gmail.com>
---------------------------------------------------------------------
-Documentation/oops-tracing.txt 的中文翻译
+Documentation/admin-guide/oops-tracing.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -50,7 +50,7 @@ cat /proc/kmsg > file, 然而你必须介入中止传输, kmsg是一个“æ°
æ¯æ»šåŠ¨åˆ°äº†ç»ˆç«¯çš„上é¢ï¼Œä½ ä¼šå‘现以高分辩率å¯åŠ¨ï¼ˆæ¯”如,vga=791)会让你读到更多的文
本。(注æ„:这需è¦vesafb,所以对‘早期’的oops没有帮助)
-(2)用串å£ç»ˆç«¯å¯åŠ¨ï¼ˆè¯·å‚看Documentation/serial-console.txt),è¿è¡Œä¸€ä¸ªnull
+(2)用串å£ç»ˆç«¯å¯åŠ¨ï¼ˆè¯·å‚看Documentation/admin-guide/serial-console.rst),è¿è¡Œä¸€ä¸ªnull
modem到å¦ä¸€å°æœºå™¨å¹¶ç”¨ä½ å–œæ¬¢çš„通讯工具获å–输出。Minicom工作地很好。
(3)使用Kdump(请å‚看Documentation/kdump/kdump.txt),
diff --git a/Documentation/zh_CN/sparse.txt b/Documentation/translations/zh_CN/sparse.txt
index cc144e581515..cc144e581515 100644
--- a/Documentation/zh_CN/sparse.txt
+++ b/Documentation/translations/zh_CN/sparse.txt
diff --git a/Documentation/zh_CN/stable_api_nonsense.txt b/Documentation/translations/zh_CN/stable_api_nonsense.txt
index c26a27d1ee7d..a2b27fab382c 100644
--- a/Documentation/zh_CN/stable_api_nonsense.txt
+++ b/Documentation/translations/zh_CN/stable_api_nonsense.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/stable_api_nonsense.txt
+Chinese translated version of Documentation/process/stable-api-nonsense.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have problem
@@ -9,7 +9,7 @@ is problem with translation.
Maintainer: Greg Kroah-Hartman <greg@kroah.com>
Chinese maintainer: TripleX Chung <zhongyu@18mail.cn>
---------------------------------------------------------------------
-Documentation/stable_api_nonsense.txt 的中文翻译
+Documentation/process/stable-api-nonsense.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
diff --git a/Documentation/zh_CN/stable_kernel_rules.txt b/Documentation/translations/zh_CN/stable_kernel_rules.txt
index 26ea5ed7cd9c..db4ba5a0c39a 100644
--- a/Documentation/zh_CN/stable_kernel_rules.txt
+++ b/Documentation/translations/zh_CN/stable_kernel_rules.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/stable_kernel_rules.txt
+Chinese translated version of Documentation/process/stable-kernel-rules.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -8,7 +8,7 @@ or if there is a problem with the translation.
Chinese maintainer: TripleX Chung <triplex@zh-kernel.org>
---------------------------------------------------------------------
-Documentation/stable_kernel_rules.txt 的中文翻译
+Documentation/process/stable-kernel-rules.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
@@ -38,7 +38,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译
- 没有“ç†è®ºä¸Šçš„竞争æ¡ä»¶â€ï¼Œé™¤éžèƒ½ç»™å‡ºç«žäº‰æ¡ä»¶å¦‚何被利用的解释。
- ä¸èƒ½å­˜åœ¨ä»»ä½•çš„“ç碎的â€ä¿®æ­£ï¼ˆæ‹¼å†™ä¿®æ­£ï¼ŒåŽ»æŽ‰å¤šä½™ç©ºæ ¼ä¹‹ç±»çš„)。
- 必须被相关å­ç³»ç»Ÿçš„维护者接å—。
- - å¿…é¡»éµå¾ªDocumentation/SubmittingPatches里的规则。
+ - å¿…é¡»éµå¾ªDocumentation/process/submitting-patches.rst里的规则。
å‘稳定版代ç æ ‘æ交补ä¸çš„过程:
diff --git a/Documentation/zh_CN/video4linux/omap3isp.txt b/Documentation/translations/zh_CN/video4linux/omap3isp.txt
index 67ffbf352ae0..67ffbf352ae0 100644
--- a/Documentation/zh_CN/video4linux/omap3isp.txt
+++ b/Documentation/translations/zh_CN/video4linux/omap3isp.txt
diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
index 698660b7f21f..698660b7f21f 100644
--- a/Documentation/zh_CN/video4linux/v4l2-framework.txt
+++ b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
diff --git a/Documentation/zh_CN/volatile-considered-harmful.txt b/Documentation/translations/zh_CN/volatile-considered-harmful.txt
index ba8149d2233a..475125967197 100644
--- a/Documentation/zh_CN/volatile-considered-harmful.txt
+++ b/Documentation/translations/zh_CN/volatile-considered-harmful.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/volatile-considered-harmful.txt
+Chinese translated version of Documentation/process/volatile-considered-harmful.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -9,7 +9,7 @@ or if there is a problem with the translation.
Maintainer: Jonathan Corbet <corbet@lwn.net>
Chinese maintainer: Bryan Wu <bryan.wu@analog.com>
---------------------------------------------------------------------
-Documentation/volatile-considered-harmful.txt 的中文翻译
+Documentation/process/volatile-considered-harmful.rst 的中文翻译
如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
diff --git a/Documentation/vfio-mediated-device.txt b/Documentation/vfio-mediated-device.txt
new file mode 100644
index 000000000000..b38afec35edc
--- /dev/null
+++ b/Documentation/vfio-mediated-device.txt
@@ -0,0 +1,398 @@
+/*
+ * VFIO Mediated devices
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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.
+ */
+
+Virtual Function I/O (VFIO) Mediated devices[1]
+===============================================
+
+The number of use cases for virtualizing DMA devices that do not have built-in
+SR_IOV capability is increasing. Previously, to virtualize such devices,
+developers had to create their own management interfaces and APIs, and then
+integrate them with user space software. To simplify integration with user space
+software, we have identified common requirements and a unified management
+interface for such devices.
+
+The VFIO driver framework provides unified APIs for direct device access. It is
+an IOMMU/device-agnostic framework for exposing direct device access to user
+space in a secure, IOMMU-protected environment. This framework is used for
+multiple devices, such as GPUs, network adapters, and compute accelerators. With
+direct device access, virtual machines or user space applications have direct
+access to the physical device. This framework is reused for mediated devices.
+
+The mediated core driver provides a common interface for mediated device
+management that can be used by drivers of different devices. This module
+provides a generic interface to perform these operations:
+
+* Create and destroy a mediated device
+* Add a mediated device to and remove it from a mediated bus driver
+* Add a mediated device to and remove it from an IOMMU group
+
+The mediated core driver also provides an interface to register a bus driver.
+For example, the mediated VFIO mdev driver is designed for mediated devices and
+supports VFIO APIs. The mediated bus driver adds a mediated device to and
+removes it from a VFIO group.
+
+The following high-level block diagram shows the main components and interfaces
+in the VFIO mediated driver framework. The diagram shows NVIDIA, Intel, and IBM
+devices as examples, as these devices are the first devices to use this module.
+
+ +---------------+
+ | |
+ | +-----------+ | mdev_register_driver() +--------------+
+ | | | +<------------------------+ |
+ | | mdev | | | |
+ | | bus | +------------------------>+ vfio_mdev.ko |<-> VFIO user
+ | | driver | | probe()/remove() | | APIs
+ | | | | +--------------+
+ | +-----------+ |
+ | |
+ | MDEV CORE |
+ | MODULE |
+ | mdev.ko |
+ | +-----------+ | mdev_register_device() +--------------+
+ | | | +<------------------------+ |
+ | | | | | nvidia.ko |<-> physical
+ | | | +------------------------>+ | device
+ | | | | callbacks +--------------+
+ | | Physical | |
+ | | device | | mdev_register_device() +--------------+
+ | | interface | |<------------------------+ |
+ | | | | | i915.ko |<-> physical
+ | | | +------------------------>+ | device
+ | | | | callbacks +--------------+
+ | | | |
+ | | | | mdev_register_device() +--------------+
+ | | | +<------------------------+ |
+ | | | | | ccw_device.ko|<-> physical
+ | | | +------------------------>+ | device
+ | | | | callbacks +--------------+
+ | +-----------+ |
+ +---------------+
+
+
+Registration Interfaces
+=======================
+
+The mediated core driver provides the following types of registration
+interfaces:
+
+* Registration interface for a mediated bus driver
+* Physical device driver interface
+
+Registration Interface for a Mediated Bus Driver
+------------------------------------------------
+
+The registration interface for a mediated bus driver provides the following
+structure to represent a mediated device's driver:
+
+ /*
+ * struct mdev_driver [2] - Mediated device's driver
+ * @name: driver name
+ * @probe: called when new device created
+ * @remove: called when device removed
+ * @driver: device driver structure
+ */
+ struct mdev_driver {
+ const char *name;
+ int (*probe) (struct device *dev);
+ void (*remove) (struct device *dev);
+ struct device_driver driver;
+ };
+
+A mediated bus driver for mdev should use this structure in the function calls
+to register and unregister itself with the core driver:
+
+* Register:
+
+ extern int mdev_register_driver(struct mdev_driver *drv,
+ struct module *owner);
+
+* Unregister:
+
+ extern void mdev_unregister_driver(struct mdev_driver *drv);
+
+The mediated bus driver is responsible for adding mediated devices to the VFIO
+group when devices are bound to the driver and removing mediated devices from
+the VFIO when devices are unbound from the driver.
+
+
+Physical Device Driver Interface
+--------------------------------
+
+The physical device driver interface provides the parent_ops[3] structure to
+define the APIs to manage work in the mediated core driver that is related to
+the physical device.
+
+The structures in the parent_ops structure are as follows:
+
+* dev_attr_groups: attributes of the parent device
+* mdev_attr_groups: attributes of the mediated device
+* supported_config: attributes to define supported configurations
+
+The functions in the parent_ops structure are as follows:
+
+* create: allocate basic resources in a driver for a mediated device
+* remove: free resources in a driver when a mediated device is destroyed
+
+The callbacks in the parent_ops structure are as follows:
+
+* open: open callback of mediated device
+* close: close callback of mediated device
+* ioctl: ioctl callback of mediated device
+* read : read emulation callback
+* write: write emulation callback
+* mmap: mmap emulation callback
+
+A driver should use the parent_ops structure in the function call to register
+itself with the mdev core driver:
+
+extern int mdev_register_device(struct device *dev,
+ const struct parent_ops *ops);
+
+However, the parent_ops structure is not required in the function call that a
+driver should use to unregister itself with the mdev core driver:
+
+extern void mdev_unregister_device(struct device *dev);
+
+
+Mediated Device Management Interface Through sysfs
+==================================================
+
+The management interface through sysfs enables user space software, such as
+libvirt, to query and configure mediated devices in a hardware-agnostic fashion.
+This management interface provides flexibility to the underlying physical
+device's driver to support features such as:
+
+* Mediated device hot plug
+* Multiple mediated devices in a single virtual machine
+* Multiple mediated devices from different physical devices
+
+Links in the mdev_bus Class Directory
+-------------------------------------
+The /sys/class/mdev_bus/ directory contains links to devices that are registered
+with the mdev core driver.
+
+Directories and files under the sysfs for Each Physical Device
+--------------------------------------------------------------
+
+|- [parent physical device]
+|--- Vendor-specific-attributes [optional]
+|--- [mdev_supported_types]
+| |--- [<type-id>]
+| | |--- create
+| | |--- name
+| | |--- available_instances
+| | |--- device_api
+| | |--- description
+| | |--- [devices]
+| |--- [<type-id>]
+| | |--- create
+| | |--- name
+| | |--- available_instances
+| | |--- device_api
+| | |--- description
+| | |--- [devices]
+| |--- [<type-id>]
+| |--- create
+| |--- name
+| |--- available_instances
+| |--- device_api
+| |--- description
+| |--- [devices]
+
+* [mdev_supported_types]
+
+ The list of currently supported mediated device types and their details.
+
+ [<type-id>], device_api, and available_instances are mandatory attributes
+ that should be provided by vendor driver.
+
+* [<type-id>]
+
+ The [<type-id>] name is created by adding the the device driver string as a
+ prefix to the string provided by the vendor driver. This format of this name
+ is as follows:
+
+ sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
+
+* device_api
+
+ This attribute should show which device API is being created, for example,
+ "vfio-pci" for a PCI device.
+
+* available_instances
+
+ This attribute should show the number of devices of type <type-id> that can be
+ created.
+
+* [device]
+
+ This directory contains links to the devices of type <type-id> that have been
+created.
+
+* name
+
+ This attribute should show human readable name. This is optional attribute.
+
+* description
+
+ This attribute should show brief features/description of the type. This is
+ optional attribute.
+
+Directories and Files Under the sysfs for Each mdev Device
+----------------------------------------------------------
+
+|- [parent phy device]
+|--- [$MDEV_UUID]
+ |--- remove
+ |--- mdev_type {link to its type}
+ |--- vendor-specific-attributes [optional]
+
+* remove (write only)
+Writing '1' to the 'remove' file destroys the mdev device. The vendor driver can
+fail the remove() callback if that device is active and the vendor driver
+doesn't support hot unplug.
+
+Example:
+ # echo 1 > /sys/bus/mdev/devices/$mdev_UUID/remove
+
+Mediated device Hot plug:
+------------------------
+
+Mediated devices can be created and assigned at runtime. The procedure to hot
+plug a mediated device is the same as the procedure to hot plug a PCI device.
+
+Translation APIs for Mediated Devices
+=====================================
+
+The following APIs are provided for translating user pfn to host pfn in a VFIO
+driver:
+
+extern int vfio_pin_pages(struct device *dev, unsigned long *user_pfn,
+ int npage, int prot, unsigned long *phys_pfn);
+
+extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn,
+ int npage);
+
+These functions call back into the back-end IOMMU module by using the pin_pages
+and unpin_pages callbacks of the struct vfio_iommu_driver_ops[4]. Currently
+these callbacks are supported in the TYPE1 IOMMU module. To enable them for
+other IOMMU backend modules, such as PPC64 sPAPR module, they need to provide
+these two callback functions.
+
+Using the Sample Code
+=====================
+
+mtty.c in samples/vfio-mdev/ directory is a sample driver program to
+demonstrate how to use the mediated device framework.
+
+The sample driver creates an mdev device that simulates a serial port over a PCI
+card.
+
+1. Build and load the mtty.ko module.
+
+ This step creates a dummy device, /sys/devices/virtual/mtty/mtty/
+
+ Files in this device directory in sysfs are similar to the following:
+
+ # tree /sys/devices/virtual/mtty/mtty/
+ /sys/devices/virtual/mtty/mtty/
+ |-- mdev_supported_types
+ | |-- mtty-1
+ | | |-- available_instances
+ | | |-- create
+ | | |-- device_api
+ | | |-- devices
+ | | `-- name
+ | `-- mtty-2
+ | |-- available_instances
+ | |-- create
+ | |-- device_api
+ | |-- devices
+ | `-- name
+ |-- mtty_dev
+ | `-- sample_mtty_dev
+ |-- power
+ | |-- autosuspend_delay_ms
+ | |-- control
+ | |-- runtime_active_time
+ | |-- runtime_status
+ | `-- runtime_suspended_time
+ |-- subsystem -> ../../../../class/mtty
+ `-- uevent
+
+2. Create a mediated device by using the dummy device that you created in the
+ previous step.
+
+ # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" > \
+ /sys/devices/virtual/mtty/mtty/mdev_supported_types/mtty-2/create
+
+3. Add parameters to qemu-kvm.
+
+ -device vfio-pci,\
+ sysfsdev=/sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001
+
+4. Boot the VM.
+
+ In the Linux guest VM, with no hardware on the host, the device appears
+ as follows:
+
+ # lspci -s 00:05.0 -xxvv
+ 00:05.0 Serial controller: Device 4348:3253 (rev 10) (prog-if 02 [16550])
+ Subsystem: Device 4348:3253
+ Physical Slot: 5
+ Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr-
+ Stepping- SERR- FastB2B- DisINTx-
+ Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort-
+ <TAbort- <MAbort- >SERR- <PERR- INTx-
+ Interrupt: pin A routed to IRQ 10
+ Region 0: I/O ports at c150 [size=8]
+ Region 1: I/O ports at c158 [size=8]
+ Kernel driver in use: serial
+ 00: 48 43 53 32 01 00 00 02 10 02 00 07 00 00 00 00
+ 10: 51 c1 00 00 59 c1 00 00 00 00 00 00 00 00 00 00
+ 20: 00 00 00 00 00 00 00 00 00 00 00 00 48 43 53 32
+ 30: 00 00 00 00 00 00 00 00 00 00 00 00 0a 01 00 00
+
+ In the Linux guest VM, dmesg output for the device is as follows:
+
+ serial 0000:00:05.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, high) -> IRQ
+10
+ 0000:00:05.0: ttyS1 at I/O 0xc150 (irq = 10) is a 16550A
+ 0000:00:05.0: ttyS2 at I/O 0xc158 (irq = 10) is a 16550A
+
+
+5. In the Linux guest VM, check the serial ports.
+
+ # setserial -g /dev/ttyS*
+ /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
+ /dev/ttyS1, UART: 16550A, Port: 0xc150, IRQ: 10
+ /dev/ttyS2, UART: 16550A, Port: 0xc158, IRQ: 10
+
+6. Using a minicom or any terminal enulation program, open port /dev/ttyS1 or
+ /dev/ttyS2 with hardware flow control disabled.
+
+7. Type data on the minicom terminal or send data to the terminal emulation
+ program and read the data.
+
+ Data is loop backed from hosts mtty driver.
+
+8. Destroy the mediated device that you created.
+
+ # echo 1 > /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001/remove
+
+References
+==========
+
+[1] See Documentation/vfio.txt for more information on VFIO.
+[2] struct mdev_driver in include/linux/mdev.h
+[3] struct parent_ops in include/linux/mdev.h
+[4] struct vfio_iommu_driver_ops in include/linux/vfio.h
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
index 2a71c8f29f68..0a9ea515512a 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virtual/kvm/msr.txt
@@ -208,7 +208,9 @@ MSR_KVM_STEAL_TIME: 0x4b564d03
__u64 steal;
__u32 version;
__u32 flags;
- __u32 pad[12];
+ __u8 preempted;
+ __u8 u8_pad[3];
+ __u32 pad[11];
}
whose data will be filled in by the hypervisor periodically. Only one
@@ -232,6 +234,11 @@ MSR_KVM_STEAL_TIME: 0x4b564d03
nanoseconds. Time during which the vcpu is idle, will not be
reported as steal time.
+ preempted: indicate the vCPU who owns this struct is running or
+ not. Non-zero values mean the vCPU has been preempted. Zero
+ means the vCPU is not preempted. NOTE, it is always zero if the
+ the hypervisor doesn't support this field.
+
MSR_KVM_EOI_EN: 0x4b564d04
data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
when disabled. Bit 1 is reserved and must be zero. When PV end of
diff --git a/Documentation/virtual/kvm/review-checklist.txt b/Documentation/virtual/kvm/review-checklist.txt
index a850986ed684..a83b27635fdd 100644
--- a/Documentation/virtual/kvm/review-checklist.txt
+++ b/Documentation/virtual/kvm/review-checklist.txt
@@ -1,8 +1,8 @@
Review checklist for kvm patches
================================
-1. The patch must follow Documentation/CodingStyle and
- Documentation/SubmittingPatches.
+1. The patch must follow Documentation/process/coding-style.rst and
+ Documentation/process/submitting-patches.rst.
2. Patches should be against kvm.git master branch.
diff --git a/Documentation/vm/numa b/Documentation/vm/numa
index e0b58c0e6b49..a08f71647714 100644
--- a/Documentation/vm/numa
+++ b/Documentation/vm/numa
@@ -82,7 +82,7 @@ such as DMA or DMA32, represent relatively scarce resources. Linux chooses
a default zonelist order based on the sizes of the various zone types relative
to the total memory of the node and the total memory of the system. The
default zonelist order may be overridden using the numa_zonelist_order kernel
-boot parameter or sysctl. [see Documentation/kernel-parameters.txt and
+boot parameter or sysctl. [see Documentation/admin-guide/kernel-parameters.rst and
Documentation/sysctl/vm.txt]
By default, Linux will attempt to satisfy memory allocation requests from the
diff --git a/Documentation/vm/transhuge.txt b/Documentation/vm/transhuge.txt
index 2ec6adb5a4ce..c4171e4519c2 100644
--- a/Documentation/vm/transhuge.txt
+++ b/Documentation/vm/transhuge.txt
@@ -136,6 +136,11 @@ or enable it back by writing 1:
echo 0 >/sys/kernel/mm/transparent_hugepage/use_zero_page
echo 1 >/sys/kernel/mm/transparent_hugepage/use_zero_page
+Some userspace (such as a test program, or an optimized memory allocation
+library) may want to know the size (in bytes) of a transparent hugepage:
+
+cat /sys/kernel/mm/transparent_hugepage/hpage_pmd_size
+
khugepaged will be automatically started when
transparent_hugepage/enabled is set to "always" or "madvise, and it'll
be automatically shutdown if it's set to "never".
diff --git a/Documentation/watchdog/convert_drivers_to_kernel_api.txt b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
index 271b8850dde7..9fffb2958d13 100644
--- a/Documentation/watchdog/convert_drivers_to_kernel_api.txt
+++ b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
@@ -213,6 +213,6 @@ The entry for the driver now needs to select WATCHDOG_CORE:
Create a patch and send it to upstream
--------------------------------------
-Make sure you understood Documentation/SubmittingPatches and send your patch to
+Make sure you understood Documentation/process/submitting-patches.rst and send your patch to
linux-watchdog@vger.kernel.org. We are looking forward to it :)
diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt
index a8d364227a77..e21850e270a0 100644
--- a/Documentation/watchdog/watchdog-parameters.txt
+++ b/Documentation/watchdog/watchdog-parameters.txt
@@ -4,7 +4,7 @@ be listed here unless the driver has its own driver-specific information
file.
-See Documentation/kernel-parameters.txt for information on
+See Documentation/admin-guide/kernel-parameters.rst for information on
providing kernel parameters for builtin drivers versus loadable
modules.
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index 9da6f3512249..5e9b826b5f62 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -921,7 +921,7 @@ They should normally not be deleted from the kernel command line even
though not all of them are actually meaningful to the kernel. Boot
loader authors who need additional command line options for the boot
loader itself should get them registered in
-Documentation/kernel-parameters.txt to make sure they will not
+Documentation/admin-guide/kernel-parameters.rst to make sure they will not
conflict with actual kernel options now or in the future.
vga=<mode>
diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
index 0965a71f9942..61b611e9eeaf 100644
--- a/Documentation/x86/x86_64/boot-options.txt
+++ b/Documentation/x86/x86_64/boot-options.txt
@@ -277,10 +277,6 @@ IOMMU (input/output memory management unit)
space might stop working. Use this option if you have devices that
are accessed from userspace directly on some PCI host bridge.
-Debugging
-
- kstack=N Print N words from the kernel stack in oops dumps.
-
Miscellaneous
nogbpages
diff --git a/MAINTAINERS b/MAINTAINERS
index 63cefa62324c..34ef63763566 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -35,13 +35,13 @@ trivial patch so apply some common sense.
PLEASE check your patch with the automated style checker
(scripts/checkpatch.pl) to catch trivial style violations.
- See Documentation/CodingStyle for guidance here.
+ See Documentation/process/coding-style.rst for guidance here.
PLEASE CC: the maintainers and mailing lists that are generated
by scripts/get_maintainer.pl. The results returned by the
script will be best if you have git installed and are making
your changes in a branch derived from Linus' latest git tree.
- See Documentation/SubmittingPatches for details.
+ See Documentation/process/submitting-patches.rst for details.
PLEASE try to include any credit lines you want added with the
patch. It avoids people being missed off by mistake and makes
@@ -54,7 +54,7 @@ trivial patch so apply some common sense.
of the Linux Foundation certificate of contribution and should
include a Signed-off-by: line. The current version of this
"Developer's Certificate of Origin" (DCO) is listed in the file
- Documentation/SubmittingPatches.
+ Documentation/process/submitting-patches.rst.
6. Make sure you have the right to send any changes you make. If you
do changes at work you may find your employer owns the patch
@@ -74,6 +74,10 @@ Descriptions of section entries:
These reviewers should be CCed on patches.
L: Mailing list that is relevant to this area
W: Web-page with status/info
+ B: URI for where to file bugs. A web-page with detailed bug
+ filing info, a direct bug tracker link, or a mailto: URI.
+ C: URI for chat protocol, server and channel where developers
+ usually hang out, for example irc://server/channel.
Q: Patchwork web based patch tracking system site
T: SCM tree type and location.
Type is one of: git, hg, quilt, stgit, topgit
@@ -577,6 +581,11 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/usb/airspy/
+ALACRITECH GIGABIT ETHERNET DRIVER
+M: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+S: Maintained
+F: drivers/net/ethernet/alacritech/*
+
ALCATEL SPEEDTOUCH USB DRIVER
M: Duncan Sands <duncan.sands@free.fr>
L: linux-usb@vger.kernel.org
@@ -1043,6 +1052,7 @@ F: arch/arm/mach-meson/
F: arch/arm/boot/dts/meson*
F: arch/arm64/boot/dts/amlogic/
F: drivers/pinctrl/meson/
+F: drivers/mmc/host/meson*
N: meson
ARM/Annapurna Labs ALPINE ARCHITECTURE
@@ -1782,6 +1792,7 @@ F: drivers/char/hw_random/st-rng.c
F: drivers/clocksource/arm_global_timer.c
F: drivers/clocksource/clksrc_st_lpc.c
F: drivers/cpufreq/sti-cpufreq.c
+F: drivers/dma/st_fdma*
F: drivers/i2c/busses/i2c-st.c
F: drivers/media/rc/st_rc.c
F: drivers/media/platform/sti/c8sectpfe/
@@ -1792,6 +1803,7 @@ F: drivers/phy/phy-stih407-usb.c
F: drivers/phy/phy-stih41x-usb.c
F: drivers/pinctrl/pinctrl-st.c
F: drivers/remoteproc/st_remoteproc.c
+F: drivers/remoteproc/st_slim_rproc.c
F: drivers/reset/sti/
F: drivers/rtc/rtc-st-lpc.c
F: drivers/tty/serial/st-asc.c
@@ -1800,6 +1812,7 @@ F: drivers/usb/host/ehci-st.c
F: drivers/usb/host/ohci-st.c
F: drivers/watchdog/st_lpc_wdt.c
F: drivers/ata/ahci_st.c
+F: include/linux/remoteproc/st_slim_rproc.h
ARM/STM32 ARCHITECTURE
M: Maxime Coquelin <mcoquelin.stm32@gmail.com>
@@ -2537,6 +2550,8 @@ L: netdev@vger.kernel.org
L: linux-kernel@vger.kernel.org
S: Supported
F: kernel/bpf/
+F: tools/testing/selftests/bpf/
+F: lib/test_bpf.c
BROADCOM B44 10/100 ETHERNET DRIVER
M: Michael Chan <michael.chan@broadcom.com>
@@ -2749,6 +2764,14 @@ L: bcm-kernel-feedback-list@broadcom.com
S: Maintained
F: drivers/mtd/nand/brcmnand/
+BROADCOM STB AVS CPUFREQ DRIVER
+M: Markus Mayer <mmayer@broadcom.com>
+M: bcm-kernel-feedback-list@broadcom.com
+L: linux-pm@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
+F: drivers/cpufreq/brcmstb*
+
BROADCOM SPECIFIC AMBA DRIVER (BCMA)
M: Rafał Miłecki <zajec5@gmail.com>
L: linux-wireless@vger.kernel.org
@@ -2937,7 +2960,7 @@ CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER
M: Kevin Tsai <ktsai@capellamicro.com>
S: Maintained
F: drivers/iio/light/cm*
-F: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+F: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
CAVIUM I2C DRIVER
M: Jan Glauber <jglauber@cavium.com>
@@ -3085,7 +3108,7 @@ M: Harry Wei <harryxiyou@gmail.com>
L: xiyoulinuxkernelgroup@googlegroups.com (subscribers-only)
L: linux-kernel@zh-kernel.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/zh_CN/
+F: Documentation/translations/zh_CN/
CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
M: Peter Chen <Peter.Chen@nxp.com>
@@ -3341,6 +3364,7 @@ L: linux-pm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
T: git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates)
+B: https://bugzilla.kernel.org
F: Documentation/cpu-freq/
F: drivers/cpufreq/
F: include/linux/cpufreq.h
@@ -3380,6 +3404,7 @@ M: Daniel Lezcano <daniel.lezcano@linaro.org>
L: linux-pm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
+B: https://bugzilla.kernel.org
F: drivers/cpuidle/*
F: include/linux/cpuidle.h
@@ -3918,7 +3943,7 @@ F: include/linux/dma-buf*
F: include/linux/reservation.h
F: include/linux/*fence.h
F: Documentation/dma-buf-sharing.txt
-T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
+T: git git://anongit.freedesktop.org/drm/drm-misc
SYNC FILE FRAMEWORK
M: Sumit Semwal <sumit.semwal@linaro.org>
@@ -3926,10 +3951,12 @@ R: Gustavo Padovan <gustavo@padovan.org>
S: Maintained
L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org
-F: drivers/dma-buf/sync_file.c
+F: drivers/dma-buf/sync_*
+F: drivers/dma-buf/sw_sync.c
F: include/linux/sync_file.h
+F: include/uapi/linux/sync_file.h
F: Documentation/sync_file.txt
-T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
+T: git git://anongit.freedesktop.org/drm/drm-misc
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
M: Vinod Koul <vinod.koul@intel.com>
@@ -4017,6 +4044,8 @@ DRM DRIVERS
M: David Airlie <airlied@linux.ie>
L: dri-devel@lists.freedesktop.org
T: git git://people.freedesktop.org/~airlied/linux
+B: https://bugs.freedesktop.org/
+C: irc://chat.freenode.net/dri-devel
S: Maintained
F: drivers/gpu/drm/
F: drivers/gpu/vga/
@@ -4027,11 +4056,30 @@ F: Documentation/gpu/
F: include/drm/
F: include/uapi/drm/
+DRM DRIVERS AND MISC GPU PATCHES
+M: Daniel Vetter <daniel.vetter@intel.com>
+M: Jani Nikula <jani.nikula@linux.intel.com>
+M: Sean Paul <seanpaul@chromium.org>
+W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/gpu/
+F: drivers/gpu/vga/
+F: drivers/gpu/drm/*
+F: include/drm/drm*
+F: include/uapi/drm/drm*
+
DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
M: Dave Airlie <airlied@redhat.com>
S: Odd Fixes
F: drivers/gpu/drm/ast/
+DRM DRIVERS FOR BRIDGE CHIPS
+M: Archit Taneja <architt@codeaurora.org>
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: drivers/gpu/drm/bridge/
+
DRM DRIVER FOR BOCHS VIRTUAL GPU
M: Gerd Hoffmann <kraxel@redhat.com>
S: Odd Fixes
@@ -4067,8 +4115,9 @@ INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
M: Daniel Vetter <daniel.vetter@intel.com>
M: Jani Nikula <jani.nikula@linux.intel.com>
L: intel-gfx@lists.freedesktop.org
-L: dri-devel@lists.freedesktop.org
W: https://01.org/linuxgraphics/
+B: https://01.org/linuxgraphics/documentation/how-report-bugs
+C: irc://chat.freenode.net/intel-gfx
Q: http://patchwork.freedesktop.org/project/intel-gfx/
T: git git://anongit.freedesktop.org/drm-intel
S: Supported
@@ -4077,6 +4126,16 @@ F: include/drm/i915*
F: include/uapi/drm/i915_drm.h
F: Documentation/gpu/i915.rst
+INTEL GVT-g DRIVERS (Intel GPU Virtualization)
+M: Zhenyu Wang <zhenyuw@linux.intel.com>
+M: Zhi Wang <zhi.a.wang@intel.com>
+L: igvt-g-dev@lists.01.org
+L: intel-gfx@lists.freedesktop.org
+W: https://01.org/igvt-g
+T: git https://github.com/01org/gvt-linux.git
+S: Supported
+F: drivers/gpu/drm/i915/gvt/
+
DRM DRIVERS FOR ATMEL HLCDC
M: Boris Brezillon <boris.brezillon@free-electrons.com>
L: dri-devel@lists.freedesktop.org
@@ -4091,6 +4150,15 @@ S: Supported
F: drivers/gpu/drm/sun4i/
F: Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+DRM DRIVERS FOR AMLOGIC SOCS
+M: Neil Armstrong <narmstrong@baylibre.com>
+L: dri-devel@lists.freedesktop.org
+L: linux-amlogic@lists.infradead.org
+W: http://linux-meson.com/
+S: Supported
+F: drivers/gpu/drm/meson/
+F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
+
DRM DRIVERS FOR EXYNOS
M: Inki Dae <inki.dae@samsung.com>
M: Joonyoung Shim <jy0922.shim@samsung.com>
@@ -4130,6 +4198,7 @@ F: drivers/gpu/drm/gma500/
DRM DRIVERS FOR HISILICON
M: Xinliang Liu <z.liuxinliang@hisilicon.com>
+M: Rongrong Zou <zourongrong@gmail.com>
R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
R: Chen Feng <puck.chen@hisilicon.com>
L: dri-devel@lists.freedesktop.org
@@ -4254,6 +4323,7 @@ DRM DRIVERS FOR VIVANTE GPU IP
M: Lucas Stach <l.stach@pengutronix.de>
R: Russell King <linux+etnaviv@armlinux.org.uk>
R: Christian Gmeiner <christian.gmeiner@gmail.com>
+L: etnaviv@lists.freedesktop.org
L: dri-devel@lists.freedesktop.org
S: Maintained
F: drivers/gpu/drm/etnaviv/
@@ -4294,6 +4364,13 @@ S: Maintained
F: drivers/gpu/drm/tilcdc/
F: Documentation/devicetree/bindings/display/tilcdc/
+DRM DRIVERS FOR ZTE ZX
+M: Shawn Guo <shawnguo@kernel.org>
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+F: drivers/gpu/drm/zte/
+F: Documentation/devicetree/bindings/display/zte,vou.txt
+
DSBR100 USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org
@@ -4638,12 +4715,14 @@ L: linux-efi@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
S: Maintained
F: Documentation/efi-stub.txt
-F: arch/ia64/kernel/efi.c
+F: arch/*/kernel/efi.c
F: arch/x86/boot/compressed/eboot.[ch]
-F: arch/x86/include/asm/efi.h
+F: arch/*/include/asm/efi.h
F: arch/x86/platform/efi/
F: drivers/firmware/efi/
F: include/linux/efi*.h
+F: arch/arm/boot/compressed/efi-header.S
+F: arch/arm64/kernel/efi-entry.S
EFI VARIABLE FILESYSTEM
M: Matthew Garrett <matthew.garrett@nebula.com>
@@ -4975,10 +5054,9 @@ F: drivers/net/wan/dlci.c
F: drivers/net/wan/sdla.c
FRAMEBUFFER LAYER
-M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-fbdev/list/
-S: Maintained
+S: Orphan
F: Documentation/fb/
F: drivers/video/
F: include/video/
@@ -5051,9 +5129,18 @@ S: Maintained
F: drivers/net/ethernet/freescale/fman
F: Documentation/devicetree/bindings/powerpc/fsl/fman.txt
+FREESCALE SOC DRIVERS
+M: Scott Wood <oss@buserror.net>
+L: linuxppc-dev@lists.ozlabs.org
+L: linux-arm-kernel@lists.infradead.org
+S: Maintained
+F: drivers/soc/fsl/
+F: include/linux/fsl/
+
FREESCALE QUICC ENGINE LIBRARY
+M: Qiang Zhao <qiang.zhao@nxp.com>
L: linuxppc-dev@lists.ozlabs.org
-S: Orphan
+S: Maintained
F: drivers/soc/fsl/qe/
F: include/soc/fsl/*qe*.h
F: include/soc/fsl/*ucc*.h
@@ -5209,6 +5296,7 @@ L: kernel-hardening@lists.openwall.com
S: Maintained
F: scripts/gcc-plugins/
F: scripts/gcc-plugin.sh
+F: scripts/Makefile.gcc-plugins
F: Documentation/gcc-plugins.txt
GCOV BASED KERNEL PROFILING
@@ -6095,14 +6183,9 @@ S: Maintained
F: Documentation/cdrom/ide-cd
F: drivers/ide/ide-cd*
-IDLE-I7300
-M: Andy Henroid <andrew.d.henroid@intel.com>
-L: linux-pm@vger.kernel.org
-S: Supported
-F: drivers/idle/i7300_idle.c
-
IEEE 802.15.4 SUBSYSTEM
M: Alexander Aring <aar@pengutronix.de>
+M: Stefan Schmidt <stefan@osg.samsung.com>
L: linux-wpan@vger.kernel.org
W: http://wpan.cakelab.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
@@ -6289,9 +6372,11 @@ S: Maintained
F: drivers/platform/x86/intel-vbtn.c
INTEL IDLE DRIVER
+M: Jacob Pan <jacob.jun.pan@linux.intel.com>
M: Len Brown <lenb@kernel.org>
L: linux-pm@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git
+B: https://bugzilla.kernel.org
S: Supported
F: drivers/idle/intel_idle.c
@@ -7565,8 +7650,10 @@ S: Maintained
MARVELL 88E6XXX ETHERNET SWITCH FABRIC DRIVER
M: Andrew Lunn <andrew@lunn.ch>
M: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/dsa/mv88e6xxx/
+F: Documentation/devicetree/bindings/net/dsa/marvell.txt
MARVELL ARMADA DRM SUPPORT
M: Russell King <rmk+kernel@armlinux.org.uk>
@@ -8280,6 +8367,12 @@ T: git git://linuxtv.org/mkrufky/tuners.git
S: Maintained
F: drivers/media/tuners/mxl5007t.*
+MXSFB DRM DRIVER
+M: Marek Vasut <marex@denx.de>
+S: Supported
+F: drivers/gpu/drm/mxsfb/
+F: Documentation/devicetree/bindings/display/mxsfb-drm.txt
+
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
M: Hyong-Youb Kim <hykim@myri.com>
L: netdev@vger.kernel.org
@@ -8457,7 +8550,6 @@ F: include/uapi/linux/net_namespace.h
F: tools/net/
F: tools/testing/selftests/net/
F: lib/random32.c
-F: lib/test_bpf.c
NETWORKING [IPv4/IPv6]
M: "David S. Miller" <davem@davemloft.net>
@@ -8686,6 +8778,16 @@ L: linux-nvme@lists.infradead.org
S: Supported
F: drivers/nvme/target/
+NVM EXPRESS FC TRANSPORT DRIVERS
+M: James Smart <james.smart@broadcom.com>
+L: linux-nvme@lists.infradead.org
+S: Supported
+F: include/linux/nvme-fc.h
+F: include/linux/nvme-fc-driver.h
+F: drivers/nvme/host/fc.c
+F: drivers/nvme/target/fc.c
+F: drivers/nvme/target/fcloop.c
+
NVMEM FRAMEWORK
M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
M: Maxime Ripard <maxime.ripard@free-electrons.com>
@@ -8748,6 +8850,7 @@ F: drivers/regulator/tps65217-regulator.c
F: drivers/regulator/tps65218-regulator.c
F: drivers/regulator/tps65910-regulator.c
F: drivers/regulator/twl-regulator.c
+F: drivers/regulator/twl6030-regulator.c
F: include/linux/i2c-omap.h
OMAP DEVICE TREE SUPPORT
@@ -8968,9 +9071,11 @@ F: drivers/of/resolver.c
OPENRISC ARCHITECTURE
M: Jonas Bonn <jonas@southpole.se>
-W: http://openrisc.net
+M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+M: Stafford Horne <shorne@gmail.com>
+L: openrisc@lists.librecores.org
+W: http://openrisc.io
S: Maintained
-T: git git://openrisc.net/~jonas/linux
F: arch/openrisc/
OPENVSWITCH
@@ -9573,8 +9678,8 @@ F: arch/mips/boot/dts/pistachio/
F: arch/mips/configs/pistachio*_defconfig
PKTCDVD DRIVER
-M: Jiri Kosina <jikos@kernel.org>
-S: Maintained
+S: Orphan
+M: linux-block@vger.kernel.org
F: drivers/block/pktcdvd.c
F: include/linux/pktcdvd.h
F: include/uapi/linux/pktcdvd.h
@@ -9809,7 +9914,7 @@ F: drivers/media/usb/pwc/*
PWM FAN DRIVER
M: Kamil Debski <kamil@wypas.org>
-M: Lukasz Majewski <l.majewski@samsung.com>
+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
L: linux-hwmon@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
@@ -10580,7 +10685,7 @@ L: netdev@vger.kernel.org
F: drivers/net/ethernet/samsung/sxgbe/
SAMSUNG THERMAL DRIVER
-M: Lukasz Majewski <l.majewski@samsung.com>
+M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
L: linux-pm@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Supported
@@ -11471,7 +11576,7 @@ STABLE BRANCH
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: stable@vger.kernel.org
S: Supported
-F: Documentation/stable_kernel_rules.txt
+F: Documentation/process/stable-kernel-rules.rst
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -12761,6 +12866,15 @@ F: drivers/vfio/
F: include/linux/vfio.h
F: include/uapi/linux/vfio.h
+VFIO MEDIATED DEVICE DRIVERS
+M: Kirti Wankhede <kwankhede@nvidia.com>
+L: kvm@vger.kernel.org
+S: Maintained
+F: Documentation/vfio-mediated-device.txt
+F: drivers/vfio/mdev/
+F: include/linux/mdev.h
+F: samples/vfio-mdev/
+
VFIO PLATFORM DRIVER
M: Baptiste Reynal <b.reynal@virtualopensystems.com>
L: kvm@vger.kernel.org
@@ -12913,7 +13027,7 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: devel@driverdev.osuosl.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
-F: Documentation/vme_api.txt
+F: Documentation/driver-api/vme.rst
F: drivers/staging/vme/
F: drivers/vme/
F: include/linux/vme*
@@ -13137,7 +13251,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
S: Maintained
F: include/linux/workqueue.h
F: kernel/workqueue.c
-F: Documentation/workqueue.txt
+F: Documentation/core-api/workqueue.rst
X-POWERS MULTIFUNCTION PMIC DEVICE DRIVERS
M: Chen-Yu Tsai <wens@csie.org>
diff --git a/README b/README
index 09f34f78f2bb..b2ba4aaa3a71 100644
--- a/README
+++ b/README
@@ -1,400 +1,18 @@
- Linux kernel release 4.x <http://kernel.org/>
+Linux kernel
+============
-These are the release notes for Linux version 4. Read them carefully,
-as they tell you what this is all about, explain how to install the
-kernel, and what to do if something goes wrong.
+This file was moved to Documentation/admin-guide/README.rst
-WHAT IS LINUX?
+Please notice that there are several guides for kernel developers and users.
+These guides can be rendered in a number of formats, like HTML and PDF.
- Linux is a clone of the operating system Unix, written from scratch by
- Linus Torvalds with assistance from a loosely-knit team of hackers across
- the Net. It aims towards POSIX and Single UNIX Specification compliance.
+In order to build the documentation, use ``make htmldocs`` or
+``make pdfdocs``.
- It has all the features you would expect in a modern fully-fledged Unix,
- including true multitasking, virtual memory, shared libraries, demand
- loading, shared copy-on-write executables, proper memory management,
- and multistack networking including IPv4 and IPv6.
-
- It is distributed under the GNU General Public License - see the
- accompanying COPYING file for more details.
-
-ON WHAT HARDWARE DOES IT RUN?
-
- Although originally developed first for 32-bit x86-based PCs (386 or higher),
- today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
- UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
- IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
- Xtensa, Tilera TILE, AVR32, ARC and Renesas M32R architectures.
-
- Linux is easily portable to most general-purpose 32- or 64-bit architectures
- as long as they have a paged memory management unit (PMMU) and a port of the
- GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
- also been ported to a number of architectures without a PMMU, although
- functionality is then obviously somewhat limited.
- Linux has also been ported to itself. You can now run the kernel as a
- userspace application - this is called UserMode Linux (UML).
-
-DOCUMENTATION:
-
- - There is a lot of documentation available both in electronic form on
- the Internet and in books, both Linux-specific and pertaining to
- general UNIX questions. I'd recommend looking into the documentation
- subdirectories on any Linux FTP site for the LDP (Linux Documentation
- Project) books. This README is not meant to be documentation on the
- system: there are much better sources available.
-
- - There are various README files in the Documentation/ subdirectory:
- these typically contain kernel-specific installation notes for some
- drivers for example. See Documentation/00-INDEX for a list of what
- is contained in each file. Please read the Changes file, as it
- contains information about the problems, which may result by upgrading
- your kernel.
-
- - The Documentation/DocBook/ subdirectory contains several guides for
- kernel developers and users. These guides can be rendered in a
- number of formats: PostScript (.ps), PDF, HTML, & man-pages, among others.
- After installation, "make psdocs", "make pdfdocs", "make htmldocs",
- or "make mandocs" will render the documentation in the requested format.
-
-INSTALLING the kernel source:
-
- - If you install the full sources, put the kernel tarball in a
- directory where you have permissions (e.g. your home directory) and
- unpack it:
-
- xz -cd linux-4.X.tar.xz | tar xvf -
-
- Replace "X" with the version number of the latest kernel.
-
- Do NOT use the /usr/src/linux area! This area has a (usually
- incomplete) set of kernel headers that are used by the library header
- files. They should match the library, and not get messed up by
- whatever the kernel-du-jour happens to be.
-
- - You can also upgrade between 4.x releases by patching. Patches are
- distributed in the xz format. To install by patching, get all the
- newer patch files, enter the top level directory of the kernel source
- (linux-4.X) and execute:
-
- xz -cd ../patch-4.x.xz | patch -p1
-
- Replace "x" for all versions bigger than the version "X" of your current
- source tree, _in_order_, and you should be ok. You may want to remove
- the backup files (some-file-name~ or some-file-name.orig), and make sure
- that there are no failed patches (some-file-name# or some-file-name.rej).
- If there are, either you or I have made a mistake.
-
- Unlike patches for the 4.x kernels, patches for the 4.x.y kernels
- (also known as the -stable kernels) are not incremental but instead apply
- directly to the base 4.x kernel. For example, if your base kernel is 4.0
- and you want to apply the 4.0.3 patch, you must not first apply the 4.0.1
- and 4.0.2 patches. Similarly, if you are running kernel version 4.0.2 and
- want to jump to 4.0.3, you must first reverse the 4.0.2 patch (that is,
- patch -R) _before_ applying the 4.0.3 patch. You can read more on this in
- Documentation/applying-patches.txt
-
- Alternatively, the script patch-kernel can be used to automate this
- process. It determines the current kernel version and applies any
- patches found.
-
- linux/scripts/patch-kernel linux
-
- The first argument in the command above is the location of the
- kernel source. Patches are applied from the current directory, but
- an alternative directory can be specified as the second argument.
-
- - Make sure you have no stale .o files and dependencies lying around:
-
- cd linux
- make mrproper
-
- You should now have the sources correctly installed.
-
-SOFTWARE REQUIREMENTS
-
- Compiling and running the 4.x kernels requires up-to-date
- versions of various software packages. Consult
- Documentation/Changes for the minimum version numbers required
- and how to get updates for these packages. Beware that using
- excessively old versions of these packages can cause indirect
- errors that are very difficult to track down, so don't assume that
- you can just update packages when obvious problems arise during
- build or operation.
-
-BUILD directory for the kernel:
-
- When compiling the kernel, all output files will per default be
- stored together with the kernel source code.
- Using the option "make O=output/dir" allows you to specify an alternate
- place for the output files (including .config).
- Example:
-
- kernel source code: /usr/src/linux-4.X
- build directory: /home/name/build/kernel
-
- To configure and build the kernel, use:
-
- cd /usr/src/linux-4.X
- make O=/home/name/build/kernel menuconfig
- make O=/home/name/build/kernel
- sudo make O=/home/name/build/kernel modules_install install
-
- Please note: If the 'O=output/dir' option is used, then it must be
- used for all invocations of make.
-
-CONFIGURING the kernel:
-
- Do not skip this step even if you are only upgrading one minor
- version. New configuration options are added in each release, and
- odd problems will turn up if the configuration files are not set up
- as expected. If you want to carry your existing configuration to a
- new version with minimal work, use "make oldconfig", which will
- only ask you for the answers to new questions.
-
- - Alternative configuration commands are:
-
- "make config" Plain text interface.
-
- "make menuconfig" Text based color menus, radiolists & dialogs.
-
- "make nconfig" Enhanced text based color menus.
-
- "make xconfig" Qt based configuration tool.
-
- "make gconfig" GTK+ based configuration tool.
-
- "make oldconfig" Default all questions based on the contents of
- your existing ./.config file and asking about
- new config symbols.
-
- "make silentoldconfig"
- Like above, but avoids cluttering the screen
- with questions already answered.
- Additionally updates the dependencies.
-
- "make olddefconfig"
- Like above, but sets new symbols to their default
- values without prompting.
-
- "make defconfig" Create a ./.config file by using the default
- symbol values from either arch/$ARCH/defconfig
- or arch/$ARCH/configs/${PLATFORM}_defconfig,
- depending on the architecture.
-
- "make ${PLATFORM}_defconfig"
- Create a ./.config file by using the default
- symbol values from
- arch/$ARCH/configs/${PLATFORM}_defconfig.
- Use "make help" to get a list of all available
- platforms of your architecture.
-
- "make allyesconfig"
- Create a ./.config file by setting symbol
- values to 'y' as much as possible.
-
- "make allmodconfig"
- Create a ./.config file by setting symbol
- values to 'm' as much as possible.
-
- "make allnoconfig" Create a ./.config file by setting symbol
- values to 'n' as much as possible.
-
- "make randconfig" Create a ./.config file by setting symbol
- values to random values.
-
- "make localmodconfig" Create a config based on current config and
- loaded modules (lsmod). Disables any module
- option that is not needed for the loaded modules.
-
- To create a localmodconfig for another machine,
- store the lsmod of that machine into a file
- and pass it in as a LSMOD parameter.
-
- target$ lsmod > /tmp/mylsmod
- target$ scp /tmp/mylsmod host:/tmp
-
- host$ make LSMOD=/tmp/mylsmod localmodconfig
-
- The above also works when cross compiling.
-
- "make localyesconfig" Similar to localmodconfig, except it will convert
- all module options to built in (=y) options.
-
- You can find more information on using the Linux kernel config tools
- in Documentation/kbuild/kconfig.txt.
-
- - NOTES on "make config":
-
- - Having unnecessary drivers will make the kernel bigger, and can
- under some circumstances lead to problems: probing for a
- nonexistent controller card may confuse your other controllers
-
- - A kernel with math-emulation compiled in will still use the
- coprocessor if one is present: the math emulation will just
- never get used in that case. The kernel will be slightly larger,
- but will work on different machines regardless of whether they
- have a math coprocessor or not.
-
- - The "kernel hacking" configuration details usually result in a
- bigger or slower kernel (or both), and can even make the kernel
- less stable by configuring some routines to actively try to
- break bad code to find kernel problems (kmalloc()). Thus you
- should probably answer 'n' to the questions for "development",
- "experimental", or "debugging" features.
-
-COMPILING the kernel:
-
- - Make sure you have at least gcc 3.2 available.
- For more information, refer to Documentation/Changes.
-
- Please note that you can still run a.out user programs with this kernel.
-
- - Do a "make" to create a compressed kernel image. It is also
- possible to do "make install" if you have lilo installed to suit the
- kernel makefiles, but you may want to check your particular lilo setup first.
-
- To do the actual install, you have to be root, but none of the normal
- build should require that. Don't take the name of root in vain.
-
- - If you configured any of the parts of the kernel as `modules', you
- will also have to do "make modules_install".
-
- - Verbose kernel compile/build output:
-
- Normally, the kernel build system runs in a fairly quiet mode (but not
- totally silent). However, sometimes you or other kernel developers need
- to see compile, link, or other commands exactly as they are executed.
- For this, use "verbose" build mode. This is done by passing
- "V=1" to the "make" command, e.g.
-
- make V=1 all
-
- To have the build system also tell the reason for the rebuild of each
- target, use "V=2". The default is "V=0".
-
- - Keep a backup kernel handy in case something goes wrong. This is
- especially true for the development releases, since each new release
- contains new code which has not been debugged. Make sure you keep a
- backup of the modules corresponding to that kernel, as well. If you
- are installing a new kernel with the same version number as your
- working kernel, make a backup of your modules directory before you
- do a "make modules_install".
-
- Alternatively, before compiling, use the kernel config option
- "LOCALVERSION" to append a unique suffix to the regular kernel version.
- LOCALVERSION can be set in the "General Setup" menu.
-
- - In order to boot your new kernel, you'll need to copy the kernel
- image (e.g. .../linux/arch/x86/boot/bzImage after compilation)
- to the place where your regular bootable kernel is found.
-
- - Booting a kernel directly from a floppy without the assistance of a
- bootloader such as LILO, is no longer supported.
-
- If you boot Linux from the hard drive, chances are you use LILO, which
- uses the kernel image as specified in the file /etc/lilo.conf. The
- kernel image file is usually /vmlinuz, /boot/vmlinuz, /bzImage or
- /boot/bzImage. To use the new kernel, save a copy of the old image
- and copy the new image over the old one. Then, you MUST RERUN LILO
- to update the loading map! If you don't, you won't be able to boot
- the new kernel image.
-
- Reinstalling LILO is usually a matter of running /sbin/lilo.
- You may wish to edit /etc/lilo.conf to specify an entry for your
- old kernel image (say, /vmlinux.old) in case the new one does not
- work. See the LILO docs for more information.
-
- After reinstalling LILO, you should be all set. Shutdown the system,
- reboot, and enjoy!
-
- If you ever need to change the default root device, video mode,
- ramdisk size, etc. in the kernel image, use the 'rdev' program (or
- alternatively the LILO boot options when appropriate). No need to
- recompile the kernel to change these parameters.
-
- - Reboot with the new kernel and enjoy.
-
-IF SOMETHING GOES WRONG:
-
- - If you have problems that seem to be due to kernel bugs, please check
- the file MAINTAINERS to see if there is a particular person associated
- with the part of the kernel that you are having trouble with. If there
- isn't anyone listed there, then the second best thing is to mail
- them to me (torvalds@linux-foundation.org), and possibly to any other
- relevant mailing-list or to the newsgroup.
-
- - In all bug-reports, *please* tell what kernel you are talking about,
- how to duplicate the problem, and what your setup is (use your common
- sense). If the problem is new, tell me so, and if the problem is
- old, please try to tell me when you first noticed it.
-
- - If the bug results in a message like
-
- unable to handle kernel paging request at address C0000010
- Oops: 0002
- EIP: 0010:XXXXXXXX
- eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
- esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
- ds: xxxx es: xxxx fs: xxxx gs: xxxx
- Pid: xx, process nr: xx
- xx xx xx xx xx xx xx xx xx xx
-
- or similar kernel debugging information on your screen or in your
- system log, please duplicate it *exactly*. The dump may look
- incomprehensible to you, but it does contain information that may
- help debugging the problem. The text above the dump is also
- important: it tells something about why the kernel dumped code (in
- the above example, it's due to a bad kernel pointer). More information
- on making sense of the dump is in Documentation/oops-tracing.txt
-
- - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
- as is, otherwise you will have to use the "ksymoops" program to make
- sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
- This utility can be downloaded from
- ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
- Alternatively, you can do the dump lookup by hand:
-
- - In debugging dumps like the above, it helps enormously if you can
- look up what the EIP value means. The hex value as such doesn't help
- me or anybody else very much: it will depend on your particular
- kernel setup. What you should do is take the hex value from the EIP
- line (ignore the "0010:"), and look it up in the kernel namelist to
- see which kernel function contains the offending address.
-
- To find out the kernel function name, you'll need to find the system
- binary associated with the kernel that exhibited the symptom. This is
- the file 'linux/vmlinux'. To extract the namelist and match it against
- the EIP from the kernel crash, do:
-
- nm vmlinux | sort | less
-
- This will give you a list of kernel addresses sorted in ascending
- order, from which it is simple to find the function that contains the
- offending address. Note that the address given by the kernel
- debugging messages will not necessarily match exactly with the
- function addresses (in fact, that is very unlikely), so you can't
- just 'grep' the list: the list will, however, give you the starting
- point of each kernel function, so by looking for the function that
- has a starting address lower than the one you are searching for but
- is followed by a function with a higher address you will find the one
- you want. In fact, it may be a good idea to include a bit of
- "context" in your problem report, giving a few lines around the
- interesting one.
-
- If you for some reason cannot do the above (you have a pre-compiled
- kernel image or similar), telling me as much about your setup as
- possible will help. Please read the REPORTING-BUGS document for details.
-
- - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you
- cannot change values or set break points.) To do this, first compile the
- kernel with -g; edit arch/x86/Makefile appropriately, then do a "make
- clean". You'll also need to enable CONFIG_PROC_FS (via "make config").
-
- After you've rebooted with the new kernel, do "gdb vmlinux /proc/kcore".
- You can now use all the usual gdb commands. The command to look up the
- point where your system crashed is "l *0xXXXXXXXX". (Replace the XXXes
- with the EIP value.)
-
- gdb'ing a non-running kernel currently fails because gdb (wrongly)
- disregards the starting offset for which the kernel is compiled.
+There are various text files in the Documentation/ subdirectory,
+several of them using the Restructured Text markup notation.
+See Documentation/00-INDEX for a list of what is contained in each file.
+Please read the Documentation/process/changes.rst file, as it contains the
+requirements for building and running the kernel, and information about
+the problems which may result by upgrading your kernel.
diff --git a/arch/Kconfig b/arch/Kconfig
index 659bdd079277..19483aea4bbc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -96,6 +96,7 @@ config KPROBES_ON_FTRACE
config UPROBES
def_bool n
+ depends on ARCH_SUPPORTS_UPROBES
help
Uprobes is the user-space counterpart to kprobes: they
enable instrumentation applications (such as 'perf probe')
@@ -363,8 +364,9 @@ menuconfig GCC_PLUGINS
See Documentation/gcc-plugins.txt for details.
config GCC_PLUGIN_CYC_COMPLEXITY
- bool "Compute the cyclomatic complexity of a function"
+ bool "Compute the cyclomatic complexity of a function" if EXPERT
depends on GCC_PLUGINS
+ depends on !COMPILE_TEST
help
The complexity M of a function's control flow graph is defined as:
M = E - N + 2P
@@ -374,6 +376,10 @@ config GCC_PLUGIN_CYC_COMPLEXITY
N = the number of nodes
P = the number of connected components (exit nodes).
+ Enabling this plugin reports the complexity to stderr during the
+ build. It mainly serves as a simple example of how to create a
+ gcc plugin for the kernel.
+
config GCC_PLUGIN_SANCOV
bool
depends on GCC_PLUGINS
@@ -512,6 +518,9 @@ config HAVE_CONTEXT_TRACKING
config HAVE_VIRT_CPU_ACCOUNTING
bool
+config ARCH_HAS_SCALED_CPUTIME
+ bool
+
config HAVE_VIRT_CPU_ACCOUNTING_GEN
bool
default y if 64BIT
diff --git a/arch/alpha/include/asm/mutex.h b/arch/alpha/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/alpha/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h
index 43a7559c448b..2fec2dee3020 100644
--- a/arch/alpha/include/asm/processor.h
+++ b/arch/alpha/include/asm/processor.h
@@ -58,7 +58,6 @@ unsigned long get_wchan(struct task_struct *p);
((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#define ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCHW
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 9e46d6e656d9..afc901b7a6f6 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -97,4 +97,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index ffb93f499c83..56e427c7aa3c 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1029,11 +1029,16 @@ SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv,
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
+asmlinkage long sys_ni_posix_timers(void);
+
SYSCALL_DEFINE2(osf_getitimer, int, which, struct itimerval32 __user *, it)
{
struct itimerval kit;
int error;
+ if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+ return sys_ni_posix_timers();
+
error = do_getitimer(which, &kit);
if (!error && put_it32(it, &kit))
error = -EFAULT;
@@ -1047,6 +1052,9 @@ SYSCALL_DEFINE3(osf_setitimer, int, which, struct itimerval32 __user *, in,
struct itimerval kin, kout;
int error;
+ if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+ return sys_ni_posix_timers();
+
if (in) {
if (get_it32(&kin, in))
return -EFAULT;
diff --git a/arch/arc/include/asm/mutex.h b/arch/arc/include/asm/mutex.h
deleted file mode 100644
index a2f88ff9f506..000000000000
--- a/arch/arc/include/asm/mutex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- */
-
-/*
- * xchg() based mutex fast path maintains a state of 0 or 1, as opposed to
- * atomic dec based which can "count" any number of lock contenders.
- * This ideally needs to be fixed in core, but for now switching to dec ver.
- */
-#if defined(CONFIG_SMP) && (CONFIG_NR_CPUS > 2)
-#include <asm-generic/mutex-dec.h>
-#else
-#include <asm-generic/mutex-xchg.h>
-#endif
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 16b630fbeb6a..6e1242da0159 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -60,15 +60,12 @@ struct task_struct;
#ifndef CONFIG_EZNPS_MTM_EXT
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#else
#define cpu_relax() \
__asm__ __volatile__ (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
-#define cpu_relax_lowlatency() barrier()
-
#endif
#define copy_segments(tsk, mm) do { } while (0)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5d529fdffab..caef68429b08 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -703,6 +703,7 @@ config ARCH_VIRT
select ARM_GIC
select ARM_GIC_V2M if PCI
select ARM_GIC_V3
+ select ARM_GIC_V3_ITS if PCI
select ARM_PSCI
select HAVE_ARM_ARCH_TIMER
diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts
index 064b322a7a04..3b23b32e1b30 100644
--- a/arch/arm/boot/dts/dra72-evm-revc.dts
+++ b/arch/arm/boot/dts/dra72-evm-revc.dts
@@ -59,15 +59,17 @@
&davinci_mdio {
dp83867_0: ethernet-phy@2 {
reg = <2>;
- ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
- ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ ti,min-output-impedance;
};
dp83867_1: ethernet-phy@3 {
reg = <3>;
- ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
- ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ ti,min-output-imepdance;
};
};
diff --git a/arch/arm/boot/dts/hisi-x5hd2.dtsi b/arch/arm/boot/dts/hisi-x5hd2.dtsi
index fdcc23d203e5..0da76c5ff6d7 100644
--- a/arch/arm/boot/dts/hisi-x5hd2.dtsi
+++ b/arch/arm/boot/dts/hisi-x5hd2.dtsi
@@ -436,18 +436,20 @@
};
gmac0: ethernet@1840000 {
- compatible = "hisilicon,hix5hd2-gmac";
+ compatible = "hisilicon,hix5hd2-gemac", "hisilicon,hisi-gemac-v1";
reg = <0x1840000 0x1000>,<0x184300c 0x4>;
interrupts = <0 71 4>;
clocks = <&clock HIX5HD2_MAC0_CLK>;
+ clock-names = "mac_core";
status = "disabled";
};
gmac1: ethernet@1841000 {
- compatible = "hisilicon,hix5hd2-gmac";
+ compatible = "hisilicon,hix5hd2-gemac", "hisilicon,hisi-gemac-v1";
reg = <0x1841000 0x1000>,<0x1843010 0x4>;
interrupts = <0 72 4>;
clocks = <&clock HIX5HD2_MAC1_CLK>;
+ clock-names = "mac_core";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index e571d66ea0fe..3d0a18abd408 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -626,4 +626,9 @@
"sru-src6", "sru-src7", "sru-src8";
};
};
+
+ rst: reset-controller@ffcc0000 {
+ compatible = "renesas,r8a7778-reset-wdt";
+ reg = <0xffcc0000 0x40>;
+ };
};
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index b9bbcce69dfb..8cf16008a09b 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -590,6 +590,11 @@
};
};
+ rst: reset-controller@ffcc0000 {
+ compatible = "renesas,r8a7779-reset-wdt";
+ reg = <0xffcc0000 0x48>;
+ };
+
sysc: system-controller@ffd85000 {
compatible = "renesas,r8a7779-sysc";
reg = <0xffd85000 0x0200>;
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 351fcc2f87df..3f10b0bf1b08 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -1471,6 +1471,11 @@
};
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7790-rst";
+ reg = <0 0xe6160000 0 0x0100>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7790-sysc";
reg = <0 0xe6180000 0 0x0200>;
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 162b55c665a3..c465c79bcca6 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -1482,6 +1482,11 @@
};
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7791-rst";
+ reg = <0 0xe6160000 0 0x0100>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7791-sysc";
reg = <0 0xe6180000 0 0x0200>;
diff --git a/arch/arm/boot/dts/r8a7792.dtsi b/arch/arm/boot/dts/r8a7792.dtsi
index 713141d38b3e..6e1f61f65d29 100644
--- a/arch/arm/boot/dts/r8a7792.dtsi
+++ b/arch/arm/boot/dts/r8a7792.dtsi
@@ -118,6 +118,11 @@
IRQ_TYPE_LEVEL_LOW)>;
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7792-rst";
+ reg = <0 0xe6160000 0 0x0100>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7792-sysc";
reg = <0 0xe6180000 0 0x0200>;
diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi
index 8d02aacf2892..e4b385eccf74 100644
--- a/arch/arm/boot/dts/r8a7793.dtsi
+++ b/arch/arm/boot/dts/r8a7793.dtsi
@@ -1279,6 +1279,11 @@
};
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7793-rst";
+ reg = <0 0xe6160000 0 0x0100>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7793-sysc";
reg = <0 0xe6180000 0 0x0200>;
diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index 9365580a194f..69e4f4fad89b 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -1375,6 +1375,11 @@
};
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7794-rst";
+ reg = <0 0xe6160000 0 0x0100>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7794-sysc";
reg = <0 0xe6180000 0 0x0200>;
diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
index 5c1fcab4a6f7..1552db00cc59 100644
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
@@ -88,10 +88,16 @@
switch0: switch0@0 {
compatible = "marvell,mv88e6085";
+ pinctrl-0 = <&pinctrl_gpio_switch0>;
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
dsa,member = <0 0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
ports {
#address-cells = <1>;
@@ -99,16 +105,19 @@
port@0 {
reg = <0>;
label = "lan0";
+ phy-handle = <&switch0phy0>;
};
port@1 {
reg = <1>;
label = "lan1";
+ phy-handle = <&switch0phy1>;
};
port@2 {
reg = <2>;
label = "lan2";
+ phy-handle = <&switch0phy2>;
};
switch0port5: port@5 {
@@ -133,6 +142,24 @@
};
};
};
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ switch0phy0: switch0phy0@0 {
+ reg = <0>;
+ interrupt-parent = <&switch0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ switch0phy1: switch1phy0@1 {
+ reg = <1>;
+ interrupt-parent = <&switch0>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; };
+ switch0phy2: switch1phy0@2 {
+ reg = <2>;
+ interrupt-parent = <&switch0>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
};
};
@@ -143,10 +170,16 @@
switch1: switch1@0 {
compatible = "marvell,mv88e6085";
+ pinctrl-0 = <&pinctrl_gpio_switch1>;
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
dsa,member = <0 1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
ports {
#address-cells = <1>;
@@ -196,12 +229,18 @@
#size-cells = <0>;
switch1phy0: switch1phy0@0 {
reg = <0>;
+ interrupt-parent = <&switch1>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
switch1phy1: switch1phy0@1 {
reg = <1>;
+ interrupt-parent = <&switch1>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
};
switch1phy2: switch1phy0@2 {
reg = <2>;
+ interrupt-parent = <&switch1>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
};
};
@@ -636,6 +675,18 @@
>;
};
+ pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+ fsl,pins = <
+ VF610_PAD_PTB5__GPIO_27 0x219d
+ >;
+ };
+
+ pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
+ fsl,pins = <
+ VF610_PAD_PTB4__GPIO_26 0x219d
+ >;
+ };
+
pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
fsl,pins = <
VF610_PAD_PTE14__GPIO_119 0x31c2
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index 37dc0fe1093f..46730017b3c5 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -757,19 +757,18 @@ EXPORT_SYMBOL_GPL(bL_switcher_put_enabled);
* while the switcher is active.
* We're just not ready to deal with that given the trickery involved.
*/
-static int bL_switcher_hotplug_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static int bL_switcher_cpu_pre(unsigned int cpu)
{
- if (bL_switcher_active) {
- int pairing = bL_switcher_cpu_pairing[(unsigned long)hcpu];
- switch (action & 0xf) {
- case CPU_UP_PREPARE:
- case CPU_DOWN_PREPARE:
- if (pairing == -1)
- return NOTIFY_BAD;
- }
- }
- return NOTIFY_DONE;
+ int pairing;
+
+ if (!bL_switcher_active)
+ return 0;
+
+ pairing = bL_switcher_cpu_pairing[cpu];
+
+ if (pairing == -1)
+ return -EINVAL;
+ return 0;
}
static bool no_bL_switcher;
@@ -782,8 +781,15 @@ static int __init bL_switcher_init(void)
if (!mcpm_is_available())
return -ENODEV;
- cpu_notifier(bL_switcher_hotplug_callback, 0);
-
+ cpuhp_setup_state_nocalls(CPUHP_ARM_BL_PREPARE, "arm/bl:prepare",
+ bL_switcher_cpu_pre, NULL);
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "arm/bl:predown",
+ NULL, bL_switcher_cpu_pre);
+ if (ret < 0) {
+ cpuhp_remove_state_nocalls(CPUHP_ARM_BL_PREPARE);
+ pr_err("bL_switcher: Failed to allocate a hotplug state\n");
+ return ret;
+ }
if (!no_bL_switcher) {
ret = bL_switcher_enable();
if (ret)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 11f37ed1dbff..30f39acd61bd 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -489,7 +489,7 @@ CONFIG_MFD_MAX8907=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_MAX8998=y
CONFIG_MFD_RK808=y
-CONFIG_MFD_PM8921_CORE=y
+CONFIG_MFD_PM8XXX=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_SEC_CORE=y
@@ -649,6 +649,9 @@ CONFIG_SND_SOC_AK4642=m
CONFIG_SND_SOC_SGTL5000=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_STI=m
+CONFIG_SND_SOC_STI_SAS=m
+CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MVEBU=y
@@ -790,6 +793,7 @@ CONFIG_DMA_OMAP=y
CONFIG_QCOM_BAM_DMA=y
CONFIG_XILINX_DMA=y
CONFIG_DMA_SUN6I=y
+CONFIG_ST_FDMA=m
CONFIG_STAGING=y
CONFIG_SENSORS_ISL29018=y
CONFIG_SENSORS_ISL29028=y
@@ -823,6 +827,8 @@ CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_REMOTEPROC=m
+CONFIG_ST_REMOTEPROC=m
CONFIG_PM_DEVFREQ=y
CONFIG_ARM_TEGRA_DEVFREQ=m
CONFIG_MEMORY=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index a016ecc0084b..e4314b1227a3 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -411,7 +411,6 @@ CONFIG_MFD_MAX77693=y
CONFIG_MFD_MAX8907=m
CONFIG_EZX_PCAP=y
CONFIG_UCB1400_CORE=m
-CONFIG_MFD_PM8921_CORE=m
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig
index c2dff4fd5fc4..74e9cd759b99 100644
--- a/arch/arm/configs/qcom_defconfig
+++ b/arch/arm/configs/qcom_defconfig
@@ -119,7 +119,6 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_MSM=y
CONFIG_THERMAL=y
CONFIG_MFD_PM8XXX=y
-CONFIG_MFD_PM8921_CORE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index a8088290b778..27475904e096 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -22,6 +22,7 @@
#include <linux/io.h>
#include <asm/barrier.h>
+#include <asm/cacheflush.h>
#include <asm/cp15.h>
#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
@@ -230,19 +231,14 @@ static inline void gic_write_bpr1(u32 val)
* AArch32, since the syndrome register doesn't provide any information for
* them.
* Consequently, the following IO helpers use 32bit accesses.
- *
- * There are only two registers that need 64bit accesses in this driver:
- * - GICD_IROUTERn, contain the affinity values associated to each interrupt.
- * The upper-word (aff3) will always be 0, so there is no need for a lock.
- * - GICR_TYPER is an ID register and doesn't need atomicity.
*/
-static inline void gic_write_irouter(u64 val, volatile void __iomem *addr)
+static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr)
{
writel_relaxed((u32)val, addr);
writel_relaxed((u32)(val >> 32), addr + 4);
}
-static inline u64 gic_read_typer(const volatile void __iomem *addr)
+static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
{
u64 val;
@@ -251,5 +247,49 @@ static inline u64 gic_read_typer(const volatile void __iomem *addr)
return val;
}
+#define gic_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l))
+
+/*
+ * GICD_IROUTERn, contain the affinity values associated to each interrupt.
+ * The upper-word (aff3) will always be 0, so there is no need for a lock.
+ */
+#define gic_write_irouter(v, c) __gic_writeq_nonatomic(v, c)
+
+/*
+ * GICR_TYPER is an ID register and doesn't need atomicity.
+ */
+#define gic_read_typer(c) __gic_readq_nonatomic(c)
+
+/*
+ * GITS_BASER - hi and lo bits may be accessed independently.
+ */
+#define gits_read_baser(c) __gic_readq_nonatomic(c)
+#define gits_write_baser(v, c) __gic_writeq_nonatomic(v, c)
+
+/*
+ * GICR_PENDBASER and GICR_PROPBASE are changed with LPIs disabled, so they
+ * won't be being used during any updates and can be changed non-atomically
+ */
+#define gicr_read_propbaser(c) __gic_readq_nonatomic(c)
+#define gicr_write_propbaser(v, c) __gic_writeq_nonatomic(v, c)
+#define gicr_read_pendbaser(c) __gic_readq_nonatomic(c)
+#define gicr_write_pendbaser(v, c) __gic_writeq_nonatomic(v, c)
+
+/*
+ * GITS_TYPER is an ID register and doesn't need atomicity.
+ */
+#define gits_read_typer(c) __gic_readq_nonatomic(c)
+
+/*
+ * GITS_CBASER - hi and lo bits may be accessed independently.
+ */
+#define gits_read_cbaser(c) __gic_readq_nonatomic(c)
+#define gits_write_cbaser(v, c) __gic_writeq_nonatomic(v, c)
+
+/*
+ * GITS_CWRITER - hi and lo bits may be accessed independently.
+ */
+#define gits_write_cwriter(v, c) __gic_writeq_nonatomic(v, c)
+
#endif /* !__ASSEMBLY__ */
#endif /* !__ASM_ARCH_GICV3_H */
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 766bf9b78160..0b06f5341b45 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -57,6 +57,9 @@ void efi_virtmap_unload(void);
#define __efi_call_early(f, ...) f(__VA_ARGS__)
#define efi_is_64bit() (false)
+#define efi_call_proto(protocol, f, instance, ...) \
+ ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+
struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 021692c64de3..42871fb8340e 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -25,7 +25,6 @@
#include <linux/string.h>
#include <linux/types.h>
-#include <linux/blk_types.h>
#include <asm/byteorder.h>
#include <asm/memory.h>
#include <asm-generic/pci_iomap.h>
diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h
deleted file mode 100644
index 87c044910fe0..000000000000
--- a/arch/arm/include/asm/mutex.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/include/asm/mutex.h
- *
- * ARM optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-/*
- * On pre-ARMv6 hardware this results in a swp-based implementation,
- * which is the most efficient. For ARMv6+, we have exclusive memory
- * accessors and use atomic_dec to avoid the extra xchg operations
- * on the locking slowpaths.
- */
-#if __LINUX_ARM_ARCH__ < 6
-#include <asm-generic/mutex-xchg.h>
-#else
-#include <asm-generic/mutex-dec.h>
-#endif
-#endif /* _ASM_MUTEX_H */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 8a1e8e995dae..c3d5fc124a05 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -82,8 +82,6 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
#endif
-#define cpu_relax_lowlatency() cpu_relax()
-
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 1e25cd80589e..3f2eb76243e3 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -186,6 +186,8 @@ tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
tlb_add_flush(tlb, addr);
}
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ tlb_remove_tlb_entry(tlb, ptep, address)
/*
* In the case of tlb vma handling, we can optimise these away in the
* case where we're doing a full MM flush. When we're doing a munmap,
@@ -211,18 +213,17 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
+ tlb->pages[tlb->nr++] = page;
+ VM_WARN_ON(tlb->nr > tlb->max);
if (tlb->nr == tlb->max)
return true;
- tlb->pages[tlb->nr++] = page;
return false;
}
static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
- if (__tlb_remove_page(tlb, page)) {
+ if (__tlb_remove_page(tlb, page))
tlb_flush_mmu(tlb);
- __tlb_remove_page(tlb, page);
- }
}
static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
@@ -231,12 +232,6 @@ static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
return __tlb_remove_page(tlb, page);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
- struct page *page)
-{
- return __tlb_remove_page(tlb, page);
-}
-
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
@@ -284,5 +279,11 @@ tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr
#define tlb_migrate_finish(mm) do { } while (0)
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+}
+
#endif /* CONFIG_MMU */
#endif
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index b8df45883cf7..188180b5523d 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -925,9 +925,9 @@ static bool core_has_os_save_restore(void)
}
}
-static void reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(unsigned int cpu)
{
- int i, raw_num_brps, err = 0, cpu = smp_processor_id();
+ int i, raw_num_brps, err = 0;
u32 val;
/*
@@ -1020,25 +1020,20 @@ out_mdbgen:
cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
}
-static int dbg_reset_notify(struct notifier_block *self,
- unsigned long action, void *cpu)
+static int dbg_reset_online(unsigned int cpu)
{
- if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
- smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
-
- return NOTIFY_OK;
+ local_irq_disable();
+ reset_ctrl_regs(cpu);
+ local_irq_enable();
+ return 0;
}
-static struct notifier_block dbg_reset_nb = {
- .notifier_call = dbg_reset_notify,
-};
-
#ifdef CONFIG_CPU_PM
static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action,
void *v)
{
if (action == CPU_PM_EXIT)
- reset_ctrl_regs(NULL);
+ reset_ctrl_regs(smp_processor_id());
return NOTIFY_OK;
}
@@ -1059,6 +1054,8 @@ static inline void pm_init(void)
static int __init arch_hw_breakpoint_init(void)
{
+ int ret;
+
debug_arch = get_debug_arch();
if (!debug_arch_supported()) {
@@ -1072,25 +1069,28 @@ static int __init arch_hw_breakpoint_init(void)
core_num_brps = get_num_brps();
core_num_wrps = get_num_wrps();
- cpu_notifier_register_begin();
-
/*
* We need to tread carefully here because DBGSWENABLE may be
* driven low on this core and there isn't an architected way to
* determine that.
*/
+ get_online_cpus();
register_undef_hook(&debug_reg_hook);
/*
- * Reset the breakpoint resources. We assume that a halting
- * debugger will leave the world in a nice state for us.
+ * Register CPU notifier which resets the breakpoint resources. We
+ * assume that a halting debugger will leave the world in a nice state
+ * for us.
*/
- on_each_cpu(reset_ctrl_regs, NULL, 1);
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm/hw_breakpoint:online",
+ dbg_reset_online, NULL);
unregister_undef_hook(&debug_reg_hook);
- if (!cpumask_empty(&debug_err_mask)) {
+ if (WARN_ON(ret < 0) || !cpumask_empty(&debug_err_mask)) {
core_num_brps = 0;
core_num_wrps = 0;
- cpu_notifier_register_done();
+ if (ret > 0)
+ cpuhp_remove_state_nocalls(ret);
+ put_online_cpus();
return 0;
}
@@ -1108,12 +1108,9 @@ static int __init arch_hw_breakpoint_init(void)
TRAP_HWBKPT, "watchpoint debug exception");
hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
TRAP_HWBKPT, "breakpoint debug exception");
+ put_online_cpus();
- /* Register hotplug and PM notifiers. */
- __register_cpu_notifier(&dbg_reset_nb);
-
- cpu_notifier_register_done();
-
+ /* Register PM notifiers. */
pm_init();
return 0;
}
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index b54db47f6f32..1dc2a34b9dbd 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -380,13 +380,6 @@ static struct pu_domain imx6q_pu_domain = {
.name = "PU",
.power_off = imx6q_pm_pu_power_off,
.power_on = imx6q_pm_pu_power_on,
- .states = {
- [0] = {
- .power_off_latency_ns = 25000,
- .power_on_latency_ns = 2000000,
- },
- },
- .state_count = 1,
},
};
@@ -430,6 +423,16 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
return 0;
+ imx6q_pu_domain.base.states = devm_kzalloc(dev,
+ sizeof(*imx6q_pu_domain.base.states),
+ GFP_KERNEL);
+ if (!imx6q_pu_domain.base.states)
+ return -ENOMEM;
+
+ imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
+ imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
+ imx6q_pu_domain.base.state_count = 1;
+
for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
pm_genpd_init(imx_gpc_domains[i], NULL, false);
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index ed9a01484030..a109f6482413 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -21,7 +21,6 @@
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/amba/mmci.h>
-#include <linux/amba/pl061.h>
#include <linux/io.h>
#include <linux/platform_data/clk-integrator.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 66070acaa888..d1db32b1a2c6 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -85,6 +85,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata smc91x_platdata = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
SMC91X_USE_DMA | SMC91X_NOWAIT,
+ .pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 40964069a17c..a2d851a3a546 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -140,6 +140,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata mainstone_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
SMC91X_NOWAIT | SMC91X_USE_DMA,
+ .pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 702f4f14b708..7b6610e9dae4 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -673,6 +673,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata stargate2_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
| SMC91X_NOWAIT | SMC91X_USE_DMA,
+ .pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index cf236db686a9..7fa4a0b5f654 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -15,7 +15,6 @@
* GNU General Public License for more details.
*/
-#include <linux/clk/renesas.h>
#include <linux/io.h>
#include <linux/irqchip.h>
@@ -23,19 +22,6 @@
#include "common.h"
-#define MODEMR 0xffcc0020
-
-static void __init r8a7778_timer_init(void)
-{
- u32 mode;
- void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-
- BUG_ON(!modemr);
- mode = ioread32(modemr);
- iounmap(modemr);
- r8a7778_clocks_init(mode);
-}
-
#define INT2SMSKCR0 0x82288 /* 0xfe782288 */
#define INT2SMSKCR1 0x8228c /* 0xfe78228c */
@@ -70,6 +56,5 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
.init_early = shmobile_init_delay,
.init_irq = r8a7778_init_irq_dt,
.init_late = shmobile_init_late,
- .init_time = r8a7778_timer_init,
.dt_compat = r8a7778_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index 0007ff51d180..0686112f2435 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -14,8 +14,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/clk/renesas.h>
-#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
@@ -76,30 +74,6 @@ static void __init r8a7779_init_irq_dt(void)
__raw_writel(0x003fee3f, INT2SMSKCR4);
}
-#define MODEMR 0xffcc0020
-
-static u32 __init r8a7779_read_mode_pins(void)
-{
- static u32 mode;
- static bool mode_valid;
-
- if (!mode_valid) {
- void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
- BUG_ON(!modemr);
- mode = ioread32(modemr);
- iounmap(modemr);
- mode_valid = true;
- }
-
- return mode;
-}
-
-static void __init r8a7779_init_time(void)
-{
- r8a7779_clocks_init(r8a7779_read_mode_pins());
- clocksource_probe();
-}
-
static const char *const r8a7779_compat_dt[] __initconst = {
"renesas,r8a7779",
NULL,
@@ -109,7 +83,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
.smp = smp_ops(r8a7779_smp_ops),
.map_io = r8a7779_map_io,
.init_early = shmobile_init_delay,
- .init_time = r8a7779_init_time,
.init_irq = r8a7779_init_irq_dt,
.init_late = shmobile_init_late,
.dt_compat = r8a7779_compat_dt,
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index afb9fdcd3d90..b527258e0a62 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
-#include <linux/clk/renesas.h>
+#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/device.h>
#include <linux/dma-contiguous.h>
@@ -71,7 +71,6 @@ static unsigned int __init get_extal_freq(void)
void __init rcar_gen2_timer_init(void)
{
- u32 mode = rcar_gen2_read_mode_pins();
#ifdef CONFIG_ARM_ARCH_TIMER
void __iomem *base;
u32 freq;
@@ -130,7 +129,7 @@ void __init rcar_gen2_timer_init(void)
iounmap(base);
#endif /* CONFIG_ARM_ARCH_TIMER */
- rcar_gen2_clocks_init(mode);
+ of_clk_init(NULL);
clocksource_probe();
}
diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
index b09f3bc5c6c1..c4d544244b19 100644
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@ -56,6 +56,10 @@
};
};
+&enet {
+ status = "ok";
+};
+
&pci_phy0 {
status = "ok";
};
@@ -174,6 +178,7 @@
&mdio_mux_iproc {
mdio@10 {
gphy0: eth-phy@10 {
+ enet-phy-lane-swap;
reg = <0x10>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index d95dc408629a..773ed593da4d 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -191,6 +191,18 @@
#include "ns2-clock.dtsi"
+ enet: ethernet@61000000 {
+ compatible = "brcm,ns2-amac";
+ reg = <0x61000000 0x1000>,
+ <0x61090000 0x1000>,
+ <0x61030000 0x100>;
+ reg-names = "amac_base", "idm_base", "nicpm_base";
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+ phy-handle = <&gphy0>;
+ phy-mode = "rgmii";
+ status = "disabled";
+ };
+
dma0: dma@61360000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x61360000 0x1000>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 7f0dc13b4087..d058e56db72d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -216,6 +216,12 @@
clocks = <&sysclk>;
};
+ dcfg: dcfg@1e00000 {
+ compatible = "fsl,ls2080a-dcfg", "syscon";
+ reg = <0x0 0x1e00000 0x0 0x10000>;
+ little-endian;
+ };
+
serial0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21c0500 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6aaa4..a59d36cd6caf 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -81,3 +81,26 @@
&pcie0 {
status = "okay";
};
+
+&mdio {
+ status = "okay";
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&eth0 {
+ phy-mode = "rgmii-id";
+ phy = <&phy0>;
+ status = "okay";
+};
+
+&eth1 {
+ phy-mode = "sgmii";
+ phy = <&phy1>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index e9bd58793464..3b8eb45bdc76 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -140,6 +140,29 @@
};
};
+ eth0: ethernet@30000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x30000 0x4000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sb_periph_clk 8>;
+ status = "disabled";
+ };
+
+ mdio: mdio@32004 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0x32004 0x4>;
+ };
+
+ eth1: ethernet@40000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x40000 0x4000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sb_periph_clk 7>;
+ status = "disabled";
+ };
+
usb3: usb@58000 {
compatible = "marvell,armada3700-xhci",
"generic-xhci";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index 8c15040f2540..625dda713548 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -321,6 +321,11 @@
#power-domain-cells = <0>;
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7795-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7795-sysc";
reg = <0 0xe6180000 0 0x0400>;
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 9217da983525..75c8c55a8248 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -233,6 +233,11 @@
#power-domain-cells = <0>;
};
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7796-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7796-sysc";
reg = <0 0xe6180000 0 0x0400>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 7afbfb0f96a3..1e24e455700b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -174,6 +174,7 @@
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
+ arm,no-tick-in-suspend;
};
xin24m: xin24m {
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dab2cb0c1f1c..6be08113a96d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -257,6 +257,7 @@ CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_RCAR=y
CONFIG_GPIO_XGENE=y
+CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 44e1d7f10add..b4ab238a59ec 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -24,7 +24,6 @@ generic-y += mm-arch-hooks.h
generic-y += mman.h
generic-y += msgbuf.h
generic-y += msi.h
-generic-y += mutex.h
generic-y += poll.h
generic-y += preempt.h
generic-y += resource.h
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index f8ae6d6e4767..f37e3a21f6e7 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -79,19 +79,10 @@
#include <linux/stringify.h>
#include <asm/barrier.h>
+#include <asm/cacheflush.h>
-#define read_gicreg(r) \
- ({ \
- u64 reg; \
- asm volatile("mrs_s %0, " __stringify(r) : "=r" (reg)); \
- reg; \
- })
-
-#define write_gicreg(v,r) \
- do { \
- u64 __val = (v); \
- asm volatile("msr_s " __stringify(r) ", %0" : : "r" (__val));\
- } while (0)
+#define read_gicreg read_sysreg_s
+#define write_gicreg write_sysreg_s
/*
* Low-level accessors
@@ -102,13 +93,13 @@
static inline void gic_write_eoir(u32 irq)
{
- asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));
+ write_sysreg_s(irq, ICC_EOIR1_EL1);
isb();
}
static inline void gic_write_dir(u32 irq)
{
- asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq));
+ write_sysreg_s(irq, ICC_DIR_EL1);
isb();
}
@@ -116,7 +107,7 @@ static inline u64 gic_read_iar_common(void)
{
u64 irqstat;
- asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+ irqstat = read_sysreg_s(ICC_IAR1_EL1);
dsb(sy);
return irqstat;
}
@@ -132,12 +123,9 @@ static inline u64 gic_read_iar_cavium_thunderx(void)
{
u64 irqstat;
- asm volatile(
- "nop;nop;nop;nop\n\t"
- "nop;nop;nop;nop\n\t"
- "mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t"
- "nop;nop;nop;nop"
- : "=r" (irqstat));
+ nops(8);
+ irqstat = read_sysreg_s(ICC_IAR1_EL1);
+ nops(4);
mb();
return irqstat;
@@ -145,37 +133,34 @@ static inline u64 gic_read_iar_cavium_thunderx(void)
static inline void gic_write_pmr(u32 val)
{
- asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
+ write_sysreg_s(val, ICC_PMR_EL1);
}
static inline void gic_write_ctlr(u32 val)
{
- asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val));
+ write_sysreg_s(val, ICC_CTLR_EL1);
isb();
}
static inline void gic_write_grpen1(u32 val)
{
- asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
+ write_sysreg_s(val, ICC_GRPEN1_EL1);
isb();
}
static inline void gic_write_sgi1r(u64 val)
{
- asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+ write_sysreg_s(val, ICC_SGI1R_EL1);
}
static inline u32 gic_read_sre(void)
{
- u64 val;
-
- asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
- return val;
+ return read_sysreg_s(ICC_SRE_EL1);
}
static inline void gic_write_sre(u32 val)
{
- asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val));
+ write_sysreg_s(val, ICC_SRE_EL1);
isb();
}
@@ -187,5 +172,21 @@ static inline void gic_write_bpr1(u32 val)
#define gic_read_typer(c) readq_relaxed(c)
#define gic_write_irouter(v, c) writeq_relaxed(v, c)
+#define gic_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l))
+
+#define gits_read_baser(c) readq_relaxed(c)
+#define gits_write_baser(v, c) writeq_relaxed(v, c)
+
+#define gits_read_cbaser(c) readq_relaxed(c)
+#define gits_write_cbaser(v, c) writeq_relaxed(v, c)
+
+#define gits_write_cwriter(v, c) writeq_relaxed(v, c)
+
+#define gicr_read_propbaser(c) readq_relaxed(c)
+#define gicr_write_propbaser(v, c) writeq_relaxed(v, c)
+
+#define gicr_write_pendbaser(v, c) writeq_relaxed(v, c)
+#define gicr_read_pendbaser(c) readq_relaxed(c)
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_ARCH_GICV3_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index a9e54aad15ef..771b3f0bc757 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -51,6 +51,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define __efi_call_early(f, ...) f(__VA_ARGS__)
#define efi_is_64bit() (true)
+#define efi_call_proto(protocol, f, instance, ...) \
+ ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+
#define alloc_screen_info(x...) &screen_info
#define free_screen_info(x...)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427bb4c2..0c00c87bb9dd 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -22,7 +22,6 @@
#ifdef __KERNEL__
#include <linux/types.h>
-#include <linux/blk_types.h>
#include <asm/byteorder.h>
#include <asm/barrier.h>
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 60e34824e18c..747c65a616ed 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -149,8 +149,6 @@ static inline void cpu_relax(void)
asm volatile("yield" ::: "memory");
}
-#define cpu_relax_lowlatency() cpu_relax()
-
/* Thread switching */
extern struct task_struct *cpu_switch_to(struct task_struct *prev,
struct task_struct *next);
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index b3d5b3e8fbcb..7b7be71e87bf 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -227,7 +227,7 @@ static struct attribute_group cpuregs_attr_group = {
.name = "identification"
};
-static int cpuid_add_regs(int cpu)
+static int cpuid_cpu_online(unsigned int cpu)
{
int rc;
struct device *dev;
@@ -248,7 +248,7 @@ out:
return rc;
}
-static int cpuid_remove_regs(int cpu)
+static int cpuid_cpu_offline(unsigned int cpu)
{
struct device *dev;
struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
@@ -264,40 +264,22 @@ static int cpuid_remove_regs(int cpu)
return 0;
}
-static int cpuid_callback(struct notifier_block *nb,
- unsigned long action, void *hcpu)
-{
- int rc = 0;
- unsigned long cpu = (unsigned long)hcpu;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- rc = cpuid_add_regs(cpu);
- break;
- case CPU_DEAD:
- rc = cpuid_remove_regs(cpu);
- break;
- }
-
- return notifier_from_errno(rc);
-}
-
static int __init cpuinfo_regs_init(void)
{
- int cpu;
-
- cpu_notifier_register_begin();
+ int cpu, ret;
for_each_possible_cpu(cpu) {
struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
kobject_init(&info->kobj, &cpuregs_kobj_type);
- if (cpu_online(cpu))
- cpuid_add_regs(cpu);
}
- __hotcpu_notifier(cpuid_callback, 0);
- cpu_notifier_register_done();
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/cpuinfo:online",
+ cpuid_cpu_online, cpuid_cpu_offline);
+ if (ret < 0) {
+ pr_err("cpuinfo: failed to register hotplug callbacks.\n");
+ return ret;
+ }
return 0;
}
static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
diff --git a/arch/avr32/include/asm/mutex.h b/arch/avr32/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/avr32/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h
index 941593c7d9f3..972adcc1e8f4 100644
--- a/arch/avr32/include/asm/processor.h
+++ b/arch/avr32/include/asm/processor.h
@@ -92,7 +92,6 @@ extern struct avr32_cpuinfo boot_cpu_data;
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#define cpu_sync_pipeline() asm volatile("sub pc, -2" : : : "memory")
struct cpu_context {
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 1fd147f09a38..5a650426f357 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _UAPI__ASM_AVR32_SOCKET_H */
diff --git a/arch/avr32/include/uapi/asm/unistd.h b/arch/avr32/include/uapi/asm/unistd.h
index 2c8a0d2b6c30..236505d889d0 100644
--- a/arch/avr32/include/uapi/asm/unistd.h
+++ b/arch/avr32/include/uapi/asm/unistd.h
@@ -340,5 +340,8 @@
#define __NR_copy_file_range 325
#define __NR_preadv2 326
#define __NR_pwritev2 327
+#define __NR_pkey_mprotect 328
+#define __NR_pkey_alloc 329
+#define __NR_pkey_free 330
#endif /* _UAPI__ASM_AVR32_UNISTD_H */
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 7b348ba70e41..774ce57f4948 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -341,4 +341,7 @@ sys_call_table:
.long __sys_copy_file_range
.long __sys_preadv2
.long __sys_pwritev2
+ .long sys_pkey_mprotect
+ .long sys_pkey_alloc
+ .long sys_pkey_free /* 330 */
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 52c179bec0cc..fdf1caecb7b9 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -242,7 +242,7 @@ dump_clock(struct clk *parent, struct clkinf *r)
clk_get_rate(parent));
if (parent->dev)
seq_printf(r->s, ", for %s", dev_name(parent->dev));
- seq_printf(r->s, "\n");
+ seq_putc(r->s, '\n');
/* cost of this scan is small, but not linear... */
r->nest = nest + NEST_DELTA;
@@ -261,23 +261,32 @@ static int clk_show(struct seq_file *s, void *unused)
struct clk *clk;
/* show all the power manager registers */
- seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
- seq_printf(s, "CKSEL = %8x\n", pm_readl(CKSEL));
- seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK));
- seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK));
- seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK));
- seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK));
- seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL0));
- seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL1));
- seq_printf(s, "IMR = %8x\n", pm_readl(IMR));
+ seq_printf(s,
+ "MCCTRL = %8x\n"
+ "CKSEL = %8x\n"
+ "CPUMASK = %8x\n"
+ "HSBMASK = %8x\n"
+ "PBAMASK = %8x\n"
+ "PBBMASK = %8x\n"
+ "PLL0 = %8x\n"
+ "PLL1 = %8x\n"
+ "IMR = %8x\n",
+ pm_readl(MCCTRL),
+ pm_readl(CKSEL),
+ pm_readl(CPU_MASK),
+ pm_readl(HSB_MASK),
+ pm_readl(PBA_MASK),
+ pm_readl(PBB_MASK),
+ pm_readl(PLL0),
+ pm_readl(PLL1),
+ pm_readl(IMR));
for (i = 0; i < 8; i++) {
if (i == 5)
continue;
seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i)));
}
- seq_printf(s, "\n");
-
+ seq_putc(s, '\n');
r.s = s;
r.nest = 0;
/* protected from changes on the list while dumping */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 13d3fc4270b7..7fae6ec7e8ec 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -367,13 +367,13 @@ static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
(mask & pdsr) ? "hi" : "lo",
(mask & pusr) ? " " : "up");
if (ifsr & mask)
- seq_printf(s, " deglitch");
+ seq_puts(s, " deglitch");
if ((osr & mdsr) & mask)
- seq_printf(s, " open-drain");
+ seq_puts(s, " open-drain");
if (imr & mask)
seq_printf(s, " irq-%d edge-both",
gpio_to_irq(chip->base + i));
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
}
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..2fb67b59d188 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -24,7 +24,6 @@ generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += mman.h
generic-y += msgbuf.h
-generic-y += mutex.h
generic-y += param.h
generic-y += percpu.h
generic-y += pgalloc.h
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index 0c265aba94ad..85d4af97c986 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -92,7 +92,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
#define cpu_relax() smp_mb()
-#define cpu_relax_lowlatency() cpu_relax()
/* Get the Silicon Revision of the chip */
static inline uint32_t __pure bfin_revid(void)
diff --git a/arch/c6x/include/asm/mutex.h b/arch/c6x/include/asm/mutex.h
deleted file mode 100644
index 7a7248e0462d..000000000000
--- a/arch/c6x/include/asm/mutex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_C6X_MUTEX_H
-#define _ASM_C6X_MUTEX_H
-
-#include <asm-generic/mutex-null.h>
-
-#endif /* _ASM_C6X_MUTEX_H */
diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h
index f2ef31be2f8b..b9eb3da7f278 100644
--- a/arch/c6x/include/asm/processor.h
+++ b/arch/c6x/include/asm/processor.h
@@ -121,7 +121,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(task) (task_pt_regs(task)->sp)
#define cpu_relax() do { } while (0)
-#define cpu_relax_lowlatency() cpu_relax()
extern const struct seq_operations cpuinfo_op;
diff --git a/arch/cris/boot/compressed/Makefile b/arch/cris/boot/compressed/Makefile
index 8fe9338c1775..e4ba0be0e782 100644
--- a/arch/cris/boot/compressed/Makefile
+++ b/arch/cris/boot/compressed/Makefile
@@ -2,9 +2,6 @@
# arch/cris/boot/compressed/Makefile
#
-asflags-y += $(LINUXINCLUDE)
-ccflags-y += -O2 $(LINUXINCLUDE)
-
# asflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/mach \
# -I$(srctree)/include/asm/arch
# ccflags-$(CONFIG_ETRAX_ARCH_V32) += -O2 -I$(srctree)/include/asm/mach
diff --git a/arch/cris/boot/rescue/Makefile b/arch/cris/boot/rescue/Makefile
index 52bd0bd1dd22..a82025940006 100644
--- a/arch/cris/boot/rescue/Makefile
+++ b/arch/cris/boot/rescue/Makefile
@@ -8,8 +8,8 @@
# asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch
# LD = gcc-cris -mlinux -march=v32 -nostdlib
-asflags-y += $(LINUXINCLUDE)
-ccflags-y += -O2 $(LINUXINCLUDE)
+ifdef CONFIG_ETRAX_AXISFLASHMAP
+
arch-$(CONFIG_ETRAX_ARCH_V10) = v10
arch-$(CONFIG_ETRAX_ARCH_V32) = v32
@@ -28,6 +28,11 @@ $(obj)/rescue.bin: $(obj)/rescue.o FORCE
$(call if_changed,objcopy)
cp -p $(obj)/rescue.bin $(objtree)
+else
+$(obj)/rescue.bin:
+
+endif
+
$(obj)/testrescue.bin: $(obj)/testrescue.o
$(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/testrescue.o tr.bin
# Pad it to 784 bytes
diff --git a/arch/cris/include/asm/mutex.h b/arch/cris/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/cris/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h
index 862126b58116..15b815df29c1 100644
--- a/arch/cris/include/asm/processor.h
+++ b/arch/cris/include/asm/processor.h
@@ -63,7 +63,6 @@ static inline void release_thread(struct task_struct *dead_task)
#define init_stack (init_thread_union.stack)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
void default_idle(void);
diff --git a/arch/frv/include/asm/mutex.h b/arch/frv/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/frv/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index 73f0a79ad8e6..ddaeb9cc9143 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -107,7 +107,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
/* data cache prefetch */
#define ARCH_HAS_PREFETCH
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index afbc98f02d27..81e03530ed39 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -90,5 +90,7 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/asm/mutex.h b/arch/h8300/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/h8300/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 111df7397ac7..65132d7ae9e5 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -127,7 +127,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#define HARD_RESET_NOW() ({ \
local_irq_disable(); \
diff --git a/arch/hexagon/include/asm/mutex.h b/arch/hexagon/include/asm/mutex.h
deleted file mode 100644
index 58b52de1bc22..000000000000
--- a/arch/hexagon/include/asm/mutex.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-#include <asm-generic/mutex-xchg.h>
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index d8501137c8d0..45a825402f63 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -56,7 +56,6 @@ struct thread_struct {
}
#define cpu_relax() __vmyield()
-#define cpu_relax_lowlatency() cpu_relax()
/*
* Decides where the kernel will search for a free chunk of vm space during
diff --git a/arch/ia64/include/asm/mutex.h b/arch/ia64/include/asm/mutex.h
deleted file mode 100644
index 28cb819e0ff9..000000000000
--- a/arch/ia64/include/asm/mutex.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * ia64 implementation of the mutex fastpath.
- *
- * Copyright (C) 2006 Ken Chen <kenneth.w.chen@intel.com>
- *
- */
-
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-
-/**
- * __mutex_fastpath_lock - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
- fail_fn(count);
-}
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
- return -1;
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - try to promote the count from 0 to 1
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, then the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- int ret = ia64_fetchadd4_rel(count, 1);
- if (unlikely(ret < 0))
- fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- *
- * If the architecture has no effective trylock variant, it should call the
- * <fail_fn> spinlock-based trylock variant unconditionally.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- if (atomic_read(count) == 1 && cmpxchg_acq(count, 1, 0) == 1)
- return 1;
- return 0;
-}
-
-#endif
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index ce53c50d0ba4..03911a336406 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -547,7 +547,6 @@ ia64_eoi (void)
}
#define cpu_relax() ia64_hint(ia64_hint_pause)
-#define cpu_relax_lowlatency() cpu_relax()
static inline int
ia64_get_irr(unsigned int vector)
diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h
index 77e541cf0e5d..fced197b9626 100644
--- a/arch/ia64/include/asm/tlb.h
+++ b/arch/ia64/include/asm/tlb.h
@@ -207,15 +207,15 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
*/
static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
- if (tlb->nr == tlb->max)
- return true;
-
tlb->need_flush = 1;
if (!tlb->nr && tlb->pages == tlb->local)
__tlb_alloc_page(tlb);
tlb->pages[tlb->nr++] = page;
+ VM_WARN_ON(tlb->nr > tlb->max);
+ if (tlb->nr == tlb->max)
+ return true;
return false;
}
@@ -236,10 +236,8 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
- if (__tlb_remove_page(tlb, page)) {
+ if (__tlb_remove_page(tlb, page))
tlb_flush_mmu(tlb);
- __tlb_remove_page(tlb, page);
- }
}
static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
@@ -248,12 +246,6 @@ static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
return __tlb_remove_page(tlb, page);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
- struct page *page)
-{
- return __tlb_remove_page(tlb, page);
-}
-
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
@@ -283,6 +275,15 @@ do { \
__tlb_remove_tlb_entry(tlb, ptep, addr); \
} while (0)
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+}
+
#define pte_free_tlb(tlb, ptep, address) \
do { \
tlb->need_flush = 1; \
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 0018fad9039f..57feb0c1f7d7 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -99,4 +99,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
index 5ed0ea92c5bf..85bba43e7d5d 100644
--- a/arch/ia64/kernel/err_inject.c
+++ b/arch/ia64/kernel/err_inject.c
@@ -224,85 +224,45 @@ static struct attribute_group err_inject_attr_group = {
.name = "err_inject"
};
/* Add/Remove err_inject interface for CPU device */
-static int err_inject_add_dev(struct device *sys_dev)
+static int err_inject_add_dev(unsigned int cpu)
{
+ struct device *sys_dev = get_cpu_device(cpu);
+
return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
}
-static int err_inject_remove_dev(struct device *sys_dev)
+static int err_inject_remove_dev(unsigned int cpu)
{
+ struct device *sys_dev = get_cpu_device(cpu);
+
sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
return 0;
}
-static int err_inject_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
- struct device *sys_dev;
-
- sys_dev = get_cpu_device(cpu);
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- err_inject_add_dev(sys_dev);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- err_inject_remove_dev(sys_dev);
- break;
- }
-
- return NOTIFY_OK;
-}
-static struct notifier_block err_inject_cpu_notifier =
-{
- .notifier_call = err_inject_cpu_callback,
-};
+static enum cpuhp_state hp_online;
-static int __init
-err_inject_init(void)
+static int __init err_inject_init(void)
{
- int i;
-
+ int ret;
#ifdef ERR_INJ_DEBUG
printk(KERN_INFO "Enter error injection driver.\n");
#endif
- cpu_notifier_register_begin();
-
- for_each_online_cpu(i) {
- err_inject_cpu_callback(&err_inject_cpu_notifier, CPU_ONLINE,
- (void *)(long)i);
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/err_inj:online",
+ err_inject_add_dev, err_inject_remove_dev);
+ if (ret >= 0) {
+ hp_online = ret;
+ ret = 0;
}
-
- __register_hotcpu_notifier(&err_inject_cpu_notifier);
-
- cpu_notifier_register_done();
-
- return 0;
+ return ret;
}
-static void __exit
-err_inject_exit(void)
+static void __exit err_inject_exit(void)
{
- int i;
- struct device *sys_dev;
-
#ifdef ERR_INJ_DEBUG
printk(KERN_INFO "Exit error injection driver.\n");
#endif
-
- cpu_notifier_register_begin();
-
- for_each_online_cpu(i) {
- sys_dev = get_cpu_device(i);
- sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
- }
-
- __unregister_hotcpu_notifier(&err_inject_cpu_notifier);
-
- cpu_notifier_register_done();
+ cpuhp_remove_state(hp_online);
}
module_init(err_inject_init);
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index c39c3cd3ac34..b6e597860888 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -932,8 +932,7 @@ static const struct file_operations proc_palinfo_fops = {
.release = single_release,
};
-static void
-create_palinfo_proc_entries(unsigned int cpu)
+static int palinfo_add_proc(unsigned int cpu)
{
pal_func_cpu_u_t f;
struct proc_dir_entry *cpu_dir;
@@ -943,7 +942,7 @@ create_palinfo_proc_entries(unsigned int cpu)
cpu_dir = proc_mkdir(cpustr, palinfo_dir);
if (!cpu_dir)
- return;
+ return -EINVAL;
f.req_cpu = cpu;
@@ -952,42 +951,21 @@ create_palinfo_proc_entries(unsigned int cpu)
proc_create_data(palinfo_entries[j].name, 0, cpu_dir,
&proc_palinfo_fops, (void *)f.value);
}
+ return 0;
}
-static void
-remove_palinfo_proc_entries(unsigned int hcpu)
+static int palinfo_del_proc(unsigned int hcpu)
{
char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
+
sprintf(cpustr, "cpu%d", hcpu);
remove_proc_subtree(cpustr, palinfo_dir);
+ return 0;
}
-static int palinfo_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int hotcpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- create_palinfo_proc_entries(hotcpu);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- remove_palinfo_proc_entries(hotcpu);
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata palinfo_cpu_notifier =
-{
- .notifier_call = palinfo_cpu_callback,
- .priority = 0,
-};
+static enum cpuhp_state hp_online;
-static int __init
-palinfo_init(void)
+static int __init palinfo_init(void)
{
int i = 0;
@@ -996,25 +974,19 @@ palinfo_init(void)
if (!palinfo_dir)
return -ENOMEM;
- cpu_notifier_register_begin();
-
- /* Create palinfo dirs in /proc for all online cpus */
- for_each_online_cpu(i) {
- create_palinfo_proc_entries(i);
+ i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/palinfo:online",
+ palinfo_add_proc, palinfo_del_proc);
+ if (i < 0) {
+ remove_proc_subtree("pal", NULL);
+ return i;
}
-
- /* Register for future delivery via notify registration */
- __register_hotcpu_notifier(&palinfo_cpu_notifier);
-
- cpu_notifier_register_done();
-
+ hp_online = i;
return 0;
}
-static void __exit
-palinfo_exit(void)
+static void __exit palinfo_exit(void)
{
- unregister_hotcpu_notifier(&palinfo_cpu_notifier);
+ cpuhp_remove_state(hp_online);
remove_proc_subtree("pal", NULL);
}
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 5313007d5423..aaf74f36cfa1 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -550,52 +550,40 @@ static const struct file_operations salinfo_data_fops = {
.llseek = default_llseek,
};
-static int
-salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+static int salinfo_cpu_online(unsigned int cpu)
{
- unsigned int i, cpu = (unsigned long)hcpu;
- unsigned long flags;
+ unsigned int i, end = ARRAY_SIZE(salinfo_data);
struct salinfo_data *data;
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- spin_lock_irqsave(&data_saved_lock, flags);
- for (i = 0, data = salinfo_data;
- i < ARRAY_SIZE(salinfo_data);
- ++i, ++data) {
- cpumask_set_cpu(cpu, &data->cpu_event);
- wake_up_interruptible(&data->read_wait);
- }
- spin_unlock_irqrestore(&data_saved_lock, flags);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- spin_lock_irqsave(&data_saved_lock, flags);
- for (i = 0, data = salinfo_data;
- i < ARRAY_SIZE(salinfo_data);
- ++i, ++data) {
- struct salinfo_data_saved *data_saved;
- int j;
- for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;
- j >= 0;
- --j, --data_saved) {
- if (data_saved->buffer && data_saved->cpu == cpu) {
- shift1_data_saved(data, j);
- }
- }
- cpumask_clear_cpu(cpu, &data->cpu_event);
- }
- spin_unlock_irqrestore(&data_saved_lock, flags);
- break;
+
+ spin_lock_irq(&data_saved_lock);
+ for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
+ cpumask_set_cpu(cpu, &data->cpu_event);
+ wake_up_interruptible(&data->read_wait);
}
- return NOTIFY_OK;
+ spin_unlock_irq(&data_saved_lock);
+ return 0;
}
-static struct notifier_block salinfo_cpu_notifier =
+static int salinfo_cpu_pre_down(unsigned int cpu)
{
- .notifier_call = salinfo_cpu_callback,
- .priority = 0,
-};
+ unsigned int i, end = ARRAY_SIZE(salinfo_data);
+ struct salinfo_data *data;
+
+ spin_lock_irq(&data_saved_lock);
+ for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
+ struct salinfo_data_saved *data_saved;
+ int j = ARRAY_SIZE(data->data_saved) - 1;
+
+ for (data_saved = data->data_saved + j; j >= 0;
+ --j, --data_saved) {
+ if (data_saved->buffer && data_saved->cpu == cpu)
+ shift1_data_saved(data, j);
+ }
+ cpumask_clear_cpu(cpu, &data->cpu_event);
+ }
+ spin_unlock_irq(&data_saved_lock);
+ return 0;
+}
static int __init
salinfo_init(void)
@@ -604,7 +592,7 @@ salinfo_init(void)
struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
struct proc_dir_entry *dir, *entry;
struct salinfo_data *data;
- int i, j;
+ int i;
salinfo_dir = proc_mkdir("sal", NULL);
if (!salinfo_dir)
@@ -617,8 +605,6 @@ salinfo_init(void)
(void *)salinfo_entries[i].feature);
}
- cpu_notifier_register_begin();
-
for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
data = salinfo_data + i;
data->type = i;
@@ -639,10 +625,6 @@ salinfo_init(void)
continue;
*sdir++ = entry;
- /* we missed any events before now */
- for_each_online_cpu(j)
- cpumask_set_cpu(j, &data->cpu_event);
-
*sdir++ = dir;
}
@@ -653,10 +635,9 @@ salinfo_init(void)
salinfo_timer.function = &salinfo_timeout;
add_timer(&salinfo_timer);
- __register_hotcpu_notifier(&salinfo_cpu_notifier);
-
- cpu_notifier_register_done();
-
+ i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/salinfo:online",
+ salinfo_cpu_online, salinfo_cpu_pre_down);
+ WARN_ON(i < 0);
return 0;
}
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 6f892b94e906..021f44ab4bfb 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -68,7 +68,7 @@ void vtime_account_user(struct task_struct *tsk)
if (ti->ac_utime) {
delta_utime = cycle_to_cputime(ti->ac_utime);
- account_user_time(tsk, delta_utime, delta_utime);
+ account_user_time(tsk, delta_utime);
ti->ac_utime = 0;
}
}
@@ -112,7 +112,7 @@ void vtime_account_system(struct task_struct *tsk)
{
cputime_t delta = vtime_delta(tsk);
- account_system_time(tsk, 0, delta, delta);
+ account_system_time(tsk, 0, delta);
}
EXPORT_SYMBOL_GPL(vtime_account_system);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index c01fe8991244..1a68f012a6dc 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -349,9 +349,9 @@ static int cpu_cache_sysfs_init(unsigned int cpu)
}
/* Add cache interface for CPU device */
-static int cache_add_dev(struct device *sys_dev)
+static int cache_add_dev(unsigned int cpu)
{
- unsigned int cpu = sys_dev->id;
+ struct device *sys_dev = get_cpu_device(cpu);
unsigned long i, j;
struct cache_info *this_object;
int retval = 0;
@@ -399,9 +399,8 @@ static int cache_add_dev(struct device *sys_dev)
}
/* Remove cache interface for CPU device */
-static int cache_remove_dev(struct device *sys_dev)
+static int cache_remove_dev(unsigned int cpu)
{
- unsigned int cpu = sys_dev->id;
unsigned long i;
for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++)
@@ -419,52 +418,13 @@ static int cache_remove_dev(struct device *sys_dev)
return 0;
}
-/*
- * When a cpu is hot-plugged, do a check and initiate
- * cache kobject if necessary
- */
-static int cache_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
- struct device *sys_dev;
-
- sys_dev = get_cpu_device(cpu);
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- cache_add_dev(sys_dev);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- cache_remove_dev(sys_dev);
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block cache_cpu_notifier =
-{
- .notifier_call = cache_cpu_callback
-};
-
static int __init cache_sysfs_init(void)
{
- int i;
-
- cpu_notifier_register_begin();
-
- for_each_online_cpu(i) {
- struct device *sys_dev = get_cpu_device((unsigned int)i);
- cache_add_dev(sys_dev);
- }
-
- __register_hotcpu_notifier(&cache_cpu_notifier);
-
- cpu_notifier_register_done();
+ int ret;
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/topology:online",
+ cache_add_dev, cache_remove_dev);
+ WARN_ON(ret < 0);
return 0;
}
-
device_initcall(cache_sysfs_init);
-
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 3cc8498fe0fe..d227a6988d6b 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -34,7 +34,7 @@ config NO_IOPORT_MAP
def_bool y
config NO_DMA
- def_bool y
+ def_bool n
config HZ
int
diff --git a/arch/m32r/include/asm/device.h b/arch/m32r/include/asm/device.h
index d8f9872b0e2d..4a9f35e0973f 100644
--- a/arch/m32r/include/asm/device.h
+++ b/arch/m32r/include/asm/device.h
@@ -3,5 +3,9 @@
*
* This file is released under the GPLv2
*/
-#include <asm-generic/device.h>
+struct dev_archdata {
+ struct dma_map_ops *dma_ops;
+};
+struct pdev_archdata {
+};
diff --git a/arch/m32r/include/asm/dma-mapping.h b/arch/m32r/include/asm/dma-mapping.h
new file mode 100644
index 000000000000..2c43a77fe942
--- /dev/null
+++ b/arch/m32r/include/asm/dma-mapping.h
@@ -0,0 +1,32 @@
+#ifndef _ASM_M32R_DMA_MAPPING_H
+#define _ASM_M32R_DMA_MAPPING_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
+
+#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+ if (dev && dev->archdata.dma_ops)
+ return dev->archdata.dma_ops;
+ return &dma_noop_ops;
+}
+
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ if (!dev->dma_mask)
+ return false;
+ return addr + size - 1 <= *dev->dma_mask;
+}
+
+#endif /* _ASM_M32R_DMA_MAPPING_H */
diff --git a/arch/m32r/include/asm/mutex.h b/arch/m32r/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/m32r/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index 9f8fd9bef70f..5767367550c6 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -133,6 +133,5 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.sp)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#endif /* _ASM_M32R_PROCESSOR_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index 5fe42fc7b6c5..5853f8e92c20 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m32r/platforms/m32700ut/setup.c b/arch/m32r/platforms/m32700ut/setup.c
index 9a4ba8a8589d..349eb341752c 100644
--- a/arch/m32r/platforms/m32700ut/setup.c
+++ b/arch/m32r/platforms/m32700ut/setup.c
@@ -201,6 +201,7 @@ static struct irq_chip m32700ut_lanpld_irq_type =
#define lcdpldirq2port(x) (unsigned long)((int)M32700UT_LCD_ICUCR1 + \
(((x) - 1) * sizeof(unsigned short)))
+#ifdef CONFIG_USB
static pld_icu_data_t lcdpld_icu_data[M32700UT_NUM_LCD_PLD_IRQ];
static void disable_m32700ut_lcdpld_irq(unsigned int irq)
@@ -253,6 +254,7 @@ static struct irq_chip m32700ut_lcdpld_irq_type =
.irq_mask = mask_m32700ut_lcdpld,
.irq_unmask = unmask_m32700ut_lcdpld,
};
+#endif
void __init init_IRQ(void)
{
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 2a5c7abb2896..9225b4ad9aeb 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -259,6 +259,12 @@ config M5407C3
help
Support for the Motorola M5407C3 board.
+config AMCORE
+ bool "Sysam AMCORE board support"
+ depends on M5307
+ help
+ Support for the Sysam AMCORE open-hardware generic board.
+
config FIREBEE
bool "FireBee board support"
depends on M547x
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index ddb8192a3661..65f63a457130 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -786,8 +786,7 @@ static void amiga_get_hardware_list(struct seq_file *m)
if (AMIGAHW_PRESENT(name)) \
seq_printf (m, "\t%s\n", str)
- seq_printf (m, "Detected hardware:\n");
-
+ seq_puts(m, "Detected hardware:\n");
AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 97a3c38cd1f5..e328eaf816e3 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -629,7 +629,7 @@ static void atari_get_hardware_list(struct seq_file *m)
if (ATARIHW_PRESENT(name)) \
seq_printf(m, "\t%s\n", str)
- seq_printf(m, "Detected hardware:\n");
+ seq_puts(m, "Detected hardware:\n");
ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
diff --git a/arch/m68k/coldfire/Makefile b/arch/m68k/coldfire/Makefile
index 68f0fac60099..4aa2c57afc35 100644
--- a/arch/m68k/coldfire/Makefile
+++ b/arch/m68k/coldfire/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_NETtel) += nettel.o
obj-$(CONFIG_CLEOPATRA) += nettel.o
obj-$(CONFIG_FIREBEE) += firebee.o
obj-$(CONFIG_MCF8390) += mcf8390.o
+obj-$(CONFIG_AMCORE) += amcore.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/m68k/coldfire/amcore.c b/arch/m68k/coldfire/amcore.c
new file mode 100644
index 000000000000..c6cb1a5cc1a5
--- /dev/null
+++ b/arch/m68k/coldfire/amcore.c
@@ -0,0 +1,156 @@
+/*
+ * amcore.c -- Support for Sysam AMCORE open board
+ *
+ * (C) Copyright 2016, Angelo Dureghello <angelo@sysam.it>
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dm9000.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/io.h>
+
+#if IS_ENABLED(CONFIG_DM9000)
+
+#define DM9000_IRQ 25
+#define DM9000_ADDR 0x30000000
+
+/*
+ * DEVICES and related device RESOURCES
+ */
+static struct resource dm9000_resources[] = {
+ /* physical address of the address register (CMD [A2] to 0)*/
+ [0] = {
+ .start = DM9000_ADDR,
+ .end = DM9000_ADDR,
+ .flags = IORESOURCE_MEM,
+ },
+ /*
+ * physical address of the data register (CMD [A2] to 1),
+ * driver wants a range >=4 to assume a 32bit data bus
+ */
+ [1] = {
+ .start = DM9000_ADDR + 4,
+ .end = DM9000_ADDR + 7,
+ .flags = IORESOURCE_MEM,
+ },
+ /* IRQ line the device's interrupt pin is connected to */
+ [2] = {
+ .start = DM9000_IRQ,
+ .end = DM9000_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct dm9000_plat_data dm9000_platdata = {
+ .flags = DM9000_PLATF_32BITONLY,
+};
+
+static struct platform_device dm9000_device = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dm9000_resources),
+ .resource = dm9000_resources,
+ .dev = {
+ .platform_data = &dm9000_platdata,
+ }
+};
+#endif
+
+static void __init dm9000_pre_init(void)
+{
+ /* Set the dm9000 interrupt to be auto-vectored */
+ mcf_autovector(DM9000_IRQ);
+}
+
+/*
+ * Partitioning of parallel NOR flash (39VF3201B)
+ */
+static struct mtd_partition amcore_partitions[] = {
+ {
+ .name = "U-Boot (128K)",
+ .size = 0x20000,
+ .offset = 0x0
+ },
+ {
+ .name = "Kernel+ROMfs (2994K)",
+ .size = 0x2E0000,
+ .offset = MTDPART_OFS_APPEND
+ },
+ {
+ .name = "Flash Free Space (1024K)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND
+ }
+};
+
+static struct physmap_flash_data flash_data = {
+ .parts = amcore_partitions,
+ .nr_parts = ARRAY_SIZE(amcore_partitions),
+ .width = 2,
+};
+
+static struct resource flash_resource = {
+ .start = 0xffc00000,
+ .end = 0xffffffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .resource = &flash_resource,
+ .num_resources = 1,
+ .dev = {
+ .platform_data = &flash_data,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "rtc-ds1307",
+ .id = -1,
+};
+
+static struct i2c_board_info amcore_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("ds1338", 0x68),
+ },
+};
+
+static struct platform_device *amcore_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_DM9000)
+ &dm9000_device,
+#endif
+ &flash_device,
+ &rtc_device,
+};
+
+static int __init init_amcore(void)
+{
+#if IS_ENABLED(CONFIG_DM9000)
+ dm9000_pre_init();
+#endif
+
+ /* Add i2c RTC Dallas chip supprt */
+ i2c_register_board_info(0, amcore_i2c_info,
+ ARRAY_SIZE(amcore_i2c_info));
+
+ platform_add_devices(amcore_devices, ARRAY_SIZE(amcore_devices));
+
+ return 0;
+}
+
+arch_initcall(init_amcore);
diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
index a0fc0c192427..84938fdbbada 100644
--- a/arch/m68k/coldfire/device.c
+++ b/arch/m68k/coldfire/device.c
@@ -327,6 +327,147 @@ static struct platform_device mcf_qspi = {
};
#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
+#if IS_ENABLED(CONFIG_I2C_IMX)
+static struct resource mcf_i2c0_resources[] = {
+ {
+ .start = MCFI2C_BASE0,
+ .end = MCFI2C_BASE0 + MCFI2C_SIZE0 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C0,
+ .end = MCF_IRQ_I2C0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c0 = {
+ .name = "imx1-i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mcf_i2c0_resources),
+ .resource = mcf_i2c0_resources,
+};
+#ifdef MCFI2C_BASE1
+
+static struct resource mcf_i2c1_resources[] = {
+ {
+ .start = MCFI2C_BASE1,
+ .end = MCFI2C_BASE1 + MCFI2C_SIZE1 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C1,
+ .end = MCF_IRQ_I2C1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c1 = {
+ .name = "imx1-i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mcf_i2c1_resources),
+ .resource = mcf_i2c1_resources,
+};
+
+#endif /* MCFI2C_BASE1 */
+
+#ifdef MCFI2C_BASE2
+
+static struct resource mcf_i2c2_resources[] = {
+ {
+ .start = MCFI2C_BASE2,
+ .end = MCFI2C_BASE2 + MCFI2C_SIZE2 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C2,
+ .end = MCF_IRQ_I2C2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c2 = {
+ .name = "imx1-i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mcf_i2c2_resources),
+ .resource = mcf_i2c2_resources,
+};
+
+#endif /* MCFI2C_BASE2 */
+
+#ifdef MCFI2C_BASE3
+
+static struct resource mcf_i2c3_resources[] = {
+ {
+ .start = MCFI2C_BASE3,
+ .end = MCFI2C_BASE3 + MCFI2C_SIZE3 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C3,
+ .end = MCF_IRQ_I2C3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c3 = {
+ .name = "imx1-i2c",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(mcf_i2c3_resources),
+ .resource = mcf_i2c3_resources,
+};
+
+#endif /* MCFI2C_BASE3 */
+
+#ifdef MCFI2C_BASE4
+
+static struct resource mcf_i2c4_resources[] = {
+ {
+ .start = MCFI2C_BASE4,
+ .end = MCFI2C_BASE4 + MCFI2C_SIZE4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C4,
+ .end = MCF_IRQ_I2C4,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c4 = {
+ .name = "imx1-i2c",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(mcf_i2c4_resources),
+ .resource = mcf_i2c4_resources,
+};
+
+#endif /* MCFI2C_BASE4 */
+
+#ifdef MCFI2C_BASE5
+
+static struct resource mcf_i2c5_resources[] = {
+ {
+ .start = MCFI2C_BASE5,
+ .end = MCFI2C_BASE5 + MCFI2C_SIZE5 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_I2C5,
+ .end = MCF_IRQ_I2C5,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_i2c5 = {
+ .name = "imx1-i2c",
+ .id = 5,
+ .num_resources = ARRAY_SIZE(mcf_i2c5_resources),
+ .resource = mcf_i2c5_resources,
+};
+
+#endif /* MCFI2C_BASE5 */
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+
static struct platform_device *mcf_devices[] __initdata = {
&mcf_uart,
#if IS_ENABLED(CONFIG_FEC)
@@ -338,6 +479,24 @@ static struct platform_device *mcf_devices[] __initdata = {
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
&mcf_qspi,
#endif
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ &mcf_i2c0,
+#ifdef MCFI2C_BASE1
+ &mcf_i2c1,
+#endif
+#ifdef MCFI2C_BASE2
+ &mcf_i2c2,
+#endif
+#ifdef MCFI2C_BASE3
+ &mcf_i2c3,
+#endif
+#ifdef MCFI2C_BASE4
+ &mcf_i2c4,
+#endif
+#ifdef MCFI2C_BASE5
+ &mcf_i2c5,
+#endif
+#endif
};
/*
diff --git a/arch/m68k/coldfire/m5206.c b/arch/m68k/coldfire/m5206.c
index 8945f5e7b39c..a3bcf0883f98 100644
--- a/arch/m68k/coldfire/m5206.c
+++ b/arch/m68k/coldfire/m5206.c
@@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -34,11 +35,21 @@ struct clk *mcf_clks[] = {
&clk_mcftmr1,
&clk_mcfuart0,
&clk_mcfuart1,
+ &clk_mcfi2c0,
NULL
};
/***************************************************************************/
+static void __init m5206_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+ MCFSIM_I2CICR);
+ mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
void __init config_BSP(char *commandp, int size)
{
#if defined(CONFIG_NETtel)
@@ -53,6 +64,7 @@ void __init config_BSP(char *commandp, int size)
mcf_mapirq2imr(25, MCFINTC_EINT1);
mcf_mapirq2imr(28, MCFINTC_EINT4);
mcf_mapirq2imr(31, MCFINTC_EINT7);
+ m5206_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m520x.c b/arch/m68k/coldfire/m520x.c
index 173834f251eb..5ba69217ce6c 100644
--- a/arch/m68k/coldfire/m520x.c
+++ b/arch/m68k/coldfire/m520x.c
@@ -28,7 +28,7 @@ DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
DEFINE_CLK(0, "edma", 17, MCF_CLK);
DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -53,7 +53,7 @@ struct clk *mcf_clks[] = {
&__clk_0_17, /* edma */
&__clk_0_18, /* intc.0 */
&__clk_0_21, /* iack.0 */
- &__clk_0_22, /* mcfi2c.0 */
+ &__clk_0_22, /* imx1-i2c.0 */
&__clk_0_23, /* mcfqspi.0 */
&__clk_0_24, /* mcfuart.0 */
&__clk_0_25, /* mcfuart.1 */
@@ -71,7 +71,7 @@ struct clk *mcf_clks[] = {
&__clk_0_40, /* sys.0 */
&__clk_0_41, /* gpio.0 */
&__clk_0_42, /* sdram.0 */
-NULL,
+ NULL,
};
static struct clk * const enable_clks[] __initconst = {
@@ -94,7 +94,7 @@ static struct clk * const enable_clks[] __initconst = {
static struct clk * const disable_clks[] __initconst = {
&__clk_0_12, /* fec.0 */
&__clk_0_17, /* edma */
- &__clk_0_22, /* mcfi2c.0 */
+ &__clk_0_22, /* imx1-i2c.0 */
&__clk_0_23, /* mcfqspi.0 */
&__clk_0_28, /* mcftmr.0 */
&__clk_0_29, /* mcftmr.1 */
@@ -133,6 +133,21 @@ static void __init m520x_qspi_init(void)
/***************************************************************************/
+static void __init m520x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ u8 par;
+
+ /* setup Port FECI2C Pin Assignment Register for I2C */
+ /* set PAR_SCL to SCL and PAR_SDA to SDA */
+ par = readb(MCF_GPIO_PAR_FECI2C);
+ par |= 0x0f;
+ writeb(par, MCF_GPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void __init m520x_uarts_init(void)
{
u16 par;
@@ -175,6 +190,7 @@ void __init config_BSP(char *commandp, int size)
m520x_uarts_init();
m520x_fec_init();
m520x_qspi_init();
+ m520x_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m523x.c b/arch/m68k/coldfire/m523x.c
index a191a467eff2..f7a0fcc5618c 100644
--- a/arch/m68k/coldfire/m523x.c
+++ b/arch/m68k/coldfire/m523x.c
@@ -34,6 +34,7 @@ DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -47,6 +48,7 @@ struct clk *mcf_clks[] = {
&clk_mcfuart2,
&clk_mcfqspi0,
&clk_fec0,
+ &clk_mcfi2c0,
NULL
};
@@ -68,6 +70,21 @@ static void __init m523x_qspi_init(void)
/***************************************************************************/
+static void __init m523x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ u8 par;
+
+ /* setup Port AS Pin Assignment Register for I2C */
+ /* set PASPA0 to SCL and PASPA1 to SDA */
+ par = readb(MCFGPIO_PAR_FECI2C);
+ par |= 0x0f;
+ writeb(par, MCFGPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void __init m523x_fec_init(void)
{
/* Set multi-function pins to ethernet use */
@@ -81,6 +98,7 @@ void __init config_BSP(char *commandp, int size)
mach_sched_init = hw_timer_init;
m523x_fec_init();
m523x_qspi_init();
+ m523x_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m5249.c b/arch/m68k/coldfire/m5249.c
index e48f55adc447..b16cf9b4580c 100644
--- a/arch/m68k/coldfire/m5249.c
+++ b/arch/m68k/coldfire/m5249.c
@@ -27,6 +27,8 @@ DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -36,6 +38,8 @@ struct clk *mcf_clks[] = {
&clk_mcfuart0,
&clk_mcfuart1,
&clk_mcfqspi0,
+ &clk_mcfi2c0,
+ &clk_mcfi2c1,
NULL
};
@@ -85,6 +89,26 @@ static void __init m5249_qspi_init(void)
/***************************************************************************/
+static void __init m5249_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ u32 r;
+
+ /* first I2C controller uses regular irq setup */
+ writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+ MCFSIM_I2CICR);
+ mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+
+ /* second I2C controller is completely different */
+ r = readl(MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
+ r &= ~MCFINTC2_INTPRI_BITS(0xf, MCF_IRQ_I2C1);
+ r |= MCFINTC2_INTPRI_BITS(0x5, MCF_IRQ_I2C1);
+ writel(r, MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
+#endif /* CONFIG_I2C_IMX */
+}
+
+/***************************************************************************/
+
#ifdef CONFIG_M5249C3
static void __init m5249_smc91x_init(void)
@@ -111,6 +135,7 @@ void __init config_BSP(char *commandp, int size)
m5249_smc91x_init();
#endif
m5249_qspi_init();
+ m5249_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m525x.c b/arch/m68k/coldfire/m525x.c
index 3d8583e2187c..110e2cd34e62 100644
--- a/arch/m68k/coldfire/m525x.c
+++ b/arch/m68k/coldfire/m525x.c
@@ -27,6 +27,8 @@ DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -36,6 +38,8 @@ struct clk *mcf_clks[] = {
&clk_mcfuart0,
&clk_mcfuart1,
&clk_mcfqspi0,
+ &clk_mcfi2c0,
+ &clk_mcfi2c1,
NULL
};
@@ -59,12 +63,12 @@ static void __init m525x_qspi_init(void)
static void __init m525x_i2c_init(void)
{
-#if IS_ENABLED(CONFIG_I2C_COLDFIRE)
+#if IS_ENABLED(CONFIG_I2C_IMX)
u32 r;
/* first I2C controller uses regular irq setup */
writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
- MCFSIM_I2CICR);
+ MCFSIM_I2CICR);
mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
/* second I2C controller is completely different */
@@ -72,7 +76,7 @@ static void __init m525x_i2c_init(void)
r &= ~MCFINTC2_INTPRI_BITS(0xf, MCF_IRQ_I2C1);
r |= MCFINTC2_INTPRI_BITS(0x5, MCF_IRQ_I2C1);
writel(r, MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
-#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m527x.c b/arch/m68k/coldfire/m527x.c
index c0b3e28f91df..b10b436b5a31 100644
--- a/arch/m68k/coldfire/m527x.c
+++ b/arch/m68k/coldfire/m527x.c
@@ -36,6 +36,7 @@ DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -50,6 +51,7 @@ struct clk *mcf_clks[] = {
&clk_mcfqspi0,
&clk_fec0,
&clk_fec1,
+ &clk_mcfi2c0,
NULL
};
@@ -76,6 +78,31 @@ static void __init m527x_qspi_init(void)
/***************************************************************************/
+static void __init m527x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+#if defined(CONFIG_M5271)
+ u8 par;
+
+ /* setup Port FECI2C Pin Assignment Register for I2C */
+ /* set PAR_SCL to SCL and PAR_SDA to SDA */
+ par = readb(MCFGPIO_PAR_FECI2C);
+ par |= 0x0f;
+ writeb(par, MCFGPIO_PAR_FECI2C);
+#elif defined(CONFIG_M5275)
+ u16 par;
+
+ /* setup Port FECI2C Pin Assignment Register for I2C */
+ /* set PAR_SCL to SCL and PAR_SDA to SDA */
+ par = readw(MCFGPIO_PAR_FECI2C);
+ par |= 0x0f;
+ writew(par, MCFGPIO_PAR_FECI2C);
+#endif
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void __init m527x_uarts_init(void)
{
u16 sepmask;
@@ -122,6 +149,7 @@ void __init config_BSP(char *commandp, int size)
m527x_uarts_init();
m527x_fec_init();
m527x_qspi_init();
+ m527x_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m528x.c b/arch/m68k/coldfire/m528x.c
index 12f9e370d8dd..ea76998d5ab9 100644
--- a/arch/m68k/coldfire/m528x.c
+++ b/arch/m68k/coldfire/m528x.c
@@ -36,6 +36,7 @@ DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -49,6 +50,7 @@ struct clk *mcf_clks[] = {
&clk_mcfuart2,
&clk_mcfqspi0,
&clk_fec0,
+ &clk_mcfi2c0,
NULL
};
@@ -64,6 +66,21 @@ static void __init m528x_qspi_init(void)
/***************************************************************************/
+static void __init m528x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ u16 paspar;
+
+ /* setup Port AS Pin Assignment Register for I2C */
+ /* set PASPA0 to SCL and PASPA1 to SDA */
+ paspar = readw(MCFGPIO_PASPAR);
+ paspar |= 0xF;
+ writew(paspar, MCFGPIO_PASPAR);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void __init m528x_uarts_init(void)
{
u8 port;
@@ -127,6 +144,7 @@ void __init config_BSP(char *commandp, int size)
m528x_uarts_init();
m528x_fec_init();
m528x_qspi_init();
+ m528x_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m5307.c b/arch/m68k/coldfire/m5307.c
index 2da1d146e344..cc5e8a50a423 100644
--- a/arch/m68k/coldfire/m5307.c
+++ b/arch/m68k/coldfire/m5307.c
@@ -35,6 +35,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -43,11 +44,23 @@ struct clk *mcf_clks[] = {
&clk_mcftmr1,
&clk_mcfuart0,
&clk_mcfuart1,
+ &clk_mcfi2c0,
NULL
};
/***************************************************************************/
+static void __init m5307_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+ MCFSIM_I2CICR);
+ mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
#if defined(CONFIG_NETtel) || \
@@ -73,6 +86,7 @@ void __init config_BSP(char *commandp, int size)
*/
wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
#endif
+ m5307_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m53xx.c b/arch/m68k/coldfire/m53xx.c
index 2502f63960bc..cf1917934b8a 100644
--- a/arch/m68k/coldfire/m53xx.c
+++ b/arch/m68k/coldfire/m53xx.c
@@ -38,7 +38,7 @@ DEFINE_CLK(0, "edma", 17, MCF_CLK);
DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -77,7 +77,7 @@ struct clk *mcf_clks[] = {
&__clk_0_18, /* intc.0 */
&__clk_0_19, /* intc.1 */
&__clk_0_21, /* iack.0 */
- &__clk_0_22, /* mcfi2c.0 */
+ &__clk_0_22, /* imx1-i2c.0 */
&__clk_0_23, /* mcfqspi.0 */
&__clk_0_24, /* mcfuart.0 */
&__clk_0_25, /* mcfuart.1 */
@@ -133,7 +133,7 @@ static struct clk * const disable_clks[] __initconst = {
&__clk_0_8, /* mcfcan.0 */
&__clk_0_12, /* fec.0 */
&__clk_0_17, /* edma */
- &__clk_0_22, /* mcfi2c.0 */
+ &__clk_0_22, /* imx1-i2c.0 */
&__clk_0_23, /* mcfqspi.0 */
&__clk_0_30, /* mcftmr.2 */
&__clk_0_31, /* mcftmr.3 */
@@ -176,6 +176,19 @@ static void __init m53xx_qspi_init(void)
/***************************************************************************/
+static void __init m53xx_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ /* setup Port AS Pin Assignment Register for I2C */
+ /* set PASPA0 to SCL and PASPA1 to SDA */
+ u8 r = readb(MCFGPIO_PAR_FECI2C);
+ r |= 0x0f;
+ writeb(r, MCFGPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void __init m53xx_uarts_init(void)
{
/* UART GPIO initialization */
@@ -218,6 +231,7 @@ void __init config_BSP(char *commandp, int size)
m53xx_uarts_init();
m53xx_fec_init();
m53xx_qspi_init();
+ m53xx_i2c_init();
#ifdef CONFIG_BDM_DISABLE
/*
diff --git a/arch/m68k/coldfire/m5407.c b/arch/m68k/coldfire/m5407.c
index 738eba6be40e..38863ddbeab0 100644
--- a/arch/m68k/coldfire/m5407.c
+++ b/arch/m68k/coldfire/m5407.c
@@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -34,11 +35,23 @@ struct clk *mcf_clks[] = {
&clk_mcftmr1,
&clk_mcfuart0,
&clk_mcfuart1,
+ &clk_mcfi2c0,
NULL
};
/***************************************************************************/
+static void __init m5407_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+ MCFSIM_I2CICR);
+ mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
mach_sched_init = hw_timer_init;
@@ -48,6 +61,7 @@ void __init config_BSP(char *commandp, int size)
mcf_mapirq2imr(27, MCFINTC_EINT3);
mcf_mapirq2imr(29, MCFINTC_EINT5);
mcf_mapirq2imr(31, MCFINTC_EINT7);
+ m5407_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/coldfire/m5441x.c b/arch/m68k/coldfire/m5441x.c
index 98a13cce93d8..dc589b039b62 100644
--- a/arch/m68k/coldfire/m5441x.c
+++ b/arch/m68k/coldfire/m5441x.c
@@ -19,13 +19,13 @@
DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
DEFINE_CLK(0, "mcfcan.1", 9, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.1", 14, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.1", 14, MCF_CLK);
DEFINE_CLK(0, "mcfdspi.1", 15, MCF_CLK);
DEFINE_CLK(0, "edma", 17, MCF_CLK);
DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
DEFINE_CLK(0, "intc.2", 20, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
DEFINE_CLK(0, "mcfdspi.0", 23, MCF_CLK);
DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -59,10 +59,10 @@ DEFINE_CLK(0, "switch.1", 56, MCF_CLK);
DEFINE_CLK(0, "nand.0", 63, MCF_CLK);
DEFINE_CLK(1, "mcfow.0", 2, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.2", 4, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.3", 5, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.4", 6, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.5", 7, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.2", 4, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.3", 5, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.4", 6, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.5", 7, MCF_CLK);
DEFINE_CLK(1, "mcfuart.4", 24, MCF_BUSCLK);
DEFINE_CLK(1, "mcfuart.5", 25, MCF_BUSCLK);
DEFINE_CLK(1, "mcfuart.6", 26, MCF_BUSCLK);
diff --git a/arch/m68k/coldfire/m54xx.c b/arch/m68k/coldfire/m54xx.c
index 386df3b68cdf..c552851ec617 100644
--- a/arch/m68k/coldfire/m54xx.c
+++ b/arch/m68k/coldfire/m54xx.c
@@ -37,6 +37,7 @@ DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
struct clk *mcf_clks[] = {
&clk_pll,
@@ -47,6 +48,7 @@ struct clk *mcf_clks[] = {
&clk_mcfuart1,
&clk_mcfuart2,
&clk_mcfuart3,
+ &clk_mcfi2c0,
NULL
};
@@ -65,6 +67,20 @@ static void __init m54xx_uarts_init(void)
/***************************************************************************/
+static void __init m54xx_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+ u32 r;
+
+ /* set the fec/i2c/irq pin assignment register for i2c */
+ r = readl(MCF_PAR_FECI2CIRQ);
+ r |= MCF_PAR_FECI2CIRQ_SDA | MCF_PAR_FECI2CIRQ_SCL;
+ writel(r, MCF_PAR_FECI2CIRQ);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
static void mcf54xx_reset(void)
{
/* disable interrupts and enable the watchdog */
@@ -86,6 +102,7 @@ void __init config_BSP(char *commandp, int size)
mach_reset = mcf54xx_reset;
mach_sched_init = hw_timer_init;
m54xx_uarts_init();
+ m54xx_i2c_init();
}
/***************************************************************************/
diff --git a/arch/m68k/configs/amcore_defconfig b/arch/m68k/configs/amcore_defconfig
new file mode 100644
index 000000000000..f108dd121e9a
--- /dev/null
+++ b/arch/m68k/configs/amcore_defconfig
@@ -0,0 +1,118 @@
+CONFIG_LOCALVERSION="amcore-001"
+CONFIG_DEFAULT_HOSTNAME="amcore"
+CONFIG_SYSVIPC=y
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_AIO is not set
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_MMU is not set
+CONFIG_M5307=y
+CONFIG_AMCORE=y
+CONFIG_UBOOT=y
+CONFIG_RAMSIZE=0x1000000
+CONFIG_KERNELBASE=0x20000
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BINFMT_FLAT=y
+# CONFIG_COREDUMP is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=115200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_IMX=y
+CONFIG_PPS=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_SYSTOHC is not set
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_FSCACHE=y
+# CONFIG_PROC_SYSCTL is not set
+CONFIG_JFFS2_FS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC16=y
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
index a0985fd088d1..fc4be028c418 100644
--- a/arch/m68k/emu/nfeth.c
+++ b/arch/m68k/emu/nfeth.c
@@ -184,7 +184,6 @@ static const struct net_device_ops nfeth_netdev_ops = {
.ndo_start_xmit = nfeth_xmit,
.ndo_tx_timeout = nfeth_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..1f2e5d31cb24 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -20,7 +20,6 @@ generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += mman.h
-generic-y += mutex.h
generic-y += percpu.h
generic-y += preempt.h
generic-y += resource.h
diff --git a/arch/m68k/include/asm/m5206sim.h b/arch/m68k/include/asm/m5206sim.h
index 4cf864f5ea7a..0ddf3efbcae9 100644
--- a/arch/m68k/include/asm/m5206sim.h
+++ b/arch/m68k/include/asm/m5206sim.h
@@ -110,6 +110,7 @@
/*
* Define system peripheral IRQ usage.
*/
+#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */
#define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */
#define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */
#define MCF_IRQ_UART0 73 /* UART0 */
@@ -138,6 +139,7 @@
#define MCFSIM_SWDICR MCFSIM_ICR8 /* Watchdog timer ICR */
#define MCFSIM_TIMER1ICR MCFSIM_ICR9 /* Timer 1 ICR */
#define MCFSIM_TIMER2ICR MCFSIM_ICR10 /* Timer 2 ICR */
+#define MCFSIM_I2CICR MCFSIM_ICR11 /* I2C ICR */
#define MCFSIM_UART1ICR MCFSIM_ICR12 /* UART 1 ICR */
#define MCFSIM_UART2ICR MCFSIM_ICR13 /* UART 2 ICR */
#ifdef CONFIG_M5206e
@@ -145,5 +147,11 @@
#define MCFSIM_DMA2ICR MCFSIM_ICR15 /* DMA 2 ICR */
#endif
+/*
+ * I2C Controller
+*/
+#define MCFI2C_BASE0 (MCF_MBAR + 0x1e0)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m5206sim_h */
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index db3f8ee4a6c6..6d50cefa76c3 100644
--- a/arch/m68k/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
@@ -50,6 +50,7 @@
#define MCFINT_UART0 26 /* Interrupt number for UART0 */
#define MCFINT_UART1 27 /* Interrupt number for UART1 */
#define MCFINT_UART2 28 /* Interrupt number for UART2 */
+#define MCFINT_I2C0 30 /* Interrupt number for I2C */
#define MCFINT_QSPI 31 /* Interrupt number for QSPI */
#define MCFINT_FECRX0 36 /* Interrupt number for FEC RX */
#define MCFINT_FECTX0 40 /* Interrupt number for FEC RX */
@@ -67,6 +68,7 @@
#define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI)
#define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1)
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0)
/*
* SDRAM configuration registers.
*/
@@ -200,5 +202,11 @@
#define MCFPM_PPMLR0 0xfc040034
#define MCFPM_LPCR 0xfc0a0007
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0 0xFC058000
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m520xsim_h */
diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h
index 5e06b4eb57f3..d43f6ab1edc9 100644
--- a/arch/m68k/include/asm/m523xsim.h
+++ b/arch/m68k/include/asm/m523xsim.h
@@ -37,7 +37,8 @@
#define MCFINT_UART0 13 /* Interrupt number for UART0 */
#define MCFINT_UART1 14 /* Interrupt number for UART1 */
#define MCFINT_UART2 15 /* Interrupt number for UART2 */
-#define MCFINT_QSPI 18 /* Interrupt number for QSPI */
+#define MCFINT_I2C0 17 /* Interrupt number for I2C */
+#define MCFINT_QSPI 18 /* Interrupt number for QSPI */
#define MCFINT_FECRX0 23 /* Interrupt number for FEC */
#define MCFINT_FECTX0 27 /* Interrupt number for FEC */
#define MCFINT_FECENTC0 29 /* Interrupt number for FEC */
@@ -53,6 +54,7 @@
#define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI)
#define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1)
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0)
/*
* SDRAM configuration registers.
@@ -208,5 +210,11 @@
#define MCFDMA_BASE2 (MCF_IPSBAR + 0x180)
#define MCFDMA_BASE3 (MCF_IPSBAR + 0x1C0)
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m523xsim_h */
diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index 2c648a043f24..35f6fbc89b92 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -37,6 +37,7 @@
#define MCFINT_UART0 13 /* Interrupt number for UART0 */
#define MCFINT_UART1 14 /* Interrupt number for UART1 */
#define MCFINT_UART2 15 /* Interrupt number for UART2 */
+#define MCFINT_I2C0 17 /* Interrupt number for I2C */
#define MCFINT_QSPI 18 /* Interrupt number for QSPI */
#define MCFINT_FECRX0 23 /* Interrupt number for FEC0 */
#define MCFINT_FECTX0 27 /* Interrupt number for FEC0 */
@@ -61,6 +62,7 @@
#define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI)
#define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1)
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0)
/*
* SDRAM configuration registers.
@@ -353,5 +355,11 @@
#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m527xsim_h */
diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index cf68ca0ac3a5..67f6182d10a4 100644
--- a/arch/m68k/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
@@ -37,6 +37,7 @@
#define MCFINT_UART0 13 /* Interrupt number for UART0 */
#define MCFINT_UART1 14 /* Interrupt number for UART1 */
#define MCFINT_UART2 15 /* Interrupt number for UART2 */
+#define MCFINT_I2C0 17 /* Interrupt number for I2C */
#define MCFINT_QSPI 18 /* Interrupt number for QSPI */
#define MCFINT_FECRX0 23 /* Interrupt number for FEC */
#define MCFINT_FECTX0 27 /* Interrupt number for FEC */
@@ -53,6 +54,8 @@
#define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI)
#define MCF_IRQ_PIT1 (MCFINT_VECBASE + MCFINT_PIT1)
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0)
+
/*
* SDRAM configuration registers.
*/
@@ -242,5 +245,11 @@
#define MCF_RCR_SWRESET 0x80 /* Software reset bit */
#define MCF_RCR_FRCSTOUT 0x40 /* Force external reset */
+/*
+ * I2C module
+ */
+#define MCFI2C_BASE0 (MCF_IPSBAR + 0x300)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m528xsim_h */
diff --git a/arch/m68k/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h
index 5d0bb7ec31f8..d2595e04eb1d 100644
--- a/arch/m68k/include/asm/m5307sim.h
+++ b/arch/m68k/include/asm/m5307sim.h
@@ -148,6 +148,7 @@
#define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */
#define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */
#define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */
+#define MCFSIM_I2CICR MCFSIM_ICR3 /* I2C ICR */
#define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */
#define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */
#define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */
@@ -155,7 +156,6 @@
#define MCFSIM_DMA2ICR MCFSIM_ICR8 /* DMA 2 ICR */
#define MCFSIM_DMA3ICR MCFSIM_ICR9 /* DMA 3 ICR */
-
/*
* Some symbol defines for the Parallel Port Pin Assignment Register
*/
@@ -174,10 +174,17 @@
/*
* Define system peripheral IRQ usage.
*/
+#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */
#define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */
#define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */
#define MCF_IRQ_UART0 73 /* UART0 */
#define MCF_IRQ_UART1 74 /* UART1 */
+/*
+ * I2C module
+ */
+#define MCFI2C_BASE0 (MCF_MBAR + 0x280)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m5307sim_h */
diff --git a/arch/m68k/include/asm/m53xxsim.h b/arch/m68k/include/asm/m53xxsim.h
index faa1a2133bfd..53329ae4d3e3 100644
--- a/arch/m68k/include/asm/m53xxsim.h
+++ b/arch/m68k/include/asm/m53xxsim.h
@@ -19,6 +19,7 @@
#define MCFINT_UART0 26 /* Interrupt number for UART0 */
#define MCFINT_UART1 27 /* Interrupt number for UART1 */
#define MCFINT_UART2 28 /* Interrupt number for UART2 */
+#define MCFINT_I2C0 30 /* Interrupt number for I2C */
#define MCFINT_QSPI 31 /* Interrupt number for QSPI */
#define MCFINT_FECRX0 36 /* Interrupt number for FEC */
#define MCFINT_FECTX0 40 /* Interrupt number for FEC */
@@ -32,6 +33,7 @@
#define MCF_IRQ_FECTX0 (MCFINT_VECBASE + MCFINT_FECTX0)
#define MCF_IRQ_FECENTC0 (MCFINT_VECBASE + MCFINT_FECENTC0)
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + MCFINT_I2C0)
#define MCF_IRQ_QSPI (MCFINT_VECBASE + MCFINT_QSPI)
#define MCF_WTM_WCR 0xFC098000
@@ -1237,5 +1239,11 @@
#define MCFEPORT_EPPDR (0xFC094005)
#define MCFEPORT_EPFR (0xFC094006)
+/*
+ * I2C Module
+ */
+#define MCFI2C_BASE0 (0xFc058000)
+#define MCFI2C_SIZE0 0x40
+
/********************************************************************/
#endif /* m53xxsim_h */
diff --git a/arch/m68k/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h
index a7550bc5cd1e..ab40c16ba989 100644
--- a/arch/m68k/include/asm/m5407sim.h
+++ b/arch/m68k/include/asm/m5407sim.h
@@ -112,6 +112,7 @@
#define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */
#define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */
#define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */
+#define MCFSIM_I2CICR MCFSIM_ICR3 /* I2C ICR */
#define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */
#define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */
#define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */
@@ -137,10 +138,17 @@
/*
* Define system peripheral IRQ usage.
*/
+#define MCF_IRQ_I2C0 29 /* I2C, Level 5 */
#define MCF_IRQ_TIMER 30 /* Timer0, Level 6 */
#define MCF_IRQ_PROFILER 31 /* Timer1, Level 7 */
#define MCF_IRQ_UART0 73 /* UART0 */
#define MCF_IRQ_UART1 74 /* UART1 */
+/*
+ * I2C module
+ */
+#define MCFI2C_BASE0 (MCF_MBAR + 0x280)
+#define MCFI2C_SIZE0 0x40
+
/****************************************************************************/
#endif /* m5407sim_h */
diff --git a/arch/m68k/include/asm/m54xxsim.h b/arch/m68k/include/asm/m54xxsim.h
index 73d937ff36eb..7758d0a1a84d 100644
--- a/arch/m68k/include/asm/m54xxsim.h
+++ b/arch/m68k/include/asm/m54xxsim.h
@@ -45,6 +45,7 @@
*/
#define MCF_IRQ_TIMER (MCFINT_VECBASE + 54) /* Slice Timer 0 */
#define MCF_IRQ_PROFILER (MCFINT_VECBASE + 53) /* Slice Timer 1 */
+#define MCF_IRQ_I2C0 (MCFINT_VECBASE + 40)
#define MCF_IRQ_UART0 (MCFINT_VECBASE + 35)
#define MCF_IRQ_UART1 (MCFINT_VECBASE + 34)
#define MCF_IRQ_UART2 (MCFINT_VECBASE + 33)
@@ -107,4 +108,14 @@
#define MCF_PAR_PSC_RTS_RTS (0x30)
#define MCF_PAR_PSC_CANRX (0x40)
+#define MCF_PAR_FECI2CIRQ (MCF_MBAR + 0x00000a44) /* FEC/I2C/IRQ */
+#define MCF_PAR_FECI2CIRQ_SDA (1 << 3)
+#define MCF_PAR_FECI2CIRQ_SCL (1 << 2)
+
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0 (MCF_MBAR + 0x8f00)
+#define MCFI2C_SIZE0 0x40
+
#endif /* m54xxsim_h */
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index c84a2183b3f0..f5f790c31bf8 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -156,6 +156,5 @@ unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) ((tsk)->thread.esp0))
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#endif
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..167150c701d1 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -27,7 +27,6 @@ generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += msgbuf.h
-generic-y += mutex.h
generic-y += param.h
generic-y += pci.h
generic-y += percpu.h
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index a0333ebcac35..ec6a49076980 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -152,7 +152,6 @@ unsigned long get_wchan(struct task_struct *p);
#define user_stack_pointer(regs) ((regs)->ctx.AX[0].U0)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
extern void setup_priv(void);
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 86f65721e629..85885a501dce 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -27,6 +27,7 @@ config MICROBLAZE
select HAVE_MEMBLOCK_NODE_MAP
select HAVE_OPROFILE
select IRQ_DOMAIN
+ select XILINX_INTC
select MODULES_USE_ELF_RELA
select OF
select OF_EARLY_FLATTREE
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
index bab3b1393ad4..d785defeeed5 100644
--- a/arch/microblaze/include/asm/irq.h
+++ b/arch/microblaze/include/asm/irq.h
@@ -16,6 +16,6 @@ struct pt_regs;
extern void do_IRQ(struct pt_regs *regs);
/* should be defined in each interrupt controller driver */
-extern unsigned int get_irq(void);
+extern unsigned int xintc_get_irq(void);
#endif /* _ASM_MICROBLAZE_IRQ_H */
diff --git a/arch/microblaze/include/asm/mutex.h b/arch/microblaze/include/asm/mutex.h
deleted file mode 100644
index ff6101aa2c71..000000000000
--- a/arch/microblaze/include/asm/mutex.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index c38d0dd91134..37ef196e4519 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -22,7 +22,6 @@
extern const struct seq_operations cpuinfo_op;
# define cpu_relax() barrier()
-# define cpu_relax_lowlatency() cpu_relax()
#define task_pt_regs(tsk) \
(((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index f08bacaf8a95..e098381af928 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -15,7 +15,7 @@ endif
extra-y := head.o vmlinux.lds
obj-y += dma.o exceptions.o \
- hw_exception_handler.o intc.o irq.o \
+ hw_exception_handler.o irq.o \
platform.o process.o prom.o ptrace.o \
reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
deleted file mode 100644
index 90bec7d71f85..000000000000
--- a/arch/microblaze/kernel/intc.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2012-2013 Xilinx, Inc.
- * Copyright (C) 2007-2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-static void __iomem *intc_baseaddr;
-
-/* No one else should require these constants, so define them locally here. */
-#define ISR 0x00 /* Interrupt Status Register */
-#define IPR 0x04 /* Interrupt Pending Register */
-#define IER 0x08 /* Interrupt Enable Register */
-#define IAR 0x0c /* Interrupt Acknowledge Register */
-#define SIE 0x10 /* Set Interrupt Enable bits */
-#define CIE 0x14 /* Clear Interrupt Enable bits */
-#define IVR 0x18 /* Interrupt Vector Register */
-#define MER 0x1c /* Master Enable Register */
-
-#define MER_ME (1<<0)
-#define MER_HIE (1<<1)
-
-static unsigned int (*read_fn)(void __iomem *);
-static void (*write_fn)(u32, void __iomem *);
-
-static void intc_write32(u32 val, void __iomem *addr)
-{
- iowrite32(val, addr);
-}
-
-static unsigned int intc_read32(void __iomem *addr)
-{
- return ioread32(addr);
-}
-
-static void intc_write32_be(u32 val, void __iomem *addr)
-{
- iowrite32be(val, addr);
-}
-
-static unsigned int intc_read32_be(void __iomem *addr)
-{
- return ioread32be(addr);
-}
-
-static void intc_enable_or_unmask(struct irq_data *d)
-{
- unsigned long mask = 1 << d->hwirq;
-
- pr_debug("enable_or_unmask: %ld\n", d->hwirq);
-
- /* ack level irqs because they can't be acked during
- * ack function since the handle_level_irq function
- * acks the irq before calling the interrupt handler
- */
- if (irqd_is_level_type(d))
- write_fn(mask, intc_baseaddr + IAR);
-
- write_fn(mask, intc_baseaddr + SIE);
-}
-
-static void intc_disable_or_mask(struct irq_data *d)
-{
- pr_debug("disable: %ld\n", d->hwirq);
- write_fn(1 << d->hwirq, intc_baseaddr + CIE);
-}
-
-static void intc_ack(struct irq_data *d)
-{
- pr_debug("ack: %ld\n", d->hwirq);
- write_fn(1 << d->hwirq, intc_baseaddr + IAR);
-}
-
-static void intc_mask_ack(struct irq_data *d)
-{
- unsigned long mask = 1 << d->hwirq;
-
- pr_debug("disable_and_ack: %ld\n", d->hwirq);
- write_fn(mask, intc_baseaddr + CIE);
- write_fn(mask, intc_baseaddr + IAR);
-}
-
-static struct irq_chip intc_dev = {
- .name = "Xilinx INTC",
- .irq_unmask = intc_enable_or_unmask,
- .irq_mask = intc_disable_or_mask,
- .irq_ack = intc_ack,
- .irq_mask_ack = intc_mask_ack,
-};
-
-static struct irq_domain *root_domain;
-
-unsigned int get_irq(void)
-{
- unsigned int hwirq, irq = -1;
-
- hwirq = read_fn(intc_baseaddr + IVR);
- if (hwirq != -1U)
- irq = irq_find_mapping(root_domain, hwirq);
-
- pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
-
- return irq;
-}
-
-static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
-{
- u32 intr_mask = (u32)d->host_data;
-
- if (intr_mask & (1 << hw)) {
- irq_set_chip_and_handler_name(irq, &intc_dev,
- handle_edge_irq, "edge");
- irq_clear_status_flags(irq, IRQ_LEVEL);
- } else {
- irq_set_chip_and_handler_name(irq, &intc_dev,
- handle_level_irq, "level");
- irq_set_status_flags(irq, IRQ_LEVEL);
- }
- return 0;
-}
-
-static const struct irq_domain_ops xintc_irq_domain_ops = {
- .xlate = irq_domain_xlate_onetwocell,
- .map = xintc_map,
-};
-
-static int __init xilinx_intc_of_init(struct device_node *intc,
- struct device_node *parent)
-{
- u32 nr_irq, intr_mask;
- int ret;
-
- intc_baseaddr = of_iomap(intc, 0);
- BUG_ON(!intc_baseaddr);
-
- ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
- if (ret < 0) {
- pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
- return ret;
- }
-
- ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
- if (ret < 0) {
- pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
- return ret;
- }
-
- if (intr_mask >> nr_irq)
- pr_warn("%s: mismatch in kind-of-intr param\n", __func__);
-
- pr_info("%s: num_irq=%d, edge=0x%x\n",
- intc->full_name, nr_irq, intr_mask);
-
- write_fn = intc_write32;
- read_fn = intc_read32;
-
- /*
- * Disable all external interrupts until they are
- * explicity requested.
- */
- write_fn(0, intc_baseaddr + IER);
-
- /* Acknowledge any pending interrupts just in case. */
- write_fn(0xffffffff, intc_baseaddr + IAR);
-
- /* Turn on the Master Enable. */
- write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
- if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
- write_fn = intc_write32_be;
- read_fn = intc_read32_be;
- write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
- }
-
- /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
- * lazy and Michal can clean it up to something nicer when he tests
- * and commits this patch. ~~gcl */
- root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
- (void *)intr_mask);
-
- irq_set_default_host(root_domain);
-
- return 0;
-}
-
-IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 11e24de91aa4..903dad822fad 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -29,12 +29,12 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
trace_hardirqs_off();
irq_enter();
- irq = get_irq();
+ irq = xintc_get_irq();
next_irq:
BUG_ON(!irq);
generic_handle_irq(irq);
- irq = get_irq();
+ irq = xintc_get_irq();
if (irq != -1U) {
pr_debug("next irq: %d\n", irq);
++concurrent_irq;
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..3269b742a75e 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -9,7 +9,6 @@ generic-y += irq_work.h
generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
-generic-y += mutex.h
generic-y += parport.h
generic-y += percpu.h
generic-y += preempt.h
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 0d36c87acbe2..95b8c471f572 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -389,7 +389,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
/*
* Return_address is a replacement for __builtin_return_address(count)
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 2027240aafbb..566ecdcb5b4b 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -108,4 +108,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/asm/mutex.h b/arch/mn10300/include/asm/mutex.h
deleted file mode 100644
index 84f5490c6fb4..000000000000
--- a/arch/mn10300/include/asm/mutex.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* MN10300 Mutex fastpath
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- *
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-#include <asm-generic/mutex-null.h>
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index b10ba121c849..18e17abf7664 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -69,7 +69,6 @@ extern void print_cpu_info(struct mn10300_cpuinfo *);
extern void dodgy_tsc(void);
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
/*
* User space process size: 1.75GB (default).
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index 5129f23a9ee1..0e12527c4b0e 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/mn10300/unit-asb2303/include/unit/smc91111.h b/arch/mn10300/unit-asb2303/include/unit/smc91111.h
index dd456e9c513f..dd4e2946438e 100644
--- a/arch/mn10300/unit-asb2303/include/unit/smc91111.h
+++ b/arch/mn10300/unit-asb2303/include/unit/smc91111.h
@@ -30,7 +30,7 @@
#if SMC_CAN_USE_16BIT
#define SMC_inw(a, r) inw((unsigned long) ((a) + (r)))
-#define SMC_outw(v, a, r) outw(v, (unsigned long) ((a) + (r)))
+#define SMC_outw(lp, v, a, r) outw(v, (unsigned long) ((a) + (r)))
#define SMC_insw(a, r, p, l) insw((unsigned long) ((a) + (r)), (p), (l))
#define SMC_outsw(a, r, p, l) outsw((unsigned long) ((a) + (r)), (p), (l))
#endif
diff --git a/arch/nios2/include/asm/mutex.h b/arch/nios2/include/asm/mutex.h
deleted file mode 100644
index ff6101aa2c71..000000000000
--- a/arch/nios2/include/asm/mutex.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h
index 1c953f0cadbf..3bbbc3d798e5 100644
--- a/arch/nios2/include/asm/processor.h
+++ b/arch/nios2/include/asm/processor.h
@@ -88,7 +88,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.kregs->sp)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#endif /* __ASSEMBLY__ */
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 489e7f909286..8d22015fde3e 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -26,6 +26,7 @@ config OPENRISC
select HAVE_DEBUG_STACKOVERFLOW
select OR1K_PIC
select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1
+ select NO_BOOTMEM
config MMU
def_bool y
@@ -98,6 +99,9 @@ config OPENRISC_HAVE_INST_DIV
Select this if your implementation has a hardware divide instruction
endmenu
+config NR_CPUS
+ int
+ default "1"
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
diff --git a/arch/openrisc/README.openrisc b/arch/openrisc/README.openrisc
index c9f7edf2b9a2..072069ab5100 100644
--- a/arch/openrisc/README.openrisc
+++ b/arch/openrisc/README.openrisc
@@ -6,7 +6,7 @@ target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
For information about OpenRISC processors and ongoing development:
- website http://openrisc.net
+ website http://openrisc.io
For more information about Linux on OpenRISC, please contact South Pole AB.
@@ -24,17 +24,17 @@ In order to build and run Linux for OpenRISC, you'll need at least a basic
toolchain and, perhaps, the architectural simulator. Steps to get these bits
in place are outlined here.
-1) The toolchain can be obtained from openrisc.net. Instructions for building
+1) The toolchain can be obtained from openrisc.io. Instructions for building
a toolchain can be found at:
-http://openrisc.net/toolchain-build.html
+https://github.com/openrisc/tutorials
2) or1ksim (optional)
or1ksim is the architectural simulator which will allow you to actually run
your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
- git clone git://openrisc.net/jonas/or1ksim-svn
+ git clone https://github.com/openrisc/or1ksim.git
cd or1ksim
./configure --prefix=$OPENRISC_PREFIX
diff --git a/arch/openrisc/TODO.openrisc b/arch/openrisc/TODO.openrisc
index acfeef9c58e3..0eb04c8240f9 100644
--- a/arch/openrisc/TODO.openrisc
+++ b/arch/openrisc/TODO.openrisc
@@ -5,9 +5,6 @@ that are due for investigation shortly, i.e. our TODO list:
-- Implement the rest of the DMA API... dma_map_sg, etc.
--- Consolidate usage of memblock and bootmem... move everything over to
- memblock.
-
-- Finish the renaming cleanup... there are references to or32 in the code
which was an older name for the architecture. The name we've settled on is
or1k and this change is slowly trickling through the stack. For the time
diff --git a/arch/openrisc/include/asm/mutex.h b/arch/openrisc/include/asm/mutex.h
deleted file mode 100644
index b85a0cfa9fc9..000000000000
--- a/arch/openrisc/include/asm/mutex.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others. All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * 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.
- */
-
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h
index 87eebd185089..3e1a46615120 100644
--- a/arch/openrisc/include/asm/pgalloc.h
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -23,7 +23,6 @@
#include <linux/threads.h>
#include <linux/mm.h>
#include <linux/memblock.h>
-#include <linux/bootmem.h>
extern int mem_init_done;
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
index 69c7df0e1420..3567aa7be555 100644
--- a/arch/openrisc/include/asm/pgtable.h
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -69,7 +69,7 @@ extern void paging_init(void);
*/
#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-2))
-#define PTRS_PER_PGD (1UL << (PAGE_SHIFT-2))
+#define PTRS_PER_PGD (1UL << (32-PGDIR_SHIFT))
/* calculate how many PGD entries a user-level program can use
* the first mappable virtual address is 0
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index 70334c9f7d24..a908e6c30a00 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -92,7 +92,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
#define init_stack (init_thread_union.stack)
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#endif /* __ASSEMBLY__ */
#endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index fec8bf97d806..aac0bde3330c 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -264,7 +264,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
l.srli r6,r6,26 // check opcode for write access
#endif
- l.sfgeui r6,0x34 // check opcode for write access
+ l.sfgeui r6,0x33 // check opcode for write access
l.bnf 1f
l.sfleui r6,0x37
l.bnf 1f
@@ -1101,8 +1101,16 @@ ENTRY(__sys_fork)
l.addi r3,r1,0
ENTRY(sys_rt_sigreturn)
- l.j _sys_rt_sigreturn
+ l.jal _sys_rt_sigreturn
l.addi r3,r1,0
+ l.sfne r30,r0
+ l.bnf _no_syscall_trace
+ l.nop
+ l.jal do_syscall_trace_leave
+ l.addi r3,r1,0
+_no_syscall_trace:
+ l.j _resume_userspace
+ l.nop
/* This is a catch-all syscall for atomic instructions for the OpenRISC 1000.
* The functions takes a variable number of parameters depending on which
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index 7095dfe7666b..277123bb4bf8 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -173,6 +173,19 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
if (usp)
userregs->sp = usp;
+
+ /*
+ * For CLONE_SETTLS set "tp" (r10) to the TLS pointer passed to sys_clone.
+ *
+ * The kernel entry is:
+ * int clone (long flags, void *child_stack, int *parent_tid,
+ * int *child_tid, struct void *tls)
+ *
+ * This makes the source r7 in the kernel registers.
+ */
+ if (clone_flags & CLONE_SETTLS)
+ userregs->gpr[10] = userregs->gpr[7];
+
userregs->gpr[11] = 0; /* Result from fork() */
kregs->gpr[20] = 0; /* Userspace thread */
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
index b4ed8b36e078..cb797a3beb47 100644
--- a/arch/openrisc/kernel/setup.c
+++ b/arch/openrisc/kernel/setup.c
@@ -38,7 +38,6 @@
#include <linux/of.h>
#include <linux/memblock.h>
#include <linux/device.h>
-#include <linux/of_platform.h>
#include <asm/sections.h>
#include <asm/segment.h>
@@ -51,18 +50,16 @@
#include "vmlinux.h"
-static unsigned long __init setup_memory(void)
+static void __init setup_memory(void)
{
- unsigned long bootmap_size;
unsigned long ram_start_pfn;
- unsigned long free_ram_start_pfn;
unsigned long ram_end_pfn;
phys_addr_t memory_start, memory_end;
struct memblock_region *region;
memory_end = memory_start = 0;
- /* Find main memory where is the kernel */
+ /* Find main memory where is the kernel, we assume its the only one */
for_each_memblock(memory, region) {
memory_start = region->base;
memory_end = region->base + region->size;
@@ -75,10 +72,11 @@ static unsigned long __init setup_memory(void)
}
ram_start_pfn = PFN_UP(memory_start);
- /* free_ram_start_pfn is first page after kernel */
- free_ram_start_pfn = PFN_UP(__pa(_end));
ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+ /* setup bootmem globals (we use no_bootmem, but mm still depends on this) */
+ min_low_pfn = ram_start_pfn;
+ max_low_pfn = ram_end_pfn;
max_pfn = ram_end_pfn;
/*
@@ -86,22 +84,13 @@ static unsigned long __init setup_memory(void)
*
* This makes the memory from the end of the kernel to the end of
* RAM usable.
- * init_bootmem sets the global values min_low_pfn, max_low_pfn.
*/
- bootmap_size = init_bootmem(free_ram_start_pfn,
- ram_end_pfn - ram_start_pfn);
- free_bootmem(PFN_PHYS(free_ram_start_pfn),
- (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
- reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
- BOOTMEM_DEFAULT);
-
- for_each_memblock(reserved, region) {
- printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
- (u32) region->base, (u32) region->size);
- reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
- }
+ memblock_reserve(__pa(_stext), _end - _stext);
+
+ early_init_fdt_reserve_self();
+ early_init_fdt_scan_reserved_mem();
- return ram_end_pfn;
+ memblock_dump_all();
}
struct cpuinfo cpuinfo;
@@ -219,15 +208,6 @@ void __init or32_early_setup(void *fdt)
early_init_devtree(fdt);
}
-static int __init openrisc_device_probe(void)
-{
- of_platform_populate(NULL, NULL, NULL, NULL);
-
- return 0;
-}
-
-device_initcall(openrisc_device_probe);
-
static inline unsigned long extract_value_bits(unsigned long reg,
short bit_nr, short width)
{
@@ -282,8 +262,6 @@ void calibrate_delay(void)
void __init setup_arch(char **cmdline_p)
{
- unsigned long max_low_pfn;
-
unflatten_and_copy_device_tree();
setup_cpuinfo();
@@ -304,8 +282,8 @@ void __init setup_arch(char **cmdline_p)
initrd_below_start_ok = 1;
#endif
- /* setup bootmem allocator */
- max_low_pfn = setup_memory();
+ /* setup memblock allocator */
+ setup_memory();
/* paging_init() sets up the MMU and marks all pages as reserved */
paging_init();
@@ -317,7 +295,7 @@ void __init setup_arch(char **cmdline_p)
*cmdline_p = boot_command_line;
- printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
+ printk(KERN_INFO "OpenRISC Linux -- http://openrisc.io\n");
}
static int show_cpuinfo(struct seq_file *m, void *v)
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index d68b9ede8423..ef31fc24344e 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -30,7 +30,13 @@
#include <asm/cache.h>
#include <asm-generic/vmlinux.lds.h>
-OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
+#ifdef __OR1K__
+#define __OUTPUT_FORMAT "elf32-or1k"
+#else
+#define __OUTPUT_FORMAT "elf32-or32"
+#endif
+
+OUTPUT_FORMAT(__OUTPUT_FORMAT, __OUTPUT_FORMAT, __OUTPUT_FORMAT)
jiffies = jiffies_64 + 4;
SECTIONS
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
index 7f94652311d7..f67d82b9d22f 100644
--- a/arch/openrisc/mm/init.c
+++ b/arch/openrisc/mm/init.c
@@ -106,11 +106,11 @@ static void __init map_ram(void)
}
/* Alloc one page for holding PTE's... */
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
/* Fill the newly allocated page with PTE'S */
- for (j = 0; p < e && j < PTRS_PER_PGD;
+ for (j = 0; p < e && j < PTRS_PER_PTE;
v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
if (v >= (u32) _e_kernel_ro ||
v < (u32) _s_kernel_ro)
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
index fa60b81aee3e..8705a46218f9 100644
--- a/arch/openrisc/mm/ioremap.c
+++ b/arch/openrisc/mm/ioremap.c
@@ -124,11 +124,7 @@ pte_t __ref *pte_alloc_one_kernel(struct mm_struct *mm,
if (likely(mem_init_done)) {
pte = (pte_t *) __get_free_page(GFP_KERNEL);
} else {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-#if 0
- /* FIXME: use memblock... */
pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
-#endif
}
if (pte)
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..91f53c07f410 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -16,7 +16,6 @@ generic-y += local.h
generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
-generic-y += mutex.h
generic-y += param.h
generic-y += percpu.h
generic-y += poll.h
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 2e674e13e005..ca40741378be 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -309,7 +309,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30])
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
/*
* parisc_requires_coherency() is used to identify the combined VIPT/PIPT
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 9c935d717df9..7a109b73ddf7 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -89,4 +89,6 @@
#define SO_CNX_ADVICE 0x402E
+#define SCM_TIMESTAMPING_OPT_STATS 0x402F
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 65fba4c34cd7..c7f120aaa98f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -160,6 +160,7 @@ config PPC
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
select GENERIC_CPU_AUTOPROBE
select HAVE_VIRT_CPU_ACCOUNTING
+ select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_KERNEL_GZIP
diff --git a/arch/powerpc/configs/dpaa.config b/arch/powerpc/configs/dpaa.config
index efa99c048543..2fe76f5e938a 100644
--- a/arch/powerpc/configs/dpaa.config
+++ b/arch/powerpc/configs/dpaa.config
@@ -1 +1,4 @@
CONFIG_FSL_DPAA=y
+CONFIG_FSL_PAMU=y
+CONFIG_FSL_FMAN=y
+CONFIG_FSL_DPAA_ETH=y
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index 9fd77f8794a0..0ebfbc8f0449 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -1009,7 +1009,8 @@ static inline void pmdp_huge_split_prepare(struct vm_area_struct *vma,
#define pmd_move_must_withdraw pmd_move_must_withdraw
struct spinlock;
static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
- struct spinlock *old_pmd_ptl)
+ struct spinlock *old_pmd_ptl,
+ struct vm_area_struct *vma)
{
if (radix_enabled())
return false;
@@ -1020,6 +1021,16 @@ static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
*/
return true;
}
+
+
+#define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
+static inline bool arch_needs_pgtable_deposit(void)
+{
+ if (radix_enabled())
+ return false;
+ return true;
+}
+
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 4f60db074725..aa2e6a34b872 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -46,26 +46,12 @@ extern cputime_t cputime_one_jiffy;
* Convert cputime <-> jiffies
*/
extern u64 __cputime_jiffies_factor;
-DECLARE_PER_CPU(unsigned long, cputime_last_delta);
-DECLARE_PER_CPU(unsigned long, cputime_scaled_last_delta);
static inline unsigned long cputime_to_jiffies(const cputime_t ct)
{
return mulhdu((__force u64) ct, __cputime_jiffies_factor);
}
-/* Estimate the scaled cputime by scaling the real cputime based on
- * the last scaled to real ratio */
-static inline cputime_t cputime_to_scaled(const cputime_t ct)
-{
- if (cpu_has_feature(CPU_FTR_SPURR) &&
- __this_cpu_read(cputime_last_delta))
- return (__force u64) ct *
- __this_cpu_read(cputime_scaled_last_delta) /
- __this_cpu_read(cputime_last_delta);
- return ct;
-}
-
static inline cputime_t jiffies_to_cputime(const unsigned long jif)
{
u64 ct;
diff --git a/arch/powerpc/include/asm/mutex.h b/arch/powerpc/include/asm/mutex.h
deleted file mode 100644
index 078155fa1189..000000000000
--- a/arch/powerpc/include/asm/mutex.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Optimised mutex implementation of include/asm-generic/mutex-dec.h algorithm
- */
-#ifndef _ASM_POWERPC_MUTEX_H
-#define _ASM_POWERPC_MUTEX_H
-
-static inline int __mutex_cmpxchg_lock(atomic_t *v, int old, int new)
-{
- int t;
-
- __asm__ __volatile__ (
-"1: lwarx %0,0,%1 # mutex trylock\n\
- cmpw 0,%0,%2\n\
- bne- 2f\n"
- PPC405_ERR77(0,%1)
-" stwcx. %3,0,%1\n\
- bne- 1b"
- PPC_ACQUIRE_BARRIER
- "\n\
-2:"
- : "=&r" (t)
- : "r" (&v->counter), "r" (old), "r" (new)
- : "cc", "memory");
-
- return t;
-}
-
-static inline int __mutex_dec_return_lock(atomic_t *v)
-{
- int t;
-
- __asm__ __volatile__(
-"1: lwarx %0,0,%1 # mutex lock\n\
- addic %0,%0,-1\n"
- PPC405_ERR77(0,%1)
-" stwcx. %0,0,%1\n\
- bne- 1b"
- PPC_ACQUIRE_BARRIER
- : "=&r" (t)
- : "r" (&v->counter)
- : "cc", "memory");
-
- return t;
-}
-
-static inline int __mutex_inc_return_unlock(atomic_t *v)
-{
- int t;
-
- __asm__ __volatile__(
- PPC_RELEASE_BARRIER
-"1: lwarx %0,0,%1 # mutex unlock\n\
- addic %0,%0,1\n"
- PPC405_ERR77(0,%1)
-" stwcx. %0,0,%1 \n\
- bne- 1b"
- : "=&r" (t)
- : "r" (&v->counter)
- : "cc", "memory");
-
- return t;
-}
-
-/**
- * __mutex_fastpath_lock - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(__mutex_dec_return_lock(count) < 0))
- fail_fn(count);
-}
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(__mutex_dec_return_lock(count) < 0))
- return -1;
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - try to promote the count from 0 to 1
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(__mutex_inc_return_unlock(count) <= 0))
- fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: fallback function
- *
- * Change the count from 1 to 0, and return 1 (success), or if the count
- * was not 1, then return 0 (failure).
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- if (likely(atomic_read(count) == 1 && __mutex_cmpxchg_lock(count, 1, 0) == 1))
- return 1;
- return 0;
-}
-
-#endif
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index c07c31b0e89e..dac83fcb9445 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -404,8 +404,6 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
#define cpu_relax() barrier()
#endif
-#define cpu_relax_lowlatency() cpu_relax()
-
/* Check that a certain kernel stack pointer is valid in task_struct p */
int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes);
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
index fa37fe93bc02..8c1b913de6d7 100644
--- a/arch/powerpc/include/asm/spinlock.h
+++ b/arch/powerpc/include/asm/spinlock.h
@@ -52,6 +52,14 @@
#define SYNC_IO
#endif
+#ifdef CONFIG_PPC_PSERIES
+#define vcpu_is_preempted vcpu_is_preempted
+static inline bool vcpu_is_preempted(int cpu)
+{
+ return !!(be32_to_cpu(lppaca_of(cpu).yield_count) & 1);
+}
+#endif
+
static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
return lock.slock == 0;
diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h
index 99e1397b71da..609557569f65 100644
--- a/arch/powerpc/include/asm/tlb.h
+++ b/arch/powerpc/include/asm/tlb.h
@@ -28,6 +28,7 @@
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define __tlb_remove_tlb_entry __tlb_remove_tlb_entry
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
extern void tlb_flush(struct mmu_gather *tlb);
@@ -46,6 +47,21 @@ static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
#endif
}
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+ if (!tlb->page_size)
+ tlb->page_size = page_size;
+ else if (tlb->page_size != page_size) {
+ tlb_flush_mmu(tlb);
+ /*
+ * update the page size after flush for the new
+ * mmu_gather.
+ */
+ tlb->page_size = page_size;
+ }
+}
+
#ifdef CONFIG_SMP
static inline int mm_is_core_local(struct mm_struct *mm)
{
diff --git a/arch/powerpc/include/asm/xilinx_intc.h b/arch/powerpc/include/asm/xilinx_intc.h
index 343612f8fece..3192d7f0a05b 100644
--- a/arch/powerpc/include/asm/xilinx_intc.h
+++ b/arch/powerpc/include/asm/xilinx_intc.h
@@ -14,7 +14,7 @@
#ifdef __KERNEL__
extern void __init xilinx_intc_init_tree(void);
-extern unsigned int xilinx_intc_get_irq(void);
+extern unsigned int xintc_get_irq(void);
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_XILINX_INTC_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 1672e3398270..44583a52f882 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -97,4 +97,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index c4f1d1f7bae0..c1fb255a60d6 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -703,7 +703,7 @@ static struct device_attribute pa6t_attrs[] = {
#endif /* HAS_PPC_PMC_PA6T */
#endif /* HAS_PPC_PMC_CLASSIC */
-static void register_cpu_online(unsigned int cpu)
+static int register_cpu_online(unsigned int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct device *s = &c->dev;
@@ -782,11 +782,12 @@ static void register_cpu_online(unsigned int cpu)
}
#endif
cacheinfo_cpu_online(cpu);
+ return 0;
}
-#ifdef CONFIG_HOTPLUG_CPU
-static void unregister_cpu_online(unsigned int cpu)
+static int unregister_cpu_online(unsigned int cpu)
{
+#ifdef CONFIG_HOTPLUG_CPU
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct device *s = &c->dev;
struct device_attribute *attrs, *pmc_attrs;
@@ -863,6 +864,8 @@ static void unregister_cpu_online(unsigned int cpu)
}
#endif
cacheinfo_cpu_offline(cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
+ return 0;
}
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
@@ -883,32 +886,6 @@ ssize_t arch_cpu_release(const char *buf, size_t count)
}
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
-#endif /* CONFIG_HOTPLUG_CPU */
-
-static int sysfs_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned int)(long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- register_cpu_online(cpu);
- break;
-#ifdef CONFIG_HOTPLUG_CPU
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- unregister_cpu_online(cpu);
- break;
-#endif
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block sysfs_cpu_nb = {
- .notifier_call = sysfs_cpu_notify,
-};
-
static DEFINE_MUTEX(cpu_mutex);
int cpu_add_dev_attr(struct device_attribute *attr)
@@ -1023,12 +1000,10 @@ static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL);
static int __init topology_init(void)
{
- int cpu;
+ int cpu, r;
register_nodes();
- cpu_notifier_register_begin();
-
for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -1047,15 +1022,10 @@ static int __init topology_init(void)
device_create_file(&c->dev, &dev_attr_physical_id);
}
-
- if (cpu_online(cpu))
- register_cpu_online(cpu);
}
-
- __register_cpu_notifier(&sysfs_cpu_nb);
-
- cpu_notifier_register_done();
-
+ r = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/topology:online",
+ register_cpu_online, unregister_cpu_online);
+ WARN_ON(r < 0);
#ifdef CONFIG_PPC64
sysfs_create_dscr_default();
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index bc3f7d0d7b79..be9751f1cb2a 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -164,8 +164,6 @@ u64 __cputime_sec_factor;
EXPORT_SYMBOL(__cputime_sec_factor);
u64 __cputime_clockt_factor;
EXPORT_SYMBOL(__cputime_clockt_factor);
-DEFINE_PER_CPU(unsigned long, cputime_last_delta);
-DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
cputime_t cputime_one_jiffy;
@@ -360,7 +358,8 @@ void vtime_account_system(struct task_struct *tsk)
unsigned long delta, sys_scaled, stolen;
delta = vtime_delta(tsk, &sys_scaled, &stolen);
- account_system_time(tsk, 0, delta, sys_scaled);
+ account_system_time(tsk, 0, delta);
+ tsk->stimescaled += sys_scaled;
if (stolen)
account_steal_time(stolen);
}
@@ -393,7 +392,8 @@ void vtime_account_user(struct task_struct *tsk)
acct->user_time = 0;
acct->user_time_scaled = 0;
acct->utime_sspurr = 0;
- account_user_time(tsk, utime, utimescaled);
+ account_user_time(tsk, utime);
+ tsk->utimescaled += utimescaled;
}
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 3686471be32b..39ef1f4a7b02 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -2254,12 +2254,12 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master)
* enter the guest. Only do this if it is the primary thread of the
* core (not if a subcore) that is entering the guest.
*/
-static inline void kvmppc_clear_host_core(int cpu)
+static inline int kvmppc_clear_host_core(unsigned int cpu)
{
int core;
if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
- return;
+ return 0;
/*
* Memory barrier can be omitted here as we will do a smp_wmb()
* later in kvmppc_start_thread and we need ensure that state is
@@ -2267,6 +2267,7 @@ static inline void kvmppc_clear_host_core(int cpu)
*/
core = cpu >> threads_shift;
kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 0;
+ return 0;
}
/*
@@ -2274,12 +2275,12 @@ static inline void kvmppc_clear_host_core(int cpu)
* Only need to do this if it is the primary thread of the core that is
* exiting.
*/
-static inline void kvmppc_set_host_core(int cpu)
+static inline int kvmppc_set_host_core(unsigned int cpu)
{
int core;
if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
- return;
+ return 0;
/*
* Memory barrier can be omitted here because we do a spin_unlock
@@ -2287,6 +2288,7 @@ static inline void kvmppc_set_host_core(int cpu)
*/
core = cpu >> threads_shift;
kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 1;
+ return 0;
}
/*
@@ -3094,36 +3096,6 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
}
#ifdef CONFIG_KVM_XICS
-static int kvmppc_cpu_notify(struct notifier_block *self, unsigned long action,
- void *hcpu)
-{
- unsigned long cpu = (long)hcpu;
-
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- kvmppc_set_host_core(cpu);
- break;
-
-#ifdef CONFIG_HOTPLUG_CPU
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- kvmppc_clear_host_core(cpu);
- break;
-#endif
- default:
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block kvmppc_cpu_notifier = {
- .notifier_call = kvmppc_cpu_notify,
-};
-
/*
* Allocate a per-core structure for managing state about which cores are
* running in the host versus the guest and for exchanging data between
@@ -3185,15 +3157,17 @@ void kvmppc_alloc_host_rm_ops(void)
return;
}
- register_cpu_notifier(&kvmppc_cpu_notifier);
-
+ cpuhp_setup_state_nocalls(CPUHP_KVM_PPC_BOOK3S_PREPARE,
+ "ppc/kvm_book3s:prepare",
+ kvmppc_set_host_core,
+ kvmppc_clear_host_core);
put_online_cpus();
}
void kvmppc_free_host_rm_ops(void)
{
if (kvmppc_host_rm_ops_hv) {
- unregister_cpu_notifier(&kvmppc_cpu_notifier);
+ cpuhp_remove_state_nocalls(CPUHP_KVM_PPC_BOOK3S_PREPARE);
kfree(kvmppc_host_rm_ops_hv->rm_core);
kfree(kvmppc_host_rm_ops_hv);
kvmppc_host_rm_ops_hv = NULL;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index a51c188b81f3..0cb6bd8bfccf 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1085,7 +1085,7 @@ static int hot_add_node_scn_to_nid(unsigned long scn_addr)
int hot_add_scn_to_nid(unsigned long scn_addr)
{
struct device_node *memory = NULL;
- int nid, found = 0;
+ int nid;
if (!numa_enabled || (min_common_depth < 0))
return first_online_node;
@@ -1101,17 +1101,6 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
if (nid < 0 || !node_online(nid))
nid = first_online_node;
- if (NODE_DATA(nid)->node_spanned_pages)
- return nid;
-
- for_each_online_node(nid) {
- if (NODE_DATA(nid)->node_spanned_pages) {
- found = 1;
- break;
- }
- }
-
- BUG_ON(!found);
return nid;
}
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 0fe98a567125..73a5cf18fd84 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -766,7 +766,7 @@ emit_clear:
func = (u8 *) __bpf_call_base + imm;
/* Save skb pointer if we need to re-cache skb data */
- if (bpf_helper_changes_skb_data(func))
+ if (bpf_helper_changes_pkt_data(func))
PPC_BPF_STL(3, 1, bpf_jit_stack_local(ctx));
bpf_jit_emit_func_call(image, ctx, (u64)func);
@@ -775,7 +775,7 @@ emit_clear:
PPC_MR(b2p[BPF_REG_0], 3);
/* refresh skb cache */
- if (bpf_helper_changes_skb_data(func)) {
+ if (bpf_helper_changes_pkt_data(func)) {
/* reload skb pointer to r3 */
PPC_BPF_LL(3, 1, bpf_jit_stack_local(ctx));
bpf_jit_emit_skb_loads(image, ctx);
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index e3257f24a8a1..1d7c1b142bf4 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -64,6 +64,7 @@ config XILINX_VIRTEX_GENERIC_BOARD
default n
select XILINX_VIRTEX_II_PRO
select XILINX_VIRTEX_4_FX
+ select XILINX_INTC
help
This option enables generic support for Xilinx Virtex based boards.
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index 91a08ea758a8..e3d5e095846b 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -48,7 +48,7 @@ define_machine(virtex) {
.probe = virtex_probe,
.setup_arch = xilinx_pci_init,
.init_IRQ = xilinx_intc_init_tree,
- .get_irq = xilinx_intc_get_irq,
+ .get_irq = xintc_get_irq,
.restart = ppc4xx_reset_system,
.calibrate_decr = generic_calibrate_decr,
};
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 48fc18041ff6..25b8d641ff9f 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -241,6 +241,7 @@ config XILINX_VIRTEX440_GENERIC_BOARD
depends on 44x
default n
select XILINX_VIRTEX_5_FXT
+ select XILINX_INTC
help
This option enables generic support for Xilinx Virtex based boards
that use a 440 based processor in the Virtex 5 FXT FPGA architecture.
diff --git a/arch/powerpc/platforms/44x/virtex.c b/arch/powerpc/platforms/44x/virtex.c
index a7e08026097a..3eb13ed926ee 100644
--- a/arch/powerpc/platforms/44x/virtex.c
+++ b/arch/powerpc/platforms/44x/virtex.c
@@ -54,7 +54,7 @@ define_machine(virtex) {
.probe = virtex_probe,
.setup_arch = xilinx_pci_init,
.init_IRQ = xilinx_intc_init_tree,
- .get_irq = xilinx_intc_get_irq,
+ .get_irq = xintc_get_irq,
.calibrate_decr = generic_calibrate_decr,
.restart = ppc4xx_reset_system,
};
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 0f52d7955796..4a86dcff3fcd 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -29,194 +29,7 @@
#include <asm/processor.h>
#include <asm/i8259.h>
#include <asm/irq.h>
-
-/*
- * INTC Registers
- */
-#define XINTC_ISR 0 /* Interrupt Status */
-#define XINTC_IPR 4 /* Interrupt Pending */
-#define XINTC_IER 8 /* Interrupt Enable */
-#define XINTC_IAR 12 /* Interrupt Acknowledge */
-#define XINTC_SIE 16 /* Set Interrupt Enable bits */
-#define XINTC_CIE 20 /* Clear Interrupt Enable bits */
-#define XINTC_IVR 24 /* Interrupt Vector */
-#define XINTC_MER 28 /* Master Enable */
-
-static struct irq_domain *master_irqhost;
-
-#define XILINX_INTC_MAXIRQS (32)
-
-/* The following table allows the interrupt type, edge or level,
- * to be cached after being read from the device tree until the interrupt
- * is mapped
- */
-static int xilinx_intc_typetable[XILINX_INTC_MAXIRQS];
-
-/* Map the interrupt type from the device tree to the interrupt types
- * used by the interrupt subsystem
- */
-static unsigned char xilinx_intc_map_senses[] = {
- IRQ_TYPE_EDGE_RISING,
- IRQ_TYPE_EDGE_FALLING,
- IRQ_TYPE_LEVEL_HIGH,
- IRQ_TYPE_LEVEL_LOW,
-};
-
-/*
- * The interrupt controller is setup such that it doesn't work well with
- * the level interrupt handler in the kernel because the handler acks the
- * interrupt before calling the application interrupt handler. To deal with
- * that, we use 2 different irq chips so that different functions can be
- * used for level and edge type interrupts.
- *
- * IRQ Chip common (across level and edge) operations
- */
-static void xilinx_intc_mask(struct irq_data *d)
-{
- int irq = irqd_to_hwirq(d);
- void * regs = irq_data_get_irq_chip_data(d);
- pr_debug("mask: %d\n", irq);
- out_be32(regs + XINTC_CIE, 1 << irq);
-}
-
-static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
-{
- return 0;
-}
-
-/*
- * IRQ Chip level operations
- */
-static void xilinx_intc_level_unmask(struct irq_data *d)
-{
- int irq = irqd_to_hwirq(d);
- void * regs = irq_data_get_irq_chip_data(d);
- pr_debug("unmask: %d\n", irq);
- out_be32(regs + XINTC_SIE, 1 << irq);
-
- /* ack level irqs because they can't be acked during
- * ack function since the handle_level_irq function
- * acks the irq before calling the inerrupt handler
- */
- out_be32(regs + XINTC_IAR, 1 << irq);
-}
-
-static struct irq_chip xilinx_intc_level_irqchip = {
- .name = "Xilinx Level INTC",
- .irq_mask = xilinx_intc_mask,
- .irq_mask_ack = xilinx_intc_mask,
- .irq_unmask = xilinx_intc_level_unmask,
- .irq_set_type = xilinx_intc_set_type,
-};
-
-/*
- * IRQ Chip edge operations
- */
-static void xilinx_intc_edge_unmask(struct irq_data *d)
-{
- int irq = irqd_to_hwirq(d);
- void *regs = irq_data_get_irq_chip_data(d);
- pr_debug("unmask: %d\n", irq);
- out_be32(regs + XINTC_SIE, 1 << irq);
-}
-
-static void xilinx_intc_edge_ack(struct irq_data *d)
-{
- int irq = irqd_to_hwirq(d);
- void * regs = irq_data_get_irq_chip_data(d);
- pr_debug("ack: %d\n", irq);
- out_be32(regs + XINTC_IAR, 1 << irq);
-}
-
-static struct irq_chip xilinx_intc_edge_irqchip = {
- .name = "Xilinx Edge INTC",
- .irq_mask = xilinx_intc_mask,
- .irq_unmask = xilinx_intc_edge_unmask,
- .irq_ack = xilinx_intc_edge_ack,
- .irq_set_type = xilinx_intc_set_type,
-};
-
-/*
- * IRQ Host operations
- */
-
-/**
- * xilinx_intc_xlate - translate virq# from device tree interrupts property
- */
-static int xilinx_intc_xlate(struct irq_domain *h, struct device_node *ct,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq,
- unsigned int *out_flags)
-{
- if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS))
- return -EINVAL;
-
- /* keep a copy of the interrupt type til the interrupt is mapped
- */
- xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]];
-
- /* Xilinx uses 2 interrupt entries, the 1st being the h/w
- * interrupt number, the 2nd being the interrupt type, edge or level
- */
- *out_hwirq = intspec[0];
- *out_flags = xilinx_intc_map_senses[intspec[1]];
-
- return 0;
-}
-static int xilinx_intc_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t irq)
-{
- irq_set_chip_data(virq, h->host_data);
-
- if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
- xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
- irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
- handle_level_irq);
- } else {
- irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
- handle_edge_irq);
- }
- return 0;
-}
-
-static const struct irq_domain_ops xilinx_intc_ops = {
- .map = xilinx_intc_map,
- .xlate = xilinx_intc_xlate,
-};
-
-struct irq_domain * __init
-xilinx_intc_init(struct device_node *np)
-{
- struct irq_domain * irq;
- void * regs;
-
- /* Find and map the intc registers */
- regs = of_iomap(np, 0);
- if (!regs) {
- pr_err("xilinx_intc: could not map registers\n");
- return NULL;
- }
-
- /* Setup interrupt controller */
- out_be32(regs + XINTC_IER, 0); /* disable all irqs */
- out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */
- out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
-
- /* Allocate and initialize an irq_domain structure. */
- irq = irq_domain_add_linear(np, XILINX_INTC_MAXIRQS, &xilinx_intc_ops,
- regs);
- if (!irq)
- panic(__FILE__ ": Cannot allocate IRQ host\n");
-
- return irq;
-}
-
-int xilinx_intc_get_irq(void)
-{
- void * regs = master_irqhost->host_data;
- pr_debug("get_irq:\n");
- return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
-}
+#include <linux/irqchip.h>
#if defined(CONFIG_PPC_I8259)
/*
@@ -265,31 +78,11 @@ static void __init xilinx_i8259_setup_cascade(void)
static inline void xilinx_i8259_setup_cascade(void) { return; }
#endif /* defined(CONFIG_PPC_I8259) */
-static const struct of_device_id xilinx_intc_match[] __initconst = {
- { .compatible = "xlnx,opb-intc-1.00.c", },
- { .compatible = "xlnx,xps-intc-1.00.a", },
- {}
-};
-
/*
* Initialize master Xilinx interrupt controller
*/
void __init xilinx_intc_init_tree(void)
{
- struct device_node *np;
-
- /* find top level interrupt controller */
- for_each_matching_node(np, xilinx_intc_match) {
- if (!of_get_property(np, "interrupts", NULL))
- break;
- }
- BUG_ON(!np);
-
- master_irqhost = xilinx_intc_init(np);
- BUG_ON(!master_irqhost);
-
- irq_set_default_host(master_irqhost);
- of_node_put(np);
-
+ irqchip_init();
xilinx_i8259_setup_cascade();
}
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 426481d4cc86..028f97be5bae 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -171,6 +171,7 @@ config S390
select SYSCTL_EXCEPTION_TRACE
select TTY
select VIRT_CPU_ACCOUNTING
+ select ARCH_HAS_SCALED_CPUTIME
select VIRT_TO_BUS
select HAVE_NMI
diff --git a/arch/s390/include/asm/mutex.h b/arch/s390/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/s390/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 602af692efdc..9d3a21aedc97 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -234,9 +234,10 @@ static inline unsigned short stap(void)
/*
* Give up the time slice of the virtual PU.
*/
-void cpu_relax(void);
+#define cpu_relax_yield cpu_relax_yield
+void cpu_relax_yield(void);
-#define cpu_relax_lowlatency() barrier()
+#define cpu_relax() barrier()
#define ECAG_CACHE_ATTRIBUTE 0
#define ECAG_CPU_ATTRIBUTE 1
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index 7e9e09f600fa..7ecd8902a5c3 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -23,6 +23,14 @@ _raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new)
return __sync_bool_compare_and_swap(lock, old, new);
}
+#ifndef CONFIG_SMP
+static inline bool arch_vcpu_is_preempted(int cpu) { return false; }
+#else
+bool arch_vcpu_is_preempted(int cpu);
+#endif
+
+#define vcpu_is_preempted arch_vcpu_is_preempted
+
/*
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index 15711de10403..853b2a3d8dee 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -104,12 +104,6 @@ static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
return __tlb_remove_page(tlb, page);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
- struct page *page)
-{
- return __tlb_remove_page(tlb, page);
-}
-
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
@@ -162,5 +156,13 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
#define tlb_remove_tlb_entry(tlb, ptep, addr) do { } while (0)
#define tlb_remove_pmd_tlb_entry(tlb, pmdp, addr) do { } while (0)
#define tlb_migrate_finish(mm) do { } while (0)
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+}
#endif /* _S390_TLB_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 41b51c2f4f1b..b24a64cbfeb1 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -96,4 +96,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 81d0808085e6..9e60ef144d03 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -53,7 +53,7 @@ void s390_update_cpu_mhz(void)
on_each_cpu(update_cpu_mhz, NULL, 0);
}
-void notrace cpu_relax(void)
+void notrace cpu_relax_yield(void)
{
if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) {
diag_stat_inc(DIAG_STAT_X044);
@@ -61,7 +61,7 @@ void notrace cpu_relax(void)
}
barrier();
}
-EXPORT_SYMBOL(cpu_relax);
+EXPORT_SYMBOL(cpu_relax_yield);
/*
* cpu_init - initializes state that is per-CPU.
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 35531fe1c5ea..df4a508ff35c 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -368,10 +368,15 @@ int smp_find_processor_id(u16 address)
return -1;
}
-int smp_vcpu_scheduled(int cpu)
+bool arch_vcpu_is_preempted(int cpu)
{
- return pcpu_running(pcpu_devices + cpu);
+ if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
+ return false;
+ if (pcpu_running(pcpu_devices + cpu))
+ return false;
+ return true;
}
+EXPORT_SYMBOL(arch_vcpu_is_preempted);
void smp_yield_cpu(int cpu)
{
@@ -1047,22 +1052,18 @@ static struct attribute_group cpu_online_attr_group = {
.attrs = cpu_online_attrs,
};
-static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
- void *hcpu)
+static int smp_cpu_online(unsigned int cpu)
{
- unsigned int cpu = (unsigned int)(long)hcpu;
struct device *s = &per_cpu(cpu_device, cpu)->dev;
- int err = 0;
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- err = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
- break;
- case CPU_DEAD:
- sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
- break;
- }
- return notifier_from_errno(err);
+ return sysfs_create_group(&s->kobj, &cpu_online_attr_group);
+}
+static int smp_cpu_pre_down(unsigned int cpu)
+{
+ struct device *s = &per_cpu(cpu_device, cpu)->dev;
+
+ sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
+ return 0;
}
static int smp_add_present_cpu(int cpu)
@@ -1083,20 +1084,12 @@ static int smp_add_present_cpu(int cpu)
rc = sysfs_create_group(&s->kobj, &cpu_common_attr_group);
if (rc)
goto out_cpu;
- if (cpu_online(cpu)) {
- rc = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
- if (rc)
- goto out_online;
- }
rc = topology_cpu_init(c);
if (rc)
goto out_topology;
return 0;
out_topology:
- if (cpu_online(cpu))
- sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
-out_online:
sysfs_remove_group(&s->kobj, &cpu_common_attr_group);
out_cpu:
#ifdef CONFIG_HOTPLUG_CPU
@@ -1149,17 +1142,15 @@ static int __init s390_smp_init(void)
if (rc)
return rc;
#endif
- cpu_notifier_register_begin();
for_each_present_cpu(cpu) {
rc = smp_add_present_cpu(cpu);
if (rc)
goto out;
}
- __hotcpu_notifier(smp_cpu_notify, 0);
-
+ rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "s390/smp:online",
+ smp_cpu_online, smp_cpu_pre_down);
out:
- cpu_notifier_register_done();
return rc;
}
subsys_initcall(s390_smp_init);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 856e30d8463f..1bd5dde2d5a9 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -137,8 +137,10 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
user_scaled = (user_scaled * mult) / div;
system_scaled = (system_scaled * mult) / div;
}
- account_user_time(tsk, user, user_scaled);
- account_system_time(tsk, hardirq_offset, system, system_scaled);
+ account_user_time(tsk, user);
+ tsk->utimescaled += user_scaled;
+ account_system_time(tsk, hardirq_offset, system);
+ tsk->stimescaled += system_scaled;
steal = S390_lowcore.steal_timer;
if ((s64) steal > 0) {
@@ -202,7 +204,8 @@ void vtime_account_irq_enter(struct task_struct *tsk)
system_scaled = (system_scaled * mult) / div;
}
- account_system_time(tsk, 0, system, system_scaled);
+ account_system_time(tsk, 0, system);
+ tsk->stimescaled += system_scaled;
virt_timer_forward(system);
}
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index e5f50a7d2f4e..e48a48ec24bc 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -37,15 +37,6 @@ static inline void _raw_compare_and_delay(unsigned int *lock, unsigned int old)
asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock));
}
-static inline int cpu_is_preempted(int cpu)
-{
- if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
- return 0;
- if (smp_vcpu_scheduled(cpu))
- return 0;
- return 1;
-}
-
void arch_spin_lock_wait(arch_spinlock_t *lp)
{
unsigned int cpu = SPINLOCK_LOCKVAL;
@@ -62,7 +53,7 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
continue;
}
/* First iteration: check if the lock owner is running. */
- if (first_diag && cpu_is_preempted(~owner)) {
+ if (first_diag && arch_vcpu_is_preempted(~owner)) {
smp_yield_cpu(~owner);
first_diag = 0;
continue;
@@ -81,7 +72,7 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
* yield the CPU unconditionally. For LPAR rely on the
* sense running status.
*/
- if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) {
+ if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(~owner)) {
smp_yield_cpu(~owner);
first_diag = 0;
}
@@ -108,7 +99,7 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
continue;
}
/* Check if the lock owner is running. */
- if (first_diag && cpu_is_preempted(~owner)) {
+ if (first_diag && arch_vcpu_is_preempted(~owner)) {
smp_yield_cpu(~owner);
first_diag = 0;
continue;
@@ -127,7 +118,7 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
* yield the CPU unconditionally. For LPAR rely on the
* sense running status.
*/
- if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) {
+ if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(~owner)) {
smp_yield_cpu(~owner);
first_diag = 0;
}
@@ -165,7 +156,7 @@ void _raw_read_lock_wait(arch_rwlock_t *rw)
owner = 0;
while (1) {
if (count-- <= 0) {
- if (owner && cpu_is_preempted(~owner))
+ if (owner && arch_vcpu_is_preempted(~owner))
smp_yield_cpu(~owner);
count = spin_retry;
}
@@ -211,7 +202,7 @@ void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev)
owner = 0;
while (1) {
if (count-- <= 0) {
- if (owner && cpu_is_preempted(~owner))
+ if (owner && arch_vcpu_is_preempted(~owner))
smp_yield_cpu(~owner);
count = spin_retry;
}
@@ -241,7 +232,7 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
owner = 0;
while (1) {
if (count-- <= 0) {
- if (owner && cpu_is_preempted(~owner))
+ if (owner && arch_vcpu_is_preempted(~owner))
smp_yield_cpu(~owner);
count = spin_retry;
}
@@ -285,7 +276,7 @@ void arch_lock_relax(unsigned int cpu)
{
if (!cpu)
return;
- if (MACHINE_IS_LPAR && !cpu_is_preempted(~cpu))
+ if (MACHINE_IS_LPAR && !arch_vcpu_is_preempted(~cpu))
return;
smp_yield_cpu(~cpu);
}
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 3ba622702ce4..ec1f0dedb948 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -1015,7 +1015,7 @@ static inline void gmap_insert_rmap(struct gmap *sg, unsigned long vmaddr,
if (slot) {
rmap->next = radix_tree_deref_slot_protected(slot,
&sg->guest_table_lock);
- radix_tree_replace_slot(slot, rmap);
+ radix_tree_replace_slot(&sg->host_to_rmap, slot, rmap);
} else {
rmap->next = NULL;
radix_tree_insert(&sg->host_to_rmap, vmaddr >> PAGE_SHIFT,
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index bee281f3163d..167b31b186c1 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -981,7 +981,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
EMIT2(0x0d00, REG_14, REG_W1);
/* lgr %b0,%r2: load return value into %b0 */
EMIT4(0xb9040000, BPF_REG_0, REG_2);
- if (bpf_helper_changes_skb_data((void *)func)) {
+ if (bpf_helper_changes_pkt_data((void *)func)) {
jit->seen |= SEEN_SKB_CHANGE;
/* lg %b1,ST_OFF_SKBP(%r15) */
EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
diff --git a/arch/score/include/asm/mutex.h b/arch/score/include/asm/mutex.h
deleted file mode 100644
index 10d48fe4db97..000000000000
--- a/arch/score/include/asm/mutex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_MUTEX_H
-#define _ASM_SCORE_MUTEX_H
-
-#include <asm-generic/mutex-dec.h>
-
-#endif /* _ASM_SCORE_MUTEX_H */
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h
index 851f441991d2..d9a922d8711b 100644
--- a/arch/score/include/asm/processor.h
+++ b/arch/score/include/asm/processor.h
@@ -24,7 +24,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#define release_thread(thread) do {} while (0)
/*
diff --git a/arch/sh/include/asm/mutex-llsc.h b/arch/sh/include/asm/mutex-llsc.h
deleted file mode 100644
index dad29b687bd3..000000000000
--- a/arch/sh/include/asm/mutex-llsc.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * arch/sh/include/asm/mutex-llsc.h
- *
- * SH-4A optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef __ASM_SH_MUTEX_LLSC_H
-#define __ASM_SH_MUTEX_LLSC_H
-
-/*
- * Attempting to lock a mutex on SH4A is done like in ARMv6+ architecure.
- * with a bastardized atomic decrement (it is not a reliable atomic decrement
- * but it satisfies the defined semantics for our purpose, while being
- * smaller and faster than a real atomic decrement or atomic swap.
- * The idea is to attempt decrementing the lock value only once. If once
- * decremented it isn't zero, or if its store-back fails due to a dispute
- * on the exclusive store, we simply bail out immediately through the slow
- * path where the lock will be reattempted until it succeeds.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- int __done, __res;
-
- __asm__ __volatile__ (
- "movli.l @%2, %0 \n"
- "add #-1, %0 \n"
- "movco.l %0, @%2 \n"
- "movt %1 \n"
- : "=&z" (__res), "=&r" (__done)
- : "r" (&(count)->counter)
- : "t");
-
- if (unlikely(!__done || __res != 0))
- fail_fn(count);
-}
-
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
- int __done, __res;
-
- __asm__ __volatile__ (
- "movli.l @%2, %0 \n"
- "add #-1, %0 \n"
- "movco.l %0, @%2 \n"
- "movt %1 \n"
- : "=&z" (__res), "=&r" (__done)
- : "r" (&(count)->counter)
- : "t");
-
- if (unlikely(!__done || __res != 0))
- __res = -1;
-
- return __res;
-}
-
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- int __done, __res;
-
- __asm__ __volatile__ (
- "movli.l @%2, %0 \n\t"
- "add #1, %0 \n\t"
- "movco.l %0, @%2 \n\t"
- "movt %1 \n\t"
- : "=&z" (__res), "=&r" (__done)
- : "r" (&(count)->counter)
- : "t");
-
- if (unlikely(!__done || __res <= 0))
- fail_fn(count);
-}
-
-/*
- * If the unlock was done on a contended lock, or if the unlock simply fails
- * then the mutex remains locked.
- */
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/*
- * For __mutex_fastpath_trylock we do an atomic decrement and check the
- * result and put it in the __res variable.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- int __res, __orig;
-
- __asm__ __volatile__ (
- "1: movli.l @%2, %0 \n\t"
- "dt %0 \n\t"
- "movco.l %0,@%2 \n\t"
- "bf 1b \n\t"
- "cmp/eq #0,%0 \n\t"
- "bt 2f \n\t"
- "mov #0, %1 \n\t"
- "bf 3f \n\t"
- "2: mov #1, %1 \n\t"
- "3: "
- : "=&z" (__orig), "=&r" (__res)
- : "r" (&count->counter)
- : "t");
-
- return __res;
-}
-#endif /* __ASM_SH_MUTEX_LLSC_H */
diff --git a/arch/sh/include/asm/mutex.h b/arch/sh/include/asm/mutex.h
deleted file mode 100644
index d8e37716a4a0..000000000000
--- a/arch/sh/include/asm/mutex.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-#if defined(CONFIG_CPU_SH4A)
-#include <asm/mutex-llsc.h>
-#else
-#include <asm-generic/mutex-dec.h>
-#endif
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index f9a09942a32d..5addd69f70ef 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -97,7 +97,6 @@ extern struct sh_cpuinfo cpu_data[];
#define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory")
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
void default_idle(void);
void stop_this_cpu(void *);
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h
index 025cdb1032f6..46e0d635e36f 100644
--- a/arch/sh/include/asm/tlb.h
+++ b/arch/sh/include/asm/tlb.h
@@ -65,6 +65,9 @@ tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address)
tlb->end = address + PAGE_SIZE;
}
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ tlb_remove_tlb_entry(tlb, ptep, address)
+
/*
* In the case of tlb vma handling, we can optimise these away in the
* case where we're doing a full MM flush. When we're doing a munmap,
@@ -115,18 +118,18 @@ static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
return __tlb_remove_page(tlb, page);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
- struct page *page)
-{
- return __tlb_remove_page(tlb, page);
-}
-
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
return tlb_remove_page(tlb, page);
}
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+}
+
#define pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep)
#define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp)
#define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp)
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 165ecdd24d22..cf4034c66362 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -155,6 +155,9 @@ config PGTABLE_LEVELS
default 4 if 64BIT
default 3
+config ARCH_SUPPORTS_UPROBES
+ def_bool y if SPARC64
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 3583d676a916..b2e650d1764f 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -213,6 +213,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_UPROBE_EVENTS=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..0569bfac4afb 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -15,7 +15,6 @@ generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += module.h
-generic-y += mutex.h
generic-y += preempt.h
generic-y += rwsem.h
generic-y += serial.h
diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h
index 04465de8f3b5..867286bf7b1a 100644
--- a/arch/sparc/include/asm/kdebug_64.h
+++ b/arch/sparc/include/asm/kdebug_64.h
@@ -10,6 +10,8 @@ enum die_val {
DIE_OOPS = 1,
DIE_DEBUG, /* ta 0x70 */
DIE_DEBUG_2, /* ta 0x71 */
+ DIE_BPT, /* ta 0x73 */
+ DIE_SSTEP, /* ta 0x74 */
DIE_DIE,
DIE_TRAP,
DIE_TRAP_TL1,
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1fb317fbc0b3..314b66851348 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -826,7 +826,7 @@ static inline unsigned long __pmd_page(pmd_t pmd)
#define pgd_page_vaddr(pgd) \
((unsigned long) __va(pgd_val(pgd)))
#define pgd_present(pgd) (pgd_val(pgd) != 0U)
-#define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL)
+#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0UL)
static inline unsigned long pud_large(pud_t pud)
{
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index 812fd08f3e62..365d4cb267b4 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -119,7 +119,6 @@ extern struct task_struct *last_task_used_math;
int do_mathemu(struct pt_regs *regs, struct task_struct *fpt);
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
extern void (*sparc_idle)(void);
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index ce2595c89471..6448cfc8292f 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -216,7 +216,6 @@ unsigned long get_wchan(struct task_struct *task);
"nop\n\t" \
".previous" \
::: "memory")
-#define cpu_relax_lowlatency() cpu_relax()
/* Prefetch support. This is tuned for UltraSPARC-III and later.
* UltraSPARC-I will treat these as nops, and UltraSPARC-II has
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index bac6a946ee00..ca57f08bd3db 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -61,7 +61,10 @@ extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
#define force_successful_syscall_return() set_thread_noerror(1)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
-#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
+#define instruction_pointer_set(regs, val) do { \
+ (regs)->tpc = (val); \
+ (regs)->tnpc = (val)+4; \
+ } while (0)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
static inline int is_syscall_success(struct pt_regs *regs)
{
@@ -77,6 +80,36 @@ unsigned long profile_pc(struct pt_regs *);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif
+
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic))
+
+extern int regs_query_register_offset(const char *name);
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs: pt_regs from which register value is gotten
+ * @offset: offset number of the register.
+ *
+ * regs_get_register returns the value of a register whose
+ * offset from @regs. The @offset is the offset of the register
+ * in struct pt_regs. If @offset is bigger than MAX_REG_OFFSET,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned long offset)
+{
+ if (unlikely(offset >= MAX_REG_OFFSET))
+ return 0;
+ if (offset == PT_V9_Y)
+ return *(unsigned int *)((unsigned long)regs + offset);
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/* Valid only for Kernel mode traps. */
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+ return regs->u_regs[UREG_I6];
+}
#else /* __ASSEMBLY__ */
#endif /* __ASSEMBLY__ */
#else /* (defined(__sparc__) && defined(__arch64__)) */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 3d7b925f6516..38a24f257b85 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -180,7 +180,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
/* flag bit 4 is available */
#define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */
-/* flag bit 6 is available */
+#define TIF_UPROBE 6 /* breakpointed or singlestepped */
#define TIF_32BIT 7 /* 32-bit binary */
#define TIF_NOHZ 8 /* in adaptive nohz mode */
#define TIF_SECCOMP 9 /* secure computing */
@@ -199,6 +199,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_UNALIGNED (1<<TIF_UNALIGNED)
+#define _TIF_UPROBE (1<<TIF_UPROBE)
#define _TIF_32BIT (1<<TIF_32BIT)
#define _TIF_NOHZ (1<<TIF_NOHZ)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
@@ -209,7 +210,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \
_TIF_DO_NOTIFY_RESUME_MASK | \
_TIF_NEED_RESCHED)
-#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
+#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
+ _TIF_SIGPENDING | _TIF_UPROBE)
#define is_32bit_task() (test_thread_flag(TIF_32BIT))
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
index 7b4898a36eee..225543000122 100644
--- a/arch/sparc/include/asm/topology_64.h
+++ b/arch/sparc/include/asm/topology_64.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_NUMA
#include <asm/mmzone.h>
+#include <asm/cpudata.h>
static inline int cpu_to_node(int cpu)
{
diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
index 781b9f1dbdc2..82e7df296abc 100644
--- a/arch/sparc/include/asm/ttable.h
+++ b/arch/sparc/include/asm/ttable.h
@@ -186,6 +186,12 @@
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
#endif
+#ifdef CONFIG_UPROBES
+#define UPROBES_TRAP(lvl) TRAP_ARG(uprobe_trap, lvl)
+#else
+#define UPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
#ifdef CONFIG_KGDB
#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
#else
diff --git a/arch/sparc/include/asm/uprobes.h b/arch/sparc/include/asm/uprobes.h
new file mode 100644
index 000000000000..f87aae5a908e
--- /dev/null
+++ b/arch/sparc/include/asm/uprobes.h
@@ -0,0 +1,59 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for sparc
+ *
+ * Copyright (C) 2013 Oracle, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Jose E. Marchesi <jose.marchesi@oracle.com>
+ * Eric Saint Etienne <eric.saint.etienne@oracle.com>
+ */
+
+typedef u32 uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES 4
+#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES * 2)
+
+#define UPROBE_SWBP_INSN_SIZE 4
+#define UPROBE_SWBP_INSN 0x91d02073 /* ta 0x73 */
+#define UPROBE_STP_INSN 0x91d02074 /* ta 0x74 */
+
+#define ANNUL_BIT (1 << 29)
+
+struct arch_uprobe {
+ union {
+ u8 insn[MAX_UINSN_BYTES];
+ u32 ixol;
+ };
+};
+
+struct arch_uprobe_task {
+ u32 saved_tpc;
+ u32 saved_tnpc;
+};
+
+struct task_struct;
+struct notifier_block;
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+
+#endif /* _ASM_UPROBES_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 31aede3af088..a25dc32f5d6a 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -86,6 +86,8 @@
#define SO_CNX_ADVICE 0x0037
+#define SCM_TIMESTAMPING_OPT_STATS 0x0038
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index fa3c02d41138..aac609889ee4 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -116,4 +116,5 @@ obj-$(CONFIG_COMPAT) += $(audit--y)
pc--$(CONFIG_PERF_EVENTS) := perf_event.o
obj-$(CONFIG_SPARC64) += $(pc--y)
+obj-$(CONFIG_UPROBES) += uprobes.o
obj-$(CONFIG_SPARC64) += jump_label.o
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 33cd171d933e..afcdd5e4f43f 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -349,37 +349,37 @@ void __init leon_init_timers(void)
/* Find GPTIMER Timer Registers base address otherwise bail out. */
nnp = rootnp;
- do {
- np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
- if (!np) {
- np = of_find_node_by_name(nnp, "01_011");
- if (!np)
- goto bad;
- }
- ampopts = 0;
- pp = of_find_property(np, "ampopts", &len);
- if (pp) {
- ampopts = *(int *)pp->value;
- if (ampopts == 0) {
- /* Skip this instance, resource already
- * allocated by other OS */
- nnp = np;
- continue;
- }
+retry:
+ np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
+ if (!np) {
+ np = of_find_node_by_name(nnp, "01_011");
+ if (!np)
+ goto bad;
+ }
+
+ ampopts = 0;
+ pp = of_find_property(np, "ampopts", &len);
+ if (pp) {
+ ampopts = *(int *)pp->value;
+ if (ampopts == 0) {
+ /* Skip this instance, resource already
+ * allocated by other OS */
+ nnp = np;
+ goto retry;
}
+ }
+
+ /* Select Timer-Instance on Timer Core. Default is zero */
+ leon3_gptimer_idx = ampopts & 0x7;
- /* Select Timer-Instance on Timer Core. Default is zero */
- leon3_gptimer_idx = ampopts & 0x7;
-
- pp = of_find_property(np, "reg", &len);
- if (pp)
- leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
- pp->value;
- pp = of_find_property(np, "interrupts", &len);
- if (pp)
- leon3_gptimer_irq = *(unsigned int *)pp->value;
- } while (0);
+ pp = of_find_property(np, "reg", &len);
+ if (pp)
+ leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
+ pp->value;
+ pp = of_find_property(np, "interrupts", &len);
+ if (pp)
+ leon3_gptimer_irq = *(unsigned int *)pp->value;
if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
goto bad;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 06981cc716b6..f4daccd12bf5 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -242,6 +242,7 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
return ret;
iommu_map_fail:
+ local_irq_restore(flags);
iommu_tbl_range_free(tbl, *dma_addrp, npages, IOMMU_ERROR_CODE);
range_alloc_fail:
@@ -414,6 +415,7 @@ bad:
return DMA_ERROR_CODE;
iommu_map_fail:
+ local_irq_restore(flags);
iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
return DMA_ERROR_CODE;
}
@@ -478,11 +480,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
- atu = iommu->atu;
-
if (nelems == 0 || !iommu)
return 0;
-
+ atu = iommu->atu;
+
prot = HV_PCI_MAP_ATTR_READ;
if (direction != DMA_TO_DEVICE)
prot |= HV_PCI_MAP_ATTR_WRITE;
diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c
index 1836cb965ff8..4b60f385c98f 100644
--- a/arch/sparc/kernel/power.c
+++ b/arch/sparc/kernel/power.c
@@ -67,9 +67,4 @@ static struct platform_driver power_driver = {
},
};
-static int __init power_init(void)
-{
- return platform_driver_register(&power_driver);
-}
-
-device_initcall(power_init);
+builtin_platform_driver(power_driver);
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index ac082dd8c67d..96494b2ef41f 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -46,6 +46,43 @@
/* #define ALLOW_INIT_TRACING */
+struct pt_regs_offset {
+ const char *name;
+ int offset;
+};
+
+#define REG_OFFSET_NAME(n, r) \
+ {.name = n, .offset = (PT_V9_##r)}
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+static const struct pt_regs_offset regoffset_table[] = {
+ REG_OFFSET_NAME("g0", G0),
+ REG_OFFSET_NAME("g1", G1),
+ REG_OFFSET_NAME("g2", G2),
+ REG_OFFSET_NAME("g3", G3),
+ REG_OFFSET_NAME("g4", G4),
+ REG_OFFSET_NAME("g5", G5),
+ REG_OFFSET_NAME("g6", G6),
+ REG_OFFSET_NAME("g7", G7),
+
+ REG_OFFSET_NAME("i0", I0),
+ REG_OFFSET_NAME("i1", I1),
+ REG_OFFSET_NAME("i2", I2),
+ REG_OFFSET_NAME("i3", I3),
+ REG_OFFSET_NAME("i4", I4),
+ REG_OFFSET_NAME("i5", I5),
+ REG_OFFSET_NAME("i6", I6),
+ REG_OFFSET_NAME("i7", I7),
+
+ REG_OFFSET_NAME("tstate", TSTATE),
+ REG_OFFSET_NAME("pc", TPC),
+ REG_OFFSET_NAME("npc", TNPC),
+ REG_OFFSET_NAME("y", Y),
+ REG_OFFSET_NAME("lr", I7),
+
+ REG_OFFSET_END,
+};
+
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -1107,3 +1144,20 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
if (test_thread_flag(TIF_NOHZ))
user_enter();
}
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name: the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+ const struct pt_regs_offset *roff;
+
+ for (roff = regoffset_table; roff->name != NULL; roff++)
+ if (!strcmp(roff->name, name))
+ return roff->offset;
+ return -EINVAL;
+}
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 5ee930c48f4c..c782c9b716db 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -545,6 +545,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
{
user_exit();
+ if (thread_info_flags & _TIF_UPROBE)
+ uprobe_notify_resume(regs);
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, orig_i0);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c
index fa8e21abb5e0..4808b6d23455 100644
--- a/arch/sparc/kernel/sysfs.c
+++ b/arch/sparc/kernel/sysfs.c
@@ -221,7 +221,7 @@ static struct device_attribute cpu_core_attrs[] = {
static DEFINE_PER_CPU(struct cpu, cpu_devices);
-static void register_cpu_online(unsigned int cpu)
+static int register_cpu_online(unsigned int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct device *s = &c->dev;
@@ -231,11 +231,12 @@ static void register_cpu_online(unsigned int cpu)
device_create_file(s, &cpu_core_attrs[i]);
register_mmu_stats(s);
+ return 0;
}
-#ifdef CONFIG_HOTPLUG_CPU
-static void unregister_cpu_online(unsigned int cpu)
+static int unregister_cpu_online(unsigned int cpu)
{
+#ifdef CONFIG_HOTPLUG_CPU
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct device *s = &c->dev;
int i;
@@ -243,33 +244,10 @@ static void unregister_cpu_online(unsigned int cpu)
unregister_mmu_stats(s);
for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
device_remove_file(s, &cpu_core_attrs[i]);
-}
-#endif
-
-static int sysfs_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned int)(long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- register_cpu_online(cpu);
- break;
-#ifdef CONFIG_HOTPLUG_CPU
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- unregister_cpu_online(cpu);
- break;
#endif
- }
- return NOTIFY_OK;
+ return 0;
}
-static struct notifier_block sysfs_cpu_nb = {
- .notifier_call = sysfs_cpu_notify,
-};
-
static void __init check_mmu_stats(void)
{
unsigned long dummy1, err;
@@ -294,26 +272,21 @@ static void register_nodes(void)
static int __init topology_init(void)
{
- int cpu;
+ int cpu, ret;
register_nodes();
check_mmu_stats();
- cpu_notifier_register_begin();
-
for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
register_cpu(c, cpu);
- if (cpu_online(cpu))
- register_cpu_online(cpu);
}
- __register_cpu_notifier(&sysfs_cpu_nb);
-
- cpu_notifier_register_done();
-
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online",
+ register_cpu_online, unregister_cpu_online);
+ WARN_ON(ret < 0);
return 0;
}
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 4094a51b1970..496fa926e1e0 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -85,7 +85,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
void bad_trap(struct pt_regs *regs, long lvl)
{
- char buffer[32];
+ char buffer[36];
siginfo_t info;
if (notify_die(DIE_TRAP, "bad trap", regs,
@@ -116,7 +116,7 @@ void bad_trap(struct pt_regs *regs, long lvl)
void bad_trap_tl1(struct pt_regs *regs, long lvl)
{
- char buffer[32];
+ char buffer[36];
if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
0, lvl, SIGTRAP) == NOTIFY_STOP)
diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S
index c6dfdaa29e20..7bd8f6556352 100644
--- a/arch/sparc/kernel/ttable_64.S
+++ b/arch/sparc/kernel/ttable_64.S
@@ -165,7 +165,7 @@ tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
tl0_linux64: LINUX_64BIT_SYSCALL_TRAP
tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context)
tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) KGDB_TRAP(0x172)
-tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
+tl0_resv173: UPROBES_TRAP(0x173) UPROBES_TRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
diff --git a/arch/sparc/kernel/uprobes.c b/arch/sparc/kernel/uprobes.c
new file mode 100644
index 000000000000..b68314050602
--- /dev/null
+++ b/arch/sparc/kernel/uprobes.c
@@ -0,0 +1,331 @@
+/*
+ * User-space Probes (UProbes) for sparc
+ *
+ * Copyright (C) 2013 Oracle 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Jose E. Marchesi <jose.marchesi@oracle.com>
+ * Eric Saint Etienne <eric.saint.etienne@oracle.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h> /* For struct task_struct */
+#include <linux/kdebug.h>
+
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+
+/* Compute the address of the breakpoint instruction and return it.
+ *
+ * Note that uprobe_get_swbp_addr is defined as a weak symbol in
+ * kernel/events/uprobe.c.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+ return instruction_pointer(regs);
+}
+
+static void copy_to_page(struct page *page, unsigned long vaddr,
+ const void *src, int len)
+{
+ void *kaddr = kmap_atomic(page);
+
+ memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
+ kunmap_atomic(kaddr);
+}
+
+/* Fill in the xol area with the probed instruction followed by the
+ * single-step trap. Some fixups in the copied instruction are
+ * performed at this point.
+ *
+ * Note that uprobe_xol_copy is defined as a weak symbol in
+ * kernel/events/uprobe.c.
+ */
+void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+ void *src, unsigned long len)
+{
+ const u32 stp_insn = UPROBE_STP_INSN;
+ u32 insn = *(u32 *) src;
+
+ /* Branches annulling their delay slot must be fixed to not do
+ * so. Clearing the annul bit on these instructions we can be
+ * sure the single-step breakpoint in the XOL slot will be
+ * executed.
+ */
+
+ u32 op = (insn >> 30) & 0x3;
+ u32 op2 = (insn >> 22) & 0x7;
+
+ if (op == 0 &&
+ (op2 == 1 || op2 == 2 || op2 == 3 || op2 == 5 || op2 == 6) &&
+ (insn & ANNUL_BIT) == ANNUL_BIT)
+ insn &= ~ANNUL_BIT;
+
+ copy_to_page(page, vaddr, &insn, len);
+ copy_to_page(page, vaddr+len, &stp_insn, 4);
+}
+
+
+/* Instruction analysis/validity.
+ *
+ * This function returns 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
+ struct mm_struct *mm, unsigned long addr)
+{
+ /* Any unsupported instruction? Then return -EINVAL */
+ return 0;
+}
+
+/* If INSN is a relative control transfer instruction, return the
+ * corrected branch destination value.
+ *
+ * Note that regs->tpc and regs->tnpc still hold the values of the
+ * program counters at the time of the single-step trap due to the
+ * execution of the UPROBE_STP_INSN at utask->xol_vaddr + 4.
+ *
+ */
+static unsigned long relbranch_fixup(u32 insn, struct uprobe_task *utask,
+ struct pt_regs *regs)
+{
+ /* Branch not taken, no mods necessary. */
+ if (regs->tnpc == regs->tpc + 0x4UL)
+ return utask->autask.saved_tnpc + 0x4UL;
+
+ /* The three cases are call, branch w/prediction,
+ * and traditional branch.
+ */
+ if ((insn & 0xc0000000) == 0x40000000 ||
+ (insn & 0xc1c00000) == 0x00400000 ||
+ (insn & 0xc1c00000) == 0x00800000) {
+ unsigned long real_pc = (unsigned long) utask->vaddr;
+ unsigned long ixol_addr = utask->xol_vaddr;
+
+ /* The instruction did all the work for us
+ * already, just apply the offset to the correct
+ * instruction location.
+ */
+ return (real_pc + (regs->tnpc - ixol_addr));
+ }
+
+ /* It is jmpl or some other absolute PC modification instruction,
+ * leave NPC as-is.
+ */
+ return regs->tnpc;
+}
+
+/* If INSN is an instruction which writes its PC location
+ * into a destination register, fix that up.
+ */
+static int retpc_fixup(struct pt_regs *regs, u32 insn,
+ unsigned long real_pc)
+{
+ unsigned long *slot = NULL;
+ int rc = 0;
+
+ /* Simplest case is 'call', which always uses %o7 */
+ if ((insn & 0xc0000000) == 0x40000000)
+ slot = &regs->u_regs[UREG_I7];
+
+ /* 'jmpl' encodes the register inside of the opcode */
+ if ((insn & 0xc1f80000) == 0x81c00000) {
+ unsigned long rd = ((insn >> 25) & 0x1f);
+
+ if (rd <= 15) {
+ slot = &regs->u_regs[rd];
+ } else {
+ unsigned long fp = regs->u_regs[UREG_FP];
+ /* Hard case, it goes onto the stack. */
+ flushw_all();
+
+ rd -= 16;
+ if (test_thread_64bit_stack(fp)) {
+ unsigned long __user *uslot =
+ (unsigned long __user *) (fp + STACK_BIAS) + rd;
+ rc = __put_user(real_pc, uslot);
+ } else {
+ unsigned int __user *uslot = (unsigned int
+ __user *) fp + rd;
+ rc = __put_user((u32) real_pc, uslot);
+ }
+ }
+ }
+ if (slot != NULL)
+ *slot = real_pc;
+ return rc;
+}
+
+/* Single-stepping can be avoided for certain instructions: NOPs and
+ * instructions that can be emulated. This function determines
+ * whether the instruction where the uprobe is installed falls in one
+ * of these cases and emulates it.
+ *
+ * This function returns true if the single-stepping can be skipped,
+ * false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ /* We currently only emulate NOP instructions.
+ */
+
+ if (auprobe->ixol == (1 << 24)) {
+ regs->tnpc += 4;
+ regs->tpc += 4;
+ return true;
+ }
+
+ return false;
+}
+
+/* Prepare to execute out of line. At this point
+ * current->utask->xol_vaddr points to an allocated XOL slot properly
+ * initialized with the original instruction and the single-stepping
+ * trap instruction.
+ *
+ * This function returns 0 on success, any other number on error.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+ struct arch_uprobe_task *autask = &current->utask->autask;
+
+ /* Save the current program counters so they can be restored
+ * later.
+ */
+ autask->saved_tpc = regs->tpc;
+ autask->saved_tnpc = regs->tnpc;
+
+ /* Adjust PC and NPC so the first instruction in the XOL slot
+ * will be executed by the user task.
+ */
+ instruction_pointer_set(regs, utask->xol_vaddr);
+
+ return 0;
+}
+
+/* Prepare to resume execution after the single-step. Called after
+ * single-stepping. To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.
+ *
+ * This function returns 0 on success, any other number on error.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+ struct arch_uprobe_task *autask = &utask->autask;
+ u32 insn = auprobe->ixol;
+ int rc = 0;
+
+ if (utask->state == UTASK_SSTEP_ACK) {
+ regs->tnpc = relbranch_fixup(insn, utask, regs);
+ regs->tpc = autask->saved_tnpc;
+ rc = retpc_fixup(regs, insn, (unsigned long) utask->vaddr);
+ } else {
+ regs->tnpc = utask->vaddr+4;
+ regs->tpc = autask->saved_tnpc+4;
+ }
+ return rc;
+}
+
+/* Handler for uprobe traps. This is called from the traps table and
+ * triggers the proper die notification.
+ */
+asmlinkage void uprobe_trap(struct pt_regs *regs,
+ unsigned long trap_level)
+{
+ BUG_ON(trap_level != 0x173 && trap_level != 0x174);
+
+ /* We are only interested in user-mode code. Uprobe traps
+ * shall not be present in kernel code.
+ */
+ if (!user_mode(regs)) {
+ local_irq_enable();
+ bad_trap(regs, trap_level);
+ return;
+ }
+
+ /* trap_level == 0x173 --> ta 0x73
+ * trap_level == 0x174 --> ta 0x74
+ */
+ if (notify_die((trap_level == 0x173) ? DIE_BPT : DIE_SSTEP,
+ (trap_level == 0x173) ? "bpt" : "sstep",
+ regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
+ bad_trap(regs, trap_level);
+}
+
+/* Callback routine for handling die notifications.
+*/
+int arch_uprobe_exception_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ int ret = NOTIFY_DONE;
+ struct die_args *args = (struct die_args *)data;
+
+ /* We are only interested in userspace traps */
+ if (args->regs && !user_mode(args->regs))
+ return NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BPT:
+ if (uprobe_pre_sstep_notifier(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+
+ case DIE_SSTEP:
+ if (uprobe_post_sstep_notifier(args->regs))
+ ret = NOTIFY_STOP;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/* This function gets called when a XOL instruction either gets
+ * trapped or the thread has a fatal signal, so reset the instruction
+ * pointer to its probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ instruction_pointer_set(regs, utask->vaddr);
+}
+
+/* If xol insn itself traps and generates a signal(Say,
+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
+ * instruction jumps back to its own address.
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+ return false;
+}
+
+unsigned long
+arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
+ struct pt_regs *regs)
+{
+ unsigned long orig_ret_vaddr = regs->u_regs[UREG_I7];
+
+ regs->u_regs[UREG_I7] = trampoline_vaddr-8;
+
+ return orig_ret_vaddr + 8;
+}
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..2d1f5638974c 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -21,7 +21,6 @@ generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
generic-y += msgbuf.h
-generic-y += mutex.h
generic-y += param.h
generic-y += parport.h
generic-y += poll.h
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 0684e88aacd8..0bc9968b97a1 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -264,8 +264,6 @@ static inline void cpu_relax(void)
barrier();
}
-#define cpu_relax_lowlatency() cpu_relax()
-
/* Info on this processor (see fs/proc/cpuinfo.c) */
struct seq_operations;
extern const struct seq_operations cpuinfo_op;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 2cd5b6874c7b..1669240c7a25 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -256,13 +256,6 @@ static void uml_net_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
-{
- dev->mtu = new_mtu;
-
- return 0;
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void uml_net_poll_controller(struct net_device *dev)
{
@@ -374,7 +367,6 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_set_rx_mode = uml_net_set_multicast_list,
.ndo_tx_timeout = uml_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = uml_net_change_mtu,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = uml_net_poll_controller,
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..052f7f6d0551 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -17,7 +17,6 @@ generic-y += irq_work.h
generic-y += kdebug.h
generic-y += mcs_spinlock.h
generic-y += mm-arch-hooks.h
-generic-y += mutex.h
generic-y += param.h
generic-y += pci.h
generic-y += percpu.h
diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h
index 821ff0acfe17..600a2e9bfee2 100644
--- a/arch/um/include/asm/tlb.h
+++ b/arch/um/include/asm/tlb.h
@@ -116,12 +116,6 @@ static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
return __tlb_remove_page(tlb, page);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
- struct page *page)
-{
- return __tlb_remove_page(tlb, page);
-}
-
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
@@ -141,6 +135,15 @@ static inline void tlb_remove_page_size(struct mmu_gather *tlb,
__tlb_remove_tlb_entry(tlb, ptep, address); \
} while (0)
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
+{
+}
+
#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
#define pud_free_tlb(tlb, pudp, addr) __pud_free_tlb(tlb, pudp, addr)
diff --git a/arch/unicore32/include/asm/mutex.h b/arch/unicore32/include/asm/mutex.h
deleted file mode 100644
index fab7d0e8adf6..000000000000
--- a/arch/unicore32/include/asm/mutex.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/mutex.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- *
- * UniCore optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef __UNICORE_MUTEX_H__
-#define __UNICORE_MUTEX_H__
-
-# include <asm-generic/mutex-xchg.h>
-#endif
diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h
index 8d21b7adf26b..4eaa42167667 100644
--- a/arch/unicore32/include/asm/processor.h
+++ b/arch/unicore32/include/asm/processor.h
@@ -71,7 +71,6 @@ extern void release_thread(struct task_struct *);
unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bada636d1065..dd47e60aabf5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -9,28 +9,50 @@ config 64BIT
config X86_32
def_bool y
depends on !64BIT
+ # Options that are inherently 32-bit kernel only:
+ select ARCH_WANT_IPC_PARSE_VERSION
+ select CLKSRC_I8253
+ select CLONE_BACKWARDS
+ select HAVE_AOUT
+ select HAVE_GENERIC_DMA_COHERENT
+ select MODULES_USE_ELF_REL
+ select OLD_SIGACTION
config X86_64
def_bool y
depends on 64BIT
+ # Options that are inherently 64-bit kernel only:
+ select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_SUPPORTS_INT128
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select HAVE_ARCH_SOFT_DIRTY
+ select MODULES_USE_ELF_RELA
+ select X86_DEV_DMA_OPS
-### Arch settings
+#
+# Arch settings
+#
+# ( Note that options that are marked 'if X86_64' could in principle be
+# ported to 32-bit as well. )
+#
config X86
def_bool y
+ #
+ # Note: keep this list sorted alphabetically
+ #
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ANON_INODES
select ARCH_CLOCKSOURCE_DATA
select ARCH_DISCARD_MEMBLOCK
- select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
+ select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_GCOV_PROFILE_ALL
- select ARCH_HAS_GIGANTIC_PAGE if X86_64
select ARCH_HAS_KCOV if X86_64
- select ARCH_HAS_PMEM_API if X86_64
select ARCH_HAS_MMIO_FLUSH
+ select ARCH_HAS_PMEM_API if X86_64
select ARCH_HAS_SG_CHAIN
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -39,23 +61,17 @@ config X86
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
- select ARCH_SUPPORTS_INT128 if X86_64
select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
select ARCH_USE_BUILTIN_BSWAP
- select ARCH_USE_CMPXCHG_LOCKREF if X86_64
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if SMP
- select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_WANT_FRAME_POINTERS
- select ARCH_WANT_IPC_PARSE_VERSION if X86_32
+ select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select BUILDTIME_EXTABLE_SORT
select CLKEVT_I8253
- select CLKSRC_I8253 if X86_32
select CLOCKSOURCE_VALIDATE_LAST_CYCLE
select CLOCKSOURCE_WATCHDOG
- select CLONE_BACKWARDS if X86_32
- select COMPAT_OLD_SIGACTION if IA32_EMULATION
select DCACHE_WORD_ACCESS
select EDAC_ATOMIC_SCRUB
select EDAC_SUPPORT
@@ -77,7 +93,6 @@ config X86
select HAVE_ACPI_APEI if ACPI
select HAVE_ACPI_APEI_NMI if ACPI
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
- select HAVE_AOUT if X86_32
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
@@ -88,12 +103,10 @@ config X86
select HAVE_ARCH_MMAP_RND_BITS if MMU
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT
select HAVE_ARCH_SECCOMP_FILTER
- select HAVE_ARCH_SOFT_DIRTY if X86_64
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
- select HAVE_ARCH_WITHIN_STACK_FRAMES
- select HAVE_EBPF_JIT if X86_64
select HAVE_ARCH_VMAP_STACK if X86_64
+ select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_CC_STACKPROTECTOR
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
@@ -106,6 +119,7 @@ config X86
select HAVE_DMA_CONTIGUOUS
select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS
+ select HAVE_EBPF_JIT if X86_64
select HAVE_EFFICIENT_UNALIGNED_ACCESS
select HAVE_EXIT_THREAD
select HAVE_FENTRY if X86_64
@@ -113,7 +127,6 @@ config X86
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
select HAVE_GCC_PLUGINS
- select HAVE_GENERIC_DMA_COHERENT if X86_32
select HAVE_HW_BREAKPOINT
select HAVE_IDE
select HAVE_IOREMAP_PROT
@@ -142,15 +155,11 @@ config X86
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_STACK_VALIDATION if X86_64
select HAVE_SYSCALL_TRACEPOINTS
- select HAVE_UID16 if X86_32 || IA32_EMULATION
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_USER_RETURN_NOTIFIER
select IRQ_FORCED_THREADING
- select MODULES_USE_ELF_RELA if X86_64
- select MODULES_USE_ELF_REL if X86_32
- select OLD_SIGACTION if X86_32
- select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
select PERF_EVENTS
select RTC_LIB
select RTC_MC146818_LIB
@@ -160,11 +169,7 @@ config X86
select THREAD_INFO_IN_TASK
select USER_STACKTRACE_SUPPORT
select VIRT_TO_BUS
- select X86_DEV_DMA_OPS if X86_64
select X86_FEATURE_NAMES if PROC_FS
- select HAVE_STACK_VALIDATION if X86_64
- select ARCH_USES_HIGH_VMA_FLAGS if X86_INTEL_MEMORY_PROTECTION_KEYS
- select ARCH_HAS_PKEYS if X86_INTEL_MEMORY_PROTECTION_KEYS
config INSTRUCTION_DECODER
def_bool y
@@ -939,6 +944,27 @@ config SCHED_MC
making when dealing with multi-core CPU chips at a cost of slightly
increased overhead in some places. If unsure say N here.
+config SCHED_MC_PRIO
+ bool "CPU core priorities scheduler support"
+ depends on SCHED_MC && CPU_SUP_INTEL
+ select X86_INTEL_PSTATE
+ select CPU_FREQ
+ default y
+ ---help---
+ Intel Turbo Boost Max Technology 3.0 enabled CPUs have a
+ core ordering determined at manufacturing time, which allows
+ certain cores to reach higher turbo frequencies (when running
+ single threaded workloads) than others.
+
+ Enabling this kernel feature teaches the scheduler about
+ the TBM3 (aka ITMT) priority order of the CPU cores and adjusts the
+ scheduler's CPU selection logic accordingly, so that higher
+ overall system performance can be achieved.
+
+ This feature will have no effect on CPUs without this feature.
+
+ If unsure say Y here.
+
source "kernel/Kconfig.preempt"
config UP_LATE_INIT
@@ -1025,7 +1051,7 @@ config X86_MCE_INTEL
config X86_MCE_AMD
def_bool y
prompt "AMD MCE features"
- depends on X86_MCE && X86_LOCAL_APIC
+ depends on X86_MCE && X86_LOCAL_APIC && AMD_NB
---help---
Additional support for AMD specific MCE features such as
the DRAM Error Threshold.
@@ -1525,7 +1551,7 @@ config X86_CHECK_BIOS_CORRUPTION
line. By default it scans the low 64k of memory every 60
seconds; see the memory_corruption_check_size and
memory_corruption_check_period parameters in
- Documentation/kernel-parameters.txt to adjust this.
+ Documentation/admin-guide/kernel-parameters.rst to adjust this.
When enabled with the default parameters, this option has
almost no overhead, as it reserves a relatively small amount
@@ -1737,6 +1763,8 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS
def_bool y
# Note: only available in 64-bit mode
depends on CPU_SUP_INTEL && X86_64
+ select ARCH_USES_HIGH_VMA_FLAGS
+ select ARCH_HAS_PKEYS
---help---
Memory Protection Keys provides a mechanism for enforcing
page-based protections, but without requiring modification of the
@@ -2092,7 +2120,7 @@ config DEBUG_HOTPLUG_CPU0
config COMPAT_VDSO
def_bool n
prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)"
- depends on X86_32 || IA32_EMULATION
+ depends on COMPAT_32
---help---
Certain buggy versions of glibc will crash if they are
presented with a 32-bit vDSO that is not mapped at the address
@@ -2694,9 +2722,10 @@ source "fs/Kconfig.binfmt"
config IA32_EMULATION
bool "IA32 Emulation"
depends on X86_64
+ select ARCH_WANT_OLD_COMPAT_IPC
select BINFMT_ELF
select COMPAT_BINFMT_ELF
- select ARCH_WANT_OLD_COMPAT_IPC
+ select COMPAT_OLD_SIGACTION
---help---
Include code to run legacy 32-bit programs under a
64-bit kernel. You should likely turn this on, unless you're
@@ -2721,6 +2750,12 @@ config X86_X32
elf32_x86_64 support enabled to compile a kernel with this
option set.
+config COMPAT_32
+ def_bool y
+ depends on IA32_EMULATION || X86_32
+ select HAVE_UID16
+ select OLD_SIGSUSPEND3
+
config COMPAT
def_bool y
depends on IA32_EMULATION || X86_X32
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 12ea8f8384f4..0d810fb15eac 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -65,7 +65,7 @@ clean-files += cpustr.h
# ---------------------------------------------------------------------------
-KBUILD_CFLAGS := $(USERINCLUDE) $(REALMODE_CFLAGS) -D_SETUP
+KBUILD_CFLAGS := $(REALMODE_CFLAGS) -D_SETUP
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
GCOV_PROFILE := n
UBSAN_SANITIZE := n
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index cc69e37548db..ff01c8fc76f7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -537,6 +537,69 @@ free_handle:
efi_call_early(free_pool, pci_handle);
}
+static void retrieve_apple_device_properties(struct boot_params *boot_params)
+{
+ efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
+ struct setup_data *data, *new;
+ efi_status_t status;
+ u32 size = 0;
+ void *p;
+
+ status = efi_call_early(locate_protocol, &guid, NULL, &p);
+ if (status != EFI_SUCCESS)
+ return;
+
+ if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
+ efi_printk(sys_table, "Unsupported properties proto version\n");
+ return;
+ }
+
+ efi_call_proto(apple_properties_protocol, get_all, p, NULL, &size);
+ if (!size)
+ return;
+
+ do {
+ status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+ size + sizeof(struct setup_data), &new);
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table,
+ "Failed to alloc mem for properties\n");
+ return;
+ }
+
+ status = efi_call_proto(apple_properties_protocol, get_all, p,
+ new->data, &size);
+
+ if (status == EFI_BUFFER_TOO_SMALL)
+ efi_call_early(free_pool, new);
+ } while (status == EFI_BUFFER_TOO_SMALL);
+
+ new->type = SETUP_APPLE_PROPERTIES;
+ new->len = size;
+ new->next = 0;
+
+ data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
+ if (!data)
+ boot_params->hdr.setup_data = (unsigned long)new;
+ else {
+ while (data->next)
+ data = (struct setup_data *)(unsigned long)data->next;
+ data->next = (unsigned long)new;
+ }
+}
+
+static void setup_quirks(struct boot_params *boot_params)
+{
+ efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
+ efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
+ efi_table_attr(efi_system_table, fw_vendor, sys_table);
+
+ if (!memcmp(fw_vendor, apple, sizeof(apple))) {
+ if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
+ retrieve_apple_device_properties(boot_params);
+ }
+}
+
static efi_status_t
setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
{
@@ -1098,6 +1161,8 @@ struct boot_params *efi_main(struct efi_config *c,
setup_efi_pci(boot_params);
+ setup_quirks(boot_params);
+
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
sizeof(*gdt), (void **)&gdt);
if (status != EFI_SUCCESS) {
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index efdfba21a5b2..4d85e600db78 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -119,8 +119,7 @@ ENTRY(startup_32)
*/
/* Load new GDT with the 64bit segments using 32bit descriptor */
- leal gdt(%ebp), %eax
- movl %eax, gdt+2(%ebp)
+ addl %ebp, gdt+2(%ebp)
lgdt gdt(%ebp)
/* Enable PAE mode */
diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c
index 0857b1a1de3b..c194d5717ae5 100644
--- a/arch/x86/crypto/crc32c-intel_glue.c
+++ b/arch/x86/crypto/crc32c-intel_glue.c
@@ -48,26 +48,13 @@
#ifdef CONFIG_X86_64
/*
* use carryless multiply version of crc32c when buffer
- * size is >= 512 (when eager fpu is enabled) or
- * >= 1024 (when eager fpu is disabled) to account
+ * size is >= 512 to account
* for fpu state save/restore overhead.
*/
-#define CRC32C_PCL_BREAKEVEN_EAGERFPU 512
-#define CRC32C_PCL_BREAKEVEN_NOEAGERFPU 1024
+#define CRC32C_PCL_BREAKEVEN 512
asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
unsigned int crc_init);
-static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU;
-#if defined(X86_FEATURE_EAGER_FPU)
-#define set_pcl_breakeven_point() \
-do { \
- if (!use_eager_fpu()) \
- crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU; \
-} while (0)
-#else
-#define set_pcl_breakeven_point() \
- (crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU)
-#endif
#endif /* CONFIG_X86_64 */
static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
@@ -190,7 +177,7 @@ static int crc32c_pcl_intel_update(struct shash_desc *desc, const u8 *data,
* use faster PCL version if datasize is large enough to
* overcome kernel fpu state save/restore overhead
*/
- if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+ if (len >= CRC32C_PCL_BREAKEVEN && irq_fpu_usable()) {
kernel_fpu_begin();
*crcp = crc_pcl(data, len, *crcp);
kernel_fpu_end();
@@ -202,7 +189,7 @@ static int crc32c_pcl_intel_update(struct shash_desc *desc, const u8 *data,
static int __crc32c_pcl_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
u8 *out)
{
- if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+ if (len >= CRC32C_PCL_BREAKEVEN && irq_fpu_usable()) {
kernel_fpu_begin();
*(__le32 *)out = ~cpu_to_le32(crc_pcl(data, len, *crcp));
kernel_fpu_end();
@@ -261,7 +248,6 @@ static int __init crc32c_intel_mod_init(void)
alg.update = crc32c_pcl_intel_update;
alg.finup = crc32c_pcl_intel_finup;
alg.digest = crc32c_pcl_intel_digest;
- set_pcl_breakeven_point();
}
#endif
return crypto_register_shash(&alg);
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 9a9e5884066c..05ed3d393da7 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -90,8 +90,8 @@ For 32-bit we have the following conventions - kernel is built with
#define SIZEOF_PTREGS 21*8
- .macro ALLOC_PT_GPREGS_ON_STACK addskip=0
- addq $-(15*8+\addskip), %rsp
+ .macro ALLOC_PT_GPREGS_ON_STACK
+ addq $-(15*8), %rsp
.endm
.macro SAVE_C_REGS_HELPER offset=0 rax=1 rcx=1 r8910=1 r11=1
@@ -147,15 +147,6 @@ For 32-bit we have the following conventions - kernel is built with
movq 5*8+\offset(%rsp), %rbx
.endm
- .macro ZERO_EXTRA_REGS
- xorl %r15d, %r15d
- xorl %r14d, %r14d
- xorl %r13d, %r13d
- xorl %r12d, %r12d
- xorl %ebp, %ebp
- xorl %ebx, %ebx
- .endm
-
.macro RESTORE_C_REGS_HELPER rstor_rax=1, rstor_rcx=1, rstor_r11=1, rstor_r8910=1, rstor_rdx=1
.if \rstor_r11
movq 6*8(%rsp), %r11
@@ -201,6 +192,26 @@ For 32-bit we have the following conventions - kernel is built with
.byte 0xf1
.endm
+/*
+ * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
+ * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
+ * is just setting the LSB, which makes it an invalid stack address and is also
+ * a signal to the unwinder that it's a pt_regs pointer in disguise.
+ *
+ * NOTE: This macro must be used *after* SAVE_EXTRA_REGS because it corrupts
+ * the original rbp.
+ */
+.macro ENCODE_FRAME_POINTER ptregs_offset=0
+#ifdef CONFIG_FRAME_POINTER
+ .if \ptregs_offset
+ leaq \ptregs_offset(%rsp), %rbp
+ .else
+ mov %rsp, %rbp
+ .endif
+ orq $0x1, %rbp
+#endif
+.endm
+
#endif /* CONFIG_X86_64 */
/*
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 21b352a11b49..acc0c6f36f3f 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -45,6 +45,7 @@
#include <asm/asm.h>
#include <asm/smap.h>
#include <asm/export.h>
+#include <asm/frame.h>
.section .entry.text, "ax"
@@ -175,6 +176,22 @@
SET_KERNEL_GS %edx
.endm
+/*
+ * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
+ * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
+ * is just setting the LSB, which makes it an invalid stack address and is also
+ * a signal to the unwinder that it's a pt_regs pointer in disguise.
+ *
+ * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
+ * original rbp.
+ */
+.macro ENCODE_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
+ mov %esp, %ebp
+ orl $0x1, %ebp
+#endif
+.endm
+
.macro RESTORE_INT_REGS
popl %ebx
popl %ecx
@@ -238,6 +255,23 @@ ENTRY(__switch_to_asm)
END(__switch_to_asm)
/*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack. This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+ FRAME_BEGIN
+
+ pushl %eax
+ call schedule_tail
+ popl %eax
+
+ FRAME_END
+ ret
+ENDPROC(schedule_tail_wrapper)
+/*
* A newly forked process directly context switches into this address.
*
* eax: prev task we switched from
@@ -245,9 +279,7 @@ END(__switch_to_asm)
* edi: kernel thread arg
*/
ENTRY(ret_from_fork)
- pushl %eax
- call schedule_tail
- popl %eax
+ call schedule_tail_wrapper
testl %ebx, %ebx
jnz 1f /* kernel threads are uncommon */
@@ -307,13 +339,13 @@ END(ret_from_exception)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
-need_resched:
+.Lneed_resched:
cmpl $0, PER_CPU_VAR(__preempt_count)
jnz restore_all
testl $X86_EFLAGS_IF, PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq
- jmp need_resched
+ jmp .Lneed_resched
END(resume_kernel)
#endif
@@ -334,7 +366,7 @@ GLOBAL(__begin_SYSENTER_singlestep_region)
*/
ENTRY(xen_sysenter_target)
addl $5*4, %esp /* remove xen-provided frame */
- jmp sysenter_past_esp
+ jmp .Lsysenter_past_esp
#endif
/*
@@ -371,7 +403,7 @@ ENTRY(xen_sysenter_target)
*/
ENTRY(entry_SYSENTER_32)
movl TSS_sysenter_sp0(%esp), %esp
-sysenter_past_esp:
+.Lsysenter_past_esp:
pushl $__USER_DS /* pt_regs->ss */
pushl %ebp /* pt_regs->sp (stashed in bp) */
pushfl /* pt_regs->flags (except IF = 0) */
@@ -504,9 +536,9 @@ ENTRY(entry_INT80_32)
restore_all:
TRACE_IRQS_IRET
-restore_all_notrace:
+.Lrestore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
- ALTERNATIVE "jmp restore_nocheck", "", X86_BUG_ESPFIX
+ ALTERNATIVE "jmp .Lrestore_nocheck", "", X86_BUG_ESPFIX
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
/*
@@ -518,22 +550,23 @@ restore_all_notrace:
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
- je ldt_ss # returning to user-space with LDT SS
+ je .Lldt_ss # returning to user-space with LDT SS
#endif
-restore_nocheck:
+.Lrestore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
-irq_return:
+.Lirq_return:
INTERRUPT_RETURN
+
.section .fixup, "ax"
ENTRY(iret_exc )
pushl $0 # no error code
pushl $do_iret_error
- jmp error_code
+ jmp common_exception
.previous
- _ASM_EXTABLE(irq_return, iret_exc)
+ _ASM_EXTABLE(.Lirq_return, iret_exc)
#ifdef CONFIG_X86_ESPFIX32
-ldt_ss:
+.Lldt_ss:
/*
* Setup and switch to ESPFIX stack
*
@@ -562,7 +595,7 @@ ldt_ss:
*/
DISABLE_INTERRUPTS(CLBR_EAX)
lss (%esp), %esp /* switch to espfix segment */
- jmp restore_nocheck
+ jmp .Lrestore_nocheck
#endif
ENDPROC(entry_INT80_32)
@@ -624,6 +657,7 @@ common_interrupt:
ASM_CLAC
addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */
SAVE_ALL
+ ENCODE_FRAME_POINTER
TRACE_IRQS_OFF
movl %esp, %eax
call do_IRQ
@@ -635,6 +669,7 @@ ENTRY(name) \
ASM_CLAC; \
pushl $~(nr); \
SAVE_ALL; \
+ ENCODE_FRAME_POINTER; \
TRACE_IRQS_OFF \
movl %esp, %eax; \
call fn; \
@@ -659,7 +694,7 @@ ENTRY(coprocessor_error)
ASM_CLAC
pushl $0
pushl $do_coprocessor_error
- jmp error_code
+ jmp common_exception
END(coprocessor_error)
ENTRY(simd_coprocessor_error)
@@ -673,14 +708,14 @@ ENTRY(simd_coprocessor_error)
#else
pushl $do_simd_coprocessor_error
#endif
- jmp error_code
+ jmp common_exception
END(simd_coprocessor_error)
ENTRY(device_not_available)
ASM_CLAC
pushl $-1 # mark this as an int
pushl $do_device_not_available
- jmp error_code
+ jmp common_exception
END(device_not_available)
#ifdef CONFIG_PARAVIRT
@@ -694,59 +729,59 @@ ENTRY(overflow)
ASM_CLAC
pushl $0
pushl $do_overflow
- jmp error_code
+ jmp common_exception
END(overflow)
ENTRY(bounds)
ASM_CLAC
pushl $0
pushl $do_bounds
- jmp error_code
+ jmp common_exception
END(bounds)
ENTRY(invalid_op)
ASM_CLAC
pushl $0
pushl $do_invalid_op
- jmp error_code
+ jmp common_exception
END(invalid_op)
ENTRY(coprocessor_segment_overrun)
ASM_CLAC
pushl $0
pushl $do_coprocessor_segment_overrun
- jmp error_code
+ jmp common_exception
END(coprocessor_segment_overrun)
ENTRY(invalid_TSS)
ASM_CLAC
pushl $do_invalid_TSS
- jmp error_code
+ jmp common_exception
END(invalid_TSS)
ENTRY(segment_not_present)
ASM_CLAC
pushl $do_segment_not_present
- jmp error_code
+ jmp common_exception
END(segment_not_present)
ENTRY(stack_segment)
ASM_CLAC
pushl $do_stack_segment
- jmp error_code
+ jmp common_exception
END(stack_segment)
ENTRY(alignment_check)
ASM_CLAC
pushl $do_alignment_check
- jmp error_code
+ jmp common_exception
END(alignment_check)
ENTRY(divide_error)
ASM_CLAC
pushl $0 # no error code
pushl $do_divide_error
- jmp error_code
+ jmp common_exception
END(divide_error)
#ifdef CONFIG_X86_MCE
@@ -754,7 +789,7 @@ ENTRY(machine_check)
ASM_CLAC
pushl $0
pushl machine_check_vector
- jmp error_code
+ jmp common_exception
END(machine_check)
#endif
@@ -762,13 +797,14 @@ ENTRY(spurious_interrupt_bug)
ASM_CLAC
pushl $0
pushl $do_spurious_interrupt_bug
- jmp error_code
+ jmp common_exception
END(spurious_interrupt_bug)
#ifdef CONFIG_XEN
ENTRY(xen_hypervisor_callback)
pushl $-1 /* orig_ax = -1 => not a system call */
SAVE_ALL
+ ENCODE_FRAME_POINTER
TRACE_IRQS_OFF
/*
@@ -823,6 +859,7 @@ ENTRY(xen_failsafe_callback)
jmp iret_exc
5: pushl $-1 /* orig_ax = -1 => not a system call */
SAVE_ALL
+ ENCODE_FRAME_POINTER
jmp ret_from_exception
.section .fixup, "ax"
@@ -882,7 +919,7 @@ ftrace_call:
popl %edx
popl %ecx
popl %eax
-ftrace_ret:
+.Lftrace_ret:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.globl ftrace_graph_call
ftrace_graph_call:
@@ -952,7 +989,7 @@ GLOBAL(ftrace_regs_call)
popl %gs
addl $8, %esp /* Skip orig_ax and ip */
popf /* Pop flags at end (no addl to corrupt flags) */
- jmp ftrace_ret
+ jmp .Lftrace_ret
popf
jmp ftrace_stub
@@ -963,7 +1000,7 @@ ENTRY(mcount)
jb ftrace_stub /* Paging not enabled yet? */
cmpl $ftrace_stub, ftrace_trace_function
- jnz trace
+ jnz .Ltrace
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
cmpl $ftrace_stub, ftrace_graph_return
jnz ftrace_graph_caller
@@ -976,7 +1013,7 @@ ftrace_stub:
ret
/* taken from glibc */
-trace:
+.Ltrace:
pushl %eax
pushl %ecx
pushl %edx
@@ -1027,7 +1064,7 @@ return_to_handler:
ENTRY(trace_page_fault)
ASM_CLAC
pushl $trace_do_page_fault
- jmp error_code
+ jmp common_exception
END(trace_page_fault)
#endif
@@ -1035,7 +1072,10 @@ ENTRY(page_fault)
ASM_CLAC
pushl $do_page_fault
ALIGN
-error_code:
+ jmp common_exception
+END(page_fault)
+
+common_exception:
/* the function address is in %gs's slot on the stack */
pushl %fs
pushl %es
@@ -1047,6 +1087,7 @@ error_code:
pushl %edx
pushl %ecx
pushl %ebx
+ ENCODE_FRAME_POINTER
cld
movl $(__KERNEL_PERCPU), %ecx
movl %ecx, %fs
@@ -1064,7 +1105,7 @@ error_code:
movl %esp, %eax # pt_regs pointer
call *%edi
jmp ret_from_exception
-END(page_fault)
+END(common_exception)
ENTRY(debug)
/*
@@ -1079,6 +1120,7 @@ ENTRY(debug)
ASM_CLAC
pushl $-1 # mark this as an int
SAVE_ALL
+ ENCODE_FRAME_POINTER
xorl %edx, %edx # error code 0
movl %esp, %eax # pt_regs pointer
@@ -1094,11 +1136,11 @@ ENTRY(debug)
.Ldebug_from_sysenter_stack:
/* We're on the SYSENTER stack. Switch off. */
- movl %esp, %ebp
+ movl %esp, %ebx
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
TRACE_IRQS_OFF
call do_debug
- movl %ebp, %esp
+ movl %ebx, %esp
jmp ret_from_exception
END(debug)
@@ -1116,11 +1158,12 @@ ENTRY(nmi)
movl %ss, %eax
cmpw $__ESPFIX_SS, %ax
popl %eax
- je nmi_espfix_stack
+ je .Lnmi_espfix_stack
#endif
pushl %eax # pt_regs->orig_ax
SAVE_ALL
+ ENCODE_FRAME_POINTER
xorl %edx, %edx # zero error code
movl %esp, %eax # pt_regs pointer
@@ -1132,21 +1175,21 @@ ENTRY(nmi)
/* Not on SYSENTER stack. */
call do_nmi
- jmp restore_all_notrace
+ jmp .Lrestore_all_notrace
.Lnmi_from_sysenter_stack:
/*
* We're on the SYSENTER stack. Switch off. No one (not even debug)
* is using the thread stack right now, so it's safe for us to use it.
*/
- movl %esp, %ebp
+ movl %esp, %ebx
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
call do_nmi
- movl %ebp, %esp
- jmp restore_all_notrace
+ movl %ebx, %esp
+ jmp .Lrestore_all_notrace
#ifdef CONFIG_X86_ESPFIX32
-nmi_espfix_stack:
+.Lnmi_espfix_stack:
/*
* create the pointer to lss back
*/
@@ -1159,12 +1202,13 @@ nmi_espfix_stack:
.endr
pushl %eax
SAVE_ALL
+ ENCODE_FRAME_POINTER
FIXUP_ESPFIX_STACK # %eax == %esp
xorl %edx, %edx # zero error code
call do_nmi
RESTORE_REGS
lss 12+4(%esp), %esp # back to espfix stack
- jmp irq_return
+ jmp .Lirq_return
#endif
END(nmi)
@@ -1172,6 +1216,7 @@ ENTRY(int3)
ASM_CLAC
pushl $-1 # mark this as an int
SAVE_ALL
+ ENCODE_FRAME_POINTER
TRACE_IRQS_OFF
xorl %edx, %edx # zero error code
movl %esp, %eax # pt_regs pointer
@@ -1181,14 +1226,14 @@ END(int3)
ENTRY(general_protection)
pushl $do_general_protection
- jmp error_code
+ jmp common_exception
END(general_protection)
#ifdef CONFIG_KVM_GUEST
ENTRY(async_page_fault)
ASM_CLAC
pushl $do_async_page_fault
- jmp error_code
+ jmp common_exception
END(async_page_fault)
#endif
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index ef766a358b37..5b219707c2f2 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -38,12 +38,6 @@
#include <asm/export.h>
#include <linux/err.h>
-/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
-#include <linux/elf-em.h>
-#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
-#define __AUDIT_ARCH_64BIT 0x80000000
-#define __AUDIT_ARCH_LE 0x40000000
-
.code64
.section .entry.text, "ax"
@@ -469,6 +463,7 @@ END(irq_entries_start)
ALLOC_PT_GPREGS_ON_STACK
SAVE_C_REGS
SAVE_EXTRA_REGS
+ ENCODE_FRAME_POINTER
testb $3, CS(%rsp)
jz 1f
@@ -985,6 +980,7 @@ ENTRY(xen_failsafe_callback)
ALLOC_PT_GPREGS_ON_STACK
SAVE_C_REGS
SAVE_EXTRA_REGS
+ ENCODE_FRAME_POINTER
jmp error_exit
END(xen_failsafe_callback)
@@ -1028,6 +1024,7 @@ ENTRY(paranoid_entry)
cld
SAVE_C_REGS 8
SAVE_EXTRA_REGS 8
+ ENCODE_FRAME_POINTER 8
movl $1, %ebx
movl $MSR_GS_BASE, %ecx
rdmsr
@@ -1075,6 +1072,7 @@ ENTRY(error_entry)
cld
SAVE_C_REGS 8
SAVE_EXTRA_REGS 8
+ ENCODE_FRAME_POINTER 8
xorl %ebx, %ebx
testb $3, CS+8(%rsp)
jz .Lerror_kernelspace
@@ -1257,6 +1255,7 @@ ENTRY(nmi)
pushq %r13 /* pt_regs->r13 */
pushq %r14 /* pt_regs->r14 */
pushq %r15 /* pt_regs->r15 */
+ ENCODE_FRAME_POINTER
/*
* At this point we no longer need to worry about stack damage
@@ -1270,11 +1269,10 @@ ENTRY(nmi)
/*
* Return back to user mode. We must *not* do the normal exit
- * work, because we don't want to enable interrupts. Fortunately,
- * do_nmi doesn't modify pt_regs.
+ * work, because we don't want to enable interrupts.
*/
SWAPGS
- jmp restore_c_regs_and_iret
+ jmp restore_regs_and_iret
.Lnmi_from_kernel:
/*
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 23c881caabd1..e739002427ed 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -161,8 +161,6 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
}
text_start = addr - image->sym_vvar_start;
- current->mm->context.vdso = (void __user *)text_start;
- current->mm->context.vdso_image = image;
/*
* MAYWRITE to allow gdb to COW and set breakpoints
@@ -189,14 +187,12 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
do_munmap(mm, text_start, image->size);
+ } else {
+ current->mm->context.vdso = (void __user *)text_start;
+ current->mm->context.vdso_image = image;
}
up_fail:
- if (ret) {
- current->mm->context.vdso = NULL;
- current->mm->context.vdso_image = NULL;
- }
-
up_write(&mm->mmap_sem);
return ret;
}
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 6e395c996900..f1c22584a46f 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -365,7 +365,11 @@ int x86_add_exclusive(unsigned int what)
{
int i;
- if (x86_pmu.lbr_pt_coexist)
+ /*
+ * When lbr_pt_coexist we allow PT to coexist with either LBR or BTS.
+ * LBR and BTS are still mutually exclusive.
+ */
+ if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
return 0;
if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
@@ -388,7 +392,7 @@ fail_unlock:
void x86_del_exclusive(unsigned int what)
{
- if (x86_pmu.lbr_pt_coexist)
+ if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
return;
atomic_dec(&x86_pmu.lbr_exclusive[what]);
@@ -2299,7 +2303,7 @@ valid_user_frame(const void __user *fp, unsigned long size)
static unsigned long get_segment_base(unsigned int segment)
{
struct desc_struct *desc;
- int idx = segment >> 3;
+ unsigned int idx = segment >> 3;
if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
#ifdef CONFIG_MODIFY_LDT_SYSCALL
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index c5047b8f777b..1c1b9fe705c8 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -36,13 +36,6 @@ static DEFINE_PER_CPU(struct pt, pt_ctx);
static struct pt_pmu pt_pmu;
-enum cpuid_regs {
- CR_EAX = 0,
- CR_ECX,
- CR_EDX,
- CR_EBX
-};
-
/*
* Capabilities of Intel PT hardware, such as number of address bits or
* supported output schemes, are cached and exported to userspace as "caps"
@@ -64,21 +57,21 @@ static struct pt_cap_desc {
u8 reg;
u32 mask;
} pt_caps[] = {
- PT_CAP(max_subleaf, 0, CR_EAX, 0xffffffff),
- PT_CAP(cr3_filtering, 0, CR_EBX, BIT(0)),
- PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)),
- PT_CAP(ip_filtering, 0, CR_EBX, BIT(2)),
- PT_CAP(mtc, 0, CR_EBX, BIT(3)),
- PT_CAP(ptwrite, 0, CR_EBX, BIT(4)),
- PT_CAP(power_event_trace, 0, CR_EBX, BIT(5)),
- PT_CAP(topa_output, 0, CR_ECX, BIT(0)),
- PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)),
- PT_CAP(single_range_output, 0, CR_ECX, BIT(2)),
- PT_CAP(payloads_lip, 0, CR_ECX, BIT(31)),
- PT_CAP(num_address_ranges, 1, CR_EAX, 0x3),
- PT_CAP(mtc_periods, 1, CR_EAX, 0xffff0000),
- PT_CAP(cycle_thresholds, 1, CR_EBX, 0xffff),
- PT_CAP(psb_periods, 1, CR_EBX, 0xffff0000),
+ PT_CAP(max_subleaf, 0, CPUID_EAX, 0xffffffff),
+ PT_CAP(cr3_filtering, 0, CPUID_EBX, BIT(0)),
+ PT_CAP(psb_cyc, 0, CPUID_EBX, BIT(1)),
+ PT_CAP(ip_filtering, 0, CPUID_EBX, BIT(2)),
+ PT_CAP(mtc, 0, CPUID_EBX, BIT(3)),
+ PT_CAP(ptwrite, 0, CPUID_EBX, BIT(4)),
+ PT_CAP(power_event_trace, 0, CPUID_EBX, BIT(5)),
+ PT_CAP(topa_output, 0, CPUID_ECX, BIT(0)),
+ PT_CAP(topa_multiple_entries, 0, CPUID_ECX, BIT(1)),
+ PT_CAP(single_range_output, 0, CPUID_ECX, BIT(2)),
+ PT_CAP(payloads_lip, 0, CPUID_ECX, BIT(31)),
+ PT_CAP(num_address_ranges, 1, CPUID_EAX, 0x3),
+ PT_CAP(mtc_periods, 1, CPUID_EAX, 0xffff0000),
+ PT_CAP(cycle_thresholds, 1, CPUID_EBX, 0xffff),
+ PT_CAP(psb_periods, 1, CPUID_EBX, 0xffff0000),
};
static u32 pt_cap_get(enum pt_capabilities cap)
@@ -213,10 +206,10 @@ static int __init pt_pmu_hw_init(void)
for (i = 0; i < PT_CPUID_LEAVES; i++) {
cpuid_count(20, i,
- &pt_pmu.caps[CR_EAX + i*PT_CPUID_REGS_NUM],
- &pt_pmu.caps[CR_EBX + i*PT_CPUID_REGS_NUM],
- &pt_pmu.caps[CR_ECX + i*PT_CPUID_REGS_NUM],
- &pt_pmu.caps[CR_EDX + i*PT_CPUID_REGS_NUM]);
+ &pt_pmu.caps[CPUID_EAX + i*PT_CPUID_REGS_NUM],
+ &pt_pmu.caps[CPUID_EBX + i*PT_CPUID_REGS_NUM],
+ &pt_pmu.caps[CPUID_ECX + i*PT_CPUID_REGS_NUM],
+ &pt_pmu.caps[CPUID_EDX + i*PT_CPUID_REGS_NUM]);
}
ret = -ENOMEM;
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index a77ee026643d..bcbb1d2ae10b 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -604,7 +604,7 @@ struct x86_pmu {
u64 lbr_sel_mask; /* LBR_SELECT valid bits */
const int *lbr_sel_map; /* lbr_select mappings */
bool lbr_double_abort; /* duplicated lbr aborts */
- bool lbr_pt_coexist; /* LBR may coexist with PT */
+ bool lbr_pt_coexist; /* (LBR|BTS) may coexist with PT */
/*
* Intel PT/LBR/BTS are exclusive
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..2b892e2313a9 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -6,10 +6,6 @@ generated-y += unistd_32_ia32.h
generated-y += unistd_64_x32.h
generated-y += xen-hypercalls.h
-genhdr-y += unistd_32.h
-genhdr-y += unistd_64.h
-genhdr-y += unistd_x32.h
-
generic-y += clkdev.h
generic-y += cputime.h
generic-y += dma-contiguous.h
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 5391b0ae7cc3..395b69551fce 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -94,7 +94,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
boot_cpu_data.x86_model <= 0x05 &&
boot_cpu_data.x86_mask < 0x0A)
return 1;
- else if (amd_e400_c1e_detected)
+ else if (boot_cpu_has(X86_BUG_AMD_APIC_C1E))
return 1;
else
return max_cstate;
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 5e828da2e18f..00c88a01301d 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -21,6 +21,10 @@ extern int amd_numa_init(void);
extern int amd_get_subcaches(int);
extern int amd_set_subcaches(int, unsigned long);
+extern int amd_smn_read(u16 node, u32 address, u32 *value);
+extern int amd_smn_write(u16 node, u32 address, u32 value);
+extern int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo);
+
struct amd_l3_cache {
unsigned indices;
u8 subcaches[4];
@@ -55,6 +59,7 @@ struct threshold_bank {
};
struct amd_northbridge {
+ struct pci_dev *root;
struct pci_dev *misc;
struct pci_dev *link;
struct amd_l3_cache l3_cache;
@@ -66,7 +71,6 @@ struct amd_northbridge_info {
u64 flags;
struct amd_northbridge *nb;
};
-extern struct amd_northbridge_info amd_northbridges;
#define AMD_NB_GART BIT(0)
#define AMD_NB_L3_INDEX_DISABLE BIT(1)
@@ -74,20 +78,9 @@ extern struct amd_northbridge_info amd_northbridges;
#ifdef CONFIG_AMD_NB
-static inline u16 amd_nb_num(void)
-{
- return amd_northbridges.num;
-}
-
-static inline bool amd_nb_has_feature(unsigned feature)
-{
- return ((amd_northbridges.flags & feature) == feature);
-}
-
-static inline struct amd_northbridge *node_to_amd_nb(int node)
-{
- return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
-}
+u16 amd_nb_num(void);
+bool amd_nb_has_feature(unsigned int feature);
+struct amd_northbridge *node_to_amd_nb(int node);
static inline u16 amd_pci_dev_to_node_id(struct pci_dev *pdev)
{
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f5aaf6c83222..0c5fbc68e82d 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -11,7 +11,6 @@
#include <asm/fixmap.h>
#include <asm/mpspec.h>
#include <asm/msr.h>
-#include <asm/idle.h>
#define ARCH_APICTIMER_STOPS_ON_C3 1
@@ -196,7 +195,7 @@ static inline void native_apic_msr_write(u32 reg, u32 v)
static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
{
- wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
+ wrmsr_notrace(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
}
static inline u32 native_apic_msr_read(u32 reg)
@@ -332,6 +331,7 @@ struct apic {
* on write for EOI.
*/
void (*eoi_write)(u32 reg, u32 v);
+ void (*native_eoi_write)(u32 reg, u32 v);
u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high);
void (*wait_icr_idle)(void);
@@ -639,7 +639,6 @@ extern void irq_exit(void);
static inline void entering_irq(void)
{
irq_enter();
- exit_idle();
}
static inline void entering_ack_irq(void)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69fc0ceb..d59c15c3defd 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -204,6 +204,7 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)
#define static_cpu_has_bug(bit) static_cpu_has((bit))
#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
+#define boot_cpu_set_bug(bit) set_cpu_cap(&boot_cpu_data, (bit))
#define MAX_CPU_FEATURES (NCAPINTS * 32)
#define cpu_have_feature boot_cpu_has
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index a39629206864..59ac427960d4 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -104,7 +104,6 @@
#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
-#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
@@ -193,6 +192,7 @@
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
+#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
@@ -226,6 +226,7 @@
#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
@@ -279,8 +280,10 @@
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
+#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
+#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */
/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
@@ -311,4 +314,6 @@
#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
+#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
+
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 389d700b961e..e99675b9c861 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -210,12 +210,18 @@ static inline bool efi_is_64bit(void)
return __efi_early()->is64;
}
+#define efi_table_attr(table, attr, instance) \
+ (efi_is_64bit() ? \
+ ((table##_64_t *)(unsigned long)instance)->attr : \
+ ((table##_32_t *)(unsigned long)instance)->attr)
+
+#define efi_call_proto(protocol, f, instance, ...) \
+ __efi_early()->call(efi_table_attr(protocol, f, instance), \
+ instance, ##__VA_ARGS__)
+
#define efi_call_early(f, ...) \
- __efi_early()->call(efi_is_64bit() ? \
- ((efi_boot_services_64_t *)(unsigned long) \
- __efi_early()->boot_services)->f : \
- ((efi_boot_services_32_t *)(unsigned long) \
- __efi_early()->boot_services)->f, __VA_ARGS__)
+ __efi_early()->call(efi_table_attr(efi_boot_services, f, \
+ __efi_early()->boot_services), __VA_ARGS__)
#define __efi_call_early(f, ...) \
__efi_early()->call((unsigned long)f, __VA_ARGS__);
diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
index 1429a7c736db..0877ae018fc9 100644
--- a/arch/x86/include/asm/fpu/api.h
+++ b/arch/x86/include/asm/fpu/api.h
@@ -27,16 +27,6 @@ extern void kernel_fpu_end(void);
extern bool irq_fpu_usable(void);
/*
- * Some instructions like VIA's padlock instructions generate a spurious
- * DNA fault but don't modify SSE registers. And these instructions
- * get used from interrupt context as well. To prevent these kernel instructions
- * in interrupt context interacting wrongly with other user/kernel fpu usage, we
- * should use them only in the context of irq_ts_save/restore()
- */
-extern int irq_ts_save(void);
-extern void irq_ts_restore(int TS_state);
-
-/*
* Query the presence of one or more xfeatures. Works on any legacy CPU as well.
*
* If 'feature_name' is set then put a human-readable description of
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 2737366ea583..d4a684997497 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -60,11 +60,6 @@ extern u64 fpu__get_supported_xfeatures_mask(void);
/*
* FPU related CPU feature flag helper routines:
*/
-static __always_inline __pure bool use_eager_fpu(void)
-{
- return static_cpu_has(X86_FEATURE_EAGER_FPU);
-}
-
static __always_inline __pure bool use_xsaveopt(void)
{
return static_cpu_has(X86_FEATURE_XSAVEOPT);
@@ -484,42 +479,42 @@ extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size)
DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
/*
- * Must be run with preemption disabled: this clears the fpu_fpregs_owner_ctx,
- * on this CPU.
+ * The in-register FPU state for an FPU context on a CPU is assumed to be
+ * valid if the fpu->last_cpu matches the CPU, and the fpu_fpregs_owner_ctx
+ * matches the FPU.
*
- * This will disable any lazy FPU state restore of the current FPU state,
- * but if the current thread owns the FPU, it will still be saved by.
+ * If the FPU register state is valid, the kernel can skip restoring the
+ * FPU state from memory.
+ *
+ * Any code that clobbers the FPU registers or updates the in-memory
+ * FPU state for a task MUST let the rest of the kernel know that the
+ * FPU registers are no longer valid for this task.
+ *
+ * Either one of these invalidation functions is enough. Invalidate
+ * a resource you control: CPU if using the CPU for something else
+ * (with preemption disabled), FPU for the current task, or a task that
+ * is prevented from running by the current task.
*/
-static inline void __cpu_disable_lazy_restore(unsigned int cpu)
+static inline void __cpu_invalidate_fpregs_state(void)
{
- per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
+ __this_cpu_write(fpu_fpregs_owner_ctx, NULL);
}
-static inline int fpu_want_lazy_restore(struct fpu *fpu, unsigned int cpu)
-{
- return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
-}
-
-
-/*
- * Wrap lazy FPU TS handling in a 'hw fpregs activation/deactivation'
- * idiom, which is then paired with the sw-flag (fpregs_active) later on:
- */
-
-static inline void __fpregs_activate_hw(void)
+static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu)
{
- if (!use_eager_fpu())
- clts();
+ fpu->last_cpu = -1;
}
-static inline void __fpregs_deactivate_hw(void)
+static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
{
- if (!use_eager_fpu())
- stts();
+ return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
}
-/* Must be paired with an 'stts' (fpregs_deactivate_hw()) after! */
-static inline void __fpregs_deactivate(struct fpu *fpu)
+/*
+ * These generally need preemption protection to work,
+ * do try to avoid using these on their own:
+ */
+static inline void fpregs_deactivate(struct fpu *fpu)
{
WARN_ON_FPU(!fpu->fpregs_active);
@@ -528,8 +523,7 @@ static inline void __fpregs_deactivate(struct fpu *fpu)
trace_x86_fpu_regs_deactivated(fpu);
}
-/* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
-static inline void __fpregs_activate(struct fpu *fpu)
+static inline void fpregs_activate(struct fpu *fpu)
{
WARN_ON_FPU(fpu->fpregs_active);
@@ -554,51 +548,19 @@ static inline int fpregs_active(void)
}
/*
- * Encapsulate the CR0.TS handling together with the
- * software flag.
- *
- * These generally need preemption protection to work,
- * do try to avoid using these on their own.
- */
-static inline void fpregs_activate(struct fpu *fpu)
-{
- __fpregs_activate_hw();
- __fpregs_activate(fpu);
-}
-
-static inline void fpregs_deactivate(struct fpu *fpu)
-{
- __fpregs_deactivate(fpu);
- __fpregs_deactivate_hw();
-}
-
-/*
* FPU state switching for scheduling.
*
* This is a two-stage process:
*
- * - switch_fpu_prepare() saves the old state and
- * sets the new state of the CR0.TS bit. This is
- * done within the context of the old process.
+ * - switch_fpu_prepare() saves the old state.
+ * This is done within the context of the old process.
*
* - switch_fpu_finish() restores the new state as
* necessary.
*/
-typedef struct { int preload; } fpu_switch_t;
-
-static inline fpu_switch_t
-switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
+static inline void
+switch_fpu_prepare(struct fpu *old_fpu, int cpu)
{
- fpu_switch_t fpu;
-
- /*
- * If the task has used the math, pre-load the FPU on xsave processors
- * or if the past 5 consecutive context-switches used math.
- */
- fpu.preload = static_cpu_has(X86_FEATURE_FPU) &&
- new_fpu->fpstate_active &&
- (use_eager_fpu() || new_fpu->counter > 5);
-
if (old_fpu->fpregs_active) {
if (!copy_fpregs_to_fpstate(old_fpu))
old_fpu->last_cpu = -1;
@@ -608,29 +570,8 @@ switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
/* But leave fpu_fpregs_owner_ctx! */
old_fpu->fpregs_active = 0;
trace_x86_fpu_regs_deactivated(old_fpu);
-
- /* Don't change CR0.TS if we just switch! */
- if (fpu.preload) {
- new_fpu->counter++;
- __fpregs_activate(new_fpu);
- trace_x86_fpu_regs_activated(new_fpu);
- prefetch(&new_fpu->state);
- } else {
- __fpregs_deactivate_hw();
- }
- } else {
- old_fpu->counter = 0;
+ } else
old_fpu->last_cpu = -1;
- if (fpu.preload) {
- new_fpu->counter++;
- if (fpu_want_lazy_restore(new_fpu, cpu))
- fpu.preload = 0;
- else
- prefetch(&new_fpu->state);
- fpregs_activate(new_fpu);
- }
- }
- return fpu;
}
/*
@@ -638,15 +579,19 @@ switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
*/
/*
- * By the time this gets called, we've already cleared CR0.TS and
- * given the process the FPU if we are going to preload the FPU
- * state - all we need to do is to conditionally restore the register
- * state itself.
+ * Set up the userspace FPU context for the new task, if the task
+ * has used the FPU.
*/
-static inline void switch_fpu_finish(struct fpu *new_fpu, fpu_switch_t fpu_switch)
+static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
{
- if (fpu_switch.preload)
- copy_kernel_to_fpregs(&new_fpu->state);
+ bool preload = static_cpu_has(X86_FEATURE_FPU) &&
+ new_fpu->fpstate_active;
+
+ if (preload) {
+ if (!fpregs_state_valid(new_fpu, cpu))
+ copy_kernel_to_fpregs(&new_fpu->state);
+ fpregs_activate(new_fpu);
+ }
}
/*
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index 48df486b02f9..3c80f5b9c09d 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -322,17 +322,6 @@ struct fpu {
unsigned char fpregs_active;
/*
- * @counter:
- *
- * This counter contains the number of consecutive context switches
- * during which the FPU stays used. If this is over a threshold, the
- * lazy FPU restore logic becomes eager, to save the trap overhead.
- * This is an unsigned char so that after 256 iterations the counter
- * wraps and the context switch behavior turns lazy again; this is to
- * deal with bursty apps that only use the FPU for a short time:
- */
- unsigned char counter;
- /*
* @state:
*
* In-memory copy of all FPU registers that we save/restore
@@ -340,29 +329,6 @@ struct fpu {
* the registers in the FPU are more recent than this state
* copy. If the task context-switches away then they get
* saved here and represent the FPU state.
- *
- * After context switches there may be a (short) time period
- * during which the in-FPU hardware registers are unchanged
- * and still perfectly match this state, if the tasks
- * scheduled afterwards are not using the FPU.
- *
- * This is the 'lazy restore' window of optimization, which
- * we track though 'fpu_fpregs_owner_ctx' and 'fpu->last_cpu'.
- *
- * We detect whether a subsequent task uses the FPU via setting
- * CR0::TS to 1, which causes any FPU use to raise a #NM fault.
- *
- * During this window, if the task gets scheduled again, we
- * might be able to skip having to do a restore from this
- * memory buffer to the hardware registers - at the cost of
- * incurring the overhead of #NM fault traps.
- *
- * Note that on modern CPUs that support the XSAVEOPT (or other
- * optimized XSAVE instructions), we don't use #NM traps anymore,
- * as the hardware can track whether FPU registers need saving
- * or not. On such CPUs we activate the non-lazy ('eagerfpu')
- * logic, which unconditionally saves/restores all FPU state
- * across context switches. (if FPU state exists.)
*/
union fpregs_state state;
/*
diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/xstate.h
index 430bacf73074..1b2799e0699a 100644
--- a/arch/x86/include/asm/fpu/xstate.h
+++ b/arch/x86/include/asm/fpu/xstate.h
@@ -21,21 +21,16 @@
/* Supervisor features */
#define XFEATURE_MASK_SUPERVISOR (XFEATURE_MASK_PT)
-/* Supported features which support lazy state saving */
-#define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \
+/* All currently supported features */
+#define XCNTXT_MASK (XFEATURE_MASK_FP | \
XFEATURE_MASK_SSE | \
XFEATURE_MASK_YMM | \
XFEATURE_MASK_OPMASK | \
XFEATURE_MASK_ZMM_Hi256 | \
- XFEATURE_MASK_Hi16_ZMM)
-
-/* Supported features which require eager state saving */
-#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | \
- XFEATURE_MASK_BNDCSR | \
- XFEATURE_MASK_PKRU)
-
-/* All currently supported features */
-#define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
+ XFEATURE_MASK_Hi16_ZMM | \
+ XFEATURE_MASK_PKRU | \
+ XFEATURE_MASK_BNDREGS | \
+ XFEATURE_MASK_BNDCSR)
#ifdef CONFIG_X86_64
#define REX_PREFIX "0x48, "
diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h
deleted file mode 100644
index c5d1785373ed..000000000000
--- a/arch/x86/include/asm/idle.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _ASM_X86_IDLE_H
-#define _ASM_X86_IDLE_H
-
-#define IDLE_START 1
-#define IDLE_END 2
-
-struct notifier_block;
-void idle_notifier_register(struct notifier_block *n);
-void idle_notifier_unregister(struct notifier_block *n);
-
-#ifdef CONFIG_X86_64
-void enter_idle(void);
-void exit_idle(void);
-#else /* !CONFIG_X86_64 */
-static inline void enter_idle(void) { }
-static inline void exit_idle(void) { }
-static inline void __exit_idle(void) { }
-#endif /* CONFIG_X86_64 */
-
-void amd_e400_remove_cpu(int cpu);
-
-#endif /* _ASM_X86_IDLE_H */
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index d31881188431..29a594a3b82a 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -21,7 +21,6 @@ enum die_val {
DIE_NMIUNKNOWN,
};
-extern void printk_address(unsigned long address);
extern void die(const char *, struct pt_regs *,long);
extern int __must_check __die(const char *, struct pt_regs *, long);
extern void show_stack_regs(struct pt_regs *regs);
diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
index c2b8d24a235c..d74747b031ec 100644
--- a/arch/x86/include/asm/kvm_page_track.h
+++ b/arch/x86/include/asm/kvm_page_track.h
@@ -29,9 +29,20 @@ struct kvm_page_track_notifier_node {
* @gpa: the physical address written by guest.
* @new: the data was written to the address.
* @bytes: the written length.
+ * @node: this node
*/
void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
- int bytes);
+ int bytes, struct kvm_page_track_notifier_node *node);
+ /*
+ * It is called when memory slot is being moved or removed
+ * users can drop write-protection for the pages in that memory slot
+ *
+ * @kvm: the kvm where memory slot being moved or removed
+ * @slot: the memory slot being moved or removed
+ * @node: this node
+ */
+ void (*track_flush_slot)(struct kvm *kvm, struct kvm_memory_slot *slot,
+ struct kvm_page_track_notifier_node *node);
};
void kvm_page_track_init(struct kvm *kvm);
@@ -58,4 +69,5 @@ kvm_page_track_unregister_notifier(struct kvm *kvm,
struct kvm_page_track_notifier_node *n);
void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
int bytes);
+void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot);
#endif
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h
index ef01fef3eebc..6c119cfae218 100644
--- a/arch/x86/include/asm/lguest_hcall.h
+++ b/arch/x86/include/asm/lguest_hcall.h
@@ -9,7 +9,6 @@
#define LHCALL_FLUSH_TLB 5
#define LHCALL_LOAD_IDT_ENTRY 6
#define LHCALL_SET_STACK 7
-#define LHCALL_TS 8
#define LHCALL_SET_CLOCKEVENT 9
#define LHCALL_HALT 10
#define LHCALL_SET_PMD 13
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 9bd7ff5ffbcc..5132f2a6c0a2 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -252,8 +252,10 @@ static inline void cmci_recheck(void) {}
#ifdef CONFIG_X86_MCE_AMD
void mce_amd_feature_init(struct cpuinfo_x86 *c);
+int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr);
#else
static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
+static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) { return -EINVAL; };
#endif
int mce_available(struct cpuinfo_x86 *c);
@@ -293,9 +295,7 @@ void do_machine_check(struct pt_regs *, long);
/*
* Threshold handler
*/
-
extern void (*mce_threshold_vector)(void);
-extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
/* Deferred error interrupt handler */
extern void (*deferred_error_int_vector)(void);
@@ -356,27 +356,31 @@ enum smca_bank_types {
N_SMCA_BANK_TYPES
};
-struct smca_bank_name {
- const char *name; /* Short name for sysfs */
- const char *long_name; /* Long name for pretty-printing */
-};
-
-extern struct smca_bank_name smca_bank_names[N_SMCA_BANK_TYPES];
+#define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype))
-#define HWID_MCATYPE(hwid, mcatype) ((hwid << 16) | mcatype)
-
-struct smca_hwid_mcatype {
+struct smca_hwid {
unsigned int bank_type; /* Use with smca_bank_types for easy indexing. */
u32 hwid_mcatype; /* (hwid,mcatype) tuple */
u32 xec_bitmap; /* Bitmap of valid ExtErrorCodes; current max is 21. */
};
-struct smca_bank_info {
- struct smca_hwid_mcatype *type;
- u32 type_instance;
+struct smca_bank {
+ struct smca_hwid *hwid;
+ /* Instance ID */
+ u32 id;
};
-extern struct smca_bank_info smca_banks[MAX_NR_BANKS];
+extern struct smca_bank smca_banks[MAX_NR_BANKS];
+
+extern const char *smca_get_long_name(enum smca_bank_types t);
+
+extern int mce_threshold_create_device(unsigned int cpu);
+extern int mce_threshold_remove_device(unsigned int cpu);
+
+#else
+
+static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };
+static inline int mce_threshold_remove_device(unsigned int cpu) { return 0; };
#endif
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index da0d81fa0b54..38711df3bcb5 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -20,6 +20,15 @@ do { \
(u32)((u64)(val)), \
(u32)((u64)(val) >> 32))
+struct ucode_patch {
+ struct list_head plist;
+ void *data; /* Intel uses only this one */
+ u32 patch_id;
+ u16 equiv_cpu;
+};
+
+extern struct list_head microcode_cache;
+
struct cpu_signature {
unsigned int sig;
unsigned int pf;
@@ -55,12 +64,7 @@ struct ucode_cpu_info {
void *mc;
};
extern struct ucode_cpu_info ucode_cpu_info[];
-
-#ifdef CONFIG_MICROCODE
-int __init microcode_init(void);
-#else
-static inline int __init microcode_init(void) { return 0; };
-#endif
+struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa);
#ifdef CONFIG_MICROCODE_INTEL
extern struct microcode_ops * __init init_intel_microcode(void);
@@ -131,11 +135,13 @@ static inline unsigned int x86_cpuid_family(void)
}
#ifdef CONFIG_MICROCODE
+int __init microcode_init(void);
extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(void);
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
#else
+static inline int __init microcode_init(void) { return 0; };
static inline void __init load_ucode_bsp(void) { }
static inline void load_ucode_ap(void) { }
static inline void reload_early_microcode(void) { }
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 15eb75484cc0..3e3e20be829a 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -40,38 +40,18 @@ struct microcode_amd {
unsigned int mpb[0];
};
-static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
- unsigned int sig)
-{
- int i = 0;
-
- if (!equiv_cpu_table)
- return 0;
-
- while (equiv_cpu_table[i].installed_cpu != 0) {
- if (sig == equiv_cpu_table[i].installed_cpu)
- return equiv_cpu_table[i].equiv_cpu;
-
- i++;
- }
- return 0;
-}
-
-extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
-extern int apply_microcode_amd(int cpu);
-extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
-
#define PATCH_MAX_SIZE PAGE_SIZE
#ifdef CONFIG_MICROCODE_AMD
extern void __init load_ucode_amd_bsp(unsigned int family);
-extern void load_ucode_amd_ap(void);
-extern int __init save_microcode_in_initrd_amd(void);
+extern void load_ucode_amd_ap(unsigned int family);
+extern int __init save_microcode_in_initrd_amd(unsigned int family);
void reload_ucode_amd(void);
#else
static inline void __init load_ucode_amd_bsp(unsigned int family) {}
-static inline void load_ucode_amd_ap(void) {}
-static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
+static inline void load_ucode_amd_ap(unsigned int family) {}
+static inline int __init
+save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
void reload_ucode_amd(void) {}
#endif
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
index 5e69154c9f07..195becc6f780 100644
--- a/arch/x86/include/asm/microcode_intel.h
+++ b/arch/x86/include/asm/microcode_intel.h
@@ -52,10 +52,6 @@ struct extended_sigtable {
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
-extern int has_newer_microcode(void *mc, unsigned int csig, int cpf, int rev);
-extern int microcode_sanity_check(void *mc, int print_err);
-extern int find_matching_signature(void *mc, unsigned int csig, int cpf);
-
#ifdef CONFIG_MICROCODE_INTEL
extern void __init load_ucode_intel_bsp(void);
extern void load_ucode_intel_ap(void);
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 8e0a9fe86de4..306c7e12af55 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -47,7 +47,7 @@ struct ldt_struct {
* allocations, but it's not worth trying to optimize.
*/
struct desc_struct *entries;
- int size;
+ unsigned int size;
};
/*
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 78f3760ca1f2..710273c617b8 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -37,6 +37,10 @@
#define EFER_FFXSR (1<<_EFER_FFXSR)
/* Intel MSRs. Some also available on other CPUs */
+
+#define MSR_PPIN_CTL 0x0000004e
+#define MSR_PPIN 0x0000004f
+
#define MSR_IA32_PERFCTR0 0x000000c1
#define MSR_IA32_PERFCTR1 0x000000c2
#define MSR_FSB_FREQ 0x000000cd
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index b5fee97813cd..db0b90c3b03e 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -70,14 +70,14 @@ extern struct tracepoint __tracepoint_read_msr;
extern struct tracepoint __tracepoint_write_msr;
extern struct tracepoint __tracepoint_rdpmc;
#define msr_tracepoint_active(t) static_key_false(&(t).key)
-extern void do_trace_write_msr(unsigned msr, u64 val, int failed);
-extern void do_trace_read_msr(unsigned msr, u64 val, int failed);
-extern void do_trace_rdpmc(unsigned msr, u64 val, int failed);
+extern void do_trace_write_msr(unsigned int msr, u64 val, int failed);
+extern void do_trace_read_msr(unsigned int msr, u64 val, int failed);
+extern void do_trace_rdpmc(unsigned int msr, u64 val, int failed);
#else
#define msr_tracepoint_active(t) false
-static inline void do_trace_write_msr(unsigned msr, u64 val, int failed) {}
-static inline void do_trace_read_msr(unsigned msr, u64 val, int failed) {}
-static inline void do_trace_rdpmc(unsigned msr, u64 val, int failed) {}
+static inline void do_trace_write_msr(unsigned int msr, u64 val, int failed) {}
+static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {}
+static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {}
#endif
static inline unsigned long long native_read_msr(unsigned int msr)
@@ -115,22 +115,36 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
}
/* Can be uninlined because referenced by paravirt */
-notrace static inline void native_write_msr(unsigned int msr,
- unsigned low, unsigned high)
+static inline void notrace
+__native_write_msr_notrace(unsigned int msr, u32 low, u32 high)
{
asm volatile("1: wrmsr\n"
"2:\n"
_ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
: : "c" (msr), "a"(low), "d" (high) : "memory");
+}
+
+/* Can be uninlined because referenced by paravirt */
+static inline void notrace
+native_write_msr(unsigned int msr, u32 low, u32 high)
+{
+ __native_write_msr_notrace(msr, low, high);
if (msr_tracepoint_active(__tracepoint_write_msr))
do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
}
+static inline void
+wrmsr_notrace(unsigned int msr, u32 low, u32 high)
+{
+ __native_write_msr_notrace(msr, low, high);
+}
+
/* Can be uninlined because referenced by paravirt */
-notrace static inline int native_write_msr_safe(unsigned int msr,
- unsigned low, unsigned high)
+static inline int notrace
+native_write_msr_safe(unsigned int msr, u32 low, u32 high)
{
int err;
+
asm volatile("2: wrmsr ; xor %[err],%[err]\n"
"1:\n\t"
".section .fixup,\"ax\"\n\t"
@@ -223,7 +237,7 @@ do { \
(void)((high) = (u32)(__val >> 32)); \
} while (0)
-static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
+static inline void wrmsr(unsigned int msr, u32 low, u32 high)
{
native_write_msr(msr, low, high);
}
@@ -231,13 +245,13 @@ static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
#define rdmsrl(msr, val) \
((val) = native_read_msr((msr)))
-static inline void wrmsrl(unsigned msr, u64 val)
+static inline void wrmsrl(unsigned int msr, u64 val)
{
native_write_msr(msr, (u32)(val & 0xffffffffULL), (u32)(val >> 32));
}
/* wrmsr with exception handling */
-static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+static inline int wrmsr_safe(unsigned int msr, u32 low, u32 high)
{
return native_write_msr_safe(msr, low, high);
}
@@ -252,7 +266,7 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
__err; \
})
-static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
+static inline int rdmsrl_safe(unsigned int msr, unsigned long long *p)
{
int err;
@@ -325,12 +339,12 @@ static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
struct msr *msrs)
{
- rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
+ rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
}
static inline void wrmsr_on_cpus(const struct cpumask *m, u32 msr_no,
struct msr *msrs)
{
- wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
+ wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
}
static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
u32 *l, u32 *h)
diff --git a/arch/x86/include/asm/mutex.h b/arch/x86/include/asm/mutex.h
deleted file mode 100644
index 7d3a48275394..000000000000
--- a/arch/x86/include/asm/mutex.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifdef CONFIG_X86_32
-# include <asm/mutex_32.h>
-#else
-# include <asm/mutex_64.h>
-#endif
diff --git a/arch/x86/include/asm/mutex_32.h b/arch/x86/include/asm/mutex_32.h
deleted file mode 100644
index e9355a84fc67..000000000000
--- a/arch/x86/include/asm/mutex_32.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Assembly implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- *
- * started by Ingo Molnar:
- *
- * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#ifndef _ASM_X86_MUTEX_32_H
-#define _ASM_X86_MUTEX_32_H
-
-#include <asm/alternative.h>
-
-/**
- * __mutex_fastpath_lock - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- * @fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fn> if it
- * wasn't 1 originally. This function MUST leave the value lower than 1
- * even when the "1" assertion wasn't true.
- */
-#define __mutex_fastpath_lock(count, fail_fn) \
-do { \
- unsigned int dummy; \
- \
- typecheck(atomic_t *, count); \
- typecheck_fn(void (*)(atomic_t *), fail_fn); \
- \
- asm volatile(LOCK_PREFIX " decl (%%eax)\n" \
- " jns 1f \n" \
- " call " #fail_fn "\n" \
- "1:\n" \
- : "=a" (dummy) \
- : "a" (count) \
- : "memory", "ecx", "edx"); \
-} while (0)
-
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int __mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(atomic_dec_return(count) < 0))
- return -1;
- else
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 0
- *
- * try to promote the mutex from 0 to 1. if it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value
- * to 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-#define __mutex_fastpath_unlock(count, fail_fn) \
-do { \
- unsigned int dummy; \
- \
- typecheck(atomic_t *, count); \
- typecheck_fn(void (*)(atomic_t *), fail_fn); \
- \
- asm volatile(LOCK_PREFIX " incl (%%eax)\n" \
- " jg 1f\n" \
- " call " #fail_fn "\n" \
- "1:\n" \
- : "=a" (dummy) \
- : "a" (count) \
- : "memory", "ecx", "edx"); \
-} while (0)
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- */
-static inline int __mutex_fastpath_trylock(atomic_t *count,
- int (*fail_fn)(atomic_t *))
-{
- /* cmpxchg because it never induces a false contention state. */
- if (likely(atomic_read(count) == 1 && atomic_cmpxchg(count, 1, 0) == 1))
- return 1;
-
- return 0;
-}
-
-#endif /* _ASM_X86_MUTEX_32_H */
diff --git a/arch/x86/include/asm/mutex_64.h b/arch/x86/include/asm/mutex_64.h
deleted file mode 100644
index d9850758464e..000000000000
--- a/arch/x86/include/asm/mutex_64.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Assembly implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- *
- * started by Ingo Molnar:
- *
- * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#ifndef _ASM_X86_MUTEX_64_H
-#define _ASM_X86_MUTEX_64_H
-
-/**
- * __mutex_fastpath_lock - decrement and call function if negative
- * @v: pointer of type atomic_t
- * @fail_fn: function to call if the result is negative
- *
- * Atomically decrements @v and calls <fail_fn> if the result is negative.
- */
-#ifdef CC_HAVE_ASM_GOTO
-static inline void __mutex_fastpath_lock(atomic_t *v,
- void (*fail_fn)(atomic_t *))
-{
- asm_volatile_goto(LOCK_PREFIX " decl %0\n"
- " jns %l[exit]\n"
- : : "m" (v->counter)
- : "memory", "cc"
- : exit);
- fail_fn(v);
-exit:
- return;
-}
-#else
-#define __mutex_fastpath_lock(v, fail_fn) \
-do { \
- unsigned long dummy; \
- \
- typecheck(atomic_t *, v); \
- typecheck_fn(void (*)(atomic_t *), fail_fn); \
- \
- asm volatile(LOCK_PREFIX " decl (%%rdi)\n" \
- " jns 1f \n" \
- " call " #fail_fn "\n" \
- "1:" \
- : "=D" (dummy) \
- : "D" (v) \
- : "rax", "rsi", "rdx", "rcx", \
- "r8", "r9", "r10", "r11", "memory"); \
-} while (0)
-#endif
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int __mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(atomic_dec_return(count) < 0))
- return -1;
- else
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - increment and call function if nonpositive
- * @v: pointer of type atomic_t
- * @fail_fn: function to call if the result is nonpositive
- *
- * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
- */
-#ifdef CC_HAVE_ASM_GOTO
-static inline void __mutex_fastpath_unlock(atomic_t *v,
- void (*fail_fn)(atomic_t *))
-{
- asm_volatile_goto(LOCK_PREFIX " incl %0\n"
- " jg %l[exit]\n"
- : : "m" (v->counter)
- : "memory", "cc"
- : exit);
- fail_fn(v);
-exit:
- return;
-}
-#else
-#define __mutex_fastpath_unlock(v, fail_fn) \
-do { \
- unsigned long dummy; \
- \
- typecheck(atomic_t *, v); \
- typecheck_fn(void (*)(atomic_t *), fail_fn); \
- \
- asm volatile(LOCK_PREFIX " incl (%%rdi)\n" \
- " jg 1f\n" \
- " call " #fail_fn "\n" \
- "1:" \
- : "=D" (dummy) \
- : "D" (v) \
- : "rax", "rsi", "rdx", "rcx", \
- "r8", "r9", "r10", "r11", "memory"); \
-} while (0)
-#endif
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: fallback function
- *
- * Change the count from 1 to 0 and return 1 (success), or return 0 (failure)
- * if it wasn't 1 originally. [the fallback function is never used on
- * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.]
- */
-static inline int __mutex_fastpath_trylock(atomic_t *count,
- int (*fail_fn)(atomic_t *))
-{
- if (likely(atomic_read(count) == 1 && atomic_cmpxchg(count, 1, 0) == 1))
- return 1;
-
- return 0;
-}
-
-#endif /* _ASM_X86_MUTEX_64_H */
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index ce932812f142..1eea6ca40694 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -41,11 +41,6 @@ static inline void set_debugreg(unsigned long val, int reg)
PVOP_VCALL2(pv_cpu_ops.set_debugreg, reg, val);
}
-static inline void clts(void)
-{
- PVOP_VCALL0(pv_cpu_ops.clts);
-}
-
static inline unsigned long read_cr0(void)
{
return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr0);
@@ -678,6 +673,11 @@ static __always_inline void pv_kick(int cpu)
PVOP_VCALL1(pv_lock_ops.kick, cpu);
}
+static __always_inline bool pv_vcpu_is_preempted(int cpu)
+{
+ return PVOP_CALLEE1(bool, pv_lock_ops.vcpu_is_preempted, cpu);
+}
+
#endif /* SMP && PARAVIRT_SPINLOCKS */
#ifdef CONFIG_X86_32
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 0f400c0e4979..bb2de45a60f2 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -103,8 +103,6 @@ struct pv_cpu_ops {
unsigned long (*get_debugreg)(int regno);
void (*set_debugreg)(int regno, unsigned long value);
- void (*clts)(void);
-
unsigned long (*read_cr0)(void);
void (*write_cr0)(unsigned long);
@@ -310,6 +308,8 @@ struct pv_lock_ops {
void (*wait)(u8 *ptr, u8 val);
void (*kick)(int cpu);
+
+ struct paravirt_callee_save vcpu_is_preempted;
};
/* This contains all the paravirt structures: we get a convenient
@@ -508,6 +508,18 @@ int paravirt_disable_iospace(void);
#define PVOP_TEST_NULL(op) ((void)op)
#endif
+#define PVOP_RETMASK(rettype) \
+ ({ unsigned long __mask = ~0UL; \
+ switch (sizeof(rettype)) { \
+ case 1: __mask = 0xffUL; break; \
+ case 2: __mask = 0xffffUL; break; \
+ case 4: __mask = 0xffffffffUL; break; \
+ default: break; \
+ } \
+ __mask; \
+ })
+
+
#define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \
pre, post, ...) \
({ \
@@ -535,7 +547,7 @@ int paravirt_disable_iospace(void);
paravirt_clobber(clbr), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
- __ret = (rettype)__eax; \
+ __ret = (rettype)(__eax & PVOP_RETMASK(rettype)); \
} \
__ret; \
})
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 84f58de08c2b..9fa03604b2b3 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -507,17 +507,6 @@ do { \
#endif
-/* This is not atomic against other CPUs -- CPU preemption needs to be off */
-#define x86_test_and_clear_bit_percpu(bit, var) \
-({ \
- bool old__; \
- asm volatile("btr %2,"__percpu_arg(1)"\n\t" \
- CC_SET(c) \
- : CC_OUT(c) (old__), "+m" (var) \
- : "dIr" (bit)); \
- old__; \
-})
-
static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,
const unsigned long __percpu *addr)
{
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index 17f218645701..ec1f3c651150 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -24,7 +24,13 @@ static __always_inline int preempt_count(void)
static __always_inline void preempt_count_set(int pc)
{
- raw_cpu_write_4(__preempt_count, pc);
+ int old, new;
+
+ do {
+ old = raw_cpu_read_4(__preempt_count);
+ new = (old & PREEMPT_NEED_RESCHED) |
+ (pc & ~PREEMPT_NEED_RESCHED);
+ } while (raw_cpu_cmpxchg_4(__preempt_count, old, new) != old);
}
/*
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 984a7bf17f6a..6aa741fbe1df 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -137,6 +137,17 @@ struct cpuinfo_x86 {
u32 microcode;
};
+struct cpuid_regs {
+ u32 eax, ebx, ecx, edx;
+};
+
+enum cpuid_regs_idx {
+ CPUID_EAX = 0,
+ CPUID_EBX,
+ CPUID_ECX,
+ CPUID_EDX,
+};
+
#define X86_VENDOR_INTEL 0
#define X86_VENDOR_CYRIX 1
#define X86_VENDOR_AMD 2
@@ -178,6 +189,9 @@ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
void print_cpu_msr(struct cpuinfo_x86 *);
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+extern u32 get_scattered_cpuid_leaf(unsigned int level,
+ unsigned int sub_leaf,
+ enum cpuid_regs_idx reg);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
@@ -588,8 +602,6 @@ static __always_inline void cpu_relax(void)
rep_nop();
}
-#define cpu_relax_lowlatency() cpu_relax()
-
/* Stop speculative execution and prefetching of modified code. */
static inline void sync_core(void)
{
@@ -621,10 +633,9 @@ static inline void sync_core(void)
}
extern void select_idle_routine(const struct cpuinfo_x86 *c);
-extern void init_amd_e400_c1e_mask(void);
+extern void amd_e400_c1e_apic_setup(void);
extern unsigned long boot_option_idle_override;
-extern bool amd_e400_c1e_detected;
enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
IDLE_POLL};
diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h
index eaba08076030..c343ab52579f 100644
--- a/arch/x86/include/asm/qspinlock.h
+++ b/arch/x86/include/asm/qspinlock.h
@@ -32,6 +32,12 @@ static inline void queued_spin_unlock(struct qspinlock *lock)
{
pv_queued_spin_unlock(lock);
}
+
+#define vcpu_is_preempted vcpu_is_preempted
+static inline bool vcpu_is_preempted(int cpu)
+{
+ return pv_vcpu_is_preempted(cpu);
+}
#else
static inline void queued_spin_unlock(struct qspinlock *lock)
{
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 19a2224f9e16..12af3e35edfa 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -6,11 +6,6 @@
#include <asm/nops.h>
-static inline void native_clts(void)
-{
- asm volatile("clts");
-}
-
/*
* Volatile isn't enough to prevent the compiler from reordering the
* read/write functions for the control registers and messing everything up.
@@ -208,16 +203,8 @@ static inline void load_gs_index(unsigned selector)
#endif
-/* Clear the 'TS' bit */
-static inline void clts(void)
-{
- native_clts();
-}
-
#endif/* CONFIG_PARAVIRT */
-#define stts() write_cr0(read_cr0() | X86_CR0_TS)
-
static inline void clflush(volatile void *__p)
{
asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 37f2e0b377ad..a3269c897ec5 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -30,8 +30,7 @@ bool in_task_stack(unsigned long *stack, struct task_struct *task,
int get_stack_info(unsigned long *stack, struct task_struct *task,
struct stack_info *info, unsigned long *visit_mask);
-void stack_type_str(enum stack_type type, const char **begin,
- const char **end);
+const char *stack_type_name(enum stack_type type);
static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
{
@@ -43,8 +42,6 @@ static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
addr + len > begin && addr + len <= end);
}
-extern int kstack_depth_to_print;
-
#ifdef CONFIG_X86_32
#define STACKSLOTS_PER_LINE 8
#else
@@ -86,9 +83,6 @@ get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, char *log_lvl);
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *sp, char *log_lvl);
-
extern unsigned int code_bytes;
/* The form of the top of the frame on the stack */
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index cf75871d2f81..6358a85e2270 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -146,4 +146,36 @@ struct pci_bus;
int x86_pci_root_bus_node(int bus);
void x86_pci_root_bus_resources(int bus, struct list_head *resources);
+extern bool x86_topology_update;
+
+#ifdef CONFIG_SCHED_MC_PRIO
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
+extern unsigned int __read_mostly sysctl_sched_itmt_enabled;
+
+/* Interface to set priority of a cpu */
+void sched_set_itmt_core_prio(int prio, int core_cpu);
+
+/* Interface to notify scheduler that system supports ITMT */
+int sched_set_itmt_support(void);
+
+/* Interface to notify scheduler that system revokes ITMT support */
+void sched_clear_itmt_support(void);
+
+#else /* CONFIG_SCHED_MC_PRIO */
+
+#define sysctl_sched_itmt_enabled 0
+static inline void sched_set_itmt_core_prio(int prio, int core_cpu)
+{
+}
+static inline int sched_set_itmt_support(void)
+{
+ return 0;
+}
+static inline void sched_clear_itmt_support(void)
+{
+}
+#endif /* CONFIG_SCHED_MC_PRIO */
+
#endif /* _ASM_X86_TOPOLOGY_H */
diff --git a/arch/x86/include/asm/trace/fpu.h b/arch/x86/include/asm/trace/fpu.h
index 9217ab1f5bf6..342e59789fcd 100644
--- a/arch/x86/include/asm/trace/fpu.h
+++ b/arch/x86/include/asm/trace/fpu.h
@@ -14,7 +14,6 @@ DECLARE_EVENT_CLASS(x86_fpu,
__field(struct fpu *, fpu)
__field(bool, fpregs_active)
__field(bool, fpstate_active)
- __field(int, counter)
__field(u64, xfeatures)
__field(u64, xcomp_bv)
),
@@ -23,17 +22,15 @@ DECLARE_EVENT_CLASS(x86_fpu,
__entry->fpu = fpu;
__entry->fpregs_active = fpu->fpregs_active;
__entry->fpstate_active = fpu->fpstate_active;
- __entry->counter = fpu->counter;
if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
__entry->xfeatures = fpu->state.xsave.header.xfeatures;
__entry->xcomp_bv = fpu->state.xsave.header.xcomp_bv;
}
),
- TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d counter: %d xfeatures: %llx xcomp_bv: %llx",
+ TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d xfeatures: %llx xcomp_bv: %llx",
__entry->fpu,
__entry->fpregs_active,
__entry->fpstate_active,
- __entry->counter,
__entry->xfeatures,
__entry->xcomp_bv
)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index faf3687f1035..ea148313570f 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -68,6 +68,12 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
__chk_range_not_ok((unsigned long __force)(addr), size, limit); \
})
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+# define WARN_ON_IN_IRQ() WARN_ON_ONCE(!in_task())
+#else
+# define WARN_ON_IN_IRQ()
+#endif
+
/**
* access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
@@ -88,8 +94,11 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
* checks that the pointer is in the user space range - after calling
* this function, memory access functions may still return -EFAULT.
*/
-#define access_ok(type, addr, size) \
- likely(!__range_not_ok(addr, size, user_addr_max()))
+#define access_ok(type, addr, size) \
+({ \
+ WARN_ON_IN_IRQ(); \
+ likely(!__range_not_ok(addr, size, user_addr_max())); \
+})
/*
* These are the main single-value transfer routines. They automatically
diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 46de9ac4b990..c5a7f3a930dd 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -13,6 +13,7 @@ struct unwind_state {
int graph_idx;
#ifdef CONFIG_FRAME_POINTER
unsigned long *bp;
+ struct pt_regs *regs;
#else
unsigned long *sp;
#endif
@@ -47,7 +48,15 @@ unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
if (unwind_done(state))
return NULL;
- return state->bp + 1;
+ return state->regs ? &state->regs->ip : state->bp + 1;
+}
+
+static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
+{
+ if (unwind_done(state))
+ return NULL;
+
+ return state->regs;
}
#else /* !CONFIG_FRAME_POINTER */
@@ -58,6 +67,11 @@ unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
return NULL;
}
+static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
+{
+ return NULL;
+}
+
#endif /* CONFIG_FRAME_POINTER */
#endif /* _ASM_X86_UNWIND_H */
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index e728699db774..3a01996db58f 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -89,8 +89,13 @@ static inline unsigned int __getcpu(void)
* works on all CPUs. This is volatile so that it orders
* correctly wrt barrier() and to keep gcc from cleverly
* hoisting it out of the calling function.
+ *
+ * If RDPID is available, use it.
*/
- asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+ alternative_io ("lsl %[p],%[seg]",
+ ".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */
+ X86_FEATURE_RDPID,
+ [p] "=a" (p), [seg] "r" (__PER_CPU_SEG));
return p;
}
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c18ce67495fa..b10bf319ed20 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -7,6 +7,7 @@
#define SETUP_DTB 2
#define SETUP_PCI 3
#define SETUP_EFI 4
+#define SETUP_APPLE_PROPERTIES 5
/* ram_size flags */
#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
index 94dc8ca434e0..1421a6585126 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -45,7 +45,9 @@ struct kvm_steal_time {
__u64 steal;
__u32 version;
__u32 flags;
- __u32 pad[12];
+ __u8 preempted;
+ __u8 u8_pad[3];
+ __u32 pad[11];
};
#define KVM_STEAL_ALIGNMENT_BITS 5
diff --git a/arch/x86/include/uapi/asm/mce.h b/arch/x86/include/uapi/asm/mce.h
index 69a6e07e3149..eb6247a7009b 100644
--- a/arch/x86/include/uapi/asm/mce.h
+++ b/arch/x86/include/uapi/asm/mce.h
@@ -28,6 +28,7 @@ struct mce {
__u64 mcgcap; /* MCGCAP MSR: machine check capabilities of CPU */
__u64 synd; /* MCA_SYND MSR: only valid on SMCA systems */
__u64 ipid; /* MCA_IPID MSR: only valid on SMCA systems */
+ __u64 ppin; /* Protected Processor Inventory Number */
};
#define MCE_GET_RECORD_LEN _IOR('M', 1, int)
diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h
index ae135de547f5..835aa51c7f6e 100644
--- a/arch/x86/include/uapi/asm/prctl.h
+++ b/arch/x86/include/uapi/asm/prctl.h
@@ -6,10 +6,8 @@
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
-#ifdef CONFIG_CHECKPOINT_RESTORE
-# define ARCH_MAP_VDSO_X32 0x2001
-# define ARCH_MAP_VDSO_32 0x2002
-# define ARCH_MAP_VDSO_64 0x2003
-#endif
+#define ARCH_MAP_VDSO_X32 0x2001
+#define ARCH_MAP_VDSO_32 0x2002
+#define ARCH_MAP_VDSO_64 0x2003
#endif /* _ASM_X86_PRCTL_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 79076d75bdbf..05110c1097ae 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_EFI) += sysfb_efi.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
obj-$(CONFIG_TRACING) += tracepoint.o
+obj-$(CONFIG_SCHED_MC_PRIO) += itmt.o
ifdef CONFIG_FRAME_POINTER
obj-y += unwind_frame.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 931ced8ca345..4764fa56924d 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -76,6 +76,7 @@ int acpi_fix_pin2_polarity __initdata;
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#endif
+#ifdef CONFIG_X86_IO_APIC
/*
* Locks related to IOAPIC hotplug
* Hotplug side:
@@ -88,6 +89,7 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
* ->ioapic_lock
*/
static DEFINE_MUTEX(acpi_ioapic_lock);
+#endif
/* --------------------------------------------------------------------------
Boot-time Configuration
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 169963f471bb..50b8ed0317a3 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -109,6 +109,15 @@ ENTRY(do_suspend_lowlevel)
movq pt_regs_r14(%rax), %r14
movq pt_regs_r15(%rax), %r15
+#ifdef CONFIG_KASAN
+ /*
+ * The suspend path may have poisoned some areas deeper in the stack,
+ * which we now need to unpoison.
+ */
+ movq %rsp, %rdi
+ call kasan_unpoison_task_stack_below
+#endif
+
xorl %eax, %eax
addq $8, %rsp
FRAME_END
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 4fdf6230d93c..458da8509b75 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -13,8 +13,20 @@
#include <linux/spinlock.h>
#include <asm/amd_nb.h>
+#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450
+#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463
+#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464
+
+/* Protect the PCI config register pairs used for SMN and DF indirect access. */
+static DEFINE_MUTEX(smn_mutex);
+
static u32 *flush_words;
+static const struct pci_device_id amd_root_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
+ {}
+};
+
const struct pci_device_id amd_nb_misc_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
@@ -24,9 +36,10 @@ const struct pci_device_id amd_nb_misc_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{}
};
-EXPORT_SYMBOL(amd_nb_misc_ids);
+EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
static const struct pci_device_id amd_nb_link_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
@@ -34,6 +47,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
{}
};
@@ -44,8 +58,25 @@ const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
{ }
};
-struct amd_northbridge_info amd_northbridges;
-EXPORT_SYMBOL(amd_northbridges);
+static struct amd_northbridge_info amd_northbridges;
+
+u16 amd_nb_num(void)
+{
+ return amd_northbridges.num;
+}
+EXPORT_SYMBOL_GPL(amd_nb_num);
+
+bool amd_nb_has_feature(unsigned int feature)
+{
+ return ((amd_northbridges.flags & feature) == feature);
+}
+EXPORT_SYMBOL_GPL(amd_nb_has_feature);
+
+struct amd_northbridge *node_to_amd_nb(int node)
+{
+ return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
+}
+EXPORT_SYMBOL_GPL(node_to_amd_nb);
static struct pci_dev *next_northbridge(struct pci_dev *dev,
const struct pci_device_id *ids)
@@ -58,13 +89,106 @@ static struct pci_dev *next_northbridge(struct pci_dev *dev,
return dev;
}
+static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
+{
+ struct pci_dev *root;
+ int err = -ENODEV;
+
+ if (node >= amd_northbridges.num)
+ goto out;
+
+ root = node_to_amd_nb(node)->root;
+ if (!root)
+ goto out;
+
+ mutex_lock(&smn_mutex);
+
+ err = pci_write_config_dword(root, 0x60, address);
+ if (err) {
+ pr_warn("Error programming SMN address 0x%x.\n", address);
+ goto out_unlock;
+ }
+
+ err = (write ? pci_write_config_dword(root, 0x64, *value)
+ : pci_read_config_dword(root, 0x64, value));
+ if (err)
+ pr_warn("Error %s SMN address 0x%x.\n",
+ (write ? "writing to" : "reading from"), address);
+
+out_unlock:
+ mutex_unlock(&smn_mutex);
+
+out:
+ return err;
+}
+
+int amd_smn_read(u16 node, u32 address, u32 *value)
+{
+ return __amd_smn_rw(node, address, value, false);
+}
+EXPORT_SYMBOL_GPL(amd_smn_read);
+
+int amd_smn_write(u16 node, u32 address, u32 value)
+{
+ return __amd_smn_rw(node, address, &value, true);
+}
+EXPORT_SYMBOL_GPL(amd_smn_write);
+
+/*
+ * Data Fabric Indirect Access uses FICAA/FICAD.
+ *
+ * Fabric Indirect Configuration Access Address (FICAA): Constructed based
+ * on the device's Instance Id and the PCI function and register offset of
+ * the desired register.
+ *
+ * Fabric Indirect Configuration Access Data (FICAD): There are FICAD LO
+ * and FICAD HI registers but so far we only need the LO register.
+ */
+int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+{
+ struct pci_dev *F4;
+ u32 ficaa;
+ int err = -ENODEV;
+
+ if (node >= amd_northbridges.num)
+ goto out;
+
+ F4 = node_to_amd_nb(node)->link;
+ if (!F4)
+ goto out;
+
+ ficaa = 1;
+ ficaa |= reg & 0x3FC;
+ ficaa |= (func & 0x7) << 11;
+ ficaa |= instance_id << 16;
+
+ mutex_lock(&smn_mutex);
+
+ err = pci_write_config_dword(F4, 0x5C, ficaa);
+ if (err) {
+ pr_warn("Error writing DF Indirect FICAA, FICAA=0x%x\n", ficaa);
+ goto out_unlock;
+ }
+
+ err = pci_read_config_dword(F4, 0x98, lo);
+ if (err)
+ pr_warn("Error reading DF Indirect FICAD LO, FICAA=0x%x.\n", ficaa);
+
+out_unlock:
+ mutex_unlock(&smn_mutex);
+
+out:
+ return err;
+}
+EXPORT_SYMBOL_GPL(amd_df_indirect_read);
+
int amd_cache_northbridges(void)
{
u16 i = 0;
struct amd_northbridge *nb;
- struct pci_dev *misc, *link;
+ struct pci_dev *root, *misc, *link;
- if (amd_nb_num())
+ if (amd_northbridges.num)
return 0;
misc = NULL;
@@ -74,15 +198,17 @@ int amd_cache_northbridges(void)
if (!i)
return -ENODEV;
- nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
+ nb = kcalloc(i, sizeof(struct amd_northbridge), GFP_KERNEL);
if (!nb)
return -ENOMEM;
amd_northbridges.nb = nb;
amd_northbridges.num = i;
- link = misc = NULL;
- for (i = 0; i != amd_nb_num(); i++) {
+ link = misc = root = NULL;
+ for (i = 0; i != amd_northbridges.num; i++) {
+ node_to_amd_nb(i)->root = root =
+ next_northbridge(root, amd_root_ids);
node_to_amd_nb(i)->misc = misc =
next_northbridge(misc, amd_nb_misc_ids);
node_to_amd_nb(i)->link = link =
@@ -139,13 +265,13 @@ struct resource *amd_get_mmconfig_range(struct resource *res)
{
u32 address;
u64 base, msr;
- unsigned segn_busn_bits;
+ unsigned int segn_busn_bits;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return NULL;
/* assume all cpus from fam10h have mmconfig */
- if (boot_cpu_data.x86 < 0x10)
+ if (boot_cpu_data.x86 < 0x10)
return NULL;
address = MSR_FAM10H_MMIO_CONF_BASE;
@@ -226,14 +352,14 @@ static void amd_cache_gart(void)
if (!amd_nb_has_feature(AMD_NB_GART))
return;
- flush_words = kmalloc(amd_nb_num() * sizeof(u32), GFP_KERNEL);
+ flush_words = kmalloc_array(amd_northbridges.num, sizeof(u32), GFP_KERNEL);
if (!flush_words) {
amd_northbridges.flags &= ~AMD_NB_GART;
pr_notice("Cannot initialize GART flush words, GART support disabled\n");
return;
}
- for (i = 0; i != amd_nb_num(); i++)
+ for (i = 0; i != amd_northbridges.num; i++)
pci_read_config_dword(node_to_amd_nb(i)->misc, 0x9c, &flush_words[i]);
}
@@ -246,18 +372,20 @@ void amd_flush_garts(void)
if (!amd_nb_has_feature(AMD_NB_GART))
return;
- /* Avoid races between AGP and IOMMU. In theory it's not needed
- but I'm not sure if the hardware won't lose flush requests
- when another is pending. This whole thing is so expensive anyways
- that it doesn't matter to serialize more. -AK */
+ /*
+ * Avoid races between AGP and IOMMU. In theory it's not needed
+ * but I'm not sure if the hardware won't lose flush requests
+ * when another is pending. This whole thing is so expensive anyways
+ * that it doesn't matter to serialize more. -AK
+ */
spin_lock_irqsave(&gart_lock, flags);
flushed = 0;
- for (i = 0; i < amd_nb_num(); i++) {
+ for (i = 0; i < amd_northbridges.num; i++) {
pci_write_config_dword(node_to_amd_nb(i)->misc, 0x9c,
flush_words[i] | 1);
flushed++;
}
- for (i = 0; i < amd_nb_num(); i++) {
+ for (i = 0; i < amd_northbridges.num; i++) {
u32 w;
/* Make sure the hardware actually executed the flush*/
for (;;) {
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 88c657b057e2..bb47e5eacd44 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -48,7 +48,6 @@
#include <asm/io_apic.h>
#include <asm/desc.h>
#include <asm/hpet.h>
-#include <asm/idle.h>
#include <asm/mtrr.h>
#include <asm/time.h>
#include <asm/smp.h>
@@ -894,11 +893,13 @@ void __init setup_boot_APIC_clock(void)
/* Setup the lapic or request the broadcast */
setup_APIC_timer();
+ amd_e400_c1e_apic_setup();
}
void setup_secondary_APIC_clock(void)
{
setup_APIC_timer();
+ amd_e400_c1e_apic_setup();
}
/*
@@ -2263,6 +2264,7 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v))
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
/* Should happen once for each apic */
WARN_ON((*drv)->eoi_write == eoi_write);
+ (*drv)->native_eoi_write = (*drv)->eoi_write;
(*drv)->eoi_write = eoi_write;
}
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 48e6d84f173e..945e512a112a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -48,7 +48,6 @@
#include <linux/bootmem.h>
#include <asm/irqdomain.h>
-#include <asm/idle.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/cpu.h>
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 51287cd90bf6..643818a7688b 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -906,14 +906,14 @@ static int apm_cpu_idle(struct cpuidle_device *dev,
static int use_apm_idle; /* = 0 */
static unsigned int last_jiffies; /* = 0 */
static unsigned int last_stime; /* = 0 */
- cputime_t stime;
+ cputime_t stime, utime;
int apm_idle_done = 0;
unsigned int jiffies_since_last_check = jiffies - last_jiffies;
unsigned int bucket;
recalc:
- task_cputime(current, NULL, &stime);
+ task_cputime(current, &utime, &stime);
if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
use_apm_idle = 0;
} else if (jiffies_since_last_check > idle_period) {
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 4a8697f7d4ef..33b63670bf09 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -20,13 +20,11 @@ obj-y := intel_cacheinfo.o scattered.o topology.o
obj-y += common.o
obj-y += rdrand.o
obj-y += match.o
+obj-y += bugs.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o
-obj-$(CONFIG_X86_32) += bugs.o
-obj-$(CONFIG_X86_64) += bugs_64.o
-
obj-$(CONFIG_CPU_SUP_INTEL) += intel.o
obj-$(CONFIG_CPU_SUP_AMD) += amd.o
obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 1e81a37c034e..71cae73a5076 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -20,6 +20,10 @@
#include "cpu.h"
+static const int amd_erratum_383[];
+static const int amd_erratum_400[];
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
+
/*
* nodes_per_socket: Stores the number of nodes per socket.
* Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -314,11 +318,30 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
smp_num_siblings = ((ebx >> 8) & 3) + 1;
c->x86_max_cores /= smp_num_siblings;
c->cpu_core_id = ebx & 0xff;
+
+ /*
+ * We may have multiple LLCs if L3 caches exist, so check if we
+ * have an L3 cache by looking at the L3 cache CPUID leaf.
+ */
+ if (cpuid_edx(0x80000006)) {
+ if (c->x86 == 0x17) {
+ /*
+ * LLC is at the core complex level.
+ * Core complex id is ApicId[3].
+ */
+ per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+ } else {
+ /* LLC is at the node level. */
+ per_cpu(cpu_llc_id, cpu) = node_id;
+ }
+ }
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value);
node_id = value & 7;
+
+ per_cpu(cpu_llc_id, cpu) = node_id;
} else
return;
@@ -329,9 +352,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_AMD_DCM);
cus_per_node = c->x86_max_cores / nodes_per_socket;
- /* store NodeID, use llc_shared_map to store sibling info */
- per_cpu(cpu_llc_id, cpu) = node_id;
-
/* core id has to be in the [0 .. cores_per_node - 1] range */
c->cpu_core_id %= cus_per_node;
}
@@ -356,15 +376,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
/* use socket ID also for last level cache */
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
amd_get_topology(c);
-
- /*
- * Fix percpu cpu_llc_id here as LLC topology is different
- * for Fam17h systems.
- */
- if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
- return;
-
- per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
#endif
}
@@ -585,11 +596,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
/* F16h erratum 793, CVE-2013-6885 */
if (c->x86 == 0x16 && c->x86_model <= 0xf)
msr_set_bit(MSR_AMD64_LS_CFG, 15);
-}
-static const int amd_erratum_383[];
-static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
+ /*
+ * Check whether the machine is affected by erratum 400. This is
+ * used to select the proper idle routine and to enable the check
+ * whether the machine is affected in arch_post_acpi_init(), which
+ * sets the X86_BUG_AMD_APIC_C1E bug depending on the MSR check.
+ */
+ if (cpu_has_amd_erratum(c, amd_erratum_400))
+ set_cpu_bug(c, X86_BUG_AMD_E400);
+}
static void init_amd_k8(struct cpuinfo_x86 *c)
{
@@ -770,9 +786,6 @@ static void init_amd(struct cpuinfo_x86 *c)
if (c->x86 > 0x11)
set_cpu_cap(c, X86_FEATURE_ARAT);
- if (cpu_has_amd_erratum(c, amd_erratum_400))
- set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
-
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
/* 3DNow or LM implies PREFETCHW */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index bd17db15a2c1..a44ef52184df 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -16,15 +16,19 @@
#include <asm/msr.h>
#include <asm/paravirt.h>
#include <asm/alternative.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
void __init check_bugs(void)
{
identify_boot_cpu();
-#ifndef CONFIG_SMP
- pr_info("CPU: ");
- print_cpu_info(&boot_cpu_data);
-#endif
+ if (!IS_ENABLED(CONFIG_SMP)) {
+ pr_info("CPU: ");
+ print_cpu_info(&boot_cpu_data);
+ }
+
+#ifdef CONFIG_X86_32
/*
* Check whether we are able to run this kernel safely on SMP.
*
@@ -40,4 +44,18 @@ void __init check_bugs(void)
alternative_instructions();
fpu__init_check_bugs();
+#else /* CONFIG_X86_64 */
+ alternative_instructions();
+
+ /*
+ * Make sure the first 2MB area is not mapped by huge pages
+ * There are typically fixed size MTRRs in there and overlapping
+ * MTRRs into large pages causes slow downs.
+ *
+ * Right now we don't do that with gbpages because there seems
+ * very little benefit for that case.
+ */
+ if (!direct_gbpages)
+ set_memory_4k((unsigned long)__va(0), 1);
+#endif
}
diff --git a/arch/x86/kernel/cpu/bugs_64.c b/arch/x86/kernel/cpu/bugs_64.c
deleted file mode 100644
index a972ac4c7e7d..000000000000
--- a/arch/x86/kernel/cpu/bugs_64.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 1994 Linus Torvalds
- * Copyright (C) 2000 SuSE
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/alternative.h>
-#include <asm/bugs.h>
-#include <asm/processor.h>
-#include <asm/mtrr.h>
-#include <asm/cacheflush.h>
-
-void __init check_bugs(void)
-{
- identify_boot_cpu();
-#if !defined(CONFIG_SMP)
- pr_info("CPU: ");
- print_cpu_info(&boot_cpu_data);
-#endif
- alternative_instructions();
-
- /*
- * Make sure the first 2MB area is not mapped by huge pages
- * There are typically fixed size MTRRs in there and overlapping
- * MTRRs into large pages causes slow downs.
- *
- * Right now we don't do that with gbpages because there seems
- * very little benefit for that case.
- */
- if (!direct_gbpages)
- set_memory_4k((unsigned long)__va(0), 1);
-}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cc9e980c68ec..729f92ba8224 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1172,7 +1172,6 @@ void enable_sep_cpu(void)
void __init identify_boot_cpu(void)
{
identify_cpu(&boot_cpu_data);
- init_amd_e400_c1e_mask();
#ifdef CONFIG_X86_32
sysenter_setup();
enable_sep_cpu();
@@ -1190,51 +1189,6 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
mtrr_ap_init();
}
-struct msr_range {
- unsigned min;
- unsigned max;
-};
-
-static const struct msr_range msr_range_array[] = {
- { 0x00000000, 0x00000418},
- { 0xc0000000, 0xc000040b},
- { 0xc0010000, 0xc0010142},
- { 0xc0011000, 0xc001103b},
-};
-
-static void __print_cpu_msr(void)
-{
- unsigned index_min, index_max;
- unsigned index;
- u64 val;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
- index_min = msr_range_array[i].min;
- index_max = msr_range_array[i].max;
-
- for (index = index_min; index < index_max; index++) {
- if (rdmsrl_safe(index, &val))
- continue;
- pr_info(" MSR%08x: %016llx\n", index, val);
- }
- }
-}
-
-static int show_msr;
-
-static __init int setup_show_msr(char *arg)
-{
- int num;
-
- get_option(&arg, &num);
-
- if (num > 0)
- show_msr = num;
- return 1;
-}
-__setup("show_msr=", setup_show_msr);
-
static __init int setup_noclflush(char *arg)
{
setup_clear_cpu_cap(X86_FEATURE_CLFLUSH);
@@ -1268,14 +1222,6 @@ void print_cpu_info(struct cpuinfo_x86 *c)
pr_cont(", stepping: 0x%x)\n", c->x86_mask);
else
pr_cont(")\n");
-
- print_cpu_msr(c);
-}
-
-void print_cpu_msr(struct cpuinfo_x86 *c)
-{
- if (c->cpu_index < show_msr)
- __print_cpu_msr();
}
static __init int setup_disablecpuid(char *arg)
@@ -1490,11 +1436,8 @@ void cpu_init(void)
*/
cr4_init_shadow();
- /*
- * Load microcode on this cpu if a valid microcode is available.
- * This is early microcode loading procedure.
- */
- load_ucode_ap();
+ if (cpu)
+ load_ucode_ap();
t = &per_cpu(cpu_tss, cpu);
oist = &per_cpu(orig_ist, cpu);
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 631356c8cca4..c7efbcfbeda6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -311,7 +311,7 @@ static int mce_severity_intel(struct mce *m, int tolerant, char **msg, bool is_e
*msg = s->msg;
s->covered = 1;
if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) {
- if (panic_on_oops || tolerant < 1)
+ if (tolerant < 1)
return MCE_PANIC_SEVERITY;
}
return s->sev;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index a7fdf453d895..132e1ec67da0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -43,6 +43,7 @@
#include <linux/export.h>
#include <linux/jump_label.h>
+#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/traps.h>
#include <asm/tlbflush.h>
@@ -135,6 +136,9 @@ void mce_setup(struct mce *m)
m->socketid = cpu_data(m->extcpu).phys_proc_id;
m->apicid = cpu_data(m->extcpu).initial_apicid;
rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
+
+ if (this_cpu_has(X86_FEATURE_INTEL_PPIN))
+ rdmsrl(MSR_PPIN, m->ppin);
}
DEFINE_PER_CPU(struct mce, injectm);
@@ -207,8 +211,12 @@ EXPORT_SYMBOL_GPL(mce_inject_log);
static struct notifier_block mce_srao_nb;
+static atomic_t num_notifiers;
+
void mce_register_decode_chain(struct notifier_block *nb)
{
+ atomic_inc(&num_notifiers);
+
/* Ensure SRAO notifier has the highest priority in the decode chain. */
if (nb != &mce_srao_nb && nb->priority == INT_MAX)
nb->priority -= 1;
@@ -219,6 +227,8 @@ EXPORT_SYMBOL_GPL(mce_register_decode_chain);
void mce_unregister_decode_chain(struct notifier_block *nb)
{
+ atomic_dec(&num_notifiers);
+
atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
}
EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
@@ -270,17 +280,17 @@ struct mca_msr_regs msr_ops = {
.misc = misc_reg
};
-static void print_mce(struct mce *m)
+static void __print_mce(struct mce *m)
{
- int ret = 0;
-
- pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
- m->extcpu, m->mcgstatus, m->bank, m->status);
+ pr_emerg(HW_ERR "CPU %d: Machine Check%s: %Lx Bank %d: %016Lx\n",
+ m->extcpu,
+ (m->mcgstatus & MCG_STATUS_MCIP ? " Exception" : ""),
+ m->mcgstatus, m->bank, m->status);
if (m->ip) {
pr_emerg(HW_ERR "RIP%s %02x:<%016Lx> ",
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
- m->cs, m->ip);
+ m->cs, m->ip);
if (m->cs == __KERNEL_CS)
print_symbol("{%s}", m->ip);
@@ -308,6 +318,13 @@ static void print_mce(struct mce *m)
pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
cpu_data(m->extcpu).microcode);
+}
+
+static void print_mce(struct mce *m)
+{
+ int ret = 0;
+
+ __print_mce(m);
/*
* Print out human-readable details about the MCE error,
@@ -569,6 +586,32 @@ static struct notifier_block mce_srao_nb = {
.priority = INT_MAX,
};
+static int mce_default_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct mce *m = (struct mce *)data;
+
+ if (!m)
+ return NOTIFY_DONE;
+
+ /*
+ * Run the default notifier if we have only the SRAO
+ * notifier and us registered.
+ */
+ if (atomic_read(&num_notifiers) > 2)
+ return NOTIFY_DONE;
+
+ __print_mce(m);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mce_default_nb = {
+ .notifier_call = mce_default_notifier,
+ /* lowest prio, we want it to run last. */
+ .priority = 0,
+};
+
/*
* Read ADDR and MISC registers.
*/
@@ -667,6 +710,15 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
mce_gather_info(&m, NULL);
+ /*
+ * m.tsc was set in mce_setup(). Clear it if not requested.
+ *
+ * FIXME: Propagate @flags to mce_gather_info/mce_setup() to avoid
+ * that dance.
+ */
+ if (!(flags & MCP_TIMESTAMP))
+ m.tsc = 0;
+
for (i = 0; i < mca_cfg.banks; i++) {
if (!mce_banks[i].ctl || !test_bit(i, *b))
continue;
@@ -674,14 +726,12 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
m.misc = 0;
m.addr = 0;
m.bank = i;
- m.tsc = 0;
barrier();
m.status = mce_rdmsrl(msr_ops.status(i));
if (!(m.status & MCI_STATUS_VAL))
continue;
-
/*
* Uncorrected or signalled events are handled by the exception
* handler when it is enabled, so don't process those here.
@@ -696,9 +746,6 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
mce_read_aux(&m, i);
- if (!(flags & MCP_TIMESTAMP))
- m.tsc = 0;
-
severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m))
@@ -1355,7 +1402,7 @@ static void mce_timer_fn(unsigned long data)
iv = __this_cpu_read(mce_next_interval);
if (mce_available(this_cpu_ptr(&cpu_info))) {
- machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_poll_banks));
+ machine_check_poll(0, this_cpu_ptr(&mce_poll_banks));
if (mce_intel_cmci_poll()) {
iv = mce_adjust_timer(iv);
@@ -1745,6 +1792,14 @@ static void mce_start_timer(unsigned int cpu, struct timer_list *t)
add_timer_on(t, cpu);
}
+static void __mcheck_cpu_setup_timer(void)
+{
+ struct timer_list *t = this_cpu_ptr(&mce_timer);
+ unsigned int cpu = smp_processor_id();
+
+ setup_pinned_timer(t, mce_timer_fn, cpu);
+}
+
static void __mcheck_cpu_init_timer(void)
{
struct timer_list *t = this_cpu_ptr(&mce_timer);
@@ -1796,7 +1851,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
__mcheck_cpu_init_generic();
__mcheck_cpu_init_vendor(c);
__mcheck_cpu_init_clear_banks();
- __mcheck_cpu_init_timer();
+ __mcheck_cpu_setup_timer();
}
/*
@@ -2138,6 +2193,7 @@ int __init mcheck_init(void)
{
mcheck_intel_therm_init();
mce_register_decode_chain(&mce_srao_nb);
+ mce_register_decode_chain(&mce_default_nb);
mcheck_vendor_init_severity();
INIT_WORK(&mce_work, mce_process_work);
@@ -2255,8 +2311,6 @@ static struct bus_type mce_subsys = {
DEFINE_PER_CPU(struct device *, mce_device);
-void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
-
static inline struct mce_bank *attr_to_bank(struct device_attribute *attr)
{
return container_of(attr, struct mce_bank, attr);
@@ -2409,6 +2463,10 @@ static int mce_device_create(unsigned int cpu)
if (!mce_available(&boot_cpu_data))
return -EIO;
+ dev = per_cpu(mce_device, cpu);
+ if (dev)
+ return 0;
+
dev = kzalloc(sizeof *dev, GFP_KERNEL);
if (!dev)
return -ENOMEM;
@@ -2468,28 +2526,25 @@ static void mce_device_remove(unsigned int cpu)
}
/* Make sure there are no machine checks on offlined CPUs. */
-static void mce_disable_cpu(void *h)
+static void mce_disable_cpu(void)
{
- unsigned long action = *(unsigned long *)h;
-
if (!mce_available(raw_cpu_ptr(&cpu_info)))
return;
- if (!(action & CPU_TASKS_FROZEN))
+ if (!cpuhp_tasks_frozen)
cmci_clear();
vendor_disable_error_reporting();
}
-static void mce_reenable_cpu(void *h)
+static void mce_reenable_cpu(void)
{
- unsigned long action = *(unsigned long *)h;
int i;
if (!mce_available(raw_cpu_ptr(&cpu_info)))
return;
- if (!(action & CPU_TASKS_FROZEN))
+ if (!cpuhp_tasks_frozen)
cmci_reenable();
for (i = 0; i < mca_cfg.banks; i++) {
struct mce_bank *b = &mce_banks[i];
@@ -2499,45 +2554,43 @@ static void mce_reenable_cpu(void *h)
}
}
-/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int
-mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int mce_cpu_dead(unsigned int cpu)
+{
+ mce_intel_hcpu_update(cpu);
+
+ /* intentionally ignoring frozen here */
+ if (!cpuhp_tasks_frozen)
+ cmci_rediscover();
+ return 0;
+}
+
+static int mce_cpu_online(unsigned int cpu)
{
- unsigned int cpu = (unsigned long)hcpu;
struct timer_list *t = &per_cpu(mce_timer, cpu);
+ int ret;
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- mce_device_create(cpu);
- if (threshold_cpu_callback)
- threshold_cpu_callback(action, cpu);
- break;
- case CPU_DEAD:
- if (threshold_cpu_callback)
- threshold_cpu_callback(action, cpu);
- mce_device_remove(cpu);
- mce_intel_hcpu_update(cpu);
+ mce_device_create(cpu);
- /* intentionally ignoring frozen here */
- if (!(action & CPU_TASKS_FROZEN))
- cmci_rediscover();
- break;
- case CPU_DOWN_PREPARE:
- smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
- del_timer_sync(t);
- break;
- case CPU_DOWN_FAILED:
- smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
- mce_start_timer(cpu, t);
- break;
+ ret = mce_threshold_create_device(cpu);
+ if (ret) {
+ mce_device_remove(cpu);
+ return ret;
}
-
- return NOTIFY_OK;
+ mce_reenable_cpu();
+ mce_start_timer(cpu, t);
+ return 0;
}
-static struct notifier_block mce_cpu_notifier = {
- .notifier_call = mce_cpu_callback,
-};
+static int mce_cpu_pre_down(unsigned int cpu)
+{
+ struct timer_list *t = &per_cpu(mce_timer, cpu);
+
+ mce_disable_cpu();
+ del_timer_sync(t);
+ mce_threshold_remove_device(cpu);
+ mce_device_remove(cpu);
+ return 0;
+}
static __init void mce_init_banks(void)
{
@@ -2559,8 +2612,8 @@ static __init void mce_init_banks(void)
static __init int mcheck_init_device(void)
{
+ enum cpuhp_state hp_online;
int err;
- int i = 0;
if (!mce_available(&boot_cpu_data)) {
err = -EIO;
@@ -2578,23 +2631,16 @@ static __init int mcheck_init_device(void)
if (err)
goto err_out_mem;
- cpu_notifier_register_begin();
- for_each_online_cpu(i) {
- err = mce_device_create(i);
- if (err) {
- /*
- * Register notifier anyway (and do not unreg it) so
- * that we don't leave undeleted timers, see notifier
- * callback above.
- */
- __register_hotcpu_notifier(&mce_cpu_notifier);
- cpu_notifier_register_done();
- goto err_device_create;
- }
- }
+ err = cpuhp_setup_state(CPUHP_X86_MCE_DEAD, "x86/mce:dead", NULL,
+ mce_cpu_dead);
+ if (err)
+ goto err_out_mem;
- __register_hotcpu_notifier(&mce_cpu_notifier);
- cpu_notifier_register_done();
+ err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/mce:online",
+ mce_cpu_online, mce_cpu_pre_down);
+ if (err < 0)
+ goto err_out_online;
+ hp_online = err;
register_syscore_ops(&mce_syscore_ops);
@@ -2607,16 +2653,10 @@ static __init int mcheck_init_device(void)
err_register:
unregister_syscore_ops(&mce_syscore_ops);
+ cpuhp_remove_state(hp_online);
-err_device_create:
- /*
- * We didn't keep track of which devices were created above, but
- * even if we had, the set of online cpus might have changed.
- * Play safe and remove for every possible cpu, since
- * mce_device_remove() will do the right thing.
- */
- for_each_possible_cpu(i)
- mce_device_remove(i);
+err_out_online:
+ cpuhp_remove_state(CPUHP_X86_MCE_DEAD);
err_out_mem:
free_cpumask_var(mce_device_initialized);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 9b5403462936..ffacfdcacb85 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -24,7 +24,6 @@
#include <asm/amd_nb.h>
#include <asm/apic.h>
-#include <asm/idle.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/trace/irq_vectors.h>
@@ -55,6 +54,8 @@
/* Threshold LVT offset is at MSR0xC0000410[15:12] */
#define SMCA_THR_LVT_OFF 0xF000
+static bool thresholding_en;
+
static const char * const th_names[] = {
"load_store",
"insn_fetch",
@@ -69,7 +70,12 @@ static const char * const smca_umc_block_names[] = {
"misc_umc"
};
-struct smca_bank_name smca_bank_names[] = {
+struct smca_bank_name {
+ const char *name; /* Short name for sysfs */
+ const char *long_name; /* Long name for pretty-printing */
+};
+
+static struct smca_bank_name smca_names[] = {
[SMCA_LS] = { "load_store", "Load Store Unit" },
[SMCA_IF] = { "insn_fetch", "Instruction Fetch Unit" },
[SMCA_L2_CACHE] = { "l2_cache", "L2 Cache" },
@@ -84,9 +90,25 @@ struct smca_bank_name smca_bank_names[] = {
[SMCA_PSP] = { "psp", "Platform Security Processor" },
[SMCA_SMU] = { "smu", "System Management Unit" },
};
-EXPORT_SYMBOL_GPL(smca_bank_names);
-static struct smca_hwid_mcatype smca_hwid_mcatypes[] = {
+const char *smca_get_name(enum smca_bank_types t)
+{
+ if (t >= N_SMCA_BANK_TYPES)
+ return NULL;
+
+ return smca_names[t].name;
+}
+
+const char *smca_get_long_name(enum smca_bank_types t)
+{
+ if (t >= N_SMCA_BANK_TYPES)
+ return NULL;
+
+ return smca_names[t].long_name;
+}
+EXPORT_SYMBOL_GPL(smca_get_long_name);
+
+static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype, xec_bitmap } */
/* ZN Core (HWID=0xB0) MCA types */
@@ -116,7 +138,7 @@ static struct smca_hwid_mcatype smca_hwid_mcatypes[] = {
{ SMCA_SMU, HWID_MCATYPE(0x01, 0x0), 0x1 },
};
-struct smca_bank_info smca_banks[MAX_NR_BANKS];
+struct smca_bank smca_banks[MAX_NR_BANKS];
EXPORT_SYMBOL_GPL(smca_banks);
/*
@@ -142,35 +164,34 @@ static void default_deferred_error_interrupt(void)
}
void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt;
-/*
- * CPU Initialization
- */
-
static void get_smca_bank_info(unsigned int bank)
{
unsigned int i, hwid_mcatype, cpu = smp_processor_id();
- struct smca_hwid_mcatype *type;
- u32 high, instanceId;
- u16 hwid, mcatype;
+ struct smca_hwid *s_hwid;
+ u32 high, instance_id;
/* Collect bank_info using CPU 0 for now. */
if (cpu)
return;
- if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &instanceId, &high)) {
+ if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &instance_id, &high)) {
pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
return;
}
- hwid = high & MCI_IPID_HWID;
- mcatype = (high & MCI_IPID_MCATYPE) >> 16;
- hwid_mcatype = HWID_MCATYPE(hwid, mcatype);
+ hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID,
+ (high & MCI_IPID_MCATYPE) >> 16);
for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
- type = &smca_hwid_mcatypes[i];
- if (hwid_mcatype == type->hwid_mcatype) {
- smca_banks[bank].type = type;
- smca_banks[bank].type_instance = instanceId;
+ s_hwid = &smca_hwid_mcatypes[i];
+ if (hwid_mcatype == s_hwid->hwid_mcatype) {
+
+ WARN(smca_banks[bank].hwid,
+ "Bank %s already initialized!\n",
+ smca_get_name(s_hwid->bank_type));
+
+ smca_banks[bank].hwid = s_hwid;
+ smca_banks[bank].id = instance_id;
break;
}
}
@@ -533,6 +554,206 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
deferred_error_interrupt_enable(c);
}
+int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr)
+{
+ u64 dram_base_addr, dram_limit_addr, dram_hole_base;
+ /* We start from the normalized address */
+ u64 ret_addr = norm_addr;
+
+ u32 tmp;
+
+ u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask;
+ u8 intlv_num_dies, intlv_num_chan, intlv_num_sockets;
+ u8 intlv_addr_sel, intlv_addr_bit;
+ u8 num_intlv_bits, hashed_bit;
+ u8 lgcy_mmio_hole_en, base = 0;
+ u8 cs_mask, cs_id = 0;
+ bool hash_enabled = false;
+
+ /* Read D18F0x1B4 (DramOffset), check if base 1 is used. */
+ if (amd_df_indirect_read(nid, 0, 0x1B4, umc, &tmp))
+ goto out_err;
+
+ /* Remove HiAddrOffset from normalized address, if enabled: */
+ if (tmp & BIT(0)) {
+ u64 hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8;
+
+ if (norm_addr >= hi_addr_offset) {
+ ret_addr -= hi_addr_offset;
+ base = 1;
+ }
+ }
+
+ /* Read D18F0x110 (DramBaseAddress). */
+ if (amd_df_indirect_read(nid, 0, 0x110 + (8 * base), umc, &tmp))
+ goto out_err;
+
+ /* Check if address range is valid. */
+ if (!(tmp & BIT(0))) {
+ pr_err("%s: Invalid DramBaseAddress range: 0x%x.\n",
+ __func__, tmp);
+ goto out_err;
+ }
+
+ lgcy_mmio_hole_en = tmp & BIT(1);
+ intlv_num_chan = (tmp >> 4) & 0xF;
+ intlv_addr_sel = (tmp >> 8) & 0x7;
+ dram_base_addr = (tmp & GENMASK_ULL(31, 12)) << 16;
+
+ /* {0, 1, 2, 3} map to address bits {8, 9, 10, 11} respectively */
+ if (intlv_addr_sel > 3) {
+ pr_err("%s: Invalid interleave address select %d.\n",
+ __func__, intlv_addr_sel);
+ goto out_err;
+ }
+
+ /* Read D18F0x114 (DramLimitAddress). */
+ if (amd_df_indirect_read(nid, 0, 0x114 + (8 * base), umc, &tmp))
+ goto out_err;
+
+ intlv_num_sockets = (tmp >> 8) & 0x1;
+ intlv_num_dies = (tmp >> 10) & 0x3;
+ dram_limit_addr = ((tmp & GENMASK_ULL(31, 12)) << 16) | GENMASK_ULL(27, 0);
+
+ intlv_addr_bit = intlv_addr_sel + 8;
+
+ /* Re-use intlv_num_chan by setting it equal to log2(#channels) */
+ switch (intlv_num_chan) {
+ case 0: intlv_num_chan = 0; break;
+ case 1: intlv_num_chan = 1; break;
+ case 3: intlv_num_chan = 2; break;
+ case 5: intlv_num_chan = 3; break;
+ case 7: intlv_num_chan = 4; break;
+
+ case 8: intlv_num_chan = 1;
+ hash_enabled = true;
+ break;
+ default:
+ pr_err("%s: Invalid number of interleaved channels %d.\n",
+ __func__, intlv_num_chan);
+ goto out_err;
+ }
+
+ num_intlv_bits = intlv_num_chan;
+
+ if (intlv_num_dies > 2) {
+ pr_err("%s: Invalid number of interleaved nodes/dies %d.\n",
+ __func__, intlv_num_dies);
+ goto out_err;
+ }
+
+ num_intlv_bits += intlv_num_dies;
+
+ /* Add a bit if sockets are interleaved. */
+ num_intlv_bits += intlv_num_sockets;
+
+ /* Assert num_intlv_bits <= 4 */
+ if (num_intlv_bits > 4) {
+ pr_err("%s: Invalid interleave bits %d.\n",
+ __func__, num_intlv_bits);
+ goto out_err;
+ }
+
+ if (num_intlv_bits > 0) {
+ u64 temp_addr_x, temp_addr_i, temp_addr_y;
+ u8 die_id_bit, sock_id_bit, cs_fabric_id;
+
+ /*
+ * Read FabricBlockInstanceInformation3_CS[BlockFabricID].
+ * This is the fabric id for this coherent slave. Use
+ * umc/channel# as instance id of the coherent slave
+ * for FICAA.
+ */
+ if (amd_df_indirect_read(nid, 0, 0x50, umc, &tmp))
+ goto out_err;
+
+ cs_fabric_id = (tmp >> 8) & 0xFF;
+ die_id_bit = 0;
+
+ /* If interleaved over more than 1 channel: */
+ if (intlv_num_chan) {
+ die_id_bit = intlv_num_chan;
+ cs_mask = (1 << die_id_bit) - 1;
+ cs_id = cs_fabric_id & cs_mask;
+ }
+
+ sock_id_bit = die_id_bit;
+
+ /* Read D18F1x208 (SystemFabricIdMask). */
+ if (intlv_num_dies || intlv_num_sockets)
+ if (amd_df_indirect_read(nid, 1, 0x208, umc, &tmp))
+ goto out_err;
+
+ /* If interleaved over more than 1 die. */
+ if (intlv_num_dies) {
+ sock_id_bit = die_id_bit + intlv_num_dies;
+ die_id_shift = (tmp >> 24) & 0xF;
+ die_id_mask = (tmp >> 8) & 0xFF;
+
+ cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit;
+ }
+
+ /* If interleaved over more than 1 socket. */
+ if (intlv_num_sockets) {
+ socket_id_shift = (tmp >> 28) & 0xF;
+ socket_id_mask = (tmp >> 16) & 0xFF;
+
+ cs_id |= ((cs_fabric_id & socket_id_mask) >> socket_id_shift) << sock_id_bit;
+ }
+
+ /*
+ * The pre-interleaved address consists of XXXXXXIIIYYYYY
+ * where III is the ID for this CS, and XXXXXXYYYYY are the
+ * address bits from the post-interleaved address.
+ * "num_intlv_bits" has been calculated to tell us how many "I"
+ * bits there are. "intlv_addr_bit" tells us how many "Y" bits
+ * there are (where "I" starts).
+ */
+ temp_addr_y = ret_addr & GENMASK_ULL(intlv_addr_bit-1, 0);
+ temp_addr_i = (cs_id << intlv_addr_bit);
+ temp_addr_x = (ret_addr & GENMASK_ULL(63, intlv_addr_bit)) << num_intlv_bits;
+ ret_addr = temp_addr_x | temp_addr_i | temp_addr_y;
+ }
+
+ /* Add dram base address */
+ ret_addr += dram_base_addr;
+
+ /* If legacy MMIO hole enabled */
+ if (lgcy_mmio_hole_en) {
+ if (amd_df_indirect_read(nid, 0, 0x104, umc, &tmp))
+ goto out_err;
+
+ dram_hole_base = tmp & GENMASK(31, 24);
+ if (ret_addr >= dram_hole_base)
+ ret_addr += (BIT_ULL(32) - dram_hole_base);
+ }
+
+ if (hash_enabled) {
+ /* Save some parentheses and grab ls-bit at the end. */
+ hashed_bit = (ret_addr >> 12) ^
+ (ret_addr >> 18) ^
+ (ret_addr >> 21) ^
+ (ret_addr >> 30) ^
+ cs_id;
+
+ hashed_bit &= BIT(0);
+
+ if (hashed_bit != ((ret_addr >> intlv_addr_bit) & BIT(0)))
+ ret_addr ^= BIT(intlv_addr_bit);
+ }
+
+ /* Is calculated system address is above DRAM limit address? */
+ if (ret_addr > dram_limit_addr)
+ goto out_err;
+
+ *sys_addr = ret_addr;
+ return 0;
+
+out_err:
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
+
static void
__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
{
@@ -645,6 +866,7 @@ static void amd_threshold_interrupt(void)
{
u32 low = 0, high = 0, address = 0;
unsigned int bank, block, cpu = smp_processor_id();
+ struct thresh_restart tr;
/* assume first bank caused it */
for (bank = 0; bank < mca_cfg.banks; ++bank) {
@@ -681,6 +903,11 @@ static void amd_threshold_interrupt(void)
log:
__log_error(bank, false, true, ((u64)high << 32) | low);
+
+ /* Reset threshold block after logging error. */
+ memset(&tr, 0, sizeof(tr));
+ tr.b = &per_cpu(threshold_banks, cpu)[bank]->blocks[block];
+ threshold_restart_bank(&tr);
}
/*
@@ -826,10 +1053,10 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
return th_names[bank];
}
- if (!smca_banks[bank].type)
+ if (!smca_banks[bank].hwid)
return NULL;
- bank_type = smca_banks[bank].type->bank_type;
+ bank_type = smca_banks[bank].hwid->bank_type;
if (b && bank_type == SMCA_UMC) {
if (b->block < ARRAY_SIZE(smca_umc_block_names))
@@ -838,8 +1065,8 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
}
snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN,
- "%s_%x", smca_bank_names[bank_type].name,
- smca_banks[bank].type_instance);
+ "%s_%x", smca_get_name(bank_type),
+ smca_banks[bank].id);
return buf_mcatype;
}
@@ -1010,31 +1237,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
return err;
}
-/* create dir/files for all valid threshold banks */
-static int threshold_create_device(unsigned int cpu)
-{
- unsigned int bank;
- struct threshold_bank **bp;
- int err = 0;
-
- bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
- GFP_KERNEL);
- if (!bp)
- return -ENOMEM;
-
- per_cpu(threshold_banks, cpu) = bp;
-
- for (bank = 0; bank < mca_cfg.banks; ++bank) {
- if (!(per_cpu(bank_map, cpu) & (1 << bank)))
- continue;
- err = threshold_create_bank(cpu, bank);
- if (err)
- return err;
- }
-
- return err;
-}
-
static void deallocate_threshold_block(unsigned int cpu,
unsigned int bank)
{
@@ -1102,48 +1304,71 @@ free_out:
per_cpu(threshold_banks, cpu)[bank] = NULL;
}
-static void threshold_remove_device(unsigned int cpu)
+int mce_threshold_remove_device(unsigned int cpu)
{
unsigned int bank;
+ if (!thresholding_en)
+ return 0;
+
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
threshold_remove_bank(cpu, bank);
}
kfree(per_cpu(threshold_banks, cpu));
+ per_cpu(threshold_banks, cpu) = NULL;
+ return 0;
}
-/* get notified when a cpu comes on/off */
-static void
-amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu)
+/* create dir/files for all valid threshold banks */
+int mce_threshold_create_device(unsigned int cpu)
{
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- threshold_create_device(cpu);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- threshold_remove_device(cpu);
- break;
- default:
- break;
+ unsigned int bank;
+ struct threshold_bank **bp;
+ int err = 0;
+
+ if (!thresholding_en)
+ return 0;
+
+ bp = per_cpu(threshold_banks, cpu);
+ if (bp)
+ return 0;
+
+ bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
+ GFP_KERNEL);
+ if (!bp)
+ return -ENOMEM;
+
+ per_cpu(threshold_banks, cpu) = bp;
+
+ for (bank = 0; bank < mca_cfg.banks; ++bank) {
+ if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+ continue;
+ err = threshold_create_bank(cpu, bank);
+ if (err)
+ goto err;
}
+ return err;
+err:
+ mce_threshold_remove_device(cpu);
+ return err;
}
static __init int threshold_init_device(void)
{
unsigned lcpu = 0;
+ if (mce_threshold_vector == amd_threshold_interrupt)
+ thresholding_en = true;
+
/* to hit CPUs online before the notifier is up */
for_each_online_cpu(lcpu) {
- int err = threshold_create_device(lcpu);
+ int err = mce_threshold_create_device(lcpu);
if (err)
return err;
}
- threshold_cpu_callback = amd_64_threshold_cpu_callback;
return 0;
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 1defb8ea882c..190b3e6cef4d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -11,6 +11,8 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <asm/apic.h>
+#include <asm/cpufeature.h>
+#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/mce.h>
@@ -130,7 +132,7 @@ bool mce_intel_cmci_poll(void)
* Reset the counter if we've logged an error in the last poll
* during the storm.
*/
- if (machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned)))
+ if (machine_check_poll(0, this_cpu_ptr(&mce_banks_owned)))
this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
else
this_cpu_dec(cmci_backoff_cnt);
@@ -342,7 +344,7 @@ void cmci_recheck(void)
return;
local_irq_save(flags);
- machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
+ machine_check_poll(0, this_cpu_ptr(&mce_banks_owned));
local_irq_restore(flags);
}
@@ -464,11 +466,46 @@ static void intel_clear_lmce(void)
wrmsrl(MSR_IA32_MCG_EXT_CTL, val);
}
+static void intel_ppin_init(struct cpuinfo_x86 *c)
+{
+ unsigned long long val;
+
+ /*
+ * Even if testing the presence of the MSR would be enough, we don't
+ * want to risk the situation where other models reuse this MSR for
+ * other purposes.
+ */
+ switch (c->x86_model) {
+ case INTEL_FAM6_IVYBRIDGE_X:
+ case INTEL_FAM6_HASWELL_X:
+ case INTEL_FAM6_BROADWELL_XEON_D:
+ case INTEL_FAM6_BROADWELL_X:
+ case INTEL_FAM6_SKYLAKE_X:
+ if (rdmsrl_safe(MSR_PPIN_CTL, &val))
+ return;
+
+ if ((val & 3UL) == 1UL) {
+ /* PPIN available but disabled: */
+ return;
+ }
+
+ /* If PPIN is disabled, but not locked, try to enable: */
+ if (!(val & 3UL)) {
+ wrmsrl_safe(MSR_PPIN_CTL, val | 2UL);
+ rdmsrl_safe(MSR_PPIN_CTL, &val);
+ }
+
+ if ((val & 3UL) == 2UL)
+ set_cpu_cap(c, X86_FEATURE_INTEL_PPIN);
+ }
+}
+
void mce_intel_feature_init(struct cpuinfo_x86 *c)
{
intel_init_thermal(c);
intel_init_cmci();
intel_init_lmce();
+ intel_ppin_init(c);
}
void mce_intel_feature_clear(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 6b9dc4d18ccc..465aca8be009 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -26,7 +26,6 @@
#include <asm/processor.h>
#include <asm/apic.h>
-#include <asm/idle.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/trace/irq_vectors.h>
@@ -271,58 +270,32 @@ static void thermal_throttle_remove_dev(struct device *dev)
}
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int
-thermal_throttle_cpu_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
+static int thermal_throttle_online(unsigned int cpu)
{
- unsigned int cpu = (unsigned long)hcpu;
- struct device *dev;
- int err = 0;
-
- dev = get_cpu_device(cpu);
-
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- err = thermal_throttle_add_dev(dev, cpu);
- WARN_ON(err);
- break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- thermal_throttle_remove_dev(dev);
- break;
- }
- return notifier_from_errno(err);
+ struct device *dev = get_cpu_device(cpu);
+
+ return thermal_throttle_add_dev(dev, cpu);
}
-static struct notifier_block thermal_throttle_cpu_notifier =
+static int thermal_throttle_offline(unsigned int cpu)
{
- .notifier_call = thermal_throttle_cpu_callback,
-};
+ struct device *dev = get_cpu_device(cpu);
+
+ thermal_throttle_remove_dev(dev);
+ return 0;
+}
static __init int thermal_throttle_init_device(void)
{
- unsigned int cpu = 0;
- int err;
+ int ret;
if (!atomic_read(&therm_throt_en))
return 0;
- cpu_notifier_register_begin();
-
- /* connect live CPUs to sysfs */
- for_each_online_cpu(cpu) {
- err = thermal_throttle_add_dev(get_cpu_device(cpu), cpu);
- WARN_ON(err);
- }
-
- __register_hotcpu_notifier(&thermal_throttle_cpu_notifier);
- cpu_notifier_register_done();
-
- return 0;
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online",
+ thermal_throttle_online,
+ thermal_throttle_offline);
+ return ret < 0 ? ret : 0;
}
device_initcall(thermal_throttle_init_device);
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
index fcf9ae9384f4..9beb092d68a5 100644
--- a/arch/x86/kernel/cpu/mcheck/threshold.c
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -6,7 +6,6 @@
#include <asm/irq_vectors.h>
#include <asm/apic.h>
-#include <asm/idle.h>
#include <asm/mce.h>
#include <asm/trace/irq_vectors.h>
diff --git a/arch/x86/kernel/cpu/microcode/Makefile b/arch/x86/kernel/cpu/microcode/Makefile
index 220b1a508513..ba12e8aa4a45 100644
--- a/arch/x86/kernel/cpu/microcode/Makefile
+++ b/arch/x86/kernel/cpu/microcode/Makefile
@@ -1,4 +1,4 @@
microcode-y := core.o
obj-$(CONFIG_MICROCODE) += microcode.o
-microcode-$(CONFIG_MICROCODE_INTEL) += intel.o intel_lib.o
+microcode-$(CONFIG_MICROCODE_INTEL) += intel.o
microcode-$(CONFIG_MICROCODE_AMD) += amd.o
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 017bda12caae..6f353bdb3a25 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -5,6 +5,7 @@
* CPUs and later.
*
* Copyright (C) 2008-2011 Advanced Micro Devices Inc.
+ * 2013-2016 Borislav Petkov <bp@alien8.de>
*
* Author: Peter Oruba <peter.oruba@amd.com>
*
@@ -39,64 +40,25 @@
static struct equiv_cpu_entry *equiv_cpu_table;
-struct ucode_patch {
- struct list_head plist;
- void *data;
- u32 patch_id;
- u16 equiv_cpu;
-};
-
-static LIST_HEAD(pcache);
-
/*
* This points to the current valid container of microcode patches which we will
- * save from the initrd before jettisoning its contents.
+ * save from the initrd/builtin before jettisoning its contents.
*/
-static u8 *container;
-static size_t container_size;
-static bool ucode_builtin;
+struct container {
+ u8 *data;
+ size_t size;
+} cont;
static u32 ucode_new_rev;
static u8 amd_ucode_patch[PATCH_MAX_SIZE];
static u16 this_equiv_id;
-static struct cpio_data ucode_cpio;
-
-static struct cpio_data __init find_ucode_in_initrd(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- char *path;
- void *start;
- size_t size;
-
- /*
- * Microcode patch container file is prepended to the initrd in cpio
- * format. See Documentation/x86/early-microcode.txt
- */
- static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
-
-#ifdef CONFIG_X86_32
- struct boot_params *p;
-
- /*
- * On 32-bit, early load occurs before paging is turned on so we need
- * to use physical addresses.
- */
- p = (struct boot_params *)__pa_nodebug(&boot_params);
- path = (char *)__pa_nodebug(ucode_path);
- start = (void *)p->hdr.ramdisk_image;
- size = p->hdr.ramdisk_size;
-#else
- path = ucode_path;
- start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
- size = boot_params.hdr.ramdisk_size;
-#endif /* !CONFIG_X86_32 */
-
- return find_cpio_data(path, start, size, NULL);
-#else
- return (struct cpio_data){ NULL, 0, "" };
-#endif
-}
+/*
+ * Microcode patch container file is prepended to the initrd in cpio
+ * format. See Documentation/x86/early-microcode.txt
+ */
+static const char
+ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin";
static size_t compute_container_size(u8 *data, u32 total_size)
{
@@ -135,48 +97,48 @@ static size_t compute_container_size(u8 *data, u32 total_size)
return size;
}
+static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
+ unsigned int sig)
+{
+ int i = 0;
+
+ if (!equiv_cpu_table)
+ return 0;
+
+ while (equiv_cpu_table[i].installed_cpu != 0) {
+ if (sig == equiv_cpu_table[i].installed_cpu)
+ return equiv_cpu_table[i].equiv_cpu;
+
+ i++;
+ }
+ return 0;
+}
+
/*
- * Early load occurs before we can vmalloc(). So we look for the microcode
- * patch container file in initrd, traverse equivalent cpu table, look for a
- * matching microcode patch, and update, all in initrd memory in place.
- * When vmalloc() is available for use later -- on 64-bit during first AP load,
- * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
- * load_microcode_amd() to save equivalent cpu table and microcode patches in
- * kernel heap memory.
+ * This scans the ucode blob for the proper container as we can have multiple
+ * containers glued together.
*/
-static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
+static struct container
+find_proper_container(u8 *ucode, size_t size, u16 *ret_id)
{
+ struct container ret = { NULL, 0 };
+ u32 eax, ebx, ecx, edx;
struct equiv_cpu_entry *eq;
- size_t *cont_sz;
- u32 *header;
- u8 *data, **cont;
- u8 (*patch)[PATCH_MAX_SIZE];
- u16 eq_id = 0;
int offset, left;
- u32 rev, eax, ebx, ecx, edx;
- u32 *new_rev;
-
-#ifdef CONFIG_X86_32
- new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
- cont_sz = (size_t *)__pa_nodebug(&container_size);
- cont = (u8 **)__pa_nodebug(&container);
- patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
-#else
- new_rev = &ucode_new_rev;
- cont_sz = &container_size;
- cont = &container;
- patch = &amd_ucode_patch;
-#endif
+ u16 eq_id = 0;
+ u32 *header;
+ u8 *data;
data = ucode;
left = size;
header = (u32 *)data;
+
/* find equiv cpu table */
if (header[0] != UCODE_MAGIC ||
header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
header[2] == 0) /* size */
- return;
+ return ret;
eax = 0x00000001;
ecx = 0;
@@ -185,7 +147,7 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
while (left > 0) {
eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
- *cont = data;
+ ret.data = data;
/* Advance past the container header */
offset = header[2] + CONTAINER_HDR_SZ;
@@ -194,15 +156,15 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
eq_id = find_equiv_id(eq, eax);
if (eq_id) {
- this_equiv_id = eq_id;
- *cont_sz = compute_container_size(*cont, left + offset);
+ ret.size = compute_container_size(ret.data, left + offset);
/*
* truncate how much we need to iterate over in the
* ucode update loop below
*/
- left = *cont_sz - offset;
- break;
+ left = ret.size - offset;
+ *ret_id = eq_id;
+ return ret;
}
/*
@@ -212,6 +174,7 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
*/
while (left > 0) {
header = (u32 *)data;
+
if (header[0] == UCODE_MAGIC &&
header[1] == UCODE_EQUIV_CPU_TABLE_TYPE)
break;
@@ -226,14 +189,64 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
ucode = data;
}
- if (!eq_id) {
- *cont = NULL;
- *cont_sz = 0;
- return;
- }
+ return ret;
+}
+
+static int __apply_microcode_amd(struct microcode_amd *mc_amd)
+{
+ u32 rev, dummy;
+
+ native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
+
+ /* verify patch application was successful */
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+ if (rev != mc_amd->hdr.patch_id)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Early load occurs before we can vmalloc(). So we look for the microcode
+ * patch container file in initrd, traverse equivalent cpu table, look for a
+ * matching microcode patch, and update, all in initrd memory in place.
+ * When vmalloc() is available for use later -- on 64-bit during first AP load,
+ * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
+ * load_microcode_amd() to save equivalent cpu table and microcode patches in
+ * kernel heap memory.
+ */
+static struct container
+apply_microcode_early_amd(void *ucode, size_t size, bool save_patch)
+{
+ struct container ret = { NULL, 0 };
+ u8 (*patch)[PATCH_MAX_SIZE];
+ int offset, left;
+ u32 rev, *header;
+ u8 *data;
+ u16 eq_id = 0;
+ u32 *new_rev;
+
+#ifdef CONFIG_X86_32
+ new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+ patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
+#else
+ new_rev = &ucode_new_rev;
+ patch = &amd_ucode_patch;
+#endif
if (check_current_patch_level(&rev, true))
- return;
+ return (struct container){ NULL, 0 };
+
+ ret = find_proper_container(ucode, size, &eq_id);
+ if (!eq_id)
+ return (struct container){ NULL, 0 };
+
+ this_equiv_id = eq_id;
+ header = (u32 *)ret.data;
+
+ /* We're pointing to an equiv table, skip over it. */
+ data = ret.data + header[2] + CONTAINER_HDR_SZ;
+ left = ret.size - (header[2] + CONTAINER_HDR_SZ);
while (left > 0) {
struct microcode_amd *mc;
@@ -252,8 +265,7 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
*new_rev = rev;
if (save_patch)
- memcpy(patch, mc,
- min_t(u32, header[1], PATCH_MAX_SIZE));
+ memcpy(patch, mc, min_t(u32, header[1], PATCH_MAX_SIZE));
}
}
@@ -261,10 +273,10 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
data += offset;
left -= offset;
}
+ return ret;
}
-static bool __init load_builtin_amd_microcode(struct cpio_data *cp,
- unsigned int family)
+static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
{
#ifdef CONFIG_X86_64
char fw_name[36] = "amd-ucode/microcode_amd.bin";
@@ -281,47 +293,45 @@ static bool __init load_builtin_amd_microcode(struct cpio_data *cp,
void __init load_ucode_amd_bsp(unsigned int family)
{
+ struct ucode_cpu_info *uci;
struct cpio_data cp;
- bool *builtin;
- void **data;
- size_t *size;
+ const char *path;
+ bool use_pa;
-#ifdef CONFIG_X86_32
- data = (void **)__pa_nodebug(&ucode_cpio.data);
- size = (size_t *)__pa_nodebug(&ucode_cpio.size);
- builtin = (bool *)__pa_nodebug(&ucode_builtin);
-#else
- data = &ucode_cpio.data;
- size = &ucode_cpio.size;
- builtin = &ucode_builtin;
-#endif
+ if (IS_ENABLED(CONFIG_X86_32)) {
+ uci = (struct ucode_cpu_info *)__pa_nodebug(ucode_cpu_info);
+ path = (const char *)__pa_nodebug(ucode_path);
+ use_pa = true;
+ } else {
+ uci = ucode_cpu_info;
+ path = ucode_path;
+ use_pa = false;
+ }
- *builtin = load_builtin_amd_microcode(&cp, family);
- if (!*builtin)
- cp = find_ucode_in_initrd();
+ if (!get_builtin_microcode(&cp, family))
+ cp = find_microcode_in_initrd(path, use_pa);
if (!(cp.data && cp.size))
return;
- *data = cp.data;
- *size = cp.size;
+ /* Get BSP's CPUID.EAX(1), needed in load_microcode_amd() */
+ uci->cpu_sig.sig = cpuid_eax(1);
- apply_ucode_in_initrd(cp.data, cp.size, true);
+ apply_microcode_early_amd(cp.data, cp.size, true);
}
#ifdef CONFIG_X86_32
/*
* On 32-bit, since AP's early load occurs before paging is turned on, we
- * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during
- * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During
- * save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch,
+ * cannot traverse cpu_equiv_table and microcode_cache in kernel heap memory.
+ * So during cold boot, AP will apply_ucode_in_initrd() just like the BSP.
+ * In save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch,
* which is used upon resume from suspend.
*/
-void load_ucode_amd_ap(void)
+void load_ucode_amd_ap(unsigned int family)
{
struct microcode_amd *mc;
- size_t *usize;
- void **ucode;
+ struct cpio_data cp;
mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch);
if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
@@ -329,60 +339,63 @@ void load_ucode_amd_ap(void)
return;
}
- ucode = (void *)__pa_nodebug(&container);
- usize = (size_t *)__pa_nodebug(&container_size);
+ if (!get_builtin_microcode(&cp, family))
+ cp = find_microcode_in_initrd((const char *)__pa_nodebug(ucode_path), true);
- if (!*ucode || !*usize)
+ if (!(cp.data && cp.size))
return;
- apply_ucode_in_initrd(*ucode, *usize, false);
-}
-
-static void __init collect_cpu_sig_on_bsp(void *arg)
-{
- unsigned int cpu = smp_processor_id();
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
- uci->cpu_sig.sig = cpuid_eax(0x00000001);
-}
-
-static void __init get_bsp_sig(void)
-{
- unsigned int bsp = boot_cpu_data.cpu_index;
- struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
-
- if (!uci->cpu_sig.sig)
- smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+ /*
+ * This would set amd_ucode_patch above so that the following APs can
+ * use it directly instead of going down this path again.
+ */
+ apply_microcode_early_amd(cp.data, cp.size, true);
}
#else
-void load_ucode_amd_ap(void)
+void load_ucode_amd_ap(unsigned int family)
{
- unsigned int cpu = smp_processor_id();
struct equiv_cpu_entry *eq;
struct microcode_amd *mc;
- u8 *cont = container;
u32 rev, eax;
u16 eq_id;
- /* Exit if called on the BSP. */
- if (!cpu)
+ /* 64-bit runs with paging enabled, thus early==false. */
+ if (check_current_patch_level(&rev, false))
return;
- if (!container)
- return;
+ /* First AP hasn't cached it yet, go through the blob. */
+ if (!cont.data) {
+ struct cpio_data cp = { NULL, 0, "" };
- /*
- * 64-bit runs with paging enabled, thus early==false.
- */
- if (check_current_patch_level(&rev, false))
- return;
+ if (cont.size == -1)
+ return;
- /* Add CONFIG_RANDOMIZE_MEMORY offset. */
- if (!ucode_builtin)
- cont += PAGE_OFFSET - __PAGE_OFFSET_BASE;
+reget:
+ if (!get_builtin_microcode(&cp, family)) {
+#ifdef CONFIG_BLK_DEV_INITRD
+ cp = find_cpio_data(ucode_path, (void *)initrd_start,
+ initrd_end - initrd_start, NULL);
+#endif
+ if (!(cp.data && cp.size)) {
+ /*
+ * Mark it so that other APs do not scan again
+ * for no real reason and slow down boot
+ * needlessly.
+ */
+ cont.size = -1;
+ return;
+ }
+ }
+
+ cont = apply_microcode_early_amd(cp.data, cp.size, false);
+ if (!(cont.data && cont.size)) {
+ cont.size = -1;
+ return;
+ }
+ }
eax = cpuid_eax(0x00000001);
- eq = (struct equiv_cpu_entry *)(cont + CONTAINER_HDR_SZ);
+ eq = (struct equiv_cpu_entry *)(cont.data + CONTAINER_HDR_SZ);
eq_id = find_equiv_id(eq, eax);
if (!eq_id)
@@ -397,61 +410,50 @@ void load_ucode_amd_ap(void)
}
} else {
- if (!ucode_cpio.data)
- return;
/*
* AP has a different equivalence ID than BSP, looks like
* mixed-steppings silicon so go through the ucode blob anew.
*/
- apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false);
+ goto reget;
}
}
-#endif
+#endif /* CONFIG_X86_32 */
+
+static enum ucode_state
+load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
-int __init save_microcode_in_initrd_amd(void)
+int __init save_microcode_in_initrd_amd(unsigned int fam)
{
- unsigned long cont;
- int retval = 0;
enum ucode_state ret;
- u8 *cont_va;
- u32 eax;
+ int retval = 0;
+ u16 eq_id;
- if (!container)
- return -EINVAL;
+ if (!cont.data) {
+ if (IS_ENABLED(CONFIG_X86_32) && (cont.size != -1)) {
+ struct cpio_data cp = { NULL, 0, "" };
-#ifdef CONFIG_X86_32
- get_bsp_sig();
- cont = (unsigned long)container;
- cont_va = __va(container);
-#else
- /*
- * We need the physical address of the container for both bitness since
- * boot_params.hdr.ramdisk_image is a physical address.
- */
- cont = __pa_nodebug(container);
- cont_va = container;
+#ifdef CONFIG_BLK_DEV_INITRD
+ cp = find_cpio_data(ucode_path, (void *)initrd_start,
+ initrd_end - initrd_start, NULL);
#endif
- /*
- * Take into account the fact that the ramdisk might get relocated and
- * therefore we need to recompute the container's position in virtual
- * memory space.
- */
- if (relocated_ramdisk)
- container = (u8 *)(__va(relocated_ramdisk) +
- (cont - boot_params.hdr.ramdisk_image));
- else
- container = cont_va;
+ if (!(cp.data && cp.size)) {
+ cont.size = -1;
+ return -EINVAL;
+ }
- /* Add CONFIG_RANDOMIZE_MEMORY offset. */
- if (!ucode_builtin)
- container += PAGE_OFFSET - __PAGE_OFFSET_BASE;
+ cont = find_proper_container(cp.data, cp.size, &eq_id);
+ if (!eq_id) {
+ cont.size = -1;
+ return -EINVAL;
+ }
- eax = cpuid_eax(0x00000001);
- eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+ } else
+ return -EINVAL;
+ }
- ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
+ ret = load_microcode_amd(smp_processor_id(), fam, cont.data, cont.size);
if (ret != UCODE_OK)
retval = -EINVAL;
@@ -459,8 +461,8 @@ int __init save_microcode_in_initrd_amd(void)
* This will be freed any msec now, stash patches for the current
* family and switch to patch cache for cpu hotplug, etc later.
*/
- container = NULL;
- container_size = 0;
+ cont.data = NULL;
+ cont.size = 0;
return retval;
}
@@ -478,8 +480,10 @@ void reload_ucode_amd(void)
return;
mc = (struct microcode_amd *)amd_ucode_patch;
+ if (!mc)
+ return;
- if (mc && rev < mc->hdr.patch_id) {
+ if (rev < mc->hdr.patch_id) {
if (!__apply_microcode_amd(mc)) {
ucode_new_rev = mc->hdr.patch_id;
pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
@@ -513,7 +517,7 @@ static struct ucode_patch *cache_find_patch(u16 equiv_cpu)
{
struct ucode_patch *p;
- list_for_each_entry(p, &pcache, plist)
+ list_for_each_entry(p, &microcode_cache, plist)
if (p->equiv_cpu == equiv_cpu)
return p;
return NULL;
@@ -523,7 +527,7 @@ static void update_cache(struct ucode_patch *new_patch)
{
struct ucode_patch *p;
- list_for_each_entry(p, &pcache, plist) {
+ list_for_each_entry(p, &microcode_cache, plist) {
if (p->equiv_cpu == new_patch->equiv_cpu) {
if (p->patch_id >= new_patch->patch_id)
/* we already have the latest patch */
@@ -536,14 +540,14 @@ static void update_cache(struct ucode_patch *new_patch)
}
}
/* no patch found, add it */
- list_add_tail(&new_patch->plist, &pcache);
+ list_add_tail(&new_patch->plist, &microcode_cache);
}
static void free_cache(void)
{
struct ucode_patch *p, *tmp;
- list_for_each_entry_safe(p, tmp, &pcache, plist) {
+ list_for_each_entry_safe(p, tmp, &microcode_cache, plist) {
__list_del(p->plist.prev, p->plist.next);
kfree(p->data);
kfree(p);
@@ -663,21 +667,7 @@ bool check_current_patch_level(u32 *rev, bool early)
return ret;
}
-int __apply_microcode_amd(struct microcode_amd *mc_amd)
-{
- u32 rev, dummy;
-
- native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
-
- /* verify patch application was successful */
- native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
- if (rev != mc_amd->hdr.patch_id)
- return -1;
-
- return 0;
-}
-
-int apply_microcode_amd(int cpu)
+static int apply_microcode_amd(int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct microcode_amd *mc_amd;
@@ -860,7 +850,8 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
return UCODE_OK;
}
-enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
+static enum ucode_state
+load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
{
enum ucode_state ret;
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 5ce5155f0695..6996413c78c3 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
* 2006 Shaohua Li <shaohua.li@intel.com>
- * 2013-2015 Borislav Petkov <bp@alien8.de>
+ * 2013-2016 Borislav Petkov <bp@alien8.de>
*
* X86 CPU microcode early update for Linux:
*
@@ -39,12 +39,15 @@
#include <asm/microcode.h>
#include <asm/processor.h>
#include <asm/cmdline.h>
+#include <asm/setup.h>
-#define MICROCODE_VERSION "2.01"
+#define DRIVER_VERSION "2.2"
static struct microcode_ops *microcode_ops;
static bool dis_ucode_ldr;
+LIST_HEAD(microcode_cache);
+
/*
* Synchronization.
*
@@ -167,7 +170,7 @@ void load_ucode_ap(void)
break;
case X86_VENDOR_AMD:
if (family >= 0x10)
- load_ucode_amd_ap();
+ load_ucode_amd_ap(family);
break;
default:
break;
@@ -185,7 +188,7 @@ static int __init save_microcode_in_initrd(void)
break;
case X86_VENDOR_AMD:
if (c->x86 >= 0x10)
- return save_microcode_in_initrd_amd();
+ return save_microcode_in_initrd_amd(c->x86);
break;
default:
break;
@@ -194,6 +197,58 @@ static int __init save_microcode_in_initrd(void)
return -EINVAL;
}
+struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ unsigned long start = 0;
+ size_t size;
+
+#ifdef CONFIG_X86_32
+ struct boot_params *params;
+
+ if (use_pa)
+ params = (struct boot_params *)__pa_nodebug(&boot_params);
+ else
+ params = &boot_params;
+
+ size = params->hdr.ramdisk_size;
+
+ /*
+ * Set start only if we have an initrd image. We cannot use initrd_start
+ * because it is not set that early yet.
+ */
+ if (size)
+ start = params->hdr.ramdisk_image;
+
+# else /* CONFIG_X86_64 */
+ size = (unsigned long)boot_params.ext_ramdisk_size << 32;
+ size |= boot_params.hdr.ramdisk_size;
+
+ if (size) {
+ start = (unsigned long)boot_params.ext_ramdisk_image << 32;
+ start |= boot_params.hdr.ramdisk_image;
+
+ start += PAGE_OFFSET;
+ }
+# endif
+
+ /*
+ * Did we relocate the ramdisk?
+ *
+ * So we possibly relocate the ramdisk *after* applying microcode on the
+ * BSP so we rely on use_pa (use physical addresses) - even if it is not
+ * absolutely correct - to determine whether we've done the ramdisk
+ * relocation already.
+ */
+ if (!use_pa && relocated_ramdisk)
+ start = initrd_start;
+
+ return find_cpio_data(path, (void *)start, size, NULL);
+#else /* !CONFIG_BLK_DEV_INITRD */
+ return (struct cpio_data){ NULL, 0, "" };
+#endif
+}
+
void reload_early_microcode(void)
{
int vendor, family;
@@ -453,16 +508,17 @@ static struct attribute_group mc_attr_group = {
static void microcode_fini_cpu(int cpu)
{
- microcode_ops->microcode_fini_cpu(cpu);
+ if (microcode_ops->microcode_fini_cpu)
+ microcode_ops->microcode_fini_cpu(cpu);
}
static enum ucode_state microcode_resume_cpu(int cpu)
{
- pr_debug("CPU%d updated upon resume\n", cpu);
-
if (apply_microcode_on_target(cpu))
return UCODE_ERROR;
+ pr_debug("CPU%d updated upon resume\n", cpu);
+
return UCODE_OK;
}
@@ -496,6 +552,9 @@ static enum ucode_state microcode_update_cpu(int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ /* Refresh CPU microcode revision after resume. */
+ collect_cpu_info(cpu);
+
if (uci->valid)
return microcode_resume_cpu(cpu);
@@ -579,12 +638,7 @@ static int mc_cpu_down_prep(unsigned int cpu)
/* Suspend is in progress, only remove the interface */
sysfs_remove_group(&dev->kobj, &mc_attr_group);
pr_debug("CPU%d removed\n", cpu);
- /*
- * When a CPU goes offline, don't free up or invalidate the copy of
- * the microcode in kernel memory, so that we can reuse it when the
- * CPU comes back online without unnecessarily requesting the userspace
- * for it again.
- */
+
return 0;
}
@@ -649,8 +703,7 @@ int __init microcode_init(void)
cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
mc_cpu_online, mc_cpu_down_prep);
- pr_info("Microcode Update Driver: v" MICROCODE_VERSION
- " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
+ pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
return 0;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index cdc0deab00c9..54d50c3694d8 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -39,125 +39,83 @@
#include <asm/setup.h>
#include <asm/msr.h>
-/*
- * Temporary microcode blobs pointers storage. We note here during early load
- * the pointers to microcode blobs we've got from whatever storage (detached
- * initrd, builtin). Later on, we put those into final storage
- * mc_saved_data.mc_saved.
- *
- * Important: those are offsets from the beginning of initrd or absolute
- * addresses within the kernel image when built-in.
- */
-static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT];
-
-static struct mc_saved_data {
- unsigned int num_saved;
- struct microcode_intel **mc_saved;
-} mc_saved_data;
+static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
-/* Microcode blobs within the initrd. 0 if builtin. */
-static struct ucode_blobs {
- unsigned long start;
- bool valid;
-} blobs;
+/* Current microcode patch used in early patching */
+struct microcode_intel *intel_ucode_patch;
-/* Go through saved patches and find the one suitable for the current CPU. */
-static enum ucode_state
-find_microcode_patch(struct microcode_intel **saved,
- unsigned int num_saved, struct ucode_cpu_info *uci)
+static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
+ unsigned int s2, unsigned int p2)
{
- struct microcode_intel *ucode_ptr, *new_mc = NULL;
- struct microcode_header_intel *mc_hdr;
- int new_rev, ret, i;
-
- new_rev = uci->cpu_sig.rev;
-
- for (i = 0; i < num_saved; i++) {
- ucode_ptr = saved[i];
- mc_hdr = (struct microcode_header_intel *)ucode_ptr;
-
- ret = has_newer_microcode(ucode_ptr,
- uci->cpu_sig.sig,
- uci->cpu_sig.pf,
- new_rev);
- if (!ret)
- continue;
-
- new_rev = mc_hdr->rev;
- new_mc = ucode_ptr;
- }
+ if (s1 != s2)
+ return false;
- if (!new_mc)
- return UCODE_NFOUND;
+ /* Processor flags are either both 0 ... */
+ if (!p1 && !p2)
+ return true;
- uci->mc = (struct microcode_intel *)new_mc;
- return UCODE_OK;
+ /* ... or they intersect. */
+ return p1 & p2;
}
-static inline void
-copy_ptrs(struct microcode_intel **mc_saved, unsigned long *mc_ptrs,
- unsigned long off, int num_saved)
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+static int find_matching_signature(void *mc, unsigned int csig, int cpf)
{
+ struct microcode_header_intel *mc_hdr = mc;
+ struct extended_sigtable *ext_hdr;
+ struct extended_signature *ext_sig;
int i;
- for (i = 0; i < num_saved; i++)
- mc_saved[i] = (struct microcode_intel *)(mc_ptrs[i] + off);
-}
-
-#ifdef CONFIG_X86_32
-static void
-microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mcs)
-{
- int i;
- struct microcode_intel ***mc_saved;
+ if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+ return 1;
- mc_saved = (struct microcode_intel ***)__pa_nodebug(&mcs->mc_saved);
+ /* Look for ext. headers: */
+ if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
+ return 0;
- for (i = 0; i < mcs->num_saved; i++) {
- struct microcode_intel *p;
+ ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
+ ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
- p = *(struct microcode_intel **)__pa_nodebug(mcs->mc_saved + i);
- mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
+ for (i = 0; i < ext_hdr->count; i++) {
+ if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+ return 1;
+ ext_sig++;
}
+ return 0;
}
-#endif
-static enum ucode_state
-load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
- unsigned long offset, struct ucode_cpu_info *uci)
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
{
- struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
- unsigned int count = mcs->num_saved;
+ struct microcode_header_intel *mc_hdr = mc;
- if (!mcs->mc_saved) {
- copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count);
+ if (mc_hdr->rev <= new_rev)
+ return 0;
- return find_microcode_patch(mc_saved_tmp, count, uci);
- } else {
-#ifdef CONFIG_X86_32
- microcode_phys(mc_saved_tmp, mcs);
- return find_microcode_patch(mc_saved_tmp, count, uci);
-#else
- return find_microcode_patch(mcs->mc_saved, count, uci);
-#endif
- }
+ return find_matching_signature(mc, csig, cpf);
}
/*
* Given CPU signature and a microcode patch, this function finds if the
* microcode patch has matching family and model with the CPU.
+ *
+ * %true - if there's a match
+ * %false - otherwise
*/
-static enum ucode_state
-matching_model_microcode(struct microcode_header_intel *mc_header,
- unsigned long sig)
+static bool microcode_matches(struct microcode_header_intel *mc_header,
+ unsigned long sig)
{
- unsigned int fam, model;
- unsigned int fam_ucode, model_ucode;
- struct extended_sigtable *ext_header;
unsigned long total_size = get_totalsize(mc_header);
unsigned long data_size = get_datasize(mc_header);
- int ext_sigcount, i;
+ struct extended_sigtable *ext_header;
+ unsigned int fam_ucode, model_ucode;
struct extended_signature *ext_sig;
+ unsigned int fam, model;
+ int ext_sigcount, i;
fam = x86_family(sig);
model = x86_model(sig);
@@ -166,11 +124,11 @@ matching_model_microcode(struct microcode_header_intel *mc_header,
model_ucode = x86_model(mc_header->sig);
if (fam == fam_ucode && model == model_ucode)
- return UCODE_OK;
+ return true;
/* Look for ext. headers: */
if (total_size <= data_size + MC_HEADER_SIZE)
- return UCODE_NFOUND;
+ return false;
ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE;
ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
@@ -181,192 +139,242 @@ matching_model_microcode(struct microcode_header_intel *mc_header,
model_ucode = x86_model(ext_sig->sig);
if (fam == fam_ucode && model == model_ucode)
- return UCODE_OK;
+ return true;
ext_sig++;
}
- return UCODE_NFOUND;
+ return false;
}
-static int
-save_microcode(struct mc_saved_data *mcs,
- struct microcode_intel **mc_saved_src,
- unsigned int num_saved)
+static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)
{
- int i, j;
- struct microcode_intel **saved_ptr;
- int ret;
+ struct ucode_patch *p;
- if (!num_saved)
- return -EINVAL;
+ p = kzalloc(size, GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
- /*
- * Copy new microcode data.
- */
- saved_ptr = kcalloc(num_saved, sizeof(struct microcode_intel *), GFP_KERNEL);
- if (!saved_ptr)
- return -ENOMEM;
-
- for (i = 0; i < num_saved; i++) {
- struct microcode_header_intel *mc_hdr;
- struct microcode_intel *mc;
- unsigned long size;
-
- if (!mc_saved_src[i]) {
- ret = -EINVAL;
- goto err;
- }
+ p->data = kmemdup(data, size, GFP_KERNEL);
+ if (!p->data) {
+ kfree(p);
+ return ERR_PTR(-ENOMEM);
+ }
- mc = mc_saved_src[i];
- mc_hdr = &mc->hdr;
- size = get_totalsize(mc_hdr);
+ return p;
+}
- saved_ptr[i] = kmemdup(mc, size, GFP_KERNEL);
- if (!saved_ptr[i]) {
- ret = -ENOMEM;
- goto err;
+static void save_microcode_patch(void *data, unsigned int size)
+{
+ struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
+ struct ucode_patch *iter, *tmp, *p;
+ bool prev_found = false;
+ unsigned int sig, pf;
+
+ mc_hdr = (struct microcode_header_intel *)data;
+
+ list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
+ mc_saved_hdr = (struct microcode_header_intel *)iter->data;
+ sig = mc_saved_hdr->sig;
+ pf = mc_saved_hdr->pf;
+
+ if (find_matching_signature(data, sig, pf)) {
+ prev_found = true;
+
+ if (mc_hdr->rev <= mc_saved_hdr->rev)
+ continue;
+
+ p = __alloc_microcode_buf(data, size);
+ if (IS_ERR(p))
+ pr_err("Error allocating buffer %p\n", data);
+ else
+ list_replace(&iter->plist, &p->plist);
}
}
/*
- * Point to newly saved microcode.
+ * There weren't any previous patches found in the list cache; save the
+ * newly found.
*/
- mcs->mc_saved = saved_ptr;
- mcs->num_saved = num_saved;
-
- return 0;
-
-err:
- for (j = 0; j <= i; j++)
- kfree(saved_ptr[j]);
- kfree(saved_ptr);
-
- return ret;
+ if (!prev_found) {
+ p = __alloc_microcode_buf(data, size);
+ if (IS_ERR(p))
+ pr_err("Error allocating buffer for %p\n", data);
+ else
+ list_add_tail(&p->plist, &microcode_cache);
+ }
}
-/*
- * A microcode patch in ucode_ptr is saved into mc_saved
- * - if it has matching signature and newer revision compared to an existing
- * patch mc_saved.
- * - or if it is a newly discovered microcode patch.
- *
- * The microcode patch should have matching model with CPU.
- *
- * Returns: The updated number @num_saved of saved microcode patches.
- */
-static unsigned int _save_mc(struct microcode_intel **mc_saved,
- u8 *ucode_ptr, unsigned int num_saved)
+static int microcode_sanity_check(void *mc, int print_err)
{
- struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
- unsigned int sig, pf;
- int found = 0, i;
+ unsigned long total_size, data_size, ext_table_size;
+ struct microcode_header_intel *mc_header = mc;
+ struct extended_sigtable *ext_header = NULL;
+ u32 sum, orig_sum, ext_sigcount = 0, i;
+ struct extended_signature *ext_sig;
- mc_hdr = (struct microcode_header_intel *)ucode_ptr;
+ total_size = get_totalsize(mc_header);
+ data_size = get_datasize(mc_header);
- for (i = 0; i < num_saved; i++) {
- mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i];
- sig = mc_saved_hdr->sig;
- pf = mc_saved_hdr->pf;
+ if (data_size + MC_HEADER_SIZE > total_size) {
+ if (print_err)
+ pr_err("Error: bad microcode data file size.\n");
+ return -EINVAL;
+ }
- if (!find_matching_signature(ucode_ptr, sig, pf))
- continue;
+ if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+ if (print_err)
+ pr_err("Error: invalid/unknown microcode update format.\n");
+ return -EINVAL;
+ }
- found = 1;
+ ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+ if (ext_table_size) {
+ u32 ext_table_sum = 0;
+ u32 *ext_tablep;
- if (mc_hdr->rev <= mc_saved_hdr->rev)
- continue;
+ if ((ext_table_size < EXT_HEADER_SIZE)
+ || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+ if (print_err)
+ pr_err("Error: truncated extended signature table.\n");
+ return -EINVAL;
+ }
+
+ ext_header = mc + MC_HEADER_SIZE + data_size;
+ if (ext_table_size != exttable_size(ext_header)) {
+ if (print_err)
+ pr_err("Error: extended signature table size mismatch.\n");
+ return -EFAULT;
+ }
+
+ ext_sigcount = ext_header->count;
/*
- * Found an older ucode saved earlier. Replace it with
- * this newer one.
+ * Check extended table checksum: the sum of all dwords that
+ * comprise a valid table must be 0.
*/
- mc_saved[i] = (struct microcode_intel *)ucode_ptr;
- break;
+ ext_tablep = (u32 *)ext_header;
+
+ i = ext_table_size / sizeof(u32);
+ while (i--)
+ ext_table_sum += ext_tablep[i];
+
+ if (ext_table_sum) {
+ if (print_err)
+ pr_warn("Bad extended signature table checksum, aborting.\n");
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Calculate the checksum of update data and header. The checksum of
+ * valid update data and header including the extended signature table
+ * must be 0.
+ */
+ orig_sum = 0;
+ i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
+ while (i--)
+ orig_sum += ((u32 *)mc)[i];
+
+ if (orig_sum) {
+ if (print_err)
+ pr_err("Bad microcode data checksum, aborting.\n");
+ return -EINVAL;
}
- /* Newly detected microcode, save it to memory. */
- if (i >= num_saved && !found)
- mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr;
+ if (!ext_table_size)
+ return 0;
- return num_saved;
+ /*
+ * Check extended signature checksum: 0 => valid.
+ */
+ for (i = 0; i < ext_sigcount; i++) {
+ ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+ EXT_SIGNATURE_SIZE * i;
+
+ sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
+ (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+ if (sum) {
+ if (print_err)
+ pr_err("Bad extended signature checksum, aborting.\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
}
/*
* Get microcode matching with BSP's model. Only CPUs with the same model as
* BSP can stay in the platform.
*/
-static enum ucode_state __init
-get_matching_model_microcode(unsigned long start, void *data, size_t size,
- struct mc_saved_data *mcs, unsigned long *mc_ptrs,
- struct ucode_cpu_info *uci)
+static struct microcode_intel *
+scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
{
- struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
struct microcode_header_intel *mc_header;
- unsigned int num_saved = mcs->num_saved;
- enum ucode_state state = UCODE_OK;
- unsigned int leftover = size;
- u8 *ucode_ptr = data;
+ struct microcode_intel *patch = NULL;
unsigned int mc_size;
- int i;
-
- while (leftover && num_saved < ARRAY_SIZE(mc_saved_tmp)) {
- if (leftover < sizeof(mc_header))
+ while (size) {
+ if (size < sizeof(struct microcode_header_intel))
break;
- mc_header = (struct microcode_header_intel *)ucode_ptr;
+ mc_header = (struct microcode_header_intel *)data;
mc_size = get_totalsize(mc_header);
- if (!mc_size || mc_size > leftover ||
- microcode_sanity_check(ucode_ptr, 0) < 0)
+ if (!mc_size ||
+ mc_size > size ||
+ microcode_sanity_check(data, 0) < 0)
break;
- leftover -= mc_size;
+ size -= mc_size;
- /*
- * Since APs with same family and model as the BSP may boot in
- * the platform, we need to find and save microcode patches
- * with the same family and model as the BSP.
- */
- if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != UCODE_OK) {
- ucode_ptr += mc_size;
+ if (!microcode_matches(mc_header, uci->cpu_sig.sig)) {
+ data += mc_size;
continue;
}
- num_saved = _save_mc(mc_saved_tmp, ucode_ptr, num_saved);
+ if (save) {
+ save_microcode_patch(data, mc_size);
+ goto next;
+ }
- ucode_ptr += mc_size;
- }
- if (leftover) {
- state = UCODE_ERROR;
- return state;
- }
+ if (!patch) {
+ if (!has_newer_microcode(data,
+ uci->cpu_sig.sig,
+ uci->cpu_sig.pf,
+ uci->cpu_sig.rev))
+ goto next;
- if (!num_saved) {
- state = UCODE_NFOUND;
- return state;
- }
+ } else {
+ struct microcode_header_intel *phdr = &patch->hdr;
- for (i = 0; i < num_saved; i++)
- mc_ptrs[i] = (unsigned long)mc_saved_tmp[i] - start;
+ if (!has_newer_microcode(data,
+ phdr->sig,
+ phdr->pf,
+ phdr->rev))
+ goto next;
+ }
+
+ /* We have a newer patch, save it. */
+ patch = data;
- mcs->num_saved = num_saved;
+next:
+ data += mc_size;
+ }
- return state;
+ if (size)
+ return NULL;
+
+ return patch;
}
static int collect_cpu_info_early(struct ucode_cpu_info *uci)
{
unsigned int val[2];
unsigned int family, model;
- struct cpu_signature csig;
+ struct cpu_signature csig = { 0 };
unsigned int eax, ebx, ecx, edx;
- csig.sig = 0;
- csig.pf = 0;
- csig.rev = 0;
-
memset(uci, 0, sizeof(*uci));
eax = 0x00000001;
@@ -374,8 +382,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
native_cpuid(&eax, &ebx, &ecx, &edx);
csig.sig = eax;
- family = x86_family(csig.sig);
- model = x86_model(csig.sig);
+ family = x86_family(eax);
+ model = x86_model(eax);
if ((model >= 5) || (family > 6)) {
/* get processor flags from MSR 0x17 */
@@ -401,40 +409,41 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
static void show_saved_mc(void)
{
#ifdef DEBUG
- int i, j;
+ int i = 0, j;
unsigned int sig, pf, rev, total_size, data_size, date;
struct ucode_cpu_info uci;
+ struct ucode_patch *p;
- if (!mc_saved_data.num_saved) {
+ if (list_empty(&microcode_cache)) {
pr_debug("no microcode data saved.\n");
return;
}
- pr_debug("Total microcode saved: %d\n", mc_saved_data.num_saved);
collect_cpu_info_early(&uci);
- sig = uci.cpu_sig.sig;
- pf = uci.cpu_sig.pf;
- rev = uci.cpu_sig.rev;
+ sig = uci.cpu_sig.sig;
+ pf = uci.cpu_sig.pf;
+ rev = uci.cpu_sig.rev;
pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
- for (i = 0; i < mc_saved_data.num_saved; i++) {
+ list_for_each_entry(p, &microcode_cache, plist) {
struct microcode_header_intel *mc_saved_header;
struct extended_sigtable *ext_header;
- int ext_sigcount;
struct extended_signature *ext_sig;
+ int ext_sigcount;
+
+ mc_saved_header = (struct microcode_header_intel *)p->data;
- mc_saved_header = (struct microcode_header_intel *)
- mc_saved_data.mc_saved[i];
- sig = mc_saved_header->sig;
- pf = mc_saved_header->pf;
- rev = mc_saved_header->rev;
- total_size = get_totalsize(mc_saved_header);
- data_size = get_datasize(mc_saved_header);
- date = mc_saved_header->date;
+ sig = mc_saved_header->sig;
+ pf = mc_saved_header->pf;
+ rev = mc_saved_header->rev;
+ date = mc_saved_header->date;
+
+ total_size = get_totalsize(mc_saved_header);
+ data_size = get_datasize(mc_saved_header);
pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, total size=0x%x, date = %04x-%02x-%02x\n",
- i, sig, pf, rev, total_size,
+ i++, sig, pf, rev, total_size,
date & 0xffff,
date >> 24,
(date >> 16) & 0xff);
@@ -443,7 +452,7 @@ static void show_saved_mc(void)
if (total_size <= data_size + MC_HEADER_SIZE)
continue;
- ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE;
+ ext_header = (void *)mc_saved_header + data_size + MC_HEADER_SIZE;
ext_sigcount = ext_header->count;
ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
@@ -456,85 +465,43 @@ static void show_saved_mc(void)
ext_sig++;
}
-
}
#endif
}
/*
- * Save this mc into mc_saved_data. So it will be loaded early when a CPU is
- * hot added or resumes.
- *
- * Please make sure this mc should be a valid microcode patch before calling
- * this function.
+ * Save this microcode patch. It will be loaded early when a CPU is
+ * hot-added or resumes.
*/
-static void save_mc_for_early(u8 *mc)
+static void save_mc_for_early(u8 *mc, unsigned int size)
{
#ifdef CONFIG_HOTPLUG_CPU
/* Synchronization during CPU hotplug. */
static DEFINE_MUTEX(x86_cpu_microcode_mutex);
- struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
- unsigned int mc_saved_count_init;
- unsigned int num_saved;
- struct microcode_intel **mc_saved;
- int ret, i;
-
mutex_lock(&x86_cpu_microcode_mutex);
- mc_saved_count_init = mc_saved_data.num_saved;
- num_saved = mc_saved_data.num_saved;
- mc_saved = mc_saved_data.mc_saved;
-
- if (mc_saved && num_saved)
- memcpy(mc_saved_tmp, mc_saved,
- num_saved * sizeof(struct microcode_intel *));
- /*
- * Save the microcode patch mc in mc_save_tmp structure if it's a newer
- * version.
- */
- num_saved = _save_mc(mc_saved_tmp, mc, num_saved);
-
- /*
- * Save the mc_save_tmp in global mc_saved_data.
- */
- ret = save_microcode(&mc_saved_data, mc_saved_tmp, num_saved);
- if (ret) {
- pr_err("Cannot save microcode patch.\n");
- goto out;
- }
-
+ save_microcode_patch(mc, size);
show_saved_mc();
- /*
- * Free old saved microcode data.
- */
- if (mc_saved) {
- for (i = 0; i < mc_saved_count_init; i++)
- kfree(mc_saved[i]);
- kfree(mc_saved);
- }
-
-out:
mutex_unlock(&x86_cpu_microcode_mutex);
#endif
}
-static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
+static bool load_builtin_intel_microcode(struct cpio_data *cp)
{
-#ifdef CONFIG_X86_64
- unsigned int eax = 0x00000001, ebx, ecx = 0, edx;
+ unsigned int eax = 1, ebx, ecx = 0, edx;
char name[30];
+ if (IS_ENABLED(CONFIG_X86_32))
+ return false;
+
native_cpuid(&eax, &ebx, &ecx, &edx);
sprintf(name, "intel-ucode/%02x-%02x-%02x",
x86_family(eax), x86_model(eax), x86_stepping(eax));
return get_builtin_firmware(cp, name);
-#else
- return false;
-#endif
}
/*
@@ -570,8 +537,7 @@ void show_ucode_info_early(void)
}
/*
- * At this point, we can not call printk() yet. Keep microcode patch number in
- * mc_saved_data.mc_saved and delay printing microcode info in
+ * At this point, we can not call printk() yet. Delay printing microcode info in
* show_ucode_info_early() until printk() works.
*/
static void print_ucode(struct ucode_cpu_info *uci)
@@ -648,206 +614,140 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
return 0;
}
-/*
- * This function converts microcode patch offsets previously stored in
- * mc_tmp_ptrs to pointers and stores the pointers in mc_saved_data.
- */
int __init save_microcode_in_initrd_intel(void)
{
- struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
- unsigned int count = mc_saved_data.num_saved;
- unsigned long offset = 0;
- int ret;
-
- if (!count)
- return 0;
+ struct ucode_cpu_info uci;
+ struct cpio_data cp;
/*
- * We have found a valid initrd but it might've been relocated in the
- * meantime so get its updated address.
+ * AP loading didn't find any microcode patch, no need to save anything.
*/
- if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && blobs.valid)
- offset = initrd_start;
-
- copy_ptrs(mc_saved, mc_tmp_ptrs, offset, count);
+ if (!intel_ucode_patch || IS_ERR(intel_ucode_patch))
+ return 0;
- ret = save_microcode(&mc_saved_data, mc_saved, count);
- if (ret)
- pr_err("Cannot save microcode patches from initrd.\n");
- else
- show_saved_mc();
+ if (!load_builtin_intel_microcode(&cp))
+ cp = find_microcode_in_initrd(ucode_path, false);
- return ret;
-}
+ if (!(cp.data && cp.size))
+ return 0;
-static __init enum ucode_state
-__scan_microcode_initrd(struct cpio_data *cd, struct ucode_blobs *blbp)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
- char *p = IS_ENABLED(CONFIG_X86_32) ? (char *)__pa_nodebug(ucode_name)
- : ucode_name;
-# ifdef CONFIG_X86_32
- unsigned long start = 0, size;
- struct boot_params *params;
+ collect_cpu_info_early(&uci);
- params = (struct boot_params *)__pa_nodebug(&boot_params);
- size = params->hdr.ramdisk_size;
+ scan_microcode(cp.data, cp.size, &uci, true);
- /*
- * Set start only if we have an initrd image. We cannot use initrd_start
- * because it is not set that early yet.
- */
- start = (size ? params->hdr.ramdisk_image : 0);
+ show_saved_mc();
-# else /* CONFIG_X86_64 */
- unsigned long start = 0, size;
+ return 0;
+}
- size = (u64)boot_params.ext_ramdisk_size << 32;
- size |= boot_params.hdr.ramdisk_size;
- if (size) {
- start = (u64)boot_params.ext_ramdisk_image << 32;
- start |= boot_params.hdr.ramdisk_image;
+/*
+ * @res_patch, output: a pointer to the patch we found.
+ */
+static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
+{
+ static const char *path;
+ struct cpio_data cp;
+ bool use_pa;
- start += PAGE_OFFSET;
+ if (IS_ENABLED(CONFIG_X86_32)) {
+ path = (const char *)__pa_nodebug(ucode_path);
+ use_pa = true;
+ } else {
+ path = ucode_path;
+ use_pa = false;
}
-# endif
-
- *cd = find_cpio_data(p, (void *)start, size, NULL);
- if (cd->data) {
- blbp->start = start;
- blbp->valid = true;
- return UCODE_OK;
- } else
-#endif /* CONFIG_BLK_DEV_INITRD */
- return UCODE_ERROR;
-}
+ /* try built-in microcode first */
+ if (!load_builtin_intel_microcode(&cp))
+ cp = find_microcode_in_initrd(path, use_pa);
-static __init enum ucode_state
-scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
- struct ucode_cpu_info *uci, struct ucode_blobs *blbp)
-{
- struct cpio_data cd = { NULL, 0, "" };
- enum ucode_state ret;
+ if (!(cp.data && cp.size))
+ return NULL;
- /* try built-in microcode first */
- if (load_builtin_intel_microcode(&cd))
- /*
- * Invalidate blobs as we might've gotten an initrd too,
- * supplied by the boot loader, by mistake or simply forgotten
- * there. That's fine, we ignore it since we've found builtin
- * microcode already.
- */
- blbp->valid = false;
- else {
- ret = __scan_microcode_initrd(&cd, blbp);
- if (ret != UCODE_OK)
- return ret;
- }
+ collect_cpu_info_early(uci);
- return get_matching_model_microcode(blbp->start, cd.data, cd.size,
- mcs, mc_ptrs, uci);
+ return scan_microcode(cp.data, cp.size, uci, false);
}
-static void __init
-_load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
- struct ucode_blobs *blbp)
+void __init load_ucode_intel_bsp(void)
{
+ struct microcode_intel *patch;
struct ucode_cpu_info uci;
- enum ucode_state ret;
-
- collect_cpu_info_early(&uci);
- ret = scan_microcode(mcs, mc_ptrs, &uci, blbp);
- if (ret != UCODE_OK)
+ patch = __load_ucode_intel(&uci);
+ if (!patch)
return;
- ret = load_microcode(mcs, mc_ptrs, blbp->start, &uci);
- if (ret != UCODE_OK)
- return;
+ uci.mc = patch;
apply_microcode_early(&uci, true);
}
-void __init load_ucode_intel_bsp(void)
+void load_ucode_intel_ap(void)
{
- struct ucode_blobs *blobs_p;
- struct mc_saved_data *mcs;
- unsigned long *ptrs;
+ struct microcode_intel *patch, **iup;
+ struct ucode_cpu_info uci;
-#ifdef CONFIG_X86_32
- mcs = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
- ptrs = (unsigned long *)__pa_nodebug(&mc_tmp_ptrs);
- blobs_p = (struct ucode_blobs *)__pa_nodebug(&blobs);
-#else
- mcs = &mc_saved_data;
- ptrs = mc_tmp_ptrs;
- blobs_p = &blobs;
-#endif
+ if (IS_ENABLED(CONFIG_X86_32))
+ iup = (struct microcode_intel **) __pa_nodebug(&intel_ucode_patch);
+ else
+ iup = &intel_ucode_patch;
+
+reget:
+ if (!*iup) {
+ patch = __load_ucode_intel(&uci);
+ if (!patch)
+ return;
+
+ *iup = patch;
+ }
- _load_ucode_intel_bsp(mcs, ptrs, blobs_p);
+ uci.mc = *iup;
+
+ if (apply_microcode_early(&uci, true)) {
+ /* Mixed-silicon system? Try to refetch the proper patch: */
+ *iup = NULL;
+
+ goto reget;
+ }
}
-void load_ucode_intel_ap(void)
+static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
{
- struct ucode_blobs *blobs_p;
- unsigned long *ptrs, start = 0;
- struct mc_saved_data *mcs;
- struct ucode_cpu_info uci;
- enum ucode_state ret;
+ struct microcode_header_intel *phdr;
+ struct ucode_patch *iter, *tmp;
-#ifdef CONFIG_X86_32
- mcs = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
- ptrs = (unsigned long *)__pa_nodebug(mc_tmp_ptrs);
- blobs_p = (struct ucode_blobs *)__pa_nodebug(&blobs);
-#else
- mcs = &mc_saved_data;
- ptrs = mc_tmp_ptrs;
- blobs_p = &blobs;
-#endif
-
- /*
- * If there is no valid ucode previously saved in memory, no need to
- * update ucode on this AP.
- */
- if (!mcs->num_saved)
- return;
+ list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
- if (blobs_p->valid) {
- start = blobs_p->start;
+ phdr = (struct microcode_header_intel *)iter->data;
- /*
- * Pay attention to CONFIG_RANDOMIZE_MEMORY=y as it shuffles
- * physmem mapping too and there we have the initrd.
- */
- start += PAGE_OFFSET - __PAGE_OFFSET_BASE;
- }
+ if (phdr->rev <= uci->cpu_sig.rev)
+ continue;
- collect_cpu_info_early(&uci);
- ret = load_microcode(mcs, ptrs, start, &uci);
- if (ret != UCODE_OK)
- return;
+ if (!find_matching_signature(phdr,
+ uci->cpu_sig.sig,
+ uci->cpu_sig.pf))
+ continue;
- apply_microcode_early(&uci, true);
+ return iter->data;
+ }
+ return NULL;
}
void reload_ucode_intel(void)
{
+ struct microcode_intel *p;
struct ucode_cpu_info uci;
- enum ucode_state ret;
-
- if (!mc_saved_data.num_saved)
- return;
collect_cpu_info_early(&uci);
- ret = find_microcode_patch(mc_saved_data.mc_saved,
- mc_saved_data.num_saved, &uci);
- if (ret != UCODE_OK)
+ p = find_patch(&uci);
+ if (!p)
return;
+ uci.mc = p;
+
apply_microcode_early(&uci, false);
}
@@ -879,24 +779,6 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
return 0;
}
-/*
- * return 0 - no update found
- * return 1 - found update
- */
-static int get_matching_mc(struct microcode_intel *mc, int cpu)
-{
- struct cpu_signature cpu_sig;
- unsigned int csig, cpf, crev;
-
- collect_cpu_info(cpu, &cpu_sig);
-
- csig = cpu_sig.sig;
- cpf = cpu_sig.pf;
- crev = cpu_sig.rev;
-
- return has_newer_microcode(mc, csig, cpf, crev);
-}
-
static int apply_microcode_intel(int cpu)
{
struct microcode_intel *mc;
@@ -911,16 +793,12 @@ static int apply_microcode_intel(int cpu)
uci = ucode_cpu_info + cpu;
mc = uci->mc;
- if (!mc)
- return 0;
-
- /*
- * Microcode on this CPU could be updated earlier. Only apply the
- * microcode patch in mc when it is newer than the one on this
- * CPU.
- */
- if (!get_matching_mc(mc, cpu))
- return 0;
+ if (!mc) {
+ /* Look for a newer patch in our cache: */
+ mc = find_patch(uci);
+ if (!mc)
+ return 0;
+ }
/* write microcode via MSR 0x79 */
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
@@ -962,7 +840,6 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
int new_rev = uci->cpu_sig.rev;
unsigned int leftover = size;
- enum ucode_state state = UCODE_OK;
unsigned int curr_mc_size = 0;
unsigned int csig, cpf;
@@ -1015,14 +892,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
if (leftover) {
vfree(new_mc);
- state = UCODE_ERROR;
- goto out;
+ return UCODE_ERROR;
}
- if (!new_mc) {
- state = UCODE_NFOUND;
- goto out;
- }
+ if (!new_mc)
+ return UCODE_NFOUND;
vfree(uci->mc);
uci->mc = (struct microcode_intel *)new_mc;
@@ -1032,12 +906,12 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
* permanent memory. So it will be loaded early when a CPU is hot added
* or resumes.
*/
- save_mc_for_early(new_mc);
+ save_mc_for_early(new_mc, curr_mc_size);
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
cpu, new_rev, uci->cpu_sig.rev);
-out:
- return state;
+
+ return UCODE_OK;
}
static int get_ucode_fw(void *to, const void *from, size_t n)
@@ -1081,20 +955,11 @@ request_microcode_user(int cpu, const void __user *buf, size_t size)
return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
}
-static void microcode_fini_cpu(int cpu)
-{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
- vfree(uci->mc);
- uci->mc = NULL;
-}
-
static struct microcode_ops microcode_intel_ops = {
.request_microcode_user = request_microcode_user,
.request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info,
.apply_microcode = apply_microcode_intel,
- .microcode_fini_cpu = microcode_fini_cpu,
};
struct microcode_ops * __init init_intel_microcode(void)
@@ -1109,4 +974,3 @@ struct microcode_ops * __init init_intel_microcode(void)
return &microcode_intel_ops;
}
-
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c
deleted file mode 100644
index 406cb6c0d9dd..000000000000
--- a/arch/x86/kernel/cpu/microcode/intel_lib.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Intel CPU Microcode Update Driver for Linux
- *
- * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
- * H Peter Anvin" <hpa@zytor.com>
- *
- * This driver allows to upgrade microcode on Intel processors
- * belonging to IA-32 family - PentiumPro, Pentium II,
- * Pentium III, Xeon, Pentium 4, etc.
- *
- * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- * Software Developer's Manual
- * Order Number 253668 or free download from:
- *
- * http://developer.intel.com/Assets/PDF/manual/253668.pdf
- *
- * For more information, go to http://www.urbanmyth.org/microcode
- *
- * 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/firmware.h>
-#include <linux/uaccess.h>
-#include <linux/kernel.h>
-
-#include <asm/microcode_intel.h>
-#include <asm/processor.h>
-#include <asm/msr.h>
-
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
- unsigned int s2, unsigned int p2)
-{
- if (s1 != s2)
- return false;
-
- /* Processor flags are either both 0 ... */
- if (!p1 && !p2)
- return true;
-
- /* ... or they intersect. */
- return p1 & p2;
-}
-
-int microcode_sanity_check(void *mc, int print_err)
-{
- unsigned long total_size, data_size, ext_table_size;
- struct microcode_header_intel *mc_header = mc;
- struct extended_sigtable *ext_header = NULL;
- u32 sum, orig_sum, ext_sigcount = 0, i;
- struct extended_signature *ext_sig;
-
- total_size = get_totalsize(mc_header);
- data_size = get_datasize(mc_header);
-
- if (data_size + MC_HEADER_SIZE > total_size) {
- if (print_err)
- pr_err("Error: bad microcode data file size.\n");
- return -EINVAL;
- }
-
- if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
- if (print_err)
- pr_err("Error: invalid/unknown microcode update format.\n");
- return -EINVAL;
- }
-
- ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
- if (ext_table_size) {
- u32 ext_table_sum = 0;
- u32 *ext_tablep;
-
- if ((ext_table_size < EXT_HEADER_SIZE)
- || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
- if (print_err)
- pr_err("Error: truncated extended signature table.\n");
- return -EINVAL;
- }
-
- ext_header = mc + MC_HEADER_SIZE + data_size;
- if (ext_table_size != exttable_size(ext_header)) {
- if (print_err)
- pr_err("Error: extended signature table size mismatch.\n");
- return -EFAULT;
- }
-
- ext_sigcount = ext_header->count;
-
- /*
- * Check extended table checksum: the sum of all dwords that
- * comprise a valid table must be 0.
- */
- ext_tablep = (u32 *)ext_header;
-
- i = ext_table_size / sizeof(u32);
- while (i--)
- ext_table_sum += ext_tablep[i];
-
- if (ext_table_sum) {
- if (print_err)
- pr_warn("Bad extended signature table checksum, aborting.\n");
- return -EINVAL;
- }
- }
-
- /*
- * Calculate the checksum of update data and header. The checksum of
- * valid update data and header including the extended signature table
- * must be 0.
- */
- orig_sum = 0;
- i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
- while (i--)
- orig_sum += ((u32 *)mc)[i];
-
- if (orig_sum) {
- if (print_err)
- pr_err("Bad microcode data checksum, aborting.\n");
- return -EINVAL;
- }
-
- if (!ext_table_size)
- return 0;
-
- /*
- * Check extended signature checksum: 0 => valid.
- */
- for (i = 0; i < ext_sigcount; i++) {
- ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
- EXT_SIGNATURE_SIZE * i;
-
- sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
- (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
- if (sum) {
- if (print_err)
- pr_err("Bad extended signature checksum, aborting.\n");
- return -EINVAL;
- }
- }
- return 0;
-}
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int find_matching_signature(void *mc, unsigned int csig, int cpf)
-{
- struct microcode_header_intel *mc_hdr = mc;
- struct extended_sigtable *ext_hdr;
- struct extended_signature *ext_sig;
- int i;
-
- if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
- return 1;
-
- /* Look for ext. headers: */
- if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
- return 0;
-
- ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
- ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
-
- for (i = 0; i < ext_hdr->count; i++) {
- if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
- return 1;
- ext_sig++;
- }
- return 0;
-}
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
-{
- struct microcode_header_intel *mc_hdr = mc;
-
- if (mc_hdr->rev <= new_rev)
- return 0;
-
- return find_matching_signature(mc, csig, cpf);
-}
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 8f44c5a50ab8..6c044543545e 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -25,7 +25,6 @@
#include <asm/hyperv.h>
#include <asm/mshyperv.h>
#include <asm/desc.h>
-#include <asm/idle.h>
#include <asm/irq_regs.h>
#include <asm/i8259.h>
#include <asm/apic.h>
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 1db8dc490b66..d1316f9c8329 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -17,11 +17,17 @@ struct cpuid_bit {
u32 sub_leaf;
};
-enum cpuid_regs {
- CR_EAX = 0,
- CR_ECX,
- CR_EDX,
- CR_EBX
+/* Please keep the leaf sorted by cpuid_bit.level for faster search. */
+static const struct cpuid_bit cpuid_bits[] = {
+ { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
+ { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
+ { X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x00000007, 0 },
+ { X86_FEATURE_AVX512_4VNNIW, CPUID_EDX, 2, 0x00000007, 0 },
+ { X86_FEATURE_AVX512_4FMAPS, CPUID_EDX, 3, 0x00000007, 0 },
+ { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
+ { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
+ { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
+ { 0, 0, 0, 0, 0 }
};
void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
@@ -30,18 +36,6 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
u32 regs[4];
const struct cpuid_bit *cb;
- static const struct cpuid_bit cpuid_bits[] = {
- { X86_FEATURE_INTEL_PT, CR_EBX,25, 0x00000007, 0 },
- { X86_FEATURE_AVX512_4VNNIW, CR_EDX, 2, 0x00000007, 0 },
- { X86_FEATURE_AVX512_4FMAPS, CR_EDX, 3, 0x00000007, 0 },
- { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 },
- { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 },
- { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 },
- { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 },
- { X86_FEATURE_PROC_FEEDBACK, CR_EDX,11, 0x80000007, 0 },
- { 0, 0, 0, 0, 0 }
- };
-
for (cb = cpuid_bits; cb->feature; cb++) {
/* Verify that the level is valid */
@@ -50,10 +44,35 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
max_level > (cb->level | 0xffff))
continue;
- cpuid_count(cb->level, cb->sub_leaf, &regs[CR_EAX],
- &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);
+ cpuid_count(cb->level, cb->sub_leaf, &regs[CPUID_EAX],
+ &regs[CPUID_EBX], &regs[CPUID_ECX],
+ &regs[CPUID_EDX]);
if (regs[cb->reg] & (1 << cb->bit))
set_cpu_cap(c, cb->feature);
}
}
+
+u32 get_scattered_cpuid_leaf(unsigned int level, unsigned int sub_leaf,
+ enum cpuid_regs_idx reg)
+{
+ const struct cpuid_bit *cb;
+ u32 cpuid_val = 0;
+
+ for (cb = cpuid_bits; cb->feature; cb++) {
+
+ if (level > cb->level)
+ continue;
+
+ if (level < cb->level)
+ break;
+
+ if (reg == cb->reg && sub_leaf == cb->sub_leaf) {
+ if (cpu_has(&boot_cpu_data, cb->feature))
+ cpuid_val |= BIT(cb->bit);
+ }
+ }
+
+ return cpuid_val;
+}
+EXPORT_SYMBOL_GPL(get_scattered_cpuid_leaf);
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 5130985b758b..891f4dad7b2c 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -24,11 +24,16 @@
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/export.h>
+#include <linux/clocksource.h>
#include <asm/div64.h>
#include <asm/x86_init.h>
#include <asm/hypervisor.h>
#include <asm/timer.h>
#include <asm/apic.h>
+#include <asm/timer.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "vmware: " fmt
#define CPUID_VMWARE_INFO_LEAF 0x40000000
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
@@ -48,6 +53,8 @@
"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) : \
"memory");
+static unsigned long vmware_tsc_khz __ro_after_init;
+
static inline int __vmware_platform(void)
{
uint32_t eax, ebx, ecx, edx;
@@ -57,35 +64,80 @@ static inline int __vmware_platform(void)
static unsigned long vmware_get_tsc_khz(void)
{
- uint64_t tsc_hz, lpj;
- uint32_t eax, ebx, ecx, edx;
+ return vmware_tsc_khz;
+}
- VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
+#ifdef CONFIG_PARAVIRT
+static struct cyc2ns_data vmware_cyc2ns __ro_after_init;
+static int vmw_sched_clock __initdata = 1;
- tsc_hz = eax | (((uint64_t)ebx) << 32);
- do_div(tsc_hz, 1000);
- BUG_ON(tsc_hz >> 32);
- pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
- (unsigned long) tsc_hz / 1000,
- (unsigned long) tsc_hz % 1000);
-
- if (!preset_lpj) {
- lpj = ((u64)tsc_hz * 1000);
- do_div(lpj, HZ);
- preset_lpj = lpj;
- }
+static __init int setup_vmw_sched_clock(char *s)
+{
+ vmw_sched_clock = 0;
+ return 0;
+}
+early_param("no-vmw-sched-clock", setup_vmw_sched_clock);
+
+static unsigned long long vmware_sched_clock(void)
+{
+ unsigned long long ns;
- return tsc_hz;
+ ns = mul_u64_u32_shr(rdtsc(), vmware_cyc2ns.cyc2ns_mul,
+ vmware_cyc2ns.cyc2ns_shift);
+ ns -= vmware_cyc2ns.cyc2ns_offset;
+ return ns;
}
+static void __init vmware_sched_clock_setup(void)
+{
+ struct cyc2ns_data *d = &vmware_cyc2ns;
+ unsigned long long tsc_now = rdtsc();
+
+ clocks_calc_mult_shift(&d->cyc2ns_mul, &d->cyc2ns_shift,
+ vmware_tsc_khz, NSEC_PER_MSEC, 0);
+ d->cyc2ns_offset = mul_u64_u32_shr(tsc_now, d->cyc2ns_mul,
+ d->cyc2ns_shift);
+
+ pv_time_ops.sched_clock = vmware_sched_clock;
+ pr_info("using sched offset of %llu ns\n", d->cyc2ns_offset);
+}
+
+static void __init vmware_paravirt_ops_setup(void)
+{
+ pv_info.name = "VMware hypervisor";
+ pv_cpu_ops.io_delay = paravirt_nop;
+
+ if (vmware_tsc_khz && vmw_sched_clock)
+ vmware_sched_clock_setup();
+}
+#else
+#define vmware_paravirt_ops_setup() do {} while (0)
+#endif
+
static void __init vmware_platform_setup(void)
{
uint32_t eax, ebx, ecx, edx;
+ uint64_t lpj, tsc_khz;
VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
if (ebx != UINT_MAX) {
+ lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
+ do_div(tsc_khz, 1000);
+ WARN_ON(tsc_khz >> 32);
+ pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
+ (unsigned long) tsc_khz / 1000,
+ (unsigned long) tsc_khz % 1000);
+
+ if (!preset_lpj) {
+ do_div(lpj, HZ);
+ preset_lpj = lpj;
+ }
+
+ vmware_tsc_khz = tsc_khz;
x86_platform.calibrate_tsc = vmware_get_tsc_khz;
+ x86_platform.calibrate_cpu = vmware_get_tsc_khz;
+
#ifdef CONFIG_X86_LOCAL_APIC
/* Skip lapic calibration since we know the bus frequency. */
lapic_timer_frequency = ecx / HZ;
@@ -96,6 +148,8 @@ static void __init vmware_platform_setup(void)
pr_warn("Failed to get TSC freq from the hypervisor\n");
}
+ vmware_paravirt_ops_setup();
+
#ifdef CONFIG_X86_IO_APIC
no_timer_check = 1;
#endif
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 2836de390f95..0931a105ffe1 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -45,10 +45,7 @@
#include <asm/msr.h>
static struct class *cpuid_class;
-
-struct cpuid_regs {
- u32 eax, ebx, ecx, edx;
-};
+static enum cpuhp_state cpuhp_cpuid_state;
static void cpuid_smp_cpuid(void *cmd_block)
{
@@ -115,7 +112,7 @@ static const struct file_operations cpuid_fops = {
.open = cpuid_open,
};
-static int cpuid_device_create(int cpu)
+static int cpuid_device_create(unsigned int cpu)
{
struct device *dev;
@@ -124,35 +121,12 @@ static int cpuid_device_create(int cpu)
return PTR_ERR_OR_ZERO(dev);
}
-static void cpuid_device_destroy(int cpu)
+static int cpuid_device_destroy(unsigned int cpu)
{
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ return 0;
}
-static int cpuid_class_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
- int err = 0;
-
- switch (action) {
- case CPU_UP_PREPARE:
- err = cpuid_device_create(cpu);
- break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- cpuid_device_destroy(cpu);
- break;
- }
- return notifier_from_errno(err);
-}
-
-static struct notifier_block cpuid_class_cpu_notifier =
-{
- .notifier_call = cpuid_class_cpu_callback,
-};
-
static char *cpuid_devnode(struct device *dev, umode_t *mode)
{
return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
@@ -160,15 +134,13 @@ static char *cpuid_devnode(struct device *dev, umode_t *mode)
static int __init cpuid_init(void)
{
- int i, err = 0;
- i = 0;
+ int err;
if (__register_chrdev(CPUID_MAJOR, 0, NR_CPUS,
"cpu/cpuid", &cpuid_fops)) {
printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
CPUID_MAJOR);
- err = -EBUSY;
- goto out;
+ return -EBUSY;
}
cpuid_class = class_create(THIS_MODULE, "cpuid");
if (IS_ERR(cpuid_class)) {
@@ -177,45 +149,28 @@ static int __init cpuid_init(void)
}
cpuid_class->devnode = cpuid_devnode;
- cpu_notifier_register_begin();
- for_each_online_cpu(i) {
- err = cpuid_device_create(i);
- if (err != 0)
- goto out_class;
- }
- __register_hotcpu_notifier(&cpuid_class_cpu_notifier);
- cpu_notifier_register_done();
+ err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/cpuid:online",
+ cpuid_device_create, cpuid_device_destroy);
+ if (err < 0)
+ goto out_class;
- err = 0;
- goto out;
+ cpuhp_cpuid_state = err;
+ return 0;
out_class:
- i = 0;
- for_each_online_cpu(i) {
- cpuid_device_destroy(i);
- }
- cpu_notifier_register_done();
class_destroy(cpuid_class);
out_chrdev:
__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
-out:
return err;
}
+module_init(cpuid_init);
static void __exit cpuid_exit(void)
{
- int cpu = 0;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- cpuid_device_destroy(cpu);
+ cpuhp_remove_state(cpuhp_cpuid_state);
class_destroy(cpuid_class);
__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
- __unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
- cpu_notifier_register_done();
}
-
-module_init(cpuid_init);
module_exit(cpuid_exit);
MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 85f854b98a9d..0cfd01d2754c 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -22,7 +22,6 @@
int panic_on_unrecovered_nmi;
int panic_on_io_nmi;
unsigned int code_bytes = 64;
-int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
static int die_counter;
bool in_task_stack(unsigned long *stack, struct task_struct *task,
@@ -46,14 +45,7 @@ static void printk_stack_address(unsigned long address, int reliable,
char *log_lvl)
{
touch_nmi_watchdog();
- printk("%s [<%p>] %s%pB\n",
- log_lvl, (void *)address, reliable ? "" : "? ",
- (void *)address);
-}
-
-void printk_address(unsigned long address)
-{
- pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address);
+ printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
}
void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
@@ -67,6 +59,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
printk("%sCall Trace:\n", log_lvl);
unwind_start(&state, task, regs, stack);
+ stack = stack ? : get_stack_pointer(task, regs);
/*
* Iterate through the stacks, starting with the current stack pointer.
@@ -82,8 +75,8 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
* - softirq stack
* - hardirq stack
*/
- for (; stack; stack = stack_info.next_sp) {
- const char *str_begin, *str_end;
+ for (regs = NULL; stack; stack = stack_info.next_sp) {
+ const char *stack_name;
/*
* If we overflowed the task stack into a guard page, jump back
@@ -95,9 +88,9 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (get_stack_info(stack, task, &stack_info, &visit_mask))
break;
- stack_type_str(stack_info.type, &str_begin, &str_end);
- if (str_begin)
- printk("%s <%s> ", log_lvl, str_begin);
+ stack_name = stack_type_name(stack_info.type);
+ if (stack_name)
+ printk("%s <%s>\n", log_lvl, stack_name);
/*
* Scan the stack, printing any text addresses we find. At the
@@ -119,6 +112,15 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (!__kernel_text_address(addr))
continue;
+ /*
+ * Don't print regs->ip again if it was already printed
+ * by __show_regs() below.
+ */
+ if (regs && stack == &regs->ip) {
+ unwind_next_frame(&state);
+ continue;
+ }
+
if (stack == ret_addr_p)
reliable = 1;
@@ -146,10 +148,15 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
* of the addresses will just be printed as unreliable.
*/
unwind_next_frame(&state);
+
+ /* if the frame has entry regs, print them */
+ regs = unwind_get_entry_regs(&state);
+ if (regs)
+ __show_regs(regs, 0);
}
- if (str_end)
- printk("%s <%s> ", log_lvl, str_end);
+ if (stack_name)
+ printk("%s </%s>\n", log_lvl, stack_name);
}
}
@@ -164,12 +171,12 @@ void show_stack(struct task_struct *task, unsigned long *sp)
if (!sp && task == current)
sp = get_stack_pointer(current, NULL);
- show_stack_log_lvl(task, NULL, sp, "");
+ show_trace_log_lvl(task, NULL, sp, KERN_DEFAULT);
}
void show_stack_regs(struct pt_regs *regs)
{
- show_stack_log_lvl(current, regs, NULL, "");
+ show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
}
static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;
@@ -261,14 +268,11 @@ int __die(const char *str, struct pt_regs *regs, long err)
sp = kernel_stack_pointer(regs);
savesegment(ss, ss);
}
- printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
- print_symbol("%s", regs->ip);
- printk(" SS:ESP %04x:%08lx\n", ss, sp);
+ printk(KERN_EMERG "EIP: %pS SS:ESP: %04x:%08lx\n",
+ (void *)regs->ip, ss, sp);
#else
/* Executive summary in case the oops scrolled away */
- printk(KERN_ALERT "RIP ");
- printk_address(regs->ip);
- printk(" RSP <%016lx>\n", regs->sp);
+ printk(KERN_ALERT "RIP: %pS RSP: %016lx\n", (void *)regs->ip, regs->sp);
#endif
return 0;
}
@@ -291,22 +295,6 @@ void die(const char *str, struct pt_regs *regs, long err)
oops_end(flags, regs, sig);
}
-static int __init kstack_setup(char *s)
-{
- ssize_t ret;
- unsigned long val;
-
- if (!s)
- return -EINVAL;
-
- ret = kstrtoul(s, 0, &val);
- if (ret)
- return ret;
- kstack_depth_to_print = val;
- return 0;
-}
-early_param("kstack", kstack_setup);
-
static int __init code_bytes_setup(char *s)
{
ssize_t ret;
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 06eb322b5f9f..bb3b5b9a6899 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -16,18 +16,15 @@
#include <asm/stacktrace.h>
-void stack_type_str(enum stack_type type, const char **begin, const char **end)
+const char *stack_type_name(enum stack_type type)
{
- switch (type) {
- case STACK_TYPE_IRQ:
- case STACK_TYPE_SOFTIRQ:
- *begin = "IRQ";
- *end = "EOI";
- break;
- default:
- *begin = NULL;
- *end = NULL;
- }
+ if (type == STACK_TYPE_IRQ)
+ return "IRQ";
+
+ if (type == STACK_TYPE_SOFTIRQ)
+ return "SOFTIRQ";
+
+ return NULL;
}
static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
@@ -109,8 +106,10 @@ recursion_check:
* just break out and report an unknown stack type.
*/
if (visit_mask) {
- if (*visit_mask & (1UL << info->type))
+ if (*visit_mask & (1UL << info->type)) {
+ printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
goto unknown;
+ }
*visit_mask |= 1UL << info->type;
}
@@ -121,36 +120,6 @@ unknown:
return -EINVAL;
}
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *sp, char *log_lvl)
-{
- unsigned long *stack;
- int i;
-
- if (!try_get_task_stack(task))
- return;
-
- sp = sp ? : get_stack_pointer(task, regs);
-
- stack = sp;
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (kstack_end(stack))
- break;
- if ((i % STACKSLOTS_PER_LINE) == 0) {
- if (i != 0)
- pr_cont("\n");
- printk("%s %08lx", log_lvl, *stack++);
- } else
- pr_cont(" %08lx", *stack++);
- touch_nmi_watchdog();
- }
- pr_cont("\n");
- show_trace_log_lvl(task, regs, sp, log_lvl);
-
- put_task_stack(task);
-}
-
-
void show_regs(struct pt_regs *regs)
{
int i;
@@ -168,8 +137,7 @@ void show_regs(struct pt_regs *regs)
unsigned char c;
u8 *ip;
- pr_emerg("Stack:\n");
- show_stack_log_lvl(current, regs, NULL, KERN_EMERG);
+ show_trace_log_lvl(current, regs, NULL, KERN_EMERG);
pr_emerg("Code:");
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 36cf1a498227..fac189efcc34 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -28,23 +28,17 @@ static unsigned long exception_stack_sizes[N_EXCEPTION_STACKS] = {
[DEBUG_STACK - 1] = DEBUG_STKSZ
};
-void stack_type_str(enum stack_type type, const char **begin, const char **end)
+const char *stack_type_name(enum stack_type type)
{
BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
- switch (type) {
- case STACK_TYPE_IRQ:
- *begin = "IRQ";
- *end = "EOI";
- break;
- case STACK_TYPE_EXCEPTION ... STACK_TYPE_EXCEPTION_LAST:
- *begin = exception_stack_names[type - STACK_TYPE_EXCEPTION];
- *end = "EOE";
- break;
- default:
- *begin = NULL;
- *end = NULL;
- }
+ if (type == STACK_TYPE_IRQ)
+ return "IRQ";
+
+ if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
+ return exception_stack_names[type - STACK_TYPE_EXCEPTION];
+
+ return NULL;
}
static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
@@ -128,8 +122,10 @@ recursion_check:
* just break out and report an unknown stack type.
*/
if (visit_mask) {
- if (*visit_mask & (1UL << info->type))
+ if (*visit_mask & (1UL << info->type)) {
+ printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
goto unknown;
+ }
*visit_mask |= 1UL << info->type;
}
@@ -140,56 +136,6 @@ unknown:
return -EINVAL;
}
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *sp, char *log_lvl)
-{
- unsigned long *irq_stack_end;
- unsigned long *irq_stack;
- unsigned long *stack;
- int i;
-
- if (!try_get_task_stack(task))
- return;
-
- irq_stack_end = (unsigned long *)this_cpu_read(irq_stack_ptr);
- irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
-
- sp = sp ? : get_stack_pointer(task, regs);
-
- stack = sp;
- for (i = 0; i < kstack_depth_to_print; i++) {
- unsigned long word;
-
- if (stack >= irq_stack && stack <= irq_stack_end) {
- if (stack == irq_stack_end) {
- stack = (unsigned long *) (irq_stack_end[-1]);
- pr_cont(" <EOI> ");
- }
- } else {
- if (kstack_end(stack))
- break;
- }
-
- if (probe_kernel_address(stack, word))
- break;
-
- if ((i % STACKSLOTS_PER_LINE) == 0) {
- if (i != 0)
- pr_cont("\n");
- printk("%s %016lx", log_lvl, word);
- } else
- pr_cont(" %016lx", word);
-
- stack++;
- touch_nmi_watchdog();
- }
-
- pr_cont("\n");
- show_trace_log_lvl(task, regs, sp, log_lvl);
-
- put_task_stack(task);
-}
-
void show_regs(struct pt_regs *regs)
{
int i;
@@ -207,8 +153,7 @@ void show_regs(struct pt_regs *regs)
unsigned char c;
u8 *ip;
- printk(KERN_DEFAULT "Stack:\n");
- show_stack_log_lvl(current, regs, NULL, KERN_DEFAULT);
+ show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
printk(KERN_DEFAULT "Code: ");
diff --git a/arch/x86/kernel/fpu/bugs.c b/arch/x86/kernel/fpu/bugs.c
index aad34aafc0e0..d913047f832c 100644
--- a/arch/x86/kernel/fpu/bugs.c
+++ b/arch/x86/kernel/fpu/bugs.c
@@ -23,17 +23,12 @@ static double __initdata y = 3145727.0;
*/
void __init fpu__init_check_bugs(void)
{
- u32 cr0_saved;
s32 fdiv_bug;
/* kernel_fpu_begin/end() relies on patched alternative instructions. */
if (!boot_cpu_has(X86_FEATURE_FPU))
return;
- /* We might have CR0::TS set already, clear it: */
- cr0_saved = read_cr0();
- write_cr0(cr0_saved & ~X86_CR0_TS);
-
kernel_fpu_begin();
/*
@@ -56,8 +51,6 @@ void __init fpu__init_check_bugs(void)
kernel_fpu_end();
- write_cr0(cr0_saved);
-
if (fdiv_bug) {
set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
pr_warn("Hmm, FPU with FDIV bug\n");
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index ebb4e95fbd74..e4e97a5355ce 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -58,27 +58,9 @@ static bool kernel_fpu_disabled(void)
return this_cpu_read(in_kernel_fpu);
}
-/*
- * Were we in an interrupt that interrupted kernel mode?
- *
- * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that
- * pair does nothing at all: the thread must not have fpu (so
- * that we don't try to save the FPU state), and TS must
- * be set (so that the clts/stts pair does nothing that is
- * visible in the interrupted kernel thread).
- *
- * Except for the eagerfpu case when we return true; in the likely case
- * the thread has FPU but we are not going to set/clear TS.
- */
static bool interrupted_kernel_fpu_idle(void)
{
- if (kernel_fpu_disabled())
- return false;
-
- if (use_eager_fpu())
- return true;
-
- return !current->thread.fpu.fpregs_active && (read_cr0() & X86_CR0_TS);
+ return !kernel_fpu_disabled();
}
/*
@@ -125,8 +107,7 @@ void __kernel_fpu_begin(void)
*/
copy_fpregs_to_fpstate(fpu);
} else {
- this_cpu_write(fpu_fpregs_owner_ctx, NULL);
- __fpregs_activate_hw();
+ __cpu_invalidate_fpregs_state();
}
}
EXPORT_SYMBOL(__kernel_fpu_begin);
@@ -137,8 +118,6 @@ void __kernel_fpu_end(void)
if (fpu->fpregs_active)
copy_kernel_to_fpregs(&fpu->state);
- else
- __fpregs_deactivate_hw();
kernel_fpu_enable();
}
@@ -159,35 +138,6 @@ void kernel_fpu_end(void)
EXPORT_SYMBOL_GPL(kernel_fpu_end);
/*
- * CR0::TS save/restore functions:
- */
-int irq_ts_save(void)
-{
- /*
- * If in process context and not atomic, we can take a spurious DNA fault.
- * Otherwise, doing clts() in process context requires disabling preemption
- * or some heavy lifting like kernel_fpu_begin()
- */
- if (!in_atomic())
- return 0;
-
- if (read_cr0() & X86_CR0_TS) {
- clts();
- return 1;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(irq_ts_save);
-
-void irq_ts_restore(int TS_state)
-{
- if (TS_state)
- stts();
-}
-EXPORT_SYMBOL_GPL(irq_ts_restore);
-
-/*
* Save the FPU state (mark it for reload if necessary):
*
* This only ever gets called for the current task.
@@ -200,10 +150,7 @@ void fpu__save(struct fpu *fpu)
trace_x86_fpu_before_save(fpu);
if (fpu->fpregs_active) {
if (!copy_fpregs_to_fpstate(fpu)) {
- if (use_eager_fpu())
- copy_kernel_to_fpregs(&fpu->state);
- else
- fpregs_deactivate(fpu);
+ copy_kernel_to_fpregs(&fpu->state);
}
}
trace_x86_fpu_after_save(fpu);
@@ -247,7 +194,6 @@ EXPORT_SYMBOL_GPL(fpstate_init);
int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
{
- dst_fpu->counter = 0;
dst_fpu->fpregs_active = 0;
dst_fpu->last_cpu = -1;
@@ -260,8 +206,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
* Don't let 'init optimized' areas of the XSAVE area
* leak into the child task:
*/
- if (use_eager_fpu())
- memset(&dst_fpu->state.xsave, 0, fpu_kernel_xstate_size);
+ memset(&dst_fpu->state.xsave, 0, fpu_kernel_xstate_size);
/*
* Save current FPU registers directly into the child
@@ -283,10 +228,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
memcpy(&src_fpu->state, &dst_fpu->state,
fpu_kernel_xstate_size);
- if (use_eager_fpu())
- copy_kernel_to_fpregs(&src_fpu->state);
- else
- fpregs_deactivate(src_fpu);
+ copy_kernel_to_fpregs(&src_fpu->state);
}
preempt_enable();
@@ -366,7 +308,7 @@ void fpu__activate_fpstate_write(struct fpu *fpu)
if (fpu->fpstate_active) {
/* Invalidate any lazy state: */
- fpu->last_cpu = -1;
+ __fpu_invalidate_fpregs_state(fpu);
} else {
fpstate_init(&fpu->state);
trace_x86_fpu_init_state(fpu);
@@ -409,7 +351,7 @@ void fpu__current_fpstate_write_begin(void)
* ensures we will not be lazy and skip a XRSTOR in the
* future.
*/
- fpu->last_cpu = -1;
+ __fpu_invalidate_fpregs_state(fpu);
}
/*
@@ -459,7 +401,6 @@ void fpu__restore(struct fpu *fpu)
trace_x86_fpu_before_restore(fpu);
fpregs_activate(fpu);
copy_kernel_to_fpregs(&fpu->state);
- fpu->counter++;
trace_x86_fpu_after_restore(fpu);
kernel_fpu_enable();
}
@@ -477,7 +418,6 @@ EXPORT_SYMBOL_GPL(fpu__restore);
void fpu__drop(struct fpu *fpu)
{
preempt_disable();
- fpu->counter = 0;
if (fpu->fpregs_active) {
/* Ignore delayed exceptions from user space */
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 2f2b8c7ccb85..60dece392b3a 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -10,18 +10,6 @@
#include <linux/init.h>
/*
- * Initialize the TS bit in CR0 according to the style of context-switches
- * we are using:
- */
-static void fpu__init_cpu_ctx_switch(void)
-{
- if (!boot_cpu_has(X86_FEATURE_EAGER_FPU))
- stts();
- else
- clts();
-}
-
-/*
* Initialize the registers found in all CPUs, CR0 and CR4:
*/
static void fpu__init_cpu_generic(void)
@@ -58,7 +46,6 @@ void fpu__init_cpu(void)
{
fpu__init_cpu_generic();
fpu__init_cpu_xstate();
- fpu__init_cpu_ctx_switch();
}
/*
@@ -233,82 +220,16 @@ static void __init fpu__init_system_xstate_size_legacy(void)
}
/*
- * FPU context switching strategies:
- *
- * Against popular belief, we don't do lazy FPU saves, due to the
- * task migration complications it brings on SMP - we only do
- * lazy FPU restores.
- *
- * 'lazy' is the traditional strategy, which is based on setting
- * CR0::TS to 1 during context-switch (instead of doing a full
- * restore of the FPU state), which causes the first FPU instruction
- * after the context switch (whenever it is executed) to fault - at
- * which point we lazily restore the FPU state into FPU registers.
- *
- * Tasks are of course under no obligation to execute FPU instructions,
- * so it can easily happen that another context-switch occurs without
- * a single FPU instruction being executed. If we eventually switch
- * back to the original task (that still owns the FPU) then we have
- * not only saved the restores along the way, but we also have the
- * FPU ready to be used for the original task.
- *
- * 'lazy' is deprecated because it's almost never a performance win
- * and it's much more complicated than 'eager'.
- *
- * 'eager' switching is by default on all CPUs, there we switch the FPU
- * state during every context switch, regardless of whether the task
- * has used FPU instructions in that time slice or not. This is done
- * because modern FPU context saving instructions are able to optimize
- * state saving and restoration in hardware: they can detect both
- * unused and untouched FPU state and optimize accordingly.
- *
- * [ Note that even in 'lazy' mode we might optimize context switches
- * to use 'eager' restores, if we detect that a task is using the FPU
- * frequently. See the fpu->counter logic in fpu/internal.h for that. ]
- */
-static enum { ENABLE, DISABLE } eagerfpu = ENABLE;
-
-/*
* Find supported xfeatures based on cpu features and command-line input.
* This must be called after fpu__init_parse_early_param() is called and
* xfeatures_mask is enumerated.
*/
u64 __init fpu__get_supported_xfeatures_mask(void)
{
- /* Support all xfeatures known to us */
- if (eagerfpu != DISABLE)
- return XCNTXT_MASK;
-
- /* Warning of xfeatures being disabled for no eagerfpu mode */
- if (xfeatures_mask & XFEATURE_MASK_EAGER) {
- pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n",
- xfeatures_mask & XFEATURE_MASK_EAGER);
- }
-
- /* Return a mask that masks out all features requiring eagerfpu mode */
- return ~XFEATURE_MASK_EAGER;
+ return XCNTXT_MASK;
}
-/*
- * Disable features dependent on eagerfpu.
- */
-static void __init fpu__clear_eager_fpu_features(void)
-{
- setup_clear_cpu_cap(X86_FEATURE_MPX);
-}
-
-/*
- * Pick the FPU context switching strategy:
- *
- * When eagerfpu is AUTO or ENABLE, we ensure it is ENABLE if either of
- * the following is true:
- *
- * (1) the cpu has xsaveopt, as it has the optimization and doing eager
- * FPU switching has a relatively low cost compared to a plain xsave;
- * (2) the cpu has xsave features (e.g. MPX) that depend on eager FPU
- * switching. Should the kernel boot with noxsaveopt, we support MPX
- * with eager FPU switching at a higher cost.
- */
+/* Legacy code to initialize eager fpu mode. */
static void __init fpu__init_system_ctx_switch(void)
{
static bool on_boot_cpu __initdata = 1;
@@ -317,17 +238,6 @@ static void __init fpu__init_system_ctx_switch(void)
on_boot_cpu = 0;
WARN_ON_FPU(current->thread.fpu.fpstate_active);
-
- if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE)
- eagerfpu = ENABLE;
-
- if (xfeatures_mask & XFEATURE_MASK_EAGER)
- eagerfpu = ENABLE;
-
- if (eagerfpu == ENABLE)
- setup_force_cpu_cap(X86_FEATURE_EAGER_FPU);
-
- printk(KERN_INFO "x86/fpu: Using '%s' FPU context switches.\n", eagerfpu == ENABLE ? "eager" : "lazy");
}
/*
@@ -336,11 +246,6 @@ static void __init fpu__init_system_ctx_switch(void)
*/
static void __init fpu__init_parse_early_param(void)
{
- if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) {
- eagerfpu = DISABLE;
- fpu__clear_eager_fpu_features();
- }
-
if (cmdline_find_option_bool(boot_command_line, "no387"))
setup_clear_cpu_cap(X86_FEATURE_FPU);
@@ -375,14 +280,6 @@ void __init fpu__init_system(struct cpuinfo_x86 *c)
*/
fpu__init_cpu();
- /*
- * But don't leave CR0::TS set yet, as some of the FPU setup
- * methods depend on being able to execute FPU instructions
- * that will fault on a set TS, such as the FXSAVE in
- * fpu__init_system_mxcsr().
- */
- clts();
-
fpu__init_system_generic();
fpu__init_system_xstate_size_legacy();
fpu__init_system_xstate();
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index a184c210efba..83c23c230b4c 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -340,11 +340,9 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
}
fpu->fpstate_active = 1;
- if (use_eager_fpu()) {
- preempt_disable();
- fpu__restore(fpu);
- preempt_enable();
- }
+ preempt_disable();
+ fpu__restore(fpu);
+ preempt_enable();
return err;
} else {
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 095ef7ddd6ae..1d7770447b3e 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -65,6 +65,7 @@ void fpu__xstate_clear_all_cpu_caps(void)
setup_clear_cpu_cap(X86_FEATURE_AVX);
setup_clear_cpu_cap(X86_FEATURE_AVX2);
setup_clear_cpu_cap(X86_FEATURE_AVX512F);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512IFMA);
setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
@@ -73,6 +74,7 @@ void fpu__xstate_clear_all_cpu_caps(void)
setup_clear_cpu_cap(X86_FEATURE_AVX512VL);
setup_clear_cpu_cap(X86_FEATURE_MPX);
setup_clear_cpu_cap(X86_FEATURE_XGETBV1);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512VBMI);
setup_clear_cpu_cap(X86_FEATURE_PKU);
setup_clear_cpu_cap(X86_FEATURE_AVX512_4VNNIW);
setup_clear_cpu_cap(X86_FEATURE_AVX512_4FMAPS);
@@ -890,15 +892,6 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
*/
if (!boot_cpu_has(X86_FEATURE_OSPKE))
return -EINVAL;
- /*
- * For most XSAVE components, this would be an arduous task:
- * brining fpstate up to date with fpregs, updating fpstate,
- * then re-populating fpregs. But, for components that are
- * never lazily managed, we can just access the fpregs
- * directly. PKRU is never managed lazily, so we can just
- * manipulate it directly. Make sure it stays that way.
- */
- WARN_ON_ONCE(!use_eager_fpu());
/* Set the bits we need in PKRU: */
if (init_val & PKEY_DISABLE_ACCESS)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 2dabea46f039..4e8577d03372 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -63,6 +63,8 @@
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
#endif
+#define SIZEOF_PTREGS 17*4
+
/*
* Number of possible pages in the lowmem region.
*
@@ -248,19 +250,19 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
#ifdef CONFIG_PARAVIRT
/* This is can only trip for a broken bootloader... */
cmpw $0x207, pa(boot_params + BP_version)
- jb default_entry
+ jb .Ldefault_entry
/* Paravirt-compatible boot parameters. Look to see what architecture
we're booting under. */
movl pa(boot_params + BP_hardware_subarch), %eax
cmpl $num_subarch_entries, %eax
- jae bad_subarch
+ jae .Lbad_subarch
movl pa(subarch_entries)(,%eax,4), %eax
subl $__PAGE_OFFSET, %eax
jmp *%eax
-bad_subarch:
+.Lbad_subarch:
WEAK(lguest_entry)
WEAK(xen_entry)
/* Unknown implementation; there's really
@@ -270,14 +272,14 @@ WEAK(xen_entry)
__INITDATA
subarch_entries:
- .long default_entry /* normal x86/PC */
+ .long .Ldefault_entry /* normal x86/PC */
.long lguest_entry /* lguest hypervisor */
.long xen_entry /* Xen hypervisor */
- .long default_entry /* Moorestown MID */
+ .long .Ldefault_entry /* Moorestown MID */
num_subarch_entries = (. - subarch_entries) / 4
.previous
#else
- jmp default_entry
+ jmp .Ldefault_entry
#endif /* CONFIG_PARAVIRT */
#ifdef CONFIG_HOTPLUG_CPU
@@ -289,7 +291,8 @@ num_subarch_entries = (. - subarch_entries) / 4
ENTRY(start_cpu0)
movl initial_stack, %ecx
movl %ecx, %esp
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
ENDPROC(start_cpu0)
#endif
@@ -317,7 +320,7 @@ ENTRY(startup_32_smp)
call load_ucode_ap
#endif
-default_entry:
+.Ldefault_entry:
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
X86_CR0_PG)
@@ -347,7 +350,7 @@ default_entry:
pushfl
popl %eax # get EFLAGS
testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
- jz enable_paging # hw disallowed setting of ID bit
+ jz .Lenable_paging # hw disallowed setting of ID bit
# which means no CPUID and no CR4
xorl %eax,%eax
@@ -357,13 +360,13 @@ default_entry:
movl $1,%eax
cpuid
andl $~1,%edx # Ignore CPUID.FPU
- jz enable_paging # No flags or only CPUID.FPU = no CR4
+ jz .Lenable_paging # No flags or only CPUID.FPU = no CR4
movl pa(mmu_cr4_features),%eax
movl %eax,%cr4
testb $X86_CR4_PAE, %al # check if PAE is enabled
- jz enable_paging
+ jz .Lenable_paging
/* Check if extended functions are implemented */
movl $0x80000000, %eax
@@ -371,7 +374,7 @@ default_entry:
/* Value must be in the range 0x80000001 to 0x8000ffff */
subl $0x80000001, %eax
cmpl $(0x8000ffff-0x80000001), %eax
- ja enable_paging
+ ja .Lenable_paging
/* Clear bogus XD_DISABLE bits */
call verify_cpu
@@ -380,7 +383,7 @@ default_entry:
cpuid
/* Execute Disable bit supported? */
btl $(X86_FEATURE_NX & 31), %edx
- jnc enable_paging
+ jnc .Lenable_paging
/* Setup EFER (Extended Feature Enable Register) */
movl $MSR_EFER, %ecx
@@ -390,7 +393,7 @@ default_entry:
/* Make changes effective */
wrmsr
-enable_paging:
+.Lenable_paging:
/*
* Enable paging
@@ -419,7 +422,7 @@ enable_paging:
*/
movb $4,X86 # at least 486
cmpl $-1,X86_CPUID
- je is486
+ je .Lis486
/* get vendor info */
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
@@ -430,7 +433,7 @@ enable_paging:
movl %ecx,X86_VENDOR_ID+8 # last 4 chars
orl %eax,%eax # do we have processor info as well?
- je is486
+ je .Lis486
movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
@@ -444,7 +447,7 @@ enable_paging:
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY
-is486:
+.Lis486:
movl $0x50022,%ecx # set AM, WP, NE and MP
movl %cr0,%eax
andl $0x80000011,%eax # Save PG,PE,ET
@@ -470,8 +473,9 @@ is486:
xorl %eax,%eax # Clear LDT
lldt %ax
- pushl $0 # fake return address for unwinder
- jmp *(initial_code)
+ call *(initial_code)
+1: jmp 1b
+ENDPROC(startup_32_smp)
#include "verify_cpu.S"
@@ -709,7 +713,12 @@ ENTRY(initial_page_table)
.data
.balign 4
ENTRY(initial_stack)
- .long init_thread_union+THREAD_SIZE
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .long init_thread_union + THREAD_SIZE - SIZEOF_PTREGS - \
+ TOP_OF_KERNEL_STACK_PADDING;
__INITRODATA
int_msg:
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index b4421cc191b0..90de28841242 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -66,13 +66,8 @@ startup_64:
* tables and then reload them.
*/
- /*
- * Setup stack for verify_cpu(). "-8" because initial_stack is defined
- * this way, see below. Our best guess is a NULL ptr for stack
- * termination heuristics and we don't want to break anything which
- * might depend on it (kgdb, ...).
- */
- leaq (__end_init_task - 8)(%rip), %rsp
+ /* Set up the stack for verify_cpu(), similar to initial_stack below */
+ leaq (__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
/* Sanitize CPU configuration */
call verify_cpu
@@ -117,20 +112,20 @@ startup_64:
movq %rdi, %rax
shrq $PGDIR_SHIFT, %rax
- leaq (4096 + _KERNPG_TABLE)(%rbx), %rdx
+ leaq (PAGE_SIZE + _KERNPG_TABLE)(%rbx), %rdx
movq %rdx, 0(%rbx,%rax,8)
movq %rdx, 8(%rbx,%rax,8)
- addq $4096, %rdx
+ addq $PAGE_SIZE, %rdx
movq %rdi, %rax
shrq $PUD_SHIFT, %rax
andl $(PTRS_PER_PUD-1), %eax
- movq %rdx, 4096(%rbx,%rax,8)
+ movq %rdx, PAGE_SIZE(%rbx,%rax,8)
incl %eax
andl $(PTRS_PER_PUD-1), %eax
- movq %rdx, 4096(%rbx,%rax,8)
+ movq %rdx, PAGE_SIZE(%rbx,%rax,8)
- addq $8192, %rbx
+ addq $PAGE_SIZE * 2, %rbx
movq %rdi, %rax
shrq $PMD_SHIFT, %rdi
addq $(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
@@ -147,6 +142,9 @@ startup_64:
decl %ecx
jnz 1b
+ test %rbp, %rbp
+ jz .Lskip_fixup
+
/*
* Fixup the kernel text+data virtual addresses. Note that
* we might write invalid pmds, when the kernel is relocated
@@ -154,9 +152,9 @@ startup_64:
* beyond _end.
*/
leaq level2_kernel_pgt(%rip), %rdi
- leaq 4096(%rdi), %r8
+ leaq PAGE_SIZE(%rdi), %r8
/* See if it is a valid page table entry */
-1: testb $1, 0(%rdi)
+1: testb $_PAGE_PRESENT, 0(%rdi)
jz 2f
addq %rbp, 0(%rdi)
/* Go to the next page */
@@ -167,6 +165,7 @@ startup_64:
/* Fixup phys_base */
addq %rbp, phys_base(%rip)
+.Lskip_fixup:
movq $(early_level4_pgt - __START_KERNEL_map), %rax
jmp 1f
ENTRY(secondary_startup_64)
@@ -265,13 +264,17 @@ ENTRY(secondary_startup_64)
movl $MSR_GS_BASE,%ecx
movl initial_gs(%rip),%eax
movl initial_gs+4(%rip),%edx
- wrmsr
+ wrmsr
/* rsi is pointer to real mode structure with interesting info.
pass it to C */
movq %rsi, %rdi
-
- /* Finally jump to run C code and to be on real kernel address
+ jmp start_cpu
+ENDPROC(secondary_startup_64)
+
+ENTRY(start_cpu)
+ /*
+ * Jump to run C code and to be on a real kernel address.
* Since we are running on identity-mapped space we have to jump
* to the full 64bit address, this is only possible as indirect
* jump. In addition we need to ensure %cs is set so we make this
@@ -295,12 +298,13 @@ ENTRY(secondary_startup_64)
* REX.W + FF /5 JMP m16:64 Jump far, absolute indirect,
* address given in m16:64.
*/
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
+ call 1f # put return address on stack for unwinder
+1: xorq %rbp, %rbp # clear frame pointer
+ movq initial_code(%rip), %rax
pushq $__KERNEL_CS # set correct cs
pushq %rax # target address in negative space
lretq
-ENDPROC(secondary_startup_64)
+ENDPROC(start_cpu)
#include "verify_cpu.S"
@@ -308,15 +312,11 @@ ENDPROC(secondary_startup_64)
/*
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set
* up already except stack. We just set up stack here. Then call
- * start_secondary().
+ * start_secondary() via start_cpu().
*/
ENTRY(start_cpu0)
- movq initial_stack(%rip),%rsp
- movq initial_code(%rip),%rax
- pushq $0 # fake return address to stop unwinder
- pushq $__KERNEL_CS # set correct cs
- pushq %rax # target address in negative space
- lretq
+ movq initial_stack(%rip), %rsp
+ jmp start_cpu
ENDPROC(start_cpu0)
#endif
@@ -328,7 +328,11 @@ ENDPROC(start_cpu0)
GLOBAL(initial_gs)
.quad INIT_PER_CPU_VAR(irq_stack_union)
GLOBAL(initial_stack)
- .quad init_thread_union+THREAD_SIZE-8
+ /*
+ * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+ * unwinder reliably detect the end of the stack.
+ */
+ .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
__FINITDATA
bad_address:
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 9f669fdd2010..7c6e9ffe4424 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -14,7 +14,6 @@
#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/irq.h>
-#include <asm/idle.h>
#include <asm/mce.h>
#include <asm/hw_irq.h>
#include <asm/desc.h>
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 9ebd0b0e73d9..6b0678a541e2 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -16,7 +16,6 @@
#include <linux/uaccess.h>
#include <linux/smp.h>
#include <asm/io_apic.h>
-#include <asm/idle.h>
#include <asm/apic.h>
int sysctl_panic_on_stackoverflow;
diff --git a/arch/x86/kernel/itmt.c b/arch/x86/kernel/itmt.c
new file mode 100644
index 000000000000..cb9c1ed1d391
--- /dev/null
+++ b/arch/x86/kernel/itmt.c
@@ -0,0 +1,215 @@
+/*
+ * itmt.c: Support Intel Turbo Boost Max Technology 3.0
+ *
+ * (C) Copyright 2016 Intel Corporation
+ * Author: Tim Chen <tim.c.chen@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
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * On platforms supporting Intel Turbo Boost Max Technology 3.0, (ITMT),
+ * the maximum turbo frequencies of some cores in a CPU package may be
+ * higher than for the other cores in the same package. In that case,
+ * better performance can be achieved by making the scheduler prefer
+ * to run tasks on the CPUs with higher max turbo frequencies.
+ *
+ * This file provides functions and data structures for enabling the
+ * scheduler to favor scheduling on cores can be boosted to a higher
+ * frequency under ITMT.
+ */
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/cpuset.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/sysctl.h>
+#include <linux/nodemask.h>
+
+static DEFINE_MUTEX(itmt_update_mutex);
+DEFINE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
+
+/* Boolean to track if system has ITMT capabilities */
+static bool __read_mostly sched_itmt_capable;
+
+/*
+ * Boolean to control whether we want to move processes to cpu capable
+ * of higher turbo frequency for cpus supporting Intel Turbo Boost Max
+ * Technology 3.0.
+ *
+ * It can be set via /proc/sys/kernel/sched_itmt_enabled
+ */
+unsigned int __read_mostly sysctl_sched_itmt_enabled;
+
+static int sched_itmt_update_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ unsigned int old_sysctl;
+ int ret;
+
+ mutex_lock(&itmt_update_mutex);
+
+ if (!sched_itmt_capable) {
+ mutex_unlock(&itmt_update_mutex);
+ return -EINVAL;
+ }
+
+ old_sysctl = sysctl_sched_itmt_enabled;
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+ if (!ret && write && old_sysctl != sysctl_sched_itmt_enabled) {
+ x86_topology_update = true;
+ rebuild_sched_domains();
+ }
+
+ mutex_unlock(&itmt_update_mutex);
+
+ return ret;
+}
+
+static unsigned int zero;
+static unsigned int one = 1;
+static struct ctl_table itmt_kern_table[] = {
+ {
+ .procname = "sched_itmt_enabled",
+ .data = &sysctl_sched_itmt_enabled,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = sched_itmt_update_handler,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ {}
+};
+
+static struct ctl_table itmt_root_table[] = {
+ {
+ .procname = "kernel",
+ .mode = 0555,
+ .child = itmt_kern_table,
+ },
+ {}
+};
+
+static struct ctl_table_header *itmt_sysctl_header;
+
+/**
+ * sched_set_itmt_support() - Indicate platform supports ITMT
+ *
+ * This function is used by the OS to indicate to scheduler that the platform
+ * is capable of supporting the ITMT feature.
+ *
+ * The current scheme has the pstate driver detects if the system
+ * is ITMT capable and call sched_set_itmt_support.
+ *
+ * This must be done only after sched_set_itmt_core_prio
+ * has been called to set the cpus' priorities.
+ * It must not be called with cpu hot plug lock
+ * held as we need to acquire the lock to rebuild sched domains
+ * later.
+ *
+ * Return: 0 on success
+ */
+int sched_set_itmt_support(void)
+{
+ mutex_lock(&itmt_update_mutex);
+
+ if (sched_itmt_capable) {
+ mutex_unlock(&itmt_update_mutex);
+ return 0;
+ }
+
+ itmt_sysctl_header = register_sysctl_table(itmt_root_table);
+ if (!itmt_sysctl_header) {
+ mutex_unlock(&itmt_update_mutex);
+ return -ENOMEM;
+ }
+
+ sched_itmt_capable = true;
+
+ sysctl_sched_itmt_enabled = 1;
+
+ if (sysctl_sched_itmt_enabled) {
+ x86_topology_update = true;
+ rebuild_sched_domains();
+ }
+
+ mutex_unlock(&itmt_update_mutex);
+
+ return 0;
+}
+
+/**
+ * sched_clear_itmt_support() - Revoke platform's support of ITMT
+ *
+ * This function is used by the OS to indicate that it has
+ * revoked the platform's support of ITMT feature.
+ *
+ * It must not be called with cpu hot plug lock
+ * held as we need to acquire the lock to rebuild sched domains
+ * later.
+ */
+void sched_clear_itmt_support(void)
+{
+ mutex_lock(&itmt_update_mutex);
+
+ if (!sched_itmt_capable) {
+ mutex_unlock(&itmt_update_mutex);
+ return;
+ }
+ sched_itmt_capable = false;
+
+ if (itmt_sysctl_header) {
+ unregister_sysctl_table(itmt_sysctl_header);
+ itmt_sysctl_header = NULL;
+ }
+
+ if (sysctl_sched_itmt_enabled) {
+ /* disable sched_itmt if we are no longer ITMT capable */
+ sysctl_sched_itmt_enabled = 0;
+ x86_topology_update = true;
+ rebuild_sched_domains();
+ }
+
+ mutex_unlock(&itmt_update_mutex);
+}
+
+int arch_asym_cpu_priority(int cpu)
+{
+ return per_cpu(sched_core_priority, cpu);
+}
+
+/**
+ * sched_set_itmt_core_prio() - Set CPU priority based on ITMT
+ * @prio: Priority of cpu core
+ * @core_cpu: The cpu number associated with the core
+ *
+ * The pstate driver will find out the max boost frequency
+ * and call this function to set a priority proportional
+ * to the max boost frequency. CPU with higher boost
+ * frequency will receive higher priority.
+ *
+ * No need to rebuild sched domain after updating
+ * the CPU priorities. The sched domains have no
+ * dependency on CPU priorities.
+ */
+void sched_set_itmt_core_prio(int prio, int core_cpu)
+{
+ int cpu, i = 1;
+
+ for_each_cpu(cpu, topology_sibling_cpumask(core_cpu)) {
+ int smt_prio;
+
+ /*
+ * Ensure that the siblings are moved to the end
+ * of the priority chain and only used when
+ * all other high priority cpus are out of capacity.
+ */
+ smt_prio = prio * smp_num_siblings / i;
+ per_cpu(sched_core_priority, cpu) = smt_prio;
+ i++;
+ }
+}
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index edbbfc854e39..36bc66416021 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -42,7 +42,6 @@
#include <asm/traps.h>
#include <asm/desc.h>
#include <asm/tlbflush.h>
-#include <asm/idle.h>
#include <asm/apic.h>
#include <asm/apicdef.h>
#include <asm/hypervisor.h>
@@ -267,13 +266,11 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
case KVM_PV_REASON_PAGE_NOT_PRESENT:
/* page is swapped out by the host. */
prev_state = exception_enter();
- exit_idle();
kvm_async_pf_task_wait((u32)read_cr2());
exception_exit(prev_state);
break;
case KVM_PV_REASON_PAGE_READY:
rcu_irq_enter();
- exit_idle();
kvm_async_pf_task_wake((u32)read_cr2());
rcu_irq_exit();
break;
@@ -308,7 +305,7 @@ static void kvm_register_steal_time(void)
static DEFINE_PER_CPU(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
-static void kvm_guest_apic_eoi_write(u32 reg, u32 val)
+static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
{
/**
* This relies on __test_and_clear_bit to modify the memory
@@ -319,7 +316,7 @@ static void kvm_guest_apic_eoi_write(u32 reg, u32 val)
*/
if (__test_and_clear_bit(KVM_PV_EOI_BIT, this_cpu_ptr(&kvm_apic_eoi)))
return;
- apic_write(APIC_EOI, APIC_EOI_ACK);
+ apic->native_eoi_write(APIC_EOI, APIC_EOI_ACK);
}
static void kvm_guest_cpu_init(void)
@@ -592,6 +589,14 @@ out:
local_irq_restore(flags);
}
+__visible bool __kvm_vcpu_is_preempted(int cpu)
+{
+ struct kvm_steal_time *src = &per_cpu(steal_time, cpu);
+
+ return !!src->preempted;
+}
+PV_CALLEE_SAVE_REGS_THUNK(__kvm_vcpu_is_preempted);
+
/*
* Setup pv_lock_ops to exploit KVM_FEATURE_PV_UNHALT if present.
*/
@@ -608,6 +613,11 @@ void __init kvm_spinlock_init(void)
pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
pv_lock_ops.wait = kvm_wait;
pv_lock_ops.kick = kvm_kick_cpu;
+
+ if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+ pv_lock_ops.vcpu_is_preempted =
+ PV_CALLEE_SAVE(__kvm_vcpu_is_preempted);
+ }
}
static __init int kvm_spinlock_init_jump(void)
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 6707039b9032..d4a15831ac58 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -34,10 +34,10 @@ static void flush_ldt(void *current_mm)
}
/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
-static struct ldt_struct *alloc_ldt_struct(int size)
+static struct ldt_struct *alloc_ldt_struct(unsigned int size)
{
struct ldt_struct *new_ldt;
- int alloc_size;
+ unsigned int alloc_size;
if (size > LDT_ENTRIES)
return NULL;
@@ -93,7 +93,7 @@ static void free_ldt_struct(struct ldt_struct *ldt)
paravirt_free_ldt(ldt->entries, ldt->size);
if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
- vfree(ldt->entries);
+ vfree_atomic(ldt->entries);
else
free_page((unsigned long)ldt->entries);
kfree(ldt);
@@ -207,11 +207,11 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct *mm = current->mm;
+ struct ldt_struct *new_ldt, *old_ldt;
+ unsigned int oldsize, newsize;
+ struct user_desc ldt_info;
struct desc_struct ldt;
int error;
- struct user_desc ldt_info;
- int oldsize, newsize;
- struct ldt_struct *new_ldt, *old_ldt;
error = -EINVAL;
if (bytecount != sizeof(ldt_info))
@@ -249,7 +249,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
old_ldt = mm->context.ldt;
oldsize = old_ldt ? old_ldt->size : 0;
- newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+ newsize = max(ldt_info.entry_number + 1, oldsize);
error = -ENOMEM;
new_ldt = alloc_ldt_struct(newsize);
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 7f3550acde1b..f5e3ff835cc8 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -44,6 +44,7 @@
#include <asm/msr.h>
static struct class *msr_class;
+static enum cpuhp_state cpuhp_msr_state;
static ssize_t msr_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
@@ -180,7 +181,7 @@ static const struct file_operations msr_fops = {
.compat_ioctl = msr_ioctl,
};
-static int msr_device_create(int cpu)
+static int msr_device_create(unsigned int cpu)
{
struct device *dev;
@@ -189,34 +190,12 @@ static int msr_device_create(int cpu)
return PTR_ERR_OR_ZERO(dev);
}
-static void msr_device_destroy(int cpu)
+static int msr_device_destroy(unsigned int cpu)
{
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ return 0;
}
-static int msr_class_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
- int err = 0;
-
- switch (action) {
- case CPU_UP_PREPARE:
- err = msr_device_create(cpu);
- break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- msr_device_destroy(cpu);
- break;
- }
- return notifier_from_errno(err);
-}
-
-static struct notifier_block __refdata msr_class_cpu_notifier = {
- .notifier_call = msr_class_cpu_callback,
-};
-
static char *msr_devnode(struct device *dev, umode_t *mode)
{
return kasprintf(GFP_KERNEL, "cpu/%u/msr", MINOR(dev->devt));
@@ -224,13 +203,11 @@ static char *msr_devnode(struct device *dev, umode_t *mode)
static int __init msr_init(void)
{
- int i, err = 0;
- i = 0;
+ int err;
if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) {
pr_err("unable to get major %d for msr\n", MSR_MAJOR);
- err = -EBUSY;
- goto out;
+ return -EBUSY;
}
msr_class = class_create(THIS_MODULE, "msr");
if (IS_ERR(msr_class)) {
@@ -239,44 +216,28 @@ static int __init msr_init(void)
}
msr_class->devnode = msr_devnode;
- cpu_notifier_register_begin();
- for_each_online_cpu(i) {
- err = msr_device_create(i);
- if (err != 0)
- goto out_class;
- }
- __register_hotcpu_notifier(&msr_class_cpu_notifier);
- cpu_notifier_register_done();
-
- err = 0;
- goto out;
+ err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/msr:online",
+ msr_device_create, msr_device_destroy);
+ if (err < 0)
+ goto out_class;
+ cpuhp_msr_state = err;
+ return 0;
out_class:
- i = 0;
- for_each_online_cpu(i)
- msr_device_destroy(i);
- cpu_notifier_register_done();
+ cpuhp_remove_state(cpuhp_msr_state);
class_destroy(msr_class);
out_chrdev:
__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
-out:
return err;
}
+module_init(msr_init);
static void __exit msr_exit(void)
{
- int cpu = 0;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- msr_device_destroy(cpu);
+ cpuhp_remove_state(cpuhp_msr_state);
class_destroy(msr_class);
__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
- __unregister_hotcpu_notifier(&msr_class_cpu_notifier);
- cpu_notifier_register_done();
}
-
-module_init(msr_init);
module_exit(msr_exit)
MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c
index 2c55a003b793..6d4bf812af45 100644
--- a/arch/x86/kernel/paravirt-spinlocks.c
+++ b/arch/x86/kernel/paravirt-spinlocks.c
@@ -12,7 +12,6 @@ __visible void __native_queued_spin_unlock(struct qspinlock *lock)
{
native_queued_spin_unlock(lock);
}
-
PV_CALLEE_SAVE_REGS_THUNK(__native_queued_spin_unlock);
bool pv_is_native_spin_unlock(void)
@@ -21,12 +20,25 @@ bool pv_is_native_spin_unlock(void)
__raw_callee_save___native_queued_spin_unlock;
}
+__visible bool __native_vcpu_is_preempted(int cpu)
+{
+ return false;
+}
+PV_CALLEE_SAVE_REGS_THUNK(__native_vcpu_is_preempted);
+
+bool pv_is_native_vcpu_is_preempted(void)
+{
+ return pv_lock_ops.vcpu_is_preempted.func ==
+ __raw_callee_save___native_vcpu_is_preempted;
+}
+
struct pv_lock_ops pv_lock_ops = {
#ifdef CONFIG_SMP
.queued_spin_lock_slowpath = native_queued_spin_lock_slowpath,
.queued_spin_unlock = PV_CALLEE_SAVE(__native_queued_spin_unlock),
.wait = paravirt_nop,
.kick = paravirt_nop,
+ .vcpu_is_preempted = PV_CALLEE_SAVE(__native_vcpu_is_preempted),
#endif /* SMP */
};
EXPORT_SYMBOL(pv_lock_ops);
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index bbf3d5933eaa..a1bfba0f7234 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -328,7 +328,6 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
.cpuid = native_cpuid,
.get_debugreg = native_get_debugreg,
.set_debugreg = native_set_debugreg,
- .clts = native_clts,
.read_cr0 = native_read_cr0,
.write_cr0 = native_write_cr0,
.read_cr4 = native_read_cr4,
diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c
index 920c6ae08592..d33ef165b1f8 100644
--- a/arch/x86/kernel/paravirt_patch_32.c
+++ b/arch/x86/kernel/paravirt_patch_32.c
@@ -8,10 +8,10 @@ DEF_NATIVE(pv_cpu_ops, iret, "iret");
DEF_NATIVE(pv_mmu_ops, read_cr2, "mov %cr2, %eax");
DEF_NATIVE(pv_mmu_ops, write_cr3, "mov %eax, %cr3");
DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax");
-DEF_NATIVE(pv_cpu_ops, clts, "clts");
#if defined(CONFIG_PARAVIRT_SPINLOCKS)
DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%eax)");
+DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %eax, %eax");
#endif
unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len)
@@ -27,6 +27,7 @@ unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len)
}
extern bool pv_is_native_spin_unlock(void);
+extern bool pv_is_native_vcpu_is_preempted(void);
unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
unsigned long addr, unsigned len)
@@ -48,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
PATCH_SITE(pv_mmu_ops, read_cr2);
PATCH_SITE(pv_mmu_ops, read_cr3);
PATCH_SITE(pv_mmu_ops, write_cr3);
- PATCH_SITE(pv_cpu_ops, clts);
#if defined(CONFIG_PARAVIRT_SPINLOCKS)
case PARAVIRT_PATCH(pv_lock_ops.queued_spin_unlock):
if (pv_is_native_spin_unlock()) {
@@ -56,9 +56,19 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
end = end_pv_lock_ops_queued_spin_unlock;
goto patch_site;
}
+ goto patch_default;
+
+ case PARAVIRT_PATCH(pv_lock_ops.vcpu_is_preempted):
+ if (pv_is_native_vcpu_is_preempted()) {
+ start = start_pv_lock_ops_vcpu_is_preempted;
+ end = end_pv_lock_ops_vcpu_is_preempted;
+ goto patch_site;
+ }
+ goto patch_default;
#endif
default:
+patch_default:
ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
break;
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c
index bb3840cedb4f..f4fcf26c9fce 100644
--- a/arch/x86/kernel/paravirt_patch_64.c
+++ b/arch/x86/kernel/paravirt_patch_64.c
@@ -10,7 +10,6 @@ DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax");
DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
-DEF_NATIVE(pv_cpu_ops, clts, "clts");
DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
@@ -21,6 +20,7 @@ DEF_NATIVE(, mov64, "mov %rdi, %rax");
#if defined(CONFIG_PARAVIRT_SPINLOCKS)
DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%rdi)");
+DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %rax, %rax");
#endif
unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len)
@@ -36,6 +36,7 @@ unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len)
}
extern bool pv_is_native_spin_unlock(void);
+extern bool pv_is_native_vcpu_is_preempted(void);
unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
unsigned long addr, unsigned len)
@@ -58,7 +59,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
PATCH_SITE(pv_mmu_ops, read_cr2);
PATCH_SITE(pv_mmu_ops, read_cr3);
PATCH_SITE(pv_mmu_ops, write_cr3);
- PATCH_SITE(pv_cpu_ops, clts);
PATCH_SITE(pv_mmu_ops, flush_tlb_single);
PATCH_SITE(pv_cpu_ops, wbinvd);
#if defined(CONFIG_PARAVIRT_SPINLOCKS)
@@ -68,9 +68,19 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
end = end_pv_lock_ops_queued_spin_unlock;
goto patch_site;
}
+ goto patch_default;
+
+ case PARAVIRT_PATCH(pv_lock_ops.vcpu_is_preempted):
+ if (pv_is_native_vcpu_is_preempted()) {
+ start = start_pv_lock_ops_vcpu_is_preempted;
+ end = end_pv_lock_ops_vcpu_is_preempted;
+ goto patch_site;
+ }
+ goto patch_default;
#endif
default:
+patch_default:
ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
break;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 0888a879120f..43c36d8a6ae2 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -23,7 +23,6 @@
#include <asm/cpu.h>
#include <asm/apic.h>
#include <asm/syscalls.h>
-#include <asm/idle.h>
#include <asm/uaccess.h>
#include <asm/mwait.h>
#include <asm/fpu/internal.h>
@@ -65,23 +64,6 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
};
EXPORT_PER_CPU_SYMBOL(cpu_tss);
-#ifdef CONFIG_X86_64
-static DEFINE_PER_CPU(unsigned char, is_idle);
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
- atomic_notifier_chain_register(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_register);
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
- atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_unregister);
-#endif
-
/*
* this gets called so that we can store lazy state into memory and copy the
* current task into the new thread.
@@ -251,39 +233,9 @@ static inline void play_dead(void)
}
#endif
-#ifdef CONFIG_X86_64
-void enter_idle(void)
-{
- this_cpu_write(is_idle, 1);
- atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
-}
-
-static void __exit_idle(void)
-{
- if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
- return;
- atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
-}
-
-/* Called from interrupts to signify idle end */
-void exit_idle(void)
-{
- /* idle loop has pid 0 */
- if (current->pid)
- return;
- __exit_idle();
-}
-#endif
-
void arch_cpu_idle_enter(void)
{
local_touch_nmi();
- enter_idle();
-}
-
-void arch_cpu_idle_exit(void)
-{
- __exit_idle();
}
void arch_cpu_idle_dead(void)
@@ -336,59 +288,33 @@ void stop_this_cpu(void *dummy)
halt();
}
-bool amd_e400_c1e_detected;
-EXPORT_SYMBOL(amd_e400_c1e_detected);
-
-static cpumask_var_t amd_e400_c1e_mask;
-
-void amd_e400_remove_cpu(int cpu)
-{
- if (amd_e400_c1e_mask != NULL)
- cpumask_clear_cpu(cpu, amd_e400_c1e_mask);
-}
-
/*
- * AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt
- * pending message MSR. If we detect C1E, then we handle it the same
- * way as C3 power states (local apic timer and TSC stop)
+ * AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
+ * states (local apic timer and TSC stop).
*/
static void amd_e400_idle(void)
{
- if (!amd_e400_c1e_detected) {
- u32 lo, hi;
-
- rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
-
- if (lo & K8_INTP_C1E_ACTIVE_MASK) {
- amd_e400_c1e_detected = true;
- if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
- mark_tsc_unstable("TSC halt in AMD C1E");
- pr_info("System has AMD C1E enabled\n");
- }
+ /*
+ * We cannot use static_cpu_has_bug() here because X86_BUG_AMD_APIC_C1E
+ * gets set after static_cpu_has() places have been converted via
+ * alternatives.
+ */
+ if (!boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
+ default_idle();
+ return;
}
- if (amd_e400_c1e_detected) {
- int cpu = smp_processor_id();
+ tick_broadcast_enter();
- if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
- cpumask_set_cpu(cpu, amd_e400_c1e_mask);
- /* Force broadcast so ACPI can not interfere. */
- tick_broadcast_force();
- pr_info("Switch to broadcast mode on CPU%d\n", cpu);
- }
- tick_broadcast_enter();
-
- default_idle();
+ default_idle();
- /*
- * The switch back from broadcast mode needs to be
- * called with interrupts disabled.
- */
- local_irq_disable();
- tick_broadcast_exit();
- local_irq_enable();
- } else
- default_idle();
+ /*
+ * The switch back from broadcast mode needs to be called with
+ * interrupts disabled.
+ */
+ local_irq_disable();
+ tick_broadcast_exit();
+ local_irq_enable();
}
/*
@@ -448,8 +374,7 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
if (x86_idle || boot_option_idle_override == IDLE_POLL)
return;
- if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) {
- /* E400: APIC timer interrupt does not wake up CPU from C1e */
+ if (boot_cpu_has_bug(X86_BUG_AMD_E400)) {
pr_info("using AMD E400 aware idle routine\n");
x86_idle = amd_e400_idle;
} else if (prefer_mwait_c1_over_halt(c)) {
@@ -459,11 +384,37 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
x86_idle = default_idle;
}
-void __init init_amd_e400_c1e_mask(void)
+void amd_e400_c1e_apic_setup(void)
+{
+ if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
+ pr_info("Switch to broadcast mode on CPU%d\n", smp_processor_id());
+ local_irq_disable();
+ tick_broadcast_force();
+ local_irq_enable();
+ }
+}
+
+void __init arch_post_acpi_subsys_init(void)
{
- /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */
- if (x86_idle == amd_e400_idle)
- zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL);
+ u32 lo, hi;
+
+ if (!boot_cpu_has_bug(X86_BUG_AMD_E400))
+ return;
+
+ /*
+ * AMD E400 detection needs to happen after ACPI has been enabled. If
+ * the machine is affected K8_INTP_C1E_ACTIVE_MASK bits are set in
+ * MSR_K8_INT_PENDING_MSG.
+ */
+ rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
+ if (!(lo & K8_INTP_C1E_ACTIVE_MASK))
+ return;
+
+ boot_cpu_set_bug(X86_BUG_AMD_APIC_C1E);
+
+ if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ mark_tsc_unstable("TSC halt in AMD C1E");
+ pr_info("System has AMD C1E enabled\n");
}
static int __init idle_setup(char *str)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index bd7be8efdc4c..d0d744108594 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -49,7 +49,6 @@
#include <asm/tlbflush.h>
#include <asm/cpu.h>
-#include <asm/idle.h>
#include <asm/syscalls.h>
#include <asm/debugreg.h>
#include <asm/switch_to.h>
@@ -72,10 +71,9 @@ void __show_regs(struct pt_regs *regs, int all)
savesegment(gs, gs);
}
- printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
- (u16)regs->cs, regs->ip, regs->flags,
- smp_processor_id());
- print_symbol("EIP is at %s\n", regs->ip);
+ printk(KERN_DEFAULT "EIP: %pS\n", (void *)regs->ip);
+ printk(KERN_DEFAULT "EFLAGS: %08lx CPU: %d\n", regs->flags,
+ smp_processor_id());
printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
regs->ax, regs->bx, regs->cx, regs->dx);
@@ -232,11 +230,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
struct fpu *next_fpu = &next->fpu;
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
- fpu_switch_t fpu_switch;
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
- fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
+ switch_fpu_prepare(prev_fpu, cpu);
/*
* Save away %gs. No need to save %fs, as it was saved on the
@@ -295,7 +292,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
if (prev->gs | next->gs)
lazy_load_gs(next->gs);
- switch_fpu_finish(next_fpu, fpu_switch);
+ switch_fpu_finish(next_fpu, cpu);
this_cpu_write(current_task, next_p);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index b3760b3c1ca0..a76b65e3e615 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -44,7 +44,6 @@
#include <asm/desc.h>
#include <asm/proto.h>
#include <asm/ia32.h>
-#include <asm/idle.h>
#include <asm/syscalls.h>
#include <asm/debugreg.h>
#include <asm/switch_to.h>
@@ -61,10 +60,15 @@ void __show_regs(struct pt_regs *regs, int all)
unsigned int fsindex, gsindex;
unsigned int ds, cs, es;
- printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
- printk_address(regs->ip);
- printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss,
- regs->sp, regs->flags);
+ printk(KERN_DEFAULT "RIP: %04lx:%pS\n", regs->cs & 0xffff,
+ (void *)regs->ip);
+ printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx", regs->ss,
+ regs->sp, regs->flags);
+ if (regs->orig_ax != -1)
+ pr_cont(" ORIG_RAX: %016lx\n", regs->orig_ax);
+ else
+ pr_cont("\n");
+
printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n",
regs->ax, regs->bx, regs->cx);
printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n",
@@ -265,9 +269,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
unsigned prev_fsindex, prev_gsindex;
- fpu_switch_t fpu_switch;
- fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
+ switch_fpu_prepare(prev_fpu, cpu);
/* We must save %fs and %gs before load_TLS() because
* %fs and %gs may be cleared by load_TLS().
@@ -417,7 +420,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
prev->gsbase = 0;
prev->gsindex = prev_gsindex;
- switch_fpu_finish(next_fpu, fpu_switch);
+ switch_fpu_finish(next_fpu, cpu);
/*
* Switch the PDA and FPU contexts.
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 79c6311cd912..5b21cb7d84d6 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -64,6 +64,15 @@ void mach_get_cmos_time(struct timespec *now)
unsigned int status, year, mon, day, hour, min, sec, century = 0;
unsigned long flags;
+ /*
+ * If pm_trace abused the RTC as storage, set the timespec to 0,
+ * which tells the caller that this RTC value is unusable.
+ */
+ if (!pm_trace_rtc_valid()) {
+ now->tv_sec = now->tv_nsec = 0;
+ return;
+ }
+
spin_lock_irqsave(&rtc_lock, flags);
/*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 9c337b0e8ba7..4cfba947d774 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -985,6 +985,30 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
+#ifdef CONFIG_MEMORY_HOTPLUG
+ /*
+ * Memory used by the kernel cannot be hot-removed because Linux
+ * cannot migrate the kernel pages. When memory hotplug is
+ * enabled, we should prevent memblock from allocating memory
+ * for the kernel.
+ *
+ * ACPI SRAT records all hotpluggable memory ranges. But before
+ * SRAT is parsed, we don't know about it.
+ *
+ * The kernel image is loaded into memory at very early time. We
+ * cannot prevent this anyway. So on NUMA system, we set any
+ * node the kernel resides in as un-hotpluggable.
+ *
+ * Since on modern servers, one node could have double-digit
+ * gigabytes memory, we can assume the memory around the kernel
+ * image is also un-hotpluggable. So before SRAT is parsed, just
+ * allocate memory near the kernel image to try the best to keep
+ * the kernel away from hotpluggable memory.
+ */
+ if (movable_node_is_enabled())
+ memblock_set_bottom_up(true);
+#endif
+
x86_report_nx();
/* after early param, so could get panic from serial */
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 2bbd27f89802..9820d6d977c6 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -1,7 +1,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/percpu.h>
@@ -12,6 +12,7 @@
#include <linux/pfn.h>
#include <asm/sections.h>
#include <asm/processor.h>
+#include <asm/desc.h>
#include <asm/setup.h>
#include <asm/mpspec.h>
#include <asm/apicdef.h>
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index c00cb64bc0a1..68f8cc222f25 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -261,10 +261,8 @@ static inline void __smp_reschedule_interrupt(void)
__visible void smp_reschedule_interrupt(struct pt_regs *regs)
{
- irq_enter();
ack_APIC_irq();
__smp_reschedule_interrupt();
- irq_exit();
/*
* KVM uses this interrupt to force a cpu out of guest mode
*/
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 42f5eb7b4f6c..0c37d4fd01b2 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -58,7 +58,6 @@
#include <asm/desc.h>
#include <asm/nmi.h>
#include <asm/irq.h>
-#include <asm/idle.h>
#include <asm/realmode.h>
#include <asm/cpu.h>
#include <asm/numa.h>
@@ -109,6 +108,17 @@ static bool logical_packages_frozen __read_mostly;
/* Maximum number of SMT threads on any online core */
int __max_smt_threads __read_mostly;
+/* Flag to indicate if a complete sched domain rebuild is required */
+bool x86_topology_update;
+
+int arch_update_cpu_topology(void)
+{
+ int retval = x86_topology_update;
+
+ x86_topology_update = false;
+ return retval;
+}
+
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
{
unsigned long flags;
@@ -471,22 +481,42 @@ static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
return false;
}
+#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC)
+static inline int x86_sched_itmt_flags(void)
+{
+ return sysctl_sched_itmt_enabled ? SD_ASYM_PACKING : 0;
+}
+
+#ifdef CONFIG_SCHED_MC
+static int x86_core_flags(void)
+{
+ return cpu_core_flags() | x86_sched_itmt_flags();
+}
+#endif
+#ifdef CONFIG_SCHED_SMT
+static int x86_smt_flags(void)
+{
+ return cpu_smt_flags() | x86_sched_itmt_flags();
+}
+#endif
+#endif
+
static struct sched_domain_topology_level x86_numa_in_package_topology[] = {
#ifdef CONFIG_SCHED_SMT
- { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
+ { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
#endif
#ifdef CONFIG_SCHED_MC
- { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
+ { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
#endif
{ NULL, },
};
static struct sched_domain_topology_level x86_topology[] = {
#ifdef CONFIG_SCHED_SMT
- { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
+ { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
#endif
#ifdef CONFIG_SCHED_MC
- { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
+ { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
#endif
{ cpu_cpu_mask, SD_INIT_NAME(DIE) },
{ NULL, },
@@ -821,14 +851,6 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
return (send_status | accept_status);
}
-void smp_announce(void)
-{
- int num_nodes = num_online_nodes();
-
- printk(KERN_INFO "x86: Booted up %d node%s, %d CPUs\n",
- num_nodes, (num_nodes > 1 ? "s" : ""), num_online_cpus());
-}
-
/* reduce the number of lines printed when booting a large cpu count system */
static void announce_cpu(int cpu, int apicid)
{
@@ -964,9 +986,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
int cpu0_nmi_registered = 0;
unsigned long timeout;
- idle->thread.sp = (unsigned long) (((struct pt_regs *)
- (THREAD_SIZE + task_stack_page(idle))) - 1);
-
+ idle->thread.sp = (unsigned long)task_pt_regs(idle);
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
initial_code = (unsigned long)start_secondary;
initial_stack = idle->thread.sp;
@@ -1111,7 +1131,7 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
return err;
/* the FPU context is blank, nobody can own it */
- __cpu_disable_lazy_restore(cpu);
+ per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
common_cpu_up(cpu, tidle);
@@ -1331,7 +1351,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
default_setup_apic_routing();
cpu0_logical_apicid = apic_bsp_setup(false);
- pr_info("CPU%d: ", 0);
+ pr_info("CPU0: ");
print_cpu_info(&cpu_data(0));
if (is_uv_system())
@@ -1575,7 +1595,6 @@ void play_dead_common(void)
{
idle_task_exit();
reset_lazy_tlbstate();
- amd_e400_remove_cpu(raw_smp_processor_id());
/* Ack it */
(void)cpu_report_death();
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index bd4e3d4d3625..bf0c6d049080 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -853,6 +853,8 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
dotraplinkage void
do_device_not_available(struct pt_regs *regs, long error_code)
{
+ unsigned long cr0;
+
RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
#ifdef CONFIG_MATH_EMULATION
@@ -866,10 +868,20 @@ do_device_not_available(struct pt_regs *regs, long error_code)
return;
}
#endif
- fpu__restore(&current->thread.fpu); /* interrupts still off */
-#ifdef CONFIG_X86_32
- cond_local_irq_enable(regs);
-#endif
+
+ /* This should not happen. */
+ cr0 = read_cr0();
+ if (WARN(cr0 & X86_CR0_TS, "CR0.TS was set")) {
+ /* Try to fix it up and carry on. */
+ write_cr0(cr0 & ~X86_CR0_TS);
+ } else {
+ /*
+ * Something terrible happened, and we're better off trying
+ * to kill the task than getting stuck in a never-ending
+ * loop of #NM faults.
+ */
+ die("unexpected #NM exception", regs, error_code);
+ }
}
NOKPROBE_SYMBOL(do_device_not_available);
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index a2456d4d286a..ea7b7f9a3b9e 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -14,13 +14,55 @@ unsigned long unwind_get_return_address(struct unwind_state *state)
if (unwind_done(state))
return 0;
+ if (state->regs && user_mode(state->regs))
+ return 0;
+
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
addr_p);
- return __kernel_text_address(addr) ? addr : 0;
+ if (!__kernel_text_address(addr)) {
+ printk_deferred_once(KERN_WARNING
+ "WARNING: unrecognized kernel stack return address %p at %p in %s:%d\n",
+ (void *)addr, addr_p, state->task->comm,
+ state->task->pid);
+ return 0;
+ }
+
+ return addr;
}
EXPORT_SYMBOL_GPL(unwind_get_return_address);
+static size_t regs_size(struct pt_regs *regs)
+{
+ /* x86_32 regs from kernel mode are two words shorter: */
+ if (IS_ENABLED(CONFIG_X86_32) && !user_mode(regs))
+ return sizeof(*regs) - 2*sizeof(long);
+
+ return sizeof(*regs);
+}
+
+static bool is_last_task_frame(struct unwind_state *state)
+{
+ unsigned long bp = (unsigned long)state->bp;
+ unsigned long regs = (unsigned long)task_pt_regs(state->task);
+
+ return bp == regs - FRAME_HEADER_SIZE;
+}
+
+/*
+ * This determines if the frame pointer actually contains an encoded pointer to
+ * pt_regs on the stack. See ENCODE_FRAME_POINTER.
+ */
+static struct pt_regs *decode_frame_pointer(unsigned long *bp)
+{
+ unsigned long regs = (unsigned long)bp;
+
+ if (!(regs & 0x1))
+ return NULL;
+
+ return (struct pt_regs *)(regs & ~0x1);
+}
+
static bool update_stack_state(struct unwind_state *state, void *addr,
size_t len)
{
@@ -43,26 +85,117 @@ static bool update_stack_state(struct unwind_state *state, void *addr,
bool unwind_next_frame(struct unwind_state *state)
{
- unsigned long *next_bp;
+ struct pt_regs *regs;
+ unsigned long *next_bp, *next_frame;
+ size_t next_len;
+ enum stack_type prev_type = state->stack_info.type;
if (unwind_done(state))
return false;
- next_bp = (unsigned long *)*state->bp;
+ /* have we reached the end? */
+ if (state->regs && user_mode(state->regs))
+ goto the_end;
+
+ if (is_last_task_frame(state)) {
+ regs = task_pt_regs(state->task);
+
+ /*
+ * kthreads (other than the boot CPU's idle thread) have some
+ * partial regs at the end of their stack which were placed
+ * there by copy_thread_tls(). But the regs don't have any
+ * useful information, so we can skip them.
+ *
+ * This user_mode() check is slightly broader than a PF_KTHREAD
+ * check because it also catches the awkward situation where a
+ * newly forked kthread transitions into a user task by calling
+ * do_execve(), which eventually clears PF_KTHREAD.
+ */
+ if (!user_mode(regs))
+ goto the_end;
+
+ /*
+ * We're almost at the end, but not quite: there's still the
+ * syscall regs frame. Entry code doesn't encode the regs
+ * pointer for syscalls, so we have to set it manually.
+ */
+ state->regs = regs;
+ state->bp = NULL;
+ return true;
+ }
+
+ /* get the next frame pointer */
+ if (state->regs)
+ next_bp = (unsigned long *)state->regs->bp;
+ else
+ next_bp = (unsigned long *)*state->bp;
+
+ /* is the next frame pointer an encoded pointer to pt_regs? */
+ regs = decode_frame_pointer(next_bp);
+ if (regs) {
+ next_frame = (unsigned long *)regs;
+ next_len = sizeof(*regs);
+ } else {
+ next_frame = next_bp;
+ next_len = FRAME_HEADER_SIZE;
+ }
/* make sure the next frame's data is accessible */
- if (!update_stack_state(state, next_bp, FRAME_HEADER_SIZE))
- return false;
+ if (!update_stack_state(state, next_frame, next_len)) {
+ /*
+ * Don't warn on bad regs->bp. An interrupt in entry code
+ * might cause a false positive warning.
+ */
+ if (state->regs)
+ goto the_end;
+
+ goto bad_address;
+ }
+
+ /* Make sure it only unwinds up and doesn't overlap the last frame: */
+ if (state->stack_info.type == prev_type) {
+ if (state->regs && (void *)next_frame < (void *)state->regs + regs_size(state->regs))
+ goto bad_address;
+
+ if (state->bp && (void *)next_frame < (void *)state->bp + FRAME_HEADER_SIZE)
+ goto bad_address;
+ }
/* move to the next frame */
- state->bp = next_bp;
+ if (regs) {
+ state->regs = regs;
+ state->bp = NULL;
+ } else {
+ state->bp = next_bp;
+ state->regs = NULL;
+ }
+
return true;
+
+bad_address:
+ if (state->regs) {
+ printk_deferred_once(KERN_WARNING
+ "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
+ state->regs, state->task->comm,
+ state->task->pid, next_frame);
+ } else {
+ printk_deferred_once(KERN_WARNING
+ "WARNING: kernel stack frame pointer at %p in %s:%d has bad value %p\n",
+ state->bp, state->task->comm,
+ state->task->pid, next_frame);
+ }
+the_end:
+ state->stack_info.type = STACK_TYPE_UNKNOWN;
+ return false;
}
EXPORT_SYMBOL_GPL(unwind_next_frame);
void __unwind_start(struct unwind_state *state, struct task_struct *task,
struct pt_regs *regs, unsigned long *first_frame)
{
+ unsigned long *bp, *frame;
+ size_t len;
+
memset(state, 0, sizeof(*state));
state->task = task;
@@ -73,12 +206,22 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
}
/* set up the starting stack frame */
- state->bp = get_frame_pointer(task, regs);
+ bp = get_frame_pointer(task, regs);
+ regs = decode_frame_pointer(bp);
+ if (regs) {
+ state->regs = regs;
+ frame = (unsigned long *)regs;
+ len = sizeof(*regs);
+ } else {
+ state->bp = bp;
+ frame = bp;
+ len = FRAME_HEADER_SIZE;
+ }
/* initialize stack info and make sure the frame data is accessible */
- get_stack_info(state->bp, state->task, &state->stack_info,
+ get_stack_info(frame, state->task, &state->stack_info,
&state->stack_mask);
- update_stack_state(state, state->bp, FRAME_HEADER_SIZE);
+ update_stack_state(state, frame, len);
/*
* The caller can provide the address of the first frame directly
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index dbf67f64d5ec..e79f15f108a8 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -91,10 +91,10 @@ SECTIONS
/* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
+ _stext = .;
/* bootstrapping code */
HEAD_TEXT
. = ALIGN(8);
- _stext = .;
TEXT_TEXT
SCHED_TEXT
CPUIDLE_TEXT
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index afa7bbb596cd..0aefb626fa8f 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -16,7 +16,6 @@
#include <linux/export.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
-#include <asm/fpu/internal.h> /* For use_eager_fpu. Ugh! */
#include <asm/user.h>
#include <asm/fpu/xstate.h>
#include "cpuid.h"
@@ -114,8 +113,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
- if (use_eager_fpu())
- kvm_x86_ops->fpu_activate(vcpu);
+ kvm_x86_ops->fpu_activate(vcpu);
/*
* The existing code assumes virtual address is 48-bit in the canonical
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index d9c7e986b4e4..87c5880ba3b7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -4405,7 +4405,8 @@ static u64 *get_written_sptes(struct kvm_mmu_page *sp, gpa_t gpa, int *nspte)
}
static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
- const u8 *new, int bytes)
+ const u8 *new, int bytes,
+ struct kvm_page_track_notifier_node *node)
{
gfn_t gfn = gpa >> PAGE_SHIFT;
struct kvm_mmu_page *sp;
@@ -4617,11 +4618,19 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu)
init_kvm_mmu(vcpu);
}
+static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
+ struct kvm_memory_slot *slot,
+ struct kvm_page_track_notifier_node *node)
+{
+ kvm_mmu_invalidate_zap_all_pages(kvm);
+}
+
void kvm_mmu_init_vm(struct kvm *kvm)
{
struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
node->track_write = kvm_mmu_pte_write;
+ node->track_flush_slot = kvm_mmu_invalidate_zap_pages_in_memslot;
kvm_page_track_register_notifier(kvm, node);
}
diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c
index b431539c3714..4a1c13eaa518 100644
--- a/arch/x86/kvm/page_track.c
+++ b/arch/x86/kvm/page_track.c
@@ -106,6 +106,7 @@ void kvm_slot_page_track_add_page(struct kvm *kvm,
if (kvm_mmu_slot_gfn_write_protect(kvm, slot, gfn))
kvm_flush_remote_tlbs(kvm);
}
+EXPORT_SYMBOL_GPL(kvm_slot_page_track_add_page);
/*
* remove the guest page from the tracking pool which stops the interception
@@ -135,6 +136,7 @@ void kvm_slot_page_track_remove_page(struct kvm *kvm,
*/
kvm_mmu_gfn_allow_lpage(slot, gfn);
}
+EXPORT_SYMBOL_GPL(kvm_slot_page_track_remove_page);
/*
* check if the corresponding access on the specified guest page is tracked.
@@ -181,6 +183,7 @@ kvm_page_track_register_notifier(struct kvm *kvm,
hlist_add_head_rcu(&n->node, &head->track_notifier_list);
spin_unlock(&kvm->mmu_lock);
}
+EXPORT_SYMBOL_GPL(kvm_page_track_register_notifier);
/*
* stop receiving the event interception. It is the opposed operation of
@@ -199,6 +202,7 @@ kvm_page_track_unregister_notifier(struct kvm *kvm,
spin_unlock(&kvm->mmu_lock);
synchronize_srcu(&head->track_srcu);
}
+EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);
/*
* Notify the node that write access is intercepted and write emulation is
@@ -222,6 +226,31 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
idx = srcu_read_lock(&head->track_srcu);
hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
if (n->track_write)
- n->track_write(vcpu, gpa, new, bytes);
+ n->track_write(vcpu, gpa, new, bytes, n);
+ srcu_read_unlock(&head->track_srcu, idx);
+}
+
+/*
+ * Notify the node that memory slot is being removed or moved so that it can
+ * drop write-protection for the pages in the memory slot.
+ *
+ * The node should figure out it has any write-protected pages in this slot
+ * by itself.
+ */
+void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+ struct kvm_page_track_notifier_head *head;
+ struct kvm_page_track_notifier_node *n;
+ int idx;
+
+ head = &kvm->arch.track_notifier_head;
+
+ if (hlist_empty(&head->track_notifier_list))
+ return;
+
+ idx = srcu_read_lock(&head->track_srcu);
+ hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
+ if (n->track_flush_slot)
+ n->track_flush_slot(kvm, slot, n);
srcu_read_unlock(&head->track_srcu, idx);
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5382b82462fc..3980da515fd0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2145,12 +2145,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
#endif
if (vmx->host_state.msr_host_bndcfgs)
wrmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs);
- /*
- * If the FPU is not active (through the host task or
- * the guest vcpu), then restore the cr0.TS bit.
- */
- if (!fpregs_active() && !vmx->vcpu.guest_fpu_loaded)
- stts();
load_gdt(this_cpu_ptr(&host_gdt));
}
@@ -4845,9 +4839,11 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
u32 low32, high32;
unsigned long tmpl;
struct desc_ptr dt;
- unsigned long cr4;
+ unsigned long cr0, cr4;
- vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */
+ cr0 = read_cr0();
+ WARN_ON(cr0 & X86_CR0_TS);
+ vmcs_writel(HOST_CR0, cr0); /* 22.2.3 */
vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
/* Save the most likely value for this task's CR4 in the VMCS. */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 04c5d96b1d67..2912684ff902 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2071,6 +2071,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
&vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
return;
+ vcpu->arch.st.steal.preempted = 0;
+
if (vcpu->arch.st.steal.version & 1)
vcpu->arch.st.steal.version += 1; /* first time write, random junk */
@@ -2826,8 +2828,22 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
}
+static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
+{
+ if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+ return;
+
+ vcpu->arch.st.steal.preempted = 1;
+
+ kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime,
+ &vcpu->arch.st.steal.preempted,
+ offsetof(struct kvm_steal_time, preempted),
+ sizeof(vcpu->arch.st.steal.preempted));
+}
+
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
+ kvm_steal_time_set_preempted(vcpu);
kvm_x86_ops->vcpu_put(vcpu);
kvm_put_guest_fpu(vcpu);
vcpu->arch.last_host_tsc = rdtsc();
@@ -5081,11 +5097,6 @@ static void emulator_get_fpu(struct x86_emulate_ctxt *ctxt)
{
preempt_disable();
kvm_load_guest_fpu(emul_to_vcpu(ctxt));
- /*
- * CR0.TS may reference the host fpu state, not the guest fpu state,
- * so it may be clear at this point.
- */
- clts();
}
static void emulator_put_fpu(struct x86_emulate_ctxt *ctxt)
@@ -7407,25 +7418,13 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
{
- if (!vcpu->guest_fpu_loaded) {
- vcpu->fpu_counter = 0;
+ if (!vcpu->guest_fpu_loaded)
return;
- }
vcpu->guest_fpu_loaded = 0;
copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
__kernel_fpu_end();
++vcpu->stat.fpu_reload;
- /*
- * If using eager FPU mode, or if the guest is a frequent user
- * of the FPU, just leave the FPU active for next time.
- * Every 255 times fpu_counter rolls over to 0; a guest that uses
- * the FPU in bursts will revert to loading it on demand.
- */
- if (!use_eager_fpu()) {
- if (++vcpu->fpu_counter < 5)
- kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
- }
trace_kvm_fpu(0);
}
@@ -8176,7 +8175,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
struct kvm_memory_slot *slot)
{
- kvm_mmu_invalidate_zap_all_pages(kvm);
+ kvm_page_track_flush_slot(kvm, slot);
}
static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 25da5bc8d83d..4ca0d78adcf0 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -497,38 +497,24 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
* a whole series of functions like read_cr0() and write_cr0().
*
* We start with cr0. cr0 allows you to turn on and off all kinds of basic
- * features, but Linux only really cares about one: the horrifically-named Task
- * Switched (TS) bit at bit 3 (ie. 8)
+ * features, but the only cr0 bit that Linux ever used at runtime was the
+ * horrifically-named Task Switched (TS) bit at bit 3 (ie. 8)
*
* What does the TS bit do? Well, it causes the CPU to trap (interrupt 7) if
* the floating point unit is used. Which allows us to restore FPU state
- * lazily after a task switch, and Linux uses that gratefully, but wouldn't a
- * name like "FPUTRAP bit" be a little less cryptic?
+ * lazily after a task switch if we wanted to, but wouldn't a name like
+ * "FPUTRAP bit" be a little less cryptic?
*
- * We store cr0 locally because the Host never changes it. The Guest sometimes
- * wants to read it and we'd prefer not to bother the Host unnecessarily.
+ * Fortunately, Linux keeps it simple and doesn't use TS, so we can ignore
+ * cr0.
*/
-static unsigned long current_cr0;
static void lguest_write_cr0(unsigned long val)
{
- lazy_hcall1(LHCALL_TS, val & X86_CR0_TS);
- current_cr0 = val;
}
static unsigned long lguest_read_cr0(void)
{
- return current_cr0;
-}
-
-/*
- * Intel provided a special instruction to clear the TS bit for people too cool
- * to use write_cr0() to do it. This "clts" instruction is faster, because all
- * the vowels have been optimized out.
- */
-static void lguest_clts(void)
-{
- lazy_hcall1(LHCALL_TS, 0);
- current_cr0 &= ~X86_CR0_TS;
+ return 0;
}
/*
@@ -1432,7 +1418,6 @@ __init void lguest_init(void)
pv_cpu_ops.load_tls = lguest_load_tls;
pv_cpu_ops.get_debugreg = lguest_get_debugreg;
pv_cpu_ops.set_debugreg = lguest_set_debugreg;
- pv_cpu_ops.clts = lguest_clts;
pv_cpu_ops.read_cr0 = lguest_read_cr0;
pv_cpu_ops.write_cr0 = lguest_write_cr0;
pv_cpu_ops.read_cr4 = lguest_read_cr4;
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index d376e4b48f88..c5959576c315 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -16,53 +16,6 @@
#include <asm/smap.h>
#include <asm/export.h>
-/* Standard copy_to_user with segment limit checking */
-ENTRY(_copy_to_user)
- mov PER_CPU_VAR(current_task), %rax
- movq %rdi,%rcx
- addq %rdx,%rcx
- jc bad_to_user
- cmpq TASK_addr_limit(%rax),%rcx
- ja bad_to_user
- ALTERNATIVE_2 "jmp copy_user_generic_unrolled", \
- "jmp copy_user_generic_string", \
- X86_FEATURE_REP_GOOD, \
- "jmp copy_user_enhanced_fast_string", \
- X86_FEATURE_ERMS
-ENDPROC(_copy_to_user)
-EXPORT_SYMBOL(_copy_to_user)
-
-/* Standard copy_from_user with segment limit checking */
-ENTRY(_copy_from_user)
- mov PER_CPU_VAR(current_task), %rax
- movq %rsi,%rcx
- addq %rdx,%rcx
- jc bad_from_user
- cmpq TASK_addr_limit(%rax),%rcx
- ja bad_from_user
- ALTERNATIVE_2 "jmp copy_user_generic_unrolled", \
- "jmp copy_user_generic_string", \
- X86_FEATURE_REP_GOOD, \
- "jmp copy_user_enhanced_fast_string", \
- X86_FEATURE_ERMS
-ENDPROC(_copy_from_user)
-EXPORT_SYMBOL(_copy_from_user)
-
-
- .section .fixup,"ax"
- /* must zero dest */
-ENTRY(bad_from_user)
-bad_from_user:
- movl %edx,%ecx
- xorl %eax,%eax
- rep
- stosb
-bad_to_user:
- movl %edx,%eax
- ret
-ENDPROC(bad_from_user)
- .previous
-
/*
* copy_user_generic_unrolled - memory copy with exception handling.
* This version is for CPUs like P4 that don't have efficient micro
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index d1dee753b949..07764255b611 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -113,14 +113,14 @@ int msr_clear_bit(u32 msr, u8 bit)
}
#ifdef CONFIG_TRACEPOINTS
-void do_trace_write_msr(unsigned msr, u64 val, int failed)
+void do_trace_write_msr(unsigned int msr, u64 val, int failed)
{
trace_write_msr(msr, val, failed);
}
EXPORT_SYMBOL(do_trace_write_msr);
EXPORT_TRACEPOINT_SYMBOL(write_msr);
-void do_trace_read_msr(unsigned msr, u64 val, int failed)
+void do_trace_read_msr(unsigned int msr, u64 val, int failed)
{
trace_read_msr(msr, val, failed);
}
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index b4908789484e..c074799bddae 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -34,3 +34,52 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
return ret;
}
EXPORT_SYMBOL_GPL(copy_from_user_nmi);
+
+/**
+ * copy_to_user: - Copy a block of data into user space.
+ * @to: Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n: Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep if pagefaults are
+ * enabled.
+ *
+ * Copy data from kernel space to user space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long _copy_to_user(void __user *to, const void *from, unsigned n)
+{
+ if (access_ok(VERIFY_WRITE, to, n))
+ n = __copy_to_user(to, from, n);
+ return n;
+}
+EXPORT_SYMBOL(_copy_to_user);
+
+/**
+ * copy_from_user: - Copy a block of data from user space.
+ * @to: Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n: Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep if pagefaults are
+ * enabled.
+ *
+ * Copy data from user space to kernel space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+unsigned long _copy_from_user(void *to, const void __user *from, unsigned n)
+{
+ if (access_ok(VERIFY_READ, from, n))
+ n = __copy_from_user(to, from, n);
+ else
+ memset(to, 0, n);
+ return n;
+}
+EXPORT_SYMBOL(_copy_from_user);
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 3bc7baf2a711..0b281217c890 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -640,52 +640,3 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
return n;
}
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
-
-/**
- * copy_to_user: - Copy a block of data into user space.
- * @to: Destination address, in user space.
- * @from: Source address, in kernel space.
- * @n: Number of bytes to copy.
- *
- * Context: User context only. This function may sleep if pagefaults are
- * enabled.
- *
- * Copy data from kernel space to user space.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-unsigned long _copy_to_user(void __user *to, const void *from, unsigned n)
-{
- if (access_ok(VERIFY_WRITE, to, n))
- n = __copy_to_user(to, from, n);
- return n;
-}
-EXPORT_SYMBOL(_copy_to_user);
-
-/**
- * copy_from_user: - Copy a block of data from user space.
- * @to: Destination address, in kernel space.
- * @from: Source address, in user space.
- * @n: Number of bytes to copy.
- *
- * Context: User context only. This function may sleep if pagefaults are
- * enabled.
- *
- * Copy data from user space to kernel space.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- *
- * If some data could not be copied, this function will pad the copied
- * data to the requested size using zero bytes.
- */
-unsigned long _copy_from_user(void *to, const void __user *from, unsigned n)
-{
- if (access_ok(VERIFY_READ, from, n))
- n = __copy_from_user(to, from, n);
- else
- memset(to, 0, n);
- return n;
-}
-EXPORT_SYMBOL(_copy_from_user);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 9f72ca3b2669..17c55a536fdd 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -679,8 +679,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
printk(KERN_CONT "paging request");
printk(KERN_CONT " at %p\n", (void *) address);
- printk(KERN_ALERT "IP:");
- printk_address(regs->ip);
+ printk(KERN_ALERT "IP: %pS\n", (void *)regs->ip);
dump_pagetable(address);
}
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 83e701f160a9..efc32bc6862b 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -986,20 +986,17 @@ int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
return 0;
}
-int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
- pfn_t pfn)
+void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, pfn_t pfn)
{
enum page_cache_mode pcm;
if (!pat_enabled())
- return 0;
+ return;
/* Set prot based on lookup */
pcm = lookup_memtype(pfn_t_to_phys(pfn));
*prot = __pgprot((pgprot_val(*prot) & (~_PAGE_CACHE_MASK)) |
cachemode2protval(pcm));
-
- return 0;
}
/*
diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c
index f88ce0e5efd9..2dab69a706ec 100644
--- a/arch/x86/mm/pkeys.c
+++ b/arch/x86/mm/pkeys.c
@@ -141,8 +141,7 @@ u32 init_pkru_value = PKRU_AD_KEY( 1) | PKRU_AD_KEY( 2) | PKRU_AD_KEY( 3) |
* Called from the FPU code when creating a fresh set of FPU
* registers. This is called from a very specific context where
* we know the FPU regstiers are safe for use and we can use PKRU
- * directly. The fact that PKRU is only available when we are
- * using eagerfpu mode makes this possible.
+ * directly.
*/
void copy_init_pkru_to_fpregs(void)
{
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index fe04a04dab8e..e76d1af60f7a 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -853,7 +853,7 @@ xadd: if (is_imm8(insn->off))
func = (u8 *) __bpf_call_base + imm32;
jmp_offset = func - (image + addrs[i]);
if (seen_ld_abs) {
- reload_skb_data = bpf_helper_changes_skb_data(func);
+ reload_skb_data = bpf_helper_changes_pkt_data(func);
if (reload_skb_data) {
EMIT1(0x57); /* push %rdi */
jmp_offset += 22; /* pop, mov, sub, mov */
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 28c04123b6dd..ffdbc4836b4f 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -339,10 +339,11 @@ fail:
return 0;
}
-static void nmi_cpu_setup(void *dummy)
+static void nmi_cpu_setup(void)
{
int cpu = smp_processor_id();
struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+
nmi_cpu_save_registers(msrs);
raw_spin_lock(&oprofilefs_lock);
model->setup_ctrs(model, msrs);
@@ -369,7 +370,7 @@ static void nmi_cpu_restore_registers(struct op_msrs *msrs)
}
}
-static void nmi_cpu_shutdown(void *dummy)
+static void nmi_cpu_shutdown(void)
{
unsigned int v;
int cpu = smp_processor_id();
@@ -387,20 +388,26 @@ static void nmi_cpu_shutdown(void *dummy)
nmi_cpu_restore_registers(msrs);
}
-static void nmi_cpu_up(void *dummy)
+static int nmi_cpu_online(unsigned int cpu)
{
+ local_irq_disable();
if (nmi_enabled)
- nmi_cpu_setup(dummy);
+ nmi_cpu_setup();
if (ctr_running)
- nmi_cpu_start(dummy);
+ nmi_cpu_start(NULL);
+ local_irq_enable();
+ return 0;
}
-static void nmi_cpu_down(void *dummy)
+static int nmi_cpu_down_prep(unsigned int cpu)
{
+ local_irq_disable();
if (ctr_running)
- nmi_cpu_stop(dummy);
+ nmi_cpu_stop(NULL);
if (nmi_enabled)
- nmi_cpu_shutdown(dummy);
+ nmi_cpu_shutdown();
+ local_irq_enable();
+ return 0;
}
static int nmi_create_files(struct dentry *root)
@@ -433,26 +440,7 @@ static int nmi_create_files(struct dentry *root)
return 0;
}
-static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
- void *data)
-{
- int cpu = (unsigned long)data;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_DOWN_FAILED:
- case CPU_ONLINE:
- smp_call_function_single(cpu, nmi_cpu_up, NULL, 0);
- break;
- case CPU_DOWN_PREPARE:
- smp_call_function_single(cpu, nmi_cpu_down, NULL, 1);
- break;
- }
- return NOTIFY_DONE;
-}
-
-static struct notifier_block oprofile_cpu_nb = {
- .notifier_call = oprofile_cpu_notifier
-};
+static enum cpuhp_state cpuhp_nmi_online;
static int nmi_setup(void)
{
@@ -495,20 +483,17 @@ static int nmi_setup(void)
if (err)
goto fail;
- cpu_notifier_register_begin();
-
- /* Use get/put_online_cpus() to protect 'nmi_enabled' */
- get_online_cpus();
nmi_enabled = 1;
/* make nmi_enabled visible to the nmi handler: */
smp_mb();
- on_each_cpu(nmi_cpu_setup, NULL, 1);
- __register_cpu_notifier(&oprofile_cpu_nb);
- put_online_cpus();
-
- cpu_notifier_register_done();
-
+ err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/oprofile:online",
+ nmi_cpu_online, nmi_cpu_down_prep);
+ if (err < 0)
+ goto fail_nmi;
+ cpuhp_nmi_online = err;
return 0;
+fail_nmi:
+ unregister_nmi_handler(NMI_LOCAL, "oprofile");
fail:
free_msrs();
return err;
@@ -518,17 +503,9 @@ static void nmi_shutdown(void)
{
struct op_msrs *msrs;
- cpu_notifier_register_begin();
-
- /* Use get/put_online_cpus() to protect 'nmi_enabled' & 'ctr_running' */
- get_online_cpus();
- on_each_cpu(nmi_cpu_shutdown, NULL, 1);
+ cpuhp_remove_state(cpuhp_nmi_online);
nmi_enabled = 0;
ctr_running = 0;
- __unregister_cpu_notifier(&oprofile_cpu_nb);
- put_online_cpus();
-
- cpu_notifier_register_done();
/* make variables visible to the nmi handler: */
smp_mb();
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index c20d2cc7ef64..ae387e5ee6f7 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -327,35 +327,18 @@ static int __init early_root_info_init(void)
#define ENABLE_CF8_EXT_CFG (1ULL << 46)
-static void enable_pci_io_ecs(void *unused)
+static int amd_bus_cpu_online(unsigned int cpu)
{
u64 reg;
+
rdmsrl(MSR_AMD64_NB_CFG, reg);
if (!(reg & ENABLE_CF8_EXT_CFG)) {
reg |= ENABLE_CF8_EXT_CFG;
wrmsrl(MSR_AMD64_NB_CFG, reg);
}
+ return 0;
}
-static int amd_cpu_notify(struct notifier_block *self, unsigned long action,
- void *hcpu)
-{
- int cpu = (long)hcpu;
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0);
- break;
- default:
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block amd_cpu_notifier = {
- .notifier_call = amd_cpu_notify,
-};
-
static void __init pci_enable_pci_io_ecs(void)
{
#ifdef CONFIG_AMD_NB
@@ -385,7 +368,7 @@ static void __init pci_enable_pci_io_ecs(void)
static int __init pci_io_ecs_init(void)
{
- int cpu;
+ int ret;
/* assume all cpus from fam10h have IO ECS */
if (boot_cpu_data.x86 < 0x10)
@@ -395,12 +378,9 @@ static int __init pci_io_ecs_init(void)
if (early_pci_allowed())
pci_enable_pci_io_ecs();
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
- (void *)(long)cpu);
- __register_cpu_notifier(&amd_cpu_notifier);
- cpu_notifier_register_done();
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/amd_bus:online",
+ amd_bus_cpu_online, NULL);
+ WARN_ON(ret < 0);
pci_probe |= PCI_HAS_IO_ECS;
diff --git a/arch/x86/platform/intel-mid/pwr.c b/arch/x86/platform/intel-mid/pwr.c
index 67375dda451c..ef03852ea6e8 100644
--- a/arch/x86/platform/intel-mid/pwr.c
+++ b/arch/x86/platform/intel-mid/pwr.c
@@ -270,7 +270,6 @@ int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
return 0;
}
-EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state);
pci_power_t intel_mid_pci_get_power_state(struct pci_dev *pdev)
{
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 9e42842e924a..766d4d3529a1 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -19,7 +19,6 @@
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_bau.h>
#include <asm/apic.h>
-#include <asm/idle.h>
#include <asm/tsc.h>
#include <asm/irq_vectors.h>
#include <asm/timer.h>
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
index cd5173a2733f..8410e7d0a5b5 100644
--- a/arch/x86/platform/uv/uv_nmi.c
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -387,8 +387,8 @@ static void uv_nmi_dump_cpu_ip_hdr(void)
/* Dump Instruction Pointer info */
static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs)
{
- pr_info("UV: %4d %6d %-32.32s ", cpu, current->pid, current->comm);
- printk_address(regs->ip);
+ pr_info("UV: %4d %6d %-32.32s %pS",
+ cpu, current->pid, current->comm, (void *)regs->ip);
}
/*
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
index 9634557a5444..ded2e8272382 100644
--- a/arch/x86/power/hibernate_64.c
+++ b/arch/x86/power/hibernate_64.c
@@ -11,6 +11,10 @@
#include <linux/gfp.h>
#include <linux/smp.h>
#include <linux/suspend.h>
+#include <linux/scatterlist.h>
+#include <linux/kdebug.h>
+
+#include <crypto/hash.h>
#include <asm/init.h>
#include <asm/proto.h>
@@ -177,14 +181,86 @@ int pfn_is_nosave(unsigned long pfn)
return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
}
+#define MD5_DIGEST_SIZE 16
+
struct restore_data_record {
unsigned long jump_address;
unsigned long jump_address_phys;
unsigned long cr3;
unsigned long magic;
+ u8 e820_digest[MD5_DIGEST_SIZE];
};
-#define RESTORE_MAGIC 0x123456789ABCDEF0UL
+#define RESTORE_MAGIC 0x23456789ABCDEF01UL
+
+#if IS_BUILTIN(CONFIG_CRYPTO_MD5)
+/**
+ * get_e820_md5 - calculate md5 according to given e820 map
+ *
+ * @map: the e820 map to be calculated
+ * @buf: the md5 result to be stored to
+ */
+static int get_e820_md5(struct e820map *map, void *buf)
+{
+ struct scatterlist sg;
+ struct crypto_ahash *tfm;
+ int size;
+ int ret = 0;
+
+ tfm = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm))
+ return -ENOMEM;
+
+ {
+ AHASH_REQUEST_ON_STACK(req, tfm);
+ size = offsetof(struct e820map, map)
+ + sizeof(struct e820entry) * map->nr_map;
+ ahash_request_set_tfm(req, tfm);
+ sg_init_one(&sg, (u8 *)map, size);
+ ahash_request_set_callback(req, 0, NULL, NULL);
+ ahash_request_set_crypt(req, &sg, buf, size);
+
+ if (crypto_ahash_digest(req))
+ ret = -EINVAL;
+ ahash_request_zero(req);
+ }
+ crypto_free_ahash(tfm);
+
+ return ret;
+}
+
+static void hibernation_e820_save(void *buf)
+{
+ get_e820_md5(e820_saved, buf);
+}
+
+static bool hibernation_e820_mismatch(void *buf)
+{
+ int ret;
+ u8 result[MD5_DIGEST_SIZE];
+
+ memset(result, 0, MD5_DIGEST_SIZE);
+ /* If there is no digest in suspend kernel, let it go. */
+ if (!memcmp(result, buf, MD5_DIGEST_SIZE))
+ return false;
+
+ ret = get_e820_md5(e820_saved, result);
+ if (ret)
+ return true;
+
+ return memcmp(result, buf, MD5_DIGEST_SIZE) ? true : false;
+}
+#else
+static void hibernation_e820_save(void *buf)
+{
+}
+
+static bool hibernation_e820_mismatch(void *buf)
+{
+ /* If md5 is not builtin for restore kernel, let it go. */
+ return false;
+}
+#endif
/**
* arch_hibernation_header_save - populate the architecture specific part
@@ -201,6 +277,9 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
rdr->jump_address_phys = __pa_symbol(&restore_registers);
rdr->cr3 = restore_cr3;
rdr->magic = RESTORE_MAGIC;
+
+ hibernation_e820_save(rdr->e820_digest);
+
return 0;
}
@@ -216,5 +295,16 @@ int arch_hibernation_header_restore(void *addr)
restore_jump_address = rdr->jump_address;
jump_address_phys = rdr->jump_address_phys;
restore_cr3 = rdr->cr3;
- return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
+
+ if (rdr->magic != RESTORE_MAGIC) {
+ pr_crit("Unrecognized hibernate image header format!\n");
+ return -EINVAL;
+ }
+
+ if (hibernation_e820_mismatch(rdr->e820_digest)) {
+ pr_crit("Hibernate inconsistent memory map detected!\n");
+ return -ENODEV;
+ }
+
+ return 0;
}
diff --git a/arch/x86/ras/mce_amd_inj.c b/arch/x86/ras/mce_amd_inj.c
index 1ac76479c266..8730c2882fff 100644
--- a/arch/x86/ras/mce_amd_inj.c
+++ b/arch/x86/ras/mce_amd_inj.c
@@ -275,6 +275,8 @@ static void do_inject(void)
unsigned int cpu = i_mce.extcpu;
u8 b = i_mce.bank;
+ rdtscll(i_mce.tsc);
+
if (i_mce.misc)
i_mce.status |= MCI_STATUS_MISCV;
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 25012abc3409..4463fa72db94 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -69,7 +69,7 @@ $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
# ---------------------------------------------------------------------------
-KBUILD_CFLAGS := $(LINUXINCLUDE) $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
+KBUILD_CFLAGS := $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
-I$(srctree)/arch/x86/boot
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
GCOV_PROFILE := n
diff --git a/arch/x86/tools/insn_sanity.c b/arch/x86/tools/insn_sanity.c
index ba70ff232917..1972565ab106 100644
--- a/arch/x86/tools/insn_sanity.c
+++ b/arch/x86/tools/insn_sanity.c
@@ -269,7 +269,8 @@ int main(int argc, char **argv)
insns++;
}
- fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+ fprintf((errors) ? stderr : stdout,
+ "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
prog,
(errors) ? "Failure" : "Success",
insns,
diff --git a/arch/x86/tools/test_get_len.c b/arch/x86/tools/test_get_len.c
index 56f04db0c9c0..ecf31e0358c8 100644
--- a/arch/x86/tools/test_get_len.c
+++ b/arch/x86/tools/test_get_len.c
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Warning: decoded and checked %d"
" instructions with %d warnings\n", insns, warnings);
else
- fprintf(stderr, "Succeed: decoded and checked %d"
+ fprintf(stdout, "Success: decoded and checked %d"
" instructions\n", insns);
return 0;
}
diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h
index 233ee09c1ce8..c77db2288982 100644
--- a/arch/x86/um/asm/processor.h
+++ b/arch/x86/um/asm/processor.h
@@ -26,7 +26,6 @@ static inline void rep_nop(void)
}
#define cpu_relax() rep_nop()
-#define cpu_relax_lowlatency() cpu_relax()
#define task_pt_regs(t) (&(t)->thread.regs)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index bdd855685403..ced7027b3fbc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -980,17 +980,6 @@ static void xen_io_delay(void)
{
}
-static void xen_clts(void)
-{
- struct multicall_space mcs;
-
- mcs = xen_mc_entry(0);
-
- MULTI_fpu_taskswitch(mcs.mc, 0);
-
- xen_mc_issue(PARAVIRT_LAZY_CPU);
-}
-
static DEFINE_PER_CPU(unsigned long, xen_cr0_value);
static unsigned long xen_read_cr0(void)
@@ -1233,8 +1222,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.set_debugreg = xen_set_debugreg,
.get_debugreg = xen_get_debugreg,
- .clts = xen_clts,
-
.read_cr0 = xen_read_cr0,
.write_cr0 = xen_write_cr0,
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 3d6e0064cbfc..e8a9ea7d7a21 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -114,6 +114,7 @@ void xen_uninit_lock_cpu(int cpu)
per_cpu(irq_name, cpu) = NULL;
}
+PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
/*
* Our init of PV spinlocks is split in two init functions due to us
@@ -137,6 +138,7 @@ void __init xen_init_spinlocks(void)
pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
pv_lock_ops.wait = xen_qlock_wait;
pv_lock_ops.kick = xen_qlock_kick;
+ pv_lock_ops.vcpu_is_preempted = PV_CALLEE_SAVE(xen_vcpu_stolen);
}
/*
diff --git a/arch/xtensa/include/asm/mutex.h b/arch/xtensa/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/xtensa/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index b42d68bfe3cf..86ffcd68e496 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -206,7 +206,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1])
#define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
/* Special register access. */
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 81435d995e11..9fdbe1fe0473 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -101,4 +101,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/block/Kconfig b/block/Kconfig
index 1d4d624492fc..8bf114a3858a 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -5,6 +5,7 @@ menuconfig BLOCK
bool "Enable the block layer" if EXPERT
default y
select SBITMAP
+ select SRCU
help
Provide block layer support for the kernel.
@@ -89,6 +90,14 @@ config BLK_DEV_INTEGRITY
T10/SCSI Data Integrity Field or the T13/ATA External Path
Protection. If in doubt, say N.
+config BLK_DEV_ZONED
+ bool "Zoned block device support"
+ ---help---
+ Block layer zoned block device support. This option enables
+ support for ZAC/ZBC host-managed and host-aware zoned block devices.
+
+ Say yes here if you have a ZAC or ZBC storage device.
+
config BLK_DEV_THROTTLING
bool "Block layer bio throttling support"
depends on BLK_CGROUP=y
@@ -112,6 +121,32 @@ config BLK_CMDLINE_PARSER
See Documentation/block/cmdline-partition.txt for more information.
+config BLK_WBT
+ bool "Enable support for block device writeback throttling"
+ default n
+ ---help---
+ Enabling this option enables the block layer to throttle buffered
+ background writeback from the VM, making it more smooth and having
+ less impact on foreground operations. The throttling is done
+ dynamically on an algorithm loosely based on CoDel, factoring in
+ the realtime performance of the disk.
+
+config BLK_WBT_SQ
+ bool "Single queue writeback throttling"
+ default n
+ depends on BLK_WBT
+ ---help---
+ Enable writeback throttling by default on legacy single queue devices
+
+config BLK_WBT_MQ
+ bool "Multiqueue writeback throttling"
+ default y
+ depends on BLK_WBT
+ ---help---
+ Enable writeback throttling by default on multiqueue devices.
+ Multiqueue currently doesn't have support for IO scheduling,
+ enabling this option is recommended.
+
menu "Partition Types"
source "block/partitions/Kconfig"
diff --git a/block/Makefile b/block/Makefile
index 36acdd7545be..a827f988c4e6 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -5,7 +5,7 @@
obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-tag.o blk-sysfs.o \
blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
- blk-lib.o blk-mq.o blk-mq-tag.o \
+ blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \
blk-mq-sysfs.o blk-mq-cpumap.o ioctl.o \
genhd.o scsi_ioctl.o partition-generic.o ioprio.o \
badblocks.o partitions/
@@ -23,3 +23,5 @@ obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o
+obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o
+obj-$(CONFIG_BLK_WBT) += blk-wbt.o
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 63f72f00c72e..5384713d48bc 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -172,7 +172,7 @@ bool bio_integrity_enabled(struct bio *bio)
{
struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
- if (!bio_is_rw(bio))
+ if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
return false;
/* Already protected? */
diff --git a/block/bio.c b/block/bio.c
index db85c5753a76..2b375020fc49 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -270,11 +270,15 @@ static void bio_free(struct bio *bio)
}
}
-void bio_init(struct bio *bio)
+void bio_init(struct bio *bio, struct bio_vec *table,
+ unsigned short max_vecs)
{
memset(bio, 0, sizeof(*bio));
atomic_set(&bio->__bi_remaining, 1);
atomic_set(&bio->__bi_cnt, 1);
+
+ bio->bi_io_vec = table;
+ bio->bi_max_vecs = max_vecs;
}
EXPORT_SYMBOL(bio_init);
@@ -480,7 +484,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
return NULL;
bio = p + front_pad;
- bio_init(bio);
+ bio_init(bio, NULL, 0);
if (nr_iovecs > inline_vecs) {
unsigned long idx = 0;
@@ -670,6 +674,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
switch (bio_op(bio)) {
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
+ case REQ_OP_WRITE_ZEROES:
break;
case REQ_OP_WRITE_SAME:
bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
@@ -847,6 +852,55 @@ done:
}
EXPORT_SYMBOL(bio_add_page);
+/**
+ * bio_iov_iter_get_pages - pin user or kernel pages and add them to a bio
+ * @bio: bio to add pages to
+ * @iter: iov iterator describing the region to be mapped
+ *
+ * Pins as many pages from *iter and appends them to @bio's bvec array. The
+ * pages will have to be released using put_page() when done.
+ */
+int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
+{
+ unsigned short nr_pages = bio->bi_max_vecs - bio->bi_vcnt;
+ struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;
+ struct page **pages = (struct page **)bv;
+ size_t offset, diff;
+ ssize_t size;
+
+ size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset);
+ if (unlikely(size <= 0))
+ return size ? size : -EFAULT;
+ nr_pages = (size + offset + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ /*
+ * Deep magic below: We need to walk the pinned pages backwards
+ * because we are abusing the space allocated for the bio_vecs
+ * for the page array. Because the bio_vecs are larger than the
+ * page pointers by definition this will always work. But it also
+ * means we can't use bio_add_page, so any changes to it's semantics
+ * need to be reflected here as well.
+ */
+ bio->bi_iter.bi_size += size;
+ bio->bi_vcnt += nr_pages;
+
+ diff = (nr_pages * PAGE_SIZE - offset) - size;
+ while (nr_pages--) {
+ bv[nr_pages].bv_page = pages[nr_pages];
+ bv[nr_pages].bv_len = PAGE_SIZE;
+ bv[nr_pages].bv_offset = 0;
+ }
+
+ bv[0].bv_offset += offset;
+ bv[0].bv_len -= offset;
+ if (diff)
+ bv[bio->bi_vcnt - 1].bv_len -= diff;
+
+ iov_iter_advance(iter, size);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bio_iov_iter_get_pages);
+
struct submit_bio_ret {
struct completion event;
int error;
@@ -1786,15 +1840,7 @@ struct bio *bio_split(struct bio *bio, int sectors,
BUG_ON(sectors <= 0);
BUG_ON(sectors >= bio_sectors(bio));
- /*
- * Discards need a mutable bio_vec to accommodate the payload
- * required by the DSM TRIM and UNMAP commands.
- */
- if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
- split = bio_clone_bioset(bio, gfp, bs);
- else
- split = bio_clone_fast(bio, gfp, bs);
-
+ split = bio_clone_fast(bio, gfp, bs);
if (!split)
return NULL;
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index b08ccbb9393a..8ba0af780e88 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -185,7 +185,8 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
}
wb_congested = wb_congested_get_create(&q->backing_dev_info,
- blkcg->css.id, GFP_NOWAIT);
+ blkcg->css.id,
+ GFP_NOWAIT | __GFP_NOWARN);
if (!wb_congested) {
ret = -ENOMEM;
goto err_put_css;
@@ -193,7 +194,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
/* allocate */
if (!new_blkg) {
- new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT);
+ new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT | __GFP_NOWARN);
if (unlikely(!new_blkg)) {
ret = -ENOMEM;
goto err_put_congested;
@@ -1022,7 +1023,7 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
}
spin_lock_init(&blkcg->lock);
- INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT);
+ INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT | __GFP_NOWARN);
INIT_HLIST_HEAD(&blkcg->blkg_list);
#ifdef CONFIG_CGROUP_WRITEBACK
INIT_LIST_HEAD(&blkcg->cgwb_list);
@@ -1240,7 +1241,7 @@ pd_prealloc:
if (blkg->pd[pol->plid])
continue;
- pd = pol->pd_alloc_fn(GFP_NOWAIT, q->node);
+ pd = pol->pd_alloc_fn(GFP_NOWAIT | __GFP_NOWARN, q->node);
if (!pd)
swap(pd, pd_prealloc);
if (!pd) {
diff --git a/block/blk-core.c b/block/blk-core.c
index 14d7c0740dc0..bd642a43b98b 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -39,6 +39,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-wbt.h"
EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
@@ -145,13 +146,13 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
if (error)
bio->bi_error = error;
- if (unlikely(rq->cmd_flags & REQ_QUIET))
+ if (unlikely(rq->rq_flags & RQF_QUIET))
bio_set_flag(bio, BIO_QUIET);
bio_advance(bio, nbytes);
/* don't actually finish bio if it's part of flush sequence */
- if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
+ if (bio->bi_iter.bi_size == 0 && !(rq->rq_flags & RQF_FLUSH_SEQ))
bio_endio(bio);
}
@@ -882,6 +883,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
fail:
blk_free_flush_queue(q->fq);
+ wbt_exit(q);
return NULL;
}
EXPORT_SYMBOL(blk_init_allocated_queue);
@@ -899,7 +901,7 @@ EXPORT_SYMBOL(blk_get_queue);
static inline void blk_free_request(struct request_list *rl, struct request *rq)
{
- if (rq->cmd_flags & REQ_ELVPRIV) {
+ if (rq->rq_flags & RQF_ELVPRIV) {
elv_put_request(rl->q, rq);
if (rq->elv.icq)
put_io_context(rq->elv.icq->ioc);
@@ -961,14 +963,14 @@ static void __freed_request(struct request_list *rl, int sync)
* A request has just been released. Account for it, update the full and
* congestion status, wake up any waiters. Called under q->queue_lock.
*/
-static void freed_request(struct request_list *rl, int op, unsigned int flags)
+static void freed_request(struct request_list *rl, bool sync,
+ req_flags_t rq_flags)
{
struct request_queue *q = rl->q;
- int sync = rw_is_sync(op, flags);
q->nr_rqs[sync]--;
rl->count[sync]--;
- if (flags & REQ_ELVPRIV)
+ if (rq_flags & RQF_ELVPRIV)
q->nr_rqs_elvpriv--;
__freed_request(rl, sync);
@@ -1056,8 +1058,7 @@ static struct io_context *rq_ioc(struct bio *bio)
/**
* __get_request - get a free request
* @rl: request list to allocate from
- * @op: REQ_OP_READ/REQ_OP_WRITE
- * @op_flags: rq_flag_bits
+ * @op: operation and flags
* @bio: bio to allocate request for (can be %NULL)
* @gfp_mask: allocation mask
*
@@ -1068,22 +1069,22 @@ static struct io_context *rq_ioc(struct bio *bio)
* Returns ERR_PTR on failure, with @q->queue_lock held.
* Returns request pointer on success, with @q->queue_lock *not held*.
*/
-static struct request *__get_request(struct request_list *rl, int op,
- int op_flags, struct bio *bio,
- gfp_t gfp_mask)
+static struct request *__get_request(struct request_list *rl, unsigned int op,
+ struct bio *bio, gfp_t gfp_mask)
{
struct request_queue *q = rl->q;
struct request *rq;
struct elevator_type *et = q->elevator->type;
struct io_context *ioc = rq_ioc(bio);
struct io_cq *icq = NULL;
- const bool is_sync = rw_is_sync(op, op_flags) != 0;
+ const bool is_sync = op_is_sync(op);
int may_queue;
+ req_flags_t rq_flags = RQF_ALLOCED;
if (unlikely(blk_queue_dying(q)))
return ERR_PTR(-ENODEV);
- may_queue = elv_may_queue(q, op, op_flags);
+ may_queue = elv_may_queue(q, op);
if (may_queue == ELV_MQUEUE_NO)
goto rq_starved;
@@ -1127,7 +1128,7 @@ static struct request *__get_request(struct request_list *rl, int op,
/*
* Decide whether the new request will be managed by elevator. If
- * so, mark @op_flags and increment elvpriv. Non-zero elvpriv will
+ * so, mark @rq_flags and increment elvpriv. Non-zero elvpriv will
* prevent the current elevator from being destroyed until the new
* request is freed. This guarantees icq's won't be destroyed and
* makes creating new ones safe.
@@ -1136,14 +1137,14 @@ static struct request *__get_request(struct request_list *rl, int op,
* it will be created after releasing queue_lock.
*/
if (blk_rq_should_init_elevator(bio) && !blk_queue_bypass(q)) {
- op_flags |= REQ_ELVPRIV;
+ rq_flags |= RQF_ELVPRIV;
q->nr_rqs_elvpriv++;
if (et->icq_cache && ioc)
icq = ioc_lookup_icq(ioc, q);
}
if (blk_queue_io_stat(q))
- op_flags |= REQ_IO_STAT;
+ rq_flags |= RQF_IO_STAT;
spin_unlock_irq(q->queue_lock);
/* allocate and init request */
@@ -1153,10 +1154,11 @@ static struct request *__get_request(struct request_list *rl, int op,
blk_rq_init(q, rq);
blk_rq_set_rl(rq, rl);
- req_set_op_attrs(rq, op, op_flags | REQ_ALLOCED);
+ rq->cmd_flags = op;
+ rq->rq_flags = rq_flags;
/* init elvpriv */
- if (op_flags & REQ_ELVPRIV) {
+ if (rq_flags & RQF_ELVPRIV) {
if (unlikely(et->icq_cache && !icq)) {
if (ioc)
icq = ioc_create_icq(ioc, q, gfp_mask);
@@ -1195,7 +1197,7 @@ fail_elvpriv:
printk_ratelimited(KERN_WARNING "%s: dev %s: request aux data allocation failed, iosched may be disturbed\n",
__func__, dev_name(q->backing_dev_info.dev));
- rq->cmd_flags &= ~REQ_ELVPRIV;
+ rq->rq_flags &= ~RQF_ELVPRIV;
rq->elv.icq = NULL;
spin_lock_irq(q->queue_lock);
@@ -1212,7 +1214,7 @@ fail_alloc:
* queue, but this is pretty rare.
*/
spin_lock_irq(q->queue_lock);
- freed_request(rl, op, op_flags);
+ freed_request(rl, is_sync, rq_flags);
/*
* in the very unlikely event that allocation failed and no
@@ -1230,8 +1232,7 @@ rq_starved:
/**
* get_request - get a free request
* @q: request_queue to allocate request from
- * @op: REQ_OP_READ/REQ_OP_WRITE
- * @op_flags: rq_flag_bits
+ * @op: operation and flags
* @bio: bio to allocate request for (can be %NULL)
* @gfp_mask: allocation mask
*
@@ -1242,18 +1243,17 @@ rq_starved:
* Returns ERR_PTR on failure, with @q->queue_lock held.
* Returns request pointer on success, with @q->queue_lock *not held*.
*/
-static struct request *get_request(struct request_queue *q, int op,
- int op_flags, struct bio *bio,
- gfp_t gfp_mask)
+static struct request *get_request(struct request_queue *q, unsigned int op,
+ struct bio *bio, gfp_t gfp_mask)
{
- const bool is_sync = rw_is_sync(op, op_flags) != 0;
+ const bool is_sync = op_is_sync(op);
DEFINE_WAIT(wait);
struct request_list *rl;
struct request *rq;
rl = blk_get_rl(q, bio); /* transferred to @rq on success */
retry:
- rq = __get_request(rl, op, op_flags, bio, gfp_mask);
+ rq = __get_request(rl, op, bio, gfp_mask);
if (!IS_ERR(rq))
return rq;
@@ -1295,7 +1295,7 @@ static struct request *blk_old_get_request(struct request_queue *q, int rw,
create_io_context(gfp_mask, q->node);
spin_lock_irq(q->queue_lock);
- rq = get_request(q, rw, 0, NULL, gfp_mask);
+ rq = get_request(q, rw, NULL, gfp_mask);
if (IS_ERR(rq)) {
spin_unlock_irq(q->queue_lock);
return rq;
@@ -1346,8 +1346,9 @@ void blk_requeue_request(struct request_queue *q, struct request *rq)
blk_delete_timer(rq);
blk_clear_rq_complete(rq);
trace_block_rq_requeue(q, rq);
+ wbt_requeue(q->rq_wb, &rq->issue_stat);
- if (rq->cmd_flags & REQ_QUEUED)
+ if (rq->rq_flags & RQF_QUEUED)
blk_queue_end_tag(q, rq);
BUG_ON(blk_queued_rq(rq));
@@ -1409,7 +1410,7 @@ EXPORT_SYMBOL_GPL(part_round_stats);
#ifdef CONFIG_PM
static void blk_pm_put_request(struct request *rq)
{
- if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending)
+ if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending)
pm_runtime_mark_last_busy(rq->q->dev);
}
#else
@@ -1421,6 +1422,8 @@ static inline void blk_pm_put_request(struct request *rq) {}
*/
void __blk_put_request(struct request_queue *q, struct request *req)
{
+ req_flags_t rq_flags = req->rq_flags;
+
if (unlikely(!q))
return;
@@ -1436,20 +1439,21 @@ void __blk_put_request(struct request_queue *q, struct request *req)
/* this is a bio leak */
WARN_ON(req->bio != NULL);
+ wbt_done(q->rq_wb, &req->issue_stat);
+
/*
* Request may not have originated from ll_rw_blk. if not,
* it didn't come out of our reserved rq pools
*/
- if (req->cmd_flags & REQ_ALLOCED) {
- unsigned int flags = req->cmd_flags;
- int op = req_op(req);
+ if (rq_flags & RQF_ALLOCED) {
struct request_list *rl = blk_rq_rl(req);
+ bool sync = op_is_sync(req->cmd_flags);
BUG_ON(!list_empty(&req->queuelist));
BUG_ON(ELV_ON_HASH(req));
blk_free_request(rl, req);
- freed_request(rl, op, flags);
+ freed_request(rl, sync, rq_flags);
blk_put_rl(rl);
}
}
@@ -1471,38 +1475,6 @@ void blk_put_request(struct request *req)
}
EXPORT_SYMBOL(blk_put_request);
-/**
- * blk_add_request_payload - add a payload to a request
- * @rq: request to update
- * @page: page backing the payload
- * @offset: offset in page
- * @len: length of the payload.
- *
- * This allows to later add a payload to an already submitted request by
- * a block driver. The driver needs to take care of freeing the payload
- * itself.
- *
- * Note that this is a quite horrible hack and nothing but handling of
- * discard requests should ever use it.
- */
-void blk_add_request_payload(struct request *rq, struct page *page,
- int offset, unsigned int len)
-{
- struct bio *bio = rq->bio;
-
- bio->bi_io_vec->bv_page = page;
- bio->bi_io_vec->bv_offset = offset;
- bio->bi_io_vec->bv_len = len;
-
- bio->bi_iter.bi_size = len;
- bio->bi_vcnt = 1;
- bio->bi_phys_segments = 1;
-
- rq->__data_len = rq->resid_len = len;
- rq->nr_phys_segments = 1;
-}
-EXPORT_SYMBOL_GPL(blk_add_request_payload);
-
bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
struct bio *bio)
{
@@ -1649,8 +1621,6 @@ out:
void init_request_from_bio(struct request *req, struct bio *bio)
{
req->cmd_type = REQ_TYPE_FS;
-
- req->cmd_flags |= bio->bi_opf & REQ_COMMON_MASK;
if (bio->bi_opf & REQ_RAHEAD)
req->cmd_flags |= REQ_FAILFAST_MASK;
@@ -1662,11 +1632,11 @@ void init_request_from_bio(struct request *req, struct bio *bio)
static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
{
- const bool sync = !!(bio->bi_opf & REQ_SYNC);
struct blk_plug *plug;
- int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT;
+ int el_ret, where = ELEVATOR_INSERT_SORT;
struct request *req;
unsigned int request_count = 0;
+ unsigned int wb_acct;
/*
* low level driver can indicate that it wants pages above a
@@ -1719,30 +1689,22 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
}
get_rq:
- /*
- * This sync check and mask will be re-done in init_request_from_bio(),
- * but we need to set it earlier to expose the sync flag to the
- * rq allocator and io schedulers.
- */
- if (sync)
- rw_flags |= REQ_SYNC;
-
- /*
- * Add in META/PRIO flags, if set, before we get to the IO scheduler
- */
- rw_flags |= (bio->bi_opf & (REQ_META | REQ_PRIO));
+ wb_acct = wbt_wait(q->rq_wb, bio, q->queue_lock);
/*
* Grab a free request. This is might sleep but can not fail.
* Returns with the queue unlocked.
*/
- req = get_request(q, bio_data_dir(bio), rw_flags, bio, GFP_NOIO);
+ req = get_request(q, bio->bi_opf, bio, GFP_NOIO);
if (IS_ERR(req)) {
+ __wbt_done(q->rq_wb, wb_acct);
bio->bi_error = PTR_ERR(req);
bio_endio(bio);
goto out_unlock;
}
+ wbt_track(&req->issue_stat, wb_acct);
+
/*
* After dropping the lock and possibly sleeping here, our request
* may now be mergeable after it had proven unmergeable (above).
@@ -1759,11 +1721,16 @@ get_rq:
/*
* If this is the first request added after a plug, fire
* of a plug trace.
+ *
+ * @request_count may become stale because of schedule
+ * out, so check plug list again.
*/
- if (!request_count)
+ if (!request_count || list_empty(&plug->list))
trace_block_plug(q);
else {
- if (request_count >= BLK_MAX_REQUEST_COUNT) {
+ struct request *last = list_entry_rq(plug->list.prev);
+ if (request_count >= BLK_MAX_REQUEST_COUNT ||
+ blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE) {
blk_flush_plug_list(plug, false);
trace_block_plug(q);
}
@@ -1788,7 +1755,12 @@ static inline void blk_partition_remap(struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
- if (bio_sectors(bio) && bdev != bdev->bd_contains) {
+ /*
+ * Zone reset does not include bi_size so bio_sectors() is always 0.
+ * Include a test for the reset op code and perform the remap if needed.
+ */
+ if (bdev != bdev->bd_contains &&
+ (bio_sectors(bio) || bio_op(bio) == REQ_OP_ZONE_RESET)) {
struct hd_struct *p = bdev->bd_part;
bio->bi_iter.bi_sector += p->start_sect;
@@ -1942,6 +1914,15 @@ generic_make_request_checks(struct bio *bio)
if (!bdev_write_same(bio->bi_bdev))
goto not_supported;
break;
+ case REQ_OP_ZONE_REPORT:
+ case REQ_OP_ZONE_RESET:
+ if (!bdev_is_zoned(bio->bi_bdev))
+ goto not_supported;
+ break;
+ case REQ_OP_WRITE_ZEROES:
+ if (!bdev_write_zeroes_sectors(bio->bi_bdev))
+ goto not_supported;
+ break;
default:
break;
}
@@ -2210,7 +2191,7 @@ unsigned int blk_rq_err_bytes(const struct request *rq)
unsigned int bytes = 0;
struct bio *bio;
- if (!(rq->cmd_flags & REQ_MIXED_MERGE))
+ if (!(rq->rq_flags & RQF_MIXED_MERGE))
return blk_rq_bytes(rq);
/*
@@ -2253,7 +2234,7 @@ void blk_account_io_done(struct request *req)
* normal IO on queueing nor completion. Accounting the
* containing request is enough.
*/
- if (blk_do_io_stat(req) && !(req->cmd_flags & REQ_FLUSH_SEQ)) {
+ if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
unsigned long duration = jiffies - req->start_time;
const int rw = rq_data_dir(req);
struct hd_struct *part;
@@ -2281,7 +2262,7 @@ static struct request *blk_pm_peek_request(struct request_queue *q,
struct request *rq)
{
if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
- (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
+ (q->rpm_status != RPM_ACTIVE && !(rq->rq_flags & RQF_PM))))
return NULL;
else
return rq;
@@ -2357,13 +2338,13 @@ struct request *blk_peek_request(struct request_queue *q)
if (!rq)
break;
- if (!(rq->cmd_flags & REQ_STARTED)) {
+ if (!(rq->rq_flags & RQF_STARTED)) {
/*
* This is the first time the device driver
* sees this request (possibly after
* requeueing). Notify IO scheduler.
*/
- if (rq->cmd_flags & REQ_SORTED)
+ if (rq->rq_flags & RQF_SORTED)
elv_activate_rq(q, rq);
/*
@@ -2371,7 +2352,7 @@ struct request *blk_peek_request(struct request_queue *q)
* it, a request that has been delayed should
* not be passed by new incoming requests
*/
- rq->cmd_flags |= REQ_STARTED;
+ rq->rq_flags |= RQF_STARTED;
trace_block_rq_issue(q, rq);
}
@@ -2380,7 +2361,7 @@ struct request *blk_peek_request(struct request_queue *q)
q->boundary_rq = NULL;
}
- if (rq->cmd_flags & REQ_DONTPREP)
+ if (rq->rq_flags & RQF_DONTPREP)
break;
if (q->dma_drain_size && blk_rq_bytes(rq)) {
@@ -2403,11 +2384,11 @@ struct request *blk_peek_request(struct request_queue *q)
/*
* the request may have been (partially) prepped.
* we need to keep this request in the front to
- * avoid resource deadlock. REQ_STARTED will
+ * avoid resource deadlock. RQF_STARTED will
* prevent other fs requests from passing this one.
*/
if (q->dma_drain_size && blk_rq_bytes(rq) &&
- !(rq->cmd_flags & REQ_DONTPREP)) {
+ !(rq->rq_flags & RQF_DONTPREP)) {
/*
* remove the space for the drain we added
* so that we don't add it again
@@ -2420,7 +2401,7 @@ struct request *blk_peek_request(struct request_queue *q)
} else if (ret == BLKPREP_KILL || ret == BLKPREP_INVALID) {
int err = (ret == BLKPREP_INVALID) ? -EREMOTEIO : -EIO;
- rq->cmd_flags |= REQ_QUIET;
+ rq->rq_flags |= RQF_QUIET;
/*
* Mark this request as started so we don't trigger
* any debug logic in the end I/O path.
@@ -2475,6 +2456,12 @@ void blk_start_request(struct request *req)
{
blk_dequeue_request(req);
+ if (test_bit(QUEUE_FLAG_STATS, &req->q->queue_flags)) {
+ blk_stat_set_issue_time(&req->issue_stat);
+ req->rq_flags |= RQF_STATS;
+ wbt_issue(req->q->rq_wb, &req->issue_stat);
+ }
+
/*
* We are now handing the request to the hardware, initialize
* resid_len to full count and add the timeout handler.
@@ -2557,7 +2544,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
req->errors = 0;
if (error && req->cmd_type == REQ_TYPE_FS &&
- !(req->cmd_flags & REQ_QUIET)) {
+ !(req->rq_flags & RQF_QUIET)) {
char *error_type;
switch (error) {
@@ -2623,6 +2610,8 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
return false;
}
+ WARN_ON_ONCE(req->rq_flags & RQF_SPECIAL_PAYLOAD);
+
req->__data_len -= total_bytes;
/* update sector only for requests with clear definition of sector */
@@ -2630,7 +2619,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
req->__sector += total_bytes >> 9;
/* mixed attributes always follow the first bio */
- if (req->cmd_flags & REQ_MIXED_MERGE) {
+ if (req->rq_flags & RQF_MIXED_MERGE) {
req->cmd_flags &= ~REQ_FAILFAST_MASK;
req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK;
}
@@ -2683,7 +2672,7 @@ void blk_unprep_request(struct request *req)
{
struct request_queue *q = req->q;
- req->cmd_flags &= ~REQ_DONTPREP;
+ req->rq_flags &= ~RQF_DONTPREP;
if (q->unprep_rq_fn)
q->unprep_rq_fn(q, req);
}
@@ -2694,8 +2683,13 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
*/
void blk_finish_request(struct request *req, int error)
{
- if (req->cmd_flags & REQ_QUEUED)
- blk_queue_end_tag(req->q, req);
+ struct request_queue *q = req->q;
+
+ if (req->rq_flags & RQF_STATS)
+ blk_stat_add(&q->rq_stats[rq_data_dir(req)], req);
+
+ if (req->rq_flags & RQF_QUEUED)
+ blk_queue_end_tag(q, req);
BUG_ON(blk_queued_rq(req));
@@ -2704,18 +2698,19 @@ void blk_finish_request(struct request *req, int error)
blk_delete_timer(req);
- if (req->cmd_flags & REQ_DONTPREP)
+ if (req->rq_flags & RQF_DONTPREP)
blk_unprep_request(req);
blk_account_io_done(req);
- if (req->end_io)
+ if (req->end_io) {
+ wbt_done(req->q->rq_wb, &req->issue_stat);
req->end_io(req, error);
- else {
+ } else {
if (blk_bidi_rq(req))
__blk_put_request(req->next_rq->q, req->next_rq);
- __blk_put_request(req->q, req);
+ __blk_put_request(q, req);
}
}
EXPORT_SYMBOL(blk_finish_request);
@@ -2939,8 +2934,6 @@ EXPORT_SYMBOL_GPL(__blk_end_request_err);
void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
struct bio *bio)
{
- req_set_op(rq, bio_op(bio));
-
if (bio_has_data(bio))
rq->nr_phys_segments = bio_phys_segments(q, bio);
@@ -3024,8 +3017,7 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
static void __blk_rq_prep_clone(struct request *dst, struct request *src)
{
dst->cpu = src->cpu;
- req_set_op_attrs(dst, req_op(src),
- (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE);
+ dst->cmd_flags = src->cmd_flags | REQ_NOMERGE;
dst->cmd_type = src->cmd_type;
dst->__sector = blk_rq_pos(src);
dst->__data_len = blk_rq_bytes(src);
@@ -3303,52 +3295,6 @@ void blk_finish_plug(struct blk_plug *plug)
}
EXPORT_SYMBOL(blk_finish_plug);
-bool blk_poll(struct request_queue *q, blk_qc_t cookie)
-{
- struct blk_plug *plug;
- long state;
- unsigned int queue_num;
- struct blk_mq_hw_ctx *hctx;
-
- if (!q->mq_ops || !q->mq_ops->poll || !blk_qc_t_valid(cookie) ||
- !test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
- return false;
-
- queue_num = blk_qc_t_to_queue_num(cookie);
- hctx = q->queue_hw_ctx[queue_num];
- hctx->poll_considered++;
-
- plug = current->plug;
- if (plug)
- blk_flush_plug_list(plug, false);
-
- state = current->state;
- while (!need_resched()) {
- int ret;
-
- hctx->poll_invoked++;
-
- ret = q->mq_ops->poll(hctx, blk_qc_t_to_tag(cookie));
- if (ret > 0) {
- hctx->poll_success++;
- set_current_state(TASK_RUNNING);
- return true;
- }
-
- if (signal_pending_state(state, current))
- set_current_state(TASK_RUNNING);
-
- if (current->state == TASK_RUNNING)
- return true;
- if (ret < 0)
- break;
- cpu_relax();
- }
-
- return false;
-}
-EXPORT_SYMBOL_GPL(blk_poll);
-
#ifdef CONFIG_PM
/**
* blk_pm_runtime_init - Block layer runtime PM initialization routine
@@ -3530,8 +3476,11 @@ EXPORT_SYMBOL(blk_set_runtime_active);
int __init blk_dev_init(void)
{
- BUILD_BUG_ON(__REQ_NR_BITS > 8 *
+ BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS));
+ BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
FIELD_SIZEOF(struct request, cmd_flags));
+ BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
+ FIELD_SIZEOF(struct bio, bi_opf));
/* used for unplugging and affects IO latency/throughput - HIGHPRI */
kblockd_workqueue = alloc_workqueue("kblockd",
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 7ea04325d02f..3ecb00a6cf45 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -72,7 +72,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
spin_lock_irq(q->queue_lock);
if (unlikely(blk_queue_dying(q))) {
- rq->cmd_flags |= REQ_QUIET;
+ rq->rq_flags |= RQF_QUIET;
rq->errors = -ENXIO;
__blk_end_request_all(rq, rq->errors);
spin_unlock_irq(q->queue_lock);
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 3c882cbc7541..20b7c7a02f1c 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -56,7 +56,7 @@
* Once while executing DATA and again after the whole sequence is
* complete. The first completion updates the contained bio but doesn't
* finish it so that the bio submitter is notified only after the whole
- * sequence is complete. This is implemented by testing REQ_FLUSH_SEQ in
+ * sequence is complete. This is implemented by testing RQF_FLUSH_SEQ in
* req_bio_endio().
*
* The above peculiarity requires that each FLUSH/FUA request has only one
@@ -127,17 +127,14 @@ static void blk_flush_restore_request(struct request *rq)
rq->bio = rq->biotail;
/* make @rq a normal request */
- rq->cmd_flags &= ~REQ_FLUSH_SEQ;
+ rq->rq_flags &= ~RQF_FLUSH_SEQ;
rq->end_io = rq->flush.saved_end_io;
}
static bool blk_flush_queue_rq(struct request *rq, bool add_front)
{
if (rq->q->mq_ops) {
- struct request_queue *q = rq->q;
-
- blk_mq_add_to_requeue_list(rq, add_front);
- blk_mq_kick_requeue_list(q);
+ blk_mq_add_to_requeue_list(rq, add_front, true);
return false;
} else {
if (add_front)
@@ -330,7 +327,8 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
}
flush_rq->cmd_type = REQ_TYPE_FS;
- req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH | REQ_FLUSH_SEQ);
+ flush_rq->cmd_flags = REQ_OP_FLUSH | REQ_PREFLUSH;
+ flush_rq->rq_flags |= RQF_FLUSH_SEQ;
flush_rq->rq_disk = first_rq->rq_disk;
flush_rq->end_io = flush_end_io;
@@ -368,7 +366,7 @@ static void flush_data_end_io(struct request *rq, int error)
elv_completed_request(q, rq);
/* for avoiding double accounting */
- rq->cmd_flags &= ~REQ_STARTED;
+ rq->rq_flags &= ~RQF_STARTED;
/*
* After populating an empty queue, kick it to avoid stall. Read
@@ -426,6 +424,13 @@ void blk_insert_flush(struct request *rq)
rq->cmd_flags &= ~REQ_FUA;
/*
+ * REQ_PREFLUSH|REQ_FUA implies REQ_SYNC, so if we clear any
+ * of those flags, we have to set REQ_SYNC to avoid skewing
+ * the request accounting.
+ */
+ rq->cmd_flags |= REQ_SYNC;
+
+ /*
* An empty flush handed down from a stacking driver may
* translate into nothing if the underlying device does not
* advertise a write-back cache. In this case, simply
@@ -449,7 +454,7 @@ void blk_insert_flush(struct request *rq)
if ((policy & REQ_FSEQ_DATA) &&
!(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
if (q->mq_ops) {
- blk_mq_insert_request(rq, false, false, true);
+ blk_mq_insert_request(rq, false, true, false);
} else
list_add_tail(&rq->queuelist, &q->queue_head);
return;
@@ -461,7 +466,7 @@ void blk_insert_flush(struct request *rq)
*/
memset(&rq->flush, 0, sizeof(rq->flush));
INIT_LIST_HEAD(&rq->flush.list);
- rq->cmd_flags |= REQ_FLUSH_SEQ;
+ rq->rq_flags |= RQF_FLUSH_SEQ;
rq->flush.saved_end_io = rq->end_io; /* Usually NULL */
if (q->mq_ops) {
rq->end_io = mq_flush_data_end_io;
@@ -513,7 +518,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
bio = bio_alloc(gfp_mask, 0);
bio->bi_bdev = bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
ret = submit_bio_wait(bio);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 46fe9248410d..ed89c8f4b2a0 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -29,7 +29,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
struct request_queue *q = bdev_get_queue(bdev);
struct bio *bio = *biop;
unsigned int granularity;
- enum req_op op;
+ unsigned int op;
int alignment;
sector_t bs_mask;
@@ -80,7 +80,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
req_sects = end_sect - sector;
}
- bio = next_bio(bio, 1, gfp_mask);
+ bio = next_bio(bio, 0, gfp_mask);
bio->bi_iter.bi_sector = sector;
bio->bi_bdev = bdev;
bio_set_op_attrs(bio, op, 0);
@@ -137,24 +137,24 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
EXPORT_SYMBOL(blkdev_issue_discard);
/**
- * blkdev_issue_write_same - queue a write same operation
+ * __blkdev_issue_write_same - generate number of bios with same page
* @bdev: target blockdev
* @sector: start sector
* @nr_sects: number of sectors to write
* @gfp_mask: memory allocation flags (for bio_alloc)
* @page: page containing data to write
+ * @biop: pointer to anchor bio
*
* Description:
- * Issue a write same request for the sectors in question.
+ * Generate and issue number of bios(REQ_OP_WRITE_SAME) with same page.
*/
-int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask,
- struct page *page)
+static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask, struct page *page,
+ struct bio **biop)
{
struct request_queue *q = bdev_get_queue(bdev);
unsigned int max_write_same_sectors;
- struct bio *bio = NULL;
- int ret = 0;
+ struct bio *bio = *biop;
sector_t bs_mask;
if (!q)
@@ -164,6 +164,9 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
if ((sector | nr_sects) & bs_mask)
return -EINVAL;
+ if (!bdev_write_same(bdev))
+ return -EOPNOTSUPP;
+
/* Ensure that max_write_same_sectors doesn't overflow bi_size */
max_write_same_sectors = UINT_MAX >> 9;
@@ -185,32 +188,112 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
bio->bi_iter.bi_size = nr_sects << 9;
nr_sects = 0;
}
+ cond_resched();
}
- if (bio) {
+ *biop = bio;
+ return 0;
+}
+
+/**
+ * blkdev_issue_write_same - queue a write same operation
+ * @bdev: target blockdev
+ * @sector: start sector
+ * @nr_sects: number of sectors to write
+ * @gfp_mask: memory allocation flags (for bio_alloc)
+ * @page: page containing data
+ *
+ * Description:
+ * Issue a write same request for the sectors in question.
+ */
+int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask,
+ struct page *page)
+{
+ struct bio *bio = NULL;
+ struct blk_plug plug;
+ int ret;
+
+ blk_start_plug(&plug);
+ ret = __blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask, page,
+ &bio);
+ if (ret == 0 && bio) {
ret = submit_bio_wait(bio);
bio_put(bio);
}
+ blk_finish_plug(&plug);
return ret;
}
EXPORT_SYMBOL(blkdev_issue_write_same);
/**
- * blkdev_issue_zeroout - generate number of zero filed write bios
+ * __blkdev_issue_write_zeroes - generate number of bios with WRITE ZEROES
* @bdev: blockdev to issue
* @sector: start sector
* @nr_sects: number of sectors to write
* @gfp_mask: memory allocation flags (for bio_alloc)
+ * @biop: pointer to anchor bio
*
* Description:
- * Generate and issue number of bios with zerofiled pages.
+ * Generate and issue number of bios(REQ_OP_WRITE_ZEROES) with zerofiled pages.
*/
+static int __blkdev_issue_write_zeroes(struct block_device *bdev,
+ sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
+ struct bio **biop)
+{
+ struct bio *bio = *biop;
+ unsigned int max_write_zeroes_sectors;
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (!q)
+ return -ENXIO;
+
+ /* Ensure that max_write_zeroes_sectors doesn't overflow bi_size */
+ max_write_zeroes_sectors = bdev_write_zeroes_sectors(bdev);
+
+ if (max_write_zeroes_sectors == 0)
+ return -EOPNOTSUPP;
+
+ while (nr_sects) {
+ bio = next_bio(bio, 0, gfp_mask);
+ bio->bi_iter.bi_sector = sector;
+ bio->bi_bdev = bdev;
+ bio_set_op_attrs(bio, REQ_OP_WRITE_ZEROES, 0);
-static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask)
+ if (nr_sects > max_write_zeroes_sectors) {
+ bio->bi_iter.bi_size = max_write_zeroes_sectors << 9;
+ nr_sects -= max_write_zeroes_sectors;
+ sector += max_write_zeroes_sectors;
+ } else {
+ bio->bi_iter.bi_size = nr_sects << 9;
+ nr_sects = 0;
+ }
+ cond_resched();
+ }
+
+ *biop = bio;
+ return 0;
+}
+
+/**
+ * __blkdev_issue_zeroout - generate number of zero filed write bios
+ * @bdev: blockdev to issue
+ * @sector: start sector
+ * @nr_sects: number of sectors to write
+ * @gfp_mask: memory allocation flags (for bio_alloc)
+ * @biop: pointer to anchor bio
+ * @discard: discard flag
+ *
+ * Description:
+ * Generate and issue number of bios with zerofiled pages.
+ */
+int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
+ bool discard)
{
int ret;
- struct bio *bio = NULL;
+ int bi_size = 0;
+ struct bio *bio = *biop;
unsigned int sz;
sector_t bs_mask;
@@ -218,6 +301,24 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
if ((sector | nr_sects) & bs_mask)
return -EINVAL;
+ if (discard) {
+ ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
+ BLKDEV_DISCARD_ZERO, biop);
+ if (ret == 0 || (ret && ret != -EOPNOTSUPP))
+ goto out;
+ }
+
+ ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
+ biop);
+ if (ret == 0 || (ret && ret != -EOPNOTSUPP))
+ goto out;
+
+ ret = __blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
+ ZERO_PAGE(0), biop);
+ if (ret == 0 || (ret && ret != -EOPNOTSUPP))
+ goto out;
+
+ ret = 0;
while (nr_sects != 0) {
bio = next_bio(bio, min(nr_sects, (sector_t)BIO_MAX_PAGES),
gfp_mask);
@@ -227,21 +328,20 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
while (nr_sects != 0) {
sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
- ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
- nr_sects -= ret >> 9;
- sector += ret >> 9;
- if (ret < (sz << 9))
+ bi_size = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
+ nr_sects -= bi_size >> 9;
+ sector += bi_size >> 9;
+ if (bi_size < (sz << 9))
break;
}
+ cond_resched();
}
- if (bio) {
- ret = submit_bio_wait(bio);
- bio_put(bio);
- return ret;
- }
- return 0;
+ *biop = bio;
+out:
+ return ret;
}
+EXPORT_SYMBOL(__blkdev_issue_zeroout);
/**
* blkdev_issue_zeroout - zero-fill a block range
@@ -258,26 +358,27 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
* the discard request fail, if the discard flag is not set, or if
* discard_zeroes_data is not supported, this function will resort to
* zeroing the blocks manually, thus provisioning (allocating,
- * anchoring) them. If the block device supports the WRITE SAME command
- * blkdev_issue_zeroout() will use it to optimize the process of
+ * anchoring) them. If the block device supports WRITE ZEROES or WRITE SAME
+ * command(s), blkdev_issue_zeroout() will use it to optimize the process of
* clearing the block range. Otherwise the zeroing will be performed
* using regular WRITE calls.
*/
-
int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, bool discard)
{
- if (discard) {
- if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
- BLKDEV_DISCARD_ZERO))
- return 0;
- }
+ int ret;
+ struct bio *bio = NULL;
+ struct blk_plug plug;
- if (bdev_write_same(bdev) &&
- blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
- ZERO_PAGE(0)) == 0)
- return 0;
+ blk_start_plug(&plug);
+ ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
+ &bio, discard);
+ if (ret == 0 && bio) {
+ ret = submit_bio_wait(bio);
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
- return __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask);
+ return ret;
}
EXPORT_SYMBOL(blkdev_issue_zeroout);
diff --git a/block/blk-map.c b/block/blk-map.c
index 27fd8d92892d..0acb6640ead7 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -16,6 +16,8 @@
int blk_rq_append_bio(struct request *rq, struct bio *bio)
{
if (!rq->bio) {
+ rq->cmd_flags &= REQ_OP_MASK;
+ rq->cmd_flags |= (bio->bi_opf & REQ_OP_MASK);
blk_rq_bio_prep(rq->q, rq, bio);
} else {
if (!ll_back_merge_fn(rq->q, rq, bio))
@@ -138,7 +140,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
} while (iov_iter_count(&i));
if (!bio_flagged(bio, BIO_USER_MAPPED))
- rq->cmd_flags |= REQ_COPY_USER;
+ rq->rq_flags |= RQF_COPY_USER;
return 0;
unmap_rq:
@@ -236,7 +238,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
if (do_copy)
- rq->cmd_flags |= REQ_COPY_USER;
+ rq->rq_flags |= RQF_COPY_USER;
ret = blk_rq_append_bio(rq, bio);
if (unlikely(ret)) {
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 2642e5fc8b69..182398cb1524 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -199,6 +199,10 @@ void blk_queue_split(struct request_queue *q, struct bio **bio,
case REQ_OP_SECURE_ERASE:
split = blk_bio_discard_split(q, *bio, bs, &nsegs);
break;
+ case REQ_OP_WRITE_ZEROES:
+ split = NULL;
+ nsegs = (*bio)->bi_phys_segments;
+ break;
case REQ_OP_WRITE_SAME:
split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
break;
@@ -237,15 +241,14 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
if (!bio)
return 0;
- /*
- * This should probably be returning 0, but blk_add_request_payload()
- * (Christoph!!!!)
- */
- if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
- return 1;
-
- if (bio_op(bio) == REQ_OP_WRITE_SAME)
+ switch (bio_op(bio)) {
+ case REQ_OP_DISCARD:
+ case REQ_OP_SECURE_ERASE:
+ case REQ_OP_WRITE_ZEROES:
+ return 0;
+ case REQ_OP_WRITE_SAME:
return 1;
+ }
fbio = bio;
cluster = blk_queue_cluster(q);
@@ -402,38 +405,21 @@ new_segment:
*bvprv = *bvec;
}
+static inline int __blk_bvec_map_sg(struct request_queue *q, struct bio_vec bv,
+ struct scatterlist *sglist, struct scatterlist **sg)
+{
+ *sg = sglist;
+ sg_set_page(*sg, bv.bv_page, bv.bv_len, bv.bv_offset);
+ return 1;
+}
+
static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
struct scatterlist *sglist,
struct scatterlist **sg)
{
struct bio_vec bvec, bvprv = { NULL };
struct bvec_iter iter;
- int nsegs, cluster;
-
- nsegs = 0;
- cluster = blk_queue_cluster(q);
-
- switch (bio_op(bio)) {
- case REQ_OP_DISCARD:
- case REQ_OP_SECURE_ERASE:
- /*
- * This is a hack - drivers should be neither modifying the
- * biovec, nor relying on bi_vcnt - but because of
- * blk_add_request_payload(), a discard bio may or may not have
- * a payload we need to set up here (thank you Christoph) and
- * bi_vcnt is really the only way of telling if we need to.
- */
- if (!bio->bi_vcnt)
- return 0;
- /* Fall through */
- case REQ_OP_WRITE_SAME:
- *sg = sglist;
- bvec = bio_iovec(bio);
- sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
- return 1;
- default:
- break;
- }
+ int cluster = blk_queue_cluster(q), nsegs = 0;
for_each_bio(bio)
bio_for_each_segment(bvec, bio, iter)
@@ -453,10 +439,14 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
struct scatterlist *sg = NULL;
int nsegs = 0;
- if (rq->bio)
+ if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+ nsegs = __blk_bvec_map_sg(q, rq->special_vec, sglist, &sg);
+ else if (rq->bio && bio_op(rq->bio) == REQ_OP_WRITE_SAME)
+ nsegs = __blk_bvec_map_sg(q, bio_iovec(rq->bio), sglist, &sg);
+ else if (rq->bio)
nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg);
- if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
+ if (unlikely(rq->rq_flags & RQF_COPY_USER) &&
(blk_rq_bytes(rq) & q->dma_pad_mask)) {
unsigned int pad_len =
(q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
@@ -486,12 +476,19 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
* Something must have been wrong if the figured number of
* segment is bigger than number of req's physical segments
*/
- WARN_ON(nsegs > rq->nr_phys_segments);
+ WARN_ON(nsegs > blk_rq_nr_phys_segments(rq));
return nsegs;
}
EXPORT_SYMBOL(blk_rq_map_sg);
+static void req_set_nomerge(struct request_queue *q, struct request *req)
+{
+ req->cmd_flags |= REQ_NOMERGE;
+ if (req == q->last_merge)
+ q->last_merge = NULL;
+}
+
static inline int ll_new_hw_segment(struct request_queue *q,
struct request *req,
struct bio *bio)
@@ -512,9 +509,7 @@ static inline int ll_new_hw_segment(struct request_queue *q,
return 1;
no_merge:
- req->cmd_flags |= REQ_NOMERGE;
- if (req == q->last_merge)
- q->last_merge = NULL;
+ req_set_nomerge(q, req);
return 0;
}
@@ -528,9 +523,7 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
return 0;
if (blk_rq_sectors(req) + bio_sectors(bio) >
blk_rq_get_max_sectors(req, blk_rq_pos(req))) {
- req->cmd_flags |= REQ_NOMERGE;
- if (req == q->last_merge)
- q->last_merge = NULL;
+ req_set_nomerge(q, req);
return 0;
}
if (!bio_flagged(req->biotail, BIO_SEG_VALID))
@@ -552,9 +545,7 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req,
return 0;
if (blk_rq_sectors(req) + bio_sectors(bio) >
blk_rq_get_max_sectors(req, bio->bi_iter.bi_sector)) {
- req->cmd_flags |= REQ_NOMERGE;
- if (req == q->last_merge)
- q->last_merge = NULL;
+ req_set_nomerge(q, req);
return 0;
}
if (!bio_flagged(bio, BIO_SEG_VALID))
@@ -634,7 +625,7 @@ void blk_rq_set_mixed_merge(struct request *rq)
unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK;
struct bio *bio;
- if (rq->cmd_flags & REQ_MIXED_MERGE)
+ if (rq->rq_flags & RQF_MIXED_MERGE)
return;
/*
@@ -647,7 +638,7 @@ void blk_rq_set_mixed_merge(struct request *rq)
(bio->bi_opf & REQ_FAILFAST_MASK) != ff);
bio->bi_opf |= ff;
}
- rq->cmd_flags |= REQ_MIXED_MERGE;
+ rq->rq_flags |= RQF_MIXED_MERGE;
}
static void blk_account_io_merge(struct request *req)
@@ -709,7 +700,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,
* makes sure that all involved bios have mixable attributes
* set properly.
*/
- if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE ||
+ if (((req->rq_flags | next->rq_flags) & RQF_MIXED_MERGE) ||
(req->cmd_flags & REQ_FAILFAST_MASK) !=
(next->cmd_flags & REQ_FAILFAST_MASK)) {
blk_rq_set_mixed_merge(req);
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index 01fb455d3377..eacd3af72099 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -259,6 +259,47 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
return ret;
}
+static void blk_mq_stat_clear(struct blk_mq_hw_ctx *hctx)
+{
+ struct blk_mq_ctx *ctx;
+ unsigned int i;
+
+ hctx_for_each_ctx(hctx, ctx, i) {
+ blk_stat_init(&ctx->stat[BLK_STAT_READ]);
+ blk_stat_init(&ctx->stat[BLK_STAT_WRITE]);
+ }
+}
+
+static ssize_t blk_mq_hw_sysfs_stat_store(struct blk_mq_hw_ctx *hctx,
+ const char *page, size_t count)
+{
+ blk_mq_stat_clear(hctx);
+ return count;
+}
+
+static ssize_t print_stat(char *page, struct blk_rq_stat *stat, const char *pre)
+{
+ return sprintf(page, "%s samples=%llu, mean=%lld, min=%lld, max=%lld\n",
+ pre, (long long) stat->nr_samples,
+ (long long) stat->mean, (long long) stat->min,
+ (long long) stat->max);
+}
+
+static ssize_t blk_mq_hw_sysfs_stat_show(struct blk_mq_hw_ctx *hctx, char *page)
+{
+ struct blk_rq_stat stat[2];
+ ssize_t ret;
+
+ blk_stat_init(&stat[BLK_STAT_READ]);
+ blk_stat_init(&stat[BLK_STAT_WRITE]);
+
+ blk_hctx_stat_get(hctx, stat);
+
+ ret = print_stat(page, &stat[BLK_STAT_READ], "read :");
+ ret += print_stat(page + ret, &stat[BLK_STAT_WRITE], "write:");
+ return ret;
+}
+
static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = {
.attr = {.name = "dispatched", .mode = S_IRUGO },
.show = blk_mq_sysfs_dispatched_show,
@@ -317,6 +358,11 @@ static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_poll = {
.show = blk_mq_hw_sysfs_poll_show,
.store = blk_mq_hw_sysfs_poll_store,
};
+static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_stat = {
+ .attr = {.name = "stats", .mode = S_IRUGO | S_IWUSR },
+ .show = blk_mq_hw_sysfs_stat_show,
+ .store = blk_mq_hw_sysfs_stat_store,
+};
static struct attribute *default_hw_ctx_attrs[] = {
&blk_mq_hw_sysfs_queued.attr,
@@ -327,6 +373,7 @@ static struct attribute *default_hw_ctx_attrs[] = {
&blk_mq_hw_sysfs_cpus.attr,
&blk_mq_hw_sysfs_active.attr,
&blk_mq_hw_sysfs_poll.attr,
+ &blk_mq_hw_sysfs_stat.attr,
NULL,
};
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f3d27a6dee09..d79fdc11b1ee 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -30,6 +30,8 @@
#include "blk.h"
#include "blk-mq.h"
#include "blk-mq-tag.h"
+#include "blk-stat.h"
+#include "blk-wbt.h"
static DEFINE_MUTEX(all_q_mutex);
static LIST_HEAD(all_q_list);
@@ -115,6 +117,33 @@ void blk_mq_unfreeze_queue(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
+/**
+ * blk_mq_quiesce_queue() - wait until all ongoing queue_rq calls have finished
+ * @q: request queue.
+ *
+ * Note: this function does not prevent that the struct request end_io()
+ * callback function is invoked. Additionally, it is not prevented that
+ * new queue_rq() calls occur unless the queue has been stopped first.
+ */
+void blk_mq_quiesce_queue(struct request_queue *q)
+{
+ struct blk_mq_hw_ctx *hctx;
+ unsigned int i;
+ bool rcu = false;
+
+ blk_mq_stop_hw_queues(q);
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (hctx->flags & BLK_MQ_F_BLOCKING)
+ synchronize_srcu(&hctx->queue_rq_srcu);
+ else
+ rcu = true;
+ }
+ if (rcu)
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
+
void blk_mq_wake_waiters(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
@@ -139,17 +168,15 @@ bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx)
EXPORT_SYMBOL(blk_mq_can_queue);
static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
- struct request *rq, int op,
- unsigned int op_flags)
+ struct request *rq, unsigned int op)
{
- if (blk_queue_io_stat(q))
- op_flags |= REQ_IO_STAT;
-
INIT_LIST_HEAD(&rq->queuelist);
/* csd/requeue_work/fifo_time is initialized before use */
rq->q = q;
rq->mq_ctx = ctx;
- req_set_op_attrs(rq, op, op_flags);
+ rq->cmd_flags = op;
+ if (blk_queue_io_stat(q))
+ rq->rq_flags |= RQF_IO_STAT;
/* do not touch atomic flags, it needs atomic ops against the timer */
rq->cpu = -1;
INIT_HLIST_NODE(&rq->hash);
@@ -184,11 +211,11 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
rq->end_io_data = NULL;
rq->next_rq = NULL;
- ctx->rq_dispatched[rw_is_sync(op, op_flags)]++;
+ ctx->rq_dispatched[op_is_sync(op)]++;
}
static struct request *
-__blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags)
+__blk_mq_alloc_request(struct blk_mq_alloc_data *data, unsigned int op)
{
struct request *rq;
unsigned int tag;
@@ -198,12 +225,12 @@ __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags)
rq = data->hctx->tags->rqs[tag];
if (blk_mq_tag_busy(data->hctx)) {
- rq->cmd_flags = REQ_MQ_INFLIGHT;
+ rq->rq_flags = RQF_MQ_INFLIGHT;
atomic_inc(&data->hctx->nr_active);
}
rq->tag = tag;
- blk_mq_rq_ctx_init(data->q, data->ctx, rq, op, op_flags);
+ blk_mq_rq_ctx_init(data->q, data->ctx, rq, op);
return rq;
}
@@ -226,7 +253,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
ctx = blk_mq_get_ctx(q);
hctx = blk_mq_map_queue(q, ctx->cpu);
blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
- rq = __blk_mq_alloc_request(&alloc_data, rw, 0);
+ rq = __blk_mq_alloc_request(&alloc_data, rw);
blk_mq_put_ctx(ctx);
if (!rq) {
@@ -278,7 +305,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, int rw,
ctx = __blk_mq_get_ctx(q, cpumask_first(hctx->cpumask));
blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
- rq = __blk_mq_alloc_request(&alloc_data, rw, 0);
+ rq = __blk_mq_alloc_request(&alloc_data, rw);
if (!rq) {
ret = -EWOULDBLOCK;
goto out_queue_exit;
@@ -298,11 +325,14 @@ static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx,
const int tag = rq->tag;
struct request_queue *q = rq->q;
- if (rq->cmd_flags & REQ_MQ_INFLIGHT)
+ if (rq->rq_flags & RQF_MQ_INFLIGHT)
atomic_dec(&hctx->nr_active);
- rq->cmd_flags = 0;
+
+ wbt_done(q->rq_wb, &rq->issue_stat);
+ rq->rq_flags = 0;
clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
+ clear_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags);
blk_mq_put_tag(hctx, ctx, tag);
blk_queue_exit(q);
}
@@ -328,6 +358,7 @@ inline void __blk_mq_end_request(struct request *rq, int error)
blk_account_io_done(rq);
if (rq->end_io) {
+ wbt_done(rq->q->rq_wb, &rq->issue_stat);
rq->end_io(rq, error);
} else {
if (unlikely(blk_bidi_rq(rq)))
@@ -378,10 +409,27 @@ static void blk_mq_ipi_complete_request(struct request *rq)
put_cpu();
}
+static void blk_mq_stat_add(struct request *rq)
+{
+ if (rq->rq_flags & RQF_STATS) {
+ /*
+ * We could rq->mq_ctx here, but there's less of a risk
+ * of races if we have the completion event add the stats
+ * to the local software queue.
+ */
+ struct blk_mq_ctx *ctx;
+
+ ctx = __blk_mq_get_ctx(rq->q, raw_smp_processor_id());
+ blk_stat_add(&ctx->stat[rq_data_dir(rq)], rq);
+ }
+}
+
static void __blk_mq_complete_request(struct request *rq)
{
struct request_queue *q = rq->q;
+ blk_mq_stat_add(rq);
+
if (!q->softirq_done_fn)
blk_mq_end_request(rq, rq->errors);
else
@@ -425,6 +473,12 @@ void blk_mq_start_request(struct request *rq)
if (unlikely(blk_bidi_rq(rq)))
rq->next_rq->resid_len = blk_rq_bytes(rq->next_rq);
+ if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
+ blk_stat_set_issue_time(&rq->issue_stat);
+ rq->rq_flags |= RQF_STATS;
+ wbt_issue(q->rq_wb, &rq->issue_stat);
+ }
+
blk_add_timer(rq);
/*
@@ -460,6 +514,7 @@ static void __blk_mq_requeue_request(struct request *rq)
struct request_queue *q = rq->q;
trace_block_rq_requeue(q, rq);
+ wbt_requeue(q->rq_wb, &rq->issue_stat);
if (test_and_clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) {
if (q->dma_drain_size && blk_rq_bytes(rq))
@@ -467,12 +522,12 @@ static void __blk_mq_requeue_request(struct request *rq)
}
}
-void blk_mq_requeue_request(struct request *rq)
+void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list)
{
__blk_mq_requeue_request(rq);
BUG_ON(blk_queued_rq(rq));
- blk_mq_add_to_requeue_list(rq, true);
+ blk_mq_add_to_requeue_list(rq, true, kick_requeue_list);
}
EXPORT_SYMBOL(blk_mq_requeue_request);
@@ -489,10 +544,10 @@ static void blk_mq_requeue_work(struct work_struct *work)
spin_unlock_irqrestore(&q->requeue_lock, flags);
list_for_each_entry_safe(rq, next, &rq_list, queuelist) {
- if (!(rq->cmd_flags & REQ_SOFTBARRIER))
+ if (!(rq->rq_flags & RQF_SOFTBARRIER))
continue;
- rq->cmd_flags &= ~REQ_SOFTBARRIER;
+ rq->rq_flags &= ~RQF_SOFTBARRIER;
list_del_init(&rq->queuelist);
blk_mq_insert_request(rq, true, false, false);
}
@@ -503,14 +558,11 @@ static void blk_mq_requeue_work(struct work_struct *work)
blk_mq_insert_request(rq, false, false, false);
}
- /*
- * Use the start variant of queue running here, so that running
- * the requeue work will kick stopped queues.
- */
- blk_mq_start_hw_queues(q);
+ blk_mq_run_hw_queues(q, false);
}
-void blk_mq_add_to_requeue_list(struct request *rq, bool at_head)
+void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
+ bool kick_requeue_list)
{
struct request_queue *q = rq->q;
unsigned long flags;
@@ -519,24 +571,21 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head)
* We abuse this flag that is otherwise used by the I/O scheduler to
* request head insertation from the workqueue.
*/
- BUG_ON(rq->cmd_flags & REQ_SOFTBARRIER);
+ BUG_ON(rq->rq_flags & RQF_SOFTBARRIER);
spin_lock_irqsave(&q->requeue_lock, flags);
if (at_head) {
- rq->cmd_flags |= REQ_SOFTBARRIER;
+ rq->rq_flags |= RQF_SOFTBARRIER;
list_add(&rq->queuelist, &q->requeue_list);
} else {
list_add_tail(&rq->queuelist, &q->requeue_list);
}
spin_unlock_irqrestore(&q->requeue_lock, flags);
-}
-EXPORT_SYMBOL(blk_mq_add_to_requeue_list);
-void blk_mq_cancel_requeue_work(struct request_queue *q)
-{
- cancel_delayed_work_sync(&q->requeue_work);
+ if (kick_requeue_list)
+ blk_mq_kick_requeue_list(q);
}
-EXPORT_SYMBOL_GPL(blk_mq_cancel_requeue_work);
+EXPORT_SYMBOL(blk_mq_add_to_requeue_list);
void blk_mq_kick_requeue_list(struct request_queue *q)
{
@@ -772,44 +821,13 @@ static inline unsigned int queued_to_index(unsigned int queued)
return min(BLK_MQ_MAX_DISPATCH_ORDER - 1, ilog2(queued) + 1);
}
-/*
- * Run this hardware queue, pulling any software queues mapped to it in.
- * Note that this function currently has various problems around ordering
- * of IO. In particular, we'd like FIFO behaviour on handling existing
- * items on the hctx->dispatch list. Ignore that for now.
- */
-static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
+bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
{
struct request_queue *q = hctx->queue;
struct request *rq;
- LIST_HEAD(rq_list);
LIST_HEAD(driver_list);
struct list_head *dptr;
- int queued;
-
- if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
- return;
-
- WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
- cpu_online(hctx->next_cpu));
-
- hctx->run++;
-
- /*
- * Touch any software queue that has pending entries.
- */
- flush_busy_ctxs(hctx, &rq_list);
-
- /*
- * If we have previous entries on our dispatch list, grab them
- * and stuff them at the front for more fair dispatch.
- */
- if (!list_empty_careful(&hctx->dispatch)) {
- spin_lock(&hctx->lock);
- if (!list_empty(&hctx->dispatch))
- list_splice_init(&hctx->dispatch, &rq_list);
- spin_unlock(&hctx->lock);
- }
+ int queued, ret = BLK_MQ_RQ_QUEUE_OK;
/*
* Start off with dptr being NULL, so we start the first request
@@ -821,16 +839,15 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
* Now process all the entries, sending them to the driver.
*/
queued = 0;
- while (!list_empty(&rq_list)) {
+ while (!list_empty(list)) {
struct blk_mq_queue_data bd;
- int ret;
- rq = list_first_entry(&rq_list, struct request, queuelist);
+ rq = list_first_entry(list, struct request, queuelist);
list_del_init(&rq->queuelist);
bd.rq = rq;
bd.list = dptr;
- bd.last = list_empty(&rq_list);
+ bd.last = list_empty(list);
ret = q->mq_ops->queue_rq(hctx, &bd);
switch (ret) {
@@ -838,7 +855,7 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
queued++;
break;
case BLK_MQ_RQ_QUEUE_BUSY:
- list_add(&rq->queuelist, &rq_list);
+ list_add(&rq->queuelist, list);
__blk_mq_requeue_request(rq);
break;
default:
@@ -856,7 +873,7 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
* We've done the first request. If we have more than 1
* left in the list, set dptr to defer issue.
*/
- if (!dptr && rq_list.next != rq_list.prev)
+ if (!dptr && list->next != list->prev)
dptr = &driver_list;
}
@@ -866,10 +883,11 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
* Any items that need requeuing? Stuff them into hctx->dispatch,
* that is where we will continue on next queue run.
*/
- if (!list_empty(&rq_list)) {
+ if (!list_empty(list)) {
spin_lock(&hctx->lock);
- list_splice(&rq_list, &hctx->dispatch);
+ list_splice(list, &hctx->dispatch);
spin_unlock(&hctx->lock);
+
/*
* the queue is expected stopped with BLK_MQ_RQ_QUEUE_BUSY, but
* it's possible the queue is stopped and restarted again
@@ -881,6 +899,61 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
**/
blk_mq_run_hw_queue(hctx, true);
}
+
+ return ret != BLK_MQ_RQ_QUEUE_BUSY;
+}
+
+/*
+ * Run this hardware queue, pulling any software queues mapped to it in.
+ * Note that this function currently has various problems around ordering
+ * of IO. In particular, we'd like FIFO behaviour on handling existing
+ * items on the hctx->dispatch list. Ignore that for now.
+ */
+static void blk_mq_process_rq_list(struct blk_mq_hw_ctx *hctx)
+{
+ LIST_HEAD(rq_list);
+ LIST_HEAD(driver_list);
+
+ if (unlikely(blk_mq_hctx_stopped(hctx)))
+ return;
+
+ hctx->run++;
+
+ /*
+ * Touch any software queue that has pending entries.
+ */
+ flush_busy_ctxs(hctx, &rq_list);
+
+ /*
+ * If we have previous entries on our dispatch list, grab them
+ * and stuff them at the front for more fair dispatch.
+ */
+ if (!list_empty_careful(&hctx->dispatch)) {
+ spin_lock(&hctx->lock);
+ if (!list_empty(&hctx->dispatch))
+ list_splice_init(&hctx->dispatch, &rq_list);
+ spin_unlock(&hctx->lock);
+ }
+
+ blk_mq_dispatch_rq_list(hctx, &rq_list);
+}
+
+static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
+{
+ int srcu_idx;
+
+ WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
+ cpu_online(hctx->next_cpu));
+
+ if (!(hctx->flags & BLK_MQ_F_BLOCKING)) {
+ rcu_read_lock();
+ blk_mq_process_rq_list(hctx);
+ rcu_read_unlock();
+ } else {
+ srcu_idx = srcu_read_lock(&hctx->queue_rq_srcu);
+ blk_mq_process_rq_list(hctx);
+ srcu_read_unlock(&hctx->queue_rq_srcu, srcu_idx);
+ }
}
/*
@@ -895,7 +968,7 @@ static int blk_mq_hctx_next_cpu(struct blk_mq_hw_ctx *hctx)
return WORK_CPU_UNBOUND;
if (--hctx->next_cpu_batch <= 0) {
- int cpu = hctx->next_cpu, next_cpu;
+ int next_cpu;
next_cpu = cpumask_next(hctx->next_cpu, hctx->cpumask);
if (next_cpu >= nr_cpu_ids)
@@ -903,8 +976,6 @@ static int blk_mq_hctx_next_cpu(struct blk_mq_hw_ctx *hctx)
hctx->next_cpu = next_cpu;
hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
-
- return cpu;
}
return hctx->next_cpu;
@@ -912,8 +983,8 @@ static int blk_mq_hctx_next_cpu(struct blk_mq_hw_ctx *hctx)
void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
{
- if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state) ||
- !blk_mq_hw_queue_mapped(hctx)))
+ if (unlikely(blk_mq_hctx_stopped(hctx) ||
+ !blk_mq_hw_queue_mapped(hctx)))
return;
if (!async && !(hctx->flags & BLK_MQ_F_BLOCKING)) {
@@ -938,7 +1009,7 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async)
queue_for_each_hw_ctx(q, hctx, i) {
if ((!blk_mq_hctx_has_pending(hctx) &&
list_empty_careful(&hctx->dispatch)) ||
- test_bit(BLK_MQ_S_STOPPED, &hctx->state))
+ blk_mq_hctx_stopped(hctx))
continue;
blk_mq_run_hw_queue(hctx, async);
@@ -946,6 +1017,26 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async)
}
EXPORT_SYMBOL(blk_mq_run_hw_queues);
+/**
+ * blk_mq_queue_stopped() - check whether one or more hctxs have been stopped
+ * @q: request queue.
+ *
+ * The caller is responsible for serializing this function against
+ * blk_mq_{start,stop}_hw_queue().
+ */
+bool blk_mq_queue_stopped(struct request_queue *q)
+{
+ struct blk_mq_hw_ctx *hctx;
+ int i;
+
+ queue_for_each_hw_ctx(q, hctx, i)
+ if (blk_mq_hctx_stopped(hctx))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(blk_mq_queue_stopped);
+
void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
{
cancel_work(&hctx->run_work);
@@ -982,18 +1073,23 @@ void blk_mq_start_hw_queues(struct request_queue *q)
}
EXPORT_SYMBOL(blk_mq_start_hw_queues);
+void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
+{
+ if (!blk_mq_hctx_stopped(hctx))
+ return;
+
+ clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+ blk_mq_run_hw_queue(hctx, async);
+}
+EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
+
void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async)
{
struct blk_mq_hw_ctx *hctx;
int i;
- queue_for_each_hw_ctx(q, hctx, i) {
- if (!test_bit(BLK_MQ_S_STOPPED, &hctx->state))
- continue;
-
- clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
- blk_mq_run_hw_queue(hctx, async);
- }
+ queue_for_each_hw_ctx(q, hctx, i)
+ blk_mq_start_stopped_hw_queue(hctx, async);
}
EXPORT_SYMBOL(blk_mq_start_stopped_hw_queues);
@@ -1155,7 +1251,7 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
{
init_request_from_bio(rq, bio);
- blk_account_io_start(rq, 1);
+ blk_account_io_start(rq, true);
}
static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
@@ -1190,40 +1286,27 @@ insert_rq:
}
}
-struct blk_map_ctx {
- struct blk_mq_hw_ctx *hctx;
- struct blk_mq_ctx *ctx;
-};
-
static struct request *blk_mq_map_request(struct request_queue *q,
struct bio *bio,
- struct blk_map_ctx *data)
+ struct blk_mq_alloc_data *data)
{
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx;
struct request *rq;
- int op = bio_data_dir(bio);
- int op_flags = 0;
- struct blk_mq_alloc_data alloc_data;
blk_queue_enter_live(q);
ctx = blk_mq_get_ctx(q);
hctx = blk_mq_map_queue(q, ctx->cpu);
- if (rw_is_sync(bio_op(bio), bio->bi_opf))
- op_flags |= REQ_SYNC;
+ trace_block_getrq(q, bio, bio->bi_opf);
+ blk_mq_set_alloc_data(data, q, 0, ctx, hctx);
+ rq = __blk_mq_alloc_request(data, bio->bi_opf);
- trace_block_getrq(q, bio, op);
- blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx);
- rq = __blk_mq_alloc_request(&alloc_data, op, op_flags);
-
- data->hctx = alloc_data.hctx;
- data->ctx = alloc_data.ctx;
data->hctx->queued++;
return rq;
}
-static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
+static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie)
{
int ret;
struct request_queue *q = rq->q;
@@ -1235,6 +1318,9 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
};
blk_qc_t new_cookie = blk_tag_to_qc_t(rq->tag, hctx->queue_num);
+ if (blk_mq_hctx_stopped(hctx))
+ goto insert;
+
/*
* For OK queue, we are done. For error, kill it. Any other
* error (busy), just add it to our list as we previously
@@ -1243,7 +1329,7 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
ret = q->mq_ops->queue_rq(hctx, &bd);
if (ret == BLK_MQ_RQ_QUEUE_OK) {
*cookie = new_cookie;
- return 0;
+ return;
}
__blk_mq_requeue_request(rq);
@@ -1252,10 +1338,11 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
*cookie = BLK_QC_T_NONE;
rq->errors = -EIO;
blk_mq_end_request(rq, rq->errors);
- return 0;
+ return;
}
- return -1;
+insert:
+ blk_mq_insert_request(rq, false, true, true);
}
/*
@@ -1265,14 +1352,15 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
*/
static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
{
- const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+ const int is_sync = op_is_sync(bio->bi_opf);
const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
- struct blk_map_ctx data;
+ struct blk_mq_alloc_data data;
struct request *rq;
- unsigned int request_count = 0;
+ unsigned int request_count = 0, srcu_idx;
struct blk_plug *plug;
struct request *same_queue_rq = NULL;
blk_qc_t cookie;
+ unsigned int wb_acct;
blk_queue_bounce(q, &bio);
@@ -1287,9 +1375,15 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
return BLK_QC_T_NONE;
+ wb_acct = wbt_wait(q->rq_wb, bio, NULL);
+
rq = blk_mq_map_request(q, bio, &data);
- if (unlikely(!rq))
+ if (unlikely(!rq)) {
+ __wbt_done(q->rq_wb, wb_acct);
return BLK_QC_T_NONE;
+ }
+
+ wbt_track(&rq->issue_stat, wb_acct);
cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num);
@@ -1312,7 +1406,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
blk_mq_bio_to_request(rq, bio);
/*
- * We do limited pluging. If the bio can be merged, do that.
+ * We do limited plugging. If the bio can be merged, do that.
* Otherwise the existing request in the plug list will be
* issued. So the plug list will have one request at most
*/
@@ -1332,9 +1426,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
blk_mq_put_ctx(data.ctx);
if (!old_rq)
goto done;
- if (!blk_mq_direct_issue_request(old_rq, &cookie))
- goto done;
- blk_mq_insert_request(old_rq, false, true, true);
+
+ if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) {
+ rcu_read_lock();
+ blk_mq_try_issue_directly(old_rq, &cookie);
+ rcu_read_unlock();
+ } else {
+ srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu);
+ blk_mq_try_issue_directly(old_rq, &cookie);
+ srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx);
+ }
goto done;
}
@@ -1359,13 +1460,14 @@ done:
*/
static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
{
- const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+ const int is_sync = op_is_sync(bio->bi_opf);
const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
struct blk_plug *plug;
unsigned int request_count = 0;
- struct blk_map_ctx data;
+ struct blk_mq_alloc_data data;
struct request *rq;
blk_qc_t cookie;
+ unsigned int wb_acct;
blk_queue_bounce(q, &bio);
@@ -1382,9 +1484,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
} else
request_count = blk_plug_queued_count(q);
+ wb_acct = wbt_wait(q->rq_wb, bio, NULL);
+
rq = blk_mq_map_request(q, bio, &data);
- if (unlikely(!rq))
+ if (unlikely(!rq)) {
+ __wbt_done(q->rq_wb, wb_acct);
return BLK_QC_T_NONE;
+ }
+
+ wbt_track(&rq->issue_stat, wb_acct);
cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num);
@@ -1401,13 +1509,25 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
*/
plug = current->plug;
if (plug) {
+ struct request *last = NULL;
+
blk_mq_bio_to_request(rq, bio);
+
+ /*
+ * @request_count may become stale because of schedule
+ * out, so check the list again.
+ */
+ if (list_empty(&plug->mq_list))
+ request_count = 0;
if (!request_count)
trace_block_plug(q);
+ else
+ last = list_entry_rq(plug->mq_list.prev);
blk_mq_put_ctx(data.ctx);
- if (request_count >= BLK_MAX_REQUEST_COUNT) {
+ if (request_count >= BLK_MAX_REQUEST_COUNT || (last &&
+ blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) {
blk_flush_plug_list(plug, false);
trace_block_plug(q);
}
@@ -1613,6 +1733,9 @@ static void blk_mq_exit_hctx(struct request_queue *q,
if (set->ops->exit_hctx)
set->ops->exit_hctx(hctx, hctx_idx);
+ if (hctx->flags & BLK_MQ_F_BLOCKING)
+ cleanup_srcu_struct(&hctx->queue_rq_srcu);
+
blk_mq_remove_cpuhp(hctx);
blk_free_flush_queue(hctx->fq);
sbitmap_free(&hctx->ctx_map);
@@ -1693,6 +1816,9 @@ static int blk_mq_init_hctx(struct request_queue *q,
flush_start_tag + hctx_idx, node))
goto free_fq;
+ if (hctx->flags & BLK_MQ_F_BLOCKING)
+ init_srcu_struct(&hctx->queue_rq_srcu);
+
return 0;
free_fq:
@@ -1723,6 +1849,8 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
spin_lock_init(&__ctx->lock);
INIT_LIST_HEAD(&__ctx->rq_list);
__ctx->queue = q;
+ blk_stat_init(&__ctx->stat[BLK_STAT_READ]);
+ blk_stat_init(&__ctx->stat[BLK_STAT_WRITE]);
/* If the cpu isn't online, the cpu is mapped to first hctx */
if (!cpu_online(i))
@@ -2018,6 +2146,11 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
*/
q->nr_requests = set->queue_depth;
+ /*
+ * Default to classic polling
+ */
+ q->poll_nsec = -1;
+
if (set->ops->complete)
blk_queue_softirq_done(q, set->ops->complete);
@@ -2053,6 +2186,8 @@ void blk_mq_free_queue(struct request_queue *q)
list_del_init(&q->all_q_node);
mutex_unlock(&all_q_mutex);
+ wbt_exit(q);
+
blk_mq_del_queue_tag_set(q);
blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
@@ -2099,16 +2234,9 @@ static void blk_mq_queue_reinit_work(void)
*/
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_freeze_queue_start(q);
- list_for_each_entry(q, &all_q_list, all_q_node) {
+ list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_freeze_queue_wait(q);
- /*
- * timeout handler can't touch hw queue during the
- * reinitialization
- */
- del_timer_sync(&q->timeout);
- }
-
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_queue_reinit(q, &cpuhp_online_new);
@@ -2353,6 +2481,165 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
}
EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues);
+static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx,
+ struct request *rq)
+{
+ struct blk_rq_stat stat[2];
+ unsigned long ret = 0;
+
+ /*
+ * If stats collection isn't on, don't sleep but turn it on for
+ * future users
+ */
+ if (!blk_stat_enable(q))
+ return 0;
+
+ /*
+ * We don't have to do this once per IO, should optimize this
+ * to just use the current window of stats until it changes
+ */
+ memset(&stat, 0, sizeof(stat));
+ blk_hctx_stat_get(hctx, stat);
+
+ /*
+ * As an optimistic guess, use half of the mean service time
+ * for this type of request. We can (and should) make this smarter.
+ * For instance, if the completion latencies are tight, we can
+ * get closer than just half the mean. This is especially
+ * important on devices where the completion latencies are longer
+ * than ~10 usec.
+ */
+ if (req_op(rq) == REQ_OP_READ && stat[BLK_STAT_READ].nr_samples)
+ ret = (stat[BLK_STAT_READ].mean + 1) / 2;
+ else if (req_op(rq) == REQ_OP_WRITE && stat[BLK_STAT_WRITE].nr_samples)
+ ret = (stat[BLK_STAT_WRITE].mean + 1) / 2;
+
+ return ret;
+}
+
+static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx,
+ struct request *rq)
+{
+ struct hrtimer_sleeper hs;
+ enum hrtimer_mode mode;
+ unsigned int nsecs;
+ ktime_t kt;
+
+ if (test_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags))
+ return false;
+
+ /*
+ * poll_nsec can be:
+ *
+ * -1: don't ever hybrid sleep
+ * 0: use half of prev avg
+ * >0: use this specific value
+ */
+ if (q->poll_nsec == -1)
+ return false;
+ else if (q->poll_nsec > 0)
+ nsecs = q->poll_nsec;
+ else
+ nsecs = blk_mq_poll_nsecs(q, hctx, rq);
+
+ if (!nsecs)
+ return false;
+
+ set_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags);
+
+ /*
+ * This will be replaced with the stats tracking code, using
+ * 'avg_completion_time / 2' as the pre-sleep target.
+ */
+ kt = ktime_set(0, nsecs);
+
+ mode = HRTIMER_MODE_REL;
+ hrtimer_init_on_stack(&hs.timer, CLOCK_MONOTONIC, mode);
+ hrtimer_set_expires(&hs.timer, kt);
+
+ hrtimer_init_sleeper(&hs, current);
+ do {
+ if (test_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags))
+ break;
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ hrtimer_start_expires(&hs.timer, mode);
+ if (hs.task)
+ io_schedule();
+ hrtimer_cancel(&hs.timer);
+ mode = HRTIMER_MODE_ABS;
+ } while (hs.task && !signal_pending(current));
+
+ __set_current_state(TASK_RUNNING);
+ destroy_hrtimer_on_stack(&hs.timer);
+ return true;
+}
+
+static bool __blk_mq_poll(struct blk_mq_hw_ctx *hctx, struct request *rq)
+{
+ struct request_queue *q = hctx->queue;
+ long state;
+
+ /*
+ * If we sleep, have the caller restart the poll loop to reset
+ * the state. Like for the other success return cases, the
+ * caller is responsible for checking if the IO completed. If
+ * the IO isn't complete, we'll get called again and will go
+ * straight to the busy poll loop.
+ */
+ if (blk_mq_poll_hybrid_sleep(q, hctx, rq))
+ return true;
+
+ hctx->poll_considered++;
+
+ state = current->state;
+ while (!need_resched()) {
+ int ret;
+
+ hctx->poll_invoked++;
+
+ ret = q->mq_ops->poll(hctx, rq->tag);
+ if (ret > 0) {
+ hctx->poll_success++;
+ set_current_state(TASK_RUNNING);
+ return true;
+ }
+
+ if (signal_pending_state(state, current))
+ set_current_state(TASK_RUNNING);
+
+ if (current->state == TASK_RUNNING)
+ return true;
+ if (ret < 0)
+ break;
+ cpu_relax();
+ }
+
+ return false;
+}
+
+bool blk_mq_poll(struct request_queue *q, blk_qc_t cookie)
+{
+ struct blk_mq_hw_ctx *hctx;
+ struct blk_plug *plug;
+ struct request *rq;
+
+ if (!q->mq_ops || !q->mq_ops->poll || !blk_qc_t_valid(cookie) ||
+ !test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
+ return false;
+
+ plug = current->plug;
+ if (plug)
+ blk_flush_plug_list(plug, false);
+
+ hctx = q->queue_hw_ctx[blk_qc_t_to_queue_num(cookie)];
+ rq = blk_mq_tag_to_rq(hctx->tags, blk_qc_t_to_tag(cookie));
+
+ return __blk_mq_poll(hctx, rq);
+}
+EXPORT_SYMBOL_GPL(blk_mq_poll);
+
void blk_mq_disable_hotplug(void)
{
mutex_lock(&all_q_mutex);
diff --git a/block/blk-mq.h b/block/blk-mq.h
index e5d25249028c..3a54dd32a6fc 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -1,6 +1,8 @@
#ifndef INT_BLK_MQ_H
#define INT_BLK_MQ_H
+#include "blk-stat.h"
+
struct blk_mq_tag_set;
struct blk_mq_ctx {
@@ -18,6 +20,7 @@ struct blk_mq_ctx {
/* incremented at completion time */
unsigned long ____cacheline_aligned_in_smp rq_completed[2];
+ struct blk_rq_stat stat[2];
struct request_queue *queue;
struct kobject kobj;
@@ -28,6 +31,7 @@ void blk_mq_freeze_queue(struct request_queue *q);
void blk_mq_free_queue(struct request_queue *q);
int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr);
void blk_mq_wake_waiters(struct request_queue *q);
+bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *, struct list_head *);
/*
* CPU hotplug helpers
@@ -100,6 +104,11 @@ static inline void blk_mq_set_alloc_data(struct blk_mq_alloc_data *data,
data->hctx = hctx;
}
+static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
+{
+ return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
+}
+
static inline bool blk_mq_hw_queue_mapped(struct blk_mq_hw_ctx *hctx)
{
return hctx->nr_ctx && hctx->tags;
diff --git a/block/blk-settings.c b/block/blk-settings.c
index f679ae122843..529e55f52a03 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -13,6 +13,7 @@
#include <linux/gfp.h>
#include "blk.h"
+#include "blk-wbt.h"
unsigned long blk_max_low_pfn;
EXPORT_SYMBOL(blk_max_low_pfn);
@@ -95,6 +96,7 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->max_dev_sectors = 0;
lim->chunk_sectors = 0;
lim->max_write_same_sectors = 0;
+ lim->max_write_zeroes_sectors = 0;
lim->max_discard_sectors = 0;
lim->max_hw_discard_sectors = 0;
lim->discard_granularity = 0;
@@ -107,6 +109,7 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->io_opt = 0;
lim->misaligned = 0;
lim->cluster = 1;
+ lim->zoned = BLK_ZONED_NONE;
}
EXPORT_SYMBOL(blk_set_default_limits);
@@ -130,6 +133,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_sectors = UINT_MAX;
lim->max_dev_sectors = UINT_MAX;
lim->max_write_same_sectors = UINT_MAX;
+ lim->max_write_zeroes_sectors = UINT_MAX;
}
EXPORT_SYMBOL(blk_set_stacking_limits);
@@ -249,6 +253,7 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
max_sectors = min_not_zero(max_hw_sectors, limits->max_dev_sectors);
max_sectors = min_t(unsigned int, max_sectors, BLK_DEF_MAX_SECTORS);
limits->max_sectors = max_sectors;
+ q->backing_dev_info.io_pages = max_sectors >> (PAGE_SHIFT - 9);
}
EXPORT_SYMBOL(blk_queue_max_hw_sectors);
@@ -298,6 +303,19 @@ void blk_queue_max_write_same_sectors(struct request_queue *q,
EXPORT_SYMBOL(blk_queue_max_write_same_sectors);
/**
+ * blk_queue_max_write_zeroes_sectors - set max sectors for a single
+ * write zeroes
+ * @q: the request queue for the device
+ * @max_write_zeroes_sectors: maximum number of sectors to write per command
+ **/
+void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
+ unsigned int max_write_zeroes_sectors)
+{
+ q->limits.max_write_zeroes_sectors = max_write_zeroes_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_write_zeroes_sectors);
+
+/**
* blk_queue_max_segments - set max hw segments for a request for this queue
* @q: the request queue for the device
* @max_segments: max number of segments
@@ -525,6 +543,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
t->max_write_same_sectors = min(t->max_write_same_sectors,
b->max_write_same_sectors);
+ t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors,
+ b->max_write_zeroes_sectors);
t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
@@ -630,6 +650,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->discard_granularity;
}
+ if (b->chunk_sectors)
+ t->chunk_sectors = min_not_zero(t->chunk_sectors,
+ b->chunk_sectors);
+
return ret;
}
EXPORT_SYMBOL(blk_stack_limits);
@@ -832,6 +856,19 @@ void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
/**
+ * blk_set_queue_depth - tell the block layer about the device queue depth
+ * @q: the request queue for the device
+ * @depth: queue depth
+ *
+ */
+void blk_set_queue_depth(struct request_queue *q, unsigned int depth)
+{
+ q->queue_depth = depth;
+ wbt_set_queue_depth(q->rq_wb, depth);
+}
+EXPORT_SYMBOL(blk_set_queue_depth);
+
+/**
* blk_queue_write_cache - configure queue's write cache
* @q: the request queue for the device
* @wc: write back cache on or off
@@ -851,6 +888,8 @@ void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua)
else
queue_flag_clear(QUEUE_FLAG_FUA, q);
spin_unlock_irq(q->queue_lock);
+
+ wbt_set_write_cache(q->rq_wb, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
}
EXPORT_SYMBOL_GPL(blk_queue_write_cache);
diff --git a/block/blk-stat.c b/block/blk-stat.c
new file mode 100644
index 000000000000..9b43efb8933f
--- /dev/null
+++ b/block/blk-stat.c
@@ -0,0 +1,256 @@
+/*
+ * Block stat tracking code
+ *
+ * Copyright (C) 2016 Jens Axboe
+ */
+#include <linux/kernel.h>
+#include <linux/blk-mq.h>
+
+#include "blk-stat.h"
+#include "blk-mq.h"
+
+static void blk_stat_flush_batch(struct blk_rq_stat *stat)
+{
+ const s32 nr_batch = READ_ONCE(stat->nr_batch);
+ const s32 nr_samples = READ_ONCE(stat->nr_samples);
+
+ if (!nr_batch)
+ return;
+ if (!nr_samples)
+ stat->mean = div64_s64(stat->batch, nr_batch);
+ else {
+ stat->mean = div64_s64((stat->mean * nr_samples) +
+ stat->batch,
+ nr_batch + nr_samples);
+ }
+
+ stat->nr_samples += nr_batch;
+ stat->nr_batch = stat->batch = 0;
+}
+
+static void blk_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
+{
+ if (!src->nr_samples)
+ return;
+
+ blk_stat_flush_batch(src);
+
+ dst->min = min(dst->min, src->min);
+ dst->max = max(dst->max, src->max);
+
+ if (!dst->nr_samples)
+ dst->mean = src->mean;
+ else {
+ dst->mean = div64_s64((src->mean * src->nr_samples) +
+ (dst->mean * dst->nr_samples),
+ dst->nr_samples + src->nr_samples);
+ }
+ dst->nr_samples += src->nr_samples;
+}
+
+static void blk_mq_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
+{
+ struct blk_mq_hw_ctx *hctx;
+ struct blk_mq_ctx *ctx;
+ uint64_t latest = 0;
+ int i, j, nr;
+
+ blk_stat_init(&dst[BLK_STAT_READ]);
+ blk_stat_init(&dst[BLK_STAT_WRITE]);
+
+ nr = 0;
+ do {
+ uint64_t newest = 0;
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ hctx_for_each_ctx(hctx, ctx, j) {
+ blk_stat_flush_batch(&ctx->stat[BLK_STAT_READ]);
+ blk_stat_flush_batch(&ctx->stat[BLK_STAT_WRITE]);
+
+ if (!ctx->stat[BLK_STAT_READ].nr_samples &&
+ !ctx->stat[BLK_STAT_WRITE].nr_samples)
+ continue;
+ if (ctx->stat[BLK_STAT_READ].time > newest)
+ newest = ctx->stat[BLK_STAT_READ].time;
+ if (ctx->stat[BLK_STAT_WRITE].time > newest)
+ newest = ctx->stat[BLK_STAT_WRITE].time;
+ }
+ }
+
+ /*
+ * No samples
+ */
+ if (!newest)
+ break;
+
+ if (newest > latest)
+ latest = newest;
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ hctx_for_each_ctx(hctx, ctx, j) {
+ if (ctx->stat[BLK_STAT_READ].time == newest) {
+ blk_stat_sum(&dst[BLK_STAT_READ],
+ &ctx->stat[BLK_STAT_READ]);
+ nr++;
+ }
+ if (ctx->stat[BLK_STAT_WRITE].time == newest) {
+ blk_stat_sum(&dst[BLK_STAT_WRITE],
+ &ctx->stat[BLK_STAT_WRITE]);
+ nr++;
+ }
+ }
+ }
+ /*
+ * If we race on finding an entry, just loop back again.
+ * Should be very rare.
+ */
+ } while (!nr);
+
+ dst[BLK_STAT_READ].time = dst[BLK_STAT_WRITE].time = latest;
+}
+
+void blk_queue_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
+{
+ if (q->mq_ops)
+ blk_mq_stat_get(q, dst);
+ else {
+ blk_stat_flush_batch(&q->rq_stats[BLK_STAT_READ]);
+ blk_stat_flush_batch(&q->rq_stats[BLK_STAT_WRITE]);
+ memcpy(&dst[BLK_STAT_READ], &q->rq_stats[BLK_STAT_READ],
+ sizeof(struct blk_rq_stat));
+ memcpy(&dst[BLK_STAT_WRITE], &q->rq_stats[BLK_STAT_WRITE],
+ sizeof(struct blk_rq_stat));
+ }
+}
+
+void blk_hctx_stat_get(struct blk_mq_hw_ctx *hctx, struct blk_rq_stat *dst)
+{
+ struct blk_mq_ctx *ctx;
+ unsigned int i, nr;
+
+ nr = 0;
+ do {
+ uint64_t newest = 0;
+
+ hctx_for_each_ctx(hctx, ctx, i) {
+ blk_stat_flush_batch(&ctx->stat[BLK_STAT_READ]);
+ blk_stat_flush_batch(&ctx->stat[BLK_STAT_WRITE]);
+
+ if (!ctx->stat[BLK_STAT_READ].nr_samples &&
+ !ctx->stat[BLK_STAT_WRITE].nr_samples)
+ continue;
+
+ if (ctx->stat[BLK_STAT_READ].time > newest)
+ newest = ctx->stat[BLK_STAT_READ].time;
+ if (ctx->stat[BLK_STAT_WRITE].time > newest)
+ newest = ctx->stat[BLK_STAT_WRITE].time;
+ }
+
+ if (!newest)
+ break;
+
+ hctx_for_each_ctx(hctx, ctx, i) {
+ if (ctx->stat[BLK_STAT_READ].time == newest) {
+ blk_stat_sum(&dst[BLK_STAT_READ],
+ &ctx->stat[BLK_STAT_READ]);
+ nr++;
+ }
+ if (ctx->stat[BLK_STAT_WRITE].time == newest) {
+ blk_stat_sum(&dst[BLK_STAT_WRITE],
+ &ctx->stat[BLK_STAT_WRITE]);
+ nr++;
+ }
+ }
+ /*
+ * If we race on finding an entry, just loop back again.
+ * Should be very rare, as the window is only updated
+ * occasionally
+ */
+ } while (!nr);
+}
+
+static void __blk_stat_init(struct blk_rq_stat *stat, s64 time_now)
+{
+ stat->min = -1ULL;
+ stat->max = stat->nr_samples = stat->mean = 0;
+ stat->batch = stat->nr_batch = 0;
+ stat->time = time_now & BLK_STAT_NSEC_MASK;
+}
+
+void blk_stat_init(struct blk_rq_stat *stat)
+{
+ __blk_stat_init(stat, ktime_to_ns(ktime_get()));
+}
+
+static bool __blk_stat_is_current(struct blk_rq_stat *stat, s64 now)
+{
+ return (now & BLK_STAT_NSEC_MASK) == (stat->time & BLK_STAT_NSEC_MASK);
+}
+
+bool blk_stat_is_current(struct blk_rq_stat *stat)
+{
+ return __blk_stat_is_current(stat, ktime_to_ns(ktime_get()));
+}
+
+void blk_stat_add(struct blk_rq_stat *stat, struct request *rq)
+{
+ s64 now, value;
+
+ now = __blk_stat_time(ktime_to_ns(ktime_get()));
+ if (now < blk_stat_time(&rq->issue_stat))
+ return;
+
+ if (!__blk_stat_is_current(stat, now))
+ __blk_stat_init(stat, now);
+
+ value = now - blk_stat_time(&rq->issue_stat);
+ if (value > stat->max)
+ stat->max = value;
+ if (value < stat->min)
+ stat->min = value;
+
+ if (stat->batch + value < stat->batch ||
+ stat->nr_batch + 1 == BLK_RQ_STAT_BATCH)
+ blk_stat_flush_batch(stat);
+
+ stat->batch += value;
+ stat->nr_batch++;
+}
+
+void blk_stat_clear(struct request_queue *q)
+{
+ if (q->mq_ops) {
+ struct blk_mq_hw_ctx *hctx;
+ struct blk_mq_ctx *ctx;
+ int i, j;
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ hctx_for_each_ctx(hctx, ctx, j) {
+ blk_stat_init(&ctx->stat[BLK_STAT_READ]);
+ blk_stat_init(&ctx->stat[BLK_STAT_WRITE]);
+ }
+ }
+ } else {
+ blk_stat_init(&q->rq_stats[BLK_STAT_READ]);
+ blk_stat_init(&q->rq_stats[BLK_STAT_WRITE]);
+ }
+}
+
+void blk_stat_set_issue_time(struct blk_issue_stat *stat)
+{
+ stat->time = (stat->time & BLK_STAT_MASK) |
+ (ktime_to_ns(ktime_get()) & BLK_STAT_TIME_MASK);
+}
+
+/*
+ * Enable stat tracking, return whether it was enabled
+ */
+bool blk_stat_enable(struct request_queue *q)
+{
+ if (!test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
+ set_bit(QUEUE_FLAG_STATS, &q->queue_flags);
+ return false;
+ }
+
+ return true;
+}
diff --git a/block/blk-stat.h b/block/blk-stat.h
new file mode 100644
index 000000000000..a2050a0a5314
--- /dev/null
+++ b/block/blk-stat.h
@@ -0,0 +1,42 @@
+#ifndef BLK_STAT_H
+#define BLK_STAT_H
+
+/*
+ * ~0.13s window as a power-of-2 (2^27 nsecs)
+ */
+#define BLK_STAT_NSEC 134217728ULL
+#define BLK_STAT_NSEC_MASK ~(BLK_STAT_NSEC - 1)
+
+/*
+ * Upper 3 bits can be used elsewhere
+ */
+#define BLK_STAT_RES_BITS 3
+#define BLK_STAT_SHIFT (64 - BLK_STAT_RES_BITS)
+#define BLK_STAT_TIME_MASK ((1ULL << BLK_STAT_SHIFT) - 1)
+#define BLK_STAT_MASK ~BLK_STAT_TIME_MASK
+
+enum {
+ BLK_STAT_READ = 0,
+ BLK_STAT_WRITE,
+};
+
+void blk_stat_add(struct blk_rq_stat *, struct request *);
+void blk_hctx_stat_get(struct blk_mq_hw_ctx *, struct blk_rq_stat *);
+void blk_queue_stat_get(struct request_queue *, struct blk_rq_stat *);
+void blk_stat_clear(struct request_queue *);
+void blk_stat_init(struct blk_rq_stat *);
+bool blk_stat_is_current(struct blk_rq_stat *);
+void blk_stat_set_issue_time(struct blk_issue_stat *);
+bool blk_stat_enable(struct request_queue *);
+
+static inline u64 __blk_stat_time(u64 time)
+{
+ return time & BLK_STAT_TIME_MASK;
+}
+
+static inline u64 blk_stat_time(struct blk_issue_stat *stat)
+{
+ return __blk_stat_time(stat->time);
+}
+
+#endif
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 9cc8d7c5439a..1dbce057592d 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -13,6 +13,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-wbt.h"
struct queue_sysfs_entry {
struct attribute attr;
@@ -41,6 +42,19 @@ queue_var_store(unsigned long *var, const char *page, size_t count)
return count;
}
+static ssize_t queue_var_store64(s64 *var, const char *page)
+{
+ int err;
+ s64 v;
+
+ err = kstrtos64(page, 10, &v);
+ if (err < 0)
+ return err;
+
+ *var = v;
+ return 0;
+}
+
static ssize_t queue_requests_show(struct request_queue *q, char *page)
{
return queue_var_show(q->nr_requests, (page));
@@ -130,6 +144,11 @@ static ssize_t queue_physical_block_size_show(struct request_queue *q, char *pag
return queue_var_show(queue_physical_block_size(q), page);
}
+static ssize_t queue_chunk_sectors_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(q->limits.chunk_sectors, page);
+}
+
static ssize_t queue_io_min_show(struct request_queue *q, char *page)
{
return queue_var_show(queue_io_min(q), page);
@@ -192,6 +211,11 @@ static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
(unsigned long long)q->limits.max_write_same_sectors << 9);
}
+static ssize_t queue_write_zeroes_max_show(struct request_queue *q, char *page)
+{
+ return sprintf(page, "%llu\n",
+ (unsigned long long)q->limits.max_write_zeroes_sectors << 9);
+}
static ssize_t
queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
@@ -212,6 +236,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
spin_lock_irq(q->queue_lock);
q->limits.max_sectors = max_sectors_kb << 1;
+ q->backing_dev_info.io_pages = max_sectors_kb >> (PAGE_SHIFT - 10);
spin_unlock_irq(q->queue_lock);
return ret;
@@ -257,6 +282,18 @@ QUEUE_SYSFS_BIT_FNS(random, ADD_RANDOM, 0);
QUEUE_SYSFS_BIT_FNS(iostats, IO_STAT, 0);
#undef QUEUE_SYSFS_BIT_FNS
+static ssize_t queue_zoned_show(struct request_queue *q, char *page)
+{
+ switch (blk_queue_zoned_model(q)) {
+ case BLK_ZONED_HA:
+ return sprintf(page, "host-aware\n");
+ case BLK_ZONED_HM:
+ return sprintf(page, "host-managed\n");
+ default:
+ return sprintf(page, "none\n");
+ }
+}
+
static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
{
return queue_var_show((blk_queue_nomerges(q) << 1) |
@@ -319,6 +356,38 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
return ret;
}
+static ssize_t queue_poll_delay_show(struct request_queue *q, char *page)
+{
+ int val;
+
+ if (q->poll_nsec == -1)
+ val = -1;
+ else
+ val = q->poll_nsec / 1000;
+
+ return sprintf(page, "%d\n", val);
+}
+
+static ssize_t queue_poll_delay_store(struct request_queue *q, const char *page,
+ size_t count)
+{
+ int err, val;
+
+ if (!q->mq_ops || !q->mq_ops->poll)
+ return -EINVAL;
+
+ err = kstrtoint(page, 10, &val);
+ if (err < 0)
+ return err;
+
+ if (val == -1)
+ q->poll_nsec = -1;
+ else
+ q->poll_nsec = val * 1000;
+
+ return count;
+}
+
static ssize_t queue_poll_show(struct request_queue *q, char *page)
{
return queue_var_show(test_bit(QUEUE_FLAG_POLL, &q->queue_flags), page);
@@ -347,6 +416,50 @@ static ssize_t queue_poll_store(struct request_queue *q, const char *page,
return ret;
}
+static ssize_t queue_wb_lat_show(struct request_queue *q, char *page)
+{
+ if (!q->rq_wb)
+ return -EINVAL;
+
+ return sprintf(page, "%llu\n", div_u64(q->rq_wb->min_lat_nsec, 1000));
+}
+
+static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
+ size_t count)
+{
+ struct rq_wb *rwb;
+ ssize_t ret;
+ s64 val;
+
+ ret = queue_var_store64(&val, page);
+ if (ret < 0)
+ return ret;
+ if (val < -1)
+ return -EINVAL;
+
+ rwb = q->rq_wb;
+ if (!rwb) {
+ ret = wbt_init(q);
+ if (ret)
+ return ret;
+
+ rwb = q->rq_wb;
+ if (!rwb)
+ return -EINVAL;
+ }
+
+ if (val == -1)
+ rwb->min_lat_nsec = wbt_default_latency_nsec(q);
+ else if (val >= 0)
+ rwb->min_lat_nsec = val * 1000ULL;
+
+ if (rwb->enable_state == WBT_STATE_ON_DEFAULT)
+ rwb->enable_state = WBT_STATE_ON_MANUAL;
+
+ wbt_update_limits(rwb);
+ return count;
+}
+
static ssize_t queue_wc_show(struct request_queue *q, char *page)
{
if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
@@ -384,6 +497,26 @@ static ssize_t queue_dax_show(struct request_queue *q, char *page)
return queue_var_show(blk_queue_dax(q), page);
}
+static ssize_t print_stat(char *page, struct blk_rq_stat *stat, const char *pre)
+{
+ return sprintf(page, "%s samples=%llu, mean=%lld, min=%lld, max=%lld\n",
+ pre, (long long) stat->nr_samples,
+ (long long) stat->mean, (long long) stat->min,
+ (long long) stat->max);
+}
+
+static ssize_t queue_stats_show(struct request_queue *q, char *page)
+{
+ struct blk_rq_stat stat[2];
+ ssize_t ret;
+
+ blk_queue_stat_get(q, stat);
+
+ ret = print_stat(page, &stat[BLK_STAT_READ], "read :");
+ ret += print_stat(page + ret, &stat[BLK_STAT_WRITE], "write:");
+ return ret;
+}
+
static struct queue_sysfs_entry queue_requests_entry = {
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
.show = queue_requests_show,
@@ -443,6 +576,11 @@ static struct queue_sysfs_entry queue_physical_block_size_entry = {
.show = queue_physical_block_size_show,
};
+static struct queue_sysfs_entry queue_chunk_sectors_entry = {
+ .attr = {.name = "chunk_sectors", .mode = S_IRUGO },
+ .show = queue_chunk_sectors_show,
+};
+
static struct queue_sysfs_entry queue_io_min_entry = {
.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
.show = queue_io_min_show,
@@ -479,12 +617,22 @@ static struct queue_sysfs_entry queue_write_same_max_entry = {
.show = queue_write_same_max_show,
};
+static struct queue_sysfs_entry queue_write_zeroes_max_entry = {
+ .attr = {.name = "write_zeroes_max_bytes", .mode = S_IRUGO },
+ .show = queue_write_zeroes_max_show,
+};
+
static struct queue_sysfs_entry queue_nonrot_entry = {
.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_nonrot,
.store = queue_store_nonrot,
};
+static struct queue_sysfs_entry queue_zoned_entry = {
+ .attr = {.name = "zoned", .mode = S_IRUGO },
+ .show = queue_zoned_show,
+};
+
static struct queue_sysfs_entry queue_nomerges_entry = {
.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
.show = queue_nomerges_show,
@@ -515,6 +663,12 @@ static struct queue_sysfs_entry queue_poll_entry = {
.store = queue_poll_store,
};
+static struct queue_sysfs_entry queue_poll_delay_entry = {
+ .attr = {.name = "io_poll_delay", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_poll_delay_show,
+ .store = queue_poll_delay_store,
+};
+
static struct queue_sysfs_entry queue_wc_entry = {
.attr = {.name = "write_cache", .mode = S_IRUGO | S_IWUSR },
.show = queue_wc_show,
@@ -526,6 +680,17 @@ static struct queue_sysfs_entry queue_dax_entry = {
.show = queue_dax_show,
};
+static struct queue_sysfs_entry queue_stats_entry = {
+ .attr = {.name = "stats", .mode = S_IRUGO },
+ .show = queue_stats_show,
+};
+
+static struct queue_sysfs_entry queue_wb_lat_entry = {
+ .attr = {.name = "wbt_lat_usec", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_wb_lat_show,
+ .store = queue_wb_lat_store,
+};
+
static struct attribute *default_attrs[] = {
&queue_requests_entry.attr,
&queue_ra_entry.attr,
@@ -538,6 +703,7 @@ static struct attribute *default_attrs[] = {
&queue_hw_sector_size_entry.attr,
&queue_logical_block_size_entry.attr,
&queue_physical_block_size_entry.attr,
+ &queue_chunk_sectors_entry.attr,
&queue_io_min_entry.attr,
&queue_io_opt_entry.attr,
&queue_discard_granularity_entry.attr,
@@ -545,7 +711,9 @@ static struct attribute *default_attrs[] = {
&queue_discard_max_hw_entry.attr,
&queue_discard_zeroes_data_entry.attr,
&queue_write_same_max_entry.attr,
+ &queue_write_zeroes_max_entry.attr,
&queue_nonrot_entry.attr,
+ &queue_zoned_entry.attr,
&queue_nomerges_entry.attr,
&queue_rq_affinity_entry.attr,
&queue_iostats_entry.attr,
@@ -553,6 +721,9 @@ static struct attribute *default_attrs[] = {
&queue_poll_entry.attr,
&queue_wc_entry.attr,
&queue_dax_entry.attr,
+ &queue_stats_entry.attr,
+ &queue_wb_lat_entry.attr,
+ &queue_poll_delay_entry.attr,
NULL,
};
@@ -627,6 +798,7 @@ static void blk_release_queue(struct kobject *kobj)
struct request_queue *q =
container_of(kobj, struct request_queue, kobj);
+ wbt_exit(q);
bdi_exit(&q->backing_dev_info);
blkcg_exit_queue(q);
@@ -667,6 +839,23 @@ struct kobj_type blk_queue_ktype = {
.release = blk_release_queue,
};
+static void blk_wb_init(struct request_queue *q)
+{
+#ifndef CONFIG_BLK_WBT_MQ
+ if (q->mq_ops)
+ return;
+#endif
+#ifndef CONFIG_BLK_WBT_SQ
+ if (q->request_fn)
+ return;
+#endif
+
+ /*
+ * If this fails, we don't get throttling
+ */
+ wbt_init(q);
+}
+
int blk_register_queue(struct gendisk *disk)
{
int ret;
@@ -706,6 +895,8 @@ int blk_register_queue(struct gendisk *disk)
if (q->mq_ops)
blk_mq_register_dev(dev, q);
+ blk_wb_init(q);
+
if (!q->request_fn)
return 0;
diff --git a/block/blk-tag.c b/block/blk-tag.c
index f0344e6939d5..bae1decb6ec3 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -270,7 +270,7 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
BUG_ON(tag >= bqt->real_max_depth);
list_del_init(&rq->queuelist);
- rq->cmd_flags &= ~REQ_QUEUED;
+ rq->rq_flags &= ~RQF_QUEUED;
rq->tag = -1;
if (unlikely(bqt->tag_index[tag] == NULL))
@@ -316,7 +316,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
unsigned max_depth;
int tag;
- if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
+ if (unlikely((rq->rq_flags & RQF_QUEUED))) {
printk(KERN_ERR
"%s: request %p for device [%s] already tagged %d",
__func__, rq,
@@ -371,7 +371,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
*/
bqt->next_tag = (tag + 1) % bqt->max_depth;
- rq->cmd_flags |= REQ_QUEUED;
+ rq->rq_flags |= RQF_QUEUED;
rq->tag = tag;
bqt->tag_index[tag] = rq;
blk_start_request(rq);
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index a3ea8260c94c..a6bb4fe326c3 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -818,13 +818,13 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
tg->io_disp[rw]++;
/*
- * REQ_THROTTLED is used to prevent the same bio to be throttled
+ * BIO_THROTTLED is used to prevent the same bio to be throttled
* more than once as a throttled bio will go through blk-throtl the
* second time when it eventually gets issued. Set it when a bio
* is being charged to a tg.
*/
- if (!(bio->bi_opf & REQ_THROTTLED))
- bio->bi_opf |= REQ_THROTTLED;
+ if (!bio_flagged(bio, BIO_THROTTLED))
+ bio_set_flag(bio, BIO_THROTTLED);
}
/**
@@ -1401,7 +1401,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg,
WARN_ON_ONCE(!rcu_read_lock_held());
/* see throtl_charge_bio() */
- if ((bio->bi_opf & REQ_THROTTLED) || !tg->has_rules[rw])
+ if (bio_flagged(bio, BIO_THROTTLED) || !tg->has_rules[rw])
goto out;
spin_lock_irq(q->queue_lock);
@@ -1480,7 +1480,7 @@ out:
* being issued.
*/
if (!throttled)
- bio->bi_opf &= ~REQ_THROTTLED;
+ bio_clear_flag(bio, BIO_THROTTLED);
return throttled;
}
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
new file mode 100644
index 000000000000..6e82769f4042
--- /dev/null
+++ b/block/blk-wbt.c
@@ -0,0 +1,750 @@
+/*
+ * buffered writeback throttling. loosely based on CoDel. We can't drop
+ * packets for IO scheduling, so the logic is something like this:
+ *
+ * - Monitor latencies in a defined window of time.
+ * - If the minimum latency in the above window exceeds some target, increment
+ * scaling step and scale down queue depth by a factor of 2x. The monitoring
+ * window is then shrunk to 100 / sqrt(scaling step + 1).
+ * - For any window where we don't have solid data on what the latencies
+ * look like, retain status quo.
+ * - If latencies look good, decrement scaling step.
+ * - If we're only doing writes, allow the scaling step to go negative. This
+ * will temporarily boost write performance, snapping back to a stable
+ * scaling step of 0 if reads show up or the heavy writers finish. Unlike
+ * positive scaling steps where we shrink the monitoring window, a negative
+ * scaling step retains the default step==0 window size.
+ *
+ * Copyright (C) 2016 Jens Axboe
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/blk_types.h>
+#include <linux/slab.h>
+#include <linux/backing-dev.h>
+#include <linux/swap.h>
+
+#include "blk-wbt.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/wbt.h>
+
+enum {
+ /*
+ * Default setting, we'll scale up (to 75% of QD max) or down (min 1)
+ * from here depending on device stats
+ */
+ RWB_DEF_DEPTH = 16,
+
+ /*
+ * 100msec window
+ */
+ RWB_WINDOW_NSEC = 100 * 1000 * 1000ULL,
+
+ /*
+ * Disregard stats, if we don't meet this minimum
+ */
+ RWB_MIN_WRITE_SAMPLES = 3,
+
+ /*
+ * If we have this number of consecutive windows with not enough
+ * information to scale up or down, scale up.
+ */
+ RWB_UNKNOWN_BUMP = 5,
+};
+
+static inline bool rwb_enabled(struct rq_wb *rwb)
+{
+ return rwb && rwb->wb_normal != 0;
+}
+
+/*
+ * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded,
+ * false if 'v' + 1 would be bigger than 'below'.
+ */
+static bool atomic_inc_below(atomic_t *v, int below)
+{
+ int cur = atomic_read(v);
+
+ for (;;) {
+ int old;
+
+ if (cur >= below)
+ return false;
+ old = atomic_cmpxchg(v, cur, cur + 1);
+ if (old == cur)
+ break;
+ cur = old;
+ }
+
+ return true;
+}
+
+static void wb_timestamp(struct rq_wb *rwb, unsigned long *var)
+{
+ if (rwb_enabled(rwb)) {
+ const unsigned long cur = jiffies;
+
+ if (cur != *var)
+ *var = cur;
+ }
+}
+
+/*
+ * If a task was rate throttled in balance_dirty_pages() within the last
+ * second or so, use that to indicate a higher cleaning rate.
+ */
+static bool wb_recent_wait(struct rq_wb *rwb)
+{
+ struct bdi_writeback *wb = &rwb->queue->backing_dev_info.wb;
+
+ return time_before(jiffies, wb->dirty_sleep + HZ);
+}
+
+static inline struct rq_wait *get_rq_wait(struct rq_wb *rwb, bool is_kswapd)
+{
+ return &rwb->rq_wait[is_kswapd];
+}
+
+static void rwb_wake_all(struct rq_wb *rwb)
+{
+ int i;
+
+ for (i = 0; i < WBT_NUM_RWQ; i++) {
+ struct rq_wait *rqw = &rwb->rq_wait[i];
+
+ if (waitqueue_active(&rqw->wait))
+ wake_up_all(&rqw->wait);
+ }
+}
+
+void __wbt_done(struct rq_wb *rwb, enum wbt_flags wb_acct)
+{
+ struct rq_wait *rqw;
+ int inflight, limit;
+
+ if (!(wb_acct & WBT_TRACKED))
+ return;
+
+ rqw = get_rq_wait(rwb, wb_acct & WBT_KSWAPD);
+ inflight = atomic_dec_return(&rqw->inflight);
+
+ /*
+ * wbt got disabled with IO in flight. Wake up any potential
+ * waiters, we don't have to do more than that.
+ */
+ if (unlikely(!rwb_enabled(rwb))) {
+ rwb_wake_all(rwb);
+ return;
+ }
+
+ /*
+ * If the device does write back caching, drop further down
+ * before we wake people up.
+ */
+ if (rwb->wc && !wb_recent_wait(rwb))
+ limit = 0;
+ else
+ limit = rwb->wb_normal;
+
+ /*
+ * Don't wake anyone up if we are above the normal limit.
+ */
+ if (inflight && inflight >= limit)
+ return;
+
+ if (waitqueue_active(&rqw->wait)) {
+ int diff = limit - inflight;
+
+ if (!inflight || diff >= rwb->wb_background / 2)
+ wake_up_all(&rqw->wait);
+ }
+}
+
+/*
+ * Called on completion of a request. Note that it's also called when
+ * a request is merged, when the request gets freed.
+ */
+void wbt_done(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+ if (!rwb)
+ return;
+
+ if (!wbt_is_tracked(stat)) {
+ if (rwb->sync_cookie == stat) {
+ rwb->sync_issue = 0;
+ rwb->sync_cookie = NULL;
+ }
+
+ if (wbt_is_read(stat))
+ wb_timestamp(rwb, &rwb->last_comp);
+ wbt_clear_state(stat);
+ } else {
+ WARN_ON_ONCE(stat == rwb->sync_cookie);
+ __wbt_done(rwb, wbt_stat_to_mask(stat));
+ wbt_clear_state(stat);
+ }
+}
+
+/*
+ * Return true, if we can't increase the depth further by scaling
+ */
+static bool calc_wb_limits(struct rq_wb *rwb)
+{
+ unsigned int depth;
+ bool ret = false;
+
+ if (!rwb->min_lat_nsec) {
+ rwb->wb_max = rwb->wb_normal = rwb->wb_background = 0;
+ return false;
+ }
+
+ /*
+ * For QD=1 devices, this is a special case. It's important for those
+ * to have one request ready when one completes, so force a depth of
+ * 2 for those devices. On the backend, it'll be a depth of 1 anyway,
+ * since the device can't have more than that in flight. If we're
+ * scaling down, then keep a setting of 1/1/1.
+ */
+ if (rwb->queue_depth == 1) {
+ if (rwb->scale_step > 0)
+ rwb->wb_max = rwb->wb_normal = 1;
+ else {
+ rwb->wb_max = rwb->wb_normal = 2;
+ ret = true;
+ }
+ rwb->wb_background = 1;
+ } else {
+ /*
+ * scale_step == 0 is our default state. If we have suffered
+ * latency spikes, step will be > 0, and we shrink the
+ * allowed write depths. If step is < 0, we're only doing
+ * writes, and we allow a temporarily higher depth to
+ * increase performance.
+ */
+ depth = min_t(unsigned int, RWB_DEF_DEPTH, rwb->queue_depth);
+ if (rwb->scale_step > 0)
+ depth = 1 + ((depth - 1) >> min(31, rwb->scale_step));
+ else if (rwb->scale_step < 0) {
+ unsigned int maxd = 3 * rwb->queue_depth / 4;
+
+ depth = 1 + ((depth - 1) << -rwb->scale_step);
+ if (depth > maxd) {
+ depth = maxd;
+ ret = true;
+ }
+ }
+
+ /*
+ * Set our max/normal/bg queue depths based on how far
+ * we have scaled down (->scale_step).
+ */
+ rwb->wb_max = depth;
+ rwb->wb_normal = (rwb->wb_max + 1) / 2;
+ rwb->wb_background = (rwb->wb_max + 3) / 4;
+ }
+
+ return ret;
+}
+
+static inline bool stat_sample_valid(struct blk_rq_stat *stat)
+{
+ /*
+ * We need at least one read sample, and a minimum of
+ * RWB_MIN_WRITE_SAMPLES. We require some write samples to know
+ * that it's writes impacting us, and not just some sole read on
+ * a device that is in a lower power state.
+ */
+ return stat[BLK_STAT_READ].nr_samples >= 1 &&
+ stat[BLK_STAT_WRITE].nr_samples >= RWB_MIN_WRITE_SAMPLES;
+}
+
+static u64 rwb_sync_issue_lat(struct rq_wb *rwb)
+{
+ u64 now, issue = ACCESS_ONCE(rwb->sync_issue);
+
+ if (!issue || !rwb->sync_cookie)
+ return 0;
+
+ now = ktime_to_ns(ktime_get());
+ return now - issue;
+}
+
+enum {
+ LAT_OK = 1,
+ LAT_UNKNOWN,
+ LAT_UNKNOWN_WRITES,
+ LAT_EXCEEDED,
+};
+
+static int __latency_exceeded(struct rq_wb *rwb, struct blk_rq_stat *stat)
+{
+ struct backing_dev_info *bdi = &rwb->queue->backing_dev_info;
+ u64 thislat;
+
+ /*
+ * If our stored sync issue exceeds the window size, or it
+ * exceeds our min target AND we haven't logged any entries,
+ * flag the latency as exceeded. wbt works off completion latencies,
+ * but for a flooded device, a single sync IO can take a long time
+ * to complete after being issued. If this time exceeds our
+ * monitoring window AND we didn't see any other completions in that
+ * window, then count that sync IO as a violation of the latency.
+ */
+ thislat = rwb_sync_issue_lat(rwb);
+ if (thislat > rwb->cur_win_nsec ||
+ (thislat > rwb->min_lat_nsec && !stat[BLK_STAT_READ].nr_samples)) {
+ trace_wbt_lat(bdi, thislat);
+ return LAT_EXCEEDED;
+ }
+
+ /*
+ * No read/write mix, if stat isn't valid
+ */
+ if (!stat_sample_valid(stat)) {
+ /*
+ * If we had writes in this stat window and the window is
+ * current, we're only doing writes. If a task recently
+ * waited or still has writes in flights, consider us doing
+ * just writes as well.
+ */
+ if ((stat[BLK_STAT_WRITE].nr_samples && blk_stat_is_current(stat)) ||
+ wb_recent_wait(rwb) || wbt_inflight(rwb))
+ return LAT_UNKNOWN_WRITES;
+ return LAT_UNKNOWN;
+ }
+
+ /*
+ * If the 'min' latency exceeds our target, step down.
+ */
+ if (stat[BLK_STAT_READ].min > rwb->min_lat_nsec) {
+ trace_wbt_lat(bdi, stat[BLK_STAT_READ].min);
+ trace_wbt_stat(bdi, stat);
+ return LAT_EXCEEDED;
+ }
+
+ if (rwb->scale_step)
+ trace_wbt_stat(bdi, stat);
+
+ return LAT_OK;
+}
+
+static int latency_exceeded(struct rq_wb *rwb)
+{
+ struct blk_rq_stat stat[2];
+
+ blk_queue_stat_get(rwb->queue, stat);
+ return __latency_exceeded(rwb, stat);
+}
+
+static void rwb_trace_step(struct rq_wb *rwb, const char *msg)
+{
+ struct backing_dev_info *bdi = &rwb->queue->backing_dev_info;
+
+ trace_wbt_step(bdi, msg, rwb->scale_step, rwb->cur_win_nsec,
+ rwb->wb_background, rwb->wb_normal, rwb->wb_max);
+}
+
+static void scale_up(struct rq_wb *rwb)
+{
+ /*
+ * Hit max in previous round, stop here
+ */
+ if (rwb->scaled_max)
+ return;
+
+ rwb->scale_step--;
+ rwb->unknown_cnt = 0;
+ blk_stat_clear(rwb->queue);
+
+ rwb->scaled_max = calc_wb_limits(rwb);
+
+ rwb_wake_all(rwb);
+
+ rwb_trace_step(rwb, "step up");
+}
+
+/*
+ * Scale rwb down. If 'hard_throttle' is set, do it quicker, since we
+ * had a latency violation.
+ */
+static void scale_down(struct rq_wb *rwb, bool hard_throttle)
+{
+ /*
+ * Stop scaling down when we've hit the limit. This also prevents
+ * ->scale_step from going to crazy values, if the device can't
+ * keep up.
+ */
+ if (rwb->wb_max == 1)
+ return;
+
+ if (rwb->scale_step < 0 && hard_throttle)
+ rwb->scale_step = 0;
+ else
+ rwb->scale_step++;
+
+ rwb->scaled_max = false;
+ rwb->unknown_cnt = 0;
+ blk_stat_clear(rwb->queue);
+ calc_wb_limits(rwb);
+ rwb_trace_step(rwb, "step down");
+}
+
+static void rwb_arm_timer(struct rq_wb *rwb)
+{
+ unsigned long expires;
+
+ if (rwb->scale_step > 0) {
+ /*
+ * We should speed this up, using some variant of a fast
+ * integer inverse square root calculation. Since we only do
+ * this for every window expiration, it's not a huge deal,
+ * though.
+ */
+ rwb->cur_win_nsec = div_u64(rwb->win_nsec << 4,
+ int_sqrt((rwb->scale_step + 1) << 8));
+ } else {
+ /*
+ * For step < 0, we don't want to increase/decrease the
+ * window size.
+ */
+ rwb->cur_win_nsec = rwb->win_nsec;
+ }
+
+ expires = jiffies + nsecs_to_jiffies(rwb->cur_win_nsec);
+ mod_timer(&rwb->window_timer, expires);
+}
+
+static void wb_timer_fn(unsigned long data)
+{
+ struct rq_wb *rwb = (struct rq_wb *) data;
+ unsigned int inflight = wbt_inflight(rwb);
+ int status;
+
+ status = latency_exceeded(rwb);
+
+ trace_wbt_timer(&rwb->queue->backing_dev_info, status, rwb->scale_step,
+ inflight);
+
+ /*
+ * If we exceeded the latency target, step down. If we did not,
+ * step one level up. If we don't know enough to say either exceeded
+ * or ok, then don't do anything.
+ */
+ switch (status) {
+ case LAT_EXCEEDED:
+ scale_down(rwb, true);
+ break;
+ case LAT_OK:
+ scale_up(rwb);
+ break;
+ case LAT_UNKNOWN_WRITES:
+ /*
+ * We started a the center step, but don't have a valid
+ * read/write sample, but we do have writes going on.
+ * Allow step to go negative, to increase write perf.
+ */
+ scale_up(rwb);
+ break;
+ case LAT_UNKNOWN:
+ if (++rwb->unknown_cnt < RWB_UNKNOWN_BUMP)
+ break;
+ /*
+ * We get here when previously scaled reduced depth, and we
+ * currently don't have a valid read/write sample. For that
+ * case, slowly return to center state (step == 0).
+ */
+ if (rwb->scale_step > 0)
+ scale_up(rwb);
+ else if (rwb->scale_step < 0)
+ scale_down(rwb, false);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Re-arm timer, if we have IO in flight
+ */
+ if (rwb->scale_step || inflight)
+ rwb_arm_timer(rwb);
+}
+
+void wbt_update_limits(struct rq_wb *rwb)
+{
+ rwb->scale_step = 0;
+ rwb->scaled_max = false;
+ calc_wb_limits(rwb);
+
+ rwb_wake_all(rwb);
+}
+
+static bool close_io(struct rq_wb *rwb)
+{
+ const unsigned long now = jiffies;
+
+ return time_before(now, rwb->last_issue + HZ / 10) ||
+ time_before(now, rwb->last_comp + HZ / 10);
+}
+
+#define REQ_HIPRIO (REQ_SYNC | REQ_META | REQ_PRIO)
+
+static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
+{
+ unsigned int limit;
+
+ /*
+ * At this point we know it's a buffered write. If this is
+ * kswapd trying to free memory, or REQ_SYNC is set, set, then
+ * it's WB_SYNC_ALL writeback, and we'll use the max limit for
+ * that. If the write is marked as a background write, then use
+ * the idle limit, or go to normal if we haven't had competing
+ * IO for a bit.
+ */
+ if ((rw & REQ_HIPRIO) || wb_recent_wait(rwb) || current_is_kswapd())
+ limit = rwb->wb_max;
+ else if ((rw & REQ_BACKGROUND) || close_io(rwb)) {
+ /*
+ * If less than 100ms since we completed unrelated IO,
+ * limit us to half the depth for background writeback.
+ */
+ limit = rwb->wb_background;
+ } else
+ limit = rwb->wb_normal;
+
+ return limit;
+}
+
+static inline bool may_queue(struct rq_wb *rwb, struct rq_wait *rqw,
+ wait_queue_t *wait, unsigned long rw)
+{
+ /*
+ * inc it here even if disabled, since we'll dec it at completion.
+ * this only happens if the task was sleeping in __wbt_wait(),
+ * and someone turned it off at the same time.
+ */
+ if (!rwb_enabled(rwb)) {
+ atomic_inc(&rqw->inflight);
+ return true;
+ }
+
+ /*
+ * If the waitqueue is already active and we are not the next
+ * in line to be woken up, wait for our turn.
+ */
+ if (waitqueue_active(&rqw->wait) &&
+ rqw->wait.task_list.next != &wait->task_list)
+ return false;
+
+ return atomic_inc_below(&rqw->inflight, get_limit(rwb, rw));
+}
+
+/*
+ * Block if we will exceed our limit, or if we are currently waiting for
+ * the timer to kick off queuing again.
+ */
+static void __wbt_wait(struct rq_wb *rwb, unsigned long rw, spinlock_t *lock)
+{
+ struct rq_wait *rqw = get_rq_wait(rwb, current_is_kswapd());
+ DEFINE_WAIT(wait);
+
+ if (may_queue(rwb, rqw, &wait, rw))
+ return;
+
+ do {
+ prepare_to_wait_exclusive(&rqw->wait, &wait,
+ TASK_UNINTERRUPTIBLE);
+
+ if (may_queue(rwb, rqw, &wait, rw))
+ break;
+
+ if (lock)
+ spin_unlock_irq(lock);
+
+ io_schedule();
+
+ if (lock)
+ spin_lock_irq(lock);
+ } while (1);
+
+ finish_wait(&rqw->wait, &wait);
+}
+
+static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio)
+{
+ const int op = bio_op(bio);
+
+ /*
+ * If not a WRITE, do nothing
+ */
+ if (op != REQ_OP_WRITE)
+ return false;
+
+ /*
+ * Don't throttle WRITE_ODIRECT
+ */
+ if ((bio->bi_opf & (REQ_SYNC | REQ_IDLE)) == (REQ_SYNC | REQ_IDLE))
+ return false;
+
+ return true;
+}
+
+/*
+ * Returns true if the IO request should be accounted, false if not.
+ * May sleep, if we have exceeded the writeback limits. Caller can pass
+ * in an irq held spinlock, if it holds one when calling this function.
+ * If we do sleep, we'll release and re-grab it.
+ */
+unsigned int wbt_wait(struct rq_wb *rwb, struct bio *bio, spinlock_t *lock)
+{
+ unsigned int ret = 0;
+
+ if (!rwb_enabled(rwb))
+ return 0;
+
+ if (bio_op(bio) == REQ_OP_READ)
+ ret = WBT_READ;
+
+ if (!wbt_should_throttle(rwb, bio)) {
+ if (ret & WBT_READ)
+ wb_timestamp(rwb, &rwb->last_issue);
+ return ret;
+ }
+
+ __wbt_wait(rwb, bio->bi_opf, lock);
+
+ if (!timer_pending(&rwb->window_timer))
+ rwb_arm_timer(rwb);
+
+ if (current_is_kswapd())
+ ret |= WBT_KSWAPD;
+
+ return ret | WBT_TRACKED;
+}
+
+void wbt_issue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+ if (!rwb_enabled(rwb))
+ return;
+
+ /*
+ * Track sync issue, in case it takes a long time to complete. Allows
+ * us to react quicker, if a sync IO takes a long time to complete.
+ * Note that this is just a hint. 'stat' can go away when the
+ * request completes, so it's important we never dereference it. We
+ * only use the address to compare with, which is why we store the
+ * sync_issue time locally.
+ */
+ if (wbt_is_read(stat) && !rwb->sync_issue) {
+ rwb->sync_cookie = stat;
+ rwb->sync_issue = blk_stat_time(stat);
+ }
+}
+
+void wbt_requeue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+ if (!rwb_enabled(rwb))
+ return;
+ if (stat == rwb->sync_cookie) {
+ rwb->sync_issue = 0;
+ rwb->sync_cookie = NULL;
+ }
+}
+
+void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth)
+{
+ if (rwb) {
+ rwb->queue_depth = depth;
+ wbt_update_limits(rwb);
+ }
+}
+
+void wbt_set_write_cache(struct rq_wb *rwb, bool write_cache_on)
+{
+ if (rwb)
+ rwb->wc = write_cache_on;
+}
+
+ /*
+ * Disable wbt, if enabled by default. Only called from CFQ, if we have
+ * cgroups enabled
+ */
+void wbt_disable_default(struct request_queue *q)
+{
+ struct rq_wb *rwb = q->rq_wb;
+
+ if (rwb && rwb->enable_state == WBT_STATE_ON_DEFAULT) {
+ del_timer_sync(&rwb->window_timer);
+ rwb->win_nsec = rwb->min_lat_nsec = 0;
+ wbt_update_limits(rwb);
+ }
+}
+EXPORT_SYMBOL_GPL(wbt_disable_default);
+
+u64 wbt_default_latency_nsec(struct request_queue *q)
+{
+ /*
+ * We default to 2msec for non-rotational storage, and 75msec
+ * for rotational storage.
+ */
+ if (blk_queue_nonrot(q))
+ return 2000000ULL;
+ else
+ return 75000000ULL;
+}
+
+int wbt_init(struct request_queue *q)
+{
+ struct rq_wb *rwb;
+ int i;
+
+ /*
+ * For now, we depend on the stats window being larger than
+ * our monitoring window. Ensure that this isn't inadvertently
+ * violated.
+ */
+ BUILD_BUG_ON(RWB_WINDOW_NSEC > BLK_STAT_NSEC);
+ BUILD_BUG_ON(WBT_NR_BITS > BLK_STAT_RES_BITS);
+
+ rwb = kzalloc(sizeof(*rwb), GFP_KERNEL);
+ if (!rwb)
+ return -ENOMEM;
+
+ for (i = 0; i < WBT_NUM_RWQ; i++) {
+ atomic_set(&rwb->rq_wait[i].inflight, 0);
+ init_waitqueue_head(&rwb->rq_wait[i].wait);
+ }
+
+ setup_timer(&rwb->window_timer, wb_timer_fn, (unsigned long) rwb);
+ rwb->wc = 1;
+ rwb->queue_depth = RWB_DEF_DEPTH;
+ rwb->last_comp = rwb->last_issue = jiffies;
+ rwb->queue = q;
+ rwb->win_nsec = RWB_WINDOW_NSEC;
+ rwb->enable_state = WBT_STATE_ON_DEFAULT;
+ wbt_update_limits(rwb);
+
+ /*
+ * Assign rwb, and turn on stats tracking for this queue
+ */
+ q->rq_wb = rwb;
+ blk_stat_enable(q);
+
+ rwb->min_lat_nsec = wbt_default_latency_nsec(q);
+
+ wbt_set_queue_depth(rwb, blk_queue_depth(q));
+ wbt_set_write_cache(rwb, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
+
+ return 0;
+}
+
+void wbt_exit(struct request_queue *q)
+{
+ struct rq_wb *rwb = q->rq_wb;
+
+ if (rwb) {
+ del_timer_sync(&rwb->window_timer);
+ q->rq_wb = NULL;
+ kfree(rwb);
+ }
+}
diff --git a/block/blk-wbt.h b/block/blk-wbt.h
new file mode 100644
index 000000000000..65f1de519f67
--- /dev/null
+++ b/block/blk-wbt.h
@@ -0,0 +1,171 @@
+#ifndef WB_THROTTLE_H
+#define WB_THROTTLE_H
+
+#include <linux/kernel.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+#include <linux/ktime.h>
+
+#include "blk-stat.h"
+
+enum wbt_flags {
+ WBT_TRACKED = 1, /* write, tracked for throttling */
+ WBT_READ = 2, /* read */
+ WBT_KSWAPD = 4, /* write, from kswapd */
+
+ WBT_NR_BITS = 3, /* number of bits */
+};
+
+enum {
+ WBT_NUM_RWQ = 2,
+};
+
+/*
+ * Enable states. Either off, or on by default (done at init time),
+ * or on through manual setup in sysfs.
+ */
+enum {
+ WBT_STATE_ON_DEFAULT = 1,
+ WBT_STATE_ON_MANUAL = 2,
+};
+
+static inline void wbt_clear_state(struct blk_issue_stat *stat)
+{
+ stat->time &= BLK_STAT_TIME_MASK;
+}
+
+static inline enum wbt_flags wbt_stat_to_mask(struct blk_issue_stat *stat)
+{
+ return (stat->time & BLK_STAT_MASK) >> BLK_STAT_SHIFT;
+}
+
+static inline void wbt_track(struct blk_issue_stat *stat, enum wbt_flags wb_acct)
+{
+ stat->time |= ((u64) wb_acct) << BLK_STAT_SHIFT;
+}
+
+static inline bool wbt_is_tracked(struct blk_issue_stat *stat)
+{
+ return (stat->time >> BLK_STAT_SHIFT) & WBT_TRACKED;
+}
+
+static inline bool wbt_is_read(struct blk_issue_stat *stat)
+{
+ return (stat->time >> BLK_STAT_SHIFT) & WBT_READ;
+}
+
+struct rq_wait {
+ wait_queue_head_t wait;
+ atomic_t inflight;
+};
+
+struct rq_wb {
+ /*
+ * Settings that govern how we throttle
+ */
+ unsigned int wb_background; /* background writeback */
+ unsigned int wb_normal; /* normal writeback */
+ unsigned int wb_max; /* max throughput writeback */
+ int scale_step;
+ bool scaled_max;
+
+ short enable_state; /* WBT_STATE_* */
+
+ /*
+ * Number of consecutive periods where we don't have enough
+ * information to make a firm scale up/down decision.
+ */
+ unsigned int unknown_cnt;
+
+ u64 win_nsec; /* default window size */
+ u64 cur_win_nsec; /* current window size */
+
+ struct timer_list window_timer;
+
+ s64 sync_issue;
+ void *sync_cookie;
+
+ unsigned int wc;
+ unsigned int queue_depth;
+
+ unsigned long last_issue; /* last non-throttled issue */
+ unsigned long last_comp; /* last non-throttled comp */
+ unsigned long min_lat_nsec;
+ struct request_queue *queue;
+ struct rq_wait rq_wait[WBT_NUM_RWQ];
+};
+
+static inline unsigned int wbt_inflight(struct rq_wb *rwb)
+{
+ unsigned int i, ret = 0;
+
+ for (i = 0; i < WBT_NUM_RWQ; i++)
+ ret += atomic_read(&rwb->rq_wait[i].inflight);
+
+ return ret;
+}
+
+#ifdef CONFIG_BLK_WBT
+
+void __wbt_done(struct rq_wb *, enum wbt_flags);
+void wbt_done(struct rq_wb *, struct blk_issue_stat *);
+enum wbt_flags wbt_wait(struct rq_wb *, struct bio *, spinlock_t *);
+int wbt_init(struct request_queue *);
+void wbt_exit(struct request_queue *);
+void wbt_update_limits(struct rq_wb *);
+void wbt_requeue(struct rq_wb *, struct blk_issue_stat *);
+void wbt_issue(struct rq_wb *, struct blk_issue_stat *);
+void wbt_disable_default(struct request_queue *);
+
+void wbt_set_queue_depth(struct rq_wb *, unsigned int);
+void wbt_set_write_cache(struct rq_wb *, bool);
+
+u64 wbt_default_latency_nsec(struct request_queue *);
+
+#else
+
+static inline void __wbt_done(struct rq_wb *rwb, enum wbt_flags flags)
+{
+}
+static inline void wbt_done(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline enum wbt_flags wbt_wait(struct rq_wb *rwb, struct bio *bio,
+ spinlock_t *lock)
+{
+ return 0;
+}
+static inline int wbt_init(struct request_queue *q)
+{
+ return -EINVAL;
+}
+static inline void wbt_exit(struct request_queue *q)
+{
+}
+static inline void wbt_update_limits(struct rq_wb *rwb)
+{
+}
+static inline void wbt_requeue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline void wbt_issue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline void wbt_disable_default(struct request_queue *q)
+{
+}
+static inline void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth)
+{
+}
+static inline void wbt_set_write_cache(struct rq_wb *rwb, bool wc)
+{
+}
+static inline u64 wbt_default_latency_nsec(struct request_queue *q)
+{
+ return 0;
+}
+
+#endif /* CONFIG_BLK_WBT */
+
+#endif
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
new file mode 100644
index 000000000000..472211fa183a
--- /dev/null
+++ b/block/blk-zoned.c
@@ -0,0 +1,348 @@
+/*
+ * Zoned block device handling
+ *
+ * Copyright (c) 2015, Hannes Reinecke
+ * Copyright (c) 2015, SUSE Linux GmbH
+ *
+ * Copyright (c) 2016, Damien Le Moal
+ * Copyright (c) 2016, Western Digital
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/blkdev.h>
+
+static inline sector_t blk_zone_start(struct request_queue *q,
+ sector_t sector)
+{
+ sector_t zone_mask = blk_queue_zone_size(q) - 1;
+
+ return sector & ~zone_mask;
+}
+
+/*
+ * Check that a zone report belongs to the partition.
+ * If yes, fix its start sector and write pointer, copy it in the
+ * zone information array and return true. Return false otherwise.
+ */
+static bool blkdev_report_zone(struct block_device *bdev,
+ struct blk_zone *rep,
+ struct blk_zone *zone)
+{
+ sector_t offset = get_start_sect(bdev);
+
+ if (rep->start < offset)
+ return false;
+
+ rep->start -= offset;
+ if (rep->start + rep->len > bdev->bd_part->nr_sects)
+ return false;
+
+ if (rep->type == BLK_ZONE_TYPE_CONVENTIONAL)
+ rep->wp = rep->start + rep->len;
+ else
+ rep->wp -= offset;
+ memcpy(zone, rep, sizeof(struct blk_zone));
+
+ return true;
+}
+
+/**
+ * blkdev_report_zones - Get zones information
+ * @bdev: Target block device
+ * @sector: Sector from which to report zones
+ * @zones: Array of zone structures where to return the zones information
+ * @nr_zones: Number of zone structures in the zone array
+ * @gfp_mask: Memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ * Get zone information starting from the zone containing @sector.
+ * The number of zone information reported may be less than the number
+ * requested by @nr_zones. The number of zones actually reported is
+ * returned in @nr_zones.
+ */
+int blkdev_report_zones(struct block_device *bdev,
+ sector_t sector,
+ struct blk_zone *zones,
+ unsigned int *nr_zones,
+ gfp_t gfp_mask)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+ struct blk_zone_report_hdr *hdr;
+ unsigned int nrz = *nr_zones;
+ struct page *page;
+ unsigned int nr_rep;
+ size_t rep_bytes;
+ unsigned int nr_pages;
+ struct bio *bio;
+ struct bio_vec *bv;
+ unsigned int i, n, nz;
+ unsigned int ofst;
+ void *addr;
+ int ret;
+
+ if (!q)
+ return -ENXIO;
+
+ if (!blk_queue_is_zoned(q))
+ return -EOPNOTSUPP;
+
+ if (!nrz)
+ return 0;
+
+ if (sector > bdev->bd_part->nr_sects) {
+ *nr_zones = 0;
+ return 0;
+ }
+
+ /*
+ * The zone report has a header. So make room for it in the
+ * payload. Also make sure that the report fits in a single BIO
+ * that will not be split down the stack.
+ */
+ rep_bytes = sizeof(struct blk_zone_report_hdr) +
+ sizeof(struct blk_zone) * nrz;
+ rep_bytes = (rep_bytes + PAGE_SIZE - 1) & PAGE_MASK;
+ if (rep_bytes > (queue_max_sectors(q) << 9))
+ rep_bytes = queue_max_sectors(q) << 9;
+
+ nr_pages = min_t(unsigned int, BIO_MAX_PAGES,
+ rep_bytes >> PAGE_SHIFT);
+ nr_pages = min_t(unsigned int, nr_pages,
+ queue_max_segments(q));
+
+ bio = bio_alloc(gfp_mask, nr_pages);
+ if (!bio)
+ return -ENOMEM;
+
+ bio->bi_bdev = bdev;
+ bio->bi_iter.bi_sector = blk_zone_start(q, sector);
+ bio_set_op_attrs(bio, REQ_OP_ZONE_REPORT, 0);
+
+ for (i = 0; i < nr_pages; i++) {
+ page = alloc_page(gfp_mask);
+ if (!page) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (!bio_add_page(bio, page, PAGE_SIZE, 0)) {
+ __free_page(page);
+ break;
+ }
+ }
+
+ if (i == 0)
+ ret = -ENOMEM;
+ else
+ ret = submit_bio_wait(bio);
+ if (ret)
+ goto out;
+
+ /*
+ * Process the report result: skip the header and go through the
+ * reported zones to fixup and fixup the zone information for
+ * partitions. At the same time, return the zone information into
+ * the zone array.
+ */
+ n = 0;
+ nz = 0;
+ nr_rep = 0;
+ bio_for_each_segment_all(bv, bio, i) {
+
+ if (!bv->bv_page)
+ break;
+
+ addr = kmap_atomic(bv->bv_page);
+
+ /* Get header in the first page */
+ ofst = 0;
+ if (!nr_rep) {
+ hdr = (struct blk_zone_report_hdr *) addr;
+ nr_rep = hdr->nr_zones;
+ ofst = sizeof(struct blk_zone_report_hdr);
+ }
+
+ /* Fixup and report zones */
+ while (ofst < bv->bv_len &&
+ n < nr_rep && nz < nrz) {
+ if (blkdev_report_zone(bdev, addr + ofst, &zones[nz]))
+ nz++;
+ ofst += sizeof(struct blk_zone);
+ n++;
+ }
+
+ kunmap_atomic(addr);
+
+ if (n >= nr_rep || nz >= nrz)
+ break;
+
+ }
+
+ *nr_zones = nz;
+out:
+ bio_for_each_segment_all(bv, bio, i)
+ __free_page(bv->bv_page);
+ bio_put(bio);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(blkdev_report_zones);
+
+/**
+ * blkdev_reset_zones - Reset zones write pointer
+ * @bdev: Target block device
+ * @sector: Start sector of the first zone to reset
+ * @nr_sectors: Number of sectors, at least the length of one zone
+ * @gfp_mask: Memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ * Reset the write pointer of the zones contained in the range
+ * @sector..@sector+@nr_sectors. Specifying the entire disk sector range
+ * is valid, but the specified range should not contain conventional zones.
+ */
+int blkdev_reset_zones(struct block_device *bdev,
+ sector_t sector, sector_t nr_sectors,
+ gfp_t gfp_mask)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+ sector_t zone_sectors;
+ sector_t end_sector = sector + nr_sectors;
+ struct bio *bio;
+ int ret;
+
+ if (!q)
+ return -ENXIO;
+
+ if (!blk_queue_is_zoned(q))
+ return -EOPNOTSUPP;
+
+ if (end_sector > bdev->bd_part->nr_sects)
+ /* Out of range */
+ return -EINVAL;
+
+ /* Check alignment (handle eventual smaller last zone) */
+ zone_sectors = blk_queue_zone_size(q);
+ if (sector & (zone_sectors - 1))
+ return -EINVAL;
+
+ if ((nr_sectors & (zone_sectors - 1)) &&
+ end_sector != bdev->bd_part->nr_sects)
+ return -EINVAL;
+
+ while (sector < end_sector) {
+
+ bio = bio_alloc(gfp_mask, 0);
+ bio->bi_iter.bi_sector = sector;
+ bio->bi_bdev = bdev;
+ bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0);
+
+ ret = submit_bio_wait(bio);
+ bio_put(bio);
+
+ if (ret)
+ return ret;
+
+ sector += zone_sectors;
+
+ /* This may take a while, so be nice to others */
+ cond_resched();
+
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(blkdev_reset_zones);
+
+/**
+ * BLKREPORTZONE ioctl processing.
+ * Called from blkdev_ioctl.
+ */
+int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct request_queue *q;
+ struct blk_zone_report rep;
+ struct blk_zone *zones;
+ int ret;
+
+ if (!argp)
+ return -EINVAL;
+
+ q = bdev_get_queue(bdev);
+ if (!q)
+ return -ENXIO;
+
+ if (!blk_queue_is_zoned(q))
+ return -ENOTTY;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (copy_from_user(&rep, argp, sizeof(struct blk_zone_report)))
+ return -EFAULT;
+
+ if (!rep.nr_zones)
+ return -EINVAL;
+
+ zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL);
+ if (!zones)
+ return -ENOMEM;
+
+ ret = blkdev_report_zones(bdev, rep.sector,
+ zones, &rep.nr_zones,
+ GFP_KERNEL);
+ if (ret)
+ goto out;
+
+ if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (rep.nr_zones) {
+ if (copy_to_user(argp + sizeof(struct blk_zone_report), zones,
+ sizeof(struct blk_zone) * rep.nr_zones))
+ ret = -EFAULT;
+ }
+
+ out:
+ kfree(zones);
+
+ return ret;
+}
+
+/**
+ * BLKRESETZONE ioctl processing.
+ * Called from blkdev_ioctl.
+ */
+int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct request_queue *q;
+ struct blk_zone_range zrange;
+
+ if (!argp)
+ return -EINVAL;
+
+ q = bdev_get_queue(bdev);
+ if (!q)
+ return -ENXIO;
+
+ if (!blk_queue_is_zoned(q))
+ return -ENOTTY;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (!(mode & FMODE_WRITE))
+ return -EBADF;
+
+ if (copy_from_user(&zrange, argp, sizeof(struct blk_zone_range)))
+ return -EFAULT;
+
+ return blkdev_reset_zones(bdev, zrange.sector, zrange.nr_sectors,
+ GFP_KERNEL);
+}
diff --git a/block/blk.h b/block/blk.h
index 74444c49078f..041185e5f129 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -111,6 +111,7 @@ void blk_account_io_done(struct request *req);
enum rq_atomic_flags {
REQ_ATOM_COMPLETE = 0,
REQ_ATOM_STARTED,
+ REQ_ATOM_POLL_SLEPT,
};
/*
@@ -130,7 +131,7 @@ static inline void blk_clear_rq_complete(struct request *rq)
/*
* Internal elevator interface
*/
-#define ELV_ON_HASH(rq) ((rq)->cmd_flags & REQ_HASHED)
+#define ELV_ON_HASH(rq) ((rq)->rq_flags & RQF_HASHED)
void blk_insert_flush(struct request *rq);
@@ -247,7 +248,7 @@ extern int blk_update_nr_requests(struct request_queue *, unsigned int);
static inline int blk_do_io_stat(struct request *rq)
{
return rq->rq_disk &&
- (rq->cmd_flags & REQ_IO_STAT) &&
+ (rq->rq_flags & RQF_IO_STAT) &&
(rq->cmd_type == REQ_TYPE_FS);
}
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 650f427d915b..b2a61e3ecb14 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -161,6 +161,8 @@ failjob_rls_job:
* Drivers/subsys should pass this to the queue init function.
*/
void bsg_request_fn(struct request_queue *q)
+ __releases(q->queue_lock)
+ __acquires(q->queue_lock)
{
struct device *dev = q->queuedata;
struct request *req;
diff --git a/block/bsg.c b/block/bsg.c
index d214e929ce18..8a05a404ae70 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -176,7 +176,7 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
* Check if sg_io_v4 from user is allowed and valid
*/
static int
-bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
+bsg_validate_sgv4_hdr(struct sg_io_v4 *hdr, int *rw)
{
int ret = 0;
@@ -226,7 +226,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
hdr->din_xfer_len);
- ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
+ ret = bsg_validate_sgv4_hdr(hdr, &rw);
if (ret)
return ERR_PTR(ret);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 5e24d880306c..c73a6fcaeb9d 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -16,6 +16,7 @@
#include <linux/blktrace_api.h>
#include <linux/blk-cgroup.h>
#include "blk.h"
+#include "blk-wbt.h"
/*
* tunables
@@ -667,10 +668,10 @@ static inline void cfqg_put(struct cfq_group *cfqg)
} while (0)
static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg,
- struct cfq_group *curr_cfqg, int op,
- int op_flags)
+ struct cfq_group *curr_cfqg,
+ unsigned int op)
{
- blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, 1);
+ blkg_rwstat_add(&cfqg->stats.queued, op, 1);
cfqg_stats_end_empty_time(&cfqg->stats);
cfqg_stats_set_start_group_wait_time(cfqg, curr_cfqg);
}
@@ -684,30 +685,29 @@ static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg,
#endif
}
-static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op,
- int op_flags)
+static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg,
+ unsigned int op)
{
- blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, -1);
+ blkg_rwstat_add(&cfqg->stats.queued, op, -1);
}
-static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op,
- int op_flags)
+static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg,
+ unsigned int op)
{
- blkg_rwstat_add(&cfqg->stats.merged, op, op_flags, 1);
+ blkg_rwstat_add(&cfqg->stats.merged, op, 1);
}
static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
- uint64_t start_time, uint64_t io_start_time, int op,
- int op_flags)
+ uint64_t start_time, uint64_t io_start_time,
+ unsigned int op)
{
struct cfqg_stats *stats = &cfqg->stats;
unsigned long long now = sched_clock();
if (time_after64(now, io_start_time))
- blkg_rwstat_add(&stats->service_time, op, op_flags,
- now - io_start_time);
+ blkg_rwstat_add(&stats->service_time, op, now - io_start_time);
if (time_after64(io_start_time, start_time))
- blkg_rwstat_add(&stats->wait_time, op, op_flags,
+ blkg_rwstat_add(&stats->wait_time, op,
io_start_time - start_time);
}
@@ -786,16 +786,16 @@ static inline void cfqg_put(struct cfq_group *cfqg) { }
#define cfq_log_cfqg(cfqd, cfqg, fmt, args...) do {} while (0)
static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg,
- struct cfq_group *curr_cfqg, int op, int op_flags) { }
+ struct cfq_group *curr_cfqg, unsigned int op) { }
static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg,
uint64_t time, unsigned long unaccounted_time) { }
-static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op,
- int op_flags) { }
-static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op,
- int op_flags) { }
+static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg,
+ unsigned int op) { }
+static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg,
+ unsigned int op) { }
static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
- uint64_t start_time, uint64_t io_start_time, int op,
- int op_flags) { }
+ uint64_t start_time, uint64_t io_start_time,
+ unsigned int op) { }
#endif /* CONFIG_CFQ_GROUP_IOSCHED */
@@ -913,15 +913,6 @@ static inline struct cfq_data *cic_to_cfqd(struct cfq_io_cq *cic)
}
/*
- * We regard a request as SYNC, if it's either a read or has the SYNC bit
- * set (in which case it could also be direct WRITE).
- */
-static inline bool cfq_bio_sync(struct bio *bio)
-{
- return bio_data_dir(bio) == READ || (bio->bi_opf & REQ_SYNC);
-}
-
-/*
* scheduler run of queue, if there are requests pending and no one in the
* driver that will restart queueing
*/
@@ -1596,7 +1587,7 @@ static struct blkcg_policy_data *cfq_cpd_alloc(gfp_t gfp)
{
struct cfq_group_data *cgd;
- cgd = kzalloc(sizeof(*cgd), GFP_KERNEL);
+ cgd = kzalloc(sizeof(*cgd), gfp);
if (!cgd)
return NULL;
return &cgd->cpd;
@@ -2474,10 +2465,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq)
{
elv_rb_del(&cfqq->sort_list, rq);
cfqq->queued[rq_is_sync(rq)]--;
- cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags);
+ cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags);
cfq_add_rq_rb(rq);
cfqg_stats_update_io_add(RQ_CFQG(rq), cfqq->cfqd->serving_group,
- req_op(rq), rq->cmd_flags);
+ rq->cmd_flags);
}
static struct request *
@@ -2491,7 +2482,7 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
if (!cic)
return NULL;
- cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
+ cfqq = cic_to_cfqq(cic, op_is_sync(bio->bi_opf));
if (cfqq)
return elv_rb_find(&cfqq->sort_list, bio_end_sector(bio));
@@ -2530,7 +2521,7 @@ static void cfq_remove_request(struct request *rq)
cfq_del_rq_rb(rq);
cfqq->cfqd->rq_queued--;
- cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags);
+ cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags);
if (rq->cmd_flags & REQ_PRIO) {
WARN_ON(!cfqq->prio_pending);
cfqq->prio_pending--;
@@ -2565,7 +2556,7 @@ static void cfq_merged_request(struct request_queue *q, struct request *req,
static void cfq_bio_merged(struct request_queue *q, struct request *req,
struct bio *bio)
{
- cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_opf);
+ cfqg_stats_update_io_merged(RQ_CFQG(req), bio->bi_opf);
}
static void
@@ -2588,7 +2579,7 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
if (cfqq->next_rq == next)
cfqq->next_rq = rq;
cfq_remove_request(next);
- cfqg_stats_update_io_merged(RQ_CFQG(rq), req_op(next), next->cmd_flags);
+ cfqg_stats_update_io_merged(RQ_CFQG(rq), next->cmd_flags);
cfqq = RQ_CFQQ(next);
/*
@@ -2605,13 +2596,14 @@ static int cfq_allow_bio_merge(struct request_queue *q, struct request *rq,
struct bio *bio)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
+ bool is_sync = op_is_sync(bio->bi_opf);
struct cfq_io_cq *cic;
struct cfq_queue *cfqq;
/*
* Disallow merge of a sync bio into an async request.
*/
- if (cfq_bio_sync(bio) && !rq_is_sync(rq))
+ if (is_sync && !rq_is_sync(rq))
return false;
/*
@@ -2622,7 +2614,7 @@ static int cfq_allow_bio_merge(struct request_queue *q, struct request *rq,
if (!cic)
return false;
- cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
+ cfqq = cic_to_cfqq(cic, is_sync);
return cfqq == RQ_CFQQ(rq);
}
@@ -3771,9 +3763,11 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
struct cfq_data *cfqd = cic_to_cfqd(cic);
struct cfq_queue *cfqq;
uint64_t serial_nr;
+ bool nonroot_cg;
rcu_read_lock();
serial_nr = bio_blkcg(bio)->css.serial_nr;
+ nonroot_cg = bio_blkcg(bio) != &blkcg_root;
rcu_read_unlock();
/*
@@ -3784,6 +3778,14 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
return;
/*
+ * If we have a non-root cgroup, we can depend on that to
+ * do proper throttling of writes. Turn off wbt for that
+ * case, if it was enabled by default.
+ */
+ if (nonroot_cg)
+ wbt_disable_default(cfqd->queue);
+
+ /*
* Drop reference to queues. New queues will be assigned in new
* group upon arrival of fresh requests.
*/
@@ -3854,7 +3856,8 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,
goto out;
}
- cfqq = kmem_cache_alloc_node(cfq_pool, GFP_NOWAIT | __GFP_ZERO,
+ cfqq = kmem_cache_alloc_node(cfq_pool,
+ GFP_NOWAIT | __GFP_ZERO | __GFP_NOWARN,
cfqd->queue->node);
if (!cfqq) {
cfqq = &cfqd->oom_cfqq;
@@ -3923,6 +3926,12 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cfqq->seek_history |= (sdist > CFQQ_SEEK_THR);
}
+static inline bool req_noidle(struct request *req)
+{
+ return req_op(req) == REQ_OP_WRITE &&
+ (req->cmd_flags & (REQ_SYNC | REQ_IDLE)) == REQ_SYNC;
+}
+
/*
* Disable idle window if the process thinks too long or seeks so much that
* it doesn't matter
@@ -3944,7 +3953,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (cfqq->queued[0] + cfqq->queued[1] >= 4)
cfq_mark_cfqq_deep(cfqq);
- if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+ if (cfqq->next_rq && req_noidle(cfqq->next_rq))
enable_idle = 0;
else if (!atomic_read(&cic->icq.ioc->active_ref) ||
!cfqd->cfq_slice_idle ||
@@ -4142,7 +4151,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
rq->fifo_time = ktime_get_ns() + cfqd->cfq_fifo_expire[rq_is_sync(rq)];
list_add_tail(&rq->queuelist, &cfqq->fifo);
cfq_add_rq_rb(rq);
- cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, req_op(rq),
+ cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group,
rq->cmd_flags);
cfq_rq_enqueued(cfqd, cfqq, rq);
}
@@ -4229,8 +4238,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
const int sync = rq_is_sync(rq);
u64 now = ktime_get_ns();
- cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d",
- !!(rq->cmd_flags & REQ_NOIDLE));
+ cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", req_noidle(rq));
cfq_update_hw_tag(cfqd);
@@ -4240,8 +4248,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
cfqq->dispatched--;
(RQ_CFQG(rq))->dispatched--;
cfqg_stats_update_completion(cfqq->cfqg, rq_start_time_ns(rq),
- rq_io_start_time_ns(rq), req_op(rq),
- rq->cmd_flags);
+ rq_io_start_time_ns(rq), rq->cmd_flags);
cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
@@ -4319,14 +4326,14 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
cfq_schedule_dispatch(cfqd);
}
-static void cfqq_boost_on_prio(struct cfq_queue *cfqq, int op_flags)
+static void cfqq_boost_on_prio(struct cfq_queue *cfqq, unsigned int op)
{
/*
* If REQ_PRIO is set, boost class and prio level, if it's below
* BE/NORM. If prio is not set, restore the potentially boosted
* class/prio level.
*/
- if (!(op_flags & REQ_PRIO)) {
+ if (!(op & REQ_PRIO)) {
cfqq->ioprio_class = cfqq->org_ioprio_class;
cfqq->ioprio = cfqq->org_ioprio;
} else {
@@ -4347,7 +4354,7 @@ static inline int __cfq_may_queue(struct cfq_queue *cfqq)
return ELV_MQUEUE_MAY;
}
-static int cfq_may_queue(struct request_queue *q, int op, int op_flags)
+static int cfq_may_queue(struct request_queue *q, unsigned int op)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
@@ -4364,10 +4371,10 @@ static int cfq_may_queue(struct request_queue *q, int op, int op_flags)
if (!cic)
return ELV_MQUEUE_MAY;
- cfqq = cic_to_cfqq(cic, rw_is_sync(op, op_flags));
+ cfqq = cic_to_cfqq(cic, op_is_sync(op));
if (cfqq) {
cfq_init_prio_data(cfqq, cic);
- cfqq_boost_on_prio(cfqq, op_flags);
+ cfqq_boost_on_prio(cfqq, op);
return __cfq_may_queue(cfqq);
}
diff --git a/block/elevator.c b/block/elevator.c
index f7d973a56fd7..40f0c04e5ad3 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -245,31 +245,31 @@ EXPORT_SYMBOL(elevator_exit);
static inline void __elv_rqhash_del(struct request *rq)
{
hash_del(&rq->hash);
- rq->cmd_flags &= ~REQ_HASHED;
+ rq->rq_flags &= ~RQF_HASHED;
}
-static void elv_rqhash_del(struct request_queue *q, struct request *rq)
+void elv_rqhash_del(struct request_queue *q, struct request *rq)
{
if (ELV_ON_HASH(rq))
__elv_rqhash_del(rq);
}
-static void elv_rqhash_add(struct request_queue *q, struct request *rq)
+void elv_rqhash_add(struct request_queue *q, struct request *rq)
{
struct elevator_queue *e = q->elevator;
BUG_ON(ELV_ON_HASH(rq));
hash_add(e->hash, &rq->hash, rq_hash_key(rq));
- rq->cmd_flags |= REQ_HASHED;
+ rq->rq_flags |= RQF_HASHED;
}
-static void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
+void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
{
__elv_rqhash_del(rq);
elv_rqhash_add(q, rq);
}
-static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
+struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
{
struct elevator_queue *e = q->elevator;
struct hlist_node *next;
@@ -352,7 +352,6 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq)
{
sector_t boundary;
struct list_head *entry;
- int stop_flags;
if (q->last_merge == rq)
q->last_merge = NULL;
@@ -362,7 +361,6 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq)
q->nr_sorted--;
boundary = q->end_sector;
- stop_flags = REQ_SOFTBARRIER | REQ_STARTED;
list_for_each_prev(entry, &q->queue_head) {
struct request *pos = list_entry_rq(entry);
@@ -370,7 +368,7 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq)
break;
if (rq_data_dir(rq) != rq_data_dir(pos))
break;
- if (pos->cmd_flags & stop_flags)
+ if (pos->rq_flags & (RQF_STARTED | RQF_SOFTBARRIER))
break;
if (blk_rq_pos(rq) >= boundary) {
if (blk_rq_pos(pos) < boundary)
@@ -510,7 +508,7 @@ void elv_merge_requests(struct request_queue *q, struct request *rq,
struct request *next)
{
struct elevator_queue *e = q->elevator;
- const int next_sorted = next->cmd_flags & REQ_SORTED;
+ const int next_sorted = next->rq_flags & RQF_SORTED;
if (next_sorted && e->type->ops.elevator_merge_req_fn)
e->type->ops.elevator_merge_req_fn(q, rq, next);
@@ -537,13 +535,13 @@ void elv_bio_merged(struct request_queue *q, struct request *rq,
#ifdef CONFIG_PM
static void blk_pm_requeue_request(struct request *rq)
{
- if (rq->q->dev && !(rq->cmd_flags & REQ_PM))
+ if (rq->q->dev && !(rq->rq_flags & RQF_PM))
rq->q->nr_pending--;
}
static void blk_pm_add_request(struct request_queue *q, struct request *rq)
{
- if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 &&
+ if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 &&
(q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING))
pm_request_resume(q->dev);
}
@@ -563,11 +561,11 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
*/
if (blk_account_rq(rq)) {
q->in_flight[rq_is_sync(rq)]--;
- if (rq->cmd_flags & REQ_SORTED)
+ if (rq->rq_flags & RQF_SORTED)
elv_deactivate_rq(q, rq);
}
- rq->cmd_flags &= ~REQ_STARTED;
+ rq->rq_flags &= ~RQF_STARTED;
blk_pm_requeue_request(rq);
@@ -597,13 +595,13 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
rq->q = q;
- if (rq->cmd_flags & REQ_SOFTBARRIER) {
+ if (rq->rq_flags & RQF_SOFTBARRIER) {
/* barriers are scheduling boundary, update end_sector */
if (rq->cmd_type == REQ_TYPE_FS) {
q->end_sector = rq_end_sector(rq);
q->boundary_rq = rq;
}
- } else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
+ } else if (!(rq->rq_flags & RQF_ELVPRIV) &&
(where == ELEVATOR_INSERT_SORT ||
where == ELEVATOR_INSERT_SORT_MERGE))
where = ELEVATOR_INSERT_BACK;
@@ -611,12 +609,12 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
switch (where) {
case ELEVATOR_INSERT_REQUEUE:
case ELEVATOR_INSERT_FRONT:
- rq->cmd_flags |= REQ_SOFTBARRIER;
+ rq->rq_flags |= RQF_SOFTBARRIER;
list_add(&rq->queuelist, &q->queue_head);
break;
case ELEVATOR_INSERT_BACK:
- rq->cmd_flags |= REQ_SOFTBARRIER;
+ rq->rq_flags |= RQF_SOFTBARRIER;
elv_drain_elevator(q);
list_add_tail(&rq->queuelist, &q->queue_head);
/*
@@ -642,7 +640,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
break;
case ELEVATOR_INSERT_SORT:
BUG_ON(rq->cmd_type != REQ_TYPE_FS);
- rq->cmd_flags |= REQ_SORTED;
+ rq->rq_flags |= RQF_SORTED;
q->nr_sorted++;
if (rq_mergeable(rq)) {
elv_rqhash_add(q, rq);
@@ -659,7 +657,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
break;
case ELEVATOR_INSERT_FLUSH:
- rq->cmd_flags |= REQ_SOFTBARRIER;
+ rq->rq_flags |= RQF_SOFTBARRIER;
blk_insert_flush(rq);
break;
default:
@@ -716,12 +714,12 @@ void elv_put_request(struct request_queue *q, struct request *rq)
e->type->ops.elevator_put_req_fn(rq);
}
-int elv_may_queue(struct request_queue *q, int op, int op_flags)
+int elv_may_queue(struct request_queue *q, unsigned int op)
{
struct elevator_queue *e = q->elevator;
if (e->type->ops.elevator_may_queue_fn)
- return e->type->ops.elevator_may_queue_fn(q, op, op_flags);
+ return e->type->ops.elevator_may_queue_fn(q, op);
return ELV_MQUEUE_MAY;
}
@@ -735,7 +733,7 @@ void elv_completed_request(struct request_queue *q, struct request *rq)
*/
if (blk_account_rq(rq)) {
q->in_flight[rq_is_sync(rq)]--;
- if ((rq->cmd_flags & REQ_SORTED) &&
+ if ((rq->rq_flags & RQF_SORTED) &&
e->type->ops.elevator_completed_req_fn)
e->type->ops.elevator_completed_req_fn(q, rq);
}
diff --git a/block/ioctl.c b/block/ioctl.c
index 755119c3c1b9..f856963204f4 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -519,6 +519,10 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
BLKDEV_DISCARD_SECURE);
case BLKZEROOUT:
return blk_ioctl_zeroout(bdev, mode, arg);
+ case BLKREPORTZONE:
+ return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
+ case BLKRESETZONE:
+ return blkdev_reset_zones_ioctl(bdev, mode, cmd, arg);
case HDIO_GETGEO:
return blkdev_getgeo(bdev, argp);
case BLKRAGET:
diff --git a/block/partition-generic.c b/block/partition-generic.c
index 71d9ed9df8da..d7beb6bbbf66 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -430,6 +430,56 @@ static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
return 0;
}
+static bool part_zone_aligned(struct gendisk *disk,
+ struct block_device *bdev,
+ sector_t from, sector_t size)
+{
+ unsigned int zone_size = bdev_zone_size(bdev);
+
+ /*
+ * If this function is called, then the disk is a zoned block device
+ * (host-aware or host-managed). This can be detected even if the
+ * zoned block device support is disabled (CONFIG_BLK_DEV_ZONED not
+ * set). In this case, however, only host-aware devices will be seen
+ * as a block device is not created for host-managed devices. Without
+ * zoned block device support, host-aware drives can still be used as
+ * regular block devices (no zone operation) and their zone size will
+ * be reported as 0. Allow this case.
+ */
+ if (!zone_size)
+ return true;
+
+ /*
+ * Check partition start and size alignement. If the drive has a
+ * smaller last runt zone, ignore it and allow the partition to
+ * use it. Check the zone size too: it should be a power of 2 number
+ * of sectors.
+ */
+ if (WARN_ON_ONCE(!is_power_of_2(zone_size))) {
+ u32 rem;
+
+ div_u64_rem(from, zone_size, &rem);
+ if (rem)
+ return false;
+ if ((from + size) < get_capacity(disk)) {
+ div_u64_rem(size, zone_size, &rem);
+ if (rem)
+ return false;
+ }
+
+ } else {
+
+ if (from & (zone_size - 1))
+ return false;
+ if ((from + size) < get_capacity(disk) &&
+ (size & (zone_size - 1)))
+ return false;
+
+ }
+
+ return true;
+}
+
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
{
struct parsed_partitions *state = NULL;
@@ -529,6 +579,21 @@ rescan:
}
}
+ /*
+ * On a zoned block device, partitions should be aligned on the
+ * device zone size (i.e. zone boundary crossing not allowed).
+ * Otherwise, resetting the write pointer of the last zone of
+ * one partition may impact the following partition.
+ */
+ if (bdev_is_zoned(bdev) &&
+ !part_zone_aligned(disk, bdev, from, size)) {
+ printk(KERN_WARNING
+ "%s: p%d start %llu+%llu is not zone aligned\n",
+ disk->disk_name, p, (unsigned long long) from,
+ (unsigned long long) size);
+ continue;
+ }
+
part = add_partition(disk, p, from, size,
state->parts[p].flags,
&state->parts[p].info);
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index e9c0993b131d..235f54d4f8a9 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -136,28 +136,27 @@ static void aead_wmem_wakeup(struct sock *sk)
static int aead_wait_for_data(struct sock *sk, unsigned flags)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct alg_sock *ask = alg_sk(sk);
struct aead_ctx *ctx = ask->private;
long timeout;
- DEFINE_WAIT(wait);
int err = -ERESTARTSYS;
if (flags & MSG_DONTWAIT)
return -EAGAIN;
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-
+ add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
- if (sk_wait_event(sk, &timeout, !ctx->more)) {
+ if (sk_wait_event(sk, &timeout, !ctx->more, &wait)) {
err = 0;
break;
}
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 28556fce4267..1e38aaa8303e 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -199,26 +199,26 @@ static void skcipher_free_sgl(struct sock *sk)
static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
{
- long timeout;
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
int err = -ERESTARTSYS;
+ long timeout;
if (flags & MSG_DONTWAIT)
return -EAGAIN;
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+ add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
- if (sk_wait_event(sk, &timeout, skcipher_writable(sk))) {
+ if (sk_wait_event(sk, &timeout, skcipher_writable(sk), &wait)) {
err = 0;
break;
}
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return err;
}
@@ -242,10 +242,10 @@ static void skcipher_wmem_wakeup(struct sock *sk)
static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
long timeout;
- DEFINE_WAIT(wait);
int err = -ERESTARTSYS;
if (flags & MSG_DONTWAIT) {
@@ -254,17 +254,17 @@ static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
+ add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
- if (sk_wait_event(sk, &timeout, ctx->used)) {
+ if (sk_wait_event(sk, &timeout, ctx->used, &wait)) {
err = 0;
break;
}
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
diff --git a/drivers/Makefile b/drivers/Makefile
index 194d20bee7dc..060026a02f59 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -107,7 +107,7 @@ obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/ media/
obj-$(CONFIG_PPS) += pps/
-obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
+obj-y += ptp/
obj-$(CONFIG_W1) += w1/
obj-y += power/
obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 535e7828445a..c5f9cbe0ae21 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -342,7 +342,7 @@ config ACPI_DEBUG
Use the acpi.debug_layer and acpi.debug_level kernel command-line
parameters documented in Documentation/acpi/debug.txt and
- Documentation/kernel-parameters.txt to control the type and
+ Documentation/admin-guide/kernel-parameters.rst to control the type and
amount of debug output.
config ACPI_PCI_SLOT
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 56190d00fd87..5cbefd7621f0 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -331,6 +331,16 @@ static void acpi_bus_osc_support(void)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
+#ifdef CONFIG_X86
+ if (boot_cpu_has(X86_FEATURE_HWP)) {
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPCV2_SUPPORT;
+ }
+#endif
+
+ if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;
+
if (!ghes_disable)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index e24ea4e796e4..7fceb3b4691b 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -82,8 +82,8 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = {
{ .name = ACPI_GENL_MCAST_GROUP_NAME, },
};
-static struct genl_family acpi_event_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family acpi_event_genl_family __ro_after_init = {
+ .module = THIS_MODULE,
.name = ACPI_GENL_FAMILY_NAME,
.version = ACPI_GENL_VERSION,
.maxattr = ACPI_GENL_ATTR_MAX,
@@ -144,7 +144,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
-static int acpi_event_genetlink_init(void)
+static int __init acpi_event_genetlink_init(void)
{
return genl_register_family(&acpi_event_genl_family);
}
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2237d3f24f0e..5c8aa9cf62d7 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -141,7 +141,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
return;
- if (amd_e400_c1e_detected)
+ if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E))
type = ACPI_STATE_C1;
/*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index bb01dea39fdc..f0b4a981b8d3 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -157,7 +157,7 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status)
status, NULL);
}
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
+void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
{
int ret;
@@ -168,7 +168,7 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
*/
if (event_flag)
acpi_processor_ppc_ost(pr->handle, 1);
- return 0;
+ return;
}
ret = acpi_processor_get_platform_limit(pr);
@@ -182,10 +182,8 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
else
acpi_processor_ppc_ost(pr->handle, 0);
}
- if (ret < 0)
- return (ret);
- else
- return cpufreq_update_policy(pr->id);
+ if (ret >= 0)
+ cpufreq_update_policy(pr->id);
}
int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
@@ -465,11 +463,33 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr)
return result;
}
EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
-int acpi_processor_notify_smm(struct module *calling_module)
+
+int acpi_processor_pstate_control(void)
{
acpi_status status;
- static int is_done = 0;
+ if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control)
+ return 0;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
+ acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+
+ status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
+ (u32)acpi_gbl_FADT.pstate_control, 8);
+ if (ACPI_SUCCESS(status))
+ return 1;
+
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Failed to write pstate_control [0x%x] to smi_command [0x%x]",
+ acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+ return -EIO;
+}
+
+int acpi_processor_notify_smm(struct module *calling_module)
+{
+ static int is_done = 0;
+ int result;
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
return -EBUSY;
@@ -492,26 +512,15 @@ int acpi_processor_notify_smm(struct module *calling_module)
is_done = -EIO;
- /* Can't write pstate_control to smi_command if either value is zero */
- if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
+ result = acpi_processor_pstate_control();
+ if (!result) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
module_put(calling_module);
return 0;
}
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
- acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
-
- status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
- (u32) acpi_gbl_FADT.pstate_control, 8);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "Failed to write pstate_control [0x%x] to "
- "smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
- acpi_gbl_FADT.smi_command));
+ if (result < 0) {
module_put(calling_module);
- return status;
+ return result;
}
/* Success. If there's no _PPC, we need to fear nothing, so
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 54abb26b7366..9b6cebe227a0 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -674,6 +674,14 @@ static void acpi_sleep_suspend_setup(void)
if (acpi_sleep_state_supported(i))
sleep_states[i] = 1;
+ /*
+ * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set and
+ * the default suspend mode was not selected from the command line.
+ */
+ if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0 &&
+ mem_sleep_default > PM_SUSPEND_MEM)
+ mem_sleep_default = PM_SUSPEND_FREEZE;
+
suspend_set_ops(old_suspend_ordering ?
&acpi_suspend_ops_old : &acpi_suspend_ops);
freeze_set_ops(&acpi_freeze_ops);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 223a770f78f3..59ce0dd50701 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -129,7 +129,7 @@ static int ata_force_tbl_size;
static char ata_force_param_buf[PAGE_SIZE] __initdata;
/* param_buf is thrown away after initialization, disallow read */
module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);
-MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
+MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/admin-guide/kernel-parameters.rst for details)");
static int atapi_enabled = 1;
module_param(atapi_enabled, int, 0444);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 6ac2b2b1e8de..5ad037c07ec7 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -584,7 +584,7 @@ static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", data32);
}
-static DEVICE_ATTR(console, 0644, console_show, console_store);
+static DEVICE_ATTR_RW(console);
#define SOLOS_ATTR_RO(x) static DEVICE_ATTR(x, 0444, solos_param_show, NULL);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d02e7c0f5bfd..afa67f9ed726 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE
config SOC_BUS
bool
+ select GLOB
source "drivers/base/regmap/Kconfig"
@@ -250,11 +251,11 @@ config DMA_SHARED_BUFFER
APIs extension; the file's descriptor can then be passed on to other
driver.
-config FENCE_TRACE
- bool "Enable verbose FENCE_TRACE messages"
+config DMA_FENCE_TRACE
+ bool "Enable verbose DMA_FENCE_TRACE messages"
depends on DMA_SHARED_BUFFER
help
- Enable the FENCE_TRACE printks. This will add extra
+ Enable the DMA_FENCE_TRACE printks. This will add extra
spam to the console log, but will make it easier to diagnose
lockup related problems for dma-buffers shared across multiple
devices.
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index e9fd32e91668..47983a2ba621 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -498,57 +498,30 @@ err:
return rc;
}
-static void cache_remove_dev(unsigned int cpu)
+static int cacheinfo_cpu_online(unsigned int cpu)
{
- if (!cpumask_test_cpu(cpu, &cache_dev_map))
- return;
- cpumask_clear_cpu(cpu, &cache_dev_map);
+ int rc = detect_cache_attributes(cpu);
- cpu_cache_sysfs_exit(cpu);
+ if (rc)
+ return rc;
+ rc = cache_add_dev(cpu);
+ if (rc)
+ free_cache_attributes(cpu);
+ return rc;
}
-static int cacheinfo_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static int cacheinfo_cpu_pre_down(unsigned int cpu)
{
- unsigned int cpu = (unsigned long)hcpu;
- int rc = 0;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- rc = detect_cache_attributes(cpu);
- if (!rc)
- rc = cache_add_dev(cpu);
- break;
- case CPU_DEAD:
- cache_remove_dev(cpu);
- free_cache_attributes(cpu);
- break;
- }
- return notifier_from_errno(rc);
+ if (cpumask_test_and_clear_cpu(cpu, &cache_dev_map))
+ cpu_cache_sysfs_exit(cpu);
+
+ free_cache_attributes(cpu);
+ return 0;
}
static int __init cacheinfo_sysfs_init(void)
{
- int cpu, rc = 0;
-
- cpu_notifier_register_begin();
-
- for_each_online_cpu(cpu) {
- rc = detect_cache_attributes(cpu);
- if (rc)
- goto out;
- rc = cache_add_dev(cpu);
- if (rc) {
- free_cache_attributes(cpu);
- pr_err("error populating cacheinfo..cpu%d\n", cpu);
- goto out;
- }
- }
- __hotcpu_notifier(cacheinfo_cpu_callback, 0);
-
-out:
- cpu_notifier_register_done();
- return rc;
+ return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "base/cacheinfo:online",
+ cacheinfo_cpu_online, cacheinfo_cpu_pre_down);
}
-
device_initcall(cacheinfo_sysfs_init);
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 8fc654f0807b..71d577025285 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/percpu.h>
#include "base.h"
@@ -985,3 +986,68 @@ void devm_free_pages(struct device *dev, unsigned long addr)
&devres));
}
EXPORT_SYMBOL_GPL(devm_free_pages);
+
+static void devm_percpu_release(struct device *dev, void *pdata)
+{
+ void __percpu *p;
+
+ p = *(void __percpu **)pdata;
+ free_percpu(p);
+}
+
+static int devm_percpu_match(struct device *dev, void *data, void *p)
+{
+ struct devres *devr = container_of(data, struct devres, data);
+
+ return *(void **)devr->data == p;
+}
+
+/**
+ * __devm_alloc_percpu - Resource-managed alloc_percpu
+ * @dev: Device to allocate per-cpu memory for
+ * @size: Size of per-cpu memory to allocate
+ * @align: Alignment of per-cpu memory to allocate
+ *
+ * Managed alloc_percpu. Per-cpu memory allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
+ size_t align)
+{
+ void *p;
+ void __percpu *pcpu;
+
+ pcpu = __alloc_percpu(size, align);
+ if (!pcpu)
+ return NULL;
+
+ p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL);
+ if (!p) {
+ free_percpu(pcpu);
+ return NULL;
+ }
+
+ *(void __percpu **)p = pcpu;
+
+ devres_add(dev, p);
+
+ return pcpu;
+}
+EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
+
+/**
+ * devm_free_percpu - Resource-managed free_percpu
+ * @dev: Device this memory belongs to
+ * @pdata: Per-cpu memory to free
+ *
+ * Free memory allocated with devm_alloc_percpu().
+ */
+void devm_free_percpu(struct device *dev, void __percpu *pdata)
+{
+ WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
+ (void *)pdata));
+}
+EXPORT_SYMBOL_GPL(devm_free_percpu);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e023066e4215..5711708532db 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -39,6 +39,105 @@
static LIST_HEAD(gpd_list);
static DEFINE_MUTEX(gpd_list_lock);
+struct genpd_lock_ops {
+ void (*lock)(struct generic_pm_domain *genpd);
+ void (*lock_nested)(struct generic_pm_domain *genpd, int depth);
+ int (*lock_interruptible)(struct generic_pm_domain *genpd);
+ void (*unlock)(struct generic_pm_domain *genpd);
+};
+
+static void genpd_lock_mtx(struct generic_pm_domain *genpd)
+{
+ mutex_lock(&genpd->mlock);
+}
+
+static void genpd_lock_nested_mtx(struct generic_pm_domain *genpd,
+ int depth)
+{
+ mutex_lock_nested(&genpd->mlock, depth);
+}
+
+static int genpd_lock_interruptible_mtx(struct generic_pm_domain *genpd)
+{
+ return mutex_lock_interruptible(&genpd->mlock);
+}
+
+static void genpd_unlock_mtx(struct generic_pm_domain *genpd)
+{
+ return mutex_unlock(&genpd->mlock);
+}
+
+static const struct genpd_lock_ops genpd_mtx_ops = {
+ .lock = genpd_lock_mtx,
+ .lock_nested = genpd_lock_nested_mtx,
+ .lock_interruptible = genpd_lock_interruptible_mtx,
+ .unlock = genpd_unlock_mtx,
+};
+
+static void genpd_lock_spin(struct generic_pm_domain *genpd)
+ __acquires(&genpd->slock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&genpd->slock, flags);
+ genpd->lock_flags = flags;
+}
+
+static void genpd_lock_nested_spin(struct generic_pm_domain *genpd,
+ int depth)
+ __acquires(&genpd->slock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave_nested(&genpd->slock, flags, depth);
+ genpd->lock_flags = flags;
+}
+
+static int genpd_lock_interruptible_spin(struct generic_pm_domain *genpd)
+ __acquires(&genpd->slock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&genpd->slock, flags);
+ genpd->lock_flags = flags;
+ return 0;
+}
+
+static void genpd_unlock_spin(struct generic_pm_domain *genpd)
+ __releases(&genpd->slock)
+{
+ spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags);
+}
+
+static const struct genpd_lock_ops genpd_spin_ops = {
+ .lock = genpd_lock_spin,
+ .lock_nested = genpd_lock_nested_spin,
+ .lock_interruptible = genpd_lock_interruptible_spin,
+ .unlock = genpd_unlock_spin,
+};
+
+#define genpd_lock(p) p->lock_ops->lock(p)
+#define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d)
+#define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p)
+#define genpd_unlock(p) p->lock_ops->unlock(p)
+
+#define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE)
+
+static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
+ struct generic_pm_domain *genpd)
+{
+ bool ret;
+
+ ret = pm_runtime_is_irq_safe(dev) && !genpd_is_irq_safe(genpd);
+
+ /* Warn once for each IRQ safe dev in no sleep domain */
+ if (ret)
+ dev_warn_once(dev, "PM domain %s will not be powered off\n",
+ genpd->name);
+
+ return ret;
+}
+
/*
* Get the generic PM domain for a particular struct device.
* This validates the struct device pointer, the PM domain pointer,
@@ -200,9 +299,9 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
genpd_sd_counter_inc(master);
- mutex_lock_nested(&master->lock, depth + 1);
+ genpd_lock_nested(master, depth + 1);
ret = genpd_poweron(master, depth + 1);
- mutex_unlock(&master->lock);
+ genpd_unlock(master);
if (ret) {
genpd_sd_counter_dec(master);
@@ -255,9 +354,9 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
spin_unlock_irq(&dev->power.lock);
if (!IS_ERR(genpd)) {
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
genpd->max_off_time_changed = true;
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
}
dev = dev->parent;
@@ -303,7 +402,12 @@ static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
if (stat > PM_QOS_FLAGS_NONE)
return -EBUSY;
- if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
+ /*
+ * Do not allow PM domain to be powered off, when an IRQ safe
+ * device is part of a non-IRQ safe domain.
+ */
+ if (!pm_runtime_suspended(pdd->dev) ||
+ irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd))
not_suspended++;
}
@@ -354,9 +458,9 @@ 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);
+ genpd_lock(genpd);
genpd_poweroff(genpd, true);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
}
/**
@@ -466,15 +570,15 @@ static int genpd_runtime_suspend(struct device *dev)
}
/*
- * If power.irq_safe is set, this routine will be run with interrupts
- * off, so it can't use mutexes.
+ * If power.irq_safe is set, this routine may be run with
+ * IRQs disabled, so suspend only if the PM domain also is irq_safe.
*/
- if (dev->power.irq_safe)
+ if (irq_safe_dev_in_no_sleep_domain(dev, genpd))
return 0;
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
genpd_poweroff(genpd, false);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
return 0;
}
@@ -503,15 +607,18 @@ static int genpd_runtime_resume(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;
- /* If power.irq_safe, the PM domain is never powered off. */
- if (dev->power.irq_safe) {
+ /*
+ * As we don't power off a non IRQ safe domain, which holds
+ * an IRQ safe device, we don't need to restore power to it.
+ */
+ if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) {
timed = false;
goto out;
}
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
ret = genpd_poweron(genpd, 0);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
if (ret)
return ret;
@@ -546,10 +653,11 @@ static int genpd_runtime_resume(struct device *dev)
err_stop:
genpd_stop_dev(genpd, dev);
err_poweroff:
- if (!dev->power.irq_safe) {
- mutex_lock(&genpd->lock);
+ if (!pm_runtime_is_irq_safe(dev) ||
+ (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) {
+ genpd_lock(genpd);
genpd_poweroff(genpd, 0);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
}
return ret;
@@ -732,20 +840,20 @@ static int pm_genpd_prepare(struct device *dev)
if (resume_needed(dev, genpd))
pm_runtime_resume(dev);
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
if (genpd->prepared_count++ == 0)
genpd->suspended_count = 0;
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
ret = pm_generic_prepare(dev);
if (ret) {
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
genpd->prepared_count--;
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
}
return ret;
@@ -936,13 +1044,13 @@ static void pm_genpd_complete(struct device *dev)
pm_generic_complete(dev);
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
genpd->prepared_count--;
if (!genpd->prepared_count)
genpd_queue_power_off_work(genpd);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
}
/**
@@ -1071,7 +1179,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (IS_ERR(gpd_data))
return PTR_ERR(gpd_data);
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
if (genpd->prepared_count > 0) {
ret = -EAGAIN;
@@ -1088,7 +1196,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
out:
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
if (ret)
genpd_free_dev_data(dev, gpd_data);
@@ -1130,7 +1238,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
gpd_data = to_gpd_data(pdd);
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
if (genpd->prepared_count > 0) {
ret = -EAGAIN;
@@ -1145,14 +1253,14 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
list_del_init(&pdd->list_node);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
genpd_free_dev_data(dev, gpd_data);
return 0;
out:
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
dev_pm_qos_add_notifier(dev, &gpd_data->nb);
return ret;
@@ -1183,12 +1291,23 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
|| genpd == subdomain)
return -EINVAL;
+ /*
+ * If the domain can be powered on/off in an IRQ safe
+ * context, ensure that the subdomain can also be
+ * powered on/off in that context.
+ */
+ if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) {
+ WARN(1, "Parent %s of subdomain %s must be IRQ safe\n",
+ genpd->name, subdomain->name);
+ return -EINVAL;
+ }
+
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
return -ENOMEM;
- mutex_lock(&subdomain->lock);
- mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+ genpd_lock(subdomain);
+ genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
if (genpd->status == GPD_STATE_POWER_OFF
&& subdomain->status != GPD_STATE_POWER_OFF) {
@@ -1211,8 +1330,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
genpd_sd_counter_inc(genpd);
out:
- mutex_unlock(&genpd->lock);
- mutex_unlock(&subdomain->lock);
+ genpd_unlock(genpd);
+ genpd_unlock(subdomain);
if (ret)
kfree(link);
return ret;
@@ -1250,8 +1369,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
return -EINVAL;
- mutex_lock(&subdomain->lock);
- mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+ genpd_lock(subdomain);
+ genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
@@ -1275,13 +1394,39 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
}
out:
- mutex_unlock(&genpd->lock);
- mutex_unlock(&subdomain->lock);
+ genpd_unlock(genpd);
+ genpd_unlock(subdomain);
return ret;
}
EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
+static int genpd_set_default_power_state(struct generic_pm_domain *genpd)
+{
+ struct genpd_power_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ genpd->states = state;
+ genpd->state_count = 1;
+ genpd->free = state;
+
+ return 0;
+}
+
+static void genpd_lock_init(struct generic_pm_domain *genpd)
+{
+ if (genpd->flags & GENPD_FLAG_IRQ_SAFE) {
+ spin_lock_init(&genpd->slock);
+ genpd->lock_ops = &genpd_spin_ops;
+ } else {
+ mutex_init(&genpd->mlock);
+ genpd->lock_ops = &genpd_mtx_ops;
+ }
+}
+
/**
* pm_genpd_init - Initialize a generic I/O PM domain object.
* @genpd: PM domain object to initialize.
@@ -1293,13 +1438,15 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
int pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off)
{
+ int ret;
+
if (IS_ERR_OR_NULL(genpd))
return -EINVAL;
INIT_LIST_HEAD(&genpd->master_links);
INIT_LIST_HEAD(&genpd->slave_links);
INIT_LIST_HEAD(&genpd->dev_list);
- mutex_init(&genpd->lock);
+ genpd_lock_init(genpd);
genpd->gov = gov;
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
atomic_set(&genpd->sd_count, 0);
@@ -1325,19 +1472,12 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->dev_ops.start = pm_clk_resume;
}
- if (genpd->state_idx >= GENPD_MAX_NUM_STATES) {
- pr_warn("Initial state index out of bounds.\n");
- genpd->state_idx = GENPD_MAX_NUM_STATES - 1;
- }
-
- if (genpd->state_count > GENPD_MAX_NUM_STATES) {
- pr_warn("Limiting states to %d\n", GENPD_MAX_NUM_STATES);
- genpd->state_count = GENPD_MAX_NUM_STATES;
- }
-
/* Use only one "off" state if there were no states declared */
- if (genpd->state_count == 0)
- genpd->state_count = 1;
+ if (genpd->state_count == 0) {
+ ret = genpd_set_default_power_state(genpd);
+ if (ret)
+ return ret;
+ }
mutex_lock(&gpd_list_lock);
list_add(&genpd->gpd_list_node, &gpd_list);
@@ -1354,16 +1494,16 @@ static int genpd_remove(struct generic_pm_domain *genpd)
if (IS_ERR_OR_NULL(genpd))
return -EINVAL;
- mutex_lock(&genpd->lock);
+ genpd_lock(genpd);
if (genpd->has_provider) {
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
pr_err("Provider present, unable to remove %s\n", genpd->name);
return -EBUSY;
}
if (!list_empty(&genpd->master_links) || genpd->device_count) {
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
pr_err("%s: unable to remove %s\n", __func__, genpd->name);
return -EBUSY;
}
@@ -1375,8 +1515,9 @@ static int genpd_remove(struct generic_pm_domain *genpd)
}
list_del(&genpd->gpd_list_node);
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
cancel_work_sync(&genpd->power_off_work);
+ kfree(genpd->free);
pr_debug("%s: removed %s\n", __func__, genpd->name);
return 0;
@@ -1890,21 +2031,117 @@ int genpd_dev_pm_attach(struct device *dev)
mutex_unlock(&gpd_list_lock);
if (ret < 0) {
- dev_err(dev, "failed to add to PM domain %s: %d",
- pd->name, ret);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to add to PM domain %s: %d",
+ pd->name, ret);
goto out;
}
dev->pm_domain->detach = genpd_dev_pm_detach;
dev->pm_domain->sync = genpd_dev_pm_sync;
- mutex_lock(&pd->lock);
+ genpd_lock(pd);
ret = genpd_poweron(pd, 0);
- mutex_unlock(&pd->lock);
+ genpd_unlock(pd);
out:
return ret ? -EPROBE_DEFER : 0;
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+
+static const struct of_device_id idle_state_match[] = {
+ { .compatible = "domain-idle-state", },
+ { }
+};
+
+static int genpd_parse_state(struct genpd_power_state *genpd_state,
+ struct device_node *state_node)
+{
+ int err;
+ u32 residency;
+ u32 entry_latency, exit_latency;
+ const struct of_device_id *match_id;
+
+ match_id = of_match_node(idle_state_match, state_node);
+ if (!match_id)
+ return -EINVAL;
+
+ err = of_property_read_u32(state_node, "entry-latency-us",
+ &entry_latency);
+ if (err) {
+ pr_debug(" * %s missing entry-latency-us property\n",
+ state_node->full_name);
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32(state_node, "exit-latency-us",
+ &exit_latency);
+ if (err) {
+ pr_debug(" * %s missing exit-latency-us property\n",
+ state_node->full_name);
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32(state_node, "min-residency-us", &residency);
+ if (!err)
+ genpd_state->residency_ns = 1000 * residency;
+
+ genpd_state->power_on_latency_ns = 1000 * exit_latency;
+ genpd_state->power_off_latency_ns = 1000 * entry_latency;
+ genpd_state->fwnode = &state_node->fwnode;
+
+ return 0;
+}
+
+/**
+ * of_genpd_parse_idle_states: Return array of idle states for the genpd.
+ *
+ * @dn: The genpd device node
+ * @states: The pointer to which the state array will be saved.
+ * @n: The count of elements in the array returned from this function.
+ *
+ * Returns the device states parsed from the OF node. The memory for the states
+ * is allocated by this function and is the responsibility of the caller to
+ * free the memory after use.
+ */
+int of_genpd_parse_idle_states(struct device_node *dn,
+ struct genpd_power_state **states, int *n)
+{
+ struct genpd_power_state *st;
+ struct device_node *np;
+ int i = 0;
+ int err, ret;
+ int count;
+ struct of_phandle_iterator it;
+
+ count = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
+ if (count <= 0)
+ return -EINVAL;
+
+ st = kcalloc(count, sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return -ENOMEM;
+
+ /* Loop over the phandles until all the requested entry is found */
+ of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) {
+ np = it.node;
+ ret = genpd_parse_state(&st[i++], np);
+ if (ret) {
+ pr_err
+ ("Parsing idle state node %s failed with err %d\n",
+ np->full_name, ret);
+ of_node_put(np);
+ kfree(st);
+ return ret;
+ }
+ }
+
+ *n = count;
+ *states = st;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
+
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -1958,7 +2195,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
char state[16];
int ret;
- ret = mutex_lock_interruptible(&genpd->lock);
+ ret = genpd_lock_interruptible(genpd);
if (ret)
return -ERESTARTSYS;
@@ -1984,7 +2221,9 @@ static int pm_genpd_summary_one(struct seq_file *s,
}
list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
- kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
+ kobj_path = kobject_get_path(&pm_data->dev->kobj,
+ genpd_is_irq_safe(genpd) ?
+ GFP_ATOMIC : GFP_KERNEL);
if (kobj_path == NULL)
continue;
@@ -1995,7 +2234,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
seq_puts(s, "\n");
exit:
- mutex_unlock(&genpd->lock);
+ genpd_unlock(genpd);
return 0;
}
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 2932a5bd892f..eb474c882ebe 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1460,10 +1460,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
dpm_watchdog_clear(&wd);
Complete:
- complete_all(&dev->power.completion);
if (error)
async_error = error;
+ complete_all(&dev->power.completion);
TRACE_SUSPEND(error);
return error;
}
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index 4c7c6da7a989..35ff06283738 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -93,6 +93,8 @@ struct opp_table *_find_opp_table(struct device *dev)
* Return: voltage in micro volt corresponding to the opp, else
* return 0
*
+ * This is useful only for devices with single power supply.
+ *
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. This means that opp which could have been fetched by
* opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
@@ -112,7 +114,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
if (IS_ERR_OR_NULL(tmp_opp))
pr_err("%s: Invalid parameters\n", __func__);
else
- v = tmp_opp->u_volt;
+ v = tmp_opp->supplies[0].u_volt;
return v;
}
@@ -210,6 +212,24 @@ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+static int _get_regulator_count(struct device *dev)
+{
+ struct opp_table *opp_table;
+ int count;
+
+ rcu_read_lock();
+
+ opp_table = _find_opp_table(dev);
+ if (!IS_ERR(opp_table))
+ count = opp_table->regulator_count;
+ else
+ count = 0;
+
+ rcu_read_unlock();
+
+ return count;
+}
+
/**
* dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds
* @dev: device for which we do this operation
@@ -222,34 +242,51 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
{
struct opp_table *opp_table;
struct dev_pm_opp *opp;
- struct regulator *reg;
+ struct regulator *reg, **regulators;
unsigned long latency_ns = 0;
- unsigned long min_uV = ~0, max_uV = 0;
- int ret;
+ int ret, i, count;
+ struct {
+ unsigned long min;
+ unsigned long max;
+ } *uV;
+
+ count = _get_regulator_count(dev);
+
+ /* Regulator may not be required for the device */
+ if (!count)
+ return 0;
+
+ regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
+ if (!regulators)
+ return 0;
+
+ uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
+ if (!uV)
+ goto free_regulators;
rcu_read_lock();
opp_table = _find_opp_table(dev);
if (IS_ERR(opp_table)) {
rcu_read_unlock();
- return 0;
+ goto free_uV;
}
- reg = opp_table->regulator;
- if (IS_ERR(reg)) {
- /* Regulator may not be required for device */
- rcu_read_unlock();
- return 0;
- }
+ memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
- list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
- if (!opp->available)
- continue;
+ for (i = 0; i < count; i++) {
+ uV[i].min = ~0;
+ uV[i].max = 0;
+
+ list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
+ if (!opp->available)
+ continue;
- if (opp->u_volt_min < min_uV)
- min_uV = opp->u_volt_min;
- if (opp->u_volt_max > max_uV)
- max_uV = opp->u_volt_max;
+ if (opp->supplies[i].u_volt_min < uV[i].min)
+ uV[i].min = opp->supplies[i].u_volt_min;
+ if (opp->supplies[i].u_volt_max > uV[i].max)
+ uV[i].max = opp->supplies[i].u_volt_max;
+ }
}
rcu_read_unlock();
@@ -258,9 +295,16 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
* The caller needs to ensure that opp_table (and hence the regulator)
* isn't freed, while we are executing this routine.
*/
- ret = regulator_set_voltage_time(reg, min_uV, max_uV);
- if (ret > 0)
- latency_ns = ret * 1000;
+ for (i = 0; reg = regulators[i], i < count; i++) {
+ ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
+ if (ret > 0)
+ latency_ns += ret * 1000;
+ }
+
+free_uV:
+ kfree(uV);
+free_regulators:
+ kfree(regulators);
return latency_ns;
}
@@ -542,8 +586,7 @@ unlock:
}
static int _set_opp_voltage(struct device *dev, struct regulator *reg,
- unsigned long u_volt, unsigned long u_volt_min,
- unsigned long u_volt_max)
+ struct dev_pm_opp_supply *supply)
{
int ret;
@@ -554,14 +597,78 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
return 0;
}
- dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, u_volt_min,
- u_volt, u_volt_max);
+ dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__,
+ supply->u_volt_min, supply->u_volt, supply->u_volt_max);
- ret = regulator_set_voltage_triplet(reg, u_volt_min, u_volt,
- u_volt_max);
+ ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
+ supply->u_volt, supply->u_volt_max);
if (ret)
dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n",
- __func__, u_volt_min, u_volt, u_volt_max, ret);
+ __func__, supply->u_volt_min, supply->u_volt,
+ supply->u_volt_max, ret);
+
+ return ret;
+}
+
+static inline int
+_generic_set_opp_clk_only(struct device *dev, struct clk *clk,
+ unsigned long old_freq, unsigned long freq)
+{
+ int ret;
+
+ ret = clk_set_rate(clk, freq);
+ if (ret) {
+ dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
+ ret);
+ }
+
+ return ret;
+}
+
+static int _generic_set_opp(struct dev_pm_set_opp_data *data)
+{
+ struct dev_pm_opp_supply *old_supply = data->old_opp.supplies;
+ struct dev_pm_opp_supply *new_supply = data->new_opp.supplies;
+ unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
+ struct regulator *reg = data->regulators[0];
+ struct device *dev= data->dev;
+ int ret;
+
+ /* This function only supports single regulator per device */
+ if (WARN_ON(data->regulator_count > 1)) {
+ dev_err(dev, "multiple regulators are not supported\n");
+ return -EINVAL;
+ }
+
+ /* Scaling up? Scale voltage before frequency */
+ if (freq > old_freq) {
+ ret = _set_opp_voltage(dev, reg, new_supply);
+ if (ret)
+ goto restore_voltage;
+ }
+
+ /* Change frequency */
+ ret = _generic_set_opp_clk_only(dev, data->clk, old_freq, freq);
+ if (ret)
+ goto restore_voltage;
+
+ /* Scaling down? Scale voltage after frequency */
+ if (freq < old_freq) {
+ ret = _set_opp_voltage(dev, reg, new_supply);
+ if (ret)
+ goto restore_freq;
+ }
+
+ return 0;
+
+restore_freq:
+ if (_generic_set_opp_clk_only(dev, data->clk, freq, old_freq))
+ dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
+ __func__, old_freq);
+restore_voltage:
+ /* This shouldn't harm even if the voltages weren't updated earlier */
+ if (old_supply->u_volt)
+ _set_opp_voltage(dev, reg, old_supply);
return ret;
}
@@ -579,12 +686,13 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
struct opp_table *opp_table;
+ unsigned long freq, old_freq;
+ int (*set_opp)(struct dev_pm_set_opp_data *data);
struct dev_pm_opp *old_opp, *opp;
- struct regulator *reg;
+ struct regulator **regulators;
+ struct dev_pm_set_opp_data *data;
struct clk *clk;
- unsigned long freq, old_freq;
- unsigned long u_volt, u_volt_min, u_volt_max;
- int ret;
+ int ret, size;
if (unlikely(!target_freq)) {
dev_err(dev, "%s: Invalid target frequency %lu\n", __func__,
@@ -633,55 +741,41 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
return ret;
}
- u_volt = opp->u_volt;
- u_volt_min = opp->u_volt_min;
- u_volt_max = opp->u_volt_max;
+ dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__,
+ old_freq, freq);
- reg = opp_table->regulator;
+ regulators = opp_table->regulators;
- rcu_read_unlock();
-
- /* Scaling up? Scale voltage before frequency */
- if (freq > old_freq) {
- ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
- u_volt_max);
- if (ret)
- goto restore_voltage;
- }
-
- /* Change frequency */
-
- dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
- __func__, old_freq, freq);
-
- ret = clk_set_rate(clk, freq);
- if (ret) {
- dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
- ret);
- goto restore_voltage;
+ /* Only frequency scaling */
+ if (!regulators) {
+ rcu_read_unlock();
+ return _generic_set_opp_clk_only(dev, clk, old_freq, freq);
}
- /* Scaling down? Scale voltage after frequency */
- if (freq < old_freq) {
- ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
- u_volt_max);
- if (ret)
- goto restore_freq;
- }
+ if (opp_table->set_opp)
+ set_opp = opp_table->set_opp;
+ else
+ set_opp = _generic_set_opp;
+
+ data = opp_table->set_opp_data;
+ data->regulators = regulators;
+ data->regulator_count = opp_table->regulator_count;
+ data->clk = clk;
+ data->dev = dev;
+
+ data->old_opp.rate = old_freq;
+ size = sizeof(*opp->supplies) * opp_table->regulator_count;
+ if (IS_ERR(old_opp))
+ memset(data->old_opp.supplies, 0, size);
+ else
+ memcpy(data->old_opp.supplies, old_opp->supplies, size);
- return 0;
+ data->new_opp.rate = freq;
+ memcpy(data->new_opp.supplies, opp->supplies, size);
-restore_freq:
- if (clk_set_rate(clk, old_freq))
- dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
- __func__, old_freq);
-restore_voltage:
- /* This shouldn't harm even if the voltages weren't updated earlier */
- if (!IS_ERR(old_opp))
- _set_opp_voltage(dev, reg, old_opp->u_volt,
- old_opp->u_volt_min, old_opp->u_volt_max);
+ rcu_read_unlock();
- return ret;
+ return set_opp(data);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate);
@@ -764,9 +858,6 @@ static struct opp_table *_add_opp_table(struct device *dev)
_of_init_opp_table(opp_table, dev);
- /* Set regulator to a non-NULL error value */
- opp_table->regulator = ERR_PTR(-ENXIO);
-
/* Find clk for the device */
opp_table->clk = clk_get(dev, NULL);
if (IS_ERR(opp_table->clk)) {
@@ -815,7 +906,10 @@ static void _remove_opp_table(struct opp_table *opp_table)
if (opp_table->prop_name)
return;
- if (!IS_ERR(opp_table->regulator))
+ if (opp_table->regulators)
+ return;
+
+ if (opp_table->set_opp)
return;
/* Release clk */
@@ -924,34 +1018,50 @@ struct dev_pm_opp *_allocate_opp(struct device *dev,
struct opp_table **opp_table)
{
struct dev_pm_opp *opp;
+ int count, supply_size;
+ struct opp_table *table;
- /* allocate new OPP node */
- opp = kzalloc(sizeof(*opp), GFP_KERNEL);
- if (!opp)
+ table = _add_opp_table(dev);
+ if (!table)
return NULL;
- INIT_LIST_HEAD(&opp->node);
+ /* Allocate space for at least one supply */
+ count = table->regulator_count ? table->regulator_count : 1;
+ supply_size = sizeof(*opp->supplies) * count;
- *opp_table = _add_opp_table(dev);
- if (!*opp_table) {
- kfree(opp);
+ /* allocate new OPP node and supplies structures */
+ opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
+ if (!opp) {
+ kfree(table);
return NULL;
}
+ /* Put the supplies at the end of the OPP structure as an empty array */
+ opp->supplies = (struct dev_pm_opp_supply *)(opp + 1);
+ INIT_LIST_HEAD(&opp->node);
+
+ *opp_table = table;
+
return opp;
}
static bool _opp_supported_by_regulators(struct dev_pm_opp *opp,
struct opp_table *opp_table)
{
- struct regulator *reg = opp_table->regulator;
-
- if (!IS_ERR(reg) &&
- !regulator_is_supported_voltage(reg, opp->u_volt_min,
- opp->u_volt_max)) {
- pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
- __func__, opp->u_volt_min, opp->u_volt_max);
- return false;
+ struct regulator *reg;
+ int i;
+
+ for (i = 0; i < opp_table->regulator_count; i++) {
+ reg = opp_table->regulators[i];
+
+ if (!regulator_is_supported_voltage(reg,
+ opp->supplies[i].u_volt_min,
+ opp->supplies[i].u_volt_max)) {
+ pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
+ __func__, opp->supplies[i].u_volt_min,
+ opp->supplies[i].u_volt_max);
+ return false;
+ }
}
return true;
@@ -983,11 +1093,13 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
/* Duplicate OPPs */
dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
- __func__, opp->rate, opp->u_volt, opp->available,
- new_opp->rate, new_opp->u_volt, new_opp->available);
+ __func__, opp->rate, opp->supplies[0].u_volt,
+ opp->available, new_opp->rate,
+ new_opp->supplies[0].u_volt, new_opp->available);
- return opp->available && new_opp->u_volt == opp->u_volt ?
- 0 : -EEXIST;
+ /* Should we compare voltages for all regulators here ? */
+ return opp->available &&
+ new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST;
}
new_opp->opp_table = opp_table;
@@ -1054,9 +1166,9 @@ int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
/* populate the opp table */
new_opp->rate = freq;
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
- new_opp->u_volt = u_volt;
- new_opp->u_volt_min = u_volt - tol;
- new_opp->u_volt_max = u_volt + tol;
+ new_opp->supplies[0].u_volt = u_volt;
+ new_opp->supplies[0].u_volt_min = u_volt - tol;
+ new_opp->supplies[0].u_volt_max = u_volt + tol;
new_opp->available = true;
new_opp->dynamic = dynamic;
@@ -1300,13 +1412,47 @@ unlock:
}
EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
+static int _allocate_set_opp_data(struct opp_table *opp_table)
+{
+ struct dev_pm_set_opp_data *data;
+ int len, count = opp_table->regulator_count;
+
+ if (WARN_ON(!count))
+ return -EINVAL;
+
+ /* space for set_opp_data */
+ len = sizeof(*data);
+
+ /* space for old_opp.supplies and new_opp.supplies */
+ len += 2 * sizeof(struct dev_pm_opp_supply) * count;
+
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->old_opp.supplies = (void *)(data + 1);
+ data->new_opp.supplies = data->old_opp.supplies + count;
+
+ opp_table->set_opp_data = data;
+
+ return 0;
+}
+
+static void _free_set_opp_data(struct opp_table *opp_table)
+{
+ kfree(opp_table->set_opp_data);
+ opp_table->set_opp_data = NULL;
+}
+
/**
- * dev_pm_opp_set_regulator() - Set regulator name for the device
+ * dev_pm_opp_set_regulators() - Set regulator names for the device
* @dev: Device for which regulator name is being set.
- * @name: Name of the regulator.
+ * @names: Array of pointers to the names of the regulator.
+ * @count: Number of regulators.
*
* In order to support OPP switching, OPP layer needs to know the name of the
- * device's regulator, as the core would be required to switch voltages as well.
+ * device's regulators, as the core would be required to switch voltages as
+ * well.
*
* This must be called before any OPPs are initialized for the device.
*
@@ -1316,11 +1462,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
* that this function is *NOT* called under RCU protection or in contexts where
* mutex cannot be locked.
*/
-int dev_pm_opp_set_regulator(struct device *dev, const char *name)
+struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
+ const char * const names[],
+ unsigned int count)
{
struct opp_table *opp_table;
struct regulator *reg;
- int ret;
+ int ret, i;
mutex_lock(&opp_table_lock);
@@ -1336,22 +1484,146 @@ int dev_pm_opp_set_regulator(struct device *dev, const char *name)
goto err;
}
- /* Already have a regulator set */
- if (WARN_ON(!IS_ERR(opp_table->regulator))) {
+ /* Already have regulators set */
+ if (opp_table->regulators) {
ret = -EBUSY;
goto err;
}
- /* Allocate the regulator */
- reg = regulator_get_optional(dev, name);
- if (IS_ERR(reg)) {
- ret = PTR_ERR(reg);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "%s: no regulator (%s) found: %d\n",
- __func__, name, ret);
+
+ opp_table->regulators = kmalloc_array(count,
+ sizeof(*opp_table->regulators),
+ GFP_KERNEL);
+ if (!opp_table->regulators) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < count; i++) {
+ reg = regulator_get_optional(dev, names[i]);
+ if (IS_ERR(reg)) {
+ ret = PTR_ERR(reg);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "%s: no regulator (%s) found: %d\n",
+ __func__, names[i], ret);
+ goto free_regulators;
+ }
+
+ opp_table->regulators[i] = reg;
+ }
+
+ opp_table->regulator_count = count;
+
+ /* Allocate block only once to pass to set_opp() routines */
+ ret = _allocate_set_opp_data(opp_table);
+ if (ret)
+ goto free_regulators;
+
+ mutex_unlock(&opp_table_lock);
+ return opp_table;
+
+free_regulators:
+ while (i != 0)
+ regulator_put(opp_table->regulators[--i]);
+
+ kfree(opp_table->regulators);
+ opp_table->regulators = NULL;
+ opp_table->regulator_count = 0;
+err:
+ _remove_opp_table(opp_table);
+unlock:
+ mutex_unlock(&opp_table_lock);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulators);
+
+/**
+ * dev_pm_opp_put_regulators() - Releases resources blocked for regulator
+ * @opp_table: OPP table returned from dev_pm_opp_set_regulators().
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_regulators(struct opp_table *opp_table)
+{
+ int i;
+
+ mutex_lock(&opp_table_lock);
+
+ if (!opp_table->regulators) {
+ pr_err("%s: Doesn't have regulators set\n", __func__);
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating opp_table */
+ WARN_ON(!list_empty(&opp_table->opp_list));
+
+ for (i = opp_table->regulator_count - 1; i >= 0; i--)
+ regulator_put(opp_table->regulators[i]);
+
+ _free_set_opp_data(opp_table);
+
+ kfree(opp_table->regulators);
+ opp_table->regulators = NULL;
+ opp_table->regulator_count = 0;
+
+ /* Try freeing opp_table if this was the last blocking resource */
+ _remove_opp_table(opp_table);
+
+unlock:
+ mutex_unlock(&opp_table_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
+
+/**
+ * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
+ * @dev: Device for which the helper is getting registered.
+ * @set_opp: Custom set OPP helper.
+ *
+ * This is useful to support complex platforms (like platforms with multiple
+ * regulators per device), instead of the generic OPP set rate helper.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_register_set_opp_helper(struct device *dev,
+ int (*set_opp)(struct dev_pm_set_opp_data *data))
+{
+ struct opp_table *opp_table;
+ int ret;
+
+ if (!set_opp)
+ return -EINVAL;
+
+ mutex_lock(&opp_table_lock);
+
+ opp_table = _add_opp_table(dev);
+ if (!opp_table) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* This should be called before OPPs are initialized */
+ if (WARN_ON(!list_empty(&opp_table->opp_list))) {
+ ret = -EBUSY;
goto err;
}
- opp_table->regulator = reg;
+ /* Already have custom set_opp helper */
+ if (WARN_ON(opp_table->set_opp)) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ opp_table->set_opp = set_opp;
mutex_unlock(&opp_table_lock);
return 0;
@@ -1363,11 +1635,12 @@ unlock:
return ret;
}
-EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_set_opp_helper);
/**
- * dev_pm_opp_put_regulator() - Releases resources blocked for regulator
- * @dev: Device for which regulator was set.
+ * dev_pm_opp_register_put_opp_helper() - Releases resources blocked for
+ * set_opp helper
+ * @dev: Device for which custom set_opp helper has to be cleared.
*
* Locking: The internal opp_table and opp structures are RCU protected.
* Hence this function internally uses RCU updater strategy with mutex locks
@@ -1375,7 +1648,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
* that this function is *NOT* called under RCU protection or in contexts where
* mutex cannot be locked.
*/
-void dev_pm_opp_put_regulator(struct device *dev)
+void dev_pm_opp_register_put_opp_helper(struct device *dev)
{
struct opp_table *opp_table;
@@ -1389,16 +1662,16 @@ void dev_pm_opp_put_regulator(struct device *dev)
goto unlock;
}
- if (IS_ERR(opp_table->regulator)) {
- dev_err(dev, "%s: Doesn't have regulator set\n", __func__);
+ if (!opp_table->set_opp) {
+ dev_err(dev, "%s: Doesn't have custom set_opp helper set\n",
+ __func__);
goto unlock;
}
/* Make sure there are no concurrent readers while updating opp_table */
WARN_ON(!list_empty(&opp_table->opp_list));
- regulator_put(opp_table->regulator);
- opp_table->regulator = ERR_PTR(-ENXIO);
+ opp_table->set_opp = NULL;
/* Try freeing opp_table if this was the last blocking resource */
_remove_opp_table(opp_table);
@@ -1406,7 +1679,7 @@ void dev_pm_opp_put_regulator(struct device *dev)
unlock:
mutex_unlock(&opp_table_lock);
}
-EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_put_opp_helper);
/**
* dev_pm_opp_add() - Add an OPP table from a table definitions
diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c
index ef1ae6b52042..95f433db4ac7 100644
--- a/drivers/base/power/opp/debugfs.c
+++ b/drivers/base/power/opp/debugfs.c
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/limits.h>
+#include <linux/slab.h>
#include "opp.h"
@@ -34,6 +35,46 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
debugfs_remove_recursive(opp->dentry);
}
+static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
+ struct opp_table *opp_table,
+ struct dentry *pdentry)
+{
+ struct dentry *d;
+ int i = 0;
+ char *name;
+
+ /* Always create at least supply-0 directory */
+ do {
+ name = kasprintf(GFP_KERNEL, "supply-%d", i);
+
+ /* Create per-opp directory */
+ d = debugfs_create_dir(name, pdentry);
+
+ kfree(name);
+
+ if (!d)
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,
+ &opp->supplies[i].u_volt))
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,
+ &opp->supplies[i].u_volt_min))
+ return false;
+
+ if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,
+ &opp->supplies[i].u_volt_max))
+ return false;
+
+ if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
+ &opp->supplies[i].u_amp))
+ return false;
+ } while (++i < opp_table->regulator_count);
+
+ return true;
+}
+
int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
{
struct dentry *pdentry = opp_table->dentry;
@@ -63,16 +104,7 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
return -ENOMEM;
- if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
+ if (!opp_debug_create_supplies(opp, opp_table, d))
return -ENOMEM;
if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c
index 5552211e6fcd..3f7d2591b173 100644
--- a/drivers/base/power/opp/of.c
+++ b/drivers/base/power/opp/of.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include <linux/export.h>
#include "opp.h"
@@ -101,16 +102,16 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
return true;
}
-/* TODO: Support multiple regulators */
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
struct opp_table *opp_table)
{
- u32 microvolt[3] = {0};
- u32 val;
- int count, ret;
+ u32 *microvolt, *microamp = NULL;
+ int supplies, vcount, icount, ret, i, j;
struct property *prop = NULL;
char name[NAME_MAX];
+ supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
+
/* Search for "opp-microvolt-<name>" */
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microvolt-%s",
@@ -128,34 +129,29 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
return 0;
}
- count = of_property_count_u32_elems(opp->np, name);
- if (count < 0) {
+ vcount = of_property_count_u32_elems(opp->np, name);
+ if (vcount < 0) {
dev_err(dev, "%s: Invalid %s property (%d)\n",
- __func__, name, count);
- return count;
+ __func__, name, vcount);
+ return vcount;
}
- /* There can be one or three elements here */
- if (count != 1 && count != 3) {
- dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
- __func__, name, count);
+ /* There can be one or three elements per supply */
+ if (vcount != supplies && vcount != supplies * 3) {
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+ __func__, name, vcount, supplies);
return -EINVAL;
}
- ret = of_property_read_u32_array(opp->np, name, microvolt, count);
+ microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
+ if (!microvolt)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
if (ret) {
dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
- return -EINVAL;
- }
-
- opp->u_volt = microvolt[0];
-
- if (count == 1) {
- opp->u_volt_min = opp->u_volt;
- opp->u_volt_max = opp->u_volt;
- } else {
- opp->u_volt_min = microvolt[1];
- opp->u_volt_max = microvolt[2];
+ ret = -EINVAL;
+ goto free_microvolt;
}
/* Search for "opp-microamp-<name>" */
@@ -172,10 +168,59 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
prop = of_find_property(opp->np, name, NULL);
}
- if (prop && !of_property_read_u32(opp->np, name, &val))
- opp->u_amp = val;
+ if (prop) {
+ icount = of_property_count_u32_elems(opp->np, name);
+ if (icount < 0) {
+ dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
+ name, icount);
+ ret = icount;
+ goto free_microvolt;
+ }
- return 0;
+ if (icount != supplies) {
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+ __func__, name, icount, supplies);
+ ret = -EINVAL;
+ goto free_microvolt;
+ }
+
+ microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
+ if (!microamp) {
+ ret = -EINVAL;
+ goto free_microvolt;
+ }
+
+ ret = of_property_read_u32_array(opp->np, name, microamp,
+ icount);
+ if (ret) {
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__,
+ name, ret);
+ ret = -EINVAL;
+ goto free_microamp;
+ }
+ }
+
+ for (i = 0, j = 0; i < supplies; i++) {
+ opp->supplies[i].u_volt = microvolt[j++];
+
+ if (vcount == supplies) {
+ opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
+ opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
+ } else {
+ opp->supplies[i].u_volt_min = microvolt[j++];
+ opp->supplies[i].u_volt_max = microvolt[j++];
+ }
+
+ if (microamp)
+ opp->supplies[i].u_amp = microamp[i];
+ }
+
+free_microamp:
+ kfree(microamp);
+free_microvolt:
+ kfree(microvolt);
+
+ return ret;
}
/**
@@ -198,7 +243,7 @@ void dev_pm_opp_of_remove_table(struct device *dev)
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
/* Returns opp descriptor node for a device, caller must do of_node_put() */
-struct device_node *_of_get_opp_desc_node(struct device *dev)
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
{
/*
* TODO: Support for multiple OPP tables.
@@ -303,9 +348,9 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
mutex_unlock(&opp_table_lock);
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
- __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
- new_opp->u_volt_min, new_opp->u_volt_max,
- new_opp->clock_latency_ns);
+ __func__, new_opp->turbo, new_opp->rate,
+ new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
+ new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns);
/*
* Notify the changes in the availability of the operable
@@ -562,7 +607,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
/* 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__);
+ dev_dbg(cpu_dev, "%s: Couldn't find opp node.\n", __func__);
return -ENOENT;
}
@@ -587,7 +632,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
/* 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",
+ dev_err(tcpu_dev, "%s: Couldn't find opp node.\n",
__func__);
ret = -ENOENT;
goto put_cpu_node;
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h
index fabd5ca1a083..af9f2b849a66 100644
--- a/drivers/base/power/opp/opp.h
+++ b/drivers/base/power/opp/opp.h
@@ -61,10 +61,7 @@ extern struct list_head opp_tables;
* @turbo: true if turbo (boost) OPP
* @suspend: true if suspend 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
+ * @supplies: Power supplies voltage/current values
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
* frequency from any other OPP's frequency.
* @opp_table: points back to the opp_table struct this opp belongs to
@@ -83,10 +80,8 @@ struct dev_pm_opp {
bool suspend;
unsigned long rate;
- unsigned long u_volt;
- unsigned long u_volt_min;
- unsigned long u_volt_max;
- unsigned long u_amp;
+ struct dev_pm_opp_supply *supplies;
+
unsigned long clock_latency_ns;
struct opp_table *opp_table;
@@ -144,7 +139,10 @@ enum opp_table_access {
* @supported_hw_count: Number of elements in supported_hw array.
* @prop_name: A name to postfix to many DT properties, while parsing them.
* @clk: Device's clock handle
- * @regulator: Supply regulator
+ * @regulators: Supply regulators
+ * @regulator_count: Number of power supply regulators
+ * @set_opp: Platform specific set_opp callback
+ * @set_opp_data: Data to be passed to set_opp callback
* @dentry: debugfs dentry pointer of the real device directory (not links).
* @dentry_name: Name of the real dentry.
*
@@ -179,7 +177,11 @@ struct opp_table {
unsigned int supported_hw_count;
const char *prop_name;
struct clk *clk;
- struct regulator *regulator;
+ struct regulator **regulators;
+ unsigned int regulator_count;
+
+ int (*set_opp)(struct dev_pm_set_opp_data *data);
+ struct dev_pm_set_opp_data *set_opp_data;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
@@ -190,7 +192,6 @@ struct opp_table {
/* Routines internal to opp core */
struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
-struct device_node *_of_get_opp_desc_node(struct device *dev);
void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 50e30e7b059d..a84332aefc2d 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -21,14 +21,22 @@ extern void pm_runtime_init(struct device *dev);
extern void pm_runtime_reinit(struct device *dev);
extern void pm_runtime_remove(struct device *dev);
+#define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0)
+#define WAKE_IRQ_DEDICATED_MANAGED BIT(1)
+#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
+ WAKE_IRQ_DEDICATED_MANAGED)
+
struct wake_irq {
struct device *dev;
+ unsigned int status;
int irq;
- bool dedicated_irq:1;
};
extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
+extern void dev_pm_enable_wake_irq_check(struct device *dev,
+ bool can_change_status);
+extern void dev_pm_disable_wake_irq_check(struct device *dev);
#ifdef CONFIG_PM_SLEEP
@@ -104,6 +112,15 @@ static inline void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
{
}
+static inline void dev_pm_enable_wake_irq_check(struct device *dev,
+ bool can_change_status)
+{
+}
+
+static inline void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+}
+
#endif
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 7f3646e459cb..58fcc758334e 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -856,7 +856,10 @@ int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
struct dev_pm_qos_request *req;
if (val < 0) {
- ret = -EINVAL;
+ if (val == PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT)
+ ret = 0;
+ else
+ ret = -EINVAL;
goto out;
}
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -883,6 +886,7 @@ int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
mutex_unlock(&dev_pm_qos_mtx);
return ret;
}
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_user_latency_tolerance);
/**
* dev_pm_qos_expose_latency_tolerance - Expose latency tolerance to userspace
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 82a081ea4317..26856d050037 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -241,7 +241,8 @@ static int rpm_check_suspend_allowed(struct device *dev)
retval = -EACCES;
else if (atomic_read(&dev->power.usage_count) > 0)
retval = -EAGAIN;
- else if (!pm_children_suspended(dev))
+ else if (!dev->power.ignore_children &&
+ atomic_read(&dev->power.child_count))
retval = -EBUSY;
/* Pending resume requests take precedence over suspends. */
@@ -515,7 +516,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
callback = RPM_GET_CALLBACK(dev, runtime_suspend);
- dev_pm_enable_wake_irq(dev);
+ dev_pm_enable_wake_irq_check(dev, true);
retval = rpm_callback(callback, dev);
if (retval)
goto fail;
@@ -554,7 +555,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
return retval;
fail:
- dev_pm_disable_wake_irq(dev);
+ dev_pm_disable_wake_irq_check(dev);
__update_runtime_status(dev, RPM_ACTIVE);
dev->power.deferred_resume = false;
wake_up_all(&dev->power.wait_queue);
@@ -712,8 +713,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
spin_lock(&parent->power.lock);
/*
- * We can resume if the parent's runtime PM is disabled or it
- * is set to ignore children.
+ * Resume the parent if it has runtime PM enabled and not been
+ * set to ignore its children.
*/
if (!parent->power.disable_depth
&& !parent->power.ignore_children) {
@@ -737,12 +738,12 @@ static int rpm_resume(struct device *dev, int rpmflags)
callback = RPM_GET_CALLBACK(dev, runtime_resume);
- dev_pm_disable_wake_irq(dev);
+ dev_pm_disable_wake_irq_check(dev);
retval = rpm_callback(callback, dev);
if (retval) {
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_cancel_pending(dev);
- dev_pm_enable_wake_irq(dev);
+ dev_pm_enable_wake_irq_check(dev, false);
} else {
no_callback:
__update_runtime_status(dev, RPM_ACTIVE);
@@ -1027,7 +1028,17 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
goto out_set;
if (status == RPM_SUSPENDED) {
- /* It always is possible to set the status to 'suspended'. */
+ /*
+ * It is invalid to suspend a device with an active child,
+ * unless it has been set to ignore its children.
+ */
+ if (!dev->power.ignore_children &&
+ atomic_read(&dev->power.child_count)) {
+ dev_err(dev, "runtime PM trying to suspend device but active child\n");
+ error = -EBUSY;
+ goto out;
+ }
+
if (parent) {
atomic_add_unless(&parent->power.child_count, -1, 0);
notify_parent = !parent->power.ignore_children;
@@ -1478,6 +1489,16 @@ int pm_runtime_force_suspend(struct device *dev)
if (ret)
goto err;
+ /*
+ * Increase the runtime PM usage count for the device's parent, in case
+ * when we find the device being used when system suspend was invoked.
+ * This informs pm_runtime_force_resume() to resume the parent
+ * immediately, which is needed to be able to resume its children,
+ * when not deferring the resume to be managed via runtime PM.
+ */
+ if (dev->parent && atomic_read(&dev->power.usage_count) > 1)
+ pm_runtime_get_noresume(dev->parent);
+
pm_runtime_set_suspended(dev);
return 0;
err:
@@ -1487,16 +1508,20 @@ err:
EXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
/**
- * pm_runtime_force_resume - Force a device into resume state.
+ * pm_runtime_force_resume - Force a device into resume state if needed.
* @dev: Device to resume.
*
* Prior invoking this function we expect the user to have brought the device
* into low power state by a call to pm_runtime_force_suspend(). Here we reverse
- * those actions and brings the device into full power. We update the runtime PM
- * status and re-enables runtime PM.
+ * those actions and brings the device into full power, if it is expected to be
+ * used on system resume. To distinguish that, we check whether the runtime PM
+ * usage count is greater than 1 (the PM core increases the usage count in the
+ * system PM prepare phase), as that indicates a real user (such as a subsystem,
+ * driver, userspace, etc.) is using it. If that is the case, the device is
+ * expected to be used on system resume as well, so then we resume it. In the
+ * other case, we defer the resume to be managed via runtime PM.
*
- * Typically this function may be invoked from a system resume callback to make
- * sure the device is put into full power state.
+ * Typically this function may be invoked from a system resume callback.
*/
int pm_runtime_force_resume(struct device *dev)
{
@@ -1513,6 +1538,17 @@ int pm_runtime_force_resume(struct device *dev)
if (!pm_runtime_status_suspended(dev))
goto out;
+ /*
+ * Decrease the parent's runtime PM usage count, if we increased it
+ * during system suspend in pm_runtime_force_suspend().
+ */
+ if (atomic_read(&dev->power.usage_count) > 1) {
+ if (dev->parent)
+ pm_runtime_put_noidle(dev->parent);
+ } else {
+ goto out;
+ }
+
ret = pm_runtime_set_active(dev);
if (ret)
goto out;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a7b46798c81d..33b4b902741a 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -263,7 +263,11 @@ static ssize_t pm_qos_latency_tolerance_store(struct device *dev,
s32 value;
int ret;
- if (kstrtos32(buf, 0, &value)) {
+ if (kstrtos32(buf, 0, &value) == 0) {
+ /* Users can't write negative values directly */
+ if (value < 0)
+ return -EINVAL;
+ } else {
if (!strcmp(buf, "auto") || !strcmp(buf, "auto\n"))
value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index efec10b49d59..1cda505d6a85 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -10,6 +10,7 @@
#include <linux/pm-trace.h>
#include <linux/export.h>
#include <linux/rtc.h>
+#include <linux/suspend.h>
#include <linux/mc146818rtc.h>
@@ -74,6 +75,9 @@
#define DEVSEED (7919)
+bool pm_trace_rtc_abused __read_mostly;
+EXPORT_SYMBOL_GPL(pm_trace_rtc_abused);
+
static unsigned int dev_hash_value;
static int set_magic_time(unsigned int user, unsigned int file, unsigned int device)
@@ -104,6 +108,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev
time.tm_min = (n % 20) * 3;
n /= 20;
mc146818_set_time(&time);
+ pm_trace_rtc_abused = true;
return n ? -1 : 0;
}
@@ -239,9 +244,31 @@ int show_trace_dev_match(char *buf, size_t size)
return ret;
}
+static int
+pm_trace_notify(struct notifier_block *nb, unsigned long mode, void *_unused)
+{
+ switch (mode) {
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ if (pm_trace_rtc_abused) {
+ pm_trace_rtc_abused = false;
+ pr_warn("Possible incorrect RTC due to pm_trace, please use 'ntpdate' or 'rdate' to reset it.\n");
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct notifier_block pm_trace_nb = {
+ .notifier_call = pm_trace_notify,
+};
+
static int early_resume_init(void)
{
hash_value_early_read = read_magic_time();
+ register_pm_notifier(&pm_trace_nb);
return 0;
}
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 0d77cd6fd8d1..404d94c6c8bc 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -110,8 +110,10 @@ void dev_pm_clear_wake_irq(struct device *dev)
dev->power.wakeirq = NULL;
spin_unlock_irqrestore(&dev->power.lock, flags);
- if (wirq->dedicated_irq)
+ if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED) {
free_irq(wirq->irq, wirq);
+ wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
+ }
kfree(wirq);
}
EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -179,7 +181,6 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
wirq->dev = dev;
wirq->irq = irq;
- wirq->dedicated_irq = true;
irq_set_status_flags(irq, IRQ_NOAUTOEN);
/*
@@ -195,6 +196,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
if (err)
goto err_free_irq;
+ wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
+
return err;
err_free_irq:
@@ -210,9 +213,9 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
* dev_pm_enable_wake_irq - Enable device wake-up interrupt
* @dev: Device
*
- * Called from the bus code or the device driver for
- * runtime_suspend() to enable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_resume() to override the PM runtime core managed wake-up
+ * interrupt handling to enable the wake-up interrupt.
*
* Note that for runtime_suspend()) the wake-up interrupts
* should be unconditionally enabled unlike for suspend()
@@ -222,7 +225,7 @@ void dev_pm_enable_wake_irq(struct device *dev)
{
struct wake_irq *wirq = dev->power.wakeirq;
- if (wirq && wirq->dedicated_irq)
+ if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
enable_irq(wirq->irq);
}
EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
@@ -231,20 +234,73 @@ EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
* dev_pm_disable_wake_irq - Disable device wake-up interrupt
* @dev: Device
*
- * Called from the bus code or the device driver for
- * runtime_resume() to disable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_suspend() to override the PM runtime core managed wake-up
+ * interrupt handling to disable the wake-up interrupt.
*/
void dev_pm_disable_wake_irq(struct device *dev)
{
struct wake_irq *wirq = dev->power.wakeirq;
- if (wirq && wirq->dedicated_irq)
+ if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
disable_irq_nosync(wirq->irq);
}
EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
/**
+ * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
+ * @dev: Device
+ * @can_change_status: Can change wake-up interrupt status
+ *
+ * Enables wakeirq conditionally. We need to enable wake-up interrupt
+ * lazily on the first rpm_suspend(). This is needed as the consumer device
+ * starts in RPM_SUSPENDED state, and the the first pm_runtime_get() would
+ * otherwise try to disable already disabled wakeirq. The wake-up interrupt
+ * starts disabled with IRQ_NOAUTOEN set.
+ *
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ * Caller must hold &dev->power.lock to change wirq->status
+ */
+void dev_pm_enable_wake_irq_check(struct device *dev,
+ bool can_change_status)
+{
+ struct wake_irq *wirq = dev->power.wakeirq;
+
+ if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+ return;
+
+ if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {
+ goto enable;
+ } else if (can_change_status) {
+ wirq->status |= WAKE_IRQ_DEDICATED_MANAGED;
+ goto enable;
+ }
+
+ return;
+
+enable:
+ enable_irq(wirq->irq);
+}
+
+/**
+ * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
+ * @dev: Device
+ *
+ * Disables wake-up interrupt conditionally based on status.
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ */
+void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+ struct wake_irq *wirq = dev->power.wakeirq;
+
+ if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+ return;
+
+ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+ disable_irq_nosync(wirq->irq);
+}
+
+/**
* dev_pm_arm_wake_irq - Arm device wake-up
* @wirq: Device wake-up interrupt
*
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 62e4de2aa8d1..bf9ba26981a5 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -811,7 +811,7 @@ void pm_print_active_wakeup_sources(void)
rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
if (ws->active) {
- pr_info("active wakeup source: %s\n", ws->name);
+ pr_debug("active wakeup source: %s\n", ws->name);
active = 1;
} else if (!active &&
(!last_activity_ws ||
@@ -822,7 +822,7 @@ void pm_print_active_wakeup_sources(void)
}
if (!active && last_activity_ws)
- pr_info("last active wakeup source: %s\n",
+ pr_debug("last active wakeup source: %s\n",
last_activity_ws->name);
rcu_read_unlock();
}
@@ -905,7 +905,7 @@ bool pm_get_wakeup_count(unsigned int *count, bool block)
split_counters(&cnt, &inpr);
if (inpr == 0 || signal_pending(current))
break;
-
+ pm_print_active_wakeup_sources();
schedule();
}
finish_wait(&wakeup_count_wait_queue, &wait);
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index 6f77d7319fc6..4ff311374c4a 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -236,15 +236,13 @@ static int regcache_lzo_read(struct regmap *map,
{
struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
int ret, blkindex, blkpos;
- size_t blksize, tmp_dst_len;
+ size_t tmp_dst_len;
void *tmp_dst;
/* index of the compressed lzo block */
blkindex = regcache_lzo_get_blkindex(map, reg);
/* register index within the decompressed block */
blkpos = regcache_lzo_get_blkpos(map, reg);
- /* size of the compressed block */
- blksize = regcache_lzo_get_blksize(map);
lzo_blocks = map->cache;
lzo_block = lzo_blocks[blkindex];
@@ -275,15 +273,13 @@ static int regcache_lzo_write(struct regmap *map,
{
struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
int ret, blkindex, blkpos;
- size_t blksize, tmp_dst_len;
+ size_t tmp_dst_len;
void *tmp_dst;
/* index of the compressed lzo block */
blkindex = regcache_lzo_get_blkindex(map, reg);
/* register index within the decompressed block */
blkpos = regcache_lzo_get_blkpos(map, reg);
- /* size of the compressed block */
- blksize = regcache_lzo_get_blksize(map);
lzo_blocks = map->cache;
lzo_block = lzo_blocks[blkindex];
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index b63f23e6ad61..dc26e5949a32 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <linux/sys_soc.h>
#include <linux/err.h>
+#include <linux/glob.h>
static DEFINE_IDA(soc_ida);
@@ -113,6 +114,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
struct soc_device *soc_dev;
int ret;
+ if (!soc_bus_type.p) {
+ ret = bus_register(&soc_bus_type);
+ if (ret)
+ goto out1;
+ }
+
soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
if (!soc_dev) {
ret = -ENOMEM;
@@ -156,6 +163,78 @@ void soc_device_unregister(struct soc_device *soc_dev)
static int __init soc_bus_register(void)
{
+ if (soc_bus_type.p)
+ return 0;
+
return bus_register(&soc_bus_type);
}
core_initcall(soc_bus_register);
+
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+ struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+ const struct soc_device_attribute *match = arg;
+
+ if (match->machine &&
+ (!soc_dev->attr->machine ||
+ !glob_match(match->machine, soc_dev->attr->machine)))
+ return 0;
+
+ if (match->family &&
+ (!soc_dev->attr->family ||
+ !glob_match(match->family, soc_dev->attr->family)))
+ return 0;
+
+ if (match->revision &&
+ (!soc_dev->attr->revision ||
+ !glob_match(match->revision, soc_dev->attr->revision)))
+ return 0;
+
+ if (match->soc_id &&
+ (!soc_dev->attr->soc_id ||
+ !glob_match(match->soc_id, soc_dev->attr->soc_id)))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * soc_device_match - identify the SoC in the machine
+ * @matches: zero-terminated array of possible matches
+ *
+ * returns the first matching entry of the argument array, or NULL
+ * if none of them match.
+ *
+ * This function is meant as a helper in place of of_match_node()
+ * in cases where either no device tree is available or the information
+ * in a device node is insufficient to identify a particular variant
+ * by its compatible strings or other properties. For new devices,
+ * the DT binding should always provide unique compatible strings
+ * that allow the use of of_match_node() instead.
+ *
+ * The calling function can use the .data entry of the
+ * soc_device_attribute to pass a structure or function pointer for
+ * each entry.
+ */
+const struct soc_device_attribute *soc_device_match(
+ const struct soc_device_attribute *matches)
+{
+ int ret = 0;
+
+ if (!matches)
+ return NULL;
+
+ while (!ret) {
+ if (!(matches->machine || matches->family ||
+ matches->revision || matches->soc_id))
+ break;
+ ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
+ soc_device_match_one);
+ if (!ret)
+ matches++;
+ else
+ return matches;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(soc_device_match);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index df3c97cb4c99..d6ec1c546f5b 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -118,51 +118,19 @@ static int topology_add_dev(unsigned int cpu)
return sysfs_create_group(&dev->kobj, &topology_attr_group);
}
-static void topology_remove_dev(unsigned int cpu)
+static int topology_remove_dev(unsigned int cpu)
{
struct device *dev = get_cpu_device(cpu);
sysfs_remove_group(&dev->kobj, &topology_attr_group);
-}
-
-static int topology_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
- int rc = 0;
-
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- rc = topology_add_dev(cpu);
- break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- topology_remove_dev(cpu);
- break;
- }
- return notifier_from_errno(rc);
+ return 0;
}
static int topology_sysfs_init(void)
{
- int cpu;
- int rc = 0;
-
- cpu_notifier_register_begin();
-
- for_each_online_cpu(cpu) {
- rc = topology_add_dev(cpu);
- if (rc)
- goto out;
- }
- __hotcpu_notifier(topology_cpu_callback, 0);
-
-out:
- cpu_notifier_register_done();
- return rc;
+ return cpuhp_setup_state(CPUHP_TOPOLOGY_PREPARE,
+ "base/topology:prepare", topology_add_dev,
+ topology_remove_dev);
}
device_initcall(topology_sysfs_init);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index bd46569e0e52..925842996986 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -295,6 +295,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 39dd30b6ef86..223ff2fcae7e 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -384,9 +384,12 @@ config BLK_DEV_RAM_DAX
allocated from highmem (only a problem for highmem systems).
config CDROM_PKTCDVD
- tristate "Packet writing on CD/DVD media"
+ tristate "Packet writing on CD/DVD media (DEPRECATED)"
depends on !UML
help
+ Note: This driver is deprecated and will be removed from the
+ kernel in the near future!
+
If you have a CDROM/DVD drive that supports packet writing, say
Y to include support. It should work with any MMC/Mt Fuji
compliant ATAPI or SCSI drive, which is just about any newer
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 0c76d4016eeb..ad793f35632c 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -395,44 +395,9 @@ static long brd_direct_access(struct block_device *bdev, sector_t sector,
#define brd_direct_access NULL
#endif
-static int brd_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- int error;
- struct brd_device *brd = bdev->bd_disk->private_data;
-
- if (cmd != BLKFLSBUF)
- return -ENOTTY;
-
- /*
- * ram device BLKFLSBUF has special semantics, we want to actually
- * release and destroy the ramdisk data.
- */
- mutex_lock(&brd_mutex);
- mutex_lock(&bdev->bd_mutex);
- error = -EBUSY;
- if (bdev->bd_openers <= 1) {
- /*
- * Kill the cache first, so it isn't written back to the
- * device.
- *
- * Another thread might instantiate more buffercache here,
- * but there is not much we can do to close that race.
- */
- kill_bdev(bdev);
- brd_free_pages(brd);
- error = 0;
- }
- mutex_unlock(&bdev->bd_mutex);
- mutex_unlock(&brd_mutex);
-
- return error;
-}
-
static const struct block_device_operations brd_fops = {
.owner = THIS_MODULE,
.rw_page = brd_rw_page,
- .ioctl = brd_ioctl,
.direct_access = brd_direct_access,
};
@@ -443,8 +408,8 @@ static int rd_nr = CONFIG_BLK_DEV_RAM_COUNT;
module_param(rd_nr, int, S_IRUGO);
MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
-int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
-module_param(rd_size, int, S_IRUGO);
+unsigned long rd_size = CONFIG_BLK_DEV_RAM_SIZE;
+module_param(rd_size, ulong, S_IRUGO);
MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
static int max_part = 1;
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 2d3d50ab74bf..8d7bcfa49c12 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -148,7 +148,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device,
if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags))
op_flags |= REQ_FUA | REQ_PREFLUSH;
- op_flags |= REQ_SYNC | REQ_NOIDLE;
+ op_flags |= REQ_SYNC;
bio = bio_alloc_drbd(GFP_NOIO);
bio->bi_bdev = bdev->md_bdev;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 942384f34e22..c7728dd77230 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1266,7 +1266,7 @@ static void submit_one_flush(struct drbd_device *device, struct issue_flush_cont
bio->bi_bdev = device->ldev->backing_bdev;
bio->bi_private = octx;
bio->bi_end_io = one_flush_endio;
- bio_set_op_attrs(bio, REQ_OP_FLUSH, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
device->flush_jif = jiffies;
set_bit(FLUSH_PENDING, &device->flags);
@@ -1648,20 +1648,8 @@ next_bio:
page_chain_for_each(page) {
unsigned len = min_t(unsigned, data_size, PAGE_SIZE);
- if (!bio_add_page(bio, page, len, 0)) {
- /* A single page must always be possible!
- * But in case it fails anyways,
- * we deal with it, and complain (below). */
- if (bio->bi_vcnt == 0) {
- drbd_err(device,
- "bio_add_page failed for len=%u, "
- "bi_vcnt=0 (bi_sector=%llu)\n",
- len, (uint64_t)bio->bi_iter.bi_sector);
- err = -ENOSPC;
- goto fail;
- }
+ if (!bio_add_page(bio, page, len, 0))
goto next_bio;
- }
data_size -= len;
sector += len >> 9;
--nr_pages;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index e3d8e4ced4a2..a391a3cfb3fe 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3806,14 +3806,10 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive)
cbdata.drive = drive;
- bio_init(&bio);
- bio.bi_io_vec = &bio_vec;
- bio_vec.bv_page = page;
- bio_vec.bv_len = size;
- bio_vec.bv_offset = 0;
- bio.bi_vcnt = 1;
- bio.bi_iter.bi_size = size;
+ bio_init(&bio, &bio_vec, 1);
bio.bi_bdev = bdev;
+ bio_add_page(&bio, page, size, 0);
+
bio.bi_iter.bi_sector = 0;
bio.bi_flags |= (1 << BIO_QUIET);
bio.bi_private = &cbdata;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fa1b7a90ba11..4af818766797 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1646,7 +1646,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(bd->rq);
if (lo->lo_state != Lo_bound)
- return -EIO;
+ return BLK_MQ_RQ_QUEUE_ERROR;
switch (req_op(cmd->rq)) {
case REQ_OP_FLUSH:
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 3cfd879267b2..f96ab717534c 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2035,18 +2035,14 @@ static int exec_drive_taskfile(struct driver_data *dd,
taskout = req_task->out_size;
taskin = req_task->in_size;
/* 130560 = 512 * 0xFF*/
- if (taskin > 130560 || taskout > 130560) {
- err = -EINVAL;
- goto abort;
- }
+ if (taskin > 130560 || taskout > 130560)
+ return -EINVAL;
if (taskout) {
outbuf = memdup_user(buf + outtotal, taskout);
- if (IS_ERR(outbuf)) {
- err = PTR_ERR(outbuf);
- outbuf = NULL;
- goto abort;
- }
+ if (IS_ERR(outbuf))
+ return PTR_ERR(outbuf);
+
outbuf_dma = pci_map_single(dd->pdev,
outbuf,
taskout,
@@ -3937,8 +3933,10 @@ static int mtip_block_initialize(struct driver_data *dd)
/* Generate the disk name, implemented same as in sd.c */
do {
- if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL))
+ if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL)) {
+ rv = -ENOMEM;
goto ida_get_error;
+ }
spin_lock(&rssd_index_lock);
rv = ida_get_new(&rssd_index_ida, &index);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7a1048755914..99c84468f154 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -41,26 +41,34 @@
#include <linux/nbd.h>
+struct nbd_sock {
+ struct socket *sock;
+ struct mutex tx_lock;
+};
+
#define NBD_TIMEDOUT 0
#define NBD_DISCONNECT_REQUESTED 1
+#define NBD_DISCONNECTED 2
+#define NBD_RUNNING 3
struct nbd_device {
u32 flags;
unsigned long runtime_flags;
- struct socket * sock; /* If == NULL, device is not ready, yet */
+ struct nbd_sock **socks;
int magic;
struct blk_mq_tag_set tag_set;
- struct mutex tx_lock;
+ struct mutex config_lock;
struct gendisk *disk;
- int blksize;
+ int num_connections;
+ atomic_t recv_threads;
+ wait_queue_head_t recv_wq;
+ loff_t blksize;
loff_t bytesize;
- /* protects initialization and shutdown of the socket */
- spinlock_t sock_lock;
struct task_struct *task_recv;
- struct task_struct *task_send;
+ struct task_struct *task_setup;
#if IS_ENABLED(CONFIG_DEBUG_FS)
struct dentry *dbg_dir;
@@ -69,7 +77,7 @@ struct nbd_device {
struct nbd_cmd {
struct nbd_device *nbd;
- struct list_head list;
+ struct completion send_complete;
};
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -126,7 +134,7 @@ static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev)
}
static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
- int blocksize, int nr_blocks)
+ loff_t blocksize, loff_t nr_blocks)
{
int ret;
@@ -135,7 +143,7 @@ static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
return ret;
nbd->blksize = blocksize;
- nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
+ nbd->bytesize = blocksize * nr_blocks;
nbd_size_update(nbd, bdev);
@@ -159,22 +167,20 @@ static void nbd_end_request(struct nbd_cmd *cmd)
*/
static void sock_shutdown(struct nbd_device *nbd)
{
- struct socket *sock;
-
- spin_lock(&nbd->sock_lock);
+ int i;
- if (!nbd->sock) {
- spin_unlock(&nbd->sock_lock);
+ if (nbd->num_connections == 0)
+ return;
+ if (test_and_set_bit(NBD_DISCONNECTED, &nbd->runtime_flags))
return;
- }
-
- sock = nbd->sock;
- dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
- nbd->sock = NULL;
- spin_unlock(&nbd->sock_lock);
- kernel_sock_shutdown(sock, SHUT_RDWR);
- sockfd_put(sock);
+ for (i = 0; i < nbd->num_connections; i++) {
+ struct nbd_sock *nsock = nbd->socks[i];
+ mutex_lock(&nsock->tx_lock);
+ kernel_sock_shutdown(nsock->sock, SHUT_RDWR);
+ mutex_unlock(&nsock->tx_lock);
+ }
+ dev_warn(disk_to_dev(nbd->disk), "shutting down sockets\n");
}
static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
@@ -182,42 +188,38 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
struct nbd_device *nbd = cmd->nbd;
- struct socket *sock = NULL;
-
- spin_lock(&nbd->sock_lock);
+ dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
set_bit(NBD_TIMEDOUT, &nbd->runtime_flags);
-
- if (nbd->sock) {
- sock = nbd->sock;
- get_file(sock->file);
- }
-
- spin_unlock(&nbd->sock_lock);
- if (sock) {
- kernel_sock_shutdown(sock, SHUT_RDWR);
- sockfd_put(sock);
- }
-
req->errors++;
- dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
+
+ /*
+ * If our disconnect packet times out then we're already holding the
+ * config_lock and could deadlock here, so just set an error and return,
+ * we'll handle shutting everything down later.
+ */
+ if (req->cmd_type == REQ_TYPE_DRV_PRIV)
+ return BLK_EH_HANDLED;
+ mutex_lock(&nbd->config_lock);
+ sock_shutdown(nbd);
+ mutex_unlock(&nbd->config_lock);
return BLK_EH_HANDLED;
}
/*
* Send or receive packet.
*/
-static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
- int msg_flags)
+static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
+ int size, int msg_flags)
{
- struct socket *sock = nbd->sock;
+ struct socket *sock = nbd->socks[index]->sock;
int result;
struct msghdr msg;
struct kvec iov;
unsigned long pflags = current->flags;
if (unlikely(!sock)) {
- dev_err(disk_to_dev(nbd->disk),
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
"Attempted %s on closed socket in sock_xmit\n",
(send ? "send" : "recv"));
return -EINVAL;
@@ -254,29 +256,29 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
return result;
}
-static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
- int flags)
+static inline int sock_send_bvec(struct nbd_device *nbd, int index,
+ struct bio_vec *bvec, int flags)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
+ result = sock_xmit(nbd, index, 1, kaddr + bvec->bv_offset,
bvec->bv_len, flags);
kunmap(bvec->bv_page);
return result;
}
/* always call with the tx_lock held */
-static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
+static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
{
struct request *req = blk_mq_rq_from_pdu(cmd);
int result, flags;
struct nbd_request request;
unsigned long size = blk_rq_bytes(req);
+ struct bio *bio;
u32 type;
+ u32 tag = blk_mq_unique_tag(req);
- if (req->cmd_type == REQ_TYPE_DRV_PRIV)
- type = NBD_CMD_DISC;
- else if (req_op(req) == REQ_OP_DISCARD)
+ if (req_op(req) == REQ_OP_DISCARD)
type = NBD_CMD_TRIM;
else if (req_op(req) == REQ_OP_FLUSH)
type = NBD_CMD_FLUSH;
@@ -288,73 +290,89 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
memset(&request, 0, sizeof(request));
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(type);
- if (type != NBD_CMD_FLUSH && type != NBD_CMD_DISC) {
+ if (type != NBD_CMD_FLUSH) {
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
request.len = htonl(size);
}
- memcpy(request.handle, &req->tag, sizeof(req->tag));
+ memcpy(request.handle, &tag, sizeof(tag));
dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n",
cmd, nbdcmd_to_ascii(type),
(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req));
- result = sock_xmit(nbd, 1, &request, sizeof(request),
+ result = sock_xmit(nbd, index, 1, &request, sizeof(request),
(type == NBD_CMD_WRITE) ? MSG_MORE : 0);
if (result <= 0) {
- dev_err(disk_to_dev(nbd->disk),
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
"Send control failed (result %d)\n", result);
return -EIO;
}
- if (type == NBD_CMD_WRITE) {
- struct req_iterator iter;
+ if (type != NBD_CMD_WRITE)
+ return 0;
+
+ flags = 0;
+ bio = req->bio;
+ while (bio) {
+ struct bio *next = bio->bi_next;
+ struct bvec_iter iter;
struct bio_vec bvec;
- /*
- * we are really probing at internals to determine
- * whether to set MSG_MORE or not...
- */
- rq_for_each_segment(bvec, req, iter) {
- flags = 0;
- if (!rq_iter_last(bvec, iter))
+
+ bio_for_each_segment(bvec, bio, iter) {
+ bool is_last = !next && bio_iter_last(bvec, iter);
+
+ if (is_last)
flags = MSG_MORE;
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
cmd, bvec.bv_len);
- result = sock_send_bvec(nbd, &bvec, flags);
+ result = sock_send_bvec(nbd, index, &bvec, flags);
if (result <= 0) {
dev_err(disk_to_dev(nbd->disk),
"Send data failed (result %d)\n",
result);
return -EIO;
}
+ /*
+ * The completion might already have come in,
+ * so break for the last one instead of letting
+ * the iterator do it. This prevents use-after-free
+ * of the bio.
+ */
+ if (is_last)
+ break;
}
+ bio = next;
}
return 0;
}
-static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
+static inline int sock_recv_bvec(struct nbd_device *nbd, int index,
+ struct bio_vec *bvec)
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
- MSG_WAITALL);
+ result = sock_xmit(nbd, index, 0, kaddr + bvec->bv_offset,
+ bvec->bv_len, MSG_WAITALL);
kunmap(bvec->bv_page);
return result;
}
/* NULL returned = something went wrong, inform userspace */
-static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
+static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
{
int result;
struct nbd_reply reply;
struct nbd_cmd *cmd;
struct request *req = NULL;
u16 hwq;
- int tag;
+ u32 tag;
reply.magic = 0;
- result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
+ result = sock_xmit(nbd, index, 0, &reply, sizeof(reply), MSG_WAITALL);
if (result <= 0) {
- dev_err(disk_to_dev(nbd->disk),
- "Receive control failed (result %d)\n", result);
+ if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
+ !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
+ dev_err(disk_to_dev(nbd->disk),
+ "Receive control failed (result %d)\n", result);
return ERR_PTR(result);
}
@@ -364,7 +382,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
return ERR_PTR(-EPROTO);
}
- memcpy(&tag, reply.handle, sizeof(int));
+ memcpy(&tag, reply.handle, sizeof(u32));
hwq = blk_mq_unique_tag_to_hwq(tag);
if (hwq < nbd->tag_set.nr_hw_queues)
@@ -376,7 +394,6 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
return ERR_PTR(-ENOENT);
}
cmd = blk_mq_rq_to_pdu(req);
-
if (ntohl(reply.error)) {
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
ntohl(reply.error));
@@ -390,7 +407,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
struct bio_vec bvec;
rq_for_each_segment(bvec, req, iter) {
- result = sock_recv_bvec(nbd, &bvec);
+ result = sock_recv_bvec(nbd, index, &bvec);
if (result <= 0) {
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
result);
@@ -400,6 +417,9 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data\n",
cmd, bvec.bv_len);
}
+ } else {
+ /* See the comment in nbd_queue_rq. */
+ wait_for_completion(&cmd->send_complete);
}
return cmd;
}
@@ -418,25 +438,24 @@ static struct device_attribute pid_attr = {
.show = pid_show,
};
-static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
+struct recv_thread_args {
+ struct work_struct work;
+ struct nbd_device *nbd;
+ int index;
+};
+
+static void recv_work(struct work_struct *work)
{
+ struct recv_thread_args *args = container_of(work,
+ struct recv_thread_args,
+ work);
+ struct nbd_device *nbd = args->nbd;
struct nbd_cmd *cmd;
- int ret;
+ int ret = 0;
BUG_ON(nbd->magic != NBD_MAGIC);
-
- sk_set_memalloc(nbd->sock->sk);
-
- 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");
- return ret;
- }
-
- nbd_size_update(nbd, bdev);
-
while (1) {
- cmd = nbd_read_stat(nbd);
+ cmd = nbd_read_stat(nbd, args->index);
if (IS_ERR(cmd)) {
ret = PTR_ERR(cmd);
break;
@@ -445,10 +464,14 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
nbd_end_request(cmd);
}
- nbd_size_clear(nbd, bdev);
-
- device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
- return ret;
+ /*
+ * We got an error, shut everybody down if this wasn't the result of a
+ * disconnect request.
+ */
+ if (ret && !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
+ sock_shutdown(nbd);
+ atomic_dec(&nbd->recv_threads);
+ wake_up(&nbd->recv_wq);
}
static void nbd_clear_req(struct request *req, void *data, bool reserved)
@@ -466,51 +489,60 @@ static void nbd_clear_que(struct nbd_device *nbd)
{
BUG_ON(nbd->magic != NBD_MAGIC);
- /*
- * Because we have set nbd->sock to NULL under the tx_lock, all
- * modifications to the list must have completed by now.
- */
- BUG_ON(nbd->sock);
-
blk_mq_tagset_busy_iter(&nbd->tag_set, nbd_clear_req, NULL);
dev_dbg(disk_to_dev(nbd->disk), "queue cleared\n");
}
-static void nbd_handle_cmd(struct nbd_cmd *cmd)
+static void nbd_handle_cmd(struct nbd_cmd *cmd, int index)
{
struct request *req = blk_mq_rq_from_pdu(cmd);
struct nbd_device *nbd = cmd->nbd;
+ struct nbd_sock *nsock;
+
+ if (index >= nbd->num_connections) {
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Attempted send on invalid socket\n");
+ goto error_out;
+ }
+
+ if (test_bit(NBD_DISCONNECTED, &nbd->runtime_flags)) {
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Attempted send on closed socket\n");
+ goto error_out;
+ }
- if (req->cmd_type != REQ_TYPE_FS)
+ if (req->cmd_type != REQ_TYPE_FS &&
+ req->cmd_type != REQ_TYPE_DRV_PRIV)
goto error_out;
- if (rq_data_dir(req) == WRITE &&
+ if (req->cmd_type == REQ_TYPE_FS &&
+ rq_data_dir(req) == WRITE &&
(nbd->flags & NBD_FLAG_READ_ONLY)) {
- dev_err(disk_to_dev(nbd->disk),
- "Write on read-only\n");
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Write on read-only\n");
goto error_out;
}
req->errors = 0;
- mutex_lock(&nbd->tx_lock);
- nbd->task_send = current;
- if (unlikely(!nbd->sock)) {
- mutex_unlock(&nbd->tx_lock);
- dev_err(disk_to_dev(nbd->disk),
- "Attempted send on closed socket\n");
+ nsock = nbd->socks[index];
+ mutex_lock(&nsock->tx_lock);
+ if (unlikely(!nsock->sock)) {
+ mutex_unlock(&nsock->tx_lock);
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Attempted send on closed socket\n");
goto error_out;
}
- if (nbd_send_cmd(nbd, cmd) != 0) {
- dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
+ if (nbd_send_cmd(nbd, cmd, index) != 0) {
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Request send failed\n");
req->errors++;
nbd_end_request(cmd);
}
- nbd->task_send = NULL;
- mutex_unlock(&nbd->tx_lock);
+ mutex_unlock(&nsock->tx_lock);
return;
@@ -524,39 +556,70 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
+ /*
+ * Since we look at the bio's to send the request over the network we
+ * need to make sure the completion work doesn't mark this request done
+ * before we are done doing our send. This keeps us from dereferencing
+ * freed data if we have particularly fast completions (ie we get the
+ * completion before we exit sock_xmit on the last bvec) or in the case
+ * that the server is misbehaving (or there was an error) before we're
+ * done sending everything over the wire.
+ */
+ init_completion(&cmd->send_complete);
blk_mq_start_request(bd->rq);
- nbd_handle_cmd(cmd);
+ nbd_handle_cmd(cmd, hctx->queue_num);
+ complete(&cmd->send_complete);
+
return BLK_MQ_RQ_QUEUE_OK;
}
-static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock)
+static int nbd_add_socket(struct nbd_device *nbd, struct socket *sock)
{
- int ret = 0;
-
- spin_lock_irq(&nbd->sock_lock);
+ struct nbd_sock **socks;
+ struct nbd_sock *nsock;
- if (nbd->sock) {
- ret = -EBUSY;
- goto out;
+ if (!nbd->task_setup)
+ nbd->task_setup = current;
+ if (nbd->task_setup != current) {
+ dev_err(disk_to_dev(nbd->disk),
+ "Device being setup by another task");
+ return -EINVAL;
}
- nbd->sock = sock;
+ socks = krealloc(nbd->socks, (nbd->num_connections + 1) *
+ sizeof(struct nbd_sock *), GFP_KERNEL);
+ if (!socks)
+ return -ENOMEM;
+ nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL);
+ if (!nsock)
+ return -ENOMEM;
-out:
- spin_unlock_irq(&nbd->sock_lock);
+ nbd->socks = socks;
+
+ mutex_init(&nsock->tx_lock);
+ nsock->sock = sock;
+ socks[nbd->num_connections++] = nsock;
- return ret;
+ return 0;
}
/* Reset all properties of an NBD device */
static void nbd_reset(struct nbd_device *nbd)
{
+ int i;
+
+ for (i = 0; i < nbd->num_connections; i++)
+ kfree(nbd->socks[i]);
+ kfree(nbd->socks);
+ nbd->socks = NULL;
nbd->runtime_flags = 0;
nbd->blksize = 1024;
nbd->bytesize = 0;
set_capacity(nbd->disk, 0);
nbd->flags = 0;
nbd->tag_set.timeout = 0;
+ nbd->num_connections = 0;
+ nbd->task_setup = NULL;
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
}
@@ -582,48 +645,68 @@ static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev)
blk_queue_write_cache(nbd->disk->queue, false, false);
}
+static void send_disconnects(struct nbd_device *nbd)
+{
+ struct nbd_request request = {};
+ int i, ret;
+
+ request.magic = htonl(NBD_REQUEST_MAGIC);
+ request.type = htonl(NBD_CMD_DISC);
+
+ for (i = 0; i < nbd->num_connections; i++) {
+ ret = sock_xmit(nbd, i, 1, &request, sizeof(request), 0);
+ if (ret <= 0)
+ dev_err(disk_to_dev(nbd->disk),
+ "Send disconnect failed %d\n", ret);
+ }
+}
+
static int nbd_dev_dbg_init(struct nbd_device *nbd);
static void nbd_dev_dbg_close(struct nbd_device *nbd);
-/* Must be called with tx_lock held */
-
+/* Must be called with config_lock held */
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case NBD_DISCONNECT: {
- struct request *sreq;
-
dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
- if (!nbd->sock)
+ if (!nbd->socks)
return -EINVAL;
- sreq = blk_mq_alloc_request(bdev_get_queue(bdev), WRITE, 0);
- if (IS_ERR(sreq))
- return -ENOMEM;
-
- mutex_unlock(&nbd->tx_lock);
+ mutex_unlock(&nbd->config_lock);
fsync_bdev(bdev);
- mutex_lock(&nbd->tx_lock);
- sreq->cmd_type = REQ_TYPE_DRV_PRIV;
+ mutex_lock(&nbd->config_lock);
/* Check again after getting mutex back. */
- if (!nbd->sock) {
- blk_mq_free_request(sreq);
+ if (!nbd->socks)
return -EINVAL;
- }
- set_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags);
-
- nbd_send_cmd(nbd, blk_mq_rq_to_pdu(sreq));
- blk_mq_free_request(sreq);
+ if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED,
+ &nbd->runtime_flags))
+ send_disconnects(nbd);
return 0;
}
-
+
case NBD_CLEAR_SOCK:
sock_shutdown(nbd);
nbd_clear_que(nbd);
kill_bdev(bdev);
+ nbd_bdev_reset(bdev);
+ /*
+ * We want to give the run thread a chance to wait for everybody
+ * to clean up and then do it's own cleanup.
+ */
+ if (!test_bit(NBD_RUNNING, &nbd->runtime_flags)) {
+ int i;
+
+ for (i = 0; i < nbd->num_connections; i++)
+ kfree(nbd->socks[i]);
+ kfree(nbd->socks);
+ nbd->socks = NULL;
+ nbd->num_connections = 0;
+ nbd->task_setup = NULL;
+ }
return 0;
case NBD_SET_SOCK: {
@@ -633,7 +716,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
if (!sock)
return err;
- err = nbd_set_socket(nbd, sock);
+ err = nbd_add_socket(nbd, sock);
if (!err && max_part)
bdev->bd_invalidated = 1;
@@ -648,7 +731,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
case NBD_SET_SIZE:
return nbd_size_set(nbd, bdev, nbd->blksize,
- arg / nbd->blksize);
+ div_s64(arg, nbd->blksize));
case NBD_SET_SIZE_BLOCKS:
return nbd_size_set(nbd, bdev, nbd->blksize, arg);
@@ -662,26 +745,61 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
return 0;
case NBD_DO_IT: {
- int error;
+ struct recv_thread_args *args;
+ int num_connections = nbd->num_connections;
+ int error = 0, i;
if (nbd->task_recv)
return -EBUSY;
- if (!nbd->sock)
+ if (!nbd->socks)
return -EINVAL;
+ if (num_connections > 1 &&
+ !(nbd->flags & NBD_FLAG_CAN_MULTI_CONN)) {
+ dev_err(disk_to_dev(nbd->disk), "server does not support multiple connections per device.\n");
+ error = -EINVAL;
+ goto out_err;
+ }
- /* We have to claim the device under the lock */
+ set_bit(NBD_RUNNING, &nbd->runtime_flags);
+ blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
+ args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
+ if (!args) {
+ error = -ENOMEM;
+ goto out_err;
+ }
nbd->task_recv = current;
- mutex_unlock(&nbd->tx_lock);
+ mutex_unlock(&nbd->config_lock);
nbd_parse_flags(nbd, bdev);
+ error = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
+ if (error) {
+ dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+ goto out_recv;
+ }
+
+ nbd_size_update(nbd, bdev);
+
nbd_dev_dbg_init(nbd);
- error = nbd_thread_recv(nbd, bdev);
+ for (i = 0; i < num_connections; i++) {
+ sk_set_memalloc(nbd->socks[i]->sock->sk);
+ atomic_inc(&nbd->recv_threads);
+ INIT_WORK(&args[i].work, recv_work);
+ args[i].nbd = nbd;
+ args[i].index = i;
+ queue_work(system_long_wq, &args[i].work);
+ }
+ wait_event_interruptible(nbd->recv_wq,
+ atomic_read(&nbd->recv_threads) == 0);
+ for (i = 0; i < num_connections; i++)
+ flush_work(&args[i].work);
nbd_dev_dbg_close(nbd);
-
- mutex_lock(&nbd->tx_lock);
+ nbd_size_clear(nbd, bdev);
+ device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
+out_recv:
+ mutex_lock(&nbd->config_lock);
nbd->task_recv = NULL;
-
+out_err:
sock_shutdown(nbd);
nbd_clear_que(nbd);
kill_bdev(bdev);
@@ -694,7 +812,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
error = -ETIMEDOUT;
nbd_reset(nbd);
-
return error;
}
@@ -726,9 +843,9 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
BUG_ON(nbd->magic != NBD_MAGIC);
- mutex_lock(&nbd->tx_lock);
+ mutex_lock(&nbd->config_lock);
error = __nbd_ioctl(bdev, nbd, cmd, arg);
- mutex_unlock(&nbd->tx_lock);
+ mutex_unlock(&nbd->config_lock);
return error;
}
@@ -748,8 +865,6 @@ static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
if (nbd->task_recv)
seq_printf(s, "recv: %d\n", task_pid_nr(nbd->task_recv));
- if (nbd->task_send)
- seq_printf(s, "send: %d\n", task_pid_nr(nbd->task_send));
return 0;
}
@@ -817,7 +932,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd)
debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout);
- debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
+ debugfs_create_u64("blocksize", 0444, dir, &nbd->blksize);
debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
return 0;
@@ -873,9 +988,7 @@ static int nbd_init_request(void *data, struct request *rq,
unsigned int numa_node)
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(rq);
-
cmd->nbd = data;
- INIT_LIST_HEAD(&cmd->list);
return 0;
}
@@ -985,13 +1098,13 @@ static int __init nbd_init(void)
for (i = 0; i < nbds_max; i++) {
struct gendisk *disk = nbd_dev[i].disk;
nbd_dev[i].magic = NBD_MAGIC;
- spin_lock_init(&nbd_dev[i].sock_lock);
- mutex_init(&nbd_dev[i].tx_lock);
+ mutex_init(&nbd_dev[i].config_lock);
disk->major = NBD_MAJOR;
disk->first_minor = i << part_shift;
disk->fops = &nbd_fops;
disk->private_data = &nbd_dev[i];
sprintf(disk->disk_name, "nbd%d", i);
+ init_waitqueue_head(&nbd_dev[i].recv_wq);
nbd_reset(&nbd_dev[i]);
add_disk(disk);
}
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index ba6f4a2e73db..4943ee22716e 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -577,6 +577,7 @@ static void null_nvm_unregister(struct nullb *nullb)
#else
static int null_nvm_register(struct nullb *nullb)
{
+ pr_err("null_blk: CONFIG_NVM needs to be enabled for LightNVM\n");
return -EINVAL;
}
static void null_nvm_unregister(struct nullb *nullb) {}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 90fa4ac149db..95c98de92971 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -721,7 +721,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->timeout = 60*HZ;
if (cgc->quiet)
- rq->cmd_flags |= REQ_QUIET;
+ rq->rq_flags |= RQF_QUIET;
blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0);
if (rq->errors)
@@ -944,39 +944,6 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_que
}
}
-/*
- * Copy all data for this packet to pkt->pages[], so that
- * a) The number of required segments for the write bio is minimized, which
- * is necessary for some scsi controllers.
- * b) The data can be used as cache to avoid read requests if we receive a
- * new write request for the same zone.
- */
-static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
-{
- int f, p, offs;
-
- /* Copy all data to pkt->pages[] */
- p = 0;
- offs = 0;
- for (f = 0; f < pkt->frames; f++) {
- if (bvec[f].bv_page != pkt->pages[p]) {
- void *vfrom = kmap_atomic(bvec[f].bv_page) + bvec[f].bv_offset;
- void *vto = page_address(pkt->pages[p]) + offs;
- memcpy(vto, vfrom, CD_FRAMESIZE);
- kunmap_atomic(vfrom);
- bvec[f].bv_page = pkt->pages[p];
- bvec[f].bv_offset = offs;
- } else {
- BUG_ON(bvec[f].bv_offset != offs);
- }
- offs += CD_FRAMESIZE;
- if (offs >= PAGE_SIZE) {
- offs = 0;
- p++;
- }
- }
-}
-
static void pkt_end_io_read(struct bio *bio)
{
struct packet_data *pkt = bio->bi_private;
@@ -1298,7 +1265,6 @@ try_next_bio:
static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
{
int f;
- struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
bio_reset(pkt->w_bio);
pkt->w_bio->bi_iter.bi_sector = pkt->sector;
@@ -1308,9 +1274,10 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
/* XXX: locking? */
for (f = 0; f < pkt->frames; f++) {
- bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
- bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
- if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
+ struct page *page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
+ unsigned offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
+
+ if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset))
BUG();
}
pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
@@ -1327,12 +1294,10 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt_dbg(2, pd, "Writing %d frames for zone %llx\n",
pkt->write_size, (unsigned long long)pkt->sector);
- if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
- pkt_make_local_copy(pkt, bvec);
+ if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames))
pkt->cache_valid = 1;
- } else {
+ else
pkt->cache_valid = 0;
- }
/* Start the write request */
atomic_set(&pkt->io_wait, 1);
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index 3822eae102db..abf805e332e2 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -36,7 +36,6 @@
#include <linux/scatterlist.h>
#include <linux/version.h>
#include <linux/err.h>
-#include <linux/scatterlist.h>
#include <linux/aer.h>
#include <linux/ctype.h>
#include <linux/wait.h>
@@ -270,8 +269,6 @@ struct skd_device {
resource_size_t mem_phys[SKD_MAX_BARS];
u32 mem_size[SKD_MAX_BARS];
- skd_irq_type_t irq_type;
- u32 msix_count;
struct skd_msix_entry *msix_entries;
struct pci_dev *pdev;
@@ -2138,12 +2135,8 @@ static void skd_send_fitmsg(struct skd_device *skdev,
u8 *bp = (u8 *)skmsg->msg_buf;
int i;
for (i = 0; i < skmsg->length; i += 8) {
- pr_debug("%s:%s:%d msg[%2d] %02x %02x %02x %02x "
- "%02x %02x %02x %02x\n",
- skdev->name, __func__, __LINE__,
- i, bp[i + 0], bp[i + 1], bp[i + 2],
- bp[i + 3], bp[i + 4], bp[i + 5],
- bp[i + 6], bp[i + 7]);
+ pr_debug("%s:%s:%d msg[%2d] %8ph\n",
+ skdev->name, __func__, __LINE__, i, &bp[i]);
if (i == 0)
i = 64 - 8;
}
@@ -2164,7 +2157,6 @@ static void skd_send_fitmsg(struct skd_device *skdev,
qcmd |= FIT_QCMD_MSGSIZE_64;
SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
-
}
static void skd_send_special_fitmsg(struct skd_device *skdev,
@@ -2177,11 +2169,8 @@ static void skd_send_special_fitmsg(struct skd_device *skdev,
int i;
for (i = 0; i < SKD_N_SPECIAL_FITMSG_BYTES; i += 8) {
- pr_debug("%s:%s:%d spcl[%2d] %02x %02x %02x %02x "
- "%02x %02x %02x %02x\n",
- skdev->name, __func__, __LINE__, i,
- bp[i + 0], bp[i + 1], bp[i + 2], bp[i + 3],
- bp[i + 4], bp[i + 5], bp[i + 6], bp[i + 7]);
+ pr_debug("%s:%s:%d spcl[%2d] %8ph\n",
+ skdev->name, __func__, __LINE__, i, &bp[i]);
if (i == 0)
i = 64 - 8;
}
@@ -2955,8 +2944,8 @@ static void skd_completion_worker(struct work_struct *work)
static void skd_isr_msg_from_dev(struct skd_device *skdev);
-irqreturn_t
-static skd_isr(int irq, void *ptr)
+static irqreturn_t
+skd_isr(int irq, void *ptr)
{
struct skd_device *skdev;
u32 intstat;
@@ -3821,10 +3810,6 @@ static irqreturn_t skd_qfull_isr(int irq, void *skd_host_data)
*/
struct skd_msix_entry {
- int have_irq;
- u32 vector;
- u32 entry;
- struct skd_device *rsp;
char isr_name[30];
};
@@ -3853,193 +3838,121 @@ static struct skd_init_msix_entry msix_entries[SKD_MAX_MSIX_COUNT] = {
{ "(Queue Full 3)", skd_qfull_isr },
};
-static void skd_release_msix(struct skd_device *skdev)
-{
- struct skd_msix_entry *qentry;
- int i;
-
- if (skdev->msix_entries) {
- for (i = 0; i < skdev->msix_count; i++) {
- qentry = &skdev->msix_entries[i];
- skdev = qentry->rsp;
-
- if (qentry->have_irq)
- devm_free_irq(&skdev->pdev->dev,
- qentry->vector, qentry->rsp);
- }
-
- kfree(skdev->msix_entries);
- }
-
- if (skdev->msix_count)
- pci_disable_msix(skdev->pdev);
-
- skdev->msix_count = 0;
- skdev->msix_entries = NULL;
-}
-
static int skd_acquire_msix(struct skd_device *skdev)
{
int i, rc;
struct pci_dev *pdev = skdev->pdev;
- struct msix_entry *entries;
- struct skd_msix_entry *qentry;
-
- entries = kzalloc(sizeof(struct msix_entry) * SKD_MAX_MSIX_COUNT,
- GFP_KERNEL);
- if (!entries)
- return -ENOMEM;
-
- for (i = 0; i < SKD_MAX_MSIX_COUNT; i++)
- entries[i].entry = i;
- rc = pci_enable_msix_exact(pdev, entries, SKD_MAX_MSIX_COUNT);
- if (rc) {
+ rc = pci_alloc_irq_vectors(pdev, SKD_MAX_MSIX_COUNT, SKD_MAX_MSIX_COUNT,
+ PCI_IRQ_MSIX);
+ if (rc < 0) {
pr_err("(%s): failed to enable MSI-X %d\n",
skd_name(skdev), rc);
- goto msix_out;
+ goto out;
}
- skdev->msix_count = SKD_MAX_MSIX_COUNT;
- skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) *
- skdev->msix_count, GFP_KERNEL);
+ skdev->msix_entries = kcalloc(SKD_MAX_MSIX_COUNT,
+ sizeof(struct skd_msix_entry), GFP_KERNEL);
if (!skdev->msix_entries) {
rc = -ENOMEM;
pr_err("(%s): msix table allocation error\n",
skd_name(skdev));
- goto msix_out;
- }
-
- for (i = 0; i < skdev->msix_count; i++) {
- qentry = &skdev->msix_entries[i];
- qentry->vector = entries[i].vector;
- qentry->entry = entries[i].entry;
- qentry->rsp = NULL;
- qentry->have_irq = 0;
- pr_debug("%s:%s:%d %s: <%s> msix (%d) vec %d, entry %x\n",
- skdev->name, __func__, __LINE__,
- pci_name(pdev), skdev->name,
- i, qentry->vector, qentry->entry);
+ goto out;
}
/* Enable MSI-X vectors for the base queue */
- for (i = 0; i < skdev->msix_count; i++) {
- qentry = &skdev->msix_entries[i];
+ for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+ struct skd_msix_entry *qentry = &skdev->msix_entries[i];
+
snprintf(qentry->isr_name, sizeof(qentry->isr_name),
"%s%d-msix %s", DRV_NAME, skdev->devno,
msix_entries[i].name);
- rc = devm_request_irq(&skdev->pdev->dev, qentry->vector,
- msix_entries[i].handler, 0,
- qentry->isr_name, skdev);
+
+ rc = devm_request_irq(&skdev->pdev->dev,
+ pci_irq_vector(skdev->pdev, i),
+ msix_entries[i].handler, 0,
+ qentry->isr_name, skdev);
if (rc) {
pr_err("(%s): Unable to register(%d) MSI-X "
"handler %d: %s\n",
skd_name(skdev), rc, i, qentry->isr_name);
goto msix_out;
- } else {
- qentry->have_irq = 1;
- qentry->rsp = skdev;
}
}
+
pr_debug("%s:%s:%d %s: <%s> msix %d irq(s) enabled\n",
skdev->name, __func__, __LINE__,
- pci_name(pdev), skdev->name, skdev->msix_count);
+ pci_name(pdev), skdev->name, SKD_MAX_MSIX_COUNT);
return 0;
msix_out:
- if (entries)
- kfree(entries);
- skd_release_msix(skdev);
+ while (--i >= 0)
+ devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), skdev);
+out:
+ kfree(skdev->msix_entries);
+ skdev->msix_entries = NULL;
return rc;
}
static int skd_acquire_irq(struct skd_device *skdev)
{
+ struct pci_dev *pdev = skdev->pdev;
+ unsigned int irq_flag = PCI_IRQ_LEGACY;
int rc;
- struct pci_dev *pdev;
-
- pdev = skdev->pdev;
- skdev->msix_count = 0;
-RETRY_IRQ_TYPE:
- switch (skdev->irq_type) {
- case SKD_IRQ_MSIX:
+ if (skd_isr_type == SKD_IRQ_MSIX) {
rc = skd_acquire_msix(skdev);
if (!rc)
- pr_info("(%s): MSI-X %d irqs enabled\n",
- skd_name(skdev), skdev->msix_count);
- else {
- pr_err(
- "(%s): failed to enable MSI-X, re-trying with MSI %d\n",
- skd_name(skdev), rc);
- skdev->irq_type = SKD_IRQ_MSI;
- goto RETRY_IRQ_TYPE;
- }
- break;
- case SKD_IRQ_MSI:
- snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d-msi",
- DRV_NAME, skdev->devno);
- rc = pci_enable_msi_range(pdev, 1, 1);
- if (rc > 0) {
- rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr, 0,
- skdev->isr_name, skdev);
- if (rc) {
- pci_disable_msi(pdev);
- pr_err(
- "(%s): failed to allocate the MSI interrupt %d\n",
- skd_name(skdev), rc);
- goto RETRY_IRQ_LEGACY;
- }
- pr_info("(%s): MSI irq %d enabled\n",
- skd_name(skdev), pdev->irq);
- } else {
-RETRY_IRQ_LEGACY:
- pr_err(
- "(%s): failed to enable MSI, re-trying with LEGACY %d\n",
- skd_name(skdev), rc);
- skdev->irq_type = SKD_IRQ_LEGACY;
- goto RETRY_IRQ_TYPE;
- }
- break;
- case SKD_IRQ_LEGACY:
- snprintf(skdev->isr_name, sizeof(skdev->isr_name),
- "%s%d-legacy", DRV_NAME, skdev->devno);
- rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr,
- IRQF_SHARED, skdev->isr_name, skdev);
- if (!rc)
- pr_info("(%s): LEGACY irq %d enabled\n",
- skd_name(skdev), pdev->irq);
- else
- pr_err("(%s): request LEGACY irq error %d\n",
- skd_name(skdev), rc);
- break;
- default:
- pr_info("(%s): irq_type %d invalid, re-set to %d\n",
- skd_name(skdev), skdev->irq_type, SKD_IRQ_DEFAULT);
- skdev->irq_type = SKD_IRQ_LEGACY;
- goto RETRY_IRQ_TYPE;
+ return 0;
+
+ pr_err("(%s): failed to enable MSI-X, re-trying with MSI %d\n",
+ skd_name(skdev), rc);
}
- return rc;
+
+ snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d", DRV_NAME,
+ skdev->devno);
+
+ if (skd_isr_type != SKD_IRQ_LEGACY)
+ irq_flag |= PCI_IRQ_MSI;
+ rc = pci_alloc_irq_vectors(pdev, 1, 1, irq_flag);
+ if (rc < 0) {
+ pr_err("(%s): failed to allocate the MSI interrupt %d\n",
+ skd_name(skdev), rc);
+ return rc;
+ }
+
+ rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr,
+ pdev->msi_enabled ? 0 : IRQF_SHARED,
+ skdev->isr_name, skdev);
+ if (rc) {
+ pci_free_irq_vectors(pdev);
+ pr_err("(%s): failed to allocate interrupt %d\n",
+ skd_name(skdev), rc);
+ return rc;
+ }
+
+ return 0;
}
static void skd_release_irq(struct skd_device *skdev)
{
- switch (skdev->irq_type) {
- case SKD_IRQ_MSIX:
- skd_release_msix(skdev);
- break;
- case SKD_IRQ_MSI:
- devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
- pci_disable_msi(skdev->pdev);
- break;
- case SKD_IRQ_LEGACY:
- devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
- break;
- default:
- pr_err("(%s): wrong irq type %d!",
- skd_name(skdev), skdev->irq_type);
- break;
+ struct pci_dev *pdev = skdev->pdev;
+
+ if (skdev->msix_entries) {
+ int i;
+
+ for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+ devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i),
+ skdev);
+ }
+
+ kfree(skdev->msix_entries);
+ skdev->msix_entries = NULL;
+ } else {
+ devm_free_irq(&pdev->dev, pdev->irq, skdev);
}
+
+ pci_free_irq_vectors(pdev);
}
/*
@@ -4402,7 +4315,6 @@ static struct skd_device *skd_construct(struct pci_dev *pdev)
skdev->pdev = pdev;
skdev->devno = skd_next_devno++;
skdev->major = blk_major;
- skdev->irq_type = skd_isr_type;
sprintf(skdev->name, DRV_NAME "%d", skdev->devno);
skdev->dev_max_queue_depth = 0;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index be90e15854ed..46f4c719fed9 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -535,7 +535,7 @@ static blk_qc_t mm_make_request(struct request_queue *q, struct bio *bio)
*card->biotail = bio;
bio->bi_next = NULL;
card->biotail = &bio->bi_next;
- if (bio->bi_opf & REQ_SYNC || !mm_check_plugged(card))
+ if (op_is_sync(bio->bi_opf) || !mm_check_plugged(card))
activate(card);
spin_unlock_irq(&card->lock);
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 4a80ee752597..726c32e35db9 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -1253,14 +1253,14 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
case BLKIF_OP_WRITE:
ring->st_wr_req++;
operation = REQ_OP_WRITE;
- operation_flags = WRITE_ODIRECT;
+ operation_flags = REQ_SYNC | REQ_IDLE;
break;
case BLKIF_OP_WRITE_BARRIER:
drain = true;
case BLKIF_OP_FLUSH_DISKCACHE:
ring->st_f_req++;
operation = REQ_OP_WRITE;
- operation_flags = WRITE_FLUSH;
+ operation_flags = REQ_PREFLUSH;
break;
default:
operation = 0; /* make gcc happy */
@@ -1272,7 +1272,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
nseg = req->operation == BLKIF_OP_INDIRECT ?
req->u.indirect.nr_segments : req->u.rw.nr_segments;
- if (unlikely(nseg == 0 && operation_flags != WRITE_FLUSH) ||
+ if (unlikely(nseg == 0 && operation_flags != REQ_PREFLUSH) ||
unlikely((req->operation != BLKIF_OP_INDIRECT) &&
(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) ||
unlikely((req->operation == BLKIF_OP_INDIRECT) &&
@@ -1334,7 +1334,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
}
/* Wait on all outstanding I/O's and once that has been completed
- * issue the WRITE_FLUSH.
+ * issue the flush.
*/
if (drain)
xen_blk_drain_io(pending_req->ring);
@@ -1380,7 +1380,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
/* This will be hit if the operation was a flush or discard. */
if (!bio) {
- BUG_ON(operation_flags != WRITE_FLUSH);
+ BUG_ON(operation_flags != REQ_PREFLUSH);
bio = bio_alloc(GFP_KERNEL, 0);
if (unlikely(bio == NULL))
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 9908597c5209..c000fdf048b2 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2043,8 +2043,9 @@ static int blkif_recover(struct blkfront_info *info)
/* Requeue pending requests (flush or discard) */
list_del_init(&req->queuelist);
BUG_ON(req->nr_phys_segments > segs);
- blk_mq_requeue_request(req);
+ blk_mq_requeue_request(req, false);
}
+ blk_mq_start_stopped_hw_queues(info->rq, true);
blk_mq_kick_requeue_list(info->rq);
while ((bio = bio_list_pop(&info->bio_list)) != NULL) {
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 4b5cd3a7b2b6..12046f4f00e4 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -160,82 +160,56 @@ int zcomp_decompress(struct zcomp_strm *zstrm,
dst, &dst_len);
}
-static int __zcomp_cpu_notifier(struct zcomp *comp,
- unsigned long action, unsigned long cpu)
+int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
{
+ struct zcomp *comp = hlist_entry(node, struct zcomp, node);
struct zcomp_strm *zstrm;
- switch (action) {
- case CPU_UP_PREPARE:
- if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
- break;
- zstrm = zcomp_strm_alloc(comp);
- if (IS_ERR_OR_NULL(zstrm)) {
- pr_err("Can't allocate a compression stream\n");
- return NOTIFY_BAD;
- }
- *per_cpu_ptr(comp->stream, cpu) = zstrm;
- break;
- case CPU_DEAD:
- case CPU_UP_CANCELED:
- zstrm = *per_cpu_ptr(comp->stream, cpu);
- if (!IS_ERR_OR_NULL(zstrm))
- zcomp_strm_free(zstrm);
- *per_cpu_ptr(comp->stream, cpu) = NULL;
- break;
- default:
- break;
+ if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
+ return 0;
+
+ zstrm = zcomp_strm_alloc(comp);
+ if (IS_ERR_OR_NULL(zstrm)) {
+ pr_err("Can't allocate a compression stream\n");
+ return -ENOMEM;
}
- return NOTIFY_OK;
+ *per_cpu_ptr(comp->stream, cpu) = zstrm;
+ return 0;
}
-static int zcomp_cpu_notifier(struct notifier_block *nb,
- unsigned long action, void *pcpu)
+int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
{
- unsigned long cpu = (unsigned long)pcpu;
- struct zcomp *comp = container_of(nb, typeof(*comp), notifier);
+ struct zcomp *comp = hlist_entry(node, struct zcomp, node);
+ struct zcomp_strm *zstrm;
- return __zcomp_cpu_notifier(comp, action, cpu);
+ zstrm = *per_cpu_ptr(comp->stream, cpu);
+ if (!IS_ERR_OR_NULL(zstrm))
+ zcomp_strm_free(zstrm);
+ *per_cpu_ptr(comp->stream, cpu) = NULL;
+ return 0;
}
static int zcomp_init(struct zcomp *comp)
{
- unsigned long cpu;
int ret;
- comp->notifier.notifier_call = zcomp_cpu_notifier;
-
comp->stream = alloc_percpu(struct zcomp_strm *);
if (!comp->stream)
return -ENOMEM;
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu) {
- ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu);
- if (ret == NOTIFY_BAD)
- goto cleanup;
- }
- __register_cpu_notifier(&comp->notifier);
- cpu_notifier_register_done();
+ ret = cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
+ if (ret < 0)
+ goto cleanup;
return 0;
cleanup:
- for_each_online_cpu(cpu)
- __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
- cpu_notifier_register_done();
- return -ENOMEM;
+ free_percpu(comp->stream);
+ return ret;
}
void zcomp_destroy(struct zcomp *comp)
{
- unsigned long cpu;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
- __unregister_cpu_notifier(&comp->notifier);
- cpu_notifier_register_done();
-
+ cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
free_percpu(comp->stream);
kfree(comp);
}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index 478cac2ed465..41c1002a7d7d 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -19,11 +19,12 @@ struct zcomp_strm {
/* dynamic per-device compression frontend */
struct zcomp {
struct zcomp_strm * __percpu *stream;
- struct notifier_block notifier;
-
const char *name;
+ struct hlist_node node;
};
+int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node);
+int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node);
ssize_t zcomp_available_show(const char *comp, char *buf);
bool zcomp_available_algorithm(const char *comp);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 5497f7fc44d0..15f58ab44d0b 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -30,6 +30,7 @@
#include <linux/err.h>
#include <linux/idr.h>
#include <linux/sysfs.h>
+#include <linux/cpuhotplug.h>
#include "zram_drv.h"
@@ -1443,15 +1444,22 @@ static void destroy_devices(void)
idr_for_each(&zram_index_idr, &zram_remove_cb, NULL);
idr_destroy(&zram_index_idr);
unregister_blkdev(zram_major, "zram");
+ cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
}
static int __init zram_init(void)
{
int ret;
+ ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare",
+ zcomp_cpu_up_prepare, zcomp_cpu_dead);
+ if (ret < 0)
+ return ret;
+
ret = class_register(&zram_control_class);
if (ret) {
pr_err("Unable to register zram-control class\n");
+ cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
return ret;
}
@@ -1459,6 +1467,7 @@ static int __init zram_init(void)
if (zram_major <= 0) {
pr_err("Unable to get major number\n");
class_unregister(&zram_control_class);
+ cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
return -EBUSY;
}
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index f742384b53f7..fc3caf4541ba 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -32,7 +32,6 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/slab.h>
#include <linux/of_irq.h>
#define BTM_HEADER_LEN 4
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index a2c921faaa12..910ec968f022 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -733,9 +733,7 @@ static int bcsp_open(struct hci_uart *hu)
skb_queue_head_init(&bcsp->rel);
skb_queue_head_init(&bcsp->unrel);
- init_timer(&bcsp->tbcsp);
- bcsp->tbcsp.function = bcsp_timed_event;
- bcsp->tbcsp.data = (u_long)hu;
+ setup_timer(&bcsp->tbcsp, bcsp_timed_event, (u_long)hu);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index 0879d64b1caf..90d0456b6744 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -204,9 +204,7 @@ static int h5_open(struct hci_uart *hu)
h5_reset_rx(h5);
- init_timer(&h5->timer);
- h5->timer.function = h5_timed_event;
- h5->timer.data = (unsigned long)hu;
+ setup_timer(&h5->timer, h5_timed_event, (unsigned long)hu);
h5->tx_win = H5_TX_WIN_MAX;
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 6c867fbc56a7..05c230719a47 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -438,14 +438,11 @@ static int qca_open(struct hci_uart *hu)
hu->priv = qca;
- init_timer(&qca->wake_retrans_timer);
- qca->wake_retrans_timer.function = hci_ibs_wake_retrans_timeout;
- qca->wake_retrans_timer.data = (u_long)hu;
+ setup_timer(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout,
+ (u_long)hu);
qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS;
- init_timer(&qca->tx_idle_timer);
- qca->tx_idle_timer.function = hci_ibs_tx_idle_timeout;
- qca->tx_idle_timer.data = (u_long)hu;
+ setup_timer(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, (u_long)hu);
qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS;
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index dcc09739a54e..45ba878ae025 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -542,6 +542,7 @@ config HANGCHECK_TIMER
config MMTIMER
tristate "MMTIMER Memory mapped RTC for SGI Altix"
depends on IA64_GENERIC || IA64_SGI_SN2
+ depends on POSIX_TIMERS
default y
help
The mmtimer device allows direct userspace access to the
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 44ce80606944..d1f5bb534e0e 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -70,21 +70,17 @@ enum {
* until we have 4 bytes, thus returning a u32 at a time,
* instead of the current u8-at-a-time.
*
- * Padlock instructions can generate a spurious DNA fault, so
- * we have to call them in the context of irq_ts_save/restore()
+ * Padlock instructions can generate a spurious DNA fault, but the
+ * kernel doesn't use CR0.TS, so this doesn't matter.
*/
static inline u32 xstore(u32 *addr, u32 edx_in)
{
u32 eax_out;
- int ts_state;
-
- ts_state = irq_ts_save();
asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
: "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr));
- irq_ts_restore(ts_state);
return eax_out;
}
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index c115217c79ae..e051fc8aa7d7 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -14,7 +14,7 @@
* (C) 2000,2001,2002,2003,2004 Omnikey AG
*
* (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
- * - Adhere to Kernel CodingStyle
+ * - Adhere to Kernel process/coding-style.rst
* - Port to 2.6.13 "new" style PCMCIA
* - Check for copy_{from,to}_user return values
* - Use nonseekable_open()
@@ -151,7 +151,7 @@ static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
static struct class *cmm_class;
/* This table doesn't use spaces after the comma between fields and thus
- * violates CodingStyle. However, I don't really think wrapping it around will
+ * violates process/coding-style.rst. However, I don't really think wrapping it around will
* make it any clearer to read -HW */
static unsigned char fi_di_table[10][14] = {
/*FI 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index d28922df01d7..a7dd5f4f2c5a 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -4248,7 +4248,6 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
static const struct net_device_ops hdlcdev_ops = {
.ndo_open = hdlcdev_open,
.ndo_stop = hdlcdev_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hdlcdev_ioctl,
.ndo_tx_timeout = hdlcdev_tx_timeout,
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6a8ac04bedeb..56c1998ced3e 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -33,7 +33,7 @@ source "drivers/clk/versatile/Kconfig"
config COMMON_CLK_MAX77686
tristate "Clock driver for Maxim 77620/77686/77802 MFD"
- depends on MFD_MAX77686 || MFD_MAX77620
+ depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST
---help---
This driver supports Maxim 77620/77686/77802 crystal oscillator
clock.
@@ -119,7 +119,7 @@ config COMMON_CLK_CS2000_CP
config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
- depends on MFD_SEC_CORE
+ depends on MFD_SEC_CORE || COMPILE_TEST
---help---
This driver supports S2MPS11/S2MPS14/S5M8767 crystal oscillator
clock. These multi-function devices have two (S2MPS14) or three
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index e3eed5a78404..b5ae5311b0a2 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -1,7 +1,6 @@
config CLK_BCM_63XX
bool "Broadcom BCM63xx clock support"
depends on ARCH_BCM_63XX || COMPILE_TEST
- depends on COMMON_CLK
select COMMON_CLK_IPROC
default ARCH_BCM_63XX
help
@@ -11,27 +10,22 @@ config CLK_BCM_63XX
config CLK_BCM_KONA
bool "Broadcom Kona CCU clock support"
depends on ARCH_BCM_MOBILE || COMPILE_TEST
- depends on COMMON_CLK
- default y
+ default ARCH_BCM_MOBILE
help
Enable common clock framework support for Broadcom SoCs
using "Kona" style clock control units, including those
in the BCM281xx and BCM21664 families.
config COMMON_CLK_IPROC
- bool "Broadcom iProc clock support"
- depends on ARCH_BCM_IPROC || ARCH_BCM_63XX || COMPILE_TEST
- depends on COMMON_CLK
- default ARCH_BCM_IPROC
+ bool
help
Enable common clock framework support for Broadcom SoCs
based on the iProc architecture
-if COMMON_CLK_IPROC
-
config CLK_BCM_CYGNUS
bool "Broadcom Cygnus clock support"
depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+ select COMMON_CLK_IPROC
default ARCH_BCM_CYGNUS
help
Enable common clock framework support for the Broadcom Cygnus SoC
@@ -39,6 +33,7 @@ config CLK_BCM_CYGNUS
config CLK_BCM_NSP
bool "Broadcom Northstar/Northstar Plus clock support"
depends on ARCH_BCM_5301X || ARCH_BCM_NSP || COMPILE_TEST
+ select COMMON_CLK_IPROC
default ARCH_BCM_5301X || ARCH_BCM_NSP
help
Enable common clock framework support for the Broadcom Northstar and
@@ -47,8 +42,7 @@ config CLK_BCM_NSP
config CLK_BCM_NS2
bool "Broadcom Northstar 2 clock support"
depends on ARCH_BCM_IPROC || COMPILE_TEST
+ select COMMON_CLK_IPROC
default ARCH_BCM_IPROC
help
Enable common clock framework support for the Broadcom Northstar 2 SoC
-
-endif
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 8c7763fd9efc..0d14409097e7 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -436,6 +436,9 @@ struct bcm2835_clock_data {
const char *const *parents;
int num_mux_parents;
+ /* Bitmap encoding which parents accept rate change propagation. */
+ unsigned int set_rate_parent;
+
u32 ctl_reg;
u32 div_reg;
@@ -751,7 +754,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
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);
+ cprman_write(cprman, data->a2w_reg,
+ cprman_read(cprman, data->a2w_reg) |
+ A2W_PLL_CHANNEL_DISABLE);
spin_unlock(&cprman->regs_lock);
}
@@ -1015,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
}
+static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+ int parent_idx,
+ unsigned long rate,
+ u32 *div,
+ unsigned long *prate)
+{
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+ unsigned long best_rate = 0;
+ u32 curdiv, mindiv, maxdiv;
+ struct clk_hw *parent;
+
+ parent = clk_hw_get_parent_by_index(hw, parent_idx);
+
+ if (!(BIT(parent_idx) & data->set_rate_parent)) {
+ *prate = clk_hw_get_rate(parent);
+ *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
+
+ return bcm2835_clock_rate_from_divisor(clock, *prate,
+ *div);
+ }
+
+ if (data->frac_bits)
+ dev_warn(cprman->dev,
+ "frac bits are not used when propagating rate change");
+
+ /* clamp to min divider of 2 if we're dealing with a mash clock */
+ mindiv = data->is_mash_clock ? 2 : 1;
+ maxdiv = BIT(data->int_bits) - 1;
+
+ /* TODO: Be smart, and only test a subset of the available divisors. */
+ for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
+ unsigned long tmp_rate;
+
+ tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
+ tmp_rate /= curdiv;
+ if (curdiv == mindiv ||
+ (tmp_rate > best_rate && tmp_rate <= rate))
+ best_rate = tmp_rate;
+
+ if (best_rate == rate)
+ break;
+ }
+
+ *div = curdiv << CM_DIV_FRAC_BITS;
+ *prate = curdiv * best_rate;
+
+ return best_rate;
+}
+
static int bcm2835_clock_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct clk_hw *parent, *best_parent = NULL;
bool current_parent_is_pllc;
unsigned long rate, best_rate = 0;
@@ -1046,9 +1101,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
continue;
- prate = clk_hw_get_rate(parent);
- div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
- rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
+ rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
+ &div, &prate);
if (rate > best_rate && rate <= req->rate) {
best_parent = parent;
best_prate = prate;
@@ -1260,6 +1314,13 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
init.name = data->name;
init.flags = data->flags | CLK_IGNORE_UNUSED;
+ /*
+ * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
+ * rate changes on at least of the parents.
+ */
+ if (data->set_rate_parent)
+ init.flags |= CLK_SET_RATE_PARENT;
+
if (data->is_vpu_clock) {
init.ops = &bcm2835_vpu_clock_clk_ops;
} else {
@@ -1596,7 +1657,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.a2w_reg = A2W_PLLH_AUX,
.load_mask = CM_PLLH_LOADAUX,
.hold_mask = 0,
- .fixed_divider = 10),
+ .fixed_divider = 1),
[BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(
.name = "pllh_pix",
.source_pll = "pllh",
@@ -1800,7 +1861,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.ctl_reg = CM_VECCTL,
.div_reg = CM_VECDIV,
.int_bits = 4,
- .frac_bits = 0),
+ .frac_bits = 0,
+ /*
+ * Allow rate change propagation only on PLLH_AUX which is
+ * assigned index 7 in the parent array.
+ */
+ .set_rate_parent = BIT(7)),
/* dsi clocks */
[BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index b8459c14a1b7..f793b2d9238c 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -216,7 +216,7 @@ static int cdce925_pll_prepare(struct clk_hw *hw)
nn = n * BIT(p);
/* q = int(nn/m) */
q = nn / m;
- if ((q < 16) || (1 > 64)) {
+ if ((q < 16) || (q > 63)) {
pr_debug("%s invalid q=%d\n", __func__, q);
return -EINVAL;
}
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 8f571548870f..3a218c3a06ae 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -53,3 +53,24 @@ void devm_clk_put(struct device *dev, struct clk *clk)
WARN_ON(ret);
}
EXPORT_SYMBOL(devm_clk_put);
+
+struct clk *devm_get_clk_from_child(struct device *dev,
+ struct device_node *np, const char *con_id)
+{
+ struct clk **ptr, *clk;
+
+ ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ clk = of_clk_get_by_name(np, con_id);
+ if (!IS_ERR(clk)) {
+ *ptr = clk;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return clk;
+}
+EXPORT_SYMBOL(devm_get_clk_from_child);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 4e691e35483a..4e0c054a787c 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -145,8 +145,8 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
init.name = name;
init.ops = &clk_gate_ops;
init.flags = flags | CLK_IS_BASIC;
- init.parent_names = (parent_name ? &parent_name: NULL);
- init.num_parents = (parent_name ? 1 : 0);
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
/* struct clk_gate assignments */
gate->reg = reg;
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
index 47649ac5d399..e51e0023fc6e 100644
--- a/drivers/clk/clk-oxnas.c
+++ b/drivers/clk/clk-oxnas.c
@@ -20,31 +20,43 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/stringify.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/oxsemi,ox810se.h>
+#include <dt-bindings/clock/oxsemi,ox820.h>
+
/* Standard regmap gate clocks */
-struct clk_oxnas {
+struct clk_oxnas_gate {
struct clk_hw hw;
- signed char bit;
+ unsigned int bit;
struct regmap *regmap;
};
+struct oxnas_stdclk_data {
+ struct clk_hw_onecell_data *onecell_data;
+ struct clk_oxnas_gate **gates;
+ unsigned int ngates;
+ struct clk_oxnas_pll **plls;
+ unsigned int nplls;
+};
+
/* Regmap offsets */
#define CLK_STAT_REGOFFSET 0x24
#define CLK_SET_REGOFFSET 0x2c
#define CLK_CLR_REGOFFSET 0x30
-static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
{
- return container_of(hw, struct clk_oxnas, hw);
+ return container_of(hw, struct clk_oxnas_gate, hw);
}
-static int oxnas_clk_is_enabled(struct clk_hw *hw)
+static int oxnas_clk_gate_is_enabled(struct clk_hw *hw)
{
- struct clk_oxnas *std = to_clk_oxnas(hw);
+ struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
int ret;
unsigned int val;
@@ -55,29 +67,29 @@ static int oxnas_clk_is_enabled(struct clk_hw *hw)
return val & BIT(std->bit);
}
-static int oxnas_clk_enable(struct clk_hw *hw)
+static int oxnas_clk_gate_enable(struct clk_hw *hw)
{
- struct clk_oxnas *std = to_clk_oxnas(hw);
+ struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
return 0;
}
-static void oxnas_clk_disable(struct clk_hw *hw)
+static void oxnas_clk_gate_disable(struct clk_hw *hw)
{
- struct clk_oxnas *std = to_clk_oxnas(hw);
+ struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
}
-static const struct clk_ops oxnas_clk_ops = {
- .enable = oxnas_clk_enable,
- .disable = oxnas_clk_disable,
- .is_enabled = oxnas_clk_is_enabled,
+static const struct clk_ops oxnas_clk_gate_ops = {
+ .enable = oxnas_clk_gate_enable,
+ .disable = oxnas_clk_gate_disable,
+ .is_enabled = oxnas_clk_gate_is_enabled,
};
-static const char *const oxnas_clk_parents[] = {
+static const char *const osc_parents[] = {
"oscillator",
};
@@ -85,63 +97,138 @@ static const char *const eth_parents[] = {
"gmacclk",
};
-#define DECLARE_STD_CLKP(__clk, __parent) \
-static const struct clk_init_data clk_##__clk##_init = { \
- .name = __stringify(__clk), \
- .ops = &oxnas_clk_ops, \
- .parent_names = __parent, \
- .num_parents = ARRAY_SIZE(__parent), \
+#define OXNAS_GATE(_name, _bit, _parents) \
+struct clk_oxnas_gate _name = { \
+ .bit = (_bit), \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name, \
+ .ops = &oxnas_clk_gate_ops, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
+ }, \
}
-#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+static OXNAS_GATE(ox810se_leon, 0, osc_parents);
+static OXNAS_GATE(ox810se_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox810se_cipher, 2, osc_parents);
+static OXNAS_GATE(ox810se_sata, 4, osc_parents);
+static OXNAS_GATE(ox810se_audio, 5, osc_parents);
+static OXNAS_GATE(ox810se_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox810se_etha, 7, eth_parents);
+static OXNAS_GATE(ox810se_pciea, 8, osc_parents);
+static OXNAS_GATE(ox810se_nand, 9, osc_parents);
+
+static struct clk_oxnas_gate *ox810se_gates[] = {
+ &ox810se_leon,
+ &ox810se_dma_sgdma,
+ &ox810se_cipher,
+ &ox810se_sata,
+ &ox810se_audio,
+ &ox810se_usbmph,
+ &ox810se_etha,
+ &ox810se_pciea,
+ &ox810se_nand,
+};
+
+static OXNAS_GATE(ox820_leon, 0, osc_parents);
+static OXNAS_GATE(ox820_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox820_cipher, 2, osc_parents);
+static OXNAS_GATE(ox820_sd, 3, osc_parents);
+static OXNAS_GATE(ox820_sata, 4, osc_parents);
+static OXNAS_GATE(ox820_audio, 5, osc_parents);
+static OXNAS_GATE(ox820_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox820_etha, 7, eth_parents);
+static OXNAS_GATE(ox820_pciea, 8, osc_parents);
+static OXNAS_GATE(ox820_nand, 9, osc_parents);
+static OXNAS_GATE(ox820_ethb, 10, eth_parents);
+static OXNAS_GATE(ox820_pcieb, 11, osc_parents);
+static OXNAS_GATE(ox820_ref600, 12, osc_parents);
+static OXNAS_GATE(ox820_usbdev, 13, osc_parents);
+
+static struct clk_oxnas_gate *ox820_gates[] = {
+ &ox820_leon,
+ &ox820_dma_sgdma,
+ &ox820_cipher,
+ &ox820_sd,
+ &ox820_sata,
+ &ox820_audio,
+ &ox820_usbmph,
+ &ox820_etha,
+ &ox820_pciea,
+ &ox820_nand,
+ &ox820_etha,
+ &ox820_pciea,
+ &ox820_ref600,
+ &ox820_usbdev,
+};
+
+static struct clk_hw_onecell_data ox810se_hw_onecell_data = {
+ .hws = {
+ [CLK_810_LEON] = &ox810se_leon.hw,
+ [CLK_810_DMA_SGDMA] = &ox810se_dma_sgdma.hw,
+ [CLK_810_CIPHER] = &ox810se_cipher.hw,
+ [CLK_810_SATA] = &ox810se_sata.hw,
+ [CLK_810_AUDIO] = &ox810se_audio.hw,
+ [CLK_810_USBMPH] = &ox810se_usbmph.hw,
+ [CLK_810_ETHA] = &ox810se_etha.hw,
+ [CLK_810_PCIEA] = &ox810se_pciea.hw,
+ [CLK_810_NAND] = &ox810se_nand.hw,
+ },
+ .num = ARRAY_SIZE(ox810se_gates),
+};
+
+static struct clk_hw_onecell_data ox820_hw_onecell_data = {
+ .hws = {
+ [CLK_820_LEON] = &ox820_leon.hw,
+ [CLK_820_DMA_SGDMA] = &ox820_dma_sgdma.hw,
+ [CLK_820_CIPHER] = &ox820_cipher.hw,
+ [CLK_820_SD] = &ox820_sd.hw,
+ [CLK_820_SATA] = &ox820_sata.hw,
+ [CLK_820_AUDIO] = &ox820_audio.hw,
+ [CLK_820_USBMPH] = &ox820_usbmph.hw,
+ [CLK_820_ETHA] = &ox820_etha.hw,
+ [CLK_820_PCIEA] = &ox820_pciea.hw,
+ [CLK_820_NAND] = &ox820_nand.hw,
+ [CLK_820_ETHB] = &ox820_ethb.hw,
+ [CLK_820_PCIEB] = &ox820_pcieb.hw,
+ [CLK_820_REF600] = &ox820_ref600.hw,
+ [CLK_820_USBDEV] = &ox820_usbdev.hw,
+ },
+ .num = ARRAY_SIZE(ox820_gates),
+};
-/* Hardware Bit - Clock association */
-struct clk_oxnas_init_data {
- unsigned long bit;
- const struct clk_init_data *clk_init;
+static struct oxnas_stdclk_data ox810se_stdclk_data = {
+ .onecell_data = &ox810se_hw_onecell_data,
+ .gates = ox810se_gates,
+ .ngates = ARRAY_SIZE(ox810se_gates),
};
-/* Clk init data declaration */
-DECLARE_STD_CLK(leon);
-DECLARE_STD_CLK(dma_sgdma);
-DECLARE_STD_CLK(cipher);
-DECLARE_STD_CLK(sata);
-DECLARE_STD_CLK(audio);
-DECLARE_STD_CLK(usbmph);
-DECLARE_STD_CLKP(etha, eth_parents);
-DECLARE_STD_CLK(pciea);
-DECLARE_STD_CLK(nand);
-
-/* Table index is clock indice */
-static const struct clk_oxnas_init_data clk_oxnas_init[] = {
- [0] = {0, &clk_leon_init},
- [1] = {1, &clk_dma_sgdma_init},
- [2] = {2, &clk_cipher_init},
- /* Skip & Do not touch to DDR clock */
- [3] = {4, &clk_sata_init},
- [4] = {5, &clk_audio_init},
- [5] = {6, &clk_usbmph_init},
- [6] = {7, &clk_etha_init},
- [7] = {8, &clk_pciea_init},
- [8] = {9, &clk_nand_init},
+static struct oxnas_stdclk_data ox820_stdclk_data = {
+ .onecell_data = &ox820_hw_onecell_data,
+ .gates = ox820_gates,
+ .ngates = ARRAY_SIZE(ox820_gates),
};
-struct clk_oxnas_data {
- struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)];
- struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)];
- struct clk *clks[ARRAY_SIZE(clk_oxnas_init)];
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+ { .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data },
+ { .compatible = "oxsemi,ox820-stdclk", &ox820_stdclk_data },
+ { }
};
static int oxnas_stdclk_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct clk_oxnas_data *clk_oxnas;
+ const struct oxnas_stdclk_data *data;
+ const struct of_device_id *id;
struct regmap *regmap;
+ int ret;
int i;
- clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL);
- if (!clk_oxnas)
- return -ENOMEM;
+ id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev);
+ if (!id)
+ return -ENODEV;
+ data = id->data;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap)) {
@@ -149,32 +236,23 @@ static int oxnas_stdclk_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
- for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
- struct clk_oxnas *_clk;
+ for (i = 0 ; i < data->ngates ; ++i)
+ data->gates[i]->regmap = regmap;
- _clk = &clk_oxnas->clk_oxnas[i];
- _clk->bit = clk_oxnas_init[i].bit;
- _clk->hw.init = clk_oxnas_init[i].clk_init;
- _clk->regmap = regmap;
+ for (i = 0; i < data->onecell_data->num; i++) {
+ if (!data->onecell_data->hws[i])
+ continue;
- clk_oxnas->clks[i] =
- devm_clk_register(&pdev->dev, &_clk->hw);
- if (WARN_ON(IS_ERR(clk_oxnas->clks[i])))
- return PTR_ERR(clk_oxnas->clks[i]);
+ ret = devm_clk_hw_register(&pdev->dev,
+ data->onecell_data->hws[i]);
+ if (ret)
+ return ret;
}
- clk_oxnas->onecell_data->clks = clk_oxnas->clks;
- clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init);
-
- return of_clk_add_provider(np, of_clk_src_onecell_get,
- clk_oxnas->onecell_data);
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
+ data->onecell_data);
}
-static const struct of_device_id oxnas_stdclk_dt_ids[] = {
- { .compatible = "oxsemi,ox810se-stdclk" },
- { }
-};
-
static struct platform_driver oxnas_stdclk_driver = {
.probe = oxnas_stdclk_probe,
.driver = {
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 80ae2a51452d..d0bf8b1c67de 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -266,6 +266,39 @@ static const struct clockgen_muxinfo ls1043a_hwa2 = {
},
};
+static const struct clockgen_muxinfo ls1046a_hwa1 = {
+ {
+ {},
+ {},
+ { 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 ls1046a_hwa2 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ {},
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1012a_cmux = {
+ {
+ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ {},
+ [2] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ }
+};
+
static const struct clockgen_muxinfo t1023_hwa1 = {
{
{},
@@ -489,6 +522,31 @@ static const struct clockgen_chipinfo chipinfo[] = {
.flags = CG_PLL_8BIT,
},
{
+ .compat = "fsl,ls1046a-clockgen",
+ .init_periph = t2080_init_periph,
+ .cmux_groups = {
+ &t1040_cmux
+ },
+ .hwaccel = {
+ &ls1046a_hwa1, &ls1046a_hwa2
+ },
+ .cmux_to_group = {
+ 0, -1
+ },
+ .pll_mask = 0x07,
+ .flags = CG_PLL_8BIT,
+ },
+ {
+ .compat = "fsl,ls1012a-clockgen",
+ .cmux_groups = {
+ &ls1012a_cmux
+ },
+ .cmux_to_group = {
+ 0, -1
+ },
+ .pll_mask = 0x03,
+ },
+ {
.compat = "fsl,ls2080a-clockgen",
.cmux_groups = {
&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
@@ -1273,8 +1331,10 @@ err:
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_ls1012a, "fsl,ls1012a-clockgen", 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_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
/* Legacy nodes */
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 02d681008401..5eb05dbf59b8 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -19,10 +19,14 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
#define STM32F4_RCC_PLLCFGR 0x04
#define STM32F4_RCC_CFGR 0x08
@@ -31,6 +35,8 @@
#define STM32F4_RCC_AHB3ENR 0x38
#define STM32F4_RCC_APB1ENR 0x40
#define STM32F4_RCC_APB2ENR 0x44
+#define STM32F4_RCC_BDCR 0x70
+#define STM32F4_RCC_CSR 0x74
struct stm32f4_gate_data {
u8 offset;
@@ -40,7 +46,7 @@ struct stm32f4_gate_data {
unsigned long flags;
};
-static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
+static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
@@ -120,26 +126,113 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
-/*
- * MAX_CLKS is the maximum value in the enumeration below plus the combined
- * hweight of stm32f42xx_gate_map (plus one).
- */
-#define MAX_CLKS 74
+static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
+};
-enum { SYSTICK, FCLK };
+enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
/*
* This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
* have gate bits associated with them. Its combined hweight is 71.
*/
-static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
- 0x0000000000000001ull,
- 0x04777f33f6fec9ffull };
+#define MAX_GATE_MAP 3
+
+static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000001ull,
+ 0x04777f33f6fec9ffull };
+
+static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000003ull,
+ 0x0c777f33f6fec9ffull };
+
+static const u64 *stm32f4_gate_map;
+
+static struct clk_hw **clks;
-static struct clk_hw *clks[MAX_CLKS];
static DEFINE_SPINLOCK(stm32f4_clk_lock);
static void __iomem *base;
+static struct regmap *pdrm;
+
/*
* "Multiplier" device for APBx clocks.
*
@@ -256,15 +349,15 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
*/
static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
{
- u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
+ u64 table[MAX_GATE_MAP];
if (primary == 1) {
- if (WARN_ON(secondary > FCLK))
+ if (WARN_ON(secondary >= END_PRIMARY_CLK))
return -EINVAL;
return secondary;
}
- memcpy(table, stm32f42xx_gate_map, sizeof(table));
+ memcpy(table, stm32f4_gate_map, sizeof(table));
/* only bits set in table can be used as indices */
if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
@@ -276,7 +369,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
table[BIT_ULL_WORD(secondary)] &=
GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
- return FCLK + hweight64(table[0]) +
+ return END_PRIMARY_CLK - 1 + hweight64(table[0]) +
(BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
(BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
}
@@ -292,6 +385,212 @@ stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
return clks[i];
}
+#define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate)
+
+static inline void disable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+static inline void sofware_reset_backup_domain(void)
+{
+ unsigned long val;
+
+ val = readl(base + STM32F4_RCC_BDCR);
+ writel(val | BIT(16), base + STM32F4_RCC_BDCR);
+ writel(val & ~BIT(16), base + STM32F4_RCC_BDCR);
+}
+
+struct stm32_rgate {
+ struct clk_gate gate;
+ u8 bit_rdy_idx;
+};
+
+#define RTC_TIMEOUT 1000000
+
+static int rgclk_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32_rgate *rgate = to_rgclk(gate);
+ u32 reg;
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.enable(hw);
+
+ ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
+ reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
+
+ enable_power_domain_write_protection();
+ return ret;
+}
+
+static void rgclk_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int rgclk_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops rgclk_ops = {
+ .enable = rgclk_enable,
+ .disable = rgclk_disable,
+ .is_enabled = rgclk_is_enabled,
+};
+
+static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
+{
+ struct stm32_rgate *rgate;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
+ int ret;
+
+ rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+ if (!rgate)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &rgclk_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ rgate->bit_rdy_idx = bit_rdy_idx;
+
+ rgate->gate.lock = lock;
+ rgate->gate.reg = reg;
+ rgate->gate.bit_idx = bit_idx;
+ rgate->gate.hw.init = &init;
+
+ hw = &rgate->gate.hw;
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(rgate);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+static int cclk_gate_enable(struct clk_hw *hw)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ ret = clk_gate_ops.enable(hw);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static void cclk_gate_disable(struct clk_hw *hw)
+{
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.disable(hw);
+
+ enable_power_domain_write_protection();
+}
+
+static int cclk_gate_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops cclk_gate_ops = {
+ .enable = cclk_gate_enable,
+ .disable = cclk_gate_disable,
+ .is_enabled = cclk_gate_is_enabled,
+};
+
+static u8 cclk_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ sofware_reset_backup_domain();
+
+ ret = clk_mux_ops.set_parent(hw, index);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static const struct clk_ops cclk_mux_ops = {
+ .get_parent = cclk_mux_get_parent,
+ .set_parent = cclk_mux_set_parent,
+};
+
+static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
+ const char * const *parent_names, int num_parents,
+ void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
+ spinlock_t *lock)
+{
+ struct clk_hw *hw;
+ struct clk_gate *gate;
+ struct clk_mux *mux;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux) {
+ kfree(gate);
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ gate->reg = reg;
+ gate->bit_idx = bit_idx;
+ gate->flags = 0;
+ gate->lock = lock;
+
+ mux->reg = reg;
+ mux->shift = shift;
+ mux->mask = 3;
+ mux->flags = 0;
+
+ hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+ &mux->hw, &cclk_mux_ops,
+ NULL, NULL,
+ &gate->hw, &cclk_gate_ops,
+ flags);
+
+ if (IS_ERR(hw)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+fail:
+ return hw;
+}
+
static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" };
static const struct clk_div_table ahb_div_table[] = {
@@ -308,10 +607,46 @@ static const struct clk_div_table apb_div_table[] = {
{ 0 },
};
+static const char *rtc_parents[4] = {
+ "no-clock", "lse", "lsi", "hse-rtc"
+};
+
+struct stm32f4_clk_data {
+ const struct stm32f4_gate_data *gates_data;
+ const u64 *gates_map;
+ int gates_num;
+};
+
+static const struct stm32f4_clk_data stm32f429_clk_data = {
+ .gates_data = stm32f429_gates,
+ .gates_map = stm32f42xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f429_gates),
+};
+
+static const struct stm32f4_clk_data stm32f469_clk_data = {
+ .gates_data = stm32f469_gates,
+ .gates_map = stm32f46xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f469_gates),
+};
+
+static const struct of_device_id stm32f4_of_match[] = {
+ {
+ .compatible = "st,stm32f42xx-rcc",
+ .data = &stm32f429_clk_data
+ },
+ {
+ .compatible = "st,stm32f469-rcc",
+ .data = &stm32f469_clk_data
+ },
+ {}
+};
+
static void __init stm32f4_rcc_init(struct device_node *np)
{
const char *hse_clk;
int n;
+ const struct of_device_id *match;
+ const struct stm32f4_clk_data *data;
base = of_iomap(np, 0);
if (!base) {
@@ -319,6 +654,25 @@ static void __init stm32f4_rcc_init(struct device_node *np)
return;
}
+ pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(pdrm)) {
+ pdrm = NULL;
+ pr_warn("%s: Unable to get syscfg\n", __func__);
+ }
+
+ match = of_match_node(stm32f4_of_match, np);
+ if (WARN_ON(!match))
+ return;
+
+ data = match->data;
+
+ clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK,
+ sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ goto fail;
+
+ stm32f4_gate_map = data->gates_map;
+
hse_clk = of_clk_get_parent_name(np, 0);
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
@@ -351,11 +705,15 @@ static void __init stm32f4_rcc_init(struct device_node *np)
clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
0, 1, 1);
- for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
- const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
- unsigned int secondary =
- 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
- int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+ for (n = 0; n < data->gates_num; n++) {
+ const struct stm32f4_gate_data *gd;
+ unsigned int secondary;
+ int idx;
+
+ gd = &data->gates_data[n];
+ secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
+ gd->bit_idx;
+ idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
if (idx < 0)
goto fail;
@@ -371,9 +729,44 @@ static void __init stm32f4_rcc_init(struct device_node *np)
}
}
+ clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
+ base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSI])) {
+ pr_err("Unable to register lsi clock\n");
+ goto fail;
+ }
+
+ clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
+ base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSE])) {
+ pr_err("Unable to register lse clock\n");
+ goto fail;
+ }
+
+ clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
+ 0, base + STM32F4_RCC_CFGR, 16, 5, 0,
+ &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_HSE_RTC])) {
+ pr_err("Unable to register hse-rtc clock\n");
+ goto fail;
+ }
+
+ clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
+ base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_RTC])) {
+ pr_err("Unable to register rtc clock\n");
+ goto fail;
+ }
+
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return;
fail:
+ kfree(clks);
iounmap(base);
}
-CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index f4fdac55727c..0621fbfb4beb 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -243,7 +243,7 @@ static int wm831x_clkout_is_prepared(struct clk_hw *hw)
if (ret < 0) {
dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
ret);
- return true;
+ return false;
}
return (ret & WM831X_CLKOUT_ENA) != 0;
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
index 3f537a04c6a6..cbed6602172b 100644
--- a/drivers/clk/hisilicon/Kconfig
+++ b/drivers/clk/hisilicon/Kconfig
@@ -1,3 +1,11 @@
+config COMMON_CLK_HI3516CV300
+ tristate "HI3516CV300 Clock Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ select RESET_HISI
+ default ARCH_HISI
+ help
+ Build the clock driver for hi3516cv300.
+
config COMMON_CLK_HI3519
tristate "Hi3519 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
@@ -6,6 +14,14 @@ config COMMON_CLK_HI3519
help
Build the clock driver for hi3519.
+config COMMON_CLK_HI3798CV200
+ tristate "Hi3798CV200 Clock Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ select RESET_HISI
+ default ARCH_HISI
+ help
+ Build the clock driver for hi3798cv200.
+
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
@@ -23,5 +39,6 @@ config RESET_HISI
config STUB_CLK_HI6220
bool "Hi6220 Stub Clock Driver"
depends on COMMON_CLK_HI6220 && MAILBOX
+ default ARCH_HISI
help
Build the Hisilicon Hi6220 stub clock driver.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index e169ec7da023..4eec5e511e4c 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -7,7 +7,9 @@ obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI3516CV300) += crg-hi3516cv300.o
obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o
+obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_RESET_HISI) += reset.o
obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o
diff --git a/drivers/clk/hisilicon/crg-hi3516cv300.c b/drivers/clk/hisilicon/crg-hi3516cv300.c
new file mode 100644
index 000000000000..2007123832bb
--- /dev/null
+++ b/drivers/clk/hisilicon/crg-hi3516cv300.c
@@ -0,0 +1,330 @@
+/*
+ * Hi3516CV300 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dt-bindings/clock/hi3516cv300-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3516CV300 core CRG */
+#define HI3516CV300_INNER_CLK_OFFSET 64
+#define HI3516CV300_FIXED_3M 65
+#define HI3516CV300_FIXED_6M 66
+#define HI3516CV300_FIXED_24M 67
+#define HI3516CV300_FIXED_49P5 68
+#define HI3516CV300_FIXED_50M 69
+#define HI3516CV300_FIXED_83P3M 70
+#define HI3516CV300_FIXED_99M 71
+#define HI3516CV300_FIXED_100M 72
+#define HI3516CV300_FIXED_148P5M 73
+#define HI3516CV300_FIXED_198M 74
+#define HI3516CV300_FIXED_297M 75
+#define HI3516CV300_UART_MUX 76
+#define HI3516CV300_FMC_MUX 77
+#define HI3516CV300_MMC0_MUX 78
+#define HI3516CV300_MMC1_MUX 79
+#define HI3516CV300_MMC2_MUX 80
+#define HI3516CV300_MMC3_MUX 81
+#define HI3516CV300_PWM_MUX 82
+#define HI3516CV300_CRG_NR_CLKS 128
+
+static const struct hisi_fixed_rate_clock hi3516cv300_fixed_rate_clks[] = {
+ { HI3516CV300_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { HI3516CV300_FIXED_6M, "6m", NULL, 0, 6000000, },
+ { HI3516CV300_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { HI3516CV300_FIXED_49P5, "49.5m", NULL, 0, 49500000, },
+ { HI3516CV300_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { HI3516CV300_FIXED_83P3M, "83.3m", NULL, 0, 83300000, },
+ { HI3516CV300_FIXED_99M, "99m", NULL, 0, 99000000, },
+ { HI3516CV300_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { HI3516CV300_FIXED_148P5M, "148.5m", NULL, 0, 148500000, },
+ { HI3516CV300_FIXED_198M, "198m", NULL, 0, 198000000, },
+ { HI3516CV300_FIXED_297M, "297m", NULL, 0, 297000000, },
+ { HI3516CV300_APB_CLK, "apb", NULL, 0, 50000000, },
+};
+
+static const char *const uart_mux_p[] = {"24m", "6m"};
+static const char *const fmc_mux_p[] = {
+ "24m", "83.3m", "148.5m", "198m", "297m"
+};
+static const char *const mmc_mux_p[] = {"49.5m"};
+static const char *const mmc2_mux_p[] = {"99m", "49.5m"};
+static const char *const pwm_mux_p[] = {"3m", "50m", "24m", "24m"};
+
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4};
+static u32 mmc_mux_table[] = {0};
+static u32 mmc2_mux_table[] = {0, 2};
+static u32 pwm_mux_table[] = {0, 1, 2, 3};
+
+static const struct hisi_mux_clock hi3516cv300_mux_clks[] = {
+ { HI3516CV300_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, },
+ { HI3516CV300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
+ { HI3516CV300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0xc4, 4, 2, 0, mmc_mux_table, },
+ { HI3516CV300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0xc4, 12, 2, 0, mmc_mux_table, },
+ { HI3516CV300_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p),
+ CLK_SET_RATE_PARENT, 0xc4, 20, 2, 0, mmc2_mux_table, },
+ { HI3516CV300_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0xc8, 4, 2, 0, mmc_mux_table, },
+ { HI3516CV300_PWM_MUX, "pwm_mux", pwm_mux_p, ARRAY_SIZE(pwm_mux_p),
+ CLK_SET_RATE_PARENT, 0x38, 2, 2, 0, pwm_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3516cv300_gate_clks[] = {
+
+ { HI3516CV300_UART0_CLK, "clk_uart0", "uart_mux", CLK_SET_RATE_PARENT,
+ 0xe4, 15, 0, },
+ { HI3516CV300_UART1_CLK, "clk_uart1", "uart_mux", CLK_SET_RATE_PARENT,
+ 0xe4, 16, 0, },
+ { HI3516CV300_UART2_CLK, "clk_uart2", "uart_mux", CLK_SET_RATE_PARENT,
+ 0xe4, 17, 0, },
+
+ { HI3516CV300_SPI0_CLK, "clk_spi0", "100m", CLK_SET_RATE_PARENT,
+ 0xe4, 13, 0, },
+ { HI3516CV300_SPI1_CLK, "clk_spi1", "100m", CLK_SET_RATE_PARENT,
+ 0xe4, 14, 0, },
+
+ { HI3516CV300_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT,
+ 0xc0, 1, 0, },
+ { HI3516CV300_MMC0_CLK, "clk_mmc0", "mmc0_mux", CLK_SET_RATE_PARENT,
+ 0xc4, 1, 0, },
+ { HI3516CV300_MMC1_CLK, "clk_mmc1", "mmc1_mux", CLK_SET_RATE_PARENT,
+ 0xc4, 9, 0, },
+ { HI3516CV300_MMC2_CLK, "clk_mmc2", "mmc2_mux", CLK_SET_RATE_PARENT,
+ 0xc4, 17, 0, },
+ { HI3516CV300_MMC3_CLK, "clk_mmc3", "mmc3_mux", CLK_SET_RATE_PARENT,
+ 0xc8, 1, 0, },
+
+ { HI3516CV300_ETH_CLK, "clk_eth", NULL, 0, 0xec, 1, 0, },
+
+ { HI3516CV300_DMAC_CLK, "clk_dmac", NULL, 0, 0xd8, 5, 0, },
+ { HI3516CV300_PWM_CLK, "clk_pwm", "pwm_mux", CLK_SET_RATE_PARENT,
+ 0x38, 1, 0, },
+
+ { HI3516CV300_USB2_BUS_CLK, "clk_usb2_bus", NULL, 0, 0xb8, 0, 0, },
+ { HI3516CV300_USB2_OHCI48M_CLK, "clk_usb2_ohci48m", NULL, 0,
+ 0xb8, 1, 0, },
+ { HI3516CV300_USB2_OHCI12M_CLK, "clk_usb2_ohci12m", NULL, 0,
+ 0xb8, 2, 0, },
+ { HI3516CV300_USB2_OTG_UTMI_CLK, "clk_usb2_otg_utmi", NULL, 0,
+ 0xb8, 3, 0, },
+ { HI3516CV300_USB2_HST_PHY_CLK, "clk_usb2_hst_phy", NULL, 0,
+ 0xb8, 4, 0, },
+ { HI3516CV300_USB2_UTMI0_CLK, "clk_usb2_utmi0", NULL, 0, 0xb8, 5, 0, },
+ { HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
+};
+
+static struct hisi_clock_data *hi3516cv300_clk_register(
+ struct platform_device *pdev)
+{
+ struct hisi_clock_data *clk_data;
+ int ret;
+
+ clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
+ if (!clk_data)
+ return ERR_PTR(-ENOMEM);
+
+ ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
+ ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
+ ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+ if (ret)
+ goto unregister_fixed_rate;
+
+ ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
+ ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
+ if (ret)
+ goto unregister_mux;
+
+ ret = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, &clk_data->clk_data);
+ if (ret)
+ goto unregister_gate;
+
+ return clk_data;
+
+unregister_gate:
+ hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+ ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
+unregister_mux:
+ hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+ ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+unregister_fixed_rate:
+ hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+ ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+ return ERR_PTR(ret);
+}
+
+static void hi3516cv300_clk_unregister(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+ ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
+ hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+ ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
+ hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+ ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
+ .register_clks = hi3516cv300_clk_register,
+ .unregister_clks = hi3516cv300_clk_unregister,
+};
+
+/* hi3516CV300 sysctrl CRG */
+#define HI3516CV300_SYSCTRL_NR_CLKS 16
+
+static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
+static u32 wdt_mux_table[] = {0, 1};
+
+static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
+ { HI3516CV300_WDT_CLK, "wdt", wdt_mux_p, ARRAY_SIZE(wdt_mux_p),
+ CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
+};
+
+static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
+ struct platform_device *pdev)
+{
+ struct hisi_clock_data *clk_data;
+ int ret;
+
+ clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
+ if (!clk_data)
+ return ERR_PTR(-ENOMEM);
+
+ ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
+ ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+ if (ret)
+ return ERR_PTR(ret);
+
+
+ ret = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, &clk_data->clk_data);
+ if (ret)
+ goto unregister_mux;
+
+ return clk_data;
+
+unregister_mux:
+ hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+ ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+ return ERR_PTR(ret);
+}
+
+static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+ ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
+ crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
+ .register_clks = hi3516cv300_sysctrl_clk_register,
+ .unregister_clks = hi3516cv300_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3516cv300_crg_match_table[] = {
+ {
+ .compatible = "hisilicon,hi3516cv300-crg",
+ .data = &hi3516cv300_crg_funcs
+ },
+ {
+ .compatible = "hisilicon,hi3516cv300-sysctrl",
+ .data = &hi3516cv300_sysctrl_funcs
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);
+
+static int hi3516cv300_crg_probe(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg;
+
+ crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+ if (!crg)
+ return -ENOMEM;
+
+ crg->funcs = of_device_get_match_data(&pdev->dev);
+ if (!crg->funcs)
+ return -ENOENT;
+
+ crg->rstc = hisi_reset_init(pdev);
+ if (!crg->rstc)
+ return -ENOMEM;
+
+ crg->clk_data = crg->funcs->register_clks(pdev);
+ if (IS_ERR(crg->clk_data)) {
+ hisi_reset_exit(crg->rstc);
+ return PTR_ERR(crg->clk_data);
+ }
+
+ platform_set_drvdata(pdev, crg);
+ return 0;
+}
+
+static int hi3516cv300_crg_remove(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ hisi_reset_exit(crg->rstc);
+ crg->funcs->unregister_clks(pdev);
+ return 0;
+}
+
+static struct platform_driver hi3516cv300_crg_driver = {
+ .probe = hi3516cv300_crg_probe,
+ .remove = hi3516cv300_crg_remove,
+ .driver = {
+ .name = "hi3516cv300-crg",
+ .of_match_table = hi3516cv300_crg_match_table,
+ },
+};
+
+static int __init hi3516cv300_crg_init(void)
+{
+ return platform_driver_register(&hi3516cv300_crg_driver);
+}
+core_initcall(hi3516cv300_crg_init);
+
+static void __exit hi3516cv300_crg_exit(void)
+{
+ platform_driver_unregister(&hi3516cv300_crg_driver);
+}
+module_exit(hi3516cv300_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");
diff --git a/drivers/clk/hisilicon/crg-hi3798cv200.c b/drivers/clk/hisilicon/crg-hi3798cv200.c
new file mode 100644
index 000000000000..fc8b5bc2d50d
--- /dev/null
+++ b/drivers/clk/hisilicon/crg-hi3798cv200.c
@@ -0,0 +1,337 @@
+/*
+ * Hi3798CV200 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dt-bindings/clock/histb-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3798CV200 core CRG */
+#define HI3798CV200_INNER_CLK_OFFSET 64
+#define HI3798CV200_FIXED_24M 65
+#define HI3798CV200_FIXED_25M 66
+#define HI3798CV200_FIXED_50M 67
+#define HI3798CV200_FIXED_75M 68
+#define HI3798CV200_FIXED_100M 69
+#define HI3798CV200_FIXED_150M 70
+#define HI3798CV200_FIXED_200M 71
+#define HI3798CV200_FIXED_250M 72
+#define HI3798CV200_FIXED_300M 73
+#define HI3798CV200_FIXED_400M 74
+#define HI3798CV200_MMC_MUX 75
+#define HI3798CV200_ETH_PUB_CLK 76
+#define HI3798CV200_ETH_BUS_CLK 77
+#define HI3798CV200_ETH_BUS0_CLK 78
+#define HI3798CV200_ETH_BUS1_CLK 79
+#define HI3798CV200_COMBPHY1_MUX 80
+
+#define HI3798CV200_CRG_NR_CLKS 128
+
+static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
+ { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
+ { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
+ { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
+ { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
+ { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
+};
+
+static const char *const mmc_mux_p[] = {
+ "100m", "50m", "25m", "200m", "150m" };
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
+
+static const char *const comphy1_mux_p[] = {
+ "100m", "25m"};
+static u32 comphy1_mux_table[] = {2, 3};
+
+static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
+ { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
+ { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
+ comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
+ CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
+ /* UART */
+ { HISTB_UART2_CLK, "clk_uart2", "75m",
+ CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+ /* I2C */
+ { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+ { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+ { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+ { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
+ { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
+ /* SPI */
+ { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+ /* SDIO */
+ { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+ CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+ { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
+ CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+ /* EMMC */
+ { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+ CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+ { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+ CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+ /* PCIE*/
+ { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
+ CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
+ { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
+ CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
+ { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
+ CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
+ { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
+ CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
+ /* Ethernet */
+ { HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
+ CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
+ { HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
+ CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
+ { HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
+ CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
+ { HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
+ CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
+ { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
+ CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
+ { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
+ CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
+ { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
+ CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
+ { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
+ CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
+ /* COMBPHY1 */
+ { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
+ CLK_SET_RATE_PARENT, 0x188, 8, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_clk_register(
+ struct platform_device *pdev)
+{
+ struct hisi_clock_data *clk_data;
+ int ret;
+
+ clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
+ if (!clk_data)
+ return ERR_PTR(-ENOMEM);
+
+ ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
+ ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+ clk_data);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
+ ARRAY_SIZE(hi3798cv200_mux_clks),
+ clk_data);
+ if (ret)
+ goto unregister_fixed_rate;
+
+ ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
+ ARRAY_SIZE(hi3798cv200_gate_clks),
+ clk_data);
+ if (ret)
+ goto unregister_mux;
+
+ ret = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, &clk_data->clk_data);
+ if (ret)
+ goto unregister_gate;
+
+ return clk_data;
+
+unregister_fixed_rate:
+ hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+ ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+ clk_data);
+
+unregister_mux:
+ hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+ ARRAY_SIZE(hi3798cv200_mux_clks),
+ clk_data);
+unregister_gate:
+ hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+ ARRAY_SIZE(hi3798cv200_gate_clks),
+ clk_data);
+ return ERR_PTR(ret);
+}
+
+static void hi3798cv200_clk_unregister(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+ ARRAY_SIZE(hi3798cv200_gate_clks),
+ crg->clk_data);
+ hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+ ARRAY_SIZE(hi3798cv200_mux_clks),
+ crg->clk_data);
+ hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+ ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+ crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
+ .register_clks = hi3798cv200_clk_register,
+ .unregister_clks = hi3798cv200_clk_unregister,
+};
+
+/* hi3798CV200 sysctrl CRG */
+
+#define HI3798CV200_SYSCTRL_NR_CLKS 16
+
+static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
+ { HISTB_IR_CLK, "clk_ir", "100m",
+ CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+ { HISTB_TIMER01_CLK, "clk_timer01", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+ { HISTB_UART0_CLK, "clk_uart0", "75m",
+ CLK_SET_RATE_PARENT, 0x48, 10, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
+ struct platform_device *pdev)
+{
+ struct hisi_clock_data *clk_data;
+ int ret;
+
+ clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
+ if (!clk_data)
+ return ERR_PTR(-ENOMEM);
+
+ ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
+ ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+ clk_data);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, &clk_data->clk_data);
+ if (ret)
+ goto unregister_gate;
+
+ return clk_data;
+
+unregister_gate:
+ hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+ ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+ clk_data);
+ return ERR_PTR(ret);
+}
+
+static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+ ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+ crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
+ .register_clks = hi3798cv200_sysctrl_clk_register,
+ .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3798cv200_crg_match_table[] = {
+ { .compatible = "hisilicon,hi3798cv200-crg",
+ .data = &hi3798cv200_crg_funcs },
+ { .compatible = "hisilicon,hi3798cv200-sysctrl",
+ .data = &hi3798cv200_sysctrl_funcs },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
+
+static int hi3798cv200_crg_probe(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg;
+
+ crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+ if (!crg)
+ return -ENOMEM;
+
+ crg->funcs = of_device_get_match_data(&pdev->dev);
+ if (!crg->funcs)
+ return -ENOENT;
+
+ crg->rstc = hisi_reset_init(pdev);
+ if (!crg->rstc)
+ return -ENOMEM;
+
+ crg->clk_data = crg->funcs->register_clks(pdev);
+ if (IS_ERR(crg->clk_data)) {
+ hisi_reset_exit(crg->rstc);
+ return PTR_ERR(crg->clk_data);
+ }
+
+ platform_set_drvdata(pdev, crg);
+ return 0;
+}
+
+static int hi3798cv200_crg_remove(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ hisi_reset_exit(crg->rstc);
+ crg->funcs->unregister_clks(pdev);
+ return 0;
+}
+
+static struct platform_driver hi3798cv200_crg_driver = {
+ .probe = hi3798cv200_crg_probe,
+ .remove = hi3798cv200_crg_remove,
+ .driver = {
+ .name = "hi3798cv200-crg",
+ .of_match_table = hi3798cv200_crg_match_table,
+ },
+};
+
+static int __init hi3798cv200_crg_init(void)
+{
+ return platform_driver_register(&hi3798cv200_crg_driver);
+}
+core_initcall(hi3798cv200_crg_init);
+
+static void __exit hi3798cv200_crg_exit(void)
+{
+ platform_driver_unregister(&hi3798cv200_crg_driver);
+}
+module_exit(hi3798cv200_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");
diff --git a/drivers/clk/hisilicon/crg.h b/drivers/clk/hisilicon/crg.h
new file mode 100644
index 000000000000..e0739717de9a
--- /dev/null
+++ b/drivers/clk/hisilicon/crg.h
@@ -0,0 +1,34 @@
+/*
+ * HiSilicon Clock and Reset Driver Header
+ *
+ * Copyright (c) 2016 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __HISI_CRG_H
+#define __HISI_CRG_H
+
+struct hisi_clock_data;
+struct hisi_reset_controller;
+
+struct hisi_crg_funcs {
+ struct hisi_clock_data* (*register_clks)(struct platform_device *pdev);
+ void (*unregister_clks)(struct platform_device *pdev);
+};
+
+struct hisi_crg_dev {
+ struct hisi_clock_data *clk_data;
+ struct hisi_reset_controller *rstc;
+ const struct hisi_crg_funcs *funcs;
+};
+
+#endif /* __HISI_CRG_H */
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index ce8ea10407e4..42ffc1c92bab 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -156,10 +156,267 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
+static int ldb_di_sel_by_clock_id(int clock_id)
+{
+ switch (clock_id) {
+ case IMX6QDL_CLK_PLL5_VIDEO_DIV:
+ if (clk_on_imx6q() &&
+ imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
+ return -ENOENT;
+ return 0;
+ case IMX6QDL_CLK_PLL2_PFD0_352M:
+ return 1;
+ case IMX6QDL_CLK_PLL2_PFD2_396M:
+ return 2;
+ case IMX6QDL_CLK_MMDC_CH1_AXI:
+ return 3;
+ case IMX6QDL_CLK_PLL3_USB_OTG:
+ return 4;
+ default:
+ return -ENOENT;
+ }
+}
+
+static void of_assigned_ldb_sels(struct device_node *node,
+ unsigned int *ldb_di0_sel,
+ unsigned int *ldb_di1_sel)
+{
+ struct of_phandle_args clkspec;
+ int index, rc, num_parents;
+ int parent, child, sel;
+
+ num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells");
+ for (index = 0; index < num_parents; index++) {
+ rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return;
+ }
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: parent clock %d not in ccm\n", index);
+ return;
+ }
+ parent = clkspec.args[0];
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0)
+ return;
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: child clock %d not in ccm\n", index);
+ return;
+ }
+ child = clkspec.args[0];
+
+ if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
+ child != IMX6QDL_CLK_LDB_DI1_SEL)
+ continue;
+
+ sel = ldb_di_sel_by_clock_id(parent);
+ if (sel < 0) {
+ pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
+ child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
+ continue;
+ }
+
+ if (child == IMX6QDL_CLK_LDB_DI0_SEL)
+ *ldb_di0_sel = sel;
+ if (child == IMX6QDL_CLK_LDB_DI1_SEL)
+ *ldb_di1_sel = sel;
+ }
+}
+
+#define CCM_CCDR 0x04
+#define CCM_CCSR 0x0c
+#define CCM_CS2CDR 0x2c
+
+#define CCDR_MMDC_CH1_MASK BIT(16)
+#define CCSR_PLL3_SW_CLK_SEL BIT(0)
+
+#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT 9
+#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT 12
+
+static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ reg = readl_relaxed(ccm_base + CCM_CCDR);
+ reg |= CCDR_MMDC_CH1_MASK;
+ writel_relaxed(reg, ccm_base + CCM_CCDR);
+}
+
+/*
+ * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
+ * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
+ * bypass clock source, since there is no CG bit for mmdc_ch1.
+ */
+static void mmdc_ch1_disable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
+ clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+
+ /*
+ * Handshake with mmdc_ch1 module must be masked when changing
+ * periph2_clk_sel.
+ */
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+
+ /* Disable pll3_sw_clk by selecting the bypass clock source */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg |= CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+}
+
+static void mmdc_ch1_reenable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ /* Enable pll3_sw_clk by disabling the bypass */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg &= ~CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
+}
+
+/*
+ * We have to follow a strict procedure when changing the LDB clock source,
+ * otherwise we risk introducing a glitch that can lock up the LDB divider.
+ * Things to keep in mind:
+ *
+ * 1. The current and new parent clock inputs to the mux must be disabled.
+ * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which
+ * has no CG bit.
+ * 3. pll2_pfd2_396m can not be gated if it is used as memory clock.
+ * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four
+ * options are in one mux and the PLL3 option along with three unused
+ * inputs is in a second mux. There is a third mux with two inputs used
+ * to decide between the first and second 4-port mux:
+ *
+ * pll5_video_div 0 --|\
+ * pll2_pfd0_352m 1 --| |_
+ * pll2_pfd2_396m 2 --| | `-|\
+ * mmdc_ch1_axi 3 --|/ | |
+ * | |--
+ * pll3_usb_otg 4 --|\ | |
+ * 5 --| |_,-|/
+ * 6 --| |
+ * 7 --|/
+ *
+ * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes at the same time.
+ * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below
+ * switches the parent to the bottom mux first and then manipulates the top
+ * mux to ensure that no glitch will enter the divider.
+ */
+static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
+{
+ unsigned int reg;
+ unsigned int sel[2][4];
+ int i;
+
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7;
+ sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7;
+
+ sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0];
+ sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0];
+
+ of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
+
+ for (i = 0; i < 2; i++) {
+ /* Warn if a glitch might have been introduced already */
+ if (sel[i][0] != 3) {
+ pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+ i, sel[i][0]);
+ }
+
+ if (sel[i][0] == sel[i][3])
+ continue;
+
+ /* Only switch to or from pll2_pfd2_396m if it is disabled */
+ if ((sel[i][0] == 2 || sel[i][3] == 2) &&
+ (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+ pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
+ i);
+ sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
+ continue;
+ }
+
+ /* First switch to the bottom mux */
+ sel[i][1] = sel[i][0] | 4;
+
+ /* Then configure the top mux before switching back to it */
+ sel[i][2] = sel[i][3] | 4;
+
+ pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i,
+ sel[i][0], sel[i][1], sel[i][2], sel[i][3]);
+ }
+
+ if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3])
+ return;
+
+ mmdc_ch1_disable(ccm_base);
+
+ for (i = 1; i < 4; i++) {
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ writel_relaxed(reg, ccm_base + CCM_CS2CDR);
+ }
+
+ mmdc_ch1_reenable(ccm_base);
+}
+
+#define CCM_ANALOG_PLL_VIDEO 0xa0
+#define CCM_ANALOG_PFD_480 0xf0
+#define CCM_ANALOG_PFD_528 0x100
+
+#define PLL_ENABLE BIT(13)
+
+#define PFD0_CLKGATE BIT(7)
+#define PFD1_CLKGATE BIT(15)
+#define PFD2_CLKGATE BIT(23)
+#define PFD3_CLKGATE BIT(31)
+
+static void disable_anatop_clocks(void __iomem *anatop_base)
+{
+ unsigned int reg;
+
+ /* Make sure PLL2 PFDs 0-2 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
+ /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
+ if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE;
+ else
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528);
+
+ /* Make sure PLL3 PFDs 0-3 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480);
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480);
+
+ /* Make sure PLL5 is disabled */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO);
+ reg &= ~PLL_ENABLE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
+}
+
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
- void __iomem *base;
+ void __iomem *anatop_base, *base;
int i;
int ret;
@@ -172,7 +429,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
- base = of_iomap(np, 0);
+ anatop_base = base = of_iomap(np, 0);
WARN_ON(!base);
/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
@@ -330,8 +587,20 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+
+ disable_anatop_clocks(anatop_base);
+
+ imx6q_mmdc_ch1_mask_handshake(base);
+
+ /*
+ * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
+ * bug. Set the muxes to the requested values before registering the
+ * ldb_di_sel clocks.
+ */
+ init_ldb_clks(np, base);
+
+ clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -582,12 +851,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
- if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
- clk_on_imx6dl()) {
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- }
-
clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
if (clk_on_imx6dl())
clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index d1d7787ce211..75c35fb12b60 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -64,6 +64,10 @@ static const char *perclk_sels[] = { "ipg", "osc", };
static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+/* epdc_pre_sels, epdc_sels, esai_sels only exists on i.MX6ULL */
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *esai_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
static struct clk *clks[IMX6UL_CLK_END];
static struct clk_onecell_data clk_data;
@@ -102,6 +106,17 @@ static u32 share_count_audio;
static u32 share_count_sai1;
static u32 share_count_sai2;
static u32 share_count_sai3;
+static u32 share_count_esai;
+
+static inline int clk_on_imx6ul(void)
+{
+ return of_machine_is_compatible("fsl,imx6ul");
+}
+
+static inline int clk_on_imx6ull(void)
+{
+ return of_machine_is_compatible("fsl,imx6ull");
+}
static void __init imx6ul_clocks_init(struct device_node *ccm_node)
{
@@ -238,12 +253,19 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
clks[IMX6UL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
clks[IMX6UL_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
+ if (clk_on_imx6ull())
+ clks[IMX6ULL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
clks[IMX6UL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
clks[IMX6UL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
clks[IMX6UL_CLK_LDB_DI0_SEL] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
clks[IMX6UL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
- clks[IMX6UL_CLK_SIM_PRE_SEL] = imx_clk_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
- clks[IMX6UL_CLK_SIM_SEL] = imx_clk_mux("sim_sel", base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_SIM_PRE_SEL] = imx_clk_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+ clks[IMX6UL_CLK_SIM_SEL] = imx_clk_mux("sim_sel", base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+ } else if (clk_on_imx6ull()) {
+ clks[IMX6ULL_CLK_EPDC_PRE_SEL] = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+ clks[IMX6ULL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+ }
clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
@@ -276,6 +298,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_SAI3_PODF] = imx_clk_divider("sai3_podf", "sai3_pred", base + 0x28, 16, 6);
clks[IMX6UL_CLK_SAI1_PRED] = imx_clk_divider("sai1_pred", "sai1_sel", base + 0x28, 6, 3);
clks[IMX6UL_CLK_SAI1_PODF] = imx_clk_divider("sai1_podf", "sai1_pred", base + 0x28, 0, 6);
+ if (clk_on_imx6ull()) {
+ clks[IMX6ULL_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3);
+ clks[IMX6ULL_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3);
+ }
clks[IMX6UL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
clks[IMX6UL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
clks[IMX6UL_CLK_SAI2_PRED] = imx_clk_divider("sai2_pred", "sai2_sel", base + 0x2c, 6, 3);
@@ -298,9 +324,15 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_APBHDMA] = imx_clk_gate2("apbh_dma", "bch_podf", base + 0x68, 4);
clks[IMX6UL_CLK_ASRC_IPG] = imx_clk_gate2_shared("asrc_ipg", "ahb", base + 0x68, 6, &share_count_asrc);
clks[IMX6UL_CLK_ASRC_MEM] = imx_clk_gate2_shared("asrc_mem", "ahb", base + 0x68, 6, &share_count_asrc);
- clks[IMX6UL_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
- clks[IMX6UL_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
- clks[IMX6UL_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
+ clks[IMX6UL_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
+ clks[IMX6UL_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
+ } else if (clk_on_imx6ull()) {
+ clks[IMX6ULL_CLK_DCP_CLK] = imx_clk_gate2("dcp", "ahb", base + 0x68, 10);
+ clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x68, 12);
+ clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x68, 12);
+ }
clks[IMX6UL_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
clks[IMX6UL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16);
clks[IMX6UL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
@@ -309,7 +341,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26);
clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
- clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
+ if (clk_on_imx6ul())
+ clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
+ else if (clk_on_imx6ull())
+ clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x80, 18);
/* CCGR1 */
clks[IMX6UL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0);
@@ -328,6 +363,11 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
/* CCGR2 */
+ if (clk_on_imx6ull()) {
+ clks[IMX6ULL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x70, 0, &share_count_esai);
+ clks[IMX6ULL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x70, 0, &share_count_esai);
+ clks[IMX6ULL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x70, 0, &share_count_esai);
+ }
clks[IMX6UL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2);
clks[IMX6UL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6);
clks[IMX6UL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8);
@@ -340,8 +380,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
/* CCGR3 */
clks[IMX6UL_CLK_UART5_IPG] = imx_clk_gate2("uart5_ipg", "ipg", base + 0x74, 2);
clks[IMX6UL_CLK_UART5_SERIAL] = imx_clk_gate2("uart5_serial", "uart_podf", base + 0x74, 2);
- clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4);
- clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x74, 4);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4);
+ clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x74, 4);
+ } else if (clk_on_imx6ull()) {
+ clks[IMX6ULL_CLK_EPDC_ACLK] = imx_clk_gate2("epdc_aclk", "axi", base + 0x74, 4);
+ clks[IMX6ULL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_podf", base + 0x74, 4);
+ }
clks[IMX6UL_CLK_UART6_IPG] = imx_clk_gate2("uart6_ipg", "ipg", base + 0x74, 6);
clks[IMX6UL_CLK_UART6_SERIAL] = imx_clk_gate2("uart6_serial", "uart_podf", base + 0x74, 6);
clks[IMX6UL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_podf", base + 0x74, 10);
@@ -385,8 +430,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
clks[IMX6UL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
clks[IMX6UL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
- clks[IMX6UL_CLK_SIM1] = imx_clk_gate2("sim1", "sim_sel", base + 0x80, 6);
- clks[IMX6UL_CLK_SIM2] = imx_clk_gate2("sim2", "sim_sel", base + 0x80, 8);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_SIM1] = imx_clk_gate2("sim1", "sim_sel", base + 0x80, 6);
+ clks[IMX6UL_CLK_SIM2] = imx_clk_gate2("sim2", "sim_sel", base + 0x80, 8);
+ }
clks[IMX6UL_CLK_EIM] = imx_clk_gate2("eim", "eim_slow_podf", base + 0x80, 10);
clks[IMX6UL_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16);
clks[IMX6UL_CLK_UART8_IPG] = imx_clk_gate2("uart8_ipg", "ipg", base + 0x80, 14);
@@ -441,7 +488,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
}
clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
- clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ if (clk_on_imx6ul())
+ clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ else if (clk_on_imx6ull())
+ clk_set_parent(clks[IMX6ULL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]);
clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
}
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index 7a6acc3e4a92..ed3a2df536ea 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -234,6 +234,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long max_rate = parent_rate * 54;
u32 div;
u32 mfn, mfd = 1000000;
+ u32 max_mfd = 0x3FFFFFFF;
u64 temp64;
if (rate > max_rate)
@@ -241,6 +242,9 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
else if (rate < min_rate)
rate = min_rate;
+ if (parent_rate <= max_mfd)
+ mfd = parent_rate;
+
div = rate / parent_rate;
temp64 = (u64) (rate - div * parent_rate);
temp64 *= mfd;
@@ -262,11 +266,15 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long max_rate = parent_rate * 54;
u32 val, div;
u32 mfn, mfd = 1000000;
+ u32 max_mfd = 0x3FFFFFFF;
u64 temp64;
if (rate < min_rate || rate > max_rate)
return -EINVAL;
+ if (parent_rate <= max_mfd)
+ mfd = parent_rate;
+
div = rate / parent_rate;
temp64 = (u64) (rate - div * parent_rate);
temp64 *= mfd;
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 3799ff82a9b4..4afad3b96a61 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -75,6 +75,14 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate)
return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
}
+static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char **parents, int num_parents)
+{
+ return clk_register_mux(NULL, name, parents, num_parents,
+ CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
+ shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div)
{
diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
index a26ba2184454..e7e840fb74ea 100644
--- a/drivers/clk/keystone/pll.c
+++ b/drivers/clk/keystone/pll.c
@@ -154,7 +154,7 @@ out:
}
/**
- * _of_clk_init - PLL initialisation via DT
+ * _of_pll_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 register0(bit 11-6)
@@ -235,7 +235,7 @@ CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock",
of_keystone_pll_clk_init);
/**
- * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper
+ * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper
* @node: device tree node for this clock
*/
static void __init of_keystone_main_pll_clk_init(struct device_node *node)
@@ -267,25 +267,30 @@ static void __init of_pll_div_clk_init(struct device_node *node)
parent_name = of_clk_get_parent_name(node, 0);
if (!parent_name) {
pr_err("%s: missing parent clock\n", __func__);
+ iounmap(reg);
return;
}
if (of_property_read_u32(node, "bit-shift", &shift)) {
pr_err("%s: missing 'shift' property\n", __func__);
+ iounmap(reg);
return;
}
if (of_property_read_u32(node, "bit-mask", &mask)) {
pr_err("%s: missing 'bit-mask' property\n", __func__);
+ iounmap(reg);
return;
}
clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
mask, 0, NULL);
- if (clk)
+ if (clk) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
- else
+ } else {
pr_err("%s: error registering divider %s\n", __func__, clk_name);
+ iounmap(reg);
+ }
}
CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index f042bd2a6a99..0bd631a41f6a 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -6,6 +6,49 @@ config COMMON_CLK_MEDIATEK
---help---
Mediatek SoCs' clock support.
+config COMMON_CLK_MT2701
+ bool "Clock driver for Mediatek MT2701"
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK
+ ---help---
+ This driver supports Mediatek MT2701 basic clocks.
+
+config COMMON_CLK_MT2701_MMSYS
+ bool "Clock driver for Mediatek MT2701 mmsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 mmsys clocks.
+
+config COMMON_CLK_MT2701_IMGSYS
+ bool "Clock driver for Mediatek MT2701 imgsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 imgsys clocks.
+
+config COMMON_CLK_MT2701_VDECSYS
+ bool "Clock driver for Mediatek MT2701 vdecsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 vdecsys clocks.
+
+config COMMON_CLK_MT2701_HIFSYS
+ bool "Clock driver for Mediatek MT2701 hifsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 hifsys clocks.
+
+config COMMON_CLK_MT2701_ETHSYS
+ bool "Clock driver for Mediatek MT2701 ethsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 ethsys clocks.
+
+config COMMON_CLK_MT2701_BDPSYS
+ bool "Clock driver for Mediatek MT2701 bdpsys"
+ select COMMON_CLK_MT2701
+ ---help---
+ This driver supports Mediatek MT2701 bdpsys clocks.
+
config COMMON_CLK_MT8135
bool "Clock driver for Mediatek MT8135"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 32e7222e7305..19ae7ef79b57 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,11 @@
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
+obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
+obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
+obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index d8787bf444eb..934bf0e45e26 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
}
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+ u32 cgbit = BIT(cg->bit);
+
+ regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+ u32 cgbit = BIT(cg->bit);
+
+ regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
static int mtk_cg_enable(struct clk_hw *hw)
{
mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
mtk_cg_clr_bit(hw);
}
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit_no_setclr(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_set_bit_no_setclr(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit_no_setclr(hw);
+}
+
const struct clk_ops mtk_clk_gate_ops_setclr = {
.is_enabled = mtk_cg_bit_is_cleared,
.enable = mtk_cg_enable,
@@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
.disable = mtk_cg_disable_inv,
};
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+ .is_enabled = mtk_cg_bit_is_cleared,
+ .enable = mtk_cg_enable_no_setclr,
+ .disable = mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+ .is_enabled = mtk_cg_bit_is_set,
+ .enable = mtk_cg_enable_inv_no_setclr,
+ .disable = mtk_cg_disable_inv_no_setclr,
+};
+
struct clk *mtk_clk_register_gate(
const char *name,
const char *parent_name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index b1821603b887..72ef89b3ad7b 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
extern const struct clk_ops mtk_clk_gate_ops_setclr;
extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
struct clk *mtk_clk_register_gate(
const char *name,
diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
new file mode 100644
index 000000000000..fe4964d05b5f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs bdp0_cg_regs = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &bdp0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_BDP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &bdp1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate bdp_clks[] = {
+ GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+ GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+ GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+ GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+ GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+ GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+ GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+ GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+ GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+ GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+ GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+ GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+ GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+ GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+ GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+ GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+ GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+ GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+ GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+ GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+ GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+ GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+ GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+ GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+ GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+ GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+ GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+ GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+ GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+ GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+ GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+ GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+ GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+ GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+ GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+ GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+ GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+ GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+ GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+ GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+ GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+ GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+ GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+ GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+ GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+ GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+ GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+ GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+ GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static const struct of_device_id of_match_clk_mt2701_bdp[] = {
+ { .compatible = "mediatek,mt2701-bdpsys", },
+ {}
+};
+
+static int clk_mt2701_bdp_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+ mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_bdp_drv = {
+ .probe = clk_mt2701_bdp_probe,
+ .driver = {
+ .name = "clk-mt2701-bdp",
+ .of_match_table = of_match_clk_mt2701_bdp,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_bdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
new file mode 100644
index 000000000000..877be8715afa
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-eth.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs eth_cg_regs = {
+ .sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &eth_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate eth_clks[] = {
+ GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+ GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+ GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+ GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+ GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+ GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+ GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+ GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static const struct of_device_id of_match_clk_mt2701_eth[] = {
+ { .compatible = "mediatek,mt2701-ethsys", },
+ {}
+};
+
+static int clk_mt2701_eth_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+ mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_eth_drv = {
+ .probe = clk_mt2701_eth_probe,
+ .driver = {
+ .name = "clk-mt2701-eth",
+ .of_match_table = of_match_clk_mt2701_eth,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_eth_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
new file mode 100644
index 000000000000..18f3723be3e8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs hif_cg_regs = {
+ .sta_ofs = 0x0030,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &hif_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate hif_clks[] = {
+ GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+ GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+ GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+ GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+ GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static const struct of_device_id of_match_clk_mt2701_hif[] = {
+ { .compatible = "mediatek,mt2701-hifsys", },
+ {}
+};
+
+static int clk_mt2701_hif_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+ mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r) {
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+ return r;
+ }
+
+ mtk_register_reset_controller(node, 1, 0x34);
+
+ return 0;
+}
+
+static struct platform_driver clk_mt2701_hif_drv = {
+ .probe = clk_mt2701_hif_probe,
+ .driver = {
+ .name = "clk-mt2701-hif",
+ .of_match_table = of_match_clk_mt2701_hif,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_hif_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
new file mode 100644
index 000000000000..b7441c98bda8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-img.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &img_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] = {
+ GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+ GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+ GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+ GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+ GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+ GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static const struct of_device_id of_match_clk_mt2701_img[] = {
+ { .compatible = "mediatek,mt2701-imgsys", },
+ {}
+};
+
+static int clk_mt2701_img_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+ 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)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_img_drv = {
+ .probe = clk_mt2701_img_probe,
+ .driver = {
+ .name = "clk-mt2701-img",
+ .of_match_table = of_match_clk_mt2701_img,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
new file mode 100644
index 000000000000..fe1f85072fc5
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-mm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs disp0_cg_regs = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &disp0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_DISP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &disp1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate mm_clks[] = {
+ GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+ GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+ GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+ GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+ GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+ GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+ GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+ GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+ GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+ GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+ GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+ GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+ GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+ GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+ GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+ GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+ GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+ GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+ GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+ GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+ GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+ GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+ GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+ GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+ GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+ GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+ GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+ GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+ GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+ GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+ GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+ GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+ GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+ GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static const struct of_device_id of_match_clk_mt2701_mm[] = {
+ { .compatible = "mediatek,mt2701-mmsys", },
+ {}
+};
+
+static int clk_mt2701_mm_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+ 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)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_mm_drv = {
+ .probe = clk_mt2701_mm_probe,
+ .driver = {
+ .name = "clk-mt2701-mm",
+ .of_match_table = of_match_clk_mt2701_mm,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
new file mode 100644
index 000000000000..d3c0fc9d6f02
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+ .set_ofs = 0x0000,
+ .clr_ofs = 0x0004,
+ .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+ .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[] = {
+ GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static const struct of_device_id of_match_clk_mt2701_vdec[] = {
+ { .compatible = "mediatek,mt2701-vdecsys", },
+ {}
+};
+
+static int clk_mt2701_vdec_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+ 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)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_vdec_drv = {
+ .probe = clk_mt2701_vdec_probe,
+ .driver = {
+ .name = "clk-mt2701-vdec",
+ .of_match_table = of_match_clk_mt2701_vdec,
+ },
+};
+
+builtin_platform_driver(clk_mt2701_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
new file mode 100644
index 000000000000..6f26e6a37a6b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-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(mt2701_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+ FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+ 108 * MHZ),
+ FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+ 400 * MHZ),
+ FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+ 295750000),
+ FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m",
+ 300 * MHZ),
+ FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+ 27 * MHZ),
+ FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+ 416 * MHZ),
+ FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+ 143 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+ 27 * MHZ),
+ FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+ DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+ DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+ DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+ FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+ FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+ FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+ FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+ FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+ FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+ FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+ FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+ FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+ FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+ FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+ FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+ FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+ FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+ FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+ FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+ FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+ FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+ FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+ FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+ FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+ FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+ FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+ FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+ FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+ FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+ FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+ FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+ FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+ FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+};
+
+static const char * const axi_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "mmpll_d2",
+ "dmpll_d2"
+};
+
+static const char * const mem_parents[] = {
+ "clk26m",
+ "dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const mm_parents[] = {
+ "clk26m",
+ "vencpll_ck",
+ "syspll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_ck"
+};
+
+static const char * const pwm_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4",
+};
+
+static const char * const vdec_parents[] = {
+ "clk26m",
+ "vdecpll_ck",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "vencpll_ck",
+ "msdcpll_d2",
+ "mmpll_d2"
+};
+
+static const char * const mfg_parents[] = {
+ "clk26m",
+ "mmpll_ck",
+ "dmpll_x2_ck",
+ "msdcpll_ck",
+ "clk26m",
+ "syspll_d3",
+ "univpll_d3",
+ "univpll1_d2"
+};
+
+static const char * const camtg_parents[] = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+ "syspll3_d2",
+ "syspll3_d4",
+ "msdcpll_d2",
+ "mmpll_d2"
+};
+
+static const char * const uart_parents[] = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+ "clk26m",
+ "univpll1_d8",
+ "univpll3_d4"
+};
+
+static const char * const msdc30_parents[] = {
+ "clk26m",
+ "msdcpll_d2",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll2_d4"
+};
+
+static const char * const audio_parents[] = {
+ "clk26m",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll3_d2",
+ "syspll4_d2",
+ "univpll3_d2",
+ "univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "syspll2_d4",
+ "syspll4_d2",
+ "syspll3_d4",
+ "syspll2_d8",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll_d26",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const scp_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const dpi0_parents[] = {
+ "clk26m",
+ "mipipll",
+ "mipipll_d2",
+ "mipipll_d4",
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] = {
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const tve_parents[] = {
+ "clk26m",
+ "mipipll",
+ "mipipll_d2",
+ "mipipll_d4",
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] = {
+ "clk26m",
+ "hdmipll_ck",
+ "hdmipll_d2",
+ "hdmipll_d3"
+};
+
+static const char * const apll_parents[] = {
+ "clk26m",
+ "audpll",
+ "audpll_d4",
+ "audpll_d8",
+ "audpll_d16",
+ "audpll_d24",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const rtc_parents[] = {
+ "32k_internal",
+ "32k_external",
+ "clk26m",
+ "univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] = {
+ "clk26m",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll3_d2",
+ "syspll2_d4",
+ "univpll3_d4",
+ "syspll4_d4",
+ "clk26m"
+};
+
+static const char * const emmc_hclk_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll1_d4",
+ "syspll2_d2"
+};
+
+static const char * const flash_parents[] = {
+ "clk26m_d8",
+ "clk26m",
+ "syspll2_d8",
+ "syspll3_d4",
+ "univpll3_d4",
+ "syspll4_d2",
+ "syspll2_d4",
+ "univpll2_d4"
+};
+
+static const char * const di_parents[] = {
+ "clk26m",
+ "tvd2pll_ck",
+ "tvd2pll_d2",
+ "clk26m"
+};
+
+static const char * const nr_osd_parents[] = {
+ "clk26m",
+ "vencpll_ck",
+ "syspll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] = {
+ "clk26m",
+ "syspll_d3",
+ "clk26m",
+ "syspll1_d16",
+ "syspll4_d2",
+ "syspll1_d4",
+ "vencpll_ck",
+ "clk26m"
+};
+
+static const char * const intdir_parents[] = {
+ "clk26m",
+ "mmpll_ck",
+ "syspll_d2",
+ "univpll_d2"
+};
+
+static const char * const asm_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll2_d2",
+ "syspll_d5"
+};
+
+static const char * const ms_card_parents[] = {
+ "clk26m",
+ "univpll3_d8",
+ "syspll4_d4"
+};
+
+static const char * const ethif_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "dmpll_ck",
+ "dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] = {
+ "clk26m",
+ "univpll_d52"
+};
+
+static const char * const cmsys_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll1_d2",
+ "univpll_d5",
+ "syspll_d5",
+ "syspll2_d2",
+ "syspll1_d4",
+ "syspll3_d2",
+ "syspll2_d4",
+ "syspll1_d8",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const clk_8bdac_parents[] = {
+ "32k_internal",
+ "8bdac_ck",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const aud2dvd_parents[] = {
+ "a1sys_hp_ck",
+ "a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] = {
+ "clk26m",
+ "univpll_d26",
+ "univpll_d52",
+ "univpll_d108",
+ "univpll2_d8",
+ "univpll2_d16",
+ "univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] = {
+ "clk26m",
+ "aud1pll_98m_ck",
+ "aud2pll_90m_ck",
+ "hadds2pll_98m",
+ "audio_ext1_ck",
+ "audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] = {
+ "aud_mux1_sel",
+ "aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] = {
+ "clk26m",
+ "armpll",
+ "mainpll",
+ "mmpll"
+};
+
+static const struct mtk_composite top_muxes[] = {
+ MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+ 0x0040, 0, 3, 7, CLK_IS_CRITICAL),
+ MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+ 0x0040, 8, 1, 15, CLK_IS_CRITICAL),
+ MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel",
+ ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL),
+ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+ 0x0040, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+ 0x0050, 0, 2, 7),
+ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+ 0x0050, 8, 4, 15),
+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+ 0x0050, 16, 3, 23),
+ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+ 0x0050, 24, 3, 31),
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+ 0x0060, 0, 1, 7),
+
+ MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+ 0x0060, 8, 3, 15),
+ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+ 0x0060, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+ 0x0060, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+ 0x0070, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+ 0x0070, 8, 3, 15),
+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+ 0x0070, 16, 1, 23),
+ MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+ 0x0070, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+ 0x0080, 0, 4, 7),
+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+ 0x0080, 8, 2, 15),
+ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+ 0x0080, 16, 3, 23),
+ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+ 0x0080, 24, 2, 31),
+
+ MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+ 0x0090, 0, 3, 7),
+ MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+ 0x0090, 8, 2, 15),
+ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+ 0x0090, 16, 3, 23),
+
+ MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+ 0x00A0, 0, 2, 7, CLK_IS_CRITICAL),
+ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+ 0x00A0, 8, 3, 15),
+ MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+ 0x00A0, 24, 2, 31),
+
+ MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+ 0x00B0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+ 0x00B0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+ 0x00B0, 16, 3, 23),
+ MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+ 0x00B0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+ hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+ 0x00C0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+ 0x00C0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+ 0x00C0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+ 0x00D0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+ 0x00D0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+ 0x00D0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+ 0x00E0, 0, 1, 7),
+ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+ 0x00E0, 8, 3, 15),
+ MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+ 0x00E0, 16, 4, 23),
+
+ MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+ 0x00E0, 24, 3, 31),
+ MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+ 0x00F0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+ 0x00F0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+ 0x00F0, 16, 1, 23),
+
+ MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+ 0x0100, 0, 3),
+
+ MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+ 0x012c, 0, 3),
+ MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+ 0x012c, 3, 3),
+ MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+ 0x012c, 6, 3),
+ MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+ 0x012c, 15, 1, 23),
+ MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+ 0x012c, 16, 1, 24),
+ MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+ 0x012c, 17, 1, 25),
+ MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+ 0x012c, 18, 1, 26),
+ MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+ 0x012c, 19, 1, 27),
+ MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+ 0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+ DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+ 0x0120, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+ 0x0120, 8, 8),
+ DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+ 0x0120, 16, 8),
+ DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+ 0x0120, 24, 8),
+ DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+ 0x0124, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+ 0x0124, 8, 8),
+ DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+ 0x0124, 16, 8),
+ DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+ 0x0124, 24, 8),
+ DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+ 0x0128, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+ 0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs = {
+ .sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top_aud_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate top_clks[] = {
+ GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+ 21),
+ GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+ 22),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+ 23),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+ 24),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+ 25),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+ 26),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+ 27),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+ 28),
+};
+
+static int mtk_topckgen_init(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ struct device_node *node = pdev->dev.of_node;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+
+ mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+ clk_data);
+
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+ base, &mt2701_clk_lock, clk_data);
+
+ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+ base, &mt2701_clk_lock, clk_data);
+
+ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+ clk_data);
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = 0x0040,
+ .clr_ofs = 0x0044,
+ .sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate infra_clks[] = {
+ GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+ GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+ GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+ GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+ GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+ GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+ GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+ GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+ GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+ GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+ GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+ GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+ FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void mtk_infrasys_init_early(struct device_node *node)
+{
+ int r, i;
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+ for (i = 0; i < CLK_INFRA_NR; i++)
+ infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+ }
+
+ mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+ infra_clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt2701-infracfg",
+ mtk_infrasys_init_early);
+
+static int mtk_infrasys_init(struct platform_device *pdev)
+{
+ int r, i;
+ struct device_node *node = pdev->dev.of_node;
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ } else {
+ for (i = 0; i < CLK_INFRA_NR; i++) {
+ if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+ infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+ }
+ }
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+ infra_clk_data);
+ mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+ infra_clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+ if (r)
+ return r;
+
+ mtk_register_reset_controller(node, 2, 0x30);
+
+ return 0;
+}
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x0010,
+ .sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+ .set_ofs = 0x000c,
+ .clr_ofs = 0x0014,
+ .sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate peri_clks[] = {
+ GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+ GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+ GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+ GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+ GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+ GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+ GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+ GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+ GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+ GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+ GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+ GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+ GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+ GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+ GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+ GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+ GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+ GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+ GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+ GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] = {
+ "clk26m",
+ "uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] = {
+ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+ 0x40c, 0, 1),
+ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+ 0x40c, 1, 1),
+ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+ 0x40c, 2, 1),
+ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+ 0x40c, 3, 1),
+};
+
+static int mtk_pericfg_init(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+ struct device_node *node = pdev->dev.of_node;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+ clk_data);
+
+ mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+ &mt2701_clk_lock, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ return r;
+
+ mtk_register_reset_controller(node, 2, 0x0);
+
+ return 0;
+}
+
+#define MT8590_PLL_FMAX (2000 * MHZ)
+#define CON0_MT8590_RST_BAR BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT8590_RST_BAR, \
+ .fmax = MT8590_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ }
+
+static const struct mtk_pll_data apmixed_plls[] = {
+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001,
+ PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+ HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+ HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+ 21, 0x230, 4, 0x0, 0x234, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+ 21, 0x240, 4, 0x0, 0x244, 0),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+ 21, 0x250, 4, 0x0, 0x254, 0),
+ PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+ 31, 0x270, 4, 0x0, 0x274, 0),
+ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+ 31, 0x280, 4, 0x0, 0x284, 0),
+ PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+ 31, 0x290, 4, 0x0, 0x294, 0),
+ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+ 31, 0x2a0, 4, 0x0, 0x2a4, 0),
+ PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+ 31, 0x2b0, 4, 0x0, 0x2b4, 0),
+ PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+ 31, 0x2c0, 4, 0x0, 0x2c4, 0),
+ PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+ 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static int mtk_apmixedsys_init(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+ if (!clk_data)
+ return -ENOMEM;
+
+ mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+ clk_data);
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt2701[] = {
+ {
+ .compatible = "mediatek,mt2701-topckgen",
+ .data = mtk_topckgen_init,
+ }, {
+ .compatible = "mediatek,mt2701-infracfg",
+ .data = mtk_infrasys_init,
+ }, {
+ .compatible = "mediatek,mt2701-pericfg",
+ .data = mtk_pericfg_init,
+ }, {
+ .compatible = "mediatek,mt2701-apmixedsys",
+ .data = mtk_apmixedsys_init,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int clk_mt2701_probe(struct platform_device *pdev)
+{
+ int (*clk_init)(struct platform_device *);
+ int r;
+
+ clk_init = of_device_get_match_data(&pdev->dev);
+ if (!clk_init)
+ return -EINVAL;
+
+ r = clk_init(pdev);
+ if (r)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt2701_drv = {
+ .probe = clk_mt2701_probe,
+ .driver = {
+ .name = "clk-mt2701",
+ .of_match_table = of_match_clk_mt2701,
+ },
+};
+
+static int __init clk_mt2701_init(void)
+{
+ return platform_driver_register(&clk_mt2701_drv);
+}
+
+arch_initcall(clk_mt2701_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index bb30f7063569..0541df78141c 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
for (i = 0; i < num; i++) {
const struct mtk_fixed_clk *rc = &clks[i];
+ if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
+ continue;
+
clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
rc->rate);
@@ -81,6 +84,9 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
for (i = 0; i < num; i++) {
const struct mtk_fixed_factor *ff = &clks[i];
+ if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
+ continue;
+
clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
CLK_SET_RATE_PARENT, ff->mult, ff->div);
@@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device_node *node,
for (i = 0; i < num; i++) {
const struct mtk_gate *gate = &clks[i];
+ if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
+ continue;
+
clk = mtk_clk_register_gate(gate->name, gate->parent_name,
regmap,
gate->regs->set_ofs,
@@ -232,6 +241,9 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
for (i = 0; i < num; i++) {
const struct mtk_composite *mc = &mcs[i];
+ if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
+ continue;
+
clk = mtk_clk_register_composite(mc, base, lock);
if (IS_ERR(clk)) {
@@ -244,3 +256,31 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
clk_data->clks[mc->id] = clk;
}
}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_clk_divider *mcd = &mcds[i];
+
+ if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
+ continue;
+
+ clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+ mcd->flags, base + mcd->div_reg, mcd->div_shift,
+ mcd->div_width, mcd->clk_divider_flags, lock);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ mcd->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[mcd->id] = clk;
+ }
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 9f24fcfa304f..f5d6b70ce189 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -87,7 +87,8 @@ struct mtk_composite {
* In case the rate change propagation to parent clocks is undesirable,
* this macro allows to specify the clock flags manually.
*/
-#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) { \
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
+ _gate, _flags) { \
.id = _id, \
.name = _name, \
.mux_reg = _reg, \
@@ -106,7 +107,8 @@ struct mtk_composite {
* parent clock by default.
*/
#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \
- MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
+ MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
+ _gate, CLK_SET_RATE_PARENT)
#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
.id = _id, \
@@ -121,7 +123,8 @@ struct mtk_composite {
.flags = CLK_SET_RATE_PARENT, \
}
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
+ _div_width, _div_shift) { \
.id = _id, \
.parent = _parent, \
.name = _name, \
@@ -156,12 +159,40 @@ struct mtk_gate {
const struct clk_ops *ops;
};
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
- int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+ const struct mtk_gate *clks, int num,
+ struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+ int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+
+ u32 div_reg;
+ unsigned char div_shift;
+ unsigned char div_width;
+ unsigned char clk_divider_flags;
+ const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .div_reg = _reg, \
+ .div_shift = _shift, \
+ .div_width = _width, \
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data);
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
#define HAVE_RST_BAR BIT(0)
+#define PLL_AO BIT(1)
struct mtk_pll_div_table {
u32 div;
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 0c2deac17ce9..a409142e9346 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
pll->data = data;
init.name = data->name;
+ init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
init.ops = &mtk_pll_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 9adaf48aea23..0fc75c395957 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -309,19 +309,19 @@ static void __init mmp2_clk_init(struct device_node *np)
pxa_unit->mpmu_base = of_iomap(np, 0);
if (!pxa_unit->mpmu_base) {
pr_err("failed to map mpmu registers\n");
- return;
+ goto free_memory;
}
pxa_unit->apmu_base = of_iomap(np, 1);
if (!pxa_unit->apmu_base) {
pr_err("failed to map apmu registers\n");
- return;
+ goto unmap_mpmu_region;
}
pxa_unit->apbc_base = of_iomap(np, 2);
if (!pxa_unit->apbc_base) {
pr_err("failed to map apbc registers\n");
- return;
+ goto unmap_apmu_region;
}
mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
@@ -333,6 +333,15 @@ static void __init mmp2_clk_init(struct device_node *np)
mmp2_axi_periph_clk_init(pxa_unit);
mmp2_clk_reset_init(np, pxa_unit);
+
+ return;
+
+unmap_apmu_region:
+ iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+ iounmap(pxa_unit->mpmu_base);
+free_memory:
+ kfree(pxa_unit);
}
CLK_OF_DECLARE(mmp2_clk, "marvell,mmp2-clock", mmp2_clk_init);
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
index e478ff44e170..cede7b4ca3b9 100644
--- a/drivers/clk/mmp/clk-of-pxa1928.c
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -216,6 +216,7 @@ static void __init pxa1928_mpmu_clk_init(struct device_node *np)
pxa_unit->mpmu_base = of_iomap(np, 0);
if (!pxa_unit->mpmu_base) {
pr_err("failed to map mpmu registers\n");
+ kfree(pxa_unit);
return;
}
@@ -234,6 +235,7 @@ static void __init pxa1928_apmu_clk_init(struct device_node *np)
pxa_unit->apmu_base = of_iomap(np, 0);
if (!pxa_unit->apmu_base) {
pr_err("failed to map apmu registers\n");
+ kfree(pxa_unit);
return;
}
@@ -254,6 +256,7 @@ static void __init pxa1928_apbc_clk_init(struct device_node *np)
pxa_unit->apbc_base = of_iomap(np, 0);
if (!pxa_unit->apbc_base) {
pr_err("failed to map apbc registers\n");
+ kfree(pxa_unit);
return;
}
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 64d1ef49caeb..1dcabe95cb67 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -278,25 +278,25 @@ static void __init pxa910_clk_init(struct device_node *np)
pxa_unit->mpmu_base = of_iomap(np, 0);
if (!pxa_unit->mpmu_base) {
pr_err("failed to map mpmu registers\n");
- return;
+ goto free_memory;
}
pxa_unit->apmu_base = of_iomap(np, 1);
if (!pxa_unit->apmu_base) {
pr_err("failed to map apmu registers\n");
- return;
+ goto unmap_mpmu_region;
}
pxa_unit->apbc_base = of_iomap(np, 2);
if (!pxa_unit->apbc_base) {
pr_err("failed to map apbc registers\n");
- return;
+ goto unmap_apmu_region;
}
pxa_unit->apbcp_base = of_iomap(np, 3);
if (!pxa_unit->apbcp_base) {
pr_err("failed to map apbcp registers\n");
- return;
+ goto unmap_apbc_region;
}
mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS);
@@ -308,6 +308,17 @@ static void __init pxa910_clk_init(struct device_node *np)
pxa910_axi_periph_clk_init(pxa_unit);
pxa910_clk_reset_init(np, pxa_unit);
+
+ return;
+
+unmap_apbc_region:
+ iounmap(pxa_unit->apbc_base);
+unmap_apmu_region:
+ iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+ iounmap(pxa_unit->mpmu_base);
+free_memory:
+ kfree(pxa_unit);
}
CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init);
diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c
index 02023baf86c9..8181b919f062 100644
--- a/drivers/clk/mvebu/ap806-system-controller.c
+++ b/drivers/clk/mvebu/ap806-system-controller.c
@@ -14,7 +14,7 @@
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -135,34 +135,17 @@ fail0:
return ret;
}
-static int ap806_syscon_clk_remove(struct platform_device *pdev)
-{
- of_clk_del_provider(pdev->dev.of_node);
- clk_unregister_fixed_factor(ap806_clks[3]);
- clk_unregister_fixed_rate(ap806_clks[2]);
- clk_unregister_fixed_rate(ap806_clks[1]);
- clk_unregister_fixed_rate(ap806_clks[0]);
-
- return 0;
-}
-
static const struct of_device_id ap806_syscon_of_match[] = {
{ .compatible = "marvell,ap806-system-controller", },
{ }
};
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
static struct platform_driver ap806_syscon_driver = {
.probe = ap806_syscon_clk_probe,
- .remove = ap806_syscon_clk_remove,
.driver = {
.name = "marvell-ap806-system-controller",
.of_match_table = ap806_syscon_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(ap806_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell AP806 System Controller driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(ap806_syscon_driver);
diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c
index f2303da7fda7..32e5b43c086f 100644
--- a/drivers/clk/mvebu/cp110-system-controller.c
+++ b/drivers/clk/mvebu/cp110-system-controller.c
@@ -30,7 +30,7 @@
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -87,7 +87,7 @@ struct cp110_gate_clk {
u8 bit_idx;
};
-#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw)
+#define to_cp110_gate_clk(hw) container_of(hw, struct cp110_gate_clk, hw)
static int cp110_gate_enable(struct clk_hw *hw)
{
@@ -123,13 +123,14 @@ static const struct clk_ops cp110_gate_ops = {
.is_enabled = cp110_gate_is_enabled,
};
-static struct clk *cp110_register_gate(const char *name,
- const char *parent_name,
- struct regmap *regmap, u8 bit_idx)
+static struct clk_hw *cp110_register_gate(const char *name,
+ const char *parent_name,
+ struct regmap *regmap, u8 bit_idx)
{
struct cp110_gate_clk *gate;
- struct clk *clk;
+ struct clk_hw *hw;
struct clk_init_data init;
+ int ret;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
@@ -146,39 +147,37 @@ static struct clk *cp110_register_gate(const char *name,
gate->bit_idx = bit_idx;
gate->hw.init = &init;
- clk = clk_register(NULL, &gate->hw);
- if (IS_ERR(clk))
+ hw = &gate->hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
kfree(gate);
+ hw = ERR_PTR(ret);
+ }
- return clk;
+ return hw;
}
-static void cp110_unregister_gate(struct clk *clk)
+static void cp110_unregister_gate(struct clk_hw *hw)
{
- struct clk_hw *hw;
-
- hw = __clk_get_hw(clk);
- if (!hw)
- return;
-
- clk_unregister(clk);
+ clk_hw_unregister(hw);
kfree(to_cp110_gate_clk(hw));
}
-static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data)
+static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
+ void *data)
{
- struct clk_onecell_data *clk_data = data;
+ struct clk_hw_onecell_data *clk_data = data;
unsigned int type = clkspec->args[0];
unsigned int idx = clkspec->args[1];
if (type == CP110_CLK_TYPE_CORE) {
if (idx > CP110_MAX_CORE_CLOCKS)
return ERR_PTR(-EINVAL);
- return clk_data->clks[idx];
+ return clk_data->hws[idx];
} else if (type == CP110_CLK_TYPE_GATABLE) {
if (idx > CP110_MAX_GATABLE_CLOCKS)
return ERR_PTR(-EINVAL);
- return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx];
+ return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx];
}
return ERR_PTR(-EINVAL);
@@ -189,8 +188,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
struct regmap *regmap;
struct device_node *np = pdev->dev.of_node;
const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
- struct clk_onecell_data *cp110_clk_data;
- struct clk *clk, **cp110_clks;
+ struct clk_hw_onecell_data *cp110_clk_data;
+ struct clk_hw *hw, **cp110_clks;
u32 nand_clk_ctrl;
int i, ret;
@@ -203,80 +202,75 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
if (ret)
return ret;
- cp110_clks = devm_kcalloc(&pdev->dev, sizeof(struct clk *),
- CP110_CLK_NUM, GFP_KERNEL);
- if (!cp110_clks)
- return -ENOMEM;
-
- cp110_clk_data = devm_kzalloc(&pdev->dev,
- sizeof(*cp110_clk_data),
+ cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) +
+ sizeof(struct clk_hw *) * CP110_CLK_NUM,
GFP_KERNEL);
if (!cp110_clk_data)
return -ENOMEM;
- cp110_clk_data->clks = cp110_clks;
- cp110_clk_data->clk_num = CP110_CLK_NUM;
+ cp110_clks = cp110_clk_data->hws;
+ cp110_clk_data->num = CP110_CLK_NUM;
- /* Register the APLL which is the root of the clk tree */
+ /* Register the APLL which is the root of the hw tree */
of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_APLL, &apll_name);
- clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
- 1000 * 1000 * 1000);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
+ 1000 * 1000 * 1000);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail0;
}
- cp110_clks[CP110_CORE_APLL] = clk;
+ cp110_clks[CP110_CORE_APLL] = hw;
/* PPv2 is APLL/3 */
of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_PPV2, &ppv2_name);
- clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail1;
}
- cp110_clks[CP110_CORE_PPV2] = clk;
+ cp110_clks[CP110_CORE_PPV2] = hw;
/* EIP clock is APLL/2 */
of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_EIP, &eip_name);
- clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail2;
}
- cp110_clks[CP110_CORE_EIP] = clk;
+ cp110_clks[CP110_CORE_EIP] = hw;
/* Core clock is EIP/2 */
of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_CORE, &core_name);
- clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail3;
}
- cp110_clks[CP110_CORE_CORE] = clk;
+ cp110_clks[CP110_CORE_CORE] = hw;
/* NAND can be either APLL/2.5 or core clock */
of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_NAND, &nand_name);
if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
- clk = clk_register_fixed_factor(NULL, nand_name,
- apll_name, 0, 2, 5);
+ hw = clk_hw_register_fixed_factor(NULL, nand_name,
+ apll_name, 0, 2, 5);
else
- clk = clk_register_fixed_factor(NULL, nand_name,
- core_name, 0, 1, 1);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = clk_hw_register_fixed_factor(NULL, nand_name,
+ core_name, 0, 1, 1);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail4;
}
- cp110_clks[CP110_CORE_NAND] = clk;
+ cp110_clks[CP110_CORE_NAND] = hw;
for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
const char *parent, *name;
@@ -335,16 +329,16 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
break;
}
- clk = cp110_register_gate(name, parent, regmap, i);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ hw = cp110_register_gate(name, parent, regmap, i);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
goto fail_gate;
}
- cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk;
+ cp110_clks[CP110_MAX_CORE_CLOCKS + i] = hw;
}
- ret = of_clk_add_provider(np, cp110_of_clk_get, cp110_clk_data);
+ ret = of_clk_add_hw_provider(np, cp110_of_clk_get, cp110_clk_data);
if (ret)
goto fail_clk_add;
@@ -355,65 +349,36 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
fail_clk_add:
fail_gate:
for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
- clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
+ hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
- if (clk)
- cp110_unregister_gate(clk);
+ if (hw)
+ cp110_unregister_gate(hw);
}
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
+ clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
fail4:
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
+ clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
fail3:
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+ clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
fail2:
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
+ clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
fail1:
- clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
+ clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
fail0:
return ret;
}
-static int cp110_syscon_clk_remove(struct platform_device *pdev)
-{
- struct clk **cp110_clks = platform_get_drvdata(pdev);
- int i;
-
- of_clk_del_provider(pdev->dev.of_node);
-
- for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
- struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
-
- if (clk)
- cp110_unregister_gate(clk);
- }
-
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
- clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
- clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-
- return 0;
-}
-
static const struct of_device_id cp110_syscon_of_match[] = {
{ .compatible = "marvell,cp110-system-controller0", },
{ }
};
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
static struct platform_driver cp110_syscon_driver = {
.probe = cp110_syscon_clk_probe,
- .remove = cp110_syscon_clk_remove,
.driver = {
.name = "marvell-cp110-system-controller0",
.of_match_table = cp110_syscon_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(cp110_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(cp110_syscon_driver);
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
index f7136b94fd0e..27781b49eb82 100644
--- a/drivers/clk/nxp/clk-lpc18xx-ccu.c
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -277,12 +277,15 @@ static void __init lpc18xx_ccu_init(struct device_node *np)
}
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
- if (!clk_data)
+ if (!clk_data) {
+ iounmap(reg_base);
return;
+ }
clk_data->num = of_property_count_strings(np, "clock-names");
clk_data->name = kcalloc(clk_data->num, sizeof(char *), GFP_KERNEL);
if (!clk_data->name) {
+ iounmap(reg_base);
kfree(clk_data);
return;
}
diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index 34c97353cdeb..5b98ff9076f3 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
- CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+ CLK_DIVIDER_ONE_BASED),
LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
- CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+ CLK_DIVIDER_ONE_BASED),
LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
@@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0),
LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE),
- LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL,
- CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+ LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED),
LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9),
0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops),
LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE),
@@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_register(u32 id)
return clk;
}
+static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate)
+{
+ u32 val;
+
+ regmap_read(clk_regmap, reg, &val);
+
+ if (!(val & div_mask)) {
+ val &= ~gate;
+ val |= BIT(__ffs(div_mask));
+ }
+
+ regmap_update_bits(clk_regmap, reg, gate | div_mask, val);
+}
+
static void __init lpc32xx_clk_init(struct device_node *np)
{
unsigned int i;
@@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(struct device_node *np)
return;
}
+ /*
+ * Divider part of PWM and MS clocks requires a quirk to avoid
+ * a misinterpretation of formally valid zero value in register
+ * bitfield, which indicates another clock gate. Instead of
+ * adding complexity to a gate clock ensure that zero value in
+ * divider clock is never met in runtime.
+ */
+ lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0));
+ lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2));
+ lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9));
+
for (i = 1; i < LPC32XX_CLK_MAX; i++) {
clk[i] = lpc32xx_clk_register(i);
if (IS_ERR(clk[i])) {
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
index 29cee9e8d4d9..74f64c3c4290 100644
--- a/drivers/clk/pxa/clk-pxa.c
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -18,7 +18,27 @@
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
-DEFINE_SPINLOCK(lock);
+#define KHz 1000
+#define MHz (1000 * 1000)
+
+#define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */
+#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */
+#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */
+#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */
+#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2)
+#define MDREFR_DRI_MASK 0xFFF
+
+static DEFINE_SPINLOCK(pxa_clk_lock);
static struct clk *pxa_clocks[CLK_MAX];
static struct clk_onecell_data onecell_data = {
@@ -89,7 +109,7 @@ int __init clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks)
pxa_clk->lp = clks[i].lp;
pxa_clk->hp = clks[i].hp;
pxa_clk->gate = clks[i].gate;
- pxa_clk->gate.lock = &lock;
+ pxa_clk->gate.lock = &pxa_clk_lock;
clk = clk_register_composite(NULL, clks[i].name,
clks[i].parent_names, 2,
&pxa_clk->hw, &cken_mux_ops,
@@ -106,3 +126,124 @@ void __init clk_pxa_dt_common_init(struct device_node *np)
{
of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
}
+
+void pxa2xx_core_turbo_switch(bool on)
+{
+ unsigned long flags;
+ unsigned int unused, clkcfg;
+
+ local_irq_save(flags);
+
+ asm("mrc p14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
+ clkcfg &= ~CLKCFG_TURBO & ~CLKCFG_HALFTURBO;
+ if (on)
+ clkcfg |= CLKCFG_TURBO;
+ clkcfg |= CLKCFG_FCS;
+
+ asm volatile(
+ " b 2f\n"
+ " .align 5\n"
+ "1: mcr p14, 0, %1, c6, c0, 0\n"
+ " b 3f\n"
+ "2: b 1b\n"
+ "3: nop\n"
+ : "=&r" (unused)
+ : "r" (clkcfg)
+ : );
+
+ local_irq_restore(flags);
+}
+
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+ u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+ void __iomem *cccr)
+{
+ unsigned int clkcfg = freq->clkcfg;
+ unsigned int unused, preset_mdrefr, postset_mdrefr;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* Calculate the next MDREFR. If we're slowing down the SDRAM clock
+ * we need to preset the smaller DRI before the change. If we're
+ * speeding up we need to set the larger DRI value after the change.
+ */
+ preset_mdrefr = postset_mdrefr = readl(mdrefr);
+ if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(freq->membus_khz)) {
+ preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
+ preset_mdrefr |= mdrefr_dri(freq->membus_khz);
+ }
+ postset_mdrefr =
+ (postset_mdrefr & ~MDREFR_DRI_MASK) |
+ mdrefr_dri(freq->membus_khz);
+
+ /* If we're dividing the memory clock by two for the SDRAM clock, this
+ * must be set prior to the change. Clearing the divide must be done
+ * after the change.
+ */
+ if (freq->div2) {
+ preset_mdrefr |= MDREFR_DB2_MASK;
+ postset_mdrefr |= MDREFR_DB2_MASK;
+ } else {
+ postset_mdrefr &= ~MDREFR_DB2_MASK;
+ }
+
+ /* Set new the CCCR and prepare CLKCFG */
+ writel(freq->cccr, cccr);
+
+ asm volatile(
+ " ldr r4, [%1]\n"
+ " b 2f\n"
+ " .align 5\n"
+ "1: str %3, [%1] /* preset the MDREFR */\n"
+ " mcr p14, 0, %2, c6, c0, 0 /* set CLKCFG[FCS] */\n"
+ " str %4, [%1] /* postset the MDREFR */\n"
+ " b 3f\n"
+ "2: b 1b\n"
+ "3: nop\n"
+ : "=&r" (unused)
+ : "r" (mdrefr), "r" (clkcfg), "r" (preset_mdrefr),
+ "r" (postset_mdrefr)
+ : "r4", "r5");
+
+ local_irq_restore(flags);
+}
+
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+ struct pxa2xx_freq *freqs, int nb_freqs)
+{
+ int i, closest_below = -1, closest_above = -1;
+ unsigned long rate;
+
+ for (i = 0; i < nb_freqs; i++) {
+ rate = freqs[i].cpll;
+ if (rate == req->rate)
+ break;
+ if (rate < req->min_rate)
+ continue;
+ if (rate > req->max_rate)
+ continue;
+ if (rate <= req->rate)
+ closest_below = i;
+ if ((rate >= req->rate) && (closest_above == -1))
+ closest_above = i;
+ }
+
+ req->best_parent_hw = NULL;
+
+ if (i < nb_freqs) {
+ rate = req->rate;
+ } else if (closest_below >= 0) {
+ rate = freqs[closest_below].cpll;
+ } else if (closest_above >= 0) {
+ rate = freqs[closest_above].cpll;
+ } else {
+ pr_debug("%s(rate=%lu) no match\n", __func__, req->rate);
+ return -EINVAL;
+ }
+
+ pr_debug("%s(rate=%lu) rate=%lu\n", __func__, req->rate, rate);
+ req->rate = rate;
+
+ return 0;
+}
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
index d1de805df867..2b90c5917b32 100644
--- a/drivers/clk/pxa/clk-pxa.h
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -13,6 +13,11 @@
#ifndef _CLK_PXA_
#define _CLK_PXA_
+#define CLKCFG_TURBO 0x1
+#define CLKCFG_FCS 0x2
+#define CLKCFG_HALFTURBO 0x4
+#define CLKCFG_FASTBUS 0x8
+
#define PARENTS(name) \
static const char *const name ## _parents[] __initconst
#define MUX_RO_RATE_RO_OPS(name, clk_name) \
@@ -35,10 +40,27 @@
NULL, NULL, CLK_GET_RATE_NOCACHE); \
}
-#define RATE_RO_OPS(name, clk_name) \
+#define RATE_RO_OPS(name, clk_name) \
+ static struct clk_hw name ## _rate_hw; \
+ static const struct clk_ops name ## _rate_ops = { \
+ .recalc_rate = name ## _get_rate, \
+ }; \
+ static struct clk * __init clk_register_ ## name(void) \
+ { \
+ return clk_register_composite(NULL, clk_name, \
+ name ## _parents, \
+ ARRAY_SIZE(name ## _parents), \
+ NULL, NULL, \
+ &name ## _rate_hw, &name ## _rate_ops, \
+ NULL, NULL, CLK_GET_RATE_NOCACHE); \
+ }
+
+#define RATE_OPS(name, clk_name) \
static struct clk_hw name ## _rate_hw; \
static struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
+ .set_rate = name ## _set_rate, \
+ .determine_rate = name ## _determine_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
{ \
@@ -50,6 +72,24 @@
NULL, NULL, CLK_GET_RATE_NOCACHE); \
}
+#define MUX_OPS(name, clk_name, flags) \
+ static struct clk_hw name ## _mux_hw; \
+ static const struct clk_ops name ## _mux_ops = { \
+ .get_parent = name ## _get_parent, \
+ .set_parent = name ## _set_parent, \
+ .determine_rate = name ## _determine_rate, \
+ }; \
+ static struct clk * __init clk_register_ ## name(void) \
+ { \
+ return clk_register_composite(NULL, clk_name, \
+ name ## _parents, \
+ ARRAY_SIZE(name ## _parents), \
+ &name ## _mux_hw, &name ## _mux_ops, \
+ NULL, NULL, \
+ NULL, NULL, \
+ CLK_GET_RATE_NOCACHE | flags); \
+ }
+
/*
* CKEN clock type
* This clock takes it source from 2 possible parents :
@@ -95,7 +135,15 @@ struct desc_clk_cken {
PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \
NULL, cken_reg, cken_bit, flag)
-static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
+struct pxa2xx_freq {
+ unsigned long cpll;
+ unsigned int membus_khz;
+ unsigned int cccr;
+ unsigned int div2;
+ unsigned int clkcfg;
+};
+
+static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
{
return 0;
}
@@ -105,4 +153,11 @@ extern void clkdev_pxa_register(int ckid, const char *con_id,
extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks);
void clk_pxa_dt_common_init(struct device_node *np);
+void pxa2xx_core_turbo_switch(bool on);
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+ u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+ void __iomem *cccr);
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+ struct pxa2xx_freq *freqs, int nb_freqs);
+
#endif
diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c
index a98b98e2a9e4..c53993b6bf87 100644
--- a/drivers/clk/pxa/clk-pxa25x.c
+++ b/drivers/clk/pxa/clk-pxa25x.c
@@ -18,6 +18,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <mach/pxa2xx-regs.h>
+#include <mach/smemc.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
@@ -30,6 +31,17 @@ enum {
PXA_CORE_TURBO,
};
+#define PXA25x_CLKCFG(T) \
+ (CLKCFG_FCS | \
+ ((T) ? CLKCFG_TURBO : 0))
+#define PXA25x_CCCR(N2, M, L) (N2 << 7 | M << 5 | L)
+
+#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF 64 /* standard 64ms SDRAM */
+
/*
* Various clock factors driven by the CCCR register.
*/
@@ -48,6 +60,34 @@ static const char * const get_freq_khz[] = {
"core", "run", "cpll", "memory"
};
+static int get_sdram_rows(void)
+{
+ static int sdram_rows;
+ unsigned int drac2 = 0, drac0 = 0;
+ u32 mdcnfg;
+
+ if (sdram_rows)
+ return sdram_rows;
+
+ mdcnfg = readl_relaxed(MDCNFG);
+
+ if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+ drac2 = MDCNFG_DRAC2(mdcnfg);
+
+ if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+ drac0 = MDCNFG_DRAC0(mdcnfg);
+
+ sdram_rows = 1 << (11 + max(drac0, drac2));
+ return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+ u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+ return interval / 32;
+}
+
/*
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.
@@ -139,6 +179,21 @@ static struct desc_clk_cken pxa25x_clocks[] __initdata = {
clk_pxa25x_memory_parents, 0),
};
+/*
+ * In this table, PXA25x_CCCR(N2, M, L) has the following meaning, where :
+ * - freq_cpll = n * m * L * 3.6864 MHz
+ * - n = N2 / 2
+ * - m = 2^(M - 1), where 1 <= M <= 3
+ * - l = L_clk_mult[L], ie. { 0, 27, 32, 36, 40, 45, 0, }[L]
+ */
+static struct pxa2xx_freq pxa25x_freqs[] = {
+ /* CPU MEMBUS CCCR DIV2 CCLKCFG */
+ { 99532800, 99500, PXA25x_CCCR(2, 1, 1), 1, PXA25x_CLKCFG(1)},
+ {199065600, 99500, PXA25x_CCCR(4, 1, 1), 0, PXA25x_CLKCFG(1)},
+ {298598400, 99500, PXA25x_CCCR(3, 2, 1), 0, PXA25x_CLKCFG(1)},
+ {398131200, 99500, PXA25x_CCCR(4, 2, 1), 0, PXA25x_CLKCFG(1)},
+};
+
static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
{
unsigned long clkcfg;
@@ -151,13 +206,24 @@ static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
return PXA_CORE_RUN;
}
-static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static int clk_pxa25x_core_set_parent(struct clk_hw *hw, u8 index)
{
- return parent_rate;
+ if (index > PXA_CORE_TURBO)
+ return -EINVAL;
+
+ pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+ return 0;
+}
+
+static int clk_pxa25x_core_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return __clk_mux_determine_rate(hw, req);
}
+
PARENTS(clk_pxa25x_core) = { "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core");
+MUX_OPS(clk_pxa25x_core, "core", CLK_SET_RATE_PARENT);
static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -182,17 +248,42 @@ static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw,
m = M_clk_mult[(cccr >> 5) & 0x03];
n2 = N2_clk_mult[(cccr >> 7) & 0x07];
- if (t)
- return m * l * n2 * parent_rate / 2;
- return m * l * parent_rate;
+ return m * l * n2 * parent_rate / 2;
+}
+
+static int clk_pxa25x_cpll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return pxa2xx_determine_rate(req, pxa25x_freqs,
+ ARRAY_SIZE(pxa25x_freqs));
+}
+
+static int clk_pxa25x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int i;
+
+ pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+ for (i = 0; i < ARRAY_SIZE(pxa25x_freqs); i++)
+ if (pxa25x_freqs[i].cpll == rate)
+ break;
+
+ if (i >= ARRAY_SIZE(pxa25x_freqs))
+ return -EINVAL;
+
+ pxa2xx_cpll_change(&pxa25x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+
+ return 0;
}
PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" };
-RATE_RO_OPS(clk_pxa25x_cpll, "cpll");
+RATE_OPS(clk_pxa25x_cpll, "cpll");
static void __init pxa25x_register_core(void)
{
- clk_register_clk_pxa25x_cpll();
- clk_register_clk_pxa25x_run();
+ clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+ clk_register_clk_pxa25x_cpll());
+ clkdev_pxa_register(CLK_NONE, "run", NULL,
+ clk_register_clk_pxa25x_run());
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa25x_core());
}
@@ -214,7 +305,8 @@ static void __init pxa25x_base_clocks_init(void)
{
pxa25x_register_plls();
pxa25x_register_core();
- clk_register_clk_pxa25x_memory();
+ clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+ clk_register_clk_pxa25x_memory());
}
#define DUMMY_CLK(_con_id, _dev_id, _parent) \
diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c
index c40b1804f58c..25a30194d27a 100644
--- a/drivers/clk/pxa/clk-pxa27x.c
+++ b/drivers/clk/pxa/clk-pxa27x.c
@@ -17,6 +17,8 @@
#include <linux/clkdev.h>
#include <linux/of.h>
+#include <mach/smemc.h>
+
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
@@ -45,11 +47,52 @@ enum {
PXA_MEM_RUN,
};
+#define PXA27x_CLKCFG(B, HT, T) \
+ (CLKCFG_FCS | \
+ ((B) ? CLKCFG_FASTBUS : 0) | \
+ ((HT) ? CLKCFG_HALFTURBO : 0) | \
+ ((T) ? CLKCFG_TURBO : 0))
+#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
+
+#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF 64 /* standard 64ms SDRAM */
+
static const char * const get_freq_khz[] = {
"core", "run", "cpll", "memory",
"system_bus"
};
+static int get_sdram_rows(void)
+{
+ static int sdram_rows;
+ unsigned int drac2 = 0, drac0 = 0;
+ u32 mdcnfg;
+
+ if (sdram_rows)
+ return sdram_rows;
+
+ mdcnfg = readl_relaxed(MDCNFG);
+
+ if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+ drac2 = MDCNFG_DRAC2(mdcnfg);
+
+ if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+ drac0 = MDCNFG_DRAC0(mdcnfg);
+
+ sdram_rows = 1 << (11 + max(drac0, drac2));
+ return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+ u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+ return (interval - 31) / 32;
+}
+
/*
* Get the clock frequency as reflected by CCSR and the turbo flag.
* We assume these values have been applied via a fcs.
@@ -145,6 +188,42 @@ static struct desc_clk_cken pxa27x_clocks[] __initdata = {
};
+/*
+ * PXA270 definitions
+ *
+ * For the PXA27x:
+ * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
+ *
+ * A = 0 => memory controller clock from table 3-7,
+ * A = 1 => memory controller clock = system bus clock
+ * Run mode frequency = 13 MHz * L
+ * Turbo mode frequency = 13 MHz * L * N
+ * System bus frequency = 13 MHz * L / (B + 1)
+ *
+ * In CCCR:
+ * A = 1
+ * L = 16 oscillator to run mode ratio
+ * 2N = 6 2 * (turbo mode to run mode ratio)
+ *
+ * In CCLKCFG:
+ * B = 1 Fast bus mode
+ * HT = 0 Half-Turbo mode
+ * T = 1 Turbo mode
+ *
+ * For now, just support some of the combinations in table 3-7 of
+ * PXA27x Processor Family Developer's Manual to simplify frequency
+ * change sequences.
+ */
+static struct pxa2xx_freq pxa27x_freqs[] = {
+ {104000000, 104000, PXA27x_CCCR(1, 8, 2), 0, PXA27x_CLKCFG(1, 0, 1) },
+ {156000000, 104000, PXA27x_CCCR(1, 8, 3), 0, PXA27x_CLKCFG(1, 0, 1) },
+ {208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) },
+ {312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) },
+ {416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) },
+ {520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) },
+ {624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) },
+};
+
static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -162,10 +241,35 @@ static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
L = l * parent_rate;
N = (L * n2) / 2;
- return t ? N : L;
+ return N;
+}
+
+static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return pxa2xx_determine_rate(req, pxa27x_freqs,
+ ARRAY_SIZE(pxa27x_freqs));
+}
+
+static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int i;
+
+ pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+ for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++)
+ if (pxa27x_freqs[i].cpll == rate)
+ break;
+
+ if (i >= ARRAY_SIZE(pxa27x_freqs))
+ return -EINVAL;
+
+ pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+ return 0;
}
+
PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
-RATE_RO_OPS(clk_pxa27x_cpll, "cpll");
+RATE_OPS(clk_pxa27x_cpll, "cpll");
static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -217,31 +321,10 @@ static void __init pxa27x_register_plls(void)
clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
}
-static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- unsigned long clkcfg;
- unsigned int t, ht, b, osc_forced;
- unsigned long ccsr = readl(CCSR);
-
- osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
- asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
- t = clkcfg & (1 << 0);
- ht = clkcfg & (1 << 2);
- b = clkcfg & (1 << 3);
-
- if (osc_forced)
- return parent_rate;
- if (ht)
- return parent_rate / 2;
- else
- return parent_rate;
-}
-
static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
{
unsigned long clkcfg;
- unsigned int t, ht, b, osc_forced;
+ unsigned int t, ht, osc_forced;
unsigned long ccsr = readl(CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
@@ -251,14 +334,30 @@ static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
ht = clkcfg & (1 << 2);
- b = clkcfg & (1 << 3);
if (ht || t)
return PXA_CORE_TURBO;
return PXA_CORE_RUN;
}
+
+static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index)
+{
+ if (index > PXA_CORE_TURBO)
+ return -EINVAL;
+
+ pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+ return 0;
+}
+
+static int clk_pxa27x_core_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return __clk_mux_determine_rate(hw, req);
+}
+
PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core");
+MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT);
static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -273,9 +372,10 @@ RATE_RO_OPS(clk_pxa27x_run, "run");
static void __init pxa27x_register_core(void)
{
- clk_register_clk_pxa27x_cpll();
- clk_register_clk_pxa27x_run();
-
+ clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+ clk_register_clk_pxa27x_cpll());
+ clkdev_pxa_register(CLK_NONE, "run", NULL,
+ clk_register_clk_pxa27x_run());
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa27x_core());
}
@@ -294,9 +394,9 @@ static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
if (osc_forced)
return parent_rate;
if (b)
- return parent_rate / 2;
- else
return parent_rate;
+ else
+ return parent_rate / 2;
}
static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
@@ -385,8 +485,10 @@ static void __init pxa27x_base_clocks_init(void)
{
pxa27x_register_plls();
pxa27x_register_core();
- clk_register_clk_pxa27x_system_bus();
- clk_register_clk_pxa27x_memory();
+ clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+ clk_register_clk_pxa27x_system_bus());
+ clkdev_pxa_register(CLK_NONE, "memory", NULL,
+ clk_register_clk_pxa27x_memory());
clk_register_clk_pxa27x_lcd_base();
}
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 0146d3c2547f..5fb8d7430908 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -2,6 +2,9 @@ config QCOM_GDSC
bool
select PM_GENERIC_DOMAINS if PM
+config QCOM_RPMCC
+ bool
+
config COMMON_CLK_QCOM
tristate "Support for Qualcomm's clock controllers"
depends on OF
@@ -9,6 +12,32 @@ config COMMON_CLK_QCOM
select REGMAP_MMIO
select RESET_CONTROLLER
+config QCOM_CLK_RPM
+ tristate "RPM based Clock Controller"
+ depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
+ select QCOM_RPMCC
+ help
+ The RPM (Resource Power Manager) is a dedicated hardware engine for
+ managing the shared SoC resources in order to keep the lowest power
+ profile. It communicates with other hardware subsystems via shared
+ memory and accepts clock requests, aggregates the requests and turns
+ the clocks on/off or scales them on demand.
+ Say Y if you want to support the clocks exposed by the RPM on
+ platforms such as apq8064, msm8660, msm8960 etc.
+
+config QCOM_CLK_SMD_RPM
+ tristate "RPM over SMD based Clock Controller"
+ depends on COMMON_CLK_QCOM && QCOM_SMD_RPM
+ select QCOM_RPMCC
+ help
+ The RPM (Resource Power Manager) is a dedicated hardware engine for
+ managing the shared SoC resources in order to keep the lowest power
+ profile. It communicates with other hardware subsystems via shared
+ memory and accepts clock requests, aggregates the requests and turns
+ the clocks on/off or scales them on demand.
+ Say Y if you want to support the clocks exposed by the RPM on
+ platforms such as apq8016, apq8084, msm8974 etc.
+
config APQ_GCC_8084
tristate "APQ8084 Global Clock Controller"
select QCOM_GDSC
@@ -132,6 +161,14 @@ config MSM_MMCC_8974
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
+config MSM_GCC_8994
+ tristate "MSM8994 Global Clock Controller"
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on msm8994 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2c, USB, UFS, SD/eMMC, PCIe, etc.
+
config MSM_GCC_8996
tristate "MSM8996 Global Clock Controller"
select QCOM_GDSC
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 1fb1f5476cb0..1c3e222b917b 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -24,8 +24,11 @@ obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
+obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
+obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e6a03eaf7a93..47a1da3739ce 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -18,17 +18,21 @@
#include <linux/delay.h>
#include "clk-alpha-pll.h"
+#include "common.h"
#define PLL_MODE 0x00
# define PLL_OUTCTRL BIT(0)
# define PLL_BYPASSNL BIT(1)
# define PLL_RESET_N BIT(2)
+# define PLL_OFFLINE_REQ BIT(7)
# define PLL_LOCK_COUNT_SHIFT 8
# define PLL_LOCK_COUNT_MASK 0x3f
# define PLL_BIAS_COUNT_SHIFT 14
# define PLL_BIAS_COUNT_MASK 0x3f
# define PLL_VOTE_FSM_ENA BIT(20)
+# define PLL_FSM_ENA BIT(20)
# define PLL_VOTE_FSM_RESET BIT(21)
+# define PLL_OFFLINE_ACK BIT(28)
# define PLL_ACTIVE_FLAG BIT(30)
# define PLL_LOCK_DET BIT(31)
@@ -46,6 +50,7 @@
#define PLL_USER_CTL_U 0x14
#define PLL_CONFIG_CTL 0x18
+#define PLL_CONFIG_CTL_U 0x20
#define PLL_TEST_CTL 0x1c
#define PLL_TEST_CTL_U 0x20
#define PLL_STATUS 0x24
@@ -55,6 +60,7 @@
*/
#define ALPHA_REG_BITWIDTH 40
#define ALPHA_BITWIDTH 32
+#define ALPHA_16BIT_MASK 0xffff
#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
struct clk_alpha_pll, clkr)
@@ -62,9 +68,10 @@
#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
struct clk_alpha_pll_postdiv, clkr)
-static int wait_for_pll(struct clk_alpha_pll *pll)
+static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
+ const char *action)
{
- u32 val, mask, off;
+ u32 val, off;
int count;
int ret;
const char *name = clk_hw_get_name(&pll->clkr.hw);
@@ -74,26 +81,148 @@ static int wait_for_pll(struct clk_alpha_pll *pll)
if (ret)
return ret;
- if (val & PLL_VOTE_FSM_ENA)
- mask = PLL_ACTIVE_FLAG;
- else
- mask = PLL_LOCK_DET;
-
- /* Wait for pll to enable. */
for (count = 100; count > 0; count--) {
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
if (ret)
return ret;
- if ((val & mask) == mask)
+ if (inverse && !(val & mask))
+ return 0;
+ else if ((val & mask) == mask)
return 0;
udelay(1);
}
- WARN(1, "%s didn't enable after voting for it!\n", name);
+ WARN(1, "%s failed to %s!\n", name, action);
return -ETIMEDOUT;
}
+#define wait_for_pll_enable_active(pll) \
+ wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable")
+
+#define wait_for_pll_enable_lock(pll) \
+ wait_for_pll(pll, PLL_LOCK_DET, 0, "enable")
+
+#define wait_for_pll_disable(pll) \
+ wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable")
+
+#define wait_for_pll_offline(pll) \
+ wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline")
+
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+ const struct alpha_pll_config *config)
+{
+ u32 val, mask;
+ u32 off = pll->offset;
+
+ regmap_write(regmap, off + PLL_L_VAL, config->l);
+ regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
+ regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
+ regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val);
+
+ val = config->main_output_mask;
+ val |= config->aux_output_mask;
+ val |= config->aux2_output_mask;
+ val |= config->early_output_mask;
+ val |= config->pre_div_val;
+ val |= config->post_div_val;
+ val |= config->vco_val;
+
+ mask = config->main_output_mask;
+ mask |= config->aux_output_mask;
+ mask |= config->aux2_output_mask;
+ mask |= config->early_output_mask;
+ mask |= config->pre_div_mask;
+ mask |= config->post_div_mask;
+ mask |= config->vco_mask;
+
+ regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val);
+
+ if (pll->flags & SUPPORTS_FSM_MODE)
+ qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0);
+}
+
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+{
+ int ret;
+ u32 val, off;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+ off = pll->offset;
+ ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+ if (ret)
+ return ret;
+
+ val |= PLL_FSM_ENA;
+
+ if (pll->flags & SUPPORTS_OFFLINE_REQ)
+ val &= ~PLL_OFFLINE_REQ;
+
+ ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
+ if (ret)
+ return ret;
+
+ /* Make sure enable request goes through before waiting for update */
+ mb();
+
+ return wait_for_pll_enable_active(pll);
+}
+
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+{
+ int ret;
+ u32 val, off;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+ off = pll->offset;
+ ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+ if (ret)
+ return;
+
+ if (pll->flags & SUPPORTS_OFFLINE_REQ) {
+ ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+ PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
+ if (ret)
+ return;
+
+ ret = wait_for_pll_offline(pll);
+ if (ret)
+ return;
+ }
+
+ /* Disable hwfsm */
+ ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+ PLL_FSM_ENA, 0);
+ if (ret)
+ return;
+
+ wait_for_pll_disable(pll);
+}
+
+static int pll_is_enabled(struct clk_hw *hw, u32 mask)
+{
+ int ret;
+ u32 val, off;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+ off = pll->offset;
+ ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+ if (ret)
+ return ret;
+
+ return !!(val & mask);
+}
+
+static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
+{
+ return pll_is_enabled(hw, PLL_ACTIVE_FLAG);
+}
+
+static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
+{
+ return pll_is_enabled(hw, PLL_LOCK_DET);
+}
+
static int clk_alpha_pll_enable(struct clk_hw *hw)
{
int ret;
@@ -112,7 +241,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
ret = clk_enable_regmap(hw);
if (ret)
return ret;
- return wait_for_pll(pll);
+ return wait_for_pll_enable_active(pll);
}
/* Skip if already enabled */
@@ -136,7 +265,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
if (ret)
return ret;
- ret = wait_for_pll(pll);
+ ret = wait_for_pll_enable_lock(pll);
if (ret)
return ret;
@@ -234,9 +363,14 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
if (ctl & PLL_ALPHA_EN) {
regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
- regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
- a = (u64)high << 32 | low;
- a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+ if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+ a = low & ALPHA_16BIT_MASK;
+ } else {
+ regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U,
+ &high);
+ a = (u64)high << 32 | low;
+ a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+ }
}
return alpha_pll_calc_rate(prate, l, a);
@@ -257,11 +391,15 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
}
- a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
-
regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
- regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
- regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+
+ if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+ regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL,
+ a & ALPHA_16BIT_MASK);
+ } else {
+ a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+ regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+ }
regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
PLL_VCO_MASK << PLL_VCO_SHIFT,
@@ -294,12 +432,23 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
+ .is_enabled = clk_alpha_pll_is_enabled,
.recalc_rate = clk_alpha_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
.set_rate = clk_alpha_pll_set_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
+const struct clk_ops clk_alpha_pll_hwfsm_ops = {
+ .enable = clk_alpha_pll_hwfsm_enable,
+ .disable = clk_alpha_pll_hwfsm_disable,
+ .is_enabled = clk_alpha_pll_hwfsm_is_enabled,
+ .recalc_rate = clk_alpha_pll_recalc_rate,
+ .round_rate = clk_alpha_pll_round_rate,
+ .set_rate = clk_alpha_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
+
static unsigned long
clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 90ce2016e1a0..d6e1ee2c7348 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -34,6 +34,10 @@ struct clk_alpha_pll {
const struct pll_vco *vco_table;
size_t num_vco;
+#define SUPPORTS_OFFLINE_REQ BIT(0)
+#define SUPPORTS_16BIT_ALPHA BIT(1)
+#define SUPPORTS_FSM_MODE BIT(2)
+ u8 flags;
struct clk_regmap clkr;
};
@@ -51,7 +55,28 @@ struct clk_alpha_pll_postdiv {
struct clk_regmap clkr;
};
+struct alpha_pll_config {
+ u32 l;
+ u32 alpha;
+ u32 config_ctl_val;
+ u32 config_ctl_hi_val;
+ u32 main_output_mask;
+ u32 aux_output_mask;
+ u32 aux2_output_mask;
+ u32 early_output_mask;
+ u32 pre_div_val;
+ u32 pre_div_mask;
+ u32 post_div_val;
+ u32 post_div_mask;
+ u32 vco_val;
+ u32 vco_mask;
+};
+
extern const struct clk_ops clk_alpha_pll_ops;
+extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ops;
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+ const struct alpha_pll_config *config);
+
#endif
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 5b940d629045..cb6cb8710daf 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -23,16 +23,11 @@
#include <asm/div64.h>
#include "clk-pll.h"
+#include "common.h"
#define PLL_OUTCTRL BIT(0)
#define PLL_BYPASSNL BIT(1)
#define PLL_RESET_N BIT(2)
-#define PLL_LOCK_COUNT_SHIFT 8
-#define PLL_LOCK_COUNT_MASK 0x3f
-#define PLL_BIAS_COUNT_SHIFT 14
-#define PLL_BIAS_COUNT_MASK 0x3f
-#define PLL_VOTE_FSM_ENA BIT(20)
-#define PLL_VOTE_FSM_RESET BIT(21)
static int clk_pll_enable(struct clk_hw *hw)
{
@@ -228,26 +223,6 @@ const struct clk_ops clk_pll_vote_ops = {
};
EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
-static void
-clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
-{
- u32 val;
- u32 mask;
-
- /* De-assert reset to FSM */
- regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
-
- /* Program bias count and lock count */
- val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT;
- mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
- mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
- regmap_update_bits(regmap, pll->mode_reg, mask, val);
-
- /* Enable PLL FSM voting */
- regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_ENA,
- PLL_VOTE_FSM_ENA);
-}
-
static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config)
{
@@ -280,7 +255,7 @@ void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
{
clk_pll_configure(pll, regmap, config);
if (fsm_mode)
- clk_pll_set_fsm_mode(pll, regmap, 8);
+ qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8);
}
EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
@@ -289,7 +264,7 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
{
clk_pll_configure(pll, regmap, config);
if (fsm_mode)
- clk_pll_set_fsm_mode(pll, regmap, 0);
+ qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0);
}
EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index b904c335cda4..1b3e8d265bdb 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -173,6 +173,7 @@ struct clk_rcg2 {
#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_floor_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;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index a071bba8018c..1a0985ae20d2 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -47,6 +47,11 @@
#define N_REG 0xc
#define D_REG 0x10
+enum freq_policy {
+ FLOOR,
+ CEIL,
+};
+
static int clk_rcg2_is_enabled(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -176,15 +181,26 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return calc_rate(parent_rate, m, n, mode, hid_div);
}
-static int _freq_tbl_determine_rate(struct clk_hw *hw,
- const struct freq_tbl *f, struct clk_rate_request *req)
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+ struct clk_rate_request *req,
+ enum freq_policy policy)
{
unsigned long clk_flags, rate = req->rate;
struct clk_hw *p;
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
int index;
- f = qcom_find_freq(f, rate);
+ switch (policy) {
+ case FLOOR:
+ f = qcom_find_freq_floor(f, rate);
+ break;
+ case CEIL:
+ f = qcom_find_freq(f, rate);
+ break;
+ default:
+ return -EINVAL;
+ };
+
if (!f)
return -EINVAL;
@@ -221,7 +237,15 @@ static int clk_rcg2_determine_rate(struct clk_hw *hw,
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, CEIL);
+}
+
+static int clk_rcg2_determine_floor_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR);
}
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -265,12 +289,23 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
return update_config(rcg);
}
-static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+ enum freq_policy policy)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const struct freq_tbl *f;
- f = qcom_find_freq(rcg->freq_tbl, rate);
+ switch (policy) {
+ case FLOOR:
+ f = qcom_find_freq_floor(rcg->freq_tbl, rate);
+ break;
+ case CEIL:
+ f = qcom_find_freq(rcg->freq_tbl, rate);
+ break;
+ default:
+ return -EINVAL;
+ };
+
if (!f)
return -EINVAL;
@@ -280,13 +315,25 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- return __clk_rcg2_set_rate(hw, rate);
+ return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return __clk_rcg2_set_rate(hw, rate, FLOOR);
}
static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate, u8 index)
{
- return __clk_rcg2_set_rate(hw, rate);
+ return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ return __clk_rcg2_set_rate(hw, rate, FLOOR);
}
const struct clk_ops clk_rcg2_ops = {
@@ -300,6 +347,17 @@ const struct clk_ops clk_rcg2_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
+const struct clk_ops clk_rcg2_floor_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,
+ .determine_rate = clk_rcg2_determine_floor_rate,
+ .set_rate = clk_rcg2_set_floor_rate,
+ .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+
static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -323,7 +381,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
pr_err("%s: RCG did not turn on\n", name);
/* set clock rate */
- ret = __clk_rcg2_set_rate(hw, rate);
+ ret = __clk_rcg2_set_rate(hw, rate, CEIL);
if (ret)
return ret;
diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c
new file mode 100644
index 000000000000..df3e5fe8442a
--- /dev/null
+++ b/drivers/clk/qcom/clk-rpm.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, 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
+ * 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-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+
+#define QCOM_RPM_MISC_CLK_TYPE 0x306b6c63
+#define QCOM_RPM_SCALING_ENABLE_ID 0x2
+
+#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \
+ static struct clk_rpm _platform##_##_active; \
+ static struct clk_rpm _platform##_##_name = { \
+ .rpm_clk_id = (r_id), \
+ .peer = &_platform##_##_active, \
+ .rate = INT_MAX, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "pxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }; \
+ static struct clk_rpm _platform##_##_active = { \
+ .rpm_clk_id = (r_id), \
+ .peer = &_platform##_##_name, \
+ .active_only = true, \
+ .rate = INT_MAX, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_ops, \
+ .name = #_active, \
+ .parent_names = (const char *[]){ "pxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
+#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \
+ static struct clk_rpm _platform##_##_active; \
+ static struct clk_rpm _platform##_##_name = { \
+ .rpm_clk_id = (r_id), \
+ .active_only = true, \
+ .peer = &_platform##_##_active, \
+ .rate = (r), \
+ .branch = true, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_branch_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "pxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }; \
+ static struct clk_rpm _platform##_##_active = { \
+ .rpm_clk_id = (r_id), \
+ .peer = &_platform##_##_name, \
+ .rate = (r), \
+ .branch = true, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_branch_ops, \
+ .name = #_active, \
+ .parent_names = (const char *[]){ "pxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
+#define DEFINE_CLK_RPM_CXO_BRANCH(_platform, _name, _active, r_id, r) \
+ static struct clk_rpm _platform##_##_active; \
+ static struct clk_rpm _platform##_##_name = { \
+ .rpm_clk_id = (r_id), \
+ .peer = &_platform##_##_active, \
+ .rate = (r), \
+ .branch = true, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_branch_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "cxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }; \
+ static struct clk_rpm _platform##_##_active = { \
+ .rpm_clk_id = (r_id), \
+ .active_only = true, \
+ .peer = &_platform##_##_name, \
+ .rate = (r), \
+ .branch = true, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_branch_ops, \
+ .name = #_active, \
+ .parent_names = (const char *[]){ "cxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
+#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
+
+struct clk_rpm {
+ const int rpm_clk_id;
+ const bool active_only;
+ unsigned long rate;
+ bool enabled;
+ bool branch;
+ struct clk_rpm *peer;
+ struct clk_hw hw;
+ struct qcom_rpm *rpm;
+};
+
+struct rpm_cc {
+ struct qcom_rpm *rpm;
+ struct clk_rpm **clks;
+ size_t num_clks;
+};
+
+struct rpm_clk_desc {
+ struct clk_rpm **clks;
+ size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_clk_lock);
+
+static int clk_rpm_handoff(struct clk_rpm *r)
+{
+ int ret;
+ u32 value = INT_MAX;
+
+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+ r->rpm_clk_id, &value, 1);
+ if (ret)
+ return ret;
+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+ r->rpm_clk_id, &value, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int clk_rpm_set_rate_active(struct clk_rpm *r, unsigned long rate)
+{
+ u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+ return qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+ r->rpm_clk_id, &value, 1);
+}
+
+static int clk_rpm_set_rate_sleep(struct clk_rpm *r, unsigned long rate)
+{
+ u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+ return qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+ r->rpm_clk_id, &value, 1);
+}
+
+static void to_active_sleep(struct clk_rpm *r, unsigned long rate,
+ unsigned long *active, unsigned long *sleep)
+{
+ *active = rate;
+
+ /*
+ * Active-only clocks don't care what the rate is during sleep. So,
+ * they vote for zero.
+ */
+ if (r->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+static int clk_rpm_prepare(struct clk_hw *hw)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+ struct clk_rpm *peer = r->peer;
+ unsigned long this_rate = 0, this_sleep_rate = 0;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ unsigned long active_rate, sleep_rate;
+ int ret = 0;
+
+ mutex_lock(&rpm_clk_lock);
+
+ /* Don't send requests to the RPM if the rate has not been set. */
+ if (!r->rate)
+ goto out;
+
+ to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate,
+ &peer_rate, &peer_sleep_rate);
+
+ active_rate = max(this_rate, peer_rate);
+
+ if (r->branch)
+ active_rate = !!active_rate;
+
+ ret = clk_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+ if (r->branch)
+ sleep_rate = !!sleep_rate;
+
+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ /* Undo the active set vote and restore it */
+ ret = clk_rpm_set_rate_active(r, peer_rate);
+
+out:
+ if (!ret)
+ r->enabled = true;
+
+ mutex_unlock(&rpm_clk_lock);
+
+ return ret;
+}
+
+static void clk_rpm_unprepare(struct clk_hw *hw)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+ struct clk_rpm *peer = r->peer;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ unsigned long active_rate, sleep_rate;
+ int ret;
+
+ mutex_lock(&rpm_clk_lock);
+
+ if (!r->rate)
+ goto out;
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate, &peer_rate,
+ &peer_sleep_rate);
+
+ active_rate = r->branch ? !!peer_rate : peer_rate;
+ ret = clk_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ goto out;
+
+ r->enabled = false;
+
+out:
+ mutex_unlock(&rpm_clk_lock);
+}
+
+static int clk_rpm_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+ struct clk_rpm *peer = r->peer;
+ unsigned long active_rate, sleep_rate;
+ unsigned long this_rate = 0, this_sleep_rate = 0;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ int ret = 0;
+
+ mutex_lock(&rpm_clk_lock);
+
+ if (!r->enabled)
+ goto out;
+
+ to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate,
+ &peer_rate, &peer_sleep_rate);
+
+ active_rate = max(this_rate, peer_rate);
+ ret = clk_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+ ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ goto out;
+
+ r->rate = rate;
+
+out:
+ mutex_unlock(&rpm_clk_lock);
+
+ return ret;
+}
+
+static long clk_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /*
+ * RPM handles rate rounding and we don't have a way to
+ * know what the rate will be, so just return whatever
+ * rate is requested.
+ */
+ return rate;
+}
+
+static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+
+ /*
+ * RPM handles rate rounding and we don't have a way to
+ * know what the rate will be, so just return whatever
+ * rate was set.
+ */
+ return r->rate;
+}
+
+static const struct clk_ops clk_rpm_ops = {
+ .prepare = clk_rpm_prepare,
+ .unprepare = clk_rpm_unprepare,
+ .set_rate = clk_rpm_set_rate,
+ .round_rate = clk_rpm_round_rate,
+ .recalc_rate = clk_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_rpm_branch_ops = {
+ .prepare = clk_rpm_prepare,
+ .unprepare = clk_rpm_unprepare,
+ .round_rate = clk_rpm_round_rate,
+ .recalc_rate = clk_rpm_recalc_rate,
+};
+
+/* apq8064 */
+DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
+DEFINE_CLK_RPM(apq8064, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
+DEFINE_CLK_RPM(apq8064, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
+DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
+DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
+
+static struct clk_rpm *apq8064_clks[] = {
+ [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
+ [RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk,
+ [RPM_CFPB_CLK] = &apq8064_cfpb_clk,
+ [RPM_CFPB_A_CLK] = &apq8064_cfpb_a_clk,
+ [RPM_DAYTONA_FABRIC_CLK] = &apq8064_daytona_clk,
+ [RPM_DAYTONA_FABRIC_A_CLK] = &apq8064_daytona_a_clk,
+ [RPM_EBI1_CLK] = &apq8064_ebi1_clk,
+ [RPM_EBI1_A_CLK] = &apq8064_ebi1_a_clk,
+ [RPM_MM_FABRIC_CLK] = &apq8064_mmfab_clk,
+ [RPM_MM_FABRIC_A_CLK] = &apq8064_mmfab_a_clk,
+ [RPM_MMFPB_CLK] = &apq8064_mmfpb_clk,
+ [RPM_MMFPB_A_CLK] = &apq8064_mmfpb_a_clk,
+ [RPM_SYS_FABRIC_CLK] = &apq8064_sfab_clk,
+ [RPM_SYS_FABRIC_A_CLK] = &apq8064_sfab_a_clk,
+ [RPM_SFPB_CLK] = &apq8064_sfpb_clk,
+ [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
+ [RPM_QDSS_CLK] = &apq8064_qdss_clk,
+ [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
+};
+
+static const struct rpm_clk_desc rpm_clk_apq8064 = {
+ .clks = apq8064_clks,
+ .num_clks = ARRAY_SIZE(apq8064_clks),
+};
+
+static const struct of_device_id rpm_clk_match_table[] = {
+ { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rpm_clk_match_table);
+
+static struct clk_hw *qcom_rpm_clk_hw_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ struct rpm_cc *rcc = data;
+ unsigned int idx = clkspec->args[0];
+
+ if (idx >= rcc->num_clks) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_clk_probe(struct platform_device *pdev)
+{
+ struct rpm_cc *rcc;
+ int ret;
+ size_t num_clks, i;
+ struct qcom_rpm *rpm;
+ struct clk_rpm **rpm_clks;
+ const struct rpm_clk_desc *desc;
+
+ rpm = dev_get_drvdata(pdev->dev.parent);
+ if (!rpm) {
+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+ return -ENODEV;
+ }
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpm_clks = desc->clks;
+ num_clks = desc->num_clks;
+
+ rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+ if (!rcc)
+ return -ENOMEM;
+
+ rcc->clks = rpm_clks;
+ rcc->num_clks = num_clks;
+
+ for (i = 0; i < num_clks; i++) {
+ if (!rpm_clks[i])
+ continue;
+
+ rpm_clks[i]->rpm = rpm;
+
+ ret = clk_rpm_handoff(rpm_clks[i]);
+ if (ret)
+ goto err;
+ }
+
+ for (i = 0; i < num_clks; i++) {
+ if (!rpm_clks[i])
+ continue;
+
+ ret = devm_clk_hw_register(&pdev->dev, &rpm_clks[i]->hw);
+ if (ret)
+ goto err;
+ }
+
+ ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_rpm_clk_hw_get,
+ rcc);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_err(&pdev->dev, "Error registering RPM Clock driver (%d)\n", ret);
+ return ret;
+}
+
+static int rpm_clk_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver rpm_clk_driver = {
+ .driver = {
+ .name = "qcom-clk-rpm",
+ .of_match_table = rpm_clk_match_table,
+ },
+ .probe = rpm_clk_probe,
+ .remove = rpm_clk_remove,
+};
+
+static int __init rpm_clk_init(void)
+{
+ return platform_driver_register(&rpm_clk_driver);
+}
+core_initcall(rpm_clk_init);
+
+static void __exit rpm_clk_exit(void)
+{
+ platform_driver_unregister(&rpm_clk_driver);
+}
+module_exit(rpm_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-rpm");
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
new file mode 100644
index 000000000000..07e2cc6ed781
--- /dev/null
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, 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
+ * 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-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/mfd/qcom-rpm.h>
+
+#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
+#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
+#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
+#define QCOM_RPM_SMD_KEY_ENABLE 0x62616e45
+#define QCOM_RPM_SMD_KEY_STATE 0x54415453
+#define QCOM_RPM_SCALING_ENABLE_ID 0x2
+
+#define __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, stat_id, \
+ key) \
+ static struct clk_smd_rpm _platform##_##_active; \
+ static struct clk_smd_rpm _platform##_##_name = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
+ .peer = &_platform##_##_active, \
+ .rate = INT_MAX, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_smd_rpm_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "xo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }; \
+ static struct clk_smd_rpm _platform##_##_active = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .active_only = true, \
+ .rpm_key = (key), \
+ .peer = &_platform##_##_name, \
+ .rate = INT_MAX, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_smd_rpm_ops, \
+ .name = #_active, \
+ .parent_names = (const char *[]){ "xo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
+#define __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, \
+ stat_id, r, key) \
+ static struct clk_smd_rpm _platform##_##_active; \
+ static struct clk_smd_rpm _platform##_##_name = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
+ .branch = true, \
+ .peer = &_platform##_##_active, \
+ .rate = (r), \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_smd_rpm_branch_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "xo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }; \
+ static struct clk_smd_rpm _platform##_##_active = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .active_only = true, \
+ .rpm_key = (key), \
+ .branch = true, \
+ .peer = &_platform##_##_name, \
+ .rate = (r), \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_smd_rpm_branch_ops, \
+ .name = #_active, \
+ .parent_names = (const char *[]){ "xo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
+#define DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id) \
+ __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \
+ 0, QCOM_RPM_SMD_KEY_RATE)
+
+#define DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, r) \
+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, \
+ r_id, 0, r, QCOM_RPM_SMD_KEY_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_QDSS(_platform, _name, _active, type, r_id) \
+ __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \
+ 0, QCOM_RPM_SMD_KEY_STATE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER(_platform, _name, _active, r_id) \
+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \
+ QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \
+ QCOM_RPM_KEY_SOFTWARE_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_platform, _name, _active, r_id) \
+ __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \
+ QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \
+ QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY)
+
+#define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw)
+
+struct clk_smd_rpm {
+ const int rpm_res_type;
+ const int rpm_key;
+ const int rpm_clk_id;
+ const int rpm_status_id;
+ const bool active_only;
+ bool enabled;
+ bool branch;
+ struct clk_smd_rpm *peer;
+ struct clk_hw hw;
+ unsigned long rate;
+ struct qcom_smd_rpm *rpm;
+};
+
+struct clk_smd_rpm_req {
+ __le32 key;
+ __le32 nbytes;
+ __le32 value;
+};
+
+struct rpm_cc {
+ struct qcom_rpm *rpm;
+ struct clk_smd_rpm **clks;
+ size_t num_clks;
+};
+
+struct rpm_smd_clk_desc {
+ struct clk_smd_rpm **clks;
+ size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_smd_clk_lock);
+
+static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
+{
+ int ret;
+ struct clk_smd_rpm_req req = {
+ .key = cpu_to_le32(r->rpm_key),
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(INT_MAX),
+ };
+
+ ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ r->rpm_res_type, r->rpm_clk_id, &req,
+ sizeof(req));
+ if (ret)
+ return ret;
+ ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ r->rpm_res_type, r->rpm_clk_id, &req,
+ sizeof(req));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
+ unsigned long rate)
+{
+ struct clk_smd_rpm_req req = {
+ .key = cpu_to_le32(r->rpm_key),
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+ };
+
+ return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ r->rpm_res_type, r->rpm_clk_id, &req,
+ sizeof(req));
+}
+
+static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
+ unsigned long rate)
+{
+ struct clk_smd_rpm_req req = {
+ .key = cpu_to_le32(r->rpm_key),
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+ };
+
+ return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ r->rpm_res_type, r->rpm_clk_id, &req,
+ sizeof(req));
+}
+
+static void to_active_sleep(struct clk_smd_rpm *r, unsigned long rate,
+ unsigned long *active, unsigned long *sleep)
+{
+ *active = rate;
+
+ /*
+ * Active-only clocks don't care what the rate is during sleep. So,
+ * they vote for zero.
+ */
+ if (r->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+static int clk_smd_rpm_prepare(struct clk_hw *hw)
+{
+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+ struct clk_smd_rpm *peer = r->peer;
+ unsigned long this_rate = 0, this_sleep_rate = 0;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ unsigned long active_rate, sleep_rate;
+ int ret = 0;
+
+ mutex_lock(&rpm_smd_clk_lock);
+
+ /* Don't send requests to the RPM if the rate has not been set. */
+ if (!r->rate)
+ goto out;
+
+ to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate,
+ &peer_rate, &peer_sleep_rate);
+
+ active_rate = max(this_rate, peer_rate);
+
+ if (r->branch)
+ active_rate = !!active_rate;
+
+ ret = clk_smd_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+ if (r->branch)
+ sleep_rate = !!sleep_rate;
+
+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ /* Undo the active set vote and restore it */
+ ret = clk_smd_rpm_set_rate_active(r, peer_rate);
+
+out:
+ if (!ret)
+ r->enabled = true;
+
+ mutex_unlock(&rpm_smd_clk_lock);
+
+ return ret;
+}
+
+static void clk_smd_rpm_unprepare(struct clk_hw *hw)
+{
+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+ struct clk_smd_rpm *peer = r->peer;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ unsigned long active_rate, sleep_rate;
+ int ret;
+
+ mutex_lock(&rpm_smd_clk_lock);
+
+ if (!r->rate)
+ goto out;
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate, &peer_rate,
+ &peer_sleep_rate);
+
+ active_rate = r->branch ? !!peer_rate : peer_rate;
+ ret = clk_smd_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ goto out;
+
+ r->enabled = false;
+
+out:
+ mutex_unlock(&rpm_smd_clk_lock);
+}
+
+static int clk_smd_rpm_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+ struct clk_smd_rpm *peer = r->peer;
+ unsigned long active_rate, sleep_rate;
+ unsigned long this_rate = 0, this_sleep_rate = 0;
+ unsigned long peer_rate = 0, peer_sleep_rate = 0;
+ int ret = 0;
+
+ mutex_lock(&rpm_smd_clk_lock);
+
+ if (!r->enabled)
+ goto out;
+
+ to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+ /* Take peer clock's rate into account only if it's enabled. */
+ if (peer->enabled)
+ to_active_sleep(peer, peer->rate,
+ &peer_rate, &peer_sleep_rate);
+
+ active_rate = max(this_rate, peer_rate);
+ ret = clk_smd_rpm_set_rate_active(r, active_rate);
+ if (ret)
+ goto out;
+
+ sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+ ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+ if (ret)
+ goto out;
+
+ r->rate = rate;
+
+out:
+ mutex_unlock(&rpm_smd_clk_lock);
+
+ return ret;
+}
+
+static long clk_smd_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /*
+ * RPM handles rate rounding and we don't have a way to
+ * know what the rate will be, so just return whatever
+ * rate is requested.
+ */
+ return rate;
+}
+
+static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+
+ /*
+ * RPM handles rate rounding and we don't have a way to
+ * know what the rate will be, so just return whatever
+ * rate was set.
+ */
+ return r->rate;
+}
+
+static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
+{
+ int ret;
+ struct clk_smd_rpm_req req = {
+ .key = cpu_to_le32(QCOM_RPM_SMD_KEY_ENABLE),
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(1),
+ };
+
+ ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ QCOM_SMD_RPM_MISC_CLK,
+ QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+ if (ret) {
+ pr_err("RPM clock scaling (sleep set) not enabled!\n");
+ return ret;
+ }
+
+ ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ QCOM_SMD_RPM_MISC_CLK,
+ QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+ if (ret) {
+ pr_err("RPM clock scaling (active set) not enabled!\n");
+ return ret;
+ }
+
+ pr_debug("%s: RPM clock scaling is enabled\n", __func__);
+ return 0;
+}
+
+static const struct clk_ops clk_smd_rpm_ops = {
+ .prepare = clk_smd_rpm_prepare,
+ .unprepare = clk_smd_rpm_unprepare,
+ .set_rate = clk_smd_rpm_set_rate,
+ .round_rate = clk_smd_rpm_round_rate,
+ .recalc_rate = clk_smd_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_smd_rpm_branch_ops = {
+ .prepare = clk_smd_rpm_prepare,
+ .unprepare = clk_smd_rpm_unprepare,
+ .round_rate = clk_smd_rpm_round_rate,
+ .recalc_rate = clk_smd_rpm_recalc_rate,
+};
+
+/* msm8916 */
+DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
+DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
+DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
+DEFINE_CLK_SMD_RPM_QDSS(msm8916, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk1, bb_clk1_a, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk2, bb_clk2_a, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk1, rf_clk1_a, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk2, rf_clk2_a, 5);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk1_pin, bb_clk1_a_pin, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk2_pin, bb_clk2_a_pin, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk1_pin, rf_clk1_a_pin, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk2_pin, rf_clk2_a_pin, 5);
+
+static struct clk_smd_rpm *msm8916_clks[] = {
+ [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
+ [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
+ [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
+ [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
+ [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk,
+ [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
+ [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1,
+ [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a,
+ [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2,
+ [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a,
+ [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
+ [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
+ [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
+ [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
+ [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
+ [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
+ [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
+ [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
+ [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
+ [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
+ [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
+ [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_msm8916 = {
+ .clks = msm8916_clks,
+ .num_clks = ARRAY_SIZE(msm8916_clks),
+};
+
+static const struct of_device_id rpm_smd_clk_match_table[] = {
+ { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
+
+static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ struct rpm_cc *rcc = data;
+ unsigned int idx = clkspec->args[0];
+
+ if (idx >= rcc->num_clks) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_smd_clk_probe(struct platform_device *pdev)
+{
+ struct rpm_cc *rcc;
+ int ret;
+ size_t num_clks, i;
+ struct qcom_smd_rpm *rpm;
+ struct clk_smd_rpm **rpm_smd_clks;
+ const struct rpm_smd_clk_desc *desc;
+
+ rpm = dev_get_drvdata(pdev->dev.parent);
+ if (!rpm) {
+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+ return -ENODEV;
+ }
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpm_smd_clks = desc->clks;
+ num_clks = desc->num_clks;
+
+ rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+ if (!rcc)
+ return -ENOMEM;
+
+ rcc->clks = rpm_smd_clks;
+ rcc->num_clks = num_clks;
+
+ for (i = 0; i < num_clks; i++) {
+ if (!rpm_smd_clks[i])
+ continue;
+
+ rpm_smd_clks[i]->rpm = rpm;
+
+ ret = clk_smd_rpm_handoff(rpm_smd_clks[i]);
+ if (ret)
+ goto err;
+ }
+
+ ret = clk_smd_rpm_enable_scaling(rpm);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < num_clks; i++) {
+ if (!rpm_smd_clks[i])
+ continue;
+
+ ret = devm_clk_hw_register(&pdev->dev, &rpm_smd_clks[i]->hw);
+ if (ret)
+ goto err;
+ }
+
+ ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get,
+ rcc);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret);
+ return ret;
+}
+
+static int rpm_smd_clk_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver rpm_smd_clk_driver = {
+ .driver = {
+ .name = "qcom-clk-smd-rpm",
+ .of_match_table = rpm_smd_clk_match_table,
+ },
+ .probe = rpm_smd_clk_probe,
+ .remove = rpm_smd_clk_remove,
+};
+
+static int __init rpm_smd_clk_init(void)
+{
+ return platform_driver_register(&rpm_smd_clk_driver);
+}
+core_initcall(rpm_smd_clk_init);
+
+static void __exit rpm_smd_clk_exit(void)
+{
+ platform_driver_unregister(&rpm_smd_clk_driver);
+}
+module_exit(rpm_smd_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM over SMD Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-smd-rpm");
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index fffcbaf0fba7..cfab7b400381 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -46,6 +46,22 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
}
EXPORT_SYMBOL_GPL(qcom_find_freq);
+const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ unsigned long rate)
+{
+ const struct freq_tbl *best = NULL;
+
+ for ( ; f->freq; f++) {
+ if (rate >= f->freq)
+ best = f;
+ else
+ break;
+ }
+
+ return best;
+}
+EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
+
int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
{
int i, num_parents = clk_hw_get_num_parents(hw);
@@ -74,6 +90,27 @@ qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
}
EXPORT_SYMBOL_GPL(qcom_cc_map);
+void
+qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count)
+{
+ u32 val;
+ u32 mask;
+
+ /* De-assert reset to FSM */
+ regmap_update_bits(map, reg, PLL_VOTE_FSM_RESET, 0);
+
+ /* Program bias count and lock count */
+ val = bias_count << PLL_BIAS_COUNT_SHIFT |
+ lock_count << PLL_LOCK_COUNT_SHIFT;
+ mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
+ mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
+ regmap_update_bits(map, reg, mask, val);
+
+ /* Enable PLL FSM voting */
+ regmap_update_bits(map, reg, PLL_VOTE_FSM_ENA, PLL_VOTE_FSM_ENA);
+}
+EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode);
+
static void qcom_cc_del_clk_provider(void *data)
{
of_clk_del_provider(data);
@@ -153,15 +190,12 @@ int qcom_cc_register_board_clk(struct device *dev, const char *path,
const char *name, unsigned long rate)
{
bool add_factor = true;
- struct device_node *node;
-
- /* The RPM clock driver will add the factor clock if present */
- if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
- node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
- if (of_device_is_available(node))
- add_factor = false;
- of_node_put(node);
- }
+
+ /*
+ * TODO: The RPM clock driver currently does not support the xo clock.
+ * When xo is added to the RPM clock driver, we should change this
+ * function to skip registration of xo factor clocks.
+ */
return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
}
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index ae9bdeb21f29..23c1927669ba 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -22,6 +22,13 @@ struct freq_tbl;
struct clk_hw;
struct parent_map;
+#define PLL_LOCK_COUNT_SHIFT 8
+#define PLL_LOCK_COUNT_MASK 0x3f
+#define PLL_BIAS_COUNT_SHIFT 14
+#define PLL_BIAS_COUNT_MASK 0x3f
+#define PLL_VOTE_FSM_ENA BIT(20)
+#define PLL_VOTE_FSM_RESET BIT(21)
+
struct qcom_cc_desc {
const struct regmap_config *config;
struct clk_regmap **clks;
@@ -34,6 +41,10 @@ struct qcom_cc_desc {
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
unsigned long rate);
+extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ unsigned long rate);
+extern void
+qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count);
extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
u8 src);
diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c
index 070037a29ea5..486d9610355c 100644
--- a/drivers/clk/qcom/gcc-apq8084.c
+++ b/drivers/clk/qcom/gcc-apq8084.c
@@ -1142,7 +1142,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1156,7 +1156,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1170,7 +1170,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1184,7 +1184,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c
index b593065de8db..33d09138f5e5 100644
--- a/drivers/clk/qcom/gcc-ipq4019.c
+++ b/drivers/clk/qcom/gcc-ipq4019.c
@@ -185,8 +185,7 @@ static struct clk_branch gcc_audio_pwm_clk = {
};
static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
- F(19200000, P_XO, 1, 2, 5),
- F(24000000, P_XO, 1, 1, 2),
+ F(19050000, P_FEPLL200, 10.5, 1, 1),
{ }
};
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 52a7d3959875..28eb200d0f1e 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -2990,11 +2990,11 @@ static int gcc_ipq806x_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+ ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 25000000);
if (ret)
return ret;
- ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+ ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 25000000);
if (ret)
return ret;
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index 5c4e193164d4..628e6ca276ec 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -1107,7 +1107,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1132,7 +1132,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 00915209e7c5..348e30da4f18 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -872,7 +872,7 @@ static struct clk_init_data sdcc1_apps_clk_src_init = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
};
static struct clk_rcg2 sdcc1_apps_clk_src = {
@@ -894,7 +894,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -908,7 +908,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -922,7 +922,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c
new file mode 100644
index 000000000000..8afd8304a070
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8994.c
@@ -0,0 +1,2300 @@
+/* Copyright (c) 2013-2016, 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/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8994.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+enum {
+ P_XO,
+ P_GPLL0,
+ P_GPLL4,
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
+static const char * const gcc_xo_gpll0[] = {
+ "xo",
+ "gpll0",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_xo_gpll0_gpll4[] = {
+ "xo",
+ "gpll0",
+ "gpll4",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "xo",
+ .parent_names = (const char *[]) { "xo_board" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll0_early = {
+ .offset = 0x00000,
+ .clkr = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll0_early",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+ .offset = 0x00000,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll0",
+ .parent_names = (const char *[]) { "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+ .offset = 0x1dc0,
+ .clkr = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll4_early",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x1dc0,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll4",
+ .parent_names = (const char *[]) { "gpll4_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+ .cmd_rcgr = 0x1d68,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_ufs_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(125000000, P_GPLL0, 1, 5, 24),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0x03d4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0660,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_blspqup_spi_apps_clk_src[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(15000000, P_GPLL0, 10, 1, 4),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 12.5, 1, 2),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x064c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x06e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x06cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0760,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x074c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x07e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x07cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0860,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+ .cmd_rcgr = 0x084c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x08e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+ .cmd_rcgr = 0x08cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+ F(3686400, P_GPLL0, 1, 96, 15625),
+ F(7372800, P_GPLL0, 1, 192, 15625),
+ F(14745600, P_GPLL0, 1, 384, 15625),
+ F(16000000, P_GPLL0, 5, 2, 15),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_GPLL0, 1, 4, 75),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(46400000, P_GPLL0, 1, 29, 375),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(51200000, P_GPLL0, 1, 32, 375),
+ F(56000000, P_GPLL0, 1, 7, 75),
+ F(58982400, P_GPLL0, 1, 1536, 15625),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(63160000, P_GPLL0, 9.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x068c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x070c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+ .cmd_rcgr = 0x078c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+ .cmd_rcgr = 0x080c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+ .cmd_rcgr = 0x088c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+ .cmd_rcgr = 0x090c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp1_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x09a0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x098c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0a20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0a0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0aa0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0a8c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0b20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0b0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0ba0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0b8c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0c20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0c0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x09cc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x0a4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+ .cmd_rcgr = 0x0acc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+ .cmd_rcgr = 0x0b4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+ .cmd_rcgr = 0x0bcc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+ .cmd_rcgr = 0x0c4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "blsp2_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_gp1_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x1904,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gp1_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_gp2_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x1944,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gp2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gp2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_gp3_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x1984,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gp3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gp3_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_pcie_0_aux_clk_src[] = {
+ F(1011000, P_XO, 1, 1, 19),
+ { }
+};
+
+static struct clk_rcg2 pcie_0_aux_clk_src = {
+ .cmd_rcgr = 0x1b00,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .freq_tbl = ftbl_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "pcie_0_aux_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_pcie_pipe_clk_src[] = {
+ F(125000000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pcie_0_pipe_clk_src = {
+ .cmd_rcgr = 0x1adc,
+ .hid_width = 5,
+ .freq_tbl = ftbl_pcie_pipe_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "pcie_0_pipe_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_pcie_1_aux_clk_src[] = {
+ F(1011000, P_XO, 1, 1, 19),
+ { }
+};
+
+static struct clk_rcg2 pcie_1_aux_clk_src = {
+ .cmd_rcgr = 0x1b80,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .freq_tbl = ftbl_pcie_1_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "pcie_1_aux_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 pcie_1_pipe_clk_src = {
+ .cmd_rcgr = 0x1b5c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_pcie_pipe_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "pcie_1_pipe_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_pdm2_clk_src[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x0cd0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0, 15, 1, 2),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 2, 0, 0),
+ F(384000000, P_GPLL4, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x04d0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_gpll4_map,
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4,
+ .num_parents = 3,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static struct freq_tbl ftbl_sdcc2_4_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0, 15, 1, 2),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x0510,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+ .cmd_rcgr = 0x0550,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "sdcc3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+ .cmd_rcgr = 0x0590,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "sdcc4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static struct freq_tbl ftbl_tsif_ref_clk_src[] = {
+ F(105500, P_XO, 1, 1, 182),
+ { }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+ .cmd_rcgr = 0x0d90,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .freq_tbl = ftbl_tsif_ref_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "tsif_ref_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x03e8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+ F(1200000, P_XO, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .cmd_rcgr = 0x1414,
+ .hid_width = 5,
+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "usb3_phy_aux_clk_src",
+ .parent_names = (const char *[]) { "xo" },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_usb_hs_system_clk_src[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+ .cmd_rcgr = 0x0490,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_usb_hs_system_clk_src,
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "usb_hs_system_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x05c4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x0648,
+ .clkr = {
+ .enable_reg = 0x0648,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x0644,
+ .clkr = {
+ .enable_reg = 0x0644,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x06c8,
+ .clkr = {
+ .enable_reg = 0x06c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x06c4,
+ .clkr = {
+ .enable_reg = 0x06c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x0748,
+ .clkr = {
+ .enable_reg = 0x0748,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x0744,
+ .clkr = {
+ .enable_reg = 0x0744,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x07c8,
+ .clkr = {
+ .enable_reg = 0x07c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x07c4,
+ .clkr = {
+ .enable_reg = 0x07c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+ .halt_reg = 0x0848,
+ .clkr = {
+ .enable_reg = 0x0848,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup5_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup5_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+ .halt_reg = 0x0844,
+ .clkr = {
+ .enable_reg = 0x0844,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup5_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup5_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+ .halt_reg = 0x08c8,
+ .clkr = {
+ .enable_reg = 0x08c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup6_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup6_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+ .halt_reg = 0x08c4,
+ .clkr = {
+ .enable_reg = 0x08c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_qup6_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_qup6_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x0684,
+ .clkr = {
+ .enable_reg = 0x0684,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x0704,
+ .clkr = {
+ .enable_reg = 0x0704,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+ .halt_reg = 0x0784,
+ .clkr = {
+ .enable_reg = 0x0784,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart3_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+ .halt_reg = 0x0804,
+ .clkr = {
+ .enable_reg = 0x0804,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart4_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+ .halt_reg = 0x0884,
+ .clkr = {
+ .enable_reg = 0x0884,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart5_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart5_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+ .halt_reg = 0x0904,
+ .clkr = {
+ .enable_reg = 0x0904,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp1_uart6_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp1_uart6_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x0944,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x0988,
+ .clkr = {
+ .enable_reg = 0x0988,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x0984,
+ .clkr = {
+ .enable_reg = 0x0984,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x0a08,
+ .clkr = {
+ .enable_reg = 0x0a08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x0a04,
+ .clkr = {
+ .enable_reg = 0x0a04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x0a88,
+ .clkr = {
+ .enable_reg = 0x0a88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x0a84,
+ .clkr = {
+ .enable_reg = 0x0a84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x0b08,
+ .clkr = {
+ .enable_reg = 0x0b08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x0b04,
+ .clkr = {
+ .enable_reg = 0x0b04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+ .halt_reg = 0x0b88,
+ .clkr = {
+ .enable_reg = 0x0b88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup5_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup5_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+ .halt_reg = 0x0b84,
+ .clkr = {
+ .enable_reg = 0x0b84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup5_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup5_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+ .halt_reg = 0x0c08,
+ .clkr = {
+ .enable_reg = 0x0c08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup6_i2c_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup6_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+ .halt_reg = 0x0c04,
+ .clkr = {
+ .enable_reg = 0x0c04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_qup6_spi_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_qup6_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x09c4,
+ .clkr = {
+ .enable_reg = 0x09c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x0a44,
+ .clkr = {
+ .enable_reg = 0x0a44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+ .halt_reg = 0x0ac4,
+ .clkr = {
+ .enable_reg = 0x0ac4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart3_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+ .halt_reg = 0x0b44,
+ .clkr = {
+ .enable_reg = 0x0b44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart4_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+ .halt_reg = 0x0bc4,
+ .clkr = {
+ .enable_reg = 0x0bc4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart5_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart5_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+ .halt_reg = 0x0c44,
+ .clkr = {
+ .enable_reg = 0x0c44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_blsp2_uart6_apps_clk",
+ .parent_names = (const char *[]) {
+ "blsp2_uart6_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x1900,
+ .clkr = {
+ .enable_reg = 0x1900,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_gp1_clk",
+ .parent_names = (const char *[]) {
+ "gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x1940,
+ .clkr = {
+ .enable_reg = 0x1940,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_gp2_clk",
+ .parent_names = (const char *[]) {
+ "gp2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x1980,
+ .clkr = {
+ .enable_reg = 0x1980,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_gp3_clk",
+ .parent_names = (const char *[]) {
+ "gp3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0x1ad4,
+ .clkr = {
+ .enable_reg = 0x1ad4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_names = (const char *[]) {
+ "pcie_0_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+ .halt_reg = 0x1ad8,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x1ad8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_names = (const char *[]) {
+ "pcie_0_pipe_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+ .halt_reg = 0x1b54,
+ .clkr = {
+ .enable_reg = 0x1b54,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_names = (const char *[]) {
+ "pcie_1_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .halt_reg = 0x1b58,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x1b58,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_names = (const char *[]) {
+ "pcie_1_pipe_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x0ccc,
+ .clkr = {
+ .enable_reg = 0x0ccc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_pdm2_clk",
+ .parent_names = (const char *[]) {
+ "pdm2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x04c4,
+ .clkr = {
+ .enable_reg = 0x04c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_names = (const char *[]) {
+ "sdcc1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x0504,
+ .clkr = {
+ .enable_reg = 0x0504,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_names = (const char *[]) {
+ "sdcc2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+ .halt_reg = 0x0544,
+ .clkr = {
+ .enable_reg = 0x0544,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sdcc3_apps_clk",
+ .parent_names = (const char *[]) {
+ "sdcc3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+ .halt_reg = 0x0584,
+ .clkr = {
+ .enable_reg = 0x0584,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sdcc4_apps_clk",
+ .parent_names = (const char *[]) {
+ "sdcc4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+ .halt_reg = 0x1d7c,
+ .clkr = {
+ .enable_reg = 0x1d7c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sys_noc_ufs_axi_clk",
+ .parent_names = (const char *[]) {
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+ .halt_reg = 0x03fc,
+ .clkr = {
+ .enable_reg = 0x03fc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_sys_noc_usb3_axi_clk",
+ .parent_names = (const char *[]) {
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+ .halt_reg = 0x0d88,
+ .clkr = {
+ .enable_reg = 0x0d88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_tsif_ref_clk",
+ .parent_names = (const char *[]) {
+ "tsif_ref_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+ .halt_reg = 0x1d48,
+ .clkr = {
+ .enable_reg = 0x1d48,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_ufs_axi_clk",
+ .parent_names = (const char *[]) {
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_cfg_clk = {
+ .halt_reg = 0x1d54,
+ .clkr = {
+ .enable_reg = 0x1d54,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_ufs_rx_cfg_clk",
+ .parent_names = (const char *[]) {
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_cfg_clk = {
+ .halt_reg = 0x1d50,
+ .clkr = {
+ .enable_reg = 0x1d50,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_ufs_tx_cfg_clk",
+ .parent_names = (const char *[]) {
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0x03c8,
+ .clkr = {
+ .enable_reg = 0x03c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_usb30_master_clk",
+ .parent_names = (const char *[]) {
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0x03d0,
+ .clkr = {
+ .enable_reg = 0x03d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_names = (const char *[]) {
+ "usb30_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .halt_reg = 0x1408,
+ .clkr = {
+ .enable_reg = 0x1408,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_usb3_phy_aux_clk",
+ .parent_names = (const char *[]) {
+ "usb3_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+ .halt_reg = 0x0484,
+ .clkr = {
+ .enable_reg = 0x0484,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data)
+ {
+ .name = "gcc_usb_hs_system_clk",
+ .parent_names = (const char *[]) {
+ "usb_hs_system_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *gcc_msm8994_clocks[] = {
+ [GPLL0_EARLY] = &gpll0_early.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+ [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+ [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+ [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+ [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr,
+ [BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr,
+ [BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr,
+ [BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr,
+ [BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [PCIE_0_AUX_CLK_SRC] = &pcie_0_aux_clk_src.clkr,
+ [PCIE_0_PIPE_CLK_SRC] = &pcie_0_pipe_clk_src.clkr,
+ [PCIE_1_AUX_CLK_SRC] = &pcie_1_aux_clk_src.clkr,
+ [PCIE_1_PIPE_CLK_SRC] = &pcie_1_pipe_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr,
+ [SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
+ [TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+ [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+ [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+ [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+ [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr,
+ [GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr,
+ [GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr,
+ [GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+ [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+ [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+ [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+ [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+ [GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
+ [GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
+ [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+ [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+ [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+ [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+ [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+};
+
+static const struct regmap_config gcc_msm8994_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x2000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_msm8994_desc = {
+ .config = &gcc_msm8994_regmap_config,
+ .clks = gcc_msm8994_clocks,
+ .num_clks = ARRAY_SIZE(gcc_msm8994_clocks),
+};
+
+static const struct of_device_id gcc_msm8994_match_table[] = {
+ { .compatible = "qcom,gcc-msm8994" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8994_match_table);
+
+static int gcc_msm8994_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct clk *clk;
+
+ clk = devm_clk_register(dev, &xo.hw);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ return qcom_cc_probe(pdev, &gcc_msm8994_desc);
+}
+
+static struct platform_driver gcc_msm8994_driver = {
+ .probe = gcc_msm8994_probe,
+ .driver = {
+ .name = "gcc-msm8994",
+ .of_match_table = gcc_msm8994_match_table,
+ },
+};
+
+static int __init gcc_msm8994_init(void)
+{
+ return platform_driver_register(&gcc_msm8994_driver);
+}
+core_initcall(gcc_msm8994_init);
+
+static void __exit gcc_msm8994_exit(void)
+{
+ platform_driver_unregister(&gcc_msm8994_driver);
+}
+module_exit(gcc_msm8994_exit);
+
+MODULE_DESCRIPTION("Qualcomm GCC MSM8994 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8994");
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index fe03e6fbc7df..4b1fc1730d29 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -460,14 +460,22 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
.num_parents = 4,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
+static struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
static struct clk_rcg2 sdcc1_ice_core_clk_src = {
.cmd_rcgr = 0x13024,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc1_ice_core_clk_src",
.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
@@ -497,7 +505,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -511,7 +519,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
.name = "sdcc3_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll4,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -535,7 +543,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_xo_gpll0,
.num_parents = 2,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -1230,10 +1238,18 @@ static struct clk_rcg2 ufs_axi_clk_src = {
},
};
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
static struct clk_rcg2 ufs_ice_core_clk_src = {
.cmd_rcgr = 0x76014,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_ice_core_clk_src",
.parent_names = gcc_xo_gpll0,
@@ -1242,10 +1258,19 @@ static struct clk_rcg2 ufs_ice_core_clk_src = {
},
};
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(256000000, P_GPLL4, 1.5, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
static struct clk_rcg2 qspi_ser_clk_src = {
.cmd_rcgr = 0x8b00c,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map,
+ .freq_tbl = ftbl_qspi_ser_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "qspi_ser_clk_src",
.parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
index f12d7b2bddd7..288186cce0ae 100644
--- a/drivers/clk/qcom/gdsc.c
+++ b/drivers/clk/qcom/gdsc.c
@@ -30,6 +30,7 @@
#define SW_OVERRIDE_MASK BIT(2)
#define HW_CONTROL_MASK BIT(1)
#define SW_COLLAPSE_MASK BIT(0)
+#define GMEM_CLAMP_IO_MASK BIT(0)
/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
#define EN_REST_WAIT_VAL (0x2 << 20)
@@ -55,6 +56,13 @@ static int gdsc_is_enabled(struct gdsc *sc, unsigned int reg)
return !!(val & PWR_ON_MASK);
}
+static int gdsc_hwctrl(struct gdsc *sc, bool en)
+{
+ u32 val = en ? HW_CONTROL_MASK : 0;
+
+ return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
+}
+
static int gdsc_toggle_logic(struct gdsc *sc, bool en)
{
int ret;
@@ -140,6 +148,18 @@ static inline void gdsc_clear_mem_on(struct gdsc *sc)
regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
}
+static inline void gdsc_deassert_clamp_io(struct gdsc *sc)
+{
+ regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+ GMEM_CLAMP_IO_MASK, 0);
+}
+
+static inline void gdsc_assert_clamp_io(struct gdsc *sc)
+{
+ regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+ GMEM_CLAMP_IO_MASK, 1);
+}
+
static int gdsc_enable(struct generic_pm_domain *domain)
{
struct gdsc *sc = domain_to_gdsc(domain);
@@ -148,6 +168,9 @@ static int gdsc_enable(struct generic_pm_domain *domain)
if (sc->pwrsts == PWRSTS_ON)
return gdsc_deassert_reset(sc);
+ if (sc->flags & CLAMP_IO)
+ gdsc_deassert_clamp_io(sc);
+
ret = gdsc_toggle_logic(sc, true);
if (ret)
return ret;
@@ -164,20 +187,39 @@ static int gdsc_enable(struct generic_pm_domain *domain)
*/
udelay(1);
+ /* Turn on HW trigger mode if supported */
+ if (sc->flags & HW_CTRL)
+ return gdsc_hwctrl(sc, true);
+
return 0;
}
static int gdsc_disable(struct generic_pm_domain *domain)
{
struct gdsc *sc = domain_to_gdsc(domain);
+ int ret;
if (sc->pwrsts == PWRSTS_ON)
return gdsc_assert_reset(sc);
+ /* Turn off HW trigger mode if supported */
+ if (sc->flags & HW_CTRL) {
+ ret = gdsc_hwctrl(sc, false);
+ if (ret < 0)
+ return ret;
+ }
+
if (sc->pwrsts & PWRSTS_OFF)
gdsc_clear_mem_on(sc);
- return gdsc_toggle_logic(sc, false);
+ ret = gdsc_toggle_logic(sc, false);
+ if (ret)
+ return ret;
+
+ if (sc->flags & CLAMP_IO)
+ gdsc_assert_clamp_io(sc);
+
+ return 0;
}
static int gdsc_init(struct gdsc *sc)
diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
index 3bf497c36bdf..39648348e5ec 100644
--- a/drivers/clk/qcom/gdsc.h
+++ b/drivers/clk/qcom/gdsc.h
@@ -39,6 +39,7 @@ struct gdsc {
struct regmap *regmap;
unsigned int gdscr;
unsigned int gds_hw_ctrl;
+ unsigned int clamp_io_ctrl;
unsigned int *cxcs;
unsigned int cxc_count;
const u8 pwrsts;
@@ -50,6 +51,8 @@ struct gdsc {
#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
const u8 flags;
#define VOTABLE BIT(0)
+#define CLAMP_IO BIT(1)
+#define HW_CTRL BIT(2)
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c
index db3998e5e2d8..977e98eadbeb 100644
--- a/drivers/clk/qcom/lcc-ipq806x.c
+++ b/drivers/clk/qcom/lcc-ipq806x.c
@@ -443,7 +443,7 @@ static int lcc_ipq806x_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
/* Configure the rate of PLL4 if the bootloader hasn't already */
- val = regmap_read(regmap, 0x0, &val);
+ regmap_read(regmap, 0x0, &val);
if (!val)
clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
/* Enable PLL4 source on the LPASS Primary PLL Mux */
diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c
index ca97e1151797..9b97246287a7 100644
--- a/drivers/clk/qcom/mmcc-msm8996.c
+++ b/drivers/clk/qcom/mmcc-msm8996.c
@@ -2945,6 +2945,7 @@ static struct gdsc venus_core0_gdsc = {
.name = "venus_core0",
},
.pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
};
static struct gdsc venus_core1_gdsc = {
@@ -2955,6 +2956,7 @@ static struct gdsc venus_core1_gdsc = {
.name = "venus_core1",
},
.pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
};
static struct gdsc camss_gdsc = {
@@ -3034,6 +3036,28 @@ static struct gdsc mdss_gdsc = {
.pwrsts = PWRSTS_OFF_ON,
};
+static struct gdsc gpu_gdsc = {
+ .gdscr = 0x4034,
+ .gds_hw_ctrl = 0x4038,
+ .pd = {
+ .name = "gpu",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+ .gdscr = 0x4024,
+ .clamp_io_ctrl = 0x4300,
+ .cxcs = (unsigned int []){ 0x4028 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "gpu_gx",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO,
+};
+
static struct clk_regmap *mmcc_msm8996_clocks[] = {
[MMPLL0_EARLY] = &mmpll0_early.clkr,
[MMPLL0_PLL] = &mmpll0.clkr,
@@ -3223,6 +3247,8 @@ static struct gdsc *mmcc_msm8996_gdscs[] = {
[CPP_GDSC] = &cpp_gdsc,
[FD_GDSC] = &fd_gdsc,
[MDSS_GDSC] = &mdss_gdsc,
+ [GPU_GDSC] = &gpu_gdsc,
+ [GPU_GX_GDSC] = &gpu_gx_gdsc,
};
static const struct qcom_reset_map mmcc_msm8996_resets[] = {
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index 41a12d376799..2586dfa0026b 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -1,5 +1,7 @@
config CLK_RENESAS_CPG_MSSR
bool
+ default y if ARCH_R8A7743
+ default y if ARCH_R8A7745
default y if ARCH_R8A7795
default y if ARCH_R8A7796
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 90dd0db7d9c6..1072f7653c0c 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -2,6 +2,8 @@ obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7743) += r8a7743-cpg-mssr.o rcar-gen2-cpg.o
+obj-$(CONFIG_ARCH_R8A7745) += r8a7745-cpg-mssr.o rcar-gen2-cpg.o
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o
diff --git a/drivers/clk/renesas/clk-r8a7778.c b/drivers/clk/renesas/clk-r8a7778.c
index 40e3a501a50e..886a8380e912 100644
--- a/drivers/clk/renesas/clk-r8a7778.c
+++ b/drivers/clk/renesas/clk-r8a7778.c
@@ -12,6 +12,7 @@
#include <linux/clk/renesas.h>
#include <linux/of_address.h>
#include <linux/slab.h>
+#include <linux/soc/renesas/rcar-rst.h>
struct r8a7778_cpg {
struct clk_onecell_data data;
@@ -83,6 +84,18 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
struct clk **clks;
unsigned int i;
int num_clks;
+ u32 mode;
+
+ if (rcar_rst_read_mode_pins(&mode))
+ return;
+
+ BUG_ON(!(mode & BIT(19)));
+
+ cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
+ (!!(mode & BIT(12)) << 1) |
+ (!!(mode & BIT(11)));
+ cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
+ (!!(mode & BIT(1)));
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
@@ -130,16 +143,3 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
r8a7778_cpg_clocks_init);
-
-void __init r8a7778_clocks_init(u32 mode)
-{
- BUG_ON(!(mode & BIT(19)));
-
- cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
- (!!(mode & BIT(12)) << 1) |
- (!!(mode & BIT(11)));
- cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
- (!!(mode & BIT(1)));
-
- of_clk_init(NULL);
-}
diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c
index cf2a37df03b1..27fbfafaf2cd 100644
--- a/drivers/clk/renesas/clk-r8a7779.c
+++ b/drivers/clk/renesas/clk-r8a7779.c
@@ -18,6 +18,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7779-clock.h>
@@ -88,8 +89,6 @@ static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 };
* Initialization
*/
-static u32 cpg_mode __initdata;
-
static struct clk * __init
r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg,
const struct cpg_clk_config *config,
@@ -127,6 +126,10 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
struct clk **clks;
unsigned int i, plla_mult;
int num_clks;
+ u32 mode;
+
+ if (rcar_rst_read_mode_pins(&mode))
+ return;
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
@@ -148,8 +151,8 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
cpg->data.clks = clks;
cpg->data.clk_num = num_clks;
- config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)];
- plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)];
+ config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)];
+ plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)];
for (i = 0; i < num_clks; ++i) {
const char *name;
@@ -173,10 +176,3 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
}
CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
r8a7779_cpg_clocks_init);
-
-void __init r8a7779_clocks_init(u32 mode)
-{
- cpg_mode = mode;
-
- of_clk_init(NULL);
-}
diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c
index 00e6aba4b9c0..f39519edc645 100644
--- a/drivers/clk/renesas/clk-rcar-gen2.c
+++ b/drivers/clk/renesas/clk-rcar-gen2.c
@@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
struct rcar_gen2_cpg {
struct clk_onecell_data data;
@@ -364,6 +365,23 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
4, 0, table, &cpg->lock);
}
+/*
+ * Reset register definitions.
+ */
+#define MODEMR 0xe6160060
+
+static u32 __init rcar_gen2_read_mode_pins(void)
+{
+ void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+ u32 mode;
+
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+
+ return mode;
+}
+
static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
{
const struct cpg_pll_config *config;
@@ -372,6 +390,13 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
unsigned int i;
int num_clks;
+ if (rcar_rst_read_mode_pins(&cpg_mode)) {
+ /* Backward-compatibility with old DT */
+ pr_warn("%s: failed to obtain mode pins from RST\n",
+ np->full_name);
+ cpg_mode = rcar_gen2_read_mode_pins();
+ }
+
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
pr_err("%s: failed to count clocks\n", __func__);
@@ -420,10 +445,3 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
}
CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
rcar_gen2_cpg_clocks_init);
-
-void __init rcar_gen2_clocks_init(u32 mode)
-{
- cpg_mode = mode;
-
- of_clk_init(NULL);
-}
diff --git a/drivers/clk/renesas/r8a7743-cpg-mssr.c b/drivers/clk/renesas/r8a7743-cpg-mssr.c
new file mode 100644
index 000000000000..6dc0b3082aa6
--- /dev/null
+++ b/drivers/clk/renesas/r8a7743-cpg-mssr.c
@@ -0,0 +1,270 @@
+/*
+ * r8a7743 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7743_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7743_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7743_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("lb", R8A7743_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
+ DEF_BASE("sdh", R8A7743_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7743_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7743_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("zg", R8A7743_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7743_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7743_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7743_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7743_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("p", R8A7743_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7743_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7743_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7743_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7743_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7743_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7743_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7743_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7743_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7743_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7743_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7743_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7743_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7743_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7743_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7743_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7743_CLK_P),
+ DEF_MOD("3dg", 112, R8A7743_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7743_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7743_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7743_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7743_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7743_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7743_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7743_CLK_ZS),
+ DEF_MOD("vsp1-sy", 131, R8A7743_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7743_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7743_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7743_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7743_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7743_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7743_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7743_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7743_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7743_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7743_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7743_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7743_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7743_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7743_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7743_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7743_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7743_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7743_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7743_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7743_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7743_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7743_CLK_HP),
+ DEF_MOD("irqc", 407, R8A7743_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7743_CLK_ZS),
+ DEF_MOD("audio-dmac1", 501, R8A7743_CLK_HP),
+ DEF_MOD("audio-dmac0", 502, R8A7743_CLK_HP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7743_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7743_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7743_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7743_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7743_CLK_P),
+ DEF_MOD("scif4", 715, R8A7743_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7743_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7743_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7743_CLK_P),
+ DEF_MOD("scif2", 719, R8A7743_CLK_P),
+ DEF_MOD("scif1", 720, R8A7743_CLK_P),
+ DEF_MOD("scif0", 721, R8A7743_CLK_P),
+ DEF_MOD("du1", 723, R8A7743_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7743_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7743_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7743_CLK_ZX),
+ DEF_MOD("vin2", 809, R8A7743_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7743_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7743_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7743_CLK_HP),
+ DEF_MOD("ether", 813, R8A7743_CLK_P),
+ DEF_MOD("sata1", 814, R8A7743_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7743_CLK_ZS),
+ DEF_MOD("gpio7", 904, R8A7743_CLK_CP),
+ DEF_MOD("gpio6", 905, R8A7743_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7743_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7743_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7743_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7743_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7743_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7743_CLK_CP),
+ DEF_MOD("can1", 915, R8A7743_CLK_P),
+ DEF_MOD("can0", 916, R8A7743_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7743_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7743_CLK_HP),
+ DEF_MOD("iicdvfs", 926, R8A7743_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7743_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7743_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7743_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7743_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7743_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7743_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7743_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7743_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7743_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7743_CLK_MP),
+};
+
+static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x172/2 x208/2 x106
+ * 0 0 1 15 x172/2 x208/2 x88
+ * 0 1 0 20 x130/2 x156/2 x80
+ * 0 1 1 20 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult */
+ { 1, 208, 106, },
+ { 1, 208, 88, },
+ { 1, 156, 80, },
+ { 1, 156, 66, },
+ { 2, 240, 122, },
+ { 2, 240, 102, },
+ { 2, 208, 106, },
+ { 2, 208, 88, },
+};
+
+static int __init r8a7743_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7743_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7743_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7743_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7743_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7743_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7743_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7743_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7743_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c
new file mode 100644
index 000000000000..2f15ba786c3b
--- /dev/null
+++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c
@@ -0,0 +1,259 @@
+/*
+ * r8a7745 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7745_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7745_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("lb", R8A7745_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
+ DEF_BASE("sdh", R8A7745_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7745_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7745_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7745_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A7745_CLK_Z2, CLK_PLL0, 1, 1),
+ DEF_FIXED("zg", R8A7745_CLK_ZG, CLK_PLL1, 6, 1),
+ DEF_FIXED("zx", R8A7745_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7745_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7745_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7745_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("p", R8A7745_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7745_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cp", R8A7745_CLK_CP, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7745_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7745_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7745_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7745_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7745_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cpex", R8A7745_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7745_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7745_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7745_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7745_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7745_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7745_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7745_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7745_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7745_CLK_P),
+ DEF_MOD("3dg", 112, R8A7745_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7745_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7745_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7745_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7745_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7745_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7745_CLK_CP),
+ DEF_MOD("vsp1du0", 128, R8A7745_CLK_ZS),
+ DEF_MOD("vsp1-sy", 131, R8A7745_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7745_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7745_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7745_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7745_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7745_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7745_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7745_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7745_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7745_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7745_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7745_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7745_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7745_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7745_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7745_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7745_CLK_HP),
+ DEF_MOD("iic1", 323, R8A7745_CLK_HP),
+ DEF_MOD("cmt1", 329, R8A7745_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7745_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7745_CLK_HP),
+ DEF_MOD("irqc", 407, R8A7745_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7745_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A7745_CLK_HP),
+ DEF_MOD("pwm", 523, R8A7745_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7745_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7745_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7745_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7745_CLK_P),
+ DEF_MOD("scif4", 715, R8A7745_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7745_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7745_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7745_CLK_P),
+ DEF_MOD("scif2", 719, R8A7745_CLK_P),
+ DEF_MOD("scif1", 720, R8A7745_CLK_P),
+ DEF_MOD("scif0", 721, R8A7745_CLK_P),
+ DEF_MOD("du0", 724, R8A7745_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX),
+ DEF_MOD("vin1", 810, R8A7745_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7745_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7745_CLK_HP),
+ DEF_MOD("ether", 813, R8A7745_CLK_P),
+ DEF_MOD("gpio6", 905, R8A7745_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7745_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7745_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7745_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7745_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7745_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7745_CLK_CP),
+ DEF_MOD("can1", 915, R8A7745_CLK_P),
+ DEF_MOD("can0", 916, R8A7745_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7745_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7745_CLK_HP),
+ DEF_MOD("i2c4", 927, R8A7745_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7745_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7745_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7745_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7745_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7745_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7745_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7745_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7745_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7745_CLK_MP),
+};
+
+static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *2
+ *---------------------------------------------------
+ * 0 0 0 15 x200/3 x208/2 x106
+ * 0 0 1 15 x200/3 x208/2 x88
+ * 0 1 0 20 x150/3 x156/2 x80
+ * 0 1 1 20 x150/3 x156/2 x66
+ * 1 0 0 26 / 2 x230/3 x240/2 x122
+ * 1 0 1 26 / 2 x230/3 x240/2 x102
+ * 1 1 0 30 / 2 x200/3 x208/2 x106
+ * 1 1 1 30 / 2 x200/3 x208/2 x88
+ *
+ * *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult PLL0 mult */
+ { 1, 208, 106, 200 },
+ { 1, 208, 88, 200 },
+ { 1, 156, 80, 150 },
+ { 1, 156, 66, 150 },
+ { 2, 240, 122, 230 },
+ { 2, 240, 102, 230 },
+ { 2, 208, 106, 200 },
+ { 2, 208, 88, 200 },
+};
+
+static int __init r8a7745_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7745_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7745_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7745_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7745_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7745_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7745_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7745_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7745_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
index f255e451e8ca..50698a7d9074 100644
--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
@@ -97,7 +98,7 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
- DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250),
+ DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
@@ -311,7 +312,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
static int __init r8a7795_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
- u32 cpg_mode = rcar_gen3_read_mode_pins();
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
if (!cpg_pll_config->extal_div) {
diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c
index eb347ed265f2..7d298c57a3e0 100644
--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c
@@ -16,6 +16,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
@@ -102,6 +103,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1),
DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_DIV6P1("csi0", R8A7796_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+
DEF_DIV6_RO("osc", R8A7796_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
@@ -109,6 +112,14 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
};
static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
+ DEF_MOD("scif5", 202, R8A7796_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A7796_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A7796_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A7796_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A7796_CLK_S3D4),
+ DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S0D3),
+ DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S0D3),
+ DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3),
DEF_MOD("cmt3", 300, R8A7796_CLK_R),
DEF_MOD("cmt2", 301, R8A7796_CLK_R),
DEF_MOD("cmt1", 302, R8A7796_CLK_R),
@@ -120,7 +131,47 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
DEF_MOD("sdif0", 314, R8A7796_CLK_SD0),
DEF_MOD("rwdt0", 402, R8A7796_CLK_R),
DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1),
+ DEF_MOD("drif7", 508, R8A7796_CLK_S3D2),
+ DEF_MOD("drif6", 509, R8A7796_CLK_S3D2),
+ DEF_MOD("drif5", 510, R8A7796_CLK_S3D2),
+ DEF_MOD("drif4", 511, R8A7796_CLK_S3D2),
+ DEF_MOD("drif3", 512, R8A7796_CLK_S3D2),
+ DEF_MOD("drif2", 513, R8A7796_CLK_S3D2),
+ DEF_MOD("drif1", 514, R8A7796_CLK_S3D2),
+ DEF_MOD("drif0", 515, R8A7796_CLK_S3D2),
+ DEF_MOD("hscif4", 516, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A7796_CLK_S3D1),
DEF_MOD("thermal", 522, R8A7796_CLK_CP),
+ DEF_MOD("fcpvd2", 601, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvd1", 602, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvb0", 607, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpci0", 617, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpcs", 619, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd2", 621, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A7796_CLK_S0D2),
+ DEF_MOD("vspb", 626, R8A7796_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A7796_CLK_S0D1),
+ DEF_MOD("csi20", 714, R8A7796_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A7796_CLK_CSI0),
+ DEF_MOD("du2", 722, R8A7796_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A7796_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A7796_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A7796_CLK_S2D1),
+ DEF_MOD("vin7", 804, R8A7796_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A7796_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A7796_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A7796_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A7796_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A7796_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A7796_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A7796_CLK_S0D2),
DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6),
DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4),
DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4),
@@ -130,6 +181,13 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
DEF_MOD("gpio2", 910, R8A7796_CLK_S3D4),
DEF_MOD("gpio1", 911, R8A7796_CLK_S3D4),
DEF_MOD("gpio0", 912, R8A7796_CLK_S3D4),
+ DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c4", 927, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A7796_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A7796_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A7796_CLK_S3D2),
};
static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
@@ -190,7 +248,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
static int __init r8a7796_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
- u32 cpg_mode = rcar_gen3_read_mode_pins();
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
if (!cpg_pll_config->extal_div) {
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c
new file mode 100644
index 000000000000..123b1e622179
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,371 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * 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 = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_pll0_div __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car
+ * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+ * now as there's no generic multiplier clock implementation and
+ * we currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ div = cpg_pll0_div;
+ if (!mult) {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div, u32 mode)
+{
+ cpg_pll_config = config;
+ cpg_pll0_div = pll0_div;
+ cpg_mode = mode;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h
new file mode 100644
index 000000000000..9eba07ff8b11
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,43 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+ unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div, u32 mode);
+
+#endif
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
index bb4f2f9a8c2f..742f6dc7c156 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.c
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -98,7 +98,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw)
u32 val, sd_fc;
unsigned int i;
- val = clk_readl(clock->reg);
+ val = readl(clock->reg);
sd_fc = val & CPG_SD_FC_MASK;
for (i = 0; i < clock->div_num; i++)
@@ -111,7 +111,7 @@ static int cpg_sd_clock_enable(struct clk_hw *hw)
val &= ~(CPG_SD_STP_MASK);
val |= clock->div_table[i].val & CPG_SD_STP_MASK;
- clk_writel(val, clock->reg);
+ writel(val, clock->reg);
return 0;
}
@@ -120,14 +120,14 @@ static void cpg_sd_clock_disable(struct clk_hw *hw)
{
struct sd_clock *clock = to_sd_clock(hw);
- clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
+ writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
}
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
{
struct sd_clock *clock = to_sd_clock(hw);
- return !(clk_readl(clock->reg) & CPG_SD_STP_MASK);
+ return !(readl(clock->reg) & CPG_SD_STP_MASK);
}
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
@@ -138,7 +138,7 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
u32 val, sd_fc;
unsigned int i;
- val = clk_readl(clock->reg);
+ val = readl(clock->reg);
sd_fc = val & CPG_SD_FC_MASK;
for (i = 0; i < clock->div_num; i++)
@@ -189,10 +189,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
if (i >= clock->div_num)
return -EINVAL;
- val = clk_readl(clock->reg);
+ val = readl(clock->reg);
val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
- clk_writel(val, clock->reg);
+ writel(val, clock->reg);
return 0;
}
@@ -333,23 +333,6 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
__clk_get_name(parent), 0, mult, div);
}
-/*
- * Reset register definitions.
- */
-#define MODEMR 0xe6160060
-
-u32 __init rcar_gen3_read_mode_pins(void)
-{
- void __iomem *modemr = ioremap_nocache(MODEMR, 4);
- u32 mode;
-
- BUG_ON(!modemr);
- mode = ioread32(modemr);
- iounmap(modemr);
-
- return mode;
-}
-
int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
unsigned int clk_extalr)
{
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index f699085147d1..f788f481dd42 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -33,7 +33,6 @@ struct rcar_gen3_cpg_pll_config {
#define CPG_RCKCR 0x240
-u32 rcar_gen3_read_mode_pins(void);
struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
struct clk **clks, void __iomem *base);
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index e1365e7491ae..8359ce75db7a 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -33,9 +33,9 @@
#include "clk-div6.h"
#ifdef DEBUG
-#define WARN_DEBUG(x) do { } while (0)
-#else
#define WARN_DEBUG(x) WARN_ON(x)
+#else
+#define WARN_DEBUG(x) do { } while (0)
#endif
@@ -146,12 +146,12 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
enable ? "ON" : "OFF");
spin_lock_irqsave(&priv->mstp_lock, flags);
- value = clk_readl(priv->base + SMSTPCR(reg));
+ value = readl(priv->base + SMSTPCR(reg));
if (enable)
value &= ~bitmask;
else
value |= bitmask;
- clk_writel(value, priv->base + SMSTPCR(reg));
+ writel(value, priv->base + SMSTPCR(reg));
spin_unlock_irqrestore(&priv->mstp_lock, flags);
@@ -159,8 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
return 0;
for (i = 1000; i > 0; --i) {
- if (!(clk_readl(priv->base + MSTPSR(reg)) &
- bitmask))
+ if (!(readl(priv->base + MSTPSR(reg)) & bitmask))
break;
cpu_relax();
}
@@ -190,7 +189,7 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
struct cpg_mssr_priv *priv = clock->priv;
u32 value;
- value = clk_readl(priv->base + MSTPSR(clock->index / 32));
+ value = readl(priv->base + MSTPSR(clock->index / 32));
return !(value & BIT(clock->index % 32));
}
@@ -309,7 +308,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
return;
fail:
- dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,",
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
core->name, PTR_ERR(clk));
}
@@ -377,7 +376,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
return;
fail:
- dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,",
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
mod->name, PTR_ERR(clk));
kfree(clock);
}
@@ -503,6 +502,18 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
}
static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_ARCH_R8A7743
+ {
+ .compatible = "renesas,r8a7743-cpg-mssr",
+ .data = &r8a7743_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_ARCH_R8A7745
+ {
+ .compatible = "renesas,r8a7745-cpg-mssr",
+ .data = &r8a7745_cpg_mssr_info,
+ },
+#endif
#ifdef CONFIG_ARCH_R8A7795
{
.compatible = "renesas,r8a7795-cpg-mssr",
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
index ee7edfaf1408..4bb7a80c6469 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.h
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -130,6 +130,8 @@ struct cpg_mssr_info {
struct clk **clks, void __iomem *base);
};
+extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
#endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index b5f2c8ed12e1..16e098c36f90 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o
obj-y += clk-ddr.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
+obj-y += clk-rk1108.o
obj-y += clk-rk3036.o
obj-y += clk-rk3188.o
obj-y += clk-rk3228.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 05b3d73bfefa..0e09684d43a5 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -124,9 +124,18 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
struct clk_notifier_data *ndata)
{
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
+ const struct rockchip_cpuclk_rate_table *rate;
unsigned long alt_prate, alt_div;
unsigned long flags;
+ /* check validity of the new rate */
+ rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for cpuclk\n",
+ __func__, ndata->new_rate);
+ return -EINVAL;
+ }
+
alt_prate = clk_get_rate(cpuclk->alt_parent);
spin_lock_irqsave(cpuclk->lock, flags);
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 9c1373e81683..6ed605776abd 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -319,7 +319,8 @@ static void rockchip_rk3036_pll_init(struct clk_hw *hw)
if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
- rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+ rate->dsmpd != cur.dsmpd ||
+ (!cur.dsmpd && (rate->frac != cur.frac))) {
struct clk *parent = clk_get_parent(hw->clk);
if (!parent) {
@@ -795,7 +796,8 @@ static void rockchip_rk3399_pll_init(struct clk_hw *hw)
if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
- rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+ rate->dsmpd != cur.dsmpd ||
+ (!cur.dsmpd && (rate->frac != cur.frac))) {
struct clk *parent = clk_get_parent(hw->clk);
if (!parent) {
diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c
new file mode 100644
index 000000000000..92750d798e5d
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk1108.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ * Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/syscore_ops.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include "clk.h"
+
+#define RK1108_GRF_SOC_STATUS0 0x480
+
+enum rk1108_plls {
+ apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+#define RK1108_DIV_CORE_MASK 0xf
+#define RK1108_DIV_CORE_SHIFT 4
+
+#define RK1108_CLKSEL0(_core_peri_div) \
+ { \
+ .reg = RK1108_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
+ RK1108_DIV_CORE_SHIFT) \
+ }
+
+#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \
+ { \
+ .prate = _prate, \
+ .divs = { \
+ RK1108_CLKSEL0(_core_peri_div), \
+ }, \
+ }
+
+static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
+ RK1108_CPUCLK_RATE(816000000, 4),
+ RK1108_CPUCLK_RATE(600000000, 4),
+ RK1108_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
+ .core_reg = RK1108_CLKSEL_CON(0),
+ .div_core_shift = 0,
+ .div_core_mask = 0x1f,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
+ .mux_core_shift = 8,
+ .mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin24m"};
+PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" };
+PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" };
+PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
+PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" };
+PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" };
+PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" };
+PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" };
+PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
+PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
+PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" };
+PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" };
+PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" };
+PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" };
+PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" };
+
+static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
+ RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
+ [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
+ RK1108_PLL_CON(11), 8, 31, 0, NULL),
+ [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
+ RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+ MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+ MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+ MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+ MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
+ RK1108_MISC_CON, 13, 2, MFLAGS),
+ MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
+ RK1108_MISC_CON, 15, 2, MFLAGS),
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ /* PD_CORE */
+ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 0, GFLAGS),
+ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK1108_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK1108_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(11), 0, GFLAGS),
+ GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(11), 1, GFLAGS),
+
+ /* PD_RKVENC */
+
+ /* PD_RKVDEC */
+
+ /* PD_PMU_wrapper */
+ COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(8), 12, GFLAGS),
+ GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 0, GFLAGS),
+ GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 1, GFLAGS),
+ GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 2, GFLAGS),
+ GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 3, GFLAGS),
+ GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 4, GFLAGS),
+ GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(10), 6, GFLAGS),
+ COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(8), 15, GFLAGS),
+ COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(8), 14, GFLAGS),
+ GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(8), 13, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+ COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(6), 0, GFLAGS),
+ GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
+ RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(7), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
+ RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(7), 3, GFLAGS),
+
+ INVERTER(0, "pclk_vip", "ext_vip",
+ RK1108_CLKSEL_CON(31), 8, IFLAGS),
+ GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(18), 10, GFLAGS),
+ GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(6), 5, GFLAGS),
+ GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(6), 4, GFLAGS),
+ COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
+ RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 5
+ */
+
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(2), 0, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(8), 0,
+ RK1108_CLKGATE_CON(2), 1, GFLAGS,
+ &rk1108_i2s0_fracmux),
+ GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
+ RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+ RK1108_CLKGATE_CON(2), 3, GFLAGS),
+
+ COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(2), 4, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(9), 0,
+ RK2928_CLKGATE_CON(2), 5, GFLAGS,
+ &rk1108_i2s1_fracmux),
+ GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 6, GFLAGS),
+
+ COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 8, GFLAGS),
+ COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(10), 0,
+ RK1108_CLKGATE_CON(2), 9, GFLAGS,
+ &rk1108_i2s2_fracmux),
+ GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+ RK1108_CLKGATE_CON(2), 10, GFLAGS),
+
+ /* PD_BUS */
+ GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 2, GFLAGS),
+ COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
+ RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
+ RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(1), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
+ RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 4, GFLAGS),
+
+ COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 1, GFLAGS),
+ COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 3, GFLAGS),
+ COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 5, GFLAGS),
+
+ COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(16), 0,
+ RK1108_CLKGATE_CON(3), 2, GFLAGS,
+ &rk1108_uart0_fracmux),
+ COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(17), 0,
+ RK1108_CLKGATE_CON(3), 4, GFLAGS,
+ &rk1108_uart1_fracmux),
+ COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(18), 0,
+ RK1108_CLKGATE_CON(3), 6, GFLAGS,
+ &rk1108_uart2_fracmux),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 10, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 11, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 12, GFLAGS),
+
+ COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 7, GFLAGS),
+ COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 8, GFLAGS),
+ COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 9, GFLAGS),
+ GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 1, GFLAGS),
+ GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 2, GFLAGS),
+ COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+ RK1108_CLKGATE_CON(3), 10, GFLAGS),
+ GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 6, GFLAGS),
+ GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 3, GFLAGS),
+ GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 7, GFLAGS),
+ GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 8, GFLAGS),
+ GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(13), 9, GFLAGS),
+
+ GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(14), 0, GFLAGS),
+
+ GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
+ RK1108_CLKGATE_CON(12), 2, GFLAGS),
+ GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 3, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 1, GFLAGS),
+
+ /* PD_DDR */
+ GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 8, GFLAGS),
+ GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 9, GFLAGS),
+ GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+ DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK1108_CLKGATE_CON(10), 9, GFLAGS),
+ GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 4, GFLAGS),
+ GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 5, GFLAGS),
+ GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(12), 6, GFLAGS),
+ GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(0), 11, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 6
+ */
+
+ /* PD_PERI */
+ COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
+ RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 5, GFLAGS),
+ GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(15), 13, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
+ RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 4, GFLAGS),
+ GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(15), 12, GFLAGS),
+
+ GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(4), 1, GFLAGS),
+ GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+ RK1108_CLKGATE_CON(4), 2, GFLAGS),
+ COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
+ RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(15), 11, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK1108_CLKGATE_CON(5), 0, GFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+ RK1108_CLKGATE_CON(5), 2, GFLAGS),
+ DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+ RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+ RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+ RK1108_CLKGATE_CON(5), 1, GFLAGS),
+ DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+ RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+
+ COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK1108_CLKGATE_CON(5), 3, GFLAGS),
+ GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+
+ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
+ RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK1108_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+
+ COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
+ RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+ RK1108_CLKGATE_CON(4), 10, GFLAGS),
+ MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
+ RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+ GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
+ GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
+ GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1),
+
+ MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1),
+};
+
+static const char *const rk1108_critical_clocks[] __initconst = {
+ "aclk_core",
+ "aclk_bus_src_gpll",
+ "aclk_periph",
+ "hclk_periph",
+ "pclk_periph",
+};
+
+static void __init rk1108_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ iounmap(reg_base);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk1108_pll_clks,
+ ARRAY_SIZE(rk1108_pll_clks),
+ RK1108_GRF_SOC_STATUS0);
+ rockchip_clk_register_branches(ctx, rk1108_clk_branches,
+ ARRAY_SIZE(rk1108_clk_branches));
+ rockchip_clk_protect_critical(rk1108_critical_clocks,
+ ARRAY_SIZE(rk1108_critical_clocks));
+
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+ mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+ &rk1108_cpuclk_data, rk1108_cpuclk_rates,
+ ARRAY_SIZE(rk1108_cpuclk_rates));
+
+ rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index d0e722a0e8cf..062ef4960244 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
RK3066_PLL_RATE( 504000000, 1, 84, 4),
RK3066_PLL_RATE( 456000000, 1, 76, 4),
RK3066_PLL_RATE( 408000000, 1, 68, 4),
+ RK3066_PLL_RATE( 400000000, 3, 100, 2),
RK3066_PLL_RATE( 384000000, 2, 128, 4),
RK3066_PLL_RATE( 360000000, 1, 60, 4),
RK3066_PLL_RATE( 312000000, 1, 52, 4),
@@ -306,14 +307,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(0), 2, GFLAGS),
- GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+ GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 3, GFLAGS),
GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 6, GFLAGS),
- GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+ GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 5, GFLAGS),
- GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
+ GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(0), 4, GFLAGS),
COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
@@ -323,12 +324,12 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
RK2928_CLKGATE_CON(1), 4, GFLAGS),
- GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+ GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0,
RK2928_CLKGATE_CON(2), 1, GFLAGS),
- COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0,
+ COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0,
RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 2, GFLAGS),
- COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0,
+ COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0,
RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 3, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 8387c7a40bda..3490887b0579 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
- RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0),
RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
@@ -87,12 +87,13 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
- RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0),
RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+ RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0),
RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
@@ -410,11 +411,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(6), 6, GFLAGS),
- GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED,
+ GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0,
RK3399_CLKGATE_CON(13), 12, GFLAGS),
- GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED,
+ GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0,
RK3399_CLKGATE_CON(13), 12, GFLAGS),
- MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED,
+ MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0,
RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
@@ -498,7 +499,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
RK3399_CLKGATE_CON(14), 10, GFLAGS),
GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(14), 11, GFLAGS),
- GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0,
RK3399_CLKGATE_CON(0), 7, GFLAGS),
/* big core */
@@ -539,7 +540,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(14), 2, GFLAGS),
- GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0,
RK3399_CLKGATE_CON(1), 7, GFLAGS),
/* gmac */
@@ -675,18 +676,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(18), 10, GFLAGS),
- GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+ GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0,
RK3399_CLKGATE_CON(18), 12, GFLAGS),
GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(18), 15, GFLAGS),
GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
RK3399_CLKGATE_CON(19), 2, GFLAGS),
- GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0,
RK3399_CLKGATE_CON(4), 11, GFLAGS),
- GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0,
RK3399_CLKGATE_CON(3), 5, GFLAGS),
- GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0,
RK3399_CLKGATE_CON(3), 6, GFLAGS),
/* cci */
@@ -966,7 +967,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
- GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+ GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS),
GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
@@ -980,7 +981,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
/* pclk_perilp0 gates */
- GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+ GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS),
/* crypto */
COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
@@ -1382,8 +1383,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
/* clk_test */
/* clk_test_pre is controlled by CRU_MISC_CON[3] */
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
- RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
- RK3368_CLKGATE_CON(13), 11, GFLAGS),
+ RK3399_CLKSEL_CON(58), 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 11, GFLAGS),
/* ddrc */
GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 1653edd792a5..d67eecc4ade9 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -34,6 +34,21 @@ struct clk;
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
+/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RK1108_PLL_CON(x) ((x) * 0x4)
+#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
+#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
+#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
+#define RK1108_GLB_SRST_FST 0x1c0
+#define RK1108_GLB_SRST_SND 0x1c4
+#define RK1108_MISC_CON 0x1cc
+#define RK1108_SDMMC_CON0 0x1d8
+#define RK1108_SDMMC_CON1 0x1dc
+#define RK1108_SDIO_CON0 0x1e0
+#define RK1108_SDIO_CON1 0x1e4
+#define RK1108_EMMC_CON0 0x1e8
+#define RK1108_EMMC_CON1 0x1ec
+
#define RK2928_PLL_CON(x) ((x) * 0x4)
#define RK2928_MODE_CON 0x40
#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index ea1608682d7f..f096bd7df40c 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -543,7 +543,7 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
static const struct samsung_gate_clock top_gate_clks[] __initconst = {
/* ENABLE_ACLK_TOP */
GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
- ENABLE_ACLK_TOP, 30, 0, 0),
+ ENABLE_ACLK_TOP, 30, CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
"div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
29, CLK_IGNORE_UNUSED, 0),
@@ -555,25 +555,25 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
ENABLE_ACLK_TOP, 24,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
ENABLE_ACLK_TOP, 23,
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
ENABLE_ACLK_TOP, 22,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_PERIS_66, "aclk_peris_66", "div_aclk_peris_66_b",
ENABLE_ACLK_TOP, 21,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_MSCL_400, "aclk_mscl_400", "div_aclk_mscl_400",
ENABLE_ACLK_TOP, 19,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_FSYS_200, "aclk_fsys_200", "div_aclk_fsys_200",
ENABLE_ACLK_TOP, 18,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_GSCL_111, "aclk_gscl_111", "div_aclk_gscl_111",
ENABLE_ACLK_TOP, 15,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_GSCL_333, "aclk_gscl_333", "div_aclk_gscl_333",
ENABLE_ACLK_TOP, 14,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -582,7 +582,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_CAM1_400, "aclk_cam1_400", "div_aclk_cam1_400",
ENABLE_ACLK_TOP, 12,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_CAM1_552, "aclk_cam1_552", "div_aclk_cam1_552",
ENABLE_ACLK_TOP, 11,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -591,7 +591,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_CAM0_400, "aclk_cam0_400", "div_aclk_cam0_400",
ENABLE_ACLK_TOP, 9,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_CAM0_552, "aclk_cam0_552", "div_aclk_cam0_552",
ENABLE_ACLK_TOP, 8,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -600,19 +600,19 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_ISP_400, "aclk_isp_400", "div_aclk_isp_400",
ENABLE_ACLK_TOP, 6,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_HEVC_400, "aclk_hevc_400", "div_aclk_hevc_400",
ENABLE_ACLK_TOP, 5,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_MFC_400, "aclk_mfc_400", "div_aclk_mfc_400",
ENABLE_ACLK_TOP, 3,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_G2D_266, "aclk_g2d_266", "div_aclk_g2d_266",
ENABLE_ACLK_TOP, 2,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_G2D_400, "aclk_g2d_400", "div_aclk_g2d_400",
ENABLE_ACLK_TOP, 0,
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
/* ENABLE_SCLK_TOP_MSCL */
GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
@@ -1385,7 +1385,7 @@ static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
ENABLE_ACLK_MIF3, 1,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_CPIF_200, "aclk_cpif_200", "div_aclk_cpif_200",
ENABLE_ACLK_MIF3, 0,
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
@@ -1929,7 +1929,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peris, "samsung,exynos5433-cmu-peris",
/* list of all parent clock list */
PNAME(mout_sclk_ufs_mphy_user_p) = { "oscclk", "sclk_ufs_mphy", };
-PNAME(mout_aclk_fsys_200_user_p) = { "oscclk", "div_aclk_fsys_200", };
+PNAME(mout_aclk_fsys_200_user_p) = { "oscclk", "aclk_fsys_200", };
PNAME(mout_sclk_pcie_100_user_p) = { "oscclk", "sclk_pcie_100_fsys",};
PNAME(mout_sclk_ufsunipro_user_p) = { "oscclk", "sclk_ufsunipro_fsys",};
PNAME(mout_sclk_mmc2_user_p) = { "oscclk", "sclk_mmc2_fsys", };
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index a485f3b284b9..918ba3164da9 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -329,8 +329,10 @@ static void __init st_of_flexgen_setup(struct device_node *np)
return;
parents = flexgen_get_parents(np, &num_parents);
- if (!parents)
+ if (!parents) {
+ iounmap(reg);
return;
+ }
match = of_match_node(flexgen_of_match, np);
if (match) {
@@ -394,6 +396,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
return;
err:
+ iounmap(reg);
if (clk_data)
kfree(clk_data->clks);
kfree(clk_data);
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 254d9526c018..8454c6e3dd65 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -35,17 +35,14 @@ config SUNXI_CCU_NK
config SUNXI_CCU_NKM
bool
- select RATIONAL
select SUNXI_CCU_GATE
config SUNXI_CCU_NKMP
bool
- select RATIONAL
select SUNXI_CCU_GATE
config SUNXI_CCU_NM
bool
- select RATIONAL
select SUNXI_CCU_FRAC
select SUNXI_CCU_GATE
@@ -56,6 +53,17 @@ config SUNXI_CCU_MP
# SoC Drivers
+config SUN50I_A64_CCU
+ bool "Support for the Allwinner A64 CCU"
+ select SUNXI_CCU_DIV
+ select SUNXI_CCU_NK
+ select SUNXI_CCU_NKM
+ select SUNXI_CCU_NKMP
+ select SUNXI_CCU_NM
+ select SUNXI_CCU_MP
+ select SUNXI_CCU_PHASE
+ default ARM64 && ARCH_SUNXI
+
config SUN6I_A31_CCU
bool "Support for the Allwinner A31/A31s CCU"
select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 106cba27c331..24fbc6e5deb8 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o
obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o
# SoC support
+obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o
obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o
obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
new file mode 100644
index 000000000000..e3c084cc6da5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. 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/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_phase.h"
+
+#include "ccu-sun50i-a64.h"
+
+static struct ccu_nkmp pll_cpux_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT(8, 5),
+ .k = _SUNXI_CCU_MULT(4, 2),
+ .m = _SUNXI_CCU_DIV(0, 2),
+ .p = _SUNXI_CCU_DIV_MAX(16, 2, 4),
+ .common = {
+ .reg = 0x000,
+ .hw.init = CLK_HW_INIT("pll-cpux",
+ "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
+ * the base (2x, 4x and 8x), and one variable divider (the one true
+ * pll audio).
+ *
+ * We don't have any need for the variable divider for now, so we just
+ * hardcode it to match with the clock names
+ */
+#define SUN50I_A64_PLL_AUDIO_REG 0x008
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
+ "osc24M", 0x008,
+ 8, 7, /* N */
+ 0, 5, /* M */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0",
+ "osc24M", 0x010,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
+ "osc24M", 0x018,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0",
+ "osc24M", 0x020,
+ 8, 5, /* N */
+ 4, 2, /* K */
+ 0, 2, /* M */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static struct ccu_nk pll_periph0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT(8, 5),
+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x028,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
+ &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+ },
+};
+
+static struct ccu_nk pll_periph1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT(8, 5),
+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x02c,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
+ &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+ },
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1",
+ "osc24M", 0x030,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
+ "osc24M", 0x038,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+/*
+ * The output function can be changed to something more complex that
+ * we do not handle yet.
+ *
+ * Hardcode the mode so that we don't fall in that case.
+ */
+#define SUN50I_A64_PLL_MIPI_REG 0x040
+
+static struct ccu_nkm pll_mipi_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT(8, 4),
+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+ .m = _SUNXI_CCU_DIV(0, 4),
+ .common = {
+ .reg = 0x040,
+ .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0",
+ &ccu_nkm_ops, CLK_SET_RATE_UNGATE),
+ },
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic",
+ "osc24M", 0x044,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
+ "osc24M", 0x048,
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
+ "osc24M", 0x04c,
+ 8, 7, /* N */
+ 0, 2, /* M */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
+
+static const char * const cpux_parents[] = { "osc32k", "osc24M",
+ "pll-cpux", "pll-cpux" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+ 0x050, 16, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc32k", "osc24M",
+ "axi", "pll-periph0" };
+static struct ccu_div ahb1_clk = {
+ .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
+
+ .mux = {
+ .shift = 12,
+ .width = 2,
+
+ .variable_prediv = {
+ .index = 3,
+ .shift = 6,
+ .width = 2,
+ },
+ },
+
+ .common = {
+ .reg = 0x054,
+ .features = CCU_FEATURE_VARIABLE_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS("ahb1",
+ ahb1_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static struct clk_div_table apb1_div_table[] = {
+ { .val = 0, .div = 2 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 8 },
+ { /* Sentinel */ },
+};
+static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
+ 0x054, 8, 2, apb1_div_table, 0);
+
+static const char * const apb2_parents[] = { "osc32k", "osc24M",
+ "pll-periph0-2x",
+ "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+ 0, 5, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const ahb2_parents[] = { "ahb1", "pll-periph0" };
+static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = {
+ { .index = 1, .div = 2 },
+};
+static struct ccu_mux ahb2_clk = {
+ .mux = {
+ .shift = 0,
+ .width = 1,
+ .fixed_predivs = ahb2_fixed_predivs,
+ .n_predivs = ARRAY_SIZE(ahb2_fixed_predivs),
+ },
+
+ .common = {
+ .reg = 0x05c,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS("ahb2",
+ ahb2_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1",
+ 0x060, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1",
+ 0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1",
+ 0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1",
+ 0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1",
+ 0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1",
+ 0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1",
+ 0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1",
+ 0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2",
+ 0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1",
+ 0x060, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1",
+ 0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1",
+ 0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1",
+ 0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1",
+ 0x060, BIT(23), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1",
+ 0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2",
+ 0x060, BIT(25), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1",
+ 0x060, BIT(28), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb2",
+ 0x060, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1",
+ 0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1",
+ 0x064, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1",
+ 0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1",
+ 0x064, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1",
+ 0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1",
+ 0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1",
+ 0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1",
+ 0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1",
+ 0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1",
+ 0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1",
+ 0x068, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1",
+ 0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1",
+ 0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1",
+ 0x068, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1",
+ 0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1",
+ 0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1",
+ 0x068, BIT(14), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2",
+ 0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2",
+ 0x06c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2",
+ 0x06c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2",
+ 0x06c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2",
+ 0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2",
+ 0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2",
+ 0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2",
+ 0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2",
+ 0x06c, BIT(20), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1",
+ 0x070, BIT(7), 0);
+
+static struct clk_div_table ths_div_table[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 6 },
+};
+static const char * const ths_parents[] = { "osc24M" };
+static struct ccu_div ths_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0x074,
+ .hw.init = CLK_HW_INIT_PARENTS("ths",
+ ths_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0",
+ "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 4, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_default_parents, 0x09c,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
+ "pll-audio-2x", "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
+ 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
+ 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
+ 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+ 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
+ 0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M",
+ 0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic",
+ 0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M",
+ 0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M",
+ 0x0cc, BIT(16), 0);
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "usb-ohci0",
+ 0x0cc, BIT(17), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
+ 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram",
+ 0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram",
+ 0x100, BIT(1), 0);
+static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram",
+ 0x100, BIT(2), 0);
+static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram",
+ 0x100, BIT(3), 0);
+
+static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
+ 0x104, 0, 4, 24, 3, BIT(31), 0);
+
+static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
+static const u8 tcon0_table[] = { 0, 2, };
+static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
+ tcon0_table, 0x118, 24, 3, BIT(31),
+ CLK_SET_RATE_PARENT);
+
+static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
+static const u8 tcon1_table[] = { 0, 2, };
+static struct ccu_div tcon1_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV(0, 4),
+ .mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table),
+ .common = {
+ .reg = 0x11c,
+ .hw.init = CLK_HW_INIT_PARENTS("tcon1",
+ tcon1_parents,
+ &ccu_div_ops,
+ CLK_SET_RATE_PARENT),
+ },
+};
+
+static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
+ 0x124, 0, 4, 24, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M",
+ 0x130, BIT(31), 0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
+ 0x134, 16, 4, 24, 3, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
+ 0x134, 0, 5, 8, 3, BIT(15), 0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
+ 0x13c, 16, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio",
+ 0x140, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x",
+ 0x140, BIT(30), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
+ 0x144, BIT(31), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
+ 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M",
+ 0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+ 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
+static const u8 dsi_dphy_table[] = { 0, 2, };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
+ dsi_dphy_parents, dsi_dphy_table,
+ 0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
+ 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+/* Fixed Factor clocks */
+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0);
+
+/* We hardcode the divider to 4 for now */
+static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
+ "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+ "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+ "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
+ "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
+ "pll-periph0", 1, 2, 0);
+static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
+ "pll-periph1", 1, 2, 0);
+static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
+ "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_a64_ccu_clks[] = {
+ &pll_cpux_clk.common,
+ &pll_audio_base_clk.common,
+ &pll_video0_clk.common,
+ &pll_ve_clk.common,
+ &pll_ddr0_clk.common,
+ &pll_periph0_clk.common,
+ &pll_periph1_clk.common,
+ &pll_video1_clk.common,
+ &pll_gpu_clk.common,
+ &pll_mipi_clk.common,
+ &pll_hsic_clk.common,
+ &pll_de_clk.common,
+ &pll_ddr1_clk.common,
+ &cpux_clk.common,
+ &axi_clk.common,
+ &ahb1_clk.common,
+ &apb1_clk.common,
+ &apb2_clk.common,
+ &ahb2_clk.common,
+ &bus_mipi_dsi_clk.common,
+ &bus_ce_clk.common,
+ &bus_dma_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_nand_clk.common,
+ &bus_dram_clk.common,
+ &bus_emac_clk.common,
+ &bus_ts_clk.common,
+ &bus_hstimer_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &bus_otg_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ehci1_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ohci1_clk.common,
+ &bus_ve_clk.common,
+ &bus_tcon0_clk.common,
+ &bus_tcon1_clk.common,
+ &bus_deinterlace_clk.common,
+ &bus_csi_clk.common,
+ &bus_hdmi_clk.common,
+ &bus_de_clk.common,
+ &bus_gpu_clk.common,
+ &bus_msgbox_clk.common,
+ &bus_spinlock_clk.common,
+ &bus_codec_clk.common,
+ &bus_spdif_clk.common,
+ &bus_pio_clk.common,
+ &bus_ths_clk.common,
+ &bus_i2s0_clk.common,
+ &bus_i2s1_clk.common,
+ &bus_i2s2_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_i2c2_clk.common,
+ &bus_scr_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_uart3_clk.common,
+ &bus_uart4_clk.common,
+ &bus_dbg_clk.common,
+ &ths_clk.common,
+ &nand_clk.common,
+ &mmc0_clk.common,
+ &mmc1_clk.common,
+ &mmc2_clk.common,
+ &ts_clk.common,
+ &ce_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &i2s0_clk.common,
+ &i2s1_clk.common,
+ &i2s2_clk.common,
+ &spdif_clk.common,
+ &usb_phy0_clk.common,
+ &usb_phy1_clk.common,
+ &usb_hsic_clk.common,
+ &usb_hsic_12m_clk.common,
+ &usb_ohci0_clk.common,
+ &usb_ohci1_clk.common,
+ &dram_clk.common,
+ &dram_ve_clk.common,
+ &dram_csi_clk.common,
+ &dram_deinterlace_clk.common,
+ &dram_ts_clk.common,
+ &de_clk.common,
+ &tcon0_clk.common,
+ &tcon1_clk.common,
+ &deinterlace_clk.common,
+ &csi_misc_clk.common,
+ &csi_sclk_clk.common,
+ &csi_mclk_clk.common,
+ &ve_clk.common,
+ &ac_dig_clk.common,
+ &ac_dig_4x_clk.common,
+ &avs_clk.common,
+ &hdmi_clk.common,
+ &hdmi_ddc_clk.common,
+ &mbus_clk.common,
+ &dsi_dphy_clk.common,
+ &gpu_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_a64_hw_clks = {
+ .hws = {
+ [CLK_OSC_12M] = &osc12M_clk.hw,
+ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
+ [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
+ [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
+ [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
+ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
+ [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
+ [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
+ [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
+ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
+ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
+ [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw,
+ [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw,
+ [CLK_PLL_DE] = &pll_de_clk.common.hw,
+ [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw,
+ [CLK_CPUX] = &cpux_clk.common.hw,
+ [CLK_AXI] = &axi_clk.common.hw,
+ [CLK_AHB1] = &ahb1_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_APB2] = &apb2_clk.common.hw,
+ [CLK_AHB2] = &ahb2_clk.common.hw,
+ [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
+ [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
+ [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
+ [CLK_BUS_TS] = &bus_ts_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
+ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
+ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
+ [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw,
+ [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw,
+ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
+ [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
+ [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,
+ [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,
+ [CLK_BUS_CODEC] = &bus_codec_clk.common.hw,
+ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
+ [CLK_BUS_PIO] = &bus_pio_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
+ [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
+ [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
+ [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
+ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
+ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
+ [CLK_BUS_SCR] = &bus_scr_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_THS] = &ths_clk.common.hw,
+ [CLK_NAND] = &nand_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC2] = &mmc2_clk.common.hw,
+ [CLK_TS] = &ts_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_I2S0] = &i2s0_clk.common.hw,
+ [CLK_I2S1] = &i2s1_clk.common.hw,
+ [CLK_I2S2] = &i2s2_clk.common.hw,
+ [CLK_SPDIF] = &spdif_clk.common.hw,
+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
+ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
+ [CLK_USB_HSIC] = &usb_hsic_clk.common.hw,
+ [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
+ [CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
+ [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw,
+ [CLK_DRAM_TS] = &dram_ts_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_TCON0] = &tcon0_clk.common.hw,
+ [CLK_TCON1] = &tcon1_clk.common.hw,
+ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
+ [CLK_CSI_MISC] = &csi_misc_clk.common.hw,
+ [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw,
+ [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_AC_DIG] = &ac_dig_clk.common.hw,
+ [CLK_AC_DIG_4X] = &ac_dig_4x_clk.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_HDMI] = &hdmi_clk.common.hw,
+ [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.common.hw,
+ [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw,
+ [CLK_GPU] = &gpu_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_a64_ccu_resets[] = {
+ [RST_USB_PHY0] = { 0x0cc, BIT(0) },
+ [RST_USB_PHY1] = { 0x0cc, BIT(1) },
+ [RST_USB_HSIC] = { 0x0cc, BIT(2) },
+
+ [RST_DRAM] = { 0x0f4, BIT(31) },
+ [RST_MBUS] = { 0x0fc, BIT(31) },
+
+ [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) },
+ [RST_BUS_CE] = { 0x2c0, BIT(5) },
+ [RST_BUS_DMA] = { 0x2c0, BIT(6) },
+ [RST_BUS_MMC0] = { 0x2c0, BIT(8) },
+ [RST_BUS_MMC1] = { 0x2c0, BIT(9) },
+ [RST_BUS_MMC2] = { 0x2c0, BIT(10) },
+ [RST_BUS_NAND] = { 0x2c0, BIT(13) },
+ [RST_BUS_DRAM] = { 0x2c0, BIT(14) },
+ [RST_BUS_EMAC] = { 0x2c0, BIT(17) },
+ [RST_BUS_TS] = { 0x2c0, BIT(18) },
+ [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },
+ [RST_BUS_SPI0] = { 0x2c0, BIT(20) },
+ [RST_BUS_SPI1] = { 0x2c0, BIT(21) },
+ [RST_BUS_OTG] = { 0x2c0, BIT(23) },
+ [RST_BUS_EHCI0] = { 0x2c0, BIT(24) },
+ [RST_BUS_EHCI1] = { 0x2c0, BIT(25) },
+ [RST_BUS_OHCI0] = { 0x2c0, BIT(28) },
+ [RST_BUS_OHCI1] = { 0x2c0, BIT(29) },
+
+ [RST_BUS_VE] = { 0x2c4, BIT(0) },
+ [RST_BUS_TCON0] = { 0x2c4, BIT(3) },
+ [RST_BUS_TCON1] = { 0x2c4, BIT(4) },
+ [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) },
+ [RST_BUS_CSI] = { 0x2c4, BIT(8) },
+ [RST_BUS_HDMI0] = { 0x2c4, BIT(10) },
+ [RST_BUS_HDMI1] = { 0x2c4, BIT(11) },
+ [RST_BUS_DE] = { 0x2c4, BIT(12) },
+ [RST_BUS_GPU] = { 0x2c4, BIT(20) },
+ [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) },
+ [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) },
+ [RST_BUS_DBG] = { 0x2c4, BIT(31) },
+
+ [RST_BUS_LVDS] = { 0x2c8, BIT(0) },
+
+ [RST_BUS_CODEC] = { 0x2d0, BIT(0) },
+ [RST_BUS_SPDIF] = { 0x2d0, BIT(1) },
+ [RST_BUS_THS] = { 0x2d0, BIT(8) },
+ [RST_BUS_I2S0] = { 0x2d0, BIT(12) },
+ [RST_BUS_I2S1] = { 0x2d0, BIT(13) },
+ [RST_BUS_I2S2] = { 0x2d0, BIT(14) },
+
+ [RST_BUS_I2C0] = { 0x2d8, BIT(0) },
+ [RST_BUS_I2C1] = { 0x2d8, BIT(1) },
+ [RST_BUS_I2C2] = { 0x2d8, BIT(2) },
+ [RST_BUS_SCR] = { 0x2d8, BIT(5) },
+ [RST_BUS_UART0] = { 0x2d8, BIT(16) },
+ [RST_BUS_UART1] = { 0x2d8, BIT(17) },
+ [RST_BUS_UART2] = { 0x2d8, BIT(18) },
+ [RST_BUS_UART3] = { 0x2d8, BIT(19) },
+ [RST_BUS_UART4] = { 0x2d8, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
+ .ccu_clks = sun50i_a64_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_a64_ccu_clks),
+
+ .hw_clks = &sun50i_a64_hw_clks,
+
+ .resets = sun50i_a64_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets),
+};
+
+static int sun50i_a64_ccu_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *reg;
+ u32 val;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ /* Force the PLL-Audio-1x divider to 4 */
+ val = readl(reg + SUN50I_A64_PLL_AUDIO_REG);
+ val &= ~GENMASK(19, 16);
+ writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG);
+
+ writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
+
+ return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+}
+
+static const struct of_device_id sun50i_a64_ccu_ids[] = {
+ { .compatible = "allwinner,sun50i-a64-ccu" },
+ { }
+};
+
+static struct platform_driver sun50i_a64_ccu_driver = {
+ .probe = sun50i_a64_ccu_probe,
+ .driver = {
+ .name = "sun50i-a64-ccu",
+ .of_match_table = sun50i_a64_ccu_ids,
+ },
+};
+builtin_platform_driver(sun50i_a64_ccu_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
new file mode 100644
index 000000000000..9b3cd24b78d2
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef _CCU_SUN50I_A64_H_
+#define _CCU_SUN50I_A64_H_
+
+#include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun50i-a64-ccu.h>
+
+#define CLK_OSC_12M 0
+#define CLK_PLL_CPUX 1
+#define CLK_PLL_AUDIO_BASE 2
+#define CLK_PLL_AUDIO 3
+#define CLK_PLL_AUDIO_2X 4
+#define CLK_PLL_AUDIO_4X 5
+#define CLK_PLL_AUDIO_8X 6
+#define CLK_PLL_VIDEO0 7
+#define CLK_PLL_VIDEO0_2X 8
+#define CLK_PLL_VE 9
+#define CLK_PLL_DDR0 10
+#define CLK_PLL_PERIPH0 11
+#define CLK_PLL_PERIPH0_2X 12
+#define CLK_PLL_PERIPH1 13
+#define CLK_PLL_PERIPH1_2X 14
+#define CLK_PLL_VIDEO1 15
+#define CLK_PLL_GPU 16
+#define CLK_PLL_MIPI 17
+#define CLK_PLL_HSIC 18
+#define CLK_PLL_DE 19
+#define CLK_PLL_DDR1 20
+#define CLK_CPUX 21
+#define CLK_AXI 22
+#define CLK_APB 23
+#define CLK_AHB1 24
+#define CLK_APB1 25
+#define CLK_APB2 26
+#define CLK_AHB2 27
+
+/* All the bus gates are exported */
+
+/* The first bunch of module clocks are exported */
+
+#define CLK_USB_OHCI0_12M 90
+
+#define CLK_USB_OHCI1_12M 92
+
+#define CLK_DRAM 94
+
+/* All the DRAM gates are exported */
+
+/* Some more module clocks are exported */
+
+#define CLK_MBUS 112
+
+/* And the DSI and GPU module clock is exported */
+
+#define CLK_NUMBER (CLK_GPU + 1)
+
+#endif /* _CCU_SUN50I_A64_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
index 2646d980087b..5c6d37bdf247 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
@@ -344,10 +344,10 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
"pll-audio-2x", "pll-audio" };
static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
- 0x0b0, 16, 2, BIT(31), 0);
+ 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
- 0x0b4, 16, 2, BIT(31), 0);
+ 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
/* TODO: the parent for most of the USB clocks is not known */
static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
@@ -415,7 +415,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio",
- 0x140, BIT(31), 0);
+ 0x140, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
0x144, BIT(31), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 4d70590f05e3..21c427d86f28 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -394,16 +394,16 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
"pll-audio-2x", "pll-audio" };
static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
- 0x0b0, 16, 2, BIT(31), 0);
+ 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
- 0x0b4, 16, 2, BIT(31), 0);
+ 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
- 0x0b8, 16, 2, BIT(31), 0);
+ 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
- 0x0c0, 0, 4, BIT(31), 0);
+ 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
0x0cc, BIT(8), 0);
@@ -466,7 +466,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
0x13c, 16, 3, BIT(31), 0);
static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio",
- 0x140, BIT(31), 0);
+ 0x140, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
0x144, BIT(31), 0);
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index 34c338832c0d..06540f7cf41c 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -20,7 +20,7 @@
#include "ccu_mux.h"
/**
- * struct _ccu_div - Internal divider description
+ * struct ccu_div_internal - Internal divider description
* @shift: Bit offset of the divider in its register
* @width: Width of the divider field in its register
* @max: Maximum value allowed for that divider. This is the
@@ -36,7 +36,7 @@
* It is basically a wrapper around the clk_divider functions
* arguments.
*/
-struct _ccu_div {
+struct ccu_div_internal {
u8 shift;
u8 width;
@@ -78,7 +78,7 @@ struct _ccu_div {
struct ccu_div {
u32 enable;
- struct _ccu_div div;
+ struct ccu_div_internal div;
struct ccu_mux_internal mux;
struct ccu_common common;
};
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c
index 5c4b10cd15b5..8b5eb7756bf7 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.c
+++ b/drivers/clk/sunxi-ng/ccu_frac.c
@@ -14,7 +14,7 @@
#include "ccu_frac.h"
bool ccu_frac_helper_is_enabled(struct ccu_common *common,
- struct _ccu_frac *cf)
+ struct ccu_frac_internal *cf)
{
if (!(common->features & CCU_FEATURE_FRACTIONAL))
return false;
@@ -23,7 +23,7 @@ bool ccu_frac_helper_is_enabled(struct ccu_common *common,
}
void ccu_frac_helper_enable(struct ccu_common *common,
- struct _ccu_frac *cf)
+ struct ccu_frac_internal *cf)
{
unsigned long flags;
u32 reg;
@@ -38,7 +38,7 @@ void ccu_frac_helper_enable(struct ccu_common *common,
}
void ccu_frac_helper_disable(struct ccu_common *common,
- struct _ccu_frac *cf)
+ struct ccu_frac_internal *cf)
{
unsigned long flags;
u32 reg;
@@ -53,7 +53,7 @@ void ccu_frac_helper_disable(struct ccu_common *common,
}
bool ccu_frac_helper_has_rate(struct ccu_common *common,
- struct _ccu_frac *cf,
+ struct ccu_frac_internal *cf,
unsigned long rate)
{
if (!(common->features & CCU_FEATURE_FRACTIONAL))
@@ -63,7 +63,7 @@ bool ccu_frac_helper_has_rate(struct ccu_common *common,
}
unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
- struct _ccu_frac *cf)
+ struct ccu_frac_internal *cf)
{
u32 reg;
@@ -84,7 +84,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
}
int ccu_frac_helper_set_rate(struct ccu_common *common,
- struct _ccu_frac *cf,
+ struct ccu_frac_internal *cf,
unsigned long rate)
{
unsigned long flags;
diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h
index e4c670b1cdfe..7b1ee380156f 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.h
+++ b/drivers/clk/sunxi-ng/ccu_frac.h
@@ -18,7 +18,7 @@
#include "ccu_common.h"
-struct _ccu_frac {
+struct ccu_frac_internal {
u32 enable;
u32 select;
@@ -33,21 +33,21 @@ struct _ccu_frac {
}
bool ccu_frac_helper_is_enabled(struct ccu_common *common,
- struct _ccu_frac *cf);
+ struct ccu_frac_internal *cf);
void ccu_frac_helper_enable(struct ccu_common *common,
- struct _ccu_frac *cf);
+ struct ccu_frac_internal *cf);
void ccu_frac_helper_disable(struct ccu_common *common,
- struct _ccu_frac *cf);
+ struct ccu_frac_internal *cf);
bool ccu_frac_helper_has_rate(struct ccu_common *common,
- struct _ccu_frac *cf,
+ struct ccu_frac_internal *cf,
unsigned long rate);
unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
- struct _ccu_frac *cf);
+ struct ccu_frac_internal *cf);
int ccu_frac_helper_set_rate(struct ccu_common *common,
- struct _ccu_frac *cf,
+ struct ccu_frac_internal *cf,
unsigned long rate);
#endif /* _CCU_FRAC_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index edf9215ea8cc..915625e97d98 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -29,8 +29,8 @@
struct ccu_mp {
u32 enable;
- struct _ccu_div m;
- struct _ccu_div p;
+ struct ccu_div_internal m;
+ struct ccu_div_internal p;
struct ccu_mux_internal mux;
struct ccu_common common;
};
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index 010e9424691d..678b6cb49f01 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -13,10 +13,23 @@
#include "ccu_gate.h"
#include "ccu_mult.h"
+struct _ccu_mult {
+ unsigned long mult, min, max;
+};
+
static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
- unsigned int max_n, unsigned int *n)
+ struct _ccu_mult *mult)
{
- *n = rate / parent;
+ int _mult;
+
+ _mult = rate / parent;
+ if (_mult < mult->min)
+ _mult = mult->min;
+
+ if (_mult > mult->max)
+ _mult = mult->max;
+
+ mult->mult = _mult;
}
static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
@@ -25,11 +38,13 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
void *data)
{
struct ccu_mult *cm = data;
- unsigned int n;
+ struct _ccu_mult _cm;
- ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+ _cm.min = 1;
+ _cm.max = 1 << cm->mult.width;
+ ccu_mult_find_best(parent_rate, rate, &_cm);
- return parent_rate * n;
+ return parent_rate * _cm.mult;
}
static void ccu_mult_disable(struct clk_hw *hw)
@@ -83,21 +98,23 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_mult *cm = hw_to_ccu_mult(hw);
+ struct _ccu_mult _cm;
unsigned long flags;
- unsigned int n;
u32 reg;
ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
&parent_rate);
- ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+ _cm.min = cm->mult.min;
+ _cm.max = 1 << cm->mult.width;
+ ccu_mult_find_best(parent_rate, rate, &_cm);
spin_lock_irqsave(cm->common.lock, flags);
reg = readl(cm->common.base + cm->common.reg);
reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift);
- writel(reg | ((n - 1) << cm->mult.shift),
+ writel(reg | ((_cm.mult - 1) << cm->mult.shift),
cm->common.base + cm->common.reg);
spin_unlock_irqrestore(cm->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h
index 5d2c8dc14073..c1a2134bdc71 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.h
+++ b/drivers/clk/sunxi-ng/ccu_mult.h
@@ -4,21 +4,26 @@
#include "ccu_common.h"
#include "ccu_mux.h"
-struct _ccu_mult {
+struct ccu_mult_internal {
u8 shift;
u8 width;
+ u8 min;
};
-#define _SUNXI_CCU_MULT(_shift, _width) \
- { \
- .shift = _shift, \
- .width = _width, \
+#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min) \
+ { \
+ .shift = _shift, \
+ .width = _width, \
+ .min = _min, \
}
+#define _SUNXI_CCU_MULT(_shift, _width) \
+ _SUNXI_CCU_MULT_MIN(_shift, _width, 1)
+
struct ccu_mult {
u32 enable;
- struct _ccu_mult mult;
+ struct ccu_mult_internal mult;
struct ccu_mux_internal mux;
struct ccu_common common;
};
diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
index d6fafb397489..eaf0fdf78d2b 100644
--- a/drivers/clk/sunxi-ng/ccu_nk.c
+++ b/drivers/clk/sunxi-ng/ccu_nk.c
@@ -9,21 +9,24 @@
*/
#include <linux/clk-provider.h>
-#include <linux/rational.h>
#include "ccu_gate.h"
#include "ccu_nk.h"
+struct _ccu_nk {
+ unsigned long n, min_n, max_n;
+ unsigned long k, min_k, max_k;
+};
+
static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
- unsigned int max_n, unsigned int max_k,
- unsigned int *n, unsigned int *k)
+ struct _ccu_nk *nk)
{
unsigned long best_rate = 0;
unsigned int best_k = 0, best_n = 0;
unsigned int _k, _n;
- for (_k = 1; _k <= max_k; _k++) {
- for (_n = 1; _n <= max_n; _n++) {
+ for (_k = nk->min_k; _k <= nk->max_k; _k++) {
+ for (_n = nk->min_n; _n <= nk->max_n; _n++) {
unsigned long tmp_rate = parent * _n * _k;
if (tmp_rate > rate)
@@ -37,8 +40,8 @@ static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
}
}
- *k = best_k;
- *n = best_n;
+ nk->k = best_k;
+ nk->n = best_n;
}
static void ccu_nk_disable(struct clk_hw *hw)
@@ -89,16 +92,19 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct ccu_nk *nk = hw_to_ccu_nk(hw);
- unsigned int n, k;
+ struct _ccu_nk _nk;
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nk->fixed_post_div;
- ccu_nk_find_best(*parent_rate, rate,
- 1 << nk->n.width, 1 << nk->k.width,
- &n, &k);
+ _nk.min_n = nk->n.min;
+ _nk.max_n = 1 << nk->n.width;
+ _nk.min_k = nk->k.min;
+ _nk.max_k = 1 << nk->k.width;
+
+ ccu_nk_find_best(*parent_rate, rate, &_nk);
+ rate = *parent_rate * _nk.n * _nk.k;
- rate = *parent_rate * n * k;
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate = rate / nk->fixed_post_div;
@@ -110,15 +116,18 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct ccu_nk *nk = hw_to_ccu_nk(hw);
unsigned long flags;
- unsigned int n, k;
+ struct _ccu_nk _nk;
u32 reg;
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate = rate * nk->fixed_post_div;
- ccu_nk_find_best(parent_rate, rate,
- 1 << nk->n.width, 1 << nk->k.width,
- &n, &k);
+ _nk.min_n = nk->n.min;
+ _nk.max_n = 1 << nk->n.width;
+ _nk.min_k = nk->k.min;
+ _nk.max_k = 1 << nk->k.width;
+
+ ccu_nk_find_best(parent_rate, rate, &_nk);
spin_lock_irqsave(nk->common.lock, flags);
@@ -126,7 +135,7 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift);
reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift);
- writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift),
+ writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift),
nk->common.base + nk->common.reg);
spin_unlock_irqrestore(nk->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h
index 4b52da0c29fe..437836b80696 100644
--- a/drivers/clk/sunxi-ng/ccu_nk.h
+++ b/drivers/clk/sunxi-ng/ccu_nk.h
@@ -30,8 +30,8 @@ struct ccu_nk {
u32 enable;
u32 lock;
- struct _ccu_mult n;
- struct _ccu_mult k;
+ struct ccu_mult_internal n;
+ struct ccu_mult_internal k;
unsigned int fixed_post_div;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 059fdc3b4f96..9b840a47a94d 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -9,15 +9,14 @@
*/
#include <linux/clk-provider.h>
-#include <linux/rational.h>
#include "ccu_gate.h"
#include "ccu_nkm.h"
struct _ccu_nkm {
- unsigned long n, max_n;
- unsigned long k, max_k;
- unsigned long m, max_m;
+ unsigned long n, min_n, max_n;
+ unsigned long k, min_k, max_k;
+ unsigned long m, min_m, max_m;
};
static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
@@ -27,22 +26,22 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
unsigned long best_n = 0, best_k = 0, best_m = 0;
unsigned long _n, _k, _m;
- for (_k = 1; _k <= nkm->max_k; _k++) {
- unsigned long tmp_rate;
-
- rational_best_approximation(rate / _k, parent,
- nkm->max_n, nkm->max_m, &_n, &_m);
-
- tmp_rate = parent * _n * _k / _m;
-
- if (tmp_rate > rate)
- continue;
-
- if ((rate - tmp_rate) < (rate - best_rate)) {
- best_rate = tmp_rate;
- best_n = _n;
- best_k = _k;
- best_m = _m;
+ for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
+ for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
+ for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+ unsigned long tmp_rate;
+
+ tmp_rate = parent * _n * _k / _m;
+
+ if (tmp_rate > rate)
+ continue;
+ if ((rate - tmp_rate) < (rate - best_rate)) {
+ best_rate = tmp_rate;
+ best_n = _n;
+ best_k = _k;
+ best_m = _m;
+ }
+ }
}
}
@@ -101,8 +100,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
struct ccu_nkm *nkm = data;
struct _ccu_nkm _nkm;
+ _nkm.min_n = nkm->n.min;
_nkm.max_n = 1 << nkm->n.width;
+ _nkm.min_k = nkm->k.min;
_nkm.max_k = 1 << nkm->k.width;
+ _nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
ccu_nkm_find_best(parent_rate, rate, &_nkm);
@@ -127,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
+ _nkm.min_n = nkm->n.min;
_nkm.max_n = 1 << nkm->n.width;
+ _nkm.min_k = nkm->k.min;
_nkm.max_k = 1 << nkm->k.width;
+ _nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
ccu_nkm_find_best(parent_rate, rate, &_nkm);
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 35493fddd8ab..34580894f4d1 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -29,9 +29,9 @@ struct ccu_nkm {
u32 enable;
u32 lock;
- struct _ccu_mult n;
- struct _ccu_mult k;
- struct _ccu_div m;
+ struct ccu_mult_internal n;
+ struct ccu_mult_internal k;
+ struct ccu_div_internal m;
struct ccu_mux_internal mux;
struct ccu_common common;
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
index 9769dee99511..684c42da3ebb 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.c
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -9,16 +9,15 @@
*/
#include <linux/clk-provider.h>
-#include <linux/rational.h>
#include "ccu_gate.h"
#include "ccu_nkmp.h"
struct _ccu_nkmp {
- unsigned long n, max_n;
- unsigned long k, max_k;
- unsigned long m, max_m;
- unsigned long p, max_p;
+ unsigned long n, min_n, max_n;
+ unsigned long k, min_k, max_k;
+ unsigned long m, min_m, max_m;
+ unsigned long p, min_p, max_p;
};
static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
@@ -28,25 +27,25 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
unsigned long _n, _k, _m, _p;
- for (_k = 1; _k <= nkmp->max_k; _k++) {
- for (_p = 1; _p <= nkmp->max_p; _p <<= 1) {
- unsigned long tmp_rate;
-
- rational_best_approximation(rate / _k, parent / _p,
- nkmp->max_n, nkmp->max_m,
- &_n, &_m);
-
- tmp_rate = parent * _n * _k / (_m * _p);
-
- if (tmp_rate > rate)
- continue;
-
- if ((rate - tmp_rate) < (rate - best_rate)) {
- best_rate = tmp_rate;
- best_n = _n;
- best_k = _k;
- best_m = _m;
- best_p = _p;
+ for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) {
+ for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) {
+ for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) {
+ for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) {
+ unsigned long tmp_rate;
+
+ tmp_rate = parent * _n * _k / (_m * _p);
+
+ if (tmp_rate > rate)
+ continue;
+
+ if ((rate - tmp_rate) < (rate - best_rate)) {
+ best_rate = tmp_rate;
+ best_n = _n;
+ best_k = _k;
+ best_m = _m;
+ best_p = _p;
+ }
+ }
}
}
}
@@ -108,9 +107,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
struct _ccu_nkmp _nkmp;
+ _nkmp.min_n = nkmp->n.min;
_nkmp.max_n = 1 << nkmp->n.width;
+ _nkmp.min_k = nkmp->k.min;
_nkmp.max_k = 1 << nkmp->k.width;
+ _nkmp.min_m = 1;
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+ _nkmp.min_p = 1;
_nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
@@ -126,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
+ _nkmp.min_n = 1;
_nkmp.max_n = 1 << nkmp->n.width;
+ _nkmp.min_k = 1;
_nkmp.max_k = 1 << nkmp->k.width;
+ _nkmp.min_m = 1;
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+ _nkmp.min_p = 1;
_nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h
index 5adb0c92a614..a82facbc6144 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.h
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.h
@@ -29,10 +29,10 @@ struct ccu_nkmp {
u32 enable;
u32 lock;
- struct _ccu_mult n;
- struct _ccu_mult k;
- struct _ccu_div m;
- struct _ccu_div p;
+ struct ccu_mult_internal n;
+ struct ccu_mult_internal k;
+ struct ccu_div_internal m;
+ struct ccu_div_internal p;
struct ccu_common common;
};
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index b61bdd8c7a7f..c9f3b6c982f0 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -9,12 +9,42 @@
*/
#include <linux/clk-provider.h>
-#include <linux/rational.h>
#include "ccu_frac.h"
#include "ccu_gate.h"
#include "ccu_nm.h"
+struct _ccu_nm {
+ unsigned long n, min_n, max_n;
+ unsigned long m, min_m, max_m;
+};
+
+static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
+ struct _ccu_nm *nm)
+{
+ unsigned long best_rate = 0;
+ unsigned long best_n = 0, best_m = 0;
+ unsigned long _n, _m;
+
+ for (_n = nm->min_n; _n <= nm->max_n; _n++) {
+ for (_m = nm->min_m; _m <= nm->max_m; _m++) {
+ unsigned long tmp_rate = parent * _n / _m;
+
+ if (tmp_rate > rate)
+ continue;
+
+ if ((rate - tmp_rate) < (rate - best_rate)) {
+ best_rate = tmp_rate;
+ best_n = _n;
+ best_m = _m;
+ }
+ }
+ }
+
+ nm->n = best_n;
+ nm->m = best_m;
+}
+
static void ccu_nm_disable(struct clk_hw *hw)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
@@ -61,24 +91,24 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
- unsigned long max_n, max_m;
- unsigned long n, m;
+ struct _ccu_nm _nm;
- max_n = 1 << nm->n.width;
- max_m = nm->m.max ?: 1 << nm->m.width;
+ _nm.min_n = nm->n.min;
+ _nm.max_n = 1 << nm->n.width;
+ _nm.min_m = 1;
+ _nm.max_m = nm->m.max ?: 1 << nm->m.width;
- rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m);
+ ccu_nm_find_best(*parent_rate, rate, &_nm);
- return *parent_rate * n / m;
+ return *parent_rate * _nm.n / _nm.m;
}
static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
+ struct _ccu_nm _nm;
unsigned long flags;
- unsigned long max_n, max_m;
- unsigned long n, m;
u32 reg;
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
@@ -86,10 +116,12 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
else
ccu_frac_helper_disable(&nm->common, &nm->frac);
- max_n = 1 << nm->n.width;
- max_m = nm->m.max ?: 1 << nm->m.width;
+ _nm.min_n = 1;
+ _nm.max_n = 1 << nm->n.width;
+ _nm.min_m = 1;
+ _nm.max_m = nm->m.max ?: 1 << nm->m.width;
- rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m);
+ ccu_nm_find_best(parent_rate, rate, &_nm);
spin_lock_irqsave(nm->common.lock, flags);
@@ -97,7 +129,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift);
reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);
- writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
+ writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift),
nm->common.base + nm->common.reg);
spin_unlock_irqrestore(nm->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
index 0b7bcd33a2df..e87fd186da78 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.h
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -30,9 +30,9 @@ struct ccu_nm {
u32 enable;
u32 lock;
- struct _ccu_mult n;
- struct _ccu_div m;
- struct _ccu_frac frac;
+ struct ccu_mult_internal n;
+ struct ccu_div_internal m;
+ struct ccu_frac_internal frac;
struct ccu_common common;
};
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index e54266cc1c51..4417ae129ac7 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -24,7 +24,7 @@
#include "clk-factors.h"
/**
- * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
* MOD0 rate is calculated as follows
* rate = (parent_rate >> p) / (m + 1);
*/
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
index c205809ba580..ad1c1cc829cb 100644
--- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -20,7 +20,7 @@
#include <linux/cpu.h>
#include <linux/err.h>
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <soc/tegra/fuse.h>
@@ -148,7 +148,6 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
{ .compatible = "nvidia,tegra124-dfll", },
{ },
};
-MODULE_DEVICE_TABLE(of, tegra124_dfll_fcpu_of_match);
static const struct dev_pm_ops tegra124_dfll_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
@@ -164,20 +163,4 @@ static struct platform_driver tegra124_dfll_fcpu_driver = {
.pm = &tegra124_dfll_pm_ops,
},
};
-
-static int __init tegra124_dfll_fcpu_init(void)
-{
- return platform_driver_register(&tegra124_dfll_fcpu_driver);
-}
-module_init(tegra124_dfll_fcpu_init);
-
-static void __exit tegra124_dfll_fcpu_exit(void)
-{
- platform_driver_unregister(&tegra124_dfll_fcpu_driver);
-}
-module_exit(tegra124_dfll_fcpu_exit);
-
-MODULE_DESCRIPTION("Tegra124 DFLL clock source driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Aleksandr Frid <afrid@nvidia.com>");
-MODULE_AUTHOR("Paul Walmsley <pwalmsley@nvidia.com>");
+builtin_platform_driver(tegra124_dfll_fcpu_driver);
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index 624115e82ff9..da9e8e7b5ce5 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -92,19 +92,19 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
/**
* tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
- * @cvb_tables: array of CVB tables
- * @sz: size of the previously mentioned array
+ * @dev: the struct device * for which the OPP table is built
+ * @tables: array of CVB tables
+ * @count: size of the previously mentioned array
* @process_id: process id of the HW module
* @speedo_id: speedo id of the HW module
* @speedo_value: speedo value of the HW module
- * @max_rate: highest safe clock rate
- * @opp_dev: the struct device * for which the OPP table is built
+ * @max_freq: highest safe clock rate
*
* On Tegra, a CVB table encodes the relationship between operating voltage
* and safe maximal frequency for a given module (e.g. GPU or CPU). This
* function calculates the optimal voltage-frequency operating points
* for the given arguments and exports them via the OPP library for the
- * given @opp_dev. Returns a pointer to the struct cvb_table that matched
+ * given @dev. Returns a pointer to the struct cvb_table that matched
* or an ERR_PTR on failure.
*/
const struct cvb_table *
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
index 8831e1a05367..11d8aa3ec186 100644
--- a/drivers/clk/ti/clk-3xxx.c
+++ b/drivers/clk/ti/clk-3xxx.c
@@ -22,13 +22,6 @@
#include "clock.h"
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST 120000000
-
#define OMAP3430ES2_ST_DSS_IDLE_SHIFT 1
#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT 5
#define OMAP3430ES2_ST_SSI_IDLE_SHIFT 8
@@ -546,14 +539,21 @@ void __init omap3_clk_lock_dpll5(void)
struct clk *dpll5_clk;
struct clk *dpll5_m2_clk;
+ /*
+ * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
+ * that can be worked around using specially crafted dpll5 settings
+ * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
+ * host clock rate, its .set_rate handler() will detect that frequency
+ * and use the errata settings.
+ */
dpll5_clk = clk_get(NULL, "dpll5_ck");
- clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+ clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
clk_prepare_enable(dpll5_clk);
- /* Program dpll5_m2_clk divider for no division */
+ /* Program dpll5_m2_clk divider */
dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
clk_prepare_enable(dpll5_m2_clk);
- clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+ clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
clk_disable_unprepare(dpll5_m2_clk);
clk_disable_unprepare(dpll5_clk);
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index bfa17d33ef3b..9fd6043314eb 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -201,7 +201,6 @@ static struct ti_dt_clk dra7xx_clks[] = {
DT_CLK(NULL, "atl_dpll_clk_mux", "atl_dpll_clk_mux"),
DT_CLK(NULL, "atl_gfclk_mux", "atl_gfclk_mux"),
DT_CLK(NULL, "dcan1_sys_clk_mux", "dcan1_sys_clk_mux"),
- DT_CLK(NULL, "gmac_gmii_ref_clk_div", "gmac_gmii_ref_clk_div"),
DT_CLK(NULL, "gmac_rft_clk_mux", "gmac_rft_clk_mux"),
DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"),
DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"),
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index c77333230bdf..45d05339d583 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
@@ -295,31 +295,17 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
return ret;
}
-static int of_dra7_atl_clk_remove(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
-
- return 0;
-}
-
static const struct of_device_id of_dra7_atl_clk_match_tbl[] = {
{ .compatible = "ti,dra7-atl", },
{},
};
-MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
static struct platform_driver dra7_atl_clk_driver = {
.driver = {
.name = "dra7-atl",
+ .suppress_bind_attrs = true,
.of_match_table = of_dra7_atl_clk_match_tbl,
},
.probe = of_dra7_atl_clk_probe,
- .remove = of_dra7_atl_clk_remove,
};
-
-module_platform_driver(dra7_atl_clk_driver);
-
-MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
-MODULE_ALIAS("platform:dra7-atl-clock");
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(dra7_atl_clk_driver);
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 90f3f472ae1c..13c37f48d9d6 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -257,11 +257,20 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
unsigned long parent_rate);
+/*
+ * OMAP3_DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define OMAP3_DPLL5_FREQ_FOR_USBHOST 120000000
+
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
unsigned long parent_rate);
int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate, u8 index);
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
void omap3_clk_lock_dpll5(void);
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 9fc8754a6e61..4b9a419d8e14 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -114,6 +114,18 @@ static const struct clk_ops omap3_dpll_ck_ops = {
.round_rate = &omap2_dpll_round_rate,
};
+static const struct clk_ops omap3_dpll5_ck_ops = {
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap3_dpll_recalc,
+ .set_rate = &omap3_dpll5_set_rate,
+ .set_parent = &omap3_noncore_dpll_set_parent,
+ .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent,
+ .determine_rate = &omap3_noncore_dpll_determine_rate,
+ .round_rate = &omap2_dpll_round_rate,
+};
+
static const struct clk_ops omap3_dpll_per_ck_ops = {
.enable = &omap3_noncore_dpll_enable,
.disable = &omap3_noncore_dpll_disable,
@@ -474,7 +486,12 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
};
- of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
+ if ((of_machine_is_compatible("ti,omap3630") ||
+ of_machine_is_compatible("ti,omap36xx")) &&
+ !strcmp(node->name, "dpll5_ck"))
+ of_ti_dpll_setup(node, &omap3_dpll5_ck_ops, &dd);
+ else
+ of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
}
CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
of_ti_omap3_dpll_setup);
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index 88f2ce81ba55..4cdd28a25584 100644
--- a/drivers/clk/ti/dpll3xxx.c
+++ b/drivers/clk/ti/dpll3xxx.c
@@ -838,3 +838,70 @@ int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
index);
}
+
+/* Apply DM3730 errata sprz319 advisory 2.1. */
+static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct omap3_dpll5_settings {
+ unsigned int rate, m, n;
+ };
+
+ static const struct omap3_dpll5_settings precomputed[] = {
+ /*
+ * From DM3730 errata advisory 2.1, table 35 and 36.
+ * The N value is increased by 1 compared to the tables as the
+ * errata lists register values while last_rounded_field is the
+ * real divider value.
+ */
+ { 12000000, 80, 0 + 1 },
+ { 13000000, 443, 5 + 1 },
+ { 19200000, 50, 0 + 1 },
+ { 26000000, 443, 11 + 1 },
+ { 38400000, 25, 0 + 1 }
+ };
+
+ const struct omap3_dpll5_settings *d;
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ struct dpll_data *dd;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
+ if (parent_rate == precomputed[i].rate)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(precomputed))
+ return false;
+
+ d = &precomputed[i];
+
+ /* Update the M, N and rounded rate values and program the DPLL. */
+ dd = clk->dpll_data;
+ dd->last_rounded_m = d->m;
+ dd->last_rounded_n = d->n;
+ dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
+ omap3_noncore_dpll_program(clk, 0);
+
+ return true;
+}
+
+/**
+ * omap3_dpll5_set_rate - set rate for omap3 dpll5
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
+ * the DPLL is used for USB host (detected through the requested rate).
+ */
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
+ if (omap3_dpll5_apply_errata(hw, parent_rate))
+ return 0;
+ }
+
+ return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index f27b360329ca..665d1d65a90e 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -1,8 +1,11 @@
obj-y += clk-uniphier-core.o
+
+obj-y += clk-uniphier-cpugear.o
obj-y += clk-uniphier-fixed-factor.o
obj-y += clk-uniphier-fixed-rate.o
obj-y += clk-uniphier-gate.o
obj-y += clk-uniphier-mux.o
+
obj-y += clk-uniphier-sys.o
obj-y += clk-uniphier-mio.o
obj-y += clk-uniphier-peri.o
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index 26c53f7963a4..0007218ce6a0 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -27,6 +27,9 @@ static struct clk_hw *uniphier_clk_register(struct device *dev,
const struct uniphier_clk_data *data)
{
switch (data->type) {
+ case UNIPHIER_CLK_TYPE_CPUGEAR:
+ return uniphier_clk_register_cpugear(dev, regmap, data->name,
+ &data->data.cpugear);
case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
return uniphier_clk_register_fixed_factor(dev, data->name,
&data->data.factor);
diff --git a/drivers/clk/uniphier/clk-uniphier-cpugear.c b/drivers/clk/uniphier/clk-uniphier-cpugear.c
new file mode 100644
index 000000000000..9bff26e0cbb0
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-cpugear.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ * Author: 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-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_CLK_CPUGEAR_STAT 0 /* status */
+#define UNIPHIER_CLK_CPUGEAR_SET 4 /* set */
+#define UNIPHIER_CLK_CPUGEAR_UPD 8 /* update */
+#define UNIPHIER_CLK_CPUGEAR_UPD_BIT BIT(0)
+
+struct uniphier_clk_cpugear {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ unsigned int regbase;
+ unsigned int mask;
+};
+
+#define to_uniphier_clk_cpugear(_hw) \
+ container_of(_hw, struct uniphier_clk_cpugear, hw)
+
+static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+ int ret;
+ unsigned int val;
+
+ ret = regmap_write_bits(gear->regmap,
+ gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+ gear->mask, index);
+ if (ret)
+ return ret;
+
+ ret = regmap_write_bits(gear->regmap,
+ gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+ UNIPHIER_CLK_CPUGEAR_UPD_BIT,
+ UNIPHIER_CLK_CPUGEAR_UPD_BIT);
+ if (ret)
+ return ret;
+
+ return regmap_read_poll_timeout(gear->regmap,
+ gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
+ val, !(val & UNIPHIER_CLK_CPUGEAR_UPD_BIT),
+ 0, 1);
+}
+
+static u8 uniphier_clk_cpugear_get_parent(struct clk_hw *hw)
+{
+ struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+ int num_parents = clk_hw_get_num_parents(hw);
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(gear->regmap,
+ gear->regbase + UNIPHIER_CLK_CPUGEAR_STAT, &val);
+ if (ret)
+ return ret;
+
+ val &= gear->mask;
+
+ return val < num_parents ? val : -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_cpugear_ops = {
+ .determine_rate = __clk_mux_determine_rate,
+ .set_parent = uniphier_clk_cpugear_set_parent,
+ .get_parent = uniphier_clk_cpugear_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+ struct regmap *regmap,
+ const char *name,
+ const struct uniphier_clk_cpugear_data *data)
+{
+ struct uniphier_clk_cpugear *gear;
+ struct clk_init_data init;
+ int ret;
+
+ gear = devm_kzalloc(dev, sizeof(*gear), GFP_KERNEL);
+ if (!gear)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &uniphier_clk_cpugear_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = data->parent_names;
+ init.num_parents = data->num_parents,
+
+ gear->regmap = regmap;
+ gear->regbase = data->regbase;
+ gear->mask = data->mask;
+ gear->hw.init = &init;
+
+ ret = devm_clk_hw_register(dev, &gear->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &gear->hw;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c
index 5d029991047d..d049316c1c0f 100644
--- a/drivers/clk/uniphier/clk-uniphier-sys.c
+++ b/drivers/clk/uniphier/clk-uniphier-sys.c
@@ -125,16 +125,35 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
};
const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = {
+ UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 392, 5), /* 1960 MHz */
+ UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1), /* 1600 MHz */
UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1), /* 2000 MHz */
+ UNIPHIER_CLK_FACTOR("vspll", -1, "ref", 80, 1), /* 2000 MHz */
UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC, MIO */
UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25),
+ /* CPU gears */
+ UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+ UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8),
+ UNIPHIER_CLK_DIV3("spll", 3, 4, 8),
+ /* Note: both gear1 and gear4 are spll/4. This is not a bug. */
+ UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+ "cpll/2", "spll/4", "cpll/3", "spll/3",
+ "spll/4", "spll/8", "cpll/4", "cpll/8"),
+ UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+ "mpll/2", "spll/4", "mpll/3", "spll/3",
+ "spll/4", "spll/8", "mpll/4", "mpll/8"),
{ /* sentinel */ }
};
const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
+ UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 88, 1), /* ARM: 2200 MHz */
+ UNIPHIER_CLK_FACTOR("gppll", -1, "ref", 52, 1), /* Mali: 1300 MHz */
+ UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1), /* Codec: 1600 MHz */
UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1), /* 2000 MHz */
+ UNIPHIER_CLK_FACTOR("s2pll", -1, "ref", 88, 1), /* IPP: 2200 MHz */
+ UNIPHIER_CLK_FACTOR("vppll", -1, "ref", 504, 5), /* 2520 MHz */
UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
UNIPHIER_LD20_SYS_CLK_SD,
@@ -147,5 +166,18 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14),
UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12),
UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13),
+ /* CPU gears */
+ UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+ UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8),
+ UNIPHIER_CLK_DIV4("s2pll", 2, 3, 4, 8),
+ UNIPHIER_CLK_CPUGEAR("cpu-ca72", 32, 0x8000, 0xf, 8,
+ "cpll/2", "spll/2", "cpll/3", "spll/3",
+ "spll/4", "spll/8", "cpll/4", "cpll/8"),
+ UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+ "cpll/2", "spll/2", "cpll/3", "spll/3",
+ "spll/4", "spll/8", "cpll/4", "cpll/8"),
+ UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+ "s2pll/2", "spll/2", "s2pll/3", "spll/3",
+ "spll/4", "spll/8", "s2pll/4", "s2pll/8"),
{ /* sentinel */ }
};
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 0244dba1f4cf..01c16ecec48f 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -20,15 +20,24 @@ struct clk_hw;
struct device;
struct regmap;
-#define UNIPHIER_CLK_MUX_MAX_PARENTS 8
+#define UNIPHIER_CLK_CPUGEAR_MAX_PARENTS 16
+#define UNIPHIER_CLK_MUX_MAX_PARENTS 8
enum uniphier_clk_type {
+ UNIPHIER_CLK_TYPE_CPUGEAR,
UNIPHIER_CLK_TYPE_FIXED_FACTOR,
UNIPHIER_CLK_TYPE_FIXED_RATE,
UNIPHIER_CLK_TYPE_GATE,
UNIPHIER_CLK_TYPE_MUX,
};
+struct uniphier_clk_cpugear_data {
+ const char *parent_names[UNIPHIER_CLK_CPUGEAR_MAX_PARENTS];
+ unsigned int num_parents;
+ unsigned int regbase;
+ unsigned int mask;
+};
+
struct uniphier_clk_fixed_factor_data {
const char *parent_name;
unsigned int mult;
@@ -58,6 +67,7 @@ struct uniphier_clk_data {
enum uniphier_clk_type type;
int idx;
union {
+ struct uniphier_clk_cpugear_data cpugear;
struct uniphier_clk_fixed_factor_data factor;
struct uniphier_clk_fixed_rate_data rate;
struct uniphier_clk_gate_data gate;
@@ -65,6 +75,20 @@ struct uniphier_clk_data {
} data;
};
+#define UNIPHIER_CLK_CPUGEAR(_name, _idx, _regbase, _mask, \
+ _num_parents, ...) \
+ { \
+ .name = (_name), \
+ .type = UNIPHIER_CLK_TYPE_CPUGEAR, \
+ .idx = (_idx), \
+ .data.cpugear = { \
+ .parent_names = { __VA_ARGS__ }, \
+ .num_parents = (_num_parents), \
+ .regbase = (_regbase), \
+ .mask = (_mask) \
+ }, \
+ }
+
#define UNIPHIER_CLK_FACTOR(_name, _idx, _parent, _mult, _div) \
{ \
.name = (_name), \
@@ -77,7 +101,6 @@ struct uniphier_clk_data {
}, \
}
-
#define UNIPHIER_CLK_GATE(_name, _idx, _parent, _reg, _bit) \
{ \
.name = (_name), \
@@ -90,7 +113,25 @@ struct uniphier_clk_data {
}, \
}
+#define UNIPHIER_CLK_DIV(parent, div) \
+ UNIPHIER_CLK_FACTOR(parent "/" #div, -1, parent, 1, div)
+
+#define UNIPHIER_CLK_DIV2(parent, div0, div1) \
+ UNIPHIER_CLK_DIV(parent, div0), \
+ UNIPHIER_CLK_DIV(parent, div1)
+
+#define UNIPHIER_CLK_DIV3(parent, div0, div1, div2) \
+ UNIPHIER_CLK_DIV2(parent, div0, div1), \
+ UNIPHIER_CLK_DIV(parent, div2)
+
+#define UNIPHIER_CLK_DIV4(parent, div0, div1, div2, div3) \
+ UNIPHIER_CLK_DIV2(parent, div0, div1), \
+ UNIPHIER_CLK_DIV2(parent, div2, div3)
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+ struct regmap *regmap,
+ const char *name,
+ const struct uniphier_clk_cpugear_data *data);
struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
const char *name,
const struct uniphier_clk_fixed_factor_data *data);
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 73c487da6d2a..02fef6830e72 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -81,6 +81,7 @@ static struct clock_event_device __percpu *arch_timer_evt;
static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
static bool arch_timer_c3stop;
static bool arch_timer_mem_use_virtual;
+static bool arch_counter_suspend_stop;
static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
@@ -576,7 +577,7 @@ static struct clocksource clocksource_counter = {
.rating = 400,
.read = arch_counter_read,
.mask = CLOCKSOURCE_MASK(56),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct cyclecounter cyclecounter = {
@@ -616,6 +617,8 @@ static void __init arch_counter_register(unsigned type)
arch_timer_read_counter = arch_counter_get_cntvct_mem;
}
+ if (!arch_counter_suspend_stop)
+ clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
cyclecounter.mult = clocksource_counter.mult;
@@ -907,6 +910,10 @@ static int __init arch_timer_of_init(struct device_node *np)
of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
arch_timer_uses_ppi = PHYS_SECURE_PPI;
+ /* On some systems, the counter stops ticking when in suspend. */
+ arch_counter_suspend_stop = of_property_read_bool(np,
+ "arm,no-tick-in-suspend");
+
return arch_timer_init();
}
CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
@@ -964,8 +971,9 @@ static int __init arch_timer_mem_init(struct device_node *np)
}
ret= -ENXIO;
- base = arch_counter_base = of_iomap(best_frame, 0);
- if (!base) {
+ base = arch_counter_base = of_io_request_and_map(best_frame, 0,
+ "arch_mem_timer");
+ if (IS_ERR(base)) {
pr_err("arch_timer: Can't map frame's registers\n");
goto out;
}
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index e71acf231c89..f2f29d2be1cf 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -96,7 +96,7 @@ static int __init bcm2835_timer_init(struct device_node *node)
ret = of_property_read_u32(node, "clock-frequency", &freq);
if (ret) {
pr_err("Can't read clock-frequency");
- return ret;
+ goto err_iounmap;
}
system_clock = base + REG_COUNTER_LO;
@@ -108,13 +108,15 @@ static int __init bcm2835_timer_init(struct device_node *node)
irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
if (irq <= 0) {
pr_err("Can't parse IRQ");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_iounmap;
}
timer = kzalloc(sizeof(*timer), GFP_KERNEL);
if (!timer) {
pr_err("Can't allocate timer struct\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_iounmap;
}
timer->control = base + REG_CONTROL;
@@ -133,7 +135,7 @@ static int __init bcm2835_timer_init(struct device_node *node)
ret = setup_irq(irq, &timer->act);
if (ret) {
pr_err("Can't set up timer IRQ\n");
- return ret;
+ goto err_iounmap;
}
clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
@@ -141,6 +143,10 @@ static int __init bcm2835_timer_init(struct device_node *node)
pr_info("bcm2835: system timer (irq = %d)\n", irq);
return 0;
+
+err_iounmap:
+ iounmap(base);
+ return ret;
}
CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
bcm2835_timer_init);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index d89b8afe23b6..920c469f3953 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -12,6 +12,27 @@ config ARM_BIG_LITTLE_CPUFREQ
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
+config ARM_BRCMSTB_AVS_CPUFREQ
+ tristate "Broadcom STB AVS CPUfreq driver"
+ depends on ARCH_BRCMSTB || COMPILE_TEST
+ default y
+ help
+ Some Broadcom STB SoCs use a co-processor running proprietary firmware
+ ("AVS") to handle voltage and frequency scaling. This driver provides
+ a standard CPUfreq interface to to the firmware.
+
+ Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
+
+config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+ bool "Broadcom STB AVS CPUfreq driver sysfs debug capability"
+ depends on ARM_BRCMSTB_AVS_CPUFREQ
+ help
+ Enabling this option turns on debug support via sysfs under
+ /sys/kernel/debug/brcmstb-avs-cpufreq. It is possible to read all and
+ write some AVS mailbox registers through sysfs entries.
+
+ If in doubt, say N.
+
config ARM_DT_BL_CPUFREQ
tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
depends on ARM_BIG_LITTLE_CPUFREQ && OF
@@ -60,14 +81,6 @@ config ARM_IMX6Q_CPUFREQ
If in doubt, say N.
-config ARM_INTEGRATOR
- tristate "CPUfreq driver for ARM Integrator CPUs"
- depends on ARCH_INTEGRATOR
- default y
- help
- This enables the CPUfreq driver for ARM Integrator CPUs.
- If in doubt, say Y.
-
config ARM_KIRKWOOD_CPUFREQ
def_bool MACH_KIRKWOOD
help
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index adbd1de1cea5..35f71825b7f3 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -6,6 +6,7 @@ config X86_INTEL_PSTATE
bool "Intel P state control"
depends on X86
select ACPI_PROCESSOR if ACPI
+ select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO
help
This driver provides a P state for Intel core processors.
The driver implements an internal governor and will become
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a093646..1e46c3918e7a 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -51,12 +51,12 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
# LITTLE drivers, so that it is probed last.
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
+obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
-obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 297e9128fe9f..3a98702b7445 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -84,7 +84,6 @@ static inline struct acpi_processor_performance *to_perf_data(struct acpi_cpufre
static struct cpufreq_driver acpi_cpufreq_driver;
static unsigned int acpi_pstate_strict;
-static struct msr __percpu *msrs;
static bool boost_state(unsigned int cpu)
{
@@ -104,11 +103,10 @@ static bool boost_state(unsigned int cpu)
return false;
}
-static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
+static int boost_set_msr(bool enable)
{
- u32 cpu;
u32 msr_addr;
- u64 msr_mask;
+ u64 msr_mask, val;
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
@@ -120,26 +118,31 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
msr_mask = MSR_K7_HWCR_CPB_DIS;
break;
default:
- return;
+ return -EINVAL;
}
- rdmsr_on_cpus(cpumask, msr_addr, msrs);
+ rdmsrl(msr_addr, val);
- for_each_cpu(cpu, cpumask) {
- struct msr *reg = per_cpu_ptr(msrs, cpu);
- if (enable)
- reg->q &= ~msr_mask;
- else
- reg->q |= msr_mask;
- }
+ if (enable)
+ val &= ~msr_mask;
+ else
+ val |= msr_mask;
+
+ wrmsrl(msr_addr, val);
+ return 0;
+}
+
+static void boost_set_msr_each(void *p_en)
+{
+ bool enable = (bool) p_en;
- wrmsr_on_cpus(cpumask, msr_addr, msrs);
+ boost_set_msr(enable);
}
static int set_boost(int val)
{
get_online_cpus();
- boost_set_msrs(val, cpu_online_mask);
+ on_each_cpu(boost_set_msr_each, (void *)(long)val, 1);
put_online_cpus();
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
@@ -536,46 +539,24 @@ static void free_acpi_perf_data(void)
free_percpu(acpi_perf_data);
}
-static int boost_notify(struct notifier_block *nb, unsigned long action,
- void *hcpu)
+static int cpufreq_boost_online(unsigned int cpu)
{
- unsigned cpu = (long)hcpu;
- const struct cpumask *cpumask;
-
- cpumask = get_cpu_mask(cpu);
+ /*
+ * On the CPU_UP path we simply keep the boost-disable flag
+ * in sync with the current global state.
+ */
+ return boost_set_msr(acpi_cpufreq_driver.boost_enabled);
+}
+static int cpufreq_boost_down_prep(unsigned int cpu)
+{
/*
* Clear the boost-disable bit on the CPU_DOWN path so that
- * this cpu cannot block the remaining ones from boosting. On
- * the CPU_UP path we simply keep the boost-disable flag in
- * sync with the current global state.
+ * this cpu cannot block the remaining ones from boosting.
*/
-
- switch (action) {
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- boost_set_msrs(acpi_cpufreq_driver.boost_enabled, cpumask);
- break;
-
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- boost_set_msrs(1, cpumask);
- break;
-
- default:
- break;
- }
-
- return NOTIFY_OK;
+ return boost_set_msr(1);
}
-
-static struct notifier_block boost_nb = {
- .notifier_call = boost_notify,
-};
-
/*
* acpi_cpufreq_early_init - initialize ACPI P-States library
*
@@ -922,37 +903,35 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.attr = acpi_cpufreq_attr,
};
+static enum cpuhp_state acpi_cpufreq_online;
+
static void __init acpi_cpufreq_boost_init(void)
{
- if (boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)) {
- msrs = msrs_alloc();
-
- if (!msrs)
- return;
-
- acpi_cpufreq_driver.set_boost = set_boost;
- acpi_cpufreq_driver.boost_enabled = boost_state(0);
-
- cpu_notifier_register_begin();
+ int ret;
- /* Force all MSRs to the same value */
- boost_set_msrs(acpi_cpufreq_driver.boost_enabled,
- cpu_online_mask);
+ if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)))
+ return;
- __register_cpu_notifier(&boost_nb);
+ acpi_cpufreq_driver.set_boost = set_boost;
+ acpi_cpufreq_driver.boost_enabled = boost_state(0);
- cpu_notifier_register_done();
+ /*
+ * This calls the online callback on all online cpu and forces all
+ * MSRs to the same value.
+ */
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpufreq/acpi:online",
+ cpufreq_boost_online, cpufreq_boost_down_prep);
+ if (ret < 0) {
+ pr_err("acpi_cpufreq: failed to register hotplug callbacks\n");
+ return;
}
+ acpi_cpufreq_online = ret;
}
static void acpi_cpufreq_boost_exit(void)
{
- if (msrs) {
- unregister_cpu_notifier(&boost_nb);
-
- msrs_free(msrs);
- msrs = NULL;
- }
+ if (acpi_cpufreq_online >= 0)
+ cpuhp_remove_state_nocalls(acpi_cpufreq_online);
}
static int __init acpi_cpufreq_init(void)
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
new file mode 100644
index 000000000000..4fda623e55bb
--- /dev/null
+++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -0,0 +1,1057 @@
+/*
+ * CPU frequency scaling for Broadcom SoCs with AVS firmware that
+ * supports DVS or DVFS
+ *
+ * Copyright (c) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * "AVS" is the name of a firmware developed at Broadcom. It derives
+ * its name from the technique called "Adaptive Voltage Scaling".
+ * Adaptive voltage scaling was the original purpose of this firmware.
+ * The AVS firmware still supports "AVS mode", where all it does is
+ * adaptive voltage scaling. However, on some newer Broadcom SoCs, the
+ * AVS Firmware, despite its unchanged name, also supports DFS mode and
+ * DVFS mode.
+ *
+ * In the context of this document and the related driver, "AVS" by
+ * itself always means the Broadcom firmware and never refers to the
+ * technique called "Adaptive Voltage Scaling".
+ *
+ * The Broadcom STB AVS CPUfreq driver provides voltage and frequency
+ * scaling on Broadcom SoCs using AVS firmware with support for DFS and
+ * DVFS. The AVS firmware is running on its own co-processor. The
+ * driver supports both uniprocessor (UP) and symmetric multiprocessor
+ * (SMP) systems which share clock and voltage across all CPUs.
+ *
+ * Actual voltage and frequency scaling is done solely by the AVS
+ * firmware. This driver does not change frequency or voltage itself.
+ * It provides a standard CPUfreq interface to the rest of the kernel
+ * and to userland. It interfaces with the AVS firmware to effect the
+ * requested changes and to report back the current system status in a
+ * way that is expected by existing tools.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#endif
+
+/* Max number of arguments AVS calls take */
+#define AVS_MAX_CMD_ARGS 4
+/*
+ * This macro is used to generate AVS parameter register offsets. For
+ * x >= AVS_MAX_CMD_ARGS, it returns 0 to protect against accidental memory
+ * access outside of the parameter range. (Offset 0 is the first parameter.)
+ */
+#define AVS_PARAM_MULT(x) ((x) < AVS_MAX_CMD_ARGS ? (x) : 0)
+
+/* AVS Mailbox Register offsets */
+#define AVS_MBOX_COMMAND 0x00
+#define AVS_MBOX_STATUS 0x04
+#define AVS_MBOX_VOLTAGE0 0x08
+#define AVS_MBOX_TEMP0 0x0c
+#define AVS_MBOX_PV0 0x10
+#define AVS_MBOX_MV0 0x14
+#define AVS_MBOX_PARAM(x) (0x18 + AVS_PARAM_MULT(x) * sizeof(u32))
+#define AVS_MBOX_REVISION 0x28
+#define AVS_MBOX_PSTATE 0x2c
+#define AVS_MBOX_HEARTBEAT 0x30
+#define AVS_MBOX_MAGIC 0x34
+#define AVS_MBOX_SIGMA_HVT 0x38
+#define AVS_MBOX_SIGMA_SVT 0x3c
+#define AVS_MBOX_VOLTAGE1 0x40
+#define AVS_MBOX_TEMP1 0x44
+#define AVS_MBOX_PV1 0x48
+#define AVS_MBOX_MV1 0x4c
+#define AVS_MBOX_FREQUENCY 0x50
+
+/* AVS Commands */
+#define AVS_CMD_AVAILABLE 0x00
+#define AVS_CMD_DISABLE 0x10
+#define AVS_CMD_ENABLE 0x11
+#define AVS_CMD_S2_ENTER 0x12
+#define AVS_CMD_S2_EXIT 0x13
+#define AVS_CMD_BBM_ENTER 0x14
+#define AVS_CMD_BBM_EXIT 0x15
+#define AVS_CMD_S3_ENTER 0x16
+#define AVS_CMD_S3_EXIT 0x17
+#define AVS_CMD_BALANCE 0x18
+/* PMAP and P-STATE commands */
+#define AVS_CMD_GET_PMAP 0x30
+#define AVS_CMD_SET_PMAP 0x31
+#define AVS_CMD_GET_PSTATE 0x40
+#define AVS_CMD_SET_PSTATE 0x41
+
+/* Different modes AVS supports (for GET_PMAP/SET_PMAP) */
+#define AVS_MODE_AVS 0x0
+#define AVS_MODE_DFS 0x1
+#define AVS_MODE_DVS 0x2
+#define AVS_MODE_DVFS 0x3
+
+/*
+ * PMAP parameter p1
+ * unused:31-24, mdiv_p0:23-16, unused:15-14, pdiv:13-10 , ndiv_int:9-0
+ */
+#define NDIV_INT_SHIFT 0
+#define NDIV_INT_MASK 0x3ff
+#define PDIV_SHIFT 10
+#define PDIV_MASK 0xf
+#define MDIV_P0_SHIFT 16
+#define MDIV_P0_MASK 0xff
+/*
+ * PMAP parameter p2
+ * mdiv_p4:31-24, mdiv_p3:23-16, mdiv_p2:15:8, mdiv_p1:7:0
+ */
+#define MDIV_P1_SHIFT 0
+#define MDIV_P1_MASK 0xff
+#define MDIV_P2_SHIFT 8
+#define MDIV_P2_MASK 0xff
+#define MDIV_P3_SHIFT 16
+#define MDIV_P3_MASK 0xff
+#define MDIV_P4_SHIFT 24
+#define MDIV_P4_MASK 0xff
+
+/* Different P-STATES AVS supports (for GET_PSTATE/SET_PSTATE) */
+#define AVS_PSTATE_P0 0x0
+#define AVS_PSTATE_P1 0x1
+#define AVS_PSTATE_P2 0x2
+#define AVS_PSTATE_P3 0x3
+#define AVS_PSTATE_P4 0x4
+#define AVS_PSTATE_MAX AVS_PSTATE_P4
+
+/* CPU L2 Interrupt Controller Registers */
+#define AVS_CPU_L2_SET0 0x04
+#define AVS_CPU_L2_INT_MASK BIT(31)
+
+/* AVS Command Status Values */
+#define AVS_STATUS_CLEAR 0x00
+/* Command/notification accepted */
+#define AVS_STATUS_SUCCESS 0xf0
+/* Command/notification rejected */
+#define AVS_STATUS_FAILURE 0xff
+/* Invalid command/notification (unknown) */
+#define AVS_STATUS_INVALID 0xf1
+/* Non-AVS modes are not supported */
+#define AVS_STATUS_NO_SUPP 0xf2
+/* Cannot set P-State until P-Map supplied */
+#define AVS_STATUS_NO_MAP 0xf3
+/* Cannot change P-Map after initial P-Map set */
+#define AVS_STATUS_MAP_SET 0xf4
+/* Max AVS status; higher numbers are used for debugging */
+#define AVS_STATUS_MAX 0xff
+
+/* Other AVS related constants */
+#define AVS_LOOP_LIMIT 10000
+#define AVS_TIMEOUT 300 /* in ms; expected completion is < 10ms */
+#define AVS_FIRMWARE_MAGIC 0xa11600d1
+
+#define BRCM_AVS_CPUFREQ_PREFIX "brcmstb-avs"
+#define BRCM_AVS_CPUFREQ_NAME BRCM_AVS_CPUFREQ_PREFIX "-cpufreq"
+#define BRCM_AVS_CPU_DATA "brcm,avs-cpu-data-mem"
+#define BRCM_AVS_CPU_INTR "brcm,avs-cpu-l2-intr"
+#define BRCM_AVS_HOST_INTR "sw_intr"
+
+struct pmap {
+ unsigned int mode;
+ unsigned int p1;
+ unsigned int p2;
+ unsigned int state;
+};
+
+struct private_data {
+ void __iomem *base;
+ void __iomem *avs_intr_base;
+ struct device *dev;
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+ struct dentry *debugfs;
+#endif
+ struct completion done;
+ struct semaphore sem;
+ struct pmap pmap;
+};
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+
+enum debugfs_format {
+ DEBUGFS_NORMAL,
+ DEBUGFS_FLOAT,
+ DEBUGFS_REV,
+};
+
+struct debugfs_data {
+ struct debugfs_entry *entry;
+ struct private_data *priv;
+};
+
+struct debugfs_entry {
+ char *name;
+ u32 offset;
+ fmode_t mode;
+ enum debugfs_format format;
+};
+
+#define DEBUGFS_ENTRY(name, mode, format) { \
+ #name, AVS_MBOX_##name, mode, format \
+}
+
+/*
+ * These are used for debugfs only. Otherwise we use AVS_MBOX_PARAM() directly.
+ */
+#define AVS_MBOX_PARAM1 AVS_MBOX_PARAM(0)
+#define AVS_MBOX_PARAM2 AVS_MBOX_PARAM(1)
+#define AVS_MBOX_PARAM3 AVS_MBOX_PARAM(2)
+#define AVS_MBOX_PARAM4 AVS_MBOX_PARAM(3)
+
+/*
+ * This table stores the name, access permissions and offset for each hardware
+ * register and is used to generate debugfs entries.
+ */
+static struct debugfs_entry debugfs_entries[] = {
+ DEBUGFS_ENTRY(COMMAND, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(STATUS, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(VOLTAGE0, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(TEMP0, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(PV0, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(MV0, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(PARAM1, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(PARAM2, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(PARAM3, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(PARAM4, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(REVISION, 0, DEBUGFS_REV),
+ DEBUGFS_ENTRY(PSTATE, 0, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(HEARTBEAT, 0, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(MAGIC, S_IWUSR, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(SIGMA_HVT, 0, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(SIGMA_SVT, 0, DEBUGFS_NORMAL),
+ DEBUGFS_ENTRY(VOLTAGE1, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(TEMP1, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(PV1, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(MV1, 0, DEBUGFS_FLOAT),
+ DEBUGFS_ENTRY(FREQUENCY, 0, DEBUGFS_NORMAL),
+};
+
+static int brcm_avs_target_index(struct cpufreq_policy *, unsigned int);
+
+static char *__strtolower(char *s)
+{
+ char *p;
+
+ for (p = s; *p; p++)
+ *p = tolower(*p);
+
+ return s;
+}
+
+#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */
+
+static void __iomem *__map_region(const char *name)
+{
+ struct device_node *np;
+ void __iomem *ptr;
+
+ np = of_find_compatible_node(NULL, NULL, name);
+ if (!np)
+ return NULL;
+
+ ptr = of_iomap(np, 0);
+ of_node_put(np);
+
+ return ptr;
+}
+
+static int __issue_avs_command(struct private_data *priv, int cmd, bool is_send,
+ u32 args[])
+{
+ unsigned long time_left = msecs_to_jiffies(AVS_TIMEOUT);
+ void __iomem *base = priv->base;
+ unsigned int i;
+ int ret;
+ u32 val;
+
+ ret = down_interruptible(&priv->sem);
+ if (ret)
+ return ret;
+
+ /*
+ * Make sure no other command is currently running: cmd is 0 if AVS
+ * co-processor is idle. Due to the guard above, we should almost never
+ * have to wait here.
+ */
+ for (i = 0, val = 1; val != 0 && i < AVS_LOOP_LIMIT; i++)
+ val = readl(base + AVS_MBOX_COMMAND);
+
+ /* Give the caller a chance to retry if AVS is busy. */
+ if (i == AVS_LOOP_LIMIT) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Clear status before we begin. */
+ writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
+
+ /* We need to send arguments for this command. */
+ if (args && is_send) {
+ for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
+ writel(args[i], base + AVS_MBOX_PARAM(i));
+ }
+
+ /* Protect from spurious interrupts. */
+ reinit_completion(&priv->done);
+
+ /* Now issue the command & tell firmware to wake up to process it. */
+ writel(cmd, base + AVS_MBOX_COMMAND);
+ writel(AVS_CPU_L2_INT_MASK, priv->avs_intr_base + AVS_CPU_L2_SET0);
+
+ /* Wait for AVS co-processor to finish processing the command. */
+ time_left = wait_for_completion_timeout(&priv->done, time_left);
+
+ /*
+ * If the AVS status is not in the expected range, it means AVS didn't
+ * complete our command in time, and we return an error. Also, if there
+ * is no "time left", we timed out waiting for the interrupt.
+ */
+ val = readl(base + AVS_MBOX_STATUS);
+ if (time_left == 0 || val == 0 || val > AVS_STATUS_MAX) {
+ dev_err(priv->dev, "AVS command %#x didn't complete in time\n",
+ cmd);
+ dev_err(priv->dev, " Time left: %u ms, AVS status: %#x\n",
+ jiffies_to_msecs(time_left), val);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ /* This command returned arguments, so we read them back. */
+ if (args && !is_send) {
+ for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
+ args[i] = readl(base + AVS_MBOX_PARAM(i));
+ }
+
+ /* Clear status to tell AVS co-processor we are done. */
+ writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
+
+ /* Convert firmware errors to errno's as much as possible. */
+ switch (val) {
+ case AVS_STATUS_INVALID:
+ ret = -EINVAL;
+ break;
+ case AVS_STATUS_NO_SUPP:
+ ret = -ENOTSUPP;
+ break;
+ case AVS_STATUS_NO_MAP:
+ ret = -ENOENT;
+ break;
+ case AVS_STATUS_MAP_SET:
+ ret = -EEXIST;
+ break;
+ case AVS_STATUS_FAILURE:
+ ret = -EIO;
+ break;
+ }
+
+out:
+ up(&priv->sem);
+
+ return ret;
+}
+
+static irqreturn_t irq_handler(int irq, void *data)
+{
+ struct private_data *priv = data;
+
+ /* AVS command completed execution. Wake up __issue_avs_command(). */
+ complete(&priv->done);
+
+ return IRQ_HANDLED;
+}
+
+static char *brcm_avs_mode_to_string(unsigned int mode)
+{
+ switch (mode) {
+ case AVS_MODE_AVS:
+ return "AVS";
+ case AVS_MODE_DFS:
+ return "DFS";
+ case AVS_MODE_DVS:
+ return "DVS";
+ case AVS_MODE_DVFS:
+ return "DVFS";
+ }
+ return NULL;
+}
+
+static void brcm_avs_parse_p1(u32 p1, unsigned int *mdiv_p0, unsigned int *pdiv,
+ unsigned int *ndiv)
+{
+ *mdiv_p0 = (p1 >> MDIV_P0_SHIFT) & MDIV_P0_MASK;
+ *pdiv = (p1 >> PDIV_SHIFT) & PDIV_MASK;
+ *ndiv = (p1 >> NDIV_INT_SHIFT) & NDIV_INT_MASK;
+}
+
+static void brcm_avs_parse_p2(u32 p2, unsigned int *mdiv_p1,
+ unsigned int *mdiv_p2, unsigned int *mdiv_p3,
+ unsigned int *mdiv_p4)
+{
+ *mdiv_p4 = (p2 >> MDIV_P4_SHIFT) & MDIV_P4_MASK;
+ *mdiv_p3 = (p2 >> MDIV_P3_SHIFT) & MDIV_P3_MASK;
+ *mdiv_p2 = (p2 >> MDIV_P2_SHIFT) & MDIV_P2_MASK;
+ *mdiv_p1 = (p2 >> MDIV_P1_SHIFT) & MDIV_P1_MASK;
+}
+
+static int brcm_avs_get_pmap(struct private_data *priv, struct pmap *pmap)
+{
+ u32 args[AVS_MAX_CMD_ARGS];
+ int ret;
+
+ ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, false, args);
+ if (ret || !pmap)
+ return ret;
+
+ pmap->mode = args[0];
+ pmap->p1 = args[1];
+ pmap->p2 = args[2];
+ pmap->state = args[3];
+
+ return 0;
+}
+
+static int brcm_avs_set_pmap(struct private_data *priv, struct pmap *pmap)
+{
+ u32 args[AVS_MAX_CMD_ARGS];
+
+ args[0] = pmap->mode;
+ args[1] = pmap->p1;
+ args[2] = pmap->p2;
+ args[3] = pmap->state;
+
+ return __issue_avs_command(priv, AVS_CMD_SET_PMAP, true, args);
+}
+
+static int brcm_avs_get_pstate(struct private_data *priv, unsigned int *pstate)
+{
+ u32 args[AVS_MAX_CMD_ARGS];
+ int ret;
+
+ ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, false, args);
+ if (ret)
+ return ret;
+ *pstate = args[0];
+
+ return 0;
+}
+
+static int brcm_avs_set_pstate(struct private_data *priv, unsigned int pstate)
+{
+ u32 args[AVS_MAX_CMD_ARGS];
+
+ args[0] = pstate;
+
+ return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, true, args);
+}
+
+static unsigned long brcm_avs_get_voltage(void __iomem *base)
+{
+ return readl(base + AVS_MBOX_VOLTAGE1);
+}
+
+static unsigned long brcm_avs_get_frequency(void __iomem *base)
+{
+ return readl(base + AVS_MBOX_FREQUENCY) * 1000; /* in kHz */
+}
+
+/*
+ * We determine which frequencies are supported by cycling through all P-states
+ * and reading back what frequency we are running at for each P-state.
+ */
+static struct cpufreq_frequency_table *
+brcm_avs_get_freq_table(struct device *dev, struct private_data *priv)
+{
+ struct cpufreq_frequency_table *table;
+ unsigned int pstate;
+ int i, ret;
+
+ /* Remember P-state for later */
+ ret = brcm_avs_get_pstate(priv, &pstate);
+ if (ret)
+ return ERR_PTR(ret);
+
+ table = devm_kzalloc(dev, (AVS_PSTATE_MAX + 1) * sizeof(*table),
+ GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = AVS_PSTATE_P0; i <= AVS_PSTATE_MAX; i++) {
+ ret = brcm_avs_set_pstate(priv, i);
+ if (ret)
+ return ERR_PTR(ret);
+ table[i].frequency = brcm_avs_get_frequency(priv->base);
+ table[i].driver_data = i;
+ }
+ table[i].frequency = CPUFREQ_TABLE_END;
+
+ /* Restore P-state */
+ ret = brcm_avs_set_pstate(priv, pstate);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return table;
+}
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+
+#define MANT(x) (unsigned int)(abs((x)) / 1000)
+#define FRAC(x) (unsigned int)(abs((x)) - abs((x)) / 1000 * 1000)
+
+static int brcm_avs_debug_show(struct seq_file *s, void *data)
+{
+ struct debugfs_data *dbgfs = s->private;
+ void __iomem *base;
+ u32 val, offset;
+
+ if (!dbgfs) {
+ seq_puts(s, "No device pointer\n");
+ return 0;
+ }
+
+ base = dbgfs->priv->base;
+ offset = dbgfs->entry->offset;
+ val = readl(base + offset);
+ switch (dbgfs->entry->format) {
+ case DEBUGFS_NORMAL:
+ seq_printf(s, "%u\n", val);
+ break;
+ case DEBUGFS_FLOAT:
+ seq_printf(s, "%d.%03d\n", MANT(val), FRAC(val));
+ break;
+ case DEBUGFS_REV:
+ seq_printf(s, "%c.%c.%c.%c\n", (val >> 24 & 0xff),
+ (val >> 16 & 0xff), (val >> 8 & 0xff),
+ val & 0xff);
+ break;
+ }
+ seq_printf(s, "0x%08x\n", val);
+
+ return 0;
+}
+
+#undef MANT
+#undef FRAC
+
+static ssize_t brcm_avs_seq_write(struct file *file, const char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ struct seq_file *s = file->private_data;
+ struct debugfs_data *dbgfs = s->private;
+ struct private_data *priv = dbgfs->priv;
+ void __iomem *base, *avs_intr_base;
+ bool use_issue_command = false;
+ unsigned long val, offset;
+ char str[128];
+ int ret;
+ char *str_ptr = str;
+
+ if (size >= sizeof(str))
+ return -E2BIG;
+
+ memset(str, 0, sizeof(str));
+ ret = copy_from_user(str, buf, size);
+ if (ret)
+ return ret;
+
+ base = priv->base;
+ avs_intr_base = priv->avs_intr_base;
+ offset = dbgfs->entry->offset;
+ /*
+ * Special case writing to "command" entry only: if the string starts
+ * with a 'c', we use the driver's __issue_avs_command() function.
+ * Otherwise, we perform a raw write. This should allow testing of raw
+ * access as well as using the higher level function. (Raw access
+ * doesn't clear the firmware return status after issuing the command.)
+ */
+ if (str_ptr[0] == 'c' && offset == AVS_MBOX_COMMAND) {
+ use_issue_command = true;
+ str_ptr++;
+ }
+ if (kstrtoul(str_ptr, 0, &val) != 0)
+ return -EINVAL;
+
+ /*
+ * Setting the P-state is a special case. We need to update the CPU
+ * frequency we report.
+ */
+ if (val == AVS_CMD_SET_PSTATE) {
+ struct cpufreq_policy *policy;
+ unsigned int pstate;
+
+ policy = cpufreq_cpu_get(smp_processor_id());
+ /* Read back the P-state we are about to set */
+ pstate = readl(base + AVS_MBOX_PARAM(0));
+ if (use_issue_command) {
+ ret = brcm_avs_target_index(policy, pstate);
+ return ret ? ret : size;
+ }
+ policy->cur = policy->freq_table[pstate].frequency;
+ }
+
+ if (use_issue_command) {
+ ret = __issue_avs_command(priv, val, false, NULL);
+ } else {
+ /* Locking here is not perfect, but is only for debug. */
+ ret = down_interruptible(&priv->sem);
+ if (ret)
+ return ret;
+
+ writel(val, base + offset);
+ /* We have to wake up the firmware to process a command. */
+ if (offset == AVS_MBOX_COMMAND)
+ writel(AVS_CPU_L2_INT_MASK,
+ avs_intr_base + AVS_CPU_L2_SET0);
+ up(&priv->sem);
+ }
+
+ return ret ? ret : size;
+}
+
+static struct debugfs_entry *__find_debugfs_entry(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++)
+ if (strcasecmp(debugfs_entries[i].name, name) == 0)
+ return &debugfs_entries[i];
+
+ return NULL;
+}
+
+static int brcm_avs_debug_open(struct inode *inode, struct file *file)
+{
+ struct debugfs_data *data;
+ fmode_t fmode;
+ int ret;
+
+ /*
+ * seq_open(), which is called by single_open(), clears "write" access.
+ * We need write access to some files, so we preserve our access mode
+ * and restore it.
+ */
+ fmode = file->f_mode;
+ /*
+ * Check access permissions even for root. We don't want to be writing
+ * to read-only registers. Access for regular users has already been
+ * checked by the VFS layer.
+ */
+ if ((fmode & FMODE_WRITER) && !(inode->i_mode & S_IWUSR))
+ return -EACCES;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ /*
+ * We use the same file system operations for all our debug files. To
+ * produce specific output, we look up the file name upon opening a
+ * debugfs entry and map it to a memory offset. This offset is then used
+ * in the generic "show" function to read a specific register.
+ */
+ data->entry = __find_debugfs_entry(file->f_path.dentry->d_iname);
+ data->priv = inode->i_private;
+
+ ret = single_open(file, brcm_avs_debug_show, data);
+ if (ret)
+ kfree(data);
+ file->f_mode = fmode;
+
+ return ret;
+}
+
+static int brcm_avs_debug_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq_priv = file->private_data;
+ struct debugfs_data *data = seq_priv->private;
+
+ kfree(data);
+ return single_release(inode, file);
+}
+
+static const struct file_operations brcm_avs_debug_ops = {
+ .open = brcm_avs_debug_open,
+ .read = seq_read,
+ .write = brcm_avs_seq_write,
+ .llseek = seq_lseek,
+ .release = brcm_avs_debug_release,
+};
+
+static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev)
+{
+ struct private_data *priv = platform_get_drvdata(pdev);
+ struct dentry *dir;
+ int i;
+
+ if (!priv)
+ return;
+
+ dir = debugfs_create_dir(BRCM_AVS_CPUFREQ_NAME, NULL);
+ if (IS_ERR_OR_NULL(dir))
+ return;
+ priv->debugfs = dir;
+
+ for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) {
+ /*
+ * The DEBUGFS_ENTRY macro generates uppercase strings. We
+ * convert them to lowercase before creating the debugfs
+ * entries.
+ */
+ char *entry = __strtolower(debugfs_entries[i].name);
+ fmode_t mode = debugfs_entries[i].mode;
+
+ if (!debugfs_create_file(entry, S_IFREG | S_IRUGO | mode,
+ dir, priv, &brcm_avs_debug_ops)) {
+ priv->debugfs = NULL;
+ debugfs_remove_recursive(dir);
+ break;
+ }
+ }
+}
+
+static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev)
+{
+ struct private_data *priv = platform_get_drvdata(pdev);
+
+ if (priv && priv->debugfs) {
+ debugfs_remove_recursive(priv->debugfs);
+ priv->debugfs = NULL;
+ }
+}
+
+#else
+
+static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) {}
+static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) {}
+
+#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */
+
+/*
+ * To ensure the right firmware is running we need to
+ * - check the MAGIC matches what we expect
+ * - brcm_avs_get_pmap() doesn't return -ENOTSUPP or -EINVAL
+ * We need to set up our interrupt handling before calling brcm_avs_get_pmap()!
+ */
+static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
+{
+ u32 magic;
+ int rc;
+
+ rc = brcm_avs_get_pmap(priv, NULL);
+ magic = readl(priv->base + AVS_MBOX_MAGIC);
+
+ return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) &&
+ (rc != -EINVAL);
+}
+
+static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ struct private_data *priv = policy->driver_data;
+
+ return brcm_avs_get_frequency(priv->base);
+}
+
+static int brcm_avs_target_index(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ return brcm_avs_set_pstate(policy->driver_data,
+ policy->freq_table[index].driver_data);
+}
+
+static int brcm_avs_suspend(struct cpufreq_policy *policy)
+{
+ struct private_data *priv = policy->driver_data;
+
+ return brcm_avs_get_pmap(priv, &priv->pmap);
+}
+
+static int brcm_avs_resume(struct cpufreq_policy *policy)
+{
+ struct private_data *priv = policy->driver_data;
+ int ret;
+
+ ret = brcm_avs_set_pmap(priv, &priv->pmap);
+ if (ret == -EEXIST) {
+ struct platform_device *pdev = cpufreq_get_driver_data();
+ struct device *dev = &pdev->dev;
+
+ dev_warn(dev, "PMAP was already set\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ * All initialization code that we only want to execute once goes here. Setup
+ * code that can be re-tried on every core (if it failed before) can go into
+ * brcm_avs_cpufreq_init().
+ */
+static int brcm_avs_prepare_init(struct platform_device *pdev)
+{
+ struct private_data *priv;
+ struct device *dev;
+ int host_irq, ret;
+
+ dev = &pdev->dev;
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ sema_init(&priv->sem, 1);
+ init_completion(&priv->done);
+ platform_set_drvdata(pdev, priv);
+
+ priv->base = __map_region(BRCM_AVS_CPU_DATA);
+ if (!priv->base) {
+ dev_err(dev, "Couldn't find property %s in device tree.\n",
+ BRCM_AVS_CPU_DATA);
+ return -ENOENT;
+ }
+
+ priv->avs_intr_base = __map_region(BRCM_AVS_CPU_INTR);
+ if (!priv->avs_intr_base) {
+ dev_err(dev, "Couldn't find property %s in device tree.\n",
+ BRCM_AVS_CPU_INTR);
+ ret = -ENOENT;
+ goto unmap_base;
+ }
+
+ host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR);
+ if (host_irq < 0) {
+ dev_err(dev, "Couldn't find interrupt %s -- %d\n",
+ BRCM_AVS_HOST_INTR, host_irq);
+ ret = host_irq;
+ goto unmap_intr_base;
+ }
+
+ ret = devm_request_irq(dev, host_irq, irq_handler, IRQF_TRIGGER_RISING,
+ BRCM_AVS_HOST_INTR, priv);
+ if (ret) {
+ dev_err(dev, "IRQ request failed: %s (%d) -- %d\n",
+ BRCM_AVS_HOST_INTR, host_irq, ret);
+ goto unmap_intr_base;
+ }
+
+ if (brcm_avs_is_firmware_loaded(priv))
+ return 0;
+
+ dev_err(dev, "AVS firmware is not loaded or doesn't support DVFS\n");
+ ret = -ENODEV;
+
+unmap_intr_base:
+ iounmap(priv->avs_intr_base);
+unmap_base:
+ iounmap(priv->base);
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
+{
+ struct cpufreq_frequency_table *freq_table;
+ struct platform_device *pdev;
+ struct private_data *priv;
+ struct device *dev;
+ int ret;
+
+ pdev = cpufreq_get_driver_data();
+ priv = platform_get_drvdata(pdev);
+ policy->driver_data = priv;
+ dev = &pdev->dev;
+
+ freq_table = brcm_avs_get_freq_table(dev, priv);
+ if (IS_ERR(freq_table)) {
+ ret = PTR_ERR(freq_table);
+ dev_err(dev, "Couldn't determine frequency table (%d).\n", ret);
+ return ret;
+ }
+
+ ret = cpufreq_table_validate_and_show(policy, freq_table);
+ if (ret) {
+ dev_err(dev, "invalid frequency table: %d\n", ret);
+ return ret;
+ }
+
+ /* All cores share the same clock and thus the same policy. */
+ cpumask_setall(policy->cpus);
+
+ ret = __issue_avs_command(priv, AVS_CMD_ENABLE, false, NULL);
+ if (!ret) {
+ unsigned int pstate;
+
+ ret = brcm_avs_get_pstate(priv, &pstate);
+ if (!ret) {
+ policy->cur = freq_table[pstate].frequency;
+ dev_info(dev, "registered\n");
+ return 0;
+ }
+ }
+
+ dev_err(dev, "couldn't initialize driver (%d)\n", ret);
+
+ return ret;
+}
+
+static ssize_t show_brcm_avs_pstate(struct cpufreq_policy *policy, char *buf)
+{
+ struct private_data *priv = policy->driver_data;
+ unsigned int pstate;
+
+ if (brcm_avs_get_pstate(priv, &pstate))
+ return sprintf(buf, "<unknown>\n");
+
+ return sprintf(buf, "%u\n", pstate);
+}
+
+static ssize_t show_brcm_avs_mode(struct cpufreq_policy *policy, char *buf)
+{
+ struct private_data *priv = policy->driver_data;
+ struct pmap pmap;
+
+ if (brcm_avs_get_pmap(priv, &pmap))
+ return sprintf(buf, "<unknown>\n");
+
+ return sprintf(buf, "%s %u\n", brcm_avs_mode_to_string(pmap.mode),
+ pmap.mode);
+}
+
+static ssize_t show_brcm_avs_pmap(struct cpufreq_policy *policy, char *buf)
+{
+ unsigned int mdiv_p0, mdiv_p1, mdiv_p2, mdiv_p3, mdiv_p4;
+ struct private_data *priv = policy->driver_data;
+ unsigned int ndiv, pdiv;
+ struct pmap pmap;
+
+ if (brcm_avs_get_pmap(priv, &pmap))
+ return sprintf(buf, "<unknown>\n");
+
+ brcm_avs_parse_p1(pmap.p1, &mdiv_p0, &pdiv, &ndiv);
+ brcm_avs_parse_p2(pmap.p2, &mdiv_p1, &mdiv_p2, &mdiv_p3, &mdiv_p4);
+
+ return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u\n",
+ pmap.p1, pmap.p2, ndiv, pdiv, mdiv_p0, mdiv_p1, mdiv_p2,
+ mdiv_p3, mdiv_p4);
+}
+
+static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf)
+{
+ struct private_data *priv = policy->driver_data;
+
+ return sprintf(buf, "0x%08lx\n", brcm_avs_get_voltage(priv->base));
+}
+
+static ssize_t show_brcm_avs_frequency(struct cpufreq_policy *policy, char *buf)
+{
+ struct private_data *priv = policy->driver_data;
+
+ return sprintf(buf, "0x%08lx\n", brcm_avs_get_frequency(priv->base));
+}
+
+cpufreq_freq_attr_ro(brcm_avs_pstate);
+cpufreq_freq_attr_ro(brcm_avs_mode);
+cpufreq_freq_attr_ro(brcm_avs_pmap);
+cpufreq_freq_attr_ro(brcm_avs_voltage);
+cpufreq_freq_attr_ro(brcm_avs_frequency);
+
+static struct freq_attr *brcm_avs_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ &brcm_avs_pstate,
+ &brcm_avs_mode,
+ &brcm_avs_pmap,
+ &brcm_avs_voltage,
+ &brcm_avs_frequency,
+ NULL
+};
+
+static struct cpufreq_driver brcm_avs_driver = {
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = brcm_avs_target_index,
+ .get = brcm_avs_cpufreq_get,
+ .suspend = brcm_avs_suspend,
+ .resume = brcm_avs_resume,
+ .init = brcm_avs_cpufreq_init,
+ .attr = brcm_avs_cpufreq_attr,
+ .name = BRCM_AVS_CPUFREQ_PREFIX,
+};
+
+static int brcm_avs_cpufreq_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = brcm_avs_prepare_init(pdev);
+ if (ret)
+ return ret;
+
+ brcm_avs_driver.driver_data = pdev;
+ ret = cpufreq_register_driver(&brcm_avs_driver);
+ if (!ret)
+ brcm_avs_cpufreq_debug_init(pdev);
+
+ return ret;
+}
+
+static int brcm_avs_cpufreq_remove(struct platform_device *pdev)
+{
+ struct private_data *priv;
+ int ret;
+
+ ret = cpufreq_unregister_driver(&brcm_avs_driver);
+ if (ret)
+ return ret;
+
+ brcm_avs_cpufreq_debug_exit(pdev);
+
+ priv = platform_get_drvdata(pdev);
+ iounmap(priv->base);
+ iounmap(priv->avs_intr_base);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id brcm_avs_cpufreq_match[] = {
+ { .compatible = BRCM_AVS_CPU_DATA },
+ { }
+};
+MODULE_DEVICE_TABLE(of, brcm_avs_cpufreq_match);
+
+static struct platform_driver brcm_avs_cpufreq_platdrv = {
+ .driver = {
+ .name = BRCM_AVS_CPUFREQ_NAME,
+ .of_match_table = brcm_avs_cpufreq_match,
+ },
+ .probe = brcm_avs_cpufreq_probe,
+ .remove = brcm_avs_cpufreq_remove,
+};
+module_platform_driver(brcm_avs_cpufreq_platdrv);
+
+MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
+MODULE_DESCRIPTION("CPUfreq driver for Broadcom STB AVS");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 4852d9efe74e..e82bb3c30b92 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -247,3 +247,10 @@ MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");
MODULE_LICENSE("GPL");
late_initcall(cppc_cpufreq_init);
+
+static const struct acpi_device_id cppc_acpi_ids[] = {
+ {ACPI_PROCESSOR_DEVICE_HID, },
+ {}
+};
+
+MODULE_DEVICE_TABLE(acpi, cppc_acpi_ids);
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 71267626456b..bc97b6a4b1cf 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -26,6 +26,9 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "allwinner,sun8i-a83t", },
{ .compatible = "allwinner,sun8i-h3", },
+ { .compatible = "arm,integrator-ap", },
+ { .compatible = "arm,integrator-cp", },
+
{ .compatible = "hisilicon,hi6220", },
{ .compatible = "fsl,imx27", },
@@ -34,6 +37,8 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "fsl,imx7d", },
{ .compatible = "marvell,berlin", },
+ { .compatible = "marvell,pxa250", },
+ { .compatible = "marvell,pxa270", },
{ .compatible = "samsung,exynos3250", },
{ .compatible = "samsung,exynos4210", },
@@ -50,6 +55,8 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "renesas,r7s72100", },
{ .compatible = "renesas,r8a73a4", },
{ .compatible = "renesas,r8a7740", },
+ { .compatible = "renesas,r8a7743", },
+ { .compatible = "renesas,r8a7745", },
{ .compatible = "renesas,r8a7778", },
{ .compatible = "renesas,r8a7779", },
{ .compatible = "renesas,r8a7790", },
@@ -72,6 +79,12 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "sigma,tango4" },
+ { .compatible = "socionext,uniphier-pro5", },
+ { .compatible = "socionext,uniphier-pxs2", },
+ { .compatible = "socionext,uniphier-ld6b", },
+ { .compatible = "socionext,uniphier-ld11", },
+ { .compatible = "socionext,uniphier-ld20", },
+
{ .compatible = "ti,am33xx", },
{ .compatible = "ti,dra7", },
{ .compatible = "ti,omap2", },
@@ -81,6 +94,8 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "xlnx,zynq-7000", },
+ { .compatible = "zte,zx296718", },
+
{ }
};
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 5c07ae05d69a..269013311e79 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -28,6 +28,7 @@
#include "cpufreq-dt.h"
struct private_data {
+ struct opp_table *opp_table;
struct device *cpu_dev;
struct thermal_cooling_device *cdev;
const char *reg_name;
@@ -143,6 +144,7 @@ static int resources_available(void)
static int cpufreq_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *freq_table;
+ struct opp_table *opp_table = NULL;
struct private_data *priv;
struct device *cpu_dev;
struct clk *cpu_clk;
@@ -186,8 +188,9 @@ static int cpufreq_init(struct cpufreq_policy *policy)
*/
name = find_supply_name(cpu_dev);
if (name) {
- ret = dev_pm_opp_set_regulator(cpu_dev, name);
- if (ret) {
+ opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
+ if (IS_ERR(opp_table)) {
+ ret = PTR_ERR(opp_table);
dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
policy->cpu, ret);
goto out_put_clk;
@@ -237,6 +240,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
}
priv->reg_name = name;
+ priv->opp_table = opp_table;
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
@@ -285,7 +289,7 @@ out_free_priv:
out_free_opp:
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
if (name)
- dev_pm_opp_put_regulator(cpu_dev);
+ dev_pm_opp_put_regulators(opp_table);
out_put_clk:
clk_put(cpu_clk);
@@ -300,7 +304,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
if (priv->reg_name)
- dev_pm_opp_put_regulator(priv->cpu_dev);
+ dev_pm_opp_put_regulators(priv->opp_table);
clk_put(policy->clk);
kfree(priv);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6e6c1fb60fbc..cc475eff90b3 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1526,7 +1526,10 @@ unsigned int cpufreq_get(unsigned int cpu)
if (policy) {
down_read(&policy->rwsem);
- ret_freq = __cpufreq_get(policy);
+
+ if (!policy_is_inactive(policy))
+ ret_freq = __cpufreq_get(policy);
+
up_read(&policy->rwsem);
cpufreq_cpu_put(policy);
@@ -2254,17 +2257,19 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
* Useful for policy notifiers which have different necessities
* at different times.
*/
-int cpufreq_update_policy(unsigned int cpu)
+void cpufreq_update_policy(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
struct cpufreq_policy new_policy;
- int ret;
if (!policy)
- return -ENODEV;
+ return;
down_write(&policy->rwsem);
+ if (policy_is_inactive(policy))
+ goto unlock;
+
pr_debug("updating policy for CPU %u\n", cpu);
memcpy(&new_policy, policy, sizeof(*policy));
new_policy.min = policy->user_policy.min;
@@ -2275,24 +2280,20 @@ int cpufreq_update_policy(unsigned int cpu)
* -> ask driver for current freq and notify governors about a change
*/
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
- if (cpufreq_suspended) {
- ret = -EAGAIN;
+ if (cpufreq_suspended)
goto unlock;
- }
+
new_policy.cur = cpufreq_update_current_freq(policy);
- if (WARN_ON(!new_policy.cur)) {
- ret = -EIO;
+ if (WARN_ON(!new_policy.cur))
goto unlock;
- }
}
- ret = cpufreq_set_policy(policy, &new_policy);
+ cpufreq_set_policy(policy, &new_policy);
unlock:
up_write(&policy->rwsem);
cpufreq_cpu_put(policy);
- return ret;
}
EXPORT_SYMBOL(cpufreq_update_policy);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 13475890d792..992f7c20760f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -37,16 +37,16 @@ struct cs_dbs_tuners {
#define DEF_SAMPLING_DOWN_FACTOR (1)
#define MAX_SAMPLING_DOWN_FACTOR (10)
-static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
- struct cpufreq_policy *policy)
+static inline unsigned int get_freq_step(struct cs_dbs_tuners *cs_tuners,
+ struct cpufreq_policy *policy)
{
- unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100;
+ unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100;
/* max freq cannot be less than 100. But who knows... */
- if (unlikely(freq_target == 0))
- freq_target = DEF_FREQUENCY_STEP;
+ if (unlikely(freq_step == 0))
+ freq_step = DEF_FREQUENCY_STEP;
- return freq_target;
+ return freq_step;
}
/*
@@ -55,10 +55,10 @@ static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
* sampling_down_factor, we check, if current idle time is more than 80%
* (default), then we try to decrease frequency
*
- * Any frequency increase takes it to the maximum frequency. Frequency reduction
- * happens at minimum steps of 5% (default) of maximum frequency
+ * Frequency updates happen at minimum steps of 5% (default) of maximum
+ * frequency
*/
-static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
+static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
{
struct policy_dbs_info *policy_dbs = policy->governor_data;
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
@@ -66,6 +66,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
struct dbs_data *dbs_data = policy_dbs->dbs_data;
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
unsigned int load = dbs_update(policy);
+ unsigned int freq_step;
/*
* break out if we 'cannot' reduce the speed as the user might
@@ -82,6 +83,23 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
if (requested_freq > policy->max || requested_freq < policy->min)
requested_freq = policy->cur;
+ freq_step = get_freq_step(cs_tuners, policy);
+
+ /*
+ * Decrease requested_freq one freq_step for each idle period that
+ * we didn't update the frequency.
+ */
+ if (policy_dbs->idle_periods < UINT_MAX) {
+ unsigned int freq_steps = policy_dbs->idle_periods * freq_step;
+
+ if (requested_freq > freq_steps)
+ requested_freq -= freq_steps;
+ else
+ requested_freq = policy->min;
+
+ policy_dbs->idle_periods = UINT_MAX;
+ }
+
/* Check for frequency increase */
if (load > dbs_data->up_threshold) {
dbs_info->down_skip = 0;
@@ -90,7 +108,7 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
if (requested_freq == policy->max)
goto out;
- requested_freq += get_freq_target(cs_tuners, policy);
+ requested_freq += freq_step;
if (requested_freq > policy->max)
requested_freq = policy->max;
@@ -106,16 +124,14 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
/* Check for frequency decrease */
if (load < cs_tuners->down_threshold) {
- unsigned int freq_target;
/*
* if we cannot reduce the frequency anymore, break out early
*/
if (requested_freq == policy->min)
goto out;
- freq_target = get_freq_target(cs_tuners, policy);
- if (requested_freq > freq_target)
- requested_freq -= freq_target;
+ if (requested_freq > freq_step)
+ requested_freq -= freq_step;
else
requested_freq = policy->min;
@@ -305,7 +321,7 @@ static void cs_start(struct cpufreq_policy *policy)
static struct dbs_governor cs_governor = {
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
.kobj_type = { .default_attrs = cs_attributes },
- .gov_dbs_timer = cs_dbs_timer,
+ .gov_dbs_update = cs_dbs_update,
.alloc = cs_alloc,
.free = cs_free,
.init = cs_init,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 642dd0f183a8..0196467280bd 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -61,7 +61,7 @@ ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
* entries can't be freed concurrently.
*/
list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
- mutex_lock(&policy_dbs->timer_mutex);
+ mutex_lock(&policy_dbs->update_mutex);
/*
* On 32-bit architectures this may race with the
* sample_delay_ns read in dbs_update_util_handler(), but that
@@ -76,7 +76,7 @@ ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
* taken, so it shouldn't be significant.
*/
gov_update_sample_delay(policy_dbs, 0);
- mutex_unlock(&policy_dbs->timer_mutex);
+ mutex_unlock(&policy_dbs->update_mutex);
}
return count;
@@ -117,7 +117,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
struct policy_dbs_info *policy_dbs = policy->governor_data;
struct dbs_data *dbs_data = policy_dbs->dbs_data;
unsigned int ignore_nice = dbs_data->ignore_nice_load;
- unsigned int max_load = 0;
+ unsigned int max_load = 0, idle_periods = UINT_MAX;
unsigned int sampling_rate, io_busy, j;
/*
@@ -215,9 +215,19 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
j_cdbs->prev_load = load;
}
+ if (time_elapsed > 2 * sampling_rate) {
+ unsigned int periods = time_elapsed / sampling_rate;
+
+ if (periods < idle_periods)
+ idle_periods = periods;
+ }
+
if (load > max_load)
max_load = load;
}
+
+ policy_dbs->idle_periods = idle_periods;
+
return max_load;
}
EXPORT_SYMBOL_GPL(dbs_update);
@@ -236,9 +246,9 @@ static void dbs_work_handler(struct work_struct *work)
* Make sure cpufreq_governor_limits() isn't evaluating load or the
* ondemand governor isn't updating the sampling rate in parallel.
*/
- mutex_lock(&policy_dbs->timer_mutex);
- gov_update_sample_delay(policy_dbs, gov->gov_dbs_timer(policy));
- mutex_unlock(&policy_dbs->timer_mutex);
+ mutex_lock(&policy_dbs->update_mutex);
+ gov_update_sample_delay(policy_dbs, gov->gov_dbs_update(policy));
+ mutex_unlock(&policy_dbs->update_mutex);
/* Allow the utilization update handler to queue up more work. */
atomic_set(&policy_dbs->work_count, 0);
@@ -348,7 +358,7 @@ static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *poli
return NULL;
policy_dbs->policy = policy;
- mutex_init(&policy_dbs->timer_mutex);
+ mutex_init(&policy_dbs->update_mutex);
atomic_set(&policy_dbs->work_count, 0);
init_irq_work(&policy_dbs->irq_work, dbs_irq_work);
INIT_WORK(&policy_dbs->work, dbs_work_handler);
@@ -367,7 +377,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
{
int j;
- mutex_destroy(&policy_dbs->timer_mutex);
+ mutex_destroy(&policy_dbs->update_mutex);
for_each_cpu(j, policy_dbs->policy->related_cpus) {
struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
@@ -547,10 +557,10 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{
struct policy_dbs_info *policy_dbs = policy->governor_data;
- mutex_lock(&policy_dbs->timer_mutex);
+ mutex_lock(&policy_dbs->update_mutex);
cpufreq_policy_apply_limits(policy);
gov_update_sample_delay(policy_dbs, 0);
- mutex_unlock(&policy_dbs->timer_mutex);
+ mutex_unlock(&policy_dbs->update_mutex);
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index ef1037e9c92b..f5717ca070cc 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -85,7 +85,7 @@ struct policy_dbs_info {
* Per policy mutex that serializes load evaluation from limit-change
* and work-handler.
*/
- struct mutex timer_mutex;
+ struct mutex update_mutex;
u64 last_sample_time;
s64 sample_delay_ns;
@@ -97,6 +97,7 @@ struct policy_dbs_info {
struct list_head list;
/* Multiplier for increasing sample delay temporarily. */
unsigned int rate_mult;
+ unsigned int idle_periods; /* For conservative */
/* Status indicators */
bool is_shared; /* This object is used by multiple CPUs */
bool work_in_progress; /* Work is being queued up or in progress */
@@ -135,7 +136,7 @@ struct dbs_governor {
*/
struct dbs_data *gdbs_data;
- unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
+ unsigned int (*gov_dbs_update)(struct cpufreq_policy *policy);
struct policy_dbs_info *(*alloc)(void);
void (*free)(struct policy_dbs_info *policy_dbs);
int (*init)(struct dbs_data *dbs_data);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 3a1f49f5f4c6..4a017e895296 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -25,7 +25,7 @@
#define MAX_SAMPLING_DOWN_FACTOR (100000)
#define MICRO_FREQUENCY_UP_THRESHOLD (95)
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
-#define MIN_FREQUENCY_UP_THRESHOLD (11)
+#define MIN_FREQUENCY_UP_THRESHOLD (1)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
static struct od_ops od_ops;
@@ -169,7 +169,7 @@ static void od_update(struct cpufreq_policy *policy)
}
}
-static unsigned int od_dbs_timer(struct cpufreq_policy *policy)
+static unsigned int od_dbs_update(struct cpufreq_policy *policy)
{
struct policy_dbs_info *policy_dbs = policy->governor_data;
struct dbs_data *dbs_data = policy_dbs->dbs_data;
@@ -191,7 +191,7 @@ static unsigned int od_dbs_timer(struct cpufreq_policy *policy)
od_update(policy);
if (dbs_info->freq_lo) {
- /* Setup timer for SUB_SAMPLE */
+ /* Setup SUB_SAMPLE */
dbs_info->sample_type = OD_SUB_SAMPLE;
return dbs_info->freq_hi_delay_us;
}
@@ -255,11 +255,11 @@ static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
/*
* Doing this without locking might lead to using different
- * rate_mult values in od_update() and od_dbs_timer().
+ * rate_mult values in od_update() and od_dbs_update().
*/
- mutex_lock(&policy_dbs->timer_mutex);
+ mutex_lock(&policy_dbs->update_mutex);
policy_dbs->rate_mult = 1;
- mutex_unlock(&policy_dbs->timer_mutex);
+ mutex_unlock(&policy_dbs->update_mutex);
}
return count;
@@ -374,8 +374,7 @@ static int od_init(struct dbs_data *dbs_data)
dbs_data->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
/*
* In nohz/micro accounting case we set the minimum frequency
- * not depending on HZ, but fixed (very low). The deferred
- * timer might skip some samples if idle/sleeping as needed.
+ * not depending on HZ, but fixed (very low).
*/
dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
} else {
@@ -415,7 +414,7 @@ static struct od_ops od_ops = {
static struct dbs_governor od_dbs_gov = {
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
.kobj_type = { .default_attrs = od_attributes },
- .gov_dbs_timer = od_dbs_timer,
+ .gov_dbs_update = od_dbs_update,
.alloc = od_alloc,
.free = od_free,
.init = od_init,
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 06d3abdffd3a..ac284e66839c 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -41,6 +41,18 @@ static int cpufreq_stats_update(struct cpufreq_stats *stats)
return 0;
}
+static void cpufreq_stats_clear_table(struct cpufreq_stats *stats)
+{
+ unsigned int count = stats->max_state;
+
+ memset(stats->time_in_state, 0, count * sizeof(u64));
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+ memset(stats->trans_table, 0, count * count * sizeof(int));
+#endif
+ stats->last_time = get_jiffies_64();
+ stats->total_trans = 0;
+}
+
static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
{
return sprintf(buf, "%d\n", policy->stats->total_trans);
@@ -64,6 +76,14 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
return len;
}
+static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf,
+ size_t count)
+{
+ /* We don't care what is written to the attribute. */
+ cpufreq_stats_clear_table(policy->stats);
+ return count;
+}
+
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
{
@@ -113,10 +133,12 @@ cpufreq_freq_attr_ro(trans_table);
cpufreq_freq_attr_ro(total_trans);
cpufreq_freq_attr_ro(time_in_state);
+cpufreq_freq_attr_wo(reset);
static struct attribute *default_attrs[] = {
&total_trans.attr,
&time_in_state.attr,
+ &reset.attr,
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
&trans_table.attr,
#endif
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
deleted file mode 100644
index 79e3ff2771a6..000000000000
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2001-2002 Deep Blue Solutions 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.
- *
- * CPU support functions
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware/icst.h>
-
-static void __iomem *cm_base;
-/* The cpufreq driver only use the OSC register */
-#define INTEGRATOR_HDR_OSC_OFFSET 0x08
-#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
-
-static struct cpufreq_driver integrator_driver;
-
-static const struct icst_params lclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 8,
- .vd_max = 132,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-static const struct icst_params cclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 12,
- .vd_max = 160,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-/*
- * Validate the speed policy.
- */
-static int integrator_verify_policy(struct cpufreq_policy *policy)
-{
- struct icst_vco vco;
-
- cpufreq_verify_within_cpu_limits(policy);
-
- vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
- policy->max = icst_hz(&cclk_params, vco) / 1000;
-
- vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
- policy->min = icst_hz(&cclk_params, vco) / 1000;
-
- cpufreq_verify_within_cpu_limits(policy);
- return 0;
-}
-
-
-static int integrator_set_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- cpumask_t cpus_allowed;
- int cpu = policy->cpu;
- struct icst_vco vco;
- struct cpufreq_freqs freqs;
- u_int cm_osc;
-
- /*
- * Save this threads cpus_allowed mask.
- */
- cpus_allowed = current->cpus_allowed;
-
- /*
- * Bind to the specified CPU. When this call returns,
- * we should be running on the right CPU.
- */
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* get current setting */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else if (machine_is_cintegrator())
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
- freqs.old = icst_hz(&cclk_params, vco) / 1000;
-
- /* icst_hz_to_vco rounds down -- so we need the next
- * larger freq in case of CPUFREQ_RELATION_L.
- */
- if (relation == CPUFREQ_RELATION_L)
- target_freq += 999;
- if (target_freq > policy->max)
- target_freq = policy->max;
- vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
- freqs.new = icst_hz(&cclk_params, vco) / 1000;
-
- if (freqs.old == freqs.new) {
- set_cpus_allowed_ptr(current, &cpus_allowed);
- return 0;
- }
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator()) {
- cm_osc &= 0xfffff800;
- cm_osc |= vco.s << 8;
- } else if (machine_is_cintegrator()) {
- cm_osc &= 0xffffff00;
- }
- cm_osc |= vco.v;
-
- __raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
- __raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET);
- __raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
-
- /*
- * Restore the CPUs allowed mask.
- */
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
- return 0;
-}
-
-static unsigned int integrator_get(unsigned int cpu)
-{
- cpumask_t cpus_allowed;
- unsigned int current_freq;
- u_int cm_osc;
- struct icst_vco vco;
-
- cpus_allowed = current->cpus_allowed;
-
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* detect memory etc. */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
-
- current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
-
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- return current_freq;
-}
-
-static int integrator_cpufreq_init(struct cpufreq_policy *policy)
-{
-
- /* set default policy and cpuinfo */
- policy->max = policy->cpuinfo.max_freq = 160000;
- policy->min = policy->cpuinfo.min_freq = 12000;
- policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-
- return 0;
-}
-
-static struct cpufreq_driver integrator_driver = {
- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = integrator_verify_policy,
- .target = integrator_set_target,
- .get = integrator_get,
- .init = integrator_cpufreq_init,
- .name = "integrator",
-};
-
-static int __init integrator_cpufreq_probe(struct platform_device *pdev)
-{
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!cm_base)
- return -ENODEV;
-
- return cpufreq_register_driver(&integrator_driver);
-}
-
-static int __exit integrator_cpufreq_remove(struct platform_device *pdev)
-{
- return cpufreq_unregister_driver(&integrator_driver);
-}
-
-static const struct of_device_id integrator_cpufreq_match[] = {
- { .compatible = "arm,core-module-integrator"},
- { },
-};
-
-MODULE_DEVICE_TABLE(of, integrator_cpufreq_match);
-
-static struct platform_driver integrator_cpufreq_driver = {
- .driver = {
- .name = "integrator-cpufreq",
- .of_match_table = integrator_cpufreq_match,
- },
- .remove = __exit_p(integrator_cpufreq_remove),
-};
-
-module_platform_driver_probe(integrator_cpufreq_driver,
- integrator_cpufreq_probe);
-
-MODULE_AUTHOR("Russell M. King");
-MODULE_DESCRIPTION("cpufreq driver for ARM Integrator CPUs");
-MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 4737520ec823..6acbd4af632e 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -37,6 +37,8 @@
#include <asm/cpufeature.h>
#include <asm/intel-family.h>
+#define INTEL_CPUFREQ_TRANSITION_LATENCY 20000
+
#define ATOM_RATIOS 0x66a
#define ATOM_VIDS 0x66b
#define ATOM_TURBO_RATIOS 0x66c
@@ -44,6 +46,7 @@
#ifdef CONFIG_ACPI
#include <acpi/processor.h>
+#include <acpi/cppc_acpi.h>
#endif
#define FRAC_BITS 8
@@ -52,6 +55,8 @@
#define EXT_BITS 6
#define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS)
+#define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS)
+#define int_ext_tofp(X) ((int64_t)(X) << EXT_FRAC_BITS)
static inline int32_t mul_fp(int32_t x, int32_t y)
{
@@ -122,6 +127,8 @@ struct sample {
* @scaling: Scaling factor to convert frequency to cpufreq
* frequency units
* @turbo_pstate: Max Turbo P state possible for this platform
+ * @max_freq: @max_pstate frequency in cpufreq units
+ * @turbo_freq: @turbo_pstate frequency in cpufreq units
*
* Stores the per cpu model P state limits and current P state.
*/
@@ -132,6 +139,8 @@ struct pstate_data {
int max_pstate_physical;
int scaling;
int turbo_pstate;
+ unsigned int max_freq;
+ unsigned int turbo_freq;
};
/**
@@ -177,6 +186,48 @@ struct _pid {
};
/**
+ * struct perf_limits - Store user and policy limits
+ * @no_turbo: User requested turbo state from intel_pstate sysfs
+ * @turbo_disabled: Platform turbo status either from msr
+ * MSR_IA32_MISC_ENABLE or when maximum available pstate
+ * matches the maximum turbo pstate
+ * @max_perf_pct: Effective maximum performance limit in percentage, this
+ * is minimum of either limits enforced by cpufreq policy
+ * or limits from user set limits via intel_pstate sysfs
+ * @min_perf_pct: Effective minimum performance limit in percentage, this
+ * is maximum of either limits enforced by cpufreq policy
+ * or limits from user set limits via intel_pstate sysfs
+ * @max_perf: This is a scaled value between 0 to 255 for max_perf_pct
+ * This value is used to limit max pstate
+ * @min_perf: This is a scaled value between 0 to 255 for min_perf_pct
+ * This value is used to limit min pstate
+ * @max_policy_pct: The maximum performance in percentage enforced by
+ * cpufreq setpolicy interface
+ * @max_sysfs_pct: The maximum performance in percentage enforced by
+ * intel pstate sysfs interface, unused when per cpu
+ * controls are enforced
+ * @min_policy_pct: The minimum performance in percentage enforced by
+ * cpufreq setpolicy interface
+ * @min_sysfs_pct: The minimum performance in percentage enforced by
+ * intel pstate sysfs interface, unused when per cpu
+ * controls are enforced
+ *
+ * Storage for user and policy defined limits.
+ */
+struct perf_limits {
+ int no_turbo;
+ int turbo_disabled;
+ int max_perf_pct;
+ int min_perf_pct;
+ int32_t max_perf;
+ int32_t min_perf;
+ int max_policy_pct;
+ int max_sysfs_pct;
+ int min_policy_pct;
+ int min_sysfs_pct;
+};
+
+/**
* struct cpudata - Per CPU instance data storage
* @cpu: CPU number for this instance data
* @policy: CPUFreq policy value
@@ -194,8 +245,19 @@ struct _pid {
* @prev_cummulative_iowait: IO Wait time difference from last and
* current sample
* @sample: Storage for storing last Sample data
+ * @perf_limits: Pointer to perf_limit unique to this CPU
+ * Not all field in the structure are applicable
+ * when per cpu controls are enforced
* @acpi_perf_data: Stores ACPI perf information read from _PSS
* @valid_pss_table: Set to true for valid ACPI _PSS entries found
+ * @epp_powersave: Last saved HWP energy performance preference
+ * (EPP) or energy performance bias (EPB),
+ * when policy switched to performance
+ * @epp_policy: Last saved policy used to set EPP/EPB
+ * @epp_default: Power on default HWP energy performance
+ * preference/bias
+ * @epp_saved: Saved EPP/EPB during system suspend or CPU offline
+ * operation
*
* This structure stores per CPU instance data for all CPUs.
*/
@@ -217,11 +279,16 @@ struct cpudata {
u64 prev_tsc;
u64 prev_cummulative_iowait;
struct sample sample;
+ struct perf_limits *perf_limits;
#ifdef CONFIG_ACPI
struct acpi_processor_performance acpi_perf_data;
bool valid_pss_table;
#endif
unsigned int iowait_boost;
+ s16 epp_powersave;
+ s16 epp_policy;
+ s16 epp_default;
+ s16 epp_saved;
};
static struct cpudata **all_cpu_data;
@@ -235,7 +302,6 @@ static struct cpudata **all_cpu_data;
* @p_gain_pct: PID proportional gain
* @i_gain_pct: PID integral gain
* @d_gain_pct: PID derivative gain
- * @boost_iowait: Whether or not to use iowait boosting.
*
* Stores per CPU model static PID configuration data.
*/
@@ -247,7 +313,6 @@ struct pstate_adjust_policy {
int p_gain_pct;
int d_gain_pct;
int i_gain_pct;
- bool boost_iowait;
};
/**
@@ -291,58 +356,19 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu);
static struct pstate_adjust_policy pid_params __read_mostly;
static struct pstate_funcs pstate_funcs __read_mostly;
static int hwp_active __read_mostly;
+static bool per_cpu_limits __read_mostly;
#ifdef CONFIG_ACPI
static bool acpi_ppc;
#endif
-/**
- * struct perf_limits - Store user and policy limits
- * @no_turbo: User requested turbo state from intel_pstate sysfs
- * @turbo_disabled: Platform turbo status either from msr
- * MSR_IA32_MISC_ENABLE or when maximum available pstate
- * matches the maximum turbo pstate
- * @max_perf_pct: Effective maximum performance limit in percentage, this
- * is minimum of either limits enforced by cpufreq policy
- * or limits from user set limits via intel_pstate sysfs
- * @min_perf_pct: Effective minimum performance limit in percentage, this
- * is maximum of either limits enforced by cpufreq policy
- * or limits from user set limits via intel_pstate sysfs
- * @max_perf: This is a scaled value between 0 to 255 for max_perf_pct
- * This value is used to limit max pstate
- * @min_perf: This is a scaled value between 0 to 255 for min_perf_pct
- * This value is used to limit min pstate
- * @max_policy_pct: The maximum performance in percentage enforced by
- * cpufreq setpolicy interface
- * @max_sysfs_pct: The maximum performance in percentage enforced by
- * intel pstate sysfs interface
- * @min_policy_pct: The minimum performance in percentage enforced by
- * cpufreq setpolicy interface
- * @min_sysfs_pct: The minimum performance in percentage enforced by
- * intel pstate sysfs interface
- *
- * Storage for user and policy defined limits.
- */
-struct perf_limits {
- int no_turbo;
- int turbo_disabled;
- int max_perf_pct;
- int min_perf_pct;
- int32_t max_perf;
- int32_t min_perf;
- int max_policy_pct;
- int max_sysfs_pct;
- int min_policy_pct;
- int min_sysfs_pct;
-};
-
static struct perf_limits performance_limits = {
.no_turbo = 0,
.turbo_disabled = 0,
.max_perf_pct = 100,
- .max_perf = int_tofp(1),
+ .max_perf = int_ext_tofp(1),
.min_perf_pct = 100,
- .min_perf = int_tofp(1),
+ .min_perf = int_ext_tofp(1),
.max_policy_pct = 100,
.max_sysfs_pct = 100,
.min_policy_pct = 0,
@@ -353,7 +379,7 @@ static struct perf_limits powersave_limits = {
.no_turbo = 0,
.turbo_disabled = 0,
.max_perf_pct = 100,
- .max_perf = int_tofp(1),
+ .max_perf = int_ext_tofp(1),
.min_perf_pct = 0,
.min_perf = 0,
.max_policy_pct = 100,
@@ -368,6 +394,8 @@ static struct perf_limits *limits = &performance_limits;
static struct perf_limits *limits = &powersave_limits;
#endif
+static DEFINE_MUTEX(intel_pstate_limits_lock);
+
#ifdef CONFIG_ACPI
static bool intel_pstate_get_ppc_enable_status(void)
@@ -379,14 +407,67 @@ static bool intel_pstate_get_ppc_enable_status(void)
return acpi_ppc;
}
+#ifdef CONFIG_ACPI_CPPC_LIB
+
+/* The work item is needed to avoid CPU hotplug locking issues */
+static void intel_pstste_sched_itmt_work_fn(struct work_struct *work)
+{
+ sched_set_itmt_support();
+}
+
+static DECLARE_WORK(sched_itmt_work, intel_pstste_sched_itmt_work_fn);
+
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+ struct cppc_perf_caps cppc_perf;
+ static u32 max_highest_perf = 0, min_highest_perf = U32_MAX;
+ int ret;
+
+ ret = cppc_get_perf_caps(cpu, &cppc_perf);
+ if (ret)
+ return;
+
+ /*
+ * The priorities can be set regardless of whether or not
+ * sched_set_itmt_support(true) has been called and it is valid to
+ * update them at any time after it has been called.
+ */
+ sched_set_itmt_core_prio(cppc_perf.highest_perf, cpu);
+
+ if (max_highest_perf <= min_highest_perf) {
+ if (cppc_perf.highest_perf > max_highest_perf)
+ max_highest_perf = cppc_perf.highest_perf;
+
+ if (cppc_perf.highest_perf < min_highest_perf)
+ min_highest_perf = cppc_perf.highest_perf;
+
+ if (max_highest_perf > min_highest_perf) {
+ /*
+ * This code can be run during CPU online under the
+ * CPU hotplug locks, so sched_set_itmt_support()
+ * cannot be called from here. Queue up a work item
+ * to invoke it.
+ */
+ schedule_work(&sched_itmt_work);
+ }
+ }
+}
+#else
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+}
+#endif
+
static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
{
struct cpudata *cpu;
int ret;
int i;
- if (hwp_active)
+ if (hwp_active) {
+ intel_pstate_set_itmt_prio(policy->cpu);
return;
+ }
if (!intel_pstate_get_ppc_enable_status())
return;
@@ -459,11 +540,11 @@ static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
}
#else
-static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
+static inline void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
{
}
-static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
+static inline void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
{
}
#endif
@@ -559,24 +640,252 @@ static inline void update_turbo_state(void)
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
}
+static s16 intel_pstate_get_epb(struct cpudata *cpu_data)
+{
+ u64 epb;
+ int ret;
+
+ if (!static_cpu_has(X86_FEATURE_EPB))
+ return -ENXIO;
+
+ ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb);
+ if (ret)
+ return (s16)ret;
+
+ return (s16)(epb & 0x0f);
+}
+
+static s16 intel_pstate_get_epp(struct cpudata *cpu_data, u64 hwp_req_data)
+{
+ s16 epp;
+
+ if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+ /*
+ * When hwp_req_data is 0, means that caller didn't read
+ * MSR_HWP_REQUEST, so need to read and get EPP.
+ */
+ if (!hwp_req_data) {
+ epp = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST,
+ &hwp_req_data);
+ if (epp)
+ return epp;
+ }
+ epp = (hwp_req_data >> 24) & 0xff;
+ } else {
+ /* When there is no EPP present, HWP uses EPB settings */
+ epp = intel_pstate_get_epb(cpu_data);
+ }
+
+ return epp;
+}
+
+static int intel_pstate_set_epb(int cpu, s16 pref)
+{
+ u64 epb;
+ int ret;
+
+ if (!static_cpu_has(X86_FEATURE_EPB))
+ return -ENXIO;
+
+ ret = rdmsrl_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb);
+ if (ret)
+ return ret;
+
+ epb = (epb & ~0x0f) | pref;
+ wrmsrl_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, epb);
+
+ return 0;
+}
+
+/*
+ * EPP/EPB display strings corresponding to EPP index in the
+ * energy_perf_strings[]
+ * index String
+ *-------------------------------------
+ * 0 default
+ * 1 performance
+ * 2 balance_performance
+ * 3 balance_power
+ * 4 power
+ */
+static const char * const energy_perf_strings[] = {
+ "default",
+ "performance",
+ "balance_performance",
+ "balance_power",
+ "power",
+ NULL
+};
+
+static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
+{
+ s16 epp;
+ int index = -EINVAL;
+
+ epp = intel_pstate_get_epp(cpu_data, 0);
+ if (epp < 0)
+ return epp;
+
+ if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+ /*
+ * Range:
+ * 0x00-0x3F : Performance
+ * 0x40-0x7F : Balance performance
+ * 0x80-0xBF : Balance power
+ * 0xC0-0xFF : Power
+ * The EPP is a 8 bit value, but our ranges restrict the
+ * value which can be set. Here only using top two bits
+ * effectively.
+ */
+ index = (epp >> 6) + 1;
+ } else if (static_cpu_has(X86_FEATURE_EPB)) {
+ /*
+ * Range:
+ * 0x00-0x03 : Performance
+ * 0x04-0x07 : Balance performance
+ * 0x08-0x0B : Balance power
+ * 0x0C-0x0F : Power
+ * The EPB is a 4 bit value, but our ranges restrict the
+ * value which can be set. Here only using top two bits
+ * effectively.
+ */
+ index = (epp >> 2) + 1;
+ }
+
+ return index;
+}
+
+static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
+ int pref_index)
+{
+ int epp = -EINVAL;
+ int ret;
+
+ if (!pref_index)
+ epp = cpu_data->epp_default;
+
+ mutex_lock(&intel_pstate_limits_lock);
+
+ if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+ u64 value;
+
+ ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, &value);
+ if (ret)
+ goto return_pref;
+
+ value &= ~GENMASK_ULL(31, 24);
+
+ /*
+ * If epp is not default, convert from index into
+ * energy_perf_strings to epp value, by shifting 6
+ * bits left to use only top two bits in epp.
+ * The resultant epp need to shifted by 24 bits to
+ * epp position in MSR_HWP_REQUEST.
+ */
+ if (epp == -EINVAL)
+ epp = (pref_index - 1) << 6;
+
+ value |= (u64)epp << 24;
+ ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
+ } else {
+ if (epp == -EINVAL)
+ epp = (pref_index - 1) << 2;
+ ret = intel_pstate_set_epb(cpu_data->cpu, epp);
+ }
+return_pref:
+ mutex_unlock(&intel_pstate_limits_lock);
+
+ return ret;
+}
+
+static ssize_t show_energy_performance_available_preferences(
+ struct cpufreq_policy *policy, char *buf)
+{
+ int i = 0;
+ int ret = 0;
+
+ while (energy_perf_strings[i] != NULL)
+ ret += sprintf(&buf[ret], "%s ", energy_perf_strings[i++]);
+
+ ret += sprintf(&buf[ret], "\n");
+
+ return ret;
+}
+
+cpufreq_freq_attr_ro(energy_performance_available_preferences);
+
+static ssize_t store_energy_performance_preference(
+ struct cpufreq_policy *policy, const char *buf, size_t count)
+{
+ struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+ char str_preference[21];
+ int ret, i = 0;
+
+ ret = sscanf(buf, "%20s", str_preference);
+ if (ret != 1)
+ return -EINVAL;
+
+ while (energy_perf_strings[i] != NULL) {
+ if (!strcmp(str_preference, energy_perf_strings[i])) {
+ intel_pstate_set_energy_pref_index(cpu_data, i);
+ return count;
+ }
+ ++i;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t show_energy_performance_preference(
+ struct cpufreq_policy *policy, char *buf)
+{
+ struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+ int preference;
+
+ preference = intel_pstate_get_energy_pref_index(cpu_data);
+ if (preference < 0)
+ return preference;
+
+ return sprintf(buf, "%s\n", energy_perf_strings[preference]);
+}
+
+cpufreq_freq_attr_rw(energy_performance_preference);
+
+static struct freq_attr *hwp_cpufreq_attrs[] = {
+ &energy_performance_preference,
+ &energy_performance_available_preferences,
+ NULL,
+};
+
static void intel_pstate_hwp_set(const struct cpumask *cpumask)
{
int min, hw_min, max, hw_max, cpu, range, adj_range;
+ struct perf_limits *perf_limits = limits;
u64 value, cap;
for_each_cpu(cpu, cpumask) {
+ int max_perf_pct, min_perf_pct;
+ struct cpudata *cpu_data = all_cpu_data[cpu];
+ s16 epp;
+
+ if (per_cpu_limits)
+ perf_limits = all_cpu_data[cpu]->perf_limits;
+
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
hw_min = HWP_LOWEST_PERF(cap);
hw_max = HWP_HIGHEST_PERF(cap);
range = hw_max - hw_min;
+ max_perf_pct = perf_limits->max_perf_pct;
+ min_perf_pct = perf_limits->min_perf_pct;
+
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
- adj_range = limits->min_perf_pct * range / 100;
+ adj_range = 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 = max_perf_pct * range / 100;
max = hw_min + adj_range;
if (limits->no_turbo) {
hw_max = HWP_GUARANTEED_PERF(cap);
@@ -586,6 +895,53 @@ static void intel_pstate_hwp_set(const struct cpumask *cpumask)
value &= ~HWP_MAX_PERF(~0L);
value |= HWP_MAX_PERF(max);
+
+ if (cpu_data->epp_policy == cpu_data->policy)
+ goto skip_epp;
+
+ cpu_data->epp_policy = cpu_data->policy;
+
+ if (cpu_data->epp_saved >= 0) {
+ epp = cpu_data->epp_saved;
+ cpu_data->epp_saved = -EINVAL;
+ goto update_epp;
+ }
+
+ if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE) {
+ epp = intel_pstate_get_epp(cpu_data, value);
+ cpu_data->epp_powersave = epp;
+ /* If EPP read was failed, then don't try to write */
+ if (epp < 0)
+ goto skip_epp;
+
+
+ epp = 0;
+ } else {
+ /* skip setting EPP, when saved value is invalid */
+ if (cpu_data->epp_powersave < 0)
+ goto skip_epp;
+
+ /*
+ * No need to restore EPP when it is not zero. This
+ * means:
+ * - Policy is not changed
+ * - user has manually changed
+ * - Error reading EPB
+ */
+ epp = intel_pstate_get_epp(cpu_data, value);
+ if (epp)
+ goto skip_epp;
+
+ epp = cpu_data->epp_powersave;
+ }
+update_epp:
+ if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+ value &= ~GENMASK_ULL(31, 24);
+ value |= (u64)epp << 24;
+ } else {
+ intel_pstate_set_epb(cpu, epp);
+ }
+skip_epp:
wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
}
}
@@ -598,6 +954,28 @@ static int intel_pstate_hwp_set_policy(struct cpufreq_policy *policy)
return 0;
}
+static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy)
+{
+ struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+
+ if (!hwp_active)
+ return 0;
+
+ cpu_data->epp_saved = intel_pstate_get_epp(cpu_data, 0);
+
+ return 0;
+}
+
+static int intel_pstate_resume(struct cpufreq_policy *policy)
+{
+ if (!hwp_active)
+ return 0;
+
+ all_cpu_data[policy->cpu]->epp_policy = 0;
+
+ return intel_pstate_hwp_set_policy(policy);
+}
+
static void intel_pstate_hwp_set_online_cpus(void)
{
get_online_cpus();
@@ -640,8 +1018,10 @@ static void __init intel_pstate_debug_expose_params(void)
struct dentry *debugfs_parent;
int i = 0;
- if (hwp_active)
+ if (hwp_active ||
+ pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load)
return;
+
debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
if (IS_ERR_OR_NULL(debugfs_parent))
return;
@@ -714,9 +1094,12 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
+ mutex_lock(&intel_pstate_limits_lock);
+
update_turbo_state();
if (limits->turbo_disabled) {
pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
+ mutex_unlock(&intel_pstate_limits_lock);
return -EPERM;
}
@@ -725,6 +1108,8 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
if (hwp_active)
intel_pstate_hwp_set_online_cpus();
+ mutex_unlock(&intel_pstate_limits_lock);
+
return count;
}
@@ -738,6 +1123,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
+ mutex_lock(&intel_pstate_limits_lock);
+
limits->max_sysfs_pct = clamp_t(int, input, 0 , 100);
limits->max_perf_pct = min(limits->max_policy_pct,
limits->max_sysfs_pct);
@@ -745,10 +1132,13 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
limits->max_perf_pct);
limits->max_perf_pct = max(limits->min_perf_pct,
limits->max_perf_pct);
- limits->max_perf = div_fp(limits->max_perf_pct, 100);
+ limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
if (hwp_active)
intel_pstate_hwp_set_online_cpus();
+
+ mutex_unlock(&intel_pstate_limits_lock);
+
return count;
}
@@ -762,6 +1152,8 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
+ mutex_lock(&intel_pstate_limits_lock);
+
limits->min_sysfs_pct = clamp_t(int, input, 0 , 100);
limits->min_perf_pct = max(limits->min_policy_pct,
limits->min_sysfs_pct);
@@ -769,10 +1161,13 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
limits->min_perf_pct);
limits->min_perf_pct = min(limits->max_perf_pct,
limits->min_perf_pct);
- limits->min_perf = div_fp(limits->min_perf_pct, 100);
+ limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
if (hwp_active)
intel_pstate_hwp_set_online_cpus();
+
+ mutex_unlock(&intel_pstate_limits_lock);
+
return count;
}
@@ -787,8 +1182,6 @@ define_one_global_ro(num_pstates);
static struct attribute *intel_pstate_attributes[] = {
&no_turbo.attr,
- &max_perf_pct.attr,
- &min_perf_pct.attr,
&turbo_pct.attr,
&num_pstates.attr,
NULL
@@ -805,9 +1198,26 @@ static void __init intel_pstate_sysfs_expose_params(void)
intel_pstate_kobject = kobject_create_and_add("intel_pstate",
&cpu_subsys.dev_root->kobj);
- BUG_ON(!intel_pstate_kobject);
+ if (WARN_ON(!intel_pstate_kobject))
+ return;
+
rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
- BUG_ON(rc);
+ if (WARN_ON(rc))
+ return;
+
+ /*
+ * If per cpu limits are enforced there are no global limits, so
+ * return without creating max/min_perf_pct attributes
+ */
+ if (per_cpu_limits)
+ return;
+
+ rc = sysfs_create_file(intel_pstate_kobject, &max_perf_pct.attr);
+ WARN_ON(rc);
+
+ rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr);
+ WARN_ON(rc);
+
}
/************************** sysfs end ************************/
@@ -818,6 +1228,9 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
+ cpudata->epp_policy = 0;
+ if (cpudata->epp_default == -EINVAL)
+ cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
}
static int atom_get_min_pstate(void)
@@ -1045,7 +1458,6 @@ static const struct cpu_defaults silvermont_params = {
.p_gain_pct = 14,
.d_gain_pct = 0,
.i_gain_pct = 4,
- .boost_iowait = true,
},
.funcs = {
.get_max = atom_get_max_pstate,
@@ -1067,7 +1479,6 @@ static const struct cpu_defaults airmont_params = {
.p_gain_pct = 14,
.d_gain_pct = 0,
.i_gain_pct = 4,
- .boost_iowait = true,
},
.funcs = {
.get_max = atom_get_max_pstate,
@@ -1109,7 +1520,6 @@ static const struct cpu_defaults bxt_params = {
.p_gain_pct = 14,
.d_gain_pct = 0,
.i_gain_pct = 4,
- .boost_iowait = true,
},
.funcs = {
.get_max = core_get_max_pstate,
@@ -1127,20 +1537,24 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
int max_perf = cpu->pstate.turbo_pstate;
int max_perf_adj;
int min_perf;
+ struct perf_limits *perf_limits = limits;
if (limits->no_turbo || limits->turbo_disabled)
max_perf = cpu->pstate.max_pstate;
+ if (per_cpu_limits)
+ perf_limits = cpu->perf_limits;
+
/*
* performance can be limited by user through sysfs, by cpufreq
* policy, or by cpu specific default values determined through
* experimentation.
*/
- max_perf_adj = fp_toint(max_perf * limits->max_perf);
+ max_perf_adj = fp_ext_toint(max_perf * perf_limits->max_perf);
*max = clamp_t(int, max_perf_adj,
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
- min_perf = fp_toint(max_perf * limits->min_perf);
+ min_perf = fp_ext_toint(max_perf * perf_limits->min_perf);
*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
}
@@ -1178,6 +1592,8 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
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();
+ cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
+ cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu);
@@ -1316,15 +1732,19 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
return cpu->pstate.current_pstate - pid_calc(&cpu->pid, perf_scaled);
}
-static inline void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
+static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate)
{
int max_perf, min_perf;
- update_turbo_state();
-
intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
pstate = clamp_t(int, pstate, min_perf, max_perf);
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
+ return pstate;
+}
+
+static void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
+{
+ pstate = intel_pstate_prepare_request(cpu, pstate);
if (pstate == cpu->pstate.current_pstate)
return;
@@ -1342,6 +1762,8 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
target_pstate = cpu->policy == CPUFREQ_POLICY_PERFORMANCE ?
cpu->pstate.turbo_pstate : pstate_funcs.get_target_pstate(cpu);
+ update_turbo_state();
+
intel_pstate_update_pstate(cpu, target_pstate);
sample = &cpu->sample;
@@ -1362,7 +1784,7 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time,
struct cpudata *cpu = container_of(data, struct cpudata, update_util);
u64 delta_ns;
- if (pid_params.boost_iowait) {
+ if (pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load) {
if (flags & SCHED_CPUFREQ_IOWAIT) {
cpu->iowait_boost = int_tofp(1);
} else if (cpu->iowait_boost) {
@@ -1408,6 +1830,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params),
ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params),
+ ICPU(INTEL_FAM6_XEON_PHI_KNM, knl_params),
ICPU(INTEL_FAM6_ATOM_GOLDMONT, bxt_params),
{}
};
@@ -1424,11 +1847,26 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
{
struct cpudata *cpu;
- if (!all_cpu_data[cpunum])
- all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata),
- GFP_KERNEL);
- if (!all_cpu_data[cpunum])
- return -ENOMEM;
+ cpu = all_cpu_data[cpunum];
+
+ if (!cpu) {
+ unsigned int size = sizeof(struct cpudata);
+
+ if (per_cpu_limits)
+ size += sizeof(struct perf_limits);
+
+ cpu = kzalloc(size, GFP_KERNEL);
+ if (!cpu)
+ return -ENOMEM;
+
+ all_cpu_data[cpunum] = cpu;
+ if (per_cpu_limits)
+ cpu->perf_limits = (struct perf_limits *)(cpu + 1);
+
+ cpu->epp_default = -EINVAL;
+ cpu->epp_powersave = -EINVAL;
+ cpu->epp_saved = -EINVAL;
+ }
cpu = all_cpu_data[cpunum];
@@ -1487,18 +1925,57 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits)
limits->no_turbo = 0;
limits->turbo_disabled = 0;
limits->max_perf_pct = 100;
- limits->max_perf = int_tofp(1);
+ limits->max_perf = int_ext_tofp(1);
limits->min_perf_pct = 100;
- limits->min_perf = int_tofp(1);
+ limits->min_perf = int_ext_tofp(1);
limits->max_policy_pct = 100;
limits->max_sysfs_pct = 100;
limits->min_policy_pct = 0;
limits->min_sysfs_pct = 0;
}
+static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
+ struct perf_limits *limits)
+{
+
+ limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
+ policy->cpuinfo.max_freq);
+ limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100);
+ if (policy->max == policy->min) {
+ limits->min_policy_pct = limits->max_policy_pct;
+ } else {
+ limits->min_policy_pct = DIV_ROUND_UP(policy->min * 100,
+ policy->cpuinfo.max_freq);
+ limits->min_policy_pct = clamp_t(int, limits->min_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);
+
+ /* Make sure min_perf_pct <= max_perf_pct */
+ limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
+
+ limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
+ limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
+ limits->max_perf = round_up(limits->max_perf, EXT_FRAC_BITS);
+ limits->min_perf = round_up(limits->min_perf, EXT_FRAC_BITS);
+
+ pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
+ limits->max_perf_pct, limits->min_perf_pct);
+}
+
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
{
struct cpudata *cpu;
+ struct perf_limits *perf_limits = NULL;
if (!policy->cpuinfo.max_freq)
return -ENODEV;
@@ -1516,41 +1993,31 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
policy->max = policy->cpuinfo.max_freq;
}
- if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
- limits = &performance_limits;
+ if (per_cpu_limits)
+ perf_limits = cpu->perf_limits;
+
+ mutex_lock(&intel_pstate_limits_lock);
+
+ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+ if (!perf_limits) {
+ limits = &performance_limits;
+ perf_limits = limits;
+ }
if (policy->max >= policy->cpuinfo.max_freq) {
pr_debug("set performance\n");
- intel_pstate_set_performance_limits(limits);
+ intel_pstate_set_performance_limits(perf_limits);
goto out;
}
} else {
pr_debug("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 = DIV_ROUND_UP(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);
-
- /* Make sure min_perf_pct <= max_perf_pct */
- limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
+ if (!perf_limits) {
+ limits = &powersave_limits;
+ perf_limits = limits;
+ }
- limits->min_perf = div_fp(limits->min_perf_pct, 100);
- limits->max_perf = div_fp(limits->max_perf_pct, 100);
- limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
+ }
+ intel_pstate_update_perf_limits(policy, perf_limits);
out:
if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
/*
@@ -1565,6 +2032,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
intel_pstate_hwp_set_policy(policy);
+ mutex_unlock(&intel_pstate_limits_lock);
+
return 0;
}
@@ -1579,22 +2048,32 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
return 0;
}
+static void intel_cpufreq_stop_cpu(struct cpufreq_policy *policy)
+{
+ intel_pstate_set_min_pstate(all_cpu_data[policy->cpu]);
+}
+
static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
{
- int cpu_num = policy->cpu;
- struct cpudata *cpu = all_cpu_data[cpu_num];
+ pr_debug("CPU %d exiting\n", policy->cpu);
- pr_debug("CPU %d exiting\n", cpu_num);
+ intel_pstate_clear_update_util_hook(policy->cpu);
+ if (hwp_active)
+ intel_pstate_hwp_save_state(policy);
+ else
+ intel_cpufreq_stop_cpu(policy);
+}
- intel_pstate_clear_update_util_hook(cpu_num);
+static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
+{
+ intel_pstate_exit_perf_limits(policy);
- if (hwp_active)
- return;
+ policy->fast_switch_possible = false;
- intel_pstate_set_min_pstate(cpu);
+ return 0;
}
-static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
+static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
{
struct cpudata *cpu;
int rc;
@@ -1605,10 +2084,13 @@ 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)
- policy->policy = CPUFREQ_POLICY_PERFORMANCE;
- else
- policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ /*
+ * We need sane value in the cpu->perf_limits, so inherit from global
+ * perf_limits limits, which are seeded with values based on the
+ * CONFIG_CPU_FREQ_DEFAULT_GOV_*, during boot up.
+ */
+ if (per_cpu_limits)
+ memcpy(cpu->perf_limits, limits, sizeof(struct perf_limits));
policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
@@ -1621,24 +2103,35 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq *= cpu->pstate.scaling;
intel_pstate_init_acpi_perf_limits(policy);
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
cpumask_set_cpu(policy->cpu, policy->cpus);
+ policy->fast_switch_possible = true;
+
return 0;
}
-static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
+static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
{
- intel_pstate_exit_perf_limits(policy);
+ int ret = __intel_pstate_cpu_init(policy);
+
+ if (ret)
+ return ret;
+
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ else
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
-static struct cpufreq_driver intel_pstate_driver = {
+static struct cpufreq_driver intel_pstate = {
.flags = CPUFREQ_CONST_LOOPS,
.verify = intel_pstate_verify_policy,
.setpolicy = intel_pstate_set_policy,
- .resume = intel_pstate_hwp_set_policy,
+ .suspend = intel_pstate_hwp_save_state,
+ .resume = intel_pstate_resume,
.get = intel_pstate_get,
.init = intel_pstate_cpu_init,
.exit = intel_pstate_cpu_exit,
@@ -1646,6 +2139,118 @@ static struct cpufreq_driver intel_pstate_driver = {
.name = "intel_pstate",
};
+static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
+{
+ struct cpudata *cpu = all_cpu_data[policy->cpu];
+ struct perf_limits *perf_limits = limits;
+
+ update_turbo_state();
+ policy->cpuinfo.max_freq = limits->turbo_disabled ?
+ cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+
+ cpufreq_verify_within_cpu_limits(policy);
+
+ if (per_cpu_limits)
+ perf_limits = cpu->perf_limits;
+
+ intel_pstate_update_perf_limits(policy, perf_limits);
+
+ return 0;
+}
+
+static unsigned int intel_cpufreq_turbo_update(struct cpudata *cpu,
+ struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ unsigned int max_freq;
+
+ update_turbo_state();
+
+ max_freq = limits->no_turbo || limits->turbo_disabled ?
+ cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+ policy->cpuinfo.max_freq = max_freq;
+ if (policy->max > max_freq)
+ policy->max = max_freq;
+
+ if (target_freq > max_freq)
+ target_freq = max_freq;
+
+ return target_freq;
+}
+
+static int intel_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpudata *cpu = all_cpu_data[policy->cpu];
+ struct cpufreq_freqs freqs;
+ int target_pstate;
+
+ freqs.old = policy->cur;
+ freqs.new = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+
+ cpufreq_freq_transition_begin(policy, &freqs);
+ switch (relation) {
+ case CPUFREQ_RELATION_L:
+ target_pstate = DIV_ROUND_UP(freqs.new, cpu->pstate.scaling);
+ break;
+ case CPUFREQ_RELATION_H:
+ target_pstate = freqs.new / cpu->pstate.scaling;
+ break;
+ default:
+ target_pstate = DIV_ROUND_CLOSEST(freqs.new, cpu->pstate.scaling);
+ break;
+ }
+ target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
+ if (target_pstate != cpu->pstate.current_pstate) {
+ cpu->pstate.current_pstate = target_pstate;
+ wrmsrl_on_cpu(policy->cpu, MSR_IA32_PERF_CTL,
+ pstate_funcs.get_val(cpu, target_pstate));
+ }
+ cpufreq_freq_transition_end(policy, &freqs, false);
+
+ return 0;
+}
+
+static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ struct cpudata *cpu = all_cpu_data[policy->cpu];
+ int target_pstate;
+
+ target_freq = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+ target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
+ intel_pstate_update_pstate(cpu, target_pstate);
+ return target_freq;
+}
+
+static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ int ret = __intel_pstate_cpu_init(policy);
+
+ if (ret)
+ return ret;
+
+ policy->cpuinfo.transition_latency = INTEL_CPUFREQ_TRANSITION_LATENCY;
+ /* This reflects the intel_pstate_get_cpu_pstates() setting. */
+ policy->cur = policy->cpuinfo.min_freq;
+
+ return 0;
+}
+
+static struct cpufreq_driver intel_cpufreq = {
+ .flags = CPUFREQ_CONST_LOOPS,
+ .verify = intel_cpufreq_verify_policy,
+ .target = intel_cpufreq_target,
+ .fast_switch = intel_cpufreq_fast_switch,
+ .init = intel_cpufreq_cpu_init,
+ .exit = intel_pstate_cpu_exit,
+ .stop_cpu = intel_cpufreq_stop_cpu,
+ .name = "intel_cpufreq",
+};
+
+static struct cpufreq_driver *intel_pstate_driver = &intel_pstate;
+
static int no_load __initdata;
static int no_hwp __initdata;
static int hwp_only __initdata;
@@ -1672,6 +2277,19 @@ static void __init copy_pid_params(struct pstate_adjust_policy *policy)
pid_params.setpoint = policy->setpoint;
}
+#ifdef CONFIG_ACPI
+static void intel_pstate_use_acpi_profile(void)
+{
+ if (acpi_gbl_FADT.preferred_profile == PM_MOBILE)
+ pstate_funcs.get_target_pstate =
+ get_target_pstate_use_cpu_load;
+}
+#else
+static void intel_pstate_use_acpi_profile(void)
+{
+}
+#endif
+
static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
{
pstate_funcs.get_max = funcs->get_max;
@@ -1683,6 +2301,7 @@ static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
pstate_funcs.get_vid = funcs->get_vid;
pstate_funcs.get_target_pstate = funcs->get_target_pstate;
+ intel_pstate_use_acpi_profile();
}
#ifdef CONFIG_ACPI
@@ -1796,9 +2415,20 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
return false;
}
+
+static void intel_pstate_request_control_from_smm(void)
+{
+ /*
+ * It may be unsafe to request P-states control from SMM if _PPC support
+ * has not been enabled.
+ */
+ if (acpi_ppc)
+ acpi_processor_pstate_control();
+}
#else /* CONFIG_ACPI not enabled */
static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
+static inline void intel_pstate_request_control_from_smm(void) {}
#endif /* CONFIG_ACPI */
static const struct x86_cpu_id hwp_support_ids[] __initconst = {
@@ -1818,6 +2448,7 @@ static int __init intel_pstate_init(void)
if (x86_match_cpu(hwp_support_ids) && !no_hwp) {
copy_cpu_funcs(&core_params.funcs);
hwp_active++;
+ intel_pstate.attr = hwp_cpufreq_attrs;
goto hwp_cpu_matched;
}
@@ -1850,7 +2481,9 @@ hwp_cpu_matched:
if (!hwp_active && hwp_only)
goto out;
- rc = cpufreq_register_driver(&intel_pstate_driver);
+ intel_pstate_request_control_from_smm();
+
+ rc = cpufreq_register_driver(intel_pstate_driver);
if (rc)
goto out;
@@ -1865,7 +2498,9 @@ out:
get_online_cpus();
for_each_online_cpu(cpu) {
if (all_cpu_data[cpu]) {
- intel_pstate_clear_update_util_hook(cpu);
+ if (intel_pstate_driver == &intel_pstate)
+ intel_pstate_clear_update_util_hook(cpu);
+
kfree(all_cpu_data[cpu]);
}
}
@@ -1881,8 +2516,13 @@ static int __init intel_pstate_setup(char *str)
if (!str)
return -EINVAL;
- if (!strcmp(str, "disable"))
+ if (!strcmp(str, "disable")) {
no_load = 1;
+ } else if (!strcmp(str, "passive")) {
+ pr_info("Passive mode enabled\n");
+ intel_pstate_driver = &intel_cpufreq;
+ no_hwp = 1;
+ }
if (!strcmp(str, "no_hwp")) {
pr_info("HWP disabled\n");
no_hwp = 1;
@@ -1891,6 +2531,8 @@ static int __init intel_pstate_setup(char *str)
force_load = 1;
if (!strcmp(str, "hwp_only"))
hwp_only = 1;
+ if (!strcmp(str, "per_cpu_perf_limits"))
+ per_cpu_limits = true;
#ifdef CONFIG_ACPI
if (!strcmp(str, "support_acpi_ppc"))
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index d3ffde806629..37671b545880 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -42,6 +42,10 @@
#define PMSR_PSAFE_ENABLE (1UL << 30)
#define PMSR_SPR_EM_DISABLE (1UL << 31)
#define PMSR_MAX(x) ((x >> 32) & 0xFF)
+#define LPSTATE_SHIFT 48
+#define GPSTATE_SHIFT 56
+#define GET_LPSTATE(x) (((x) >> LPSTATE_SHIFT) & 0xFF)
+#define GET_GPSTATE(x) (((x) >> GPSTATE_SHIFT) & 0xFF)
#define MAX_RAMP_DOWN_TIME 5120
/*
@@ -592,7 +596,8 @@ void gpstate_timer_handler(unsigned long data)
{
struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
struct global_pstate_info *gpstates = policy->driver_data;
- int gpstate_idx;
+ int gpstate_idx, lpstate_idx;
+ unsigned long val;
unsigned int time_diff = jiffies_to_msecs(jiffies)
- gpstates->last_sampled_time;
struct powernv_smp_call_data freq_data;
@@ -600,21 +605,37 @@ void gpstate_timer_handler(unsigned long data)
if (!spin_trylock(&gpstates->gpstate_lock))
return;
+ /*
+ * If PMCR was last updated was using fast_swtich then
+ * We may have wrong in gpstate->last_lpstate_idx
+ * value. Hence, read from PMCR to get correct data.
+ */
+ val = get_pmspr(SPRN_PMCR);
+ freq_data.gpstate_id = (s8)GET_GPSTATE(val);
+ freq_data.pstate_id = (s8)GET_LPSTATE(val);
+ if (freq_data.gpstate_id == freq_data.pstate_id) {
+ reset_gpstates(policy);
+ spin_unlock(&gpstates->gpstate_lock);
+ return;
+ }
+
gpstates->last_sampled_time += time_diff;
gpstates->elapsed_time += time_diff;
- freq_data.pstate_id = idx_to_pstate(gpstates->last_lpstate_idx);
- if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) ||
- (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) {
+ if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) {
gpstate_idx = pstate_to_idx(freq_data.pstate_id);
+ lpstate_idx = gpstate_idx;
reset_gpstates(policy);
gpstates->highest_lpstate_idx = gpstate_idx;
} else {
+ lpstate_idx = pstate_to_idx(freq_data.pstate_id);
gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
gpstates->highest_lpstate_idx,
- gpstates->last_lpstate_idx);
+ lpstate_idx);
}
-
+ freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
+ gpstates->last_gpstate_idx = gpstate_idx;
+ gpstates->last_lpstate_idx = lpstate_idx;
/*
* If local pstate is equal to global pstate, rampdown is over
* So timer is not required to be queued.
@@ -622,10 +643,6 @@ void gpstate_timer_handler(unsigned long data)
if (gpstate_idx != gpstates->last_lpstate_idx)
queue_gpstate_timer(gpstates);
- freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
- gpstates->last_gpstate_idx = pstate_to_idx(freq_data.gpstate_id);
- gpstates->last_lpstate_idx = pstate_to_idx(freq_data.pstate_id);
-
spin_unlock(&gpstates->gpstate_lock);
/* Timer may get migrated to a different cpu on cpu hot unplug */
@@ -647,8 +664,14 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
if (unlikely(rebooting) && new_index != get_nominal_index())
return 0;
- if (!throttled)
+ if (!throttled) {
+ /* we don't want to be preempted while
+ * checking if the CPU frequency has been throttled
+ */
+ preempt_disable();
powernv_cpufreq_throttle_check(NULL);
+ preempt_enable();
+ }
cur_msec = jiffies_to_msecs(get_jiffies_64());
@@ -752,9 +775,12 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
spin_lock_init(&gpstates->gpstate_lock);
ret = cpufreq_table_validate_and_show(policy, powernv_freqs);
- if (ret < 0)
+ if (ret < 0) {
kfree(policy->driver_data);
+ return ret;
+ }
+ policy->fast_switch_possible = true;
return ret;
}
@@ -897,6 +923,20 @@ static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
del_timer_sync(&gpstates->timer);
}
+static unsigned int powernv_fast_switch(struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ int index;
+ struct powernv_smp_call_data freq_data;
+
+ index = cpufreq_table_find_index_dl(policy, target_freq);
+ freq_data.pstate_id = powernv_freqs[index].driver_data;
+ freq_data.gpstate_id = powernv_freqs[index].driver_data;
+ set_pstate(&freq_data);
+
+ return powernv_freqs[index].frequency;
+}
+
static struct cpufreq_driver powernv_cpufreq_driver = {
.name = "powernv-cpufreq",
.flags = CPUFREQ_CONST_LOOPS,
@@ -904,6 +944,7 @@ static struct cpufreq_driver powernv_cpufreq_driver = {
.exit = powernv_cpufreq_cpu_exit,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = powernv_cpufreq_target_index,
+ .fast_switch = powernv_fast_switch,
.get = powernv_cpufreq_get,
.stop_cpu = powernv_cpufreq_stop_cpu,
.attr = powernv_cpu_freq_attr,
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 7fe442ca38f4..0835a37a5f3a 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -22,7 +22,7 @@
#define POWERNV_THRESHOLD_LATENCY_NS 200000
-struct cpuidle_driver powernv_idle_driver = {
+static struct cpuidle_driver powernv_idle_driver = {
.name = "powernv_idle",
.owner = THIS_MODULE,
};
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index c73207abb5a4..62810ff3b00f 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -97,7 +97,23 @@ static int find_deepest_state(struct cpuidle_driver *drv,
return ret;
}
-#ifdef CONFIG_SUSPEND
+/**
+ * cpuidle_use_deepest_state - Set/clear governor override flag.
+ * @enable: New value of the flag.
+ *
+ * Set/unset the current CPU to use the deepest idle state (override governors
+ * going forward if set).
+ */
+void cpuidle_use_deepest_state(bool enable)
+{
+ struct cpuidle_device *dev;
+
+ preempt_disable();
+ dev = cpuidle_get_device();
+ dev->use_deepest_state = enable;
+ preempt_enable();
+}
+
/**
* cpuidle_find_deepest_state - Find the deepest available idle state.
* @drv: cpuidle driver for the given CPU.
@@ -109,6 +125,7 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
return find_deepest_state(drv, dev, UINT_MAX, 0, false);
}
+#ifdef CONFIG_SUSPEND
static void enter_freeze_proper(struct cpuidle_driver *drv,
struct cpuidle_device *dev, int index)
{
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index a5c111b67f37..ffca4fc0061d 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -38,6 +38,12 @@ static int init_state_node(struct cpuidle_state *idle_state,
* state enter function.
*/
idle_state->enter = match_id->data;
+ /*
+ * Since this is not a "coupled" state, it's safe to assume interrupts
+ * won't be enabled when it exits allowing the tick to be frozen
+ * safely. So enter() can be also enter_freeze() callback.
+ */
+ idle_state->enter_freeze = match_id->data;
err = of_property_read_u32(state_node, "wakeup-latency-us",
&idle_state->exit_latency);
diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c
index fb9f511cca23..4e78263e34a4 100644
--- a/drivers/cpuidle/governor.c
+++ b/drivers/cpuidle/governor.c
@@ -9,7 +9,6 @@
*/
#include <linux/mutex.h>
-#include <linux/module.h>
#include <linux/cpuidle.h>
#include "cpuidle.h"
@@ -53,14 +52,11 @@ int cpuidle_switch_governor(struct cpuidle_governor *gov)
if (cpuidle_curr_governor) {
list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
cpuidle_disable_device(dev);
- module_put(cpuidle_curr_governor->owner);
}
cpuidle_curr_governor = gov;
if (gov) {
- if (!try_module_get(cpuidle_curr_governor->owner))
- return -EINVAL;
list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
cpuidle_enable_device(dev);
cpuidle_install_idle_handler();
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 63bd5a403e22..fe8f08948fcb 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/cpuidle.h>
#include <linux/pm_qos.h>
-#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/tick.h>
@@ -177,7 +176,6 @@ static struct cpuidle_governor ladder_governor = {
.enable = ladder_enable_device,
.select = ladder_select_state,
.reflect = ladder_reflect,
- .owner = THIS_MODULE,
};
/**
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 03d38c291de6..d9b5b9398a0f 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -19,7 +19,6 @@
#include <linux/tick.h>
#include <linux/sched.h>
#include <linux/math64.h>
-#include <linux/module.h>
/*
* Please note when changing the tuning values:
@@ -484,7 +483,6 @@ static struct cpuidle_governor menu_governor = {
.enable = menu_enable_device,
.select = menu_select,
.reflect = menu_reflect,
- .owner = THIS_MODULE,
};
/**
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 832a2c3f01ff..c5adc8c9ac43 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -403,8 +403,10 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
/* state statistics */
for (i = 0; i < drv->state_count; i++) {
kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
- if (!kobj)
+ if (!kobj) {
+ ret = -ENOMEM;
goto error_state;
+ }
kobj->state = &drv->states[i];
kobj->state_usage = &device->states_usage[i];
init_completion(&kobj->kobj_unregister);
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index e4ddb921d7b3..56b153805462 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -592,16 +592,18 @@ badkey_err:
static int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
{
- int ret = 0;
- struct sge_ofld_txq *q;
struct adapter *adap = netdev2adap(dev);
+ struct sge_uld_txq_info *txq_info =
+ adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+ struct sge_uld_txq *txq;
+ int ret = 0;
local_bh_disable();
- q = &adap->sge.ofldtxq[idx];
- spin_lock(&q->sendq.lock);
- if (q->full)
+ txq = &txq_info->uldtxq[idx];
+ spin_lock(&txq->sendq.lock);
+ if (txq->full)
ret = -1;
- spin_unlock(&q->sendq.lock);
+ spin_unlock(&txq->sendq.lock);
local_bh_enable();
return ret;
}
@@ -674,11 +676,11 @@ static int chcr_device_init(struct chcr_context *ctx)
}
u_ctx = ULD_CTX(ctx);
rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
- ctx->dev->tx_channel_id = 0;
rxq_idx = ctx->dev->tx_channel_id * rxq_perchan;
rxq_idx += id % rxq_perchan;
spin_lock(&ctx->dev->lock_chcr_dev);
ctx->tx_channel_id = rxq_idx;
+ ctx->dev->tx_channel_id = !ctx->dev->tx_channel_id;
spin_unlock(&ctx->dev->lock_chcr_dev);
}
out:
diff --git a/drivers/crypto/chelsio/chcr_core.c b/drivers/crypto/chelsio/chcr_core.c
index fb5f9bbfa09c..4d7f6700fd7e 100644
--- a/drivers/crypto/chelsio/chcr_core.c
+++ b/drivers/crypto/chelsio/chcr_core.c
@@ -42,6 +42,7 @@ static chcr_handler_func work_handlers[NUM_CPL_CMDS] = {
static struct cxgb4_uld_info chcr_uld_info = {
.name = DRV_MODULE_NAME,
.nrxq = MAX_ULD_QSETS,
+ .ntxq = MAX_ULD_QSETS,
.rxq_size = 1024,
.add = chcr_uld_add,
.state_change = chcr_uld_state_change,
@@ -126,7 +127,7 @@ static int cpl_fw6_pld_handler(struct chcr_dev *dev,
int chcr_send_wr(struct sk_buff *skb)
{
- return cxgb4_ofld_send(skb->dev, skb);
+ return cxgb4_crypto_send(skb->dev, skb);
}
static void *chcr_uld_add(const struct cxgb4_lld_info *lld)
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 441e86b23571..b3869748cc6b 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -183,8 +183,8 @@ static inline void padlock_store_cword(struct cword *cword)
/*
* While the padlock instructions don't use FP/SSE registers, they
- * generate a spurious DNA fault when cr0.ts is '1'. These instructions
- * should be used only inside the irq_ts_save/restore() context
+ * generate a spurious DNA fault when CR0.TS is '1'. Fortunately,
+ * the kernel doesn't use CR0.TS.
*/
static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key,
@@ -298,24 +298,18 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
- int ts_state;
padlock_reset_key(&ctx->cword.encrypt);
- ts_state = irq_ts_save();
ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1);
- irq_ts_restore(ts_state);
padlock_store_cword(&ctx->cword.encrypt);
}
static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
- int ts_state;
padlock_reset_key(&ctx->cword.encrypt);
- ts_state = irq_ts_save();
ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1);
- irq_ts_restore(ts_state);
padlock_store_cword(&ctx->cword.encrypt);
}
@@ -346,14 +340,12 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
struct blkcipher_walk walk;
int err;
- int ts_state;
padlock_reset_key(&ctx->cword.encrypt);
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
- ts_state = irq_ts_save();
while ((nbytes = walk.nbytes)) {
padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
ctx->E, &ctx->cword.encrypt,
@@ -361,7 +353,6 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
nbytes &= AES_BLOCK_SIZE - 1;
err = blkcipher_walk_done(desc, &walk, nbytes);
}
- irq_ts_restore(ts_state);
padlock_store_cword(&ctx->cword.encrypt);
@@ -375,14 +366,12 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
struct blkcipher_walk walk;
int err;
- int ts_state;
padlock_reset_key(&ctx->cword.decrypt);
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
- ts_state = irq_ts_save();
while ((nbytes = walk.nbytes)) {
padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
ctx->D, &ctx->cword.decrypt,
@@ -390,7 +379,6 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
nbytes &= AES_BLOCK_SIZE - 1;
err = blkcipher_walk_done(desc, &walk, nbytes);
}
- irq_ts_restore(ts_state);
padlock_store_cword(&ctx->cword.encrypt);
@@ -425,14 +413,12 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
struct blkcipher_walk walk;
int err;
- int ts_state;
padlock_reset_key(&ctx->cword.encrypt);
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
- ts_state = irq_ts_save();
while ((nbytes = walk.nbytes)) {
u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr,
walk.dst.virt.addr, ctx->E,
@@ -442,7 +428,6 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
nbytes &= AES_BLOCK_SIZE - 1;
err = blkcipher_walk_done(desc, &walk, nbytes);
}
- irq_ts_restore(ts_state);
padlock_store_cword(&ctx->cword.decrypt);
@@ -456,14 +441,12 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
struct blkcipher_walk walk;
int err;
- int ts_state;
padlock_reset_key(&ctx->cword.encrypt);
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
- ts_state = irq_ts_save();
while ((nbytes = walk.nbytes)) {
padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr,
ctx->D, walk.iv, &ctx->cword.decrypt,
@@ -472,8 +455,6 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
err = blkcipher_walk_done(desc, &walk, nbytes);
}
- irq_ts_restore(ts_state);
-
padlock_store_cword(&ctx->cword.encrypt);
return err;
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
index 8c5f90647b7a..bc72d20c32c3 100644
--- a/drivers/crypto/padlock-sha.c
+++ b/drivers/crypto/padlock-sha.c
@@ -89,7 +89,6 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in,
struct sha1_state state;
unsigned int space;
unsigned int leftover;
- int ts_state;
int err;
dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -120,14 +119,11 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in,
memcpy(result, &state.state, SHA1_DIGEST_SIZE);
- /* prevent taking the spurious DNA fault with padlock. */
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */
: \
: "c"((unsigned long)state.count + count), \
"a"((unsigned long)state.count), \
"S"(in), "D"(result));
- irq_ts_restore(ts_state);
padlock_output_block((uint32_t *)result, (uint32_t *)out, 5);
@@ -155,7 +151,6 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in,
struct sha256_state state;
unsigned int space;
unsigned int leftover;
- int ts_state;
int err;
dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -186,14 +181,11 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in,
memcpy(result, &state.state, SHA256_DIGEST_SIZE);
- /* prevent taking the spurious DNA fault with padlock. */
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */
: \
: "c"((unsigned long)state.count + count), \
"a"((unsigned long)state.count), \
"S"(in), "D"(result));
- irq_ts_restore(ts_state);
padlock_output_block((uint32_t *)result, (uint32_t *)out, 8);
@@ -312,7 +304,6 @@ static int padlock_sha1_update_nano(struct shash_desc *desc,
u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
((aligned(STACK_ALIGN)));
u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
- int ts_state;
partial = sctx->count & 0x3f;
sctx->count += len;
@@ -328,23 +319,19 @@ static int padlock_sha1_update_nano(struct shash_desc *desc,
memcpy(sctx->buffer + partial, data,
done + SHA1_BLOCK_SIZE);
src = sctx->buffer;
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xc8"
: "+S"(src), "+D"(dst) \
: "a"((long)-1), "c"((unsigned long)1));
- irq_ts_restore(ts_state);
done += SHA1_BLOCK_SIZE;
src = data + done;
}
/* Process the left bytes from the input data */
if (len - done >= SHA1_BLOCK_SIZE) {
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xc8"
: "+S"(src), "+D"(dst)
: "a"((long)-1),
"c"((unsigned long)((len - done) / SHA1_BLOCK_SIZE)));
- irq_ts_restore(ts_state);
done += ((len - done) - (len - done) % SHA1_BLOCK_SIZE);
src = data + done;
}
@@ -401,7 +388,6 @@ static int padlock_sha256_update_nano(struct shash_desc *desc, const u8 *data,
u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
((aligned(STACK_ALIGN)));
u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
- int ts_state;
partial = sctx->count & 0x3f;
sctx->count += len;
@@ -417,23 +403,19 @@ static int padlock_sha256_update_nano(struct shash_desc *desc, const u8 *data,
memcpy(sctx->buf + partial, data,
done + SHA256_BLOCK_SIZE);
src = sctx->buf;
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xd0"
: "+S"(src), "+D"(dst)
: "a"((long)-1), "c"((unsigned long)1));
- irq_ts_restore(ts_state);
done += SHA256_BLOCK_SIZE;
src = data + done;
}
/* Process the left bytes from input data*/
if (len - done >= SHA256_BLOCK_SIZE) {
- ts_state = irq_ts_save();
asm volatile (".byte 0xf3,0x0f,0xa6,0xd0"
: "+S"(src), "+D"(dst)
: "a"((long)-1),
"c"((unsigned long)((len - done) / 64)));
- irq_ts_restore(ts_state);
done += ((len - done) - (len - done) % 64);
src = data + done;
}
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index bf3ea7603a58..a324801d6a66 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -850,7 +850,7 @@ err_out:
EXPORT_SYMBOL(devfreq_add_governor);
/**
- * devfreq_remove_device() - Remove devfreq feature from a device.
+ * devfreq_remove_governor() - Remove devfreq feature from a device.
* @governor: the devfreq governor to be removed
*/
int devfreq_remove_governor(struct devfreq_governor *governor)
diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
index 49e712aca0c1..5c3e7b11e8a6 100644
--- a/drivers/devfreq/event/exynos-nocp.c
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -190,6 +190,7 @@ static const struct of_device_id exynos_nocp_id_match[] = {
{ .compatible = "samsung,exynos5420-nocp", },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, exynos_nocp_id_match);
static struct regmap_config exynos_nocp_regmap_config = {
.reg_bits = 32,
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index f55cf0eb2a66..107eb91a9415 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -15,7 +15,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/mutex.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
@@ -34,7 +33,6 @@ struct exynos_ppmu {
unsigned int num_events;
struct device *dev;
- struct mutex lock;
struct exynos_ppmu_data ppmu;
};
@@ -90,8 +88,6 @@ struct __exynos_ppmu_events {
PPMU_EVENT(d1-cpu),
PPMU_EVENT(d1-general),
PPMU_EVENT(d1-rt),
-
- { /* sentinel */ },
};
static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
@@ -351,6 +347,7 @@ static const struct of_device_id exynos_ppmu_id_match[] = {
},
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np)
{
@@ -463,7 +460,6 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
- mutex_init(&info->lock);
info->dev = &pdev->dev;
/* Parse dt data to get resource */
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 43fcc5a7f515..22b113363ffc 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -188,6 +188,7 @@ static const struct of_device_id rockchip_dfi_id_match[] = {
{ .compatible = "rockchip,rk3399-dfi" },
{ },
};
+MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
static int rockchip_dfi_probe(struct platform_device *pdev)
{
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 29866f7e6d7e..a8ed7792ece2 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -35,7 +35,7 @@ struct exynos_bus {
unsigned int edev_count;
struct mutex lock;
- struct dev_pm_opp *curr_opp;
+ unsigned long curr_freq;
struct regulator *regulator;
struct clk *clk;
@@ -99,7 +99,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
{
struct exynos_bus *bus = dev_get_drvdata(dev);
struct dev_pm_opp *new_opp;
- unsigned long old_freq, new_freq, old_volt, new_volt, tol;
+ unsigned long old_freq, new_freq, new_volt, tol;
int ret = 0;
/* Get new opp-bus instance according to new bus clock */
@@ -113,8 +113,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
new_freq = dev_pm_opp_get_freq(new_opp);
new_volt = dev_pm_opp_get_voltage(new_opp);
- old_freq = dev_pm_opp_get_freq(bus->curr_opp);
- old_volt = dev_pm_opp_get_voltage(bus->curr_opp);
+ old_freq = bus->curr_freq;
rcu_read_unlock();
if (old_freq == new_freq)
@@ -146,7 +145,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
goto out;
}
}
- bus->curr_opp = new_opp;
+ bus->curr_freq = new_freq;
dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
old_freq/1000, new_freq/1000);
@@ -163,9 +162,7 @@ static int exynos_bus_get_dev_status(struct device *dev,
struct devfreq_event_data edata;
int ret;
- rcu_read_lock();
- stat->current_frequency = dev_pm_opp_get_freq(bus->curr_opp);
- rcu_read_unlock();
+ stat->current_frequency = bus->curr_freq;
ret = exynos_bus_get_event(bus, &edata);
if (ret < 0) {
@@ -226,7 +223,7 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
}
new_freq = dev_pm_opp_get_freq(new_opp);
- old_freq = dev_pm_opp_get_freq(bus->curr_opp);
+ old_freq = bus->curr_freq;
rcu_read_unlock();
if (old_freq == new_freq)
@@ -242,7 +239,7 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
}
*freq = new_freq;
- bus->curr_opp = new_opp;
+ bus->curr_freq = new_freq;
dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
old_freq/1000, new_freq/1000);
@@ -335,6 +332,7 @@ static int exynos_bus_parse_of(struct device_node *np,
struct exynos_bus *bus)
{
struct device *dev = bus->dev;
+ struct dev_pm_opp *opp;
unsigned long rate;
int ret;
@@ -352,22 +350,23 @@ static int exynos_bus_parse_of(struct device_node *np,
}
/* Get the freq and voltage from OPP table to scale the bus freq */
- rcu_read_lock();
ret = dev_pm_opp_of_add_table(dev);
if (ret < 0) {
dev_err(dev, "failed to get OPP table\n");
- rcu_read_unlock();
goto err_clk;
}
rate = clk_get_rate(bus->clk);
- bus->curr_opp = devfreq_recommended_opp(dev, &rate, 0);
- if (IS_ERR(bus->curr_opp)) {
+
+ rcu_read_lock();
+ opp = devfreq_recommended_opp(dev, &rate, 0);
+ if (IS_ERR(opp)) {
dev_err(dev, "failed to find dev_pm_opp\n");
rcu_read_unlock();
- ret = PTR_ERR(bus->curr_opp);
+ ret = PTR_ERR(opp);
goto err_opp;
}
+ bus->curr_freq = dev_pm_opp_get_freq(opp);
rcu_read_unlock();
return 0;
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
index e24b73d66659..27d2f349b53c 100644
--- a/drivers/devfreq/rk3399_dmc.c
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -80,7 +80,6 @@ struct rk3399_dmcfreq {
struct regulator *vdd_center;
unsigned long rate, target_rate;
unsigned long volt, target_volt;
- struct dev_pm_opp *curr_opp;
};
static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
@@ -102,9 +101,6 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
target_rate = dev_pm_opp_get_freq(opp);
target_volt = dev_pm_opp_get_voltage(opp);
- dmcfreq->rate = dev_pm_opp_get_freq(dmcfreq->curr_opp);
- dmcfreq->volt = dev_pm_opp_get_voltage(dmcfreq->curr_opp);
-
rcu_read_unlock();
if (dmcfreq->rate == target_rate)
@@ -165,7 +161,9 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
if (err)
dev_err(dev, "Cannot to set vol %lu uV\n", target_volt);
- dmcfreq->curr_opp = opp;
+ dmcfreq->rate = target_rate;
+ dmcfreq->volt = target_volt;
+
out:
mutex_unlock(&dmcfreq->lock);
return err;
@@ -414,7 +412,6 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
*/
if (dev_pm_opp_of_add_table(dev)) {
dev_err(dev, "Invalid operating-points in device tree.\n");
- rcu_read_unlock();
return -EINVAL;
}
@@ -431,12 +428,13 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
rcu_read_unlock();
return PTR_ERR(opp);
}
+ data->rate = dev_pm_opp_get_freq(opp);
+ data->volt = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
- data->curr_opp = opp;
rk3399_devfreq_dmc_profile.initial_freq = data->rate;
- data->devfreq = devfreq_add_device(dev,
+ data->devfreq = devm_devfreq_add_device(dev,
&rk3399_devfreq_dmc_profile,
"simple_ondemand",
&data->ondemand_data);
@@ -454,6 +452,7 @@ static const struct of_device_id rk3399dmc_devfreq_of_match[] = {
{ .compatible = "rockchip,rk3399-dmc" },
{ },
};
+MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match);
static struct platform_driver rk3399_dmcfreq_driver = {
.probe = rk3399_dmcfreq_probe,
diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
index 2585821b24ab..ed3b785bae37 100644
--- a/drivers/dma-buf/Kconfig
+++ b/drivers/dma-buf/Kconfig
@@ -7,7 +7,7 @@ config SYNC_FILE
select DMA_SHARED_BUFFER
---help---
The Sync File Framework adds explicit syncronization via
- userspace. It enables send/receive 'struct fence' objects to/from
+ userspace. It enables send/receive 'struct dma_fence' objects to/from
userspace via Sync File fds for synchronization between drivers via
userspace components. It has been ported from Android.
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 210a10bfad2b..c33bf8863147 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,3 +1,3 @@
-obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o
+obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o
obj-$(CONFIG_SYNC_FILE) += sync_file.o
obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index cf04d249a6a4..e72e64484131 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -25,7 +25,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/dma-buf.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/anon_inodes.h>
#include <linux/export.h>
#include <linux/debugfs.h>
@@ -124,7 +124,7 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
return base + offset;
}
-static void dma_buf_poll_cb(struct fence *fence, struct fence_cb *cb)
+static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb;
unsigned long flags;
@@ -140,7 +140,7 @@ static unsigned int dma_buf_poll(struct file *file, poll_table *poll)
struct dma_buf *dmabuf;
struct reservation_object *resv;
struct reservation_object_list *fobj;
- struct fence *fence_excl;
+ struct dma_fence *fence_excl;
unsigned long events;
unsigned shared_count, seq;
@@ -187,20 +187,20 @@ retry:
spin_unlock_irq(&dmabuf->poll.lock);
if (events & pevents) {
- if (!fence_get_rcu(fence_excl)) {
+ if (!dma_fence_get_rcu(fence_excl)) {
/* force a recheck */
events &= ~pevents;
dma_buf_poll_cb(NULL, &dcb->cb);
- } else if (!fence_add_callback(fence_excl, &dcb->cb,
- dma_buf_poll_cb)) {
+ } else if (!dma_fence_add_callback(fence_excl, &dcb->cb,
+ dma_buf_poll_cb)) {
events &= ~pevents;
- fence_put(fence_excl);
+ dma_fence_put(fence_excl);
} else {
/*
* No callback queued, wake up any additional
* waiters.
*/
- fence_put(fence_excl);
+ dma_fence_put(fence_excl);
dma_buf_poll_cb(NULL, &dcb->cb);
}
}
@@ -222,9 +222,9 @@ retry:
goto out;
for (i = 0; i < shared_count; ++i) {
- struct fence *fence = rcu_dereference(fobj->shared[i]);
+ struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
- if (!fence_get_rcu(fence)) {
+ if (!dma_fence_get_rcu(fence)) {
/*
* fence refcount dropped to zero, this means
* that fobj has been freed
@@ -235,13 +235,13 @@ retry:
dma_buf_poll_cb(NULL, &dcb->cb);
break;
}
- if (!fence_add_callback(fence, &dcb->cb,
- dma_buf_poll_cb)) {
- fence_put(fence);
+ if (!dma_fence_add_callback(fence, &dcb->cb,
+ dma_buf_poll_cb)) {
+ dma_fence_put(fence);
events &= ~POLLOUT;
break;
}
- fence_put(fence);
+ dma_fence_put(fence);
}
/* No callback queued, wake up any additional waiters. */
diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/dma-fence-array.c
index f1989fcaf354..67eb7c8fb88c 100644
--- a/drivers/dma-buf/fence-array.c
+++ b/drivers/dma-buf/dma-fence-array.c
@@ -1,5 +1,5 @@
/*
- * fence-array: aggregate fences to be waited together
+ * dma-fence-array: aggregate fences to be waited together
*
* Copyright (C) 2016 Collabora Ltd
* Copyright (C) 2016 Advanced Micro Devices, Inc.
@@ -19,35 +19,34 @@
#include <linux/export.h>
#include <linux/slab.h>
-#include <linux/fence-array.h>
+#include <linux/dma-fence-array.h>
-static void fence_array_cb_func(struct fence *f, struct fence_cb *cb);
-
-static const char *fence_array_get_driver_name(struct fence *fence)
+static const char *dma_fence_array_get_driver_name(struct dma_fence *fence)
{
- return "fence_array";
+ return "dma_fence_array";
}
-static const char *fence_array_get_timeline_name(struct fence *fence)
+static const char *dma_fence_array_get_timeline_name(struct dma_fence *fence)
{
return "unbound";
}
-static void fence_array_cb_func(struct fence *f, struct fence_cb *cb)
+static void dma_fence_array_cb_func(struct dma_fence *f,
+ struct dma_fence_cb *cb)
{
- struct fence_array_cb *array_cb =
- container_of(cb, struct fence_array_cb, cb);
- struct fence_array *array = array_cb->array;
+ struct dma_fence_array_cb *array_cb =
+ container_of(cb, struct dma_fence_array_cb, cb);
+ struct dma_fence_array *array = array_cb->array;
if (atomic_dec_and_test(&array->num_pending))
- fence_signal(&array->base);
- fence_put(&array->base);
+ dma_fence_signal(&array->base);
+ dma_fence_put(&array->base);
}
-static bool fence_array_enable_signaling(struct fence *fence)
+static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
{
- struct fence_array *array = to_fence_array(fence);
- struct fence_array_cb *cb = (void *)(&array[1]);
+ struct dma_fence_array *array = to_dma_fence_array(fence);
+ struct dma_fence_array_cb *cb = (void *)(&array[1]);
unsigned i;
for (i = 0; i < array->num_fences; ++i) {
@@ -60,10 +59,10 @@ static bool fence_array_enable_signaling(struct fence *fence)
* until we signal the array as complete (but that is now
* insufficient).
*/
- fence_get(&array->base);
- if (fence_add_callback(array->fences[i], &cb[i].cb,
- fence_array_cb_func)) {
- fence_put(&array->base);
+ dma_fence_get(&array->base);
+ if (dma_fence_add_callback(array->fences[i], &cb[i].cb,
+ dma_fence_array_cb_func)) {
+ dma_fence_put(&array->base);
if (atomic_dec_and_test(&array->num_pending))
return false;
}
@@ -72,69 +71,71 @@ static bool fence_array_enable_signaling(struct fence *fence)
return true;
}
-static bool fence_array_signaled(struct fence *fence)
+static bool dma_fence_array_signaled(struct dma_fence *fence)
{
- struct fence_array *array = to_fence_array(fence);
+ struct dma_fence_array *array = to_dma_fence_array(fence);
return atomic_read(&array->num_pending) <= 0;
}
-static void fence_array_release(struct fence *fence)
+static void dma_fence_array_release(struct dma_fence *fence)
{
- struct fence_array *array = to_fence_array(fence);
+ struct dma_fence_array *array = to_dma_fence_array(fence);
unsigned i;
for (i = 0; i < array->num_fences; ++i)
- fence_put(array->fences[i]);
+ dma_fence_put(array->fences[i]);
kfree(array->fences);
- fence_free(fence);
+ dma_fence_free(fence);
}
-const struct fence_ops fence_array_ops = {
- .get_driver_name = fence_array_get_driver_name,
- .get_timeline_name = fence_array_get_timeline_name,
- .enable_signaling = fence_array_enable_signaling,
- .signaled = fence_array_signaled,
- .wait = fence_default_wait,
- .release = fence_array_release,
+const struct dma_fence_ops dma_fence_array_ops = {
+ .get_driver_name = dma_fence_array_get_driver_name,
+ .get_timeline_name = dma_fence_array_get_timeline_name,
+ .enable_signaling = dma_fence_array_enable_signaling,
+ .signaled = dma_fence_array_signaled,
+ .wait = dma_fence_default_wait,
+ .release = dma_fence_array_release,
};
-EXPORT_SYMBOL(fence_array_ops);
+EXPORT_SYMBOL(dma_fence_array_ops);
/**
- * fence_array_create - Create a custom fence array
+ * dma_fence_array_create - Create a custom fence array
* @num_fences: [in] number of fences to add in the array
* @fences: [in] array containing the fences
* @context: [in] fence context to use
* @seqno: [in] sequence number to use
* @signal_on_any: [in] signal on any fence in the array
*
- * Allocate a fence_array object and initialize the base fence with fence_init().
+ * Allocate a dma_fence_array object and initialize the base fence with
+ * dma_fence_init().
* In case of error it returns NULL.
*
* The caller should allocate the fences array with num_fences size
* and fill it with the fences it wants to add to the object. Ownership of this
- * array is taken and fence_put() is used on each fence on release.
+ * array is taken and dma_fence_put() is used on each fence on release.
*
* If @signal_on_any is true the fence array signals if any fence in the array
* signals, otherwise it signals when all fences in the array signal.
*/
-struct fence_array *fence_array_create(int num_fences, struct fence **fences,
- u64 context, unsigned seqno,
- bool signal_on_any)
+struct dma_fence_array *dma_fence_array_create(int num_fences,
+ struct dma_fence **fences,
+ u64 context, unsigned seqno,
+ bool signal_on_any)
{
- struct fence_array *array;
+ struct dma_fence_array *array;
size_t size = sizeof(*array);
/* Allocate the callback structures behind the array. */
- size += num_fences * sizeof(struct fence_array_cb);
+ size += num_fences * sizeof(struct dma_fence_array_cb);
array = kzalloc(size, GFP_KERNEL);
if (!array)
return NULL;
spin_lock_init(&array->lock);
- fence_init(&array->base, &fence_array_ops, &array->lock,
- context, seqno);
+ dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock,
+ context, seqno);
array->num_fences = num_fences;
atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
@@ -142,4 +143,4 @@ struct fence_array *fence_array_create(int num_fences, struct fence **fences,
return array;
}
-EXPORT_SYMBOL(fence_array_create);
+EXPORT_SYMBOL(dma_fence_array_create);
diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/dma-fence.c
index 4d51f9e83fa8..0212af7997d9 100644
--- a/drivers/dma-buf/fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -21,13 +21,13 @@
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/atomic.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#define CREATE_TRACE_POINTS
-#include <trace/events/fence.h>
+#include <trace/events/dma_fence.h>
-EXPORT_TRACEPOINT_SYMBOL(fence_annotate_wait_on);
-EXPORT_TRACEPOINT_SYMBOL(fence_emit);
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_annotate_wait_on);
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit);
/*
* fence context counter: each execution context should have its own
@@ -35,39 +35,41 @@ EXPORT_TRACEPOINT_SYMBOL(fence_emit);
* context or not. One device can have multiple separate contexts,
* and they're used if some engine can run independently of another.
*/
-static atomic64_t fence_context_counter = ATOMIC64_INIT(0);
+static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(0);
/**
- * fence_context_alloc - allocate an array of fence contexts
+ * dma_fence_context_alloc - allocate an array of fence contexts
* @num: [in] amount of contexts to allocate
*
* This function will return the first index of the number of fences allocated.
* The fence context is used for setting fence->context to a unique number.
*/
-u64 fence_context_alloc(unsigned num)
+u64 dma_fence_context_alloc(unsigned num)
{
BUG_ON(!num);
- return atomic64_add_return(num, &fence_context_counter) - num;
+ return atomic64_add_return(num, &dma_fence_context_counter) - num;
}
-EXPORT_SYMBOL(fence_context_alloc);
+EXPORT_SYMBOL(dma_fence_context_alloc);
/**
- * fence_signal_locked - signal completion of a fence
+ * dma_fence_signal_locked - signal completion of a fence
* @fence: the fence to signal
*
* Signal completion for software callbacks on a fence, this will unblock
- * fence_wait() calls and run all the callbacks added with
- * fence_add_callback(). Can be called multiple times, but since a fence
+ * dma_fence_wait() calls and run all the callbacks added with
+ * dma_fence_add_callback(). Can be called multiple times, but since a fence
* can only go from unsignaled to signaled state, it will only be effective
* the first time.
*
- * Unlike fence_signal, this function must be called with fence->lock held.
+ * Unlike dma_fence_signal, this function must be called with fence->lock held.
*/
-int fence_signal_locked(struct fence *fence)
+int dma_fence_signal_locked(struct dma_fence *fence)
{
- struct fence_cb *cur, *tmp;
+ struct dma_fence_cb *cur, *tmp;
int ret = 0;
+ lockdep_assert_held(fence->lock);
+
if (WARN_ON(!fence))
return -EINVAL;
@@ -76,15 +78,15 @@ int fence_signal_locked(struct fence *fence)
smp_mb__before_atomic();
}
- if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
ret = -EINVAL;
/*
- * we might have raced with the unlocked fence_signal,
+ * we might have raced with the unlocked dma_fence_signal,
* still run through all callbacks
*/
} else
- trace_fence_signaled(fence);
+ trace_dma_fence_signaled(fence);
list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
list_del_init(&cur->node);
@@ -92,19 +94,19 @@ int fence_signal_locked(struct fence *fence)
}
return ret;
}
-EXPORT_SYMBOL(fence_signal_locked);
+EXPORT_SYMBOL(dma_fence_signal_locked);
/**
- * fence_signal - signal completion of a fence
+ * dma_fence_signal - signal completion of a fence
* @fence: the fence to signal
*
* Signal completion for software callbacks on a fence, this will unblock
- * fence_wait() calls and run all the callbacks added with
- * fence_add_callback(). Can be called multiple times, but since a fence
+ * dma_fence_wait() calls and run all the callbacks added with
+ * dma_fence_add_callback(). Can be called multiple times, but since a fence
* can only go from unsignaled to signaled state, it will only be effective
* the first time.
*/
-int fence_signal(struct fence *fence)
+int dma_fence_signal(struct dma_fence *fence)
{
unsigned long flags;
@@ -116,13 +118,13 @@ int fence_signal(struct fence *fence)
smp_mb__before_atomic();
}
- if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
return -EINVAL;
- trace_fence_signaled(fence);
+ trace_dma_fence_signaled(fence);
- if (test_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
- struct fence_cb *cur, *tmp;
+ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
+ struct dma_fence_cb *cur, *tmp;
spin_lock_irqsave(fence->lock, flags);
list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
@@ -133,10 +135,10 @@ int fence_signal(struct fence *fence)
}
return 0;
}
-EXPORT_SYMBOL(fence_signal);
+EXPORT_SYMBOL(dma_fence_signal);
/**
- * fence_wait_timeout - sleep until the fence gets signaled
+ * dma_fence_wait_timeout - sleep until the fence gets signaled
* or until timeout elapses
* @fence: [in] the fence to wait on
* @intr: [in] if true, do an interruptible wait
@@ -152,78 +154,76 @@ EXPORT_SYMBOL(fence_signal);
* freed before return, resulting in undefined behavior.
*/
signed long
-fence_wait_timeout(struct fence *fence, bool intr, signed long timeout)
+dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
{
signed long ret;
if (WARN_ON(timeout < 0))
return -EINVAL;
- if (timeout == 0)
- return fence_is_signaled(fence);
-
- trace_fence_wait_start(fence);
+ trace_dma_fence_wait_start(fence);
ret = fence->ops->wait(fence, intr, timeout);
- trace_fence_wait_end(fence);
+ trace_dma_fence_wait_end(fence);
return ret;
}
-EXPORT_SYMBOL(fence_wait_timeout);
+EXPORT_SYMBOL(dma_fence_wait_timeout);
-void fence_release(struct kref *kref)
+void dma_fence_release(struct kref *kref)
{
- struct fence *fence =
- container_of(kref, struct fence, refcount);
+ struct dma_fence *fence =
+ container_of(kref, struct dma_fence, refcount);
- trace_fence_destroy(fence);
+ trace_dma_fence_destroy(fence);
BUG_ON(!list_empty(&fence->cb_list));
if (fence->ops->release)
fence->ops->release(fence);
else
- fence_free(fence);
+ dma_fence_free(fence);
}
-EXPORT_SYMBOL(fence_release);
+EXPORT_SYMBOL(dma_fence_release);
-void fence_free(struct fence *fence)
+void dma_fence_free(struct dma_fence *fence)
{
kfree_rcu(fence, rcu);
}
-EXPORT_SYMBOL(fence_free);
+EXPORT_SYMBOL(dma_fence_free);
/**
- * fence_enable_sw_signaling - enable signaling on fence
+ * dma_fence_enable_sw_signaling - enable signaling on fence
* @fence: [in] the fence to enable
*
* this will request for sw signaling to be enabled, to make the fence
* complete as soon as possible
*/
-void fence_enable_sw_signaling(struct fence *fence)
+void dma_fence_enable_sw_signaling(struct dma_fence *fence)
{
unsigned long flags;
- if (!test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags) &&
- !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
- trace_fence_enable_signal(fence);
+ if (!test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+ &fence->flags) &&
+ !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ trace_dma_fence_enable_signal(fence);
spin_lock_irqsave(fence->lock, flags);
if (!fence->ops->enable_signaling(fence))
- fence_signal_locked(fence);
+ dma_fence_signal_locked(fence);
spin_unlock_irqrestore(fence->lock, flags);
}
}
-EXPORT_SYMBOL(fence_enable_sw_signaling);
+EXPORT_SYMBOL(dma_fence_enable_sw_signaling);
/**
- * fence_add_callback - add a callback to be called when the fence
+ * dma_fence_add_callback - add a callback to be called when the fence
* is signaled
* @fence: [in] the fence to wait on
* @cb: [in] the callback to register
* @func: [in] the function to call
*
- * cb will be initialized by fence_add_callback, no initialization
+ * cb will be initialized by dma_fence_add_callback, no initialization
* by the caller is required. Any number of callbacks can be registered
* to a fence, but a callback can only be registered to one fence at a time.
*
@@ -232,15 +232,15 @@ EXPORT_SYMBOL(fence_enable_sw_signaling);
* *not* call the callback)
*
* Add a software callback to the fence. Same restrictions apply to
- * refcount as it does to fence_wait, however the caller doesn't need to
+ * refcount as it does to dma_fence_wait, however the caller doesn't need to
* keep a refcount to fence afterwards: when software access is enabled,
* the creator of the fence is required to keep the fence alive until
- * after it signals with fence_signal. The callback itself can be called
+ * after it signals with dma_fence_signal. The callback itself can be called
* from irq context.
*
*/
-int fence_add_callback(struct fence *fence, struct fence_cb *cb,
- fence_func_t func)
+int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
+ dma_fence_func_t func)
{
unsigned long flags;
int ret = 0;
@@ -249,22 +249,23 @@ int fence_add_callback(struct fence *fence, struct fence_cb *cb,
if (WARN_ON(!fence || !func))
return -EINVAL;
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
INIT_LIST_HEAD(&cb->node);
return -ENOENT;
}
spin_lock_irqsave(fence->lock, flags);
- was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
+ was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+ &fence->flags);
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
ret = -ENOENT;
else if (!was_set) {
- trace_fence_enable_signal(fence);
+ trace_dma_fence_enable_signal(fence);
if (!fence->ops->enable_signaling(fence)) {
- fence_signal_locked(fence);
+ dma_fence_signal_locked(fence);
ret = -ENOENT;
}
}
@@ -278,10 +279,10 @@ int fence_add_callback(struct fence *fence, struct fence_cb *cb,
return ret;
}
-EXPORT_SYMBOL(fence_add_callback);
+EXPORT_SYMBOL(dma_fence_add_callback);
/**
- * fence_remove_callback - remove a callback from the signaling list
+ * dma_fence_remove_callback - remove a callback from the signaling list
* @fence: [in] the fence to wait on
* @cb: [in] the callback to remove
*
@@ -296,7 +297,7 @@ EXPORT_SYMBOL(fence_add_callback);
* with a reference held to the fence.
*/
bool
-fence_remove_callback(struct fence *fence, struct fence_cb *cb)
+dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
{
unsigned long flags;
bool ret;
@@ -311,15 +312,15 @@ fence_remove_callback(struct fence *fence, struct fence_cb *cb)
return ret;
}
-EXPORT_SYMBOL(fence_remove_callback);
+EXPORT_SYMBOL(dma_fence_remove_callback);
struct default_wait_cb {
- struct fence_cb base;
+ struct dma_fence_cb base;
struct task_struct *task;
};
static void
-fence_default_wait_cb(struct fence *fence, struct fence_cb *cb)
+dma_fence_default_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct default_wait_cb *wait =
container_of(cb, struct default_wait_cb, base);
@@ -328,25 +329,27 @@ fence_default_wait_cb(struct fence *fence, struct fence_cb *cb)
}
/**
- * fence_default_wait - default sleep until the fence gets signaled
+ * dma_fence_default_wait - default sleep until the fence gets signaled
* or until timeout elapses
* @fence: [in] the fence to wait on
* @intr: [in] if true, do an interruptible wait
* @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
*
* Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
- * remaining timeout in jiffies on success.
+ * remaining timeout in jiffies on success. If timeout is zero the value one is
+ * returned if the fence is already signaled for consistency with other
+ * functions taking a jiffies timeout.
*/
signed long
-fence_default_wait(struct fence *fence, bool intr, signed long timeout)
+dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout)
{
struct default_wait_cb cb;
unsigned long flags;
- signed long ret = timeout;
+ signed long ret = timeout ? timeout : 1;
bool was_set;
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
- return timeout;
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return ret;
spin_lock_irqsave(fence->lock, flags);
@@ -355,25 +358,26 @@ fence_default_wait(struct fence *fence, bool intr, signed long timeout)
goto out;
}
- was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
+ was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+ &fence->flags);
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
goto out;
if (!was_set) {
- trace_fence_enable_signal(fence);
+ trace_dma_fence_enable_signal(fence);
if (!fence->ops->enable_signaling(fence)) {
- fence_signal_locked(fence);
+ dma_fence_signal_locked(fence);
goto out;
}
}
- cb.base.func = fence_default_wait_cb;
+ cb.base.func = dma_fence_default_wait_cb;
cb.task = current;
list_add(&cb.base.node, &fence->cb_list);
- while (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {
+ while (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {
if (intr)
__set_current_state(TASK_INTERRUPTIBLE);
else
@@ -395,28 +399,34 @@ out:
spin_unlock_irqrestore(fence->lock, flags);
return ret;
}
-EXPORT_SYMBOL(fence_default_wait);
+EXPORT_SYMBOL(dma_fence_default_wait);
static bool
-fence_test_signaled_any(struct fence **fences, uint32_t count)
+dma_fence_test_signaled_any(struct dma_fence **fences, uint32_t count,
+ uint32_t *idx)
{
int i;
for (i = 0; i < count; ++i) {
- struct fence *fence = fences[i];
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ struct dma_fence *fence = fences[i];
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ if (idx)
+ *idx = i;
return true;
+ }
}
return false;
}
/**
- * fence_wait_any_timeout - sleep until any fence gets signaled
+ * dma_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
+ * @idx: [out] the first signaled fence index, meaningful only on
+ * positive return
*
* Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
* interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
@@ -427,8 +437,8 @@ fence_test_signaled_any(struct fence **fences, uint32_t count)
* 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)
+dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t count,
+ bool intr, signed long timeout, uint32_t *idx)
{
struct default_wait_cb *cb;
signed long ret = timeout;
@@ -439,8 +449,11 @@ fence_wait_any_timeout(struct fence **fences, uint32_t count,
if (timeout == 0) {
for (i = 0; i < count; ++i)
- if (fence_is_signaled(fences[i]))
+ if (dma_fence_is_signaled(fences[i])) {
+ if (idx)
+ *idx = i;
return 1;
+ }
return 0;
}
@@ -452,17 +465,19 @@ fence_wait_any_timeout(struct fence **fences, uint32_t count,
}
for (i = 0; i < count; ++i) {
- struct fence *fence = fences[i];
+ struct dma_fence *fence = fences[i];
- if (fence->ops->wait != fence_default_wait) {
+ if (fence->ops->wait != dma_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)) {
+ if (dma_fence_add_callback(fence, &cb[i].base,
+ dma_fence_default_wait_cb)) {
/* This fence is already signaled */
+ if (idx)
+ *idx = i;
goto fence_rm_cb;
}
}
@@ -473,7 +488,7 @@ fence_wait_any_timeout(struct fence **fences, uint32_t count,
else
set_current_state(TASK_UNINTERRUPTIBLE);
- if (fence_test_signaled_any(fences, count))
+ if (dma_fence_test_signaled_any(fences, count, idx))
break;
ret = schedule_timeout(ret);
@@ -486,34 +501,34 @@ fence_wait_any_timeout(struct fence **fences, uint32_t count,
fence_rm_cb:
while (i-- > 0)
- fence_remove_callback(fences[i], &cb[i].base);
+ dma_fence_remove_callback(fences[i], &cb[i].base);
err_free_cb:
kfree(cb);
return ret;
}
-EXPORT_SYMBOL(fence_wait_any_timeout);
+EXPORT_SYMBOL(dma_fence_wait_any_timeout);
/**
- * fence_init - Initialize a custom fence.
+ * dma_fence_init - Initialize a custom fence.
* @fence: [in] the fence to initialize
- * @ops: [in] the fence_ops for operations on this fence
+ * @ops: [in] the dma_fence_ops for operations on this fence
* @lock: [in] the irqsafe spinlock to use for locking this fence
* @context: [in] the execution context this fence is run on
* @seqno: [in] a linear increasing sequence number for this context
*
* Initializes an allocated fence, the caller doesn't have to keep its
* refcount after committing with this fence, but it will need to hold a
- * refcount again if fence_ops.enable_signaling gets called. This can
+ * refcount again if dma_fence_ops.enable_signaling gets called. This can
* be used for other implementing other types of fence.
*
* context and seqno are used for easy comparison between fences, allowing
- * to check which fence is later by simply using fence_later.
+ * to check which fence is later by simply using dma_fence_later.
*/
void
-fence_init(struct fence *fence, const struct fence_ops *ops,
- spinlock_t *lock, u64 context, unsigned seqno)
+dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
+ spinlock_t *lock, u64 context, unsigned seqno)
{
BUG_ON(!lock);
BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
@@ -527,6 +542,6 @@ fence_init(struct fence *fence, const struct fence_ops *ops,
fence->seqno = seqno;
fence->flags = 0UL;
- trace_fence_init(fence);
+ trace_dma_fence_init(fence);
}
-EXPORT_SYMBOL(fence_init);
+EXPORT_SYMBOL(dma_fence_init);
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index 723d8af988e5..393817e849ed 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -102,17 +102,17 @@ EXPORT_SYMBOL(reservation_object_reserve_shared);
static void
reservation_object_add_shared_inplace(struct reservation_object *obj,
struct reservation_object_list *fobj,
- struct fence *fence)
+ struct dma_fence *fence)
{
u32 i;
- fence_get(fence);
+ dma_fence_get(fence);
preempt_disable();
write_seqcount_begin(&obj->seq);
for (i = 0; i < fobj->shared_count; ++i) {
- struct fence *old_fence;
+ struct dma_fence *old_fence;
old_fence = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(obj));
@@ -123,7 +123,7 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
write_seqcount_end(&obj->seq);
preempt_enable();
- fence_put(old_fence);
+ dma_fence_put(old_fence);
return;
}
}
@@ -143,12 +143,12 @@ static void
reservation_object_add_shared_replace(struct reservation_object *obj,
struct reservation_object_list *old,
struct reservation_object_list *fobj,
- struct fence *fence)
+ struct dma_fence *fence)
{
unsigned i;
- struct fence *old_fence = NULL;
+ struct dma_fence *old_fence = NULL;
- fence_get(fence);
+ dma_fence_get(fence);
if (!old) {
RCU_INIT_POINTER(fobj->shared[0], fence);
@@ -165,7 +165,7 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
fobj->shared_count = old->shared_count;
for (i = 0; i < old->shared_count; ++i) {
- struct fence *check;
+ struct dma_fence *check;
check = rcu_dereference_protected(old->shared[i],
reservation_object_held(obj));
@@ -196,7 +196,7 @@ done:
kfree_rcu(old, rcu);
if (old_fence)
- fence_put(old_fence);
+ dma_fence_put(old_fence);
}
/**
@@ -208,7 +208,7 @@ done:
* reservation_object_reserve_shared() has been called.
*/
void reservation_object_add_shared_fence(struct reservation_object *obj,
- struct fence *fence)
+ struct dma_fence *fence)
{
struct reservation_object_list *old, *fobj = obj->staged;
@@ -231,9 +231,9 @@ EXPORT_SYMBOL(reservation_object_add_shared_fence);
* Add a fence to the exclusive slot. The obj->lock must be held.
*/
void reservation_object_add_excl_fence(struct reservation_object *obj,
- struct fence *fence)
+ struct dma_fence *fence)
{
- struct fence *old_fence = reservation_object_get_excl(obj);
+ struct dma_fence *old_fence = reservation_object_get_excl(obj);
struct reservation_object_list *old;
u32 i = 0;
@@ -242,7 +242,7 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
i = old->shared_count;
if (fence)
- fence_get(fence);
+ dma_fence_get(fence);
preempt_disable();
write_seqcount_begin(&obj->seq);
@@ -255,11 +255,11 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
/* inplace update, no shared fences */
while (i--)
- fence_put(rcu_dereference_protected(old->shared[i],
+ dma_fence_put(rcu_dereference_protected(old->shared[i],
reservation_object_held(obj)));
if (old_fence)
- fence_put(old_fence);
+ dma_fence_put(old_fence);
}
EXPORT_SYMBOL(reservation_object_add_excl_fence);
@@ -276,26 +276,32 @@ EXPORT_SYMBOL(reservation_object_add_excl_fence);
* Zero or -errno
*/
int reservation_object_get_fences_rcu(struct reservation_object *obj,
- struct fence **pfence_excl,
+ struct dma_fence **pfence_excl,
unsigned *pshared_count,
- struct fence ***pshared)
+ struct dma_fence ***pshared)
{
- unsigned shared_count = 0;
- unsigned retry = 1;
- struct fence **shared = NULL, *fence_excl = NULL;
- int ret = 0;
+ struct dma_fence **shared = NULL;
+ struct dma_fence *fence_excl;
+ unsigned int shared_count;
+ int ret = 1;
- while (retry) {
+ do {
struct reservation_object_list *fobj;
unsigned seq;
+ unsigned int i;
- seq = read_seqcount_begin(&obj->seq);
+ shared_count = i = 0;
rcu_read_lock();
+ seq = read_seqcount_begin(&obj->seq);
+
+ fence_excl = rcu_dereference(obj->fence_excl);
+ if (fence_excl && !dma_fence_get_rcu(fence_excl))
+ goto unlock;
fobj = rcu_dereference(obj->fence);
if (fobj) {
- struct fence **nshared;
+ struct dma_fence **nshared;
size_t sz = sizeof(*shared) * fobj->shared_max;
nshared = krealloc(shared, sz,
@@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
}
ret = -ENOMEM;
- shared_count = 0;
break;
}
shared = nshared;
- memcpy(shared, fobj->shared, sz);
shared_count = fobj->shared_count;
- } else
- shared_count = 0;
- fence_excl = rcu_dereference(obj->fence_excl);
-
- retry = read_seqcount_retry(&obj->seq, seq);
- if (retry)
- goto unlock;
-
- if (!fence_excl || fence_get_rcu(fence_excl)) {
- unsigned i;
for (i = 0; i < shared_count; ++i) {
- if (fence_get_rcu(shared[i]))
- continue;
-
- /* uh oh, refcount failed, abort and retry */
- while (i--)
- fence_put(shared[i]);
-
- if (fence_excl) {
- fence_put(fence_excl);
- fence_excl = NULL;
- }
-
- retry = 1;
- break;
+ shared[i] = rcu_dereference(fobj->shared[i]);
+ if (!dma_fence_get_rcu(shared[i]))
+ break;
}
- } else
- retry = 1;
+ }
+ if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
+ while (i--)
+ dma_fence_put(shared[i]);
+ dma_fence_put(fence_excl);
+ goto unlock;
+ }
+
+ ret = 0;
unlock:
rcu_read_unlock();
- }
- *pshared_count = shared_count;
- if (shared_count)
- *pshared = shared;
- else {
- *pshared = NULL;
+ } while (ret);
+
+ if (!shared_count) {
kfree(shared);
+ shared = NULL;
}
+
+ *pshared_count = shared_count;
+ *pshared = shared;
*pfence_excl = fence_excl;
return ret;
@@ -377,12 +368,9 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
bool wait_all, bool intr,
unsigned long timeout)
{
- struct fence *fence;
+ struct dma_fence *fence;
unsigned seq, shared_count, i = 0;
- long ret = timeout;
-
- if (!timeout)
- return reservation_object_test_signaled_rcu(obj, wait_all);
+ long ret = timeout ? timeout : 1;
retry:
fence = NULL;
@@ -397,20 +385,18 @@ retry:
if (fobj)
shared_count = fobj->shared_count;
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
for (i = 0; i < shared_count; ++i) {
- struct fence *lfence = rcu_dereference(fobj->shared[i]);
+ struct dma_fence *lfence = rcu_dereference(fobj->shared[i]);
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+ &lfence->flags))
continue;
- if (!fence_get_rcu(lfence))
+ if (!dma_fence_get_rcu(lfence))
goto unlock_retry;
- if (fence_is_signaled(lfence)) {
- fence_put(lfence);
+ if (dma_fence_is_signaled(lfence)) {
+ dma_fence_put(lfence);
continue;
}
@@ -420,18 +406,16 @@ retry:
}
if (!shared_count) {
- struct fence *fence_excl = rcu_dereference(obj->fence_excl);
-
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
+ struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
if (fence_excl &&
- !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) {
- if (!fence_get_rcu(fence_excl))
+ !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+ &fence_excl->flags)) {
+ if (!dma_fence_get_rcu(fence_excl))
goto unlock_retry;
- if (fence_is_signaled(fence_excl))
- fence_put(fence_excl);
+ if (dma_fence_is_signaled(fence_excl))
+ dma_fence_put(fence_excl);
else
fence = fence_excl;
}
@@ -439,8 +423,13 @@ retry:
rcu_read_unlock();
if (fence) {
- ret = fence_wait_timeout(fence, intr, ret);
- fence_put(fence);
+ if (read_seqcount_retry(&obj->seq, seq)) {
+ dma_fence_put(fence);
+ goto retry;
+ }
+
+ ret = dma_fence_wait_timeout(fence, intr, ret);
+ dma_fence_put(fence);
if (ret > 0 && wait_all && (i + 1 < shared_count))
goto retry;
}
@@ -454,18 +443,18 @@ EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu);
static inline int
-reservation_object_test_signaled_single(struct fence *passed_fence)
+reservation_object_test_signaled_single(struct dma_fence *passed_fence)
{
- struct fence *fence, *lfence = passed_fence;
+ struct dma_fence *fence, *lfence = passed_fence;
int ret = 1;
- if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
- fence = fence_get_rcu(lfence);
+ if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
+ fence = dma_fence_get_rcu(lfence);
if (!fence)
return -1;
- ret = !!fence_is_signaled(fence);
- fence_put(fence);
+ ret = !!dma_fence_is_signaled(fence);
+ dma_fence_put(fence);
}
return ret;
}
@@ -484,12 +473,13 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
bool test_all)
{
unsigned seq, shared_count;
- int ret = true;
+ int ret;
+ rcu_read_lock();
retry:
+ ret = true;
shared_count = 0;
seq = read_seqcount_begin(&obj->seq);
- rcu_read_lock();
if (test_all) {
unsigned i;
@@ -500,46 +490,35 @@ retry:
if (fobj)
shared_count = fobj->shared_count;
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
for (i = 0; i < shared_count; ++i) {
- struct fence *fence = rcu_dereference(fobj->shared[i]);
+ struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
ret = reservation_object_test_signaled_single(fence);
if (ret < 0)
- goto unlock_retry;
+ goto retry;
else if (!ret)
break;
}
- /*
- * There could be a read_seqcount_retry here, but nothing cares
- * about whether it's the old or newer fence pointers that are
- * signaled. That race could still have happened after checking
- * read_seqcount_retry. If you care, use ww_mutex_lock.
- */
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto retry;
}
if (!shared_count) {
- struct fence *fence_excl = rcu_dereference(obj->fence_excl);
-
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
+ struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
if (fence_excl) {
ret = reservation_object_test_signaled_single(
fence_excl);
if (ret < 0)
- goto unlock_retry;
+ goto retry;
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto retry;
}
}
rcu_read_unlock();
return ret;
-
-unlock_retry:
- rcu_read_unlock();
- goto retry;
}
EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu);
diff --git a/drivers/dma-buf/seqno-fence.c b/drivers/dma-buf/seqno-fence.c
index 71127f8f1626..f47112a64763 100644
--- a/drivers/dma-buf/seqno-fence.c
+++ b/drivers/dma-buf/seqno-fence.c
@@ -21,35 +21,35 @@
#include <linux/export.h>
#include <linux/seqno-fence.h>
-static const char *seqno_fence_get_driver_name(struct fence *fence)
+static const char *seqno_fence_get_driver_name(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->get_driver_name(fence);
}
-static const char *seqno_fence_get_timeline_name(struct fence *fence)
+static const char *seqno_fence_get_timeline_name(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->get_timeline_name(fence);
}
-static bool seqno_enable_signaling(struct fence *fence)
+static bool seqno_enable_signaling(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->enable_signaling(fence);
}
-static bool seqno_signaled(struct fence *fence)
+static bool seqno_signaled(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
}
-static void seqno_release(struct fence *fence)
+static void seqno_release(struct dma_fence *fence)
{
struct seqno_fence *f = to_seqno_fence(fence);
@@ -57,18 +57,18 @@ static void seqno_release(struct fence *fence)
if (f->ops->release)
f->ops->release(fence);
else
- fence_free(&f->base);
+ dma_fence_free(&f->base);
}
-static signed long seqno_wait(struct fence *fence, bool intr,
- signed long timeout)
+static signed long seqno_wait(struct dma_fence *fence, bool intr,
+ signed long timeout)
{
struct seqno_fence *f = to_seqno_fence(fence);
return f->ops->wait(fence, intr, timeout);
}
-const struct fence_ops seqno_fence_ops = {
+const struct dma_fence_ops seqno_fence_ops = {
.get_driver_name = seqno_fence_get_driver_name,
.get_timeline_name = seqno_fence_get_timeline_name,
.enable_signaling = seqno_enable_signaling,
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 62e8e6dc7953..69c5ff36e2f9 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -68,9 +68,9 @@ struct sw_sync_create_fence_data {
#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
-static const struct fence_ops timeline_fence_ops;
+static const struct dma_fence_ops timeline_fence_ops;
-static inline struct sync_pt *fence_to_sync_pt(struct fence *fence)
+static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence)
{
if (fence->ops != &timeline_fence_ops)
return NULL;
@@ -84,7 +84,7 @@ static inline struct sync_pt *fence_to_sync_pt(struct fence *fence)
* Creates a new sync_timeline. Returns the sync_timeline object or NULL in
* case of error.
*/
-struct sync_timeline *sync_timeline_create(const char *name)
+static struct sync_timeline *sync_timeline_create(const char *name)
{
struct sync_timeline *obj;
@@ -93,7 +93,7 @@ struct sync_timeline *sync_timeline_create(const char *name)
return NULL;
kref_init(&obj->kref);
- obj->context = fence_context_alloc(1);
+ obj->context = dma_fence_context_alloc(1);
strlcpy(obj->name, name, sizeof(obj->name));
INIT_LIST_HEAD(&obj->child_list_head);
@@ -146,7 +146,7 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
list_for_each_entry_safe(pt, next, &obj->active_list_head,
active_list) {
- if (fence_is_signaled_locked(&pt->base))
+ if (dma_fence_is_signaled_locked(&pt->base))
list_del_init(&pt->active_list);
}
@@ -179,30 +179,30 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size,
spin_lock_irqsave(&obj->child_list_lock, flags);
sync_timeline_get(obj);
- fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
- obj->context, value);
+ dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
+ obj->context, value);
list_add_tail(&pt->child_list, &obj->child_list_head);
INIT_LIST_HEAD(&pt->active_list);
spin_unlock_irqrestore(&obj->child_list_lock, flags);
return pt;
}
-static const char *timeline_fence_get_driver_name(struct fence *fence)
+static const char *timeline_fence_get_driver_name(struct dma_fence *fence)
{
return "sw_sync";
}
-static const char *timeline_fence_get_timeline_name(struct fence *fence)
+static const char *timeline_fence_get_timeline_name(struct dma_fence *fence)
{
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
return parent->name;
}
-static void timeline_fence_release(struct fence *fence)
+static void timeline_fence_release(struct dma_fence *fence)
{
- struct sync_pt *pt = fence_to_sync_pt(fence);
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_pt *pt = dma_fence_to_sync_pt(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
unsigned long flags;
spin_lock_irqsave(fence->lock, flags);
@@ -212,20 +212,20 @@ static void timeline_fence_release(struct fence *fence)
spin_unlock_irqrestore(fence->lock, flags);
sync_timeline_put(parent);
- fence_free(fence);
+ dma_fence_free(fence);
}
-static bool timeline_fence_signaled(struct fence *fence)
+static bool timeline_fence_signaled(struct dma_fence *fence)
{
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
return (fence->seqno > parent->value) ? false : true;
}
-static bool timeline_fence_enable_signaling(struct fence *fence)
+static bool timeline_fence_enable_signaling(struct dma_fence *fence)
{
- struct sync_pt *pt = fence_to_sync_pt(fence);
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_pt *pt = dma_fence_to_sync_pt(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
if (timeline_fence_signaled(fence))
return false;
@@ -234,26 +234,26 @@ static bool timeline_fence_enable_signaling(struct fence *fence)
return true;
}
-static void timeline_fence_value_str(struct fence *fence,
+static void timeline_fence_value_str(struct dma_fence *fence,
char *str, int size)
{
snprintf(str, size, "%d", fence->seqno);
}
-static void timeline_fence_timeline_value_str(struct fence *fence,
+static void timeline_fence_timeline_value_str(struct dma_fence *fence,
char *str, int size)
{
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
snprintf(str, size, "%d", parent->value);
}
-static const struct fence_ops timeline_fence_ops = {
+static const struct dma_fence_ops timeline_fence_ops = {
.get_driver_name = timeline_fence_get_driver_name,
.get_timeline_name = timeline_fence_get_timeline_name,
.enable_signaling = timeline_fence_enable_signaling,
.signaled = timeline_fence_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = timeline_fence_release,
.fence_value_str = timeline_fence_value_str,
.timeline_value_str = timeline_fence_timeline_value_str,
@@ -316,8 +316,8 @@ static long sw_sync_ioctl_create_fence(struct sync_timeline *obj,
}
sync_file = sync_file_create(&pt->base);
+ dma_fence_put(&pt->base);
if (!sync_file) {
- fence_put(&pt->base);
err = -ENOMEM;
goto err;
}
diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
index 2dd4c3db6caa..48b20e34fb6d 100644
--- a/drivers/dma-buf/sync_debug.c
+++ b/drivers/dma-buf/sync_debug.c
@@ -71,12 +71,13 @@ static const char *sync_status_str(int status)
return "error";
}
-static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show)
+static void sync_print_fence(struct seq_file *s,
+ struct dma_fence *fence, bool show)
{
int status = 1;
- struct sync_timeline *parent = fence_parent(fence);
+ struct sync_timeline *parent = dma_fence_parent(fence);
- if (fence_is_signaled_locked(fence))
+ if (dma_fence_is_signaled_locked(fence))
status = fence->status;
seq_printf(s, " %s%sfence %s",
@@ -135,10 +136,10 @@ static void sync_print_sync_file(struct seq_file *s,
int i;
seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
- sync_status_str(!fence_is_signaled(sync_file->fence)));
+ sync_status_str(!dma_fence_is_signaled(sync_file->fence)));
- if (fence_is_array(sync_file->fence)) {
- struct fence_array *array = to_fence_array(sync_file->fence);
+ if (dma_fence_is_array(sync_file->fence)) {
+ struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
for (i = 0; i < array->num_fences; ++i)
sync_print_fence(s, array->fences[i], true);
diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h
index d269aa6783aa..26fe8b9907b3 100644
--- a/drivers/dma-buf/sync_debug.h
+++ b/drivers/dma-buf/sync_debug.h
@@ -15,7 +15,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/sync_file.h>
#include <uapi/linux/sync_file.h>
@@ -45,10 +45,9 @@ struct sync_timeline {
struct list_head sync_timeline_list;
};
-static inline struct sync_timeline *fence_parent(struct fence *fence)
+static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence)
{
- return container_of(fence->lock, struct sync_timeline,
- child_list_lock);
+ return container_of(fence->lock, struct sync_timeline, child_list_lock);
}
/**
@@ -58,7 +57,7 @@ static inline struct sync_timeline *fence_parent(struct fence *fence)
* @active_list: sync timeline active child's list
*/
struct sync_pt {
- struct fence base;
+ struct dma_fence base;
struct list_head child_list;
struct list_head active_list;
};
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index b29a9e817320..6d802f2d2881 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -54,7 +54,7 @@ err:
return NULL;
}
-static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
+static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct sync_file *sync_file;
@@ -71,7 +71,7 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
* takes ownership of @fence. The sync_file can be released with
* fput(sync_file->file). Returns the sync_file or NULL in case of error.
*/
-struct sync_file *sync_file_create(struct fence *fence)
+struct sync_file *sync_file_create(struct dma_fence *fence)
{
struct sync_file *sync_file;
@@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struct fence *fence)
if (!sync_file)
return NULL;
- sync_file->fence = fence;
+ sync_file->fence = dma_fence_get(fence);
snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
fence->ops->get_driver_name(fence),
@@ -121,16 +121,16 @@ err:
* Ensures @fd references a valid sync_file and returns a fence that
* represents all fence in the sync_file. On error NULL is returned.
*/
-struct fence *sync_file_get_fence(int fd)
+struct dma_fence *sync_file_get_fence(int fd)
{
struct sync_file *sync_file;
- struct fence *fence;
+ struct dma_fence *fence;
sync_file = sync_file_fdget(fd);
if (!sync_file)
return NULL;
- fence = fence_get(sync_file->fence);
+ fence = dma_fence_get(sync_file->fence);
fput(sync_file->file);
return fence;
@@ -138,22 +138,23 @@ struct fence *sync_file_get_fence(int fd)
EXPORT_SYMBOL(sync_file_get_fence);
static int sync_file_set_fence(struct sync_file *sync_file,
- struct fence **fences, int num_fences)
+ struct dma_fence **fences, int num_fences)
{
- struct fence_array *array;
+ struct dma_fence_array *array;
/*
* The reference for the fences in the new sync_file and held
* in add_fence() during the merge procedure, so for num_fences == 1
* we already own a new reference to the fence. For num_fence > 1
- * we own the reference of the fence_array creation.
+ * we own the reference of the dma_fence_array creation.
*/
if (num_fences == 1) {
sync_file->fence = fences[0];
kfree(fences);
} else {
- array = fence_array_create(num_fences, fences,
- fence_context_alloc(1), 1, false);
+ array = dma_fence_array_create(num_fences, fences,
+ dma_fence_context_alloc(1),
+ 1, false);
if (!array)
return -ENOMEM;
@@ -163,10 +164,11 @@ static int sync_file_set_fence(struct sync_file *sync_file,
return 0;
}
-static struct fence **get_fences(struct sync_file *sync_file, int *num_fences)
+static struct dma_fence **get_fences(struct sync_file *sync_file,
+ int *num_fences)
{
- if (fence_is_array(sync_file->fence)) {
- struct fence_array *array = to_fence_array(sync_file->fence);
+ if (dma_fence_is_array(sync_file->fence)) {
+ struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
*num_fences = array->num_fences;
return array->fences;
@@ -176,12 +178,13 @@ static struct fence **get_fences(struct sync_file *sync_file, int *num_fences)
return &sync_file->fence;
}
-static void add_fence(struct fence **fences, int *i, struct fence *fence)
+static void add_fence(struct dma_fence **fences,
+ int *i, struct dma_fence *fence)
{
fences[*i] = fence;
- if (!fence_is_signaled(fence)) {
- fence_get(fence);
+ if (!dma_fence_is_signaled(fence)) {
+ dma_fence_get(fence);
(*i)++;
}
}
@@ -200,7 +203,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
struct sync_file *b)
{
struct sync_file *sync_file;
- struct fence **fences, **nfences, **a_fences, **b_fences;
+ struct dma_fence **fences, **nfences, **a_fences, **b_fences;
int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
sync_file = sync_file_alloc();
@@ -226,8 +229,8 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
* and sync_file_create, this is a reasonable assumption.
*/
for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
- struct fence *pt_a = a_fences[i_a];
- struct fence *pt_b = b_fences[i_b];
+ struct dma_fence *pt_a = a_fences[i_a];
+ struct dma_fence *pt_b = b_fences[i_b];
if (pt_a->context < pt_b->context) {
add_fence(fences, &i, pt_a);
@@ -255,7 +258,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
add_fence(fences, &i, b_fences[i_b]);
if (i == 0)
- fences[i++] = fence_get(a_fences[0]);
+ fences[i++] = dma_fence_get(a_fences[0]);
if (num_fences > i) {
nfences = krealloc(fences, i * sizeof(*fences),
@@ -286,8 +289,8 @@ static void sync_file_free(struct kref *kref)
kref);
if (test_bit(POLL_ENABLED, &sync_file->fence->flags))
- fence_remove_callback(sync_file->fence, &sync_file->cb);
- fence_put(sync_file->fence);
+ dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
+ dma_fence_put(sync_file->fence);
kfree(sync_file);
}
@@ -305,14 +308,13 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait)
poll_wait(file, &sync_file->wq, wait);
- if (!poll_does_not_wait(wait) &&
- !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
- if (fence_add_callback(sync_file->fence, &sync_file->cb,
- fence_check_cb_func) < 0)
+ if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
+ if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
+ fence_check_cb_func) < 0)
wake_up_all(&sync_file->wq);
}
- return fence_is_signaled(sync_file->fence) ? POLLIN : 0;
+ return dma_fence_is_signaled(sync_file->fence) ? POLLIN : 0;
}
static long sync_file_ioctl_merge(struct sync_file *sync_file,
@@ -370,14 +372,14 @@ err_put_fd:
return err;
}
-static void sync_fill_fence_info(struct fence *fence,
+static void sync_fill_fence_info(struct dma_fence *fence,
struct sync_fence_info *info)
{
strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
sizeof(info->obj_name));
strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
sizeof(info->driver_name));
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
info->status = fence->status >= 0 ? 1 : fence->status;
else
info->status = 0;
@@ -389,7 +391,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
{
struct sync_file_info info;
struct sync_fence_info *fence_info = NULL;
- struct fence **fences;
+ struct dma_fence **fences;
__u32 size;
int num_fences, ret, i;
@@ -429,7 +431,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
no_fences:
strlcpy(info.name, sync_file->name, sizeof(info.name));
- info.status = fence_is_signaled(sync_file->fence);
+ info.status = dma_fence_is_signaled(sync_file->fence);
info.num_fences = num_fences;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 141aefbe37ec..2154ea3c5d1c 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -436,6 +436,20 @@ config STE_DMA40
help
Support for ST-Ericsson DMA40 controller
+config ST_FDMA
+ tristate "ST FDMA dmaengine support"
+ depends on ARCH_STI
+ depends on REMOTEPROC
+ select ST_SLIM_REMOTEPROC
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Enable support for ST FDMA controller.
+ It supports 16 independent DMA channels, accepts up to 32 DMA requests
+
+ Say Y here if you have such a chipset.
+ If unsure, say N.
+
config STM32_DMA
bool "STMicroelectronics STM32 DMA support"
depends on ARCH_STM32 || COMPILE_TEST
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index e4dc9cac7ee8..a4fa3360e609 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o
obj-$(CONFIG_TI_EDMA) += edma.o
obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_ST_FDMA) += st_fdma.o
obj-y += qcom/
obj-y += xilinx/
diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h
index 48fa4cf9f64a..2f3bbc88ff2a 100644
--- a/drivers/dma/ioat/registers.h
+++ b/drivers/dma/ioat/registers.h
@@ -106,8 +106,6 @@
#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */
#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */
-/* IOAT1 define left for i7300_idle driver to not fail compiling */
-#define IOAT1_CHANSTS_OFFSET 0x04
#define IOAT_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */
#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR (~0x3fULL)
#define IOAT_CHANSTS_SOFT_ERR 0x10ULL
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
new file mode 100644
index 000000000000..bfb79bd0c6de
--- /dev/null
+++ b/drivers/dma/st_fdma.c
@@ -0,0 +1,889 @@
+/*
+ * DMA driver for STMicroelectronics STi FDMA controller
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * Author: Ludovic Barre <Ludovic.barre@st.com>
+ * Peter Griffin <peter.griffin@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/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/remoteproc.h>
+
+#include "st_fdma.h"
+
+static inline struct st_fdma_chan *to_st_fdma_chan(struct dma_chan *c)
+{
+ return container_of(c, struct st_fdma_chan, vchan.chan);
+}
+
+static struct st_fdma_desc *to_st_fdma_desc(struct virt_dma_desc *vd)
+{
+ return container_of(vd, struct st_fdma_desc, vdesc);
+}
+
+static int st_fdma_dreq_get(struct st_fdma_chan *fchan)
+{
+ struct st_fdma_dev *fdev = fchan->fdev;
+ u32 req_line_cfg = fchan->cfg.req_line;
+ u32 dreq_line;
+ int try = 0;
+
+ /*
+ * dreq_mask is shared for n channels of fdma, so all accesses must be
+ * atomic. if the dreq_mask is changed between ffz and set_bit,
+ * we retry
+ */
+ do {
+ if (fdev->dreq_mask == ~0L) {
+ dev_err(fdev->dev, "No req lines available\n");
+ return -EINVAL;
+ }
+
+ if (try || req_line_cfg >= ST_FDMA_NR_DREQS) {
+ dev_err(fdev->dev, "Invalid or used req line\n");
+ return -EINVAL;
+ } else {
+ dreq_line = req_line_cfg;
+ }
+
+ try++;
+ } while (test_and_set_bit(dreq_line, &fdev->dreq_mask));
+
+ dev_dbg(fdev->dev, "get dreq_line:%d mask:%#lx\n",
+ dreq_line, fdev->dreq_mask);
+
+ return dreq_line;
+}
+
+static void st_fdma_dreq_put(struct st_fdma_chan *fchan)
+{
+ struct st_fdma_dev *fdev = fchan->fdev;
+
+ dev_dbg(fdev->dev, "put dreq_line:%#x\n", fchan->dreq_line);
+ clear_bit(fchan->dreq_line, &fdev->dreq_mask);
+}
+
+static void st_fdma_xfer_desc(struct st_fdma_chan *fchan)
+{
+ struct virt_dma_desc *vdesc;
+ unsigned long nbytes, ch_cmd, cmd;
+
+ vdesc = vchan_next_desc(&fchan->vchan);
+ if (!vdesc)
+ return;
+
+ fchan->fdesc = to_st_fdma_desc(vdesc);
+ nbytes = fchan->fdesc->node[0].desc->nbytes;
+ cmd = FDMA_CMD_START(fchan->vchan.chan.chan_id);
+ ch_cmd = fchan->fdesc->node[0].pdesc | FDMA_CH_CMD_STA_START;
+
+ /* start the channel for the descriptor */
+ fnode_write(fchan, nbytes, FDMA_CNTN_OFST);
+ fchan_write(fchan, ch_cmd, FDMA_CH_CMD_OFST);
+ writel(cmd,
+ fchan->fdev->slim_rproc->peri + FDMA_CMD_SET_OFST);
+
+ dev_dbg(fchan->fdev->dev, "start chan:%d\n", fchan->vchan.chan.chan_id);
+}
+
+static void st_fdma_ch_sta_update(struct st_fdma_chan *fchan,
+ unsigned long int_sta)
+{
+ unsigned long ch_sta, ch_err;
+ int ch_id = fchan->vchan.chan.chan_id;
+ struct st_fdma_dev *fdev = fchan->fdev;
+
+ ch_sta = fchan_read(fchan, FDMA_CH_CMD_OFST);
+ ch_err = ch_sta & FDMA_CH_CMD_ERR_MASK;
+ ch_sta &= FDMA_CH_CMD_STA_MASK;
+
+ if (int_sta & FDMA_INT_STA_ERR) {
+ dev_warn(fdev->dev, "chan:%d, error:%ld\n", ch_id, ch_err);
+ fchan->status = DMA_ERROR;
+ return;
+ }
+
+ switch (ch_sta) {
+ case FDMA_CH_CMD_STA_PAUSED:
+ fchan->status = DMA_PAUSED;
+ break;
+
+ case FDMA_CH_CMD_STA_RUNNING:
+ fchan->status = DMA_IN_PROGRESS;
+ break;
+ }
+}
+
+static irqreturn_t st_fdma_irq_handler(int irq, void *dev_id)
+{
+ struct st_fdma_dev *fdev = dev_id;
+ irqreturn_t ret = IRQ_NONE;
+ struct st_fdma_chan *fchan = &fdev->chans[0];
+ unsigned long int_sta, clr;
+
+ int_sta = fdma_read(fdev, FDMA_INT_STA_OFST);
+ clr = int_sta;
+
+ for (; int_sta != 0 ; int_sta >>= 2, fchan++) {
+ if (!(int_sta & (FDMA_INT_STA_CH | FDMA_INT_STA_ERR)))
+ continue;
+
+ spin_lock(&fchan->vchan.lock);
+ st_fdma_ch_sta_update(fchan, int_sta);
+
+ if (fchan->fdesc) {
+ if (!fchan->fdesc->iscyclic) {
+ list_del(&fchan->fdesc->vdesc.node);
+ vchan_cookie_complete(&fchan->fdesc->vdesc);
+ fchan->fdesc = NULL;
+ fchan->status = DMA_COMPLETE;
+ } else {
+ vchan_cyclic_callback(&fchan->fdesc->vdesc);
+ }
+
+ /* Start the next descriptor (if available) */
+ if (!fchan->fdesc)
+ st_fdma_xfer_desc(fchan);
+ }
+
+ spin_unlock(&fchan->vchan.lock);
+ ret = IRQ_HANDLED;
+ }
+
+ fdma_write(fdev, clr, FDMA_INT_CLR_OFST);
+
+ return ret;
+}
+
+static struct dma_chan *st_fdma_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct st_fdma_dev *fdev = ofdma->of_dma_data;
+ struct dma_chan *chan;
+ struct st_fdma_chan *fchan;
+ int ret;
+
+ if (dma_spec->args_count < 1)
+ return ERR_PTR(-EINVAL);
+
+ if (fdev->dma_device.dev->of_node != dma_spec->np)
+ return ERR_PTR(-EINVAL);
+
+ ret = rproc_boot(fdev->slim_rproc->rproc);
+ if (ret == -ENOENT)
+ return ERR_PTR(-EPROBE_DEFER);
+ else if (ret)
+ return ERR_PTR(ret);
+
+ chan = dma_get_any_slave_channel(&fdev->dma_device);
+ if (!chan)
+ goto err_chan;
+
+ fchan = to_st_fdma_chan(chan);
+
+ fchan->cfg.of_node = dma_spec->np;
+ fchan->cfg.req_line = dma_spec->args[0];
+ fchan->cfg.req_ctrl = 0;
+ fchan->cfg.type = ST_FDMA_TYPE_FREE_RUN;
+
+ if (dma_spec->args_count > 1)
+ fchan->cfg.req_ctrl = dma_spec->args[1]
+ & FDMA_REQ_CTRL_CFG_MASK;
+
+ if (dma_spec->args_count > 2)
+ fchan->cfg.type = dma_spec->args[2];
+
+ if (fchan->cfg.type == ST_FDMA_TYPE_FREE_RUN) {
+ fchan->dreq_line = 0;
+ } else {
+ fchan->dreq_line = st_fdma_dreq_get(fchan);
+ if (IS_ERR_VALUE(fchan->dreq_line)) {
+ chan = ERR_PTR(fchan->dreq_line);
+ goto err_chan;
+ }
+ }
+
+ dev_dbg(fdev->dev, "xlate req_line:%d type:%d req_ctrl:%#lx\n",
+ fchan->cfg.req_line, fchan->cfg.type, fchan->cfg.req_ctrl);
+
+ return chan;
+
+err_chan:
+ rproc_shutdown(fdev->slim_rproc->rproc);
+ return chan;
+
+}
+
+static void st_fdma_free_desc(struct virt_dma_desc *vdesc)
+{
+ struct st_fdma_desc *fdesc;
+ int i;
+
+ fdesc = to_st_fdma_desc(vdesc);
+ for (i = 0; i < fdesc->n_nodes; i++)
+ dma_pool_free(fdesc->fchan->node_pool, fdesc->node[i].desc,
+ fdesc->node[i].pdesc);
+ kfree(fdesc);
+}
+
+static struct st_fdma_desc *st_fdma_alloc_desc(struct st_fdma_chan *fchan,
+ int sg_len)
+{
+ struct st_fdma_desc *fdesc;
+ int i;
+
+ fdesc = kzalloc(sizeof(*fdesc) +
+ sizeof(struct st_fdma_sw_node) * sg_len, GFP_NOWAIT);
+ if (!fdesc)
+ return NULL;
+
+ fdesc->fchan = fchan;
+ fdesc->n_nodes = sg_len;
+ for (i = 0; i < sg_len; i++) {
+ fdesc->node[i].desc = dma_pool_alloc(fchan->node_pool,
+ GFP_NOWAIT, &fdesc->node[i].pdesc);
+ if (!fdesc->node[i].desc)
+ goto err;
+ }
+ return fdesc;
+
+err:
+ while (--i >= 0)
+ dma_pool_free(fchan->node_pool, fdesc->node[i].desc,
+ fdesc->node[i].pdesc);
+ kfree(fdesc);
+ return NULL;
+}
+
+static int st_fdma_alloc_chan_res(struct dma_chan *chan)
+{
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+
+ /* Create the dma pool for descriptor allocation */
+ fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device),
+ fchan->fdev->dev,
+ sizeof(struct st_fdma_hw_node),
+ __alignof__(struct st_fdma_hw_node),
+ 0);
+
+ if (!fchan->node_pool) {
+ dev_err(fchan->fdev->dev, "unable to allocate desc pool\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(fchan->fdev->dev, "alloc ch_id:%d type:%d\n",
+ fchan->vchan.chan.chan_id, fchan->cfg.type);
+
+ return 0;
+}
+
+static void st_fdma_free_chan_res(struct dma_chan *chan)
+{
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ struct rproc *rproc = fchan->fdev->slim_rproc->rproc;
+ unsigned long flags;
+
+ LIST_HEAD(head);
+
+ dev_dbg(fchan->fdev->dev, "%s: freeing chan:%d\n",
+ __func__, fchan->vchan.chan.chan_id);
+
+ if (fchan->cfg.type != ST_FDMA_TYPE_FREE_RUN)
+ st_fdma_dreq_put(fchan);
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+ fchan->fdesc = NULL;
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+ dma_pool_destroy(fchan->node_pool);
+ fchan->node_pool = NULL;
+ memset(&fchan->cfg, 0, sizeof(struct st_fdma_cfg));
+
+ rproc_shutdown(rproc);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_memcpy(
+ struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct st_fdma_chan *fchan;
+ struct st_fdma_desc *fdesc;
+ struct st_fdma_hw_node *hw_node;
+
+ if (!len)
+ return NULL;
+
+ fchan = to_st_fdma_chan(chan);
+
+ /* We only require a single descriptor */
+ fdesc = st_fdma_alloc_desc(fchan, 1);
+ if (!fdesc) {
+ dev_err(fchan->fdev->dev, "no memory for desc\n");
+ return NULL;
+ }
+
+ hw_node = fdesc->node[0].desc;
+ hw_node->next = 0;
+ hw_node->control = FDMA_NODE_CTRL_REQ_MAP_FREE_RUN;
+ hw_node->control |= FDMA_NODE_CTRL_SRC_INCR;
+ hw_node->control |= FDMA_NODE_CTRL_DST_INCR;
+ hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+ hw_node->nbytes = len;
+ hw_node->saddr = src;
+ hw_node->daddr = dst;
+ hw_node->generic.length = len;
+ hw_node->generic.sstride = 0;
+ hw_node->generic.dstride = 0;
+
+ return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static int config_reqctrl(struct st_fdma_chan *fchan,
+ enum dma_transfer_direction direction)
+{
+ u32 maxburst = 0, addr = 0;
+ enum dma_slave_buswidth width;
+ int ch_id = fchan->vchan.chan.chan_id;
+ struct st_fdma_dev *fdev = fchan->fdev;
+
+ switch (direction) {
+
+ case DMA_DEV_TO_MEM:
+ fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_WNR;
+ maxburst = fchan->scfg.src_maxburst;
+ width = fchan->scfg.src_addr_width;
+ addr = fchan->scfg.src_addr;
+ break;
+
+ case DMA_MEM_TO_DEV:
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_WNR;
+ maxburst = fchan->scfg.dst_maxburst;
+ width = fchan->scfg.dst_addr_width;
+ addr = fchan->scfg.dst_addr;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_OPCODE_MASK;
+
+ switch (width) {
+
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST1;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST2;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST4;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_8_BYTES:
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST8;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_NUM_OPS_MASK;
+ fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_NUM_OPS(maxburst-1);
+ dreq_write(fchan, fchan->cfg.req_ctrl, FDMA_REQ_CTRL_OFST);
+
+ fchan->cfg.dev_addr = addr;
+ fchan->cfg.dir = direction;
+
+ dev_dbg(fdev->dev, "chan:%d config_reqctrl:%#x req_ctrl:%#lx\n",
+ ch_id, addr, fchan->cfg.req_ctrl);
+
+ return 0;
+}
+
+static void fill_hw_node(struct st_fdma_hw_node *hw_node,
+ struct st_fdma_chan *fchan,
+ enum dma_transfer_direction direction)
+{
+ if (direction == DMA_MEM_TO_DEV) {
+ hw_node->control |= FDMA_NODE_CTRL_SRC_INCR;
+ hw_node->control |= FDMA_NODE_CTRL_DST_STATIC;
+ hw_node->daddr = fchan->cfg.dev_addr;
+ } else {
+ hw_node->control |= FDMA_NODE_CTRL_SRC_STATIC;
+ hw_node->control |= FDMA_NODE_CTRL_DST_INCR;
+ hw_node->saddr = fchan->cfg.dev_addr;
+ }
+
+ hw_node->generic.sstride = 0;
+ hw_node->generic.dstride = 0;
+}
+
+static inline struct st_fdma_chan *st_fdma_prep_common(struct dma_chan *chan,
+ size_t len, enum dma_transfer_direction direction)
+{
+ struct st_fdma_chan *fchan;
+
+ if (!chan || !len)
+ return NULL;
+
+ fchan = to_st_fdma_chan(chan);
+
+ if (!is_slave_direction(direction)) {
+ dev_err(fchan->fdev->dev, "bad direction?\n");
+ return NULL;
+ }
+
+ return fchan;
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags)
+{
+ struct st_fdma_chan *fchan;
+ struct st_fdma_desc *fdesc;
+ int sg_len, i;
+
+ fchan = st_fdma_prep_common(chan, len, direction);
+ if (!fchan)
+ return NULL;
+
+ if (!period_len)
+ return NULL;
+
+ if (config_reqctrl(fchan, direction)) {
+ dev_err(fchan->fdev->dev, "bad width or direction\n");
+ return NULL;
+ }
+
+ /* the buffer length must be a multiple of period_len */
+ if (len % period_len != 0) {
+ dev_err(fchan->fdev->dev, "len is not multiple of period\n");
+ return NULL;
+ }
+
+ sg_len = len / period_len;
+ fdesc = st_fdma_alloc_desc(fchan, sg_len);
+ if (!fdesc) {
+ dev_err(fchan->fdev->dev, "no memory for desc\n");
+ return NULL;
+ }
+
+ fdesc->iscyclic = true;
+
+ for (i = 0; i < sg_len; i++) {
+ struct st_fdma_hw_node *hw_node = fdesc->node[i].desc;
+
+ hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+
+ hw_node->control =
+ FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+ hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+
+ fill_hw_node(hw_node, fchan, direction);
+
+ if (direction == DMA_MEM_TO_DEV)
+ hw_node->saddr = buf_addr + (i * period_len);
+ else
+ hw_node->daddr = buf_addr + (i * period_len);
+
+ hw_node->nbytes = period_len;
+ hw_node->generic.length = period_len;
+ }
+
+ return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct st_fdma_chan *fchan;
+ struct st_fdma_desc *fdesc;
+ struct st_fdma_hw_node *hw_node;
+ struct scatterlist *sg;
+ int i;
+
+ fchan = st_fdma_prep_common(chan, sg_len, direction);
+ if (!fchan)
+ return NULL;
+
+ if (!sgl)
+ return NULL;
+
+ fdesc = st_fdma_alloc_desc(fchan, sg_len);
+ if (!fdesc) {
+ dev_err(fchan->fdev->dev, "no memory for desc\n");
+ return NULL;
+ }
+
+ fdesc->iscyclic = false;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ hw_node = fdesc->node[i].desc;
+
+ hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+ hw_node->control = FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+
+ fill_hw_node(hw_node, fchan, direction);
+
+ if (direction == DMA_MEM_TO_DEV)
+ hw_node->saddr = sg_dma_address(sg);
+ else
+ hw_node->daddr = sg_dma_address(sg);
+
+ hw_node->nbytes = sg_dma_len(sg);
+ hw_node->generic.length = sg_dma_len(sg);
+ }
+
+ /* interrupt at end of last node */
+ hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+
+ return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static size_t st_fdma_desc_residue(struct st_fdma_chan *fchan,
+ struct virt_dma_desc *vdesc,
+ bool in_progress)
+{
+ struct st_fdma_desc *fdesc = fchan->fdesc;
+ size_t residue = 0;
+ dma_addr_t cur_addr = 0;
+ int i;
+
+ if (in_progress) {
+ cur_addr = fchan_read(fchan, FDMA_CH_CMD_OFST);
+ cur_addr &= FDMA_CH_CMD_DATA_MASK;
+ }
+
+ for (i = fchan->fdesc->n_nodes - 1 ; i >= 0; i--) {
+ if (cur_addr == fdesc->node[i].pdesc) {
+ residue += fnode_read(fchan, FDMA_CNTN_OFST);
+ break;
+ }
+ residue += fdesc->node[i].desc->nbytes;
+ }
+
+ return residue;
+}
+
+static enum dma_status st_fdma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+ vd = vchan_find_desc(&fchan->vchan, cookie);
+ if (fchan->fdesc && cookie == fchan->fdesc->vdesc.tx.cookie)
+ txstate->residue = st_fdma_desc_residue(fchan, vd, true);
+ else if (vd)
+ txstate->residue = st_fdma_desc_residue(fchan, vd, false);
+ else
+ txstate->residue = 0;
+
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+ return ret;
+}
+
+static void st_fdma_issue_pending(struct dma_chan *chan)
+{
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+
+ if (vchan_issue_pending(&fchan->vchan) && !fchan->fdesc)
+ st_fdma_xfer_desc(fchan);
+
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+}
+
+static int st_fdma_pause(struct dma_chan *chan)
+{
+ unsigned long flags;
+ LIST_HEAD(head);
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ int ch_id = fchan->vchan.chan.chan_id;
+ unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+ dev_dbg(fchan->fdev->dev, "pause chan:%d\n", ch_id);
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+ if (fchan->fdesc)
+ fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+ return 0;
+}
+
+static int st_fdma_resume(struct dma_chan *chan)
+{
+ unsigned long flags;
+ unsigned long val;
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ int ch_id = fchan->vchan.chan.chan_id;
+
+ dev_dbg(fchan->fdev->dev, "resume chan:%d\n", ch_id);
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+ if (fchan->fdesc) {
+ val = fchan_read(fchan, FDMA_CH_CMD_OFST);
+ val &= FDMA_CH_CMD_DATA_MASK;
+ fchan_write(fchan, val, FDMA_CH_CMD_OFST);
+ }
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+ return 0;
+}
+
+static int st_fdma_terminate_all(struct dma_chan *chan)
+{
+ unsigned long flags;
+ LIST_HEAD(head);
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+ int ch_id = fchan->vchan.chan.chan_id;
+ unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+ dev_dbg(fchan->fdev->dev, "terminate chan:%d\n", ch_id);
+
+ spin_lock_irqsave(&fchan->vchan.lock, flags);
+ fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+ fchan->fdesc = NULL;
+ vchan_get_all_descriptors(&fchan->vchan, &head);
+ spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+ vchan_dma_desc_free_list(&fchan->vchan, &head);
+
+ return 0;
+}
+
+static int st_fdma_slave_config(struct dma_chan *chan,
+ struct dma_slave_config *slave_cfg)
+{
+ struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+
+ memcpy(&fchan->scfg, slave_cfg, sizeof(fchan->scfg));
+ return 0;
+}
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_11 = {
+ .name = "STiH407",
+ .id = 0,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_12 = {
+ .name = "STiH407",
+ .id = 1,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_13 = {
+ .name = "STiH407",
+ .id = 2,
+};
+
+static const struct of_device_id st_fdma_match[] = {
+ { .compatible = "st,stih407-fdma-mpe31-11"
+ , .data = &fdma_mpe31_stih407_11 },
+ { .compatible = "st,stih407-fdma-mpe31-12"
+ , .data = &fdma_mpe31_stih407_12 },
+ { .compatible = "st,stih407-fdma-mpe31-13"
+ , .data = &fdma_mpe31_stih407_13 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_fdma_match);
+
+static int st_fdma_parse_dt(struct platform_device *pdev,
+ const struct st_fdma_driverdata *drvdata,
+ struct st_fdma_dev *fdev)
+{
+ snprintf(fdev->fw_name, FW_NAME_SIZE, "fdma_%s_%d.elf",
+ drvdata->name, drvdata->id);
+
+ return of_property_read_u32(pdev->dev.of_node, "dma-channels",
+ &fdev->nr_channels);
+}
+#define FDMA_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 st_fdma_free(struct st_fdma_dev *fdev)
+{
+ struct st_fdma_chan *fchan;
+ int i;
+
+ for (i = 0; i < fdev->nr_channels; i++) {
+ fchan = &fdev->chans[i];
+ list_del(&fchan->vchan.chan.device_node);
+ tasklet_kill(&fchan->vchan.task);
+ }
+}
+
+static int st_fdma_probe(struct platform_device *pdev)
+{
+ struct st_fdma_dev *fdev;
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+ const struct st_fdma_driverdata *drvdata;
+ int ret, i;
+
+ match = of_match_device((st_fdma_match), &pdev->dev);
+ if (!match || !match->data) {
+ dev_err(&pdev->dev, "No device match found\n");
+ return -ENODEV;
+ }
+
+ drvdata = match->data;
+
+ fdev = devm_kzalloc(&pdev->dev, sizeof(*fdev), GFP_KERNEL);
+ if (!fdev)
+ return -ENOMEM;
+
+ ret = st_fdma_parse_dt(pdev, drvdata, fdev);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to find platform data\n");
+ goto err;
+ }
+
+ fdev->chans = devm_kcalloc(&pdev->dev, fdev->nr_channels,
+ sizeof(struct st_fdma_chan), GFP_KERNEL);
+ if (!fdev->chans)
+ return -ENOMEM;
+
+ fdev->dev = &pdev->dev;
+ fdev->drvdata = drvdata;
+ platform_set_drvdata(pdev, fdev);
+
+ fdev->irq = platform_get_irq(pdev, 0);
+ if (fdev->irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq resource\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0,
+ dev_name(&pdev->dev), fdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq (%d)\n", ret);
+ goto err;
+ }
+
+ fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name);
+ if (IS_ERR(fdev->slim_rproc)) {
+ ret = PTR_ERR(fdev->slim_rproc);
+ dev_err(&pdev->dev, "slim_rproc_alloc failed (%d)\n", ret);
+ goto err;
+ }
+
+ /* Initialise list of FDMA channels */
+ INIT_LIST_HEAD(&fdev->dma_device.channels);
+ for (i = 0; i < fdev->nr_channels; i++) {
+ struct st_fdma_chan *fchan = &fdev->chans[i];
+
+ fchan->fdev = fdev;
+ fchan->vchan.desc_free = st_fdma_free_desc;
+ vchan_init(&fchan->vchan, &fdev->dma_device);
+ }
+
+ /* Initialise the FDMA dreq (reserve 0 & 31 for FDMA use) */
+ fdev->dreq_mask = BIT(0) | BIT(31);
+
+ dma_cap_set(DMA_SLAVE, fdev->dma_device.cap_mask);
+ dma_cap_set(DMA_CYCLIC, fdev->dma_device.cap_mask);
+ dma_cap_set(DMA_MEMCPY, fdev->dma_device.cap_mask);
+
+ fdev->dma_device.dev = &pdev->dev;
+ fdev->dma_device.device_alloc_chan_resources = st_fdma_alloc_chan_res;
+ fdev->dma_device.device_free_chan_resources = st_fdma_free_chan_res;
+ fdev->dma_device.device_prep_dma_cyclic = st_fdma_prep_dma_cyclic;
+ fdev->dma_device.device_prep_slave_sg = st_fdma_prep_slave_sg;
+ fdev->dma_device.device_prep_dma_memcpy = st_fdma_prep_dma_memcpy;
+ fdev->dma_device.device_tx_status = st_fdma_tx_status;
+ fdev->dma_device.device_issue_pending = st_fdma_issue_pending;
+ fdev->dma_device.device_terminate_all = st_fdma_terminate_all;
+ fdev->dma_device.device_config = st_fdma_slave_config;
+ fdev->dma_device.device_pause = st_fdma_pause;
+ fdev->dma_device.device_resume = st_fdma_resume;
+
+ fdev->dma_device.src_addr_widths = FDMA_DMA_BUSWIDTHS;
+ fdev->dma_device.dst_addr_widths = FDMA_DMA_BUSWIDTHS;
+ fdev->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ fdev->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+ ret = dma_async_device_register(&fdev->dma_device);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register DMA device (%d)\n", ret);
+ goto err_rproc;
+ }
+
+ ret = of_dma_controller_register(np, st_fdma_of_xlate, fdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register controller (%d)\n", ret);
+ goto err_dma_dev;
+ }
+
+ dev_info(&pdev->dev, "ST FDMA engine driver, irq:%d\n", fdev->irq);
+
+ return 0;
+
+err_dma_dev:
+ dma_async_device_unregister(&fdev->dma_device);
+err_rproc:
+ st_fdma_free(fdev);
+ st_slim_rproc_put(fdev->slim_rproc);
+err:
+ return ret;
+}
+
+static int st_fdma_remove(struct platform_device *pdev)
+{
+ struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
+
+ devm_free_irq(&pdev->dev, fdev->irq, fdev);
+ st_slim_rproc_put(fdev->slim_rproc);
+ of_dma_controller_free(pdev->dev.of_node);
+ dma_async_device_unregister(&fdev->dma_device);
+
+ return 0;
+}
+
+static struct platform_driver st_fdma_platform_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = st_fdma_match,
+ },
+ .probe = st_fdma_probe,
+ .remove = st_fdma_remove,
+};
+module_platform_driver(st_fdma_platform_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
+MODULE_AUTHOR("Ludovic.barre <Ludovic.barre@st.com>");
+MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
+MODULE_ALIAS("platform: " DRIVER_NAME);
diff --git a/drivers/dma/st_fdma.h b/drivers/dma/st_fdma.h
new file mode 100644
index 000000000000..c58e00d4ab37
--- /dev/null
+++ b/drivers/dma/st_fdma.h
@@ -0,0 +1,249 @@
+/*
+ * DMA driver header for STMicroelectronics STi FDMA controller
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * Author: Ludovic Barre <Ludovic.barre@st.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.
+ */
+#ifndef __DMA_ST_FDMA_H
+#define __DMA_ST_FDMA_H
+
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/io.h>
+#include <linux/remoteproc/st_slim_rproc.h>
+#include "virt-dma.h"
+
+#define ST_FDMA_NR_DREQS 32
+#define FW_NAME_SIZE 30
+#define DRIVER_NAME "st-fdma"
+
+/**
+ * struct st_fdma_generic_node - Free running/paced generic node
+ *
+ * @length: Length in bytes of a line in a 2D mem to mem
+ * @sstride: Stride, in bytes, between source lines in a 2D data move
+ * @dstride: Stride, in bytes, between destination lines in a 2D data move
+ */
+struct st_fdma_generic_node {
+ u32 length;
+ u32 sstride;
+ u32 dstride;
+};
+
+/**
+ * struct st_fdma_hw_node - Node structure used by fdma hw
+ *
+ * @next: Pointer to next node
+ * @control: Transfer Control Parameters
+ * @nbytes: Number of Bytes to read
+ * @saddr: Source address
+ * @daddr: Destination address
+ *
+ * @generic: generic node for free running/paced transfert type
+ * 2 others transfert type are possible, but not yet implemented
+ *
+ * The NODE structures must be aligned to a 32 byte boundary
+ */
+struct st_fdma_hw_node {
+ u32 next;
+ u32 control;
+ u32 nbytes;
+ u32 saddr;
+ u32 daddr;
+ union {
+ struct st_fdma_generic_node generic;
+ };
+} __aligned(32);
+
+/*
+ * node control parameters
+ */
+#define FDMA_NODE_CTRL_REQ_MAP_MASK GENMASK(4, 0)
+#define FDMA_NODE_CTRL_REQ_MAP_FREE_RUN 0x0
+#define FDMA_NODE_CTRL_REQ_MAP_DREQ(n) ((n)&FDMA_NODE_CTRL_REQ_MAP_MASK)
+#define FDMA_NODE_CTRL_REQ_MAP_EXT FDMA_NODE_CTRL_REQ_MAP_MASK
+#define FDMA_NODE_CTRL_SRC_MASK GENMASK(6, 5)
+#define FDMA_NODE_CTRL_SRC_STATIC BIT(5)
+#define FDMA_NODE_CTRL_SRC_INCR BIT(6)
+#define FDMA_NODE_CTRL_DST_MASK GENMASK(8, 7)
+#define FDMA_NODE_CTRL_DST_STATIC BIT(7)
+#define FDMA_NODE_CTRL_DST_INCR BIT(8)
+#define FDMA_NODE_CTRL_SECURE BIT(15)
+#define FDMA_NODE_CTRL_PAUSE_EON BIT(30)
+#define FDMA_NODE_CTRL_INT_EON BIT(31)
+
+/**
+ * struct st_fdma_sw_node - descriptor structure for link list
+ *
+ * @pdesc: Physical address of desc
+ * @node: link used for putting this into a channel queue
+ */
+struct st_fdma_sw_node {
+ dma_addr_t pdesc;
+ struct st_fdma_hw_node *desc;
+};
+
+#define NAME_SZ 10
+
+struct st_fdma_driverdata {
+ u32 id;
+ char name[NAME_SZ];
+};
+
+struct st_fdma_desc {
+ struct virt_dma_desc vdesc;
+ struct st_fdma_chan *fchan;
+ bool iscyclic;
+ unsigned int n_nodes;
+ struct st_fdma_sw_node node[];
+};
+
+enum st_fdma_type {
+ ST_FDMA_TYPE_FREE_RUN,
+ ST_FDMA_TYPE_PACED,
+};
+
+struct st_fdma_cfg {
+ struct device_node *of_node;
+ enum st_fdma_type type;
+ dma_addr_t dev_addr;
+ enum dma_transfer_direction dir;
+ int req_line; /* request line */
+ long req_ctrl; /* Request control */
+};
+
+struct st_fdma_chan {
+ struct st_fdma_dev *fdev;
+ struct dma_pool *node_pool;
+ struct dma_slave_config scfg;
+ struct st_fdma_cfg cfg;
+
+ int dreq_line;
+
+ struct virt_dma_chan vchan;
+ struct st_fdma_desc *fdesc;
+ enum dma_status status;
+};
+
+struct st_fdma_dev {
+ struct device *dev;
+ const struct st_fdma_driverdata *drvdata;
+ struct dma_device dma_device;
+
+ struct st_slim_rproc *slim_rproc;
+
+ int irq;
+
+ struct st_fdma_chan *chans;
+
+ spinlock_t dreq_lock;
+ unsigned long dreq_mask;
+
+ u32 nr_channels;
+ char fw_name[FW_NAME_SIZE];
+};
+
+/* Peripheral Registers*/
+
+#define FDMA_CMD_STA_OFST 0xFC0
+#define FDMA_CMD_SET_OFST 0xFC4
+#define FDMA_CMD_CLR_OFST 0xFC8
+#define FDMA_CMD_MASK_OFST 0xFCC
+#define FDMA_CMD_START(ch) (0x1 << (ch << 1))
+#define FDMA_CMD_PAUSE(ch) (0x2 << (ch << 1))
+#define FDMA_CMD_FLUSH(ch) (0x3 << (ch << 1))
+
+#define FDMA_INT_STA_OFST 0xFD0
+#define FDMA_INT_STA_CH 0x1
+#define FDMA_INT_STA_ERR 0x2
+
+#define FDMA_INT_SET_OFST 0xFD4
+#define FDMA_INT_CLR_OFST 0xFD8
+#define FDMA_INT_MASK_OFST 0xFDC
+
+#define fdma_read(fdev, name) \
+ readl((fdev)->slim_rproc->peri + name)
+
+#define fdma_write(fdev, val, name) \
+ writel((val), (fdev)->slim_rproc->peri + name)
+
+/* fchan interface (dmem) */
+#define FDMA_CH_CMD_OFST 0x200
+#define FDMA_CH_CMD_STA_MASK GENMASK(1, 0)
+#define FDMA_CH_CMD_STA_IDLE (0x0)
+#define FDMA_CH_CMD_STA_START (0x1)
+#define FDMA_CH_CMD_STA_RUNNING (0x2)
+#define FDMA_CH_CMD_STA_PAUSED (0x3)
+#define FDMA_CH_CMD_ERR_MASK GENMASK(4, 2)
+#define FDMA_CH_CMD_ERR_INT (0x0 << 2)
+#define FDMA_CH_CMD_ERR_NAND (0x1 << 2)
+#define FDMA_CH_CMD_ERR_MCHI (0x2 << 2)
+#define FDMA_CH_CMD_DATA_MASK GENMASK(31, 5)
+#define fchan_read(fchan, name) \
+ readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+ + (fchan)->vchan.chan.chan_id * 0x4 \
+ + name)
+
+#define fchan_write(fchan, val, name) \
+ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+ + (fchan)->vchan.chan.chan_id * 0x4 \
+ + name)
+
+/* req interface */
+#define FDMA_REQ_CTRL_OFST 0x240
+#define dreq_write(fchan, val, name) \
+ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+ + fchan->dreq_line * 0x04 \
+ + name)
+/* node interface */
+#define FDMA_NODE_SZ 128
+#define FDMA_PTRN_OFST 0x800
+#define FDMA_CNTN_OFST 0x808
+#define FDMA_SADDRN_OFST 0x80c
+#define FDMA_DADDRN_OFST 0x810
+#define fnode_read(fchan, name) \
+ readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+ + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+ + name)
+
+#define fnode_write(fchan, val, name) \
+ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+ + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+ + name)
+
+/*
+ * request control bits
+ */
+#define FDMA_REQ_CTRL_NUM_OPS_MASK GENMASK(31, 24)
+#define FDMA_REQ_CTRL_NUM_OPS(n) (FDMA_REQ_CTRL_NUM_OPS_MASK & \
+ ((n) << 24))
+#define FDMA_REQ_CTRL_INITIATOR_MASK BIT(22)
+#define FDMA_REQ_CTRL_INIT0 (0x0 << 22)
+#define FDMA_REQ_CTRL_INIT1 (0x1 << 22)
+#define FDMA_REQ_CTRL_INC_ADDR_ON BIT(21)
+#define FDMA_REQ_CTRL_DATA_SWAP_ON BIT(17)
+#define FDMA_REQ_CTRL_WNR BIT(14)
+#define FDMA_REQ_CTRL_OPCODE_MASK GENMASK(7, 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST1 (0x0 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST2 (0x1 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST4 (0x2 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST8 (0x3 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST16 (0x4 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST32 (0x5 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST64 (0x6 << 4)
+#define FDMA_REQ_CTRL_HOLDOFF_MASK GENMASK(2, 0)
+#define FDMA_REQ_CTRL_HOLDOFF(n) ((n) & FDMA_REQ_CTRL_HOLDOFF_MASK)
+
+/* bits used by client to configure request control */
+#define FDMA_REQ_CTRL_CFG_MASK (FDMA_REQ_CTRL_HOLDOFF_MASK | \
+ FDMA_REQ_CTRL_DATA_SWAP_ON | \
+ FDMA_REQ_CTRL_INC_ADDR_ON | \
+ FDMA_REQ_CTRL_INITIATOR_MASK)
+
+#endif /* __DMA_ST_FDMA_H */
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 58d3e2b39b5b..6421cc3c7dc1 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -153,13 +153,17 @@ static ssize_t altr_sdr_mc_err_inject_write(struct file *file,
if (count == 3) {
edac_printk(KERN_ALERT, EDAC_MC,
"Inject Double bit error\n");
+ local_irq_disable();
regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
(read_reg | priv->ue_set_mask));
+ local_irq_enable();
} else {
edac_printk(KERN_ALERT, EDAC_MC,
"Inject Single bit error\n");
+ local_irq_disable();
regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
(read_reg | priv->ce_set_mask));
+ local_irq_enable();
}
ptemp[0] = 0x5A5A5A5A;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index ee181c53626f..260251177830 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -164,8 +164,23 @@ static inline int amd64_read_dct_pci_cfg(struct amd64_pvt *pvt, u8 dct,
* other archs, we might not have access to the caches directly.
*/
+static inline void __f17h_set_scrubval(struct amd64_pvt *pvt, u32 scrubval)
+{
+ /*
+ * Fam17h supports scrub values between 0x5 and 0x14. Also, the values
+ * are shifted down by 0x5, so scrubval 0x5 is written to the register
+ * as 0x0, scrubval 0x6 as 0x1, etc.
+ */
+ if (scrubval >= 0x5 && scrubval <= 0x14) {
+ scrubval -= 0x5;
+ pci_write_bits32(pvt->F6, F17H_SCR_LIMIT_ADDR, scrubval, 0xF);
+ pci_write_bits32(pvt->F6, F17H_SCR_BASE_ADDR, 1, 0x1);
+ } else {
+ pci_write_bits32(pvt->F6, F17H_SCR_BASE_ADDR, 0, 0x1);
+ }
+}
/*
- * scan the scrub rate mapping table for a close or matching bandwidth value to
+ * 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 amd64_pvt *pvt, u32 new_bw, u32 min_rate)
@@ -196,7 +211,9 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 new_bw, u32 min_rate)
scrubval = scrubrates[i].scrubval;
- if (pvt->fam == 0x15 && pvt->model == 0x60) {
+ if (pvt->fam == 0x17) {
+ __f17h_set_scrubval(pvt, scrubval);
+ } else 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);
@@ -233,18 +250,34 @@ static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
static int get_scrub_rate(struct mem_ctl_info *mci)
{
struct amd64_pvt *pvt = mci->pvt_info;
- u32 scrubval = 0;
int i, retval = -EINVAL;
+ u32 scrubval = 0;
- if (pvt->fam == 0x15) {
+ switch (pvt->fam) {
+ case 0x15:
/* Erratum #505 */
if (pvt->model < 0x10)
f15h_select_dct(pvt, 0);
if (pvt->model == 0x60)
amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
- } else
+ break;
+
+ case 0x17:
+ amd64_read_pci_cfg(pvt->F6, F17H_SCR_BASE_ADDR, &scrubval);
+ if (scrubval & BIT(0)) {
+ amd64_read_pci_cfg(pvt->F6, F17H_SCR_LIMIT_ADDR, &scrubval);
+ scrubval &= 0xF;
+ scrubval += 0x5;
+ } else {
+ scrubval = 0;
+ }
+ break;
+
+ default:
amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
+ break;
+ }
scrubval = scrubval & 0x001F;
@@ -682,15 +715,33 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
*/
static unsigned long determine_edac_cap(struct amd64_pvt *pvt)
{
- u8 bit;
unsigned long edac_cap = EDAC_FLAG_NONE;
+ u8 bit;
- bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
- ? 19
- : 17;
+ if (pvt->umc) {
+ u8 i, umc_en_mask = 0, dimm_ecc_en_mask = 0;
- if (pvt->dclr0 & BIT(bit))
- edac_cap = EDAC_FLAG_SECDED;
+ for (i = 0; i < NUM_UMCS; i++) {
+ if (!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT))
+ continue;
+
+ umc_en_mask |= BIT(i);
+
+ /* UMC Configuration bit 12 (DimmEccEn) */
+ if (pvt->umc[i].umc_cfg & BIT(12))
+ dimm_ecc_en_mask |= BIT(i);
+ }
+
+ if (umc_en_mask == dimm_ecc_en_mask)
+ edac_cap = EDAC_FLAG_SECDED;
+ } else {
+ bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
+ ? 19
+ : 17;
+
+ if (pvt->dclr0 & BIT(bit))
+ edac_cap = EDAC_FLAG_SECDED;
+ }
return edac_cap;
}
@@ -729,8 +780,75 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
(dclr & BIT(15)) ? "yes" : "no");
}
+static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
+{
+ u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
+ int dimm, size0, size1;
+
+ edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
+
+ for (dimm = 0; dimm < 4; dimm++) {
+ size0 = 0;
+
+ if (dcsb[dimm*2] & DCSB_CS_ENABLE)
+ size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+
+ size1 = 0;
+ if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
+ size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+
+ amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
+ dimm * 2, size0,
+ dimm * 2 + 1, size1);
+ }
+}
+
+static void __dump_misc_regs_df(struct amd64_pvt *pvt)
+{
+ struct amd64_umc *umc;
+ u32 i, tmp, umc_base;
+
+ for (i = 0; i < NUM_UMCS; i++) {
+ umc_base = get_umc_base(i);
+ umc = &pvt->umc[i];
+
+ edac_dbg(1, "UMC%d DIMM cfg: 0x%x\n", i, umc->dimm_cfg);
+ edac_dbg(1, "UMC%d UMC cfg: 0x%x\n", i, umc->umc_cfg);
+ edac_dbg(1, "UMC%d SDP ctrl: 0x%x\n", i, umc->sdp_ctrl);
+ edac_dbg(1, "UMC%d ECC ctrl: 0x%x\n", i, umc->ecc_ctrl);
+
+ amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_ECC_BAD_SYMBOL, &tmp);
+ edac_dbg(1, "UMC%d ECC bad symbol: 0x%x\n", i, tmp);
+
+ amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_UMC_CAP, &tmp);
+ edac_dbg(1, "UMC%d UMC cap: 0x%x\n", i, tmp);
+ edac_dbg(1, "UMC%d UMC cap high: 0x%x\n", i, umc->umc_cap_hi);
+
+ edac_dbg(1, "UMC%d ECC capable: %s, ChipKill ECC capable: %s\n",
+ i, (umc->umc_cap_hi & BIT(30)) ? "yes" : "no",
+ (umc->umc_cap_hi & BIT(31)) ? "yes" : "no");
+ edac_dbg(1, "UMC%d All DIMMs support ECC: %s\n",
+ i, (umc->umc_cfg & BIT(12)) ? "yes" : "no");
+ edac_dbg(1, "UMC%d x4 DIMMs present: %s\n",
+ i, (umc->dimm_cfg & BIT(6)) ? "yes" : "no");
+ edac_dbg(1, "UMC%d x16 DIMMs present: %s\n",
+ i, (umc->dimm_cfg & BIT(7)) ? "yes" : "no");
+
+ if (pvt->dram_type == MEM_LRDDR4) {
+ amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_ADDR_CFG, &tmp);
+ edac_dbg(1, "UMC%d LRDIMM %dx rank multiply\n",
+ i, 1 << ((tmp >> 4) & 0x3));
+ }
+
+ debug_display_dimm_sizes_df(pvt, i);
+ }
+
+ edac_dbg(1, "F0x104 (DRAM Hole Address): 0x%08x, base: 0x%08x\n",
+ pvt->dhar, dhar_base(pvt));
+}
+
/* Display and decode various NB registers for debug purposes. */
-static void dump_misc_regs(struct amd64_pvt *pvt)
+static void __dump_misc_regs(struct amd64_pvt *pvt)
{
edac_dbg(1, "F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
@@ -750,8 +868,6 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
(pvt->fam == 0xf) ? k8_dhar_offset(pvt)
: f10_dhar_offset(pvt));
- edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
-
debug_display_dimm_sizes(pvt, 0);
/* everything below this point is Fam10h and above */
@@ -760,13 +876,25 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
debug_display_dimm_sizes(pvt, 1);
- amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
-
/* Only if NOT ganged does dclr1 have valid info */
if (!dct_ganging_enabled(pvt))
debug_dump_dramcfg_low(pvt, pvt->dclr1, 1);
}
+/* Display and decode various NB registers for debug purposes. */
+static void dump_misc_regs(struct amd64_pvt *pvt)
+{
+ if (pvt->umc)
+ __dump_misc_regs_df(pvt);
+ else
+ __dump_misc_regs(pvt);
+
+ edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
+
+ amd64_info("using %s syndromes.\n",
+ ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
+}
+
/*
* See BKDG, F2x[1,0][5C:40], F2[1,0][6C:60]
*/
@@ -789,46 +917,78 @@ static void prep_chip_selects(struct amd64_pvt *pvt)
*/
static void read_dct_base_mask(struct amd64_pvt *pvt)
{
- int cs;
+ int base_reg0, base_reg1, mask_reg0, mask_reg1, cs;
prep_chip_selects(pvt);
+ if (pvt->umc) {
+ base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR;
+ base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR;
+ mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK;
+ mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK;
+ } else {
+ base_reg0 = DCSB0;
+ base_reg1 = DCSB1;
+ mask_reg0 = DCSM0;
+ mask_reg1 = DCSM1;
+ }
+
for_each_chip_select(cs, 0, pvt) {
- int reg0 = DCSB0 + (cs * 4);
- int reg1 = DCSB1 + (cs * 4);
+ int reg0 = base_reg0 + (cs * 4);
+ int reg1 = base_reg1 + (cs * 4);
u32 *base0 = &pvt->csels[0].csbases[cs];
u32 *base1 = &pvt->csels[1].csbases[cs];
- if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
- edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
- cs, *base0, reg0);
+ if (pvt->umc) {
+ if (!amd_smn_read(pvt->mc_node_id, reg0, base0))
+ edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n",
+ cs, *base0, reg0);
- if (pvt->fam == 0xf)
- continue;
+ if (!amd_smn_read(pvt->mc_node_id, reg1, base1))
+ edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n",
+ cs, *base1, reg1);
+ } else {
+ if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
+ edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
+ cs, *base0, reg0);
+
+ if (pvt->fam == 0xf)
+ continue;
- if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
- edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",
- cs, *base1, (pvt->fam == 0x10) ? reg1
+ if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
+ edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",
+ cs, *base1, (pvt->fam == 0x10) ? reg1
: reg0);
+ }
}
for_each_chip_select_mask(cs, 0, pvt) {
- int reg0 = DCSM0 + (cs * 4);
- int reg1 = DCSM1 + (cs * 4);
+ int reg0 = mask_reg0 + (cs * 4);
+ int reg1 = mask_reg1 + (cs * 4);
u32 *mask0 = &pvt->csels[0].csmasks[cs];
u32 *mask1 = &pvt->csels[1].csmasks[cs];
- if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
- edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
- cs, *mask0, reg0);
+ if (pvt->umc) {
+ if (!amd_smn_read(pvt->mc_node_id, reg0, mask0))
+ edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n",
+ cs, *mask0, reg0);
- if (pvt->fam == 0xf)
- continue;
+ if (!amd_smn_read(pvt->mc_node_id, reg1, mask1))
+ edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n",
+ cs, *mask1, reg1);
+ } else {
+ if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
+ edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
+ cs, *mask0, reg0);
+
+ if (pvt->fam == 0xf)
+ continue;
- if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
- edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",
- cs, *mask1, (pvt->fam == 0x10) ? reg1
+ if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
+ edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",
+ cs, *mask1, (pvt->fam == 0x10) ? reg1
: reg0);
+ }
}
}
@@ -881,6 +1041,15 @@ static void determine_memory_type(struct amd64_pvt *pvt)
case 0x16:
goto ddr3;
+ case 0x17:
+ if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5))
+ pvt->dram_type = MEM_LRDDR4;
+ else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4))
+ pvt->dram_type = MEM_RDDR4;
+ else
+ pvt->dram_type = MEM_DDR4;
+ return;
+
default:
WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
pvt->dram_type = MEM_EMPTY;
@@ -1210,6 +1379,19 @@ static int f1x_early_channel_count(struct amd64_pvt *pvt)
return channels;
}
+static int f17_early_channel_count(struct amd64_pvt *pvt)
+{
+ int i, channels = 0;
+
+ /* SDP Control bit 31 (SdpInit) is clear for unused UMC channels */
+ for (i = 0; i < NUM_UMCS; i++)
+ channels += !!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT);
+
+ amd64_info("MCT channel count: %d\n", channels);
+
+ return channels;
+}
+
static int ddr3_cs_size(unsigned i, bool dct_width)
{
unsigned shift = 0;
@@ -1337,6 +1519,23 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
return ddr3_cs_size(cs_mode, false);
}
+static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc,
+ unsigned int cs_mode, int csrow_nr)
+{
+ u32 base_addr = pvt->csels[umc].csbases[csrow_nr];
+
+ /* Each mask is used for every two base addresses. */
+ u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1];
+
+ /* Register [31:1] = Address [39:9]. Size is in kBs here. */
+ u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1;
+
+ edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask);
+
+ /* Return size in MBs. */
+ return size >> 10;
+}
+
static void read_dram_ctl_register(struct amd64_pvt *pvt)
{
@@ -1897,8 +2096,9 @@ static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
size0 = 0;
if (dcsb[dimm*2] & DCSB_CS_ENABLE)
- /* For f15m60h, need multiplier for LRDIMM cs_size
- * calculation. We pass 'dimm' value to the dbam_to_cs
+ /*
+ * For F15m60h, we need multiplier for LRDIMM cs_size
+ * calculation. We pass dimm value to the dbam_to_cs
* mapper so we can find the multiplier from the
* corresponding DCSM.
*/
@@ -1989,6 +2189,15 @@ static struct amd64_family_type family_types[] = {
.dbam_to_cs = f16_dbam_to_chip_select,
}
},
+ [F17_CPUS] = {
+ .ctl_name = "F17h",
+ .f0_id = PCI_DEVICE_ID_AMD_17H_DF_F0,
+ .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6,
+ .ops = {
+ .early_channel_count = f17_early_channel_count,
+ .dbam_to_cs = f17_base_addr_to_cs_size,
+ }
+ },
};
/*
@@ -2155,7 +2364,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
}
-static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
+static void __log_ecc_error(struct mem_ctl_info *mci, struct err_info *err,
u8 ecc_type)
{
enum hw_event_mc_err_type err_type;
@@ -2165,6 +2374,8 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
err_type = HW_EVENT_ERR_CORRECTED;
else if (ecc_type == 1)
err_type = HW_EVENT_ERR_UNCORRECTED;
+ else if (ecc_type == 3)
+ err_type = HW_EVENT_ERR_DEFERRED;
else {
WARN(1, "Something is rotten in the state of Denmark.\n");
return;
@@ -2181,7 +2392,13 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
string = "Failed to map error addr to a csrow";
break;
case ERR_CHANNEL:
- string = "unknown syndrome - possible error reporting race";
+ string = "Unknown syndrome - possible error reporting race";
+ break;
+ case ERR_SYND:
+ string = "MCA_SYND not valid - unknown syndrome and csrow";
+ break;
+ case ERR_NORM_ADDR:
+ string = "Cannot decode normalized address";
break;
default:
string = "WTF error";
@@ -2227,36 +2444,127 @@ static inline void decode_bus_error(int node_id, struct mce *m)
pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, &err);
- __log_bus_error(mci, &err, ecc_type);
+ __log_ecc_error(mci, &err, ecc_type);
+}
+
+/*
+ * To find the UMC channel represented by this bank we need to match on its
+ * instance_id. The instance_id of a bank is held in the lower 32 bits of its
+ * IPID.
+ */
+static int find_umc_channel(struct amd64_pvt *pvt, struct mce *m)
+{
+ u32 umc_instance_id[] = {0x50f00, 0x150f00};
+ u32 instance_id = m->ipid & GENMASK(31, 0);
+ int i, channel = -1;
+
+ for (i = 0; i < ARRAY_SIZE(umc_instance_id); i++)
+ if (umc_instance_id[i] == instance_id)
+ channel = i;
+
+ return channel;
+}
+
+static void decode_umc_error(int node_id, struct mce *m)
+{
+ u8 ecc_type = (m->status >> 45) & 0x3;
+ struct mem_ctl_info *mci;
+ struct amd64_pvt *pvt;
+ struct err_info err;
+ u64 sys_addr;
+
+ mci = edac_mc_find(node_id);
+ if (!mci)
+ return;
+
+ pvt = mci->pvt_info;
+
+ memset(&err, 0, sizeof(err));
+
+ if (m->status & MCI_STATUS_DEFERRED)
+ ecc_type = 3;
+
+ err.channel = find_umc_channel(pvt, m);
+ if (err.channel < 0) {
+ err.err_code = ERR_CHANNEL;
+ goto log_error;
+ }
+
+ if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
+ err.err_code = ERR_NORM_ADDR;
+ goto log_error;
+ }
+
+ error_address_to_page_and_offset(sys_addr, &err);
+
+ if (!(m->status & MCI_STATUS_SYNDV)) {
+ err.err_code = ERR_SYND;
+ goto log_error;
+ }
+
+ if (ecc_type == 2) {
+ u8 length = (m->synd >> 18) & 0x3f;
+
+ if (length)
+ err.syndrome = (m->synd >> 32) & GENMASK(length - 1, 0);
+ else
+ err.err_code = ERR_CHANNEL;
+ }
+
+ err.csrow = m->synd & 0x7;
+
+log_error:
+ __log_ecc_error(mci, &err, ecc_type);
}
/*
* Use pvt->F3 which contains the F3 CPU PCI device to get the related
* F1 (AddrMap) and F2 (Dct) devices. Return negative value on error.
+ * Reserve F0 and F6 on systems with a UMC.
*/
-static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f2_id)
-{
+static int
+reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
+{
+ if (pvt->umc) {
+ pvt->F0 = pci_get_related_function(pvt->F3->vendor, pci_id1, pvt->F3);
+ if (!pvt->F0) {
+ amd64_err("F0 not found, device 0x%x (broken BIOS?)\n", pci_id1);
+ return -ENODEV;
+ }
+
+ pvt->F6 = pci_get_related_function(pvt->F3->vendor, pci_id2, pvt->F3);
+ if (!pvt->F6) {
+ pci_dev_put(pvt->F0);
+ pvt->F0 = NULL;
+
+ amd64_err("F6 not found: device 0x%x (broken BIOS?)\n", pci_id2);
+ return -ENODEV;
+ }
+
+ edac_dbg(1, "F0: %s\n", pci_name(pvt->F0));
+ edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
+ edac_dbg(1, "F6: %s\n", pci_name(pvt->F6));
+
+ return 0;
+ }
+
/* Reserve the ADDRESS MAP Device */
- pvt->F1 = pci_get_related_function(pvt->F3->vendor, f1_id, pvt->F3);
+ pvt->F1 = pci_get_related_function(pvt->F3->vendor, pci_id1, pvt->F3);
if (!pvt->F1) {
- amd64_err("error address map device not found: "
- "vendor %x device 0x%x (broken BIOS?)\n",
- PCI_VENDOR_ID_AMD, f1_id);
+ amd64_err("F1 not found: device 0x%x (broken BIOS?)\n", pci_id1);
return -ENODEV;
}
/* Reserve the DCT Device */
- pvt->F2 = pci_get_related_function(pvt->F3->vendor, f2_id, pvt->F3);
+ pvt->F2 = pci_get_related_function(pvt->F3->vendor, pci_id2, pvt->F3);
if (!pvt->F2) {
pci_dev_put(pvt->F1);
pvt->F1 = NULL;
- amd64_err("error F2 device not found: "
- "vendor %x device 0x%x (broken BIOS?)\n",
- PCI_VENDOR_ID_AMD, f2_id);
-
+ amd64_err("F2 not found: device 0x%x (broken BIOS?)\n", pci_id2);
return -ENODEV;
}
+
edac_dbg(1, "F1: %s\n", pci_name(pvt->F1));
edac_dbg(1, "F2: %s\n", pci_name(pvt->F2));
edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
@@ -2266,8 +2574,69 @@ static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f2_id)
static void free_mc_sibling_devs(struct amd64_pvt *pvt)
{
- pci_dev_put(pvt->F1);
- pci_dev_put(pvt->F2);
+ if (pvt->umc) {
+ pci_dev_put(pvt->F0);
+ pci_dev_put(pvt->F6);
+ } else {
+ pci_dev_put(pvt->F1);
+ pci_dev_put(pvt->F2);
+ }
+}
+
+static void determine_ecc_sym_sz(struct amd64_pvt *pvt)
+{
+ pvt->ecc_sym_sz = 4;
+
+ if (pvt->umc) {
+ u8 i;
+
+ for (i = 0; i < NUM_UMCS; i++) {
+ /* Check enabled channels only: */
+ if ((pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) &&
+ (pvt->umc[i].ecc_ctrl & BIT(7))) {
+ pvt->ecc_sym_sz = 8;
+ break;
+ }
+ }
+
+ return;
+ }
+
+ if (pvt->fam >= 0x10) {
+ u32 tmp;
+
+ amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+ /* F16h has only DCT0, so no need to read dbam1. */
+ if (pvt->fam != 0x16)
+ amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1);
+
+ /* F10h, revD and later can do x8 ECC too. */
+ if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25))
+ pvt->ecc_sym_sz = 8;
+ }
+}
+
+/*
+ * Retrieve the hardware registers of the memory controller.
+ */
+static void __read_mc_regs_df(struct amd64_pvt *pvt)
+{
+ u8 nid = pvt->mc_node_id;
+ struct amd64_umc *umc;
+ u32 i, umc_base;
+
+ /* Read registers from each UMC */
+ for (i = 0; i < NUM_UMCS; i++) {
+
+ umc_base = get_umc_base(i);
+ umc = &pvt->umc[i];
+
+ amd_smn_read(nid, umc_base + UMCCH_DIMM_CFG, &umc->dimm_cfg);
+ amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
+ amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
+ amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
+ amd_smn_read(nid, umc_base + UMCCH_UMC_CAP_HI, &umc->umc_cap_hi);
+ }
}
/*
@@ -2276,24 +2645,31 @@ static void free_mc_sibling_devs(struct amd64_pvt *pvt)
*/
static void read_mc_regs(struct amd64_pvt *pvt)
{
- unsigned range;
+ unsigned int range;
u64 msr_val;
- u32 tmp;
/*
* Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
- * those are Read-As-Zero
+ * those are Read-As-Zero.
*/
rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem);
edac_dbg(0, " TOP_MEM: 0x%016llx\n", pvt->top_mem);
- /* check first whether TOP_MEM2 is enabled */
+ /* Check first whether TOP_MEM2 is enabled: */
rdmsrl(MSR_K8_SYSCFG, msr_val);
- if (msr_val & (1U << 21)) {
+ if (msr_val & BIT(21)) {
rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2);
edac_dbg(0, " TOP_MEM2: 0x%016llx\n", pvt->top_mem2);
- } else
+ } else {
edac_dbg(0, " TOP_MEM2 disabled\n");
+ }
+
+ if (pvt->umc) {
+ __read_mc_regs_df(pvt);
+ amd64_read_pci_cfg(pvt->F0, DF_DHAR, &pvt->dhar);
+
+ goto skip;
+ }
amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap);
@@ -2322,8 +2698,6 @@ static void read_mc_regs(struct amd64_pvt *pvt)
dram_dst_node(pvt, range));
}
- read_dct_base_mask(pvt);
-
amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar);
amd64_read_dct_pci_cfg(pvt, 0, DBAM0, &pvt->dbam0);
@@ -2337,20 +2711,14 @@ static void read_mc_regs(struct amd64_pvt *pvt)
amd64_read_dct_pci_cfg(pvt, 1, DCHR0, &pvt->dchr1);
}
- pvt->ecc_sym_sz = 4;
+skip:
+ read_dct_base_mask(pvt);
+
determine_memory_type(pvt);
edac_dbg(1, " DIMM type: %s\n", edac_mem_types[pvt->dram_type]);
- if (pvt->fam >= 0x10) {
- amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
- /* F16h has only DCT0, so no need to read dbam1 */
- if (pvt->fam != 0x16)
- amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1);
+ determine_ecc_sym_sz(pvt);
- /* F10h, revD and later can do x8 ECC too */
- if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25))
- pvt->ecc_sym_sz = 8;
- }
dump_misc_regs(pvt);
}
@@ -2420,20 +2788,22 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
static int init_csrows(struct mem_ctl_info *mci)
{
struct amd64_pvt *pvt = mci->pvt_info;
+ enum edac_type edac_mode = EDAC_NONE;
struct csrow_info *csrow;
struct dimm_info *dimm;
- enum edac_type edac_mode;
int i, j, empty = 1;
int nr_pages = 0;
u32 val;
- amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
+ if (!pvt->umc) {
+ amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
- pvt->nbcfg = val;
+ pvt->nbcfg = val;
- edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
- pvt->mc_node_id, val,
- !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
+ edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+ pvt->mc_node_id, val,
+ !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
+ }
/*
* We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
@@ -2469,14 +2839,18 @@ static int init_csrows(struct mem_ctl_info *mci)
edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
- /*
- * determine whether CHIPKILL or JUST ECC or NO ECC is operating
- */
- if (pvt->nbcfg & NBCFG_ECC_ENABLE)
- edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ?
- EDAC_S4ECD4ED : EDAC_SECDED;
- else
- edac_mode = EDAC_NONE;
+ /* Determine DIMM ECC mode: */
+ if (pvt->umc) {
+ if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED)
+ edac_mode = EDAC_S4ECD4ED;
+ else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED)
+ edac_mode = EDAC_SECDED;
+
+ } else if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
+ edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL)
+ ? EDAC_S4ECD4ED
+ : EDAC_SECDED;
+ }
for (j = 0; j < pvt->channel_count; j++) {
dimm = csrow->channels[j]->dimm;
@@ -2539,7 +2913,7 @@ static int toggle_ecc_err_reporting(struct ecc_settings *s, u16 nid, bool on)
if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) {
amd64_warn("%s: error allocating mask\n", __func__);
- return false;
+ return -ENOMEM;
}
get_cpus_on_this_dct_cpumask(cmask, nid);
@@ -2627,7 +3001,6 @@ static void restore_ecc_error_reporting(struct ecc_settings *s, u16 nid,
{
u32 value, mask = 0x3; /* UECC/CECC enable */
-
if (!s->nbctl_valid)
return;
@@ -2663,20 +3036,50 @@ static const char *ecc_msg =
static bool ecc_enabled(struct pci_dev *F3, u16 nid)
{
- u32 value;
- u8 ecc_en = 0;
bool nb_mce_en = false;
+ u8 ecc_en = 0, i;
+ u32 value;
- amd64_read_pci_cfg(F3, NBCFG, &value);
+ if (boot_cpu_data.x86 >= 0x17) {
+ u8 umc_en_mask = 0, ecc_en_mask = 0;
- ecc_en = !!(value & NBCFG_ECC_ENABLE);
- amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
+ for (i = 0; i < NUM_UMCS; i++) {
+ u32 base = get_umc_base(i);
+
+ /* Only check enabled UMCs. */
+ if (amd_smn_read(nid, base + UMCCH_SDP_CTRL, &value))
+ continue;
+
+ if (!(value & UMC_SDP_INIT))
+ continue;
+
+ umc_en_mask |= BIT(i);
- nb_mce_en = nb_mce_bank_enabled_on_node(nid);
- if (!nb_mce_en)
- amd64_notice("NB MCE bank disabled, set MSR "
- "0x%08x[4] on node %d to enable.\n",
- MSR_IA32_MCG_CTL, nid);
+ if (amd_smn_read(nid, base + UMCCH_UMC_CAP_HI, &value))
+ continue;
+
+ if (value & UMC_ECC_ENABLED)
+ ecc_en_mask |= BIT(i);
+ }
+
+ /* Check whether at least one UMC is enabled: */
+ if (umc_en_mask)
+ ecc_en = umc_en_mask == ecc_en_mask;
+
+ /* Assume UMC MCA banks are enabled. */
+ nb_mce_en = true;
+ } else {
+ amd64_read_pci_cfg(F3, NBCFG, &value);
+
+ ecc_en = !!(value & NBCFG_ECC_ENABLE);
+
+ nb_mce_en = nb_mce_bank_enabled_on_node(nid);
+ if (!nb_mce_en)
+ amd64_notice("NB MCE bank disabled, set MSR 0x%08x[4] on node %d to enable.\n",
+ MSR_IA32_MCG_CTL, nid);
+ }
+
+ amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
if (!ecc_en || !nb_mce_en) {
amd64_notice("%s", ecc_msg);
@@ -2685,6 +3088,27 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
return true;
}
+static inline void
+f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
+{
+ u8 i, ecc_en = 1, cpk_en = 1;
+
+ for (i = 0; i < NUM_UMCS; i++) {
+ if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {
+ ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED);
+ cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP);
+ }
+ }
+
+ /* Set chipkill only if ECC is enabled: */
+ if (ecc_en) {
+ mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+
+ if (cpk_en)
+ mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+ }
+}
+
static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
struct amd64_family_type *fam)
{
@@ -2693,17 +3117,21 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
mci->edac_ctl_cap = EDAC_FLAG_NONE;
- if (pvt->nbcap & NBCAP_SECDED)
- mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+ if (pvt->umc) {
+ f17h_determine_edac_ctl_cap(mci, pvt);
+ } else {
+ if (pvt->nbcap & NBCAP_SECDED)
+ mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
- if (pvt->nbcap & NBCAP_CHIPKILL)
- mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+ if (pvt->nbcap & NBCAP_CHIPKILL)
+ mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+ }
mci->edac_cap = determine_edac_cap(pvt);
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = EDAC_AMD64_VERSION;
mci->ctl_name = fam->ctl_name;
- mci->dev_name = pci_name(pvt->F2);
+ mci->dev_name = pci_name(pvt->F3);
mci->ctl_page_to_phys = NULL;
/* memory scrubber interface */
@@ -2759,6 +3187,11 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
pvt->ops = &family_types[F16_CPUS].ops;
break;
+ case 0x17:
+ fam_type = &family_types[F17_CPUS];
+ pvt->ops = &family_types[F17_CPUS].ops;
+ break;
+
default:
amd64_err("Unsupported family!\n");
return NULL;
@@ -2789,6 +3222,7 @@ static int init_one_instance(unsigned int nid)
struct mem_ctl_info *mci = NULL;
struct edac_mc_layer layers[2];
struct amd64_pvt *pvt = NULL;
+ u16 pci_id1, pci_id2;
int err = 0, ret;
ret = -ENOMEM;
@@ -2804,10 +3238,23 @@ static int init_one_instance(unsigned int nid)
if (!fam_type)
goto err_free;
- ret = -ENODEV;
- err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f2_id);
+ if (pvt->fam >= 0x17) {
+ pvt->umc = kcalloc(NUM_UMCS, sizeof(struct amd64_umc), GFP_KERNEL);
+ if (!pvt->umc) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ pci_id1 = fam_type->f0_id;
+ pci_id2 = fam_type->f6_id;
+ } else {
+ pci_id1 = fam_type->f1_id;
+ pci_id2 = fam_type->f2_id;
+ }
+
+ err = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2);
if (err)
- goto err_free;
+ goto err_post_init;
read_mc_regs(pvt);
@@ -2857,7 +3304,10 @@ static int init_one_instance(unsigned int nid)
if (report_gart_errors)
amd_report_gart_errors(true);
- amd_register_ecc_decoder(decode_bus_error);
+ if (pvt->umc)
+ amd_register_ecc_decoder(decode_umc_error);
+ else
+ amd_register_ecc_decoder(decode_bus_error);
return 0;
@@ -2867,6 +3317,10 @@ err_add_mc:
err_siblings:
free_mc_sibling_devs(pvt);
+err_post_init:
+ if (pvt->fam >= 0x17)
+ kfree(pvt->umc);
+
err_free:
kfree(pvt);
@@ -2893,7 +3347,11 @@ static int probe_one_instance(unsigned int nid)
if (!ecc_enable_override)
goto err_enable;
- amd64_warn("Forcing ECC on!\n");
+ if (boot_cpu_data.x86 >= 0x17) {
+ amd64_warn("Forcing ECC on is not recommended on newer systems. Please enable ECC in BIOS.");
+ goto err_enable;
+ } else
+ amd64_warn("Forcing ECC on!\n");
if (!enable_ecc_error_reporting(s, nid, F3))
goto err_enable;
@@ -2902,7 +3360,9 @@ static int probe_one_instance(unsigned int nid)
ret = init_one_instance(nid);
if (ret < 0) {
amd64_err("Error probing instance: %d\n", nid);
- restore_ecc_error_reporting(s, nid, F3);
+
+ if (boot_cpu_data.x86 < 0x17)
+ restore_ecc_error_reporting(s, nid, F3);
}
return ret;
@@ -2938,7 +3398,11 @@ static void remove_one_instance(unsigned int nid)
/* unregister from EDAC MCE */
amd_report_gart_errors(false);
- amd_unregister_ecc_decoder(decode_bus_error);
+
+ if (pvt->umc)
+ amd_unregister_ecc_decoder(decode_umc_error);
+ else
+ amd_unregister_ecc_decoder(decode_bus_error);
kfree(ecc_stngs[nid]);
ecc_stngs[nid] = NULL;
@@ -2963,7 +3427,10 @@ static void setup_pci_device(void)
return;
pvt = mci->pvt_info;
- pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
+ if (pvt->umc)
+ pci_ctl = edac_pci_create_generic_ctl(&pvt->F0->dev, EDAC_MOD_STR);
+ else
+ pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
if (!pci_ctl) {
pr_warn("%s(): Unable to create PCI control\n", __func__);
pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
@@ -2975,6 +3442,7 @@ static const struct x86_cpu_id amd64_cpuids[] = {
{ X86_VENDOR_AMD, 0x10, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x15, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x16, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
+ { X86_VENDOR_AMD, 0x17, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ }
};
MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids);
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index c08870479054..f14c24d5b140 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -30,10 +30,10 @@
edac_printk(KERN_NOTICE, "amd64", fmt, ##arg)
#define amd64_warn(fmt, arg...) \
- edac_printk(KERN_WARNING, "amd64", fmt, ##arg)
+ edac_printk(KERN_WARNING, "amd64", "Warning: " fmt, ##arg)
#define amd64_err(fmt, arg...) \
- edac_printk(KERN_ERR, "amd64", fmt, ##arg)
+ edac_printk(KERN_ERR, "amd64", "Error: " fmt, ##arg)
#define amd64_mc_warn(mci, fmt, arg...) \
edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg)
@@ -118,6 +118,8 @@
#define PCI_DEVICE_ID_AMD_16H_NB_F2 0x1532
#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F2 0x1582
+#define PCI_DEVICE_ID_AMD_17H_DF_F0 0x1460
+#define PCI_DEVICE_ID_AMD_17H_DF_F6 0x1466
/*
* Function 1 - Address Map
@@ -202,6 +204,8 @@
#define DCT_SEL_HI 0x114
#define F15H_M60H_SCRCTRL 0x1C8
+#define F17H_SCR_BASE_ADDR 0x48
+#define F17H_SCR_LIMIT_ADDR 0x4C
/*
* Function 3 - Misc Control
@@ -248,6 +252,31 @@
/* MSRs */
#define MSR_MCGCTL_NBE BIT(4)
+/* F17h */
+
+/* F0: */
+#define DF_DHAR 0x104
+
+/* UMC CH register offsets */
+#define UMCCH_BASE_ADDR 0x0
+#define UMCCH_ADDR_MASK 0x20
+#define UMCCH_ADDR_CFG 0x30
+#define UMCCH_DIMM_CFG 0x80
+#define UMCCH_UMC_CFG 0x100
+#define UMCCH_SDP_CTRL 0x104
+#define UMCCH_ECC_CTRL 0x14C
+#define UMCCH_ECC_BAD_SYMBOL 0xD90
+#define UMCCH_UMC_CAP 0xDF0
+#define UMCCH_UMC_CAP_HI 0xDF4
+
+/* UMC CH bitfields */
+#define UMC_ECC_CHIPKILL_CAP BIT(31)
+#define UMC_ECC_ENABLED BIT(30)
+
+#define UMC_SDP_INIT BIT(31)
+
+#define NUM_UMCS 2
+
enum amd_families {
K8_CPUS = 0,
F10_CPUS,
@@ -256,6 +285,7 @@ enum amd_families {
F15_M60H_CPUS,
F16_CPUS,
F16_M30H_CPUS,
+ F17_CPUS,
NUM_FAMILIES,
};
@@ -288,11 +318,19 @@ struct chip_select {
u8 m_cnt;
};
+struct amd64_umc {
+ u32 dimm_cfg; /* DIMM Configuration reg */
+ u32 umc_cfg; /* Configuration reg */
+ u32 sdp_ctrl; /* SDP Control reg */
+ u32 ecc_ctrl; /* DRAM ECC Control reg */
+ u32 umc_cap_hi; /* Capabilities High reg */
+};
+
struct amd64_pvt {
struct low_ops *ops;
/* pci_device handles which we utilize */
- struct pci_dev *F1, *F2, *F3;
+ struct pci_dev *F0, *F1, *F2, *F3, *F6;
u16 mc_node_id; /* MC index of this MC node */
u8 fam; /* CPU family */
@@ -335,6 +373,8 @@ struct amd64_pvt {
/* cache the dram_type */
enum mem_type dram_type;
+
+ struct amd64_umc *umc; /* UMC registers */
};
enum err_codes {
@@ -342,6 +382,8 @@ enum err_codes {
ERR_NODE = -1,
ERR_CSROW = -2,
ERR_CHANNEL = -3,
+ ERR_SYND = -4,
+ ERR_NORM_ADDR = -5,
};
struct err_info {
@@ -354,6 +396,12 @@ struct err_info {
u32 offset;
};
+static inline u32 get_umc_base(u8 channel)
+{
+ /* ch0: 0x50000, ch1: 0x150000 */
+ return 0x50000 + (!!channel << 20);
+}
+
static inline u64 get_dram_base(struct amd64_pvt *pvt, u8 i)
{
u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
@@ -422,7 +470,7 @@ struct low_ops {
struct amd64_family_type {
const char *ctl_name;
- u16 f1_id, f2_id;
+ u16 f0_id, f1_id, f2_id, f6_id;
struct low_ops ops;
};
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index c3ee3ad98a63..d2ea9c4f1824 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -482,15 +482,8 @@ void edac_mc_free(struct mem_ctl_info *mci)
}
EXPORT_SYMBOL_GPL(edac_mc_free);
-
-/**
- * find_mci_by_dev
- *
- * scan list of controllers looking for the one that manages
- * the 'dev' device
- * @dev: pointer to a struct device related with the MCI
- */
-struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+/* Caller must hold mem_ctls_mutex */
+static struct mem_ctl_info *__find_mci_by_dev(struct device *dev)
{
struct mem_ctl_info *mci;
struct list_head *item;
@@ -506,6 +499,24 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev)
return NULL;
}
+
+/**
+ * find_mci_by_dev
+ *
+ * scan list of controllers looking for the one that manages
+ * the 'dev' device
+ * @dev: pointer to a struct device related with the MCI
+ */
+struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+{
+ struct mem_ctl_info *ret;
+
+ mutex_lock(&mem_ctls_mutex);
+ ret = __find_mci_by_dev(dev);
+ mutex_unlock(&mem_ctls_mutex);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(find_mci_by_dev);
/*
@@ -588,7 +599,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci)
insert_before = &mc_devices;
- p = find_mci_by_dev(mci->pdev);
+ p = __find_mci_by_dev(mci->pdev);
if (unlikely(p != NULL))
goto fail0;
@@ -640,26 +651,28 @@ static int del_mc_from_global_list(struct mem_ctl_info *mci)
*
* If found, return a pointer to the structure.
* Else return NULL.
- *
- * Caller must hold mem_ctls_mutex.
*/
struct mem_ctl_info *edac_mc_find(int idx)
{
+ struct mem_ctl_info *mci = NULL;
struct list_head *item;
- struct mem_ctl_info *mci;
+
+ mutex_lock(&mem_ctls_mutex);
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
if (mci->mc_idx >= idx) {
- if (mci->mc_idx == idx)
- return mci;
-
+ if (mci->mc_idx == idx) {
+ goto unlock;
+ }
break;
}
}
- return NULL;
+unlock:
+ mutex_unlock(&mem_ctls_mutex);
+ return mci;
}
EXPORT_SYMBOL(edac_mc_find);
@@ -779,7 +792,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
mutex_lock(&mem_ctls_mutex);
/* find the requested mci struct in the global list */
- mci = find_mci_by_dev(dev);
+ mci = __find_mci_by_dev(dev);
if (mci == NULL) {
mutex_unlock(&mem_ctls_mutex);
return NULL;
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index daaac2c79ca7..34208f38c5b1 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -8,7 +8,7 @@ static struct amd_decoder_ops *fam_ops;
static u8 xec_mask = 0xf;
static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m);
+static void (*decode_dram_ecc)(int node_id, struct mce *m);
void amd_report_gart_errors(bool v)
{
@@ -18,16 +18,16 @@ EXPORT_SYMBOL_GPL(amd_report_gart_errors);
void amd_register_ecc_decoder(void (*f)(int, struct mce *))
{
- nb_bus_decoder = f;
+ decode_dram_ecc = f;
}
EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
{
- if (nb_bus_decoder) {
- WARN_ON(nb_bus_decoder != f);
+ if (decode_dram_ecc) {
+ WARN_ON(decode_dram_ecc != f);
- nb_bus_decoder = NULL;
+ decode_dram_ecc = NULL;
}
}
EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
@@ -763,8 +763,8 @@ static void decode_mc4_mce(struct mce *m)
pr_cont("%s.\n", mc4_mce_desc[xec]);
- if (nb_bus_decoder)
- nb_bus_decoder(node_id, m);
+ if (decode_dram_ecc)
+ decode_dram_ecc(node_id, m);
return;
}
break;
@@ -851,7 +851,7 @@ static void decode_mc6_mce(struct mce *m)
/* Decode errors according to Scalable MCA specification */
static void decode_smca_errors(struct mce *m)
{
- struct smca_hwid_mcatype *type;
+ struct smca_hwid *hwid;
unsigned int bank_type;
const char *ip_name;
u8 xec = XEC(m->status, xec_mask);
@@ -862,21 +862,28 @@ static void decode_smca_errors(struct mce *m)
if (boot_cpu_data.x86 >= 0x17 && m->bank == 4)
pr_emerg(HW_ERR "Bank 4 is reserved on Fam17h.\n");
- type = smca_banks[m->bank].type;
- if (!type)
+ hwid = smca_banks[m->bank].hwid;
+ if (!hwid)
return;
- bank_type = type->bank_type;
- ip_name = smca_bank_names[bank_type].long_name;
+ bank_type = hwid->bank_type;
+ ip_name = smca_get_long_name(bank_type);
pr_emerg(HW_ERR "%s Extended Error Code: %d\n", ip_name, xec);
/* Only print the decode of valid error codes */
if (xec < smca_mce_descs[bank_type].num_descs &&
- (type->xec_bitmap & BIT_ULL(xec))) {
+ (hwid->xec_bitmap & BIT_ULL(xec))) {
pr_emerg(HW_ERR "%s Error: ", ip_name);
pr_cont("%s.\n", smca_mce_descs[bank_type].descs[xec]);
}
+
+ /*
+ * amd_get_nb_id() returns the last level cache id.
+ * The last level cache on Fam17h is 1 level below the node.
+ */
+ if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
+ decode_dram_ecc(amd_get_nb_id(m->extcpu) >> 1, m);
}
static inline void amd_decode_err_code(u16 ec)
@@ -957,10 +964,13 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
- if (c->x86 >= 0x15)
- pr_cont("|%s|%s",
- ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
- ((m->status & MCI_STATUS_POISON) ? "Poison" : "-"));
+ if (c->x86 >= 0x15) {
+ pr_cont("|%s", (m->status & MCI_STATUS_DEFERRED ? "Deferred" : "-"));
+
+ /* F15h, bank4, bit 43 is part of McaStatSubCache. */
+ if (c->x86 != 0x15 || m->bank != 4)
+ pr_cont("|%s", (m->status & MCI_STATUS_POISON ? "Poison" : "-"));
+ }
if (boot_cpu_has(X86_FEATURE_SMCA)) {
u32 low, high;
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index ff0567526ee3..c62602141f95 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -300,6 +300,22 @@ err:
return res;
}
+static int mpc85xx_pci_err_remove(struct platform_device *op)
+{
+ struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
+ struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+
+ edac_dbg(0, "\n");
+
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, orig_pci_err_cap_dr);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
+
+ edac_pci_del_device(&op->dev);
+ edac_pci_free_ctl_info(pci);
+
+ return 0;
+}
+
static const struct platform_device_id mpc85xx_pci_err_match[] = {
{
.name = "mpc85xx-pci-edac"
@@ -309,6 +325,7 @@ static const struct platform_device_id mpc85xx_pci_err_match[] = {
static struct platform_driver mpc85xx_pci_err_driver = {
.probe = mpc85xx_pci_err_probe,
+ .remove = mpc85xx_pci_err_remove,
.id_table = mpc85xx_pci_err_match,
.driver = {
.name = "mpc85xx_pci_err",
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 54775221a01f..c1ad0eb7d5dd 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -23,6 +23,7 @@
#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/mce.h>
@@ -3365,12 +3366,13 @@ fail0:
{ X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
static const struct x86_cpu_id sbridge_cpuids[] = {
- ICPU(0x2d, pci_dev_descr_sbridge_table), /* SANDY_BRIDGE */
- ICPU(0x3e, pci_dev_descr_ibridge_table), /* IVY_BRIDGE */
- ICPU(0x3f, pci_dev_descr_haswell_table), /* HASWELL */
- ICPU(0x4f, pci_dev_descr_broadwell_table), /* BROADWELL */
- ICPU(0x56, pci_dev_descr_broadwell_table), /* BROADWELL-DE */
- ICPU(0x57, pci_dev_descr_knl_table), /* KNIGHTS_LANDING */
+ ICPU(INTEL_FAM6_SANDYBRIDGE_X, pci_dev_descr_sbridge_table),
+ ICPU(INTEL_FAM6_IVYBRIDGE_X, pci_dev_descr_ibridge_table),
+ ICPU(INTEL_FAM6_HASWELL_X, pci_dev_descr_haswell_table),
+ ICPU(INTEL_FAM6_BROADWELL_X, pci_dev_descr_broadwell_table),
+ ICPU(INTEL_FAM6_BROADWELL_XEON_D, pci_dev_descr_broadwell_table),
+ ICPU(INTEL_FAM6_XEON_PHI_KNL, pci_dev_descr_knl_table),
+ ICPU(INTEL_FAM6_XEON_PHI_KNM, pci_dev_descr_knl_table),
{ }
};
MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c
index 0ff4878c2aa1..9edcb29b3001 100644
--- a/drivers/edac/skx_edac.c
+++ b/drivers/edac/skx_edac.c
@@ -25,6 +25,7 @@
#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/mce.h>
@@ -262,8 +263,8 @@ fail:
return -ENODEV;
}
-const struct x86_cpu_id skx_cpuids[] = {
- { X86_VENDOR_INTEL, 6, 0x55, 0, 0 }, /* Skylake */
+static const struct x86_cpu_id skx_cpuids[] = {
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X, 0, 0 },
{ }
};
MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
@@ -1036,7 +1037,7 @@ static void skx_remove(void)
* search for all the devices we need
* check which DIMMs are present.
*/
-int __init skx_init(void)
+static int __init skx_init(void)
{
const struct x86_cpu_id *id;
const struct munit *m;
diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c
index bf19b6e3bd12..5569391ea800 100644
--- a/drivers/edac/xgene_edac.c
+++ b/drivers/edac/xgene_edac.c
@@ -1602,16 +1602,16 @@ static void xgene_edac_pa_report(struct edac_device_ctl_info *edac_dev)
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");
+ "Multiple 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");
+ "Multiple 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");
+ dev_err(edac_dev->dev, "Multiple 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)
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 15475892af0c..5d3640264f2d 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1368,15 +1368,6 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
return NETDEV_TX_OK;
}
-static int fwnet_change_mtu(struct net_device *net, int new_mtu)
-{
- if (new_mtu < 68)
- return -EINVAL;
-
- net->mtu = new_mtu;
- return 0;
-}
-
static const struct ethtool_ops fwnet_ethtool_ops = {
.get_link = ethtool_op_get_link,
};
@@ -1385,7 +1376,6 @@ static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
.ndo_start_xmit = fwnet_tx,
- .ndo_change_mtu = fwnet_change_mtu,
};
static void fwnet_init_dev(struct net_device *net)
@@ -1454,7 +1444,6 @@ static int fwnet_probe(struct fw_unit *unit,
struct net_device *net;
bool allocated_netdev = false;
struct fwnet_device *dev;
- unsigned max_mtu;
int ret;
union fwnet_hwaddr *ha;
@@ -1493,13 +1482,9 @@ static int fwnet_probe(struct fw_unit *unit,
goto out;
dev->local_fifo = dev->handler.offset;
- /*
- * Use the RFC 2734 default 1500 octets or the maximum payload
- * as initial MTU
- */
- max_mtu = (1 << (card->max_receive + 1))
- - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE;
- net->mtu = min(1500U, max_mtu);
+ net->mtu = 1500U;
+ net->min_mtu = ETH_MIN_MTU;
+ net->max_mtu = 0xfff;
/* Set our hardware address while we're at it */
ha = (union fwnet_hwaddr *)net->dev_addr;
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index c981be17d3c0..2e78b0b96d74 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -129,7 +129,25 @@ config EFI_TEST
Say Y here to enable the runtime services support via /dev/efi_test.
If unsure, say N.
+config APPLE_PROPERTIES
+ bool "Apple Device Properties"
+ depends on EFI_STUB && X86
+ select EFI_DEV_PATH_PARSER
+ select UCS2_STRING
+ help
+ Retrieve properties from EFI on Apple Macs and assign them to
+ devices, allowing for improved support of Apple hardware.
+ Properties that would otherwise be missing include the
+ Thunderbolt Device ROM and GPU configuration data.
+
+ If unsure, say Y if you have a Mac. Otherwise N.
+
endmenu
config UEFI_CPER
bool
+
+config EFI_DEV_PATH_PARSER
+ bool
+ depends on ACPI
+ default n
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index c8a439f6d715..ad67342313ed 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -21,6 +21,8 @@ obj-$(CONFIG_EFI_STUB) += libstub/
obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
obj-$(CONFIG_EFI_TEST) += test/
+obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
+obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
obj-$(CONFIG_ARM) += $(arm-obj-y)
diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c
new file mode 100644
index 000000000000..c473f4c5ca34
--- /dev/null
+++ b/drivers/firmware/efi/apple-properties.c
@@ -0,0 +1,248 @@
+/*
+ * apple-properties.c - EFI device properties on Macs
+ * Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "apple-properties: " fmt
+
+#include <linux/bootmem.h>
+#include <linux/dmi.h>
+#include <linux/efi.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/ucs2_string.h>
+#include <asm/setup.h>
+
+static bool dump_properties __initdata;
+
+static int __init dump_properties_enable(char *arg)
+{
+ dump_properties = true;
+ return 0;
+}
+
+__setup("dump_apple_properties", dump_properties_enable);
+
+struct dev_header {
+ u32 len;
+ u32 prop_count;
+ struct efi_dev_path path[0];
+ /*
+ * followed by key/value pairs, each key and value preceded by u32 len,
+ * len includes itself, value may be empty (in which case its len is 4)
+ */
+};
+
+struct properties_header {
+ u32 len;
+ u32 version;
+ u32 dev_count;
+ struct dev_header dev_header[0];
+};
+
+static u8 one __initdata = 1;
+
+static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
+ struct device *dev, void *ptr,
+ struct property_entry entry[])
+{
+ int i;
+
+ for (i = 0; i < dev_header->prop_count; i++) {
+ int remaining = dev_header->len - (ptr - (void *)dev_header);
+ u32 key_len, val_len;
+ char *key;
+
+ if (sizeof(key_len) > remaining)
+ break;
+
+ key_len = *(typeof(key_len) *)ptr;
+ if (key_len + sizeof(val_len) > remaining ||
+ key_len < sizeof(key_len) + sizeof(efi_char16_t) ||
+ *(efi_char16_t *)(ptr + sizeof(key_len)) == 0) {
+ dev_err(dev, "invalid property name len at %#zx\n",
+ ptr - (void *)dev_header);
+ break;
+ }
+
+ val_len = *(typeof(val_len) *)(ptr + key_len);
+ if (key_len + val_len > remaining ||
+ val_len < sizeof(val_len)) {
+ dev_err(dev, "invalid property val len at %#zx\n",
+ ptr - (void *)dev_header + key_len);
+ break;
+ }
+
+ /* 4 bytes to accommodate UTF-8 code points + null byte */
+ key = kzalloc((key_len - sizeof(key_len)) * 4 + 1, GFP_KERNEL);
+ if (!key) {
+ dev_err(dev, "cannot allocate property name\n");
+ break;
+ }
+ ucs2_as_utf8(key, ptr + sizeof(key_len),
+ key_len - sizeof(key_len));
+
+ entry[i].name = key;
+ entry[i].is_array = true;
+ entry[i].length = val_len - sizeof(val_len);
+ entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len);
+ if (!entry[i].length) {
+ /* driver core doesn't accept empty properties */
+ entry[i].length = 1;
+ entry[i].pointer.raw_data = &one;
+ }
+
+ if (dump_properties) {
+ dev_info(dev, "property: %s\n", entry[i].name);
+ print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET,
+ 16, 1, entry[i].pointer.raw_data,
+ entry[i].length, true);
+ }
+
+ ptr += key_len + val_len;
+ }
+
+ if (i != dev_header->prop_count) {
+ dev_err(dev, "got %d device properties, expected %u\n", i,
+ dev_header->prop_count);
+ print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+ 16, 1, dev_header, dev_header->len, true);
+ return;
+ }
+
+ dev_info(dev, "assigning %d device properties\n", i);
+}
+
+static int __init unmarshal_devices(struct properties_header *properties)
+{
+ size_t offset = offsetof(struct properties_header, dev_header[0]);
+
+ while (offset + sizeof(struct dev_header) < properties->len) {
+ struct dev_header *dev_header = (void *)properties + offset;
+ struct property_entry *entry = NULL;
+ struct device *dev;
+ size_t len;
+ int ret, i;
+ void *ptr;
+
+ if (offset + dev_header->len > properties->len ||
+ dev_header->len <= sizeof(*dev_header)) {
+ pr_err("invalid len in dev_header at %#zx\n", offset);
+ return -EINVAL;
+ }
+
+ ptr = dev_header->path;
+ len = dev_header->len - sizeof(*dev_header);
+
+ dev = efi_get_device_by_path((struct efi_dev_path **)&ptr, &len);
+ if (IS_ERR(dev)) {
+ pr_err("device path parse error %ld at %#zx:\n",
+ PTR_ERR(dev), ptr - (void *)dev_header);
+ print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+ 16, 1, dev_header, dev_header->len, true);
+ dev = NULL;
+ goto skip_device;
+ }
+
+ entry = kcalloc(dev_header->prop_count + 1, sizeof(*entry),
+ GFP_KERNEL);
+ if (!entry) {
+ dev_err(dev, "cannot allocate properties\n");
+ goto skip_device;
+ }
+
+ unmarshal_key_value_pairs(dev_header, dev, ptr, entry);
+ if (!entry[0].name)
+ goto skip_device;
+
+ ret = device_add_properties(dev, entry); /* makes deep copy */
+ if (ret)
+ dev_err(dev, "error %d assigning properties\n", ret);
+
+ for (i = 0; entry[i].name; i++)
+ kfree(entry[i].name);
+
+skip_device:
+ kfree(entry);
+ put_device(dev);
+ offset += dev_header->len;
+ }
+
+ return 0;
+}
+
+static int __init map_properties(void)
+{
+ struct properties_header *properties;
+ struct setup_data *data;
+ u32 data_len;
+ u64 pa_data;
+ int ret;
+
+ if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.") &&
+ !dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc."))
+ return 0;
+
+ pa_data = boot_params.hdr.setup_data;
+ while (pa_data) {
+ data = ioremap(pa_data, sizeof(*data));
+ if (!data) {
+ pr_err("cannot map setup_data header\n");
+ return -ENOMEM;
+ }
+
+ if (data->type != SETUP_APPLE_PROPERTIES) {
+ pa_data = data->next;
+ iounmap(data);
+ continue;
+ }
+
+ data_len = data->len;
+ iounmap(data);
+
+ data = ioremap(pa_data, sizeof(*data) + data_len);
+ if (!data) {
+ pr_err("cannot map setup_data payload\n");
+ return -ENOMEM;
+ }
+
+ properties = (struct properties_header *)data->data;
+ if (properties->version != 1) {
+ pr_err("unsupported version:\n");
+ print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+ 16, 1, properties, data_len, true);
+ ret = -ENOTSUPP;
+ } else if (properties->len != data_len) {
+ pr_err("length mismatch, expected %u\n", data_len);
+ print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+ 16, 1, properties, data_len, true);
+ ret = -EINVAL;
+ } else
+ ret = unmarshal_devices(properties);
+
+ /*
+ * Can only free the setup_data payload but not its header
+ * to avoid breaking the chain of ->next pointers.
+ */
+ data->len = 0;
+ iounmap(data);
+ free_bootmem_late(pa_data + sizeof(*data), data_len);
+
+ return ret;
+ }
+ return 0;
+}
+
+fs_initcall(map_properties);
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 8efe13075c92..f853ad2c4ca0 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -244,8 +244,10 @@ void __init efi_init(void)
"Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
efi.memmap.desc_version);
- if (uefi_init() < 0)
+ if (uefi_init() < 0) {
+ efi_memmap_unmap();
return;
+ }
reserve_regions();
efi_memattr_init();
diff --git a/drivers/firmware/efi/dev-path-parser.c b/drivers/firmware/efi/dev-path-parser.c
new file mode 100644
index 000000000000..85d1834ee9b7
--- /dev/null
+++ b/drivers/firmware/efi/dev-path-parser.c
@@ -0,0 +1,203 @@
+/*
+ * dev-path-parser.c - EFI Device Path parser
+ * Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/efi.h>
+#include <linux/pci.h>
+
+struct acpi_hid_uid {
+ struct acpi_device_id hid[2];
+ char uid[11]; /* UINT_MAX + null byte */
+};
+
+static int __init match_acpi_dev(struct device *dev, void *data)
+{
+ struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
+ struct acpi_device *adev = to_acpi_device(dev);
+
+ if (acpi_match_device_ids(adev, hid_uid.hid))
+ return 0;
+
+ if (adev->pnp.unique_id)
+ return !strcmp(adev->pnp.unique_id, hid_uid.uid);
+ else
+ return !strcmp("0", hid_uid.uid);
+}
+
+static long __init parse_acpi_path(struct efi_dev_path *node,
+ struct device *parent, struct device **child)
+{
+ struct acpi_hid_uid hid_uid = {};
+ struct device *phys_dev;
+
+ if (node->length != 12)
+ return -EINVAL;
+
+ sprintf(hid_uid.hid[0].id, "%c%c%c%04X",
+ 'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
+ 'A' + ((node->acpi.hid >> 5) & 0x1f) - 1,
+ 'A' + ((node->acpi.hid >> 0) & 0x1f) - 1,
+ node->acpi.hid >> 16);
+ sprintf(hid_uid.uid, "%u", node->acpi.uid);
+
+ *child = bus_find_device(&acpi_bus_type, NULL, &hid_uid,
+ match_acpi_dev);
+ if (!*child)
+ return -ENODEV;
+
+ phys_dev = acpi_get_first_physical_node(to_acpi_device(*child));
+ if (phys_dev) {
+ get_device(phys_dev);
+ put_device(*child);
+ *child = phys_dev;
+ }
+
+ return 0;
+}
+
+static int __init match_pci_dev(struct device *dev, void *data)
+{
+ unsigned int devfn = *(unsigned int *)data;
+
+ return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
+}
+
+static long __init parse_pci_path(struct efi_dev_path *node,
+ struct device *parent, struct device **child)
+{
+ unsigned int devfn;
+
+ if (node->length != 6)
+ return -EINVAL;
+ if (!parent)
+ return -EINVAL;
+
+ devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
+
+ *child = device_find_child(parent, &devfn, match_pci_dev);
+ if (!*child)
+ return -ENODEV;
+
+ return 0;
+}
+
+/*
+ * Insert parsers for further node types here.
+ *
+ * Each parser takes a pointer to the @node and to the @parent (will be NULL
+ * for the first device path node). If a device corresponding to @node was
+ * found below @parent, its reference count should be incremented and the
+ * device returned in @child.
+ *
+ * The return value should be 0 on success or a negative int on failure.
+ * The special return values 0x01 (EFI_DEV_END_INSTANCE) and 0xFF
+ * (EFI_DEV_END_ENTIRE) signal the end of the device path, only
+ * parse_end_path() is supposed to return this.
+ *
+ * Be sure to validate the node length and contents before commencing the
+ * search for a device.
+ */
+
+static long __init parse_end_path(struct efi_dev_path *node,
+ struct device *parent, struct device **child)
+{
+ if (node->length != 4)
+ return -EINVAL;
+ if (node->sub_type != EFI_DEV_END_INSTANCE &&
+ node->sub_type != EFI_DEV_END_ENTIRE)
+ return -EINVAL;
+ if (!parent)
+ return -ENODEV;
+
+ *child = get_device(parent);
+ return node->sub_type;
+}
+
+/**
+ * efi_get_device_by_path - find device by EFI Device Path
+ * @node: EFI Device Path
+ * @len: maximum length of EFI Device Path in bytes
+ *
+ * Parse a series of EFI Device Path nodes at @node and find the corresponding
+ * device. If the device was found, its reference count is incremented and a
+ * pointer to it is returned. The caller needs to drop the reference with
+ * put_device() after use. The @node pointer is updated to point to the
+ * location immediately after the "End of Hardware Device Path" node.
+ *
+ * If another Device Path instance follows, @len is decremented by the number
+ * of bytes consumed. Otherwise @len is set to %0.
+ *
+ * If a Device Path node is malformed or its corresponding device is not found,
+ * @node is updated to point to this offending node and an ERR_PTR is returned.
+ *
+ * If @len is initially %0, the function returns %NULL. Thus, to iterate over
+ * all instances in a path, the following idiom may be used:
+ *
+ * while (!IS_ERR_OR_NULL(dev = efi_get_device_by_path(&node, &len))) {
+ * // do something with dev
+ * put_device(dev);
+ * }
+ * if (IS_ERR(dev))
+ * // report error
+ *
+ * Devices can only be found if they're already instantiated. Most buses
+ * instantiate devices in the "subsys" initcall level, hence the earliest
+ * initcall level in which this function should be called is "fs".
+ *
+ * Returns the device on success or
+ * %ERR_PTR(-ENODEV) if no device was found,
+ * %ERR_PTR(-EINVAL) if a node is malformed or exceeds @len,
+ * %ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented.
+ */
+struct device * __init efi_get_device_by_path(struct efi_dev_path **node,
+ size_t *len)
+{
+ struct device *parent = NULL, *child;
+ long ret = 0;
+
+ if (!*len)
+ return NULL;
+
+ while (!ret) {
+ if (*len < 4 || *len < (*node)->length)
+ ret = -EINVAL;
+ else if ((*node)->type == EFI_DEV_ACPI &&
+ (*node)->sub_type == EFI_DEV_BASIC_ACPI)
+ ret = parse_acpi_path(*node, parent, &child);
+ else if ((*node)->type == EFI_DEV_HW &&
+ (*node)->sub_type == EFI_DEV_PCI)
+ ret = parse_pci_path(*node, parent, &child);
+ else if (((*node)->type == EFI_DEV_END_PATH ||
+ (*node)->type == EFI_DEV_END_PATH2))
+ ret = parse_end_path(*node, parent, &child);
+ else
+ ret = -ENOTSUPP;
+
+ put_device(parent);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ parent = child;
+ *node = (void *)*node + (*node)->length;
+ *len -= (*node)->length;
+ }
+
+ if (ret == EFI_DEV_END_ENTIRE)
+ *len = 0;
+
+ return child;
+}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1ac199cd75e7..92914801e388 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,7 +23,10 @@
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/io.h>
+#include <linux/kexec.h>
#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/ucs2_string.h>
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
.esrt = EFI_INVALID_TABLE_ADDR,
.properties_table = EFI_INVALID_TABLE_ADDR,
.mem_attr_table = EFI_INVALID_TABLE_ADDR,
+ .rng_seed = EFI_INVALID_TABLE_ADDR,
};
EXPORT_SYMBOL(efi);
@@ -259,8 +263,10 @@ static __init int efivar_ssdt_load(void)
}
data = kmalloc(size, GFP_KERNEL);
- if (!data)
+ if (!data) {
+ ret = -ENOMEM;
goto free_entry;
+ }
ret = efivar_entry_get(entry, NULL, &size, data);
if (ret) {
@@ -438,6 +444,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
+ {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
{NULL_GUID, NULL, NULL},
};
@@ -499,6 +506,29 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
pr_cont("\n");
set_bit(EFI_CONFIG_TABLES, &efi.flags);
+ if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
+ struct linux_efi_random_seed *seed;
+ u32 size = 0;
+
+ seed = early_memremap(efi.rng_seed, sizeof(*seed));
+ if (seed != NULL) {
+ size = seed->size;
+ early_memunmap(seed, sizeof(*seed));
+ } else {
+ pr_err("Could not map UEFI random seed!\n");
+ }
+ if (size > 0) {
+ seed = early_memremap(efi.rng_seed,
+ sizeof(*seed) + size);
+ if (seed != NULL) {
+ add_device_randomness(seed->bits, seed->size);
+ early_memunmap(seed, sizeof(*seed) + size);
+ } else {
+ pr_err("Could not map UEFI random seed!\n");
+ }
+ }
+ }
+
/* Parse the EFI Properties table if it exists */
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
efi_properties_table_t *tbl;
@@ -822,3 +852,47 @@ int efi_status_to_err(efi_status_t status)
return err;
}
+
+#ifdef CONFIG_KEXEC
+static int update_efi_random_seed(struct notifier_block *nb,
+ unsigned long code, void *unused)
+{
+ struct linux_efi_random_seed *seed;
+ u32 size = 0;
+
+ if (!kexec_in_progress)
+ return NOTIFY_DONE;
+
+ seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+ if (seed != NULL) {
+ size = min(seed->size, 32U);
+ memunmap(seed);
+ } else {
+ pr_err("Could not map UEFI random seed!\n");
+ }
+ if (size > 0) {
+ seed = memremap(efi.rng_seed, sizeof(*seed) + size,
+ MEMREMAP_WB);
+ if (seed != NULL) {
+ seed->size = size;
+ get_random_bytes(seed->bits, seed->size);
+ memunmap(seed);
+ } else {
+ pr_err("Could not map UEFI random seed!\n");
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block efi_random_seed_nb = {
+ .notifier_call = update_efi_random_seed,
+};
+
+static int register_update_efi_random_seed(void)
+{
+ if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
+ return 0;
+ return register_reboot_notifier(&efi_random_seed_nb);
+}
+late_initcall(register_update_efi_random_seed);
+#endif
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d305e7..6621b13c370f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ 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 \
+lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \
$(patsubst %.c,lib-%.o,$(arm-deps))
lib-$(CONFIG_ARM) += arm32-stub.o
-lib-$(CONFIG_ARM64) += arm64-stub.o random.o
+lib-$(CONFIG_ARM64) += arm64-stub.o
CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
#
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56755f6..b4f7d78f9e8b 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
if (status != EFI_SUCCESS)
pr_efi_err(sys_table, "Failed initrd from command line!\n");
+ efi_random_get_seed(sys_table);
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index aded10662020..757badc1debb 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
-#endif
-
#define EFI_MMAP_NR_SLACK_SLOTS 8
struct file_info {
@@ -186,14 +177,16 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
goto fail;
/*
- * Enforce minimum alignment that EFI requires when requesting
- * a specific address. We are doing page-based allocations,
- * so we must be aligned to a page.
+ * Enforce minimum alignment that EFI or Linux requires when
+ * requesting a specific address. We are doing page-based (or
+ * larger) allocations, and both the address and size must meet
+ * alignment constraints.
*/
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;
- nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+ size = round_up(size, EFI_ALLOC_ALIGN);
+ nr_pages = size / EFI_PAGE_SIZE;
again:
for (i = 0; i < map_size / desc_size; i++) {
efi_memory_desc_t *desc;
@@ -208,7 +201,7 @@ again:
continue;
start = desc->phys_addr;
- end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+ end = start + desc->num_pages * EFI_PAGE_SIZE;
if (end > max)
end = max;
@@ -278,14 +271,16 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
goto fail;
/*
- * Enforce minimum alignment that EFI requires when requesting
- * a specific address. We are doing page-based allocations,
- * so we must be aligned to a page.
+ * Enforce minimum alignment that EFI or Linux requires when
+ * requesting a specific address. We are doing page-based (or
+ * larger) allocations, and both the address and size must meet
+ * alignment constraints.
*/
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;
- nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+ size = round_up(size, EFI_ALLOC_ALIGN);
+ nr_pages = size / EFI_PAGE_SIZE;
for (i = 0; i < map_size / desc_size; i++) {
efi_memory_desc_t *desc;
unsigned long m = (unsigned long)map;
@@ -300,7 +295,7 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
continue;
start = desc->phys_addr;
- end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+ end = start + desc->num_pages * EFI_PAGE_SIZE;
/*
* Don't allocate at 0x0. It will confuse code that
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index ee49cd23ee63..b98824e3800a 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
*/
#undef __init
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
+#endif
+
void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
@@ -62,4 +71,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
#endif
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 0c9f58c5ba50..7e72954d5860 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -8,6 +8,7 @@
*/
#include <linux/efi.h>
+#include <linux/log2.h>
#include <asm/efi.h>
#include "efistub.h"
@@ -41,21 +42,23 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
*/
static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
unsigned long size,
- unsigned long align)
+ unsigned long align_shift)
{
- u64 start, end;
+ unsigned long align = 1UL << align_shift;
+ u64 first_slot, last_slot, region_end;
if (md->type != EFI_CONVENTIONAL_MEMORY)
return 0;
- start = round_up(md->phys_addr, align);
- end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
- align);
+ region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1);
- if (start > end)
+ first_slot = round_up(md->phys_addr, align);
+ last_slot = round_down(region_end - size + 1, align);
+
+ if (first_slot > last_slot)
return 0;
- return (end - start + 1) / align;
+ return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1;
}
/*
@@ -98,7 +101,7 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
efi_memory_desc_t *md = (void *)memory_map + map_offset;
unsigned long slots;
- slots = get_entry_num_slots(md, size, align);
+ slots = get_entry_num_slots(md, size, ilog2(align));
MD_NUM_SLOTS(md) = slots;
total_slots += slots;
}
@@ -141,3 +144,51 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
return status;
}
+
+#define RANDOM_SEED_SIZE 32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+ efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+ efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+ efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+ struct efi_rng_protocol *rng;
+ struct linux_efi_random_seed *seed;
+ efi_status_t status;
+
+ status = efi_call_early(locate_protocol, &rng_proto, NULL,
+ (void **)&rng);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+ sizeof(*seed) + RANDOM_SEED_SIZE,
+ (void **)&seed);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+ seed->bits);
+ if (status == EFI_UNSUPPORTED)
+ /*
+ * Use whatever algorithm we have available if the raw algorithm
+ * is not implemented.
+ */
+ status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+ seed->bits);
+
+ if (status != EFI_SUCCESS)
+ goto err_freepool;
+
+ seed->size = RANDOM_SEED_SIZE;
+ status = efi_call_early(install_configuration_table, &rng_table_guid,
+ seed);
+ if (status != EFI_SUCCESS)
+ goto err_freepool;
+
+ return EFI_SUCCESS;
+
+err_freepool:
+ efi_call_early(free_pool, seed);
+ return status;
+}
diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c
index f61bb52be318..8cd578f62059 100644
--- a/drivers/firmware/efi/test/efi_test.c
+++ b/drivers/firmware/efi/test/efi_test.c
@@ -8,7 +8,6 @@
*
*/
-#include <linux/version.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -156,7 +155,7 @@ static long efi_runtime_get_variable(unsigned long arg)
{
struct efi_getvariable __user *getvariable_user;
struct efi_getvariable getvariable;
- unsigned long datasize, prev_datasize, *dz;
+ unsigned long datasize = 0, prev_datasize, *dz;
efi_guid_t vendor_guid, *vd = NULL;
efi_status_t status;
efi_char16_t *name = NULL;
@@ -266,14 +265,10 @@ static long efi_runtime_set_variable(unsigned long arg)
return rv;
}
- data = kmalloc(setvariable.data_size, GFP_KERNEL);
- if (!data) {
+ data = memdup_user(setvariable.data, setvariable.data_size);
+ if (IS_ERR(data)) {
kfree(name);
- return -ENOMEM;
- }
- if (copy_from_user(data, setvariable.data, setvariable.data_size)) {
- rv = -EFAULT;
- goto out;
+ return PTR_ERR(data);
}
status = efi.set_variable(name, &vendor_guid,
@@ -429,7 +424,7 @@ static long efi_runtime_get_nextvariablename(unsigned long arg)
efi_guid_t *vd = NULL;
efi_guid_t vendor_guid;
efi_char16_t *name = NULL;
- int rv;
+ int rv = 0;
getnextvariablename_user = (struct efi_getnextvariablename __user *)arg;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ed37e5908b91..d5d36549ecc1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -167,7 +167,7 @@ config GPIO_DWAPB
config GPIO_EM
tristate "Emma Mobile GPIO"
- depends on ARM && OF_GPIO
+ depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO
help
Say yes here to support GPIO on Renesas Emma Mobile SoCs.
@@ -451,7 +451,7 @@ config GPIO_VR41XX
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
- depends on PCI
+ depends on (X86 || COMPILE_TEST) && PCI
select MFD_CORE
select MFD_VX855
help
@@ -520,6 +520,7 @@ config GPIO_ZYNQ
config GPIO_ZX
bool "ZTE ZX GPIO support"
+ depends on ARCH_ZX || COMPILE_TEST
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO device on ZTE ZX SoCs.
@@ -603,7 +604,7 @@ config GPIO_IT87
config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
- depends on PCI
+ depends on (X86 || COMPILE_TEST) && PCI
select MFD_CORE
select LPC_SCH
help
@@ -777,16 +778,13 @@ config GPIO_PCF857X
platform-neutral GPIO calls.
config GPIO_SX150X
- bool "Semtech SX150x I2C GPIO expander"
- depends on I2C=y
- select GPIOLIB_IRQCHIP
+ bool "Semtech SX150x I2C GPIO expander (deprecated)"
+ depends on PINCTRL && I2C=y
+ select PINCTRL_SX150X
default n
help
- Say yes here to provide support for Semtech SX150-series I2C
- GPIO expanders. Compatible models include:
-
- 8 bits: sx1508q
- 16 bits: sx1509q
+ Say yes here to provide support for Semtech SX150x-series I2C
+ GPIO expanders. The GPIO driver was replaced by a Pinctrl version.
config GPIO_TPIC2810
tristate "TPIC2810 8-Bit I2C GPO expander"
@@ -798,6 +796,7 @@ config GPIO_TPIC2810
config GPIO_TS4900
tristate "Technologic Systems FPGA I2C GPIO"
+ depends on SOC_IMX6 || COMPILE_TEST
select REGMAP_I2C
help
Say yes here to enabled the GPIO driver for Technologic's FPGA core.
@@ -814,6 +813,14 @@ config GPIO_ADP5520
This option enables support for on-chip GPIO found
on Analog Devices ADP5520 PMICs.
+config GPIO_ALTERA_A10SR
+ tristate "Altera Arria10 System Resource GPIO"
+ depends on MFD_ALTERA_A10SR
+ help
+ Driver for Arria10 Development Kit GPIO expansion which
+ includes reads of pushbuttons and DIP switches as well
+ as writes to LEDs.
+
config GPIO_ARIZONA
tristate "Wolfson Microelectronics Arizona class devices"
depends on MFD_ARIZONA
@@ -822,7 +829,7 @@ config GPIO_ARIZONA
config GPIO_CRYSTAL_COVE
tristate "GPIO support for Crystal Cove PMIC"
- depends on INTEL_SOC_PMIC
+ depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
select GPIOLIB_IRQCHIP
help
Support for GPIO pins on Crystal Cove PMIC.
@@ -835,6 +842,7 @@ config GPIO_CRYSTAL_COVE
config GPIO_CS5535
tristate "AMD CS5535/CS5536 GPIO support"
+ depends on X86 || MIPS || COMPILE_TEST
depends on MFD_CS5535
help
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
@@ -927,7 +935,7 @@ config GPIO_MAX77620
config GPIO_MSIC
bool "Intel MSIC mixed signal gpio support"
- depends on MFD_INTEL_MSIC
+ depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
help
Enable support for GPIO on intel MSIC controllers found in
intel MID devices
@@ -1028,7 +1036,7 @@ config GPIO_UCB1400
config GPIO_WHISKEY_COVE
tristate "GPIO support for Whiskey Cove PMIC"
- depends on INTEL_SOC_PMIC
+ depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
select GPIOLIB_IRQCHIP
help
Support for GPIO pins on Whiskey Cove PMIC.
@@ -1067,6 +1075,7 @@ menu "PCI GPIO expanders"
config GPIO_AMD8111
tristate "AMD 8111 GPIO driver"
+ depends on X86 || COMPILE_TEST
help
The AMD 8111 south bridge contains 32 GPIO pins which can be used.
@@ -1108,6 +1117,7 @@ config GPIO_MERRIFIELD
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
+ depends on X86 || COMPILE_TEST
select GENERIC_IRQ_CHIP
help
ML7213 is companion chip for Intel Atom E6xx series.
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d074c2299393..a7676b82de6f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += devres.o
obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
+obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
+obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
@@ -102,7 +104,6 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
-obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o
obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 8ff7b0d3eac6..89863ea25de1 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -468,17 +468,19 @@ static int adnp_irq_setup(struct adnp *adnp)
return err;
}
- err = gpiochip_irqchip_add(chip,
- &adnp_irq_chip,
- 0,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ err = gpiochip_irqchip_add_nested(chip,
+ &adnp_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (err) {
dev_err(chip->parent,
"could not connect irqchip to gpiochip\n");
return err;
}
+ gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq);
+
return 0;
}
diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c
new file mode 100644
index 000000000000..9e1a138fed53
--- /dev/null
+++ b/drivers/gpio/gpio-altera-a10sr.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright Intel Corporation (C) 2014-2016. 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/>.
+ *
+ * GPIO driver for Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from gpio-tps65910.c
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/mfd/altera-a10sr.h>
+#include <linux/module.h>
+
+/**
+ * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure
+ * @gp: : instance of the gpio_chip
+ * @regmap: the regmap from the parent device.
+ */
+struct altr_a10sr_gpio {
+ struct gpio_chip gp;
+ struct regmap *regmap;
+};
+
+static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
+ int ret, val;
+
+ ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT));
+}
+
+static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
+
+ regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
+ BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
+ value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset)
+ : 0);
+}
+
+static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
+ unsigned int nr)
+{
+ if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT))
+ return 0;
+ return -EINVAL;
+}
+
+static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int nr, int value)
+{
+ if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+ return 0;
+ return -EINVAL;
+}
+
+static struct gpio_chip altr_a10sr_gc = {
+ .label = "altr_a10sr_gpio",
+ .owner = THIS_MODULE,
+ .get = altr_a10sr_gpio_get,
+ .set = altr_a10sr_gpio_set,
+ .direction_input = altr_a10sr_gpio_direction_input,
+ .direction_output = altr_a10sr_gpio_direction_output,
+ .can_sleep = true,
+ .ngpio = 12,
+ .base = -1,
+};
+
+static int altr_a10sr_gpio_probe(struct platform_device *pdev)
+{
+ struct altr_a10sr_gpio *gpio;
+ int ret;
+ struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ gpio->regmap = a10sr->regmap;
+
+ gpio->gp = altr_a10sr_gc;
+
+ gpio->gp.of_node = pdev->dev.of_node;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, gpio);
+
+ return 0;
+}
+
+static const struct of_device_id altr_a10sr_gpio_of_match[] = {
+ { .compatible = "altr,a10sr-gpio" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match);
+
+static struct platform_driver altr_a10sr_gpio_driver = {
+ .probe = altr_a10sr_gpio_probe,
+ .driver = {
+ .name = "altr_a10sr_gpio",
+ .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match),
+ },
+};
+module_platform_driver(altr_a10sr_gpio_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>");
+MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO");
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 482462889c8f..1f91557717a6 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -137,15 +137,10 @@ static int arizona_gpio_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
ret);
- goto err;
+ return ret;
}
- platform_set_drvdata(pdev, arizona_gpio);
-
- return ret;
-
-err:
- return ret;
+ return 0;
}
static struct platform_driver arizona_gpio_driver = {
diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c
index d9c2a517c6df..4a346b7b4172 100644
--- a/drivers/gpio/gpio-axp209.c
+++ b/drivers/gpio/gpio-axp209.c
@@ -64,13 +64,9 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
- int reg, ret;
-
- reg = axp20x_gpio_get_reg(offset);
- if (reg < 0)
- return reg;
+ int ret;
- ret = regmap_read(gpio->regmap, reg, &val);
+ ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
if (ret)
return ret;
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
index 7c446d118cd6..2197368cc899 100644
--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -351,8 +351,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
return retval;
}
- gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
+ gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
IRQF_ONESHOT, KBUILD_MODNAME, cg);
@@ -362,6 +362,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
return retval;
}
+ gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq);
+
return 0;
}
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index dd262f00295d..9191056548fe 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -40,6 +40,7 @@ struct davinci_gpio_regs {
typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
#define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */
+#define MAX_LABEL_SIZE 20
static void __iomem *gpio_base;
@@ -201,6 +202,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
struct davinci_gpio_regs __iomem *regs;
struct device *dev = &pdev->dev;
struct resource *res;
+ char label[MAX_LABEL_SIZE];
pdata = davinci_gpio_get_pdata(pdev);
if (!pdata) {
@@ -237,7 +239,10 @@ static int davinci_gpio_probe(struct platform_device *pdev)
return PTR_ERR(gpio_base);
for (i = 0, base = 0; base < ngpio; i++, base += 32) {
- chips[i].chip.label = "DaVinci";
+ snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i);
+ chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
+ if (!chips[i].chip.label)
+ return -ENOMEM;
chips[i].chip.direction_input = davinci_direction_in;
chips[i].chip.get = davinci_gpio_get;
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
index f7a60a441e95..5d38b08d1ee2 100644
--- a/drivers/gpio/gpio-dln2.c
+++ b/drivers/gpio/gpio-dln2.c
@@ -467,7 +467,6 @@ static int dln2_gpio_probe(struct platform_device *pdev)
dln2->gpio.base = -1;
dln2->gpio.ngpio = pins;
dln2->gpio.can_sleep = true;
- dln2->gpio.irq_not_threaded = true;
dln2->gpio.set = dln2_gpio_set;
dln2->gpio.get = dln2_gpio_get;
dln2->gpio.request = dln2_gpio_request;
diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c
index 00b022c9acb3..a254d5b07b94 100644
--- a/drivers/gpio/gpio-etraxfs.c
+++ b/drivers/gpio/gpio-etraxfs.c
@@ -471,9 +471,4 @@ static struct platform_driver etraxfs_gpio_driver = {
.probe = etraxfs_gpio_probe,
};
-static int __init etraxfs_gpio_init(void)
-{
- return platform_driver_register(&etraxfs_gpio_driver);
-}
-
-device_initcall(etraxfs_gpio_init);
+builtin_platform_driver(etraxfs_gpio_driver);
diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c
index 0b4df6051097..271356effb2e 100644
--- a/drivers/gpio/gpio-htc-egpio.c
+++ b/drivers/gpio/gpio-htc-egpio.c
@@ -17,7 +17,7 @@
#include <linux/platform_data/gpio-htc-egpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/init.h>
struct egpio_chip {
int reg_start;
@@ -160,10 +160,14 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset)
bit = egpio_bit(ei, offset);
reg = egpio->reg_start + egpio_pos(ei, offset);
- value = egpio_readw(ei, reg);
- pr_debug("readw(%p + %x) = %x\n",
- ei->base_addr, reg << ei->bus_shift, value);
- return !!(value & bit);
+ if (test_bit(offset, &egpio->is_out)) {
+ return !!(egpio->cached_values & (1 << offset));
+ } else {
+ value = egpio_readw(ei, reg);
+ pr_debug("readw(%p + %x) = %x\n",
+ ei->base_addr, reg << ei->bus_shift, value);
+ return !!(value & bit);
+ }
}
static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -225,6 +229,15 @@ static int egpio_direction_output(struct gpio_chip *chip,
}
}
+static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ struct egpio_chip *egpio;
+
+ egpio = gpiochip_get_data(chip);
+
+ return !test_bit(offset, &egpio->is_out);
+}
+
static void egpio_write_cache(struct egpio_info *ei)
{
int i;
@@ -327,6 +340,7 @@ static int __init egpio_probe(struct platform_device *pdev)
chip->set = egpio_set;
chip->direction_input = egpio_direction_input;
chip->direction_output = egpio_direction_output;
+ chip->get_direction = egpio_get_direction;
chip->base = pdata->chip[i].gpio_base;
chip->ngpio = pdata->chip[i].num_gpios;
@@ -367,24 +381,6 @@ fail:
return ret;
}
-static int __exit egpio_remove(struct platform_device *pdev)
-{
- struct egpio_info *ei = platform_get_drvdata(pdev);
- unsigned int irq, irq_end;
-
- if (ei->chained_irq) {
- irq_end = ei->irq_start + ei->nirqs;
- for (irq = ei->irq_start; irq < irq_end; irq++) {
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
- }
- irq_set_chained_handler(ei->chained_irq, NULL);
- device_init_wakeup(&pdev->dev, 0);
- }
-
- return 0;
-}
-
#ifdef CONFIG_PM
static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
{
@@ -416,8 +412,8 @@ static int egpio_resume(struct platform_device *pdev)
static struct platform_driver egpio_driver = {
.driver = {
.name = "htc-egpio",
+ .suppress_bind_attrs = true,
},
- .remove = __exit_p(egpio_remove),
.suspend = egpio_suspend,
.resume = egpio_resume,
};
@@ -426,15 +422,5 @@ static int __init egpio_init(void)
{
return platform_driver_probe(&egpio_driver, egpio_probe);
}
-
-static void __exit egpio_exit(void)
-{
- platform_driver_unregister(&egpio_driver);
-}
-
/* start early for dependencies */
subsys_initcall(egpio_init);
-module_exit(egpio_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kevin O'Connor <kevin@koconnor.net>");
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index 164de64b11fc..a1e44c221f66 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -421,9 +421,4 @@ static struct pci_driver intel_gpio_driver = {
},
};
-static int __init intel_gpio_init(void)
-{
- return pci_register_driver(&intel_gpio_driver);
-}
-
-device_initcall(intel_gpio_init);
+builtin_pci_driver(intel_gpio_driver);
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index a9aaf9d822b4..4ea4c6a1313b 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -520,20 +520,19 @@ static int max732x_irq_setup(struct max732x_chip *chip,
client->irq);
return ret;
}
- ret = gpiochip_irqchip_add(&chip->gpio_chip,
- &max732x_irq_chip,
- irq_base,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
+ &max732x_irq_chip,
+ irq_base,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
- gpiochip_set_chained_irqchip(&chip->gpio_chip,
- &max732x_irq_chip,
- client->irq,
- NULL);
+ gpiochip_set_nested_irqchip(&chip->gpio_chip,
+ &max732x_irq_chip,
+ client->irq);
}
return 0;
diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c
index b46b436cb97f..ec8de4190db9 100644
--- a/drivers/gpio/gpio-max77620.c
+++ b/drivers/gpio/gpio-max77620.c
@@ -21,9 +21,6 @@ struct max77620_gpio {
struct gpio_chip gpio_chip;
struct regmap *rmap;
struct device *dev;
- int gpio_irq;
- int irq_base;
- int gpio_base;
};
static const struct regmap_irq max77620_gpio_irqs[] = {
@@ -254,7 +251,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->rmap = chip->rmap;
mgpio->dev = &pdev->dev;
- mgpio->gpio_irq = gpio_irq;
mgpio->gpio_chip.label = pdev->name;
mgpio->gpio_chip.parent = &pdev->dev;
@@ -268,7 +264,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
mgpio->gpio_chip.can_sleep = 1;
mgpio->gpio_chip.base = -1;
- mgpio->irq_base = -1;
#ifdef CONFIG_OF_GPIO
mgpio->gpio_chip.of_node = pdev->dev.parent->of_node;
#endif
@@ -281,9 +276,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
return ret;
}
- mgpio->gpio_base = mgpio->gpio_chip.base;
- ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq,
- IRQF_ONESHOT, mgpio->irq_base,
+ ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq,
+ IRQF_ONESHOT, -1,
&max77620_gpio_irq_chip,
&chip->gpio_irq_data);
if (ret < 0) {
@@ -296,6 +290,7 @@ static int max77620_gpio_probe(struct platform_device *pdev)
static const struct platform_device_id max77620_gpio_devtype[] = {
{ .name = "max77620-gpio", },
+ { .name = "max20024-gpio", },
{},
};
MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index d55af50e7034..ffb73f688ae1 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -217,8 +217,4 @@ static struct platform_driver mb86s70_gpio_driver = {
.remove = mb86s70_gpio_remove,
};
-static int __init mb86s70_gpio_init(void)
-{
- return platform_driver_register(&mb86s70_gpio_driver);
-}
-device_initcall(mb86s70_gpio_init);
+builtin_platform_driver(mb86s70_gpio_driver);
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 99d37b56c258..504550665091 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -473,21 +473,20 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
return err;
}
- err = gpiochip_irqchip_add(chip,
- &mcp23s08_irq_chip,
- 0,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ err = gpiochip_irqchip_add_nested(chip,
+ &mcp23s08_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (err) {
dev_err(chip->parent,
"could not connect irqchip to gpiochip: %d\n", err);
return err;
}
- gpiochip_set_chained_irqchip(chip,
- &mcp23s08_irq_chip,
- mcp->irq,
- NULL);
+ gpiochip_set_nested_irqchip(chip,
+ &mcp23s08_irq_chip,
+ mcp->irq);
return 0;
}
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index 45b51278b8ee..69e0f4ace465 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -161,6 +162,34 @@ static int mrfld_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
+static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+
+ return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
+static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+ unsigned int debounce)
+{
+ struct mrfld_gpio *priv = gpiochip_get_data(chip);
+ void __iomem *gfbr = gpio_reg(chip, offset, GFBR);
+ unsigned long flags;
+ u32 value;
+
+ raw_spin_lock_irqsave(&priv->lock, flags);
+
+ if (debounce)
+ value = readl(gfbr) & ~BIT(offset % 32);
+ else
+ value = readl(gfbr) | BIT(offset % 32);
+ writel(value, gfbr);
+
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
static void mrfld_irq_ack(struct irq_data *d)
{
struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
@@ -384,6 +413,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
priv->chip.direction_output = mrfld_gpio_direction_output;
priv->chip.get = mrfld_gpio_get;
priv->chip.set = mrfld_gpio_set;
+ priv->chip.get_direction = mrfld_gpio_get_direction;
+ priv->chip.set_debounce = mrfld_gpio_set_debounce;
priv->chip.base = gpio_base;
priv->chip.ngpio = MRFLD_NGPIO;
priv->chip.can_sleep = false;
@@ -411,7 +442,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
}
retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
- handle_simple_irq, IRQ_TYPE_NONE);
+ handle_bad_irq, IRQ_TYPE_NONE);
if (retval) {
dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
return retval;
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index ee1724806f46..1e8fde8cb803 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -87,10 +87,15 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
u32 val;
u32 pin_mask = 1 << d->hwirq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct mxs_gpio_port *port = gc->private;
void __iomem *pin_addr;
int edge;
+ if (!(ct->type & type))
+ if (irq_setup_alt_chip(d, type))
+ return -EINVAL;
+
port->both_edges &= ~pin_mask;
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
@@ -119,10 +124,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
/* set level or edge */
pin_addr = port->base + PINCTRL_IRQLEV(port);
- if (edge & GPIO_INT_LEV_MASK)
+ if (edge & GPIO_INT_LEV_MASK) {
writel(pin_mask, pin_addr + MXS_SET);
- else
+ writel(pin_mask, port->base + PINCTRL_IRQEN(port) + MXS_SET);
+ } else {
writel(pin_mask, pin_addr + MXS_CLR);
+ writel(pin_mask, port->base + PINCTRL_PIN2IRQ(port) + MXS_SET);
+ }
/* set polarity */
pin_addr = port->base + PINCTRL_IRQPOL(port);
@@ -202,21 +210,37 @@ static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
- gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
+ gc = irq_alloc_generic_chip("gpio-mxs", 2, irq_base,
port->base, handle_level_irq);
if (!gc)
return -ENOMEM;
gc->private = port;
- ct = gc->chip_types;
+ ct = &gc->chip_types[0];
+ ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_disable_reg;
+ ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+ ct->chip.irq_set_type = mxs_gpio_set_irq_type;
+ ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
+ ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
+ ct->regs.enable = PINCTRL_PIN2IRQ(port) + MXS_SET;
+ ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
+
+ ct = &gc->chip_types[1];
+ ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_clr_bit;
- ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_disable_reg;
+ ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
ct->chip.irq_set_type = mxs_gpio_set_irq_type;
ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
- ct->regs.mask = PINCTRL_IRQEN(port);
+ ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET;
+ ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR;
+ ct->handler = handle_level_irq;
irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
IRQ_NOREQUEST, 0);
@@ -297,11 +321,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
}
port->base = base;
- /*
- * select the pin interrupt functionality but initially
- * disable the interrupts
- */
- writel(~0U, port->base + PINCTRL_PIN2IRQ(port));
+ /* initially disable the interrupts */
+ writel(0, port->base + PINCTRL_PIN2IRQ(port));
writel(0, port->base + PINCTRL_IRQEN(port));
/* clear address has to be used to clear IRQSTAT bits */
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index fe731f094257..d5d72d84b719 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -74,6 +74,7 @@ static const struct i2c_device_id pca953x_id[] = {
{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
{ "max7315", 8 | PCA953X_TYPE | PCA_INT, },
+ { "max7318", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
@@ -635,20 +636,20 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
return ret;
}
- ret = gpiochip_irqchip_add(&chip->gpio_chip,
- &pca953x_irq_chip,
- irq_base,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
+ &pca953x_irq_chip,
+ irq_base,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
- gpiochip_set_chained_irqchip(&chip->gpio_chip,
- &pca953x_irq_chip,
- client->irq, NULL);
+ gpiochip_set_nested_irqchip(&chip->gpio_chip,
+ &pca953x_irq_chip,
+ client->irq);
}
return 0;
@@ -907,6 +908,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
{ .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
{ .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), },
{ .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), },
+ { .compatible = "maxim,max7318", .data = OF_953X(16, PCA_INT), },
{ .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), },
{ .compatible = "ti,pca9536", .data = OF_953X( 4, 0), },
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index d168410e2338..895af42a4513 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -378,9 +378,10 @@ static int pcf857x_probe(struct i2c_client *client,
/* Enable irqchip if we have an interrupt */
if (client->irq) {
- status = gpiochip_irqchip_add(&gpio->chip, &pcf857x_irq_chip,
- 0, handle_level_irq,
- IRQ_TYPE_NONE);
+ status = gpiochip_irqchip_add_nested(&gpio->chip,
+ &pcf857x_irq_chip,
+ 0, handle_level_irq,
+ IRQ_TYPE_NONE);
if (status) {
dev_err(&client->dev, "cannot add irqchip\n");
goto fail;
@@ -393,8 +394,8 @@ static int pcf857x_probe(struct i2c_client *client,
if (status)
goto fail;
- gpiochip_set_chained_irqchip(&gpio->chip, &pcf857x_irq_chip,
- client->irq, NULL);
+ gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+ client->irq);
gpio->irq_parent = client->irq;
}
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 6e3c1430616f..0a6bfd2b06e5 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -23,7 +23,6 @@
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
-#include <linux/amba/pl061.h>
#include <linux/slab.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm.h>
@@ -50,11 +49,12 @@ struct pl061_context_save_regs {
};
#endif
-struct pl061_gpio {
+struct pl061 {
spinlock_t lock;
void __iomem *base;
struct gpio_chip gc;
+ int parent_irq;
#ifdef CONFIG_PM
struct pl061_context_save_regs csave_regs;
@@ -63,22 +63,22 @@ struct pl061_gpio {
static int pl061_get_direction(struct gpio_chip *gc, unsigned offset)
{
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
- return !(readb(chip->base + GPIODIR) & BIT(offset));
+ return !(readb(pl061->base + GPIODIR) & BIT(offset));
}
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
unsigned long flags;
unsigned char gpiodir;
- spin_lock_irqsave(&chip->lock, flags);
- gpiodir = readb(chip->base + GPIODIR);
+ spin_lock_irqsave(&pl061->lock, flags);
+ gpiodir = readb(pl061->base + GPIODIR);
gpiodir &= ~(BIT(offset));
- writeb(gpiodir, chip->base + GPIODIR);
- spin_unlock_irqrestore(&chip->lock, flags);
+ writeb(gpiodir, pl061->base + GPIODIR);
+ spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
@@ -86,44 +86,44 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
unsigned long flags;
unsigned char gpiodir;
- spin_lock_irqsave(&chip->lock, flags);
- writeb(!!value << offset, chip->base + (BIT(offset + 2)));
- gpiodir = readb(chip->base + GPIODIR);
+ spin_lock_irqsave(&pl061->lock, flags);
+ writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
+ gpiodir = readb(pl061->base + GPIODIR);
gpiodir |= BIT(offset);
- writeb(gpiodir, chip->base + GPIODIR);
+ writeb(gpiodir, pl061->base + GPIODIR);
/*
* gpio value is set again, because pl061 doesn't allow to set value of
* a gpio pin before configuring it in OUT mode.
*/
- writeb(!!value << offset, chip->base + (BIT(offset + 2)));
- spin_unlock_irqrestore(&chip->lock, flags);
+ writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
+ spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
{
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
- return !!readb(chip->base + (BIT(offset + 2)));
+ return !!readb(pl061->base + (BIT(offset + 2)));
}
static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
{
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
- writeb(!!value << offset, chip->base + (BIT(offset + 2)));
+ writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
}
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
int offset = irqd_to_hwirq(d);
unsigned long flags;
u8 gpiois, gpioibe, gpioiev;
@@ -143,11 +143,11 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
}
- spin_lock_irqsave(&chip->lock, flags);
+ spin_lock_irqsave(&pl061->lock, flags);
- gpioiev = readb(chip->base + GPIOIEV);
- gpiois = readb(chip->base + GPIOIS);
- gpioibe = readb(chip->base + GPIOIBE);
+ gpioiev = readb(pl061->base + GPIOIEV);
+ gpiois = readb(pl061->base + GPIOIS);
+ gpioibe = readb(pl061->base + GPIOIBE);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
@@ -199,11 +199,11 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
offset);
}
- writeb(gpiois, chip->base + GPIOIS);
- writeb(gpioibe, chip->base + GPIOIBE);
- writeb(gpioiev, chip->base + GPIOIEV);
+ writeb(gpiois, pl061->base + GPIOIS);
+ writeb(gpioibe, pl061->base + GPIOIBE);
+ writeb(gpioiev, pl061->base + GPIOIEV);
- spin_unlock_irqrestore(&chip->lock, flags);
+ spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
@@ -213,12 +213,12 @@ static void pl061_irq_handler(struct irq_desc *desc)
unsigned long pending;
int offset;
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc);
- pending = readb(chip->base + GPIOMIS);
+ pending = readb(pl061->base + GPIOMIS);
if (pending) {
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(irq_find_mapping(gc->irqdomain,
@@ -231,27 +231,27 @@ static void pl061_irq_handler(struct irq_desc *desc)
static void pl061_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
- spin_lock(&chip->lock);
- gpioie = readb(chip->base + GPIOIE) & ~mask;
- writeb(gpioie, chip->base + GPIOIE);
- spin_unlock(&chip->lock);
+ spin_lock(&pl061->lock);
+ gpioie = readb(pl061->base + GPIOIE) & ~mask;
+ writeb(gpioie, pl061->base + GPIOIE);
+ spin_unlock(&pl061->lock);
}
static void pl061_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
- spin_lock(&chip->lock);
- gpioie = readb(chip->base + GPIOIE) | mask;
- writeb(gpioie, chip->base + GPIOIE);
- spin_unlock(&chip->lock);
+ spin_lock(&pl061->lock);
+ gpioie = readb(pl061->base + GPIOIE) | mask;
+ writeb(gpioie, pl061->base + GPIOIE);
+ spin_unlock(&pl061->lock);
}
/**
@@ -265,19 +265,20 @@ static void pl061_irq_unmask(struct irq_data *d)
static void pl061_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct pl061_gpio *chip = gpiochip_get_data(gc);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
- spin_lock(&chip->lock);
- writeb(mask, chip->base + GPIOIC);
- spin_unlock(&chip->lock);
+ spin_lock(&pl061->lock);
+ writeb(mask, pl061->base + GPIOIC);
+ spin_unlock(&pl061->lock);
}
static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pl061 *pl061 = gpiochip_get_data(gc);
- return irq_set_irq_wake(gc->irq_parent, state);
+ return irq_set_irq_wake(pl061->parent_irq, state);
}
static struct irq_chip pl061_irqchip = {
@@ -292,81 +293,60 @@ static struct irq_chip pl061_irqchip = {
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
- struct pl061_platform_data *pdata = dev_get_platdata(dev);
- struct pl061_gpio *chip;
- int ret, irq, i, irq_base;
+ struct pl061 *pl061;
+ int ret, irq;
- chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
+ pl061 = devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL);
+ if (pl061 == NULL)
return -ENOMEM;
- if (pdata) {
- chip->gc.base = pdata->gpio_base;
- irq_base = pdata->irq_base;
- if (irq_base <= 0) {
- dev_err(&adev->dev, "invalid IRQ base in pdata\n");
- return -ENODEV;
- }
- } else {
- chip->gc.base = -1;
- irq_base = 0;
- }
-
- chip->base = devm_ioremap_resource(dev, &adev->res);
- if (IS_ERR(chip->base))
- return PTR_ERR(chip->base);
+ pl061->base = devm_ioremap_resource(dev, &adev->res);
+ if (IS_ERR(pl061->base))
+ return PTR_ERR(pl061->base);
- spin_lock_init(&chip->lock);
+ spin_lock_init(&pl061->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
- chip->gc.request = gpiochip_generic_request;
- chip->gc.free = gpiochip_generic_free;
+ pl061->gc.request = gpiochip_generic_request;
+ pl061->gc.free = gpiochip_generic_free;
}
- chip->gc.get_direction = pl061_get_direction;
- chip->gc.direction_input = pl061_direction_input;
- chip->gc.direction_output = pl061_direction_output;
- chip->gc.get = pl061_get_value;
- chip->gc.set = pl061_set_value;
- chip->gc.ngpio = PL061_GPIO_NR;
- chip->gc.label = dev_name(dev);
- chip->gc.parent = dev;
- chip->gc.owner = THIS_MODULE;
-
- ret = gpiochip_add_data(&chip->gc, chip);
+ pl061->gc.base = -1;
+ pl061->gc.get_direction = pl061_get_direction;
+ pl061->gc.direction_input = pl061_direction_input;
+ pl061->gc.direction_output = pl061_direction_output;
+ pl061->gc.get = pl061_get_value;
+ pl061->gc.set = pl061_set_value;
+ pl061->gc.ngpio = PL061_GPIO_NR;
+ pl061->gc.label = dev_name(dev);
+ pl061->gc.parent = dev;
+ pl061->gc.owner = THIS_MODULE;
+
+ ret = gpiochip_add_data(&pl061->gc, pl061);
if (ret)
return ret;
/*
* irq_chip support
*/
- writeb(0, chip->base + GPIOIE); /* disable irqs */
+ writeb(0, pl061->base + GPIOIE); /* disable irqs */
irq = adev->irq[0];
if (irq < 0) {
dev_err(&adev->dev, "invalid IRQ\n");
return -ENODEV;
}
+ pl061->parent_irq = irq;
- ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip,
- irq_base, handle_bad_irq,
+ ret = gpiochip_irqchip_add(&pl061->gc, &pl061_irqchip,
+ 0, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_info(&adev->dev, "could not add irqchip\n");
return ret;
}
- gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip,
+ gpiochip_set_chained_irqchip(&pl061->gc, &pl061_irqchip,
irq, pl061_irq_handler);
- for (i = 0; i < PL061_GPIO_NR; i++) {
- if (pdata) {
- if (pdata->directions & (BIT(i)))
- pl061_direction_output(&chip->gc, i,
- pdata->values & (BIT(i)));
- else
- pl061_direction_input(&chip->gc, i);
- }
- }
-
- amba_set_drvdata(adev, chip);
+ amba_set_drvdata(adev, pl061);
dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n",
&adev->res.start);
@@ -376,20 +356,20 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
#ifdef CONFIG_PM
static int pl061_suspend(struct device *dev)
{
- struct pl061_gpio *chip = dev_get_drvdata(dev);
+ struct pl061 *pl061 = dev_get_drvdata(dev);
int offset;
- chip->csave_regs.gpio_data = 0;
- chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR);
- chip->csave_regs.gpio_is = readb(chip->base + GPIOIS);
- chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE);
- chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV);
- chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
+ pl061->csave_regs.gpio_data = 0;
+ pl061->csave_regs.gpio_dir = readb(pl061->base + GPIODIR);
+ pl061->csave_regs.gpio_is = readb(pl061->base + GPIOIS);
+ pl061->csave_regs.gpio_ibe = readb(pl061->base + GPIOIBE);
+ pl061->csave_regs.gpio_iev = readb(pl061->base + GPIOIEV);
+ pl061->csave_regs.gpio_ie = readb(pl061->base + GPIOIE);
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
- if (chip->csave_regs.gpio_dir & (BIT(offset)))
- chip->csave_regs.gpio_data |=
- pl061_get_value(&chip->gc, offset) << offset;
+ if (pl061->csave_regs.gpio_dir & (BIT(offset)))
+ pl061->csave_regs.gpio_data |=
+ pl061_get_value(&pl061->gc, offset) << offset;
}
return 0;
@@ -397,22 +377,22 @@ static int pl061_suspend(struct device *dev)
static int pl061_resume(struct device *dev)
{
- struct pl061_gpio *chip = dev_get_drvdata(dev);
+ struct pl061 *pl061 = dev_get_drvdata(dev);
int offset;
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
- if (chip->csave_regs.gpio_dir & (BIT(offset)))
- pl061_direction_output(&chip->gc, offset,
- chip->csave_regs.gpio_data &
+ if (pl061->csave_regs.gpio_dir & (BIT(offset)))
+ pl061_direction_output(&pl061->gc, offset,
+ pl061->csave_regs.gpio_data &
(BIT(offset)));
else
- pl061_direction_input(&chip->gc, offset);
+ pl061_direction_input(&pl061->gc, offset);
}
- writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS);
- writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE);
- writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV);
- writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE);
+ writeb(pl061->csave_regs.gpio_is, pl061->base + GPIOIS);
+ writeb(pl061->csave_regs.gpio_ibe, pl061->base + GPIOIBE);
+ writeb(pl061->csave_regs.gpio_iev, pl061->base + GPIOIEV);
+ writeb(pl061->csave_regs.gpio_ie, pl061->base + GPIOIE);
return 0;
}
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 5b0042776ec7..16cbc5702865 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -413,7 +413,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
stmpe->partnum != STMPE1801) {
stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
stmpe_reg_write(stmpe,
- stmpe->regs[STMPE_IDX_GPEDR_LSB + i],
+ stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
status[i]);
}
}
@@ -484,21 +484,20 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
if (stmpe_gpio->norequest_mask & BIT(i))
clear_bit(i, stmpe_gpio->chip.irq_valid_mask);
}
- ret = gpiochip_irqchip_add(&stmpe_gpio->chip,
- &stmpe_gpio_irq_chip,
- 0,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ ret = gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
+ &stmpe_gpio_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (ret) {
dev_err(&pdev->dev,
"could not connect irqchip to gpiochip\n");
goto out_disable;
}
- gpiochip_set_chained_irqchip(&stmpe_gpio->chip,
- &stmpe_gpio_irq_chip,
- irq,
- NULL);
+ gpiochip_set_nested_irqchip(&stmpe_gpio->chip,
+ &stmpe_gpio_irq_chip,
+ irq);
}
platform_set_drvdata(pdev, stmpe_gpio);
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
deleted file mode 100644
index af95de89db01..000000000000
--- a/drivers/gpio/gpio-sx150x.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * Driver for Semtech SX150X I2C GPIO Expanders
- *
- * Author: Gregory Bean <gbean@codeaurora.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 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.
- */
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-
-#define NO_UPDATE_PENDING -1
-
-/* The chip models of sx150x */
-#define SX150X_123 0
-#define SX150X_456 1
-#define SX150X_789 2
-
-struct sx150x_123_pri {
- u8 reg_pld_mode;
- u8 reg_pld_table0;
- u8 reg_pld_table1;
- u8 reg_pld_table2;
- u8 reg_pld_table3;
- u8 reg_pld_table4;
- u8 reg_advance;
-};
-
-struct sx150x_456_pri {
- u8 reg_pld_mode;
- u8 reg_pld_table0;
- u8 reg_pld_table1;
- u8 reg_pld_table2;
- u8 reg_pld_table3;
- u8 reg_pld_table4;
- u8 reg_advance;
-};
-
-struct sx150x_789_pri {
- u8 reg_drain;
- u8 reg_polarity;
- u8 reg_clock;
- u8 reg_misc;
- u8 reg_reset;
- u8 ngpios;
-};
-
-struct sx150x_device_data {
- u8 model;
- u8 reg_pullup;
- u8 reg_pulldn;
- u8 reg_dir;
- u8 reg_data;
- u8 reg_irq_mask;
- u8 reg_irq_src;
- u8 reg_sense;
- u8 ngpios;
- union {
- struct sx150x_123_pri x123;
- struct sx150x_456_pri x456;
- struct sx150x_789_pri x789;
- } pri;
-};
-
-/**
- * struct sx150x_platform_data - config data for SX150x driver
- * @gpio_base: The index number of the first GPIO assigned to this
- * GPIO expander. The expander will create a block of
- * consecutively numbered gpios beginning at the given base,
- * with the size of the block depending on the model of the
- * expander chip.
- * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO
- * instead of as an oscillator, increasing the size of the
- * GP(I)O pool created by this expander by one. The
- * output-only GPO pin will be added at the end of the block.
- * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor
- * for each IO line in the expander. Setting the bit at
- * position n will enable the pull-up for the IO at
- * the corresponding offset. For chips with fewer than
- * 16 IO pins, high-end bits are ignored.
- * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down
- * resistor for each IO line in the expander. Setting the
- * bit at position n will enable the pull-down for the IO at
- * the corresponding offset. For chips with fewer than
- * 16 IO pins, high-end bits are ignored.
- * @io_polarity: A bit-mask which enables polarity inversion for each IO line
- * in the expander. Setting the bit at position n inverts
- * the polarity of that IO line, while clearing it results
- * in normal polarity. For chips with fewer than 16 IO pins,
- * high-end bits are ignored.
- * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line
- * is connected, via which it reports interrupt events
- * across all GPIO lines. This must be a real,
- * pre-existing IRQ line.
- * Setting this value < 0 disables the irq_chip functionality
- * of the driver.
- * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based
- * IRQ lines will appear. Similarly to gpio_base, the expander
- * will create a block of irqs beginning at this number.
- * This value is ignored if irq_summary is < 0.
- * @reset_during_probe: If set to true, the driver will trigger a full
- * reset of the chip at the beginning of the probe
- * in order to place it in a known state.
- */
-struct sx150x_platform_data {
- unsigned gpio_base;
- bool oscio_is_gpo;
- u16 io_pullup_ena;
- u16 io_pulldn_ena;
- u16 io_polarity;
- int irq_summary;
- unsigned irq_base;
- bool reset_during_probe;
-};
-
-struct sx150x_chip {
- struct gpio_chip gpio_chip;
- struct i2c_client *client;
- const struct sx150x_device_data *dev_cfg;
- int irq_summary;
- int irq_base;
- int irq_update;
- u32 irq_sense;
- u32 irq_masked;
- u32 dev_sense;
- u32 dev_masked;
- struct irq_chip irq_chip;
- struct mutex lock;
-};
-
-static const struct sx150x_device_data sx150x_devices[] = {
- [0] = { /* sx1508q */
- .model = SX150X_789,
- .reg_pullup = 0x03,
- .reg_pulldn = 0x04,
- .reg_dir = 0x07,
- .reg_data = 0x08,
- .reg_irq_mask = 0x09,
- .reg_irq_src = 0x0c,
- .reg_sense = 0x0b,
- .pri.x789 = {
- .reg_drain = 0x05,
- .reg_polarity = 0x06,
- .reg_clock = 0x0f,
- .reg_misc = 0x10,
- .reg_reset = 0x7d,
- },
- .ngpios = 8,
- },
- [1] = { /* sx1509q */
- .model = SX150X_789,
- .reg_pullup = 0x07,
- .reg_pulldn = 0x09,
- .reg_dir = 0x0f,
- .reg_data = 0x11,
- .reg_irq_mask = 0x13,
- .reg_irq_src = 0x19,
- .reg_sense = 0x17,
- .pri.x789 = {
- .reg_drain = 0x0b,
- .reg_polarity = 0x0d,
- .reg_clock = 0x1e,
- .reg_misc = 0x1f,
- .reg_reset = 0x7d,
- },
- .ngpios = 16
- },
- [2] = { /* sx1506q */
- .model = SX150X_456,
- .reg_pullup = 0x05,
- .reg_pulldn = 0x07,
- .reg_dir = 0x03,
- .reg_data = 0x01,
- .reg_irq_mask = 0x09,
- .reg_irq_src = 0x0f,
- .reg_sense = 0x0d,
- .pri.x456 = {
- .reg_pld_mode = 0x21,
- .reg_pld_table0 = 0x23,
- .reg_pld_table1 = 0x25,
- .reg_pld_table2 = 0x27,
- .reg_pld_table3 = 0x29,
- .reg_pld_table4 = 0x2b,
- .reg_advance = 0xad,
- },
- .ngpios = 16
- },
- [3] = { /* sx1502q */
- .model = SX150X_123,
- .reg_pullup = 0x02,
- .reg_pulldn = 0x03,
- .reg_dir = 0x01,
- .reg_data = 0x00,
- .reg_irq_mask = 0x05,
- .reg_irq_src = 0x08,
- .reg_sense = 0x07,
- .pri.x123 = {
- .reg_pld_mode = 0x10,
- .reg_pld_table0 = 0x11,
- .reg_pld_table1 = 0x12,
- .reg_pld_table2 = 0x13,
- .reg_pld_table3 = 0x14,
- .reg_pld_table4 = 0x15,
- .reg_advance = 0xad,
- },
- .ngpios = 8,
- },
-};
-
-static const struct i2c_device_id sx150x_id[] = {
- {"sx1508q", 0},
- {"sx1509q", 1},
- {"sx1506q", 2},
- {"sx1502q", 3},
- {}
-};
-
-static const struct of_device_id sx150x_of_match[] = {
- { .compatible = "semtech,sx1508q" },
- { .compatible = "semtech,sx1509q" },
- { .compatible = "semtech,sx1506q" },
- { .compatible = "semtech,sx1502q" },
- {},
-};
-
-static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
-{
- s32 err = i2c_smbus_write_byte_data(client, reg, val);
-
- if (err < 0)
- dev_warn(&client->dev,
- "i2c write fail: can't write %02x to %02x: %d\n",
- val, reg, err);
- return err;
-}
-
-static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
-{
- s32 err = i2c_smbus_read_byte_data(client, reg);
-
- if (err >= 0)
- *val = err;
- else
- dev_warn(&client->dev,
- "i2c read fail: can't read from %02x: %d\n",
- reg, err);
- return err;
-}
-
-static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
-{
- return (chip->dev_cfg->ngpios == offset);
-}
-
-/*
- * These utility functions solve the common problem of locating and setting
- * configuration bits. Configuration bits are grouped into registers
- * whose indexes increase downwards. For example, with eight-bit registers,
- * sixteen gpios would have their config bits grouped in the following order:
- * REGISTER N-1 [ f e d c b a 9 8 ]
- * N [ 7 6 5 4 3 2 1 0 ]
- *
- * For multi-bit configurations, the pattern gets wider:
- * REGISTER N-3 [ f f e e d d c c ]
- * N-2 [ b b a a 9 9 8 8 ]
- * N-1 [ 7 7 6 6 5 5 4 4 ]
- * N [ 3 3 2 2 1 1 0 0 ]
- *
- * Given the address of the starting register 'N', the index of the gpio
- * whose configuration we seek to change, and the width in bits of that
- * configuration, these functions allow us to locate the correct
- * register and mask the correct bits.
- */
-static inline void sx150x_find_cfg(u8 offset, u8 width,
- u8 *reg, u8 *mask, u8 *shift)
-{
- *reg -= offset * width / 8;
- *mask = (1 << width) - 1;
- *shift = (offset * width) % 8;
- *mask <<= *shift;
-}
-
-static s32 sx150x_write_cfg(struct sx150x_chip *chip,
- u8 offset, u8 width, u8 reg, u8 val)
-{
- u8 mask;
- u8 data;
- u8 shift;
- s32 err;
-
- sx150x_find_cfg(offset, width, &reg, &mask, &shift);
- err = sx150x_i2c_read(chip->client, reg, &data);
- if (err < 0)
- return err;
-
- data &= ~mask;
- data |= (val << shift) & mask;
- return sx150x_i2c_write(chip->client, reg, data);
-}
-
-static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
-{
- u8 reg = chip->dev_cfg->reg_data;
- u8 mask;
- u8 data;
- u8 shift;
- s32 err;
-
- sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
- err = sx150x_i2c_read(chip->client, reg, &data);
- if (err >= 0)
- err = (data & mask) != 0 ? 1 : 0;
-
- return err;
-}
-
-static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
-{
- sx150x_i2c_write(chip->client,
- chip->dev_cfg->pri.x789.reg_clock,
- (val ? 0x1f : 0x10));
-}
-
-static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
-{
- sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->reg_data,
- (val ? 1 : 0));
-}
-
-static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
-{
- return sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->reg_dir,
- 1);
-}
-
-static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
-{
- int err;
-
- err = sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->reg_data,
- (val ? 1 : 0));
- if (err >= 0)
- err = sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->reg_dir,
- 0);
- return err;
-}
-
-static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
- struct sx150x_chip *chip = gpiochip_get_data(gc);
- int status = -EINVAL;
-
- if (!offset_is_oscio(chip, offset)) {
- mutex_lock(&chip->lock);
- status = sx150x_get_io(chip, offset);
- mutex_unlock(&chip->lock);
- }
-
- return (status < 0) ? status : !!status;
-}
-
-static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
-{
- struct sx150x_chip *chip = gpiochip_get_data(gc);
-
- mutex_lock(&chip->lock);
- if (offset_is_oscio(chip, offset))
- sx150x_set_oscio(chip, val);
- else
- sx150x_set_io(chip, offset, val);
- mutex_unlock(&chip->lock);
-}
-
-static int sx150x_gpio_set_single_ended(struct gpio_chip *gc,
- unsigned offset,
- enum single_ended_mode mode)
-{
- struct sx150x_chip *chip = gpiochip_get_data(gc);
-
- /* On the SX160X 789 we can set open drain */
- if (chip->dev_cfg->model != SX150X_789)
- return -ENOTSUPP;
-
- if (mode == LINE_MODE_PUSH_PULL)
- return sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->pri.x789.reg_drain,
- 0);
-
- if (mode == LINE_MODE_OPEN_DRAIN)
- return sx150x_write_cfg(chip,
- offset,
- 1,
- chip->dev_cfg->pri.x789.reg_drain,
- 1);
- return -ENOTSUPP;
-}
-
-static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
- struct sx150x_chip *chip = gpiochip_get_data(gc);
- int status = -EINVAL;
-
- if (!offset_is_oscio(chip, offset)) {
- mutex_lock(&chip->lock);
- status = sx150x_io_input(chip, offset);
- mutex_unlock(&chip->lock);
- }
- return status;
-}
-
-static int sx150x_gpio_direction_output(struct gpio_chip *gc,
- unsigned offset,
- int val)
-{
- struct sx150x_chip *chip = gpiochip_get_data(gc);
- int status = 0;
-
- if (!offset_is_oscio(chip, offset)) {
- mutex_lock(&chip->lock);
- status = sx150x_io_output(chip, offset, val);
- mutex_unlock(&chip->lock);
- }
- return status;
-}
-
-static void sx150x_irq_mask(struct irq_data *d)
-{
- struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned n = d->hwirq;
-
- chip->irq_masked |= (1 << n);
- chip->irq_update = n;
-}
-
-static void sx150x_irq_unmask(struct irq_data *d)
-{
- struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned n = d->hwirq;
-
- chip->irq_masked &= ~(1 << n);
- chip->irq_update = n;
-}
-
-static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
- struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned n, val = 0;
-
- if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- return -EINVAL;
-
- n = d->hwirq;
-
- if (flow_type & IRQ_TYPE_EDGE_RISING)
- val |= 0x1;
- if (flow_type & IRQ_TYPE_EDGE_FALLING)
- val |= 0x2;
-
- chip->irq_sense &= ~(3UL << (n * 2));
- chip->irq_sense |= val << (n * 2);
- chip->irq_update = n;
- return 0;
-}
-
-static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
-{
- struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
- unsigned nhandled = 0;
- unsigned sub_irq;
- unsigned n;
- s32 err;
- u8 val;
- int i;
-
- for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
- err = sx150x_i2c_read(chip->client,
- chip->dev_cfg->reg_irq_src - i,
- &val);
- if (err < 0)
- continue;
-
- sx150x_i2c_write(chip->client,
- chip->dev_cfg->reg_irq_src - i,
- val);
- for (n = 0; n < 8; ++n) {
- if (val & (1 << n)) {
- sub_irq = irq_find_mapping(
- chip->gpio_chip.irqdomain,
- (i * 8) + n);
- handle_nested_irq(sub_irq);
- ++nhandled;
- }
- }
- }
-
- return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
-}
-
-static void sx150x_irq_bus_lock(struct irq_data *d)
-{
- struct sx150x_chip *chip = gpiochip_get_data(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 = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned n;
-
- if (chip->irq_update == NO_UPDATE_PENDING)
- goto out;
-
- n = chip->irq_update;
- chip->irq_update = NO_UPDATE_PENDING;
-
- /* Avoid updates if nothing changed */
- if (chip->dev_sense == chip->irq_sense &&
- chip->dev_masked == chip->irq_masked)
- goto out;
-
- chip->dev_sense = chip->irq_sense;
- chip->dev_masked = chip->irq_masked;
-
- if (chip->irq_masked & (1 << n)) {
- sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
- sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
- } else {
- sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
- sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
- chip->irq_sense >> (n * 2));
- }
-out:
- mutex_unlock(&chip->lock);
-}
-
-static void sx150x_init_chip(struct sx150x_chip *chip,
- struct i2c_client *client,
- kernel_ulong_t driver_data,
- struct sx150x_platform_data *pdata)
-{
- mutex_init(&chip->lock);
-
- chip->client = client;
- chip->dev_cfg = &sx150x_devices[driver_data];
- chip->gpio_chip.parent = &client->dev;
- chip->gpio_chip.label = client->name;
- chip->gpio_chip.direction_input = sx150x_gpio_direction_input;
- chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
- chip->gpio_chip.get = sx150x_gpio_get;
- chip->gpio_chip.set = sx150x_gpio_set;
- chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended;
- chip->gpio_chip.base = pdata->gpio_base;
- chip->gpio_chip.can_sleep = true;
- chip->gpio_chip.ngpio = chip->dev_cfg->ngpios;
-#ifdef CONFIG_OF_GPIO
- chip->gpio_chip.of_node = client->dev.of_node;
- chip->gpio_chip.of_gpio_n_cells = 2;
-#endif
- if (pdata->oscio_is_gpo)
- ++chip->gpio_chip.ngpio;
-
- chip->irq_chip.name = client->name;
- chip->irq_chip.irq_mask = sx150x_irq_mask;
- chip->irq_chip.irq_unmask = sx150x_irq_unmask;
- chip->irq_chip.irq_set_type = sx150x_irq_set_type;
- chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock;
- chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
- chip->irq_summary = -1;
- chip->irq_base = -1;
- chip->irq_masked = ~0;
- chip->irq_sense = 0;
- chip->dev_masked = ~0;
- chip->dev_sense = 0;
- chip->irq_update = NO_UPDATE_PENDING;
-}
-
-static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
-{
- int err = 0;
- unsigned n;
-
- for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
- err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
- return err;
-}
-
-static int sx150x_reset(struct sx150x_chip *chip)
-{
- int err;
-
- err = i2c_smbus_write_byte_data(chip->client,
- chip->dev_cfg->pri.x789.reg_reset,
- 0x12);
- if (err < 0)
- return err;
-
- err = i2c_smbus_write_byte_data(chip->client,
- chip->dev_cfg->pri.x789.reg_reset,
- 0x34);
- return err;
-}
-
-static int sx150x_init_hw(struct sx150x_chip *chip,
- struct sx150x_platform_data *pdata)
-{
- int err = 0;
-
- if (pdata->reset_during_probe) {
- err = sx150x_reset(chip);
- if (err < 0)
- return err;
- }
-
- if (chip->dev_cfg->model == SX150X_789)
- err = sx150x_i2c_write(chip->client,
- chip->dev_cfg->pri.x789.reg_misc,
- 0x01);
- else if (chip->dev_cfg->model == SX150X_456)
- err = sx150x_i2c_write(chip->client,
- chip->dev_cfg->pri.x456.reg_advance,
- 0x04);
- else
- err = sx150x_i2c_write(chip->client,
- chip->dev_cfg->pri.x123.reg_advance,
- 0x00);
- if (err < 0)
- return err;
-
- err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
- pdata->io_pullup_ena);
- if (err < 0)
- return err;
-
- err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
- pdata->io_pulldn_ena);
- if (err < 0)
- return err;
-
- if (chip->dev_cfg->model == SX150X_789) {
- err = sx150x_init_io(chip,
- chip->dev_cfg->pri.x789.reg_polarity,
- pdata->io_polarity);
- if (err < 0)
- return err;
- } else if (chip->dev_cfg->model == SX150X_456) {
- /* Set all pins to work in normal mode */
- err = sx150x_init_io(chip,
- chip->dev_cfg->pri.x456.reg_pld_mode,
- 0);
- if (err < 0)
- return err;
- } else {
- /* Set all pins to work in normal mode */
- err = sx150x_init_io(chip,
- chip->dev_cfg->pri.x123.reg_pld_mode,
- 0);
- if (err < 0)
- return err;
- }
-
-
- if (pdata->oscio_is_gpo)
- sx150x_set_oscio(chip, 0);
-
- return err;
-}
-
-static int sx150x_install_irq_chip(struct sx150x_chip *chip,
- int irq_summary,
- int irq_base)
-{
- int err;
-
- chip->irq_summary = irq_summary;
- chip->irq_base = irq_base;
-
- /* Add gpio chip to irq subsystem */
- err = gpiochip_irqchip_add(&chip->gpio_chip,
- &chip->irq_chip, chip->irq_base,
- handle_edge_irq, IRQ_TYPE_EDGE_BOTH);
- if (err) {
- dev_err(&chip->client->dev,
- "could not connect irqchip to gpiochip\n");
- return err;
- }
-
- err = devm_request_threaded_irq(&chip->client->dev,
- irq_summary, NULL, sx150x_irq_thread_fn,
- IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING,
- chip->irq_chip.name, chip);
- if (err < 0) {
- chip->irq_summary = -1;
- chip->irq_base = -1;
- }
-
- return err;
-}
-
-static int sx150x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WRITE_WORD_DATA;
- struct sx150x_platform_data *pdata;
- struct sx150x_chip *chip;
- int rc;
-
- pdata = dev_get_platdata(&client->dev);
- if (!pdata)
- return -EINVAL;
-
- if (!i2c_check_functionality(client->adapter, i2c_funcs))
- return -ENOSYS;
-
- chip = devm_kzalloc(&client->dev,
- sizeof(struct sx150x_chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- sx150x_init_chip(chip, client, id->driver_data, pdata);
- rc = sx150x_init_hw(chip, pdata);
- if (rc < 0)
- return rc;
-
- rc = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
- if (rc)
- return rc;
-
- if (pdata->irq_summary >= 0) {
- rc = sx150x_install_irq_chip(chip,
- pdata->irq_summary,
- pdata->irq_base);
- if (rc < 0)
- return rc;
- }
-
- i2c_set_clientdata(client, chip);
-
- return 0;
-}
-
-static struct i2c_driver sx150x_driver = {
- .driver = {
- .name = "sx150x",
- .of_match_table = of_match_ptr(sx150x_of_match),
- },
- .probe = sx150x_probe,
- .id_table = sx150x_id,
-};
-
-static int __init sx150x_init(void)
-{
- return i2c_add_driver(&sx150x_driver);
-}
-subsys_initcall(sx150x_init);
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index d6e21f1a70a9..be97101c2c9a 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -337,21 +337,20 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
return ret;
}
- ret = gpiochip_irqchip_add(&tc3589x_gpio->chip,
- &tc3589x_gpio_irq_chip,
- 0,
- handle_simple_irq,
- IRQ_TYPE_NONE);
+ ret = gpiochip_irqchip_add_nested(&tc3589x_gpio->chip,
+ &tc3589x_gpio_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
if (ret) {
dev_err(&pdev->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
- gpiochip_set_chained_irqchip(&tc3589x_gpio->chip,
- &tc3589x_gpio_irq_chip,
- irq,
- NULL);
+ gpiochip_set_nested_irqchip(&tc3589x_gpio->chip,
+ &tc3589x_gpio_irq_chip,
+ irq);
platform_set_drvdata(pdev, tc3589x_gpio);
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 3edb09cb9ee0..521fbe338589 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -283,8 +283,4 @@ static struct platform_driver vf610_gpio_driver = {
.probe = vf610_gpio_probe,
};
-static int __init gpio_vf610_init(void)
-{
- return platform_driver_register(&vf610_gpio_driver);
-}
-device_initcall(gpio_vf610_init);
+builtin_platform_driver(vf610_gpio_driver);
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
index d0ddba7a9d08..34baee5b1dd6 100644
--- a/drivers/gpio/gpio-wcove.c
+++ b/drivers/gpio/gpio-wcove.c
@@ -426,8 +426,8 @@ static int wcove_gpio_probe(struct platform_device *pdev)
return ret;
}
- ret = gpiochip_irqchip_add(&wg->chip, &wcove_irqchip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
+ ret = gpiochip_irqchip_add_nested(&wg->chip, &wcove_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "Failed to add irqchip: %d\n", ret);
return ret;
@@ -446,6 +446,8 @@ static int wcove_gpio_probe(struct platform_device *pdev)
return ret;
}
+ gpiochip_set_nested_irqchip(&wg->chip, &wcove_irqchip, virq);
+
return 0;
}
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 72a4b326fd0d..a3faefa44f68 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -468,7 +468,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
int ret;
memset(&args, 0, sizeof(args));
- ret = acpi_node_get_property_reference(fwnode, propname, index, &args);
+ ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
+ &args);
if (ret) {
struct acpi_device *adev = to_acpi_device_node(fwnode);
@@ -483,13 +484,13 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
* 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];
- }
+ if (args.nargs != 3)
+ return -EPROTO;
+
+ lookup->index = args.args[0];
+ lookup->pin_index = args.args[1];
+ lookup->active_low = !!args.args[2];
+
return 0;
}
@@ -859,6 +860,77 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
}
}
+static struct gpio_desc *acpi_gpiochip_parse_own_gpio(
+ struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode,
+ const char **name, unsigned int *lflags, unsigned int *dflags)
+{
+ struct gpio_chip *chip = achip->chip;
+ struct gpio_desc *desc;
+ u32 gpios[2];
+ int ret;
+
+ *lflags = 0;
+ *dflags = 0;
+ *name = NULL;
+
+ ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
+ ARRAY_SIZE(gpios));
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ desc = gpiochip_get_desc(chip, ret);
+ if (IS_ERR(desc))
+ return desc;
+
+ if (gpios[1])
+ *lflags |= GPIO_ACTIVE_LOW;
+
+ if (fwnode_property_present(fwnode, "input"))
+ *dflags |= GPIOD_IN;
+ else if (fwnode_property_present(fwnode, "output-low"))
+ *dflags |= GPIOD_OUT_LOW;
+ else if (fwnode_property_present(fwnode, "output-high"))
+ *dflags |= GPIOD_OUT_HIGH;
+ else
+ return ERR_PTR(-EINVAL);
+
+ fwnode_property_read_string(fwnode, "line-name", name);
+
+ return desc;
+}
+
+static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
+{
+ struct gpio_chip *chip = achip->chip;
+ struct fwnode_handle *fwnode;
+
+ device_for_each_child_node(chip->parent, fwnode) {
+ unsigned int lflags, dflags;
+ struct gpio_desc *desc;
+ const char *name;
+ int ret;
+
+ if (!fwnode_property_present(fwnode, "gpio-hog"))
+ continue;
+
+ desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name,
+ &lflags, &dflags);
+ if (IS_ERR(desc))
+ continue;
+
+ ret = gpiod_hog(desc, name, lflags, dflags);
+ if (ret) {
+ dev_err(chip->parent, "Failed to hog GPIO\n");
+ fwnode_handle_put(fwnode);
+ return;
+ }
+ }
+}
+
void acpi_gpiochip_add(struct gpio_chip *chip)
{
struct acpi_gpio_chip *acpi_gpio;
@@ -889,7 +961,11 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
return;
}
+ if (!chip->names)
+ devprop_gpiochip_set_names(chip);
+
acpi_gpiochip_request_regions(acpi_gpio);
+ acpi_gpiochip_scan_gpios(acpi_gpio);
acpi_walk_dep_device_list(handle);
}
@@ -918,18 +994,27 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
kfree(acpi_gpio);
}
-static unsigned int acpi_gpio_package_count(const union acpi_object *obj)
+static int acpi_gpio_package_count(const union acpi_object *obj)
{
const union acpi_object *element = obj->package.elements;
const union acpi_object *end = element + obj->package.count;
unsigned int count = 0;
while (element < end) {
- if (element->type == ACPI_TYPE_LOCAL_REFERENCE)
+ switch (element->type) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ element += 3;
+ /* Fallthrough */
+ case ACPI_TYPE_INTEGER:
+ element++;
count++;
+ break;
- element++;
+ default:
+ return -EPROTO;
+ }
}
+
return count;
}
diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c
new file mode 100644
index 000000000000..27f383bda7d9
--- /dev/null
+++ b/drivers/gpio/gpiolib-devprop.c
@@ -0,0 +1,67 @@
+/*
+ * Device property helpers for GPIO chips.
+ *
+ * Copyright (C) 2016, 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/property.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+#include "gpiolib.h"
+
+/**
+ * devprop_gpiochip_set_names - Set GPIO line names using device properties
+ * @chip: GPIO chip whose lines should be named, if possible
+ *
+ * Looks for device property "gpio-line-names" and if it exists assigns
+ * GPIO line names for the chip. The memory allocated for the assigned
+ * names belong to the underlying firmware node and should not be released
+ * by the caller.
+ */
+void devprop_gpiochip_set_names(struct gpio_chip *chip)
+{
+ struct gpio_device *gdev = chip->gpiodev;
+ const char **names;
+ int ret, i;
+
+ if (!chip->parent) {
+ dev_warn(&gdev->dev, "GPIO chip parent is NULL\n");
+ return;
+ }
+
+ ret = device_property_read_string_array(chip->parent, "gpio-line-names",
+ NULL, 0);
+ if (ret < 0)
+ return;
+
+ if (ret != gdev->ngpio) {
+ dev_warn(chip->parent,
+ "names %d do not match number of GPIOs %d\n", ret,
+ gdev->ngpio);
+ return;
+ }
+
+ names = kcalloc(gdev->ngpio, sizeof(*names), GFP_KERNEL);
+ if (!names)
+ return;
+
+ ret = device_property_read_string_array(chip->parent, "gpio-line-names",
+ names, gdev->ngpio);
+ if (ret < 0) {
+ dev_warn(chip->parent, "failed to read GPIO line names\n");
+ kfree(names);
+ return;
+ }
+
+ for (i = 0; i < gdev->ngpio; i++)
+ gdev->descs[i].name = names[i];
+
+ kfree(names);
+}
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 193f15d50bba..92b185f19232 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -226,51 +226,6 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
}
/**
- * of_gpiochip_set_names() - set up the names of the lines
- * @chip: GPIO chip whose lines should be named, if possible
- */
-static void of_gpiochip_set_names(struct gpio_chip *gc)
-{
- struct gpio_device *gdev = gc->gpiodev;
- struct device_node *np = gc->of_node;
- int i;
- int nstrings;
-
- nstrings = of_property_count_strings(np, "gpio-line-names");
- if (nstrings <= 0)
- /* Lines names not present */
- return;
-
- /* This is normally not what you want */
- if (gdev->ngpio != nstrings)
- dev_info(&gdev->dev, "gpio-line-names specifies %d line "
- "names but there are %d lines on the chip\n",
- nstrings, gdev->ngpio);
-
- /*
- * Make sure to not index beyond the end of the number of descriptors
- * of the GPIO device.
- */
- for (i = 0; i < gdev->ngpio; i++) {
- const char *name;
- int ret;
-
- ret = of_property_read_string_index(np,
- "gpio-line-names",
- i,
- &name);
- if (ret) {
- if (ret != -ENODATA)
- dev_err(&gdev->dev,
- "unable to name line %d: %d\n",
- i, ret);
- break;
- }
- gdev->descs[i].name = name;
- }
-}
-
-/**
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
*
@@ -296,8 +251,10 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
continue;
ret = gpiod_hog(desc, name, lflags, dflags);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(np);
return ret;
+ }
}
return 0;
@@ -526,7 +483,7 @@ int of_gpiochip_add(struct gpio_chip *chip)
/* If the chip defines names itself, these take precedence */
if (!chip->names)
- of_gpiochip_set_names(chip);
+ devprop_gpiochip_set_names(chip);
of_node_get(chip->of_node);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 868128a676ba..f4c26c7826cd 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -986,7 +986,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp)
return -ENODEV;
get_device(&gdev->dev);
filp->private_data = gdev;
- return 0;
+
+ return nonseekable_open(inode, filp);
}
/**
@@ -1011,7 +1012,7 @@ static const struct file_operations gpio_fileops = {
.release = gpio_chrdev_release,
.open = gpio_chrdev_open,
.owner = THIS_MODULE,
- .llseek = noop_llseek,
+ .llseek = no_llseek,
.unlocked_ioctl = gpio_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = gpio_ioctl_compat,
@@ -1512,7 +1513,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
}
/**
- * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
+ * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
* @gpiochip: the gpiochip to set the irqchip chain to
* @irqchip: the irqchip to chain to the gpiochip
* @parent_irq: the irq number corresponding to the parent IRQ for this
@@ -1521,10 +1522,10 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
* coming out of the gpiochip. If the interrupt is nested rather than
* cascaded, pass NULL in this handler argument
*/
-void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
- struct irq_chip *irqchip,
- int parent_irq,
- irq_flow_handler_t parent_handler)
+static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ int parent_irq,
+ irq_flow_handler_t parent_handler)
{
unsigned int offset;
@@ -1548,7 +1549,7 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
irq_set_chained_handler_and_data(parent_irq, parent_handler,
gpiochip);
- gpiochip->irq_parent = parent_irq;
+ gpiochip->irq_chained_parent = parent_irq;
}
/* Set the parent IRQ for all affected IRQs */
@@ -1559,9 +1560,48 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
parent_irq);
}
}
+
+/**
+ * gpiochip_set_chained_irqchip() - connects a chained irqchip to a gpiochip
+ * @gpiochip: the gpiochip to set the irqchip chain to
+ * @irqchip: the irqchip to chain to the gpiochip
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
+ * chained irqchip
+ * @parent_handler: the parent interrupt handler for the accumulated IRQ
+ * coming out of the gpiochip. If the interrupt is nested rather than
+ * cascaded, pass NULL in this handler argument
+ */
+void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ int parent_irq,
+ irq_flow_handler_t parent_handler)
+{
+ gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
+ parent_handler);
+}
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
/**
+ * gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip
+ * @gpiochip: the gpiochip to set the irqchip nested handler to
+ * @irqchip: the irqchip to nest to the gpiochip
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
+ * nested irqchip
+ */
+void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ int parent_irq)
+{
+ if (!gpiochip->irq_nested) {
+ chip_err(gpiochip, "tried to nest a chained gpiochip\n");
+ return;
+ }
+ gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
+ NULL);
+}
+EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
+
+/**
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
* @d: the irqdomain used by this irqchip
* @irq: the global irq number used by this GPIO irqchip irq
@@ -1583,8 +1623,8 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
*/
irq_set_lockdep_class(irq, chip->lock_key);
irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
- /* Chips that can sleep need nested thread handlers */
- if (chip->can_sleep && !chip->irq_not_threaded)
+ /* Chips that use nested thread handlers have them marked */
+ if (chip->irq_nested)
irq_set_nested_thread(irq, 1);
irq_set_noprobe(irq);
@@ -1602,7 +1642,7 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
{
struct gpio_chip *chip = d->host_data;
- if (chip->can_sleep)
+ if (chip->irq_nested)
irq_set_nested_thread(irq, 0);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
@@ -1657,9 +1697,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
acpi_gpiochip_free_interrupts(gpiochip);
- if (gpiochip->irq_parent) {
- irq_set_chained_handler(gpiochip->irq_parent, NULL);
- irq_set_handler_data(gpiochip->irq_parent, NULL);
+ if (gpiochip->irq_chained_parent) {
+ irq_set_chained_handler(gpiochip->irq_chained_parent, NULL);
+ irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
}
/* Remove all IRQ mappings and delete the domain */
@@ -1683,7 +1723,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
}
/**
- * gpiochip_irqchip_add() - adds an irqchip to a gpiochip
+ * _gpiochip_irqchip_add() - adds an irqchip to a gpiochip
* @gpiochip: the gpiochip to add the irqchip to
* @irqchip: the irqchip to add to the gpiochip
* @first_irq: if not dynamically assigned, the base (first) IRQ to
@@ -1691,6 +1731,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
* @handler: the irq handler to use (often a predefined irq core function)
* @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
* to have the core avoid setting up any default type in the hardware.
+ * @nested: whether this is a nested irqchip calling handle_nested_irq()
+ * in its IRQ handler
* @lock_key: lockdep class
*
* This function closely associates a certain irqchip with a certain
@@ -1712,6 +1754,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
unsigned int first_irq,
irq_flow_handler_t handler,
unsigned int type,
+ bool nested,
struct lock_class_key *lock_key)
{
struct device_node *of_node;
@@ -1726,6 +1769,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
pr_err("missing gpiochip .dev parent pointer\n");
return -EINVAL;
}
+ gpiochip->irq_nested = nested;
of_node = gpiochip->parent->of_node;
#ifdef CONFIG_OF_GPIO
/*
@@ -2223,6 +2267,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
struct gpio_chip *gc = desc->gdev->chip;
+ int val = !!value;
int ret;
/* GPIOs used for IRQs shall not be set as output */
@@ -2242,7 +2287,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
goto set_output_value;
}
/* Emulate open drain by not actively driving the line high */
- if (value)
+ if (val)
return gpiod_direction_input(desc);
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
@@ -2253,7 +2298,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
goto set_output_value;
}
/* Emulate open source by not actively driving the line low */
- if (!value)
+ if (!val)
return gpiod_direction_input(desc);
} else {
/* Make sure to disable open drain/source hardware, if any */
@@ -2271,10 +2316,10 @@ set_output_value:
return -EIO;
}
- ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value);
+ ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), val);
if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
- trace_gpio_value(desc_to_gpio(desc), 0, value);
+ trace_gpio_value(desc_to_gpio(desc), 0, val);
trace_gpio_direction(desc_to_gpio(desc), 0, ret);
return ret;
}
@@ -2314,6 +2359,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
VALIDATE_DESC(desc);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
+ else
+ value = !!value;
return _gpiod_direction_output_raw(desc, value);
}
EXPORT_SYMBOL_GPL(gpiod_direction_output);
@@ -2758,6 +2805,15 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
}
set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+
+ /*
+ * If the consumer has not set up a label (such as when the
+ * IRQ is referenced from .to_irq()) we set up a label here
+ * so it is clear this is used as an interrupt.
+ */
+ if (!desc->label)
+ desc_set_label(desc, "interrupt");
+
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
@@ -2772,10 +2828,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
*/
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
- if (offset >= chip->ngpio)
+ struct gpio_desc *desc;
+
+ desc = gpiochip_get_desc(chip, offset);
+ if (IS_ERR(desc))
return;
- clear_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
+ clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
+
+ /* If we only had this marking, erase it */
+ if (desc->label && !strcmp(desc->label, "interrupt"))
+ desc_set_label(desc, NULL);
}
EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
@@ -3170,7 +3233,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
/* Process flags */
if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
status = gpiod_direction_output(desc,
- dflags & GPIOD_FLAGS_BIT_DIR_VAL);
+ !!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
else
status = gpiod_direction_input(desc);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 346fbda39220..d10eaf520860 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -209,6 +209,8 @@ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
return desc - &desc->gdev->descs[0];
}
+void devprop_gpiochip_set_names(struct gpio_chip *chip);
+
/* With descriptor prefix */
#define gpiod_emerg(desc, fmt, ...) \
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 483059a22b1b..ebfe8404c25f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -12,6 +12,7 @@ menuconfig DRM
select I2C
select I2C_ALGOBIT
select DMA_SHARED_BUFFER
+ select SYNC_FILE
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
@@ -33,6 +34,20 @@ config DRM_DP_AUX_CHARDEV
read and write values to arbitrary DPCD registers on the DP aux
channel.
+config DRM_DEBUG_MM
+ bool "Insert extra checks and debug info into the DRM range managers"
+ default n
+ depends on DRM=y
+ depends on STACKTRACE_SUPPORT
+ select STACKDEPOT
+ help
+ Enable allocation tracking of memory manager and leak detection on
+ shutdown.
+
+ Recommended for driver developers only.
+
+ If in doubt, say "N".
+
config DRM_KMS_HELPER
tristate
depends on DRM
@@ -223,6 +238,12 @@ source "drivers/gpu/drm/hisilicon/Kconfig"
source "drivers/gpu/drm/mediatek/Kconfig"
+source "drivers/gpu/drm/zte/Kconfig"
+
+source "drivers/gpu/drm/mxsfb/Kconfig"
+
+source "drivers/gpu/drm/meson/Kconfig"
+
# Keep legacy drivers last
menuconfig DRM_LEGACY
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 25c720454017..b9ae4280de9d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -9,13 +9,14 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
- drm_info.o drm_debugfs.o drm_encoder_slave.o \
+ drm_info.o drm_encoder_slave.o \
drm_trace_points.o drm_global.o drm_prime.o \
drm_rect.o drm_vma_manager.o drm_flip_work.o \
drm_modeset_lock.o drm_atomic.o drm_bridge.o \
drm_framebuffer.o drm_connector.o drm_blend.o \
drm_encoder.o drm_mode_object.o drm_property.o \
- drm_plane.o drm_color_mgmt.o
+ drm_plane.o drm_color_mgmt.o drm_print.o \
+ drm_dumb_buffers.o drm_mode_config.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -23,6 +24,7 @@ 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-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
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 \
@@ -79,6 +81,7 @@ obj-$(CONFIG_DRM_TEGRA) += tegra/
obj-$(CONFIG_DRM_STI) += sti/
obj-$(CONFIG_DRM_IMX) += imx/
obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
+obj-$(CONFIG_DRM_MESON) += meson/
obj-y += i2c/
obj-y += panel/
obj-y += bridge/
@@ -86,3 +89,5 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
obj-$(CONFIG_DRM_ARCPGU)+= arc/
obj-y += hisilicon/
+obj-$(CONFIG_DRM_ZTE) += zte/
+obj-$(CONFIG_DRM_MXSFB) += mxsfb/
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 248a05d02917..41bd2bf28f4c 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \
amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
- amdgpu_gtt_mgr.o
+ amdgpu_gtt_mgr.o amdgpu_vram_mgr.o
# add asic specific block
amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
diff --git a/drivers/gpu/drm/amd/amdgpu/ObjectID.h b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
index b8d66670bb17..06192698bd96 100644
--- a/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+++ b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
@@ -90,7 +90,6 @@
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25
#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27
-#define ENCODER_OBJECT_ID_VIRTUAL 0x28
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
@@ -120,7 +119,6 @@
#define CONNECTOR_OBJECT_ID_eDP 0x14
#define CONNECTOR_OBJECT_ID_MXM 0x15
#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
-#define CONNECTOR_OBJECT_ID_VIRTUAL 0x17
/* deleted */
@@ -149,7 +147,6 @@
#define GRAPH_OBJECT_ENUM_ID5 0x05
#define GRAPH_OBJECT_ENUM_ID6 0x06
#define GRAPH_OBJECT_ENUM_ID7 0x07
-#define GRAPH_OBJECT_ENUM_VIRTUAL 0x08
/****************************************************/
/* Graphics Object ID Bit definition */
@@ -411,10 +408,6 @@
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
-#define ENCODER_VIRTUAL_ENUM_VIRTUAL ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
- GRAPH_OBJECT_ENUM_VIRTUAL << ENUM_ID_SHIFT |\
- ENCODER_OBJECT_ID_VIRTUAL << OBJECT_ID_SHIFT)
-
/****************************************************/
/* Connector Object ID definition - Shared with BIOS */
/****************************************************/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 05c2850c04b0..63208e5c1588 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -34,7 +34,7 @@
#include <linux/kref.h>
#include <linux/interval_tree.h>
#include <linux/hashtable.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <ttm/ttm_bo_api.h>
#include <ttm/ttm_bo_driver.h>
@@ -53,7 +53,11 @@
#include "amdgpu_ucode.h"
#include "amdgpu_ttm.h"
#include "amdgpu_gds.h"
+#include "amdgpu_sync.h"
+#include "amdgpu_ring.h"
+#include "amdgpu_vm.h"
#include "amd_powerplay.h"
+#include "amdgpu_dpm.h"
#include "amdgpu_acp.h"
#include "gpu_scheduler.h"
@@ -88,15 +92,16 @@ extern int amdgpu_vm_debug;
extern int amdgpu_sched_jobs;
extern int amdgpu_sched_hw_submission;
extern int amdgpu_powerplay;
-extern int amdgpu_powercontainment;
+extern int amdgpu_no_evict;
+extern int amdgpu_direct_gma_size;
extern unsigned amdgpu_pcie_gen_cap;
extern unsigned amdgpu_pcie_lane_cap;
extern unsigned amdgpu_cg_mask;
extern unsigned amdgpu_pg_mask;
extern char *amdgpu_disable_cu;
-extern int amdgpu_sclk_deep_sleep_en;
extern char *amdgpu_virtual_display;
extern unsigned amdgpu_pp_feature_mask;
+extern int amdgpu_vram_page_split;
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
@@ -107,12 +112,6 @@ extern unsigned amdgpu_pp_feature_mask;
#define AMDGPUFB_CONN_LIMIT 4
#define AMDGPU_BIOS_NUM_SCRATCH 8
-/* max number of rings */
-#define AMDGPU_MAX_RINGS 16
-#define AMDGPU_MAX_GFX_RINGS 1
-#define AMDGPU_MAX_COMPUTE_RINGS 8
-#define AMDGPU_MAX_VCE_RINGS 3
-
/* max number of IP instances */
#define AMDGPU_MAX_SDMA_INSTANCES 2
@@ -152,8 +151,6 @@ extern unsigned amdgpu_pp_feature_mask;
struct amdgpu_device;
struct amdgpu_ib;
-struct amdgpu_vm;
-struct amdgpu_ring;
struct amdgpu_cs_parser;
struct amdgpu_job;
struct amdgpu_irq_src;
@@ -198,21 +195,38 @@ int amdgpu_wait_for_idle(struct amdgpu_device *adev,
bool amdgpu_is_idle(struct amdgpu_device *adev,
enum amd_ip_block_type block_type);
+#define AMDGPU_MAX_IP_NUM 16
+
+struct amdgpu_ip_block_status {
+ bool valid;
+ bool sw;
+ bool hw;
+ bool late_initialized;
+ bool hang;
+};
+
struct amdgpu_ip_block_version {
- enum amd_ip_block_type type;
- u32 major;
- u32 minor;
- u32 rev;
+ const enum amd_ip_block_type type;
+ const u32 major;
+ const u32 minor;
+ const u32 rev;
const struct amd_ip_funcs *funcs;
};
+struct amdgpu_ip_block {
+ struct amdgpu_ip_block_status status;
+ const struct amdgpu_ip_block_version *version;
+};
+
int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
enum amd_ip_block_type type,
u32 major, u32 minor);
-const struct amdgpu_ip_block_version * amdgpu_get_ip_block(
- struct amdgpu_device *adev,
- enum amd_ip_block_type type);
+struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev,
+ enum amd_ip_block_type type);
+
+int amdgpu_ip_block_add(struct amdgpu_device *adev,
+ const struct amdgpu_ip_block_version *ip_block_version);
/* provided by hw blocks that can move/clear data. e.g., gfx or sdma */
struct amdgpu_buffer_funcs {
@@ -286,47 +300,6 @@ struct amdgpu_ih_funcs {
void (*set_rptr)(struct amdgpu_device *adev);
};
-/* provided by hw blocks that expose a ring buffer for commands */
-struct amdgpu_ring_funcs {
- /* ring read/write ptr handling */
- u32 (*get_rptr)(struct amdgpu_ring *ring);
- u32 (*get_wptr)(struct amdgpu_ring *ring);
- void (*set_wptr)(struct amdgpu_ring *ring);
- /* validating and patching of IBs */
- int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
- /* command emit functions */
- void (*emit_ib)(struct amdgpu_ring *ring,
- struct amdgpu_ib *ib,
- unsigned vm_id, bool ctx_switch);
- void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
- uint64_t seq, unsigned flags);
- void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
- void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
- uint64_t pd_addr);
- void (*emit_hdp_flush)(struct amdgpu_ring *ring);
- void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
- void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
- uint32_t gds_base, uint32_t gds_size,
- uint32_t gws_base, uint32_t gws_size,
- uint32_t oa_base, uint32_t oa_size);
- /* testing functions */
- int (*test_ring)(struct amdgpu_ring *ring);
- int (*test_ib)(struct amdgpu_ring *ring, long timeout);
- /* insert NOP packets */
- void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
- /* pad the indirect buffer to the necessary number of dw */
- void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
- unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
- void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
- /* note usage for clock and power gating */
- void (*begin_use)(struct amdgpu_ring *ring);
- void (*end_use)(struct amdgpu_ring *ring);
- void (*emit_switch_buffer) (struct amdgpu_ring *ring);
- void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
- unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring);
- unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring);
-};
-
/*
* BIOS.
*/
@@ -364,47 +337,6 @@ struct amdgpu_clock {
};
/*
- * Fences.
- */
-struct amdgpu_fence_driver {
- uint64_t gpu_addr;
- volatile uint32_t *cpu_addr;
- /* sync_seq is protected by ring emission lock */
- uint32_t sync_seq;
- atomic_t last_seq;
- bool initialized;
- struct amdgpu_irq_src *irq_src;
- unsigned irq_type;
- struct timer_list fallback_timer;
- unsigned num_fences_mask;
- spinlock_t lock;
- struct fence **fences;
-};
-
-/* some special values for the owner field */
-#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
-#define AMDGPU_FENCE_OWNER_VM ((void*)1ul)
-
-#define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
-#define AMDGPU_FENCE_FLAG_INT (1 << 1)
-
-int amdgpu_fence_driver_init(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
-void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
-
-int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
- unsigned num_hw_submission);
-int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
- struct amdgpu_irq_src *irq_src,
- unsigned irq_type);
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **fence);
-void amdgpu_fence_process(struct amdgpu_ring *ring);
-int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
-unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
-
-/*
* BO.
*/
struct amdgpu_bo_list_entry {
@@ -427,7 +359,7 @@ struct amdgpu_bo_va_mapping {
struct amdgpu_bo_va {
/* protected by bo being reserved */
struct list_head bo_list;
- struct fence *last_pt_update;
+ struct dma_fence *last_pt_update;
unsigned ref_count;
/* protected by vm mutex and spinlock */
@@ -465,7 +397,6 @@ struct amdgpu_bo {
*/
struct list_head va;
/* Constant after initialization */
- struct amdgpu_device *adev;
struct drm_gem_object gem_base;
struct amdgpu_bo *parent;
struct amdgpu_bo *shadow;
@@ -544,7 +475,7 @@ struct amdgpu_sa_bo {
struct amdgpu_sa_manager *manager;
unsigned soffset;
unsigned eoffset;
- struct fence *fence;
+ struct dma_fence *fence;
};
/*
@@ -562,27 +493,6 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
int amdgpu_mode_dumb_mmap(struct drm_file *filp,
struct drm_device *dev,
uint32_t handle, uint64_t *offset_p);
-/*
- * Synchronization
- */
-struct amdgpu_sync {
- DECLARE_HASHTABLE(fences, 4);
- struct fence *last_vm_update;
-};
-
-void amdgpu_sync_create(struct amdgpu_sync *sync);
-int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
- struct fence *f);
-int amdgpu_sync_resv(struct amdgpu_device *adev,
- struct amdgpu_sync *sync,
- struct reservation_object *resv,
- void *owner);
-struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
- struct amdgpu_ring *ring);
-struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
-void amdgpu_sync_free(struct amdgpu_sync *sync);
-int amdgpu_sync_init(void);
-void amdgpu_sync_fini(void);
int amdgpu_fence_slab_init(void);
void amdgpu_fence_slab_fini(void);
@@ -704,10 +614,10 @@ struct amdgpu_flip_work {
uint64_t base;
struct drm_pending_vblank_event *event;
struct amdgpu_bo *old_abo;
- struct fence *excl;
+ struct dma_fence *excl;
unsigned shared_count;
- struct fence **shared;
- struct fence_cb cb;
+ struct dma_fence **shared;
+ struct dma_fence_cb cb;
bool async;
};
@@ -724,14 +634,6 @@ struct amdgpu_ib {
uint32_t flags;
};
-enum amdgpu_ring_type {
- AMDGPU_RING_TYPE_GFX,
- AMDGPU_RING_TYPE_COMPUTE,
- AMDGPU_RING_TYPE_SDMA,
- AMDGPU_RING_TYPE_UVD,
- AMDGPU_RING_TYPE_VCE
-};
-
extern const struct amd_sched_backend_ops amdgpu_sched_ops;
int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
@@ -743,214 +645,7 @@ void amdgpu_job_free_resources(struct amdgpu_job *job);
void amdgpu_job_free(struct amdgpu_job *job);
int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
struct amd_sched_entity *entity, void *owner,
- struct fence **f);
-
-struct amdgpu_ring {
- struct amdgpu_device *adev;
- const struct amdgpu_ring_funcs *funcs;
- struct amdgpu_fence_driver fence_drv;
- struct amd_gpu_scheduler sched;
-
- struct amdgpu_bo *ring_obj;
- volatile uint32_t *ring;
- unsigned rptr_offs;
- unsigned wptr;
- unsigned wptr_old;
- unsigned ring_size;
- unsigned max_dw;
- int count_dw;
- uint64_t gpu_addr;
- uint32_t align_mask;
- uint32_t ptr_mask;
- bool ready;
- u32 nop;
- u32 idx;
- u32 me;
- u32 pipe;
- u32 queue;
- struct amdgpu_bo *mqd_obj;
- u32 doorbell_index;
- bool use_doorbell;
- unsigned wptr_offs;
- unsigned fence_offs;
- uint64_t current_ctx;
- enum amdgpu_ring_type type;
- char name[16];
- unsigned cond_exe_offs;
- u64 cond_exe_gpu_addr;
- volatile u32 *cond_exe_cpu_addr;
-#if defined(CONFIG_DEBUG_FS)
- struct dentry *ent;
-#endif
-};
-
-/*
- * VM
- */
-
-/* maximum number of VMIDs */
-#define AMDGPU_NUM_VM 16
-
-/* Maximum number of PTEs the hardware can write with one command */
-#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF
-
-/* number of entries in page table */
-#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
-
-/* PTBs (Page Table Blocks) need to be aligned to 32K */
-#define AMDGPU_VM_PTB_ALIGN_SIZE 32768
-
-/* LOG2 number of continuous pages for the fragment field */
-#define AMDGPU_LOG2_PAGES_PER_FRAG 4
-
-#define AMDGPU_PTE_VALID (1 << 0)
-#define AMDGPU_PTE_SYSTEM (1 << 1)
-#define AMDGPU_PTE_SNOOPED (1 << 2)
-
-/* VI only */
-#define AMDGPU_PTE_EXECUTABLE (1 << 4)
-
-#define AMDGPU_PTE_READABLE (1 << 5)
-#define AMDGPU_PTE_WRITEABLE (1 << 6)
-
-#define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7)
-
-/* 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_list_entry entry;
- uint64_t addr;
- uint64_t shadow_addr;
-};
-
-struct amdgpu_vm {
- /* tree of virtual addresses mapped */
- struct rb_root va;
-
- /* protecting invalidated */
- spinlock_t status_lock;
-
- /* BOs moved, but not yet updated in the PT */
- struct list_head invalidated;
-
- /* BOs cleared in the PT because of a move */
- struct list_head cleared;
-
- /* BO mappings freed, but not yet updated in the PT */
- struct list_head freed;
-
- /* contains the page directory */
- struct amdgpu_bo *page_directory;
- unsigned max_pde_used;
- struct fence *page_directory_fence;
- uint64_t last_eviction_counter;
-
- /* array of page tables, one for each page directory entry */
- struct amdgpu_vm_pt *page_tables;
-
- /* for id and flush management per ring */
- struct amdgpu_vm_id *ids[AMDGPU_MAX_RINGS];
-
- /* protecting freed */
- spinlock_t freed_lock;
-
- /* Scheduler entity for page table updates */
- struct amd_sched_entity entity;
-
- /* client id */
- u64 client_id;
-};
-
-struct amdgpu_vm_id {
- struct list_head list;
- struct fence *first;
- struct amdgpu_sync active;
- struct fence *last_flush;
- atomic64_t owner;
-
- uint64_t pd_gpu_addr;
- /* last flushed PD/PT update */
- struct fence *flushed_updates;
-
- uint32_t current_gpu_reset_count;
-
- uint32_t gds_base;
- uint32_t gds_size;
- uint32_t gws_base;
- uint32_t gws_size;
- uint32_t oa_base;
- uint32_t oa_size;
-};
-
-struct amdgpu_vm_manager {
- /* Handling of VMIDs */
- struct mutex lock;
- unsigned num_ids;
- struct list_head ids_lru;
- struct amdgpu_vm_id ids[AMDGPU_NUM_VM];
-
- /* Handling of VM fences */
- u64 fence_context;
- unsigned seqno[AMDGPU_MAX_RINGS];
-
- uint32_t max_pfn;
- /* vram base address for page table entry */
- u64 vram_base_offset;
- /* is vm enabled? */
- bool enabled;
- /* vm pte handling */
- const struct amdgpu_vm_pte_funcs *vm_pte_funcs;
- struct amdgpu_ring *vm_pte_rings[AMDGPU_MAX_RINGS];
- unsigned vm_pte_num_rings;
- atomic_t vm_pte_next_ring;
- /* client id counter */
- atomic64_t client_counter;
-};
-
-void amdgpu_vm_manager_init(struct amdgpu_device *adev);
-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);
-void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
- struct list_head *validated,
- struct amdgpu_bo_list_entry *entry);
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- struct list_head *duplicates);
-void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
- struct amdgpu_vm *vm);
-int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
- struct amdgpu_sync *sync, struct fence *fence,
- struct amdgpu_job *job);
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
-void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
-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,
- bool clear);
-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);
+ struct dma_fence **f);
/*
* context related structures
@@ -958,7 +653,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
struct amdgpu_ctx_ring {
uint64_t sequence;
- struct fence **fences;
+ struct dma_fence **fences;
struct amd_sched_entity entity;
};
@@ -967,7 +662,7 @@ struct amdgpu_ctx {
struct amdgpu_device *adev;
unsigned reset_counter;
spinlock_t ring_lock;
- struct fence **fences;
+ struct dma_fence **fences;
struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS];
bool preamble_presented;
};
@@ -983,8 +678,8 @@ struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id);
int amdgpu_ctx_put(struct amdgpu_ctx *ctx);
uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,
- struct fence *fence);
-struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
+ struct dma_fence *fence);
+struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
struct amdgpu_ring *ring, uint64_t seq);
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
@@ -1094,6 +789,16 @@ struct amdgpu_scratch {
/*
* GFX configurations
*/
+#define AMDGPU_GFX_MAX_SE 4
+#define AMDGPU_GFX_MAX_SH_PER_SE 2
+
+struct amdgpu_rb_config {
+ uint32_t rb_backend_disable;
+ uint32_t user_rb_backend_disable;
+ uint32_t raster_config;
+ uint32_t raster_config_1;
+};
+
struct amdgpu_gca_config {
unsigned max_shader_engines;
unsigned max_tile_pipes;
@@ -1122,6 +827,8 @@ struct amdgpu_gca_config {
uint32_t tile_mode_array[32];
uint32_t macrotile_mode_array[16];
+
+ struct amdgpu_rb_config rb_config[AMDGPU_GFX_MAX_SE][AMDGPU_GFX_MAX_SH_PER_SE];
};
struct amdgpu_cu_info {
@@ -1134,6 +841,9 @@ struct amdgpu_gfx_funcs {
/* get the gpu clock counter */
uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev);
void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance);
+ void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields);
+ void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t start, uint32_t size, uint32_t *dst);
+ void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst);
};
struct amdgpu_gfx {
@@ -1182,23 +892,13 @@ struct amdgpu_gfx {
int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
unsigned size, struct amdgpu_ib *ib);
void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
- struct fence *f);
+ struct dma_fence *f);
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
- struct amdgpu_ib *ib, struct fence *last_vm_update,
- struct amdgpu_job *job, struct fence **f);
+ struct amdgpu_ib *ib, struct dma_fence *last_vm_update,
+ struct amdgpu_job *job, struct dma_fence **f);
int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
-int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
-void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
-void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
-void amdgpu_ring_commit(struct amdgpu_ring *ring);
-void amdgpu_ring_undo(struct amdgpu_ring *ring);
-int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
- unsigned ring_size, u32 nop, u32 align_mask,
- struct amdgpu_irq_src *irq_src, unsigned irq_type,
- enum amdgpu_ring_type ring_type);
-void amdgpu_ring_fini(struct amdgpu_ring *ring);
/*
* CS.
@@ -1226,7 +926,7 @@ struct amdgpu_cs_parser {
struct amdgpu_bo_list *bo_list;
struct amdgpu_bo_list_entry vm_pd;
struct list_head validated;
- struct fence *fence;
+ struct dma_fence *fence;
uint64_t bytes_moved_threshold;
uint64_t bytes_moved;
struct amdgpu_bo_list_entry *evictable;
@@ -1246,7 +946,7 @@ struct amdgpu_job {
struct amdgpu_ring *ring;
struct amdgpu_sync sync;
struct amdgpu_ib *ibs;
- struct fence *fence; /* the hw fence */
+ struct dma_fence *fence; /* the hw fence */
uint32_t preamble_status;
uint32_t num_ibs;
void *owner;
@@ -1295,354 +995,6 @@ struct amdgpu_wb {
int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb);
void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb);
-
-
-enum amdgpu_int_thermal_type {
- THERMAL_TYPE_NONE,
- THERMAL_TYPE_EXTERNAL,
- THERMAL_TYPE_EXTERNAL_GPIO,
- THERMAL_TYPE_RV6XX,
- THERMAL_TYPE_RV770,
- THERMAL_TYPE_ADT7473_WITH_INTERNAL,
- THERMAL_TYPE_EVERGREEN,
- THERMAL_TYPE_SUMO,
- THERMAL_TYPE_NI,
- THERMAL_TYPE_SI,
- THERMAL_TYPE_EMC2103_WITH_INTERNAL,
- THERMAL_TYPE_CI,
- THERMAL_TYPE_KV,
-};
-
-enum amdgpu_dpm_auto_throttle_src {
- AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL,
- AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL
-};
-
-enum amdgpu_dpm_event_src {
- AMDGPU_DPM_EVENT_SRC_ANALOG = 0,
- AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1,
- AMDGPU_DPM_EVENT_SRC_DIGITAL = 2,
- AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
- AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
-};
-
-#define AMDGPU_MAX_VCE_LEVELS 6
-
-enum amdgpu_vce_level {
- AMDGPU_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */
- AMDGPU_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */
- AMDGPU_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */
- AMDGPU_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
- AMDGPU_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */
- AMDGPU_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
-};
-
-struct amdgpu_ps {
- u32 caps; /* vbios flags */
- u32 class; /* vbios flags */
- u32 class2; /* vbios flags */
- /* UVD clocks */
- u32 vclk;
- u32 dclk;
- /* VCE clocks */
- u32 evclk;
- u32 ecclk;
- bool vce_active;
- enum amdgpu_vce_level vce_level;
- /* asic priv */
- void *ps_priv;
-};
-
-struct amdgpu_dpm_thermal {
- /* thermal interrupt work */
- struct work_struct work;
- /* low temperature threshold */
- int min_temp;
- /* high temperature threshold */
- int max_temp;
- /* was last interrupt low to high or high to low */
- bool high_to_low;
- /* interrupt source */
- struct amdgpu_irq_src irq;
-};
-
-enum amdgpu_clk_action
-{
- AMDGPU_SCLK_UP = 1,
- AMDGPU_SCLK_DOWN
-};
-
-struct amdgpu_blacklist_clocks
-{
- u32 sclk;
- u32 mclk;
- enum amdgpu_clk_action action;
-};
-
-struct amdgpu_clock_and_voltage_limits {
- u32 sclk;
- u32 mclk;
- u16 vddc;
- u16 vddci;
-};
-
-struct amdgpu_clock_array {
- u32 count;
- u32 *values;
-};
-
-struct amdgpu_clock_voltage_dependency_entry {
- u32 clk;
- u16 v;
-};
-
-struct amdgpu_clock_voltage_dependency_table {
- u32 count;
- struct amdgpu_clock_voltage_dependency_entry *entries;
-};
-
-union amdgpu_cac_leakage_entry {
- struct {
- u16 vddc;
- u32 leakage;
- };
- struct {
- u16 vddc1;
- u16 vddc2;
- u16 vddc3;
- };
-};
-
-struct amdgpu_cac_leakage_table {
- u32 count;
- union amdgpu_cac_leakage_entry *entries;
-};
-
-struct amdgpu_phase_shedding_limits_entry {
- u16 voltage;
- u32 sclk;
- u32 mclk;
-};
-
-struct amdgpu_phase_shedding_limits_table {
- u32 count;
- struct amdgpu_phase_shedding_limits_entry *entries;
-};
-
-struct amdgpu_uvd_clock_voltage_dependency_entry {
- u32 vclk;
- u32 dclk;
- u16 v;
-};
-
-struct amdgpu_uvd_clock_voltage_dependency_table {
- u8 count;
- struct amdgpu_uvd_clock_voltage_dependency_entry *entries;
-};
-
-struct amdgpu_vce_clock_voltage_dependency_entry {
- u32 ecclk;
- u32 evclk;
- u16 v;
-};
-
-struct amdgpu_vce_clock_voltage_dependency_table {
- u8 count;
- struct amdgpu_vce_clock_voltage_dependency_entry *entries;
-};
-
-struct amdgpu_ppm_table {
- u8 ppm_design;
- u16 cpu_core_number;
- u32 platform_tdp;
- u32 small_ac_platform_tdp;
- u32 platform_tdc;
- u32 small_ac_platform_tdc;
- u32 apu_tdp;
- u32 dgpu_tdp;
- u32 dgpu_ulv_power;
- u32 tj_max;
-};
-
-struct amdgpu_cac_tdp_table {
- u16 tdp;
- u16 configurable_tdp;
- u16 tdc;
- u16 battery_power_limit;
- u16 small_power_limit;
- u16 low_cac_leakage;
- u16 high_cac_leakage;
- u16 maximum_power_delivery_limit;
-};
-
-struct amdgpu_dpm_dynamic_state {
- struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk;
- struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk;
- struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk;
- struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk;
- struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk;
- struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table;
- struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table;
- struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table;
- struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table;
- struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk;
- struct amdgpu_clock_array valid_sclk_values;
- struct amdgpu_clock_array valid_mclk_values;
- struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc;
- struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac;
- u32 mclk_sclk_ratio;
- u32 sclk_mclk_delta;
- u16 vddc_vddci_delta;
- u16 min_vddc_for_pcie_gen2;
- struct amdgpu_cac_leakage_table cac_leakage_table;
- struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table;
- struct amdgpu_ppm_table *ppm_table;
- struct amdgpu_cac_tdp_table *cac_tdp_table;
-};
-
-struct amdgpu_dpm_fan {
- u16 t_min;
- u16 t_med;
- u16 t_high;
- u16 pwm_min;
- u16 pwm_med;
- u16 pwm_high;
- u8 t_hyst;
- u32 cycle_delay;
- u16 t_max;
- u8 control_mode;
- u16 default_max_fan_pwm;
- u16 default_fan_output_sensitivity;
- u16 fan_output_sensitivity;
- bool ucode_fan_control;
-};
-
-enum amdgpu_pcie_gen {
- AMDGPU_PCIE_GEN1 = 0,
- AMDGPU_PCIE_GEN2 = 1,
- AMDGPU_PCIE_GEN3 = 2,
- AMDGPU_PCIE_GEN_INVALID = 0xffff
-};
-
-enum amdgpu_dpm_forced_level {
- AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
- AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
- AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
- AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
-};
-
-struct amdgpu_vce_state {
- /* vce clocks */
- u32 evclk;
- u32 ecclk;
- /* gpu clocks */
- u32 sclk;
- u32 mclk;
- u8 clk_idx;
- u8 pstate;
-};
-
-struct amdgpu_dpm_funcs {
- int (*get_temperature)(struct amdgpu_device *adev);
- int (*pre_set_power_state)(struct amdgpu_device *adev);
- int (*set_power_state)(struct amdgpu_device *adev);
- void (*post_set_power_state)(struct amdgpu_device *adev);
- void (*display_configuration_changed)(struct amdgpu_device *adev);
- u32 (*get_sclk)(struct amdgpu_device *adev, bool low);
- u32 (*get_mclk)(struct amdgpu_device *adev, bool low);
- void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps);
- void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m);
- int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level);
- bool (*vblank_too_short)(struct amdgpu_device *adev);
- void (*powergate_uvd)(struct amdgpu_device *adev, bool gate);
- void (*powergate_vce)(struct amdgpu_device *adev, bool gate);
- void (*enable_bapm)(struct amdgpu_device *adev, bool enable);
- void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode);
- u32 (*get_fan_control_mode)(struct amdgpu_device *adev);
- int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed);
- int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed);
- int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask);
- int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
- int (*get_sclk_od)(struct amdgpu_device *adev);
- int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
- int (*get_mclk_od)(struct amdgpu_device *adev);
- int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value);
-};
-
-struct amdgpu_dpm {
- struct amdgpu_ps *ps;
- /* number of valid power states */
- int num_ps;
- /* current power state that is active */
- struct amdgpu_ps *current_ps;
- /* requested power state */
- struct amdgpu_ps *requested_ps;
- /* boot up power state */
- struct amdgpu_ps *boot_ps;
- /* default uvd power state */
- struct amdgpu_ps *uvd_ps;
- /* vce requirements */
- struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS];
- enum amdgpu_vce_level vce_level;
- enum amd_pm_state_type state;
- enum amd_pm_state_type user_state;
- u32 platform_caps;
- u32 voltage_response_time;
- u32 backbias_response_time;
- void *priv;
- u32 new_active_crtcs;
- int new_active_crtc_count;
- u32 current_active_crtcs;
- int current_active_crtc_count;
- struct amdgpu_dpm_dynamic_state dyn_state;
- struct amdgpu_dpm_fan fan;
- u32 tdp_limit;
- u32 near_tdp_limit;
- u32 near_tdp_limit_adjusted;
- u32 sq_ramping_threshold;
- u32 cac_leakage;
- u16 tdp_od_limit;
- u32 tdp_adjustment;
- u16 load_line_slope;
- bool power_control;
- bool ac_power;
- /* special states active */
- bool thermal_active;
- bool uvd_active;
- bool vce_active;
- /* thermal handling */
- struct amdgpu_dpm_thermal thermal;
- /* forced levels */
- enum amdgpu_dpm_forced_level forced_level;
-};
-
-struct amdgpu_pm {
- struct mutex mutex;
- u32 current_sclk;
- u32 current_mclk;
- u32 default_sclk;
- u32 default_mclk;
- struct amdgpu_i2c_chan *i2c_bus;
- /* internal thermal controller on rv6xx+ */
- enum amdgpu_int_thermal_type int_thermal_type;
- struct device *int_hwmon_dev;
- /* fan control parameters */
- bool no_fan;
- u8 fan_pulses_per_revolution;
- u8 fan_min_rpm;
- 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;
- const struct amdgpu_dpm_funcs *funcs;
- uint32_t pcie_gen_mask;
- uint32_t pcie_mlw_mask;
- struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
-};
-
void amdgpu_get_pcie_info(struct amdgpu_device *adev);
/*
@@ -1863,6 +1215,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp);
int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
@@ -1940,14 +1294,6 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
-struct amdgpu_ip_block_status {
- bool valid;
- bool sw;
- bool hw;
- bool late_initialized;
- bool hang;
-};
-
struct amdgpu_device {
struct device *dev;
struct drm_device *ddev;
@@ -1986,6 +1332,7 @@ struct amdgpu_device {
/* BIOS */
uint8_t *bios;
+ uint32_t bios_size;
bool is_atom_bios;
struct amdgpu_bo *stollen_vga_memory;
uint32_t bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
@@ -2103,9 +1450,8 @@ struct amdgpu_device {
/* GDS */
struct amdgpu_gds gds;
- const struct amdgpu_ip_block_version *ip_blocks;
+ struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
int num_ip_blocks;
- struct amdgpu_ip_block_status *ip_block_status;
struct mutex mn_lock;
DECLARE_HASHTABLE(mn_hash, 7);
@@ -2128,6 +1474,11 @@ struct amdgpu_device {
};
+static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
+{
+ return container_of(bdev, struct amdgpu_device, mman.bdev);
+}
+
bool amdgpu_device_is_px(struct drm_device *dev);
int amdgpu_device_init(struct amdgpu_device *adev,
struct drm_device *ddev,
@@ -2279,15 +1630,12 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
#define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
#define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o))
-#define amdgpu_ring_get_emit_ib_size(r) (r)->funcs->get_emit_ib_size((r))
-#define amdgpu_ring_get_dma_frame_size(r) (r)->funcs->get_dma_frame_size((r))
#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
#define amdgpu_display_set_vga_render_state(adev, r) (adev)->mode_info.funcs->set_vga_render_state((adev), (r))
#define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc))
#define amdgpu_display_vblank_wait(adev, crtc) (adev)->mode_info.funcs->vblank_wait((adev), (crtc))
-#define amdgpu_display_is_display_hung(adev) (adev)->mode_info.funcs->is_display_hung((adev))
#define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l))
#define amdgpu_display_backlight_get_level(adev, e) (adev)->mode_info.funcs->backlight_get_level((e))
#define amdgpu_display_hpd_sense(adev, h) (adev)->mode_info.funcs->hpd_sense((adev), (h))
@@ -2302,108 +1650,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
#define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b))
#define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
-#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
-#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
-#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev))
-#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev))
-#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps))
-#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev))
-#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e))
#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
#define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance))
-
-#define amdgpu_dpm_read_sensor(adev, idx, value) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \
- -EINVAL)
-
-#define amdgpu_dpm_get_temperature(adev) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \
- (adev)->pm.funcs->get_temperature((adev)))
-
-#define amdgpu_dpm_set_fan_control_mode(adev, m) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \
- (adev)->pm.funcs->set_fan_control_mode((adev), (m)))
-
-#define amdgpu_dpm_get_fan_control_mode(adev) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \
- (adev)->pm.funcs->get_fan_control_mode((adev)))
-
-#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
- (adev)->pm.funcs->set_fan_speed_percent((adev), (s)))
-
-#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
- (adev)->pm.funcs->get_fan_speed_percent((adev), (s)))
-
-#define amdgpu_dpm_get_sclk(adev, l) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \
- (adev)->pm.funcs->get_sclk((adev), (l)))
-
-#define amdgpu_dpm_get_mclk(adev, l) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \
- (adev)->pm.funcs->get_mclk((adev), (l)))
-
-
-#define amdgpu_dpm_force_performance_level(adev, l) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \
- (adev)->pm.funcs->force_performance_level((adev), (l)))
-
-#define amdgpu_dpm_powergate_uvd(adev, g) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \
- (adev)->pm.funcs->powergate_uvd((adev), (g)))
-
-#define amdgpu_dpm_powergate_vce(adev, g) \
- ((adev)->pp_enabled ? \
- (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \
- (adev)->pm.funcs->powergate_vce((adev), (g)))
-
-#define amdgpu_dpm_get_current_power_state(adev) \
- (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_get_performance_level(adev) \
- (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_get_pp_num_states(adev, data) \
- (adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
-
-#define amdgpu_dpm_get_pp_table(adev, table) \
- (adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)
-
-#define amdgpu_dpm_set_pp_table(adev, buf, size) \
- (adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)
-
-#define amdgpu_dpm_print_clock_levels(adev, type, buf) \
- (adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)
-
-#define amdgpu_dpm_force_clock_level(adev, type, level) \
- (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)
-
-#define amdgpu_dpm_get_sclk_od(adev) \
- (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_set_sclk_od(adev, value) \
- (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)
-
-#define amdgpu_dpm_get_mclk_od(adev) \
- ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle))
-
-#define amdgpu_dpm_set_mclk_od(adev, value) \
- ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))
-
-#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \
- (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
-
#define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
/* Common functions */
@@ -2434,8 +1682,6 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base);
void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc);
void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size);
-u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev);
-int amdgpu_ttm_global_init(struct amdgpu_device *adev);
int amdgpu_ttm_init(struct amdgpu_device *adev);
void amdgpu_ttm_fini(struct amdgpu_device *adev);
void amdgpu_program_register_sequence(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index 2057683f7b59..06879d1dcabd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -265,14 +265,14 @@ static int acp_hw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- const struct amdgpu_ip_block_version *ip_version =
+ const struct amdgpu_ip_block *ip_block =
amdgpu_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP);
- if (!ip_version)
+ if (!ip_block)
return -EINVAL;
r = amd_acp_hw_init(adev->acp.cgs_device,
- ip_version->major, ip_version->minor);
+ ip_block->version->major, ip_block->version->minor);
/* -ENODEV means board uses AZ rather than ACP */
if (r == -ENODEV)
return 0;
@@ -459,7 +459,7 @@ static int acp_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs acp_ip_funcs = {
+static const struct amd_ip_funcs acp_ip_funcs = {
.name = "acp_ip",
.early_init = acp_early_init,
.late_init = NULL,
@@ -475,3 +475,12 @@ const struct amd_ip_funcs acp_ip_funcs = {
.set_clockgating_state = acp_set_clockgating_state,
.set_powergating_state = acp_set_powergating_state,
};
+
+const struct amdgpu_ip_block_version acp_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_ACP,
+ .major = 2,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &acp_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
index 8a396313c86f..a288ce25c176 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
@@ -37,6 +37,6 @@ struct amdgpu_acp {
struct acp_pm_domain *acp_genpd;
};
-extern const struct amd_ip_funcs acp_ip_funcs;
+extern const struct amdgpu_ip_block_version acp_ip_block;
#endif /* __AMDGPU_ACP_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 8e6bf548d689..56a86dd5789e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1115,49 +1115,6 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
return 0;
}
-uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev)
-{
- GET_ENGINE_CLOCK_PS_ALLOCATION args;
- int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
-
- amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
- return le32_to_cpu(args.ulReturnEngineClock);
-}
-
-uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev)
-{
- GET_MEMORY_CLOCK_PS_ALLOCATION args;
- int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
-
- amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
- return le32_to_cpu(args.ulReturnMemoryClock);
-}
-
-void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev,
- uint32_t eng_clock)
-{
- SET_ENGINE_CLOCK_PS_ALLOCATION args;
- int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
-
- args.ulTargetEngineClock = cpu_to_le32(eng_clock); /* 10 khz */
-
- amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev,
- uint32_t mem_clock)
-{
- SET_MEMORY_CLOCK_PS_ALLOCATION args;
- int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
-
- if (adev->flags & AMD_IS_APU)
- return;
-
- args.ulTargetMemoryClock = cpu_to_le32(mem_clock); /* 10 khz */
-
- amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
u32 eng_clock, u32 mem_clock)
{
@@ -1256,45 +1213,6 @@ int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *
return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage);
}
-void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,
- u16 voltage_level,
- u8 voltage_type)
-{
- union set_voltage args;
- int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
- u8 frev, crev, volt_index = voltage_level;
-
- if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
- return;
-
- /* 0xff01 is a flag rather then an actual voltage */
- if (voltage_level == 0xff01)
- return;
-
- switch (crev) {
- case 1:
- args.v1.ucVoltageType = voltage_type;
- args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
- args.v1.ucVoltageIndex = volt_index;
- break;
- case 2:
- args.v2.ucVoltageType = voltage_type;
- args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
- args.v2.usVoltageLevel = cpu_to_le16(voltage_level);
- break;
- case 3:
- args.v3.ucVoltageType = voltage_type;
- args.v3.ucVoltageMode = ATOM_SET_VOLTAGE;
- args.v3.usVoltageLevel = cpu_to_le16(voltage_level);
- break;
- default:
- DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
- return;
- }
-
- amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
int amdgpu_atombios_get_leakage_id_from_vbios(struct amdgpu_device *adev,
u16 *leakage_id)
{
@@ -1784,6 +1702,19 @@ void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev)
WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]);
}
+void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
+ bool hung)
+{
+ u32 tmp = RREG32(mmBIOS_SCRATCH_3);
+
+ if (hung)
+ tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+ else
+ tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+
+ WREG32(mmBIOS_SCRATCH_3, tmp);
+}
+
/* Atom needs data in little endian format
* so swap as appropriate when copying data to
* or from atom. Note that atom operates on
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
index 17356151db38..70e9acef5d9c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
@@ -163,16 +163,6 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
bool strobe_mode,
struct atom_mpll_param *mpll_param);
-uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev);
-uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev);
-void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev,
- uint32_t eng_clock);
-void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev,
- uint32_t mem_clock);
-void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,
- u16 voltage_level,
- u8 voltage_type);
-
void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
u32 eng_clock, u32 mem_clock);
@@ -206,6 +196,8 @@ void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock);
void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev);
void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev);
void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev);
+void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
+ bool hung);
void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
index 345305235349..cc97eee93226 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
@@ -33,7 +33,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
{
unsigned long start_jiffies;
unsigned long end_jiffies;
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
int i, r;
start_jiffies = jiffies;
@@ -43,17 +43,17 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
false);
if (r)
goto exit_do_move;
- r = fence_wait(fence, false);
+ r = dma_fence_wait(fence, false);
if (r)
goto exit_do_move;
- fence_put(fence);
+ dma_fence_put(fence);
}
end_jiffies = jiffies;
r = jiffies_to_msecs(end_jiffies - start_jiffies);
exit_do_move:
if (fence)
- fence_put(fence);
+ dma_fence_put(fence);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 2b6afe123f3d..4f973a9c7b87 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -70,10 +70,11 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
return false;
}
adev->bios = kmalloc(size, GFP_KERNEL);
- if (adev->bios == NULL) {
+ if (!adev->bios) {
iounmap(bios);
return false;
}
+ adev->bios_size = size;
memcpy_fromio(adev->bios, bios, size);
iounmap(bios);
return true;
@@ -103,6 +104,7 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
pci_unmap_rom(adev->pdev, bios);
return false;
}
+ adev->bios_size = size;
memcpy_fromio(adev->bios, bios, size);
pci_unmap_rom(adev->pdev, bios);
return true;
@@ -135,6 +137,7 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
DRM_ERROR("no memory to allocate for BIOS\n");
return false;
}
+ adev->bios_size = len;
/* read complete BIOS */
return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
@@ -159,6 +162,7 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
if (adev->bios == NULL) {
return false;
}
+ adev->bios_size = size;
return true;
}
@@ -273,6 +277,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
kfree(adev->bios);
return false;
}
+ adev->bios_size = size;
return true;
}
#else
@@ -334,6 +339,7 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
}
adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
+ adev->bios_size = vhdr->ImageLength;
ret = !!adev->bios;
out_unmap:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
index 662976292535..9ada56c16a58 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -146,7 +146,8 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device,
switch(type) {
case CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB:
case CGS_GPU_MEM_TYPE__VISIBLE_FB:
- flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+ flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
domain = AMDGPU_GEM_DOMAIN_VRAM;
if (max_offset > adev->mc.real_vram_size)
return -EINVAL;
@@ -157,7 +158,8 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device,
break;
case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB:
case CGS_GPU_MEM_TYPE__INVISIBLE_FB:
- flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+ flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
domain = AMDGPU_GEM_DOMAIN_VRAM;
if (adev->mc.visible_vram_size < adev->mc.real_vram_size) {
place.fpfn =
@@ -240,7 +242,7 @@ static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h
r = amdgpu_bo_reserve(obj, false);
if (unlikely(r != 0))
return r;
- r = amdgpu_bo_pin_restricted(obj, AMDGPU_GEM_DOMAIN_GTT,
+ r = amdgpu_bo_pin_restricted(obj, obj->prefered_domains,
min_offset, max_offset, mcaddr);
amdgpu_bo_unreserve(obj);
return r;
@@ -624,11 +626,11 @@ static int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device,
int i, r = -1;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type) {
- r = adev->ip_blocks[i].funcs->set_clockgating_state(
+ if (adev->ip_blocks[i].version->type == block_type) {
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state(
(void *)adev,
state);
break;
@@ -645,11 +647,11 @@ static int amdgpu_cgs_set_powergating_state(struct cgs_device *cgs_device,
int i, r = -1;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type) {
- r = adev->ip_blocks[i].funcs->set_powergating_state(
+ if (adev->ip_blocks[i].version->type == block_type) {
+ r = adev->ip_blocks[i].version->funcs->set_powergating_state(
(void *)adev,
state);
break;
@@ -685,15 +687,21 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
result = AMDGPU_UCODE_ID_CP_MEC1;
break;
case CGS_UCODE_ID_CP_MEC_JT2:
- if (adev->asic_type == CHIP_TONGA || adev->asic_type == CHIP_POLARIS11
- || adev->asic_type == CHIP_POLARIS10)
- result = AMDGPU_UCODE_ID_CP_MEC2;
- else
+ /* for VI. JT2 should be the same as JT1, because:
+ 1, MEC2 and MEC1 use exactly same FW.
+ 2, JT2 is not pached but JT1 is.
+ */
+ if (adev->asic_type >= CHIP_TOPAZ)
result = AMDGPU_UCODE_ID_CP_MEC1;
+ else
+ result = AMDGPU_UCODE_ID_CP_MEC2;
break;
case CGS_UCODE_ID_RLC_G:
result = AMDGPU_UCODE_ID_RLC_G;
break;
+ case CGS_UCODE_ID_STORAGE:
+ result = AMDGPU_UCODE_ID_STORAGE;
+ break;
default:
DRM_ERROR("Firmware type not supported\n");
}
@@ -715,7 +723,7 @@ static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
enum cgs_ucode_id type)
{
CGS_FUNC_ADEV;
- uint16_t fw_version;
+ uint16_t fw_version = 0;
switch (type) {
case CGS_UCODE_ID_SDMA0:
@@ -745,9 +753,11 @@ static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
case CGS_UCODE_ID_RLC_G:
fw_version = adev->gfx.rlc_fw_version;
break;
+ case CGS_UCODE_ID_STORAGE:
+ break;
default:
DRM_ERROR("firmware type %d do not have version\n", type);
- fw_version = 0;
+ break;
}
return fw_version;
}
@@ -776,12 +786,18 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
(type == CGS_UCODE_ID_CP_MEC_JT2)) {
- gpu_addr += le32_to_cpu(header->jt_offset) << 2;
+ gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
data_size = le32_to_cpu(header->jt_size) << 2;
}
- info->mc_addr = gpu_addr;
+
+ info->kptr = ucode->kaddr;
info->image_size = data_size;
+ info->mc_addr = gpu_addr;
info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
+
+ if (CGS_UCODE_ID_CP_MEC == type)
+ info->image_size = (header->jt_offset) << 2;
+
info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
} else {
@@ -860,6 +876,12 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
return 0;
}
+static int amdgpu_cgs_is_virtualization_enabled(void *cgs_device)
+{
+ CGS_FUNC_ADEV;
+ return amdgpu_sriov_vf(adev);
+}
+
static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device,
struct cgs_system_info *sys_info)
{
@@ -1213,6 +1235,7 @@ static const struct cgs_ops amdgpu_cgs_ops = {
amdgpu_cgs_notify_dpm_enabled,
amdgpu_cgs_call_acpi_method,
amdgpu_cgs_query_system_info,
+ amdgpu_cgs_is_virtualization_enabled
};
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 086aa5c9c634..8d1cf2d3e663 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
.force = amdgpu_connector_dvi_force,
};
-static struct drm_encoder *
-amdgpu_connector_virtual_encoder(struct drm_connector *connector)
-{
- int enc_id = connector->encoder_ids[0];
- struct drm_encoder *encoder;
- int i;
- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- if (connector->encoder_ids[i] == 0)
- break;
-
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
- if (!encoder)
- continue;
-
- if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
- return encoder;
- }
-
- /* pick the first one */
- if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
- return NULL;
-}
-
-static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector)
-{
- struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
-
- if (encoder) {
- amdgpu_connector_add_common_modes(encoder, connector);
- }
-
- return 0;
-}
-
-static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- return MODE_OK;
-}
-
-static int
-amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode)
-{
- return 0;
-}
-
-static enum drm_connector_status
-
-amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
-static int
-amdgpu_connector_virtual_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val)
-{
- return 0;
-}
-
-static void amdgpu_connector_virtual_force(struct drm_connector *connector)
-{
- return;
-}
-
-static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = {
- .get_modes = amdgpu_connector_virtual_get_modes,
- .mode_valid = amdgpu_connector_virtual_mode_valid,
- .best_encoder = amdgpu_connector_virtual_encoder,
-};
-
-static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = {
- .dpms = amdgpu_connector_virtual_dpms,
- .detect = amdgpu_connector_virtual_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = amdgpu_connector_virtual_set_property,
- .destroy = amdgpu_connector_destroy,
- .force = amdgpu_connector_virtual_force,
-};
-
void
amdgpu_connector_add(struct amdgpu_device *adev,
uint32_t connector_id,
@@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev,
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
break;
- case DRM_MODE_CONNECTOR_VIRTUAL:
- amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
- if (!amdgpu_dig_connector)
- goto failed;
- amdgpu_connector->con_priv = amdgpu_dig_connector;
- drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type);
- drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs);
- subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
- break;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 82dc8d20e28a..29d6d84d1c28 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -355,6 +355,7 @@ static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev,
static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
struct amdgpu_bo *bo)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
u64 initial_bytes_moved;
uint32_t domain;
int r;
@@ -372,9 +373,9 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
retry:
amdgpu_ttm_placement_from_domain(bo, domain);
- initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
+ initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
- p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
+ p->bytes_moved += atomic64_read(&adev->num_bytes_moved) -
initial_bytes_moved;
if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
@@ -387,9 +388,9 @@ retry:
/* Last resort, try to evict something from the current working set */
static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
- struct amdgpu_bo_list_entry *lobj)
+ struct amdgpu_bo *validated)
{
- uint32_t domain = lobj->robj->allowed_domains;
+ uint32_t domain = validated->allowed_domains;
int r;
if (!p->evictable)
@@ -400,11 +401,12 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
struct amdgpu_bo_list_entry *candidate = p->evictable;
struct amdgpu_bo *bo = candidate->robj;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
u64 initial_bytes_moved;
uint32_t other;
/* If we reached our current BO we can forget it */
- if (candidate == lobj)
+ if (candidate->robj == validated)
break;
other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
@@ -420,9 +422,9 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
/* Good we can try to move this BO somewhere else */
amdgpu_ttm_placement_from_domain(bo, other);
- initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
+ initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
- p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
+ p->bytes_moved += atomic64_read(&adev->num_bytes_moved) -
initial_bytes_moved;
if (unlikely(r))
@@ -437,6 +439,23 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
return false;
}
+static int amdgpu_cs_validate(void *param, struct amdgpu_bo *bo)
+{
+ struct amdgpu_cs_parser *p = param;
+ int r;
+
+ do {
+ r = amdgpu_cs_bo_validate(p, bo);
+ } while (r == -ENOMEM && amdgpu_cs_try_evict(p, bo));
+ if (r)
+ return r;
+
+ if (bo->shadow)
+ r = amdgpu_cs_bo_validate(p, bo->shadow);
+
+ return r;
+}
+
static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
struct list_head *validated)
{
@@ -464,18 +483,10 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
if (p->evictable == lobj)
p->evictable = NULL;
- do {
- r = amdgpu_cs_bo_validate(p, bo);
- } while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj));
+ r = amdgpu_cs_validate(p, bo);
if (r)
return r;
- if (bo->shadow) {
- r = amdgpu_cs_bo_validate(p, bo);
- if (r)
- return r;
- }
-
if (binding_userptr) {
drm_free_large(lobj->user_pages);
lobj->user_pages = NULL;
@@ -594,14 +605,19 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
list_splice(&need_pages, &p->validated);
}
- amdgpu_vm_get_pt_bos(p->adev, &fpriv->vm, &duplicates);
-
p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev);
p->bytes_moved = 0;
p->evictable = list_last_entry(&p->validated,
struct amdgpu_bo_list_entry,
tv.head);
+ r = amdgpu_vm_validate_pt_bos(p->adev, &fpriv->vm,
+ amdgpu_cs_validate, p);
+ if (r) {
+ DRM_ERROR("amdgpu_vm_validate_pt_bos() failed.\n");
+ goto error_validate;
+ }
+
r = amdgpu_cs_list_validate(p, &duplicates);
if (r) {
DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
@@ -720,7 +736,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
ttm_eu_backoff_reservation(&parser->ticket,
&parser->validated);
}
- fence_put(parser->fence);
+ dma_fence_put(parser->fence);
if (parser->ctx)
amdgpu_ctx_put(parser->ctx);
@@ -757,7 +773,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
if (p->bo_list) {
for (i = 0; i < p->bo_list->num_entries; i++) {
- struct fence *f;
+ struct dma_fence *f;
/* ignore duplicates */
bo = p->bo_list->array[i].robj;
@@ -807,13 +823,14 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
/* Only for UVD/VCE VM emulation */
if (ring->funcs->parse_cs) {
- p->job->vm = NULL;
for (i = 0; i < p->job->num_ibs; i++) {
r = amdgpu_ring_parse_cs(ring, p, i);
if (r)
return r;
}
- } else {
+ }
+
+ if (p->job->vm) {
p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
r = amdgpu_bo_vm_update_pte(p, vm);
@@ -824,16 +841,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
return amdgpu_cs_sync_rings(p);
}
-static int amdgpu_cs_handle_lockup(struct amdgpu_device *adev, int r)
-{
- if (r == -EDEADLK) {
- r = amdgpu_gpu_reset(adev);
- if (!r)
- r = -EAGAIN;
- }
- return r;
-}
-
static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
struct amdgpu_cs_parser *parser)
{
@@ -902,7 +909,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
offset = ((uint64_t)m->it.start) * AMDGPU_GPU_PAGE_SIZE;
kptr += chunk_ib->va_start - offset;
- r = amdgpu_ib_get(adev, NULL, chunk_ib->ib_bytes, ib);
+ r = amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib);
if (r) {
DRM_ERROR("Failed to get ib !\n");
return r;
@@ -917,9 +924,9 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
return r;
}
- ib->gpu_addr = chunk_ib->va_start;
}
+ ib->gpu_addr = chunk_ib->va_start;
ib->length_dw = chunk_ib->ib_bytes / 4;
ib->flags = chunk_ib->flags;
j++;
@@ -927,8 +934,8 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
/* UVD & VCE fw doesn't support user fences */
if (parser->job->uf_addr && (
- parser->job->ring->type == AMDGPU_RING_TYPE_UVD ||
- parser->job->ring->type == AMDGPU_RING_TYPE_VCE))
+ parser->job->ring->funcs->type == AMDGPU_RING_TYPE_UVD ||
+ parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE))
return -EINVAL;
return 0;
@@ -957,7 +964,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
for (j = 0; j < num_deps; ++j) {
struct amdgpu_ring *ring;
struct amdgpu_ctx *ctx;
- struct fence *fence;
+ struct dma_fence *fence;
r = amdgpu_cs_get_ring(adev, deps[j].ip_type,
deps[j].ip_instance,
@@ -979,7 +986,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
} else if (fence) {
r = amdgpu_sync_fence(adev, &p->job->sync,
fence);
- fence_put(fence);
+ dma_fence_put(fence);
amdgpu_ctx_put(ctx);
if (r)
return r;
@@ -1009,7 +1016,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
job->owner = p->filp;
job->fence_ctx = entity->fence_context;
- p->fence = fence_get(&job->base.s_fence->finished);
+ p->fence = dma_fence_get(&job->base.s_fence->finished);
cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence);
job->uf_sequence = cs->out.handle;
amdgpu_job_free_resources(job);
@@ -1037,29 +1044,29 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
r = amdgpu_cs_parser_init(&parser, data);
if (r) {
DRM_ERROR("Failed to initialize parser !\n");
- amdgpu_cs_parser_fini(&parser, r, false);
- r = amdgpu_cs_handle_lockup(adev, r);
- return r;
- }
- r = amdgpu_cs_parser_bos(&parser, data);
- 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);
+ goto out;
}
- if (!r) {
- r = amdgpu_cs_dependencies(adev, &parser);
- if (r)
- DRM_ERROR("Failed in the dependencies handling %d!\n", r);
+ r = amdgpu_cs_parser_bos(&parser, data);
+ if (r) {
+ if (r == -ENOMEM)
+ DRM_ERROR("Not enough memory for command submission!\n");
+ else if (r != -ERESTARTSYS)
+ DRM_ERROR("Failed to process the buffer list %d!\n", r);
+ goto out;
}
+ reserved_buffers = true;
+ r = amdgpu_cs_ib_fill(adev, &parser);
if (r)
goto out;
+ r = amdgpu_cs_dependencies(adev, &parser);
+ if (r) {
+ DRM_ERROR("Failed in the dependencies handling %d!\n", r);
+ goto out;
+ }
+
for (i = 0; i < parser.job->num_ibs; i++)
trace_amdgpu_cs(&parser, i);
@@ -1071,7 +1078,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
out:
amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
- r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
@@ -1092,7 +1098,7 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout);
struct amdgpu_ring *ring = NULL;
struct amdgpu_ctx *ctx;
- struct fence *fence;
+ struct dma_fence *fence;
long r;
r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance,
@@ -1108,8 +1114,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
if (IS_ERR(fence))
r = PTR_ERR(fence);
else if (fence) {
- r = fence_wait_timeout(fence, true, timeout);
- fence_put(fence);
+ r = dma_fence_wait_timeout(fence, true, timeout);
+ dma_fence_put(fence);
} else
r = 1;
@@ -1124,6 +1130,180 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
}
/**
+ * amdgpu_cs_get_fence - helper to get fence from drm_amdgpu_fence
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @user: drm_amdgpu_fence copied from user space
+ */
+static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev,
+ struct drm_file *filp,
+ struct drm_amdgpu_fence *user)
+{
+ struct amdgpu_ring *ring;
+ struct amdgpu_ctx *ctx;
+ struct dma_fence *fence;
+ int r;
+
+ r = amdgpu_cs_get_ring(adev, user->ip_type, user->ip_instance,
+ user->ring, &ring);
+ if (r)
+ return ERR_PTR(r);
+
+ ctx = amdgpu_ctx_get(filp->driver_priv, user->ctx_id);
+ if (ctx == NULL)
+ return ERR_PTR(-EINVAL);
+
+ fence = amdgpu_ctx_get_fence(ctx, ring, user->seq_no);
+ amdgpu_ctx_put(ctx);
+
+ return fence;
+}
+
+/**
+ * amdgpu_cs_wait_all_fence - wait on all fences to signal
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @wait: wait parameters
+ * @fences: array of drm_amdgpu_fence
+ */
+static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
+ struct drm_file *filp,
+ union drm_amdgpu_wait_fences *wait,
+ struct drm_amdgpu_fence *fences)
+{
+ uint32_t fence_count = wait->in.fence_count;
+ unsigned int i;
+ long r = 1;
+
+ for (i = 0; i < fence_count; i++) {
+ struct dma_fence *fence;
+ unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
+
+ fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
+ if (IS_ERR(fence))
+ return PTR_ERR(fence);
+ else if (!fence)
+ continue;
+
+ r = dma_fence_wait_timeout(fence, true, timeout);
+ if (r < 0)
+ return r;
+
+ if (r == 0)
+ break;
+ }
+
+ memset(wait, 0, sizeof(*wait));
+ wait->out.status = (r > 0);
+
+ return 0;
+}
+
+/**
+ * amdgpu_cs_wait_any_fence - wait on any fence to signal
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @wait: wait parameters
+ * @fences: array of drm_amdgpu_fence
+ */
+static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev,
+ struct drm_file *filp,
+ union drm_amdgpu_wait_fences *wait,
+ struct drm_amdgpu_fence *fences)
+{
+ unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
+ uint32_t fence_count = wait->in.fence_count;
+ uint32_t first = ~0;
+ struct dma_fence **array;
+ unsigned int i;
+ long r;
+
+ /* Prepare the fence array */
+ array = kcalloc(fence_count, sizeof(struct dma_fence *), GFP_KERNEL);
+
+ if (array == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < fence_count; i++) {
+ struct dma_fence *fence;
+
+ fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
+ if (IS_ERR(fence)) {
+ r = PTR_ERR(fence);
+ goto err_free_fence_array;
+ } else if (fence) {
+ array[i] = fence;
+ } else { /* NULL, the fence has been already signaled */
+ r = 1;
+ goto out;
+ }
+ }
+
+ r = dma_fence_wait_any_timeout(array, fence_count, true, timeout,
+ &first);
+ if (r < 0)
+ goto err_free_fence_array;
+
+out:
+ memset(wait, 0, sizeof(*wait));
+ wait->out.status = (r > 0);
+ wait->out.first_signaled = first;
+ /* set return value 0 to indicate success */
+ r = 0;
+
+err_free_fence_array:
+ for (i = 0; i < fence_count; i++)
+ dma_fence_put(array[i]);
+ kfree(array);
+
+ return r;
+}
+
+/**
+ * amdgpu_cs_wait_fences_ioctl - wait for multiple command submissions to finish
+ *
+ * @dev: drm device
+ * @data: data from userspace
+ * @filp: file private
+ */
+int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp)
+{
+ struct amdgpu_device *adev = dev->dev_private;
+ union drm_amdgpu_wait_fences *wait = data;
+ uint32_t fence_count = wait->in.fence_count;
+ struct drm_amdgpu_fence *fences_user;
+ struct drm_amdgpu_fence *fences;
+ int r;
+
+ /* Get the fences from userspace */
+ fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence),
+ GFP_KERNEL);
+ if (fences == NULL)
+ return -ENOMEM;
+
+ fences_user = (void __user *)(unsigned long)(wait->in.fences);
+ if (copy_from_user(fences, fences_user,
+ sizeof(struct drm_amdgpu_fence) * fence_count)) {
+ r = -EFAULT;
+ goto err_free_fences;
+ }
+
+ if (wait->in.wait_all)
+ r = amdgpu_cs_wait_all_fences(adev, filp, wait, fences);
+ else
+ r = amdgpu_cs_wait_any_fence(adev, filp, wait, fences);
+
+err_free_fences:
+ kfree(fences);
+
+ return r;
+}
+
+/**
* amdgpu_cs_find_bo_va - find bo_va for VM address
*
* @parser: command submission parser context
@@ -1196,6 +1376,15 @@ int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser)
r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
if (unlikely(r))
return r;
+
+ if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
+ continue;
+
+ bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
+ amdgpu_ttm_placement_from_domain(bo, bo->allowed_domains);
+ r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+ if (unlikely(r))
+ return r;
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index a5e2fcbef0f0..400c66ba4c6b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -35,7 +35,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx)
kref_init(&ctx->refcount);
spin_lock_init(&ctx->ring_lock);
ctx->fences = kcalloc(amdgpu_sched_jobs * AMDGPU_MAX_RINGS,
- sizeof(struct fence*), GFP_KERNEL);
+ sizeof(struct dma_fence*), GFP_KERNEL);
if (!ctx->fences)
return -ENOMEM;
@@ -55,18 +55,18 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx)
r = amd_sched_entity_init(&ring->sched, &ctx->rings[i].entity,
rq, amdgpu_sched_jobs);
if (r)
- break;
+ goto failed;
}
- if (i < adev->num_rings) {
- for (j = 0; j < i; j++)
- amd_sched_entity_fini(&adev->rings[j]->sched,
- &ctx->rings[j].entity);
- kfree(ctx->fences);
- ctx->fences = NULL;
- return r;
- }
return 0;
+
+failed:
+ for (j = 0; j < i; j++)
+ amd_sched_entity_fini(&adev->rings[j]->sched,
+ &ctx->rings[j].entity);
+ kfree(ctx->fences);
+ ctx->fences = NULL;
+ return r;
}
static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
@@ -79,7 +79,7 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
for (j = 0; j < amdgpu_sched_jobs; ++j)
- fence_put(ctx->rings[i].fences[j]);
+ dma_fence_put(ctx->rings[i].fences[j]);
kfree(ctx->fences);
ctx->fences = NULL;
@@ -241,39 +241,39 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
}
uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,
- struct fence *fence)
+ struct dma_fence *fence)
{
struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx];
uint64_t seq = cring->sequence;
unsigned idx = 0;
- struct fence *other = NULL;
+ struct dma_fence *other = NULL;
idx = seq & (amdgpu_sched_jobs - 1);
other = cring->fences[idx];
if (other) {
signed long r;
- r = fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
+ r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
if (r < 0)
DRM_ERROR("Error (%ld) waiting for fence!\n", r);
}
- fence_get(fence);
+ dma_fence_get(fence);
spin_lock(&ctx->ring_lock);
cring->fences[idx] = fence;
cring->sequence++;
spin_unlock(&ctx->ring_lock);
- fence_put(other);
+ dma_fence_put(other);
return seq;
}
-struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
- struct amdgpu_ring *ring, uint64_t seq)
+struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
+ struct amdgpu_ring *ring, uint64_t seq)
{
struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx];
- struct fence *fence;
+ struct dma_fence *fence;
spin_lock(&ctx->ring_lock);
@@ -288,7 +288,7 @@ struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
return NULL;
}
- fence = fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
+ fence = dma_fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
spin_unlock(&ctx->ring_lock);
return fence;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index e41d4baebf86..cc8aafd9cb0d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -264,7 +264,8 @@ static int amdgpu_vram_scratch_init(struct amdgpu_device *adev)
if (adev->vram_scratch.robj == NULL) {
r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE,
PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &adev->vram_scratch.robj);
if (r) {
return r;
@@ -442,13 +443,9 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev,
static void amdgpu_wb_fini(struct amdgpu_device *adev)
{
if (adev->wb.wb_obj) {
- if (!amdgpu_bo_reserve(adev->wb.wb_obj, false)) {
- amdgpu_bo_kunmap(adev->wb.wb_obj);
- amdgpu_bo_unpin(adev->wb.wb_obj);
- amdgpu_bo_unreserve(adev->wb.wb_obj);
- }
- amdgpu_bo_unref(&adev->wb.wb_obj);
- adev->wb.wb = NULL;
+ amdgpu_bo_free_kernel(&adev->wb.wb_obj,
+ &adev->wb.gpu_addr,
+ (void **)&adev->wb.wb);
adev->wb.wb_obj = NULL;
}
}
@@ -467,33 +464,14 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)
int r;
if (adev->wb.wb_obj == NULL) {
- r = amdgpu_bo_create(adev, AMDGPU_MAX_WB * 4, PAGE_SIZE, true,
- AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
- &adev->wb.wb_obj);
+ r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * 4,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ &adev->wb.wb_obj, &adev->wb.gpu_addr,
+ (void **)&adev->wb.wb);
if (r) {
dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
return r;
}
- r = amdgpu_bo_reserve(adev->wb.wb_obj, false);
- if (unlikely(r != 0)) {
- amdgpu_wb_fini(adev);
- return r;
- }
- r = amdgpu_bo_pin(adev->wb.wb_obj, AMDGPU_GEM_DOMAIN_GTT,
- &adev->wb.gpu_addr);
- if (r) {
- amdgpu_bo_unreserve(adev->wb.wb_obj);
- dev_warn(adev->dev, "(%d) pin WB bo failed\n", r);
- amdgpu_wb_fini(adev);
- return r;
- }
- r = amdgpu_bo_kmap(adev->wb.wb_obj, (void **)&adev->wb.wb);
- amdgpu_bo_unreserve(adev->wb.wb_obj);
- if (r) {
- dev_warn(adev->dev, "(%d) map WB bo failed\n", r);
- amdgpu_wb_fini(adev);
- return r;
- }
adev->wb.num_wb = AMDGPU_MAX_WB;
memset(&adev->wb.used, 0, sizeof(adev->wb.used));
@@ -1038,6 +1016,13 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev)
amdgpu_vm_block_size);
amdgpu_vm_block_size = 9;
}
+
+ if (amdgpu_vram_page_split != -1 && (amdgpu_vram_page_split < 16 ||
+ !amdgpu_check_pot_argument(amdgpu_vram_page_split))) {
+ dev_warn(adev->dev, "invalid VRAM page split (%d)\n",
+ amdgpu_vram_page_split);
+ amdgpu_vram_page_split = 1024;
+ }
}
/**
@@ -1112,11 +1097,11 @@ int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type) {
- r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
- state);
+ if (adev->ip_blocks[i].version->type == block_type) {
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+ state);
if (r)
return r;
break;
@@ -1132,11 +1117,11 @@ int amdgpu_set_powergating_state(struct amdgpu_device *adev,
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type) {
- r = adev->ip_blocks[i].funcs->set_powergating_state((void *)adev,
- state);
+ if (adev->ip_blocks[i].version->type == block_type) {
+ r = adev->ip_blocks[i].version->funcs->set_powergating_state((void *)adev,
+ state);
if (r)
return r;
break;
@@ -1151,10 +1136,10 @@ int amdgpu_wait_for_idle(struct amdgpu_device *adev,
int i, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type) {
- r = adev->ip_blocks[i].funcs->wait_for_idle((void *)adev);
+ if (adev->ip_blocks[i].version->type == block_type) {
+ r = adev->ip_blocks[i].version->funcs->wait_for_idle((void *)adev);
if (r)
return r;
break;
@@ -1170,23 +1155,22 @@ bool amdgpu_is_idle(struct amdgpu_device *adev,
int i;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].type == block_type)
- return adev->ip_blocks[i].funcs->is_idle((void *)adev);
+ if (adev->ip_blocks[i].version->type == block_type)
+ return adev->ip_blocks[i].version->funcs->is_idle((void *)adev);
}
return true;
}
-const struct amdgpu_ip_block_version * amdgpu_get_ip_block(
- struct amdgpu_device *adev,
- enum amd_ip_block_type type)
+struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev,
+ enum amd_ip_block_type type)
{
int i;
for (i = 0; i < adev->num_ip_blocks; i++)
- if (adev->ip_blocks[i].type == type)
+ if (adev->ip_blocks[i].version->type == type)
return &adev->ip_blocks[i];
return NULL;
@@ -1207,38 +1191,75 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
enum amd_ip_block_type type,
u32 major, u32 minor)
{
- const struct amdgpu_ip_block_version *ip_block;
- ip_block = amdgpu_get_ip_block(adev, type);
+ struct amdgpu_ip_block *ip_block = amdgpu_get_ip_block(adev, type);
- if (ip_block && ((ip_block->major > major) ||
- ((ip_block->major == major) &&
- (ip_block->minor >= minor))))
+ if (ip_block && ((ip_block->version->major > major) ||
+ ((ip_block->version->major == major) &&
+ (ip_block->version->minor >= minor))))
return 0;
return 1;
}
-static void amdgpu_whether_enable_virtual_display(struct amdgpu_device *adev)
+/**
+ * amdgpu_ip_block_add
+ *
+ * @adev: amdgpu_device pointer
+ * @ip_block_version: pointer to the IP to add
+ *
+ * Adds the IP block driver information to the collection of IPs
+ * on the asic.
+ */
+int amdgpu_ip_block_add(struct amdgpu_device *adev,
+ const struct amdgpu_ip_block_version *ip_block_version)
+{
+ if (!ip_block_version)
+ return -EINVAL;
+
+ adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version;
+
+ return 0;
+}
+
+static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
{
adev->enable_virtual_display = false;
if (amdgpu_virtual_display) {
struct drm_device *ddev = adev->ddev;
const char *pci_address_name = pci_name(ddev->pdev);
- char *pciaddstr, *pciaddstr_tmp, *pciaddname;
+ char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname;
pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
pciaddstr_tmp = pciaddstr;
- while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) {
+ while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) {
+ pciaddname = strsep(&pciaddname_tmp, ",");
if (!strcmp(pci_address_name, pciaddname)) {
+ long num_crtc;
+ int res = -1;
+
adev->enable_virtual_display = true;
+
+ if (pciaddname_tmp)
+ res = kstrtol(pciaddname_tmp, 10,
+ &num_crtc);
+
+ if (!res) {
+ if (num_crtc < 1)
+ num_crtc = 1;
+ if (num_crtc > 6)
+ num_crtc = 6;
+ adev->mode_info.num_crtc = num_crtc;
+ } else {
+ adev->mode_info.num_crtc = 1;
+ }
break;
}
}
- DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n",
- amdgpu_virtual_display, pci_address_name,
- adev->enable_virtual_display);
+ DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n",
+ amdgpu_virtual_display, pci_address_name,
+ adev->enable_virtual_display, adev->mode_info.num_crtc);
kfree(pciaddstr);
}
@@ -1248,7 +1269,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
{
int i, r;
- amdgpu_whether_enable_virtual_display(adev);
+ amdgpu_device_enable_virtual_display(adev);
switch (adev->asic_type) {
case CHIP_TOPAZ:
@@ -1300,33 +1321,24 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
return -EINVAL;
}
- adev->ip_block_status = kcalloc(adev->num_ip_blocks,
- sizeof(struct amdgpu_ip_block_status), GFP_KERNEL);
- if (adev->ip_block_status == NULL)
- return -ENOMEM;
-
- if (adev->ip_blocks == NULL) {
- DRM_ERROR("No IP blocks found!\n");
- return r;
- }
-
for (i = 0; i < adev->num_ip_blocks; i++) {
if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
DRM_ERROR("disabled ip block: %d\n", i);
- adev->ip_block_status[i].valid = false;
+ adev->ip_blocks[i].status.valid = false;
} else {
- if (adev->ip_blocks[i].funcs->early_init) {
- r = adev->ip_blocks[i].funcs->early_init((void *)adev);
+ if (adev->ip_blocks[i].version->funcs->early_init) {
+ r = adev->ip_blocks[i].version->funcs->early_init((void *)adev);
if (r == -ENOENT) {
- adev->ip_block_status[i].valid = false;
+ adev->ip_blocks[i].status.valid = false;
} else if (r) {
- DRM_ERROR("early_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("early_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
} else {
- adev->ip_block_status[i].valid = true;
+ adev->ip_blocks[i].status.valid = true;
}
} else {
- adev->ip_block_status[i].valid = true;
+ adev->ip_blocks[i].status.valid = true;
}
}
}
@@ -1342,22 +1354,23 @@ static int amdgpu_init(struct amdgpu_device *adev)
int i, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
+ r = adev->ip_blocks[i].version->funcs->sw_init((void *)adev);
if (r) {
- DRM_ERROR("sw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("sw_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
- adev->ip_block_status[i].sw = true;
+ adev->ip_blocks[i].status.sw = true;
/* need to do gmc hw init early so we can allocate gpu mem */
- if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
r = amdgpu_vram_scratch_init(adev);
if (r) {
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
return r;
}
- r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
+ r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
if (r) {
DRM_ERROR("hw_init %d failed %d\n", i, r);
return r;
@@ -1367,22 +1380,23 @@ static int amdgpu_init(struct amdgpu_device *adev)
DRM_ERROR("amdgpu_wb_init failed %d\n", r);
return r;
}
- adev->ip_block_status[i].hw = true;
+ adev->ip_blocks[i].status.hw = true;
}
}
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].sw)
+ if (!adev->ip_blocks[i].status.sw)
continue;
/* gmc hw init is done early */
- if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC)
continue;
- r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
+ r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
if (r) {
- DRM_ERROR("hw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("hw_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
- adev->ip_block_status[i].hw = true;
+ adev->ip_blocks[i].status.hw = true;
}
return 0;
@@ -1393,25 +1407,26 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
int i = 0, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].funcs->late_init) {
- r = adev->ip_blocks[i].funcs->late_init((void *)adev);
+ if (adev->ip_blocks[i].version->funcs->late_init) {
+ r = adev->ip_blocks[i].version->funcs->late_init((void *)adev);
if (r) {
- DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("late_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
- adev->ip_block_status[i].late_initialized = true;
+ adev->ip_blocks[i].status.late_initialized = true;
}
/* skip CG for VCE/UVD, it's handled specially */
- if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD &&
- adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) {
+ if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
+ adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
/* enable clockgating to save power */
- r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
- AMD_CG_STATE_GATE);
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+ AMD_CG_STATE_GATE);
if (r) {
DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n",
- adev->ip_blocks[i].funcs->name, r);
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
}
@@ -1426,68 +1441,77 @@ static int amdgpu_fini(struct amdgpu_device *adev)
/* need to disable SMC first */
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].hw)
+ if (!adev->ip_blocks[i].status.hw)
continue;
- if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) {
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
/* ungate blocks before hw fini so that we can shutdown the blocks safely */
- r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
- AMD_CG_STATE_UNGATE);
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+ AMD_CG_STATE_UNGATE);
if (r) {
DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
- adev->ip_blocks[i].funcs->name, r);
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
- r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+ r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
/* XXX handle errors */
if (r) {
DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
- adev->ip_blocks[i].funcs->name, r);
+ adev->ip_blocks[i].version->funcs->name, r);
}
- adev->ip_block_status[i].hw = false;
+ adev->ip_blocks[i].status.hw = false;
break;
}
}
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_status[i].hw)
+ if (!adev->ip_blocks[i].status.hw)
continue;
- if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
amdgpu_wb_fini(adev);
amdgpu_vram_scratch_fini(adev);
}
- /* ungate blocks before hw fini so that we can shutdown the blocks safely */
- r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
- AMD_CG_STATE_UNGATE);
- if (r) {
- DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
- return r;
+
+ if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
+ adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
+ /* ungate blocks before hw fini so that we can shutdown the blocks safely */
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+ AMD_CG_STATE_UNGATE);
+ if (r) {
+ DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ return r;
+ }
}
- r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+
+ r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
/* XXX handle errors */
if (r) {
- DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
}
- adev->ip_block_status[i].hw = false;
+
+ adev->ip_blocks[i].status.hw = false;
}
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_status[i].sw)
+ if (!adev->ip_blocks[i].status.sw)
continue;
- r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
+ r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
/* XXX handle errors */
if (r) {
- DRM_DEBUG("sw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_DEBUG("sw_fini of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
}
- adev->ip_block_status[i].sw = false;
- adev->ip_block_status[i].valid = false;
+ adev->ip_blocks[i].status.sw = false;
+ adev->ip_blocks[i].status.valid = false;
}
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_status[i].late_initialized)
+ if (!adev->ip_blocks[i].status.late_initialized)
continue;
- if (adev->ip_blocks[i].funcs->late_fini)
- adev->ip_blocks[i].funcs->late_fini((void *)adev);
- adev->ip_block_status[i].late_initialized = false;
+ if (adev->ip_blocks[i].version->funcs->late_fini)
+ adev->ip_blocks[i].version->funcs->late_fini((void *)adev);
+ adev->ip_blocks[i].status.late_initialized = false;
}
return 0;
@@ -1505,21 +1529,23 @@ int amdgpu_suspend(struct amdgpu_device *adev)
}
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
/* ungate blocks so that suspend can properly shut them down */
if (i != AMD_IP_BLOCK_TYPE_SMC) {
- r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
- AMD_CG_STATE_UNGATE);
+ r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+ AMD_CG_STATE_UNGATE);
if (r) {
- DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
}
}
/* XXX handle errors */
- r = adev->ip_blocks[i].funcs->suspend(adev);
+ r = adev->ip_blocks[i].version->funcs->suspend(adev);
/* XXX handle errors */
if (r) {
- DRM_ERROR("suspend of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("suspend of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
}
}
@@ -1531,11 +1557,12 @@ static int amdgpu_resume(struct amdgpu_device *adev)
int i, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- r = adev->ip_blocks[i].funcs->resume(adev);
+ r = adev->ip_blocks[i].version->funcs->resume(adev);
if (r) {
- DRM_ERROR("resume of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+ DRM_ERROR("resume of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
return r;
}
}
@@ -1586,7 +1613,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->vm_manager.vm_pte_funcs = NULL;
adev->vm_manager.vm_pte_num_rings = 0;
adev->gart.gart_funcs = NULL;
- adev->fence_context = fence_context_alloc(AMDGPU_MAX_RINGS);
+ adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
adev->smc_rreg = &amdgpu_invalid_rreg;
adev->smc_wreg = &amdgpu_invalid_wreg;
@@ -1846,8 +1873,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
amdgpu_fence_driver_fini(adev);
amdgpu_fbdev_fini(adev);
r = amdgpu_fini(adev);
- kfree(adev->ip_block_status);
- adev->ip_block_status = NULL;
adev->accel_working = false;
/* free i2c buses */
amdgpu_i2c_fini(adev);
@@ -1943,7 +1968,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
r = amdgpu_suspend(adev);
- /* evict remaining vram memory */
+ /* evict remaining vram memory
+ * This second call to evict vram is to evict the gart page table
+ * using the CPU.
+ */
amdgpu_bo_evict_vram(adev);
amdgpu_atombios_scratch_regs_save(adev);
@@ -2085,13 +2113,13 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
bool asic_hang = false;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_blocks[i].funcs->check_soft_reset)
- adev->ip_block_status[i].hang =
- adev->ip_blocks[i].funcs->check_soft_reset(adev);
- if (adev->ip_block_status[i].hang) {
- DRM_INFO("IP block:%d is hang!\n", i);
+ if (adev->ip_blocks[i].version->funcs->check_soft_reset)
+ adev->ip_blocks[i].status.hang =
+ adev->ip_blocks[i].version->funcs->check_soft_reset(adev);
+ if (adev->ip_blocks[i].status.hang) {
+ DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
asic_hang = true;
}
}
@@ -2103,11 +2131,11 @@ static int amdgpu_pre_soft_reset(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_block_status[i].hang &&
- adev->ip_blocks[i].funcs->pre_soft_reset) {
- r = adev->ip_blocks[i].funcs->pre_soft_reset(adev);
+ if (adev->ip_blocks[i].status.hang &&
+ adev->ip_blocks[i].version->funcs->pre_soft_reset) {
+ r = adev->ip_blocks[i].version->funcs->pre_soft_reset(adev);
if (r)
return r;
}
@@ -2121,13 +2149,13 @@ static bool amdgpu_need_full_reset(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) ||
- (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) ||
- (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) ||
- (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) {
- if (adev->ip_block_status[i].hang) {
+ if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
+ (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
+ (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
+ (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)) {
+ if (adev->ip_blocks[i].status.hang) {
DRM_INFO("Some block need full reset!\n");
return true;
}
@@ -2141,11 +2169,11 @@ static int amdgpu_soft_reset(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_block_status[i].hang &&
- adev->ip_blocks[i].funcs->soft_reset) {
- r = adev->ip_blocks[i].funcs->soft_reset(adev);
+ if (adev->ip_blocks[i].status.hang &&
+ adev->ip_blocks[i].version->funcs->soft_reset) {
+ r = adev->ip_blocks[i].version->funcs->soft_reset(adev);
if (r)
return r;
}
@@ -2159,11 +2187,11 @@ static int amdgpu_post_soft_reset(struct amdgpu_device *adev)
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_status[i].valid)
+ if (!adev->ip_blocks[i].status.valid)
continue;
- if (adev->ip_block_status[i].hang &&
- adev->ip_blocks[i].funcs->post_soft_reset)
- r = adev->ip_blocks[i].funcs->post_soft_reset(adev);
+ if (adev->ip_blocks[i].status.hang &&
+ adev->ip_blocks[i].version->funcs->post_soft_reset)
+ r = adev->ip_blocks[i].version->funcs->post_soft_reset(adev);
if (r)
return r;
}
@@ -2182,7 +2210,7 @@ bool amdgpu_need_backup(struct amdgpu_device *adev)
static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
- struct fence **fence)
+ struct dma_fence **fence)
{
uint32_t domain;
int r;
@@ -2298,30 +2326,30 @@ retry:
if (need_full_reset && amdgpu_need_backup(adev)) {
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
struct amdgpu_bo *bo, *tmp;
- struct fence *fence = NULL, *next = NULL;
+ struct dma_fence *fence = NULL, *next = NULL;
DRM_INFO("recover vram bo from shadow\n");
mutex_lock(&adev->shadow_list_lock);
list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
if (fence) {
- r = fence_wait(fence, false);
+ r = dma_fence_wait(fence, false);
if (r) {
WARN(r, "recovery from shadow isn't comleted\n");
break;
}
}
- fence_put(fence);
+ dma_fence_put(fence);
fence = next;
}
mutex_unlock(&adev->shadow_list_lock);
if (fence) {
- r = fence_wait(fence, false);
+ r = dma_fence_wait(fence, false);
if (r)
WARN(r, "recovery from shadow isn't comleted\n");
}
- fence_put(fence);
+ dma_fence_put(fence);
}
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
@@ -2471,9 +2499,6 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev,
adev->debugfs_count = i;
#if defined(CONFIG_DEBUG_FS)
drm_debugfs_create_files(files, nfiles,
- adev->ddev->control->debugfs_root,
- adev->ddev->control);
- drm_debugfs_create_files(files, nfiles,
adev->ddev->primary->debugfs_root,
adev->ddev->primary);
#endif
@@ -2488,9 +2513,6 @@ static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev)
for (i = 0; i < adev->debugfs_count; i++) {
drm_debugfs_remove_files(adev->debugfs[i].files,
adev->debugfs[i].num_files,
- adev->ddev->control);
- drm_debugfs_remove_files(adev->debugfs[i].files,
- adev->debugfs[i].num_files,
adev->ddev->primary);
}
#endif
@@ -2517,6 +2539,13 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
se_bank = (*pos >> 24) & 0x3FF;
sh_bank = (*pos >> 34) & 0x3FF;
instance_bank = (*pos >> 44) & 0x3FF;
+
+ if (se_bank == 0x3FF)
+ se_bank = 0xFFFFFFFF;
+ if (sh_bank == 0x3FF)
+ sh_bank = 0xFFFFFFFF;
+ if (instance_bank == 0x3FF)
+ instance_bank = 0xFFFFFFFF;
use_bank = 1;
} else {
use_bank = 0;
@@ -2525,8 +2554,8 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
*pos &= 0x3FFFF;
if (use_bank) {
- if (sh_bank >= adev->gfx.config.max_sh_per_se ||
- se_bank >= adev->gfx.config.max_shader_engines)
+ if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
+ (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines))
return -EINVAL;
mutex_lock(&adev->grbm_idx_mutex);
amdgpu_gfx_select_se_sh(adev, se_bank,
@@ -2573,10 +2602,45 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
struct amdgpu_device *adev = f->f_inode->i_private;
ssize_t result = 0;
int r;
+ bool pm_pg_lock, use_bank;
+ unsigned instance_bank, sh_bank, se_bank;
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
+ /* are we reading registers for which a PG lock is necessary? */
+ pm_pg_lock = (*pos >> 23) & 1;
+
+ if (*pos & (1ULL << 62)) {
+ se_bank = (*pos >> 24) & 0x3FF;
+ sh_bank = (*pos >> 34) & 0x3FF;
+ instance_bank = (*pos >> 44) & 0x3FF;
+
+ if (se_bank == 0x3FF)
+ se_bank = 0xFFFFFFFF;
+ if (sh_bank == 0x3FF)
+ sh_bank = 0xFFFFFFFF;
+ if (instance_bank == 0x3FF)
+ instance_bank = 0xFFFFFFFF;
+ use_bank = 1;
+ } else {
+ use_bank = 0;
+ }
+
+ *pos &= 0x3FFFF;
+
+ if (use_bank) {
+ if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
+ (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines))
+ return -EINVAL;
+ mutex_lock(&adev->grbm_idx_mutex);
+ amdgpu_gfx_select_se_sh(adev, se_bank,
+ sh_bank, instance_bank);
+ }
+
+ if (pm_pg_lock)
+ mutex_lock(&adev->pm.mutex);
+
while (size) {
uint32_t value;
@@ -2595,6 +2659,14 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
size -= 4;
}
+ if (use_bank) {
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ mutex_unlock(&adev->grbm_idx_mutex);
+ }
+
+ if (pm_pg_lock)
+ mutex_unlock(&adev->pm.mutex);
+
return result;
}
@@ -2857,6 +2929,116 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
return !r ? 4 : r;
}
+static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = f->f_inode->i_private;
+ int r, x;
+ ssize_t result=0;
+ uint32_t offset, se, sh, cu, wave, simd, data[32];
+
+ if (size & 3 || *pos & 3)
+ return -EINVAL;
+
+ /* decode offset */
+ offset = (*pos & 0x7F);
+ se = ((*pos >> 7) & 0xFF);
+ sh = ((*pos >> 15) & 0xFF);
+ cu = ((*pos >> 23) & 0xFF);
+ wave = ((*pos >> 31) & 0xFF);
+ simd = ((*pos >> 37) & 0xFF);
+
+ /* switch to the specific se/sh/cu */
+ mutex_lock(&adev->grbm_idx_mutex);
+ amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+
+ x = 0;
+ if (adev->gfx.funcs->read_wave_data)
+ adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x);
+
+ amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ if (!x)
+ return -EINVAL;
+
+ while (size && (offset < x * 4)) {
+ uint32_t value;
+
+ value = data[offset >> 2];
+ r = put_user(value, (uint32_t *)buf);
+ if (r)
+ return r;
+
+ result += 4;
+ buf += 4;
+ offset += 4;
+ size -= 4;
+ }
+
+ return result;
+}
+
+static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = f->f_inode->i_private;
+ int r;
+ ssize_t result = 0;
+ uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
+
+ if (size & 3 || *pos & 3)
+ return -EINVAL;
+
+ /* decode offset */
+ offset = (*pos & 0xFFF); /* in dwords */
+ se = ((*pos >> 12) & 0xFF);
+ sh = ((*pos >> 20) & 0xFF);
+ cu = ((*pos >> 28) & 0xFF);
+ wave = ((*pos >> 36) & 0xFF);
+ simd = ((*pos >> 44) & 0xFF);
+ thread = ((*pos >> 52) & 0xFF);
+ bank = ((*pos >> 60) & 1);
+
+ data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* switch to the specific se/sh/cu */
+ mutex_lock(&adev->grbm_idx_mutex);
+ amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+
+ if (bank == 0) {
+ if (adev->gfx.funcs->read_wave_vgprs)
+ adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data);
+ } else {
+ if (adev->gfx.funcs->read_wave_sgprs)
+ adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data);
+ }
+
+ amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ while (size) {
+ uint32_t value;
+
+ value = data[offset++];
+ r = put_user(value, (uint32_t *)buf);
+ if (r) {
+ result = r;
+ goto err;
+ }
+
+ result += 4;
+ buf += 4;
+ size -= 4;
+ }
+
+err:
+ kfree(data);
+ return result;
+}
+
static const struct file_operations amdgpu_debugfs_regs_fops = {
.owner = THIS_MODULE,
.read = amdgpu_debugfs_regs_read,
@@ -2894,6 +3076,17 @@ static const struct file_operations amdgpu_debugfs_sensors_fops = {
.llseek = default_llseek
};
+static const struct file_operations amdgpu_debugfs_wave_fops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_debugfs_wave_read,
+ .llseek = default_llseek
+};
+static const struct file_operations amdgpu_debugfs_gpr_fops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_debugfs_gpr_read,
+ .llseek = default_llseek
+};
+
static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_regs_fops,
&amdgpu_debugfs_regs_didt_fops,
@@ -2901,6 +3094,8 @@ static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_regs_smc_fops,
&amdgpu_debugfs_gca_config_fops,
&amdgpu_debugfs_sensors_fops,
+ &amdgpu_debugfs_wave_fops,
+ &amdgpu_debugfs_gpr_fops,
};
static const char *debugfs_regs_names[] = {
@@ -2910,6 +3105,8 @@ static const char *debugfs_regs_names[] = {
"amdgpu_regs_smc",
"amdgpu_gca_config",
"amdgpu_sensors",
+ "amdgpu_wave",
+ "amdgpu_gpr",
};
static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 083e2b429872..581601ca6b89 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -35,29 +35,29 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
-static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
+static void amdgpu_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct amdgpu_flip_work *work =
container_of(cb, struct amdgpu_flip_work, cb);
- fence_put(f);
+ dma_fence_put(f);
schedule_work(&work->flip_work.work);
}
static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
- struct fence **f)
+ struct dma_fence **f)
{
- struct fence *fence= *f;
+ struct dma_fence *fence= *f;
if (fence == NULL)
return false;
*f = NULL;
- if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
+ if (!dma_fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
return true;
- fence_put(fence);
+ dma_fence_put(fence);
return false;
}
@@ -68,9 +68,9 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
struct amdgpu_flip_work *work =
container_of(delayed_work, struct amdgpu_flip_work, flip_work);
struct amdgpu_device *adev = work->adev;
- struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id];
+ struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id];
- struct drm_crtc *crtc = &amdgpuCrtc->base;
+ struct drm_crtc *crtc = &amdgpu_crtc->base;
unsigned long flags;
unsigned i;
int vpos, hpos;
@@ -85,14 +85,14 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
/* Wait until we're out of the vertical blank period before the one
* targeted by the flip
*/
- if (amdgpuCrtc->enabled &&
+ if (amdgpu_crtc->enabled &&
(amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0,
&vpos, &hpos, NULL, NULL,
&crtc->hwmode)
& (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
(int)(work->target_vblank -
- amdgpu_get_vblank_counter_kms(adev->ddev, amdgpuCrtc->crtc_id)) > 0) {
+ amdgpu_get_vblank_counter_kms(adev->ddev, amdgpu_crtc->crtc_id)) > 0) {
schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000));
return;
}
@@ -104,12 +104,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
/* Set the flip status */
- amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
+ amdgpu_crtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n",
- amdgpuCrtc->crtc_id, amdgpuCrtc, work);
+ amdgpu_crtc->crtc_id, amdgpu_crtc, work);
}
@@ -187,7 +187,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
goto cleanup;
}
- r = amdgpu_bo_pin_restricted(new_abo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, &base);
+ r = amdgpu_bo_pin(new_abo, AMDGPU_GEM_DOMAIN_VRAM, &base);
if (unlikely(r != 0)) {
r = -EINVAL;
DRM_ERROR("failed to pin new abo buffer before flip\n");
@@ -244,9 +244,9 @@ unreserve:
cleanup:
amdgpu_bo_unref(&work->old_abo);
- fence_put(work->excl);
+ dma_fence_put(work->excl);
for (i = 0; i < work->shared_count; ++i)
- fence_put(work->shared[i]);
+ dma_fence_put(work->shared[i]);
kfree(work->shared);
kfree(work);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
index 14f57d9915e3..6ca0333ca4c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
@@ -553,9 +553,10 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
}
- for (i = 0; i < states->numEntries; i++) {
- if (i >= AMDGPU_MAX_VCE_LEVELS)
- break;
+ adev->pm.dpm.num_of_vce_states =
+ states->numEntries > AMD_MAX_VCE_LEVELS ?
+ AMD_MAX_VCE_LEVELS : states->numEntries;
+ for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
vce_clk = (VCEClockInfo *)
((u8 *)&array->entries[0] +
(state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
@@ -955,3 +956,12 @@ u8 amdgpu_encode_pci_lane_width(u32 lanes)
return encoded_lanes[lanes];
}
+
+struct amd_vce_state*
+amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx)
+{
+ if (idx < adev->pm.dpm.num_of_vce_states)
+ return &adev->pm.dpm.vce_states[idx];
+
+ return NULL;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 3738a96c2619..955d6f21e2b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -23,6 +23,453 @@
#ifndef __AMDGPU_DPM_H__
#define __AMDGPU_DPM_H__
+enum amdgpu_int_thermal_type {
+ THERMAL_TYPE_NONE,
+ THERMAL_TYPE_EXTERNAL,
+ THERMAL_TYPE_EXTERNAL_GPIO,
+ THERMAL_TYPE_RV6XX,
+ THERMAL_TYPE_RV770,
+ THERMAL_TYPE_ADT7473_WITH_INTERNAL,
+ THERMAL_TYPE_EVERGREEN,
+ THERMAL_TYPE_SUMO,
+ THERMAL_TYPE_NI,
+ THERMAL_TYPE_SI,
+ THERMAL_TYPE_EMC2103_WITH_INTERNAL,
+ THERMAL_TYPE_CI,
+ THERMAL_TYPE_KV,
+};
+
+enum amdgpu_dpm_auto_throttle_src {
+ AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL,
+ AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL
+};
+
+enum amdgpu_dpm_event_src {
+ AMDGPU_DPM_EVENT_SRC_ANALOG = 0,
+ AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1,
+ AMDGPU_DPM_EVENT_SRC_DIGITAL = 2,
+ AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
+ AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
+};
+
+#define SCLK_DEEP_SLEEP_MASK 0x8
+
+struct amdgpu_ps {
+ u32 caps; /* vbios flags */
+ u32 class; /* vbios flags */
+ u32 class2; /* vbios flags */
+ /* UVD clocks */
+ u32 vclk;
+ u32 dclk;
+ /* VCE clocks */
+ u32 evclk;
+ u32 ecclk;
+ bool vce_active;
+ enum amd_vce_level vce_level;
+ /* asic priv */
+ void *ps_priv;
+};
+
+struct amdgpu_dpm_thermal {
+ /* thermal interrupt work */
+ struct work_struct work;
+ /* low temperature threshold */
+ int min_temp;
+ /* high temperature threshold */
+ int max_temp;
+ /* was last interrupt low to high or high to low */
+ bool high_to_low;
+ /* interrupt source */
+ struct amdgpu_irq_src irq;
+};
+
+enum amdgpu_clk_action
+{
+ AMDGPU_SCLK_UP = 1,
+ AMDGPU_SCLK_DOWN
+};
+
+struct amdgpu_blacklist_clocks
+{
+ u32 sclk;
+ u32 mclk;
+ enum amdgpu_clk_action action;
+};
+
+struct amdgpu_clock_and_voltage_limits {
+ u32 sclk;
+ u32 mclk;
+ u16 vddc;
+ u16 vddci;
+};
+
+struct amdgpu_clock_array {
+ u32 count;
+ u32 *values;
+};
+
+struct amdgpu_clock_voltage_dependency_entry {
+ u32 clk;
+ u16 v;
+};
+
+struct amdgpu_clock_voltage_dependency_table {
+ u32 count;
+ struct amdgpu_clock_voltage_dependency_entry *entries;
+};
+
+union amdgpu_cac_leakage_entry {
+ struct {
+ u16 vddc;
+ u32 leakage;
+ };
+ struct {
+ u16 vddc1;
+ u16 vddc2;
+ u16 vddc3;
+ };
+};
+
+struct amdgpu_cac_leakage_table {
+ u32 count;
+ union amdgpu_cac_leakage_entry *entries;
+};
+
+struct amdgpu_phase_shedding_limits_entry {
+ u16 voltage;
+ u32 sclk;
+ u32 mclk;
+};
+
+struct amdgpu_phase_shedding_limits_table {
+ u32 count;
+ struct amdgpu_phase_shedding_limits_entry *entries;
+};
+
+struct amdgpu_uvd_clock_voltage_dependency_entry {
+ u32 vclk;
+ u32 dclk;
+ u16 v;
+};
+
+struct amdgpu_uvd_clock_voltage_dependency_table {
+ u8 count;
+ struct amdgpu_uvd_clock_voltage_dependency_entry *entries;
+};
+
+struct amdgpu_vce_clock_voltage_dependency_entry {
+ u32 ecclk;
+ u32 evclk;
+ u16 v;
+};
+
+struct amdgpu_vce_clock_voltage_dependency_table {
+ u8 count;
+ struct amdgpu_vce_clock_voltage_dependency_entry *entries;
+};
+
+struct amdgpu_ppm_table {
+ u8 ppm_design;
+ u16 cpu_core_number;
+ u32 platform_tdp;
+ u32 small_ac_platform_tdp;
+ u32 platform_tdc;
+ u32 small_ac_platform_tdc;
+ u32 apu_tdp;
+ u32 dgpu_tdp;
+ u32 dgpu_ulv_power;
+ u32 tj_max;
+};
+
+struct amdgpu_cac_tdp_table {
+ u16 tdp;
+ u16 configurable_tdp;
+ u16 tdc;
+ u16 battery_power_limit;
+ u16 small_power_limit;
+ u16 low_cac_leakage;
+ u16 high_cac_leakage;
+ u16 maximum_power_delivery_limit;
+};
+
+struct amdgpu_dpm_dynamic_state {
+ struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk;
+ struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk;
+ struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk;
+ struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk;
+ struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk;
+ struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table;
+ struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table;
+ struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table;
+ struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table;
+ struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk;
+ struct amdgpu_clock_array valid_sclk_values;
+ struct amdgpu_clock_array valid_mclk_values;
+ struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc;
+ struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac;
+ u32 mclk_sclk_ratio;
+ u32 sclk_mclk_delta;
+ u16 vddc_vddci_delta;
+ u16 min_vddc_for_pcie_gen2;
+ struct amdgpu_cac_leakage_table cac_leakage_table;
+ struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table;
+ struct amdgpu_ppm_table *ppm_table;
+ struct amdgpu_cac_tdp_table *cac_tdp_table;
+};
+
+struct amdgpu_dpm_fan {
+ u16 t_min;
+ u16 t_med;
+ u16 t_high;
+ u16 pwm_min;
+ u16 pwm_med;
+ u16 pwm_high;
+ u8 t_hyst;
+ u32 cycle_delay;
+ u16 t_max;
+ u8 control_mode;
+ u16 default_max_fan_pwm;
+ u16 default_fan_output_sensitivity;
+ u16 fan_output_sensitivity;
+ bool ucode_fan_control;
+};
+
+enum amdgpu_pcie_gen {
+ AMDGPU_PCIE_GEN1 = 0,
+ AMDGPU_PCIE_GEN2 = 1,
+ AMDGPU_PCIE_GEN3 = 2,
+ AMDGPU_PCIE_GEN_INVALID = 0xffff
+};
+
+enum amdgpu_dpm_forced_level {
+ AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
+ AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
+ AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
+ AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
+};
+
+struct amdgpu_dpm_funcs {
+ int (*get_temperature)(struct amdgpu_device *adev);
+ int (*pre_set_power_state)(struct amdgpu_device *adev);
+ int (*set_power_state)(struct amdgpu_device *adev);
+ void (*post_set_power_state)(struct amdgpu_device *adev);
+ void (*display_configuration_changed)(struct amdgpu_device *adev);
+ u32 (*get_sclk)(struct amdgpu_device *adev, bool low);
+ u32 (*get_mclk)(struct amdgpu_device *adev, bool low);
+ void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps);
+ void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m);
+ int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level);
+ bool (*vblank_too_short)(struct amdgpu_device *adev);
+ void (*powergate_uvd)(struct amdgpu_device *adev, bool gate);
+ void (*powergate_vce)(struct amdgpu_device *adev, bool gate);
+ void (*enable_bapm)(struct amdgpu_device *adev, bool enable);
+ void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode);
+ u32 (*get_fan_control_mode)(struct amdgpu_device *adev);
+ int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed);
+ int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed);
+ int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask);
+ int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
+ int (*get_sclk_od)(struct amdgpu_device *adev);
+ int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
+ int (*get_mclk_od)(struct amdgpu_device *adev);
+ int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value);
+ int (*check_state_equal)(struct amdgpu_device *adev,
+ struct amdgpu_ps *cps,
+ struct amdgpu_ps *rps,
+ bool *equal);
+
+ struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx);
+};
+
+#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
+#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
+#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev))
+#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev))
+#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps))
+#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev))
+#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e))
+
+#define amdgpu_dpm_read_sensor(adev, idx, value) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \
+ -EINVAL)
+
+#define amdgpu_dpm_get_temperature(adev) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \
+ (adev)->pm.funcs->get_temperature((adev)))
+
+#define amdgpu_dpm_set_fan_control_mode(adev, m) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \
+ (adev)->pm.funcs->set_fan_control_mode((adev), (m)))
+
+#define amdgpu_dpm_get_fan_control_mode(adev) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \
+ (adev)->pm.funcs->get_fan_control_mode((adev)))
+
+#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+ (adev)->pm.funcs->set_fan_speed_percent((adev), (s)))
+
+#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+ (adev)->pm.funcs->get_fan_speed_percent((adev), (s)))
+
+#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_fan_speed_rpm((adev)->powerplay.pp_handle, (s)) : \
+ -EINVAL)
+
+#define amdgpu_dpm_get_sclk(adev, l) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \
+ (adev)->pm.funcs->get_sclk((adev), (l)))
+
+#define amdgpu_dpm_get_mclk(adev, l) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \
+ (adev)->pm.funcs->get_mclk((adev), (l)))
+
+
+#define amdgpu_dpm_force_performance_level(adev, l) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \
+ (adev)->pm.funcs->force_performance_level((adev), (l)))
+
+#define amdgpu_dpm_powergate_uvd(adev, g) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \
+ (adev)->pm.funcs->powergate_uvd((adev), (g)))
+
+#define amdgpu_dpm_powergate_vce(adev, g) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \
+ (adev)->pm.funcs->powergate_vce((adev), (g)))
+
+#define amdgpu_dpm_get_current_power_state(adev) \
+ (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_get_performance_level(adev) \
+ (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_get_pp_num_states(adev, data) \
+ (adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
+
+#define amdgpu_dpm_get_pp_table(adev, table) \
+ (adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)
+
+#define amdgpu_dpm_set_pp_table(adev, buf, size) \
+ (adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)
+
+#define amdgpu_dpm_print_clock_levels(adev, type, buf) \
+ (adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)
+
+#define amdgpu_dpm_force_clock_level(adev, type, level) \
+ (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)
+
+#define amdgpu_dpm_get_sclk_od(adev) \
+ (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_set_sclk_od(adev, value) \
+ (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)
+
+#define amdgpu_dpm_get_mclk_od(adev) \
+ ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle))
+
+#define amdgpu_dpm_set_mclk_od(adev, value) \
+ ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))
+
+#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \
+ (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
+
+#define amgdpu_dpm_check_state_equal(adev, cps, rps, equal) (adev)->pm.funcs->check_state_equal((adev), (cps),(rps),(equal))
+
+#define amdgpu_dpm_get_vce_clock_state(adev, i) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \
+ (adev)->pm.funcs->get_vce_clock_state((adev), (i)))
+
+struct amdgpu_dpm {
+ struct amdgpu_ps *ps;
+ /* number of valid power states */
+ int num_ps;
+ /* current power state that is active */
+ struct amdgpu_ps *current_ps;
+ /* requested power state */
+ struct amdgpu_ps *requested_ps;
+ /* boot up power state */
+ struct amdgpu_ps *boot_ps;
+ /* default uvd power state */
+ struct amdgpu_ps *uvd_ps;
+ /* vce requirements */
+ u32 num_of_vce_states;
+ struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS];
+ enum amd_vce_level vce_level;
+ enum amd_pm_state_type state;
+ enum amd_pm_state_type user_state;
+ enum amd_pm_state_type last_state;
+ enum amd_pm_state_type last_user_state;
+ u32 platform_caps;
+ u32 voltage_response_time;
+ u32 backbias_response_time;
+ void *priv;
+ u32 new_active_crtcs;
+ int new_active_crtc_count;
+ u32 current_active_crtcs;
+ int current_active_crtc_count;
+ struct amdgpu_dpm_dynamic_state dyn_state;
+ struct amdgpu_dpm_fan fan;
+ u32 tdp_limit;
+ u32 near_tdp_limit;
+ u32 near_tdp_limit_adjusted;
+ u32 sq_ramping_threshold;
+ u32 cac_leakage;
+ u16 tdp_od_limit;
+ u32 tdp_adjustment;
+ u16 load_line_slope;
+ bool power_control;
+ bool ac_power;
+ /* special states active */
+ bool thermal_active;
+ bool uvd_active;
+ bool vce_active;
+ /* thermal handling */
+ struct amdgpu_dpm_thermal thermal;
+ /* forced levels */
+ enum amdgpu_dpm_forced_level forced_level;
+};
+
+struct amdgpu_pm {
+ struct mutex mutex;
+ u32 current_sclk;
+ u32 current_mclk;
+ u32 default_sclk;
+ u32 default_mclk;
+ struct amdgpu_i2c_chan *i2c_bus;
+ /* internal thermal controller on rv6xx+ */
+ enum amdgpu_int_thermal_type int_thermal_type;
+ struct device *int_hwmon_dev;
+ /* fan control parameters */
+ bool no_fan;
+ u8 fan_pulses_per_revolution;
+ u8 fan_min_rpm;
+ 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;
+ const struct amdgpu_dpm_funcs *funcs;
+ uint32_t pcie_gen_mask;
+ uint32_t pcie_mlw_mask;
+ struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
+};
+
#define R600_SSTU_DFLT 0
#define R600_SST_DFLT 0x00C8
@@ -82,4 +529,7 @@ u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev,
u16 default_lanes);
u8 amdgpu_encode_pci_lane_width(u32 lanes);
+struct amd_vce_state*
+amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index e0890deccb2f..8cb937b2bfcc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -58,9 +58,10 @@
* - 3.6.0 - kmd involves use CONTEXT_CONTROL in ring buffer.
* - 3.7.0 - Add support for VCE clock list packet
* - 3.8.0 - Add support raster config init in the kernel
+ * - 3.9.0 - Add support for memory query info about VRAM and GTT.
*/
#define KMS_DRIVER_MAJOR 3
-#define KMS_DRIVER_MINOR 8
+#define KMS_DRIVER_MINOR 9
#define KMS_DRIVER_PATCHLEVEL 0
int amdgpu_vram_limit = 0;
@@ -85,12 +86,13 @@ int amdgpu_vm_size = 64;
int amdgpu_vm_block_size = -1;
int amdgpu_vm_fault_stop = 0;
int amdgpu_vm_debug = 0;
+int amdgpu_vram_page_split = 1024;
int amdgpu_exp_hw_support = 0;
int amdgpu_sched_jobs = 32;
int amdgpu_sched_hw_submission = 2;
int amdgpu_powerplay = -1;
-int amdgpu_powercontainment = 1;
-int amdgpu_sclk_deep_sleep_en = 1;
+int amdgpu_no_evict = 0;
+int amdgpu_direct_gma_size = 0;
unsigned amdgpu_pcie_gen_cap = 0;
unsigned amdgpu_pcie_lane_cap = 0;
unsigned amdgpu_cg_mask = 0xffffffff;
@@ -165,6 +167,9 @@ 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(vram_page_split, "Number of pages after we split VRAM allocations (default 1024, -1 = disable)");
+module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444);
+
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);
@@ -177,14 +182,14 @@ module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444);
MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))");
module_param_named(powerplay, amdgpu_powerplay, int, 0444);
-MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 = disable)");
-module_param_named(powercontainment, amdgpu_powercontainment, int, 0444);
-
MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))");
module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444);
-MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)");
-module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444);
+MODULE_PARM_DESC(no_evict, "Support pinning request from user space (1 = enable, 0 = disable (default))");
+module_param_named(no_evict, amdgpu_no_evict, int, 0444);
+
+MODULE_PARM_DESC(direct_gma_size, "Direct GMA size in megabytes (max 96MB)");
+module_param_named(direct_gma_size, amdgpu_direct_gma_size, int, 0444);
MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))");
module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444);
@@ -201,7 +206,8 @@ module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444);
MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)");
module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444);
-MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)");
+MODULE_PARM_DESC(virtual_display,
+ "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)");
module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
static const struct pci_device_id pciidlist[] = {
@@ -381,6 +387,7 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x6939, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
/* fiji */
{0x1002, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
+ {0x1002, 0x730F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
/* carrizo */
{0x1002, 0x9870, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9874, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 9fb8aa4d6bae..24629bec181a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -75,27 +75,21 @@ amdgpufb_release(struct fb_info *info, int user)
static struct fb_ops amdgpufb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_open = amdgpufb_open,
.fb_release = amdgpufb_release,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
-int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled)
+int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled)
{
int aligned = width;
int pitch_mask = 0;
- switch (bpp / 8) {
+ switch (cpp) {
case 1:
pitch_mask = 255;
break;
@@ -110,7 +104,7 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
aligned += pitch_mask;
aligned &= ~pitch_mask;
- return aligned;
+ return aligned * cpp;
}
static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -139,20 +133,21 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
int ret;
int aligned_size, size;
int height = mode_cmd->height;
- u32 bpp, depth;
+ u32 cpp;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+ cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
/* need to align pitch with crtc limits */
- mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, bpp,
- fb_tiled) * ((bpp + 1) / 8);
+ mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
+ fb_tiled);
height = ALIGN(mode_cmd->height, 8);
size = mode_cmd->pitches[0] * height;
aligned_size = ALIGN(size, PAGE_SIZE);
ret = amdgpu_gem_object_create(adev, aligned_size, 0,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
true, &gobj);
if (ret) {
printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
@@ -176,7 +171,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
}
- ret = amdgpu_bo_pin_restricted(abo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, NULL);
+ ret = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM, NULL);
if (ret) {
amdgpu_bo_unreserve(abo);
goto out_unref;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 77b34ec92632..7b60fb79c3a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -48,7 +48,7 @@
*/
struct amdgpu_fence {
- struct fence base;
+ struct dma_fence base;
/* RB, DMA, etc. */
struct amdgpu_ring *ring;
@@ -74,8 +74,8 @@ void amdgpu_fence_slab_fini(void)
/*
* Cast helper
*/
-static const struct fence_ops amdgpu_fence_ops;
-static inline struct amdgpu_fence *to_amdgpu_fence(struct fence *f)
+static const struct dma_fence_ops amdgpu_fence_ops;
+static inline struct amdgpu_fence *to_amdgpu_fence(struct dma_fence *f)
{
struct amdgpu_fence *__f = container_of(f, struct amdgpu_fence, base);
@@ -131,11 +131,11 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
* Emits a fence command on the requested ring (all asics).
* Returns 0 on success, -ENOMEM on failure.
*/
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f)
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_fence *fence;
- struct fence *old, **ptr;
+ struct dma_fence *old, **ptr;
uint32_t seq;
fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
@@ -144,10 +144,10 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f)
seq = ++ring->fence_drv.sync_seq;
fence->ring = ring;
- fence_init(&fence->base, &amdgpu_fence_ops,
- &ring->fence_drv.lock,
- adev->fence_context + ring->idx,
- seq);
+ dma_fence_init(&fence->base, &amdgpu_fence_ops,
+ &ring->fence_drv.lock,
+ adev->fence_context + ring->idx,
+ seq);
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
seq, AMDGPU_FENCE_FLAG_INT);
@@ -156,12 +156,12 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f)
* emitting the fence would mess up the hardware ring buffer.
*/
old = rcu_dereference_protected(*ptr, 1);
- if (old && !fence_is_signaled(old)) {
+ if (old && !dma_fence_is_signaled(old)) {
DRM_INFO("rcu slot is busy\n");
- fence_wait(old, false);
+ dma_fence_wait(old, false);
}
- rcu_assign_pointer(*ptr, fence_get(&fence->base));
+ rcu_assign_pointer(*ptr, dma_fence_get(&fence->base));
*f = &fence->base;
@@ -212,7 +212,7 @@ void amdgpu_fence_process(struct amdgpu_ring *ring)
seq &= drv->num_fences_mask;
do {
- struct fence *fence, **ptr;
+ struct dma_fence *fence, **ptr;
++last_seq;
last_seq &= drv->num_fences_mask;
@@ -225,13 +225,13 @@ void amdgpu_fence_process(struct amdgpu_ring *ring)
if (!fence)
continue;
- r = fence_signal(fence);
+ r = dma_fence_signal(fence);
if (!r)
- FENCE_TRACE(fence, "signaled from irq context\n");
+ DMA_FENCE_TRACE(fence, "signaled from irq context\n");
else
BUG();
- fence_put(fence);
+ dma_fence_put(fence);
} while (last_seq != seq);
}
@@ -261,7 +261,7 @@ static void amdgpu_fence_fallback(unsigned long arg)
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring)
{
uint64_t seq = ACCESS_ONCE(ring->fence_drv.sync_seq);
- struct fence *fence, **ptr;
+ struct dma_fence *fence, **ptr;
int r;
if (!seq)
@@ -270,14 +270,14 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring)
ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask];
rcu_read_lock();
fence = rcu_dereference(*ptr);
- if (!fence || !fence_get_rcu(fence)) {
+ if (!fence || !dma_fence_get_rcu(fence)) {
rcu_read_unlock();
return 0;
}
rcu_read_unlock();
- r = fence_wait(fence, false);
- fence_put(fence);
+ r = dma_fence_wait(fence, false);
+ dma_fence_put(fence);
return r;
}
@@ -382,24 +382,27 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
if (!ring->fence_drv.fences)
return -ENOMEM;
- 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,
- num_hw_submission,
- timeout, ring->name);
- if (r) {
- DRM_ERROR("Failed to create scheduler on ring %s.\n",
- ring->name);
- return r;
+ /* No need to setup the GPU scheduler for KIQ ring */
+ if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) {
+ 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,
+ num_hw_submission,
+ timeout, ring->name);
+ if (r) {
+ DRM_ERROR("Failed to create scheduler on ring %s.\n",
+ ring->name);
+ return r;
+ }
}
return 0;
@@ -453,7 +456,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
amd_sched_fini(&ring->sched);
del_timer_sync(&ring->fence_drv.fallback_timer);
for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
- fence_put(ring->fence_drv.fences[j]);
+ dma_fence_put(ring->fence_drv.fences[j]);
kfree(ring->fence_drv.fences);
ring->fence_drv.fences = NULL;
ring->fence_drv.initialized = false;
@@ -542,12 +545,12 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev)
* Common fence implementation
*/
-static const char *amdgpu_fence_get_driver_name(struct fence *fence)
+static const char *amdgpu_fence_get_driver_name(struct dma_fence *fence)
{
return "amdgpu";
}
-static const char *amdgpu_fence_get_timeline_name(struct fence *f)
+static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
return (const char *)fence->ring->name;
@@ -561,7 +564,7 @@ static const char *amdgpu_fence_get_timeline_name(struct fence *f)
* 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)
+static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
@@ -569,7 +572,7 @@ static bool amdgpu_fence_enable_signaling(struct fence *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);
+ DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
return true;
}
@@ -583,7 +586,7 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
*/
static void amdgpu_fence_free(struct rcu_head *rcu)
{
- struct fence *f = container_of(rcu, struct fence, rcu);
+ struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
struct amdgpu_fence *fence = to_amdgpu_fence(f);
kmem_cache_free(amdgpu_fence_slab, fence);
}
@@ -596,16 +599,16 @@ static void amdgpu_fence_free(struct rcu_head *rcu)
* This function is called when the reference count becomes zero.
* It just RCU schedules freeing up the fence.
*/
-static void amdgpu_fence_release(struct fence *f)
+static void amdgpu_fence_release(struct dma_fence *f)
{
call_rcu(&f->rcu, amdgpu_fence_free);
}
-static const struct fence_ops amdgpu_fence_ops = {
+static const struct dma_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,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = amdgpu_fence_release,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index 21a1242fc13b..964d2a946ed5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -126,7 +126,8 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
if (adev->gart.robj == NULL) {
r = amdgpu_bo_create(adev, adev->gart.table_size,
PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &adev->gart.robj);
if (r) {
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index a7ea9a3b454e..cd62f6ffde2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -116,10 +116,11 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
* Call from drm_gem_handle_create which appear in both new and open ioctl
* case.
*/
-int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv)
+int amdgpu_gem_object_open(struct drm_gem_object *obj,
+ struct drm_file *file_priv)
{
struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj);
- struct amdgpu_device *adev = abo->adev;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_va *bo_va;
@@ -142,7 +143,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
struct drm_file *file_priv)
{
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- struct amdgpu_device *adev = bo->adev;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
struct amdgpu_vm *vm = &fpriv->vm;
@@ -407,10 +408,8 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
}
robj = gem_to_amdgpu_bo(gobj);
- if (timeout == 0)
- ret = reservation_object_test_signaled_rcu(robj->tbo.resv, true);
- else
- ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, timeout);
+ ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true,
+ timeout);
/* ret == 0 means not signaled,
* ret > 0 means signaled
@@ -470,6 +469,16 @@ out:
return r;
}
+static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
+{
+ unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
+
+ /* if anything is swapped out don't swap it in here,
+ just abort and wait for the next CS */
+
+ return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
+}
+
/**
* amdgpu_gem_va_update_vm -update the bo_va in its VM
*
@@ -480,7 +489,8 @@ out:
* vital here, so they are not reported back to userspace.
*/
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va, uint32_t operation)
+ struct amdgpu_bo_va *bo_va,
+ uint32_t operation)
{
struct ttm_validate_buffer tv, *entry;
struct amdgpu_bo_list_entry vm_pd;
@@ -503,7 +513,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (r)
goto error_print;
- amdgpu_vm_get_pt_bos(adev, bo_va->vm, &duplicates);
list_for_each_entry(entry, &list, head) {
domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
/* if anything is swapped out don't swap it in here,
@@ -511,13 +520,10 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (domain == AMDGPU_GEM_DOMAIN_CPU)
goto error_unreserve;
}
- list_for_each_entry(entry, &duplicates, head) {
- domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
- /* if anything is swapped out don't swap it in here,
- just abort and wait for the next CS */
- if (domain == AMDGPU_GEM_DOMAIN_CPU)
- goto error_unreserve;
- }
+ r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
+ NULL);
+ if (r)
+ goto error_unreserve;
r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
if (r)
@@ -538,8 +544,6 @@ error_print:
DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
}
-
-
int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
@@ -549,7 +553,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_bo *abo;
struct amdgpu_bo_va *bo_va;
- struct ttm_validate_buffer tv, tv_pd;
+ struct amdgpu_bo_list_entry vm_pd;
+ struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket;
struct list_head list, duplicates;
uint32_t invalid_flags, va_flags = 0;
@@ -594,9 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
tv.shared = true;
list_add(&tv.head, &list);
- tv_pd.bo = &fpriv->vm.page_directory->tbo;
- tv_pd.shared = true;
- list_add(&tv_pd.head, &list);
+ amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
if (r) {
@@ -704,7 +707,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
uint32_t handle;
int r;
- args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+ args->pitch = amdgpu_align_pitch(adev, args->width,
+ DIV_ROUND_UP(args->bpp, 8), 0);
args->size = (u64)args->pitch * args->height;
args->size = ALIGN(args->size, PAGE_SIZE);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index a074edd95c70..01a42b6a69a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -24,6 +24,7 @@
*/
#include <drm/drmP.h>
#include "amdgpu.h"
+#include "amdgpu_gfx.h"
/*
* GPU scratch registers helpers function.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 51321e154c09..e02044086445 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -27,6 +27,7 @@
int amdgpu_gfx_scratch_get(struct amdgpu_device *adev, uint32_t *reg);
void amdgpu_gfx_scratch_free(struct amdgpu_device *adev, uint32_t reg);
-unsigned amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se, unsigned max_sh);
+void amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se,
+ unsigned max_sh);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index f86c84427778..00f46b0e076d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -164,10 +164,13 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man,
spin_unlock(&mgr->lock);
node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (!node)
- return -ENOMEM;
+ if (!node) {
+ r = -ENOMEM;
+ goto err_out;
+ }
node->start = AMDGPU_BO_INVALID_OFFSET;
+ node->size = mem->num_pages;
mem->mm_node = node;
if (place->fpfn || place->lpfn || place->flags & TTM_PL_FLAG_TOPDOWN) {
@@ -175,12 +178,20 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man,
if (unlikely(r)) {
kfree(node);
mem->mm_node = NULL;
+ r = 0;
+ goto err_out;
}
} else {
mem->start = node->start;
}
return 0;
+err_out:
+ spin_lock(&mgr->lock);
+ mgr->available += mem->num_pages;
+ spin_unlock(&mgr->lock);
+
+ return r;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 6a6c86c9c169..216a9572d946 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -89,7 +89,7 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
* Free an IB (all asics).
*/
void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
- struct fence *f)
+ struct dma_fence *f)
{
amdgpu_sa_bo_free(adev, &ib->sa_bo, f);
}
@@ -116,8 +116,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
* to SI there was just a DE IB.
*/
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
- struct amdgpu_ib *ibs, struct fence *last_vm_update,
- struct amdgpu_job *job, struct fence **f)
+ struct amdgpu_ib *ibs, struct dma_fence *last_vm_update,
+ struct amdgpu_job *job, struct dma_fence **f)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib *ib = &ibs[0];
@@ -152,8 +152,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
return -EINVAL;
}
- alloc_size = amdgpu_ring_get_dma_frame_size(ring) +
- num_ibs * amdgpu_ring_get_emit_ib_size(ring);
+ alloc_size = ring->funcs->emit_frame_size + num_ibs *
+ ring->funcs->emit_ib_size;
r = amdgpu_ring_alloc(ring, alloc_size);
if (r) {
@@ -161,7 +161,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
return r;
}
- if (ring->type == AMDGPU_RING_TYPE_SDMA && ring->funcs->init_cond_exec)
+ if (ring->funcs->init_cond_exec)
patch_offset = amdgpu_ring_init_cond_exec(ring);
if (vm) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 9fa809876339..fb902932f571 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -424,15 +424,6 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
return 0;
}
-bool amdgpu_irq_get_delayed(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src,
- unsigned type)
-{
- if ((type >= src->num_types) || !src->enabled_types)
- return false;
- return atomic_inc_return(&src->enabled_types[type]) == 1;
-}
-
/**
* amdgpu_irq_put - disable interrupt
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
index f016464035b8..1642f4108297 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
@@ -88,9 +88,6 @@ int amdgpu_irq_update(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type);
int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type);
-bool amdgpu_irq_get_delayed(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src,
- unsigned type);
int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type);
bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 8c5807994073..a0de6286c453 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -81,7 +81,7 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
void amdgpu_job_free_resources(struct amdgpu_job *job)
{
- struct fence *f;
+ struct dma_fence *f;
unsigned i;
/* use sched fence if available */
@@ -95,7 +95,7 @@ static void amdgpu_job_free_cb(struct amd_sched_job *s_job)
{
struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base);
- fence_put(job->fence);
+ dma_fence_put(job->fence);
amdgpu_sync_free(&job->sync);
kfree(job);
}
@@ -104,14 +104,14 @@ void amdgpu_job_free(struct amdgpu_job *job)
{
amdgpu_job_free_resources(job);
- fence_put(job->fence);
+ dma_fence_put(job->fence);
amdgpu_sync_free(&job->sync);
kfree(job);
}
int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
struct amd_sched_entity *entity, void *owner,
- struct fence **f)
+ struct dma_fence **f)
{
int r;
job->ring = ring;
@@ -125,19 +125,19 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
job->owner = owner;
job->fence_ctx = entity->fence_context;
- *f = fence_get(&job->base.s_fence->finished);
+ *f = dma_fence_get(&job->base.s_fence->finished);
amdgpu_job_free_resources(job);
amd_sched_entity_push_job(&job->base);
return 0;
}
-static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
+static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
{
struct amdgpu_job *job = to_amdgpu_job(sched_job);
struct amdgpu_vm *vm = job->vm;
- struct fence *fence = amdgpu_sync_get_fence(&job->sync);
+ struct dma_fence *fence = amdgpu_sync_get_fence(&job->sync);
if (fence == NULL && vm && !job->vm_id) {
struct amdgpu_ring *ring = job->ring;
@@ -155,9 +155,9 @@ static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
return fence;
}
-static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job)
+static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)
{
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
struct amdgpu_job *job;
int r;
@@ -176,8 +176,8 @@ static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
/* if gpu reset, hw fence will be replaced here */
- fence_put(job->fence);
- job->fence = fence_get(fence);
+ dma_fence_put(job->fence);
+ job->fence = dma_fence_get(fence);
amdgpu_job_free_resources(job);
return fence;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 3938fca1ea8e..9af87eaf8ee3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -308,10 +308,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
}
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (adev->ip_blocks[i].type == type &&
- adev->ip_block_status[i].valid) {
- ip.hw_ip_version_major = adev->ip_blocks[i].major;
- ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
+ if (adev->ip_blocks[i].version->type == type &&
+ adev->ip_blocks[i].status.valid) {
+ ip.hw_ip_version_major = adev->ip_blocks[i].version->major;
+ ip.hw_ip_version_minor = adev->ip_blocks[i].version->minor;
ip.capabilities_flags = 0;
ip.available_rings = ring_mask;
ip.ib_start_alignment = ib_start_alignment;
@@ -347,8 +347,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
}
for (i = 0; i < adev->num_ip_blocks; i++)
- if (adev->ip_blocks[i].type == type &&
- adev->ip_block_status[i].valid &&
+ if (adev->ip_blocks[i].version->type == type &&
+ adev->ip_blocks[i].status.valid &&
count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
count++;
@@ -413,6 +413,36 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
return copy_to_user(out, &vram_gtt,
min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0;
}
+ case AMDGPU_INFO_MEMORY: {
+ struct drm_amdgpu_memory_info mem;
+
+ memset(&mem, 0, sizeof(mem));
+ mem.vram.total_heap_size = adev->mc.real_vram_size;
+ mem.vram.usable_heap_size =
+ adev->mc.real_vram_size - adev->vram_pin_size;
+ mem.vram.heap_usage = atomic64_read(&adev->vram_usage);
+ mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
+
+ mem.cpu_accessible_vram.total_heap_size =
+ adev->mc.visible_vram_size;
+ mem.cpu_accessible_vram.usable_heap_size =
+ adev->mc.visible_vram_size -
+ (adev->vram_pin_size - adev->invisible_pin_size);
+ mem.cpu_accessible_vram.heap_usage =
+ atomic64_read(&adev->vram_vis_usage);
+ mem.cpu_accessible_vram.max_allocation =
+ mem.cpu_accessible_vram.usable_heap_size * 3 / 4;
+
+ mem.gtt.total_heap_size = adev->mc.gtt_size;
+ mem.gtt.usable_heap_size =
+ adev->mc.gtt_size - adev->gart_pin_size;
+ mem.gtt.heap_usage = atomic64_read(&adev->gtt_usage);
+ mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4;
+
+ return copy_to_user(out, &mem,
+ min((size_t)size, sizeof(mem)))
+ ? -EFAULT : 0;
+ }
case AMDGPU_INFO_READ_MMR_REG: {
unsigned n, alloc_size;
uint32_t *regs;
@@ -475,6 +505,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
dev_info.ids_flags = 0;
if (adev->flags & AMD_IS_APU)
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
+ if (amdgpu_sriov_vf(adev))
+ dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
dev_info.virtual_address_offset = AMDGPU_VA_RESERVED_SIZE;
dev_info.virtual_address_max = (uint64_t)adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
dev_info.virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
@@ -494,6 +526,50 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
return copy_to_user(out, &dev_info,
min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
}
+ case AMDGPU_INFO_VCE_CLOCK_TABLE: {
+ unsigned i;
+ struct drm_amdgpu_info_vce_clock_table vce_clk_table = {};
+ struct amd_vce_state *vce_state;
+
+ for (i = 0; i < AMDGPU_VCE_CLOCK_TABLE_ENTRIES; i++) {
+ vce_state = amdgpu_dpm_get_vce_clock_state(adev, i);
+ if (vce_state) {
+ vce_clk_table.entries[i].sclk = vce_state->sclk;
+ vce_clk_table.entries[i].mclk = vce_state->mclk;
+ vce_clk_table.entries[i].eclk = vce_state->evclk;
+ vce_clk_table.num_valid_entries++;
+ }
+ }
+
+ return copy_to_user(out, &vce_clk_table,
+ min((size_t)size, sizeof(vce_clk_table))) ? -EFAULT : 0;
+ }
+ case AMDGPU_INFO_VBIOS: {
+ uint32_t bios_size = adev->bios_size;
+
+ switch (info->vbios_info.type) {
+ case AMDGPU_INFO_VBIOS_SIZE:
+ return copy_to_user(out, &bios_size,
+ min((size_t)size, sizeof(bios_size)))
+ ? -EFAULT : 0;
+ case AMDGPU_INFO_VBIOS_IMAGE: {
+ uint8_t *bios;
+ uint32_t bios_offset = info->vbios_info.offset;
+
+ if (bios_offset >= bios_size)
+ return -EINVAL;
+
+ bios = adev->bios + bios_offset;
+ return copy_to_user(out, bios,
+ min((size_t)size, (size_t)(bios_size - bios_offset)))
+ ? -EFAULT : 0;
+ }
+ default:
+ DRM_DEBUG_KMS("Invalid request %d\n",
+ info->vbios_info.type);
+ return -EINVAL;
+ }
+ }
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->query);
return -EINVAL;
@@ -775,6 +851,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
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_WAIT_FENCES, amdgpu_cs_wait_fences_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),
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
index 32fa7b7913f7..7ea3cacf9f9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
@@ -285,7 +285,7 @@ free_rmn:
int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
{
unsigned long end = addr + amdgpu_bo_size(bo) - 1;
- struct amdgpu_device *adev = bo->adev;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_mn *rmn;
struct amdgpu_mn_node *node = NULL;
struct list_head bos;
@@ -340,7 +340,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
*/
void amdgpu_mn_unregister(struct amdgpu_bo *bo)
{
- struct amdgpu_device *adev = bo->adev;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_mn *rmn;
struct list_head *head;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 7b0eff7d060b..202b4176b74e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -271,8 +271,6 @@ struct amdgpu_display_funcs {
u32 (*vblank_get_counter)(struct amdgpu_device *adev, int crtc);
/* wait for vblank */
void (*vblank_wait)(struct amdgpu_device *adev, int crtc);
- /* is dce hung */
- bool (*is_display_hung)(struct amdgpu_device *adev);
/* set backlight level */
void (*backlight_set_level)(struct amdgpu_encoder *amdgpu_encoder,
u8 level);
@@ -341,8 +339,6 @@ struct amdgpu_mode_info {
int num_dig; /* number of dig blocks */
int disp_priority;
const struct amdgpu_display_funcs *funcs;
- struct hrtimer vblank_timer;
- enum amdgpu_interrupt_state vsync_timer_enabled;
};
#define AMDGPU_MAX_BL_LEVEL 0xFF
@@ -413,6 +409,9 @@ struct amdgpu_crtc {
u32 wm_high;
u32 lb_vblank_lead_lines;
struct drm_display_mode hw_mode;
+ /* for virtual dce */
+ struct hrtimer vblank_timer;
+ enum amdgpu_interrupt_state vsync_timer_enabled;
};
struct amdgpu_encoder_atom_dig {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index f3efb1c5dae9..bf79b73e1538 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -88,18 +88,19 @@ static void amdgpu_update_memory_usage(struct amdgpu_device *adev,
static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
struct amdgpu_bo *bo;
bo = container_of(tbo, struct amdgpu_bo, tbo);
- amdgpu_update_memory_usage(bo->adev, &bo->tbo.mem, NULL);
+ amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL);
drm_gem_object_release(&bo->gem_base);
amdgpu_bo_unref(&bo->parent);
if (!list_empty(&bo->shadow_list)) {
- mutex_lock(&bo->adev->shadow_list_lock);
+ mutex_lock(&adev->shadow_list_lock);
list_del_init(&bo->shadow_list);
- mutex_unlock(&bo->adev->shadow_list_lock);
+ mutex_unlock(&adev->shadow_list_lock);
}
kfree(bo->metadata);
kfree(bo);
@@ -121,20 +122,14 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
unsigned visible_pfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
+ unsigned lpfn = 0;
- if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS &&
- !(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
- adev->mc.visible_vram_size < adev->mc.real_vram_size) {
- places[c].fpfn = visible_pfn;
- places[c].lpfn = 0;
- places[c].flags = TTM_PL_FLAG_WC |
- TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM |
- TTM_PL_FLAG_TOPDOWN;
- c++;
- }
+ /* This forces a reallocation if the flag wasn't set before */
+ if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
+ lpfn = adev->mc.real_vram_size >> PAGE_SHIFT;
places[c].fpfn = 0;
- places[c].lpfn = 0;
+ places[c].lpfn = lpfn;
places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM;
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
@@ -205,8 +200,10 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
{
- amdgpu_ttm_placement_init(abo->adev, &abo->placement,
- abo->placements, domain, abo->flags);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
+
+ amdgpu_ttm_placement_init(adev, &abo->placement, abo->placements,
+ domain, abo->flags);
}
static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo,
@@ -245,7 +242,8 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
int r;
r = amdgpu_bo_create(adev, size, align, true, domain,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, bo_ptr);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate kernel bo\n", r);
@@ -351,7 +349,6 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
kfree(bo);
return r;
}
- bo->adev = adev;
INIT_LIST_HEAD(&bo->shadow_list);
INIT_LIST_HEAD(&bo->va);
bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM |
@@ -374,39 +371,36 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
amdgpu_fill_placement_to_bo(bo, placement);
/* Kernel allocation are uninterruptible */
+
+ if (!resv) {
+ bool locked;
+
+ reservation_object_init(&bo->tbo.ttm_resv);
+ locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock);
+ WARN_ON(!locked);
+ }
r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
&bo->placement, page_align, !kernel, NULL,
- acc_size, sg, resv, &amdgpu_ttm_bo_destroy);
- if (unlikely(r != 0)) {
+ acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
+ &amdgpu_ttm_bo_destroy);
+ if (unlikely(r != 0))
return r;
- }
if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
- struct fence *fence;
-
- if (adev->mman.buffer_funcs_ring == NULL ||
- !adev->mman.buffer_funcs_ring->ready) {
- r = -EBUSY;
- goto fail_free;
- }
-
- r = amdgpu_bo_reserve(bo, false);
- if (unlikely(r != 0))
- goto fail_free;
+ struct dma_fence *fence;
- amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
- r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
- if (unlikely(r != 0))
+ r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
+ if (unlikely(r))
goto fail_unreserve;
- amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
amdgpu_bo_fence(bo, fence, false);
- amdgpu_bo_unreserve(bo);
- fence_put(bo->tbo.moving);
- bo->tbo.moving = fence_get(fence);
- fence_put(fence);
+ dma_fence_put(bo->tbo.moving);
+ bo->tbo.moving = dma_fence_get(fence);
+ dma_fence_put(fence);
}
+ if (!resv)
+ ww_mutex_unlock(&bo->tbo.resv->lock);
*bo_ptr = bo;
trace_amdgpu_bo_create(bo);
@@ -414,8 +408,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
return 0;
fail_unreserve:
- amdgpu_bo_unreserve(bo);
-fail_free:
+ ww_mutex_unlock(&bo->tbo.resv->lock);
amdgpu_bo_unref(&bo);
return r;
}
@@ -491,7 +484,7 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
- struct fence **fence,
+ struct dma_fence **fence,
bool direct)
{
@@ -523,7 +516,7 @@ int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
- struct fence **fence,
+ struct dma_fence **fence,
bool direct)
{
@@ -616,6 +609,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
u64 min_offset, u64 max_offset,
u64 *gpu_addr)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r, i;
unsigned fpfn, lpfn;
@@ -643,18 +637,20 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
return 0;
}
+
+ bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
amdgpu_ttm_placement_from_domain(bo, domain);
for (i = 0; i < bo->placement.num_placement; i++) {
/* force to pin into visible video ram */
if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) &&
(!max_offset || max_offset >
- bo->adev->mc.visible_vram_size)) {
+ adev->mc.visible_vram_size)) {
if (WARN_ON_ONCE(min_offset >
- bo->adev->mc.visible_vram_size))
+ adev->mc.visible_vram_size))
return -EINVAL;
fpfn = min_offset >> PAGE_SHIFT;
- lpfn = bo->adev->mc.visible_vram_size >> PAGE_SHIFT;
+ lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
} else {
fpfn = min_offset >> PAGE_SHIFT;
lpfn = max_offset >> PAGE_SHIFT;
@@ -669,12 +665,12 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (unlikely(r)) {
- dev_err(bo->adev->dev, "%p pin failed\n", bo);
+ dev_err(adev->dev, "%p pin failed\n", bo);
goto error;
}
r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
if (unlikely(r)) {
- dev_err(bo->adev->dev, "%p bind failed\n", bo);
+ dev_err(adev->dev, "%p bind failed\n", bo);
goto error;
}
@@ -682,11 +678,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
if (gpu_addr != NULL)
*gpu_addr = amdgpu_bo_gpu_offset(bo);
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
- bo->adev->vram_pin_size += amdgpu_bo_size(bo);
+ adev->vram_pin_size += amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
- bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
+ adev->invisible_pin_size += amdgpu_bo_size(bo);
} else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
- bo->adev->gart_pin_size += amdgpu_bo_size(bo);
+ adev->gart_pin_size += amdgpu_bo_size(bo);
}
error:
@@ -700,10 +696,11 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr)
int amdgpu_bo_unpin(struct amdgpu_bo *bo)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r, i;
if (!bo->pin_count) {
- dev_warn(bo->adev->dev, "%p unpin not necessary\n", bo);
+ dev_warn(adev->dev, "%p unpin not necessary\n", bo);
return 0;
}
bo->pin_count--;
@@ -715,16 +712,16 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
}
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (unlikely(r)) {
- dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo);
+ dev_err(adev->dev, "%p validate failed for unpin\n", bo);
goto error;
}
if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
- bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
+ adev->vram_pin_size -= amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
- bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
+ adev->invisible_pin_size -= amdgpu_bo_size(bo);
} else if (bo->tbo.mem.mem_type == TTM_PL_TT) {
- bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
+ adev->gart_pin_size -= amdgpu_bo_size(bo);
}
error:
@@ -854,6 +851,7 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *new_mem)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
struct amdgpu_bo *abo;
struct ttm_mem_reg *old_mem = &bo->mem;
@@ -861,21 +859,21 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
return;
abo = container_of(bo, struct amdgpu_bo, tbo);
- amdgpu_vm_bo_invalidate(abo->adev, abo);
+ amdgpu_vm_bo_invalidate(adev, abo);
/* update statistics */
if (!new_mem)
return;
/* move_notify is called before move happens */
- amdgpu_update_memory_usage(abo->adev, &bo->mem, new_mem);
+ amdgpu_update_memory_usage(adev, &bo->mem, new_mem);
trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
}
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
{
- struct amdgpu_device *adev;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
struct amdgpu_bo *abo;
unsigned long offset, size, lpfn;
int i, r;
@@ -884,13 +882,14 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
return 0;
abo = container_of(bo, struct amdgpu_bo, tbo);
- adev = abo->adev;
if (bo->mem.mem_type != TTM_PL_VRAM)
return 0;
size = bo->mem.num_pages << PAGE_SHIFT;
offset = bo->mem.start << PAGE_SHIFT;
- if ((offset + size) <= adev->mc.visible_vram_size)
+ /* TODO: figure out how to map scattered VRAM to the CPU */
+ if ((offset + size) <= adev->mc.visible_vram_size &&
+ (abo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS))
return 0;
/* Can't move a pinned BO to visible VRAM */
@@ -898,6 +897,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
return -EINVAL;
/* hurrah the memory is not visible ! */
+ abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM);
lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
for (i = 0; i < abo->placement.num_placement; i++) {
@@ -931,7 +931,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
* @shared: true if fence should be added shared
*
*/
-void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
+void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
bool shared)
{
struct reservation_object *resv = bo->tbo.resv;
@@ -959,6 +959,8 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
!bo->pin_count);
WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET);
+ WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM &&
+ !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS));
return bo->tbo.offset;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 8255034d73eb..5cbf59ec0f68 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -71,12 +71,13 @@ static inline unsigned amdgpu_mem_type_to_domain(u32 mem_type)
*/
static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r;
r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS)
- dev_err(bo->adev->dev, "%p reserve failed\n", bo);
+ dev_err(adev->dev, "%p reserve failed\n", bo);
return r;
}
return 0;
@@ -156,19 +157,19 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *new_mem);
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
-void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
+void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
bool shared);
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
- struct fence **fence, bool direct);
+ struct dma_fence **fence, bool direct);
int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
- struct fence **fence,
+ struct dma_fence **fence,
bool direct);
@@ -200,7 +201,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
unsigned size, unsigned align);
void amdgpu_sa_bo_free(struct amdgpu_device *adev,
struct amdgpu_sa_bo **sa_bo,
- struct fence *fence);
+ struct dma_fence *fence);
#if defined(CONFIG_DEBUG_FS)
void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
struct seq_file *m);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index accc908bdc88..723ae682bf25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -737,6 +737,21 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev,
return sprintf(buf, "%i\n", speed);
}
+static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ int err;
+ u32 speed;
+
+ err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed);
+ if (err)
+ return err;
+
+ return sprintf(buf, "%i\n", speed);
+}
+
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1);
@@ -744,6 +759,7 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, amdgpu
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0);
static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0);
static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0);
static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -753,6 +769,7 @@ static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_pwm1_enable.dev_attr.attr,
&sensor_dev_attr_pwm1_min.dev_attr.attr,
&sensor_dev_attr_pwm1_max.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
NULL
};
@@ -804,6 +821,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
+ /* requires powerplay */
+ if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr)
+ return 0;
+
return effective_mode;
}
@@ -986,10 +1007,10 @@ restart_search:
static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
{
- int i;
struct amdgpu_ps *ps;
enum amd_pm_state_type dpm_state;
int ret;
+ bool equal;
/* if dpm init failed */
if (!adev->pm.dpm_enabled)
@@ -1009,46 +1030,6 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
else
return;
- /* no need to reprogram if nothing changed unless we are on BTC+ */
- if (adev->pm.dpm.current_ps == adev->pm.dpm.requested_ps) {
- /* vce just modifies an existing state so force a change */
- if (ps->vce_active != adev->pm.dpm.vce_active)
- goto force;
- if (adev->flags & AMD_IS_APU) {
- /* for APUs if the num crtcs changed but state is the same,
- * all we need to do is update the display configuration.
- */
- if (adev->pm.dpm.new_active_crtcs != adev->pm.dpm.current_active_crtcs) {
- /* update display watermarks based on new power state */
- amdgpu_display_bandwidth_update(adev);
- /* update displays */
- amdgpu_dpm_display_configuration_changed(adev);
- adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
- adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
- }
- return;
- } else {
- /* for BTC+ if the num crtcs hasn't changed and state is the same,
- * nothing to do, if the num crtcs is > 1 and state is the same,
- * update display configuration.
- */
- if (adev->pm.dpm.new_active_crtcs ==
- adev->pm.dpm.current_active_crtcs) {
- return;
- } else if ((adev->pm.dpm.current_active_crtc_count > 1) &&
- (adev->pm.dpm.new_active_crtc_count > 1)) {
- /* update display watermarks based on new power state */
- amdgpu_display_bandwidth_update(adev);
- /* update displays */
- amdgpu_dpm_display_configuration_changed(adev);
- adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
- adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
- return;
- }
- }
- }
-
-force:
if (amdgpu_dpm == 1) {
printk("switching from power state:\n");
amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps);
@@ -1059,31 +1040,21 @@ force:
/* update whether vce is active */
ps->vce_active = adev->pm.dpm.vce_active;
+ amdgpu_dpm_display_configuration_changed(adev);
+
ret = amdgpu_dpm_pre_set_power_state(adev);
if (ret)
return;
- /* update display watermarks based on new power state */
- amdgpu_display_bandwidth_update(adev);
+ if ((0 != amgdpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)))
+ equal = false;
- /* wait for the rings to drain */
- for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
- struct amdgpu_ring *ring = adev->rings[i];
- if (ring && ring->ready)
- amdgpu_fence_wait_empty(ring);
- }
+ if (equal)
+ return;
- /* program the new power state */
amdgpu_dpm_set_power_state(adev);
-
- /* update current power state */
- adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps;
-
amdgpu_dpm_post_set_power_state(adev);
- /* update displays */
- amdgpu_dpm_display_configuration_changed(adev);
-
adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
@@ -1135,7 +1106,7 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = true;
/* XXX select vce level based on ring/task */
- adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
+ adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
mutex_unlock(&adev->pm.mutex);
} else {
mutex_lock(&adev->pm.mutex);
@@ -1276,20 +1247,20 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
struct drm_device *ddev = adev->ddev;
struct drm_crtc *crtc;
struct amdgpu_crtc *amdgpu_crtc;
+ int i = 0;
if (!adev->pm.dpm_enabled)
return;
- if (adev->pp_enabled) {
- int i = 0;
+ amdgpu_display_bandwidth_update(adev);
- amdgpu_display_bandwidth_update(adev);
- for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
- struct amdgpu_ring *ring = adev->rings[i];
- if (ring && ring->ready)
- amdgpu_fence_wait_empty(ring);
- }
+ for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+ struct amdgpu_ring *ring = adev->rings[i];
+ if (ring && ring->ready)
+ amdgpu_fence_wait_empty(ring);
+ }
+ if (adev->pp_enabled) {
amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL);
} else {
mutex_lock(&adev->pm.mutex);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
index 7532ff822aa7..fc592c2b0e16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -155,9 +155,6 @@ static int amdgpu_pp_sw_init(void *handle)
ret = adev->powerplay.ip_funcs->sw_init(
adev->powerplay.pp_handle);
- if (adev->pp_enabled)
- adev->pm.dpm_enabled = true;
-
return ret;
}
@@ -187,6 +184,9 @@ static int amdgpu_pp_hw_init(void *handle)
ret = adev->powerplay.ip_funcs->hw_init(
adev->powerplay.pp_handle);
+ if ((amdgpu_dpm != 0) && !amdgpu_sriov_vf(adev))
+ adev->pm.dpm_enabled = true;
+
return ret;
}
@@ -299,7 +299,7 @@ static int amdgpu_pp_soft_reset(void *handle)
return ret;
}
-const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
+static const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
.name = "amdgpu_powerplay",
.early_init = amdgpu_pp_early_init,
.late_init = amdgpu_pp_late_init,
@@ -316,3 +316,12 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
.set_clockgating_state = amdgpu_pp_set_clockgating_state,
.set_powergating_state = amdgpu_pp_set_powergating_state,
};
+
+const struct amdgpu_ip_block_version amdgpu_pp_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SMC,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &amdgpu_pp_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
index da5cf47cfd99..c0c4bfdcdb14 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
@@ -23,11 +23,11 @@
*
*/
-#ifndef __AMDGPU_POPWERPLAY_H__
-#define __AMDGPU_POPWERPLAY_H__
+#ifndef __AMDGPU_POWERPLAY_H__
+#define __AMDGPU_POWERPLAY_H__
#include "amd_shared.h"
-extern const struct amd_ip_funcs amdgpu_pp_ip_funcs;
+extern const struct amdgpu_ip_block_version amdgpu_pp_ip_block;
-#endif /* __AMDSOC_DM_H__ */
+#endif /* __AMDGPU_POWERPLAY_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 3cb5e903cd62..4c992826d2d6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -65,7 +65,7 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw)
{
/* Align requested size with padding so unlock_commit can
* pad safely */
- ndw = (ndw + ring->align_mask) & ~ring->align_mask;
+ ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask;
/* Make sure we aren't trying to allocate more space
* than the maximum for one submission
@@ -94,7 +94,7 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
int i;
for (i = 0; i < count; i++)
- amdgpu_ring_write(ring, ring->nop);
+ amdgpu_ring_write(ring, ring->funcs->nop);
}
/** amdgpu_ring_generic_pad_ib - pad IB with NOP packets
@@ -106,8 +106,8 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
*/
void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
{
- while (ib->length_dw & ring->align_mask)
- ib->ptr[ib->length_dw++] = ring->nop;
+ while (ib->length_dw & ring->funcs->align_mask)
+ ib->ptr[ib->length_dw++] = ring->funcs->nop;
}
/**
@@ -125,8 +125,9 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)
uint32_t count;
/* We pad to match fetch size */
- count = ring->align_mask + 1 - (ring->wptr & ring->align_mask);
- count %= ring->align_mask + 1;
+ count = ring->funcs->align_mask + 1 -
+ (ring->wptr & ring->funcs->align_mask);
+ count %= ring->funcs->align_mask + 1;
ring->funcs->insert_nop(ring, count);
mb();
@@ -163,9 +164,8 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring)
* Returns 0 on success, error on failure.
*/
int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
- unsigned max_dw, u32 nop, u32 align_mask,
- struct amdgpu_irq_src *irq_src, unsigned irq_type,
- enum amdgpu_ring_type ring_type)
+ unsigned max_dw, struct amdgpu_irq_src *irq_src,
+ unsigned irq_type)
{
int r;
@@ -216,9 +216,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
ring->ring_size = roundup_pow_of_two(max_dw * 4 *
amdgpu_sched_hw_submission);
- ring->align_mask = align_mask;
- ring->nop = nop;
- ring->type = ring_type;
/* Allocate ring buffer */
if (ring->ring_obj == NULL) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
new file mode 100644
index 000000000000..574f0b79c690
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016 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) 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: Christian König
+ */
+#ifndef __AMDGPU_RING_H__
+#define __AMDGPU_RING_H__
+
+#include "gpu_scheduler.h"
+
+/* max number of rings */
+#define AMDGPU_MAX_RINGS 16
+#define AMDGPU_MAX_GFX_RINGS 1
+#define AMDGPU_MAX_COMPUTE_RINGS 8
+#define AMDGPU_MAX_VCE_RINGS 3
+
+/* some special values for the owner field */
+#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
+#define AMDGPU_FENCE_OWNER_VM ((void*)1ul)
+
+#define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
+#define AMDGPU_FENCE_FLAG_INT (1 << 1)
+
+enum amdgpu_ring_type {
+ AMDGPU_RING_TYPE_GFX,
+ AMDGPU_RING_TYPE_COMPUTE,
+ AMDGPU_RING_TYPE_SDMA,
+ AMDGPU_RING_TYPE_UVD,
+ AMDGPU_RING_TYPE_VCE,
+ AMDGPU_RING_TYPE_KIQ
+};
+
+struct amdgpu_device;
+struct amdgpu_ring;
+struct amdgpu_ib;
+struct amdgpu_cs_parser;
+
+/*
+ * Fences.
+ */
+struct amdgpu_fence_driver {
+ uint64_t gpu_addr;
+ volatile uint32_t *cpu_addr;
+ /* sync_seq is protected by ring emission lock */
+ uint32_t sync_seq;
+ atomic_t last_seq;
+ bool initialized;
+ struct amdgpu_irq_src *irq_src;
+ unsigned irq_type;
+ struct timer_list fallback_timer;
+ unsigned num_fences_mask;
+ spinlock_t lock;
+ struct dma_fence **fences;
+};
+
+int amdgpu_fence_driver_init(struct amdgpu_device *adev);
+void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
+void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
+
+int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
+ unsigned num_hw_submission);
+int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
+ struct amdgpu_irq_src *irq_src,
+ unsigned irq_type);
+void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
+void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence);
+void amdgpu_fence_process(struct amdgpu_ring *ring);
+int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
+unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
+
+/*
+ * Rings.
+ */
+
+/* provided by hw blocks that expose a ring buffer for commands */
+struct amdgpu_ring_funcs {
+ enum amdgpu_ring_type type;
+ uint32_t align_mask;
+ u32 nop;
+
+ /* ring read/write ptr handling */
+ u32 (*get_rptr)(struct amdgpu_ring *ring);
+ u32 (*get_wptr)(struct amdgpu_ring *ring);
+ void (*set_wptr)(struct amdgpu_ring *ring);
+ /* validating and patching of IBs */
+ int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
+ /* constants to calculate how many DW are needed for an emit */
+ unsigned emit_frame_size;
+ unsigned emit_ib_size;
+ /* command emit functions */
+ void (*emit_ib)(struct amdgpu_ring *ring,
+ struct amdgpu_ib *ib,
+ unsigned vm_id, bool ctx_switch);
+ void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
+ uint64_t seq, unsigned flags);
+ void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
+ void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
+ uint64_t pd_addr);
+ void (*emit_hdp_flush)(struct amdgpu_ring *ring);
+ void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
+ void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
+ uint32_t gds_base, uint32_t gds_size,
+ uint32_t gws_base, uint32_t gws_size,
+ uint32_t oa_base, uint32_t oa_size);
+ /* testing functions */
+ int (*test_ring)(struct amdgpu_ring *ring);
+ int (*test_ib)(struct amdgpu_ring *ring, long timeout);
+ /* insert NOP packets */
+ void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
+ /* pad the indirect buffer to the necessary number of dw */
+ void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+ unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
+ void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
+ /* note usage for clock and power gating */
+ void (*begin_use)(struct amdgpu_ring *ring);
+ void (*end_use)(struct amdgpu_ring *ring);
+ void (*emit_switch_buffer) (struct amdgpu_ring *ring);
+ void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
+};
+
+struct amdgpu_ring {
+ struct amdgpu_device *adev;
+ const struct amdgpu_ring_funcs *funcs;
+ struct amdgpu_fence_driver fence_drv;
+ struct amd_gpu_scheduler sched;
+
+ struct amdgpu_bo *ring_obj;
+ volatile uint32_t *ring;
+ unsigned rptr_offs;
+ unsigned wptr;
+ unsigned wptr_old;
+ unsigned ring_size;
+ unsigned max_dw;
+ int count_dw;
+ uint64_t gpu_addr;
+ uint32_t ptr_mask;
+ bool ready;
+ u32 idx;
+ u32 me;
+ u32 pipe;
+ u32 queue;
+ struct amdgpu_bo *mqd_obj;
+ u32 doorbell_index;
+ bool use_doorbell;
+ unsigned wptr_offs;
+ unsigned fence_offs;
+ uint64_t current_ctx;
+ char name[16];
+ unsigned cond_exe_offs;
+ u64 cond_exe_gpu_addr;
+ volatile u32 *cond_exe_cpu_addr;
+#if defined(CONFIG_DEBUG_FS)
+ struct dentry *ent;
+#endif
+};
+
+int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
+void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
+void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+void amdgpu_ring_commit(struct amdgpu_ring *ring);
+void amdgpu_ring_undo(struct amdgpu_ring *ring);
+int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
+ unsigned ring_size, struct amdgpu_irq_src *irq_src,
+ unsigned irq_type);
+void amdgpu_ring_fini(struct amdgpu_ring *ring);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index d8af37a845f4..de9f919ae336 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -147,7 +147,7 @@ static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo)
}
list_del_init(&sa_bo->olist);
list_del_init(&sa_bo->flist);
- fence_put(sa_bo->fence);
+ dma_fence_put(sa_bo->fence);
kfree(sa_bo);
}
@@ -161,7 +161,7 @@ static void amdgpu_sa_bo_try_free(struct amdgpu_sa_manager *sa_manager)
sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist);
list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) {
if (sa_bo->fence == NULL ||
- !fence_is_signaled(sa_bo->fence)) {
+ !dma_fence_is_signaled(sa_bo->fence)) {
return;
}
amdgpu_sa_bo_remove_locked(sa_bo);
@@ -244,7 +244,7 @@ static bool amdgpu_sa_event(struct amdgpu_sa_manager *sa_manager,
}
static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
- struct fence **fences,
+ struct dma_fence **fences,
unsigned *tries)
{
struct amdgpu_sa_bo *best_bo = NULL;
@@ -272,7 +272,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
sa_bo = list_first_entry(&sa_manager->flist[i],
struct amdgpu_sa_bo, flist);
- if (!fence_is_signaled(sa_bo->fence)) {
+ if (!dma_fence_is_signaled(sa_bo->fence)) {
fences[i] = sa_bo->fence;
continue;
}
@@ -314,7 +314,7 @@ 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_SA_NUM_FENCE_LISTS];
+ struct dma_fence *fences[AMDGPU_SA_NUM_FENCE_LISTS];
unsigned tries[AMDGPU_SA_NUM_FENCE_LISTS];
unsigned count;
int i, r;
@@ -327,9 +327,8 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
return -EINVAL;
*sa_bo = kmalloc(sizeof(struct amdgpu_sa_bo), GFP_KERNEL);
- if ((*sa_bo) == NULL) {
+ if (!(*sa_bo))
return -ENOMEM;
- }
(*sa_bo)->manager = sa_manager;
(*sa_bo)->fence = NULL;
INIT_LIST_HEAD(&(*sa_bo)->olist);
@@ -356,14 +355,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
for (i = 0, count = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i)
if (fences[i])
- fences[count++] = fence_get(fences[i]);
+ fences[count++] = dma_fence_get(fences[i]);
if (count) {
spin_unlock(&sa_manager->wq.lock);
- t = fence_wait_any_timeout(fences, count, false,
- MAX_SCHEDULE_TIMEOUT);
+ t = dma_fence_wait_any_timeout(fences, count, false,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
for (i = 0; i < count; ++i)
- fence_put(fences[i]);
+ dma_fence_put(fences[i]);
r = (t > 0) ? 0 : t;
spin_lock(&sa_manager->wq.lock);
@@ -384,7 +384,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
}
void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
- struct fence *fence)
+ struct dma_fence *fence)
{
struct amdgpu_sa_manager *sa_manager;
@@ -394,10 +394,10 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
sa_manager = (*sa_bo)->manager;
spin_lock(&sa_manager->wq.lock);
- if (fence && !fence_is_signaled(fence)) {
+ if (fence && !dma_fence_is_signaled(fence)) {
uint32_t idx;
- (*sa_bo)->fence = fence_get(fence);
+ (*sa_bo)->fence = dma_fence_get(fence);
idx = fence->context % AMDGPU_SA_NUM_FENCE_LISTS;
list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]);
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 5c8d3022fb87..ed814e6d0207 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -34,7 +34,7 @@
struct amdgpu_sync_entry {
struct hlist_node node;
- struct fence *fence;
+ struct dma_fence *fence;
};
static struct kmem_cache *amdgpu_sync_slab;
@@ -60,7 +60,8 @@ void amdgpu_sync_create(struct amdgpu_sync *sync)
*
* Test if the fence was issued by us.
*/
-static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
+static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
+ struct dma_fence *f)
{
struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
@@ -81,7 +82,7 @@ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
*
* Extract who originally created the fence.
*/
-static void *amdgpu_sync_get_owner(struct fence *f)
+static void *amdgpu_sync_get_owner(struct dma_fence *f)
{
struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
@@ -99,13 +100,14 @@ static void *amdgpu_sync_get_owner(struct fence *f)
*
* Either keep the existing fence or the new one, depending which one is later.
*/
-static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
+static void amdgpu_sync_keep_later(struct dma_fence **keep,
+ struct dma_fence *fence)
{
- if (*keep && fence_is_later(*keep, fence))
+ if (*keep && dma_fence_is_later(*keep, fence))
return;
- fence_put(*keep);
- *keep = fence_get(fence);
+ dma_fence_put(*keep);
+ *keep = dma_fence_get(fence);
}
/**
@@ -117,7 +119,7 @@ static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
* Tries to add the fence to an existing hash entry. Returns true when an entry
* was found, false otherwise.
*/
-static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f)
+static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f)
{
struct amdgpu_sync_entry *e;
@@ -139,7 +141,7 @@ static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f)
*
*/
int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
- struct fence *f)
+ struct dma_fence *f)
{
struct amdgpu_sync_entry *e;
@@ -158,7 +160,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
return -ENOMEM;
hash_add(sync->fences, &e->node, f->context);
- e->fence = fence_get(f);
+ e->fence = dma_fence_get(f);
return 0;
}
@@ -177,7 +179,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
void *owner)
{
struct reservation_object_list *flist;
- struct fence *f;
+ struct dma_fence *f;
void *fence_owner;
unsigned i;
int r = 0;
@@ -231,15 +233,15 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
* Returns the next fence not signaled yet without removing it from the sync
* object.
*/
-struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
- struct amdgpu_ring *ring)
+struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+ struct amdgpu_ring *ring)
{
struct amdgpu_sync_entry *e;
struct hlist_node *tmp;
int i;
hash_for_each_safe(sync->fences, i, tmp, e, node) {
- struct fence *f = e->fence;
+ struct dma_fence *f = e->fence;
struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
if (ring && s_fence) {
@@ -247,16 +249,16 @@ struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
* when they are scheduled.
*/
if (s_fence->sched == &ring->sched) {
- if (fence_is_signaled(&s_fence->scheduled))
+ if (dma_fence_is_signaled(&s_fence->scheduled))
continue;
return &s_fence->scheduled;
}
}
- if (fence_is_signaled(f)) {
+ if (dma_fence_is_signaled(f)) {
hash_del(&e->node);
- fence_put(f);
+ dma_fence_put(f);
kmem_cache_free(amdgpu_sync_slab, e);
continue;
}
@@ -274,11 +276,11 @@ struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
*
* Get and removes the next fence from the sync object not signaled yet.
*/
-struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
+struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
{
struct amdgpu_sync_entry *e;
struct hlist_node *tmp;
- struct fence *f;
+ struct dma_fence *f;
int i;
hash_for_each_safe(sync->fences, i, tmp, e, node) {
@@ -288,10 +290,10 @@ struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
hash_del(&e->node);
kmem_cache_free(amdgpu_sync_slab, e);
- if (!fence_is_signaled(f))
+ if (!dma_fence_is_signaled(f))
return f;
- fence_put(f);
+ dma_fence_put(f);
}
return NULL;
}
@@ -311,11 +313,11 @@ void amdgpu_sync_free(struct amdgpu_sync *sync)
hash_for_each_safe(sync->fences, i, tmp, e, node) {
hash_del(&e->node);
- fence_put(e->fence);
+ dma_fence_put(e->fence);
kmem_cache_free(amdgpu_sync_slab, e);
}
- fence_put(sync->last_vm_update);
+ dma_fence_put(sync->last_vm_update);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
new file mode 100644
index 000000000000..605be266e07f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 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) 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: Christian König
+ */
+#ifndef __AMDGPU_SYNC_H__
+#define __AMDGPU_SYNC_H__
+
+#include <linux/hashtable.h>
+
+struct dma_fence;
+struct reservation_object;
+struct amdgpu_device;
+struct amdgpu_ring;
+
+/*
+ * Container for fences used to sync command submissions.
+ */
+struct amdgpu_sync {
+ DECLARE_HASHTABLE(fences, 4);
+ struct dma_fence *last_vm_update;
+};
+
+void amdgpu_sync_create(struct amdgpu_sync *sync);
+int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
+ struct dma_fence *f);
+int amdgpu_sync_resv(struct amdgpu_device *adev,
+ struct amdgpu_sync *sync,
+ struct reservation_object *resv,
+ void *owner);
+struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+ struct amdgpu_ring *ring);
+struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
+void amdgpu_sync_free(struct amdgpu_sync *sync);
+int amdgpu_sync_init(void);
+void amdgpu_sync_fini(void);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
index b827c75e95de..e05a24325eeb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
@@ -78,7 +78,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
void *gtt_map, *vram_map;
void **gtt_start, **gtt_end;
void **vram_start, **vram_end;
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
@@ -118,13 +118,13 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
goto out_lclean_unpin;
}
- r = fence_wait(fence, false);
+ r = dma_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
goto out_lclean_unpin;
}
- fence_put(fence);
+ dma_fence_put(fence);
r = amdgpu_bo_kmap(vram_obj, &vram_map);
if (r) {
@@ -163,13 +163,13 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
goto out_lclean_unpin;
}
- r = fence_wait(fence, false);
+ r = dma_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
goto out_lclean_unpin;
}
- fence_put(fence);
+ dma_fence_put(fence);
r = amdgpu_bo_kmap(gtt_obj[i], &gtt_map);
if (r) {
@@ -216,7 +216,7 @@ out_lclean:
amdgpu_bo_unref(&gtt_obj[i]);
}
if (fence)
- fence_put(fence);
+ dma_fence_put(fence);
break;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 067e5e683bb3..bb964a8ff938 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -104,7 +104,7 @@ TRACE_EVENT(amdgpu_cs_ioctl,
__field(struct amdgpu_device *, adev)
__field(struct amd_sched_job *, sched_job)
__field(struct amdgpu_ib *, ib)
- __field(struct fence *, fence)
+ __field(struct dma_fence *, fence)
__field(char *, ring_name)
__field(u32, num_ibs)
),
@@ -129,7 +129,7 @@ TRACE_EVENT(amdgpu_sched_run_job,
__field(struct amdgpu_device *, adev)
__field(struct amd_sched_job *, sched_job)
__field(struct amdgpu_ib *, ib)
- __field(struct fence *, fence)
+ __field(struct dma_fence *, fence)
__field(char *, ring_name)
__field(u32, num_ibs)
),
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index dcaf691f56b5..bc70f80260d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -34,7 +34,6 @@
#include <ttm/ttm_placement.h>
#include <ttm/ttm_module.h>
#include <ttm/ttm_page_alloc.h>
-#include <ttm/ttm_memory.h>
#include <drm/drmP.h>
#include <drm/amdgpu_drm.h>
#include <linux/seq_file.h>
@@ -51,16 +50,6 @@
static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev);
static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev);
-static struct amdgpu_device *amdgpu_get_adev(struct ttm_bo_device *bdev)
-{
- struct amdgpu_mman *mman;
- struct amdgpu_device *adev;
-
- mman = container_of(bdev, struct amdgpu_mman, bdev);
- adev = container_of(mman, struct amdgpu_device, mman);
- return adev;
-}
-
/*
* Global memory.
@@ -75,7 +64,7 @@ static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref)
ttm_mem_global_release(ref->object);
}
-int amdgpu_ttm_global_init(struct amdgpu_device *adev)
+static int amdgpu_ttm_global_init(struct amdgpu_device *adev)
{
struct drm_global_reference *global_ref;
struct amdgpu_ring *ring;
@@ -150,7 +139,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
{
struct amdgpu_device *adev;
- adev = amdgpu_get_adev(bdev);
+ adev = amdgpu_ttm_adev(bdev);
switch (type) {
case TTM_PL_SYSTEM:
@@ -168,7 +157,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
break;
case TTM_PL_VRAM:
/* "On-card" video ram */
- man->func = &ttm_bo_manager_func;
+ man->func = &amdgpu_vram_mgr_func;
man->gpu_offset = adev->mc.vram_start;
man->flags = TTM_MEMTYPE_FLAG_FIXED |
TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -195,6 +184,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
struct ttm_placement *placement)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
struct amdgpu_bo *abo;
static struct ttm_place placements = {
.fpfn = 0,
@@ -213,7 +203,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
abo = container_of(bo, struct amdgpu_bo, tbo);
switch (bo->mem.mem_type) {
case TTM_PL_VRAM:
- if (abo->adev->mman.buffer_funcs_ring->ready == false) {
+ if (adev->mman.buffer_funcs_ring->ready == false) {
amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
} else {
amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT);
@@ -229,7 +219,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
* allocating address space for the BO.
*/
abo->placements[i].lpfn =
- abo->adev->mc.gtt_size >> PAGE_SHIFT;
+ adev->mc.gtt_size >> PAGE_SHIFT;
}
}
break;
@@ -260,63 +250,115 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo,
new_mem->mm_node = NULL;
}
-static int amdgpu_move_blit(struct ttm_buffer_object *bo,
- bool evict, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem,
- struct ttm_mem_reg *old_mem)
+static int amdgpu_mm_node_addr(struct ttm_buffer_object *bo,
+ struct drm_mm_node *mm_node,
+ struct ttm_mem_reg *mem,
+ uint64_t *addr)
{
- struct amdgpu_device *adev;
- struct amdgpu_ring *ring;
- uint64_t old_start, new_start;
- struct fence *fence;
int r;
- adev = amdgpu_get_adev(bo->bdev);
- ring = adev->mman.buffer_funcs_ring;
-
- switch (old_mem->mem_type) {
+ switch (mem->mem_type) {
case TTM_PL_TT:
- r = amdgpu_ttm_bind(bo, old_mem);
+ r = amdgpu_ttm_bind(bo, mem);
if (r)
return r;
case TTM_PL_VRAM:
- old_start = (u64)old_mem->start << PAGE_SHIFT;
- old_start += bo->bdev->man[old_mem->mem_type].gpu_offset;
+ *addr = mm_node->start << PAGE_SHIFT;
+ *addr += bo->bdev->man[mem->mem_type].gpu_offset;
break;
default:
- DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+ DRM_ERROR("Unknown placement %d\n", mem->mem_type);
return -EINVAL;
}
- switch (new_mem->mem_type) {
- case TTM_PL_TT:
- r = amdgpu_ttm_bind(bo, new_mem);
- if (r)
- return r;
- case TTM_PL_VRAM:
- new_start = (u64)new_mem->start << PAGE_SHIFT;
- new_start += bo->bdev->man[new_mem->mem_type].gpu_offset;
- break;
- default:
- DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
- return -EINVAL;
- }
+ return 0;
+}
+
+static int amdgpu_move_blit(struct ttm_buffer_object *bo,
+ bool evict, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem,
+ struct ttm_mem_reg *old_mem)
+{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
+ struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
+
+ struct drm_mm_node *old_mm, *new_mm;
+ uint64_t old_start, old_size, new_start, new_size;
+ unsigned long num_pages;
+ struct dma_fence *fence = NULL;
+ int r;
+
+ BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0);
+
if (!ring->ready) {
DRM_ERROR("Trying to move memory with ring turned off.\n");
return -EINVAL;
}
- BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0);
+ old_mm = old_mem->mm_node;
+ r = amdgpu_mm_node_addr(bo, old_mm, old_mem, &old_start);
+ if (r)
+ return r;
+ old_size = old_mm->size;
+
- r = amdgpu_copy_buffer(ring, old_start, new_start,
- new_mem->num_pages * PAGE_SIZE, /* bytes */
- bo->resv, &fence, false);
+ new_mm = new_mem->mm_node;
+ r = amdgpu_mm_node_addr(bo, new_mm, new_mem, &new_start);
if (r)
return r;
+ new_size = new_mm->size;
+
+ num_pages = new_mem->num_pages;
+ while (num_pages) {
+ unsigned long cur_pages = min(old_size, new_size);
+ struct dma_fence *next;
+
+ r = amdgpu_copy_buffer(ring, old_start, new_start,
+ cur_pages * PAGE_SIZE,
+ bo->resv, &next, false);
+ if (r)
+ goto error;
+
+ dma_fence_put(fence);
+ fence = next;
+
+ num_pages -= cur_pages;
+ if (!num_pages)
+ break;
+
+ old_size -= cur_pages;
+ if (!old_size) {
+ r = amdgpu_mm_node_addr(bo, ++old_mm, old_mem,
+ &old_start);
+ if (r)
+ goto error;
+ old_size = old_mm->size;
+ } else {
+ old_start += cur_pages * PAGE_SIZE;
+ }
+
+ new_size -= cur_pages;
+ if (!new_size) {
+ r = amdgpu_mm_node_addr(bo, ++new_mm, new_mem,
+ &new_start);
+ if (r)
+ goto error;
+
+ new_size = new_mm->size;
+ } else {
+ new_start += cur_pages * PAGE_SIZE;
+ }
+ }
r = ttm_bo_pipeline_move(bo, fence, evict, new_mem);
- fence_put(fence);
+ dma_fence_put(fence);
+ return r;
+
+error:
+ if (fence)
+ dma_fence_wait(fence, false);
+ dma_fence_put(fence);
return r;
}
@@ -332,7 +374,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
struct ttm_placement placement;
int r;
- adev = amdgpu_get_adev(bo->bdev);
+ adev = amdgpu_ttm_adev(bo->bdev);
tmp_mem = *new_mem;
tmp_mem.mm_node = NULL;
placement.num_placement = 1;
@@ -379,7 +421,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
struct ttm_place placements;
int r;
- adev = amdgpu_get_adev(bo->bdev);
+ adev = amdgpu_ttm_adev(bo->bdev);
tmp_mem = *new_mem;
tmp_mem.mm_node = NULL;
placement.num_placement = 1;
@@ -422,7 +464,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo,
if (WARN_ON_ONCE(abo->pin_count > 0))
return -EINVAL;
- adev = amdgpu_get_adev(bo->bdev);
+ adev = amdgpu_ttm_adev(bo->bdev);
/* remember the eviction */
if (evict)
@@ -475,7 +517,7 @@ memcpy:
static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
{
struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
- struct amdgpu_device *adev = amdgpu_get_adev(bdev);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
mem->bus.addr = NULL;
mem->bus.offset = 0;
@@ -607,7 +649,7 @@ release_pages:
/* prepare the sg table with the user pages */
static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
{
- struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
unsigned nents;
int r;
@@ -639,7 +681,7 @@ release_sg:
static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
{
- struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
struct sg_page_iter sg_iter;
@@ -799,7 +841,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_bo_device *bdev,
struct amdgpu_device *adev;
struct amdgpu_ttm_tt *gtt;
- adev = amdgpu_get_adev(bdev);
+ adev = amdgpu_ttm_adev(bdev);
gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL);
if (gtt == NULL) {
@@ -843,7 +885,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm)
return 0;
}
- adev = amdgpu_get_adev(ttm->bdev);
+ adev = amdgpu_ttm_adev(ttm->bdev);
#ifdef CONFIG_SWIOTLB
if (swiotlb_nr_tbl()) {
@@ -889,7 +931,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
if (slave)
return;
- adev = amdgpu_get_adev(ttm->bdev);
+ adev = amdgpu_ttm_adev(ttm->bdev);
#ifdef CONFIG_SWIOTLB
if (swiotlb_nr_tbl()) {
@@ -1012,7 +1054,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo)
{
- struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
unsigned i, j;
for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
@@ -1029,7 +1071,7 @@ static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo)
static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo)
{
- struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
unsigned log2_size = min(ilog2(tbo->num_pages),
AMDGPU_TTM_LRU_SIZE - 1);
@@ -1060,12 +1102,37 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo)
return res;
}
+static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
+ const struct ttm_place *place)
+{
+ if (bo->mem.mem_type == TTM_PL_VRAM &&
+ bo->mem.start == AMDGPU_BO_INVALID_OFFSET) {
+ unsigned long num_pages = bo->mem.num_pages;
+ struct drm_mm_node *node = bo->mem.mm_node;
+
+ /* Check each drm MM node individually */
+ while (num_pages) {
+ if (place->fpfn < (node->start + node->size) &&
+ !(place->lpfn && place->lpfn <= node->start))
+ return true;
+
+ num_pages -= node->size;
+ ++node;
+ }
+
+ return false;
+ }
+
+ return ttm_bo_eviction_valuable(bo, place);
+}
+
static struct ttm_bo_driver amdgpu_bo_driver = {
.ttm_tt_create = &amdgpu_ttm_tt_create,
.ttm_tt_populate = &amdgpu_ttm_tt_populate,
.ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate,
.invalidate_caches = &amdgpu_invalidate_caches,
.init_mem_type = &amdgpu_init_mem_type,
+ .eviction_valuable = amdgpu_ttm_bo_eviction_valuable,
.evict_flags = &amdgpu_evict_flags,
.move = &amdgpu_bo_move,
.verify_access = &amdgpu_verify_access,
@@ -1083,6 +1150,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
unsigned i, j;
int r;
+ r = amdgpu_ttm_global_init(adev);
+ if (r) {
+ return r;
+ }
/* No others user of address space so set it to 0 */
r = ttm_bo_device_init(&adev->mman.bdev,
adev->mman.bo_global_ref.ref.object,
@@ -1119,7 +1190,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &adev->stollen_vga_memory);
if (r) {
return r;
@@ -1247,7 +1319,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
- struct fence **fence, bool direct_submit)
+ struct dma_fence **fence, bool direct_submit)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_job *job;
@@ -1294,7 +1366,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
if (direct_submit) {
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs,
NULL, NULL, fence);
- job->fence = fence_get(*fence);
+ job->fence = dma_fence_get(*fence);
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
amdgpu_job_free(job);
@@ -1313,28 +1385,40 @@ error_free:
}
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
- uint32_t src_data,
- struct reservation_object *resv,
- struct fence **fence)
+ uint32_t src_data,
+ struct reservation_object *resv,
+ struct dma_fence **fence)
{
- struct amdgpu_device *adev = bo->adev;
- struct amdgpu_job *job;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
- uint32_t max_bytes, byte_count;
- uint64_t dst_offset;
+ struct drm_mm_node *mm_node;
+ unsigned long num_pages;
unsigned int num_loops, num_dw;
- unsigned int i;
+
+ struct amdgpu_job *job;
int r;
- byte_count = bo->tbo.num_pages << PAGE_SHIFT;
- max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
- num_loops = DIV_ROUND_UP(byte_count, max_bytes);
+ if (!ring->ready) {
+ DRM_ERROR("Trying to clear memory with ring turned off.\n");
+ return -EINVAL;
+ }
+
+ num_pages = bo->tbo.num_pages;
+ mm_node = bo->tbo.mem.mm_node;
+ num_loops = 0;
+ while (num_pages) {
+ uint32_t byte_count = mm_node->size << PAGE_SHIFT;
+
+ num_loops += DIV_ROUND_UP(byte_count, max_bytes);
+ num_pages -= mm_node->size;
+ ++mm_node;
+ }
num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;
/* for IB padding */
- while (num_dw & 0x7)
- num_dw++;
+ num_dw += 64;
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
if (r)
@@ -1342,28 +1426,43 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
if (resv) {
r = amdgpu_sync_resv(adev, &job->sync, resv,
- AMDGPU_FENCE_OWNER_UNDEFINED);
+ AMDGPU_FENCE_OWNER_UNDEFINED);
if (r) {
DRM_ERROR("sync failed (%d).\n", r);
goto error_free;
}
}
- dst_offset = bo->tbo.mem.start << PAGE_SHIFT;
- for (i = 0; i < num_loops; i++) {
- uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
+ num_pages = bo->tbo.num_pages;
+ mm_node = bo->tbo.mem.mm_node;
- amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
- dst_offset, cur_size_in_bytes);
+ while (num_pages) {
+ uint32_t byte_count = mm_node->size << PAGE_SHIFT;
+ uint64_t dst_addr;
- dst_offset += cur_size_in_bytes;
- byte_count -= cur_size_in_bytes;
+ r = amdgpu_mm_node_addr(&bo->tbo, mm_node,
+ &bo->tbo.mem, &dst_addr);
+ if (r)
+ return r;
+
+ while (byte_count) {
+ uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
+
+ amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
+ dst_addr, cur_size_in_bytes);
+
+ dst_addr += cur_size_in_bytes;
+ byte_count -= cur_size_in_bytes;
+ }
+
+ num_pages -= mm_node->size;
+ ++mm_node;
}
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
r = amdgpu_job_submit(job, ring, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, fence);
+ AMDGPU_FENCE_OWNER_UNDEFINED, fence);
if (r)
goto error_free;
@@ -1554,8 +1653,3 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev)
#endif
}
-
-u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev)
-{
- return ttm_get_kernel_zone_memory_size(adev->mman.mem_global_ref.object);
-}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index 9812c805326c..98ee384f0fca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -66,6 +66,7 @@ struct amdgpu_mman {
};
extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func;
+extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func;
int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *tbo,
@@ -77,11 +78,11 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
- struct fence **fence, bool direct_submit);
+ struct dma_fence **fence, bool direct_submit);
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct reservation_object *resv,
- struct fence **fence);
+ struct dma_fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
bool amdgpu_ttm_is_bound(struct ttm_tt *ttm);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index cb3d252f3c78..0f0b38191fac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -228,6 +228,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,
ucode->mc_addr = mc_addr;
ucode->kaddr = kptr;
+ if (ucode->ucode_id == AMDGPU_UCODE_ID_STORAGE)
+ return 0;
+
header = (const struct common_firmware_header *)ucode->fw->data;
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes)),
@@ -236,6 +239,31 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,
return 0;
}
+static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
+ uint64_t mc_addr, void *kptr)
+{
+ const struct gfx_firmware_header_v1_0 *header = NULL;
+ const struct common_firmware_header *comm_hdr = NULL;
+ uint8_t* src_addr = NULL;
+ uint8_t* dst_addr = NULL;
+
+ if (NULL == ucode->fw)
+ return 0;
+
+ comm_hdr = (const struct common_firmware_header *)ucode->fw->data;
+ header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+ dst_addr = ucode->kaddr +
+ ALIGN(le32_to_cpu(comm_hdr->ucode_size_bytes),
+ PAGE_SIZE);
+ src_addr = (uint8_t *)ucode->fw->data +
+ le32_to_cpu(comm_hdr->ucode_array_offset_bytes) +
+ (le32_to_cpu(header->jt_offset) * 4);
+ memcpy(dst_addr, src_addr, le32_to_cpu(header->jt_size) * 4);
+
+ return 0;
+}
+
+
int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
{
struct amdgpu_bo **bo = &adev->firmware.fw_buf;
@@ -247,7 +275,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
const struct common_firmware_header *header = NULL;
err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true,
- AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo);
+ amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
+ 0, NULL, NULL, bo);
if (err) {
dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err);
goto failed;
@@ -259,7 +288,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
goto failed_reserve;
}
- err = amdgpu_bo_pin(*bo, AMDGPU_GEM_DOMAIN_GTT, &fw_mc_addr);
+ err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
+ &fw_mc_addr);
if (err) {
dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err);
goto failed_pin;
@@ -279,6 +309,13 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
header = (const struct common_firmware_header *)ucode->fw->data;
amdgpu_ucode_init_single_fw(ucode, fw_mc_addr + fw_offset,
fw_buf_ptr + fw_offset);
+ if (i == AMDGPU_UCODE_ID_CP_MEC1) {
+ const struct gfx_firmware_header_v1_0 *cp_hdr;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+ amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset,
+ fw_buf_ptr + fw_offset);
+ fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+ }
fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index e468be4e28fa..a8a4230729f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -130,6 +130,7 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_CP_MEC1,
AMDGPU_UCODE_ID_CP_MEC2,
AMDGPU_UCODE_ID_RLC_G,
+ AMDGPU_UCODE_ID_STORAGE,
AMDGPU_UCODE_ID_MAXIMUM,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index e3281cacc586..a81dfaeeb8c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -333,7 +333,7 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
for (i = 0; i < adev->uvd.max_handles; ++i) {
uint32_t handle = atomic_read(&adev->uvd.handles[i]);
if (handle != 0 && adev->uvd.filp[i] == filp) {
- struct fence *fence;
+ struct dma_fence *fence;
r = amdgpu_uvd_get_destroy_msg(ring, handle,
false, &fence);
@@ -342,8 +342,8 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
continue;
}
- fence_wait(fence, false);
- fence_put(fence);
+ dma_fence_wait(fence, false);
+ dma_fence_put(fence);
adev->uvd.filp[i] = NULL;
atomic_set(&adev->uvd.handles[i], 0);
@@ -360,6 +360,18 @@ static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
}
}
+static u64 amdgpu_uvd_get_addr_from_ctx(struct amdgpu_uvd_cs_ctx *ctx)
+{
+ uint32_t lo, hi;
+ uint64_t addr;
+
+ lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
+ hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
+ addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
+
+ return addr;
+}
+
/**
* amdgpu_uvd_cs_pass1 - first parsing round
*
@@ -372,14 +384,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
{
struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_bo *bo;
- uint32_t cmd, lo, hi;
- uint64_t addr;
+ uint32_t cmd;
+ uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx);
int r = 0;
- lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
- hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
- addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
-
mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo);
if (mapping == NULL) {
DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
@@ -698,18 +706,16 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
{
struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_bo *bo;
- uint32_t cmd, lo, hi;
+ uint32_t cmd;
uint64_t start, end;
- uint64_t addr;
+ uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx);
int r;
- lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
- hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
- addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
-
mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo);
- if (mapping == NULL)
+ if (mapping == NULL) {
+ DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
return -EINVAL;
+ }
start = amdgpu_bo_gpu_offset(bo);
@@ -876,6 +882,9 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
struct amdgpu_ib *ib = &parser->job->ibs[ib_idx];
int r;
+ parser->job->vm = NULL;
+ ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
+
if (ib->length_dw % 16) {
DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n",
ib->length_dw);
@@ -890,10 +899,13 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
ctx.buf_sizes = buf_sizes;
ctx.ib_idx = ib_idx;
- /* first round, make sure the buffers are actually in the UVD segment */
- r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1);
- if (r)
- return r;
+ /* first round only required on chips without UVD 64 bit address support */
+ if (!parser->adev->uvd.address_64_bit) {
+ /* first round, make sure the buffers are actually in the UVD segment */
+ r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1);
+ if (r)
+ return r;
+ }
/* second round, patch buffer addresses into the command stream */
r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass2);
@@ -909,14 +921,14 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
}
static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
- bool direct, struct fence **fence)
+ bool direct, struct dma_fence **fence)
{
struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket;
struct list_head head;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
struct amdgpu_device *adev = ring->adev;
uint64_t addr;
int i, r;
@@ -931,7 +943,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
if (r)
return r;
- if (!bo->adev->uvd.address_64_bit) {
+ if (!ring->adev->uvd.address_64_bit) {
amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
amdgpu_uvd_force_into_uvd_segment(bo);
}
@@ -960,7 +972,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
if (direct) {
r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
- job->fence = fence_get(f);
+ job->fence = dma_fence_get(f);
if (r)
goto err_free;
@@ -975,9 +987,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
ttm_eu_fence_buffer_objects(&ticket, &head, f);
if (fence)
- *fence = fence_get(f);
+ *fence = dma_fence_get(f);
amdgpu_bo_unref(&bo);
- fence_put(f);
+ dma_fence_put(f);
return 0;
@@ -993,7 +1005,7 @@ err:
crash the vcpu so just try to emmit a dummy create/destroy msg to
avoid this */
int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
- struct fence **fence)
+ struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_bo *bo;
@@ -1002,7 +1014,8 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &bo);
if (r)
return r;
@@ -1042,7 +1055,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
}
int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct fence **fence)
+ bool direct, struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_bo *bo;
@@ -1051,7 +1064,8 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &bo);
if (r)
return r;
@@ -1128,7 +1142,7 @@ void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring)
*/
int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
- struct fence *fence;
+ struct dma_fence *fence;
long r;
r = amdgpu_uvd_get_create_msg(ring, 1, NULL);
@@ -1143,7 +1157,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
goto error;
}
- r = fence_wait_timeout(fence, false, timeout);
+ r = dma_fence_wait_timeout(fence, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out.\n");
r = -ETIMEDOUT;
@@ -1154,7 +1168,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
r = 0;
}
- fence_put(fence);
+ dma_fence_put(fence);
error:
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index c850009602d1..6249ba1bde2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -29,9 +29,9 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev);
int amdgpu_uvd_suspend(struct amdgpu_device *adev);
int amdgpu_uvd_resume(struct amdgpu_device *adev);
int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
- struct fence **fence);
+ struct dma_fence **fence);
int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct fence **fence);
+ bool direct, struct dma_fence **fence);
void amdgpu_uvd_free_handles(struct amdgpu_device *adev,
struct drm_file *filp);
int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 7fe8fd884f06..69b66b9e7f57 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -157,7 +157,8 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL, &adev->vce.vcpu_bo);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
@@ -395,12 +396,12 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
* Open up a stream for HW test
*/
int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
- struct fence **fence)
+ struct dma_fence **fence)
{
const unsigned ib_size_dw = 1024;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
uint64_t dummy;
int i, r;
@@ -450,14 +451,14 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
ib->ptr[i] = 0x0;
r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
- job->fence = fence_get(f);
+ job->fence = dma_fence_get(f);
if (r)
goto err;
amdgpu_job_free(job);
if (fence)
- *fence = fence_get(f);
- fence_put(f);
+ *fence = dma_fence_get(f);
+ dma_fence_put(f);
return 0;
err:
@@ -476,12 +477,12 @@ err:
* Close up a stream for HW test or if userspace failed to do so
*/
int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct fence **fence)
+ bool direct, struct dma_fence **fence)
{
const unsigned ib_size_dw = 1024;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -513,7 +514,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
if (direct) {
r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
- job->fence = fence_get(f);
+ job->fence = dma_fence_get(f);
if (r)
goto err;
@@ -526,8 +527,8 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
}
if (fence)
- *fence = fence_get(f);
- fence_put(f);
+ *fence = dma_fence_get(f);
+ dma_fence_put(f);
return 0;
err:
@@ -641,6 +642,9 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
uint32_t *size = &tmp;
int i, r, idx = 0;
+ p->job->vm = NULL;
+ ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
+
r = amdgpu_cs_sysvm_access_required(p);
if (r)
return r;
@@ -788,6 +792,96 @@ out:
}
/**
+ * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode
+ *
+ * @p: parser context
+ *
+ */
+int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx)
+{
+ struct amdgpu_ib *ib = &p->job->ibs[ib_idx];
+ int session_idx = -1;
+ uint32_t destroyed = 0;
+ uint32_t created = 0;
+ uint32_t allocated = 0;
+ uint32_t tmp, handle = 0;
+ int i, r = 0, idx = 0;
+
+ while (idx < ib->length_dw) {
+ uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
+ uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
+
+ if ((len < 8) || (len & 3)) {
+ DRM_ERROR("invalid VCE command length (%d)!\n", len);
+ r = -EINVAL;
+ goto out;
+ }
+
+ switch (cmd) {
+ case 0x00000001: /* session */
+ handle = amdgpu_get_ib_value(p, ib_idx, idx + 2);
+ session_idx = amdgpu_vce_validate_handle(p, handle,
+ &allocated);
+ if (session_idx < 0) {
+ r = session_idx;
+ goto out;
+ }
+ break;
+
+ case 0x01000001: /* create */
+ created |= 1 << session_idx;
+ if (destroyed & (1 << session_idx)) {
+ destroyed &= ~(1 << session_idx);
+ allocated |= 1 << session_idx;
+
+ } else if (!(allocated & (1 << session_idx))) {
+ DRM_ERROR("Handle already in use!\n");
+ r = -EINVAL;
+ goto out;
+ }
+
+ break;
+
+ case 0x02000001: /* destroy */
+ destroyed |= 1 << session_idx;
+ break;
+
+ default:
+ break;
+ }
+
+ if (session_idx == -1) {
+ DRM_ERROR("no session command at start of IB\n");
+ r = -EINVAL;
+ goto out;
+ }
+
+ idx += len / 4;
+ }
+
+ if (allocated & ~created) {
+ DRM_ERROR("New session without create command!\n");
+ r = -ENOENT;
+ }
+
+out:
+ if (!r) {
+ /* No error, free all destroyed handle slots */
+ tmp = destroyed;
+ amdgpu_ib_free(p->adev, ib, NULL);
+ } else {
+ /* Error during parsing, free all allocated handle slots */
+ tmp = allocated;
+ }
+
+ for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
+ if (tmp & (1 << i))
+ atomic_set(&p->adev->vce.handles[i], 0);
+
+ return r;
+}
+
+/**
* amdgpu_vce_ring_emit_ib - execute indirect buffer
*
* @ring: engine to use
@@ -823,18 +917,6 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
amdgpu_ring_write(ring, VCE_CMD_END);
}
-unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 4; /* amdgpu_vce_ring_emit_ib */
-}
-
-unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */
-}
-
/**
* amdgpu_vce_ring_test_ring - test if VCE ring is working
*
@@ -883,7 +965,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
*/
int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
long r;
/* skip vce ring1/2 ib test for now, since it's not reliable */
@@ -902,7 +984,7 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
goto error;
}
- r = fence_wait_timeout(fence, false, timeout);
+ r = dma_fence_wait_timeout(fence, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out.\n");
r = -ETIMEDOUT;
@@ -913,6 +995,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
r = 0;
}
error:
- fence_put(fence);
+ dma_fence_put(fence);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
index 12729d2852df..d98041f7508d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
@@ -29,11 +29,12 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
int amdgpu_vce_suspend(struct amdgpu_device *adev);
int amdgpu_vce_resume(struct amdgpu_device *adev);
int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
- struct fence **fence);
+ struct dma_fence **fence);
int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct fence **fence);
+ bool direct, struct dma_fence **fence);
void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
+int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx);
void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib,
unsigned vm_id, bool ctx_switch);
void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 968c4260d7a7..1dda9321bd5a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -25,7 +25,7 @@
* Alex Deucher
* Jerome Glisse
*/
-#include <linux/fence-array.h>
+#include <linux/dma-fence-array.h>
#include <drm/drmP.h>
#include <drm/amdgpu_drm.h>
#include "amdgpu.h"
@@ -116,38 +116,43 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
}
/**
- * amdgpu_vm_get_bos - add the vm BOs to a duplicates list
+ * amdgpu_vm_validate_pt_bos - validate the page table BOs
*
* @adev: amdgpu device pointer
* @vm: vm providing the BOs
- * @duplicates: head of duplicates list
+ * @validate: callback to do the validation
+ * @param: parameter for the validation callback
*
- * Add the page directory to the BO duplicates list
- * for command submission.
+ * Validate the page table BOs on command submission if neccessary.
*/
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- struct list_head *duplicates)
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ int (*validate)(void *p, struct amdgpu_bo *bo),
+ void *param)
{
uint64_t num_evictions;
unsigned i;
+ int r;
/* We only need to validate the page tables
* if they aren't already valid.
*/
num_evictions = atomic64_read(&adev->num_evictions);
if (num_evictions == vm->last_eviction_counter)
- return;
+ return 0;
/* add the vm page table to the list */
for (i = 0; i <= vm->max_pde_used; ++i) {
- struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
+ struct amdgpu_bo *bo = vm->page_tables[i].bo;
- if (!entry->robj)
+ if (!bo)
continue;
- list_add(&entry->tv.head, duplicates);
+ r = validate(param, bo);
+ if (r)
+ return r;
}
+ return 0;
}
/**
@@ -166,12 +171,12 @@ void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
spin_lock(&glob->lru_lock);
for (i = 0; i <= vm->max_pde_used; ++i) {
- struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
+ struct amdgpu_bo *bo = vm->page_tables[i].bo;
- if (!entry->robj)
+ if (!bo)
continue;
- ttm_bo_move_to_lru_tail(&entry->robj->tbo);
+ ttm_bo_move_to_lru_tail(&bo->tbo);
}
spin_unlock(&glob->lru_lock);
}
@@ -194,14 +199,14 @@ static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev,
* Allocate an id for the vm, adding fences to the sync obj as necessary.
*/
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
- struct amdgpu_sync *sync, struct fence *fence,
+ struct amdgpu_sync *sync, struct dma_fence *fence,
struct amdgpu_job *job)
{
struct amdgpu_device *adev = ring->adev;
uint64_t fence_context = adev->fence_context + ring->idx;
- struct fence *updates = sync->last_vm_update;
+ struct dma_fence *updates = sync->last_vm_update;
struct amdgpu_vm_id *id, *idle;
- struct fence **fences;
+ struct dma_fence **fences;
unsigned i;
int r = 0;
@@ -225,17 +230,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
if (&idle->list == &adev->vm_manager.ids_lru) {
u64 fence_context = adev->vm_manager.fence_context + ring->idx;
unsigned seqno = ++adev->vm_manager.seqno[ring->idx];
- struct fence_array *array;
+ struct dma_fence_array *array;
unsigned j;
for (j = 0; j < i; ++j)
- fence_get(fences[j]);
+ dma_fence_get(fences[j]);
- array = fence_array_create(i, fences, fence_context,
+ array = dma_fence_array_create(i, fences, fence_context,
seqno, true);
if (!array) {
for (j = 0; j < i; ++j)
- fence_put(fences[j]);
+ dma_fence_put(fences[j]);
kfree(fences);
r = -ENOMEM;
goto error;
@@ -243,7 +248,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
r = amdgpu_sync_fence(ring->adev, sync, &array->base);
- fence_put(&array->base);
+ dma_fence_put(&array->base);
if (r)
goto error;
@@ -257,7 +262,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
/* Check if we can use a VMID already assigned to this VM */
i = ring->idx;
do {
- struct fence *flushed;
+ struct dma_fence *flushed;
id = vm->ids[i++];
if (i == AMDGPU_MAX_RINGS)
@@ -279,12 +284,12 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
continue;
if (id->last_flush->context != fence_context &&
- !fence_is_signaled(id->last_flush))
+ !dma_fence_is_signaled(id->last_flush))
continue;
flushed = id->flushed_updates;
if (updates &&
- (!flushed || fence_is_later(updates, flushed)))
+ (!flushed || dma_fence_is_later(updates, flushed)))
continue;
/* Good we can use this VMID. Remember this submission as
@@ -315,14 +320,14 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
if (r)
goto error;
- fence_put(id->first);
- id->first = fence_get(fence);
+ dma_fence_put(id->first);
+ id->first = dma_fence_get(fence);
- fence_put(id->last_flush);
+ dma_fence_put(id->last_flush);
id->last_flush = NULL;
- fence_put(id->flushed_updates);
- id->flushed_updates = fence_get(updates);
+ dma_fence_put(id->flushed_updates);
+ id->flushed_updates = dma_fence_get(updates);
id->pd_gpu_addr = job->vm_pd_addr;
id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter);
@@ -341,9 +346,9 @@ error:
static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- const struct amdgpu_ip_block_version *ip_block;
+ const struct amdgpu_ip_block *ip_block;
- if (ring->type != AMDGPU_RING_TYPE_COMPUTE)
+ if (ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE)
/* only compute rings */
return false;
@@ -351,10 +356,10 @@ static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring)
if (!ip_block)
return false;
- if (ip_block->major <= 7) {
+ if (ip_block->version->major <= 7) {
/* gfx7 has no workaround */
return true;
- } else if (ip_block->major == 8) {
+ } else if (ip_block->version->major == 8) {
if (adev->gfx.mec_fw_version >= 673)
/* gfx8 is fixed in MEC firmware 673 */
return false;
@@ -393,7 +398,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
if (ring->funcs->emit_vm_flush && (job->vm_needs_flush ||
amdgpu_vm_is_gpu_reset(adev, id))) {
- struct fence *fence;
+ struct dma_fence *fence;
trace_amdgpu_vm_flush(job->vm_pd_addr, ring->idx, job->vm_id);
amdgpu_ring_emit_vm_flush(ring, job->vm_id, job->vm_pd_addr);
@@ -403,7 +408,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
return r;
mutex_lock(&adev->vm_manager.lock);
- fence_put(id->last_flush);
+ dma_fence_put(id->last_flush);
id->last_flush = fence;
mutex_unlock(&adev->vm_manager.lock);
}
@@ -525,70 +530,6 @@ static void amdgpu_vm_do_copy_ptes(struct amdgpu_pte_update_params *params,
}
/**
- * amdgpu_vm_clear_bo - initially clear the page dir/table
- *
- * @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_vm *vm,
- struct amdgpu_bo *bo)
-{
- struct amdgpu_ring *ring;
- struct fence *fence = NULL;
- struct amdgpu_job *job;
- struct amdgpu_pte_update_params params;
- unsigned entries;
- uint64_t addr;
- int r;
-
- ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
-
- 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;
-
- r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
- if (r)
- goto error;
-
- addr = amdgpu_bo_gpu_offset(bo);
- entries = amdgpu_bo_size(bo) / 8;
-
- r = amdgpu_job_alloc_with_ib(adev, 64, &job);
- if (r)
- goto error;
-
- memset(&params, 0, sizeof(params));
- params.adev = adev;
- params.ib = &job->ibs[0];
- amdgpu_vm_do_set_ptes(&params, addr, 0, entries, 0, 0);
- amdgpu_ring_pad_ib(ring, &job->ibs[0]);
-
- WARN_ON(job->ibs[0].length_dw > 64);
- r = amdgpu_job_submit(job, ring, &vm->entity,
- AMDGPU_FENCE_OWNER_VM, &fence);
- if (r)
- goto error_free;
-
- amdgpu_bo_fence(bo, fence, true);
- fence_put(fence);
- return 0;
-
-error_free:
- amdgpu_job_free(job);
-
-error:
- return r;
-}
-
-/**
* amdgpu_vm_map_gart - Resolve gart mapping of addr
*
* @pages_addr: optional DMA address to use for lookup
@@ -612,32 +553,35 @@ static uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr)
return result;
}
-static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- bool shadow)
+/*
+ * amdgpu_vm_update_pdes - make sure that page directory is valid
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ *
+ * Allocates new page tables if necessary
+ * and updates the page directory.
+ * Returns 0 for success, error for failure.
+ */
+int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
{
+ struct amdgpu_bo *shadow;
struct amdgpu_ring *ring;
- struct amdgpu_bo *pd = shadow ? vm->page_directory->shadow :
- vm->page_directory;
- uint64_t pd_addr;
+ uint64_t pd_addr, shadow_addr;
uint32_t incr = AMDGPU_VM_PTE_COUNT * 8;
- uint64_t last_pde = ~0, last_pt = ~0;
+ uint64_t last_pde = ~0, last_pt = ~0, last_shadow = ~0;
unsigned count = 0, pt_idx, ndw;
struct amdgpu_job *job;
struct amdgpu_pte_update_params params;
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
int r;
- if (!pd)
- return 0;
-
- r = amdgpu_ttm_bind(&pd->tbo, &pd->tbo.mem);
- if (r)
- return r;
-
- pd_addr = amdgpu_bo_gpu_offset(pd);
ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
+ shadow = vm->page_directory->shadow;
/* padding, etc. */
ndw = 64;
@@ -645,6 +589,17 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
/* assume the worst case */
ndw += vm->max_pde_used * 6;
+ pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
+ if (shadow) {
+ r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem);
+ if (r)
+ return r;
+ shadow_addr = amdgpu_bo_gpu_offset(shadow);
+ ndw *= 2;
+ } else {
+ shadow_addr = 0;
+ }
+
r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job);
if (r)
return r;
@@ -655,30 +610,26 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
/* walk over the address space and update the page directory */
for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) {
- struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj;
+ struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo;
uint64_t pde, pt;
if (bo == NULL)
continue;
if (bo->shadow) {
- struct amdgpu_bo *shadow = bo->shadow;
+ struct amdgpu_bo *pt_shadow = bo->shadow;
- r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem);
+ r = amdgpu_ttm_bind(&pt_shadow->tbo,
+ &pt_shadow->tbo.mem);
if (r)
return r;
}
pt = amdgpu_bo_gpu_offset(bo);
- if (!shadow) {
- if (vm->page_tables[pt_idx].addr == pt)
- continue;
- vm->page_tables[pt_idx].addr = pt;
- } else {
- if (vm->page_tables[pt_idx].shadow_addr == pt)
- continue;
- vm->page_tables[pt_idx].shadow_addr = pt;
- }
+ if (vm->page_tables[pt_idx].addr == pt)
+ continue;
+
+ vm->page_tables[pt_idx].addr = pt;
pde = pd_addr + pt_idx * 8;
if (((last_pde + 8 * count) != pde) ||
@@ -686,6 +637,13 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
(count == AMDGPU_VM_MAX_UPDATE_SIZE)) {
if (count) {
+ if (shadow)
+ amdgpu_vm_do_set_ptes(&params,
+ last_shadow,
+ last_pt, count,
+ incr,
+ AMDGPU_PTE_VALID);
+
amdgpu_vm_do_set_ptes(&params, last_pde,
last_pt, count, incr,
AMDGPU_PTE_VALID);
@@ -693,34 +651,44 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
count = 1;
last_pde = pde;
+ last_shadow = shadow_addr + pt_idx * 8;
last_pt = pt;
} else {
++count;
}
}
- if (count)
+ if (count) {
+ if (vm->page_directory->shadow)
+ amdgpu_vm_do_set_ptes(&params, last_shadow, last_pt,
+ count, incr, AMDGPU_PTE_VALID);
+
amdgpu_vm_do_set_ptes(&params, last_pde, last_pt,
count, incr, AMDGPU_PTE_VALID);
+ }
- if (params.ib->length_dw != 0) {
- amdgpu_ring_pad_ib(ring, params.ib);
- amdgpu_sync_resv(adev, &job->sync, pd->tbo.resv,
+ if (params.ib->length_dw == 0) {
+ amdgpu_job_free(job);
+ return 0;
+ }
+
+ amdgpu_ring_pad_ib(ring, params.ib);
+ amdgpu_sync_resv(adev, &job->sync, vm->page_directory->tbo.resv,
+ AMDGPU_FENCE_OWNER_VM);
+ if (shadow)
+ amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv,
AMDGPU_FENCE_OWNER_VM);
- WARN_ON(params.ib->length_dw > ndw);
- r = amdgpu_job_submit(job, ring, &vm->entity,
- AMDGPU_FENCE_OWNER_VM, &fence);
- if (r)
- goto error_free;
- amdgpu_bo_fence(pd, fence, true);
- fence_put(vm->page_directory_fence);
- vm->page_directory_fence = fence_get(fence);
- fence_put(fence);
+ WARN_ON(params.ib->length_dw > ndw);
+ r = amdgpu_job_submit(job, ring, &vm->entity,
+ AMDGPU_FENCE_OWNER_VM, &fence);
+ if (r)
+ goto error_free;
- } else {
- amdgpu_job_free(job);
- }
+ amdgpu_bo_fence(vm->page_directory, fence, true);
+ dma_fence_put(vm->page_directory_fence);
+ vm->page_directory_fence = dma_fence_get(fence);
+ dma_fence_put(fence);
return 0;
@@ -729,29 +697,6 @@ error_free:
return r;
}
-/*
- * amdgpu_vm_update_pdes - make sure that page directory is valid
- *
- * @adev: amdgpu_device pointer
- * @vm: requested vm
- * @start: start of GPU address range
- * @end: end of GPU address range
- *
- * Allocates new page tables if necessary
- * and updates the page directory.
- * Returns 0 for success, error for failure.
- */
-int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
- struct amdgpu_vm *vm)
-{
- int r;
-
- r = amdgpu_vm_update_pd_or_shadow(adev, vm, true);
- if (r)
- return r;
- return amdgpu_vm_update_pd_or_shadow(adev, vm, false);
-}
-
/**
* amdgpu_vm_update_ptes - make sure that page tables are valid
*
@@ -781,11 +726,11 @@ static void amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
/* initialize the variables */
addr = start;
pt_idx = addr >> amdgpu_vm_block_size;
- pt = vm->page_tables[pt_idx].entry.robj;
+ pt = vm->page_tables[pt_idx].bo;
if (params->shadow) {
if (!pt->shadow)
return;
- pt = vm->page_tables[pt_idx].entry.robj->shadow;
+ pt = pt->shadow;
}
if ((addr & ~mask) == (end & ~mask))
nptes = end - addr;
@@ -804,11 +749,11 @@ static void amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
/* walk over the address space and update the page tables */
while (addr < end) {
pt_idx = addr >> amdgpu_vm_block_size;
- pt = vm->page_tables[pt_idx].entry.robj;
+ pt = vm->page_tables[pt_idx].bo;
if (params->shadow) {
if (!pt->shadow)
return;
- pt = vm->page_tables[pt_idx].entry.robj->shadow;
+ pt = pt->shadow;
}
if ((addr & ~mask) == (end & ~mask))
@@ -929,20 +874,20 @@ static void amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params,
* Returns 0 for success, -EINVAL for failure.
*/
static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
- struct fence *exclusive,
+ struct dma_fence *exclusive,
uint64_t src,
dma_addr_t *pages_addr,
struct amdgpu_vm *vm,
uint64_t start, uint64_t last,
uint32_t flags, uint64_t addr,
- struct fence **fence)
+ struct dma_fence **fence)
{
struct amdgpu_ring *ring;
void *owner = AMDGPU_FENCE_OWNER_VM;
unsigned nptes, ncmds, ndw;
struct amdgpu_job *job;
struct amdgpu_pte_update_params params;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
int r;
memset(&params, 0, sizeof(params));
@@ -1045,10 +990,10 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
amdgpu_bo_fence(vm->page_directory, f, true);
if (fence) {
- fence_put(*fence);
- *fence = fence_get(f);
+ dma_fence_put(*fence);
+ *fence = dma_fence_get(f);
}
- fence_put(f);
+ dma_fence_put(f);
return 0;
error_free:
@@ -1065,8 +1010,8 @@ error_free:
* @pages_addr: DMA addresses to use for mapping
* @vm: requested vm
* @mapping: mapped range and flags to use for the update
- * @addr: addr to set the area to
* @flags: HW flags for the mapping
+ * @nodes: array of drm_mm_nodes with the MC addresses
* @fence: optional resulting fence
*
* Split the mapping into smaller chunks so that each update fits
@@ -1074,17 +1019,16 @@ error_free:
* Returns 0 for success, -EINVAL for failure.
*/
static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
- struct fence *exclusive,
+ struct dma_fence *exclusive,
uint32_t gtt_flags,
dma_addr_t *pages_addr,
struct amdgpu_vm *vm,
struct amdgpu_bo_va_mapping *mapping,
- uint32_t flags, uint64_t addr,
- struct fence **fence)
+ uint32_t flags,
+ struct drm_mm_node *nodes,
+ struct dma_fence **fence)
{
- const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE;
-
- uint64_t src = 0, start = mapping->it.start;
+ uint64_t pfn, src = 0, start = mapping->it.start;
int r;
/* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here
@@ -1097,23 +1041,40 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
trace_amdgpu_vm_bo_update(mapping);
- if (pages_addr) {
- if (flags == gtt_flags)
- src = adev->gart.table_addr + (addr >> 12) * 8;
- addr = 0;
+ pfn = mapping->offset >> PAGE_SHIFT;
+ if (nodes) {
+ while (pfn >= nodes->size) {
+ pfn -= nodes->size;
+ ++nodes;
+ }
}
- addr += mapping->offset;
- if (!pages_addr || src)
- return amdgpu_vm_bo_update_mapping(adev, exclusive,
- src, pages_addr, vm,
- start, mapping->it.last,
- flags, addr, fence);
+ do {
+ uint64_t max_entries;
+ uint64_t addr, last;
- while (start != mapping->it.last + 1) {
- uint64_t last;
+ if (nodes) {
+ addr = nodes->start << PAGE_SHIFT;
+ max_entries = (nodes->size - pfn) *
+ (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE);
+ } else {
+ addr = 0;
+ max_entries = S64_MAX;
+ }
- last = min((uint64_t)mapping->it.last, start + max_size - 1);
+ if (pages_addr) {
+ if (flags == gtt_flags)
+ src = adev->gart.table_addr +
+ (addr >> AMDGPU_GPU_PAGE_SHIFT) * 8;
+ else
+ max_entries = min(max_entries, 16ull * 1024ull);
+ addr = 0;
+ } else if (flags & AMDGPU_PTE_VALID) {
+ addr += adev->vm_manager.vram_base_offset;
+ }
+ addr += pfn << PAGE_SHIFT;
+
+ last = min((uint64_t)mapping->it.last, start + max_entries - 1);
r = amdgpu_vm_bo_update_mapping(adev, exclusive,
src, pages_addr, vm,
start, last, flags, addr,
@@ -1121,9 +1082,14 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
if (r)
return r;
+ pfn += last - start + 1;
+ if (nodes && nodes->size == pfn) {
+ pfn = 0;
+ ++nodes;
+ }
start = last + 1;
- addr += max_size * AMDGPU_GPU_PAGE_SIZE;
- }
+
+ } while (unlikely(start != mapping->it.last + 1));
return 0;
}
@@ -1147,40 +1113,30 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
dma_addr_t *pages_addr = NULL;
uint32_t gtt_flags, flags;
struct ttm_mem_reg *mem;
- struct fence *exclusive;
- uint64_t addr;
+ struct drm_mm_node *nodes;
+ struct dma_fence *exclusive;
int r;
if (clear) {
mem = NULL;
- addr = 0;
+ nodes = NULL;
exclusive = NULL;
} else {
struct ttm_dma_tt *ttm;
mem = &bo_va->bo->tbo.mem;
- addr = (u64)mem->start << PAGE_SHIFT;
- switch (mem->mem_type) {
- case TTM_PL_TT:
+ nodes = mem->mm_node;
+ if (mem->mem_type == TTM_PL_TT) {
ttm = container_of(bo_va->bo->tbo.ttm, struct
ttm_dma_tt, ttm);
pages_addr = ttm->dma_address;
- break;
-
- case TTM_PL_VRAM:
- addr += adev->vm_manager.vram_base_offset;
- break;
-
- default:
- break;
}
-
exclusive = reservation_object_get_excl(bo_va->bo->tbo.resv);
}
flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem);
gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) &&
- adev == bo_va->bo->adev) ? flags : 0;
+ adev == amdgpu_ttm_adev(bo_va->bo->tbo.bdev)) ? flags : 0;
spin_lock(&vm->status_lock);
if (!list_empty(&bo_va->vm_status))
@@ -1190,7 +1146,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
list_for_each_entry(mapping, &bo_va->invalids, list) {
r = amdgpu_vm_bo_split_mapping(adev, exclusive,
gtt_flags, pages_addr, vm,
- mapping, flags, addr,
+ mapping, flags, nodes,
&bo_va->last_pt_update);
if (r)
return r;
@@ -1405,18 +1361,18 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
/* 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;
- struct amdgpu_bo_list_entry *entry;
struct amdgpu_bo *pt;
- entry = &vm->page_tables[pt_idx].entry;
- if (entry->robj)
+ if (vm->page_tables[pt_idx].bo)
continue;
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 |
- AMDGPU_GEM_CREATE_SHADOW,
+ AMDGPU_GEM_CREATE_SHADOW |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+ AMDGPU_GEM_CREATE_VRAM_CLEARED,
NULL, resv, &pt);
if (r)
goto error_free;
@@ -1426,27 +1382,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
*/
pt->parent = amdgpu_bo_ref(vm->page_directory);
- r = amdgpu_vm_clear_bo(adev, vm, pt);
- if (r) {
- amdgpu_bo_unref(&pt->shadow);
- amdgpu_bo_unref(&pt);
- goto error_free;
- }
-
- if (pt->shadow) {
- r = amdgpu_vm_clear_bo(adev, vm, pt->shadow);
- if (r) {
- amdgpu_bo_unref(&pt->shadow);
- amdgpu_bo_unref(&pt);
- goto error_free;
- }
- }
-
- entry->robj = pt;
- entry->priority = 0;
- entry->tv.bo = &entry->robj->tbo;
- entry->tv.shared = true;
- entry->user_pages = NULL;
+ vm->page_tables[pt_idx].bo = pt;
vm->page_tables[pt_idx].addr = 0;
}
@@ -1547,7 +1483,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
kfree(mapping);
}
- fence_put(bo_va->last_pt_update);
+ dma_fence_put(bo_va->last_pt_update);
kfree(bo_va);
}
@@ -1626,7 +1562,9 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
r = amdgpu_bo_create(adev, pd_size, align, true,
AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
- AMDGPU_GEM_CREATE_SHADOW,
+ AMDGPU_GEM_CREATE_SHADOW |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+ AMDGPU_GEM_CREATE_VRAM_CLEARED,
NULL, NULL, &vm->page_directory);
if (r)
goto error_free_sched_entity;
@@ -1635,24 +1573,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
if (r)
goto error_free_page_directory;
- r = amdgpu_vm_clear_bo(adev, vm, vm->page_directory);
- if (r)
- goto error_unreserve;
-
- if (vm->page_directory->shadow) {
- r = amdgpu_vm_clear_bo(adev, vm, vm->page_directory->shadow);
- if (r)
- goto error_unreserve;
- }
-
vm->last_eviction_counter = atomic64_read(&adev->num_evictions);
amdgpu_bo_unreserve(vm->page_directory);
return 0;
-error_unreserve:
- amdgpu_bo_unreserve(vm->page_directory);
-
error_free_page_directory:
amdgpu_bo_unref(&vm->page_directory->shadow);
amdgpu_bo_unref(&vm->page_directory);
@@ -1697,7 +1622,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
}
for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) {
- struct amdgpu_bo *pt = vm->page_tables[i].entry.robj;
+ struct amdgpu_bo *pt = vm->page_tables[i].bo;
if (!pt)
continue;
@@ -1709,7 +1634,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
amdgpu_bo_unref(&vm->page_directory->shadow);
amdgpu_bo_unref(&vm->page_directory);
- fence_put(vm->page_directory_fence);
+ dma_fence_put(vm->page_directory_fence);
}
/**
@@ -1733,7 +1658,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
&adev->vm_manager.ids_lru);
}
- adev->vm_manager.fence_context = fence_context_alloc(AMDGPU_MAX_RINGS);
+ adev->vm_manager.fence_context =
+ dma_fence_context_alloc(AMDGPU_MAX_RINGS);
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
adev->vm_manager.seqno[i] = 0;
@@ -1755,9 +1681,9 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
for (i = 0; i < AMDGPU_NUM_VM; ++i) {
struct amdgpu_vm_id *id = &adev->vm_manager.ids[i];
- fence_put(adev->vm_manager.ids[i].first);
+ dma_fence_put(adev->vm_manager.ids[i].first);
amdgpu_sync_free(&adev->vm_manager.ids[i].active);
- fence_put(id->flushed_updates);
- fence_put(id->last_flush);
+ dma_fence_put(id->flushed_updates);
+ dma_fence_put(id->last_flush);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
new file mode 100644
index 000000000000..adbc2f5e5c7f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2016 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) 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: Christian König
+ */
+#ifndef __AMDGPU_VM_H__
+#define __AMDGPU_VM_H__
+
+#include <linux/rbtree.h>
+
+#include "gpu_scheduler.h"
+#include "amdgpu_sync.h"
+#include "amdgpu_ring.h"
+
+struct amdgpu_bo_va;
+struct amdgpu_job;
+struct amdgpu_bo_list_entry;
+
+/*
+ * GPUVM handling
+ */
+
+/* maximum number of VMIDs */
+#define AMDGPU_NUM_VM 16
+
+/* Maximum number of PTEs the hardware can write with one command */
+#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF
+
+/* number of entries in page table */
+#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
+
+/* PTBs (Page Table Blocks) need to be aligned to 32K */
+#define AMDGPU_VM_PTB_ALIGN_SIZE 32768
+
+/* LOG2 number of continuous pages for the fragment field */
+#define AMDGPU_LOG2_PAGES_PER_FRAG 4
+
+#define AMDGPU_PTE_VALID (1 << 0)
+#define AMDGPU_PTE_SYSTEM (1 << 1)
+#define AMDGPU_PTE_SNOOPED (1 << 2)
+
+/* VI only */
+#define AMDGPU_PTE_EXECUTABLE (1 << 4)
+
+#define AMDGPU_PTE_READABLE (1 << 5)
+#define AMDGPU_PTE_WRITEABLE (1 << 6)
+
+#define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7)
+
+/* 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_vm {
+ /* tree of virtual addresses mapped */
+ struct rb_root va;
+
+ /* protecting invalidated */
+ spinlock_t status_lock;
+
+ /* BOs moved, but not yet updated in the PT */
+ struct list_head invalidated;
+
+ /* BOs cleared in the PT because of a move */
+ struct list_head cleared;
+
+ /* BO mappings freed, but not yet updated in the PT */
+ struct list_head freed;
+
+ /* contains the page directory */
+ struct amdgpu_bo *page_directory;
+ unsigned max_pde_used;
+ struct dma_fence *page_directory_fence;
+ uint64_t last_eviction_counter;
+
+ /* array of page tables, one for each page directory entry */
+ struct amdgpu_vm_pt *page_tables;
+
+ /* for id and flush management per ring */
+ struct amdgpu_vm_id *ids[AMDGPU_MAX_RINGS];
+
+ /* protecting freed */
+ spinlock_t freed_lock;
+
+ /* Scheduler entity for page table updates */
+ struct amd_sched_entity entity;
+
+ /* client id */
+ u64 client_id;
+};
+
+struct amdgpu_vm_id {
+ struct list_head list;
+ struct dma_fence *first;
+ struct amdgpu_sync active;
+ struct dma_fence *last_flush;
+ atomic64_t owner;
+
+ uint64_t pd_gpu_addr;
+ /* last flushed PD/PT update */
+ struct dma_fence *flushed_updates;
+
+ uint32_t current_gpu_reset_count;
+
+ uint32_t gds_base;
+ uint32_t gds_size;
+ uint32_t gws_base;
+ uint32_t gws_size;
+ uint32_t oa_base;
+ uint32_t oa_size;
+};
+
+struct amdgpu_vm_manager {
+ /* Handling of VMIDs */
+ struct mutex lock;
+ unsigned num_ids;
+ struct list_head ids_lru;
+ struct amdgpu_vm_id ids[AMDGPU_NUM_VM];
+
+ /* Handling of VM fences */
+ u64 fence_context;
+ unsigned seqno[AMDGPU_MAX_RINGS];
+
+ uint32_t max_pfn;
+ /* vram base address for page table entry */
+ u64 vram_base_offset;
+ /* is vm enabled? */
+ bool enabled;
+ /* vm pte handling */
+ const struct amdgpu_vm_pte_funcs *vm_pte_funcs;
+ struct amdgpu_ring *vm_pte_rings[AMDGPU_MAX_RINGS];
+ unsigned vm_pte_num_rings;
+ atomic_t vm_pte_next_ring;
+ /* client id counter */
+ atomic64_t client_counter;
+};
+
+void amdgpu_vm_manager_init(struct amdgpu_device *adev);
+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);
+void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
+ struct list_head *validated,
+ struct amdgpu_bo_list_entry *entry);
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ int (*callback)(void *p, struct amdgpu_bo *bo),
+ void *param);
+void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm);
+int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
+ struct amdgpu_sync *sync, struct dma_fence *fence,
+ struct amdgpu_job *job);
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
+void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
+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,
+ bool clear);
+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);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
new file mode 100644
index 000000000000..d710226a0fff
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2016 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) 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: Christian König
+ */
+
+#include <drm/drmP.h>
+#include "amdgpu.h"
+
+struct amdgpu_vram_mgr {
+ struct drm_mm mm;
+ spinlock_t lock;
+};
+
+/**
+ * amdgpu_vram_mgr_init - init VRAM manager and DRM MM
+ *
+ * @man: TTM memory type manager
+ * @p_size: maximum size of VRAM
+ *
+ * Allocate and initialize the VRAM manager.
+ */
+static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man,
+ unsigned long p_size)
+{
+ struct amdgpu_vram_mgr *mgr;
+
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+ if (!mgr)
+ return -ENOMEM;
+
+ drm_mm_init(&mgr->mm, 0, p_size);
+ spin_lock_init(&mgr->lock);
+ man->priv = mgr;
+ return 0;
+}
+
+/**
+ * amdgpu_vram_mgr_fini - free and destroy VRAM manager
+ *
+ * @man: TTM memory type manager
+ *
+ * Destroy and free the VRAM manager, returns -EBUSY if ranges are still
+ * allocated inside it.
+ */
+static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man)
+{
+ struct amdgpu_vram_mgr *mgr = man->priv;
+
+ spin_lock(&mgr->lock);
+ if (!drm_mm_clean(&mgr->mm)) {
+ spin_unlock(&mgr->lock);
+ return -EBUSY;
+ }
+
+ drm_mm_takedown(&mgr->mm);
+ spin_unlock(&mgr->lock);
+ kfree(mgr);
+ man->priv = NULL;
+ return 0;
+}
+
+/**
+ * amdgpu_vram_mgr_new - allocate new ranges
+ *
+ * @man: TTM memory type manager
+ * @tbo: TTM BO we need this range for
+ * @place: placement flags and restrictions
+ * @mem: the resulting mem object
+ *
+ * Allocate VRAM for the given BO.
+ */
+static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
+ struct ttm_buffer_object *tbo,
+ const struct ttm_place *place,
+ struct ttm_mem_reg *mem)
+{
+ struct amdgpu_bo *bo = container_of(tbo, struct amdgpu_bo, tbo);
+ struct amdgpu_vram_mgr *mgr = man->priv;
+ struct drm_mm *mm = &mgr->mm;
+ struct drm_mm_node *nodes;
+ enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT;
+ enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
+ unsigned long lpfn, num_nodes, pages_per_node, pages_left;
+ unsigned i;
+ int r;
+
+ lpfn = place->lpfn;
+ if (!lpfn)
+ lpfn = man->size;
+
+ if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS ||
+ place->lpfn || amdgpu_vram_page_split == -1) {
+ pages_per_node = ~0ul;
+ num_nodes = 1;
+ } else {
+ pages_per_node = max((uint32_t)amdgpu_vram_page_split,
+ mem->page_alignment);
+ num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
+ }
+
+ nodes = kcalloc(num_nodes, sizeof(*nodes), GFP_KERNEL);
+ if (!nodes)
+ return -ENOMEM;
+
+ if (place->flags & TTM_PL_FLAG_TOPDOWN) {
+ sflags = DRM_MM_SEARCH_BELOW;
+ aflags = DRM_MM_CREATE_TOP;
+ }
+
+ pages_left = mem->num_pages;
+
+ spin_lock(&mgr->lock);
+ for (i = 0; i < num_nodes; ++i) {
+ unsigned long pages = min(pages_left, pages_per_node);
+ uint32_t alignment = mem->page_alignment;
+
+ if (pages == pages_per_node)
+ alignment = pages_per_node;
+ else
+ sflags |= DRM_MM_SEARCH_BEST;
+
+ r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages,
+ alignment, 0,
+ place->fpfn, lpfn,
+ sflags, aflags);
+ if (unlikely(r))
+ goto error;
+
+ pages_left -= pages;
+ }
+ spin_unlock(&mgr->lock);
+
+ mem->start = num_nodes == 1 ? nodes[0].start : AMDGPU_BO_INVALID_OFFSET;
+ mem->mm_node = nodes;
+
+ return 0;
+
+error:
+ while (i--)
+ drm_mm_remove_node(&nodes[i]);
+ spin_unlock(&mgr->lock);
+
+ kfree(nodes);
+ return r == -ENOSPC ? 0 : r;
+}
+
+/**
+ * amdgpu_vram_mgr_del - free ranges
+ *
+ * @man: TTM memory type manager
+ * @tbo: TTM BO we need this range for
+ * @place: placement flags and restrictions
+ * @mem: TTM memory object
+ *
+ * Free the allocated VRAM again.
+ */
+static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man,
+ struct ttm_mem_reg *mem)
+{
+ struct amdgpu_vram_mgr *mgr = man->priv;
+ struct drm_mm_node *nodes = mem->mm_node;
+ unsigned pages = mem->num_pages;
+
+ if (!mem->mm_node)
+ return;
+
+ spin_lock(&mgr->lock);
+ while (pages) {
+ pages -= nodes->size;
+ drm_mm_remove_node(nodes);
+ ++nodes;
+ }
+ spin_unlock(&mgr->lock);
+
+ kfree(mem->mm_node);
+ mem->mm_node = NULL;
+}
+
+/**
+ * amdgpu_vram_mgr_debug - dump VRAM table
+ *
+ * @man: TTM memory type manager
+ * @prefix: text prefix
+ *
+ * Dump the table content using printk.
+ */
+static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
+ const char *prefix)
+{
+ struct amdgpu_vram_mgr *mgr = man->priv;
+
+ spin_lock(&mgr->lock);
+ drm_mm_debug_table(&mgr->mm, prefix);
+ spin_unlock(&mgr->lock);
+}
+
+const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
+ amdgpu_vram_mgr_init,
+ amdgpu_vram_mgr_fini,
+ amdgpu_vram_mgr_new,
+ amdgpu_vram_mgr_del,
+ amdgpu_vram_mgr_debug
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
index f7d236f95e74..8c9bc75a9c2d 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -31,6 +31,7 @@
#include "atom.h"
#include "atom-bits.h"
#include "atombios_encoders.h"
+#include "atombios_crtc.h"
#include "amdgpu_atombios.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 5be788b269e2..bda9e3de191e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -887,9 +887,6 @@ static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
{
struct ci_power_info *pi = ci_get_pi(adev);
- if (pi->uvd_power_gated == gate)
- return;
-
pi->uvd_power_gated = gate;
ci_update_uvd_dpm(adev, gate);
@@ -960,6 +957,12 @@ static void ci_apply_state_adjust_rules(struct amdgpu_device *adev,
sclk = ps->performance_levels[0].sclk;
}
+ if (adev->pm.pm_display_cfg.min_core_set_clock > sclk)
+ sclk = adev->pm.pm_display_cfg.min_core_set_clock;
+
+ if (adev->pm.pm_display_cfg.min_mem_set_clock > mclk)
+ mclk = adev->pm.pm_display_cfg.min_mem_set_clock;
+
if (rps->vce_active) {
if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk)
sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk;
@@ -2201,6 +2204,11 @@ static int ci_upload_firmware(struct amdgpu_device *adev)
struct ci_power_info *pi = ci_get_pi(adev);
int i, ret;
+ if (amdgpu_ci_is_smc_running(adev)) {
+ DRM_INFO("smc is running, no need to load smc firmware\n");
+ return 0;
+ }
+
for (i = 0; i < adev->usec_timeout; i++) {
if (RREG32_SMC(ixRCU_UC_EVENTS) & RCU_UC_EVENTS__boot_seq_done_MASK)
break;
@@ -4190,8 +4198,10 @@ static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
{
struct ci_power_info *pi = ci_get_pi(adev);
u32 tmp;
+ int ret = 0;
if (!gate) {
+ /* turn the clocks on when decoding */
if (pi->caps_uvd_dpm ||
(adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count <= 0))
pi->smc_state_table.UvdBootLevel = 0;
@@ -4203,9 +4213,14 @@ static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
tmp &= ~DPM_TABLE_475__UvdBootLevel_MASK;
tmp |= (pi->smc_state_table.UvdBootLevel << DPM_TABLE_475__UvdBootLevel__SHIFT);
WREG32_SMC(ixDPM_TABLE_475, tmp);
+ ret = ci_enable_uvd_dpm(adev, true);
+ } else {
+ ret = ci_enable_uvd_dpm(adev, false);
+ if (ret)
+ return ret;
}
- return ci_enable_uvd_dpm(adev, !gate);
+ return ret;
}
static u8 ci_get_vce_boot_level(struct amdgpu_device *adev)
@@ -4247,13 +4262,12 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
ret = ci_enable_vce_dpm(adev, true);
} else {
+ ret = ci_enable_vce_dpm(adev, false);
+ if (ret)
+ return ret;
/* turn the clocks off when not encoding */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
- if (ret)
- return ret;
-
- ret = ci_enable_vce_dpm(adev, false);
}
}
return ret;
@@ -5219,6 +5233,7 @@ static void ci_update_current_ps(struct amdgpu_device *adev,
pi->current_rps = *rps;
pi->current_ps = *new_ps;
pi->current_rps.ps_priv = &pi->current_ps;
+ adev->pm.dpm.current_ps = &pi->current_rps;
}
static void ci_update_requested_ps(struct amdgpu_device *adev,
@@ -5230,6 +5245,7 @@ static void ci_update_requested_ps(struct amdgpu_device *adev,
pi->requested_rps = *rps;
pi->requested_ps = *new_ps;
pi->requested_rps.ps_priv = &pi->requested_ps;
+ adev->pm.dpm.requested_ps = &pi->requested_rps;
}
static int ci_dpm_pre_set_power_state(struct amdgpu_device *adev)
@@ -5267,8 +5283,6 @@ static int ci_dpm_enable(struct amdgpu_device *adev)
struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
int ret;
- if (amdgpu_ci_is_smc_running(adev))
- return -EINVAL;
if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
ci_enable_voltage_control(adev);
ret = ci_construct_voltage_tables(adev);
@@ -5689,7 +5703,7 @@ static int ci_parse_power_table(struct amdgpu_device *adev)
adev->pm.dpm.num_ps = state_array->ucNumEntries;
/* fill in the vce power states */
- for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+ for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
u32 sclk, mclk;
clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
clock_info = (union pplib_clock_info *)
@@ -5874,7 +5888,7 @@ static int ci_dpm_init(struct amdgpu_device *adev)
pi->pcie_dpm_key_disabled = 0;
pi->thermal_sclk_dpm_enabled = 0;
- if (amdgpu_sclk_deep_sleep_en)
+ if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
@@ -5977,7 +5991,7 @@ static int ci_dpm_init(struct amdgpu_device *adev)
tmp |= CNB_PWRMGT_CNTL__DPM_ENABLED_MASK;
break;
default:
- DRM_ERROR("Invalid PCC GPIO: %u!\n", gpio.shift);
+ DRM_INFO("Invalid PCC GPIO: %u!\n", gpio.shift);
break;
}
WREG32_SMC(ixCNB_PWRMGT_CNTL, tmp);
@@ -6069,7 +6083,7 @@ ci_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
activity_percent = activity_percent > 100 ? 100 : activity_percent;
}
- seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis");
+ seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis");
seq_printf(m, "power level avg sclk: %u mclk: %u\n",
sclk, mclk);
@@ -6094,6 +6108,56 @@ static void ci_dpm_print_power_state(struct amdgpu_device *adev,
amdgpu_dpm_print_ps_status(adev, rps);
}
+static inline bool ci_are_power_levels_equal(const struct ci_pl *ci_cpl1,
+ const struct ci_pl *ci_cpl2)
+{
+ return ((ci_cpl1->mclk == ci_cpl2->mclk) &&
+ (ci_cpl1->sclk == ci_cpl2->sclk) &&
+ (ci_cpl1->pcie_gen == ci_cpl2->pcie_gen) &&
+ (ci_cpl1->pcie_lane == ci_cpl2->pcie_lane));
+}
+
+static int ci_check_state_equal(struct amdgpu_device *adev,
+ struct amdgpu_ps *cps,
+ struct amdgpu_ps *rps,
+ bool *equal)
+{
+ struct ci_ps *ci_cps;
+ struct ci_ps *ci_rps;
+ int i;
+
+ if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
+ return -EINVAL;
+
+ ci_cps = ci_get_ps(cps);
+ ci_rps = ci_get_ps(rps);
+
+ if (ci_cps == NULL) {
+ *equal = false;
+ return 0;
+ }
+
+ if (ci_cps->performance_level_count != ci_rps->performance_level_count) {
+
+ *equal = false;
+ return 0;
+ }
+
+ for (i = 0; i < ci_cps->performance_level_count; i++) {
+ if (!ci_are_power_levels_equal(&(ci_cps->performance_levels[i]),
+ &(ci_rps->performance_levels[i]))) {
+ *equal = false;
+ return 0;
+ }
+ }
+
+ /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+ *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
+ *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
+
+ return 0;
+}
+
static u32 ci_dpm_get_sclk(struct amdgpu_device *adev, bool low)
{
struct ci_power_info *pi = ci_get_pi(adev);
@@ -6289,12 +6353,19 @@ static int ci_dpm_suspend(void *handle)
if (adev->pm.dpm_enabled) {
mutex_lock(&adev->pm.mutex);
- /* disable dpm */
- ci_dpm_disable(adev);
- /* reset the power state */
- adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
+ amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
+ AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
+ amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
+ AMDGPU_THERMAL_IRQ_HIGH_TO_LOW);
+ adev->pm.dpm.last_user_state = adev->pm.dpm.user_state;
+ adev->pm.dpm.last_state = adev->pm.dpm.state;
+ adev->pm.dpm.user_state = POWER_STATE_TYPE_INTERNAL_BOOT;
+ adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_BOOT;
mutex_unlock(&adev->pm.mutex);
+ amdgpu_pm_compute_clocks(adev);
+
}
+
return 0;
}
@@ -6312,6 +6383,8 @@ static int ci_dpm_resume(void *handle)
adev->pm.dpm_enabled = false;
else
adev->pm.dpm_enabled = true;
+ adev->pm.dpm.user_state = adev->pm.dpm.last_user_state;
+ adev->pm.dpm.state = adev->pm.dpm.last_state;
mutex_unlock(&adev->pm.mutex);
if (adev->pm.dpm_enabled)
amdgpu_pm_compute_clocks(adev);
@@ -6646,6 +6719,8 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = {
.set_sclk_od = ci_dpm_set_sclk_od,
.get_mclk_od = ci_dpm_get_mclk_od,
.set_mclk_od = ci_dpm_set_mclk_od,
+ .check_state_equal = ci_check_state_equal,
+ .get_vce_clock_state = amdgpu_get_vce_clock_state,
};
static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -6664,3 +6739,12 @@ static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev)
adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs;
}
+
+const struct amdgpu_ip_block_version ci_dpm_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SMC,
+ .major = 7,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &ci_dpm_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index a845b6a93b79..302df85893ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1189,18 +1189,6 @@ static int cik_gpu_pci_config_reset(struct amdgpu_device *adev)
return r;
}
-static void cik_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung)
-{
- u32 tmp = RREG32(mmBIOS_SCRATCH_3);
-
- if (hung)
- tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
- else
- tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-
- WREG32(mmBIOS_SCRATCH_3, tmp);
-}
-
/**
* cik_asic_reset - soft reset GPU
*
@@ -1213,11 +1201,12 @@ static void cik_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hu
static int cik_asic_reset(struct amdgpu_device *adev)
{
int r;
- cik_set_bios_scratch_engine_hung(adev, true);
+
+ amdgpu_atombios_scratch_regs_engine_hung(adev, true);
r = cik_gpu_pci_config_reset(adev);
- cik_set_bios_scratch_engine_hung(adev, false);
+ amdgpu_atombios_scratch_regs_engine_hung(adev, false);
return r;
}
@@ -1641,745 +1630,6 @@ static void cik_detect_hw_virtualization(struct amdgpu_device *adev)
adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
}
-static const struct amdgpu_ip_block_version bonaire_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 2,
- .rev = 0,
- .funcs = &dce_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version bonaire_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 2,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 5,
- .rev = 0,
- .funcs = &dce_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 3,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version hawaii_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 5,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 3,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 3,
- .rev = 0,
- .funcs = &dce_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version kabini_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 3,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 3,
- .rev = 0,
- .funcs = &dce_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version mullins_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 3,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 1,
- .rev = 0,
- .funcs = &dce_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version kaveri_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 8,
- .minor = 1,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &gfx_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &cik_sdma_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 4,
- .minor = 2,
- .rev = 0,
- .funcs = &uvd_v4_2_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v2_0_ip_funcs,
- },
-};
-
-int cik_set_ip_blocks(struct amdgpu_device *adev)
-{
- if (adev->enable_virtual_display) {
- switch (adev->asic_type) {
- case CHIP_BONAIRE:
- adev->ip_blocks = bonaire_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks_vd);
- break;
- case CHIP_HAWAII:
- adev->ip_blocks = hawaii_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks_vd);
- break;
- case CHIP_KAVERI:
- adev->ip_blocks = kaveri_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks_vd);
- break;
- case CHIP_KABINI:
- adev->ip_blocks = kabini_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks_vd);
- break;
- case CHIP_MULLINS:
- adev->ip_blocks = mullins_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks_vd);
- break;
- default:
- /* FIXME: not supported yet */
- return -EINVAL;
- }
- } else {
- switch (adev->asic_type) {
- case CHIP_BONAIRE:
- adev->ip_blocks = bonaire_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks);
- break;
- case CHIP_HAWAII:
- adev->ip_blocks = hawaii_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks);
- break;
- case CHIP_KAVERI:
- adev->ip_blocks = kaveri_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks);
- break;
- case CHIP_KABINI:
- adev->ip_blocks = kabini_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks);
- break;
- case CHIP_MULLINS:
- adev->ip_blocks = mullins_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks);
- break;
- default:
- /* FIXME: not supported yet */
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
static const struct amdgpu_asic_funcs cik_asic_funcs =
{
.read_disabled_bios = &cik_read_disabled_bios,
@@ -2612,7 +1862,7 @@ static int cik_common_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs cik_common_ip_funcs = {
+static const struct amd_ip_funcs cik_common_ip_funcs = {
.name = "cik_common",
.early_init = cik_common_early_init,
.late_init = NULL,
@@ -2628,3 +1878,79 @@ const struct amd_ip_funcs cik_common_ip_funcs = {
.set_clockgating_state = cik_common_set_clockgating_state,
.set_powergating_state = cik_common_set_powergating_state,
};
+
+static const struct amdgpu_ip_block_version cik_common_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_COMMON,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &cik_common_ip_funcs,
+};
+
+int cik_set_ip_blocks(struct amdgpu_device *adev)
+{
+ switch (adev->asic_type) {
+ case CHIP_BONAIRE:
+ amdgpu_ip_block_add(adev, &cik_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+ amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v8_2_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
+ amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+ break;
+ case CHIP_HAWAII:
+ amdgpu_ip_block_add(adev, &cik_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+ amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v8_5_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block);
+ amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+ break;
+ case CHIP_KAVERI:
+ amdgpu_ip_block_add(adev, &cik_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+ amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v8_1_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v7_1_ip_block);
+ amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+ break;
+ case CHIP_KABINI:
+ case CHIP_MULLINS:
+ amdgpu_ip_block_add(adev, &cik_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+ amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v8_3_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
+ amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+ break;
+ default:
+ /* FIXME: not supported yet */
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.h b/drivers/gpu/drm/amd/amdgpu/cik.h
index 5ebd2d7a0327..c4989f51ecef 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.h
+++ b/drivers/gpu/drm/amd/amdgpu/cik.h
@@ -24,8 +24,6 @@
#ifndef __CIK_H__
#define __CIK_H__
-extern const struct amd_ip_funcs cik_common_ip_funcs;
-
void cik_srbm_select(struct amdgpu_device *adev,
u32 me, u32 pipe, u32 queue, u32 vmid);
int cik_set_ip_blocks(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
index be3d6f79a864..319b32cdea84 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
@@ -413,7 +413,7 @@ static int cik_ih_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs cik_ih_ip_funcs = {
+static const struct amd_ip_funcs cik_ih_ip_funcs = {
.name = "cik_ih",
.early_init = cik_ih_early_init,
.late_init = NULL,
@@ -441,3 +441,12 @@ static void cik_ih_set_interrupt_funcs(struct amdgpu_device *adev)
if (adev->irq.ih_funcs == NULL)
adev->irq.ih_funcs = &cik_ih_funcs;
}
+
+const struct amdgpu_ip_block_version cik_ih_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_IH,
+ .major = 2,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &cik_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.h b/drivers/gpu/drm/amd/amdgpu/cik_ih.h
index 6b0f375ec244..1d9ddee2868e 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.h
@@ -24,6 +24,6 @@
#ifndef __CIK_IH_H__
#define __CIK_IH_H__
-extern const struct amd_ip_funcs cik_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version cik_ih_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index cb952acc7133..4c34dbc7a254 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -206,10 +206,10 @@ static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
for (i = 0; i < count; i++)
if (sdma && sdma->burst_nop && (i == 0))
- amdgpu_ring_write(ring, ring->nop |
+ amdgpu_ring_write(ring, ring->funcs->nop |
SDMA_NOP_COUNT(count - 1));
else
- amdgpu_ring_write(ring, ring->nop);
+ amdgpu_ring_write(ring, ring->funcs->nop);
}
/**
@@ -622,7 +622,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
unsigned index;
u32 tmp = 0;
u64 gpu_addr;
@@ -655,7 +655,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err1;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -675,7 +675,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
err1:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err0:
amdgpu_wb_free(adev, index);
return r;
@@ -848,22 +848,6 @@ static void cik_sdma_ring_emit_vm_flush(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */
}
-static unsigned cik_sdma_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 7 + 4; /* cik_sdma_ring_emit_ib */
-}
-
-static unsigned cik_sdma_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 6 + /* cik_sdma_ring_emit_hdp_flush */
- 3 + /* cik_sdma_ring_emit_hdp_invalidate */
- 6 + /* cik_sdma_ring_emit_pipeline_sync */
- 12 + /* cik_sdma_ring_emit_vm_flush */
- 9 + 9 + 9; /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */
-}
-
static void cik_enable_sdma_mgcg(struct amdgpu_device *adev,
bool enable)
{
@@ -959,11 +943,10 @@ static int cik_sdma_sw_init(void *handle)
ring->ring_obj = NULL;
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 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);
+ AMDGPU_SDMA_IRQ_TRAP0 :
+ AMDGPU_SDMA_IRQ_TRAP1);
if (r)
return r;
}
@@ -1207,7 +1190,7 @@ static int cik_sdma_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs cik_sdma_ip_funcs = {
+static const struct amd_ip_funcs cik_sdma_ip_funcs = {
.name = "cik_sdma",
.early_init = cik_sdma_early_init,
.late_init = NULL,
@@ -1225,10 +1208,19 @@ const struct amd_ip_funcs cik_sdma_ip_funcs = {
};
static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_SDMA,
+ .align_mask = 0xf,
+ .nop = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0),
.get_rptr = cik_sdma_ring_get_rptr,
.get_wptr = cik_sdma_ring_get_wptr,
.set_wptr = cik_sdma_ring_set_wptr,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 6 + /* cik_sdma_ring_emit_hdp_flush */
+ 3 + /* cik_sdma_ring_emit_hdp_invalidate */
+ 6 + /* cik_sdma_ring_emit_pipeline_sync */
+ 12 + /* cik_sdma_ring_emit_vm_flush */
+ 9 + 9 + 9, /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */
+ .emit_ib_size = 7 + 4, /* cik_sdma_ring_emit_ib */
.emit_ib = cik_sdma_ring_emit_ib,
.emit_fence = cik_sdma_ring_emit_fence,
.emit_pipeline_sync = cik_sdma_ring_emit_pipeline_sync,
@@ -1239,8 +1231,6 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
.test_ib = cik_sdma_ring_test_ib,
.insert_nop = cik_sdma_ring_insert_nop,
.pad_ib = cik_sdma_ring_pad_ib,
- .get_emit_ib_size = cik_sdma_ring_get_emit_ib_size,
- .get_dma_frame_size = cik_sdma_ring_get_dma_frame_size,
};
static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev)
@@ -1352,3 +1342,12 @@ static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev)
adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
}
}
+
+const struct amdgpu_ip_block_version cik_sdma_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SDMA,
+ .major = 2,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &cik_sdma_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.h b/drivers/gpu/drm/amd/amdgpu/cik_sdma.h
index 027727c677b8..a4a8fe01410b 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.h
@@ -24,6 +24,6 @@
#ifndef __CIK_SDMA_H__
#define __CIK_SDMA_H__
-extern const struct amd_ip_funcs cik_sdma_ip_funcs;
+extern const struct amdgpu_ip_block_version cik_sdma_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/cikd.h b/drivers/gpu/drm/amd/amdgpu/cikd.h
index 8659852aea9e..6cbd913fd12e 100644
--- a/drivers/gpu/drm/amd/amdgpu/cikd.h
+++ b/drivers/gpu/drm/amd/amdgpu/cikd.h
@@ -43,6 +43,14 @@
#define CRTC4_REGISTER_OFFSET (0x477c - 0x1b7c)
#define CRTC5_REGISTER_OFFSET (0x4a7c - 0x1b7c)
+/* hpd instance offsets */
+#define HPD0_REGISTER_OFFSET (0x1807 - 0x1807)
+#define HPD1_REGISTER_OFFSET (0x180a - 0x1807)
+#define HPD2_REGISTER_OFFSET (0x180d - 0x1807)
+#define HPD3_REGISTER_OFFSET (0x1810 - 0x1807)
+#define HPD4_REGISTER_OFFSET (0x1813 - 0x1807)
+#define HPD5_REGISTER_OFFSET (0x1816 - 0x1807)
+
#define BONAIRE_GB_ADDR_CONFIG_GOLDEN 0x12010001
#define HAWAII_GB_ADDR_CONFIG_GOLDEN 0x12011003
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 3c082e143730..ba2b66be9022 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -438,7 +438,7 @@ static int cz_dpm_init(struct amdgpu_device *adev)
pi->caps_td_ramping = true;
pi->caps_tcp_ramping = true;
}
- if (amdgpu_sclk_deep_sleep_en)
+ if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
@@ -1250,7 +1250,8 @@ static void cz_update_current_ps(struct amdgpu_device *adev,
pi->current_ps = *ps;
pi->current_rps = *rps;
- pi->current_rps.ps_priv = ps;
+ pi->current_rps.ps_priv = &pi->current_ps;
+ adev->pm.dpm.current_ps = &pi->current_rps;
}
@@ -1262,7 +1263,8 @@ static void cz_update_requested_ps(struct amdgpu_device *adev,
pi->requested_ps = *ps;
pi->requested_rps = *rps;
- pi->requested_rps.ps_priv = ps;
+ pi->requested_rps.ps_priv = &pi->requested_ps;
+ adev->pm.dpm.requested_ps = &pi->requested_rps;
}
@@ -2109,9 +2111,8 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
if (gate) {
if (pi->caps_uvd_pg) {
- /* disable clockgating so we can properly shut down the block */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_CG_STATE_UNGATE);
+ AMD_CG_STATE_GATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to set clockgating state\n");
return;
@@ -2157,9 +2158,8 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
return;
}
- /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_CG_STATE_GATE);
+ AMD_CG_STATE_UNGATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to set clockgating state\n");
return;
@@ -2257,6 +2257,18 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
}
}
+static int cz_check_state_equal(struct amdgpu_device *adev,
+ struct amdgpu_ps *cps,
+ struct amdgpu_ps *rps,
+ bool *equal)
+{
+ if (equal == NULL)
+ return -EINVAL;
+
+ *equal = false;
+ return 0;
+}
+
const struct amd_ip_funcs cz_dpm_ip_funcs = {
.name = "cz_dpm",
.early_init = cz_dpm_early_init,
@@ -2289,6 +2301,7 @@ static const struct amdgpu_dpm_funcs cz_dpm_funcs = {
.vblank_too_short = NULL,
.powergate_uvd = cz_dpm_powergate_uvd,
.powergate_vce = cz_dpm_powergate_vce,
+ .check_state_equal = cz_check_state_equal,
};
static void cz_dpm_set_funcs(struct amdgpu_device *adev)
@@ -2296,3 +2309,12 @@ static void cz_dpm_set_funcs(struct amdgpu_device *adev)
if (NULL == adev->pm.funcs)
adev->pm.funcs = &cz_dpm_funcs;
}
+
+const struct amdgpu_ip_block_version cz_dpm_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SMC,
+ .major = 8,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &cz_dpm_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
index 3d23a70b6432..fe7cbb24da7b 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
@@ -394,7 +394,7 @@ static int cz_ih_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs cz_ih_ip_funcs = {
+static const struct amd_ip_funcs cz_ih_ip_funcs = {
.name = "cz_ih",
.early_init = cz_ih_early_init,
.late_init = NULL,
@@ -423,3 +423,11 @@ static void cz_ih_set_interrupt_funcs(struct amdgpu_device *adev)
adev->irq.ih_funcs = &cz_ih_funcs;
}
+const struct amdgpu_ip_block_version cz_ih_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_IH,
+ .major = 3,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &cz_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.h b/drivers/gpu/drm/amd/amdgpu/cz_ih.h
index fc4057a2ecb9..14be7753221b 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.h
@@ -24,6 +24,6 @@
#ifndef __CZ_IH_H__
#define __CZ_IH_H__
-extern const struct amd_ip_funcs cz_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version cz_ih_ip_block;
#endif /* __CZ_IH_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 9260caef74fa..9999dc71b998 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -31,6 +31,7 @@
#include "atombios_encoders.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
+#include "dce_v10_0.h"
#include "dce/dce_10_0_d.h"
#include "dce/dce_10_0_sh_mask.h"
@@ -330,33 +331,12 @@ static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
static bool dce_v10_0_hpd_sense(struct amdgpu_device *adev,
enum amdgpu_hpd_id hpd)
{
- int idx;
bool connected = false;
- switch (hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (hpd >= adev->mode_info.num_hpd)
return connected;
- }
- if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) &
+ if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) &
DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK)
connected = true;
@@ -376,37 +356,16 @@ static void dce_v10_0_hpd_set_polarity(struct amdgpu_device *adev,
{
u32 tmp;
bool connected = dce_v10_0_hpd_sense(adev, hpd);
- int idx;
- switch (hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (hpd >= adev->mode_info.num_hpd)
return;
- }
- tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]);
if (connected)
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0);
else
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1);
- WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp);
}
/**
@@ -422,33 +381,12 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
u32 tmp;
- int idx;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
continue;
- }
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -457,24 +395,24 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
* https://bugzilla.redhat.com/show_bug.cgi?id=726143
* also avoid interrupt storms during dpms.
*/
- tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
- WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
continue;
}
- tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
- WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
- tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
DC_HPD_CONNECT_INT_DELAY,
AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS);
tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
DC_HPD_DISCONNECT_INT_DELAY,
AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
- WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
dce_v10_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
amdgpu_irq_get(adev, &adev->hpd_irq,
@@ -495,37 +433,16 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev)
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
u32 tmp;
- int idx;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
continue;
- }
- tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0);
- WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
amdgpu_irq_put(adev, &adev->hpd_irq,
amdgpu_connector->hpd.hpd);
@@ -2115,7 +2032,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
u32 tmp, viewport_w, viewport_h;
int r;
bool bypass_lut = false;
- char *format_name;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -2227,9 +2144,8 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
bypass_lut = true;
break;
default:
- format_name = drm_get_format_name(target_fb->pixel_format);
- DRM_ERROR("Unsupported screen format %s\n", format_name);
- kfree(format_name);
+ DRM_ERROR("Unsupported screen format %s\n",
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
@@ -2577,6 +2493,9 @@ static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc,
struct amdgpu_device *adev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
+
/* avivo cursor are offset into the total surface */
x += crtc->x;
y += crtc->y;
@@ -2593,11 +2512,6 @@ static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc,
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));
-
- amdgpu_crtc->cursor_x = x;
- amdgpu_crtc->cursor_y = y;
return 0;
}
@@ -2623,6 +2537,7 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
struct drm_gem_object *obj;
struct amdgpu_bo *aobj;
int ret;
@@ -2661,9 +2576,6 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
return ret;
}
- amdgpu_crtc->cursor_width = width;
- amdgpu_crtc->cursor_height = height;
-
dce_v10_0_lock_cursor(crtc, true);
if (hot_x != amdgpu_crtc->cursor_hot_x ||
@@ -2679,6 +2591,14 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
amdgpu_crtc->cursor_hot_y = hot_y;
}
+ if (width != amdgpu_crtc->cursor_width ||
+ height != amdgpu_crtc->cursor_height) {
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (width - 1) << 16 | (height - 1));
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
+ }
+
dce_v10_0_show_cursor(crtc);
dce_v10_0_lock_cursor(crtc, false);
@@ -2700,6 +2620,7 @@ unpin:
static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
if (amdgpu_crtc->cursor_bo) {
dce_v10_0_lock_cursor(crtc, true);
@@ -2707,6 +2628,10 @@ static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
dce_v10_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
amdgpu_crtc->cursor_y);
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (amdgpu_crtc->cursor_width - 1) << 16 |
+ (amdgpu_crtc->cursor_height - 1));
+
dce_v10_0_show_cursor(crtc);
dce_v10_0_lock_cursor(crtc, false);
@@ -3548,7 +3473,7 @@ static int dce_v10_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs dce_v10_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v10_0_ip_funcs = {
.name = "dce_v10_0",
.early_init = dce_v10_0_early_init,
.late_init = NULL,
@@ -3833,7 +3758,6 @@ static const struct amdgpu_display_funcs dce_v10_0_display_funcs = {
.bandwidth_update = &dce_v10_0_bandwidth_update,
.vblank_get_counter = &dce_v10_0_vblank_get_counter,
.vblank_wait = &dce_v10_0_vblank_wait,
- .is_display_hung = &dce_v10_0_is_display_hung,
.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
.hpd_sense = &dce_v10_0_hpd_sense,
@@ -3879,3 +3803,21 @@ static void dce_v10_0_set_irq_funcs(struct amdgpu_device *adev)
adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
adev->hpd_irq.funcs = &dce_v10_0_hpd_irq_funcs;
}
+
+const struct amdgpu_ip_block_version dce_v10_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 10,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &dce_v10_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v10_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 10,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &dce_v10_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
index e3dc04d293e4..7a0747789f1d 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
@@ -24,7 +24,9 @@
#ifndef __DCE_V10_0_H__
#define __DCE_V10_0_H__
-extern const struct amd_ip_funcs dce_v10_0_ip_funcs;
+
+extern const struct amdgpu_ip_block_version dce_v10_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v10_1_ip_block;
void dce_v10_0_disable_dce(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 367739bd1927..b3d62b909f43 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -31,6 +31,7 @@
#include "atombios_encoders.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
+#include "dce_v11_0.h"
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
@@ -346,33 +347,12 @@ static int dce_v11_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
static bool dce_v11_0_hpd_sense(struct amdgpu_device *adev,
enum amdgpu_hpd_id hpd)
{
- int idx;
bool connected = false;
- switch (hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (hpd >= adev->mode_info.num_hpd)
return connected;
- }
- if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) &
+ if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) &
DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK)
connected = true;
@@ -392,37 +372,16 @@ static void dce_v11_0_hpd_set_polarity(struct amdgpu_device *adev,
{
u32 tmp;
bool connected = dce_v11_0_hpd_sense(adev, hpd);
- int idx;
- switch (hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (hpd >= adev->mode_info.num_hpd)
return;
- }
- tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]);
if (connected)
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0);
else
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1);
- WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp);
}
/**
@@ -438,33 +397,12 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev)
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
u32 tmp;
- int idx;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
continue;
- }
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -473,24 +411,24 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev)
* https://bugzilla.redhat.com/show_bug.cgi?id=726143
* also avoid interrupt storms during dpms.
*/
- tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
- WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
continue;
}
- tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
- WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
- tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
DC_HPD_CONNECT_INT_DELAY,
AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS);
tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
DC_HPD_DISCONNECT_INT_DELAY,
AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
- WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
dce_v11_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
@@ -510,37 +448,16 @@ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev)
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
u32 tmp;
- int idx;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- idx = 0;
- break;
- case AMDGPU_HPD_2:
- idx = 1;
- break;
- case AMDGPU_HPD_3:
- idx = 2;
- break;
- case AMDGPU_HPD_4:
- idx = 3;
- break;
- case AMDGPU_HPD_5:
- idx = 4;
- break;
- case AMDGPU_HPD_6:
- idx = 5;
- break;
- default:
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
continue;
- }
- tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+ tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0);
- WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+ WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
}
@@ -2096,7 +2013,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
u32 tmp, viewport_w, viewport_h;
int r;
bool bypass_lut = false;
- char *format_name;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -2208,9 +2125,8 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
bypass_lut = true;
break;
default:
- format_name = drm_get_format_name(target_fb->pixel_format);
- DRM_ERROR("Unsupported screen format %s\n", format_name);
- kfree(format_name);
+ DRM_ERROR("Unsupported screen format %s\n",
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
@@ -2593,6 +2509,9 @@ static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc,
struct amdgpu_device *adev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
+
/* avivo cursor are offset into the total surface */
x += crtc->x;
y += crtc->y;
@@ -2609,11 +2528,6 @@ static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc,
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));
-
- amdgpu_crtc->cursor_x = x;
- amdgpu_crtc->cursor_y = y;
return 0;
}
@@ -2639,6 +2553,7 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
struct drm_gem_object *obj;
struct amdgpu_bo *aobj;
int ret;
@@ -2677,9 +2592,6 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
return ret;
}
- amdgpu_crtc->cursor_width = width;
- amdgpu_crtc->cursor_height = height;
-
dce_v11_0_lock_cursor(crtc, true);
if (hot_x != amdgpu_crtc->cursor_hot_x ||
@@ -2695,6 +2607,14 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
amdgpu_crtc->cursor_hot_y = hot_y;
}
+ if (width != amdgpu_crtc->cursor_width ||
+ height != amdgpu_crtc->cursor_height) {
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (width - 1) << 16 | (height - 1));
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
+ }
+
dce_v11_0_show_cursor(crtc);
dce_v11_0_lock_cursor(crtc, false);
@@ -2716,6 +2636,7 @@ unpin:
static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
if (amdgpu_crtc->cursor_bo) {
dce_v11_0_lock_cursor(crtc, true);
@@ -2723,6 +2644,10 @@ static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
dce_v11_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
amdgpu_crtc->cursor_y);
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (amdgpu_crtc->cursor_width - 1) << 16 |
+ (amdgpu_crtc->cursor_height - 1));
+
dce_v11_0_show_cursor(crtc);
dce_v11_0_lock_cursor(crtc, false);
@@ -3605,7 +3530,7 @@ static int dce_v11_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs dce_v11_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v11_0_ip_funcs = {
.name = "dce_v11_0",
.early_init = dce_v11_0_early_init,
.late_init = NULL,
@@ -3889,7 +3814,6 @@ static const struct amdgpu_display_funcs dce_v11_0_display_funcs = {
.bandwidth_update = &dce_v11_0_bandwidth_update,
.vblank_get_counter = &dce_v11_0_vblank_get_counter,
.vblank_wait = &dce_v11_0_vblank_wait,
- .is_display_hung = &dce_v11_0_is_display_hung,
.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
.hpd_sense = &dce_v11_0_hpd_sense,
@@ -3935,3 +3859,21 @@ static void dce_v11_0_set_irq_funcs(struct amdgpu_device *adev)
adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
adev->hpd_irq.funcs = &dce_v11_0_hpd_irq_funcs;
}
+
+const struct amdgpu_ip_block_version dce_v11_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 11,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &dce_v11_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v11_2_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 11,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &dce_v11_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
index 1f58a65ba2ef..0d878ca3acba 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
@@ -24,7 +24,8 @@
#ifndef __DCE_V11_0_H__
#define __DCE_V11_0_H__
-extern const struct amd_ip_funcs dce_v11_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v11_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v11_2_ip_block;
void dce_v11_0_disable_dce(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index 15f9fc0514b2..e564442b6393 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -30,8 +30,19 @@
#include "atombios_encoders.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
-#include "si/si_reg.h"
-#include "si/sid.h"
+
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gca/gfx_6_0_d.h"
+#include "gca/gfx_6_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "gca/gfx_7_2_enum.h"
+#include "si_enums.h"
static void dce_v6_0_set_display_funcs(struct amdgpu_device *adev);
static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -46,6 +57,16 @@ static const u32 crtc_offsets[6] =
SI_CRTC5_REGISTER_OFFSET
};
+static const u32 hpd_offsets[] =
+{
+ mmDC_HPD1_INT_STATUS - mmDC_HPD1_INT_STATUS,
+ mmDC_HPD2_INT_STATUS - mmDC_HPD1_INT_STATUS,
+ mmDC_HPD3_INT_STATUS - mmDC_HPD1_INT_STATUS,
+ mmDC_HPD4_INT_STATUS - mmDC_HPD1_INT_STATUS,
+ mmDC_HPD5_INT_STATUS - mmDC_HPD1_INT_STATUS,
+ mmDC_HPD6_INT_STATUS - mmDC_HPD1_INT_STATUS,
+};
+
static const uint32_t dig_offsets[] = {
SI_CRTC0_REGISTER_OFFSET,
SI_CRTC1_REGISTER_OFFSET,
@@ -63,46 +84,37 @@ static const struct {
uint32_t hpd;
} interrupt_status_offsets[6] = { {
- .reg = DISP_INTERRUPT_STATUS,
+ .reg = mmDISP_INTERRUPT_STATUS,
.vblank = DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK
}, {
- .reg = DISP_INTERRUPT_STATUS_CONTINUE,
+ .reg = mmDISP_INTERRUPT_STATUS_CONTINUE,
.vblank = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK
}, {
- .reg = DISP_INTERRUPT_STATUS_CONTINUE2,
+ .reg = mmDISP_INTERRUPT_STATUS_CONTINUE2,
.vblank = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK
}, {
- .reg = DISP_INTERRUPT_STATUS_CONTINUE3,
+ .reg = mmDISP_INTERRUPT_STATUS_CONTINUE3,
.vblank = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK
}, {
- .reg = DISP_INTERRUPT_STATUS_CONTINUE4,
+ .reg = mmDISP_INTERRUPT_STATUS_CONTINUE4,
.vblank = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK
}, {
- .reg = DISP_INTERRUPT_STATUS_CONTINUE5,
+ .reg = mmDISP_INTERRUPT_STATUS_CONTINUE5,
.vblank = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK,
.vline = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK,
.hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK
} };
-static const uint32_t hpd_int_control_offsets[6] = {
- DC_HPD1_INT_CONTROL,
- DC_HPD2_INT_CONTROL,
- DC_HPD3_INT_CONTROL,
- DC_HPD4_INT_CONTROL,
- DC_HPD5_INT_CONTROL,
- DC_HPD6_INT_CONTROL,
-};
-
static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev,
u32 block_offset, u32 reg)
{
@@ -118,7 +130,7 @@ static void dce_v6_0_audio_endpt_wreg(struct amdgpu_device *adev,
static bool dce_v6_0_is_in_vblank(struct amdgpu_device *adev, int crtc)
{
- if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+ if (RREG32(mmCRTC_STATUS + crtc_offsets[crtc]) & CRTC_STATUS__CRTC_V_BLANK_MASK)
return true;
else
return false;
@@ -128,8 +140,8 @@ static bool dce_v6_0_is_counter_moving(struct amdgpu_device *adev, int crtc)
{
u32 pos1, pos2;
- pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
- pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ pos1 = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ pos2 = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
if (pos1 != pos2)
return true;
@@ -151,7 +163,7 @@ static void dce_v6_0_vblank_wait(struct amdgpu_device *adev, int crtc)
if (crtc >= adev->mode_info.num_crtc)
return;
- if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN))
+ if (!(RREG32(mmCRTC_CONTROL + crtc_offsets[crtc]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK))
return;
/* depending on when we hit vblank, we may be close to active; if so,
@@ -179,7 +191,7 @@ static u32 dce_v6_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
if (crtc >= adev->mode_info.num_crtc)
return 0;
else
- return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
+ return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
static void dce_v6_0_pageflip_interrupt_init(struct amdgpu_device *adev)
@@ -219,16 +231,16 @@ static void dce_v6_0_page_flip(struct amdgpu_device *adev,
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
/* flip at hsync for async, default is vsync */
- WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
- EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
+ WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
+ GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK : 0);
/* update the scanout addresses */
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
(u32)crtc_base);
/* post the write */
- RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
+ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
@@ -236,8 +248,8 @@ static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
{
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL;
- *vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + crtc_offsets[crtc]);
- *position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ *vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
+ *position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
return 0;
@@ -257,34 +269,11 @@ static bool dce_v6_0_hpd_sense(struct amdgpu_device *adev,
{
bool connected = false;
- switch (hpd) {
- case AMDGPU_HPD_1:
- if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- case AMDGPU_HPD_2:
- if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- case AMDGPU_HPD_3:
- if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- case AMDGPU_HPD_4:
- if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- case AMDGPU_HPD_5:
- if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- case AMDGPU_HPD_6:
- if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
- connected = true;
- break;
- default:
- break;
- }
+ if (hpd >= adev->mode_info.num_hpd)
+ return connected;
+
+ if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
+ connected = true;
return connected;
}
@@ -303,58 +292,15 @@ static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev,
u32 tmp;
bool connected = dce_v6_0_hpd_sense(adev, hpd);
- switch (hpd) {
- case AMDGPU_HPD_1:
- tmp = RREG32(DC_HPD1_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD1_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_2:
- tmp = RREG32(DC_HPD2_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD2_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_3:
- tmp = RREG32(DC_HPD3_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD3_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_4:
- tmp = RREG32(DC_HPD4_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD4_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_5:
- tmp = RREG32(DC_HPD5_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD5_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_6:
- tmp = RREG32(DC_HPD6_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPDx_INT_POLARITY;
- else
- tmp |= DC_HPDx_INT_POLARITY;
- WREG32(DC_HPD6_INT_CONTROL, tmp);
- break;
- default:
- break;
- }
+ if (hpd >= adev->mode_info.num_hpd)
+ return;
+
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+ if (connected)
+ tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+ else
+ tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
}
/**
@@ -369,34 +315,17 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
- u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
- DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;
+ u32 tmp;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- WREG32(DC_HPD1_CONTROL, tmp);
- break;
- case AMDGPU_HPD_2:
- WREG32(DC_HPD2_CONTROL, tmp);
- break;
- case AMDGPU_HPD_3:
- WREG32(DC_HPD3_CONTROL, tmp);
- break;
- case AMDGPU_HPD_4:
- WREG32(DC_HPD4_CONTROL, tmp);
- break;
- case AMDGPU_HPD_5:
- WREG32(DC_HPD5_CONTROL, tmp);
- break;
- case AMDGPU_HPD_6:
- WREG32(DC_HPD6_CONTROL, tmp);
- break;
- default:
- break;
- }
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+ continue;
+
+ tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp |= DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+ WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -405,34 +334,9 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev)
* https://bugzilla.redhat.com/show_bug.cgi?id=726143
* also avoid interrupt storms during dpms.
*/
- u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
-
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL;
- break;
- case AMDGPU_HPD_2:
- dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL;
- break;
- case AMDGPU_HPD_3:
- dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL;
- break;
- case AMDGPU_HPD_4:
- dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL;
- break;
- case AMDGPU_HPD_5:
- dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL;
- break;
- case AMDGPU_HPD_6:
- dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL;
- break;
- default:
- continue;
- }
-
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
- dc_hpd_int_cntl &= ~DC_HPDx_INT_EN;
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
continue;
}
@@ -454,46 +358,25 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
+ u32 tmp;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- WREG32(DC_HPD1_CONTROL, 0);
- break;
- case AMDGPU_HPD_2:
- WREG32(DC_HPD2_CONTROL, 0);
- break;
- case AMDGPU_HPD_3:
- WREG32(DC_HPD3_CONTROL, 0);
- break;
- case AMDGPU_HPD_4:
- WREG32(DC_HPD4_CONTROL, 0);
- break;
- case AMDGPU_HPD_5:
- WREG32(DC_HPD5_CONTROL, 0);
- break;
- case AMDGPU_HPD_6:
- WREG32(DC_HPD6_CONTROL, 0);
- break;
- default:
- break;
- }
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+ continue;
+
+ tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp &= ~DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+ WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0);
+
amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
}
}
static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
{
- return SI_DC_GPIO_HPD_A;
-}
-
-static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev)
-{
- DRM_INFO("xxxx: dce_v6_0_is_display_hung ----no imp!!!!!\n");
-
- return true;
+ return mmDC_GPIO_HPD_A;
}
static u32 evergreen_get_vblank_counter(struct amdgpu_device* adev, int crtc)
@@ -501,7 +384,7 @@ static u32 evergreen_get_vblank_counter(struct amdgpu_device* adev, int crtc)
if (crtc >= adev->mode_info.num_crtc)
return 0;
else
- return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
+ return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev,
@@ -510,25 +393,25 @@ static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev,
u32 crtc_enabled, tmp, frame_count;
int i, j;
- save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
- save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+ save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL);
+ save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL);
/* disable VGA render */
- WREG32(VGA_RENDER_CONTROL, 0);
+ WREG32(mmVGA_RENDER_CONTROL, 0);
/* blank the display controllers */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
- crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN;
+ crtc_enabled = RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK;
if (crtc_enabled) {
save->crtc_enabled[i] = true;
- tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
+ tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
- if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
+ if (!(tmp & CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK)) {
dce_v6_0_vblank_wait(adev, i);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
- tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
- WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp |= CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK;
+ WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
/* wait for the next frame */
frame_count = evergreen_get_vblank_counter(adev, i);
@@ -539,11 +422,11 @@ static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev,
}
/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
- tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
- tmp &= ~EVERGREEN_CRTC_MASTER_EN;
- WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+ WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
save->crtc_enabled[i] = false;
/* ***** */
} else {
@@ -560,41 +443,40 @@ static void dce_v6_0_resume_mc_access(struct amdgpu_device *adev,
/* update crtc base addresses */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
upper_32_bits(adev->mc.vram_start));
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+ WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
upper_32_bits(adev->mc.vram_start));
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
(u32)adev->mc.vram_start);
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
+ WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
(u32)adev->mc.vram_start);
}
- WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
- WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start);
+ WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
+ WREG32(mmVGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start);
/* unlock regs and wait for update */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
if (save->crtc_enabled[i]) {
- tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]);
- if ((tmp & 0x7) != 3) {
+ tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]);
+ if ((tmp & 0x7) != 0) {
tmp &= ~0x7;
- tmp |= 0x3;
- WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+ WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp);
}
- tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
- if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) {
- tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
- WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+ tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+ if (tmp & GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK) {
+ tmp &= ~GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
+ WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
}
- tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ tmp = RREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i]);
if (tmp & 1) {
tmp &= ~1;
- WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ WREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
}
for (j = 0; j < adev->usec_timeout; j++) {
- tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
- if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0)
+ tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+ if ((tmp & GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK) == 0)
break;
udelay(1);
}
@@ -602,19 +484,62 @@ static void dce_v6_0_resume_mc_access(struct amdgpu_device *adev,
}
/* Unlock vga access */
- WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
+ WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control);
mdelay(1);
- WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+ WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
}
static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev,
bool render)
{
- if (!render)
- WREG32(R_000300_VGA_RENDER_CONTROL,
- RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
+ if (!render)
+ WREG32(mmVGA_RENDER_CONTROL,
+ RREG32(mmVGA_RENDER_CONTROL) & VGA_VSTATUS_CNTL);
+
+}
+
+static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev)
+{
+ int num_crtc = 0;
+
+ switch (adev->asic_type) {
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ case CHIP_VERDE:
+ num_crtc = 6;
+ break;
+ case CHIP_OLAND:
+ num_crtc = 2;
+ break;
+ default:
+ num_crtc = 0;
+ }
+ return num_crtc;
+}
+
+void dce_v6_0_disable_dce(struct amdgpu_device *adev)
+{
+ /*Disable VGA render and enabled crtc, if has DCE engine*/
+ if (amdgpu_atombios_has_dce_engine_info(adev)) {
+ u32 tmp;
+ int crtc_enabled, i;
+
+ dce_v6_0_set_vga_render_state(adev, false);
+ /*Disable crtc*/
+ for (i = 0; i < dce_v6_0_get_num_crtc(adev); i++) {
+ crtc_enabled = RREG32(mmCRTC_CONTROL + crtc_offsets[i]) &
+ CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+ if (crtc_enabled) {
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+ WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ }
+ }
+ }
}
static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
@@ -647,19 +572,23 @@ static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
case 6:
if (dither == AMDGPU_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
- tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
- FMT_SPATIAL_DITHER_EN);
+ tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK);
else
- tmp |= FMT_TRUNCATE_EN;
+ tmp |= FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK;
break;
case 8:
if (dither == AMDGPU_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
- tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
- FMT_RGB_RANDOM_ENABLE |
- FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
+ tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH_MASK);
else
- tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH);
+ tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK |
+ FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH_MASK);
break;
case 10:
default:
@@ -667,7 +596,7 @@ static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
break;
}
- WREG32(FMT_BIT_DEPTH_CONTROL + amdgpu_crtc->crtc_offset, tmp);
+ WREG32(mmFMT_BIT_DEPTH_CONTROL + amdgpu_crtc->crtc_offset, tmp);
}
/**
@@ -681,7 +610,7 @@ static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
*/
static u32 si_get_number_of_dram_channels(struct amdgpu_device *adev)
{
- u32 tmp = RREG32(MC_SHARED_CHMAP);
+ u32 tmp = RREG32(mmMC_SHARED_CHMAP);
switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) {
case 0:
@@ -1178,28 +1107,28 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
}
/* select wm A */
- arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
+ arb_control3 = RREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
tmp = arb_control3;
tmp &= ~LATENCY_WATERMARK_MASK(3);
tmp |= LATENCY_WATERMARK_MASK(1);
- WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
- WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset,
- (LATENCY_LOW_WATERMARK(latency_watermark_a) |
- LATENCY_HIGH_WATERMARK(line_time)));
+ WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
+ WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset,
+ ((latency_watermark_a << DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT) |
+ (line_time << DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT)));
/* select wm B */
- tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
+ tmp = RREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
tmp &= ~LATENCY_WATERMARK_MASK(3);
tmp |= LATENCY_WATERMARK_MASK(2);
- WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
- WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset,
- (LATENCY_LOW_WATERMARK(latency_watermark_b) |
- LATENCY_HIGH_WATERMARK(line_time)));
+ WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
+ WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset,
+ ((latency_watermark_b << DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT) |
+ (line_time << DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT)));
/* restore original selection */
- WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, arb_control3);
+ WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, arb_control3);
/* write the priority marks */
- WREG32(PRIORITY_A_CNT + amdgpu_crtc->crtc_offset, priority_a_cnt);
- WREG32(PRIORITY_B_CNT + amdgpu_crtc->crtc_offset, priority_b_cnt);
+ WREG32(mmPRIORITY_A_CNT + amdgpu_crtc->crtc_offset, priority_a_cnt);
+ WREG32(mmPRIORITY_B_CNT + amdgpu_crtc->crtc_offset, priority_b_cnt);
/* save values for DPM */
amdgpu_crtc->line_time = line_time;
@@ -1217,7 +1146,7 @@ static u32 dce_v6_0_line_buffer_adjust(struct amdgpu_device *adev,
/*
* Line Buffer Setup
* There are 3 line buffers, each one shared by 2 display controllers.
- * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
+ * mmDC_LB_MEMORY_SPLIT controls how that line buffer is shared between
* the display controllers. The paritioning is done via one of four
* preset allocations specified in bits 21:20:
* 0 - half lb
@@ -1240,14 +1169,14 @@ static u32 dce_v6_0_line_buffer_adjust(struct amdgpu_device *adev,
buffer_alloc = 0;
}
- WREG32(DC_LB_MEMORY_SPLIT + amdgpu_crtc->crtc_offset,
+ WREG32(mmDC_LB_MEMORY_SPLIT + amdgpu_crtc->crtc_offset,
DC_LB_MEMORY_CONFIG(tmp));
- WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
- DMIF_BUFFERS_ALLOCATED(buffer_alloc));
+ WREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
+ (buffer_alloc << PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT));
for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
- DMIF_BUFFERS_ALLOCATED_COMPLETED)
+ if (RREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
+ PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK)
break;
udelay(1);
}
@@ -1489,12 +1418,12 @@ static void dce_v6_0_afmt_fini(struct amdgpu_device *adev)
static const u32 vga_control_regs[6] =
{
- AVIVO_D1VGA_CONTROL,
- AVIVO_D2VGA_CONTROL,
- EVERGREEN_D3VGA_CONTROL,
- EVERGREEN_D4VGA_CONTROL,
- EVERGREEN_D5VGA_CONTROL,
- EVERGREEN_D6VGA_CONTROL,
+ mmD1VGA_CONTROL,
+ mmD2VGA_CONTROL,
+ mmD3VGA_CONTROL,
+ mmD4VGA_CONTROL,
+ mmD5VGA_CONTROL,
+ mmD6VGA_CONTROL,
};
static void dce_v6_0_vga_enable(struct drm_crtc *crtc, bool enable)
@@ -1514,7 +1443,7 @@ static void dce_v6_0_grph_enable(struct drm_crtc *crtc, bool enable)
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
- WREG32(EVERGREEN_GRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0);
+ WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0);
}
static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
@@ -1530,10 +1459,11 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
struct amdgpu_bo *abo;
uint64_t fb_location, tiling_flags;
uint32_t fb_format, fb_pitch_pixels, pipe_config;
- u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
+ u32 fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_NONE);
u32 viewport_w, viewport_h;
int r;
bool bypass_lut = false;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -1573,71 +1503,71 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
switch (target_fb->pixel_format) {
case DRM_FORMAT_C8:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_8BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_INDEXED));
break;
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB4444:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB4444));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_ARGB4444));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
#endif
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_ARGB1555));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
#endif
break;
case DRM_FORMAT_BGRX5551:
case DRM_FORMAT_BGRA5551:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA5551));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_BGRA5551));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
#endif
break;
case DRM_FORMAT_RGB565:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_ARGB565));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
#endif
break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_ARGB8888));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
#endif
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB2101010));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_ARGB2101010));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
#endif
/* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
bypass_lut = true;
break;
case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_BGRA1010102:
- fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
- EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA1010102));
+ fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+ GRPH_FORMAT(GRPH_FORMAT_BGRA1010102));
#ifdef __BIG_ENDIAN
- fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+ fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
#endif
/* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
bypass_lut = true;
break;
default:
DRM_ERROR("Unsupported screen format %s\n",
- drm_get_format_name(target_fb->pixel_format));
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
@@ -1650,75 +1580,75 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
- fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
- fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
- fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
- fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
- fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
- fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect);
+ fb_format |= GRPH_NUM_BANKS(num_banks);
+ fb_format |= GRPH_ARRAY_MODE(GRPH_ARRAY_2D_TILED_THIN1);
+ fb_format |= GRPH_TILE_SPLIT(tile_split);
+ fb_format |= GRPH_BANK_WIDTH(bankw);
+ fb_format |= GRPH_BANK_HEIGHT(bankh);
+ fb_format |= GRPH_MACRO_TILE_ASPECT(mtaspect);
} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == ARRAY_1D_TILED_THIN1) {
- fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
+ fb_format |= GRPH_ARRAY_MODE(GRPH_ARRAY_1D_TILED_THIN1);
}
pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
- fb_format |= SI_GRPH_PIPE_CONFIG(pipe_config);
+ fb_format |= GRPH_PIPE_CONFIG(pipe_config);
dce_v6_0_vga_enable(crtc, false);
/* Make sure surface address is updated at vertical blank rather than
* horizontal blank
*/
- WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(fb_location));
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(fb_location));
- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
- (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
- WREG32(EVERGREEN_GRPH_CONTROL + amdgpu_crtc->crtc_offset, fb_format);
- WREG32(EVERGREEN_GRPH_SWAP_CONTROL + amdgpu_crtc->crtc_offset, fb_swap);
+ WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ (u32)fb_location & GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK);
+ WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ (u32) fb_location & GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK);
+ WREG32(mmGRPH_CONTROL + amdgpu_crtc->crtc_offset, fb_format);
+ WREG32(mmGRPH_SWAP_CNTL + amdgpu_crtc->crtc_offset, fb_swap);
/*
* The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT
* for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to
* retain the full precision throughout the pipeline.
*/
- WREG32_P(EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL + amdgpu_crtc->crtc_offset,
- (bypass_lut ? EVERGREEN_LUT_10BIT_BYPASS_EN : 0),
- ~EVERGREEN_LUT_10BIT_BYPASS_EN);
+ WREG32_P(mmGRPH_LUT_10BIT_BYPASS + amdgpu_crtc->crtc_offset,
+ (bypass_lut ? GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK : 0),
+ ~GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK);
if (bypass_lut)
DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");
- WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_GRPH_X_START + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_GRPH_Y_START + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_GRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
- WREG32(EVERGREEN_GRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
+ WREG32(mmGRPH_SURFACE_OFFSET_X + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmGRPH_SURFACE_OFFSET_Y + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmGRPH_X_START + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmGRPH_Y_START + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
+ WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
- WREG32(EVERGREEN_GRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
+ WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
dce_v6_0_grph_enable(crtc, true);
- WREG32(EVERGREEN_DESKTOP_HEIGHT + amdgpu_crtc->crtc_offset,
+ WREG32(mmDESKTOP_HEIGHT + amdgpu_crtc->crtc_offset,
target_fb->height);
x &= ~3;
y &= ~1;
- WREG32(EVERGREEN_VIEWPORT_START + amdgpu_crtc->crtc_offset,
+ WREG32(mmVIEWPORT_START + amdgpu_crtc->crtc_offset,
(x << 16) | y);
viewport_w = crtc->mode.hdisplay;
viewport_h = (crtc->mode.vdisplay + 1) & ~1;
- WREG32(EVERGREEN_VIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
+ WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
/* set pageflip to happen anywhere in vblank interval */
- WREG32(EVERGREEN_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb);
@@ -1745,10 +1675,10 @@ static void dce_v6_0_set_interleave(struct drm_crtc *crtc,
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset,
- EVERGREEN_INTERLEAVE_EN);
+ WREG32(mmDATA_FORMAT + amdgpu_crtc->crtc_offset,
+ INTERLEAVE_EN);
else
- WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDATA_FORMAT + amdgpu_crtc->crtc_offset, 0);
}
static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc)
@@ -1761,54 +1691,52 @@ static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc)
DRM_DEBUG_KMS("%d\n", amdgpu_crtc->crtc_id);
- WREG32(NI_INPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
- NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
- WREG32(NI_PRESCALE_GRPH_CONTROL + amdgpu_crtc->crtc_offset,
- NI_GRPH_PRESCALE_BYPASS);
- WREG32(NI_PRESCALE_OVL_CONTROL + amdgpu_crtc->crtc_offset,
- NI_OVL_PRESCALE_BYPASS);
- WREG32(NI_INPUT_GAMMA_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) |
- NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT)));
-
+ WREG32(mmINPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE__SHIFT) |
+ (0 << INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE__SHIFT)));
+ WREG32(mmPRESCALE_GRPH_CONTROL + amdgpu_crtc->crtc_offset,
+ PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS_MASK);
+ WREG32(mmPRESCALE_OVL_CONTROL + amdgpu_crtc->crtc_offset,
+ PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS_MASK);
+ WREG32(mmINPUT_GAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE__SHIFT) |
+ (0 << INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE__SHIFT)));
+ WREG32(mmDC_LUT_CONTROL + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_DC_LUT_CONTROL + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_BLACK_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_BLACK_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_BLACK_OFFSET_RED + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_WHITE_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0xffff);
+ WREG32(mmDC_LUT_WHITE_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0xffff);
+ WREG32(mmDC_LUT_WHITE_OFFSET_RED + amdgpu_crtc->crtc_offset, 0xffff);
- WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0xffff);
- WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0xffff);
- WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + amdgpu_crtc->crtc_offset, 0xffff);
+ WREG32(mmDC_LUT_RW_MODE + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x00000007);
- WREG32(EVERGREEN_DC_LUT_RW_MODE + amdgpu_crtc->crtc_offset, 0);
- WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x00000007);
-
- WREG32(EVERGREEN_DC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0);
+ WREG32(mmDC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0);
for (i = 0; i < 256; i++) {
- WREG32(EVERGREEN_DC_LUT_30_COLOR + amdgpu_crtc->crtc_offset,
+ WREG32(mmDC_LUT_30_COLOR + amdgpu_crtc->crtc_offset,
(amdgpu_crtc->lut_r[i] << 20) |
(amdgpu_crtc->lut_g[i] << 10) |
(amdgpu_crtc->lut_b[i] << 0));
}
- WREG32(NI_DEGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
- NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
- NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
- NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
- WREG32(NI_GAMUT_REMAP_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) |
- NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS)));
- WREG32(NI_REGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
- NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
- WREG32(NI_OUTPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
- (NI_OUTPUT_CSC_GRPH_MODE(0) |
- NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
+ WREG32(mmDEGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE__SHIFT) |
+ (0 << DEGAMMA_CONTROL__OVL_DEGAMMA_MODE__SHIFT) |
+ ICON_DEGAMMA_MODE(0) |
+ (0 << DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE__SHIFT)));
+ WREG32(mmGAMUT_REMAP_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE__SHIFT) |
+ (0 << GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE__SHIFT)));
+ WREG32(mmREGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << REGAMMA_CONTROL__GRPH_REGAMMA_MODE__SHIFT) |
+ (0 << REGAMMA_CONTROL__OVL_REGAMMA_MODE__SHIFT)));
+ WREG32(mmOUTPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
+ ((0 << OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE__SHIFT) |
+ (0 << OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE__SHIFT)));
/* XXX match this to the depth of the crtc fmt block, move to modeset? */
WREG32(0x1a50 + amdgpu_crtc->crtc_offset, 0);
@@ -1887,12 +1815,12 @@ static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock)
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
uint32_t cur_lock;
- cur_lock = RREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset);
+ cur_lock = RREG32(mmCUR_UPDATE + amdgpu_crtc->crtc_offset);
if (lock)
- cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
+ cur_lock |= CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK;
else
- cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
- WREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset, cur_lock);
+ cur_lock &= ~CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK;
+ WREG32(mmCUR_UPDATE + amdgpu_crtc->crtc_offset, cur_lock);
}
static void dce_v6_0_hide_cursor(struct drm_crtc *crtc)
@@ -1900,9 +1828,9 @@ static void dce_v6_0_hide_cursor(struct drm_crtc *crtc)
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = crtc->dev->dev_private;
- WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset,
- EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
- EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
+ WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset,
+ (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) |
+ (CURSOR_URGENT_1_2 << CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT));
}
@@ -1912,15 +1840,15 @@ static void dce_v6_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(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+ WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(amdgpu_crtc->cursor_addr));
- WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+ WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(amdgpu_crtc->cursor_addr));
- WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset,
- EVERGREEN_CURSOR_EN |
- EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
- EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
+ 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));
}
@@ -1931,7 +1859,8 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc,
struct amdgpu_device *adev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
- int w = amdgpu_crtc->cursor_width;
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
/* avivo cursor are offset into the total surface */
x += crtc->x;
@@ -1947,13 +1876,9 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc,
y = 0;
}
- WREG32(EVERGREEN_CUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
- WREG32(EVERGREEN_CUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
- WREG32(EVERGREEN_CUR_SIZE + amdgpu_crtc->crtc_offset,
- ((w - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
+ WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
+ WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
- amdgpu_crtc->cursor_x = x;
- amdgpu_crtc->cursor_y = y;
return 0;
}
@@ -1978,6 +1903,7 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
struct drm_gem_object *obj;
struct amdgpu_bo *aobj;
int ret;
@@ -2016,12 +1942,11 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
return ret;
}
- amdgpu_crtc->cursor_width = width;
- amdgpu_crtc->cursor_height = height;
-
dce_v6_0_lock_cursor(crtc, true);
- if (hot_x != amdgpu_crtc->cursor_hot_x ||
+ if (width != amdgpu_crtc->cursor_width ||
+ height != amdgpu_crtc->cursor_height ||
+ hot_x != amdgpu_crtc->cursor_hot_x ||
hot_y != amdgpu_crtc->cursor_hot_y) {
int x, y;
@@ -2030,10 +1955,20 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
dce_v6_0_cursor_move_locked(crtc, x, y);
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
amdgpu_crtc->cursor_hot_x = hot_x;
amdgpu_crtc->cursor_hot_y = hot_y;
}
+ if (width != amdgpu_crtc->cursor_width ||
+ height != amdgpu_crtc->cursor_height) {
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (width - 1) << 16 | (height - 1));
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
+ }
+
dce_v6_0_show_cursor(crtc);
dce_v6_0_lock_cursor(crtc, false);
@@ -2055,6 +1990,7 @@ unpin:
static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
if (amdgpu_crtc->cursor_bo) {
dce_v6_0_lock_cursor(crtc, true);
@@ -2062,6 +1998,10 @@ static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
dce_v6_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
amdgpu_crtc->cursor_y);
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (amdgpu_crtc->cursor_width - 1) << 16 |
+ (amdgpu_crtc->cursor_height - 1));
+
dce_v6_0_show_cursor(crtc);
dce_v6_0_lock_cursor(crtc, false);
}
@@ -2117,13 +2057,13 @@ static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode)
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);
+ drm_crtc_vblank_on(crtc);
dce_v6_0_crtc_load_lut(crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- drm_vblank_pre_modeset(dev, amdgpu_crtc->crtc_id);
+ drm_crtc_vblank_off(crtc);
if (amdgpu_crtc->enabled)
amdgpu_atombios_crtc_blank(crtc, ATOM_ENABLE);
amdgpu_atombios_crtc_enable(crtc, ATOM_DISABLE);
@@ -2338,21 +2278,20 @@ static int dce_v6_0_early_init(void *handle)
dce_v6_0_set_display_funcs(adev);
dce_v6_0_set_irq_funcs(adev);
+ adev->mode_info.num_crtc = dce_v6_0_get_num_crtc(adev);
+
switch (adev->asic_type) {
case CHIP_TAHITI:
case CHIP_PITCAIRN:
case CHIP_VERDE:
- adev->mode_info.num_crtc = 6;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6;
break;
case CHIP_OLAND:
- adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 2;
adev->mode_info.num_dig = 2;
break;
default:
- /* FIXME: not supported yet */
return -EINVAL;
}
@@ -2556,14 +2495,14 @@ static void dce_v6_0_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- interrupt_mask = RREG32(INT_MASK + reg_block);
+ interrupt_mask = RREG32(mmINT_MASK + reg_block);
interrupt_mask &= ~VBLANK_INT_MASK;
- WREG32(INT_MASK + reg_block, interrupt_mask);
+ WREG32(mmINT_MASK + reg_block, interrupt_mask);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- interrupt_mask = RREG32(INT_MASK + reg_block);
+ interrupt_mask = RREG32(mmINT_MASK + reg_block);
interrupt_mask |= VBLANK_INT_MASK;
- WREG32(INT_MASK + reg_block, interrupt_mask);
+ WREG32(mmINT_MASK + reg_block, interrupt_mask);
break;
default:
break;
@@ -2582,42 +2521,23 @@ static int dce_v6_0_set_hpd_interrupt_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
+ u32 dc_hpd_int_cntl;
- switch (type) {
- case AMDGPU_HPD_1:
- dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL;
- break;
- case AMDGPU_HPD_2:
- dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL;
- break;
- case AMDGPU_HPD_3:
- dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL;
- break;
- case AMDGPU_HPD_4:
- dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL;
- break;
- case AMDGPU_HPD_5:
- dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL;
- break;
- case AMDGPU_HPD_6:
- dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL;
- break;
- default:
+ if (type >= adev->mode_info.num_hpd) {
DRM_DEBUG("invalid hdp %d\n", type);
return 0;
}
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
- dc_hpd_int_cntl &= ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
+ dc_hpd_int_cntl &= ~DC_HPDx_INT_EN;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
- dc_hpd_int_cntl |= (DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
+ dc_hpd_int_cntl |= DC_HPDx_INT_EN;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
break;
default:
break;
@@ -2685,7 +2605,7 @@ static int dce_v6_0_crtc_irq(struct amdgpu_device *adev,
switch (entry->src_data) {
case 0: /* vblank */
if (disp_int & interrupt_status_offsets[crtc].vblank)
- WREG32(VBLANK_STATUS + crtc_offsets[crtc], VBLANK_ACK);
+ WREG32(mmVBLANK_STATUS + crtc_offsets[crtc], VBLANK_ACK);
else
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
@@ -2696,7 +2616,7 @@ static int dce_v6_0_crtc_irq(struct amdgpu_device *adev,
break;
case 1: /* vline */
if (disp_int & interrupt_status_offsets[crtc].vline)
- WREG32(VLINE_STATUS + crtc_offsets[crtc], VLINE_ACK);
+ WREG32(mmVLINE_STATUS + crtc_offsets[crtc], VLINE_ACK);
else
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
@@ -2722,12 +2642,12 @@ static int dce_v6_0_set_pageflip_interrupt_state(struct amdgpu_device *adev,
return -EINVAL;
}
- reg = RREG32(GRPH_INT_CONTROL + crtc_offsets[type]);
+ reg = RREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type]);
if (state == AMDGPU_IRQ_STATE_DISABLE)
- WREG32(GRPH_INT_CONTROL + crtc_offsets[type],
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
else
- WREG32(GRPH_INT_CONTROL + crtc_offsets[type],
+ WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
return 0;
@@ -2750,9 +2670,9 @@ static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev,
return -EINVAL;
}
- if (RREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id]) &
+ if (RREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id]) &
GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
- WREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id],
+ WREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id],
GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
/* IRQ could occur when in initial stage */
@@ -2790,7 +2710,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- uint32_t disp_int, mask, int_control, tmp;
+ uint32_t disp_int, mask, tmp;
unsigned hpd;
if (entry->src_data >= adev->mode_info.num_hpd) {
@@ -2801,12 +2721,11 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
hpd = entry->src_data;
disp_int = RREG32(interrupt_status_offsets[hpd].reg);
mask = interrupt_status_offsets[hpd].hpd;
- int_control = hpd_int_control_offsets[hpd];
if (disp_int & mask) {
- tmp = RREG32(int_control);
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
- WREG32(int_control, tmp);
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
schedule_work(&adev->hotplug_work);
DRM_INFO("IH: HPD%d\n", hpd + 1);
}
@@ -2827,7 +2746,7 @@ static int dce_v6_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs dce_v6_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v6_0_ip_funcs = {
.name = "dce_v6_0",
.early_init = dce_v6_0_early_init,
.late_init = NULL,
@@ -3122,7 +3041,6 @@ static const struct amdgpu_display_funcs dce_v6_0_display_funcs = {
.bandwidth_update = &dce_v6_0_bandwidth_update,
.vblank_get_counter = &dce_v6_0_vblank_get_counter,
.vblank_wait = &dce_v6_0_vblank_wait,
- .is_display_hung = &dce_v6_0_is_display_hung,
.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
.hpd_sense = &dce_v6_0_hpd_sense,
@@ -3168,3 +3086,21 @@ static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev)
adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
adev->hpd_irq.funcs = &dce_v6_0_hpd_irq_funcs;
}
+
+const struct amdgpu_ip_block_version dce_v6_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 6,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &dce_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v6_4_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 6,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &dce_v6_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h
index 6a5528105bb6..7b546b596de1 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h
@@ -24,6 +24,9 @@
#ifndef __DCE_V6_0_H__
#define __DCE_V6_0_H__
-extern const struct amd_ip_funcs dce_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v6_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v6_4_ip_block;
+
+void dce_v6_0_disable_dce(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 8c4d808db0f1..6ce7fb42dbef 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -31,6 +31,7 @@
#include "atombios_encoders.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
+#include "dce_v8_0.h"
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
@@ -56,6 +57,16 @@ static const u32 crtc_offsets[6] =
CRTC5_REGISTER_OFFSET
};
+static const u32 hpd_offsets[] =
+{
+ HPD0_REGISTER_OFFSET,
+ HPD1_REGISTER_OFFSET,
+ HPD2_REGISTER_OFFSET,
+ HPD3_REGISTER_OFFSET,
+ HPD4_REGISTER_OFFSET,
+ HPD5_REGISTER_OFFSET
+};
+
static const uint32_t dig_offsets[] = {
CRTC0_REGISTER_OFFSET,
CRTC1_REGISTER_OFFSET,
@@ -104,15 +115,6 @@ static const struct {
.hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK
} };
-static const uint32_t hpd_int_control_offsets[6] = {
- mmDC_HPD1_INT_CONTROL,
- mmDC_HPD2_INT_CONTROL,
- mmDC_HPD3_INT_CONTROL,
- mmDC_HPD4_INT_CONTROL,
- mmDC_HPD5_INT_CONTROL,
- mmDC_HPD6_INT_CONTROL,
-};
-
static u32 dce_v8_0_audio_endpt_rreg(struct amdgpu_device *adev,
u32 block_offset, u32 reg)
{
@@ -278,34 +280,12 @@ static bool dce_v8_0_hpd_sense(struct amdgpu_device *adev,
{
bool connected = false;
- switch (hpd) {
- case AMDGPU_HPD_1:
- if (RREG32(mmDC_HPD1_INT_STATUS) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
- connected = true;
- break;
- case AMDGPU_HPD_2:
- if (RREG32(mmDC_HPD2_INT_STATUS) & DC_HPD2_INT_STATUS__DC_HPD2_SENSE_MASK)
- connected = true;
- break;
- case AMDGPU_HPD_3:
- if (RREG32(mmDC_HPD3_INT_STATUS) & DC_HPD3_INT_STATUS__DC_HPD3_SENSE_MASK)
- connected = true;
- break;
- case AMDGPU_HPD_4:
- if (RREG32(mmDC_HPD4_INT_STATUS) & DC_HPD4_INT_STATUS__DC_HPD4_SENSE_MASK)
- connected = true;
- break;
- case AMDGPU_HPD_5:
- if (RREG32(mmDC_HPD5_INT_STATUS) & DC_HPD5_INT_STATUS__DC_HPD5_SENSE_MASK)
- connected = true;
- break;
- case AMDGPU_HPD_6:
- if (RREG32(mmDC_HPD6_INT_STATUS) & DC_HPD6_INT_STATUS__DC_HPD6_SENSE_MASK)
- connected = true;
- break;
- default:
- break;
- }
+ if (hpd >= adev->mode_info.num_hpd)
+ return connected;
+
+ if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) &
+ DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
+ connected = true;
return connected;
}
@@ -324,58 +304,15 @@ static void dce_v8_0_hpd_set_polarity(struct amdgpu_device *adev,
u32 tmp;
bool connected = dce_v8_0_hpd_sense(adev, hpd);
- switch (hpd) {
- case AMDGPU_HPD_1:
- tmp = RREG32(mmDC_HPD1_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
- WREG32(mmDC_HPD1_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_2:
- tmp = RREG32(mmDC_HPD2_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK;
- WREG32(mmDC_HPD2_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_3:
- tmp = RREG32(mmDC_HPD3_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK;
- WREG32(mmDC_HPD3_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_4:
- tmp = RREG32(mmDC_HPD4_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK;
- WREG32(mmDC_HPD4_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_5:
- tmp = RREG32(mmDC_HPD5_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK;
- WREG32(mmDC_HPD5_INT_CONTROL, tmp);
- break;
- case AMDGPU_HPD_6:
- tmp = RREG32(mmDC_HPD6_INT_CONTROL);
- if (connected)
- tmp &= ~DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK;
- else
- tmp |= DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK;
- WREG32(mmDC_HPD6_INT_CONTROL, tmp);
- break;
- default:
- break;
- }
+ if (hpd >= adev->mode_info.num_hpd)
+ return;
+
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+ if (connected)
+ tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+ else
+ tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
}
/**
@@ -390,35 +327,17 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
- u32 tmp = (0x9c4 << DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER__SHIFT) |
- (0xfa << DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER__SHIFT) |
- DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+ u32 tmp;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- WREG32(mmDC_HPD1_CONTROL, tmp);
- break;
- case AMDGPU_HPD_2:
- WREG32(mmDC_HPD2_CONTROL, tmp);
- break;
- case AMDGPU_HPD_3:
- WREG32(mmDC_HPD3_CONTROL, tmp);
- break;
- case AMDGPU_HPD_4:
- WREG32(mmDC_HPD4_CONTROL, tmp);
- break;
- case AMDGPU_HPD_5:
- WREG32(mmDC_HPD5_CONTROL, tmp);
- break;
- case AMDGPU_HPD_6:
- WREG32(mmDC_HPD6_CONTROL, tmp);
- break;
- default:
- break;
- }
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+ continue;
+
+ tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp |= DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+ WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -427,34 +346,9 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev)
* https://bugzilla.redhat.com/show_bug.cgi?id=726143
* also avoid interrupt storms during dpms.
*/
- u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
-
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL;
- break;
- case AMDGPU_HPD_2:
- dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL;
- break;
- case AMDGPU_HPD_3:
- dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL;
- break;
- case AMDGPU_HPD_4:
- dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL;
- break;
- case AMDGPU_HPD_5:
- dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL;
- break;
- case AMDGPU_HPD_6:
- dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL;
- break;
- default:
- continue;
- }
-
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
- dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
continue;
}
@@ -475,32 +369,18 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
+ u32 tmp;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
- switch (amdgpu_connector->hpd.hpd) {
- case AMDGPU_HPD_1:
- WREG32(mmDC_HPD1_CONTROL, 0);
- break;
- case AMDGPU_HPD_2:
- WREG32(mmDC_HPD2_CONTROL, 0);
- break;
- case AMDGPU_HPD_3:
- WREG32(mmDC_HPD3_CONTROL, 0);
- break;
- case AMDGPU_HPD_4:
- WREG32(mmDC_HPD4_CONTROL, 0);
- break;
- case AMDGPU_HPD_5:
- WREG32(mmDC_HPD5_CONTROL, 0);
- break;
- case AMDGPU_HPD_6:
- WREG32(mmDC_HPD6_CONTROL, 0);
- break;
- default:
- break;
- }
+ if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+ continue;
+
+ tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+ tmp &= ~DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+ WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0);
+
amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
}
}
@@ -2030,7 +1910,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
u32 viewport_w, viewport_h;
int r;
bool bypass_lut = false;
- char *format_name;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -2135,9 +2015,8 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
bypass_lut = true;
break;
default:
- format_name = drm_get_format_name(target_fb->pixel_format);
- DRM_ERROR("Unsupported screen format %s\n", format_name);
- kfree(format_name);
+ DRM_ERROR("Unsupported screen format %s\n",
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
@@ -2465,6 +2344,9 @@ static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc,
struct amdgpu_device *adev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
+ amdgpu_crtc->cursor_x = x;
+ amdgpu_crtc->cursor_y = y;
+
/* avivo cursor are offset into the total surface */
x += crtc->x;
y += crtc->y;
@@ -2481,11 +2363,6 @@ static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc,
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));
-
- amdgpu_crtc->cursor_x = x;
- amdgpu_crtc->cursor_y = y;
return 0;
}
@@ -2511,6 +2388,7 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
int32_t hot_y)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
struct drm_gem_object *obj;
struct amdgpu_bo *aobj;
int ret;
@@ -2549,9 +2427,6 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
return ret;
}
- amdgpu_crtc->cursor_width = width;
- amdgpu_crtc->cursor_height = height;
-
dce_v8_0_lock_cursor(crtc, true);
if (hot_x != amdgpu_crtc->cursor_hot_x ||
@@ -2563,10 +2438,20 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
dce_v8_0_cursor_move_locked(crtc, x, y);
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
amdgpu_crtc->cursor_hot_x = hot_x;
amdgpu_crtc->cursor_hot_y = hot_y;
}
+ if (width != amdgpu_crtc->cursor_width ||
+ height != amdgpu_crtc->cursor_height) {
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (width - 1) << 16 | (height - 1));
+ amdgpu_crtc->cursor_width = width;
+ amdgpu_crtc->cursor_height = height;
+ }
+
dce_v8_0_show_cursor(crtc);
dce_v8_0_lock_cursor(crtc, false);
@@ -2588,6 +2473,7 @@ unpin:
static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct amdgpu_device *adev = crtc->dev->dev_private;
if (amdgpu_crtc->cursor_bo) {
dce_v8_0_lock_cursor(crtc, true);
@@ -2595,6 +2481,10 @@ static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
dce_v8_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
amdgpu_crtc->cursor_y);
+ WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+ (amdgpu_crtc->cursor_width - 1) << 16 |
+ (amdgpu_crtc->cursor_height - 1));
+
dce_v8_0_show_cursor(crtc);
dce_v8_0_lock_cursor(crtc, false);
@@ -3198,42 +3088,23 @@ static int dce_v8_0_set_hpd_interrupt_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
+ u32 dc_hpd_int_cntl;
- switch (type) {
- case AMDGPU_HPD_1:
- dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL;
- break;
- case AMDGPU_HPD_2:
- dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL;
- break;
- case AMDGPU_HPD_3:
- dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL;
- break;
- case AMDGPU_HPD_4:
- dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL;
- break;
- case AMDGPU_HPD_5:
- dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL;
- break;
- case AMDGPU_HPD_6:
- dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL;
- break;
- default:
+ if (type >= adev->mode_info.num_hpd) {
DRM_DEBUG("invalid hdp %d\n", type);
return 0;
}
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
+ dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
+ dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
dc_hpd_int_cntl |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
- WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
break;
default:
break;
@@ -3406,7 +3277,7 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- uint32_t disp_int, mask, int_control, tmp;
+ uint32_t disp_int, mask, tmp;
unsigned hpd;
if (entry->src_data >= adev->mode_info.num_hpd) {
@@ -3417,12 +3288,11 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev,
hpd = entry->src_data;
disp_int = RREG32(interrupt_status_offsets[hpd].reg);
mask = interrupt_status_offsets[hpd].hpd;
- int_control = hpd_int_control_offsets[hpd];
if (disp_int & mask) {
- tmp = RREG32(int_control);
+ tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
- WREG32(int_control, tmp);
+ WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
schedule_work(&adev->hotplug_work);
DRM_DEBUG("IH: HPD%d\n", hpd + 1);
}
@@ -3443,7 +3313,7 @@ static int dce_v8_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs dce_v8_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v8_0_ip_funcs = {
.name = "dce_v8_0",
.early_init = dce_v8_0_early_init,
.late_init = NULL,
@@ -3727,7 +3597,6 @@ static const struct amdgpu_display_funcs dce_v8_0_display_funcs = {
.bandwidth_update = &dce_v8_0_bandwidth_update,
.vblank_get_counter = &dce_v8_0_vblank_get_counter,
.vblank_wait = &dce_v8_0_vblank_wait,
- .is_display_hung = &dce_v8_0_is_display_hung,
.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
.hpd_sense = &dce_v8_0_hpd_sense,
@@ -3773,3 +3642,48 @@ static void dce_v8_0_set_irq_funcs(struct amdgpu_device *adev)
adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
adev->hpd_irq.funcs = &dce_v8_0_hpd_irq_funcs;
}
+
+const struct amdgpu_ip_block_version dce_v8_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 8,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 8,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_2_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 8,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_3_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 8,
+ .minor = 3,
+ .rev = 0,
+ .funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_5_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 8,
+ .minor = 5,
+ .rev = 0,
+ .funcs = &dce_v8_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
index 7d0770c3a49b..13b802dd946a 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
@@ -24,7 +24,11 @@
#ifndef __DCE_V8_0_H__
#define __DCE_V8_0_H__
-extern const struct amd_ip_funcs dce_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_1_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_2_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_3_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_5_ip_block;
void dce_v8_0_disable_dce(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index c2bd9f045532..e4a5a5ac0ff3 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -27,6 +27,9 @@
#include "atom.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
+#ifdef CONFIG_DRM_AMDGPU_SI
+#include "dce_v6_0.h"
+#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "dce_v8_0.h"
#endif
@@ -34,11 +37,13 @@
#include "dce_v11_0.h"
#include "dce_virtual.h"
+#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
+
+
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
-static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry);
+static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
+ int index);
/**
* dce_virtual_vblank_wait - vblank wait asic callback.
@@ -90,15 +95,18 @@ static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
return 0;
}
-static bool dce_virtual_is_display_hung(struct amdgpu_device *adev)
-{
- return false;
-}
-
static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
struct amdgpu_mode_mc_save *save)
{
switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ case CHIP_VERDE:
+ case CHIP_OLAND:
+ dce_v6_0_disable_dce(adev);
+ break;
+#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
@@ -119,6 +127,9 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
dce_v11_0_disable_dce(adev);
break;
case CHIP_TOPAZ:
+#ifdef CONFIG_DRM_AMDGPU_SI
+ case CHIP_HAINAN:
+#endif
/* no DCE */
return;
default:
@@ -195,16 +206,15 @@ static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
switch (mode) {
case DRM_MODE_DPMS_ON:
amdgpu_crtc->enabled = true;
- /* Make sure VBLANK and PFLIP interrupts are still enabled */
+ /* Make sure VBLANK 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_on(dev, amdgpu_crtc->crtc_id);
+ drm_crtc_vblank_on(crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- drm_vblank_off(dev, amdgpu_crtc->crtc_id);
+ drm_crtc_vblank_off(crtc);
amdgpu_crtc->enabled = false;
break;
}
@@ -264,24 +274,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct drm_encoder *encoder;
-
- /* assign the encoder to the amdgpu crtc to avoid repeated lookups later */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- amdgpu_crtc->encoder = encoder;
- amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder);
- break;
- }
- }
- if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) {
- amdgpu_crtc->encoder = NULL;
- amdgpu_crtc->connector = NULL;
- return false;
- }
-
return true;
}
@@ -341,6 +333,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
amdgpu_crtc->encoder = NULL;
amdgpu_crtc->connector = NULL;
+ amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
return 0;
@@ -350,48 +343,121 @@ static int dce_virtual_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->mode_info.vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
dce_virtual_set_display_funcs(adev);
dce_virtual_set_irq_funcs(adev);
- adev->mode_info.num_crtc = 1;
adev->mode_info.num_hpd = 1;
adev->mode_info.num_dig = 1;
return 0;
}
-static bool dce_virtual_get_connector_info(struct amdgpu_device *adev)
+static struct drm_encoder *
+dce_virtual_encoder(struct drm_connector *connector)
{
- struct amdgpu_i2c_bus_rec ddc_bus;
- struct amdgpu_router router;
- struct amdgpu_hpd hpd;
+ int enc_id = connector->encoder_ids[0];
+ struct drm_encoder *encoder;
+ int i;
- /* look up gpio for ddc, hpd */
- ddc_bus.valid = false;
- hpd.hpd = AMDGPU_HPD_NONE;
- /* needed for aux chan transactions */
- ddc_bus.hpd = hpd.hpd;
+ for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+ if (connector->encoder_ids[i] == 0)
+ break;
- memset(&router, 0, sizeof(router));
- router.ddc_valid = false;
- router.cd_valid = false;
- amdgpu_display_add_connector(adev,
- 0,
- ATOM_DEVICE_CRT1_SUPPORT,
- DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus,
- CONNECTOR_OBJECT_ID_VIRTUAL,
- &hpd,
- &router);
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ if (!encoder)
+ continue;
- amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL,
- ATOM_DEVICE_CRT1_SUPPORT,
- 0);
+ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
+ return encoder;
+ }
- amdgpu_link_encoder_connector(adev->ddev);
+ /* pick the first one */
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
+ return NULL;
+}
+
+static int dce_virtual_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode = NULL;
+ unsigned i;
+ static const struct mode_size {
+ int w;
+ int h;
+ } common_modes[17] = {
+ { 640, 480},
+ { 720, 480},
+ { 800, 600},
+ { 848, 480},
+ {1024, 768},
+ {1152, 768},
+ {1280, 720},
+ {1280, 800},
+ {1280, 854},
+ {1280, 960},
+ {1280, 1024},
+ {1440, 900},
+ {1400, 1050},
+ {1680, 1050},
+ {1600, 1200},
+ {1920, 1080},
+ {1920, 1200}
+ };
+
+ for (i = 0; i < 17; i++) {
+ mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+ drm_mode_probed_add(connector, mode);
+ }
- return true;
+ return 0;
+}
+
+static int dce_virtual_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
}
+static int
+dce_virtual_dpms(struct drm_connector *connector, int mode)
+{
+ return 0;
+}
+
+static int
+dce_virtual_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static void dce_virtual_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+ kfree(connector);
+}
+
+static void dce_virtual_force(struct drm_connector *connector)
+{
+ return;
+}
+
+static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
+ .get_modes = dce_virtual_get_modes,
+ .mode_valid = dce_virtual_mode_valid,
+ .best_encoder = dce_virtual_encoder,
+};
+
+static const struct drm_connector_funcs dce_virtual_connector_funcs = {
+ .dpms = dce_virtual_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = dce_virtual_set_property,
+ .destroy = dce_virtual_destroy,
+ .force = dce_virtual_force,
+};
+
static int dce_virtual_sw_init(void *handle)
{
int r, i;
@@ -420,16 +486,16 @@ static int dce_virtual_sw_init(void *handle)
adev->ddev->mode_config.max_width = 16384;
adev->ddev->mode_config.max_height = 16384;
- /* allocate crtcs */
+ /* allocate crtcs, encoders, connectors */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
r = dce_virtual_crtc_init(adev, i);
if (r)
return r;
+ r = dce_virtual_connector_encoder_init(adev, i);
+ if (r)
+ return r;
}
- dce_virtual_get_connector_info(adev);
- amdgpu_print_display_setup(adev->ddev);
-
drm_kms_helper_poll_init(adev->ddev);
adev->mode_info.mode_config_initialized = true;
@@ -496,7 +562,7 @@ static int dce_virtual_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs dce_virtual_ip_funcs = {
+static const struct amd_ip_funcs dce_virtual_ip_funcs = {
.name = "dce_virtual",
.early_init = dce_virtual_early_init,
.late_init = NULL,
@@ -526,8 +592,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
static void
dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
return;
}
@@ -547,10 +613,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
-
- /* set the active encoder to connector routing */
- amdgpu_encoder_set_active_device(encoder);
-
return true;
}
@@ -576,45 +638,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
.destroy = dce_virtual_encoder_destroy,
};
-static void dce_virtual_encoder_add(struct amdgpu_device *adev,
- uint32_t encoder_enum,
- uint32_t supported_device,
- u16 caps)
+static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
+ int index)
{
- struct drm_device *dev = adev->ddev;
struct drm_encoder *encoder;
- struct amdgpu_encoder *amdgpu_encoder;
-
- /* see if we already added it */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- amdgpu_encoder = to_amdgpu_encoder(encoder);
- if (amdgpu_encoder->encoder_enum == encoder_enum) {
- amdgpu_encoder->devices |= supported_device;
- return;
- }
+ struct drm_connector *connector;
+
+ /* add a new encoder */
+ encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
+ if (!encoder)
+ return -ENOMEM;
+ encoder->possible_crtcs = 1 << index;
+ drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
+ connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
+ if (!connector) {
+ kfree(encoder);
+ return -ENOMEM;
}
- /* add a new one */
- amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL);
- if (!amdgpu_encoder)
- return;
+ /* add a new connector */
+ drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+ drm_connector_register(connector);
- encoder = &amdgpu_encoder->base;
- encoder->possible_crtcs = 0x1;
- amdgpu_encoder->enc_priv = NULL;
- amdgpu_encoder->encoder_enum = encoder_enum;
- amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
- amdgpu_encoder->devices = supported_device;
- amdgpu_encoder->rmx_type = RMX_OFF;
- amdgpu_encoder->underscan_type = UNDERSCAN_OFF;
- amdgpu_encoder->is_ext_encoder = false;
- amdgpu_encoder->caps = caps;
-
- drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs,
- DRM_MODE_ENCODER_VIRTUAL, NULL);
- drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
- DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id);
+ /* link them */
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return 0;
}
static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
@@ -622,7 +679,6 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
.bandwidth_update = &dce_virtual_bandwidth_update,
.vblank_get_counter = &dce_virtual_vblank_get_counter,
.vblank_wait = &dce_virtual_vblank_wait,
- .is_display_hung = &dce_virtual_is_display_hung,
.backlight_set_level = NULL,
.backlight_get_level = NULL,
.hpd_sense = &dce_virtual_hpd_sense,
@@ -630,8 +686,8 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
.page_flip = &dce_virtual_page_flip,
.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
- .add_encoder = &dce_virtual_encoder_add,
- .add_connector = &amdgpu_connector_add,
+ .add_encoder = NULL,
+ .add_connector = NULL,
.stop_mc_access = &dce_virtual_stop_mc_access,
.resume_mc_access = &dce_virtual_resume_mc_access,
};
@@ -642,107 +698,13 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
adev->mode_info.funcs = &dce_virtual_display_funcs;
}
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
-{
- struct amdgpu_mode_info *mode_info = container_of(vblank_timer, struct amdgpu_mode_info ,vblank_timer);
- struct amdgpu_device *adev = container_of(mode_info, struct amdgpu_device ,mode_info);
- unsigned crtc = 0;
- drm_handle_vblank(adev->ddev, crtc);
- dce_virtual_pageflip_irq(adev, NULL, NULL);
- hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
- return HRTIMER_NORESTART;
-}
-
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
- int crtc,
- enum amdgpu_interrupt_state state)
-{
- if (crtc >= adev->mode_info.num_crtc) {
- DRM_DEBUG("invalid crtc %d\n", crtc);
- return;
- }
-
- if (state && !adev->mode_info.vsync_timer_enabled) {
- DRM_DEBUG("Enable software vsync timer\n");
- hrtimer_init(&adev->mode_info.vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtimer_set_expires(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD));
- adev->mode_info.vblank_timer.function = dce_virtual_vblank_timer_handle;
- hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
- } else if (!state && adev->mode_info.vsync_timer_enabled) {
- DRM_DEBUG("Disable software vsync timer\n");
- hrtimer_cancel(&adev->mode_info.vblank_timer);
- }
-
- adev->mode_info.vsync_timer_enabled = state;
- DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
-}
-
-
-static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- unsigned type,
- enum amdgpu_interrupt_state state)
-{
- switch (type) {
- case AMDGPU_CRTC_IRQ_VBLANK1:
- dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state);
- break;
- default:
- break;
- }
- return 0;
-}
-
-static void dce_virtual_crtc_vblank_int_ack(struct amdgpu_device *adev,
- int crtc)
-{
- if (crtc >= adev->mode_info.num_crtc) {
- DRM_DEBUG("invalid crtc %d\n", crtc);
- return;
- }
-}
-
-static int dce_virtual_crtc_irq(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry)
-{
- unsigned crtc = 0;
- unsigned irq_type = AMDGPU_CRTC_IRQ_VBLANK1;
-
- dce_virtual_crtc_vblank_int_ack(adev, crtc);
-
- if (amdgpu_irq_enabled(adev, source, irq_type)) {
- drm_handle_vblank(adev->ddev, crtc);
- }
- dce_virtual_pageflip_irq(adev, NULL, NULL);
- DRM_DEBUG("IH: D%d vblank\n", crtc + 1);
- return 0;
-}
-
-static int dce_virtual_set_pageflip_irq_state(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src,
- unsigned type,
- enum amdgpu_interrupt_state state)
-{
- if (type >= adev->mode_info.num_crtc) {
- DRM_ERROR("invalid pageflip crtc %d\n", type);
- return -EINVAL;
- }
- DRM_DEBUG("[FM]set pageflip irq type %d state %d\n", type, state);
-
- return 0;
-}
-
-static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry)
+static int dce_virtual_pageflip(struct amdgpu_device *adev,
+ unsigned crtc_id)
{
unsigned long flags;
- unsigned crtc_id = 0;
struct amdgpu_crtc *amdgpu_crtc;
struct amdgpu_flip_work *works;
- crtc_id = 0;
amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
if (crtc_id >= adev->mode_info.num_crtc) {
@@ -781,22 +743,79 @@ static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
return 0;
}
+static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
+{
+ struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
+ struct amdgpu_crtc, vblank_timer);
+ struct drm_device *ddev = amdgpu_crtc->base.dev;
+ struct amdgpu_device *adev = ddev->dev_private;
+
+ drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
+ dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
+ hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD),
+ HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+
+static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
+ int crtc,
+ enum amdgpu_interrupt_state state)
+{
+ if (crtc >= adev->mode_info.num_crtc) {
+ DRM_DEBUG("invalid crtc %d\n", crtc);
+ return;
+ }
+
+ if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
+ DRM_DEBUG("Enable software vsync timer\n");
+ hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
+ ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD));
+ adev->mode_info.crtcs[crtc]->vblank_timer.function =
+ dce_virtual_vblank_timer_handle;
+ hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
+ ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
+ } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
+ DRM_DEBUG("Disable software vsync timer\n");
+ hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
+ }
+
+ adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
+ DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
+}
+
+
+static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ if (type > AMDGPU_CRTC_IRQ_VBLANK6)
+ return -EINVAL;
+
+ dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
+
+ return 0;
+}
+
static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
.set = dce_virtual_set_crtc_irq_state,
- .process = dce_virtual_crtc_irq,
-};
-
-static const struct amdgpu_irq_src_funcs dce_virtual_pageflip_irq_funcs = {
- .set = dce_virtual_set_pageflip_irq_state,
- .process = dce_virtual_pageflip_irq,
+ .process = NULL,
};
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
{
adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
-
- adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
- adev->pageflip_irq.funcs = &dce_virtual_pageflip_irq_funcs;
}
+const struct amdgpu_ip_block_version dce_virtual_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &dce_virtual_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
index e239243f6ebc..ed422012c8c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
@@ -24,8 +24,7 @@
#ifndef __DCE_VIRTUAL_H__
#define __DCE_VIRTUAL_H__
-extern const struct amd_ip_funcs dce_virtual_ip_funcs;
-#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
+extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 40abb6b81c09..558640aee15a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -26,15 +26,18 @@
#include "amdgpu_gfx.h"
#include "amdgpu_ucode.h"
#include "si/clearstate_si.h"
-#include "si/sid.h"
-
-#define GFX6_NUM_GFX_RINGS 1
-#define GFX6_NUM_COMPUTE_RINGS 2
-#define STATIC_PER_CU_PG_ENABLE (1 << 3)
-#define DYN_PER_CU_PG_ENABLE (1 << 2)
-#define RLC_SAVE_AND_RESTORE_STARTING_OFFSET 0x90
-#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET 0x3D
-
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gca/gfx_6_0_d.h"
+#include "gca/gfx_6_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "gca/gfx_7_2_enum.h"
+#include "si_enums.h"
static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev);
static void gfx_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -70,6 +73,15 @@ static void gfx_v6_0_get_csb_buffer(struct amdgpu_device *adev, volatile u32 *bu
//static void gfx_v6_0_init_cp_pg_table(struct amdgpu_device *adev);
static void gfx_v6_0_init_pg(struct amdgpu_device *adev);
+#define ARRAY_MODE(x) ((x) << GB_TILE_MODE0__ARRAY_MODE__SHIFT)
+#define PIPE_CONFIG(x) ((x) << GB_TILE_MODE0__PIPE_CONFIG__SHIFT)
+#define TILE_SPLIT(x) ((x) << GB_TILE_MODE0__TILE_SPLIT__SHIFT)
+#define MICRO_TILE_MODE(x) ((x) << 0)
+#define SAMPLE_SPLIT(x) ((x) << GB_TILE_MODE0__SAMPLE_SPLIT__SHIFT)
+#define BANK_WIDTH(x) ((x) << 14)
+#define BANK_HEIGHT(x) ((x) << 16)
+#define MACRO_TILE_ASPECT(x) ((x) << 18)
+#define NUM_BANKS(x) ((x) << 20)
static const u32 verde_rlc_save_restore_register_list[] =
{
@@ -400,8 +412,8 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
}
if (adev->asic_type == CHIP_VERDE ||
- adev->asic_type == CHIP_OLAND ||
- adev->asic_type == CHIP_HAINAN) {
+ adev->asic_type == CHIP_OLAND ||
+ adev->asic_type == CHIP_HAINAN) {
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
switch (reg_offset) {
case 0:
@@ -414,7 +426,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 1:
+ case 1:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -434,7 +446,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 3:
+ case 3:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -444,7 +456,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 4:
+ case 4:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -454,7 +466,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 5:
+ case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -464,7 +476,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 6:
+ case 6:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -474,7 +486,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 7:
+ case 7:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -484,7 +496,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 8:
+ case 8:
gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -494,7 +506,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 9:
+ case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -504,7 +516,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 10:
+ case 10:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -514,7 +526,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 11:
+ case 11:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -524,7 +536,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 12:
+ case 12:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -534,7 +546,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 13:
+ case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -544,7 +556,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 14:
+ case 14:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -554,7 +566,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 15:
+ case 15:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -564,7 +576,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 16:
+ case 16:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -574,7 +586,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 17:
+ case 17:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P4_8x16) |
@@ -584,7 +596,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 21:
+ case 21:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
@@ -594,7 +606,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 22:
+ case 22:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
@@ -604,7 +616,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
break;
- case 23:
+ case 23:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
@@ -614,7 +626,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 24:
+ case 24:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
@@ -624,7 +636,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
break;
- case 25:
+ case 25:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
@@ -639,7 +651,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
break;
}
adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
- WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden);
+ WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
}
} else if ((adev->asic_type == CHIP_TAHITI) || (adev->asic_type == CHIP_PITCAIRN)) {
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
@@ -879,7 +891,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
break;
}
adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
- WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden);
+ WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
}
} else{
@@ -894,19 +906,23 @@ static void gfx_v6_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
u32 data;
if (instance == 0xffffffff)
- data = INSTANCE_BROADCAST_WRITES;
+ data = REG_SET_FIELD(0, GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES, 1);
else
- data = INSTANCE_INDEX(instance);
+ data = REG_SET_FIELD(0, GRBM_GFX_INDEX, INSTANCE_INDEX, instance);
if ((se_num == 0xffffffff) && (sh_num == 0xffffffff))
- data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
+ data |= GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK |
+ GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK;
else if (se_num == 0xffffffff)
- data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num);
+ data |= GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK |
+ (sh_num << GRBM_GFX_INDEX__SH_INDEX__SHIFT);
else if (sh_num == 0xffffffff)
- data |= SH_BROADCAST_WRITES | SE_INDEX(se_num);
+ data |= GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK |
+ (se_num << GRBM_GFX_INDEX__SE_INDEX__SHIFT);
else
- data |= SH_INDEX(sh_num) | SE_INDEX(se_num);
- WREG32(GRBM_GFX_INDEX, data);
+ data |= (sh_num << GRBM_GFX_INDEX__SH_INDEX__SHIFT) |
+ (se_num << GRBM_GFX_INDEX__SE_INDEX__SHIFT);
+ WREG32(mmGRBM_GFX_INDEX, data);
}
static u32 gfx_v6_0_create_bitmask(u32 bit_width)
@@ -920,11 +936,11 @@ static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev,
{
u32 data, mask;
- data = RREG32(CC_RB_BACKEND_DISABLE);
- data &= BACKEND_DISABLE_MASK;
- data |= RREG32(GC_USER_RB_BACKEND_DISABLE);
+ data = RREG32(mmCC_RB_BACKEND_DISABLE);
+ data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK;
+ data |= RREG32(mmGC_USER_RB_BACKEND_DISABLE);
- data >>= BACKEND_DISABLE_SHIFT;
+ data >>= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT;
mask = gfx_v6_0_create_bitmask(max_rb_num_per_se / sh_per_se);
@@ -936,14 +952,23 @@ static void gfx_v6_0_raster_config(struct amdgpu_device *adev, u32 *rconf)
switch (adev->asic_type) {
case CHIP_TAHITI:
case CHIP_PITCAIRN:
- *rconf |= RB_XSEL2(2) | RB_XSEL | PKR_MAP(2) | PKR_YSEL(1) |
- SE_MAP(2) | SE_XSEL(2) | SE_YSEL(2);
+ *rconf |=
+ (2 << PA_SC_RASTER_CONFIG__RB_XSEL2__SHIFT) |
+ (1 << PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT) |
+ (2 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT) |
+ (1 << PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT) |
+ (2 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT) |
+ (2 << PA_SC_RASTER_CONFIG__SE_XSEL__SHIFT) |
+ (2 << PA_SC_RASTER_CONFIG__SE_YSEL__SHIFT);
break;
case CHIP_VERDE:
- *rconf |= RB_XSEL | PKR_MAP(2) | PKR_YSEL(1);
+ *rconf |=
+ (1 << PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT) |
+ (2 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT) |
+ (1 << PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT);
break;
case CHIP_OLAND:
- *rconf |= RB_YSEL;
+ *rconf |= (1 << PA_SC_RASTER_CONFIG__RB_YSEL__SHIFT);
break;
case CHIP_HAINAN:
*rconf |= 0x0;
@@ -981,24 +1006,24 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
int idx = (se / 2) * 2;
if ((num_se > 1) && (!se_mask[idx] || !se_mask[idx + 1])) {
- raster_config_se &= ~SE_MAP_MASK;
+ raster_config_se &= ~PA_SC_RASTER_CONFIG__SE_MAP_MASK;
if (!se_mask[idx]) {
- raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_3);
+ raster_config_se |= RASTER_CONFIG_SE_MAP_3 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT;
} else {
- raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_0);
+ raster_config_se |= RASTER_CONFIG_SE_MAP_0 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT;
}
}
pkr0_mask &= rb_mask;
pkr1_mask &= rb_mask;
if (rb_per_se > 2 && (!pkr0_mask || !pkr1_mask)) {
- raster_config_se &= ~PKR_MAP_MASK;
+ raster_config_se &= ~PA_SC_RASTER_CONFIG__PKR_MAP_MASK;
if (!pkr0_mask) {
- raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_3);
+ raster_config_se |= RASTER_CONFIG_PKR_MAP_3 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT;
} else {
- raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_0);
+ raster_config_se |= RASTER_CONFIG_PKR_MAP_0 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT;
}
}
@@ -1009,14 +1034,14 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
rb0_mask &= rb_mask;
rb1_mask &= rb_mask;
if (!rb0_mask || !rb1_mask) {
- raster_config_se &= ~RB_MAP_PKR0_MASK;
+ raster_config_se &= ~PA_SC_RASTER_CONFIG__RB_MAP_PKR0_MASK;
if (!rb0_mask) {
raster_config_se |=
- RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_3);
+ RASTER_CONFIG_RB_MAP_3 << PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT;
} else {
raster_config_se |=
- RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_0);
+ RASTER_CONFIG_RB_MAP_0 << PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT;
}
}
@@ -1026,14 +1051,14 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
rb0_mask &= rb_mask;
rb1_mask &= rb_mask;
if (!rb0_mask || !rb1_mask) {
- raster_config_se &= ~RB_MAP_PKR1_MASK;
+ raster_config_se &= ~PA_SC_RASTER_CONFIG__RB_MAP_PKR1_MASK;
if (!rb0_mask) {
raster_config_se |=
- RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_3);
+ RASTER_CONFIG_RB_MAP_3 << PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT;
} else {
raster_config_se |=
- RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_0);
+ RASTER_CONFIG_RB_MAP_0 << PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT;
}
}
}
@@ -1041,7 +1066,7 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
/* GRBM_GFX_INDEX has a different offset on SI */
gfx_v6_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
- WREG32(PA_SC_RASTER_CONFIG, raster_config_se);
+ WREG32(mmPA_SC_RASTER_CONFIG, raster_config_se);
}
/* GRBM_GFX_INDEX has a different offset on SI */
@@ -1063,7 +1088,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
for (j = 0; j < sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
data = gfx_v6_0_get_rb_disabled(adev, max_rb_num_per_se, sh_per_se);
- disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
+ disabled_rbs |= data << ((i * sh_per_se + j) * 2);
}
}
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
@@ -1105,7 +1130,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
if (!adev->gfx.config.backend_enable_mask ||
adev->gfx.config.num_rbs >= num_rb_pipes)
- WREG32(PA_SC_RASTER_CONFIG, data);
+ WREG32(mmPA_SC_RASTER_CONFIG, data);
else
gfx_v6_0_write_harvested_raster_configs(adev, data,
adev->gfx.config.backend_enable_mask,
@@ -1124,11 +1149,11 @@ static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev, u32 cu_per_sh)
{
u32 data, mask;
- data = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
- data &= INACTIVE_CUS_MASK;
- data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG);
+ data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
+ data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
+ data |= RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
- data >>= INACTIVE_CUS_SHIFT;
+ data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
mask = gfx_v6_0_create_bitmask(cu_per_sh);
@@ -1148,7 +1173,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev,
for (i = 0; i < se_num; i++) {
for (j = 0; j < sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
- data = RREG32(SPI_STATIC_THREAD_MGMT_3);
+ data = RREG32(mmSPI_STATIC_THREAD_MGMT_3);
active_cu = gfx_v6_0_get_cu_enabled(adev, cu_per_sh);
mask = 1;
@@ -1156,7 +1181,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev,
mask <<= k;
if (active_cu & mask) {
data &= ~mask;
- WREG32(SPI_STATIC_THREAD_MGMT_3, data);
+ WREG32(mmSPI_STATIC_THREAD_MGMT_3, data);
break;
}
}
@@ -1209,7 +1234,6 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN;
break;
-
case CHIP_VERDE:
adev->gfx.config.max_shader_engines = 1;
adev->gfx.config.max_tile_pipes = 4;
@@ -1266,18 +1290,18 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
break;
}
- WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
- WREG32(SRBM_INT_CNTL, 1);
- WREG32(SRBM_INT_ACK, 1);
+ WREG32(mmGRBM_CNTL, (0xff << GRBM_CNTL__READ_TIMEOUT__SHIFT));
+ WREG32(mmSRBM_INT_CNTL, 1);
+ WREG32(mmSRBM_INT_ACK, 1);
- WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
+ WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
- mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
- mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+ mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
+ mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes;
adev->gfx.config.mem_max_burst_length_bytes = 256;
- tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
+ tmp = (mc_arb_ramcfg & MC_ARB_RAMCFG__NOOFCOLS_MASK) >> MC_ARB_RAMCFG__NOOFCOLS__SHIFT;
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;
@@ -1285,32 +1309,33 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
adev->gfx.config.num_gpus = 1;
adev->gfx.config.multi_gpu_tile_size = 64;
- gb_addr_config &= ~ROW_SIZE_MASK;
+ gb_addr_config &= ~GB_ADDR_CONFIG__ROW_SIZE_MASK;
switch (adev->gfx.config.mem_row_size_in_kb) {
case 1:
default:
- gb_addr_config |= ROW_SIZE(0);
+ gb_addr_config |= 0 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
break;
case 2:
- gb_addr_config |= ROW_SIZE(1);
+ gb_addr_config |= 1 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
break;
case 4:
- gb_addr_config |= ROW_SIZE(2);
+ gb_addr_config |= 2 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
break;
}
adev->gfx.config.gb_addr_config = gb_addr_config;
- WREG32(GB_ADDR_CONFIG, gb_addr_config);
- WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
- WREG32(DMIF_ADDR_CALC, gb_addr_config);
- WREG32(HDP_ADDR_CONFIG, gb_addr_config);
- WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
- WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
+ WREG32(mmGB_ADDR_CONFIG, gb_addr_config);
+ WREG32(mmDMIF_ADDR_CONFIG, gb_addr_config);
+ WREG32(mmDMIF_ADDR_CALC, gb_addr_config);
+ WREG32(mmHDP_ADDR_CONFIG, gb_addr_config);
+ WREG32(mmDMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
+ WREG32(mmDMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
+
#if 0
if (adev->has_uvd) {
- WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
- WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
- WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
+ 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);
}
#endif
gfx_v6_0_tiling_mode_table_init(adev);
@@ -1325,45 +1350,48 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
gfx_v6_0_get_cu_info(adev);
- WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
- ROQ_IB2_START(0x2b)));
- WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
+ WREG32(mmCP_QUEUE_THRESHOLDS, ((0x16 << CP_QUEUE_THRESHOLDS__ROQ_IB1_START__SHIFT) |
+ (0x2b << CP_QUEUE_THRESHOLDS__ROQ_IB2_START__SHIFT)));
+ WREG32(mmCP_MEQ_THRESHOLDS, (0x30 << CP_MEQ_THRESHOLDS__MEQ1_START__SHIFT) |
+ (0x60 << CP_MEQ_THRESHOLDS__MEQ2_START__SHIFT));
- sx_debug_1 = RREG32(SX_DEBUG_1);
- WREG32(SX_DEBUG_1, sx_debug_1);
+ sx_debug_1 = RREG32(mmSX_DEBUG_1);
+ WREG32(mmSX_DEBUG_1, sx_debug_1);
- WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4));
+ WREG32(mmSPI_CONFIG_CNTL_1, (4 << SPI_CONFIG_CNTL_1__VTX_DONE_DELAY__SHIFT));
- WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_frontend) |
- SC_BACKEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_backend) |
- SC_HIZ_TILE_FIFO_SIZE(adev->gfx.config.sc_hiz_tile_fifo_size) |
- SC_EARLYZ_TILE_FIFO_SIZE(adev->gfx.config.sc_earlyz_tile_fifo_size)));
+ WREG32(mmPA_SC_FIFO_SIZE, ((adev->gfx.config.sc_prim_fifo_size_frontend << PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT) |
+ (adev->gfx.config.sc_prim_fifo_size_backend << PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT) |
+ (adev->gfx.config.sc_hiz_tile_fifo_size << PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT) |
+ (adev->gfx.config.sc_earlyz_tile_fifo_size << PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT)));
- WREG32(VGT_NUM_INSTANCES, 1);
- WREG32(CP_PERFMON_CNTL, 0);
- WREG32(SQ_CONFIG, 0);
- WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
- FORCE_EOV_MAX_REZ_CNT(255)));
+ WREG32(mmVGT_NUM_INSTANCES, 1);
+ WREG32(mmCP_PERFMON_CNTL, 0);
+ WREG32(mmSQ_CONFIG, 0);
+ WREG32(mmPA_SC_FORCE_EOV_MAX_CNTS, ((4095 << PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT__SHIFT) |
+ (255 << PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT__SHIFT)));
- WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
- AUTO_INVLD_EN(ES_AND_GS_AUTO));
+ WREG32(mmVGT_CACHE_INVALIDATION,
+ (VC_AND_TC << VGT_CACHE_INVALIDATION__CACHE_INVALIDATION__SHIFT) |
+ (ES_AND_GS_AUTO << VGT_CACHE_INVALIDATION__AUTO_INVLD_EN__SHIFT));
- WREG32(VGT_GS_VERTEX_REUSE, 16);
- WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+ WREG32(mmVGT_GS_VERTEX_REUSE, 16);
+ WREG32(mmPA_SC_LINE_STIPPLE_STATE, 0);
- WREG32(CB_PERFCOUNTER0_SELECT0, 0);
- WREG32(CB_PERFCOUNTER0_SELECT1, 0);
- WREG32(CB_PERFCOUNTER1_SELECT0, 0);
- WREG32(CB_PERFCOUNTER1_SELECT1, 0);
- WREG32(CB_PERFCOUNTER2_SELECT0, 0);
- WREG32(CB_PERFCOUNTER2_SELECT1, 0);
- WREG32(CB_PERFCOUNTER3_SELECT0, 0);
- WREG32(CB_PERFCOUNTER3_SELECT1, 0);
+ WREG32(mmCB_PERFCOUNTER0_SELECT0, 0);
+ WREG32(mmCB_PERFCOUNTER0_SELECT1, 0);
+ WREG32(mmCB_PERFCOUNTER1_SELECT0, 0);
+ WREG32(mmCB_PERFCOUNTER1_SELECT1, 0);
+ WREG32(mmCB_PERFCOUNTER2_SELECT0, 0);
+ WREG32(mmCB_PERFCOUNTER2_SELECT1, 0);
+ WREG32(mmCB_PERFCOUNTER3_SELECT0, 0);
+ WREG32(mmCB_PERFCOUNTER3_SELECT1, 0);
- hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
- WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+ hdp_host_path_cntl = RREG32(mmHDP_HOST_PATH_CNTL);
+ WREG32(mmHDP_HOST_PATH_CNTL, hdp_host_path_cntl);
- WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
+ WREG32(mmPA_CL_ENHANCE, PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK |
+ (3 << PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT));
udelay(50);
}
@@ -1374,7 +1402,7 @@ static void gfx_v6_0_scratch_init(struct amdgpu_device *adev)
int i;
adev->gfx.scratch.num_reg = 7;
- adev->gfx.scratch.reg_base = SCRATCH_REG0;
+ adev->gfx.scratch.reg_base = mmSCRATCH_REG0;
for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
adev->gfx.scratch.free[i] = true;
adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i;
@@ -1430,11 +1458,18 @@ static void gfx_v6_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
WRITE_DATA_DST_SEL(0)));
- amdgpu_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL);
+ amdgpu_ring_write(ring, mmHDP_MEM_COHERENCY_FLUSH_CNTL);
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, 0x1);
}
+static void gfx_v6_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+ amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+ EVENT_INDEX(0));
+}
+
/**
* gfx_v6_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
*
@@ -1448,7 +1483,7 @@ static void gfx_v6_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
WRITE_DATA_DST_SEL(0)));
- amdgpu_ring_write(ring, HDP_DEBUG0);
+ amdgpu_ring_write(ring, mmHDP_DEBUG0);
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, 0x1);
}
@@ -1460,7 +1495,7 @@ static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
/* flush read cache over gart */
amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
- amdgpu_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START));
+ amdgpu_ring_write(ring, (mmCP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START));
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
amdgpu_ring_write(ring, PACKET3_TCL1_ACTION_ENA |
@@ -1475,7 +1510,8 @@ static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
amdgpu_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5));
amdgpu_ring_write(ring, addr & 0xfffffffc);
amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
- DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
+ ((write64bit ? 2 : 1) << CP_EOP_DONE_DATA_CNTL__DATA_SEL__SHIFT) |
+ ((int_sel ? 2 : 0) << CP_EOP_DONE_DATA_CNTL__INT_SEL__SHIFT));
amdgpu_ring_write(ring, lower_32_bits(seq));
amdgpu_ring_write(ring, upper_32_bits(seq));
}
@@ -1522,7 +1558,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
uint32_t scratch;
uint32_t tmp = 0;
long r;
@@ -1548,7 +1584,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err2;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -1569,7 +1605,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
err2:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err1:
amdgpu_gfx_scratch_free(adev, scratch);
return r;
@@ -1578,11 +1614,13 @@ err1:
static void gfx_v6_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
{
int i;
- if (enable)
- WREG32(CP_ME_CNTL, 0);
- else {
- WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
- WREG32(SCRATCH_UMSK, 0);
+ if (enable) {
+ WREG32(mmCP_ME_CNTL, 0);
+ } else {
+ WREG32(mmCP_ME_CNTL, (CP_ME_CNTL__ME_HALT_MASK |
+ CP_ME_CNTL__PFP_HALT_MASK |
+ CP_ME_CNTL__CE_HALT_MASK));
+ WREG32(mmSCRATCH_UMSK, 0);
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].ready = false;
for (i = 0; i < adev->gfx.num_compute_rings; i++)
@@ -1616,34 +1654,33 @@ static int gfx_v6_0_cp_gfx_load_microcode(struct amdgpu_device *adev)
fw_data = (const __le32 *)
(adev->gfx.pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
- WREG32(CP_PFP_UCODE_ADDR, 0);
+ WREG32(mmCP_PFP_UCODE_ADDR, 0);
for (i = 0; i < fw_size; i++)
- WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32(CP_PFP_UCODE_ADDR, 0);
+ WREG32(mmCP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(mmCP_PFP_UCODE_ADDR, 0);
/* CE */
fw_data = (const __le32 *)
(adev->gfx.ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
- WREG32(CP_CE_UCODE_ADDR, 0);
+ WREG32(mmCP_CE_UCODE_ADDR, 0);
for (i = 0; i < fw_size; i++)
- WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32(CP_CE_UCODE_ADDR, 0);
+ WREG32(mmCP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(mmCP_CE_UCODE_ADDR, 0);
/* ME */
fw_data = (const __be32 *)
(adev->gfx.me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
- WREG32(CP_ME_RAM_WADDR, 0);
+ WREG32(mmCP_ME_RAM_WADDR, 0);
for (i = 0; i < fw_size; i++)
- WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
- WREG32(CP_ME_RAM_WADDR, 0);
+ WREG32(mmCP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+ WREG32(mmCP_ME_RAM_WADDR, 0);
-
- WREG32(CP_PFP_UCODE_ADDR, 0);
- WREG32(CP_CE_UCODE_ADDR, 0);
- WREG32(CP_ME_RAM_WADDR, 0);
- WREG32(CP_ME_RAM_RADDR, 0);
+ WREG32(mmCP_PFP_UCODE_ADDR, 0);
+ WREG32(mmCP_CE_UCODE_ADDR, 0);
+ WREG32(mmCP_ME_RAM_WADDR, 0);
+ WREG32(mmCP_ME_RAM_RADDR, 0);
return 0;
}
@@ -1720,14 +1757,14 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
int r;
u64 rptr_addr;
- WREG32(CP_SEM_WAIT_TIMER, 0x0);
- WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
+ WREG32(mmCP_SEM_WAIT_TIMER, 0x0);
+ WREG32(mmCP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */
- WREG32(CP_RB_WPTR_DELAY, 0);
+ WREG32(mmCP_RB_WPTR_DELAY, 0);
- WREG32(CP_DEBUG, 0);
- WREG32(SCRATCH_ADDR, 0);
+ WREG32(mmCP_DEBUG, 0);
+ WREG32(mmSCRATCH_ADDR, 0);
/* ring 0 - compute and gfx */
/* Set ring buffer size */
@@ -1738,24 +1775,24 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
#ifdef __BIG_ENDIAN
tmp |= BUF_SWAP_32BIT;
#endif
- WREG32(CP_RB0_CNTL, tmp);
+ WREG32(mmCP_RB0_CNTL, tmp);
/* Initialize the ring buffer's read and write pointers */
- WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
+ WREG32(mmCP_RB0_CNTL, tmp | CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK);
ring->wptr = 0;
- WREG32(CP_RB0_WPTR, ring->wptr);
+ WREG32(mmCP_RB0_WPTR, ring->wptr);
/* set the wb address whether it's enabled or not */
rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
- WREG32(CP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
- WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+ WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
+ WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
- WREG32(SCRATCH_UMSK, 0);
+ WREG32(mmSCRATCH_UMSK, 0);
mdelay(1);
- WREG32(CP_RB0_CNTL, tmp);
+ WREG32(mmCP_RB0_CNTL, tmp);
- WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
+ WREG32(mmCP_RB0_BASE, ring->gpu_addr >> 8);
/* start the rings */
gfx_v6_0_cp_gfx_start(adev);
@@ -1779,11 +1816,11 @@ static u32 gfx_v6_0_ring_get_wptr(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
if (ring == &adev->gfx.gfx_ring[0])
- return RREG32(CP_RB0_WPTR);
+ return RREG32(mmCP_RB0_WPTR);
else if (ring == &adev->gfx.compute_ring[0])
- return RREG32(CP_RB1_WPTR);
+ return RREG32(mmCP_RB1_WPTR);
else if (ring == &adev->gfx.compute_ring[1])
- return RREG32(CP_RB2_WPTR);
+ return RREG32(mmCP_RB2_WPTR);
else
BUG();
}
@@ -1792,8 +1829,8 @@ static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- WREG32(CP_RB0_WPTR, ring->wptr);
- (void)RREG32(CP_RB0_WPTR);
+ WREG32(mmCP_RB0_WPTR, ring->wptr);
+ (void)RREG32(mmCP_RB0_WPTR);
}
static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
@@ -1801,11 +1838,11 @@ static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
if (ring == &adev->gfx.compute_ring[0]) {
- WREG32(CP_RB1_WPTR, ring->wptr);
- (void)RREG32(CP_RB1_WPTR);
+ WREG32(mmCP_RB1_WPTR, ring->wptr);
+ (void)RREG32(mmCP_RB1_WPTR);
} else if (ring == &adev->gfx.compute_ring[1]) {
- WREG32(CP_RB2_WPTR, ring->wptr);
- (void)RREG32(CP_RB2_WPTR);
+ WREG32(mmCP_RB2_WPTR, ring->wptr);
+ (void)RREG32(mmCP_RB2_WPTR);
} else {
BUG();
}
@@ -1817,7 +1854,7 @@ static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
u32 tmp;
u32 rb_bufsz;
- int r;
+ int i, r;
u64 rptr_addr;
/* ring1 - compute only */
@@ -1829,19 +1866,19 @@ static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev)
#ifdef __BIG_ENDIAN
tmp |= BUF_SWAP_32BIT;
#endif
- WREG32(CP_RB1_CNTL, tmp);
+ WREG32(mmCP_RB1_CNTL, tmp);
- WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
+ WREG32(mmCP_RB1_CNTL, tmp | CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK);
ring->wptr = 0;
- WREG32(CP_RB1_WPTR, ring->wptr);
+ WREG32(mmCP_RB1_WPTR, ring->wptr);
rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
- WREG32(CP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
- WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+ WREG32(mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
+ WREG32(mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
mdelay(1);
- WREG32(CP_RB1_CNTL, tmp);
- WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
+ WREG32(mmCP_RB1_CNTL, tmp);
+ WREG32(mmCP_RB1_BASE, ring->gpu_addr >> 8);
ring = &adev->gfx.compute_ring[1];
rb_bufsz = order_base_2(ring->ring_size / 8);
@@ -1849,32 +1886,27 @@ static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev)
#ifdef __BIG_ENDIAN
tmp |= BUF_SWAP_32BIT;
#endif
- WREG32(CP_RB2_CNTL, tmp);
+ WREG32(mmCP_RB2_CNTL, tmp);
- WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
+ WREG32(mmCP_RB2_CNTL, tmp | CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK);
ring->wptr = 0;
- WREG32(CP_RB2_WPTR, ring->wptr);
+ WREG32(mmCP_RB2_WPTR, ring->wptr);
rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
- WREG32(CP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
- WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+ WREG32(mmCP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
+ WREG32(mmCP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
mdelay(1);
- WREG32(CP_RB2_CNTL, tmp);
- WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
+ WREG32(mmCP_RB2_CNTL, tmp);
+ WREG32(mmCP_RB2_BASE, ring->gpu_addr >> 8);
- adev->gfx.compute_ring[0].ready = true;
- adev->gfx.compute_ring[1].ready = true;
+ adev->gfx.compute_ring[0].ready = false;
+ adev->gfx.compute_ring[1].ready = false;
- r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[0]);
- if (r) {
- adev->gfx.compute_ring[0].ready = false;
- return r;
- }
-
- r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[1]);
- if (r) {
- adev->gfx.compute_ring[1].ready = false;
- return r;
+ for (i = 0; i < 2; i++) {
+ r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[i]);
+ if (r)
+ return r;
+ adev->gfx.compute_ring[i].ready = true;
}
return 0;
@@ -1892,24 +1924,26 @@ static int gfx_v6_0_cp_load_microcode(struct amdgpu_device *adev)
static void gfx_v6_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
bool enable)
-{
- u32 tmp = RREG32(CP_INT_CNTL_RING0);
+{
+ u32 tmp = RREG32(mmCP_INT_CNTL_RING0);
u32 mask;
int i;
if (enable)
- tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+ tmp |= (CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK |
+ CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK);
else
- tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
- WREG32(CP_INT_CNTL_RING0, tmp);
+ tmp &= ~(CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK |
+ CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK);
+ WREG32(mmCP_INT_CNTL_RING0, tmp);
if (!enable) {
/* read a gfx register */
- tmp = RREG32(DB_DEPTH_INFO);
+ tmp = RREG32(mmDB_DEPTH_INFO);
mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS;
for (i = 0; i < adev->usec_timeout; i++) {
- if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
+ if ((RREG32(mmRLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
break;
udelay(1);
}
@@ -1940,7 +1974,7 @@ static int gfx_v6_0_cp_resume(struct amdgpu_device *adev)
static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
uint32_t seq = ring->fence_drv.sync_seq;
uint64_t addr = ring->fence_drv.gpu_addr;
@@ -1966,16 +2000,16 @@ static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
unsigned vm_id, uint64_t pd_addr)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
/* write new base address */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
WRITE_DATA_DST_SEL(0)));
if (vm_id < 8) {
- amdgpu_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id ));
+ amdgpu_ring_write(ring, (mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id ));
} else {
- amdgpu_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8)));
+ amdgpu_ring_write(ring, (mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8)));
}
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, pd_addr >> 12);
@@ -1984,7 +2018,7 @@ static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
WRITE_DATA_DST_SEL(0)));
- amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST);
+ amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST);
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, 1 << vm_id);
@@ -1992,7 +2026,7 @@ static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
amdgpu_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */
WAIT_REG_MEM_ENGINE(0))); /* me */
- amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST);
+ amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST);
amdgpu_ring_write(ring, 0);
amdgpu_ring_write(ring, 0); /* ref */
amdgpu_ring_write(ring, 0); /* mask */
@@ -2071,7 +2105,6 @@ static int gfx_v6_0_rlc_init(struct amdgpu_device *adev)
if (src_ptr) {
/* save restore block */
if (adev->gfx.rlc.save_restore_obj == NULL) {
-
r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
@@ -2166,20 +2199,12 @@ static int gfx_v6_0_rlc_init(struct amdgpu_device *adev)
static void gfx_v6_0_enable_lbpw(struct amdgpu_device *adev, bool enable)
{
- u32 tmp;
-
- tmp = RREG32(RLC_LB_CNTL);
- if (enable)
- tmp |= LOAD_BALANCE_ENABLE;
- else
- tmp &= ~LOAD_BALANCE_ENABLE;
- WREG32(RLC_LB_CNTL, tmp);
+ WREG32_FIELD(RLC_LB_CNTL, LOAD_BALANCE_ENABLE, enable ? 1 : 0);
if (!enable) {
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
- WREG32(SPI_LB_CU_MASK, 0x00ff);
+ WREG32(mmSPI_LB_CU_MASK, 0x00ff);
}
-
}
static void gfx_v6_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
@@ -2187,13 +2212,13 @@ static void gfx_v6_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0)
+ if (RREG32(mmRLC_SERDES_MASTER_BUSY_0) == 0)
break;
udelay(1);
}
for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0)
+ if (RREG32(mmRLC_SERDES_MASTER_BUSY_1) == 0)
break;
udelay(1);
}
@@ -2203,20 +2228,20 @@ static void gfx_v6_0_update_rlc(struct amdgpu_device *adev, u32 rlc)
{
u32 tmp;
- tmp = RREG32(RLC_CNTL);
+ tmp = RREG32(mmRLC_CNTL);
if (tmp != rlc)
- WREG32(RLC_CNTL, rlc);
+ WREG32(mmRLC_CNTL, rlc);
}
static u32 gfx_v6_0_halt_rlc(struct amdgpu_device *adev)
{
u32 data, orig;
- orig = data = RREG32(RLC_CNTL);
+ orig = data = RREG32(mmRLC_CNTL);
- if (data & RLC_ENABLE) {
- data &= ~RLC_ENABLE;
- WREG32(RLC_CNTL, data);
+ if (data & RLC_CNTL__RLC_ENABLE_F32_MASK) {
+ data &= ~RLC_CNTL__RLC_ENABLE_F32_MASK;
+ WREG32(mmRLC_CNTL, data);
gfx_v6_0_wait_for_rlc_serdes(adev);
}
@@ -2226,7 +2251,7 @@ static u32 gfx_v6_0_halt_rlc(struct amdgpu_device *adev)
static void gfx_v6_0_rlc_stop(struct amdgpu_device *adev)
{
- WREG32(RLC_CNTL, 0);
+ WREG32(mmRLC_CNTL, 0);
gfx_v6_0_enable_gui_idle_interrupt(adev, false);
gfx_v6_0_wait_for_rlc_serdes(adev);
@@ -2234,7 +2259,7 @@ static void gfx_v6_0_rlc_stop(struct amdgpu_device *adev)
static void gfx_v6_0_rlc_start(struct amdgpu_device *adev)
{
- WREG32(RLC_CNTL, RLC_ENABLE);
+ WREG32(mmRLC_CNTL, RLC_CNTL__RLC_ENABLE_F32_MASK);
gfx_v6_0_enable_gui_idle_interrupt(adev, true);
@@ -2243,13 +2268,9 @@ static void gfx_v6_0_rlc_start(struct amdgpu_device *adev)
static void gfx_v6_0_rlc_reset(struct amdgpu_device *adev)
{
- u32 tmp = RREG32(GRBM_SOFT_RESET);
-
- tmp |= SOFT_RESET_RLC;
- WREG32(GRBM_SOFT_RESET, tmp);
+ WREG32_FIELD(GRBM_SOFT_RESET, SOFT_RESET_RLC, 1);
udelay(50);
- tmp &= ~SOFT_RESET_RLC;
- WREG32(GRBM_SOFT_RESET, tmp);
+ WREG32_FIELD(GRBM_SOFT_RESET, SOFT_RESET_RLC, 0);
udelay(50);
}
@@ -2258,11 +2279,12 @@ static bool gfx_v6_0_lbpw_supported(struct amdgpu_device *adev)
u32 tmp;
/* Enable LBPW only for DDR3 */
- tmp = RREG32(MC_SEQ_MISC0);
+ tmp = RREG32(mmMC_SEQ_MISC0);
if ((tmp & 0xF0000000) == 0xB0000000)
return true;
return false;
}
+
static void gfx_v6_0_init_cg(struct amdgpu_device *adev)
{
}
@@ -2283,15 +2305,15 @@ static int gfx_v6_0_rlc_resume(struct amdgpu_device *adev)
gfx_v6_0_init_pg(adev);
gfx_v6_0_init_cg(adev);
- WREG32(RLC_RL_BASE, 0);
- WREG32(RLC_RL_SIZE, 0);
- WREG32(RLC_LB_CNTL, 0);
- WREG32(RLC_LB_CNTR_MAX, 0xffffffff);
- WREG32(RLC_LB_CNTR_INIT, 0);
- WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);
+ WREG32(mmRLC_RL_BASE, 0);
+ WREG32(mmRLC_RL_SIZE, 0);
+ WREG32(mmRLC_LB_CNTL, 0);
+ WREG32(mmRLC_LB_CNTR_MAX, 0xffffffff);
+ WREG32(mmRLC_LB_CNTR_INIT, 0);
+ WREG32(mmRLC_LB_INIT_CU_MASK, 0xffffffff);
- WREG32(RLC_MC_CNTL, 0);
- WREG32(RLC_UCODE_CNTL, 0);
+ WREG32(mmRLC_MC_CNTL, 0);
+ WREG32(mmRLC_UCODE_CNTL, 0);
hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
@@ -2301,10 +2323,10 @@ static int gfx_v6_0_rlc_resume(struct amdgpu_device *adev)
amdgpu_ucode_print_rlc_hdr(&hdr->header);
for (i = 0; i < fw_size; i++) {
- WREG32(RLC_UCODE_ADDR, i);
- WREG32(RLC_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(mmRLC_UCODE_ADDR, i);
+ WREG32(mmRLC_UCODE_DATA, le32_to_cpup(fw_data++));
}
- WREG32(RLC_UCODE_ADDR, 0);
+ WREG32(mmRLC_UCODE_ADDR, 0);
gfx_v6_0_enable_lbpw(adev, gfx_v6_0_lbpw_supported(adev));
gfx_v6_0_rlc_start(adev);
@@ -2316,38 +2338,38 @@ static void gfx_v6_0_enable_cgcg(struct amdgpu_device *adev, bool enable)
{
u32 data, orig, tmp;
- orig = data = RREG32(RLC_CGCG_CGLS_CTRL);
+ orig = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
gfx_v6_0_enable_gui_idle_interrupt(adev, true);
- WREG32(RLC_GCPM_GENERAL_3, 0x00000080);
+ WREG32(mmRLC_GCPM_GENERAL_3, 0x00000080);
tmp = gfx_v6_0_halt_rlc(adev);
- WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
- WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
- WREG32(RLC_SERDES_WR_CTRL, 0x00b000ff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_CTRL, 0x00b000ff);
gfx_v6_0_wait_for_rlc_serdes(adev);
gfx_v6_0_update_rlc(adev, tmp);
- WREG32(RLC_SERDES_WR_CTRL, 0x007000ff);
+ WREG32(mmRLC_SERDES_WR_CTRL, 0x007000ff);
- data |= CGCG_EN | CGLS_EN;
+ data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
} else {
gfx_v6_0_enable_gui_idle_interrupt(adev, false);
- RREG32(CB_CGTT_SCLK_CTRL);
- RREG32(CB_CGTT_SCLK_CTRL);
- RREG32(CB_CGTT_SCLK_CTRL);
- RREG32(CB_CGTT_SCLK_CTRL);
+ RREG32(mmCB_CGTT_SCLK_CTRL);
+ RREG32(mmCB_CGTT_SCLK_CTRL);
+ RREG32(mmCB_CGTT_SCLK_CTRL);
+ RREG32(mmCB_CGTT_SCLK_CTRL);
- data &= ~(CGCG_EN | CGLS_EN);
+ data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
}
if (orig != data)
- WREG32(RLC_CGCG_CGLS_CTRL, data);
+ WREG32(mmRLC_CGCG_CGLS_CTRL, data);
}
@@ -2357,51 +2379,51 @@ static void gfx_v6_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
u32 data, orig, tmp = 0;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
- orig = data = RREG32(CGTS_SM_CTRL_REG);
+ orig = data = RREG32(mmCGTS_SM_CTRL_REG);
data = 0x96940200;
if (orig != data)
- WREG32(CGTS_SM_CTRL_REG, data);
+ WREG32(mmCGTS_SM_CTRL_REG, data);
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
- orig = data = RREG32(CP_MEM_SLP_CNTL);
- data |= CP_MEM_LS_EN;
+ orig = data = RREG32(mmCP_MEM_SLP_CNTL);
+ data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
if (orig != data)
- WREG32(CP_MEM_SLP_CNTL, data);
+ WREG32(mmCP_MEM_SLP_CNTL, data);
}
- orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
+ orig = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
data &= 0xffffffc0;
if (orig != data)
- WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
+ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
tmp = gfx_v6_0_halt_rlc(adev);
- WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
- WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
- WREG32(RLC_SERDES_WR_CTRL, 0x00d000ff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_CTRL, 0x00d000ff);
gfx_v6_0_update_rlc(adev, tmp);
} else {
- orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
+ orig = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
data |= 0x00000003;
if (orig != data)
- WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
+ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
- data = RREG32(CP_MEM_SLP_CNTL);
- if (data & CP_MEM_LS_EN) {
- data &= ~CP_MEM_LS_EN;
- WREG32(CP_MEM_SLP_CNTL, data);
+ data = RREG32(mmCP_MEM_SLP_CNTL);
+ if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
+ data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+ WREG32(mmCP_MEM_SLP_CNTL, data);
}
- orig = data = RREG32(CGTS_SM_CTRL_REG);
- data |= LS_OVERRIDE | OVERRIDE;
+ orig = data = RREG32(mmCGTS_SM_CTRL_REG);
+ data |= CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK | CGTS_SM_CTRL_REG__OVERRIDE_MASK;
if (orig != data)
- WREG32(CGTS_SM_CTRL_REG, data);
+ WREG32(mmCGTS_SM_CTRL_REG, data);
tmp = gfx_v6_0_halt_rlc(adev);
- WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
- WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
- WREG32(RLC_SERDES_WR_CTRL, 0x00e000ff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+ WREG32(mmRLC_SERDES_WR_CTRL, 0x00e000ff);
gfx_v6_0_update_rlc(adev, tmp);
}
@@ -2421,6 +2443,7 @@ static void gfx_v6_0_update_cg(struct amdgpu_device *adev,
gfx_v6_0_enable_gui_idle_interrupt(adev, true);
}
*/
+
static void gfx_v6_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev,
bool enable)
{
@@ -2435,13 +2458,13 @@ static void gfx_v6_0_enable_cp_pg(struct amdgpu_device *adev, bool enable)
{
u32 data, orig;
- orig = data = RREG32(RLC_PG_CNTL);
+ orig = data = RREG32(mmRLC_PG_CNTL);
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_CP))
data &= ~0x8000;
else
data |= 0x8000;
if (orig != data)
- WREG32(RLC_PG_CNTL, data);
+ WREG32(mmRLC_PG_CNTL, data);
}
static void gfx_v6_0_enable_gds_pg(struct amdgpu_device *adev, bool enable)
@@ -2518,26 +2541,13 @@ static void gfx_v6_0_init_cp_pg_table(struct amdgpu_device *adev)
static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev,
bool enable)
{
-
- u32 tmp;
-
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
- tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10);
- WREG32(RLC_TTOP_D, tmp);
-
- tmp = RREG32(RLC_PG_CNTL);
- tmp |= GFX_PG_ENABLE;
- WREG32(RLC_PG_CNTL, tmp);
-
- tmp = RREG32(RLC_AUTO_PG_CTRL);
- tmp |= AUTO_PG_EN;
- WREG32(RLC_AUTO_PG_CTRL, tmp);
+ WREG32(mmRLC_TTOP_D, RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10));
+ WREG32_FIELD(RLC_PG_CNTL, GFX_POWER_GATING_ENABLE, 1);
+ WREG32_FIELD(RLC_AUTO_PG_CTRL, AUTO_PG_EN, 1);
} else {
- tmp = RREG32(RLC_AUTO_PG_CTRL);
- tmp &= ~AUTO_PG_EN;
- WREG32(RLC_AUTO_PG_CTRL, tmp);
-
- tmp = RREG32(DB_RENDER_CONTROL);
+ WREG32_FIELD(RLC_AUTO_PG_CTRL, AUTO_PG_EN, 0);
+ (void)RREG32(mmDB_RENDER_CONTROL);
}
}
@@ -2550,8 +2560,8 @@ static u32 gfx_v6_0_get_cu_active_bitmap(struct amdgpu_device *adev,
mutex_lock(&adev->grbm_idx_mutex);
gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff);
- tmp = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
- tmp1 = RREG32(GC_USER_SHADER_ARRAY_CONFIG);
+ tmp = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
+ tmp1 = RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
@@ -2594,12 +2604,8 @@ static void gfx_v6_0_init_ao_cu_mask(struct amdgpu_device *adev)
}
}
- WREG32(RLC_PG_AO_CU_MASK, tmp);
-
- tmp = RREG32(RLC_MAX_PG_CU);
- tmp &= ~MAX_PU_CU_MASK;
- tmp |= MAX_PU_CU(active_cu_number);
- WREG32(RLC_MAX_PG_CU, tmp);
+ WREG32(mmRLC_PG_AO_CU_MASK, tmp);
+ WREG32_FIELD(RLC_MAX_PG_CU, MAX_POWERED_UP_CU, active_cu_number);
}
static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
@@ -2607,13 +2613,13 @@ static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
{
u32 data, orig;
- orig = data = RREG32(RLC_PG_CNTL);
+ orig = data = RREG32(mmRLC_PG_CNTL);
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG))
- data |= STATIC_PER_CU_PG_ENABLE;
+ data |= RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
else
- data &= ~STATIC_PER_CU_PG_ENABLE;
+ data &= ~RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
if (orig != data)
- WREG32(RLC_PG_CNTL, data);
+ WREG32(mmRLC_PG_CNTL, data);
}
static void gfx_v6_0_enable_gfx_dynamic_mgpg(struct amdgpu_device *adev,
@@ -2621,33 +2627,28 @@ static void gfx_v6_0_enable_gfx_dynamic_mgpg(struct amdgpu_device *adev,
{
u32 data, orig;
- orig = data = RREG32(RLC_PG_CNTL);
+ orig = data = RREG32(mmRLC_PG_CNTL);
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_DMG))
- data |= DYN_PER_CU_PG_ENABLE;
+ data |= RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
else
- data &= ~DYN_PER_CU_PG_ENABLE;
+ data &= ~RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
if (orig != data)
- WREG32(RLC_PG_CNTL, data);
+ WREG32(mmRLC_PG_CNTL, data);
}
static void gfx_v6_0_init_gfx_cgpg(struct amdgpu_device *adev)
{
u32 tmp;
- WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+ WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+ WREG32_FIELD(RLC_PG_CNTL, GFX_POWER_GATING_SRC, 1);
+ WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
- tmp = RREG32(RLC_PG_CNTL);
- tmp |= GFX_PG_SRC;
- WREG32(RLC_PG_CNTL, tmp);
-
- WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
-
- tmp = RREG32(RLC_AUTO_PG_CTRL);
-
- tmp &= ~GRBM_REG_SGIT_MASK;
- tmp |= GRBM_REG_SGIT(0x700);
- tmp &= ~PG_AFTER_GRBM_REG_ST_MASK;
- WREG32(RLC_AUTO_PG_CTRL, tmp);
+ tmp = RREG32(mmRLC_AUTO_PG_CTRL);
+ tmp &= ~RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK;
+ tmp |= (0x700 << RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT);
+ tmp &= ~RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD_MASK;
+ WREG32(mmRLC_AUTO_PG_CTRL, tmp);
}
static void gfx_v6_0_update_gfx_pg(struct amdgpu_device *adev, bool enable)
@@ -2703,7 +2704,6 @@ static void gfx_v6_0_get_csb_buffer(struct amdgpu_device *adev,
buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
-
buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CONTEXT_CONTROL, 1));
buffer[count++] = cpu_to_le32(0x80000000);
buffer[count++] = cpu_to_le32(0x80000000);
@@ -2723,7 +2723,7 @@ static void gfx_v6_0_get_csb_buffer(struct amdgpu_device *adev,
}
buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 1));
- buffer[count++] = cpu_to_le32(PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
+ buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
switch (adev->asic_type) {
case CHIP_TAHITI:
@@ -2766,16 +2766,16 @@ static void gfx_v6_0_init_pg(struct amdgpu_device *adev)
gfx_v6_0_enable_cp_pg(adev, true);
gfx_v6_0_enable_gds_pg(adev, true);
} else {
- WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
- WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
+ WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+ WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
}
gfx_v6_0_init_ao_cu_mask(adev);
gfx_v6_0_update_gfx_pg(adev, true);
} else {
- WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
- WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
+ WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+ WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
}
}
@@ -2800,50 +2800,86 @@ static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev)
uint64_t clock;
mutex_lock(&adev->gfx.gpu_clock_mutex);
- WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1);
- clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) |
- ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+ WREG32(mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+ clock = (uint64_t)RREG32(mmRLC_GPU_CLOCK_COUNT_LSB) |
+ ((uint64_t)RREG32(mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
mutex_unlock(&adev->gfx.gpu_clock_mutex);
return clock;
}
static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
{
+ if (flags & AMDGPU_HAVE_CTX_SWITCH)
+ gfx_v6_0_ring_emit_vgt_flush(ring);
amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1));
amdgpu_ring_write(ring, 0x80000000);
amdgpu_ring_write(ring, 0);
}
-static unsigned gfx_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
+
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
{
- return
- 6; /* gfx_v6_0_ring_emit_ib */
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (address << SQ_IND_INDEX__INDEX__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK));
+ return RREG32(mmSQ_IND_DATA);
}
-static unsigned gfx_v6_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t thread,
+ uint32_t regno, uint32_t num, uint32_t *out)
{
- return
- 5 + /* gfx_v6_0_ring_emit_hdp_flush */
- 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
- 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
- 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
- 17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
- 3; /* gfx_v6_ring_emit_cntxcntl */
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (regno << SQ_IND_INDEX__INDEX__SHIFT) |
+ (thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK) |
+ (SQ_IND_INDEX__AUTO_INCR_MASK));
+ while (num--)
+ *(out++) = RREG32(mmSQ_IND_DATA);
}
-static unsigned gfx_v6_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
+static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
- return
- 5 + /* gfx_v6_0_ring_emit_hdp_flush */
- 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
- 7 + /* gfx_v6_0_ring_emit_pipeline_sync */
- 17 + /* gfx_v6_0_ring_emit_vm_flush */
- 14 + 14 + 14; /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+ /* type 0 wave data */
+ dst[(*no_fields)++] = 0;
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+}
+
+static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t start,
+ uint32_t size, uint32_t *dst)
+{
+ wave_read_regs(
+ adev, simd, wave, 0,
+ start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
}
static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = {
.get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter,
.select_se_sh = &gfx_v6_0_select_se_sh,
+ .read_wave_data = &gfx_v6_0_read_wave_data,
+ .read_wave_sgprs = &gfx_v6_0_read_wave_sgprs,
};
static int gfx_v6_0_early_init(void *handle)
@@ -2896,9 +2932,7 @@ static int gfx_v6_0_sw_init(void *handle)
ring->ring_obj = NULL;
sprintf(ring->name, "gfx");
r = amdgpu_ring_init(adev, ring, 1024,
- 0x80000000, 0xf,
- &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
- AMDGPU_RING_TYPE_GFX);
+ &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
if (r)
return r;
}
@@ -2920,9 +2954,7 @@ static int gfx_v6_0_sw_init(void *handle)
sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
r = amdgpu_ring_init(adev, ring, 1024,
- 0x80000000, 0xf,
- &adev->gfx.eop_irq, irq_type,
- AMDGPU_RING_TYPE_COMPUTE);
+ &adev->gfx.eop_irq, irq_type);
if (r)
return r;
}
@@ -2998,7 +3030,7 @@ static bool gfx_v6_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (RREG32(GRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
+ if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
return false;
else
return true;
@@ -3029,14 +3061,14 @@ static void gfx_v6_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
- cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
+ cp_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
- cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
+ cp_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
default:
break;
@@ -3051,27 +3083,27 @@ static void gfx_v6_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
switch (state){
case AMDGPU_IRQ_STATE_DISABLE:
if (ring == 0) {
- cp_int_cntl = RREG32(CP_INT_CNTL_RING1);
- cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING1, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING1);
+ cp_int_cntl &= ~CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING1, cp_int_cntl);
break;
} else {
- cp_int_cntl = RREG32(CP_INT_CNTL_RING2);
- cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING2, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING2);
+ cp_int_cntl &= ~CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING2, cp_int_cntl);
break;
}
case AMDGPU_IRQ_STATE_ENABLE:
if (ring == 0) {
- cp_int_cntl = RREG32(CP_INT_CNTL_RING1);
- cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING1, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING1);
+ cp_int_cntl |= CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING1, cp_int_cntl);
break;
} else {
- cp_int_cntl = RREG32(CP_INT_CNTL_RING2);
- cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING2, cp_int_cntl);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING2);
+ cp_int_cntl |= CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK;
+ WREG32(mmCP_INT_CNTL_RING2, cp_int_cntl);
break;
}
@@ -3092,14 +3124,14 @@ static int gfx_v6_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
default:
break;
@@ -3117,14 +3149,14 @@ static int gfx_v6_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+ cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK;
- WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+ WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
break;
default:
break;
@@ -3164,7 +3196,7 @@ static int gfx_v6_0_eop_irq(struct amdgpu_device *adev,
break;
case 1:
case 2:
- amdgpu_fence_process(&adev->gfx.compute_ring[entry->ring_id -1]);
+ amdgpu_fence_process(&adev->gfx.compute_ring[entry->ring_id - 1]);
break;
default:
break;
@@ -3237,7 +3269,7 @@ static int gfx_v6_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
.name = "gfx_v6_0",
.early_init = gfx_v6_0_early_init,
.late_init = NULL,
@@ -3255,10 +3287,20 @@ const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
+ .type = AMDGPU_RING_TYPE_GFX,
+ .align_mask = 0xff,
+ .nop = 0x80000000,
.get_rptr = gfx_v6_0_ring_get_rptr,
.get_wptr = gfx_v6_0_ring_get_wptr,
.set_wptr = gfx_v6_0_ring_set_wptr_gfx,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 5 + /* gfx_v6_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
+ 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+ 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
+ 17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
+ 3 + 2, /* gfx_v6_ring_emit_cntxcntl including vgt flush */
+ .emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
.emit_ib = gfx_v6_0_ring_emit_ib,
.emit_fence = gfx_v6_0_ring_emit_fence,
.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3269,15 +3311,22 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
.test_ib = gfx_v6_0_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
.emit_cntxcntl = gfx_v6_ring_emit_cntxcntl,
- .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size,
- .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_gfx,
};
static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
+ .type = AMDGPU_RING_TYPE_COMPUTE,
+ .align_mask = 0xff,
+ .nop = 0x80000000,
.get_rptr = gfx_v6_0_ring_get_rptr,
.get_wptr = gfx_v6_0_ring_get_wptr,
.set_wptr = gfx_v6_0_ring_set_wptr_compute,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 5 + /* gfx_v6_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
+ 7 + /* gfx_v6_0_ring_emit_pipeline_sync */
+ 17 + /* gfx_v6_0_ring_emit_vm_flush */
+ 14 + 14 + 14, /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+ .emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
.emit_ib = gfx_v6_0_ring_emit_ib,
.emit_fence = gfx_v6_0_ring_emit_fence,
.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3287,8 +3336,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
.test_ring = gfx_v6_0_ring_test_ring,
.test_ib = gfx_v6_0_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
- .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size,
- .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_compute,
};
static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -3360,3 +3407,12 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
cu_info->number = active_cu_number;
cu_info->ao_cu_mask = ao_cu_mask;
}
+
+const struct amdgpu_ip_block_version gfx_v6_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 6,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gfx_v6_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h
index b9657e72b248..ced6fc42f688 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h
@@ -24,6 +24,6 @@
#ifndef __GFX_V6_0_H__
#define __GFX_V6_0_H__
-extern const struct amd_ip_funcs gfx_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v6_0_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 71116da9e782..c4e14015ec5b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -2077,9 +2077,9 @@ static int gfx_v7_0_ring_test_ring(struct amdgpu_ring *ring)
static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
{
u32 ref_and_mask;
- int usepfp = ring->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1;
+ int usepfp = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1;
- if (ring->type == AMDGPU_RING_TYPE_COMPUTE) {
+ if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
switch (ring->me) {
case 1:
ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -2105,6 +2105,18 @@ static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, 0x20); /* poll interval */
}
+static void gfx_v7_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+ amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+ EVENT_INDEX(4));
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+ amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+ EVENT_INDEX(0));
+}
+
+
/**
* gfx_v7_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
*
@@ -2260,6 +2272,7 @@ static void gfx_v7_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
+ gfx_v7_0_ring_emit_vgt_flush(ring);
/* set load_global_config & load_global_uconfig */
dw2 |= 0x8001;
/* set load_cs_sh_regs */
@@ -2286,7 +2299,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
uint32_t scratch;
uint32_t tmp = 0;
long r;
@@ -2312,7 +2325,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err2;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -2333,7 +2346,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
err2:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err1:
amdgpu_gfx_scratch_free(adev, scratch);
return r;
@@ -3222,7 +3235,7 @@ static int gfx_v7_0_cp_resume(struct amdgpu_device *adev)
*/
static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
uint32_t seq = ring->fence_drv.sync_seq;
uint64_t addr = ring->fence_drv.gpu_addr;
@@ -3262,7 +3275,7 @@ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
unsigned vm_id, uint64_t pd_addr)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -3391,7 +3404,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
if (adev->gfx.rlc.save_restore_obj == NULL) {
r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL,
&adev->gfx.rlc.save_restore_obj);
if (r) {
@@ -3435,7 +3449,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
if (adev->gfx.rlc.clear_state_obj == NULL) {
r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL,
&adev->gfx.rlc.clear_state_obj);
if (r) {
@@ -3475,7 +3490,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
if (adev->gfx.rlc.cp_table_obj == NULL) {
r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL,
&adev->gfx.rlc.cp_table_obj);
if (r) {
@@ -4354,44 +4370,69 @@ static void gfx_v7_0_ring_emit_gds_switch(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base));
}
-static unsigned gfx_v7_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring)
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
{
- return
- 4; /* gfx_v7_0_ring_emit_ib_gfx */
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (address << SQ_IND_INDEX__INDEX__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK));
+ return RREG32(mmSQ_IND_DATA);
}
-static unsigned gfx_v7_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t thread,
+ uint32_t regno, uint32_t num, uint32_t *out)
{
- return
- 20 + /* gfx_v7_0_ring_emit_gds_switch */
- 7 + /* gfx_v7_0_ring_emit_hdp_flush */
- 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
- 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
- 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
- 17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
- 3; /* gfx_v7_ring_emit_cntxcntl */
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (regno << SQ_IND_INDEX__INDEX__SHIFT) |
+ (thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK) |
+ (SQ_IND_INDEX__AUTO_INCR_MASK));
+ while (num--)
+ *(out++) = RREG32(mmSQ_IND_DATA);
}
-static unsigned gfx_v7_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring)
+static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
- return
- 4; /* gfx_v7_0_ring_emit_ib_compute */
+ /* type 0 wave data */
+ dst[(*no_fields)++] = 0;
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
}
-static unsigned gfx_v7_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
+static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t start,
+ uint32_t size, uint32_t *dst)
{
- return
- 20 + /* gfx_v7_0_ring_emit_gds_switch */
- 7 + /* gfx_v7_0_ring_emit_hdp_flush */
- 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
- 7 + /* gfx_v7_0_ring_emit_pipeline_sync */
- 17 + /* gfx_v7_0_ring_emit_vm_flush */
- 7 + 7 + 7; /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */
+ wave_read_regs(
+ adev, simd, wave, 0,
+ start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
}
static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = {
.get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter,
.select_se_sh = &gfx_v7_0_select_se_sh,
+ .read_wave_data = &gfx_v7_0_read_wave_data,
+ .read_wave_sgprs = &gfx_v7_0_read_wave_sgprs,
};
static const struct amdgpu_rlc_funcs gfx_v7_0_rlc_funcs = {
@@ -4643,9 +4684,7 @@ static int gfx_v7_0_sw_init(void *handle)
ring->ring_obj = NULL;
sprintf(ring->name, "gfx");
r = amdgpu_ring_init(adev, ring, 1024,
- PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
- &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
- AMDGPU_RING_TYPE_GFX);
+ &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
if (r)
return r;
}
@@ -4670,9 +4709,7 @@ static int gfx_v7_0_sw_init(void *handle)
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
/* type-2 packets are deprecated on MEC, use type-3 instead */
r = amdgpu_ring_init(adev, ring, 1024,
- PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
- &adev->gfx.eop_irq, irq_type,
- AMDGPU_RING_TYPE_COMPUTE);
+ &adev->gfx.eop_irq, irq_type);
if (r)
return r;
}
@@ -5123,7 +5160,7 @@ static int gfx_v7_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
.name = "gfx_v7_0",
.early_init = gfx_v7_0_early_init,
.late_init = gfx_v7_0_late_init,
@@ -5141,10 +5178,21 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
+ .type = AMDGPU_RING_TYPE_GFX,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
.get_rptr = gfx_v7_0_ring_get_rptr,
.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 20 + /* gfx_v7_0_ring_emit_gds_switch */
+ 7 + /* gfx_v7_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
+ 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
+ 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
+ 17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
+ 3 + 4, /* gfx_v7_ring_emit_cntxcntl including vgt flush*/
+ .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_gfx */
.emit_ib = gfx_v7_0_ring_emit_ib_gfx,
.emit_fence = gfx_v7_0_ring_emit_fence_gfx,
.emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync,
@@ -5157,15 +5205,23 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
.insert_nop = amdgpu_ring_insert_nop,
.pad_ib = amdgpu_ring_generic_pad_ib,
.emit_cntxcntl = gfx_v7_ring_emit_cntxcntl,
- .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_gfx,
- .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_gfx,
};
static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
+ .type = AMDGPU_RING_TYPE_COMPUTE,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
.get_rptr = gfx_v7_0_ring_get_rptr,
.get_wptr = gfx_v7_0_ring_get_wptr_compute,
.set_wptr = gfx_v7_0_ring_set_wptr_compute,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 20 + /* gfx_v7_0_ring_emit_gds_switch */
+ 7 + /* gfx_v7_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
+ 7 + /* gfx_v7_0_ring_emit_pipeline_sync */
+ 17 + /* gfx_v7_0_ring_emit_vm_flush */
+ 7 + 7 + 7, /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */
+ .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_compute */
.emit_ib = gfx_v7_0_ring_emit_ib_compute,
.emit_fence = gfx_v7_0_ring_emit_fence_compute,
.emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync,
@@ -5177,8 +5233,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
.test_ib = gfx_v7_0_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
.pad_ib = amdgpu_ring_generic_pad_ib,
- .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_compute,
- .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_compute,
};
static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -5289,3 +5343,39 @@ static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev)
cu_info->number = active_cu_number;
cu_info->ao_cu_mask = ao_cu_mask;
}
+
+const struct amdgpu_ip_block_version gfx_v7_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 7,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 7,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_2_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 7,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_3_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 7,
+ .minor = 3,
+ .rev = 0,
+ .funcs = &gfx_v7_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h
index 94e3ea147c26..2f5164cc0e53 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h
@@ -24,6 +24,9 @@
#ifndef __GFX_V7_0_H__
#define __GFX_V7_0_H__
-extern const struct amd_ip_funcs gfx_v7_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v7_0_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_1_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_2_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_3_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index bb97182dc749..6324f67bdb1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -25,6 +25,7 @@
#include "amdgpu.h"
#include "amdgpu_gfx.h"
#include "vi.h"
+#include "vi_structs.h"
#include "vid.h"
#include "amdgpu_ucode.h"
#include "amdgpu_atombios.h"
@@ -167,6 +168,7 @@ static const u32 golden_settings_tonga_a11[] =
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
mmPA_SC_FIFO_DEPTH_CNTL, 0x000003ff, 0x000000fc,
mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0000003c,
mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
mmTCC_CTRL, 0x00100000, 0xf31fff7f,
@@ -797,7 +799,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
uint32_t scratch;
uint32_t tmp = 0;
long r;
@@ -823,7 +825,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err2;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out.\n");
r = -ETIMEDOUT;
@@ -843,7 +845,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
}
err2:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err1:
amdgpu_gfx_scratch_free(adev, scratch);
return r;
@@ -1057,6 +1059,19 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+ /* we need account JT in */
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+
+ if (amdgpu_sriov_vf(adev)) {
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE];
+ info->ucode_id = AMDGPU_UCODE_ID_STORAGE;
+ info->fw = adev->gfx.mec_fw;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(64 * PAGE_SIZE), PAGE_SIZE);
+ }
+
if (adev->gfx.mec2_fw) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
@@ -1126,34 +1141,8 @@ static void gfx_v8_0_get_csb_buffer(struct amdgpu_device *adev,
buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 2));
buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG -
PACKET3_SET_CONTEXT_REG_START);
- switch (adev->asic_type) {
- case CHIP_TONGA:
- case CHIP_POLARIS10:
- buffer[count++] = cpu_to_le32(0x16000012);
- buffer[count++] = cpu_to_le32(0x0000002A);
- break;
- case CHIP_POLARIS11:
- buffer[count++] = cpu_to_le32(0x16000012);
- buffer[count++] = cpu_to_le32(0x00000000);
- break;
- case CHIP_FIJI:
- buffer[count++] = cpu_to_le32(0x3a00161a);
- buffer[count++] = cpu_to_le32(0x0000002e);
- break;
- case CHIP_TOPAZ:
- case CHIP_CARRIZO:
- buffer[count++] = cpu_to_le32(0x00000002);
- buffer[count++] = cpu_to_le32(0x00000000);
- break;
- case CHIP_STONEY:
- buffer[count++] = cpu_to_le32(0x00000000);
- buffer[count++] = cpu_to_le32(0x00000000);
- break;
- default:
- buffer[count++] = cpu_to_le32(0x00000000);
- buffer[count++] = cpu_to_le32(0x00000000);
- break;
- }
+ buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config);
+ buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config_1);
buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE);
@@ -1272,7 +1261,8 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
if (adev->gfx.rlc.clear_state_obj == NULL) {
r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL,
&adev->gfx.rlc.clear_state_obj);
if (r) {
@@ -1314,7 +1304,8 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
if (adev->gfx.rlc.cp_table_obj == NULL) {
r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
- AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
NULL, NULL,
&adev->gfx.rlc.cp_table_obj);
if (r) {
@@ -1382,7 +1373,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
if (adev->gfx.mec.hpd_eop_obj == NULL) {
r = amdgpu_bo_create(adev,
- adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2,
+ adev->gfx.mec.num_queue * MEC_HPD_SIZE,
PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
&adev->gfx.mec.hpd_eop_obj);
@@ -1411,7 +1402,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
return r;
}
- memset(hpd, 0, adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2);
+ memset(hpd, 0, adev->gfx.mec.num_queue * MEC_HPD_SIZE);
amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj);
amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj);
@@ -1574,7 +1565,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
{
struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
int r, i;
u32 tmp;
unsigned total_size, vgpr_offset, sgpr_offset;
@@ -1707,7 +1698,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
}
/* wait for the GPU to finish processing the IB */
- r = fence_wait(f, false);
+ r = dma_fence_wait(f, false);
if (r) {
DRM_ERROR("amdgpu: fence wait failed (%d).\n", r);
goto fail;
@@ -1728,7 +1719,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
fail:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
return r;
}
@@ -2044,10 +2035,8 @@ static int gfx_v8_0_sw_init(void *handle)
ring->doorbell_index = AMDGPU_DOORBELL_GFX_RING0;
}
- r = amdgpu_ring_init(adev, ring, 1024,
- PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
- &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
- AMDGPU_RING_TYPE_GFX);
+ r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
+ AMDGPU_CP_IRQ_GFX_EOP);
if (r)
return r;
}
@@ -2071,10 +2060,8 @@ static int gfx_v8_0_sw_init(void *handle)
sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
/* type-2 packets are deprecated on MEC, use type-3 instead */
- r = amdgpu_ring_init(adev, ring, 1024,
- PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
- &adev->gfx.eop_irq, irq_type,
- AMDGPU_RING_TYPE_COMPUTE);
+ r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
+ irq_type);
if (r)
return r;
}
@@ -3678,6 +3665,21 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)
num_rb_pipes);
}
+ /* cache the values for userspace */
+ for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+ for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+ gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+ adev->gfx.config.rb_config[i][j].rb_backend_disable =
+ RREG32(mmCC_RB_BACKEND_DISABLE);
+ adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
+ RREG32(mmGC_USER_RB_BACKEND_DISABLE);
+ adev->gfx.config.rb_config[i][j].raster_config =
+ RREG32(mmPA_SC_RASTER_CONFIG);
+ adev->gfx.config.rb_config[i][j].raster_config_1 =
+ RREG32(mmPA_SC_RASTER_CONFIG_1);
+ }
+ }
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -3904,7 +3906,7 @@ static int gfx_v8_0_init_save_restore_list(struct amdgpu_device *adev)
int list_size;
unsigned int *register_list_format =
kmalloc(adev->gfx.rlc.reg_list_format_size_bytes, GFP_KERNEL);
- if (register_list_format == NULL)
+ if (!register_list_format)
return -ENOMEM;
memcpy(register_list_format, adev->gfx.rlc.register_list_format,
adev->gfx.rlc.reg_list_format_size_bytes);
@@ -4330,7 +4332,7 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
u32 tmp;
u32 rb_bufsz;
- u64 rb_addr, rptr_addr;
+ u64 rb_addr, rptr_addr, wptr_gpu_addr;
int r;
/* Set the write pointer delay */
@@ -4361,6 +4363,9 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+ wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+ WREG32(mmCP_RB_WPTR_POLL_ADDR_LO, lower_32_bits(wptr_gpu_addr));
+ WREG32(mmCP_RB_WPTR_POLL_ADDR_HI, upper_32_bits(wptr_gpu_addr));
mdelay(1);
WREG32(mmCP_RB0_CNTL, tmp);
@@ -4466,267 +4471,6 @@ static int gfx_v8_0_cp_compute_load_microcode(struct amdgpu_device *adev)
return 0;
}
-struct vi_mqd {
- uint32_t header; /* ordinal0 */
- uint32_t compute_dispatch_initiator; /* ordinal1 */
- uint32_t compute_dim_x; /* ordinal2 */
- uint32_t compute_dim_y; /* ordinal3 */
- uint32_t compute_dim_z; /* ordinal4 */
- uint32_t compute_start_x; /* ordinal5 */
- uint32_t compute_start_y; /* ordinal6 */
- uint32_t compute_start_z; /* ordinal7 */
- uint32_t compute_num_thread_x; /* ordinal8 */
- uint32_t compute_num_thread_y; /* ordinal9 */
- uint32_t compute_num_thread_z; /* ordinal10 */
- uint32_t compute_pipelinestat_enable; /* ordinal11 */
- uint32_t compute_perfcount_enable; /* ordinal12 */
- uint32_t compute_pgm_lo; /* ordinal13 */
- uint32_t compute_pgm_hi; /* ordinal14 */
- uint32_t compute_tba_lo; /* ordinal15 */
- uint32_t compute_tba_hi; /* ordinal16 */
- uint32_t compute_tma_lo; /* ordinal17 */
- uint32_t compute_tma_hi; /* ordinal18 */
- uint32_t compute_pgm_rsrc1; /* ordinal19 */
- uint32_t compute_pgm_rsrc2; /* ordinal20 */
- uint32_t compute_vmid; /* ordinal21 */
- uint32_t compute_resource_limits; /* ordinal22 */
- uint32_t compute_static_thread_mgmt_se0; /* ordinal23 */
- uint32_t compute_static_thread_mgmt_se1; /* ordinal24 */
- uint32_t compute_tmpring_size; /* ordinal25 */
- uint32_t compute_static_thread_mgmt_se2; /* ordinal26 */
- uint32_t compute_static_thread_mgmt_se3; /* ordinal27 */
- uint32_t compute_restart_x; /* ordinal28 */
- uint32_t compute_restart_y; /* ordinal29 */
- uint32_t compute_restart_z; /* ordinal30 */
- uint32_t compute_thread_trace_enable; /* ordinal31 */
- uint32_t compute_misc_reserved; /* ordinal32 */
- uint32_t compute_dispatch_id; /* ordinal33 */
- uint32_t compute_threadgroup_id; /* ordinal34 */
- uint32_t compute_relaunch; /* ordinal35 */
- uint32_t compute_wave_restore_addr_lo; /* ordinal36 */
- uint32_t compute_wave_restore_addr_hi; /* ordinal37 */
- uint32_t compute_wave_restore_control; /* ordinal38 */
- uint32_t reserved9; /* ordinal39 */
- uint32_t reserved10; /* ordinal40 */
- uint32_t reserved11; /* ordinal41 */
- uint32_t reserved12; /* ordinal42 */
- uint32_t reserved13; /* ordinal43 */
- uint32_t reserved14; /* ordinal44 */
- uint32_t reserved15; /* ordinal45 */
- uint32_t reserved16; /* ordinal46 */
- uint32_t reserved17; /* ordinal47 */
- uint32_t reserved18; /* ordinal48 */
- uint32_t reserved19; /* ordinal49 */
- uint32_t reserved20; /* ordinal50 */
- uint32_t reserved21; /* ordinal51 */
- uint32_t reserved22; /* ordinal52 */
- uint32_t reserved23; /* ordinal53 */
- uint32_t reserved24; /* ordinal54 */
- uint32_t reserved25; /* ordinal55 */
- uint32_t reserved26; /* ordinal56 */
- uint32_t reserved27; /* ordinal57 */
- uint32_t reserved28; /* ordinal58 */
- uint32_t reserved29; /* ordinal59 */
- uint32_t reserved30; /* ordinal60 */
- uint32_t reserved31; /* ordinal61 */
- uint32_t reserved32; /* ordinal62 */
- uint32_t reserved33; /* ordinal63 */
- uint32_t reserved34; /* ordinal64 */
- uint32_t compute_user_data_0; /* ordinal65 */
- uint32_t compute_user_data_1; /* ordinal66 */
- uint32_t compute_user_data_2; /* ordinal67 */
- uint32_t compute_user_data_3; /* ordinal68 */
- uint32_t compute_user_data_4; /* ordinal69 */
- uint32_t compute_user_data_5; /* ordinal70 */
- uint32_t compute_user_data_6; /* ordinal71 */
- uint32_t compute_user_data_7; /* ordinal72 */
- uint32_t compute_user_data_8; /* ordinal73 */
- uint32_t compute_user_data_9; /* ordinal74 */
- uint32_t compute_user_data_10; /* ordinal75 */
- uint32_t compute_user_data_11; /* ordinal76 */
- uint32_t compute_user_data_12; /* ordinal77 */
- uint32_t compute_user_data_13; /* ordinal78 */
- uint32_t compute_user_data_14; /* ordinal79 */
- uint32_t compute_user_data_15; /* ordinal80 */
- uint32_t cp_compute_csinvoc_count_lo; /* ordinal81 */
- uint32_t cp_compute_csinvoc_count_hi; /* ordinal82 */
- uint32_t reserved35; /* ordinal83 */
- uint32_t reserved36; /* ordinal84 */
- uint32_t reserved37; /* ordinal85 */
- uint32_t cp_mqd_query_time_lo; /* ordinal86 */
- uint32_t cp_mqd_query_time_hi; /* ordinal87 */
- uint32_t cp_mqd_connect_start_time_lo; /* ordinal88 */
- uint32_t cp_mqd_connect_start_time_hi; /* ordinal89 */
- uint32_t cp_mqd_connect_end_time_lo; /* ordinal90 */
- uint32_t cp_mqd_connect_end_time_hi; /* ordinal91 */
- uint32_t cp_mqd_connect_end_wf_count; /* ordinal92 */
- uint32_t cp_mqd_connect_end_pq_rptr; /* ordinal93 */
- uint32_t cp_mqd_connect_end_pq_wptr; /* ordinal94 */
- uint32_t cp_mqd_connect_end_ib_rptr; /* ordinal95 */
- uint32_t reserved38; /* ordinal96 */
- uint32_t reserved39; /* ordinal97 */
- uint32_t cp_mqd_save_start_time_lo; /* ordinal98 */
- uint32_t cp_mqd_save_start_time_hi; /* ordinal99 */
- uint32_t cp_mqd_save_end_time_lo; /* ordinal100 */
- uint32_t cp_mqd_save_end_time_hi; /* ordinal101 */
- uint32_t cp_mqd_restore_start_time_lo; /* ordinal102 */
- uint32_t cp_mqd_restore_start_time_hi; /* ordinal103 */
- uint32_t cp_mqd_restore_end_time_lo; /* ordinal104 */
- uint32_t cp_mqd_restore_end_time_hi; /* ordinal105 */
- uint32_t reserved40; /* ordinal106 */
- uint32_t reserved41; /* ordinal107 */
- uint32_t gds_cs_ctxsw_cnt0; /* ordinal108 */
- uint32_t gds_cs_ctxsw_cnt1; /* ordinal109 */
- uint32_t gds_cs_ctxsw_cnt2; /* ordinal110 */
- uint32_t gds_cs_ctxsw_cnt3; /* ordinal111 */
- uint32_t reserved42; /* ordinal112 */
- uint32_t reserved43; /* ordinal113 */
- uint32_t cp_pq_exe_status_lo; /* ordinal114 */
- uint32_t cp_pq_exe_status_hi; /* ordinal115 */
- uint32_t cp_packet_id_lo; /* ordinal116 */
- uint32_t cp_packet_id_hi; /* ordinal117 */
- uint32_t cp_packet_exe_status_lo; /* ordinal118 */
- uint32_t cp_packet_exe_status_hi; /* ordinal119 */
- uint32_t gds_save_base_addr_lo; /* ordinal120 */
- uint32_t gds_save_base_addr_hi; /* ordinal121 */
- uint32_t gds_save_mask_lo; /* ordinal122 */
- uint32_t gds_save_mask_hi; /* ordinal123 */
- uint32_t ctx_save_base_addr_lo; /* ordinal124 */
- uint32_t ctx_save_base_addr_hi; /* ordinal125 */
- uint32_t reserved44; /* ordinal126 */
- uint32_t reserved45; /* ordinal127 */
- uint32_t cp_mqd_base_addr_lo; /* ordinal128 */
- uint32_t cp_mqd_base_addr_hi; /* ordinal129 */
- uint32_t cp_hqd_active; /* ordinal130 */
- uint32_t cp_hqd_vmid; /* ordinal131 */
- uint32_t cp_hqd_persistent_state; /* ordinal132 */
- uint32_t cp_hqd_pipe_priority; /* ordinal133 */
- uint32_t cp_hqd_queue_priority; /* ordinal134 */
- uint32_t cp_hqd_quantum; /* ordinal135 */
- uint32_t cp_hqd_pq_base_lo; /* ordinal136 */
- uint32_t cp_hqd_pq_base_hi; /* ordinal137 */
- uint32_t cp_hqd_pq_rptr; /* ordinal138 */
- uint32_t cp_hqd_pq_rptr_report_addr_lo; /* ordinal139 */
- uint32_t cp_hqd_pq_rptr_report_addr_hi; /* ordinal140 */
- uint32_t cp_hqd_pq_wptr_poll_addr; /* ordinal141 */
- uint32_t cp_hqd_pq_wptr_poll_addr_hi; /* ordinal142 */
- uint32_t cp_hqd_pq_doorbell_control; /* ordinal143 */
- uint32_t cp_hqd_pq_wptr; /* ordinal144 */
- uint32_t cp_hqd_pq_control; /* ordinal145 */
- uint32_t cp_hqd_ib_base_addr_lo; /* ordinal146 */
- uint32_t cp_hqd_ib_base_addr_hi; /* ordinal147 */
- uint32_t cp_hqd_ib_rptr; /* ordinal148 */
- uint32_t cp_hqd_ib_control; /* ordinal149 */
- uint32_t cp_hqd_iq_timer; /* ordinal150 */
- uint32_t cp_hqd_iq_rptr; /* ordinal151 */
- uint32_t cp_hqd_dequeue_request; /* ordinal152 */
- uint32_t cp_hqd_dma_offload; /* ordinal153 */
- uint32_t cp_hqd_sema_cmd; /* ordinal154 */
- uint32_t cp_hqd_msg_type; /* ordinal155 */
- uint32_t cp_hqd_atomic0_preop_lo; /* ordinal156 */
- uint32_t cp_hqd_atomic0_preop_hi; /* ordinal157 */
- uint32_t cp_hqd_atomic1_preop_lo; /* ordinal158 */
- uint32_t cp_hqd_atomic1_preop_hi; /* ordinal159 */
- uint32_t cp_hqd_hq_status0; /* ordinal160 */
- uint32_t cp_hqd_hq_control0; /* ordinal161 */
- uint32_t cp_mqd_control; /* ordinal162 */
- uint32_t cp_hqd_hq_status1; /* ordinal163 */
- uint32_t cp_hqd_hq_control1; /* ordinal164 */
- uint32_t cp_hqd_eop_base_addr_lo; /* ordinal165 */
- uint32_t cp_hqd_eop_base_addr_hi; /* ordinal166 */
- uint32_t cp_hqd_eop_control; /* ordinal167 */
- uint32_t cp_hqd_eop_rptr; /* ordinal168 */
- uint32_t cp_hqd_eop_wptr; /* ordinal169 */
- uint32_t cp_hqd_eop_done_events; /* ordinal170 */
- uint32_t cp_hqd_ctx_save_base_addr_lo; /* ordinal171 */
- uint32_t cp_hqd_ctx_save_base_addr_hi; /* ordinal172 */
- uint32_t cp_hqd_ctx_save_control; /* ordinal173 */
- uint32_t cp_hqd_cntl_stack_offset; /* ordinal174 */
- uint32_t cp_hqd_cntl_stack_size; /* ordinal175 */
- uint32_t cp_hqd_wg_state_offset; /* ordinal176 */
- uint32_t cp_hqd_ctx_save_size; /* ordinal177 */
- uint32_t cp_hqd_gds_resource_state; /* ordinal178 */
- uint32_t cp_hqd_error; /* ordinal179 */
- uint32_t cp_hqd_eop_wptr_mem; /* ordinal180 */
- uint32_t cp_hqd_eop_dones; /* ordinal181 */
- uint32_t reserved46; /* ordinal182 */
- uint32_t reserved47; /* ordinal183 */
- uint32_t reserved48; /* ordinal184 */
- uint32_t reserved49; /* ordinal185 */
- uint32_t reserved50; /* ordinal186 */
- uint32_t reserved51; /* ordinal187 */
- uint32_t reserved52; /* ordinal188 */
- uint32_t reserved53; /* ordinal189 */
- uint32_t reserved54; /* ordinal190 */
- uint32_t reserved55; /* ordinal191 */
- uint32_t iqtimer_pkt_header; /* ordinal192 */
- uint32_t iqtimer_pkt_dw0; /* ordinal193 */
- uint32_t iqtimer_pkt_dw1; /* ordinal194 */
- uint32_t iqtimer_pkt_dw2; /* ordinal195 */
- uint32_t iqtimer_pkt_dw3; /* ordinal196 */
- uint32_t iqtimer_pkt_dw4; /* ordinal197 */
- uint32_t iqtimer_pkt_dw5; /* ordinal198 */
- uint32_t iqtimer_pkt_dw6; /* ordinal199 */
- uint32_t iqtimer_pkt_dw7; /* ordinal200 */
- uint32_t iqtimer_pkt_dw8; /* ordinal201 */
- uint32_t iqtimer_pkt_dw9; /* ordinal202 */
- uint32_t iqtimer_pkt_dw10; /* ordinal203 */
- uint32_t iqtimer_pkt_dw11; /* ordinal204 */
- uint32_t iqtimer_pkt_dw12; /* ordinal205 */
- uint32_t iqtimer_pkt_dw13; /* ordinal206 */
- uint32_t iqtimer_pkt_dw14; /* ordinal207 */
- uint32_t iqtimer_pkt_dw15; /* ordinal208 */
- uint32_t iqtimer_pkt_dw16; /* ordinal209 */
- uint32_t iqtimer_pkt_dw17; /* ordinal210 */
- uint32_t iqtimer_pkt_dw18; /* ordinal211 */
- uint32_t iqtimer_pkt_dw19; /* ordinal212 */
- uint32_t iqtimer_pkt_dw20; /* ordinal213 */
- uint32_t iqtimer_pkt_dw21; /* ordinal214 */
- uint32_t iqtimer_pkt_dw22; /* ordinal215 */
- uint32_t iqtimer_pkt_dw23; /* ordinal216 */
- uint32_t iqtimer_pkt_dw24; /* ordinal217 */
- uint32_t iqtimer_pkt_dw25; /* ordinal218 */
- uint32_t iqtimer_pkt_dw26; /* ordinal219 */
- uint32_t iqtimer_pkt_dw27; /* ordinal220 */
- uint32_t iqtimer_pkt_dw28; /* ordinal221 */
- uint32_t iqtimer_pkt_dw29; /* ordinal222 */
- uint32_t iqtimer_pkt_dw30; /* ordinal223 */
- uint32_t iqtimer_pkt_dw31; /* ordinal224 */
- uint32_t reserved56; /* ordinal225 */
- uint32_t reserved57; /* ordinal226 */
- uint32_t reserved58; /* ordinal227 */
- uint32_t set_resources_header; /* ordinal228 */
- uint32_t set_resources_dw1; /* ordinal229 */
- uint32_t set_resources_dw2; /* ordinal230 */
- uint32_t set_resources_dw3; /* ordinal231 */
- uint32_t set_resources_dw4; /* ordinal232 */
- uint32_t set_resources_dw5; /* ordinal233 */
- uint32_t set_resources_dw6; /* ordinal234 */
- uint32_t set_resources_dw7; /* ordinal235 */
- uint32_t reserved59; /* ordinal236 */
- uint32_t reserved60; /* ordinal237 */
- uint32_t reserved61; /* ordinal238 */
- uint32_t reserved62; /* ordinal239 */
- uint32_t reserved63; /* ordinal240 */
- uint32_t reserved64; /* ordinal241 */
- uint32_t reserved65; /* ordinal242 */
- uint32_t reserved66; /* ordinal243 */
- uint32_t reserved67; /* ordinal244 */
- uint32_t reserved68; /* ordinal245 */
- uint32_t reserved69; /* ordinal246 */
- uint32_t reserved70; /* ordinal247 */
- uint32_t reserved71; /* ordinal248 */
- uint32_t reserved72; /* ordinal249 */
- uint32_t reserved73; /* ordinal250 */
- uint32_t reserved74; /* ordinal251 */
- uint32_t reserved75; /* ordinal252 */
- uint32_t reserved76; /* ordinal253 */
- uint32_t reserved77; /* ordinal254 */
- uint32_t reserved78; /* ordinal255 */
-
- uint32_t reserved_t[256]; /* Reserve 256 dword buffer used by ucode */
-};
-
static void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
{
int i, r;
@@ -4760,34 +4504,7 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
u32 *buf;
struct vi_mqd *mqd;
- /* init the pipes */
- mutex_lock(&adev->srbm_mutex);
- for (i = 0; i < (adev->gfx.mec.num_pipe * adev->gfx.mec.num_mec); i++) {
- int me = (i < 4) ? 1 : 2;
- int pipe = (i < 4) ? i : (i - 4);
-
- eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE);
- eop_gpu_addr >>= 8;
-
- vi_srbm_select(adev, me, pipe, 0, 0);
-
- /* write the EOP addr */
- WREG32(mmCP_HQD_EOP_BASE_ADDR, eop_gpu_addr);
- WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr));
-
- /* set the VMID assigned */
- WREG32(mmCP_HQD_VMID, 0);
-
- /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
- tmp = RREG32(mmCP_HQD_EOP_CONTROL);
- tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
- (order_base_2(MEC_HPD_SIZE / 4) - 1));
- WREG32(mmCP_HQD_EOP_CONTROL, tmp);
- }
- vi_srbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
-
- /* init the queues. Just two for now. */
+ /* init the queues. */
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
@@ -4839,6 +4556,22 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
ring->pipe,
ring->queue, 0);
+ eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE);
+ eop_gpu_addr >>= 8;
+
+ /* write the EOP addr */
+ WREG32(mmCP_HQD_EOP_BASE_ADDR, eop_gpu_addr);
+ WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr));
+
+ /* set the VMID assigned */
+ WREG32(mmCP_HQD_VMID, 0);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+ tmp = RREG32(mmCP_HQD_EOP_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+ (order_base_2(MEC_HPD_SIZE / 4) - 1));
+ WREG32(mmCP_HQD_EOP_CONTROL, tmp);
+
/* disable wptr polling */
tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
@@ -4922,9 +4655,9 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
- mqd->cp_hqd_pq_wptr_poll_addr = wb_gpu_addr & 0xfffffffc;
+ mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
- WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr);
+ WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo);
WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
mqd->cp_hqd_pq_wptr_poll_addr_hi);
@@ -5095,6 +4828,10 @@ static int gfx_v8_0_hw_fini(void *handle)
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
+ if (amdgpu_sriov_vf(adev)) {
+ pr_debug("For SRIOV client, shouldn't do anything.\n");
+ return 0;
+ }
gfx_v8_0_cp_enable(adev, false);
gfx_v8_0_rlc_stop(adev);
gfx_v8_0_cp_compute_fini(adev);
@@ -5437,9 +5174,70 @@ static void gfx_v8_0_ring_emit_gds_switch(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base));
}
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
+{
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (address << SQ_IND_INDEX__INDEX__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK));
+ return RREG32(mmSQ_IND_DATA);
+}
+
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t thread,
+ uint32_t regno, uint32_t num, uint32_t *out)
+{
+ WREG32(mmSQ_IND_INDEX,
+ (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+ (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+ (regno << SQ_IND_INDEX__INDEX__SHIFT) |
+ (thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+ (SQ_IND_INDEX__FORCE_READ_MASK) |
+ (SQ_IND_INDEX__AUTO_INCR_MASK));
+ while (num--)
+ *(out++) = RREG32(mmSQ_IND_DATA);
+}
+
+static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+{
+ /* type 0 wave data */
+ dst[(*no_fields)++] = 0;
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+}
+
+static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+ uint32_t wave, uint32_t start,
+ uint32_t size, uint32_t *dst)
+{
+ wave_read_regs(
+ adev, simd, wave, 0,
+ start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
+}
+
+
static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = {
.get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter,
.select_se_sh = &gfx_v8_0_select_se_sh,
+ .read_wave_data = &gfx_v8_0_read_wave_data,
+ .read_wave_sgprs = &gfx_v8_0_read_wave_sgprs,
};
static int gfx_v8_0_early_init(void *handle)
@@ -5891,29 +5689,24 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
adev->gfx.rlc.funcs->enter_safe_mode(adev);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
- /* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/
- * Cmp_busy/GFX_Idle interrupts
- */
- gfx_v8_0_enable_gui_idle_interrupt(adev, true);
-
temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK;
if (temp1 != data1)
WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
- /* 2 wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+ /* : wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
gfx_v8_0_wait_for_rlc_serdes(adev);
- /* 3 - clear cgcg override */
+ /* 2 - clear cgcg override */
gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
gfx_v8_0_wait_for_rlc_serdes(adev);
- /* 4 - write cmd to set CGLS */
+ /* 3 - write cmd to set CGLS */
gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
- /* 5 - enable cgcg */
+ /* 4 - enable cgcg */
data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) {
@@ -5931,6 +5724,11 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
if (temp != data)
WREG32(mmRLC_CGCG_CGLS_CTRL, data);
+
+ /* 5 enable cntx_empty_int_enable/cntx_busy_int_enable/
+ * Cmp_busy/GFX_Idle interrupts
+ */
+ gfx_v8_0_enable_gui_idle_interrupt(adev, true);
} else {
/* disable cntx_empty_int_enable & GFX Idle interrupt */
gfx_v8_0_enable_gui_idle_interrupt(adev, false);
@@ -6119,7 +5917,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
{
u32 ref_and_mask, reg_mem_engine;
- if (ring->type == AMDGPU_RING_TYPE_COMPUTE) {
+ if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
switch (ring->me) {
case 1:
ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -6147,6 +5945,18 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, 0x20); /* poll interval */
}
+static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+ amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+ EVENT_INDEX(4));
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+ amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+ EVENT_INDEX(0));
+}
+
+
static void gfx_v8_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)
{
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -6221,7 +6031,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
uint32_t seq = ring->fence_drv.sync_seq;
uint64_t addr = ring->fence_drv.gpu_addr;
@@ -6239,11 +6049,7 @@ static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
unsigned vm_id, uint64_t pd_addr)
{
- int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
-
- /* GFX8 emits 128 dw nop to prevent DE do vm_flush before CE finish CEIB */
- if (usepfp)
- amdgpu_ring_insert_nop(ring, 128);
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -6336,6 +6142,7 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
+ gfx_v8_0_ring_emit_vgt_flush(ring);
/* set load_global_config & load_global_uconfig */
dw2 |= 0x8001;
/* set load_cs_sh_regs */
@@ -6359,42 +6166,6 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
amdgpu_ring_write(ring, 0);
}
-static unsigned gfx_v8_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring)
-{
- return
- 4; /* gfx_v8_0_ring_emit_ib_gfx */
-}
-
-static unsigned gfx_v8_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
-{
- return
- 20 + /* gfx_v8_0_ring_emit_gds_switch */
- 7 + /* gfx_v8_0_ring_emit_hdp_flush */
- 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
- 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */
- 7 + /* gfx_v8_0_ring_emit_pipeline_sync */
- 256 + 19 + /* gfx_v8_0_ring_emit_vm_flush */
- 2 + /* gfx_v8_ring_emit_sb */
- 3; /* gfx_v8_ring_emit_cntxcntl */
-}
-
-static unsigned gfx_v8_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring)
-{
- return
- 4; /* gfx_v8_0_ring_emit_ib_compute */
-}
-
-static unsigned gfx_v8_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
-{
- return
- 20 + /* gfx_v8_0_ring_emit_gds_switch */
- 7 + /* gfx_v8_0_ring_emit_hdp_flush */
- 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
- 7 + /* gfx_v8_0_ring_emit_pipeline_sync */
- 17 + /* gfx_v8_0_ring_emit_vm_flush */
- 7 + 7 + 7; /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */
-}
-
static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
enum amdgpu_interrupt_state state)
{
@@ -6540,7 +6311,7 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev,
return 0;
}
-const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
.name = "gfx_v8_0",
.early_init = gfx_v8_0_early_init,
.late_init = gfx_v8_0_late_init,
@@ -6561,10 +6332,22 @@ const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
+ .type = AMDGPU_RING_TYPE_GFX,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
.get_rptr = gfx_v8_0_ring_get_rptr,
.get_wptr = gfx_v8_0_ring_get_wptr_gfx,
.set_wptr = gfx_v8_0_ring_set_wptr_gfx,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 20 + /* gfx_v8_0_ring_emit_gds_switch */
+ 7 + /* gfx_v8_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+ 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */
+ 7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+ 128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */
+ 2 + /* gfx_v8_ring_emit_sb */
+ 3 + 4, /* gfx_v8_ring_emit_cntxcntl including vgt flush */
+ .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
.emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync,
@@ -6578,15 +6361,23 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.emit_switch_buffer = gfx_v8_ring_emit_sb,
.emit_cntxcntl = gfx_v8_ring_emit_cntxcntl,
- .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_gfx,
- .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_gfx,
};
static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
+ .type = AMDGPU_RING_TYPE_COMPUTE,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
.get_rptr = gfx_v8_0_ring_get_rptr,
.get_wptr = gfx_v8_0_ring_get_wptr_compute,
.set_wptr = gfx_v8_0_ring_set_wptr_compute,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 20 + /* gfx_v8_0_ring_emit_gds_switch */
+ 7 + /* gfx_v8_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+ 7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+ 17 + /* gfx_v8_0_ring_emit_vm_flush */
+ 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */
+ .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */
.emit_ib = gfx_v8_0_ring_emit_ib_compute,
.emit_fence = gfx_v8_0_ring_emit_fence_compute,
.emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync,
@@ -6598,8 +6389,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
.test_ib = gfx_v8_0_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
.pad_ib = amdgpu_ring_generic_pad_ib,
- .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_compute,
- .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_compute,
};
static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -6752,3 +6541,21 @@ static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev)
cu_info->number = active_cu_number;
cu_info->ao_cu_mask = ao_cu_mask;
}
+
+const struct amdgpu_ip_block_version gfx_v8_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 8,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gfx_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v8_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 8,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &gfx_v8_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h
index ebed1f829297..788cc3ab584b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h
@@ -24,6 +24,7 @@
#ifndef __GFX_V8_0_H__
#define __GFX_V8_0_H__
-extern const struct amd_ip_funcs gfx_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v8_1_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index b13c8aaec078..45a573e63d4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -1,4 +1,3 @@
-
/*
* Copyright 2014 Advanced Micro Devices, Inc.
*
@@ -26,7 +25,16 @@
#include "amdgpu.h"
#include "gmc_v6_0.h"
#include "amdgpu_ucode.h"
-#include "si/sid.h"
+
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "si_enums.h"
static void gmc_v6_0_set_gart_funcs(struct amdgpu_device *adev);
static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -37,6 +45,16 @@ MODULE_FIRMWARE("radeon/pitcairn_mc.bin");
MODULE_FIRMWARE("radeon/verde_mc.bin");
MODULE_FIRMWARE("radeon/oland_mc.bin");
+#define MC_SEQ_MISC0__MT__MASK 0xf0000000
+#define MC_SEQ_MISC0__MT__GDDR1 0x10000000
+#define MC_SEQ_MISC0__MT__DDR2 0x20000000
+#define MC_SEQ_MISC0__MT__GDDR3 0x30000000
+#define MC_SEQ_MISC0__MT__GDDR4 0x40000000
+#define MC_SEQ_MISC0__MT__GDDR5 0x50000000
+#define MC_SEQ_MISC0__MT__HBM 0x60000000
+#define MC_SEQ_MISC0__MT__DDR3 0xB0000000
+
+
static const u32 crtc_offsets[6] =
{
SI_CRTC0_REGISTER_OFFSET,
@@ -57,14 +75,14 @@ static void gmc_v6_0_mc_stop(struct amdgpu_device *adev,
gmc_v6_0_wait_for_idle((void *)adev);
- blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
- if (REG_GET_FIELD(blackout, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE) != 1) {
+ blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
+ if (REG_GET_FIELD(blackout, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE) != 1) {
/* Block CPU access */
- WREG32(BIF_FB_EN, 0);
+ WREG32(mmBIF_FB_EN, 0);
/* blackout the MC */
blackout = REG_SET_FIELD(blackout,
- mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0);
- WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
+ MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE, 0);
+ WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout | 1);
}
/* wait for the MC to settle */
udelay(100);
@@ -77,13 +95,13 @@ static void gmc_v6_0_mc_resume(struct amdgpu_device *adev,
u32 tmp;
/* unblackout the MC */
- tmp = RREG32(MC_SHARED_BLACKOUT_CNTL);
- tmp = REG_SET_FIELD(tmp, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0);
- WREG32(MC_SHARED_BLACKOUT_CNTL, tmp);
+ tmp = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
+ tmp = REG_SET_FIELD(tmp, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE, 0);
+ WREG32(mmMC_SHARED_BLACKOUT_CNTL, tmp);
/* allow CPU access */
- tmp = REG_SET_FIELD(0, mmBIF_FB_EN, xxFB_READ_EN, 1);
- tmp = REG_SET_FIELD(tmp, mmBIF_FB_EN, xxFB_WRITE_EN, 1);
- WREG32(BIF_FB_EN, tmp);
+ tmp = REG_SET_FIELD(0, BIF_FB_EN, FB_READ_EN, 1);
+ tmp = REG_SET_FIELD(tmp, BIF_FB_EN, FB_WRITE_EN, 1);
+ WREG32(mmBIF_FB_EN, tmp);
if (adev->mode_info.num_crtc)
amdgpu_display_resume_mc_access(adev, save);
@@ -158,37 +176,37 @@ static int gmc_v6_0_mc_load_microcode(struct amdgpu_device *adev)
new_fw_data = (const __le32 *)
(adev->mc.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
+ running = RREG32(mmMC_SEQ_SUP_CNTL) & MC_SEQ_SUP_CNTL__RUN_MASK;
if (running == 0) {
/* reset the engine and set to writable */
- WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
- WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
+ WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
+ WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
/* load mc io regs */
for (i = 0; i < regs_size; i++) {
- WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
- WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
+ WREG32(mmMC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
+ WREG32(mmMC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
}
/* load the MC ucode */
for (i = 0; i < ucode_size; i++) {
- WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+ WREG32(mmMC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
}
/* put the engine back into the active state */
- WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
- WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
- WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
+ WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
+ WREG32(mmMC_SEQ_SUP_CNTL, 0x00000004);
+ WREG32(mmMC_SEQ_SUP_CNTL, 0x00000001);
/* wait for training to complete */
for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0)
+ if (RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL) & MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0_MASK)
break;
udelay(1);
}
for (i = 0; i < adev->usec_timeout; i++) {
- if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1)
+ if (RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL) & MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1_MASK)
break;
udelay(1);
}
@@ -225,7 +243,7 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
WREG32((0xb08 + j), 0x00000000);
WREG32((0xb09 + j), 0x00000000);
}
- WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+ WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
gmc_v6_0_mc_stop(adev, &save);
@@ -233,24 +251,24 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
}
- WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
+ WREG32(mmVGA_HDP_CONTROL, VGA_HDP_CONTROL__VGA_MEMORY_DISABLE_MASK);
/* Update configuration */
- WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ WREG32(mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
adev->mc.vram_start >> 12);
- WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ WREG32(mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
adev->mc.vram_end >> 12);
- WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
+ WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
adev->vram_scratch.gpu_addr >> 12);
tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16;
tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF);
- WREG32(MC_VM_FB_LOCATION, tmp);
+ WREG32(mmMC_VM_FB_LOCATION, tmp);
/* XXX double check these! */
- WREG32(HDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8));
- WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
- WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
- WREG32(MC_VM_AGP_BASE, 0);
- WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
- WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
+ WREG32(mmHDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8));
+ WREG32(mmHDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
+ WREG32(mmHDP_NONSURFACE_SIZE, 0x3FFFFFFF);
+ WREG32(mmMC_VM_AGP_BASE, 0);
+ WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF);
+ WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF);
if (gmc_v6_0_wait_for_idle((void *)adev)) {
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
@@ -265,16 +283,16 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
u32 tmp;
int chansize, numchan;
- tmp = RREG32(MC_ARB_RAMCFG);
- if (tmp & CHANSIZE_OVERRIDE) {
+ tmp = RREG32(mmMC_ARB_RAMCFG);
+ if (tmp & (1 << 11)) {
chansize = 16;
- } else if (tmp & CHANSIZE_MASK) {
+ } else if (tmp & MC_ARB_RAMCFG__CHANSIZE_MASK) {
chansize = 64;
} else {
chansize = 32;
}
- tmp = RREG32(MC_SHARED_CHMAP);
- switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+ tmp = RREG32(mmMC_SHARED_CHMAP);
+ switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) {
case 0:
default:
numchan = 1;
@@ -309,15 +327,15 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
adev->mc.aper_base = pci_resource_start(adev->pdev, 0);
adev->mc.aper_size = pci_resource_len(adev->pdev, 0);
/* size in MB on si */
- adev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
- adev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+ adev->mc.mc_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+ adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
adev->mc.visible_vram_size = adev->mc.aper_size;
/* unless the user had overridden it, set the gart
* size equal to the 1024 or vram, whichever is larger.
*/
if (amdgpu_gart_size == -1)
- adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+ adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
else
adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
@@ -329,9 +347,9 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
static void gmc_v6_0_gart_flush_gpu_tlb(struct amdgpu_device *adev,
uint32_t vmid)
{
- WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0);
+ WREG32(mmHDP_MEM_COHERENCY_FLUSH_CNTL, 0);
- WREG32(VM_INVALIDATE_REQUEST, 1 << vmid);
+ WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
}
static int gmc_v6_0_gart_set_pte_pde(struct amdgpu_device *adev,
@@ -355,20 +373,20 @@ static void gmc_v6_0_set_fault_enable_default(struct amdgpu_device *adev,
{
u32 tmp;
- tmp = RREG32(VM_CONTEXT1_CNTL);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxRANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxDUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxPDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxVALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxREAD_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
- xxWRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- WREG32(VM_CONTEXT1_CNTL, 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);
}
static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
@@ -383,33 +401,39 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
if (r)
return r;
/* Setup TLB control */
- WREG32(MC_VM_MX_L1_TLB_CNTL,
+ WREG32(mmMC_VM_MX_L1_TLB_CNTL,
(0xA << 7) |
- ENABLE_L1_TLB |
- ENABLE_L1_FRAGMENT_PROCESSING |
- SYSTEM_ACCESS_MODE_NOT_IN_SYS |
- ENABLE_ADVANCED_DRIVER_MODEL |
- SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+ MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB_MASK |
+ MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING_MASK |
+ MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK |
+ MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL_MASK |
+ (0UL << MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT));
/* Setup L2 cache */
- WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
- ENABLE_L2_FRAGMENT_PROCESSING |
- ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
- ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
- EFFECTIVE_L2_QUEUE_SIZE(7) |
- CONTEXT1_IDENTITY_ACCESS_MODE(1));
- WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
- WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
- BANK_SELECT(4) |
- L2_CACHE_BIGK_FRAGMENT_SIZE(4));
+ WREG32(mmVM_L2_CNTL,
+ VM_L2_CNTL__ENABLE_L2_CACHE_MASK |
+ VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING_MASK |
+ VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+ VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+ (7UL << VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT) |
+ (1UL << VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT));
+ WREG32(mmVM_L2_CNTL2,
+ VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS_MASK |
+ VM_L2_CNTL2__INVALIDATE_L2_CACHE_MASK);
+ WREG32(mmVM_L2_CNTL3,
+ VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK |
+ (4UL << VM_L2_CNTL3__BANK_SELECT__SHIFT) |
+ (4UL << VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT));
/* setup context0 */
- WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
- WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
+ WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
+ WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
+ WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
+ WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(adev->dummy_page.addr >> 12));
- WREG32(VM_CONTEXT0_CNTL2, 0);
- WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT));
+ WREG32(mmVM_CONTEXT0_CNTL2, 0);
+ WREG32(mmVM_CONTEXT0_CNTL,
+ VM_CONTEXT0_CNTL__ENABLE_CONTEXT_MASK |
+ (0UL << VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH__SHIFT) |
+ VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK);
WREG32(0x575, 0);
WREG32(0x576, 0);
@@ -417,39 +441,41 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
/* empty context1-15 */
/* set vm size, must be a multiple of 4 */
- WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1);
+ WREG32(mmVM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
+ WREG32(mmVM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1);
/* Assign the pt base to something valid for now; the pts used for
* the VMs are determined by the application and setup and assigned
* on the fly in the vm part of radeon_gart.c
*/
for (i = 1; i < 16; i++) {
if (i < 8)
- WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i,
+ WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i,
adev->gart.table_addr >> 12);
else
- WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8,
+ WREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8,
adev->gart.table_addr >> 12);
}
/* enable context1-15 */
- WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
+ WREG32(mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(adev->dummy_page.addr >> 12));
- WREG32(VM_CONTEXT1_CNTL2, 4);
- WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
- PAGE_TABLE_BLOCK_SIZE(amdgpu_vm_block_size - 9) |
- RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT |
- PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT |
- PDE0_PROTECTION_FAULT_ENABLE_DEFAULT |
- VALID_PROTECTION_FAULT_ENABLE_INTERRUPT |
- VALID_PROTECTION_FAULT_ENABLE_DEFAULT |
- READ_PROTECTION_FAULT_ENABLE_INTERRUPT |
- READ_PROTECTION_FAULT_ENABLE_DEFAULT |
- WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
- WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
+ WREG32(mmVM_CONTEXT1_CNTL2, 4);
+ WREG32(mmVM_CONTEXT1_CNTL,
+ VM_CONTEXT1_CNTL__ENABLE_CONTEXT_MASK |
+ (1UL << VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH__SHIFT) |
+ ((amdgpu_vm_block_size - 9) << VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT) |
+ VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
+ VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
+ VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
+ VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
+ VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
+ VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK);
gmc_v6_0_gart_flush_gpu_tlb(adev, 0);
dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n",
@@ -488,19 +514,22 @@ static void gmc_v6_0_gart_disable(struct amdgpu_device *adev)
}*/
/* Disable all tables */
- WREG32(VM_CONTEXT0_CNTL, 0);
- WREG32(VM_CONTEXT1_CNTL, 0);
+ WREG32(mmVM_CONTEXT0_CNTL, 0);
+ WREG32(mmVM_CONTEXT1_CNTL, 0);
/* Setup TLB control */
- WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS |
- SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+ WREG32(mmMC_VM_MX_L1_TLB_CNTL,
+ MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK |
+ (0UL << MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT));
/* Setup L2 cache */
- WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
- ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
- EFFECTIVE_L2_QUEUE_SIZE(7) |
- CONTEXT1_IDENTITY_ACCESS_MODE(1));
- WREG32(VM_L2_CNTL2, 0);
- WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
- L2_CACHE_BIGK_FRAGMENT_SIZE(0));
+ WREG32(mmVM_L2_CNTL,
+ VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+ VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+ (7UL << VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT) |
+ (1UL << VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT));
+ WREG32(mmVM_L2_CNTL2, 0);
+ WREG32(mmVM_L2_CNTL3,
+ VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK |
+ (0UL << VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT));
amdgpu_gart_table_vram_unpin(adev);
}
@@ -523,7 +552,7 @@ static int gmc_v6_0_vm_init(struct amdgpu_device *adev)
/* base offset of vram pages */
if (adev->flags & AMD_IS_APU) {
- u64 tmp = RREG32(MC_VM_FB_OFFSET);
+ u64 tmp = RREG32(mmMC_VM_FB_OFFSET);
tmp <<= 22;
adev->vm_manager.vram_base_offset = tmp;
} else
@@ -540,19 +569,19 @@ static void gmc_v6_0_vm_decode_fault(struct amdgpu_device *adev,
u32 status, u32 addr, u32 mc_client)
{
u32 mc_id;
- u32 vmid = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, xxVMID);
- u32 protections = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
- xxPROTECTIONS);
+ u32 vmid = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
+ u32 protections = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+ PROTECTIONS);
char block[5] = { mc_client >> 24, (mc_client >> 16) & 0xff,
(mc_client >> 8) & 0xff, mc_client & 0xff, 0 };
- mc_id = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
- xxMEMORY_CLIENT_ID);
+ mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+ MEMORY_CLIENT_ID);
dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
protections, vmid, addr,
- REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
- xxMEMORY_CLIENT_RW) ?
+ REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+ MEMORY_CLIENT_RW) ?
"write" : "read", block, mc_client, mc_id);
}
@@ -655,7 +684,7 @@ static void gmc_v6_0_enable_hdp_mgcg(struct amdgpu_device *adev,
{
u32 orig, data;
- orig = data = RREG32(HDP_HOST_PATH_CNTL);
+ orig = data = RREG32(mmHDP_HOST_PATH_CNTL);
if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_MGCG))
data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 0);
@@ -663,7 +692,7 @@ static void gmc_v6_0_enable_hdp_mgcg(struct amdgpu_device *adev,
data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 1);
if (orig != data)
- WREG32(HDP_HOST_PATH_CNTL, data);
+ WREG32(mmHDP_HOST_PATH_CNTL, data);
}
static void gmc_v6_0_enable_hdp_ls(struct amdgpu_device *adev,
@@ -671,7 +700,7 @@ static void gmc_v6_0_enable_hdp_ls(struct amdgpu_device *adev,
{
u32 orig, data;
- orig = data = RREG32(HDP_MEM_POWER_LS);
+ orig = data = RREG32(mmHDP_MEM_POWER_LS);
if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_LS))
data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 1);
@@ -679,7 +708,7 @@ static void gmc_v6_0_enable_hdp_ls(struct amdgpu_device *adev,
data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 0);
if (orig != data)
- WREG32(HDP_MEM_POWER_LS, data);
+ WREG32(mmHDP_MEM_POWER_LS, data);
}
*/
@@ -713,7 +742,7 @@ static int gmc_v6_0_early_init(void *handle)
if (adev->flags & AMD_IS_APU) {
adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
} else {
- u32 tmp = RREG32(MC_SEQ_MISC0);
+ u32 tmp = RREG32(mmMC_SEQ_MISC0);
tmp &= MC_SEQ_MISC0__MT__MASK;
adev->mc.vram_type = gmc_v6_0_convert_vram_type(tmp);
}
@@ -766,11 +795,6 @@ static int gmc_v6_0_sw_init(void *handle)
return r;
}
- r = amdgpu_ttm_global_init(adev);
- if (r) {
- return r;
- }
-
r = gmc_v6_0_mc_init(adev);
if (r)
return r;
@@ -879,7 +903,7 @@ static int gmc_v6_0_resume(void *handle)
static bool gmc_v6_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- u32 tmp = RREG32(SRBM_STATUS);
+ u32 tmp = RREG32(mmSRBM_STATUS);
if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK | SRBM_STATUS__VMC_BUSY_MASK))
@@ -895,7 +919,7 @@ static int gmc_v6_0_wait_for_idle(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
for (i = 0; i < adev->usec_timeout; i++) {
- tmp = RREG32(SRBM_STATUS) & (SRBM_STATUS__MCB_BUSY_MASK |
+ tmp = RREG32(mmSRBM_STATUS) & (SRBM_STATUS__MCB_BUSY_MASK |
SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
SRBM_STATUS__MCC_BUSY_MASK |
SRBM_STATUS__MCD_BUSY_MASK |
@@ -913,17 +937,17 @@ static int gmc_v6_0_soft_reset(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_mode_mc_save save;
u32 srbm_soft_reset = 0;
- u32 tmp = RREG32(SRBM_STATUS);
+ u32 tmp = RREG32(mmSRBM_STATUS);
if (tmp & SRBM_STATUS__VMC_BUSY_MASK)
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,
- mmSRBM_SOFT_RESET, xxSOFT_RESET_VMC, 1);
+ SRBM_SOFT_RESET, SOFT_RESET_VMC, 1);
if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK)) {
if (!(adev->flags & AMD_IS_APU))
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,
- mmSRBM_SOFT_RESET, xxSOFT_RESET_MC, 1);
+ SRBM_SOFT_RESET, SOFT_RESET_MC, 1);
}
if (srbm_soft_reset) {
@@ -933,17 +957,17 @@ static int gmc_v6_0_soft_reset(void *handle)
}
- tmp = RREG32(SRBM_SOFT_RESET);
+ tmp = RREG32(mmSRBM_SOFT_RESET);
tmp |= srbm_soft_reset;
dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
- WREG32(SRBM_SOFT_RESET, tmp);
- tmp = RREG32(SRBM_SOFT_RESET);
+ WREG32(mmSRBM_SOFT_RESET, tmp);
+ tmp = RREG32(mmSRBM_SOFT_RESET);
udelay(50);
tmp &= ~srbm_soft_reset;
- WREG32(SRBM_SOFT_RESET, tmp);
- tmp = RREG32(SRBM_SOFT_RESET);
+ WREG32(mmSRBM_SOFT_RESET, tmp);
+ tmp = RREG32(mmSRBM_SOFT_RESET);
udelay(50);
@@ -969,20 +993,20 @@ static int gmc_v6_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- tmp = RREG32(VM_CONTEXT0_CNTL);
+ tmp = RREG32(mmVM_CONTEXT0_CNTL);
tmp &= ~bits;
- WREG32(VM_CONTEXT0_CNTL, tmp);
- tmp = RREG32(VM_CONTEXT1_CNTL);
+ WREG32(mmVM_CONTEXT0_CNTL, tmp);
+ tmp = RREG32(mmVM_CONTEXT1_CNTL);
tmp &= ~bits;
- WREG32(VM_CONTEXT1_CNTL, tmp);
+ WREG32(mmVM_CONTEXT1_CNTL, tmp);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- tmp = RREG32(VM_CONTEXT0_CNTL);
+ tmp = RREG32(mmVM_CONTEXT0_CNTL);
tmp |= bits;
- WREG32(VM_CONTEXT0_CNTL, tmp);
- tmp = RREG32(VM_CONTEXT1_CNTL);
+ WREG32(mmVM_CONTEXT0_CNTL, tmp);
+ tmp = RREG32(mmVM_CONTEXT1_CNTL);
tmp |= bits;
- WREG32(VM_CONTEXT1_CNTL, tmp);
+ WREG32(mmVM_CONTEXT1_CNTL, tmp);
break;
default:
break;
@@ -997,9 +1021,9 @@ static int gmc_v6_0_process_interrupt(struct amdgpu_device *adev,
{
u32 addr, status;
- addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR);
- status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS);
- WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
+ addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
+ status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
+ WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
if (!addr && !status)
return 0;
@@ -1007,13 +1031,15 @@ static int gmc_v6_0_process_interrupt(struct amdgpu_device *adev,
if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
gmc_v6_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",
- addr);
- dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
- status);
- gmc_v6_0_vm_decode_fault(adev, status, addr, 0);
+ if (printk_ratelimit()) {
+ 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",
+ addr);
+ dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+ status);
+ gmc_v6_0_vm_decode_fault(adev, status, addr, 0);
+ }
return 0;
}
@@ -1030,7 +1056,7 @@ static int gmc_v6_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs gmc_v6_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v6_0_ip_funcs = {
.name = "gmc_v6_0",
.early_init = gmc_v6_0_early_init,
.late_init = gmc_v6_0_late_init,
@@ -1069,3 +1095,11 @@ static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev)
adev->mc.vm_fault.funcs = &gmc_v6_0_irq_funcs;
}
+const struct amdgpu_ip_block_version gmc_v6_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 6,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gmc_v6_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h
index 42c4fc676cd4..ed2f64dec47a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h
@@ -24,6 +24,6 @@
#ifndef __GMC_V6_0_H__
#define __GMC_V6_0_H__
-extern const struct amd_ip_funcs gmc_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v6_0_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index aa0c4b964621..273b16fb9459 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -385,7 +385,7 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
* size equal to the 1024 or vram, whichever is larger.
*/
if (amdgpu_gart_size == -1)
- adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+ adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
else
adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
@@ -711,7 +711,7 @@ static void gmc_v7_0_vm_decode_fault(struct amdgpu_device *adev,
mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
MEMORY_CLIENT_ID);
- printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
+ dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
protections, vmid, addr,
REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
MEMORY_CLIENT_RW) ?
@@ -945,11 +945,6 @@ static int gmc_v7_0_sw_init(void *handle)
return r;
}
- r = amdgpu_ttm_global_init(adev);
- if (r) {
- return r;
- }
-
r = gmc_v7_0_mc_init(adev);
if (r)
return r;
@@ -1198,13 +1193,15 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
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",
- addr);
- dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
- status);
- gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
+ if (printk_ratelimit()) {
+ 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",
+ addr);
+ dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+ status);
+ gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
+ }
return 0;
}
@@ -1235,7 +1232,7 @@ static int gmc_v7_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
.name = "gmc_v7_0",
.early_init = gmc_v7_0_early_init,
.late_init = gmc_v7_0_late_init,
@@ -1273,3 +1270,21 @@ static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev)
adev->mc.vm_fault.num_types = 1;
adev->mc.vm_fault.funcs = &gmc_v7_0_irq_funcs;
}
+
+const struct amdgpu_ip_block_version gmc_v7_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 7,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gmc_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v7_4_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 7,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &gmc_v7_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h
index 0b386b5d2f7a..ebce2966c1c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h
@@ -24,6 +24,7 @@
#ifndef __GMC_V7_0_H__
#define __GMC_V7_0_H__
-extern const struct amd_ip_funcs gmc_v7_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v7_0_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v7_4_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index a16b2201d52c..0daac3a5be79 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -472,7 +472,7 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
* size equal to the 1024 or vram, whichever is larger.
*/
if (amdgpu_gart_size == -1)
- adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+ adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
else
adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
@@ -837,7 +837,7 @@ static void gmc_v8_0_vm_decode_fault(struct amdgpu_device *adev,
mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
MEMORY_CLIENT_ID);
- printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
+ dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
protections, vmid, addr,
REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
MEMORY_CLIENT_RW) ?
@@ -952,11 +952,6 @@ static int gmc_v8_0_sw_init(void *handle)
return r;
}
- r = amdgpu_ttm_global_init(adev);
- if (r) {
- return r;
- }
-
r = gmc_v8_0_mc_init(adev);
if (r)
return r;
@@ -1242,13 +1237,15 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
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",
- addr);
- dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
- status);
- gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
+ if (printk_ratelimit()) {
+ 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",
+ addr);
+ dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+ status);
+ gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
+ }
return 0;
}
@@ -1437,7 +1434,7 @@ static int gmc_v8_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
.name = "gmc_v8_0",
.early_init = gmc_v8_0_early_init,
.late_init = gmc_v8_0_late_init,
@@ -1478,3 +1475,30 @@ static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev)
adev->mc.vm_fault.num_types = 1;
adev->mc.vm_fault.funcs = &gmc_v8_0_irq_funcs;
}
+
+const struct amdgpu_ip_block_version gmc_v8_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 8,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &gmc_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v8_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 8,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &gmc_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v8_5_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+ .major = 8,
+ .minor = 5,
+ .rev = 0,
+ .funcs = &gmc_v8_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h
index fc5001a8119d..19b8a8aed204 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h
@@ -24,6 +24,8 @@
#ifndef __GMC_V8_0_H__
#define __GMC_V8_0_H__
-extern const struct amd_ip_funcs gmc_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v8_1_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v8_5_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
index 3b8906ce3511..ac21bb7bc0f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
@@ -392,7 +392,7 @@ static int iceland_ih_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs iceland_ih_ip_funcs = {
+static const struct amd_ip_funcs iceland_ih_ip_funcs = {
.name = "iceland_ih",
.early_init = iceland_ih_early_init,
.late_init = NULL,
@@ -421,3 +421,11 @@ static void iceland_ih_set_interrupt_funcs(struct amdgpu_device *adev)
adev->irq.ih_funcs = &iceland_ih_funcs;
}
+const struct amdgpu_ip_block_version iceland_ih_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_IH,
+ .major = 2,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &iceland_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.h b/drivers/gpu/drm/amd/amdgpu/iceland_ih.h
index 57558cddfbcb..3235f4277548 100644
--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.h
@@ -24,6 +24,6 @@
#ifndef __ICELAND_IH_H__
#define __ICELAND_IH_H__
-extern const struct amd_ip_funcs iceland_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version iceland_ih_ip_block;
#endif /* __ICELAND_IH_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 71d2856222fa..5a1bc358bcb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2796,7 +2796,7 @@ static int kv_parse_power_table(struct amdgpu_device *adev)
adev->pm.dpm.num_ps = state_array->ucNumEntries;
/* fill in the vce power states */
- for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+ for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
u32 sclk;
clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
clock_info = (union pplib_clock_info *)
@@ -2845,7 +2845,7 @@ static int kv_dpm_init(struct amdgpu_device *adev)
pi->caps_tcp_ramping = true;
}
- if (amdgpu_sclk_deep_sleep_en)
+ if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
@@ -3245,6 +3245,18 @@ static int kv_dpm_set_powergating_state(void *handle,
return 0;
}
+static int kv_check_state_equal(struct amdgpu_device *adev,
+ struct amdgpu_ps *cps,
+ struct amdgpu_ps *rps,
+ bool *equal)
+{
+ if (equal == NULL)
+ return -EINVAL;
+
+ *equal = false;
+ return 0;
+}
+
const struct amd_ip_funcs kv_dpm_ip_funcs = {
.name = "kv_dpm",
.early_init = kv_dpm_early_init,
@@ -3275,6 +3287,8 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = {
.force_performance_level = &kv_dpm_force_performance_level,
.powergate_uvd = &kv_dpm_powergate_uvd,
.enable_bapm = &kv_dpm_enable_bapm,
+ .get_vce_clock_state = amdgpu_get_vce_clock_state,
+ .check_state_equal = kv_check_state_equal,
};
static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -3293,3 +3307,12 @@ static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev)
adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs;
}
+
+const struct amdgpu_ip_block_version kv_dpm_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SMC,
+ .major = 7,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &kv_dpm_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index 565dab3c7218..fbe74a33899c 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -232,10 +232,10 @@ static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
for (i = 0; i < count; i++)
if (sdma && sdma->burst_nop && (i == 0))
- amdgpu_ring_write(ring, ring->nop |
+ amdgpu_ring_write(ring, ring->funcs->nop |
SDMA_PKT_NOP_HEADER_COUNT(count - 1));
else
- amdgpu_ring_write(ring, ring->nop);
+ amdgpu_ring_write(ring, ring->funcs->nop);
}
/**
@@ -668,7 +668,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
unsigned index;
u32 tmp = 0;
u64 gpu_addr;
@@ -705,7 +705,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err1;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -725,7 +725,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout)
err1:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err0:
amdgpu_wb_free(adev, index);
return r;
@@ -775,11 +775,11 @@ static void sdma_v2_4_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
unsigned ndw = count * 2;
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
- SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
+ SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
ib->ptr[ib->length_dw++] = pe;
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
- for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ for (; ndw > 0; ndw -= 2) {
ib->ptr[ib->length_dw++] = lower_32_bits(value);
ib->ptr[ib->length_dw++] = upper_32_bits(value);
value += incr;
@@ -902,22 +902,6 @@ static void sdma_v2_4_ring_emit_vm_flush(struct amdgpu_ring *ring,
SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
}
-static unsigned sdma_v2_4_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 7 + 6; /* sdma_v2_4_ring_emit_ib */
-}
-
-static unsigned sdma_v2_4_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 6 + /* sdma_v2_4_ring_emit_hdp_flush */
- 3 + /* sdma_v2_4_ring_emit_hdp_invalidate */
- 6 + /* sdma_v2_4_ring_emit_pipeline_sync */
- 12 + /* sdma_v2_4_ring_emit_vm_flush */
- 10 + 10 + 10; /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */
-}
-
static int sdma_v2_4_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -965,11 +949,10 @@ static int sdma_v2_4_sw_init(void *handle)
ring->use_doorbell = false;
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 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);
+ AMDGPU_SDMA_IRQ_TRAP0 :
+ AMDGPU_SDMA_IRQ_TRAP1);
if (r)
return r;
}
@@ -1204,7 +1187,7 @@ static int sdma_v2_4_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
+static const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
.name = "sdma_v2_4",
.early_init = sdma_v2_4_early_init,
.late_init = NULL,
@@ -1222,10 +1205,19 @@ const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
};
static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_SDMA,
+ .align_mask = 0xf,
+ .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.get_rptr = sdma_v2_4_ring_get_rptr,
.get_wptr = sdma_v2_4_ring_get_wptr,
.set_wptr = sdma_v2_4_ring_set_wptr,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 6 + /* sdma_v2_4_ring_emit_hdp_flush */
+ 3 + /* sdma_v2_4_ring_emit_hdp_invalidate */
+ 6 + /* sdma_v2_4_ring_emit_pipeline_sync */
+ 12 + /* sdma_v2_4_ring_emit_vm_flush */
+ 10 + 10 + 10, /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */
+ .emit_ib_size = 7 + 6, /* sdma_v2_4_ring_emit_ib */
.emit_ib = sdma_v2_4_ring_emit_ib,
.emit_fence = sdma_v2_4_ring_emit_fence,
.emit_pipeline_sync = sdma_v2_4_ring_emit_pipeline_sync,
@@ -1236,8 +1228,6 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
.test_ib = sdma_v2_4_ring_test_ib,
.insert_nop = sdma_v2_4_ring_insert_nop,
.pad_ib = sdma_v2_4_ring_pad_ib,
- .get_emit_ib_size = sdma_v2_4_ring_get_emit_ib_size,
- .get_dma_frame_size = sdma_v2_4_ring_get_dma_frame_size,
};
static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev)
@@ -1350,3 +1340,12 @@ static void sdma_v2_4_set_vm_pte_funcs(struct amdgpu_device *adev)
adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
}
}
+
+const struct amdgpu_ip_block_version sdma_v2_4_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SDMA,
+ .major = 2,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &sdma_v2_4_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h
index 07349f5ee10f..28b433729216 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h
@@ -24,6 +24,6 @@
#ifndef __SDMA_V2_4_H__
#define __SDMA_V2_4_H__
-extern const struct amd_ip_funcs sdma_v2_4_ip_funcs;
+extern const struct amdgpu_ip_block_version sdma_v2_4_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index a9d10941fb53..1170a64a3184 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -392,10 +392,10 @@ static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
for (i = 0; i < count; i++)
if (sdma && sdma->burst_nop && (i == 0))
- amdgpu_ring_write(ring, ring->nop |
+ amdgpu_ring_write(ring, ring->funcs->nop |
SDMA_PKT_NOP_HEADER_COUNT(count - 1));
else
- amdgpu_ring_write(ring, ring->nop);
+ amdgpu_ring_write(ring, ring->funcs->nop);
}
/**
@@ -871,7 +871,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
unsigned index;
u32 tmp = 0;
u64 gpu_addr;
@@ -908,7 +908,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err1;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -927,7 +927,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
}
err1:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err0:
amdgpu_wb_free(adev, index);
return r;
@@ -977,11 +977,11 @@ static void sdma_v3_0_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
unsigned ndw = count * 2;
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
- SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
+ SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
- for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ for (; ndw > 0; ndw -= 2) {
ib->ptr[ib->length_dw++] = lower_32_bits(value);
ib->ptr[ib->length_dw++] = upper_32_bits(value);
value += incr;
@@ -1104,22 +1104,6 @@ static void sdma_v3_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
}
-static unsigned sdma_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 7 + 6; /* sdma_v3_0_ring_emit_ib */
-}
-
-static unsigned sdma_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 6 + /* sdma_v3_0_ring_emit_hdp_flush */
- 3 + /* sdma_v3_0_ring_emit_hdp_invalidate */
- 6 + /* sdma_v3_0_ring_emit_pipeline_sync */
- 12 + /* sdma_v3_0_ring_emit_vm_flush */
- 10 + 10 + 10; /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
-}
-
static int sdma_v3_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1177,11 +1161,10 @@ static int sdma_v3_0_sw_init(void *handle)
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 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);
+ AMDGPU_SDMA_IRQ_TRAP0 :
+ AMDGPU_SDMA_IRQ_TRAP1);
if (r)
return r;
}
@@ -1544,7 +1527,7 @@ static int sdma_v3_0_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
+static const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
.name = "sdma_v3_0",
.early_init = sdma_v3_0_early_init,
.late_init = NULL,
@@ -1565,10 +1548,19 @@ const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_SDMA,
+ .align_mask = 0xf,
+ .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.get_rptr = sdma_v3_0_ring_get_rptr,
.get_wptr = sdma_v3_0_ring_get_wptr,
.set_wptr = sdma_v3_0_ring_set_wptr,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 6 + /* sdma_v3_0_ring_emit_hdp_flush */
+ 3 + /* sdma_v3_0_ring_emit_hdp_invalidate */
+ 6 + /* sdma_v3_0_ring_emit_pipeline_sync */
+ 12 + /* sdma_v3_0_ring_emit_vm_flush */
+ 10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
+ .emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */
.emit_ib = sdma_v3_0_ring_emit_ib,
.emit_fence = sdma_v3_0_ring_emit_fence,
.emit_pipeline_sync = sdma_v3_0_ring_emit_pipeline_sync,
@@ -1579,8 +1571,6 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.test_ib = sdma_v3_0_ring_test_ib,
.insert_nop = sdma_v3_0_ring_insert_nop,
.pad_ib = sdma_v3_0_ring_pad_ib,
- .get_emit_ib_size = sdma_v3_0_ring_get_emit_ib_size,
- .get_dma_frame_size = sdma_v3_0_ring_get_dma_frame_size,
};
static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -1693,3 +1683,21 @@ static void sdma_v3_0_set_vm_pte_funcs(struct amdgpu_device *adev)
adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
}
}
+
+const struct amdgpu_ip_block_version sdma_v3_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SDMA,
+ .major = 3,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &sdma_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version sdma_v3_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SDMA,
+ .major = 3,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &sdma_v3_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h
index 0cb9698a3054..7aa223d35f1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h
@@ -24,6 +24,7 @@
#ifndef __SDMA_V3_0_H__
#define __SDMA_V3_0_H__
-extern const struct amd_ip_funcs sdma_v3_0_ip_funcs;
+extern const struct amdgpu_ip_block_version sdma_v3_0_ip_block;
+extern const struct amdgpu_ip_block_version sdma_v3_1_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index dc9511c5ecb8..3ed8ad8725b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -39,6 +39,7 @@
#include "si_dma.h"
#include "dce_v6_0.h"
#include "si.h"
+#include "dce_virtual.h"
static const u32 tahiti_golden_registers[] =
{
@@ -905,7 +906,7 @@ static void si_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}
-u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg)
+static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long flags;
u32 r;
@@ -918,7 +919,7 @@ u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg)
return r;
}
-void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
+static void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
{
unsigned long flags;
@@ -1811,7 +1812,7 @@ static int si_common_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs si_common_ip_funcs = {
+static const struct amd_ip_funcs si_common_ip_funcs = {
.name = "si_common",
.early_init = si_common_early_init,
.late_init = NULL,
@@ -1828,119 +1829,13 @@ const struct amd_ip_funcs si_common_ip_funcs = {
.set_powergating_state = si_common_set_powergating_state,
};
-static const struct amdgpu_ip_block_version verde_ip_blocks[] =
+static const struct amdgpu_ip_block_version si_common_ip_block =
{
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_dma_ip_funcs,
- },
-/* {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 3,
- .minor = 1,
- .rev = 0,
- .funcs = &si_null_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_null_ip_funcs,
- },
- */
-};
-
-
-static const struct amdgpu_ip_block_version hainan_ip_blocks[] =
-{
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &si_dma_ip_funcs,
- },
+ .type = AMD_IP_BLOCK_TYPE_COMMON,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &si_common_ip_funcs,
};
int si_set_ip_blocks(struct amdgpu_device *adev)
@@ -1949,13 +1844,42 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
case CHIP_VERDE:
case CHIP_TAHITI:
case CHIP_PITCAIRN:
+ amdgpu_ip_block_add(adev, &si_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_dma_ip_block);
+ /* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */
+ /* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */
+ break;
case CHIP_OLAND:
- adev->ip_blocks = verde_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks);
+ amdgpu_ip_block_add(adev, &si_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v6_4_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_dma_ip_block);
+ /* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */
+ /* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */
break;
case CHIP_HAINAN:
- adev->ip_blocks = hainan_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks);
+ amdgpu_ip_block_add(adev, &si_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &si_dma_ip_block);
break;
default:
BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/si.h b/drivers/gpu/drm/amd/amdgpu/si.h
index 959d7b63e0e5..589225080c24 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.h
+++ b/drivers/gpu/drm/amd/amdgpu/si.h
@@ -24,8 +24,6 @@
#ifndef __SI_H__
#define __SI_H__
-extern const struct amd_ip_funcs si_common_ip_funcs;
-
void si_srbm_select(struct amdgpu_device *adev,
u32 me, u32 pipe, u32 queue, u32 vmid);
int si_set_ip_blocks(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index de358193a8f9..3dd552ae0b59 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -274,7 +274,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib ib;
- struct fence *f = NULL;
+ struct dma_fence *f = NULL;
unsigned index;
u32 tmp = 0;
u64 gpu_addr;
@@ -305,7 +305,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
if (r)
goto err1;
- r = fence_wait_timeout(f, false, timeout);
+ r = dma_fence_wait_timeout(f, false, timeout);
if (r == 0) {
DRM_ERROR("amdgpu: IB test timed out\n");
r = -ETIMEDOUT;
@@ -325,7 +325,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
err1:
amdgpu_ib_free(adev, &ib, NULL);
- fence_put(f);
+ dma_fence_put(f);
err0:
amdgpu_wb_free(adev, index);
return r;
@@ -495,22 +495,6 @@ static void si_dma_ring_emit_vm_flush(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */
}
-static unsigned si_dma_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 7 + 3; /* si_dma_ring_emit_ib */
-}
-
-static unsigned si_dma_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 3 + /* si_dma_ring_emit_hdp_flush */
- 3 + /* si_dma_ring_emit_hdp_invalidate */
- 6 + /* si_dma_ring_emit_pipeline_sync */
- 12 + /* si_dma_ring_emit_vm_flush */
- 9 + 9 + 9; /* si_dma_ring_emit_fence x3 for user fence, vm fence */
-}
-
static int si_dma_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -547,11 +531,10 @@ static int si_dma_sw_init(void *handle)
ring->use_doorbell = false;
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 1024,
- DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), 0xf,
&adev->sdma.trap_irq,
(i == 0) ?
- AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
- AMDGPU_RING_TYPE_SDMA);
+ AMDGPU_SDMA_IRQ_TRAP0 :
+ AMDGPU_SDMA_IRQ_TRAP1);
if (r)
return r;
}
@@ -762,7 +745,7 @@ static int si_dma_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs si_dma_ip_funcs = {
+static const struct amd_ip_funcs si_dma_ip_funcs = {
.name = "si_dma",
.early_init = si_dma_early_init,
.late_init = NULL,
@@ -780,10 +763,19 @@ const struct amd_ip_funcs si_dma_ip_funcs = {
};
static const struct amdgpu_ring_funcs si_dma_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_SDMA,
+ .align_mask = 0xf,
+ .nop = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0),
.get_rptr = si_dma_ring_get_rptr,
.get_wptr = si_dma_ring_get_wptr,
.set_wptr = si_dma_ring_set_wptr,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 3 + /* si_dma_ring_emit_hdp_flush */
+ 3 + /* si_dma_ring_emit_hdp_invalidate */
+ 6 + /* si_dma_ring_emit_pipeline_sync */
+ 12 + /* si_dma_ring_emit_vm_flush */
+ 9 + 9 + 9, /* si_dma_ring_emit_fence x3 for user fence, vm fence */
+ .emit_ib_size = 7 + 3, /* si_dma_ring_emit_ib */
.emit_ib = si_dma_ring_emit_ib,
.emit_fence = si_dma_ring_emit_fence,
.emit_pipeline_sync = si_dma_ring_emit_pipeline_sync,
@@ -794,8 +786,6 @@ static const struct amdgpu_ring_funcs si_dma_ring_funcs = {
.test_ib = si_dma_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
.pad_ib = si_dma_ring_pad_ib,
- .get_emit_ib_size = si_dma_ring_get_emit_ib_size,
- .get_dma_frame_size = si_dma_ring_get_dma_frame_size,
};
static void si_dma_set_ring_funcs(struct amdgpu_device *adev)
@@ -913,3 +903,12 @@ static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev)
adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
}
}
+
+const struct amdgpu_ip_block_version si_dma_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SDMA,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &si_dma_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.h b/drivers/gpu/drm/amd/amdgpu/si_dma.h
index 3a3e0c78a54b..5ac1b8452fb4 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.h
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.h
@@ -24,6 +24,6 @@
#ifndef __SI_DMA_H__
#define __SI_DMA_H__
-extern const struct amd_ip_funcs si_dma_ip_funcs;
+extern const struct amdgpu_ip_block_version si_dma_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
index d6f85b1a0b93..6c65a1a2de79 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
@@ -3171,6 +3171,7 @@ static void ni_update_current_ps(struct amdgpu_device *adev,
eg_pi->current_rps = *rps;
ni_pi->current_ps = *new_ps;
eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
+ adev->pm.dpm.current_ps = &eg_pi->current_rps;
}
static void ni_update_requested_ps(struct amdgpu_device *adev,
@@ -3183,6 +3184,7 @@ static void ni_update_requested_ps(struct amdgpu_device *adev,
eg_pi->requested_rps = *rps;
ni_pi->requested_ps = *new_ps;
eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
+ adev->pm.dpm.requested_ps = &eg_pi->requested_rps;
}
static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev,
@@ -3504,6 +3506,7 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
(adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83) ||
+ (adev->pdev->revision == 0x87) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605)) {
max_sclk = 75000;
@@ -7347,7 +7350,7 @@ static int si_parse_power_table(struct amdgpu_device *adev)
adev->pm.dpm.num_ps = state_array->ucNumEntries;
/* fill in the vce power states */
- for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+ for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
u32 sclk, mclk;
clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
clock_info = (union pplib_clock_info *)
@@ -7713,6 +7716,7 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev)
(adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83) ||
+ (adev->pdev->revision == 0x87) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605))
chip_name = "oland_k";
@@ -7986,6 +7990,57 @@ static int si_dpm_early_init(void *handle)
return 0;
}
+static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1,
+ const struct rv7xx_pl *si_cpl2)
+{
+ return ((si_cpl1->mclk == si_cpl2->mclk) &&
+ (si_cpl1->sclk == si_cpl2->sclk) &&
+ (si_cpl1->pcie_gen == si_cpl2->pcie_gen) &&
+ (si_cpl1->vddc == si_cpl2->vddc) &&
+ (si_cpl1->vddci == si_cpl2->vddci));
+}
+
+static int si_check_state_equal(struct amdgpu_device *adev,
+ struct amdgpu_ps *cps,
+ struct amdgpu_ps *rps,
+ bool *equal)
+{
+ struct si_ps *si_cps;
+ struct si_ps *si_rps;
+ int i;
+
+ if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
+ return -EINVAL;
+
+ si_cps = si_get_ps(cps);
+ si_rps = si_get_ps(rps);
+
+ if (si_cps == NULL) {
+ printk("si_cps is NULL\n");
+ *equal = false;
+ return 0;
+ }
+
+ if (si_cps->performance_level_count != si_rps->performance_level_count) {
+ *equal = false;
+ return 0;
+ }
+
+ for (i = 0; i < si_cps->performance_level_count; i++) {
+ if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]),
+ &(si_rps->performance_levels[i]))) {
+ *equal = false;
+ return 0;
+ }
+ }
+
+ /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+ *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
+ *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
+
+ return 0;
+}
+
const struct amd_ip_funcs si_dpm_ip_funcs = {
.name = "si_dpm",
@@ -8020,6 +8075,8 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = {
.get_fan_control_mode = &si_dpm_get_fan_control_mode,
.set_fan_speed_percent = &si_dpm_set_fan_speed_percent,
.get_fan_speed_percent = &si_dpm_get_fan_speed_percent,
+ .check_state_equal = &si_check_state_equal,
+ .get_vce_clock_state = amdgpu_get_vce_clock_state,
};
static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -8039,3 +8096,11 @@ static void si_dpm_set_irq_funcs(struct amdgpu_device *adev)
adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs;
}
+const struct amdgpu_ip_block_version si_dpm_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_SMC,
+ .major = 6,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &si_dpm_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/si_enums.h b/drivers/gpu/drm/amd/amdgpu/si_enums.h
new file mode 100644
index 000000000000..fde2086246fa
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/si_enums.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2016 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) 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.
+ *
+ */
+#ifndef SI_ENUMS_H
+#define SI_ENUMS_H
+
+#define VBLANK_INT_MASK (1 << 0)
+#define DC_HPDx_INT_EN (1 << 16)
+#define VBLANK_ACK (1 << 4)
+#define VLINE_ACK (1 << 4)
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+#define VGA_VSTATUS_CNTL 0xFFFCFFFF
+#define PRIORITY_MARK_MASK 0x7fff
+#define PRIORITY_OFF (1 << 16)
+#define PRIORITY_ALWAYS_ON (1 << 20)
+#define INTERLEAVE_EN (1 << 0)
+
+#define LATENCY_WATERMARK_MASK(x) ((x) << 16)
+#define DC_LB_MEMORY_CONFIG(x) ((x) << 20)
+#define ICON_DEGAMMA_MODE(x) (((x) & 0x3) << 8)
+
+#define GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0)
+#define GRPH_ENDIAN_NONE 0
+#define GRPH_ENDIAN_8IN16 1
+#define GRPH_ENDIAN_8IN32 2
+#define GRPH_ENDIAN_8IN64 3
+
+#define GRPH_DEPTH(x) (((x) & 0x3) << 0)
+#define GRPH_DEPTH_8BPP 0
+#define GRPH_DEPTH_16BPP 1
+#define GRPH_DEPTH_32BPP 2
+
+#define GRPH_FORMAT(x) (((x) & 0x7) << 8)
+#define GRPH_FORMAT_INDEXED 0
+#define GRPH_FORMAT_ARGB1555 0
+#define GRPH_FORMAT_ARGB565 1
+#define GRPH_FORMAT_ARGB4444 2
+#define GRPH_FORMAT_AI88 3
+#define GRPH_FORMAT_MONO16 4
+#define GRPH_FORMAT_BGRA5551 5
+#define GRPH_FORMAT_ARGB8888 0
+#define GRPH_FORMAT_ARGB2101010 1
+#define GRPH_FORMAT_32BPP_DIG 2
+#define GRPH_FORMAT_8B_ARGB2101010 3
+#define GRPH_FORMAT_BGRA1010102 4
+#define GRPH_FORMAT_8B_BGRA1010102 5
+#define GRPH_FORMAT_RGB111110 6
+#define GRPH_FORMAT_BGR101111 7
+
+#define GRPH_NUM_BANKS(x) (((x) & 0x3) << 2)
+#define GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20)
+#define GRPH_ARRAY_LINEAR_GENERAL 0
+#define GRPH_ARRAY_LINEAR_ALIGNED 1
+#define GRPH_ARRAY_1D_TILED_THIN1 2
+#define GRPH_ARRAY_2D_TILED_THIN1 4
+#define GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13)
+#define GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6)
+#define GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11)
+#define GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18)
+#define GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20)
+#define GRPH_PIPE_CONFIG(x) (((x) & 0x1f) << 24)
+
+#define CURSOR_EN (1 << 0)
+#define CURSOR_MODE(x) (((x) & 0x3) << 8)
+#define CURSOR_MONO 0
+#define CURSOR_24_1 1
+#define CURSOR_24_8_PRE_MULT 2
+#define CURSOR_24_8_UNPRE_MULT 3
+#define CURSOR_2X_MAGNIFY (1 << 16)
+#define CURSOR_FORCE_MC_ON (1 << 20)
+#define CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24)
+#define CURSOR_URGENT_ALWAYS 0
+#define CURSOR_URGENT_1_8 1
+#define CURSOR_URGENT_1_4 2
+#define CURSOR_URGENT_3_8 3
+#define CURSOR_URGENT_1_2 4
+#define CURSOR_UPDATE_PENDING (1 << 0)
+#define CURSOR_UPDATE_TAKEN (1 << 1)
+#define CURSOR_UPDATE_LOCK (1 << 16)
+#define CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24)
+
+#define AMDGPU_NUM_OF_VMIDS 8
+#define SI_CRTC0_REGISTER_OFFSET 0
+#define SI_CRTC1_REGISTER_OFFSET 0x300
+#define SI_CRTC2_REGISTER_OFFSET 0x2600
+#define SI_CRTC3_REGISTER_OFFSET 0x2900
+#define SI_CRTC4_REGISTER_OFFSET 0x2c00
+#define SI_CRTC5_REGISTER_OFFSET 0x2f00
+
+#define DMA0_REGISTER_OFFSET 0x000
+#define DMA1_REGISTER_OFFSET 0x200
+#define ES_AND_GS_AUTO 3
+#define RADEON_PACKET_TYPE3 3
+#define CE_PARTITION_BASE 3
+#define BUF_SWAP_32BIT (2 << 16)
+
+#define GFX_POWER_STATUS (1 << 1)
+#define GFX_CLOCK_STATUS (1 << 2)
+#define GFX_LS_STATUS (1 << 3)
+#define RLC_BUSY_STATUS (1 << 0)
+
+#define RLC_PUD(x) ((x) << 0)
+#define RLC_PUD_MASK (0xff << 0)
+#define RLC_PDD(x) ((x) << 8)
+#define RLC_PDD_MASK (0xff << 8)
+#define RLC_TTPD(x) ((x) << 16)
+#define RLC_TTPD_MASK (0xff << 16)
+#define RLC_MSD(x) ((x) << 24)
+#define RLC_MSD_MASK (0xff << 24)
+#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
+#define WRITE_DATA_DST_SEL(x) ((x) << 8)
+#define EVENT_TYPE(x) ((x) << 0)
+#define EVENT_INDEX(x) ((x) << 8)
+#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4)
+#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0)
+#define WAIT_REG_MEM_ENGINE(x) ((x) << 8)
+
+#define GFX6_NUM_GFX_RINGS 1
+#define GFX6_NUM_COMPUTE_RINGS 2
+#define RLC_SAVE_AND_RESTORE_STARTING_OFFSET 0x90
+#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET 0x3D
+
+#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003
+#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002
+#define HAINAN_GB_ADDR_CONFIG_GOLDEN 0x02010001
+
+#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) | \
+ (((op) & 0xFF) << 8) | \
+ ((n) & 0x3FFF) << 16)
+#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1)
+#define PACKET3_NOP 0x10
+#define PACKET3_SET_BASE 0x11
+#define PACKET3_BASE_INDEX(x) ((x) << 0)
+#define PACKET3_CLEAR_STATE 0x12
+#define PACKET3_INDEX_BUFFER_SIZE 0x13
+#define PACKET3_DISPATCH_DIRECT 0x15
+#define PACKET3_DISPATCH_INDIRECT 0x16
+#define PACKET3_ALLOC_GDS 0x1B
+#define PACKET3_WRITE_GDS_RAM 0x1C
+#define PACKET3_ATOMIC_GDS 0x1D
+#define PACKET3_ATOMIC 0x1E
+#define PACKET3_OCCLUSION_QUERY 0x1F
+#define PACKET3_SET_PREDICATION 0x20
+#define PACKET3_REG_RMW 0x21
+#define PACKET3_COND_EXEC 0x22
+#define PACKET3_PRED_EXEC 0x23
+#define PACKET3_DRAW_INDIRECT 0x24
+#define PACKET3_DRAW_INDEX_INDIRECT 0x25
+#define PACKET3_INDEX_BASE 0x26
+#define PACKET3_DRAW_INDEX_2 0x27
+#define PACKET3_CONTEXT_CONTROL 0x28
+#define PACKET3_INDEX_TYPE 0x2A
+#define PACKET3_DRAW_INDIRECT_MULTI 0x2C
+#define PACKET3_DRAW_INDEX_AUTO 0x2D
+#define PACKET3_DRAW_INDEX_IMMD 0x2E
+#define PACKET3_NUM_INSTANCES 0x2F
+#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30
+#define PACKET3_INDIRECT_BUFFER_CONST 0x31
+#define PACKET3_INDIRECT_BUFFER 0x3F
+#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
+#define PACKET3_DRAW_INDEX_OFFSET_2 0x35
+#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36
+#define PACKET3_WRITE_DATA 0x37
+#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38
+#define PACKET3_MEM_SEMAPHORE 0x39
+#define PACKET3_MPEG_INDEX 0x3A
+#define PACKET3_COPY_DW 0x3B
+#define PACKET3_WAIT_REG_MEM 0x3C
+#define PACKET3_MEM_WRITE 0x3D
+#define PACKET3_COPY_DATA 0x40
+#define PACKET3_CP_DMA 0x41
+# define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20)
+# define PACKET3_CP_DMA_ENGINE(x) ((x) << 27)
+# define PACKET3_CP_DMA_SRC_SEL(x) ((x) << 29)
+# define PACKET3_CP_DMA_CP_SYNC (1 << 31)
+# define PACKET3_CP_DMA_DIS_WC (1 << 21)
+# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22)
+# define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24)
+# define PACKET3_CP_DMA_CMD_SAS (1 << 26)
+# define PACKET3_CP_DMA_CMD_DAS (1 << 27)
+# define PACKET3_CP_DMA_CMD_SAIC (1 << 28)
+# define PACKET3_CP_DMA_CMD_DAIC (1 << 29)
+# define PACKET3_CP_DMA_CMD_RAW_WAIT (1 << 30)
+#define PACKET3_PFP_SYNC_ME 0x42
+#define PACKET3_SURFACE_SYNC 0x43
+# define PACKET3_DEST_BASE_0_ENA (1 << 0)
+# define PACKET3_DEST_BASE_1_ENA (1 << 1)
+# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
+# define PACKET3_CB1_DEST_BASE_ENA (1 << 7)
+# define PACKET3_CB2_DEST_BASE_ENA (1 << 8)
+# define PACKET3_CB3_DEST_BASE_ENA (1 << 9)
+# define PACKET3_CB4_DEST_BASE_ENA (1 << 10)
+# define PACKET3_CB5_DEST_BASE_ENA (1 << 11)
+# define PACKET3_CB6_DEST_BASE_ENA (1 << 12)
+# define PACKET3_CB7_DEST_BASE_ENA (1 << 13)
+# define PACKET3_DB_DEST_BASE_ENA (1 << 14)
+# define PACKET3_DEST_BASE_2_ENA (1 << 19)
+# define PACKET3_DEST_BASE_3_ENA (1 << 21)
+# define PACKET3_TCL1_ACTION_ENA (1 << 22)
+# define PACKET3_TC_ACTION_ENA (1 << 23)
+# define PACKET3_CB_ACTION_ENA (1 << 25)
+# define PACKET3_DB_ACTION_ENA (1 << 26)
+# define PACKET3_SH_KCACHE_ACTION_ENA (1 << 27)
+# define PACKET3_SH_ICACHE_ACTION_ENA (1 << 29)
+#define PACKET3_ME_INITIALIZE 0x44
+#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define PACKET3_COND_WRITE 0x45
+#define PACKET3_EVENT_WRITE 0x46
+#define PACKET3_EVENT_WRITE_EOP 0x47
+#define PACKET3_EVENT_WRITE_EOS 0x48
+#define PACKET3_PREAMBLE_CNTL 0x4A
+# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28)
+# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28)
+#define PACKET3_ONE_REG_WRITE 0x57
+#define PACKET3_LOAD_CONFIG_REG 0x5F
+#define PACKET3_LOAD_CONTEXT_REG 0x60
+#define PACKET3_LOAD_SH_REG 0x61
+#define PACKET3_SET_CONFIG_REG 0x68
+#define PACKET3_SET_CONFIG_REG_START 0x00002000
+#define PACKET3_SET_CONFIG_REG_END 0x00002c00
+#define PACKET3_SET_CONTEXT_REG 0x69
+#define PACKET3_SET_CONTEXT_REG_START 0x000a000
+#define PACKET3_SET_CONTEXT_REG_END 0x000a400
+#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
+#define PACKET3_SET_RESOURCE_INDIRECT 0x74
+#define PACKET3_SET_SH_REG 0x76
+#define PACKET3_SET_SH_REG_START 0x00002c00
+#define PACKET3_SET_SH_REG_END 0x00003000
+#define PACKET3_SET_SH_REG_OFFSET 0x77
+#define PACKET3_ME_WRITE 0x7A
+#define PACKET3_SCRATCH_RAM_WRITE 0x7D
+#define PACKET3_SCRATCH_RAM_READ 0x7E
+#define PACKET3_CE_WRITE 0x7F
+#define PACKET3_LOAD_CONST_RAM 0x80
+#define PACKET3_WRITE_CONST_RAM 0x81
+#define PACKET3_WRITE_CONST_RAM_OFFSET 0x82
+#define PACKET3_DUMP_CONST_RAM 0x83
+#define PACKET3_INCREMENT_CE_COUNTER 0x84
+#define PACKET3_INCREMENT_DE_COUNTER 0x85
+#define PACKET3_WAIT_ON_CE_COUNTER 0x86
+#define PACKET3_WAIT_ON_DE_COUNTER 0x87
+#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88
+#define PACKET3_SET_CE_DE_COUNTERS 0x89
+#define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A
+#define PACKET3_SWITCH_BUFFER 0x8B
+#define PACKET3_SEM_WAIT_ON_SIGNAL (0x1 << 12)
+#define PACKET3_SEM_SEL_SIGNAL (0x6 << 29)
+#define PACKET3_SEM_SEL_WAIT (0x7 << 29)
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c
index 8fae3d4a2360..db0f36846661 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c
@@ -268,7 +268,7 @@ static int si_ih_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs si_ih_ip_funcs = {
+static const struct amd_ip_funcs si_ih_ip_funcs = {
.name = "si_ih",
.early_init = si_ih_early_init,
.late_init = NULL,
@@ -297,3 +297,11 @@ static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev)
adev->irq.ih_funcs = &si_ih_funcs;
}
+const struct amdgpu_ip_block_version si_ih_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_IH,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &si_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.h b/drivers/gpu/drm/amd/amdgpu/si_ih.h
index f3e3a954369c..42e64a53e24f 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/si_ih.h
@@ -24,6 +24,6 @@
#ifndef __SI_IH_H__
#define __SI_IH_H__
-extern const struct amd_ip_funcs si_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version si_ih_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
index b4ea229bb449..52b71ee58793 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
@@ -455,7 +455,7 @@ static int tonga_ih_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs tonga_ih_ip_funcs = {
+static const struct amd_ip_funcs tonga_ih_ip_funcs = {
.name = "tonga_ih",
.early_init = tonga_ih_early_init,
.late_init = NULL,
@@ -487,3 +487,11 @@ static void tonga_ih_set_interrupt_funcs(struct amdgpu_device *adev)
adev->irq.ih_funcs = &tonga_ih_funcs;
}
+const struct amdgpu_ip_block_version tonga_ih_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_IH,
+ .major = 3,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &tonga_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.h b/drivers/gpu/drm/amd/amdgpu/tonga_ih.h
index 7392d70fa4a7..499027eee5c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.h
@@ -24,6 +24,6 @@
#ifndef __TONGA_IH_H__
#define __TONGA_IH_H__
-extern const struct amd_ip_funcs tonga_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version tonga_ih_ip_block;
-#endif /* __CZ_IH_H__ */
+#endif /* __TONGA_IH_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index f6c941550b8f..96444e4d862a 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -36,13 +36,17 @@
#include "bif/bif_4_1_d.h"
+#include "smu/smu_7_0_1_d.h"
+#include "smu/smu_7_0_1_sh_mask.h"
+
static void uvd_v4_2_mc_resume(struct amdgpu_device *adev);
static void uvd_v4_2_init_cg(struct amdgpu_device *adev);
static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev);
static void uvd_v4_2_set_irq_funcs(struct amdgpu_device *adev);
static int uvd_v4_2_start(struct amdgpu_device *adev);
static void uvd_v4_2_stop(struct amdgpu_device *adev);
-
+static int uvd_v4_2_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state);
/**
* uvd_v4_2_ring_get_rptr - get read pointer
*
@@ -116,8 +120,7 @@ static int uvd_v4_2_sw_init(void *handle)
ring = &adev->uvd.ring;
sprintf(ring->name, "uvd");
- r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
- &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
return r;
}
@@ -152,9 +155,9 @@ static int uvd_v4_2_hw_init(void *handle)
uint32_t tmp;
int r;
- /* raise clocks while booting up the VCPU */
- amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
-
+ uvd_v4_2_init_cg(adev);
+ uvd_v4_2_set_clockgating_state(adev, AMD_CG_STATE_GATE);
+ amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
r = uvd_v4_2_start(adev);
if (r)
goto done;
@@ -194,8 +197,6 @@ static int uvd_v4_2_hw_init(void *handle)
amdgpu_ring_commit(ring);
done:
- /* lower clocks again */
- amdgpu_asic_set_uvd_clocks(adev, 0, 0);
if (!r)
DRM_INFO("UVD initialized successfully.\n");
@@ -272,9 +273,6 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
uvd_v4_2_mc_resume(adev);
- /* disable clock gating */
- WREG32(mmUVD_CGC_GATE, 0);
-
/* disable interupt */
WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
@@ -526,20 +524,6 @@ static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, ib->length_dw);
}
-static unsigned uvd_v4_2_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 4; /* uvd_v4_2_ring_emit_ib */
-}
-
-static unsigned uvd_v4_2_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 2 + /* uvd_v4_2_ring_emit_hdp_flush */
- 2 + /* uvd_v4_2_ring_emit_hdp_invalidate */
- 14; /* uvd_v4_2_ring_emit_fence x1 no user fence */
-}
-
/**
* uvd_v4_2_mc_resume - memory controller programming
*
@@ -580,8 +564,6 @@ static void uvd_v4_2_mc_resume(struct amdgpu_device *adev)
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);
-
- uvd_v4_2_init_cg(adev);
}
static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
@@ -591,7 +573,7 @@ static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
- data = 0xfff;
+ data |= 0xfff;
WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
orig = data = RREG32(mmUVD_CGC_CTRL);
@@ -615,6 +597,8 @@ static void uvd_v4_2_set_dcm(struct amdgpu_device *adev,
{
u32 tmp, tmp2;
+ WREG32_FIELD(UVD_CGC_GATE, REGS, 0);
+
tmp = RREG32(mmUVD_CGC_CTRL);
tmp &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK | UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
tmp |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
@@ -738,7 +722,7 @@ static int uvd_v4_2_set_powergating_state(void *handle,
}
}
-const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
+static const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
.name = "uvd_v4_2",
.early_init = uvd_v4_2_early_init,
.late_init = NULL,
@@ -756,10 +740,18 @@ const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
};
static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_UVD,
+ .align_mask = 0xf,
+ .nop = PACKET0(mmUVD_NO_OP, 0),
.get_rptr = uvd_v4_2_ring_get_rptr,
.get_wptr = uvd_v4_2_ring_get_wptr,
.set_wptr = uvd_v4_2_ring_set_wptr,
.parse_cs = amdgpu_uvd_ring_parse_cs,
+ .emit_frame_size =
+ 2 + /* uvd_v4_2_ring_emit_hdp_flush */
+ 2 + /* uvd_v4_2_ring_emit_hdp_invalidate */
+ 14, /* uvd_v4_2_ring_emit_fence x1 no user fence */
+ .emit_ib_size = 4, /* uvd_v4_2_ring_emit_ib */
.emit_ib = uvd_v4_2_ring_emit_ib,
.emit_fence = uvd_v4_2_ring_emit_fence,
.emit_hdp_flush = uvd_v4_2_ring_emit_hdp_flush,
@@ -770,8 +762,6 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_uvd_ring_begin_use,
.end_use = amdgpu_uvd_ring_end_use,
- .get_emit_ib_size = uvd_v4_2_ring_get_emit_ib_size,
- .get_dma_frame_size = uvd_v4_2_ring_get_dma_frame_size,
};
static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev)
@@ -789,3 +779,12 @@ static void uvd_v4_2_set_irq_funcs(struct amdgpu_device *adev)
adev->uvd.irq.num_types = 1;
adev->uvd.irq.funcs = &uvd_v4_2_irq_funcs;
}
+
+const struct amdgpu_ip_block_version uvd_v4_2_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_UVD,
+ .major = 4,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &uvd_v4_2_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h
index 0a615dd50840..8a0444bb8b95 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h
@@ -24,6 +24,6 @@
#ifndef __UVD_V4_2_H__
#define __UVD_V4_2_H__
-extern const struct amd_ip_funcs uvd_v4_2_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v4_2_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index 400c16fe579e..a79e283590fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -33,12 +33,17 @@
#include "oss/oss_2_0_sh_mask.h"
#include "bif/bif_5_0_d.h"
#include "vi.h"
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev);
static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev);
static int uvd_v5_0_start(struct amdgpu_device *adev);
static void uvd_v5_0_stop(struct amdgpu_device *adev);
-
+static int uvd_v5_0_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state);
+static void uvd_v5_0_enable_mgcg(struct amdgpu_device *adev,
+ bool enable);
/**
* uvd_v5_0_ring_get_rptr - get read pointer
*
@@ -112,8 +117,7 @@ static int uvd_v5_0_sw_init(void *handle)
ring = &adev->uvd.ring;
sprintf(ring->name, "uvd");
- r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
- &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
return r;
}
@@ -148,9 +152,6 @@ static int uvd_v5_0_hw_init(void *handle)
uint32_t tmp;
int r;
- /* raise clocks while booting up the VCPU */
- amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
-
r = uvd_v5_0_start(adev);
if (r)
goto done;
@@ -188,11 +189,7 @@ static int uvd_v5_0_hw_init(void *handle)
amdgpu_ring_write(ring, 3);
amdgpu_ring_commit(ring);
-
done:
- /* lower clocks again */
- amdgpu_asic_set_uvd_clocks(adev, 0, 0);
-
if (!r)
DRM_INFO("UVD initialized successfully.\n");
@@ -225,6 +222,7 @@ static int uvd_v5_0_suspend(void *handle)
r = uvd_v5_0_hw_fini(adev);
if (r)
return r;
+ uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_GATE);
r = amdgpu_uvd_suspend(adev);
if (r)
@@ -312,8 +310,9 @@ static int uvd_v5_0_start(struct amdgpu_device *adev)
uvd_v5_0_mc_resume(adev);
- /* disable clock gating */
- WREG32(mmUVD_CGC_GATE, 0);
+ amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
+ uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
+ uvd_v5_0_enable_mgcg(adev, true);
/* disable interupt */
WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
@@ -577,20 +576,6 @@ static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, ib->length_dw);
}
-static unsigned uvd_v5_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 6; /* uvd_v5_0_ring_emit_ib */
-}
-
-static unsigned uvd_v5_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 2 + /* uvd_v5_0_ring_emit_hdp_flush */
- 2 + /* uvd_v5_0_ring_emit_hdp_invalidate */
- 14; /* uvd_v5_0_ring_emit_fence x1 no user fence */
-}
-
static bool uvd_v5_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -641,16 +626,12 @@ static int uvd_v5_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
-static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
+static void uvd_v5_0_enable_clock_gating(struct amdgpu_device *adev, bool enable)
{
- uint32_t data, data1, data2, suvd_flags;
+ uint32_t data1, data3, suvd_flags;
- data = RREG32(mmUVD_CGC_CTRL);
data1 = RREG32(mmUVD_SUVD_CGC_GATE);
- data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
-
- data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
- UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+ data3 = RREG32(mmUVD_CGC_GATE);
suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
UVD_SUVD_CGC_GATE__SIT_MASK |
@@ -658,6 +639,51 @@ static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
UVD_SUVD_CGC_GATE__SCM_MASK |
UVD_SUVD_CGC_GATE__SDB_MASK;
+ if (enable) {
+ data3 |= (UVD_CGC_GATE__SYS_MASK |
+ UVD_CGC_GATE__UDEC_MASK |
+ UVD_CGC_GATE__MPEG2_MASK |
+ UVD_CGC_GATE__RBC_MASK |
+ UVD_CGC_GATE__LMI_MC_MASK |
+ UVD_CGC_GATE__IDCT_MASK |
+ UVD_CGC_GATE__MPRD_MASK |
+ UVD_CGC_GATE__MPC_MASK |
+ UVD_CGC_GATE__LBSI_MASK |
+ UVD_CGC_GATE__LRBBM_MASK |
+ UVD_CGC_GATE__UDEC_RE_MASK |
+ UVD_CGC_GATE__UDEC_CM_MASK |
+ UVD_CGC_GATE__UDEC_IT_MASK |
+ UVD_CGC_GATE__UDEC_DB_MASK |
+ UVD_CGC_GATE__UDEC_MP_MASK |
+ UVD_CGC_GATE__WCB_MASK |
+ UVD_CGC_GATE__JPEG_MASK |
+ UVD_CGC_GATE__SCPU_MASK);
+ /* only in pg enabled, we can gate clock to vcpu*/
+ if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
+ data3 |= UVD_CGC_GATE__VCPU_MASK;
+ data3 &= ~UVD_CGC_GATE__REGS_MASK;
+ data1 |= suvd_flags;
+ } else {
+ data3 = 0;
+ data1 = 0;
+ }
+
+ WREG32(mmUVD_SUVD_CGC_GATE, data1);
+ WREG32(mmUVD_CGC_GATE, data3);
+}
+
+static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
+{
+ uint32_t data, data2;
+
+ data = RREG32(mmUVD_CGC_CTRL);
+ data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+
+
+ data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
+ UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+
+
data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
(4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY));
@@ -688,11 +714,8 @@ static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
- data1 |= suvd_flags;
WREG32(mmUVD_CGC_CTRL, data);
- WREG32(mmUVD_CGC_GATE, 0);
- WREG32(mmUVD_SUVD_CGC_GATE, data1);
WREG32(mmUVD_SUVD_CGC_CTRL, data2);
}
@@ -737,6 +760,32 @@ static void uvd_v5_0_set_hw_clock_gating(struct amdgpu_device *adev)
}
#endif
+static void uvd_v5_0_enable_mgcg(struct amdgpu_device *adev,
+ bool enable)
+{
+ u32 orig, data;
+
+ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
+ data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+ data |= 0xfff;
+ WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+ orig = data = RREG32(mmUVD_CGC_CTRL);
+ data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ if (orig != data)
+ WREG32(mmUVD_CGC_CTRL, data);
+ } else {
+ data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+ data &= ~0xfff;
+ WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+ orig = data = RREG32(mmUVD_CGC_CTRL);
+ data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ if (orig != data)
+ WREG32(mmUVD_CGC_CTRL, data);
+ }
+}
+
static int uvd_v5_0_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
@@ -752,17 +801,18 @@ static int uvd_v5_0_set_clockgating_state(void *handle,
curstate = state;
if (enable) {
- /* disable HW gating and enable Sw gating */
- uvd_v5_0_set_sw_clock_gating(adev);
- } else {
/* wait for STATUS to clear */
if (uvd_v5_0_wait_for_idle(handle))
return -EBUSY;
+ uvd_v5_0_enable_clock_gating(adev, true);
/* enable HW gates because UVD is idle */
/* uvd_v5_0_set_hw_clock_gating(adev); */
+ } else {
+ uvd_v5_0_enable_clock_gating(adev, false);
}
+ uvd_v5_0_set_sw_clock_gating(adev);
return 0;
}
@@ -789,7 +839,7 @@ static int uvd_v5_0_set_powergating_state(void *handle,
}
}
-const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
+static const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
.name = "uvd_v5_0",
.early_init = uvd_v5_0_early_init,
.late_init = NULL,
@@ -807,10 +857,18 @@ const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_UVD,
+ .align_mask = 0xf,
+ .nop = PACKET0(mmUVD_NO_OP, 0),
.get_rptr = uvd_v5_0_ring_get_rptr,
.get_wptr = uvd_v5_0_ring_get_wptr,
.set_wptr = uvd_v5_0_ring_set_wptr,
.parse_cs = amdgpu_uvd_ring_parse_cs,
+ .emit_frame_size =
+ 2 + /* uvd_v5_0_ring_emit_hdp_flush */
+ 2 + /* uvd_v5_0_ring_emit_hdp_invalidate */
+ 14, /* uvd_v5_0_ring_emit_fence x1 no user fence */
+ .emit_ib_size = 6, /* uvd_v5_0_ring_emit_ib */
.emit_ib = uvd_v5_0_ring_emit_ib,
.emit_fence = uvd_v5_0_ring_emit_fence,
.emit_hdp_flush = uvd_v5_0_ring_emit_hdp_flush,
@@ -821,8 +879,6 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_uvd_ring_begin_use,
.end_use = amdgpu_uvd_ring_end_use,
- .get_emit_ib_size = uvd_v5_0_ring_get_emit_ib_size,
- .get_dma_frame_size = uvd_v5_0_ring_get_dma_frame_size,
};
static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -840,3 +896,12 @@ static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev)
adev->uvd.irq.num_types = 1;
adev->uvd.irq.funcs = &uvd_v5_0_irq_funcs;
}
+
+const struct amdgpu_ip_block_version uvd_v5_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_UVD,
+ .major = 5,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &uvd_v5_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h
index e3b3c49fa5de..2eaaea793ac5 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h
@@ -24,6 +24,6 @@
#ifndef __UVD_V5_0_H__
#define __UVD_V5_0_H__
-extern const struct amd_ip_funcs uvd_v5_0_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v5_0_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index ab3df6d75656..ba0bbf7138dc 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -42,6 +42,10 @@ static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev);
static int uvd_v6_0_start(struct amdgpu_device *adev);
static void uvd_v6_0_stop(struct amdgpu_device *adev);
static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev);
+static int uvd_v6_0_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state);
+static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,
+ bool enable);
/**
* uvd_v6_0_ring_get_rptr - get read pointer
@@ -116,8 +120,7 @@ static int uvd_v6_0_sw_init(void *handle)
ring = &adev->uvd.ring;
sprintf(ring->name, "uvd");
- r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
- &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
return r;
}
@@ -394,11 +397,11 @@ static int uvd_v6_0_start(struct amdgpu_device *adev)
lmi_swap_cntl = 0;
mp_swap_cntl = 0;
+ amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
+ uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
+ uvd_v6_0_enable_mgcg(adev, true);
uvd_v6_0_mc_resume(adev);
- /* disable clock gating */
- WREG32_FIELD(UVD_CGC_CTRL, DYN_CLOCK_MODE, 0);
-
/* disable interupt */
WREG32_FIELD(UVD_MASTINT_EN, VCPU_EN, 0);
@@ -725,31 +728,6 @@ static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, 0xE);
}
-static unsigned uvd_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 8; /* uvd_v6_0_ring_emit_ib */
-}
-
-static unsigned uvd_v6_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 2 + /* uvd_v6_0_ring_emit_hdp_flush */
- 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
- 10 + /* uvd_v6_0_ring_emit_pipeline_sync */
- 14; /* uvd_v6_0_ring_emit_fence x1 no user fence */
-}
-
-static unsigned uvd_v6_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring)
-{
- return
- 2 + /* uvd_v6_0_ring_emit_hdp_flush */
- 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
- 10 + /* uvd_v6_0_ring_emit_pipeline_sync */
- 20 + /* uvd_v6_0_ring_emit_vm_flush */
- 14 + 14; /* uvd_v6_0_ring_emit_fence x2 vm fence */
-}
-
static bool uvd_v6_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -862,22 +840,72 @@ static int uvd_v6_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
+static void uvd_v6_0_enable_clock_gating(struct amdgpu_device *adev, bool enable)
+{
+ uint32_t data1, data3;
+
+ data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+ data3 = RREG32(mmUVD_CGC_GATE);
+
+ data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |
+ UVD_SUVD_CGC_GATE__SIT_MASK |
+ UVD_SUVD_CGC_GATE__SMP_MASK |
+ UVD_SUVD_CGC_GATE__SCM_MASK |
+ UVD_SUVD_CGC_GATE__SDB_MASK |
+ UVD_SUVD_CGC_GATE__SRE_H264_MASK |
+ UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |
+ UVD_SUVD_CGC_GATE__SIT_H264_MASK |
+ UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |
+ UVD_SUVD_CGC_GATE__SCM_H264_MASK |
+ UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |
+ UVD_SUVD_CGC_GATE__SDB_H264_MASK |
+ UVD_SUVD_CGC_GATE__SDB_HEVC_MASK;
+
+ if (enable) {
+ data3 |= (UVD_CGC_GATE__SYS_MASK |
+ UVD_CGC_GATE__UDEC_MASK |
+ UVD_CGC_GATE__MPEG2_MASK |
+ UVD_CGC_GATE__RBC_MASK |
+ UVD_CGC_GATE__LMI_MC_MASK |
+ UVD_CGC_GATE__LMI_UMC_MASK |
+ UVD_CGC_GATE__IDCT_MASK |
+ UVD_CGC_GATE__MPRD_MASK |
+ UVD_CGC_GATE__MPC_MASK |
+ UVD_CGC_GATE__LBSI_MASK |
+ UVD_CGC_GATE__LRBBM_MASK |
+ UVD_CGC_GATE__UDEC_RE_MASK |
+ UVD_CGC_GATE__UDEC_CM_MASK |
+ UVD_CGC_GATE__UDEC_IT_MASK |
+ UVD_CGC_GATE__UDEC_DB_MASK |
+ UVD_CGC_GATE__UDEC_MP_MASK |
+ UVD_CGC_GATE__WCB_MASK |
+ UVD_CGC_GATE__JPEG_MASK |
+ UVD_CGC_GATE__SCPU_MASK |
+ UVD_CGC_GATE__JPEG2_MASK);
+ /* only in pg enabled, we can gate clock to vcpu*/
+ if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
+ data3 |= UVD_CGC_GATE__VCPU_MASK;
+
+ data3 &= ~UVD_CGC_GATE__REGS_MASK;
+ } else {
+ data3 = 0;
+ }
+
+ WREG32(mmUVD_SUVD_CGC_GATE, data1);
+ WREG32(mmUVD_CGC_GATE, data3);
+}
+
static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev)
{
- uint32_t data, data1, data2, suvd_flags;
+ uint32_t data, data2;
data = RREG32(mmUVD_CGC_CTRL);
- data1 = RREG32(mmUVD_SUVD_CGC_GATE);
data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+
data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
- suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
- UVD_SUVD_CGC_GATE__SIT_MASK |
- UVD_SUVD_CGC_GATE__SMP_MASK |
- UVD_SUVD_CGC_GATE__SCM_MASK |
- UVD_SUVD_CGC_GATE__SDB_MASK;
data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
@@ -910,11 +938,8 @@ static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev)
UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
- data1 |= suvd_flags;
WREG32(mmUVD_CGC_CTRL, data);
- WREG32(mmUVD_CGC_GATE, 0);
- WREG32(mmUVD_SUVD_CGC_GATE, data1);
WREG32(mmUVD_SUVD_CGC_CTRL, data2);
}
@@ -961,44 +986,53 @@ static void uvd_v6_0_set_hw_clock_gating(struct amdgpu_device *adev)
}
#endif
-static void uvd_v6_set_bypass_mode(struct amdgpu_device *adev, bool enable)
+static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,
+ bool enable)
{
- u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);
+ u32 orig, data;
- if (enable)
- tmp |= (GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
- GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
- else
- tmp &= ~(GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
- GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
+ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
+ data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+ data |= 0xfff;
+ WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
- WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
+ orig = data = RREG32(mmUVD_CGC_CTRL);
+ data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ if (orig != data)
+ WREG32(mmUVD_CGC_CTRL, data);
+ } else {
+ data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+ data &= ~0xfff;
+ WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+ orig = data = RREG32(mmUVD_CGC_CTRL);
+ data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ if (orig != data)
+ WREG32(mmUVD_CGC_CTRL, data);
+ }
}
static int uvd_v6_0_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- if (adev->asic_type == CHIP_FIJI ||
- adev->asic_type == CHIP_POLARIS10)
- uvd_v6_set_bypass_mode(adev, state == AMD_CG_STATE_GATE ? true : false);
+ bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
return 0;
- if (state == AMD_CG_STATE_GATE) {
- /* disable HW gating and enable Sw gating */
- uvd_v6_0_set_sw_clock_gating(adev);
- } else {
+ if (enable) {
/* wait for STATUS to clear */
if (uvd_v6_0_wait_for_idle(handle))
return -EBUSY;
-
+ uvd_v6_0_enable_clock_gating(adev, true);
/* enable HW gates because UVD is idle */
/* uvd_v6_0_set_hw_clock_gating(adev); */
+ } else {
+ /* disable HW gating and enable Sw gating */
+ uvd_v6_0_enable_clock_gating(adev, false);
}
-
+ uvd_v6_0_set_sw_clock_gating(adev);
return 0;
}
@@ -1027,7 +1061,7 @@ static int uvd_v6_0_set_powergating_state(void *handle,
}
}
-const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
+static const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
.name = "uvd_v6_0",
.early_init = uvd_v6_0_early_init,
.late_init = NULL,
@@ -1048,10 +1082,19 @@ const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = {
+ .type = AMDGPU_RING_TYPE_UVD,
+ .align_mask = 0xf,
+ .nop = PACKET0(mmUVD_NO_OP, 0),
.get_rptr = uvd_v6_0_ring_get_rptr,
.get_wptr = uvd_v6_0_ring_get_wptr,
.set_wptr = uvd_v6_0_ring_set_wptr,
.parse_cs = amdgpu_uvd_ring_parse_cs,
+ .emit_frame_size =
+ 2 + /* uvd_v6_0_ring_emit_hdp_flush */
+ 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
+ 10 + /* uvd_v6_0_ring_emit_pipeline_sync */
+ 14, /* uvd_v6_0_ring_emit_fence x1 no user fence */
+ .emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */
.emit_ib = uvd_v6_0_ring_emit_ib,
.emit_fence = uvd_v6_0_ring_emit_fence,
.emit_hdp_flush = uvd_v6_0_ring_emit_hdp_flush,
@@ -1062,15 +1105,22 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_uvd_ring_begin_use,
.end_use = amdgpu_uvd_ring_end_use,
- .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size,
- .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size,
};
static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_UVD,
+ .align_mask = 0xf,
+ .nop = PACKET0(mmUVD_NO_OP, 0),
.get_rptr = uvd_v6_0_ring_get_rptr,
.get_wptr = uvd_v6_0_ring_get_wptr,
.set_wptr = uvd_v6_0_ring_set_wptr,
- .parse_cs = NULL,
+ .emit_frame_size =
+ 2 + /* uvd_v6_0_ring_emit_hdp_flush */
+ 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
+ 10 + /* uvd_v6_0_ring_emit_pipeline_sync */
+ 20 + /* uvd_v6_0_ring_emit_vm_flush */
+ 14 + 14, /* uvd_v6_0_ring_emit_fence x2 vm fence */
+ .emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */
.emit_ib = uvd_v6_0_ring_emit_ib,
.emit_fence = uvd_v6_0_ring_emit_fence,
.emit_vm_flush = uvd_v6_0_ring_emit_vm_flush,
@@ -1083,8 +1133,6 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_uvd_ring_begin_use,
.end_use = amdgpu_uvd_ring_end_use,
- .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size,
- .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size_vm,
};
static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -1108,3 +1156,30 @@ static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev)
adev->uvd.irq.num_types = 1;
adev->uvd.irq.funcs = &uvd_v6_0_irq_funcs;
}
+
+const struct amdgpu_ip_block_version uvd_v6_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_UVD,
+ .major = 6,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &uvd_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version uvd_v6_2_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_UVD,
+ .major = 6,
+ .minor = 2,
+ .rev = 0,
+ .funcs = &uvd_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version uvd_v6_3_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_UVD,
+ .major = 6,
+ .minor = 3,
+ .rev = 0,
+ .funcs = &uvd_v6_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h
index 6b92a2352986..d3d48c6428cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h
@@ -24,6 +24,8 @@
#ifndef __UVD_V6_0_H__
#define __UVD_V6_0_H__
-extern const struct amd_ip_funcs uvd_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v6_0_ip_block;
+extern const struct amdgpu_ip_block_version uvd_v6_2_ip_block;
+extern const struct amdgpu_ip_block_version uvd_v6_3_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index 76e64ad04a53..38ed903dd6f8 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -224,8 +224,8 @@ static int vce_v2_0_sw_init(void *handle)
for (i = 0; i < adev->vce.num_rings; i++) {
ring = &adev->vce.ring[i];
sprintf(ring->name, "vce%d", i);
- r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
- &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
+ r = amdgpu_ring_init(adev, ring, 512,
+ &adev->vce.irq, 0);
if (r)
return r;
}
@@ -592,7 +592,7 @@ static int vce_v2_0_set_powergating_state(void *handle,
return vce_v2_0_start(adev);
}
-const struct amd_ip_funcs vce_v2_0_ip_funcs = {
+static const struct amd_ip_funcs vce_v2_0_ip_funcs = {
.name = "vce_v2_0",
.early_init = vce_v2_0_early_init,
.late_init = NULL,
@@ -610,10 +610,15 @@ const struct amd_ip_funcs vce_v2_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_VCE,
+ .align_mask = 0xf,
+ .nop = VCE_CMD_NO_OP,
.get_rptr = vce_v2_0_ring_get_rptr,
.get_wptr = vce_v2_0_ring_get_wptr,
.set_wptr = vce_v2_0_ring_set_wptr,
.parse_cs = amdgpu_vce_ring_parse_cs,
+ .emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */
+ .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
.emit_ib = amdgpu_vce_ring_emit_ib,
.emit_fence = amdgpu_vce_ring_emit_fence,
.test_ring = amdgpu_vce_ring_test_ring,
@@ -622,8 +627,6 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vce_ring_begin_use,
.end_use = amdgpu_vce_ring_end_use,
- .get_emit_ib_size = amdgpu_vce_ring_get_emit_ib_size,
- .get_dma_frame_size = amdgpu_vce_ring_get_dma_frame_size,
};
static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -644,3 +647,12 @@ static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev)
adev->vce.irq.num_types = 1;
adev->vce.irq.funcs = &vce_v2_0_irq_funcs;
};
+
+const struct amdgpu_ip_block_version vce_v2_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_VCE,
+ .major = 2,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &vce_v2_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h
index 0d2ae8a01acd..4d15167654a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h
@@ -24,6 +24,6 @@
#ifndef __VCE_V2_0_H__
#define __VCE_V2_0_H__
-extern const struct amd_ip_funcs vce_v2_0_ip_funcs;
+extern const struct amdgpu_ip_block_version vce_v2_0_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 6feed726e299..6b3293a1c7b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -134,7 +134,7 @@ static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
accessible but the firmware will throttle the clocks on the
fly as necessary.
*/
- if (gated) {
+ if (!gated) {
data = RREG32(mmVCE_CLOCK_GATING_B);
data |= 0x1ff;
data &= ~0xef0000;
@@ -395,8 +395,7 @@ static int vce_v3_0_sw_init(void *handle)
for (i = 0; i < adev->vce.num_rings; i++) {
ring = &adev->vce.ring[i];
sprintf(ring->name, "vce%d", i);
- r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
- &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0);
if (r)
return r;
}
@@ -814,28 +813,7 @@ static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, seq);
}
-static unsigned vce_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
- return
- 5; /* vce_v3_0_ring_emit_ib */
-}
-
-static unsigned vce_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
- return
- 4 + /* vce_v3_0_emit_pipeline_sync */
- 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */
-}
-
-static unsigned vce_v3_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring)
-{
- return
- 6 + /* vce_v3_0_emit_vm_flush */
- 4 + /* vce_v3_0_emit_pipeline_sync */
- 6 + 6; /* amdgpu_vce_ring_emit_fence x2 vm fence */
-}
-
-const struct amd_ip_funcs vce_v3_0_ip_funcs = {
+static const struct amd_ip_funcs vce_v3_0_ip_funcs = {
.name = "vce_v3_0",
.early_init = vce_v3_0_early_init,
.late_init = NULL,
@@ -856,10 +834,17 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = {
};
static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = {
+ .type = AMDGPU_RING_TYPE_VCE,
+ .align_mask = 0xf,
+ .nop = VCE_CMD_NO_OP,
.get_rptr = vce_v3_0_ring_get_rptr,
.get_wptr = vce_v3_0_ring_get_wptr,
.set_wptr = vce_v3_0_ring_set_wptr,
.parse_cs = amdgpu_vce_ring_parse_cs,
+ .emit_frame_size =
+ 4 + /* vce_v3_0_emit_pipeline_sync */
+ 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */
+ .emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */
.emit_ib = amdgpu_vce_ring_emit_ib,
.emit_fence = amdgpu_vce_ring_emit_fence,
.test_ring = amdgpu_vce_ring_test_ring,
@@ -868,15 +853,21 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vce_ring_begin_use,
.end_use = amdgpu_vce_ring_end_use,
- .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size,
- .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size,
};
static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCE,
+ .align_mask = 0xf,
+ .nop = VCE_CMD_NO_OP,
.get_rptr = vce_v3_0_ring_get_rptr,
.get_wptr = vce_v3_0_ring_get_wptr,
.set_wptr = vce_v3_0_ring_set_wptr,
- .parse_cs = NULL,
+ .parse_cs = amdgpu_vce_ring_parse_cs_vm,
+ .emit_frame_size =
+ 6 + /* vce_v3_0_emit_vm_flush */
+ 4 + /* vce_v3_0_emit_pipeline_sync */
+ 6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */
+ .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
.emit_ib = vce_v3_0_ring_emit_ib,
.emit_vm_flush = vce_v3_0_emit_vm_flush,
.emit_pipeline_sync = vce_v3_0_emit_pipeline_sync,
@@ -887,8 +878,6 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = {
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vce_ring_begin_use,
.end_use = amdgpu_vce_ring_end_use,
- .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size,
- .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size_vm,
};
static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -916,3 +905,30 @@ static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
adev->vce.irq.num_types = 1;
adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
};
+
+const struct amdgpu_ip_block_version vce_v3_0_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_VCE,
+ .major = 3,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &vce_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version vce_v3_1_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_VCE,
+ .major = 3,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &vce_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version vce_v3_4_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_VCE,
+ .major = 3,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &vce_v3_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h
index b45af65da81f..08b908c7de0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h
@@ -24,6 +24,8 @@
#ifndef __VCE_V3_0_H__
#define __VCE_V3_0_H__
-extern const struct amd_ip_funcs vce_v3_0_ip_funcs;
+extern const struct amdgpu_ip_block_version vce_v3_0_ip_block;
+extern const struct amdgpu_ip_block_version vce_v3_1_ip_block;
+extern const struct amdgpu_ip_block_version vce_v3_4_ip_block;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index f62f1a74f890..9f771f4ffcb7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -123,8 +123,8 @@ static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg)
u32 r;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
- WREG32(mmSMC_IND_INDEX_0, (reg));
- r = RREG32(mmSMC_IND_DATA_0);
+ WREG32(mmSMC_IND_INDEX_11, (reg));
+ r = RREG32(mmSMC_IND_DATA_11);
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return r;
}
@@ -134,8 +134,8 @@ static void vi_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
unsigned long flags;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
- WREG32(mmSMC_IND_INDEX_0, (reg));
- WREG32(mmSMC_IND_DATA_0, (v));
+ WREG32(mmSMC_IND_INDEX_11, (reg));
+ WREG32(mmSMC_IND_DATA_11, (v));
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
}
@@ -439,12 +439,12 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev,
/* take the smc lock since we are using the smc index */
spin_lock_irqsave(&adev->smc_idx_lock, flags);
/* set rom index to 0 */
- WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX);
- WREG32(mmSMC_IND_DATA_0, 0);
+ WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX);
+ WREG32(mmSMC_IND_DATA_11, 0);
/* set index to data for continous read */
- WREG32(mmSMC_IND_INDEX_0, ixROM_DATA);
+ WREG32(mmSMC_IND_INDEX_11, ixROM_DATA);
for (i = 0; i < length_dw; i++)
- dw_ptr[i] = RREG32(mmSMC_IND_DATA_0);
+ dw_ptr[i] = RREG32(mmSMC_IND_DATA_11);
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return true;
@@ -558,21 +558,100 @@ static const struct amdgpu_allowed_register_entry vi_allowed_read_registers[] =
{mmPA_SC_RASTER_CONFIG_1, false, true},
};
-static uint32_t vi_read_indexed_register(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 reg_offset)
-{
- uint32_t val;
+static uint32_t vi_get_register_value(struct amdgpu_device *adev,
+ bool indexed, u32 se_num,
+ u32 sh_num, u32 reg_offset)
+{
+ if (indexed) {
+ uint32_t val;
+ unsigned se_idx = (se_num == 0xffffffff) ? 0 : se_num;
+ unsigned sh_idx = (sh_num == 0xffffffff) ? 0 : sh_num;
+
+ switch (reg_offset) {
+ case mmCC_RB_BACKEND_DISABLE:
+ return adev->gfx.config.rb_config[se_idx][sh_idx].rb_backend_disable;
+ case mmGC_USER_RB_BACKEND_DISABLE:
+ return adev->gfx.config.rb_config[se_idx][sh_idx].user_rb_backend_disable;
+ case mmPA_SC_RASTER_CONFIG:
+ return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config;
+ case mmPA_SC_RASTER_CONFIG_1:
+ return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config_1;
+ }
- mutex_lock(&adev->grbm_idx_mutex);
- if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ mutex_lock(&adev->grbm_idx_mutex);
+ if (se_num != 0xffffffff || sh_num != 0xffffffff)
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
- val = RREG32(reg_offset);
+ val = RREG32(reg_offset);
- if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
- mutex_unlock(&adev->grbm_idx_mutex);
- return val;
+ if (se_num != 0xffffffff || sh_num != 0xffffffff)
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ mutex_unlock(&adev->grbm_idx_mutex);
+ return val;
+ } else {
+ unsigned idx;
+
+ switch (reg_offset) {
+ case mmGB_ADDR_CONFIG:
+ return adev->gfx.config.gb_addr_config;
+ case mmMC_ARB_RAMCFG:
+ return adev->gfx.config.mc_arb_ramcfg;
+ case mmGB_TILE_MODE0:
+ case mmGB_TILE_MODE1:
+ case mmGB_TILE_MODE2:
+ case mmGB_TILE_MODE3:
+ case mmGB_TILE_MODE4:
+ case mmGB_TILE_MODE5:
+ case mmGB_TILE_MODE6:
+ case mmGB_TILE_MODE7:
+ case mmGB_TILE_MODE8:
+ case mmGB_TILE_MODE9:
+ case mmGB_TILE_MODE10:
+ case mmGB_TILE_MODE11:
+ case mmGB_TILE_MODE12:
+ case mmGB_TILE_MODE13:
+ case mmGB_TILE_MODE14:
+ case mmGB_TILE_MODE15:
+ case mmGB_TILE_MODE16:
+ case mmGB_TILE_MODE17:
+ case mmGB_TILE_MODE18:
+ case mmGB_TILE_MODE19:
+ case mmGB_TILE_MODE20:
+ case mmGB_TILE_MODE21:
+ case mmGB_TILE_MODE22:
+ case mmGB_TILE_MODE23:
+ case mmGB_TILE_MODE24:
+ case mmGB_TILE_MODE25:
+ case mmGB_TILE_MODE26:
+ case mmGB_TILE_MODE27:
+ case mmGB_TILE_MODE28:
+ case mmGB_TILE_MODE29:
+ case mmGB_TILE_MODE30:
+ case mmGB_TILE_MODE31:
+ idx = (reg_offset - mmGB_TILE_MODE0);
+ return adev->gfx.config.tile_mode_array[idx];
+ case mmGB_MACROTILE_MODE0:
+ case mmGB_MACROTILE_MODE1:
+ case mmGB_MACROTILE_MODE2:
+ case mmGB_MACROTILE_MODE3:
+ case mmGB_MACROTILE_MODE4:
+ case mmGB_MACROTILE_MODE5:
+ case mmGB_MACROTILE_MODE6:
+ case mmGB_MACROTILE_MODE7:
+ case mmGB_MACROTILE_MODE8:
+ case mmGB_MACROTILE_MODE9:
+ case mmGB_MACROTILE_MODE10:
+ case mmGB_MACROTILE_MODE11:
+ case mmGB_MACROTILE_MODE12:
+ case mmGB_MACROTILE_MODE13:
+ case mmGB_MACROTILE_MODE14:
+ case mmGB_MACROTILE_MODE15:
+ idx = (reg_offset - mmGB_MACROTILE_MODE0);
+ return adev->gfx.config.macrotile_mode_array[idx];
+ default:
+ return RREG32(reg_offset);
+ }
+ }
}
static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
@@ -607,10 +686,9 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
if (reg_offset != asic_register_entry->reg_offset)
continue;
if (!asic_register_entry->untouched)
- *value = asic_register_entry->grbm_indexed ?
- vi_read_indexed_register(adev, se_num,
- sh_num, reg_offset) :
- RREG32(reg_offset);
+ *value = vi_get_register_value(adev,
+ asic_register_entry->grbm_indexed,
+ se_num, sh_num, reg_offset);
return 0;
}
}
@@ -620,10 +698,9 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
continue;
if (!vi_allowed_read_registers[i].untouched)
- *value = vi_allowed_read_registers[i].grbm_indexed ?
- vi_read_indexed_register(adev, se_num,
- sh_num, reg_offset) :
- RREG32(reg_offset);
+ *value = vi_get_register_value(adev,
+ vi_allowed_read_registers[i].grbm_indexed,
+ se_num, sh_num, reg_offset);
return 0;
}
return -EINVAL;
@@ -654,18 +731,6 @@ static int vi_gpu_pci_config_reset(struct amdgpu_device *adev)
return -EINVAL;
}
-static void vi_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung)
-{
- u32 tmp = RREG32(mmBIOS_SCRATCH_3);
-
- if (hung)
- tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
- else
- tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-
- WREG32(mmBIOS_SCRATCH_3, tmp);
-}
-
/**
* vi_asic_reset - soft reset GPU
*
@@ -679,11 +744,11 @@ static int vi_asic_reset(struct amdgpu_device *adev)
{
int r;
- vi_set_bios_scratch_engine_hung(adev, true);
+ amdgpu_atombios_scratch_regs_engine_hung(adev, true);
r = vi_gpu_pci_config_reset(adev);
- vi_set_bios_scratch_engine_hung(adev, false);
+ amdgpu_atombios_scratch_regs_engine_hung(adev, false);
return r;
}
@@ -783,734 +848,6 @@ static void vi_enable_doorbell_aperture(struct amdgpu_device *adev,
WREG32(mmBIF_DOORBELL_APER_EN, tmp);
}
-/* topaz has no DCE, UVD, VCE */
-static const struct amdgpu_ip_block_version topaz_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 4,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 4,
- .rev = 0,
- .funcs = &iceland_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 4,
- .rev = 0,
- .funcs = &sdma_v2_4_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version topaz_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 4,
- .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 2,
- .minor = 4,
- .rev = 0,
- .funcs = &iceland_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 2,
- .minor = 4,
- .rev = 0,
- .funcs = &sdma_v2_4_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version tonga_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 10,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_v10_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 5,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v5_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version tonga_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 10,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 5,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v5_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version fiji_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 5,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 10,
- .minor = 1,
- .rev = 0,
- .funcs = &dce_v10_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version fiji_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 5,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 1,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 10,
- .minor = 1,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version polaris11_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 1,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 1,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 11,
- .minor = 2,
- .rev = 0,
- .funcs = &dce_v11_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 1,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 3,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 4,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version polaris11_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 1,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 1,
- .rev = 0,
- .funcs = &tonga_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 2,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 11,
- .minor = 2,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 1,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 3,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 4,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-};
-
-static const struct amdgpu_ip_block_version cz_ip_blocks[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &cz_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 11,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_v11_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-#if defined(CONFIG_DRM_AMD_ACP)
- {
- .type = AMD_IP_BLOCK_TYPE_ACP,
- .major = 2,
- .minor = 2,
- .rev = 0,
- .funcs = &acp_ip_funcs,
- },
-#endif
-};
-
-static const struct amdgpu_ip_block_version cz_ip_blocks_vd[] =
-{
- /* ORDER MATTERS! */
- {
- .type = AMD_IP_BLOCK_TYPE_COMMON,
- .major = 2,
- .minor = 0,
- .rev = 0,
- .funcs = &vi_common_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_IH,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &cz_ih_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &amdgpu_pp_ip_funcs
- },
- {
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 11,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_GFX,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &gfx_v8_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_SDMA,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &sdma_v3_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_UVD,
- .major = 6,
- .minor = 0,
- .rev = 0,
- .funcs = &uvd_v6_0_ip_funcs,
- },
- {
- .type = AMD_IP_BLOCK_TYPE_VCE,
- .major = 3,
- .minor = 0,
- .rev = 0,
- .funcs = &vce_v3_0_ip_funcs,
- },
-#if defined(CONFIG_DRM_AMD_ACP)
- {
- .type = AMD_IP_BLOCK_TYPE_ACP,
- .major = 2,
- .minor = 2,
- .rev = 0,
- .funcs = &acp_ip_funcs,
- },
-#endif
-};
-
-int vi_set_ip_blocks(struct amdgpu_device *adev)
-{
- if (adev->enable_virtual_display) {
- switch (adev->asic_type) {
- case CHIP_TOPAZ:
- adev->ip_blocks = topaz_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks_vd);
- break;
- case CHIP_FIJI:
- adev->ip_blocks = fiji_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_vd);
- break;
- case CHIP_TONGA:
- adev->ip_blocks = tonga_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_vd);
- break;
- case CHIP_POLARIS11:
- case CHIP_POLARIS10:
- adev->ip_blocks = polaris11_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks_vd);
- break;
-
- case CHIP_CARRIZO:
- case CHIP_STONEY:
- adev->ip_blocks = cz_ip_blocks_vd;
- adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_vd);
- break;
- default:
- /* FIXME: not supported yet */
- return -EINVAL;
- }
- } else {
- switch (adev->asic_type) {
- case CHIP_TOPAZ:
- adev->ip_blocks = topaz_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks);
- break;
- case CHIP_FIJI:
- adev->ip_blocks = fiji_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
- break;
- case CHIP_TONGA:
- adev->ip_blocks = tonga_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
- break;
- case CHIP_POLARIS11:
- case CHIP_POLARIS10:
- adev->ip_blocks = polaris11_ip_blocks;
- adev->num_ip_blocks = ARRAY_SIZE(polaris11_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;
- default:
- /* FIXME: not supported yet */
- return -EINVAL;
- }
- }
-
- 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
@@ -1589,22 +926,25 @@ static int vi_common_early_init(void *handle)
AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_ROM_MGCG |
AMD_CG_SUPPORT_MC_MGCG |
- AMD_CG_SUPPORT_MC_LS;
+ AMD_CG_SUPPORT_MC_LS |
+ AMD_CG_SUPPORT_UVD_MGCG;
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x3c;
break;
case CHIP_TONGA:
adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
- adev->pg_flags = 0;
+ adev->pg_flags = AMD_PG_SUPPORT_UVD;
adev->external_rev_id = adev->rev_id + 0x14;
break;
case CHIP_POLARIS11:
- adev->cg_flags = 0;
+ adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
+ AMD_CG_SUPPORT_VCE_MGCG;
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x5A;
break;
case CHIP_POLARIS10:
- adev->cg_flags = 0;
+ adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
+ AMD_CG_SUPPORT_VCE_MGCG;
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x50;
break;
@@ -1910,7 +1250,7 @@ static int vi_common_set_powergating_state(void *handle,
return 0;
}
-const struct amd_ip_funcs vi_common_ip_funcs = {
+static const struct amd_ip_funcs vi_common_ip_funcs = {
.name = "vi_common",
.early_init = vi_common_early_init,
.late_init = NULL,
@@ -1927,3 +1267,110 @@ const struct amd_ip_funcs vi_common_ip_funcs = {
.set_powergating_state = vi_common_set_powergating_state,
};
+static const struct amdgpu_ip_block_version vi_common_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_COMMON,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &vi_common_ip_funcs,
+};
+
+int vi_set_ip_blocks(struct amdgpu_device *adev)
+{
+ switch (adev->asic_type) {
+ case CHIP_TOPAZ:
+ /* topaz has no DCE, UVD, VCE */
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v7_4_ip_block);
+ amdgpu_ip_block_add(adev, &iceland_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v2_4_ip_block);
+ break;
+ case CHIP_FIJI:
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v8_5_ip_block);
+ amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v10_1_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v3_0_ip_block);
+ break;
+ case CHIP_TONGA:
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v10_0_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v5_0_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v3_0_ip_block);
+ break;
+ case CHIP_POLARIS11:
+ case CHIP_POLARIS10:
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block);
+ amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v11_2_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v3_1_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v6_3_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v3_4_ip_block);
+ break;
+ case CHIP_CARRIZO:
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &cz_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v3_1_ip_block);
+#if defined(CONFIG_DRM_AMD_ACP)
+ amdgpu_ip_block_add(adev, &acp_ip_block);
+#endif
+ break;
+ case CHIP_STONEY:
+ amdgpu_ip_block_add(adev, &vi_common_ip_block);
+ amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+ amdgpu_ip_block_add(adev, &cz_ih_ip_block);
+ amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+ if (adev->enable_virtual_display)
+ amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+ else
+ amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
+ amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block);
+ amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+ amdgpu_ip_block_add(adev, &uvd_v6_2_ip_block);
+ amdgpu_ip_block_add(adev, &vce_v3_4_ip_block);
+#if defined(CONFIG_DRM_AMD_ACP)
+ amdgpu_ip_block_add(adev, &acp_ip_block);
+#endif
+ break;
+ default:
+ /* FIXME: not supported yet */
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.h b/drivers/gpu/drm/amd/amdgpu/vi.h
index 502094042462..575d7aed5d32 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.h
+++ b/drivers/gpu/drm/amd/amdgpu/vi.h
@@ -24,8 +24,6 @@
#ifndef __VI_H__
#define __VI_H__
-extern const struct amd_ip_funcs vi_common_ip_funcs;
-
void vi_srbm_select(struct amdgpu_device *adev,
u32 me, u32 pipe, u32 queue, u32 vmid);
int vi_set_ip_blocks(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index bec8125bceb0..d1986276dbbd 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -84,6 +84,29 @@ enum amd_powergating_state {
AMD_PG_STATE_UNGATE,
};
+struct amd_vce_state {
+ /* vce clocks */
+ u32 evclk;
+ u32 ecclk;
+ /* gpu clocks */
+ u32 sclk;
+ u32 mclk;
+ u8 clk_idx;
+ u8 pstate;
+};
+
+
+#define AMD_MAX_VCE_LEVELS 6
+
+enum amd_vce_level {
+ AMD_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */
+ AMD_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */
+ AMD_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */
+ AMD_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
+ AMD_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */
+ AMD_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
+};
+
/* CG flags */
#define AMD_CG_SUPPORT_GFX_MGCG (1 << 0)
#define AMD_CG_SUPPORT_GFX_MGLS (1 << 1)
diff --git a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h
new file mode 100644
index 000000000000..7138fbf7256a
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h
@@ -0,0 +1,661 @@
+/*
+ *
+ * Copyright (C) 2016 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 BIF_3_0_D_H
+#define BIF_3_0_D_H
+
+#define ixPB0_DFT_DEBUG_CTRL_REG0 0x1300C
+#define ixPB0_DFT_JIT_INJ_REG0 0x13000
+#define ixPB0_DFT_JIT_INJ_REG1 0x13004
+#define ixPB0_DFT_JIT_INJ_REG2 0x13008
+#define ixPB0_GLB_CTRL_REG0 0x10004
+#define ixPB0_GLB_CTRL_REG1 0x10008
+#define ixPB0_GLB_CTRL_REG2 0x1000C
+#define ixPB0_GLB_CTRL_REG3 0x10010
+#define ixPB0_GLB_CTRL_REG4 0x10014
+#define ixPB0_GLB_CTRL_REG5 0x10018
+#define ixPB0_GLB_OVRD_REG0 0x10030
+#define ixPB0_GLB_OVRD_REG1 0x10034
+#define ixPB0_GLB_OVRD_REG2 0x10038
+#define ixPB0_GLB_SCI_STAT_OVRD_REG0 0x1001C
+#define ixPB0_GLB_SCI_STAT_OVRD_REG1 0x10020
+#define ixPB0_GLB_SCI_STAT_OVRD_REG2 0x10024
+#define ixPB0_GLB_SCI_STAT_OVRD_REG3 0x10028
+#define ixPB0_GLB_SCI_STAT_OVRD_REG4 0x1002C
+#define ixPB0_HW_DEBUG 0x12004
+#define ixPB0_PIF_CNTL 0x0010
+#define ixPB0_PIF_CNTL2 0x0014
+#define ixPB0_PIF_HW_DEBUG 0x0002
+#define ixPB0_PIF_PAIRING 0x0011
+#define ixPB0_PIF_PDNB_OVERRIDE_0 0x0020
+#define ixPB0_PIF_PDNB_OVERRIDE_10 0x0032
+#define ixPB0_PIF_PDNB_OVERRIDE_1 0x0021
+#define ixPB0_PIF_PDNB_OVERRIDE_11 0x0033
+#define ixPB0_PIF_PDNB_OVERRIDE_12 0x0034
+#define ixPB0_PIF_PDNB_OVERRIDE_13 0x0035
+#define ixPB0_PIF_PDNB_OVERRIDE_14 0x0036
+#define ixPB0_PIF_PDNB_OVERRIDE_15 0x0037
+#define ixPB0_PIF_PDNB_OVERRIDE_2 0x0022
+#define ixPB0_PIF_PDNB_OVERRIDE_3 0x0023
+#define ixPB0_PIF_PDNB_OVERRIDE_4 0x0024
+#define ixPB0_PIF_PDNB_OVERRIDE_5 0x0025
+#define ixPB0_PIF_PDNB_OVERRIDE_6 0x0026
+#define ixPB0_PIF_PDNB_OVERRIDE_7 0x0027
+#define ixPB0_PIF_PDNB_OVERRIDE_8 0x0030
+#define ixPB0_PIF_PDNB_OVERRIDE_9 0x0031
+#define ixPB0_PIF_PWRDOWN_0 0x0012
+#define ixPB0_PIF_PWRDOWN_1 0x0013
+#define ixPB0_PIF_PWRDOWN_2 0x0017
+#define ixPB0_PIF_PWRDOWN_3 0x0018
+#define ixPB0_PIF_SC_CTL 0x0016
+#define ixPB0_PIF_SCRATCH 0x0001
+#define ixPB0_PIF_SEQ_STATUS_0 0x0028
+#define ixPB0_PIF_SEQ_STATUS_10 0x003A
+#define ixPB0_PIF_SEQ_STATUS_1 0x0029
+#define ixPB0_PIF_SEQ_STATUS_11 0x003B
+#define ixPB0_PIF_SEQ_STATUS_12 0x003C
+#define ixPB0_PIF_SEQ_STATUS_13 0x003D
+#define ixPB0_PIF_SEQ_STATUS_14 0x003E
+#define ixPB0_PIF_SEQ_STATUS_15 0x003F
+#define ixPB0_PIF_SEQ_STATUS_2 0x002A
+#define ixPB0_PIF_SEQ_STATUS_3 0x002B
+#define ixPB0_PIF_SEQ_STATUS_4 0x002C
+#define ixPB0_PIF_SEQ_STATUS_5 0x002D
+#define ixPB0_PIF_SEQ_STATUS_6 0x002E
+#define ixPB0_PIF_SEQ_STATUS_7 0x002F
+#define ixPB0_PIF_SEQ_STATUS_8 0x0038
+#define ixPB0_PIF_SEQ_STATUS_9 0x0039
+#define ixPB0_PIF_TXPHYSTATUS 0x0015
+#define ixPB0_PLL_LC0_CTRL_REG0 0x14480
+#define ixPB0_PLL_LC0_OVRD_REG0 0x14490
+#define ixPB0_PLL_LC0_OVRD_REG1 0x14494
+#define ixPB0_PLL_LC0_SCI_STAT_OVRD_REG0 0x14500
+#define ixPB0_PLL_LC1_SCI_STAT_OVRD_REG0 0x14504
+#define ixPB0_PLL_LC2_SCI_STAT_OVRD_REG0 0x14508
+#define ixPB0_PLL_LC3_SCI_STAT_OVRD_REG0 0x1450C
+#define ixPB0_PLL_RO0_CTRL_REG0 0x14440
+#define ixPB0_PLL_RO0_OVRD_REG0 0x14450
+#define ixPB0_PLL_RO0_OVRD_REG1 0x14454
+#define ixPB0_PLL_RO0_SCI_STAT_OVRD_REG0 0x14460
+#define ixPB0_PLL_RO1_SCI_STAT_OVRD_REG0 0x14464
+#define ixPB0_PLL_RO2_SCI_STAT_OVRD_REG0 0x14468
+#define ixPB0_PLL_RO3_SCI_STAT_OVRD_REG0 0x1446C
+#define ixPB0_PLL_RO_GLB_CTRL_REG0 0x14000
+#define ixPB0_PLL_RO_GLB_OVRD_REG0 0x14010
+#define ixPB0_RX_GLB_CTRL_REG0 0x16000
+#define ixPB0_RX_GLB_CTRL_REG1 0x16004
+#define ixPB0_RX_GLB_CTRL_REG2 0x16008
+#define ixPB0_RX_GLB_CTRL_REG3 0x1600C
+#define ixPB0_RX_GLB_CTRL_REG4 0x16010
+#define ixPB0_RX_GLB_CTRL_REG5 0x16014
+#define ixPB0_RX_GLB_CTRL_REG6 0x16018
+#define ixPB0_RX_GLB_CTRL_REG7 0x1601C
+#define ixPB0_RX_GLB_CTRL_REG8 0x16020
+#define ixPB0_RX_GLB_OVRD_REG0 0x16030
+#define ixPB0_RX_GLB_OVRD_REG1 0x16034
+#define ixPB0_RX_GLB_SCI_STAT_OVRD_REG0 0x16028
+#define ixPB0_RX_LANE0_CTRL_REG0 0x16440
+#define ixPB0_RX_LANE0_SCI_STAT_OVRD_REG0 0x16448
+#define ixPB0_RX_LANE10_CTRL_REG0 0x17500
+#define ixPB0_RX_LANE10_SCI_STAT_OVRD_REG0 0x17508
+#define ixPB0_RX_LANE11_CTRL_REG0 0x17600
+#define ixPB0_RX_LANE11_SCI_STAT_OVRD_REG0 0x17608
+#define ixPB0_RX_LANE12_CTRL_REG0 0x17840
+#define ixPB0_RX_LANE12_SCI_STAT_OVRD_REG0 0x17848
+#define ixPB0_RX_LANE13_CTRL_REG0 0x17880
+#define ixPB0_RX_LANE13_SCI_STAT_OVRD_REG0 0x17888
+#define ixPB0_RX_LANE14_CTRL_REG0 0x17900
+#define ixPB0_RX_LANE14_SCI_STAT_OVRD_REG0 0x17908
+#define ixPB0_RX_LANE15_CTRL_REG0 0x17A00
+#define ixPB0_RX_LANE15_SCI_STAT_OVRD_REG0 0x17A08
+#define ixPB0_RX_LANE1_CTRL_REG0 0x16480
+#define ixPB0_RX_LANE1_SCI_STAT_OVRD_REG0 0x16488
+#define ixPB0_RX_LANE2_CTRL_REG0 0x16500
+#define ixPB0_RX_LANE2_SCI_STAT_OVRD_REG0 0x16508
+#define ixPB0_RX_LANE3_CTRL_REG0 0x16600
+#define ixPB0_RX_LANE3_SCI_STAT_OVRD_REG0 0x16608
+#define ixPB0_RX_LANE4_CTRL_REG0 0x16800
+#define ixPB0_RX_LANE4_SCI_STAT_OVRD_REG0 0x16848
+#define ixPB0_RX_LANE5_CTRL_REG0 0x16880
+#define ixPB0_RX_LANE5_SCI_STAT_OVRD_REG0 0x16888
+#define ixPB0_RX_LANE6_CTRL_REG0 0x16900
+#define ixPB0_RX_LANE6_SCI_STAT_OVRD_REG0 0x16908
+#define ixPB0_RX_LANE7_CTRL_REG0 0x16A00
+#define ixPB0_RX_LANE7_SCI_STAT_OVRD_REG0 0x16A08
+#define ixPB0_RX_LANE8_CTRL_REG0 0x17440
+#define ixPB0_RX_LANE8_SCI_STAT_OVRD_REG0 0x17448
+#define ixPB0_RX_LANE9_CTRL_REG0 0x17480
+#define ixPB0_RX_LANE9_SCI_STAT_OVRD_REG0 0x17488
+#define ixPB0_STRAP_GLB_REG0 0x12020
+#define ixPB0_STRAP_PLL_REG0 0x12030
+#define ixPB0_STRAP_RX_REG0 0x12028
+#define ixPB0_STRAP_RX_REG1 0x1202C
+#define ixPB0_STRAP_TX_REG0 0x12024
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0 0x18014
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1 0x18018
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2 0x1801C
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3 0x18020
+#define ixPB0_TX_GLB_CTRL_REG0 0x18000
+#define ixPB0_TX_GLB_LANE_SKEW_CTRL 0x18004
+#define ixPB0_TX_GLB_OVRD_REG0 0x18030
+#define ixPB0_TX_GLB_OVRD_REG1 0x18034
+#define ixPB0_TX_GLB_OVRD_REG2 0x18038
+#define ixPB0_TX_GLB_OVRD_REG3 0x1803C
+#define ixPB0_TX_GLB_OVRD_REG4 0x18040
+#define ixPB0_TX_GLB_SCI_STAT_OVRD_REG0 0x18010
+#define ixPB0_TX_LANE0_CTRL_REG0 0x18440
+#define ixPB0_TX_LANE0_OVRD_REG0 0x18444
+#define ixPB0_TX_LANE0_SCI_STAT_OVRD_REG0 0x18448
+#define ixPB0_TX_LANE10_CTRL_REG0 0x19500
+#define ixPB0_TX_LANE10_OVRD_REG0 0x19504
+#define ixPB0_TX_LANE10_SCI_STAT_OVRD_REG0 0x19508
+#define ixPB0_TX_LANE11_CTRL_REG0 0x19600
+#define ixPB0_TX_LANE11_OVRD_REG0 0x19604
+#define ixPB0_TX_LANE11_SCI_STAT_OVRD_REG0 0x19608
+#define ixPB0_TX_LANE12_CTRL_REG0 0x19840
+#define ixPB0_TX_LANE12_OVRD_REG0 0x19844
+#define ixPB0_TX_LANE12_SCI_STAT_OVRD_REG0 0x19848
+#define ixPB0_TX_LANE13_CTRL_REG0 0x19880
+#define ixPB0_TX_LANE13_OVRD_REG0 0x19884
+#define ixPB0_TX_LANE13_SCI_STAT_OVRD_REG0 0x19888
+#define ixPB0_TX_LANE14_CTRL_REG0 0x19900
+#define ixPB0_TX_LANE14_OVRD_REG0 0x19904
+#define ixPB0_TX_LANE14_SCI_STAT_OVRD_REG0 0x19908
+#define ixPB0_TX_LANE15_CTRL_REG0 0x19A00
+#define ixPB0_TX_LANE15_OVRD_REG0 0x19A04
+#define ixPB0_TX_LANE15_SCI_STAT_OVRD_REG0 0x19A08
+#define ixPB0_TX_LANE1_CTRL_REG0 0x18480
+#define ixPB0_TX_LANE1_OVRD_REG0 0x18484
+#define ixPB0_TX_LANE1_SCI_STAT_OVRD_REG0 0x18488
+#define ixPB0_TX_LANE2_CTRL_REG0 0x18500
+#define ixPB0_TX_LANE2_OVRD_REG0 0x18504
+#define ixPB0_TX_LANE2_SCI_STAT_OVRD_REG0 0x18508
+#define ixPB0_TX_LANE3_CTRL_REG0 0x18600
+#define ixPB0_TX_LANE3_OVRD_REG0 0x18604
+#define ixPB0_TX_LANE3_SCI_STAT_OVRD_REG0 0x18608
+#define ixPB0_TX_LANE4_CTRL_REG0 0x18840
+#define ixPB0_TX_LANE4_OVRD_REG0 0x18844
+#define ixPB0_TX_LANE4_SCI_STAT_OVRD_REG0 0x18848
+#define ixPB0_TX_LANE5_CTRL_REG0 0x18880
+#define ixPB0_TX_LANE5_OVRD_REG0 0x18884
+#define ixPB0_TX_LANE5_SCI_STAT_OVRD_REG0 0x18888
+#define ixPB0_TX_LANE6_CTRL_REG0 0x18900
+#define ixPB0_TX_LANE6_OVRD_REG0 0x18904
+#define ixPB0_TX_LANE6_SCI_STAT_OVRD_REG0 0x18908
+#define ixPB0_TX_LANE7_CTRL_REG0 0x18A00
+#define ixPB0_TX_LANE7_OVRD_REG0 0x18A04
+#define ixPB0_TX_LANE7_SCI_STAT_OVRD_REG0 0x18A08
+#define ixPB0_TX_LANE8_CTRL_REG0 0x19440
+#define ixPB0_TX_LANE8_OVRD_REG0 0x19444
+#define ixPB0_TX_LANE8_SCI_STAT_OVRD_REG0 0x19448
+#define ixPB0_TX_LANE9_CTRL_REG0 0x19480
+#define ixPB0_TX_LANE9_OVRD_REG0 0x19484
+#define ixPB0_TX_LANE9_SCI_STAT_OVRD_REG0 0x19488
+#define ixPB1_DFT_DEBUG_CTRL_REG0 0x1300C
+#define ixPB1_DFT_JIT_INJ_REG0 0x13000
+#define ixPB1_DFT_JIT_INJ_REG1 0x13004
+#define ixPB1_DFT_JIT_INJ_REG2 0x13008
+#define ixPB1_GLB_CTRL_REG0 0x10004
+#define ixPB1_GLB_CTRL_REG1 0x10008
+#define ixPB1_GLB_CTRL_REG2 0x1000C
+#define ixPB1_GLB_CTRL_REG3 0x10010
+#define ixPB1_GLB_CTRL_REG4 0x10014
+#define ixPB1_GLB_CTRL_REG5 0x10018
+#define ixPB1_GLB_OVRD_REG0 0x10030
+#define ixPB1_GLB_OVRD_REG1 0x10034
+#define ixPB1_GLB_OVRD_REG2 0x10038
+#define ixPB1_GLB_SCI_STAT_OVRD_REG0 0x1001C
+#define ixPB1_GLB_SCI_STAT_OVRD_REG1 0x10020
+#define ixPB1_GLB_SCI_STAT_OVRD_REG2 0x10024
+#define ixPB1_GLB_SCI_STAT_OVRD_REG3 0x10028
+#define ixPB1_GLB_SCI_STAT_OVRD_REG4 0x1002C
+#define ixPB1_HW_DEBUG 0x12004
+#define ixPB1_PIF_CNTL 0x0010
+#define ixPB1_PIF_CNTL2 0x0014
+#define ixPB1_PIF_HW_DEBUG 0x0002
+#define ixPB1_PIF_PAIRING 0x0011
+#define ixPB1_PIF_PDNB_OVERRIDE_0 0x0020
+#define ixPB1_PIF_PDNB_OVERRIDE_10 0x0032
+#define ixPB1_PIF_PDNB_OVERRIDE_1 0x0021
+#define ixPB1_PIF_PDNB_OVERRIDE_11 0x0033
+#define ixPB1_PIF_PDNB_OVERRIDE_12 0x0034
+#define ixPB1_PIF_PDNB_OVERRIDE_13 0x0035
+#define ixPB1_PIF_PDNB_OVERRIDE_14 0x0036
+#define ixPB1_PIF_PDNB_OVERRIDE_15 0x0037
+#define ixPB1_PIF_PDNB_OVERRIDE_2 0x0022
+#define ixPB1_PIF_PDNB_OVERRIDE_3 0x0023
+#define ixPB1_PIF_PDNB_OVERRIDE_4 0x0024
+#define ixPB1_PIF_PDNB_OVERRIDE_5 0x0025
+#define ixPB1_PIF_PDNB_OVERRIDE_6 0x0026
+#define ixPB1_PIF_PDNB_OVERRIDE_7 0x0027
+#define ixPB1_PIF_PDNB_OVERRIDE_8 0x0030
+#define ixPB1_PIF_PDNB_OVERRIDE_9 0x0031
+#define ixPB1_PIF_PWRDOWN_0 0x0012
+#define ixPB1_PIF_PWRDOWN_1 0x0013
+#define ixPB1_PIF_PWRDOWN_2 0x0017
+#define ixPB1_PIF_PWRDOWN_3 0x0018
+#define ixPB1_PIF_SC_CTL 0x0016
+#define ixPB1_PIF_SCRATCH 0x0001
+#define ixPB1_PIF_SEQ_STATUS_0 0x0028
+#define ixPB1_PIF_SEQ_STATUS_10 0x003A
+#define ixPB1_PIF_SEQ_STATUS_1 0x0029
+#define ixPB1_PIF_SEQ_STATUS_11 0x003B
+#define ixPB1_PIF_SEQ_STATUS_12 0x003C
+#define ixPB1_PIF_SEQ_STATUS_13 0x003D
+#define ixPB1_PIF_SEQ_STATUS_14 0x003E
+#define ixPB1_PIF_SEQ_STATUS_15 0x003F
+#define ixPB1_PIF_SEQ_STATUS_2 0x002A
+#define ixPB1_PIF_SEQ_STATUS_3 0x002B
+#define ixPB1_PIF_SEQ_STATUS_4 0x002C
+#define ixPB1_PIF_SEQ_STATUS_5 0x002D
+#define ixPB1_PIF_SEQ_STATUS_6 0x002E
+#define ixPB1_PIF_SEQ_STATUS_7 0x002F
+#define ixPB1_PIF_SEQ_STATUS_8 0x0038
+#define ixPB1_PIF_SEQ_STATUS_9 0x0039
+#define ixPB1_PIF_TXPHYSTATUS 0x0015
+#define ixPB1_PLL_LC0_CTRL_REG0 0x14480
+#define ixPB1_PLL_LC0_OVRD_REG0 0x14490
+#define ixPB1_PLL_LC0_OVRD_REG1 0x14494
+#define ixPB1_PLL_LC0_SCI_STAT_OVRD_REG0 0x14500
+#define ixPB1_PLL_LC1_SCI_STAT_OVRD_REG0 0x14504
+#define ixPB1_PLL_LC2_SCI_STAT_OVRD_REG0 0x14508
+#define ixPB1_PLL_LC3_SCI_STAT_OVRD_REG0 0x1450C
+#define ixPB1_PLL_RO0_CTRL_REG0 0x14440
+#define ixPB1_PLL_RO0_OVRD_REG0 0x14450
+#define ixPB1_PLL_RO0_OVRD_REG1 0x14454
+#define ixPB1_PLL_RO0_SCI_STAT_OVRD_REG0 0x14460
+#define ixPB1_PLL_RO1_SCI_STAT_OVRD_REG0 0x14464
+#define ixPB1_PLL_RO2_SCI_STAT_OVRD_REG0 0x14468
+#define ixPB1_PLL_RO3_SCI_STAT_OVRD_REG0 0x1446C
+#define ixPB1_PLL_RO_GLB_CTRL_REG0 0x14000
+#define ixPB1_PLL_RO_GLB_OVRD_REG0 0x14010
+#define ixPB1_RX_GLB_CTRL_REG0 0x16000
+#define ixPB1_RX_GLB_CTRL_REG1 0x16004
+#define ixPB1_RX_GLB_CTRL_REG2 0x16008
+#define ixPB1_RX_GLB_CTRL_REG3 0x1600C
+#define ixPB1_RX_GLB_CTRL_REG4 0x16010
+#define ixPB1_RX_GLB_CTRL_REG5 0x16014
+#define ixPB1_RX_GLB_CTRL_REG6 0x16018
+#define ixPB1_RX_GLB_CTRL_REG7 0x1601C
+#define ixPB1_RX_GLB_CTRL_REG8 0x16020
+#define ixPB1_RX_GLB_OVRD_REG0 0x16030
+#define ixPB1_RX_GLB_OVRD_REG1 0x16034
+#define ixPB1_RX_GLB_SCI_STAT_OVRD_REG0 0x16028
+#define ixPB1_RX_LANE0_CTRL_REG0 0x16440
+#define ixPB1_RX_LANE0_SCI_STAT_OVRD_REG0 0x16448
+#define ixPB1_RX_LANE10_CTRL_REG0 0x17500
+#define ixPB1_RX_LANE10_SCI_STAT_OVRD_REG0 0x17508
+#define ixPB1_RX_LANE11_CTRL_REG0 0x17600
+#define ixPB1_RX_LANE11_SCI_STAT_OVRD_REG0 0x17608
+#define ixPB1_RX_LANE12_CTRL_REG0 0x17840
+#define ixPB1_RX_LANE12_SCI_STAT_OVRD_REG0 0x17848
+#define ixPB1_RX_LANE13_CTRL_REG0 0x17880
+#define ixPB1_RX_LANE13_SCI_STAT_OVRD_REG0 0x17888
+#define ixPB1_RX_LANE14_CTRL_REG0 0x17900
+#define ixPB1_RX_LANE14_SCI_STAT_OVRD_REG0 0x17908
+#define ixPB1_RX_LANE15_CTRL_REG0 0x17A00
+#define ixPB1_RX_LANE15_SCI_STAT_OVRD_REG0 0x17A08
+#define ixPB1_RX_LANE1_CTRL_REG0 0x16480
+#define ixPB1_RX_LANE1_SCI_STAT_OVRD_REG0 0x16488
+#define ixPB1_RX_LANE2_CTRL_REG0 0x16500
+#define ixPB1_RX_LANE2_SCI_STAT_OVRD_REG0 0x16508
+#define ixPB1_RX_LANE3_CTRL_REG0 0x16600
+#define ixPB1_RX_LANE3_SCI_STAT_OVRD_REG0 0x16608
+#define ixPB1_RX_LANE4_CTRL_REG0 0x16800
+#define ixPB1_RX_LANE4_SCI_STAT_OVRD_REG0 0x16848
+#define ixPB1_RX_LANE5_CTRL_REG0 0x16880
+#define ixPB1_RX_LANE5_SCI_STAT_OVRD_REG0 0x16888
+#define ixPB1_RX_LANE6_CTRL_REG0 0x16900
+#define ixPB1_RX_LANE6_SCI_STAT_OVRD_REG0 0x16908
+#define ixPB1_RX_LANE7_CTRL_REG0 0x16A00
+#define ixPB1_RX_LANE7_SCI_STAT_OVRD_REG0 0x16A08
+#define ixPB1_RX_LANE8_CTRL_REG0 0x17440
+#define ixPB1_RX_LANE8_SCI_STAT_OVRD_REG0 0x17448
+#define ixPB1_RX_LANE9_CTRL_REG0 0x17480
+#define ixPB1_RX_LANE9_SCI_STAT_OVRD_REG0 0x17488
+#define ixPB1_STRAP_GLB_REG0 0x12020
+#define ixPB1_STRAP_PLL_REG0 0x12030
+#define ixPB1_STRAP_RX_REG0 0x12028
+#define ixPB1_STRAP_RX_REG1 0x1202C
+#define ixPB1_STRAP_TX_REG0 0x12024
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0 0x18014
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1 0x18018
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2 0x1801C
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3 0x18020
+#define ixPB1_TX_GLB_CTRL_REG0 0x18000
+#define ixPB1_TX_GLB_LANE_SKEW_CTRL 0x18004
+#define ixPB1_TX_GLB_OVRD_REG0 0x18030
+#define ixPB1_TX_GLB_OVRD_REG1 0x18034
+#define ixPB1_TX_GLB_OVRD_REG2 0x18038
+#define ixPB1_TX_GLB_OVRD_REG3 0x1803C
+#define ixPB1_TX_GLB_OVRD_REG4 0x18040
+#define ixPB1_TX_GLB_SCI_STAT_OVRD_REG0 0x18010
+#define ixPB1_TX_LANE0_CTRL_REG0 0x18440
+#define ixPB1_TX_LANE0_OVRD_REG0 0x18444
+#define ixPB1_TX_LANE0_SCI_STAT_OVRD_REG0 0x18448
+#define ixPB1_TX_LANE10_CTRL_REG0 0x19500
+#define ixPB1_TX_LANE10_OVRD_REG0 0x19504
+#define ixPB1_TX_LANE10_SCI_STAT_OVRD_REG0 0x19508
+#define ixPB1_TX_LANE11_CTRL_REG0 0x19600
+#define ixPB1_TX_LANE11_OVRD_REG0 0x19604
+#define ixPB1_TX_LANE11_SCI_STAT_OVRD_REG0 0x19608
+#define ixPB1_TX_LANE12_CTRL_REG0 0x19840
+#define ixPB1_TX_LANE12_OVRD_REG0 0x19844
+#define ixPB1_TX_LANE12_SCI_STAT_OVRD_REG0 0x19848
+#define ixPB1_TX_LANE13_CTRL_REG0 0x19880
+#define ixPB1_TX_LANE13_OVRD_REG0 0x19884
+#define ixPB1_TX_LANE13_SCI_STAT_OVRD_REG0 0x19888
+#define ixPB1_TX_LANE14_CTRL_REG0 0x19900
+#define ixPB1_TX_LANE14_OVRD_REG0 0x19904
+#define ixPB1_TX_LANE14_SCI_STAT_OVRD_REG0 0x19908
+#define ixPB1_TX_LANE15_CTRL_REG0 0x19A00
+#define ixPB1_TX_LANE15_OVRD_REG0 0x19A04
+#define ixPB1_TX_LANE15_SCI_STAT_OVRD_REG0 0x19A08
+#define ixPB1_TX_LANE1_CTRL_REG0 0x18480
+#define ixPB1_TX_LANE1_OVRD_REG0 0x18484
+#define ixPB1_TX_LANE1_SCI_STAT_OVRD_REG0 0x18488
+#define ixPB1_TX_LANE2_CTRL_REG0 0x18500
+#define ixPB1_TX_LANE2_OVRD_REG0 0x18504
+#define ixPB1_TX_LANE2_SCI_STAT_OVRD_REG0 0x18508
+#define ixPB1_TX_LANE3_CTRL_REG0 0x18600
+#define ixPB1_TX_LANE3_OVRD_REG0 0x18604
+#define ixPB1_TX_LANE3_SCI_STAT_OVRD_REG0 0x18608
+#define ixPB1_TX_LANE4_CTRL_REG0 0x18840
+#define ixPB1_TX_LANE4_OVRD_REG0 0x18844
+#define ixPB1_TX_LANE4_SCI_STAT_OVRD_REG0 0x18848
+#define ixPB1_TX_LANE5_CTRL_REG0 0x18880
+#define ixPB1_TX_LANE5_OVRD_REG0 0x18884
+#define ixPB1_TX_LANE5_SCI_STAT_OVRD_REG0 0x18888
+#define ixPB1_TX_LANE6_CTRL_REG0 0x18900
+#define ixPB1_TX_LANE6_OVRD_REG0 0x18904
+#define ixPB1_TX_LANE6_SCI_STAT_OVRD_REG0 0x18908
+#define ixPB1_TX_LANE7_CTRL_REG0 0x18A00
+#define ixPB1_TX_LANE7_OVRD_REG0 0x18A04
+#define ixPB1_TX_LANE7_SCI_STAT_OVRD_REG0 0x18A08
+#define ixPB1_TX_LANE8_CTRL_REG0 0x19440
+#define ixPB1_TX_LANE8_OVRD_REG0 0x19444
+#define ixPB1_TX_LANE8_SCI_STAT_OVRD_REG0 0x19448
+#define ixPB1_TX_LANE9_CTRL_REG0 0x19480
+#define ixPB1_TX_LANE9_OVRD_REG0 0x19484
+#define ixPB1_TX_LANE9_SCI_STAT_OVRD_REG0 0x19488
+#define ixPCIE_BUS_CNTL 0x0021
+#define ixPCIE_CFG_CNTL 0x003C
+#define ixPCIE_CI_CNTL 0x0020
+#define ixPCIE_CNTL 0x0010
+#define ixPCIE_CNTL2 0x001C
+#define ixPCIE_CONFIG_CNTL 0x0011
+#define ixPCIE_DEBUG_CNTL 0x0012
+#define ixPCIE_ERR_CNTL 0x006A
+#define ixPCIE_F0_DPA_CAP 0x00E0
+#define ixPCIE_F0_DPA_CNTL 0x00E5
+#define ixPCIE_F0_DPA_LATENCY_INDICATOR 0x00E4
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0 0x00E7
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1 0x00E8
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2 0x00E9
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3 0x00EA
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4 0x00EB
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5 0x00EC
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6 0x00ED
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7 0x00EE
+#define ixPCIE_FC_CPL 0x0062
+#define ixPCIE_FC_NP 0x0061
+#define ixPCIE_FC_P 0x0060
+#define ixPCIE_HW_DEBUG 0x0002
+#define ixPCIE_I2C_REG_ADDR_EXPAND 0x003A
+#define ixPCIE_I2C_REG_DATA 0x003B
+#define ixPCIE_INT_CNTL 0x001A
+#define ixPCIE_INT_STATUS 0x001B
+#define ixPCIE_LC_BEST_EQ_SETTINGS 0x00B9
+#define ixPCIE_LC_BW_CHANGE_CNTL 0x00B2
+#define ixPCIE_LC_CDR_CNTL 0x00B3
+#define ixPCIE_LC_CNTL 0x00A0
+#define ixPCIE_LC_CNTL2 0x00B1
+#define ixPCIE_LC_CNTL3 0x00B5
+#define ixPCIE_LC_CNTL4 0x00B6
+#define ixPCIE_LC_CNTL5 0x00B7
+#define ixPCIE_LC_FORCE_COEFF 0x00B8
+#define ixPCIE_LC_FORCE_EQ_REQ_COEFF 0x00BA
+#define ixPCIE_LC_LANE_CNTL 0x00B4
+#define ixPCIE_LC_LINK_WIDTH_CNTL 0x00A2
+#define ixPCIE_LC_N_FTS_CNTL 0x00A3
+#define ixPCIE_LC_SPEED_CNTL 0x00A4
+#define ixPCIE_LC_STATE0 0x00A5
+#define ixPCIE_LC_STATE10 0x0026
+#define ixPCIE_LC_STATE1 0x00A6
+#define ixPCIE_LC_STATE11 0x0027
+#define ixPCIE_LC_STATE2 0x00A7
+#define ixPCIE_LC_STATE3 0x00A8
+#define ixPCIE_LC_STATE4 0x00A9
+#define ixPCIE_LC_STATE5 0x00AA
+#define ixPCIE_LC_STATE6 0x0022
+#define ixPCIE_LC_STATE7 0x0023
+#define ixPCIE_LC_STATE8 0x0024
+#define ixPCIE_LC_STATE9 0x0025
+#define ixPCIE_LC_STATUS1 0x0028
+#define ixPCIE_LC_STATUS2 0x0029
+#define ixPCIE_LC_TRAINING_CNTL 0x00A1
+#define ixPCIE_P_BUF_STATUS 0x0041
+#define ixPCIE_P_CNTL 0x0040
+#define ixPCIE_P_DECODER_STATUS 0x0042
+#define ixPCIE_PERF_CNTL_EVENT0_PORT_SEL 0x0093
+#define ixPCIE_PERF_CNTL_EVENT1_PORT_SEL 0x0094
+#define ixPCIE_PERF_CNTL_MST_C_CLK 0x0087
+#define ixPCIE_PERF_CNTL_MST_R_CLK 0x0084
+#define ixPCIE_PERF_CNTL_SLV_NS_C_CLK 0x0090
+#define ixPCIE_PERF_CNTL_SLV_R_CLK 0x008A
+#define ixPCIE_PERF_CNTL_SLV_S_C_CLK 0x008D
+#define ixPCIE_PERF_CNTL_TXCLK 0x0081
+#define ixPCIE_PERF_CNTL_TXCLK2 0x0095
+#define ixPCIE_PERF_COUNT0_MST_C_CLK 0x0088
+#define ixPCIE_PERF_COUNT0_MST_R_CLK 0x0085
+#define ixPCIE_PERF_COUNT0_SLV_NS_C_CLK 0x0091
+#define ixPCIE_PERF_COUNT0_SLV_R_CLK 0x008B
+#define ixPCIE_PERF_COUNT0_SLV_S_C_CLK 0x008E
+#define ixPCIE_PERF_COUNT0_TXCLK 0x0082
+#define ixPCIE_PERF_COUNT0_TXCLK2 0x0096
+#define ixPCIE_PERF_COUNT1_MST_C_CLK 0x0089
+#define ixPCIE_PERF_COUNT1_MST_R_CLK 0x0086
+#define ixPCIE_PERF_COUNT1_SLV_NS_C_CLK 0x0092
+#define ixPCIE_PERF_COUNT1_SLV_R_CLK 0x008C
+#define ixPCIE_PERF_COUNT1_SLV_S_C_CLK 0x008F
+#define ixPCIE_PERF_COUNT1_TXCLK 0x0083
+#define ixPCIE_PERF_COUNT1_TXCLK2 0x0097
+#define ixPCIE_PERF_COUNT_CNTL 0x0080
+#define ixPCIEP_HW_DEBUG 0x0002
+#define ixPCIE_P_MISC_STATUS 0x0043
+#define ixPCIEP_PORT_CNTL 0x0010
+#define ixPCIE_P_PORT_LANE_STATUS 0x0050
+#define ixPCIE_PRBS_CLR 0x00C8
+#define ixPCIE_PRBS_ERRCNT_0 0x00D0
+#define ixPCIE_PRBS_ERRCNT_10 0x00DA
+#define ixPCIE_PRBS_ERRCNT_1 0x00D1
+#define ixPCIE_PRBS_ERRCNT_11 0x00DB
+#define ixPCIE_PRBS_ERRCNT_12 0x00DC
+#define ixPCIE_PRBS_ERRCNT_13 0x00DD
+#define ixPCIE_PRBS_ERRCNT_14 0x00DE
+#define ixPCIE_PRBS_ERRCNT_15 0x00DF
+#define ixPCIE_PRBS_ERRCNT_2 0x00D2
+#define ixPCIE_PRBS_ERRCNT_3 0x00D3
+#define ixPCIE_PRBS_ERRCNT_4 0x00D4
+#define ixPCIE_PRBS_ERRCNT_5 0x00D5
+#define ixPCIE_PRBS_ERRCNT_6 0x00D6
+#define ixPCIE_PRBS_ERRCNT_7 0x00D7
+#define ixPCIE_PRBS_ERRCNT_8 0x00D8
+#define ixPCIE_PRBS_ERRCNT_9 0x00D9
+#define ixPCIE_PRBS_FREERUN 0x00CB
+#define ixPCIE_PRBS_HI_BITCNT 0x00CF
+#define ixPCIE_PRBS_LO_BITCNT 0x00CE
+#define ixPCIE_PRBS_MISC 0x00CC
+#define ixPCIE_PRBS_STATUS1 0x00C9
+#define ixPCIE_PRBS_STATUS2 0x00CA
+#define ixPCIE_PRBS_USER_PATTERN 0x00CD
+#define ixPCIE_P_RCV_L0S_FTS_DET 0x0050
+#define ixPCIEP_RESERVED 0x0000
+#define ixPCIEP_SCRATCH 0x0001
+#define ixPCIEP_STRAP_LC 0x00C0
+#define ixPCIEP_STRAP_MISC 0x00C1
+#define ixPCIE_RESERVED 0x0000
+#define ixPCIE_RX_CNTL 0x0070
+#define ixPCIE_RX_CNTL2 0x001D
+#define ixPCIE_RX_CNTL3 0x0074
+#define ixPCIE_RX_CREDITS_ALLOCATED_CPL 0x0082
+#define ixPCIE_RX_CREDITS_ALLOCATED_NP 0x0081
+#define ixPCIE_RX_CREDITS_ALLOCATED_P 0x0080
+#define ixPCIE_RX_EXPECTED_SEQNUM 0x0071
+#define ixPCIE_RX_LAST_TLP0 0x0031
+#define ixPCIE_RX_LAST_TLP1 0x0032
+#define ixPCIE_RX_LAST_TLP2 0x0033
+#define ixPCIE_RX_LAST_TLP3 0x0034
+#define ixPCIE_RX_NUM_NAK 0x000E
+#define ixPCIE_RX_NUM_NAK_GENERATED 0x000F
+#define ixPCIE_RX_VENDOR_SPECIFIC 0x0072
+#define ixPCIE_SCRATCH 0x0001
+#define ixPCIE_STRAP_F0 0x00B0
+#define ixPCIE_STRAP_F1 0x00B1
+#define ixPCIE_STRAP_F2 0x00B2
+#define ixPCIE_STRAP_F3 0x00B3
+#define ixPCIE_STRAP_F4 0x00B4
+#define ixPCIE_STRAP_F5 0x00B5
+#define ixPCIE_STRAP_F6 0x00B6
+#define ixPCIE_STRAP_F7 0x00B7
+#define ixPCIE_STRAP_I2C_BD 0x00C4
+#define ixPCIE_STRAP_MISC 0x00C0
+#define ixPCIE_STRAP_MISC2 0x00C1
+#define ixPCIE_STRAP_PI 0x00C2
+#define ixPCIE_TX_ACK_LATENCY_LIMIT 0x0026
+#define ixPCIE_TX_CNTL 0x0020
+#define ixPCIE_TX_CREDITS_ADVT_CPL 0x0032
+#define ixPCIE_TX_CREDITS_ADVT_NP 0x0031
+#define ixPCIE_TX_CREDITS_ADVT_P 0x0030
+#define ixPCIE_TX_CREDITS_FCU_THRESHOLD 0x0037
+#define ixPCIE_TX_CREDITS_INIT_CPL 0x0035
+#define ixPCIE_TX_CREDITS_INIT_NP 0x0034
+#define ixPCIE_TX_CREDITS_INIT_P 0x0033
+#define ixPCIE_TX_CREDITS_STATUS 0x0036
+#define ixPCIE_TX_LAST_TLP0 0x0035
+#define ixPCIE_TX_LAST_TLP1 0x0036
+#define ixPCIE_TX_LAST_TLP2 0x0037
+#define ixPCIE_TX_LAST_TLP3 0x0038
+#define ixPCIE_TX_REPLAY 0x0025
+#define ixPCIE_TX_REQUESTER_ID 0x0021
+#define ixPCIE_TX_REQUEST_NUM_CNTL 0x0023
+#define ixPCIE_TX_SEQ 0x0024
+#define ixPCIE_TX_VENDOR_SPECIFIC 0x0022
+#define ixPCIE_WPR_CNTL 0x0030
+#define mmBACO_CNTL 0x14E5
+#define mmBF_ANA_ISO_CNTL 0x14C7
+#define mmBIF_BACO_DEBUG 0x14DF
+#define mmBIF_BACO_DEBUG_LATCH 0x14DC
+#define mmBIF_BACO_MSIC 0x14DE
+#define mmBIF_BUSNUM_CNTL1 0x1525
+#define mmBIF_BUSNUM_CNTL2 0x152B
+#define mmBIF_BUSNUM_LIST0 0x1526
+#define mmBIF_BUSNUM_LIST1 0x1527
+#define mmBIF_BUSY_DELAY_CNTR 0x1529
+#define mmBIF_CLK_PDWN_DELAY_TIMER 0x151F
+#define mmBIF_DEBUG_CNTL 0x151C
+#define mmBIF_DEBUG_MUX 0x151D
+#define mmBIF_DEBUG_OUT 0x151E
+#define mmBIF_DEVFUNCNUM_LIST0 0x14E8
+#define mmBIF_DEVFUNCNUM_LIST1 0x14E7
+#define mmBIF_FB_EN 0x1524
+#define mmBIF_FEATURES_CONTROL_MISC 0x14C2
+#define mmBIF_PERFCOUNTER0_RESULT 0x152D
+#define mmBIF_PERFCOUNTER1_RESULT 0x152E
+#define mmBIF_PERFMON_CNTL 0x152C
+#define mmBIF_PIF_TXCLK_SWITCH_TIMER 0x152F
+#define mmBIF_RESET_EN 0x1511
+#define mmBIF_SCRATCH0 0x150E
+#define mmBIF_SCRATCH1 0x150F
+#define mmBIF_SSA_DISP_LOWER 0x14D2
+#define mmBIF_SSA_DISP_UPPER 0x14D3
+#define mmBIF_SSA_GFX0_LOWER 0x14CA
+#define mmBIF_SSA_GFX0_UPPER 0x14CB
+#define mmBIF_SSA_GFX1_LOWER 0x14CC
+#define mmBIF_SSA_GFX1_UPPER 0x14CD
+#define mmBIF_SSA_GFX2_LOWER 0x14CE
+#define mmBIF_SSA_GFX2_UPPER 0x14CF
+#define mmBIF_SSA_GFX3_LOWER 0x14D0
+#define mmBIF_SSA_GFX3_UPPER 0x14D1
+#define mmBIF_SSA_MC_LOWER 0x14D4
+#define mmBIF_SSA_MC_UPPER 0x14D5
+#define mmBIF_SSA_PWR_STATUS 0x14C8
+#define mmBIF_XDMA_HI 0x14C1
+#define mmBIF_XDMA_LO 0x14C0
+#define mmBIOS_SCRATCH_0 0x05C9
+#define mmBIOS_SCRATCH_10 0x05D3
+#define mmBIOS_SCRATCH_1 0x05CA
+#define mmBIOS_SCRATCH_11 0x05D4
+#define mmBIOS_SCRATCH_12 0x05D5
+#define mmBIOS_SCRATCH_13 0x05D6
+#define mmBIOS_SCRATCH_14 0x05D7
+#define mmBIOS_SCRATCH_15 0x05D8
+#define mmBIOS_SCRATCH_2 0x05CB
+#define mmBIOS_SCRATCH_3 0x05CC
+#define mmBIOS_SCRATCH_4 0x05CD
+#define mmBIOS_SCRATCH_5 0x05CE
+#define mmBIOS_SCRATCH_6 0x05CF
+#define mmBIOS_SCRATCH_7 0x05D0
+#define mmBIOS_SCRATCH_8 0x05D1
+#define mmBIOS_SCRATCH_9 0x05D2
+#define mmBUS_CNTL 0x1508
+#define mmCAPTURE_HOST_BUSNUM 0x153C
+#define mmCLKREQB_PAD_CNTL 0x1521
+#define mmCONFIG_APER_SIZE 0x150C
+#define mmCONFIG_CNTL 0x1509
+#define mmCONFIG_F0_BASE 0x150B
+#define mmCONFIG_MEMSIZE 0x150A
+#define mmCONFIG_REG_APER_SIZE 0x150D
+#define mmHDP_MEM_COHERENCY_FLUSH_CNTL 0x1520
+#define mmHDP_REG_COHERENCY_FLUSH_CNTL 0x1528
+#define mmHOST_BUSNUM 0x153D
+#define mmHW_DEBUG 0x1515
+#define mmIMPCTL_RESET 0x14F5
+#define mmINTERRUPT_CNTL 0x151A
+#define mmINTERRUPT_CNTL2 0x151B
+#define mmMASTER_CREDIT_CNTL 0x1516
+#define mmMM_CFGREGS_CNTL 0x1513
+#define mmMM_DATA 0x0001
+#define mmMM_INDEX 0x0000
+#define mmMM_INDEX_HI 0x0006
+#define mmNEW_REFCLKB_TIMER 0x14EA
+#define mmNEW_REFCLKB_TIMER_1 0x14E9
+#define mmPCIE_DATA 0x000D
+#define mmPCIE_INDEX 0x000C
+#define mmPEER0_FB_OFFSET_HI 0x14F3
+#define mmPEER0_FB_OFFSET_LO 0x14F2
+#define mmPEER1_FB_OFFSET_HI 0x14F1
+#define mmPEER1_FB_OFFSET_LO 0x14F0
+#define mmPEER2_FB_OFFSET_HI 0x14EF
+#define mmPEER2_FB_OFFSET_LO 0x14EE
+#define mmPEER3_FB_OFFSET_HI 0x14ED
+#define mmPEER3_FB_OFFSET_LO 0x14EC
+#define mmPEER_REG_RANGE0 0x153E
+#define mmPEER_REG_RANGE1 0x153F
+#define mmSLAVE_HANG_ERROR 0x153B
+#define mmSLAVE_HANG_PROTECTION_CNTL 0x1536
+#define mmSLAVE_REQ_CREDIT_CNTL 0x1517
+#define mmSMBCLK_PAD_CNTL 0x1523
+#define mmSMBDAT_PAD_CNTL 0x1522
+#define mmSMBUS_BACO_DUMMY 0x14C6
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h
new file mode 100644
index 000000000000..e94445acf3c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h
@@ -0,0 +1,8127 @@
+/*
+ *
+ * Copyright (C) 2016 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 BIF_3_0_SH_MASK_H
+#define BIF_3_0_SH_MASK_H
+
+#define BACO_CNTL__BACO_ANA_ISO_DIS_MASK 0x00000080L
+#define BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT 0x00000007
+#define BACO_CNTL__BACO_BCLK_OFF_MASK 0x00000002L
+#define BACO_CNTL__BACO_BCLK_OFF__SHIFT 0x00000001
+#define BACO_CNTL__BACO_EN_MASK 0x00000001L
+#define BACO_CNTL__BACO_EN__SHIFT 0x00000000
+#define BACO_CNTL__BACO_HANG_PROTECTION_EN_MASK 0x00000020L
+#define BACO_CNTL__BACO_HANG_PROTECTION_EN__SHIFT 0x00000005
+#define BACO_CNTL__BACO_ISO_DIS_MASK 0x00000004L
+#define BACO_CNTL__BACO_ISO_DIS__SHIFT 0x00000002
+#define BACO_CNTL__BACO_MODE_MASK 0x00000040L
+#define BACO_CNTL__BACO_MODE__SHIFT 0x00000006
+#define BACO_CNTL__BACO_POWER_OFF_MASK 0x00000008L
+#define BACO_CNTL__BACO_POWER_OFF__SHIFT 0x00000003
+#define BACO_CNTL__BACO_RESET_EN_MASK 0x00000010L
+#define BACO_CNTL__BACO_RESET_EN__SHIFT 0x00000004
+#define BACO_CNTL__PWRGOOD_BF_MASK 0x00000200L
+#define BACO_CNTL__PWRGOOD_BF__SHIFT 0x00000009
+#define BACO_CNTL__PWRGOOD_DVO_MASK 0x00001000L
+#define BACO_CNTL__PWRGOOD_DVO__SHIFT 0x0000000c
+#define BACO_CNTL__PWRGOOD_GPIO_MASK 0x00000400L
+#define BACO_CNTL__PWRGOOD_GPIO__SHIFT 0x0000000a
+#define BACO_CNTL__PWRGOOD_MEM_MASK 0x00000800L
+#define BACO_CNTL__PWRGOOD_MEM__SHIFT 0x0000000b
+#define BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK 0x00000100L
+#define BACO_CNTL__RCU_BIF_CONFIG_DONE__SHIFT 0x00000008
+#define BF_ANA_ISO_CNTL__BF_ANA_ISO_DIS_MASK_MASK 0x00000001L
+#define BF_ANA_ISO_CNTL__BF_ANA_ISO_DIS_MASK__SHIFT 0x00000000
+#define BF_ANA_ISO_CNTL__BF_VDDC_ISO_DIS_MASK_MASK 0x00000002L
+#define BF_ANA_ISO_CNTL__BF_VDDC_ISO_DIS_MASK__SHIFT 0x00000001
+#define BIF_BACO_DEBUG__BIF_BACO_SCANDUMP_FLG_MASK 0x00000001L
+#define BIF_BACO_DEBUG__BIF_BACO_SCANDUMP_FLG__SHIFT 0x00000000
+#define BIF_BACO_DEBUG_LATCH__BIF_BACO_LATCH_FLG_MASK 0x00000001L
+#define BIF_BACO_DEBUG_LATCH__BIF_BACO_LATCH_FLG__SHIFT 0x00000000
+#define BIF_BACO_MSIC__BIF_XTALIN_SEL_MASK 0x00000001L
+#define BIF_BACO_MSIC__BIF_XTALIN_SEL__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL1__ID_MASK_MASK 0x000000ffL
+#define BIF_BUSNUM_CNTL1__ID_MASK__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_EN_MASK 0x00000100L
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_EN__SHIFT 0x00000008
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_SEL_MASK 0x000000ffL
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_SEL__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL2__ERROR_MULTIPLE_ID_MATCH_MASK 0x00020000L
+#define BIF_BUSNUM_CNTL2__ERROR_MULTIPLE_ID_MATCH__SHIFT 0x00000011
+#define BIF_BUSNUM_CNTL2__HDPREG_CNTL_MASK 0x00010000L
+#define BIF_BUSNUM_CNTL2__HDPREG_CNTL__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST0__ID0_MASK 0x000000ffL
+#define BIF_BUSNUM_LIST0__ID0__SHIFT 0x00000000
+#define BIF_BUSNUM_LIST0__ID1_MASK 0x0000ff00L
+#define BIF_BUSNUM_LIST0__ID1__SHIFT 0x00000008
+#define BIF_BUSNUM_LIST0__ID2_MASK 0x00ff0000L
+#define BIF_BUSNUM_LIST0__ID2__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST0__ID3_MASK 0xff000000L
+#define BIF_BUSNUM_LIST0__ID3__SHIFT 0x00000018
+#define BIF_BUSNUM_LIST1__ID4_MASK 0x000000ffL
+#define BIF_BUSNUM_LIST1__ID4__SHIFT 0x00000000
+#define BIF_BUSNUM_LIST1__ID5_MASK 0x0000ff00L
+#define BIF_BUSNUM_LIST1__ID5__SHIFT 0x00000008
+#define BIF_BUSNUM_LIST1__ID6_MASK 0x00ff0000L
+#define BIF_BUSNUM_LIST1__ID6__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST1__ID7_MASK 0xff000000L
+#define BIF_BUSNUM_LIST1__ID7__SHIFT 0x00000018
+#define BIF_BUSY_DELAY_CNTR__DELAY_CNT_MASK 0x0000003fL
+#define BIF_BUSY_DELAY_CNTR__DELAY_CNT__SHIFT 0x00000000
+#define BIF_CLK_PDWN_DELAY_TIMER__TIMER_MASK 0x000003ffL
+#define BIF_CLK_PDWN_DELAY_TIMER__TIMER__SHIFT 0x00000000
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK1_MASK 0x00000010L
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK1__SHIFT 0x00000004
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK2_MASK 0x00000020L
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK2__SHIFT 0x00000005
+#define BIF_DEBUG_CNTL__DEBUG_EN_MASK 0x00000001L
+#define BIF_DEBUG_CNTL__DEBUG_EN__SHIFT 0x00000000
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK1_MASK 0x00001f00L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK1__SHIFT 0x00000008
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK2_MASK 0x001f0000L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK2__SHIFT 0x00000010
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_XSP_MASK 0x01000000L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_XSP__SHIFT 0x00000018
+#define BIF_DEBUG_CNTL__DEBUG_MULTIBLOCKEN_MASK 0x00000002L
+#define BIF_DEBUG_CNTL__DEBUG_MULTIBLOCKEN__SHIFT 0x00000001
+#define BIF_DEBUG_CNTL__DEBUG_OUT_EN_MASK 0x00000004L
+#define BIF_DEBUG_CNTL__DEBUG_OUT_EN__SHIFT 0x00000002
+#define BIF_DEBUG_CNTL__DEBUG_PAD_SEL_MASK 0x00000008L
+#define BIF_DEBUG_CNTL__DEBUG_PAD_SEL__SHIFT 0x00000003
+#define BIF_DEBUG_CNTL__DEBUG_SWAP_MASK 0x00000080L
+#define BIF_DEBUG_CNTL__DEBUG_SWAP__SHIFT 0x00000007
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_CLKSEL_MASK 0xc0000000L
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_CLKSEL__SHIFT 0x0000001e
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_EN_MASK 0x00000040L
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_EN__SHIFT 0x00000006
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK1_MASK 0x0000003fL
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK1__SHIFT 0x00000000
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK2_MASK 0x00003f00L
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK2__SHIFT 0x00000008
+#define BIF_DEBUG_OUT__DEBUG_OUTPUT_MASK 0x0001ffffL
+#define BIF_DEBUG_OUT__DEBUG_OUTPUT__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID0_MASK 0x000000ffL
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID0__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID1_MASK 0x0000ff00L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID1__SHIFT 0x00000008
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID2_MASK 0x00ff0000L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID2__SHIFT 0x00000010
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID3_MASK 0xff000000L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID3__SHIFT 0x00000018
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID4_MASK 0x000000ffL
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID4__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID5_MASK 0x0000ff00L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID5__SHIFT 0x00000008
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID6_MASK 0x00ff0000L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID6__SHIFT 0x00000010
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID7_MASK 0xff000000L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID7__SHIFT 0x00000018
+#define BIF_FB_EN__FB_READ_EN_MASK 0x00000001L
+#define BIF_FB_EN__FB_READ_EN__SHIFT 0x00000000
+#define BIF_FB_EN__FB_WRITE_EN_MASK 0x00000002L
+#define BIF_FB_EN__FB_WRITE_EN__SHIFT 0x00000001
+#define BIF_FEATURES_CONTROL_MISC__BIF_MST_CPL_EP_DIS_MASK 0x00000008L
+#define BIF_FEATURES_CONTROL_MISC__BIF_MST_CPL_EP_DIS__SHIFT 0x00000003
+#define BIF_FEATURES_CONTROL_MISC__BIF_SLV_REQ_EP_DIS_MASK 0x00000004L
+#define BIF_FEATURES_CONTROL_MISC__BIF_SLV_REQ_EP_DIS__SHIFT 0x00000002
+#define BIF_FEATURES_CONTROL_MISC__IGNORE_BE_CHECK_GASKET_COMB_DIS_MASK 0x00000100L
+#define BIF_FEATURES_CONTROL_MISC__IGNORE_BE_CHECK_GASKET_COMB_DIS__SHIFT 0x00000008
+#define BIF_FEATURES_CONTROL_MISC__MST_BIF_REQ_EP_DIS_MASK 0x00000001L
+#define BIF_FEATURES_CONTROL_MISC__MST_BIF_REQ_EP_DIS__SHIFT 0x00000000
+#define BIF_FEATURES_CONTROL_MISC__PLL_SWITCH_IMPCTL_CAL_DONE_DIS_MASK 0x00000080L
+#define BIF_FEATURES_CONTROL_MISC__PLL_SWITCH_IMPCTL_CAL_DONE_DIS__SHIFT 0x00000007
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_ALL_DIS_MASK 0x00000020L
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_ALL_DIS__SHIFT 0x00000005
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_PART_DIS_MASK 0x00000040L
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_PART_DIS__SHIFT 0x00000006
+#define BIF_FEATURES_CONTROL_MISC__SLV_BIF_CPL_EP_DIS_MASK 0x00000002L
+#define BIF_FEATURES_CONTROL_MISC__SLV_BIF_CPL_EP_DIS__SHIFT 0x00000001
+#define BIF_FEATURES_CONTROL_MISC__UR_PSN_PKT_REPORT_POISON_DIS_MASK 0x00000010L
+#define BIF_FEATURES_CONTROL_MISC__UR_PSN_PKT_REPORT_POISON_DIS__SHIFT 0x00000004
+#define BIF_PERFCOUNTER0_RESULT__PERFCOUNTER_RESULT_MASK 0xffffffffL
+#define BIF_PERFCOUNTER0_RESULT__PERFCOUNTER_RESULT__SHIFT 0x00000000
+#define BIF_PERFCOUNTER1_RESULT__PERFCOUNTER_RESULT_MASK 0xffffffffL
+#define BIF_PERFCOUNTER1_RESULT__PERFCOUNTER_RESULT__SHIFT 0x00000000
+#define BIF_PERFMON_CNTL__PERFCOUNTER_EN_MASK 0x00000001L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_EN__SHIFT 0x00000000
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET0_MASK 0x00000002L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET0__SHIFT 0x00000001
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET1_MASK 0x00000004L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET1__SHIFT 0x00000002
+#define BIF_PERFMON_CNTL__PERF_SEL0_MASK 0x00001f00L
+#define BIF_PERFMON_CNTL__PERF_SEL0__SHIFT 0x00000008
+#define BIF_PERFMON_CNTL__PERF_SEL1_MASK 0x0003e000L
+#define BIF_PERFMON_CNTL__PERF_SEL1__SHIFT 0x0000000d
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL0_ACK_TIMER_MASK 0x00000007L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL0_ACK_TIMER__SHIFT 0x00000000
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL1_ACK_TIMER_MASK 0x00000038L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL1_ACK_TIMER__SHIFT 0x00000003
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL_SWITCH_TIMER_MASK 0x000003c0L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL_SWITCH_TIMER__SHIFT 0x00000006
+#define BIF_RESET_EN__BIF_COR_RESET_EN_MASK 0x00400000L
+#define BIF_RESET_EN__BIF_COR_RESET_EN__SHIFT 0x00000016
+#define BIF_RESET_EN__CFG_RESET_EN_MASK 0x00000040L
+#define BIF_RESET_EN__CFG_RESET_EN__SHIFT 0x00000006
+#define BIF_RESET_EN__CFG_RESET_PULSE_WIDTH_MASK 0x0003f000L
+#define BIF_RESET_EN__CFG_RESET_PULSE_WIDTH__SHIFT 0x0000000c
+#define BIF_RESET_EN__COR_RESET_EN_MASK 0x00000008L
+#define BIF_RESET_EN__COR_RESET_EN__SHIFT 0x00000003
+#define BIF_RESET_EN__DRV_RESET_DELAY_SEL_MASK 0x000c0000L
+#define BIF_RESET_EN__DRV_RESET_DELAY_SEL__SHIFT 0x00000012
+#define BIF_RESET_EN__DRV_RESET_EN_MASK 0x00000080L
+#define BIF_RESET_EN__DRV_RESET_EN__SHIFT 0x00000007
+#define BIF_RESET_EN__FUNC0_FLR_EN_MASK 0x00800000L
+#define BIF_RESET_EN__FUNC0_FLR_EN__SHIFT 0x00000017
+#define BIF_RESET_EN__FUNC0_RESET_DELAY_SEL_MASK 0x0c000000L
+#define BIF_RESET_EN__FUNC0_RESET_DELAY_SEL__SHIFT 0x0000001a
+#define BIF_RESET_EN__FUNC1_FLR_EN_MASK 0x01000000L
+#define BIF_RESET_EN__FUNC1_FLR_EN__SHIFT 0x00000018
+#define BIF_RESET_EN__FUNC1_RESET_DELAY_SEL_MASK 0x30000000L
+#define BIF_RESET_EN__FUNC1_RESET_DELAY_SEL__SHIFT 0x0000001c
+#define BIF_RESET_EN__FUNC2_FLR_EN_MASK 0x02000000L
+#define BIF_RESET_EN__FUNC2_FLR_EN__SHIFT 0x00000019
+#define BIF_RESET_EN__FUNC2_RESET_DELAY_SEL_MASK 0xc0000000L
+#define BIF_RESET_EN__FUNC2_RESET_DELAY_SEL__SHIFT 0x0000001e
+#define BIF_RESET_EN__HOT_RESET_EN_MASK 0x00000200L
+#define BIF_RESET_EN__HOT_RESET_EN__SHIFT 0x00000009
+#define BIF_RESET_EN__LINK_DISABLE_RESET_EN_MASK 0x00000400L
+#define BIF_RESET_EN__LINK_DISABLE_RESET_EN__SHIFT 0x0000000a
+#define BIF_RESET_EN__LINK_DOWN_RESET_EN_MASK 0x00000800L
+#define BIF_RESET_EN__LINK_DOWN_RESET_EN__SHIFT 0x0000000b
+#define BIF_RESET_EN__PHY_RESET_EN_MASK 0x00000004L
+#define BIF_RESET_EN__PHY_RESET_EN__SHIFT 0x00000002
+#define BIF_RESET_EN__PIF_RSTB_EN_MASK 0x00100000L
+#define BIF_RESET_EN__PIF_RSTB_EN__SHIFT 0x00000014
+#define BIF_RESET_EN__PIF_STRAP_ALLVALID_EN_MASK 0x00200000L
+#define BIF_RESET_EN__PIF_STRAP_ALLVALID_EN__SHIFT 0x00000015
+#define BIF_RESET_EN__REG_RESET_EN_MASK 0x00000010L
+#define BIF_RESET_EN__REG_RESET_EN__SHIFT 0x00000004
+#define BIF_RESET_EN__RESET_CFGREG_ONLY_EN_MASK 0x00000100L
+#define BIF_RESET_EN__RESET_CFGREG_ONLY_EN__SHIFT 0x00000008
+#define BIF_RESET_EN__SOFT_RST_MODE_MASK 0x00000002L
+#define BIF_RESET_EN__SOFT_RST_MODE__SHIFT 0x00000001
+#define BIF_RESET_EN__STY_RESET_EN_MASK 0x00000020L
+#define BIF_RESET_EN__STY_RESET_EN__SHIFT 0x00000005
+#define BIF_SCRATCH0__BIF_SCRATCH0_MASK 0xffffffffL
+#define BIF_SCRATCH0__BIF_SCRATCH0__SHIFT 0x00000000
+#define BIF_SCRATCH1__BIF_SCRATCH1_MASK 0xffffffffL
+#define BIF_SCRATCH1__BIF_SCRATCH1__SHIFT 0x00000000
+#define BIF_SSA_DISP_LOWER__SSA_DISP_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_DISP_LOWER__SSA_DISP_LOWER__SHIFT 0x00000002
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_DISP_UPPER__SSA_DISP_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_DISP_UPPER__SSA_DISP_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX0_UPPER__SSA_GFX0_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX0_UPPER__SSA_GFX0_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX1_UPPER__SSA_GFX1_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX1_UPPER__SSA_GFX1_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX2_UPPER__SSA_GFX2_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX2_UPPER__SSA_GFX2_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX3_UPPER__SSA_GFX3_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX3_UPPER__SSA_GFX3_UPPER__SHIFT 0x00000002
+#define BIF_SSA_MC_LOWER__SSA_MC_FB_STALL_EN_MASK 0x20000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_FB_STALL_EN__SHIFT 0x0000001d
+#define BIF_SSA_MC_LOWER__SSA_MC_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_MC_LOWER__SSA_MC_LOWER__SHIFT 0x00000002
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_MC_UPPER__SSA_MC_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_MC_UPPER__SSA_MC_UPPER__SHIFT 0x00000002
+#define BIF_SSA_PWR_STATUS__SSA_DISP_PWR_STATUS_MASK 0x00000002L
+#define BIF_SSA_PWR_STATUS__SSA_DISP_PWR_STATUS__SHIFT 0x00000001
+#define BIF_SSA_PWR_STATUS__SSA_GFX_PWR_STATUS_MASK 0x00000001L
+#define BIF_SSA_PWR_STATUS__SSA_GFX_PWR_STATUS__SHIFT 0x00000000
+#define BIF_SSA_PWR_STATUS__SSA_MC_PWR_STATUS_MASK 0x00000004L
+#define BIF_SSA_PWR_STATUS__SSA_MC_PWR_STATUS__SHIFT 0x00000002
+#define BIF_XDMA_HI__BIF_XDMA_UPPER_BOUND_MASK 0x1fffffffL
+#define BIF_XDMA_HI__BIF_XDMA_UPPER_BOUND__SHIFT 0x00000000
+#define BIF_XDMA_LO__BIF_XDMA_APER_EN_MASK 0x80000000L
+#define BIF_XDMA_LO__BIF_XDMA_APER_EN__SHIFT 0x0000001f
+#define BIF_XDMA_LO__BIF_XDMA_LOWER_BOUND_MASK 0x1fffffffL
+#define BIF_XDMA_LO__BIF_XDMA_LOWER_BOUND__SHIFT 0x00000000
+#define BIOS_SCRATCH_0__BIOS_SCRATCH_0_MASK 0xffffffffL
+#define BIOS_SCRATCH_0__BIOS_SCRATCH_0__SHIFT 0x00000000
+#define BIOS_SCRATCH_10__BIOS_SCRATCH_10_MASK 0xffffffffL
+#define BIOS_SCRATCH_10__BIOS_SCRATCH_10__SHIFT 0x00000000
+#define BIOS_SCRATCH_11__BIOS_SCRATCH_11_MASK 0xffffffffL
+#define BIOS_SCRATCH_11__BIOS_SCRATCH_11__SHIFT 0x00000000
+#define BIOS_SCRATCH_12__BIOS_SCRATCH_12_MASK 0xffffffffL
+#define BIOS_SCRATCH_12__BIOS_SCRATCH_12__SHIFT 0x00000000
+#define BIOS_SCRATCH_13__BIOS_SCRATCH_13_MASK 0xffffffffL
+#define BIOS_SCRATCH_13__BIOS_SCRATCH_13__SHIFT 0x00000000
+#define BIOS_SCRATCH_14__BIOS_SCRATCH_14_MASK 0xffffffffL
+#define BIOS_SCRATCH_14__BIOS_SCRATCH_14__SHIFT 0x00000000
+#define BIOS_SCRATCH_15__BIOS_SCRATCH_15_MASK 0xffffffffL
+#define BIOS_SCRATCH_15__BIOS_SCRATCH_15__SHIFT 0x00000000
+#define BIOS_SCRATCH_1__BIOS_SCRATCH_1_MASK 0xffffffffL
+#define BIOS_SCRATCH_1__BIOS_SCRATCH_1__SHIFT 0x00000000
+#define BIOS_SCRATCH_2__BIOS_SCRATCH_2_MASK 0xffffffffL
+#define BIOS_SCRATCH_2__BIOS_SCRATCH_2__SHIFT 0x00000000
+#define BIOS_SCRATCH_3__BIOS_SCRATCH_3_MASK 0xffffffffL
+#define BIOS_SCRATCH_3__BIOS_SCRATCH_3__SHIFT 0x00000000
+#define BIOS_SCRATCH_4__BIOS_SCRATCH_4_MASK 0xffffffffL
+#define BIOS_SCRATCH_4__BIOS_SCRATCH_4__SHIFT 0x00000000
+#define BIOS_SCRATCH_5__BIOS_SCRATCH_5_MASK 0xffffffffL
+#define BIOS_SCRATCH_5__BIOS_SCRATCH_5__SHIFT 0x00000000
+#define BIOS_SCRATCH_6__BIOS_SCRATCH_6_MASK 0xffffffffL
+#define BIOS_SCRATCH_6__BIOS_SCRATCH_6__SHIFT 0x00000000
+#define BIOS_SCRATCH_7__BIOS_SCRATCH_7_MASK 0xffffffffL
+#define BIOS_SCRATCH_7__BIOS_SCRATCH_7__SHIFT 0x00000000
+#define BIOS_SCRATCH_8__BIOS_SCRATCH_8_MASK 0xffffffffL
+#define BIOS_SCRATCH_8__BIOS_SCRATCH_8__SHIFT 0x00000000
+#define BIOS_SCRATCH_9__BIOS_SCRATCH_9_MASK 0xffffffffL
+#define BIOS_SCRATCH_9__BIOS_SCRATCH_9__SHIFT 0x00000000
+#define BUS_CNTL__BIF_ERR_RTR_BKPRESSURE_EN_MASK 0x00000100L
+#define BUS_CNTL__BIF_ERR_RTR_BKPRESSURE_EN__SHIFT 0x00000008
+#define BUS_CNTL__BIOS_ROM_DIS_MASK 0x00000002L
+#define BUS_CNTL__BIOS_ROM_DIS__SHIFT 0x00000001
+#define BUS_CNTL__BIOS_ROM_WRT_EN_MASK 0x00000001L
+#define BUS_CNTL__BIOS_ROM_WRT_EN__SHIFT 0x00000000
+#define BUS_CNTL__PMI_BM_DIS_MASK 0x00000010L
+#define BUS_CNTL__PMI_BM_DIS__SHIFT 0x00000004
+#define BUS_CNTL__PMI_INT_DIS_MASK 0x00000020L
+#define BUS_CNTL__PMI_INT_DIS__SHIFT 0x00000005
+#define BUS_CNTL__PMI_IO_DIS_MASK 0x00000004L
+#define BUS_CNTL__PMI_IO_DIS__SHIFT 0x00000002
+#define BUS_CNTL__PMI_MEM_DIS_MASK 0x00000008L
+#define BUS_CNTL__PMI_MEM_DIS__SHIFT 0x00000003
+#define BUS_CNTL__RD_STALL_IO_WR_MASK 0x00040000L
+#define BUS_CNTL__RD_STALL_IO_WR__SHIFT 0x00000012
+#define BUS_CNTL__SET_AZ_TC_MASK 0x00001c00L
+#define BUS_CNTL__SET_AZ_TC__SHIFT 0x0000000a
+#define BUS_CNTL__SET_MC_TC_MASK 0x0000e000L
+#define BUS_CNTL__SET_MC_TC__SHIFT 0x0000000d
+#define BUS_CNTL__VGA_MEM_COHERENCY_DIS_MASK 0x00000080L
+#define BUS_CNTL__VGA_MEM_COHERENCY_DIS__SHIFT 0x00000007
+#define BUS_CNTL__VGA_REG_COHERENCY_DIS_MASK 0x00000040L
+#define BUS_CNTL__VGA_REG_COHERENCY_DIS__SHIFT 0x00000006
+#define BUS_CNTL__ZERO_BE_RD_EN_MASK 0x00020000L
+#define BUS_CNTL__ZERO_BE_RD_EN__SHIFT 0x00000011
+#define BUS_CNTL__ZERO_BE_WR_EN_MASK 0x00010000L
+#define BUS_CNTL__ZERO_BE_WR_EN__SHIFT 0x00000010
+#define CAPTURE_HOST_BUSNUM__CHECK_EN_MASK 0x00000001L
+#define CAPTURE_HOST_BUSNUM__CHECK_EN__SHIFT 0x00000000
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_A_MASK 0x00000001L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_A__SHIFT 0x00000000
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_CNTL_EN_MASK 0x00001000L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_CNTL_EN__SHIFT 0x0000000c
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_MODE_MASK 0x00000004L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_MODE__SHIFT 0x00000002
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SCHMEN_MASK 0x00000800L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SCHMEN__SHIFT 0x0000000b
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SEL_MASK 0x00000002L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SEL__SHIFT 0x00000001
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SLEWN_MASK 0x00000200L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SLEWN__SHIFT 0x00000009
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN0_MASK 0x00000020L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN0__SHIFT 0x00000005
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN1_MASK 0x00000040L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN1__SHIFT 0x00000006
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN2_MASK 0x00000080L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN2__SHIFT 0x00000007
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN3_MASK 0x00000100L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN3__SHIFT 0x00000008
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SPARE_MASK 0x00000018L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SPARE__SHIFT 0x00000003
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_WAKE_MASK 0x00000400L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_WAKE__SHIFT 0x0000000a
+#define CONFIG_APER_SIZE__APER_SIZE_MASK 0xffffffffL
+#define CONFIG_APER_SIZE__APER_SIZE__SHIFT 0x00000000
+#define CONFIG_CNTL__CFG_VGA_RAM_EN_MASK 0x00000001L
+#define CONFIG_CNTL__CFG_VGA_RAM_EN__SHIFT 0x00000000
+#define CONFIG_CNTL__GENMO_MONO_ADDRESS_B_MASK 0x00000004L
+#define CONFIG_CNTL__GENMO_MONO_ADDRESS_B__SHIFT 0x00000002
+#define CONFIG_CNTL__GRPH_ADRSEL_MASK 0x00000018L
+#define CONFIG_CNTL__GRPH_ADRSEL__SHIFT 0x00000003
+#define CONFIG_CNTL__VGA_DIS_MASK 0x00000002L
+#define CONFIG_CNTL__VGA_DIS__SHIFT 0x00000001
+#define CONFIG_F0_BASE__F0_BASE_MASK 0xffffffffL
+#define CONFIG_F0_BASE__F0_BASE__SHIFT 0x00000000
+#define CONFIG_MEMSIZE__CONFIG_MEMSIZE_MASK 0xffffffffL
+#define CONFIG_MEMSIZE__CONFIG_MEMSIZE__SHIFT 0x00000000
+#define CONFIG_REG_APER_SIZE__REG_APER_SIZE_MASK 0x000fffffL
+#define CONFIG_REG_APER_SIZE__REG_APER_SIZE__SHIFT 0x00000000
+#define HDP_MEM_COHERENCY_FLUSH_CNTL__HDP_MEM_FLUSH_ADDR_MASK 0x00000001L
+#define HDP_MEM_COHERENCY_FLUSH_CNTL__HDP_MEM_FLUSH_ADDR__SHIFT 0x00000000
+#define HDP_REG_COHERENCY_FLUSH_CNTL__HDP_REG_FLUSH_ADDR_MASK 0x00000001L
+#define HDP_REG_COHERENCY_FLUSH_CNTL__HDP_REG_FLUSH_ADDR__SHIFT 0x00000000
+#define HOST_BUSNUM__HOST_ID_MASK 0x0000ffffL
+#define HOST_BUSNUM__HOST_ID__SHIFT 0x00000000
+#define HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define HW_DEBUG__HW_16_DEBUG_MASK 0x00010000L
+#define HW_DEBUG__HW_16_DEBUG__SHIFT 0x00000010
+#define HW_DEBUG__HW_17_DEBUG_MASK 0x00020000L
+#define HW_DEBUG__HW_17_DEBUG__SHIFT 0x00000011
+#define HW_DEBUG__HW_18_DEBUG_MASK 0x00040000L
+#define HW_DEBUG__HW_18_DEBUG__SHIFT 0x00000012
+#define HW_DEBUG__HW_19_DEBUG_MASK 0x00080000L
+#define HW_DEBUG__HW_19_DEBUG__SHIFT 0x00000013
+#define HW_DEBUG__HW_20_DEBUG_MASK 0x00100000L
+#define HW_DEBUG__HW_20_DEBUG__SHIFT 0x00000014
+#define HW_DEBUG__HW_21_DEBUG_MASK 0x00200000L
+#define HW_DEBUG__HW_21_DEBUG__SHIFT 0x00000015
+#define HW_DEBUG__HW_22_DEBUG_MASK 0x00400000L
+#define HW_DEBUG__HW_22_DEBUG__SHIFT 0x00000016
+#define HW_DEBUG__HW_23_DEBUG_MASK 0x00800000L
+#define HW_DEBUG__HW_23_DEBUG__SHIFT 0x00000017
+#define HW_DEBUG__HW_24_DEBUG_MASK 0x01000000L
+#define HW_DEBUG__HW_24_DEBUG__SHIFT 0x00000018
+#define HW_DEBUG__HW_25_DEBUG_MASK 0x02000000L
+#define HW_DEBUG__HW_25_DEBUG__SHIFT 0x00000019
+#define HW_DEBUG__HW_26_DEBUG_MASK 0x04000000L
+#define HW_DEBUG__HW_26_DEBUG__SHIFT 0x0000001a
+#define HW_DEBUG__HW_27_DEBUG_MASK 0x08000000L
+#define HW_DEBUG__HW_27_DEBUG__SHIFT 0x0000001b
+#define HW_DEBUG__HW_28_DEBUG_MASK 0x10000000L
+#define HW_DEBUG__HW_28_DEBUG__SHIFT 0x0000001c
+#define HW_DEBUG__HW_29_DEBUG_MASK 0x20000000L
+#define HW_DEBUG__HW_29_DEBUG__SHIFT 0x0000001d
+#define HW_DEBUG__HW_30_DEBUG_MASK 0x40000000L
+#define HW_DEBUG__HW_30_DEBUG__SHIFT 0x0000001e
+#define HW_DEBUG__HW_31_DEBUG_MASK 0x80000000L
+#define HW_DEBUG__HW_31_DEBUG__SHIFT 0x0000001f
+#define IMPCTL_RESET__IMP_SW_RESET_MASK 0x00000001L
+#define IMPCTL_RESET__IMP_SW_RESET__SHIFT 0x00000000
+#define INTERRUPT_CNTL2__IH_DUMMY_RD_ADDR_MASK 0xffffffffL
+#define INTERRUPT_CNTL2__IH_DUMMY_RD_ADDR__SHIFT 0x00000000
+#define INTERRUPT_CNTL__GEN_GPIO_INT_EN_MASK 0x00001e00L
+#define INTERRUPT_CNTL__GEN_GPIO_INT_EN__SHIFT 0x00000009
+#define INTERRUPT_CNTL__GEN_IH_INT_EN_MASK 0x00000100L
+#define INTERRUPT_CNTL__GEN_IH_INT_EN__SHIFT 0x00000008
+#define INTERRUPT_CNTL__IH_DUMMY_RD_EN_MASK 0x00000002L
+#define INTERRUPT_CNTL__IH_DUMMY_RD_EN__SHIFT 0x00000001
+#define INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK 0x00000001L
+#define INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE__SHIFT 0x00000000
+#define INTERRUPT_CNTL__IH_INTR_DLY_CNTR_MASK 0x000000f0L
+#define INTERRUPT_CNTL__IH_INTR_DLY_CNTR__SHIFT 0x00000004
+#define INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK 0x00000008L
+#define INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN__SHIFT 0x00000003
+#define INTERRUPT_CNTL__SELECT_INT_GPIO_OUTPUT_MASK 0x00006000L
+#define INTERRUPT_CNTL__SELECT_INT_GPIO_OUTPUT__SHIFT 0x0000000d
+#define MASTER_CREDIT_CNTL__BIF_AZ_RDRET_CREDIT_MASK 0x003f0000L
+#define MASTER_CREDIT_CNTL__BIF_AZ_RDRET_CREDIT__SHIFT 0x00000010
+#define MASTER_CREDIT_CNTL__BIF_MC_RDRET_CREDIT_MASK 0x0000003fL
+#define MASTER_CREDIT_CNTL__BIF_MC_RDRET_CREDIT__SHIFT 0x00000000
+#define MM_CFGREGS_CNTL__MM_CFG_FUNC_SEL_MASK 0x00000007L
+#define MM_CFGREGS_CNTL__MM_CFG_FUNC_SEL__SHIFT 0x00000000
+#define MM_CFGREGS_CNTL__MM_WR_TO_CFG_EN_MASK 0x00000008L
+#define MM_CFGREGS_CNTL__MM_WR_TO_CFG_EN__SHIFT 0x00000003
+#define MM_DATA__MM_DATA_MASK 0xffffffffL
+#define MM_DATA__MM_DATA__SHIFT 0x00000000
+#define MM_INDEX_HI__MM_OFFSET_HI_MASK 0xffffffffL
+#define MM_INDEX_HI__MM_OFFSET_HI__SHIFT 0x00000000
+#define MM_INDEX__MM_APER_MASK 0x80000000L
+#define MM_INDEX__MM_APER__SHIFT 0x0000001f
+#define MM_INDEX__MM_OFFSET_MASK 0x7fffffffL
+#define MM_INDEX__MM_OFFSET__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER_1__PHY_PLL_PDWN_TIMER_MASK 0x000003ffL
+#define NEW_REFCLKB_TIMER_1__PHY_PLL_PDWN_TIMER__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER_1__PLL0_PDNB_EN_MASK 0x00000400L
+#define NEW_REFCLKB_TIMER_1__PLL0_PDNB_EN__SHIFT 0x0000000a
+#define NEW_REFCLKB_TIMER__REFCLK_ON_MASK 0x00200000L
+#define NEW_REFCLKB_TIMER__REFCLK_ON__SHIFT 0x00000015
+#define NEW_REFCLKB_TIMER__REG_STOP_REFCLK_EN_MASK 0x00000001L
+#define NEW_REFCLKB_TIMER__REG_STOP_REFCLK_EN__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER__STOP_REFCLK_TIMER_MASK 0x001ffffeL
+#define NEW_REFCLKB_TIMER__STOP_REFCLK_TIMER__SHIFT 0x00000001
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN_MASK 0x00000001L
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN__SHIFT 0x00000000
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE_MASK 0x0000003eL
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE__SHIFT 0x00000001
+#define PB0_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP_MASK 0x00000f00L
+#define PB0_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP__SHIFT 0x00000008
+#define PB0_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN_MASK 0x00800000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN__SHIFT 0x00000017
+#define PB0_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN_MASK 0x00400000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN__SHIFT 0x00000016
+#define PB0_DFT_JIT_INJ_REG0__DFT_NUM_STEPS_MASK 0x0000001fL
+#define PB0_DFT_JIT_INJ_REG0__DFT_NUM_STEPS__SHIFT 0x00000000
+#define PB0_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME_MASK 0xff000000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME__SHIFT 0x00000018
+#define PB0_DFT_JIT_INJ_REG1__DFT_BLOCK_EN_MASK 0x00010000L
+#define PB0_DFT_JIT_INJ_REG1__DFT_BLOCK_EN__SHIFT 0x00000010
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_EN_MASK 0x00000100L
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_EN__SHIFT 0x00000008
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE_MASK 0x000000ffL
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE__SHIFT 0x00000000
+#define PB0_DFT_JIT_INJ_REG2__DFT_LANE_EN_MASK 0x0000ffffL
+#define PB0_DFT_JIT_INJ_REG2__DFT_LANE_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG0__BACKUP_MASK 0x0000ffffL
+#define PB0_GLB_CTRL_REG0__BACKUP__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG0__CFG_IDLEDET_TH_MASK 0x00030000L
+#define PB0_GLB_CTRL_REG0__CFG_IDLEDET_TH__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL_MASK 0x00700000L
+#define PB0_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL__SHIFT 0x00000014
+#define PB0_GLB_CTRL_REG0__DBG_RXFEBYP_EN_MASK 0x00800000L
+#define PB0_GLB_CTRL_REG0__DBG_RXFEBYP_EN__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG0__DBG_RXPRBS_CLR_MASK 0x01000000L
+#define PB0_GLB_CTRL_REG0__DBG_RXPRBS_CLR__SHIFT 0x00000018
+#define PB0_GLB_CTRL_REG0__DBG_RXTOGGLE_EN_MASK 0x02000000L
+#define PB0_GLB_CTRL_REG0__DBG_RXTOGGLE_EN__SHIFT 0x00000019
+#define PB0_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN_MASK 0x04000000L
+#define PB0_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN__SHIFT 0x0000001a
+#define PB0_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE_MASK 0xc0000000L
+#define PB0_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE__SHIFT 0x0000001e
+#define PB0_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV_MASK 0x80000000L
+#define PB0_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV__SHIFT 0x0000001f
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN_MASK 0x00000001L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL_MASK 0x0000007eL
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL__SHIFT 0x00000001
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN_MASK 0x00000080L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN__SHIFT 0x00000007
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL_MASK 0x00003f00L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL__SHIFT 0x00000008
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN_MASK 0x00004000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN__SHIFT 0x0000000e
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL_MASK 0x003f8000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL__SHIFT 0x0000000f
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN_MASK 0x00400000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL_MASK 0x3f800000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG1__TST_LOSPDTST_EN_MASK 0x40000000L
+#define PB0_GLB_CTRL_REG1__TST_LOSPDTST_EN__SHIFT 0x0000001e
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN_MASK 0x00000001L
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL_MASK 0x000000feL
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL__SHIFT 0x00000001
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN_MASK 0x00000100L
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN__SHIFT 0x00000008
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL_MASK 0x0000fe00L
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL__SHIFT 0x00000009
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN_MASK 0x00010000L
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL_MASK 0x00fe0000L
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL__SHIFT 0x00000011
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN_MASK 0x01000000L
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN__SHIFT 0x00000018
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL_MASK 0xfe000000L
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL__SHIFT 0x00000019
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL_MASK 0x00000060L
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL__SHIFT 0x00000005
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL_MASK 0x00000180L
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL__SHIFT 0x00000007
+#define PB0_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL_MASK 0x00000600L
+#define PB0_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL__SHIFT 0x00000009
+#define PB0_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL_MASK 0x0001c000L
+#define PB0_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL__SHIFT 0x0000000e
+#define PB0_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN_MASK 0x00001000L
+#define PB0_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN__SHIFT 0x0000000c
+#define PB0_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN_MASK 0x00000800L
+#define PB0_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN__SHIFT 0x0000000b
+#define PB0_GLB_CTRL_REG3__DBG_DLL_CLK_SEL_MASK 0x001c0000L
+#define PB0_GLB_CTRL_REG3__DBG_DLL_CLK_SEL__SHIFT 0x00000012
+#define PB0_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE_MASK 0x80000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE__SHIFT 0x0000001f
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN_MASK 0x00400000L
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL_MASK 0x07800000L
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN_MASK 0x08000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN__SHIFT 0x0000001b
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL_MASK 0x70000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL__SHIFT 0x0000001c
+#define PB0_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL_MASK 0x00200000L
+#define PB0_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL__SHIFT 0x00000015
+#define PB0_GLB_CTRL_REG3__RXDBG_SEL_MASK 0x0000001fL
+#define PB0_GLB_CTRL_REG3__RXDBG_SEL__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_EXEC_MASK 0x03c00000L
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_EXEC__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_INST_MASK 0x0000ffffL
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_INST__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN_MASK 0x00040000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN__SHIFT 0x00000012
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL_MASK 0x00030000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL_MASK 0x04000000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000001a
+#define PB0_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE_MASK 0x10000000L
+#define PB0_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE__SHIFT 0x0000001c
+#define PB0_GLB_CTRL_REG4__PWRGOOD_OVRD_MASK 0x08000000L
+#define PB0_GLB_CTRL_REG4__PWRGOOD_OVRD__SHIFT 0x0000001b
+#define PB0_GLB_CTRL_REG5__DBG_RXAPU_MODE_MASK 0x000000ffL
+#define PB0_GLB_CTRL_REG5__DBG_RXAPU_MODE__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL_MASK 0x0000ffffL
+#define PB0_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB0_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN_MASK 0x00008000L
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN__SHIFT 0x0000000f
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN_MASK 0x00000004L
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN__SHIFT 0x00000002
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL_MASK 0x00000008L
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL__SHIFT 0x00000003
+#define PB0_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN_MASK 0x00000001L
+#define PB0_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN_MASK 0x00000002L
+#define PB0_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN__SHIFT 0x00000001
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_EN_MASK 0x00000001L
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_EN__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL_MASK 0x00000002L
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT_MASK 0x00000010L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT__SHIFT 0x00000004
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE_MASK 0x00100000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG0__RXIMP_MASK 0x000f0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__RXIMP__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXNIMP_MASK 0x00000f00L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXNIMP__SHIFT 0x00000008
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXPIMP_MASK 0x0000f000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXPIMP__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_0_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_0__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_1_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_1__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_2_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_2__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_3_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_3__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_4_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_4__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_5_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_5__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_6_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_6__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_7_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_7__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_10_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_10__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_11_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_11__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_8_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_8__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_9_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_9__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_12_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_12__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_13_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_13__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_14_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_14__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_15_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_15__SHIFT 0x0000001c
+#define PB0_HW_DEBUG__PB0_HW_00_DEBUG_MASK 0x00000001L
+#define PB0_HW_DEBUG__PB0_HW_00_DEBUG__SHIFT 0x00000000
+#define PB0_HW_DEBUG__PB0_HW_01_DEBUG_MASK 0x00000002L
+#define PB0_HW_DEBUG__PB0_HW_01_DEBUG__SHIFT 0x00000001
+#define PB0_HW_DEBUG__PB0_HW_02_DEBUG_MASK 0x00000004L
+#define PB0_HW_DEBUG__PB0_HW_02_DEBUG__SHIFT 0x00000002
+#define PB0_HW_DEBUG__PB0_HW_03_DEBUG_MASK 0x00000008L
+#define PB0_HW_DEBUG__PB0_HW_03_DEBUG__SHIFT 0x00000003
+#define PB0_HW_DEBUG__PB0_HW_04_DEBUG_MASK 0x00000010L
+#define PB0_HW_DEBUG__PB0_HW_04_DEBUG__SHIFT 0x00000004
+#define PB0_HW_DEBUG__PB0_HW_05_DEBUG_MASK 0x00000020L
+#define PB0_HW_DEBUG__PB0_HW_05_DEBUG__SHIFT 0x00000005
+#define PB0_HW_DEBUG__PB0_HW_06_DEBUG_MASK 0x00000040L
+#define PB0_HW_DEBUG__PB0_HW_06_DEBUG__SHIFT 0x00000006
+#define PB0_HW_DEBUG__PB0_HW_07_DEBUG_MASK 0x00000080L
+#define PB0_HW_DEBUG__PB0_HW_07_DEBUG__SHIFT 0x00000007
+#define PB0_HW_DEBUG__PB0_HW_08_DEBUG_MASK 0x00000100L
+#define PB0_HW_DEBUG__PB0_HW_08_DEBUG__SHIFT 0x00000008
+#define PB0_HW_DEBUG__PB0_HW_09_DEBUG_MASK 0x00000200L
+#define PB0_HW_DEBUG__PB0_HW_09_DEBUG__SHIFT 0x00000009
+#define PB0_HW_DEBUG__PB0_HW_10_DEBUG_MASK 0x00000400L
+#define PB0_HW_DEBUG__PB0_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB0_HW_DEBUG__PB0_HW_11_DEBUG_MASK 0x00000800L
+#define PB0_HW_DEBUG__PB0_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB0_HW_DEBUG__PB0_HW_12_DEBUG_MASK 0x00001000L
+#define PB0_HW_DEBUG__PB0_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB0_HW_DEBUG__PB0_HW_13_DEBUG_MASK 0x00002000L
+#define PB0_HW_DEBUG__PB0_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB0_HW_DEBUG__PB0_HW_14_DEBUG_MASK 0x00004000L
+#define PB0_HW_DEBUG__PB0_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB0_HW_DEBUG__PB0_HW_15_DEBUG_MASK 0x00008000L
+#define PB0_HW_DEBUG__PB0_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB0_HW_DEBUG__PB0_HW_16_DEBUG_MASK 0x00010000L
+#define PB0_HW_DEBUG__PB0_HW_16_DEBUG__SHIFT 0x00000010
+#define PB0_HW_DEBUG__PB0_HW_17_DEBUG_MASK 0x00020000L
+#define PB0_HW_DEBUG__PB0_HW_17_DEBUG__SHIFT 0x00000011
+#define PB0_HW_DEBUG__PB0_HW_18_DEBUG_MASK 0x00040000L
+#define PB0_HW_DEBUG__PB0_HW_18_DEBUG__SHIFT 0x00000012
+#define PB0_HW_DEBUG__PB0_HW_19_DEBUG_MASK 0x00080000L
+#define PB0_HW_DEBUG__PB0_HW_19_DEBUG__SHIFT 0x00000013
+#define PB0_HW_DEBUG__PB0_HW_20_DEBUG_MASK 0x00100000L
+#define PB0_HW_DEBUG__PB0_HW_20_DEBUG__SHIFT 0x00000014
+#define PB0_HW_DEBUG__PB0_HW_21_DEBUG_MASK 0x00200000L
+#define PB0_HW_DEBUG__PB0_HW_21_DEBUG__SHIFT 0x00000015
+#define PB0_HW_DEBUG__PB0_HW_22_DEBUG_MASK 0x00400000L
+#define PB0_HW_DEBUG__PB0_HW_22_DEBUG__SHIFT 0x00000016
+#define PB0_HW_DEBUG__PB0_HW_23_DEBUG_MASK 0x00800000L
+#define PB0_HW_DEBUG__PB0_HW_23_DEBUG__SHIFT 0x00000017
+#define PB0_HW_DEBUG__PB0_HW_24_DEBUG_MASK 0x01000000L
+#define PB0_HW_DEBUG__PB0_HW_24_DEBUG__SHIFT 0x00000018
+#define PB0_HW_DEBUG__PB0_HW_25_DEBUG_MASK 0x02000000L
+#define PB0_HW_DEBUG__PB0_HW_25_DEBUG__SHIFT 0x00000019
+#define PB0_HW_DEBUG__PB0_HW_26_DEBUG_MASK 0x04000000L
+#define PB0_HW_DEBUG__PB0_HW_26_DEBUG__SHIFT 0x0000001a
+#define PB0_HW_DEBUG__PB0_HW_27_DEBUG_MASK 0x08000000L
+#define PB0_HW_DEBUG__PB0_HW_27_DEBUG__SHIFT 0x0000001b
+#define PB0_HW_DEBUG__PB0_HW_28_DEBUG_MASK 0x10000000L
+#define PB0_HW_DEBUG__PB0_HW_28_DEBUG__SHIFT 0x0000001c
+#define PB0_HW_DEBUG__PB0_HW_29_DEBUG_MASK 0x20000000L
+#define PB0_HW_DEBUG__PB0_HW_29_DEBUG__SHIFT 0x0000001d
+#define PB0_HW_DEBUG__PB0_HW_30_DEBUG_MASK 0x40000000L
+#define PB0_HW_DEBUG__PB0_HW_30_DEBUG__SHIFT 0x0000001e
+#define PB0_HW_DEBUG__PB0_HW_31_DEBUG_MASK 0x80000000L
+#define PB0_HW_DEBUG__PB0_HW_31_DEBUG__SHIFT 0x0000001f
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_EN_MASK 0x00000080L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_EN__SHIFT 0x00000007
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0_MASK 0x00000100L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0__SHIFT 0x00000008
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10_MASK 0x00040000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10__SHIFT 0x00000012
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11_MASK 0x00080000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11__SHIFT 0x00000013
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12_MASK 0x00100000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12__SHIFT 0x00000014
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13_MASK 0x00200000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13__SHIFT 0x00000015
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14_MASK 0x00400000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14__SHIFT 0x00000016
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15_MASK 0x00800000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15__SHIFT 0x00000017
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2_MASK 0x00000400L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2__SHIFT 0x0000000a
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3_MASK 0x00000800L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4_MASK 0x00001000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4__SHIFT 0x0000000c
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5_MASK 0x00002000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5__SHIFT 0x0000000d
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6_MASK 0x00004000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6__SHIFT 0x0000000e
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7_MASK 0x00008000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8_MASK 0x00010000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8__SHIFT 0x00000010
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9_MASK 0x00020000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9__SHIFT 0x00000011
+#define PB0_PIF_CNTL2__RXDETECT_SAMPL_TIME_MASK 0x00000006L
+#define PB0_PIF_CNTL2__RXDETECT_SAMPL_TIME__SHIFT 0x00000001
+#define PB0_PIF_CNTL2__RXPHYSTATUS_DELAY_MASK 0x07000000L
+#define PB0_PIF_CNTL2__RXPHYSTATUS_DELAY__SHIFT 0x00000018
+#define PB0_PIF_CNTL__DA_FIFO_RESET_0_MASK 0x00000002L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_0__SHIFT 0x00000001
+#define PB0_PIF_CNTL__DA_FIFO_RESET_1_MASK 0x00000020L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_1__SHIFT 0x00000005
+#define PB0_PIF_CNTL__DA_FIFO_RESET_2_MASK 0x00000200L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_2__SHIFT 0x00000009
+#define PB0_PIF_CNTL__DA_FIFO_RESET_3_MASK 0x00002000L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_3__SHIFT 0x0000000d
+#define PB0_PIF_CNTL__DIVINIT_MODE_MASK 0x00000100L
+#define PB0_PIF_CNTL__DIVINIT_MODE__SHIFT 0x00000008
+#define PB0_PIF_CNTL__EI_CYCLE_OFF_TIME_MASK 0x00700000L
+#define PB0_PIF_CNTL__EI_CYCLE_OFF_TIME__SHIFT 0x00000014
+#define PB0_PIF_CNTL__EI_DET_CYCLE_MODE_MASK 0x00000010L
+#define PB0_PIF_CNTL__EI_DET_CYCLE_MODE__SHIFT 0x00000004
+#define PB0_PIF_CNTL__EXIT_L0S_INIT_DIS_MASK 0x00800000L
+#define PB0_PIF_CNTL__EXIT_L0S_INIT_DIS__SHIFT 0x00000017
+#define PB0_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP_MASK 0x10000000L
+#define PB0_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP__SHIFT 0x0000001c
+#define PB0_PIF_CNTL__IGNORE_TxDataValid_EP_DIS_MASK 0x20000000L
+#define PB0_PIF_CNTL__IGNORE_TxDataValid_EP_DIS__SHIFT 0x0000001d
+#define PB0_PIF_CNTL__LS2_EXIT_TIME_MASK 0x000e0000L
+#define PB0_PIF_CNTL__LS2_EXIT_TIME__SHIFT 0x00000011
+#define PB0_PIF_CNTL__PHYCMD_CR_EN_MODE_MASK 0x00000008L
+#define PB0_PIF_CNTL__PHYCMD_CR_EN_MODE__SHIFT 0x00000003
+#define PB0_PIF_CNTL__PHY_CR_EN_MODE_MASK 0x00000004L
+#define PB0_PIF_CNTL__PHY_CR_EN_MODE__SHIFT 0x00000002
+#define PB0_PIF_CNTL__PLL_BINDING_ENABLE_MASK 0x00000400L
+#define PB0_PIF_CNTL__PLL_BINDING_ENABLE__SHIFT 0x0000000a
+#define PB0_PIF_CNTL__RXDETECT_FIFO_RESET_MODE_MASK 0x00000040L
+#define PB0_PIF_CNTL__RXDETECT_FIFO_RESET_MODE__SHIFT 0x00000006
+#define PB0_PIF_CNTL__RXDETECT_TX_PWR_MODE_MASK 0x00000080L
+#define PB0_PIF_CNTL__RXDETECT_TX_PWR_MODE__SHIFT 0x00000007
+#define PB0_PIF_CNTL__RXEN_GATER_MASK 0x0f000000L
+#define PB0_PIF_CNTL__RXEN_GATER__SHIFT 0x00000018
+#define PB0_PIF_CNTL__SC_CALIB_DONE_CNTL_MASK 0x00000800L
+#define PB0_PIF_CNTL__SC_CALIB_DONE_CNTL__SHIFT 0x0000000b
+#define PB0_PIF_CNTL__SERIAL_CFG_ENABLE_MASK 0x00000001L
+#define PB0_PIF_CNTL__SERIAL_CFG_ENABLE__SHIFT 0x00000000
+#define PB0_PIF_CNTL__TXGND_TIME_MASK 0x00010000L
+#define PB0_PIF_CNTL__TXGND_TIME__SHIFT 0x00000010
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_00_DEBUG_MASK 0x00000001L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_00_DEBUG__SHIFT 0x00000000
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_01_DEBUG_MASK 0x00000002L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_01_DEBUG__SHIFT 0x00000001
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_02_DEBUG_MASK 0x00000004L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_02_DEBUG__SHIFT 0x00000002
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_03_DEBUG_MASK 0x00000008L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_03_DEBUG__SHIFT 0x00000003
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_04_DEBUG_MASK 0x00000010L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_04_DEBUG__SHIFT 0x00000004
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_05_DEBUG_MASK 0x00000020L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_05_DEBUG__SHIFT 0x00000005
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_06_DEBUG_MASK 0x00000040L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_06_DEBUG__SHIFT 0x00000006
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_07_DEBUG_MASK 0x00000080L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_07_DEBUG__SHIFT 0x00000007
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_08_DEBUG_MASK 0x00000100L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_08_DEBUG__SHIFT 0x00000008
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_09_DEBUG_MASK 0x00000200L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_09_DEBUG__SHIFT 0x00000009
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_10_DEBUG_MASK 0x00000400L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_11_DEBUG_MASK 0x00000800L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_12_DEBUG_MASK 0x00001000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_13_DEBUG_MASK 0x00002000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_14_DEBUG_MASK 0x00004000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_15_DEBUG_MASK 0x00008000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB0_PIF_PAIRING__MULTI_PIF_MASK 0x02000000L
+#define PB0_PIF_PAIRING__MULTI_PIF__SHIFT 0x00000019
+#define PB0_PIF_PAIRING__X16_LANE_15_0_MASK 0x00100000L
+#define PB0_PIF_PAIRING__X16_LANE_15_0__SHIFT 0x00000014
+#define PB0_PIF_PAIRING__X2_LANE_1_0_MASK 0x00000001L
+#define PB0_PIF_PAIRING__X2_LANE_1_0__SHIFT 0x00000000
+#define PB0_PIF_PAIRING__X2_LANE_11_10_MASK 0x00000020L
+#define PB0_PIF_PAIRING__X2_LANE_11_10__SHIFT 0x00000005
+#define PB0_PIF_PAIRING__X2_LANE_13_12_MASK 0x00000040L
+#define PB0_PIF_PAIRING__X2_LANE_13_12__SHIFT 0x00000006
+#define PB0_PIF_PAIRING__X2_LANE_15_14_MASK 0x00000080L
+#define PB0_PIF_PAIRING__X2_LANE_15_14__SHIFT 0x00000007
+#define PB0_PIF_PAIRING__X2_LANE_3_2_MASK 0x00000002L
+#define PB0_PIF_PAIRING__X2_LANE_3_2__SHIFT 0x00000001
+#define PB0_PIF_PAIRING__X2_LANE_5_4_MASK 0x00000004L
+#define PB0_PIF_PAIRING__X2_LANE_5_4__SHIFT 0x00000002
+#define PB0_PIF_PAIRING__X2_LANE_7_6_MASK 0x00000008L
+#define PB0_PIF_PAIRING__X2_LANE_7_6__SHIFT 0x00000003
+#define PB0_PIF_PAIRING__X2_LANE_9_8_MASK 0x00000010L
+#define PB0_PIF_PAIRING__X2_LANE_9_8__SHIFT 0x00000004
+#define PB0_PIF_PAIRING__X4_LANE_11_8_MASK 0x00000400L
+#define PB0_PIF_PAIRING__X4_LANE_11_8__SHIFT 0x0000000a
+#define PB0_PIF_PAIRING__X4_LANE_15_12_MASK 0x00000800L
+#define PB0_PIF_PAIRING__X4_LANE_15_12__SHIFT 0x0000000b
+#define PB0_PIF_PAIRING__X4_LANE_3_0_MASK 0x00000100L
+#define PB0_PIF_PAIRING__X4_LANE_3_0__SHIFT 0x00000008
+#define PB0_PIF_PAIRING__X4_LANE_7_4_MASK 0x00000200L
+#define PB0_PIF_PAIRING__X4_LANE_7_4__SHIFT 0x00000009
+#define PB0_PIF_PAIRING__X8_LANE_15_8_MASK 0x00020000L
+#define PB0_PIF_PAIRING__X8_LANE_15_8__SHIFT 0x00000011
+#define PB0_PIF_PAIRING__X8_LANE_7_0_MASK 0x00010000L
+#define PB0_PIF_PAIRING__X8_LANE_7_0__SHIFT 0x00000010
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000b
+#define PB0_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3__SHIFT 0x00000000
+#define PB0_PIF_SC_CTL__SC_CALIBRATION_MASK 0x00000001L
+#define PB0_PIF_SC_CTL__SC_CALIBRATION__SHIFT 0x00000000
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0_MASK 0x00000020L
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0__SHIFT 0x00000005
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S_MASK 0x00000010L
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S__SHIFT 0x00000004
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0_MASK 0x00000008L
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0__SHIFT 0x00000003
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0S_MASK 0x00000004L
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0S__SHIFT 0x00000002
+#define PB0_PIF_SC_CTL__SC_LANE_0_RESUME_MASK 0x00010000L
+#define PB0_PIF_SC_CTL__SC_LANE_0_RESUME__SHIFT 0x00000010
+#define PB0_PIF_SC_CTL__SC_LANE_10_RESUME_MASK 0x04000000L
+#define PB0_PIF_SC_CTL__SC_LANE_10_RESUME__SHIFT 0x0000001a
+#define PB0_PIF_SC_CTL__SC_LANE_11_RESUME_MASK 0x08000000L
+#define PB0_PIF_SC_CTL__SC_LANE_11_RESUME__SHIFT 0x0000001b
+#define PB0_PIF_SC_CTL__SC_LANE_12_RESUME_MASK 0x10000000L
+#define PB0_PIF_SC_CTL__SC_LANE_12_RESUME__SHIFT 0x0000001c
+#define PB0_PIF_SC_CTL__SC_LANE_13_RESUME_MASK 0x20000000L
+#define PB0_PIF_SC_CTL__SC_LANE_13_RESUME__SHIFT 0x0000001d
+#define PB0_PIF_SC_CTL__SC_LANE_14_RESUME_MASK 0x40000000L
+#define PB0_PIF_SC_CTL__SC_LANE_14_RESUME__SHIFT 0x0000001e
+#define PB0_PIF_SC_CTL__SC_LANE_15_RESUME_MASK 0x80000000L
+#define PB0_PIF_SC_CTL__SC_LANE_15_RESUME__SHIFT 0x0000001f
+#define PB0_PIF_SC_CTL__SC_LANE_1_RESUME_MASK 0x00020000L
+#define PB0_PIF_SC_CTL__SC_LANE_1_RESUME__SHIFT 0x00000011
+#define PB0_PIF_SC_CTL__SC_LANE_2_RESUME_MASK 0x00040000L
+#define PB0_PIF_SC_CTL__SC_LANE_2_RESUME__SHIFT 0x00000012
+#define PB0_PIF_SC_CTL__SC_LANE_3_RESUME_MASK 0x00080000L
+#define PB0_PIF_SC_CTL__SC_LANE_3_RESUME__SHIFT 0x00000013
+#define PB0_PIF_SC_CTL__SC_LANE_4_RESUME_MASK 0x00100000L
+#define PB0_PIF_SC_CTL__SC_LANE_4_RESUME__SHIFT 0x00000014
+#define PB0_PIF_SC_CTL__SC_LANE_5_RESUME_MASK 0x00200000L
+#define PB0_PIF_SC_CTL__SC_LANE_5_RESUME__SHIFT 0x00000015
+#define PB0_PIF_SC_CTL__SC_LANE_6_RESUME_MASK 0x00400000L
+#define PB0_PIF_SC_CTL__SC_LANE_6_RESUME__SHIFT 0x00000016
+#define PB0_PIF_SC_CTL__SC_LANE_7_RESUME_MASK 0x00800000L
+#define PB0_PIF_SC_CTL__SC_LANE_7_RESUME__SHIFT 0x00000017
+#define PB0_PIF_SC_CTL__SC_LANE_8_RESUME_MASK 0x01000000L
+#define PB0_PIF_SC_CTL__SC_LANE_8_RESUME__SHIFT 0x00000018
+#define PB0_PIF_SC_CTL__SC_LANE_9_RESUME_MASK 0x02000000L
+#define PB0_PIF_SC_CTL__SC_LANE_9_RESUME__SHIFT 0x00000019
+#define PB0_PIF_SC_CTL__SC_PHASE_1_MASK 0x00000100L
+#define PB0_PIF_SC_CTL__SC_PHASE_1__SHIFT 0x00000008
+#define PB0_PIF_SC_CTL__SC_PHASE_2_MASK 0x00000200L
+#define PB0_PIF_SC_CTL__SC_PHASE_2__SHIFT 0x00000009
+#define PB0_PIF_SC_CTL__SC_PHASE_3_MASK 0x00000400L
+#define PB0_PIF_SC_CTL__SC_PHASE_3__SHIFT 0x0000000a
+#define PB0_PIF_SC_CTL__SC_PHASE_4_MASK 0x00000800L
+#define PB0_PIF_SC_CTL__SC_PHASE_4__SHIFT 0x0000000b
+#define PB0_PIF_SC_CTL__SC_PHASE_5_MASK 0x00001000L
+#define PB0_PIF_SC_CTL__SC_PHASE_5__SHIFT 0x0000000c
+#define PB0_PIF_SC_CTL__SC_PHASE_6_MASK 0x00002000L
+#define PB0_PIF_SC_CTL__SC_PHASE_6__SHIFT 0x0000000d
+#define PB0_PIF_SC_CTL__SC_PHASE_7_MASK 0x00004000L
+#define PB0_PIF_SC_CTL__SC_PHASE_7__SHIFT 0x0000000e
+#define PB0_PIF_SC_CTL__SC_PHASE_8_MASK 0x00008000L
+#define PB0_PIF_SC_CTL__SC_PHASE_8__SHIFT 0x0000000f
+#define PB0_PIF_SC_CTL__SC_RXDETECT_MASK 0x00000002L
+#define PB0_PIF_SC_CTL__SC_RXDETECT__SHIFT 0x00000001
+#define PB0_PIF_SC_CTL__SC_SPEED_CHANGE_MASK 0x00000040L
+#define PB0_PIF_SC_CTL__SC_SPEED_CHANGE__SHIFT 0x00000006
+#define PB0_PIF_SCRATCH__PIF_SCRATCH_MASK 0xffffffffL
+#define PB0_PIF_SCRATCH__PIF_SCRATCH__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_0__SEQ_PHASE_0_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_PHASE_0__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_10__SEQ_PHASE_10_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_PHASE_10__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_11__SEQ_PHASE_11_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_PHASE_11__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_12__SEQ_PHASE_12_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_PHASE_12__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_13__SEQ_PHASE_13_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_PHASE_13__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_14__SEQ_PHASE_14_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_PHASE_14__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_15__SEQ_PHASE_15_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_PHASE_15__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_1__SEQ_PHASE_1_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_PHASE_1__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_2__SEQ_PHASE_2_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_PHASE_2__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_3__SEQ_PHASE_3_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_PHASE_3__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_4__SEQ_PHASE_4_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_PHASE_4__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_5__SEQ_PHASE_5_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_PHASE_5__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_6__SEQ_PHASE_6_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_PHASE_6__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_7__SEQ_PHASE_7_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_PHASE_7__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_8__SEQ_PHASE_8_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_PHASE_8__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_9__SEQ_PHASE_9_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_PHASE_9__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9__SHIFT 0x00000006
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_0_MASK 0x00000001L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_0__SHIFT 0x00000000
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_10_MASK 0x00000400L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_10__SHIFT 0x0000000a
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_11_MASK 0x00000800L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_11__SHIFT 0x0000000b
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_12_MASK 0x00001000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_12__SHIFT 0x0000000c
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_13_MASK 0x00002000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_13__SHIFT 0x0000000d
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_14_MASK 0x00004000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_14__SHIFT 0x0000000e
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_15_MASK 0x00008000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_15__SHIFT 0x0000000f
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_1_MASK 0x00000002L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_1__SHIFT 0x00000001
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_2_MASK 0x00000004L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_2__SHIFT 0x00000002
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_3_MASK 0x00000008L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_3__SHIFT 0x00000003
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_4_MASK 0x00000010L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_4__SHIFT 0x00000004
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_5_MASK 0x00000020L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_5__SHIFT 0x00000005
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_6_MASK 0x00000040L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_6__SHIFT 0x00000006
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_7_MASK 0x00000080L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_7__SHIFT 0x00000007
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_8_MASK 0x00000100L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_8__SHIFT 0x00000008
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_9_MASK 0x00000200L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_9__SHIFT 0x00000009
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0_MASK 0x00000003L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0_MASK 0x00000010L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0_MASK 0x00000007L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0_MASK 0x00000080L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000070L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0_MASK 0x00000200L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0__SHIFT 0x00000009
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0_MASK 0x00000100L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0__SHIFT 0x00000008
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0_MASK 0x00040000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0__SHIFT 0x00000012
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0_MASK 0x0003fc00L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0__SHIFT 0x0000000a
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0_MASK 0x10000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0__SHIFT 0x0000001c
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0_MASK 0x0ff80000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0__SHIFT 0x00000013
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0_MASK 0x80000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0__SHIFT 0x0000001f
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0_MASK 0x60000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0__SHIFT 0x0000001d
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0_MASK 0x00000007L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0_MASK 0x00040000L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0__SHIFT 0x00000012
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0_MASK 0x0003c000L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0__SHIFT 0x0000000e
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000020L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000010L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00000080L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000040L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0_MASK 0x00000200L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0__SHIFT 0x00000009
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0_MASK 0x00000100L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0__SHIFT 0x00000008
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0_MASK 0x00000003L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0_MASK 0x000007f0L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0__SHIFT 0x00000004
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB0_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0_MASK 0x00000800L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0__SHIFT 0x0000000b
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0_MASK 0x00000100L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000008
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0_MASK 0x000000ffL
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0_MASK 0x00001000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0__SHIFT 0x0000000c
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000e00L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000009
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0_MASK 0x00004000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0__SHIFT 0x0000000e
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0_MASK 0x00002000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0_MASK 0x10000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0__SHIFT 0x0000001c
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0_MASK 0x0fff8000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0__SHIFT 0x0000000f
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0_MASK 0x80000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0__SHIFT 0x0000001f
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0_MASK 0x40000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0__SHIFT 0x0000001e
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0_MASK 0x00400000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000016
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0_MASK 0x00380000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000013
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0_MASK 0x00000020L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0_MASK 0x0000001fL
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0_MASK 0x00000100L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0__SHIFT 0x00000008
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0_MASK 0x000000c0L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000400L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x0000000a
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000200L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000009
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00001000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x0000000c
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000800L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x0000000b
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0_MASK 0x00004000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0__SHIFT 0x0000000e
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0_MASK 0x00002000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000200L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000009
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000400L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000a
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000800L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000b
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00100000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000014
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00200000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000015
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00001000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x0000000c
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00002000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000d
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00004000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000e
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00400000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000016
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00800000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000017
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2_MASK 0x00000100L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000008
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000002L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000001
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000004L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x00000002
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000008L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x00000003
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00010000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000010
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00020000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000011
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00000010L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x00000004
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00000020L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x00000005
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00000040L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x00000006
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00040000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000012
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00080000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000013
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2_MASK 0x00000080L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000007
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC_MASK 0x00000001L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1_MASK 0x000003ffL
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2_MASK 0x000ffc00L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2__SHIFT 0x0000000a
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3_MASK 0x3ff00000L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1_MASK 0x01000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2_MASK 0x02000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2__SHIFT 0x00000019
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3_MASK 0x04000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1_MASK 0x03000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2_MASK 0x0c000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3_MASK 0x30000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1_MASK 0x00000001L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2_MASK 0x00000002L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2__SHIFT 0x00000001
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3_MASK 0x00000004L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3__SHIFT 0x00000002
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2_MASK 0x0f000000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3_MASK 0xf0000000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1_MASK 0x00000007L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2_MASK 0x00000038L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2__SHIFT 0x00000003
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3_MASK 0x000001c0L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3__SHIFT 0x00000006
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2_MASK 0x0f000000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3_MASK 0xf0000000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1_MASK 0x00000e00L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1__SHIFT 0x00000009
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2_MASK 0x00007000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3_MASK 0x00038000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3__SHIFT 0x0000000f
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1_MASK 0x0000001fL
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2_MASK 0x000003e0L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2__SHIFT 0x00000005
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3_MASK 0x00007c00L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3__SHIFT 0x0000000a
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1_MASK 0x00008000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1__SHIFT 0x0000000f
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2_MASK 0x00010000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3_MASK 0x00020000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3__SHIFT 0x00000011
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1_MASK 0x00040000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1__SHIFT 0x00000012
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2_MASK 0x00080000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2__SHIFT 0x00000013
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3_MASK 0x00100000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0_MASK 0x40000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x01000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2_MASK 0x04000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1_MASK 0x001c0000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1__SHIFT 0x00000012
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2_MASK 0x00e00000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2__SHIFT 0x00000015
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3_MASK 0x07000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x00001000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2_MASK 0x00002000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2__SHIFT 0x0000000d
+#define PB0_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2_MASK 0x00020000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000011
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN_MASK 0x80000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN__SHIFT 0x0000001f
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL_MASK 0x40000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL__SHIFT 0x0000001e
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN_MASK 0x00000002L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN__SHIFT 0x00000001
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL_MASK 0x00000001L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL__SHIFT 0x00000000
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN_MASK 0x00000008L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN__SHIFT 0x00000003
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL_MASK 0x00000004L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL__SHIFT 0x00000002
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN_MASK 0x20000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN__SHIFT 0x0000001d
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL_MASK 0x10000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000100L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000008
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x000000c0L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000006
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN_MASK 0x00000400L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN__SHIFT 0x0000000a
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL_MASK 0x00000200L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL__SHIFT 0x00000009
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00001000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000c
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000800L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x0000000b
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN_MASK 0x00004000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN__SHIFT 0x0000000e
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL_MASK 0x00002000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL__SHIFT 0x0000000d
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN_MASK 0x00010000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN__SHIFT 0x00000010
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL_MASK 0x00008000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL__SHIFT 0x0000000f
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN_MASK 0x00040000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN__SHIFT 0x00000012
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL_MASK 0x00020000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL__SHIFT 0x00000011
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN_MASK 0x00100000L
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN__SHIFT 0x00000014
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL_MASK 0x00080000L
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL__SHIFT 0x00000013
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN_MASK 0x00400000L
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN__SHIFT 0x00000016
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL_MASK 0x00200000L
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL__SHIFT 0x00000015
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN_MASK 0x01000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN__SHIFT 0x00000018
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL_MASK 0x00800000L
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL__SHIFT 0x00000017
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN_MASK 0x00000002L
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN__SHIFT 0x00000001
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL_MASK 0x00000001L
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL__SHIFT 0x00000000
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3_MASK 0x00010000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3__SHIFT 0x00000010
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15_MASK 0x00080000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15__SHIFT 0x00000013
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7_MASK 0x00020000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7__SHIFT 0x00000011
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11_MASK 0x00040000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11__SHIFT 0x00000012
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3_MASK 0x00100000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3__SHIFT 0x00000014
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15_MASK 0x00800000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15__SHIFT 0x00000017
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7_MASK 0x00200000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7__SHIFT 0x00000015
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11_MASK 0x00400000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11__SHIFT 0x00000016
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_RX_LANE0_CTRL_REG0__RX_BACKUP_0_MASK 0x000000ffL
+#define PB0_RX_LANE0_CTRL_REG0__RX_BACKUP_0__SHIFT 0x00000000
+#define PB0_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0_MASK 0x00002000L
+#define PB0_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0__SHIFT 0x0000000d
+#define PB0_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0_MASK 0x00000c00L
+#define PB0_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0__SHIFT 0x0000000a
+#define PB0_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0_MASK 0x00001000L
+#define PB0_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0__SHIFT 0x0000000c
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0_MASK 0x00000008L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0__SHIFT 0x00000003
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0_MASK 0x00000080L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0__SHIFT 0x00000007
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0_MASK 0x00000100L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0__SHIFT 0x00000008
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0_MASK 0x00000200L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0__SHIFT 0x00000009
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0_MASK 0x00000070L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0__SHIFT 0x00000004
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0_MASK 0x00000007L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0__SHIFT 0x00000000
+#define PB0_RX_LANE10_CTRL_REG0__RX_BACKUP_10_MASK 0x000000ffL
+#define PB0_RX_LANE10_CTRL_REG0__RX_BACKUP_10__SHIFT 0x00000000
+#define PB0_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10_MASK 0x00002000L
+#define PB0_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10__SHIFT 0x0000000d
+#define PB0_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10_MASK 0x00000c00L
+#define PB0_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10__SHIFT 0x0000000a
+#define PB0_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10_MASK 0x00001000L
+#define PB0_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10__SHIFT 0x0000000c
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10_MASK 0x00000008L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10__SHIFT 0x00000003
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10_MASK 0x00000080L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10__SHIFT 0x00000007
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10_MASK 0x00000100L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10__SHIFT 0x00000008
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10_MASK 0x00000200L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10__SHIFT 0x00000009
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10_MASK 0x00000070L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10__SHIFT 0x00000004
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10_MASK 0x00000007L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10__SHIFT 0x00000000
+#define PB0_RX_LANE11_CTRL_REG0__RX_BACKUP_11_MASK 0x000000ffL
+#define PB0_RX_LANE11_CTRL_REG0__RX_BACKUP_11__SHIFT 0x00000000
+#define PB0_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11_MASK 0x00002000L
+#define PB0_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11__SHIFT 0x0000000d
+#define PB0_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11_MASK 0x00000c00L
+#define PB0_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11__SHIFT 0x0000000a
+#define PB0_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11_MASK 0x00001000L
+#define PB0_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11__SHIFT 0x0000000c
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11_MASK 0x00000008L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11__SHIFT 0x00000003
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11_MASK 0x00000080L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11__SHIFT 0x00000007
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11_MASK 0x00000100L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11__SHIFT 0x00000008
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11_MASK 0x00000200L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11__SHIFT 0x00000009
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11_MASK 0x00000070L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11__SHIFT 0x00000004
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11_MASK 0x00000007L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11__SHIFT 0x00000000
+#define PB0_RX_LANE12_CTRL_REG0__RX_BACKUP_12_MASK 0x000000ffL
+#define PB0_RX_LANE12_CTRL_REG0__RX_BACKUP_12__SHIFT 0x00000000
+#define PB0_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12_MASK 0x00002000L
+#define PB0_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12__SHIFT 0x0000000d
+#define PB0_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12_MASK 0x00000c00L
+#define PB0_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12__SHIFT 0x0000000a
+#define PB0_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12_MASK 0x00001000L
+#define PB0_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12__SHIFT 0x0000000c
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12_MASK 0x00000008L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12__SHIFT 0x00000003
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12_MASK 0x00000080L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12__SHIFT 0x00000007
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12_MASK 0x00000100L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12__SHIFT 0x00000008
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12_MASK 0x00000200L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12__SHIFT 0x00000009
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12_MASK 0x00000070L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12__SHIFT 0x00000004
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12_MASK 0x00000007L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12__SHIFT 0x00000000
+#define PB0_RX_LANE13_CTRL_REG0__RX_BACKUP_13_MASK 0x000000ffL
+#define PB0_RX_LANE13_CTRL_REG0__RX_BACKUP_13__SHIFT 0x00000000
+#define PB0_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13_MASK 0x00002000L
+#define PB0_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13__SHIFT 0x0000000d
+#define PB0_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13_MASK 0x00000c00L
+#define PB0_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13__SHIFT 0x0000000a
+#define PB0_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13_MASK 0x00001000L
+#define PB0_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13__SHIFT 0x0000000c
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13_MASK 0x00000008L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13__SHIFT 0x00000003
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13_MASK 0x00000080L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13__SHIFT 0x00000007
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13_MASK 0x00000100L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13__SHIFT 0x00000008
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13_MASK 0x00000200L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13__SHIFT 0x00000009
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13_MASK 0x00000070L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13__SHIFT 0x00000004
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13_MASK 0x00000007L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13__SHIFT 0x00000000
+#define PB0_RX_LANE14_CTRL_REG0__RX_BACKUP_14_MASK 0x000000ffL
+#define PB0_RX_LANE14_CTRL_REG0__RX_BACKUP_14__SHIFT 0x00000000
+#define PB0_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14_MASK 0x00002000L
+#define PB0_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14__SHIFT 0x0000000d
+#define PB0_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14_MASK 0x00000c00L
+#define PB0_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14__SHIFT 0x0000000a
+#define PB0_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14_MASK 0x00001000L
+#define PB0_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14__SHIFT 0x0000000c
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14_MASK 0x00000008L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14__SHIFT 0x00000003
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14_MASK 0x00000080L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14__SHIFT 0x00000007
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14_MASK 0x00000100L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14__SHIFT 0x00000008
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14_MASK 0x00000200L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14__SHIFT 0x00000009
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14_MASK 0x00000070L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14__SHIFT 0x00000004
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14_MASK 0x00000007L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14__SHIFT 0x00000000
+#define PB0_RX_LANE15_CTRL_REG0__RX_BACKUP_15_MASK 0x000000ffL
+#define PB0_RX_LANE15_CTRL_REG0__RX_BACKUP_15__SHIFT 0x00000000
+#define PB0_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15_MASK 0x00002000L
+#define PB0_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15__SHIFT 0x0000000d
+#define PB0_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15_MASK 0x00000c00L
+#define PB0_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15__SHIFT 0x0000000a
+#define PB0_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15_MASK 0x00001000L
+#define PB0_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15__SHIFT 0x0000000c
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15_MASK 0x00000008L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15__SHIFT 0x00000003
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15_MASK 0x00000080L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15__SHIFT 0x00000007
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15_MASK 0x00000100L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15__SHIFT 0x00000008
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15_MASK 0x00000200L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15__SHIFT 0x00000009
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15_MASK 0x00000070L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15__SHIFT 0x00000004
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15_MASK 0x00000007L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15__SHIFT 0x00000000
+#define PB0_RX_LANE1_CTRL_REG0__RX_BACKUP_1_MASK 0x000000ffL
+#define PB0_RX_LANE1_CTRL_REG0__RX_BACKUP_1__SHIFT 0x00000000
+#define PB0_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1_MASK 0x00002000L
+#define PB0_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1__SHIFT 0x0000000d
+#define PB0_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1_MASK 0x00000c00L
+#define PB0_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1__SHIFT 0x0000000a
+#define PB0_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1_MASK 0x00001000L
+#define PB0_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1__SHIFT 0x0000000c
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1_MASK 0x00000008L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1__SHIFT 0x00000003
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1_MASK 0x00000080L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1__SHIFT 0x00000007
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1_MASK 0x00000100L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1__SHIFT 0x00000008
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1_MASK 0x00000200L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1__SHIFT 0x00000009
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1_MASK 0x00000070L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1__SHIFT 0x00000004
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1_MASK 0x00000007L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1__SHIFT 0x00000000
+#define PB0_RX_LANE2_CTRL_REG0__RX_BACKUP_2_MASK 0x000000ffL
+#define PB0_RX_LANE2_CTRL_REG0__RX_BACKUP_2__SHIFT 0x00000000
+#define PB0_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2_MASK 0x00002000L
+#define PB0_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2__SHIFT 0x0000000d
+#define PB0_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2_MASK 0x00000c00L
+#define PB0_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2__SHIFT 0x0000000a
+#define PB0_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2_MASK 0x00001000L
+#define PB0_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2__SHIFT 0x0000000c
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2_MASK 0x00000008L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2__SHIFT 0x00000003
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2_MASK 0x00000080L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2__SHIFT 0x00000007
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2_MASK 0x00000100L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2__SHIFT 0x00000008
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2_MASK 0x00000200L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2__SHIFT 0x00000009
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2_MASK 0x00000070L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2__SHIFT 0x00000004
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2_MASK 0x00000007L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2__SHIFT 0x00000000
+#define PB0_RX_LANE3_CTRL_REG0__RX_BACKUP_3_MASK 0x000000ffL
+#define PB0_RX_LANE3_CTRL_REG0__RX_BACKUP_3__SHIFT 0x00000000
+#define PB0_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3_MASK 0x00002000L
+#define PB0_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3__SHIFT 0x0000000d
+#define PB0_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3_MASK 0x00000c00L
+#define PB0_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3__SHIFT 0x0000000a
+#define PB0_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3_MASK 0x00001000L
+#define PB0_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3__SHIFT 0x0000000c
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3_MASK 0x00000008L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3__SHIFT 0x00000003
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3_MASK 0x00000080L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3__SHIFT 0x00000007
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3_MASK 0x00000100L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3__SHIFT 0x00000008
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3_MASK 0x00000200L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3__SHIFT 0x00000009
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3_MASK 0x00000070L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3__SHIFT 0x00000004
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3_MASK 0x00000007L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3__SHIFT 0x00000000
+#define PB0_RX_LANE4_CTRL_REG0__RX_BACKUP_4_MASK 0x000000ffL
+#define PB0_RX_LANE4_CTRL_REG0__RX_BACKUP_4__SHIFT 0x00000000
+#define PB0_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4_MASK 0x00002000L
+#define PB0_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4__SHIFT 0x0000000d
+#define PB0_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4_MASK 0x00000c00L
+#define PB0_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4__SHIFT 0x0000000a
+#define PB0_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4_MASK 0x00001000L
+#define PB0_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4__SHIFT 0x0000000c
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4_MASK 0x00000008L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4__SHIFT 0x00000003
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4_MASK 0x00000080L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4__SHIFT 0x00000007
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4_MASK 0x00000100L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4__SHIFT 0x00000008
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4_MASK 0x00000200L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4__SHIFT 0x00000009
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4_MASK 0x00000070L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4__SHIFT 0x00000004
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4_MASK 0x00000007L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4__SHIFT 0x00000000
+#define PB0_RX_LANE5_CTRL_REG0__RX_BACKUP_5_MASK 0x000000ffL
+#define PB0_RX_LANE5_CTRL_REG0__RX_BACKUP_5__SHIFT 0x00000000
+#define PB0_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5_MASK 0x00002000L
+#define PB0_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5__SHIFT 0x0000000d
+#define PB0_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5_MASK 0x00000c00L
+#define PB0_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5__SHIFT 0x0000000a
+#define PB0_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5_MASK 0x00001000L
+#define PB0_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5__SHIFT 0x0000000c
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5_MASK 0x00000008L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5__SHIFT 0x00000003
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5_MASK 0x00000080L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5__SHIFT 0x00000007
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5_MASK 0x00000100L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5__SHIFT 0x00000008
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5_MASK 0x00000200L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5__SHIFT 0x00000009
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5_MASK 0x00000070L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5__SHIFT 0x00000004
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5_MASK 0x00000007L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5__SHIFT 0x00000000
+#define PB0_RX_LANE6_CTRL_REG0__RX_BACKUP_6_MASK 0x000000ffL
+#define PB0_RX_LANE6_CTRL_REG0__RX_BACKUP_6__SHIFT 0x00000000
+#define PB0_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6_MASK 0x00002000L
+#define PB0_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6__SHIFT 0x0000000d
+#define PB0_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6_MASK 0x00000c00L
+#define PB0_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6__SHIFT 0x0000000a
+#define PB0_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6_MASK 0x00001000L
+#define PB0_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6__SHIFT 0x0000000c
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6_MASK 0x00000008L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6__SHIFT 0x00000003
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6_MASK 0x00000080L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6__SHIFT 0x00000007
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6_MASK 0x00000100L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6__SHIFT 0x00000008
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6_MASK 0x00000200L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6__SHIFT 0x00000009
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6_MASK 0x00000070L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6__SHIFT 0x00000004
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6_MASK 0x00000007L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6__SHIFT 0x00000000
+#define PB0_RX_LANE7_CTRL_REG0__RX_BACKUP_7_MASK 0x000000ffL
+#define PB0_RX_LANE7_CTRL_REG0__RX_BACKUP_7__SHIFT 0x00000000
+#define PB0_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7_MASK 0x00002000L
+#define PB0_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7__SHIFT 0x0000000d
+#define PB0_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7_MASK 0x00000c00L
+#define PB0_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7__SHIFT 0x0000000a
+#define PB0_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7_MASK 0x00001000L
+#define PB0_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7__SHIFT 0x0000000c
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7_MASK 0x00000008L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7__SHIFT 0x00000003
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7_MASK 0x00000080L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7__SHIFT 0x00000007
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7_MASK 0x00000100L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7__SHIFT 0x00000008
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7_MASK 0x00000200L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7__SHIFT 0x00000009
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7_MASK 0x00000070L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7__SHIFT 0x00000004
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7_MASK 0x00000007L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7__SHIFT 0x00000000
+#define PB0_RX_LANE8_CTRL_REG0__RX_BACKUP_8_MASK 0x000000ffL
+#define PB0_RX_LANE8_CTRL_REG0__RX_BACKUP_8__SHIFT 0x00000000
+#define PB0_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8_MASK 0x00002000L
+#define PB0_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8__SHIFT 0x0000000d
+#define PB0_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8_MASK 0x00000c00L
+#define PB0_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8__SHIFT 0x0000000a
+#define PB0_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8_MASK 0x00001000L
+#define PB0_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8__SHIFT 0x0000000c
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8_MASK 0x00000008L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8__SHIFT 0x00000003
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8_MASK 0x00000080L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8__SHIFT 0x00000007
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8_MASK 0x00000100L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8__SHIFT 0x00000008
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8_MASK 0x00000200L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8__SHIFT 0x00000009
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8_MASK 0x00000070L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8__SHIFT 0x00000004
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8_MASK 0x00000007L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8__SHIFT 0x00000000
+#define PB0_RX_LANE9_CTRL_REG0__RX_BACKUP_9_MASK 0x000000ffL
+#define PB0_RX_LANE9_CTRL_REG0__RX_BACKUP_9__SHIFT 0x00000000
+#define PB0_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9_MASK 0x00002000L
+#define PB0_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9__SHIFT 0x0000000d
+#define PB0_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9_MASK 0x00000c00L
+#define PB0_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9__SHIFT 0x0000000a
+#define PB0_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9_MASK 0x00001000L
+#define PB0_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9__SHIFT 0x0000000c
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9_MASK 0x00000008L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9__SHIFT 0x00000003
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9_MASK 0x00000080L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9__SHIFT 0x00000007
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9_MASK 0x00000100L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9__SHIFT 0x00000008
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9_MASK 0x00000200L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9__SHIFT 0x00000009
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9_MASK 0x00000070L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9__SHIFT 0x00000004
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9_MASK 0x00000007L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9__SHIFT 0x00000000
+#define PB0_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL_MASK 0x00008000L
+#define PB0_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99__SHIFT 0x00000003
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1_MASK 0x00000700L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1__SHIFT 0x00000008
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2_MASK 0x00003800L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2__SHIFT 0x0000000b
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3_MASK 0x0001c000L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3__SHIFT 0x0000000e
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER_MASK 0x00400000L
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER__SHIFT 0x00000016
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN_MASK 0x00200000L
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN__SHIFT 0x00000015
+#define PB0_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING_MASK 0x00080000L
+#define PB0_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING__SHIFT 0x00000013
+#define PB0_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON_MASK 0x00800000L
+#define PB0_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON__SHIFT 0x00000017
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL_MASK 0x00000007L
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL_MASK 0x00000038L
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL__SHIFT 0x00000003
+#define PB0_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF_MASK 0x01000000L
+#define PB0_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF__SHIFT 0x00000018
+#define PB0_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS_MASK 0x00100000L
+#define PB0_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS__SHIFT 0x00000014
+#define PB0_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL_MASK 0x00060000L
+#define PB0_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL__SHIFT 0x00000011
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15_MASK 0x40000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15__SHIFT 0x0000001e
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0_MASK 0x00000001L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0__SHIFT 0x00000000
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10_MASK 0x00000400L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10__SHIFT 0x0000000a
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11_MASK 0x00000800L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11__SHIFT 0x0000000b
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12_MASK 0x00001000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12__SHIFT 0x0000000c
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13_MASK 0x00002000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13__SHIFT 0x0000000d
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14_MASK 0x00004000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14__SHIFT 0x0000000e
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15_MASK 0x00008000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15__SHIFT 0x0000000f
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1_MASK 0x00000002L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1__SHIFT 0x00000001
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2_MASK 0x00000004L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2__SHIFT 0x00000002
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3_MASK 0x00000008L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3__SHIFT 0x00000003
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4_MASK 0x00000010L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4__SHIFT 0x00000004
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5_MASK 0x00000020L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5__SHIFT 0x00000005
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6_MASK 0x00000040L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6__SHIFT 0x00000006
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7_MASK 0x00000080L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7__SHIFT 0x00000007
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8_MASK 0x00000100L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8__SHIFT 0x00000008
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9_MASK 0x00000200L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9__SHIFT 0x00000009
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1_MASK 0x00010000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1__SHIFT 0x00000010
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11_MASK 0x00200000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11__SHIFT 0x00000015
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13_MASK 0x00400000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13__SHIFT 0x00000016
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15_MASK 0x00800000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15__SHIFT 0x00000017
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3_MASK 0x00020000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3__SHIFT 0x00000011
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5_MASK 0x00040000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5__SHIFT 0x00000012
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7_MASK 0x00080000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7__SHIFT 0x00000013
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9_MASK 0x00100000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9__SHIFT 0x00000014
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3_MASK 0x01000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3__SHIFT 0x00000018
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15_MASK 0x08000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15__SHIFT 0x0000001b
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7_MASK 0x02000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7__SHIFT 0x00000019
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11_MASK 0x04000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11__SHIFT 0x0000001a
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7_MASK 0x10000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7__SHIFT 0x0000001c
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15_MASK 0x20000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15__SHIFT 0x0000001d
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000008L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000003
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x00000007L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL_MASK 0x000000f0L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00001e00L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN_MASK 0x00002000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN__SHIFT 0x0000000d
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL_MASK 0x0007c000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN_MASK 0x00080000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN__SHIFT 0x00000013
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL_MASK 0x01f00000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000014
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN_MASK 0x02000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL_MASK 0x3c000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL__SHIFT 0x0000001a
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN_MASK 0x40000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN__SHIFT 0x0000001e
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL__SHIFT 0x00000005
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN_MASK 0x00000040L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN__SHIFT 0x00000006
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00000080L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000007
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00000400L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN_MASK 0x00001000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN__SHIFT 0x0000000c
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL_MASK 0x00000800L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL__SHIFT 0x0000000b
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN_MASK 0x00004000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL_MASK 0x00002000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL__SHIFT 0x0000000d
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN_MASK 0x02000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL_MASK 0x01ff8000L
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL__SHIFT 0x0000000f
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN_MASK 0x08000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN__SHIFT 0x0000001b
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL_MASK 0x04000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL__SHIFT 0x0000001a
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN_MASK 0x20000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN__SHIFT 0x0000001d
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL_MASK 0x10000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN_MASK 0x80000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN__SHIFT 0x0000001f
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL_MASK 0x40000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL__SHIFT 0x0000001e
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL_MASK 0x0000f000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL__SHIFT 0x0000000c
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000f0000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000010
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL_MASK 0x01f00000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL__SHIFT 0x00000014
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL_MASK 0x3e000000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN_MASK 0x00000800L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN__SHIFT 0x0000000b
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL_MASK 0x00000400L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN_MASK 0x00000008L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN__SHIFT 0x00000003
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL_MASK 0x00000004L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL__SHIFT 0x00000002
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN__SHIFT 0x00000005
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN_MASK 0x00000080L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN__SHIFT 0x00000007
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL_MASK 0x00000040L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL__SHIFT 0x00000006
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN_MASK 0x00000002L
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN__SHIFT 0x00000001
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL_MASK 0x00000001L
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL_MASK 0x00003c00L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0003c000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL_MASK 0x007c0000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL__SHIFT 0x00000012
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0f800000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000017
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL_MASK 0xf0000000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000000f0L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000005
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0_MASK 0x00000001L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0__SHIFT 0x00000000
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0_MASK 0x00000002L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0__SHIFT 0x00000001
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0_MASK 0x00000004L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0__SHIFT 0x00000002
+#define PB0_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0_MASK 0x00000008L
+#define PB0_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0_MASK 0x00000002L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0__SHIFT 0x00000001
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0_MASK 0x00000001L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0_MASK 0x00000008L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0_MASK 0x00000004L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0__SHIFT 0x00000002
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0_MASK 0x00000020L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0_MASK 0x00000010L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0_MASK 0x00000080L
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0_MASK 0x00000040L
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0_MASK 0x0000fc00L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0__SHIFT 0x0000000a
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0_MASK 0x00000300L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0__SHIFT 0x00000008
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0_MASK 0x00000080L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0__SHIFT 0x00000007
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0_MASK 0x00000008L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0_MASK 0x00000070L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0__SHIFT 0x00000004
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0_MASK 0x00000007L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0__SHIFT 0x00000000
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10_MASK 0x00000001L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10__SHIFT 0x00000000
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10_MASK 0x00000002L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10__SHIFT 0x00000001
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10_MASK 0x00000004L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10__SHIFT 0x00000002
+#define PB0_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10_MASK 0x00000008L
+#define PB0_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10_MASK 0x00000002L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10__SHIFT 0x00000001
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10_MASK 0x00000001L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10__SHIFT 0x00000000
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10_MASK 0x00000008L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10_MASK 0x00000004L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10__SHIFT 0x00000002
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10_MASK 0x00000020L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10__SHIFT 0x00000005
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10_MASK 0x00000010L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10__SHIFT 0x00000004
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10_MASK 0x00000080L
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10__SHIFT 0x00000007
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10_MASK 0x00000040L
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10__SHIFT 0x00000006
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10_MASK 0x0000fc00L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10__SHIFT 0x0000000a
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10_MASK 0x00000300L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10__SHIFT 0x00000008
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10_MASK 0x00000080L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10__SHIFT 0x00000007
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10_MASK 0x00000008L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10_MASK 0x00000070L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10__SHIFT 0x00000004
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10_MASK 0x00000007L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10__SHIFT 0x00000000
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11_MASK 0x00000001L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11__SHIFT 0x00000000
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11_MASK 0x00000002L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11__SHIFT 0x00000001
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11_MASK 0x00000004L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11__SHIFT 0x00000002
+#define PB0_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11_MASK 0x00000008L
+#define PB0_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11_MASK 0x00000002L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11__SHIFT 0x00000001
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11_MASK 0x00000001L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11__SHIFT 0x00000000
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11_MASK 0x00000008L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11_MASK 0x00000004L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11__SHIFT 0x00000002
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11_MASK 0x00000020L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11__SHIFT 0x00000005
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11_MASK 0x00000010L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11__SHIFT 0x00000004
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11_MASK 0x00000080L
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11__SHIFT 0x00000007
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11_MASK 0x00000040L
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11__SHIFT 0x00000006
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11_MASK 0x0000fc00L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11__SHIFT 0x0000000a
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11_MASK 0x00000300L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11__SHIFT 0x00000008
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11_MASK 0x00000080L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11__SHIFT 0x00000007
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11_MASK 0x00000008L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11_MASK 0x00000070L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11__SHIFT 0x00000004
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11_MASK 0x00000007L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11__SHIFT 0x00000000
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12_MASK 0x00000001L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12__SHIFT 0x00000000
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12_MASK 0x00000002L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12__SHIFT 0x00000001
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12_MASK 0x00000004L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12__SHIFT 0x00000002
+#define PB0_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12_MASK 0x00000008L
+#define PB0_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12_MASK 0x00000002L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12__SHIFT 0x00000001
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12_MASK 0x00000001L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12__SHIFT 0x00000000
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12_MASK 0x00000008L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12_MASK 0x00000004L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12__SHIFT 0x00000002
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12_MASK 0x00000020L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12__SHIFT 0x00000005
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12_MASK 0x00000010L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12__SHIFT 0x00000004
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12_MASK 0x00000080L
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12__SHIFT 0x00000007
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12_MASK 0x00000040L
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12__SHIFT 0x00000006
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12_MASK 0x0000fc00L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12__SHIFT 0x0000000a
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12_MASK 0x00000300L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12__SHIFT 0x00000008
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12_MASK 0x00000080L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12__SHIFT 0x00000007
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12_MASK 0x00000008L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12_MASK 0x00000070L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12__SHIFT 0x00000004
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12_MASK 0x00000007L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12__SHIFT 0x00000000
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13_MASK 0x00000001L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13__SHIFT 0x00000000
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13_MASK 0x00000002L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13__SHIFT 0x00000001
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13_MASK 0x00000004L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13__SHIFT 0x00000002
+#define PB0_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13_MASK 0x00000008L
+#define PB0_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13_MASK 0x00000002L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13__SHIFT 0x00000001
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13_MASK 0x00000001L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13__SHIFT 0x00000000
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13_MASK 0x00000008L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13_MASK 0x00000004L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13__SHIFT 0x00000002
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13_MASK 0x00000020L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13__SHIFT 0x00000005
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13_MASK 0x00000010L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13__SHIFT 0x00000004
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13_MASK 0x00000080L
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13__SHIFT 0x00000007
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13_MASK 0x00000040L
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13__SHIFT 0x00000006
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13_MASK 0x0000fc00L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13__SHIFT 0x0000000a
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13_MASK 0x00000300L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13__SHIFT 0x00000008
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13_MASK 0x00000080L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13__SHIFT 0x00000007
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13_MASK 0x00000008L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13_MASK 0x00000070L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13__SHIFT 0x00000004
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13_MASK 0x00000007L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13__SHIFT 0x00000000
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14_MASK 0x00000001L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14__SHIFT 0x00000000
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14_MASK 0x00000002L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14__SHIFT 0x00000001
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14_MASK 0x00000004L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14__SHIFT 0x00000002
+#define PB0_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14_MASK 0x00000008L
+#define PB0_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14_MASK 0x00000002L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14__SHIFT 0x00000001
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14_MASK 0x00000001L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14__SHIFT 0x00000000
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14_MASK 0x00000008L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14_MASK 0x00000004L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14__SHIFT 0x00000002
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14_MASK 0x00000020L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14__SHIFT 0x00000005
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14_MASK 0x00000010L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14__SHIFT 0x00000004
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14_MASK 0x00000080L
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14__SHIFT 0x00000007
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14_MASK 0x00000040L
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14__SHIFT 0x00000006
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14_MASK 0x0000fc00L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14__SHIFT 0x0000000a
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14_MASK 0x00000300L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14__SHIFT 0x00000008
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14_MASK 0x00000080L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14__SHIFT 0x00000007
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14_MASK 0x00000008L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14_MASK 0x00000070L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14__SHIFT 0x00000004
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14_MASK 0x00000007L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14__SHIFT 0x00000000
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15_MASK 0x00000001L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15__SHIFT 0x00000000
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15_MASK 0x00000002L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15__SHIFT 0x00000001
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15_MASK 0x00000004L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15__SHIFT 0x00000002
+#define PB0_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15_MASK 0x00000008L
+#define PB0_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15_MASK 0x00000002L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15__SHIFT 0x00000001
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15_MASK 0x00000001L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15__SHIFT 0x00000000
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15_MASK 0x00000008L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15_MASK 0x00000004L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15__SHIFT 0x00000002
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15_MASK 0x00000020L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15__SHIFT 0x00000005
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15_MASK 0x00000010L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15__SHIFT 0x00000004
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15_MASK 0x00000080L
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15__SHIFT 0x00000007
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15_MASK 0x00000040L
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15__SHIFT 0x00000006
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15_MASK 0x0000fc00L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15__SHIFT 0x0000000a
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15_MASK 0x00000300L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15__SHIFT 0x00000008
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15_MASK 0x00000080L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15__SHIFT 0x00000007
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15_MASK 0x00000008L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15_MASK 0x00000070L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15__SHIFT 0x00000004
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15_MASK 0x00000007L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15__SHIFT 0x00000000
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1_MASK 0x00000001L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1__SHIFT 0x00000000
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1_MASK 0x00000002L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1__SHIFT 0x00000001
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1_MASK 0x00000004L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1__SHIFT 0x00000002
+#define PB0_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1_MASK 0x00000008L
+#define PB0_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1_MASK 0x00000002L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1__SHIFT 0x00000001
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1_MASK 0x00000001L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1__SHIFT 0x00000000
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1_MASK 0x00000008L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1_MASK 0x00000004L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1__SHIFT 0x00000002
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1_MASK 0x00000020L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1__SHIFT 0x00000005
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1_MASK 0x00000010L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1__SHIFT 0x00000004
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1_MASK 0x00000080L
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1__SHIFT 0x00000007
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1_MASK 0x00000040L
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1__SHIFT 0x00000006
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1_MASK 0x0000fc00L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1__SHIFT 0x0000000a
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1_MASK 0x00000300L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1__SHIFT 0x00000008
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1_MASK 0x00000080L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1__SHIFT 0x00000007
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1_MASK 0x00000008L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1_MASK 0x00000070L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1__SHIFT 0x00000004
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1_MASK 0x00000007L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1__SHIFT 0x00000000
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2_MASK 0x00000001L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2__SHIFT 0x00000000
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2_MASK 0x00000002L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2__SHIFT 0x00000001
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2_MASK 0x00000004L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2__SHIFT 0x00000002
+#define PB0_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2_MASK 0x00000008L
+#define PB0_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2_MASK 0x00000002L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2__SHIFT 0x00000001
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2_MASK 0x00000001L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2__SHIFT 0x00000000
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2_MASK 0x00000008L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2_MASK 0x00000004L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2__SHIFT 0x00000002
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2_MASK 0x00000020L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2__SHIFT 0x00000005
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2_MASK 0x00000010L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2__SHIFT 0x00000004
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2_MASK 0x00000080L
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2__SHIFT 0x00000007
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2_MASK 0x00000040L
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2__SHIFT 0x00000006
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2_MASK 0x0000fc00L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2__SHIFT 0x0000000a
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2_MASK 0x00000300L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2__SHIFT 0x00000008
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2_MASK 0x00000080L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2__SHIFT 0x00000007
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2_MASK 0x00000008L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2_MASK 0x00000070L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2__SHIFT 0x00000004
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2_MASK 0x00000007L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2__SHIFT 0x00000000
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3_MASK 0x00000001L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3__SHIFT 0x00000000
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3_MASK 0x00000002L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3__SHIFT 0x00000001
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3_MASK 0x00000004L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3__SHIFT 0x00000002
+#define PB0_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3_MASK 0x00000008L
+#define PB0_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3_MASK 0x00000002L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3__SHIFT 0x00000001
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3_MASK 0x00000001L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3__SHIFT 0x00000000
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3_MASK 0x00000008L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3_MASK 0x00000004L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3__SHIFT 0x00000002
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3_MASK 0x00000020L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3__SHIFT 0x00000005
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3_MASK 0x00000010L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3__SHIFT 0x00000004
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3_MASK 0x00000080L
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3__SHIFT 0x00000007
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3_MASK 0x00000040L
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3__SHIFT 0x00000006
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3_MASK 0x0000fc00L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3__SHIFT 0x0000000a
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3_MASK 0x00000300L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3__SHIFT 0x00000008
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3_MASK 0x00000080L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3__SHIFT 0x00000007
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3_MASK 0x00000008L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3_MASK 0x00000070L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3__SHIFT 0x00000004
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3_MASK 0x00000007L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3__SHIFT 0x00000000
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4_MASK 0x00000001L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4__SHIFT 0x00000000
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4_MASK 0x00000002L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4__SHIFT 0x00000001
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4_MASK 0x00000004L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4__SHIFT 0x00000002
+#define PB0_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4_MASK 0x00000008L
+#define PB0_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4_MASK 0x00000002L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4__SHIFT 0x00000001
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4_MASK 0x00000001L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4__SHIFT 0x00000000
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4_MASK 0x00000008L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4_MASK 0x00000004L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4__SHIFT 0x00000002
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4_MASK 0x00000020L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4__SHIFT 0x00000005
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4_MASK 0x00000010L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4__SHIFT 0x00000004
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4_MASK 0x00000080L
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4__SHIFT 0x00000007
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4_MASK 0x00000040L
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4__SHIFT 0x00000006
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4_MASK 0x0000fc00L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4__SHIFT 0x0000000a
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4_MASK 0x00000300L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4__SHIFT 0x00000008
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4_MASK 0x00000080L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4__SHIFT 0x00000007
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4_MASK 0x00000008L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4_MASK 0x00000070L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4__SHIFT 0x00000004
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4_MASK 0x00000007L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4__SHIFT 0x00000000
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5_MASK 0x00000001L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5__SHIFT 0x00000000
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5_MASK 0x00000002L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5__SHIFT 0x00000001
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5_MASK 0x00000004L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5__SHIFT 0x00000002
+#define PB0_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5_MASK 0x00000008L
+#define PB0_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5_MASK 0x00000002L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5__SHIFT 0x00000001
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5_MASK 0x00000001L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5__SHIFT 0x00000000
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5_MASK 0x00000008L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5_MASK 0x00000004L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5__SHIFT 0x00000002
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5_MASK 0x00000020L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5__SHIFT 0x00000005
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5_MASK 0x00000010L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5__SHIFT 0x00000004
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5_MASK 0x00000080L
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5__SHIFT 0x00000007
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5_MASK 0x00000040L
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5__SHIFT 0x00000006
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5_MASK 0x0000fc00L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5__SHIFT 0x0000000a
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5_MASK 0x00000300L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5__SHIFT 0x00000008
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5_MASK 0x00000080L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5__SHIFT 0x00000007
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5_MASK 0x00000008L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5_MASK 0x00000070L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5__SHIFT 0x00000004
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5_MASK 0x00000007L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5__SHIFT 0x00000000
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6_MASK 0x00000001L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6__SHIFT 0x00000000
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6_MASK 0x00000002L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6__SHIFT 0x00000001
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6_MASK 0x00000004L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6__SHIFT 0x00000002
+#define PB0_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6_MASK 0x00000008L
+#define PB0_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6_MASK 0x00000002L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6__SHIFT 0x00000001
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6_MASK 0x00000001L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6__SHIFT 0x00000000
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6_MASK 0x00000008L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6_MASK 0x00000004L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6__SHIFT 0x00000002
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6_MASK 0x00000020L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6__SHIFT 0x00000005
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6_MASK 0x00000010L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6__SHIFT 0x00000004
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6_MASK 0x00000080L
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6__SHIFT 0x00000007
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6_MASK 0x00000040L
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6__SHIFT 0x00000006
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6_MASK 0x0000fc00L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6__SHIFT 0x0000000a
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6_MASK 0x00000300L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6__SHIFT 0x00000008
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6_MASK 0x00000080L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6__SHIFT 0x00000007
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6_MASK 0x00000008L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6_MASK 0x00000070L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6__SHIFT 0x00000004
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6_MASK 0x00000007L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6__SHIFT 0x00000000
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7_MASK 0x00000001L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7__SHIFT 0x00000000
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7_MASK 0x00000002L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7__SHIFT 0x00000001
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7_MASK 0x00000004L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7__SHIFT 0x00000002
+#define PB0_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7_MASK 0x00000008L
+#define PB0_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7_MASK 0x00000002L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7__SHIFT 0x00000001
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7_MASK 0x00000001L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7__SHIFT 0x00000000
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7_MASK 0x00000008L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7_MASK 0x00000004L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7__SHIFT 0x00000002
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7_MASK 0x00000020L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7__SHIFT 0x00000005
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7_MASK 0x00000010L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7__SHIFT 0x00000004
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7_MASK 0x00000080L
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7__SHIFT 0x00000007
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7_MASK 0x00000040L
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7__SHIFT 0x00000006
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7_MASK 0x0000fc00L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7__SHIFT 0x0000000a
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7_MASK 0x00000300L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7__SHIFT 0x00000008
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7_MASK 0x00000080L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7__SHIFT 0x00000007
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7_MASK 0x00000008L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7_MASK 0x00000070L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7__SHIFT 0x00000004
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7_MASK 0x00000007L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7__SHIFT 0x00000000
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8_MASK 0x00000001L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8__SHIFT 0x00000000
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8_MASK 0x00000002L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8__SHIFT 0x00000001
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8_MASK 0x00000004L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8__SHIFT 0x00000002
+#define PB0_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8_MASK 0x00000008L
+#define PB0_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8_MASK 0x00000002L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8__SHIFT 0x00000001
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8_MASK 0x00000001L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8__SHIFT 0x00000000
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8_MASK 0x00000008L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8_MASK 0x00000004L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8__SHIFT 0x00000002
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8_MASK 0x00000020L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8__SHIFT 0x00000005
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8_MASK 0x00000010L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8__SHIFT 0x00000004
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8_MASK 0x00000080L
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8__SHIFT 0x00000007
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8_MASK 0x00000040L
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8__SHIFT 0x00000006
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8_MASK 0x0000fc00L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8__SHIFT 0x0000000a
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8_MASK 0x00000300L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8__SHIFT 0x00000008
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8_MASK 0x00000080L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8__SHIFT 0x00000007
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8_MASK 0x00000008L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8_MASK 0x00000070L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8__SHIFT 0x00000004
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8_MASK 0x00000007L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8__SHIFT 0x00000000
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9_MASK 0x00000001L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9__SHIFT 0x00000000
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9_MASK 0x00000002L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9__SHIFT 0x00000001
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9_MASK 0x00000004L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9__SHIFT 0x00000002
+#define PB0_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9_MASK 0x00000008L
+#define PB0_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9_MASK 0x00000002L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9__SHIFT 0x00000001
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9_MASK 0x00000001L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9__SHIFT 0x00000000
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9_MASK 0x00000008L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9_MASK 0x00000004L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9__SHIFT 0x00000002
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9_MASK 0x00000020L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9__SHIFT 0x00000005
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9_MASK 0x00000010L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9__SHIFT 0x00000004
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9_MASK 0x00000080L
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9__SHIFT 0x00000007
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9_MASK 0x00000040L
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9__SHIFT 0x00000006
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9_MASK 0x0000fc00L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9__SHIFT 0x0000000a
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9_MASK 0x00000300L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9__SHIFT 0x00000008
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9_MASK 0x00000080L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9__SHIFT 0x00000007
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9_MASK 0x00000008L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9_MASK 0x00000070L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9__SHIFT 0x00000004
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9_MASK 0x00000007L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9__SHIFT 0x00000000
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN_MASK 0x00000001L
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN__SHIFT 0x00000000
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE_MASK 0x0000003eL
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE__SHIFT 0x00000001
+#define PB1_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP_MASK 0x00000f00L
+#define PB1_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP__SHIFT 0x00000008
+#define PB1_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN_MASK 0x00800000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN__SHIFT 0x00000017
+#define PB1_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN_MASK 0x00400000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN__SHIFT 0x00000016
+#define PB1_DFT_JIT_INJ_REG0__DFT_NUM_STEPS_MASK 0x0000001fL
+#define PB1_DFT_JIT_INJ_REG0__DFT_NUM_STEPS__SHIFT 0x00000000
+#define PB1_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME_MASK 0xff000000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME__SHIFT 0x00000018
+#define PB1_DFT_JIT_INJ_REG1__DFT_BLOCK_EN_MASK 0x00010000L
+#define PB1_DFT_JIT_INJ_REG1__DFT_BLOCK_EN__SHIFT 0x00000010
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_EN_MASK 0x00000100L
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_EN__SHIFT 0x00000008
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE_MASK 0x000000ffL
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE__SHIFT 0x00000000
+#define PB1_DFT_JIT_INJ_REG2__DFT_LANE_EN_MASK 0x0000ffffL
+#define PB1_DFT_JIT_INJ_REG2__DFT_LANE_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG0__BACKUP_MASK 0x0000ffffL
+#define PB1_GLB_CTRL_REG0__BACKUP__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG0__CFG_IDLEDET_TH_MASK 0x00030000L
+#define PB1_GLB_CTRL_REG0__CFG_IDLEDET_TH__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL_MASK 0x00700000L
+#define PB1_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL__SHIFT 0x00000014
+#define PB1_GLB_CTRL_REG0__DBG_RXFEBYP_EN_MASK 0x00800000L
+#define PB1_GLB_CTRL_REG0__DBG_RXFEBYP_EN__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG0__DBG_RXPRBS_CLR_MASK 0x01000000L
+#define PB1_GLB_CTRL_REG0__DBG_RXPRBS_CLR__SHIFT 0x00000018
+#define PB1_GLB_CTRL_REG0__DBG_RXTOGGLE_EN_MASK 0x02000000L
+#define PB1_GLB_CTRL_REG0__DBG_RXTOGGLE_EN__SHIFT 0x00000019
+#define PB1_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN_MASK 0x04000000L
+#define PB1_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN__SHIFT 0x0000001a
+#define PB1_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE_MASK 0xc0000000L
+#define PB1_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE__SHIFT 0x0000001e
+#define PB1_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV_MASK 0x80000000L
+#define PB1_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV__SHIFT 0x0000001f
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN_MASK 0x00000001L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL_MASK 0x0000007eL
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL__SHIFT 0x00000001
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN_MASK 0x00000080L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN__SHIFT 0x00000007
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL_MASK 0x00003f00L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL__SHIFT 0x00000008
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN_MASK 0x00004000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN__SHIFT 0x0000000e
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL_MASK 0x003f8000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL__SHIFT 0x0000000f
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN_MASK 0x00400000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL_MASK 0x3f800000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG1__TST_LOSPDTST_EN_MASK 0x40000000L
+#define PB1_GLB_CTRL_REG1__TST_LOSPDTST_EN__SHIFT 0x0000001e
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN_MASK 0x00000001L
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL_MASK 0x000000feL
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL__SHIFT 0x00000001
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN_MASK 0x00000100L
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN__SHIFT 0x00000008
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL_MASK 0x0000fe00L
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL__SHIFT 0x00000009
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN_MASK 0x00010000L
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL_MASK 0x00fe0000L
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL__SHIFT 0x00000011
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN_MASK 0x01000000L
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN__SHIFT 0x00000018
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL_MASK 0xfe000000L
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL__SHIFT 0x00000019
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL_MASK 0x00000060L
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL__SHIFT 0x00000005
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL_MASK 0x00000180L
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL__SHIFT 0x00000007
+#define PB1_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL_MASK 0x00000600L
+#define PB1_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL__SHIFT 0x00000009
+#define PB1_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL_MASK 0x0001c000L
+#define PB1_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL__SHIFT 0x0000000e
+#define PB1_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN_MASK 0x00001000L
+#define PB1_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN__SHIFT 0x0000000c
+#define PB1_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN_MASK 0x00000800L
+#define PB1_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN__SHIFT 0x0000000b
+#define PB1_GLB_CTRL_REG3__DBG_DLL_CLK_SEL_MASK 0x001c0000L
+#define PB1_GLB_CTRL_REG3__DBG_DLL_CLK_SEL__SHIFT 0x00000012
+#define PB1_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE_MASK 0x80000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE__SHIFT 0x0000001f
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN_MASK 0x00400000L
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL_MASK 0x07800000L
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN_MASK 0x08000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN__SHIFT 0x0000001b
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL_MASK 0x70000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL__SHIFT 0x0000001c
+#define PB1_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL_MASK 0x00200000L
+#define PB1_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL__SHIFT 0x00000015
+#define PB1_GLB_CTRL_REG3__RXDBG_SEL_MASK 0x0000001fL
+#define PB1_GLB_CTRL_REG3__RXDBG_SEL__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_EXEC_MASK 0x03c00000L
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_EXEC__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_INST_MASK 0x0000ffffL
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_INST__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN_MASK 0x00040000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN__SHIFT 0x00000012
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL_MASK 0x00030000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL_MASK 0x04000000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000001a
+#define PB1_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE_MASK 0x10000000L
+#define PB1_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE__SHIFT 0x0000001c
+#define PB1_GLB_CTRL_REG4__PWRGOOD_OVRD_MASK 0x08000000L
+#define PB1_GLB_CTRL_REG4__PWRGOOD_OVRD__SHIFT 0x0000001b
+#define PB1_GLB_CTRL_REG5__DBG_RXAPU_MODE_MASK 0x000000ffL
+#define PB1_GLB_CTRL_REG5__DBG_RXAPU_MODE__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL_MASK 0x0000ffffL
+#define PB1_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB1_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN_MASK 0x00008000L
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN__SHIFT 0x0000000f
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN_MASK 0x00000004L
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN__SHIFT 0x00000002
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL_MASK 0x00000008L
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL__SHIFT 0x00000003
+#define PB1_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN_MASK 0x00000001L
+#define PB1_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN_MASK 0x00000002L
+#define PB1_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN__SHIFT 0x00000001
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_EN_MASK 0x00000001L
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_EN__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL_MASK 0x00000002L
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT_MASK 0x00000010L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT__SHIFT 0x00000004
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE_MASK 0x00100000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG0__RXIMP_MASK 0x000f0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__RXIMP__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXNIMP_MASK 0x00000f00L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXNIMP__SHIFT 0x00000008
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXPIMP_MASK 0x0000f000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXPIMP__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_0_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_0__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_1_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_1__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_2_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_2__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_3_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_3__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_4_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_4__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_5_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_5__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_6_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_6__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_7_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_7__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_10_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_10__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_11_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_11__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_8_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_8__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_9_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_9__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_12_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_12__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_13_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_13__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_14_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_14__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_15_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_15__SHIFT 0x0000001c
+#define PB1_HW_DEBUG__PB1_HW_00_DEBUG_MASK 0x00000001L
+#define PB1_HW_DEBUG__PB1_HW_00_DEBUG__SHIFT 0x00000000
+#define PB1_HW_DEBUG__PB1_HW_01_DEBUG_MASK 0x00000002L
+#define PB1_HW_DEBUG__PB1_HW_01_DEBUG__SHIFT 0x00000001
+#define PB1_HW_DEBUG__PB1_HW_02_DEBUG_MASK 0x00000004L
+#define PB1_HW_DEBUG__PB1_HW_02_DEBUG__SHIFT 0x00000002
+#define PB1_HW_DEBUG__PB1_HW_03_DEBUG_MASK 0x00000008L
+#define PB1_HW_DEBUG__PB1_HW_03_DEBUG__SHIFT 0x00000003
+#define PB1_HW_DEBUG__PB1_HW_04_DEBUG_MASK 0x00000010L
+#define PB1_HW_DEBUG__PB1_HW_04_DEBUG__SHIFT 0x00000004
+#define PB1_HW_DEBUG__PB1_HW_05_DEBUG_MASK 0x00000020L
+#define PB1_HW_DEBUG__PB1_HW_05_DEBUG__SHIFT 0x00000005
+#define PB1_HW_DEBUG__PB1_HW_06_DEBUG_MASK 0x00000040L
+#define PB1_HW_DEBUG__PB1_HW_06_DEBUG__SHIFT 0x00000006
+#define PB1_HW_DEBUG__PB1_HW_07_DEBUG_MASK 0x00000080L
+#define PB1_HW_DEBUG__PB1_HW_07_DEBUG__SHIFT 0x00000007
+#define PB1_HW_DEBUG__PB1_HW_08_DEBUG_MASK 0x00000100L
+#define PB1_HW_DEBUG__PB1_HW_08_DEBUG__SHIFT 0x00000008
+#define PB1_HW_DEBUG__PB1_HW_09_DEBUG_MASK 0x00000200L
+#define PB1_HW_DEBUG__PB1_HW_09_DEBUG__SHIFT 0x00000009
+#define PB1_HW_DEBUG__PB1_HW_10_DEBUG_MASK 0x00000400L
+#define PB1_HW_DEBUG__PB1_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB1_HW_DEBUG__PB1_HW_11_DEBUG_MASK 0x00000800L
+#define PB1_HW_DEBUG__PB1_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB1_HW_DEBUG__PB1_HW_12_DEBUG_MASK 0x00001000L
+#define PB1_HW_DEBUG__PB1_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB1_HW_DEBUG__PB1_HW_13_DEBUG_MASK 0x00002000L
+#define PB1_HW_DEBUG__PB1_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB1_HW_DEBUG__PB1_HW_14_DEBUG_MASK 0x00004000L
+#define PB1_HW_DEBUG__PB1_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB1_HW_DEBUG__PB1_HW_15_DEBUG_MASK 0x00008000L
+#define PB1_HW_DEBUG__PB1_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB1_HW_DEBUG__PB1_HW_16_DEBUG_MASK 0x00010000L
+#define PB1_HW_DEBUG__PB1_HW_16_DEBUG__SHIFT 0x00000010
+#define PB1_HW_DEBUG__PB1_HW_17_DEBUG_MASK 0x00020000L
+#define PB1_HW_DEBUG__PB1_HW_17_DEBUG__SHIFT 0x00000011
+#define PB1_HW_DEBUG__PB1_HW_18_DEBUG_MASK 0x00040000L
+#define PB1_HW_DEBUG__PB1_HW_18_DEBUG__SHIFT 0x00000012
+#define PB1_HW_DEBUG__PB1_HW_19_DEBUG_MASK 0x00080000L
+#define PB1_HW_DEBUG__PB1_HW_19_DEBUG__SHIFT 0x00000013
+#define PB1_HW_DEBUG__PB1_HW_20_DEBUG_MASK 0x00100000L
+#define PB1_HW_DEBUG__PB1_HW_20_DEBUG__SHIFT 0x00000014
+#define PB1_HW_DEBUG__PB1_HW_21_DEBUG_MASK 0x00200000L
+#define PB1_HW_DEBUG__PB1_HW_21_DEBUG__SHIFT 0x00000015
+#define PB1_HW_DEBUG__PB1_HW_22_DEBUG_MASK 0x00400000L
+#define PB1_HW_DEBUG__PB1_HW_22_DEBUG__SHIFT 0x00000016
+#define PB1_HW_DEBUG__PB1_HW_23_DEBUG_MASK 0x00800000L
+#define PB1_HW_DEBUG__PB1_HW_23_DEBUG__SHIFT 0x00000017
+#define PB1_HW_DEBUG__PB1_HW_24_DEBUG_MASK 0x01000000L
+#define PB1_HW_DEBUG__PB1_HW_24_DEBUG__SHIFT 0x00000018
+#define PB1_HW_DEBUG__PB1_HW_25_DEBUG_MASK 0x02000000L
+#define PB1_HW_DEBUG__PB1_HW_25_DEBUG__SHIFT 0x00000019
+#define PB1_HW_DEBUG__PB1_HW_26_DEBUG_MASK 0x04000000L
+#define PB1_HW_DEBUG__PB1_HW_26_DEBUG__SHIFT 0x0000001a
+#define PB1_HW_DEBUG__PB1_HW_27_DEBUG_MASK 0x08000000L
+#define PB1_HW_DEBUG__PB1_HW_27_DEBUG__SHIFT 0x0000001b
+#define PB1_HW_DEBUG__PB1_HW_28_DEBUG_MASK 0x10000000L
+#define PB1_HW_DEBUG__PB1_HW_28_DEBUG__SHIFT 0x0000001c
+#define PB1_HW_DEBUG__PB1_HW_29_DEBUG_MASK 0x20000000L
+#define PB1_HW_DEBUG__PB1_HW_29_DEBUG__SHIFT 0x0000001d
+#define PB1_HW_DEBUG__PB1_HW_30_DEBUG_MASK 0x40000000L
+#define PB1_HW_DEBUG__PB1_HW_30_DEBUG__SHIFT 0x0000001e
+#define PB1_HW_DEBUG__PB1_HW_31_DEBUG_MASK 0x80000000L
+#define PB1_HW_DEBUG__PB1_HW_31_DEBUG__SHIFT 0x0000001f
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_EN_MASK 0x00000080L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_EN__SHIFT 0x00000007
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0_MASK 0x00000100L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0__SHIFT 0x00000008
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10_MASK 0x00040000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10__SHIFT 0x00000012
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11_MASK 0x00080000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11__SHIFT 0x00000013
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12_MASK 0x00100000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12__SHIFT 0x00000014
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13_MASK 0x00200000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13__SHIFT 0x00000015
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14_MASK 0x00400000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14__SHIFT 0x00000016
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15_MASK 0x00800000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15__SHIFT 0x00000017
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2_MASK 0x00000400L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2__SHIFT 0x0000000a
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3_MASK 0x00000800L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4_MASK 0x00001000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4__SHIFT 0x0000000c
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5_MASK 0x00002000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5__SHIFT 0x0000000d
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6_MASK 0x00004000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6__SHIFT 0x0000000e
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7_MASK 0x00008000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8_MASK 0x00010000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8__SHIFT 0x00000010
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9_MASK 0x00020000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9__SHIFT 0x00000011
+#define PB1_PIF_CNTL2__RXDETECT_SAMPL_TIME_MASK 0x00000006L
+#define PB1_PIF_CNTL2__RXDETECT_SAMPL_TIME__SHIFT 0x00000001
+#define PB1_PIF_CNTL2__RXPHYSTATUS_DELAY_MASK 0x07000000L
+#define PB1_PIF_CNTL2__RXPHYSTATUS_DELAY__SHIFT 0x00000018
+#define PB1_PIF_CNTL__DA_FIFO_RESET_0_MASK 0x00000002L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_0__SHIFT 0x00000001
+#define PB1_PIF_CNTL__DA_FIFO_RESET_1_MASK 0x00000020L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_1__SHIFT 0x00000005
+#define PB1_PIF_CNTL__DA_FIFO_RESET_2_MASK 0x00000200L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_2__SHIFT 0x00000009
+#define PB1_PIF_CNTL__DA_FIFO_RESET_3_MASK 0x00002000L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_3__SHIFT 0x0000000d
+#define PB1_PIF_CNTL__DIVINIT_MODE_MASK 0x00000100L
+#define PB1_PIF_CNTL__DIVINIT_MODE__SHIFT 0x00000008
+#define PB1_PIF_CNTL__EI_CYCLE_OFF_TIME_MASK 0x00700000L
+#define PB1_PIF_CNTL__EI_CYCLE_OFF_TIME__SHIFT 0x00000014
+#define PB1_PIF_CNTL__EI_DET_CYCLE_MODE_MASK 0x00000010L
+#define PB1_PIF_CNTL__EI_DET_CYCLE_MODE__SHIFT 0x00000004
+#define PB1_PIF_CNTL__EXIT_L0S_INIT_DIS_MASK 0x00800000L
+#define PB1_PIF_CNTL__EXIT_L0S_INIT_DIS__SHIFT 0x00000017
+#define PB1_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP_MASK 0x10000000L
+#define PB1_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP__SHIFT 0x0000001c
+#define PB1_PIF_CNTL__IGNORE_TxDataValid_EP_DIS_MASK 0x20000000L
+#define PB1_PIF_CNTL__IGNORE_TxDataValid_EP_DIS__SHIFT 0x0000001d
+#define PB1_PIF_CNTL__LS2_EXIT_TIME_MASK 0x000e0000L
+#define PB1_PIF_CNTL__LS2_EXIT_TIME__SHIFT 0x00000011
+#define PB1_PIF_CNTL__PHYCMD_CR_EN_MODE_MASK 0x00000008L
+#define PB1_PIF_CNTL__PHYCMD_CR_EN_MODE__SHIFT 0x00000003
+#define PB1_PIF_CNTL__PHY_CR_EN_MODE_MASK 0x00000004L
+#define PB1_PIF_CNTL__PHY_CR_EN_MODE__SHIFT 0x00000002
+#define PB1_PIF_CNTL__PLL_BINDING_ENABLE_MASK 0x00000400L
+#define PB1_PIF_CNTL__PLL_BINDING_ENABLE__SHIFT 0x0000000a
+#define PB1_PIF_CNTL__RXDETECT_FIFO_RESET_MODE_MASK 0x00000040L
+#define PB1_PIF_CNTL__RXDETECT_FIFO_RESET_MODE__SHIFT 0x00000006
+#define PB1_PIF_CNTL__RXDETECT_TX_PWR_MODE_MASK 0x00000080L
+#define PB1_PIF_CNTL__RXDETECT_TX_PWR_MODE__SHIFT 0x00000007
+#define PB1_PIF_CNTL__RXEN_GATER_MASK 0x0f000000L
+#define PB1_PIF_CNTL__RXEN_GATER__SHIFT 0x00000018
+#define PB1_PIF_CNTL__SC_CALIB_DONE_CNTL_MASK 0x00000800L
+#define PB1_PIF_CNTL__SC_CALIB_DONE_CNTL__SHIFT 0x0000000b
+#define PB1_PIF_CNTL__SERIAL_CFG_ENABLE_MASK 0x00000001L
+#define PB1_PIF_CNTL__SERIAL_CFG_ENABLE__SHIFT 0x00000000
+#define PB1_PIF_CNTL__TXGND_TIME_MASK 0x00010000L
+#define PB1_PIF_CNTL__TXGND_TIME__SHIFT 0x00000010
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_00_DEBUG_MASK 0x00000001L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_00_DEBUG__SHIFT 0x00000000
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_01_DEBUG_MASK 0x00000002L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_01_DEBUG__SHIFT 0x00000001
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_02_DEBUG_MASK 0x00000004L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_02_DEBUG__SHIFT 0x00000002
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_03_DEBUG_MASK 0x00000008L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_03_DEBUG__SHIFT 0x00000003
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_04_DEBUG_MASK 0x00000010L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_04_DEBUG__SHIFT 0x00000004
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_05_DEBUG_MASK 0x00000020L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_05_DEBUG__SHIFT 0x00000005
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_06_DEBUG_MASK 0x00000040L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_06_DEBUG__SHIFT 0x00000006
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_07_DEBUG_MASK 0x00000080L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_07_DEBUG__SHIFT 0x00000007
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_08_DEBUG_MASK 0x00000100L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_08_DEBUG__SHIFT 0x00000008
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_09_DEBUG_MASK 0x00000200L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_09_DEBUG__SHIFT 0x00000009
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_10_DEBUG_MASK 0x00000400L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_11_DEBUG_MASK 0x00000800L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_12_DEBUG_MASK 0x00001000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_13_DEBUG_MASK 0x00002000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_14_DEBUG_MASK 0x00004000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_15_DEBUG_MASK 0x00008000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB1_PIF_PAIRING__MULTI_PIF_MASK 0x02000000L
+#define PB1_PIF_PAIRING__MULTI_PIF__SHIFT 0x00000019
+#define PB1_PIF_PAIRING__X16_LANE_15_0_MASK 0x00100000L
+#define PB1_PIF_PAIRING__X16_LANE_15_0__SHIFT 0x00000014
+#define PB1_PIF_PAIRING__X2_LANE_1_0_MASK 0x00000001L
+#define PB1_PIF_PAIRING__X2_LANE_1_0__SHIFT 0x00000000
+#define PB1_PIF_PAIRING__X2_LANE_11_10_MASK 0x00000020L
+#define PB1_PIF_PAIRING__X2_LANE_11_10__SHIFT 0x00000005
+#define PB1_PIF_PAIRING__X2_LANE_13_12_MASK 0x00000040L
+#define PB1_PIF_PAIRING__X2_LANE_13_12__SHIFT 0x00000006
+#define PB1_PIF_PAIRING__X2_LANE_15_14_MASK 0x00000080L
+#define PB1_PIF_PAIRING__X2_LANE_15_14__SHIFT 0x00000007
+#define PB1_PIF_PAIRING__X2_LANE_3_2_MASK 0x00000002L
+#define PB1_PIF_PAIRING__X2_LANE_3_2__SHIFT 0x00000001
+#define PB1_PIF_PAIRING__X2_LANE_5_4_MASK 0x00000004L
+#define PB1_PIF_PAIRING__X2_LANE_5_4__SHIFT 0x00000002
+#define PB1_PIF_PAIRING__X2_LANE_7_6_MASK 0x00000008L
+#define PB1_PIF_PAIRING__X2_LANE_7_6__SHIFT 0x00000003
+#define PB1_PIF_PAIRING__X2_LANE_9_8_MASK 0x00000010L
+#define PB1_PIF_PAIRING__X2_LANE_9_8__SHIFT 0x00000004
+#define PB1_PIF_PAIRING__X4_LANE_11_8_MASK 0x00000400L
+#define PB1_PIF_PAIRING__X4_LANE_11_8__SHIFT 0x0000000a
+#define PB1_PIF_PAIRING__X4_LANE_15_12_MASK 0x00000800L
+#define PB1_PIF_PAIRING__X4_LANE_15_12__SHIFT 0x0000000b
+#define PB1_PIF_PAIRING__X4_LANE_3_0_MASK 0x00000100L
+#define PB1_PIF_PAIRING__X4_LANE_3_0__SHIFT 0x00000008
+#define PB1_PIF_PAIRING__X4_LANE_7_4_MASK 0x00000200L
+#define PB1_PIF_PAIRING__X4_LANE_7_4__SHIFT 0x00000009
+#define PB1_PIF_PAIRING__X8_LANE_15_8_MASK 0x00020000L
+#define PB1_PIF_PAIRING__X8_LANE_15_8__SHIFT 0x00000011
+#define PB1_PIF_PAIRING__X8_LANE_7_0_MASK 0x00010000L
+#define PB1_PIF_PAIRING__X8_LANE_7_0__SHIFT 0x00000010
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000b
+#define PB1_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3__SHIFT 0x00000000
+#define PB1_PIF_SC_CTL__SC_CALIBRATION_MASK 0x00000001L
+#define PB1_PIF_SC_CTL__SC_CALIBRATION__SHIFT 0x00000000
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0_MASK 0x00000020L
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0__SHIFT 0x00000005
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S_MASK 0x00000010L
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S__SHIFT 0x00000004
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0_MASK 0x00000008L
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0__SHIFT 0x00000003
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0S_MASK 0x00000004L
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0S__SHIFT 0x00000002
+#define PB1_PIF_SC_CTL__SC_LANE_0_RESUME_MASK 0x00010000L
+#define PB1_PIF_SC_CTL__SC_LANE_0_RESUME__SHIFT 0x00000010
+#define PB1_PIF_SC_CTL__SC_LANE_10_RESUME_MASK 0x04000000L
+#define PB1_PIF_SC_CTL__SC_LANE_10_RESUME__SHIFT 0x0000001a
+#define PB1_PIF_SC_CTL__SC_LANE_11_RESUME_MASK 0x08000000L
+#define PB1_PIF_SC_CTL__SC_LANE_11_RESUME__SHIFT 0x0000001b
+#define PB1_PIF_SC_CTL__SC_LANE_12_RESUME_MASK 0x10000000L
+#define PB1_PIF_SC_CTL__SC_LANE_12_RESUME__SHIFT 0x0000001c
+#define PB1_PIF_SC_CTL__SC_LANE_13_RESUME_MASK 0x20000000L
+#define PB1_PIF_SC_CTL__SC_LANE_13_RESUME__SHIFT 0x0000001d
+#define PB1_PIF_SC_CTL__SC_LANE_14_RESUME_MASK 0x40000000L
+#define PB1_PIF_SC_CTL__SC_LANE_14_RESUME__SHIFT 0x0000001e
+#define PB1_PIF_SC_CTL__SC_LANE_15_RESUME_MASK 0x80000000L
+#define PB1_PIF_SC_CTL__SC_LANE_15_RESUME__SHIFT 0x0000001f
+#define PB1_PIF_SC_CTL__SC_LANE_1_RESUME_MASK 0x00020000L
+#define PB1_PIF_SC_CTL__SC_LANE_1_RESUME__SHIFT 0x00000011
+#define PB1_PIF_SC_CTL__SC_LANE_2_RESUME_MASK 0x00040000L
+#define PB1_PIF_SC_CTL__SC_LANE_2_RESUME__SHIFT 0x00000012
+#define PB1_PIF_SC_CTL__SC_LANE_3_RESUME_MASK 0x00080000L
+#define PB1_PIF_SC_CTL__SC_LANE_3_RESUME__SHIFT 0x00000013
+#define PB1_PIF_SC_CTL__SC_LANE_4_RESUME_MASK 0x00100000L
+#define PB1_PIF_SC_CTL__SC_LANE_4_RESUME__SHIFT 0x00000014
+#define PB1_PIF_SC_CTL__SC_LANE_5_RESUME_MASK 0x00200000L
+#define PB1_PIF_SC_CTL__SC_LANE_5_RESUME__SHIFT 0x00000015
+#define PB1_PIF_SC_CTL__SC_LANE_6_RESUME_MASK 0x00400000L
+#define PB1_PIF_SC_CTL__SC_LANE_6_RESUME__SHIFT 0x00000016
+#define PB1_PIF_SC_CTL__SC_LANE_7_RESUME_MASK 0x00800000L
+#define PB1_PIF_SC_CTL__SC_LANE_7_RESUME__SHIFT 0x00000017
+#define PB1_PIF_SC_CTL__SC_LANE_8_RESUME_MASK 0x01000000L
+#define PB1_PIF_SC_CTL__SC_LANE_8_RESUME__SHIFT 0x00000018
+#define PB1_PIF_SC_CTL__SC_LANE_9_RESUME_MASK 0x02000000L
+#define PB1_PIF_SC_CTL__SC_LANE_9_RESUME__SHIFT 0x00000019
+#define PB1_PIF_SC_CTL__SC_PHASE_1_MASK 0x00000100L
+#define PB1_PIF_SC_CTL__SC_PHASE_1__SHIFT 0x00000008
+#define PB1_PIF_SC_CTL__SC_PHASE_2_MASK 0x00000200L
+#define PB1_PIF_SC_CTL__SC_PHASE_2__SHIFT 0x00000009
+#define PB1_PIF_SC_CTL__SC_PHASE_3_MASK 0x00000400L
+#define PB1_PIF_SC_CTL__SC_PHASE_3__SHIFT 0x0000000a
+#define PB1_PIF_SC_CTL__SC_PHASE_4_MASK 0x00000800L
+#define PB1_PIF_SC_CTL__SC_PHASE_4__SHIFT 0x0000000b
+#define PB1_PIF_SC_CTL__SC_PHASE_5_MASK 0x00001000L
+#define PB1_PIF_SC_CTL__SC_PHASE_5__SHIFT 0x0000000c
+#define PB1_PIF_SC_CTL__SC_PHASE_6_MASK 0x00002000L
+#define PB1_PIF_SC_CTL__SC_PHASE_6__SHIFT 0x0000000d
+#define PB1_PIF_SC_CTL__SC_PHASE_7_MASK 0x00004000L
+#define PB1_PIF_SC_CTL__SC_PHASE_7__SHIFT 0x0000000e
+#define PB1_PIF_SC_CTL__SC_PHASE_8_MASK 0x00008000L
+#define PB1_PIF_SC_CTL__SC_PHASE_8__SHIFT 0x0000000f
+#define PB1_PIF_SC_CTL__SC_RXDETECT_MASK 0x00000002L
+#define PB1_PIF_SC_CTL__SC_RXDETECT__SHIFT 0x00000001
+#define PB1_PIF_SC_CTL__SC_SPEED_CHANGE_MASK 0x00000040L
+#define PB1_PIF_SC_CTL__SC_SPEED_CHANGE__SHIFT 0x00000006
+#define PB1_PIF_SCRATCH__PIF_SCRATCH_MASK 0xffffffffL
+#define PB1_PIF_SCRATCH__PIF_SCRATCH__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_0__SEQ_PHASE_0_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_PHASE_0__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_10__SEQ_PHASE_10_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_PHASE_10__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_11__SEQ_PHASE_11_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_PHASE_11__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_12__SEQ_PHASE_12_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_PHASE_12__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_13__SEQ_PHASE_13_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_PHASE_13__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_14__SEQ_PHASE_14_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_PHASE_14__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_15__SEQ_PHASE_15_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_PHASE_15__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_1__SEQ_PHASE_1_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_PHASE_1__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_2__SEQ_PHASE_2_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_PHASE_2__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_3__SEQ_PHASE_3_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_PHASE_3__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_4__SEQ_PHASE_4_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_PHASE_4__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_5__SEQ_PHASE_5_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_PHASE_5__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_6__SEQ_PHASE_6_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_PHASE_6__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_7__SEQ_PHASE_7_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_PHASE_7__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_8__SEQ_PHASE_8_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_PHASE_8__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_9__SEQ_PHASE_9_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_PHASE_9__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9__SHIFT 0x00000006
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_0_MASK 0x00000001L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_0__SHIFT 0x00000000
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_10_MASK 0x00000400L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_10__SHIFT 0x0000000a
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_11_MASK 0x00000800L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_11__SHIFT 0x0000000b
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_12_MASK 0x00001000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_12__SHIFT 0x0000000c
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_13_MASK 0x00002000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_13__SHIFT 0x0000000d
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_14_MASK 0x00004000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_14__SHIFT 0x0000000e
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_15_MASK 0x00008000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_15__SHIFT 0x0000000f
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_1_MASK 0x00000002L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_1__SHIFT 0x00000001
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_2_MASK 0x00000004L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_2__SHIFT 0x00000002
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_3_MASK 0x00000008L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_3__SHIFT 0x00000003
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_4_MASK 0x00000010L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_4__SHIFT 0x00000004
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_5_MASK 0x00000020L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_5__SHIFT 0x00000005
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_6_MASK 0x00000040L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_6__SHIFT 0x00000006
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_7_MASK 0x00000080L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_7__SHIFT 0x00000007
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_8_MASK 0x00000100L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_8__SHIFT 0x00000008
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_9_MASK 0x00000200L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_9__SHIFT 0x00000009
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0_MASK 0x00000003L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0_MASK 0x00000010L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0_MASK 0x00000007L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0_MASK 0x00000080L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000070L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0_MASK 0x00000200L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0__SHIFT 0x00000009
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0_MASK 0x00000100L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0__SHIFT 0x00000008
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0_MASK 0x00040000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0__SHIFT 0x00000012
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0_MASK 0x0003fc00L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0__SHIFT 0x0000000a
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0_MASK 0x10000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0__SHIFT 0x0000001c
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0_MASK 0x0ff80000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0__SHIFT 0x00000013
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0_MASK 0x80000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0__SHIFT 0x0000001f
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0_MASK 0x60000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0__SHIFT 0x0000001d
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0_MASK 0x00000007L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0_MASK 0x00040000L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0__SHIFT 0x00000012
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0_MASK 0x0003c000L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0__SHIFT 0x0000000e
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000020L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000010L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00000080L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000040L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0_MASK 0x00000200L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0__SHIFT 0x00000009
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0_MASK 0x00000100L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0__SHIFT 0x00000008
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0_MASK 0x00000003L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0_MASK 0x000007f0L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0__SHIFT 0x00000004
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB1_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0_MASK 0x00000800L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0__SHIFT 0x0000000b
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0_MASK 0x00000100L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000008
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0_MASK 0x000000ffL
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0_MASK 0x00001000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0__SHIFT 0x0000000c
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000e00L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000009
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0_MASK 0x00004000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0__SHIFT 0x0000000e
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0_MASK 0x00002000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0_MASK 0x10000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0__SHIFT 0x0000001c
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0_MASK 0x0fff8000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0__SHIFT 0x0000000f
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0_MASK 0x80000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0__SHIFT 0x0000001f
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0_MASK 0x40000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0__SHIFT 0x0000001e
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0_MASK 0x00400000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000016
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0_MASK 0x00380000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000013
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0_MASK 0x00000020L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0_MASK 0x0000001fL
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0_MASK 0x00000100L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0__SHIFT 0x00000008
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0_MASK 0x000000c0L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000400L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x0000000a
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000200L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000009
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00001000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x0000000c
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000800L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x0000000b
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0_MASK 0x00004000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0__SHIFT 0x0000000e
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0_MASK 0x00002000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000200L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000009
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000400L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000a
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000800L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000b
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00100000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000014
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00200000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000015
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00001000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x0000000c
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00002000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000d
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00004000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000e
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00400000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000016
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00800000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000017
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2_MASK 0x00000100L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000008
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000002L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000001
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000004L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x00000002
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000008L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x00000003
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00010000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000010
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00020000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000011
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00000010L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x00000004
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00000020L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x00000005
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00000040L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x00000006
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00040000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000012
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00080000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000013
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2_MASK 0x00000080L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000007
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC_MASK 0x00000001L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1_MASK 0x000003ffL
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2_MASK 0x000ffc00L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2__SHIFT 0x0000000a
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3_MASK 0x3ff00000L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1_MASK 0x01000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2_MASK 0x02000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2__SHIFT 0x00000019
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3_MASK 0x04000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1_MASK 0x03000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2_MASK 0x0c000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3_MASK 0x30000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1_MASK 0x00000001L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2_MASK 0x00000002L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2__SHIFT 0x00000001
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3_MASK 0x00000004L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3__SHIFT 0x00000002
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2_MASK 0x0f000000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3_MASK 0xf0000000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1_MASK 0x00000007L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2_MASK 0x00000038L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2__SHIFT 0x00000003
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3_MASK 0x000001c0L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3__SHIFT 0x00000006
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2_MASK 0x0f000000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3_MASK 0xf0000000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1_MASK 0x00000e00L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1__SHIFT 0x00000009
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2_MASK 0x00007000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3_MASK 0x00038000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3__SHIFT 0x0000000f
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1_MASK 0x0000001fL
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2_MASK 0x000003e0L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2__SHIFT 0x00000005
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3_MASK 0x00007c00L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3__SHIFT 0x0000000a
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1_MASK 0x00008000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1__SHIFT 0x0000000f
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2_MASK 0x00010000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3_MASK 0x00020000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3__SHIFT 0x00000011
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1_MASK 0x00040000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1__SHIFT 0x00000012
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2_MASK 0x00080000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2__SHIFT 0x00000013
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3_MASK 0x00100000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0_MASK 0x40000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x01000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2_MASK 0x04000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1_MASK 0x001c0000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1__SHIFT 0x00000012
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2_MASK 0x00e00000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2__SHIFT 0x00000015
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3_MASK 0x07000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x00001000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2_MASK 0x00002000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2__SHIFT 0x0000000d
+#define PB1_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2_MASK 0x00020000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000011
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN_MASK 0x80000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN__SHIFT 0x0000001f
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL_MASK 0x40000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL__SHIFT 0x0000001e
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN_MASK 0x00000002L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN__SHIFT 0x00000001
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL_MASK 0x00000001L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL__SHIFT 0x00000000
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN_MASK 0x00000008L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN__SHIFT 0x00000003
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL_MASK 0x00000004L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL__SHIFT 0x00000002
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN_MASK 0x20000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN__SHIFT 0x0000001d
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL_MASK 0x10000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000100L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000008
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x000000c0L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000006
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN_MASK 0x00000400L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN__SHIFT 0x0000000a
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL_MASK 0x00000200L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL__SHIFT 0x00000009
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00001000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000c
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000800L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x0000000b
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN_MASK 0x00004000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN__SHIFT 0x0000000e
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL_MASK 0x00002000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL__SHIFT 0x0000000d
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN_MASK 0x00010000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN__SHIFT 0x00000010
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL_MASK 0x00008000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL__SHIFT 0x0000000f
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN_MASK 0x00040000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN__SHIFT 0x00000012
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL_MASK 0x00020000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL__SHIFT 0x00000011
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN_MASK 0x00100000L
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN__SHIFT 0x00000014
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL_MASK 0x00080000L
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL__SHIFT 0x00000013
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN_MASK 0x00400000L
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN__SHIFT 0x00000016
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL_MASK 0x00200000L
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL__SHIFT 0x00000015
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN_MASK 0x01000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN__SHIFT 0x00000018
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL_MASK 0x00800000L
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL__SHIFT 0x00000017
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN_MASK 0x00000002L
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN__SHIFT 0x00000001
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL_MASK 0x00000001L
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL__SHIFT 0x00000000
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3_MASK 0x00010000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3__SHIFT 0x00000010
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15_MASK 0x00080000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15__SHIFT 0x00000013
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7_MASK 0x00020000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7__SHIFT 0x00000011
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11_MASK 0x00040000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11__SHIFT 0x00000012
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3_MASK 0x00100000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3__SHIFT 0x00000014
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15_MASK 0x00800000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15__SHIFT 0x00000017
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7_MASK 0x00200000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7__SHIFT 0x00000015
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11_MASK 0x00400000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11__SHIFT 0x00000016
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_RX_LANE0_CTRL_REG0__RX_BACKUP_0_MASK 0x000000ffL
+#define PB1_RX_LANE0_CTRL_REG0__RX_BACKUP_0__SHIFT 0x00000000
+#define PB1_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0_MASK 0x00002000L
+#define PB1_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0__SHIFT 0x0000000d
+#define PB1_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0_MASK 0x00000c00L
+#define PB1_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0__SHIFT 0x0000000a
+#define PB1_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0_MASK 0x00001000L
+#define PB1_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0__SHIFT 0x0000000c
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0_MASK 0x00000008L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0__SHIFT 0x00000003
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0_MASK 0x00000080L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0__SHIFT 0x00000007
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0_MASK 0x00000100L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0__SHIFT 0x00000008
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0_MASK 0x00000200L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0__SHIFT 0x00000009
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0_MASK 0x00000070L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0__SHIFT 0x00000004
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0_MASK 0x00000007L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0__SHIFT 0x00000000
+#define PB1_RX_LANE10_CTRL_REG0__RX_BACKUP_10_MASK 0x000000ffL
+#define PB1_RX_LANE10_CTRL_REG0__RX_BACKUP_10__SHIFT 0x00000000
+#define PB1_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10_MASK 0x00002000L
+#define PB1_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10__SHIFT 0x0000000d
+#define PB1_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10_MASK 0x00000c00L
+#define PB1_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10__SHIFT 0x0000000a
+#define PB1_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10_MASK 0x00001000L
+#define PB1_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10__SHIFT 0x0000000c
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10_MASK 0x00000008L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10__SHIFT 0x00000003
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10_MASK 0x00000080L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10__SHIFT 0x00000007
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10_MASK 0x00000100L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10__SHIFT 0x00000008
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10_MASK 0x00000200L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10__SHIFT 0x00000009
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10_MASK 0x00000070L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10__SHIFT 0x00000004
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10_MASK 0x00000007L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10__SHIFT 0x00000000
+#define PB1_RX_LANE11_CTRL_REG0__RX_BACKUP_11_MASK 0x000000ffL
+#define PB1_RX_LANE11_CTRL_REG0__RX_BACKUP_11__SHIFT 0x00000000
+#define PB1_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11_MASK 0x00002000L
+#define PB1_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11__SHIFT 0x0000000d
+#define PB1_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11_MASK 0x00000c00L
+#define PB1_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11__SHIFT 0x0000000a
+#define PB1_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11_MASK 0x00001000L
+#define PB1_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11__SHIFT 0x0000000c
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11_MASK 0x00000008L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11__SHIFT 0x00000003
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11_MASK 0x00000080L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11__SHIFT 0x00000007
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11_MASK 0x00000100L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11__SHIFT 0x00000008
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11_MASK 0x00000200L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11__SHIFT 0x00000009
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11_MASK 0x00000070L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11__SHIFT 0x00000004
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11_MASK 0x00000007L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11__SHIFT 0x00000000
+#define PB1_RX_LANE12_CTRL_REG0__RX_BACKUP_12_MASK 0x000000ffL
+#define PB1_RX_LANE12_CTRL_REG0__RX_BACKUP_12__SHIFT 0x00000000
+#define PB1_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12_MASK 0x00002000L
+#define PB1_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12__SHIFT 0x0000000d
+#define PB1_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12_MASK 0x00000c00L
+#define PB1_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12__SHIFT 0x0000000a
+#define PB1_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12_MASK 0x00001000L
+#define PB1_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12__SHIFT 0x0000000c
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12_MASK 0x00000008L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12__SHIFT 0x00000003
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12_MASK 0x00000080L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12__SHIFT 0x00000007
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12_MASK 0x00000100L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12__SHIFT 0x00000008
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12_MASK 0x00000200L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12__SHIFT 0x00000009
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12_MASK 0x00000070L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12__SHIFT 0x00000004
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12_MASK 0x00000007L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12__SHIFT 0x00000000
+#define PB1_RX_LANE13_CTRL_REG0__RX_BACKUP_13_MASK 0x000000ffL
+#define PB1_RX_LANE13_CTRL_REG0__RX_BACKUP_13__SHIFT 0x00000000
+#define PB1_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13_MASK 0x00002000L
+#define PB1_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13__SHIFT 0x0000000d
+#define PB1_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13_MASK 0x00000c00L
+#define PB1_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13__SHIFT 0x0000000a
+#define PB1_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13_MASK 0x00001000L
+#define PB1_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13__SHIFT 0x0000000c
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13_MASK 0x00000008L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13__SHIFT 0x00000003
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13_MASK 0x00000080L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13__SHIFT 0x00000007
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13_MASK 0x00000100L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13__SHIFT 0x00000008
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13_MASK 0x00000200L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13__SHIFT 0x00000009
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13_MASK 0x00000070L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13__SHIFT 0x00000004
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13_MASK 0x00000007L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13__SHIFT 0x00000000
+#define PB1_RX_LANE14_CTRL_REG0__RX_BACKUP_14_MASK 0x000000ffL
+#define PB1_RX_LANE14_CTRL_REG0__RX_BACKUP_14__SHIFT 0x00000000
+#define PB1_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14_MASK 0x00002000L
+#define PB1_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14__SHIFT 0x0000000d
+#define PB1_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14_MASK 0x00000c00L
+#define PB1_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14__SHIFT 0x0000000a
+#define PB1_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14_MASK 0x00001000L
+#define PB1_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14__SHIFT 0x0000000c
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14_MASK 0x00000008L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14__SHIFT 0x00000003
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14_MASK 0x00000080L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14__SHIFT 0x00000007
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14_MASK 0x00000100L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14__SHIFT 0x00000008
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14_MASK 0x00000200L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14__SHIFT 0x00000009
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14_MASK 0x00000070L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14__SHIFT 0x00000004
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14_MASK 0x00000007L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14__SHIFT 0x00000000
+#define PB1_RX_LANE15_CTRL_REG0__RX_BACKUP_15_MASK 0x000000ffL
+#define PB1_RX_LANE15_CTRL_REG0__RX_BACKUP_15__SHIFT 0x00000000
+#define PB1_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15_MASK 0x00002000L
+#define PB1_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15__SHIFT 0x0000000d
+#define PB1_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15_MASK 0x00000c00L
+#define PB1_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15__SHIFT 0x0000000a
+#define PB1_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15_MASK 0x00001000L
+#define PB1_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15__SHIFT 0x0000000c
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15_MASK 0x00000008L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15__SHIFT 0x00000003
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15_MASK 0x00000080L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15__SHIFT 0x00000007
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15_MASK 0x00000100L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15__SHIFT 0x00000008
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15_MASK 0x00000200L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15__SHIFT 0x00000009
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15_MASK 0x00000070L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15__SHIFT 0x00000004
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15_MASK 0x00000007L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15__SHIFT 0x00000000
+#define PB1_RX_LANE1_CTRL_REG0__RX_BACKUP_1_MASK 0x000000ffL
+#define PB1_RX_LANE1_CTRL_REG0__RX_BACKUP_1__SHIFT 0x00000000
+#define PB1_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1_MASK 0x00002000L
+#define PB1_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1__SHIFT 0x0000000d
+#define PB1_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1_MASK 0x00000c00L
+#define PB1_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1__SHIFT 0x0000000a
+#define PB1_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1_MASK 0x00001000L
+#define PB1_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1__SHIFT 0x0000000c
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1_MASK 0x00000008L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1__SHIFT 0x00000003
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1_MASK 0x00000080L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1__SHIFT 0x00000007
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1_MASK 0x00000100L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1__SHIFT 0x00000008
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1_MASK 0x00000200L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1__SHIFT 0x00000009
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1_MASK 0x00000070L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1__SHIFT 0x00000004
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1_MASK 0x00000007L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1__SHIFT 0x00000000
+#define PB1_RX_LANE2_CTRL_REG0__RX_BACKUP_2_MASK 0x000000ffL
+#define PB1_RX_LANE2_CTRL_REG0__RX_BACKUP_2__SHIFT 0x00000000
+#define PB1_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2_MASK 0x00002000L
+#define PB1_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2__SHIFT 0x0000000d
+#define PB1_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2_MASK 0x00000c00L
+#define PB1_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2__SHIFT 0x0000000a
+#define PB1_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2_MASK 0x00001000L
+#define PB1_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2__SHIFT 0x0000000c
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2_MASK 0x00000008L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2__SHIFT 0x00000003
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2_MASK 0x00000080L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2__SHIFT 0x00000007
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2_MASK 0x00000100L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2__SHIFT 0x00000008
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2_MASK 0x00000200L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2__SHIFT 0x00000009
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2_MASK 0x00000070L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2__SHIFT 0x00000004
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2_MASK 0x00000007L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2__SHIFT 0x00000000
+#define PB1_RX_LANE3_CTRL_REG0__RX_BACKUP_3_MASK 0x000000ffL
+#define PB1_RX_LANE3_CTRL_REG0__RX_BACKUP_3__SHIFT 0x00000000
+#define PB1_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3_MASK 0x00002000L
+#define PB1_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3__SHIFT 0x0000000d
+#define PB1_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3_MASK 0x00000c00L
+#define PB1_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3__SHIFT 0x0000000a
+#define PB1_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3_MASK 0x00001000L
+#define PB1_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3__SHIFT 0x0000000c
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3_MASK 0x00000008L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3__SHIFT 0x00000003
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3_MASK 0x00000080L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3__SHIFT 0x00000007
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3_MASK 0x00000100L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3__SHIFT 0x00000008
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3_MASK 0x00000200L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3__SHIFT 0x00000009
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3_MASK 0x00000070L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3__SHIFT 0x00000004
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3_MASK 0x00000007L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3__SHIFT 0x00000000
+#define PB1_RX_LANE4_CTRL_REG0__RX_BACKUP_4_MASK 0x000000ffL
+#define PB1_RX_LANE4_CTRL_REG0__RX_BACKUP_4__SHIFT 0x00000000
+#define PB1_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4_MASK 0x00002000L
+#define PB1_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4__SHIFT 0x0000000d
+#define PB1_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4_MASK 0x00000c00L
+#define PB1_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4__SHIFT 0x0000000a
+#define PB1_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4_MASK 0x00001000L
+#define PB1_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4__SHIFT 0x0000000c
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4_MASK 0x00000008L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4__SHIFT 0x00000003
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4_MASK 0x00000080L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4__SHIFT 0x00000007
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4_MASK 0x00000100L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4__SHIFT 0x00000008
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4_MASK 0x00000200L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4__SHIFT 0x00000009
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4_MASK 0x00000070L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4__SHIFT 0x00000004
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4_MASK 0x00000007L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4__SHIFT 0x00000000
+#define PB1_RX_LANE5_CTRL_REG0__RX_BACKUP_5_MASK 0x000000ffL
+#define PB1_RX_LANE5_CTRL_REG0__RX_BACKUP_5__SHIFT 0x00000000
+#define PB1_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5_MASK 0x00002000L
+#define PB1_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5__SHIFT 0x0000000d
+#define PB1_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5_MASK 0x00000c00L
+#define PB1_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5__SHIFT 0x0000000a
+#define PB1_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5_MASK 0x00001000L
+#define PB1_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5__SHIFT 0x0000000c
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5_MASK 0x00000008L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5__SHIFT 0x00000003
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5_MASK 0x00000080L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5__SHIFT 0x00000007
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5_MASK 0x00000100L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5__SHIFT 0x00000008
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5_MASK 0x00000200L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5__SHIFT 0x00000009
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5_MASK 0x00000070L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5__SHIFT 0x00000004
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5_MASK 0x00000007L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5__SHIFT 0x00000000
+#define PB1_RX_LANE6_CTRL_REG0__RX_BACKUP_6_MASK 0x000000ffL
+#define PB1_RX_LANE6_CTRL_REG0__RX_BACKUP_6__SHIFT 0x00000000
+#define PB1_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6_MASK 0x00002000L
+#define PB1_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6__SHIFT 0x0000000d
+#define PB1_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6_MASK 0x00000c00L
+#define PB1_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6__SHIFT 0x0000000a
+#define PB1_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6_MASK 0x00001000L
+#define PB1_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6__SHIFT 0x0000000c
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6_MASK 0x00000008L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6__SHIFT 0x00000003
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6_MASK 0x00000080L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6__SHIFT 0x00000007
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6_MASK 0x00000100L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6__SHIFT 0x00000008
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6_MASK 0x00000200L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6__SHIFT 0x00000009
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6_MASK 0x00000070L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6__SHIFT 0x00000004
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6_MASK 0x00000007L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6__SHIFT 0x00000000
+#define PB1_RX_LANE7_CTRL_REG0__RX_BACKUP_7_MASK 0x000000ffL
+#define PB1_RX_LANE7_CTRL_REG0__RX_BACKUP_7__SHIFT 0x00000000
+#define PB1_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7_MASK 0x00002000L
+#define PB1_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7__SHIFT 0x0000000d
+#define PB1_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7_MASK 0x00000c00L
+#define PB1_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7__SHIFT 0x0000000a
+#define PB1_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7_MASK 0x00001000L
+#define PB1_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7__SHIFT 0x0000000c
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7_MASK 0x00000008L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7__SHIFT 0x00000003
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7_MASK 0x00000080L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7__SHIFT 0x00000007
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7_MASK 0x00000100L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7__SHIFT 0x00000008
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7_MASK 0x00000200L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7__SHIFT 0x00000009
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7_MASK 0x00000070L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7__SHIFT 0x00000004
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7_MASK 0x00000007L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7__SHIFT 0x00000000
+#define PB1_RX_LANE8_CTRL_REG0__RX_BACKUP_8_MASK 0x000000ffL
+#define PB1_RX_LANE8_CTRL_REG0__RX_BACKUP_8__SHIFT 0x00000000
+#define PB1_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8_MASK 0x00002000L
+#define PB1_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8__SHIFT 0x0000000d
+#define PB1_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8_MASK 0x00000c00L
+#define PB1_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8__SHIFT 0x0000000a
+#define PB1_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8_MASK 0x00001000L
+#define PB1_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8__SHIFT 0x0000000c
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8_MASK 0x00000008L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8__SHIFT 0x00000003
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8_MASK 0x00000080L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8__SHIFT 0x00000007
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8_MASK 0x00000100L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8__SHIFT 0x00000008
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8_MASK 0x00000200L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8__SHIFT 0x00000009
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8_MASK 0x00000070L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8__SHIFT 0x00000004
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8_MASK 0x00000007L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8__SHIFT 0x00000000
+#define PB1_RX_LANE9_CTRL_REG0__RX_BACKUP_9_MASK 0x000000ffL
+#define PB1_RX_LANE9_CTRL_REG0__RX_BACKUP_9__SHIFT 0x00000000
+#define PB1_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9_MASK 0x00002000L
+#define PB1_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9__SHIFT 0x0000000d
+#define PB1_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9_MASK 0x00000c00L
+#define PB1_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9__SHIFT 0x0000000a
+#define PB1_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9_MASK 0x00001000L
+#define PB1_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9__SHIFT 0x0000000c
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9_MASK 0x00000008L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9__SHIFT 0x00000003
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9_MASK 0x00000080L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9__SHIFT 0x00000007
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9_MASK 0x00000100L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9__SHIFT 0x00000008
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9_MASK 0x00000200L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9__SHIFT 0x00000009
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9_MASK 0x00000070L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9__SHIFT 0x00000004
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9_MASK 0x00000007L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9__SHIFT 0x00000000
+#define PB1_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL_MASK 0x00008000L
+#define PB1_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99__SHIFT 0x00000003
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1_MASK 0x00000700L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1__SHIFT 0x00000008
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2_MASK 0x00003800L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2__SHIFT 0x0000000b
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3_MASK 0x0001c000L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3__SHIFT 0x0000000e
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER_MASK 0x00400000L
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER__SHIFT 0x00000016
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN_MASK 0x00200000L
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN__SHIFT 0x00000015
+#define PB1_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING_MASK 0x00080000L
+#define PB1_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING__SHIFT 0x00000013
+#define PB1_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON_MASK 0x00800000L
+#define PB1_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON__SHIFT 0x00000017
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL_MASK 0x00000007L
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL_MASK 0x00000038L
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL__SHIFT 0x00000003
+#define PB1_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF_MASK 0x01000000L
+#define PB1_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF__SHIFT 0x00000018
+#define PB1_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS_MASK 0x00100000L
+#define PB1_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS__SHIFT 0x00000014
+#define PB1_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL_MASK 0x00060000L
+#define PB1_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL__SHIFT 0x00000011
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15_MASK 0x40000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15__SHIFT 0x0000001e
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0_MASK 0x00000001L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0__SHIFT 0x00000000
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10_MASK 0x00000400L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10__SHIFT 0x0000000a
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11_MASK 0x00000800L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11__SHIFT 0x0000000b
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12_MASK 0x00001000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12__SHIFT 0x0000000c
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13_MASK 0x00002000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13__SHIFT 0x0000000d
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14_MASK 0x00004000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14__SHIFT 0x0000000e
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15_MASK 0x00008000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15__SHIFT 0x0000000f
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1_MASK 0x00000002L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1__SHIFT 0x00000001
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2_MASK 0x00000004L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2__SHIFT 0x00000002
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3_MASK 0x00000008L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3__SHIFT 0x00000003
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4_MASK 0x00000010L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4__SHIFT 0x00000004
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5_MASK 0x00000020L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5__SHIFT 0x00000005
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6_MASK 0x00000040L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6__SHIFT 0x00000006
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7_MASK 0x00000080L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7__SHIFT 0x00000007
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8_MASK 0x00000100L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8__SHIFT 0x00000008
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9_MASK 0x00000200L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9__SHIFT 0x00000009
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1_MASK 0x00010000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1__SHIFT 0x00000010
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11_MASK 0x00200000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11__SHIFT 0x00000015
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13_MASK 0x00400000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13__SHIFT 0x00000016
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15_MASK 0x00800000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15__SHIFT 0x00000017
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3_MASK 0x00020000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3__SHIFT 0x00000011
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5_MASK 0x00040000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5__SHIFT 0x00000012
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7_MASK 0x00080000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7__SHIFT 0x00000013
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9_MASK 0x00100000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9__SHIFT 0x00000014
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3_MASK 0x01000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3__SHIFT 0x00000018
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15_MASK 0x08000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15__SHIFT 0x0000001b
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7_MASK 0x02000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7__SHIFT 0x00000019
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11_MASK 0x04000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11__SHIFT 0x0000001a
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7_MASK 0x10000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7__SHIFT 0x0000001c
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15_MASK 0x20000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15__SHIFT 0x0000001d
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000008L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000003
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x00000007L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL_MASK 0x000000f0L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00001e00L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN_MASK 0x00002000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN__SHIFT 0x0000000d
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL_MASK 0x0007c000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN_MASK 0x00080000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN__SHIFT 0x00000013
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL_MASK 0x01f00000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000014
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN_MASK 0x02000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL_MASK 0x3c000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL__SHIFT 0x0000001a
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN_MASK 0x40000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN__SHIFT 0x0000001e
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL__SHIFT 0x00000005
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN_MASK 0x00000040L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN__SHIFT 0x00000006
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00000080L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000007
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00000400L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN_MASK 0x00001000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN__SHIFT 0x0000000c
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL_MASK 0x00000800L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL__SHIFT 0x0000000b
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN_MASK 0x00004000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL_MASK 0x00002000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL__SHIFT 0x0000000d
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN_MASK 0x02000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL_MASK 0x01ff8000L
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL__SHIFT 0x0000000f
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN_MASK 0x08000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN__SHIFT 0x0000001b
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL_MASK 0x04000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL__SHIFT 0x0000001a
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN_MASK 0x20000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN__SHIFT 0x0000001d
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL_MASK 0x10000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN_MASK 0x80000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN__SHIFT 0x0000001f
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL_MASK 0x40000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL__SHIFT 0x0000001e
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL_MASK 0x0000f000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL__SHIFT 0x0000000c
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000f0000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000010
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL_MASK 0x01f00000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL__SHIFT 0x00000014
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL_MASK 0x3e000000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN_MASK 0x00000800L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN__SHIFT 0x0000000b
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL_MASK 0x00000400L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN_MASK 0x00000008L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN__SHIFT 0x00000003
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL_MASK 0x00000004L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL__SHIFT 0x00000002
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN__SHIFT 0x00000005
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN_MASK 0x00000080L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN__SHIFT 0x00000007
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL_MASK 0x00000040L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL__SHIFT 0x00000006
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN_MASK 0x00000002L
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN__SHIFT 0x00000001
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL_MASK 0x00000001L
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL_MASK 0x00003c00L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0003c000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL_MASK 0x007c0000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL__SHIFT 0x00000012
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0f800000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000017
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL_MASK 0xf0000000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000000f0L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000005
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0_MASK 0x00000001L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0__SHIFT 0x00000000
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0_MASK 0x00000002L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0__SHIFT 0x00000001
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0_MASK 0x00000004L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0__SHIFT 0x00000002
+#define PB1_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0_MASK 0x00000008L
+#define PB1_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0_MASK 0x00000002L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0__SHIFT 0x00000001
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0_MASK 0x00000001L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0_MASK 0x00000008L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0_MASK 0x00000004L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0__SHIFT 0x00000002
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0_MASK 0x00000020L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0_MASK 0x00000010L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0_MASK 0x00000080L
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0_MASK 0x00000040L
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0_MASK 0x0000fc00L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0__SHIFT 0x0000000a
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0_MASK 0x00000300L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0__SHIFT 0x00000008
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0_MASK 0x00000080L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0__SHIFT 0x00000007
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0_MASK 0x00000008L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0_MASK 0x00000070L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0__SHIFT 0x00000004
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0_MASK 0x00000007L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0__SHIFT 0x00000000
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10_MASK 0x00000001L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10__SHIFT 0x00000000
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10_MASK 0x00000002L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10__SHIFT 0x00000001
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10_MASK 0x00000004L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10__SHIFT 0x00000002
+#define PB1_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10_MASK 0x00000008L
+#define PB1_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10_MASK 0x00000002L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10__SHIFT 0x00000001
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10_MASK 0x00000001L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10__SHIFT 0x00000000
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10_MASK 0x00000008L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10_MASK 0x00000004L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10__SHIFT 0x00000002
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10_MASK 0x00000020L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10__SHIFT 0x00000005
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10_MASK 0x00000010L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10__SHIFT 0x00000004
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10_MASK 0x00000080L
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10__SHIFT 0x00000007
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10_MASK 0x00000040L
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10__SHIFT 0x00000006
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10_MASK 0x0000fc00L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10__SHIFT 0x0000000a
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10_MASK 0x00000300L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10__SHIFT 0x00000008
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10_MASK 0x00000080L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10__SHIFT 0x00000007
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10_MASK 0x00000008L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10_MASK 0x00000070L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10__SHIFT 0x00000004
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10_MASK 0x00000007L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10__SHIFT 0x00000000
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11_MASK 0x00000001L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11__SHIFT 0x00000000
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11_MASK 0x00000002L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11__SHIFT 0x00000001
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11_MASK 0x00000004L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11__SHIFT 0x00000002
+#define PB1_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11_MASK 0x00000008L
+#define PB1_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11_MASK 0x00000002L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11__SHIFT 0x00000001
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11_MASK 0x00000001L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11__SHIFT 0x00000000
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11_MASK 0x00000008L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11_MASK 0x00000004L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11__SHIFT 0x00000002
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11_MASK 0x00000020L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11__SHIFT 0x00000005
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11_MASK 0x00000010L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11__SHIFT 0x00000004
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11_MASK 0x00000080L
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11__SHIFT 0x00000007
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11_MASK 0x00000040L
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11__SHIFT 0x00000006
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11_MASK 0x0000fc00L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11__SHIFT 0x0000000a
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11_MASK 0x00000300L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11__SHIFT 0x00000008
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11_MASK 0x00000080L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11__SHIFT 0x00000007
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11_MASK 0x00000008L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11_MASK 0x00000070L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11__SHIFT 0x00000004
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11_MASK 0x00000007L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11__SHIFT 0x00000000
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12_MASK 0x00000001L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12__SHIFT 0x00000000
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12_MASK 0x00000002L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12__SHIFT 0x00000001
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12_MASK 0x00000004L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12__SHIFT 0x00000002
+#define PB1_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12_MASK 0x00000008L
+#define PB1_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12_MASK 0x00000002L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12__SHIFT 0x00000001
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12_MASK 0x00000001L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12__SHIFT 0x00000000
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12_MASK 0x00000008L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12_MASK 0x00000004L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12__SHIFT 0x00000002
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12_MASK 0x00000020L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12__SHIFT 0x00000005
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12_MASK 0x00000010L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12__SHIFT 0x00000004
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12_MASK 0x00000080L
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12__SHIFT 0x00000007
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12_MASK 0x00000040L
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12__SHIFT 0x00000006
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12_MASK 0x0000fc00L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12__SHIFT 0x0000000a
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12_MASK 0x00000300L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12__SHIFT 0x00000008
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12_MASK 0x00000080L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12__SHIFT 0x00000007
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12_MASK 0x00000008L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12_MASK 0x00000070L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12__SHIFT 0x00000004
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12_MASK 0x00000007L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12__SHIFT 0x00000000
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13_MASK 0x00000001L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13__SHIFT 0x00000000
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13_MASK 0x00000002L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13__SHIFT 0x00000001
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13_MASK 0x00000004L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13__SHIFT 0x00000002
+#define PB1_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13_MASK 0x00000008L
+#define PB1_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13_MASK 0x00000002L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13__SHIFT 0x00000001
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13_MASK 0x00000001L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13__SHIFT 0x00000000
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13_MASK 0x00000008L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13_MASK 0x00000004L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13__SHIFT 0x00000002
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13_MASK 0x00000020L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13__SHIFT 0x00000005
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13_MASK 0x00000010L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13__SHIFT 0x00000004
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13_MASK 0x00000080L
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13__SHIFT 0x00000007
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13_MASK 0x00000040L
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13__SHIFT 0x00000006
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13_MASK 0x0000fc00L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13__SHIFT 0x0000000a
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13_MASK 0x00000300L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13__SHIFT 0x00000008
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13_MASK 0x00000080L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13__SHIFT 0x00000007
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13_MASK 0x00000008L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13_MASK 0x00000070L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13__SHIFT 0x00000004
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13_MASK 0x00000007L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13__SHIFT 0x00000000
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14_MASK 0x00000001L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14__SHIFT 0x00000000
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14_MASK 0x00000002L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14__SHIFT 0x00000001
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14_MASK 0x00000004L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14__SHIFT 0x00000002
+#define PB1_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14_MASK 0x00000008L
+#define PB1_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14_MASK 0x00000002L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14__SHIFT 0x00000001
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14_MASK 0x00000001L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14__SHIFT 0x00000000
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14_MASK 0x00000008L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14_MASK 0x00000004L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14__SHIFT 0x00000002
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14_MASK 0x00000020L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14__SHIFT 0x00000005
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14_MASK 0x00000010L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14__SHIFT 0x00000004
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14_MASK 0x00000080L
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14__SHIFT 0x00000007
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14_MASK 0x00000040L
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14__SHIFT 0x00000006
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14_MASK 0x0000fc00L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14__SHIFT 0x0000000a
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14_MASK 0x00000300L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14__SHIFT 0x00000008
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14_MASK 0x00000080L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14__SHIFT 0x00000007
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14_MASK 0x00000008L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14_MASK 0x00000070L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14__SHIFT 0x00000004
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14_MASK 0x00000007L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14__SHIFT 0x00000000
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15_MASK 0x00000001L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15__SHIFT 0x00000000
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15_MASK 0x00000002L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15__SHIFT 0x00000001
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15_MASK 0x00000004L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15__SHIFT 0x00000002
+#define PB1_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15_MASK 0x00000008L
+#define PB1_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15_MASK 0x00000002L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15__SHIFT 0x00000001
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15_MASK 0x00000001L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15__SHIFT 0x00000000
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15_MASK 0x00000008L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15_MASK 0x00000004L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15__SHIFT 0x00000002
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15_MASK 0x00000020L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15__SHIFT 0x00000005
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15_MASK 0x00000010L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15__SHIFT 0x00000004
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15_MASK 0x00000080L
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15__SHIFT 0x00000007
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15_MASK 0x00000040L
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15__SHIFT 0x00000006
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15_MASK 0x0000fc00L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15__SHIFT 0x0000000a
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15_MASK 0x00000300L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15__SHIFT 0x00000008
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15_MASK 0x00000080L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15__SHIFT 0x00000007
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15_MASK 0x00000008L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15_MASK 0x00000070L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15__SHIFT 0x00000004
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15_MASK 0x00000007L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15__SHIFT 0x00000000
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1_MASK 0x00000001L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1__SHIFT 0x00000000
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1_MASK 0x00000002L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1__SHIFT 0x00000001
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1_MASK 0x00000004L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1__SHIFT 0x00000002
+#define PB1_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1_MASK 0x00000008L
+#define PB1_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1_MASK 0x00000002L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1__SHIFT 0x00000001
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1_MASK 0x00000001L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1__SHIFT 0x00000000
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1_MASK 0x00000008L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1_MASK 0x00000004L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1__SHIFT 0x00000002
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1_MASK 0x00000020L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1__SHIFT 0x00000005
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1_MASK 0x00000010L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1__SHIFT 0x00000004
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1_MASK 0x00000080L
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1__SHIFT 0x00000007
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1_MASK 0x00000040L
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1__SHIFT 0x00000006
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1_MASK 0x0000fc00L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1__SHIFT 0x0000000a
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1_MASK 0x00000300L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1__SHIFT 0x00000008
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1_MASK 0x00000080L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1__SHIFT 0x00000007
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1_MASK 0x00000008L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1_MASK 0x00000070L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1__SHIFT 0x00000004
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1_MASK 0x00000007L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1__SHIFT 0x00000000
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2_MASK 0x00000001L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2__SHIFT 0x00000000
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2_MASK 0x00000002L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2__SHIFT 0x00000001
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2_MASK 0x00000004L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2__SHIFT 0x00000002
+#define PB1_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2_MASK 0x00000008L
+#define PB1_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2_MASK 0x00000002L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2__SHIFT 0x00000001
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2_MASK 0x00000001L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2__SHIFT 0x00000000
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2_MASK 0x00000008L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2_MASK 0x00000004L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2__SHIFT 0x00000002
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2_MASK 0x00000020L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2__SHIFT 0x00000005
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2_MASK 0x00000010L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2__SHIFT 0x00000004
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2_MASK 0x00000080L
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2__SHIFT 0x00000007
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2_MASK 0x00000040L
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2__SHIFT 0x00000006
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2_MASK 0x0000fc00L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2__SHIFT 0x0000000a
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2_MASK 0x00000300L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2__SHIFT 0x00000008
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2_MASK 0x00000080L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2__SHIFT 0x00000007
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2_MASK 0x00000008L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2_MASK 0x00000070L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2__SHIFT 0x00000004
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2_MASK 0x00000007L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2__SHIFT 0x00000000
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3_MASK 0x00000001L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3__SHIFT 0x00000000
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3_MASK 0x00000002L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3__SHIFT 0x00000001
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3_MASK 0x00000004L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3__SHIFT 0x00000002
+#define PB1_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3_MASK 0x00000008L
+#define PB1_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3_MASK 0x00000002L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3__SHIFT 0x00000001
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3_MASK 0x00000001L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3__SHIFT 0x00000000
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3_MASK 0x00000008L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3_MASK 0x00000004L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3__SHIFT 0x00000002
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3_MASK 0x00000020L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3__SHIFT 0x00000005
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3_MASK 0x00000010L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3__SHIFT 0x00000004
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3_MASK 0x00000080L
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3__SHIFT 0x00000007
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3_MASK 0x00000040L
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3__SHIFT 0x00000006
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3_MASK 0x0000fc00L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3__SHIFT 0x0000000a
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3_MASK 0x00000300L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3__SHIFT 0x00000008
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3_MASK 0x00000080L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3__SHIFT 0x00000007
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3_MASK 0x00000008L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3_MASK 0x00000070L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3__SHIFT 0x00000004
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3_MASK 0x00000007L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3__SHIFT 0x00000000
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4_MASK 0x00000001L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4__SHIFT 0x00000000
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4_MASK 0x00000002L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4__SHIFT 0x00000001
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4_MASK 0x00000004L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4__SHIFT 0x00000002
+#define PB1_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4_MASK 0x00000008L
+#define PB1_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4_MASK 0x00000002L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4__SHIFT 0x00000001
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4_MASK 0x00000001L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4__SHIFT 0x00000000
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4_MASK 0x00000008L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4_MASK 0x00000004L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4__SHIFT 0x00000002
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4_MASK 0x00000020L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4__SHIFT 0x00000005
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4_MASK 0x00000010L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4__SHIFT 0x00000004
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4_MASK 0x00000080L
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4__SHIFT 0x00000007
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4_MASK 0x00000040L
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4__SHIFT 0x00000006
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4_MASK 0x0000fc00L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4__SHIFT 0x0000000a
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4_MASK 0x00000300L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4__SHIFT 0x00000008
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4_MASK 0x00000080L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4__SHIFT 0x00000007
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4_MASK 0x00000008L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4_MASK 0x00000070L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4__SHIFT 0x00000004
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4_MASK 0x00000007L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4__SHIFT 0x00000000
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5_MASK 0x00000001L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5__SHIFT 0x00000000
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5_MASK 0x00000002L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5__SHIFT 0x00000001
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5_MASK 0x00000004L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5__SHIFT 0x00000002
+#define PB1_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5_MASK 0x00000008L
+#define PB1_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5_MASK 0x00000002L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5__SHIFT 0x00000001
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5_MASK 0x00000001L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5__SHIFT 0x00000000
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5_MASK 0x00000008L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5_MASK 0x00000004L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5__SHIFT 0x00000002
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5_MASK 0x00000020L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5__SHIFT 0x00000005
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5_MASK 0x00000010L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5__SHIFT 0x00000004
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5_MASK 0x00000080L
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5__SHIFT 0x00000007
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5_MASK 0x00000040L
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5__SHIFT 0x00000006
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5_MASK 0x0000fc00L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5__SHIFT 0x0000000a
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5_MASK 0x00000300L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5__SHIFT 0x00000008
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5_MASK 0x00000080L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5__SHIFT 0x00000007
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5_MASK 0x00000008L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5_MASK 0x00000070L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5__SHIFT 0x00000004
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5_MASK 0x00000007L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5__SHIFT 0x00000000
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6_MASK 0x00000001L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6__SHIFT 0x00000000
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6_MASK 0x00000002L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6__SHIFT 0x00000001
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6_MASK 0x00000004L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6__SHIFT 0x00000002
+#define PB1_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6_MASK 0x00000008L
+#define PB1_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6_MASK 0x00000002L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6__SHIFT 0x00000001
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6_MASK 0x00000001L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6__SHIFT 0x00000000
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6_MASK 0x00000008L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6_MASK 0x00000004L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6__SHIFT 0x00000002
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6_MASK 0x00000020L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6__SHIFT 0x00000005
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6_MASK 0x00000010L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6__SHIFT 0x00000004
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6_MASK 0x00000080L
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6__SHIFT 0x00000007
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6_MASK 0x00000040L
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6__SHIFT 0x00000006
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6_MASK 0x0000fc00L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6__SHIFT 0x0000000a
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6_MASK 0x00000300L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6__SHIFT 0x00000008
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6_MASK 0x00000080L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6__SHIFT 0x00000007
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6_MASK 0x00000008L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6_MASK 0x00000070L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6__SHIFT 0x00000004
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6_MASK 0x00000007L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6__SHIFT 0x00000000
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7_MASK 0x00000001L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7__SHIFT 0x00000000
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7_MASK 0x00000002L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7__SHIFT 0x00000001
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7_MASK 0x00000004L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7__SHIFT 0x00000002
+#define PB1_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7_MASK 0x00000008L
+#define PB1_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7_MASK 0x00000002L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7__SHIFT 0x00000001
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7_MASK 0x00000001L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7__SHIFT 0x00000000
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7_MASK 0x00000008L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7_MASK 0x00000004L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7__SHIFT 0x00000002
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7_MASK 0x00000020L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7__SHIFT 0x00000005
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7_MASK 0x00000010L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7__SHIFT 0x00000004
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7_MASK 0x00000080L
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7__SHIFT 0x00000007
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7_MASK 0x00000040L
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7__SHIFT 0x00000006
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7_MASK 0x0000fc00L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7__SHIFT 0x0000000a
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7_MASK 0x00000300L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7__SHIFT 0x00000008
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7_MASK 0x00000080L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7__SHIFT 0x00000007
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7_MASK 0x00000008L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7_MASK 0x00000070L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7__SHIFT 0x00000004
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7_MASK 0x00000007L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7__SHIFT 0x00000000
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8_MASK 0x00000001L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8__SHIFT 0x00000000
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8_MASK 0x00000002L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8__SHIFT 0x00000001
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8_MASK 0x00000004L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8__SHIFT 0x00000002
+#define PB1_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8_MASK 0x00000008L
+#define PB1_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8_MASK 0x00000002L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8__SHIFT 0x00000001
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8_MASK 0x00000001L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8__SHIFT 0x00000000
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8_MASK 0x00000008L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8_MASK 0x00000004L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8__SHIFT 0x00000002
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8_MASK 0x00000020L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8__SHIFT 0x00000005
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8_MASK 0x00000010L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8__SHIFT 0x00000004
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8_MASK 0x00000080L
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8__SHIFT 0x00000007
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8_MASK 0x00000040L
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8__SHIFT 0x00000006
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8_MASK 0x0000fc00L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8__SHIFT 0x0000000a
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8_MASK 0x00000300L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8__SHIFT 0x00000008
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8_MASK 0x00000080L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8__SHIFT 0x00000007
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8_MASK 0x00000008L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8_MASK 0x00000070L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8__SHIFT 0x00000004
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8_MASK 0x00000007L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8__SHIFT 0x00000000
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9_MASK 0x00000001L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9__SHIFT 0x00000000
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9_MASK 0x00000002L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9__SHIFT 0x00000001
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9_MASK 0x00000004L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9__SHIFT 0x00000002
+#define PB1_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9_MASK 0x00000008L
+#define PB1_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9_MASK 0x00000002L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9__SHIFT 0x00000001
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9_MASK 0x00000001L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9__SHIFT 0x00000000
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9_MASK 0x00000008L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9_MASK 0x00000004L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9__SHIFT 0x00000002
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9_MASK 0x00000020L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9__SHIFT 0x00000005
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9_MASK 0x00000010L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9__SHIFT 0x00000004
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9_MASK 0x00000080L
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9__SHIFT 0x00000007
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9_MASK 0x00000040L
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9__SHIFT 0x00000006
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9_MASK 0x0000fc00L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9__SHIFT 0x0000000a
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9_MASK 0x00000300L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9__SHIFT 0x00000008
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9_MASK 0x00000080L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9__SHIFT 0x00000007
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9_MASK 0x00000008L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9_MASK 0x00000070L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9__SHIFT 0x00000004
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9_MASK 0x00000007L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9__SHIFT 0x00000000
+#define PCIE_BUS_CNTL__IMMEDIATE_PMI_DIS_MASK 0x00000080L
+#define PCIE_BUS_CNTL__IMMEDIATE_PMI_DIS__SHIFT 0x00000007
+#define PCIE_BUS_CNTL__PMI_INT_DIS_MASK 0x00000040L
+#define PCIE_BUS_CNTL__PMI_INT_DIS__SHIFT 0x00000006
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN2_HIDDEN_REG_MASK 0x00000001L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN2_HIDDEN_REG__SHIFT 0x00000000
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN3_HIDDEN_REG_MASK 0x00000004L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN3_HIDDEN_REG__SHIFT 0x00000002
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_HIDDEN_REG_MASK 0x00000002L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_HIDDEN_REG__SHIFT 0x00000001
+#define PCIE_CI_CNTL__CI_MST_CMPL_DUMMY_DATA_MASK 0x00000010L
+#define PCIE_CI_CNTL__CI_MST_CMPL_DUMMY_DATA__SHIFT 0x00000004
+#define PCIE_CI_CNTL__CI_MST_IGNORE_PAGE_ALIGNED_REQUEST_MASK 0x00002000L
+#define PCIE_CI_CNTL__CI_MST_IGNORE_PAGE_ALIGNED_REQUEST__SHIFT 0x0000000d
+#define PCIE_CI_CNTL__CI_RC_ORDERING_DIS_MASK 0x00000200L
+#define PCIE_CI_CNTL__CI_RC_ORDERING_DIS__SHIFT 0x00000009
+#define PCIE_CI_CNTL__CI_SLAVE_GEN_USR_DIS_MASK 0x00000008L
+#define PCIE_CI_CNTL__CI_SLAVE_GEN_USR_DIS__SHIFT 0x00000003
+#define PCIE_CI_CNTL__CI_SLAVE_SPLIT_MODE_MASK 0x00000004L
+#define PCIE_CI_CNTL__CI_SLAVE_SPLIT_MODE__SHIFT 0x00000002
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_DIS_MASK 0x00000400L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_DIS__SHIFT 0x0000000a
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_MODE_MASK 0x00000800L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_MODE__SHIFT 0x0000000b
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_SOR_MASK 0x00001000L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_SOR__SHIFT 0x0000000c
+#define PCIE_CI_CNTL__CI_SLV_ORDERING_DIS_MASK 0x00000100L
+#define PCIE_CI_CNTL__CI_SLV_ORDERING_DIS__SHIFT 0x00000008
+#define PCIE_CI_CNTL__CI_SLV_RC_RD_REQ_SIZE_MASK 0x000000c0L
+#define PCIE_CI_CNTL__CI_SLV_RC_RD_REQ_SIZE__SHIFT 0x00000006
+#define PCIE_CNTL2__MST_MEM_LS_EN_MASK 0x00040000L
+#define PCIE_CNTL2__MST_MEM_LS_EN__SHIFT 0x00000012
+#define PCIE_CNTL2__MST_MEM_SD_EN_MASK 0x00400000L
+#define PCIE_CNTL2__MST_MEM_SD_EN__SHIFT 0x00000016
+#define PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK 0x00080000L
+#define PCIE_CNTL2__REPLAY_MEM_LS_EN__SHIFT 0x00000013
+#define PCIE_CNTL2__REPLAY_MEM_SD_EN_MASK 0x00800000L
+#define PCIE_CNTL2__REPLAY_MEM_SD_EN__SHIFT 0x00000017
+#define PCIE_CNTL2__RX_NP_MEM_WRITE_ENCODING_MASK 0x1f000000L
+#define PCIE_CNTL2__RX_NP_MEM_WRITE_ENCODING__SHIFT 0x00000018
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_LS_EN_MASK 0x00020000L
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_LS_EN__SHIFT 0x00000011
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_SD_EN_MASK 0x00200000L
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_SD_EN__SHIFT 0x00000015
+#define PCIE_CNTL2__SLV_MEM_LS_EN_MASK 0x00010000L
+#define PCIE_CNTL2__SLV_MEM_LS_EN__SHIFT 0x00000010
+#define PCIE_CNTL2__SLV_MEM_SD_EN_MASK 0x00100000L
+#define PCIE_CNTL2__SLV_MEM_SD_EN__SHIFT 0x00000014
+#define PCIE_CNTL2__TX_ARB_MST_LIMIT_MASK 0x000007c0L
+#define PCIE_CNTL2__TX_ARB_MST_LIMIT__SHIFT 0x00000006
+#define PCIE_CNTL2__TX_ARB_ROUND_ROBIN_EN_MASK 0x00000001L
+#define PCIE_CNTL2__TX_ARB_ROUND_ROBIN_EN__SHIFT 0x00000000
+#define PCIE_CNTL2__TX_ARB_SLV_LIMIT_MASK 0x0000003eL
+#define PCIE_CNTL2__TX_ARB_SLV_LIMIT__SHIFT 0x00000001
+#define PCIE_CNTL__HWINIT_WR_LOCK_MASK 0x00000001L
+#define PCIE_CNTL__HWINIT_WR_LOCK__SHIFT 0x00000000
+#define PCIE_CNTL__LC_HOT_PLUG_DELAY_SEL_MASK 0x0000000eL
+#define PCIE_CNTL__LC_HOT_PLUG_DELAY_SEL__SHIFT 0x00000001
+#define PCIE_CNTL__PCIE_HT_NP_MEM_WRITE_MASK 0x00000200L
+#define PCIE_CNTL__PCIE_HT_NP_MEM_WRITE__SHIFT 0x00000009
+#define PCIE_CNTL__PCIE_MALFORM_ATOMIC_OPS_MASK 0x00000100L
+#define PCIE_CNTL__PCIE_MALFORM_ATOMIC_OPS__SHIFT 0x00000008
+#define PCIE_CNTL__RX_ATS_TRAN_CPL_SPLIT_DIS_MASK 0x00800000L
+#define PCIE_CNTL__RX_ATS_TRAN_CPL_SPLIT_DIS__SHIFT 0x00000017
+#define PCIE_CNTL__RX_CPL_POSTED_REQ_ORD_EN_MASK 0x80000000L
+#define PCIE_CNTL__RX_CPL_POSTED_REQ_ORD_EN__SHIFT 0x0000001f
+#define PCIE_CNTL__RX_RCB_ATS_UC_DIS_MASK 0x00008000L
+#define PCIE_CNTL__RX_RCB_ATS_UC_DIS__SHIFT 0x0000000f
+#define PCIE_CNTL__RX_RCB_CHANNEL_ORDERING_MASK 0x00100000L
+#define PCIE_CNTL__RX_RCB_CHANNEL_ORDERING__SHIFT 0x00000014
+#define PCIE_CNTL__RX_RCB_CPL_TIMEOUT_TEST_MODE_MASK 0x00080000L
+#define PCIE_CNTL__RX_RCB_CPL_TIMEOUT_TEST_MODE__SHIFT 0x00000013
+#define PCIE_CNTL__RX_RCB_INVALID_SIZE_DIS_MASK 0x00020000L
+#define PCIE_CNTL__RX_RCB_INVALID_SIZE_DIS__SHIFT 0x00000011
+#define PCIE_CNTL__RX_RCB_REORDER_EN_MASK 0x00010000L
+#define PCIE_CNTL__RX_RCB_REORDER_EN__SHIFT 0x00000010
+#define PCIE_CNTL__RX_RCB_UNEXP_CPL_DIS_MASK 0x00040000L
+#define PCIE_CNTL__RX_RCB_UNEXP_CPL_DIS__SHIFT 0x00000012
+#define PCIE_CNTL__RX_RCB_WRONG_ATTR_DIS_MASK 0x00200000L
+#define PCIE_CNTL__RX_RCB_WRONG_ATTR_DIS__SHIFT 0x00000015
+#define PCIE_CNTL__RX_RCB_WRONG_FUNCNUM_DIS_MASK 0x00400000L
+#define PCIE_CNTL__RX_RCB_WRONG_FUNCNUM_DIS__SHIFT 0x00000016
+#define PCIE_CNTL__RX_SB_ADJ_PAYLOAD_SIZE_MASK 0x00001c00L
+#define PCIE_CNTL__RX_SB_ADJ_PAYLOAD_SIZE__SHIFT 0x0000000a
+#define PCIE_CNTL__TX_CPL_DEBUG_MASK 0x3f000000L
+#define PCIE_CNTL__TX_CPL_DEBUG__SHIFT 0x00000018
+#define PCIE_CNTL__UR_ERR_REPORT_DIS_MASK 0x00000080L
+#define PCIE_CNTL__UR_ERR_REPORT_DIS__SHIFT 0x00000007
+#define PCIE_CONFIG_CNTL__CI_EXTENDED_TAG_EN_OVERRIDE_MASK 0x02000000L
+#define PCIE_CONFIG_CNTL__CI_EXTENDED_TAG_EN_OVERRIDE__SHIFT 0x00000019
+#define PCIE_CONFIG_CNTL__CI_MAX_PAYLOAD_SIZE_MODE_MASK 0x00010000L
+#define PCIE_CONFIG_CNTL__CI_MAX_PAYLOAD_SIZE_MODE__SHIFT 0x00000010
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_REQUEST_SIZE_MODE_MASK 0x00100000L
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_REQUEST_SIZE_MODE__SHIFT 0x00000014
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_SAFE_MODE_MASK 0x01000000L
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_SAFE_MODE__SHIFT 0x00000018
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_PAYLOAD_SIZE_MASK 0x000e0000L
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_PAYLOAD_SIZE__SHIFT 0x00000011
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_READ_REQUEST_SIZE_MASK 0x00e00000L
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_READ_REQUEST_SIZE__SHIFT 0x00000015
+#define PCIE_CONFIG_CNTL__DYN_CLK_LATENCY_MASK 0x0000000fL
+#define PCIE_CONFIG_CNTL__DYN_CLK_LATENCY__SHIFT 0x00000000
+#define PCIE_DATA__PCIE_DATA_MASK 0xffffffffL
+#define PCIE_DATA__PCIE_DATA__SHIFT 0x00000000
+#define PCIE_DEBUG_CNTL__DEBUG_LANE_EN_MASK 0xffff0000L
+#define PCIE_DEBUG_CNTL__DEBUG_LANE_EN__SHIFT 0x00000010
+#define PCIE_DEBUG_CNTL__DEBUG_PORT_EN_MASK 0x000000ffL
+#define PCIE_DEBUG_CNTL__DEBUG_PORT_EN__SHIFT 0x00000000
+#define PCIE_DEBUG_CNTL__DEBUG_SELECT_MASK 0x00000100L
+#define PCIE_DEBUG_CNTL__DEBUG_SELECT__SHIFT 0x00000008
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F0_TIMER_EXPIRED_MASK 0x00000800L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F0_TIMER_EXPIRED__SHIFT 0x0000000b
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F1_TIMER_EXPIRED_MASK 0x00001000L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F1_TIMER_EXPIRED__SHIFT 0x0000000c
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F2_TIMER_EXPIRED_MASK 0x00002000L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F2_TIMER_EXPIRED__SHIFT 0x0000000d
+#define PCIE_ERR_CNTL__AER_HDR_LOG_TIMEOUT_MASK 0x00000700L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_TIMEOUT__SHIFT 0x00000008
+#define PCIE_ERR_CNTL__CI_NP_SLV_BUF_RD_HALT_STATUS_MASK 0x00008000L
+#define PCIE_ERR_CNTL__CI_NP_SLV_BUF_RD_HALT_STATUS__SHIFT 0x0000000f
+#define PCIE_ERR_CNTL__CI_P_SLV_BUF_RD_HALT_STATUS_MASK 0x00004000L
+#define PCIE_ERR_CNTL__CI_P_SLV_BUF_RD_HALT_STATUS__SHIFT 0x0000000e
+#define PCIE_ERR_CNTL__CI_SLV_BUF_HALT_RESET_MASK 0x00010000L
+#define PCIE_ERR_CNTL__CI_SLV_BUF_HALT_RESET__SHIFT 0x00000010
+#define PCIE_ERR_CNTL__ERR_REPORTING_DIS_MASK 0x00000001L
+#define PCIE_ERR_CNTL__ERR_REPORTING_DIS__SHIFT 0x00000000
+#define PCIE_ERR_CNTL__RX_GENERATE_ECRC_ERR_MASK 0x00000080L
+#define PCIE_ERR_CNTL__RX_GENERATE_ECRC_ERR__SHIFT 0x00000007
+#define PCIE_ERR_CNTL__RX_GENERATE_LCRC_ERR_MASK 0x00000020L
+#define PCIE_ERR_CNTL__RX_GENERATE_LCRC_ERR__SHIFT 0x00000005
+#define PCIE_ERR_CNTL__STRAP_FIRST_RCVD_ERR_LOG_MASK 0x00000002L
+#define PCIE_ERR_CNTL__STRAP_FIRST_RCVD_ERR_LOG__SHIFT 0x00000001
+#define PCIE_ERR_CNTL__TX_GENERATE_ECRC_ERR_MASK 0x00000040L
+#define PCIE_ERR_CNTL__TX_GENERATE_ECRC_ERR__SHIFT 0x00000006
+#define PCIE_ERR_CNTL__TX_GENERATE_LCRC_ERR_MASK 0x00000010L
+#define PCIE_ERR_CNTL__TX_GENERATE_LCRC_ERR__SHIFT 0x00000004
+#define PCIE_F0_DPA_CAP__PWR_ALLOC_SCALE_MASK 0x00003000L
+#define PCIE_F0_DPA_CAP__PWR_ALLOC_SCALE__SHIFT 0x0000000c
+#define PCIE_F0_DPA_CAP__TRANS_LAT_UNIT_MASK 0x00000300L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_UNIT__SHIFT 0x00000008
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_0_MASK 0x00ff0000L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_0__SHIFT 0x00000010
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_1_MASK 0xff000000L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_1__SHIFT 0x00000018
+#define PCIE_F0_DPA_CNTL__SUBSTATE_STATUS_MASK 0x0000001fL
+#define PCIE_F0_DPA_CNTL__SUBSTATE_STATUS__SHIFT 0x00000000
+#define PCIE_F0_DPA_LATENCY_INDICATOR__TRANS_LAT_INDICATOR_BITS_MASK 0x000000ffL
+#define PCIE_F0_DPA_LATENCY_INDICATOR__TRANS_LAT_INDICATOR_BITS__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_FC_CPL__CPLD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_CPL__CPLD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_CPL__CPLH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_CPL__CPLH_CREDITS__SHIFT 0x00000008
+#define PCIE_FC_NP__NPD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_NP__NPD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_NP__NPH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_NP__NPH_CREDITS__SHIFT 0x00000008
+#define PCIE_FC_P__PD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_P__PD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_P__PH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_P__PH_CREDITS__SHIFT 0x00000008
+#define PCIE_HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define PCIE_HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define PCIE_HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define PCIE_HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define PCIE_HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define PCIE_HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define PCIE_HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define PCIE_HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define PCIE_HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define PCIE_HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define PCIE_HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define PCIE_HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define PCIE_HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define PCIE_HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define PCIE_HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define PCIE_HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define PCIE_HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define PCIE_HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define PCIE_HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define PCIE_HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define PCIE_HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define PCIE_HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define PCIE_HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define PCIE_HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define PCIE_HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define PCIE_HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define PCIE_HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define PCIE_HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define PCIE_HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define PCIE_HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define PCIE_HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define PCIE_HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define PCIE_I2C_REG_ADDR_EXPAND__I2C_REG_ADDR_MASK 0x0001ffffL
+#define PCIE_I2C_REG_ADDR_EXPAND__I2C_REG_ADDR__SHIFT 0x00000000
+#define PCIE_I2C_REG_DATA__I2C_REG_DATA_MASK 0xffffffffL
+#define PCIE_I2C_REG_DATA__I2C_REG_DATA__SHIFT 0x00000000
+#define PCIE_INDEX__PCIE_INDEX_MASK 0x000000ffL
+#define PCIE_INDEX__PCIE_INDEX__SHIFT 0x00000000
+#define PCIE_INT_CNTL__CORR_ERR_INT_EN_MASK 0x00000001L
+#define PCIE_INT_CNTL__CORR_ERR_INT_EN__SHIFT 0x00000000
+#define PCIE_INT_CNTL__FATAL_ERR_INT_EN_MASK 0x00000004L
+#define PCIE_INT_CNTL__FATAL_ERR_INT_EN__SHIFT 0x00000002
+#define PCIE_INT_CNTL__LINK_BW_INT_EN_MASK 0x00000080L
+#define PCIE_INT_CNTL__LINK_BW_INT_EN__SHIFT 0x00000007
+#define PCIE_INT_CNTL__MISC_ERR_INT_EN_MASK 0x00000010L
+#define PCIE_INT_CNTL__MISC_ERR_INT_EN__SHIFT 0x00000004
+#define PCIE_INT_CNTL__NON_FATAL_ERR_INT_EN_MASK 0x00000002L
+#define PCIE_INT_CNTL__NON_FATAL_ERR_INT_EN__SHIFT 0x00000001
+#define PCIE_INT_CNTL__POWER_STATE_CHG_INT_EN_MASK 0x00000040L
+#define PCIE_INT_CNTL__POWER_STATE_CHG_INT_EN__SHIFT 0x00000006
+#define PCIE_INT_CNTL__QUIESCE_RCVD_INT_EN_MASK 0x00000100L
+#define PCIE_INT_CNTL__QUIESCE_RCVD_INT_EN__SHIFT 0x00000008
+#define PCIE_INT_CNTL__USR_DETECTED_INT_EN_MASK 0x00000008L
+#define PCIE_INT_CNTL__USR_DETECTED_INT_EN__SHIFT 0x00000003
+#define PCIE_INT_STATUS__CORR_ERR_INT_STATUS_MASK 0x00000001L
+#define PCIE_INT_STATUS__CORR_ERR_INT_STATUS__SHIFT 0x00000000
+#define PCIE_INT_STATUS__FATAL_ERR_INT_STATUS_MASK 0x00000004L
+#define PCIE_INT_STATUS__FATAL_ERR_INT_STATUS__SHIFT 0x00000002
+#define PCIE_INT_STATUS__LINK_BW_INT_STATUS_MASK 0x00000080L
+#define PCIE_INT_STATUS__LINK_BW_INT_STATUS__SHIFT 0x00000007
+#define PCIE_INT_STATUS__MISC_ERR_INT_STATUS_MASK 0x00000010L
+#define PCIE_INT_STATUS__MISC_ERR_INT_STATUS__SHIFT 0x00000004
+#define PCIE_INT_STATUS__NON_FATAL_ERR_INT_STATUS_MASK 0x00000002L
+#define PCIE_INT_STATUS__NON_FATAL_ERR_INT_STATUS__SHIFT 0x00000001
+#define PCIE_INT_STATUS__POWER_STATE_CHG_INT_STATUS_MASK 0x00000040L
+#define PCIE_INT_STATUS__POWER_STATE_CHG_INT_STATUS__SHIFT 0x00000006
+#define PCIE_INT_STATUS__QUIESCE_RCVD_INT_STATUS_MASK 0x00000100L
+#define PCIE_INT_STATUS__QUIESCE_RCVD_INT_STATUS__SHIFT 0x00000008
+#define PCIE_INT_STATUS__USR_DETECTED_INT_STATUS_MASK 0x00000008L
+#define PCIE_INT_STATUS__USR_DETECTED_INT_STATUS__SHIFT 0x00000003
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_CURSOR_MASK 0x0000fc00L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_CURSOR__SHIFT 0x0000000a
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_FOM_MASK 0x3fc00000L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_FOM__SHIFT 0x00000016
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_POSTCURSOR_MASK 0x003f0000L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_POSTCURSOR__SHIFT 0x00000010
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRECURSOR_MASK 0x000003f0L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRECURSOR__SHIFT 0x00000004
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRESET_MASK 0x0000000fL
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRESET__SHIFT 0x00000000
+#define PCIE_LC_BW_CHANGE_CNTL__LC_BW_CHANGE_INT_EN_MASK 0x00000001L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_BW_CHANGE_INT_EN__SHIFT 0x00000000
+#define PCIE_LC_BW_CHANGE_CNTL__LC_FAILED_SPEED_NEG_MASK 0x00000020L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_FAILED_SPEED_NEG__SHIFT 0x00000005
+#define PCIE_LC_BW_CHANGE_CNTL__LC_HW_INIT_SPEED_CHANGE_MASK 0x00000002L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_HW_INIT_SPEED_CHANGE__SHIFT 0x00000001
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LINK_BW_NOTIFICATION_DETECT_MODE_MASK 0x00000400L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LINK_BW_NOTIFICATION_DETECT_MODE__SHIFT 0x0000000a
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LONG_LW_CHANGE_MASK 0x00000040L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LONG_LW_CHANGE__SHIFT 0x00000006
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_FAILED_MASK 0x00000200L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_FAILED__SHIFT 0x00000009
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_OTHER_MASK 0x00000100L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_OTHER__SHIFT 0x00000008
+#define PCIE_LC_BW_CHANGE_CNTL__LC_OTHER_INIT_SPEED_CHANGE_MASK 0x00000008L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_OTHER_INIT_SPEED_CHANGE__SHIFT 0x00000003
+#define PCIE_LC_BW_CHANGE_CNTL__LC_RELIABILITY_SPEED_CHANGE_MASK 0x00000010L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_RELIABILITY_SPEED_CHANGE__SHIFT 0x00000004
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SHORT_LW_CHANGE_MASK 0x00000080L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SHORT_LW_CHANGE__SHIFT 0x00000007
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SW_INIT_SPEED_CHANGE_MASK 0x00000004L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SW_INIT_SPEED_CHANGE__SHIFT 0x00000002
+#define PCIE_LC_CDR_CNTL__LC_CDR_SET_TYPE_MASK 0x03000000L
+#define PCIE_LC_CDR_CNTL__LC_CDR_SET_TYPE__SHIFT 0x00000018
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_OFF_MASK 0x00000fffL
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_OFF__SHIFT 0x00000000
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_SETS_MASK 0x00fff000L
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_SETS__SHIFT 0x0000000c
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1_MASK 0x00020000L
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1__SHIFT 0x00000011
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23_MASK 0x00040000L
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23__SHIFT 0x00000012
+#define PCIE_LC_CNTL2__LC_ASSERT_INACTIVE_DURING_HOLD_MASK 0x00400000L
+#define PCIE_LC_CNTL2__LC_ASSERT_INACTIVE_DURING_HOLD__SHIFT 0x00000016
+#define PCIE_LC_CNTL2__LC_BLOCK_EL_IDLE_IN_L0_MASK 0x00100000L
+#define PCIE_LC_CNTL2__LC_BLOCK_EL_IDLE_IN_L0__SHIFT 0x00000014
+#define PCIE_LC_CNTL2__LC_DEASSERT_RX_EN_IN_L0S_MASK 0x00080000L
+#define PCIE_LC_CNTL2__LC_DEASSERT_RX_EN_IN_L0S__SHIFT 0x00000013
+#define PCIE_LC_CNTL2__LC_DISABLE_INFERRED_ELEC_IDLE_DET_MASK 0x00010000L
+#define PCIE_LC_CNTL2__LC_DISABLE_INFERRED_ELEC_IDLE_DET__SHIFT 0x00000010
+#define PCIE_LC_CNTL2__LC_DISABLE_LOST_SYM_LOCK_ARCS_MASK 0x04000000L
+#define PCIE_LC_CNTL2__LC_DISABLE_LOST_SYM_LOCK_ARCS__SHIFT 0x0000001a
+#define PCIE_LC_CNTL2__LC_ELEC_IDLE_MODE_MASK 0x0000c000L
+#define PCIE_LC_CNTL2__LC_ELEC_IDLE_MODE__SHIFT 0x0000000e
+#define PCIE_LC_CNTL2__LC_ENABLE_INFERRED_ELEC_IDLE_FOR_PI_MASK 0x80000000L
+#define PCIE_LC_CNTL2__LC_ENABLE_INFERRED_ELEC_IDLE_FOR_PI__SHIFT 0x0000001f
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_MASK 0x00000800L
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_RESTART_EN_MASK 0x00001000L
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_RESTART_EN__SHIFT 0x0000000c
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE__SHIFT 0x0000000b
+#define PCIE_LC_CNTL2__LC_LINK_BW_NOTIFICATION_DIS_MASK 0x08000000L
+#define PCIE_LC_CNTL2__LC_LINK_BW_NOTIFICATION_DIS__SHIFT 0x0000001b
+#define PCIE_LC_CNTL2__LC_LINK_UP_REVERSAL_EN_MASK 0x00000400L
+#define PCIE_LC_CNTL2__LC_LINK_UP_REVERSAL_EN__SHIFT 0x0000000a
+#define PCIE_LC_CNTL2__LC_LOOK_FOR_BW_REDUCTION_MASK 0x00000080L
+#define PCIE_LC_CNTL2__LC_LOOK_FOR_BW_REDUCTION__SHIFT 0x00000007
+#define PCIE_LC_CNTL2__LC_MORE_TS2_EN_MASK 0x00000100L
+#define PCIE_LC_CNTL2__LC_MORE_TS2_EN__SHIFT 0x00000008
+#define PCIE_LC_CNTL2__LC_PMI_L1_WAIT_FOR_SLV_IDLE_MASK 0x10000000L
+#define PCIE_LC_CNTL2__LC_PMI_L1_WAIT_FOR_SLV_IDLE__SHIFT 0x0000001c
+#define PCIE_LC_CNTL2__LC_PWR_DOWN_NEG_OFF_LANES_MASK 0x02000000L
+#define PCIE_LC_CNTL2__LC_PWR_DOWN_NEG_OFF_LANES__SHIFT 0x00000019
+#define PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS_MASK 0x00200000L
+#define PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS__SHIFT 0x00000015
+#define PCIE_LC_CNTL2__LC_STATE_TIMED_OUT_MASK 0x00000040L
+#define PCIE_LC_CNTL2__LC_STATE_TIMED_OUT__SHIFT 0x00000006
+#define PCIE_LC_CNTL2__LC_TEST_TIMER_SEL_MASK 0x60000000L
+#define PCIE_LC_CNTL2__LC_TEST_TIMER_SEL__SHIFT 0x0000001d
+#define PCIE_LC_CNTL2__LC_TIMED_OUT_STATE_MASK 0x0000003fL
+#define PCIE_LC_CNTL2__LC_TIMED_OUT_STATE__SHIFT 0x00000000
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_LANES_IN_LW_NEG_MASK 0x01800000L
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_LANES_IN_LW_NEG__SHIFT 0x00000017
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_OTHER_LANES_MODE_MASK 0x00002000L
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_OTHER_LANES_MODE__SHIFT 0x0000000d
+#define PCIE_LC_CNTL2__LC_X12_NEGOTIATION_DIS_MASK 0x00000200L
+#define PCIE_LC_CNTL2__LC_X12_NEGOTIATION_DIS__SHIFT 0x00000009
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_EN_MASK 0x00040000L
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_EN__SHIFT 0x00000012
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_MAX_FAIL_SEL_MASK 0x00180000L
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_MAX_FAIL_SEL__SHIFT 0x00000013
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPT_FAILED_MASK 0x00000100L
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPT_FAILED__SHIFT 0x00000008
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK 0x000000c0L
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPTS_ALLOWED__SHIFT 0x00000006
+#define PCIE_LC_CNTL3__LC_CHIP_BIF_USB_IDLE_EN_MASK 0x00010000L
+#define PCIE_LC_CNTL3__LC_CHIP_BIF_USB_IDLE_EN__SHIFT 0x00000010
+#define PCIE_LC_CNTL3__LC_CLR_FAILED_AUTO_SPD_CHANGE_CNT_MASK 0x00000200L
+#define PCIE_LC_CNTL3__LC_CLR_FAILED_AUTO_SPD_CHANGE_CNT__SHIFT 0x00000009
+#define PCIE_LC_CNTL3__LC_COMP_TO_DETECT_MASK 0x00000010L
+#define PCIE_LC_CNTL3__LC_COMP_TO_DETECT__SHIFT 0x00000004
+#define PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK_MASK 0x00800000L
+#define PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK__SHIFT 0x00000017
+#define PCIE_LC_CNTL3__LC_EHP_RX_PHY_CMD_MASK 0x00003000L
+#define PCIE_LC_CNTL3__LC_EHP_RX_PHY_CMD__SHIFT 0x0000000c
+#define PCIE_LC_CNTL3__LC_EHP_TX_PHY_CMD_MASK 0x0000c000L
+#define PCIE_LC_CNTL3__LC_EHP_TX_PHY_CMD__SHIFT 0x0000000e
+#define PCIE_LC_CNTL3__LC_ENHANCED_HOT_PLUG_EN_MASK 0x00000400L
+#define PCIE_LC_CNTL3__LC_ENHANCED_HOT_PLUG_EN__SHIFT 0x0000000a
+#define PCIE_LC_CNTL3__LC_FAST_L1_ENTRY_EXIT_EN_MASK 0x00200000L
+#define PCIE_LC_CNTL3__LC_FAST_L1_ENTRY_EXIT_EN__SHIFT 0x00000015
+#define PCIE_LC_CNTL3__LC_GO_TO_RECOVERY_MASK 0x40000000L
+#define PCIE_LC_CNTL3__LC_GO_TO_RECOVERY__SHIFT 0x0000001e
+#define PCIE_LC_CNTL3__LC_HW_VOLTAGE_IF_CONTROL_MASK 0x03000000L
+#define PCIE_LC_CNTL3__LC_HW_VOLTAGE_IF_CONTROL__SHIFT 0x00000018
+#define PCIE_LC_CNTL3__LC_L1_BLOCK_RECONFIG_EN_MASK 0x00020000L
+#define PCIE_LC_CNTL3__LC_L1_BLOCK_RECONFIG_EN__SHIFT 0x00000011
+#define PCIE_LC_CNTL3__LC_N_EIE_SEL_MASK 0x80000000L
+#define PCIE_LC_CNTL3__LC_N_EIE_SEL__SHIFT 0x0000001f
+#define PCIE_LC_CNTL3__LC_RCVD_DEEMPHASIS_MASK 0x00000008L
+#define PCIE_LC_CNTL3__LC_RCVD_DEEMPHASIS__SHIFT 0x00000003
+#define PCIE_LC_CNTL3__LC_RCVR_DET_EN_OVERRIDE_MASK 0x00000800L
+#define PCIE_LC_CNTL3__LC_RCVR_DET_EN_OVERRIDE__SHIFT 0x0000000b
+#define PCIE_LC_CNTL3__LC_RESET_TSX_CNT_IN_RLOCK_EN_MASK 0x00000020L
+#define PCIE_LC_CNTL3__LC_RESET_TSX_CNT_IN_RLOCK_EN__SHIFT 0x00000005
+#define PCIE_LC_CNTL3__LC_RXPHYCMD_INACTIVE_EN_MODE_MASK 0x00400000L
+#define PCIE_LC_CNTL3__LC_RXPHYCMD_INACTIVE_EN_MODE__SHIFT 0x00000016
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_CNTL_MASK 0x00000006L
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_CNTL__SHIFT 0x00000001
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_MASK 0x00000001L
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS__SHIFT 0x00000000
+#define PCIE_LC_CNTL3__LC_VOLTAGE_TIMER_SEL_MASK 0x3c000000L
+#define PCIE_LC_CNTL3__LC_VOLTAGE_TIMER_SEL__SHIFT 0x0000001a
+#define PCIE_LC_CNTL4__LC_8GT_SKIP_ORDER_EN_MASK 0x02000000L
+#define PCIE_LC_CNTL4__LC_8GT_SKIP_ORDER_EN__SHIFT 0x00000019
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_MASK 0x00000010L
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_REQ_PHASE_MASK 0x00010000L
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_REQ_PHASE__SHIFT 0x00000010
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ__SHIFT 0x00000004
+#define PCIE_LC_CNTL4__LC_DSC_CHECK_COEFFS_IN_RLOCK_MASK 0x00000400L
+#define PCIE_LC_CNTL4__LC_DSC_CHECK_COEFFS_IN_RLOCK__SHIFT 0x0000000a
+#define PCIE_LC_CNTL4__LC_EQ_SEARCH_MODE_MASK 0x00000300L
+#define PCIE_LC_CNTL4__LC_EQ_SEARCH_MODE__SHIFT 0x00000008
+#define PCIE_LC_CNTL4__LC_EQ_WAIT_FOR_EVAL_DONE_MASK 0x01000000L
+#define PCIE_LC_CNTL4__LC_EQ_WAIT_FOR_EVAL_DONE__SHIFT 0x00000018
+#define PCIE_LC_CNTL4__LC_EXTEND_EIEOS_MASK 0x00000040L
+#define PCIE_LC_CNTL4__LC_EXTEND_EIEOS__SHIFT 0x00000006
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_IN_EQ_REQ_PHASE_MASK 0x00020000L
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_IN_EQ_REQ_PHASE__SHIFT 0x00000011
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_VALUE_MASK 0x003c0000L
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_VALUE__SHIFT 0x00000012
+#define PCIE_LC_CNTL4__LC_IGNORE_PARITY_MASK 0x00000080L
+#define PCIE_LC_CNTL4__LC_IGNORE_PARITY__SHIFT 0x00000007
+#define PCIE_LC_CNTL4__LC_PCIE_TX_FULL_SWING_MASK 0x00800000L
+#define PCIE_LC_CNTL4__LC_PCIE_TX_FULL_SWING__SHIFT 0x00000017
+#define PCIE_LC_CNTL4__LC_QUIESCE_RCVD_MASK 0x00004000L
+#define PCIE_LC_CNTL4__LC_QUIESCE_RCVD__SHIFT 0x0000000e
+#define PCIE_LC_CNTL4__LC_REDO_EQ_MASK 0x00000020L
+#define PCIE_LC_CNTL4__LC_REDO_EQ__SHIFT 0x00000005
+#define PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK 0x00002000L
+#define PCIE_LC_CNTL4__LC_SET_QUIESCE__SHIFT 0x0000000d
+#define PCIE_LC_CNTL4__LC_TX_ENABLE_BEHAVIOUR_MASK 0x00000003L
+#define PCIE_LC_CNTL4__LC_TX_ENABLE_BEHAVIOUR__SHIFT 0x00000000
+#define PCIE_LC_CNTL4__LC_UNEXPECTED_COEFFS_RCVD_MASK 0x00008000L
+#define PCIE_LC_CNTL4__LC_UNEXPECTED_COEFFS_RCVD__SHIFT 0x0000000f
+#define PCIE_LC_CNTL4__LC_USC_DELAY_DLLPS_MASK 0x00400000L
+#define PCIE_LC_CNTL4__LC_USC_DELAY_DLLPS__SHIFT 0x00000016
+#define PCIE_LC_CNTL4__LC_USC_EQ_NOT_REQD_MASK 0x00000800L
+#define PCIE_LC_CNTL4__LC_USC_EQ_NOT_REQD__SHIFT 0x0000000b
+#define PCIE_LC_CNTL4__LC_USC_GO_TO_EQ_MASK 0x00001000L
+#define PCIE_LC_CNTL4__LC_USC_GO_TO_EQ__SHIFT 0x0000000c
+#define PCIE_LC_CNTL4__LC_WAIT_FOR_MORE_TS_IN_RLOCK_MASK 0xfc000000L
+#define PCIE_LC_CNTL4__LC_WAIT_FOR_MORE_TS_IN_RLOCK__SHIFT 0x0000001a
+#define PCIE_LC_CNTL5__LC_EQ_FS_0_MASK 0x0000003fL
+#define PCIE_LC_CNTL5__LC_EQ_FS_0__SHIFT 0x00000000
+#define PCIE_LC_CNTL5__LC_EQ_FS_8_MASK 0x00000fc0L
+#define PCIE_LC_CNTL5__LC_EQ_FS_8__SHIFT 0x00000006
+#define PCIE_LC_CNTL5__LC_EQ_LF_0_MASK 0x0003f000L
+#define PCIE_LC_CNTL5__LC_EQ_LF_0__SHIFT 0x0000000c
+#define PCIE_LC_CNTL5__LC_EQ_LF_8_MASK 0x00fc0000L
+#define PCIE_LC_CNTL5__LC_EQ_LF_8__SHIFT 0x00000012
+#define PCIE_LC_CNTL__LC_16X_CLEAR_TX_PIPE_MASK 0x000000f0L
+#define PCIE_LC_CNTL__LC_16X_CLEAR_TX_PIPE__SHIFT 0x00000004
+#define PCIE_LC_CNTL__LC_ASPM_TO_L1_DIS_MASK 0x01000000L
+#define PCIE_LC_CNTL__LC_ASPM_TO_L1_DIS__SHIFT 0x00000018
+#define PCIE_LC_CNTL__LC_DELAY_COUNT_MASK 0x06000000L
+#define PCIE_LC_CNTL__LC_DELAY_COUNT__SHIFT 0x00000019
+#define PCIE_LC_CNTL__LC_DELAY_L0S_EXIT_MASK 0x08000000L
+#define PCIE_LC_CNTL__LC_DELAY_L0S_EXIT__SHIFT 0x0000001b
+#define PCIE_LC_CNTL__LC_DELAY_L1_EXIT_MASK 0x10000000L
+#define PCIE_LC_CNTL__LC_DELAY_L1_EXIT__SHIFT 0x0000001c
+#define PCIE_LC_CNTL__LC_DONT_ENTER_L23_IN_D0_MASK 0x00000002L
+#define PCIE_LC_CNTL__LC_DONT_ENTER_L23_IN_D0__SHIFT 0x00000001
+#define PCIE_LC_CNTL__LC_ESCAPE_L1L23_EN_MASK 0x40000000L
+#define PCIE_LC_CNTL__LC_ESCAPE_L1L23_EN__SHIFT 0x0000001e
+#define PCIE_LC_CNTL__LC_EXTEND_WAIT_FOR_EL_IDLE_MASK 0x20000000L
+#define PCIE_LC_CNTL__LC_EXTEND_WAIT_FOR_EL_IDLE__SHIFT 0x0000001d
+#define PCIE_LC_CNTL__LC_FACTOR_IN_EXT_SYNC_MASK 0x00100000L
+#define PCIE_LC_CNTL__LC_FACTOR_IN_EXT_SYNC__SHIFT 0x00000014
+#define PCIE_LC_CNTL__LC_GATE_RCVR_IDLE_MASK 0x80000000L
+#define PCIE_LC_CNTL__LC_GATE_RCVR_IDLE__SHIFT 0x0000001f
+#define PCIE_LC_CNTL__LC_INC_N_FTS_EN_MASK 0x00020000L
+#define PCIE_LC_CNTL__LC_INC_N_FTS_EN__SHIFT 0x00000011
+#define PCIE_LC_CNTL__LC_L0S_INACTIVITY_MASK 0x00000f00L
+#define PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT 0x00000008
+#define PCIE_LC_CNTL__LC_L1_IMMEDIATE_ACK_MASK 0x00800000L
+#define PCIE_LC_CNTL__LC_L1_IMMEDIATE_ACK__SHIFT 0x00000017
+#define PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK 0x0000f000L
+#define PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT 0x0000000c
+#define PCIE_LC_CNTL__LC_LOOK_FOR_IDLE_IN_L1L23_MASK 0x000c0000L
+#define PCIE_LC_CNTL__LC_LOOK_FOR_IDLE_IN_L1L23__SHIFT 0x00000012
+#define PCIE_LC_CNTL__LC_PMI_TO_L1_DIS_MASK 0x00010000L
+#define PCIE_LC_CNTL__LC_PMI_TO_L1_DIS__SHIFT 0x00000010
+#define PCIE_LC_CNTL__LC_RESET_L_IDLE_COUNT_EN_MASK 0x00000004L
+#define PCIE_LC_CNTL__LC_RESET_L_IDLE_COUNT_EN__SHIFT 0x00000002
+#define PCIE_LC_CNTL__LC_RESET_LINK_MASK 0x00000008L
+#define PCIE_LC_CNTL__LC_RESET_LINK__SHIFT 0x00000003
+#define PCIE_LC_CNTL__LC_WAIT_FOR_PM_ACK_DIS_MASK 0x00200000L
+#define PCIE_LC_CNTL__LC_WAIT_FOR_PM_ACK_DIS__SHIFT 0x00000015
+#define PCIE_LC_CNTL__LC_WAKE_FROM_L23_MASK 0x00400000L
+#define PCIE_LC_CNTL__LC_WAKE_FROM_L23__SHIFT 0x00000016
+#define PCIE_LC_FORCE_COEFF__LC_3X3_COEFF_SEARCH_EN_MASK 0x00080000L
+#define PCIE_LC_FORCE_COEFF__LC_3X3_COEFF_SEARCH_EN__SHIFT 0x00000013
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_COEFF_MASK 0x00000001L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_COEFF__SHIFT 0x00000000
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_CURSOR_MASK 0x00001f80L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_CURSOR__SHIFT 0x00000007
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_POST_CURSOR_MASK 0x0007e000L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_POST_CURSOR__SHIFT 0x0000000d
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_PRE_CURSOR_MASK 0x0000007eL
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_PRE_CURSOR__SHIFT 0x00000001
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_COEFF_IN_EQ_REQ_PHASE_MASK 0x00000001L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_COEFF_IN_EQ_REQ_PHASE__SHIFT 0x00000000
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_CURSOR_REQ_MASK 0x00001f80L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_CURSOR_REQ__SHIFT 0x00000007
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_POST_CURSOR_REQ_MASK 0x0007e000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_POST_CURSOR_REQ__SHIFT 0x0000000d
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_PRE_CURSOR_REQ_MASK 0x0000007eL
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_PRE_CURSOR_REQ__SHIFT 0x00000001
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FS_OTHER_END_MASK 0x01f80000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FS_OTHER_END__SHIFT 0x00000013
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_LF_OTHER_END_MASK 0x7e000000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_LF_OTHER_END__SHIFT 0x00000019
+#define PCIE_LC_LANE_CNTL__LC_CORRUPTED_LANES_MASK 0x0000ffffL
+#define PCIE_LC_LANE_CNTL__LC_CORRUPTED_LANES__SHIFT 0x00000000
+#define PCIE_LC_LANE_CNTL__LC_LANE_DIS_MASK 0xffff0000L
+#define PCIE_LC_LANE_CNTL__LC_LANE_DIS__SHIFT 0x00000010
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DEASSERT_TX_PDNB_MASK 0x00010000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DEASSERT_TX_PDNB__SHIFT 0x00000010
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DUAL_END_RECONFIG_EN_MASK 0x00080000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DUAL_END_RECONFIG_EN__SHIFT 0x00000013
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYN_LANES_PWR_STATE_MASK 0x00600000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYN_LANES_PWR_STATE__SHIFT 0x00000015
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYNLINK_MST_EN_MASK 0x00040000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYNLINK_MST_EN__SHIFT 0x00000012
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_EQ_REVERSAL_LOGIC_EN_MASK 0x00800000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_EQ_REVERSAL_LOGIC_EN__SHIFT 0x00000017
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN_MASK 0x00020000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN__SHIFT 0x00000011
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_MASK 0x00000007L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x00000004
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH__SHIFT 0x00000000
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_ARC_MISSING_ESCAPE_MASK 0x00000080L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_ARC_MISSING_ESCAPE__SHIFT 0x00000007
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_NOW_MASK 0x00000100L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_NOW__SHIFT 0x00000008
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATE_EN_MASK 0x00000400L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATE_EN__SHIFT 0x0000000a
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATION_SUPPORT_MASK 0x00000200L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATION_SUPPORT__SHIFT 0x00000009
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_SHORT_RECONFIG_EN_MASK 0x00000800L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_SHORT_RECONFIG_EN__SHIFT 0x0000000b
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_TIMER_SEL_MASK 0x00008000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_TIMER_SEL__SHIFT 0x0000000f
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_WAIT_FOR_RCVR_DIS_MASK 0x00004000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_WAIT_FOR_RCVR_DIS__SHIFT 0x0000000e
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_CAPABLE_MASK 0x00100000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_CAPABLE__SHIFT 0x00000014
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_DIS_MASK 0x00002000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_DIS__SHIFT 0x0000000d
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_SUPPORT_MASK 0x00001000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_SUPPORT__SHIFT 0x0000000c
+#define PCIE_LC_N_FTS_CNTL__LC_N_FTS_MASK 0xff000000L
+#define PCIE_LC_N_FTS_CNTL__LC_N_FTS__SHIFT 0x00000018
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_FTS_BEFORE_RECOVERY_MASK 0x00000200L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_FTS_BEFORE_RECOVERY__SHIFT 0x00000009
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_LIMIT_MASK 0x00ff0000L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_LIMIT__SHIFT 0x00000010
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_MASK 0x000000ffL
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_OVERRIDE_EN_MASK 0x00000100L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_OVERRIDE_EN__SHIFT 0x00000008
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS__SHIFT 0x00000000
+#define PCIE_LC_SPEED_CNTL__LC_1_OR_MORE_TS2_SPEED_ARC_EN_MASK 0x00020000L
+#define PCIE_LC_SPEED_CNTL__LC_1_OR_MORE_TS2_SPEED_ARC_EN__SHIFT 0x00000011
+#define PCIE_LC_SPEED_CNTL__LC_AUTO_RECOVERY_DIS_MASK 0x00400000L
+#define PCIE_LC_SPEED_CNTL__LC_AUTO_RECOVERY_DIS__SHIFT 0x00000016
+#define PCIE_LC_SPEED_CNTL__LC_CHECK_DATA_RATE_MASK 0x04000000L
+#define PCIE_LC_SPEED_CNTL__LC_CHECK_DATA_RATE__SHIFT 0x0000001a
+#define PCIE_LC_SPEED_CNTL__LC_CLR_FAILED_SPD_CHANGE_CNT_MASK 0x00010000L
+#define PCIE_LC_SPEED_CNTL__LC_CLR_FAILED_SPD_CHANGE_CNT__SHIFT 0x00000010
+#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0x00006000L
+#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x0000000d
+#define PCIE_LC_SPEED_CNTL__LC_DATA_RATE_ADVERTISED_MASK 0x03000000L
+#define PCIE_LC_SPEED_CNTL__LC_DATA_RATE_ADVERTISED__SHIFT 0x00000018
+#define PCIE_LC_SPEED_CNTL__LC_DELAY_COEFF_UPDATE_DIS_MASK 0x80000000L
+#define PCIE_LC_SPEED_CNTL__LC_DELAY_COEFF_UPDATE_DIS__SHIFT 0x0000001f
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CHECK_EQTS_IN_RCFG_MASK 0x40000000L
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CHECK_EQTS_IN_RCFG__SHIFT 0x0000001e
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CLR_TARGET_SPD_CHANGE_STATUS_MASK 0x00008000L
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CLR_TARGET_SPD_CHANGE_STATUS__SHIFT 0x0000000f
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_HW_SPEED_CHANGE_MASK 0x00000100L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_HW_SPEED_CHANGE__SHIFT 0x00000008
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK 0x00000040L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE__SHIFT 0x00000006
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_HW_SPEED_CHANGE_MASK 0x00000080L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_HW_SPEED_CHANGE__SHIFT 0x00000007
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_SW_SPEED_CHANGE_MASK 0x00000020L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_SW_SPEED_CHANGE__SHIFT 0x00000005
+#define PCIE_LC_SPEED_CNTL__LC_GEN2_EN_STRAP_MASK 0x00000001L
+#define PCIE_LC_SPEED_CNTL__LC_GEN2_EN_STRAP__SHIFT 0x00000000
+#define PCIE_LC_SPEED_CNTL__LC_GEN3_EN_STRAP_MASK 0x00000002L
+#define PCIE_LC_SPEED_CNTL__LC_GEN3_EN_STRAP__SHIFT 0x00000001
+#define PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK 0x00000200L
+#define PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE__SHIFT 0x00000009
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L0s_EN_MASK 0x10000000L
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L0s_EN__SHIFT 0x0000001c
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L1_EN_MASK 0x20000000L
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L1_EN__SHIFT 0x0000001d
+#define PCIE_LC_SPEED_CNTL__LC_MULT_UPSTREAM_AUTO_SPD_CHNG_EN_MASK 0x08000000L
+#define PCIE_LC_SPEED_CNTL__LC_MULT_UPSTREAM_AUTO_SPD_CHNG_EN__SHIFT 0x0000001b
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN2_MASK 0x00040000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN2__SHIFT 0x00000012
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN3_MASK 0x00100000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN3__SHIFT 0x00000014
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN2_MASK 0x00080000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN2__SHIFT 0x00000013
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN3_MASK 0x00200000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN3__SHIFT 0x00000015
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPT_FAILED_MASK 0x00001000L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPT_FAILED__SHIFT 0x0000000c
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK 0x00000c00L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPTS_ALLOWED__SHIFT 0x0000000a
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_STATUS_MASK 0x00800000L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_STATUS__SHIFT 0x00000017
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_EN_MASK 0x00000004L
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_EN__SHIFT 0x00000002
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_MASK 0x00000018L
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE__SHIFT 0x00000003
+#define PCIE_LC_STATE0__LC_CURRENT_STATE_MASK 0x0000003fL
+#define PCIE_LC_STATE0__LC_CURRENT_STATE__SHIFT 0x00000000
+#define PCIE_LC_STATE0__LC_PREV_STATE1_MASK 0x00003f00L
+#define PCIE_LC_STATE0__LC_PREV_STATE1__SHIFT 0x00000008
+#define PCIE_LC_STATE0__LC_PREV_STATE2_MASK 0x003f0000L
+#define PCIE_LC_STATE0__LC_PREV_STATE2__SHIFT 0x00000010
+#define PCIE_LC_STATE0__LC_PREV_STATE3_MASK 0x3f000000L
+#define PCIE_LC_STATE0__LC_PREV_STATE3__SHIFT 0x00000018
+#define PCIE_LC_STATE10__LC_PREV_STATE40_MASK 0x0000003fL
+#define PCIE_LC_STATE10__LC_PREV_STATE40__SHIFT 0x00000000
+#define PCIE_LC_STATE10__LC_PREV_STATE41_MASK 0x00003f00L
+#define PCIE_LC_STATE10__LC_PREV_STATE41__SHIFT 0x00000008
+#define PCIE_LC_STATE10__LC_PREV_STATE42_MASK 0x003f0000L
+#define PCIE_LC_STATE10__LC_PREV_STATE42__SHIFT 0x00000010
+#define PCIE_LC_STATE10__LC_PREV_STATE43_MASK 0x3f000000L
+#define PCIE_LC_STATE10__LC_PREV_STATE43__SHIFT 0x00000018
+#define PCIE_LC_STATE11__LC_PREV_STATE44_MASK 0x0000003fL
+#define PCIE_LC_STATE11__LC_PREV_STATE44__SHIFT 0x00000000
+#define PCIE_LC_STATE11__LC_PREV_STATE45_MASK 0x00003f00L
+#define PCIE_LC_STATE11__LC_PREV_STATE45__SHIFT 0x00000008
+#define PCIE_LC_STATE11__LC_PREV_STATE46_MASK 0x003f0000L
+#define PCIE_LC_STATE11__LC_PREV_STATE46__SHIFT 0x00000010
+#define PCIE_LC_STATE11__LC_PREV_STATE47_MASK 0x3f000000L
+#define PCIE_LC_STATE11__LC_PREV_STATE47__SHIFT 0x00000018
+#define PCIE_LC_STATE1__LC_PREV_STATE4_MASK 0x0000003fL
+#define PCIE_LC_STATE1__LC_PREV_STATE4__SHIFT 0x00000000
+#define PCIE_LC_STATE1__LC_PREV_STATE5_MASK 0x00003f00L
+#define PCIE_LC_STATE1__LC_PREV_STATE5__SHIFT 0x00000008
+#define PCIE_LC_STATE1__LC_PREV_STATE6_MASK 0x003f0000L
+#define PCIE_LC_STATE1__LC_PREV_STATE6__SHIFT 0x00000010
+#define PCIE_LC_STATE1__LC_PREV_STATE7_MASK 0x3f000000L
+#define PCIE_LC_STATE1__LC_PREV_STATE7__SHIFT 0x00000018
+#define PCIE_LC_STATE2__LC_PREV_STATE10_MASK 0x003f0000L
+#define PCIE_LC_STATE2__LC_PREV_STATE10__SHIFT 0x00000010
+#define PCIE_LC_STATE2__LC_PREV_STATE11_MASK 0x3f000000L
+#define PCIE_LC_STATE2__LC_PREV_STATE11__SHIFT 0x00000018
+#define PCIE_LC_STATE2__LC_PREV_STATE8_MASK 0x0000003fL
+#define PCIE_LC_STATE2__LC_PREV_STATE8__SHIFT 0x00000000
+#define PCIE_LC_STATE2__LC_PREV_STATE9_MASK 0x00003f00L
+#define PCIE_LC_STATE2__LC_PREV_STATE9__SHIFT 0x00000008
+#define PCIE_LC_STATE3__LC_PREV_STATE12_MASK 0x0000003fL
+#define PCIE_LC_STATE3__LC_PREV_STATE12__SHIFT 0x00000000
+#define PCIE_LC_STATE3__LC_PREV_STATE13_MASK 0x00003f00L
+#define PCIE_LC_STATE3__LC_PREV_STATE13__SHIFT 0x00000008
+#define PCIE_LC_STATE3__LC_PREV_STATE14_MASK 0x003f0000L
+#define PCIE_LC_STATE3__LC_PREV_STATE14__SHIFT 0x00000010
+#define PCIE_LC_STATE3__LC_PREV_STATE15_MASK 0x3f000000L
+#define PCIE_LC_STATE3__LC_PREV_STATE15__SHIFT 0x00000018
+#define PCIE_LC_STATE4__LC_PREV_STATE16_MASK 0x0000003fL
+#define PCIE_LC_STATE4__LC_PREV_STATE16__SHIFT 0x00000000
+#define PCIE_LC_STATE4__LC_PREV_STATE17_MASK 0x00003f00L
+#define PCIE_LC_STATE4__LC_PREV_STATE17__SHIFT 0x00000008
+#define PCIE_LC_STATE4__LC_PREV_STATE18_MASK 0x003f0000L
+#define PCIE_LC_STATE4__LC_PREV_STATE18__SHIFT 0x00000010
+#define PCIE_LC_STATE4__LC_PREV_STATE19_MASK 0x3f000000L
+#define PCIE_LC_STATE4__LC_PREV_STATE19__SHIFT 0x00000018
+#define PCIE_LC_STATE5__LC_PREV_STATE20_MASK 0x0000003fL
+#define PCIE_LC_STATE5__LC_PREV_STATE20__SHIFT 0x00000000
+#define PCIE_LC_STATE5__LC_PREV_STATE21_MASK 0x00003f00L
+#define PCIE_LC_STATE5__LC_PREV_STATE21__SHIFT 0x00000008
+#define PCIE_LC_STATE5__LC_PREV_STATE22_MASK 0x003f0000L
+#define PCIE_LC_STATE5__LC_PREV_STATE22__SHIFT 0x00000010
+#define PCIE_LC_STATE5__LC_PREV_STATE23_MASK 0x3f000000L
+#define PCIE_LC_STATE5__LC_PREV_STATE23__SHIFT 0x00000018
+#define PCIE_LC_STATE6__LC_PREV_STATE24_MASK 0x0000003fL
+#define PCIE_LC_STATE6__LC_PREV_STATE24__SHIFT 0x00000000
+#define PCIE_LC_STATE6__LC_PREV_STATE25_MASK 0x00003f00L
+#define PCIE_LC_STATE6__LC_PREV_STATE25__SHIFT 0x00000008
+#define PCIE_LC_STATE6__LC_PREV_STATE26_MASK 0x003f0000L
+#define PCIE_LC_STATE6__LC_PREV_STATE26__SHIFT 0x00000010
+#define PCIE_LC_STATE6__LC_PREV_STATE27_MASK 0x3f000000L
+#define PCIE_LC_STATE6__LC_PREV_STATE27__SHIFT 0x00000018
+#define PCIE_LC_STATE7__LC_PREV_STATE28_MASK 0x0000003fL
+#define PCIE_LC_STATE7__LC_PREV_STATE28__SHIFT 0x00000000
+#define PCIE_LC_STATE7__LC_PREV_STATE29_MASK 0x00003f00L
+#define PCIE_LC_STATE7__LC_PREV_STATE29__SHIFT 0x00000008
+#define PCIE_LC_STATE7__LC_PREV_STATE30_MASK 0x003f0000L
+#define PCIE_LC_STATE7__LC_PREV_STATE30__SHIFT 0x00000010
+#define PCIE_LC_STATE7__LC_PREV_STATE31_MASK 0x3f000000L
+#define PCIE_LC_STATE7__LC_PREV_STATE31__SHIFT 0x00000018
+#define PCIE_LC_STATE8__LC_PREV_STATE32_MASK 0x0000003fL
+#define PCIE_LC_STATE8__LC_PREV_STATE32__SHIFT 0x00000000
+#define PCIE_LC_STATE8__LC_PREV_STATE33_MASK 0x00003f00L
+#define PCIE_LC_STATE8__LC_PREV_STATE33__SHIFT 0x00000008
+#define PCIE_LC_STATE8__LC_PREV_STATE34_MASK 0x003f0000L
+#define PCIE_LC_STATE8__LC_PREV_STATE34__SHIFT 0x00000010
+#define PCIE_LC_STATE8__LC_PREV_STATE35_MASK 0x3f000000L
+#define PCIE_LC_STATE8__LC_PREV_STATE35__SHIFT 0x00000018
+#define PCIE_LC_STATE9__LC_PREV_STATE36_MASK 0x0000003fL
+#define PCIE_LC_STATE9__LC_PREV_STATE36__SHIFT 0x00000000
+#define PCIE_LC_STATE9__LC_PREV_STATE37_MASK 0x00003f00L
+#define PCIE_LC_STATE9__LC_PREV_STATE37__SHIFT 0x00000008
+#define PCIE_LC_STATE9__LC_PREV_STATE38_MASK 0x003f0000L
+#define PCIE_LC_STATE9__LC_PREV_STATE38__SHIFT 0x00000010
+#define PCIE_LC_STATE9__LC_PREV_STATE39_MASK 0x3f000000L
+#define PCIE_LC_STATE9__LC_PREV_STATE39__SHIFT 0x00000018
+#define PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK 0x000000e0L
+#define PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH__SHIFT 0x00000005
+#define PCIE_LC_STATUS1__LC_OPERATING_LINK_WIDTH_MASK 0x0000001cL
+#define PCIE_LC_STATUS1__LC_OPERATING_LINK_WIDTH__SHIFT 0x00000002
+#define PCIE_LC_STATUS1__LC_REVERSE_RCVR_MASK 0x00000001L
+#define PCIE_LC_STATUS1__LC_REVERSE_RCVR__SHIFT 0x00000000
+#define PCIE_LC_STATUS1__LC_REVERSE_XMIT_MASK 0x00000002L
+#define PCIE_LC_STATUS1__LC_REVERSE_XMIT__SHIFT 0x00000001
+#define PCIE_LC_STATUS2__LC_TOTAL_INACTIVE_LANES_MASK 0x0000ffffL
+#define PCIE_LC_STATUS2__LC_TOTAL_INACTIVE_LANES__SHIFT 0x00000000
+#define PCIE_LC_STATUS2__LC_TURN_ON_LANE_MASK 0xffff0000L
+#define PCIE_LC_STATUS2__LC_TURN_ON_LANE__SHIFT 0x00000010
+#define PCIE_LC_TRAINING_CNTL__LC_ALLOW_TX_L1_CONTROL_MASK 0x10000000L
+#define PCIE_LC_TRAINING_CNTL__LC_ALLOW_TX_L1_CONTROL__SHIFT 0x0000001c
+#define PCIE_LC_TRAINING_CNTL__LC_ASPM_L1_NAK_TIMER_SEL_MASK 0x00c00000L
+#define PCIE_LC_TRAINING_CNTL__LC_ASPM_L1_NAK_TIMER_SEL__SHIFT 0x00000016
+#define PCIE_LC_TRAINING_CNTL__LC_AUTONOMOUS_CHANGE_OFF_MASK 0x00020000L
+#define PCIE_LC_TRAINING_CNTL__LC_AUTONOMOUS_CHANGE_OFF__SHIFT 0x00000011
+#define PCIE_LC_TRAINING_CNTL__LC_COMPLIANCE_RECEIVE_MASK 0x00000010L
+#define PCIE_LC_TRAINING_CNTL__LC_COMPLIANCE_RECEIVE__SHIFT 0x00000004
+#define PCIE_LC_TRAINING_CNTL__LC_DISABLE_TRAINING_BIT_ARCH_MASK 0x00002000L
+#define PCIE_LC_TRAINING_CNTL__LC_DISABLE_TRAINING_BIT_ARCH__SHIFT 0x0000000d
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_R_SPEED_MASK 0x01000000L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_R_SPEED__SHIFT 0x00000018
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_TEST_MASK 0x02000000L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_TEST__SHIFT 0x00000019
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_GO_TO_L0S_IF_L1_ARMED_MASK 0x00000800L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_GO_TO_L0S_IF_L1_ARMED__SHIFT 0x0000000b
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_EQ_REQ_TIME_MASK 0xc0000000L
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_EQ_REQ_TIME__SHIFT 0x0000001e
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_WAIT_FOR_SKP_MASK 0x00010000L
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_WAIT_FOR_SKP__SHIFT 0x00000010
+#define PCIE_LC_TRAINING_CNTL__LC_HW_LINK_DIS_EN_MASK 0x00080000L
+#define PCIE_LC_TRAINING_CNTL__LC_HW_LINK_DIS_EN__SHIFT 0x00000013
+#define PCIE_LC_TRAINING_CNTL__LC_INIT_SPD_CHG_WITH_CSR_EN_MASK 0x00001000L
+#define PCIE_LC_TRAINING_CNTL__LC_INIT_SPD_CHG_WITH_CSR_EN__SHIFT 0x0000000c
+#define PCIE_LC_TRAINING_CNTL__LC_L0S_L1_TRAINING_CNTL_EN_MASK 0x00000040L
+#define PCIE_LC_TRAINING_CNTL__LC_L0S_L1_TRAINING_CNTL_EN__SHIFT 0x00000006
+#define PCIE_LC_TRAINING_CNTL__LC_L1_LONG_WAKE_FIX_EN_MASK 0x00000080L
+#define PCIE_LC_TRAINING_CNTL__LC_L1_LONG_WAKE_FIX_EN__SHIFT 0x00000007
+#define PCIE_LC_TRAINING_CNTL__LC_LINK_DIS_BY_HW_MASK 0x00100000L
+#define PCIE_LC_TRAINING_CNTL__LC_LINK_DIS_BY_HW__SHIFT 0x00000014
+#define PCIE_LC_TRAINING_CNTL__LC_LOOK_FOR_MORE_NON_MATCHING_TS1_MASK 0x00000020L
+#define PCIE_LC_TRAINING_CNTL__LC_LOOK_FOR_MORE_NON_MATCHING_TS1__SHIFT 0x00000005
+#define PCIE_LC_TRAINING_CNTL__LC_POWER_STATE_MASK 0x00000700L
+#define PCIE_LC_TRAINING_CNTL__LC_POWER_STATE__SHIFT 0x00000008
+#define PCIE_LC_TRAINING_CNTL__LC_RESET_ASPM_L1_NAK_TIMER_MASK 0x04000000L
+#define PCIE_LC_TRAINING_CNTL__LC_RESET_ASPM_L1_NAK_TIMER__SHIFT 0x0000001a
+#define PCIE_LC_TRAINING_CNTL__LC_SHORT_RCFG_TIMEOUT_MASK 0x08000000L
+#define PCIE_LC_TRAINING_CNTL__LC_SHORT_RCFG_TIMEOUT__SHIFT 0x0000001b
+#define PCIE_LC_TRAINING_CNTL__LC_STATIC_TX_PIPE_COUNT_EN_MASK 0x00200000L
+#define PCIE_LC_TRAINING_CNTL__LC_STATIC_TX_PIPE_COUNT_EN__SHIFT 0x00000015
+#define PCIE_LC_TRAINING_CNTL__LC_TRAINING_CNTL_MASK 0x0000000fL
+#define PCIE_LC_TRAINING_CNTL__LC_TRAINING_CNTL__SHIFT 0x00000000
+#define PCIE_LC_TRAINING_CNTL__LC_UPCONFIGURE_CAP_OFF_MASK 0x00040000L
+#define PCIE_LC_TRAINING_CNTL__LC_UPCONFIGURE_CAP_OFF__SHIFT 0x00000012
+#define PCIE_LC_TRAINING_CNTL__LC_WAIT_FOR_FOM_VALID_AFTER_TRACK_MASK 0x20000000L
+#define PCIE_LC_TRAINING_CNTL__LC_WAIT_FOR_FOM_VALID_AFTER_TRACK__SHIFT 0x0000001d
+#define PCIE_P_BUF_STATUS__P_OVERFLOW_ERR_MASK 0x0000ffffL
+#define PCIE_P_BUF_STATUS__P_OVERFLOW_ERR__SHIFT 0x00000000
+#define PCIE_P_BUF_STATUS__P_UNDERFLOW_ERR_MASK 0xffff0000L
+#define PCIE_P_BUF_STATUS__P_UNDERFLOW_ERR__SHIFT 0x00000010
+#define PCIE_P_CNTL__P_ALWAYS_USE_FAST_TXCLK_MASK 0x00002000L
+#define PCIE_P_CNTL__P_ALWAYS_USE_FAST_TXCLK__SHIFT 0x0000000d
+#define PCIE_P_CNTL__P_BLK_LOCK_MODE_MASK 0x00001000L
+#define PCIE_P_CNTL__P_BLK_LOCK_MODE__SHIFT 0x0000000c
+#define PCIE_P_CNTL__P_ELASTDESKEW_HW_DEBUG_MASK 0x00000008L
+#define PCIE_P_CNTL__P_ELASTDESKEW_HW_DEBUG__SHIFT 0x00000003
+#define PCIE_P_CNTL__P_ELEC_IDLE_MODE_MASK 0x0000c000L
+#define PCIE_P_CNTL__P_ELEC_IDLE_MODE__SHIFT 0x0000000e
+#define PCIE_P_CNTL__P_IGNORE_CRC_ERR_MASK 0x00000010L
+#define PCIE_P_CNTL__P_IGNORE_CRC_ERR__SHIFT 0x00000004
+#define PCIE_P_CNTL__P_IGNORE_EDB_ERR_MASK 0x00000040L
+#define PCIE_P_CNTL__P_IGNORE_EDB_ERR__SHIFT 0x00000006
+#define PCIE_P_CNTL__P_IGNORE_IDL_ERR_MASK 0x00000080L
+#define PCIE_P_CNTL__P_IGNORE_IDL_ERR__SHIFT 0x00000007
+#define PCIE_P_CNTL__P_IGNORE_LEN_ERR_MASK 0x00000020L
+#define PCIE_P_CNTL__P_IGNORE_LEN_ERR__SHIFT 0x00000005
+#define PCIE_P_CNTL__P_IGNORE_TOK_ERR_MASK 0x00000100L
+#define PCIE_P_CNTL__P_IGNORE_TOK_ERR__SHIFT 0x00000008
+#define PCIE_P_CNTL__P_PWRDN_EN_MASK 0x00000001L
+#define PCIE_P_CNTL__P_PWRDN_EN__SHIFT 0x00000000
+#define PCIE_P_CNTL__P_SYMALIGN_HW_DEBUG_MASK 0x00000004L
+#define PCIE_P_CNTL__P_SYMALIGN_HW_DEBUG__SHIFT 0x00000002
+#define PCIE_P_CNTL__P_SYMALIGN_MODE_MASK 0x00000002L
+#define PCIE_P_CNTL__P_SYMALIGN_MODE__SHIFT 0x00000001
+#define PCIE_P_DECODER_STATUS__P_DECODE_ERR_MASK 0x0000ffffL
+#define PCIE_P_DECODER_STATUS__P_DECODE_ERR__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_C_CLK_MASK 0x00000f00L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_C_CLK__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_R_CLK_MASK 0x000000f0L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_R_CLK__SHIFT 0x00000004
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_NS_C_CLK_MASK 0x00f00000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_NS_C_CLK__SHIFT 0x00000014
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_R_CLK_MASK 0x0000f000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_R_CLK__SHIFT 0x0000000c
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_S_C_CLK_MASK 0x000f0000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_S_C_CLK__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK2_MASK 0x0f000000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK2__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK_MASK 0x0000000fL
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_C_CLK_MASK 0x00000f00L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_C_CLK__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_R_CLK_MASK 0x000000f0L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_R_CLK__SHIFT 0x00000004
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_NS_C_CLK_MASK 0x00f00000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_NS_C_CLK__SHIFT 0x00000014
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_R_CLK_MASK 0x0000f000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_R_CLK__SHIFT 0x0000000c
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_S_C_CLK_MASK 0x000f0000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_S_C_CLK__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK2_MASK 0x0f000000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK2__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK_MASK 0x0000000fL
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_TXCLK2__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_TXCLK2__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_TXCLK2__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_TXCLK2__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_TXCLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_TXCLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_TXCLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_TXCLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_TXCLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_TXCLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_TXCLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_TXCLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_COUNT0_MST_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_MST_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_MST_R_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_MST_R_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_NS_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_NS_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_R_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_R_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_S_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_S_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_TXCLK2__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_TXCLK2__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_TXCLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_TXCLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_MST_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_MST_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_MST_R_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_MST_R_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_NS_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_NS_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_R_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_R_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_S_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_S_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_TXCLK2__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_TXCLK2__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_TXCLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_TXCLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_EN_MASK 0x00000001L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_EN__SHIFT 0x00000000
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_RESET_MASK 0x00000004L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_RESET__SHIFT 0x00000002
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_SHADOW_WR_MASK 0x00000002L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_SHADOW_WR__SHIFT 0x00000001
+#define PCIEP_HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define PCIEP_HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define PCIEP_HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define PCIEP_HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define PCIEP_HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define PCIEP_HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define PCIEP_HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define PCIEP_HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define PCIEP_HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define PCIEP_HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define PCIEP_HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define PCIEP_HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define PCIEP_HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define PCIEP_HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define PCIEP_HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define PCIEP_HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define PCIEP_HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define PCIEP_HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define PCIEP_HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define PCIEP_HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define PCIEP_HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define PCIEP_HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define PCIEP_HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define PCIEP_HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define PCIEP_HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define PCIEP_HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define PCIEP_HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define PCIEP_HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define PCIEP_HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define PCIEP_HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define PCIEP_HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define PCIEP_HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define PCIE_P_MISC_STATUS__P_DESKEW_ERR_MASK 0x000000ffL
+#define PCIE_P_MISC_STATUS__P_DESKEW_ERR__SHIFT 0x00000000
+#define PCIE_P_MISC_STATUS__P_SYMUNLOCK_ERR_MASK 0xffff0000L
+#define PCIE_P_MISC_STATUS__P_SYMUNLOCK_ERR__SHIFT 0x00000010
+#define PCIE_PORT_DATA__PCIE_DATA_MASK 0xffffffffL
+#define PCIE_PORT_DATA__PCIE_DATA__SHIFT 0x00000000
+#define PCIE_PORT_INDEX__PCIE_INDEX_MASK 0x000000ffL
+#define PCIE_PORT_INDEX__PCIE_INDEX__SHIFT 0x00000000
+#define PCIEP_PORT_CNTL__CI_SLV_CPL_STATIC_ALLOC_LIMIT_S_MASK 0x00007f00L
+#define PCIEP_PORT_CNTL__CI_SLV_CPL_STATIC_ALLOC_LIMIT_S__SHIFT 0x00000008
+#define PCIEP_PORT_CNTL__CI_SNOOP_OVERRIDE_MASK 0x00000002L
+#define PCIEP_PORT_CNTL__CI_SNOOP_OVERRIDE__SHIFT 0x00000001
+#define PCIEP_PORT_CNTL__HOTPLUG_MSG_EN_MASK 0x00000004L
+#define PCIEP_PORT_CNTL__HOTPLUG_MSG_EN__SHIFT 0x00000002
+#define PCIEP_PORT_CNTL__NATIVE_PME_EN_MASK 0x00000008L
+#define PCIEP_PORT_CNTL__NATIVE_PME_EN__SHIFT 0x00000003
+#define PCIEP_PORT_CNTL__PMI_BM_DIS_MASK 0x00000020L
+#define PCIEP_PORT_CNTL__PMI_BM_DIS__SHIFT 0x00000005
+#define PCIEP_PORT_CNTL__PWR_FAULT_EN_MASK 0x00000010L
+#define PCIEP_PORT_CNTL__PWR_FAULT_EN__SHIFT 0x00000004
+#define PCIEP_PORT_CNTL__SEQNUM_DEBUG_MODE_MASK 0x00000040L
+#define PCIEP_PORT_CNTL__SEQNUM_DEBUG_MODE__SHIFT 0x00000006
+#define PCIEP_PORT_CNTL__SLV_PORT_REQ_EN_MASK 0x00000001L
+#define PCIEP_PORT_CNTL__SLV_PORT_REQ_EN__SHIFT 0x00000000
+#define PCIE_P_PORT_LANE_STATUS__PHY_LINK_WIDTH_MASK 0x0000007eL
+#define PCIE_P_PORT_LANE_STATUS__PHY_LINK_WIDTH__SHIFT 0x00000001
+#define PCIE_P_PORT_LANE_STATUS__PORT_LANE_REVERSAL_MASK 0x00000001L
+#define PCIE_P_PORT_LANE_STATUS__PORT_LANE_REVERSAL__SHIFT 0x00000000
+#define PCIE_PRBS_CLR__PRBS_CHECKER_DEBUG_BUS_SELECT_MASK 0x000f0000L
+#define PCIE_PRBS_CLR__PRBS_CHECKER_DEBUG_BUS_SELECT__SHIFT 0x00000010
+#define PCIE_PRBS_CLR__PRBS_CLR_MASK 0x0000ffffL
+#define PCIE_PRBS_CLR__PRBS_CLR__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_0__PRBS_ERRCNT_0_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_0__PRBS_ERRCNT_0__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_10__PRBS_ERRCNT_10_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_10__PRBS_ERRCNT_10__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_11__PRBS_ERRCNT_11_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_11__PRBS_ERRCNT_11__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_12__PRBS_ERRCNT_12_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_12__PRBS_ERRCNT_12__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_13__PRBS_ERRCNT_13_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_13__PRBS_ERRCNT_13__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_14__PRBS_ERRCNT_14_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_14__PRBS_ERRCNT_14__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_15__PRBS_ERRCNT_15_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_15__PRBS_ERRCNT_15__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_1__PRBS_ERRCNT_1_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_1__PRBS_ERRCNT_1__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_2__PRBS_ERRCNT_2_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_2__PRBS_ERRCNT_2__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_3__PRBS_ERRCNT_3_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_3__PRBS_ERRCNT_3__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_4__PRBS_ERRCNT_4_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_4__PRBS_ERRCNT_4__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_5__PRBS_ERRCNT_5_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_5__PRBS_ERRCNT_5__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_6__PRBS_ERRCNT_6_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_6__PRBS_ERRCNT_6__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_7__PRBS_ERRCNT_7_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_7__PRBS_ERRCNT_7__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_8__PRBS_ERRCNT_8_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_8__PRBS_ERRCNT_8__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_9__PRBS_ERRCNT_9_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_9__PRBS_ERRCNT_9__SHIFT 0x00000000
+#define PCIE_PRBS_FREERUN__PRBS_FREERUN_MASK 0x0000ffffL
+#define PCIE_PRBS_FREERUN__PRBS_FREERUN__SHIFT 0x00000000
+#define PCIE_PRBS_HI_BITCNT__PRBS_HI_BITCNT_MASK 0x000000ffL
+#define PCIE_PRBS_HI_BITCNT__PRBS_HI_BITCNT__SHIFT 0x00000000
+#define PCIE_PRBS_LO_BITCNT__PRBS_LO_BITCNT_MASK 0xffffffffL
+#define PCIE_PRBS_LO_BITCNT__PRBS_LO_BITCNT__SHIFT 0x00000000
+#define PCIE_PRBS_MISC__PRBS_8BIT_SEL_MASK 0x00000010L
+#define PCIE_PRBS_MISC__PRBS_8BIT_SEL__SHIFT 0x00000004
+#define PCIE_PRBS_MISC__PRBS_CHK_ERR_MASK_MASK 0xffff0000L
+#define PCIE_PRBS_MISC__PRBS_CHK_ERR_MASK__SHIFT 0x00000010
+#define PCIE_PRBS_MISC__PRBS_COMMA_NUM_MASK 0x00000060L
+#define PCIE_PRBS_MISC__PRBS_COMMA_NUM__SHIFT 0x00000005
+#define PCIE_PRBS_MISC__PRBS_DATA_RATE_MASK 0x0000c000L
+#define PCIE_PRBS_MISC__PRBS_DATA_RATE__SHIFT 0x0000000e
+#define PCIE_PRBS_MISC__PRBS_EN_MASK 0x00000001L
+#define PCIE_PRBS_MISC__PRBS_EN__SHIFT 0x00000000
+#define PCIE_PRBS_MISC__PRBS_LOCK_CNT_MASK 0x00000f80L
+#define PCIE_PRBS_MISC__PRBS_LOCK_CNT__SHIFT 0x00000007
+#define PCIE_PRBS_MISC__PRBS_TEST_MODE_MASK 0x00000006L
+#define PCIE_PRBS_MISC__PRBS_TEST_MODE__SHIFT 0x00000001
+#define PCIE_PRBS_MISC__PRBS_USER_PATTERN_TOGGLE_MASK 0x00000008L
+#define PCIE_PRBS_MISC__PRBS_USER_PATTERN_TOGGLE__SHIFT 0x00000003
+#define PCIE_PRBS_STATUS1__PRBS_ERRSTAT_MASK 0x0000ffffL
+#define PCIE_PRBS_STATUS1__PRBS_ERRSTAT__SHIFT 0x00000000
+#define PCIE_PRBS_STATUS1__PRBS_LOCKED_MASK 0xffff0000L
+#define PCIE_PRBS_STATUS1__PRBS_LOCKED__SHIFT 0x00000010
+#define PCIE_PRBS_STATUS2__PRBS_BITCNT_DONE_MASK 0x0000ffffL
+#define PCIE_PRBS_STATUS2__PRBS_BITCNT_DONE__SHIFT 0x00000000
+#define PCIE_PRBS_USER_PATTERN__PRBS_USER_PATTERN_MASK 0x3fffffffL
+#define PCIE_PRBS_USER_PATTERN__PRBS_USER_PATTERN__SHIFT 0x00000000
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MAX_MASK 0x0000ff00L
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MAX__SHIFT 0x00000008
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MIN_MASK 0x000000ffL
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MIN__SHIFT 0x00000000
+#define PCIEP_RESERVED__PCIEP_RESERVED_MASK 0xffffffffL
+#define PCIEP_RESERVED__PCIEP_RESERVED__SHIFT 0x00000000
+#define PCIEP_SCRATCH__PCIEP_SCRATCH_MASK 0xffffffffL
+#define PCIEP_SCRATCH__PCIEP_SCRATCH__SHIFT 0x00000000
+#define PCIEP_STRAP_LC__STRAP_AUTO_RC_SPEED_NEGOTIATION_DIS_MASK 0x00008000L
+#define PCIEP_STRAP_LC__STRAP_AUTO_RC_SPEED_NEGOTIATION_DIS__SHIFT 0x0000000f
+#define PCIEP_STRAP_LC__STRAP_BYPASS_RCVR_DET_MASK 0x00000800L
+#define PCIEP_STRAP_LC__STRAP_BYPASS_RCVR_DET__SHIFT 0x0000000b
+#define PCIEP_STRAP_LC__STRAP_COMPLIANCE_DIS_MASK 0x00001000L
+#define PCIEP_STRAP_LC__STRAP_COMPLIANCE_DIS__SHIFT 0x0000000c
+#define PCIEP_STRAP_LC__STRAP_FORCE_COMPLIANCE_MASK 0x00002000L
+#define PCIEP_STRAP_LC__STRAP_FORCE_COMPLIANCE__SHIFT 0x0000000d
+#define PCIEP_STRAP_LC__STRAP_FTS_yTSx_COUNT_MASK 0x00000003L
+#define PCIEP_STRAP_LC__STRAP_FTS_yTSx_COUNT__SHIFT 0x00000000
+#define PCIEP_STRAP_LC__STRAP_LANE_NEGOTIATION_MASK 0x00070000L
+#define PCIEP_STRAP_LC__STRAP_LANE_NEGOTIATION__SHIFT 0x00000010
+#define PCIEP_STRAP_LC__STRAP_LONG_yTSx_COUNT_MASK 0x0000000cL
+#define PCIEP_STRAP_LC__STRAP_LONG_yTSx_COUNT__SHIFT 0x00000002
+#define PCIEP_STRAP_LC__STRAP_MED_yTSx_COUNT_MASK 0x00000030L
+#define PCIEP_STRAP_LC__STRAP_MED_yTSx_COUNT__SHIFT 0x00000004
+#define PCIEP_STRAP_LC__STRAP_REVERSE_LC_LANES_MASK 0x00004000L
+#define PCIEP_STRAP_LC__STRAP_REVERSE_LC_LANES__SHIFT 0x0000000e
+#define PCIEP_STRAP_LC__STRAP_SHORT_yTSx_COUNT_MASK 0x000000c0L
+#define PCIEP_STRAP_LC__STRAP_SHORT_yTSx_COUNT__SHIFT 0x00000006
+#define PCIEP_STRAP_LC__STRAP_SKIP_INTERVAL_MASK 0x00000700L
+#define PCIEP_STRAP_LC__STRAP_SKIP_INTERVAL__SHIFT 0x00000008
+#define PCIEP_STRAP_MISC__STRAP_E2E_PREFIX_EN_MASK 0x00000002L
+#define PCIEP_STRAP_MISC__STRAP_E2E_PREFIX_EN__SHIFT 0x00000001
+#define PCIEP_STRAP_MISC__STRAP_EXTENDED_FMT_SUPPORTED_MASK 0x00000004L
+#define PCIEP_STRAP_MISC__STRAP_EXTENDED_FMT_SUPPORTED__SHIFT 0x00000002
+#define PCIEP_STRAP_MISC__STRAP_OBFF_SUPPORTED_MASK 0x00000018L
+#define PCIEP_STRAP_MISC__STRAP_OBFF_SUPPORTED__SHIFT 0x00000003
+#define PCIEP_STRAP_MISC__STRAP_REVERSE_LANES_MASK 0x00000001L
+#define PCIEP_STRAP_MISC__STRAP_REVERSE_LANES__SHIFT 0x00000000
+#define PCIE_RESERVED__PCIE_RESERVED_MASK 0xffffffffL
+#define PCIE_RESERVED__PCIE_RESERVED__SHIFT 0x00000000
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_ATSTRANSREQ_UR_MASK 0x00000008L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_ATSTRANSREQ_UR__SHIFT 0x00000003
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVALIDPASID_UR_MASK 0x00000001L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVALIDPASID_UR__SHIFT 0x00000000
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVCPL_UR_MASK 0x00000020L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVCPL_UR__SHIFT 0x00000005
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_PAGEREQMSG_UR_MASK 0x00000010L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_PAGEREQMSG_UR__SHIFT 0x00000004
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMRD_UR_MASK 0x00000002L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMRD_UR__SHIFT 0x00000001
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMWR_UR_MASK 0x00000004L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMWR_UR__SHIFT 0x00000002
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVCPLPASID_UR_MASK 0x00000010L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVCPLPASID_UR__SHIFT 0x00000004
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVREQ_UR_MASK 0x00000008L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVREQ_UR__SHIFT 0x00000003
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_PRGRESPMSG_UR_MASK 0x00000004L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_PRGRESPMSG_UR__SHIFT 0x00000002
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMRDPASID_UR_MASK 0x00000001L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMRDPASID_UR__SHIFT 0x00000000
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMWRPASID_UR_MASK 0x00000002L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMWRPASID_UR__SHIFT 0x00000001
+#define PCIE_RX_CNTL__RX_FC_INIT_FROM_REG_MASK 0x00008000L
+#define PCIE_RX_CNTL__RX_FC_INIT_FROM_REG__SHIFT 0x0000000f
+#define PCIE_RX_CNTL__RX_GEN_ONE_NAK_MASK 0x00004000L
+#define PCIE_RX_CNTL__RX_GEN_ONE_NAK__SHIFT 0x0000000e
+#define PCIE_RX_CNTL__RX_IGNORE_AT_ERR_MASK 0x00001000L
+#define PCIE_RX_CNTL__RX_IGNORE_AT_ERR__SHIFT 0x0000000c
+#define PCIE_RX_CNTL__RX_IGNORE_BE_ERR_MASK 0x00000002L
+#define PCIE_RX_CNTL__RX_IGNORE_BE_ERR__SHIFT 0x00000001
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_ERR_MASK 0x00000010L
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_ERR__SHIFT 0x00000004
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_UR_MASK 0x00000400L
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_UR__SHIFT 0x0000000a
+#define PCIE_RX_CNTL__RX_IGNORE_CPL_ERR_MASK 0x00000020L
+#define PCIE_RX_CNTL__RX_IGNORE_CPL_ERR__SHIFT 0x00000005
+#define PCIE_RX_CNTL__RX_IGNORE_CPLPREFIX_ERR_MASK 0x00800000L
+#define PCIE_RX_CNTL__RX_IGNORE_CPLPREFIX_ERR__SHIFT 0x00000017
+#define PCIE_RX_CNTL__RX_IGNORE_CRC_ERR_MASK 0x00000008L
+#define PCIE_RX_CNTL__RX_IGNORE_CRC_ERR__SHIFT 0x00000003
+#define PCIE_RX_CNTL__RX_IGNORE_EP_ERR_MASK 0x00000040L
+#define PCIE_RX_CNTL__RX_IGNORE_EP_ERR__SHIFT 0x00000006
+#define PCIE_RX_CNTL__RX_IGNORE_INVALIDPASID_ERR_MASK 0x01000000L
+#define PCIE_RX_CNTL__RX_IGNORE_INVALIDPASID_ERR__SHIFT 0x00000018
+#define PCIE_RX_CNTL__RX_IGNORE_IO_ERR_MASK 0x00000001L
+#define PCIE_RX_CNTL__RX_IGNORE_IO_ERR__SHIFT 0x00000000
+#define PCIE_RX_CNTL__RX_IGNORE_IO_UR_MASK 0x00000800L
+#define PCIE_RX_CNTL__RX_IGNORE_IO_UR__SHIFT 0x0000000b
+#define PCIE_RX_CNTL__RX_IGNORE_LEN_MISMATCH_ERR_MASK 0x00000080L
+#define PCIE_RX_CNTL__RX_IGNORE_LEN_MISMATCH_ERR__SHIFT 0x00000007
+#define PCIE_RX_CNTL__RX_IGNORE_MAX_PAYLOAD_ERR_MASK 0x00000100L
+#define PCIE_RX_CNTL__RX_IGNORE_MAX_PAYLOAD_ERR__SHIFT 0x00000008
+#define PCIE_RX_CNTL__RX_IGNORE_MAXPREFIX_ERR_MASK 0x00400000L
+#define PCIE_RX_CNTL__RX_IGNORE_MAXPREFIX_ERR__SHIFT 0x00000016
+#define PCIE_RX_CNTL__RX_IGNORE_MSG_ERR_MASK 0x00000004L
+#define PCIE_RX_CNTL__RX_IGNORE_MSG_ERR__SHIFT 0x00000002
+#define PCIE_RX_CNTL__RX_IGNORE_NOT_PASID_UR_MASK 0x02000000L
+#define PCIE_RX_CNTL__RX_IGNORE_NOT_PASID_UR__SHIFT 0x00000019
+#define PCIE_RX_CNTL__RX_IGNORE_SHORTPREFIX_ERR_MASK 0x00200000L
+#define PCIE_RX_CNTL__RX_IGNORE_SHORTPREFIX_ERR__SHIFT 0x00000015
+#define PCIE_RX_CNTL__RX_IGNORE_TC_ERR_MASK 0x00000200L
+#define PCIE_RX_CNTL__RX_IGNORE_TC_ERR__SHIFT 0x00000009
+#define PCIE_RX_CNTL__RX_NAK_IF_FIFO_FULL_MASK 0x00002000L
+#define PCIE_RX_CNTL__RX_NAK_IF_FIFO_FULL__SHIFT 0x0000000d
+#define PCIE_RX_CNTL__RX_PCIE_CPL_TIMEOUT_DIS_MASK 0x00100000L
+#define PCIE_RX_CNTL__RX_PCIE_CPL_TIMEOUT_DIS__SHIFT 0x00000014
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MASK 0x00070000L
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MODE_MASK 0x00080000L
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MODE__SHIFT 0x00000013
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLH__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPH__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PH__SHIFT 0x00000010
+#define PCIE_RX_EXPECTED_SEQNUM__RX_EXPECTED_SEQNUM_MASK 0x00000fffL
+#define PCIE_RX_EXPECTED_SEQNUM__RX_EXPECTED_SEQNUM__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP0__RX_LAST_TLP0_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP0__RX_LAST_TLP0__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP1__RX_LAST_TLP1_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP1__RX_LAST_TLP1__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP2__RX_LAST_TLP2_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP2__RX_LAST_TLP2__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP3__RX_LAST_TLP3_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP3__RX_LAST_TLP3__SHIFT 0x00000000
+#define PCIE_RX_NUM_NAK_GENERATED__RX_NUM_NAK_GENERATED_MASK 0xffffffffL
+#define PCIE_RX_NUM_NAK_GENERATED__RX_NUM_NAK_GENERATED__SHIFT 0x00000000
+#define PCIE_RX_NUM_NAK__RX_NUM_NAK_MASK 0xffffffffL
+#define PCIE_RX_NUM_NAK__RX_NUM_NAK__SHIFT 0x00000000
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_DATA_MASK 0x00ffffffL
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_DATA__SHIFT 0x00000000
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_STATUS_MASK 0x01000000L
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_STATUS__SHIFT 0x00000018
+#define PCIE_SCRATCH__PCIE_SCRATCH_MASK 0xffffffffL
+#define PCIE_SCRATCH__PCIE_SCRATCH__SHIFT 0x00000000
+#define PCIE_STRAP_F0__STRAP_F0_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F0__STRAP_F0_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F0__STRAP_F0_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F0__STRAP_F0_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F0__STRAP_F0_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F0__STRAP_F0_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F0__STRAP_F0_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F0__STRAP_F0_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F0__STRAP_F0_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F0__STRAP_F0_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F0__STRAP_F0_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F0__STRAP_F0_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F0__STRAP_F0_EN_MASK 0x00000001L
+#define PCIE_STRAP_F0__STRAP_F0_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F0__STRAP_F0_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F0__STRAP_F0_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F0__STRAP_F0_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F0__STRAP_F0_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F0__STRAP_F0_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F0__STRAP_F0_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F0__STRAP_F0_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F0__STRAP_F0_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F0__STRAP_F0_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F0__STRAP_F0_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F0__STRAP_F0_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F0__STRAP_F0_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F1__STRAP_F1_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F1__STRAP_F1_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F1__STRAP_F1_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F1__STRAP_F1_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F1__STRAP_F1_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F1__STRAP_F1_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F1__STRAP_F1_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F1__STRAP_F1_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F1__STRAP_F1_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F1__STRAP_F1_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F1__STRAP_F1_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F1__STRAP_F1_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F1__STRAP_F1_EN_MASK 0x00000001L
+#define PCIE_STRAP_F1__STRAP_F1_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F1__STRAP_F1_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F1__STRAP_F1_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F1__STRAP_F1_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F1__STRAP_F1_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F1__STRAP_F1_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F1__STRAP_F1_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F1__STRAP_F1_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F1__STRAP_F1_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F1__STRAP_F1_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F1__STRAP_F1_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F1__STRAP_F1_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F1__STRAP_F1_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F2__STRAP_F2_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F2__STRAP_F2_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F2__STRAP_F2_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F2__STRAP_F2_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F2__STRAP_F2_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F2__STRAP_F2_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F2__STRAP_F2_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F2__STRAP_F2_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F2__STRAP_F2_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F2__STRAP_F2_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F2__STRAP_F2_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F2__STRAP_F2_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F2__STRAP_F2_EN_MASK 0x00000001L
+#define PCIE_STRAP_F2__STRAP_F2_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F2__STRAP_F2_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F2__STRAP_F2_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F2__STRAP_F2_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F2__STRAP_F2_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F2__STRAP_F2_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F2__STRAP_F2_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F2__STRAP_F2_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F2__STRAP_F2_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F2__STRAP_F2_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F2__STRAP_F2_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F2__STRAP_F2_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F2__STRAP_F2_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F3__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F3__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F4__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F4__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F5__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F5__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F6__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F6__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F7__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F7__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_DBG_I2C_EN_MASK 0x00000080L
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_DBG_I2C_EN__SHIFT 0x00000007
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_I2C_SLV_ADR_MASK 0x0000007fL
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_I2C_SLV_ADR__SHIFT 0x00000000
+#define PCIE_STRAP_MISC2__STRAP_GEN2_COMPLIANCE_MASK 0x00000002L
+#define PCIE_STRAP_MISC2__STRAP_GEN2_COMPLIANCE__SHIFT 0x00000001
+#define PCIE_STRAP_MISC2__STRAP_GEN3_COMPLIANCE_MASK 0x00000008L
+#define PCIE_STRAP_MISC2__STRAP_GEN3_COMPLIANCE__SHIFT 0x00000003
+#define PCIE_STRAP_MISC2__STRAP_MSTCPL_TIMEOUT_EN_MASK 0x00000004L
+#define PCIE_STRAP_MISC2__STRAP_MSTCPL_TIMEOUT_EN__SHIFT 0x00000002
+#define PCIE_STRAP_MISC__STRAP_CLK_PM_EN_MASK 0x01000000L
+#define PCIE_STRAP_MISC__STRAP_CLK_PM_EN__SHIFT 0x00000018
+#define PCIE_STRAP_MISC__STRAP_ECN1P1_EN_MASK 0x02000000L
+#define PCIE_STRAP_MISC__STRAP_ECN1P1_EN__SHIFT 0x00000019
+#define PCIE_STRAP_MISC__STRAP_EXT_VC_COUNT_MASK 0x04000000L
+#define PCIE_STRAP_MISC__STRAP_EXT_VC_COUNT__SHIFT 0x0000001a
+#define PCIE_STRAP_MISC__STRAP_FLR_EN_MASK 0x40000000L
+#define PCIE_STRAP_MISC__STRAP_FLR_EN__SHIFT 0x0000001e
+#define PCIE_STRAP_MISC__STRAP_LINK_CONFIG_MASK 0x0000000fL
+#define PCIE_STRAP_MISC__STRAP_LINK_CONFIG__SHIFT 0x00000000
+#define PCIE_STRAP_MISC__STRAP_MAX_PASID_WIDTH_MASK 0x00001f00L
+#define PCIE_STRAP_MISC__STRAP_MAX_PASID_WIDTH__SHIFT 0x00000008
+#define PCIE_STRAP_MISC__STRAP_MST_ADR64_EN_MASK 0x20000000L
+#define PCIE_STRAP_MISC__STRAP_MST_ADR64_EN__SHIFT 0x0000001d
+#define PCIE_STRAP_MISC__STRAP_PASID_EXE_PERMISSION_SUPPORTED_MASK 0x00002000L
+#define PCIE_STRAP_MISC__STRAP_PASID_EXE_PERMISSION_SUPPORTED__SHIFT 0x0000000d
+#define PCIE_STRAP_MISC__STRAP_PASID_GLOBAL_INVALIDATE_SUPPORTED_MASK 0x00008000L
+#define PCIE_STRAP_MISC__STRAP_PASID_GLOBAL_INVALIDATE_SUPPORTED__SHIFT 0x0000000f
+#define PCIE_STRAP_MISC__STRAP_PASID_PRIV_MODE_SUPPORTED_MASK 0x00004000L
+#define PCIE_STRAP_MISC__STRAP_PASID_PRIV_MODE_SUPPORTED__SHIFT 0x0000000e
+#define PCIE_STRAP_MISC__STRAP_REVERSE_ALL_MASK 0x10000000L
+#define PCIE_STRAP_MISC__STRAP_REVERSE_ALL__SHIFT 0x0000001c
+#define PCIE_STRAP_PI__STRAP_QUICKSIM_START_MASK 0x00000001L
+#define PCIE_STRAP_PI__STRAP_QUICKSIM_START__SHIFT 0x00000000
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_MODE_MASK 0x20000000L
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_MODE__SHIFT 0x0000001d
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_PATTERN_MASK 0x10000000L
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_PATTERN__SHIFT 0x0000001c
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_MASK 0x00000fffL
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_OVERWRITE_MASK 0x00001000L
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_OVERWRITE__SHIFT 0x0000000c
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT__SHIFT 0x00000000
+#define PCIE_TX_CNTL__TX_CLEAR_EXTRA_PM_REQS_MASK 0x00400000L
+#define PCIE_TX_CNTL__TX_CLEAR_EXTRA_PM_REQS__SHIFT 0x00000016
+#define PCIE_TX_CNTL__TX_CPL_PASS_P_MASK 0x00100000L
+#define PCIE_TX_CNTL__TX_CPL_PASS_P__SHIFT 0x00000014
+#define PCIE_TX_CNTL__TX_FC_UPDATE_TIMEOUT_DIS_MASK 0x00800000L
+#define PCIE_TX_CNTL__TX_FC_UPDATE_TIMEOUT_DIS__SHIFT 0x00000017
+#define PCIE_TX_CNTL__TX_FLUSH_TLP_DIS_MASK 0x00008000L
+#define PCIE_TX_CNTL__TX_FLUSH_TLP_DIS__SHIFT 0x0000000f
+#define PCIE_TX_CNTL__TX_NP_PASS_P_MASK 0x00200000L
+#define PCIE_TX_CNTL__TX_NP_PASS_P__SHIFT 0x00000015
+#define PCIE_TX_CNTL__TX_PACK_PACKET_DIS_MASK 0x00004000L
+#define PCIE_TX_CNTL__TX_PACK_PACKET_DIS__SHIFT 0x0000000e
+#define PCIE_TX_CNTL__TX_RO_OVERRIDE_MASK 0x00003000L
+#define PCIE_TX_CNTL__TX_RO_OVERRIDE__SHIFT 0x0000000c
+#define PCIE_TX_CNTL__TX_SNR_OVERRIDE_MASK 0x00000c00L
+#define PCIE_TX_CNTL__TX_SNR_OVERRIDE__SHIFT 0x0000000a
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC0_MASK 0x00000700L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC0__SHIFT 0x00000008
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC1_MASK 0x07000000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC1__SHIFT 0x00000018
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC0_MASK 0x00000070L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC0__SHIFT 0x00000004
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC1_MASK 0x00700000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC1__SHIFT 0x00000014
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC0_MASK 0x00000007L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC0__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC1_MASK 0x00070000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC1__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLD_MASK 0x00100000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLD__SHIFT 0x00000014
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLH_MASK 0x00200000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLH__SHIFT 0x00000015
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPD_MASK 0x00040000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPD__SHIFT 0x00000012
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPH_MASK 0x00080000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPH__SHIFT 0x00000013
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PD_MASK 0x00010000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PD__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PH_MASK 0x00020000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PH__SHIFT 0x00000011
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLD_MASK 0x00000010L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLD__SHIFT 0x00000004
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLH_MASK 0x00000020L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLH__SHIFT 0x00000005
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPD_MASK 0x00000004L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPD__SHIFT 0x00000002
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPH_MASK 0x00000008L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPH__SHIFT 0x00000003
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PD_MASK 0x00000001L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PH_MASK 0x00000002L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PH__SHIFT 0x00000001
+#define PCIE_TX_LAST_TLP0__TX_LAST_TLP0_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP0__TX_LAST_TLP0__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP1__TX_LAST_TLP1_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP1__TX_LAST_TLP1__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP2__TX_LAST_TLP2_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP2__TX_LAST_TLP2__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP3__TX_LAST_TLP3_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP3__TX_LAST_TLP3__SHIFT 0x00000000
+#define PCIE_TX_REPLAY__TX_REPLAY_NUM_MASK 0x00000007L
+#define PCIE_TX_REPLAY__TX_REPLAY_NUM__SHIFT 0x00000000
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_MASK 0xffff0000L
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_OVERWRITE_MASK 0x00008000L
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_OVERWRITE__SHIFT 0x0000000f
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER__SHIFT 0x00000010
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_BUS_MASK 0x0000ff00L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_BUS__SHIFT 0x00000008
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_DEVICE_MASK 0x000000f8L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_DEVICE__SHIFT 0x00000003
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_FUNCTION_MASK 0x00000007L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_FUNCTION__SHIFT 0x00000000
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_EN_MASK 0x80000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_EN__SHIFT 0x0000001f
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_MASK 0x3f000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP__SHIFT 0x00000018
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_VC1_EN_MASK 0x40000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_VC1_EN__SHIFT 0x0000001e
+#define PCIE_TX_SEQ__TX_ACKD_SEQ_MASK 0x0fff0000L
+#define PCIE_TX_SEQ__TX_ACKD_SEQ__SHIFT 0x00000010
+#define PCIE_TX_SEQ__TX_NEXT_TRANSMIT_SEQ_MASK 0x00000fffL
+#define PCIE_TX_SEQ__TX_NEXT_TRANSMIT_SEQ__SHIFT 0x00000000
+#define PCIE_TX_VENDOR_SPECIFIC__TX_VENDOR_DATA_MASK 0x00ffffffL
+#define PCIE_TX_VENDOR_SPECIFIC__TX_VENDOR_DATA__SHIFT 0x00000000
+#define PCIE_WPR_CNTL__WPR_RESET_COR_EN_MASK 0x00000008L
+#define PCIE_WPR_CNTL__WPR_RESET_COR_EN__SHIFT 0x00000003
+#define PCIE_WPR_CNTL__WPR_RESET_HOT_RST_EN_MASK 0x00000001L
+#define PCIE_WPR_CNTL__WPR_RESET_HOT_RST_EN__SHIFT 0x00000000
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DIS_EN_MASK 0x00000004L
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DIS_EN__SHIFT 0x00000002
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DWN_EN_MASK 0x00000002L
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DWN_EN__SHIFT 0x00000001
+#define PCIE_WPR_CNTL__WPR_RESET_PHY_EN_MASK 0x00000040L
+#define PCIE_WPR_CNTL__WPR_RESET_PHY_EN__SHIFT 0x00000006
+#define PCIE_WPR_CNTL__WPR_RESET_REG_EN_MASK 0x00000010L
+#define PCIE_WPR_CNTL__WPR_RESET_REG_EN__SHIFT 0x00000004
+#define PCIE_WPR_CNTL__WPR_RESET_STY_EN_MASK 0x00000020L
+#define PCIE_WPR_CNTL__WPR_RESET_STY_EN__SHIFT 0x00000005
+#define PEER0_FB_OFFSET_HI__PEER0_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER0_FB_OFFSET_HI__PEER0_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER0_FB_OFFSET_LO__PEER0_FB_EN_MASK 0x80000000L
+#define PEER0_FB_OFFSET_LO__PEER0_FB_EN__SHIFT 0x0000001f
+#define PEER0_FB_OFFSET_LO__PEER0_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER0_FB_OFFSET_LO__PEER0_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER1_FB_OFFSET_HI__PEER1_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER1_FB_OFFSET_HI__PEER1_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER1_FB_OFFSET_LO__PEER1_FB_EN_MASK 0x80000000L
+#define PEER1_FB_OFFSET_LO__PEER1_FB_EN__SHIFT 0x0000001f
+#define PEER1_FB_OFFSET_LO__PEER1_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER1_FB_OFFSET_LO__PEER1_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER2_FB_OFFSET_HI__PEER2_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER2_FB_OFFSET_HI__PEER2_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER2_FB_OFFSET_LO__PEER2_FB_EN_MASK 0x80000000L
+#define PEER2_FB_OFFSET_LO__PEER2_FB_EN__SHIFT 0x0000001f
+#define PEER2_FB_OFFSET_LO__PEER2_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER2_FB_OFFSET_LO__PEER2_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER3_FB_OFFSET_HI__PEER3_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER3_FB_OFFSET_HI__PEER3_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER3_FB_OFFSET_LO__PEER3_FB_EN_MASK 0x80000000L
+#define PEER3_FB_OFFSET_LO__PEER3_FB_EN__SHIFT 0x0000001f
+#define PEER3_FB_OFFSET_LO__PEER3_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER3_FB_OFFSET_LO__PEER3_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER_REG_RANGE0__END_ADDR_MASK 0xffff0000L
+#define PEER_REG_RANGE0__END_ADDR__SHIFT 0x00000010
+#define PEER_REG_RANGE0__START_ADDR_MASK 0x0000ffffL
+#define PEER_REG_RANGE0__START_ADDR__SHIFT 0x00000000
+#define PEER_REG_RANGE1__END_ADDR_MASK 0xffff0000L
+#define PEER_REG_RANGE1__END_ADDR__SHIFT 0x00000010
+#define PEER_REG_RANGE1__START_ADDR_MASK 0x0000ffffL
+#define PEER_REG_RANGE1__START_ADDR__SHIFT 0x00000000
+#define SLAVE_HANG_ERROR__AUDIO_HANG_ERROR_MASK 0x00000010L
+#define SLAVE_HANG_ERROR__AUDIO_HANG_ERROR__SHIFT 0x00000004
+#define SLAVE_HANG_ERROR__CEC_HANG_ERROR_MASK 0x00000020L
+#define SLAVE_HANG_ERROR__CEC_HANG_ERROR__SHIFT 0x00000005
+#define SLAVE_HANG_ERROR__HDP_HANG_ERROR_MASK 0x00000002L
+#define SLAVE_HANG_ERROR__HDP_HANG_ERROR__SHIFT 0x00000001
+#define SLAVE_HANG_ERROR__ROM_HANG_ERROR_MASK 0x00000008L
+#define SLAVE_HANG_ERROR__ROM_HANG_ERROR__SHIFT 0x00000003
+#define SLAVE_HANG_ERROR__SRBM_HANG_ERROR_MASK 0x00000001L
+#define SLAVE_HANG_ERROR__SRBM_HANG_ERROR__SHIFT 0x00000000
+#define SLAVE_HANG_ERROR__VGA_HANG_ERROR_MASK 0x00000004L
+#define SLAVE_HANG_ERROR__VGA_HANG_ERROR__SHIFT 0x00000002
+#define SLAVE_HANG_PROTECTION_CNTL__HANG_PROTECTION_TIMER_SEL_MASK 0x0000000eL
+#define SLAVE_HANG_PROTECTION_CNTL__HANG_PROTECTION_TIMER_SEL__SHIFT 0x00000001
+#define SLAVE_REQ_CREDIT_CNTL__BIF_AZ_REQ_CREDIT_MASK 0x00100000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_AZ_REQ_CREDIT__SHIFT 0x00000014
+#define SLAVE_REQ_CREDIT_CNTL__BIF_HDP_REQ_CREDIT_MASK 0x00007c00L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_HDP_REQ_CREDIT__SHIFT 0x0000000a
+#define SLAVE_REQ_CREDIT_CNTL__BIF_ROM_REQ_CREDIT_MASK 0x00008000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_ROM_REQ_CREDIT__SHIFT 0x0000000f
+#define SLAVE_REQ_CREDIT_CNTL__BIF_SRBM_REQ_CREDIT_MASK 0x0000001fL
+#define SLAVE_REQ_CREDIT_CNTL__BIF_SRBM_REQ_CREDIT__SHIFT 0x00000000
+#define SLAVE_REQ_CREDIT_CNTL__BIF_VGA_REQ_CREDIT_MASK 0x000001e0L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_VGA_REQ_CREDIT__SHIFT 0x00000005
+#define SLAVE_REQ_CREDIT_CNTL__BIF_XDMA_REQ_CREDIT_MASK 0x7e000000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_XDMA_REQ_CREDIT__SHIFT 0x00000019
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_A_MASK 0x00000001L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_A__SHIFT 0x00000000
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_CNTL_EN_MASK 0x00001000L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_CNTL_EN__SHIFT 0x0000000c
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_MODE_MASK 0x00000004L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_MODE__SHIFT 0x00000002
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SCHMEN_MASK 0x00000800L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SCHMEN__SHIFT 0x0000000b
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SEL_MASK 0x00000002L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SEL__SHIFT 0x00000001
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SLEWN_MASK 0x00000200L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SLEWN__SHIFT 0x00000009
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN0_MASK 0x00000020L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN0__SHIFT 0x00000005
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN1_MASK 0x00000040L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN1__SHIFT 0x00000006
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN2_MASK 0x00000080L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN2__SHIFT 0x00000007
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN3_MASK 0x00000100L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN3__SHIFT 0x00000008
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SPARE_MASK 0x00000018L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SPARE__SHIFT 0x00000003
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_WAKE_MASK 0x00000400L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_WAKE__SHIFT 0x0000000a
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_A_MASK 0x00000001L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_A__SHIFT 0x00000000
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_CNTL_EN_MASK 0x00001000L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_CNTL_EN__SHIFT 0x0000000c
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_MODE_MASK 0x00000004L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_MODE__SHIFT 0x00000002
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SCHMEN_MASK 0x00000800L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SCHMEN__SHIFT 0x0000000b
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SEL_MASK 0x00000002L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SEL__SHIFT 0x00000001
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SLEWN_MASK 0x00000200L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SLEWN__SHIFT 0x00000009
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN0_MASK 0x00000020L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN0__SHIFT 0x00000005
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN1_MASK 0x00000040L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN1__SHIFT 0x00000006
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN2_MASK 0x00000080L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN2__SHIFT 0x00000007
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN3_MASK 0x00000100L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN3__SHIFT 0x00000008
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SPARE_MASK 0x00000018L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SPARE__SHIFT 0x00000003
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_WAKE_MASK 0x00000400L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_WAKE__SHIFT 0x0000000a
+#define SMBUS_BACO_DUMMY__SMBUS_BACO_DUMMY_DATA_MASK 0xffffffffL
+#define SMBUS_BACO_DUMMY__SMBUS_BACO_DUMMY_DATA__SHIFT 0x00000000
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h
index 09a7df17570d..09a7df17570d 100755..100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h
index 1ddc4183a1c9..1ddc4183a1c9 100755..100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h
new file mode 100644
index 000000000000..ae798f768853
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h
@@ -0,0 +1,4457 @@
+/*
+ *
+ * Copyright (C) 2016 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 DCE_6_0_D_H
+#define DCE_6_0_D_H
+
+#define ixATTR00 0x0000
+#define ixATTR01 0x0001
+#define ixATTR02 0x0002
+#define ixATTR03 0x0003
+#define ixATTR04 0x0004
+#define ixATTR05 0x0005
+#define ixATTR06 0x0006
+#define ixATTR07 0x0007
+#define ixATTR08 0x0008
+#define ixATTR09 0x0009
+#define ixATTR0A 0x000A
+#define ixATTR0B 0x000B
+#define ixATTR0C 0x000C
+#define ixATTR0D 0x000D
+#define ixATTR0E 0x000E
+#define ixATTR0F 0x000F
+#define ixATTR10 0x0010
+#define ixATTR11 0x0011
+#define ixATTR12 0x0012
+#define ixATTR13 0x0013
+#define ixATTR14 0x0014
+#define ixAUDIO_DESCRIPTOR0 0x0001
+#define ixAUDIO_DESCRIPTOR10 0x000B
+#define ixAUDIO_DESCRIPTOR1 0x0002
+#define ixAUDIO_DESCRIPTOR11 0x000C
+#define ixAUDIO_DESCRIPTOR12 0x000D
+#define ixAUDIO_DESCRIPTOR13 0x000E
+#define ixAUDIO_DESCRIPTOR2 0x0003
+#define ixAUDIO_DESCRIPTOR3 0x0004
+#define ixAUDIO_DESCRIPTOR4 0x0005
+#define ixAUDIO_DESCRIPTOR5 0x0006
+#define ixAUDIO_DESCRIPTOR6 0x0007
+#define ixAUDIO_DESCRIPTOR7 0x0008
+#define ixAUDIO_DESCRIPTOR8 0x0009
+#define ixAUDIO_DESCRIPTOR9 0x000A
+#define ixAZALIA_CUMULATIVE_LATENCY_COUNT 0x0003
+#define ixAZALIA_CUMULATIVE_REQUEST_COUNT 0x0004
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID 0x0003
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT 0x0002
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER 0x0004
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING 0x0009
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE 0x0008
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x0001
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS 0x0005
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES 0x0006
+#define ixAZALIA_F0_CODEC_CONVERTER_PIN_DEBUG 0x0000
+#define ixAZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL 0x0007
+#define ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO 0x0062
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 0x0028
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10 0x0032
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1 0x0029
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11 0x0033
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12 0x0034
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13 0x0035
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2 0x002A
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3 0x002B
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4 0x002C
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5 0x002D
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6 0x002E
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7 0x002F
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8 0x0030
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9 0x0031
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER 0x0025
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL 0x0054
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE 0x0036
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2 0x0057
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE 0x0058
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x0056
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR 0x0038
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC 0x0037
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE 0x0023
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0 0x003A
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1 0x003B
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2 0x003C
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3 0x003D
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4 0x003E
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5 0x003F
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6 0x0040
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7 0x0041
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8 0x0042
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE 0x0022
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE 0x0055
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL 0x0024
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x0020
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES 0x0021
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0 0x0059
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1 0x005A
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2 0x005B
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3 0x005C
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4 0x005D
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5 0x005E
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6 0x005F
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7 0x0060
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8 0x0061
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID 0x2706
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT 0x2200
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER 0x270D
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2 0x270E
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3 0x273E
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE 0x2770
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x2F09
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS 0x2F0B
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES 0x2F0A
+#define ixAZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL 0x2724
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION 0x1770
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE 0x1705
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESET 0x17FF
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID 0x1720
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2 0x1721
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3 0x1722
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4 0x1723
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE 0x1F05
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES 0x1F0F
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS 0x1F0B
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT 0x1F04
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES 0x1F0A
+#define ixAZALIA_F2_CODEC_PIN_ASSOCIATION_INFO 0x3793
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR 0x3776
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA 0x3776
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA 0x3781
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX 0x3780
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION 0x3771
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO 0x3772
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_HBR 0x377C
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC 0x377B
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID 0x0000
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE 0x3777
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE 0x3785
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE 0x3778
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE 0x3786
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE 0x3779
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE 0x3787
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE 0x377A
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE 0x3788
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE 0x3789
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID0 0x0003
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID1 0x0004
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID 0x0001
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x371C
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2 0x371D
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3 0x371E
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4 0x371F
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY 0x3702
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE 0x3709
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION 0x3770
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN 0x0002
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE 0x3708
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL 0x3707
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x3F09
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES 0x3F0C
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH 0x3F0E
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID 0x0F02
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT 0x0F04
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID 0x0F00
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0 0x378A
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1 0x378B
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2 0x378C
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3 0x378D
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4 0x378E
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5 0x378F
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6 0x3790
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7 0x3791
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8 0x3792
+#define ixAZALIA_FIFO_SIZE_CONTROL 0x0000
+#define ixAZALIA_LATENCY_COUNTER_CONTROL 0x0001
+#define ixAZALIA_STREAM_DEBUG 0x0005
+#define ixAZALIA_WORSTCASE_LATENCY_COUNT 0x0002
+#define ixCRT00 0x0000
+#define ixCRT01 0x0001
+#define ixCRT02 0x0002
+#define ixCRT03 0x0003
+#define ixCRT04 0x0004
+#define ixCRT05 0x0005
+#define ixCRT06 0x0006
+#define ixCRT07 0x0007
+#define ixCRT08 0x0008
+#define ixCRT09 0x0009
+#define ixCRT0A 0x000A
+#define ixCRT0B 0x000B
+#define ixCRT0C 0x000C
+#define ixCRT0D 0x000D
+#define ixCRT0E 0x000E
+#define ixCRT0F 0x000F
+#define ixCRT10 0x0010
+#define ixCRT11 0x0011
+#define ixCRT12 0x0012
+#define ixCRT13 0x0013
+#define ixCRT14 0x0014
+#define ixCRT15 0x0015
+#define ixCRT16 0x0016
+#define ixCRT17 0x0017
+#define ixCRT18 0x0018
+#define ixCRT1E 0x001E
+#define ixCRT1F 0x001F
+#define ixCRT22 0x0022
+#define ixDCIO_DEBUG10 0x0010
+#define ixDCIO_DEBUG1 0x0001
+#define ixDCIO_DEBUG11 0x0011
+#define ixDCIO_DEBUG12 0x0012
+#define ixDCIO_DEBUG13 0x0013
+#define ixDCIO_DEBUG2 0x0002
+#define ixDCIO_DEBUG3 0x0003
+#define ixDCIO_DEBUG4 0x0004
+#define ixDCIO_DEBUG5 0x0005
+#define ixDCIO_DEBUG6 0x0006
+#define ixDCIO_DEBUG7 0x0007
+#define ixDCIO_DEBUG8 0x0008
+#define ixDCIO_DEBUG9 0x0009
+#define ixDCIO_DEBUGA 0x000A
+#define ixDCIO_DEBUGB 0x000B
+#define ixDCIO_DEBUGC 0x000C
+#define ixDCIO_DEBUGD 0x000D
+#define ixDCIO_DEBUGE 0x000E
+#define ixDCIO_DEBUGF 0x000F
+#define ixDCIO_DEBUG_ID 0x0000
+#define ixDMIF_DEBUG02_CORE0 0x0002
+#define ixDMIF_DEBUG02_CORE1 0x000A
+#define ixDP_AUX1_DEBUG_A 0x0010
+#define ixDP_AUX1_DEBUG_B 0x0011
+#define ixDP_AUX1_DEBUG_C 0x0012
+#define ixDP_AUX1_DEBUG_D 0x0013
+#define ixDP_AUX1_DEBUG_E 0x0014
+#define ixDP_AUX1_DEBUG_F 0x0015
+#define ixDP_AUX1_DEBUG_G 0x0016
+#define ixDP_AUX1_DEBUG_H 0x0017
+#define ixDP_AUX1_DEBUG_I 0x0018
+#define ixDP_AUX2_DEBUG_A 0x0020
+#define ixDP_AUX2_DEBUG_B 0x0021
+#define ixDP_AUX2_DEBUG_C 0x0022
+#define ixDP_AUX2_DEBUG_D 0x0023
+#define ixDP_AUX2_DEBUG_E 0x0024
+#define ixDP_AUX2_DEBUG_F 0x0025
+#define ixDP_AUX2_DEBUG_G 0x0026
+#define ixDP_AUX2_DEBUG_H 0x0027
+#define ixDP_AUX2_DEBUG_I 0x0028
+#define ixDP_AUX3_DEBUG_A 0x0030
+#define ixDP_AUX3_DEBUG_B 0x0031
+#define ixDP_AUX3_DEBUG_C 0x0032
+#define ixDP_AUX3_DEBUG_D 0x0033
+#define ixDP_AUX3_DEBUG_E 0x0034
+#define ixDP_AUX3_DEBUG_F 0x0035
+#define ixDP_AUX3_DEBUG_G 0x0036
+#define ixDP_AUX3_DEBUG_H 0x0037
+#define ixDP_AUX3_DEBUG_I 0x0038
+#define ixDP_AUX4_DEBUG_A 0x0040
+#define ixDP_AUX4_DEBUG_B 0x0041
+#define ixDP_AUX4_DEBUG_C 0x0042
+#define ixDP_AUX4_DEBUG_D 0x0043
+#define ixDP_AUX4_DEBUG_E 0x0044
+#define ixDP_AUX4_DEBUG_F 0x0045
+#define ixDP_AUX4_DEBUG_G 0x0046
+#define ixDP_AUX4_DEBUG_H 0x0047
+#define ixDP_AUX4_DEBUG_I 0x0048
+#define ixDP_AUX5_DEBUG_A 0x0070
+#define ixDP_AUX5_DEBUG_B 0x0071
+#define ixDP_AUX5_DEBUG_C 0x0072
+#define ixDP_AUX5_DEBUG_D 0x0073
+#define ixDP_AUX5_DEBUG_E 0x0074
+#define ixDP_AUX5_DEBUG_F 0x0075
+#define ixDP_AUX5_DEBUG_G 0x0076
+#define ixDP_AUX5_DEBUG_H 0x0077
+#define ixDP_AUX5_DEBUG_I 0x0078
+#define ixDP_AUX6_DEBUG_A 0x0080
+#define ixDP_AUX6_DEBUG_B 0x0081
+#define ixDP_AUX6_DEBUG_C 0x0082
+#define ixDP_AUX6_DEBUG_D 0x0083
+#define ixDP_AUX6_DEBUG_E 0x0084
+#define ixDP_AUX6_DEBUG_F 0x0085
+#define ixDP_AUX6_DEBUG_G 0x0086
+#define ixDP_AUX6_DEBUG_H 0x0087
+#define ixDP_AUX6_DEBUG_I 0x0088
+#define ixFMT_DEBUG0 0x0001
+#define ixFMT_DEBUG1 0x0002
+#define ixFMT_DEBUG2 0x0003
+#define ixFMT_DEBUG_ID 0x0000
+#define ixGRA00 0x0000
+#define ixGRA01 0x0001
+#define ixGRA02 0x0002
+#define ixGRA03 0x0003
+#define ixGRA04 0x0004
+#define ixGRA05 0x0005
+#define ixGRA06 0x0006
+#define ixGRA07 0x0007
+#define ixGRA08 0x0008
+#define ixIDDCCIF02_DBG_DCCIF_C 0x0009
+#define ixIDDCCIF04_DBG_DCCIF_E 0x000B
+#define ixIDDCCIF05_DBG_DCCIF_F 0x000C
+#define ixMVP_DEBUG_12 0x000C
+#define ixMVP_DEBUG_13 0x000D
+#define ixMVP_DEBUG_14 0x000E
+#define ixMVP_DEBUG_15 0x000F
+#define ixMVP_DEBUG_16 0x0010
+#define ixMVP_DEBUG_17 0x0011
+#define ixSEQ00 0x0000
+#define ixSEQ01 0x0001
+#define ixSEQ02 0x0002
+#define ixSEQ03 0x0003
+#define ixSEQ04 0x0004
+#define ixSINK_DESCRIPTION0 0x0005
+#define ixSINK_DESCRIPTION10 0x000F
+#define ixSINK_DESCRIPTION1 0x0006
+#define ixSINK_DESCRIPTION11 0x0010
+#define ixSINK_DESCRIPTION12 0x0011
+#define ixSINK_DESCRIPTION13 0x0012
+#define ixSINK_DESCRIPTION14 0x0013
+#define ixSINK_DESCRIPTION15 0x0014
+#define ixSINK_DESCRIPTION16 0x0015
+#define ixSINK_DESCRIPTION17 0x0016
+#define ixSINK_DESCRIPTION2 0x0007
+#define ixSINK_DESCRIPTION3 0x0008
+#define ixSINK_DESCRIPTION4 0x0009
+#define ixSINK_DESCRIPTION5 0x000A
+#define ixSINK_DESCRIPTION6 0x000B
+#define ixSINK_DESCRIPTION7 0x000C
+#define ixSINK_DESCRIPTION8 0x000D
+#define ixSINK_DESCRIPTION9 0x000E
+#define ixVGADCC_DBG_DCCIF_C 0x007E
+#define mmABM_TEST_DEBUG_DATA 0x169F
+#define mmABM_TEST_DEBUG_INDEX 0x169E
+#define mmAFMT_60958_0 0x1C41
+#define mmAFMT_60958_1 0x1C42
+#define mmAFMT_60958_2 0x1C48
+#define mmAFMT_AUDIO_CRC_CONTROL 0x1C43
+#define mmAFMT_AUDIO_CRC_RESULT 0x1C49
+#define mmAFMT_AUDIO_DBG_DTO_CNTL 0x1C52
+#define mmAFMT_AUDIO_INFO0 0x1C3F
+#define mmAFMT_AUDIO_INFO1 0x1C40
+#define mmAFMT_AUDIO_PACKET_CONTROL 0x1C4B
+#define mmAFMT_AUDIO_PACKET_CONTROL2 0x1C17
+#define mmAFMT_AUDIO_SRC_CONTROL 0x1C4F
+#define mmAFMT_AVI_INFO0 0x1C21
+#define mmAFMT_AVI_INFO1 0x1C22
+#define mmAFMT_AVI_INFO2 0x1C23
+#define mmAFMT_AVI_INFO3 0x1C24
+#define mmAFMT_GENERIC_0 0x1C28
+#define mmAFMT_GENERIC_1 0x1C29
+#define mmAFMT_GENERIC_2 0x1C2A
+#define mmAFMT_GENERIC_3 0x1C2B
+#define mmAFMT_GENERIC_4 0x1C2C
+#define mmAFMT_GENERIC_5 0x1C2D
+#define mmAFMT_GENERIC_6 0x1C2E
+#define mmAFMT_GENERIC_7 0x1C2F
+#define mmAFMT_GENERIC_HDR 0x1C27
+#define mmAFMT_INFOFRAME_CONTROL0 0x1C4D
+#define mmAFMT_INTERRUPT_STATUS 0x1C14
+#define mmAFMT_ISRC1_0 0x1C18
+#define mmAFMT_ISRC1_1 0x1C19
+#define mmAFMT_ISRC1_2 0x1C1A
+#define mmAFMT_ISRC1_3 0x1C1B
+#define mmAFMT_ISRC1_4 0x1C1C
+#define mmAFMT_ISRC2_0 0x1C1D
+#define mmAFMT_ISRC2_1 0x1C1E
+#define mmAFMT_ISRC2_2 0x1C1F
+#define mmAFMT_ISRC2_3 0x1C20
+#define mmAFMT_MPEG_INFO0 0x1C25
+#define mmAFMT_MPEG_INFO1 0x1C26
+#define mmAFMT_RAMP_CONTROL0 0x1C44
+#define mmAFMT_RAMP_CONTROL1 0x1C45
+#define mmAFMT_RAMP_CONTROL2 0x1C46
+#define mmAFMT_RAMP_CONTROL3 0x1C47
+#define mmAFMT_STATUS 0x1C4A
+#define mmAFMT_VBI_PACKET_CONTROL 0x1C4C
+#define mmATTRDR 0x00F0
+#define mmATTRDW 0x00F0
+#define mmATTRX 0x00F0
+#define mmAUX_ARB_CONTROL 0x1882
+#define mmAUX_CONTROL 0x1880
+#define mmAUX_DPHY_RX_CONTROL0 0x188A
+#define mmAUX_DPHY_RX_CONTROL1 0x188B
+#define mmAUX_DPHY_RX_STATUS 0x188D
+#define mmAUX_DPHY_TX_CONTROL 0x1889
+#define mmAUX_DPHY_TX_REF_CONTROL 0x1888
+#define mmAUX_DPHY_TX_STATUS 0x188C
+#define mmAUX_GTC_SYNC_CONTROL 0x188E
+#define mmAUX_GTC_SYNC_DATA 0x1890
+#define mmAUX_INTERRUPT_CONTROL 0x1883
+#define mmAUX_LS_DATA 0x1887
+#define mmAUX_LS_STATUS 0x1885
+#define mmAUXN_IMPCAL 0x190C
+#define mmAUXP_IMPCAL 0x190B
+#define mmAUX_SW_CONTROL 0x1881
+#define mmAUX_SW_DATA 0x1886
+#define mmAUX_SW_STATUS 0x1884
+#define mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER 0x17C9
+#define mmAZALIA_AUDIO_DTO 0x17BA
+#define mmAZALIA_AUDIO_DTO_CONTROL 0x17BB
+#define mmAZALIA_BDL_DMA_CONTROL 0x17BF
+#define mmAZALIA_CONTROLLER_DEBUG 0x17CF
+#define mmAZALIA_CORB_DMA_CONTROL 0x17C1
+#define mmAZALIA_CYCLIC_BUFFER_SYNC 0x17CA
+#define mmAZALIA_DATA_DMA_CONTROL 0x17BE
+#define mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL 0x17D5
+#define mmAZALIA_F0_CODEC_DEBUG 0x17DF
+#define mmAZALIA_F0_CODEC_ENDPOINT_DATA 0x1781
+#define mmAZALIA_F0_CODEC_ENDPOINT_INDEX 0x1780
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION 0x17DE
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE 0x17DB
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESET 0x17DC
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID 0x17DD
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE 0x17D7
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES 0x17DA
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS 0x17D9
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES 0x17D8
+#define mmAZALIA_F0_CODEC_RESYNC_FIFO_CONTROL 0x17D6
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID 0x17D3
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID 0x17D2
+#define mmAZALIA_GLOBAL_CAPABILITIES 0x17CB
+#define mmAZALIA_OUTPUT_PAYLOAD_CAPABILITY 0x17CC
+#define mmAZALIA_OUTPUT_STREAM_ARBITER_CONTROL 0x17CD
+#define mmAZALIA_RIRB_AND_DP_CONTROL 0x17C0
+#define mmAZALIA_SCLK_CONTROL 0x17BC
+#define mmAZALIA_STREAM_DATA 0x17E9
+#define mmAZALIA_STREAM_INDEX 0x17E8
+#define mmAZALIA_UNDERFLOW_FILLER_SAMPLE 0x17BD
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1781
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1780
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1787
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1786
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA 0x178D
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x178C
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1793
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1792
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1799
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1798
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_DATA 0x179F
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x179E
+#define mmAZF0STREAM0_AZALIA_STREAM_DATA 0x17E9
+#define mmAZF0STREAM0_AZALIA_STREAM_INDEX 0x17E8
+#define mmAZF0STREAM1_AZALIA_STREAM_DATA 0x17ED
+#define mmAZF0STREAM1_AZALIA_STREAM_INDEX 0x17EC
+#define mmAZF0STREAM2_AZALIA_STREAM_DATA 0x17F1
+#define mmAZF0STREAM2_AZALIA_STREAM_INDEX 0x17F0
+#define mmAZF0STREAM3_AZALIA_STREAM_DATA 0x17F5
+#define mmAZF0STREAM3_AZALIA_STREAM_INDEX 0x17F4
+#define mmAZF0STREAM4_AZALIA_STREAM_DATA 0x17F9
+#define mmAZF0STREAM4_AZALIA_STREAM_INDEX 0x17F8
+#define mmAZF0STREAM5_AZALIA_STREAM_DATA 0x17FD
+#define mmAZF0STREAM5_AZALIA_STREAM_INDEX 0x17FC
+#define mmAZ_TEST_DEBUG_DATA 0x17D1
+#define mmAZ_TEST_DEBUG_INDEX 0x17D0
+#define mmBL1_PWM_ABM_CNTL 0x162E
+#define mmBL1_PWM_AMBIENT_LIGHT_LEVEL 0x1628
+#define mmBL1_PWM_BL_UPDATE_SAMPLE_RATE 0x162F
+#define mmBL1_PWM_CURRENT_ABM_LEVEL 0x162B
+#define mmBL1_PWM_FINAL_DUTY_CYCLE 0x162C
+#define mmBL1_PWM_GRP2_REG_LOCK 0x1630
+#define mmBL1_PWM_MINIMUM_DUTY_CYCLE 0x162D
+#define mmBL1_PWM_TARGET_ABM_LEVEL 0x162A
+#define mmBL1_PWM_USER_LEVEL 0x1629
+#define mmBL_PWM_CNTL 0x191E
+#define mmBL_PWM_CNTL2 0x191F
+#define mmBL_PWM_GRP1_REG_LOCK 0x1921
+#define mmBL_PWM_PERIOD_CNTL 0x1920
+#define mmBPHYC_DAC_AUTO_CALIB_CONTROL 0x19FE
+#define mmBPHYC_DAC_MACRO_CNTL 0x19FD
+#define mmCC_DC_PIPE_DIS 0x177F
+#define mmCC_RCU_DC_AUDIO_PORT_CONNECTIVITY 0x17D4
+#define mmCOMM_MATRIXA_TRANS_C11_C12 0x1A43
+#define mmCOMM_MATRIXA_TRANS_C13_C14 0x1A44
+#define mmCOMM_MATRIXA_TRANS_C21_C22 0x1A45
+#define mmCOMM_MATRIXA_TRANS_C23_C24 0x1A46
+#define mmCOMM_MATRIXA_TRANS_C31_C32 0x1A47
+#define mmCOMM_MATRIXA_TRANS_C33_C34 0x1A48
+#define mmCOMM_MATRIXB_TRANS_C11_C12 0x1A49
+#define mmCOMM_MATRIXB_TRANS_C13_C14 0x1A4A
+#define mmCOMM_MATRIXB_TRANS_C21_C22 0x1A4B
+#define mmCOMM_MATRIXB_TRANS_C23_C24 0x1A4C
+#define mmCOMM_MATRIXB_TRANS_C31_C32 0x1A4D
+#define mmCOMM_MATRIXB_TRANS_C33_C34 0x1A4E
+#define mmCRTC0_CRTC_3D_STRUCTURE_CONTROL 0x1B78
+#define mmCRTC0_CRTC_ALLOW_STOP_OFF_V_CNT 0x1BC3
+#define mmCRTC0_CRTC_BLACK_COLOR 0x1BA2
+#define mmCRTC0_CRTC_BLANK_CONTROL 0x1B9D
+#define mmCRTC0_CRTC_BLANK_DATA_COLOR 0x1BA1
+#define mmCRTC0_CRTC_CONTROL 0x1B9C
+#define mmCRTC0_CRTC_COUNT_CONTROL 0x1BA9
+#define mmCRTC0_CRTC_COUNT_RESET 0x1BAA
+#define mmCRTC0_CRTC_DCFE_CLOCK_CONTROL 0x1B7C
+#define mmCRTC0_CRTC_DOUBLE_BUFFER_CONTROL 0x1BB6
+#define mmCRTC0_CRTC_DTMTEST_CNTL 0x1B92
+#define mmCRTC0_CRTC_DTMTEST_STATUS_POSITION 0x1B93
+#define mmCRTC0_CRTC_FLOW_CONTROL 0x1B99
+#define mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL 0x1B98
+#define mmCRTC0_CRTC_GSL_CONTROL 0x1B7B
+#define mmCRTC0_CRTC_GSL_VSYNC_GAP 0x1B79
+#define mmCRTC0_CRTC_GSL_WINDOW 0x1B7A
+#define mmCRTC0_CRTC_H_BLANK_EARLY_NUM 0x1B7D
+#define mmCRTC0_CRTC_H_BLANK_START_END 0x1B81
+#define mmCRTC0_CRTC_H_SYNC_A 0x1B82
+#define mmCRTC0_CRTC_H_SYNC_A_CNTL 0x1B83
+#define mmCRTC0_CRTC_H_SYNC_B 0x1B84
+#define mmCRTC0_CRTC_H_SYNC_B_CNTL 0x1B85
+#define mmCRTC0_CRTC_H_TOTAL 0x1B80
+#define mmCRTC0_CRTC_INTERLACE_CONTROL 0x1B9E
+#define mmCRTC0_CRTC_INTERLACE_STATUS 0x1B9F
+#define mmCRTC0_CRTC_INTERRUPT_CONTROL 0x1BB4
+#define mmCRTC0_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1BAB
+#define mmCRTC0_CRTC_MASTER_EN 0x1BC2
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT 0x1BBF
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1BC0
+#define mmCRTC0_CRTC_MVP_STATUS 0x1BC1
+#define mmCRTC0_CRTC_NOM_VERT_POSITION 0x1BA5
+#define mmCRTC0_CRTC_OVERSCAN_COLOR 0x1BA0
+#define mmCRTC0_CRTC_SNAPSHOT_CONTROL 0x1BB0
+#define mmCRTC0_CRTC_SNAPSHOT_FRAME 0x1BB2
+#define mmCRTC0_CRTC_SNAPSHOT_POSITION 0x1BB1
+#define mmCRTC0_CRTC_SNAPSHOT_STATUS 0x1BAF
+#define mmCRTC0_CRTC_START_LINE_CONTROL 0x1BB3
+#define mmCRTC0_CRTC_STATUS 0x1BA3
+#define mmCRTC0_CRTC_STATUS_FRAME_COUNT 0x1BA6
+#define mmCRTC0_CRTC_STATUS_HV_COUNT 0x1BA8
+#define mmCRTC0_CRTC_STATUS_POSITION 0x1BA4
+#define mmCRTC0_CRTC_STATUS_VF_COUNT 0x1BA7
+#define mmCRTC0_CRTC_STEREO_CONTROL 0x1BAE
+#define mmCRTC0_CRTC_STEREO_FORCE_NEXT_EYE 0x1B9B
+#define mmCRTC0_CRTC_STEREO_STATUS 0x1BAD
+#define mmCRTC0_CRTC_TEST_DEBUG_DATA 0x1BC7
+#define mmCRTC0_CRTC_TEST_DEBUG_INDEX 0x1BC6
+#define mmCRTC0_CRTC_TEST_PATTERN_COLOR 0x1BBC
+#define mmCRTC0_CRTC_TEST_PATTERN_CONTROL 0x1BBA
+#define mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS 0x1BBB
+#define mmCRTC0_CRTC_TRIGA_CNTL 0x1B94
+#define mmCRTC0_CRTC_TRIGA_MANUAL_TRIG 0x1B95
+#define mmCRTC0_CRTC_TRIGB_CNTL 0x1B96
+#define mmCRTC0_CRTC_TRIGB_MANUAL_TRIG 0x1B97
+#define mmCRTC0_CRTC_UPDATE_LOCK 0x1BB5
+#define mmCRTC0_CRTC_VBI_END 0x1B86
+#define mmCRTC0_CRTC_V_BLANK_START_END 0x1B8D
+#define mmCRTC0_CRTC_VERT_SYNC_CONTROL 0x1BAC
+#define mmCRTC0_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x1BB7
+#define mmCRTC0_CRTC_V_SYNC_A 0x1B8E
+#define mmCRTC0_CRTC_V_SYNC_A_CNTL 0x1B8F
+#define mmCRTC0_CRTC_V_SYNC_B 0x1B90
+#define mmCRTC0_CRTC_V_SYNC_B_CNTL 0x1B91
+#define mmCRTC0_CRTC_VSYNC_NOM_INT_STATUS 0x1B8C
+#define mmCRTC0_CRTC_V_TOTAL 0x1B87
+#define mmCRTC0_CRTC_V_TOTAL_CONTROL 0x1B8A
+#define mmCRTC0_CRTC_V_TOTAL_INT_STATUS 0x1B8B
+#define mmCRTC0_CRTC_V_TOTAL_MAX 0x1B89
+#define mmCRTC0_CRTC_V_TOTAL_MIN 0x1B88
+#define mmCRTC0_CRTC_V_UPDATE_INT_STATUS 0x1BC4
+#define mmCRTC0_DCFE_DBG_SEL 0x1B7E
+#define mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL 0x1B7F
+#define mmCRTC0_MASTER_UPDATE_LOCK 0x1BBD
+#define mmCRTC0_MASTER_UPDATE_MODE 0x1BBE
+#define mmCRTC0_PIXEL_RATE_CNTL 0x0140
+#define mmCRTC1_CRTC_3D_STRUCTURE_CONTROL 0x1E78
+#define mmCRTC1_CRTC_ALLOW_STOP_OFF_V_CNT 0x1EC3
+#define mmCRTC1_CRTC_BLACK_COLOR 0x1EA2
+#define mmCRTC1_CRTC_BLANK_CONTROL 0x1E9D
+#define mmCRTC1_CRTC_BLANK_DATA_COLOR 0x1EA1
+#define mmCRTC1_CRTC_CONTROL 0x1E9C
+#define mmCRTC1_CRTC_COUNT_CONTROL 0x1EA9
+#define mmCRTC1_CRTC_COUNT_RESET 0x1EAA
+#define mmCRTC1_CRTC_DCFE_CLOCK_CONTROL 0x1E7C
+#define mmCRTC1_CRTC_DOUBLE_BUFFER_CONTROL 0x1EB6
+#define mmCRTC1_CRTC_DTMTEST_CNTL 0x1E92
+#define mmCRTC1_CRTC_DTMTEST_STATUS_POSITION 0x1E93
+#define mmCRTC1_CRTC_FLOW_CONTROL 0x1E99
+#define mmCRTC1_CRTC_FORCE_COUNT_NOW_CNTL 0x1E98
+#define mmCRTC1_CRTC_GSL_CONTROL 0x1E7B
+#define mmCRTC1_CRTC_GSL_VSYNC_GAP 0x1E79
+#define mmCRTC1_CRTC_GSL_WINDOW 0x1E7A
+#define mmCRTC1_CRTC_H_BLANK_EARLY_NUM 0x1E7D
+#define mmCRTC1_CRTC_H_BLANK_START_END 0x1E81
+#define mmCRTC1_CRTC_H_SYNC_A 0x1E82
+#define mmCRTC1_CRTC_H_SYNC_A_CNTL 0x1E83
+#define mmCRTC1_CRTC_H_SYNC_B 0x1E84
+#define mmCRTC1_CRTC_H_SYNC_B_CNTL 0x1E85
+#define mmCRTC1_CRTC_H_TOTAL 0x1E80
+#define mmCRTC1_CRTC_INTERLACE_CONTROL 0x1E9E
+#define mmCRTC1_CRTC_INTERLACE_STATUS 0x1E9F
+#define mmCRTC1_CRTC_INTERRUPT_CONTROL 0x1EB4
+#define mmCRTC1_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1EAB
+#define mmCRTC1_CRTC_MASTER_EN 0x1EC2
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT 0x1EBF
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1EC0
+#define mmCRTC1_CRTC_MVP_STATUS 0x1EC1
+#define mmCRTC1_CRTC_NOM_VERT_POSITION 0x1EA5
+#define mmCRTC1_CRTC_OVERSCAN_COLOR 0x1EA0
+#define mmCRTC1_CRTC_SNAPSHOT_CONTROL 0x1EB0
+#define mmCRTC1_CRTC_SNAPSHOT_FRAME 0x1EB2
+#define mmCRTC1_CRTC_SNAPSHOT_POSITION 0x1EB1
+#define mmCRTC1_CRTC_SNAPSHOT_STATUS 0x1EAF
+#define mmCRTC1_CRTC_START_LINE_CONTROL 0x1EB3
+#define mmCRTC1_CRTC_STATUS 0x1EA3
+#define mmCRTC1_CRTC_STATUS_FRAME_COUNT 0x1EA6
+#define mmCRTC1_CRTC_STATUS_HV_COUNT 0x1EA8
+#define mmCRTC1_CRTC_STATUS_POSITION 0x1EA4
+#define mmCRTC1_CRTC_STATUS_VF_COUNT 0x1EA7
+#define mmCRTC1_CRTC_STEREO_CONTROL 0x1EAE
+#define mmCRTC1_CRTC_STEREO_FORCE_NEXT_EYE 0x1E9B
+#define mmCRTC1_CRTC_STEREO_STATUS 0x1EAD
+#define mmCRTC1_CRTC_TEST_DEBUG_DATA 0x1EC7
+#define mmCRTC1_CRTC_TEST_DEBUG_INDEX 0x1EC6
+#define mmCRTC1_CRTC_TEST_PATTERN_COLOR 0x1EBC
+#define mmCRTC1_CRTC_TEST_PATTERN_CONTROL 0x1EBA
+#define mmCRTC1_CRTC_TEST_PATTERN_PARAMETERS 0x1EBB
+#define mmCRTC1_CRTC_TRIGA_CNTL 0x1E94
+#define mmCRTC1_CRTC_TRIGA_MANUAL_TRIG 0x1E95
+#define mmCRTC1_CRTC_TRIGB_CNTL 0x1E96
+#define mmCRTC1_CRTC_TRIGB_MANUAL_TRIG 0x1E97
+#define mmCRTC1_CRTC_UPDATE_LOCK 0x1EB5
+#define mmCRTC1_CRTC_VBI_END 0x1E86
+#define mmCRTC1_CRTC_V_BLANK_START_END 0x1E8D
+#define mmCRTC1_CRTC_VERT_SYNC_CONTROL 0x1EAC
+#define mmCRTC1_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x1EB7
+#define mmCRTC1_CRTC_V_SYNC_A 0x1E8E
+#define mmCRTC1_CRTC_V_SYNC_A_CNTL 0x1E8F
+#define mmCRTC1_CRTC_V_SYNC_B 0x1E90
+#define mmCRTC1_CRTC_V_SYNC_B_CNTL 0x1E91
+#define mmCRTC1_CRTC_VSYNC_NOM_INT_STATUS 0x1E8C
+#define mmCRTC1_CRTC_V_TOTAL 0x1E87
+#define mmCRTC1_CRTC_V_TOTAL_CONTROL 0x1E8A
+#define mmCRTC1_CRTC_V_TOTAL_INT_STATUS 0x1E8B
+#define mmCRTC1_CRTC_V_TOTAL_MAX 0x1E89
+#define mmCRTC1_CRTC_V_TOTAL_MIN 0x1E88
+#define mmCRTC1_CRTC_V_UPDATE_INT_STATUS 0x1EC4
+#define mmCRTC1_DCFE_DBG_SEL 0x1E7E
+#define mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL 0x1E7F
+#define mmCRTC1_MASTER_UPDATE_LOCK 0x1EBD
+#define mmCRTC1_MASTER_UPDATE_MODE 0x1EBE
+#define mmCRTC1_PIXEL_RATE_CNTL 0x0144
+#define mmCRTC2_CRTC_3D_STRUCTURE_CONTROL 0x4178
+#define mmCRTC2_CRTC_ALLOW_STOP_OFF_V_CNT 0x41C3
+#define mmCRTC2_CRTC_BLACK_COLOR 0x41A2
+#define mmCRTC2_CRTC_BLANK_CONTROL 0x419D
+#define mmCRTC2_CRTC_BLANK_DATA_COLOR 0x41A1
+#define mmCRTC2_CRTC_CONTROL 0x419C
+#define mmCRTC2_CRTC_COUNT_CONTROL 0x41A9
+#define mmCRTC2_CRTC_COUNT_RESET 0x41AA
+#define mmCRTC2_CRTC_DCFE_CLOCK_CONTROL 0x417C
+#define mmCRTC2_CRTC_DOUBLE_BUFFER_CONTROL 0x41B6
+#define mmCRTC2_CRTC_DTMTEST_CNTL 0x4192
+#define mmCRTC2_CRTC_DTMTEST_STATUS_POSITION 0x4193
+#define mmCRTC2_CRTC_FLOW_CONTROL 0x4199
+#define mmCRTC2_CRTC_FORCE_COUNT_NOW_CNTL 0x4198
+#define mmCRTC2_CRTC_GSL_CONTROL 0x417B
+#define mmCRTC2_CRTC_GSL_VSYNC_GAP 0x4179
+#define mmCRTC2_CRTC_GSL_WINDOW 0x417A
+#define mmCRTC2_CRTC_H_BLANK_EARLY_NUM 0x417D
+#define mmCRTC2_CRTC_H_BLANK_START_END 0x4181
+#define mmCRTC2_CRTC_H_SYNC_A 0x4182
+#define mmCRTC2_CRTC_H_SYNC_A_CNTL 0x4183
+#define mmCRTC2_CRTC_H_SYNC_B 0x4184
+#define mmCRTC2_CRTC_H_SYNC_B_CNTL 0x4185
+#define mmCRTC2_CRTC_H_TOTAL 0x4180
+#define mmCRTC2_CRTC_INTERLACE_CONTROL 0x419E
+#define mmCRTC2_CRTC_INTERLACE_STATUS 0x419F
+#define mmCRTC2_CRTC_INTERRUPT_CONTROL 0x41B4
+#define mmCRTC2_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x41AB
+#define mmCRTC2_CRTC_MASTER_EN 0x41C2
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT 0x41BF
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x41C0
+#define mmCRTC2_CRTC_MVP_STATUS 0x41C1
+#define mmCRTC2_CRTC_NOM_VERT_POSITION 0x41A5
+#define mmCRTC2_CRTC_OVERSCAN_COLOR 0x41A0
+#define mmCRTC2_CRTC_SNAPSHOT_CONTROL 0x41B0
+#define mmCRTC2_CRTC_SNAPSHOT_FRAME 0x41B2
+#define mmCRTC2_CRTC_SNAPSHOT_POSITION 0x41B1
+#define mmCRTC2_CRTC_SNAPSHOT_STATUS 0x41AF
+#define mmCRTC2_CRTC_START_LINE_CONTROL 0x41B3
+#define mmCRTC2_CRTC_STATUS 0x41A3
+#define mmCRTC2_CRTC_STATUS_FRAME_COUNT 0x41A6
+#define mmCRTC2_CRTC_STATUS_HV_COUNT 0x41A8
+#define mmCRTC2_CRTC_STATUS_POSITION 0x41A4
+#define mmCRTC2_CRTC_STATUS_VF_COUNT 0x41A7
+#define mmCRTC2_CRTC_STEREO_CONTROL 0x41AE
+#define mmCRTC2_CRTC_STEREO_FORCE_NEXT_EYE 0x419B
+#define mmCRTC2_CRTC_STEREO_STATUS 0x41AD
+#define mmCRTC2_CRTC_TEST_DEBUG_DATA 0x41C7
+#define mmCRTC2_CRTC_TEST_DEBUG_INDEX 0x41C6
+#define mmCRTC2_CRTC_TEST_PATTERN_COLOR 0x41BC
+#define mmCRTC2_CRTC_TEST_PATTERN_CONTROL 0x41BA
+#define mmCRTC2_CRTC_TEST_PATTERN_PARAMETERS 0x41BB
+#define mmCRTC2_CRTC_TRIGA_CNTL 0x4194
+#define mmCRTC2_CRTC_TRIGA_MANUAL_TRIG 0x4195
+#define mmCRTC2_CRTC_TRIGB_CNTL 0x4196
+#define mmCRTC2_CRTC_TRIGB_MANUAL_TRIG 0x4197
+#define mmCRTC2_CRTC_UPDATE_LOCK 0x41B5
+#define mmCRTC2_CRTC_VBI_END 0x4186
+#define mmCRTC2_CRTC_V_BLANK_START_END 0x418D
+#define mmCRTC2_CRTC_VERT_SYNC_CONTROL 0x41AC
+#define mmCRTC2_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x41B7
+#define mmCRTC2_CRTC_V_SYNC_A 0x418E
+#define mmCRTC2_CRTC_V_SYNC_A_CNTL 0x418F
+#define mmCRTC2_CRTC_V_SYNC_B 0x4190
+#define mmCRTC2_CRTC_V_SYNC_B_CNTL 0x4191
+#define mmCRTC2_CRTC_VSYNC_NOM_INT_STATUS 0x418C
+#define mmCRTC2_CRTC_V_TOTAL 0x4187
+#define mmCRTC2_CRTC_V_TOTAL_CONTROL 0x418A
+#define mmCRTC2_CRTC_V_TOTAL_INT_STATUS 0x418B
+#define mmCRTC2_CRTC_V_TOTAL_MAX 0x4189
+#define mmCRTC2_CRTC_V_TOTAL_MIN 0x4188
+#define mmCRTC2_CRTC_V_UPDATE_INT_STATUS 0x41C4
+#define mmCRTC2_DCFE_DBG_SEL 0x417E
+#define mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL 0x417F
+#define mmCRTC2_MASTER_UPDATE_LOCK 0x41BD
+#define mmCRTC2_MASTER_UPDATE_MODE 0x41BE
+#define mmCRTC2_PIXEL_RATE_CNTL 0x0148
+#define mmCRTC3_CRTC_3D_STRUCTURE_CONTROL 0x4478
+#define mmCRTC3_CRTC_ALLOW_STOP_OFF_V_CNT 0x44C3
+#define mmCRTC3_CRTC_BLACK_COLOR 0x44A2
+#define mmCRTC3_CRTC_BLANK_CONTROL 0x449D
+#define mmCRTC3_CRTC_BLANK_DATA_COLOR 0x44A1
+#define mmCRTC3_CRTC_CONTROL 0x449C
+#define mmCRTC3_CRTC_COUNT_CONTROL 0x44A9
+#define mmCRTC3_CRTC_COUNT_RESET 0x44AA
+#define mmCRTC3_CRTC_DCFE_CLOCK_CONTROL 0x447C
+#define mmCRTC3_CRTC_DOUBLE_BUFFER_CONTROL 0x44B6
+#define mmCRTC3_CRTC_DTMTEST_CNTL 0x4492
+#define mmCRTC3_CRTC_DTMTEST_STATUS_POSITION 0x4493
+#define mmCRTC3_CRTC_FLOW_CONTROL 0x4499
+#define mmCRTC3_CRTC_FORCE_COUNT_NOW_CNTL 0x4498
+#define mmCRTC3_CRTC_GSL_CONTROL 0x447B
+#define mmCRTC3_CRTC_GSL_VSYNC_GAP 0x4479
+#define mmCRTC3_CRTC_GSL_WINDOW 0x447A
+#define mmCRTC3_CRTC_H_BLANK_EARLY_NUM 0x447D
+#define mmCRTC3_CRTC_H_BLANK_START_END 0x4481
+#define mmCRTC3_CRTC_H_SYNC_A 0x4482
+#define mmCRTC3_CRTC_H_SYNC_A_CNTL 0x4483
+#define mmCRTC3_CRTC_H_SYNC_B 0x4484
+#define mmCRTC3_CRTC_H_SYNC_B_CNTL 0x4485
+#define mmCRTC3_CRTC_H_TOTAL 0x4480
+#define mmCRTC3_CRTC_INTERLACE_CONTROL 0x449E
+#define mmCRTC3_CRTC_INTERLACE_STATUS 0x449F
+#define mmCRTC3_CRTC_INTERRUPT_CONTROL 0x44B4
+#define mmCRTC3_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x44AB
+#define mmCRTC3_CRTC_MASTER_EN 0x44C2
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT 0x44BF
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x44C0
+#define mmCRTC3_CRTC_MVP_STATUS 0x44C1
+#define mmCRTC3_CRTC_NOM_VERT_POSITION 0x44A5
+#define mmCRTC3_CRTC_OVERSCAN_COLOR 0x44A0
+#define mmCRTC3_CRTC_SNAPSHOT_CONTROL 0x44B0
+#define mmCRTC3_CRTC_SNAPSHOT_FRAME 0x44B2
+#define mmCRTC3_CRTC_SNAPSHOT_POSITION 0x44B1
+#define mmCRTC3_CRTC_SNAPSHOT_STATUS 0x44AF
+#define mmCRTC3_CRTC_START_LINE_CONTROL 0x44B3
+#define mmCRTC3_CRTC_STATUS 0x44A3
+#define mmCRTC3_CRTC_STATUS_FRAME_COUNT 0x44A6
+#define mmCRTC3_CRTC_STATUS_HV_COUNT 0x44A8
+#define mmCRTC3_CRTC_STATUS_POSITION 0x44A4
+#define mmCRTC3_CRTC_STATUS_VF_COUNT 0x44A7
+#define mmCRTC3_CRTC_STEREO_CONTROL 0x44AE
+#define mmCRTC3_CRTC_STEREO_FORCE_NEXT_EYE 0x449B
+#define mmCRTC3_CRTC_STEREO_STATUS 0x44AD
+#define mmCRTC3_CRTC_TEST_DEBUG_DATA 0x44C7
+#define mmCRTC3_CRTC_TEST_DEBUG_INDEX 0x44C6
+#define mmCRTC3_CRTC_TEST_PATTERN_COLOR 0x44BC
+#define mmCRTC3_CRTC_TEST_PATTERN_CONTROL 0x44BA
+#define mmCRTC3_CRTC_TEST_PATTERN_PARAMETERS 0x44BB
+#define mmCRTC3_CRTC_TRIGA_CNTL 0x4494
+#define mmCRTC3_CRTC_TRIGA_MANUAL_TRIG 0x4495
+#define mmCRTC3_CRTC_TRIGB_CNTL 0x4496
+#define mmCRTC3_CRTC_TRIGB_MANUAL_TRIG 0x4497
+#define mmCRTC3_CRTC_UPDATE_LOCK 0x44B5
+#define mmCRTC3_CRTC_VBI_END 0x4486
+#define mmCRTC3_CRTC_V_BLANK_START_END 0x448D
+#define mmCRTC3_CRTC_VERT_SYNC_CONTROL 0x44AC
+#define mmCRTC3_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x44B7
+#define mmCRTC3_CRTC_V_SYNC_A 0x448E
+#define mmCRTC3_CRTC_V_SYNC_A_CNTL 0x448F
+#define mmCRTC3_CRTC_V_SYNC_B 0x4490
+#define mmCRTC3_CRTC_V_SYNC_B_CNTL 0x4491
+#define mmCRTC3_CRTC_VSYNC_NOM_INT_STATUS 0x448C
+#define mmCRTC3_CRTC_V_TOTAL 0x4487
+#define mmCRTC3_CRTC_V_TOTAL_CONTROL 0x448A
+#define mmCRTC3_CRTC_V_TOTAL_INT_STATUS 0x448B
+#define mmCRTC3_CRTC_V_TOTAL_MAX 0x4489
+#define mmCRTC3_CRTC_V_TOTAL_MIN 0x4488
+#define mmCRTC3_CRTC_V_UPDATE_INT_STATUS 0x44C4
+#define mmCRTC3_DCFE_DBG_SEL 0x447E
+#define mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL 0x447F
+#define mmCRTC_3D_STRUCTURE_CONTROL 0x1B78
+#define mmCRTC3_MASTER_UPDATE_LOCK 0x44BD
+#define mmCRTC3_MASTER_UPDATE_MODE 0x44BE
+#define mmCRTC3_PIXEL_RATE_CNTL 0x014C
+#define mmCRTC4_CRTC_3D_STRUCTURE_CONTROL 0x4778
+#define mmCRTC4_CRTC_ALLOW_STOP_OFF_V_CNT 0x47C3
+#define mmCRTC4_CRTC_BLACK_COLOR 0x47A2
+#define mmCRTC4_CRTC_BLANK_CONTROL 0x479D
+#define mmCRTC4_CRTC_BLANK_DATA_COLOR 0x47A1
+#define mmCRTC4_CRTC_CONTROL 0x479C
+#define mmCRTC4_CRTC_COUNT_CONTROL 0x47A9
+#define mmCRTC4_CRTC_COUNT_RESET 0x47AA
+#define mmCRTC4_CRTC_DCFE_CLOCK_CONTROL 0x477C
+#define mmCRTC4_CRTC_DOUBLE_BUFFER_CONTROL 0x47B6
+#define mmCRTC4_CRTC_DTMTEST_CNTL 0x4792
+#define mmCRTC4_CRTC_DTMTEST_STATUS_POSITION 0x4793
+#define mmCRTC4_CRTC_FLOW_CONTROL 0x4799
+#define mmCRTC4_CRTC_FORCE_COUNT_NOW_CNTL 0x4798
+#define mmCRTC4_CRTC_GSL_CONTROL 0x477B
+#define mmCRTC4_CRTC_GSL_VSYNC_GAP 0x4779
+#define mmCRTC4_CRTC_GSL_WINDOW 0x477A
+#define mmCRTC4_CRTC_H_BLANK_EARLY_NUM 0x477D
+#define mmCRTC4_CRTC_H_BLANK_START_END 0x4781
+#define mmCRTC4_CRTC_H_SYNC_A 0x4782
+#define mmCRTC4_CRTC_H_SYNC_A_CNTL 0x4783
+#define mmCRTC4_CRTC_H_SYNC_B 0x4784
+#define mmCRTC4_CRTC_H_SYNC_B_CNTL 0x4785
+#define mmCRTC4_CRTC_H_TOTAL 0x4780
+#define mmCRTC4_CRTC_INTERLACE_CONTROL 0x479E
+#define mmCRTC4_CRTC_INTERLACE_STATUS 0x479F
+#define mmCRTC4_CRTC_INTERRUPT_CONTROL 0x47B4
+#define mmCRTC4_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x47AB
+#define mmCRTC4_CRTC_MASTER_EN 0x47C2
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT 0x47BF
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x47C0
+#define mmCRTC4_CRTC_MVP_STATUS 0x47C1
+#define mmCRTC4_CRTC_NOM_VERT_POSITION 0x47A5
+#define mmCRTC4_CRTC_OVERSCAN_COLOR 0x47A0
+#define mmCRTC4_CRTC_SNAPSHOT_CONTROL 0x47B0
+#define mmCRTC4_CRTC_SNAPSHOT_FRAME 0x47B2
+#define mmCRTC4_CRTC_SNAPSHOT_POSITION 0x47B1
+#define mmCRTC4_CRTC_SNAPSHOT_STATUS 0x47AF
+#define mmCRTC4_CRTC_START_LINE_CONTROL 0x47B3
+#define mmCRTC4_CRTC_STATUS 0x47A3
+#define mmCRTC4_CRTC_STATUS_FRAME_COUNT 0x47A6
+#define mmCRTC4_CRTC_STATUS_HV_COUNT 0x47A8
+#define mmCRTC4_CRTC_STATUS_POSITION 0x47A4
+#define mmCRTC4_CRTC_STATUS_VF_COUNT 0x47A7
+#define mmCRTC4_CRTC_STEREO_CONTROL 0x47AE
+#define mmCRTC4_CRTC_STEREO_FORCE_NEXT_EYE 0x479B
+#define mmCRTC4_CRTC_STEREO_STATUS 0x47AD
+#define mmCRTC4_CRTC_TEST_DEBUG_DATA 0x47C7
+#define mmCRTC4_CRTC_TEST_DEBUG_INDEX 0x47C6
+#define mmCRTC4_CRTC_TEST_PATTERN_COLOR 0x47BC
+#define mmCRTC4_CRTC_TEST_PATTERN_CONTROL 0x47BA
+#define mmCRTC4_CRTC_TEST_PATTERN_PARAMETERS 0x47BB
+#define mmCRTC4_CRTC_TRIGA_CNTL 0x4794
+#define mmCRTC4_CRTC_TRIGA_MANUAL_TRIG 0x4795
+#define mmCRTC4_CRTC_TRIGB_CNTL 0x4796
+#define mmCRTC4_CRTC_TRIGB_MANUAL_TRIG 0x4797
+#define mmCRTC4_CRTC_UPDATE_LOCK 0x47B5
+#define mmCRTC4_CRTC_VBI_END 0x4786
+#define mmCRTC4_CRTC_V_BLANK_START_END 0x478D
+#define mmCRTC4_CRTC_VERT_SYNC_CONTROL 0x47AC
+#define mmCRTC4_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x47B7
+#define mmCRTC4_CRTC_V_SYNC_A 0x478E
+#define mmCRTC4_CRTC_V_SYNC_A_CNTL 0x478F
+#define mmCRTC4_CRTC_V_SYNC_B 0x4790
+#define mmCRTC4_CRTC_V_SYNC_B_CNTL 0x4791
+#define mmCRTC4_CRTC_VSYNC_NOM_INT_STATUS 0x478C
+#define mmCRTC4_CRTC_V_TOTAL 0x4787
+#define mmCRTC4_CRTC_V_TOTAL_CONTROL 0x478A
+#define mmCRTC4_CRTC_V_TOTAL_INT_STATUS 0x478B
+#define mmCRTC4_CRTC_V_TOTAL_MAX 0x4789
+#define mmCRTC4_CRTC_V_TOTAL_MIN 0x4788
+#define mmCRTC4_CRTC_V_UPDATE_INT_STATUS 0x47C4
+#define mmCRTC4_DCFE_DBG_SEL 0x477E
+#define mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL 0x477F
+#define mmCRTC4_MASTER_UPDATE_LOCK 0x47BD
+#define mmCRTC4_MASTER_UPDATE_MODE 0x47BE
+#define mmCRTC4_PIXEL_RATE_CNTL 0x0150
+#define mmCRTC5_CRTC_3D_STRUCTURE_CONTROL 0x4A78
+#define mmCRTC5_CRTC_ALLOW_STOP_OFF_V_CNT 0x4AC3
+#define mmCRTC5_CRTC_BLACK_COLOR 0x4AA2
+#define mmCRTC5_CRTC_BLANK_CONTROL 0x4A9D
+#define mmCRTC5_CRTC_BLANK_DATA_COLOR 0x4AA1
+#define mmCRTC5_CRTC_CONTROL 0x4A9C
+#define mmCRTC5_CRTC_COUNT_CONTROL 0x4AA9
+#define mmCRTC5_CRTC_COUNT_RESET 0x4AAA
+#define mmCRTC5_CRTC_DCFE_CLOCK_CONTROL 0x4A7C
+#define mmCRTC5_CRTC_DOUBLE_BUFFER_CONTROL 0x4AB6
+#define mmCRTC5_CRTC_DTMTEST_CNTL 0x4A92
+#define mmCRTC5_CRTC_DTMTEST_STATUS_POSITION 0x4A93
+#define mmCRTC5_CRTC_FLOW_CONTROL 0x4A99
+#define mmCRTC5_CRTC_FORCE_COUNT_NOW_CNTL 0x4A98
+#define mmCRTC5_CRTC_GSL_CONTROL 0x4A7B
+#define mmCRTC5_CRTC_GSL_VSYNC_GAP 0x4A79
+#define mmCRTC5_CRTC_GSL_WINDOW 0x4A7A
+#define mmCRTC5_CRTC_H_BLANK_EARLY_NUM 0x4A7D
+#define mmCRTC5_CRTC_H_BLANK_START_END 0x4A81
+#define mmCRTC5_CRTC_H_SYNC_A 0x4A82
+#define mmCRTC5_CRTC_H_SYNC_A_CNTL 0x4A83
+#define mmCRTC5_CRTC_H_SYNC_B 0x4A84
+#define mmCRTC5_CRTC_H_SYNC_B_CNTL 0x4A85
+#define mmCRTC5_CRTC_H_TOTAL 0x4A80
+#define mmCRTC5_CRTC_INTERLACE_CONTROL 0x4A9E
+#define mmCRTC5_CRTC_INTERLACE_STATUS 0x4A9F
+#define mmCRTC5_CRTC_INTERRUPT_CONTROL 0x4AB4
+#define mmCRTC5_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x4AAB
+#define mmCRTC5_CRTC_MASTER_EN 0x4AC2
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT 0x4ABF
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x4AC0
+#define mmCRTC5_CRTC_MVP_STATUS 0x4AC1
+#define mmCRTC5_CRTC_NOM_VERT_POSITION 0x4AA5
+#define mmCRTC5_CRTC_OVERSCAN_COLOR 0x4AA0
+#define mmCRTC5_CRTC_SNAPSHOT_CONTROL 0x4AB0
+#define mmCRTC5_CRTC_SNAPSHOT_FRAME 0x4AB2
+#define mmCRTC5_CRTC_SNAPSHOT_POSITION 0x4AB1
+#define mmCRTC5_CRTC_SNAPSHOT_STATUS 0x4AAF
+#define mmCRTC5_CRTC_START_LINE_CONTROL 0x4AB3
+#define mmCRTC5_CRTC_STATUS 0x4AA3
+#define mmCRTC5_CRTC_STATUS_FRAME_COUNT 0x4AA6
+#define mmCRTC5_CRTC_STATUS_HV_COUNT 0x4AA8
+#define mmCRTC5_CRTC_STATUS_POSITION 0x4AA4
+#define mmCRTC5_CRTC_STATUS_VF_COUNT 0x4AA7
+#define mmCRTC5_CRTC_STEREO_CONTROL 0x4AAE
+#define mmCRTC5_CRTC_STEREO_FORCE_NEXT_EYE 0x4A9B
+#define mmCRTC5_CRTC_STEREO_STATUS 0x4AAD
+#define mmCRTC5_CRTC_TEST_DEBUG_DATA 0x4AC7
+#define mmCRTC5_CRTC_TEST_DEBUG_INDEX 0x4AC6
+#define mmCRTC5_CRTC_TEST_PATTERN_COLOR 0x4ABC
+#define mmCRTC5_CRTC_TEST_PATTERN_CONTROL 0x4ABA
+#define mmCRTC5_CRTC_TEST_PATTERN_PARAMETERS 0x4ABB
+#define mmCRTC5_CRTC_TRIGA_CNTL 0x4A94
+#define mmCRTC5_CRTC_TRIGA_MANUAL_TRIG 0x4A95
+#define mmCRTC5_CRTC_TRIGB_CNTL 0x4A96
+#define mmCRTC5_CRTC_TRIGB_MANUAL_TRIG 0x4A97
+#define mmCRTC5_CRTC_UPDATE_LOCK 0x4AB5
+#define mmCRTC5_CRTC_VBI_END 0x4A86
+#define mmCRTC5_CRTC_V_BLANK_START_END 0x4A8D
+#define mmCRTC5_CRTC_VERT_SYNC_CONTROL 0x4AAC
+#define mmCRTC5_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x4AB7
+#define mmCRTC5_CRTC_V_SYNC_A 0x4A8E
+#define mmCRTC5_CRTC_V_SYNC_A_CNTL 0x4A8F
+#define mmCRTC5_CRTC_V_SYNC_B 0x4A90
+#define mmCRTC5_CRTC_V_SYNC_B_CNTL 0x4A91
+#define mmCRTC5_CRTC_VSYNC_NOM_INT_STATUS 0x4A8C
+#define mmCRTC5_CRTC_V_TOTAL 0x4A87
+#define mmCRTC5_CRTC_V_TOTAL_CONTROL 0x4A8A
+#define mmCRTC5_CRTC_V_TOTAL_INT_STATUS 0x4A8B
+#define mmCRTC5_CRTC_V_TOTAL_MAX 0x4A89
+#define mmCRTC5_CRTC_V_TOTAL_MIN 0x4A88
+#define mmCRTC5_CRTC_V_UPDATE_INT_STATUS 0x4AC4
+#define mmCRTC5_DCFE_DBG_SEL 0x4A7E
+#define mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL 0x4A7F
+#define mmCRTC5_MASTER_UPDATE_LOCK 0x4ABD
+#define mmCRTC5_MASTER_UPDATE_MODE 0x4ABE
+#define mmCRTC5_PIXEL_RATE_CNTL 0x0154
+#define mmCRTC8_DATA 0x00ED
+#define mmCRTC8_IDX 0x00ED
+#define mmCRTC_ALLOW_STOP_OFF_V_CNT 0x1BC3
+#define mmCRTC_BLACK_COLOR 0x1BA2
+#define mmCRTC_BLANK_CONTROL 0x1B9D
+#define mmCRTC_BLANK_DATA_COLOR 0x1BA1
+#define mmCRTC_CONTROL 0x1B9C
+#define mmCRTC_COUNT_CONTROL 0x1BA9
+#define mmCRTC_COUNT_RESET 0x1BAA
+#define mmCRTC_DCFE_CLOCK_CONTROL 0x1B7C
+#define mmCRTC_DOUBLE_BUFFER_CONTROL 0x1BB6
+#define mmCRTC_DTMTEST_CNTL 0x1B92
+#define mmCRTC_DTMTEST_STATUS_POSITION 0x1B93
+#define mmCRTC_FLOW_CONTROL 0x1B99
+#define mmCRTC_FORCE_COUNT_NOW_CNTL 0x1B98
+#define mmCRTC_GSL_CONTROL 0x1B7B
+#define mmCRTC_GSL_VSYNC_GAP 0x1B79
+#define mmCRTC_GSL_WINDOW 0x1B7A
+#define mmCRTC_H_BLANK_EARLY_NUM 0x1B7D
+#define mmCRTC_H_BLANK_START_END 0x1B81
+#define mmCRTC_H_SYNC_A 0x1B82
+#define mmCRTC_H_SYNC_A_CNTL 0x1B83
+#define mmCRTC_H_SYNC_B 0x1B84
+#define mmCRTC_H_SYNC_B_CNTL 0x1B85
+#define mmCRTC_H_TOTAL 0x1B80
+#define mmCRTC_INTERLACE_CONTROL 0x1B9E
+#define mmCRTC_INTERLACE_STATUS 0x1B9F
+#define mmCRTC_INTERRUPT_CONTROL 0x1BB4
+#define mmCRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1BAB
+#define mmCRTC_MASTER_EN 0x1BC2
+#define mmCRTC_MVP_INBAND_CNTL_INSERT 0x1BBF
+#define mmCRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1BC0
+#define mmCRTC_MVP_STATUS 0x1BC1
+#define mmCRTC_NOM_VERT_POSITION 0x1BA5
+#define mmCRTC_OVERSCAN_COLOR 0x1BA0
+#define mmCRTC_SNAPSHOT_CONTROL 0x1BB0
+#define mmCRTC_SNAPSHOT_FRAME 0x1BB2
+#define mmCRTC_SNAPSHOT_POSITION 0x1BB1
+#define mmCRTC_SNAPSHOT_STATUS 0x1BAF
+#define mmCRTC_START_LINE_CONTROL 0x1BB3
+#define mmCRTC_STATUS 0x1BA3
+#define mmCRTC_STATUS_FRAME_COUNT 0x1BA6
+#define mmCRTC_STATUS_HV_COUNT 0x1BA8
+#define mmCRTC_STATUS_POSITION 0x1BA4
+#define mmCRTC_STATUS_VF_COUNT 0x1BA7
+#define mmCRTC_STEREO_CONTROL 0x1BAE
+#define mmCRTC_STEREO_FORCE_NEXT_EYE 0x1B9B
+#define mmCRTC_STEREO_STATUS 0x1BAD
+#define mmCRTC_TEST_DEBUG_DATA 0x1BC7
+#define mmCRTC_TEST_DEBUG_INDEX 0x1BC6
+#define mmCRTC_TEST_PATTERN_COLOR 0x1BBC
+#define mmCRTC_TEST_PATTERN_CONTROL 0x1BBA
+#define mmCRTC_TEST_PATTERN_PARAMETERS 0x1BBB
+#define mmCRTC_TRIGA_CNTL 0x1B94
+#define mmCRTC_TRIGA_MANUAL_TRIG 0x1B95
+#define mmCRTC_TRIGB_CNTL 0x1B96
+#define mmCRTC_TRIGB_MANUAL_TRIG 0x1B97
+#define mmCRTC_UPDATE_LOCK 0x1BB5
+#define mmCRTC_VBI_END 0x1B86
+#define mmCRTC_V_BLANK_START_END 0x1B8D
+#define mmCRTC_VERT_SYNC_CONTROL 0x1BAC
+#define mmCRTC_VGA_PARAMETER_CAPTURE_MODE 0x1BB7
+#define mmCRTC_V_SYNC_A 0x1B8E
+#define mmCRTC_V_SYNC_A_CNTL 0x1B8F
+#define mmCRTC_V_SYNC_B 0x1B90
+#define mmCRTC_V_SYNC_B_CNTL 0x1B91
+#define mmCRTC_VSYNC_NOM_INT_STATUS 0x1B8C
+#define mmCRTC_V_TOTAL 0x1B87
+#define mmCRTC_V_TOTAL_CONTROL 0x1B8A
+#define mmCRTC_V_TOTAL_INT_STATUS 0x1B8B
+#define mmCRTC_V_TOTAL_MAX 0x1B89
+#define mmCRTC_V_TOTAL_MIN 0x1B88
+#define mmCRTC_V_UPDATE_INT_STATUS 0x1BC4
+#define mmCUR_COLOR1 0x1A6C
+#define mmCUR_COLOR2 0x1A6D
+#define mmCUR_CONTROL 0x1A66
+#define mmCUR_HOT_SPOT 0x1A6B
+#define mmCUR_POSITION 0x1A6A
+#define mmCUR_REQUEST_FILTER_CNTL 0x1A99
+#define mmCUR_SIZE 0x1A68
+#define mmCUR_SURFACE_ADDRESS 0x1A67
+#define mmCUR_SURFACE_ADDRESS_HIGH 0x1A69
+#define mmCUR_UPDATE 0x1A6E
+#define mmD1VGA_CONTROL 0x00CC
+#define mmD2VGA_CONTROL 0x00CE
+#define mmD3VGA_CONTROL 0x00F8
+#define mmD4VGA_CONTROL 0x00F9
+#define mmD5VGA_CONTROL 0x00FA
+#define mmD6VGA_CONTROL 0x00FB
+#define mmDAC_AUTODETECT_CONTROL 0x19EE
+#define mmDAC_AUTODETECT_CONTROL2 0x19EF
+#define mmDAC_AUTODETECT_CONTROL3 0x19F0
+#define mmDAC_AUTODETECT_INT_CONTROL 0x19F2
+#define mmDAC_AUTODETECT_STATUS 0x19F1
+#define mmDAC_CLK_ENABLE 0x0128
+#define mmDAC_COMPARATOR_ENABLE 0x19F7
+#define mmDAC_COMPARATOR_OUTPUT 0x19F8
+#define mmDAC_CONTROL 0x19F6
+#define mmDAC_CRC_CONTROL 0x19E7
+#define mmDAC_CRC_EN 0x19E6
+#define mmDAC_CRC_SIG_CONTROL 0x19EB
+#define mmDAC_CRC_SIG_CONTROL_MASK 0x19E9
+#define mmDAC_CRC_SIG_RGB 0x19EA
+#define mmDAC_CRC_SIG_RGB_MASK 0x19E8
+#define mmDAC_DATA 0x00F2
+#define mmDAC_DFT_CONFIG 0x19FA
+#define mmDAC_ENABLE 0x19E4
+#define mmDAC_FIFO_STATUS 0x19FB
+#define mmDAC_FORCE_DATA 0x19F4
+#define mmDAC_FORCE_OUTPUT_CNTL 0x19F3
+#define mmDAC_MACRO_CNTL_RESERVED0 0x19FC
+#define mmDAC_MACRO_CNTL_RESERVED1 0x19FD
+#define mmDAC_MACRO_CNTL_RESERVED2 0x19FE
+#define mmDAC_MACRO_CNTL_RESERVED3 0x19FF
+#define mmDAC_MASK 0x00F1
+#define mmDAC_POWERDOWN 0x19F5
+#define mmDAC_PWR_CNTL 0x19F9
+#define mmDAC_R_INDEX 0x00F1
+#define mmDAC_SOURCE_SELECT 0x19E5
+#define mmDAC_STEREOSYNC_SELECT 0x19ED
+#define mmDAC_SYNC_TRISTATE_CONTROL 0x19EC
+#define mmDAC_W_INDEX 0x00F2
+#define mmDC_ABM1_ACE_CNTL_MISC 0x1641
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_0 0x163A
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_1 0x163B
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_2 0x163C
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_3 0x163D
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_4 0x163E
+#define mmDC_ABM1_ACE_THRES_12 0x163F
+#define mmDC_ABM1_ACE_THRES_34 0x1640
+#define mmDC_ABM1_BL_MASTER_LOCK 0x169C
+#define mmDC_ABM1_CNTL 0x1638
+#define mmDC_ABM1_DEBUG_MISC 0x1649
+#define mmDC_ABM1_HG_BIN_1_32_SHIFT_FLAG 0x1656
+#define mmDC_ABM1_HG_BIN_17_24_SHIFT_INDEX 0x1659
+#define mmDC_ABM1_HG_BIN_1_8_SHIFT_INDEX 0x1657
+#define mmDC_ABM1_HG_BIN_25_32_SHIFT_INDEX 0x165A
+#define mmDC_ABM1_HG_BIN_9_16_SHIFT_INDEX 0x1658
+#define mmDC_ABM1_HGLS_REG_READ_PROGRESS 0x164A
+#define mmDC_ABM1_HG_MISC_CTRL 0x164B
+#define mmDC_ABM1_HG_RESULT_10 0x1664
+#define mmDC_ABM1_HG_RESULT_1 0x165B
+#define mmDC_ABM1_HG_RESULT_11 0x1665
+#define mmDC_ABM1_HG_RESULT_12 0x1666
+#define mmDC_ABM1_HG_RESULT_13 0x1667
+#define mmDC_ABM1_HG_RESULT_14 0x1668
+#define mmDC_ABM1_HG_RESULT_15 0x1669
+#define mmDC_ABM1_HG_RESULT_16 0x166A
+#define mmDC_ABM1_HG_RESULT_17 0x166B
+#define mmDC_ABM1_HG_RESULT_18 0x166C
+#define mmDC_ABM1_HG_RESULT_19 0x166D
+#define mmDC_ABM1_HG_RESULT_20 0x166E
+#define mmDC_ABM1_HG_RESULT_2 0x165C
+#define mmDC_ABM1_HG_RESULT_21 0x166F
+#define mmDC_ABM1_HG_RESULT_22 0x1670
+#define mmDC_ABM1_HG_RESULT_23 0x1671
+#define mmDC_ABM1_HG_RESULT_24 0x1672
+#define mmDC_ABM1_HG_RESULT_3 0x165D
+#define mmDC_ABM1_HG_RESULT_4 0x165E
+#define mmDC_ABM1_HG_RESULT_5 0x165F
+#define mmDC_ABM1_HG_RESULT_6 0x1660
+#define mmDC_ABM1_HG_RESULT_7 0x1661
+#define mmDC_ABM1_HG_RESULT_8 0x1662
+#define mmDC_ABM1_HG_RESULT_9 0x1663
+#define mmDC_ABM1_HG_SAMPLE_RATE 0x1654
+#define mmDC_ABM1_IPCSC_COEFF_SEL 0x1639
+#define mmDC_ABM1_LS_FILTERED_MIN_MAX_LUMA 0x164E
+#define mmDC_ABM1_LS_MAX_PIXEL_VALUE_COUNT 0x1653
+#define mmDC_ABM1_LS_MIN_MAX_LUMA 0x164D
+#define mmDC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES 0x1651
+#define mmDC_ABM1_LS_MIN_PIXEL_VALUE_COUNT 0x1652
+#define mmDC_ABM1_LS_OVR_SCAN_BIN 0x1650
+#define mmDC_ABM1_LS_PIXEL_COUNT 0x164F
+#define mmDC_ABM1_LS_SAMPLE_RATE 0x1655
+#define mmDC_ABM1_LS_SUM_OF_LUMA 0x164C
+#define mmDC_ABM1_OVERSCAN_PIXEL_VALUE 0x169B
+#define mmDCCG_AUDIO_DTO0_MODULE 0x016D
+#define mmDCCG_AUDIO_DTO0_PHASE 0x016C
+#define mmDCCG_AUDIO_DTO1_MODULE 0x0171
+#define mmDCCG_AUDIO_DTO1_PHASE 0x0170
+#define mmDCCG_AUDIO_DTO_SOURCE 0x016B
+#define mmDCCG_CAC_STATUS 0x0137
+#define mmDCCG_GATE_DISABLE_CNTL 0x0134
+#define mmDCCG_GTC_CNTL 0x0120
+#define mmDCCG_GTC_CURRENT 0x0123
+#define mmDCCG_GTC_DTO_MODULO 0x0122
+#define mmDCCG_PERFMON_CNTL 0x0133
+#define mmDCCG_PLL0_PLL_ANALOG 0x1708
+#define mmDCCG_PLL0_PLL_CNTL 0x1707
+#define mmDCCG_PLL0_PLL_DEBUG_CNTL 0x170B
+#define mmDCCG_PLL0_PLL_DISPCLK_CURRENT_DTO_PHASE 0x170F
+#define mmDCCG_PLL0_PLL_DISPCLK_DTO_CNTL 0x170E
+#define mmDCCG_PLL0_PLL_DS_CNTL 0x1705
+#define mmDCCG_PLL0_PLL_FB_DIV 0x1701
+#define mmDCCG_PLL0_PLL_IDCLK_CNTL 0x1706
+#define mmDCCG_PLL0_PLL_POST_DIV 0x1702
+#define mmDCCG_PLL0_PLL_REF_DIV 0x1700
+#define mmDCCG_PLL0_PLL_SS_AMOUNT_DSFRAC 0x1703
+#define mmDCCG_PLL0_PLL_SS_CNTL 0x1704
+#define mmDCCG_PLL0_PLL_UNLOCK_DETECT_CNTL 0x170A
+#define mmDCCG_PLL0_PLL_UPDATE_CNTL 0x170D
+#define mmDCCG_PLL0_PLL_UPDATE_LOCK 0x170C
+#define mmDCCG_PLL0_PLL_VREG_CNTL 0x1709
+#define mmDCCG_PLL1_PLL_ANALOG 0x1718
+#define mmDCCG_PLL1_PLL_CNTL 0x1717
+#define mmDCCG_PLL1_PLL_DEBUG_CNTL 0x171B
+#define mmDCCG_PLL1_PLL_DISPCLK_CURRENT_DTO_PHASE 0x171F
+#define mmDCCG_PLL1_PLL_DISPCLK_DTO_CNTL 0x171E
+#define mmDCCG_PLL1_PLL_DS_CNTL 0x1715
+#define mmDCCG_PLL1_PLL_FB_DIV 0x1711
+#define mmDCCG_PLL1_PLL_IDCLK_CNTL 0x1716
+#define mmDCCG_PLL1_PLL_POST_DIV 0x1712
+#define mmDCCG_PLL1_PLL_REF_DIV 0x1710
+#define mmDCCG_PLL1_PLL_SS_AMOUNT_DSFRAC 0x1713
+#define mmDCCG_PLL1_PLL_SS_CNTL 0x1714
+#define mmDCCG_PLL1_PLL_UNLOCK_DETECT_CNTL 0x171A
+#define mmDCCG_PLL1_PLL_UPDATE_CNTL 0x171D
+#define mmDCCG_PLL1_PLL_UPDATE_LOCK 0x171C
+#define mmDCCG_PLL1_PLL_VREG_CNTL 0x1719
+#define mmDCCG_PLL2_PLL_ANALOG 0x1728
+#define mmDCCG_PLL2_PLL_CNTL 0x1727
+#define mmDCCG_PLL2_PLL_DEBUG_CNTL 0x172B
+#define mmDCCG_PLL2_PLL_DISPCLK_CURRENT_DTO_PHASE 0x172F
+#define mmDCCG_PLL2_PLL_DISPCLK_DTO_CNTL 0x172E
+#define mmDCCG_PLL2_PLL_DS_CNTL 0x1725
+#define mmDCCG_PLL2_PLL_FB_DIV 0x1721
+#define mmDCCG_PLL2_PLL_IDCLK_CNTL 0x1726
+#define mmDCCG_PLL2_PLL_POST_DIV 0x1722
+#define mmDCCG_PLL2_PLL_REF_DIV 0x1720
+#define mmDCCG_PLL2_PLL_SS_AMOUNT_DSFRAC 0x1723
+#define mmDCCG_PLL2_PLL_SS_CNTL 0x1724
+#define mmDCCG_PLL2_PLL_UNLOCK_DETECT_CNTL 0x172A
+#define mmDCCG_PLL2_PLL_UPDATE_CNTL 0x172D
+#define mmDCCG_PLL2_PLL_UPDATE_LOCK 0x172C
+#define mmDCCG_PLL2_PLL_VREG_CNTL 0x1729
+#define mmDCCG_SOFT_RESET 0x015F
+#define mmDCCG_TEST_CLK_SEL 0x017E
+#define mmDCCG_TEST_DEBUG_DATA 0x017D
+#define mmDCCG_TEST_DEBUG_INDEX 0x017C
+#define mmDCCG_VPCLK_CNTL 0x031F
+#define mmDCDEBUG_BUS_CLK1_SEL 0x1860
+#define mmDCDEBUG_BUS_CLK2_SEL 0x1861
+#define mmDCDEBUG_BUS_CLK3_SEL 0x1862
+#define mmDCDEBUG_BUS_CLK4_SEL 0x1863
+#define mmDCDEBUG_OUT_CNTL 0x186B
+#define mmDCDEBUG_OUT_DATA 0x186E
+#define mmDCDEBUG_OUT_PIN_OVERRIDE 0x186A
+#define mmDC_DMCU_SCRATCH 0x1618
+#define mmDC_DVODATA_CONFIG 0x1905
+#define mmDCFE0_SOFT_RESET 0x0158
+#define mmDCFE1_SOFT_RESET 0x0159
+#define mmDCFE2_SOFT_RESET 0x015A
+#define mmDCFE3_SOFT_RESET 0x015B
+#define mmDCFE4_SOFT_RESET 0x015C
+#define mmDCFE5_SOFT_RESET 0x015D
+#define mmDCFE_DBG_SEL 0x1B7E
+#define mmDCFE_MEM_LIGHT_SLEEP_CNTL 0x1B7F
+#define mmDC_GENERICA 0x1900
+#define mmDC_GENERICB 0x1901
+#define mmDC_GPIO_DDC1_A 0x194D
+#define mmDC_GPIO_DDC1_EN 0x194E
+#define mmDC_GPIO_DDC1_MASK 0x194C
+#define mmDC_GPIO_DDC1_Y 0x194F
+#define mmDC_GPIO_DDC2_A 0x1951
+#define mmDC_GPIO_DDC2_EN 0x1952
+#define mmDC_GPIO_DDC2_MASK 0x1950
+#define mmDC_GPIO_DDC2_Y 0x1953
+#define mmDC_GPIO_DDC3_A 0x1955
+#define mmDC_GPIO_DDC3_EN 0x1956
+#define mmDC_GPIO_DDC3_MASK 0x1954
+#define mmDC_GPIO_DDC3_Y 0x1957
+#define mmDC_GPIO_DDC4_A 0x1959
+#define mmDC_GPIO_DDC4_EN 0x195A
+#define mmDC_GPIO_DDC4_MASK 0x1958
+#define mmDC_GPIO_DDC4_Y 0x195B
+#define mmDC_GPIO_DDC5_A 0x195D
+#define mmDC_GPIO_DDC5_EN 0x195E
+#define mmDC_GPIO_DDC5_MASK 0x195C
+#define mmDC_GPIO_DDC5_Y 0x195F
+#define mmDC_GPIO_DDC6_A 0x1961
+#define mmDC_GPIO_DDC6_EN 0x1962
+#define mmDC_GPIO_DDC6_MASK 0x1960
+#define mmDC_GPIO_DDC6_Y 0x1963
+#define mmDC_GPIO_DDCVGA_A 0x1971
+#define mmDC_GPIO_DDCVGA_EN 0x1972
+#define mmDC_GPIO_DDCVGA_MASK 0x1970
+#define mmDC_GPIO_DDCVGA_Y 0x1973
+#define mmDC_GPIO_DEBUG 0x1904
+#define mmDC_GPIO_DVODATA_A 0x1949
+#define mmDC_GPIO_DVODATA_EN 0x194A
+#define mmDC_GPIO_DVODATA_MASK 0x1948
+#define mmDC_GPIO_DVODATA_Y 0x194B
+#define mmDC_GPIO_GENERIC_A 0x1945
+#define mmDC_GPIO_GENERIC_EN 0x1946
+#define mmDC_GPIO_GENERIC_MASK 0x1944
+#define mmDC_GPIO_GENERIC_Y 0x1947
+#define mmDC_GPIO_GENLK_A 0x1969
+#define mmDC_GPIO_GENLK_EN 0x196A
+#define mmDC_GPIO_GENLK_MASK 0x1968
+#define mmDC_GPIO_GENLK_Y 0x196B
+#define mmDC_GPIO_HPD_A 0x196D
+#define mmDC_GPIO_HPD_EN 0x196E
+#define mmDC_GPIO_HPD_MASK 0x196C
+#define mmDC_GPIO_HPD_Y 0x196F
+#define mmDC_GPIO_I2CPAD_A 0x1975
+#define mmDC_GPIO_I2CPAD_EN 0x1976
+#define mmDC_GPIO_I2CPAD_MASK 0x1974
+#define mmDC_GPIO_I2CPAD_STRENGTH 0x197A
+#define mmDC_GPIO_I2CPAD_Y 0x1977
+#define mmDC_GPIO_PAD_STRENGTH_1 0x1978
+#define mmDC_GPIO_PAD_STRENGTH_2 0x1979
+#define mmDC_GPIO_PWRSEQ_A 0x1941
+#define mmDC_GPIO_PWRSEQ_EN 0x1942
+#define mmDC_GPIO_PWRSEQ_MASK 0x1940
+#define mmDC_GPIO_PWRSEQ_Y 0x1943
+#define mmDC_GPIO_SYNCA_A 0x1965
+#define mmDC_GPIO_SYNCA_EN 0x1966
+#define mmDC_GPIO_SYNCA_MASK 0x1964
+#define mmDC_GPIO_SYNCA_Y 0x1967
+#define mmDC_GPU_TIMER_READ 0x1929
+#define mmDC_GPU_TIMER_READ_CNTL 0x192A
+#define mmDC_GPU_TIMER_START_POSITION_P_FLIP 0x1928
+#define mmDC_GPU_TIMER_START_POSITION_V_UPDATE 0x1927
+#define mmDC_HPD1_CONTROL 0x1809
+#define mmDC_HPD1_FAST_TRAIN_CNTL 0x1864
+#define mmDC_HPD1_INT_CONTROL 0x1808
+#define mmDC_HPD1_INT_STATUS 0x1807
+#define mmDC_HPD1_TOGGLE_FILT_CNTL 0x18BC
+#define mmDC_HPD2_CONTROL 0x180C
+#define mmDC_HPD2_FAST_TRAIN_CNTL 0x1865
+#define mmDC_HPD2_INT_CONTROL 0x180B
+#define mmDC_HPD2_INT_STATUS 0x180A
+#define mmDC_HPD2_TOGGLE_FILT_CNTL 0x18BD
+#define mmDC_HPD3_CONTROL 0x180F
+#define mmDC_HPD3_FAST_TRAIN_CNTL 0x1866
+#define mmDC_HPD3_INT_CONTROL 0x180E
+#define mmDC_HPD3_INT_STATUS 0x180D
+#define mmDC_HPD3_TOGGLE_FILT_CNTL 0x18BE
+#define mmDC_HPD4_CONTROL 0x1812
+#define mmDC_HPD4_FAST_TRAIN_CNTL 0x1867
+#define mmDC_HPD4_INT_CONTROL 0x1811
+#define mmDC_HPD4_INT_STATUS 0x1810
+#define mmDC_HPD4_TOGGLE_FILT_CNTL 0x18FC
+#define mmDC_HPD5_CONTROL 0x1815
+#define mmDC_HPD5_FAST_TRAIN_CNTL 0x1868
+#define mmDC_HPD5_INT_CONTROL 0x1814
+#define mmDC_HPD5_INT_STATUS 0x1813
+#define mmDC_HPD5_TOGGLE_FILT_CNTL 0x18FD
+#define mmDC_HPD6_CONTROL 0x1818
+#define mmDC_HPD6_FAST_TRAIN_CNTL 0x1869
+#define mmDC_HPD6_INT_CONTROL 0x1817
+#define mmDC_HPD6_INT_STATUS 0x1816
+#define mmDC_HPD6_TOGGLE_FILT_CNTL 0x18FE
+#define mmDC_I2C_ARBITRATION 0x181A
+#define mmDC_I2C_CONTROL 0x1819
+#define mmDC_I2C_DATA 0x1833
+#define mmDC_I2C_DDC1_HW_STATUS 0x181D
+#define mmDC_I2C_DDC1_SETUP 0x1824
+#define mmDC_I2C_DDC1_SPEED 0x1823
+#define mmDC_I2C_DDC2_HW_STATUS 0x181E
+#define mmDC_I2C_DDC2_SETUP 0x1826
+#define mmDC_I2C_DDC2_SPEED 0x1825
+#define mmDC_I2C_DDC3_HW_STATUS 0x181F
+#define mmDC_I2C_DDC3_SETUP 0x1828
+#define mmDC_I2C_DDC3_SPEED 0x1827
+#define mmDC_I2C_DDC4_HW_STATUS 0x1820
+#define mmDC_I2C_DDC4_SETUP 0x182A
+#define mmDC_I2C_DDC4_SPEED 0x1829
+#define mmDC_I2C_DDC5_HW_STATUS 0x1821
+#define mmDC_I2C_DDC5_SETUP 0x182C
+#define mmDC_I2C_DDC5_SPEED 0x182B
+#define mmDC_I2C_DDC6_HW_STATUS 0x1822
+#define mmDC_I2C_DDC6_SETUP 0x182E
+#define mmDC_I2C_DDC6_SPEED 0x182D
+#define mmDC_I2C_DDCVGA_HW_STATUS 0x1855
+#define mmDC_I2C_DDCVGA_SETUP 0x1857
+#define mmDC_I2C_DDCVGA_SPEED 0x1856
+#define mmDC_I2C_EDID_DETECT_CTRL 0x186F
+#define mmDC_I2C_INTERRUPT_CONTROL 0x181B
+#define mmDC_I2C_SW_STATUS 0x181C
+#define mmDC_I2C_TRANSACTION0 0x182F
+#define mmDC_I2C_TRANSACTION1 0x1830
+#define mmDC_I2C_TRANSACTION2 0x1831
+#define mmDC_I2C_TRANSACTION3 0x1832
+#define mmDCI_CLK_CNTL 0x031E
+#define mmDCI_CLK_RAMP_CNTL 0x0324
+#define mmDCI_DEBUG_CONFIG 0x0323
+#define mmDCI_MEM_PWR_CNTL 0x0326
+#define mmDCI_MEM_PWR_STATE 0x031B
+#define mmDCI_MEM_PWR_STATE2 0x0322
+#define mmDCIO_DEBUG 0x192E
+#define mmDCIO_GSL0_CNTL 0x1924
+#define mmDCIO_GSL1_CNTL 0x1925
+#define mmDCIO_GSL2_CNTL 0x1926
+#define mmDCIO_GSL_GENLK_PAD_CNTL 0x1922
+#define mmDCIO_GSL_SWAPLOCK_PAD_CNTL 0x1923
+#define mmDCIO_IMPCAL_CNTL_AB 0x190D
+#define mmDCIO_IMPCAL_CNTL_CD 0x1911
+#define mmDCIO_IMPCAL_CNTL_EF 0x1915
+#define mmDCIO_TEST_DEBUG_DATA 0x1930
+#define mmDCIO_TEST_DEBUG_INDEX 0x192F
+#define mmDCIO_UNIPHY0_UNIPHY_ANG_BIST_CNTL 0x198C
+#define mmDCIO_UNIPHY0_UNIPHY_CHANNEL_XBAR_CNTL 0x198E
+#define mmDCIO_UNIPHY0_UNIPHY_DATA_SYNCHRONIZATION 0x198A
+#define mmDCIO_UNIPHY0_UNIPHY_LINK_CNTL 0x198D
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_CONTROL1 0x1986
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_CONTROL2 0x1987
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_FBDIV 0x1985
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_SS_CNTL 0x1989
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_SS_STEP_SIZE 0x1988
+#define mmDCIO_UNIPHY0_UNIPHY_POWER_CONTROL 0x1984
+#define mmDCIO_UNIPHY0_UNIPHY_REG_TEST_OUTPUT 0x198B
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL1 0x1980
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL2 0x1981
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL3 0x1982
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL4 0x1983
+#define mmDCIO_UNIPHY1_UNIPHY_ANG_BIST_CNTL 0x199C
+#define mmDCIO_UNIPHY1_UNIPHY_CHANNEL_XBAR_CNTL 0x199E
+#define mmDCIO_UNIPHY1_UNIPHY_DATA_SYNCHRONIZATION 0x199A
+#define mmDCIO_UNIPHY1_UNIPHY_LINK_CNTL 0x199D
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_CONTROL1 0x1996
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_CONTROL2 0x1997
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_FBDIV 0x1995
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_SS_CNTL 0x1999
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_SS_STEP_SIZE 0x1998
+#define mmDCIO_UNIPHY1_UNIPHY_POWER_CONTROL 0x1994
+#define mmDCIO_UNIPHY1_UNIPHY_REG_TEST_OUTPUT 0x199B
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL1 0x1990
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL2 0x1991
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL3 0x1992
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL4 0x1993
+#define mmDCIO_UNIPHY2_UNIPHY_ANG_BIST_CNTL 0x19AC
+#define mmDCIO_UNIPHY2_UNIPHY_CHANNEL_XBAR_CNTL 0x19AE
+#define mmDCIO_UNIPHY2_UNIPHY_DATA_SYNCHRONIZATION 0x19AA
+#define mmDCIO_UNIPHY2_UNIPHY_LINK_CNTL 0x19AD
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_CONTROL1 0x19A6
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_CONTROL2 0x19A7
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_FBDIV 0x19A5
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_SS_CNTL 0x19A9
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_SS_STEP_SIZE 0x19A8
+#define mmDCIO_UNIPHY2_UNIPHY_POWER_CONTROL 0x19A4
+#define mmDCIO_UNIPHY2_UNIPHY_REG_TEST_OUTPUT 0x19AB
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL1 0x19A0
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL2 0x19A1
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL3 0x19A2
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL4 0x19A3
+#define mmDCIO_UNIPHY3_UNIPHY_ANG_BIST_CNTL 0x19BC
+#define mmDCIO_UNIPHY3_UNIPHY_CHANNEL_XBAR_CNTL 0x19BE
+#define mmDCIO_UNIPHY3_UNIPHY_DATA_SYNCHRONIZATION 0x19BA
+#define mmDCIO_UNIPHY3_UNIPHY_LINK_CNTL 0x19BD
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_CONTROL1 0x19B6
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_CONTROL2 0x19B7
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_FBDIV 0x19B5
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_SS_CNTL 0x19B9
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_SS_STEP_SIZE 0x19B8
+#define mmDCIO_UNIPHY3_UNIPHY_POWER_CONTROL 0x19B4
+#define mmDCIO_UNIPHY3_UNIPHY_REG_TEST_OUTPUT 0x19BB
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL1 0x19B0
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL2 0x19B1
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL3 0x19B2
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL4 0x19B3
+#define mmDCIO_UNIPHY4_UNIPHY_ANG_BIST_CNTL 0x19CC
+#define mmDCIO_UNIPHY4_UNIPHY_CHANNEL_XBAR_CNTL 0x19CE
+#define mmDCIO_UNIPHY4_UNIPHY_DATA_SYNCHRONIZATION 0x19CA
+#define mmDCIO_UNIPHY4_UNIPHY_LINK_CNTL 0x19CD
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_CONTROL1 0x19C6
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_CONTROL2 0x19C7
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_FBDIV 0x19C5
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_SS_CNTL 0x19C9
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_SS_STEP_SIZE 0x19C8
+#define mmDCIO_UNIPHY4_UNIPHY_POWER_CONTROL 0x19C4
+#define mmDCIO_UNIPHY4_UNIPHY_REG_TEST_OUTPUT 0x19CB
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL1 0x19C0
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL2 0x19C1
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL3 0x19C2
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL4 0x19C3
+#define mmDCIO_UNIPHY5_UNIPHY_ANG_BIST_CNTL 0x19DC
+#define mmDCIO_UNIPHY5_UNIPHY_CHANNEL_XBAR_CNTL 0x19DE
+#define mmDCIO_UNIPHY5_UNIPHY_DATA_SYNCHRONIZATION 0x19DA
+#define mmDCIO_UNIPHY5_UNIPHY_LINK_CNTL 0x19DD
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_CONTROL1 0x19D6
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_CONTROL2 0x19D7
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_FBDIV 0x19D5
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_SS_CNTL 0x19D9
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_SS_STEP_SIZE 0x19D8
+#define mmDCIO_UNIPHY5_UNIPHY_POWER_CONTROL 0x19D4
+#define mmDCIO_UNIPHY5_UNIPHY_REG_TEST_OUTPUT 0x19DB
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL1 0x19D0
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL2 0x19D1
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL3 0x19D2
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL4 0x19D3
+#define mmDCI_SOFT_RESET 0x015E
+#define mmDCI_TEST_DEBUG_DATA 0x0321
+#define mmDCI_TEST_DEBUG_INDEX 0x0320
+#define mmDC_LUT_30_COLOR 0x1A7C
+#define mmDC_LUT_AUTOFILL 0x1A7F
+#define mmDC_LUT_BLACK_OFFSET_BLUE 0x1A81
+#define mmDC_LUT_BLACK_OFFSET_GREEN 0x1A82
+#define mmDC_LUT_BLACK_OFFSET_RED 0x1A83
+#define mmDC_LUT_CONTROL 0x1A80
+#define mmDC_LUT_PWL_DATA 0x1A7B
+#define mmDC_LUT_RW_INDEX 0x1A79
+#define mmDC_LUT_RW_MODE 0x1A78
+#define mmDC_LUT_SEQ_COLOR 0x1A7A
+#define mmDC_LUT_VGA_ACCESS_ENABLE 0x1A7D
+#define mmDC_LUT_WHITE_OFFSET_BLUE 0x1A84
+#define mmDC_LUT_WHITE_OFFSET_GREEN 0x1A85
+#define mmDC_LUT_WHITE_OFFSET_RED 0x1A86
+#define mmDC_LUT_WRITE_EN_MASK 0x1A7E
+#define mmDC_MVP_LB_CONTROL 0x1ADB
+#define mmDCO_CLK_CNTL 0x192B
+#define mmDCO_CLK_RAMP_CNTL 0x192C
+#define mmDCO_LIGHT_SLEEP_DIS 0x1907
+#define mmDCO_MEM_POWER_STATE 0x1906
+#define mmDCO_SOFT_RESET 0x0167
+#define mmDCP0_COMM_MATRIXA_TRANS_C11_C12 0x1A43
+#define mmDCP0_COMM_MATRIXA_TRANS_C13_C14 0x1A44
+#define mmDCP0_COMM_MATRIXA_TRANS_C21_C22 0x1A45
+#define mmDCP0_COMM_MATRIXA_TRANS_C23_C24 0x1A46
+#define mmDCP0_COMM_MATRIXA_TRANS_C31_C32 0x1A47
+#define mmDCP0_COMM_MATRIXA_TRANS_C33_C34 0x1A48
+#define mmDCP0_COMM_MATRIXB_TRANS_C11_C12 0x1A49
+#define mmDCP0_COMM_MATRIXB_TRANS_C13_C14 0x1A4A
+#define mmDCP0_COMM_MATRIXB_TRANS_C21_C22 0x1A4B
+#define mmDCP0_COMM_MATRIXB_TRANS_C23_C24 0x1A4C
+#define mmDCP0_COMM_MATRIXB_TRANS_C31_C32 0x1A4D
+#define mmDCP0_COMM_MATRIXB_TRANS_C33_C34 0x1A4E
+#define mmDCP0_CUR_COLOR1 0x1A6C
+#define mmDCP0_CUR_COLOR2 0x1A6D
+#define mmDCP0_CUR_CONTROL 0x1A66
+#define mmDCP0_CUR_HOT_SPOT 0x1A6B
+#define mmDCP0_CUR_POSITION 0x1A6A
+#define mmDCP0_CUR_REQUEST_FILTER_CNTL 0x1A99
+#define mmDCP0_CUR_SIZE 0x1A68
+#define mmDCP0_CUR_SURFACE_ADDRESS 0x1A67
+#define mmDCP0_CUR_SURFACE_ADDRESS_HIGH 0x1A69
+#define mmDCP0_CUR_UPDATE 0x1A6E
+#define mmDCP0_DC_LUT_30_COLOR 0x1A7C
+#define mmDCP0_DC_LUT_AUTOFILL 0x1A7F
+#define mmDCP0_DC_LUT_BLACK_OFFSET_BLUE 0x1A81
+#define mmDCP0_DC_LUT_BLACK_OFFSET_GREEN 0x1A82
+#define mmDCP0_DC_LUT_BLACK_OFFSET_RED 0x1A83
+#define mmDCP0_DC_LUT_CONTROL 0x1A80
+#define mmDCP0_DC_LUT_PWL_DATA 0x1A7B
+#define mmDCP0_DC_LUT_RW_INDEX 0x1A79
+#define mmDCP0_DC_LUT_RW_MODE 0x1A78
+#define mmDCP0_DC_LUT_SEQ_COLOR 0x1A7A
+#define mmDCP0_DC_LUT_VGA_ACCESS_ENABLE 0x1A7D
+#define mmDCP0_DC_LUT_WHITE_OFFSET_BLUE 0x1A84
+#define mmDCP0_DC_LUT_WHITE_OFFSET_GREEN 0x1A85
+#define mmDCP0_DC_LUT_WHITE_OFFSET_RED 0x1A86
+#define mmDCP0_DC_LUT_WRITE_EN_MASK 0x1A7E
+#define mmDCP0_DCP_CRC_CONTROL 0x1A87
+#define mmDCP0_DCP_CRC_CURRENT 0x1A89
+#define mmDCP0_DCP_CRC_LAST 0x1A8B
+#define mmDCP0_DCP_CRC_MASK 0x1A88
+#define mmDCP0_DCP_DEBUG 0x1A8D
+#define mmDCP0_DCP_DEBUG2 0x1A98
+#define mmDCP0_DCP_FP_CONVERTED_FIELD 0x1A65
+#define mmDCP0_DCP_GSL_CONTROL 0x1A90
+#define mmDCP0_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1A91
+#define mmDCP0_DCP_RANDOM_SEEDS 0x1A61
+#define mmDCP0_DCP_SPATIAL_DITHER_CNTL 0x1A60
+#define mmDCP0_DCP_TEST_DEBUG_DATA 0x1A96
+#define mmDCP0_DCP_TEST_DEBUG_INDEX 0x1A95
+#define mmDCP0_DEGAMMA_CONTROL 0x1A58
+#define mmDCP0_DENORM_CONTROL 0x1A50
+#define mmDCP0_GAMUT_REMAP_C11_C12 0x1A5A
+#define mmDCP0_GAMUT_REMAP_C13_C14 0x1A5B
+#define mmDCP0_GAMUT_REMAP_C21_C22 0x1A5C
+#define mmDCP0_GAMUT_REMAP_C23_C24 0x1A5D
+#define mmDCP0_GAMUT_REMAP_C31_C32 0x1A5E
+#define mmDCP0_GAMUT_REMAP_C33_C34 0x1A5F
+#define mmDCP0_GAMUT_REMAP_CONTROL 0x1A59
+#define mmDCP0_GRPH_COMPRESS_PITCH 0x1A1A
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS 0x1A19
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1A1B
+#define mmDCP0_GRPH_CONTROL 0x1A01
+#define mmDCP0_GRPH_DFQ_CONTROL 0x1A14
+#define mmDCP0_GRPH_DFQ_STATUS 0x1A15
+#define mmDCP0_GRPH_ENABLE 0x1A00
+#define mmDCP0_GRPH_FLIP_CONTROL 0x1A12
+#define mmDCP0_GRPH_INTERRUPT_CONTROL 0x1A17
+#define mmDCP0_GRPH_INTERRUPT_STATUS 0x1A16
+#define mmDCP0_GRPH_LUT_10BIT_BYPASS 0x1A02
+#define mmDCP0_GRPH_PITCH 0x1A06
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS 0x1A04
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1A07
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS 0x1A05
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A08
+#define mmDCP0_GRPH_STEREOSYNC_FLIP 0x1A97
+#define mmDCP0_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1A18
+#define mmDCP0_GRPH_SURFACE_ADDRESS_INUSE 0x1A13
+#define mmDCP0_GRPH_SURFACE_OFFSET_X 0x1A09
+#define mmDCP0_GRPH_SURFACE_OFFSET_Y 0x1A0A
+#define mmDCP0_GRPH_SWAP_CNTL 0x1A03
+#define mmDCP0_GRPH_UPDATE 0x1A11
+#define mmDCP0_GRPH_X_END 0x1A0D
+#define mmDCP0_GRPH_X_START 0x1A0B
+#define mmDCP0_GRPH_Y_END 0x1A0E
+#define mmDCP0_GRPH_Y_START 0x1A0C
+#define mmDCP0_INPUT_CSC_C11_C12 0x1A36
+#define mmDCP0_INPUT_CSC_C13_C14 0x1A37
+#define mmDCP0_INPUT_CSC_C21_C22 0x1A38
+#define mmDCP0_INPUT_CSC_C23_C24 0x1A39
+#define mmDCP0_INPUT_CSC_C31_C32 0x1A3A
+#define mmDCP0_INPUT_CSC_C33_C34 0x1A3B
+#define mmDCP0_INPUT_CSC_CONTROL 0x1A35
+#define mmDCP0_INPUT_GAMMA_CONTROL 0x1A10
+#define mmDCP0_KEY_CONTROL 0x1A53
+#define mmDCP0_KEY_RANGE_ALPHA 0x1A54
+#define mmDCP0_KEY_RANGE_BLUE 0x1A57
+#define mmDCP0_KEY_RANGE_GREEN 0x1A56
+#define mmDCP0_KEY_RANGE_RED 0x1A55
+#define mmDCP0_OUTPUT_CSC_C11_C12 0x1A3D
+#define mmDCP0_OUTPUT_CSC_C13_C14 0x1A3E
+#define mmDCP0_OUTPUT_CSC_C21_C22 0x1A3F
+#define mmDCP0_OUTPUT_CSC_C23_C24 0x1A40
+#define mmDCP0_OUTPUT_CSC_C31_C32 0x1A41
+#define mmDCP0_OUTPUT_CSC_C33_C34 0x1A42
+#define mmDCP0_OUTPUT_CSC_CONTROL 0x1A3C
+#define mmDCP0_OUT_ROUND_CONTROL 0x1A51
+#define mmDCP0_OVL_CONTROL1 0x1A1D
+#define mmDCP0_OVL_CONTROL2 0x1A1E
+#define mmDCP0_OVL_DFQ_CONTROL 0x1A29
+#define mmDCP0_OVL_DFQ_STATUS 0x1A2A
+#define mmDCP0_OVL_ENABLE 0x1A1C
+#define mmDCP0_OVL_END 0x1A26
+#define mmDCP0_OVL_PITCH 0x1A21
+#define mmDCP0_OVLSCL_EDGE_PIXEL_CNTL 0x1A2C
+#define mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS 0x1A92
+#define mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A94
+#define mmDCP0_OVL_START 0x1A25
+#define mmDCP0_OVL_STEREOSYNC_FLIP 0x1A93
+#define mmDCP0_OVL_SURFACE_ADDRESS 0x1A20
+#define mmDCP0_OVL_SURFACE_ADDRESS_HIGH 0x1A22
+#define mmDCP0_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x1A2B
+#define mmDCP0_OVL_SURFACE_ADDRESS_INUSE 0x1A28
+#define mmDCP0_OVL_SURFACE_OFFSET_X 0x1A23
+#define mmDCP0_OVL_SURFACE_OFFSET_Y 0x1A24
+#define mmDCP0_OVL_SWAP_CNTL 0x1A1F
+#define mmDCP0_OVL_UPDATE 0x1A27
+#define mmDCP0_PRESCALE_GRPH_CONTROL 0x1A2D
+#define mmDCP0_PRESCALE_OVL_CONTROL 0x1A31
+#define mmDCP0_PRESCALE_VALUES_GRPH_B 0x1A30
+#define mmDCP0_PRESCALE_VALUES_GRPH_G 0x1A2F
+#define mmDCP0_PRESCALE_VALUES_GRPH_R 0x1A2E
+#define mmDCP0_PRESCALE_VALUES_OVL_CB 0x1A32
+#define mmDCP0_PRESCALE_VALUES_OVL_CR 0x1A34
+#define mmDCP0_PRESCALE_VALUES_OVL_Y 0x1A33
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL1 0x1AA6
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL2 0x1AA7
+#define mmDCP0_REGAMMA_CNTLA_REGION_0_1 0x1AA8
+#define mmDCP0_REGAMMA_CNTLA_REGION_10_11 0x1AAD
+#define mmDCP0_REGAMMA_CNTLA_REGION_12_13 0x1AAE
+#define mmDCP0_REGAMMA_CNTLA_REGION_14_15 0x1AAF
+#define mmDCP0_REGAMMA_CNTLA_REGION_2_3 0x1AA9
+#define mmDCP0_REGAMMA_CNTLA_REGION_4_5 0x1AAA
+#define mmDCP0_REGAMMA_CNTLA_REGION_6_7 0x1AAB
+#define mmDCP0_REGAMMA_CNTLA_REGION_8_9 0x1AAC
+#define mmDCP0_REGAMMA_CNTLA_SLOPE_CNTL 0x1AA5
+#define mmDCP0_REGAMMA_CNTLA_START_CNTL 0x1AA4
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL1 0x1AB2
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL2 0x1AB3
+#define mmDCP0_REGAMMA_CNTLB_REGION_0_1 0x1AB4
+#define mmDCP0_REGAMMA_CNTLB_REGION_10_11 0x1AB9
+#define mmDCP0_REGAMMA_CNTLB_REGION_12_13 0x1ABA
+#define mmDCP0_REGAMMA_CNTLB_REGION_14_15 0x1ABB
+#define mmDCP0_REGAMMA_CNTLB_REGION_2_3 0x1AB5
+#define mmDCP0_REGAMMA_CNTLB_REGION_4_5 0x1AB6
+#define mmDCP0_REGAMMA_CNTLB_REGION_6_7 0x1AB7
+#define mmDCP0_REGAMMA_CNTLB_REGION_8_9 0x1AB8
+#define mmDCP0_REGAMMA_CNTLB_SLOPE_CNTL 0x1AB1
+#define mmDCP0_REGAMMA_CNTLB_START_CNTL 0x1AB0
+#define mmDCP0_REGAMMA_CONTROL 0x1AA0
+#define mmDCP0_REGAMMA_LUT_DATA 0x1AA2
+#define mmDCP0_REGAMMA_LUT_INDEX 0x1AA1
+#define mmDCP0_REGAMMA_LUT_WRITE_EN_MASK 0x1AA3
+#define mmDCP1_COMM_MATRIXA_TRANS_C11_C12 0x1D43
+#define mmDCP1_COMM_MATRIXA_TRANS_C13_C14 0x1D44
+#define mmDCP1_COMM_MATRIXA_TRANS_C21_C22 0x1D45
+#define mmDCP1_COMM_MATRIXA_TRANS_C23_C24 0x1D46
+#define mmDCP1_COMM_MATRIXA_TRANS_C31_C32 0x1D47
+#define mmDCP1_COMM_MATRIXA_TRANS_C33_C34 0x1D48
+#define mmDCP1_COMM_MATRIXB_TRANS_C11_C12 0x1D49
+#define mmDCP1_COMM_MATRIXB_TRANS_C13_C14 0x1D4A
+#define mmDCP1_COMM_MATRIXB_TRANS_C21_C22 0x1D4B
+#define mmDCP1_COMM_MATRIXB_TRANS_C23_C24 0x1D4C
+#define mmDCP1_COMM_MATRIXB_TRANS_C31_C32 0x1D4D
+#define mmDCP1_COMM_MATRIXB_TRANS_C33_C34 0x1D4E
+#define mmDCP1_CUR_COLOR1 0x1D6C
+#define mmDCP1_CUR_COLOR2 0x1D6D
+#define mmDCP1_CUR_CONTROL 0x1D66
+#define mmDCP1_CUR_HOT_SPOT 0x1D6B
+#define mmDCP1_CUR_POSITION 0x1D6A
+#define mmDCP1_CUR_REQUEST_FILTER_CNTL 0x1D99
+#define mmDCP1_CUR_SIZE 0x1D68
+#define mmDCP1_CUR_SURFACE_ADDRESS 0x1D67
+#define mmDCP1_CUR_SURFACE_ADDRESS_HIGH 0x1D69
+#define mmDCP1_CUR_UPDATE 0x1D6E
+#define mmDCP1_DC_LUT_30_COLOR 0x1D7C
+#define mmDCP1_DC_LUT_AUTOFILL 0x1D7F
+#define mmDCP1_DC_LUT_BLACK_OFFSET_BLUE 0x1D81
+#define mmDCP1_DC_LUT_BLACK_OFFSET_GREEN 0x1D82
+#define mmDCP1_DC_LUT_BLACK_OFFSET_RED 0x1D83
+#define mmDCP1_DC_LUT_CONTROL 0x1D80
+#define mmDCP1_DC_LUT_PWL_DATA 0x1D7B
+#define mmDCP1_DC_LUT_RW_INDEX 0x1D79
+#define mmDCP1_DC_LUT_RW_MODE 0x1D78
+#define mmDCP1_DC_LUT_SEQ_COLOR 0x1D7A
+#define mmDCP1_DC_LUT_VGA_ACCESS_ENABLE 0x1D7D
+#define mmDCP1_DC_LUT_WHITE_OFFSET_BLUE 0x1D84
+#define mmDCP1_DC_LUT_WHITE_OFFSET_GREEN 0x1D85
+#define mmDCP1_DC_LUT_WHITE_OFFSET_RED 0x1D86
+#define mmDCP1_DC_LUT_WRITE_EN_MASK 0x1D7E
+#define mmDCP1_DCP_CRC_CONTROL 0x1D87
+#define mmDCP1_DCP_CRC_CURRENT 0x1D89
+#define mmDCP1_DCP_CRC_LAST 0x1D8B
+#define mmDCP1_DCP_CRC_MASK 0x1D88
+#define mmDCP1_DCP_DEBUG 0x1D8D
+#define mmDCP1_DCP_DEBUG2 0x1D98
+#define mmDCP1_DCP_FP_CONVERTED_FIELD 0x1D65
+#define mmDCP1_DCP_GSL_CONTROL 0x1D90
+#define mmDCP1_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1D91
+#define mmDCP1_DCP_RANDOM_SEEDS 0x1D61
+#define mmDCP1_DCP_SPATIAL_DITHER_CNTL 0x1D60
+#define mmDCP1_DCP_TEST_DEBUG_DATA 0x1D96
+#define mmDCP1_DCP_TEST_DEBUG_INDEX 0x1D95
+#define mmDCP1_DEGAMMA_CONTROL 0x1D58
+#define mmDCP1_DENORM_CONTROL 0x1D50
+#define mmDCP1_GAMUT_REMAP_C11_C12 0x1D5A
+#define mmDCP1_GAMUT_REMAP_C13_C14 0x1D5B
+#define mmDCP1_GAMUT_REMAP_C21_C22 0x1D5C
+#define mmDCP1_GAMUT_REMAP_C23_C24 0x1D5D
+#define mmDCP1_GAMUT_REMAP_C31_C32 0x1D5E
+#define mmDCP1_GAMUT_REMAP_C33_C34 0x1D5F
+#define mmDCP1_GAMUT_REMAP_CONTROL 0x1D59
+#define mmDCP1_GRPH_COMPRESS_PITCH 0x1D1A
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS 0x1D19
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1D1B
+#define mmDCP1_GRPH_CONTROL 0x1D01
+#define mmDCP1_GRPH_DFQ_CONTROL 0x1D14
+#define mmDCP1_GRPH_DFQ_STATUS 0x1D15
+#define mmDCP1_GRPH_ENABLE 0x1D00
+#define mmDCP1_GRPH_FLIP_CONTROL 0x1D12
+#define mmDCP1_GRPH_INTERRUPT_CONTROL 0x1D17
+#define mmDCP1_GRPH_INTERRUPT_STATUS 0x1D16
+#define mmDCP1_GRPH_LUT_10BIT_BYPASS 0x1D02
+#define mmDCP1_GRPH_PITCH 0x1D06
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS 0x1D04
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1D07
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS 0x1D05
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1D08
+#define mmDCP1_GRPH_STEREOSYNC_FLIP 0x1D97
+#define mmDCP1_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1D18
+#define mmDCP1_GRPH_SURFACE_ADDRESS_INUSE 0x1D13
+#define mmDCP1_GRPH_SURFACE_OFFSET_X 0x1D09
+#define mmDCP1_GRPH_SURFACE_OFFSET_Y 0x1D0A
+#define mmDCP1_GRPH_SWAP_CNTL 0x1D03
+#define mmDCP1_GRPH_UPDATE 0x1D11
+#define mmDCP1_GRPH_X_END 0x1D0D
+#define mmDCP1_GRPH_X_START 0x1D0B
+#define mmDCP1_GRPH_Y_END 0x1D0E
+#define mmDCP1_GRPH_Y_START 0x1D0C
+#define mmDCP1_INPUT_CSC_C11_C12 0x1D36
+#define mmDCP1_INPUT_CSC_C13_C14 0x1D37
+#define mmDCP1_INPUT_CSC_C21_C22 0x1D38
+#define mmDCP1_INPUT_CSC_C23_C24 0x1D39
+#define mmDCP1_INPUT_CSC_C31_C32 0x1D3A
+#define mmDCP1_INPUT_CSC_C33_C34 0x1D3B
+#define mmDCP1_INPUT_CSC_CONTROL 0x1D35
+#define mmDCP1_INPUT_GAMMA_CONTROL 0x1D10
+#define mmDCP1_KEY_CONTROL 0x1D53
+#define mmDCP1_KEY_RANGE_ALPHA 0x1D54
+#define mmDCP1_KEY_RANGE_BLUE 0x1D57
+#define mmDCP1_KEY_RANGE_GREEN 0x1D56
+#define mmDCP1_KEY_RANGE_RED 0x1D55
+#define mmDCP1_OUTPUT_CSC_C11_C12 0x1D3D
+#define mmDCP1_OUTPUT_CSC_C13_C14 0x1D3E
+#define mmDCP1_OUTPUT_CSC_C21_C22 0x1D3F
+#define mmDCP1_OUTPUT_CSC_C23_C24 0x1D40
+#define mmDCP1_OUTPUT_CSC_C31_C32 0x1D41
+#define mmDCP1_OUTPUT_CSC_C33_C34 0x1D42
+#define mmDCP1_OUTPUT_CSC_CONTROL 0x1D3C
+#define mmDCP1_OUT_ROUND_CONTROL 0x1D51
+#define mmDCP1_OVL_CONTROL1 0x1D1D
+#define mmDCP1_OVL_CONTROL2 0x1D1E
+#define mmDCP1_OVL_DFQ_CONTROL 0x1D29
+#define mmDCP1_OVL_DFQ_STATUS 0x1D2A
+#define mmDCP1_OVL_ENABLE 0x1D1C
+#define mmDCP1_OVL_END 0x1D26
+#define mmDCP1_OVL_PITCH 0x1D21
+#define mmDCP1_OVLSCL_EDGE_PIXEL_CNTL 0x1D2C
+#define mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS 0x1D92
+#define mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1D94
+#define mmDCP1_OVL_START 0x1D25
+#define mmDCP1_OVL_STEREOSYNC_FLIP 0x1D93
+#define mmDCP1_OVL_SURFACE_ADDRESS 0x1D20
+#define mmDCP1_OVL_SURFACE_ADDRESS_HIGH 0x1D22
+#define mmDCP1_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x1D2B
+#define mmDCP1_OVL_SURFACE_ADDRESS_INUSE 0x1D28
+#define mmDCP1_OVL_SURFACE_OFFSET_X 0x1D23
+#define mmDCP1_OVL_SURFACE_OFFSET_Y 0x1D24
+#define mmDCP1_OVL_SWAP_CNTL 0x1D1F
+#define mmDCP1_OVL_UPDATE 0x1D27
+#define mmDCP1_PRESCALE_GRPH_CONTROL 0x1D2D
+#define mmDCP1_PRESCALE_OVL_CONTROL 0x1D31
+#define mmDCP1_PRESCALE_VALUES_GRPH_B 0x1D30
+#define mmDCP1_PRESCALE_VALUES_GRPH_G 0x1D2F
+#define mmDCP1_PRESCALE_VALUES_GRPH_R 0x1D2E
+#define mmDCP1_PRESCALE_VALUES_OVL_CB 0x1D32
+#define mmDCP1_PRESCALE_VALUES_OVL_CR 0x1D34
+#define mmDCP1_PRESCALE_VALUES_OVL_Y 0x1D33
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL1 0x1DA6
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL2 0x1DA7
+#define mmDCP1_REGAMMA_CNTLA_REGION_0_1 0x1DA8
+#define mmDCP1_REGAMMA_CNTLA_REGION_10_11 0x1DAD
+#define mmDCP1_REGAMMA_CNTLA_REGION_12_13 0x1DAE
+#define mmDCP1_REGAMMA_CNTLA_REGION_14_15 0x1DAF
+#define mmDCP1_REGAMMA_CNTLA_REGION_2_3 0x1DA9
+#define mmDCP1_REGAMMA_CNTLA_REGION_4_5 0x1DAA
+#define mmDCP1_REGAMMA_CNTLA_REGION_6_7 0x1DAB
+#define mmDCP1_REGAMMA_CNTLA_REGION_8_9 0x1DAC
+#define mmDCP1_REGAMMA_CNTLA_SLOPE_CNTL 0x1DA5
+#define mmDCP1_REGAMMA_CNTLA_START_CNTL 0x1DA4
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL1 0x1DB2
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL2 0x1DB3
+#define mmDCP1_REGAMMA_CNTLB_REGION_0_1 0x1DB4
+#define mmDCP1_REGAMMA_CNTLB_REGION_10_11 0x1DB9
+#define mmDCP1_REGAMMA_CNTLB_REGION_12_13 0x1DBA
+#define mmDCP1_REGAMMA_CNTLB_REGION_14_15 0x1DBB
+#define mmDCP1_REGAMMA_CNTLB_REGION_2_3 0x1DB5
+#define mmDCP1_REGAMMA_CNTLB_REGION_4_5 0x1DB6
+#define mmDCP1_REGAMMA_CNTLB_REGION_6_7 0x1DB7
+#define mmDCP1_REGAMMA_CNTLB_REGION_8_9 0x1DB8
+#define mmDCP1_REGAMMA_CNTLB_SLOPE_CNTL 0x1DB1
+#define mmDCP1_REGAMMA_CNTLB_START_CNTL 0x1DB0
+#define mmDCP1_REGAMMA_CONTROL 0x1DA0
+#define mmDCP1_REGAMMA_LUT_DATA 0x1DA2
+#define mmDCP1_REGAMMA_LUT_INDEX 0x1DA1
+#define mmDCP1_REGAMMA_LUT_WRITE_EN_MASK 0x1DA3
+#define mmDCP2_COMM_MATRIXA_TRANS_C11_C12 0x4043
+#define mmDCP2_COMM_MATRIXA_TRANS_C13_C14 0x4044
+#define mmDCP2_COMM_MATRIXA_TRANS_C21_C22 0x4045
+#define mmDCP2_COMM_MATRIXA_TRANS_C23_C24 0x4046
+#define mmDCP2_COMM_MATRIXA_TRANS_C31_C32 0x4047
+#define mmDCP2_COMM_MATRIXA_TRANS_C33_C34 0x4048
+#define mmDCP2_COMM_MATRIXB_TRANS_C11_C12 0x4049
+#define mmDCP2_COMM_MATRIXB_TRANS_C13_C14 0x404A
+#define mmDCP2_COMM_MATRIXB_TRANS_C21_C22 0x404B
+#define mmDCP2_COMM_MATRIXB_TRANS_C23_C24 0x404C
+#define mmDCP2_COMM_MATRIXB_TRANS_C31_C32 0x404D
+#define mmDCP2_COMM_MATRIXB_TRANS_C33_C34 0x404E
+#define mmDCP2_CUR_COLOR1 0x406C
+#define mmDCP2_CUR_COLOR2 0x406D
+#define mmDCP2_CUR_CONTROL 0x4066
+#define mmDCP2_CUR_HOT_SPOT 0x406B
+#define mmDCP2_CUR_POSITION 0x406A
+#define mmDCP2_CUR_REQUEST_FILTER_CNTL 0x4099
+#define mmDCP2_CUR_SIZE 0x4068
+#define mmDCP2_CUR_SURFACE_ADDRESS 0x4067
+#define mmDCP2_CUR_SURFACE_ADDRESS_HIGH 0x4069
+#define mmDCP2_CUR_UPDATE 0x406E
+#define mmDCP2_DC_LUT_30_COLOR 0x407C
+#define mmDCP2_DC_LUT_AUTOFILL 0x407F
+#define mmDCP2_DC_LUT_BLACK_OFFSET_BLUE 0x4081
+#define mmDCP2_DC_LUT_BLACK_OFFSET_GREEN 0x4082
+#define mmDCP2_DC_LUT_BLACK_OFFSET_RED 0x4083
+#define mmDCP2_DC_LUT_CONTROL 0x4080
+#define mmDCP2_DC_LUT_PWL_DATA 0x407B
+#define mmDCP2_DC_LUT_RW_INDEX 0x4079
+#define mmDCP2_DC_LUT_RW_MODE 0x4078
+#define mmDCP2_DC_LUT_SEQ_COLOR 0x407A
+#define mmDCP2_DC_LUT_VGA_ACCESS_ENABLE 0x407D
+#define mmDCP2_DC_LUT_WHITE_OFFSET_BLUE 0x4084
+#define mmDCP2_DC_LUT_WHITE_OFFSET_GREEN 0x4085
+#define mmDCP2_DC_LUT_WHITE_OFFSET_RED 0x4086
+#define mmDCP2_DC_LUT_WRITE_EN_MASK 0x407E
+#define mmDCP2_DCP_CRC_CONTROL 0x4087
+#define mmDCP2_DCP_CRC_CURRENT 0x4089
+#define mmDCP2_DCP_CRC_LAST 0x408B
+#define mmDCP2_DCP_CRC_MASK 0x4088
+#define mmDCP2_DCP_DEBUG 0x408D
+#define mmDCP2_DCP_DEBUG2 0x4098
+#define mmDCP2_DCP_FP_CONVERTED_FIELD 0x4065
+#define mmDCP2_DCP_GSL_CONTROL 0x4090
+#define mmDCP2_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4091
+#define mmDCP2_DCP_RANDOM_SEEDS 0x4061
+#define mmDCP2_DCP_SPATIAL_DITHER_CNTL 0x4060
+#define mmDCP2_DCP_TEST_DEBUG_DATA 0x4096
+#define mmDCP2_DCP_TEST_DEBUG_INDEX 0x4095
+#define mmDCP2_DEGAMMA_CONTROL 0x4058
+#define mmDCP2_DENORM_CONTROL 0x4050
+#define mmDCP2_GAMUT_REMAP_C11_C12 0x405A
+#define mmDCP2_GAMUT_REMAP_C13_C14 0x405B
+#define mmDCP2_GAMUT_REMAP_C21_C22 0x405C
+#define mmDCP2_GAMUT_REMAP_C23_C24 0x405D
+#define mmDCP2_GAMUT_REMAP_C31_C32 0x405E
+#define mmDCP2_GAMUT_REMAP_C33_C34 0x405F
+#define mmDCP2_GAMUT_REMAP_CONTROL 0x4059
+#define mmDCP2_GRPH_COMPRESS_PITCH 0x401A
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS 0x4019
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x401B
+#define mmDCP2_GRPH_CONTROL 0x4001
+#define mmDCP2_GRPH_DFQ_CONTROL 0x4014
+#define mmDCP2_GRPH_DFQ_STATUS 0x4015
+#define mmDCP2_GRPH_ENABLE 0x4000
+#define mmDCP2_GRPH_FLIP_CONTROL 0x4012
+#define mmDCP2_GRPH_INTERRUPT_CONTROL 0x4017
+#define mmDCP2_GRPH_INTERRUPT_STATUS 0x4016
+#define mmDCP2_GRPH_LUT_10BIT_BYPASS 0x4002
+#define mmDCP2_GRPH_PITCH 0x4006
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS 0x4004
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4007
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS 0x4005
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4008
+#define mmDCP2_GRPH_STEREOSYNC_FLIP 0x4097
+#define mmDCP2_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4018
+#define mmDCP2_GRPH_SURFACE_ADDRESS_INUSE 0x4013
+#define mmDCP2_GRPH_SURFACE_OFFSET_X 0x4009
+#define mmDCP2_GRPH_SURFACE_OFFSET_Y 0x400A
+#define mmDCP2_GRPH_SWAP_CNTL 0x4003
+#define mmDCP2_GRPH_UPDATE 0x4011
+#define mmDCP2_GRPH_X_END 0x400D
+#define mmDCP2_GRPH_X_START 0x400B
+#define mmDCP2_GRPH_Y_END 0x400E
+#define mmDCP2_GRPH_Y_START 0x400C
+#define mmDCP2_INPUT_CSC_C11_C12 0x4036
+#define mmDCP2_INPUT_CSC_C13_C14 0x4037
+#define mmDCP2_INPUT_CSC_C21_C22 0x4038
+#define mmDCP2_INPUT_CSC_C23_C24 0x4039
+#define mmDCP2_INPUT_CSC_C31_C32 0x403A
+#define mmDCP2_INPUT_CSC_C33_C34 0x403B
+#define mmDCP2_INPUT_CSC_CONTROL 0x4035
+#define mmDCP2_INPUT_GAMMA_CONTROL 0x4010
+#define mmDCP2_KEY_CONTROL 0x4053
+#define mmDCP2_KEY_RANGE_ALPHA 0x4054
+#define mmDCP2_KEY_RANGE_BLUE 0x4057
+#define mmDCP2_KEY_RANGE_GREEN 0x4056
+#define mmDCP2_KEY_RANGE_RED 0x4055
+#define mmDCP2_OUTPUT_CSC_C11_C12 0x403D
+#define mmDCP2_OUTPUT_CSC_C13_C14 0x403E
+#define mmDCP2_OUTPUT_CSC_C21_C22 0x403F
+#define mmDCP2_OUTPUT_CSC_C23_C24 0x4040
+#define mmDCP2_OUTPUT_CSC_C31_C32 0x4041
+#define mmDCP2_OUTPUT_CSC_C33_C34 0x4042
+#define mmDCP2_OUTPUT_CSC_CONTROL 0x403C
+#define mmDCP2_OUT_ROUND_CONTROL 0x4051
+#define mmDCP2_OVL_CONTROL1 0x401D
+#define mmDCP2_OVL_CONTROL2 0x401E
+#define mmDCP2_OVL_DFQ_CONTROL 0x4029
+#define mmDCP2_OVL_DFQ_STATUS 0x402A
+#define mmDCP2_OVL_ENABLE 0x401C
+#define mmDCP2_OVL_END 0x4026
+#define mmDCP2_OVL_PITCH 0x4021
+#define mmDCP2_OVLSCL_EDGE_PIXEL_CNTL 0x402C
+#define mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS 0x4092
+#define mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4094
+#define mmDCP2_OVL_START 0x4025
+#define mmDCP2_OVL_STEREOSYNC_FLIP 0x4093
+#define mmDCP2_OVL_SURFACE_ADDRESS 0x4020
+#define mmDCP2_OVL_SURFACE_ADDRESS_HIGH 0x4022
+#define mmDCP2_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x402B
+#define mmDCP2_OVL_SURFACE_ADDRESS_INUSE 0x4028
+#define mmDCP2_OVL_SURFACE_OFFSET_X 0x4023
+#define mmDCP2_OVL_SURFACE_OFFSET_Y 0x4024
+#define mmDCP2_OVL_SWAP_CNTL 0x401F
+#define mmDCP2_OVL_UPDATE 0x4027
+#define mmDCP2_PRESCALE_GRPH_CONTROL 0x402D
+#define mmDCP2_PRESCALE_OVL_CONTROL 0x4031
+#define mmDCP2_PRESCALE_VALUES_GRPH_B 0x4030
+#define mmDCP2_PRESCALE_VALUES_GRPH_G 0x402F
+#define mmDCP2_PRESCALE_VALUES_GRPH_R 0x402E
+#define mmDCP2_PRESCALE_VALUES_OVL_CB 0x4032
+#define mmDCP2_PRESCALE_VALUES_OVL_CR 0x4034
+#define mmDCP2_PRESCALE_VALUES_OVL_Y 0x4033
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL1 0x40A6
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL2 0x40A7
+#define mmDCP2_REGAMMA_CNTLA_REGION_0_1 0x40A8
+#define mmDCP2_REGAMMA_CNTLA_REGION_10_11 0x40AD
+#define mmDCP2_REGAMMA_CNTLA_REGION_12_13 0x40AE
+#define mmDCP2_REGAMMA_CNTLA_REGION_14_15 0x40AF
+#define mmDCP2_REGAMMA_CNTLA_REGION_2_3 0x40A9
+#define mmDCP2_REGAMMA_CNTLA_REGION_4_5 0x40AA
+#define mmDCP2_REGAMMA_CNTLA_REGION_6_7 0x40AB
+#define mmDCP2_REGAMMA_CNTLA_REGION_8_9 0x40AC
+#define mmDCP2_REGAMMA_CNTLA_SLOPE_CNTL 0x40A5
+#define mmDCP2_REGAMMA_CNTLA_START_CNTL 0x40A4
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL1 0x40B2
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL2 0x40B3
+#define mmDCP2_REGAMMA_CNTLB_REGION_0_1 0x40B4
+#define mmDCP2_REGAMMA_CNTLB_REGION_10_11 0x40B9
+#define mmDCP2_REGAMMA_CNTLB_REGION_12_13 0x40BA
+#define mmDCP2_REGAMMA_CNTLB_REGION_14_15 0x40BB
+#define mmDCP2_REGAMMA_CNTLB_REGION_2_3 0x40B5
+#define mmDCP2_REGAMMA_CNTLB_REGION_4_5 0x40B6
+#define mmDCP2_REGAMMA_CNTLB_REGION_6_7 0x40B7
+#define mmDCP2_REGAMMA_CNTLB_REGION_8_9 0x40B8
+#define mmDCP2_REGAMMA_CNTLB_SLOPE_CNTL 0x40B1
+#define mmDCP2_REGAMMA_CNTLB_START_CNTL 0x40B0
+#define mmDCP2_REGAMMA_CONTROL 0x40A0
+#define mmDCP2_REGAMMA_LUT_DATA 0x40A2
+#define mmDCP2_REGAMMA_LUT_INDEX 0x40A1
+#define mmDCP2_REGAMMA_LUT_WRITE_EN_MASK 0x40A3
+#define mmDCP3_COMM_MATRIXA_TRANS_C11_C12 0x4343
+#define mmDCP3_COMM_MATRIXA_TRANS_C13_C14 0x4344
+#define mmDCP3_COMM_MATRIXA_TRANS_C21_C22 0x4345
+#define mmDCP3_COMM_MATRIXA_TRANS_C23_C24 0x4346
+#define mmDCP3_COMM_MATRIXA_TRANS_C31_C32 0x4347
+#define mmDCP3_COMM_MATRIXA_TRANS_C33_C34 0x4348
+#define mmDCP3_COMM_MATRIXB_TRANS_C11_C12 0x4349
+#define mmDCP3_COMM_MATRIXB_TRANS_C13_C14 0x434A
+#define mmDCP3_COMM_MATRIXB_TRANS_C21_C22 0x434B
+#define mmDCP3_COMM_MATRIXB_TRANS_C23_C24 0x434C
+#define mmDCP3_COMM_MATRIXB_TRANS_C31_C32 0x434D
+#define mmDCP3_COMM_MATRIXB_TRANS_C33_C34 0x434E
+#define mmDCP3_CUR_COLOR1 0x436C
+#define mmDCP3_CUR_COLOR2 0x436D
+#define mmDCP3_CUR_CONTROL 0x4366
+#define mmDCP3_CUR_HOT_SPOT 0x436B
+#define mmDCP3_CUR_POSITION 0x436A
+#define mmDCP3_CUR_REQUEST_FILTER_CNTL 0x4399
+#define mmDCP3_CUR_SIZE 0x4368
+#define mmDCP3_CUR_SURFACE_ADDRESS 0x4367
+#define mmDCP3_CUR_SURFACE_ADDRESS_HIGH 0x4369
+#define mmDCP3_CUR_UPDATE 0x436E
+#define mmDCP3_DC_LUT_30_COLOR 0x437C
+#define mmDCP3_DC_LUT_AUTOFILL 0x437F
+#define mmDCP3_DC_LUT_BLACK_OFFSET_BLUE 0x4381
+#define mmDCP3_DC_LUT_BLACK_OFFSET_GREEN 0x4382
+#define mmDCP3_DC_LUT_BLACK_OFFSET_RED 0x4383
+#define mmDCP3_DC_LUT_CONTROL 0x4380
+#define mmDCP3_DC_LUT_PWL_DATA 0x437B
+#define mmDCP3_DC_LUT_RW_INDEX 0x4379
+#define mmDCP3_DC_LUT_RW_MODE 0x4378
+#define mmDCP3_DC_LUT_SEQ_COLOR 0x437A
+#define mmDCP3_DC_LUT_VGA_ACCESS_ENABLE 0x437D
+#define mmDCP3_DC_LUT_WHITE_OFFSET_BLUE 0x4384
+#define mmDCP3_DC_LUT_WHITE_OFFSET_GREEN 0x4385
+#define mmDCP3_DC_LUT_WHITE_OFFSET_RED 0x4386
+#define mmDCP3_DC_LUT_WRITE_EN_MASK 0x437E
+#define mmDCP3_DCP_CRC_CONTROL 0x4387
+#define mmDCP3_DCP_CRC_CURRENT 0x4389
+#define mmDCP3_DCP_CRC_LAST 0x438B
+#define mmDCP3_DCP_CRC_MASK 0x4388
+#define mmDCP3_DCP_DEBUG 0x438D
+#define mmDCP3_DCP_DEBUG2 0x4398
+#define mmDCP3_DCP_FP_CONVERTED_FIELD 0x4365
+#define mmDCP3_DCP_GSL_CONTROL 0x4390
+#define mmDCP3_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4391
+#define mmDCP3_DCP_RANDOM_SEEDS 0x4361
+#define mmDCP3_DCP_SPATIAL_DITHER_CNTL 0x4360
+#define mmDCP3_DCP_TEST_DEBUG_DATA 0x4396
+#define mmDCP3_DCP_TEST_DEBUG_INDEX 0x4395
+#define mmDCP3_DEGAMMA_CONTROL 0x4358
+#define mmDCP3_DENORM_CONTROL 0x4350
+#define mmDCP3_GAMUT_REMAP_C11_C12 0x435A
+#define mmDCP3_GAMUT_REMAP_C13_C14 0x435B
+#define mmDCP3_GAMUT_REMAP_C21_C22 0x435C
+#define mmDCP3_GAMUT_REMAP_C23_C24 0x435D
+#define mmDCP3_GAMUT_REMAP_C31_C32 0x435E
+#define mmDCP3_GAMUT_REMAP_C33_C34 0x435F
+#define mmDCP3_GAMUT_REMAP_CONTROL 0x4359
+#define mmDCP3_GRPH_COMPRESS_PITCH 0x431A
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS 0x4319
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x431B
+#define mmDCP3_GRPH_CONTROL 0x4301
+#define mmDCP3_GRPH_DFQ_CONTROL 0x4314
+#define mmDCP3_GRPH_DFQ_STATUS 0x4315
+#define mmDCP3_GRPH_ENABLE 0x4300
+#define mmDCP3_GRPH_FLIP_CONTROL 0x4312
+#define mmDCP3_GRPH_INTERRUPT_CONTROL 0x4317
+#define mmDCP3_GRPH_INTERRUPT_STATUS 0x4316
+#define mmDCP3_GRPH_LUT_10BIT_BYPASS 0x4302
+#define mmDCP3_GRPH_PITCH 0x4306
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS 0x4304
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4307
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS 0x4305
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4308
+#define mmDCP3_GRPH_STEREOSYNC_FLIP 0x4397
+#define mmDCP3_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4318
+#define mmDCP3_GRPH_SURFACE_ADDRESS_INUSE 0x4313
+#define mmDCP3_GRPH_SURFACE_OFFSET_X 0x4309
+#define mmDCP3_GRPH_SURFACE_OFFSET_Y 0x430A
+#define mmDCP3_GRPH_SWAP_CNTL 0x4303
+#define mmDCP3_GRPH_UPDATE 0x4311
+#define mmDCP3_GRPH_X_END 0x430D
+#define mmDCP3_GRPH_X_START 0x430B
+#define mmDCP3_GRPH_Y_END 0x430E
+#define mmDCP3_GRPH_Y_START 0x430C
+#define mmDCP3_INPUT_CSC_C11_C12 0x4336
+#define mmDCP3_INPUT_CSC_C13_C14 0x4337
+#define mmDCP3_INPUT_CSC_C21_C22 0x4338
+#define mmDCP3_INPUT_CSC_C23_C24 0x4339
+#define mmDCP3_INPUT_CSC_C31_C32 0x433A
+#define mmDCP3_INPUT_CSC_C33_C34 0x433B
+#define mmDCP3_INPUT_CSC_CONTROL 0x4335
+#define mmDCP3_INPUT_GAMMA_CONTROL 0x4310
+#define mmDCP3_KEY_CONTROL 0x4353
+#define mmDCP3_KEY_RANGE_ALPHA 0x4354
+#define mmDCP3_KEY_RANGE_BLUE 0x4357
+#define mmDCP3_KEY_RANGE_GREEN 0x4356
+#define mmDCP3_KEY_RANGE_RED 0x4355
+#define mmDCP3_OUTPUT_CSC_C11_C12 0x433D
+#define mmDCP3_OUTPUT_CSC_C13_C14 0x433E
+#define mmDCP3_OUTPUT_CSC_C21_C22 0x433F
+#define mmDCP3_OUTPUT_CSC_C23_C24 0x4340
+#define mmDCP3_OUTPUT_CSC_C31_C32 0x4341
+#define mmDCP3_OUTPUT_CSC_C33_C34 0x4342
+#define mmDCP3_OUTPUT_CSC_CONTROL 0x433C
+#define mmDCP3_OUT_ROUND_CONTROL 0x4351
+#define mmDCP3_OVL_CONTROL1 0x431D
+#define mmDCP3_OVL_CONTROL2 0x431E
+#define mmDCP3_OVL_DFQ_CONTROL 0x4329
+#define mmDCP3_OVL_DFQ_STATUS 0x432A
+#define mmDCP3_OVL_ENABLE 0x431C
+#define mmDCP3_OVL_END 0x4326
+#define mmDCP3_OVL_PITCH 0x4321
+#define mmDCP3_OVLSCL_EDGE_PIXEL_CNTL 0x432C
+#define mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS 0x4392
+#define mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4394
+#define mmDCP3_OVL_START 0x4325
+#define mmDCP3_OVL_STEREOSYNC_FLIP 0x4393
+#define mmDCP3_OVL_SURFACE_ADDRESS 0x4320
+#define mmDCP3_OVL_SURFACE_ADDRESS_HIGH 0x4322
+#define mmDCP3_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x432B
+#define mmDCP3_OVL_SURFACE_ADDRESS_INUSE 0x4328
+#define mmDCP3_OVL_SURFACE_OFFSET_X 0x4323
+#define mmDCP3_OVL_SURFACE_OFFSET_Y 0x4324
+#define mmDCP3_OVL_SWAP_CNTL 0x431F
+#define mmDCP3_OVL_UPDATE 0x4327
+#define mmDCP3_PRESCALE_GRPH_CONTROL 0x432D
+#define mmDCP3_PRESCALE_OVL_CONTROL 0x4331
+#define mmDCP3_PRESCALE_VALUES_GRPH_B 0x4330
+#define mmDCP3_PRESCALE_VALUES_GRPH_G 0x432F
+#define mmDCP3_PRESCALE_VALUES_GRPH_R 0x432E
+#define mmDCP3_PRESCALE_VALUES_OVL_CB 0x4332
+#define mmDCP3_PRESCALE_VALUES_OVL_CR 0x4334
+#define mmDCP3_PRESCALE_VALUES_OVL_Y 0x4333
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL1 0x43A6
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL2 0x43A7
+#define mmDCP3_REGAMMA_CNTLA_REGION_0_1 0x43A8
+#define mmDCP3_REGAMMA_CNTLA_REGION_10_11 0x43AD
+#define mmDCP3_REGAMMA_CNTLA_REGION_12_13 0x43AE
+#define mmDCP3_REGAMMA_CNTLA_REGION_14_15 0x43AF
+#define mmDCP3_REGAMMA_CNTLA_REGION_2_3 0x43A9
+#define mmDCP3_REGAMMA_CNTLA_REGION_4_5 0x43AA
+#define mmDCP3_REGAMMA_CNTLA_REGION_6_7 0x43AB
+#define mmDCP3_REGAMMA_CNTLA_REGION_8_9 0x43AC
+#define mmDCP3_REGAMMA_CNTLA_SLOPE_CNTL 0x43A5
+#define mmDCP3_REGAMMA_CNTLA_START_CNTL 0x43A4
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL1 0x43B2
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL2 0x43B3
+#define mmDCP3_REGAMMA_CNTLB_REGION_0_1 0x43B4
+#define mmDCP3_REGAMMA_CNTLB_REGION_10_11 0x43B9
+#define mmDCP3_REGAMMA_CNTLB_REGION_12_13 0x43BA
+#define mmDCP3_REGAMMA_CNTLB_REGION_14_15 0x43BB
+#define mmDCP3_REGAMMA_CNTLB_REGION_2_3 0x43B5
+#define mmDCP3_REGAMMA_CNTLB_REGION_4_5 0x43B6
+#define mmDCP3_REGAMMA_CNTLB_REGION_6_7 0x43B7
+#define mmDCP3_REGAMMA_CNTLB_REGION_8_9 0x43B8
+#define mmDCP3_REGAMMA_CNTLB_SLOPE_CNTL 0x43B1
+#define mmDCP3_REGAMMA_CNTLB_START_CNTL 0x43B0
+#define mmDCP3_REGAMMA_CONTROL 0x43A0
+#define mmDCP3_REGAMMA_LUT_DATA 0x43A2
+#define mmDCP3_REGAMMA_LUT_INDEX 0x43A1
+#define mmDCP3_REGAMMA_LUT_WRITE_EN_MASK 0x43A3
+#define mmDCP4_COMM_MATRIXA_TRANS_C11_C12 0x4643
+#define mmDCP4_COMM_MATRIXA_TRANS_C13_C14 0x4644
+#define mmDCP4_COMM_MATRIXA_TRANS_C21_C22 0x4645
+#define mmDCP4_COMM_MATRIXA_TRANS_C23_C24 0x4646
+#define mmDCP4_COMM_MATRIXA_TRANS_C31_C32 0x4647
+#define mmDCP4_COMM_MATRIXA_TRANS_C33_C34 0x4648
+#define mmDCP4_COMM_MATRIXB_TRANS_C11_C12 0x4649
+#define mmDCP4_COMM_MATRIXB_TRANS_C13_C14 0x464A
+#define mmDCP4_COMM_MATRIXB_TRANS_C21_C22 0x464B
+#define mmDCP4_COMM_MATRIXB_TRANS_C23_C24 0x464C
+#define mmDCP4_COMM_MATRIXB_TRANS_C31_C32 0x464D
+#define mmDCP4_COMM_MATRIXB_TRANS_C33_C34 0x464E
+#define mmDCP4_CUR_COLOR1 0x466C
+#define mmDCP4_CUR_COLOR2 0x466D
+#define mmDCP4_CUR_CONTROL 0x4666
+#define mmDCP4_CUR_HOT_SPOT 0x466B
+#define mmDCP4_CUR_POSITION 0x466A
+#define mmDCP4_CUR_REQUEST_FILTER_CNTL 0x4699
+#define mmDCP4_CUR_SIZE 0x4668
+#define mmDCP4_CUR_SURFACE_ADDRESS 0x4667
+#define mmDCP4_CUR_SURFACE_ADDRESS_HIGH 0x4669
+#define mmDCP4_CUR_UPDATE 0x466E
+#define mmDCP4_DC_LUT_30_COLOR 0x467C
+#define mmDCP4_DC_LUT_AUTOFILL 0x467F
+#define mmDCP4_DC_LUT_BLACK_OFFSET_BLUE 0x4681
+#define mmDCP4_DC_LUT_BLACK_OFFSET_GREEN 0x4682
+#define mmDCP4_DC_LUT_BLACK_OFFSET_RED 0x4683
+#define mmDCP4_DC_LUT_CONTROL 0x4680
+#define mmDCP4_DC_LUT_PWL_DATA 0x467B
+#define mmDCP4_DC_LUT_RW_INDEX 0x4679
+#define mmDCP4_DC_LUT_RW_MODE 0x4678
+#define mmDCP4_DC_LUT_SEQ_COLOR 0x467A
+#define mmDCP4_DC_LUT_VGA_ACCESS_ENABLE 0x467D
+#define mmDCP4_DC_LUT_WHITE_OFFSET_BLUE 0x4684
+#define mmDCP4_DC_LUT_WHITE_OFFSET_GREEN 0x4685
+#define mmDCP4_DC_LUT_WHITE_OFFSET_RED 0x4686
+#define mmDCP4_DC_LUT_WRITE_EN_MASK 0x467E
+#define mmDCP4_DCP_CRC_CONTROL 0x4687
+#define mmDCP4_DCP_CRC_CURRENT 0x4689
+#define mmDCP4_DCP_CRC_LAST 0x468B
+#define mmDCP4_DCP_CRC_MASK 0x4688
+#define mmDCP4_DCP_DEBUG 0x468D
+#define mmDCP4_DCP_DEBUG2 0x4698
+#define mmDCP4_DCP_FP_CONVERTED_FIELD 0x4665
+#define mmDCP4_DCP_GSL_CONTROL 0x4690
+#define mmDCP4_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4691
+#define mmDCP4_DCP_RANDOM_SEEDS 0x4661
+#define mmDCP4_DCP_SPATIAL_DITHER_CNTL 0x4660
+#define mmDCP4_DCP_TEST_DEBUG_DATA 0x4696
+#define mmDCP4_DCP_TEST_DEBUG_INDEX 0x4695
+#define mmDCP4_DEGAMMA_CONTROL 0x4658
+#define mmDCP4_DENORM_CONTROL 0x4650
+#define mmDCP4_GAMUT_REMAP_C11_C12 0x465A
+#define mmDCP4_GAMUT_REMAP_C13_C14 0x465B
+#define mmDCP4_GAMUT_REMAP_C21_C22 0x465C
+#define mmDCP4_GAMUT_REMAP_C23_C24 0x465D
+#define mmDCP4_GAMUT_REMAP_C31_C32 0x465E
+#define mmDCP4_GAMUT_REMAP_C33_C34 0x465F
+#define mmDCP4_GAMUT_REMAP_CONTROL 0x4659
+#define mmDCP4_GRPH_COMPRESS_PITCH 0x461A
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS 0x4619
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x461B
+#define mmDCP4_GRPH_CONTROL 0x4601
+#define mmDCP4_GRPH_DFQ_CONTROL 0x4614
+#define mmDCP4_GRPH_DFQ_STATUS 0x4615
+#define mmDCP4_GRPH_ENABLE 0x4600
+#define mmDCP4_GRPH_FLIP_CONTROL 0x4612
+#define mmDCP4_GRPH_INTERRUPT_CONTROL 0x4617
+#define mmDCP4_GRPH_INTERRUPT_STATUS 0x4616
+#define mmDCP4_GRPH_LUT_10BIT_BYPASS 0x4602
+#define mmDCP4_GRPH_PITCH 0x4606
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS 0x4604
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4607
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS 0x4605
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4608
+#define mmDCP4_GRPH_STEREOSYNC_FLIP 0x4697
+#define mmDCP4_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4618
+#define mmDCP4_GRPH_SURFACE_ADDRESS_INUSE 0x4613
+#define mmDCP4_GRPH_SURFACE_OFFSET_X 0x4609
+#define mmDCP4_GRPH_SURFACE_OFFSET_Y 0x460A
+#define mmDCP4_GRPH_SWAP_CNTL 0x4603
+#define mmDCP4_GRPH_UPDATE 0x4611
+#define mmDCP4_GRPH_X_END 0x460D
+#define mmDCP4_GRPH_X_START 0x460B
+#define mmDCP4_GRPH_Y_END 0x460E
+#define mmDCP4_GRPH_Y_START 0x460C
+#define mmDCP4_INPUT_CSC_C11_C12 0x4636
+#define mmDCP4_INPUT_CSC_C13_C14 0x4637
+#define mmDCP4_INPUT_CSC_C21_C22 0x4638
+#define mmDCP4_INPUT_CSC_C23_C24 0x4639
+#define mmDCP4_INPUT_CSC_C31_C32 0x463A
+#define mmDCP4_INPUT_CSC_C33_C34 0x463B
+#define mmDCP4_INPUT_CSC_CONTROL 0x4635
+#define mmDCP4_INPUT_GAMMA_CONTROL 0x4610
+#define mmDCP4_KEY_CONTROL 0x4653
+#define mmDCP4_KEY_RANGE_ALPHA 0x4654
+#define mmDCP4_KEY_RANGE_BLUE 0x4657
+#define mmDCP4_KEY_RANGE_GREEN 0x4656
+#define mmDCP4_KEY_RANGE_RED 0x4655
+#define mmDCP4_OUTPUT_CSC_C11_C12 0x463D
+#define mmDCP4_OUTPUT_CSC_C13_C14 0x463E
+#define mmDCP4_OUTPUT_CSC_C21_C22 0x463F
+#define mmDCP4_OUTPUT_CSC_C23_C24 0x4640
+#define mmDCP4_OUTPUT_CSC_C31_C32 0x4641
+#define mmDCP4_OUTPUT_CSC_C33_C34 0x4642
+#define mmDCP4_OUTPUT_CSC_CONTROL 0x463C
+#define mmDCP4_OUT_ROUND_CONTROL 0x4651
+#define mmDCP4_OVL_CONTROL1 0x461D
+#define mmDCP4_OVL_CONTROL2 0x461E
+#define mmDCP4_OVL_DFQ_CONTROL 0x4629
+#define mmDCP4_OVL_DFQ_STATUS 0x462A
+#define mmDCP4_OVL_ENABLE 0x461C
+#define mmDCP4_OVL_END 0x4626
+#define mmDCP4_OVL_PITCH 0x4621
+#define mmDCP4_OVLSCL_EDGE_PIXEL_CNTL 0x462C
+#define mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS 0x4692
+#define mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4694
+#define mmDCP4_OVL_START 0x4625
+#define mmDCP4_OVL_STEREOSYNC_FLIP 0x4693
+#define mmDCP4_OVL_SURFACE_ADDRESS 0x4620
+#define mmDCP4_OVL_SURFACE_ADDRESS_HIGH 0x4622
+#define mmDCP4_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x462B
+#define mmDCP4_OVL_SURFACE_ADDRESS_INUSE 0x4628
+#define mmDCP4_OVL_SURFACE_OFFSET_X 0x4623
+#define mmDCP4_OVL_SURFACE_OFFSET_Y 0x4624
+#define mmDCP4_OVL_SWAP_CNTL 0x461F
+#define mmDCP4_OVL_UPDATE 0x4627
+#define mmDCP4_PRESCALE_GRPH_CONTROL 0x462D
+#define mmDCP4_PRESCALE_OVL_CONTROL 0x4631
+#define mmDCP4_PRESCALE_VALUES_GRPH_B 0x4630
+#define mmDCP4_PRESCALE_VALUES_GRPH_G 0x462F
+#define mmDCP4_PRESCALE_VALUES_GRPH_R 0x462E
+#define mmDCP4_PRESCALE_VALUES_OVL_CB 0x4632
+#define mmDCP4_PRESCALE_VALUES_OVL_CR 0x4634
+#define mmDCP4_PRESCALE_VALUES_OVL_Y 0x4633
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL1 0x46A6
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL2 0x46A7
+#define mmDCP4_REGAMMA_CNTLA_REGION_0_1 0x46A8
+#define mmDCP4_REGAMMA_CNTLA_REGION_10_11 0x46AD
+#define mmDCP4_REGAMMA_CNTLA_REGION_12_13 0x46AE
+#define mmDCP4_REGAMMA_CNTLA_REGION_14_15 0x46AF
+#define mmDCP4_REGAMMA_CNTLA_REGION_2_3 0x46A9
+#define mmDCP4_REGAMMA_CNTLA_REGION_4_5 0x46AA
+#define mmDCP4_REGAMMA_CNTLA_REGION_6_7 0x46AB
+#define mmDCP4_REGAMMA_CNTLA_REGION_8_9 0x46AC
+#define mmDCP4_REGAMMA_CNTLA_SLOPE_CNTL 0x46A5
+#define mmDCP4_REGAMMA_CNTLA_START_CNTL 0x46A4
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL1 0x46B2
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL2 0x46B3
+#define mmDCP4_REGAMMA_CNTLB_REGION_0_1 0x46B4
+#define mmDCP4_REGAMMA_CNTLB_REGION_10_11 0x46B9
+#define mmDCP4_REGAMMA_CNTLB_REGION_12_13 0x46BA
+#define mmDCP4_REGAMMA_CNTLB_REGION_14_15 0x46BB
+#define mmDCP4_REGAMMA_CNTLB_REGION_2_3 0x46B5
+#define mmDCP4_REGAMMA_CNTLB_REGION_4_5 0x46B6
+#define mmDCP4_REGAMMA_CNTLB_REGION_6_7 0x46B7
+#define mmDCP4_REGAMMA_CNTLB_REGION_8_9 0x46B8
+#define mmDCP4_REGAMMA_CNTLB_SLOPE_CNTL 0x46B1
+#define mmDCP4_REGAMMA_CNTLB_START_CNTL 0x46B0
+#define mmDCP4_REGAMMA_CONTROL 0x46A0
+#define mmDCP4_REGAMMA_LUT_DATA 0x46A2
+#define mmDCP4_REGAMMA_LUT_INDEX 0x46A1
+#define mmDCP4_REGAMMA_LUT_WRITE_EN_MASK 0x46A3
+#define mmDCP5_COMM_MATRIXA_TRANS_C11_C12 0x4943
+#define mmDCP5_COMM_MATRIXA_TRANS_C13_C14 0x4944
+#define mmDCP5_COMM_MATRIXA_TRANS_C21_C22 0x4945
+#define mmDCP5_COMM_MATRIXA_TRANS_C23_C24 0x4946
+#define mmDCP5_COMM_MATRIXA_TRANS_C31_C32 0x4947
+#define mmDCP5_COMM_MATRIXA_TRANS_C33_C34 0x4948
+#define mmDCP5_COMM_MATRIXB_TRANS_C11_C12 0x4949
+#define mmDCP5_COMM_MATRIXB_TRANS_C13_C14 0x494A
+#define mmDCP5_COMM_MATRIXB_TRANS_C21_C22 0x494B
+#define mmDCP5_COMM_MATRIXB_TRANS_C23_C24 0x494C
+#define mmDCP5_COMM_MATRIXB_TRANS_C31_C32 0x494D
+#define mmDCP5_COMM_MATRIXB_TRANS_C33_C34 0x494E
+#define mmDCP5_CUR_COLOR1 0x496C
+#define mmDCP5_CUR_COLOR2 0x496D
+#define mmDCP5_CUR_CONTROL 0x4966
+#define mmDCP5_CUR_HOT_SPOT 0x496B
+#define mmDCP5_CUR_POSITION 0x496A
+#define mmDCP5_CUR_REQUEST_FILTER_CNTL 0x4999
+#define mmDCP5_CUR_SIZE 0x4968
+#define mmDCP5_CUR_SURFACE_ADDRESS 0x4967
+#define mmDCP5_CUR_SURFACE_ADDRESS_HIGH 0x4969
+#define mmDCP5_CUR_UPDATE 0x496E
+#define mmDCP5_DC_LUT_30_COLOR 0x497C
+#define mmDCP5_DC_LUT_AUTOFILL 0x497F
+#define mmDCP5_DC_LUT_BLACK_OFFSET_BLUE 0x4981
+#define mmDCP5_DC_LUT_BLACK_OFFSET_GREEN 0x4982
+#define mmDCP5_DC_LUT_BLACK_OFFSET_RED 0x4983
+#define mmDCP5_DC_LUT_CONTROL 0x4980
+#define mmDCP5_DC_LUT_PWL_DATA 0x497B
+#define mmDCP5_DC_LUT_RW_INDEX 0x4979
+#define mmDCP5_DC_LUT_RW_MODE 0x4978
+#define mmDCP5_DC_LUT_SEQ_COLOR 0x497A
+#define mmDCP5_DC_LUT_VGA_ACCESS_ENABLE 0x497D
+#define mmDCP5_DC_LUT_WHITE_OFFSET_BLUE 0x4984
+#define mmDCP5_DC_LUT_WHITE_OFFSET_GREEN 0x4985
+#define mmDCP5_DC_LUT_WHITE_OFFSET_RED 0x4986
+#define mmDCP5_DC_LUT_WRITE_EN_MASK 0x497E
+#define mmDCP5_DCP_CRC_CONTROL 0x4987
+#define mmDCP5_DCP_CRC_CURRENT 0x4989
+#define mmDCP5_DCP_CRC_LAST 0x498B
+#define mmDCP5_DCP_CRC_MASK 0x4988
+#define mmDCP5_DCP_DEBUG 0x498D
+#define mmDCP5_DCP_DEBUG2 0x4998
+#define mmDCP5_DCP_FP_CONVERTED_FIELD 0x4965
+#define mmDCP5_DCP_GSL_CONTROL 0x4990
+#define mmDCP5_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4991
+#define mmDCP5_DCP_RANDOM_SEEDS 0x4961
+#define mmDCP5_DCP_SPATIAL_DITHER_CNTL 0x4960
+#define mmDCP5_DCP_TEST_DEBUG_DATA 0x4996
+#define mmDCP5_DCP_TEST_DEBUG_INDEX 0x4995
+#define mmDCP5_DEGAMMA_CONTROL 0x4958
+#define mmDCP5_DENORM_CONTROL 0x4950
+#define mmDCP5_GAMUT_REMAP_C11_C12 0x495A
+#define mmDCP5_GAMUT_REMAP_C13_C14 0x495B
+#define mmDCP5_GAMUT_REMAP_C21_C22 0x495C
+#define mmDCP5_GAMUT_REMAP_C23_C24 0x495D
+#define mmDCP5_GAMUT_REMAP_C31_C32 0x495E
+#define mmDCP5_GAMUT_REMAP_C33_C34 0x495F
+#define mmDCP5_GAMUT_REMAP_CONTROL 0x4959
+#define mmDCP5_GRPH_COMPRESS_PITCH 0x491A
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS 0x4919
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x491B
+#define mmDCP5_GRPH_CONTROL 0x4901
+#define mmDCP5_GRPH_DFQ_CONTROL 0x4914
+#define mmDCP5_GRPH_DFQ_STATUS 0x4915
+#define mmDCP5_GRPH_ENABLE 0x4900
+#define mmDCP5_GRPH_FLIP_CONTROL 0x4912
+#define mmDCP5_GRPH_INTERRUPT_CONTROL 0x4917
+#define mmDCP5_GRPH_INTERRUPT_STATUS 0x4916
+#define mmDCP5_GRPH_LUT_10BIT_BYPASS 0x4902
+#define mmDCP5_GRPH_PITCH 0x4906
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS 0x4904
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4907
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS 0x4905
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4908
+#define mmDCP5_GRPH_STEREOSYNC_FLIP 0x4997
+#define mmDCP5_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4918
+#define mmDCP5_GRPH_SURFACE_ADDRESS_INUSE 0x4913
+#define mmDCP5_GRPH_SURFACE_OFFSET_X 0x4909
+#define mmDCP5_GRPH_SURFACE_OFFSET_Y 0x490A
+#define mmDCP5_GRPH_SWAP_CNTL 0x4903
+#define mmDCP5_GRPH_UPDATE 0x4911
+#define mmDCP5_GRPH_X_END 0x490D
+#define mmDCP5_GRPH_X_START 0x490B
+#define mmDCP5_GRPH_Y_END 0x490E
+#define mmDCP5_GRPH_Y_START 0x490C
+#define mmDCP5_INPUT_CSC_C11_C12 0x4936
+#define mmDCP5_INPUT_CSC_C13_C14 0x4937
+#define mmDCP5_INPUT_CSC_C21_C22 0x4938
+#define mmDCP5_INPUT_CSC_C23_C24 0x4939
+#define mmDCP5_INPUT_CSC_C31_C32 0x493A
+#define mmDCP5_INPUT_CSC_C33_C34 0x493B
+#define mmDCP5_INPUT_CSC_CONTROL 0x4935
+#define mmDCP5_INPUT_GAMMA_CONTROL 0x4910
+#define mmDCP5_KEY_CONTROL 0x4953
+#define mmDCP5_KEY_RANGE_ALPHA 0x4954
+#define mmDCP5_KEY_RANGE_BLUE 0x4957
+#define mmDCP5_KEY_RANGE_GREEN 0x4956
+#define mmDCP5_KEY_RANGE_RED 0x4955
+#define mmDCP5_OUTPUT_CSC_C11_C12 0x493D
+#define mmDCP5_OUTPUT_CSC_C13_C14 0x493E
+#define mmDCP5_OUTPUT_CSC_C21_C22 0x493F
+#define mmDCP5_OUTPUT_CSC_C23_C24 0x4940
+#define mmDCP5_OUTPUT_CSC_C31_C32 0x4941
+#define mmDCP5_OUTPUT_CSC_C33_C34 0x4942
+#define mmDCP5_OUTPUT_CSC_CONTROL 0x493C
+#define mmDCP5_OUT_ROUND_CONTROL 0x4951
+#define mmDCP5_OVL_CONTROL1 0x491D
+#define mmDCP5_OVL_CONTROL2 0x491E
+#define mmDCP5_OVL_DFQ_CONTROL 0x4929
+#define mmDCP5_OVL_DFQ_STATUS 0x492A
+#define mmDCP5_OVL_ENABLE 0x491C
+#define mmDCP5_OVL_END 0x4926
+#define mmDCP5_OVL_PITCH 0x4921
+#define mmDCP5_OVLSCL_EDGE_PIXEL_CNTL 0x492C
+#define mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS 0x4992
+#define mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4994
+#define mmDCP5_OVL_START 0x4925
+#define mmDCP5_OVL_STEREOSYNC_FLIP 0x4993
+#define mmDCP5_OVL_SURFACE_ADDRESS 0x4920
+#define mmDCP5_OVL_SURFACE_ADDRESS_HIGH 0x4922
+#define mmDCP5_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x492B
+#define mmDCP5_OVL_SURFACE_ADDRESS_INUSE 0x4928
+#define mmDCP5_OVL_SURFACE_OFFSET_X 0x4923
+#define mmDCP5_OVL_SURFACE_OFFSET_Y 0x4924
+#define mmDCP5_OVL_SWAP_CNTL 0x491F
+#define mmDCP5_OVL_UPDATE 0x4927
+#define mmDCP5_PRESCALE_GRPH_CONTROL 0x492D
+#define mmDCP5_PRESCALE_OVL_CONTROL 0x4931
+#define mmDCP5_PRESCALE_VALUES_GRPH_B 0x4930
+#define mmDCP5_PRESCALE_VALUES_GRPH_G 0x492F
+#define mmDCP5_PRESCALE_VALUES_GRPH_R 0x492E
+#define mmDCP5_PRESCALE_VALUES_OVL_CB 0x4932
+#define mmDCP5_PRESCALE_VALUES_OVL_CR 0x4934
+#define mmDCP5_PRESCALE_VALUES_OVL_Y 0x4933
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL1 0x49A6
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL2 0x49A7
+#define mmDCP5_REGAMMA_CNTLA_REGION_0_1 0x49A8
+#define mmDCP5_REGAMMA_CNTLA_REGION_10_11 0x49AD
+#define mmDCP5_REGAMMA_CNTLA_REGION_12_13 0x49AE
+#define mmDCP5_REGAMMA_CNTLA_REGION_14_15 0x49AF
+#define mmDCP5_REGAMMA_CNTLA_REGION_2_3 0x49A9
+#define mmDCP5_REGAMMA_CNTLA_REGION_4_5 0x49AA
+#define mmDCP5_REGAMMA_CNTLA_REGION_6_7 0x49AB
+#define mmDCP5_REGAMMA_CNTLA_REGION_8_9 0x49AC
+#define mmDCP5_REGAMMA_CNTLA_SLOPE_CNTL 0x49A5
+#define mmDCP5_REGAMMA_CNTLA_START_CNTL 0x49A4
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL1 0x49B2
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL2 0x49B3
+#define mmDCP5_REGAMMA_CNTLB_REGION_0_1 0x49B4
+#define mmDCP5_REGAMMA_CNTLB_REGION_10_11 0x49B9
+#define mmDCP5_REGAMMA_CNTLB_REGION_12_13 0x49BA
+#define mmDCP5_REGAMMA_CNTLB_REGION_14_15 0x49BB
+#define mmDCP5_REGAMMA_CNTLB_REGION_2_3 0x49B5
+#define mmDCP5_REGAMMA_CNTLB_REGION_4_5 0x49B6
+#define mmDCP5_REGAMMA_CNTLB_REGION_6_7 0x49B7
+#define mmDCP5_REGAMMA_CNTLB_REGION_8_9 0x49B8
+#define mmDCP5_REGAMMA_CNTLB_SLOPE_CNTL 0x49B1
+#define mmDCP5_REGAMMA_CNTLB_START_CNTL 0x49B0
+#define mmDCP5_REGAMMA_CONTROL 0x49A0
+#define mmDCP5_REGAMMA_LUT_DATA 0x49A2
+#define mmDCP5_REGAMMA_LUT_INDEX 0x49A1
+#define mmDCP5_REGAMMA_LUT_WRITE_EN_MASK 0x49A3
+#define mmDC_PAD_EXTERN_SIG 0x1902
+#define mmDCP_CRC_CONTROL 0x1A87
+#define mmDCP_CRC_CURRENT 0x1A89
+#define mmDCP_CRC_LAST 0x1A8B
+#define mmDCP_CRC_MASK 0x1A88
+#define mmDCP_DEBUG 0x1A8D
+#define mmDCP_DEBUG2 0x1A98
+#define mmDCP_FP_CONVERTED_FIELD 0x1A65
+#define mmDC_PGCNTL_STATUS_REG 0x177E
+#define mmDC_PGFSM_CONFIG_REG 0x177C
+#define mmDC_PGFSM_WRITE_REG 0x177D
+#define mmDCP_GSL_CONTROL 0x1A90
+#define mmDCPG_TEST_DEBUG_DATA 0x177B
+#define mmDCPG_TEST_DEBUG_INDEX 0x1779
+#define mmDC_PINSTRAPS 0x1917
+#define mmDCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1A91
+#define mmDCP_RANDOM_SEEDS 0x1A61
+#define mmDCP_SPATIAL_DITHER_CNTL 0x1A60
+#define mmDCP_TEST_DEBUG_DATA 0x1A96
+#define mmDCP_TEST_DEBUG_INDEX 0x1A95
+#define mmDC_RBBMIF_RDWR_CNTL1 0x031A
+#define mmDC_RBBMIF_RDWR_CNTL2 0x031D
+#define mmDC_REF_CLK_CNTL 0x1903
+#define mmDC_XDMA_INTERFACE_CNTL 0x0327
+#define mmDEGAMMA_CONTROL 0x1A58
+#define mmDENORM_CONTROL 0x1A50
+#define mmDENTIST_DISPCLK_CNTL 0x0124
+#define mmDIG0_AFMT_60958_0 0x1C41
+#define mmDIG0_AFMT_60958_1 0x1C42
+#define mmDIG0_AFMT_60958_2 0x1C48
+#define mmDIG0_AFMT_AUDIO_CRC_CONTROL 0x1C43
+#define mmDIG0_AFMT_AUDIO_CRC_RESULT 0x1C49
+#define mmDIG0_AFMT_AUDIO_DBG_DTO_CNTL 0x1C52
+#define mmDIG0_AFMT_AUDIO_INFO0 0x1C3F
+#define mmDIG0_AFMT_AUDIO_INFO1 0x1C40
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL 0x1C4B
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL2 0x1C17
+#define mmDIG0_AFMT_AUDIO_SRC_CONTROL 0x1C4F
+#define mmDIG0_AFMT_AVI_INFO0 0x1C21
+#define mmDIG0_AFMT_AVI_INFO1 0x1C22
+#define mmDIG0_AFMT_AVI_INFO2 0x1C23
+#define mmDIG0_AFMT_AVI_INFO3 0x1C24
+#define mmDIG0_AFMT_GENERIC_0 0x1C28
+#define mmDIG0_AFMT_GENERIC_1 0x1C29
+#define mmDIG0_AFMT_GENERIC_2 0x1C2A
+#define mmDIG0_AFMT_GENERIC_3 0x1C2B
+#define mmDIG0_AFMT_GENERIC_4 0x1C2C
+#define mmDIG0_AFMT_GENERIC_5 0x1C2D
+#define mmDIG0_AFMT_GENERIC_6 0x1C2E
+#define mmDIG0_AFMT_GENERIC_7 0x1C2F
+#define mmDIG0_AFMT_GENERIC_HDR 0x1C27
+#define mmDIG0_AFMT_INFOFRAME_CONTROL0 0x1C4D
+#define mmDIG0_AFMT_INTERRUPT_STATUS 0x1C14
+#define mmDIG0_AFMT_ISRC1_0 0x1C18
+#define mmDIG0_AFMT_ISRC1_1 0x1C19
+#define mmDIG0_AFMT_ISRC1_2 0x1C1A
+#define mmDIG0_AFMT_ISRC1_3 0x1C1B
+#define mmDIG0_AFMT_ISRC1_4 0x1C1C
+#define mmDIG0_AFMT_ISRC2_0 0x1C1D
+#define mmDIG0_AFMT_ISRC2_1 0x1C1E
+#define mmDIG0_AFMT_ISRC2_2 0x1C1F
+#define mmDIG0_AFMT_ISRC2_3 0x1C20
+#define mmDIG0_AFMT_MPEG_INFO0 0x1C25
+#define mmDIG0_AFMT_MPEG_INFO1 0x1C26
+#define mmDIG0_AFMT_RAMP_CONTROL0 0x1C44
+#define mmDIG0_AFMT_RAMP_CONTROL1 0x1C45
+#define mmDIG0_AFMT_RAMP_CONTROL2 0x1C46
+#define mmDIG0_AFMT_RAMP_CONTROL3 0x1C47
+#define mmDIG0_AFMT_STATUS 0x1C4A
+#define mmDIG0_AFMT_VBI_PACKET_CONTROL 0x1C4C
+#define mmDIG0_DIG_BE_CNTL 0x1C50
+#define mmDIG0_DIG_BE_EN_CNTL 0x1C51
+#define mmDIG0_DIG_CLOCK_PATTERN 0x1C03
+#define mmDIG0_DIG_DISPCLK_SWITCH_CNTL 0x1C08
+#define mmDIG0_DIG_DISPCLK_SWITCH_STATUS 0x1C09
+#define mmDIG0_DIG_FE_CNTL 0x1C00
+#define mmDIG0_DIG_FIFO_STATUS 0x1C0A
+#define mmDIG0_DIG_LANE_ENABLE 0x1C8D
+#define mmDIG0_DIG_OUTPUT_CRC_CNTL 0x1C01
+#define mmDIG0_DIG_OUTPUT_CRC_RESULT 0x1C02
+#define mmDIG0_DIG_RANDOM_PATTERN_SEED 0x1C05
+#define mmDIG0_DIG_TEST_PATTERN 0x1C04
+#define mmDIG0_HDMI_ACR_32_0 0x1C37
+#define mmDIG0_HDMI_ACR_32_1 0x1C38
+#define mmDIG0_HDMI_ACR_44_0 0x1C39
+#define mmDIG0_HDMI_ACR_44_1 0x1C3A
+#define mmDIG0_HDMI_ACR_48_0 0x1C3B
+#define mmDIG0_HDMI_ACR_48_1 0x1C3C
+#define mmDIG0_HDMI_ACR_PACKET_CONTROL 0x1C0F
+#define mmDIG0_HDMI_ACR_STATUS_0 0x1C3D
+#define mmDIG0_HDMI_ACR_STATUS_1 0x1C3E
+#define mmDIG0_HDMI_AUDIO_PACKET_CONTROL 0x1C0E
+#define mmDIG0_HDMI_CONTROL 0x1C0C
+#define mmDIG0_HDMI_GC 0x1C16
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL0 0x1C13
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL1 0x1C30
+#define mmDIG0_HDMI_INFOFRAME_CONTROL0 0x1C11
+#define mmDIG0_HDMI_INFOFRAME_CONTROL1 0x1C12
+#define mmDIG0_HDMI_STATUS 0x1C0D
+#define mmDIG0_HDMI_VBI_PACKET_CONTROL 0x1C10
+#define mmDIG0_LVDS_DATA_CNTL 0x1C8C
+#define mmDIG0_TMDS_CNTL 0x1C7C
+#define mmDIG0_TMDS_CONTROL0_FEEDBACK 0x1C7E
+#define mmDIG0_TMDS_CONTROL_CHAR 0x1C7D
+#define mmDIG0_TMDS_CTL0_1_GEN_CNTL 0x1C86
+#define mmDIG0_TMDS_CTL2_3_GEN_CNTL 0x1C87
+#define mmDIG0_TMDS_CTL_BITS 0x1C83
+#define mmDIG0_TMDS_DCBALANCER_CONTROL 0x1C84
+#define mmDIG0_TMDS_DEBUG 0x1C82
+#define mmDIG0_TMDS_STEREOSYNC_CTL_SEL 0x1C7F
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_0_1 0x1C80
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_2_3 0x1C81
+#define mmDIG1_AFMT_60958_0 0x1F41
+#define mmDIG1_AFMT_60958_1 0x1F42
+#define mmDIG1_AFMT_60958_2 0x1F48
+#define mmDIG1_AFMT_AUDIO_CRC_CONTROL 0x1F43
+#define mmDIG1_AFMT_AUDIO_CRC_RESULT 0x1F49
+#define mmDIG1_AFMT_AUDIO_DBG_DTO_CNTL 0x1F52
+#define mmDIG1_AFMT_AUDIO_INFO0 0x1F3F
+#define mmDIG1_AFMT_AUDIO_INFO1 0x1F40
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL 0x1F4B
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL2 0x1F17
+#define mmDIG1_AFMT_AUDIO_SRC_CONTROL 0x1F4F
+#define mmDIG1_AFMT_AVI_INFO0 0x1F21
+#define mmDIG1_AFMT_AVI_INFO1 0x1F22
+#define mmDIG1_AFMT_AVI_INFO2 0x1F23
+#define mmDIG1_AFMT_AVI_INFO3 0x1F24
+#define mmDIG1_AFMT_GENERIC_0 0x1F28
+#define mmDIG1_AFMT_GENERIC_1 0x1F29
+#define mmDIG1_AFMT_GENERIC_2 0x1F2A
+#define mmDIG1_AFMT_GENERIC_3 0x1F2B
+#define mmDIG1_AFMT_GENERIC_4 0x1F2C
+#define mmDIG1_AFMT_GENERIC_5 0x1F2D
+#define mmDIG1_AFMT_GENERIC_6 0x1F2E
+#define mmDIG1_AFMT_GENERIC_7 0x1F2F
+#define mmDIG1_AFMT_GENERIC_HDR 0x1F27
+#define mmDIG1_AFMT_INFOFRAME_CONTROL0 0x1F4D
+#define mmDIG1_AFMT_INTERRUPT_STATUS 0x1F14
+#define mmDIG1_AFMT_ISRC1_0 0x1F18
+#define mmDIG1_AFMT_ISRC1_1 0x1F19
+#define mmDIG1_AFMT_ISRC1_2 0x1F1A
+#define mmDIG1_AFMT_ISRC1_3 0x1F1B
+#define mmDIG1_AFMT_ISRC1_4 0x1F1C
+#define mmDIG1_AFMT_ISRC2_0 0x1F1D
+#define mmDIG1_AFMT_ISRC2_1 0x1F1E
+#define mmDIG1_AFMT_ISRC2_2 0x1F1F
+#define mmDIG1_AFMT_ISRC2_3 0x1F20
+#define mmDIG1_AFMT_MPEG_INFO0 0x1F25
+#define mmDIG1_AFMT_MPEG_INFO1 0x1F26
+#define mmDIG1_AFMT_RAMP_CONTROL0 0x1F44
+#define mmDIG1_AFMT_RAMP_CONTROL1 0x1F45
+#define mmDIG1_AFMT_RAMP_CONTROL2 0x1F46
+#define mmDIG1_AFMT_RAMP_CONTROL3 0x1F47
+#define mmDIG1_AFMT_STATUS 0x1F4A
+#define mmDIG1_AFMT_VBI_PACKET_CONTROL 0x1F4C
+#define mmDIG1_DIG_BE_CNTL 0x1F50
+#define mmDIG1_DIG_BE_EN_CNTL 0x1F51
+#define mmDIG1_DIG_CLOCK_PATTERN 0x1F03
+#define mmDIG1_DIG_DISPCLK_SWITCH_CNTL 0x1F08
+#define mmDIG1_DIG_DISPCLK_SWITCH_STATUS 0x1F09
+#define mmDIG1_DIG_FE_CNTL 0x1F00
+#define mmDIG1_DIG_FIFO_STATUS 0x1F0A
+#define mmDIG1_DIG_LANE_ENABLE 0x1F8D
+#define mmDIG1_DIG_OUTPUT_CRC_CNTL 0x1F01
+#define mmDIG1_DIG_OUTPUT_CRC_RESULT 0x1F02
+#define mmDIG1_DIG_RANDOM_PATTERN_SEED 0x1F05
+#define mmDIG1_DIG_TEST_PATTERN 0x1F04
+#define mmDIG1_HDMI_ACR_32_0 0x1F37
+#define mmDIG1_HDMI_ACR_32_1 0x1F38
+#define mmDIG1_HDMI_ACR_44_0 0x1F39
+#define mmDIG1_HDMI_ACR_44_1 0x1F3A
+#define mmDIG1_HDMI_ACR_48_0 0x1F3B
+#define mmDIG1_HDMI_ACR_48_1 0x1F3C
+#define mmDIG1_HDMI_ACR_PACKET_CONTROL 0x1F0F
+#define mmDIG1_HDMI_ACR_STATUS_0 0x1F3D
+#define mmDIG1_HDMI_ACR_STATUS_1 0x1F3E
+#define mmDIG1_HDMI_AUDIO_PACKET_CONTROL 0x1F0E
+#define mmDIG1_HDMI_CONTROL 0x1F0C
+#define mmDIG1_HDMI_GC 0x1F16
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL0 0x1F13
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL1 0x1F30
+#define mmDIG1_HDMI_INFOFRAME_CONTROL0 0x1F11
+#define mmDIG1_HDMI_INFOFRAME_CONTROL1 0x1F12
+#define mmDIG1_HDMI_STATUS 0x1F0D
+#define mmDIG1_HDMI_VBI_PACKET_CONTROL 0x1F10
+#define mmDIG1_LVDS_DATA_CNTL 0x1F8C
+#define mmDIG1_TMDS_CNTL 0x1F7C
+#define mmDIG1_TMDS_CONTROL0_FEEDBACK 0x1F7E
+#define mmDIG1_TMDS_CONTROL_CHAR 0x1F7D
+#define mmDIG1_TMDS_CTL0_1_GEN_CNTL 0x1F86
+#define mmDIG1_TMDS_CTL2_3_GEN_CNTL 0x1F87
+#define mmDIG1_TMDS_CTL_BITS 0x1F83
+#define mmDIG1_TMDS_DCBALANCER_CONTROL 0x1F84
+#define mmDIG1_TMDS_DEBUG 0x1F82
+#define mmDIG1_TMDS_STEREOSYNC_CTL_SEL 0x1F7F
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_0_1 0x1F80
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_2_3 0x1F81
+#define mmDIG2_AFMT_60958_0 0x4241
+#define mmDIG2_AFMT_60958_1 0x4242
+#define mmDIG2_AFMT_60958_2 0x4248
+#define mmDIG2_AFMT_AUDIO_CRC_CONTROL 0x4243
+#define mmDIG2_AFMT_AUDIO_CRC_RESULT 0x4249
+#define mmDIG2_AFMT_AUDIO_DBG_DTO_CNTL 0x4252
+#define mmDIG2_AFMT_AUDIO_INFO0 0x423F
+#define mmDIG2_AFMT_AUDIO_INFO1 0x4240
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL 0x424B
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL2 0x4217
+#define mmDIG2_AFMT_AUDIO_SRC_CONTROL 0x424F
+#define mmDIG2_AFMT_AVI_INFO0 0x4221
+#define mmDIG2_AFMT_AVI_INFO1 0x4222
+#define mmDIG2_AFMT_AVI_INFO2 0x4223
+#define mmDIG2_AFMT_AVI_INFO3 0x4224
+#define mmDIG2_AFMT_GENERIC_0 0x4228
+#define mmDIG2_AFMT_GENERIC_1 0x4229
+#define mmDIG2_AFMT_GENERIC_2 0x422A
+#define mmDIG2_AFMT_GENERIC_3 0x422B
+#define mmDIG2_AFMT_GENERIC_4 0x422C
+#define mmDIG2_AFMT_GENERIC_5 0x422D
+#define mmDIG2_AFMT_GENERIC_6 0x422E
+#define mmDIG2_AFMT_GENERIC_7 0x422F
+#define mmDIG2_AFMT_GENERIC_HDR 0x4227
+#define mmDIG2_AFMT_INFOFRAME_CONTROL0 0x424D
+#define mmDIG2_AFMT_INTERRUPT_STATUS 0x4214
+#define mmDIG2_AFMT_ISRC1_0 0x4218
+#define mmDIG2_AFMT_ISRC1_1 0x4219
+#define mmDIG2_AFMT_ISRC1_2 0x421A
+#define mmDIG2_AFMT_ISRC1_3 0x421B
+#define mmDIG2_AFMT_ISRC1_4 0x421C
+#define mmDIG2_AFMT_ISRC2_0 0x421D
+#define mmDIG2_AFMT_ISRC2_1 0x421E
+#define mmDIG2_AFMT_ISRC2_2 0x421F
+#define mmDIG2_AFMT_ISRC2_3 0x4220
+#define mmDIG2_AFMT_MPEG_INFO0 0x4225
+#define mmDIG2_AFMT_MPEG_INFO1 0x4226
+#define mmDIG2_AFMT_RAMP_CONTROL0 0x4244
+#define mmDIG2_AFMT_RAMP_CONTROL1 0x4245
+#define mmDIG2_AFMT_RAMP_CONTROL2 0x4246
+#define mmDIG2_AFMT_RAMP_CONTROL3 0x4247
+#define mmDIG2_AFMT_STATUS 0x424A
+#define mmDIG2_AFMT_VBI_PACKET_CONTROL 0x424C
+#define mmDIG2_DIG_BE_CNTL 0x4250
+#define mmDIG2_DIG_BE_EN_CNTL 0x4251
+#define mmDIG2_DIG_CLOCK_PATTERN 0x4203
+#define mmDIG2_DIG_DISPCLK_SWITCH_CNTL 0x4208
+#define mmDIG2_DIG_DISPCLK_SWITCH_STATUS 0x4209
+#define mmDIG2_DIG_FE_CNTL 0x4200
+#define mmDIG2_DIG_FIFO_STATUS 0x420A
+#define mmDIG2_DIG_LANE_ENABLE 0x428D
+#define mmDIG2_DIG_OUTPUT_CRC_CNTL 0x4201
+#define mmDIG2_DIG_OUTPUT_CRC_RESULT 0x4202
+#define mmDIG2_DIG_RANDOM_PATTERN_SEED 0x4205
+#define mmDIG2_DIG_TEST_PATTERN 0x4204
+#define mmDIG2_HDMI_ACR_32_0 0x4237
+#define mmDIG2_HDMI_ACR_32_1 0x4238
+#define mmDIG2_HDMI_ACR_44_0 0x4239
+#define mmDIG2_HDMI_ACR_44_1 0x423A
+#define mmDIG2_HDMI_ACR_48_0 0x423B
+#define mmDIG2_HDMI_ACR_48_1 0x423C
+#define mmDIG2_HDMI_ACR_PACKET_CONTROL 0x420F
+#define mmDIG2_HDMI_ACR_STATUS_0 0x423D
+#define mmDIG2_HDMI_ACR_STATUS_1 0x423E
+#define mmDIG2_HDMI_AUDIO_PACKET_CONTROL 0x420E
+#define mmDIG2_HDMI_CONTROL 0x420C
+#define mmDIG2_HDMI_GC 0x4216
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL0 0x4213
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL1 0x4230
+#define mmDIG2_HDMI_INFOFRAME_CONTROL0 0x4211
+#define mmDIG2_HDMI_INFOFRAME_CONTROL1 0x4212
+#define mmDIG2_HDMI_STATUS 0x420D
+#define mmDIG2_HDMI_VBI_PACKET_CONTROL 0x4210
+#define mmDIG2_LVDS_DATA_CNTL 0x428C
+#define mmDIG2_TMDS_CNTL 0x427C
+#define mmDIG2_TMDS_CONTROL0_FEEDBACK 0x427E
+#define mmDIG2_TMDS_CONTROL_CHAR 0x427D
+#define mmDIG2_TMDS_CTL0_1_GEN_CNTL 0x4286
+#define mmDIG2_TMDS_CTL2_3_GEN_CNTL 0x4287
+#define mmDIG2_TMDS_CTL_BITS 0x4283
+#define mmDIG2_TMDS_DCBALANCER_CONTROL 0x4284
+#define mmDIG2_TMDS_DEBUG 0x4282
+#define mmDIG2_TMDS_STEREOSYNC_CTL_SEL 0x427F
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_0_1 0x4280
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_2_3 0x4281
+#define mmDIG3_AFMT_60958_0 0x4541
+#define mmDIG3_AFMT_60958_1 0x4542
+#define mmDIG3_AFMT_60958_2 0x4548
+#define mmDIG3_AFMT_AUDIO_CRC_CONTROL 0x4543
+#define mmDIG3_AFMT_AUDIO_CRC_RESULT 0x4549
+#define mmDIG3_AFMT_AUDIO_DBG_DTO_CNTL 0x4552
+#define mmDIG3_AFMT_AUDIO_INFO0 0x453F
+#define mmDIG3_AFMT_AUDIO_INFO1 0x4540
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL 0x454B
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL2 0x4517
+#define mmDIG3_AFMT_AUDIO_SRC_CONTROL 0x454F
+#define mmDIG3_AFMT_AVI_INFO0 0x4521
+#define mmDIG3_AFMT_AVI_INFO1 0x4522
+#define mmDIG3_AFMT_AVI_INFO2 0x4523
+#define mmDIG3_AFMT_AVI_INFO3 0x4524
+#define mmDIG3_AFMT_GENERIC_0 0x4528
+#define mmDIG3_AFMT_GENERIC_1 0x4529
+#define mmDIG3_AFMT_GENERIC_2 0x452A
+#define mmDIG3_AFMT_GENERIC_3 0x452B
+#define mmDIG3_AFMT_GENERIC_4 0x452C
+#define mmDIG3_AFMT_GENERIC_5 0x452D
+#define mmDIG3_AFMT_GENERIC_6 0x452E
+#define mmDIG3_AFMT_GENERIC_7 0x452F
+#define mmDIG3_AFMT_GENERIC_HDR 0x4527
+#define mmDIG3_AFMT_INFOFRAME_CONTROL0 0x454D
+#define mmDIG3_AFMT_INTERRUPT_STATUS 0x4514
+#define mmDIG3_AFMT_ISRC1_0 0x4518
+#define mmDIG3_AFMT_ISRC1_1 0x4519
+#define mmDIG3_AFMT_ISRC1_2 0x451A
+#define mmDIG3_AFMT_ISRC1_3 0x451B
+#define mmDIG3_AFMT_ISRC1_4 0x451C
+#define mmDIG3_AFMT_ISRC2_0 0x451D
+#define mmDIG3_AFMT_ISRC2_1 0x451E
+#define mmDIG3_AFMT_ISRC2_2 0x451F
+#define mmDIG3_AFMT_ISRC2_3 0x4520
+#define mmDIG3_AFMT_MPEG_INFO0 0x4525
+#define mmDIG3_AFMT_MPEG_INFO1 0x4526
+#define mmDIG3_AFMT_RAMP_CONTROL0 0x4544
+#define mmDIG3_AFMT_RAMP_CONTROL1 0x4545
+#define mmDIG3_AFMT_RAMP_CONTROL2 0x4546
+#define mmDIG3_AFMT_RAMP_CONTROL3 0x4547
+#define mmDIG3_AFMT_STATUS 0x454A
+#define mmDIG3_AFMT_VBI_PACKET_CONTROL 0x454C
+#define mmDIG3_DIG_BE_CNTL 0x4550
+#define mmDIG3_DIG_BE_EN_CNTL 0x4551
+#define mmDIG3_DIG_CLOCK_PATTERN 0x4503
+#define mmDIG3_DIG_DISPCLK_SWITCH_CNTL 0x4508
+#define mmDIG3_DIG_DISPCLK_SWITCH_STATUS 0x4509
+#define mmDIG3_DIG_FE_CNTL 0x4500
+#define mmDIG3_DIG_FIFO_STATUS 0x450A
+#define mmDIG3_DIG_LANE_ENABLE 0x458D
+#define mmDIG3_DIG_OUTPUT_CRC_CNTL 0x4501
+#define mmDIG3_DIG_OUTPUT_CRC_RESULT 0x4502
+#define mmDIG3_DIG_RANDOM_PATTERN_SEED 0x4505
+#define mmDIG3_DIG_TEST_PATTERN 0x4504
+#define mmDIG3_HDMI_ACR_32_0 0x4537
+#define mmDIG3_HDMI_ACR_32_1 0x4538
+#define mmDIG3_HDMI_ACR_44_0 0x4539
+#define mmDIG3_HDMI_ACR_44_1 0x453A
+#define mmDIG3_HDMI_ACR_48_0 0x453B
+#define mmDIG3_HDMI_ACR_48_1 0x453C
+#define mmDIG3_HDMI_ACR_PACKET_CONTROL 0x450F
+#define mmDIG3_HDMI_ACR_STATUS_0 0x453D
+#define mmDIG3_HDMI_ACR_STATUS_1 0x453E
+#define mmDIG3_HDMI_AUDIO_PACKET_CONTROL 0x450E
+#define mmDIG3_HDMI_CONTROL 0x450C
+#define mmDIG3_HDMI_GC 0x4516
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL0 0x4513
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL1 0x4530
+#define mmDIG3_HDMI_INFOFRAME_CONTROL0 0x4511
+#define mmDIG3_HDMI_INFOFRAME_CONTROL1 0x4512
+#define mmDIG3_HDMI_STATUS 0x450D
+#define mmDIG3_HDMI_VBI_PACKET_CONTROL 0x4510
+#define mmDIG3_LVDS_DATA_CNTL 0x458C
+#define mmDIG3_TMDS_CNTL 0x457C
+#define mmDIG3_TMDS_CONTROL0_FEEDBACK 0x457E
+#define mmDIG3_TMDS_CONTROL_CHAR 0x457D
+#define mmDIG3_TMDS_CTL0_1_GEN_CNTL 0x4586
+#define mmDIG3_TMDS_CTL2_3_GEN_CNTL 0x4587
+#define mmDIG3_TMDS_CTL_BITS 0x4583
+#define mmDIG3_TMDS_DCBALANCER_CONTROL 0x4584
+#define mmDIG3_TMDS_DEBUG 0x4582
+#define mmDIG3_TMDS_STEREOSYNC_CTL_SEL 0x457F
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_0_1 0x4580
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_2_3 0x4581
+#define mmDIG4_AFMT_60958_0 0x4841
+#define mmDIG4_AFMT_60958_1 0x4842
+#define mmDIG4_AFMT_60958_2 0x4848
+#define mmDIG4_AFMT_AUDIO_CRC_CONTROL 0x4843
+#define mmDIG4_AFMT_AUDIO_CRC_RESULT 0x4849
+#define mmDIG4_AFMT_AUDIO_DBG_DTO_CNTL 0x4852
+#define mmDIG4_AFMT_AUDIO_INFO0 0x483F
+#define mmDIG4_AFMT_AUDIO_INFO1 0x4840
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL 0x484B
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL2 0x4817
+#define mmDIG4_AFMT_AUDIO_SRC_CONTROL 0x484F
+#define mmDIG4_AFMT_AVI_INFO0 0x4821
+#define mmDIG4_AFMT_AVI_INFO1 0x4822
+#define mmDIG4_AFMT_AVI_INFO2 0x4823
+#define mmDIG4_AFMT_AVI_INFO3 0x4824
+#define mmDIG4_AFMT_GENERIC_0 0x4828
+#define mmDIG4_AFMT_GENERIC_1 0x4829
+#define mmDIG4_AFMT_GENERIC_2 0x482A
+#define mmDIG4_AFMT_GENERIC_3 0x482B
+#define mmDIG4_AFMT_GENERIC_4 0x482C
+#define mmDIG4_AFMT_GENERIC_5 0x482D
+#define mmDIG4_AFMT_GENERIC_6 0x482E
+#define mmDIG4_AFMT_GENERIC_7 0x482F
+#define mmDIG4_AFMT_GENERIC_HDR 0x4827
+#define mmDIG4_AFMT_INFOFRAME_CONTROL0 0x484D
+#define mmDIG4_AFMT_INTERRUPT_STATUS 0x4814
+#define mmDIG4_AFMT_ISRC1_0 0x4818
+#define mmDIG4_AFMT_ISRC1_1 0x4819
+#define mmDIG4_AFMT_ISRC1_2 0x481A
+#define mmDIG4_AFMT_ISRC1_3 0x481B
+#define mmDIG4_AFMT_ISRC1_4 0x481C
+#define mmDIG4_AFMT_ISRC2_0 0x481D
+#define mmDIG4_AFMT_ISRC2_1 0x481E
+#define mmDIG4_AFMT_ISRC2_2 0x481F
+#define mmDIG4_AFMT_ISRC2_3 0x4820
+#define mmDIG4_AFMT_MPEG_INFO0 0x4825
+#define mmDIG4_AFMT_MPEG_INFO1 0x4826
+#define mmDIG4_AFMT_RAMP_CONTROL0 0x4844
+#define mmDIG4_AFMT_RAMP_CONTROL1 0x4845
+#define mmDIG4_AFMT_RAMP_CONTROL2 0x4846
+#define mmDIG4_AFMT_RAMP_CONTROL3 0x4847
+#define mmDIG4_AFMT_STATUS 0x484A
+#define mmDIG4_AFMT_VBI_PACKET_CONTROL 0x484C
+#define mmDIG4_DIG_BE_CNTL 0x4850
+#define mmDIG4_DIG_BE_EN_CNTL 0x4851
+#define mmDIG4_DIG_CLOCK_PATTERN 0x4803
+#define mmDIG4_DIG_DISPCLK_SWITCH_CNTL 0x4808
+#define mmDIG4_DIG_DISPCLK_SWITCH_STATUS 0x4809
+#define mmDIG4_DIG_FE_CNTL 0x4800
+#define mmDIG4_DIG_FIFO_STATUS 0x480A
+#define mmDIG4_DIG_LANE_ENABLE 0x488D
+#define mmDIG4_DIG_OUTPUT_CRC_CNTL 0x4801
+#define mmDIG4_DIG_OUTPUT_CRC_RESULT 0x4802
+#define mmDIG4_DIG_RANDOM_PATTERN_SEED 0x4805
+#define mmDIG4_DIG_TEST_PATTERN 0x4804
+#define mmDIG4_HDMI_ACR_32_0 0x4837
+#define mmDIG4_HDMI_ACR_32_1 0x4838
+#define mmDIG4_HDMI_ACR_44_0 0x4839
+#define mmDIG4_HDMI_ACR_44_1 0x483A
+#define mmDIG4_HDMI_ACR_48_0 0x483B
+#define mmDIG4_HDMI_ACR_48_1 0x483C
+#define mmDIG4_HDMI_ACR_PACKET_CONTROL 0x480F
+#define mmDIG4_HDMI_ACR_STATUS_0 0x483D
+#define mmDIG4_HDMI_ACR_STATUS_1 0x483E
+#define mmDIG4_HDMI_AUDIO_PACKET_CONTROL 0x480E
+#define mmDIG4_HDMI_CONTROL 0x480C
+#define mmDIG4_HDMI_GC 0x4816
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL0 0x4813
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL1 0x4830
+#define mmDIG4_HDMI_INFOFRAME_CONTROL0 0x4811
+#define mmDIG4_HDMI_INFOFRAME_CONTROL1 0x4812
+#define mmDIG4_HDMI_STATUS 0x480D
+#define mmDIG4_HDMI_VBI_PACKET_CONTROL 0x4810
+#define mmDIG4_LVDS_DATA_CNTL 0x488C
+#define mmDIG4_TMDS_CNTL 0x487C
+#define mmDIG4_TMDS_CONTROL0_FEEDBACK 0x487E
+#define mmDIG4_TMDS_CONTROL_CHAR 0x487D
+#define mmDIG4_TMDS_CTL0_1_GEN_CNTL 0x4886
+#define mmDIG4_TMDS_CTL2_3_GEN_CNTL 0x4887
+#define mmDIG4_TMDS_CTL_BITS 0x4883
+#define mmDIG4_TMDS_DCBALANCER_CONTROL 0x4884
+#define mmDIG4_TMDS_DEBUG 0x4882
+#define mmDIG4_TMDS_STEREOSYNC_CTL_SEL 0x487F
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_0_1 0x4880
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_2_3 0x4881
+#define mmDIG5_AFMT_60958_0 0x4B41
+#define mmDIG5_AFMT_60958_1 0x4B42
+#define mmDIG5_AFMT_60958_2 0x4B48
+#define mmDIG5_AFMT_AUDIO_CRC_CONTROL 0x4B43
+#define mmDIG5_AFMT_AUDIO_CRC_RESULT 0x4B49
+#define mmDIG5_AFMT_AUDIO_DBG_DTO_CNTL 0x4B52
+#define mmDIG5_AFMT_AUDIO_INFO0 0x4B3F
+#define mmDIG5_AFMT_AUDIO_INFO1 0x4B40
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL 0x4B4B
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL2 0x4B17
+#define mmDIG5_AFMT_AUDIO_SRC_CONTROL 0x4B4F
+#define mmDIG5_AFMT_AVI_INFO0 0x4B21
+#define mmDIG5_AFMT_AVI_INFO1 0x4B22
+#define mmDIG5_AFMT_AVI_INFO2 0x4B23
+#define mmDIG5_AFMT_AVI_INFO3 0x4B24
+#define mmDIG5_AFMT_GENERIC_0 0x4B28
+#define mmDIG5_AFMT_GENERIC_1 0x4B29
+#define mmDIG5_AFMT_GENERIC_2 0x4B2A
+#define mmDIG5_AFMT_GENERIC_3 0x4B2B
+#define mmDIG5_AFMT_GENERIC_4 0x4B2C
+#define mmDIG5_AFMT_GENERIC_5 0x4B2D
+#define mmDIG5_AFMT_GENERIC_6 0x4B2E
+#define mmDIG5_AFMT_GENERIC_7 0x4B2F
+#define mmDIG5_AFMT_GENERIC_HDR 0x4B27
+#define mmDIG5_AFMT_INFOFRAME_CONTROL0 0x4B4D
+#define mmDIG5_AFMT_INTERRUPT_STATUS 0x4B14
+#define mmDIG5_AFMT_ISRC1_0 0x4B18
+#define mmDIG5_AFMT_ISRC1_1 0x4B19
+#define mmDIG5_AFMT_ISRC1_2 0x4B1A
+#define mmDIG5_AFMT_ISRC1_3 0x4B1B
+#define mmDIG5_AFMT_ISRC1_4 0x4B1C
+#define mmDIG5_AFMT_ISRC2_0 0x4B1D
+#define mmDIG5_AFMT_ISRC2_1 0x4B1E
+#define mmDIG5_AFMT_ISRC2_2 0x4B1F
+#define mmDIG5_AFMT_ISRC2_3 0x4B20
+#define mmDIG5_AFMT_MPEG_INFO0 0x4B25
+#define mmDIG5_AFMT_MPEG_INFO1 0x4B26
+#define mmDIG5_AFMT_RAMP_CONTROL0 0x4B44
+#define mmDIG5_AFMT_RAMP_CONTROL1 0x4B45
+#define mmDIG5_AFMT_RAMP_CONTROL2 0x4B46
+#define mmDIG5_AFMT_RAMP_CONTROL3 0x4B47
+#define mmDIG5_AFMT_STATUS 0x4B4A
+#define mmDIG5_AFMT_VBI_PACKET_CONTROL 0x4B4C
+#define mmDIG5_DIG_BE_CNTL 0x4B50
+#define mmDIG5_DIG_BE_EN_CNTL 0x4B51
+#define mmDIG5_DIG_CLOCK_PATTERN 0x4B03
+#define mmDIG5_DIG_DISPCLK_SWITCH_CNTL 0x4B08
+#define mmDIG5_DIG_DISPCLK_SWITCH_STATUS 0x4B09
+#define mmDIG5_DIG_FE_CNTL 0x4B00
+#define mmDIG5_DIG_FIFO_STATUS 0x4B0A
+#define mmDIG5_DIG_LANE_ENABLE 0x4B8D
+#define mmDIG5_DIG_OUTPUT_CRC_CNTL 0x4B01
+#define mmDIG5_DIG_OUTPUT_CRC_RESULT 0x4B02
+#define mmDIG5_DIG_RANDOM_PATTERN_SEED 0x4B05
+#define mmDIG5_DIG_TEST_PATTERN 0x4B04
+#define mmDIG5_HDMI_ACR_32_0 0x4B37
+#define mmDIG5_HDMI_ACR_32_1 0x4B38
+#define mmDIG5_HDMI_ACR_44_0 0x4B39
+#define mmDIG5_HDMI_ACR_44_1 0x4B3A
+#define mmDIG5_HDMI_ACR_48_0 0x4B3B
+#define mmDIG5_HDMI_ACR_48_1 0x4B3C
+#define mmDIG5_HDMI_ACR_PACKET_CONTROL 0x4B0F
+#define mmDIG5_HDMI_ACR_STATUS_0 0x4B3D
+#define mmDIG5_HDMI_ACR_STATUS_1 0x4B3E
+#define mmDIG5_HDMI_AUDIO_PACKET_CONTROL 0x4B0E
+#define mmDIG5_HDMI_CONTROL 0x4B0C
+#define mmDIG5_HDMI_GC 0x4B16
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL0 0x4B13
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL1 0x4B30
+#define mmDIG5_HDMI_INFOFRAME_CONTROL0 0x4B11
+#define mmDIG5_HDMI_INFOFRAME_CONTROL1 0x4B12
+#define mmDIG5_HDMI_STATUS 0x4B0D
+#define mmDIG5_HDMI_VBI_PACKET_CONTROL 0x4B10
+#define mmDIG5_LVDS_DATA_CNTL 0x4B8C
+#define mmDIG5_TMDS_CNTL 0x4B7C
+#define mmDIG5_TMDS_CONTROL0_FEEDBACK 0x4B7E
+#define mmDIG5_TMDS_CONTROL_CHAR 0x4B7D
+#define mmDIG5_TMDS_CTL0_1_GEN_CNTL 0x4B86
+#define mmDIG5_TMDS_CTL2_3_GEN_CNTL 0x4B87
+#define mmDIG5_TMDS_CTL_BITS 0x4B83
+#define mmDIG5_TMDS_DCBALANCER_CONTROL 0x4B84
+#define mmDIG5_TMDS_DEBUG 0x4B82
+#define mmDIG5_TMDS_STEREOSYNC_CTL_SEL 0x4B7F
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_0_1 0x4B80
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_2_3 0x4B81
+#define mmDIG_BE_CNTL 0x1C50
+#define mmDIG_BE_EN_CNTL 0x1C51
+#define mmDIG_CLOCK_PATTERN 0x1C03
+#define mmDIG_DISPCLK_SWITCH_CNTL 0x1C08
+#define mmDIG_DISPCLK_SWITCH_STATUS 0x1C09
+#define mmDIG_FE_CNTL 0x1C00
+#define mmDIG_FIFO_STATUS 0x1C0A
+#define mmDIG_LANE_ENABLE 0x1C8D
+#define mmDIG_OUTPUT_CRC_CNTL 0x1C01
+#define mmDIG_OUTPUT_CRC_RESULT 0x1C02
+#define mmDIG_RANDOM_PATTERN_SEED 0x1C05
+#define mmDIG_SOFT_RESET 0x013D
+#define mmDIG_TEST_PATTERN 0x1C04
+#define mmDISPCLK_CGTT_BLK_CTRL_REG 0x0135
+#define mmDISPCLK_FREQ_CHANGE_CNTL 0x0131
+#define mmDISP_INTERRUPT_STATUS 0x183D
+#define mmDISP_INTERRUPT_STATUS_CONTINUE 0x183E
+#define mmDISP_INTERRUPT_STATUS_CONTINUE2 0x183F
+#define mmDISP_INTERRUPT_STATUS_CONTINUE3 0x1840
+#define mmDISP_INTERRUPT_STATUS_CONTINUE4 0x1853
+#define mmDISP_INTERRUPT_STATUS_CONTINUE5 0x1854
+#define mmDISPOUT_STEREOSYNC_SEL 0x18BF
+#define mmDISPPLL_BG_CNTL 0x013C
+#define mmDISP_TIMER_CONTROL 0x1842
+#define mmDMCU_CTRL 0x1600
+#define mmDMCU_ERAM_RD_CTRL 0x160B
+#define mmDMCU_ERAM_RD_DATA 0x160C
+#define mmDMCU_ERAM_WR_CTRL 0x1609
+#define mmDMCU_ERAM_WR_DATA 0x160A
+#define mmDMCU_EVENT_TRIGGER 0x1611
+#define mmDMCU_FW_CHECKSUM_SMPL_BYTE_POS 0x161A
+#define mmDMCU_FW_CS_HI 0x1606
+#define mmDMCU_FW_CS_LO 0x1607
+#define mmDMCU_FW_END_ADDR 0x1604
+#define mmDMCU_FW_ISR_START_ADDR 0x1605
+#define mmDMCU_FW_START_ADDR 0x1603
+#define mmDMCU_INT_CNT 0x1619
+#define mmDMCU_INTERRUPT_STATUS 0x1614
+#define mmDMCU_INTERRUPT_TO_HOST_EN_MASK 0x1615
+#define mmDMCU_INTERRUPT_TO_UC_EN_MASK 0x1616
+#define mmDMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL 0x1617
+#define mmDMCU_IRAM_RD_CTRL 0x160F
+#define mmDMCU_IRAM_RD_DATA 0x1610
+#define mmDMCU_IRAM_WR_CTRL 0x160D
+#define mmDMCU_IRAM_WR_DATA 0x160E
+#define mmDMCU_PC_START_ADDR 0x1602
+#define mmDMCU_RAM_ACCESS_CTRL 0x1608
+#define mmDMCU_STATUS 0x1601
+#define mmDMCU_TEST_DEBUG_DATA 0x1627
+#define mmDMCU_TEST_DEBUG_INDEX 0x1626
+#define mmDMCU_UC_CLK_GATING_CNTL 0x161B
+#define mmDMCU_UC_INTERNAL_INT_STATUS 0x1612
+#define mmDMIF_ADDR_CALC 0x0300
+#define mmDMIF_ADDR_CONFIG 0x02F5
+#define mmDMIF_ARBITRATION_CONTROL 0x02F9
+#define mmDMIF_CONTROL 0x02F6
+#define mmDMIF_HW_DEBUG 0x02F8
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 0x1B30
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL2 0x1B31
+#define mmDMIF_PG0_DPG_PIPE_DPM_CONTROL 0x1B34
+#define mmDMIF_PG0_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1B36
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL 0x1B35
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1B37
+#define mmDMIF_PG0_DPG_PIPE_URGENCY_CONTROL 0x1B33
+#define mmDMIF_PG0_DPG_TEST_DEBUG_DATA 0x1B39
+#define mmDMIF_PG0_DPG_TEST_DEBUG_INDEX 0x1B38
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL1 0x1E30
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL2 0x1E31
+#define mmDMIF_PG1_DPG_PIPE_DPM_CONTROL 0x1E34
+#define mmDMIF_PG1_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1E36
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL 0x1E35
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1E37
+#define mmDMIF_PG1_DPG_PIPE_URGENCY_CONTROL 0x1E33
+#define mmDMIF_PG1_DPG_TEST_DEBUG_DATA 0x1E39
+#define mmDMIF_PG1_DPG_TEST_DEBUG_INDEX 0x1E38
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL1 0x4130
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL2 0x4131
+#define mmDMIF_PG2_DPG_PIPE_DPM_CONTROL 0x4134
+#define mmDMIF_PG2_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4136
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL 0x4135
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4137
+#define mmDMIF_PG2_DPG_PIPE_URGENCY_CONTROL 0x4133
+#define mmDMIF_PG2_DPG_TEST_DEBUG_DATA 0x4139
+#define mmDMIF_PG2_DPG_TEST_DEBUG_INDEX 0x4138
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL1 0x4430
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL2 0x4431
+#define mmDMIF_PG3_DPG_PIPE_DPM_CONTROL 0x4434
+#define mmDMIF_PG3_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4436
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL 0x4435
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4437
+#define mmDMIF_PG3_DPG_PIPE_URGENCY_CONTROL 0x4433
+#define mmDMIF_PG3_DPG_TEST_DEBUG_DATA 0x4439
+#define mmDMIF_PG3_DPG_TEST_DEBUG_INDEX 0x4438
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL1 0x4730
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL2 0x4731
+#define mmDMIF_PG4_DPG_PIPE_DPM_CONTROL 0x4734
+#define mmDMIF_PG4_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4736
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL 0x4735
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4737
+#define mmDMIF_PG4_DPG_PIPE_URGENCY_CONTROL 0x4733
+#define mmDMIF_PG4_DPG_TEST_DEBUG_DATA 0x4739
+#define mmDMIF_PG4_DPG_TEST_DEBUG_INDEX 0x4738
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL1 0x4A30
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL2 0x4A31
+#define mmDMIF_PG5_DPG_PIPE_DPM_CONTROL 0x4A34
+#define mmDMIF_PG5_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4A36
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL 0x4A35
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4A37
+#define mmDMIF_PG5_DPG_PIPE_URGENCY_CONTROL 0x4A33
+#define mmDMIF_PG5_DPG_TEST_DEBUG_DATA 0x4A39
+#define mmDMIF_PG5_DPG_TEST_DEBUG_INDEX 0x4A38
+#define mmDMIF_STATUS 0x02F7
+#define mmDMIF_STATUS2 0x0301
+#define mmDMIF_TEST_DEBUG_DATA 0x0313
+#define mmDMIF_TEST_DEBUG_INDEX 0x0312
+#define mmDOUT_DCE_VCE_CONTROL 0x18FF
+#define mmDOUT_POWER_MANAGEMENT_CNTL 0x1841
+#define mmDOUT_SCRATCH0 0x1844
+#define mmDOUT_SCRATCH1 0x1845
+#define mmDOUT_SCRATCH2 0x1846
+#define mmDOUT_SCRATCH3 0x1847
+#define mmDOUT_SCRATCH4 0x1848
+#define mmDOUT_SCRATCH5 0x1849
+#define mmDOUT_SCRATCH6 0x184A
+#define mmDOUT_SCRATCH7 0x184B
+#define mmDOUT_TEST_DEBUG_DATA 0x184E
+#define mmDOUT_TEST_DEBUG_INDEX 0x184D
+#define mmDP0_DP_CONFIG 0x1CC2
+#define mmDP0_DP_DPHY_8B10B_CNTL 0x1CD3
+#define mmDP0_DP_DPHY_CNTL 0x1CD0
+#define mmDP0_DP_DPHY_CRC_CNTL 0x1CD7
+#define mmDP0_DP_DPHY_CRC_EN 0x1CD6
+#define mmDP0_DP_DPHY_CRC_MST_CNTL 0x1CC6
+#define mmDP0_DP_DPHY_CRC_MST_STATUS 0x1CC7
+#define mmDP0_DP_DPHY_CRC_RESULT 0x1CD8
+#define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE
+#define mmDP0_DP_DPHY_FAST_TRAINING_STATUS 0x1CE9
+#define mmDP0_DP_DPHY_PRBS_CNTL 0x1CD4
+#define mmDP0_DP_DPHY_SYM0 0x1CD2
+#define mmDP0_DP_DPHY_SYM1 0x1CE0
+#define mmDP0_DP_DPHY_SYM2 0x1CDF
+#define mmDP0_DP_DPHY_TRAINING_PATTERN_SEL 0x1CD1
+#define mmDP0_DP_HBR2_EYE_PATTERN 0x1CC8
+#define mmDP0_DP_LINK_CNTL 0x1CC0
+#define mmDP0_DP_LINK_FRAMING_CNTL 0x1CCC
+#define mmDP0_DP_MSA_COLORIMETRY 0x1CDA
+#define mmDP0_DP_MSA_MISC 0x1CC5
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE1 0x1CEA
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE2 0x1CEB
+#define mmDP0_DP_MSE_LINK_TIMING 0x1CE8
+#define mmDP0_DP_MSE_MISC_CNTL 0x1CDB
+#define mmDP0_DP_MSE_RATE_CNTL 0x1CE1
+#define mmDP0_DP_MSE_RATE_UPDATE 0x1CE3
+#define mmDP0_DP_MSE_SAT0 0x1CE4
+#define mmDP0_DP_MSE_SAT1 0x1CE5
+#define mmDP0_DP_MSE_SAT2 0x1CE6
+#define mmDP0_DP_MSE_SAT_UPDATE 0x1CE7
+#define mmDP0_DP_PIXEL_FORMAT 0x1CC1
+#define mmDP0_DP_SEC_AUD_M 0x1CA7
+#define mmDP0_DP_SEC_AUD_M_READBACK 0x1CA8
+#define mmDP0_DP_SEC_AUD_N 0x1CA5
+#define mmDP0_DP_SEC_AUD_N_READBACK 0x1CA6
+#define mmDP0_DP_SEC_CNTL 0x1CA0
+#define mmDP0_DP_SEC_CNTL1 0x1CAB
+#define mmDP0_DP_SEC_FRAMING1 0x1CA1
+#define mmDP0_DP_SEC_FRAMING2 0x1CA2
+#define mmDP0_DP_SEC_FRAMING3 0x1CA3
+#define mmDP0_DP_SEC_FRAMING4 0x1CA4
+#define mmDP0_DP_SEC_PACKET_CNTL 0x1CAA
+#define mmDP0_DP_SEC_TIMESTAMP 0x1CA9
+#define mmDP0_DP_STEER_FIFO 0x1CC4
+#define mmDP0_DP_TEST_DEBUG_DATA 0x1CFD
+#define mmDP0_DP_TEST_DEBUG_INDEX 0x1CFC
+#define mmDP0_DP_VID_INTERRUPT_CNTL 0x1CCF
+#define mmDP0_DP_VID_M 0x1CCB
+#define mmDP0_DP_VID_MSA_VBID 0x1CCD
+#define mmDP0_DP_VID_N 0x1CCA
+#define mmDP0_DP_VID_STREAM_CNTL 0x1CC3
+#define mmDP0_DP_VID_TIMING 0x1CC9
+#define mmDP1_DP_CONFIG 0x1FC2
+#define mmDP1_DP_DPHY_8B10B_CNTL 0x1FD3
+#define mmDP1_DP_DPHY_CNTL 0x1FD0
+#define mmDP1_DP_DPHY_CRC_CNTL 0x1FD7
+#define mmDP1_DP_DPHY_CRC_EN 0x1FD6
+#define mmDP1_DP_DPHY_CRC_MST_CNTL 0x1FC6
+#define mmDP1_DP_DPHY_CRC_MST_STATUS 0x1FC7
+#define mmDP1_DP_DPHY_CRC_RESULT 0x1FD8
+#define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE
+#define mmDP1_DP_DPHY_FAST_TRAINING_STATUS 0x1FE9
+#define mmDP1_DP_DPHY_PRBS_CNTL 0x1FD4
+#define mmDP1_DP_DPHY_SYM0 0x1FD2
+#define mmDP1_DP_DPHY_SYM1 0x1FE0
+#define mmDP1_DP_DPHY_SYM2 0x1FDF
+#define mmDP1_DP_DPHY_TRAINING_PATTERN_SEL 0x1FD1
+#define mmDP1_DP_HBR2_EYE_PATTERN 0x1FC8
+#define mmDP1_DP_LINK_CNTL 0x1FC0
+#define mmDP1_DP_LINK_FRAMING_CNTL 0x1FCC
+#define mmDP1_DP_MSA_COLORIMETRY 0x1FDA
+#define mmDP1_DP_MSA_MISC 0x1FC5
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE1 0x1FEA
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE2 0x1FEB
+#define mmDP1_DP_MSE_LINK_TIMING 0x1FE8
+#define mmDP1_DP_MSE_MISC_CNTL 0x1FDB
+#define mmDP1_DP_MSE_RATE_CNTL 0x1FE1
+#define mmDP1_DP_MSE_RATE_UPDATE 0x1FE3
+#define mmDP1_DP_MSE_SAT0 0x1FE4
+#define mmDP1_DP_MSE_SAT1 0x1FE5
+#define mmDP1_DP_MSE_SAT2 0x1FE6
+#define mmDP1_DP_MSE_SAT_UPDATE 0x1FE7
+#define mmDP1_DP_PIXEL_FORMAT 0x1FC1
+#define mmDP1_DP_SEC_AUD_M 0x1FA7
+#define mmDP1_DP_SEC_AUD_M_READBACK 0x1FA8
+#define mmDP1_DP_SEC_AUD_N 0x1FA5
+#define mmDP1_DP_SEC_AUD_N_READBACK 0x1FA6
+#define mmDP1_DP_SEC_CNTL 0x1FA0
+#define mmDP1_DP_SEC_CNTL1 0x1FAB
+#define mmDP1_DP_SEC_FRAMING1 0x1FA1
+#define mmDP1_DP_SEC_FRAMING2 0x1FA2
+#define mmDP1_DP_SEC_FRAMING3 0x1FA3
+#define mmDP1_DP_SEC_FRAMING4 0x1FA4
+#define mmDP1_DP_SEC_PACKET_CNTL 0x1FAA
+#define mmDP1_DP_SEC_TIMESTAMP 0x1FA9
+#define mmDP1_DP_STEER_FIFO 0x1FC4
+#define mmDP1_DP_TEST_DEBUG_DATA 0x1FFD
+#define mmDP1_DP_TEST_DEBUG_INDEX 0x1FFC
+#define mmDP1_DP_VID_INTERRUPT_CNTL 0x1FCF
+#define mmDP1_DP_VID_M 0x1FCB
+#define mmDP1_DP_VID_MSA_VBID 0x1FCD
+#define mmDP1_DP_VID_N 0x1FCA
+#define mmDP1_DP_VID_STREAM_CNTL 0x1FC3
+#define mmDP1_DP_VID_TIMING 0x1FC9
+#define mmDP2_DP_CONFIG 0x42C2
+#define mmDP2_DP_DPHY_8B10B_CNTL 0x42D3
+#define mmDP2_DP_DPHY_CNTL 0x42D0
+#define mmDP2_DP_DPHY_CRC_CNTL 0x42D7
+#define mmDP2_DP_DPHY_CRC_EN 0x42D6
+#define mmDP2_DP_DPHY_CRC_MST_CNTL 0x42C6
+#define mmDP2_DP_DPHY_CRC_MST_STATUS 0x42C7
+#define mmDP2_DP_DPHY_CRC_RESULT 0x42D8
+#define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE
+#define mmDP2_DP_DPHY_FAST_TRAINING_STATUS 0x42E9
+#define mmDP2_DP_DPHY_PRBS_CNTL 0x42D4
+#define mmDP2_DP_DPHY_SYM0 0x42D2
+#define mmDP2_DP_DPHY_SYM1 0x42E0
+#define mmDP2_DP_DPHY_SYM2 0x42DF
+#define mmDP2_DP_DPHY_TRAINING_PATTERN_SEL 0x42D1
+#define mmDP2_DP_HBR2_EYE_PATTERN 0x42C8
+#define mmDP2_DP_LINK_CNTL 0x42C0
+#define mmDP2_DP_LINK_FRAMING_CNTL 0x42CC
+#define mmDP2_DP_MSA_COLORIMETRY 0x42DA
+#define mmDP2_DP_MSA_MISC 0x42C5
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE1 0x42EA
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE2 0x42EB
+#define mmDP2_DP_MSE_LINK_TIMING 0x42E8
+#define mmDP2_DP_MSE_MISC_CNTL 0x42DB
+#define mmDP2_DP_MSE_RATE_CNTL 0x42E1
+#define mmDP2_DP_MSE_RATE_UPDATE 0x42E3
+#define mmDP2_DP_MSE_SAT0 0x42E4
+#define mmDP2_DP_MSE_SAT1 0x42E5
+#define mmDP2_DP_MSE_SAT2 0x42E6
+#define mmDP2_DP_MSE_SAT_UPDATE 0x42E7
+#define mmDP2_DP_PIXEL_FORMAT 0x42C1
+#define mmDP2_DP_SEC_AUD_M 0x42A7
+#define mmDP2_DP_SEC_AUD_M_READBACK 0x42A8
+#define mmDP2_DP_SEC_AUD_N 0x42A5
+#define mmDP2_DP_SEC_AUD_N_READBACK 0x42A6
+#define mmDP2_DP_SEC_CNTL 0x42A0
+#define mmDP2_DP_SEC_CNTL1 0x42AB
+#define mmDP2_DP_SEC_FRAMING1 0x42A1
+#define mmDP2_DP_SEC_FRAMING2 0x42A2
+#define mmDP2_DP_SEC_FRAMING3 0x42A3
+#define mmDP2_DP_SEC_FRAMING4 0x42A4
+#define mmDP2_DP_SEC_PACKET_CNTL 0x42AA
+#define mmDP2_DP_SEC_TIMESTAMP 0x42A9
+#define mmDP2_DP_STEER_FIFO 0x42C4
+#define mmDP2_DP_TEST_DEBUG_DATA 0x42FD
+#define mmDP2_DP_TEST_DEBUG_INDEX 0x42FC
+#define mmDP2_DP_VID_INTERRUPT_CNTL 0x42CF
+#define mmDP2_DP_VID_M 0x42CB
+#define mmDP2_DP_VID_MSA_VBID 0x42CD
+#define mmDP2_DP_VID_N 0x42CA
+#define mmDP2_DP_VID_STREAM_CNTL 0x42C3
+#define mmDP2_DP_VID_TIMING 0x42C9
+#define mmDP3_DP_CONFIG 0x45C2
+#define mmDP3_DP_DPHY_8B10B_CNTL 0x45D3
+#define mmDP3_DP_DPHY_CNTL 0x45D0
+#define mmDP3_DP_DPHY_CRC_CNTL 0x45D7
+#define mmDP3_DP_DPHY_CRC_EN 0x45D6
+#define mmDP3_DP_DPHY_CRC_MST_CNTL 0x45C6
+#define mmDP3_DP_DPHY_CRC_MST_STATUS 0x45C7
+#define mmDP3_DP_DPHY_CRC_RESULT 0x45D8
+#define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE
+#define mmDP3_DP_DPHY_FAST_TRAINING_STATUS 0x45E9
+#define mmDP3_DP_DPHY_PRBS_CNTL 0x45D4
+#define mmDP3_DP_DPHY_SYM0 0x45D2
+#define mmDP3_DP_DPHY_SYM1 0x45E0
+#define mmDP3_DP_DPHY_SYM2 0x45DF
+#define mmDP3_DP_DPHY_TRAINING_PATTERN_SEL 0x45D1
+#define mmDP3_DP_HBR2_EYE_PATTERN 0x45C8
+#define mmDP3_DP_LINK_CNTL 0x45C0
+#define mmDP3_DP_LINK_FRAMING_CNTL 0x45CC
+#define mmDP3_DP_MSA_COLORIMETRY 0x45DA
+#define mmDP3_DP_MSA_MISC 0x45C5
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE1 0x45EA
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE2 0x45EB
+#define mmDP3_DP_MSE_LINK_TIMING 0x45E8
+#define mmDP3_DP_MSE_MISC_CNTL 0x45DB
+#define mmDP3_DP_MSE_RATE_CNTL 0x45E1
+#define mmDP3_DP_MSE_RATE_UPDATE 0x45E3
+#define mmDP3_DP_MSE_SAT0 0x45E4
+#define mmDP3_DP_MSE_SAT1 0x45E5
+#define mmDP3_DP_MSE_SAT2 0x45E6
+#define mmDP3_DP_MSE_SAT_UPDATE 0x45E7
+#define mmDP3_DP_PIXEL_FORMAT 0x45C1
+#define mmDP3_DP_SEC_AUD_M 0x45A7
+#define mmDP3_DP_SEC_AUD_M_READBACK 0x45A8
+#define mmDP3_DP_SEC_AUD_N 0x45A5
+#define mmDP3_DP_SEC_AUD_N_READBACK 0x45A6
+#define mmDP3_DP_SEC_CNTL 0x45A0
+#define mmDP3_DP_SEC_CNTL1 0x45AB
+#define mmDP3_DP_SEC_FRAMING1 0x45A1
+#define mmDP3_DP_SEC_FRAMING2 0x45A2
+#define mmDP3_DP_SEC_FRAMING3 0x45A3
+#define mmDP3_DP_SEC_FRAMING4 0x45A4
+#define mmDP3_DP_SEC_PACKET_CNTL 0x45AA
+#define mmDP3_DP_SEC_TIMESTAMP 0x45A9
+#define mmDP3_DP_STEER_FIFO 0x45C4
+#define mmDP3_DP_TEST_DEBUG_DATA 0x45FD
+#define mmDP3_DP_TEST_DEBUG_INDEX 0x45FC
+#define mmDP3_DP_VID_INTERRUPT_CNTL 0x45CF
+#define mmDP3_DP_VID_M 0x45CB
+#define mmDP3_DP_VID_MSA_VBID 0x45CD
+#define mmDP3_DP_VID_N 0x45CA
+#define mmDP3_DP_VID_STREAM_CNTL 0x45C3
+#define mmDP3_DP_VID_TIMING 0x45C9
+#define mmDP4_DP_CONFIG 0x48C2
+#define mmDP4_DP_DPHY_8B10B_CNTL 0x48D3
+#define mmDP4_DP_DPHY_CNTL 0x48D0
+#define mmDP4_DP_DPHY_CRC_CNTL 0x48D7
+#define mmDP4_DP_DPHY_CRC_EN 0x48D6
+#define mmDP4_DP_DPHY_CRC_MST_CNTL 0x48C6
+#define mmDP4_DP_DPHY_CRC_MST_STATUS 0x48C7
+#define mmDP4_DP_DPHY_CRC_RESULT 0x48D8
+#define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE
+#define mmDP4_DP_DPHY_FAST_TRAINING_STATUS 0x48E9
+#define mmDP4_DP_DPHY_PRBS_CNTL 0x48D4
+#define mmDP4_DP_DPHY_SYM0 0x48D2
+#define mmDP4_DP_DPHY_SYM1 0x48E0
+#define mmDP4_DP_DPHY_SYM2 0x48DF
+#define mmDP4_DP_DPHY_TRAINING_PATTERN_SEL 0x48D1
+#define mmDP4_DP_HBR2_EYE_PATTERN 0x48C8
+#define mmDP4_DP_LINK_CNTL 0x48C0
+#define mmDP4_DP_LINK_FRAMING_CNTL 0x48CC
+#define mmDP4_DP_MSA_COLORIMETRY 0x48DA
+#define mmDP4_DP_MSA_MISC 0x48C5
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE1 0x48EA
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE2 0x48EB
+#define mmDP4_DP_MSE_LINK_TIMING 0x48E8
+#define mmDP4_DP_MSE_MISC_CNTL 0x48DB
+#define mmDP4_DP_MSE_RATE_CNTL 0x48E1
+#define mmDP4_DP_MSE_RATE_UPDATE 0x48E3
+#define mmDP4_DP_MSE_SAT0 0x48E4
+#define mmDP4_DP_MSE_SAT1 0x48E5
+#define mmDP4_DP_MSE_SAT2 0x48E6
+#define mmDP4_DP_MSE_SAT_UPDATE 0x48E7
+#define mmDP4_DP_PIXEL_FORMAT 0x48C1
+#define mmDP4_DP_SEC_AUD_M 0x48A7
+#define mmDP4_DP_SEC_AUD_M_READBACK 0x48A8
+#define mmDP4_DP_SEC_AUD_N 0x48A5
+#define mmDP4_DP_SEC_AUD_N_READBACK 0x48A6
+#define mmDP4_DP_SEC_CNTL 0x48A0
+#define mmDP4_DP_SEC_CNTL1 0x48AB
+#define mmDP4_DP_SEC_FRAMING1 0x48A1
+#define mmDP4_DP_SEC_FRAMING2 0x48A2
+#define mmDP4_DP_SEC_FRAMING3 0x48A3
+#define mmDP4_DP_SEC_FRAMING4 0x48A4
+#define mmDP4_DP_SEC_PACKET_CNTL 0x48AA
+#define mmDP4_DP_SEC_TIMESTAMP 0x48A9
+#define mmDP4_DP_STEER_FIFO 0x48C4
+#define mmDP4_DP_TEST_DEBUG_DATA 0x48FD
+#define mmDP4_DP_TEST_DEBUG_INDEX 0x48FC
+#define mmDP4_DP_VID_INTERRUPT_CNTL 0x48CF
+#define mmDP4_DP_VID_M 0x48CB
+#define mmDP4_DP_VID_MSA_VBID 0x48CD
+#define mmDP4_DP_VID_N 0x48CA
+#define mmDP4_DP_VID_STREAM_CNTL 0x48C3
+#define mmDP4_DP_VID_TIMING 0x48C9
+#define mmDP5_DP_CONFIG 0x4BC2
+#define mmDP5_DP_DPHY_8B10B_CNTL 0x4BD3
+#define mmDP5_DP_DPHY_CNTL 0x4BD0
+#define mmDP5_DP_DPHY_CRC_CNTL 0x4BD7
+#define mmDP5_DP_DPHY_CRC_EN 0x4BD6
+#define mmDP5_DP_DPHY_CRC_MST_CNTL 0x4BC6
+#define mmDP5_DP_DPHY_CRC_MST_STATUS 0x4BC7
+#define mmDP5_DP_DPHY_CRC_RESULT 0x4BD8
+#define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE
+#define mmDP5_DP_DPHY_FAST_TRAINING_STATUS 0x4BE9
+#define mmDP5_DP_DPHY_PRBS_CNTL 0x4BD4
+#define mmDP5_DP_DPHY_SYM0 0x4BD2
+#define mmDP5_DP_DPHY_SYM1 0x4BE0
+#define mmDP5_DP_DPHY_SYM2 0x4BDF
+#define mmDP5_DP_DPHY_TRAINING_PATTERN_SEL 0x4BD1
+#define mmDP5_DP_HBR2_EYE_PATTERN 0x4BC8
+#define mmDP5_DP_LINK_CNTL 0x4BC0
+#define mmDP5_DP_LINK_FRAMING_CNTL 0x4BCC
+#define mmDP5_DP_MSA_COLORIMETRY 0x4BDA
+#define mmDP5_DP_MSA_MISC 0x4BC5
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE1 0x4BEA
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE2 0x4BEB
+#define mmDP5_DP_MSE_LINK_TIMING 0x4BE8
+#define mmDP5_DP_MSE_MISC_CNTL 0x4BDB
+#define mmDP5_DP_MSE_RATE_CNTL 0x4BE1
+#define mmDP5_DP_MSE_RATE_UPDATE 0x4BE3
+#define mmDP5_DP_MSE_SAT0 0x4BE4
+#define mmDP5_DP_MSE_SAT1 0x4BE5
+#define mmDP5_DP_MSE_SAT2 0x4BE6
+#define mmDP5_DP_MSE_SAT_UPDATE 0x4BE7
+#define mmDP5_DP_PIXEL_FORMAT 0x4BC1
+#define mmDP5_DP_SEC_AUD_M 0x4BA7
+#define mmDP5_DP_SEC_AUD_M_READBACK 0x4BA8
+#define mmDP5_DP_SEC_AUD_N 0x4BA5
+#define mmDP5_DP_SEC_AUD_N_READBACK 0x4BA6
+#define mmDP5_DP_SEC_CNTL 0x4BA0
+#define mmDP5_DP_SEC_CNTL1 0x4BAB
+#define mmDP5_DP_SEC_FRAMING1 0x4BA1
+#define mmDP5_DP_SEC_FRAMING2 0x4BA2
+#define mmDP5_DP_SEC_FRAMING3 0x4BA3
+#define mmDP5_DP_SEC_FRAMING4 0x4BA4
+#define mmDP5_DP_SEC_PACKET_CNTL 0x4BAA
+#define mmDP5_DP_SEC_TIMESTAMP 0x4BA9
+#define mmDP5_DP_STEER_FIFO 0x4BC4
+#define mmDP5_DP_TEST_DEBUG_DATA 0x4BFD
+#define mmDP5_DP_TEST_DEBUG_INDEX 0x4BFC
+#define mmDP5_DP_VID_INTERRUPT_CNTL 0x4BCF
+#define mmDP5_DP_VID_M 0x4BCB
+#define mmDP5_DP_VID_MSA_VBID 0x4BCD
+#define mmDP5_DP_VID_N 0x4BCA
+#define mmDP5_DP_VID_STREAM_CNTL 0x4BC3
+#define mmDP5_DP_VID_TIMING 0x4BC9
+#define mmDP_AUX0_AUX_ARB_CONTROL 0x1882
+#define mmDP_AUX0_AUX_CONTROL 0x1880
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL0 0x188A
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL1 0x188B
+#define mmDP_AUX0_AUX_DPHY_RX_STATUS 0x188D
+#define mmDP_AUX0_AUX_DPHY_TX_CONTROL 0x1889
+#define mmDP_AUX0_AUX_DPHY_TX_REF_CONTROL 0x1888
+#define mmDP_AUX0_AUX_DPHY_TX_STATUS 0x188C
+#define mmDP_AUX0_AUX_GTC_SYNC_CONTROL 0x188E
+#define mmDP_AUX0_AUX_GTC_SYNC_DATA 0x1890
+#define mmDP_AUX0_AUX_INTERRUPT_CONTROL 0x1883
+#define mmDP_AUX0_AUX_LS_DATA 0x1887
+#define mmDP_AUX0_AUX_LS_STATUS 0x1885
+#define mmDP_AUX0_AUX_SW_CONTROL 0x1881
+#define mmDP_AUX0_AUX_SW_DATA 0x1886
+#define mmDP_AUX0_AUX_SW_STATUS 0x1884
+#define mmDP_AUX1_AUX_ARB_CONTROL 0x1896
+#define mmDP_AUX1_AUX_CONTROL 0x1894
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL0 0x189E
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL1 0x189F
+#define mmDP_AUX1_AUX_DPHY_RX_STATUS 0x18A1
+#define mmDP_AUX1_AUX_DPHY_TX_CONTROL 0x189D
+#define mmDP_AUX1_AUX_DPHY_TX_REF_CONTROL 0x189C
+#define mmDP_AUX1_AUX_DPHY_TX_STATUS 0x18A0
+#define mmDP_AUX1_AUX_GTC_SYNC_CONTROL 0x18A2
+#define mmDP_AUX1_AUX_GTC_SYNC_DATA 0x18A4
+#define mmDP_AUX1_AUX_INTERRUPT_CONTROL 0x1897
+#define mmDP_AUX1_AUX_LS_DATA 0x189B
+#define mmDP_AUX1_AUX_LS_STATUS 0x1899
+#define mmDP_AUX1_AUX_SW_CONTROL 0x1895
+#define mmDP_AUX1_AUX_SW_DATA 0x189A
+#define mmDP_AUX1_AUX_SW_STATUS 0x1898
+#define mmDP_AUX2_AUX_ARB_CONTROL 0x18AA
+#define mmDP_AUX2_AUX_CONTROL 0x18A8
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL0 0x18B2
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL1 0x18B3
+#define mmDP_AUX2_AUX_DPHY_RX_STATUS 0x18B5
+#define mmDP_AUX2_AUX_DPHY_TX_CONTROL 0x18B1
+#define mmDP_AUX2_AUX_DPHY_TX_REF_CONTROL 0x18B0
+#define mmDP_AUX2_AUX_DPHY_TX_STATUS 0x18B4
+#define mmDP_AUX2_AUX_GTC_SYNC_CONTROL 0x18B6
+#define mmDP_AUX2_AUX_GTC_SYNC_DATA 0x18B8
+#define mmDP_AUX2_AUX_INTERRUPT_CONTROL 0x18AB
+#define mmDP_AUX2_AUX_LS_DATA 0x18AF
+#define mmDP_AUX2_AUX_LS_STATUS 0x18AD
+#define mmDP_AUX2_AUX_SW_CONTROL 0x18A9
+#define mmDP_AUX2_AUX_SW_DATA 0x18AE
+#define mmDP_AUX2_AUX_SW_STATUS 0x18AC
+#define mmDP_AUX3_AUX_ARB_CONTROL 0x18C2
+#define mmDP_AUX3_AUX_CONTROL 0x18C0
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL0 0x18CA
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL1 0x18CB
+#define mmDP_AUX3_AUX_DPHY_RX_STATUS 0x18CD
+#define mmDP_AUX3_AUX_DPHY_TX_CONTROL 0x18C9
+#define mmDP_AUX3_AUX_DPHY_TX_REF_CONTROL 0x18C8
+#define mmDP_AUX3_AUX_DPHY_TX_STATUS 0x18CC
+#define mmDP_AUX3_AUX_GTC_SYNC_CONTROL 0x18CE
+#define mmDP_AUX3_AUX_GTC_SYNC_DATA 0x18D0
+#define mmDP_AUX3_AUX_INTERRUPT_CONTROL 0x18C3
+#define mmDP_AUX3_AUX_LS_DATA 0x18C7
+#define mmDP_AUX3_AUX_LS_STATUS 0x18C5
+#define mmDP_AUX3_AUX_SW_CONTROL 0x18C1
+#define mmDP_AUX3_AUX_SW_DATA 0x18C6
+#define mmDP_AUX3_AUX_SW_STATUS 0x18C4
+#define mmDP_AUX4_AUX_ARB_CONTROL 0x18D6
+#define mmDP_AUX4_AUX_CONTROL 0x18D4
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL0 0x18DE
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL1 0x18DF
+#define mmDP_AUX4_AUX_DPHY_RX_STATUS 0x18E1
+#define mmDP_AUX4_AUX_DPHY_TX_CONTROL 0x18DD
+#define mmDP_AUX4_AUX_DPHY_TX_REF_CONTROL 0x18DC
+#define mmDP_AUX4_AUX_DPHY_TX_STATUS 0x18E0
+#define mmDP_AUX4_AUX_GTC_SYNC_CONTROL 0x18E2
+#define mmDP_AUX4_AUX_GTC_SYNC_DATA 0x18E4
+#define mmDP_AUX4_AUX_INTERRUPT_CONTROL 0x18D7
+#define mmDP_AUX4_AUX_LS_DATA 0x18DB
+#define mmDP_AUX4_AUX_LS_STATUS 0x18D9
+#define mmDP_AUX4_AUX_SW_CONTROL 0x18D5
+#define mmDP_AUX4_AUX_SW_DATA 0x18DA
+#define mmDP_AUX4_AUX_SW_STATUS 0x18D8
+#define mmDP_AUX5_AUX_ARB_CONTROL 0x18EA
+#define mmDP_AUX5_AUX_CONTROL 0x18E8
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL0 0x18F2
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL1 0x18F3
+#define mmDP_AUX5_AUX_DPHY_RX_STATUS 0x18F5
+#define mmDP_AUX5_AUX_DPHY_TX_CONTROL 0x18F1
+#define mmDP_AUX5_AUX_DPHY_TX_REF_CONTROL 0x18F0
+#define mmDP_AUX5_AUX_DPHY_TX_STATUS 0x18F4
+#define mmDP_AUX5_AUX_GTC_SYNC_CONTROL 0x18F6
+#define mmDP_AUX5_AUX_GTC_SYNC_DATA 0x18F8
+#define mmDP_AUX5_AUX_INTERRUPT_CONTROL 0x18EB
+#define mmDP_AUX5_AUX_LS_DATA 0x18EF
+#define mmDP_AUX5_AUX_LS_STATUS 0x18ED
+#define mmDP_AUX5_AUX_SW_CONTROL 0x18E9
+#define mmDP_AUX5_AUX_SW_DATA 0x18EE
+#define mmDP_AUX5_AUX_SW_STATUS 0x18EC
+#define mmDP_CONFIG 0x1CC2
+#define mmDP_DPHY_8B10B_CNTL 0x1CD3
+#define mmDP_DPHY_CNTL 0x1CD0
+#define mmDP_DPHY_CRC_CNTL 0x1CD7
+#define mmDP_DPHY_CRC_EN 0x1CD6
+#define mmDP_DPHY_CRC_MST_CNTL 0x1CC6
+#define mmDP_DPHY_CRC_MST_STATUS 0x1CC7
+#define mmDP_DPHY_CRC_RESULT 0x1CD8
+#define mmDP_DPHY_FAST_TRAINING 0x1CCE
+#define mmDP_DPHY_FAST_TRAINING_STATUS 0x1CE9
+#define mmDP_DPHY_PRBS_CNTL 0x1CD4
+#define mmDP_DPHY_SYM0 0x1CD2
+#define mmDP_DPHY_SYM1 0x1CE0
+#define mmDP_DPHY_SYM2 0x1CDF
+#define mmDP_DPHY_TRAINING_PATTERN_SEL 0x1CD1
+#define mmDP_DTO0_MODULO 0x0142
+#define mmDP_DTO0_PHASE 0x0141
+#define mmDP_DTO1_MODULO 0x0146
+#define mmDP_DTO1_PHASE 0x0145
+#define mmDP_DTO2_MODULO 0x014A
+#define mmDP_DTO2_PHASE 0x0149
+#define mmDP_DTO3_MODULO 0x014E
+#define mmDP_DTO3_PHASE 0x014D
+#define mmDP_DTO4_MODULO 0x0152
+#define mmDP_DTO4_PHASE 0x0151
+#define mmDP_DTO5_MODULO 0x0156
+#define mmDP_DTO5_PHASE 0x0155
+#define mmDPG_PIPE_ARBITRATION_CONTROL1 0x1B30
+#define mmDPG_PIPE_ARBITRATION_CONTROL2 0x1B31
+#define mmDPG_PIPE_DPM_CONTROL 0x1B34
+#define mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1B36
+#define mmDPG_PIPE_STUTTER_CONTROL 0x1B35
+#define mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1B37
+#define mmDPG_PIPE_URGENCY_CONTROL 0x1B33
+#define mmDPG_TEST_DEBUG_DATA 0x1B39
+#define mmDPG_TEST_DEBUG_INDEX 0x1B38
+#define mmDP_HBR2_EYE_PATTERN 0x1CC8
+#define mmDP_LINK_CNTL 0x1CC0
+#define mmDP_LINK_FRAMING_CNTL 0x1CCC
+#define mmDP_MSA_COLORIMETRY 0x1CDA
+#define mmDP_MSA_MISC 0x1CC5
+#define mmDP_MSA_V_TIMING_OVERRIDE1 0x1CEA
+#define mmDP_MSA_V_TIMING_OVERRIDE2 0x1CEB
+#define mmDP_MSE_LINK_TIMING 0x1CE8
+#define mmDP_MSE_MISC_CNTL 0x1CDB
+#define mmDP_MSE_RATE_CNTL 0x1CE1
+#define mmDP_MSE_RATE_UPDATE 0x1CE3
+#define mmDP_MSE_SAT0 0x1CE4
+#define mmDP_MSE_SAT1 0x1CE5
+#define mmDP_MSE_SAT2 0x1CE6
+#define mmDP_MSE_SAT_UPDATE 0x1CE7
+#define mmDP_PIXEL_FORMAT 0x1CC1
+#define mmDP_SEC_AUD_M 0x1CA7
+#define mmDP_SEC_AUD_M_READBACK 0x1CA8
+#define mmDP_SEC_AUD_N 0x1CA5
+#define mmDP_SEC_AUD_N_READBACK 0x1CA6
+#define mmDP_SEC_CNTL 0x1CA0
+#define mmDP_SEC_CNTL1 0x1CAB
+#define mmDP_SEC_FRAMING1 0x1CA1
+#define mmDP_SEC_FRAMING2 0x1CA2
+#define mmDP_SEC_FRAMING3 0x1CA3
+#define mmDP_SEC_FRAMING4 0x1CA4
+#define mmDP_SEC_PACKET_CNTL 0x1CAA
+#define mmDP_SEC_TIMESTAMP 0x1CA9
+#define mmDP_STEER_FIFO 0x1CC4
+#define mmDP_TEST_DEBUG_DATA 0x1CFD
+#define mmDP_TEST_DEBUG_INDEX 0x1CFC
+#define mmDP_VID_INTERRUPT_CNTL 0x1CCF
+#define mmDP_VID_M 0x1CCB
+#define mmDP_VID_MSA_VBID 0x1CCD
+#define mmDP_VID_N 0x1CCA
+#define mmDP_VID_STREAM_CNTL 0x1CC3
+#define mmDP_VID_TIMING 0x1CC9
+#define mmDVOACLKC_CNTL 0x016A
+#define mmDVOACLKC_MVP_CNTL 0x0169
+#define mmDVOACLKD_CNTL 0x0168
+#define mmDVO_CLK_ENABLE 0x0129
+#define mmDVO_CONTROL 0x185B
+#define mmDVO_CRC2_SIG_MASK 0x185D
+#define mmDVO_CRC2_SIG_RESULT 0x185E
+#define mmDVO_CRC_EN 0x185C
+#define mmDVO_ENABLE 0x1858
+#define mmDVO_FIFO_ERROR_STATUS 0x185F
+#define mmDVO_OUTPUT 0x185A
+#define mmDVO_SKEW_ADJUST 0x197D
+#define mmDVO_SOURCE_SELECT 0x1859
+#define mmDVO_STRENGTH_CONTROL 0x197B
+#define mmDVO_VREF_CONTROL 0x197C
+#define mmEXT_OVERSCAN_LEFT_RIGHT 0x1B5E
+#define mmEXT_OVERSCAN_TOP_BOTTOM 0x1B5F
+#define mmFBC_CLIENT_REGION_MASK 0x16EB
+#define mmFBC_CNTL 0x16D0
+#define mmFBC_COMP_CNTL 0x16D4
+#define mmFBC_COMP_MODE 0x16D5
+#define mmFBC_CSM_REGION_OFFSET_01 0x16E9
+#define mmFBC_CSM_REGION_OFFSET_23 0x16EA
+#define mmFBC_DEBUG0 0x16D6
+#define mmFBC_DEBUG1 0x16D7
+#define mmFBC_DEBUG2 0x16D8
+#define mmFBC_DEBUG_COMP 0x16EC
+#define mmFBC_DEBUG_CSR 0x16ED
+#define mmFBC_DEBUG_CSR_RDATA 0x16EE
+#define mmFBC_DEBUG_CSR_RDATA_HI 0x16F6
+#define mmFBC_DEBUG_CSR_WDATA 0x16EF
+#define mmFBC_DEBUG_CSR_WDATA_HI 0x16F7
+#define mmFBC_IDLE_FORCE_CLEAR_MASK 0x16D2
+#define mmFBC_IDLE_MASK 0x16D1
+#define mmFBC_IND_LUT0 0x16D9
+#define mmFBC_IND_LUT10 0x16E3
+#define mmFBC_IND_LUT1 0x16DA
+#define mmFBC_IND_LUT11 0x16E4
+#define mmFBC_IND_LUT12 0x16E5
+#define mmFBC_IND_LUT13 0x16E6
+#define mmFBC_IND_LUT14 0x16E7
+#define mmFBC_IND_LUT15 0x16E8
+#define mmFBC_IND_LUT2 0x16DB
+#define mmFBC_IND_LUT3 0x16DC
+#define mmFBC_IND_LUT4 0x16DD
+#define mmFBC_IND_LUT5 0x16DE
+#define mmFBC_IND_LUT6 0x16DF
+#define mmFBC_IND_LUT7 0x16E0
+#define mmFBC_IND_LUT8 0x16E1
+#define mmFBC_IND_LUT9 0x16E2
+#define mmFBC_MISC 0x16F0
+#define mmFBC_START_STOP_DELAY 0x16D3
+#define mmFBC_STATUS 0x16F1
+#define mmFBC_TEST_DEBUG_DATA 0x16F5
+#define mmFBC_TEST_DEBUG_INDEX 0x16F4
+#define mmFMT0_FMT_BIT_DEPTH_CONTROL 0x1BF2
+#define mmFMT0_FMT_CLAMP_CNTL 0x1BF9
+#define mmFMT0_FMT_CONTROL 0x1BEE
+#define mmFMT0_FMT_CRC_CNTL 0x1BFA
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL 0x1BFE
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x1BFC
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN 0x1BFD
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN_MASK 0x1BFB
+#define mmFMT0_FMT_DEBUG_CNTL 0x1BFF
+#define mmFMT0_FMT_DITHER_RAND_B_SEED 0x1BF5
+#define mmFMT0_FMT_DITHER_RAND_G_SEED 0x1BF4
+#define mmFMT0_FMT_DITHER_RAND_R_SEED 0x1BF3
+#define mmFMT0_FMT_DYNAMIC_EXP_CNTL 0x1BED
+#define mmFMT0_FMT_FORCE_DATA_0_1 0x1BF0
+#define mmFMT0_FMT_FORCE_DATA_2_3 0x1BF1
+#define mmFMT0_FMT_FORCE_OUTPUT_CNTL 0x1BEF
+#define mmFMT0_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1BF6
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1BF7
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1BF8
+#define mmFMT0_FMT_TEST_DEBUG_DATA 0x1BEC
+#define mmFMT0_FMT_TEST_DEBUG_INDEX 0x1BEB
+#define mmFMT1_FMT_BIT_DEPTH_CONTROL 0x1EF2
+#define mmFMT1_FMT_CLAMP_CNTL 0x1EF9
+#define mmFMT1_FMT_CONTROL 0x1EEE
+#define mmFMT1_FMT_CRC_CNTL 0x1EFA
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL 0x1EFE
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x1EFC
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN 0x1EFD
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN_MASK 0x1EFB
+#define mmFMT1_FMT_DEBUG_CNTL 0x1EFF
+#define mmFMT1_FMT_DITHER_RAND_B_SEED 0x1EF5
+#define mmFMT1_FMT_DITHER_RAND_G_SEED 0x1EF4
+#define mmFMT1_FMT_DITHER_RAND_R_SEED 0x1EF3
+#define mmFMT1_FMT_DYNAMIC_EXP_CNTL 0x1EED
+#define mmFMT1_FMT_FORCE_DATA_0_1 0x1EF0
+#define mmFMT1_FMT_FORCE_DATA_2_3 0x1EF1
+#define mmFMT1_FMT_FORCE_OUTPUT_CNTL 0x1EEF
+#define mmFMT1_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1EF6
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1EF7
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1EF8
+#define mmFMT1_FMT_TEST_DEBUG_DATA 0x1EEC
+#define mmFMT1_FMT_TEST_DEBUG_INDEX 0x1EEB
+#define mmFMT2_FMT_BIT_DEPTH_CONTROL 0x41F2
+#define mmFMT2_FMT_CLAMP_CNTL 0x41F9
+#define mmFMT2_FMT_CONTROL 0x41EE
+#define mmFMT2_FMT_CRC_CNTL 0x41FA
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL 0x41FE
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x41FC
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN 0x41FD
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN_MASK 0x41FB
+#define mmFMT2_FMT_DEBUG_CNTL 0x41FF
+#define mmFMT2_FMT_DITHER_RAND_B_SEED 0x41F5
+#define mmFMT2_FMT_DITHER_RAND_G_SEED 0x41F4
+#define mmFMT2_FMT_DITHER_RAND_R_SEED 0x41F3
+#define mmFMT2_FMT_DYNAMIC_EXP_CNTL 0x41ED
+#define mmFMT2_FMT_FORCE_DATA_0_1 0x41F0
+#define mmFMT2_FMT_FORCE_DATA_2_3 0x41F1
+#define mmFMT2_FMT_FORCE_OUTPUT_CNTL 0x41EF
+#define mmFMT2_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x41F6
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x41F7
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x41F8
+#define mmFMT2_FMT_TEST_DEBUG_DATA 0x41EC
+#define mmFMT2_FMT_TEST_DEBUG_INDEX 0x41EB
+#define mmFMT3_FMT_BIT_DEPTH_CONTROL 0x44F2
+#define mmFMT3_FMT_CLAMP_CNTL 0x44F9
+#define mmFMT3_FMT_CONTROL 0x44EE
+#define mmFMT3_FMT_CRC_CNTL 0x44FA
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL 0x44FE
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x44FC
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN 0x44FD
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN_MASK 0x44FB
+#define mmFMT3_FMT_DEBUG_CNTL 0x44FF
+#define mmFMT3_FMT_DITHER_RAND_B_SEED 0x44F5
+#define mmFMT3_FMT_DITHER_RAND_G_SEED 0x44F4
+#define mmFMT3_FMT_DITHER_RAND_R_SEED 0x44F3
+#define mmFMT3_FMT_DYNAMIC_EXP_CNTL 0x44ED
+#define mmFMT3_FMT_FORCE_DATA_0_1 0x44F0
+#define mmFMT3_FMT_FORCE_DATA_2_3 0x44F1
+#define mmFMT3_FMT_FORCE_OUTPUT_CNTL 0x44EF
+#define mmFMT3_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x44F6
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x44F7
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x44F8
+#define mmFMT3_FMT_TEST_DEBUG_DATA 0x44EC
+#define mmFMT3_FMT_TEST_DEBUG_INDEX 0x44EB
+#define mmFMT4_FMT_BIT_DEPTH_CONTROL 0x47F2
+#define mmFMT4_FMT_CLAMP_CNTL 0x47F9
+#define mmFMT4_FMT_CONTROL 0x47EE
+#define mmFMT4_FMT_CRC_CNTL 0x47FA
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL 0x47FE
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x47FC
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN 0x47FD
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN_MASK 0x47FB
+#define mmFMT4_FMT_DEBUG_CNTL 0x47FF
+#define mmFMT4_FMT_DITHER_RAND_B_SEED 0x47F5
+#define mmFMT4_FMT_DITHER_RAND_G_SEED 0x47F4
+#define mmFMT4_FMT_DITHER_RAND_R_SEED 0x47F3
+#define mmFMT4_FMT_DYNAMIC_EXP_CNTL 0x47ED
+#define mmFMT4_FMT_FORCE_DATA_0_1 0x47F0
+#define mmFMT4_FMT_FORCE_DATA_2_3 0x47F1
+#define mmFMT4_FMT_FORCE_OUTPUT_CNTL 0x47EF
+#define mmFMT4_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x47F6
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x47F7
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x47F8
+#define mmFMT4_FMT_TEST_DEBUG_DATA 0x47EC
+#define mmFMT4_FMT_TEST_DEBUG_INDEX 0x47EB
+#define mmFMT5_FMT_BIT_DEPTH_CONTROL 0x4AF2
+#define mmFMT5_FMT_CLAMP_CNTL 0x4AF9
+#define mmFMT5_FMT_CONTROL 0x4AEE
+#define mmFMT5_FMT_CRC_CNTL 0x4AFA
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL 0x4AFE
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x4AFC
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN 0x4AFD
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN_MASK 0x4AFB
+#define mmFMT5_FMT_DEBUG_CNTL 0x4AFF
+#define mmFMT5_FMT_DITHER_RAND_B_SEED 0x4AF5
+#define mmFMT5_FMT_DITHER_RAND_G_SEED 0x4AF4
+#define mmFMT5_FMT_DITHER_RAND_R_SEED 0x4AF3
+#define mmFMT5_FMT_DYNAMIC_EXP_CNTL 0x4AED
+#define mmFMT5_FMT_FORCE_DATA_0_1 0x4AF0
+#define mmFMT5_FMT_FORCE_DATA_2_3 0x4AF1
+#define mmFMT5_FMT_FORCE_OUTPUT_CNTL 0x4AEF
+#define mmFMT5_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x4AF6
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x4AF7
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x4AF8
+#define mmFMT5_FMT_TEST_DEBUG_DATA 0x4AEC
+#define mmFMT5_FMT_TEST_DEBUG_INDEX 0x4AEB
+#define mmFMT_BIT_DEPTH_CONTROL 0x1BF2
+#define mmFMT_CLAMP_CNTL 0x1BF9
+#define mmFMT_CONTROL 0x1BEE
+#define mmFMT_CRC_CNTL 0x1BFA
+#define mmFMT_CRC_SIG_BLUE_CONTROL 0x1BFE
+#define mmFMT_CRC_SIG_BLUE_CONTROL_MASK 0x1BFC
+#define mmFMT_CRC_SIG_RED_GREEN 0x1BFD
+#define mmFMT_CRC_SIG_RED_GREEN_MASK 0x1BFB
+#define mmFMT_DEBUG_CNTL 0x1BFF
+#define mmFMT_DITHER_RAND_B_SEED 0x1BF5
+#define mmFMT_DITHER_RAND_G_SEED 0x1BF4
+#define mmFMT_DITHER_RAND_R_SEED 0x1BF3
+#define mmFMT_DYNAMIC_EXP_CNTL 0x1BED
+#define mmFMT_FORCE_DATA_0_1 0x1BF0
+#define mmFMT_FORCE_DATA_2_3 0x1BF1
+#define mmFMT_FORCE_OUTPUT_CNTL 0x1BEF
+#define mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1BF6
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1BF7
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1BF8
+#define mmFMT_TEST_DEBUG_DATA 0x1BEC
+#define mmFMT_TEST_DEBUG_INDEX 0x1BEB
+#define mmGAMUT_REMAP_C11_C12 0x1A5A
+#define mmGAMUT_REMAP_C13_C14 0x1A5B
+#define mmGAMUT_REMAP_C21_C22 0x1A5C
+#define mmGAMUT_REMAP_C23_C24 0x1A5D
+#define mmGAMUT_REMAP_C31_C32 0x1A5E
+#define mmGAMUT_REMAP_C33_C34 0x1A5F
+#define mmGAMUT_REMAP_CONTROL 0x1A59
+#define mmGENENB 0x00F0
+#define mmGENERIC_I2C_CONTROL 0x1834
+#define mmGENERIC_I2C_DATA 0x183A
+#define mmGENERIC_I2C_INTERRUPT_CONTROL 0x1835
+#define mmGENERIC_I2C_PIN_DEBUG 0x183C
+#define mmGENERIC_I2C_PIN_SELECTION 0x183B
+#define mmGENERIC_I2C_SETUP 0x1838
+#define mmGENERIC_I2C_SPEED 0x1837
+#define mmGENERIC_I2C_STATUS 0x1836
+#define mmGENERIC_I2C_TRANSACTION 0x1839
+#define mmGENFC_RD 0x00F2
+#define mmGENFC_WT 0x00EE
+#define mmGENMO_RD 0x00F3
+#define mmGENMO_WT 0x00F0
+#define mmGENS0 0x00F0
+#define mmGENS1 0x00EE
+#define mmGRPH8_DATA 0x00F3
+#define mmGRPH8_IDX 0x00F3
+#define mmGRPH_COMPRESS_PITCH 0x1A1A
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS 0x1A19
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1A1B
+#define mmGRPH_CONTROL 0x1A01
+#define mmGRPH_DFQ_CONTROL 0x1A14
+#define mmGRPH_DFQ_STATUS 0x1A15
+#define mmGRPH_ENABLE 0x1A00
+#define mmGRPH_FLIP_CONTROL 0x1A12
+#define mmGRPH_INTERRUPT_CONTROL 0x1A17
+#define mmGRPH_INTERRUPT_STATUS 0x1A16
+#define mmGRPH_LUT_10BIT_BYPASS 0x1A02
+#define mmGRPH_PITCH 0x1A06
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS 0x1A04
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1A07
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS 0x1A05
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A08
+#define mmGRPH_STEREOSYNC_FLIP 0x1A97
+#define mmGRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1A18
+#define mmGRPH_SURFACE_ADDRESS_INUSE 0x1A13
+#define mmGRPH_SURFACE_OFFSET_X 0x1A09
+#define mmGRPH_SURFACE_OFFSET_Y 0x1A0A
+#define mmGRPH_SWAP_CNTL 0x1A03
+#define mmGRPH_UPDATE 0x1A11
+#define mmGRPH_X_END 0x1A0D
+#define mmGRPH_X_START 0x1A0B
+#define mmGRPH_Y_END 0x1A0E
+#define mmGRPH_Y_START 0x1A0C
+#define mmHDMI_ACR_32_0 0x1C37
+#define mmHDMI_ACR_32_1 0x1C38
+#define mmHDMI_ACR_44_0 0x1C39
+#define mmHDMI_ACR_44_1 0x1C3A
+#define mmHDMI_ACR_48_0 0x1C3B
+#define mmHDMI_ACR_48_1 0x1C3C
+#define mmHDMI_ACR_PACKET_CONTROL 0x1C0F
+#define mmHDMI_ACR_STATUS_0 0x1C3D
+#define mmHDMI_ACR_STATUS_1 0x1C3E
+#define mmHDMI_AUDIO_PACKET_CONTROL 0x1C0E
+#define mmHDMI_CONTROL 0x1C0C
+#define mmHDMI_GC 0x1C16
+#define mmHDMI_GENERIC_PACKET_CONTROL0 0x1C13
+#define mmHDMI_GENERIC_PACKET_CONTROL1 0x1C30
+#define mmHDMI_INFOFRAME_CONTROL0 0x1C11
+#define mmHDMI_INFOFRAME_CONTROL1 0x1C12
+#define mmHDMI_STATUS 0x1C0D
+#define mmHDMI_VBI_PACKET_CONTROL 0x1C10
+#define mmINPUT_CSC_C11_C12 0x1A36
+#define mmINPUT_CSC_C13_C14 0x1A37
+#define mmINPUT_CSC_C21_C22 0x1A38
+#define mmINPUT_CSC_C23_C24 0x1A39
+#define mmINPUT_CSC_C31_C32 0x1A3A
+#define mmINPUT_CSC_C33_C34 0x1A3B
+#define mmINPUT_CSC_CONTROL 0x1A35
+#define mmINPUT_GAMMA_CONTROL 0x1A10
+#define mmKEY_CONTROL 0x1A53
+#define mmKEY_RANGE_ALPHA 0x1A54
+#define mmKEY_RANGE_BLUE 0x1A57
+#define mmKEY_RANGE_GREEN 0x1A56
+#define mmKEY_RANGE_RED 0x1A55
+#define mmLB0_DC_MVP_LB_CONTROL 0x1ADB
+#define mmLB0_LB_DEBUG 0x1AFC
+#define mmLB0_LB_DEBUG2 0x1AC9
+#define mmLB0_LB_NO_OUTSTANDING_REQ_STATUS 0x1AC8
+#define mmLB0_LB_SYNC_RESET_SEL 0x1ACA
+#define mmLB0_LB_TEST_DEBUG_DATA 0x1AFF
+#define mmLB0_LB_TEST_DEBUG_INDEX 0x1AFE
+#define mmLB0_MVP_AFR_FLIP_FIFO_CNTL 0x1AD9
+#define mmLB0_MVP_AFR_FLIP_MODE 0x1AD8
+#define mmLB0_MVP_FLIP_LINE_NUM_INSERT 0x1ADA
+#define mmLB1_DC_MVP_LB_CONTROL 0x1DDB
+#define mmLB1_LB_DEBUG 0x1DFC
+#define mmLB1_LB_DEBUG2 0x1DC9
+#define mmLB1_LB_NO_OUTSTANDING_REQ_STATUS 0x1DC8
+#define mmLB1_LB_SYNC_RESET_SEL 0x1DCA
+#define mmLB1_LB_TEST_DEBUG_DATA 0x1DFF
+#define mmLB1_LB_TEST_DEBUG_INDEX 0x1DFE
+#define mmLB1_MVP_AFR_FLIP_FIFO_CNTL 0x1DD9
+#define mmLB1_MVP_AFR_FLIP_MODE 0x1DD8
+#define mmLB1_MVP_FLIP_LINE_NUM_INSERT 0x1DDA
+#define mmLB2_DC_MVP_LB_CONTROL 0x40DB
+#define mmLB2_LB_DEBUG 0x40FC
+#define mmLB2_LB_DEBUG2 0x40C9
+#define mmLB2_LB_NO_OUTSTANDING_REQ_STATUS 0x40C8
+#define mmLB2_LB_SYNC_RESET_SEL 0x40CA
+#define mmLB2_LB_TEST_DEBUG_DATA 0x40FF
+#define mmLB2_LB_TEST_DEBUG_INDEX 0x40FE
+#define mmLB2_MVP_AFR_FLIP_FIFO_CNTL 0x40D9
+#define mmLB2_MVP_AFR_FLIP_MODE 0x40D8
+#define mmLB2_MVP_FLIP_LINE_NUM_INSERT 0x40DA
+#define mmLB3_DC_MVP_LB_CONTROL 0x43DB
+#define mmLB3_LB_DEBUG 0x43FC
+#define mmLB3_LB_DEBUG2 0x43C9
+#define mmLB3_LB_NO_OUTSTANDING_REQ_STATUS 0x43C8
+#define mmLB3_LB_SYNC_RESET_SEL 0x43CA
+#define mmLB3_LB_TEST_DEBUG_DATA 0x43FF
+#define mmLB3_LB_TEST_DEBUG_INDEX 0x43FE
+#define mmLB3_MVP_AFR_FLIP_FIFO_CNTL 0x43D9
+#define mmLB3_MVP_AFR_FLIP_MODE 0x43D8
+#define mmLB3_MVP_FLIP_LINE_NUM_INSERT 0x43DA
+#define mmLB4_DC_MVP_LB_CONTROL 0x46DB
+#define mmLB4_LB_DEBUG 0x46FC
+#define mmLB4_LB_DEBUG2 0x46C9
+#define mmLB4_LB_NO_OUTSTANDING_REQ_STATUS 0x46C8
+#define mmLB4_LB_SYNC_RESET_SEL 0x46CA
+#define mmLB4_LB_TEST_DEBUG_DATA 0x46FF
+#define mmLB4_LB_TEST_DEBUG_INDEX 0x46FE
+#define mmLB4_MVP_AFR_FLIP_FIFO_CNTL 0x46D9
+#define mmLB4_MVP_AFR_FLIP_MODE 0x46D8
+#define mmLB4_MVP_FLIP_LINE_NUM_INSERT 0x46DA
+#define mmLB5_DC_MVP_LB_CONTROL 0x49DB
+#define mmLB5_LB_DEBUG 0x49FC
+#define mmLB5_LB_DEBUG2 0x49C9
+#define mmLB5_LB_NO_OUTSTANDING_REQ_STATUS 0x49C8
+#define mmLB5_LB_SYNC_RESET_SEL 0x49CA
+#define mmLB5_LB_TEST_DEBUG_DATA 0x49FF
+#define mmLB5_LB_TEST_DEBUG_INDEX 0x49FE
+#define mmLB5_MVP_AFR_FLIP_FIFO_CNTL 0x49D9
+#define mmLB5_MVP_AFR_FLIP_MODE 0x49D8
+#define mmLB5_MVP_FLIP_LINE_NUM_INSERT 0x49DA
+#define mmLB_DEBUG 0x1AFC
+#define mmLB_DEBUG2 0x1AC9
+#define mmLB_NO_OUTSTANDING_REQ_STATUS 0x1AC8
+#define mmLB_SYNC_RESET_SEL 0x1ACA
+#define mmLB_TEST_DEBUG_DATA 0x1AFF
+#define mmLB_TEST_DEBUG_INDEX 0x1AFE
+#define mmLIGHT_SLEEP_CNTL 0x0132
+#define mmLOW_POWER_TILING_CONTROL 0x0325
+#define mmLVDS_DATA_CNTL 0x1C8C
+#define mmLVTMA_PWRSEQ_CNTL 0x1919
+#define mmLVTMA_PWRSEQ_DELAY1 0x191C
+#define mmLVTMA_PWRSEQ_DELAY2 0x191D
+#define mmLVTMA_PWRSEQ_REF_DIV 0x191B
+#define mmLVTMA_PWRSEQ_STATE 0x191A
+#define mmMASTER_COMM_CMD_REG 0x161F
+#define mmMASTER_COMM_CNTL_REG 0x1620
+#define mmMASTER_COMM_DATA_REG1 0x161C
+#define mmMASTER_COMM_DATA_REG2 0x161D
+#define mmMASTER_COMM_DATA_REG3 0x161E
+#define mmMASTER_UPDATE_LOCK 0x1BBD
+#define mmMASTER_UPDATE_MODE 0x1BBE
+#define mmMC_DC_INTERFACE_NACK_STATUS 0x031C
+#define mmMCIF_CONTROL 0x0314
+#define mmMCIF_MEM_CONTROL 0x0319
+#define mmMCIF_TEST_DEBUG_DATA 0x0317
+#define mmMCIF_TEST_DEBUG_INDEX 0x0316
+#define mmMCIF_VMID 0x0318
+#define mmMCIF_WRITE_COMBINE_CONTROL 0x0315
+#define mmMICROSECOND_TIME_BASE_DIV 0x013B
+#define mmMILLISECOND_TIME_BASE_DIV 0x0130
+#define mmMVP_AFR_FLIP_FIFO_CNTL 0x1AD9
+#define mmMVP_AFR_FLIP_MODE 0x1AD8
+#define mmMVP_BLACK_KEYER 0x1686
+#define mmMVP_CONTROL1 0x1680
+#define mmMVP_CONTROL2 0x1681
+#define mmMVP_CONTROL3 0x168A
+#define mmMVP_CRC_CNTL 0x1687
+#define mmMVP_CRC_RESULT_BLUE_GREEN 0x1688
+#define mmMVP_CRC_RESULT_RED 0x1689
+#define mmMVP_DEBUG 0x168F
+#define mmMVP_FIFO_CONTROL 0x1682
+#define mmMVP_FIFO_STATUS 0x1683
+#define mmMVP_FLIP_LINE_NUM_INSERT 0x1ADA
+#define mmMVP_INBAND_CNTL_CAP 0x1685
+#define mmMVP_RECEIVE_CNT_CNTL1 0x168B
+#define mmMVP_RECEIVE_CNT_CNTL2 0x168C
+#define mmMVP_SLAVE_STATUS 0x1684
+#define mmMVP_TEST_DEBUG_DATA 0x168E
+#define mmMVP_TEST_DEBUG_INDEX 0x168D
+#define mmOUTPUT_CSC_C11_C12 0x1A3D
+#define mmOUTPUT_CSC_C13_C14 0x1A3E
+#define mmOUTPUT_CSC_C21_C22 0x1A3F
+#define mmOUTPUT_CSC_C23_C24 0x1A40
+#define mmOUTPUT_CSC_C31_C32 0x1A41
+#define mmOUTPUT_CSC_C33_C34 0x1A42
+#define mmOUTPUT_CSC_CONTROL 0x1A3C
+#define mmOUT_ROUND_CONTROL 0x1A51
+#define mmOVL_CONTROL1 0x1A1D
+#define mmOVL_CONTROL2 0x1A1E
+#define mmOVL_DFQ_CONTROL 0x1A29
+#define mmOVL_DFQ_STATUS 0x1A2A
+#define mmOVL_ENABLE 0x1A1C
+#define mmOVL_END 0x1A26
+#define mmOVL_PITCH 0x1A21
+#define mmOVLSCL_EDGE_PIXEL_CNTL 0x1A2C
+#define mmOVL_SECONDARY_SURFACE_ADDRESS 0x1A92
+#define mmOVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A94
+#define mmOVL_START 0x1A25
+#define mmOVL_STEREOSYNC_FLIP 0x1A93
+#define mmOVL_SURFACE_ADDRESS 0x1A20
+#define mmOVL_SURFACE_ADDRESS_HIGH 0x1A22
+#define mmOVL_SURFACE_ADDRESS_HIGH_INUSE 0x1A2B
+#define mmOVL_SURFACE_ADDRESS_INUSE 0x1A28
+#define mmOVL_SURFACE_OFFSET_X 0x1A23
+#define mmOVL_SURFACE_OFFSET_Y 0x1A24
+#define mmOVL_SWAP_CNTL 0x1A1F
+#define mmOVL_UPDATE 0x1A27
+#define mmPHY_AUX_CNTL 0x197F
+#define mmPIPE0_ARBITRATION_CONTROL3 0x02FA
+#define mmPIPE0_DMIF_BUFFER_CONTROL 0x0328
+#define mmPIPE0_MAX_REQUESTS 0x0302
+#define mmPIPE0_PG_CONFIG 0x1760
+#define mmPIPE0_PG_ENABLE 0x1761
+#define mmPIPE0_PG_STATUS 0x1762
+#define mmPIPE1_ARBITRATION_CONTROL3 0x02FB
+#define mmPIPE1_DMIF_BUFFER_CONTROL 0x0330
+#define mmPIPE1_MAX_REQUESTS 0x0303
+#define mmPIPE1_PG_CONFIG 0x1764
+#define mmPIPE1_PG_ENABLE 0x1765
+#define mmPIPE1_PG_STATUS 0x1766
+#define mmPIPE2_ARBITRATION_CONTROL3 0x02FC
+#define mmPIPE2_DMIF_BUFFER_CONTROL 0x0338
+#define mmPIPE2_MAX_REQUESTS 0x0304
+#define mmPIPE2_PG_CONFIG 0x1768
+#define mmPIPE2_PG_ENABLE 0x1769
+#define mmPIPE2_PG_STATUS 0x176A
+#define mmPIPE3_ARBITRATION_CONTROL3 0x02FD
+#define mmPIPE3_DMIF_BUFFER_CONTROL 0x0340
+#define mmPIPE3_MAX_REQUESTS 0x0305
+#define mmPIPE3_PG_CONFIG 0x176C
+#define mmPIPE3_PG_ENABLE 0x176D
+#define mmPIPE3_PG_STATUS 0x176E
+#define mmPIPE4_ARBITRATION_CONTROL3 0x02FE
+#define mmPIPE4_DMIF_BUFFER_CONTROL 0x0348
+#define mmPIPE4_MAX_REQUESTS 0x0306
+#define mmPIPE4_PG_CONFIG 0x1770
+#define mmPIPE4_PG_ENABLE 0x1771
+#define mmPIPE4_PG_STATUS 0x1772
+#define mmPIPE5_ARBITRATION_CONTROL3 0x02FF
+#define mmPIPE5_DMIF_BUFFER_CONTROL 0x0350
+#define mmPIPE5_MAX_REQUESTS 0x0307
+#define mmPIPE5_PG_CONFIG 0x1774
+#define mmPIPE5_PG_ENABLE 0x1775
+#define mmPIPE5_PG_STATUS 0x1776
+#define mmPIXCLK0_RESYNC_CNTL 0x013A
+#define mmPIXCLK1_RESYNC_CNTL 0x0138
+#define mmPIXCLK2_RESYNC_CNTL 0x0139
+#define mmPLL_ANALOG 0x1708
+#define mmPLL_CNTL 0x1707
+#define mmPLL_DEBUG_CNTL 0x170B
+#define mmPLL_DISPCLK_CURRENT_DTO_PHASE 0x170F
+#define mmPLL_DISPCLK_DTO_CNTL 0x170E
+#define mmPLL_DS_CNTL 0x1705
+#define mmPLL_FB_DIV 0x1701
+#define mmPLL_IDCLK_CNTL 0x1706
+#define mmPLL_POST_DIV 0x1702
+#define mmPLL_REF_DIV 0x1700
+#define mmPLL_SS_AMOUNT_DSFRAC 0x1703
+#define mmPLL_SS_CNTL 0x1704
+#define mmPLL_UNLOCK_DETECT_CNTL 0x170A
+#define mmPLL_UPDATE_CNTL 0x170D
+#define mmPLL_UPDATE_LOCK 0x170C
+#define mmPLL_VREG_CNTL 0x1709
+#define mmPRESCALE_GRPH_CONTROL 0x1A2D
+#define mmPRESCALE_OVL_CONTROL 0x1A31
+#define mmPRESCALE_VALUES_GRPH_B 0x1A30
+#define mmPRESCALE_VALUES_GRPH_G 0x1A2F
+#define mmPRESCALE_VALUES_GRPH_R 0x1A2E
+#define mmPRESCALE_VALUES_OVL_CB 0x1A32
+#define mmPRESCALE_VALUES_OVL_CR 0x1A34
+#define mmPRESCALE_VALUES_OVL_Y 0x1A33
+#define mmREGAMMA_CNTLA_END_CNTL1 0x1AA6
+#define mmREGAMMA_CNTLA_END_CNTL2 0x1AA7
+#define mmREGAMMA_CNTLA_REGION_0_1 0x1AA8
+#define mmREGAMMA_CNTLA_REGION_10_11 0x1AAD
+#define mmREGAMMA_CNTLA_REGION_12_13 0x1AAE
+#define mmREGAMMA_CNTLA_REGION_14_15 0x1AAF
+#define mmREGAMMA_CNTLA_REGION_2_3 0x1AA9
+#define mmREGAMMA_CNTLA_REGION_4_5 0x1AAA
+#define mmREGAMMA_CNTLA_REGION_6_7 0x1AAB
+#define mmREGAMMA_CNTLA_REGION_8_9 0x1AAC
+#define mmREGAMMA_CNTLA_SLOPE_CNTL 0x1AA5
+#define mmREGAMMA_CNTLA_START_CNTL 0x1AA4
+#define mmREGAMMA_CNTLB_END_CNTL1 0x1AB2
+#define mmREGAMMA_CNTLB_END_CNTL2 0x1AB3
+#define mmREGAMMA_CNTLB_REGION_0_1 0x1AB4
+#define mmREGAMMA_CNTLB_REGION_10_11 0x1AB9
+#define mmREGAMMA_CNTLB_REGION_12_13 0x1ABA
+#define mmREGAMMA_CNTLB_REGION_14_15 0x1ABB
+#define mmREGAMMA_CNTLB_REGION_2_3 0x1AB5
+#define mmREGAMMA_CNTLB_REGION_4_5 0x1AB6
+#define mmREGAMMA_CNTLB_REGION_6_7 0x1AB7
+#define mmREGAMMA_CNTLB_REGION_8_9 0x1AB8
+#define mmREGAMMA_CNTLB_SLOPE_CNTL 0x1AB1
+#define mmREGAMMA_CNTLB_START_CNTL 0x1AB0
+#define mmREGAMMA_CONTROL 0x1AA0
+#define mmREGAMMA_LUT_DATA 0x1AA2
+#define mmREGAMMA_LUT_INDEX 0x1AA1
+#define mmREGAMMA_LUT_WRITE_EN_MASK 0x1AA3
+#define mmSCL0_EXT_OVERSCAN_LEFT_RIGHT 0x1B5E
+#define mmSCL0_EXT_OVERSCAN_TOP_BOTTOM 0x1B5F
+#define mmSCL0_SCL_ALU_CONTROL 0x1B54
+#define mmSCL0_SCL_AUTOMATIC_MODE_CONTROL 0x1B47
+#define mmSCL0_SCL_BYPASS_CONTROL 0x1B45
+#define mmSCL0_SCL_COEF_RAM_CONFLICT_STATUS 0x1B55
+#define mmSCL0_SCL_COEF_RAM_SELECT 0x1B40
+#define mmSCL0_SCL_COEF_RAM_TAP_DATA 0x1B41
+#define mmSCL0_SCL_CONTROL 0x1B44
+#define mmSCL0_SCL_DEBUG 0x1B6A
+#define mmSCL0_SCL_DEBUG2 0x1B69
+#define mmSCL0_SCL_F_SHARP_CONTROL 0x1B53
+#define mmSCL0_SCL_HORZ_FILTER_CONTROL 0x1B4A
+#define mmSCL0_SCL_HORZ_FILTER_SCALE_RATIO 0x1B4B
+#define mmSCL0_SCL_MANUAL_REPLICATE_CONTROL 0x1B46
+#define mmSCL0_SCL_MODE_CHANGE_DET1 0x1B60
+#define mmSCL0_SCL_MODE_CHANGE_DET2 0x1B61
+#define mmSCL0_SCL_MODE_CHANGE_DET3 0x1B62
+#define mmSCL0_SCL_MODE_CHANGE_MASK 0x1B63
+#define mmSCL0_SCL_TAP_CONTROL 0x1B43
+#define mmSCL0_SCL_TEST_DEBUG_DATA 0x1B6C
+#define mmSCL0_SCL_TEST_DEBUG_INDEX 0x1B6B
+#define mmSCL0_SCL_UPDATE 0x1B51
+#define mmSCL0_SCL_VERT_FILTER_CONTROL 0x1B4E
+#define mmSCL0_SCL_VERT_FILTER_INIT 0x1B50
+#define mmSCL0_SCL_VERT_FILTER_INIT_BOT 0x1B57
+#define mmSCL0_SCL_VERT_FILTER_SCALE_RATIO 0x1B4F
+#define mmSCL0_VIEWPORT_SIZE 0x1B5D
+#define mmSCL0_VIEWPORT_START 0x1B5C
+#define mmSCL1_EXT_OVERSCAN_LEFT_RIGHT 0x1E5E
+#define mmSCL1_EXT_OVERSCAN_TOP_BOTTOM 0x1E5F
+#define mmSCL1_SCL_ALU_CONTROL 0x1E54
+#define mmSCL1_SCL_AUTOMATIC_MODE_CONTROL 0x1E47
+#define mmSCL1_SCL_BYPASS_CONTROL 0x1E45
+#define mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS 0x1E55
+#define mmSCL1_SCL_COEF_RAM_SELECT 0x1E40
+#define mmSCL1_SCL_COEF_RAM_TAP_DATA 0x1E41
+#define mmSCL1_SCL_CONTROL 0x1E44
+#define mmSCL1_SCL_DEBUG 0x1E6A
+#define mmSCL1_SCL_DEBUG2 0x1E69
+#define mmSCL1_SCL_F_SHARP_CONTROL 0x1E53
+#define mmSCL1_SCL_HORZ_FILTER_CONTROL 0x1E4A
+#define mmSCL1_SCL_HORZ_FILTER_SCALE_RATIO 0x1E4B
+#define mmSCL1_SCL_MANUAL_REPLICATE_CONTROL 0x1E46
+#define mmSCL1_SCL_MODE_CHANGE_DET1 0x1E60
+#define mmSCL1_SCL_MODE_CHANGE_DET2 0x1E61
+#define mmSCL1_SCL_MODE_CHANGE_DET3 0x1E62
+#define mmSCL1_SCL_MODE_CHANGE_MASK 0x1E63
+#define mmSCL1_SCL_TAP_CONTROL 0x1E43
+#define mmSCL1_SCL_TEST_DEBUG_DATA 0x1E6C
+#define mmSCL1_SCL_TEST_DEBUG_INDEX 0x1E6B
+#define mmSCL1_SCL_UPDATE 0x1E51
+#define mmSCL1_SCL_VERT_FILTER_CONTROL 0x1E4E
+#define mmSCL1_SCL_VERT_FILTER_INIT 0x1E50
+#define mmSCL1_SCL_VERT_FILTER_INIT_BOT 0x1E57
+#define mmSCL1_SCL_VERT_FILTER_SCALE_RATIO 0x1E4F
+#define mmSCL1_VIEWPORT_SIZE 0x1E5D
+#define mmSCL1_VIEWPORT_START 0x1E5C
+#define mmSCL2_EXT_OVERSCAN_LEFT_RIGHT 0x415E
+#define mmSCL2_EXT_OVERSCAN_TOP_BOTTOM 0x415F
+#define mmSCL2_SCL_ALU_CONTROL 0x4154
+#define mmSCL2_SCL_AUTOMATIC_MODE_CONTROL 0x4147
+#define mmSCL2_SCL_BYPASS_CONTROL 0x4145
+#define mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS 0x4155
+#define mmSCL2_SCL_COEF_RAM_SELECT 0x4140
+#define mmSCL2_SCL_COEF_RAM_TAP_DATA 0x4141
+#define mmSCL2_SCL_CONTROL 0x4144
+#define mmSCL2_SCL_DEBUG 0x416A
+#define mmSCL2_SCL_DEBUG2 0x4169
+#define mmSCL2_SCL_F_SHARP_CONTROL 0x4153
+#define mmSCL2_SCL_HORZ_FILTER_CONTROL 0x414A
+#define mmSCL2_SCL_HORZ_FILTER_SCALE_RATIO 0x414B
+#define mmSCL2_SCL_MANUAL_REPLICATE_CONTROL 0x4146
+#define mmSCL2_SCL_MODE_CHANGE_DET1 0x4160
+#define mmSCL2_SCL_MODE_CHANGE_DET2 0x4161
+#define mmSCL2_SCL_MODE_CHANGE_DET3 0x4162
+#define mmSCL2_SCL_MODE_CHANGE_MASK 0x4163
+#define mmSCL2_SCL_TAP_CONTROL 0x4143
+#define mmSCL2_SCL_TEST_DEBUG_DATA 0x416C
+#define mmSCL2_SCL_TEST_DEBUG_INDEX 0x416B
+#define mmSCL2_SCL_UPDATE 0x4151
+#define mmSCL2_SCL_VERT_FILTER_CONTROL 0x414E
+#define mmSCL2_SCL_VERT_FILTER_INIT 0x4150
+#define mmSCL2_SCL_VERT_FILTER_INIT_BOT 0x4157
+#define mmSCL2_SCL_VERT_FILTER_SCALE_RATIO 0x414F
+#define mmSCL2_VIEWPORT_SIZE 0x415D
+#define mmSCL2_VIEWPORT_START 0x415C
+#define mmSCL3_EXT_OVERSCAN_LEFT_RIGHT 0x445E
+#define mmSCL3_EXT_OVERSCAN_TOP_BOTTOM 0x445F
+#define mmSCL3_SCL_ALU_CONTROL 0x4454
+#define mmSCL3_SCL_AUTOMATIC_MODE_CONTROL 0x4447
+#define mmSCL3_SCL_BYPASS_CONTROL 0x4445
+#define mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS 0x4455
+#define mmSCL3_SCL_COEF_RAM_SELECT 0x4440
+#define mmSCL3_SCL_COEF_RAM_TAP_DATA 0x4441
+#define mmSCL3_SCL_CONTROL 0x4444
+#define mmSCL3_SCL_DEBUG 0x446A
+#define mmSCL3_SCL_DEBUG2 0x4469
+#define mmSCL3_SCL_F_SHARP_CONTROL 0x4453
+#define mmSCL3_SCL_HORZ_FILTER_CONTROL 0x444A
+#define mmSCL3_SCL_HORZ_FILTER_SCALE_RATIO 0x444B
+#define mmSCL3_SCL_MANUAL_REPLICATE_CONTROL 0x4446
+#define mmSCL3_SCL_MODE_CHANGE_DET1 0x4460
+#define mmSCL3_SCL_MODE_CHANGE_DET2 0x4461
+#define mmSCL3_SCL_MODE_CHANGE_DET3 0x4462
+#define mmSCL3_SCL_MODE_CHANGE_MASK 0x4463
+#define mmSCL3_SCL_TAP_CONTROL 0x4443
+#define mmSCL3_SCL_TEST_DEBUG_DATA 0x446C
+#define mmSCL3_SCL_TEST_DEBUG_INDEX 0x446B
+#define mmSCL3_SCL_UPDATE 0x4451
+#define mmSCL3_SCL_VERT_FILTER_CONTROL 0x444E
+#define mmSCL3_SCL_VERT_FILTER_INIT 0x4450
+#define mmSCL3_SCL_VERT_FILTER_INIT_BOT 0x4457
+#define mmSCL3_SCL_VERT_FILTER_SCALE_RATIO 0x444F
+#define mmSCL3_VIEWPORT_SIZE 0x445D
+#define mmSCL3_VIEWPORT_START 0x445C
+#define mmSCL4_EXT_OVERSCAN_LEFT_RIGHT 0x475E
+#define mmSCL4_EXT_OVERSCAN_TOP_BOTTOM 0x475F
+#define mmSCL4_SCL_ALU_CONTROL 0x4754
+#define mmSCL4_SCL_AUTOMATIC_MODE_CONTROL 0x4747
+#define mmSCL4_SCL_BYPASS_CONTROL 0x4745
+#define mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS 0x4755
+#define mmSCL4_SCL_COEF_RAM_SELECT 0x4740
+#define mmSCL4_SCL_COEF_RAM_TAP_DATA 0x4741
+#define mmSCL4_SCL_CONTROL 0x4744
+#define mmSCL4_SCL_DEBUG 0x476A
+#define mmSCL4_SCL_DEBUG2 0x4769
+#define mmSCL4_SCL_F_SHARP_CONTROL 0x4753
+#define mmSCL4_SCL_HORZ_FILTER_CONTROL 0x474A
+#define mmSCL4_SCL_HORZ_FILTER_SCALE_RATIO 0x474B
+#define mmSCL4_SCL_MANUAL_REPLICATE_CONTROL 0x4746
+#define mmSCL4_SCL_MODE_CHANGE_DET1 0x4760
+#define mmSCL4_SCL_MODE_CHANGE_DET2 0x4761
+#define mmSCL4_SCL_MODE_CHANGE_DET3 0x4762
+#define mmSCL4_SCL_MODE_CHANGE_MASK 0x4763
+#define mmSCL4_SCL_TAP_CONTROL 0x4743
+#define mmSCL4_SCL_TEST_DEBUG_DATA 0x476C
+#define mmSCL4_SCL_TEST_DEBUG_INDEX 0x476B
+#define mmSCL4_SCL_UPDATE 0x4751
+#define mmSCL4_SCL_VERT_FILTER_CONTROL 0x474E
+#define mmSCL4_SCL_VERT_FILTER_INIT 0x4750
+#define mmSCL4_SCL_VERT_FILTER_INIT_BOT 0x4757
+#define mmSCL4_SCL_VERT_FILTER_SCALE_RATIO 0x474F
+#define mmSCL4_VIEWPORT_SIZE 0x475D
+#define mmSCL4_VIEWPORT_START 0x475C
+#define mmSCL5_EXT_OVERSCAN_LEFT_RIGHT 0x4A5E
+#define mmSCL5_EXT_OVERSCAN_TOP_BOTTOM 0x4A5F
+#define mmSCL5_SCL_ALU_CONTROL 0x4A54
+#define mmSCL5_SCL_AUTOMATIC_MODE_CONTROL 0x4A47
+#define mmSCL5_SCL_BYPASS_CONTROL 0x4A45
+#define mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS 0x4A55
+#define mmSCL5_SCL_COEF_RAM_SELECT 0x4A40
+#define mmSCL5_SCL_COEF_RAM_TAP_DATA 0x4A41
+#define mmSCL5_SCL_CONTROL 0x4A44
+#define mmSCL5_SCL_DEBUG 0x4A6A
+#define mmSCL5_SCL_DEBUG2 0x4A69
+#define mmSCL5_SCL_F_SHARP_CONTROL 0x4A53
+#define mmSCL5_SCL_HORZ_FILTER_CONTROL 0x4A4A
+#define mmSCL5_SCL_HORZ_FILTER_SCALE_RATIO 0x4A4B
+#define mmSCL5_SCL_MANUAL_REPLICATE_CONTROL 0x4A46
+#define mmSCL5_SCL_MODE_CHANGE_DET1 0x4A60
+#define mmSCL5_SCL_MODE_CHANGE_DET2 0x4A61
+#define mmSCL5_SCL_MODE_CHANGE_DET3 0x4A62
+#define mmSCL5_SCL_MODE_CHANGE_MASK 0x4A63
+#define mmSCL5_SCL_TAP_CONTROL 0x4A43
+#define mmSCL5_SCL_TEST_DEBUG_DATA 0x4A6C
+#define mmSCL5_SCL_TEST_DEBUG_INDEX 0x4A6B
+#define mmSCL5_SCL_UPDATE 0x4A51
+#define mmSCL5_SCL_VERT_FILTER_CONTROL 0x4A4E
+#define mmSCL5_SCL_VERT_FILTER_INIT 0x4A50
+#define mmSCL5_SCL_VERT_FILTER_INIT_BOT 0x4A57
+#define mmSCL5_SCL_VERT_FILTER_SCALE_RATIO 0x4A4F
+#define mmSCL5_VIEWPORT_SIZE 0x4A5D
+#define mmSCL5_VIEWPORT_START 0x4A5C
+#define mmSCL_ALU_CONTROL 0x1B54
+#define mmSCL_AUTOMATIC_MODE_CONTROL 0x1B47
+#define mmSCL_BYPASS_CONTROL 0x1B45
+#define mmSCL_COEF_RAM_CONFLICT_STATUS 0x1B55
+#define mmSCL_COEF_RAM_SELECT 0x1B40
+#define mmSCL_COEF_RAM_TAP_DATA 0x1B41
+#define mmSCL_CONTROL 0x1B44
+#define mmSCL_DEBUG 0x1B6A
+#define mmSCL_DEBUG2 0x1B69
+#define mmSCL_F_SHARP_CONTROL 0x1B53
+#define mmSCL_HORZ_FILTER_CONTROL 0x1B4A
+#define mmSCL_HORZ_FILTER_SCALE_RATIO 0x1B4B
+#define mmSCLK_CGTT_BLK_CTRL_REG 0x0136
+#define mmSCL_MANUAL_REPLICATE_CONTROL 0x1B46
+#define mmSCL_MODE_CHANGE_DET1 0x1B60
+#define mmSCL_MODE_CHANGE_DET2 0x1B61
+#define mmSCL_MODE_CHANGE_DET3 0x1B62
+#define mmSCL_MODE_CHANGE_MASK 0x1B63
+#define mmSCL_TAP_CONTROL 0x1B43
+#define mmSCL_TEST_DEBUG_DATA 0x1B6C
+#define mmSCL_TEST_DEBUG_INDEX 0x1B6B
+#define mmSCL_UPDATE 0x1B51
+#define mmSCL_VERT_FILTER_CONTROL 0x1B4E
+#define mmSCL_VERT_FILTER_INIT 0x1B50
+#define mmSCL_VERT_FILTER_INIT_BOT 0x1B57
+#define mmSCL_VERT_FILTER_SCALE_RATIO 0x1B4F
+#define mmSEQ8_DATA 0x00F1
+#define mmSEQ8_IDX 0x00F1
+#define mmSLAVE_COMM_CMD_REG 0x1624
+#define mmSLAVE_COMM_CNTL_REG 0x1625
+#define mmSLAVE_COMM_DATA_REG1 0x1621
+#define mmSLAVE_COMM_DATA_REG2 0x1622
+#define mmSLAVE_COMM_DATA_REG3 0x1623
+#define mmSYMCLKA_CLOCK_ENABLE 0x0160
+#define mmSYMCLKB_CLOCK_ENABLE 0x0161
+#define mmSYMCLKC_CLOCK_ENABLE 0x0162
+#define mmSYMCLKD_CLOCK_ENABLE 0x0163
+#define mmSYMCLKE_CLOCK_ENABLE 0x0164
+#define mmSYMCLKF_CLOCK_ENABLE 0x0165
+#define mmTMDS_CNTL 0x1C7C
+#define mmTMDS_CONTROL0_FEEDBACK 0x1C7E
+#define mmTMDS_CONTROL_CHAR 0x1C7D
+#define mmTMDS_CTL0_1_GEN_CNTL 0x1C86
+#define mmTMDS_CTL2_3_GEN_CNTL 0x1C87
+#define mmTMDS_CTL_BITS 0x1C83
+#define mmTMDS_DCBALANCER_CONTROL 0x1C84
+#define mmTMDS_DEBUG 0x1C82
+#define mmTMDS_STEREOSYNC_CTL_SEL 0x1C7F
+#define mmTMDS_SYNC_CHAR_PATTERN_0_1 0x1C80
+#define mmTMDS_SYNC_CHAR_PATTERN_2_3 0x1C81
+#define mmUNIPHYAB_TPG_CONTROL 0x1931
+#define mmUNIPHYAB_TPG_SEED 0x1932
+#define mmUNIPHY_ANG_BIST_CNTL 0x198C
+#define mmUNIPHYCD_TPG_CONTROL 0x1933
+#define mmUNIPHYCD_TPG_SEED 0x1934
+#define mmUNIPHY_CHANNEL_XBAR_CNTL 0x198E
+#define mmUNIPHY_DATA_SYNCHRONIZATION 0x198A
+#define mmUNIPHYEF_TPG_CONTROL 0x1935
+#define mmUNIPHYEF_TPG_SEED 0x1936
+#define mmUNIPHY_IMPCAL_LINKA 0x1908
+#define mmUNIPHY_IMPCAL_LINKB 0x1909
+#define mmUNIPHY_IMPCAL_LINKC 0x190F
+#define mmUNIPHY_IMPCAL_LINKD 0x1910
+#define mmUNIPHY_IMPCAL_LINKE 0x1913
+#define mmUNIPHY_IMPCAL_LINKF 0x1914
+#define mmUNIPHY_IMPCAL_PERIOD 0x190A
+#define mmUNIPHY_IMPCAL_PSW_AB 0x190E
+#define mmUNIPHY_IMPCAL_PSW_CD 0x1912
+#define mmUNIPHY_IMPCAL_PSW_EF 0x1916
+#define mmUNIPHY_LINK_CNTL 0x198D
+#define mmUNIPHY_PLL_CONTROL1 0x1986
+#define mmUNIPHY_PLL_CONTROL2 0x1987
+#define mmUNIPHY_PLL_FBDIV 0x1985
+#define mmUNIPHY_PLL_SS_CNTL 0x1989
+#define mmUNIPHY_PLL_SS_STEP_SIZE 0x1988
+#define mmUNIPHY_POWER_CONTROL 0x1984
+#define mmUNIPHY_REG_TEST_OUTPUT 0x198B
+#define mmUNIPHY_SOFT_RESET 0x0166
+#define mmUNIPHY_TX_CONTROL1 0x1980
+#define mmUNIPHY_TX_CONTROL2 0x1981
+#define mmUNIPHY_TX_CONTROL3 0x1982
+#define mmUNIPHY_TX_CONTROL4 0x1983
+#define mmVGA25_PPLL_ANALOG 0x00E4
+#define mmVGA25_PPLL_FB_DIV 0x00DC
+#define mmVGA25_PPLL_POST_DIV 0x00E0
+#define mmVGA25_PPLL_REF_DIV 0x00D8
+#define mmVGA28_PPLL_ANALOG 0x00E5
+#define mmVGA28_PPLL_FB_DIV 0x00DD
+#define mmVGA28_PPLL_POST_DIV 0x00E1
+#define mmVGA28_PPLL_REF_DIV 0x00D9
+#define mmVGA41_PPLL_ANALOG 0x00E6
+#define mmVGA41_PPLL_FB_DIV 0x00DE
+#define mmVGA41_PPLL_POST_DIV 0x00E2
+#define mmVGA41_PPLL_REF_DIV 0x00DA
+#define mmVGA_CACHE_CONTROL 0x00CB
+#define mmVGA_DEBUG_READBACK_DATA 0x00D7
+#define mmVGA_DEBUG_READBACK_INDEX 0x00D6
+#define mmVGA_DISPBUF1_SURFACE_ADDR 0x00C6
+#define mmVGA_DISPBUF2_SURFACE_ADDR 0x00C8
+#define mmVGA_HDP_CONTROL 0x00CA
+#define mmVGA_HW_DEBUG 0x00CF
+#define mmVGA_INTERRUPT_CONTROL 0x00D1
+#define mmVGA_INTERRUPT_STATUS 0x00D3
+#define mmVGA_MAIN_CONTROL 0x00D4
+#define mmVGA_MEMORY_BASE_ADDRESS 0x00C4
+#define mmVGA_MEMORY_BASE_ADDRESS_HIGH 0x00C9
+#define mmVGA_MEM_READ_PAGE_ADDR 0x0013
+#define mmVGA_MEM_WRITE_PAGE_ADDR 0x0012
+#define mmVGA_MODE_CONTROL 0x00C2
+#define mmVGA_RENDER_CONTROL 0x00C0
+#define mmVGA_SEQUENCER_RESET_CONTROL 0x00C1
+#define mmVGA_SOURCE_SELECT 0x00FC
+#define mmVGA_STATUS 0x00D0
+#define mmVGA_STATUS_CLEAR 0x00D2
+#define mmVGA_SURFACE_PITCH_SELECT 0x00C3
+#define mmVGA_TEST_CONTROL 0x00D5
+#define mmVGA_TEST_DEBUG_DATA 0x00C7
+#define mmVGA_TEST_DEBUG_INDEX 0x00C5
+#define mmVIEWPORT_SIZE 0x1B5D
+#define mmVIEWPORT_START 0x1B5C
+#define mmXDMA_CLOCK_GATING_CNTL 0x0409
+#define mmXDMA_IF_BIF_STATUS 0x0418
+#define mmXDMA_INTERRUPT 0x0406
+#define mmXDMA_LOCAL_SURFACE_TILING1 0x03F4
+#define mmXDMA_LOCAL_SURFACE_TILING2 0x03F5
+#define mmXDMA_MC_PCIE_CLIENT_CONFIG 0x03E9
+#define mmXDMA_MEM_POWER_CNTL 0x040B
+#define mmXDMA_MSTR_CMD_URGENT_CNTL 0x03F6
+#define mmXDMA_MSTR_CNTL 0x03E0
+#define mmXDMA_MSTR_HEIGHT 0x03E3
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR 0x03F1
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH 0x03F2
+#define mmXDMA_MSTR_LOCAL_SURFACE_PITCH 0x03F3
+#define mmXDMA_MSTR_MEM_CLIENT_CONFIG 0x03EA
+#define mmXDMA_MSTR_MEM_NACK_STATUS 0x040D
+#define mmXDMA_MSTR_MEM_URGENT_CNTL 0x03F7
+#define mmXDMA_MSTR_PCIE_NACK_STATUS 0x040C
+#define mmXDMA_MSTR_READ_COMMAND 0x03E1
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS 0x03E6
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH 0x03E7
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE 0x03E4
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE_HIGH 0x03E5
+#define mmXDMA_MSTR_STATUS 0x03E8
+#define mmXDMA_RBBMIF_RDWR_CNTL 0x040A
+#define mmXDMA_SLV_CNTL 0x03FB
+#define mmXDMA_SLV_FLIP_PENDING 0x0407
+#define mmXDMA_SLV_MEM_CLIENT_CONFIG 0x03FD
+#define mmXDMA_SLV_MEM_NACK_STATUS 0x040F
+#define mmXDMA_SLV_PCIE_NACK_STATUS 0x040E
+#define mmXDMA_SLV_READ_LATENCY_AVE 0x0405
+#define mmXDMA_SLV_READ_LATENCY_MINMAX 0x0404
+#define mmXDMA_SLV_READ_LATENCY_TIMER 0x0412
+#define mmXDMA_SLV_READ_URGENT_CNTL 0x03FF
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS 0x0402
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS_HIGH 0x0403
+#define mmXDMA_SLV_SLS_PITCH 0x03FE
+#define mmXDMA_SLV_WB_RATE_CNTL 0x0401
+#define mmXDMA_SLV_WRITE_URGENT_CNTL 0x0400
+#define mmXDMA_TEST_DEBUG_DATA 0x041D
+#define mmXDMA_TEST_DEBUG_INDEX 0x041C
+
+/* Registers that spilled out of sid.h */
+#define mmDATA_FORMAT 0x1AC0
+#define mmDESKTOP_HEIGHT 0x1AC1
+#define mmDC_LB_MEMORY_SPLIT 0x1AC3
+#define mmPRIORITY_A_CNT 0x1AC6
+#define mmPRIORITY_B_CNT 0x1AC7
+#define mmDPG_PIPE_ARBITRATION_CONTROL3 0x1B32
+#define mmINT_MASK 0x1AD0
+#define mmVLINE_STATUS 0x1AEE
+#define mmVBLANK_STATUS 0x1AEF
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
new file mode 100644
index 000000000000..9a4d4c299d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
@@ -0,0 +1,9836 @@
+/*
+ *
+ * Copyright (C) 2016 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 DCE_6_0_SH_MASK_H
+#define DCE_6_0_SH_MASK_H
+
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define AFMT_60958_0__AFMT_60958_CS_A_MASK 0x00000001L
+#define AFMT_60958_0__AFMT_60958_CS_A__SHIFT 0x00000000
+#define AFMT_60958_0__AFMT_60958_CS_B_MASK 0x00000002L
+#define AFMT_60958_0__AFMT_60958_CS_B__SHIFT 0x00000001
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE_MASK 0x0000ff00L
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE__SHIFT 0x00000008
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK 0x00f00000L
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000014
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK 0x30000000L
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY__SHIFT 0x0000001c
+#define AFMT_60958_0__AFMT_60958_CS_C_MASK 0x00000004L
+#define AFMT_60958_0__AFMT_60958_CS_C__SHIFT 0x00000002
+#define AFMT_60958_0__AFMT_60958_CS_D_MASK 0x00000038L
+#define AFMT_60958_0__AFMT_60958_CS_D__SHIFT 0x00000003
+#define AFMT_60958_0__AFMT_60958_CS_MODE_MASK 0x000000c0L
+#define AFMT_60958_0__AFMT_60958_CS_MODE__SHIFT 0x00000006
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY_MASK 0x0f000000L
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000018
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER_MASK 0x000f0000L
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER__SHIFT 0x00000010
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R_MASK 0x00f00000L
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000014
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x000000f0L
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000004
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH_MASK 0x0000000fL
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH__SHIFT 0x00000000
+#define AFMT_60958_1__AFMT_60958_VALID_L_MASK 0x00010000L
+#define AFMT_60958_1__AFMT_60958_VALID_L__SHIFT 0x00000010
+#define AFMT_60958_1__AFMT_60958_VALID_R_MASK 0x00040000L
+#define AFMT_60958_1__AFMT_60958_VALID_R__SHIFT 0x00000012
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4_MASK 0x00000f00L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000008
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5_MASK 0x0000f000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x0000000c
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6_MASK 0x000f0000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000010
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7_MASK 0x00f00000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000014
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL_MASK 0x0000f000L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL__SHIFT 0x0000000c
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT_MASK 0x00000010L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT__SHIFT 0x00000004
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT_MASK 0xffff0000L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT__SHIFT 0x00000010
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN_MASK 0x00000001L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN__SHIFT 0x00000000
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE_MASK 0x00000100L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE__SHIFT 0x00000008
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE_MASK 0x00000001L
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE__SHIFT 0x00000000
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_MASK 0xffffff00L
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC__SHIFT 0x00000008
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE_MASK 0x00000100L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE__SHIFT 0x00000008
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV_MASK 0x00070000L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV__SHIFT 0x00000010
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI_MASK 0x00007000L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI__SHIFT 0x0000000c
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL_MASK 0x00000007L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC_MASK 0x00000700L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC__SHIFT 0x00000008
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET_MASK 0x00ff0000L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET__SHIFT 0x00000010
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT_MASK 0x00007800L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT__SHIFT 0x0000000b
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT_MASK 0x1f000000L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT__SHIFT 0x00000018
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA_MASK 0x000000ffL
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH_MASK 0x00008000L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH__SHIFT 0x0000000f
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL_MASK 0x00030000L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL__SHIFT 0x00000010
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV_MASK 0x00007800L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV__SHIFT 0x0000000b
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD_MASK 0x10000000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD__SHIFT 0x0000001c
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE_MASK 0x0000ff00L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE__SHIFT 0x00000008
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD_MASK 0x00000001L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD__SHIFT 0x00000000
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT_MASK 0x00000002L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT__SHIFT 0x00000001
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID_MASK 0x00ff0000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID__SHIFT 0x00000010
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD_MASK 0x01000000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD__SHIFT 0x00000018
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE_MASK 0x04000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE__SHIFT 0x0000001a
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP_MASK 0x01000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP__SHIFT 0x00000018
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK_MASK 0x00800000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK__SHIFT 0x00000017
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK 0x00000001L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND__SHIFT 0x00000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN_MASK 0x00001000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN__SHIFT 0x0000000c
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE_MASK 0x00004000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE__SHIFT 0x0000000e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK_MASK 0x40000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK__SHIFT 0x0000001e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB_MASK 0x80000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB__SHIFT 0x0000001f
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS_MASK 0x00000800L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS__SHIFT 0x0000000b
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT_MASK 0x00000007L
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT__SHIFT 0x00000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A_MASK 0x00001000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A__SHIFT 0x0000000c
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B_MASK 0x00000c00L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B__SHIFT 0x0000000a
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C_MASK 0x00c00000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C__SHIFT 0x00000016
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC_MASK 0x70000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC__SHIFT 0x0000001c
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC_MASK 0x80000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC__SHIFT 0x0000001f
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M_MASK 0x00300000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M__SHIFT 0x00000014
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_PB1_RSVD_MASK 0x00008000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_PB1_RSVD__SHIFT 0x0000000f
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q_MASK 0x0c000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q__SHIFT 0x0000001a
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R_MASK 0x000f0000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R__SHIFT 0x00000010
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC_MASK 0x03000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC__SHIFT 0x00000018
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S_MASK 0x00000300L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S__SHIFT 0x00000008
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y_MASK 0x00006000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y__SHIFT 0x0000000d
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN_MASK 0x00003000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN__SHIFT 0x0000000c
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PB4_RSVD_MASK 0x00000080L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PB4_RSVD__SHIFT 0x00000007
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR_MASK 0x00000f00L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR__SHIFT 0x00000008
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP_MASK 0xffff0000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP__SHIFT 0x00000010
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC_MASK 0x0000007fL
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC__SHIFT 0x00000000
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ_MASK 0x0000c000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ__SHIFT 0x0000000e
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM_MASK 0x0000ffffL
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM__SHIFT 0x00000000
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT_MASK 0xffff0000L
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT__SHIFT 0x00000010
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT_MASK 0x0000ffffL
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT__SHIFT 0x00000000
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION_MASK 0xff000000L
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION__SHIFT 0x00000018
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0_MASK 0x000000ffL
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0__SHIFT 0x00000000
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1_MASK 0x0000ff00L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1__SHIFT 0x00000008
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2_MASK 0x00ff0000L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2__SHIFT 0x00000010
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3_MASK 0xff000000L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3__SHIFT 0x00000018
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4_MASK 0x000000ffL
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4__SHIFT 0x00000000
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5_MASK 0x0000ff00L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5__SHIFT 0x00000008
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6_MASK 0x00ff0000L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6__SHIFT 0x00000010
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7_MASK 0xff000000L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7__SHIFT 0x00000018
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10_MASK 0x00ff0000L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10__SHIFT 0x00000010
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11_MASK 0xff000000L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11__SHIFT 0x00000018
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8_MASK 0x000000ffL
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8__SHIFT 0x00000000
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9_MASK 0x0000ff00L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9__SHIFT 0x00000008
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12_MASK 0x000000ffL
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12__SHIFT 0x00000000
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13_MASK 0x0000ff00L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13__SHIFT 0x00000008
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14_MASK 0x00ff0000L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14__SHIFT 0x00000010
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15_MASK 0xff000000L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15__SHIFT 0x00000018
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16_MASK 0x000000ffL
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16__SHIFT 0x00000000
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17_MASK 0x0000ff00L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17__SHIFT 0x00000008
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18_MASK 0x00ff0000L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18__SHIFT 0x00000010
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19_MASK 0xff000000L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19__SHIFT 0x00000018
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20_MASK 0x000000ffL
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20__SHIFT 0x00000000
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21_MASK 0x0000ff00L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21__SHIFT 0x00000008
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22_MASK 0x00ff0000L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22__SHIFT 0x00000010
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23_MASK 0xff000000L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23__SHIFT 0x00000018
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24_MASK 0x000000ffL
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24__SHIFT 0x00000000
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25_MASK 0x0000ff00L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25__SHIFT 0x00000008
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26_MASK 0x00ff0000L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26__SHIFT 0x00000010
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27_MASK 0xff000000L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27__SHIFT 0x00000018
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28_MASK 0x000000ffL
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28__SHIFT 0x00000000
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29_MASK 0x0000ff00L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29__SHIFT 0x00000008
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30_MASK 0x00ff0000L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30__SHIFT 0x00000010
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31_MASK 0xff000000L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31__SHIFT 0x00000018
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0_MASK 0x000000ffL
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0__SHIFT 0x00000000
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1_MASK 0x0000ff00L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1__SHIFT 0x00000008
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2_MASK 0x00ff0000L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2__SHIFT 0x00000010
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3_MASK 0xff000000L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3__SHIFT 0x00000018
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE_MASK 0x00000040L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE__SHIFT 0x00000006
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE_MASK 0x00000080L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE__SHIFT 0x00000007
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE_MASK 0x00000400L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE__SHIFT 0x0000000a
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE_MASK 0x00000040L
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE__SHIFT 0x00000006
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS_MASK 0x00000007L
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS__SHIFT 0x00000000
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID_MASK 0x00000080L
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID__SHIFT 0x00000007
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0_MASK 0x000000ffL
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0__SHIFT 0x00000000
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1_MASK 0x0000ff00L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1__SHIFT 0x00000008
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2_MASK 0x00ff0000L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2__SHIFT 0x00000010
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3_MASK 0xff000000L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3__SHIFT 0x00000018
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4_MASK 0x000000ffL
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4__SHIFT 0x00000000
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5_MASK 0x0000ff00L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5__SHIFT 0x00000008
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6_MASK 0x00ff0000L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6__SHIFT 0x00000010
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7_MASK 0xff000000L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7__SHIFT 0x00000018
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10_MASK 0x00ff0000L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10__SHIFT 0x00000010
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11_MASK 0xff000000L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11__SHIFT 0x00000018
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8_MASK 0x000000ffL
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8__SHIFT 0x00000000
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9_MASK 0x0000ff00L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9__SHIFT 0x00000008
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12_MASK 0x000000ffL
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12__SHIFT 0x00000000
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13_MASK 0x0000ff00L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13__SHIFT 0x00000008
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14_MASK 0x00ff0000L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14__SHIFT 0x00000010
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15_MASK 0xff000000L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15__SHIFT 0x00000018
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16_MASK 0x000000ffL
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16__SHIFT 0x00000000
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17_MASK 0x0000ff00L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17__SHIFT 0x00000008
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18_MASK 0x00ff0000L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18__SHIFT 0x00000010
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19_MASK 0xff000000L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19__SHIFT 0x00000018
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20_MASK 0x000000ffL
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20__SHIFT 0x00000000
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21_MASK 0x0000ff00L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21__SHIFT 0x00000008
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22_MASK 0x00ff0000L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22__SHIFT 0x00000010
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23_MASK 0xff000000L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23__SHIFT 0x00000018
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24_MASK 0x000000ffL
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24__SHIFT 0x00000000
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25_MASK 0x0000ff00L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25__SHIFT 0x00000008
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26_MASK 0x00ff0000L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26__SHIFT 0x00000010
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27_MASK 0xff000000L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27__SHIFT 0x00000018
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28_MASK 0x000000ffL
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28__SHIFT 0x00000000
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29_MASK 0x0000ff00L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29__SHIFT 0x00000008
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30_MASK 0x00ff0000L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30__SHIFT 0x00000010
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31_MASK 0xff000000L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31__SHIFT 0x00000018
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0_MASK 0x0000ff00L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0__SHIFT 0x00000008
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1_MASK 0x00ff0000L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1__SHIFT 0x00000010
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2_MASK 0xff000000L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2__SHIFT 0x00000018
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR_MASK 0x00001000L
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR__SHIFT 0x0000000c
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3_MASK 0x000000ffL
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3__SHIFT 0x00000000
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF_MASK 0x00000300L
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF__SHIFT 0x00000008
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN_MASK 0x80000000L
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN__SHIFT 0x0000001f
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE_MASK 0xff000000L
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE__SHIFT 0x00000018
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT__SHIFT 0x00000000
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE_MASK 0x00000010L
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE__SHIFT 0x00000004
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW_MASK 0x01000000L
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW__SHIFT 0x00000018
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG_MASK 0x40000000L
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG__SHIFT 0x0000001e
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE_MASK 0x00000100L
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE__SHIFT 0x00000008
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE_MASK 0x00000004L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE__SHIFT 0x00000002
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE_MASK 0x00000008L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE__SHIFT 0x00000003
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX_MASK 0xc0000000L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX__SHIFT 0x0000001e
+#define ATTR00__ATTR_PAL_MASK 0x0000003fL
+#define ATTR00__ATTR_PAL__SHIFT 0x00000000
+#define ATTR01__ATTR_PAL_MASK 0x0000003fL
+#define ATTR01__ATTR_PAL__SHIFT 0x00000000
+#define ATTR02__ATTR_PAL_MASK 0x0000003fL
+#define ATTR02__ATTR_PAL__SHIFT 0x00000000
+#define ATTR03__ATTR_PAL_MASK 0x0000003fL
+#define ATTR03__ATTR_PAL__SHIFT 0x00000000
+#define ATTR04__ATTR_PAL_MASK 0x0000003fL
+#define ATTR04__ATTR_PAL__SHIFT 0x00000000
+#define ATTR05__ATTR_PAL_MASK 0x0000003fL
+#define ATTR05__ATTR_PAL__SHIFT 0x00000000
+#define ATTR06__ATTR_PAL_MASK 0x0000003fL
+#define ATTR06__ATTR_PAL__SHIFT 0x00000000
+#define ATTR07__ATTR_PAL_MASK 0x0000003fL
+#define ATTR07__ATTR_PAL__SHIFT 0x00000000
+#define ATTR08__ATTR_PAL_MASK 0x0000003fL
+#define ATTR08__ATTR_PAL__SHIFT 0x00000000
+#define ATTR09__ATTR_PAL_MASK 0x0000003fL
+#define ATTR09__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0A__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0A__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0B__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0B__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0C__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0C__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0D__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0D__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0E__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0E__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0F__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0F__ATTR_PAL__SHIFT 0x00000000
+#define ATTR10__ATTR_BLINK_EN_MASK 0x00000008L
+#define ATTR10__ATTR_BLINK_EN__SHIFT 0x00000003
+#define ATTR10__ATTR_CSEL_EN_MASK 0x00000080L
+#define ATTR10__ATTR_CSEL_EN__SHIFT 0x00000007
+#define ATTR10__ATTR_GRPH_MODE_MASK 0x00000001L
+#define ATTR10__ATTR_GRPH_MODE__SHIFT 0x00000000
+#define ATTR10__ATTR_LGRPH_EN_MASK 0x00000004L
+#define ATTR10__ATTR_LGRPH_EN__SHIFT 0x00000002
+#define ATTR10__ATTR_MONO_EN_MASK 0x00000002L
+#define ATTR10__ATTR_MONO_EN__SHIFT 0x00000001
+#define ATTR10__ATTR_PANTOPONLY_MASK 0x00000020L
+#define ATTR10__ATTR_PANTOPONLY__SHIFT 0x00000005
+#define ATTR10__ATTR_PCLKBY2_MASK 0x00000040L
+#define ATTR10__ATTR_PCLKBY2__SHIFT 0x00000006
+#define ATTR11__ATTR_OVSC_MASK 0x000000ffL
+#define ATTR11__ATTR_OVSC__SHIFT 0x00000000
+#define ATTR12__ATTR_MAP_EN_MASK 0x0000000fL
+#define ATTR12__ATTR_MAP_EN__SHIFT 0x00000000
+#define ATTR12__ATTR_VSMUX_MASK 0x00000030L
+#define ATTR12__ATTR_VSMUX__SHIFT 0x00000004
+#define ATTR13__ATTR_PPAN_MASK 0x0000000fL
+#define ATTR13__ATTR_PPAN__SHIFT 0x00000000
+#define ATTR14__ATTR_CSEL1_MASK 0x00000003L
+#define ATTR14__ATTR_CSEL1__SHIFT 0x00000000
+#define ATTR14__ATTR_CSEL2_MASK 0x0000000cL
+#define ATTR14__ATTR_CSEL2__SHIFT 0x00000002
+#define ATTRDR__ATTR_DATA_MASK 0x000000ffL
+#define ATTRDR__ATTR_DATA__SHIFT 0x00000000
+#define ATTRDW__ATTR_DATA_MASK 0x000000ffL
+#define ATTRDW__ATTR_DATA__SHIFT 0x00000000
+#define ATTRX__ATTR_IDX_MASK 0x0000001fL
+#define ATTRX__ATTR_IDX__SHIFT 0x00000000
+#define ATTRX__ATTR_PAL_RW_ENB_MASK 0x00000020L
+#define ATTRX__ATTR_PAL_RW_ENB__SHIFT 0x00000005
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY_MASK 0x00000003L
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY__SHIFT 0x00000000
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG_MASK 0x02000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG__SHIFT 0x00000019
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ_MASK 0x01000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ_MASK 0x01000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO_MASK 0x00000400L
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO__SHIFT 0x0000000a
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO_MASK 0x00000100L
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO__SHIFT 0x00000008
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS_MASK 0x0000000cL
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS__SHIFT 0x00000002
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG_MASK 0x00020000L
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG__SHIFT 0x00000011
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ_MASK 0x00010000L
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ__SHIFT 0x00000010
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ_MASK 0x00010000L
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ__SHIFT 0x00000010
+#define AUX_CONTROL__AUX_DEGLITCH_EN_MASK 0x20000000L
+#define AUX_CONTROL__AUX_DEGLITCH_EN__SHIFT 0x0000001d
+#define AUX_CONTROL__AUX_EN_MASK 0x00000001L
+#define AUX_CONTROL__AUX_EN__SHIFT 0x00000000
+#define AUX_CONTROL__AUX_HPD_SEL_MASK 0x00700000L
+#define AUX_CONTROL__AUX_HPD_SEL__SHIFT 0x00000014
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON_MASK 0x00010000L
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON__SHIFT 0x00000010
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN_MASK 0x01000000L
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN__SHIFT 0x00000018
+#define AUX_CONTROL__AUX_LS_READ_EN_MASK 0x00000100L
+#define AUX_CONTROL__AUX_LS_READ_EN__SHIFT 0x00000008
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE_MASK 0x00001000L
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE__SHIFT 0x0000000c
+#define AUX_CONTROL__AUX_MODE_DET_EN_MASK 0x00040000L
+#define AUX_CONTROL__AUX_MODE_DET_EN__SHIFT 0x00000012
+#define AUX_CONTROL__AUX_TEST_MODE_MASK 0x10000000L
+#define AUX_CONTROL__AUX_TEST_MODE__SHIFT 0x0000001c
+#define AUX_CONTROL__SPARE_0_MASK 0x40000000L
+#define AUX_CONTROL__SPARE_0__SHIFT 0x0000001e
+#define AUX_CONTROL__SPARE_1_MASK 0x80000000L
+#define AUX_CONTROL__SPARE_1__SHIFT 0x0000001f
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT_MASK 0x00020000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT__SHIFT 0x00000011
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START_MASK 0x00040000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START__SHIFT 0x00000012
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP_MASK 0x00080000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP__SHIFT 0x00000013
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD_MASK 0x70000000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD__SHIFT 0x0000001c
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN_MASK 0x00003000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN__SHIFT 0x0000000c
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN_MASK 0x00300000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN__SHIFT 0x00000014
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW_MASK 0x00000700L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW__SHIFT 0x00000008
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW_MASK 0x00000070L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW__SHIFT 0x00000004
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN_MASK 0x07000000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN__SHIFT 0x00000018
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN_MASK 0x00010000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN__SHIFT 0x00000010
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP_MASK 0x000000ffL
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP__SHIFT 0x00000000
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT_MASK 0x001f0000L
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT__SHIFT 0x00000010
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_MASK 0x3fe00000L
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD__SHIFT 0x00000015
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE_MASK 0x00000007L
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE__SHIFT 0x00000000
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT_MASK 0x00001f00L
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT__SHIFT 0x00000008
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN_MASK 0x00000007L
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN__SHIFT 0x00000000
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS_MASK 0x00003f00L
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS__SHIFT 0x00000008
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE_MASK 0x00000030L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE__SHIFT 0x00000004
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV_MASK 0x01ff0000L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV__SHIFT 0x00000010
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL_MASK 0x00000001L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL__SHIFT 0x00000000
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE_MASK 0x00000001L
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE__SHIFT 0x00000000
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD_MASK 0x01ff0000L
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD__SHIFT 0x00000010
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE_MASK 0x00000070L
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE__SHIFT 0x00000004
+#define AUX_GTC_SYNC_CONTROL__AUX_GTC_SYNC_EN_MASK 0x00000001L
+#define AUX_GTC_SYNC_CONTROL__AUX_GTC_SYNC_EN__SHIFT 0x00000000
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK_MASK 0x00000020L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK__SHIFT 0x00000005
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT_MASK 0x00000010L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT__SHIFT 0x00000004
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK_MASK 0x00000040L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK__SHIFT 0x00000006
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK_MASK 0x00000002L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK__SHIFT 0x00000001
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT_MASK 0x00000001L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT__SHIFT 0x00000000
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK_MASK 0x00000004L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK__SHIFT 0x00000002
+#define AUX_LS_DATA__AUX_LS_DATA_MASK 0x0000ff00L
+#define AUX_LS_DATA__AUX_LS_DATA__SHIFT 0x00000008
+#define AUX_LS_DATA__AUX_LS_INDEX_MASK 0x001f0000L
+#define AUX_LS_DATA__AUX_LS_INDEX__SHIFT 0x00000010
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ_MASK 0x20000000L
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ__SHIFT 0x0000001d
+#define AUX_LS_STATUS__AUX_LS_DONE_MASK 0x00000001L
+#define AUX_LS_STATUS__AUX_LS_DONE__SHIFT 0x00000000
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON_MASK 0x00000200L
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON__SHIFT 0x00000009
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE_MASK 0x00000800L
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE__SHIFT 0x0000000b
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT_MASK 0x1f000000L
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT__SHIFT 0x00000018
+#define AUX_LS_STATUS__AUX_LS_REQ_MASK 0x00000002L
+#define AUX_LS_STATUS__AUX_LS_REQ__SHIFT 0x00000001
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START_MASK 0x00080000L
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START__SHIFT 0x00000013
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP_MASK 0x00004000L
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP__SHIFT 0x0000000e
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL_MASK 0x00001000L
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL__SHIFT 0x0000000c
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW_MASK 0x00000100L
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW__SHIFT 0x00000008
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE_MASK 0x00000400L
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE__SHIFT 0x0000000a
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H_MASK 0x00400000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H__SHIFT 0x00000016
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L_MASK 0x00800000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L__SHIFT 0x00000017
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET_MASK 0x00100000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET__SHIFT 0x00000014
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H_MASK 0x00040000L
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H__SHIFT 0x00000012
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L_MASK 0x00020000L
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L__SHIFT 0x00000011
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_MASK 0x00000080L
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT__SHIFT 0x00000007
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE_MASK 0x00000070L
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE__SHIFT 0x00000004
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK_MASK 0x80000000L
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK__SHIFT 0x0000001f
+#define AUX_LS_STATUS__AUX_LS_UPDATED_MASK 0x40000000L
+#define AUX_LS_STATUS__AUX_LS_UPDATED__SHIFT 0x0000001e
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK_MASK 0x00000400L
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK__SHIFT 0x0000000a
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_MASK 0x00000200L
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR__SHIFT 0x00000009
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT_MASK 0x00000100L
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT__SHIFT 0x00000008
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE_MASK 0x00000001L
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE__SHIFT 0x00000000
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x0000001c
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_MASK 0x0f000000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE__SHIFT 0x00000018
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY_MASK 0x00f00000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY__SHIFT 0x00000014
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE_MASK 0x000f0000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE__SHIFT 0x00000010
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK_MASK 0x00000400L
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK__SHIFT 0x0000000a
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_MASK 0x00000200L
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR__SHIFT 0x00000009
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT_MASK 0x00000100L
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT__SHIFT 0x00000008
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE_MASK 0x00000001L
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE__SHIFT 0x00000000
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x0000001c
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_MASK 0x0f000000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE__SHIFT 0x00000018
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY_MASK 0x00f00000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY__SHIFT 0x00000014
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE_MASK 0x000f0000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE__SHIFT 0x00000010
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG_MASK 0x00000004L
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG__SHIFT 0x00000002
+#define AUX_SW_CONTROL__AUX_SW_GO_MASK 0x00000001L
+#define AUX_SW_CONTROL__AUX_SW_GO__SHIFT 0x00000000
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY_MASK 0x000000f0L
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY__SHIFT 0x00000004
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES_MASK 0x001f0000L
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES__SHIFT 0x00000010
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE_MASK 0x80000000L
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE__SHIFT 0x0000001f
+#define AUX_SW_DATA__AUX_SW_DATA_MASK 0x0000ff00L
+#define AUX_SW_DATA__AUX_SW_DATA_RW_MASK 0x00000001L
+#define AUX_SW_DATA__AUX_SW_DATA_RW__SHIFT 0x00000000
+#define AUX_SW_DATA__AUX_SW_DATA__SHIFT 0x00000008
+#define AUX_SW_DATA__AUX_SW_INDEX_MASK 0x001f0000L
+#define AUX_SW_DATA__AUX_SW_INDEX__SHIFT 0x00000010
+#define AUX_SW_STATUS__AUX_ARB_STATUS_MASK 0xc0000000L
+#define AUX_SW_STATUS__AUX_ARB_STATUS__SHIFT 0x0000001e
+#define AUX_SW_STATUS__AUX_SW_DONE_MASK 0x00000001L
+#define AUX_SW_STATUS__AUX_SW_DONE__SHIFT 0x00000000
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK 0x00000200L
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON__SHIFT 0x00000009
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE_MASK 0x00000800L
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE__SHIFT 0x0000000b
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT_MASK 0x1f000000L
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT__SHIFT 0x00000018
+#define AUX_SW_STATUS__AUX_SW_REQ_MASK 0x00000002L
+#define AUX_SW_STATUS__AUX_SW_REQ__SHIFT 0x00000001
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START_MASK 0x00080000L
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START__SHIFT 0x00000013
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK 0x00004000L
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP__SHIFT 0x0000000e
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL_MASK 0x00001000L
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL__SHIFT 0x0000000c
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW_MASK 0x00000100L
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW__SHIFT 0x00000008
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE_MASK 0x00000400L
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE__SHIFT 0x0000000a
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK 0x00400000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H__SHIFT 0x00000016
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK 0x00800000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L__SHIFT 0x00000017
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK 0x00100000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET__SHIFT 0x00000014
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H_MASK 0x00040000L
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H__SHIFT 0x00000012
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L_MASK 0x00020000L
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L__SHIFT 0x00000011
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK 0x00000080L
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT__SHIFT 0x00000007
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK 0x00000070L
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE__SHIFT 0x00000004
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER_MASK 0xffffffffL
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER__SHIFT 0x00000000
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE_MASK 0xffff0000L
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE__SHIFT 0x00000010
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE_MASK 0x0000ffffL
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE__SHIFT 0x00000000
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO_MASK 0x00000300L
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO__SHIFT 0x00000008
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS_MASK 0x00000030L
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP_MASK 0x00000003L
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG_MASK 0xffffffffL
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG__SHIFT 0x00000000
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS_MASK 0x00000010L
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP_MASK 0x00000001L
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT_MASK 0xffffffffL
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT__SHIFT 0x00000000
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT_MASK 0xffffffffL
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT__SHIFT 0x00000000
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE_MASK 0x00000001L
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE__SHIFT 0x00000000
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD_MASK 0x00010000L
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD__SHIFT 0x00000010
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL_MASK 0x00020000L
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL__SHIFT 0x00000011
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS_MASK 0x00000030L
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP_MASK 0x00000003L
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT_MASK 0x00000070L
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT_MASK 0x00000007L
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x00000070L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x00000700L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x00003800L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x00004000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0x0000000e
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x00008000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0x0000000f
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x00007f00L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x00000010L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x00800000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x00000017
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x00000080L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x00000020L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x00000040L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x00000004L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x00000002L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PIN_DEBUG__AZALIA_DEBUG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x00700000L
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x00000003L
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x00000200L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x00000400L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x00000001L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x0000001e
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT_MASK 0x80000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO_MASK 0x00fc0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO__SHIFT 0x00000012
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT_MASK 0x78000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT__SHIFT 0x0000001b
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION_MASK 0x0000007fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED_MASK 0x80000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE_MASK 0x02000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE__SHIFT 0x00000019
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0xf0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE_MASK 0x02000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x00000019
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0x00000f00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x0000001e
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID_MASK 0x0000ffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID_MASK 0xffff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE_MASK 0x10000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD_MASK 0x03ffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x00000004L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x00000003L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x0000003cL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x00000002
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x00000003L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x00000004L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x00000002
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x00000078L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x00000080L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x00000007
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x00000003
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x0000003fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000040L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000006
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000010L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x00000060L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x00000005
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x00000080L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x00000007
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x00000010L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x00000070L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x00000700L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x00003800L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x00004000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0x0000000e
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x00008000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R_MASK 0x00008000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R__SHIFT 0x0000000f
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0x0000000f
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC_MASK 0x0000007fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x00007f00L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x00000010L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x00000001L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x00800000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x00000017
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x00000020L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x00000040L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x00000004L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x00000002L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x00700000L
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x00000003L
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x00000200L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x00000400L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x00000001L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0x00ff0000L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x0000001e
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x0000001f
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE_MASK 0x00000078L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT_MASK 0x00000078L
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID_MASK 0x0000ffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID_MASK 0x0000ffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY_MASK 0x000000c0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0x0000f000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0x0000000c
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0x00000f00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x0000001e
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT_MASK 0x80000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT__SHIFT 0x0000001f
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION_MASK 0x00000200L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO_MASK 0x0000fc00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION_MASK 0x00000100L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION_MASK 0x0000007fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x01000000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x00010000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x00000004L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x00000003L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x0000003cL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x00000002
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x00000003L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x00000004L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x00000002
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x00000078L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x00000080L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x00000007
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x00000003
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x0000003fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000040L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000006
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000010L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x00000060L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x00000005
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x00000080L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x00000007
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x00000010L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000004
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE_MASK 0x00007f00L
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE__SHIFT 0x00000008
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT_MASK 0x00ff0000L
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT__SHIFT 0x00000010
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE_MASK 0x0000007fL
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE__SHIFT 0x00000000
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS_MASK 0x00000006L
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS__SHIFT 0x00000001
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET_MASK 0x00000001L
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET__SHIFT 0x00000000
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY_MASK 0x0000ffffL
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY__SHIFT 0x00000000
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY_MASK 0xffff0000L
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY__SHIFT 0x00000010
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL_MASK 0x000000ffL
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL__SHIFT 0x00000000
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE_MASK 0x00000100L
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE__SHIFT 0x00000008
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP_MASK 0x00000010L
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP__SHIFT 0x00000004
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP_MASK 0x00000001L
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL_MASK 0x00000030L
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL__SHIFT 0x00000004
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA_MASK 0xffffffffL
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA__SHIFT 0x00000000
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA_MASK 0xffffffffL
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA__SHIFT 0x00000000
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX_MASK 0x000000ffL
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX__SHIFT 0x00000000
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN_MASK 0x00000100L
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN__SHIFT 0x00000008
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE_MASK 0xffffffffL
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE__SHIFT 0x00000000
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT_MASK 0xffffffffL
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN_MASK 0x00000008L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN__SHIFT 0x00000003
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN_MASK 0x00000004L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN__SHIFT 0x00000002
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE_MASK 0xffff0000L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE__SHIFT 0x00000010
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN_MASK 0x00000001L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN__SHIFT 0x00000000
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN_MASK 0x00000002L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN__SHIFT 0x00000001
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE_MASK 0x0001ffffL
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE__SHIFT 0x00000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL_MASK 0x000e0000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL__SHIFT 0x00000011
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN_MASK 0x80000000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001f
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN_MASK 0x01000000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000018
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK_MASK 0x00000001L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK__SHIFT 0x00000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING_MASK 0x00000100L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING__SHIFT 0x00000008
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START_MASK 0x00010000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START__SHIFT 0x00000010
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE_MASK 0x0001ffffL
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE__SHIFT 0x00000000
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL__SHIFT 0x00000000
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE_MASK 0x40000000L
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE__SHIFT 0x0000001e
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN_MASK 0x80000000L
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN__SHIFT 0x0000001f
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE_MASK 0x0000ffffL
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE__SHIFT 0x00000000
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT_MASK 0x30000000L
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT__SHIFT 0x0000001c
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT_MASK 0x0000ffffL
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT__SHIFT 0x00000000
+#define BL_PWM_CNTL__BL_PWM_EN_MASK 0x80000000L
+#define BL_PWM_CNTL__BL_PWM_EN__SHIFT 0x0000001f
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN_MASK 0x40000000L
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN__SHIFT 0x0000001e
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL_MASK 0x000e0000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL__SHIFT 0x00000011
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN_MASK 0x80000000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001f
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN_MASK 0x01000000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000018
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK_MASK 0x00000001L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK__SHIFT 0x00000000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING_MASK 0x00000100L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING__SHIFT 0x00000008
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START_MASK 0x00010000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START__SHIFT 0x00000010
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT_MASK 0x000f0000L
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT__SHIFT 0x00000010
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_MASK 0x0000ffffL
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD__SHIFT 0x00000000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE_MASK 0x10000000L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE__SHIFT 0x0000001c
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN_MASK 0x00000004L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN__SHIFT 0x00000002
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN_MASK 0x00000002L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN__SHIFT 0x00000001
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB_MASK 0x00000001L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB__SHIFT 0x00000000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK_MASK 0x00700000L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK__SHIFT 0x00000014
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST_MASK 0x00003ff0L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST__SHIFT 0x00000004
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR_MASK 0x0f000000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR__SHIFT 0x00000018
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT_MASK 0x003f0000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT__SHIFT 0x00000010
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON_MASK 0x10000000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON__SHIFT 0x0000001c
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL_MASK 0x00003f00L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL__SHIFT 0x00000008
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL_MASK 0x00000003L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL__SHIFT 0x00000000
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS_MASK 0x0000007eL
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS__SHIFT 0x00000001
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_MASK 0x00000007L
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE_MASK 0x00000010L
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE__SHIFT 0x00000004
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34__SHIFT 0x00000010
+#define CRT00__H_TOTAL_MASK 0x000000ffL
+#define CRT00__H_TOTAL__SHIFT 0x00000000
+#define CRT01__H_DISP_END_MASK 0x000000ffL
+#define CRT01__H_DISP_END__SHIFT 0x00000000
+#define CRT02__H_BLANK_START_MASK 0x000000ffL
+#define CRT02__H_BLANK_START__SHIFT 0x00000000
+#define CRT03__CR10CR11_R_DIS_B_MASK 0x00000080L
+#define CRT03__CR10CR11_R_DIS_B__SHIFT 0x00000007
+#define CRT03__H_BLANK_END_MASK 0x0000001fL
+#define CRT03__H_BLANK_END__SHIFT 0x00000000
+#define CRT03__H_DE_SKEW_MASK 0x00000060L
+#define CRT03__H_DE_SKEW__SHIFT 0x00000005
+#define CRT04__H_SYNC_START_MASK 0x000000ffL
+#define CRT04__H_SYNC_START__SHIFT 0x00000000
+#define CRT05__H_BLANK_END_B5_MASK 0x00000080L
+#define CRT05__H_BLANK_END_B5__SHIFT 0x00000007
+#define CRT05__H_SYNC_END_MASK 0x0000001fL
+#define CRT05__H_SYNC_END__SHIFT 0x00000000
+#define CRT05__H_SYNC_SKEW_MASK 0x00000060L
+#define CRT05__H_SYNC_SKEW__SHIFT 0x00000005
+#define CRT06__V_TOTAL_MASK 0x000000ffL
+#define CRT06__V_TOTAL__SHIFT 0x00000000
+#define CRT07__LINE_CMP_B8_MASK 0x00000010L
+#define CRT07__LINE_CMP_B8__SHIFT 0x00000004
+#define CRT07__V_BLANK_START_B8_MASK 0x00000008L
+#define CRT07__V_BLANK_START_B8__SHIFT 0x00000003
+#define CRT07__V_DISP_END_B8_MASK 0x00000002L
+#define CRT07__V_DISP_END_B8__SHIFT 0x00000001
+#define CRT07__V_DISP_END_B9_MASK 0x00000040L
+#define CRT07__V_DISP_END_B9__SHIFT 0x00000006
+#define CRT07__V_SYNC_START_B8_MASK 0x00000004L
+#define CRT07__V_SYNC_START_B8__SHIFT 0x00000002
+#define CRT07__V_SYNC_START_B9_MASK 0x00000080L
+#define CRT07__V_SYNC_START_B9__SHIFT 0x00000007
+#define CRT07__V_TOTAL_B8_MASK 0x00000001L
+#define CRT07__V_TOTAL_B8__SHIFT 0x00000000
+#define CRT07__V_TOTAL_B9_MASK 0x00000020L
+#define CRT07__V_TOTAL_B9__SHIFT 0x00000005
+#define CRT08__BYTE_PAN_MASK 0x00000060L
+#define CRT08__BYTE_PAN__SHIFT 0x00000005
+#define CRT08__ROW_SCAN_START_MASK 0x0000001fL
+#define CRT08__ROW_SCAN_START__SHIFT 0x00000000
+#define CRT09__DOUBLE_CHAR_HEIGHT_MASK 0x00000080L
+#define CRT09__DOUBLE_CHAR_HEIGHT__SHIFT 0x00000007
+#define CRT09__LINE_CMP_B9_MASK 0x00000040L
+#define CRT09__LINE_CMP_B9__SHIFT 0x00000006
+#define CRT09__MAX_ROW_SCAN_MASK 0x0000001fL
+#define CRT09__MAX_ROW_SCAN__SHIFT 0x00000000
+#define CRT09__V_BLANK_START_B9_MASK 0x00000020L
+#define CRT09__V_BLANK_START_B9__SHIFT 0x00000005
+#define CRT0A__CURSOR_DISABLE_MASK 0x00000020L
+#define CRT0A__CURSOR_DISABLE__SHIFT 0x00000005
+#define CRT0A__CURSOR_START_MASK 0x0000001fL
+#define CRT0A__CURSOR_START__SHIFT 0x00000000
+#define CRT0B__CURSOR_END_MASK 0x0000001fL
+#define CRT0B__CURSOR_END__SHIFT 0x00000000
+#define CRT0B__CURSOR_SKEW_MASK 0x00000060L
+#define CRT0B__CURSOR_SKEW__SHIFT 0x00000005
+#define CRT0C__DISP_START_MASK 0x000000ffL
+#define CRT0C__DISP_START__SHIFT 0x00000000
+#define CRT0D__DISP_START_MASK 0x000000ffL
+#define CRT0D__DISP_START__SHIFT 0x00000000
+#define CRT0E__CURSOR_LOC_HI_MASK 0x000000ffL
+#define CRT0E__CURSOR_LOC_HI__SHIFT 0x00000000
+#define CRT0F__CURSOR_LOC_LO_MASK 0x000000ffL
+#define CRT0F__CURSOR_LOC_LO__SHIFT 0x00000000
+#define CRT10__V_SYNC_START_MASK 0x000000ffL
+#define CRT10__V_SYNC_START__SHIFT 0x00000000
+#define CRT11__C0T7_WR_ONLY_MASK 0x00000080L
+#define CRT11__C0T7_WR_ONLY__SHIFT 0x00000007
+#define CRT11__SEL5_REFRESH_CYC_MASK 0x00000040L
+#define CRT11__SEL5_REFRESH_CYC__SHIFT 0x00000006
+#define CRT11__V_INTR_CLR_MASK 0x00000010L
+#define CRT11__V_INTR_CLR__SHIFT 0x00000004
+#define CRT11__V_INTR_EN_MASK 0x00000020L
+#define CRT11__V_INTR_EN__SHIFT 0x00000005
+#define CRT11__V_SYNC_END_MASK 0x0000000fL
+#define CRT11__V_SYNC_END__SHIFT 0x00000000
+#define CRT12__V_DISP_END_MASK 0x000000ffL
+#define CRT12__V_DISP_END__SHIFT 0x00000000
+#define CRT13__DISP_PITCH_MASK 0x000000ffL
+#define CRT13__DISP_PITCH__SHIFT 0x00000000
+#define CRT14__ADDR_CNT_BY4_MASK 0x00000020L
+#define CRT14__ADDR_CNT_BY4__SHIFT 0x00000005
+#define CRT14__DOUBLE_WORD_MASK 0x00000040L
+#define CRT14__DOUBLE_WORD__SHIFT 0x00000006
+#define CRT14__UNDRLN_LOC_MASK 0x0000001fL
+#define CRT14__UNDRLN_LOC__SHIFT 0x00000000
+#define CRT15__V_BLANK_START_MASK 0x000000ffL
+#define CRT15__V_BLANK_START__SHIFT 0x00000000
+#define CRT16__V_BLANK_END_MASK 0x000000ffL
+#define CRT16__V_BLANK_END__SHIFT 0x00000000
+#define CRT17__ADDR_CNT_BY2_MASK 0x00000008L
+#define CRT17__ADDR_CNT_BY2__SHIFT 0x00000003
+#define CRT17__BYTE_MODE_MASK 0x00000040L
+#define CRT17__BYTE_MODE__SHIFT 0x00000006
+#define CRT17__CRTC_SYNC_EN_MASK 0x00000080L
+#define CRT17__CRTC_SYNC_EN__SHIFT 0x00000007
+#define CRT17__RA0_AS_A13B_MASK 0x00000001L
+#define CRT17__RA0_AS_A13B__SHIFT 0x00000000
+#define CRT17__RA1_AS_A14B_MASK 0x00000002L
+#define CRT17__RA1_AS_A14B__SHIFT 0x00000001
+#define CRT17__VCOUNT_BY2_MASK 0x00000004L
+#define CRT17__VCOUNT_BY2__SHIFT 0x00000002
+#define CRT17__WRAP_A15TOA0_MASK 0x00000020L
+#define CRT17__WRAP_A15TOA0__SHIFT 0x00000005
+#define CRT18__LINE_CMP_MASK 0x000000ffL
+#define CRT18__LINE_CMP__SHIFT 0x00000000
+#define CRT1E__GRPH_DEC_RD1_MASK 0x00000002L
+#define CRT1E__GRPH_DEC_RD1__SHIFT 0x00000001
+#define CRT1F__GRPH_DEC_RD0_MASK 0x000000ffL
+#define CRT1F__GRPH_DEC_RD0__SHIFT 0x00000000
+#define CRT22__GRPH_LATCH_DATA_MASK 0x000000ffL
+#define CRT22__GRPH_LATCH_DATA__SHIFT 0x00000000
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL_MASK 0x00000100L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL_MASK 0x00000200L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE_MASK 0x00000010L
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE__SHIFT 0x00000004
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL_MASK 0x00000100L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL_MASK 0x00000200L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE_MASK 0x00000010L
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE__SHIFT 0x00000004
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL_MASK 0x00000100L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL_MASK 0x00000200L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE_MASK 0x00000010L
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE__SHIFT 0x00000004
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB_MASK 0x00000010L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB__SHIFT 0x00000004
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_MASK 0x00000001L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN__SHIFT 0x00000000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_MASK 0x000c0000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_MASK 0x00010000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING_MASK 0x00020000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING__SHIFT 0x00000011
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET__SHIFT 0x00000010
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT__SHIFT 0x00000012
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR_MASK 0x00001000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR__SHIFT 0x0000000c
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE_MASK 0x00000300L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE__SHIFT 0x00000008
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL_MASK 0x00000100L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL_MASK 0x00000200L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE_MASK 0x00000010L
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE__SHIFT 0x00000004
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL_MASK 0x00000100L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL_MASK 0x00000200L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE_MASK 0x00000010L
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE__SHIFT 0x00000004
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL_MASK 0x00000100L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL_MASK 0x00000200L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE_MASK 0x00000010L
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE__SHIFT 0x00000004
+#define CRTC8_DATA__VCRTC_DATA_MASK 0x000000ffL
+#define CRTC8_DATA__VCRTC_DATA__SHIFT 0x00000000
+#define CRTC8_IDX__VCRTC_IDX_MASK 0x0000003fL
+#define CRTC8_IDX__VCRTC_IDX__SHIFT 0x00000000
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT_MASK 0x000000ffL
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT__SHIFT 0x00000000
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT_MASK 0x00010000L
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT__SHIFT 0x00000010
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB_MASK 0x000003ffL
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB__SHIFT 0x00000000
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y_MASK 0x000ffc00L
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y__SHIFT 0x0000000a
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR_MASK 0x3ff00000L
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR__SHIFT 0x00000014
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK 0x00000100L
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN__SHIFT 0x00000008
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE_MASK 0x00010000L
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE__SHIFT 0x00000010
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE_MASK 0x00000001L
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE__SHIFT 0x00000000
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB_MASK 0x000003ffL
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB__SHIFT 0x00000000
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y_MASK 0x000ffc00L
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y__SHIFT 0x0000000a
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR_MASK 0x3ff00000L
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR__SHIFT 0x00000014
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE_MASK 0x00010000L
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE__SHIFT 0x00000010
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL_MASK 0x00000300L
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL__SHIFT 0x00000008
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE_MASK 0x01000000L
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE__SHIFT 0x00000018
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL_MASK 0x00002000L
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL__SHIFT 0x0000000d
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL_MASK 0x00700000L
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL__SHIFT 0x00000014
+#define CRTC_CONTROL__CRTC_MASTER_EN_MASK 0x00000001L
+#define CRTC_CONTROL__CRTC_MASTER_EN__SHIFT 0x00000000
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN_MASK 0x20000000L
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN__SHIFT 0x0000001d
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL_MASK 0x00001000L
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL__SHIFT 0x0000000c
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL_MASK 0x00000010L
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL__SHIFT 0x00000004
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN_MASK 0x00000001L
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN__SHIFT 0x00000000
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT_MASK 0x0000001eL
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT__SHIFT 0x00000001
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT_MASK 0x00000001L
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE_MASK 0x80000000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE__SHIFT 0x0000001f
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_TEST_CLK_SEL_MASK 0x1f000000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_TEST_CLK_SEL__SHIFT 0x00000018
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_DCP_GATE_DISABLE_MASK 0x00000100L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_DCP_GATE_DISABLE__SHIFT 0x00000008
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_SCL_GATE_DISABLE_MASK 0x00001000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_SCL_GATE_DISABLE__SHIFT 0x0000000c
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_R_DCFE_GATE_DISABLE_MASK 0x00000010L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_R_DCFE_GATE_DISABLE__SHIFT 0x00000004
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN_MASK 0x00010000L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN__SHIFT 0x00000010
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY_MASK 0x00000100L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY__SHIFT 0x00000008
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING_MASK 0x00000001L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING__SHIFT 0x00000000
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV_MASK 0x0000001eL
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV__SHIFT 0x00000001
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN_MASK 0x00000001L
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN__SHIFT 0x00000000
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY_MASK 0x00010000L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY__SHIFT 0x00000010
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS_MASK 0x01000000L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS__SHIFT 0x00000018
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY_MASK 0x00000100L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY__SHIFT 0x00000008
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK_MASK 0x00000010L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK__SHIFT 0x00000004
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR_MASK 0x01000000L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR__SHIFT 0x00000018
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE_MASK 0x00000003L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE__SHIFT 0x00000000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED_MASK 0x00010000L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED__SHIFT 0x00000010
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL_MASK 0x00000100L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL__SHIFT 0x00000008
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS_MASK 0x10000000L
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS__SHIFT 0x0000001c
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM_MASK 0x00001fffL
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM__SHIFT 0x00000000
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY_MASK 0x001f0000L
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY__SHIFT 0x00000010
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR_MASK 0x00080000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR__SHIFT 0x00000013
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY_MASK 0x0000ff00L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY__SHIFT 0x00000008
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT_MASK 0x000000ffL
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT__SHIFT 0x00000000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASK 0xff000000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER_MASK 0x00800000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER__SHIFT 0x00000017
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE_MASK 0x00060000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE__SHIFT 0x00000011
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED_MASK 0x00100000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED__SHIFT 0x00000014
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP__SHIFT 0x00000018
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL_MASK 0x00010000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL__SHIFT 0x00000010
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END_MASK 0x1fff0000L
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END__SHIFT 0x00000010
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START_MASK 0x00001fffL
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START__SHIFT 0x00000000
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS_MASK 0x00010000L
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS__SHIFT 0x00000010
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_MASK 0x000003ffL
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM__SHIFT 0x00000000
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END_MASK 0x1fff0000L
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END__SHIFT 0x00000010
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START_MASK 0x00001fffL
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START__SHIFT 0x00000000
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN_MASK 0x00010000L
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN__SHIFT 0x00000010
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF_MASK 0x00020000L
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF__SHIFT 0x00000011
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL_MASK 0x00000001L
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL__SHIFT 0x00000000
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END_MASK 0x1fff0000L
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END__SHIFT 0x00000010
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START_MASK 0x00001fffL
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START__SHIFT 0x00000000
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN_MASK 0x00010000L
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN__SHIFT 0x00000010
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF_MASK 0x00020000L
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF__SHIFT 0x00000011
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL_MASK 0x00000001L
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL__SHIFT 0x00000000
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END_MASK 0x1fff0000L
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END__SHIFT 0x00000010
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START_MASK 0x00001fffL
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START__SHIFT 0x00000000
+#define CRTC_H_TOTAL__CRTC_H_TOTAL_MASK 0x00001fffL
+#define CRTC_H_TOTAL__CRTC_H_TOTAL__SHIFT 0x00000000
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE_MASK 0x00000001L
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE__SHIFT 0x00000000
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD_MASK 0x00030000L
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD__SHIFT 0x00000010
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD_MASK 0x00000001L
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD__SHIFT 0x00000000
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD_MASK 0x00000002L
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD__SHIFT 0x00000001
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK_MASK 0x00000100L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK__SHIFT 0x00000008
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE_MASK 0x00000200L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE__SHIFT 0x00000009
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK_MASK 0x00010000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK__SHIFT 0x00000010
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE_MASK 0x00020000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE__SHIFT 0x00000011
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK_MASK 0x40000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK__SHIFT 0x0000001e
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE_MASK 0x80000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE__SHIFT 0x0000001f
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK_MASK 0x00000001L
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK__SHIFT 0x00000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE_MASK 0x00000002L
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE__SHIFT 0x00000001
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK_MASK 0x01000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK__SHIFT 0x00000018
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE_MASK 0x04000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE__SHIFT 0x0000001a
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK_MASK 0x02000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK__SHIFT 0x00000019
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE_MASK 0x08000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE__SHIFT 0x0000001b
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK_MASK 0x10000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK__SHIFT 0x0000001c
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE_MASK 0x20000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE__SHIFT 0x0000001d
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK 0x00000010L
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK__SHIFT 0x00000004
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE_MASK 0x00000020L
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE__SHIFT 0x00000005
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_MASK 0x00000001L
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SHIFT 0x00000000
+#define CRTC_MASTER_EN__CRTC_MASTER_EN_MASK 0x00000001L
+#define CRTC_MASTER_EN__CRTC_MASTER_EN__SHIFT 0x00000000
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_MASK 0xffffff00L
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT__SHIFT 0x00000008
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE_MASK 0x00000003L
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE__SHIFT 0x00000000
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER_MASK 0x000000ffL
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER__SHIFT 0x00000000
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR_MASK 0x00100000L
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR__SHIFT 0x00000014
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED_MASK 0x00000010L
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED__SHIFT 0x00000004
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR_MASK 0x00010000L
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR__SHIFT 0x00000010
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED_MASK 0x00000001L
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED__SHIFT 0x00000000
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM_MASK 0x00001fffL
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM__SHIFT 0x00000000
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE_MASK 0x000003ffL
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE__SHIFT 0x00000000
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN_MASK 0x000ffc00L
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN__SHIFT 0x0000000a
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED_MASK 0x3ff00000L
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED__SHIFT 0x00000014
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL_MASK 0x00000003L
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT_MASK 0x00ffffffL
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR_MASK 0x00000002L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR__SHIFT 0x00000001
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER_MASK 0x00000004L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER__SHIFT 0x00000002
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED_MASK 0x00000001L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED__SHIFT 0x00000000
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION_MASK 0x000f0000L
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION__SHIFT 0x00000010
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY_MASK 0x00000100L
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY__SHIFT 0x00000008
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY_MASK 0x00000001L
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY__SHIFT 0x00000000
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP_MASK 0x00020000L
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP__SHIFT 0x00000011
+#define CRTC_STATUS__CRTC_H_BLANK_MASK 0x00010000L
+#define CRTC_STATUS__CRTC_H_BLANK__SHIFT 0x00000010
+#define CRTC_STATUS__CRTC_H_SYNC_A_MASK 0x00040000L
+#define CRTC_STATUS__CRTC_H_SYNC_A__SHIFT 0x00000012
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP_MASK 0x00000002L
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP__SHIFT 0x00000001
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE_MASK 0x00000020L
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE__SHIFT 0x00000005
+#define CRTC_STATUS__CRTC_V_BLANK_MASK 0x00000001L
+#define CRTC_STATUS__CRTC_V_BLANK__SHIFT 0x00000000
+#define CRTC_STATUS__CRTC_V_START_LINE_MASK 0x00000010L
+#define CRTC_STATUS__CRTC_V_START_LINE__SHIFT 0x00000004
+#define CRTC_STATUS__CRTC_V_SYNC_A_MASK 0x00000004L
+#define CRTC_STATUS__CRTC_V_SYNC_A__SHIFT 0x00000002
+#define CRTC_STATUS__CRTC_V_UPDATE_MASK 0x00000008L
+#define CRTC_STATUS__CRTC_V_UPDATE__SHIFT 0x00000003
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT_MASK 0x00ffffffL
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT_MASK 0x1fffffffL
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT_MASK 0x1fffffffL
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT__SHIFT 0x00000000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN_MASK 0x01000000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN__SHIFT 0x00000018
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM_MASK 0x00001fffL
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM__SHIFT 0x00000000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY_MASK 0x00008000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY__SHIFT 0x0000000f
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY_MASK 0x00010000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY__SHIFT 0x00000010
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE_MASK 0x00000003L
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE__SHIFT 0x00000000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE_MASK 0x00000001L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE__SHIFT 0x00000000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING_MASK 0x03000000L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING__SHIFT 0x00000018
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT_MASK 0x00000100L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT__SHIFT 0x00000008
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT_MASK 0x00010000L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT__SHIFT 0x00000010
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA_MASK 0x0000ffffL
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK_MASK 0x003f0000L
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT_MASK 0xff000000L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT__SHIFT 0x00000018
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE_MASK 0x00010000L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN_MASK 0x00000001L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE_MASK 0x00000700L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE__SHIFT 0x00000008
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES_MASK 0x0000f000L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES__SHIFT 0x0000000c
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0_MASK 0x0000000fL
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1_MASK 0x000000f0L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1__SHIFT 0x00000004
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET_MASK 0xffff0000L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES_MASK 0x00000f00L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES__SHIFT 0x00000008
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR_MASK 0x80000000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR__SHIFT 0x0000001f
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY_MASK 0x1f000000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY__SHIFT 0x00000018
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL_MASK 0x00030000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL__SHIFT 0x00000010
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT_MASK 0x00300000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT__SHIFT 0x00000014
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS_MASK 0x00000200L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS__SHIFT 0x00000009
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED_MASK 0x00000800L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED__SHIFT 0x0000000b
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT_MASK 0x000000e0L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT__SHIFT 0x00000005
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS_MASK 0x00000400L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS__SHIFT 0x0000000a
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN_MASK 0x00000100L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN__SHIFT 0x00000008
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL_MASK 0x00003000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL__SHIFT 0x0000000c
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG_MASK 0x00000001L
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG__SHIFT 0x00000000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR_MASK 0x80000000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR__SHIFT 0x0000001f
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY_MASK 0x1f000000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY__SHIFT 0x00000018
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL_MASK 0x00030000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL__SHIFT 0x00000010
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT_MASK 0x00300000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT__SHIFT 0x00000014
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS_MASK 0x00000200L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS__SHIFT 0x00000009
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED_MASK 0x00000800L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED__SHIFT 0x0000000b
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT_MASK 0x000000e0L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT__SHIFT 0x00000005
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS_MASK 0x00000400L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS__SHIFT 0x0000000a
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN_MASK 0x00000100L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN__SHIFT 0x00000008
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL_MASK 0x00003000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL__SHIFT 0x0000000c
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG_MASK 0x00000001L
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG__SHIFT 0x00000000
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK_MASK 0x00000001L
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK__SHIFT 0x00000000
+#define CRTC_VBI_END__CRTC_VBI_H_END_MASK 0x1fff0000L
+#define CRTC_VBI_END__CRTC_VBI_H_END__SHIFT 0x00000010
+#define CRTC_VBI_END__CRTC_VBI_V_END_MASK 0x00001fffL
+#define CRTC_VBI_END__CRTC_VBI_V_END__SHIFT 0x00000000
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END_MASK 0x1fff0000L
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END__SHIFT 0x00000010
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START_MASK 0x00001fffL
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START__SHIFT 0x00000000
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE_MASK 0x00030000L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE__SHIFT 0x00000010
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR_MASK 0x00000100L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR__SHIFT 0x00000008
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED_MASK 0x00000001L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED__SHIFT 0x00000000
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE_MASK 0x00000001L
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE__SHIFT 0x00000000
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL_MASK 0x00000001L
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL__SHIFT 0x00000000
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END_MASK 0x1fff0000L
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END__SHIFT 0x00000010
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START_MASK 0x00001fffL
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START__SHIFT 0x00000000
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL_MASK 0x00000001L
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL__SHIFT 0x00000000
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END_MASK 0x1fff0000L
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END__SHIFT 0x00000010
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START_MASK 0x00001fffL
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START__SHIFT 0x00000000
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR_MASK 0x00000010L
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR__SHIFT 0x00000004
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_MASK 0x00000001L
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM__SHIFT 0x00000000
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT_MASK 0x00000100L
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT__SHIFT 0x00000008
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC_MASK 0x00001000L
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC__SHIFT 0x0000000c
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_MASK 0xffff0000L
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK__SHIFT 0x00000010
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL_MASK 0x00000010L
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL__SHIFT 0x00000004
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL_MASK 0x00000001L
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL__SHIFT 0x00000000
+#define CRTC_V_TOTAL__CRTC_V_TOTAL_MASK 0x00001fffL
+#define CRTC_V_TOTAL__CRTC_V_TOTAL__SHIFT 0x00000000
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK_MASK 0x00000100L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK__SHIFT 0x00000008
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000010L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x00000004
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MASK 0x00000001L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK_MASK 0x00001000L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK__SHIFT 0x0000000c
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED__SHIFT 0x00000000
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING_MASK 0x00010000L
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING__SHIFT 0x00000010
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX_MASK 0x00001fffL
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX__SHIFT 0x00000000
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN_MASK 0x00001fffL
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN__SHIFT 0x00000000
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK 0x00000100L
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR__SHIFT 0x00000008
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED_MASK 0x00000001L
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED__SHIFT 0x00000000
+#define CUR_COLOR1__CUR_COLOR1_BLUE_MASK 0x000000ffL
+#define CUR_COLOR1__CUR_COLOR1_BLUE__SHIFT 0x00000000
+#define CUR_COLOR1__CUR_COLOR1_GREEN_MASK 0x0000ff00L
+#define CUR_COLOR1__CUR_COLOR1_GREEN__SHIFT 0x00000008
+#define CUR_COLOR1__CUR_COLOR1_RED_MASK 0x00ff0000L
+#define CUR_COLOR1__CUR_COLOR1_RED__SHIFT 0x00000010
+#define CUR_COLOR2__CUR_COLOR2_BLUE_MASK 0x000000ffL
+#define CUR_COLOR2__CUR_COLOR2_BLUE__SHIFT 0x00000000
+#define CUR_COLOR2__CUR_COLOR2_GREEN_MASK 0x0000ff00L
+#define CUR_COLOR2__CUR_COLOR2_GREEN__SHIFT 0x00000008
+#define CUR_COLOR2__CUR_COLOR2_RED_MASK 0x00ff0000L
+#define CUR_COLOR2__CUR_COLOR2_RED__SHIFT 0x00000010
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP_MASK 0x00000010L
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP__SHIFT 0x00000004
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00010000L
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x00000010
+#define CUR_CONTROL__CURSOR_EN_MASK 0x00000001L
+#define CUR_CONTROL__CURSOR_EN__SHIFT 0x00000000
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON_MASK 0x00100000L
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON__SHIFT 0x00000014
+#define CUR_CONTROL__CURSOR_MODE_MASK 0x00000300L
+#define CUR_CONTROL__CURSOR_MODE__SHIFT 0x00000008
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL_MASK 0x07000000L
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT 0x00000018
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X_MASK 0x003f0000L
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X__SHIFT 0x00000010
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y_MASK 0x0000003fL
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y__SHIFT 0x00000000
+#define CUR_POSITION__CURSOR_X_POSITION_MASK 0x3fff0000L
+#define CUR_POSITION__CURSOR_X_POSITION__SHIFT 0x00000010
+#define CUR_POSITION__CURSOR_Y_POSITION_MASK 0x00003fffL
+#define CUR_POSITION__CURSOR_Y_POSITION__SHIFT 0x00000000
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS_MASK 0x00000001L
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS__SHIFT 0x00000000
+#define CUR_SIZE__CURSOR_HEIGHT_MASK 0x0000003fL
+#define CUR_SIZE__CURSOR_HEIGHT__SHIFT 0x00000000
+#define CUR_SIZE__CURSOR_WIDTH_MASK 0x003f0000L
+#define CUR_SIZE__CURSOR_WIDTH__SHIFT 0x00000010
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS_MASK 0xffffffffL
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS__SHIFT 0x00000000
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK 0x00010000L
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK__SHIFT 0x00000010
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING_MASK 0x00000001L
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING__SHIFT 0x00000000
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN_MASK 0x00000002L
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN__SHIFT 0x00000001
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE_MASK 0x00000001L
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D1VGA_CONTROL__D1VGA_ROTATE_MASK 0x03000000L
+#define D1VGA_CONTROL__D1VGA_ROTATE__SHIFT 0x00000018
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT_MASK 0x00000100L
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE_MASK 0x00000001L
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D2VGA_CONTROL__D2VGA_ROTATE_MASK 0x03000000L
+#define D2VGA_CONTROL__D2VGA_ROTATE__SHIFT 0x00000018
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT_MASK 0x00000100L
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE_MASK 0x00000001L
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D3VGA_CONTROL__D3VGA_ROTATE_MASK 0x03000000L
+#define D3VGA_CONTROL__D3VGA_ROTATE__SHIFT 0x00000018
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT_MASK 0x00000100L
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE_MASK 0x00000001L
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D4VGA_CONTROL__D4VGA_ROTATE_MASK 0x03000000L
+#define D4VGA_CONTROL__D4VGA_ROTATE__SHIFT 0x00000018
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT_MASK 0x00000100L
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE_MASK 0x00000001L
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D5VGA_CONTROL__D5VGA_ROTATE_MASK 0x03000000L
+#define D5VGA_CONTROL__D5VGA_ROTATE__SHIFT 0x00000018
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT_MASK 0x00000100L
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE_MASK 0x00000001L
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D6VGA_CONTROL__D6VGA_ROTATE_MASK 0x03000000L
+#define D6VGA_CONTROL__D6VGA_ROTATE__SHIFT 0x00000018
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT_MASK 0x00000100L
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER_MASK 0x000000ffL
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER__SHIFT 0x00000000
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE_MASK 0x00000100L
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY_MASK 0x000000ffL
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY__SHIFT 0x00000000
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY_MASK 0x0000ff00L
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK_MASK 0x00070000L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK__SHIFT 0x00000010
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER_MASK 0x0000ff00L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE_MASK 0x00000003L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE__SHIFT 0x00000000
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK_MASK 0x00000001L
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK__SHIFT 0x00000000
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE_MASK 0x00010000L
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE__SHIFT 0x00000010
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE_MASK 0x03000000L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE__SHIFT 0x00000018
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT_MASK 0x00000010L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT__SHIFT 0x00000004
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE_MASK 0x00030000L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE__SHIFT 0x00000010
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE_MASK 0x00000300L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE__SHIFT 0x00000008
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS_MASK 0x00000001L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS__SHIFT 0x00000000
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE_MASK 0x00000001L
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE__SHIFT 0x00000000
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE_MASK 0x00000010L
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE__SHIFT 0x00000004
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE_MASK 0x00040000L
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE__SHIFT 0x00000012
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN_MASK 0x00000001L
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN__SHIFT 0x00000000
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN_MASK 0x00000100L
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN__SHIFT 0x00000008
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE_MASK 0x00020000L
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE__SHIFT 0x00000011
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE_MASK 0x00010000L
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE__SHIFT 0x00000010
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE_MASK 0x00000002L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE__SHIFT 0x00000001
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN_MASK 0x00000004L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN__SHIFT 0x00000002
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_MASK 0x00000001L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED_MASK 0x00000008L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED__SHIFT 0x00000003
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT__SHIFT 0x00000000
+#define DAC_CONTROL__DAC_DFORCE_EN_MASK 0x00000001L
+#define DAC_CONTROL__DAC_DFORCE_EN__SHIFT 0x00000000
+#define DAC_CONTROL__DAC_TV_ENABLE_MASK 0x00000100L
+#define DAC_CONTROL__DAC_TV_ENABLE__SHIFT 0x00000008
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT_MASK 0x00010000L
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT__SHIFT 0x00000010
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD_MASK 0x00000001L
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD__SHIFT 0x00000000
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKb_MASK 0x00000100L
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKb__SHIFT 0x00000008
+#define DAC_CRC_EN__DAC_CRC_CONT_EN_MASK 0x00010000L
+#define DAC_CRC_EN__DAC_CRC_CONT_EN__SHIFT 0x00000010
+#define DAC_CRC_EN__DAC_CRC_EN_MASK 0x00000001L
+#define DAC_CRC_EN__DAC_CRC_EN__SHIFT 0x00000000
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL_MASK 0x0000003fL
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL__SHIFT 0x00000000
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK_MASK 0x0000003fL
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE_MASK 0x000003ffL
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN_MASK 0x000ffc00L
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN__SHIFT 0x0000000a
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED_MASK 0x3ff00000L
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED__SHIFT 0x00000014
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK_MASK 0x000003ffL
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK_MASK 0x000ffc00L
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK__SHIFT 0x0000000a
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK_MASK 0x3ff00000L
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK__SHIFT 0x00000014
+#define DAC_DATA__DAC_DATA_MASK 0x0000003fL
+#define DAC_DATA__DAC_DATA__SHIFT 0x00000000
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG_MASK 0xffffffffL
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG__SHIFT 0x00000000
+#define DAC_ENABLE__DAC_ENABLE_MASK 0x00000001L
+#define DAC_ENABLE__DAC_ENABLE__SHIFT 0x00000000
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE_MASK 0x00000002L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE__SHIFT 0x00000001
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK_MASK 0x00000020L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK__SHIFT 0x00000005
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_MASK 0x00000010L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR__SHIFT 0x00000004
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW_MASK 0x0000000cL
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW__SHIFT 0x00000002
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM_MASK 0x00000100L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM__SHIFT 0x00000008
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED_MASK 0x20000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL_MASK 0x000f0000L
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DAC_FORCE_DATA__DAC_FORCE_DATA_MASK 0x000003ffL
+#define DAC_FORCE_DATA__DAC_FORCE_DATA__SHIFT 0x00000000
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN_MASK 0x00000001L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN__SHIFT 0x00000000
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKb_ONLY_MASK 0x01000000L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKb_ONLY__SHIFT 0x00000018
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL_MASK 0x00000700L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL__SHIFT 0x00000008
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MASK__DAC_MASK_MASK 0x000000ffL
+#define DAC_MASK__DAC_MASK__SHIFT 0x00000000
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE_MASK 0x00000100L
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE__SHIFT 0x00000008
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN_MASK 0x00010000L
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN__SHIFT 0x00000010
+#define DAC_POWERDOWN__DAC_POWERDOWN_MASK 0x00000001L
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED_MASK 0x01000000L
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED__SHIFT 0x00000018
+#define DAC_POWERDOWN__DAC_POWERDOWN__SHIFT 0x00000000
+#define DAC_PWR_CNTL__DAC_BG_MODE_MASK 0x00000003L
+#define DAC_PWR_CNTL__DAC_BG_MODE__SHIFT 0x00000000
+#define DAC_PWR_CNTL__DAC_PWRCNTL_MASK 0x00030000L
+#define DAC_PWR_CNTL__DAC_PWRCNTL__SHIFT 0x00000010
+#define DAC_R_INDEX__DAC_R_INDEX_MASK 0x000000ffL
+#define DAC_R_INDEX__DAC_R_INDEX__SHIFT 0x00000000
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT_MASK 0x00000007L
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT__SHIFT 0x00000000
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT_MASK 0x00000008L
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT__SHIFT 0x00000003
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT_MASK 0x00000007L
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT__SHIFT 0x00000000
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE_MASK 0x00000001L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE__SHIFT 0x00000000
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE_MASK 0x00010000L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE__SHIFT 0x00000010
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE_MASK 0x00000100L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE__SHIFT 0x00000008
+#define DAC_W_INDEX__DAC_W_INDEX_MASK 0x000000ffL
+#define DAC_W_INDEX__DAC_W_INDEX__SHIFT 0x00000000
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR_MASK 0x00000100L
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR__SHIFT 0x00000008
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_MASK 0x00000001L
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1_MASK 0x000003ffL
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2_MASK 0x03ff0000L
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2__SHIFT 0x00000010
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING_MASK 0x40000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING__SHIFT 0x0000001e
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN_MASK 0x10000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001c
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN_MASK 0x20000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN__SHIFT 0x0000001d
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3_MASK 0x000003ffL
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4_MASK 0x03ff0000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4__SHIFT 0x00000010
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK_MASK 0x80000000L
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE_MASK 0x80000000L
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE__SHIFT 0x0000001f
+#define DC_ABM1_CNTL__ABM1_EN_MASK 0x00000001L
+#define DC_ABM1_CNTL__ABM1_EN__SHIFT 0x00000000
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT_MASK 0x00000700L
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT__SHIFT 0x00000008
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT_MASK 0x00010000L
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT__SHIFT 0x00000010
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT_MASK 0x00000001L
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT__SHIFT 0x00000000
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT_MASK 0x00000100L
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT__SHIFT 0x00000008
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS_MASK 0x00000004L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS__SHIFT 0x00000002
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR_MASK 0x80000000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x0000001f
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_MASK 0x00000400L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME__SHIFT 0x0000000a
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS_MASK 0x00000001L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS__SHIFT 0x00000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR_MASK 0x00010000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x00000010
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_MASK 0x00000100L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME__SHIFT 0x00000008
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS_MASK 0x00000002L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS__SHIFT 0x00000001
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR_MASK 0x01000000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x00000018
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_MASK 0x00000200L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME__SHIFT 0x00000009
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN_MASK 0x00800000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000017
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL_MASK 0x07000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL__SHIFT 0x00000018
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START_MASK 0x10000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START__SHIFT 0x0000001c
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING_MASK 0x40000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING__SHIFT 0x0000001e
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL_MASK 0x00030000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL__SHIFT 0x00000010
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL_MASK 0x00001000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL__SHIFT 0x0000000c
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN_MASK 0x20000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001d
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL_MASK 0x00000003L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL__SHIFT 0x00000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL_MASK 0x00000100L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL__SHIFT 0x00000008
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN_MASK 0x00100000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN__SHIFT 0x00000014
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9__SHIFT 0x00000000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B_MASK 0x0000000fL
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B__SHIFT 0x00000000
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G_MASK 0x00000f00L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G__SHIFT 0x00000008
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R_MASK 0x000f0000L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R__SHIFT 0x00000010
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA_MASK 0x03ff0000L
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA__SHIFT 0x00000010
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA_MASK 0x000003ffL
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA__SHIFT 0x00000000
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA_MASK 0x03ff0000L
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA__SHIFT 0x00000010
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA_MASK 0x000003ffL
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES_MASK 0x03ff0000L
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES__SHIFT 0x00000010
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES_MASK 0x000003ffL
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN_MASK 0x00ffffffL
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN__SHIFT 0x00000000
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA_MASK 0xffffffffL
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA__SHIFT 0x00000000
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE_MASK 0x3ff00000L
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE__SHIFT 0x00000014
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE_MASK 0x000ffc00L
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE__SHIFT 0x0000000a
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE_MASK 0x000003ffL
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL_MASK 0x00000007L
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL_MASK 0x00000010L
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL__SHIFT 0x00000004
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA_MASK 0xffffffffL
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA__SHIFT 0x00000000
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE_MASK 0x00000010L
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE__SHIFT 0x00000004
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE_MASK 0x00000020L
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE__SHIFT 0x00000005
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE_MASK 0x00000001L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE__SHIFT 0x00000000
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_RAMP_DIV_ID_MASK 0x07000000L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_RAMP_DIV_ID__SHIFT 0x00000018
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE_MASK 0x00000002L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE__SHIFT 0x00000001
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_RAMP_DISABLE_MASK 0x00100000L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_RAMP_DISABLE__SHIFT 0x00000014
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE_MASK 0x00000040L
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE__SHIFT 0x00000006
+#define DCCG_GATE_DISABLE_CNTL__PCLK_TV_GATE_DISABLE_MASK 0x00010000L
+#define DCCG_GATE_DISABLE_CNTL__PCLK_TV_GATE_DISABLE__SHIFT 0x00000010
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE_MASK 0x00000004L
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE__SHIFT 0x00000002
+#define DCCG_GATE_DISABLE_CNTL__SCLK_RAMP_DIV_ID_MASK 0x70000000L
+#define DCCG_GATE_DISABLE_CNTL__SCLK_RAMP_DIV_ID__SHIFT 0x0000001c
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKA_GATE_DISABLE_MASK 0x00000100L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKA_GATE_DISABLE__SHIFT 0x00000008
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKB_GATE_DISABLE_MASK 0x00000200L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKB_GATE_DISABLE__SHIFT 0x00000009
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKC_GATE_DISABLE_MASK 0x00000400L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKC_GATE_DISABLE__SHIFT 0x0000000a
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKD_GATE_DISABLE_MASK 0x00000800L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKD_GATE_DISABLE__SHIFT 0x0000000b
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKE_GATE_DISABLE_MASK 0x00001000L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKE_GATE_DISABLE__SHIFT 0x0000000c
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKF_GATE_DISABLE_MASK 0x00002000L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKF_GATE_DISABLE__SHIFT 0x0000000d
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE_MASK 0x00000001L
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE__SHIFT 0x00000000
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT_MASK 0xffffffffL
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT__SHIFT 0x00000000
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO_MASK 0xffffffffL
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO__SHIFT 0x00000000
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL_MASK 0x00000700L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL__SHIFT 0x00000008
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE_MASK 0x00000001L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE__SHIFT 0x00000000
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE_MASK 0x00000002L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE__SHIFT 0x00000001
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC_MASK 0x00000080L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC__SHIFT 0x00000007
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC_MASK 0x00000040L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC__SHIFT 0x00000006
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE_MASK 0x00000010L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE__SHIFT 0x00000004
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK1_ENABLE_MASK 0x00000004L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK1_ENABLE__SHIFT 0x00000002
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK2_ENABLE_MASK 0x00000008L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK2_ENABLE__SHIFT 0x00000003
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN_MASK 0x00000020L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN__SHIFT 0x00000005
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET_MASK 0x00000001L
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET__SHIFT 0x00000000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV_MASK 0x00010000L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV__SHIFT 0x00000010
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL_MASK 0x000000ffL
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL__SHIFT 0x00000000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV_MASK 0x01000000L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV__SHIFT 0x00000018
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL_MASK 0x0000ff00L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL__SHIFT 0x00000008
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCCG_TEST_DEBUG_INDEX__DCCG_DBG_SEL_MASK 0x00001000L
+#define DCCG_TEST_DEBUG_INDEX__DCCG_DBG_SEL__SHIFT 0x0000000c
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DCCG_VPCLK_CNTL__AZ_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCCG_VPCLK_CNTL__AZ_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCCG_VPCLK_CNTL__AZ_MEM_SHUTDOWN_DIS_MASK 0x04000000L
+#define DCCG_VPCLK_CNTL__AZ_MEM_SHUTDOWN_DIS__SHIFT 0x0000001a
+#define DCCG_VPCLK_CNTL__DCCG_VPCLK_POL_MASK 0x00000001L
+#define DCCG_VPCLK_CNTL__DCCG_VPCLK_POL__SHIFT 0x00000000
+#define DCCG_VPCLK_CNTL__DMCU_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCCG_VPCLK_CNTL__DMCU_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCCG_VPCLK_CNTL__DMCU_MEM_SHUTDOWN_DIS_MASK 0x00010000L
+#define DCCG_VPCLK_CNTL__DMCU_MEM_SHUTDOWN_DIS__SHIFT 0x00000010
+#define DCCG_VPCLK_CNTL__DMIF0_LIGHT_SLEEP_DIS_MASK 0x00000100L
+#define DCCG_VPCLK_CNTL__DMIF0_LIGHT_SLEEP_DIS__SHIFT 0x00000008
+#define DCCG_VPCLK_CNTL__DMIF0_MEM_SHUTDOWN_DIS_MASK 0x00100000L
+#define DCCG_VPCLK_CNTL__DMIF0_MEM_SHUTDOWN_DIS__SHIFT 0x00000014
+#define DCCG_VPCLK_CNTL__DMIF1_LIGHT_SLEEP_DIS_MASK 0x00000200L
+#define DCCG_VPCLK_CNTL__DMIF1_LIGHT_SLEEP_DIS__SHIFT 0x00000009
+#define DCCG_VPCLK_CNTL__DMIF1_MEM_SHUTDOWN_DIS_MASK 0x00200000L
+#define DCCG_VPCLK_CNTL__DMIF1_MEM_SHUTDOWN_DIS__SHIFT 0x00000015
+#define DCCG_VPCLK_CNTL__DMIF2_LIGHT_SLEEP_DIS_MASK 0x00000400L
+#define DCCG_VPCLK_CNTL__DMIF2_LIGHT_SLEEP_DIS__SHIFT 0x0000000a
+#define DCCG_VPCLK_CNTL__DMIF2_MEM_SHUTDOWN_DIS_MASK 0x00400000L
+#define DCCG_VPCLK_CNTL__DMIF2_MEM_SHUTDOWN_DIS__SHIFT 0x00000016
+#define DCCG_VPCLK_CNTL__DMIF3_LIGHT_SLEEP_DIS_MASK 0x00000800L
+#define DCCG_VPCLK_CNTL__DMIF3_LIGHT_SLEEP_DIS__SHIFT 0x0000000b
+#define DCCG_VPCLK_CNTL__DMIF3_MEM_SHUTDOWN_DIS_MASK 0x00800000L
+#define DCCG_VPCLK_CNTL__DMIF3_MEM_SHUTDOWN_DIS__SHIFT 0x00000017
+#define DCCG_VPCLK_CNTL__DMIF4_LIGHT_SLEEP_DIS_MASK 0x00001000L
+#define DCCG_VPCLK_CNTL__DMIF4_LIGHT_SLEEP_DIS__SHIFT 0x0000000c
+#define DCCG_VPCLK_CNTL__DMIF4_MEM_SHUTDOWN_DIS_MASK 0x01000000L
+#define DCCG_VPCLK_CNTL__DMIF4_MEM_SHUTDOWN_DIS__SHIFT 0x00000018
+#define DCCG_VPCLK_CNTL__DMIF5_LIGHT_SLEEP_DIS_MASK 0x00002000L
+#define DCCG_VPCLK_CNTL__DMIF5_LIGHT_SLEEP_DIS__SHIFT 0x0000000d
+#define DCCG_VPCLK_CNTL__DMIF5_MEM_SHUTDOWN_DIS_MASK 0x02000000L
+#define DCCG_VPCLK_CNTL__DMIF5_MEM_SHUTDOWN_DIS__SHIFT 0x00000019
+#define DCCG_VPCLK_CNTL__DMIF_XLR_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000020L
+#define DCCG_VPCLK_CNTL__DMIF_XLR_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000005
+#define DCCG_VPCLK_CNTL__DMIF_XLR_MEM_SHUTDOWN_MODE_FORCE_MASK 0x00040000L
+#define DCCG_VPCLK_CNTL__DMIF_XLR_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000012
+#define DCCG_VPCLK_CNTL__FBC_LIGHT_SLEEP_DIS_MASK 0x00004000L
+#define DCCG_VPCLK_CNTL__FBC_LIGHT_SLEEP_DIS__SHIFT 0x0000000e
+#define DCCG_VPCLK_CNTL__FBC_MEM_SHUTDOWN_DIS_MASK 0x00080000L
+#define DCCG_VPCLK_CNTL__FBC_MEM_SHUTDOWN_DIS__SHIFT 0x00000013
+#define DCCG_VPCLK_CNTL__MCIF_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000010L
+#define DCCG_VPCLK_CNTL__MCIF_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000004
+#define DCCG_VPCLK_CNTL__MCIF_MEM_SHUTDOWN_MODE_FORCE_MASK 0x00020000L
+#define DCCG_VPCLK_CNTL__MCIF_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000011
+#define DCCG_VPCLK_CNTL__VGA_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000002L
+#define DCCG_VPCLK_CNTL__VGA_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000001
+#define DCCG_VPCLK_CNTL__VIP_LIGHT_SLEEP_DIS_MASK 0x00008000L
+#define DCCG_VPCLK_CNTL__VIP_LIGHT_SLEEP_DIS__SHIFT 0x0000000f
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL_MASK 0x0000001fL
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_EN_MASK 0x00000020L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_EN__SHIFT 0x00000005
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_PIN_SEL_MASK 0x00000040L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_PIN_SEL__SHIFT 0x00000006
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_SEL_MASK 0x00300000L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_SEL__SHIFT 0x00000014
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_EN_MASK 0x00000080L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_EN__SHIFT 0x00000007
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_MASK 0x000fff00L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA__SHIFT 0x00000008
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA_MASK 0xffffffffL
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA__SHIFT 0x00000000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN_MASK 0x00001000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN__SHIFT 0x0000000c
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL_MASK 0x0000000fL
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL_MASK 0x000001f0L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL__SHIFT 0x00000004
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN_MASK 0x10000000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN__SHIFT 0x0000001c
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL_MASK 0x000f0000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL__SHIFT 0x00000010
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL_MASK 0x01f00000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL__SHIFT 0x00000014
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH_MASK 0xffffffffL
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH__SHIFT 0x00000000
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN_MASK 0x00200000L
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN__SHIFT 0x00000015
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN_MASK 0x00100000L
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN__SHIFT 0x00000014
+#define DC_DVODATA_CONFIG__VIP_MUX_EN_MASK 0x00080000L
+#define DC_DVODATA_CONFIG__VIP_MUX_EN__SHIFT 0x00000013
+#define DCFE0_SOFT_RESET__CRTC0_SOFT_RESET_MASK 0x00000010L
+#define DCFE0_SOFT_RESET__CRTC0_SOFT_RESET__SHIFT 0x00000004
+#define DCFE0_SOFT_RESET__DCP0_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE0_SOFT_RESET__DCP0_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE0_SOFT_RESET__DCP0_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE0_SOFT_RESET__DCP0_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE0_SOFT_RESET__SCL0_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE0_SOFT_RESET__SCL0_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE0_SOFT_RESET__SCL0_SOFT_RESET_MASK 0x00000008L
+#define DCFE0_SOFT_RESET__SCL0_SOFT_RESET__SHIFT 0x00000003
+#define DCFE1_SOFT_RESET__CRTC1_SOFT_RESET_MASK 0x00000010L
+#define DCFE1_SOFT_RESET__CRTC1_SOFT_RESET__SHIFT 0x00000004
+#define DCFE1_SOFT_RESET__DCP1_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE1_SOFT_RESET__DCP1_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE1_SOFT_RESET__DCP1_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE1_SOFT_RESET__DCP1_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE1_SOFT_RESET__SCL1_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE1_SOFT_RESET__SCL1_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE1_SOFT_RESET__SCL1_SOFT_RESET_MASK 0x00000008L
+#define DCFE1_SOFT_RESET__SCL1_SOFT_RESET__SHIFT 0x00000003
+#define DCFE2_SOFT_RESET__CRTC2_SOFT_RESET_MASK 0x00000010L
+#define DCFE2_SOFT_RESET__CRTC2_SOFT_RESET__SHIFT 0x00000004
+#define DCFE2_SOFT_RESET__DCP2_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE2_SOFT_RESET__DCP2_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE2_SOFT_RESET__DCP2_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE2_SOFT_RESET__DCP2_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE2_SOFT_RESET__SCL2_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE2_SOFT_RESET__SCL2_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE2_SOFT_RESET__SCL2_SOFT_RESET_MASK 0x00000008L
+#define DCFE2_SOFT_RESET__SCL2_SOFT_RESET__SHIFT 0x00000003
+#define DCFE3_SOFT_RESET__CRTC3_SOFT_RESET_MASK 0x00000010L
+#define DCFE3_SOFT_RESET__CRTC3_SOFT_RESET__SHIFT 0x00000004
+#define DCFE3_SOFT_RESET__DCP3_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE3_SOFT_RESET__DCP3_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE3_SOFT_RESET__DCP3_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE3_SOFT_RESET__DCP3_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE3_SOFT_RESET__SCL3_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE3_SOFT_RESET__SCL3_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE3_SOFT_RESET__SCL3_SOFT_RESET_MASK 0x00000008L
+#define DCFE3_SOFT_RESET__SCL3_SOFT_RESET__SHIFT 0x00000003
+#define DCFE4_SOFT_RESET__CRTC4_SOFT_RESET_MASK 0x00000010L
+#define DCFE4_SOFT_RESET__CRTC4_SOFT_RESET__SHIFT 0x00000004
+#define DCFE4_SOFT_RESET__DCP4_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE4_SOFT_RESET__DCP4_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE4_SOFT_RESET__DCP4_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE4_SOFT_RESET__DCP4_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE4_SOFT_RESET__SCL4_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE4_SOFT_RESET__SCL4_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE4_SOFT_RESET__SCL4_SOFT_RESET_MASK 0x00000008L
+#define DCFE4_SOFT_RESET__SCL4_SOFT_RESET__SHIFT 0x00000003
+#define DCFE5_SOFT_RESET__CRTC5_SOFT_RESET_MASK 0x00000010L
+#define DCFE5_SOFT_RESET__CRTC5_SOFT_RESET__SHIFT 0x00000004
+#define DCFE5_SOFT_RESET__DCP5_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE5_SOFT_RESET__DCP5_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE5_SOFT_RESET__DCP5_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE5_SOFT_RESET__DCP5_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE5_SOFT_RESET__SCL5_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE5_SOFT_RESET__SCL5_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE5_SOFT_RESET__SCL5_SOFT_RESET_MASK 0x00000008L
+#define DCFE5_SOFT_RESET__SCL5_SOFT_RESET__SHIFT 0x00000003
+#define DCFE_DBG_SEL__DCFE_DBG_SEL_MASK 0x0000000fL
+#define DCFE_DBG_SEL__DCFE_DBG_SEL__SHIFT 0x00000000
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_MEM_PWR_STATE_MASK 0x00000300L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_MEM_PWR_STATE_MASK 0x00003000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB1_MEM_SHUTDOWN_DIS_MASK 0x20000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB1_MEM_SHUTDOWN_DIS__SHIFT 0x0000001d
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB2_MEM_SHUTDOWN_DIS_MASK 0x40000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB2_MEM_SHUTDOWN_DIS__SHIFT 0x0000001e
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_0_MASK 0x00030000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_0__SHIFT 0x00000010
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_1_MASK 0x00c00000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_1__SHIFT 0x00000016
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_2_MASK 0x03000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_2__SHIFT 0x00000018
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__PIPE_MEM_SHUTDOWN_DIS_MASK 0x10000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__PIPE_MEM_SHUTDOWN_DIS__SHIFT 0x0000001c
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_LIGHT_SLEEP_DIS_MASK 0x00000040L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_LIGHT_SLEEP_DIS__SHIFT 0x00000006
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_MEM_PWR_STATE_MASK 0x00300000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_MEM_PWR_STATE__SHIFT 0x00000012
+#define DC_GENERICA__GENERICA_EN_MASK 0x00000001L
+#define DC_GENERICA__GENERICA_EN__SHIFT 0x00000000
+#define DC_GENERICA__GENERICA_SEL_MASK 0x00000f00L
+#define DC_GENERICA__GENERICA_SEL__SHIFT 0x00000008
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0x07000000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x00000018
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL_MASK 0x00070000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x00000010
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0x00700000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x00000014
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL_MASK 0x00007000L
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL__SHIFT 0x0000000c
+#define DC_GENERICB__GENERICB_EN_MASK 0x00000001L
+#define DC_GENERICB__GENERICB_EN__SHIFT 0x00000000
+#define DC_GENERICB__GENERICB_SEL_MASK 0x00000f00L
+#define DC_GENERICB__GENERICB_SEL__SHIFT 0x00000008
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0x07000000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x00000018
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL_MASK 0x00070000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x00000010
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0x00700000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x00000014
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL_MASK 0x00007000L
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL__SHIFT 0x0000000c
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC1_MASK__AUX1_POL_MASK 0x00100000L
+#define DC_GPIO_DDC1_MASK__AUX1_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC2_MASK__AUX2_POL_MASK 0x00100000L
+#define DC_GPIO_DDC2_MASK__AUX2_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC3_MASK__AUX3_POL_MASK 0x00100000L
+#define DC_GPIO_DDC3_MASK__AUX3_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC4_MASK__AUX4_POL_MASK 0x00100000L
+#define DC_GPIO_DDC4_MASK__AUX4_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC5_MASK__AUX5_POL_MASK 0x00100000L
+#define DC_GPIO_DDC5_MASK__AUX5_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC6_MASK__AUX6_POL_MASK 0x00100000L
+#define DC_GPIO_DDC6_MASK__AUX6_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK 0x00010000L
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK 0x00100000L
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL__SHIFT 0x00000014
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL_MASK 0x00010000L
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL__SHIFT 0x00000010
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG_MASK 0x00000300L
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG__SHIFT 0x00000008
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG_MASK 0x00000001L
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCLK_A_MASK 0x10000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCLK_A__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCNTL_A_MASK 0x07000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCNTL_A__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_A__DC_GPIO_MVP_DVOCNTL_A_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_MVP_DVOCNTL_A__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCLK_EN_MASK 0x10000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCLK_EN__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCNTL_EN_MASK 0x07000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCNTL_EN__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVODATA_EN_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVODATA_EN__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_EN__DC_GPIO_MVP_DVOCNTL_EN_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_MVP_DVOCNTL_EN__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCLK_MASK_MASK 0x10000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCLK_MASK__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCNTL_MASK_MASK 0x07000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCNTL_MASK__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVODATA_MASK_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVODATA_MASK__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_MVP_DVOCNTL_MASK_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_MVP_DVOCNTL_MASK__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCLK_Y_MASK 0x10000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCLK_Y__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCNTL_Y_MASK 0x07000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCNTL_Y__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVODATA_Y_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVODATA_Y__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_Y__DC_GPIO_MVP_DVOCNTL_Y_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_MVP_DVOCNTL_Y__SHIFT 0x0000001e
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK 0x00000001L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK 0x00000100L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK 0x00010000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK 0x00100000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK 0x00200000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK 0x00400000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK 0x00800000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A__SHIFT 0x00000017
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN_MASK 0x00000001L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN_MASK 0x00000100L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN_MASK 0x00010000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN_MASK 0x00100000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN_MASK 0x00200000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN_MASK 0x00400000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN_MASK 0x00800000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN__SHIFT 0x00000017
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK_MASK 0x00000001L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV_MASK 0x00000004L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV__SHIFT 0x00000002
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK_MASK 0x00000010L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK__SHIFT 0x00000004
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS_MASK 0x00000020L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS__SHIFT 0x00000005
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV_MASK 0x00000040L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV__SHIFT 0x00000006
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK_MASK 0x00000100L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV_MASK 0x00000400L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV__SHIFT 0x0000000a
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK_MASK 0x00001000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK__SHIFT 0x0000000c
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS_MASK 0x00002000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS__SHIFT 0x0000000d
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV_MASK 0x00004000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV__SHIFT 0x0000000e
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK_MASK 0x00010000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV_MASK 0x00040000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV__SHIFT 0x00000012
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK_MASK 0x00100000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS_MASK 0x00200000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV_MASK 0x00400000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK_MASK 0x01000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK__SHIFT 0x00000018
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV_MASK 0x04000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV__SHIFT 0x0000001a
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y_MASK 0x00000001L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y_MASK 0x00000100L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y_MASK 0x00010000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y_MASK 0x00100000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y_MASK 0x00200000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y_MASK 0x00400000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y_MASK 0x00800000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y__SHIFT 0x00000017
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK 0x00000001L
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A__SHIFT 0x00000000
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK 0x00000100L
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A__SHIFT 0x00000008
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK 0x00010000L
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A__SHIFT 0x00000010
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK 0x01000000L
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A__SHIFT 0x00000018
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN_MASK 0x00000001L
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN_MASK 0x00000100L
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN__SHIFT 0x00000008
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN_MASK 0x00010000L
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN__SHIFT 0x00000010
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN_MASK 0x01000000L
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN__SHIFT 0x00000018
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN_MASK 0x00000008L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN__SHIFT 0x00000003
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV_MASK 0x00000004L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV__SHIFT 0x00000002
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK_MASK 0x00000100L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK__SHIFT 0x00000008
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN_MASK 0x00000800L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN__SHIFT 0x0000000b
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV_MASK 0x00000400L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV__SHIFT 0x0000000a
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK_MASK 0x00010000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK__SHIFT 0x00000010
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN_MASK 0x00080000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN__SHIFT 0x00000013
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV_MASK 0x00040000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV__SHIFT 0x00000012
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK_MASK 0x01000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK__SHIFT 0x00000018
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN_MASK 0x08000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN__SHIFT 0x0000001b
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV_MASK 0x04000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV__SHIFT 0x0000001a
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y_MASK 0x00000001L
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y_MASK 0x00000100L
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y__SHIFT 0x00000008
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y_MASK 0x00010000L
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y__SHIFT 0x00000010
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y_MASK 0x01000000L
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y__SHIFT 0x00000018
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK 0x00000001L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A__SHIFT 0x00000000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK 0x00000100L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A__SHIFT 0x00000008
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK 0x00010000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A__SHIFT 0x00000010
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK 0x01000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A__SHIFT 0x00000018
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK 0x04000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A__SHIFT 0x0000001a
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK 0x10000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A__SHIFT 0x0000001c
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK 0x00000001L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN__SHIFT 0x00000000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK 0x00000100L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN__SHIFT 0x00000008
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK 0x00010000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN__SHIFT 0x00000010
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK 0x01000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN__SHIFT 0x00000018
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK 0x04000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN__SHIFT 0x0000001a
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK 0x10000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN__SHIFT 0x0000001c
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK 0x00000001L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK__SHIFT 0x00000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV_MASK 0x00000040L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV__SHIFT 0x00000006
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK 0x00000100L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK__SHIFT 0x00000008
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV_MASK 0x00000400L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV__SHIFT 0x0000000a
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK 0x00010000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK__SHIFT 0x00000010
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV_MASK 0x00040000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV__SHIFT 0x00000012
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK 0x00100000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK__SHIFT 0x00000014
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS_MASK 0x00200000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS__SHIFT 0x00000015
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV_MASK 0x00400000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV__SHIFT 0x00000016
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK 0x01000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK__SHIFT 0x00000018
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV_MASK 0x04000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV__SHIFT 0x0000001a
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK 0x10000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK__SHIFT 0x0000001c
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS_MASK 0x20000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS__SHIFT 0x0000001d
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV_MASK 0x40000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV__SHIFT 0x0000001e
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK 0x00000001L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y__SHIFT 0x00000000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK 0x00000100L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y__SHIFT 0x00000008
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK 0x00010000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y__SHIFT 0x00000010
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK 0x01000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y__SHIFT 0x00000018
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK 0x04000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y__SHIFT 0x0000001a
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK 0x10000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y__SHIFT 0x0000001c
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK 0x00000004L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV__SHIFT 0x00000002
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK 0x00000010L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK__SHIFT 0x00000004
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK 0x00000020L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS__SHIFT 0x00000005
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK 0x00000040L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV__SHIFT 0x00000006
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y__SHIFT 0x00000001
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN_MASK 0x0f000000L
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN__SHIFT 0x00000018
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP_MASK 0xf0000000L
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP__SHIFT 0x0000001c
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN_MASK 0x000f0000L
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN__SHIFT 0x00000010
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP_MASK 0x00f00000L
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP__SHIFT 0x00000014
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN_MASK 0x00000002L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN__SHIFT 0x00000001
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV_MASK 0x00000040L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV__SHIFT 0x00000006
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS_MASK 0x00001000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS__SHIFT 0x0000000c
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV_MASK 0x00004000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV__SHIFT 0x0000000e
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS_MASK 0x00100000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS__SHIFT 0x00000014
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV_MASK 0x00400000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV__SHIFT 0x00000016
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y__SHIFT 0x00000010
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK 0x00000001L
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK 0x00000100L
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN_MASK 0x00000001L
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN_MASK 0x00000100L
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK_MASK 0x07000000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK__SHIFT 0x00000018
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK_MASK 0x00000001L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV_MASK 0x00000040L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV__SHIFT 0x00000006
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK_MASK 0x70000000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK__SHIFT 0x0000001c
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK_MASK 0x00000100L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS_MASK 0x00001000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS__SHIFT 0x0000000c
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV_MASK 0x00004000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y_MASK 0x00000001L
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y_MASK 0x00000100L
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y__SHIFT 0x00000008
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT_MASK 0x0000003fL
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT__SHIFT 0x00000000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM_MASK 0x00000700L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM__SHIFT 0x00000008
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM_MASK 0x00003800L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM__SHIFT 0x0000000b
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM_MASK 0x0001c000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM__SHIFT 0x0000000e
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM_MASK 0x000e0000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM__SHIFT 0x00000011
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM_MASK 0x00700000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM__SHIFT 0x00000014
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM_MASK 0x03800000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM__SHIFT 0x00000017
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ_MASK 0xffffffffL
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP_MASK 0x00000007L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP_MASK 0x00000070L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP__SHIFT 0x00000004
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP_MASK 0x00000700L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP__SHIFT 0x00000008
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP_MASK 0x00007000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP__SHIFT 0x0000000c
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP_MASK 0x00070000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP__SHIFT 0x00000010
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP_MASK 0x00700000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP__SHIFT 0x00000014
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE_MASK 0x00000007L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE_MASK 0x00000070L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE__SHIFT 0x00000004
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE_MASK 0x00000700L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE__SHIFT 0x00000008
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE_MASK 0x00007000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE__SHIFT 0x0000000c
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE_MASK 0x00070000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE__SHIFT 0x00000010
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE_MASK 0x00700000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE__SHIFT 0x00000014
+#define DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD1_CONTROL__DC_HPD1_EN_MASK 0x10000000L
+#define DC_HPD1_CONTROL__DC_HPD1_EN__SHIFT 0x0000001c
+#define DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK 0x00000001L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK__SHIFT 0x00000000
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK 0x00010000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN__SHIFT 0x00000010
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD1_INT_STATUS__DC_HPD1_INT_STATUS_MASK 0x00000001L
+#define DC_HPD1_INT_STATUS__DC_HPD1_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD1_INT_STATUS__DC_HPD1_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD1_INT_STATUS__DC_HPD1_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK 0x00000002L
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE__SHIFT 0x00000001
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD2_CONTROL__DC_HPD2_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD2_CONTROL__DC_HPD2_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD2_CONTROL__DC_HPD2_EN_MASK 0x10000000L
+#define DC_HPD2_CONTROL__DC_HPD2_EN__SHIFT 0x0000001c
+#define DC_HPD2_CONTROL__DC_HPD2_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD2_CONTROL__DC_HPD2_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_ACK_MASK 0x00000001L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_ACK__SHIFT 0x00000000
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_EN_MASK 0x00010000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_EN__SHIFT 0x00000010
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD2_INT_STATUS__DC_HPD2_INT_STATUS_MASK 0x00000001L
+#define DC_HPD2_INT_STATUS__DC_HPD2_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD2_INT_STATUS__DC_HPD2_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD2_INT_STATUS__DC_HPD2_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_MASK 0x00000002L
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE__SHIFT 0x00000001
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD3_CONTROL__DC_HPD3_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD3_CONTROL__DC_HPD3_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD3_CONTROL__DC_HPD3_EN_MASK 0x10000000L
+#define DC_HPD3_CONTROL__DC_HPD3_EN__SHIFT 0x0000001c
+#define DC_HPD3_CONTROL__DC_HPD3_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD3_CONTROL__DC_HPD3_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_ACK_MASK 0x00000001L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_ACK__SHIFT 0x00000000
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_EN_MASK 0x00010000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_EN__SHIFT 0x00000010
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD3_INT_STATUS__DC_HPD3_INT_STATUS_MASK 0x00000001L
+#define DC_HPD3_INT_STATUS__DC_HPD3_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD3_INT_STATUS__DC_HPD3_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD3_INT_STATUS__DC_HPD3_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_MASK 0x00000002L
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE__SHIFT 0x00000001
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD4_CONTROL__DC_HPD4_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD4_CONTROL__DC_HPD4_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD4_CONTROL__DC_HPD4_EN_MASK 0x10000000L
+#define DC_HPD4_CONTROL__DC_HPD4_EN__SHIFT 0x0000001c
+#define DC_HPD4_CONTROL__DC_HPD4_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD4_CONTROL__DC_HPD4_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_ACK_MASK 0x00000001L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_ACK__SHIFT 0x00000000
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_EN_MASK 0x00010000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_EN__SHIFT 0x00000010
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD4_INT_STATUS__DC_HPD4_INT_STATUS_MASK 0x00000001L
+#define DC_HPD4_INT_STATUS__DC_HPD4_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD4_INT_STATUS__DC_HPD4_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD4_INT_STATUS__DC_HPD4_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_MASK 0x00000002L
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE__SHIFT 0x00000001
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD5_CONTROL__DC_HPD5_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD5_CONTROL__DC_HPD5_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD5_CONTROL__DC_HPD5_EN_MASK 0x10000000L
+#define DC_HPD5_CONTROL__DC_HPD5_EN__SHIFT 0x0000001c
+#define DC_HPD5_CONTROL__DC_HPD5_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD5_CONTROL__DC_HPD5_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_ACK_MASK 0x00000001L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_ACK__SHIFT 0x00000000
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_EN_MASK 0x00010000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_EN__SHIFT 0x00000010
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD5_INT_STATUS__DC_HPD5_INT_STATUS_MASK 0x00000001L
+#define DC_HPD5_INT_STATUS__DC_HPD5_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD5_INT_STATUS__DC_HPD5_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD5_INT_STATUS__DC_HPD5_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_MASK 0x00000002L
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE__SHIFT 0x00000001
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD6_CONTROL__DC_HPD6_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD6_CONTROL__DC_HPD6_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD6_CONTROL__DC_HPD6_EN_MASK 0x10000000L
+#define DC_HPD6_CONTROL__DC_HPD6_EN__SHIFT 0x0000001c
+#define DC_HPD6_CONTROL__DC_HPD6_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD6_CONTROL__DC_HPD6_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_ACK_MASK 0x00000001L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_ACK__SHIFT 0x00000000
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_EN_MASK 0x00010000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_EN__SHIFT 0x00000010
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD6_INT_STATUS__DC_HPD6_INT_STATUS_MASK 0x00000001L
+#define DC_HPD6_INT_STATUS__DC_HPD6_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD6_INT_STATUS__DC_HPD6_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD6_INT_STATUS__DC_HPD6_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_MASK 0x00000002L
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE__SHIFT 0x00000001
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER_MASK 0x00000100L
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER__SHIFT 0x00000008
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER_MASK 0x00001000L
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER__SHIFT 0x0000000c
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG_MASK 0x02000000L
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG__SHIFT 0x00000019
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ_MASK 0x01000000L
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ__SHIFT 0x00000018
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO_MASK 0x00000010L
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO__SHIFT 0x00000004
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS_MASK 0x0000000cL
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS__SHIFT 0x00000002
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG_MASK 0x00200000L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG__SHIFT 0x00000015
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_MASK 0x00000003L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY__SHIFT 0x00000000
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ_MASK 0x00100000L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ__SHIFT 0x00000014
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL_MASK 0x80000000L
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL__SHIFT 0x0000001f
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT_MASK 0x00000700L
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT__SHIFT 0x00000008
+#define DC_I2C_CONTROL__DC_I2C_GO_MASK 0x00000001L
+#define DC_I2C_CONTROL__DC_I2C_GO__SHIFT 0x00000000
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET_MASK 0x00000004L
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET__SHIFT 0x00000002
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET_MASK 0x00000002L
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET__SHIFT 0x00000001
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET_MASK 0x00000008L
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET__SHIFT 0x00000003
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT_MASK 0x00300000L
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT__SHIFT 0x00000014
+#define DC_I2C_DATA__DC_I2C_DATA_MASK 0x0000ff00L
+#define DC_I2C_DATA__DC_I2C_DATA_RW_MASK 0x00000001L
+#define DC_I2C_DATA__DC_I2C_DATA_RW__SHIFT 0x00000000
+#define DC_I2C_DATA__DC_I2C_DATA__SHIFT 0x00000008
+#define DC_I2C_DATA__DC_I2C_INDEX_MASK 0x00ff0000L
+#define DC_I2C_DATA__DC_I2C_INDEX__SHIFT 0x00000010
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE_MASK 0x80000000L
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE__SHIFT 0x0000001f
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID_MASK 0x00f00000L
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID__SHIFT 0x00000014
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET_MASK 0x10000000L
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET__SHIFT 0x0000001c
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME_MASK 0x0000ffffL
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME__SHIFT 0x00000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK_MASK 0x00000020L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK__SHIFT 0x00000005
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT_MASK 0x00000010L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT__SHIFT 0x00000004
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK_MASK 0x00000040L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK__SHIFT 0x00000006
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK_MASK 0x00000200L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK__SHIFT 0x00000009
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT_MASK 0x00000100L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT__SHIFT 0x00000008
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK_MASK 0x00000400L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK__SHIFT 0x0000000a
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK_MASK 0x00002000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK__SHIFT 0x0000000d
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT_MASK 0x00001000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT__SHIFT 0x0000000c
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK_MASK 0x00004000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK__SHIFT 0x0000000e
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK_MASK 0x00020000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK__SHIFT 0x00000011
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT_MASK 0x00010000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT__SHIFT 0x00000010
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK_MASK 0x00040000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK__SHIFT 0x00000012
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK_MASK 0x00200000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK__SHIFT 0x00000015
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT_MASK 0x00100000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT__SHIFT 0x00000014
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK_MASK 0x00400000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK__SHIFT 0x00000016
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK_MASK 0x02000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK__SHIFT 0x00000019
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT_MASK 0x01000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT__SHIFT 0x00000018
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK_MASK 0x04000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK__SHIFT 0x0000001a
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK_MASK 0x10000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK__SHIFT 0x0000001c
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT_MASK 0x08000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT__SHIFT 0x0000001b
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK_MASK 0x20000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK__SHIFT 0x0000001d
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK_MASK 0x00000002L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK__SHIFT 0x00000001
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT_MASK 0x00000001L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT__SHIFT 0x00000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK_MASK 0x00000004L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK__SHIFT 0x00000002
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK 0x00000010L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED__SHIFT 0x00000004
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW_MASK 0x00000080L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW__SHIFT 0x00000007
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK 0x00000004L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE__SHIFT 0x00000002
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED_MASK 0x00000040L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED__SHIFT 0x00000006
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0_MASK 0x00001000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0__SHIFT 0x0000000c
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1_MASK 0x00002000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1__SHIFT 0x0000000d
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2_MASK 0x00004000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2__SHIFT 0x0000000e
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3_MASK 0x00008000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3__SHIFT 0x0000000f
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ_MASK 0x00040000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ__SHIFT 0x00000012
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS_MASK 0x00000003L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS__SHIFT 0x00000000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK 0x00000100L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK__SHIFT 0x00000008
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK 0x00000020L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT__SHIFT 0x00000005
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0_MASK 0x00000001L
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION0__DC_I2C_START0_MASK 0x00001000L
+#define DC_I2C_TRANSACTION0__DC_I2C_START0__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0_MASK 0x00002000L
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0_MASK 0x00000100L
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1_MASK 0x00000001L
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION1__DC_I2C_START1_MASK 0x00001000L
+#define DC_I2C_TRANSACTION1__DC_I2C_START1__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1_MASK 0x00002000L
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1_MASK 0x00000100L
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2_MASK 0x00000001L
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION2__DC_I2C_START2_MASK 0x00001000L
+#define DC_I2C_TRANSACTION2__DC_I2C_START2__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2_MASK 0x00002000L
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2_MASK 0x00000100L
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3_MASK 0x00000001L
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION3__DC_I2C_START3_MASK 0x00001000L
+#define DC_I2C_TRANSACTION3__DC_I2C_START3__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3_MASK 0x00002000L
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3_MASK 0x00000100L
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3__SHIFT 0x00000008
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL_MASK 0xf8000000L
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL__SHIFT 0x0000001b
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL_MASK 0x0000001fL
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL__SHIFT 0x00000000
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS_MASK 0x00008000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS__SHIFT 0x0000000f
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS_MASK 0x00010000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS__SHIFT 0x00000010
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS_MASK 0x00020000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS__SHIFT 0x00000011
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS_MASK 0x00040000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS__SHIFT 0x00000012
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS_MASK 0x00080000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS__SHIFT 0x00000013
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS_MASK 0x00100000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS__SHIFT 0x00000014
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS_MASK 0x00200000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS__SHIFT 0x00000015
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS_MASK 0x00000200L
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS__SHIFT 0x00000009
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS_MASK 0x00000800L
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS__SHIFT 0x0000000b
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS_MASK 0x00002000L
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS__SHIFT 0x0000000d
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS_MASK 0x00000040L
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS__SHIFT 0x00000006
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS_MASK 0x00000020L
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS__SHIFT 0x00000005
+#define DCI_CLK_CNTL__DISPCLK_R_DMCU_GATE_DIS_MASK 0x00004000L
+#define DCI_CLK_CNTL__DISPCLK_R_DMCU_GATE_DIS__SHIFT 0x0000000e
+#define DCI_CLK_CNTL__DISPCLK_R_VGA_GATE_DIS_MASK 0x00000400L
+#define DCI_CLK_CNTL__DISPCLK_R_VGA_GATE_DIS__SHIFT 0x0000000a
+#define DCI_CLK_CNTL__DISPCLK_R_VIP_GATE_DIS_MASK 0x00001000L
+#define DCI_CLK_CNTL__DISPCLK_R_VIP_GATE_DIS__SHIFT 0x0000000c
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS_MASK 0x00400000L
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS__SHIFT 0x00000016
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS_MASK 0x00800000L
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS__SHIFT 0x00000017
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS_MASK 0x00000100L
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS__SHIFT 0x00000008
+#define DCI_DEBUG_CONFIG__DCI_DBG_SEL_MASK 0x0000000fL
+#define DCI_DEBUG_CONFIG__DCI_DBG_SEL__SHIFT 0x00000000
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_PWR_STATE_MASK 0x00003000L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000040L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000006
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000002L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000001
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000080L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000007
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_PWR_STATE_MASK 0x00030000L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000200L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000009
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_PWR_STATE_MASK 0x00300000L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000400L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x0000000a
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000800L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x0000000b
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM1_PWR_STATE_MASK 0x00000003L
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM1_PWR_STATE__SHIFT 0x00000000
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM2_PWR_STATE_MASK 0x0000000cL
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM2_PWR_STATE__SHIFT 0x00000002
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM3_PWR_STATE_MASK 0x00000030L
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM3_PWR_STATE__SHIFT 0x00000004
+#define DCI_MEM_PWR_STATE__AZ_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCI_MEM_PWR_STATE__AZ_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCI_MEM_PWR_STATE__DMCU_IRAM_PWR_STATE_MASK 0x30000000L
+#define DCI_MEM_PWR_STATE__DMCU_IRAM_PWR_STATE__SHIFT 0x0000001c
+#define DCI_MEM_PWR_STATE__DMCU_MEM_PWR_STATE_MASK 0x00000003L
+#define DCI_MEM_PWR_STATE__DMCU_MEM_PWR_STATE__SHIFT 0x00000000
+#define DCI_MEM_PWR_STATE__DMIF0_MEM_PWR_STATE_MASK 0x0000000cL
+#define DCI_MEM_PWR_STATE__DMIF0_MEM_PWR_STATE__SHIFT 0x00000002
+#define DCI_MEM_PWR_STATE__DMIF1_MEM_PWR_STATE_MASK 0x00000030L
+#define DCI_MEM_PWR_STATE__DMIF1_MEM_PWR_STATE__SHIFT 0x00000004
+#define DCI_MEM_PWR_STATE__DMIF2_MEM_PWR_STATE_MASK 0x000000c0L
+#define DCI_MEM_PWR_STATE__DMIF2_MEM_PWR_STATE__SHIFT 0x00000006
+#define DCI_MEM_PWR_STATE__DMIF3_MEM_PWR_STATE_MASK 0x00000300L
+#define DCI_MEM_PWR_STATE__DMIF3_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCI_MEM_PWR_STATE__DMIF4_MEM_PWR_STATE_MASK 0x00000c00L
+#define DCI_MEM_PWR_STATE__DMIF4_MEM_PWR_STATE__SHIFT 0x0000000a
+#define DCI_MEM_PWR_STATE__DMIF5_MEM_PWR_STATE_MASK 0x00003000L
+#define DCI_MEM_PWR_STATE__DMIF5_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM1_PWR_STATE_MASK 0x0c000000L
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM1_PWR_STATE__SHIFT 0x0000001a
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM_PWR_STATE_MASK 0x03000000L
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM_PWR_STATE__SHIFT 0x00000018
+#define DCI_MEM_PWR_STATE__FBC_MEM_PWR_STATE_MASK 0x00030000L
+#define DCI_MEM_PWR_STATE__FBC_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCI_MEM_PWR_STATE__MCIF_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCI_MEM_PWR_STATE__MCIF_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCI_MEM_PWR_STATE__VGA_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCI_MEM_PWR_STATE__VGA_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCI_MEM_PWR_STATE__VIP_MEM_PWR_STATE_MASK 0x00300000L
+#define DCI_MEM_PWR_STATE__VIP_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_CLK_TRISTATE_MASK 0x00040000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_CLK_TRISTATE__SHIFT 0x00000012
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_MASK 0x00008000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_PREMUX_MASK 0x00004000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_PREMUX__SHIFT 0x0000000e
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_REG_MASK 0x00002000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_REG__SHIFT 0x0000000d
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0__SHIFT 0x0000000f
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_MASK 0x00100000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_PREMUX_MASK 0x00080000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_PREMUX__SHIFT 0x00000013
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_REG_MASK 0x00010000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_REG__SHIFT 0x00000010
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN__SHIFT 0x00000014
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MASK_REG_MASK 0x00400000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MASK_REG__SHIFT 0x00000016
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MUX_MASK 0x00200000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MUX__SHIFT 0x00000015
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_MASK 0x08000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_PREMUX_MASK 0x04000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_PREMUX__SHIFT 0x0000001a
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0__SHIFT 0x0000001b
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_ENABLE_MASK 0x00800000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_ENABLE__SHIFT 0x00000017
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_HSYNC_TRISTATE_MASK 0x00020000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_HSYNC_TRISTATE__SHIFT 0x00000011
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_RATE_SEL_MASK 0x02000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_RATE_SEL__SHIFT 0x00000019
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_VSYNC_TRISTATE_MASK 0x01000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_VSYNC_TRISTATE__SHIFT 0x00000018
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCLK_C_MASK 0x00001000L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCLK_C__SHIFT 0x0000000c
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_MASK 0x000000c0L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_REG_MASK 0x00000003L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_REG__SHIFT 0x00000000
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0__SHIFT 0x00000006
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_MASK 0x00000c00L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_REG_MASK 0x00000030L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_REG__SHIFT 0x00000004
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN__SHIFT 0x0000000a
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_MASK_REG_MASK 0x0000000cL
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_MASK_REG__SHIFT 0x00000002
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_SEL0_MASK 0x00000300L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_SEL0__SHIFT 0x00000008
+#define DCIO_DEBUG2__DCIO_DEBUG2_MASK 0xffffffffL
+#define DCIO_DEBUG2__DCIO_DEBUG2__SHIFT 0x00000000
+#define DCIO_DEBUG3__DCIO_DEBUG3_MASK 0xffffffffL
+#define DCIO_DEBUG3__DCIO_DEBUG3__SHIFT 0x00000000
+#define DCIO_DEBUG4__DCIO_DEBUG4_MASK 0xffffffffL
+#define DCIO_DEBUG4__DCIO_DEBUG4__SHIFT 0x00000000
+#define DCIO_DEBUG5__DCIO_DEBUG5_MASK 0xffffffffL
+#define DCIO_DEBUG5__DCIO_DEBUG5__SHIFT 0x00000000
+#define DCIO_DEBUG6__DCIO_DEBUG6_MASK 0xffffffffL
+#define DCIO_DEBUG6__DCIO_DEBUG6__SHIFT 0x00000000
+#define DCIO_DEBUG7__DCIO_DEBUG7_MASK 0xffffffffL
+#define DCIO_DEBUG7__DCIO_DEBUG7__SHIFT 0x00000000
+#define DCIO_DEBUG8__DCIO_DEBUG8_MASK 0xffffffffL
+#define DCIO_DEBUG8__DCIO_DEBUG8__SHIFT 0x00000000
+#define DCIO_DEBUG9__DCIO_DEBUG9_MASK 0xffffffffL
+#define DCIO_DEBUG9__DCIO_DEBUG9__SHIFT 0x00000000
+#define DCIO_DEBUGA__DCIO_DEBUGA_MASK 0xffffffffL
+#define DCIO_DEBUGA__DCIO_DEBUGA__SHIFT 0x00000000
+#define DCIO_DEBUGB__DCIO_DEBUGB_MASK 0xffffffffL
+#define DCIO_DEBUGB__DCIO_DEBUGB__SHIFT 0x00000000
+#define DCIO_DEBUGC__DCIO_DEBUGC_MASK 0xffffffffL
+#define DCIO_DEBUGC__DCIO_DEBUGC__SHIFT 0x00000000
+#define DCIO_DEBUG__DCIO_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG__DCIO_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUGD__DCIO_DEBUGD_MASK 0xffffffffL
+#define DCIO_DEBUGD__DCIO_DEBUGD__SHIFT 0x00000000
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID_MASK 0xffffffffL
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID__SHIFT 0x00000000
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL_MASK 0x00000030L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL__SHIFT 0x00000004
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK_MASK 0x00000300L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK__SHIFT 0x00000008
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL_MASK 0x00000003L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL_MASK 0x00300000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL__SHIFT 0x00000014
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK_MASK 0x03000000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK__SHIFT 0x00000018
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL_MASK 0x00030000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL__SHIFT 0x00000010
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL_MASK 0x00000030L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL__SHIFT 0x00000004
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK_MASK 0x00000300L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK__SHIFT 0x00000008
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL_MASK 0x00000003L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL_MASK 0x00300000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL__SHIFT 0x00000014
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK_MASK 0x03000000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK__SHIFT 0x00000018
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL_MASK 0x00030000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL__SHIFT 0x00000010
+#define DCIO_IMPCAL_CNTL_AB__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_AB__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET_MASK 0x00000010L
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET__SHIFT 0x00000004
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET_MASK 0x00000020L
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET__SHIFT 0x00000005
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET_MASK 0x00000040L
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET__SHIFT 0x00000006
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET_MASK 0x00000080L
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET__SHIFT 0x00000007
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET_MASK 0x00000100L
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET__SHIFT 0x00000008
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET_MASK 0x00000200L
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET__SHIFT 0x00000009
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET_MASK 0x00001000L
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET__SHIFT 0x0000000c
+#define DCI_SOFT_RESET__FBC_SOFT_RESET_MASK 0x00000008L
+#define DCI_SOFT_RESET__FBC_SOFT_RESET__SHIFT 0x00000003
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET_MASK 0x00000004L
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET__SHIFT 0x00000002
+#define DCI_SOFT_RESET__VGA_SOFT_RESET_MASK 0x00000001L
+#define DCI_SOFT_RESET__VGA_SOFT_RESET__SHIFT 0x00000000
+#define DCI_SOFT_RESET__VIP_SOFT_RESET_MASK 0x00000002L
+#define DCI_SOFT_RESET__VIP_SOFT_RESET__SHIFT 0x00000001
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE_MASK 0x000003ffL
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE__SHIFT 0x00000000
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN_MASK 0x000ffc00L
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN__SHIFT 0x0000000a
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED_MASK 0x3ff00000L
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED__SHIFT 0x00000014
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE_MASK 0x00000002L
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE__SHIFT 0x00000001
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_MASK 0x00000001L
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED__SHIFT 0x00000000
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN_MASK 0x00000020L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN__SHIFT 0x00000005
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT_MASK 0x000000c0L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT__SHIFT 0x00000006
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN_MASK 0x00000010L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN__SHIFT 0x00000004
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN_MASK 0x00002000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN__SHIFT 0x0000000d
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT_MASK 0x0000c000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT__SHIFT 0x0000000e
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN_MASK 0x00001000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN__SHIFT 0x0000000c
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN_MASK 0x00200000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN__SHIFT 0x00000015
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT_MASK 0x00c00000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT__SHIFT 0x00000016
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN_MASK 0x00100000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN__SHIFT 0x00000014
+#define DC_LUT_CONTROL__DC_LUT_INC_B_MASK 0x0000000fL
+#define DC_LUT_CONTROL__DC_LUT_INC_B__SHIFT 0x00000000
+#define DC_LUT_CONTROL__DC_LUT_INC_G_MASK 0x00000f00L
+#define DC_LUT_CONTROL__DC_LUT_INC_G__SHIFT 0x00000008
+#define DC_LUT_CONTROL__DC_LUT_INC_R_MASK 0x000f0000L
+#define DC_LUT_CONTROL__DC_LUT_INC_R__SHIFT 0x00000010
+#define DC_LUT_PWL_DATA__DC_LUT_BASE_MASK 0x0000ffffL
+#define DC_LUT_PWL_DATA__DC_LUT_BASE__SHIFT 0x00000000
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA_MASK 0xffff0000L
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA__SHIFT 0x00000010
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX_MASK 0x000000ffL
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX__SHIFT 0x00000000
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE_MASK 0x00000001L
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE__SHIFT 0x00000000
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR_MASK 0x0000ffffL
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR__SHIFT 0x00000000
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE_MASK 0x00000001L
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED__SHIFT 0x00000000
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK_MASK 0x00000007L
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK__SHIFT 0x00000000
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS_MASK 0x80000000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS__SHIFT 0x0000001f
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP_MASK 0x10000000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP__SHIFT 0x0000001c
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE_MASK 0x00001000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE__SHIFT 0x0000000c
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO_MASK 0x00010000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO__SHIFT 0x00000010
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL_MASK 0x00000100L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL__SHIFT 0x00000008
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS_MASK 0x00100000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS__SHIFT 0x00000014
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE_MASK 0x00000003L
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE__SHIFT 0x00000000
+#define DCO_CLK_CNTL__DCO_TEST_CLK_SEL_MASK 0x0000001fL
+#define DCO_CLK_CNTL__DCO_TEST_CLK_SEL__SHIFT 0x00000000
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS_MASK 0x00000040L
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS__SHIFT 0x00000006
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS_MASK 0x00000100L
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS__SHIFT 0x00000008
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS_MASK 0x00000200L
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS__SHIFT 0x00000009
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS_MASK 0x01000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS__SHIFT 0x00000018
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS_MASK 0x02000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS__SHIFT 0x00000019
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS_MASK 0x04000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS__SHIFT 0x0000001a
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS_MASK 0x08000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS__SHIFT 0x0000001b
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS_MASK 0x10000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS__SHIFT 0x0000001c
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS_MASK 0x20000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS__SHIFT 0x0000001d
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS_MASK 0x00000080L
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS__SHIFT 0x00000007
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS_MASK 0x00010000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS__SHIFT 0x00000010
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS_MASK 0x00020000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS__SHIFT 0x00000011
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS_MASK 0x00040000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS__SHIFT 0x00000012
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS_MASK 0x00080000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS__SHIFT 0x00000013
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS_MASK 0x00100000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS__SHIFT 0x00000014
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS_MASK 0x00200000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS__SHIFT 0x00000015
+#define DCO_CLK_CNTL__DISPCLK_R_ABM_GATE_DIS_MASK 0x00001000L
+#define DCO_CLK_CNTL__DISPCLK_R_ABM_GATE_DIS__SHIFT 0x0000000c
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS_MASK 0x00000020L
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS__SHIFT 0x00000005
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_ABM_RAMP_DIS_MASK 0x00000040L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_ABM_RAMP_DIS__SHIFT 0x00000006
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACA_RAMP_DIS_MASK 0x00000100L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACA_RAMP_DIS__SHIFT 0x00000008
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACB_RAMP_DIS_MASK 0x00000200L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACB_RAMP_DIS__SHIFT 0x00000009
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGA_RAMP_DIS_MASK 0x01000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGA_RAMP_DIS__SHIFT 0x00000018
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGB_RAMP_DIS_MASK 0x02000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGB_RAMP_DIS__SHIFT 0x00000019
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGC_RAMP_DIS_MASK 0x04000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGC_RAMP_DIS__SHIFT 0x0000001a
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGD_RAMP_DIS_MASK 0x08000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGD_RAMP_DIS__SHIFT 0x0000001b
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGE_RAMP_DIS_MASK 0x10000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGE_RAMP_DIS__SHIFT 0x0000001c
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGF_RAMP_DIS_MASK 0x20000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGF_RAMP_DIS__SHIFT 0x0000001d
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DVO_RAMP_DIS_MASK 0x00000080L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DVO_RAMP_DIS__SHIFT 0x00000007
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT0_RAMP_DIS_MASK 0x00010000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT0_RAMP_DIS__SHIFT 0x00000010
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT1_RAMP_DIS_MASK 0x00020000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT1_RAMP_DIS__SHIFT 0x00000011
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT2_RAMP_DIS_MASK 0x00040000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT2_RAMP_DIS__SHIFT 0x00000012
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT3_RAMP_DIS_MASK 0x00080000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT3_RAMP_DIS__SHIFT 0x00000013
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT4_RAMP_DIS_MASK 0x00100000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT4_RAMP_DIS__SHIFT 0x00000014
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT5_RAMP_DIS_MASK 0x00200000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT5_RAMP_DIS__SHIFT 0x00000015
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_ABM_RAMP_DIS_MASK 0x00001000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_ABM_RAMP_DIS__SHIFT 0x0000000c
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_DCO_RAMP_DIS_MASK 0x00000020L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_DCO_RAMP_DIS__SHIFT 0x00000005
+#define DCO_LIGHT_SLEEP_DIS__DPA_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCO_LIGHT_SLEEP_DIS__DPA_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCO_LIGHT_SLEEP_DIS__DPA_MEM_SHUTDOWN_DIS_MASK 0x00020000L
+#define DCO_LIGHT_SLEEP_DIS__DPA_MEM_SHUTDOWN_DIS__SHIFT 0x00000011
+#define DCO_LIGHT_SLEEP_DIS__DPB_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCO_LIGHT_SLEEP_DIS__DPB_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCO_LIGHT_SLEEP_DIS__DPB_MEM_SHUTDOWN_DIS_MASK 0x00040000L
+#define DCO_LIGHT_SLEEP_DIS__DPB_MEM_SHUTDOWN_DIS__SHIFT 0x00000012
+#define DCO_LIGHT_SLEEP_DIS__DPC_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCO_LIGHT_SLEEP_DIS__DPC_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCO_LIGHT_SLEEP_DIS__DPC_MEM_SHUTDOWN_DIS_MASK 0x00080000L
+#define DCO_LIGHT_SLEEP_DIS__DPC_MEM_SHUTDOWN_DIS__SHIFT 0x00000013
+#define DCO_LIGHT_SLEEP_DIS__DPD_LIGHT_SLEEP_DIS_MASK 0x00000040L
+#define DCO_LIGHT_SLEEP_DIS__DPD_LIGHT_SLEEP_DIS__SHIFT 0x00000006
+#define DCO_LIGHT_SLEEP_DIS__DPD_MEM_SHUTDOWN_DIS_MASK 0x00100000L
+#define DCO_LIGHT_SLEEP_DIS__DPD_MEM_SHUTDOWN_DIS__SHIFT 0x00000014
+#define DCO_LIGHT_SLEEP_DIS__DPE_LIGHT_SLEEP_DIS_MASK 0x00000080L
+#define DCO_LIGHT_SLEEP_DIS__DPE_LIGHT_SLEEP_DIS__SHIFT 0x00000007
+#define DCO_LIGHT_SLEEP_DIS__DPE_MEM_SHUTDOWN_DIS_MASK 0x00200000L
+#define DCO_LIGHT_SLEEP_DIS__DPE_MEM_SHUTDOWN_DIS__SHIFT 0x00000015
+#define DCO_LIGHT_SLEEP_DIS__DPF_LIGHT_SLEEP_DIS_MASK 0x00000100L
+#define DCO_LIGHT_SLEEP_DIS__DPF_LIGHT_SLEEP_DIS__SHIFT 0x00000008
+#define DCO_LIGHT_SLEEP_DIS__DPF_MEM_SHUTDOWN_DIS_MASK 0x00400000L
+#define DCO_LIGHT_SLEEP_DIS__DPF_MEM_SHUTDOWN_DIS__SHIFT 0x00000016
+#define DCO_LIGHT_SLEEP_DIS__HDMI0_LIGHT_SLEEP_DIS_MASK 0x00000200L
+#define DCO_LIGHT_SLEEP_DIS__HDMI0_LIGHT_SLEEP_DIS__SHIFT 0x00000009
+#define DCO_LIGHT_SLEEP_DIS__HDMI1_LIGHT_SLEEP_DIS_MASK 0x00000400L
+#define DCO_LIGHT_SLEEP_DIS__HDMI1_LIGHT_SLEEP_DIS__SHIFT 0x0000000a
+#define DCO_LIGHT_SLEEP_DIS__HDMI2_LIGHT_SLEEP_DIS_MASK 0x00000800L
+#define DCO_LIGHT_SLEEP_DIS__HDMI2_LIGHT_SLEEP_DIS__SHIFT 0x0000000b
+#define DCO_LIGHT_SLEEP_DIS__HDMI3_LIGHT_SLEEP_DIS_MASK 0x00001000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI3_LIGHT_SLEEP_DIS__SHIFT 0x0000000c
+#define DCO_LIGHT_SLEEP_DIS__HDMI4_LIGHT_SLEEP_DIS_MASK 0x00002000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI4_LIGHT_SLEEP_DIS__SHIFT 0x0000000d
+#define DCO_LIGHT_SLEEP_DIS__HDMI5_LIGHT_SLEEP_DIS_MASK 0x00004000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI5_LIGHT_SLEEP_DIS__SHIFT 0x0000000e
+#define DCO_LIGHT_SLEEP_DIS__I2C_LIGHT_SLEEP_FORCE_MASK 0x00000002L
+#define DCO_LIGHT_SLEEP_DIS__I2C_LIGHT_SLEEP_FORCE__SHIFT 0x00000001
+#define DCO_LIGHT_SLEEP_DIS__MVP_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCO_LIGHT_SLEEP_DIS__MVP_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCO_LIGHT_SLEEP_DIS__MVP_MEM_SHUTDOWN_DIS_MASK 0x00010000L
+#define DCO_LIGHT_SLEEP_DIS__MVP_MEM_SHUTDOWN_DIS__SHIFT 0x00000010
+#define DCO_LIGHT_SLEEP_DIS__TVOUT_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCO_LIGHT_SLEEP_DIS__TVOUT_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCO_MEM_POWER_STATE__DPA_MEM_PWR_STATE_MASK 0x000000c0L
+#define DCO_MEM_POWER_STATE__DPA_MEM_PWR_STATE__SHIFT 0x00000006
+#define DCO_MEM_POWER_STATE__DPB_MEM_PWR_STATE_MASK 0x00000300L
+#define DCO_MEM_POWER_STATE__DPB_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCO_MEM_POWER_STATE__DPC_MEM_PWR_STATE_MASK 0x00000c00L
+#define DCO_MEM_POWER_STATE__DPC_MEM_PWR_STATE__SHIFT 0x0000000a
+#define DCO_MEM_POWER_STATE__DPD_MEM_PWR_STATE_MASK 0x00003000L
+#define DCO_MEM_POWER_STATE__DPD_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCO_MEM_POWER_STATE__DPE_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCO_MEM_POWER_STATE__DPE_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCO_MEM_POWER_STATE__DPF_MEM_PWR_STATE_MASK 0x00030000L
+#define DCO_MEM_POWER_STATE__DPF_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCO_MEM_POWER_STATE__HDMI0_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCO_MEM_POWER_STATE__HDMI0_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCO_MEM_POWER_STATE__HDMI1_MEM_PWR_STATE_MASK 0x00300000L
+#define DCO_MEM_POWER_STATE__HDMI1_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCO_MEM_POWER_STATE__HDMI2_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCO_MEM_POWER_STATE__HDMI2_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCO_MEM_POWER_STATE__HDMI3_MEM_PWR_STATE_MASK 0x03000000L
+#define DCO_MEM_POWER_STATE__HDMI3_MEM_PWR_STATE__SHIFT 0x00000018
+#define DCO_MEM_POWER_STATE__HDMI4_MEM_PWR_STATE_MASK 0x0c000000L
+#define DCO_MEM_POWER_STATE__HDMI4_MEM_PWR_STATE__SHIFT 0x0000001a
+#define DCO_MEM_POWER_STATE__HDMI5_MEM_PWR_STATE_MASK 0x30000000L
+#define DCO_MEM_POWER_STATE__HDMI5_MEM_PWR_STATE__SHIFT 0x0000001c
+#define DCO_MEM_POWER_STATE__I2C_MEM_PWR_STATE_MASK 0x0000000cL
+#define DCO_MEM_POWER_STATE__I2C_MEM_PWR_STATE__SHIFT 0x00000002
+#define DCO_MEM_POWER_STATE__MVP_MEM_PWR_STATE_MASK 0x00000030L
+#define DCO_MEM_POWER_STATE__MVP_MEM_PWR_STATE__SHIFT 0x00000004
+#define DCO_MEM_POWER_STATE__TVOUT_MEM_PWR_STATE_MASK 0x00000003L
+#define DCO_MEM_POWER_STATE__TVOUT_MEM_PWR_STATE__SHIFT 0x00000000
+#define DCO_SOFT_RESET__ABM_SOFT_RESET_MASK 0x02000000L
+#define DCO_SOFT_RESET__ABM_SOFT_RESET__SHIFT 0x00000019
+#define DCO_SOFT_RESET__DACA_CFG_IF_SOFT_RESET_MASK 0x20000000L
+#define DCO_SOFT_RESET__DACA_CFG_IF_SOFT_RESET__SHIFT 0x0000001d
+#define DCO_SOFT_RESET__DACA_SOFT_RESET_MASK 0x00000001L
+#define DCO_SOFT_RESET__DACA_SOFT_RESET__SHIFT 0x00000000
+#define DCO_SOFT_RESET__DACB_SOFT_RESET_MASK 0x00000002L
+#define DCO_SOFT_RESET__DACB_SOFT_RESET__SHIFT 0x00000001
+#define DCO_SOFT_RESET__DVO_ENABLE_RST_MASK 0x00000008L
+#define DCO_SOFT_RESET__DVO_ENABLE_RST__SHIFT 0x00000003
+#define DCO_SOFT_RESET__DVO_SOFT_RESET_MASK 0x08000000L
+#define DCO_SOFT_RESET__DVO_SOFT_RESET__SHIFT 0x0000001b
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET_MASK 0x00010000L
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET__SHIFT 0x00000010
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET_MASK 0x00020000L
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET__SHIFT 0x00000011
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET_MASK 0x00040000L
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET__SHIFT 0x00000012
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET_MASK 0x00080000L
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET__SHIFT 0x00000013
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET_MASK 0x00100000L
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET__SHIFT 0x00000014
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET_MASK 0x00200000L
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET__SHIFT 0x00000015
+#define DCO_SOFT_RESET__MVP_SOFT_RESET_MASK 0x01000000L
+#define DCO_SOFT_RESET__MVP_SOFT_RESET__SHIFT 0x00000018
+#define DCO_SOFT_RESET__SOFT_RESET_DVO_MASK 0x00000004L
+#define DCO_SOFT_RESET__SOFT_RESET_DVO__SHIFT 0x00000002
+#define DCO_SOFT_RESET__SRBM_SOFT_RESET_ENABLE_MASK 0x10000000L
+#define DCO_SOFT_RESET__SRBM_SOFT_RESET_ENABLE__SHIFT 0x0000001c
+#define DCO_SOFT_RESET__TVOUT_SOFT_RESET_MASK 0x04000000L
+#define DCO_SOFT_RESET__TVOUT_SOFT_RESET__SHIFT 0x0000001a
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL_MASK 0x0000000fL
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL__SHIFT 0x00000000
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS_MASK 0x00000030L
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS__SHIFT 0x00000004
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE_MASK 0x00000001L
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE__SHIFT 0x00000000
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL_MASK 0x00000300L
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL__SHIFT 0x00000008
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL_MASK 0x0000001cL
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL__SHIFT 0x00000002
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT_MASK 0xffffffffL
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT__SHIFT 0x00000000
+#define DCP_CRC_LAST__DCP_CRC_LAST_MASK 0xffffffffL
+#define DCP_CRC_LAST__DCP_CRC_LAST__SHIFT 0x00000000
+#define DCP_CRC_MASK__DCP_CRC_MASK_MASK 0xffffffffL
+#define DCP_CRC_MASK__DCP_CRC_MASK__SHIFT 0x00000000
+#define DCP_DEBUG2__DCP_DEBUG2_MASK 0xffffffffL
+#define DCP_DEBUG2__DCP_DEBUG2__SHIFT 0x00000000
+#define DCP_DEBUG__DCP_DEBUG_MASK 0xffffffffL
+#define DCP_DEBUG__DCP_DEBUG__SHIFT 0x00000000
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA_MASK 0x0003ffffL
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA__SHIFT 0x00000000
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX_MASK 0x07f00000L
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX__SHIFT 0x00000014
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG_MASK 0xffff0000L
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG__SHIFT 0x00000010
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS_MASK 0x00000004L
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS__SHIFT 0x00000002
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY_MASK 0x00000001L
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY__SHIFT 0x00000000
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE_MASK 0x00000002L
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE__SHIFT 0x00000001
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG_MASK 0xffffffffL
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG__SHIFT 0x00000000
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG_MASK 0xffffffffL
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG__SHIFT 0x00000000
+#define DCP_GSL_CONTROL__DCP_GSL0_EN_MASK 0x00000001L
+#define DCP_GSL_CONTROL__DCP_GSL0_EN__SHIFT 0x00000000
+#define DCP_GSL_CONTROL__DCP_GSL1_EN_MASK 0x00000002L
+#define DCP_GSL_CONTROL__DCP_GSL1_EN__SHIFT 0x00000001
+#define DCP_GSL_CONTROL__DCP_GSL2_EN_MASK 0x00000004L
+#define DCP_GSL_CONTROL__DCP_GSL2_EN__SHIFT 0x00000002
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING_MASK 0x08000000L
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING__SHIFT 0x0000001b
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY_MASK 0xf0000000L
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY__SHIFT 0x0000001c
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY_MASK 0x0000f000L
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY__SHIFT 0x0000000c
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN_MASK 0x00010000L
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN__SHIFT 0x00000010
+#define DCP_GSL_CONTROL__DCP_GSL_MODE_MASK 0x00000300L
+#define DCP_GSL_CONTROL__DCP_GSL_MODE__SHIFT 0x00000008
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE_MASK 0x03000000L
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE__SHIFT 0x00000018
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000c000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0x0000000e
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS_MASK 0x00000400L
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS__SHIFT 0x0000000a
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS_MASK 0x00010000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS__SHIFT 0x00000010
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD_MASK 0x00002000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD__SHIFT 0x0000000d
+#define DC_PINSTRAPS__DC_PINSTRAPS_VIP_DEVICE_MASK 0x00000800L
+#define DC_PINSTRAPS__DC_PINSTRAPS_VIP_DEVICE__SHIFT 0x0000000b
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP_MASK 0x0000000fL
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP__SHIFT 0x00000000
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP_MASK 0x000000f0L
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP__SHIFT 0x00000004
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED_MASK 0x00ff0000L
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED__SHIFT 0x00000010
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED_MASK 0x0000ff00L
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED__SHIFT 0x00000008
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED_MASK 0x000000ffL
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED__SHIFT 0x00000000
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE_MASK 0x00000100L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE__SHIFT 0x00000008
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE_MASK 0x00000400L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE__SHIFT 0x0000000a
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE_MASK 0x00000200L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE__SHIFT 0x00000009
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH_MASK 0x00000040L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH__SHIFT 0x00000006
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN_MASK 0x00000001L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN__SHIFT 0x00000000
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE_MASK 0x00000030L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE__SHIFT 0x00000004
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_DELAY_MASK 0x00000007L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_DELAY__SHIFT 0x00000000
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_DELAY_MASK 0x00000070L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_DELAY__SHIFT 0x00000004
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_TIMEOUT_DIS_MASK 0x00000080L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_TIMEOUT_DIS__SHIFT 0x00000007
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_DELAY_MASK 0x00000700L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_DELAY__SHIFT 0x00000008
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_TIMEOUT_DIS_MASK 0x00000800L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_TIMEOUT_DIS__SHIFT 0x0000000b
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_DELAY_MASK 0x00007000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_DELAY__SHIFT 0x0000000c
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_TIMEOUT_DIS_MASK 0x00008000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_TIMEOUT_DIS__SHIFT 0x0000000f
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_DELAY_MASK 0x00070000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_DELAY__SHIFT 0x00000010
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_TIMEOUT_DIS_MASK 0x00080000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_TIMEOUT_DIS__SHIFT 0x00000013
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_DELAY_MASK 0x00000007L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_DELAY__SHIFT 0x00000000
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_DELAY_MASK 0x00000070L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_DELAY__SHIFT 0x00000004
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_TIMEOUT_DIS_MASK 0x00000080L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_TIMEOUT_DIS__SHIFT 0x00000007
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL_MASK 0x00000300L
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL__SHIFT 0x00000008
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL_MASK 0x00000003L
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL__SHIFT 0x00000000
+#define DC_XDMA_INTERFACE_CNTL__DC_FLIP_PENDING_TO_DCP_MASK 0x00400000L
+#define DC_XDMA_INTERFACE_CNTL__DC_FLIP_PENDING_TO_DCP__SHIFT 0x00000016
+#define DC_XDMA_INTERFACE_CNTL__DC_XDMA_FLIP_PENDING_MASK 0x00010000L
+#define DC_XDMA_INTERFACE_CNTL__DC_XDMA_FLIP_PENDING__SHIFT 0x00000010
+#define DC_XDMA_INTERFACE_CNTL__XDMA_M_FLIP_PENDING_TO_DCP_MASK 0x00100000L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_M_FLIP_PENDING_TO_DCP__SHIFT 0x00000014
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_ENABLE_MASK 0x0000003fL
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_ENABLE__SHIFT 0x00000000
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_SEL_MASK 0x00000700L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_SEL__SHIFT 0x00000008
+#define DC_XDMA_INTERFACE_CNTL__XDMA_S_FLIP_PENDING_TO_DCP_MASK 0x00200000L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_S_FLIP_PENDING_TO_DCP__SHIFT 0x00000015
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE_MASK 0x00003000L
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE__SHIFT 0x0000000c
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE_MASK 0x00000003L
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE__SHIFT 0x00000000
+#define DEGAMMA_CONTROL__OVL_DEGAMMA_MODE_MASK 0x00000030L
+#define DEGAMMA_CONTROL__OVL_DEGAMMA_MODE__SHIFT 0x00000004
+#define DENORM_CONTROL__DENORM_MODE_MASK 0x00000007L
+#define DENORM_CONTROL__DENORM_MODE__SHIFT 0x00000000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x00080000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x00000013
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE_MASK 0x00018000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE__SHIFT 0x0000000f
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG_MASK 0x00020000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG__SHIFT 0x00000011
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG_MASK 0x00040000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG__SHIFT 0x00000012
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x00007f00L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x00000008
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x0000007fL
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x00000000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE_MASK 0x00100000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE__SHIFT 0x00000014
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG_MASK 0x00200000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG__SHIFT 0x00000015
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG_MASK 0x00400000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG__SHIFT 0x00000016
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER_MASK 0x7f000000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER__SHIFT 0x00000018
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT_MASK 0x00003f00L
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT__SHIFT 0x00000008
+#define DIG_BE_CNTL__DIG_HPD_SELECT_MASK 0x70000000L
+#define DIG_BE_CNTL__DIG_HPD_SELECT__SHIFT 0x0000001c
+#define DIG_BE_CNTL__DIG_MODE_MASK 0x00070000L
+#define DIG_BE_CNTL__DIG_MODE__SHIFT 0x00000010
+#define DIG_BE_EN_CNTL__DIG_ENABLE_MASK 0x00000001L
+#define DIG_BE_EN_CNTL__DIG_ENABLE__SHIFT 0x00000000
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON_MASK 0x00000100L
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON__SHIFT 0x00000008
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN_MASK 0x000003ffL
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN__SHIFT 0x00000000
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT_MASK 0x00000001L
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT__SHIFT 0x00000000
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK_MASK 0x00000100L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK__SHIFT 0x00000008
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK 0x00000010L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK_MASK 0x00001000L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK__SHIFT 0x0000000c
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT__SHIFT 0x00000004
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_MASK 0x00000001L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED__SHIFT 0x00000000
+#define DIG_FE_CNTL__DIG_DUAL_LINK_ENABLE_MASK 0x00010000L
+#define DIG_FE_CNTL__DIG_DUAL_LINK_ENABLE__SHIFT 0x00000010
+#define DIG_FE_CNTL__DIG_RB_SWITCH_EN_MASK 0x00100000L
+#define DIG_FE_CNTL__DIG_RB_SWITCH_EN__SHIFT 0x00000014
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT_MASK 0x00000007L
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT__SHIFT 0x00000000
+#define DIG_FE_CNTL__DIG_START_MASK 0x00000400L
+#define DIG_FE_CNTL__DIG_START__SHIFT 0x0000000a
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN_MASK 0x00000100L
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN__SHIFT 0x00000008
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT_MASK 0x00000070L
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT__SHIFT 0x00000004
+#define DIG_FE_CNTL__DIG_SWAP_MASK 0x00040000L
+#define DIG_FE_CNTL__DIG_SWAP__SHIFT 0x00000012
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON_MASK 0x01000000L
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON__SHIFT 0x00000018
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x00000008
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR_MASK 0x00000001L
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR__SHIFT 0x00000000
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL_MASK 0x001f0000L
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DIG_LANE_ENABLE__DIG_CLK_EN_MASK 0x00000100L
+#define DIG_LANE_ENABLE__DIG_CLK_EN__SHIFT 0x00000008
+#define DIG_LANE_ENABLE__DIG_LANE0EN_MASK 0x00000001L
+#define DIG_LANE_ENABLE__DIG_LANE0EN__SHIFT 0x00000000
+#define DIG_LANE_ENABLE__DIG_LANE1EN_MASK 0x00000002L
+#define DIG_LANE_ENABLE__DIG_LANE1EN__SHIFT 0x00000001
+#define DIG_LANE_ENABLE__DIG_LANE2EN_MASK 0x00000004L
+#define DIG_LANE_ENABLE__DIG_LANE2EN__SHIFT 0x00000002
+#define DIG_LANE_ENABLE__DIG_LANE3EN_MASK 0x00000008L
+#define DIG_LANE_ENABLE__DIG_LANE3EN__SHIFT 0x00000003
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL_MASK 0x00000300L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL__SHIFT 0x00000008
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN_MASK 0x00000001L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN__SHIFT 0x00000000
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL_MASK 0x00000010L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL__SHIFT 0x00000004
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT_MASK 0x3fffffffL
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT__SHIFT 0x00000000
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED_MASK 0x00ffffffL
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED__SHIFT 0x00000000
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY_MASK 0x01000000L
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY__SHIFT 0x00000018
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET_MASK 0x00000002L
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET__SHIFT 0x00000001
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET_MASK 0x00000001L
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET__SHIFT 0x00000000
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET_MASK 0x00000020L
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET__SHIFT 0x00000005
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET_MASK 0x00000010L
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET__SHIFT 0x00000004
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET_MASK 0x00000200L
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET__SHIFT 0x00000009
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET_MASK 0x00000100L
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET__SHIFT 0x00000008
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET_MASK 0x00002000L
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET__SHIFT 0x0000000d
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET_MASK 0x00001000L
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET__SHIFT 0x0000000c
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET_MASK 0x00020000L
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET__SHIFT 0x00000011
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET_MASK 0x00010000L
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET__SHIFT 0x00000010
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET_MASK 0x00200000L
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET__SHIFT 0x00000015
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET_MASK 0x00100000L
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET__SHIFT 0x00000014
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL_MASK 0x00000002L
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL__SHIFT 0x00000001
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN_MASK 0x00000010L
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN__SHIFT 0x00000004
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET_MASK 0x00000020L
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET__SHIFT 0x00000005
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN_MASK 0x03ff0000L
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN__SHIFT 0x00000010
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN_MASK 0x00000040L
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN__SHIFT 0x00000006
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN_MASK 0x00000001L
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN__SHIFT 0x00000000
+#define DIG_TEST_PATTERN__LVDS_EYE_PATTERN_MASK 0x00000100L
+#define DIG_TEST_PATTERN__LVDS_EYE_PATTERN__SHIFT 0x00000008
+#define DIG_TEST_PATTERN__LVDS_TEST_CLOCK_DATA_MASK 0x00000004L
+#define DIG_TEST_PATTERN__LVDS_TEST_CLOCK_DATA__SHIFT 0x00000002
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN_MASK 0x40000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN__SHIFT 0x0000001e
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET_MASK 0x10000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET__SHIFT 0x0000001c
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE_MASK 0x20000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE__SHIFT 0x0000001d
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE_MASK 0x80000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE__SHIFT 0x0000001f
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE_MASK 0x00100000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE__SHIFT 0x00000014
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES_MASK 0x0e000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES__SHIFT 0x00000019
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY_MASK 0x00003fffL
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY__SHIFT 0x00000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE_MASK 0x000f0000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_MASK 0x40000000L
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT__SHIFT 0x0000001e
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT_MASK 0x10000000L
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT__SHIFT 0x0000001c
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT_MASK 0x20000000L
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT__SHIFT 0x0000001d
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_TIMER_INTERRUPT_MASK 0x01000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_TIMER_INTERRUPT__SHIFT 0x00000018
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT_MASK 0x00400000L
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT__SHIFT 0x00000016
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT_MASK 0x00800000L
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT__SHIFT 0x00000017
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT_MASK 0x02000000L
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT__SHIFT 0x00000019
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT_MASK 0x01000000L
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT__SHIFT 0x00000018
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT_MASK 0x00200000L
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT__SHIFT 0x00000015
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT_MASK 0x08000000L
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT__SHIFT 0x0000001b
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT_MASK 0x04000000L
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT__SHIFT 0x0000001a
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISPOUT_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL_MASK 0x00000007L
+#define DISPOUT_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL__SHIFT 0x00000000
+#define DISPOUT_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL_MASK 0x00070000L
+#define DISPOUT_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL__SHIFT 0x00000010
+#define DISPPLL_BG_CNTL__DISPPLL_BG_ADJ_MASK 0x000000f0L
+#define DISPPLL_BG_CNTL__DISPPLL_BG_ADJ__SHIFT 0x00000004
+#define DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK 0x00000001L
+#define DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT 0x00000000
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01ffffffL
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x00000000
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x00000019
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK 0x40000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MSK_MASK 0x08000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MSK__SHIFT 0x0000001b
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_RUNNING_MASK 0x04000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_RUNNING__SHIFT 0x0000001a
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT__SHIFT 0x0000001e
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x20000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x0000001d
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_MASK 0x10000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT__SHIFT 0x0000001c
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC_MASK 0x00000004L
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC__SHIFT 0x00000002
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC_MASK 0x00000008L
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC__SHIFT 0x00000003
+#define DMCU_CTRL__DMCU_ENABLE_MASK 0x00000010L
+#define DMCU_CTRL__DMCU_ENABLE__SHIFT 0x00000004
+#define DMCU_CTRL__IGNORE_PWRMGT_MASK 0x00000002L
+#define DMCU_CTRL__IGNORE_PWRMGT__SHIFT 0x00000001
+#define DMCU_CTRL__RESET_UC_MASK 0x00000001L
+#define DMCU_CTRL__RESET_UC__SHIFT 0x00000000
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT_MASK 0xffc00000L
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT__SHIFT 0x00000016
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR_MASK 0x0000ffffL
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR__SHIFT 0x00000000
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE_MASK 0x000f0000L
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE__SHIFT 0x00000010
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE_MASK 0x00100000L
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE__SHIFT 0x00000014
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA_MASK 0xffffffffL
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA__SHIFT 0x00000000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR_MASK 0x0000ffffL
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR__SHIFT 0x00000000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE_MASK 0x000f0000L
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE__SHIFT 0x00000010
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE_MASK 0x00100000L
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE__SHIFT 0x00000014
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA_MASK 0xffffffffL
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA__SHIFT 0x00000000
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC_MASK 0x00000001L
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC__SHIFT 0x00000000
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST_MASK 0x00800000L
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST__SHIFT 0x00000017
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE_MASK 0x007f0000L
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE__SHIFT 0x00000010
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS_MASK 0x0000000cL
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS__SHIFT 0x00000002
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS_MASK 0x00000003L
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS__SHIFT 0x00000000
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI_MASK 0xffffffffL
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI__SHIFT 0x00000000
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO_MASK 0xffffffffL
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO__SHIFT 0x00000000
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT_MASK 0x00ff0000L
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT__SHIFT 0x00000010
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT_MASK 0x000000ffL
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT__SHIFT 0x00000000
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT_MASK 0x0000ff00L
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR_MASK 0x00000004L
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR__SHIFT 0x00000002
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED_MASK 0x00000004L
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED__SHIFT 0x00000002
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR_MASK 0x00000001L
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR__SHIFT 0x00000000
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED_MASK 0x00000001L
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED__SHIFT 0x00000000
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR_MASK 0x00000002L
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR__SHIFT 0x00000001
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED_MASK 0x00000002L
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED__SHIFT 0x00000001
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR_MASK 0x00040000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR__SHIFT 0x00000012
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED_MASK 0x00040000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000012
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR_MASK 0x00001000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED_MASK 0x00001000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR_MASK 0x00080000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR__SHIFT 0x00000013
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED_MASK 0x00080000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000013
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR_MASK 0x00002000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED_MASK 0x00002000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR_MASK 0x00100000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR__SHIFT 0x00000014
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED_MASK 0x00100000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000014
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR_MASK 0x00004000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED_MASK 0x00004000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR_MASK 0x00200000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR__SHIFT 0x00000015
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED_MASK 0x00200000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000015
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR_MASK 0x00008000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED_MASK 0x00008000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR_MASK 0x00400000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR__SHIFT 0x00000016
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED_MASK 0x00400000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000016
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR_MASK 0x00010000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR__SHIFT 0x00000010
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED_MASK 0x00010000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED__SHIFT 0x00000010
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR_MASK 0x00800000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR__SHIFT 0x00000017
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED_MASK 0x00800000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000017
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR_MASK 0x00020000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR__SHIFT 0x00000011
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED_MASK 0x00020000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED__SHIFT 0x00000011
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR_MASK 0x00000100L
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED_MASK 0x00000100L
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED_MASK 0x00000008L
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED__SHIFT 0x00000003
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED_MASK 0x00000200L
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED__SHIFT 0x00000009
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR_MASK 0x00000400L
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED_MASK 0x00000400L
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR_MASK 0x00000800L
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED_MASK 0x00000800L
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR_MASK 0x01000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR__SHIFT 0x00000018
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED_MASK 0x01000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED__SHIFT 0x00000018
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR_MASK 0x02000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR__SHIFT 0x00000019
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED_MASK 0x02000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED__SHIFT 0x00000019
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR_MASK 0x04000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED_MASK 0x04000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR_MASK 0x08000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED_MASK 0x08000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR_MASK 0x10000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED_MASK 0x10000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR_MASK 0x20000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED_MASK 0x20000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_MASK_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_MASK__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_MASK_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_MASK__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_MASK_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_MASK__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_MASK_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_MASK__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_MASK_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_MASK__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_MASK_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_MASK__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_MASK_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_MASK__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_MASK_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_MASK__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_MASK_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_MASK__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_MASK_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_MASK__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_MASK_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_MASK__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_MASK_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_MASK__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK_MASK 0x00000200L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK__SHIFT 0x00000009
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK_MASK 0x00000400L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK_MASK 0x00000800L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN_MASK 0x00000100L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN__SHIFT 0x00000008
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN_MASK 0x00000008L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN__SHIFT 0x00000003
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN_MASK 0x01000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN__SHIFT 0x00000018
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN_MASK 0x02000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN__SHIFT 0x00000019
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN_MASK 0x04000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN_MASK 0x08000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN_MASK 0x10000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN_MASK 0x20000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL_MASK 0x00000100L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL__SHIFT 0x00000008
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL_MASK 0x00000008L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000003
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL_MASK 0x01000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL__SHIFT 0x00000018
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL_MASK 0x02000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL__SHIFT 0x00000019
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL_MASK 0x04000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL_MASK 0x08000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL_MASK 0x10000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL_MASK 0x20000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001d
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR_MASK 0x000003ffL
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR__SHIFT 0x00000000
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA_MASK 0x000000ffL
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA__SHIFT 0x00000000
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR_MASK 0x000003ffL
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR__SHIFT 0x00000000
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA_MASK 0x000000ffL
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA__SHIFT 0x00000000
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN_MASK 0x00000010L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN__SHIFT 0x00000004
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC_MASK 0x00000002L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC__SHIFT 0x00000001
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC_MASK 0x00000001L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC__SHIFT 0x00000000
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN_MASK 0x00000020L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN__SHIFT 0x00000005
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC_MASK 0x00000008L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC__SHIFT 0x00000003
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC_MASK 0x00000004L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC__SHIFT 0x00000002
+#define DMCU_RAM_ACCESS_CTRL__UC_RST_RELEASE_DELAY_CNT_MASK 0x0000ff00L
+#define DMCU_RAM_ACCESS_CTRL__UC_RST_RELEASE_DELAY_CNT__SHIFT 0x00000008
+#define DMCU_STATUS__UC_IN_RESET_MASK 0x00000001L
+#define DMCU_STATUS__UC_IN_RESET__SHIFT 0x00000000
+#define DMCU_STATUS__UC_IN_STOP_MODE_MASK 0x00000004L
+#define DMCU_STATUS__UC_IN_STOP_MODE__SHIFT 0x00000002
+#define DMCU_STATUS__UC_IN_WAIT_MODE_MASK 0x00000002L
+#define DMCU_STATUS__UC_IN_WAIT_MODE__SHIFT 0x00000001
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY_MASK 0x00000700L
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY__SHIFT 0x00000008
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY_MASK 0x00000007L
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY__SHIFT 0x00000000
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN_MASK 0x00010000L
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN__SHIFT 0x00000010
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP_MASK 0x00000008L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP__SHIFT 0x00000003
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN_MASK 0x00000001L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN__SHIFT 0x00000000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE_MASK 0x00004000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE__SHIFT 0x0000000e
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW_MASK 0x00008000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW__SHIFT 0x0000000f
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT_MASK 0x00000200L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT__SHIFT 0x00000009
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT_MASK 0x00000004L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT__SHIFT 0x00000002
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1_MASK 0x00002000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1__SHIFT 0x0000000d
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2_MASK 0x00001000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2__SHIFT 0x0000000c
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3_MASK 0x00000800L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3__SHIFT 0x0000000b
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5_MASK 0x00000400L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5__SHIFT 0x0000000a
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1_MASK 0x00000080L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1__SHIFT 0x00000007
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2_MASK 0x00000040L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2__SHIFT 0x00000006
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3_MASK 0x00000020L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3__SHIFT 0x00000005
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4_MASK 0x00000010L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4__SHIFT 0x00000004
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW_MASK 0x00000100L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW__SHIFT 0x00000008
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN_MASK 0x00000002L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN__SHIFT 0x00000001
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE_MASK 0x30000000L
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE__SHIFT 0x0000001c
+#define DMIF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define DMIF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define DMIF_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define DMIF_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define DMIF_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define DMIF_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define DMIF_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define DMIF_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define DMIF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define DMIF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define DMIF_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define DMIF_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define DMIF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define DMIF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD_MASK 0x0000ffffL
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD__SHIFT 0x00000000
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT_MASK 0xffff0000L
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT__SHIFT 0x00000010
+#define DMIF_CONTROL__DMIF_BUFF_SIZE_MASK 0x00000003L
+#define DMIF_CONTROL__DMIF_BUFF_SIZE__SHIFT 0x00000000
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN_MASK 0x60000000L
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN__SHIFT 0x0000001d
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION_MASK 0x1f000000L
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION__SHIFT 0x00000018
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT_MASK 0x00000010L
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT__SHIFT 0x00000004
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE_MASK 0x0000f000L
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE__SHIFT 0x0000000c
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK_MASK 0x00000004L
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK__SHIFT 0x00000002
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS_MASK 0x003f0000L
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS__SHIFT 0x00000010
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE_MASK 0x00000700L
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE__SHIFT 0x00000008
+#define DMIF_DEBUG02_CORE0__DB_DATA_MASK 0x0000ffffL
+#define DMIF_DEBUG02_CORE0__DB_DATA__SHIFT 0x00000000
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN_MASK 0x00010000L
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN__SHIFT 0x00000010
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER_MASK 0x0ffe0000L
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER__SHIFT 0x00000011
+#define DMIF_DEBUG02_CORE1__DB_DATA_MASK 0x0000ffffL
+#define DMIF_DEBUG02_CORE1__DB_DATA__SHIFT 0x00000000
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN_MASK 0x00010000L
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN__SHIFT 0x00000010
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER_MASK 0x0ffe0000L
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER__SHIFT 0x00000011
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG_MASK 0xffffffffL
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG__SHIFT 0x00000000
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS_MASK 0x00000100L
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS__SHIFT 0x00000008
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS_MASK 0x00000200L
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS__SHIFT 0x00000009
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS_MASK 0x00000001L
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS__SHIFT 0x00000000
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS_MASK 0x00000002L
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS__SHIFT 0x00000001
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS_MASK 0x00000004L
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS__SHIFT 0x00000002
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS_MASK 0x00000008L
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS__SHIFT 0x00000003
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS_MASK 0x00000010L
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS__SHIFT 0x00000004
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS_MASK 0x00000020L
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS__SHIFT 0x00000005
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE_MASK 0x00003f00L
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE__SHIFT 0x00000008
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x00010000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x00000010
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT_MASK 0x00700000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT__SHIFT 0x00000014
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x00020000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x00000011
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE_MASK 0x0000003fL
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE__SHIFT 0x00000000
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT_MASK 0x07000000L
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT__SHIFT 0x00000018
+#define DMIF_STATUS__DMIF_UNDERFLOW_MASK 0x10000000L
+#define DMIF_STATUS__DMIF_UNDERFLOW__SHIFT 0x0000001c
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT_MASK 0x00000070L
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT__SHIFT 0x00000004
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT_MASK 0x00000007L
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT__SHIFT 0x00000000
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF_MASK 0x00000100L
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF__SHIFT 0x00000008
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET_MASK 0x00000001L
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET__SHIFT 0x00000000
+#define DOUT_SCRATCH0__DOUT_SCRATCH0_MASK 0xffffffffL
+#define DOUT_SCRATCH0__DOUT_SCRATCH0__SHIFT 0x00000000
+#define DOUT_SCRATCH1__DOUT_SCRATCH1_MASK 0xffffffffL
+#define DOUT_SCRATCH1__DOUT_SCRATCH1__SHIFT 0x00000000
+#define DOUT_SCRATCH2__DOUT_SCRATCH2_MASK 0xffffffffL
+#define DOUT_SCRATCH2__DOUT_SCRATCH2__SHIFT 0x00000000
+#define DOUT_SCRATCH3__DOUT_SCRATCH3_MASK 0xffffffffL
+#define DOUT_SCRATCH3__DOUT_SCRATCH3__SHIFT 0x00000000
+#define DOUT_SCRATCH4__DOUT_SCRATCH4_MASK 0xffffffffL
+#define DOUT_SCRATCH4__DOUT_SCRATCH4__SHIFT 0x00000000
+#define DOUT_SCRATCH5__DOUT_SCRATCH5_MASK 0xffffffffL
+#define DOUT_SCRATCH5__DOUT_SCRATCH5__SHIFT 0x00000000
+#define DOUT_SCRATCH6__DOUT_SCRATCH6_MASK 0xffffffffL
+#define DOUT_SCRATCH6__DOUT_SCRATCH6__SHIFT 0x00000000
+#define DOUT_SCRATCH7__DOUT_SCRATCH7_MASK 0xffffffffL
+#define DOUT_SCRATCH7__DOUT_SCRATCH7__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_DATA__DOUT_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DOUT_TEST_DEBUG_DATA__DOUT_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_AUX1_DEBUG_A__DP_AUX1_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_A__DP_AUX1_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_B__DP_AUX1_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_B__DP_AUX1_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_C__DP_AUX1_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_C__DP_AUX1_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_D__DP_AUX1_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_D__DP_AUX1_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_E__DP_AUX1_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_E__DP_AUX1_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_F__DP_AUX1_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_F__DP_AUX1_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_G__DP_AUX1_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_G__DP_AUX1_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_H__DP_AUX1_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_H__DP_AUX1_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_I__DP_AUX1_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_I__DP_AUX1_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_A__DP_AUX2_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_A__DP_AUX2_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_B__DP_AUX2_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_B__DP_AUX2_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_C__DP_AUX2_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_C__DP_AUX2_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_D__DP_AUX2_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_D__DP_AUX2_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_E__DP_AUX2_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_E__DP_AUX2_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_F__DP_AUX2_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_F__DP_AUX2_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_G__DP_AUX2_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_G__DP_AUX2_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_H__DP_AUX2_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_H__DP_AUX2_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_I__DP_AUX2_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_I__DP_AUX2_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_A__DP_AUX3_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_A__DP_AUX3_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_B__DP_AUX3_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_B__DP_AUX3_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_C__DP_AUX3_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_C__DP_AUX3_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_D__DP_AUX3_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_D__DP_AUX3_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_E__DP_AUX3_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_E__DP_AUX3_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_F__DP_AUX3_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_F__DP_AUX3_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_G__DP_AUX3_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_G__DP_AUX3_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_H__DP_AUX3_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_H__DP_AUX3_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_I__DP_AUX3_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_I__DP_AUX3_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_A__DP_AUX4_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_A__DP_AUX4_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_B__DP_AUX4_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_B__DP_AUX4_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_C__DP_AUX4_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_C__DP_AUX4_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_D__DP_AUX4_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_D__DP_AUX4_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_E__DP_AUX4_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_E__DP_AUX4_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_F__DP_AUX4_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_F__DP_AUX4_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_G__DP_AUX4_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_G__DP_AUX4_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_H__DP_AUX4_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_H__DP_AUX4_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_I__DP_AUX4_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_I__DP_AUX4_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_A__DP_AUX5_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_A__DP_AUX5_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_B__DP_AUX5_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_B__DP_AUX5_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_C__DP_AUX5_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_C__DP_AUX5_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_D__DP_AUX5_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_D__DP_AUX5_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_E__DP_AUX5_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_E__DP_AUX5_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_F__DP_AUX5_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_F__DP_AUX5_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_G__DP_AUX5_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_G__DP_AUX5_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_H__DP_AUX5_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_H__DP_AUX5_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_I__DP_AUX5_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_I__DP_AUX5_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_A__DP_AUX6_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_A__DP_AUX6_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_B__DP_AUX6_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_B__DP_AUX6_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_C__DP_AUX6_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_C__DP_AUX6_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_D__DP_AUX6_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_D__DP_AUX6_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_E__DP_AUX6_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_E__DP_AUX6_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_F__DP_AUX6_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_F__DP_AUX6_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_G__DP_AUX6_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_G__DP_AUX6_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_H__DP_AUX6_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_H__DP_AUX6_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_I__DP_AUX6_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_I__DP_AUX6_DEBUG_I__SHIFT 0x00000000
+#define DP_CONFIG__DP_UDI_LANES_MASK 0x00000003L
+#define DP_CONFIG__DP_UDI_LANES__SHIFT 0x00000000
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP_MASK 0x01000000L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP__SHIFT 0x00000018
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP_MASK 0x00010000L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP__SHIFT 0x00000010
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET_MASK 0x00000100L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET__SHIFT 0x00000008
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0_MASK 0x00000001L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0__SHIFT 0x00000000
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1_MASK 0x00000002L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1__SHIFT 0x00000001
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2_MASK 0x00000004L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2__SHIFT 0x00000002
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3_MASK 0x00000008L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3__SHIFT 0x00000003
+#define DP_DPHY_CNTL__DPHY_BYPASS_MASK 0x00010000L
+#define DP_DPHY_CNTL__DPHY_BYPASS__SHIFT 0x00000010
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS_MASK 0x01000000L
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS__SHIFT 0x00000018
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD_MASK 0x00000001L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD__SHIFT 0x00000000
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK_MASK 0x00ff0000L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK__SHIFT 0x00000010
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL_MASK 0x00000030L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL__SHIFT 0x00000004
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN_MASK 0x00000010L
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN__SHIFT 0x00000004
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN_MASK 0x00000001L
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN__SHIFT 0x00000000
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID_MASK 0x00000100L
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT_MASK 0x0000003fL
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT__SHIFT 0x00000000
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT_MASK 0x00003f00L
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK_MASK 0x00010000L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK__SHIFT 0x00000010
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_MASK 0x00000100L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK_MASK 0x00000001L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK__SHIFT 0x00000000
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1_MASK 0x0000ff00L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1__SHIFT 0x00000008
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2_MASK 0x00ff0000L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2__SHIFT 0x00000010
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3_MASK 0xff000000L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3__SHIFT 0x00000018
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT_MASK 0x000000ffL
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT__SHIFT 0x00000000
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME_MASK 0x000fff00L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME__SHIFT 0x00000008
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME_MASK 0xfff00000L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME__SHIFT 0x00000014
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN_MASK 0x00000004L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN__SHIFT 0x00000002
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE_MASK 0x00000001L
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE__SHIFT 0x00000000
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START_MASK 0x00000002L
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START__SHIFT 0x00000001
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK_MASK 0x00001000L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK__SHIFT 0x0000000c
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK_MASK 0x00000100L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK__SHIFT 0x00000008
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED_MASK 0x00000010L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED__SHIFT 0x00000004
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE_MASK 0x00000007L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE__SHIFT 0x00000000
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN_MASK 0x00000001L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN__SHIFT 0x00000000
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED_MASK 0x7fffff00L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED__SHIFT 0x00000008
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL_MASK 0x00000030L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL__SHIFT 0x00000004
+#define DP_DPHY_SYM0__DPHY_SYM1_MASK 0x000003ffL
+#define DP_DPHY_SYM0__DPHY_SYM1__SHIFT 0x00000000
+#define DP_DPHY_SYM0__DPHY_SYM2_MASK 0x000ffc00L
+#define DP_DPHY_SYM0__DPHY_SYM2__SHIFT 0x0000000a
+#define DP_DPHY_SYM0__DPHY_SYM3_MASK 0x3ff00000L
+#define DP_DPHY_SYM0__DPHY_SYM3__SHIFT 0x00000014
+#define DP_DPHY_SYM1__DPHY_SYM4_MASK 0x000003ffL
+#define DP_DPHY_SYM1__DPHY_SYM4__SHIFT 0x00000000
+#define DP_DPHY_SYM1__DPHY_SYM5_MASK 0x000ffc00L
+#define DP_DPHY_SYM1__DPHY_SYM5__SHIFT 0x0000000a
+#define DP_DPHY_SYM1__DPHY_SYM6_MASK 0x3ff00000L
+#define DP_DPHY_SYM1__DPHY_SYM6__SHIFT 0x00000014
+#define DP_DPHY_SYM2__DPHY_SYM7_MASK 0x000003ffL
+#define DP_DPHY_SYM2__DPHY_SYM7__SHIFT 0x00000000
+#define DP_DPHY_SYM2__DPHY_SYM8_MASK 0x000ffc00L
+#define DP_DPHY_SYM2__DPHY_SYM8__SHIFT 0x0000000a
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL_MASK 0x00000003L
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL__SHIFT 0x00000000
+#define DP_DTO0_MODULO__DP_DTO0_MODULO_MASK 0xffffffffL
+#define DP_DTO0_MODULO__DP_DTO0_MODULO__SHIFT 0x00000000
+#define DP_DTO0_PHASE__DP_DTO0_PHASE_MASK 0xffffffffL
+#define DP_DTO0_PHASE__DP_DTO0_PHASE__SHIFT 0x00000000
+#define DP_DTO1_MODULO__DP_DTO1_MODULO_MASK 0xffffffffL
+#define DP_DTO1_MODULO__DP_DTO1_MODULO__SHIFT 0x00000000
+#define DP_DTO1_PHASE__DP_DTO1_PHASE_MASK 0xffffffffL
+#define DP_DTO1_PHASE__DP_DTO1_PHASE__SHIFT 0x00000000
+#define DP_DTO2_MODULO__DP_DTO2_MODULO_MASK 0xffffffffL
+#define DP_DTO2_MODULO__DP_DTO2_MODULO__SHIFT 0x00000000
+#define DP_DTO2_PHASE__DP_DTO2_PHASE_MASK 0xffffffffL
+#define DP_DTO2_PHASE__DP_DTO2_PHASE__SHIFT 0x00000000
+#define DP_DTO3_MODULO__DP_DTO3_MODULO_MASK 0xffffffffL
+#define DP_DTO3_MODULO__DP_DTO3_MODULO__SHIFT 0x00000000
+#define DP_DTO3_PHASE__DP_DTO3_PHASE_MASK 0xffffffffL
+#define DP_DTO3_PHASE__DP_DTO3_PHASE__SHIFT 0x00000000
+#define DP_DTO4_MODULO__DP_DTO4_MODULO_MASK 0xffffffffL
+#define DP_DTO4_MODULO__DP_DTO4_MODULO__SHIFT 0x00000000
+#define DP_DTO4_PHASE__DP_DTO4_PHASE_MASK 0xffffffffL
+#define DP_DTO4_PHASE__DP_DTO4_PHASE__SHIFT 0x00000000
+#define DP_DTO5_MODULO__DP_DTO5_MODULO_MASK 0xffffffffL
+#define DP_DTO5_MODULO__DP_DTO5_MODULO__SHIFT 0x00000000
+#define DP_DTO5_PHASE__DP_DTO5_PHASE_MASK 0xffffffffL
+#define DP_DTO5_PHASE__DP_DTO5_PHASE__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT_MASK 0xffff0000L
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT__SHIFT 0x00000010
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION_MASK 0x0000ffffL
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT_MASK 0x0000ffffL
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000L
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x00000010
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x00000010L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE__SHIFT 0x00000004
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON_MASK 0x00000100L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON__SHIFT 0x00000008
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK_MASK 0x00003000L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK__SHIFT 0x0000000c
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT_MASK 0x00000400L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT__SHIFT 0x0000000a
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON_MASK 0x00000200L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON__SHIFT 0x00000009
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST_MASK 0x00000100L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x00000008
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x00000010L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x00000004
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x00000001L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH__SHIFT 0x00000000
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH_MASK 0x00000010L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH__SHIFT 0x00000004
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH_MASK 0x00000080L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH__SHIFT 0x00000007
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH_MASK 0x00000020L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH__SHIFT 0x00000005
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH_MASK 0x00000040L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH__SHIFT 0x00000006
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH_MASK 0x00000800L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH__SHIFT 0x0000000b
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH_MASK 0x00000400L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH__SHIFT 0x0000000a
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH_MASK 0x00000200L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH__SHIFT 0x00000009
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH_MASK 0x00000100L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x00000008
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x00000010L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR__SHIFT 0x00000004
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC_MASK 0x00000080L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC__SHIFT 0x00000007
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON_MASK 0x00000020L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON__SHIFT 0x00000005
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA_MASK 0x00000040L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA__SHIFT 0x00000006
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON_MASK 0x00000800L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON__SHIFT 0x0000000b
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH_MASK 0x00000400L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH__SHIFT 0x0000000a
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK_MASK 0x00000200L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK__SHIFT 0x00000009
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON_MASK 0x00000100L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON__SHIFT 0x00000008
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK_MASK 0x0000ffffL
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE_MASK 0x00000001L
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE__SHIFT 0x00000000
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE_MASK 0x00020000L
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE__SHIFT 0x00000011
+#define DP_LINK_CNTL__DP_LINK_STATUS_MASK 0x00000100L
+#define DP_LINK_CNTL__DP_LINK_STATUS__SHIFT 0x00000008
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE_MASK 0x00000010L
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE__SHIFT 0x00000004
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL_MASK 0x0003ffffL
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL__SHIFT 0x00000000
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE_MASK 0x01000000L
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE__SHIFT 0x00000018
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE_MASK 0x10000000L
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE__SHIFT 0x0000001c
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE_MASK 0x00000100L
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE__SHIFT 0x00000008
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_MASK 0x000000ffL
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE__SHIFT 0x00000000
+#define DP_MSA_MISC__DP_MSA_MISC1_MASK 0x000000f8L
+#define DP_MSA_MISC__DP_MSA_MISC1__SHIFT 0x00000003
+#define DP_MSA_MISC__DP_MSA_MISC2_MASK 0x0000ff00L
+#define DP_MSA_MISC__DP_MSA_MISC2__SHIFT 0x00000008
+#define DP_MSA_MISC__DP_MSA_MISC3_MASK 0x00ff0000L
+#define DP_MSA_MISC__DP_MSA_MISC3__SHIFT 0x00000010
+#define DP_MSA_MISC__DP_MSA_MISC4_MASK 0xff000000L
+#define DP_MSA_MISC__DP_MSA_MISC4__SHIFT 0x00000018
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN_MASK 0x00000001L
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN__SHIFT 0x00000000
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE_MASK 0x0001fff0L
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE__SHIFT 0x00000004
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE_MASK 0x1fff0000L
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE__SHIFT 0x00000010
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE_MASK 0x00001fffL
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE__SHIFT 0x00000000
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME_MASK 0x000003ffL
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME__SHIFT 0x00000000
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE_MASK 0x00030000L
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE__SHIFT 0x00000010
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE_MASK 0x00000001L
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE__SHIFT 0x00000000
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE_MASK 0x00000010L
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE__SHIFT 0x00000004
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER_MASK 0x00000100L
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER__SHIFT 0x00000008
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X_MASK 0xfc000000L
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X__SHIFT 0x0000001a
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y_MASK 0x03ffffffL
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y__SHIFT 0x00000000
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK 0x00000001L
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING__SHIFT 0x00000000
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0_MASK 0x00003f00L
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0__SHIFT 0x00000008
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1_MASK 0x3f000000L
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1__SHIFT 0x00000018
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0_MASK 0x00000007L
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0__SHIFT 0x00000000
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1_MASK 0x00070000L
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1__SHIFT 0x00000010
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2_MASK 0x00003f00L
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2__SHIFT 0x00000008
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3_MASK 0x3f000000L
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3__SHIFT 0x00000018
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2_MASK 0x00000007L
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2__SHIFT 0x00000000
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3_MASK 0x00070000L
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3__SHIFT 0x00000010
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4_MASK 0x00003f00L
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4__SHIFT 0x00000008
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5_MASK 0x3f000000L
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5__SHIFT 0x00000018
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4_MASK 0x00000007L
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4__SHIFT 0x00000000
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5_MASK 0x00070000L
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5__SHIFT 0x00000010
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT_MASK 0x00000100L
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT__SHIFT 0x00000008
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE_MASK 0x00000003L
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE__SHIFT 0x00000000
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH_MASK 0x07000000L
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH__SHIFT 0x00000018
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE_MASK 0x00000100L
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE__SHIFT 0x00000008
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING_MASK 0x00000003L
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING__SHIFT 0x00000000
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE_MASK 0x00010000L
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE__SHIFT 0x00000010
+#define DP_SEC_AUD_M__DP_SEC_AUD_M_MASK 0x00ffffffL
+#define DP_SEC_AUD_M__DP_SEC_AUD_M__SHIFT 0x00000000
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK_MASK 0x00ffffffL
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK__SHIFT 0x00000000
+#define DP_SEC_AUD_N__DP_SEC_AUD_N_MASK 0x00ffffffL
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__SHIFT 0x00000000
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK_MASK 0x00ffffffL
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK__SHIFT 0x00000000
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE_MASK 0x00000001L
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE__SHIFT 0x00000000
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE_MASK 0x00010000L
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE__SHIFT 0x00000010
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE_MASK 0x00001000L
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE__SHIFT 0x0000000c
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE_MASK 0x00000010L
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE__SHIFT 0x00000004
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE_MASK 0x00000100L
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE__SHIFT 0x00000008
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE_MASK 0x01000000L
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE__SHIFT 0x00000018
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE_MASK 0x00100000L
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE__SHIFT 0x00000014
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE_MASK 0x00200000L
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE__SHIFT 0x00000015
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE_MASK 0x00400000L
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE__SHIFT 0x00000016
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE_MASK 0x00800000L
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE__SHIFT 0x00000017
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE_MASK 0x10000000L
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE__SHIFT 0x0000001c
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE_MASK 0x00000001L
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE__SHIFT 0x00000000
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION_MASK 0x00000fffL
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION__SHIFT 0x00000000
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION_MASK 0x0000ffffL
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION__SHIFT 0x00000000
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE_MASK 0x00003fffL
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE__SHIFT 0x00000000
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_MASK 0x10000000L
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE__SHIFT 0x0000001c
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS_MASK 0x20000000L
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS__SHIFT 0x0000001d
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK_MASK 0x01000000L
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK__SHIFT 0x00000018
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS_MASK 0x00100000L
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS__SHIFT 0x00000014
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE_MASK 0x00010000L
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE__SHIFT 0x00000010
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE_MASK 0x0000000eL
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE__SHIFT 0x00000001
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY_MASK 0x00000010L
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY__SHIFT 0x00000004
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION_MASK 0x00003f00L
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION__SHIFT 0x00000008
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE_MASK 0x00000001L
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__SHIFT 0x00000000
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET_MASK 0x00000001L
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET__SHIFT 0x00000000
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK_MASK 0x00000040L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK__SHIFT 0x00000006
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG_MASK 0x00000010L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG__SHIFT 0x00000004
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT_MASK 0x00000020L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT__SHIFT 0x00000005
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK_MASK 0x00000080L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK__SHIFT 0x00000007
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK_MASK 0x00001000L
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK__SHIFT 0x0000000c
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG_MASK 0x00000100L
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG__SHIFT 0x00000008
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK_MASK 0x00000002L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK__SHIFT 0x00000001
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT_MASK 0x00000001L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT__SHIFT 0x00000000
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK_MASK 0x00000004L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK__SHIFT 0x00000002
+#define DP_VID_M__DP_VID_M_MASK 0x00ffffffL
+#define DP_VID_M__DP_VID_M__SHIFT 0x00000000
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION_MASK 0x00000fffL
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION__SHIFT 0x00000000
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE_MASK 0x00010000L
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE__SHIFT 0x00000010
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL_MASK 0x01000000L
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL__SHIFT 0x00000018
+#define DP_VID_N__DP_VID_N_MASK 0x00ffffffL
+#define DP_VID_N__DP_VID_N__SHIFT 0x00000000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT_MASK 0x00100000L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT__SHIFT 0x00000014
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER_MASK 0x00000300L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER__SHIFT 0x00000008
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE_MASK 0x00000001L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE__SHIFT 0x00000000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS_MASK 0x00010000L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS__SHIFT 0x00000010
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN_MASK 0x00000100L
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN__SHIFT 0x00000008
+#define DP_VID_TIMING__DP_VID_N_DIV_MASK 0xff000000L
+#define DP_VID_TIMING__DP_VID_N_DIV__SHIFT 0x00000018
+#define DP_VID_TIMING__DP_VID_TIMING_MODE_MASK 0x00000001L
+#define DP_VID_TIMING__DP_VID_TIMING_MODE__SHIFT 0x00000000
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKC_CNTL__DVOACLKC_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKC_CNTL__DVOACLKC_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKC_CNTL__DVOACLKC_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKC_CNTL__DVOACLKC_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKC_CNTL__DVOACLKC_IN_PHASE_MASK 0x00040000L
+#define DVOACLKC_CNTL__DVOACLKC_IN_PHASE__SHIFT 0x00000012
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_IN_PHASE_MASK 0x00040000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_IN_PHASE__SHIFT 0x00000012
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_SKEW_PHASE_OVERRIDE_MASK 0x00100000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_SKEW_PHASE_OVERRIDE__SHIFT 0x00000014
+#define DVOACLKC_MVP_CNTL__MVP_CLK_A_SRC_SEL_MASK 0x03000000L
+#define DVOACLKC_MVP_CNTL__MVP_CLK_A_SRC_SEL__SHIFT 0x00000018
+#define DVOACLKC_MVP_CNTL__MVP_CLK_B_SRC_SEL_MASK 0x30000000L
+#define DVOACLKC_MVP_CNTL__MVP_CLK_B_SRC_SEL__SHIFT 0x0000001c
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKD_CNTL__DVOACLKD_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKD_CNTL__DVOACLKD_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKD_CNTL__DVOACLKD_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKD_CNTL__DVOACLKD_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKD_CNTL__DVOACLKD_IN_PHASE_MASK 0x00040000L
+#define DVOACLKD_CNTL__DVOACLKD_IN_PHASE__SHIFT 0x00000012
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE_MASK 0x00000001L
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE__SHIFT 0x00000000
+#define DVO_CONTROL__DVO_COLOR_FORMAT_MASK 0x03000000L
+#define DVO_CONTROL__DVO_COLOR_FORMAT__SHIFT 0x00000018
+#define DVO_CONTROL__DVO_CTL3_MASK 0x80000000L
+#define DVO_CONTROL__DVO_CTL3__SHIFT 0x0000001f
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN_MASK 0x00000100L
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN__SHIFT 0x00000008
+#define DVO_CONTROL__DVO_INVERT_DVOCLK_MASK 0x00040000L
+#define DVO_CONTROL__DVO_INVERT_DVOCLK__SHIFT 0x00000012
+#define DVO_CONTROL__DVO_RATE_SELECT_MASK 0x00000001L
+#define DVO_CONTROL__DVO_RATE_SELECT__SHIFT 0x00000000
+#define DVO_CONTROL__DVO_RESET_FIFO_MASK 0x00010000L
+#define DVO_CONTROL__DVO_RESET_FIFO__SHIFT 0x00000010
+#define DVO_CONTROL__DVO_SDRCLK_SEL_MASK 0x00000002L
+#define DVO_CONTROL__DVO_SDRCLK_SEL__SHIFT 0x00000001
+#define DVO_CONTROL__DVO_SYNC_PHASE_MASK 0x00020000L
+#define DVO_CONTROL__DVO_SYNC_PHASE__SHIFT 0x00000011
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK_MASK 0x07ffffffL
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK__SHIFT 0x00000000
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT_MASK 0x07ffffffL
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT__SHIFT 0x00000000
+#define DVO_CRC_EN__DVO_CRC2_EN_MASK 0x00010000L
+#define DVO_CRC_EN__DVO_CRC2_EN__SHIFT 0x00000010
+#define DVO_ENABLE__DVO_ENABLE_MASK 0x00000001L
+#define DVO_ENABLE__DVO_ENABLE__SHIFT 0x00000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED_MASK 0x20000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK_MASK 0x00000100L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK__SHIFT 0x00000008
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR_MASK 0x00000001L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR__SHIFT 0x00000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL_MASK 0x000f0000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DVO_OUTPUT__DVO_CLOCK_MODE_MASK 0x00000100L
+#define DVO_OUTPUT__DVO_CLOCK_MODE__SHIFT 0x00000008
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE_MASK 0x00000003L
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE__SHIFT 0x00000000
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST_MASK 0xffffffffL
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST__SHIFT 0x00000000
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT_MASK 0x00000007L
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT__SHIFT 0x00000000
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT_MASK 0x00070000L
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT__SHIFT 0x00000010
+#define DVO_STRENGTH_CONTROL__DVOCLK_SN_MASK 0x0000f000L
+#define DVO_STRENGTH_CONTROL__DVOCLK_SN__SHIFT 0x0000000c
+#define DVO_STRENGTH_CONTROL__DVOCLK_SP_MASK 0x00000f00L
+#define DVO_STRENGTH_CONTROL__DVOCLK_SP__SHIFT 0x00000008
+#define DVO_STRENGTH_CONTROL__DVO_LSB_VMODE_MASK 0x10000000L
+#define DVO_STRENGTH_CONTROL__DVO_LSB_VMODE__SHIFT 0x0000001c
+#define DVO_STRENGTH_CONTROL__DVO_MSB_VMODE_MASK 0x20000000L
+#define DVO_STRENGTH_CONTROL__DVO_MSB_VMODE__SHIFT 0x0000001d
+#define DVO_STRENGTH_CONTROL__DVO_SN_MASK 0x000000f0L
+#define DVO_STRENGTH_CONTROL__DVO_SN__SHIFT 0x00000004
+#define DVO_STRENGTH_CONTROL__DVO_SP_MASK 0x0000000fL
+#define DVO_STRENGTH_CONTROL__DVO_SP__SHIFT 0x00000000
+#define DVO_VREF_CONTROL__DVO_VREFCAL_MASK 0x000000f0L
+#define DVO_VREF_CONTROL__DVO_VREFCAL__SHIFT 0x00000004
+#define DVO_VREF_CONTROL__DVO_VREFPON_MASK 0x00000001L
+#define DVO_VREF_CONTROL__DVO_VREFPON__SHIFT 0x00000000
+#define DVO_VREF_CONTROL__DVO_VREFSEL_MASK 0x00000002L
+#define DVO_VREF_CONTROL__DVO_VREFSEL__SHIFT 0x00000001
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT_MASK 0x0fff0000L
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT__SHIFT 0x00000010
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT_MASK 0x00000fffL
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT__SHIFT 0x00000000
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM_MASK 0x00000fffL
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM__SHIFT 0x00000000
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP_MASK 0x0fff0000L
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP__SHIFT 0x00000010
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK_MASK 0x000f0000L
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK__SHIFT 0x00000010
+#define FBC_CNTL__FBC_COHERENCY_MODE_MASK 0x00030000L
+#define FBC_CNTL__FBC_COHERENCY_MODE__SHIFT 0x00000010
+#define FBC_CNTL__FBC_EN_MASK 0x80000000L
+#define FBC_CNTL__FBC_EN__SHIFT 0x0000001f
+#define FBC_CNTL__FBC_GRPH_COMP_EN_MASK 0x00000001L
+#define FBC_CNTL__FBC_GRPH_COMP_EN__SHIFT 0x00000000
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN_MASK 0x02000000L
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN__SHIFT 0x00000019
+#define FBC_CNTL__FBC_SRC_SEL_MASK 0x0000000eL
+#define FBC_CNTL__FBC_SRC_SEL__SHIFT 0x00000001
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN_MASK 0x00010000L
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN__SHIFT 0x00000010
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN_MASK 0x00020000L
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN__SHIFT 0x00000011
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN_MASK 0x00040000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN__SHIFT 0x00000012
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN_MASK 0x00080000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN__SHIFT 0x00000013
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN_MASK 0x00100000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN__SHIFT 0x00000014
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION_MASK 0x0000000fL
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION__SHIFT 0x00000000
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN_MASK 0x00000100L
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN__SHIFT 0x00000008
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN_MASK 0x00000400L
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN__SHIFT 0x0000000a
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN_MASK 0x00000200L
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN__SHIFT 0x00000009
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN_MASK 0x00000800L
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN__SHIFT 0x0000000b
+#define FBC_COMP_MODE__FBC_IND_EN_MASK 0x00010000L
+#define FBC_COMP_MODE__FBC_IND_EN__SHIFT 0x00000010
+#define FBC_COMP_MODE__FBC_RLE_EN_MASK 0x00000001L
+#define FBC_COMP_MODE__FBC_RLE_EN__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0_MASK 0x000003ffL
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1_MASK 0x03ff0000L
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1__SHIFT 0x00000010
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2_MASK 0x000003ffL
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3_MASK 0x03ff0000L
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3__SHIFT 0x00000010
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS_MASK 0x00010000L
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS__SHIFT 0x00000010
+#define FBC_DEBUG0__FBC_DEBUG0_MASK 0x00fe0000L
+#define FBC_DEBUG0__FBC_DEBUG0__SHIFT 0x00000011
+#define FBC_DEBUG0__FBC_DEBUG_MUX_MASK 0xff000000L
+#define FBC_DEBUG0__FBC_DEBUG_MUX__SHIFT 0x00000018
+#define FBC_DEBUG0__FBC_PERF_MUX0_MASK 0x000000ffL
+#define FBC_DEBUG0__FBC_PERF_MUX0__SHIFT 0x00000000
+#define FBC_DEBUG0__FBC_PERF_MUX1_MASK 0x0000ff00L
+#define FBC_DEBUG0__FBC_PERF_MUX1__SHIFT 0x00000008
+#define FBC_DEBUG1__FBC_DEBUG1_MASK 0xffffffffL
+#define FBC_DEBUG1__FBC_DEBUG1__SHIFT 0x00000000
+#define FBC_DEBUG2__FBC_DEBUG2_MASK 0xffffffffL
+#define FBC_DEBUG2__FBC_DEBUG2__SHIFT 0x00000000
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE_MASK 0x00000800L
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x0000000b
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS_MASK 0x000000f0L
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS__SHIFT 0x00000004
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL_MASK 0x00000300L
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL__SHIFT 0x00000008
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE_MASK 0x00000400L
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x0000000a
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE_MASK 0x00000008L
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE__SHIFT 0x00000003
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP_MASK 0x00000003L
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP__SHIFT 0x00000000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR_MASK 0x000003ffL
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR__SHIFT 0x00000000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN_MASK 0x80000000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN__SHIFT 0x0000001f
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA_MASK 0x00020000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA__SHIFT 0x00000011
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA_MASK 0x00010000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA__SHIFT 0x00000010
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA_MASK 0xffffffffL
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI_MASK 0x000000ffL
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA_MASK 0xffffffffL
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI_MASK 0x000000ffL
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI__SHIFT 0x00000000
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK_MASK 0xffffffffL
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK__SHIFT 0x00000000
+#define FBC_IDLE_MASK__FBC_IDLE_MASK_MASK 0xffffffffL
+#define FBC_IDLE_MASK__FBC_IDLE_MASK__SHIFT 0x00000000
+#define FBC_IND_LUT0__FBC_IND_LUT0_MASK 0x00ffffffL
+#define FBC_IND_LUT0__FBC_IND_LUT0__SHIFT 0x00000000
+#define FBC_IND_LUT10__FBC_IND_LUT10_MASK 0x00ffffffL
+#define FBC_IND_LUT10__FBC_IND_LUT10__SHIFT 0x00000000
+#define FBC_IND_LUT11__FBC_IND_LUT11_MASK 0x00ffffffL
+#define FBC_IND_LUT11__FBC_IND_LUT11__SHIFT 0x00000000
+#define FBC_IND_LUT12__FBC_IND_LUT12_MASK 0x00ffffffL
+#define FBC_IND_LUT12__FBC_IND_LUT12__SHIFT 0x00000000
+#define FBC_IND_LUT13__FBC_IND_LUT13_MASK 0x00ffffffL
+#define FBC_IND_LUT13__FBC_IND_LUT13__SHIFT 0x00000000
+#define FBC_IND_LUT14__FBC_IND_LUT14_MASK 0x00ffffffL
+#define FBC_IND_LUT14__FBC_IND_LUT14__SHIFT 0x00000000
+#define FBC_IND_LUT15__FBC_IND_LUT15_MASK 0x00ffffffL
+#define FBC_IND_LUT15__FBC_IND_LUT15__SHIFT 0x00000000
+#define FBC_IND_LUT1__FBC_IND_LUT1_MASK 0x00ffffffL
+#define FBC_IND_LUT1__FBC_IND_LUT1__SHIFT 0x00000000
+#define FBC_IND_LUT2__FBC_IND_LUT2_MASK 0x00ffffffL
+#define FBC_IND_LUT2__FBC_IND_LUT2__SHIFT 0x00000000
+#define FBC_IND_LUT3__FBC_IND_LUT3_MASK 0x00ffffffL
+#define FBC_IND_LUT3__FBC_IND_LUT3__SHIFT 0x00000000
+#define FBC_IND_LUT4__FBC_IND_LUT4_MASK 0x00ffffffL
+#define FBC_IND_LUT4__FBC_IND_LUT4__SHIFT 0x00000000
+#define FBC_IND_LUT5__FBC_IND_LUT5_MASK 0x00ffffffL
+#define FBC_IND_LUT5__FBC_IND_LUT5__SHIFT 0x00000000
+#define FBC_IND_LUT6__FBC_IND_LUT6_MASK 0x00ffffffL
+#define FBC_IND_LUT6__FBC_IND_LUT6__SHIFT 0x00000000
+#define FBC_IND_LUT7__FBC_IND_LUT7_MASK 0x00ffffffL
+#define FBC_IND_LUT7__FBC_IND_LUT7__SHIFT 0x00000000
+#define FBC_IND_LUT8__FBC_IND_LUT8_MASK 0x00ffffffL
+#define FBC_IND_LUT8__FBC_IND_LUT8__SHIFT 0x00000000
+#define FBC_IND_LUT9__FBC_IND_LUT9_MASK 0x00ffffffL
+#define FBC_IND_LUT9__FBC_IND_LUT9__SHIFT 0x00000000
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR_MASK 0x00010000L
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR__SHIFT 0x00000010
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_MASK 0x00000003L
+#define FBC_MISC__FBC_DECOMPRESS_ERROR__SHIFT 0x00000000
+#define FBC_MISC__FBC_DIVIDE_X_MASK 0x00000300L
+#define FBC_MISC__FBC_DIVIDE_X__SHIFT 0x00000008
+#define FBC_MISC__FBC_DIVIDE_Y_MASK 0x00000400L
+#define FBC_MISC__FBC_DIVIDE_Y__SHIFT 0x0000000a
+#define FBC_MISC__FBC_ERROR_PIXEL_MASK 0x000000f0L
+#define FBC_MISC__FBC_ERROR_PIXEL__SHIFT 0x00000004
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR_MASK 0x00000008L
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR__SHIFT 0x00000003
+#define FBC_MISC__FBC_RESET_AT_DISABLE_MASK 0x00200000L
+#define FBC_MISC__FBC_RESET_AT_DISABLE__SHIFT 0x00000015
+#define FBC_MISC__FBC_RESET_AT_ENABLE_MASK 0x00100000L
+#define FBC_MISC__FBC_RESET_AT_ENABLE__SHIFT 0x00000014
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY_MASK 0x00001000L
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY__SHIFT 0x0000000c
+#define FBC_MISC__FBC_RSM_WRITE_VALUE_MASK 0x00000800L
+#define FBC_MISC__FBC_RSM_WRITE_VALUE__SHIFT 0x0000000b
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL_MASK 0xf0000000L
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL__SHIFT 0x0000001c
+#define FBC_MISC__FBC_STOP_ON_ERROR_MASK 0x00000004L
+#define FBC_MISC__FBC_STOP_ON_ERROR__SHIFT 0x00000002
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY_MASK 0x00001f00L
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY__SHIFT 0x00000008
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY_MASK 0x0000001fL
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY__SHIFT 0x00000000
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY_MASK 0x00000080L
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY__SHIFT 0x00000007
+#define FBC_STATUS__FBC_ENABLE_STATUS_MASK 0x00000001L
+#define FBC_STATUS__FBC_ENABLE_STATUS__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL_MASK 0x0c000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL__SHIFT 0x0000001a
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL_MASK 0x30000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL__SHIFT 0x0000001c
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL_MASK 0xc0000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL__SHIFT 0x0000001e
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK 0x00002000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE__SHIFT 0x0000000d
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK 0x00008000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE__SHIFT 0x0000000f
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE_MASK 0x00004000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE__SHIFT 0x0000000e
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH_MASK 0x00001000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH__SHIFT 0x0000000c
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK 0x00000100L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN__SHIFT 0x00000008
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE_MASK 0x00000600L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE__SHIFT 0x00000009
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH_MASK 0x00100000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH__SHIFT 0x00000014
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN_MASK 0x00010000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN__SHIFT 0x00000010
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET_MASK 0x00600000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET__SHIFT 0x00000015
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET_MASK 0x02000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET__SHIFT 0x00000019
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL_MASK 0x01000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL__SHIFT 0x00000018
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH_MASK 0x00000010L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH__SHIFT 0x00000004
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK 0x00000001L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN__SHIFT 0x00000000
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT_MASK 0x00070000L
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT__SHIFT 0x00000010
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN_MASK 0x00000001L
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN__SHIFT 0x00000000
+#define FMT_CONTROL__FMT_PIXEL_ENCODING_MASK 0x00010000L
+#define FMT_CONTROL__FMT_PIXEL_ENCODING__SHIFT 0x00000010
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE_MASK 0x00000001L
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE__SHIFT 0x00000000
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL_MASK 0x00000010L
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL__SHIFT 0x00000004
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN_MASK 0x00000010L
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN__SHIFT 0x00000004
+#define FMT_CRC_CNTL__FMT_CRC_EN_MASK 0x00000001L
+#define FMT_CRC_CNTL__FMT_CRC_EN__SHIFT 0x00000000
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE_MASK 0x00100000L
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE__SHIFT 0x00000014
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT_MASK 0x01000000L
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT__SHIFT 0x00000018
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE_MASK 0x00003000L
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE__SHIFT 0x0000000c
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKb_MASK 0x00000100L
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKb__SHIFT 0x00000008
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS_MASK 0x00010000L
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS__SHIFT 0x00000010
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE_MASK 0x0000ffffL
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE__SHIFT 0x00000000
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL_MASK 0xffff0000L
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL__SHIFT 0x00000010
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK_MASK 0x0000ffffL
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK__SHIFT 0x00000000
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK_MASK 0xffff0000L
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN_MASK 0xffff0000L
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED_MASK 0x0000ffffL
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED__SHIFT 0x00000000
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK_MASK 0xffff0000L
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK_MASK 0x0000ffffL
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK__SHIFT 0x00000000
+#define FMT_DEBUG0__FMT_DEBUG0_MASK 0xffffffffL
+#define FMT_DEBUG0__FMT_DEBUG0__SHIFT 0x00000000
+#define FMT_DEBUG1__FMT_DEBUG1_MASK 0xffffffffL
+#define FMT_DEBUG1__FMT_DEBUG1__SHIFT 0x00000000
+#define FMT_DEBUG2__FMT_DEBUG2_MASK 0xffffffffL
+#define FMT_DEBUG2__FMT_DEBUG2__SHIFT 0x00000000
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT_MASK 0x00000003L
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT__SHIFT 0x00000000
+#define FMT_DEBUG_ID__FMT_DEBUG_ID_MASK 0xffffffffL
+#define FMT_DEBUG_ID__FMT_DEBUG_ID__SHIFT 0x00000000
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED__SHIFT 0x00000000
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED__SHIFT 0x00000000
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED__SHIFT 0x00000000
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN_MASK 0x00000001L
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN__SHIFT 0x00000000
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE_MASK 0x00000010L
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE__SHIFT 0x00000004
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA0_MASK 0x0000ffffL
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA0__SHIFT 0x00000000
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA1_MASK 0xffff0000L
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA1__SHIFT 0x00000010
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA2_MASK 0x0000ffffL
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA2__SHIFT 0x00000000
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA3_MASK 0xffff0000L
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA3__SHIFT 0x00000010
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_EN_MASK 0x00000001L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_EN__SHIFT 0x00000000
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_ON_BLANKb_ONLY_MASK 0x00010000L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_ON_BLANKb_ONLY__SHIFT 0x00000010
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_COLOR_MASK 0x00000700L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_COLOR__SHIFT 0x00000008
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_SLOT_MASK 0x0000f000L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_SLOT__SHIFT 0x0000000c
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_RGB1_BGR0_MASK 0x00000010L
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_RGB1_BGR0__SHIFT 0x00000004
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_SELECT_MASK 0x00000001L
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_SELECT__SHIFT 0x00000000
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX_MASK 0xffffffffL
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SHIFT 0x00000000
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX_MASK 0xffffffffL
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11_MASK 0x0000ffffL
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11__SHIFT 0x00000000
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12_MASK 0xffff0000L
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12__SHIFT 0x00000010
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13_MASK 0x0000ffffL
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13__SHIFT 0x00000000
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14_MASK 0xffff0000L
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14__SHIFT 0x00000010
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21_MASK 0x0000ffffL
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21__SHIFT 0x00000000
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22_MASK 0xffff0000L
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22__SHIFT 0x00000010
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23_MASK 0x0000ffffL
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23__SHIFT 0x00000000
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24_MASK 0xffff0000L
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24__SHIFT 0x00000010
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31_MASK 0x0000ffffL
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31__SHIFT 0x00000000
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32_MASK 0xffff0000L
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32__SHIFT 0x00000010
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33_MASK 0x0000ffffL
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33__SHIFT 0x00000000
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34_MASK 0xffff0000L
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34__SHIFT 0x00000010
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE_MASK 0x00000003L
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE__SHIFT 0x00000000
+#define GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE_MASK 0x00000030L
+#define GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE__SHIFT 0x00000004
+#define GENENB__BLK_IO_BASE_MASK 0x000000ffL
+#define GENENB__BLK_IO_BASE__SHIFT 0x00000000
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL_MASK 0x80000000L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL__SHIFT 0x0000001f
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE_MASK 0x00000008L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE__SHIFT 0x00000003
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO_MASK 0x00000001L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO__SHIFT 0x00000000
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET_MASK 0x00000004L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET__SHIFT 0x00000002
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET_MASK 0x00000002L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET__SHIFT 0x00000001
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_MASK 0x0000ff00L
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW_MASK 0x00000001L
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW__SHIFT 0x00000000
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA__SHIFT 0x00000008
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_MASK 0x000f0000L
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX__SHIFT 0x00000010
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE_MASK 0x80000000L
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE__SHIFT 0x0000001f
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK_MASK 0x00000002L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK__SHIFT 0x00000001
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT_MASK 0x00000001L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT__SHIFT 0x00000000
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK_MASK 0x00000004L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK__SHIFT 0x00000002
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN_MASK 0x00000004L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN__SHIFT 0x00000002
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT_MASK 0x00000002L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT__SHIFT 0x00000001
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT_MASK 0x00000001L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT__SHIFT 0x00000000
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN_MASK 0x00000040L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN__SHIFT 0x00000006
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT_MASK 0x00000020L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT__SHIFT 0x00000005
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT_MASK 0x00000010L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT__SHIFT 0x00000004
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL_MASK 0x0000007fL
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL__SHIFT 0x00000000
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL_MASK 0x00007f00L
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL__SHIFT 0x00000008
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN_MASK 0x00000080L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN__SHIFT 0x00000007
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN_MASK 0x00000001L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN__SHIFT 0x00000000
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL_MASK 0x00000002L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT_MASK 0xff000000L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT__SHIFT 0x00000018
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE_MASK 0xffff0000L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE__SHIFT 0x00000010
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD_MASK 0x00000003L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD__SHIFT 0x00000000
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED_MASK 0x00000020L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED__SHIFT 0x00000005
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE_MASK 0x00000010L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE__SHIFT 0x00000004
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK_MASK 0x00000400L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK__SHIFT 0x0000000a
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS_MASK 0x0000000fL
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS__SHIFT 0x00000000
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK_MASK 0x00000200L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK__SHIFT 0x00000009
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT_MASK 0x00000040L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT__SHIFT 0x00000006
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ_MASK 0x00000200L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ__SHIFT 0x00000009
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT_MASK 0x000f0000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT__SHIFT 0x00000010
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW_MASK 0x00000001L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW__SHIFT 0x00000000
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START_MASK 0x00001000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START__SHIFT 0x0000000c
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_MASK 0x00002000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK_MASK 0x00000100L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK__SHIFT 0x00000008
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP__SHIFT 0x0000000d
+#define GENFC_RD__VSYNC_SEL_R_MASK 0x00000008L
+#define GENFC_RD__VSYNC_SEL_R__SHIFT 0x00000003
+#define GENFC_WT__VSYNC_SEL_W_MASK 0x00000008L
+#define GENFC_WT__VSYNC_SEL_W__SHIFT 0x00000003
+#define GENMO_RD__GENMO_MONO_ADDRESS_B_MASK 0x00000001L
+#define GENMO_RD__GENMO_MONO_ADDRESS_B__SHIFT 0x00000000
+#define GENMO_RD__ODD_EVEN_MD_PGSEL_MASK 0x00000020L
+#define GENMO_RD__ODD_EVEN_MD_PGSEL__SHIFT 0x00000005
+#define GENMO_RD__VGA_CKSEL_MASK 0x0000000cL
+#define GENMO_RD__VGA_CKSEL__SHIFT 0x00000002
+#define GENMO_RD__VGA_HSYNC_POL_MASK 0x00000040L
+#define GENMO_RD__VGA_HSYNC_POL__SHIFT 0x00000006
+#define GENMO_RD__VGA_RAM_EN_MASK 0x00000002L
+#define GENMO_RD__VGA_RAM_EN__SHIFT 0x00000001
+#define GENMO_RD__VGA_VSYNC_POL_MASK 0x00000080L
+#define GENMO_RD__VGA_VSYNC_POL__SHIFT 0x00000007
+#define GENMO_WT__GENMO_MONO_ADDRESS_B_MASK 0x00000001L
+#define GENMO_WT__GENMO_MONO_ADDRESS_B__SHIFT 0x00000000
+#define GENMO_WT__ODD_EVEN_MD_PGSEL_MASK 0x00000020L
+#define GENMO_WT__ODD_EVEN_MD_PGSEL__SHIFT 0x00000005
+#define GENMO_WT__VGA_CKSEL_MASK 0x0000000cL
+#define GENMO_WT__VGA_CKSEL__SHIFT 0x00000002
+#define GENMO_WT__VGA_HSYNC_POL_MASK 0x00000040L
+#define GENMO_WT__VGA_HSYNC_POL__SHIFT 0x00000006
+#define GENMO_WT__VGA_RAM_EN_MASK 0x00000002L
+#define GENMO_WT__VGA_RAM_EN__SHIFT 0x00000001
+#define GENMO_WT__VGA_VSYNC_POL_MASK 0x00000080L
+#define GENMO_WT__VGA_VSYNC_POL__SHIFT 0x00000007
+#define GENS0__CRT_INTR_MASK 0x00000080L
+#define GENS0__CRT_INTR__SHIFT 0x00000007
+#define GENS0__SENSE_SWITCH_MASK 0x00000010L
+#define GENS0__SENSE_SWITCH__SHIFT 0x00000004
+#define GENS1__NO_DISPLAY_MASK 0x00000001L
+#define GENS1__NO_DISPLAY__SHIFT 0x00000000
+#define GENS1__PIXEL_READ_BACK_MASK 0x00000030L
+#define GENS1__PIXEL_READ_BACK__SHIFT 0x00000004
+#define GENS1__VGA_VSTATUS_MASK 0x00000008L
+#define GENS1__VGA_VSTATUS__SHIFT 0x00000003
+#define GRA00__GRPH_SET_RESET0_MASK 0x00000001L
+#define GRA00__GRPH_SET_RESET0__SHIFT 0x00000000
+#define GRA00__GRPH_SET_RESET1_MASK 0x00000002L
+#define GRA00__GRPH_SET_RESET1__SHIFT 0x00000001
+#define GRA00__GRPH_SET_RESET2_MASK 0x00000004L
+#define GRA00__GRPH_SET_RESET2__SHIFT 0x00000002
+#define GRA00__GRPH_SET_RESET3_MASK 0x00000008L
+#define GRA00__GRPH_SET_RESET3__SHIFT 0x00000003
+#define GRA01__GRPH_SET_RESET_ENA0_MASK 0x00000001L
+#define GRA01__GRPH_SET_RESET_ENA0__SHIFT 0x00000000
+#define GRA01__GRPH_SET_RESET_ENA1_MASK 0x00000002L
+#define GRA01__GRPH_SET_RESET_ENA1__SHIFT 0x00000001
+#define GRA01__GRPH_SET_RESET_ENA2_MASK 0x00000004L
+#define GRA01__GRPH_SET_RESET_ENA2__SHIFT 0x00000002
+#define GRA01__GRPH_SET_RESET_ENA3_MASK 0x00000008L
+#define GRA01__GRPH_SET_RESET_ENA3__SHIFT 0x00000003
+#define GRA02__GRPH_CCOMP_MASK 0x0000000fL
+#define GRA02__GRPH_CCOMP__SHIFT 0x00000000
+#define GRA03__GRPH_FN_SEL_MASK 0x00000018L
+#define GRA03__GRPH_FN_SEL__SHIFT 0x00000003
+#define GRA03__GRPH_ROTATE_MASK 0x00000007L
+#define GRA03__GRPH_ROTATE__SHIFT 0x00000000
+#define GRA04__GRPH_RMAP_MASK 0x00000003L
+#define GRA04__GRPH_RMAP__SHIFT 0x00000000
+#define GRA05__CGA_ODDEVEN_MASK 0x00000010L
+#define GRA05__CGA_ODDEVEN__SHIFT 0x00000004
+#define GRA05__GRPH_OES_MASK 0x00000020L
+#define GRA05__GRPH_OES__SHIFT 0x00000005
+#define GRA05__GRPH_PACK_MASK 0x00000040L
+#define GRA05__GRPH_PACK__SHIFT 0x00000006
+#define GRA05__GRPH_READ1_MASK 0x00000008L
+#define GRA05__GRPH_READ1__SHIFT 0x00000003
+#define GRA05__GRPH_WRITE_MODE_MASK 0x00000003L
+#define GRA05__GRPH_WRITE_MODE__SHIFT 0x00000000
+#define GRA06__GRPH_ADRSEL_MASK 0x0000000cL
+#define GRA06__GRPH_ADRSEL__SHIFT 0x00000002
+#define GRA06__GRPH_GRAPHICS_MASK 0x00000001L
+#define GRA06__GRPH_GRAPHICS__SHIFT 0x00000000
+#define GRA06__GRPH_ODDEVEN_MASK 0x00000002L
+#define GRA06__GRPH_ODDEVEN__SHIFT 0x00000001
+#define GRA07__GRPH_XCARE0_MASK 0x00000001L
+#define GRA07__GRPH_XCARE0__SHIFT 0x00000000
+#define GRA07__GRPH_XCARE1_MASK 0x00000002L
+#define GRA07__GRPH_XCARE1__SHIFT 0x00000001
+#define GRA07__GRPH_XCARE2_MASK 0x00000004L
+#define GRA07__GRPH_XCARE2__SHIFT 0x00000002
+#define GRA07__GRPH_XCARE3_MASK 0x00000008L
+#define GRA07__GRPH_XCARE3__SHIFT 0x00000003
+#define GRA08__GRPH_BMSK_MASK 0x000000ffL
+#define GRA08__GRPH_BMSK__SHIFT 0x00000000
+#define GRPH8_DATA__GRPH_DATA_MASK 0x000000ffL
+#define GRPH8_DATA__GRPH_DATA__SHIFT 0x00000000
+#define GRPH8_IDX__GRPH_IDX_MASK 0x0000000fL
+#define GRPH8_IDX__GRPH_IDX__SHIFT 0x00000000
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH_MASK 0x0001ffc0L
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH__SHIFT 0x00000006
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE_MASK 0x00010000L
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000010
+#define GRPH_CONTROL__GRPH_ARRAY_MODE_MASK 0x00f00000L
+#define GRPH_CONTROL__GRPH_ARRAY_MODE__SHIFT 0x00000014
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT_MASK 0x00001800L
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT__SHIFT 0x0000000b
+#define GRPH_CONTROL__GRPH_BANK_WIDTH_MASK 0x000000c0L
+#define GRPH_CONTROL__GRPH_BANK_WIDTH__SHIFT 0x00000006
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE_MASK 0x80000000L
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE__SHIFT 0x0000001f
+#define GRPH_CONTROL__GRPH_DEPTH_MASK 0x00000003L
+#define GRPH_CONTROL__GRPH_DEPTH__SHIFT 0x00000000
+#define GRPH_CONTROL__GRPH_FORMAT_MASK 0x00000700L
+#define GRPH_CONTROL__GRPH_FORMAT__SHIFT 0x00000008
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_MASK 0x000c0000L
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT__SHIFT 0x00000012
+#define GRPH_CONTROL__GRPH_NUM_BANKS_MASK 0x0000000cL
+#define GRPH_CONTROL__GRPH_NUM_BANKS__SHIFT 0x00000002
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG_MASK 0x1f000000L
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG__SHIFT 0x00000018
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE_MASK 0x00020000L
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000011
+#define GRPH_CONTROL__GRPH_TILE_SPLIT_MASK 0x0000e000L
+#define GRPH_CONTROL__GRPH_TILE_SPLIT__SHIFT 0x0000000d
+#define GRPH_CONTROL__GRPH_Z_MASK 0x00000030L
+#define GRPH_CONTROL__GRPH_Z__SHIFT 0x00000004
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES_MASK 0x00000700L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES__SHIFT 0x00000008
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET_MASK 0x00000001L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET__SHIFT 0x00000000
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE_MASK 0x00000070L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE__SHIFT 0x00000004
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK_MASK 0x00000200L
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK__SHIFT 0x00000009
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG_MASK 0x00000100L
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG__SHIFT 0x00000008
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES_MASK 0x0000000fL
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES__SHIFT 0x00000000
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES_MASK 0x000000f0L
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES__SHIFT 0x00000004
+#define GRPH_ENABLE__GRPH_ENABLE_MASK 0x00000001L
+#define GRPH_ENABLE__GRPH_ENABLE__SHIFT 0x00000000
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK 0x00000001L
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN__SHIFT 0x00000000
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x00000001L
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK__SHIFT 0x00000000
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE_MASK 0x00000100L
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE__SHIFT 0x00000008
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK 0x00000100L
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR__SHIFT 0x00000008
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK 0x00000001L
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED__SHIFT 0x00000000
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN_MASK 0x00010000L
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN__SHIFT 0x00000010
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK 0x00000100L
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN__SHIFT 0x00000008
+#define GRPH_PITCH__GRPH_PITCH_MASK 0x00007fffL
+#define GRPH_PITCH__GRPH_PITCH__SHIFT 0x00000000
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE_MASK 0x00000001L
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE__SHIFT 0x00000000
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE_MASK 0x00000001L
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE__SHIFT 0x00000000
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING_MASK 0x00010000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING__SHIFT 0x00000010
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING_MASK 0x00020000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING__SHIFT 0x00000011
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN_MASK 0x00000001L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN__SHIFT 0x00000000
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE_MASK 0x00000300L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE__SHIFT 0x00000008
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE__SHIFT 0x0000001c
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE_MASK 0x000000ffL
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE__SHIFT 0x00000000
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE_MASK 0xffffff00L
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE__SHIFT 0x00000008
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X_MASK 0x00003fffL
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X__SHIFT 0x00000000
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y_MASK 0x00003fffL
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y__SHIFT 0x00000000
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR_MASK 0x00000c00L
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR__SHIFT 0x0000000a
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR_MASK 0x00000300L
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR__SHIFT 0x00000008
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP_MASK 0x00000003L
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT 0x00000000
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR_MASK 0x000000c0L
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR__SHIFT 0x00000006
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR_MASK 0x00000030L
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR__SHIFT 0x00000004
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING_MASK 0x00000001L
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING__SHIFT 0x00000000
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN_MASK 0x00000002L
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN__SHIFT 0x00000001
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_MASK 0x10000000L
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x0000001c
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK 0x00000004L
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING__SHIFT 0x00000002
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN_MASK 0x00000008L
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN__SHIFT 0x00000003
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE_MASK 0x00000100L
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE__SHIFT 0x00000008
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK 0x00010000L
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK__SHIFT 0x00000010
+#define GRPH_X_END__GRPH_X_END_MASK 0x00007fffL
+#define GRPH_X_END__GRPH_X_END__SHIFT 0x00000000
+#define GRPH_X_START__GRPH_X_START_MASK 0x00003fffL
+#define GRPH_X_START__GRPH_X_START__SHIFT 0x00000000
+#define GRPH_Y_END__GRPH_Y_END_MASK 0x00007fffL
+#define GRPH_Y_END__GRPH_Y_END__SHIFT 0x00000000
+#define GRPH_Y_START__GRPH_Y_START_MASK 0x00003fffL
+#define GRPH_Y_START__GRPH_Y_START__SHIFT 0x00000000
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK 0xfffff000L
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32__SHIFT 0x0000000c
+#define HDMI_ACR_32_1__HDMI_ACR_N_32_MASK 0x000fffffL
+#define HDMI_ACR_32_1__HDMI_ACR_N_32__SHIFT 0x00000000
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK 0xfffff000L
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT 0x0000000c
+#define HDMI_ACR_44_1__HDMI_ACR_N_44_MASK 0x000fffffL
+#define HDMI_ACR_44_1__HDMI_ACR_N_44__SHIFT 0x00000000
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK 0xfffff000L
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48__SHIFT 0x0000000c
+#define HDMI_ACR_48_1__HDMI_ACR_N_48_MASK 0x000fffffL
+#define HDMI_ACR_48_1__HDMI_ACR_N_48__SHIFT 0x00000000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY_MASK 0x80000000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY__SHIFT 0x0000001f
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK 0x00001000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND__SHIFT 0x0000000c
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT_MASK 0x00000002L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT__SHIFT 0x00000001
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE_MASK 0x00070000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE__SHIFT 0x00000010
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT_MASK 0x00000030L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT__SHIFT 0x00000004
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND_MASK 0x00000001L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND__SHIFT 0x00000000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK 0x00000100L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE__SHIFT 0x00000008
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS_MASK 0xfffff000L
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS__SHIFT 0x0000000c
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N_MASK 0x000fffffL
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N__SHIFT 0x00000000
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN_MASK 0x00000030L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN__SHIFT 0x00000004
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE_MASK 0x001f0000L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE__SHIFT 0x00000010
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS_MASK 0x00000100L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS__SHIFT 0x00000008
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH_MASK 0x30000000L
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH__SHIFT 0x0000001c
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK 0x01000000L
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE__SHIFT 0x00000018
+#define HDMI_CONTROL__HDMI_ERROR_ACK_MASK 0x00000100L
+#define HDMI_CONTROL__HDMI_ERROR_ACK__SHIFT 0x00000008
+#define HDMI_CONTROL__HDMI_ERROR_MASK_MASK 0x00000200L
+#define HDMI_CONTROL__HDMI_ERROR_MASK__SHIFT 0x00000009
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE_MASK 0x00000001L
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE__SHIFT 0x00000000
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION_MASK 0x00000010L
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION__SHIFT 0x00000004
+#define HDMI_GC__HDMI_DEFAULT_PHASE_MASK 0x00000010L
+#define HDMI_GC__HDMI_DEFAULT_PHASE__SHIFT 0x00000004
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT_MASK 0x00000004L
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT__SHIFT 0x00000002
+#define HDMI_GC__HDMI_GC_AVMUTE_MASK 0x00000001L
+#define HDMI_GC__HDMI_GC_AVMUTE__SHIFT 0x00000000
+#define HDMI_GC__HDMI_PACKING_PHASE_MASK 0x00000f00L
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE_MASK 0x00001000L
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE__SHIFT 0x0000000c
+#define HDMI_GC__HDMI_PACKING_PHASE__SHIFT 0x00000008
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT_MASK 0x00000002L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT__SHIFT 0x00000001
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_MASK 0x003f0000L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE__SHIFT 0x00000010
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND_MASK 0x00000001L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND__SHIFT 0x00000000
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT_MASK 0x00000020L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT__SHIFT 0x00000005
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_MASK 0x3f000000L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE__SHIFT 0x00000018
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND_MASK 0x00000010L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND__SHIFT 0x00000004
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT_MASK 0x00000002L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT__SHIFT 0x00000001
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE_MASK 0x003f0000L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE__SHIFT 0x00000010
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND_MASK 0x00000001L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND__SHIFT 0x00000000
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT_MASK 0x00000020L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT__SHIFT 0x00000005
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE_MASK 0x3f000000L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE__SHIFT 0x00000018
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND_MASK 0x00000010L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND__SHIFT 0x00000004
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT_MASK 0x00000020L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT__SHIFT 0x00000005
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND_MASK 0x00000010L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND__SHIFT 0x00000004
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK 0x00000002L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT__SHIFT 0x00000001
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK 0x00000001L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND__SHIFT 0x00000000
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT_MASK 0x00000200L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT__SHIFT 0x00000009
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND_MASK 0x00000100L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND__SHIFT 0x00000008
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE_MASK 0x00003f00L
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT 0x00000008
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE_MASK 0x0000003fL
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT 0x00000000
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE_MASK 0x003f0000L
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE__SHIFT 0x00000010
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE_MASK 0x00000001L
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE__SHIFT 0x00000000
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR_MASK 0x00010000L
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR__SHIFT 0x00000010
+#define HDMI_STATUS__HDMI_ERROR_INT_MASK 0x08000000L
+#define HDMI_STATUS__HDMI_ERROR_INT__SHIFT 0x0000001b
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR_MASK 0x00100000L
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR__SHIFT 0x00000014
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT_MASK 0x00000020L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT__SHIFT 0x00000005
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND_MASK 0x00000010L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND__SHIFT 0x00000004
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT_MASK 0x00000200L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT__SHIFT 0x00000009
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE_MASK 0x003f0000L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE__SHIFT 0x00000010
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND_MASK 0x00000100L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND__SHIFT 0x00000008
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND_MASK 0x00000001L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND__SHIFT 0x00000000
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffffL
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x00000000
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E_MASK 0xffffffffL
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E__SHIFT 0x00000000
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F_MASK 0xffffffffL
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F__SHIFT 0x00000000
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11_MASK 0x0000ffffL
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11__SHIFT 0x00000000
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12_MASK 0xffff0000L
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12__SHIFT 0x00000010
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13_MASK 0x0000ffffL
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13__SHIFT 0x00000000
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14_MASK 0xffff0000L
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14__SHIFT 0x00000010
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21_MASK 0x0000ffffL
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21__SHIFT 0x00000000
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22_MASK 0xffff0000L
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22__SHIFT 0x00000010
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23_MASK 0x0000ffffL
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23__SHIFT 0x00000000
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24_MASK 0xffff0000L
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24__SHIFT 0x00000010
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31_MASK 0x0000ffffL
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31__SHIFT 0x00000000
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32_MASK 0xffff0000L
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32__SHIFT 0x00000010
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33_MASK 0x0000ffffL
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33__SHIFT 0x00000000
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34_MASK 0xffff0000L
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34__SHIFT 0x00000010
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE_MASK 0x00000003L
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE__SHIFT 0x00000000
+#define INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE_MASK 0x00000030L
+#define INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE__SHIFT 0x00000004
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE_MASK 0x00000003L
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE__SHIFT 0x00000000
+#define INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE_MASK 0x00000030L
+#define INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE__SHIFT 0x00000004
+#define KEY_CONTROL__GRPH_OVL_HALF_BLEND_MASK 0x10000000L
+#define KEY_CONTROL__GRPH_OVL_HALF_BLEND__SHIFT 0x0000001c
+#define KEY_CONTROL__KEY_MODE_MASK 0x00000006L
+#define KEY_CONTROL__KEY_MODE__SHIFT 0x00000001
+#define KEY_CONTROL__KEY_SELECT_MASK 0x00000001L
+#define KEY_CONTROL__KEY_SELECT__SHIFT 0x00000000
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW__SHIFT 0x00000000
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW__SHIFT 0x00000000
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW__SHIFT 0x00000000
+#define KEY_RANGE_RED__KEY_RED_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_RED__KEY_RED_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_RED__KEY_RED_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_RED__KEY_RED_LOW__SHIFT 0x00000000
+#define LB_DEBUG2__LB_DEBUG2_MASK 0xffffffffL
+#define LB_DEBUG2__LB_DEBUG2__SHIFT 0x00000000
+#define LB_DEBUG__LB_DEBUG_MASK 0xffffffffL
+#define LB_DEBUG__LB_DEBUG__SHIFT 0x00000000
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT_MASK 0x00000001L
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT__SHIFT 0x00000000
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2_MASK 0x00000010L
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2__SHIFT 0x00000004
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL_MASK 0x00000003L
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL__SHIFT 0x00000000
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define LIGHT_SLEEP_CNTL__LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define LIGHT_SLEEP_CNTL__LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define LIGHT_SLEEP_CNTL__MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define LIGHT_SLEEP_CNTL__MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE_MASK 0x00000001L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE__SHIFT 0x00000000
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE_MASK 0x00000018L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE__SHIFT 0x00000003
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS_MASK 0x00000700L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS__SHIFT 0x00000008
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES_MASK 0x000000e0L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES__SHIFT 0x00000005
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE_MASK 0x00000800L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE__SHIFT 0x0000000b
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE_MASK 0x00007000L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE__SHIFT 0x0000000c
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN_MASK 0x0fff0000L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN__SHIFT 0x00000010
+#define LVDS_DATA_CNTL__LVDS_24BIT_ENABLE_MASK 0x00000001L
+#define LVDS_DATA_CNTL__LVDS_24BIT_ENABLE__SHIFT 0x00000000
+#define LVDS_DATA_CNTL__LVDS_24BIT_FORMAT_MASK 0x00000010L
+#define LVDS_DATA_CNTL__LVDS_24BIT_FORMAT__SHIFT 0x00000004
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_DE_MASK 0x00000100L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_DE__SHIFT 0x00000008
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_HS_MASK 0x00000400L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_HS__SHIFT 0x0000000a
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_VS_MASK 0x00000200L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_VS__SHIFT 0x00000009
+#define LVDS_DATA_CNTL__LVDS_2ND_LINK_CNTL_BITS_MASK 0x00007000L
+#define LVDS_DATA_CNTL__LVDS_2ND_LINK_CNTL_BITS__SHIFT 0x0000000c
+#define LVDS_DATA_CNTL__LVDS_DTMG_POL_MASK 0x00040000L
+#define LVDS_DATA_CNTL__LVDS_DTMG_POL__SHIFT 0x00000012
+#define LVDS_DATA_CNTL__LVDS_FP_POL_MASK 0x00010000L
+#define LVDS_DATA_CNTL__LVDS_FP_POL__SHIFT 0x00000010
+#define LVDS_DATA_CNTL__LVDS_LP_POL_MASK 0x00020000L
+#define LVDS_DATA_CNTL__LVDS_LP_POL__SHIFT 0x00000011
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_MASK 0x01000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD_MASK 0x02000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD__SHIFT 0x00000019
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL_MASK 0x04000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL__SHIFT 0x0000001a
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_MASK 0x00010000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD_MASK 0x00020000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD__SHIFT 0x00000011
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL_MASK 0x00040000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL__SHIFT 0x00000012
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN_MASK 0x00000002L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN__SHIFT 0x00000001
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN_MASK 0x00000001L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE_MASK 0x00000010L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE__SHIFT 0x00000004
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_MASK 0x00000100L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD_MASK 0x00000200L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD__SHIFT 0x00000009
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL_MASK 0x00000400L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL__SHIFT 0x0000000a
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1_MASK 0x00ff0000L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2_MASK 0xff000000L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1_MASK 0x000000ffL
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2_MASK 0x0000ff00L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3_MASK 0x00ff0000L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH_MASK 0x000000ffL
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3_MASK 0x0000ff00L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN_MASK 0x01000000L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV_MASK 0xffff0000L
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV_MASK 0x00000fffL
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON_MASK 0x00000008L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON__SHIFT 0x00000003
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON_MASK 0x00000002L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON__SHIFT 0x00000001
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE_MASK 0x00000010L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE__SHIFT 0x00000004
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE_MASK 0x00000f00L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN_MASK 0x00000004L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN__SHIFT 0x00000002
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R_MASK 0x00000001L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R__SHIFT 0x00000000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3__SHIFT 0x00000018
+#define MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK_MASK 0x00000100L
+#define MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK__SHIFT 0x00000008
+#define MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK_MASK 0x00000001L
+#define MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK__SHIFT 0x00000000
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE_MASK 0x00030000L
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE__SHIFT 0x00000010
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_MODE_MASK 0x00000007L
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_MODE__SHIFT 0x00000000
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR_MASK 0x00000010L
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR__SHIFT 0x00000004
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED_MASK 0x00000001L
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED__SHIFT 0x00000000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR_MASK 0x00100000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR__SHIFT 0x00000014
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED_MASK 0x00010000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED__SHIFT 0x00000010
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR_MASK 0x10000000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR__SHIFT 0x0000001c
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED_MASK 0x01000000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED__SHIFT 0x00000018
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR_MASK 0x00001000L
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR__SHIFT 0x0000000c
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED_MASK 0x00000100L
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED__SHIFT 0x00000008
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE_MASK 0x00000010L
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000004
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL_MASK 0x00ff0000L
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL__SHIFT 0x00000010
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY_MASK 0x3f000000L
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY__SHIFT 0x00000018
+#define MCIF_CONTROL__MCIF_BUFF_SIZE_MASK 0x00000003L
+#define MCIF_CONTROL__MCIF_BUFF_SIZE__SHIFT 0x00000000
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x40000000L
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x0000001e
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x80000000L
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x0000001f
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL_MASK 0x0000f000L
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL__SHIFT 0x0000000c
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE_MASK 0x00000100L
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000008
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS_MASK 0x00000001L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS__SHIFT 0x00000000
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_MASK 0x00000030L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE__SHIFT 0x00000004
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE_MASK 0x00070000L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE__SHIFT 0x00000010
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE_MASK 0x00007f00L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE__SHIFT 0x00000008
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE_MASK 0x00180000L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE__SHIFT 0x00000013
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define MCIF_VMID__MCIF_WR_VMID_MASK 0x0000000fL
+#define MCIF_VMID__MCIF_WR_VMID__SHIFT 0x00000000
+#define MCIF_VMID__VIP_WR_VMID_MASK 0x000000f0L
+#define MCIF_VMID__VIP_WR_VMID__SHIFT 0x00000004
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT_MASK 0x000000ffL
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT__SHIFT 0x00000000
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT_MASK 0x0000ff00L
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT__SHIFT 0x00000008
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x00100000L
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x00000014
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV_MASK 0x0000007fL
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV__SHIFT 0x00000000
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL_MASK 0x00020000L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL__SHIFT 0x00000011
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV_MASK 0x00007f00L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV__SHIFT 0x00000008
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL_MASK 0x00010000L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL__SHIFT 0x00000010
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x00100000L
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x00000014
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV_MASK 0x0001ffffL
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV__SHIFT 0x00000000
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES_MASK 0x0000000fL
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES__SHIFT 0x00000000
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK_MASK 0x00001000L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK__SHIFT 0x0000000c
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG_MASK 0x00000100L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG__SHIFT 0x00000008
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_MASK 0x00000010L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET__SHIFT 0x00000004
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE_MASK 0x00000003L
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE__SHIFT 0x00000000
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B_MASK 0x3ff00000L
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B__SHIFT 0x00000014
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G_MASK 0x000ffc00L
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G__SHIFT 0x0000000a
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R_MASK 0x000003ffL
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R__SHIFT 0x00000000
+#define MVP_CONTROL1__MVP_30BPP_EN_MASK 0x10000000L
+#define MVP_CONTROL1__MVP_30BPP_EN__SHIFT 0x0000001c
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE_MASK 0x00000400L
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE__SHIFT 0x0000000a
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL_MASK 0x00010000L
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL__SHIFT 0x00000010
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND_MASK 0x01000000L
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND__SHIFT 0x00000018
+#define MVP_CONTROL1__MVP_EN_MASK 0x00000001L
+#define MVP_CONTROL1__MVP_EN__SHIFT 0x00000000
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION_MASK 0x00300000L
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000014
+#define MVP_CONTROL1__MVP_MIXER_MODE_MASK 0x00000070L
+#define MVP_CONTROL1__MVP_MIXER_MODE__SHIFT 0x00000004
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK_MASK 0x00000200L
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK__SHIFT 0x00000009
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_MASK 0x00000100L
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL__SHIFT 0x00000008
+#define MVP_CONTROL1__MVP_RATE_CONTROL_MASK 0x00001000L
+#define MVP_CONTROL1__MVP_RATE_CONTROL__SHIFT 0x0000000c
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A_MASK 0x40000000L
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A__SHIFT 0x0000001e
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B_MASK 0x80000000L
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B__SHIFT 0x0000001f
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX_MASK 0x00010000L
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX__SHIFT 0x00000010
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN_MASK 0x00100000L
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN__SHIFT 0x00000014
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL_MASK 0x00000100L
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL__SHIFT 0x00000008
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL_MASK 0x00001000L
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL__SHIFT 0x0000000c
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL_MASK 0x00000001L
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL__SHIFT 0x00000000
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL_MASK 0x00000010L
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL__SHIFT 0x00000004
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR_MASK 0x10000000L
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR__SHIFT 0x0000001c
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN_MASK 0x01000000L
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN__SHIFT 0x00000018
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL_MASK 0x00000010L
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL__SHIFT 0x00000004
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE_MASK 0x00000100L
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE__SHIFT 0x00000008
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN_MASK 0x00100000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN__SHIFT 0x00000014
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP_MASK 0x10000000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP__SHIFT 0x0000001c
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE_MASK 0x00001000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE__SHIFT 0x0000000c
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO_MASK 0x00010000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO__SHIFT 0x00000010
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES_MASK 0x00000001L
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES__SHIFT 0x00000000
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN_MASK 0x01000000L
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN__SHIFT 0x00000018
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK_MASK 0x000000ffL
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK__SHIFT 0x00000000
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN_MASK 0x20000000L
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN__SHIFT 0x0000001d
+#define MVP_CRC_CNTL__MVP_CRC_EN_MASK 0x10000000L
+#define MVP_CRC_CNTL__MVP_CRC_EN__SHIFT 0x0000001c
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK_MASK 0x0000ff00L
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK__SHIFT 0x00000008
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK_MASK 0x00ff0000L
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK__SHIFT 0x00000010
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL_MASK 0x40000000L
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL__SHIFT 0x0000001e
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT_MASK 0x0000ffffL
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT__SHIFT 0x00000000
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT_MASK 0xffff0000L
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT__SHIFT 0x00000010
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT_MASK 0x0000ffffL
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT__SHIFT 0x00000000
+#define MVP_DEBUG_05__IDE0_MVP_GPU_CHAIN_LOCATION_MASK 0x00000006L
+#define MVP_DEBUG_05__IDE0_MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000001
+#define MVP_DEBUG_09__IDE4_CRTC2_MVP_GPU_CHAIN_LOCATION_MASK 0x00000006L
+#define MVP_DEBUG_09__IDE4_CRTC2_MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000001
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H_MASK 0x00000001L
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H__SHIFT 0x00000000
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_MASK 0x01fffffeL
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A__SHIFT 0x00000001
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H_MASK 0x00000001L
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H__SHIFT 0x00000000
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_MASK 0x01fffffeL
+#define MVP_DEBUG_13__IDED_MVP_DATA_B__SHIFT 0x00000001
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B_MASK 0x04000000L
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B__SHIFT 0x0000001a
+#define MVP_DEBUG_13__IDED_START_READ_B_MASK 0x02000000L
+#define MVP_DEBUG_13__IDED_START_READ_B__SHIFT 0x00000019
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B_MASK 0x38000000L
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B__SHIFT 0x0000001b
+#define MVP_DEBUG_14__IDEE_CRC_PHASE_MASK 0x00100000L
+#define MVP_DEBUG_14__IDEE_CRC_PHASE__SHIFT 0x00000014
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A_MASK 0x00080000L
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A__SHIFT 0x00000013
+#define MVP_DEBUG_14__IDEE_READ_ADD_MASK 0x00000007L
+#define MVP_DEBUG_14__IDEE_READ_ADD__SHIFT 0x00000000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B_MASK 0x00020000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B__SHIFT 0x00000011
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_MASK 0x00010000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE__SHIFT 0x00000010
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE_MASK 0x00040000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE__SHIFT 0x00000012
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B_MASK 0x00008000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B__SHIFT 0x0000000f
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_MASK 0x00004000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE__SHIFT 0x0000000e
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A_MASK 0x00000800L
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A__SHIFT 0x0000000b
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B_MASK 0x00001000L
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B__SHIFT 0x0000000c
+#define MVP_DEBUG_14__IDEE_START_READ_B_MASK 0x00000400L
+#define MVP_DEBUG_14__IDEE_START_READ_B__SHIFT 0x0000000a
+#define MVP_DEBUG_14__IDEE_START_READ_MASK 0x00000200L
+#define MVP_DEBUG_14__IDEE_START_READ__SHIFT 0x00000009
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO_MASK 0x00002000L
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO__SHIFT 0x0000000d
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A_MASK 0x00000038L
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A__SHIFT 0x00000003
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B_MASK 0x000001c0L
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B__SHIFT 0x00000006
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA_MASK 0xfffffff0L
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA__SHIFT 0x00000004
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN_MASK 0x00000001L
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN__SHIFT 0x00000000
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT_MASK 0x00000008L
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT__SHIFT 0x00000003
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL_MASK 0x00000004L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL__SHIFT 0x00000002
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL_MASK 0x00000002L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL__SHIFT 0x00000001
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES_MASK 0x00000ff0L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES__SHIFT 0x00000004
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW_MASK 0x00001000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW__SHIFT 0x0000000c
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ_MASK 0x00000001L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ__SHIFT 0x00000000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW_MASK 0x00002000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW__SHIFT 0x0000000d
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR_MASK 0x00ff0000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR__SHIFT 0x00000010
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR_MASK 0xff000000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR__SHIFT 0x00000018
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE_MASK 0x00000002L
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE__SHIFT 0x00000001
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA_MASK 0xfffffffcL
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA__SHIFT 0x00000002
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_MASK 0x00000001L
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ__SHIFT 0x00000000
+#define MVP_DEBUG__MVP_DEBUG_BITS_MASK 0xffffff00L
+#define MVP_DEBUG__MVP_DEBUG_BITS__SHIFT 0x00000008
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP_MASK 0x00000020L
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP__SHIFT 0x00000005
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP_MASK 0x00000010L
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP__SHIFT 0x00000004
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY_MASK 0x00000080L
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY__SHIFT 0x00000007
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR_MASK 0x00000040L
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR__SHIFT 0x00000006
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN_MASK 0x00000002L
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN__SHIFT 0x00000001
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL_MASK 0x00000008L
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL__SHIFT 0x00000003
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN_MASK 0x00000001L
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN__SHIFT 0x00000000
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL_MASK 0x00000004L
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL__SHIFT 0x00000002
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT_MASK 0x00ff0000L
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT__SHIFT 0x00000010
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM_MASK 0x0000ff00L
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM__SHIFT 0x00000008
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM_MASK 0x000000ffL
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM__SHIFT 0x00000000
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS_MASK 0x80000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS__SHIFT 0x0000001f
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK_MASK 0x40000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK__SHIFT 0x0000001e
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL_MASK 0x000000ffL
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL__SHIFT 0x00000000
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK_MASK 0x00010000L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK__SHIFT 0x00000010
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_MASK 0x00000100L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED_MASK 0x00001000L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED__SHIFT 0x0000000c
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW__SHIFT 0x00000008
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK_MASK 0x10000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK__SHIFT 0x0000001c
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_MASK 0x00100000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED_MASK 0x01000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED__SHIFT 0x00000018
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW__SHIFT 0x00000014
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE_MASK 0x40000000L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE__SHIFT 0x0000001e
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MASK 0x007fff00L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE_MASK 0x00000003L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE__SHIFT 0x00000000
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT__SHIFT 0x00000008
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET_MASK 0x3f000000L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET__SHIFT 0x00000018
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL_MASK 0x00000001L
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL__SHIFT 0x00000000
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP_MASK 0xffffff00L
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP__SHIFT 0x00000008
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN_MASK 0x00000010L
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN__SHIFT 0x00000004
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN_MASK 0x80000000L
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN__SHIFT 0x0000001f
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT_MASK 0x1fff0000L
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT__SHIFT 0x00000010
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT_MASK 0x00001fffL
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT__SHIFT 0x00000000
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_MASK 0x00001fffL
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET_MASK 0x80000000L
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET__SHIFT 0x0000001f
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT__SHIFT 0x00000000
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED_MASK 0x1fff0000L
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED__SHIFT 0x00000010
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED_MASK 0x00001fffL
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11_MASK 0x0000ffffL
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11__SHIFT 0x00000000
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12_MASK 0xffff0000L
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12__SHIFT 0x00000010
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13_MASK 0x0000ffffL
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13__SHIFT 0x00000000
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14_MASK 0xffff0000L
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14__SHIFT 0x00000010
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21_MASK 0x0000ffffL
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21__SHIFT 0x00000000
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22_MASK 0xffff0000L
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22__SHIFT 0x00000010
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23_MASK 0x0000ffffL
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23__SHIFT 0x00000000
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24_MASK 0xffff0000L
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24__SHIFT 0x00000010
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31_MASK 0x0000ffffL
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31__SHIFT 0x00000000
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32_MASK 0xffff0000L
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32__SHIFT 0x00000010
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33_MASK 0x0000ffffL
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33__SHIFT 0x00000000
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34_MASK 0xffff0000L
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34__SHIFT 0x00000010
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE_MASK 0x00000007L
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE__SHIFT 0x00000000
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE_MASK 0x00000070L
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE__SHIFT 0x00000004
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE_MASK 0x0000000fL
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE__SHIFT 0x00000000
+#define OVL_CONTROL1__OVL_ADDRESS_TRANSLATION_ENABLE_MASK 0x00010000L
+#define OVL_CONTROL1__OVL_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000010
+#define OVL_CONTROL1__OVL_ARRAY_MODE_MASK 0x00f00000L
+#define OVL_CONTROL1__OVL_ARRAY_MODE__SHIFT 0x00000014
+#define OVL_CONTROL1__OVL_BANK_HEIGHT_MASK 0x00001800L
+#define OVL_CONTROL1__OVL_BANK_HEIGHT__SHIFT 0x0000000b
+#define OVL_CONTROL1__OVL_BANK_WIDTH_MASK 0x000000c0L
+#define OVL_CONTROL1__OVL_BANK_WIDTH__SHIFT 0x00000006
+#define OVL_CONTROL1__OVL_COLOR_EXPANSION_MODE_MASK 0x01000000L
+#define OVL_CONTROL1__OVL_COLOR_EXPANSION_MODE__SHIFT 0x00000018
+#define OVL_CONTROL1__OVL_DEPTH_MASK 0x00000003L
+#define OVL_CONTROL1__OVL_DEPTH__SHIFT 0x00000000
+#define OVL_CONTROL1__OVL_FORMAT_MASK 0x00000700L
+#define OVL_CONTROL1__OVL_FORMAT__SHIFT 0x00000008
+#define OVL_CONTROL1__OVL_MACRO_TILE_ASPECT_MASK 0x000c0000L
+#define OVL_CONTROL1__OVL_MACRO_TILE_ASPECT__SHIFT 0x00000012
+#define OVL_CONTROL1__OVL_NUM_BANKS_MASK 0x0000000cL
+#define OVL_CONTROL1__OVL_NUM_BANKS__SHIFT 0x00000002
+#define OVL_CONTROL1__OVL_PIPE_CONFIG_MASK 0x3e000000L
+#define OVL_CONTROL1__OVL_PIPE_CONFIG__SHIFT 0x00000019
+#define OVL_CONTROL1__OVL_PRIVILEGED_ACCESS_ENABLE_MASK 0x00020000L
+#define OVL_CONTROL1__OVL_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000011
+#define OVL_CONTROL1__OVL_TILE_SPLIT_MASK 0x0000e000L
+#define OVL_CONTROL1__OVL_TILE_SPLIT__SHIFT 0x0000000d
+#define OVL_CONTROL1__OVL_Z_MASK 0x00000030L
+#define OVL_CONTROL1__OVL_Z__SHIFT 0x00000004
+#define OVL_CONTROL2__OVL_HALF_RESOLUTION_ENABLE_MASK 0x00000001L
+#define OVL_CONTROL2__OVL_HALF_RESOLUTION_ENABLE__SHIFT 0x00000000
+#define OVL_DFQ_CONTROL__OVL_DFQ_MIN_FREE_ENTRIES_MASK 0x00000700L
+#define OVL_DFQ_CONTROL__OVL_DFQ_MIN_FREE_ENTRIES__SHIFT 0x00000008
+#define OVL_DFQ_CONTROL__OVL_DFQ_RESET_MASK 0x00000001L
+#define OVL_DFQ_CONTROL__OVL_DFQ_RESET__SHIFT 0x00000000
+#define OVL_DFQ_CONTROL__OVL_DFQ_SIZE_MASK 0x00000070L
+#define OVL_DFQ_CONTROL__OVL_DFQ_SIZE__SHIFT 0x00000004
+#define OVL_DFQ_STATUS__OVL_DFQ_NUM_ENTRIES_MASK 0x0000000fL
+#define OVL_DFQ_STATUS__OVL_DFQ_NUM_ENTRIES__SHIFT 0x00000000
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_ACK_MASK 0x00000200L
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_ACK__SHIFT 0x00000009
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_FLAG_MASK 0x00000100L
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_FLAG__SHIFT 0x00000008
+#define OVL_DFQ_STATUS__OVL_SECONDARY_DFQ_NUM_ENTRIES_MASK 0x000000f0L
+#define OVL_DFQ_STATUS__OVL_SECONDARY_DFQ_NUM_ENTRIES__SHIFT 0x00000004
+#define OVL_ENABLE__OVL_ENABLE_MASK 0x00000001L
+#define OVL_ENABLE__OVL_ENABLE__SHIFT 0x00000000
+#define OVL_ENABLE__OVLSCL_EN_MASK 0x00000100L
+#define OVL_ENABLE__OVLSCL_EN__SHIFT 0x00000008
+#define OVL_END__OVL_X_END_MASK 0x7fff0000L
+#define OVL_END__OVL_X_END__SHIFT 0x00000010
+#define OVL_END__OVL_Y_END_MASK 0x00007fffL
+#define OVL_END__OVL_Y_END__SHIFT 0x00000000
+#define OVL_PITCH__OVL_PITCH_MASK 0x00007fffL
+#define OVL_PITCH__OVL_PITCH__SHIFT 0x00000000
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_BCB_MASK 0x000003ffL
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_BCB__SHIFT 0x00000000
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_GY_MASK 0x000ffc00L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_GY__SHIFT 0x0000000a
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_RCR_MASK 0x3ff00000L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_RCR__SHIFT 0x00000014
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_EDGE_PIXEL_SEL_MASK 0x80000000L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_EDGE_PIXEL_SEL__SHIFT 0x0000001f
+#define OVL_SECONDARY_SURFACE_ADDRESS_HIGH__OVL_SECONDARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define OVL_SECONDARY_SURFACE_ADDRESS_HIGH__OVL_SECONDARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_DFQ_ENABLE_MASK 0x00000001L
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_DFQ_ENABLE__SHIFT 0x00000000
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define OVL_START__OVL_X_START_MASK 0x3fff0000L
+#define OVL_START__OVL_X_START__SHIFT 0x00000010
+#define OVL_START__OVL_Y_START_MASK 0x00003fffL
+#define OVL_START__OVL_Y_START__SHIFT 0x00000000
+#define OVL_STEREOSYNC_FLIP__OVL_PRIMARY_SURFACE_PENDING_MASK 0x00010000L
+#define OVL_STEREOSYNC_FLIP__OVL_PRIMARY_SURFACE_PENDING__SHIFT 0x00000010
+#define OVL_STEREOSYNC_FLIP__OVL_SECONDARY_SURFACE_PENDING_MASK 0x00020000L
+#define OVL_STEREOSYNC_FLIP__OVL_SECONDARY_SURFACE_PENDING__SHIFT 0x00000011
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_EN_MASK 0x00000001L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_EN__SHIFT 0x00000000
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_MODE_MASK 0x00000300L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_MODE__SHIFT 0x00000008
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_SELECT_DISABLE__SHIFT 0x0000001c
+#define OVL_SURFACE_ADDRESS_HIGH_INUSE__OVL_SURFACE_ADDRESS_HIGH_INUSE_MASK 0x000000ffL
+#define OVL_SURFACE_ADDRESS_HIGH_INUSE__OVL_SURFACE_ADDRESS_HIGH_INUSE__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS_HIGH__OVL_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define OVL_SURFACE_ADDRESS_HIGH__OVL_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS_INUSE__OVL_SURFACE_ADDRESS_INUSE_MASK 0xffffff00L
+#define OVL_SURFACE_ADDRESS_INUSE__OVL_SURFACE_ADDRESS_INUSE__SHIFT 0x00000008
+#define OVL_SURFACE_ADDRESS__OVL_DFQ_ENABLE_MASK 0x00000001L
+#define OVL_SURFACE_ADDRESS__OVL_DFQ_ENABLE__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS__OVL_SURFACE_ADDRESS_MASK 0xffffff00L
+#define OVL_SURFACE_ADDRESS__OVL_SURFACE_ADDRESS__SHIFT 0x00000008
+#define OVL_SURFACE_OFFSET_X__OVL_SURFACE_OFFSET_X_MASK 0x00003fffL
+#define OVL_SURFACE_OFFSET_X__OVL_SURFACE_OFFSET_X__SHIFT 0x00000000
+#define OVL_SURFACE_OFFSET_Y__OVL_SURFACE_OFFSET_Y_MASK 0x00003fffL
+#define OVL_SURFACE_OFFSET_Y__OVL_SURFACE_OFFSET_Y__SHIFT 0x00000000
+#define OVL_SWAP_CNTL__OVL_ALPHA_CROSSBAR_MASK 0x00000c00L
+#define OVL_SWAP_CNTL__OVL_ALPHA_CROSSBAR__SHIFT 0x0000000a
+#define OVL_SWAP_CNTL__OVL_BLUE_CROSSBAR_MASK 0x00000300L
+#define OVL_SWAP_CNTL__OVL_BLUE_CROSSBAR__SHIFT 0x00000008
+#define OVL_SWAP_CNTL__OVL_ENDIAN_SWAP_MASK 0x00000003L
+#define OVL_SWAP_CNTL__OVL_ENDIAN_SWAP__SHIFT 0x00000000
+#define OVL_SWAP_CNTL__OVL_GREEN_CROSSBAR_MASK 0x000000c0L
+#define OVL_SWAP_CNTL__OVL_GREEN_CROSSBAR__SHIFT 0x00000006
+#define OVL_SWAP_CNTL__OVL_RED_CROSSBAR_MASK 0x00000030L
+#define OVL_SWAP_CNTL__OVL_RED_CROSSBAR__SHIFT 0x00000004
+#define OVL_UPDATE__OVL_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define OVL_UPDATE__OVL_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define OVL_UPDATE__OVL_UPDATE_LOCK_MASK 0x00010000L
+#define OVL_UPDATE__OVL_UPDATE_LOCK__SHIFT 0x00000010
+#define OVL_UPDATE__OVL_UPDATE_PENDING_MASK 0x00000001L
+#define OVL_UPDATE__OVL_UPDATE_PENDING__SHIFT 0x00000000
+#define OVL_UPDATE__OVL_UPDATE_TAKEN_MASK 0x00000002L
+#define OVL_UPDATE__OVL_UPDATE_TAKEN__SHIFT 0x00000001
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL_MASK 0x00010000L
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL__SHIFT 0x00000010
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN_MASK 0x00001000L
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN__SHIFT 0x0000000c
+#define PHY_AUX_CNTL__AUX_PAD_WAKE_MASK 0x00004000L
+#define PHY_AUX_CNTL__AUX_PAD_WAKE__SHIFT 0x0000000e
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON_MASK 0x00000001L
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE_MASK 0x00000001L
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE__SHIFT 0x00000000
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON_MASK 0x00000001L
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE_MASK 0x00000001L
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE__SHIFT 0x00000000
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON_MASK 0x00000001L
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE_MASK 0x00000001L
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE__SHIFT 0x00000000
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON_MASK 0x00000001L
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE_MASK 0x00000001L
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE__SHIFT 0x00000000
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON_MASK 0x00000001L
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE_MASK 0x00000001L
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE__SHIFT 0x00000000
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON_MASK 0x00000001L
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE_MASK 0x00000001L
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE__SHIFT 0x00000000
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0_MASK 0x00000030L
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0__SHIFT 0x00000004
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE__SHIFT 0x00000000
+#define PIXCLK1_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL1_MASK 0x00000030L
+#define PIXCLK1_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL1__SHIFT 0x00000004
+#define PIXCLK1_RESYNC_CNTL__PIXCLK1_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK1_RESYNC_CNTL__PIXCLK1_RESYNC_ENABLE__SHIFT 0x00000000
+#define PIXCLK2_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL2_MASK 0x00000030L
+#define PIXCLK2_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL2__SHIFT 0x00000004
+#define PIXCLK2_RESYNC_CNTL__PIXCLK2_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK2_RESYNC_CNTL__PIXCLK2_RESYNC_ENABLE__SHIFT 0x00000000
+#define PLL_ANALOG__PLL_CAL_MODE_MASK 0x0000001fL
+#define PLL_ANALOG__PLL_CAL_MODE__SHIFT 0x00000000
+#define PLL_ANALOG__PLL_CP_MASK 0x00000f00L
+#define PLL_ANALOG__PLL_CP__SHIFT 0x00000008
+#define PLL_ANALOG__PLL_IBIAS_MASK 0xff000000L
+#define PLL_ANALOG__PLL_IBIAS__SHIFT 0x00000018
+#define PLL_ANALOG__PLL_LF_MODE_MASK 0x001ff000L
+#define PLL_ANALOG__PLL_LF_MODE__SHIFT 0x0000000c
+#define PLL_ANALOG__PLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define PLL_ANALOG__PLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define PLL_CNTL__PLL_ANTIGLITCH_RESETB_MASK 0x00000080L
+#define PLL_CNTL__PLL_ANTIGLITCH_RESETB__SHIFT 0x00000007
+#define PLL_CNTL__PLL_ANTI_GLITCH_RESET_MASK 0x00002000L
+#define PLL_CNTL__PLL_ANTI_GLITCH_RESET__SHIFT 0x0000000d
+#define PLL_CNTL__PLL_BYPASS_CAL_MASK 0x00000004L
+#define PLL_CNTL__PLL_BYPASS_CAL__SHIFT 0x00000002
+#define PLL_CNTL__PLL_CAL_BYPASS_REFDIV_MASK 0x00000400L
+#define PLL_CNTL__PLL_CAL_BYPASS_REFDIV__SHIFT 0x0000000a
+#define PLL_CNTL__PLL_CALIB_DONE_MASK 0x00100000L
+#define PLL_CNTL__PLL_CALIB_DONE__SHIFT 0x00000014
+#define PLL_CNTL__PLL_CALREF_MASK 0x00000300L
+#define PLL_CNTL__PLL_CALREF__SHIFT 0x00000008
+#define PLL_CNTL__PLL_DIG_SPARE_MASK 0xfc000000L
+#define PLL_CNTL__PLL_DIG_SPARE__SHIFT 0x0000001a
+#define PLL_CNTL__PLL_LOCKED_MASK 0x00200000L
+#define PLL_CNTL__PLL_LOCKED__SHIFT 0x00000015
+#define PLL_CNTL__PLL_LOCK_FREQ_SEL_MASK 0x00080000L
+#define PLL_CNTL__PLL_LOCK_FREQ_SEL__SHIFT 0x00000013
+#define PLL_CNTL__PLL_PCIE_REFCLK_SEL_MASK 0x00000040L
+#define PLL_CNTL__PLL_PCIE_REFCLK_SEL__SHIFT 0x00000006
+#define PLL_CNTL__PLL_POST_DIV_SRC_MASK 0x00000008L
+#define PLL_CNTL__PLL_POST_DIV_SRC__SHIFT 0x00000003
+#define PLL_CNTL__PLL_POWER_DOWN_MASK 0x00000002L
+#define PLL_CNTL__PLL_POWER_DOWN__SHIFT 0x00000001
+#define PLL_CNTL__PLL_REFCLK_SEL_MASK 0x00001800L
+#define PLL_CNTL__PLL_REFCLK_SEL__SHIFT 0x0000000b
+#define PLL_CNTL__PLL_REF_DIV_SRC_MASK 0x00070000L
+#define PLL_CNTL__PLL_REF_DIV_SRC__SHIFT 0x00000010
+#define PLL_CNTL__PLL_RESET_MASK 0x00000001L
+#define PLL_CNTL__PLL_RESET__SHIFT 0x00000000
+#define PLL_CNTL__PLL_TIMING_MODE_STATUS_MASK 0x03000000L
+#define PLL_CNTL__PLL_TIMING_MODE_STATUS__SHIFT 0x00000018
+#define PLL_CNTL__PLL_VCOREF_MASK 0x00000030L
+#define PLL_CNTL__PLL_VCOREF__SHIFT 0x00000004
+#define PLL_DEBUG_CNTL__PLL_DEBUG_CLK_SEL_MASK 0x00000f00L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_CLK_SEL__SHIFT 0x00000008
+#define PLL_DEBUG_CNTL__PLL_DEBUG_MUXOUT_SEL_MASK 0x000000f0L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_MUXOUT_SEL__SHIFT 0x00000004
+#define PLL_DEBUG_CNTL__PLL_DEBUG_SIGNALS_ENABLE_MASK 0x00000001L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_SIGNALS_ENABLE__SHIFT 0x00000000
+#define PLL_DISPCLK_CURRENT_DTO_PHASE__PLL_DISPCLK_CURRENT_DTO_PHASE_MASK 0x000001ffL
+#define PLL_DISPCLK_CURRENT_DTO_PHASE__PLL_DISPCLK_CURRENT_DTO_PHASE__SHIFT 0x00000000
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_COMPL_DELAY_MASK 0xff000000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_COMPL_DELAY__SHIFT 0x00000018
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_DIS_MASK 0x00010000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_DIS__SHIFT 0x00000010
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_PHASE_MASK 0x000001ffL
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_PHASE__SHIFT 0x00000000
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_ACK_MASK 0x00400000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_ACK__SHIFT 0x00000016
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_MODE_MASK 0x00060000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_MODE__SHIFT 0x00000011
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_PENDING_MASK 0x00100000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_PENDING__SHIFT 0x00000014
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_REQ_MASK 0x00200000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_REQ__SHIFT 0x00000015
+#define PLL_DS_CNTL__PLL_DS_FRAC_MASK 0x0000ffffL
+#define PLL_DS_CNTL__PLL_DS_FRAC__SHIFT 0x00000000
+#define PLL_DS_CNTL__PLL_DS_MODE_MASK 0x00040000L
+#define PLL_DS_CNTL__PLL_DS_MODE__SHIFT 0x00000012
+#define PLL_DS_CNTL__PLL_DS_ORDER_MASK 0x00030000L
+#define PLL_DS_CNTL__PLL_DS_ORDER__SHIFT 0x00000010
+#define PLL_DS_CNTL__PLL_DS_PRBS_EN_MASK 0x00080000L
+#define PLL_DS_CNTL__PLL_DS_PRBS_EN__SHIFT 0x00000013
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define PLL_FB_DIV__PLL_FB_DIV_MASK 0x0fff0000L
+#define PLL_FB_DIV__PLL_FB_DIV__SHIFT 0x00000010
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_MASK 0x000f0000L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_RESET_MASK 0x00000100L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_RESET__SHIFT 0x00000008
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_SELECT_MASK 0x00001000L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_SELECT__SHIFT 0x0000000c
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV__SHIFT 0x00000010
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_DIFF_EN_MASK 0x00000002L
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_DIFF_EN__SHIFT 0x00000001
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_EN_MASK 0x00000001L
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_EN__SHIFT 0x00000000
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_DIFF_EN_MASK 0x00000008L
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_DIFF_EN__SHIFT 0x00000003
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_EN_MASK 0x00000004L
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_EN__SHIFT 0x00000002
+#define PLL_IDCLK_CNTL__PLL_UNIPHY_IDCLK_DIFF_EN_MASK 0x00000010L
+#define PLL_IDCLK_CNTL__PLL_UNIPHY_IDCLK_DIFF_EN__SHIFT 0x00000004
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DISPCLK_MASK 0x00000080L
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DISPCLK__SHIFT 0x00000007
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DPREFCLK_MASK 0x00008000L
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DPREFCLK__SHIFT 0x0000000f
+#define PLL_POST_DIV__PLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define PLL_POST_DIV__PLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define PLL_POST_DIV__PLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define PLL_POST_DIV__PLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define PLL_POST_DIV__PLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define PLL_REF_DIV__PLL_CALIBRATION_REF_DIV_MASK 0x0000f000L
+#define PLL_REF_DIV__PLL_CALIBRATION_REF_DIV__SHIFT 0x0000000c
+#define PLL_REF_DIV__PLL_REF_DIV_MASK 0x000003ffL
+#define PLL_REF_DIV__PLL_REF_DIV__SHIFT 0x00000000
+#define PLL_SS_AMOUNT_DSFRAC__PLL_SS_AMOUNT_DSFRAC_MASK 0x0000ffffL
+#define PLL_SS_AMOUNT_DSFRAC__PLL_SS_AMOUNT_DSFRAC__SHIFT 0x00000000
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_FBDIV_MASK 0x000000ffL
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_FBDIV__SHIFT 0x00000000
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_NFRAC_SLIP_MASK 0x00000f00L
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_NFRAC_SLIP__SHIFT 0x00000008
+#define PLL_SS_CNTL__PLL_SS_EN_MASK 0x00001000L
+#define PLL_SS_CNTL__PLL_SS_EN__SHIFT 0x0000000c
+#define PLL_SS_CNTL__PLL_SS_MODE_MASK 0x00002000L
+#define PLL_SS_CNTL__PLL_SS_MODE__SHIFT 0x0000000d
+#define PLL_SS_CNTL__PLL_SS_STEP_SIZE_DSFRAC_MASK 0xffff0000L
+#define PLL_SS_CNTL__PLL_SS_STEP_SIZE_DSFRAC__SHIFT 0x00000010
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_COUNT_MASK 0x00000070L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_COUNT__SHIFT 0x00000004
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DETECT_ENABLE_MASK 0x00000001L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DETECT_ENABLE__SHIFT 0x00000000
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_RES100_SELECT_MASK 0x00000002L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_RES100_SELECT__SHIFT 0x00000001
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_CLEAR_MASK 0x00000008L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_CLEAR__SHIFT 0x00000003
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_STATUS_MASK 0x00000004L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_STATUS__SHIFT 0x00000002
+#define PLL_UPDATE_CNTL__PLL_AUTO_RESET_DISABLE_MASK 0x00010000L
+#define PLL_UPDATE_CNTL__PLL_AUTO_RESET_DISABLE__SHIFT 0x00000010
+#define PLL_UPDATE_CNTL__PLL_UPDATE_PENDING_MASK 0x00000001L
+#define PLL_UPDATE_CNTL__PLL_UPDATE_PENDING__SHIFT 0x00000000
+#define PLL_UPDATE_CNTL__PLL_UPDATE_POINT_MASK 0x00000100L
+#define PLL_UPDATE_CNTL__PLL_UPDATE_POINT__SHIFT 0x00000008
+#define PLL_UPDATE_LOCK__PLL_UPDATE_LOCK_MASK 0x00000001L
+#define PLL_UPDATE_LOCK__PLL_UPDATE_LOCK__SHIFT 0x00000000
+#define PLL_VREG_CNTL__PLL_VREF_SEL_MASK 0x04000000L
+#define PLL_VREG_CNTL__PLL_VREF_SEL__SHIFT 0x0000001a
+#define PLL_VREG_CNTL__PLL_VREG_BIAS_MASK 0xf0000000L
+#define PLL_VREG_CNTL__PLL_VREG_BIAS__SHIFT 0x0000001c
+#define PLL_VREG_CNTL__PLL_VREG_CNTL_MASK 0x000fffffL
+#define PLL_VREG_CNTL__PLL_VREG_CNTL__SHIFT 0x00000000
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN_MASK 0x00000008L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN__SHIFT 0x00000003
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS_MASK 0x00000010L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS__SHIFT 0x00000004
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN_MASK 0x00000004L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN__SHIFT 0x00000002
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN_MASK 0x00000002L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN__SHIFT 0x00000001
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT_MASK 0x00000001L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT__SHIFT 0x00000000
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS_MASK 0x00000010L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS__SHIFT 0x00000004
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CB_SIGN_MASK 0x00000002L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CB_SIGN__SHIFT 0x00000001
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CR_SIGN_MASK 0x00000008L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CR_SIGN__SHIFT 0x00000003
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_SELECT_MASK 0x00000001L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_SELECT__SHIFT 0x00000000
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_Y_SIGN_MASK 0x00000004L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_Y_SIGN__SHIFT 0x00000002
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B__SHIFT 0x00000010
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G__SHIFT 0x00000010
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_BIAS_CB_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_BIAS_CB__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_SCALE_CB_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_SCALE_CB__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_BIAS_CR_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_BIAS_CR__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_SCALE_CR_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_SCALE_CR__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_BIAS_Y_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_BIAS_Y__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_SCALE_Y_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_SCALE_Y__SHIFT 0x00000010
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END_MASK 0x0000ffffL
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END__SHIFT 0x00000000
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE_MASK 0xffff0000L
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE__SHIFT 0x00000010
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE_MASK 0x0000ffffL
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE_MASK 0x0003ffffL
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_MASK 0x0003ffffL
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT_MASK 0x07f00000L
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT__SHIFT 0x00000014
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START__SHIFT 0x00000000
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END_MASK 0x0000ffffL
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END__SHIFT 0x00000000
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE_MASK 0xffff0000L
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE__SHIFT 0x00000010
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE_MASK 0x0000ffffL
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE_MASK 0x0003ffffL
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_MASK 0x0003ffffL
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT_MASK 0x07f00000L
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT__SHIFT 0x00000014
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START__SHIFT 0x00000000
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE_MASK 0x00000007L
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE__SHIFT 0x00000000
+#define REGAMMA_CONTROL__OVL_REGAMMA_MODE_MASK 0x00000070L
+#define REGAMMA_CONTROL__OVL_REGAMMA_MODE__SHIFT 0x00000004
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA_MASK 0x0007ffffL
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA__SHIFT 0x00000000
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX_MASK 0x000001ffL
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX__SHIFT 0x00000000
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK_MASK 0x00000007L
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK__SHIFT 0x00000000
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE_MASK 0x00000001L
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE__SHIFT 0x00000000
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE_MASK 0x00000003L
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE__SHIFT 0x00000000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK_MASK 0x00000100L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK__SHIFT 0x00000008
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG_MASK 0x00000001L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG__SHIFT 0x00000000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS_MASK 0x00010000L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS__SHIFT 0x00000010
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK_MASK 0x00001000L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK__SHIFT 0x0000000c
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE_MASK 0x00030000L
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE__SHIFT 0x00000010
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE_MASK 0x00000f00L
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE__SHIFT 0x00000008
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX_MASK 0x0000000fL
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX__SHIFT 0x00000000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN_MASK 0x00008000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN__SHIFT 0x0000000f
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_MASK 0x00003fffL
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF__SHIFT 0x00000000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN_MASK 0x80000000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN__SHIFT 0x0000001f
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_MASK 0x3fff0000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF__SHIFT 0x00000010
+#define SCL_DEBUG2__SCL_DEBUG2_MASK 0xffffffffL
+#define SCL_DEBUG2__SCL_DEBUG2__SHIFT 0x00000000
+#define SCL_DEBUG__SCL_DEBUG_MASK 0xffffffffL
+#define SCL_DEBUG__SCL_DEBUG__SHIFT 0x00000000
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN_MASK 0x00000010L
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN__SHIFT 0x00000004
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR_MASK 0x00000007L
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR__SHIFT 0x00000000
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN_MASK 0x00001000L
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN__SHIFT 0x0000000c
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR_MASK 0x00000700L
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR__SHIFT 0x00000008
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST_MASK 0x00000001L
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST__SHIFT 0x00000000
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO_MASK 0x03ffffffL
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO__SHIFT 0x00000000
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR_MASK 0x00000f00L
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR__SHIFT 0x00000008
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR_MASK 0x0000000fL
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO_MASK 0x0fffff80L
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO__SHIFT 0x00000007
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK_MASK 0x00000010L
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK__SHIFT 0x00000004
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_MASK 0x00000001L
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO_MASK 0x001fffffL
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT_MASK 0x00003fffL
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH_MASK 0x3fff0000L
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH__SHIFT 0x00000010
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK_MASK 0x00000001L
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define SCL_UPDATE__SCL_UPDATE_LOCK_MASK 0x00010000L
+#define SCL_UPDATE__SCL_UPDATE_LOCK__SHIFT 0x00000010
+#define SCL_UPDATE__SCL_UPDATE_PENDING_MASK 0x00000001L
+#define SCL_UPDATE__SCL_UPDATE_PENDING__SHIFT 0x00000000
+#define SCL_UPDATE__SCL_UPDATE_TAKEN_MASK 0x00000100L
+#define SCL_UPDATE__SCL_UPDATE_TAKEN__SHIFT 0x00000008
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST_MASK 0x00000001L
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT_MASK 0x0000ffffL
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT_MASK 0x00070000L
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT__SHIFT 0x00000010
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC_MASK 0x0000ffffL
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT_MASK 0x00070000L
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT__SHIFT 0x00000010
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO_MASK 0x03ffffffL
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO__SHIFT 0x00000000
+#define SEQ00__SEQ_RST0B_MASK 0x00000001L
+#define SEQ00__SEQ_RST0B__SHIFT 0x00000000
+#define SEQ00__SEQ_RST1B_MASK 0x00000002L
+#define SEQ00__SEQ_RST1B__SHIFT 0x00000001
+#define SEQ01__SEQ_DOT8_MASK 0x00000001L
+#define SEQ01__SEQ_DOT8__SHIFT 0x00000000
+#define SEQ01__SEQ_MAXBW_MASK 0x00000020L
+#define SEQ01__SEQ_MAXBW__SHIFT 0x00000005
+#define SEQ01__SEQ_PCLKBY2_MASK 0x00000008L
+#define SEQ01__SEQ_PCLKBY2__SHIFT 0x00000003
+#define SEQ01__SEQ_SHIFT2_MASK 0x00000004L
+#define SEQ01__SEQ_SHIFT2__SHIFT 0x00000002
+#define SEQ01__SEQ_SHIFT4_MASK 0x00000010L
+#define SEQ01__SEQ_SHIFT4__SHIFT 0x00000004
+#define SEQ02__SEQ_MAP0_EN_MASK 0x00000001L
+#define SEQ02__SEQ_MAP0_EN__SHIFT 0x00000000
+#define SEQ02__SEQ_MAP1_EN_MASK 0x00000002L
+#define SEQ02__SEQ_MAP1_EN__SHIFT 0x00000001
+#define SEQ02__SEQ_MAP2_EN_MASK 0x00000004L
+#define SEQ02__SEQ_MAP2_EN__SHIFT 0x00000002
+#define SEQ02__SEQ_MAP3_EN_MASK 0x00000008L
+#define SEQ02__SEQ_MAP3_EN__SHIFT 0x00000003
+#define SEQ03__SEQ_FONT_A0_MASK 0x00000020L
+#define SEQ03__SEQ_FONT_A0__SHIFT 0x00000005
+#define SEQ03__SEQ_FONT_A1_MASK 0x00000004L
+#define SEQ03__SEQ_FONT_A1__SHIFT 0x00000002
+#define SEQ03__SEQ_FONT_A2_MASK 0x00000008L
+#define SEQ03__SEQ_FONT_A2__SHIFT 0x00000003
+#define SEQ03__SEQ_FONT_B0_MASK 0x00000010L
+#define SEQ03__SEQ_FONT_B0__SHIFT 0x00000004
+#define SEQ03__SEQ_FONT_B1_MASK 0x00000001L
+#define SEQ03__SEQ_FONT_B1__SHIFT 0x00000000
+#define SEQ03__SEQ_FONT_B2_MASK 0x00000002L
+#define SEQ03__SEQ_FONT_B2__SHIFT 0x00000001
+#define SEQ04__SEQ_256K_MASK 0x00000002L
+#define SEQ04__SEQ_256K__SHIFT 0x00000001
+#define SEQ04__SEQ_CHAIN_MASK 0x00000008L
+#define SEQ04__SEQ_CHAIN__SHIFT 0x00000003
+#define SEQ04__SEQ_ODDEVEN_MASK 0x00000004L
+#define SEQ04__SEQ_ODDEVEN__SHIFT 0x00000002
+#define SEQ8_DATA__SEQ_DATA_MASK 0x000000ffL
+#define SEQ8_DATA__SEQ_DATA__SHIFT 0x00000000
+#define SEQ8_IDX__SEQ_IDX_MASK 0x00000007L
+#define SEQ8_IDX__SEQ_IDX__SHIFT 0x00000000
+#define SINK_DESCRIPTION0__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION0__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION10__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION10__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION11__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION11__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION12__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION12__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION13__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION13__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION14__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION14__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION15__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION15__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION16__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION16__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION17__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION17__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION1__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION1__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION2__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION2__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION3__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION3__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION4__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION4__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION5__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION5__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION6__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION6__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION7__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION7__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION8__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION8__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION9__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION9__DESCRIPTION__SHIFT 0x00000000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS_MASK 0x00000100L
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS__SHIFT 0x00000008
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT_MASK 0x00000001L
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3__SHIFT 0x00000018
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC__SHIFT 0x00000008
+#define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
+#define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
+#define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
+#define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
+#define TMDS_CNTL__TMDS_SYNC_PHASE_MASK 0x00000001L
+#define TMDS_CNTL__TMDS_SYNC_PHASE__SHIFT 0x00000000
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY_MASK 0x00000300L
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY__SHIFT 0x00000008
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT_MASK 0x00000003L
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT__SHIFT 0x00000000
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN_MASK 0x00000001L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN__SHIFT 0x00000000
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN_MASK 0x00000002L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN__SHIFT 0x00000001
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN_MASK 0x00000004L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN__SHIFT 0x00000002
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN_MASK 0x00000008L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN__SHIFT 0x00000003
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN_MASK 0x80000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN__SHIFT 0x0000001f
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY_MASK 0x00000070L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY__SHIFT 0x00000004
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT_MASK 0x00000080L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT__SHIFT 0x00000007
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION_MASK 0x00000300L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION__SHIFT 0x00000008
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL_MASK 0x0000000fL
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL__SHIFT 0x00000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT_MASK 0x00000800L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT__SHIFT 0x0000000b
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN_MASK 0x00001000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN__SHIFT 0x0000000c
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH_MASK 0x00000400L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH__SHIFT 0x0000000a
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY_MASK 0x00700000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY__SHIFT 0x00000014
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT_MASK 0x00800000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT__SHIFT 0x00000017
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION_MASK 0x03000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION__SHIFT 0x00000018
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL_MASK 0x000f0000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL__SHIFT 0x00000010
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT_MASK 0x08000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT__SHIFT 0x0000001b
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN_MASK 0x10000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN__SHIFT 0x0000001c
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH_MASK 0x04000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH__SHIFT 0x0000001a
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY_MASK 0x00000070L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY__SHIFT 0x00000004
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT_MASK 0x00000080L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT__SHIFT 0x00000007
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION_MASK 0x00000300L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION__SHIFT 0x00000008
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL_MASK 0x0000000fL
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL__SHIFT 0x00000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT_MASK 0x00000800L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT__SHIFT 0x0000000b
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN_MASK 0x00001000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN__SHIFT 0x0000000c
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH_MASK 0x00000400L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH__SHIFT 0x0000000a
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY_MASK 0x00700000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY__SHIFT 0x00000014
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT_MASK 0x00800000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT__SHIFT 0x00000017
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION_MASK 0x03000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION__SHIFT 0x00000018
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL_MASK 0x000f0000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL__SHIFT 0x00000010
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT_MASK 0x08000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT__SHIFT 0x0000001b
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN_MASK 0x10000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN__SHIFT 0x0000001c
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH_MASK 0x04000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH__SHIFT 0x0000001a
+#define TMDS_CTL_BITS__TMDS_CTL0_MASK 0x00000001L
+#define TMDS_CTL_BITS__TMDS_CTL0__SHIFT 0x00000000
+#define TMDS_CTL_BITS__TMDS_CTL1_MASK 0x00000100L
+#define TMDS_CTL_BITS__TMDS_CTL1__SHIFT 0x00000008
+#define TMDS_CTL_BITS__TMDS_CTL2_MASK 0x00010000L
+#define TMDS_CTL_BITS__TMDS_CTL2__SHIFT 0x00000010
+#define TMDS_CTL_BITS__TMDS_CTL3_MASK 0x01000000L
+#define TMDS_CTL_BITS__TMDS_CTL3__SHIFT 0x00000018
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN_MASK 0x00000001L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN__SHIFT 0x00000000
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE_MASK 0x01000000L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE__SHIFT 0x00000018
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN_MASK 0x00000100L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN__SHIFT 0x00000008
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN_MASK 0x000f0000L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN__SHIFT 0x00000010
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN_MASK 0x00000070L
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN__SHIFT 0x00000004
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN_MASK 0x02000000L
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN__SHIFT 0x00000019
+#define TMDS_DEBUG__TMDS_DEBUG_DE_MASK 0x01000000L
+#define TMDS_DEBUG__TMDS_DEBUG_DE__SHIFT 0x00000018
+#define TMDS_DEBUG__TMDS_DEBUG_EN_MASK 0x00000001L
+#define TMDS_DEBUG__TMDS_DEBUG_EN__SHIFT 0x00000000
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN_MASK 0x00000200L
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN__SHIFT 0x00000009
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_MASK 0x00000100L
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC__SHIFT 0x00000008
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN_MASK 0x00020000L
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN__SHIFT 0x00000011
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_MASK 0x00010000L
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC__SHIFT 0x00000010
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL_MASK 0x00000003L
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0_MASK 0x000003ffL
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1_MASK 0x03ff0000L
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1__SHIFT 0x00000010
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2_MASK 0x000003ffL
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3_MASK 0x03ff0000L
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3__SHIFT 0x00000010
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_EN_MASK 0x00010000L
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_EN__SHIFT 0x00000010
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYAB_TPG_SEED__UNIPHYAB_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYAB_TPG_SEED__UNIPHYAB_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_ERROR_MASK 0x001f0000L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_ERROR__SHIFT 0x00000010
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_RESET_MASK 0x00000002L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_RESET__SHIFT 0x00000001
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_PRESETB_MASK 0x01000000L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_PRESETB__SHIFT 0x00000018
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_RX_BIAS_MASK 0x00000f00L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_RX_BIAS__SHIFT 0x00000008
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_TEST_RX_EN_MASK 0x00000001L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_TEST_RX_EN__SHIFT 0x00000000
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_EN_MASK 0x00010000L
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_EN__SHIFT 0x00000010
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYCD_TPG_SEED__UNIPHYCD_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYCD_TPG_SEED__UNIPHYCD_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x00000003L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x00000000
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x00000300L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x00000008
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x00030000L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x00000010
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x03000000L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x00000018
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_ERROR_MASK 0x00000040L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_ERROR__SHIFT 0x00000006
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_LEVEL_MASK 0x00000030L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_LEVEL__SHIFT 0x00000004
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYNSEL_MASK 0x00000001L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYNSEL__SHIFT 0x00000000
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DUAL_LINK_PHASE_MASK 0x00010000L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DUAL_LINK_PHASE__SHIFT 0x00000010
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_LINK_ENABLE_MASK 0x00001000L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_LINK_ENABLE__SHIFT 0x0000000c
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_SOURCE_SELECT_MASK 0x00000100L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_SOURCE_SELECT__SHIFT 0x00000008
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_EN_MASK 0x00010000L
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_EN__SHIFT 0x00000010
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYEF_TPG_SEED__UNIPHYEF_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYEF_TPG_SEED__UNIPHYEF_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD_MASK 0xffffffffL
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF__SHIFT 0x00000010
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x00001000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0x0000000c
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x00002000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0x0000000d
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x00004000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0x0000000e
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x00008000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0x0000000f
+#define UNIPHY_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x00700000L
+#define UNIPHY_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x00000014
+#define UNIPHY_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x00030000L
+#define UNIPHY_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x00000010
+#define UNIPHY_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x00000700L
+#define UNIPHY_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x00000008
+#define UNIPHY_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x00000001L
+#define UNIPHY_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x00000000
+#define UNIPHY_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x00000010L
+#define UNIPHY_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_BW_CNTL_MASK 0x00ff0000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_BW_CNTL__SHIFT 0x00000010
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLK_EN_MASK 0x00000008L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLK_EN__SHIFT 0x00000003
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLKPH_EN_MASK 0x000000f0L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLKPH_EN__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_ENABLE_MASK 0x00000001L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_ENABLE__SHIFT 0x00000000
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_EXT_RESET_EN_MASK 0x00000004L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_EXT_RESET_EN__SHIFT 0x00000002
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_LF_CNTL_MASK 0x00007f00L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_LF_CNTL__SHIFT 0x00000008
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_RESET_MASK 0x00000002L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_RESET__SHIFT 0x00000001
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_EN_MASK 0x02000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_EN__SHIFT 0x00000019
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_SRC_MASK 0x01000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_SRC__SHIFT 0x00000018
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_VCTL_ADC_EN_MASK 0x04000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_VCTL_ADC_EN__SHIFT 0x0000001a
+#define UNIPHY_PLL_CONTROL1__UNIPHY_VCO_MODE_MASK 0x30000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_VCO_MODE__SHIFT 0x0000001c
+#define UNIPHY_PLL_CONTROL2__UNIPHY_CLKINV_MASK 0x00002000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_CLKINV__SHIFT 0x0000000d
+#define UNIPHY_PLL_CONTROL2__UNIPHY_DPLLSEL_MASK 0x0000000cL
+#define UNIPHY_PLL_CONTROL2__UNIPHY_DPLLSEL__SHIFT 0x00000002
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_EN_MASK 0x00001000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_EN__SHIFT 0x0000000c
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_SEL_MASK 0x00000010L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_SEL__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IPCIE_REFCLK_SEL_MASK 0x00000020L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IPCIE_REFCLK_SEL__SHIFT 0x00000005
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IXTALIN_SEL_MASK 0x00000040L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IXTALIN_SEL__SHIFT 0x00000006
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PCIEREF_CLK_EN_MASK 0x00000800L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PCIEREF_CLK_EN__SHIFT 0x0000000b
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIVFRAC_SEL_MASK 0x00100000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIVFRAC_SEL__SHIFT 0x00000014
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIV_SEL_MASK 0xe0000000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIV_SEL__SHIFT 0x0000001d
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_DISPCLK_MODE_MASK 0x00000003L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_DISPCLK_MODE__SHIFT 0x00000000
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFCLK_SRC_MASK 0x00000700L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFCLK_SRC__SHIFT 0x00000008
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFDIV_MASK 0x1f000000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFDIV__SHIFT 0x00000018
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_TEST_FBDIV_FRAC_BYPASS_MASK 0x00080000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_TEST_FBDIV_FRAC_BYPASS__SHIFT 0x00000013
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_VTOI_BIAS_CNTL_MASK 0x00010000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_VTOI_BIAS_CNTL__SHIFT 0x00000010
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_FRACTION_MASK 0x0000fffcL
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_FRACTION__SHIFT 0x00000002
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_MASK 0x0fff0000L
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV__SHIFT 0x00000010
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_DSMOD_EN_MASK 0x00001000L
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_DSMOD_EN__SHIFT 0x0000000c
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_EN_MASK 0x00002000L
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_EN__SHIFT 0x0000000d
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_STEP_NUM_MASK 0x00000fffL
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_STEP_NUM__SHIFT 0x00000000
+#define UNIPHY_PLL_SS_STEP_SIZE__UNIPHY_PLL_SS_STEP_SIZE_MASK 0x03ffffffL
+#define UNIPHY_PLL_SS_STEP_SIZE__UNIPHY_PLL_SS_STEP_SIZE__SHIFT 0x00000000
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ0P45_MASK 0x000f0000L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ0P45__SHIFT 0x00000010
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P00_MASK 0x00000f00L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P00__SHIFT 0x00000008
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P25_MASK 0x0000f000L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P25__SHIFT 0x0000000c
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGPDN_MASK 0x00000001L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGPDN__SHIFT 0x00000000
+#define UNIPHY_POWER_CONTROL__UNIPHY_BIASREF_SEL_MASK 0x00000004L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BIASREF_SEL__SHIFT 0x00000002
+#define UNIPHY_POWER_CONTROL__UNIPHY_RST_LOGIC_MASK 0x00000002L
+#define UNIPHY_POWER_CONTROL__UNIPHY_RST_LOGIC__SHIFT 0x00000001
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_ERROR_MASK 0x01f00000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_ERROR__SHIFT 0x00000014
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_RESET_MASK 0x00008000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_RESET__SHIFT 0x0000000f
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_SEL_MASK 0x00010000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_SEL__SHIFT 0x00000010
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_INTRESET_MASK 0x20000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_INTRESET__SHIFT 0x0000001d
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_FREQ_LOCK_MASK 0x10000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_FREQ_LOCK__SHIFT 0x0000001c
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_VCTL_ADC_MASK 0x0e000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_VCTL_ADC__SHIFT 0x00000019
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_CNTL_MASK 0x0000001fL
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_CNTL__SHIFT 0x00000000
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_VCTL_EN_MASK 0x00020000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_VCTL_EN__SHIFT 0x00000011
+#define UNIPHY_SOFT_RESET__DSYNCA_SOFT_RESET_MASK 0x00000001L
+#define UNIPHY_SOFT_RESET__DSYNCA_SOFT_RESET__SHIFT 0x00000000
+#define UNIPHY_SOFT_RESET__DSYNCB_SOFT_RESET_MASK 0x00000002L
+#define UNIPHY_SOFT_RESET__DSYNCB_SOFT_RESET__SHIFT 0x00000001
+#define UNIPHY_SOFT_RESET__DSYNCC_SOFT_RESET_MASK 0x00000004L
+#define UNIPHY_SOFT_RESET__DSYNCC_SOFT_RESET__SHIFT 0x00000002
+#define UNIPHY_SOFT_RESET__DSYNCD_SOFT_RESET_MASK 0x00000008L
+#define UNIPHY_SOFT_RESET__DSYNCD_SOFT_RESET__SHIFT 0x00000003
+#define UNIPHY_SOFT_RESET__DSYNCE_SOFT_RESET_MASK 0x00000010L
+#define UNIPHY_SOFT_RESET__DSYNCE_SOFT_RESET__SHIFT 0x00000004
+#define UNIPHY_SOFT_RESET__DSYNCF_SOFT_RESET_MASK 0x00000020L
+#define UNIPHY_SOFT_RESET__DSYNCF_SOFT_RESET__SHIFT 0x00000005
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR0_MASK 0x00000007L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR0__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR1_MASK 0x00000070L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR1__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR2_MASK 0x00000700L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR2__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR3_MASK 0x00007000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR3__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR4_MASK 0x00070000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR4__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS0_MASK 0x00300000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS0__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS1_MASK 0x00c00000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS1__SHIFT 0x00000016
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS2_MASK 0x03000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS2__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS3_MASK 0x0c000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS3__SHIFT 0x0000001a
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS4_MASK 0x30000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS4__SHIFT 0x0000001c
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH0_PC_MASK 0x00000003L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH0_PC__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH1_PC_MASK 0x00000030L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH1_PC__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH2_PC_MASK 0x00000300L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH2_PC__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH3_PC_MASK 0x00003000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH3_PC__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH4_PC_MASK 0x00030000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH4_PC__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH_SEL_MASK 0x00100000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH_SEL__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT0_CPSEL_MASK 0x00600000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT0_CPSEL__SHIFT 0x00000015
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT1_CPSEL_MASK 0x01800000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT1_CPSEL__SHIFT 0x00000017
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT2_CPSEL_MASK 0x06000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT2_CPSEL__SHIFT 0x00000019
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT3_CPSEL_MASK 0x18000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT3_CPSEL__SHIFT 0x0000001b
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT4_CPSEL_MASK 0x60000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT4_CPSEL__SHIFT 0x0000001d
+#define UNIPHY_TX_CONTROL3__UNIPHY_LVDS_PULLDWN_MASK 0x80000000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_LVDS_PULLDWN__SHIFT 0x0000001f
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL0_MASK 0x00100000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL0__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL1_MASK 0x00200000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL1__SHIFT 0x00000015
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL2_MASK 0x00400000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL2__SHIFT 0x00000016
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL3_MASK 0x00800000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL3__SHIFT 0x00000017
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_CLK_MASK 0x000000f0L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_CLK__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_DAT_MASK 0x00000f00L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_DAT__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_CLK_MASK 0x00000003L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_CLK__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_DAT_MASK 0x0000000cL
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_DAT__SHIFT 0x00000002
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_CLK_MASK 0x00007000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_CLK__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_DAT_MASK 0x00070000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_DAT__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL3__UNIPHY_TX_VS_ADJ_MASK 0x1f000000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_TX_VS_ADJ__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_CLK_MASK 0x0000001fL
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_CLK__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_DAT_MASK 0x000003e0L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_DAT__SHIFT 0x00000005
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_CLK_MASK 0x07000000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_CLK__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_DAT_MASK 0x70000000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_DAT__SHIFT 0x0000001c
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_CLK_MASK 0x0001f000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_CLK__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_DAT_MASK 0x003e0000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_DAT__SHIFT 0x00000011
+#define VGA25_PPLL_ANALOG__VGA25_CAL_MODE_MASK 0x0000001fL
+#define VGA25_PPLL_ANALOG__VGA25_CAL_MODE__SHIFT 0x00000000
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_CP_MASK 0x00000f00L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_CP__SHIFT 0x00000008
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_IBIAS_MASK 0xff000000L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA25_PPLL_REF_DIV__VGA25_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA25_PPLL_REF_DIV__VGA25_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA28_PPLL_ANALOG__VGA28_CAL_MODE_MASK 0x0000001fL
+#define VGA28_PPLL_ANALOG__VGA28_CAL_MODE__SHIFT 0x00000000
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_CP_MASK 0x00000f00L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_CP__SHIFT 0x00000008
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_IBIAS_MASK 0xff000000L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA28_PPLL_REF_DIV__VGA28_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA28_PPLL_REF_DIV__VGA28_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA41_PPLL_ANALOG__VGA41_CAL_MODE_MASK 0x0000001fL
+#define VGA41_PPLL_ANALOG__VGA41_CAL_MODE__SHIFT 0x00000000
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_CP_MASK 0x00000f00L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_CP__SHIFT 0x00000008
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_IBIAS_MASK 0xff000000L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA41_PPLL_REF_DIV__VGA41_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA41_PPLL_REF_DIV__VGA41_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY_MASK 0x00100000L
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY__SHIFT 0x00000014
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT_MASK 0x3f000000L
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT__SHIFT 0x00000018
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE_MASK 0x00010000L
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE__SHIFT 0x00000010
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE_MASK 0x00000100L
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE__SHIFT 0x00000008
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS_MASK 0x00000001L
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS__SHIFT 0x00000000
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffffL
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x00000000
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA_MASK 0xffffffffL
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA__SHIFT 0x00000000
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX_MASK 0x000000ffL
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX__SHIFT 0x00000000
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR_MASK 0x01ffffffL
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR__SHIFT 0x00000000
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR_MASK 0x01ffffffL
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR__SHIFT 0x00000000
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE_MASK 0x00000010L
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE__SHIFT 0x00000004
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN_MASK 0x00000001L
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN__SHIFT 0x00000000
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE_MASK 0x00000100L
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE__SHIFT 0x00000008
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET_MASK 0x00010000L
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET__SHIFT 0x00000010
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL_MASK 0x01000000L
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL__SHIFT 0x00000018
+#define VGA_HW_DEBUG__VGA_HW_DEBUG_MASK 0xffffffffL
+#define VGA_HW_DEBUG__VGA_HW_DEBUG__SHIFT 0x00000000
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK_MASK 0x00010000L
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK__SHIFT 0x00000010
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK_MASK 0x00000001L
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK__SHIFT 0x00000000
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK_MASK 0x01000000L
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK__SHIFT 0x00000018
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK_MASK 0x00000100L
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK__SHIFT 0x00000008
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS_MASK 0x00000004L
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS__SHIFT 0x00000002
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS_MASK 0x00000001L
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS__SHIFT 0x00000000
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS_MASK 0x00000008L
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS__SHIFT 0x00000003
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS_MASK 0x00000002L
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS__SHIFT 0x00000001
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT_MASK 0x00000003L
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT__SHIFT 0x00000000
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE_MASK 0x20000000L
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE__SHIFT 0x0000001d
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT_MASK 0x80000000L
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT__SHIFT 0x0000001f
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT_MASK 0x03000000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT__SHIFT 0x00000018
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT_MASK 0x00030000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT__SHIFT 0x00000010
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT_MASK 0x04000000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT__SHIFT 0x0000001a
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT_MASK 0x00000300L
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT__SHIFT 0x00000008
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE_MASK 0x08000000L
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE__SHIFT 0x0000001b
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT_MASK 0x00000018L
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT__SHIFT 0x00000003
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION_MASK 0x000000e0L
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION__SHIFT 0x00000005
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE_MASK 0x10000000L
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE__SHIFT 0x0000001c
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH_MASK 0x000000ffL
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH__SHIFT 0x00000000
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS_MASK 0xffffffffL
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS__SHIFT 0x00000000
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR_MASK 0x000003ffL
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR__SHIFT 0x00000000
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR_MASK 0x03ff0000L
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR__SHIFT 0x00000010
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR_MASK 0x000003ffL
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR__SHIFT 0x00000000
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR_MASK 0x03ff0000L
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR__SHIFT 0x00000010
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING_MASK 0x00000100L
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING__SHIFT 0x00000008
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR_MASK 0x00000001L
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR__SHIFT 0x00000000
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE_MASK 0x00000030L
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE__SHIFT 0x00000004
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN_MASK 0x00010000L
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN__SHIFT 0x00000010
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE_MASK 0x00000060L
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE__SHIFT 0x00000005
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE_MASK 0x0000001fL
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE__SHIFT 0x00000000
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT_MASK 0x00000080L
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT__SHIFT 0x00000007
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE_MASK 0x00000100L
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE__SHIFT 0x00000008
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT_MASK 0x01000000L
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT__SHIFT 0x00000018
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL_MASK 0x02000000L
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL__SHIFT 0x00000019
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL_MASK 0x00030000L
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL__SHIFT 0x00000010
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000001L
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000000
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000100L
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x00000008
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000002L
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000001
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000200L
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x00000009
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000004L
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000002
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000400L
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000a
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000008L
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000003
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000800L
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000b
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000010L
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000004
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00001000L
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000c
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000020L
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000005
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00002000L
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000d
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE_MASK 0x00010000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE__SHIFT 0x00000010
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT_MASK 0x00fc0000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT__SHIFT 0x00000012
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT_MASK 0x00020000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT__SHIFT 0x00000011
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A_MASK 0x00000007L
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A__SHIFT 0x00000000
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B_MASK 0x00000700L
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B__SHIFT 0x00000008
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR_MASK 0x00010000L
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR__SHIFT 0x00000010
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR_MASK 0x00000001L
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR__SHIFT 0x00000000
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR_MASK 0x01000000L
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR__SHIFT 0x00000018
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR_MASK 0x00000100L
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR__SHIFT 0x00000008
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS_MASK 0x00000004L
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS__SHIFT 0x00000002
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS_MASK 0x00000001L
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS__SHIFT 0x00000000
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS_MASK 0x00000008L
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS__SHIFT 0x00000003
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS_MASK 0x00000002L
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS__SHIFT 0x00000001
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT_MASK 0x00000300L
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT__SHIFT 0x00000008
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT_MASK 0x00000003L
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT__SHIFT 0x00000000
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE_MASK 0x00000001L
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE__SHIFT 0x00000000
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT_MASK 0x01000000L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT__SHIFT 0x00000018
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE_MASK 0x00010000L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE__SHIFT 0x00000010
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START_MASK 0x00000100L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START__SHIFT 0x00000008
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT_MASK 0x00003fffL
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT__SHIFT 0x00000000
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH_MASK 0x3fff0000L
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH__SHIFT 0x00000010
+#define VIEWPORT_START__VIEWPORT_X_START_MASK 0x3fff0000L
+#define VIEWPORT_START__VIEWPORT_X_START__SHIFT 0x00000010
+#define VIEWPORT_START__VIEWPORT_Y_START_MASK 0x00003fffL
+#define VIEWPORT_START__VIEWPORT_Y_START__SHIFT 0x00000000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS_MASK 0x00008000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS__SHIFT 0x0000000f
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS_MASK 0x00080000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS__SHIFT 0x00000013
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS_MASK 0x00040000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS__SHIFT 0x00000012
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS_MASK 0x00100000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS__SHIFT 0x00000014
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS_MASK 0x00010000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS__SHIFT 0x00000010
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR_MASK 0x00000100L
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR__SHIFT 0x00000008
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS_MASK 0x0000000fL
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS__SHIFT 0x00000000
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK_MASK 0x00000400L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK__SHIFT 0x0000000a
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK_MASK 0x00000200L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK__SHIFT 0x00000009
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT_MASK 0x00000100L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT__SHIFT 0x00000008
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_ACK_MASK 0x00004000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_ACK__SHIFT 0x0000000e
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_MASK_MASK 0x00002000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_MASK__SHIFT 0x0000000d
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_STAT_MASK 0x00001000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_STAT__SHIFT 0x0000000c
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK_MASK 0x00040000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK__SHIFT 0x00000012
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK_MASK 0x00020000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK__SHIFT 0x00000011
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT_MASK 0x00010000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT__SHIFT 0x00000010
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE_MASK 0x0000000fL
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE__SHIFT 0x00000000
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT_MASK 0x00000c00L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT__SHIFT 0x0000000a
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH_MASK 0x00000300L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH__SHIFT 0x00000008
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT_MASK 0x00003000L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT__SHIFT 0x0000000c
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS_MASK 0x00300000L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS__SHIFT 0x00000014
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT_MASK 0x00000070L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT__SHIFT 0x00000004
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE_MASK 0x00c00000L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE__SHIFT 0x00000016
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG_MASK 0xf8000000L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG__SHIFT 0x0000001b
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE_MASK 0x00000007L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE__SHIFT 0x00000000
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV_MASK 0x00010000L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV__SHIFT 0x00000010
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP_MASK 0x00000300L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP__SHIFT 0x00000008
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID_MASK 0x0000f000L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID__SHIFT 0x0000000c
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_MODE_FORCE_MASK 0x00010000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000010
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_POWER_STATE_MASK 0xc0000000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_POWER_STATE__SHIFT 0x0000001e
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_MODE_FORCE_MASK 0x01000000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000018
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE_MASK 0x00040000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE__SHIFT 0x00000012
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE_MASK 0x00010000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE__SHIFT 0x00000010
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY_MASK 0x00000200L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY__SHIFT 0x00000009
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET_MASK 0x00100000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET__SHIFT 0x00000014
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT_MASK 0x00003fffL
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT__SHIFT 0x00000000
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT_MASK 0x3fff0000L
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT__SHIFT 0x00000010
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_MASK 0xffffffffL
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__SHIFT 0x00000000
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH_MASK 0x00003fffL
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV_MASK 0x00010000L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV__SHIFT 0x00000010
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP_MASK 0x00000300L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP__SHIFT 0x00000008
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID_MASK 0x0000f000L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR_MASK 0x00010000L
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR__SHIFT 0x00000010
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_MASK 0x00003000L
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG_MASK 0x000003ffL
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL_MASK 0x00000001L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT_MASK 0x000000f0L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT__SHIFT 0x00000004
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER_MASK 0xffff0000L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER__SHIFT 0x00000010
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR_MASK 0x00010000L
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR__SHIFT 0x00000010
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_MASK 0x00003000L
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK__SHIFT 0x0000000c
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG_MASK 0x000003ffL
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG__SHIFT 0x00000000
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH_MASK 0x3fff0000L
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH__SHIFT 0x00000010
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE_MASK 0x00003fffL
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS_MASK 0xffffffffL
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE_MASK 0xffffffffL
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE__SHIFT 0x00000000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT_MASK 0x00003fffL
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT__SHIFT 0x00000000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT_MASK 0x3fff0000L
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT__SHIFT 0x00000010
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY_MASK 0x00000007L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY__SHIFT 0x00000000
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY_MASK 0xffff8000L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY__SHIFT 0x0000000f
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE_MASK 0x00000100L
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE__SHIFT 0x00000008
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE_MASK 0x00010000L
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE__SHIFT 0x00000010
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY_MASK 0x00000200L
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY__SHIFT 0x00000009
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN_MASK 0x00080000L
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN__SHIFT 0x00000013
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET_MASK 0x00100000L
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET__SHIFT 0x00000014
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING_MASK 0x00000001L
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING__SHIFT 0x00000000
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV_MASK 0x00010000L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV__SHIFT 0x00000010
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP_MASK 0x00000300L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP__SHIFT 0x00000008
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID_MASK 0x0000f000L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID__SHIFT 0x0000000c
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR_MASK 0x80000000L
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR__SHIFT 0x0000001f
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_MASK 0x00030000L
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK__SHIFT 0x00000010
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG_MASK 0x0000ffffL
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG__SHIFT 0x00000000
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR_MASK 0x00010000L
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR__SHIFT 0x00000010
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_MASK 0x00003000L
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK__SHIFT 0x0000000c
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG_MASK 0x000003ffL
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC_MASK 0x000fffffL
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT_MASK 0xfff00000L
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT__SHIFT 0x00000014
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX_MASK 0xffff0000L
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX__SHIFT 0x00000010
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN_MASK 0x0000ffffL
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER_MASK 0x0000ffffL
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER__SHIFT 0x00000000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL_MASK 0x00000001L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL__SHIFT 0x00000000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT_MASK 0x000000f0L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT__SHIFT 0x00000004
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER_MASK 0xffff0000L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER__SHIFT 0x00000010
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH_MASK 0x000000ffL
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x00000000
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS_MASK 0xffffffffL
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS__SHIFT 0x00000000
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH_MASK 0x00003fffL
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH__SHIFT 0x00000000
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH_MASK 0x3fff0000L
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH__SHIFT 0x00000010
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD_MASK 0xffff0000L
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD__SHIFT 0x00000010
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE_MASK 0x000001ffL
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE__SHIFT 0x00000000
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_MASK 0x00000001L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL__SHIFT 0x00000000
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h
new file mode 100644
index 000000000000..c75aee25619e
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h
@@ -0,0 +1,1784 @@
+/*
+ *
+ * Copyright (C) 2016 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_6_0_D_H
+#define GFX_6_0_D_H
+
+#define ixCLIPPER_DEBUG_REG00 0x0000
+#define ixCLIPPER_DEBUG_REG01 0x0001
+#define ixCLIPPER_DEBUG_REG02 0x0002
+#define ixCLIPPER_DEBUG_REG03 0x0003
+#define ixCLIPPER_DEBUG_REG04 0x0004
+#define ixCLIPPER_DEBUG_REG05 0x0005
+#define ixCLIPPER_DEBUG_REG06 0x0006
+#define ixCLIPPER_DEBUG_REG07 0x0007
+#define ixCLIPPER_DEBUG_REG08 0x0008
+#define ixCLIPPER_DEBUG_REG09 0x0009
+#define ixCLIPPER_DEBUG_REG10 0x000A
+#define ixCLIPPER_DEBUG_REG11 0x000B
+#define ixCLIPPER_DEBUG_REG12 0x000C
+#define ixCLIPPER_DEBUG_REG13 0x000D
+#define ixCLIPPER_DEBUG_REG14 0x000E
+#define ixCLIPPER_DEBUG_REG15 0x000F
+#define ixCLIPPER_DEBUG_REG16 0x0010
+#define ixCLIPPER_DEBUG_REG17 0x0011
+#define ixCLIPPER_DEBUG_REG18 0x0012
+#define ixCLIPPER_DEBUG_REG19 0x0013
+#define ixGDS_DEBUG_REG0 0x0000
+#define ixGDS_DEBUG_REG1 0x0001
+#define ixGDS_DEBUG_REG2 0x0002
+#define ixGDS_DEBUG_REG3 0x0003
+#define ixGDS_DEBUG_REG4 0x0004
+#define ixGDS_DEBUG_REG5 0x0005
+#define ixGDS_DEBUG_REG6 0x0006
+#define ixIA_DEBUG_REG0 0x0000
+#define ixIA_DEBUG_REG1 0x0001
+#define ixIA_DEBUG_REG2 0x0002
+#define ixIA_DEBUG_REG3 0x0003
+#define ixIA_DEBUG_REG4 0x0004
+#define ixIA_DEBUG_REG5 0x0005
+#define ixIA_DEBUG_REG6 0x0006
+#define ixIA_DEBUG_REG7 0x0007
+#define ixIA_DEBUG_REG8 0x0008
+#define ixIA_DEBUG_REG9 0x0009
+#define ixPA_SC_DEBUG_REG0 0x0000
+#define ixPA_SC_DEBUG_REG1 0x0001
+#define ixSETUP_DEBUG_REG0 0x0018
+#define ixSETUP_DEBUG_REG1 0x0019
+#define ixSETUP_DEBUG_REG2 0x001A
+#define ixSETUP_DEBUG_REG3 0x001B
+#define ixSETUP_DEBUG_REG4 0x001C
+#define ixSETUP_DEBUG_REG5 0x001D
+#define ixSQ_DEBUG_CTRL_LOCAL 0x0009
+#define ixSQ_DEBUG_STS_LOCAL 0x0008
+#define ixSQ_INTERRUPT_WORD_AUTO 0x20C0
+#define ixSQ_INTERRUPT_WORD_CMN 0x20C0
+#define ixSQ_INTERRUPT_WORD_WAVE 0x20C0
+#define ixSQ_WAVE_EXEC_HI 0x027F
+#define ixSQ_WAVE_EXEC_LO 0x027E
+#define ixSQ_WAVE_GPR_ALLOC 0x0015
+#define ixSQ_WAVE_HW_ID 0x0014
+#define ixSQ_WAVE_IB_DBG0 0x001C
+#define ixSQ_WAVE_IB_STS 0x0017
+#define ixSQ_WAVE_INST_DW0 0x001A
+#define ixSQ_WAVE_INST_DW1 0x001B
+#define ixSQ_WAVE_LDS_ALLOC 0x0016
+#define ixSQ_WAVE_M0 0x027C
+#define ixSQ_WAVE_MODE 0x0011
+#define ixSQ_WAVE_PC_HI 0x0019
+#define ixSQ_WAVE_PC_LO 0x0018
+#define ixSQ_WAVE_STATUS 0x0012
+#define ixSQ_WAVE_TBA_HI 0x026D
+#define ixSQ_WAVE_TBA_LO 0x026C
+#define ixSQ_WAVE_TMA_HI 0x026F
+#define ixSQ_WAVE_TMA_LO 0x026E
+#define ixSQ_WAVE_TRAPSTS 0x0013
+#define ixSQ_WAVE_TTMP0 0x0270
+#define ixSQ_WAVE_TTMP10 0x027A
+#define ixSQ_WAVE_TTMP1 0x0271
+#define ixSQ_WAVE_TTMP11 0x027B
+#define ixSQ_WAVE_TTMP2 0x0272
+#define ixSQ_WAVE_TTMP3 0x0273
+#define ixSQ_WAVE_TTMP4 0x0274
+#define ixSQ_WAVE_TTMP5 0x0275
+#define ixSQ_WAVE_TTMP6 0x0276
+#define ixSQ_WAVE_TTMP7 0x0277
+#define ixSQ_WAVE_TTMP8 0x0278
+#define ixSQ_WAVE_TTMP9 0x0279
+#define ixSXIFCCG_DEBUG_REG0 0x0014
+#define ixSXIFCCG_DEBUG_REG1 0x0015
+#define ixSXIFCCG_DEBUG_REG2 0x0016
+#define ixSXIFCCG_DEBUG_REG3 0x0017
+#define ixVGT_DEBUG_REG0 0x0000
+#define ixVGT_DEBUG_REG10 0x000A
+#define ixVGT_DEBUG_REG1 0x0001
+#define ixVGT_DEBUG_REG11 0x000B
+#define ixVGT_DEBUG_REG12 0x000C
+#define ixVGT_DEBUG_REG13 0x000D
+#define ixVGT_DEBUG_REG14 0x000E
+#define ixVGT_DEBUG_REG15 0x000F
+#define ixVGT_DEBUG_REG16 0x0010
+#define ixVGT_DEBUG_REG17 0x0011
+#define ixVGT_DEBUG_REG18 0x0012
+#define ixVGT_DEBUG_REG19 0x0013
+#define ixVGT_DEBUG_REG20 0x0014
+#define ixVGT_DEBUG_REG2 0x0002
+#define ixVGT_DEBUG_REG21 0x0015
+#define ixVGT_DEBUG_REG22 0x0016
+#define ixVGT_DEBUG_REG23 0x0017
+#define ixVGT_DEBUG_REG24 0x0018
+#define ixVGT_DEBUG_REG25 0x0019
+#define ixVGT_DEBUG_REG26 0x001A
+#define ixVGT_DEBUG_REG27 0x001B
+#define ixVGT_DEBUG_REG28 0x001C
+#define ixVGT_DEBUG_REG29 0x001D
+#define ixVGT_DEBUG_REG30 0x001E
+#define ixVGT_DEBUG_REG3 0x0003
+#define ixVGT_DEBUG_REG31 0x001F
+#define ixVGT_DEBUG_REG32 0x0020
+#define ixVGT_DEBUG_REG33 0x0021
+#define ixVGT_DEBUG_REG34 0x0022
+#define ixVGT_DEBUG_REG35 0x0023
+#define ixVGT_DEBUG_REG36 0x0024
+#define ixVGT_DEBUG_REG4 0x0004
+#define ixVGT_DEBUG_REG5 0x0005
+#define ixVGT_DEBUG_REG6 0x0006
+#define ixVGT_DEBUG_REG7 0x0007
+#define ixVGT_DEBUG_REG8 0x0008
+#define ixVGT_DEBUG_REG9 0x0009
+#define mmBCI_DEBUG_READ 0x24E3
+#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_BLEND_ALPHA 0xA108
+#define mmCB_BLEND_BLUE 0xA107
+#define mmCB_BLEND_GREEN 0xA106
+#define mmCB_BLEND_RED 0xA105
+#define mmCB_CGTT_SCLK_CTRL 0x2698
+#define mmCB_COLOR0_ATTRIB 0xA31D
+#define mmCB_COLOR0_BASE 0xA318
+#define mmCB_COLOR0_CLEAR_WORD0 0xA323
+#define mmCB_COLOR0_CLEAR_WORD1 0xA324
+#define mmCB_COLOR0_CMASK 0xA31F
+#define mmCB_COLOR0_CMASK_SLICE 0xA320
+#define mmCB_COLOR0_FMASK 0xA321
+#define mmCB_COLOR0_FMASK_SLICE 0xA322
+#define mmCB_COLOR0_INFO 0xA31C
+#define mmCB_COLOR0_PITCH 0xA319
+#define mmCB_COLOR0_SLICE 0xA31A
+#define mmCB_COLOR0_VIEW 0xA31B
+#define mmCB_COLOR1_ATTRIB 0xA32C
+#define mmCB_COLOR1_BASE 0xA327
+#define mmCB_COLOR1_CLEAR_WORD0 0xA332
+#define mmCB_COLOR1_CLEAR_WORD1 0xA333
+#define mmCB_COLOR1_CMASK 0xA32E
+#define mmCB_COLOR1_CMASK_SLICE 0xA32F
+#define mmCB_COLOR1_FMASK 0xA330
+#define mmCB_COLOR1_FMASK_SLICE 0xA331
+#define mmCB_COLOR1_INFO 0xA32B
+#define mmCB_COLOR1_PITCH 0xA328
+#define mmCB_COLOR1_SLICE 0xA329
+#define mmCB_COLOR1_VIEW 0xA32A
+#define mmCB_COLOR2_ATTRIB 0xA33B
+#define mmCB_COLOR2_BASE 0xA336
+#define mmCB_COLOR2_CLEAR_WORD0 0xA341
+#define mmCB_COLOR2_CLEAR_WORD1 0xA342
+#define mmCB_COLOR2_CMASK 0xA33D
+#define mmCB_COLOR2_CMASK_SLICE 0xA33E
+#define mmCB_COLOR2_FMASK 0xA33F
+#define mmCB_COLOR2_FMASK_SLICE 0xA340
+#define mmCB_COLOR2_INFO 0xA33A
+#define mmCB_COLOR2_PITCH 0xA337
+#define mmCB_COLOR2_SLICE 0xA338
+#define mmCB_COLOR2_VIEW 0xA339
+#define mmCB_COLOR3_ATTRIB 0xA34A
+#define mmCB_COLOR3_BASE 0xA345
+#define mmCB_COLOR3_CLEAR_WORD0 0xA350
+#define mmCB_COLOR3_CLEAR_WORD1 0xA351
+#define mmCB_COLOR3_CMASK 0xA34C
+#define mmCB_COLOR3_CMASK_SLICE 0xA34D
+#define mmCB_COLOR3_FMASK 0xA34E
+#define mmCB_COLOR3_FMASK_SLICE 0xA34F
+#define mmCB_COLOR3_INFO 0xA349
+#define mmCB_COLOR3_PITCH 0xA346
+#define mmCB_COLOR3_SLICE 0xA347
+#define mmCB_COLOR3_VIEW 0xA348
+#define mmCB_COLOR4_ATTRIB 0xA359
+#define mmCB_COLOR4_BASE 0xA354
+#define mmCB_COLOR4_CLEAR_WORD0 0xA35F
+#define mmCB_COLOR4_CLEAR_WORD1 0xA360
+#define mmCB_COLOR4_CMASK 0xA35B
+#define mmCB_COLOR4_CMASK_SLICE 0xA35C
+#define mmCB_COLOR4_FMASK 0xA35D
+#define mmCB_COLOR4_FMASK_SLICE 0xA35E
+#define mmCB_COLOR4_INFO 0xA358
+#define mmCB_COLOR4_PITCH 0xA355
+#define mmCB_COLOR4_SLICE 0xA356
+#define mmCB_COLOR4_VIEW 0xA357
+#define mmCB_COLOR5_ATTRIB 0xA368
+#define mmCB_COLOR5_BASE 0xA363
+#define mmCB_COLOR5_CLEAR_WORD0 0xA36E
+#define mmCB_COLOR5_CLEAR_WORD1 0xA36F
+#define mmCB_COLOR5_CMASK 0xA36A
+#define mmCB_COLOR5_CMASK_SLICE 0xA36B
+#define mmCB_COLOR5_FMASK 0xA36C
+#define mmCB_COLOR5_FMASK_SLICE 0xA36D
+#define mmCB_COLOR5_INFO 0xA367
+#define mmCB_COLOR5_PITCH 0xA364
+#define mmCB_COLOR5_SLICE 0xA365
+#define mmCB_COLOR5_VIEW 0xA366
+#define mmCB_COLOR6_ATTRIB 0xA377
+#define mmCB_COLOR6_BASE 0xA372
+#define mmCB_COLOR6_CLEAR_WORD0 0xA37D
+#define mmCB_COLOR6_CLEAR_WORD1 0xA37E
+#define mmCB_COLOR6_CMASK 0xA379
+#define mmCB_COLOR6_CMASK_SLICE 0xA37A
+#define mmCB_COLOR6_FMASK 0xA37B
+#define mmCB_COLOR6_FMASK_SLICE 0xA37C
+#define mmCB_COLOR6_INFO 0xA376
+#define mmCB_COLOR6_PITCH 0xA373
+#define mmCB_COLOR6_SLICE 0xA374
+#define mmCB_COLOR6_VIEW 0xA375
+#define mmCB_COLOR7_ATTRIB 0xA386
+#define mmCB_COLOR7_BASE 0xA381
+#define mmCB_COLOR7_CLEAR_WORD0 0xA38C
+#define mmCB_COLOR7_CLEAR_WORD1 0xA38D
+#define mmCB_COLOR7_CMASK 0xA388
+#define mmCB_COLOR7_CMASK_SLICE 0xA389
+#define mmCB_COLOR7_FMASK 0xA38A
+#define mmCB_COLOR7_FMASK_SLICE 0xA38B
+#define mmCB_COLOR7_INFO 0xA385
+#define mmCB_COLOR7_PITCH 0xA382
+#define mmCB_COLOR7_SLICE 0xA383
+#define mmCB_COLOR7_VIEW 0xA384
+#define mmCB_COLOR_CONTROL 0xA202
+#define mmCB_DEBUG_BUS_10 0x26A2
+#define mmCB_DEBUG_BUS_1 0x2699
+#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_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_HW_CONTROL 0x2684
+#define mmCB_HW_CONTROL_1 0x2685
+#define mmCB_HW_CONTROL_2 0x2686
+#define mmCB_PERFCOUNTER0_HI 0x2691
+#define mmCB_PERFCOUNTER0_LO 0x2690
+#define mmCB_PERFCOUNTER0_SELECT1 0x2689
+#define mmCB_PERFCOUNTER1_HI 0x2693
+#define mmCB_PERFCOUNTER1_LO 0x2692
+#define mmCB_PERFCOUNTER2_HI 0x2695
+#define mmCB_PERFCOUNTER2_LO 0x2694
+#define mmCB_PERFCOUNTER3_HI 0x2697
+#define mmCB_PERFCOUNTER3_LO 0x2696
+#define mmCB_SHADER_MASK 0xA08F
+#define mmCB_TARGET_MASK 0xA08E
+#define mmCC_GC_SHADER_ARRAY_CONFIG 0x226F
+#define mmCC_RB_BACKEND_DISABLE 0x263D
+#define mmCC_RB_DAISY_CHAIN 0x2641
+#define mmCC_RB_REDUNDANCY 0x263C
+#define mmCC_SQC_BANK_DISABLE 0x2307
+#define mmCGTS_RD_CTRL_REG 0x2455
+#define mmCGTS_RD_REG 0x2456
+#define mmCGTS_SM_CTRL_REG 0x2454
+#define mmCGTS_TCC_DISABLE 0x2452
+#define mmCGTS_USER_TCC_DISABLE 0x2453
+#define mmCGTT_BCI_CLK_CTRL 0x24A9
+#define mmCGTT_CP_CLK_CTRL 0x3059
+#define mmCGTT_GDS_CLK_CTRL 0x25DD
+#define mmCGTT_IA_CLK_CTRL 0x2261
+#define mmCGTT_PA_CLK_CTRL 0x2286
+#define mmCGTT_PC_CLK_CTRL 0x24A8
+#define mmCGTT_RLC_CLK_CTRL 0x30E0
+#define mmCGTT_SC_CLK_CTRL 0x22CA
+#define mmCGTT_SPI_CLK_CTRL 0x2451
+#define mmCGTT_SQ_CLK_CTRL 0x2362
+#define mmCGTT_SQG_CLK_CTRL 0x2363
+#define mmCGTT_SX_CLK_CTRL0 0x240C
+#define mmCGTT_SX_CLK_CTRL1 0x240D
+#define mmCGTT_SX_CLK_CTRL2 0x240E
+#define mmCGTT_SX_CLK_CTRL3 0x240F
+#define mmCGTT_SX_CLK_CTRL4 0x2410
+#define mmCGTT_TCI_CLK_CTRL 0x2B60
+#define mmCGTT_TCP_CLK_CTRL 0x2B15
+#define mmCGTT_VGT_CLK_CTRL 0x225F
+#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 mmCOMPUTE_DIM_X 0x2E01
+#define mmCOMPUTE_DIM_Y 0x2E02
+#define mmCOMPUTE_DIM_Z 0x2E03
+#define mmCOMPUTE_DISPATCH_INITIATOR 0x2E00
+#define mmCOMPUTE_NUM_THREAD_X 0x2E07
+#define mmCOMPUTE_NUM_THREAD_Y 0x2E08
+#define mmCOMPUTE_NUM_THREAD_Z 0x2E09
+#define mmCOMPUTE_PGM_HI 0x2E0D
+#define mmCOMPUTE_PGM_LO 0x2E0C
+#define mmCOMPUTE_PGM_RSRC1 0x2E12
+#define mmCOMPUTE_PGM_RSRC2 0x2E13
+#define mmCOMPUTE_RESOURCE_LIMITS 0x2E15
+#define mmCOMPUTE_START_X 0x2E04
+#define mmCOMPUTE_START_Y 0x2E05
+#define mmCOMPUTE_START_Z 0x2E06
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE0 0x2E16
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE1 0x2E17
+#define mmCOMPUTE_TBA_HI 0x2E0F
+#define mmCOMPUTE_TBA_LO 0x2E0E
+#define mmCOMPUTE_TMA_HI 0x2E11
+#define mmCOMPUTE_TMA_LO 0x2E10
+#define mmCOMPUTE_TMPRING_SIZE 0x2E18
+#define mmCOMPUTE_USER_DATA_0 0x2E40
+#define mmCOMPUTE_USER_DATA_10 0x2E4A
+#define mmCOMPUTE_USER_DATA_1 0x2E41
+#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_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_VMID 0x2E14
+#define mmCP_APPEND_ADDR_HI 0x2159
+#define mmCP_APPEND_ADDR_LO 0x2158
+#define mmCP_APPEND_DATA 0x215A
+#define mmCP_APPEND_LAST_CS_FENCE 0x215B
+#define mmCP_APPEND_LAST_PS_FENCE 0x215C
+#define mmCP_ATOMIC_PREOP_HI 0x215E
+#define mmCP_ATOMIC_PREOP_LO 0x215D
+#define mmCP_BUSY_STAT 0x219F
+#define mmCP_CE_HEADER_DUMP 0x21A4
+#define mmCP_CE_IB1_BASE_HI 0x21C7
+#define mmCP_CE_IB1_BASE_LO 0x21C6
+#define mmCP_CE_IB1_BUFSZ 0x21C8
+#define mmCP_CE_IB2_BASE_HI 0x21CA
+#define mmCP_CE_IB2_BASE_LO 0x21C9
+#define mmCP_CE_IB2_BUFSZ 0x21CB
+#define mmCP_CE_INIT_BASE_HI 0x21C4
+#define mmCP_CE_INIT_BASE_LO 0x21C3
+#define mmCP_CE_INIT_BUFSZ 0x21C5
+#define mmCP_CEQ1_AVAIL 0x21E6
+#define mmCP_CEQ2_AVAIL 0x21E7
+#define mmCP_CE_ROQ_IB1_STAT 0x21E9
+#define mmCP_CE_ROQ_IB2_STAT 0x21EA
+#define mmCP_CE_ROQ_RB_STAT 0x21E8
+#define mmCP_CE_UCODE_ADDR 0x305A
+#define mmCP_CE_UCODE_DATA 0x305B
+#define mmCP_CMD_DATA 0x21DF
+#define mmCP_CMD_INDEX 0x21DE
+#define mmCP_CNTX_STAT 0x21B8
+#define mmCP_COHER_BASE 0x217E
+#define mmCP_COHER_CNTL 0x217C
+#define mmCP_COHER_SIZE 0x217D
+#define mmCP_COHER_START_DELAY 0x217B
+#define mmCP_COHER_STATUS 0x217F
+#define mmCP_CSF_CNTL 0x21B5
+#define mmCP_CSF_STAT 0x21B4
+#define mmCP_DMA_CNTL 0x218A
+#define mmCP_DMA_ME_COMMAND 0x2184
+#define mmCP_DMA_ME_DST_ADDR 0x2182
+#define mmCP_DMA_ME_DST_ADDR_HI 0x2183
+#define mmCP_DMA_ME_SRC_ADDR 0x2180
+#define mmCP_DMA_ME_SRC_ADDR_HI 0x2181
+#define mmCP_DMA_PFP_COMMAND 0x2189
+#define mmCP_DMA_PFP_DST_ADDR 0x2187
+#define mmCP_DMA_PFP_DST_ADDR_HI 0x2188
+#define mmCP_DMA_PFP_SRC_ADDR 0x2185
+#define mmCP_DMA_PFP_SRC_ADDR_HI 0x2186
+#define mmCP_DMA_READ_TAGS 0x218B
+#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_EOP_DONE_ADDR_HI 0x2101
+#define mmCP_EOP_DONE_ADDR_LO 0x2100
+#define mmCP_EOP_DONE_DATA_HI 0x2103
+#define mmCP_EOP_DONE_DATA_LO 0x2102
+#define mmCP_EOP_LAST_FENCE_HI 0x2105
+#define mmCP_EOP_LAST_FENCE_LO 0x2104
+#define mmCP_GDS_ATOMIC0_PREOP_HI 0x2160
+#define mmCP_GDS_ATOMIC0_PREOP_LO 0x215F
+#define mmCP_GDS_ATOMIC1_PREOP_HI 0x2162
+#define mmCP_GDS_ATOMIC1_PREOP_LO 0x2161
+#define mmCP_GRBM_FREE_COUNT 0x21A3
+#define mmCP_IB1_BASE_HI 0x21CD
+#define mmCP_IB1_BASE_LO 0x21CC
+#define mmCP_IB1_BUFSZ 0x21CE
+#define mmCP_IB1_OFFSET 0x2192
+#define mmCP_IB1_PREAMBLE_BEGIN 0x2194
+#define mmCP_IB1_PREAMBLE_END 0x2195
+#define mmCP_IB2_BASE_HI 0x21D0
+#define mmCP_IB2_BASE_LO 0x21CF
+#define mmCP_IB2_BUFSZ 0x21D1
+#define mmCP_IB2_OFFSET 0x2193
+#define mmCP_IB2_PREAMBLE_BEGIN 0x2196
+#define mmCP_IB2_PREAMBLE_END 0x2197
+#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_STAT_DEBUG 0x21F7
+#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_MC_PACK_DELAY_CNT 0x21A7
+#define mmCP_ME_CNTL 0x21B6
+#define mmCP_ME_HEADER_DUMP 0x21A1
+#define mmCP_ME_MC_RADDR_HI 0x216E
+#define mmCP_ME_MC_RADDR_LO 0x216D
+#define mmCP_ME_MC_WADDR_HI 0x216A
+#define mmCP_ME_MC_WADDR_LO 0x2169
+#define mmCP_ME_MC_WDATA_HI 0x216C
+#define mmCP_ME_MC_WDATA_LO 0x216B
+#define mmCP_MEM_SLP_CNTL 0x3079
+#define mmCP_ME_PREEMPTION 0x21B9
+#define mmCP_MEQ_AVAIL 0x21DD
+#define mmCP_MEQ_STAT 0x21E5
+#define mmCP_MEQ_THRESHOLDS 0x21D9
+#define mmCP_ME_RAM_DATA 0x3058
+#define mmCP_ME_RAM_RADDR 0x3056
+#define mmCP_ME_RAM_WADDR 0x3057
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_HI 0x210B
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_LO 0x210A
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_HI 0x210F
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_LO 0x210E
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_HI 0x2113
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_LO 0x2112
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_HI 0x2117
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_LO 0x2116
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_HI 0x2109
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_LO 0x2108
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_HI 0x210D
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_LO 0x210C
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_HI 0x2111
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_LO 0x2110
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_HI 0x2115
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_LO 0x2114
+#define mmCP_PA_CINVOC_COUNT_HI 0x2129
+#define mmCP_PA_CINVOC_COUNT_LO 0x2128
+#define mmCP_PA_CPRIM_COUNT_HI 0x212B
+#define mmCP_PA_CPRIM_COUNT_LO 0x212A
+#define mmCP_PERFMON_CNTL 0x21FF
+#define mmCP_PERFMON_CNTX_CNTL 0xA0D8
+#define mmCP_PFP_HEADER_DUMP 0x21A2
+#define mmCP_PFP_IB_CONTROL 0x218D
+#define mmCP_PFP_LOAD_CONTROL 0x218E
+#define mmCP_PFP_UCODE_ADDR 0x3054
+#define mmCP_PFP_UCODE_DATA 0x3055
+#define mmCP_PIPE_STATS_ADDR_HI 0x2119
+#define mmCP_PIPE_STATS_ADDR_LO 0x2118
+#define mmCP_PWR_CNTL 0x3078
+#define mmCP_QUEUE_THRESHOLDS 0x21D8
+#define mmCP_RB0_BASE 0x3040
+#define mmCP_RB0_CNTL 0x3041
+#define mmCP_RB0_RPTR 0x21C0
+#define mmCP_RB0_RPTR_ADDR 0x3043
+#define mmCP_RB0_RPTR_ADDR_HI 0x3044
+#define mmCP_RB0_WPTR 0x3045
+#define mmCP_RB1_BASE 0x3060
+#define mmCP_RB1_CNTL 0x3061
+#define mmCP_RB1_RPTR 0x21BF
+#define mmCP_RB1_RPTR_ADDR 0x3062
+#define mmCP_RB1_RPTR_ADDR_HI 0x3063
+#define mmCP_RB1_WPTR 0x3064
+#define mmCP_RB2_BASE 0x3065
+#define mmCP_RB2_CNTL 0x3066
+#define mmCP_RB2_RPTR 0x21BE
+#define mmCP_RB2_RPTR_ADDR 0x3067
+#define mmCP_RB2_RPTR_ADDR_HI 0x3068
+#define mmCP_RB2_WPTR 0x3069
+#define mmCP_RB_BASE 0x3040
+#define mmCP_RB_CNTL 0x3041
+#define mmCP_RB_OFFSET 0x2191
+#define mmCP_RB_RPTR 0x21C0
+#define mmCP_RB_RPTR_ADDR 0x3043
+#define mmCP_RB_RPTR_ADDR_HI 0x3044
+#define mmCP_RB_RPTR_WR 0x3042
+#define mmCP_RB_VMID 0x3051
+#define mmCP_RB_WPTR 0x3045
+#define mmCP_RB_WPTR_DELAY 0x21C1
+#define mmCP_RB_WPTR_POLL_ADDR_HI 0x3047
+#define mmCP_RB_WPTR_POLL_ADDR_LO 0x3046
+#define mmCP_RB_WPTR_POLL_CNTL 0x21C2
+#define mmCP_RING0_PRIORITY 0x304D
+#define mmCP_RING1_PRIORITY 0x304E
+#define mmCP_RING2_PRIORITY 0x304F
+#define mmCP_RINGID 0xA0D9
+#define mmCP_RING_PRIORITY_CNTS 0x304C
+#define mmCP_ROQ1_THRESHOLDS 0x21D5
+#define mmCP_ROQ2_AVAIL 0x21DC
+#define mmCP_ROQ2_THRESHOLDS 0x21D6
+#define mmCP_ROQ_AVAIL 0x21DA
+#define mmCP_ROQ_IB1_STAT 0x21E1
+#define mmCP_ROQ_IB2_STAT 0x21E2
+#define mmCP_ROQ_RB_STAT 0x21E0
+#define mmCP_SC_PSINVOC_COUNT0_HI 0x212D
+#define mmCP_SC_PSINVOC_COUNT0_LO 0x212C
+#define mmCP_SC_PSINVOC_COUNT1_HI 0x212F
+#define mmCP_SC_PSINVOC_COUNT1_LO 0x212E
+#define mmCP_SCRATCH_DATA 0x2190
+#define mmCP_SCRATCH_INDEX 0x218F
+#define mmCP_SEM_INCOMPLETE_TIMER_CNTL 0x2172
+#define mmCP_SEM_WAIT_TIMER 0x216F
+#define mmCP_SIG_SEM_ADDR_HI 0x2171
+#define mmCP_SIG_SEM_ADDR_LO 0x2170
+#define mmCP_STALLED_STAT1 0x219D
+#define mmCP_STALLED_STAT2 0x219E
+#define mmCP_STALLED_STAT3 0x219C
+#define mmCP_STAT 0x21A0
+#define mmCP_ST_BASE_HI 0x21D3
+#define mmCP_ST_BASE_LO 0x21D2
+#define mmCP_ST_BUFSZ 0x21D4
+#define mmCP_STQ_AVAIL 0x21DB
+#define mmCP_STQ_STAT 0x21E3
+#define mmCP_STQ_THRESHOLDS 0x21D7
+#define mmCP_STREAM_OUT_ADDR_HI 0x2107
+#define mmCP_STREAM_OUT_ADDR_LO 0x2106
+#define mmCP_STRMOUT_CNTL 0x213F
+#define mmCP_VGT_CSINVOC_COUNT_HI 0x2131
+#define mmCP_VGT_CSINVOC_COUNT_LO 0x2130
+#define mmCP_VGT_DSINVOC_COUNT_HI 0x2127
+#define mmCP_VGT_DSINVOC_COUNT_LO 0x2126
+#define mmCP_VGT_GSINVOC_COUNT_HI 0x2123
+#define mmCP_VGT_GSINVOC_COUNT_LO 0x2122
+#define mmCP_VGT_GSPRIM_COUNT_HI 0x211F
+#define mmCP_VGT_GSPRIM_COUNT_LO 0x211E
+#define mmCP_VGT_HSINVOC_COUNT_HI 0x2125
+#define mmCP_VGT_HSINVOC_COUNT_LO 0x2124
+#define mmCP_VGT_IAPRIM_COUNT_HI 0x211D
+#define mmCP_VGT_IAPRIM_COUNT_LO 0x211C
+#define mmCP_VGT_IAVERT_COUNT_HI 0x211B
+#define mmCP_VGT_IAVERT_COUNT_LO 0x211A
+#define mmCP_VGT_VSINVOC_COUNT_HI 0x2121
+#define mmCP_VGT_VSINVOC_COUNT_LO 0x2120
+#define mmCP_VMID 0xA0DA
+#define mmCP_WAIT_REG_MEM_TIMEOUT 0x2174
+#define mmCP_WAIT_SEM_ADDR_HI 0x2176
+#define mmCP_WAIT_SEM_ADDR_LO 0x2175
+#define mmCS_COPY_STATE 0xA1F3
+#define mmDB_ALPHA_TO_MASK 0xA2DC
+#define mmDB_CGTT_CLK_CTRL_0 0x261A
+#define mmDB_COUNT_CONTROL 0xA001
+#define mmDB_CREDIT_LIMIT 0x2614
+#define mmDB_DEBUG 0x260C
+#define mmDB_DEBUG2 0x260D
+#define mmDB_DEBUG3 0x260E
+#define mmDB_DEBUG4 0x260F
+#define mmDB_DEPTH_BOUNDS_MAX 0xA009
+#define mmDB_DEPTH_BOUNDS_MIN 0xA008
+#define mmDB_DEPTH_CLEAR 0xA00B
+#define mmDB_DEPTH_CONTROL 0xA200
+#define mmDB_DEPTH_INFO 0xA00F
+#define mmDB_DEPTH_SIZE 0xA016
+#define mmDB_DEPTH_SLICE 0xA017
+#define mmDB_DEPTH_VIEW 0xA002
+#define mmDB_EQAA 0xA201
+#define mmDB_FIFO_DEPTH1 0x2618
+#define mmDB_FIFO_DEPTH2 0x2619
+#define mmDB_FREE_CACHELINES 0x2617
+#define mmDB_HTILE_DATA_BASE 0xA005
+#define mmDB_HTILE_SURFACE 0xA2AF
+#define mmDB_PERFCOUNTER0_HI 0x2602
+#define mmDB_PERFCOUNTER0_LO 0x2601
+#define mmDB_PERFCOUNTER0_SELECT 0x2600
+#define mmDB_PERFCOUNTER1_HI 0x2605
+#define mmDB_PERFCOUNTER1_LO 0x2604
+#define mmDB_PERFCOUNTER1_SELECT 0x2603
+#define mmDB_PERFCOUNTER2_HI 0x2608
+#define mmDB_PERFCOUNTER2_LO 0x2607
+#define mmDB_PERFCOUNTER2_SELECT 0x2606
+#define mmDB_PERFCOUNTER3_HI 0x260B
+#define mmDB_PERFCOUNTER3_LO 0x260A
+#define mmDB_PERFCOUNTER3_SELECT 0x2609
+#define mmDB_PRELOAD_CONTROL 0xA2B2
+#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_RENDER_CONTROL 0xA000
+#define mmDB_RENDER_OVERRIDE 0xA003
+#define mmDB_RENDER_OVERRIDE2 0xA004
+#define mmDB_SHADER_CONTROL 0xA203
+#define mmDB_SRESULTS_COMPARE_STATE0 0xA2B0
+#define mmDB_SRESULTS_COMPARE_STATE1 0xA2B1
+#define mmDB_STENCIL_CLEAR 0xA00A
+#define mmDB_STENCIL_CONTROL 0xA10B
+#define mmDB_STENCIL_INFO 0xA011
+#define mmDB_STENCIL_READ_BASE 0xA013
+#define mmDB_STENCILREFMASK 0xA10C
+#define mmDB_STENCILREFMASK_BF 0xA10D
+#define mmDB_STENCIL_WRITE_BASE 0xA015
+#define mmDB_SUBTILE_CONTROL 0x2616
+#define mmDB_WATERMARKS 0x2615
+#define mmDB_Z_INFO 0xA010
+#define mmDB_ZPASS_COUNT_HI 0x261D
+#define mmDB_ZPASS_COUNT_LOW 0x261C
+#define mmDB_Z_READ_BASE 0xA012
+#define mmDB_Z_WRITE_BASE 0xA014
+#define mmDEBUG_DATA 0x203D
+#define mmDEBUG_INDEX 0x203C
+#define mmGB_ADDR_CONFIG 0x263E
+#define mmGB_BACKEND_MAP 0x263F
+#define mmGB_EDC_MODE 0x307E
+#define mmGB_GPU_ID 0x2640
+#define mmGB_TILE_MODE0 0x2644
+#define mmGB_TILE_MODE10 0x264E
+#define mmGB_TILE_MODE1 0x2645
+#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_MODE2 0x2646
+#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_MODE3 0x2647
+#define mmGB_TILE_MODE31 0x2663
+#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 mmGC_PRIV_MODE 0x3048
+#define mmGC_USER_RB_BACKEND_DISABLE 0x26DF
+#define mmGC_USER_SHADER_ARRAY_CONFIG 0x2270
+#define mmGDS_ATOM_BASE 0x25CE
+#define mmGDS_ATOM_CNTL 0x25CC
+#define mmGDS_ATOM_COMPLETE 0x25CD
+#define mmGDS_ATOM_DST 0x25D2
+#define mmGDS_ATOM_OFFSET0 0x25D0
+#define mmGDS_ATOM_OFFSET1 0x25D1
+#define mmGDS_ATOM_OP 0x25D3
+#define mmGDS_ATOM_READ0 0x25D8
+#define mmGDS_ATOM_READ0_U 0x25D9
+#define mmGDS_ATOM_READ1 0x25DA
+#define mmGDS_ATOM_READ1_U 0x25DB
+#define mmGDS_ATOM_SIZE 0x25CF
+#define mmGDS_ATOM_SRC0 0x25D4
+#define mmGDS_ATOM_SRC0_U 0x25D5
+#define mmGDS_ATOM_SRC1 0x25D6
+#define mmGDS_ATOM_SRC1_U 0x25D7
+#define mmGDS_CNTL_STATUS 0x25C1
+#define mmGDS_CONFIG 0x25C0
+#define mmGDS_DEBUG_CNTL 0x25DE
+#define mmGDS_DEBUG_DATA 0x25DF
+#define mmGDS_ENHANCE 0x25DC
+#define mmGDS_GRBM_SECDED_CNT 0x25E3
+#define mmGDS_GWS_RESOURCE 0x25E1
+#define mmGDS_GWS_RESOURCE_CNTL 0x25E0
+#define mmGDS_OA_DED 0x25E4
+#define mmGDS_PERFCOUNTER0_HI 0x25E7
+#define mmGDS_PERFCOUNTER0_LO 0x25E6
+#define mmGDS_PERFCOUNTER0_SELECT 0x25E5
+#define mmGDS_PERFCOUNTER1_HI 0x25EA
+#define mmGDS_PERFCOUNTER1_LO 0x25E9
+#define mmGDS_PERFCOUNTER1_SELECT 0x25E8
+#define mmGDS_PERFCOUNTER2_HI 0x25ED
+#define mmGDS_PERFCOUNTER2_LO 0x25EC
+#define mmGDS_PERFCOUNTER2_SELECT 0x25EB
+#define mmGDS_PERFCOUNTER3_HI 0x25F0
+#define mmGDS_PERFCOUNTER3_LO 0x25EF
+#define mmGDS_PERFCOUNTER3_SELECT 0x25EE
+#define mmGDS_RD_ADDR 0x25C2
+#define mmGDS_RD_BURST_ADDR 0x25C4
+#define mmGDS_RD_BURST_COUNT 0x25C5
+#define mmGDS_RD_BURST_DATA 0x25C6
+#define mmGDS_RD_DATA 0x25C3
+#define mmGDS_SECDED_CNT 0x25E2
+#define mmGDS_WR_ADDR 0x25C7
+#define mmGDS_WR_BURST_ADDR 0x25C9
+#define mmGDS_WR_BURST_DATA 0x25CA
+#define mmGDS_WR_DATA 0x25C8
+#define mmGDS_WRITE_COMPLETE 0x25CB
+#define mmGFX_COPY_STATE 0xA1F4
+#define mmGRBM_CAM_DATA 0x3001
+#define mmGRBM_CAM_INDEX 0x3000
+#define mmGRBM_CNTL 0x2000
+#define mmGRBM_DEBUG 0x2014
+#define mmGRBM_DEBUG_CNTL 0x2009
+#define mmGRBM_DEBUG_DATA 0x200A
+#define mmGRBM_DEBUG_SNAPSHOT 0x2015
+#define mmGRBM_GFX_CLKEN_CNTL 0x200C
+#define mmGRBM_GFX_INDEX 0x200B
+#define mmGRBM_INT_CNTL 0x2018
+#define mmGRBM_NOWHERE 0x203F
+#define mmGRBM_PERFCOUNTER0_HI 0x201F
+#define mmGRBM_PERFCOUNTER0_LO 0x201E
+#define mmGRBM_PERFCOUNTER0_SELECT 0x201C
+#define mmGRBM_PERFCOUNTER1_HI 0x2021
+#define mmGRBM_PERFCOUNTER1_LO 0x2020
+#define mmGRBM_PERFCOUNTER1_SELECT 0x201D
+#define mmGRBM_PWR_CNTL 0x2003
+#define mmGRBM_READ_ERROR 0x2016
+#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 mmGRBM_SE0_PERFCOUNTER_HI 0x202B
+#define mmGRBM_SE0_PERFCOUNTER_LO 0x202A
+#define mmGRBM_SE0_PERFCOUNTER_SELECT 0x2026
+#define mmGRBM_SE1_PERFCOUNTER_HI 0x202D
+#define mmGRBM_SE1_PERFCOUNTER_LO 0x202C
+#define mmGRBM_SE1_PERFCOUNTER_SELECT 0x2027
+#define mmGRBM_SKEW_CNTL 0x2001
+#define mmGRBM_SOFT_RESET 0x2008
+#define mmGRBM_STATUS 0x2004
+#define mmGRBM_STATUS2 0x2002
+#define mmGRBM_STATUS_SE0 0x2005
+#define mmGRBM_STATUS_SE1 0x2006
+#define mmGRBM_WAIT_IDLE_CLOCKS 0x200D
+#define mmIA_CNTL_STATUS 0x2237
+#define mmIA_DEBUG_CNTL 0x223A
+#define mmIA_DEBUG_DATA 0x223B
+#define mmIA_ENHANCE 0xA29C
+#define mmIA_MULTI_VGT_PARAM 0xA2AA
+#define mmIA_PERFCOUNTER0_HI 0x2225
+#define mmIA_PERFCOUNTER0_LO 0x2224
+#define mmIA_PERFCOUNTER0_SELECT 0x2220
+#define mmIA_PERFCOUNTER1_HI 0x2227
+#define mmIA_PERFCOUNTER1_LO 0x2226
+#define mmIA_PERFCOUNTER1_SELECT 0x2221
+#define mmIA_PERFCOUNTER2_HI 0x2229
+#define mmIA_PERFCOUNTER2_LO 0x2228
+#define mmIA_PERFCOUNTER2_SELECT 0x2222
+#define mmIA_PERFCOUNTER3_HI 0x222B
+#define mmIA_PERFCOUNTER3_LO 0x222A
+#define mmIA_PERFCOUNTER3_SELECT 0x2223
+#define mmIA_VMID_OVERRIDE 0x2260
+#define mmPA_CL_CLIP_CNTL 0xA204
+#define mmPA_CL_CNTL_STATUS 0x2284
+#define mmPA_CL_ENHANCE 0x2285
+#define mmPA_CL_GB_HORZ_CLIP_ADJ 0xA2FC
+#define mmPA_CL_GB_HORZ_DISC_ADJ 0xA2FD
+#define mmPA_CL_GB_VERT_CLIP_ADJ 0xA2FA
+#define mmPA_CL_GB_VERT_DISC_ADJ 0xA2FB
+#define mmPA_CL_NANINF_CNTL 0xA208
+#define mmPA_CL_POINT_CULL_RAD 0xA1F8
+#define mmPA_CL_POINT_SIZE 0xA1F7
+#define mmPA_CL_POINT_X_RAD 0xA1F5
+#define mmPA_CL_POINT_Y_RAD 0xA1F6
+#define mmPA_CL_UCP_0_W 0xA172
+#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_1_W 0xA176
+#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_2_W 0xA17A
+#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_3_W 0xA17E
+#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_4_W 0xA182
+#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_5_W 0xA186
+#define mmPA_CL_UCP_5_X 0xA183
+#define mmPA_CL_UCP_5_Y 0xA184
+#define mmPA_CL_UCP_5_Z 0xA185
+#define mmPA_CL_VPORT_XOFFSET 0xA110
+#define mmPA_CL_VPORT_XOFFSET_10 0xA14C
+#define mmPA_CL_VPORT_XOFFSET_1 0xA116
+#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_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_XSCALE 0xA10F
+#define mmPA_CL_VPORT_XSCALE_10 0xA14B
+#define mmPA_CL_VPORT_XSCALE_1 0xA115
+#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_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_YOFFSET 0xA112
+#define mmPA_CL_VPORT_YOFFSET_10 0xA14E
+#define mmPA_CL_VPORT_YOFFSET_1 0xA118
+#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_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_YSCALE 0xA111
+#define mmPA_CL_VPORT_YSCALE_10 0xA14D
+#define mmPA_CL_VPORT_YSCALE_1 0xA117
+#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_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_ZOFFSET 0xA114
+#define mmPA_CL_VPORT_ZOFFSET_10 0xA150
+#define mmPA_CL_VPORT_ZOFFSET_1 0xA11A
+#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_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_ZSCALE 0xA113
+#define mmPA_CL_VPORT_ZSCALE_10 0xA14F
+#define mmPA_CL_VPORT_ZSCALE_1 0xA119
+#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_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_VS_OUT_CNTL 0xA207
+#define mmPA_CL_VTE_CNTL 0xA206
+#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_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_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_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_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_BR 0xA085
+#define mmPA_SC_CLIPRECT_0_TL 0xA084
+#define mmPA_SC_CLIPRECT_1_BR 0xA087
+#define mmPA_SC_CLIPRECT_1_TL 0xA086
+#define mmPA_SC_CLIPRECT_2_BR 0xA089
+#define mmPA_SC_CLIPRECT_2_TL 0xA088
+#define mmPA_SC_CLIPRECT_3_BR 0xA08B
+#define mmPA_SC_CLIPRECT_3_TL 0xA08A
+#define mmPA_SC_CLIPRECT_RULE 0xA083
+#define mmPA_SC_DEBUG_CNTL 0x22F6
+#define mmPA_SC_DEBUG_DATA 0x22F7
+#define mmPA_SC_EDGERULE 0xA08C
+#define mmPA_SC_ENHANCE 0x22FC
+#define mmPA_SC_FIFO_DEPTH_CNTL 0x2295
+#define mmPA_SC_FIFO_SIZE 0x22F3
+#define mmPA_SC_FORCE_EOV_MAX_CNTS 0x22C9
+#define mmPA_SC_GENERIC_SCISSOR_BR 0xA091
+#define mmPA_SC_GENERIC_SCISSOR_TL 0xA090
+#define mmPA_SC_IF_FIFO_SIZE 0x22F5
+#define mmPA_SC_LINE_CNTL 0xA2F7
+#define mmPA_SC_LINE_STIPPLE 0xA283
+#define mmPA_SC_LINE_STIPPLE_STATE 0x22C4
+#define mmPA_SC_MODE_CNTL_0 0xA292
+#define mmPA_SC_MODE_CNTL_1 0xA293
+#define mmPA_SC_PERFCOUNTER0_HI 0x22A9
+#define mmPA_SC_PERFCOUNTER0_LO 0x22A8
+#define mmPA_SC_PERFCOUNTER0_SELECT 0x22A0
+#define mmPA_SC_PERFCOUNTER1_HI 0x22AB
+#define mmPA_SC_PERFCOUNTER1_LO 0x22AA
+#define mmPA_SC_PERFCOUNTER1_SELECT 0x22A1
+#define mmPA_SC_PERFCOUNTER2_HI 0x22AD
+#define mmPA_SC_PERFCOUNTER2_LO 0x22AC
+#define mmPA_SC_PERFCOUNTER2_SELECT 0x22A2
+#define mmPA_SC_PERFCOUNTER3_HI 0x22AF
+#define mmPA_SC_PERFCOUNTER3_LO 0x22AE
+#define mmPA_SC_PERFCOUNTER3_SELECT 0x22A3
+#define mmPA_SC_PERFCOUNTER4_HI 0x22B1
+#define mmPA_SC_PERFCOUNTER4_LO 0x22B0
+#define mmPA_SC_PERFCOUNTER4_SELECT 0x22A4
+#define mmPA_SC_PERFCOUNTER5_HI 0x22B3
+#define mmPA_SC_PERFCOUNTER5_LO 0x22B2
+#define mmPA_SC_PERFCOUNTER5_SELECT 0x22A5
+#define mmPA_SC_PERFCOUNTER6_HI 0x22B5
+#define mmPA_SC_PERFCOUNTER6_LO 0x22B4
+#define mmPA_SC_PERFCOUNTER6_SELECT 0x22A6
+#define mmPA_SC_PERFCOUNTER7_HI 0x22B7
+#define mmPA_SC_PERFCOUNTER7_LO 0x22B6
+#define mmPA_SC_PERFCOUNTER7_SELECT 0x22A7
+#define mmPA_SC_RASTER_CONFIG 0xA0D4
+#define mmPA_SC_SCREEN_SCISSOR_BR 0xA00D
+#define mmPA_SC_SCREEN_SCISSOR_TL 0xA00C
+#define mmPA_SC_VPORT_SCISSOR_0_BR 0xA095
+#define mmPA_SC_VPORT_SCISSOR_0_TL 0xA094
+#define mmPA_SC_VPORT_SCISSOR_10_BR 0xA0A9
+#define mmPA_SC_VPORT_SCISSOR_10_TL 0xA0A8
+#define mmPA_SC_VPORT_SCISSOR_11_BR 0xA0AB
+#define mmPA_SC_VPORT_SCISSOR_11_TL 0xA0AA
+#define mmPA_SC_VPORT_SCISSOR_12_BR 0xA0AD
+#define mmPA_SC_VPORT_SCISSOR_12_TL 0xA0AC
+#define mmPA_SC_VPORT_SCISSOR_13_BR 0xA0AF
+#define mmPA_SC_VPORT_SCISSOR_13_TL 0xA0AE
+#define mmPA_SC_VPORT_SCISSOR_14_BR 0xA0B1
+#define mmPA_SC_VPORT_SCISSOR_14_TL 0xA0B0
+#define mmPA_SC_VPORT_SCISSOR_15_BR 0xA0B3
+#define mmPA_SC_VPORT_SCISSOR_15_TL 0xA0B2
+#define mmPA_SC_VPORT_SCISSOR_1_BR 0xA097
+#define mmPA_SC_VPORT_SCISSOR_1_TL 0xA096
+#define mmPA_SC_VPORT_SCISSOR_2_BR 0xA099
+#define mmPA_SC_VPORT_SCISSOR_2_TL 0xA098
+#define mmPA_SC_VPORT_SCISSOR_3_BR 0xA09B
+#define mmPA_SC_VPORT_SCISSOR_3_TL 0xA09A
+#define mmPA_SC_VPORT_SCISSOR_4_BR 0xA09D
+#define mmPA_SC_VPORT_SCISSOR_4_TL 0xA09C
+#define mmPA_SC_VPORT_SCISSOR_5_BR 0xA09F
+#define mmPA_SC_VPORT_SCISSOR_5_TL 0xA09E
+#define mmPA_SC_VPORT_SCISSOR_6_BR 0xA0A1
+#define mmPA_SC_VPORT_SCISSOR_6_TL 0xA0A0
+#define mmPA_SC_VPORT_SCISSOR_7_BR 0xA0A3
+#define mmPA_SC_VPORT_SCISSOR_7_TL 0xA0A2
+#define mmPA_SC_VPORT_SCISSOR_8_BR 0xA0A5
+#define mmPA_SC_VPORT_SCISSOR_8_TL 0xA0A4
+#define mmPA_SC_VPORT_SCISSOR_9_BR 0xA0A7
+#define mmPA_SC_VPORT_SCISSOR_9_TL 0xA0A6
+#define mmPA_SC_VPORT_ZMAX_0 0xA0B5
+#define mmPA_SC_VPORT_ZMAX_10 0xA0C9
+#define mmPA_SC_VPORT_ZMAX_1 0xA0B7
+#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_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_ZMIN_0 0xA0B4
+#define mmPA_SC_VPORT_ZMIN_10 0xA0C8
+#define mmPA_SC_VPORT_ZMIN_1 0xA0B6
+#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_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_WINDOW_OFFSET 0xA080
+#define mmPA_SC_WINDOW_SCISSOR_BR 0xA082
+#define mmPA_SC_WINDOW_SCISSOR_TL 0xA081
+#define mmPA_SU_CNTL_STATUS 0x2294
+#define mmPA_SU_DEBUG_CNTL 0x2280
+#define mmPA_SU_DEBUG_DATA 0x2281
+#define mmPA_SU_HARDWARE_SCREEN_OFFSET 0xA08D
+#define mmPA_SU_LINE_CNTL 0xA282
+#define mmPA_SU_LINE_STIPPLE_CNTL 0xA209
+#define mmPA_SU_LINE_STIPPLE_SCALE 0xA20A
+#define mmPA_SU_LINE_STIPPLE_VALUE 0x2298
+#define mmPA_SU_PERFCOUNTER0_HI 0x228D
+#define mmPA_SU_PERFCOUNTER0_LO 0x228C
+#define mmPA_SU_PERFCOUNTER0_SELECT 0x2288
+#define mmPA_SU_PERFCOUNTER1_HI 0x228F
+#define mmPA_SU_PERFCOUNTER1_LO 0x228E
+#define mmPA_SU_PERFCOUNTER1_SELECT 0x2289
+#define mmPA_SU_PERFCOUNTER2_HI 0x2291
+#define mmPA_SU_PERFCOUNTER2_LO 0x2290
+#define mmPA_SU_PERFCOUNTER2_SELECT 0x228A
+#define mmPA_SU_PERFCOUNTER3_HI 0x2293
+#define mmPA_SU_PERFCOUNTER3_LO 0x2292
+#define mmPA_SU_PERFCOUNTER3_SELECT 0x228B
+#define mmPA_SU_POINT_MINMAX 0xA281
+#define mmPA_SU_POINT_SIZE 0xA280
+#define mmPA_SU_POLY_OFFSET_BACK_OFFSET 0xA2E3
+#define mmPA_SU_POLY_OFFSET_BACK_SCALE 0xA2E2
+#define mmPA_SU_POLY_OFFSET_CLAMP 0xA2DF
+#define mmPA_SU_POLY_OFFSET_DB_FMT_CNTL 0xA2DE
+#define mmPA_SU_POLY_OFFSET_FRONT_OFFSET 0xA2E1
+#define mmPA_SU_POLY_OFFSET_FRONT_SCALE 0xA2E0
+#define mmPA_SU_PRIM_FILTER_CNTL 0xA20B
+#define mmPA_SU_SC_MODE_CNTL 0xA205
+#define mmPA_SU_VTX_CNTL 0xA2F9
+#define mmRAS_BCI_SIGNATURE0 0x339E
+#define mmRAS_BCI_SIGNATURE1 0x339F
+#define mmRAS_CB_SIGNATURE0 0x339D
+#define mmRAS_DB_SIGNATURE0 0x338B
+#define mmRAS_IA_SIGNATURE0 0x3397
+#define mmRAS_IA_SIGNATURE1 0x3398
+#define mmRAS_PA_SIGNATURE0 0x338C
+#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_SIGNATURE_CONTROL 0x3380
+#define mmRAS_SIGNATURE_MASK 0x3381
+#define mmRAS_SPI_SIGNATURE0 0x3399
+#define mmRAS_SPI_SIGNATURE1 0x339A
+#define mmRAS_SQ_SIGNATURE0 0x338E
+#define mmRAS_SX_SIGNATURE0 0x3382
+#define mmRAS_SX_SIGNATURE1 0x3383
+#define mmRAS_SX_SIGNATURE2 0x3384
+#define mmRAS_SX_SIGNATURE3 0x3385
+#define mmRAS_TA_SIGNATURE0 0x339B
+#define mmRAS_TD_SIGNATURE0 0x339C
+#define mmRAS_VGT_SIGNATURE0 0x338D
+#define mmRLC_AUTO_PG_CTRL 0x310D
+#define mmRLC_CAPTURE_GPU_CLOCK_COUNT 0x30D0
+#define mmRLC_CGCG_CGLS_CTRL 0x3101
+#define mmRLC_CGCG_RAMP_CTRL 0x3102
+#define mmRLC_CGTT_MGCG_OVERRIDE 0x3100
+#define mmRLC_CNTL 0x30C0
+#define mmRLC_CU_STATUS 0x3106
+#define mmRLC_DEBUG 0x30CA
+#define mmRLC_DEBUG_SELECT 0x30C9
+#define mmRLC_DRIVER_CPDMA_STATUS 0x30C7
+#define mmRLC_DYN_PG_REQUEST 0x3104
+#define mmRLC_DYN_PG_STATUS 0x3103
+#define mmRLC_GPU_CLOCK_32 0x30D5
+#define mmRLC_GPU_CLOCK_32_RES_SEL 0x30D4
+#define mmRLC_GPU_CLOCK_COUNT_LSB 0x30CE
+#define mmRLC_GPU_CLOCK_COUNT_MSB 0x30CF
+#define mmRLC_LB_ALWAYS_ACTIVE_CU_MASK 0x3108
+#define mmRLC_LB_CNTL 0x30C3
+#define mmRLC_LB_CNTR_INIT 0x30C6
+#define mmRLC_LB_CNTR_MAX 0x30C5
+#define mmRLC_LB_INIT_CU_MASK 0x3107
+#define mmRLC_LB_PARAMS 0x3109
+#define mmRLC_LOAD_BALANCE_CNTR 0x30F6
+#define mmRLC_MAX_PG_CU 0x310C
+#define mmRLC_MC_CNTL 0x30D1
+#define mmRLC_MEM_SLP_CNTL 0x30D8
+#define mmRLC_PERFCOUNTER0_HI 0x30DC
+#define mmRLC_PERFCOUNTER0_LO 0x30DB
+#define mmRLC_PERFCOUNTER0_SELECT 0x30DA
+#define mmRLC_PERFCOUNTER1_HI 0x30DF
+#define mmRLC_PERFCOUNTER1_LO 0x30DE
+#define mmRLC_PERFCOUNTER1_SELECT 0x30DD
+#define mmRLC_PERFMON_CNTL 0x30D9
+#define mmRLC_PG_ALWAYS_ON_CU_MASK 0x310B
+#define mmRLC_PG_CNTL 0x30D7
+#define mmRLC_SAVE_AND_RESTORE_BASE 0x30C4
+#define mmRLC_SERDES_RD_DATA_0 0x3112
+#define mmRLC_SERDES_RD_DATA_1 0x3113
+#define mmRLC_SERDES_RD_DATA_2 0x3114
+#define mmRLC_SERDES_RD_MASTER_INDEX 0x3111
+#define mmRLC_SERDES_WR_CTRL 0x3117
+#define mmRLC_SERDES_WR_DATA 0x3118
+#define mmRLC_SMU_GRBM_REG_SAVE_CTRL 0x310E
+#define mmRLC_SMU_PG_CTRL 0x310F
+#define mmRLC_SMU_PG_WAKE_UP_CTRL 0x3110
+#define mmRLC_SOFT_RESET_GPU 0x30D6
+#define mmRLC_STAT 0x30D3
+#define mmRLC_THREAD1_DELAY 0x310A
+#define mmRLC_UCODE_CNTL 0x30D2
+#define mmSCRATCH_ADDR 0x2151
+#define mmSCRATCH_REG0 0x2140
+#define mmSCRATCH_REG1 0x2141
+#define mmSCRATCH_REG2 0x2142
+#define mmSCRATCH_REG3 0x2143
+#define mmSCRATCH_REG4 0x2144
+#define mmSCRATCH_REG5 0x2145
+#define mmSCRATCH_REG6 0x2146
+#define mmSCRATCH_REG7 0x2147
+#define mmSCRATCH_UMSK 0x2150
+#define mmSPI_ARB_CYCLES_0 0x243D
+#define mmSPI_ARB_CYCLES_1 0x243E
+#define mmSPI_ARB_PRIORITY 0x243C
+#define mmSPI_BARYC_CNTL 0xA1B8
+#define mmSPI_CONFIG_CNTL 0x2440
+#define mmSPI_CONFIG_CNTL_1 0x244F
+#define mmSPI_DEBUG_BUSY 0x2450
+#define mmSPI_DEBUG_CNTL 0x2441
+#define mmSPI_DEBUG_READ 0x2442
+#define mmSPI_GDS_CREDITS 0x24D8
+#define mmSPI_INTERP_CONTROL_0 0xA1B5
+#define mmSPI_LB_CTR_CTRL 0x24D4
+#define mmSPI_LB_CU_MASK 0x24D5
+#define mmSPI_LB_DATA_REG 0x24D6
+#define mmSPI_PERFCOUNTER0_HI 0x2447
+#define mmSPI_PERFCOUNTER0_LO 0x2448
+#define mmSPI_PERFCOUNTER0_SELECT 0x2443
+#define mmSPI_PERFCOUNTER1_HI 0x2449
+#define mmSPI_PERFCOUNTER1_LO 0x244A
+#define mmSPI_PERFCOUNTER1_SELECT 0x2444
+#define mmSPI_PERFCOUNTER2_HI 0x244B
+#define mmSPI_PERFCOUNTER2_LO 0x244C
+#define mmSPI_PERFCOUNTER2_SELECT 0x2445
+#define mmSPI_PERFCOUNTER3_HI 0x244D
+#define mmSPI_PERFCOUNTER3_LO 0x244E
+#define mmSPI_PERFCOUNTER3_SELECT 0x2446
+#define mmSPI_PERFCOUNTER_BINS 0x243F
+#define mmSPI_PG_ENABLE_STATIC_CU_MASK 0x24D7
+#define mmSPI_PS_IN_CONTROL 0xA1B6
+#define mmSPI_PS_INPUT_ADDR 0xA1B4
+#define mmSPI_PS_INPUT_CNTL_0 0xA191
+#define mmSPI_PS_INPUT_CNTL_10 0xA19B
+#define mmSPI_PS_INPUT_CNTL_1 0xA192
+#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_2 0xA193
+#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_3 0xA194
+#define mmSPI_PS_INPUT_CNTL_31 0xA1B0
+#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_ENA 0xA1B3
+#define mmSPI_PS_MAX_WAVE_ID 0x243B
+#define mmSPI_SHADER_COL_FORMAT 0xA1C5
+#define mmSPI_SHADER_PGM_HI_ES 0x2CC9
+#define mmSPI_SHADER_PGM_HI_GS 0x2C89
+#define mmSPI_SHADER_PGM_HI_HS 0x2D09
+#define mmSPI_SHADER_PGM_HI_LS 0x2D49
+#define mmSPI_SHADER_PGM_HI_PS 0x2C09
+#define mmSPI_SHADER_PGM_HI_VS 0x2C49
+#define mmSPI_SHADER_PGM_LO_ES 0x2CC8
+#define mmSPI_SHADER_PGM_LO_GS 0x2C88
+#define mmSPI_SHADER_PGM_LO_HS 0x2D08
+#define mmSPI_SHADER_PGM_LO_LS 0x2D48
+#define mmSPI_SHADER_PGM_LO_PS 0x2C08
+#define mmSPI_SHADER_PGM_LO_VS 0x2C48
+#define mmSPI_SHADER_PGM_RSRC1_ES 0x2CCA
+#define mmSPI_SHADER_PGM_RSRC1_GS 0x2C8A
+#define mmSPI_SHADER_PGM_RSRC1_HS 0x2D0A
+#define mmSPI_SHADER_PGM_RSRC1_LS 0x2D4A
+#define mmSPI_SHADER_PGM_RSRC1_PS 0x2C0A
+#define mmSPI_SHADER_PGM_RSRC1_VS 0x2C4A
+#define mmSPI_SHADER_PGM_RSRC2_ES 0x2CCB
+#define mmSPI_SHADER_PGM_RSRC2_GS 0x2C8B
+#define mmSPI_SHADER_PGM_RSRC2_HS 0x2D0B
+#define mmSPI_SHADER_PGM_RSRC2_LS 0x2D4B
+#define mmSPI_SHADER_PGM_RSRC2_PS 0x2C0B
+#define mmSPI_SHADER_PGM_RSRC2_VS 0x2C4B
+#define mmSPI_SHADER_POS_FORMAT 0xA1C3
+#define mmSPI_SHADER_TBA_HI_ES 0x2CC1
+#define mmSPI_SHADER_TBA_HI_GS 0x2C81
+#define mmSPI_SHADER_TBA_HI_HS 0x2D01
+#define mmSPI_SHADER_TBA_HI_LS 0x2D41
+#define mmSPI_SHADER_TBA_HI_PS 0x2C01
+#define mmSPI_SHADER_TBA_HI_VS 0x2C41
+#define mmSPI_SHADER_TBA_LO_ES 0x2CC0
+#define mmSPI_SHADER_TBA_LO_GS 0x2C80
+#define mmSPI_SHADER_TBA_LO_HS 0x2D00
+#define mmSPI_SHADER_TBA_LO_LS 0x2D40
+#define mmSPI_SHADER_TBA_LO_PS 0x2C00
+#define mmSPI_SHADER_TBA_LO_VS 0x2C40
+#define mmSPI_SHADER_TMA_HI_ES 0x2CC3
+#define mmSPI_SHADER_TMA_HI_GS 0x2C83
+#define mmSPI_SHADER_TMA_HI_HS 0x2D03
+#define mmSPI_SHADER_TMA_HI_LS 0x2D43
+#define mmSPI_SHADER_TMA_HI_PS 0x2C03
+#define mmSPI_SHADER_TMA_HI_VS 0x2C43
+#define mmSPI_SHADER_TMA_LO_ES 0x2CC2
+#define mmSPI_SHADER_TMA_LO_GS 0x2C82
+#define mmSPI_SHADER_TMA_LO_HS 0x2D02
+#define mmSPI_SHADER_TMA_LO_LS 0x2D42
+#define mmSPI_SHADER_TMA_LO_PS 0x2C02
+#define mmSPI_SHADER_TMA_LO_VS 0x2C42
+#define mmSPI_SHADER_USER_DATA_ES_0 0x2CCC
+#define mmSPI_SHADER_USER_DATA_ES_10 0x2CD6
+#define mmSPI_SHADER_USER_DATA_ES_1 0x2CCD
+#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_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_GS_0 0x2C8C
+#define mmSPI_SHADER_USER_DATA_GS_10 0x2C96
+#define mmSPI_SHADER_USER_DATA_GS_1 0x2C8D
+#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_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_HS_0 0x2D0C
+#define mmSPI_SHADER_USER_DATA_HS_10 0x2D16
+#define mmSPI_SHADER_USER_DATA_HS_1 0x2D0D
+#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_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_LS_0 0x2D4C
+#define mmSPI_SHADER_USER_DATA_LS_10 0x2D56
+#define mmSPI_SHADER_USER_DATA_LS_1 0x2D4D
+#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 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_PS_0 0x2C0C
+#define mmSPI_SHADER_USER_DATA_PS_10 0x2C16
+#define mmSPI_SHADER_USER_DATA_PS_1 0x2C0D
+#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_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_VS_0 0x2C4C
+#define mmSPI_SHADER_USER_DATA_VS_10 0x2C56
+#define mmSPI_SHADER_USER_DATA_VS_1 0x2C4D
+#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_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_Z_FORMAT 0xA1C4
+#define mmSPI_SLAVE_DEBUG_BUSY 0x24D3
+#define mmSPI_SX_EXPORT_BUFFER_SIZES 0x24D9
+#define mmSPI_SX_SCOREBOARD_BUFFER_SIZES 0x24DA
+#define mmSPI_TMPRING_SIZE 0xA1BA
+#define mmSPI_VS_OUT_CONFIG 0xA1B1
+#define mmSQ_ALU_CLK_CTRL 0x2360
+#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 mmSQC_CACHES 0x2302
+#define mmSQC_CONFIG 0x2301
+#define mmSQ_CONFIG 0x2300
+#define mmSQC_SECDED_CNT 0x23A0
+#define mmSQ_DEBUG_STS_GLOBAL 0x2309
+#define mmSQ_DED_CNT 0x23A2
+#define mmSQ_DED_INFO 0x23A3
+#define mmSQ_DS_0 0x237F
+#define mmSQ_DS_1 0x237F
+#define mmSQ_EXP_0 0x237F
+#define mmSQ_EXP_1 0x237F
+#define mmSQ_FIFO_SIZES 0x2305
+#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_IND_CMD 0x237A
+#define mmSQ_IND_DATA 0x2379
+#define mmSQ_IND_INDEX 0x2378
+#define mmSQ_INST 0x237F
+#define mmSQ_LB_CTR_CTRL 0x2398
+#define mmSQ_LB_DATA_ALU_CYCLES 0x2399
+#define mmSQ_LB_DATA_ALU_STALLS 0x239B
+#define mmSQ_LB_DATA_TEX_CYCLES 0x239A
+#define mmSQ_LB_DATA_TEX_STALLS 0x239C
+#define mmSQ_MIMG_0 0x237F
+#define mmSQ_MIMG_1 0x237F
+#define mmSQ_MTBUF_0 0x237F
+#define mmSQ_MTBUF_1 0x237F
+#define mmSQ_MUBUF_0 0x237F
+#define mmSQ_MUBUF_1 0x237F
+#define mmSQ_PERFCOUNTER0_HI 0x2321
+#define mmSQ_PERFCOUNTER0_LO 0x2320
+#define mmSQ_PERFCOUNTER0_SELECT 0x2340
+#define mmSQ_PERFCOUNTER10_HI 0x2335
+#define mmSQ_PERFCOUNTER10_LO 0x2334
+#define mmSQ_PERFCOUNTER10_SELECT 0x234A
+#define mmSQ_PERFCOUNTER11_HI 0x2337
+#define mmSQ_PERFCOUNTER11_LO 0x2336
+#define mmSQ_PERFCOUNTER11_SELECT 0x234B
+#define mmSQ_PERFCOUNTER12_HI 0x2339
+#define mmSQ_PERFCOUNTER12_LO 0x2338
+#define mmSQ_PERFCOUNTER12_SELECT 0x234C
+#define mmSQ_PERFCOUNTER13_HI 0x233B
+#define mmSQ_PERFCOUNTER13_LO 0x233A
+#define mmSQ_PERFCOUNTER13_SELECT 0x234D
+#define mmSQ_PERFCOUNTER14_HI 0x233D
+#define mmSQ_PERFCOUNTER14_LO 0x233C
+#define mmSQ_PERFCOUNTER14_SELECT 0x234E
+#define mmSQ_PERFCOUNTER15_HI 0x233F
+#define mmSQ_PERFCOUNTER15_LO 0x233E
+#define mmSQ_PERFCOUNTER15_SELECT 0x234F
+#define mmSQ_PERFCOUNTER1_HI 0x2323
+#define mmSQ_PERFCOUNTER1_LO 0x2322
+#define mmSQ_PERFCOUNTER1_SELECT 0x2341
+#define mmSQ_PERFCOUNTER2_HI 0x2325
+#define mmSQ_PERFCOUNTER2_LO 0x2324
+#define mmSQ_PERFCOUNTER2_SELECT 0x2342
+#define mmSQ_PERFCOUNTER3_HI 0x2327
+#define mmSQ_PERFCOUNTER3_LO 0x2326
+#define mmSQ_PERFCOUNTER3_SELECT 0x2343
+#define mmSQ_PERFCOUNTER4_HI 0x2329
+#define mmSQ_PERFCOUNTER4_LO 0x2328
+#define mmSQ_PERFCOUNTER4_SELECT 0x2344
+#define mmSQ_PERFCOUNTER5_HI 0x232B
+#define mmSQ_PERFCOUNTER5_LO 0x232A
+#define mmSQ_PERFCOUNTER5_SELECT 0x2345
+#define mmSQ_PERFCOUNTER6_HI 0x232D
+#define mmSQ_PERFCOUNTER6_LO 0x232C
+#define mmSQ_PERFCOUNTER6_SELECT 0x2346
+#define mmSQ_PERFCOUNTER7_HI 0x232F
+#define mmSQ_PERFCOUNTER7_LO 0x232E
+#define mmSQ_PERFCOUNTER7_SELECT 0x2347
+#define mmSQ_PERFCOUNTER8_HI 0x2331
+#define mmSQ_PERFCOUNTER8_LO 0x2330
+#define mmSQ_PERFCOUNTER8_SELECT 0x2348
+#define mmSQ_PERFCOUNTER9_HI 0x2333
+#define mmSQ_PERFCOUNTER9_LO 0x2332
+#define mmSQ_PERFCOUNTER9_SELECT 0x2349
+#define mmSQ_PERFCOUNTER_CTRL 0x2306
+#define mmSQ_POWER_THROTTLE 0x2396
+#define mmSQ_POWER_THROTTLE2 0x2397
+#define mmSQ_RANDOM_WAVE_PRI 0x2303
+#define mmSQ_REG_CREDITS 0x2304
+#define mmSQ_SEC_CNT 0x23A1
+#define mmSQ_SMRD 0x237F
+#define mmSQ_SOP1 0x237F
+#define mmSQ_SOP2 0x237F
+#define mmSQ_SOPC 0x237F
+#define mmSQ_SOPK 0x237F
+#define mmSQ_SOPP 0x237F
+#define mmSQ_TEX_CLK_CTRL 0x2361
+#define mmSQ_THREAD_TRACE_BASE 0x2380
+#define mmSQ_THREAD_TRACE_CNTR 0x2390
+#define mmSQ_THREAD_TRACE_CTRL 0x238F
+#define mmSQ_THREAD_TRACE_HIWATER 0x2392
+#define mmSQ_THREAD_TRACE_MASK 0x2382
+#define mmSQ_THREAD_TRACE_MODE 0x238E
+#define mmSQ_THREAD_TRACE_PERF_MASK 0x2384
+#define mmSQ_THREAD_TRACE_SIZE 0x2381
+#define mmSQ_THREAD_TRACE_STATUS 0x238D
+#define mmSQ_THREAD_TRACE_TOKEN_MASK 0x2383
+#define mmSQ_THREAD_TRACE_USERDATA_0 0x2388
+#define mmSQ_THREAD_TRACE_USERDATA_1 0x2389
+#define mmSQ_THREAD_TRACE_USERDATA_2 0x238A
+#define mmSQ_THREAD_TRACE_USERDATA_3 0x238B
+#define mmSQ_THREAD_TRACE_WORD_CMN 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_EVENT 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_ISSUE 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_MISC 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_PERF_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_PERF_2_OF_2 0x23B1
+#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_TIME 0x23B0
+#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_WAVE_START 0x23B0
+#define mmSQ_THREAD_TRACE_WPTR 0x238C
+#define mmSQ_TIME_HI 0x237C
+#define mmSQ_TIME_LO 0x237D
+#define mmSQ_VINTRP 0x237F
+#define mmSQ_VOP1 0x237F
+#define mmSQ_VOP2 0x237F
+#define mmSQ_VOP3_0 0x237F
+#define mmSQ_VOP3_0_SDST_ENC 0x237F
+#define mmSQ_VOP3_1 0x237F
+#define mmSQ_VOPC 0x237F
+#define mmSX_DEBUG_1 0x2418
+#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_PERFCOUNTER0_HI 0x2421
+#define mmSX_PERFCOUNTER0_LO 0x2420
+#define mmSX_PERFCOUNTER0_SELECT 0x241C
+#define mmSX_PERFCOUNTER1_HI 0x2423
+#define mmSX_PERFCOUNTER1_LO 0x2422
+#define mmSX_PERFCOUNTER1_SELECT 0x241D
+#define mmSX_PERFCOUNTER2_HI 0x2425
+#define mmSX_PERFCOUNTER2_LO 0x2424
+#define mmSX_PERFCOUNTER2_SELECT 0x241E
+#define mmSX_PERFCOUNTER3_HI 0x2427
+#define mmSX_PERFCOUNTER3_LO 0x2426
+#define mmSX_PERFCOUNTER3_SELECT 0x241F
+#define mmTA_BC_BASE_ADDR 0xA020
+#define mmTA_CGTT_CTRL 0x2544
+#define mmTA_CNTL 0x2541
+#define mmTA_CNTL_AUX 0x2542
+#define mmTA_CS_BC_BASE_ADDR 0x2543
+#define mmTA_DEBUG_DATA 0x254D
+#define mmTA_DEBUG_INDEX 0x254C
+#define mmTA_PERFCOUNTER0_HI 0x2556
+#define mmTA_PERFCOUNTER0_LO 0x2555
+#define mmTA_PERFCOUNTER0_SELECT 0x2554
+#define mmTA_PERFCOUNTER1_HI 0x2562
+#define mmTA_PERFCOUNTER1_LO 0x2561
+#define mmTA_PERFCOUNTER1_SELECT 0x2560
+#define mmTA_SCRATCH 0x2564
+#define mmTA_STATUS 0x2548
+#define mmTCA_CGTT_SCLK_CTRL 0x2BC1
+#define mmTCA_CTRL 0x2BC0
+#define mmTCA_PERFCOUNTER0_HI 0x2BD2
+#define mmTCA_PERFCOUNTER0_LO 0x2BD1
+#define mmTCA_PERFCOUNTER0_SELECT 0x2BD0
+#define mmTCA_PERFCOUNTER1_HI 0x2BD5
+#define mmTCA_PERFCOUNTER1_LO 0x2BD4
+#define mmTCA_PERFCOUNTER1_SELECT 0x2BD3
+#define mmTCA_PERFCOUNTER2_HI 0x2BD8
+#define mmTCA_PERFCOUNTER2_LO 0x2BD7
+#define mmTCA_PERFCOUNTER2_SELECT 0x2BD6
+#define mmTCA_PERFCOUNTER3_HI 0x2BDB
+#define mmTCA_PERFCOUNTER3_LO 0x2BDA
+#define mmTCA_PERFCOUNTER3_SELECT 0x2BD9
+#define mmTCC_CGTT_SCLK_CTRL 0x2B81
+#define mmTCC_CTRL 0x2B80
+#define mmTCC_EDC_COUNTER 0x2B82
+#define mmTCC_PERFCOUNTER0_HI 0x2B92
+#define mmTCC_PERFCOUNTER0_LO 0x2B91
+#define mmTCC_PERFCOUNTER0_SELECT 0x2B90
+#define mmTCC_PERFCOUNTER1_HI 0x2B95
+#define mmTCC_PERFCOUNTER1_LO 0x2B94
+#define mmTCC_PERFCOUNTER1_SELECT 0x2B93
+#define mmTCC_PERFCOUNTER2_HI 0x2B98
+#define mmTCC_PERFCOUNTER2_LO 0x2B97
+#define mmTCC_PERFCOUNTER2_SELECT 0x2B96
+#define mmTCC_PERFCOUNTER3_HI 0x2B9B
+#define mmTCC_PERFCOUNTER3_LO 0x2B9A
+#define mmTCC_PERFCOUNTER3_SELECT 0x2B99
+#define mmTCI_CNTL_1 0x2B62
+#define mmTCI_CNTL_2 0x2B63
+#define mmTCI_STATUS 0x2B61
+#define mmTCP_ADDR_CONFIG 0x2B05
+#define mmTCP_BUFFER_ADDR_HASH_CNTL 0x2B16
+#define mmTCP_CHAN_STEER_HI 0x2B04
+#define mmTCP_CHAN_STEER_LO 0x2B03
+#define mmTCP_CNTL 0x2B02
+#define mmTCP_CREDIT 0x2B06
+#define mmTCP_EDC_COUNTER 0x2B17
+#define mmTCP_INVALIDATE 0x2B00
+#define mmTCP_PERFCOUNTER0_HI 0x2B0A
+#define mmTCP_PERFCOUNTER0_LO 0x2B0B
+#define mmTCP_PERFCOUNTER0_SELECT 0x2B09
+#define mmTCP_PERFCOUNTER1_HI 0x2B0D
+#define mmTCP_PERFCOUNTER1_LO 0x2B0E
+#define mmTCP_PERFCOUNTER1_SELECT 0x2B0C
+#define mmTCP_PERFCOUNTER2_HI 0x2B10
+#define mmTCP_PERFCOUNTER2_LO 0x2B11
+#define mmTCP_PERFCOUNTER2_SELECT 0x2B0F
+#define mmTCP_PERFCOUNTER3_HI 0x2B13
+#define mmTCP_PERFCOUNTER3_LO 0x2B14
+#define mmTCP_PERFCOUNTER3_SELECT 0x2B12
+#define mmTCP_STATUS 0x2B01
+#define mmTD_CGTT_CTRL 0x2527
+#define mmTD_CNTL 0x2525
+#define mmTD_DEBUG_DATA 0x2529
+#define mmTD_DEBUG_INDEX 0x2528
+#define mmTD_PERFCOUNTER0_HI 0x252E
+#define mmTD_PERFCOUNTER0_LO 0x252D
+#define mmTD_PERFCOUNTER0_SELECT 0x252C
+#define mmTD_SCRATCH 0x2530
+#define mmTD_STATUS 0x2526
+#define mmUSER_SQC_BANK_DISABLE 0x2308
+#define mmVGT_CACHE_INVALIDATION 0x2231
+#define mmVGT_CNTL_STATUS 0x223C
+#define mmVGT_DEBUG_CNTL 0x2238
+#define mmVGT_DEBUG_DATA 0x2239
+#define mmVGT_DMA_BASE 0xA1FA
+#define mmVGT_DMA_BASE_HI 0xA1F9
+#define mmVGT_DMA_DATA_FIFO_DEPTH 0x222D
+#define mmVGT_DMA_INDEX_TYPE 0xA29F
+#define mmVGT_DMA_MAX_SIZE 0xA29E
+#define mmVGT_DMA_NUM_INSTANCES 0xA2A2
+#define mmVGT_DMA_REQ_FIFO_DEPTH 0x222E
+#define mmVGT_DMA_SIZE 0xA29D
+#define mmVGT_DRAW_INIT_FIFO_DEPTH 0x222F
+#define mmVGT_DRAW_INITIATOR 0xA1FC
+#define mmVGT_ENHANCE 0xA294
+#define mmVGT_ESGS_RING_ITEMSIZE 0xA2AB
+#define mmVGT_ESGS_RING_SIZE 0x2232
+#define mmVGT_ES_PER_GS 0xA296
+#define mmVGT_EVENT_ADDRESS_REG 0xA1FE
+#define mmVGT_EVENT_INITIATOR 0xA2A4
+#define mmVGT_FIFO_DEPTHS 0x2234
+#define mmVGT_GROUP_DECR 0xA28B
+#define mmVGT_GROUP_FIRST_DECR 0xA28A
+#define mmVGT_GROUP_PRIM_TYPE 0xA289
+#define mmVGT_GROUP_VECT_0_CNTL 0xA28C
+#define mmVGT_GROUP_VECT_0_FMT_CNTL 0xA28E
+#define mmVGT_GROUP_VECT_1_CNTL 0xA28D
+#define mmVGT_GROUP_VECT_1_FMT_CNTL 0xA28F
+#define mmVGT_GS_INSTANCE_CNT 0xA2E4
+#define mmVGT_GS_MAX_VERT_OUT 0xA2CE
+#define mmVGT_GS_MODE 0xA290
+#define mmVGT_GS_OUT_PRIM_TYPE 0xA29B
+#define mmVGT_GS_PER_ES 0xA295
+#define mmVGT_GS_PER_VS 0xA297
+#define mmVGT_GS_VERTEX_REUSE 0x2235
+#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 mmVGT_GSVS_RING_ITEMSIZE 0xA2AC
+#define mmVGT_GSVS_RING_OFFSET_1 0xA298
+#define mmVGT_GSVS_RING_OFFSET_2 0xA299
+#define mmVGT_GSVS_RING_OFFSET_3 0xA29A
+#define mmVGT_GSVS_RING_SIZE 0x2233
+#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_HS_OFFCHIP_PARAM 0x226C
+#define mmVGT_IMMED_DATA 0xA1FD
+#define mmVGT_INDEX_TYPE 0x2257
+#define mmVGT_INDX_OFFSET 0xA102
+#define mmVGT_INSTANCE_STEP_RATE_0 0xA2A8
+#define mmVGT_INSTANCE_STEP_RATE_1 0xA2A9
+#define mmVGT_LAST_COPY_STATE 0x2230
+#define mmVGT_LS_HS_CONFIG 0xA2D6
+#define mmVGT_MAX_VTX_INDX 0xA100
+#define mmVGT_MC_LAT_CNTL 0x2236
+#define mmVGT_MIN_VTX_INDX 0xA101
+#define mmVGT_MULTI_PRIM_IB_RESET_EN 0xA2A5
+#define mmVGT_MULTI_PRIM_IB_RESET_INDX 0xA103
+#define mmVGT_NUM_INDICES 0x225C
+#define mmVGT_NUM_INSTANCES 0x225D
+#define mmVGT_OUT_DEALLOC_CNTL 0xA317
+#define mmVGT_OUTPUT_PATH_CNTL 0xA284
+#define mmVGT_PERFCOUNTER0_HI 0x224D
+#define mmVGT_PERFCOUNTER0_LO 0x224C
+#define mmVGT_PERFCOUNTER0_SELECT 0x2248
+#define mmVGT_PERFCOUNTER1_HI 0x224F
+#define mmVGT_PERFCOUNTER1_LO 0x224E
+#define mmVGT_PERFCOUNTER1_SELECT 0x2249
+#define mmVGT_PERFCOUNTER2_HI 0x2251
+#define mmVGT_PERFCOUNTER2_LO 0x2250
+#define mmVGT_PERFCOUNTER2_SELECT 0x224A
+#define mmVGT_PERFCOUNTER3_HI 0x2253
+#define mmVGT_PERFCOUNTER3_LO 0x2252
+#define mmVGT_PERFCOUNTER3_SELECT 0x224B
+#define mmVGT_PERFCOUNTER_SEID_MASK 0x2247
+#define mmVGT_PRIMITIVEID_EN 0xA2A1
+#define mmVGT_PRIMITIVEID_RESET 0xA2A3
+#define mmVGT_PRIMITIVE_TYPE 0x2256
+#define mmVGT_REUSE_OFF 0xA2AD
+#define mmVGT_SHADER_STAGES_EN 0xA2D5
+#define mmVGT_STRMOUT_BUFFER_CONFIG 0xA2E6
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_0 0x2258
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_1 0x2259
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_2 0x225A
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_3 0x225B
+#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_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_CONFIG 0xA2E5
+#define mmVGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE 0xA2CB
+#define mmVGT_STRMOUT_DRAW_OPAQUE_OFFSET 0xA2CA
+#define mmVGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0xA2CC
+#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_SYS_CONFIG 0x2263
+#define mmVGT_TF_MEMORY_BASE 0x226E
+#define mmVGT_TF_PARAM 0xA2DB
+#define mmVGT_TF_RING_SIZE 0x2262
+#define mmVGT_VERTEX_REUSE_BLOCK_CNTL 0xA316
+#define mmVGT_VTX_CNT_EN 0xA2AE
+#define mmVGT_VTX_VECT_EJECT_REG 0x222C
+
+/* manually added from old sid.h */
+#define mmCB_PERFCOUNTER0_SELECT0 0x2688
+#define mmCB_PERFCOUNTER1_SELECT0 0x268A
+#define mmCB_PERFCOUNTER1_SELECT1 0x268B
+#define mmCB_PERFCOUNTER2_SELECT0 0x268C
+#define mmCB_PERFCOUNTER2_SELECT1 0x268D
+#define mmCB_PERFCOUNTER3_SELECT0 0x268E
+#define mmCB_PERFCOUNTER3_SELECT1 0x268F
+#define mmCP_COHER_CNTL2 0x217A
+#define mmCP_DEBUG 0x307F
+#define mmRLC_SERDES_MASTER_BUSY_0 0x3119
+#define mmRLC_SERDES_MASTER_BUSY_1 0x311A
+#define mmRLC_RL_BASE 0x30C1
+#define mmRLC_RL_SIZE 0x30C2
+#define mmRLC_UCODE_ADDR 0x30CB
+#define mmRLC_UCODE_DATA 0x30CC
+#define mmRLC_GCPM_GENERAL_3 0x311E
+#define mmRLC_SERDES_WR_MASTER_MASK_0 0x3115
+#define mmRLC_SERDES_WR_MASTER_MASK_1 0x3116
+#define mmRLC_TTOP_D 0x3105
+#define mmRLC_CLEAR_STATE_RESTORE_BASE 0x30C8
+#define mmRLC_PG_AO_CU_MASK 0x310B
+#define mmSPI_STATIC_THREAD_MGMT_3 0x243A
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
new file mode 100644
index 000000000000..b5e634749665
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
@@ -0,0 +1,12821 @@
+/*
+ *
+ * Copyright (C) 2016 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_6_0_SH_MASK_H
+#define GFX_6_0_SH_MASK_H
+
+#define BCI_DEBUG_READ__DATA_MASK 0x00ffffffL
+#define BCI_DEBUG_READ__DATA__SHIFT 0x00000000
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND0_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND0_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND0_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND0_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND1_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND1_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND1_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND1_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND2_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND2_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND2_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND2_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND3_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND3_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND3_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND3_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND4_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND4_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND4_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND4_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND5_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND5_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND5_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND5_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND6_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND6_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND6_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND6_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND7_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND7_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND7_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND7_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND_ALPHA__BLEND_ALPHA_MASK 0xffffffffL
+#define CB_BLEND_ALPHA__BLEND_ALPHA__SHIFT 0x00000000
+#define CB_BLEND_BLUE__BLEND_BLUE_MASK 0xffffffffL
+#define CB_BLEND_BLUE__BLEND_BLUE__SHIFT 0x00000000
+#define CB_BLEND_GREEN__BLEND_GREEN_MASK 0xffffffffL
+#define CB_BLEND_GREEN__BLEND_GREEN__SHIFT 0x00000000
+#define CB_BLEND_RED__BLEND_RED_MASK 0xffffffffL
+#define CB_BLEND_RED__BLEND_RED__SHIFT 0x00000000
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CB_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CB_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR0_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR0_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR0_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR0_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR0_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR0_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR0_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR0_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR0_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR0_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR0_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR0_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR0_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR0_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR0_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR0_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR0_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR0_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR0_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR0_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR0_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR0_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR0_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR0_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR0_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR0_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR0_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR0_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR0_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR1_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR1_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR1_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR1_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR1_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR1_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR1_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR1_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR1_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR1_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR1_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR1_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR1_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR1_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR1_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR1_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR1_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR1_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR1_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR1_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR1_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR1_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR1_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR1_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR1_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR1_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR1_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR1_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR1_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR2_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR2_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR2_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR2_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR2_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR2_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR2_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR2_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR2_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR2_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR2_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR2_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR2_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR2_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR2_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR2_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR2_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR2_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR2_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR2_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR2_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR2_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR2_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR2_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR2_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR2_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR2_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR2_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR2_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR3_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR3_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR3_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR3_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR3_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR3_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR3_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR3_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR3_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR3_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR3_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR3_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR3_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR3_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR3_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR3_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR3_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR3_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR3_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR3_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR3_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR3_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR3_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR3_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR3_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR3_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR3_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR3_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR3_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR4_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR4_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR4_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR4_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR4_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR4_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR4_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR4_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR4_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR4_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR4_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR4_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR4_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR4_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR4_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR4_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR4_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR4_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR4_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR4_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR4_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR4_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR4_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR4_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR4_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR4_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR4_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR4_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR4_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR5_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR5_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR5_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR5_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR5_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR5_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR5_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR5_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR5_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR5_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR5_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR5_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR5_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR5_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR5_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR5_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR5_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR5_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR5_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR5_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR5_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR5_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR5_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR5_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR5_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR5_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR5_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR5_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR5_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR6_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR6_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR6_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR6_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR6_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR6_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR6_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR6_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR6_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR6_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR6_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR6_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR6_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR6_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR6_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR6_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR6_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR6_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR6_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR6_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR6_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR6_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR6_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR6_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR6_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR6_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR6_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR6_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR6_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR7_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR7_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR7_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR7_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR7_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR7_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR7_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR7_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR7_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR7_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR7_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR7_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR7_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR7_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR7_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR7_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR7_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR7_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR7_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR7_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR7_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR7_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR7_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR7_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR7_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR7_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR7_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR7_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR7_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE_MASK 0x00000008L
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE__SHIFT 0x00000003
+#define CB_COLOR_CONTROL__MODE_MASK 0x00000070L
+#define CB_COLOR_CONTROL__MODE__SHIFT 0x00000004
+#define CB_COLOR_CONTROL__ROP3_MASK 0x00ff0000L
+#define CB_COLOR_CONTROL__ROP3__SHIFT 0x00000010
+#define CB_DEBUG_BUS_13__AC_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_13__AC_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_13__CACHE_CTRL_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_13__CACHE_CTRL_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_13__CRW_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_13__CRW_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_13__EVICT_PENDING_MASK 0x00000200L
+#define CB_DEBUG_BUS_13__EVICT_PENDING__SHIFT 0x00000009
+#define CB_DEBUG_BUS_13__FC_RD_PENDING_MASK 0x00000100L
+#define CB_DEBUG_BUS_13__FC_RD_PENDING__SHIFT 0x00000008
+#define CB_DEBUG_BUS_13__FC_WR_PENDING_MASK 0x00000080L
+#define CB_DEBUG_BUS_13__FC_WR_PENDING__SHIFT 0x00000007
+#define CB_DEBUG_BUS_13__LAST_RD_ARB_WINNER_MASK 0x00000400L
+#define CB_DEBUG_BUS_13__LAST_RD_ARB_WINNER__SHIFT 0x0000000a
+#define CB_DEBUG_BUS_13__MC_WR_PENDING_MASK 0x00000040L
+#define CB_DEBUG_BUS_13__MC_WR_PENDING__SHIFT 0x00000006
+#define CB_DEBUG_BUS_13__MU_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_13__MU_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_13__MU_STATE_MASK 0x0007f800L
+#define CB_DEBUG_BUS_13__MU_STATE__SHIFT 0x0000000b
+#define CB_DEBUG_BUS_13__TILE_INTFC_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_13__TILE_INTFC_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_13__TQ_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_13__TQ_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_14__ADDR_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_14__ADDR_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_14__CACHE_CTL_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_14__CACHE_CTL_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_14__CLEAR_BUSY_MASK 0x00000100L
+#define CB_DEBUG_BUS_14__CLEAR_BUSY__SHIFT 0x00000008
+#define CB_DEBUG_BUS_14__FOP_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_14__FOP_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_14__LAT_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_14__LAT_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_14__MERGE_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_14__MERGE_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_14__QUAD_BUSY_MASK 0x00000040L
+#define CB_DEBUG_BUS_14__QUAD_BUSY__SHIFT 0x00000006
+#define CB_DEBUG_BUS_14__TILE_BUSY_MASK 0x00000080L
+#define CB_DEBUG_BUS_14__TILE_BUSY__SHIFT 0x00000007
+#define CB_DEBUG_BUS_14__TILE_RETIREMENT_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_14__TILE_RETIREMENT_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_15__CS_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_15__CS_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_15__DS_BUSY_MASK 0x00000040L
+#define CB_DEBUG_BUS_15__DS_BUSY__SHIFT 0x00000006
+#define CB_DEBUG_BUS_15__IB_BUSY_MASK 0x00000100L
+#define CB_DEBUG_BUS_15__IB_BUSY__SHIFT 0x00000008
+#define CB_DEBUG_BUS_15__RB_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_15__RB_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_15__SF_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_15__SF_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_15__SURF_SYNC_START_MASK 0x00000004L
+#define CB_DEBUG_BUS_15__SURF_SYNC_START__SHIFT 0x00000002
+#define CB_DEBUG_BUS_15__SURF_SYNC_STATE_MASK 0x00000003L
+#define CB_DEBUG_BUS_15__SURF_SYNC_STATE__SHIFT 0x00000000
+#define CB_DEBUG_BUS_15__TB_BUSY_MASK 0x00000080L
+#define CB_DEBUG_BUS_15__TB_BUSY__SHIFT 0x00000007
+#define CB_DEBUG_BUS_16__CC_WRREQ_FIFO_EMPTY_MASK 0x00100000L
+#define CB_DEBUG_BUS_16__CC_WRREQ_FIFO_EMPTY__SHIFT 0x00000014
+#define CB_DEBUG_BUS_16__CM_WRREQ_FIFO_EMPTY_MASK 0x00400000L
+#define CB_DEBUG_BUS_16__CM_WRREQ_FIFO_EMPTY__SHIFT 0x00000016
+#define CB_DEBUG_BUS_16__FC_WRREQ_FIFO_EMPTY_MASK 0x00200000L
+#define CB_DEBUG_BUS_16__FC_WRREQ_FIFO_EMPTY__SHIFT 0x00000015
+#define CB_DEBUG_BUS_16__LAST_RD_GRANT_VEC_MASK 0x000003c0L
+#define CB_DEBUG_BUS_16__LAST_RD_GRANT_VEC__SHIFT 0x00000006
+#define CB_DEBUG_BUS_16__LAST_WR_GRANT_VEC_MASK 0x000f0000L
+#define CB_DEBUG_BUS_16__LAST_WR_GRANT_VEC__SHIFT 0x00000010
+#define CB_DEBUG_BUS_16__MC_RDREQ_CREDITS_MASK 0x0000003fL
+#define CB_DEBUG_BUS_16__MC_RDREQ_CREDITS__SHIFT 0x00000000
+#define CB_DEBUG_BUS_16__MC_WRREQ_CREDITS_MASK 0x0000fc00L
+#define CB_DEBUG_BUS_16__MC_WRREQ_CREDITS__SHIFT 0x0000000a
+#define CB_DEBUG_BUS_17__BB_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_17__BB_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_17__CC_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_17__CC_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_17__CM_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_17__CM_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_17__CORE_SCLK_VLD_MASK 0x00000020L
+#define CB_DEBUG_BUS_17__CORE_SCLK_VLD__SHIFT 0x00000005
+#define CB_DEBUG_BUS_17__FC_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_17__FC_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_17__MA_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_17__MA_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_17__REG_SCLK0_VLD_MASK 0x00000080L
+#define CB_DEBUG_BUS_17__REG_SCLK0_VLD__SHIFT 0x00000007
+#define CB_DEBUG_BUS_17__REG_SCLK1_VLD_MASK 0x00000040L
+#define CB_DEBUG_BUS_17__REG_SCLK1_VLD__SHIFT 0x00000006
+#define CB_DEBUG_BUS_18__NOT_USED_MASK 0x00ffffffL
+#define CB_DEBUG_BUS_18__NOT_USED__SHIFT 0x00000000
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS_MASK 0x0001f800L
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS__SHIFT 0x0000000b
+#define CB_HW_CONTROL_1__CHICKEN_BITS_MASK 0xfc000000L
+#define CB_HW_CONTROL_1__CHICKEN_BITS__SHIFT 0x0000001a
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS_MASK 0x0000001fL
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS__SHIFT 0x00000000
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH_MASK 0x03fe0000L
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH__SHIFT 0x00000011
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS_MASK 0x000007e0L
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS__SHIFT 0x00000005
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH_MASK 0x000000ffL
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH__SHIFT 0x00000000
+#define CB_HW_CONTROL_2__CHICKEN_BITS_MASK 0xff800000L
+#define CB_HW_CONTROL_2__CHICKEN_BITS__SHIFT 0x00000017
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH_MASK 0x007f8000L
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH__SHIFT 0x0000000f
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH_MASK 0x00007f00L
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH__SHIFT 0x00000008
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL_MASK 0x00000001L
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL__SHIFT 0x00000000
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE_MASK 0x00010000L
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE__SHIFT 0x00000010
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT_MASK 0x0000f000L
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT__SHIFT 0x0000000c
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT_MASK 0x0000000fL
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT__SHIFT 0x00000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS_MASK 0x02000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS__SHIFT 0x00000019
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL_MASK 0x04000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL__SHIFT 0x0000001a
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST_MASK 0x01000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST__SHIFT 0x00000018
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST_MASK 0x00200000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST__SHIFT 0x00000015
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED_MASK 0x08000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED__SHIFT 0x0000001b
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT_MASK 0x40000000L
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT__SHIFT 0x0000001e
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK_MASK 0x00400000L
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK__SHIFT 0x00000016
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING_MASK 0x00040000L
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING__SHIFT 0x00000012
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE_MASK 0x80000000L
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE__SHIFT 0x0000001f
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG_MASK 0x00800000L
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG__SHIFT 0x00000017
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT_MASK 0x000003c0L
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT__SHIFT 0x00000006
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE_MASK 0x00100000L
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE__SHIFT 0x00000014
+#define CB_HW_CONTROL__FORCE_NEEDS_DST_MASK 0x00080000L
+#define CB_HW_CONTROL__FORCE_NEEDS_DST__SHIFT 0x00000013
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT_MASK 0x20000000L
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT__SHIFT 0x0000001d
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT_MASK 0x10000000L
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT__SHIFT 0x0000001c
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000001ffL
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0007fc00L
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_SHADER_MASK__OUTPUT0_ENABLE_MASK 0x0000000fL
+#define CB_SHADER_MASK__OUTPUT0_ENABLE__SHIFT 0x00000000
+#define CB_SHADER_MASK__OUTPUT1_ENABLE_MASK 0x000000f0L
+#define CB_SHADER_MASK__OUTPUT1_ENABLE__SHIFT 0x00000004
+#define CB_SHADER_MASK__OUTPUT2_ENABLE_MASK 0x00000f00L
+#define CB_SHADER_MASK__OUTPUT2_ENABLE__SHIFT 0x00000008
+#define CB_SHADER_MASK__OUTPUT3_ENABLE_MASK 0x0000f000L
+#define CB_SHADER_MASK__OUTPUT3_ENABLE__SHIFT 0x0000000c
+#define CB_SHADER_MASK__OUTPUT4_ENABLE_MASK 0x000f0000L
+#define CB_SHADER_MASK__OUTPUT4_ENABLE__SHIFT 0x00000010
+#define CB_SHADER_MASK__OUTPUT5_ENABLE_MASK 0x00f00000L
+#define CB_SHADER_MASK__OUTPUT5_ENABLE__SHIFT 0x00000014
+#define CB_SHADER_MASK__OUTPUT6_ENABLE_MASK 0x0f000000L
+#define CB_SHADER_MASK__OUTPUT6_ENABLE__SHIFT 0x00000018
+#define CB_SHADER_MASK__OUTPUT7_ENABLE_MASK 0xf0000000L
+#define CB_SHADER_MASK__OUTPUT7_ENABLE__SHIFT 0x0000001c
+#define CB_TARGET_MASK__TARGET0_ENABLE_MASK 0x0000000fL
+#define CB_TARGET_MASK__TARGET0_ENABLE__SHIFT 0x00000000
+#define CB_TARGET_MASK__TARGET1_ENABLE_MASK 0x000000f0L
+#define CB_TARGET_MASK__TARGET1_ENABLE__SHIFT 0x00000004
+#define CB_TARGET_MASK__TARGET2_ENABLE_MASK 0x00000f00L
+#define CB_TARGET_MASK__TARGET2_ENABLE__SHIFT 0x00000008
+#define CB_TARGET_MASK__TARGET3_ENABLE_MASK 0x0000f000L
+#define CB_TARGET_MASK__TARGET3_ENABLE__SHIFT 0x0000000c
+#define CB_TARGET_MASK__TARGET4_ENABLE_MASK 0x000f0000L
+#define CB_TARGET_MASK__TARGET4_ENABLE__SHIFT 0x00000010
+#define CB_TARGET_MASK__TARGET5_ENABLE_MASK 0x00f00000L
+#define CB_TARGET_MASK__TARGET5_ENABLE__SHIFT 0x00000014
+#define CB_TARGET_MASK__TARGET6_ENABLE_MASK 0x0f000000L
+#define CB_TARGET_MASK__TARGET6_ENABLE__SHIFT 0x00000018
+#define CB_TARGET_MASK__TARGET7_ENABLE_MASK 0xf0000000L
+#define CB_TARGET_MASK__TARGET7_ENABLE__SHIFT 0x0000001c
+#define CC_GC_SHADER_ARRAY_CONFIG__DPFP_RATE_MASK 0x00000006L
+#define CC_GC_SHADER_ARRAY_CONFIG__DPFP_RATE__SHIFT 0x00000001
+#define CC_GC_SHADER_ARRAY_CONFIG__HALF_LDS_MASK 0x00000010L
+#define CC_GC_SHADER_ARRAY_CONFIG__HALF_LDS__SHIFT 0x00000004
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000L
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x00000010
+#define CC_GC_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE_MASK 0x00000008L
+#define CC_GC_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x00000003
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define CC_RB_DAISY_CHAIN__RB_0_MASK 0x0000000fL
+#define CC_RB_DAISY_CHAIN__RB_0__SHIFT 0x00000000
+#define CC_RB_DAISY_CHAIN__RB_1_MASK 0x000000f0L
+#define CC_RB_DAISY_CHAIN__RB_1__SHIFT 0x00000004
+#define CC_RB_DAISY_CHAIN__RB_2_MASK 0x00000f00L
+#define CC_RB_DAISY_CHAIN__RB_2__SHIFT 0x00000008
+#define CC_RB_DAISY_CHAIN__RB_3_MASK 0x0000f000L
+#define CC_RB_DAISY_CHAIN__RB_3__SHIFT 0x0000000c
+#define CC_RB_DAISY_CHAIN__RB_4_MASK 0x000f0000L
+#define CC_RB_DAISY_CHAIN__RB_4__SHIFT 0x00000010
+#define CC_RB_DAISY_CHAIN__RB_5_MASK 0x00f00000L
+#define CC_RB_DAISY_CHAIN__RB_5__SHIFT 0x00000014
+#define CC_RB_DAISY_CHAIN__RB_6_MASK 0x0f000000L
+#define CC_RB_DAISY_CHAIN__RB_6__SHIFT 0x00000018
+#define CC_RB_DAISY_CHAIN__RB_7_MASK 0xf0000000L
+#define CC_RB_DAISY_CHAIN__RB_7__SHIFT 0x0000001c
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0_MASK 0x00001000L
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0__SHIFT 0x0000000c
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1_MASK 0x00100000L
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1__SHIFT 0x00000014
+#define CC_RB_REDUNDANCY__FAILED_RB0_MASK 0x00000f00L
+#define CC_RB_REDUNDANCY__FAILED_RB0__SHIFT 0x00000008
+#define CC_RB_REDUNDANCY__FAILED_RB1_MASK 0x000f0000L
+#define CC_RB_REDUNDANCY__FAILED_RB1__SHIFT 0x00000010
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0x000f0000L
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x00000010
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0x00f00000L
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x00000014
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0x0f000000L
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x00000018
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000L
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x0000001c
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL_MASK 0x00001f00L
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL__SHIFT 0x00000008
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL_MASK 0x0000001fL
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL__SHIFT 0x00000000
+#define CGTS_RD_REG__READ_DATA_MASK 0x00003fffL
+#define CGTS_RD_REG__READ_DATA__SHIFT 0x00000000
+#define CGTS_SM_CTRL_REG__BASE_MODE_MASK 0x00010000L
+#define CGTS_SM_CTRL_REG__BASE_MODE__SHIFT 0x00000010
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK 0x00400000L
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE__SHIFT 0x00000016
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED_MASK 0x00001000L
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED__SHIFT 0x0000000c
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY_MASK 0x00000ff0L
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY__SHIFT 0x00000004
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK 0x00800000L
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN__SHIFT 0x00000017
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_MASK 0xff000000L
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT 0x00000018
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY_MASK 0x0000000fL
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY__SHIFT 0x00000000
+#define CGTS_SM_CTRL_REG__OVERRIDE_MASK 0x00200000L
+#define CGTS_SM_CTRL_REG__OVERRIDE__SHIFT 0x00000015
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK 0x00100000L
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE__SHIFT 0x00000014
+#define CGTS_SM_CTRL_REG__SM_MODE_MASK 0x000e0000L
+#define CGTS_SM_CTRL_REG__SM_MODE__SHIFT 0x00000011
+#define CGTS_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000L
+#define CGTS_TCC_DISABLE__TCC_DISABLE__SHIFT 0x00000010
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000L
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE__SHIFT 0x00000010
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000L
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000L
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000L
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE_MASK 0x08000000L
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE_MASK 0x04000000L
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE_MASK 0x02000000L
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE__SHIFT 0x00000019
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE_MASK 0x01000000L
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE__SHIFT 0x00000018
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_BCI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_BCI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_BCI_CLK_CTRL__RESERVED_MASK 0x00fff000L
+#define CGTT_BCI_CLK_CTRL__RESERVED__SHIFT 0x0000000c
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_CP_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_CP_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000L
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x0000001e
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000L
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x0000001f
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_GDS_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_GDS_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE_MASK 0x20000000L
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE_MASK 0x04000000L
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE__SHIFT 0x0000001a
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_IA_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_IA_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE_MASK 0x02000000L
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE__SHIFT 0x00000019
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE_MASK 0x40000000L
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_PA_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_PA_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE_MASK 0x80000000L
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE_MASK 0x20000000L
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE_MASK 0x02000000L
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE__SHIFT 0x00000019
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000L
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000L
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000L
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE_MASK 0x08000000L
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE_MASK 0x04000000L
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0x00fc0000L
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x00000012
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x01000000L
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x00000018
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_PC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_PC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_RLC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_RLC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000L
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x0000001e
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000L
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x0000001f
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE_MASK 0x04000000L
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE_MASK 0x40000000L
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE_MASK 0x20000000L
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE_MASK 0x10000000L
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE_MASK 0x08000000L
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0x00fc0000L
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x00000012
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x01000000L
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x00000018
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SPI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SPI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SQ_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SQ_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SQG_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SQG_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL0__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL0__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL0__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL0__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL1__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL1__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL1__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL1__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL2__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL2__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL2__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL2__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL3__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL3__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL3__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL3__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL4__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL4__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL4__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL4__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_TCI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_TCI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_TCP_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_TCP_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE_MASK 0x04000000L
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE__SHIFT 0x0000001a
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE_MASK 0x20000000L
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_VGT_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_VGT_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE_MASK 0x02000000L
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE__SHIFT 0x00000019
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write_MASK 0x00000100L
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full_MASK 0x00001000L
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write_MASK 0x00000800L
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty_MASK 0x00008000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty__SHIFT 0x0000000f
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full_MASK 0x00010000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty_MASK 0x00002000L
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full_MASK 0x00004000L
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free_MASK 0x00000600L
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free__SHIFT 0x00000009
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty_MASK 0x00020000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid_MASK 0x00000700L
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot_MASK 0x000e0000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate_MASK 0x0001c000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid_MASK 0x00003800L
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx_MASK 0x0c000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid_MASK 0x00000007L
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx_MASK 0x000000c0L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0_MASK 0x000f0000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1_MASK 0x0000f000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid_MASK 0x00000038L
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt_MASK 0x00f00000L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event_MASK 0x00000008L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive_MASK 0x00000040L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt_MASK 0x000f0000L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event_MASK 0x00000004L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event__SHIFT 0x00000002
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive_MASK 0x00000020L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive__SHIFT 0x00000005
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt_MASK 0x0000f000L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event_MASK 0x00000002L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive_MASK 0x00000010L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive__SHIFT 0x00000004
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event_MASK 0x00000001L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load_MASK 0x00c00000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out_MASK 0x000c0000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert_MASK 0x00300000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty_MASK 0x00010000L
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx_MASK 0x00003000L
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty_MASK 0x00008000L
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty__SHIFT 0x0000000f
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt_MASK 0x001e0000L
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive_MASK 0x00000020L
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive__SHIFT 0x00000005
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive_MASK 0x00000040L
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx_MASK 0x00000007L
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents_MASK 0x1f000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices_MASK 0x00600000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG13__point_clip_candidate_MASK 0x00000008L
+#define CLIPPER_DEBUG_REG13__point_clip_candidate__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG13__prim_back_valid_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG13__prim_back_valid__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG13__prim_nan_kill_MASK 0x00000010L
+#define CLIPPER_DEBUG_REG13__prim_nan_kill__SHIFT 0x00000004
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty_MASK 0x00004000L
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot_MASK 0x00e00000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id_MASK 0x3f000000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0_MASK 0x0003f000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1_MASK 0x00000fc0L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2_MASK 0x0000003fL
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG14__prim_back_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG14__prim_back_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0_MASK 0x7c000000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1_MASK 0x03e00000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2_MASK 0x001f0000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb_MASK 0x0000ffffL
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG16__sm0_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG16__sm0_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG17__sm1_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG17__sm1_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG18__sm2_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG18__sm2_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG19__sm3_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG19__sm3_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt__SHIFT 0x0000000d
+#define COHER_DEST_BASE_0__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_0__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_1__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_1__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_2__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_2__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_3__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_3__DEST_BASE_256B__SHIFT 0x00000000
+#define COMPUTE_DIM_X__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_X__SIZE__SHIFT 0x00000000
+#define COMPUTE_DIM_Y__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_Y__SIZE__SHIFT 0x00000000
+#define COMPUTE_DIM_Z__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_Z__SIZE__SHIFT 0x00000000
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN_MASK 0x00000001L
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN__SHIFT 0x00000000
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC_MASK 0x00001000L
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC__SHIFT 0x0000000c
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL_MASK 0x00000380L
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL__SHIFT 0x00000007
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000_MASK 0x00000004L
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000__SHIFT 0x00000002
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL_MASK 0x00000008L
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL__SHIFT 0x00000003
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE_MASK 0x00000010L
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE__SHIFT 0x00000004
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE_MASK 0x00000040L
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE__SHIFT 0x00000006
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN_MASK 0x00000002L
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN__SHIFT 0x00000001
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE_MASK 0x00004000L
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE__SHIFT 0x0000000e
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL_MASK 0x00000400L
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL__SHIFT 0x0000000a
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS_MASK 0x00000020L
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS__SHIFT 0x00000005
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL_MASK 0x00000800L
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL__SHIFT 0x0000000b
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_PGM_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_PGM_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_PGM_HI__INST_ATC_MASK 0x00000100L
+#define COMPUTE_PGM_HI__INST_ATC__SHIFT 0x00000008
+#define COMPUTE_PGM_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_PGM_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC1__BULKY_MASK 0x01000000L
+#define COMPUTE_PGM_RSRC1__BULKY__SHIFT 0x00000018
+#define COMPUTE_PGM_RSRC1__CDBG_USER_MASK 0x02000000L
+#define COMPUTE_PGM_RSRC1__CDBG_USER__SHIFT 0x00000019
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE_MASK 0x00400000L
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE__SHIFT 0x00000016
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP_MASK 0x00200000L
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP__SHIFT 0x00000015
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE_MASK 0x000ff000L
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE__SHIFT 0x0000000c
+#define COMPUTE_PGM_RSRC1__IEEE_MODE_MASK 0x00800000L
+#define COMPUTE_PGM_RSRC1__IEEE_MODE__SHIFT 0x00000017
+#define COMPUTE_PGM_RSRC1__PRIORITY_MASK 0x00000c00L
+#define COMPUTE_PGM_RSRC1__PRIORITY__SHIFT 0x0000000a
+#define COMPUTE_PGM_RSRC1__PRIV_MASK 0x00100000L
+#define COMPUTE_PGM_RSRC1__PRIV__SHIFT 0x00000014
+#define COMPUTE_PGM_RSRC1__SGPRS_MASK 0x000003c0L
+#define COMPUTE_PGM_RSRC1__SGPRS__SHIFT 0x00000006
+#define COMPUTE_PGM_RSRC1__VGPRS_MASK 0x0000003fL
+#define COMPUTE_PGM_RSRC1__VGPRS__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MASK 0x7f000000L
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB_MASK 0x00006000L
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB__SHIFT 0x0000000d
+#define COMPUTE_PGM_RSRC2__EXCP_EN__SHIFT 0x00000018
+#define COMPUTE_PGM_RSRC2__LDS_SIZE_MASK 0x00ff8000L
+#define COMPUTE_PGM_RSRC2__LDS_SIZE__SHIFT 0x0000000f
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN_MASK 0x00000001L
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC2__TGID_X_EN_MASK 0x00000080L
+#define COMPUTE_PGM_RSRC2__TGID_X_EN__SHIFT 0x00000007
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN_MASK 0x00000100L
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN__SHIFT 0x00000008
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN_MASK 0x00000200L
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN__SHIFT 0x00000009
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN_MASK 0x00000400L
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN__SHIFT 0x0000000a
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT_MASK 0x00001800L
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT__SHIFT 0x0000000b
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT_MASK 0x00000040L
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT__SHIFT 0x00000006
+#define COMPUTE_PGM_RSRC2__USER_SGPR_MASK 0x0000003eL
+#define COMPUTE_PGM_RSRC2__USER_SGPR__SHIFT 0x00000001
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT_MASK 0x07000000L
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT__SHIFT 0x00000018
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST_MASK 0x00800000L
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST__SHIFT 0x00000017
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD_MASK 0x003f0000L
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD__SHIFT 0x00000010
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL_MASK 0x00400000L
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL__SHIFT 0x00000016
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU_MASK 0x0000f000L
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU__SHIFT 0x0000000c
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH_MASK 0x0000003fL
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH__SHIFT 0x00000000
+#define COMPUTE_START_X__START_MASK 0xffffffffL
+#define COMPUTE_START_X__START__SHIFT 0x00000000
+#define COMPUTE_START_Y__START_MASK 0xffffffffL
+#define COMPUTE_START_Y__START__SHIFT 0x00000000
+#define COMPUTE_START_Z__START_MASK 0xffffffffL
+#define COMPUTE_START_Z__START__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN_MASK 0x0000ffffL
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN_MASK 0xffff0000L
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN__SHIFT 0x00000010
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN_MASK 0x0000ffffL
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN_MASK 0xffff0000L
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN__SHIFT 0x00000010
+#define COMPUTE_TBA_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_TBA_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_TBA_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_TBA_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_TMA_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_TMA_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_TMA_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_TMA_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_TMPRING_SIZE__WAVESIZE_MASK 0x01fff000L
+#define COMPUTE_TMPRING_SIZE__WAVESIZE__SHIFT 0x0000000c
+#define COMPUTE_TMPRING_SIZE__WAVES_MASK 0x00000fffL
+#define COMPUTE_TMPRING_SIZE__WAVES__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_0__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_0__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_10__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_10__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_11__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_11__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_12__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_12__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_13__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_13__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_14__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_14__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_15__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_15__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_1__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_1__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_2__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_2__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_3__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_3__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_4__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_4__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_5__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_5__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_6__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_6__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_7__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_7__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_8__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_8__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_9__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_9__DATA__SHIFT 0x00000000
+#define COMPUTE_VMID__DATA_MASK 0x0000000fL
+#define COMPUTE_VMID__DATA__SHIFT 0x00000000
+#define CP_APPEND_ADDR_HI__COMMAND_MASK 0xe0000000L
+#define CP_APPEND_ADDR_HI__COMMAND__SHIFT 0x0000001d
+#define CP_APPEND_ADDR_HI__CS_PS_SEL_MASK 0x00030000L
+#define CP_APPEND_ADDR_HI__CS_PS_SEL__SHIFT 0x00000010
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI_MASK 0x000000ffL
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI__SHIFT 0x00000000
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO_MASK 0xfffffffcL
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO__SHIFT 0x00000002
+#define CP_APPEND_DATA__DATA_MASK 0xffffffffL
+#define CP_APPEND_DATA__DATA__SHIFT 0x00000000
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE_MASK 0xffffffffL
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE__SHIFT 0x00000000
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE_MASK 0xffffffffL
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE__SHIFT 0x00000000
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI_MASK 0xffffffffL
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI__SHIFT 0x00000000
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO_MASK 0xffffffffL
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO__SHIFT 0x00000000
+#define CP_BUSY_STAT__CE_PARSING_PACKETS_MASK 0x00400000L
+#define CP_BUSY_STAT__CE_PARSING_PACKETS__SHIFT 0x00000016
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO_MASK 0x00000040L
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO__SHIFT 0x00000006
+#define CP_BUSY_STAT__EOP_DONE_BUSY_MASK 0x00040000L
+#define CP_BUSY_STAT__EOP_DONE_BUSY__SHIFT 0x00000012
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY_MASK 0x00008000L
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY__SHIFT 0x0000000f
+#define CP_BUSY_STAT__ME_PARSER_BUSY_MASK 0x00020000L
+#define CP_BUSY_STAT__ME_PARSER_BUSY__SHIFT 0x00000011
+#define CP_BUSY_STAT__ME_PARSING_PACKETS_MASK 0x00000100L
+#define CP_BUSY_STAT__ME_PARSING_PACKETS__SHIFT 0x00000008
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS_MASK 0x00000080L
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS__SHIFT 0x00000007
+#define CP_BUSY_STAT__PIPE_STATS_BUSY_MASK 0x00100000L
+#define CP_BUSY_STAT__PIPE_STATS_BUSY__SHIFT 0x00000014
+#define CP_BUSY_STAT__RCIU_CE_BUSY_MASK 0x00200000L
+#define CP_BUSY_STAT__RCIU_CE_BUSY__SHIFT 0x00000015
+#define CP_BUSY_STAT__RCIU_ME_BUSY_MASK 0x00000400L
+#define CP_BUSY_STAT__RCIU_ME_BUSY__SHIFT 0x0000000a
+#define CP_BUSY_STAT__RCIU_PFP_BUSY_MASK 0x00000200L
+#define CP_BUSY_STAT__RCIU_PFP_BUSY__SHIFT 0x00000009
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY_MASK 0x00000001L
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY__SHIFT 0x00000000
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY_MASK 0x00001000L
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY__SHIFT 0x0000000c
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING_MASK 0x00002000L
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING__SHIFT 0x0000000d
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS_MASK 0x00004000L
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS__SHIFT 0x0000000e
+#define CP_BUSY_STAT__STRM_OUT_BUSY_MASK 0x00080000L
+#define CP_BUSY_STAT__STRM_OUT_BUSY__SHIFT 0x00000013
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP_MASK 0xffffffffL
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP__SHIFT 0x00000000
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI_MASK 0x000000ffL
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x00000000
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffcL
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x00000002
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ_MASK 0x000fffffL
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x00000000
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI_MASK 0x000000ffL
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x00000000
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffcL
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x00000002
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ_MASK 0x000fffffL
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x00000000
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI_MASK 0x000000ffL
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI__SHIFT 0x00000000
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO_MASK 0xffffffe0L
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO__SHIFT 0x00000005
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ_MASK 0x00000fffL
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ__SHIFT 0x00000000
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1_MASK 0x07ff0000L
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1__SHIFT 0x00000010
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING_MASK 0x000007ffL
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING__SHIFT 0x00000000
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2_MASK 0x000007ffL
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2__SHIFT 0x00000000
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1_MASK 0x000003ffL
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1__SHIFT 0x00000000
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1_MASK 0x03ff0000L
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1__SHIFT 0x00000010
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2_MASK 0x000003ffL
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2__SHIFT 0x00000000
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2_MASK 0x03ff0000L
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2__SHIFT 0x00000010
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY_MASK 0x000003ffL
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY__SHIFT 0x00000000
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY_MASK 0x03ff0000L
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY__SHIFT 0x00000010
+#define CP_CE_UCODE_ADDR__UCODE_ADDR_MASK 0x00000fffL
+#define CP_CE_UCODE_ADDR__UCODE_ADDR__SHIFT 0x00000000
+#define CP_CE_UCODE_DATA__UCODE_DATA_MASK 0xffffffffL
+#define CP_CE_UCODE_DATA__UCODE_DATA__SHIFT 0x00000000
+#define CP_CMD_DATA__CMD_DATA_MASK 0xffffffffL
+#define CP_CMD_DATA__CMD_DATA__SHIFT 0x00000000
+#define CP_CMD_INDEX__CMD_INDEX_MASK 0x000007ffL
+#define CP_CMD_INDEX__CMD_INDEX__SHIFT 0x00000000
+#define CP_CMD_INDEX__CMD_ME_SEL_MASK 0x00003000L
+#define CP_CMD_INDEX__CMD_ME_SEL__SHIFT 0x0000000c
+#define CP_CMD_INDEX__CMD_QUEUE_SEL_MASK 0x00030000L
+#define CP_CMD_INDEX__CMD_QUEUE_SEL__SHIFT 0x00000010
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS_MASK 0x0ff00000L
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS__SHIFT 0x00000014
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS_MASK 0x000000ffL
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS__SHIFT 0x00000000
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT_MASK 0x70000000L
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT__SHIFT 0x0000001c
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT_MASK 0x00000700L
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT__SHIFT 0x00000008
+#define CP_COHER_BASE__COHER_BASE_256B_MASK 0xffffffffL
+#define CP_COHER_BASE__COHER_BASE_256B__SHIFT 0x00000000
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B_MASK 0x000000ffL
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B__SHIFT 0x00000000
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA_MASK 0x00000040L
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA__SHIFT 0x00000006
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA_MASK 0x00000080L
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA__SHIFT 0x00000007
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA_MASK 0x00000100L
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA__SHIFT 0x00000008
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA_MASK 0x00000200L
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA__SHIFT 0x00000009
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA_MASK 0x00000400L
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA__SHIFT 0x0000000a
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA_MASK 0x00000800L
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA__SHIFT 0x0000000b
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA_MASK 0x00001000L
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA__SHIFT 0x0000000c
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA_MASK 0x00002000L
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA__SHIFT 0x0000000d
+#define CP_COHER_CNTL__CB_ACTION_ENA_MASK 0x02000000L
+#define CP_COHER_CNTL__CB_ACTION_ENA__SHIFT 0x00000019
+#define CP_COHER_CNTL__DB_ACTION_ENA_MASK 0x04000000L
+#define CP_COHER_CNTL__DB_ACTION_ENA__SHIFT 0x0000001a
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA_MASK 0x00004000L
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA__SHIFT 0x0000000e
+#define CP_COHER_CNTL__DEST_BASE_0_ENA_MASK 0x00000001L
+#define CP_COHER_CNTL__DEST_BASE_0_ENA__SHIFT 0x00000000
+#define CP_COHER_CNTL__DEST_BASE_1_ENA_MASK 0x00000002L
+#define CP_COHER_CNTL__DEST_BASE_1_ENA__SHIFT 0x00000001
+#define CP_COHER_CNTL__DEST_BASE_2_ENA_MASK 0x00080000L
+#define CP_COHER_CNTL__DEST_BASE_2_ENA__SHIFT 0x00000013
+#define CP_COHER_CNTL__DEST_BASE_3_ENA_MASK 0x00200000L
+#define CP_COHER_CNTL__DEST_BASE_3_ENA__SHIFT 0x00000015
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA_MASK 0x20000000L
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA__SHIFT 0x0000001d
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA_MASK 0x08000000L
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA__SHIFT 0x0000001b
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA_MASK 0x10000000L
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA__SHIFT 0x0000001c
+#define CP_COHER_CNTL__TC_ACTION_ENA_MASK 0x00800000L
+#define CP_COHER_CNTL__TC_ACTION_ENA__SHIFT 0x00000017
+#define CP_COHER_CNTL__TCL1_ACTION_ENA_MASK 0x00400000L
+#define CP_COHER_CNTL__TCL1_ACTION_ENA__SHIFT 0x00000016
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA_MASK 0x00008000L
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA__SHIFT 0x0000000f
+#define CP_COHER_CNTL__TC_VOL_ACTION_ENA_MASK 0x00010000L
+#define CP_COHER_CNTL__TC_VOL_ACTION_ENA__SHIFT 0x00000010
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA_MASK 0x00040000L
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA__SHIFT 0x00000012
+#define CP_COHER_SIZE__COHER_SIZE_256B_MASK 0xffffffffL
+#define CP_COHER_SIZE__COHER_SIZE_256B__SHIFT 0x00000000
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B_MASK 0x000000ffL
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B__SHIFT 0x00000000
+#define CP_COHER_START_DELAY__START_DELAY_COUNT_MASK 0x0000003fL
+#define CP_COHER_START_DELAY__START_DELAY_COUNT__SHIFT 0x00000000
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX_MASK 0x000000ffL
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX__SHIFT 0x00000000
+#define CP_COHER_STATUS__MEID_MASK 0x03000000L
+#define CP_COHER_STATUS__MEID__SHIFT 0x00000018
+#define CP_COHER_STATUS__PHASE1_STATUS_MASK 0x40000000L
+#define CP_COHER_STATUS__PHASE1_STATUS__SHIFT 0x0000001e
+#define CP_COHER_STATUS__STATUS_MASK 0x80000000L
+#define CP_COHER_STATUS__STATUS__SHIFT 0x0000001f
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH_MASK 0x0000000fL
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH__SHIFT 0x00000000
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT_MASK 0x00003f00L
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT__SHIFT 0x00000008
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED_MASK 0x0000000fL
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED__SHIFT 0x00000000
+#define CP_DMA_CNTL__BUFFER_DEPTH_MASK 0x000f0000L
+#define CP_DMA_CNTL__BUFFER_DEPTH__SHIFT 0x00000010
+#define CP_DMA_CNTL__MIN_AVAILSZ_MASK 0x00000030L
+#define CP_DMA_CNTL__MIN_AVAILSZ__SHIFT 0x00000004
+#define CP_DMA_CNTL__PIO_COUNT_MASK 0xc0000000L
+#define CP_DMA_CNTL__PIO_COUNT__SHIFT 0x0000001e
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY_MASK 0x10000000L
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY__SHIFT 0x0000001c
+#define CP_DMA_CNTL__PIO_FIFO_FULL_MASK 0x20000000L
+#define CP_DMA_CNTL__PIO_FIFO_FULL__SHIFT 0x0000001d
+#define CP_DMA_ME_COMMAND__BYTE_COUNT_MASK 0x001fffffL
+#define CP_DMA_ME_COMMAND__BYTE_COUNT__SHIFT 0x00000000
+#define CP_DMA_ME_COMMAND__DAIC_MASK 0x20000000L
+#define CP_DMA_ME_COMMAND__DAIC__SHIFT 0x0000001d
+#define CP_DMA_ME_COMMAND__DAS_MASK 0x08000000L
+#define CP_DMA_ME_COMMAND__DAS__SHIFT 0x0000001b
+#define CP_DMA_ME_COMMAND__DIS_WC_MASK 0x00200000L
+#define CP_DMA_ME_COMMAND__DIS_WC__SHIFT 0x00000015
+#define CP_DMA_ME_COMMAND__DST_SWAP_MASK 0x03000000L
+#define CP_DMA_ME_COMMAND__DST_SWAP__SHIFT 0x00000018
+#define CP_DMA_ME_COMMAND__RAW_WAIT_MASK 0x40000000L
+#define CP_DMA_ME_COMMAND__RAW_WAIT__SHIFT 0x0000001e
+#define CP_DMA_ME_COMMAND__SAIC_MASK 0x10000000L
+#define CP_DMA_ME_COMMAND__SAIC__SHIFT 0x0000001c
+#define CP_DMA_ME_COMMAND__SAS_MASK 0x04000000L
+#define CP_DMA_ME_COMMAND__SAS__SHIFT 0x0000001a
+#define CP_DMA_ME_COMMAND__SRC_SWAP_MASK 0x00c00000L
+#define CP_DMA_ME_COMMAND__SRC_SWAP__SHIFT 0x00000016
+#define CP_DMA_ME_DST_ADDR__DST_ADDR_MASK 0xffffffffL
+#define CP_DMA_ME_DST_ADDR__DST_ADDR__SHIFT 0x00000000
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR_MASK 0xffffffffL
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR__SHIFT 0x00000000
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT_MASK 0x001fffffL
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT__SHIFT 0x00000000
+#define CP_DMA_PFP_COMMAND__DAIC_MASK 0x20000000L
+#define CP_DMA_PFP_COMMAND__DAIC__SHIFT 0x0000001d
+#define CP_DMA_PFP_COMMAND__DAS_MASK 0x08000000L
+#define CP_DMA_PFP_COMMAND__DAS__SHIFT 0x0000001b
+#define CP_DMA_PFP_COMMAND__DIS_WC_MASK 0x00200000L
+#define CP_DMA_PFP_COMMAND__DIS_WC__SHIFT 0x00000015
+#define CP_DMA_PFP_COMMAND__DST_SWAP_MASK 0x03000000L
+#define CP_DMA_PFP_COMMAND__DST_SWAP__SHIFT 0x00000018
+#define CP_DMA_PFP_COMMAND__RAW_WAIT_MASK 0x40000000L
+#define CP_DMA_PFP_COMMAND__RAW_WAIT__SHIFT 0x0000001e
+#define CP_DMA_PFP_COMMAND__SAIC_MASK 0x10000000L
+#define CP_DMA_PFP_COMMAND__SAIC__SHIFT 0x0000001c
+#define CP_DMA_PFP_COMMAND__SAS_MASK 0x04000000L
+#define CP_DMA_PFP_COMMAND__SAS__SHIFT 0x0000001a
+#define CP_DMA_PFP_COMMAND__SRC_SWAP_MASK 0x00c00000L
+#define CP_DMA_PFP_COMMAND__SRC_SWAP__SHIFT 0x00000016
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR_MASK 0xffffffffL
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR__SHIFT 0x00000000
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR_MASK 0xffffffffL
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR__SHIFT 0x00000000
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_MASK 0x03ffffffL
+#define CP_DMA_READ_TAGS__DMA_READ_TAG__SHIFT 0x00000000
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID_MASK 0x10000000L
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID__SHIFT 0x0000001c
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING0__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING0__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING0__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING0__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE_RING1__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING1__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING1__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING1__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE_RING2__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING2__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING2__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING2__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE__VMID__SHIFT 0x00000010
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI_MASK 0x0000ffffL
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI__SHIFT 0x00000000
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO_MASK 0xfffffffcL
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO__SHIFT 0x00000002
+#define CP_EOP_DONE_ADDR_LO__ADDR_SWAP_MASK 0x00000003L
+#define CP_EOP_DONE_ADDR_LO__ADDR_SWAP__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID_MASK 0x0000ffffL
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL_MASK 0xe0000000L
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL__SHIFT 0x0000001d
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL_MASK 0x00030000L
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL__SHIFT 0x00000010
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL_MASK 0x07000000L
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL__SHIFT 0x00000018
+#define CP_EOP_DONE_DATA_HI__DATA_HI_MASK 0xffffffffL
+#define CP_EOP_DONE_DATA_HI__DATA_HI__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_LO__DATA_LO_MASK 0xffffffffL
+#define CP_EOP_DONE_DATA_LO__DATA_LO__SHIFT 0x00000000
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI_MASK 0xffffffffL
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI__SHIFT 0x00000000
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO_MASK 0xffffffffL
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO__SHIFT 0x00000000
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI_MASK 0xffffffffL
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI__SHIFT 0x00000000
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO_MASK 0xffffffffL
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO__SHIFT 0x00000000
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI_MASK 0xffffffffL
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI__SHIFT 0x00000000
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO_MASK 0xffffffffL
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO__SHIFT 0x00000000
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS_MASK 0x00003f00L
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS__SHIFT 0x00000008
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_MASK 0x0000003fL
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP_MASK 0x003f0000L
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP__SHIFT 0x00000010
+#define CP_GRBM_FREE_COUNT__FREE_COUNT__SHIFT 0x00000000
+#define CP_IB1_BASE_HI__IB1_BASE_HI_MASK 0x000000ffL
+#define CP_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x00000000
+#define CP_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffcL
+#define CP_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x00000002
+#define CP_IB1_BUFSZ__IB1_BUFSZ_MASK 0x000fffffL
+#define CP_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x00000000
+#define CP_IB1_OFFSET__IB1_OFFSET_MASK 0x000fffffL
+#define CP_IB1_OFFSET__IB1_OFFSET__SHIFT 0x00000000
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN_MASK 0x000fffffL
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN__SHIFT 0x00000000
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END_MASK 0x000fffffL
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END__SHIFT 0x00000000
+#define CP_IB2_BASE_HI__IB2_BASE_HI_MASK 0x000000ffL
+#define CP_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x00000000
+#define CP_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffcL
+#define CP_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x00000002
+#define CP_IB2_BUFSZ__IB2_BUFSZ_MASK 0x000fffffL
+#define CP_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x00000000
+#define CP_IB2_OFFSET__IB2_OFFSET_MASK 0x000fffffL
+#define CP_IB2_OFFSET__IB2_OFFSET__SHIFT 0x00000000
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN_MASK 0x000fffffL
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN__SHIFT 0x00000000
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END_MASK 0x000fffffL
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END__SHIFT 0x00000000
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED_MASK 0x00080000L
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED__SHIFT 0x00000013
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED_MASK 0x00100000L
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED__SHIFT 0x00000014
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0x0000000e
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x0000001f
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x0000001e
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x0000001d
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x00000018
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED_MASK 0x00400000L
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED__SHIFT 0x00000016
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x00000017
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x0000001b
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x0000001a
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x00000011
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING0__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING0__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_MC_PACK_DELAY_CNT__PACK_DELAY_CNT_MASK 0x0000001fL
+#define CP_MC_PACK_DELAY_CNT__PACK_DELAY_CNT__SHIFT 0x00000000
+#define CP_ME_CNTL__CE_HALT_MASK 0x01000000L
+#define CP_ME_CNTL__CE_HALT__SHIFT 0x00000018
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE_MASK 0x00000010L
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE__SHIFT 0x00000004
+#define CP_ME_CNTL__CE_STEP_MASK 0x02000000L
+#define CP_ME_CNTL__CE_STEP__SHIFT 0x00000019
+#define CP_ME_CNTL__ME_HALT_MASK 0x10000000L
+#define CP_ME_CNTL__ME_HALT__SHIFT 0x0000001c
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE_MASK 0x00000100L
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE__SHIFT 0x00000008
+#define CP_ME_CNTL__ME_STEP_MASK 0x20000000L
+#define CP_ME_CNTL__ME_STEP__SHIFT 0x0000001d
+#define CP_ME_CNTL__PFP_HALT_MASK 0x04000000L
+#define CP_ME_CNTL__PFP_HALT__SHIFT 0x0000001a
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE_MASK 0x00000040L
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE__SHIFT 0x00000006
+#define CP_ME_CNTL__PFP_STEP_MASK 0x08000000L
+#define CP_ME_CNTL__PFP_STEP__SHIFT 0x0000001b
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP_MASK 0xffffffffL
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP__SHIFT 0x00000000
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI_MASK 0x000000ffL
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI__SHIFT 0x00000000
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO_MASK 0xfffffffcL
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO__SHIFT 0x00000002
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP_MASK 0x00000003L
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP__SHIFT 0x00000000
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI_MASK 0x000000ffL
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI__SHIFT 0x00000000
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO_MASK 0xfffffffcL
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO__SHIFT 0x00000002
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP_MASK 0x00000003L
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP__SHIFT 0x00000000
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI_MASK 0xffffffffL
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI__SHIFT 0x00000000
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO_MASK 0xffffffffL
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO__SHIFT 0x00000000
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN_MASK 0x00000002L
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN__SHIFT 0x00000001
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK 0x00000001L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN__SHIFT 0x00000000
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY_MASK 0x00ff0000L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY__SHIFT 0x00000010
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY_MASK 0x0000ff00L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY__SHIFT 0x00000008
+#define CP_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000L
+#define CP_MEM_SLP_CNTL__RESERVED1__SHIFT 0x00000018
+#define CP_MEM_SLP_CNTL__RESERVED_MASK 0x000000fcL
+#define CP_MEM_SLP_CNTL__RESERVED__SHIFT 0x00000002
+#define CP_ME_PREEMPTION__ME_CNTXSW_PREEMPTION_MASK 0x00000001L
+#define CP_ME_PREEMPTION__ME_CNTXSW_PREEMPTION__SHIFT 0x00000000
+#define CP_MEQ_AVAIL__MEQ_CNT_MASK 0x000003ffL
+#define CP_MEQ_AVAIL__MEQ_CNT__SHIFT 0x00000000
+#define CP_MEQ_STAT__MEQ_RPTR_MASK 0x000003ffL
+#define CP_MEQ_STAT__MEQ_RPTR__SHIFT 0x00000000
+#define CP_MEQ_STAT__MEQ_WPTR_MASK 0x03ff0000L
+#define CP_MEQ_STAT__MEQ_WPTR__SHIFT 0x00000010
+#define CP_MEQ_THRESHOLDS__MEQ1_START_MASK 0x000000ffL
+#define CP_MEQ_THRESHOLDS__MEQ1_START__SHIFT 0x00000000
+#define CP_MEQ_THRESHOLDS__MEQ2_START_MASK 0x0000ff00L
+#define CP_MEQ_THRESHOLDS__MEQ2_START__SHIFT 0x00000008
+#define CP_ME_RAM_DATA__ME_RAM_DATA_MASK 0xffffffffL
+#define CP_ME_RAM_DATA__ME_RAM_DATA__SHIFT 0x00000000
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR_MASK 0x00000fffL
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR__SHIFT 0x00000000
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR_MASK 0x00000fffL
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO__SHIFT 0x00000000
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE_MASK 0x00000300L
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE__SHIFT 0x00000008
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define CP_PERFMON_CNTL__PERFMON_STATE_MASK 0x0000000fL
+#define CP_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE_MASK 0x000000f0L
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE__SHIFT 0x00000004
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE_MASK 0x80000000L
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE__SHIFT 0x0000001f
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP_MASK 0xffffffffL
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP__SHIFT 0x00000000
+#define CP_PFP_IB_CONTROL__IB_EN_MASK 0x00000001L
+#define CP_PFP_IB_CONTROL__IB_EN__SHIFT 0x00000000
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN_MASK 0x00000002L
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN__SHIFT 0x00000001
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN_MASK 0x00000001L
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN__SHIFT 0x00000000
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN_MASK 0x01000000L
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN__SHIFT 0x00000018
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN_MASK 0x00010000L
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN__SHIFT 0x00000010
+#define CP_PFP_LOAD_CONTROL__UCONFIG_REG_EN_MASK 0x00008000L
+#define CP_PFP_LOAD_CONTROL__UCONFIG_REG_EN__SHIFT 0x0000000f
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR_MASK 0x00000fffL
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR__SHIFT 0x00000000
+#define CP_PFP_UCODE_DATA__UCODE_DATA_MASK 0xffffffffL
+#define CP_PFP_UCODE_DATA__UCODE_DATA__SHIFT 0x00000000
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI_MASK 0xffffffffL
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI__SHIFT 0x00000000
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO_MASK 0xfffffffcL
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO__SHIFT 0x00000002
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_SWAP_MASK 0x00000003L
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_SWAP__SHIFT 0x00000000
+#define CP_PWR_CNTL__GFX_CLK_HALT_MASK 0x00000001L
+#define CP_PWR_CNTL__GFX_CLK_HALT__SHIFT 0x00000000
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START_MASK 0x0000003fL
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START__SHIFT 0x00000000
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START_MASK 0x00003f00L
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START__SHIFT 0x00000008
+#define CP_RB0_BASE_HI__RB_BASE_HI_MASK 0x000000ffL
+#define CP_RB0_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define CP_RB0_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB0_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB0_CNTL__BUF_SWAP_MASK 0x00030000L
+#define CP_RB0_CNTL__BUF_SWAP__SHIFT 0x00000010
+#define CP_RB0_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB0_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB0_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB0_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB0_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB0_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB0_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB0_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB0_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB0_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB0_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB0_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB0_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB0_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB0_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB0_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB1_BASE_HI__RB_BASE_HI_MASK 0x000000ffL
+#define CP_RB1_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define CP_RB1_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB1_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB1_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB1_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB1_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB1_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB1_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB1_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB1_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB1_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB1_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB1_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB1_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB1_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB1_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB1_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB1_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB1_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB2_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB2_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB2_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB2_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB2_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB2_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB2_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB2_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB2_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB2_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB2_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB2_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB2_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB2_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB2_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB2_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB2_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB2_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB_CNTL__BUF_SWAP_MASK 0x00030000L
+#define CP_RB_CNTL__BUF_SWAP__SHIFT 0x00000010
+#define CP_RB_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB_OFFSET__RB_OFFSET_MASK 0x000fffffL
+#define CP_RB_OFFSET__RB_OFFSET__SHIFT 0x00000000
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB_RPTR_WR__RB_RPTR_WR_MASK 0x000fffffL
+#define CP_RB_RPTR_WR__RB_RPTR_WR__SHIFT 0x00000000
+#define CP_RB_VMID__RB0_VMID_MASK 0x0000000fL
+#define CP_RB_VMID__RB0_VMID__SHIFT 0x00000000
+#define CP_RB_VMID__RB1_VMID_MASK 0x00000f00L
+#define CP_RB_VMID__RB1_VMID__SHIFT 0x00000008
+#define CP_RB_VMID__RB2_VMID_MASK 0x000f0000L
+#define CP_RB_VMID__RB2_VMID__SHIFT 0x00000010
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT_MASK 0xf0000000L
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT__SHIFT 0x0000001c
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER_MASK 0x0fffffffL
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_HI__OBSOLETE_MASK 0x000000ffL
+#define CP_RB_WPTR_POLL_ADDR_HI__OBSOLETE__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI_MASK 0x000000ffL
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_LO__OBSOLETE_MASK 0xfffffffcL
+#define CP_RB_WPTR_POLL_ADDR_LO__OBSOLETE__SHIFT 0x00000002
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO_MASK 0xfffffffcL
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO__SHIFT 0x00000002
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT_MASK 0xffff0000L
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT 0x00000010
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY_MASK 0x0000ffffL
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT 0x00000000
+#define CP_RB_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RING0_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING0_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RING1_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING1_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RING2_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING2_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RINGID__RINGID_MASK 0x00000003L
+#define CP_RINGID__RINGID__SHIFT 0x00000000
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0x000000ffL
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x00000000
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0x0000ff00L
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x00000008
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0x00ff0000L
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x00000010
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000L
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x00000018
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START_MASK 0x00ff0000L
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START__SHIFT 0x00000010
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START_MASK 0xff000000L
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START__SHIFT 0x00000018
+#define CP_ROQ1_THRESHOLDS__RB1_START_MASK 0x000000ffL
+#define CP_ROQ1_THRESHOLDS__RB1_START__SHIFT 0x00000000
+#define CP_ROQ1_THRESHOLDS__RB2_START_MASK 0x0000ff00L
+#define CP_ROQ1_THRESHOLDS__RB2_START__SHIFT 0x00000008
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2_MASK 0x000007ffL
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2__SHIFT 0x00000000
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START_MASK 0x0000ff00L
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START__SHIFT 0x00000008
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START_MASK 0x00ff0000L
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START__SHIFT 0x00000010
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START_MASK 0x000000ffL
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START__SHIFT 0x00000000
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START_MASK 0xff000000L
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START__SHIFT 0x00000018
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1_MASK 0x07ff0000L
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1__SHIFT 0x00000010
+#define CP_ROQ_AVAIL__ROQ_CNT_RING_MASK 0x000007ffL
+#define CP_ROQ_AVAIL__ROQ_CNT_RING__SHIFT 0x00000000
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1_MASK 0x000003ffL
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1__SHIFT 0x00000000
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1_MASK 0x03ff0000L
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1__SHIFT 0x00000010
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2_MASK 0x000003ffL
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2__SHIFT 0x00000000
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2_MASK 0x03ff0000L
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2__SHIFT 0x00000010
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY_MASK 0x000003ffL
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY__SHIFT 0x00000000
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY_MASK 0x03ff0000L
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY__SHIFT 0x00000010
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE__SHIFT 0x00000000
+#define CP_SCRATCH_DATA__SCRATCH_DATA_MASK 0xffffffffL
+#define CP_SCRATCH_DATA__SCRATCH_DATA__SHIFT 0x00000000
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX_MASK 0x000000ffL
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX__SHIFT 0x00000000
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER_MASK 0xffffffffL
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER__SHIFT 0x00000000
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0x000000ffL
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x00000000
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x03000000L
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x00000018
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000L
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x0000001d
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x00100000L
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x00000014
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x00010000L
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x00000010
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8L
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x00000003
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x00000003L
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x00000000
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG_MASK 0x00000400L
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG__SHIFT 0x0000000a
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG_MASK 0x00000800L
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG__SHIFT 0x0000000b
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x00002000L
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x0000000d
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM_MASK 0x00001000L
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x0000000c
+#define CP_STALLED_STAT1__ME_WAITING_ON_MC_READ_DATA_MASK 0x00004000L
+#define CP_STALLED_STAT1__ME_WAITING_ON_MC_READ_DATA__SHIFT 0x0000000e
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA_MASK 0x00008000L
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA__SHIFT 0x0000000f
+#define CP_STALLED_STAT1__MIU_WAITING_ON_RDREQ_FREE_MASK 0x00010000L
+#define CP_STALLED_STAT1__MIU_WAITING_ON_RDREQ_FREE__SHIFT 0x00000010
+#define CP_STALLED_STAT1__MIU_WAITING_ON_WRREQ_FREE_MASK 0x00020000L
+#define CP_STALLED_STAT1__MIU_WAITING_ON_WRREQ_FREE__SHIFT 0x00000011
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV_MASK 0x00000010L
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV__SHIFT 0x00000004
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV_MASK 0x00000004L
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV__SHIFT 0x00000002
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION_MASK 0x10000000L
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION__SHIFT 0x0000001c
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ_MASK 0x10000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ__SHIFT 0x0000001c
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ_MASK 0x08000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ__SHIFT 0x0000001b
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ_MASK 0x04000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ__SHIFT 0x0000001a
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE_MASK 0x00800000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE__SHIFT 0x00000017
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE_MASK 0x01000000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE__SHIFT 0x00000018
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE_MASK 0x02000000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE__SHIFT 0x00000019
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION_MASK 0x10000000L
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION__SHIFT 0x0000001c
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE_MASK 0x02000000L
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE__SHIFT 0x00000019
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE_MASK 0x04000000L
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE__SHIFT 0x0000001a
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE_MASK 0x20000000L
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE__SHIFT 0x0000001d
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM_MASK 0x08000000L
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM__SHIFT 0x0000001b
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE_MASK 0x00200000L
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE__SHIFT 0x00000015
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM_MASK 0x00400000L
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM__SHIFT 0x00000016
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME_MASK 0x00000800L
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME__SHIFT 0x0000000b
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x00010000L
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x00000010
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV_MASK 0x00001000L
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV__SHIFT 0x0000000c
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV_MASK 0x00002000L
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV__SHIFT 0x0000000d
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP_MASK 0x00004000L
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP__SHIFT 0x0000000e
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ_MASK 0x00040000L
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ__SHIFT 0x00000012
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH_MASK 0x00008000L
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH__SHIFT 0x0000000f
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER_MASK 0x00000400L
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER__SHIFT 0x0000000a
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER_MASK 0x00000200L
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER__SHIFT 0x00000009
+#define CP_STALLED_STAT2__PFP_MIU_READ_PENDING_MASK 0x00000040L
+#define CP_STALLED_STAT2__PFP_MIU_READ_PENDING__SHIFT 0x00000006
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING_MASK 0x00000020L
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING__SHIFT 0x00000005
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x00100000L
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x00000014
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM_MASK 0x00080000L
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x00000013
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV_MASK 0x00000002L
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV__SHIFT 0x00000001
+#define CP_STALLED_STAT2__PFP_TO_MIU_WRITE_NOT_RDY_TO_RCV_MASK 0x00000080L
+#define CP_STALLED_STAT2__PFP_TO_MIU_WRITE_NOT_RDY_TO_RCV__SHIFT 0x00000007
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV_MASK 0x00000004L
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV__SHIFT 0x00000002
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING_MASK 0x00000010L
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING__SHIFT 0x00000004
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA_MASK 0x00000100L
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA__SHIFT 0x00000008
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING_MASK 0x01000000L
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING__SHIFT 0x00000018
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x00020000L
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x00000011
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING_MASK 0x00800000L
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING__SHIFT 0x00000017
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN_MASK 0x80000000L
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN__SHIFT 0x0000001f
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS_MASK 0x40000000L
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS__SHIFT 0x0000001e
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV_MASK 0x00000040L
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV__SHIFT 0x00000006
+#define CP_STALLED_STAT3__CE_TO_MIU_WRITE_NOT_RDY_TO_RCV_MASK 0x00000100L
+#define CP_STALLED_STAT3__CE_TO_MIU_WRITE_NOT_RDY_TO_RCV__SHIFT 0x00000008
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY_MASK 0x00000010L
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY__SHIFT 0x00000004
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV_MASK 0x00000002L
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV__SHIFT 0x00000001
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY_MASK 0x00000008L
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY__SHIFT 0x00000003
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY_MASK 0x00000020L
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY__SHIFT 0x00000005
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV_MASK 0x00000080L
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV__SHIFT 0x00000007
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA_MASK 0x00000400L
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA__SHIFT 0x0000000a
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG_MASK 0x00000800L
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG__SHIFT 0x0000000b
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER_MASK 0x00000004L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER__SHIFT 0x00000002
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_MASK 0x00001000L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER__SHIFT 0x0000000c
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW_MASK 0x00002000L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW__SHIFT 0x0000000d
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE_MASK 0x00004000L
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE__SHIFT 0x0000000e
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS_MASK 0x00008000L
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS__SHIFT 0x0000000f
+#define CP_STAT__CE_BUSY_MASK 0x04000000L
+#define CP_STAT__CE_BUSY__SHIFT 0x0000001a
+#define CP_STAT__CP_BUSY_MASK 0x80000000L
+#define CP_STAT__CP_BUSY__SHIFT 0x0000001f
+#define CP_STAT__CPC_CPG_BUSY_MASK 0x02000000L
+#define CP_STAT__CPC_CPG_BUSY__SHIFT 0x00000019
+#define CP_STAT__DC_BUSY_MASK 0x00002000L
+#define CP_STAT__DC_BUSY__SHIFT 0x0000000d
+#define CP_STAT__DMA_BUSY_MASK 0x00400000L
+#define CP_STAT__DMA_BUSY__SHIFT 0x00000016
+#define CP_STAT__INTERRUPT_BUSY_MASK 0x00100000L
+#define CP_STAT__INTERRUPT_BUSY__SHIFT 0x00000014
+#define CP_STAT__ME_BUSY_MASK 0x00020000L
+#define CP_STAT__ME_BUSY__SHIFT 0x00000011
+#define CP_STAT__MEQ_BUSY_MASK 0x00010000L
+#define CP_STAT__MEQ_BUSY__SHIFT 0x00000010
+#define CP_STAT__MIU_RDREQ_BUSY_MASK 0x00000080L
+#define CP_STAT__MIU_RDREQ_BUSY__SHIFT 0x00000007
+#define CP_STAT__MIU_WRREQ_BUSY_MASK 0x00000100L
+#define CP_STAT__MIU_WRREQ_BUSY__SHIFT 0x00000008
+#define CP_STAT__PFP_BUSY_MASK 0x00008000L
+#define CP_STAT__PFP_BUSY__SHIFT 0x0000000f
+#define CP_STAT__QUERY_BUSY_MASK 0x00040000L
+#define CP_STAT__QUERY_BUSY__SHIFT 0x00000012
+#define CP_STAT__RCIU_BUSY_MASK 0x00800000L
+#define CP_STAT__RCIU_BUSY__SHIFT 0x00000017
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY_MASK 0x20000000L
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY__SHIFT 0x0000001d
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY_MASK 0x40000000L
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY__SHIFT 0x0000001e
+#define CP_STAT__ROQ_CE_RING_BUSY_MASK 0x10000000L
+#define CP_STAT__ROQ_CE_RING_BUSY__SHIFT 0x0000001c
+#define CP_STAT__ROQ_INDIRECT1_BUSY_MASK 0x00000400L
+#define CP_STAT__ROQ_INDIRECT1_BUSY__SHIFT 0x0000000a
+#define CP_STAT__ROQ_INDIRECT2_BUSY_MASK 0x00000800L
+#define CP_STAT__ROQ_INDIRECT2_BUSY__SHIFT 0x0000000b
+#define CP_STAT__ROQ_RING_BUSY_MASK 0x00000200L
+#define CP_STAT__ROQ_RING_BUSY__SHIFT 0x00000009
+#define CP_STAT__ROQ_STATE_BUSY_MASK 0x00001000L
+#define CP_STAT__ROQ_STATE_BUSY__SHIFT 0x0000000c
+#define CP_STAT__SCRATCH_RAM_BUSY_MASK 0x01000000L
+#define CP_STAT__SCRATCH_RAM_BUSY__SHIFT 0x00000018
+#define CP_STAT__SEMAPHORE_BUSY_MASK 0x00080000L
+#define CP_STAT__SEMAPHORE_BUSY__SHIFT 0x00000013
+#define CP_STAT__SURFACE_SYNC_BUSY_MASK 0x00200000L
+#define CP_STAT__SURFACE_SYNC_BUSY__SHIFT 0x00000015
+#define CP_STAT__TCIU_BUSY_MASK 0x08000000L
+#define CP_STAT__TCIU_BUSY__SHIFT 0x0000001b
+#define CP_ST_BASE_HI__ST_BASE_HI_MASK 0x000000ffL
+#define CP_ST_BASE_HI__ST_BASE_HI__SHIFT 0x00000000
+#define CP_ST_BASE_LO__ST_BASE_LO_MASK 0xfffffffcL
+#define CP_ST_BASE_LO__ST_BASE_LO__SHIFT 0x00000002
+#define CP_ST_BUFSZ__ST_BUFSZ_MASK 0x000fffffL
+#define CP_ST_BUFSZ__ST_BUFSZ__SHIFT 0x00000000
+#define CP_STQ_AVAIL__STQ_CNT_MASK 0x000001ffL
+#define CP_STQ_AVAIL__STQ_CNT__SHIFT 0x00000000
+#define CP_STQ_STAT__STQ_RPTR_MASK 0x000003ffL
+#define CP_STQ_STAT__STQ_RPTR__SHIFT 0x00000000
+#define CP_STQ_THRESHOLDS__STQ0_START_MASK 0x000000ffL
+#define CP_STQ_THRESHOLDS__STQ0_START__SHIFT 0x00000000
+#define CP_STQ_THRESHOLDS__STQ1_START_MASK 0x0000ff00L
+#define CP_STQ_THRESHOLDS__STQ1_START__SHIFT 0x00000008
+#define CP_STQ_THRESHOLDS__STQ2_START_MASK 0x00ff0000L
+#define CP_STQ_THRESHOLDS__STQ2_START__SHIFT 0x00000010
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI_MASK 0xffffffffL
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI__SHIFT 0x00000000
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO_MASK 0xfffffffcL
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO__SHIFT 0x00000002
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_SWAP_MASK 0x00000003L
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_SWAP__SHIFT 0x00000000
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE_MASK 0x00000001L
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE__SHIFT 0x00000000
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST_MASK 0x0000ffffL
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST__SHIFT 0x00000000
+#define CP_VMID_PREEMPT__PREEMPT_STATUS_MASK 0xffff0000L
+#define CP_VMID_PREEMPT__PREEMPT_STATUS__SHIFT 0x00000010
+#define CP_VMID_RESET__RESET_REQUEST_MASK 0x0000ffffL
+#define CP_VMID_RESET__RESET_REQUEST__SHIFT 0x00000000
+#define CP_VMID_RESET__RESET_STATUS_MASK 0xffff0000L
+#define CP_VMID_RESET__RESET_STATUS__SHIFT 0x00000010
+#define CP_VMID__VMID_MASK 0x0000000fL
+#define CP_VMID__VMID__SHIFT 0x00000000
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT_MASK 0xffffffffL
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT__SHIFT 0x00000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0x000000ffL
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x00000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x03000000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x00000018
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x0000001d
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x00100000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x00000014
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x00010000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x00000010
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8L
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x00000003
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x00000003L
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x00000000
+#define CS_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define CS_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE_MASK 0x00000001L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE__SHIFT 0x00000000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0_MASK 0x00000300L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0__SHIFT 0x00000008
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1_MASK 0x00000c00L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1__SHIFT 0x0000000a
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2_MASK 0x00003000L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2__SHIFT 0x0000000c
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3_MASK 0x0000c000L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3__SHIFT 0x0000000e
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND_MASK 0x00010000L
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND__SHIFT 0x00000010
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS__SHIFT 0x00000004
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY_MASK 0x0000000fL
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY__SHIFT 0x00000000
+#define DB_CGTT_CLK_CTRL_0__RESERVED_MASK 0x00fff000L
+#define DB_CGTT_CLK_CTRL_0__RESERVED__SHIFT 0x0000000c
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0_MASK 0x80000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1_MASK 0x40000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2_MASK 0x20000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3_MASK 0x10000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4_MASK 0x08000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5_MASK 0x04000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6_MASK 0x02000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7_MASK 0x01000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE_MASK 0x00f00000L
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE__SHIFT 0x00000014
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_MASK 0x00000002L
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS__SHIFT 0x00000001
+#define DB_COUNT_CONTROL__SAMPLE_RATE_MASK 0x00000070L
+#define DB_COUNT_CONTROL__SAMPLE_RATE__SHIFT 0x00000004
+#define DB_COUNT_CONTROL__SFAIL_ENABLE_MASK 0x000f0000L
+#define DB_COUNT_CONTROL__SFAIL_ENABLE__SHIFT 0x00000010
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE_MASK 0x0f000000L
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE__SHIFT 0x00000018
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE_MASK 0xf0000000L
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE__SHIFT 0x0000001c
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE_MASK 0x0000f000L
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE__SHIFT 0x0000000c
+#define DB_COUNT_CONTROL__ZPASS_ENABLE_MASK 0x00000f00L
+#define DB_COUNT_CONTROL__ZPASS_ENABLE__SHIFT 0x00000008
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE_MASK 0x00000001L
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE__SHIFT 0x00000000
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS_MASK 0x00001c00L
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS__SHIFT 0x0000000a
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS_MASK 0x7f000000L
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS__SHIFT 0x00000018
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS_MASK 0x000003e0L
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS__SHIFT 0x00000005
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS_MASK 0x0000001fL
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS__SHIFT 0x00000000
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING_MASK 0x00000001L
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING__SHIFT 0x00000000
+#define DB_DEBUG2__CLK_OFF_DELAY_MASK 0x00003e00L
+#define DB_DEBUG2__CLK_OFF_DELAY__SHIFT 0x00000009
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING_MASK 0x00040000L
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING__SHIFT 0x00000012
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES_MASK 0x00010000L
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES__SHIFT 0x00000010
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING_MASK 0x00020000L
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING__SHIFT 0x00000011
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ_MASK 0x00000100L
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ__SHIFT 0x00000008
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_MASK 0x00000020L
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ_MASK 0x00000080L
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ__SHIFT 0x00000007
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL__SHIFT 0x00000005
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL_MASK 0x20000000L
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL__SHIFT 0x0000001d
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL_MASK 0x00080000L
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL__SHIFT 0x00000013
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM_MASK 0x80000000L
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM__SHIFT 0x0000001f
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE_MASK 0x00000004L
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE__SHIFT 0x00000002
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE_MASK 0x00000002L
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE__SHIFT 0x00000001
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER_MASK 0x00004000L
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER__SHIFT 0x0000000e
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT_MASK 0x80000000L
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT__SHIFT 0x0000001f
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM_MASK 0x00000010L
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM__SHIFT 0x00000004
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB_MASK 0x00000008L
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB__SHIFT 0x00000003
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL_MASK 0x00000040L
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL__SHIFT 0x00000006
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM_MASK 0x10000000L
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM__SHIFT 0x0000001c
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING_MASK 0x00008000L
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING__SHIFT 0x0000000f
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION_MASK 0x00020000L
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION__SHIFT 0x00000011
+#define DB_DEBUG3__DB_EXTRA_DEBUG3_MASK 0xfc000000L
+#define DB_DEBUG3__DB_EXTRA_DEBUG3__SHIFT 0x0000001a
+#define DB_DEBUG3__DISABLE_DI_DT_STALL_MASK 0x02000000L
+#define DB_DEBUG3__DISABLE_DI_DT_STALL__SHIFT 0x00000019
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT_MASK 0x01000000L
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT__SHIFT 0x00000018
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP_MASK 0x00000010L
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP__SHIFT 0x00000004
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE_MASK 0x00200000L
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE__SHIFT 0x00000015
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS_MASK 0x00004000L
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS__SHIFT 0x0000000e
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK_MASK 0x00010000L
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK__SHIFT 0x00000010
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE_MASK 0x00008000L
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE__SHIFT 0x0000000f
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING_MASK 0x00080000L
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING__SHIFT 0x00000013
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING_MASK 0x00002000L
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING__SHIFT 0x0000000d
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX_MASK 0x08000000L
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX__SHIFT 0x0000001b
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD_MASK 0x00800000L
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD__SHIFT 0x00000017
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP_MASK 0x00000800L
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP__SHIFT 0x0000000b
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT_MASK 0x00000400L
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT__SHIFT 0x0000000a
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS_MASK 0x00000080L
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS__SHIFT 0x00000007
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE_MASK 0x00100000L
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE__SHIFT 0x00000014
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION_MASK 0x00000008L
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION__SHIFT 0x00000003
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION_MASK 0x00000100L
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION__SHIFT 0x00000008
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND_MASK 0x20000000L
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND__SHIFT 0x0000001d
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND_MASK 0x10000000L
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND__SHIFT 0x0000001c
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET_MASK 0x04000000L
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET__SHIFT 0x0000001a
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS_MASK 0x00001000L
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS__SHIFT 0x0000000c
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT_MASK 0x00400000L
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT__SHIFT 0x00000016
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB_MASK 0x00800000L
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB__SHIFT 0x00000017
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z_MASK 0x00000020L
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z__SHIFT 0x00000005
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z_MASK 0x00000040L
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z__SHIFT 0x00000006
+#define DB_DEBUG3__FORCE_DB_IS_GOOD_MASK 0x00000004L
+#define DB_DEBUG3__FORCE_DB_IS_GOOD__SHIFT 0x00000002
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE_MASK 0x00040000L
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE__SHIFT 0x00000012
+#define DB_DEBUG4__DB_EXTRA_DEBUG4_MASK 0xffffffc0L
+#define DB_DEBUG4__DB_EXTRA_DEBUG4__SHIFT 0x00000006
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL_MASK 0x00000020L
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL__SHIFT 0x00000005
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION_MASK 0x00000002L
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION__SHIFT 0x00000001
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION_MASK 0x00000001L
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION__SHIFT 0x00000000
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL_MASK 0x00000004L
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL__SHIFT 0x00000002
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE_MASK 0x00000002L
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE__SHIFT 0x00000001
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE_MASK 0x00008000L
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE__SHIFT 0x0000000f
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE_MASK 0x00004000L
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE__SHIFT 0x0000000e
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ_MASK 0x00000040L
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ__SHIFT 0x00000006
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE_MASK 0x00180000L
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE__SHIFT 0x00000013
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0_MASK 0x00000c00L
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0__SHIFT 0x0000000a
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1_MASK 0x00003000L
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1__SHIFT 0x0000000c
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE_MASK 0x00000300L
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE__SHIFT 0x00000008
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ_MASK 0x00000080L
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ__SHIFT 0x00000007
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE_MASK 0x00010000L
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE__SHIFT 0x00000010
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE_MASK 0x00000001L
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE__SHIFT 0x00000000
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES_MASK 0x0f000000L
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES__SHIFT 0x00000018
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS_MASK 0x00040000L
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS__SHIFT 0x00000012
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC_MASK 0x40000000L
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC__SHIFT 0x0000001e
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC_MASK 0x80000000L
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC__SHIFT 0x0000001f
+#define DB_DEBUG__DISABLE_SUMM_SQUADS_MASK 0x00020000L
+#define DB_DEBUG__DISABLE_SUMM_SQUADS__SHIFT 0x00000011
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION_MASK 0x00800000L
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION__SHIFT 0x00000017
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE_MASK 0x00000008L
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE__SHIFT 0x00000003
+#define DB_DEBUG__FETCH_FULL_Z_TILE_MASK 0x00000004L
+#define DB_DEBUG__FETCH_FULL_Z_TILE__SHIFT 0x00000002
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT_MASK 0x20000000L
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT__SHIFT 0x0000001d
+#define DB_DEBUG__FORCE_Z_MODE_MASK 0x00000030L
+#define DB_DEBUG__FORCE_Z_MODE__SHIFT 0x00000004
+#define DB_DEBUG__NEVER_FREE_Z_ONLY_MASK 0x00200000L
+#define DB_DEBUG__NEVER_FREE_Z_ONLY__SHIFT 0x00000015
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT_MASK 0x10000000L
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT__SHIFT 0x0000001c
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS_MASK 0x00400000L
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS__SHIFT 0x00000016
+#define DB_DEPTH_BOUNDS_MAX__MAX_MASK 0xffffffffL
+#define DB_DEPTH_BOUNDS_MAX__MAX__SHIFT 0x00000000
+#define DB_DEPTH_BOUNDS_MIN__MIN_MASK 0xffffffffL
+#define DB_DEPTH_BOUNDS_MIN__MIN__SHIFT 0x00000000
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR_MASK 0xffffffffL
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR__SHIFT 0x00000000
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE_MASK 0x00000080L
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE__SHIFT 0x00000007
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE_MASK 0x00000008L
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE__SHIFT 0x00000003
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS_MASK 0x80000000L
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS__SHIFT 0x0000001f
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL_MASK 0x40000000L
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL__SHIFT 0x0000001e
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE_MASK 0x00000001L
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE__SHIFT 0x00000000
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF_MASK 0x00700000L
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF__SHIFT 0x00000014
+#define DB_DEPTH_CONTROL__STENCILFUNC_MASK 0x00000700L
+#define DB_DEPTH_CONTROL__STENCILFUNC__SHIFT 0x00000008
+#define DB_DEPTH_CONTROL__Z_ENABLE_MASK 0x00000002L
+#define DB_DEPTH_CONTROL__Z_ENABLE__SHIFT 0x00000001
+#define DB_DEPTH_CONTROL__ZFUNC_MASK 0x00000070L
+#define DB_DEPTH_CONTROL__ZFUNC__SHIFT 0x00000004
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE_MASK 0x00000004L
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE__SHIFT 0x00000002
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK_MASK 0x0000000fL
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK__SHIFT 0x00000000
+#define DB_DEPTH_INFO__ARRAY_MODE_MASK 0x000000f0L
+#define DB_DEPTH_INFO__ARRAY_MODE__SHIFT 0x00000004
+#define DB_DEPTH_INFO__BANK_HEIGHT_MASK 0x00018000L
+#define DB_DEPTH_INFO__BANK_HEIGHT__SHIFT 0x0000000f
+#define DB_DEPTH_INFO__BANK_WIDTH_MASK 0x00006000L
+#define DB_DEPTH_INFO__BANK_WIDTH__SHIFT 0x0000000d
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT_MASK 0x00060000L
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT__SHIFT 0x00000011
+#define DB_DEPTH_INFO__NUM_BANKS_MASK 0x00180000L
+#define DB_DEPTH_INFO__NUM_BANKS__SHIFT 0x00000013
+#define DB_DEPTH_INFO__PIPE_CONFIG_MASK 0x00001f00L
+#define DB_DEPTH_INFO__PIPE_CONFIG__SHIFT 0x00000008
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX_MASK 0x003ff800L
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX__SHIFT 0x0000000b
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX_MASK 0x000007ffL
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX__SHIFT 0x00000000
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX_MASK 0x003fffffL
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX__SHIFT 0x00000000
+#define DB_DEPTH_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define DB_DEPTH_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define DB_DEPTH_VIEW__SLICE_START_MASK 0x000007ffL
+#define DB_DEPTH_VIEW__SLICE_START__SHIFT 0x00000000
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY_MASK 0x02000000L
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY__SHIFT 0x00000019
+#define DB_DEPTH_VIEW__Z_READ_ONLY_MASK 0x01000000L
+#define DB_DEPTH_VIEW__Z_READ_ONLY__SHIFT 0x00000018
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE_MASK 0x00200000L
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE__SHIFT 0x00000015
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES_MASK 0x00007000L
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES__SHIFT 0x0000000c
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION_MASK 0x08000000L
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION__SHIFT 0x0000001b
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS_MASK 0x00010000L
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS__SHIFT 0x00000010
+#define DB_EQAA__INCOHERENT_EQAA_READS_MASK 0x00020000L
+#define DB_EQAA__INCOHERENT_EQAA_READS__SHIFT 0x00000011
+#define DB_EQAA__INTERPOLATE_COMP_Z_MASK 0x00040000L
+#define DB_EQAA__INTERPOLATE_COMP_Z__SHIFT 0x00000012
+#define DB_EQAA__INTERPOLATE_SRC_Z_MASK 0x00080000L
+#define DB_EQAA__INTERPOLATE_SRC_Z__SHIFT 0x00000013
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES_MASK 0x00000700L
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES__SHIFT 0x00000008
+#define DB_EQAA__MAX_ANCHOR_SAMPLES_MASK 0x00000007L
+#define DB_EQAA__MAX_ANCHOR_SAMPLES__SHIFT 0x00000000
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT_MASK 0x07000000L
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT__SHIFT 0x00000018
+#define DB_EQAA__PS_ITER_SAMPLES_MASK 0x00000070L
+#define DB_EQAA__PS_ITER_SAMPLES__SHIFT 0x00000004
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS_MASK 0x00100000L
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS__SHIFT 0x00000014
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH_MASK 0x1fe00000L
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH__SHIFT 0x00000015
+#define DB_FIFO_DEPTH1__MCC_DEPTH_MASK 0x0000fc00L
+#define DB_FIFO_DEPTH1__MCC_DEPTH__SHIFT 0x0000000a
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH_MASK 0x0000001fL
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH__SHIFT 0x00000000
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH_MASK 0x000003e0L
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH__SHIFT 0x00000005
+#define DB_FIFO_DEPTH1__QC_DEPTH_MASK 0x001f0000L
+#define DB_FIFO_DEPTH1__QC_DEPTH__SHIFT 0x00000010
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH_MASK 0x000000ffL
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH__SHIFT 0x00000000
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH_MASK 0x00007f00L
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH__SHIFT 0x00000008
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH_MASK 0x01ff8000L
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH__SHIFT 0x0000000f
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH_MASK 0xfe000000L
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH__SHIFT 0x00000019
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH_MASK 0x0000007fL
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH__SHIFT 0x00000000
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH_MASK 0x01e00000L
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH__SHIFT 0x00000015
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH_MASK 0x00003f80L
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH__SHIFT 0x00000007
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH_MASK 0x001fc000L
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH__SHIFT 0x0000000e
+#define DB_FREE_CACHELINES__QUAD_READ_REQS_MASK 0xfe000000L
+#define DB_FREE_CACHELINES__QUAD_READ_REQS__SHIFT 0x00000019
+#define DB_HTILE_DATA_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_HTILE_DATA_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE_MASK 0x00010000L
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE__SHIFT 0x00000010
+#define DB_HTILE_SURFACE__FULL_CACHE_MASK 0x00000002L
+#define DB_HTILE_SURFACE__FULL_CACHE__SHIFT 0x00000001
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN_MASK 0x00000004L
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN__SHIFT 0x00000002
+#define DB_HTILE_SURFACE__LINEAR_MASK 0x00000001L
+#define DB_HTILE_SURFACE__LINEAR__SHIFT 0x00000000
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT_MASK 0x0000fc00L
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT__SHIFT 0x0000000a
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH_MASK 0x000003f0L
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH__SHIFT 0x00000004
+#define DB_HTILE_SURFACE__PRELOAD_MASK 0x00000008L
+#define DB_HTILE_SURFACE__PRELOAD__SHIFT 0x00000003
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PRELOAD_CONTROL__MAX_X_MASK 0x00ff0000L
+#define DB_PRELOAD_CONTROL__MAX_X__SHIFT 0x00000010
+#define DB_PRELOAD_CONTROL__MAX_Y_MASK 0xff000000L
+#define DB_PRELOAD_CONTROL__MAX_Y__SHIFT 0x00000018
+#define DB_PRELOAD_CONTROL__START_X_MASK 0x000000ffL
+#define DB_PRELOAD_CONTROL__START_X__SHIFT 0x00000000
+#define DB_PRELOAD_CONTROL__START_Y_MASK 0x0000ff00L
+#define DB_PRELOAD_CONTROL__START_Y__SHIFT 0x00000008
+#define DB_READ_DEBUG_0__BUSY_DATA0_MASK 0xffffffffL
+#define DB_READ_DEBUG_0__BUSY_DATA0__SHIFT 0x00000000
+#define DB_READ_DEBUG_1__BUSY_DATA1_MASK 0xffffffffL
+#define DB_READ_DEBUG_1__BUSY_DATA1__SHIFT 0x00000000
+#define DB_READ_DEBUG_2__BUSY_DATA2_MASK 0xffffffffL
+#define DB_READ_DEBUG_2__BUSY_DATA2__SHIFT 0x00000000
+#define DB_READ_DEBUG_3__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_3__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_4__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_4__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_5__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_5__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_6__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_6__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_7__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_7__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_8__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_8__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_9__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_9__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_A__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_A__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_B__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_B__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_C__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_C__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_D__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_D__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_E__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_E__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_F__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_F__DEBUG_DATA__SHIFT 0x00000000
+#define DB_RENDER_CONTROL__COPY_CENTROID_MASK 0x00000080L
+#define DB_RENDER_CONTROL__COPY_CENTROID__SHIFT 0x00000007
+#define DB_RENDER_CONTROL__COPY_SAMPLE_MASK 0x00000f00L
+#define DB_RENDER_CONTROL__COPY_SAMPLE__SHIFT 0x00000008
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE_MASK 0x00000001L
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE__SHIFT 0x00000000
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE_MASK 0x00000040L
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE__SHIFT 0x00000006
+#define DB_RENDER_CONTROL__DEPTH_COPY_MASK 0x00000004L
+#define DB_RENDER_CONTROL__DEPTH_COPY__SHIFT 0x00000002
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE_MASK 0x00000010L
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE__SHIFT 0x00000004
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE_MASK 0x00000002L
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE__SHIFT 0x00000001
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE_MASK 0x00000020L
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE__SHIFT 0x00000005
+#define DB_RENDER_CONTROL__STENCIL_COPY_MASK 0x00000008L
+#define DB_RENDER_CONTROL__STENCIL_COPY__SHIFT 0x00000003
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH_MASK 0x00000100L
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH__SHIFT 0x00000008
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE_MASK 0x00000400L
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE__SHIFT 0x0000000a
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION_MASK 0x00000080L
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION__SHIFT 0x00000007
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS_MASK 0x00800000L
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS__SHIFT 0x00000017
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP_MASK 0x00000200L
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP__SHIFT 0x00000009
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION_MASK 0x00000040L
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION__SHIFT 0x00000006
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION_MASK 0x00000020L
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION__SHIFT 0x00000005
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF_MASK 0x001c0000L
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF__SHIFT 0x00000012
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF_MASK 0x00038000L
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF__SHIFT 0x0000000f
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC_MASK 0x00007000L
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC__SHIFT 0x0000000c
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL_MASK 0x00000003L
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL__SHIFT 0x00000000
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN_MASK 0x0000001cL
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN__SHIFT 0x00000002
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS_MASK 0x00400000L
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS__SHIFT 0x00000016
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE_MASK 0x00200000L
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE__SHIFT 0x00000015
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE_MASK 0x00000800L
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE__SHIFT 0x0000000b
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED_MASK 0x00040000L
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED__SHIFT 0x00000012
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES_MASK 0x04000000L
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES__SHIFT 0x0000001a
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP_MASK 0x00010000L
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP__SHIFT 0x00000010
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE_MASK 0x00000100L
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE__SHIFT 0x00000008
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE_MASK 0x00000080L
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE__SHIFT 0x00000007
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL_MASK 0x00000400L
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL__SHIFT 0x0000000a
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE_MASK 0x00006000L
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE__SHIFT 0x0000000d
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0_MASK 0x0000000cL
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0__SHIFT 0x00000002
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1_MASK 0x00000030L
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1__SHIFT 0x00000004
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE_MASK 0x00000003L
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE__SHIFT 0x00000000
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT_MASK 0x00008000L
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT__SHIFT 0x0000000f
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER_MASK 0x00000040L
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER__SHIFT 0x00000006
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY_MASK 0x10000000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY__SHIFT 0x0000001c
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ_MASK 0x00001000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ__SHIFT 0x0000000c
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID_MASK 0x40000000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID__SHIFT 0x0000001e
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY_MASK 0x08000000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY__SHIFT 0x0000001b
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM_MASK 0x00180000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM__SHIFT 0x00000013
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ_MASK 0x00000800L
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ__SHIFT 0x0000000b
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID_MASK 0x20000000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID__SHIFT 0x0000001d
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE_MASK 0x00020000L
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE__SHIFT 0x00000011
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT_MASK 0x03e00000L
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT__SHIFT 0x00000015
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE_MASK 0x00000200L
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE__SHIFT 0x00000009
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION_MASK 0x80000000L
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION__SHIFT 0x0000001f
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE_MASK 0x00000800L
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE__SHIFT 0x0000000b
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT_MASK 0x00006000L
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT__SHIFT 0x0000000d
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE_MASK 0x00000080L
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE__SHIFT 0x00000007
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER_MASK 0x00001000L
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER__SHIFT 0x0000000c
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL_MASK 0x00000200L
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL__SHIFT 0x00000009
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP_MASK 0x00000400L
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP__SHIFT 0x0000000a
+#define DB_SHADER_CONTROL__KILL_ENABLE_MASK 0x00000040L
+#define DB_SHADER_CONTROL__KILL_ENABLE__SHIFT 0x00000006
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE_MASK 0x00000100L
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE__SHIFT 0x00000008
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE_MASK 0x00000004L
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE__SHIFT 0x00000002
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE_MASK 0x00000002L
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE__SHIFT 0x00000001
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE_MASK 0x00000001L
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE__SHIFT 0x00000000
+#define DB_SHADER_CONTROL__Z_ORDER_MASK 0x00000030L
+#define DB_SHADER_CONTROL__Z_ORDER__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0_MASK 0x00000007L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0__SHIFT 0x00000000
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0_MASK 0x000ff000L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0__SHIFT 0x0000000c
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0_MASK 0x00000ff0L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0_MASK 0x01000000L
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0__SHIFT 0x00000018
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1_MASK 0x00000007L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1__SHIFT 0x00000000
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1_MASK 0x000ff000L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1__SHIFT 0x0000000c
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1_MASK 0x00000ff0L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1_MASK 0x01000000L
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1__SHIFT 0x00000018
+#define DB_STENCIL_CLEAR__CLEAR_MASK 0x000000ffL
+#define DB_STENCIL_CLEAR__CLEAR__SHIFT 0x00000000
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF_MASK 0x0000f000L
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF__SHIFT 0x0000000c
+#define DB_STENCIL_CONTROL__STENCILFAIL_MASK 0x0000000fL
+#define DB_STENCIL_CONTROL__STENCILFAIL__SHIFT 0x00000000
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF_MASK 0x00f00000L
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF__SHIFT 0x00000014
+#define DB_STENCIL_CONTROL__STENCILZFAIL_MASK 0x00000f00L
+#define DB_STENCIL_CONTROL__STENCILZFAIL__SHIFT 0x00000008
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF_MASK 0x000f0000L
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF__SHIFT 0x00000010
+#define DB_STENCIL_CONTROL__STENCILZPASS_MASK 0x000000f0L
+#define DB_STENCIL_CONTROL__STENCILZPASS__SHIFT 0x00000004
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR_MASK 0x08000000L
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR__SHIFT 0x0000001b
+#define DB_STENCIL_INFO__FORMAT_MASK 0x00000001L
+#define DB_STENCIL_INFO__FORMAT__SHIFT 0x00000000
+#define DB_STENCIL_INFO__TILE_MODE_INDEX_MASK 0x00700000L
+#define DB_STENCIL_INFO__TILE_MODE_INDEX__SHIFT 0x00000014
+#define DB_STENCIL_INFO__TILE_SPLIT_MASK 0x0000e000L
+#define DB_STENCIL_INFO__TILE_SPLIT__SHIFT 0x0000000d
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE_MASK 0x20000000L
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE__SHIFT 0x0000001d
+#define DB_STENCIL_READ_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_STENCIL_READ_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF_MASK 0x0000ff00L
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF__SHIFT 0x00000008
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF_MASK 0xff000000L
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF__SHIFT 0x00000018
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF_MASK 0x000000ffL
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF__SHIFT 0x00000000
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF_MASK 0x00ff0000L
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF__SHIFT 0x00000010
+#define DB_STENCILREFMASK__STENCILMASK_MASK 0x0000ff00L
+#define DB_STENCILREFMASK__STENCILMASK__SHIFT 0x00000008
+#define DB_STENCILREFMASK__STENCILOPVAL_MASK 0xff000000L
+#define DB_STENCILREFMASK__STENCILOPVAL__SHIFT 0x00000018
+#define DB_STENCILREFMASK__STENCILTESTVAL_MASK 0x000000ffL
+#define DB_STENCILREFMASK__STENCILTESTVAL__SHIFT 0x00000000
+#define DB_STENCILREFMASK__STENCILWRITEMASK_MASK 0x00ff0000L
+#define DB_STENCILREFMASK__STENCILWRITEMASK__SHIFT 0x00000010
+#define DB_STENCIL_WRITE_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_STENCIL_WRITE_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_SUBTILE_CONTROL__MSAA16_X_MASK 0x00030000L
+#define DB_SUBTILE_CONTROL__MSAA16_X__SHIFT 0x00000010
+#define DB_SUBTILE_CONTROL__MSAA16_Y_MASK 0x000c0000L
+#define DB_SUBTILE_CONTROL__MSAA16_Y__SHIFT 0x00000012
+#define DB_SUBTILE_CONTROL__MSAA1_X_MASK 0x00000003L
+#define DB_SUBTILE_CONTROL__MSAA1_X__SHIFT 0x00000000
+#define DB_SUBTILE_CONTROL__MSAA1_Y_MASK 0x0000000cL
+#define DB_SUBTILE_CONTROL__MSAA1_Y__SHIFT 0x00000002
+#define DB_SUBTILE_CONTROL__MSAA2_X_MASK 0x00000030L
+#define DB_SUBTILE_CONTROL__MSAA2_X__SHIFT 0x00000004
+#define DB_SUBTILE_CONTROL__MSAA2_Y_MASK 0x000000c0L
+#define DB_SUBTILE_CONTROL__MSAA2_Y__SHIFT 0x00000006
+#define DB_SUBTILE_CONTROL__MSAA4_X_MASK 0x00000300L
+#define DB_SUBTILE_CONTROL__MSAA4_X__SHIFT 0x00000008
+#define DB_SUBTILE_CONTROL__MSAA4_Y_MASK 0x00000c00L
+#define DB_SUBTILE_CONTROL__MSAA4_Y__SHIFT 0x0000000a
+#define DB_SUBTILE_CONTROL__MSAA8_X_MASK 0x00003000L
+#define DB_SUBTILE_CONTROL__MSAA8_X__SHIFT 0x0000000c
+#define DB_SUBTILE_CONTROL__MSAA8_Y_MASK 0x0000c000L
+#define DB_SUBTILE_CONTROL__MSAA8_Y__SHIFT 0x0000000e
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE_MASK 0x40000000L
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE__SHIFT 0x0000001e
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD_MASK 0x80000000L
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD__SHIFT 0x0000001f
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE_MASK 0x07f00000L
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE__SHIFT 0x00000014
+#define DB_WATERMARKS__DEPTH_FLUSH_MASK 0x000007e0L
+#define DB_WATERMARKS__DEPTH_FLUSH__SHIFT 0x00000005
+#define DB_WATERMARKS__DEPTH_FREE_MASK 0x0000001fL
+#define DB_WATERMARKS__DEPTH_FREE__SHIFT 0x00000000
+#define DB_WATERMARKS__DEPTH_PENDING_FREE_MASK 0x000f8000L
+#define DB_WATERMARKS__DEPTH_PENDING_FREE__SHIFT 0x0000000f
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE_MASK 0x08000000L
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE__SHIFT 0x0000001b
+#define DB_WATERMARKS__FORCE_SUMMARIZE_MASK 0x00007800L
+#define DB_WATERMARKS__FORCE_SUMMARIZE__SHIFT 0x0000000b
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE_MASK 0x10000000L
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE__SHIFT 0x0000001c
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE_MASK 0x20000000L
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE__SHIFT 0x0000001d
+#define DB_Z_INFO__ALLOW_EXPCLEAR_MASK 0x08000000L
+#define DB_Z_INFO__ALLOW_EXPCLEAR__SHIFT 0x0000001b
+#define DB_Z_INFO__FORMAT_MASK 0x00000003L
+#define DB_Z_INFO__FORMAT__SHIFT 0x00000000
+#define DB_Z_INFO__NUM_SAMPLES_MASK 0x0000000cL
+#define DB_Z_INFO__NUM_SAMPLES__SHIFT 0x00000002
+#define DB_Z_INFO__READ_SIZE_MASK 0x10000000L
+#define DB_Z_INFO__READ_SIZE__SHIFT 0x0000001c
+#define DB_Z_INFO__TILE_MODE_INDEX_MASK 0x00700000L
+#define DB_Z_INFO__TILE_MODE_INDEX__SHIFT 0x00000014
+#define DB_Z_INFO__TILE_SPLIT_MASK 0x0000e000L
+#define DB_Z_INFO__TILE_SPLIT__SHIFT 0x0000000d
+#define DB_Z_INFO__TILE_SURFACE_ENABLE_MASK 0x20000000L
+#define DB_Z_INFO__TILE_SURFACE_ENABLE__SHIFT 0x0000001d
+#define DB_Z_INFO__ZRANGE_PRECISION_MASK 0x80000000L
+#define DB_Z_INFO__ZRANGE_PRECISION__SHIFT 0x0000001f
+#define DB_ZPASS_COUNT_HI__COUNT_HI_MASK 0x7fffffffL
+#define DB_ZPASS_COUNT_HI__COUNT_HI__SHIFT 0x00000000
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW_MASK 0xffffffffL
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW__SHIFT 0x00000000
+#define DB_Z_READ_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_Z_READ_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_Z_WRITE_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_Z_WRITE_BASE__BASE_256B__SHIFT 0x00000000
+#define DEBUG_DATA__DEBUG_DATA_MASK 0xffffffffL
+#define DEBUG_DATA__DEBUG_DATA__SHIFT 0x00000000
+#define DEBUG_INDEX__DEBUG_INDEX_MASK 0x0003ffffL
+#define DEBUG_INDEX__DEBUG_INDEX__SHIFT 0x00000000
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define GB_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define GB_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define GB_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define GB_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define GB_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define GB_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define GB_BACKEND_MAP__BACKEND_MAP_MASK 0xffffffffL
+#define GB_BACKEND_MAP__BACKEND_MAP__SHIFT 0x00000000
+#define GB_EDC_MODE__BYPASS_MASK 0x80000000L
+#define GB_EDC_MODE__BYPASS__SHIFT 0x0000001f
+#define GB_EDC_MODE__DED_MODE_MASK 0x00300000L
+#define GB_EDC_MODE__DED_MODE__SHIFT 0x00000014
+#define GB_EDC_MODE__FORCE_SEC_ON_DED_MASK 0x00010000L
+#define GB_EDC_MODE__FORCE_SEC_ON_DED__SHIFT 0x00000010
+#define GB_EDC_MODE__PROP_FED_MASK 0x20000000L
+#define GB_EDC_MODE__PROP_FED__SHIFT 0x0000001d
+#define GB_GPU_ID__GPU_ID_MASK 0x0000000fL
+#define GB_GPU_ID__GPU_ID__SHIFT 0x00000000
+#define GB_TILE_MODE0__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE0__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE0__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE0__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE0__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE0__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE0__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE0__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE10__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE10__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE10__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE10__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE10__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE10__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE10__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE10__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE11__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE11__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE11__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE11__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE11__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE11__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE11__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE11__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE12__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE12__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE12__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE12__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE12__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE12__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE12__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE12__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE13__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE13__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE13__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE13__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE13__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE13__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE13__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE13__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE14__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE14__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE14__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE14__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE14__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE14__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE14__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE14__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE15__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE15__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE15__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE15__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE15__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE15__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE15__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE15__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE16__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE16__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE16__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE16__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE16__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE16__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE16__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE16__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE17__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE17__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE17__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE17__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE17__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE17__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE17__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE17__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE18__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE18__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE18__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE18__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE18__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE18__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE18__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE18__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE19__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE19__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE19__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE19__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE19__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE19__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE19__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE19__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE1__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE1__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE1__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE1__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE1__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE1__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE1__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE1__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE20__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE20__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE20__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE20__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE20__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE20__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE20__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE20__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE21__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE21__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE21__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE21__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE21__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE21__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE21__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE21__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE22__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE22__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE22__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE22__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE22__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE22__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE22__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE22__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE23__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE23__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE23__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE23__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE23__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE23__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE23__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE23__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE24__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE24__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE24__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE24__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE24__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE24__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE24__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE24__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE25__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE25__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE25__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE25__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE25__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE25__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE25__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE25__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE26__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE26__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE26__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE26__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE26__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE26__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE26__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE26__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE27__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE27__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE27__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE27__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE27__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE27__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE27__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE27__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE28__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE28__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE28__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE28__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE28__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE28__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE28__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE28__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE29__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE29__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE29__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE29__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE29__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE29__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE29__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE29__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE2__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE2__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE2__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE2__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE2__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE2__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE2__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE2__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE30__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE30__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE30__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE30__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE30__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE30__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE30__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE30__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE31__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE31__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE31__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE31__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE31__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE31__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE31__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE31__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE3__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE3__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE3__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE3__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE3__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE3__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE3__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE3__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE4__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE4__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE4__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE4__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE4__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE4__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE4__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE4__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE5__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE5__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE5__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE5__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE5__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE5__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE5__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE5__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE6__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE6__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE6__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE6__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE6__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE6__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE6__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE6__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE7__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE7__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE7__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE7__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE7__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE7__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE7__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE7__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE8__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE8__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE8__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE8__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE8__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE8__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE8__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE8__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE9__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE9__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE9__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE9__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE9__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE9__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE9__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE9__TILE_SPLIT__SHIFT 0x0000000b
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define GC_USER_SHADER_ARRAY_CONFIG__DPFP_RATE_MASK 0x00000006L
+#define GC_USER_SHADER_ARRAY_CONFIG__DPFP_RATE__SHIFT 0x00000001
+#define GC_USER_SHADER_ARRAY_CONFIG__HALF_LDS_MASK 0x00000010L
+#define GC_USER_SHADER_ARRAY_CONFIG__HALF_LDS__SHIFT 0x00000004
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000L
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x00000010
+#define GC_USER_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE_MASK 0x00000008L
+#define GC_USER_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x00000003
+#define GDS_ATOM_BASE__BASE_MASK 0x0000ffffL
+#define GDS_ATOM_BASE__BASE__SHIFT 0x00000000
+#define GDS_ATOM_BASE__UNUSED_MASK 0xffff0000L
+#define GDS_ATOM_BASE__UNUSED__SHIFT 0x00000010
+#define GDS_ATOM_CNTL__AINC_MASK 0x0000003fL
+#define GDS_ATOM_CNTL__AINC__SHIFT 0x00000000
+#define GDS_ATOM_CNTL__DMODE_MASK 0x00000100L
+#define GDS_ATOM_CNTL__DMODE__SHIFT 0x00000008
+#define GDS_ATOM_CNTL__UNUSED1_MASK 0x000000c0L
+#define GDS_ATOM_CNTL__UNUSED1__SHIFT 0x00000006
+#define GDS_ATOM_CNTL__UNUSED2_MASK 0xfffffe00L
+#define GDS_ATOM_CNTL__UNUSED2__SHIFT 0x00000009
+#define GDS_ATOM_COMPLETE__COMPLETE_MASK 0x00000001L
+#define GDS_ATOM_COMPLETE__COMPLETE__SHIFT 0x00000000
+#define GDS_ATOM_COMPLETE__UNUSED_MASK 0xfffffffeL
+#define GDS_ATOM_COMPLETE__UNUSED__SHIFT 0x00000001
+#define GDS_ATOM_DST__DST_MASK 0xffffffffL
+#define GDS_ATOM_DST__DST__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET0__OFFSET0_MASK 0x000000ffL
+#define GDS_ATOM_OFFSET0__OFFSET0__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET0__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OFFSET0__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_OFFSET1__OFFSET1_MASK 0x000000ffL
+#define GDS_ATOM_OFFSET1__OFFSET1__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET1__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OFFSET1__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_OP__OP_MASK 0x000000ffL
+#define GDS_ATOM_OP__OP__SHIFT 0x00000000
+#define GDS_ATOM_OP__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OP__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_READ0__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ0__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ0_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ0_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ1__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ1__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ1_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ1_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SIZE__SIZE_MASK 0x0000ffffL
+#define GDS_ATOM_SIZE__SIZE__SHIFT 0x00000000
+#define GDS_ATOM_SIZE__UNUSED_MASK 0xffff0000L
+#define GDS_ATOM_SIZE__UNUSED__SHIFT 0x00000010
+#define GDS_ATOM_SRC0__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC0__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC0_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC0_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC1__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC1__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC1_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC1_U__DATA__SHIFT 0x00000000
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT_MASK 0x00000010L
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT__SHIFT 0x00000004
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT_MASK 0x00000008L
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT__SHIFT 0x00000003
+#define GDS_CNTL_STATUS__DS_RD_CLAMP_MASK 0x00000040L
+#define GDS_CNTL_STATUS__DS_RD_CLAMP__SHIFT 0x00000006
+#define GDS_CNTL_STATUS__DS_WR_CLAMP_MASK 0x00000020L
+#define GDS_CNTL_STATUS__DS_WR_CLAMP__SHIFT 0x00000005
+#define GDS_CNTL_STATUS__GDS_BUSY_MASK 0x00000001L
+#define GDS_CNTL_STATUS__GDS_BUSY__SHIFT 0x00000000
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY_MASK 0x00000002L
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY__SHIFT 0x00000001
+#define GDS_CNTL_STATUS__ORD_APP_BUSY_MASK 0x00000004L
+#define GDS_CNTL_STATUS__ORD_APP_BUSY__SHIFT 0x00000002
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL_MASK 0x00000006L
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL__SHIFT 0x00000001
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL_MASK 0x00000018L
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL__SHIFT 0x00000003
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL_MASK 0x00000060L
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL__SHIFT 0x00000005
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL_MASK 0x00000180L
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL__SHIFT 0x00000007
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX_MASK 0x0000001fL
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX__SHIFT 0x00000000
+#define GDS_DEBUG_CNTL__UNUSED_MASK 0xffffffe0L
+#define GDS_DEBUG_CNTL__UNUSED__SHIFT 0x00000005
+#define GDS_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define GDS_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define GDS_DEBUG_REG0__buff_write_MASK 0x00020000L
+#define GDS_DEBUG_REG0__buff_write__SHIFT 0x00000011
+#define GDS_DEBUG_REG0__cstate_MASK 0x0001e000L
+#define GDS_DEBUG_REG0__cstate__SHIFT 0x0000000d
+#define GDS_DEBUG_REG0__flush_request_MASK 0x00040000L
+#define GDS_DEBUG_REG0__flush_request__SHIFT 0x00000012
+#define GDS_DEBUG_REG0__last_pixel_ptr_MASK 0x00001000L
+#define GDS_DEBUG_REG0__last_pixel_ptr__SHIFT 0x0000000c
+#define GDS_DEBUG_REG0__spare1_MASK 0x00000001L
+#define GDS_DEBUG_REG0__spare1__SHIFT 0x00000000
+#define GDS_DEBUG_REG0__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG0__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG0__wbuf_fifo_empty_MASK 0x00100000L
+#define GDS_DEBUG_REG0__wbuf_fifo_empty__SHIFT 0x00000014
+#define GDS_DEBUG_REG0__wbuf_fifo_full_MASK 0x00200000L
+#define GDS_DEBUG_REG0__wbuf_fifo_full__SHIFT 0x00000015
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete_MASK 0x00080000L
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete__SHIFT 0x00000013
+#define GDS_DEBUG_REG0__write_buff_valid_MASK 0x00000040L
+#define GDS_DEBUG_REG0__write_buff_valid__SHIFT 0x00000006
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr_MASK 0x00000f80L
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr__SHIFT 0x00000007
+#define GDS_DEBUG_REG1__addr_fifo_empty_MASK 0x00200000L
+#define GDS_DEBUG_REG1__addr_fifo_empty__SHIFT 0x00000015
+#define GDS_DEBUG_REG1__addr_fifo_full_MASK 0x00100000L
+#define GDS_DEBUG_REG1__addr_fifo_full__SHIFT 0x00000014
+#define GDS_DEBUG_REG1__awaiting_data_MASK 0x00080000L
+#define GDS_DEBUG_REG1__awaiting_data__SHIFT 0x00000013
+#define GDS_DEBUG_REG1__buffer_invalid_MASK 0x00800000L
+#define GDS_DEBUG_REG1__buffer_invalid__SHIFT 0x00000017
+#define GDS_DEBUG_REG1__buffer_loaded_MASK 0x00400000L
+#define GDS_DEBUG_REG1__buffer_loaded__SHIFT 0x00000016
+#define GDS_DEBUG_REG1__data_ready_MASK 0x00040000L
+#define GDS_DEBUG_REG1__data_ready__SHIFT 0x00000012
+#define GDS_DEBUG_REG1__pixel_addr_MASK 0x0001fffcL
+#define GDS_DEBUG_REG1__pixel_addr__SHIFT 0x00000002
+#define GDS_DEBUG_REG1__pixel_vld_MASK 0x00020000L
+#define GDS_DEBUG_REG1__pixel_vld__SHIFT 0x00000011
+#define GDS_DEBUG_REG1__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG1__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG1__tag_hit_MASK 0x00000001L
+#define GDS_DEBUG_REG1__tag_hit__SHIFT 0x00000000
+#define GDS_DEBUG_REG1__tag_miss_MASK 0x00000002L
+#define GDS_DEBUG_REG1__tag_miss__SHIFT 0x00000001
+#define GDS_DEBUG_REG2__app_sel_MASK 0x000000f0L
+#define GDS_DEBUG_REG2__app_sel__SHIFT 0x00000004
+#define GDS_DEBUG_REG2__cmd_write_MASK 0x00000008L
+#define GDS_DEBUG_REG2__cmd_write__SHIFT 0x00000003
+#define GDS_DEBUG_REG2__ds_credit_avail_MASK 0x00000002L
+#define GDS_DEBUG_REG2__ds_credit_avail__SHIFT 0x00000001
+#define GDS_DEBUG_REG2__ds_full_MASK 0x00000001L
+#define GDS_DEBUG_REG2__ds_full__SHIFT 0x00000000
+#define GDS_DEBUG_REG2__ord_idx_free_MASK 0x00000004L
+#define GDS_DEBUG_REG2__ord_idx_free__SHIFT 0x00000002
+#define GDS_DEBUG_REG2__req_MASK 0x007fff00L
+#define GDS_DEBUG_REG2__req__SHIFT 0x00000008
+#define GDS_DEBUG_REG2__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG2__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG3__pipe0_busy_num_MASK 0x00007800L
+#define GDS_DEBUG_REG3__pipe0_busy_num__SHIFT 0x0000000b
+#define GDS_DEBUG_REG3__pipe_num_busy_MASK 0x000007ffL
+#define GDS_DEBUG_REG3__pipe_num_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG3__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG3__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG4__cmd_write_MASK 0x00020000L
+#define GDS_DEBUG_REG4__cmd_write__SHIFT 0x00000011
+#define GDS_DEBUG_REG4__credit_cnt_gt0_MASK 0x00010000L
+#define GDS_DEBUG_REG4__credit_cnt_gt0__SHIFT 0x00000010
+#define GDS_DEBUG_REG4__cur_reso_barrier_MASK 0x00002000L
+#define GDS_DEBUG_REG4__cur_reso_barrier__SHIFT 0x0000000d
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0_MASK 0x00008000L
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0__SHIFT 0x0000000f
+#define GDS_DEBUG_REG4__cur_reso_fed_MASK 0x00001000L
+#define GDS_DEBUG_REG4__cur_reso_fed__SHIFT 0x0000000c
+#define GDS_DEBUG_REG4__cur_reso_flag_MASK 0x00004000L
+#define GDS_DEBUG_REG4__cur_reso_flag__SHIFT 0x0000000e
+#define GDS_DEBUG_REG4__cur_reso_head_dirty_MASK 0x00000400L
+#define GDS_DEBUG_REG4__cur_reso_head_dirty__SHIFT 0x0000000a
+#define GDS_DEBUG_REG4__cur_reso_head_flag_MASK 0x00000800L
+#define GDS_DEBUG_REG4__cur_reso_head_flag__SHIFT 0x0000000b
+#define GDS_DEBUG_REG4__cur_reso_head_valid_MASK 0x00000200L
+#define GDS_DEBUG_REG4__cur_reso_head_valid__SHIFT 0x00000009
+#define GDS_DEBUG_REG4__cur_reso_MASK 0x000001f8L
+#define GDS_DEBUG_REG4__cur_reso__SHIFT 0x00000003
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd_MASK 0x00080000L
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd__SHIFT 0x00000013
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr_MASK 0x00040000L
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr__SHIFT 0x00000012
+#define GDS_DEBUG_REG4__gws_bulkfree_MASK 0x00200000L
+#define GDS_DEBUG_REG4__gws_bulkfree__SHIFT 0x00000015
+#define GDS_DEBUG_REG4__gws_busy_MASK 0x00000001L
+#define GDS_DEBUG_REG4__gws_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG4__gws_out_stall_MASK 0x00000004L
+#define GDS_DEBUG_REG4__gws_out_stall__SHIFT 0x00000002
+#define GDS_DEBUG_REG4__gws_req_MASK 0x00000002L
+#define GDS_DEBUG_REG4__gws_req__SHIFT 0x00000001
+#define GDS_DEBUG_REG4__ram_gws_re_MASK 0x00400000L
+#define GDS_DEBUG_REG4__ram_gws_re__SHIFT 0x00000016
+#define GDS_DEBUG_REG4__ram_gws_we_MASK 0x00800000L
+#define GDS_DEBUG_REG4__ram_gws_we__SHIFT 0x00000017
+#define GDS_DEBUG_REG4__ram_read_busy_MASK 0x00100000L
+#define GDS_DEBUG_REG4__ram_read_busy__SHIFT 0x00000014
+#define GDS_DEBUG_REG4__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG4__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG5__alloc_opco_error_MASK 0x00000004L
+#define GDS_DEBUG_REG5__alloc_opco_error__SHIFT 0x00000002
+#define GDS_DEBUG_REG5__dealloc_opco_error_MASK 0x00000008L
+#define GDS_DEBUG_REG5__dealloc_opco_error__SHIFT 0x00000003
+#define GDS_DEBUG_REG5__dec_error_MASK 0x00000002L
+#define GDS_DEBUG_REG5__dec_error__SHIFT 0x00000001
+#define GDS_DEBUG_REG5__error_ds_address_MASK 0x003fff00L
+#define GDS_DEBUG_REG5__error_ds_address__SHIFT 0x00000008
+#define GDS_DEBUG_REG5__spare1_MASK 0xffc00000L
+#define GDS_DEBUG_REG5__spare1__SHIFT 0x00000016
+#define GDS_DEBUG_REG5__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG5__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG5__wrap_opco_error_MASK 0x00000010L
+#define GDS_DEBUG_REG5__wrap_opco_error__SHIFT 0x00000004
+#define GDS_DEBUG_REG5__write_dis_MASK 0x00000001L
+#define GDS_DEBUG_REG5__write_dis__SHIFT 0x00000000
+#define GDS_DEBUG_REG6__counters_busy_MASK 0x001fffe0L
+#define GDS_DEBUG_REG6__counters_busy__SHIFT 0x00000005
+#define GDS_DEBUG_REG6__counters_enabled_MASK 0x0000001eL
+#define GDS_DEBUG_REG6__counters_enabled__SHIFT 0x00000001
+#define GDS_DEBUG_REG6__oa_busy_MASK 0x00000001L
+#define GDS_DEBUG_REG6__oa_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG6__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG6__spare__SHIFT 0x00000018
+#define GDS_ENHANCE__AUTO_INC_INDEX_MASK 0x00010000L
+#define GDS_ENHANCE__AUTO_INC_INDEX__SHIFT 0x00000010
+#define GDS_ENHANCE__MISC_MASK 0x0000ffffL
+#define GDS_ENHANCE__MISC__SHIFT 0x00000000
+#define GDS_ENHANCE__UNUSED_MASK 0xffff0000L
+#define GDS_ENHANCE__UNUSED__SHIFT 0x00000010
+#define GDS_GRBM_SECDED_CNT__DED_MASK 0xffff0000L
+#define GDS_GRBM_SECDED_CNT__DED__SHIFT 0x00000010
+#define GDS_GRBM_SECDED_CNT__SEC_MASK 0x0000ffffL
+#define GDS_GRBM_SECDED_CNT__SEC__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNTL__INDEX_MASK 0x0000003fL
+#define GDS_GWS_RESOURCE_CNTL__INDEX__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNTL__UNUSED_MASK 0xffffffc0L
+#define GDS_GWS_RESOURCE_CNTL__UNUSED__SHIFT 0x00000006
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT_MASK 0x0000ffffL
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNT__UNUSED_MASK 0xffff0000L
+#define GDS_GWS_RESOURCE_CNT__UNUSED__SHIFT 0x00000010
+#define GDS_GWS_RESOURCE__COUNTER_MASK 0x00001ffeL
+#define GDS_GWS_RESOURCE__COUNTER__SHIFT 0x00000001
+#define GDS_GWS_RESOURCE__DED_MASK 0x00004000L
+#define GDS_GWS_RESOURCE__DED__SHIFT 0x0000000e
+#define GDS_GWS_RESOURCE__FLAG_MASK 0x00000001L
+#define GDS_GWS_RESOURCE__FLAG__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE__HEAD_FLAG_MASK 0x10000000L
+#define GDS_GWS_RESOURCE__HEAD_FLAG__SHIFT 0x0000001c
+#define GDS_GWS_RESOURCE__HEAD_QUEUE_MASK 0x07ff0000L
+#define GDS_GWS_RESOURCE__HEAD_QUEUE__SHIFT 0x00000010
+#define GDS_GWS_RESOURCE__HEAD_VALID_MASK 0x08000000L
+#define GDS_GWS_RESOURCE__HEAD_VALID__SHIFT 0x0000001b
+#define GDS_GWS_RESOURCE__RELEASE_ALL_MASK 0x00008000L
+#define GDS_GWS_RESOURCE__RELEASE_ALL__SHIFT 0x0000000f
+#define GDS_GWS_RESOURCE_RESET__RESET_MASK 0x00000001L
+#define GDS_GWS_RESOURCE_RESET__RESET__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID_MASK 0x0000ff00L
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID__SHIFT 0x00000008
+#define GDS_GWS_RESOURCE__TYPE_MASK 0x00002000L
+#define GDS_GWS_RESOURCE__TYPE__SHIFT 0x0000000d
+#define GDS_GWS_RESOURCE__UNUSED1_MASK 0xe0000000L
+#define GDS_GWS_RESOURCE__UNUSED1__SHIFT 0x0000001d
+#define GDS_OA_DED__ME0_CS_DED_MASK 0x00000004L
+#define GDS_OA_DED__ME0_CS_DED__SHIFT 0x00000002
+#define GDS_OA_DED__ME0_GFXHP3D_PIX_DED_MASK 0x00000001L
+#define GDS_OA_DED__ME0_GFXHP3D_PIX_DED__SHIFT 0x00000000
+#define GDS_OA_DED__ME0_GFXHP3D_VTX_DED_MASK 0x00000002L
+#define GDS_OA_DED__ME0_GFXHP3D_VTX_DED__SHIFT 0x00000001
+#define GDS_OA_DED__ME1_PIPE0_DED_MASK 0x00000010L
+#define GDS_OA_DED__ME1_PIPE0_DED__SHIFT 0x00000004
+#define GDS_OA_DED__ME1_PIPE1_DED_MASK 0x00000020L
+#define GDS_OA_DED__ME1_PIPE1_DED__SHIFT 0x00000005
+#define GDS_OA_DED__ME1_PIPE2_DED_MASK 0x00000040L
+#define GDS_OA_DED__ME1_PIPE2_DED__SHIFT 0x00000006
+#define GDS_OA_DED__ME1_PIPE3_DED_MASK 0x00000080L
+#define GDS_OA_DED__ME1_PIPE3_DED__SHIFT 0x00000007
+#define GDS_OA_DED__ME2_PIPE0_DED_MASK 0x00000100L
+#define GDS_OA_DED__ME2_PIPE0_DED__SHIFT 0x00000008
+#define GDS_OA_DED__ME2_PIPE1_DED_MASK 0x00000200L
+#define GDS_OA_DED__ME2_PIPE1_DED__SHIFT 0x00000009
+#define GDS_OA_DED__ME2_PIPE2_DED_MASK 0x00000400L
+#define GDS_OA_DED__ME2_PIPE2_DED__SHIFT 0x0000000a
+#define GDS_OA_DED__ME2_PIPE3_DED_MASK 0x00000800L
+#define GDS_OA_DED__ME2_PIPE3_DED__SHIFT 0x0000000b
+#define GDS_OA_DED__UNUSED0_MASK 0x00000008L
+#define GDS_OA_DED__UNUSED0__SHIFT 0x00000003
+#define GDS_OA_DED__UNUSED1_MASK 0xfffff000L
+#define GDS_OA_DED__UNUSED1__SHIFT 0x0000000c
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_RD_ADDR__READ_ADDR_MASK 0xffffffffL
+#define GDS_RD_ADDR__READ_ADDR__SHIFT 0x00000000
+#define GDS_RD_BURST_ADDR__BURST_ADDR_MASK 0xffffffffL
+#define GDS_RD_BURST_ADDR__BURST_ADDR__SHIFT 0x00000000
+#define GDS_RD_BURST_COUNT__BURST_COUNT_MASK 0xffffffffL
+#define GDS_RD_BURST_COUNT__BURST_COUNT__SHIFT 0x00000000
+#define GDS_RD_BURST_DATA__BURST_DATA_MASK 0xffffffffL
+#define GDS_RD_BURST_DATA__BURST_DATA__SHIFT 0x00000000
+#define GDS_RD_DATA__READ_DATA_MASK 0xffffffffL
+#define GDS_RD_DATA__READ_DATA__SHIFT 0x00000000
+#define GDS_SECDED_CNT__DED_MASK 0xffff0000L
+#define GDS_SECDED_CNT__DED__SHIFT 0x00000010
+#define GDS_SECDED_CNT__SEC_MASK 0x0000ffffL
+#define GDS_SECDED_CNT__SEC__SHIFT 0x00000000
+#define GDS_WR_ADDR__WRITE_ADDR_MASK 0xffffffffL
+#define GDS_WR_ADDR__WRITE_ADDR__SHIFT 0x00000000
+#define GDS_WR_BURST_ADDR__WRITE_ADDR_MASK 0xffffffffL
+#define GDS_WR_BURST_ADDR__WRITE_ADDR__SHIFT 0x00000000
+#define GDS_WR_BURST_DATA__WRITE_DATA_MASK 0xffffffffL
+#define GDS_WR_BURST_DATA__WRITE_DATA__SHIFT 0x00000000
+#define GDS_WR_DATA__WRITE_DATA_MASK 0xffffffffL
+#define GDS_WR_DATA__WRITE_DATA__SHIFT 0x00000000
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE_MASK 0xffffffffL
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE__SHIFT 0x00000000
+#define GFX_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define GFX_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define GRBM_CAM_DATA__CAM_ADDR_MASK 0x0000ffffL
+#define GRBM_CAM_DATA__CAM_ADDR__SHIFT 0x00000000
+#define GRBM_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000L
+#define GRBM_CAM_DATA__CAM_REMAPADDR__SHIFT 0x00000010
+#define GRBM_CAM_INDEX__CAM_INDEX_MASK 0x00000007L
+#define GRBM_CAM_INDEX__CAM_INDEX__SHIFT 0x00000000
+#define GRBM_CNTL__READ_TIMEOUT_MASK 0x000000ffL
+#define GRBM_CNTL__READ_TIMEOUT__SHIFT 0x00000000
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX_MASK 0x0000003fL
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX__SHIFT 0x00000000
+#define GRBM_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define GRBM_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT_MASK 0x00000040L
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT__SHIFT 0x00000006
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE_MASK 0x00001000L
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x0000000c
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE_MASK 0x00000f00L
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE__SHIFT 0x00000008
+#define GRBM_DEBUG__IGNORE_FAO_MASK 0x00000020L
+#define GRBM_DEBUG__IGNORE_FAO__SHIFT 0x00000005
+#define GRBM_DEBUG__IGNORE_RDY_MASK 0x00000002L
+#define GRBM_DEBUG__IGNORE_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY_MASK 0x00000001L
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY__SHIFT 0x00000000
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY_MASK 0x00000002L
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS_MASK 0x00000080L
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS__SHIFT 0x00000007
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY_MASK 0x00000200L
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY__SHIFT 0x00000009
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0_MASK 0x00000040L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0__SHIFT 0x00000006
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1_MASK 0x00004000L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1__SHIFT 0x0000000e
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0_MASK 0x00000080L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0__SHIFT 0x00000007
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1_MASK 0x00008000L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1__SHIFT 0x0000000f
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0_MASK 0x00000100L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0__SHIFT 0x00000008
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1_MASK 0x00010000L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1__SHIFT 0x00000010
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0_MASK 0x00000200L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0__SHIFT 0x00000009
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1_MASK 0x00020000L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1__SHIFT 0x00000011
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0_MASK 0x00000400L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0__SHIFT 0x0000000a
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1_MASK 0x00040000L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1__SHIFT 0x00000012
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0_MASK 0x00000800L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0__SHIFT 0x0000000b
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1_MASK 0x00080000L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1__SHIFT 0x00000013
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0_MASK 0x00001000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0__SHIFT 0x0000000c
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1_MASK 0x00100000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1__SHIFT 0x00000014
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0_MASK 0x00002000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0__SHIFT 0x0000000d
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1_MASK 0x00200000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1__SHIFT 0x00000015
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY_MASK 0x00000002L
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY_MASK 0x00000008L
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY__SHIFT 0x00000003
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY_MASK 0x00000010L
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY__SHIFT 0x00000004
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK 0x40000000L
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES__SHIFT 0x0000001e
+#define GRBM_GFX_INDEX__INSTANCE_INDEX_MASK 0x000000ffL
+#define GRBM_GFX_INDEX__INSTANCE_INDEX__SHIFT 0x00000000
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK 0x80000000L
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES__SHIFT 0x0000001f
+#define GRBM_GFX_INDEX__SE_INDEX_MASK 0x00ff0000L
+#define GRBM_GFX_INDEX__SE_INDEX__SHIFT 0x00000010
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK 0x20000000L
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES__SHIFT 0x0000001d
+#define GRBM_GFX_INDEX__SH_INDEX_MASK 0x0000ff00L
+#define GRBM_GFX_INDEX__SH_INDEX__SHIFT 0x00000008
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE_MASK 0x00080000L
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE__SHIFT 0x00000013
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE_MASK 0x00000001L
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE__SHIFT 0x00000000
+#define GRBM_NOWHERE__DATA_MASK 0xffffffffL
+#define GRBM_NOWHERE__DATA__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x02000000L
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000019
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x00400000L
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x00000016
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x01000000L
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x00000018
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x00800000L
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000017
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x04000000L
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001a
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00004000L
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000e
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x08000000L
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001b
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000L
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001c
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x02000000L
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000019
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x00400000L
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x00000016
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x01000000L
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x00000018
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x00800000L
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000017
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x04000000L
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001a
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00004000L
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000e
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x08000000L
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001b
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000L
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001c
+#define GRBM_PWR_CNTL__REQ_TYPE_MASK 0x0000000fL
+#define GRBM_PWR_CNTL__REQ_TYPE__SHIFT 0x00000000
+#define GRBM_PWR_CNTL__RSP_TYPE_MASK 0x000000f0L
+#define GRBM_PWR_CNTL__RSP_TYPE__SHIFT 0x00000004
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA_MASK 0x00080000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA__SHIFT 0x00000013
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF_MASK 0x00100000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF__SHIFT 0x00000014
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF_MASK 0x00200000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF__SHIFT 0x00000015
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF_MASK 0x00400000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF__SHIFT 0x00000016
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF_MASK 0x00800000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF__SHIFT 0x00000017
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0_MASK 0x01000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0__SHIFT 0x00000018
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1_MASK 0x02000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1__SHIFT 0x00000019
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2_MASK 0x04000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2__SHIFT 0x0000001a
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3_MASK 0x08000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3__SHIFT 0x0000001b
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0_MASK 0x10000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0__SHIFT 0x0000001c
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1_MASK 0x20000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1__SHIFT 0x0000001d
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2_MASK 0x40000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2__SHIFT 0x0000001e
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3_MASK 0x80000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3__SHIFT 0x0000001f
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC_MASK 0x00040000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC__SHIFT 0x00000012
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM_MASK 0x00020000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM__SHIFT 0x00000011
+#define GRBM_READ_ERROR__READ_ADDRESS_MASK 0x0003fffcL
+#define GRBM_READ_ERROR__READ_ADDRESS__SHIFT 0x00000002
+#define GRBM_READ_ERROR__READ_ERROR_MASK 0x80000000L
+#define GRBM_READ_ERROR__READ_ERROR__SHIFT 0x0000001f
+#define GRBM_READ_ERROR__READ_MEID_MASK 0x00c00000L
+#define GRBM_READ_ERROR__READ_MEID__SHIFT 0x00000016
+#define GRBM_READ_ERROR__READ_PIPEID_MASK 0x00300000L
+#define GRBM_READ_ERROR__READ_PIPEID__SHIFT 0x00000014
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00008000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000f
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00008000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000f
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_SKEW_CNTL__SKEW_COUNT_MASK 0x00000fc0L
+#define GRBM_SKEW_CNTL__SKEW_COUNT__SHIFT 0x00000006
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD_MASK 0x0000003fL
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD__SHIFT 0x00000000
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC_MASK 0x00040000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC__SHIFT 0x00000012
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF_MASK 0x00020000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF__SHIFT 0x00000011
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG_MASK 0x00080000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG__SHIFT 0x00000013
+#define GRBM_SOFT_RESET__SOFT_RESET_CP_MASK 0x00000001L
+#define GRBM_SOFT_RESET__SOFT_RESET_CP__SHIFT 0x00000000
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK 0x00010000L
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX__SHIFT 0x00000010
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK 0x00000004L
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC__SHIFT 0x00000002
+#define GRBM_STATUS2__CPC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS2__CPC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS2__CPF_BUSY_MASK 0x10000000L
+#define GRBM_STATUS2__CPF_BUSY__SHIFT 0x0000001c
+#define GRBM_STATUS2__CPG_BUSY_MASK 0x40000000L
+#define GRBM_STATUS2__CPG_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING_MASK 0x00000010L
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING__SHIFT 0x00000004
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL_MASK 0x0000000fL
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL__SHIFT 0x00000000
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING_MASK 0x00000020L
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING__SHIFT 0x00000005
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING_MASK 0x00000040L
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING__SHIFT 0x00000006
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING_MASK 0x00000080L
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING__SHIFT 0x00000007
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING_MASK 0x00000100L
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING__SHIFT 0x00000008
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING_MASK 0x00000200L
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING__SHIFT 0x00000009
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING_MASK 0x00000400L
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING__SHIFT 0x0000000a
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING_MASK 0x00000800L
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING__SHIFT 0x0000000b
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING_MASK 0x00001000L
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING__SHIFT 0x0000000c
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING_MASK 0x00002000L
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING__SHIFT 0x0000000d
+#define GRBM_STATUS2__RLC_BUSY_MASK 0x00000100L
+#define GRBM_STATUS2__RLC_BUSY__SHIFT 0x00000008
+#define GRBM_STATUS2__RLC_RQ_PENDING_MASK 0x00000001L
+#define GRBM_STATUS2__RLC_RQ_PENDING__SHIFT 0x00000000
+#define GRBM_STATUS2__TC_BUSY_MASK 0x00000200L
+#define GRBM_STATUS2__TC_BUSY__SHIFT 0x00000009
+#define GRBM_STATUS__BCI_BUSY_MASK 0x00800000L
+#define GRBM_STATUS__BCI_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS__CB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS__CB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS__CB_CLEAN_MASK 0x00002000L
+#define GRBM_STATUS__CB_CLEAN__SHIFT 0x0000000d
+#define GRBM_STATUS__CP_BUSY_MASK 0x20000000L
+#define GRBM_STATUS__CP_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS__CP_COHERENCY_BUSY_MASK 0x10000000L
+#define GRBM_STATUS__CP_COHERENCY_BUSY__SHIFT 0x0000001c
+#define GRBM_STATUS__DB_BUSY_MASK 0x04000000L
+#define GRBM_STATUS__DB_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS__DB_CLEAN_MASK 0x00001000L
+#define GRBM_STATUS__DB_CLEAN__SHIFT 0x0000000c
+#define GRBM_STATUS__GDS_BUSY_MASK 0x00008000L
+#define GRBM_STATUS__GDS_BUSY__SHIFT 0x0000000f
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING_MASK 0x00000200L
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING__SHIFT 0x00000009
+#define GRBM_STATUS__GUI_ACTIVE_MASK 0x80000000L
+#define GRBM_STATUS__GUI_ACTIVE__SHIFT 0x0000001f
+#define GRBM_STATUS__IA_BUSY_MASK 0x00080000L
+#define GRBM_STATUS__IA_BUSY_NO_DMA_MASK 0x00040000L
+#define GRBM_STATUS__IA_BUSY_NO_DMA__SHIFT 0x00000012
+#define GRBM_STATUS__IA_BUSY__SHIFT 0x00000013
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING_MASK 0x00000080L
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING__SHIFT 0x00000007
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL_MASK 0x0000000fL
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL__SHIFT 0x00000000
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING_MASK 0x00000100L
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING__SHIFT 0x00000008
+#define GRBM_STATUS__PA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS__PA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS__SC_BUSY_MASK 0x01000000L
+#define GRBM_STATUS__SC_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE0__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE0__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE0__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE0__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE0__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE0__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE0__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE0__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE0__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE0__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE0__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE0__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE0__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE0__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE0__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE0__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE0__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE0__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE0__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE0__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE0__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE0__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE1__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE1__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE1__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE1__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE1__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE1__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE1__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE1__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE1__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE1__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE1__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE1__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE1__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE1__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE1__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE1__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE1__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE1__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE1__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE1__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE1__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE1__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE2__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE2__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE2__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE2__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE2__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE2__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE2__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE2__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE2__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE2__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE2__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE2__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE2__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE2__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE2__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE2__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE2__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE2__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE2__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE2__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE2__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE2__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE3__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE3__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE3__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE3__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE3__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE3__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE3__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE3__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE3__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE3__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE3__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE3__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE3__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE3__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE3__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE3__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE3__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE3__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE3__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE3__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE3__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE3__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS__SPI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS__SPI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS__SRBM_RQ_PENDING_MASK 0x00000020L
+#define GRBM_STATUS__SRBM_RQ_PENDING__SHIFT 0x00000005
+#define GRBM_STATUS__SX_BUSY_MASK 0x00100000L
+#define GRBM_STATUS__SX_BUSY__SHIFT 0x00000014
+#define GRBM_STATUS__TA_BUSY_MASK 0x00004000L
+#define GRBM_STATUS__TA_BUSY__SHIFT 0x0000000e
+#define GRBM_STATUS__VGT_BUSY_MASK 0x00020000L
+#define GRBM_STATUS__VGT_BUSY__SHIFT 0x00000011
+#define GRBM_STATUS__WD_BUSY_MASK 0x00200000L
+#define GRBM_STATUS__WD_BUSY_NO_DMA_MASK 0x00010000L
+#define GRBM_STATUS__WD_BUSY_NO_DMA__SHIFT 0x00000010
+#define GRBM_STATUS__WD_BUSY__SHIFT 0x00000015
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS_MASK 0x000000ffL
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS__SHIFT 0x00000000
+#define IA_CNTL_STATUS__IA_ADC_BUSY_MASK 0x00000010L
+#define IA_CNTL_STATUS__IA_ADC_BUSY__SHIFT 0x00000004
+#define IA_CNTL_STATUS__IA_BUSY_MASK 0x00000001L
+#define IA_CNTL_STATUS__IA_BUSY__SHIFT 0x00000000
+#define IA_CNTL_STATUS__IA_DMA_BUSY_MASK 0x00000002L
+#define IA_CNTL_STATUS__IA_DMA_BUSY__SHIFT 0x00000001
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY_MASK 0x00000004L
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY__SHIFT 0x00000002
+#define IA_CNTL_STATUS__IA_GRP_BUSY_MASK 0x00000008L
+#define IA_CNTL_STATUS__IA_GRP_BUSY__SHIFT 0x00000003
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX_MASK 0x0000003fL
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX__SHIFT 0x00000000
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B_MASK 0x00000040L
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B__SHIFT 0x00000006
+#define IA_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define IA_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define IA_DEBUG_REG0__core_clk_busy_MASK 0x04000000L
+#define IA_DEBUG_REG0__core_clk_busy__SHIFT 0x0000001a
+#define IA_DEBUG_REG0__dma_busy_MASK 0x00000040L
+#define IA_DEBUG_REG0__dma_busy__SHIFT 0x00000006
+#define IA_DEBUG_REG0__dma_grp_hp_valid_MASK 0x00001000L
+#define IA_DEBUG_REG0__dma_grp_hp_valid__SHIFT 0x0000000c
+#define IA_DEBUG_REG0__dma_grp_valid_MASK 0x00000400L
+#define IA_DEBUG_REG0__dma_grp_valid__SHIFT 0x0000000a
+#define IA_DEBUG_REG0__dma_req_busy_MASK 0x00000020L
+#define IA_DEBUG_REG0__dma_req_busy__SHIFT 0x00000005
+#define IA_DEBUG_REG0__grp_busy_MASK 0x00000100L
+#define IA_DEBUG_REG0__grp_busy__SHIFT 0x00000008
+#define IA_DEBUG_REG0__grp_dma_hp_read_MASK 0x00002000L
+#define IA_DEBUG_REG0__grp_dma_hp_read__SHIFT 0x0000000d
+#define IA_DEBUG_REG0__grp_dma_read_MASK 0x00000800L
+#define IA_DEBUG_REG0__grp_dma_read__SHIFT 0x0000000b
+#define IA_DEBUG_REG0__ia_busy_extended_MASK 0x00000001L
+#define IA_DEBUG_REG0__ia_busy_extended__SHIFT 0x00000000
+#define IA_DEBUG_REG0__ia_busy_MASK 0x00000004L
+#define IA_DEBUG_REG0__ia_busy__SHIFT 0x00000002
+#define IA_DEBUG_REG0__ia_nodma_busy_extended_MASK 0x00000002L
+#define IA_DEBUG_REG0__ia_nodma_busy_extended__SHIFT 0x00000001
+#define IA_DEBUG_REG0__ia_nodma_busy_MASK 0x00000008L
+#define IA_DEBUG_REG0__ia_nodma_busy__SHIFT 0x00000003
+#define IA_DEBUG_REG0__mc_xl8r_busy_MASK 0x00000080L
+#define IA_DEBUG_REG0__mc_xl8r_busy__SHIFT 0x00000007
+#define IA_DEBUG_REG0__reg_clk_busy_MASK 0x01000000L
+#define IA_DEBUG_REG0__reg_clk_busy__SHIFT 0x00000018
+#define IA_DEBUG_REG0__sclk_core_vld_MASK 0x20000000L
+#define IA_DEBUG_REG0__sclk_core_vld__SHIFT 0x0000001d
+#define IA_DEBUG_REG0__sclk_reg_vld_MASK 0x10000000L
+#define IA_DEBUG_REG0__sclk_reg_vld__SHIFT 0x0000001c
+#define IA_DEBUG_REG0__SPARE0_MASK 0x00000010L
+#define IA_DEBUG_REG0__SPARE0__SHIFT 0x00000004
+#define IA_DEBUG_REG0__SPARE1_MASK 0x00000200L
+#define IA_DEBUG_REG0__SPARE1__SHIFT 0x00000009
+#define IA_DEBUG_REG0__SPARE2_MASK 0x00ffc000L
+#define IA_DEBUG_REG0__SPARE2__SHIFT 0x0000000e
+#define IA_DEBUG_REG0__SPARE3_MASK 0x00100000L
+#define IA_DEBUG_REG0__SPARE3__SHIFT 0x00000014
+#define IA_DEBUG_REG0__SPARE4_MASK 0x08000000L
+#define IA_DEBUG_REG0__SPARE4__SHIFT 0x0000001b
+#define IA_DEBUG_REG0__SPARE5_MASK 0x40000000L
+#define IA_DEBUG_REG0__SPARE5__SHIFT 0x0000001e
+#define IA_DEBUG_REG0__SPARE6_MASK 0x80000000L
+#define IA_DEBUG_REG0__SPARE6__SHIFT 0x0000001f
+#define IA_DEBUG_REG1__current_data_valid_MASK 0x10000000L
+#define IA_DEBUG_REG1__current_data_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG1__discard_1st_chunk_MASK 0x00000100L
+#define IA_DEBUG_REG1__discard_1st_chunk__SHIFT 0x00000008
+#define IA_DEBUG_REG1__discard_2nd_chunk_MASK 0x00000200L
+#define IA_DEBUG_REG1__discard_2nd_chunk__SHIFT 0x00000009
+#define IA_DEBUG_REG1__dma_buf_type_q_MASK 0x00000060L
+#define IA_DEBUG_REG1__dma_buf_type_q__SHIFT 0x00000005
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q_MASK 0x00004000L
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG1__dma_data_fifo_full_MASK 0x00008000L
+#define IA_DEBUG_REG1__dma_data_fifo_full__SHIFT 0x0000000f
+#define IA_DEBUG_REG1__dma_grp_valid_MASK 0x04000000L
+#define IA_DEBUG_REG1__dma_grp_valid__SHIFT 0x0000001a
+#define IA_DEBUG_REG1__dma_input_fifo_empty_MASK 0x00000001L
+#define IA_DEBUG_REG1__dma_input_fifo_empty__SHIFT 0x00000000
+#define IA_DEBUG_REG1__dma_input_fifo_full_MASK 0x00000002L
+#define IA_DEBUG_REG1__dma_input_fifo_full__SHIFT 0x00000001
+#define IA_DEBUG_REG1__dma_mask_fifo_empty_MASK 0x00002000L
+#define IA_DEBUG_REG1__dma_mask_fifo_empty__SHIFT 0x0000000d
+#define IA_DEBUG_REG1__dma_mask_fifo_we_MASK 0x40000000L
+#define IA_DEBUG_REG1__dma_mask_fifo_we__SHIFT 0x0000001e
+#define IA_DEBUG_REG1__dma_rdreq_dr_q_MASK 0x00000008L
+#define IA_DEBUG_REG1__dma_rdreq_dr_q__SHIFT 0x00000003
+#define IA_DEBUG_REG1__dma_req_fifo_empty_MASK 0x00010000L
+#define IA_DEBUG_REG1__dma_req_fifo_empty__SHIFT 0x00000010
+#define IA_DEBUG_REG1__dma_req_fifo_full_MASK 0x00020000L
+#define IA_DEBUG_REG1__dma_req_fifo_full__SHIFT 0x00000011
+#define IA_DEBUG_REG1__dma_req_path_q_MASK 0x00000080L
+#define IA_DEBUG_REG1__dma_req_path_q__SHIFT 0x00000007
+#define IA_DEBUG_REG1__dma_ret_data_we_q_MASK 0x80000000L
+#define IA_DEBUG_REG1__dma_ret_data_we_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG1__dma_skid_fifo_empty_MASK 0x01000000L
+#define IA_DEBUG_REG1__dma_skid_fifo_empty__SHIFT 0x00000018
+#define IA_DEBUG_REG1__dma_skid_fifo_full_MASK 0x02000000L
+#define IA_DEBUG_REG1__dma_skid_fifo_full__SHIFT 0x00000019
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q_MASK 0x00000800L
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q__SHIFT 0x0000000b
+#define IA_DEBUG_REG1__dma_zero_indices_q_MASK 0x00000010L
+#define IA_DEBUG_REG1__dma_zero_indices_q__SHIFT 0x00000004
+#define IA_DEBUG_REG1__grp_dma_read_MASK 0x08000000L
+#define IA_DEBUG_REG1__grp_dma_read__SHIFT 0x0000001b
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op_MASK 0x00001000L
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op__SHIFT 0x0000000c
+#define IA_DEBUG_REG1__out_of_range_r2_q_MASK 0x20000000L
+#define IA_DEBUG_REG1__out_of_range_r2_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG1__second_tc_ret_data_q_MASK 0x00000400L
+#define IA_DEBUG_REG1__second_tc_ret_data_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG1__stage2_dr_MASK 0x00040000L
+#define IA_DEBUG_REG1__stage2_dr__SHIFT 0x00000012
+#define IA_DEBUG_REG1__stage2_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG1__stage2_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG1__stage3_dr_MASK 0x00100000L
+#define IA_DEBUG_REG1__stage3_dr__SHIFT 0x00000014
+#define IA_DEBUG_REG1__stage3_rtr_MASK 0x00200000L
+#define IA_DEBUG_REG1__stage3_rtr__SHIFT 0x00000015
+#define IA_DEBUG_REG1__stage4_dr_MASK 0x00400000L
+#define IA_DEBUG_REG1__stage4_dr__SHIFT 0x00000016
+#define IA_DEBUG_REG1__stage4_rtr_MASK 0x00800000L
+#define IA_DEBUG_REG1__stage4_rtr__SHIFT 0x00000017
+#define IA_DEBUG_REG1__start_new_packet_MASK 0x00000004L
+#define IA_DEBUG_REG1__start_new_packet__SHIFT 0x00000002
+#define IA_DEBUG_REG2__hp_current_data_valid_MASK 0x10000000L
+#define IA_DEBUG_REG2__hp_current_data_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG2__hp_discard_1st_chunk_MASK 0x00000100L
+#define IA_DEBUG_REG2__hp_discard_1st_chunk__SHIFT 0x00000008
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk_MASK 0x00000200L
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk__SHIFT 0x00000009
+#define IA_DEBUG_REG2__hp_dma_buf_type_q_MASK 0x00000060L
+#define IA_DEBUG_REG2__hp_dma_buf_type_q__SHIFT 0x00000005
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q_MASK 0x00004000L
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full_MASK 0x00008000L
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full__SHIFT 0x0000000f
+#define IA_DEBUG_REG2__hp_dma_grp_valid_MASK 0x04000000L
+#define IA_DEBUG_REG2__hp_dma_grp_valid__SHIFT 0x0000001a
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty_MASK 0x00000001L
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty__SHIFT 0x00000000
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full_MASK 0x00000002L
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full__SHIFT 0x00000001
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty_MASK 0x00002000L
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty__SHIFT 0x0000000d
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we_MASK 0x40000000L
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we__SHIFT 0x0000001e
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q_MASK 0x00000008L
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q__SHIFT 0x00000003
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty_MASK 0x00010000L
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty__SHIFT 0x00000010
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full_MASK 0x00020000L
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full__SHIFT 0x00000011
+#define IA_DEBUG_REG2__hp_dma_req_path_q_MASK 0x00000080L
+#define IA_DEBUG_REG2__hp_dma_req_path_q__SHIFT 0x00000007
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q_MASK 0x80000000L
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty_MASK 0x01000000L
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty__SHIFT 0x00000018
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full_MASK 0x02000000L
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full__SHIFT 0x00000019
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q_MASK 0x00000800L
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q__SHIFT 0x0000000b
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q_MASK 0x00000010L
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q__SHIFT 0x00000004
+#define IA_DEBUG_REG2__hp_grp_dma_read_MASK 0x08000000L
+#define IA_DEBUG_REG2__hp_grp_dma_read__SHIFT 0x0000001b
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op_MASK 0x00001000L
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op__SHIFT 0x0000000c
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q_MASK 0x20000000L
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q_MASK 0x00000400L
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG2__hp_stage2_dr_MASK 0x00040000L
+#define IA_DEBUG_REG2__hp_stage2_dr__SHIFT 0x00000012
+#define IA_DEBUG_REG2__hp_stage2_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG2__hp_stage2_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG2__hp_stage3_dr_MASK 0x00100000L
+#define IA_DEBUG_REG2__hp_stage3_dr__SHIFT 0x00000014
+#define IA_DEBUG_REG2__hp_stage3_rtr_MASK 0x00200000L
+#define IA_DEBUG_REG2__hp_stage3_rtr__SHIFT 0x00000015
+#define IA_DEBUG_REG2__hp_stage4_dr_MASK 0x00400000L
+#define IA_DEBUG_REG2__hp_stage4_dr__SHIFT 0x00000016
+#define IA_DEBUG_REG2__hp_stage4_rtr_MASK 0x00800000L
+#define IA_DEBUG_REG2__hp_stage4_rtr__SHIFT 0x00000017
+#define IA_DEBUG_REG2__hp_start_new_packet_MASK 0x00000004L
+#define IA_DEBUG_REG2__hp_start_new_packet__SHIFT 0x00000002
+#define IA_DEBUG_REG3__discard_1st_chunk_MASK 0x04000000L
+#define IA_DEBUG_REG3__discard_1st_chunk__SHIFT 0x0000001a
+#define IA_DEBUG_REG3__discard_2nd_chunk_MASK 0x08000000L
+#define IA_DEBUG_REG3__discard_2nd_chunk__SHIFT 0x0000001b
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out_MASK 0x00000008L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out__SHIFT 0x00000003
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out_MASK 0x00000004L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out__SHIFT 0x00000002
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read_MASK 0x00000002L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read__SHIFT 0x00000001
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out_MASK 0x00000010L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out__SHIFT 0x00000004
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid_MASK 0x00000001L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid__SHIFT 0x00000000
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out_MASK 0x00000800L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out__SHIFT 0x0000000b
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out_MASK 0x00000400L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out__SHIFT 0x0000000a
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read_MASK 0x00000200L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read__SHIFT 0x00000009
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out_MASK 0x00001000L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out__SHIFT 0x0000000c
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid_MASK 0x00000100L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid__SHIFT 0x00000008
+#define IA_DEBUG_REG3__dma_rdreq_send_out_MASK 0x00008000L
+#define IA_DEBUG_REG3__dma_rdreq_send_out__SHIFT 0x0000000f
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0_MASK 0x00000020L
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0__SHIFT 0x00000005
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q_MASK 0x00002000L
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q__SHIFT 0x0000000d
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q_MASK 0x00040000L
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q__SHIFT 0x00000012
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out_MASK 0x20000000L
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out__SHIFT 0x0000001d
+#define IA_DEBUG_REG3__last_tc_req_p1_MASK 0x10000000L
+#define IA_DEBUG_REG3__last_tc_req_p1__SHIFT 0x0000001c
+#define IA_DEBUG_REG3__mc_out_rtr_MASK 0x00004000L
+#define IA_DEBUG_REG3__mc_out_rtr__SHIFT 0x0000000e
+#define IA_DEBUG_REG3__must_service_pipe0_req_MASK 0x00000040L
+#define IA_DEBUG_REG3__must_service_pipe0_req__SHIFT 0x00000006
+#define IA_DEBUG_REG3__pair0_valid_p1_MASK 0x00100000L
+#define IA_DEBUG_REG3__pair0_valid_p1__SHIFT 0x00000014
+#define IA_DEBUG_REG3__pair1_valid_p1_MASK 0x00200000L
+#define IA_DEBUG_REG3__pair1_valid_p1__SHIFT 0x00000015
+#define IA_DEBUG_REG3__pair2_valid_p1_MASK 0x00400000L
+#define IA_DEBUG_REG3__pair2_valid_p1__SHIFT 0x00000016
+#define IA_DEBUG_REG3__pair3_valid_p1_MASK 0x00800000L
+#define IA_DEBUG_REG3__pair3_valid_p1__SHIFT 0x00000017
+#define IA_DEBUG_REG3__pipe0_dr_MASK 0x00010000L
+#define IA_DEBUG_REG3__pipe0_dr__SHIFT 0x00000010
+#define IA_DEBUG_REG3__pipe0_rtr_MASK 0x00020000L
+#define IA_DEBUG_REG3__pipe0_rtr__SHIFT 0x00000011
+#define IA_DEBUG_REG3__send_pipe1_req_MASK 0x00000080L
+#define IA_DEBUG_REG3__send_pipe1_req__SHIFT 0x00000007
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in_MASK 0x80000000L
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in__SHIFT 0x0000001f
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in_MASK 0x40000000L
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in__SHIFT 0x0000001e
+#define IA_DEBUG_REG3__tc_out_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG3__tc_out_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG3__tc_req_count_q_MASK 0x03000000L
+#define IA_DEBUG_REG3__tc_req_count_q__SHIFT 0x00000018
+#define IA_DEBUG_REG4__current_shift_is_vect1_q_MASK 0x80000000L
+#define IA_DEBUG_REG4__current_shift_is_vect1_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG4__di_event_flag_p1_q_MASK 0x00100000L
+#define IA_DEBUG_REG4__di_event_flag_p1_q__SHIFT 0x00000014
+#define IA_DEBUG_REG4__di_first_group_of_draw_q_MASK 0x20000000L
+#define IA_DEBUG_REG4__di_first_group_of_draw_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG4__di_major_mode_p1_q_MASK 0x00010000L
+#define IA_DEBUG_REG4__di_major_mode_p1_q__SHIFT 0x00000010
+#define IA_DEBUG_REG4__di_source_select_p1_q_MASK 0x0c000000L
+#define IA_DEBUG_REG4__di_source_select_p1_q__SHIFT 0x0000001a
+#define IA_DEBUG_REG4__di_state_sel_p1_q_MASK 0x00e00000L
+#define IA_DEBUG_REG4__di_state_sel_p1_q__SHIFT 0x00000015
+#define IA_DEBUG_REG4__draw_opaq_active_q_MASK 0x02000000L
+#define IA_DEBUG_REG4__draw_opaq_active_q__SHIFT 0x00000019
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q_MASK 0x01000000L
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q__SHIFT 0x00000018
+#define IA_DEBUG_REG4__grp_se0_fifo_empty_MASK 0x00000040L
+#define IA_DEBUG_REG4__grp_se0_fifo_empty__SHIFT 0x00000006
+#define IA_DEBUG_REG4__grp_se0_fifo_full_MASK 0x00000080L
+#define IA_DEBUG_REG4__grp_se0_fifo_full__SHIFT 0x00000007
+#define IA_DEBUG_REG4__gs_mode_p1_q_MASK 0x000e0000L
+#define IA_DEBUG_REG4__gs_mode_p1_q__SHIFT 0x00000011
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q_MASK 0x00008000L
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q__SHIFT 0x0000000f
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q_MASK 0x00004000L
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG4__last_shift_of_draw_MASK 0x40000000L
+#define IA_DEBUG_REG4__last_shift_of_draw__SHIFT 0x0000001e
+#define IA_DEBUG_REG4__pipe0_dr_MASK 0x00000001L
+#define IA_DEBUG_REG4__pipe0_dr__SHIFT 0x00000000
+#define IA_DEBUG_REG4__pipe0_rtr_MASK 0x00000100L
+#define IA_DEBUG_REG4__pipe0_rtr__SHIFT 0x00000008
+#define IA_DEBUG_REG4__pipe1_dr_MASK 0x00000002L
+#define IA_DEBUG_REG4__pipe1_dr__SHIFT 0x00000001
+#define IA_DEBUG_REG4__pipe1_rtr_MASK 0x00000200L
+#define IA_DEBUG_REG4__pipe1_rtr__SHIFT 0x00000009
+#define IA_DEBUG_REG4__pipe2_dr_MASK 0x00000004L
+#define IA_DEBUG_REG4__pipe2_dr__SHIFT 0x00000002
+#define IA_DEBUG_REG4__pipe2_rtr_MASK 0x00000400L
+#define IA_DEBUG_REG4__pipe2_rtr__SHIFT 0x0000000a
+#define IA_DEBUG_REG4__pipe3_dr_MASK 0x00000008L
+#define IA_DEBUG_REG4__pipe3_dr__SHIFT 0x00000003
+#define IA_DEBUG_REG4__pipe3_rtr_MASK 0x00000800L
+#define IA_DEBUG_REG4__pipe3_rtr__SHIFT 0x0000000b
+#define IA_DEBUG_REG4__pipe4_dr_MASK 0x00000010L
+#define IA_DEBUG_REG4__pipe4_dr__SHIFT 0x00000004
+#define IA_DEBUG_REG4__pipe4_rtr_MASK 0x00001000L
+#define IA_DEBUG_REG4__pipe4_rtr__SHIFT 0x0000000c
+#define IA_DEBUG_REG4__pipe5_dr_MASK 0x00000020L
+#define IA_DEBUG_REG4__pipe5_dr__SHIFT 0x00000005
+#define IA_DEBUG_REG4__pipe5_rtr_MASK 0x00002000L
+#define IA_DEBUG_REG4__pipe5_rtr__SHIFT 0x0000000d
+#define IA_DEBUG_REG4__ready_to_read_di_MASK 0x10000000L
+#define IA_DEBUG_REG4__ready_to_read_di__SHIFT 0x0000001c
+#define IA_DEBUG_REG5__di_index_counter_q_15_0_MASK 0x0000ffffL
+#define IA_DEBUG_REG5__di_index_counter_q_15_0__SHIFT 0x00000000
+#define IA_DEBUG_REG5__draw_input_fifo_empty_MASK 0x80000000L
+#define IA_DEBUG_REG5__draw_input_fifo_empty__SHIFT 0x0000001f
+#define IA_DEBUG_REG5__draw_input_fifo_full_MASK 0x40000000L
+#define IA_DEBUG_REG5__draw_input_fifo_full__SHIFT 0x0000001e
+#define IA_DEBUG_REG5__instanceid_13_0_MASK 0x3fff0000L
+#define IA_DEBUG_REG5__instanceid_13_0__SHIFT 0x00000010
+#define IA_DEBUG_REG6__after_group_partial_MASK 0x00400000L
+#define IA_DEBUG_REG6__after_group_partial__SHIFT 0x00000016
+#define IA_DEBUG_REG6__current_shift_q_MASK 0x0000000fL
+#define IA_DEBUG_REG6__current_shift_q__SHIFT 0x00000000
+#define IA_DEBUG_REG6__current_stride_pre_MASK 0x000000f0L
+#define IA_DEBUG_REG6__current_stride_pre__SHIFT 0x00000004
+#define IA_DEBUG_REG6__current_stride_q_MASK 0x00001f00L
+#define IA_DEBUG_REG6__current_stride_q__SHIFT 0x00000008
+#define IA_DEBUG_REG6__curr_prim_partial_MASK 0x00008000L
+#define IA_DEBUG_REG6__curr_prim_partial__SHIFT 0x0000000f
+#define IA_DEBUG_REG6__extract_group_MASK 0x00800000L
+#define IA_DEBUG_REG6__extract_group__SHIFT 0x00000017
+#define IA_DEBUG_REG6__first_group_partial_MASK 0x00002000L
+#define IA_DEBUG_REG6__first_group_partial__SHIFT 0x0000000d
+#define IA_DEBUG_REG6__grp_shift_debug_data_MASK 0xff000000L
+#define IA_DEBUG_REG6__grp_shift_debug_data__SHIFT 0x00000018
+#define IA_DEBUG_REG6__next_group_partial_MASK 0x00200000L
+#define IA_DEBUG_REG6__next_group_partial__SHIFT 0x00000015
+#define IA_DEBUG_REG6__next_stride_q_MASK 0x001f0000L
+#define IA_DEBUG_REG6__next_stride_q__SHIFT 0x00000010
+#define IA_DEBUG_REG6__second_group_partial_MASK 0x00004000L
+#define IA_DEBUG_REG6__second_group_partial__SHIFT 0x0000000e
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q_MASK 0x02000000L
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q__SHIFT 0x00000019
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q_MASK 0x04000000L
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q__SHIFT 0x0000001a
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q_MASK 0x08000000L
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q__SHIFT 0x0000001b
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q_MASK 0x00800000L
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q__SHIFT 0x00000017
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q_MASK 0x00700000L
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q__SHIFT 0x00000014
+#define IA_DEBUG_REG7__reset_indx_state_q_MASK 0x0000000fL
+#define IA_DEBUG_REG7__reset_indx_state_q__SHIFT 0x00000000
+#define IA_DEBUG_REG7__shift_event_flag_p2_q_MASK 0x01000000L
+#define IA_DEBUG_REG7__shift_event_flag_p2_q__SHIFT 0x00000018
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q_MASK 0x80000000L
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q_MASK 0x40000000L
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q__SHIFT 0x0000001e
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q_MASK 0x20000000L
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q_MASK 0x10000000L
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q__SHIFT 0x0000001c
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q_MASK 0x0000f000L
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q__SHIFT 0x0000000c
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q_MASK 0x000f0000L
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q__SHIFT 0x00000010
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q_MASK 0x00000f00L
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q__SHIFT 0x00000008
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q_MASK 0x000000f0L
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q__SHIFT 0x00000004
+#define IA_DEBUG_REG8__di_prim_type_p1_q_MASK 0x0000001fL
+#define IA_DEBUG_REG8__di_prim_type_p1_q__SHIFT 0x00000000
+#define IA_DEBUG_REG8__grp_components_valid_MASK 0xf0000000L
+#define IA_DEBUG_REG8__grp_components_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG8__grp_continued_MASK 0x00000800L
+#define IA_DEBUG_REG8__grp_continued__SHIFT 0x0000000b
+#define IA_DEBUG_REG8__grp_eopg_MASK 0x04000000L
+#define IA_DEBUG_REG8__grp_eopg__SHIFT 0x0000001a
+#define IA_DEBUG_REG8__grp_eop_MASK 0x02000000L
+#define IA_DEBUG_REG8__grp_eop__SHIFT 0x00000019
+#define IA_DEBUG_REG8__grp_event_flag_MASK 0x08000000L
+#define IA_DEBUG_REG8__grp_event_flag__SHIFT 0x0000001b
+#define IA_DEBUG_REG8__grp_null_primitive_MASK 0x01000000L
+#define IA_DEBUG_REG8__grp_null_primitive__SHIFT 0x00000018
+#define IA_DEBUG_REG8__grp_output_path_MASK 0x00e00000L
+#define IA_DEBUG_REG8__grp_output_path__SHIFT 0x00000015
+#define IA_DEBUG_REG8__grp_state_sel_MASK 0x00007000L
+#define IA_DEBUG_REG8__grp_state_sel__SHIFT 0x0000000c
+#define IA_DEBUG_REG8__grp_sub_prim_type_MASK 0x001f8000L
+#define IA_DEBUG_REG8__grp_sub_prim_type__SHIFT 0x0000000f
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q_MASK 0x00000100L
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q__SHIFT 0x00000008
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q_MASK 0x00000400L
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q_MASK 0x00000200L
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q__SHIFT 0x00000009
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q_MASK 0x00000080L
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q__SHIFT 0x00000007
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q_MASK 0x00000020L
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q__SHIFT 0x00000005
+#define IA_DEBUG_REG8__two_prim_input_p1_q_MASK 0x00000040L
+#define IA_DEBUG_REG8__two_prim_input_p1_q__SHIFT 0x00000006
+#define IA_DEBUG_REG9__eopg_between_prims_p6_MASK 0x00000400L
+#define IA_DEBUG_REG9__eopg_between_prims_p6__SHIFT 0x0000000a
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6_MASK 0x00000200L
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6__SHIFT 0x00000009
+#define IA_DEBUG_REG9__gfx_se_switch_p6_MASK 0x00000002L
+#define IA_DEBUG_REG9__gfx_se_switch_p6__SHIFT 0x00000001
+#define IA_DEBUG_REG9__grp_se1_fifo_empty_MASK 0x00040000L
+#define IA_DEBUG_REG9__grp_se1_fifo_empty__SHIFT 0x00000012
+#define IA_DEBUG_REG9__grp_se1_fifo_full_MASK 0x00080000L
+#define IA_DEBUG_REG9__grp_se1_fifo_full__SHIFT 0x00000013
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6_MASK 0x00000008L
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6__SHIFT 0x00000003
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6_MASK 0x00000004L
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6__SHIFT 0x00000002
+#define IA_DEBUG_REG9__prim0_eoi_p6_MASK 0x00000020L
+#define IA_DEBUG_REG9__prim0_eoi_p6__SHIFT 0x00000005
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6_MASK 0x00000080L
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6__SHIFT 0x00000007
+#define IA_DEBUG_REG9__prim1_eoi_p6_MASK 0x00000010L
+#define IA_DEBUG_REG9__prim1_eoi_p6__SHIFT 0x00000004
+#define IA_DEBUG_REG9__prim1_to_other_se_p6_MASK 0x00000100L
+#define IA_DEBUG_REG9__prim1_to_other_se_p6__SHIFT 0x00000008
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6_MASK 0x00000040L
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6__SHIFT 0x00000006
+#define IA_DEBUG_REG9__prim1_xfer_p6_MASK 0x00020000L
+#define IA_DEBUG_REG9__prim1_xfer_p6__SHIFT 0x00000011
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6_MASK 0x00000800L
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6__SHIFT 0x0000000b
+#define IA_DEBUG_REG9__prim_counter_q_MASK 0xfffc0000L
+#define IA_DEBUG_REG9__prim_counter_q__SHIFT 0x00000012
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6_MASK 0x00001000L
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6__SHIFT 0x0000000c
+#define IA_DEBUG_REG9__send_to_se1_p6_MASK 0x00000001L
+#define IA_DEBUG_REG9__send_to_se1_p6__SHIFT 0x00000000
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q_MASK 0x00010000L
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q__SHIFT 0x00000010
+#define IA_DEBUG_REG9__SPARE0_MASK 0x00004000L
+#define IA_DEBUG_REG9__SPARE0__SHIFT 0x0000000e
+#define IA_DEBUG_REG9__SPARE1_MASK 0x00008000L
+#define IA_DEBUG_REG9__SPARE1__SHIFT 0x0000000f
+#define IA_DEBUG_REG9__two_prim_output_p5_q_MASK 0x00002000L
+#define IA_DEBUG_REG9__two_prim_output_p5_q__SHIFT 0x0000000d
+#define IA_ENHANCE__MISC_MASK 0xffffffffL
+#define IA_ENHANCE__MISC__SHIFT 0x00000000
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON_MASK 0x00040000L
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON__SHIFT 0x00000012
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON_MASK 0x00010000L
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON__SHIFT 0x00000010
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE_MASK 0x0000ffffL
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE__SHIFT 0x00000000
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI_MASK 0x00080000L
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI__SHIFT 0x00000013
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP_MASK 0x00020000L
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP__SHIFT 0x00000011
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP_MASK 0x00100000L
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP__SHIFT 0x00000014
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_VMID_OVERRIDE__ENABLE_MASK 0x00000001L
+#define IA_VMID_OVERRIDE__ENABLE__SHIFT 0x00000000
+#define IA_VMID_OVERRIDE__VMID_MASK 0x0000001eL
+#define IA_VMID_OVERRIDE__VMID__SHIFT 0x00000001
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA_MASK 0x00040000L
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA__SHIFT 0x00000012
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE_MASK 0x00010000L
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE__SHIFT 0x00000010
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT_MASK 0x00100000L
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT__SHIFT 0x00000014
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF_MASK 0x00080000L
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF__SHIFT 0x00000013
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA_MASK 0x01000000L
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA__SHIFT 0x00000018
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL_MASK 0x00400000L
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL__SHIFT 0x00000016
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE_MASK 0x0000c000L
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE__SHIFT 0x0000000e
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG_MASK 0x00002000L
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG__SHIFT 0x0000000d
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA_MASK 0x00020000L
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA__SHIFT 0x00000011
+#define PA_CL_CLIP_CNTL__UCP_ENA_0_MASK 0x00000001L
+#define PA_CL_CLIP_CNTL__UCP_ENA_0__SHIFT 0x00000000
+#define PA_CL_CLIP_CNTL__UCP_ENA_1_MASK 0x00000002L
+#define PA_CL_CLIP_CNTL__UCP_ENA_1__SHIFT 0x00000001
+#define PA_CL_CLIP_CNTL__UCP_ENA_2_MASK 0x00000004L
+#define PA_CL_CLIP_CNTL__UCP_ENA_2__SHIFT 0x00000002
+#define PA_CL_CLIP_CNTL__UCP_ENA_3_MASK 0x00000008L
+#define PA_CL_CLIP_CNTL__UCP_ENA_3__SHIFT 0x00000003
+#define PA_CL_CLIP_CNTL__UCP_ENA_4_MASK 0x00000010L
+#define PA_CL_CLIP_CNTL__UCP_ENA_4__SHIFT 0x00000004
+#define PA_CL_CLIP_CNTL__UCP_ENA_5_MASK 0x00000020L
+#define PA_CL_CLIP_CNTL__UCP_ENA_5__SHIFT 0x00000005
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE_MASK 0x02000000L
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE__SHIFT 0x00000019
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR_MASK 0x00200000L
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR__SHIFT 0x00000015
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE_MASK 0x08000000L
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE__SHIFT 0x0000001b
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE_MASK 0x04000000L
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE__SHIFT 0x0000001a
+#define PA_CL_CNTL_STATUS__CL_BUSY_MASK 0x80000000L
+#define PA_CL_CNTL_STATUS__CL_BUSY__SHIFT 0x0000001f
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL_MASK 0x00000008L
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL__SHIFT 0x00000003
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK 0x00000001L
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA__SHIFT 0x00000000
+#define PA_CL_ENHANCE__ECO_SPARE0_MASK 0x80000000L
+#define PA_CL_ENHANCE__ECO_SPARE0__SHIFT 0x0000001f
+#define PA_CL_ENHANCE__ECO_SPARE1_MASK 0x40000000L
+#define PA_CL_ENHANCE__ECO_SPARE1__SHIFT 0x0000001e
+#define PA_CL_ENHANCE__ECO_SPARE2_MASK 0x20000000L
+#define PA_CL_ENHANCE__ECO_SPARE2__SHIFT 0x0000001d
+#define PA_CL_ENHANCE__ECO_SPARE3_MASK 0x10000000L
+#define PA_CL_ENHANCE__ECO_SPARE3__SHIFT 0x0000001c
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ_MASK 0x00000006L
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT 0x00000001
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE_MASK 0x00000010L
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE__SHIFT 0x00000004
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL_MASK 0x00000020L
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL__SHIFT 0x00000005
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD_MASK 0x00004000L
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD__SHIFT 0x0000000e
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN_MASK 0x00002000L
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN__SHIFT 0x0000000d
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF_MASK 0x00001000L
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF__SHIFT 0x0000000c
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN_MASK 0x00000200L
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN__SHIFT 0x00000009
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF_MASK 0x00000100L
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF__SHIFT 0x00000008
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN_MASK 0x00000800L
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN__SHIFT 0x0000000b
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF_MASK 0x00000400L
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF__SHIFT 0x0000000a
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0_MASK 0x00000008L
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0__SHIFT 0x00000003
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0_MASK 0x00100000L
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0__SHIFT 0x00000014
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD_MASK 0x00000004L
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD__SHIFT 0x00000002
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN_MASK 0x00000040L
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN__SHIFT 0x00000006
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0_MASK 0x00000080L
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0__SHIFT 0x00000007
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD_MASK 0x00000001L
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD__SHIFT 0x00000000
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN_MASK 0x00000010L
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN__SHIFT 0x00000004
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD_MASK 0x00000002L
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD__SHIFT 0x00000001
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN_MASK 0x00000020L
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN__SHIFT 0x00000005
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_SIZE__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_SIZE__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_X_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_X_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0_MASK 0x00000001L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0__SHIFT 0x00000000
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1_MASK 0x00000002L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1__SHIFT 0x00000001
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2_MASK 0x00000004L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2__SHIFT 0x00000002
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3_MASK 0x00000008L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3__SHIFT 0x00000003
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4_MASK 0x00000010L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4__SHIFT 0x00000004
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5_MASK 0x00000020L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5__SHIFT 0x00000005
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6_MASK 0x00000040L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6__SHIFT 0x00000006
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7_MASK 0x00000080L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7__SHIFT 0x00000007
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0_MASK 0x00000100L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0__SHIFT 0x00000008
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1_MASK 0x00000200L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1__SHIFT 0x00000009
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2_MASK 0x00000400L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2__SHIFT 0x0000000a
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3_MASK 0x00000800L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3__SHIFT 0x0000000b
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4_MASK 0x00001000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4__SHIFT 0x0000000c
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5_MASK 0x00002000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5__SHIFT 0x0000000d
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6_MASK 0x00004000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6__SHIFT 0x0000000e
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7_MASK 0x00008000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7__SHIFT 0x0000000f
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG_MASK 0x00020000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG__SHIFT 0x00000011
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG_MASK 0x02000000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG__SHIFT 0x00000019
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG_MASK 0x00100000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG__SHIFT 0x00000014
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE_MASK 0x00010000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE__SHIFT 0x00000010
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX_MASK 0x00040000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX__SHIFT 0x00000012
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX_MASK 0x00080000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX__SHIFT 0x00000013
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA_MASK 0x00400000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA__SHIFT 0x00000016
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA_MASK 0x00800000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA__SHIFT 0x00000017
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA_MASK 0x01000000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA__SHIFT 0x00000018
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA_MASK 0x00200000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA__SHIFT 0x00000015
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF_MASK 0x00000800L
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF__SHIFT 0x0000000b
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA_MASK 0x00000002L
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA__SHIFT 0x00000001
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA_MASK 0x00000001L
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA__SHIFT 0x00000000
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA_MASK 0x00000008L
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA__SHIFT 0x00000003
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA_MASK 0x00000004L
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA__SHIFT 0x00000002
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA_MASK 0x00000020L
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA__SHIFT 0x00000005
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA_MASK 0x00000010L
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA__SHIFT 0x00000004
+#define PA_CL_VTE_CNTL__VTX_W0_FMT_MASK 0x00000400L
+#define PA_CL_VTE_CNTL__VTX_W0_FMT__SHIFT 0x0000000a
+#define PA_CL_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100L
+#define PA_CL_VTE_CNTL__VTX_XY_FMT__SHIFT 0x00000008
+#define PA_CL_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200L
+#define PA_CL_VTE_CNTL__VTX_Z_FMT__SHIFT 0x00000009
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN_MASK 0x00000010L
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN__SHIFT 0x00000004
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE_MASK 0x03000000L
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE__SHIFT 0x00000018
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST_MASK 0x0001e000L
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST__SHIFT 0x0000000d
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES_MASK 0x00700000L
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES__SHIFT 0x00000014
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES_MASK 0x00000007L
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0_MASK 0x0000ffffL
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0_MASK 0xffff0000L
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0__SHIFT 0x00000010
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1_MASK 0x0000ffffL
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1_MASK 0xffff0000L
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0_MASK 0x0000000fL
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0__SHIFT 0x00000000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1_MASK 0x000000f0L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1__SHIFT 0x00000004
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2_MASK 0x00000f00L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2__SHIFT 0x00000008
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3_MASK 0x0000f000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3__SHIFT 0x0000000c
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4_MASK 0x000f0000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4__SHIFT 0x00000010
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5_MASK 0x00f00000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5__SHIFT 0x00000014
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6_MASK 0x0f000000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6__SHIFT 0x00000018
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7_MASK 0xf0000000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10_MASK 0x00000f00L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10__SHIFT 0x00000008
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11_MASK 0x0000f000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11__SHIFT 0x0000000c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12_MASK 0x000f0000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12__SHIFT 0x00000010
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13_MASK 0x00f00000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13__SHIFT 0x00000014
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14_MASK 0x0f000000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14__SHIFT 0x00000018
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15_MASK 0xf0000000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8_MASK 0x0000000fL
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8__SHIFT 0x00000000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9_MASK 0x000000f0L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9__SHIFT 0x00000004
+#define PA_SC_CLIPRECT_0_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_0_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_0_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_0_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_0_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_0_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_0_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_0_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_1_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_1_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_1_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_1_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_1_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_1_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_1_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_1_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_2_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_2_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_2_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_2_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_2_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_2_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_2_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_2_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_3_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_3_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_3_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_3_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_3_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_3_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_3_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_3_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE_MASK 0x0000ffffL
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE__SHIFT 0x00000000
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX_MASK 0x0000003fL
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX__SHIFT 0x00000000
+#define PA_SC_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define PA_SC_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG0__REG0_FIELD0_MASK 0x00000003L
+#define PA_SC_DEBUG_REG0__REG0_FIELD0__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG0__REG0_FIELD1_MASK 0x0000000cL
+#define PA_SC_DEBUG_REG0__REG0_FIELD1__SHIFT 0x00000002
+#define PA_SC_DEBUG_REG1__REG1_FIELD0_MASK 0x00000003L
+#define PA_SC_DEBUG_REG1__REG1_FIELD0__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG1__REG1_FIELD1_MASK 0x0000000cL
+#define PA_SC_DEBUG_REG1__REG1_FIELD1__SHIFT 0x00000002
+#define PA_SC_EDGERULE__ER_LINE_BT_MASK 0xf0000000L
+#define PA_SC_EDGERULE__ER_LINE_BT__SHIFT 0x0000001c
+#define PA_SC_EDGERULE__ER_LINE_LR_MASK 0x0003f000L
+#define PA_SC_EDGERULE__ER_LINE_LR__SHIFT 0x0000000c
+#define PA_SC_EDGERULE__ER_LINE_RL_MASK 0x00fc0000L
+#define PA_SC_EDGERULE__ER_LINE_RL__SHIFT 0x00000012
+#define PA_SC_EDGERULE__ER_LINE_TB_MASK 0x0f000000L
+#define PA_SC_EDGERULE__ER_LINE_TB__SHIFT 0x00000018
+#define PA_SC_EDGERULE__ER_POINT_MASK 0x000000f0L
+#define PA_SC_EDGERULE__ER_POINT__SHIFT 0x00000004
+#define PA_SC_EDGERULE__ER_RECT_MASK 0x00000f00L
+#define PA_SC_EDGERULE__ER_RECT__SHIFT 0x00000008
+#define PA_SC_EDGERULE__ER_TRI_MASK 0x0000000fL
+#define PA_SC_EDGERULE__ER_TRI__SHIFT 0x00000000
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX_MASK 0x00000004L
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX__SHIFT 0x00000002
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION_MASK 0x00000200L
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION__SHIFT 0x00000009
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS_MASK 0x00004000L
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS__SHIFT 0x0000000e
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING_MASK 0x00200000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING__SHIFT 0x00000015
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS_MASK 0x00800000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS__SHIFT 0x00000017
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST_MASK 0x00040000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST__SHIFT 0x00000012
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE_MASK 0x00010000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE__SHIFT 0x00000010
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING_MASK 0x00400000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING__SHIFT 0x00000016
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING_MASK 0x00080000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING__SHIFT 0x00000013
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE_MASK 0x00002000L
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE__SHIFT 0x0000000d
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE_MASK 0x000000c0L
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE__SHIFT 0x00000006
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX_MASK 0x00000002L
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX__SHIFT 0x00000001
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX_MASK 0x00000020L
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX__SHIFT 0x00000005
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM_MASK 0x00000400L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM__SHIFT 0x0000000a
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE_MASK 0x00000800L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE__SHIFT 0x0000000b
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE_MASK 0x00001000L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE__SHIFT 0x0000000c
+#define PA_SC_ENHANCE__ECO_SPARE0_MASK 0x80000000L
+#define PA_SC_ENHANCE__ECO_SPARE0__SHIFT 0x0000001f
+#define PA_SC_ENHANCE__ECO_SPARE1_MASK 0x40000000L
+#define PA_SC_ENHANCE__ECO_SPARE1__SHIFT 0x0000001e
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS_MASK 0x00000008L
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS__SHIFT 0x00000003
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID_MASK 0x00000010L
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID__SHIFT 0x00000004
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE_MASK 0x00008000L
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE__SHIFT 0x0000000f
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID_MASK 0x01000000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID__SHIFT 0x00000018
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE_MASK 0x00020000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE__SHIFT 0x00000011
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY_MASK 0x00100000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY__SHIFT 0x00000014
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER_MASK 0x00000001L
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER__SHIFT 0x00000000
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER_MASK 0x00000100L
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER__SHIFT 0x00000008
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH_MASK 0x000000ffL
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH__SHIFT 0x00000000
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE_MASK 0x00007fc0L
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT 0x00000006
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE_MASK 0xff800000L
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT 0x00000017
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE_MASK 0x0000003fL
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT 0x00000000
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE_MASK 0x001f8000L
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT 0x0000000f
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_MASK 0x0000ffffL
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT__SHIFT 0x00000000
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_MASK 0xffff0000L
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE_MASK 0x00fc0000L
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE__SHIFT 0x00000012
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE_MASK 0x00000fc0L
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE__SHIFT 0x00000006
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE_MASK 0x0000003fL
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE__SHIFT 0x00000000
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE_MASK 0x0003f000L
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE__SHIFT 0x0000000c
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA_MASK 0x00001000L
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA__SHIFT 0x0000000c
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH_MASK 0x00000200L
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH__SHIFT 0x00000009
+#define PA_SC_LINE_CNTL__LAST_PIXEL_MASK 0x00000400L
+#define PA_SC_LINE_CNTL__LAST_PIXEL__SHIFT 0x0000000a
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA_MASK 0x00000800L
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA__SHIFT 0x0000000b
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL_MASK 0x60000000L
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL__SHIFT 0x0000001d
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN_MASK 0x0000ffffL
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN__SHIFT 0x00000000
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER_MASK 0x10000000L
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER__SHIFT 0x0000001c
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT_MASK 0x00ff0000L
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT__SHIFT 0x00000010
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT_MASK 0x0000ff00L
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT__SHIFT 0x00000008
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR_MASK 0x0000000fL
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE_MASK 0x00000004L
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE__SHIFT 0x00000002
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE_MASK 0x00000001L
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR_MASK 0x00000008L
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR__SHIFT 0x00000003
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE_MASK 0x00000002L
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE__SHIFT 0x00000001
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE_MASK 0x02000000L
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE__SHIFT 0x00000019
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE_MASK 0x04000000L
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE__SHIFT 0x0000001a
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE_MASK 0x00080000L
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE__SHIFT 0x00000013
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_MASK 0x00f00000L
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE__SHIFT 0x00000014
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK_MASK 0x00008000L
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK__SHIFT 0x0000000f
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z_MASK 0x00004000L
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z__SHIFT 0x0000000e
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE_MASK 0x01000000L
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE__SHIFT 0x00000018
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE_MASK 0x00040000L
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE__SHIFT 0x00000012
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE_MASK 0x00020000L
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE__SHIFT 0x00000011
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE_MASK 0x08000000L
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE__SHIFT 0x0000001b
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK_MASK 0x70000000L
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK__SHIFT 0x0000001c
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE_MASK 0x00010000L
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE__SHIFT 0x00000010
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE_MASK 0x00000080L
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE__SHIFT 0x00000007
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE_MASK 0x00000200L
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE__SHIFT 0x00000009
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR_MASK 0x00000400L
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR__SHIFT 0x0000000a
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE_MASK 0x00000100L
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE__SHIFT 0x00000008
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST_MASK 0x00000004L
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST__SHIFT 0x00000002
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT_MASK 0x00000002L
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT__SHIFT 0x00000001
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE_MASK 0x00000008L
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE__SHIFT 0x00000003
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE_MASK 0x00000070L
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE__SHIFT 0x00000004
+#define PA_SC_MODE_CNTL_1__WALK_SIZE_MASK 0x00000001L
+#define PA_SC_MODE_CNTL_1__WALK_SIZE__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT_MASK 0x00000800L
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT__SHIFT 0x0000000b
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET_MASK 0x00001000L
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET__SHIFT 0x0000000c
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT_MASK 0x00002000L
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT__SHIFT 0x0000000d
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP_MASK 0x00000003L
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL_MASK 0x0000000cL
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL__SHIFT 0x00000002
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL_MASK 0x00000030L
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL__SHIFT 0x00000004
+#define PA_SC_RASTER_CONFIG__PKR_MAP_MASK 0x00000300L
+#define PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT 0x00000008
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2_MASK 0x0000c000L
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2__SHIFT 0x0000000e
+#define PA_SC_RASTER_CONFIG__PKR_XSEL_MASK 0x00000c00L
+#define PA_SC_RASTER_CONFIG__PKR_XSEL__SHIFT 0x0000000a
+#define PA_SC_RASTER_CONFIG__PKR_YSEL_MASK 0x00003000L
+#define PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT 0x0000000c
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0_MASK 0x00000003L
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1_MASK 0x0000000cL
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT 0x00000002
+#define PA_SC_RASTER_CONFIG__RB_XSEL2_MASK 0x00000030L
+#define PA_SC_RASTER_CONFIG__RB_XSEL2__SHIFT 0x00000004
+#define PA_SC_RASTER_CONFIG__RB_XSEL_MASK 0x00000040L
+#define PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT 0x00000006
+#define PA_SC_RASTER_CONFIG__RB_YSEL_MASK 0x00000080L
+#define PA_SC_RASTER_CONFIG__RB_YSEL__SHIFT 0x00000007
+#define PA_SC_RASTER_CONFIG__SC_MAP_MASK 0x00030000L
+#define PA_SC_RASTER_CONFIG__SC_MAP__SHIFT 0x00000010
+#define PA_SC_RASTER_CONFIG__SC_XSEL_MASK 0x000c0000L
+#define PA_SC_RASTER_CONFIG__SC_XSEL__SHIFT 0x00000012
+#define PA_SC_RASTER_CONFIG__SC_YSEL_MASK 0x00300000L
+#define PA_SC_RASTER_CONFIG__SC_YSEL__SHIFT 0x00000014
+#define PA_SC_RASTER_CONFIG__SE_MAP_MASK 0x03000000L
+#define PA_SC_RASTER_CONFIG__SE_MAP__SHIFT 0x00000018
+#define PA_SC_RASTER_CONFIG__SE_XSEL_MASK 0x0c000000L
+#define PA_SC_RASTER_CONFIG__SE_XSEL__SHIFT 0x0000001a
+#define PA_SC_RASTER_CONFIG__SE_YSEL_MASK 0x30000000L
+#define PA_SC_RASTER_CONFIG__SE_YSEL__SHIFT 0x0000001c
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X_MASK 0x0000ffffL
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y_MASK 0xffff0000L
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X_MASK 0x0000ffffL
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y_MASK 0xffff0000L
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_MASK 0x0000ffffL
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET__SHIFT 0x00000000
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_MASK 0xffff0000L
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SU_CNTL_STATUS__SU_BUSY_MASK 0x80000000L
+#define PA_SU_CNTL_STATUS__SU_BUSY__SHIFT 0x0000001f
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX_MASK 0x0000001fL
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX__SHIFT 0x00000000
+#define PA_SU_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define PA_SU_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X_MASK 0x000001ffL
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X__SHIFT 0x00000000
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y_MASK 0x01ff0000L
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y__SHIFT 0x00000010
+#define PA_SU_LINE_CNTL__WIDTH_MASK 0x0000ffffL
+#define PA_SU_LINE_CNTL__WIDTH__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST_MASK 0x00000010L
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST__SHIFT 0x00000004
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH_MASK 0x00000004L
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH__SHIFT 0x00000002
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM_MASK 0x00000008L
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM__SHIFT 0x00000003
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET_MASK 0x00000003L
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE_MASK 0xffffffffL
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE_MASK 0x00ffffffL
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_POINT_MINMAX__MAX_SIZE_MASK 0xffff0000L
+#define PA_SU_POINT_MINMAX__MAX_SIZE__SHIFT 0x00000010
+#define PA_SU_POINT_MINMAX__MIN_SIZE_MASK 0x0000ffffL
+#define PA_SU_POINT_MINMAX__MIN_SIZE__SHIFT 0x00000000
+#define PA_SU_POINT_SIZE__HEIGHT_MASK 0x0000ffffL
+#define PA_SU_POINT_SIZE__HEIGHT__SHIFT 0x00000000
+#define PA_SU_POINT_SIZE__WIDTH_MASK 0xffff0000L
+#define PA_SU_POINT_SIZE__WIDTH__SHIFT 0x00000010
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT_MASK 0x00000100L
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT__SHIFT 0x00000008
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS_MASK 0x000000ffL
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE__SHIFT 0x00000000
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA_MASK 0x00000020L
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA__SHIFT 0x00000005
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE_MASK 0x00000002L
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE__SHIFT 0x00000001
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA_MASK 0x00000040L
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA__SHIFT 0x00000006
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE_MASK 0x00000004L
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE__SHIFT 0x00000002
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT_MASK 0x0000ff00L
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT__SHIFT 0x00000008
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA_MASK 0x00000080L
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA__SHIFT 0x00000007
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE_MASK 0x00000008L
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE__SHIFT 0x00000003
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA_MASK 0x00000010L
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA__SHIFT 0x00000004
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE_MASK 0x00000001L
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE__SHIFT 0x00000000
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION_MASK 0x40000000L
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION__SHIFT 0x0000001e
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION_MASK 0x80000000L
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION__SHIFT 0x0000001f
+#define PA_SU_SC_MODE_CNTL__CULL_BACK_MASK 0x00000002L
+#define PA_SU_SC_MODE_CNTL__CULL_BACK__SHIFT 0x00000001
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT_MASK 0x00000001L
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT__SHIFT 0x00000000
+#define PA_SU_SC_MODE_CNTL__FACE_MASK 0x00000004L
+#define PA_SU_SC_MODE_CNTL__FACE__SHIFT 0x00000002
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA_MASK 0x00200000L
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA__SHIFT 0x00000015
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS_MASK 0x00100000L
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS__SHIFT 0x00000014
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE_MASK 0x00000700L
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE__SHIFT 0x00000008
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE_MASK 0x000000e0L
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE__SHIFT 0x00000005
+#define PA_SU_SC_MODE_CNTL__POLY_MODE_MASK 0x00000018L
+#define PA_SU_SC_MODE_CNTL__POLY_MODE__SHIFT 0x00000003
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE_MASK 0x00001000L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE__SHIFT 0x0000000c
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE_MASK 0x00000800L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE__SHIFT 0x0000000b
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE_MASK 0x00002000L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE__SHIFT 0x0000000d
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST_MASK 0x00080000L
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST__SHIFT 0x00000013
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE_MASK 0x00010000L
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE__SHIFT 0x00000010
+#define PA_SU_VTX_CNTL__PIX_CENTER_MASK 0x00000001L
+#define PA_SU_VTX_CNTL__PIX_CENTER__SHIFT 0x00000000
+#define PA_SU_VTX_CNTL__QUANT_MODE_MASK 0x00000038L
+#define PA_SU_VTX_CNTL__QUANT_MODE__SHIFT 0x00000003
+#define PA_SU_VTX_CNTL__ROUND_MODE_MASK 0x00000006L
+#define PA_SU_VTX_CNTL__ROUND_MODE__SHIFT 0x00000001
+#define RAS_BCI_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_BCI_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_BCI_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_BCI_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_CB_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_CB_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_DB_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_DB_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_IA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_IA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_IA_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_IA_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_PA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_PA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE2__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE2__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE3__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE3__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE4__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE4__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE5__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE5__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE6__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE6__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE7__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE7__SIGNATURE__SHIFT 0x00000000
+#define RAS_SIGNATURE_CONTROL__ENABLE_MASK 0x00000001L
+#define RAS_SIGNATURE_CONTROL__ENABLE__SHIFT 0x00000000
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK_MASK 0xffffffffL
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK__SHIFT 0x00000000
+#define RAS_SPI_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SPI_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SPI_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SPI_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SQ_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SQ_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE2__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE2__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE3__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE3__SIGNATURE__SHIFT 0x00000000
+#define RAS_TA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_TA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_TD_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_TD_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_VGT_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_VGT_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN_MASK 0x00000002L
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN__SHIFT 0x00000001
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN_MASK 0x00000001L
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN__SHIFT 0x00000000
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN_MASK 0x00000004L
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN__SHIFT 0x00000002
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK 0x0007fff8L
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT 0x00000003
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD_MASK 0xfff80000L
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD__SHIFT 0x00000013
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE_MASK 0x00000001L
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE__SHIFT 0x00000000
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED_MASK 0xfffffffeL
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED__SHIFT 0x00000001
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER_MASK 0x08000000L
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER__SHIFT 0x0000001b
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK 0x00000001L
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN__SHIFT 0x00000000
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD_MASK 0x0000ff00L
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT 0x00000008
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL_MASK 0x10000000L
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL__SHIFT 0x0000001c
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK 0x00000002L
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN__SHIFT 0x00000001
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY_MASK 0x000000fcL
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT 0x00000002
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE_MASK 0x60000000L
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE__SHIFT 0x0000001d
+#define RLC_CGCG_CGLS_CTRL__SPARE_MASK 0x80000000L
+#define RLC_CGCG_CGLS_CTRL__SPARE__SHIFT 0x0000001f
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT_MASK 0x0000000fL
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT__SHIFT 0x00000000
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT_MASK 0x000000f0L
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT__SHIFT 0x00000004
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT_MASK 0x0fff0000L
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT__SHIFT 0x00000010
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT_MASK 0xf0000000L
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT__SHIFT 0x0000001c
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT_MASK 0x00000f00L
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT__SHIFT 0x00000008
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT_MASK 0x0000f000L
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT__SHIFT 0x0000000c
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE_MASK 0xffffffffL
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE__SHIFT 0x00000000
+#define RLC_CNTL__FORCE_RETRY_MASK 0x00000002L
+#define RLC_CNTL__FORCE_RETRY__SHIFT 0x00000001
+#define RLC_CNTL__READ_CACHE_DISABLE_MASK 0x00000004L
+#define RLC_CNTL__READ_CACHE_DISABLE__SHIFT 0x00000002
+#define RLC_CNTL__RESERVED_MASK 0xffffff00L
+#define RLC_CNTL__RESERVED__SHIFT 0x00000008
+#define RLC_CNTL__RLC_ENABLE_F32_MASK 0x00000001L
+#define RLC_CNTL__RLC_ENABLE_F32__SHIFT 0x00000000
+#define RLC_CNTL__RLC_STEP_F32_MASK 0x00000008L
+#define RLC_CNTL__RLC_STEP_F32__SHIFT 0x00000003
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE_MASK 0x00000010L
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE__SHIFT 0x00000004
+#define RLC_CU_STATUS__WORK_PENDING_MASK 0xffffffffL
+#define RLC_CU_STATUS__WORK_PENDING__SHIFT 0x00000000
+#define RLC_DEBUG__DATA_MASK 0xffffffffL
+#define RLC_DEBUG__DATA__SHIFT 0x00000000
+#define RLC_DEBUG_SELECT__RESERVED_MASK 0xffff8000L
+#define RLC_DEBUG_SELECT__RESERVED__SHIFT 0x0000000f
+#define RLC_DEBUG_SELECT__SELECT_MASK 0x000000ffL
+#define RLC_DEBUG_SELECT__SELECT__SHIFT 0x00000000
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_ACK_MASK 0x00000010L
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_ACK__SHIFT 0x00000004
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_REQUEST_MASK 0x00000001L
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_REQUEST__SHIFT 0x00000000
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED1_MASK 0x0000000eL
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED1__SHIFT 0x00000001
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED_MASK 0xffffffe0L
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED__SHIFT 0x00000005
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK_MASK 0xffffffffL
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK__SHIFT 0x00000000
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffffL
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x00000000
+#define RLC_GPM_SCRATCH_ADDR__ADDR_MASK 0x000001ffL
+#define RLC_GPM_SCRATCH_ADDR__ADDR__SHIFT 0x00000000
+#define RLC_GPM_SCRATCH_ADDR__RESERVED_MASK 0xfffffe00L
+#define RLC_GPM_SCRATCH_ADDR__RESERVED__SHIFT 0x00000009
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED_MASK 0xffffffc0L
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED__SHIFT 0x00000006
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL_MASK 0x0000003fL
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB__SHIFT 0x00000000
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK_MASK 0xffffffffL
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK__SHIFT 0x00000000
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST_MASK 0x00000ff0L
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST__SHIFT 0x00000004
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY_MASK 0x00000002L
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY__SHIFT 0x00000001
+#define RLC_LB_CNTL__LB_CNT_REG_INC_MASK 0x00000008L
+#define RLC_LB_CNTL__LB_CNT_REG_INC__SHIFT 0x00000003
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE_MASK 0x00000004L
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE__SHIFT 0x00000002
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE_MASK 0x00000001L
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE__SHIFT 0x00000000
+#define RLC_LB_CNTL__RESERVED_MASK 0xfffffff0L
+#define RLC_LB_CNTL__RESERVED__SHIFT 0x00000004
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT_MASK 0xffffffffL
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT__SHIFT 0x00000000
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX_MASK 0xffffffffL
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX__SHIFT 0x00000000
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK_MASK 0xffffffffL
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK__SHIFT 0x00000000
+#define RLC_LB_PARAMS__FIFO_SAMPLES_MASK 0x000000feL
+#define RLC_LB_PARAMS__FIFO_SAMPLES__SHIFT 0x00000001
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL_MASK 0xffff0000L
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL__SHIFT 0x00000010
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES_MASK 0x0000ff00L
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES__SHIFT 0x00000008
+#define RLC_LB_PARAMS__SKIP_L2_CHECK_MASK 0x00000001L
+#define RLC_LB_PARAMS__SKIP_L2_CHECK__SHIFT 0x00000000
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR_MASK 0xffffffffL
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR__SHIFT 0x00000000
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK 0x000000ffL
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT 0x00000000
+#define RLC_MAX_PG_CU__SPARE_MASK 0xffffff00L
+#define RLC_MAX_PG_CU__SPARE__SHIFT 0x00000008
+#define RLC_MC_CNTL__RDNFO_STALL_MASK 0x10000000L
+#define RLC_MC_CNTL__RDNFO_STALL__SHIFT 0x0000001c
+#define RLC_MC_CNTL__RDNFO_URG_MASK 0x00f00000L
+#define RLC_MC_CNTL__RDNFO_URG__SHIFT 0x00000014
+#define RLC_MC_CNTL__RDREQ_PRIV_MASK 0x08000000L
+#define RLC_MC_CNTL__RDREQ_PRIV__SHIFT 0x0000001b
+#define RLC_MC_CNTL__RDREQ_SWAP_MASK 0x03000000L
+#define RLC_MC_CNTL__RDREQ_SWAP__SHIFT 0x00000018
+#define RLC_MC_CNTL__RDREQ_TRAN_MASK 0x04000000L
+#define RLC_MC_CNTL__RDREQ_TRAN__SHIFT 0x0000001a
+#define RLC_MC_CNTL__RESERVED_B_MASK 0x000fe000L
+#define RLC_MC_CNTL__RESERVED_B__SHIFT 0x0000000d
+#define RLC_MC_CNTL__RESERVED_MASK 0xe0000000L
+#define RLC_MC_CNTL__RESERVED__SHIFT 0x0000001d
+#define RLC_MC_CNTL__WRNFO_STALL_MASK 0x00000010L
+#define RLC_MC_CNTL__WRNFO_STALL__SHIFT 0x00000004
+#define RLC_MC_CNTL__WRNFO_URG_MASK 0x000001e0L
+#define RLC_MC_CNTL__WRNFO_URG__SHIFT 0x00000005
+#define RLC_MC_CNTL__WRREQ_DW_IMASK_MASK 0x00001e00L
+#define RLC_MC_CNTL__WRREQ_DW_IMASK__SHIFT 0x00000009
+#define RLC_MC_CNTL__WRREQ_PRIV_MASK 0x00000008L
+#define RLC_MC_CNTL__WRREQ_PRIV__SHIFT 0x00000003
+#define RLC_MC_CNTL__WRREQ_SWAP_MASK 0x00000003L
+#define RLC_MC_CNTL__WRREQ_SWAP__SHIFT 0x00000000
+#define RLC_MC_CNTL__WRREQ_TRAN_MASK 0x00000004L
+#define RLC_MC_CNTL__WRREQ_TRAN__SHIFT 0x00000002
+#define RLC_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000L
+#define RLC_MEM_SLP_CNTL__RESERVED1__SHIFT 0x00000018
+#define RLC_MEM_SLP_CNTL__RESERVED_MASK 0x000000fcL
+#define RLC_MEM_SLP_CNTL__RESERVED__SHIFT 0x00000002
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN_MASK 0x00000002L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN__SHIFT 0x00000001
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK 0x00000001L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN__SHIFT 0x00000000
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY_MASK 0x00ff0000L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY__SHIFT 0x00000010
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY_MASK 0x0000ff00L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY__SHIFT 0x00000008
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define RLC_PERFMON_CNTL__PERFMON_STATE_MASK 0x00000007L
+#define RLC_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK_MASK 0xffffffffL
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK__SHIFT 0x00000000
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE_MASK 0x00010000L
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE__SHIFT 0x00000010
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK 0x00000004L
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE__SHIFT 0x00000002
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK 0x00000001L
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE__SHIFT 0x00000000
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC_MASK 0x00000002L
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC__SHIFT 0x00000001
+#define RLC_PG_CNTL__PG_ERROR_STATUS_MASK 0xff000000L
+#define RLC_PG_CNTL__PG_ERROR_STATUS__SHIFT 0x00000018
+#define RLC_PG_CNTL__RESERVED1_MASK 0x00f80000L
+#define RLC_PG_CNTL__RESERVED1__SHIFT 0x00000013
+#define RLC_PG_CNTL__RESERVED_MASK 0xfffffff0L
+#define RLC_PG_CNTL__RESERVED__SHIFT 0x00000004
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK 0x00040000L
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE__SHIFT 0x00000012
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK 0x00020000L
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE__SHIFT 0x00000011
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK 0x00000008L
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE__SHIFT 0x00000003
+#define RLC_SAVE_AND_RESTORE_BASE__BASE_MASK 0xffffffffL
+#define RLC_SAVE_AND_RESTORE_BASE__BASE__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_0__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_0__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_1__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_1__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_2__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_2__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID_MASK 0x0000000fL
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID__SHIFT 0x00000000
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID_MASK 0x0000c000L
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID__SHIFT 0x0000000e
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE_MASK 0x00003800L
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE__SHIFT 0x0000000b
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID_MASK 0x000001c0L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID__SHIFT 0x00000006
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID_MASK 0x00000200L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID__SHIFT 0x00000009
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_MASK 0x00000400L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU__SHIFT 0x0000000a
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID_MASK 0x00000030L
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID__SHIFT 0x00000004
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE_MASK 0xffffc000L
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE__SHIFT 0x0000000e
+#define RLC_SERDES_WR_CTRL__BPM_ADDR_MASK 0x000000ffL
+#define RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT 0x00000000
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_0_MASK 0x00100000L
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_0__SHIFT 0x00000014
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_1_MASK 0x00200000L
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_1__SHIFT 0x00000015
+#define RLC_SERDES_WR_CTRL__CGLS_DISABLE_MASK 0x00020000L
+#define RLC_SERDES_WR_CTRL__CGLS_DISABLE__SHIFT 0x00000011
+#define RLC_SERDES_WR_CTRL__CGLS_ENABLE_MASK 0x00010000L
+#define RLC_SERDES_WR_CTRL__CGLS_ENABLE__SHIFT 0x00000010
+#define RLC_SERDES_WR_CTRL__CGLS_OFF_MASK 0x00080000L
+#define RLC_SERDES_WR_CTRL__CGLS_OFF__SHIFT 0x00000013
+#define RLC_SERDES_WR_CTRL__CGLS_ON_MASK 0x00040000L
+#define RLC_SERDES_WR_CTRL__CGLS_ON__SHIFT 0x00000012
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_0_MASK 0x00400000L
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_0__SHIFT 0x00000016
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_1_MASK 0x00800000L
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_1__SHIFT 0x00000017
+#define RLC_SERDES_WR_CTRL__P1_SELECT_MASK 0x00000400L
+#define RLC_SERDES_WR_CTRL__P1_SELECT__SHIFT 0x0000000a
+#define RLC_SERDES_WR_CTRL__P2_SELECT_MASK 0x00000800L
+#define RLC_SERDES_WR_CTRL__P2_SELECT__SHIFT 0x0000000b
+#define RLC_SERDES_WR_CTRL__POWER_DOWN_MASK 0x00000100L
+#define RLC_SERDES_WR_CTRL__POWER_DOWN__SHIFT 0x00000008
+#define RLC_SERDES_WR_CTRL__POWER_UP_MASK 0x00000200L
+#define RLC_SERDES_WR_CTRL__POWER_UP__SHIFT 0x00000009
+#define RLC_SERDES_WR_CTRL__READ_COMMAND_MASK 0x00002000L
+#define RLC_SERDES_WR_CTRL__READ_COMMAND__SHIFT 0x0000000d
+#define RLC_SERDES_WR_CTRL__REG_ADDR_MASK 0xf0000000L
+#define RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT 0x0000001c
+#define RLC_SERDES_WR_CTRL__RESERVED_1_MASK 0x0000c000L
+#define RLC_SERDES_WR_CTRL__RESERVED_1__SHIFT 0x0000000e
+#define RLC_SERDES_WR_CTRL__RESERVED_2_MASK 0x0f000000L
+#define RLC_SERDES_WR_CTRL__RESERVED_2__SHIFT 0x00000018
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK 0x00001000L
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND__SHIFT 0x0000000c
+#define RLC_SERDES_WR_DATA__DATA_MASK 0xffffffffL
+#define RLC_SERDES_WR_DATA__DATA__SHIFT 0x00000000
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE_MASK 0x00000001L
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE__SHIFT 0x00000000
+#define RLC_SMU_PG_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_PG_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_PG_CTRL__START_PG_MASK 0x00000001L
+#define RLC_SMU_PG_CTRL__START_PG__SHIFT 0x00000000
+#define RLC_SMU_PG_WAKE_UP_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_PG_WAKE_UP_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_PG_WAKE_UP_CTRL__START_PG_WAKE_UP_MASK 0x00000001L
+#define RLC_SMU_PG_WAKE_UP_CTRL__START_PG_WAKE_UP__SHIFT 0x00000000
+#define RLC_SOFT_RESET_GPU__RESERVED_MASK 0xfffffffeL
+#define RLC_SOFT_RESET_GPU__RESERVED__SHIFT 0x00000001
+#define RLC_SOFT_RESET_GPU__SOFT_RESET_GPU_MASK 0x00000001L
+#define RLC_SOFT_RESET_GPU__SOFT_RESET_GPU__SHIFT 0x00000000
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffffL
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x00000000
+#define RLC_STAT__RESERVED_MASK 0xfffffff0L
+#define RLC_STAT__RESERVED__SHIFT 0x00000004
+#define RLC_STAT__RLC_BUSY_MASK 0x00000001L
+#define RLC_STAT__RLC_BUSY__SHIFT 0x00000000
+#define RLC_STAT__RLC_GPM_BUSY_MASK 0x00000002L
+#define RLC_STAT__RLC_GPM_BUSY__SHIFT 0x00000001
+#define RLC_STAT__RLC_SPM_BUSY_MASK 0x00000004L
+#define RLC_STAT__RLC_SPM_BUSY__SHIFT 0x00000002
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY_MASK 0x000000ffL
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY__SHIFT 0x00000000
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY_MASK 0x0000ff00L
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY__SHIFT 0x00000008
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY_MASK 0x00ff0000L
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY__SHIFT 0x00000010
+#define RLC_THREAD1_DELAY__SPARE_MASK 0xff000000L
+#define RLC_THREAD1_DELAY__SPARE__SHIFT 0x00000018
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS_MASK 0xffffffffL
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS__SHIFT 0x00000000
+#define SCRATCH_ADDR__OBSOLETE_ADDR_MASK 0xffffffffL
+#define SCRATCH_ADDR__OBSOLETE_ADDR__SHIFT 0x00000000
+#define SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffffL
+#define SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x00000000
+#define SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffffL
+#define SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x00000000
+#define SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffffL
+#define SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x00000000
+#define SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffffL
+#define SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x00000000
+#define SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffffL
+#define SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x00000000
+#define SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffffL
+#define SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x00000000
+#define SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffffL
+#define SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x00000000
+#define SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffffL
+#define SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x00000000
+#define SCRATCH_UMSK__OBSOLETE_SWAP_MASK 0x00030000L
+#define SCRATCH_UMSK__OBSOLETE_SWAP__SHIFT 0x00000010
+#define SCRATCH_UMSK__OBSOLETE_UMSK_MASK 0x000000ffL
+#define SCRATCH_UMSK__OBSOLETE_UMSK__SHIFT 0x00000000
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld_MASK 0x80000000L
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG0__event_gated_MASK 0x10000000L
+#define SETUP_DEBUG_REG0__event_gated__SHIFT 0x0000001c
+#define SETUP_DEBUG_REG0__event_id_gated_MASK 0x0fc00000L
+#define SETUP_DEBUG_REG0__event_id_gated__SHIFT 0x00000016
+#define SETUP_DEBUG_REG0__geom_busy_MASK 0x00200000L
+#define SETUP_DEBUG_REG0__geom_busy__SHIFT 0x00000015
+#define SETUP_DEBUG_REG0__geom_enable_MASK 0x00008000L
+#define SETUP_DEBUG_REG0__geom_enable__SHIFT 0x0000000f
+#define SETUP_DEBUG_REG0__ge_stallb_MASK 0x00004000L
+#define SETUP_DEBUG_REG0__ge_stallb__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG0__pfifo_busy_MASK 0x00080000L
+#define SETUP_DEBUG_REG0__pfifo_busy__SHIFT 0x00000013
+#define SETUP_DEBUG_REG0__pmode_prim_gated_MASK 0x20000000L
+#define SETUP_DEBUG_REG0__pmode_prim_gated__SHIFT 0x0000001d
+#define SETUP_DEBUG_REG0__pmode_state_MASK 0x00003f00L
+#define SETUP_DEBUG_REG0__pmode_state__SHIFT 0x00000008
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state_MASK 0x00000003L
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state__SHIFT 0x00000000
+#define SETUP_DEBUG_REG0__su_clip_baryc_free_MASK 0x00030000L
+#define SETUP_DEBUG_REG0__su_clip_baryc_free__SHIFT 0x00000010
+#define SETUP_DEBUG_REG0__su_clip_rtr_MASK 0x00040000L
+#define SETUP_DEBUG_REG0__su_clip_rtr__SHIFT 0x00000012
+#define SETUP_DEBUG_REG0__su_cntl_busy_MASK 0x00100000L
+#define SETUP_DEBUG_REG0__su_cntl_busy__SHIFT 0x00000014
+#define SETUP_DEBUG_REG0__su_cntl_state_MASK 0x0000003cL
+#define SETUP_DEBUG_REG0__su_cntl_state__SHIFT 0x00000002
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld_MASK 0x40000000L
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld__SHIFT 0x0000001e
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated_MASK 0x00003fffL
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated__SHIFT 0x00000000
+#define SETUP_DEBUG_REG4__backfacing_gated_MASK 0x00008000L
+#define SETUP_DEBUG_REG4__backfacing_gated__SHIFT 0x0000000f
+#define SETUP_DEBUG_REG4__clipped_gated_MASK 0x00080000L
+#define SETUP_DEBUG_REG4__clipped_gated__SHIFT 0x00000013
+#define SETUP_DEBUG_REG4__dealloc_slot_gated_MASK 0x00700000L
+#define SETUP_DEBUG_REG4__dealloc_slot_gated__SHIFT 0x00000014
+#define SETUP_DEBUG_REG4__diamond_rule_gated_MASK 0x03000000L
+#define SETUP_DEBUG_REG4__diamond_rule_gated__SHIFT 0x00000018
+#define SETUP_DEBUG_REG4__eop_gated_MASK 0x80000000L
+#define SETUP_DEBUG_REG4__eop_gated__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG4__fpov_gated_MASK 0x60000000L
+#define SETUP_DEBUG_REG4__fpov_gated__SHIFT 0x0000001d
+#define SETUP_DEBUG_REG4__null_prim_gated_MASK 0x00004000L
+#define SETUP_DEBUG_REG4__null_prim_gated__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG4__st_indx_gated_MASK 0x00070000L
+#define SETUP_DEBUG_REG4__st_indx_gated__SHIFT 0x00000010
+#define SETUP_DEBUG_REG4__type_gated_MASK 0x1c000000L
+#define SETUP_DEBUG_REG4__type_gated__SHIFT 0x0000001a
+#define SETUP_DEBUG_REG4__xmajor_gated_MASK 0x00800000L
+#define SETUP_DEBUG_REG4__xmajor_gated__SHIFT 0x00000017
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated_MASK 0x0fffc000L
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated_MASK 0x00003fffL
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated__SHIFT 0x00000000
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld_MASK 0x80000000L
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG5__provoking_vtx_gated_MASK 0x30000000L
+#define SETUP_DEBUG_REG5__provoking_vtx_gated__SHIFT 0x0000001c
+#define SETUP_DEBUG_REG5__valid_prim_gated_MASK 0x40000000L
+#define SETUP_DEBUG_REG5__valid_prim_gated__SHIFT 0x0000001e
+#define SPI_ARB_CYCLES_0__TS0_DURATION_MASK 0x0000ffffL
+#define SPI_ARB_CYCLES_0__TS0_DURATION__SHIFT 0x00000000
+#define SPI_ARB_CYCLES_0__TS1_DURATION_MASK 0xffff0000L
+#define SPI_ARB_CYCLES_0__TS1_DURATION__SHIFT 0x00000010
+#define SPI_ARB_CYCLES_1__TS2_DURATION_MASK 0x0000ffffL
+#define SPI_ARB_CYCLES_1__TS2_DURATION__SHIFT 0x00000000
+#define SPI_ARB_CYCLES_1__TS3_DURATION_MASK 0xffff0000L
+#define SPI_ARB_CYCLES_1__TS3_DURATION__SHIFT 0x00000010
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0_MASK 0x00000007L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0__SHIFT 0x00000000
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1_MASK 0x00000038L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1__SHIFT 0x00000003
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2_MASK 0x000001c0L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2__SHIFT 0x00000006
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3_MASK 0x00000e00L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3__SHIFT 0x00000009
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT_MASK 0x00003000L
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT__SHIFT 0x0000000c
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT_MASK 0x0000c000L
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT__SHIFT 0x0000000e
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT_MASK 0x00030000L
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT__SHIFT 0x00000010
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT_MASK 0x000c0000L
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT__SHIFT 0x00000012
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS_MASK 0x01000000L
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS__SHIFT 0x00000018
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL_MASK 0x00000100L
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL__SHIFT 0x00000008
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL_MASK 0x00001000L
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL__SHIFT 0x0000000c
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL_MASK 0x00000001L
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL__SHIFT 0x00000000
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL_MASK 0x00000010L
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL__SHIFT 0x00000004
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION_MASK 0x00030000L
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION__SHIFT 0x00000010
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC_MASK 0x00100000L
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC__SHIFT 0x00000014
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE_MASK 0x00000100L
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE__SHIFT 0x00000008
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW_MASK 0x00000010L
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW__SHIFT 0x00000004
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT_MASK 0x00003c00L
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT__SHIFT 0x0000000a
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE_MASK 0x00000200L
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE__SHIFT 0x00000009
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE_MASK 0x00000040L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE__SHIFT 0x00000006
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE_MASK 0xffff0000L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE__SHIFT 0x00000010
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT_MASK 0x00000080L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT__SHIFT 0x00000007
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_MASK 0x0000000fL
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY__SHIFT 0x00000000
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS_MASK 0x02000000L
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS__SHIFT 0x00000019
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS_MASK 0x01000000L
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS__SHIFT 0x00000018
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER_MASK 0x00e00000L
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER__SHIFT 0x00000015
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY_MASK 0x001fffffL
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY__SHIFT 0x00000000
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET_MASK 0x04000000L
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET__SHIFT 0x0000001a
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL_MASK 0x08000000L
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL__SHIFT 0x0000001b
+#define SPI_DEBUG_BUSY__CS0_BUSY_MASK 0x00000080L
+#define SPI_DEBUG_BUSY__CS0_BUSY__SHIFT 0x00000007
+#define SPI_DEBUG_BUSY__CS1_BUSY_MASK 0x00000100L
+#define SPI_DEBUG_BUSY__CS1_BUSY__SHIFT 0x00000008
+#define SPI_DEBUG_BUSY__CS2_BUSY_MASK 0x00000200L
+#define SPI_DEBUG_BUSY__CS2_BUSY__SHIFT 0x00000009
+#define SPI_DEBUG_BUSY__CS3_BUSY_MASK 0x00000800L
+#define SPI_DEBUG_BUSY__CS3_BUSY__SHIFT 0x0000000b
+#define SPI_DEBUG_BUSY__CS4_BUSY_MASK 0x00001000L
+#define SPI_DEBUG_BUSY__CS4_BUSY__SHIFT 0x0000000c
+#define SPI_DEBUG_BUSY__CS5_BUSY_MASK 0x00002000L
+#define SPI_DEBUG_BUSY__CS5_BUSY__SHIFT 0x0000000d
+#define SPI_DEBUG_BUSY__CS6_BUSY_MASK 0x00004000L
+#define SPI_DEBUG_BUSY__CS6_BUSY__SHIFT 0x0000000e
+#define SPI_DEBUG_BUSY__CS7_BUSY_MASK 0x00008000L
+#define SPI_DEBUG_BUSY__CS7_BUSY__SHIFT 0x0000000f
+#define SPI_DEBUG_BUSY__CSG_BUSY_MASK 0x00000080L
+#define SPI_DEBUG_BUSY__CSG_BUSY__SHIFT 0x00000007
+#define SPI_DEBUG_BUSY__ES_BUSY_MASK 0x00000004L
+#define SPI_DEBUG_BUSY__ES_BUSY__SHIFT 0x00000002
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY_MASK 0x00008000L
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY__SHIFT 0x0000000f
+#define SPI_DEBUG_BUSY__GRBM_BUSY_MASK 0x00010000L
+#define SPI_DEBUG_BUSY__GRBM_BUSY__SHIFT 0x00000010
+#define SPI_DEBUG_BUSY__GS_BUSY_MASK 0x00000008L
+#define SPI_DEBUG_BUSY__GS_BUSY__SHIFT 0x00000003
+#define SPI_DEBUG_BUSY__HS_BUSY_MASK 0x00000002L
+#define SPI_DEBUG_BUSY__HS_BUSY__SHIFT 0x00000001
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY_MASK 0x00000400L
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY__SHIFT 0x0000000a
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY_MASK 0x00000800L
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY__SHIFT 0x0000000b
+#define SPI_DEBUG_BUSY__LS_BUSY_MASK 0x00000001L
+#define SPI_DEBUG_BUSY__LS_BUSY__SHIFT 0x00000000
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY_MASK 0x00100000L
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY__SHIFT 0x00000014
+#define SPI_DEBUG_BUSY__PS0_BUSY_MASK 0x00000020L
+#define SPI_DEBUG_BUSY__PS0_BUSY__SHIFT 0x00000005
+#define SPI_DEBUG_BUSY__PS1_BUSY_MASK 0x00000040L
+#define SPI_DEBUG_BUSY__PS1_BUSY__SHIFT 0x00000006
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY_MASK 0x00001000L
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY__SHIFT 0x0000000c
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY_MASK 0x00002000L
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY__SHIFT 0x0000000d
+#define SPI_DEBUG_BUSY__SPIS_BUSY_MASK 0x00020000L
+#define SPI_DEBUG_BUSY__SPIS_BUSY__SHIFT 0x00000011
+#define SPI_DEBUG_BUSY__VS_BUSY_MASK 0x00000010L
+#define SPI_DEBUG_BUSY__VS_BUSY__SHIFT 0x00000004
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE_MASK 0x00000001L
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE__SHIFT 0x00000000
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL_MASK 0x000003e0L
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL__SHIFT 0x00000005
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL_MASK 0x0e000000L
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL__SHIFT 0x00000019
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN_MASK 0x80000000L
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN__SHIFT 0x0000001f
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL_MASK 0x00010000L
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL__SHIFT 0x00000010
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL_MASK 0x0000fc00L
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL__SHIFT 0x0000000a
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL_MASK 0x0000001eL
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL__SHIFT 0x00000001
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0_MASK 0x00020000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0__SHIFT 0x00000011
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1_MASK 0x00040000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1__SHIFT 0x00000012
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2_MASK 0x00080000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2__SHIFT 0x00000013
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3_MASK 0x00100000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3__SHIFT 0x00000014
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4_MASK 0x00200000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4__SHIFT 0x00000015
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5_MASK 0x00400000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5__SHIFT 0x00000016
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6_MASK 0x00800000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6__SHIFT 0x00000017
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7_MASK 0x01000000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7__SHIFT 0x00000018
+#define SPI_DEBUG_READ__DATA_MASK 0x00ffffffL
+#define SPI_DEBUG_READ__DATA__SHIFT 0x00000000
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS_MASK 0x0000ff00L
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS__SHIFT 0x00000008
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS_MASK 0x000000ffL
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS__SHIFT 0x00000000
+#define SPI_GDS_CREDITS__UNUSED_MASK 0xffff0000L
+#define SPI_GDS_CREDITS__UNUSED__SHIFT 0x00000010
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA_MASK 0x00000001L
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA__SHIFT 0x00000000
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA_MASK 0x00000002L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA__SHIFT 0x00000001
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W_MASK 0x00003800L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W__SHIFT 0x0000000b
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X_MASK 0x0000001cL
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X__SHIFT 0x00000002
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y_MASK 0x000000e0L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y__SHIFT 0x00000005
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z_MASK 0x00000700L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z__SHIFT 0x00000008
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1_MASK 0x00004000L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1__SHIFT 0x0000000e
+#define SPI_LB_CTR_CTRL__LOAD_MASK 0x00000001L
+#define SPI_LB_CTR_CTRL__LOAD__SHIFT 0x00000000
+#define SPI_LB_CU_MASK__CU_MASK_MASK 0x0000ffffL
+#define SPI_LB_CU_MASK__CU_MASK__SHIFT 0x00000000
+#define SPI_LB_DATA_REG__CNT_DATA_MASK 0xffffffffL
+#define SPI_LB_DATA_REG__CNT_DATA__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX_MASK 0x000000f0L
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX__SHIFT 0x00000004
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN_MASK 0x0000000fL
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN__SHIFT 0x00000000
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX_MASK 0x0000f000L
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX__SHIFT 0x0000000c
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN_MASK 0x00000f00L
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN__SHIFT 0x00000008
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX_MASK 0x00f00000L
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX__SHIFT 0x00000014
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN_MASK 0x000f0000L
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN__SHIFT 0x00000010
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX_MASK 0xf0000000L
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX__SHIFT 0x0000001c
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN_MASK 0x0f000000L
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN__SHIFT 0x00000018
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK_MASK 0x0000ffffL
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK__SHIFT 0x00000000
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE_MASK 0x00004000L
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE__SHIFT 0x0000000e
+#define SPI_PS_IN_CONTROL__NUM_INTERP_MASK 0x0000003fL
+#define SPI_PS_IN_CONTROL__NUM_INTERP__SHIFT 0x00000000
+#define SPI_PS_IN_CONTROL__PARAM_GEN_MASK 0x00000040L
+#define SPI_PS_IN_CONTROL__PARAM_GEN__SHIFT 0x00000006
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA_MASK 0x00002000L
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA__SHIFT 0x0000000d
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA_MASK 0x00001000L
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA__SHIFT 0x0000000c
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA_MASK 0x00000020L
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA__SHIFT 0x00000005
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA_MASK 0x00000040L
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA__SHIFT 0x00000006
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA_MASK 0x00000010L
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA__SHIFT 0x00000004
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA_MASK 0x00000080L
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA__SHIFT 0x00000007
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA_MASK 0x00000002L
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA__SHIFT 0x00000001
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA_MASK 0x00000004L
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA__SHIFT 0x00000002
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA_MASK 0x00000008L
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA__SHIFT 0x00000003
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA_MASK 0x00000001L
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA__SHIFT 0x00000000
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA_MASK 0x00008000L
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA__SHIFT 0x0000000f
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA_MASK 0x00000800L
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA__SHIFT 0x0000000b
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA_MASK 0x00000100L
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA__SHIFT 0x00000008
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA_MASK 0x00000200L
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA__SHIFT 0x00000009
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA_MASK 0x00000400L
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA__SHIFT 0x0000000a
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA_MASK 0x00004000L
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA__SHIFT 0x0000000e
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_0__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_0__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_0__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_0__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_10__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_10__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_10__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_10__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_11__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_11__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_11__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_11__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_12__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_12__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_12__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_12__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_13__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_13__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_13__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_13__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_14__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_14__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_14__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_14__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_15__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_15__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_15__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_15__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_16__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_16__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_16__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_16__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_17__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_17__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_17__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_17__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_18__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_18__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_18__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_18__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_19__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_19__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_19__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_19__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_1__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_1__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_1__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_1__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_20__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_20__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_20__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_20__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_21__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_21__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_21__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_21__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_22__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_22__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_22__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_22__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_23__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_23__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_23__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_23__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_24__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_24__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_24__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_24__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_25__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_25__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_25__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_25__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_26__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_26__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_26__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_26__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_27__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_27__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_27__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_27__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_28__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_28__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_28__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_28__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_29__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_29__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_29__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_29__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_2__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_2__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_2__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_2__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_30__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_30__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_30__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_30__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_31__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_31__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_31__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_31__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_3__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_3__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_3__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_3__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_4__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_4__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_4__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_4__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_5__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_5__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_5__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_5__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_6__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_6__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_6__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_6__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_7__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_7__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_7__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_7__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_8__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_8__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_8__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_8__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_9__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_9__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_9__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_9__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA_MASK 0x00002000L
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA__SHIFT 0x0000000d
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA_MASK 0x00001000L
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA__SHIFT 0x0000000c
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA_MASK 0x00000020L
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA__SHIFT 0x00000005
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA_MASK 0x00000040L
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA__SHIFT 0x00000006
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA_MASK 0x00000010L
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA__SHIFT 0x00000004
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA_MASK 0x00000080L
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA__SHIFT 0x00000007
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA_MASK 0x00000002L
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA__SHIFT 0x00000001
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA_MASK 0x00000004L
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA__SHIFT 0x00000002
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA_MASK 0x00000008L
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA__SHIFT 0x00000003
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA_MASK 0x00000001L
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA__SHIFT 0x00000000
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA_MASK 0x00008000L
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA__SHIFT 0x0000000f
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA_MASK 0x00000800L
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA__SHIFT 0x0000000b
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA_MASK 0x00000100L
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA__SHIFT 0x00000008
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA_MASK 0x00000200L
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA__SHIFT 0x00000009
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA_MASK 0x00000400L
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA__SHIFT 0x0000000a
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA_MASK 0x00004000L
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA__SHIFT 0x0000000e
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID_MASK 0x00000fffL
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID__SHIFT 0x00000000
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT_MASK 0x000000f0L
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT__SHIFT 0x00000004
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT_MASK 0x00000f00L
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT__SHIFT 0x00000008
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT_MASK 0x0000f000L
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT__SHIFT 0x0000000c
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT_MASK 0x000f0000L
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT__SHIFT 0x00000010
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT_MASK 0x00f00000L
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT__SHIFT 0x00000014
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT_MASK 0x0f000000L
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT__SHIFT 0x00000018
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT_MASK 0xf0000000L
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL_MASK 0x38000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER_MASK 0x40000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER__SHIFT 0x0000001e
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE_MASK 0x04000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL_MASK 0x0e000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL__SHIFT 0x00000019
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER_MASK 0x10000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE_MASK 0x01000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL_MASK 0x07000000L
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER_MASK 0x08000000L
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL_MASK 0x1c000000L
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER_MASK 0x20000000L
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER__SHIFT 0x0000001d
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL_MASK 0x0e000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL__SHIFT 0x00000019
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER_MASK 0x10000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE_MASK 0x01000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL_MASK 0x38000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER_MASK 0x40000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER__SHIFT 0x0000001e
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE_MASK 0x04000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN_MASK 0x00007f00L
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN_MASK 0x0001ff00L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN_MASK 0x0001ff00L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN_MASK 0x00003f80L
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN_MASK 0x0000fe00L
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN__SHIFT 0x00000009
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN_MASK 0x00000100L
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN_MASK 0x007f0000L
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN_MASK 0x007f0000L
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE_MASK 0x0000ff00L
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN_MASK 0x000fe000L
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN__SHIFT 0x0000000d
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN_MASK 0x00000100L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN_MASK 0x00000200L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN__SHIFT 0x00000009
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN_MASK 0x00000400L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN_MASK 0x00000800L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN__SHIFT 0x0000000b
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN_MASK 0x00001000L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT_MASK 0x000000f0L
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT__SHIFT 0x00000004
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT_MASK 0x00000f00L
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT__SHIFT 0x00000008
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT_MASK 0x0000f000L
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT__SHIFT 0x0000000c
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY_MASK 0x00000004L
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY__SHIFT 0x00000002
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY_MASK 0x00200000L
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY__SHIFT 0x00000015
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY_MASK 0x00000008L
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY__SHIFT 0x00000003
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY_MASK 0x00000002L
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY__SHIFT 0x00000001
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY_MASK 0x00000001L
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY__SHIFT 0x00000000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY_MASK 0x00000200L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY__SHIFT 0x00000009
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY_MASK 0x00000400L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY__SHIFT 0x0000000a
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY_MASK 0x00000800L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY__SHIFT 0x0000000b
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY_MASK 0x00001000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY__SHIFT 0x0000000c
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY_MASK 0x00002000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY__SHIFT 0x0000000d
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY_MASK 0x00004000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY__SHIFT 0x0000000e
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY_MASK 0x00008000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY__SHIFT 0x0000000f
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY_MASK 0x00010000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY__SHIFT 0x00000010
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY_MASK 0x00000020L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY__SHIFT 0x00000005
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY_MASK 0x00000040L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY__SHIFT 0x00000006
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY_MASK 0x00000080L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY__SHIFT 0x00000007
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY_MASK 0x00000100L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY__SHIFT 0x00000008
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY_MASK 0x00000010L
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY__SHIFT 0x00000004
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY_MASK 0x00020000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY__SHIFT 0x00000011
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY_MASK 0x00040000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY__SHIFT 0x00000012
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY_MASK 0x00080000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY__SHIFT 0x00000013
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY_MASK 0x00100000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY__SHIFT 0x00000014
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE_MASK 0x0000ffffL
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE__SHIFT 0x00000000
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE_MASK 0xffff0000L
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE__SHIFT 0x00000010
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE_MASK 0x0000ffffL
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE__SHIFT 0x00000000
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE_MASK 0xffff0000L
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE__SHIFT 0x00000010
+#define SPI_TMPRING_SIZE__WAVESIZE_MASK 0x01fff000L
+#define SPI_TMPRING_SIZE__WAVESIZE__SHIFT 0x0000000c
+#define SPI_TMPRING_SIZE__WAVES_MASK 0x00000fffL
+#define SPI_TMPRING_SIZE__WAVES__SHIFT 0x00000000
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT_MASK 0x0000003eL
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT__SHIFT 0x00000001
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK_MASK 0x00000040L
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK__SHIFT 0x00000006
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0x0000ffffL
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x00000000
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000L
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x00000010
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffffL
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0x0000ffffL
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE_MASK 0x40000000L
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE__SHIFT 0x0000001e
+#define SQ_BUF_RSRC_WORD1__STRIDE_MASK 0x3fff0000L
+#define SQ_BUF_RSRC_WORD1__STRIDE__SHIFT 0x00000010
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE_MASK 0x80000000L
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE__SHIFT 0x0000001f
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS_MASK 0xffffffffL
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE_MASK 0x00800000L
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE__SHIFT 0x00000017
+#define SQ_BUF_RSRC_WORD3__ATC_MASK 0x01000000L
+#define SQ_BUF_RSRC_WORD3__ATC__SHIFT 0x00000018
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT_MASK 0x00078000L
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT__SHIFT 0x0000000f
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W_MASK 0x00000e00L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W__SHIFT 0x00000009
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X_MASK 0x00000007L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y_MASK 0x00000038L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y__SHIFT 0x00000003
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z_MASK 0x000001c0L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z__SHIFT 0x00000006
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE_MASK 0x00180000L
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE__SHIFT 0x00000013
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE_MASK 0x02000000L
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE__SHIFT 0x00000019
+#define SQ_BUF_RSRC_WORD3__HEAP_MASK 0x04000000L
+#define SQ_BUF_RSRC_WORD3__HEAP__SHIFT 0x0000001a
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE_MASK 0x00600000L
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE__SHIFT 0x00000015
+#define SQ_BUF_RSRC_WORD3__MTYPE_MASK 0x38000000L
+#define SQ_BUF_RSRC_WORD3__MTYPE__SHIFT 0x0000001b
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT_MASK 0x00007000L
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT__SHIFT 0x0000000c
+#define SQ_BUF_RSRC_WORD3__TYPE_MASK 0xc0000000L
+#define SQ_BUF_RSRC_WORD3__TYPE__SHIFT 0x0000001e
+#define SQC_CACHES__DATA_INVALIDATE_MASK 0x00000002L
+#define SQC_CACHES__DATA_INVALIDATE__SHIFT 0x00000001
+#define SQC_CACHES__INST_INVALIDATE_MASK 0x00000001L
+#define SQC_CACHES__INST_INVALIDATE__SHIFT 0x00000000
+#define SQC_CACHES__INVALIDATE_VOLATILE_MASK 0x00000004L
+#define SQC_CACHES__INVALIDATE_VOLATILE__SHIFT 0x00000002
+#define SQC_CONFIG__DATA_CACHE_SIZE_MASK 0x0000000cL
+#define SQC_CONFIG__DATA_CACHE_SIZE__SHIFT 0x00000002
+#define SQC_CONFIG__FORCE_ALWAYS_MISS_MASK 0x00000080L
+#define SQC_CONFIG__FORCE_ALWAYS_MISS__SHIFT 0x00000007
+#define SQC_CONFIG__FORCE_IN_ORDER_MASK 0x00000100L
+#define SQC_CONFIG__FORCE_IN_ORDER__SHIFT 0x00000008
+#define SQC_CONFIG__HIT_FIFO_DEPTH_MASK 0x00000040L
+#define SQC_CONFIG__HIT_FIFO_DEPTH__SHIFT 0x00000006
+#define SQC_CONFIG__IDENTITY_HASH_BANK_MASK 0x00000200L
+#define SQC_CONFIG__IDENTITY_HASH_BANK__SHIFT 0x00000009
+#define SQC_CONFIG__IDENTITY_HASH_SET_MASK 0x00000400L
+#define SQC_CONFIG__IDENTITY_HASH_SET__SHIFT 0x0000000a
+#define SQC_CONFIG__INST_CACHE_SIZE_MASK 0x00000003L
+#define SQC_CONFIG__INST_CACHE_SIZE__SHIFT 0x00000000
+#define SQC_CONFIG__MISS_FIFO_DEPTH_MASK 0x00000030L
+#define SQC_CONFIG__MISS_FIFO_DEPTH__SHIFT 0x00000004
+#define SQC_CONFIG__PER_VMID_INV_DISABLE_MASK 0x00000800L
+#define SQC_CONFIG__PER_VMID_INV_DISABLE__SHIFT 0x0000000b
+#define SQ_CONFIG__DEBUG_EN_MASK 0x00000100L
+#define SQ_CONFIG__DEBUG_EN__SHIFT 0x00000008
+#define SQ_CONFIG__DISABLE_IB_DEP_CHECK_MASK 0x00000400L
+#define SQ_CONFIG__DISABLE_IB_DEP_CHECK__SHIFT 0x0000000a
+#define SQ_CONFIG__DISABLE_SCA_BYPASS_MASK 0x00000200L
+#define SQ_CONFIG__DISABLE_SCA_BYPASS__SHIFT 0x00000009
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE_MASK 0x00008000L
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE__SHIFT 0x0000000f
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE_MASK 0x00002000L
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE__SHIFT 0x0000000d
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE_MASK 0x00004000L
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE__SHIFT 0x0000000e
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE_MASK 0x00001000L
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE__SHIFT 0x0000000c
+#define SQ_CONFIG__ENABLE_SOFT_CLAUSE_MASK 0x00000800L
+#define SQ_CONFIG__ENABLE_SOFT_CLAUSE__SHIFT 0x0000000b
+#define SQ_CONFIG__UNUSED_MASK 0x000000ffL
+#define SQ_CONFIG__UNUSED__SHIFT 0x00000000
+#define SQC_SECDED_CNT__DATA_DED_MASK 0xff000000L
+#define SQC_SECDED_CNT__DATA_DED__SHIFT 0x00000018
+#define SQC_SECDED_CNT__DATA_SEC_MASK 0x00ff0000L
+#define SQC_SECDED_CNT__DATA_SEC__SHIFT 0x00000010
+#define SQC_SECDED_CNT__INST_DED_MASK 0x0000ff00L
+#define SQC_SECDED_CNT__INST_DED__SHIFT 0x00000008
+#define SQC_SECDED_CNT__INST_SEC_MASK 0x000000ffL
+#define SQC_SECDED_CNT__INST_SEC__SHIFT 0x00000000
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED_MASK 0x000000ffL
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0_MASK 0x000000ffL
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1_MASK 0x0000ff00L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1__SHIFT 0x00000008
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST_MASK 0xff000000L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST__SHIFT 0x00000018
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED_MASK 0x00ff0000L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED__SHIFT 0x00000010
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD_MASK 0x0000000fL
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG_MASK 0x000000f0L
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG__SHIFT 0x00000004
+#define SQ_DEBUG_STS_GLOBAL__BUSY_MASK 0x00000001L
+#define SQ_DEBUG_STS_GLOBAL__BUSY__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY_MASK 0x00000002L
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY__SHIFT 0x00000001
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0_MASK 0x0000fff0L
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0__SHIFT 0x00000004
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1_MASK 0x0fff0000L
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1__SHIFT 0x00000010
+#define SQ_DEBUG_STS_LOCAL__BUSY_MASK 0x00000001L
+#define SQ_DEBUG_STS_LOCAL__BUSY__SHIFT 0x00000000
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL_MASK 0x000003f0L
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL__SHIFT 0x00000004
+#define SQ_DED_CNT__LDS_DED_MASK 0x0000003fL
+#define SQ_DED_CNT__LDS_DED__SHIFT 0x00000000
+#define SQ_DED_CNT__SGPR_DED_MASK 0x00001f00L
+#define SQ_DED_CNT__SGPR_DED__SHIFT 0x00000008
+#define SQ_DED_CNT__VGPR_DED_MASK 0x01ff0000L
+#define SQ_DED_CNT__VGPR_DED__SHIFT 0x00000010
+#define SQ_DED_INFO__SIMD_ID_MASK 0x00000030L
+#define SQ_DED_INFO__SIMD_ID__SHIFT 0x00000004
+#define SQ_DED_INFO__SOURCE_MASK 0x000001c0L
+#define SQ_DED_INFO__SOURCE__SHIFT 0x00000006
+#define SQ_DED_INFO__VM_ID_MASK 0x00001e00L
+#define SQ_DED_INFO__VM_ID__SHIFT 0x00000009
+#define SQ_DED_INFO__WAVE_ID_MASK 0x0000000fL
+#define SQ_DED_INFO__WAVE_ID__SHIFT 0x00000000
+#define SQ_DS_0__ENCODING_MASK 0xfc000000L
+#define SQ_DS_0__ENCODING__SHIFT 0x0000001a
+#define SQ_DS_0__GDS_MASK 0x00020000L
+#define SQ_DS_0__GDS__SHIFT 0x00000011
+#define SQ_DS_0__OFFSET0_MASK 0x000000ffL
+#define SQ_DS_0__OFFSET0__SHIFT 0x00000000
+#define SQ_DS_0__OFFSET1_MASK 0x0000ff00L
+#define SQ_DS_0__OFFSET1__SHIFT 0x00000008
+#define SQ_DS_0__OP_MASK 0x03fc0000L
+#define SQ_DS_0__OP__SHIFT 0x00000012
+#define SQ_DS_1__ADDR_MASK 0x000000ffL
+#define SQ_DS_1__ADDR__SHIFT 0x00000000
+#define SQ_DS_1__DATA0_MASK 0x0000ff00L
+#define SQ_DS_1__DATA0__SHIFT 0x00000008
+#define SQ_DS_1__DATA1_MASK 0x00ff0000L
+#define SQ_DS_1__DATA1__SHIFT 0x00000010
+#define SQ_DS_1__VDST_MASK 0xff000000L
+#define SQ_DS_1__VDST__SHIFT 0x00000018
+#define SQ_EXP_0__COMPR_MASK 0x00000400L
+#define SQ_EXP_0__COMPR__SHIFT 0x0000000a
+#define SQ_EXP_0__DONE_MASK 0x00000800L
+#define SQ_EXP_0__DONE__SHIFT 0x0000000b
+#define SQ_EXP_0__ENCODING_MASK 0xfc000000L
+#define SQ_EXP_0__ENCODING__SHIFT 0x0000001a
+#define SQ_EXP_0__EN_MASK 0x0000000fL
+#define SQ_EXP_0__EN__SHIFT 0x00000000
+#define SQ_EXP_0__TGT_MASK 0x000003f0L
+#define SQ_EXP_0__TGT__SHIFT 0x00000004
+#define SQ_EXP_0__VM_MASK 0x00001000L
+#define SQ_EXP_0__VM__SHIFT 0x0000000c
+#define SQ_EXP_1__VSRC0_MASK 0x000000ffL
+#define SQ_EXP_1__VSRC0__SHIFT 0x00000000
+#define SQ_EXP_1__VSRC1_MASK 0x0000ff00L
+#define SQ_EXP_1__VSRC1__SHIFT 0x00000008
+#define SQ_EXP_1__VSRC2_MASK 0x00ff0000L
+#define SQ_EXP_1__VSRC2__SHIFT 0x00000010
+#define SQ_EXP_1__VSRC3_MASK 0xff000000L
+#define SQ_EXP_1__VSRC3__SHIFT 0x00000018
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE_MASK 0x00030000L
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE__SHIFT 0x00000010
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE_MASK 0x0000000fL
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE__SHIFT 0x00000000
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE_MASK 0x00000f00L
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE__SHIFT 0x00000008
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE_MASK 0x000c0000L
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE__SHIFT 0x00000012
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffffL
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0x000000ffL
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT_MASK 0x03f00000L
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD1__MIN_LOD_MASK 0x000fff00L
+#define SQ_IMG_RSRC_WORD1__MIN_LOD__SHIFT 0x00000008
+#define SQ_IMG_RSRC_WORD1__MTYPE_MASK 0xc0000000L
+#define SQ_IMG_RSRC_WORD1__MTYPE__SHIFT 0x0000001e
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT_MASK 0x3c000000L
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT__SHIFT 0x0000001a
+#define SQ_IMG_RSRC_WORD2__HEIGHT_MASK 0x0fffc000L
+#define SQ_IMG_RSRC_WORD2__HEIGHT__SHIFT 0x0000000e
+#define SQ_IMG_RSRC_WORD2__INTERLACED_MASK 0x80000000L
+#define SQ_IMG_RSRC_WORD2__INTERLACED__SHIFT 0x0000001f
+#define SQ_IMG_RSRC_WORD2__PERF_MOD_MASK 0x70000000L
+#define SQ_IMG_RSRC_WORD2__PERF_MOD__SHIFT 0x0000001c
+#define SQ_IMG_RSRC_WORD2__WIDTH_MASK 0x00003fffL
+#define SQ_IMG_RSRC_WORD2__WIDTH__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD3__ATC_MASK 0x08000000L
+#define SQ_IMG_RSRC_WORD3__ATC__SHIFT 0x0000001b
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL_MASK 0x0000f000L
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL__SHIFT 0x0000000c
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W_MASK 0x00000e00L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W__SHIFT 0x00000009
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X_MASK 0x00000007L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y_MASK 0x00000038L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y__SHIFT 0x00000003
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z_MASK 0x000001c0L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z__SHIFT 0x00000006
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL_MASK 0x000f0000L
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL__SHIFT 0x00000010
+#define SQ_IMG_RSRC_WORD3__MTYPE_MASK 0x04000000L
+#define SQ_IMG_RSRC_WORD3__MTYPE__SHIFT 0x0000001a
+#define SQ_IMG_RSRC_WORD3__POW2_PAD_MASK 0x02000000L
+#define SQ_IMG_RSRC_WORD3__POW2_PAD__SHIFT 0x00000019
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX_MASK 0x01f00000L
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD3__TYPE_MASK 0xf0000000L
+#define SQ_IMG_RSRC_WORD3__TYPE__SHIFT 0x0000001c
+#define SQ_IMG_RSRC_WORD4__DEPTH_MASK 0x00001fffL
+#define SQ_IMG_RSRC_WORD4__DEPTH__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD4__PITCH_MASK 0x07ffe000L
+#define SQ_IMG_RSRC_WORD4__PITCH__SHIFT 0x0000000d
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY_MASK 0x00001fffL
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY_MASK 0x03ffe000L
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY__SHIFT 0x0000000d
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID_MASK 0x000ff000L
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID__SHIFT 0x0000000c
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN_MASK 0x00100000L
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN_MASK 0x00000fffL
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD6__UNUNSED_MASK 0xffe00000L
+#define SQ_IMG_RSRC_WORD6__UNUNSED__SHIFT 0x00000015
+#define SQ_IMG_RSRC_WORD7__UNUNSED_MASK 0xffffffffL
+#define SQ_IMG_RSRC_WORD7__UNUNSED__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS_MASK 0x07e00000L
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS__SHIFT 0x00000015
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD_MASK 0x00070000L
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD__SHIFT 0x00000010
+#define SQ_IMG_SAMP_WORD0__CLAMP_X_MASK 0x00000007L
+#define SQ_IMG_SAMP_WORD0__CLAMP_X__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y_MASK 0x00000038L
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y__SHIFT 0x00000003
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z_MASK 0x000001c0L
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z__SHIFT 0x00000006
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC_MASK 0x00007000L
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC__SHIFT 0x0000000c
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP_MASK 0x10000000L
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE_MASK 0x60000000L
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE__SHIFT 0x0000001d
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA_MASK 0x00100000L
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA__SHIFT 0x00000014
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED_MASK 0x00008000L
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED__SHIFT 0x0000000f
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO_MASK 0x00000e00L
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO__SHIFT 0x00000009
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC_MASK 0x00080000L
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC__SHIFT 0x00000013
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD_MASK 0x08000000L
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD__SHIFT 0x0000001b
+#define SQ_IMG_SAMP_WORD1__MAX_LOD_MASK 0x00fff000L
+#define SQ_IMG_SAMP_WORD1__MAX_LOD__SHIFT 0x0000000c
+#define SQ_IMG_SAMP_WORD1__MIN_LOD_MASK 0x00000fffL
+#define SQ_IMG_SAMP_WORD1__MIN_LOD__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD1__PERF_MIP_MASK 0x0f000000L
+#define SQ_IMG_SAMP_WORD1__PERF_MIP__SHIFT 0x00000018
+#define SQ_IMG_SAMP_WORD1__PERF_Z_MASK 0xf0000000L
+#define SQ_IMG_SAMP_WORD1__PERF_Z__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL_MASK 0x20000000L
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL__SHIFT 0x0000001d
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX_MASK 0x40000000L
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX__SHIFT 0x0000001e
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_MASK 0x00003fffL
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC_MASK 0x000fc000L
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC__SHIFT 0x0000000e
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER_MASK 0x0c000000L
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER__SHIFT 0x0000001a
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP_MASK 0x10000000L
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER_MASK 0x00300000L
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER__SHIFT 0x00000014
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER_MASK 0x00c00000L
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER__SHIFT 0x00000016
+#define SQ_IMG_SAMP_WORD2__Z_FILTER_MASK 0x03000000L
+#define SQ_IMG_SAMP_WORD2__Z_FILTER__SHIFT 0x00000018
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR_MASK 0x00000fffL
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE_MASK 0xc0000000L
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE__SHIFT 0x0000001e
+#define SQ_IND_DATA__DATA_MASK 0xffffffffL
+#define SQ_IND_DATA__DATA__SHIFT 0x00000000
+#define SQ_IND_INDEX__AUTO_INCR_MASK 0x00001000L
+#define SQ_IND_INDEX__AUTO_INCR__SHIFT 0x0000000c
+#define SQ_IND_INDEX__FORCE_READ_MASK 0x00002000L
+#define SQ_IND_INDEX__FORCE_READ__SHIFT 0x0000000d
+#define SQ_IND_INDEX__INDEX_MASK 0xffff0000L
+#define SQ_IND_INDEX__INDEX__SHIFT 0x00000010
+#define SQ_IND_INDEX__READ_TIMEOUT_MASK 0x00004000L
+#define SQ_IND_INDEX__READ_TIMEOUT__SHIFT 0x0000000e
+#define SQ_IND_INDEX__SIMD_ID_MASK 0x00000030L
+#define SQ_IND_INDEX__SIMD_ID__SHIFT 0x00000004
+#define SQ_IND_INDEX__THREAD_ID_MASK 0x00000fc0L
+#define SQ_IND_INDEX__THREAD_ID__SHIFT 0x00000006
+#define SQ_IND_INDEX__UNINDEXED_MASK 0x00008000L
+#define SQ_IND_INDEX__UNINDEXED__SHIFT 0x0000000f
+#define SQ_IND_INDEX__WAVE_ID_MASK 0x0000000fL
+#define SQ_IND_INDEX__WAVE_ID__SHIFT 0x00000000
+#define SQ_INST__ENCODING_MASK 0xffffffffL
+#define SQ_INST__ENCODING__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP_MASK 0x00000010L
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP__SHIFT 0x00000004
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW_MASK 0x00000020L
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW__SHIFT 0x00000005
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW_MASK 0x00000040L
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW__SHIFT 0x00000006
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW_MASK 0x00000080L
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW__SHIFT 0x00000007
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP_MASK 0x00000008L
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP__SHIFT 0x00000003
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL_MASK 0x00000004L
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL__SHIFT 0x00000002
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_MASK 0x00000001L
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_AUTO__WLT_MASK 0x00000002L
+#define SQ_INTERRUPT_WORD_AUTO__WLT__SHIFT 0x00000001
+#define SQ_INTERRUPT_WORD_CMN__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_CMN__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_CMN__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_CMN__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID_MASK 0x00f00000L
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID__SHIFT 0x00000014
+#define SQ_INTERRUPT_WORD_WAVE__DATA_MASK 0x000000ffL
+#define SQ_INTERRUPT_WORD_WAVE__DATA__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_WAVE__PRIV_MASK 0x00000200L
+#define SQ_INTERRUPT_WORD_WAVE__PRIV__SHIFT 0x00000009
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID_MASK 0x01000000L
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID__SHIFT 0x00000018
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID_MASK 0x000c0000L
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID__SHIFT 0x00000012
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID_MASK 0x00003c00L
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID__SHIFT 0x0000000a
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID_MASK 0x0003c000L
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID__SHIFT 0x0000000e
+#define SQ_LB_CTR_CTRL__CLEAR_MASK 0x00000004L
+#define SQ_LB_CTR_CTRL__CLEAR__SHIFT 0x00000002
+#define SQ_LB_CTR_CTRL__LOAD_MASK 0x00000002L
+#define SQ_LB_CTR_CTRL__LOAD__SHIFT 0x00000001
+#define SQ_LB_CTR_CTRL__START_MASK 0x00000001L
+#define SQ_LB_CTR_CTRL__START__SHIFT 0x00000000
+#define SQ_LB_DATA_ALU_CYCLES__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_ALU_CYCLES__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_ALU_STALLS__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_ALU_STALLS__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_TEX_CYCLES__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_TEX_CYCLES__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_TEX_STALLS__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_TEX_STALLS__DATA__SHIFT 0x00000000
+#define SQ_MIMG_0__DA_MASK 0x00004000L
+#define SQ_MIMG_0__DA__SHIFT 0x0000000e
+#define SQ_MIMG_0__DMASK_MASK 0x00000f00L
+#define SQ_MIMG_0__DMASK__SHIFT 0x00000008
+#define SQ_MIMG_0__ENCODING_MASK 0xfc000000L
+#define SQ_MIMG_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MIMG_0__GLC_MASK 0x00002000L
+#define SQ_MIMG_0__GLC__SHIFT 0x0000000d
+#define SQ_MIMG_0__LWE_MASK 0x00020000L
+#define SQ_MIMG_0__LWE__SHIFT 0x00000011
+#define SQ_MIMG_0__OP_MASK 0x01fc0000L
+#define SQ_MIMG_0__OP__SHIFT 0x00000012
+#define SQ_MIMG_0__R128_MASK 0x00008000L
+#define SQ_MIMG_0__R128__SHIFT 0x0000000f
+#define SQ_MIMG_0__SLC_MASK 0x02000000L
+#define SQ_MIMG_0__SLC__SHIFT 0x00000019
+#define SQ_MIMG_0__TFE_MASK 0x00010000L
+#define SQ_MIMG_0__TFE__SHIFT 0x00000010
+#define SQ_MIMG_0__UNORM_MASK 0x00001000L
+#define SQ_MIMG_0__UNORM__SHIFT 0x0000000c
+#define SQ_MIMG_1__SRSRC_MASK 0x001f0000L
+#define SQ_MIMG_1__SRSRC__SHIFT 0x00000010
+#define SQ_MIMG_1__SSAMP_MASK 0x03e00000L
+#define SQ_MIMG_1__SSAMP__SHIFT 0x00000015
+#define SQ_MIMG_1__VADDR_MASK 0x000000ffL
+#define SQ_MIMG_1__VADDR__SHIFT 0x00000000
+#define SQ_MIMG_1__VDATA_MASK 0x0000ff00L
+#define SQ_MIMG_1__VDATA__SHIFT 0x00000008
+#define SQ_MTBUF_0__ADDR64_MASK 0x00008000L
+#define SQ_MTBUF_0__ADDR64__SHIFT 0x0000000f
+#define SQ_MTBUF_0__DFMT_MASK 0x00780000L
+#define SQ_MTBUF_0__DFMT__SHIFT 0x00000013
+#define SQ_MTBUF_0__ENCODING_MASK 0xfc000000L
+#define SQ_MTBUF_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MTBUF_0__GLC_MASK 0x00004000L
+#define SQ_MTBUF_0__GLC__SHIFT 0x0000000e
+#define SQ_MTBUF_0__IDXEN_MASK 0x00002000L
+#define SQ_MTBUF_0__IDXEN__SHIFT 0x0000000d
+#define SQ_MTBUF_0__NFMT_MASK 0x03800000L
+#define SQ_MTBUF_0__NFMT__SHIFT 0x00000017
+#define SQ_MTBUF_0__OFFEN_MASK 0x00001000L
+#define SQ_MTBUF_0__OFFEN__SHIFT 0x0000000c
+#define SQ_MTBUF_0__OFFSET_MASK 0x00000fffL
+#define SQ_MTBUF_0__OFFSET__SHIFT 0x00000000
+#define SQ_MTBUF_0__OP_MASK 0x00070000L
+#define SQ_MTBUF_0__OP__SHIFT 0x00000010
+#define SQ_MTBUF_1__SLC_MASK 0x00400000L
+#define SQ_MTBUF_1__SLC__SHIFT 0x00000016
+#define SQ_MTBUF_1__SOFFSET_MASK 0xff000000L
+#define SQ_MTBUF_1__SOFFSET__SHIFT 0x00000018
+#define SQ_MTBUF_1__SRSRC_MASK 0x001f0000L
+#define SQ_MTBUF_1__SRSRC__SHIFT 0x00000010
+#define SQ_MTBUF_1__TFE_MASK 0x00800000L
+#define SQ_MTBUF_1__TFE__SHIFT 0x00000017
+#define SQ_MTBUF_1__VADDR_MASK 0x000000ffL
+#define SQ_MTBUF_1__VADDR__SHIFT 0x00000000
+#define SQ_MTBUF_1__VDATA_MASK 0x0000ff00L
+#define SQ_MTBUF_1__VDATA__SHIFT 0x00000008
+#define SQ_MUBUF_0__ADDR64_MASK 0x00008000L
+#define SQ_MUBUF_0__ADDR64__SHIFT 0x0000000f
+#define SQ_MUBUF_0__ENCODING_MASK 0xfc000000L
+#define SQ_MUBUF_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MUBUF_0__GLC_MASK 0x00004000L
+#define SQ_MUBUF_0__GLC__SHIFT 0x0000000e
+#define SQ_MUBUF_0__IDXEN_MASK 0x00002000L
+#define SQ_MUBUF_0__IDXEN__SHIFT 0x0000000d
+#define SQ_MUBUF_0__LDS_MASK 0x00010000L
+#define SQ_MUBUF_0__LDS__SHIFT 0x00000010
+#define SQ_MUBUF_0__OFFEN_MASK 0x00001000L
+#define SQ_MUBUF_0__OFFEN__SHIFT 0x0000000c
+#define SQ_MUBUF_0__OFFSET_MASK 0x00000fffL
+#define SQ_MUBUF_0__OFFSET__SHIFT 0x00000000
+#define SQ_MUBUF_0__OP_MASK 0x01fc0000L
+#define SQ_MUBUF_0__OP__SHIFT 0x00000012
+#define SQ_MUBUF_1__SLC_MASK 0x00400000L
+#define SQ_MUBUF_1__SLC__SHIFT 0x00000016
+#define SQ_MUBUF_1__SOFFSET_MASK 0xff000000L
+#define SQ_MUBUF_1__SOFFSET__SHIFT 0x00000018
+#define SQ_MUBUF_1__SRSRC_MASK 0x001f0000L
+#define SQ_MUBUF_1__SRSRC__SHIFT 0x00000010
+#define SQ_MUBUF_1__TFE_MASK 0x00800000L
+#define SQ_MUBUF_1__TFE__SHIFT 0x00000017
+#define SQ_MUBUF_1__VADDR_MASK 0x000000ffL
+#define SQ_MUBUF_1__VADDR__SHIFT 0x00000000
+#define SQ_MUBUF_1__VDATA_MASK 0x0000ff00L
+#define SQ_MUBUF_1__VDATA__SHIFT 0x00000008
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN_MASK 0x00000001L
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN__SHIFT 0x00000000
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE_MASK 0x00001f00L
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE__SHIFT 0x00000008
+#define SQ_PERFCOUNTER_CTRL__CS_EN_MASK 0x00000040L
+#define SQ_PERFCOUNTER_CTRL__CS_EN__SHIFT 0x00000006
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH_MASK 0x00002000L
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH__SHIFT 0x0000000d
+#define SQ_PERFCOUNTER_CTRL__ES_EN_MASK 0x00000008L
+#define SQ_PERFCOUNTER_CTRL__ES_EN__SHIFT 0x00000003
+#define SQ_PERFCOUNTER_CTRL__GS_EN_MASK 0x00000004L
+#define SQ_PERFCOUNTER_CTRL__GS_EN__SHIFT 0x00000002
+#define SQ_PERFCOUNTER_CTRL__HS_EN_MASK 0x00000010L
+#define SQ_PERFCOUNTER_CTRL__HS_EN__SHIFT 0x00000004
+#define SQ_PERFCOUNTER_CTRL__LS_EN_MASK 0x00000020L
+#define SQ_PERFCOUNTER_CTRL__LS_EN__SHIFT 0x00000005
+#define SQ_PERFCOUNTER_CTRL__PS_EN_MASK 0x00000001L
+#define SQ_PERFCOUNTER_CTRL__PS_EN__SHIFT 0x00000000
+#define SQ_PERFCOUNTER_CTRL__VS_EN_MASK 0x00000002L
+#define SQ_PERFCOUNTER_CTRL__VS_EN__SHIFT 0x00000001
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000L
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x0000001b
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK 0x00003fffL
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA__SHIFT 0x00000000
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK 0x03ff0000L
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x00000010
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK_MASK 0x80000000L
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK__SHIFT 0x0000001f
+#define SQ_POWER_THROTTLE__MAX_POWER_MASK 0x3fff0000L
+#define SQ_POWER_THROTTLE__MAX_POWER__SHIFT 0x00000010
+#define SQ_POWER_THROTTLE__MIN_POWER_MASK 0x00003fffL
+#define SQ_POWER_THROTTLE__MIN_POWER__SHIFT 0x00000000
+#define SQ_POWER_THROTTLE__PHASE_OFFSET_MASK 0xc0000000L
+#define SQ_POWER_THROTTLE__PHASE_OFFSET__SHIFT 0x0000001e
+#define SQ_RANDOM_WAVE_PRI__RET_MASK 0x0000007fL
+#define SQ_RANDOM_WAVE_PRI__RET__SHIFT 0x00000000
+#define SQ_RANDOM_WAVE_PRI__RNG_MASK 0x001ffc00L
+#define SQ_RANDOM_WAVE_PRI__RNG__SHIFT 0x0000000a
+#define SQ_RANDOM_WAVE_PRI__RUI_MASK 0x00000380L
+#define SQ_RANDOM_WAVE_PRI__RUI__SHIFT 0x00000007
+#define SQ_REG_CREDITS__CMD_CREDITS_MASK 0x00000f00L
+#define SQ_REG_CREDITS__CMD_CREDITS__SHIFT 0x00000008
+#define SQ_REG_CREDITS__CMD_OVERFLOW_MASK 0x80000000L
+#define SQ_REG_CREDITS__CMD_OVERFLOW__SHIFT 0x0000001f
+#define SQ_REG_CREDITS__IMMED_OVERFLOW_MASK 0x40000000L
+#define SQ_REG_CREDITS__IMMED_OVERFLOW__SHIFT 0x0000001e
+#define SQ_REG_CREDITS__REG_BUSY_MASK 0x10000000L
+#define SQ_REG_CREDITS__REG_BUSY__SHIFT 0x0000001c
+#define SQ_REG_CREDITS__SRBM_CREDITS_MASK 0x0000003fL
+#define SQ_REG_CREDITS__SRBM_CREDITS__SHIFT 0x00000000
+#define SQ_REG_CREDITS__SRBM_OVERFLOW_MASK 0x20000000L
+#define SQ_REG_CREDITS__SRBM_OVERFLOW__SHIFT 0x0000001d
+#define SQ_SEC_CNT__LDS_SEC_MASK 0x0000003fL
+#define SQ_SEC_CNT__LDS_SEC__SHIFT 0x00000000
+#define SQ_SEC_CNT__SGPR_SEC_MASK 0x00001f00L
+#define SQ_SEC_CNT__SGPR_SEC__SHIFT 0x00000008
+#define SQ_SEC_CNT__VGPR_SEC_MASK 0x01ff0000L
+#define SQ_SEC_CNT__VGPR_SEC__SHIFT 0x00000010
+#define SQ_SMRD__ENCODING_MASK 0xf8000000L
+#define SQ_SMRD__ENCODING__SHIFT 0x0000001b
+#define SQ_SMRD__IMM_MASK 0x00000100L
+#define SQ_SMRD__IMM__SHIFT 0x00000008
+#define SQ_SMRD__OFFSET_MASK 0x000000ffL
+#define SQ_SMRD__OFFSET__SHIFT 0x00000000
+#define SQ_SMRD__OP_MASK 0x07c00000L
+#define SQ_SMRD__OP__SHIFT 0x00000016
+#define SQ_SMRD__SBASE_MASK 0x00007e00L
+#define SQ_SMRD__SBASE__SHIFT 0x00000009
+#define SQ_SMRD__SDST_MASK 0x003f8000L
+#define SQ_SMRD__SDST__SHIFT 0x0000000f
+#define SQ_SOP1__ENCODING_MASK 0xff800000L
+#define SQ_SOP1__ENCODING__SHIFT 0x00000017
+#define SQ_SOP1__OP_MASK 0x0000ff00L
+#define SQ_SOP1__OP__SHIFT 0x00000008
+#define SQ_SOP1__SDST_MASK 0x007f0000L
+#define SQ_SOP1__SDST__SHIFT 0x00000010
+#define SQ_SOP1__SSRC0_MASK 0x000000ffL
+#define SQ_SOP1__SSRC0__SHIFT 0x00000000
+#define SQ_SOP2__ENCODING_MASK 0xc0000000L
+#define SQ_SOP2__ENCODING__SHIFT 0x0000001e
+#define SQ_SOP2__OP_MASK 0x3f800000L
+#define SQ_SOP2__OP__SHIFT 0x00000017
+#define SQ_SOP2__SDST_MASK 0x007f0000L
+#define SQ_SOP2__SDST__SHIFT 0x00000010
+#define SQ_SOP2__SSRC0_MASK 0x000000ffL
+#define SQ_SOP2__SSRC0__SHIFT 0x00000000
+#define SQ_SOP2__SSRC1_MASK 0x0000ff00L
+#define SQ_SOP2__SSRC1__SHIFT 0x00000008
+#define SQ_SOPC__ENCODING_MASK 0xff800000L
+#define SQ_SOPC__ENCODING__SHIFT 0x00000017
+#define SQ_SOPC__OP_MASK 0x007f0000L
+#define SQ_SOPC__OP__SHIFT 0x00000010
+#define SQ_SOPC__SSRC0_MASK 0x000000ffL
+#define SQ_SOPC__SSRC0__SHIFT 0x00000000
+#define SQ_SOPC__SSRC1_MASK 0x0000ff00L
+#define SQ_SOPC__SSRC1__SHIFT 0x00000008
+#define SQ_SOPK__ENCODING_MASK 0xf0000000L
+#define SQ_SOPK__ENCODING__SHIFT 0x0000001c
+#define SQ_SOPK__OP_MASK 0x0f800000L
+#define SQ_SOPK__OP__SHIFT 0x00000017
+#define SQ_SOPK__SDST_MASK 0x007f0000L
+#define SQ_SOPK__SDST__SHIFT 0x00000010
+#define SQ_SOPK__SIMM16_MASK 0x0000ffffL
+#define SQ_SOPK__SIMM16__SHIFT 0x00000000
+#define SQ_SOPP__ENCODING_MASK 0xff800000L
+#define SQ_SOPP__ENCODING__SHIFT 0x00000017
+#define SQ_SOPP__OP_MASK 0x007f0000L
+#define SQ_SOPP__OP__SHIFT 0x00000010
+#define SQ_SOPP__SIMM16_MASK 0x0000ffffL
+#define SQ_SOPP__SIMM16__SHIFT 0x00000000
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0x0000ffffL
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x00000000
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000L
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_BASE2__ATC_MASK 0x00000010L
+#define SQ_THREAD_TRACE_BASE2__ATC__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_BASE__ADDR_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_BASE__ADDR__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_CNTR__CNTR_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_CNTR__CNTR__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER_MASK 0x80000000L
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_HIWATER__HIWATER_MASK 0x00000007L
+#define SQ_THREAD_TRACE_HIWATER__HIWATER__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MASK__CU_SEL_MASK 0x0000001fL
+#define SQ_THREAD_TRACE_MASK__CU_SEL__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MASK__RANDOM_SEED_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_MASK__RANDOM_SEED__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN_MASK 0x00000080L
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN__SHIFT 0x00000007
+#define SQ_THREAD_TRACE_MASK__SH_SEL_MASK 0x00000020L
+#define SQ_THREAD_TRACE_MASK__SH_SEL__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN_MASK 0x00004000L
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN_MASK 0x00008000L
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK_MASK 0x00003000L
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN_MASK 0x02000000L
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN__SHIFT 0x00000019
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE_MASK 0x01800000L
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE__SHIFT 0x00000017
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN_MASK 0x40000000L
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK_MASK 0x18000000L
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK__SHIFT 0x0000001b
+#define SQ_THREAD_TRACE_MODE__MASK_CS_MASK 0x001c0000L
+#define SQ_THREAD_TRACE_MODE__MASK_CS__SHIFT 0x00000012
+#define SQ_THREAD_TRACE_MODE__MASK_ES_MASK 0x00000e00L
+#define SQ_THREAD_TRACE_MODE__MASK_ES__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_MODE__MASK_GS_MASK 0x000001c0L
+#define SQ_THREAD_TRACE_MODE__MASK_GS__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_MODE__MASK_HS_MASK 0x00007000L
+#define SQ_THREAD_TRACE_MODE__MASK_HS__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_MODE__MASK_LS_MASK 0x00038000L
+#define SQ_THREAD_TRACE_MODE__MASK_LS__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_MODE__MASK_PS_MASK 0x00000007L
+#define SQ_THREAD_TRACE_MODE__MASK_PS__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MODE__MASK_VS_MASK 0x00000038L
+#define SQ_THREAD_TRACE_MODE__MASK_VS__SHIFT 0x00000003
+#define SQ_THREAD_TRACE_MODE__MODE_MASK 0x00600000L
+#define SQ_THREAD_TRACE_MODE__MODE__SHIFT 0x00000015
+#define SQ_THREAD_TRACE_MODE__PRIV_MASK 0x04000000L
+#define SQ_THREAD_TRACE_MODE__PRIV__SHIFT 0x0000001a
+#define SQ_THREAD_TRACE_MODE__TEST_MODE_MASK 0x20000000L
+#define SQ_THREAD_TRACE_MODE__TEST_MODE__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_MODE__WRAP_MASK 0x80000000L
+#define SQ_THREAD_TRACE_MODE__WRAP__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_SIZE__SIZE_MASK 0x003fffffL
+#define SQ_THREAD_TRACE_SIZE__SIZE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_STATUS__BUSY_MASK 0x40000000L
+#define SQ_THREAD_TRACE_STATUS__BUSY__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE_MASK 0x00070000L
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING_MASK 0x00000007L
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_STATUS__FULL_MASK 0x80000000L
+#define SQ_THREAD_TRACE_STATUS__FULL__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF_MASK 0x20000000L
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL_MASK 0x01000000L
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL__SHIFT 0x00000018
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK_MASK 0x00ff0000L
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_0__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_0__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_1__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_1__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_2__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_2__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_3__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_3__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE_MASK 0x0000fc00L
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE_MASK 0x000001c0L
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE_MASK 0x0000f000L
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID_MASK 0x00000600L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID_MASK 0x000001e0L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI_MASK 0x00ffffffL
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID_MASK 0x00000600L
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_INST__SIZE_MASK 0x00000800L
+#define SQ_THREAD_TRACE_WORD_INST__SIZE__SHIFT 0x0000000b
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID_MASK 0x000001e0L
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0_MASK 0x00000300L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0__SHIFT 0x00000008
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1_MASK 0x00000c00L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2_MASK 0x00003000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4_MASK 0x00030000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5_MASK 0x000c0000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5__SHIFT 0x00000012
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6_MASK 0x00300000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6__SHIFT 0x00000014
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7_MASK 0x00c00000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7__SHIFT 0x00000016
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8_MASK 0x03000000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8__SHIFT 0x00000018
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9_MASK 0x0c000000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9__SHIFT 0x0000001a
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID_MASK 0x00000060L
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE_MASK 0x000000c0L
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0_MASK 0x01fff000L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO_MASK 0xfe000000L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO__SHIFT 0x00000019
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK_MASK 0x00000c00L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI_MASK 0x0000003fL
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2_MASK 0x0007ffc0L
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3_MASK 0xfff80000L
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3__SHIFT 0x00000013
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID_MASK 0x00000180L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID__SHIFT 0x00000007
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID_MASK 0x00000060L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV_MASK 0x00000200L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP_MASK 0x00008000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV_MASK 0x00004000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE_MASK 0x00001c00L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT_MASK 0x1fc00000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT__SHIFT 0x00000016
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER_MASK 0x001f0000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID_MASK 0xe0000000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED_MASK 0x00200000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED__SHIFT 0x00000015
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET_MASK 0xc0000000L
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_WPTR__WPTR_MASK 0x3fffffffL
+#define SQ_THREAD_TRACE_WPTR__WPTR__SHIFT 0x00000000
+#define SQ_TIME_HI__TIME_MASK 0xffffffffL
+#define SQ_TIME_HI__TIME__SHIFT 0x00000000
+#define SQ_TIME_LO__TIME_MASK 0xffffffffL
+#define SQ_TIME_LO__TIME__SHIFT 0x00000000
+#define SQ_VINTRP__ATTRCHAN_MASK 0x00000300L
+#define SQ_VINTRP__ATTRCHAN__SHIFT 0x00000008
+#define SQ_VINTRP__ATTR_MASK 0x0000fc00L
+#define SQ_VINTRP__ATTR__SHIFT 0x0000000a
+#define SQ_VINTRP__ENCODING_MASK 0xfc000000L
+#define SQ_VINTRP__ENCODING__SHIFT 0x0000001a
+#define SQ_VINTRP__OP_MASK 0x00030000L
+#define SQ_VINTRP__OP__SHIFT 0x00000010
+#define SQ_VINTRP__VDST_MASK 0x03fc0000L
+#define SQ_VINTRP__VDST__SHIFT 0x00000012
+#define SQ_VINTRP__VSRC_MASK 0x000000ffL
+#define SQ_VINTRP__VSRC__SHIFT 0x00000000
+#define SQ_VOP1__ENCODING_MASK 0xfe000000L
+#define SQ_VOP1__ENCODING__SHIFT 0x00000019
+#define SQ_VOP1__OP_MASK 0x0001fe00L
+#define SQ_VOP1__OP__SHIFT 0x00000009
+#define SQ_VOP1__SRC0_MASK 0x000001ffL
+#define SQ_VOP1__SRC0__SHIFT 0x00000000
+#define SQ_VOP1__VDST_MASK 0x01fe0000L
+#define SQ_VOP1__VDST__SHIFT 0x00000011
+#define SQ_VOP2__ENCODING_MASK 0x80000000L
+#define SQ_VOP2__ENCODING__SHIFT 0x0000001f
+#define SQ_VOP2__OP_MASK 0x7e000000L
+#define SQ_VOP2__OP__SHIFT 0x00000019
+#define SQ_VOP2__SRC0_MASK 0x000001ffL
+#define SQ_VOP2__SRC0__SHIFT 0x00000000
+#define SQ_VOP2__VDST_MASK 0x01fe0000L
+#define SQ_VOP2__VDST__SHIFT 0x00000011
+#define SQ_VOP2__VSRC1_MASK 0x0001fe00L
+#define SQ_VOP2__VSRC1__SHIFT 0x00000009
+#define SQ_VOP3_0__ABS_MASK 0x00000700L
+#define SQ_VOP3_0__ABS__SHIFT 0x00000008
+#define SQ_VOP3_0__CLAMP_MASK 0x00000800L
+#define SQ_VOP3_0__CLAMP__SHIFT 0x0000000b
+#define SQ_VOP3_0__ENCODING_MASK 0xfc000000L
+#define SQ_VOP3_0__ENCODING__SHIFT 0x0000001a
+#define SQ_VOP3_0__OP_MASK 0x03fe0000L
+#define SQ_VOP3_0__OP__SHIFT 0x00000011
+#define SQ_VOP3_0_SDST_ENC__ENCODING_MASK 0xfc000000L
+#define SQ_VOP3_0_SDST_ENC__ENCODING__SHIFT 0x0000001a
+#define SQ_VOP3_0_SDST_ENC__OP_MASK 0x03fe0000L
+#define SQ_VOP3_0_SDST_ENC__OP__SHIFT 0x00000011
+#define SQ_VOP3_0_SDST_ENC__SDST_MASK 0x00007f00L
+#define SQ_VOP3_0_SDST_ENC__SDST__SHIFT 0x00000008
+#define SQ_VOP3_0_SDST_ENC__VDST_MASK 0x000000ffL
+#define SQ_VOP3_0_SDST_ENC__VDST__SHIFT 0x00000000
+#define SQ_VOP3_0__VDST_MASK 0x000000ffL
+#define SQ_VOP3_0__VDST__SHIFT 0x00000000
+#define SQ_VOP3_1__NEG_MASK 0xe0000000L
+#define SQ_VOP3_1__NEG__SHIFT 0x0000001d
+#define SQ_VOP3_1__OMOD_MASK 0x18000000L
+#define SQ_VOP3_1__OMOD__SHIFT 0x0000001b
+#define SQ_VOP3_1__SRC0_MASK 0x000001ffL
+#define SQ_VOP3_1__SRC0__SHIFT 0x00000000
+#define SQ_VOP3_1__SRC1_MASK 0x0003fe00L
+#define SQ_VOP3_1__SRC1__SHIFT 0x00000009
+#define SQ_VOP3_1__SRC2_MASK 0x07fc0000L
+#define SQ_VOP3_1__SRC2__SHIFT 0x00000012
+#define SQ_VOPC__ENCODING_MASK 0xfe000000L
+#define SQ_VOPC__ENCODING__SHIFT 0x00000019
+#define SQ_VOPC__OP_MASK 0x01fe0000L
+#define SQ_VOPC__OP__SHIFT 0x00000011
+#define SQ_VOPC__SRC0_MASK 0x000001ffL
+#define SQ_VOPC__SRC0__SHIFT 0x00000000
+#define SQ_VOPC__VSRC1_MASK 0x0001fe00L
+#define SQ_VOPC__VSRC1__SHIFT 0x00000009
+#define SQ_WAVE_EXEC_HI__EXEC_HI_MASK 0xffffffffL
+#define SQ_WAVE_EXEC_HI__EXEC_HI__SHIFT 0x00000000
+#define SQ_WAVE_EXEC_LO__EXEC_LO_MASK 0xffffffffL
+#define SQ_WAVE_EXEC_LO__EXEC_LO__SHIFT 0x00000000
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE_MASK 0x003f0000L
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE__SHIFT 0x00000010
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE_MASK 0x0f000000L
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE__SHIFT 0x00000018
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE_MASK 0x0000003fL
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE__SHIFT 0x00000000
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE_MASK 0x00003f00L
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE__SHIFT 0x00000008
+#define SQ_WAVE_HW_ID__CU_ID_MASK 0x00000f00L
+#define SQ_WAVE_HW_ID__CU_ID__SHIFT 0x00000008
+#define SQ_WAVE_HW_ID__ME_ID_MASK 0xc0000000L
+#define SQ_WAVE_HW_ID__ME_ID__SHIFT 0x0000001e
+#define SQ_WAVE_HW_ID__PIPE_ID_MASK 0x000000c0L
+#define SQ_WAVE_HW_ID__PIPE_ID__SHIFT 0x00000006
+#define SQ_WAVE_HW_ID__QUEUE_ID_MASK 0x07000000L
+#define SQ_WAVE_HW_ID__QUEUE_ID__SHIFT 0x00000018
+#define SQ_WAVE_HW_ID__SE_ID_MASK 0x00002000L
+#define SQ_WAVE_HW_ID__SE_ID__SHIFT 0x0000000d
+#define SQ_WAVE_HW_ID__SH_ID_MASK 0x00001000L
+#define SQ_WAVE_HW_ID__SH_ID__SHIFT 0x0000000c
+#define SQ_WAVE_HW_ID__SIMD_ID_MASK 0x00000030L
+#define SQ_WAVE_HW_ID__SIMD_ID__SHIFT 0x00000004
+#define SQ_WAVE_HW_ID__STATE_ID_MASK 0x38000000L
+#define SQ_WAVE_HW_ID__STATE_ID__SHIFT 0x0000001b
+#define SQ_WAVE_HW_ID__TG_ID_MASK 0x000f0000L
+#define SQ_WAVE_HW_ID__TG_ID__SHIFT 0x00000010
+#define SQ_WAVE_HW_ID__VM_ID_MASK 0x00f00000L
+#define SQ_WAVE_HW_ID__VM_ID__SHIFT 0x00000014
+#define SQ_WAVE_HW_ID__WAVE_ID_MASK 0x0000000fL
+#define SQ_WAVE_HW_ID__WAVE_ID__SHIFT 0x00000000
+#define SQ_WAVE_IB_DBG0__ECC_ST_MASK 0x00c00000L
+#define SQ_WAVE_IB_DBG0__ECC_ST__SHIFT 0x00000016
+#define SQ_WAVE_IB_DBG0__HYB_CNT_MASK 0x06000000L
+#define SQ_WAVE_IB_DBG0__HYB_CNT__SHIFT 0x00000019
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR_MASK 0x00000300L
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR__SHIFT 0x00000008
+#define SQ_WAVE_IB_DBG0__IBUF_ST_MASK 0x00000007L
+#define SQ_WAVE_IB_DBG0__IBUF_ST__SHIFT 0x00000000
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR_MASK 0x00000c00L
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR__SHIFT 0x0000000a
+#define SQ_WAVE_IB_DBG0__INST_STR_ST_MASK 0x00070000L
+#define SQ_WAVE_IB_DBG0__INST_STR_ST__SHIFT 0x00000010
+#define SQ_WAVE_IB_DBG0__IS_HYB_MASK 0x01000000L
+#define SQ_WAVE_IB_DBG0__IS_HYB__SHIFT 0x00000018
+#define SQ_WAVE_IB_DBG0__KILL_MASK 0x08000000L
+#define SQ_WAVE_IB_DBG0__KILL__SHIFT 0x0000001b
+#define SQ_WAVE_IB_DBG0__MISC_CNT_MASK 0x00380000L
+#define SQ_WAVE_IB_DBG0__MISC_CNT__SHIFT 0x00000013
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH_MASK 0x10000000L
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH__SHIFT 0x0000001c
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW_MASK 0x00000010L
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW__SHIFT 0x00000004
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT_MASK 0x000000e0L
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT__SHIFT 0x00000005
+#define SQ_WAVE_IB_DBG0__PC_INVALID_MASK 0x00000008L
+#define SQ_WAVE_IB_DBG0__PC_INVALID__SHIFT 0x00000003
+#define SQ_WAVE_IB_STS__EXP_CNT_MASK 0x00000070L
+#define SQ_WAVE_IB_STS__EXP_CNT__SHIFT 0x00000004
+#define SQ_WAVE_IB_STS__LGKM_CNT_MASK 0x00001f00L
+#define SQ_WAVE_IB_STS__LGKM_CNT__SHIFT 0x00000008
+#define SQ_WAVE_IB_STS__VALU_CNT_MASK 0x0000e000L
+#define SQ_WAVE_IB_STS__VALU_CNT__SHIFT 0x0000000d
+#define SQ_WAVE_IB_STS__VM_CNT_MASK 0x0000000fL
+#define SQ_WAVE_IB_STS__VM_CNT__SHIFT 0x00000000
+#define SQ_WAVE_INST_DW0__INST_DW0_MASK 0xffffffffL
+#define SQ_WAVE_INST_DW0__INST_DW0__SHIFT 0x00000000
+#define SQ_WAVE_INST_DW1__INST_DW1_MASK 0xffffffffL
+#define SQ_WAVE_INST_DW1__INST_DW1__SHIFT 0x00000000
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE_MASK 0x000000ffL
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE__SHIFT 0x00000000
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE_MASK 0x001ff000L
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE__SHIFT 0x0000000c
+#define SQ_WAVE_M0__M0_MASK 0xffffffffL
+#define SQ_WAVE_M0__M0__SHIFT 0x00000000
+#define SQ_WAVE_MODE__CSP_MASK 0xe0000000L
+#define SQ_WAVE_MODE__CSP__SHIFT 0x0000001d
+#define SQ_WAVE_MODE__DEBUG_EN_MASK 0x00000800L
+#define SQ_WAVE_MODE__DEBUG_EN__SHIFT 0x0000000b
+#define SQ_WAVE_MODE__DX10_CLAMP_MASK 0x00000100L
+#define SQ_WAVE_MODE__DX10_CLAMP__SHIFT 0x00000008
+#define SQ_WAVE_MODE__EXCP_EN_MASK 0x0007f000L
+#define SQ_WAVE_MODE__EXCP_EN__SHIFT 0x0000000c
+#define SQ_WAVE_MODE__FP_DENORM_MASK 0x000000f0L
+#define SQ_WAVE_MODE__FP_DENORM__SHIFT 0x00000004
+#define SQ_WAVE_MODE__FP_ROUND_MASK 0x0000000fL
+#define SQ_WAVE_MODE__FP_ROUND__SHIFT 0x00000000
+#define SQ_WAVE_MODE__IEEE_MASK 0x00000200L
+#define SQ_WAVE_MODE__IEEE__SHIFT 0x00000009
+#define SQ_WAVE_MODE__LOD_CLAMPED_MASK 0x00000400L
+#define SQ_WAVE_MODE__LOD_CLAMPED__SHIFT 0x0000000a
+#define SQ_WAVE_MODE__VSKIP_MASK 0x10000000L
+#define SQ_WAVE_MODE__VSKIP__SHIFT 0x0000001c
+#define SQ_WAVE_PC_HI__PC_HI_MASK 0x000000ffL
+#define SQ_WAVE_PC_HI__PC_HI__SHIFT 0x00000000
+#define SQ_WAVE_PC_LO__PC_LO_MASK 0xffffffffL
+#define SQ_WAVE_PC_LO__PC_LO__SHIFT 0x00000000
+#define SQ_WAVE_STATUS__COND_DBG_SYS_MASK 0x00200000L
+#define SQ_WAVE_STATUS__COND_DBG_SYS__SHIFT 0x00000015
+#define SQ_WAVE_STATUS__COND_DBG_USER_MASK 0x00100000L
+#define SQ_WAVE_STATUS__COND_DBG_USER__SHIFT 0x00000014
+#define SQ_WAVE_STATUS__DATA_ATC_MASK 0x00400000L
+#define SQ_WAVE_STATUS__DATA_ATC__SHIFT 0x00000016
+#define SQ_WAVE_STATUS__DISPATCH_CACHE_CTRL_MASK 0x07000000L
+#define SQ_WAVE_STATUS__DISPATCH_CACHE_CTRL__SHIFT 0x00000018
+#define SQ_WAVE_STATUS__ECC_ERR_MASK 0x00020000L
+#define SQ_WAVE_STATUS__ECC_ERR__SHIFT 0x00000011
+#define SQ_WAVE_STATUS__EXECZ_MASK 0x00000200L
+#define SQ_WAVE_STATUS__EXECZ__SHIFT 0x00000009
+#define SQ_WAVE_STATUS__EXPORT_RDY_MASK 0x00000100L
+#define SQ_WAVE_STATUS__EXPORT_RDY__SHIFT 0x00000008
+#define SQ_WAVE_STATUS__HALT_MASK 0x00002000L
+#define SQ_WAVE_STATUS__HALT__SHIFT 0x0000000d
+#define SQ_WAVE_STATUS__IN_BARRIER_MASK 0x00001000L
+#define SQ_WAVE_STATUS__IN_BARRIER__SHIFT 0x0000000c
+#define SQ_WAVE_STATUS__INST_ATC_MASK 0x00800000L
+#define SQ_WAVE_STATUS__INST_ATC__SHIFT 0x00000017
+#define SQ_WAVE_STATUS__IN_TG_MASK 0x00000800L
+#define SQ_WAVE_STATUS__IN_TG__SHIFT 0x0000000b
+#define SQ_WAVE_STATUS__MUST_EXPORT_MASK 0x08000000L
+#define SQ_WAVE_STATUS__MUST_EXPORT__SHIFT 0x0000001b
+#define SQ_WAVE_STATUS__PERF_EN_MASK 0x00080000L
+#define SQ_WAVE_STATUS__PERF_EN__SHIFT 0x00000013
+#define SQ_WAVE_STATUS__PRIV_MASK 0x00000020L
+#define SQ_WAVE_STATUS__PRIV__SHIFT 0x00000005
+#define SQ_WAVE_STATUS__SCC_MASK 0x00000001L
+#define SQ_WAVE_STATUS__SCC__SHIFT 0x00000000
+#define SQ_WAVE_STATUS__SKIP_EXPORT_MASK 0x00040000L
+#define SQ_WAVE_STATUS__SKIP_EXPORT__SHIFT 0x00000012
+#define SQ_WAVE_STATUS__SPI_PRIO_MASK 0x00000006L
+#define SQ_WAVE_STATUS__SPI_PRIO__SHIFT 0x00000001
+#define SQ_WAVE_STATUS__TRAP_EN_MASK 0x00000040L
+#define SQ_WAVE_STATUS__TRAP_EN__SHIFT 0x00000006
+#define SQ_WAVE_STATUS__TRAP_MASK 0x00004000L
+#define SQ_WAVE_STATUS__TRAP__SHIFT 0x0000000e
+#define SQ_WAVE_STATUS__TTRACE_CU_EN_MASK 0x00008000L
+#define SQ_WAVE_STATUS__TTRACE_CU_EN__SHIFT 0x0000000f
+#define SQ_WAVE_STATUS__TTRACE_EN_MASK 0x00000080L
+#define SQ_WAVE_STATUS__TTRACE_EN__SHIFT 0x00000007
+#define SQ_WAVE_STATUS__VALID_MASK 0x00010000L
+#define SQ_WAVE_STATUS__VALID__SHIFT 0x00000010
+#define SQ_WAVE_STATUS__VCCZ_MASK 0x00000400L
+#define SQ_WAVE_STATUS__VCCZ__SHIFT 0x0000000a
+#define SQ_WAVE_STATUS__WAVE_PRIO_MASK 0x00000018L
+#define SQ_WAVE_STATUS__WAVE_PRIO__SHIFT 0x00000003
+#define SQ_WAVE_TBA_HI__ADDR_HI_MASK 0x000000ffL
+#define SQ_WAVE_TBA_HI__ADDR_HI__SHIFT 0x00000000
+#define SQ_WAVE_TBA_LO__ADDR_LO_MASK 0xffffffffL
+#define SQ_WAVE_TBA_LO__ADDR_LO__SHIFT 0x00000000
+#define SQ_WAVE_TMA_HI__ADDR_HI_MASK 0x000000ffL
+#define SQ_WAVE_TMA_HI__ADDR_HI__SHIFT 0x00000000
+#define SQ_WAVE_TMA_LO__ADDR_LO_MASK 0xffffffffL
+#define SQ_WAVE_TMA_LO__ADDR_LO__SHIFT 0x00000000
+#define SQ_WAVE_TRAPSTS__DP_RATE_MASK 0xe0000000L
+#define SQ_WAVE_TRAPSTS__DP_RATE__SHIFT 0x0000001d
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE_MASK 0x003f0000L
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE__SHIFT 0x00000010
+#define SQ_WAVE_TRAPSTS__EXCP_MASK 0x0000007fL
+#define SQ_WAVE_TRAPSTS__EXCP__SHIFT 0x00000000
+#define SQ_WAVE_TTMP0__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP0__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP10__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP10__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP11__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP11__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP1__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP1__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP2__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP2__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP3__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP3__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP4__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP4__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP5__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP5__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP6__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP6__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP7__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP7__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP8__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP8__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP9__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP9__DATA__SHIFT 0x00000000
+#define SX_DEBUG_1__DEBUG_DATA_MASK 0xffffff80L
+#define SX_DEBUG_1__DEBUG_DATA__SHIFT 0x00000007
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT_MASK 0x0000007fL
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY_MASK 0x80000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY_MASK 0x40000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY_MASK 0x20000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY_MASK 0x10000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY_MASK 0x08000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY_MASK 0x04000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY_MASK 0x02000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY__SHIFT 0x00000019
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID_MASK 0x01000000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID_MASK 0x00200000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID_MASK 0x00040000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID_MASK 0x00008000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0_MASK 0x00000400L
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE_MASK 0x00000800L
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0_MASK 0x00000080L
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE_MASK 0x00000100L
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0_MASK 0x00000010L
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE_MASK 0x00000020L
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0_MASK 0x00000002L
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE_MASK 0x00000004L
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY_MASK 0x80000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY_MASK 0x40000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY_MASK 0x20000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY_MASK 0x10000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY_MASK 0x08000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY_MASK 0x04000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY_MASK 0x02000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY__SHIFT 0x00000019
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY_MASK 0x01000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY_MASK 0x00200000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY_MASK 0x01000000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY_MASK 0x00200000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_4__RESERVED_MASK 0xfe000000L
+#define SX_DEBUG_BUSY_4__RESERVED__SHIFT 0x00000019
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL_MASK 0x80000000L
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL_MASK 0x40000000L
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY__PA_SX_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY__PA_SX_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY__PCCMD_VALID_MASK 0x08000000L
+#define SX_DEBUG_BUSY__PCCMD_VALID__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS_MASK 0x00000001L
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS__SHIFT 0x00000000
+#define SX_DEBUG_BUSY__POS_INMUX_VALID_MASK 0x00100000L
+#define SX_DEBUG_BUSY__POS_INMUX_VALID__SHIFT 0x00000014
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY__VDATA0_VALID_MASK 0x20000000L
+#define SX_DEBUG_BUSY__VDATA0_VALID__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY__VDATA1_VALID_MASK 0x10000000L
+#define SX_DEBUG_BUSY__VDATA1_VALID__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1_MASK 0x04000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2_MASK 0x02000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2__SHIFT 0x00000019
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3_MASK 0x01000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3__SHIFT 0x00000018
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1_MASK 0x00800000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1__SHIFT 0x00000017
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2_MASK 0x00400000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2__SHIFT 0x00000016
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3_MASK 0x00200000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3__SHIFT 0x00000015
+#define SXIFCCG_DEBUG_REG0__point_address_MASK 0x000001c0L
+#define SXIFCCG_DEBUG_REG0__point_address__SHIFT 0x00000006
+#define SXIFCCG_DEBUG_REG0__position_address_MASK 0x0000003fL
+#define SXIFCCG_DEBUG_REG0__position_address__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance_MASK 0x80000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance__SHIFT 0x0000001f
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc_MASK 0x40000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc__SHIFT 0x0000001e
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel_MASK 0x0c000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci_MASK 0x03ff0000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask_MASK 0x0000f000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask__SHIFT 0x0000000c
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id_MASK 0x30000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id__SHIFT 0x0000001c
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx_MASK 0x00000e00L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx__SHIFT 0x00000009
+#define SXIFCCG_DEBUG_REG1__aux_sel_MASK 0x00300000L
+#define SXIFCCG_DEBUG_REG1__aux_sel__SHIFT 0x00000014
+#define SXIFCCG_DEBUG_REG1__available_positions_MASK 0x0000007fL
+#define SXIFCCG_DEBUG_REG1__available_positions__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0_MASK 0xf0000000L
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0__SHIFT 0x0000001c
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1_MASK 0x0f000000L
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1__SHIFT 0x00000018
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp_MASK 0x000f0000L
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena_MASK 0x00008000L
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena__SHIFT 0x0000000f
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents_MASK 0x00007c00L
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents__SHIFT 0x0000000a
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx_MASK 0x00000380L
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx__SHIFT 0x00000007
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0_MASK 0x00800000L
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1_MASK 0x00400000L
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1__SHIFT 0x00000016
+#define SXIFCCG_DEBUG_REG2__param_cache_base_MASK 0x0000007fL
+#define SXIFCCG_DEBUG_REG2__param_cache_base__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded_MASK 0x00008000L
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded__SHIFT 0x0000000f
+#define SXIFCCG_DEBUG_REG2__req_active_verts_MASK 0x007f0000L
+#define SXIFCCG_DEBUG_REG2__req_active_verts__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG2__sx_aux_MASK 0x00000180L
+#define SXIFCCG_DEBUG_REG2__sx_aux__SHIFT 0x00000007
+#define SXIFCCG_DEBUG_REG2__sx_request_indx_MASK 0x00007e00L
+#define SXIFCCG_DEBUG_REG2__sx_request_indx__SHIFT 0x00000009
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts_MASK 0xfc000000L
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx_MASK 0x03800000L
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO_MASK 0x000000ffL
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG3__available_positions_MASK 0x001fc000L
+#define SXIFCCG_DEBUG_REG3__available_positions__SHIFT 0x0000000e
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full_MASK 0x20000000L
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full__SHIFT 0x0000001d
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write_MASK 0x80000000L
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write__SHIFT 0x0000001f
+#define SXIFCCG_DEBUG_REG3__current_state_MASK 0x00600000L
+#define SXIFCCG_DEBUG_REG3__current_state__SHIFT 0x00000015
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena_MASK 0x00002000L
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena__SHIFT 0x0000000d
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena_MASK 0x00001000L
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena__SHIFT 0x0000000c
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty_MASK 0x02000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty__SHIFT 0x00000019
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full_MASK 0x04000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write_MASK 0x40000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write__SHIFT 0x0000001e
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty_MASK 0x00800000L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable_MASK 0x00000f00L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable__SHIFT 0x00000008
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full_MASK 0x01000000L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full__SHIFT 0x00000018
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty_MASK 0x08000000L
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty__SHIFT 0x0000001b
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full_MASK 0x10000000L
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full__SHIFT 0x0000001c
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define TA_BC_BASE_ADDR__ADDRESS_MASK 0xffffffffL
+#define TA_BC_BASE_ADDR__ADDRESS__SHIFT 0x00000000
+#define TA_BC_BASE_ADDR_HI__ADDRESS_MASK 0x000000ffL
+#define TA_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x00000000
+#define TA_CGTT_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TA_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TA_CGTT_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TA_CGTT_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TA_CNTL__ALIGNER_CREDIT_MASK 0x001f0000L
+#define TA_CNTL__ALIGNER_CREDIT__SHIFT 0x00000010
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE_MASK 0x00010000L
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE__SHIFT 0x00000010
+#define TA_CNTL__TC_DATA_CREDIT_MASK 0x0000e000L
+#define TA_CNTL__TC_DATA_CREDIT__SHIFT 0x0000000d
+#define TA_CNTL__TD_FIFO_CREDIT_MASK 0xffc00000L
+#define TA_CNTL__TD_FIFO_CREDIT__SHIFT 0x00000016
+#define TA_CS_BC_BASE_ADDR__ADDRESS_MASK 0xffffffffL
+#define TA_CS_BC_BASE_ADDR__ADDRESS__SHIFT 0x00000000
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS_MASK 0x000000ffL
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x00000000
+#define TA_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define TA_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define TA_DEBUG_INDEX__INDEX_MASK 0x0000001fL
+#define TA_DEBUG_INDEX__INDEX__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000000ffL
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0003fc00L
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TA_SCRATCH__SCRATCH_MASK 0xffffffffL
+#define TA_SCRATCH__SCRATCH__SHIFT 0x00000000
+#define TA_STATUS__AL_BUSY_MASK 0x40000000L
+#define TA_STATUS__AL_BUSY__SHIFT 0x0000001e
+#define TA_STATUS__BUSY_MASK 0x80000000L
+#define TA_STATUS__BUSY__SHIFT 0x0000001f
+#define TA_STATUS__FA_BUSY_MASK 0x20000000L
+#define TA_STATUS__FA_BUSY__SHIFT 0x0000001d
+#define TA_STATUS__FA_LFIFO_EMPTYB_MASK 0x00200000L
+#define TA_STATUS__FA_LFIFO_EMPTYB__SHIFT 0x00000015
+#define TA_STATUS__FA_PFIFO_EMPTYB_MASK 0x00100000L
+#define TA_STATUS__FA_PFIFO_EMPTYB__SHIFT 0x00000014
+#define TA_STATUS__FA_SFIFO_EMPTYB_MASK 0x00400000L
+#define TA_STATUS__FA_SFIFO_EMPTYB__SHIFT 0x00000016
+#define TA_STATUS__FG_BUSY_MASK 0x02000000L
+#define TA_STATUS__FG_BUSY__SHIFT 0x00000019
+#define TA_STATUS__FG_LFIFO_EMPTYB_MASK 0x00002000L
+#define TA_STATUS__FG_LFIFO_EMPTYB__SHIFT 0x0000000d
+#define TA_STATUS__FG_PFIFO_EMPTYB_MASK 0x00001000L
+#define TA_STATUS__FG_PFIFO_EMPTYB__SHIFT 0x0000000c
+#define TA_STATUS__FG_SFIFO_EMPTYB_MASK 0x00004000L
+#define TA_STATUS__FG_SFIFO_EMPTYB__SHIFT 0x0000000e
+#define TA_STATUS__FL_BUSY_MASK 0x08000000L
+#define TA_STATUS__FL_BUSY__SHIFT 0x0000001b
+#define TA_STATUS__FL_LFIFO_EMPTYB_MASK 0x00020000L
+#define TA_STATUS__FL_LFIFO_EMPTYB__SHIFT 0x00000011
+#define TA_STATUS__FL_PFIFO_EMPTYB_MASK 0x00010000L
+#define TA_STATUS__FL_PFIFO_EMPTYB__SHIFT 0x00000010
+#define TA_STATUS__FL_SFIFO_EMPTYB_MASK 0x00040000L
+#define TA_STATUS__FL_SFIFO_EMPTYB__SHIFT 0x00000012
+#define TA_STATUS__IN_BUSY_MASK 0x01000000L
+#define TA_STATUS__IN_BUSY__SHIFT 0x00000018
+#define TA_STATUS__LA_BUSY_MASK 0x04000000L
+#define TA_STATUS__LA_BUSY__SHIFT 0x0000001a
+#define TA_STATUS__TA_BUSY_MASK 0x10000000L
+#define TA_STATUS__TA_BUSY__SHIFT 0x0000001c
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TCA_CTRL__HOLE_TIMEOUT_MASK 0x0000000fL
+#define TCA_CTRL__HOLE_TIMEOUT__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TCC_CTRL__CACHE_SIZE_MASK 0x00000003L
+#define TCC_CTRL__CACHE_SIZE__SHIFT 0x00000000
+#define TCC_CTRL__LATENCY_FIFO_SIZE_MASK 0x000f0000L
+#define TCC_CTRL__LATENCY_FIFO_SIZE__SHIFT 0x00000010
+#define TCC_CTRL__RATE_MASK 0x0000000cL
+#define TCC_CTRL__RATE__SHIFT 0x00000002
+#define TCC_CTRL__SRC_FIFO_SIZE_MASK 0x0000f000L
+#define TCC_CTRL__SRC_FIFO_SIZE__SHIFT 0x0000000c
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS_MASK 0x00100000L
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS__SHIFT 0x00000014
+#define TCC_CTRL__WRITEBACK_MARGIN_MASK 0x000000f0L
+#define TCC_CTRL__WRITEBACK_MARGIN__SHIFT 0x00000004
+#define TCC_EDC_COUNTER__DED_COUNT_MASK 0x000f0000L
+#define TCC_EDC_COUNTER__DED_COUNT__SHIFT 0x00000010
+#define TCC_EDC_COUNTER__SEC_COUNT_MASK 0x0000000fL
+#define TCC_EDC_COUNTER__SEC_COUNT__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCI_CNTL_1__REQ_FIFO_DEPTH_MASK 0x00ff0000L
+#define TCI_CNTL_1__REQ_FIFO_DEPTH__SHIFT 0x00000010
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES_MASK 0x0000ffffL
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES__SHIFT 0x00000000
+#define TCI_CNTL_1__WDATA_RAM_DEPTH_MASK 0xff000000L
+#define TCI_CNTL_1__WDATA_RAM_DEPTH__SHIFT 0x00000018
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2_MASK 0x00000001L
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2__SHIFT 0x00000000
+#define TCI_CNTL_2__TCA_MAX_CREDIT_MASK 0x000001feL
+#define TCI_CNTL_2__TCA_MAX_CREDIT__SHIFT 0x00000001
+#define TCI_STATUS__TCI_BUSY_MASK 0x00000001L
+#define TCI_STATUS__TCI_BUSY__SHIFT 0x00000000
+#define TCP_ADDR_CONFIG__COLHI_WIDTH_MASK 0x000001c0L
+#define TCP_ADDR_CONFIG__COLHI_WIDTH__SHIFT 0x00000006
+#define TCP_ADDR_CONFIG__NUM_BANKS_MASK 0x00000030L
+#define TCP_ADDR_CONFIG__NUM_BANKS__SHIFT 0x00000004
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS_MASK 0x0000000fL
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS__SHIFT 0x00000000
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI_MASK 0x00000200L
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI__SHIFT 0x00000009
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS_MASK 0x00000700L
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS__SHIFT 0x00000008
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT_MASK 0x07000000L
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT__SHIFT 0x00000018
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS_MASK 0x00000007L
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS__SHIFT 0x00000000
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT_MASK 0x00070000L
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT__SHIFT 0x00000010
+#define TCP_CHAN_STEER_HI__CHAN8_MASK 0x0000000fL
+#define TCP_CHAN_STEER_HI__CHAN8__SHIFT 0x00000000
+#define TCP_CHAN_STEER_HI__CHAN9_MASK 0x000000f0L
+#define TCP_CHAN_STEER_HI__CHAN9__SHIFT 0x00000004
+#define TCP_CHAN_STEER_HI__CHANA_MASK 0x00000f00L
+#define TCP_CHAN_STEER_HI__CHANA__SHIFT 0x00000008
+#define TCP_CHAN_STEER_HI__CHANB_MASK 0x0000f000L
+#define TCP_CHAN_STEER_HI__CHANB__SHIFT 0x0000000c
+#define TCP_CHAN_STEER_HI__CHANC_MASK 0x000f0000L
+#define TCP_CHAN_STEER_HI__CHANC__SHIFT 0x00000010
+#define TCP_CHAN_STEER_HI__CHAND_MASK 0x00f00000L
+#define TCP_CHAN_STEER_HI__CHAND__SHIFT 0x00000014
+#define TCP_CHAN_STEER_HI__CHANE_MASK 0x0f000000L
+#define TCP_CHAN_STEER_HI__CHANE__SHIFT 0x00000018
+#define TCP_CHAN_STEER_HI__CHANF_MASK 0xf0000000L
+#define TCP_CHAN_STEER_HI__CHANF__SHIFT 0x0000001c
+#define TCP_CHAN_STEER_LO__CHAN0_MASK 0x0000000fL
+#define TCP_CHAN_STEER_LO__CHAN0__SHIFT 0x00000000
+#define TCP_CHAN_STEER_LO__CHAN1_MASK 0x000000f0L
+#define TCP_CHAN_STEER_LO__CHAN1__SHIFT 0x00000004
+#define TCP_CHAN_STEER_LO__CHAN2_MASK 0x00000f00L
+#define TCP_CHAN_STEER_LO__CHAN2__SHIFT 0x00000008
+#define TCP_CHAN_STEER_LO__CHAN3_MASK 0x0000f000L
+#define TCP_CHAN_STEER_LO__CHAN3__SHIFT 0x0000000c
+#define TCP_CHAN_STEER_LO__CHAN4_MASK 0x000f0000L
+#define TCP_CHAN_STEER_LO__CHAN4__SHIFT 0x00000010
+#define TCP_CHAN_STEER_LO__CHAN5_MASK 0x00f00000L
+#define TCP_CHAN_STEER_LO__CHAN5__SHIFT 0x00000014
+#define TCP_CHAN_STEER_LO__CHAN6_MASK 0x0f000000L
+#define TCP_CHAN_STEER_LO__CHAN6__SHIFT 0x00000018
+#define TCP_CHAN_STEER_LO__CHAN7_MASK 0xf0000000L
+#define TCP_CHAN_STEER_LO__CHAN7__SHIFT 0x0000001c
+#define TCP_CNTL__DISABLE_Z_MAP_MASK 0x10000000L
+#define TCP_CNTL__DISABLE_Z_MAP__SHIFT 0x0000001c
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE_MASK 0x00000020L
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE__SHIFT 0x00000005
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE_MASK 0x00000010L
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE__SHIFT 0x00000004
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT_MASK 0x0fc00000L
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT__SHIFT 0x00000016
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT_MASK 0x001f8000L
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT__SHIFT 0x0000000f
+#define TCP_CNTL__FORCE_HIT_MASK 0x00000001L
+#define TCP_CNTL__FORCE_HIT__SHIFT 0x00000000
+#define TCP_CNTL__FORCE_MISS_MASK 0x00000002L
+#define TCP_CNTL__FORCE_MISS__SHIFT 0x00000001
+#define TCP_CNTL__INV_ALL_VMIDS_MASK 0x20000000L
+#define TCP_CNTL__INV_ALL_VMIDS__SHIFT 0x0000001d
+#define TCP_CNTL__L1_SIZE_MASK 0x0000000cL
+#define TCP_CNTL__L1_SIZE__SHIFT 0x00000002
+#define TCP_CREDIT__LFIFO_CREDIT_MASK 0x000003ffL
+#define TCP_CREDIT__LFIFO_CREDIT__SHIFT 0x00000000
+#define TCP_CREDIT__REQ_FIFO_CREDIT_MASK 0x007f0000L
+#define TCP_CREDIT__REQ_FIFO_CREDIT__SHIFT 0x00000010
+#define TCP_CREDIT__TD_CREDIT_MASK 0xe0000000L
+#define TCP_CREDIT__TD_CREDIT__SHIFT 0x0000001d
+#define TCP_EDC_COUNTER__DED_COUNT_MASK 0x000f0000L
+#define TCP_EDC_COUNTER__DED_COUNT__SHIFT 0x00000010
+#define TCP_EDC_COUNTER__SEC_COUNT_MASK 0x0000000fL
+#define TCP_EDC_COUNTER__SEC_COUNT__SHIFT 0x00000000
+#define TCP_INVALIDATE__START_MASK 0x00000001L
+#define TCP_INVALIDATE__START__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_STATUS__TCP_BUSY_MASK 0x00000001L
+#define TCP_STATUS__TCP_BUSY__SHIFT 0x00000000
+#define TD_CGTT_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TD_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TD_CGTT_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TD_CGTT_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TD_CNTL__DISABLE_POWER_THROTTLE_MASK 0x00100000L
+#define TD_CNTL__DISABLE_POWER_THROTTLE__SHIFT 0x00000014
+#define TD_CNTL__EXTEND_LDS_STALL_MASK 0x00000600L
+#define TD_CNTL__EXTEND_LDS_STALL__SHIFT 0x00000009
+#define TD_CNTL__GATHER4_DX9_MODE_MASK 0x00080000L
+#define TD_CNTL__GATHER4_DX9_MODE__SHIFT 0x00000013
+#define TD_CNTL__GATHER4_FLOAT_MODE_MASK 0x00010000L
+#define TD_CNTL__GATHER4_FLOAT_MODE__SHIFT 0x00000010
+#define TD_CNTL__LD_FLOAT_MODE_MASK 0x00040000L
+#define TD_CNTL__LD_FLOAT_MODE__SHIFT 0x00000012
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST_MASK 0x00001800L
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST__SHIFT 0x0000000b
+#define TD_CNTL__PAD_STALL_EN_MASK 0x00000100L
+#define TD_CNTL__PAD_STALL_EN__SHIFT 0x00000008
+#define TD_CNTL__PRECISION_COMPATIBILITY_MASK 0x00008000L
+#define TD_CNTL__PRECISION_COMPATIBILITY__SHIFT 0x0000000f
+#define TD_CNTL__SYNC_PHASE_SH_MASK 0x00000003L
+#define TD_CNTL__SYNC_PHASE_SH__SHIFT 0x00000000
+#define TD_CNTL__SYNC_PHASE_VC_SMX_MASK 0x00000030L
+#define TD_CNTL__SYNC_PHASE_VC_SMX__SHIFT 0x00000004
+#define TD_DEBUG_DATA__DATA_MASK 0x00ffffffL
+#define TD_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define TD_DEBUG_INDEX__INDEX_MASK 0x0000001fL
+#define TD_DEBUG_INDEX__INDEX__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000000ffL
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0003fc00L
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TD_SCRATCH__SCRATCH_MASK 0xffffffffL
+#define TD_SCRATCH__SCRATCH__SHIFT 0x00000000
+#define TD_STATUS__BUSY_MASK 0x80000000L
+#define TD_STATUS__BUSY__SHIFT 0x0000001f
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0x000f0000L
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x00000010
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0x00f00000L
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x00000014
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0x0f000000L
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x00000018
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000L
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x0000001c
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN_MASK 0x000000c0L
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN__SHIFT 0x00000006
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_MASK 0x00000003L
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION__SHIFT 0x00000000
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD_MASK 0x00000800L
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD__SHIFT 0x0000000b
+#define VGT_CACHE_INVALIDATION__ES_LIMIT_MASK 0x001f0000L
+#define VGT_CACHE_INVALIDATION__ES_LIMIT__SHIFT 0x00000010
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN_MASK 0x00001000L
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN__SHIFT 0x0000000c
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH_MASK 0x00002000L
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH__SHIFT 0x0000000d
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE_MASK 0x00000200L
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE__SHIFT 0x00000009
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER_MASK 0x00000020L
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER__SHIFT 0x00000005
+#define VGT_CNTL_STATUS__VGT_BUSY_MASK 0x00000001L
+#define VGT_CNTL_STATUS__VGT_BUSY__SHIFT 0x00000000
+#define VGT_CNTL_STATUS__VGT_GS_BUSY_MASK 0x00000080L
+#define VGT_CNTL_STATUS__VGT_GS_BUSY__SHIFT 0x00000007
+#define VGT_CNTL_STATUS__VGT_HS_BUSY_MASK 0x00000100L
+#define VGT_CNTL_STATUS__VGT_HS_BUSY__SHIFT 0x00000008
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY_MASK 0x00000004L
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY__SHIFT 0x00000002
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY_MASK 0x00000002L
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY__SHIFT 0x00000001
+#define VGT_CNTL_STATUS__VGT_PI_BUSY_MASK 0x00000040L
+#define VGT_CNTL_STATUS__VGT_PI_BUSY__SHIFT 0x00000006
+#define VGT_CNTL_STATUS__VGT_PT_BUSY_MASK 0x00000008L
+#define VGT_CNTL_STATUS__VGT_PT_BUSY__SHIFT 0x00000003
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY_MASK 0x00000200L
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY__SHIFT 0x00000009
+#define VGT_CNTL_STATUS__VGT_TE_BUSY_MASK 0x00000010L
+#define VGT_CNTL_STATUS__VGT_TE_BUSY__SHIFT 0x00000004
+#define VGT_CNTL_STATUS__VGT_VR_BUSY_MASK 0x00000020L
+#define VGT_CNTL_STATUS__VGT_VR_BUSY__SHIFT 0x00000005
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX_MASK 0x0000003fL
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX__SHIFT 0x00000000
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B_MASK 0x00000040L
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B__SHIFT 0x00000006
+#define VGT_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define VGT_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define VGT_DEBUG_REG0__cm_busy_MASK 0x00008000L
+#define VGT_DEBUG_REG0__cm_busy__SHIFT 0x0000000f
+#define VGT_DEBUG_REG0__combined_out_busy_MASK 0x00200000L
+#define VGT_DEBUG_REG0__combined_out_busy__SHIFT 0x00000015
+#define VGT_DEBUG_REG0__core_clk_busy_MASK 0x04000000L
+#define VGT_DEBUG_REG0__core_clk_busy__SHIFT 0x0000001a
+#define VGT_DEBUG_REG0__frmt_busy_MASK 0x00020000L
+#define VGT_DEBUG_REG0__frmt_busy__SHIFT 0x00000011
+#define VGT_DEBUG_REG0__gog_busy_MASK 0x00010000L
+#define VGT_DEBUG_REG0__gog_busy__SHIFT 0x00000010
+#define VGT_DEBUG_REG0__gs_busy_MASK 0x00001000L
+#define VGT_DEBUG_REG0__gs_busy__SHIFT 0x0000000c
+#define VGT_DEBUG_REG0__gs_clk_busy_MASK 0x08000000L
+#define VGT_DEBUG_REG0__gs_clk_busy__SHIFT 0x0000001b
+#define VGT_DEBUG_REG0__pa_interfaces_busy_MASK 0x00800000L
+#define VGT_DEBUG_REG0__pa_interfaces_busy__SHIFT 0x00000017
+#define VGT_DEBUG_REG0__pi_busy_MASK 0x00000100L
+#define VGT_DEBUG_REG0__pi_busy__SHIFT 0x00000008
+#define VGT_DEBUG_REG0__pt_pi_busy_MASK 0x00000400L
+#define VGT_DEBUG_REG0__pt_pi_busy__SHIFT 0x0000000a
+#define VGT_DEBUG_REG0__rcm_busy_MASK 0x00002000L
+#define VGT_DEBUG_REG0__rcm_busy__SHIFT 0x0000000d
+#define VGT_DEBUG_REG0__reg_clk_busy_MASK 0x01000000L
+#define VGT_DEBUG_REG0__reg_clk_busy__SHIFT 0x00000018
+#define VGT_DEBUG_REG0__sclk_core_vld_MASK 0x20000000L
+#define VGT_DEBUG_REG0__sclk_core_vld__SHIFT 0x0000001d
+#define VGT_DEBUG_REG0__sclk_gs_vld_MASK 0x40000000L
+#define VGT_DEBUG_REG0__sclk_gs_vld__SHIFT 0x0000001e
+#define VGT_DEBUG_REG0__SPARE0_MASK 0x80000000L
+#define VGT_DEBUG_REG0__SPARE0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG0__SPARE10_MASK 0x00040000L
+#define VGT_DEBUG_REG0__SPARE10__SHIFT 0x00000012
+#define VGT_DEBUG_REG0__SPARE1_MASK 0x10000000L
+#define VGT_DEBUG_REG0__SPARE1__SHIFT 0x0000001c
+#define VGT_DEBUG_REG0__SPARE2_MASK 0x02000000L
+#define VGT_DEBUG_REG0__SPARE2__SHIFT 0x00000019
+#define VGT_DEBUG_REG0__SPARE3_MASK 0x00100000L
+#define VGT_DEBUG_REG0__SPARE3__SHIFT 0x00000014
+#define VGT_DEBUG_REG0__SPARE4_MASK 0x00000080L
+#define VGT_DEBUG_REG0__SPARE4__SHIFT 0x00000007
+#define VGT_DEBUG_REG0__SPARE5_MASK 0x00000040L
+#define VGT_DEBUG_REG0__SPARE5__SHIFT 0x00000006
+#define VGT_DEBUG_REG0__SPARE6_MASK 0x00000020L
+#define VGT_DEBUG_REG0__SPARE6__SHIFT 0x00000005
+#define VGT_DEBUG_REG0__SPARE7_MASK 0x00000010L
+#define VGT_DEBUG_REG0__SPARE7__SHIFT 0x00000004
+#define VGT_DEBUG_REG0__SPARE8_MASK 0x00000008L
+#define VGT_DEBUG_REG0__SPARE8__SHIFT 0x00000003
+#define VGT_DEBUG_REG0__SPARE9_MASK 0x00000002L
+#define VGT_DEBUG_REG0__SPARE9__SHIFT 0x00000001
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy_MASK 0x00400000L
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy__SHIFT 0x00000016
+#define VGT_DEBUG_REG0__te11_pi_busy_MASK 0x00080000L
+#define VGT_DEBUG_REG0__te11_pi_busy__SHIFT 0x00000013
+#define VGT_DEBUG_REG0__te_pi_busy_MASK 0x00000800L
+#define VGT_DEBUG_REG0__te_pi_busy__SHIFT 0x0000000b
+#define VGT_DEBUG_REG0__tm_busy_MASK 0x00004000L
+#define VGT_DEBUG_REG0__tm_busy__SHIFT 0x0000000e
+#define VGT_DEBUG_REG0__vgt_busy_extended_MASK 0x00000001L
+#define VGT_DEBUG_REG0__vgt_busy_extended__SHIFT 0x00000000
+#define VGT_DEBUG_REG0__vgt_busy_MASK 0x00000004L
+#define VGT_DEBUG_REG0__vgt_busy__SHIFT 0x00000002
+#define VGT_DEBUG_REG0__vr_pi_busy_MASK 0x00000200L
+#define VGT_DEBUG_REG0__vr_pi_busy__SHIFT 0x00000009
+#define VGT_DEBUG_REG10__eopg_r2_q_MASK 0x00000020L
+#define VGT_DEBUG_REG10__eopg_r2_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG10__eotg_r2_q_MASK 0x00000040L
+#define VGT_DEBUG_REG10__eotg_r2_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0_MASK 0xff800000L
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0_MASK 0x007fe000L
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0__SHIFT 0x0000000d
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q_MASK 0x0000001fL
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q_MASK 0x00000180L
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q_MASK 0x00001000L
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq_MASK 0x00000800L
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq__SHIFT 0x0000000b
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG10__SPARE2_MASK 0x00000600L
+#define VGT_DEBUG_REG10__SPARE2__SHIFT 0x00000009
+#define VGT_DEBUG_REG11__counters_available_r0_MASK 0x00001000L
+#define VGT_DEBUG_REG11__counters_available_r0__SHIFT 0x0000000c
+#define VGT_DEBUG_REG11__counters_avail_r0_MASK 0x00000800L
+#define VGT_DEBUG_REG11__counters_avail_r0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG11__counters_busy_r0_MASK 0x00000400L
+#define VGT_DEBUG_REG11__counters_busy_r0__SHIFT 0x0000000a
+#define VGT_DEBUG_REG11__es_r0_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG11__es_r0_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy_MASK 0x00000008L
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy__SHIFT 0x00000003
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full_MASK 0x08000000L
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full__SHIFT 0x0000001b
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3_MASK 0x00000200L
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3__SHIFT 0x00000009
+#define VGT_DEBUG_REG11__es_tbl_empty_MASK 0x40000000L
+#define VGT_DEBUG_REG11__es_tbl_empty__SHIFT 0x0000001e
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG11__gs_issue_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG11__gs_issue_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG11__gs_r0_rtr_MASK 0x00080000L
+#define VGT_DEBUG_REG11__gs_r0_rtr__SHIFT 0x00000013
+#define VGT_DEBUG_REG11__hold_eswave_MASK 0x00000100L
+#define VGT_DEBUG_REG11__hold_eswave__SHIFT 0x00000008
+#define VGT_DEBUG_REG11__no_active_states_r0_MASK 0x80000000L
+#define VGT_DEBUG_REG11__no_active_states_r0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG11__send_event_q_MASK 0x20000000L
+#define VGT_DEBUG_REG11__send_event_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG11__SPARE0_MASK 0x00040000L
+#define VGT_DEBUG_REG11__SPARE0__SHIFT 0x00000012
+#define VGT_DEBUG_REG11__SPARE1_MASK 0x00000020L
+#define VGT_DEBUG_REG11__SPARE1__SHIFT 0x00000005
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy_MASK 0x00000080L
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy__SHIFT 0x00000007
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy_MASK 0x00000040L
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy__SHIFT 0x00000006
+#define VGT_DEBUG_REG11__tm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG11__tm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG11__tm_noif_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG11__tm_noif_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG11__tm_out_busy_q_MASK 0x00000004L
+#define VGT_DEBUG_REG11__tm_out_busy_q__SHIFT 0x00000002
+#define VGT_DEBUG_REG11__tm_pt_event_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG11__tm_pt_event_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr_MASK 0x01000000L
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr__SHIFT 0x00000018
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr_MASK 0x00400000L
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr__SHIFT 0x00000016
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr_MASK 0x00800000L
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr__SHIFT 0x00000017
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q_MASK 0x00008000L
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q_MASK 0x00004000L
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy_MASK 0x00000010L
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy__SHIFT 0x00000004
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full_MASK 0x10000000L
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full__SHIFT 0x0000001c
+#define VGT_DEBUG_REG11__vs_event_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG11__vs_event_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG11__vs_event_fifo_full_MASK 0x04000000L
+#define VGT_DEBUG_REG11__vs_event_fifo_full__SHIFT 0x0000001a
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG12__gs_state0_r0_q_MASK 0x00000007L
+#define VGT_DEBUG_REG12__gs_state0_r0_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG12__gs_state1_r0_q_MASK 0x00000038L
+#define VGT_DEBUG_REG12__gs_state1_r0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG12__gs_state2_r0_q_MASK 0x000001c0L
+#define VGT_DEBUG_REG12__gs_state2_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG12__gs_state3_r0_q_MASK 0x00000e00L
+#define VGT_DEBUG_REG12__gs_state3_r0_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG12__gs_state4_r0_q_MASK 0x00007000L
+#define VGT_DEBUG_REG12__gs_state4_r0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG12__gs_state5_r0_q_MASK 0x00038000L
+#define VGT_DEBUG_REG12__gs_state5_r0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG12__gs_state6_r0_q_MASK 0x001c0000L
+#define VGT_DEBUG_REG12__gs_state6_r0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG12__gs_state7_r0_q_MASK 0x00e00000L
+#define VGT_DEBUG_REG12__gs_state7_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG12__gs_state8_r0_q_MASK 0x07000000L
+#define VGT_DEBUG_REG12__gs_state8_r0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG12__gs_state9_r0_q_MASK 0x38000000L
+#define VGT_DEBUG_REG12__gs_state9_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG12__hold_eswave_eop_MASK 0x40000000L
+#define VGT_DEBUG_REG12__hold_eswave_eop__SHIFT 0x0000001e
+#define VGT_DEBUG_REG12__SPARE0_MASK 0x80000000L
+#define VGT_DEBUG_REG12__SPARE0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q_MASK 0xf8000000L
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG13__es_tbl_full_MASK 0x01000000L
+#define VGT_DEBUG_REG13__es_tbl_full__SHIFT 0x00000018
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0_MASK 0x00800000L
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0_MASK 0x00400000L
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0__SHIFT 0x00000016
+#define VGT_DEBUG_REG13__gs_state10_r0_q_MASK 0x00000007L
+#define VGT_DEBUG_REG13__gs_state10_r0_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG13__gs_state11_r0_q_MASK 0x00000038L
+#define VGT_DEBUG_REG13__gs_state11_r0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG13__gs_state12_r0_q_MASK 0x000001c0L
+#define VGT_DEBUG_REG13__gs_state12_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG13__gs_state13_r0_q_MASK 0x00000e00L
+#define VGT_DEBUG_REG13__gs_state13_r0_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG13__gs_state14_r0_q_MASK 0x00007000L
+#define VGT_DEBUG_REG13__gs_state14_r0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG13__gs_state15_r0_q_MASK 0x00038000L
+#define VGT_DEBUG_REG13__gs_state15_r0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0_MASK 0x003c0000L
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0__SHIFT 0x00000012
+#define VGT_DEBUG_REG13__SPARE0_MASK 0x04000000L
+#define VGT_DEBUG_REG13__SPARE0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG13__SPARE1_MASK 0x02000000L
+#define VGT_DEBUG_REG13__SPARE1__SHIFT 0x00000019
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q_MASK 0x00000400L
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full_MASK 0x00000010L
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full__SHIFT 0x00000004
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0_MASK 0x20000000L
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0__SHIFT 0x0000001d
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0_MASK 0x00000020L
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0__SHIFT 0x00000005
+#define VGT_DEBUG_REG14__gs_tbl_full_r0_MASK 0x00000800L
+#define VGT_DEBUG_REG14__gs_tbl_full_r0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy_MASK 0x08000000L
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy__SHIFT 0x0000001b
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy_MASK 0x00200000L
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy__SHIFT 0x00000015
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0_MASK 0x04000000L
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0_MASK 0x00000040L
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0__SHIFT 0x00000006
+#define VGT_DEBUG_REG14__SPARE0_MASK 0x40000000L
+#define VGT_DEBUG_REG14__SPARE0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG14__SPARE1_MASK 0x10000000L
+#define VGT_DEBUG_REG14__SPARE1__SHIFT 0x0000001c
+#define VGT_DEBUG_REG14__SPARE2_MASK 0x001ff000L
+#define VGT_DEBUG_REG14__SPARE2__SHIFT 0x0000000c
+#define VGT_DEBUG_REG14__SPARE3_MASK 0x0000000fL
+#define VGT_DEBUG_REG14__SPARE3__SHIFT 0x00000000
+#define VGT_DEBUG_REG14__SPARE8_MASK 0x00000180L
+#define VGT_DEBUG_REG14__SPARE8__SHIFT 0x00000007
+#define VGT_DEBUG_REG14__SPARE_MASK 0x01c00000L
+#define VGT_DEBUG_REG14__SPARE__SHIFT 0x00000016
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q_MASK 0x80000000L
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q_MASK 0x02000000L
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q__SHIFT 0x00000019
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0_MASK 0x00000200L
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0__SHIFT 0x00000009
+#define VGT_DEBUG_REG15__active_sm_q_MASK 0x000003e0L
+#define VGT_DEBUG_REG15__active_sm_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG15__cm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG15__cm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q_MASK 0x000f8000L
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG15__counters_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG15__counters_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG15__counters_full_MASK 0x00000010L
+#define VGT_DEBUG_REG15__counters_full__SHIFT 0x00000004
+#define VGT_DEBUG_REG15__entry_rdptr_q_MASK 0x00007c00L
+#define VGT_DEBUG_REG15__entry_rdptr_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0_MASK 0x10000000L
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0__SHIFT 0x0000001c
+#define VGT_DEBUG_REG15__output_fifo_empty_MASK 0x00000004L
+#define VGT_DEBUG_REG15__output_fifo_empty__SHIFT 0x00000002
+#define VGT_DEBUG_REG15__output_fifo_full_MASK 0x00000008L
+#define VGT_DEBUG_REG15__output_fifo_full__SHIFT 0x00000003
+#define VGT_DEBUG_REG15__SPARE25_MASK 0x03f00000L
+#define VGT_DEBUG_REG15__SPARE25__SHIFT 0x00000014
+#define VGT_DEBUG_REG15__SPARE31_MASK 0xe0000000L
+#define VGT_DEBUG_REG15__SPARE31__SHIFT 0x0000001d
+#define VGT_DEBUG_REG15__st_cut_mode_q_MASK 0x0c000000L
+#define VGT_DEBUG_REG15__st_cut_mode_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG16__gog_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG16__gog_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel_MASK 0x0e000000L
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel__SHIFT 0x00000019
+#define VGT_DEBUG_REG16__gog_state_q_MASK 0x0000000eL
+#define VGT_DEBUG_REG16__gog_state_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG16__indx_valid_r0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG16__indx_valid_r0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG16__indx_valid_r1_q_MASK 0x00020000L
+#define VGT_DEBUG_REG16__indx_valid_r1_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG16__indx_valid_r2_q_MASK 0x00002000L
+#define VGT_DEBUG_REG16__indx_valid_r2_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q_MASK 0x10000000L
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG16__new_vs_thread_r2_MASK 0x80000000L
+#define VGT_DEBUG_REG16__new_vs_thread_r2__SHIFT 0x0000001f
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0_MASK 0x40000000L
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG16__prim_valid_r0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG16__prim_valid_r0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG16__prim_valid_r1_q_MASK 0x00010000L
+#define VGT_DEBUG_REG16__prim_valid_r1_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG16__prim_valid_r2_q_MASK 0x00004000L
+#define VGT_DEBUG_REG16__prim_valid_r2_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG16__r0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG16__r0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG16__r1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG16__r1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG16__r1_upstream_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG16__r1_upstream_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG16__r2_indx_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG16__r2_indx_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG16__r2_prim_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG16__r2_prim_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG16__r2_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG16__r2_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG16__send_event_q_MASK 0x00400000L
+#define VGT_DEBUG_REG16__send_event_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG16__SPARE24_MASK 0x01800000L
+#define VGT_DEBUG_REG16__SPARE24__SHIFT 0x00000017
+#define VGT_DEBUG_REG16__valid_r0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG16__valid_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG16__valid_r1_q_MASK 0x00040000L
+#define VGT_DEBUG_REG16__valid_r1_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG16__valid_r2_q_MASK 0x00008000L
+#define VGT_DEBUG_REG16__valid_r2_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q_MASK 0x01000000L
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0_MASK 0x20000000L
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0__SHIFT 0x0000001d
+#define VGT_DEBUG_REG17__gog_out_indx_13_0_MASK 0xfffc0000L
+#define VGT_DEBUG_REG17__gog_out_indx_13_0__SHIFT 0x00000012
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0_MASK 0x0003f000L
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0__SHIFT 0x0000000c
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0_MASK 0x00000fc0L
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0__SHIFT 0x00000006
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0_MASK 0x0000003fL
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG18__components_valid_r0_q_MASK 0xe0000000L
+#define VGT_DEBUG_REG18__components_valid_r0_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d_MASK 0x00800000L
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d__SHIFT 0x00000017
+#define VGT_DEBUG_REG18__eop_r0_q_MASK 0x00400000L
+#define VGT_DEBUG_REG18__eop_r0_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG18__grp_vr_valid_MASK 0x00000001L
+#define VGT_DEBUG_REG18__grp_vr_valid__SHIFT 0x00000000
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q_MASK 0x08000000L
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q_MASK 0x10000000L
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG18__indices_to_send_q_MASK 0x00000700L
+#define VGT_DEBUG_REG18__indices_to_send_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG18__indx0_hit_d_MASK 0x00040000L
+#define VGT_DEBUG_REG18__indx0_hit_d__SHIFT 0x00000012
+#define VGT_DEBUG_REG18__indx0_new_d_MASK 0x00002000L
+#define VGT_DEBUG_REG18__indx0_new_d__SHIFT 0x0000000d
+#define VGT_DEBUG_REG18__indx1_hit_d_MASK 0x00020000L
+#define VGT_DEBUG_REG18__indx1_hit_d__SHIFT 0x00000011
+#define VGT_DEBUG_REG18__indx1_new_d_MASK 0x00004000L
+#define VGT_DEBUG_REG18__indx1_new_d__SHIFT 0x0000000e
+#define VGT_DEBUG_REG18__indx2_hit_d_MASK 0x00010000L
+#define VGT_DEBUG_REG18__indx2_hit_d__SHIFT 0x00000010
+#define VGT_DEBUG_REG18__indx2_new_d_MASK 0x00008000L
+#define VGT_DEBUG_REG18__indx2_new_d__SHIFT 0x0000000f
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG18__last_indx_of_prim_MASK 0x00001000L
+#define VGT_DEBUG_REG18__last_indx_of_prim__SHIFT 0x0000000c
+#define VGT_DEBUG_REG18__null_primitive_r0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG18__null_primitive_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG18__out_vr_indx_read_MASK 0x00000040L
+#define VGT_DEBUG_REG18__out_vr_indx_read__SHIFT 0x00000006
+#define VGT_DEBUG_REG18__out_vr_prim_read_MASK 0x00000080L
+#define VGT_DEBUG_REG18__out_vr_prim_read__SHIFT 0x00000007
+#define VGT_DEBUG_REG18__pipe0_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG18__pipe0_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG18__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG18__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG18__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG18__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG18__pipe1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG18__pipe1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q_MASK 0x07000000L
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG18__valid_indices_MASK 0x00000800L
+#define VGT_DEBUG_REG18__valid_indices__SHIFT 0x0000000b
+#define VGT_DEBUG_REG18__vr_grp_read_MASK 0x00000008L
+#define VGT_DEBUG_REG18__vr_grp_read__SHIFT 0x00000003
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect_MASK 0x00080000L
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect__SHIFT 0x00000013
+#define VGT_DEBUG_REG19__buffered_prim_eop_MASK 0x00040000L
+#define VGT_DEBUG_REG19__buffered_prim_eop__SHIFT 0x00000012
+#define VGT_DEBUG_REG19__buffered_prim_event_MASK 0x00010000L
+#define VGT_DEBUG_REG19__buffered_prim_event__SHIFT 0x00000010
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive_MASK 0x00020000L
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive__SHIFT 0x00000011
+#define VGT_DEBUG_REG19__buffered_prim_type_event_MASK 0x03f00000L
+#define VGT_DEBUG_REG19__buffered_prim_type_event__SHIFT 0x00000014
+#define VGT_DEBUG_REG19__filter_event_MASK 0x80000000L
+#define VGT_DEBUG_REG19__filter_event__SHIFT 0x0000001f
+#define VGT_DEBUG_REG19__hold_prim_MASK 0x00000800L
+#define VGT_DEBUG_REG19__hold_prim__SHIFT 0x0000000b
+#define VGT_DEBUG_REG19__new_packet_q_MASK 0x00008000L
+#define VGT_DEBUG_REG19__new_packet_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector_MASK 0x40000000L
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector__SHIFT 0x0000001e
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx_MASK 0x30000000L
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx__SHIFT 0x0000001c
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q_MASK 0x00000020L
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q_MASK 0x00000010L
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q_MASK 0x00000400L
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG19__prim_buffer_empty_MASK 0x00000004L
+#define VGT_DEBUG_REG19__prim_buffer_empty__SHIFT 0x00000002
+#define VGT_DEBUG_REG19__prim_buffer_full_MASK 0x00000008L
+#define VGT_DEBUG_REG19__prim_buffer_full__SHIFT 0x00000003
+#define VGT_DEBUG_REG19__separate_out_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG19__separate_out_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q_MASK 0x00000100L
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q_MASK 0x00000200L
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q_MASK 0x00000080L
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q_MASK 0x00000040L
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q_MASK 0x00004000L
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q_MASK 0x08000000L
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q_MASK 0x04000000L
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q_MASK 0x00001000L
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q_MASK 0x00002000L
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG1__gog_out_indx_valid_MASK 0x10000000L
+#define VGT_DEBUG_REG1__gog_out_indx_valid__SHIFT 0x0000001c
+#define VGT_DEBUG_REG1__gog_out_prim_valid_MASK 0x40000000L
+#define VGT_DEBUG_REG1__gog_out_prim_valid__SHIFT 0x0000001e
+#define VGT_DEBUG_REG1__gs_pi_read_MASK 0x08000000L
+#define VGT_DEBUG_REG1__gs_pi_read__SHIFT 0x0000001b
+#define VGT_DEBUG_REG1__out_indx_read_MASK 0x20000000L
+#define VGT_DEBUG_REG1__out_indx_read__SHIFT 0x0000001d
+#define VGT_DEBUG_REG1__out_prim_read_MASK 0x80000000L
+#define VGT_DEBUG_REG1__out_prim_read__SHIFT 0x0000001f
+#define VGT_DEBUG_REG1__pi_gs_valid_MASK 0x04000000L
+#define VGT_DEBUG_REG1__pi_gs_valid__SHIFT 0x0000001a
+#define VGT_DEBUG_REG1__pi_pt_valid_MASK 0x00001000L
+#define VGT_DEBUG_REG1__pi_pt_valid__SHIFT 0x0000000c
+#define VGT_DEBUG_REG1__pi_te_valid_MASK 0x00004000L
+#define VGT_DEBUG_REG1__pi_te_valid__SHIFT 0x0000000e
+#define VGT_DEBUG_REG1__pi_vr_valid_MASK 0x00000400L
+#define VGT_DEBUG_REG1__pi_vr_valid__SHIFT 0x0000000a
+#define VGT_DEBUG_REG1__pt_out_indx_valid_MASK 0x00100000L
+#define VGT_DEBUG_REG1__pt_out_indx_valid__SHIFT 0x00000014
+#define VGT_DEBUG_REG1__pt_out_prim_valid_MASK 0x00400000L
+#define VGT_DEBUG_REG1__pt_out_prim_valid__SHIFT 0x00000016
+#define VGT_DEBUG_REG1__pt_pi_read_MASK 0x00002000L
+#define VGT_DEBUG_REG1__pt_pi_read__SHIFT 0x0000000d
+#define VGT_DEBUG_REG1__SPARE0_MASK 0x00000200L
+#define VGT_DEBUG_REG1__SPARE0__SHIFT 0x00000009
+#define VGT_DEBUG_REG1__SPARE10_MASK 0x00200000L
+#define VGT_DEBUG_REG1__SPARE10__SHIFT 0x00000015
+#define VGT_DEBUG_REG1__SPARE11_MASK 0x00080000L
+#define VGT_DEBUG_REG1__SPARE11__SHIFT 0x00000013
+#define VGT_DEBUG_REG1__SPARE12_MASK 0x00020000L
+#define VGT_DEBUG_REG1__SPARE12__SHIFT 0x00000011
+#define VGT_DEBUG_REG1__SPARE1_MASK 0x00000100L
+#define VGT_DEBUG_REG1__SPARE1__SHIFT 0x00000008
+#define VGT_DEBUG_REG1__SPARE23_MASK 0x00800000L
+#define VGT_DEBUG_REG1__SPARE23__SHIFT 0x00000017
+#define VGT_DEBUG_REG1__SPARE25_MASK 0x02000000L
+#define VGT_DEBUG_REG1__SPARE25__SHIFT 0x00000019
+#define VGT_DEBUG_REG1__SPARE2_MASK 0x00000080L
+#define VGT_DEBUG_REG1__SPARE2__SHIFT 0x00000007
+#define VGT_DEBUG_REG1__SPARE3_MASK 0x00000040L
+#define VGT_DEBUG_REG1__SPARE3__SHIFT 0x00000006
+#define VGT_DEBUG_REG1__SPARE4_MASK 0x00000020L
+#define VGT_DEBUG_REG1__SPARE4__SHIFT 0x00000005
+#define VGT_DEBUG_REG1__SPARE5_MASK 0x00000010L
+#define VGT_DEBUG_REG1__SPARE5__SHIFT 0x00000004
+#define VGT_DEBUG_REG1__SPARE6_MASK 0x00000008L
+#define VGT_DEBUG_REG1__SPARE6__SHIFT 0x00000003
+#define VGT_DEBUG_REG1__SPARE7_MASK 0x00000004L
+#define VGT_DEBUG_REG1__SPARE7__SHIFT 0x00000002
+#define VGT_DEBUG_REG1__SPARE8_MASK 0x00000002L
+#define VGT_DEBUG_REG1__SPARE8__SHIFT 0x00000001
+#define VGT_DEBUG_REG1__SPARE9_MASK 0x00000001L
+#define VGT_DEBUG_REG1__SPARE9__SHIFT 0x00000000
+#define VGT_DEBUG_REG1__te_grp_read_MASK 0x00008000L
+#define VGT_DEBUG_REG1__te_grp_read__SHIFT 0x0000000f
+#define VGT_DEBUG_REG1__te_out_data_valid_MASK 0x01000000L
+#define VGT_DEBUG_REG1__te_out_data_valid__SHIFT 0x00000018
+#define VGT_DEBUG_REG1__vr_out_indx_valid_MASK 0x00010000L
+#define VGT_DEBUG_REG1__vr_out_indx_valid__SHIFT 0x00000010
+#define VGT_DEBUG_REG1__vr_out_prim_valid_MASK 0x00040000L
+#define VGT_DEBUG_REG1__vr_out_prim_valid__SHIFT 0x00000012
+#define VGT_DEBUG_REG1__vr_pi_read_MASK 0x00000800L
+#define VGT_DEBUG_REG1__vr_pi_read__SHIFT 0x0000000b
+#define VGT_DEBUG_REG20__alloc_counter_q_MASK 0x003c0000L
+#define VGT_DEBUG_REG20__alloc_counter_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q_MASK 0x1fc00000L
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0_MASK 0x40000000L
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0_MASK 0x00010000L
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0__SHIFT 0x00000010
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex_MASK 0x0000ffffL
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex__SHIFT 0x00000000
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0_MASK 0x80000000L
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG20__new_allocate_q_MASK 0x20000000L
+#define VGT_DEBUG_REG20__new_allocate_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG20__SPARE17_MASK 0x00020000L
+#define VGT_DEBUG_REG20__SPARE17__SHIFT 0x00000011
+#define VGT_DEBUG_REG21__buff_full_p1_MASK 0x01000000L
+#define VGT_DEBUG_REG21__buff_full_p1__SHIFT 0x00000018
+#define VGT_DEBUG_REG21__eopg_p0_q_MASK 0x40000000L
+#define VGT_DEBUG_REG21__eopg_p0_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG21__eotg_r2_q_MASK 0x04000000L
+#define VGT_DEBUG_REG21__eotg_r2_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG21__full_state_p1_q_MASK 0x00008000L
+#define VGT_DEBUG_REG21__full_state_p1_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG21__indx_count_q_not_0_MASK 0x00002000L
+#define VGT_DEBUG_REG21__indx_count_q_not_0__SHIFT 0x0000000d
+#define VGT_DEBUG_REG21__indx_side_fifo_empty_MASK 0x00000002L
+#define VGT_DEBUG_REG21__indx_side_fifo_empty__SHIFT 0x00000001
+#define VGT_DEBUG_REG21__indx_side_fifo_full_MASK 0x00000080L
+#define VGT_DEBUG_REG21__indx_side_fifo_full__SHIFT 0x00000007
+#define VGT_DEBUG_REG21__indx_side_indx_valid_MASK 0x00010000L
+#define VGT_DEBUG_REG21__indx_side_indx_valid__SHIFT 0x00000010
+#define VGT_DEBUG_REG21__interfaces_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG21__interfaces_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG21__is_event_p0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG21__is_event_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG21__lshs_dealloc_p1_MASK 0x00200000L
+#define VGT_DEBUG_REG21__lshs_dealloc_p1__SHIFT 0x00000015
+#define VGT_DEBUG_REG21__null_r2_q_MASK 0x08000000L
+#define VGT_DEBUG_REG21__null_r2_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG21__out_indx_fifo_empty_MASK 0x00000001L
+#define VGT_DEBUG_REG21__out_indx_fifo_empty__SHIFT 0x00000000
+#define VGT_DEBUG_REG21__out_indx_fifo_full_MASK 0x00000040L
+#define VGT_DEBUG_REG21__out_indx_fifo_full__SHIFT 0x00000006
+#define VGT_DEBUG_REG21__p0_dr_MASK 0x10000000L
+#define VGT_DEBUG_REG21__p0_dr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG21__p0_nobp_MASK 0x80000000L
+#define VGT_DEBUG_REG21__p0_nobp__SHIFT 0x0000001f
+#define VGT_DEBUG_REG21__p0_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG21__p0_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG21__pipe0_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG21__pipe0_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG21__pipe0_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG21__pipe0_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG21__pipe1_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG21__pipe1_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG21__pipe1_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG21__pipe1_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG21__pipe2_dr_MASK 0x00000010L
+#define VGT_DEBUG_REG21__pipe2_dr__SHIFT 0x00000004
+#define VGT_DEBUG_REG21__pipe2_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG21__pipe2_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG21__stateid_p0_q_MASK 0x000e0000L
+#define VGT_DEBUG_REG21__stateid_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG21__stream_id_r2_q_MASK 0x00400000L
+#define VGT_DEBUG_REG21__stream_id_r2_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG21__strmout_valid_p1_MASK 0x02000000L
+#define VGT_DEBUG_REG21__strmout_valid_p1__SHIFT 0x00000019
+#define VGT_DEBUG_REG21__vsthread_buff_empty_MASK 0x00000020L
+#define VGT_DEBUG_REG21__vsthread_buff_empty__SHIFT 0x00000005
+#define VGT_DEBUG_REG21__vsthread_buff_full_MASK 0x00000800L
+#define VGT_DEBUG_REG21__vsthread_buff_full__SHIFT 0x0000000b
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0_MASK 0x00800000L
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q_MASK 0x00004000L
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG22__cm_state16_MASK 0x00000003L
+#define VGT_DEBUG_REG22__cm_state16__SHIFT 0x00000000
+#define VGT_DEBUG_REG22__cm_state17_MASK 0x0000000cL
+#define VGT_DEBUG_REG22__cm_state17__SHIFT 0x00000002
+#define VGT_DEBUG_REG22__cm_state18_MASK 0x00000030L
+#define VGT_DEBUG_REG22__cm_state18__SHIFT 0x00000004
+#define VGT_DEBUG_REG22__cm_state19_MASK 0x000000c0L
+#define VGT_DEBUG_REG22__cm_state19__SHIFT 0x00000006
+#define VGT_DEBUG_REG22__cm_state20_MASK 0x00000300L
+#define VGT_DEBUG_REG22__cm_state20__SHIFT 0x00000008
+#define VGT_DEBUG_REG22__cm_state21_MASK 0x00000c00L
+#define VGT_DEBUG_REG22__cm_state21__SHIFT 0x0000000a
+#define VGT_DEBUG_REG22__cm_state22_MASK 0x00003000L
+#define VGT_DEBUG_REG22__cm_state22__SHIFT 0x0000000c
+#define VGT_DEBUG_REG22__cm_state23_MASK 0x0000c000L
+#define VGT_DEBUG_REG22__cm_state23__SHIFT 0x0000000e
+#define VGT_DEBUG_REG22__cm_state24_MASK 0x00030000L
+#define VGT_DEBUG_REG22__cm_state24__SHIFT 0x00000010
+#define VGT_DEBUG_REG22__cm_state25_MASK 0x000c0000L
+#define VGT_DEBUG_REG22__cm_state25__SHIFT 0x00000012
+#define VGT_DEBUG_REG22__cm_state26_MASK 0x00300000L
+#define VGT_DEBUG_REG22__cm_state26__SHIFT 0x00000014
+#define VGT_DEBUG_REG22__cm_state27_MASK 0x00c00000L
+#define VGT_DEBUG_REG22__cm_state27__SHIFT 0x00000016
+#define VGT_DEBUG_REG22__cm_state28_MASK 0x03000000L
+#define VGT_DEBUG_REG22__cm_state28__SHIFT 0x00000018
+#define VGT_DEBUG_REG22__cm_state29_MASK 0x0c000000L
+#define VGT_DEBUG_REG22__cm_state29__SHIFT 0x0000001a
+#define VGT_DEBUG_REG22__cm_state30_MASK 0x30000000L
+#define VGT_DEBUG_REG22__cm_state30__SHIFT 0x0000001c
+#define VGT_DEBUG_REG22__cm_state31_MASK 0xc0000000L
+#define VGT_DEBUG_REG22__cm_state31__SHIFT 0x0000001e
+#define VGT_DEBUG_REG23__frmt_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG23__frmt_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG23__new_verts_r2_q_MASK 0x00018000L
+#define VGT_DEBUG_REG23__new_verts_r2_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG23__prim_dr_r2_q_MASK 0x00001000L
+#define VGT_DEBUG_REG23__prim_dr_r2_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG23__prim_fifo_empty_MASK 0x00000200L
+#define VGT_DEBUG_REG23__prim_fifo_empty__SHIFT 0x00000009
+#define VGT_DEBUG_REG23__prim_fifo_full_MASK 0x00000400L
+#define VGT_DEBUG_REG23__prim_fifo_full__SHIFT 0x0000000a
+#define VGT_DEBUG_REG23__prim_r2_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG23__prim_r2_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG23__prim_r3_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG23__prim_r3_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q_MASK 0x00e00000L
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr_MASK 0x00000002L
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr__SHIFT 0x00000001
+#define VGT_DEBUG_REG23__SPARE_MASK 0xff000000L
+#define VGT_DEBUG_REG23__SPARE__SHIFT 0x00000018
+#define VGT_DEBUG_REG23__vert_dr_r0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG23__vert_dr_r0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG23__vert_dr_r1_q_MASK 0x00002000L
+#define VGT_DEBUG_REG23__vert_dr_r1_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG23__vert_dr_r2_q_MASK 0x00000800L
+#define VGT_DEBUG_REG23__vert_dr_r2_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG23__vert_r0_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG23__vert_r0_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG23__vert_r1_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG23__vert_r1_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG23__vert_r2_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG23__vert_r2_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG23__vert_r3_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG23__vert_r3_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG23__verts_sent_r2_q_MASK 0x001e0000L
+#define VGT_DEBUG_REG23__verts_sent_r2_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0_MASK 0x00ffffffL
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q_MASK 0x03000000L
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG24__SPARE31_MASK 0xfc000000L
+#define VGT_DEBUG_REG24__SPARE31__SHIFT 0x0000001a
+#define VGT_DEBUG_REG25__active_sm_r0_q_MASK 0x3c000000L
+#define VGT_DEBUG_REG25__active_sm_r0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q_MASK 0x80000000L
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q_MASK 0x40000000L
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0_MASK 0x03ffffffL
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG26__cm_state0_MASK 0x00000003L
+#define VGT_DEBUG_REG26__cm_state0__SHIFT 0x00000000
+#define VGT_DEBUG_REG26__cm_state10_MASK 0x00300000L
+#define VGT_DEBUG_REG26__cm_state10__SHIFT 0x00000014
+#define VGT_DEBUG_REG26__cm_state11_MASK 0x00c00000L
+#define VGT_DEBUG_REG26__cm_state11__SHIFT 0x00000016
+#define VGT_DEBUG_REG26__cm_state12_MASK 0x03000000L
+#define VGT_DEBUG_REG26__cm_state12__SHIFT 0x00000018
+#define VGT_DEBUG_REG26__cm_state13_MASK 0x0c000000L
+#define VGT_DEBUG_REG26__cm_state13__SHIFT 0x0000001a
+#define VGT_DEBUG_REG26__cm_state14_MASK 0x30000000L
+#define VGT_DEBUG_REG26__cm_state14__SHIFT 0x0000001c
+#define VGT_DEBUG_REG26__cm_state15_MASK 0xc0000000L
+#define VGT_DEBUG_REG26__cm_state15__SHIFT 0x0000001e
+#define VGT_DEBUG_REG26__cm_state1_MASK 0x0000000cL
+#define VGT_DEBUG_REG26__cm_state1__SHIFT 0x00000002
+#define VGT_DEBUG_REG26__cm_state2_MASK 0x00000030L
+#define VGT_DEBUG_REG26__cm_state2__SHIFT 0x00000004
+#define VGT_DEBUG_REG26__cm_state3_MASK 0x000000c0L
+#define VGT_DEBUG_REG26__cm_state3__SHIFT 0x00000006
+#define VGT_DEBUG_REG26__cm_state4_MASK 0x00000300L
+#define VGT_DEBUG_REG26__cm_state4__SHIFT 0x00000008
+#define VGT_DEBUG_REG26__cm_state5_MASK 0x00000c00L
+#define VGT_DEBUG_REG26__cm_state5__SHIFT 0x0000000a
+#define VGT_DEBUG_REG26__cm_state6_MASK 0x00003000L
+#define VGT_DEBUG_REG26__cm_state6__SHIFT 0x0000000c
+#define VGT_DEBUG_REG26__cm_state7_MASK 0x0000c000L
+#define VGT_DEBUG_REG26__cm_state7__SHIFT 0x0000000e
+#define VGT_DEBUG_REG26__cm_state8_MASK 0x00030000L
+#define VGT_DEBUG_REG26__cm_state8__SHIFT 0x00000010
+#define VGT_DEBUG_REG26__cm_state9_MASK 0x000c0000L
+#define VGT_DEBUG_REG26__cm_state9__SHIFT 0x00000012
+#define VGT_DEBUG_REG27__eop_p1_q_MASK 0x00000800L
+#define VGT_DEBUG_REG27__eop_p1_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG27__event_flag_p1_q_MASK 0x00000400L
+#define VGT_DEBUG_REG27__event_flag_p1_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG27__gsc0_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG27__gsc0_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG27__gsc0_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG27__gsc0_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG27__gsc_2cycle_output_MASK 0x00010000L
+#define VGT_DEBUG_REG27__gsc_2cycle_output__SHIFT 0x00000010
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG27__gsc_eop_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG27__gsc_eop_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q_MASK 0x7ff00000L
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q_MASK 0x00003000L
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG27__indices_to_send_p0_q_MASK 0x00000300L
+#define VGT_DEBUG_REG27__indices_to_send_p0_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q_MASK 0x00000080L
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG27__last_indx_of_vsprim_MASK 0x00040000L
+#define VGT_DEBUG_REG27__last_indx_of_vsprim__SHIFT 0x00000012
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim_MASK 0x80000000L
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim__SHIFT 0x0000001f
+#define VGT_DEBUG_REG27__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG27__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG27__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG27__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG27__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG27__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG27__pipe1_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG27__pipe1_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG27__tm_pt_event_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG27__tm_pt_event_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG28__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG28__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG28__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG28__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG28__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG28__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG28__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG28__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG28__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG28__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG28__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG28__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG28__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG28__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG28__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG28__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG28__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG28__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG28__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG28__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG28__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG28__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG28__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG28__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG28__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG28__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG28__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG28__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2_MASK 0x80000000L
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2__SHIFT 0x0000001f
+#define VGT_DEBUG_REG29__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG29__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG29__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG29__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG29__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG29__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG29__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG29__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG29__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG29__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG29__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG29__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG29__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG29__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG29__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG29__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG29__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG29__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG29__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG29__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG29__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG29__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG29__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG29__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG29__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG29__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG29__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG29__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3_MASK 0x80000000L
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3__SHIFT 0x0000001f
+#define VGT_DEBUG_REG2__grpModBusy_MASK 0x00000080L
+#define VGT_DEBUG_REG2__grpModBusy__SHIFT 0x00000007
+#define VGT_DEBUG_REG2__hs_grp_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG2__hs_grp_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG2__hsInputFifoEmpty_MASK 0x00001000L
+#define VGT_DEBUG_REG2__hsInputFifoEmpty__SHIFT 0x0000000c
+#define VGT_DEBUG_REG2__hsInputFifoFull_MASK 0x00040000L
+#define VGT_DEBUG_REG2__hsInputFifoFull__SHIFT 0x00000012
+#define VGT_DEBUG_REG2__hs_noif_busy_MASK 0x00000002L
+#define VGT_DEBUG_REG2__hs_noif_busy__SHIFT 0x00000001
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts_MASK 0x00000040L
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts__SHIFT 0x00000006
+#define VGT_DEBUG_REG2__hsTifFifoEmpty_MASK 0x00002000L
+#define VGT_DEBUG_REG2__hsTifFifoEmpty__SHIFT 0x0000000d
+#define VGT_DEBUG_REG2__hsTifFifoFull_MASK 0x00080000L
+#define VGT_DEBUG_REG2__hsTifFifoFull__SHIFT 0x00000013
+#define VGT_DEBUG_REG2__hsVertFifoEmpty_MASK 0x00000400L
+#define VGT_DEBUG_REG2__hsVertFifoEmpty__SHIFT 0x0000000a
+#define VGT_DEBUG_REG2__hsVertFifoFull_MASK 0x00010000L
+#define VGT_DEBUG_REG2__hsVertFifoFull__SHIFT 0x00000010
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty_MASK 0x00000800L
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty__SHIFT 0x0000000b
+#define VGT_DEBUG_REG2__hsWaveFifoFull_MASK 0x00020000L
+#define VGT_DEBUG_REG2__hsWaveFifoFull__SHIFT 0x00000011
+#define VGT_DEBUG_REG2__lsFwaveFlag_MASK 0x08000000L
+#define VGT_DEBUG_REG2__lsFwaveFlag__SHIFT 0x0000001b
+#define VGT_DEBUG_REG2__ls_sh_id_MASK 0x04000000L
+#define VGT_DEBUG_REG2__ls_sh_id__SHIFT 0x0000001a
+#define VGT_DEBUG_REG2__lsVertFifoEmpty_MASK 0x00000100L
+#define VGT_DEBUG_REG2__lsVertFifoEmpty__SHIFT 0x00000008
+#define VGT_DEBUG_REG2__lsVertFifoFull_MASK 0x00004000L
+#define VGT_DEBUG_REG2__lsVertFifoFull__SHIFT 0x0000000e
+#define VGT_DEBUG_REG2__lsVertIfBusy_0_MASK 0x00000008L
+#define VGT_DEBUG_REG2__lsVertIfBusy_0__SHIFT 0x00000003
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty_MASK 0x00000200L
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty__SHIFT 0x00000009
+#define VGT_DEBUG_REG2__lsWaveFifoFull_MASK 0x00008000L
+#define VGT_DEBUG_REG2__lsWaveFifoFull__SHIFT 0x0000000f
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0_MASK 0x00000020L
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0__SHIFT 0x00000005
+#define VGT_DEBUG_REG2__lsWaveSendFlush_MASK 0x10000000L
+#define VGT_DEBUG_REG2__lsWaveSendFlush__SHIFT 0x0000001c
+#define VGT_DEBUG_REG2__p0_dr_MASK 0x00400000L
+#define VGT_DEBUG_REG2__p0_dr__SHIFT 0x00000016
+#define VGT_DEBUG_REG2__p0_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG2__p0_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG2__p0_rts_MASK 0x01000000L
+#define VGT_DEBUG_REG2__p0_rts__SHIFT 0x00000018
+#define VGT_DEBUG_REG2__p1_dr_MASK 0x00800000L
+#define VGT_DEBUG_REG2__p1_dr__SHIFT 0x00000017
+#define VGT_DEBUG_REG2__p1_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG2__p1_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG2__p1_rts_MASK 0x02000000L
+#define VGT_DEBUG_REG2__p1_rts__SHIFT 0x00000019
+#define VGT_DEBUG_REG2__SPARE_MASK 0xffffffffL
+#define VGT_DEBUG_REG2__SPARE__SHIFT 0x00000000
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG2__tfmmIsBusy_MASK 0x00000004L
+#define VGT_DEBUG_REG2__tfmmIsBusy__SHIFT 0x00000002
+#define VGT_DEBUG_REG30__dynamic_hs_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG30__dynamic_hs_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG30__event_or_null_p0_q_MASK 0x00000008L
+#define VGT_DEBUG_REG30__event_or_null_p0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG30__first_data_chunk_invalid_p0_q_MASK 0x08000000L
+#define VGT_DEBUG_REG30__first_data_chunk_invalid_p0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG30__first_data_ret_of_req_p0_q_MASK 0x04000000L
+#define VGT_DEBUG_REG30__first_data_ret_of_req_p0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG30__first_fetch_of_tg_p0_q_MASK 0x02000000L
+#define VGT_DEBUG_REG30__first_fetch_of_tg_p0_q__SHIFT 0x00000019
+#define VGT_DEBUG_REG30__last_tf_of_tg_MASK 0x00080000L
+#define VGT_DEBUG_REG30__last_tf_of_tg__SHIFT 0x00000013
+#define VGT_DEBUG_REG30__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG30__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG30__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG30__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG30__pipe0_tf_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG30__pipe0_tf_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG30__pipe1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG30__pipe1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG30__pipe1_tf_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG30__pipe1_tf_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG30__pipe2_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG30__pipe2_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG30__pipe2_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG30__pipe2_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG30__pipe4_dr_MASK 0x40000000L
+#define VGT_DEBUG_REG30__pipe4_dr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG30__pipe4_rtr_MASK 0x80000000L
+#define VGT_DEBUG_REG30__pipe4_rtr__SHIFT 0x0000001f
+#define VGT_DEBUG_REG30__tf_fetch_state_q_MASK 0x00070000L
+#define VGT_DEBUG_REG30__tf_fetch_state_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG30__tf_pointer_p0_q_MASK 0x00f00000L
+#define VGT_DEBUG_REG30__tf_pointer_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG30__tf_xfer_count_p2_q_MASK 0x30000000L
+#define VGT_DEBUG_REG30__tf_xfer_count_p2_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG30__ttp_patch_fifo_empty_MASK 0x00000200L
+#define VGT_DEBUG_REG30__ttp_patch_fifo_empty__SHIFT 0x00000009
+#define VGT_DEBUG_REG30__ttp_patch_fifo_full_MASK 0x00000100L
+#define VGT_DEBUG_REG30__ttp_patch_fifo_full__SHIFT 0x00000008
+#define VGT_DEBUG_REG30__ttp_tf0_fifo_empty_MASK 0x00000400L
+#define VGT_DEBUG_REG30__ttp_tf0_fifo_empty__SHIFT 0x0000000a
+#define VGT_DEBUG_REG30__ttp_tf1_fifo_empty_MASK 0x00000800L
+#define VGT_DEBUG_REG30__ttp_tf1_fifo_empty__SHIFT 0x0000000b
+#define VGT_DEBUG_REG30__ttp_tf2_fifo_empty_MASK 0x00001000L
+#define VGT_DEBUG_REG30__ttp_tf2_fifo_empty__SHIFT 0x0000000c
+#define VGT_DEBUG_REG30__ttp_tf3_fifo_empty_MASK 0x00002000L
+#define VGT_DEBUG_REG30__ttp_tf3_fifo_empty__SHIFT 0x0000000d
+#define VGT_DEBUG_REG30__ttp_tf4_fifo_empty_MASK 0x00004000L
+#define VGT_DEBUG_REG30__ttp_tf4_fifo_empty__SHIFT 0x0000000e
+#define VGT_DEBUG_REG30__ttp_tf5_fifo_empty_MASK 0x00008000L
+#define VGT_DEBUG_REG30__ttp_tf5_fifo_empty__SHIFT 0x0000000f
+#define VGT_DEBUG_REG31__inner_ring_done_q_MASK 0x80000000L
+#define VGT_DEBUG_REG31__inner_ring_done_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG31__outer_ring_done_q_MASK 0x40000000L
+#define VGT_DEBUG_REG31__outer_ring_done_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts_MASK 0x00400000L
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts__SHIFT 0x00000016
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts_MASK 0x00800000L
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts__SHIFT 0x00000017
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts_MASK 0x00100000L
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts__SHIFT 0x00000014
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts_MASK 0x00200000L
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts__SHIFT 0x00000015
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG31__pg_edge_fifo_full_MASK 0x10000000L
+#define VGT_DEBUG_REG31__pg_edge_fifo_full__SHIFT 0x0000001c
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty_MASK 0x04000000L
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty__SHIFT 0x0000001a
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full_MASK 0x20000000L
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full__SHIFT 0x0000001d
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty_MASK 0x01000000L
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty__SHIFT 0x00000018
+#define VGT_DEBUG_REG31__pg_patch_fifo_full_MASK 0x08000000L
+#define VGT_DEBUG_REG31__pg_patch_fifo_full__SHIFT 0x0000001b
+#define VGT_DEBUG_REG31__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG31__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG31__pipe0_rtr_MASK 0x00000002L
+#define VGT_DEBUG_REG31__pipe0_rtr__SHIFT 0x00000001
+#define VGT_DEBUG_REG31__pipe1_inner_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG31__pipe1_inner_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG31__pipe1_outer_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG31__pipe1_outer_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG31__pipe2_inner_dr_MASK 0x00000020L
+#define VGT_DEBUG_REG31__pipe2_inner_dr__SHIFT 0x00000005
+#define VGT_DEBUG_REG31__pipe2_inner_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG31__pipe2_inner_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG31__pipe2_outer_dr_MASK 0x00000010L
+#define VGT_DEBUG_REG31__pipe2_outer_dr__SHIFT 0x00000004
+#define VGT_DEBUG_REG31__pipe2_outer_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG31__pipe2_outer_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG31__pipe3_inner_dr_MASK 0x00000080L
+#define VGT_DEBUG_REG31__pipe3_inner_dr__SHIFT 0x00000007
+#define VGT_DEBUG_REG31__pipe3_inner_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG31__pipe3_inner_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG31__pipe3_outer_dr_MASK 0x00000040L
+#define VGT_DEBUG_REG31__pipe3_outer_dr__SHIFT 0x00000006
+#define VGT_DEBUG_REG31__pipe3_outer_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG31__pipe3_outer_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG31__pipe4_inner_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG31__pipe4_inner_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG31__pipe4_inner_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG31__pipe4_inner_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG31__pipe4_outer_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG31__pipe4_outer_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG31__pipe4_outer_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG31__pipe4_outer_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG31__pipe5_inner_dr_MASK 0x00000800L
+#define VGT_DEBUG_REG31__pipe5_inner_dr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG31__pipe5_inner_rtr_MASK 0x00080000L
+#define VGT_DEBUG_REG31__pipe5_inner_rtr__SHIFT 0x00000013
+#define VGT_DEBUG_REG31__pipe5_outer_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG31__pipe5_outer_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG31__pipe5_outer_rtr_MASK 0x00040000L
+#define VGT_DEBUG_REG31__pipe5_outer_rtr__SHIFT 0x00000012
+#define VGT_DEBUG_REG32__event_flag_p5_q_MASK 0x00000100L
+#define VGT_DEBUG_REG32__event_flag_p5_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG32__event_null_special_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG32__event_null_special_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG32__fifos_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG32__fifos_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q_MASK 0x00000400L
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q_MASK 0x00000200L
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG32__first_ring_of_patch_MASK 0x00000001L
+#define VGT_DEBUG_REG32__first_ring_of_patch__SHIFT 0x00000000
+#define VGT_DEBUG_REG32__inner2_fifos_rtr_MASK 0x01000000L
+#define VGT_DEBUG_REG32__inner2_fifos_rtr__SHIFT 0x00000018
+#define VGT_DEBUG_REG32__inner_fifos_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG32__inner_fifos_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring_MASK 0x00000010L
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring__SHIFT 0x00000004
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring_MASK 0x00000004L
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring__SHIFT 0x00000002
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q_MASK 0x00000800L
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG32__last_point_of_inner_edge_MASK 0x00000020L
+#define VGT_DEBUG_REG32__last_point_of_inner_edge__SHIFT 0x00000005
+#define VGT_DEBUG_REG32__last_point_of_outer_edge_MASK 0x00000008L
+#define VGT_DEBUG_REG32__last_point_of_outer_edge__SHIFT 0x00000003
+#define VGT_DEBUG_REG32__last_ring_of_patch_MASK 0x00000002L
+#define VGT_DEBUG_REG32__last_ring_of_patch__SHIFT 0x00000001
+#define VGT_DEBUG_REG32__outer_fifos_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG32__outer_fifos_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full_MASK 0x00020000L
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full__SHIFT 0x00000011
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full_MASK 0x00010000L
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full__SHIFT 0x00000010
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full_MASK 0x00100000L
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full__SHIFT 0x00000014
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full_MASK 0x00040000L
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full__SHIFT 0x00000012
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full_MASK 0x00400000L
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full__SHIFT 0x00000016
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full_MASK 0x00200000L
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full__SHIFT 0x00000015
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full_MASK 0x00080000L
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full__SHIFT 0x00000013
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full_MASK 0x00800000L
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full__SHIFT 0x00000017
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG32__SPARE_MASK 0x80000000L
+#define VGT_DEBUG_REG32__SPARE__SHIFT 0x0000001f
+#define VGT_DEBUG_REG32__tess_topology_p5_q_MASK 0x00003000L
+#define VGT_DEBUG_REG32__tess_topology_p5_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG33__con_prim_fifo_empty_MASK 0x00040000L
+#define VGT_DEBUG_REG33__con_prim_fifo_empty__SHIFT 0x00000012
+#define VGT_DEBUG_REG33__con_prim_fifo_full_MASK 0x00010000L
+#define VGT_DEBUG_REG33__con_prim_fifo_full__SHIFT 0x00000010
+#define VGT_DEBUG_REG33__con_ring1_busy_MASK 0x80000000L
+#define VGT_DEBUG_REG33__con_ring1_busy__SHIFT 0x0000001f
+#define VGT_DEBUG_REG33__con_ring2_busy_MASK 0x40000000L
+#define VGT_DEBUG_REG33__con_ring2_busy__SHIFT 0x0000001e
+#define VGT_DEBUG_REG33__con_ring3_busy_MASK 0x20000000L
+#define VGT_DEBUG_REG33__con_ring3_busy__SHIFT 0x0000001d
+#define VGT_DEBUG_REG33__con_vert_fifo_empty_MASK 0x00080000L
+#define VGT_DEBUG_REG33__con_vert_fifo_empty__SHIFT 0x00000013
+#define VGT_DEBUG_REG33__con_vert_fifo_full_MASK 0x00020000L
+#define VGT_DEBUG_REG33__con_vert_fifo_full__SHIFT 0x00000011
+#define VGT_DEBUG_REG33__first_prim_of_patch_q_MASK 0x00008000L
+#define VGT_DEBUG_REG33__first_prim_of_patch_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG33__pipe0_patch_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG33__pipe0_patch_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG33__pipe0_patch_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG33__pipe0_patch_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG33__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG33__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG33__pipe1_patch_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG33__pipe1_patch_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG33__pipe2_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG33__pipe2_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG33__pipe2_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG33__pipe2_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG33__pipe3_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG33__pipe3_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG33__pipe3_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG33__pipe3_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG33__ring1_in_sync_q_MASK 0x00000800L
+#define VGT_DEBUG_REG33__ring1_in_sync_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG33__ring1_pipe1_dr_MASK 0x00000040L
+#define VGT_DEBUG_REG33__ring1_pipe1_dr__SHIFT 0x00000006
+#define VGT_DEBUG_REG33__ring1_valid_p2_MASK 0x00800000L
+#define VGT_DEBUG_REG33__ring1_valid_p2__SHIFT 0x00000017
+#define VGT_DEBUG_REG33__ring2_in_sync_q_MASK 0x00000400L
+#define VGT_DEBUG_REG33__ring2_in_sync_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG33__ring2_pipe1_dr_MASK 0x00000020L
+#define VGT_DEBUG_REG33__ring2_pipe1_dr__SHIFT 0x00000005
+#define VGT_DEBUG_REG33__ring2_valid_p2_MASK 0x00400000L
+#define VGT_DEBUG_REG33__ring2_valid_p2__SHIFT 0x00000016
+#define VGT_DEBUG_REG33__ring3_in_sync_q_MASK 0x00002000L
+#define VGT_DEBUG_REG33__ring3_in_sync_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG33__ring3_pipe1_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG33__ring3_pipe1_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG33__ring3_valid_p2_MASK 0x00200000L
+#define VGT_DEBUG_REG33__ring3_valid_p2__SHIFT 0x00000015
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en_MASK 0x10000000L
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en__SHIFT 0x0000001c
+#define VGT_DEBUG_REG33__tess_topology_p0_q_MASK 0x0c000000L
+#define VGT_DEBUG_REG33__tess_topology_p0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG33__tess_type_p0_q_MASK 0x03000000L
+#define VGT_DEBUG_REG33__tess_type_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG33__tm_te11_event_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG33__tm_te11_event_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG34__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG34__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG34__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG34__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG34__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG34__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG34__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG34__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG34__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG34__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG34__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG34__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG34__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG34__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG34__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG34__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG34__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG34__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG34__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG34__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG34__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG34__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG34__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG34__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG34__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG34__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG34__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG34__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1_MASK 0x80000000L
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1__SHIFT 0x0000001f
+#define VGT_DEBUG_REG35__event_flag_p1_q_MASK 0x00040000L
+#define VGT_DEBUG_REG35__event_flag_p1_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG35__first_req_of_tg_p1_q_MASK 0x10000000L
+#define VGT_DEBUG_REG35__first_req_of_tg_p1_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG35__last_req_of_tg_p2_MASK 0x00000800L
+#define VGT_DEBUG_REG35__last_req_of_tg_p2__SHIFT 0x0000000b
+#define VGT_DEBUG_REG35__null_flag_p1_q_MASK 0x00080000L
+#define VGT_DEBUG_REG35__null_flag_p1_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG35__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG35__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG35__pipe0_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG35__pipe0_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG35__pipe1_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG35__pipe1_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG35__pipe1_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG35__pipe1_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG35__second_tf_ret_data_q_MASK 0x08000000L
+#define VGT_DEBUG_REG35__second_tf_ret_data_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG35__spi_vgt_hs_done_cnt_q_MASK 0x0003f000L
+#define VGT_DEBUG_REG35__spi_vgt_hs_done_cnt_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG35__TC_VGT_rdret_data_in_MASK 0x80000000L
+#define VGT_DEBUG_REG35__TC_VGT_rdret_data_in__SHIFT 0x0000001f
+#define VGT_DEBUG_REG35__tf_data_fifo_busy_q_MASK 0x00000040L
+#define VGT_DEBUG_REG35__tf_data_fifo_busy_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG35__tf_data_fifo_cnt_q_MASK 0x07f00000L
+#define VGT_DEBUG_REG35__tf_data_fifo_cnt_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG35__tf_data_fifo_rtr_q_MASK 0x00000080L
+#define VGT_DEBUG_REG35__tf_data_fifo_rtr_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_empty_MASK 0x00000010L
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_empty__SHIFT 0x00000004
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_full_MASK 0x00000020L
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_full__SHIFT 0x00000005
+#define VGT_DEBUG_REG35__tf_skid_fifo_empty_MASK 0x00000100L
+#define VGT_DEBUG_REG35__tf_skid_fifo_empty__SHIFT 0x00000008
+#define VGT_DEBUG_REG35__tf_skid_fifo_full_MASK 0x00000200L
+#define VGT_DEBUG_REG35__tf_skid_fifo_full__SHIFT 0x00000009
+#define VGT_DEBUG_REG35__VGT_TC_rdnfo_stall_out_MASK 0x40000000L
+#define VGT_DEBUG_REG35__VGT_TC_rdnfo_stall_out__SHIFT 0x0000001e
+#define VGT_DEBUG_REG35__vgt_tc_rdreq_rtr_q_MASK 0x00000400L
+#define VGT_DEBUG_REG35__vgt_tc_rdreq_rtr_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG35__VGT_TC_rdreq_send_out_MASK 0x20000000L
+#define VGT_DEBUG_REG35__VGT_TC_rdreq_send_out__SHIFT 0x0000001d
+#define VGT_DEBUG_REG3__hsWaveRelInd_MASK 0xfc000000L
+#define VGT_DEBUG_REG3__hsWaveRelInd__SHIFT 0x0000001a
+#define VGT_DEBUG_REG3__lsPatchCnt_MASK 0x03fc0000L
+#define VGT_DEBUG_REG3__lsPatchCnt__SHIFT 0x00000012
+#define VGT_DEBUG_REG3__lsTgRelInd_MASK 0x00000fffL
+#define VGT_DEBUG_REG3__lsTgRelInd__SHIFT 0x00000000
+#define VGT_DEBUG_REG3__lsWaveRelInd_MASK 0x0003f000L
+#define VGT_DEBUG_REG3__lsWaveRelInd__SHIFT 0x0000000c
+#define VGT_DEBUG_REG4__hsCpCnt_MASK 0x1f000000L
+#define VGT_DEBUG_REG4__hsCpCnt__SHIFT 0x00000018
+#define VGT_DEBUG_REG4__hsFwaveFlag_MASK 0x40000000L
+#define VGT_DEBUG_REG4__hsFwaveFlag__SHIFT 0x0000001e
+#define VGT_DEBUG_REG4__hsPatchCnt_MASK 0x000000ffL
+#define VGT_DEBUG_REG4__hsPatchCnt__SHIFT 0x00000000
+#define VGT_DEBUG_REG4__hsPrimId_15_0_MASK 0x00ffff00L
+#define VGT_DEBUG_REG4__hsPrimId_15_0__SHIFT 0x00000008
+#define VGT_DEBUG_REG4__hsWaveSendFlush_MASK 0x20000000L
+#define VGT_DEBUG_REG4__hsWaveSendFlush__SHIFT 0x0000001d
+#define VGT_DEBUG_REG4__SPARE_MASK 0xffffffffL
+#define VGT_DEBUG_REG4__SPARE__SHIFT 0x00000000
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0_MASK 0x0000f800L
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0_MASK 0x000000f8L
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0__SHIFT 0x00000003
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0_MASK 0xf8000000L
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0__SHIFT 0x0000001b
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0_MASK 0x00f80000L
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0__SHIFT 0x00000013
+#define VGT_DEBUG_REG5__SPARE1_MASK 0x07000000L
+#define VGT_DEBUG_REG5__SPARE1__SHIFT 0x00000018
+#define VGT_DEBUG_REG5__SPARE2_MASK 0x00070000L
+#define VGT_DEBUG_REG5__SPARE2__SHIFT 0x00000010
+#define VGT_DEBUG_REG5__SPARE3_MASK 0x00000700L
+#define VGT_DEBUG_REG5__SPARE3__SHIFT 0x00000008
+#define VGT_DEBUG_REG5__SPARE4_MASK 0x00000007L
+#define VGT_DEBUG_REG5__SPARE4__SHIFT 0x00000000
+#define VGT_DEBUG_REG6__debug_BASE_MASK 0x0000ffffL
+#define VGT_DEBUG_REG6__debug_BASE__SHIFT 0x00000000
+#define VGT_DEBUG_REG6__debug_SIZE_MASK 0xffff0000L
+#define VGT_DEBUG_REG6__debug_SIZE__SHIFT 0x00000010
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty_MASK 0x00000001L
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty__SHIFT 0x00000000
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull_MASK 0x00000002L
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull__SHIFT 0x00000001
+#define VGT_DEBUG_REG7__hs_pipe0_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG7__hs_pipe0_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG7__hs_pipe0_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG7__hs_pipe0_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG7__hs_pipe1_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG7__hs_pipe1_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG7__SPARE_MASK 0x0000ffe0L
+#define VGT_DEBUG_REG7__SPARE__SHIFT 0x00000005
+#define VGT_DEBUG_REG7__TF_addr_MASK 0xffff0000L
+#define VGT_DEBUG_REG7__TF_addr__SHIFT 0x00000010
+#define VGT_DEBUG_REG8__es_gs_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG8__es_gs_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG8__gs_event_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG8__gs_event_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q_MASK 0x04000000L
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG8__gsprim_buff_full_q_MASK 0x08000000L
+#define VGT_DEBUG_REG8__gsprim_buff_full_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q_MASK 0x00000020L
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG8__hold_for_es_flush_MASK 0x01000000L
+#define VGT_DEBUG_REG8__hold_for_es_flush__SHIFT 0x00000018
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty_MASK 0x00040000L
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty__SHIFT 0x00000012
+#define VGT_DEBUG_REG8__r0_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG8__r0_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG8__r1_inst_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG8__r1_inst_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG8__r1_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG8__r1_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG8__r2_indx_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG8__r2_indx_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG8__r2_no_bp_rtr_MASK 0x00800000L
+#define VGT_DEBUG_REG8__r2_no_bp_rtr__SHIFT 0x00000017
+#define VGT_DEBUG_REG8__r2_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG8__r2_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG8__rcm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG8__rcm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG8__rcm_noif_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG8__rcm_noif_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q_MASK 0x00000010L
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q_MASK 0x00000008L
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG8__te_prim_fifo_empty_MASK 0x10000000L
+#define VGT_DEBUG_REG8__te_prim_fifo_empty__SHIFT 0x0000001c
+#define VGT_DEBUG_REG8__te_prim_fifo_full_MASK 0x20000000L
+#define VGT_DEBUG_REG8__te_prim_fifo_full__SHIFT 0x0000001d
+#define VGT_DEBUG_REG8__te_vert_fifo_empty_MASK 0x40000000L
+#define VGT_DEBUG_REG8__te_vert_fifo_empty__SHIFT 0x0000001e
+#define VGT_DEBUG_REG8__te_vert_fifo_full_MASK 0x80000000L
+#define VGT_DEBUG_REG8__te_vert_fifo_full__SHIFT 0x0000001f
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG8__valid_r0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG8__valid_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG8__valid_r1_q_MASK 0x00000080L
+#define VGT_DEBUG_REG8__valid_r1_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG8__valid_r2_MASK 0x00000100L
+#define VGT_DEBUG_REG8__valid_r2_q_MASK 0x00000200L
+#define VGT_DEBUG_REG8__valid_r2_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG8__valid_r2__SHIFT 0x00000008
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q_MASK 0x00400000L
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q_MASK 0x00080000L
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG9__eop_indx_r3_MASK 0x00000010L
+#define VGT_DEBUG_REG9__eop_indx_r3__SHIFT 0x00000004
+#define VGT_DEBUG_REG9__eop_prim_r3_MASK 0x00000020L
+#define VGT_DEBUG_REG9__eop_prim_r3__SHIFT 0x00000005
+#define VGT_DEBUG_REG9__es_eov_r3_MASK 0x00000040L
+#define VGT_DEBUG_REG9__es_eov_r3__SHIFT 0x00000006
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0_MASK 0x02000000L
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0__SHIFT 0x00000019
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0_MASK 0x00000080L
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0__SHIFT 0x00000007
+#define VGT_DEBUG_REG9__gs_eov_r3_MASK 0x00000008L
+#define VGT_DEBUG_REG9__gs_eov_r3__SHIFT 0x00000003
+#define VGT_DEBUG_REG9__gs_instancing_state_q_MASK 0x01000000L
+#define VGT_DEBUG_REG9__gs_instancing_state_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q_MASK 0x00400000L
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0_MASK 0x04000000L
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q_MASK 0x00040000L
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0_MASK 0x00000400L
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0__SHIFT 0x0000000a
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q_MASK 0x0003f800L
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q_MASK 0x00380000L
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG9__indices_to_send_r2_q_MASK 0x00000003L
+#define VGT_DEBUG_REG9__indices_to_send_r2_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q_MASK 0x00800000L
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q__SHIFT 0x00000017
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q_MASK 0x80000000L
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG9__pending_es_flush_r3_MASK 0x00000200L
+#define VGT_DEBUG_REG9__pending_es_flush_r3__SHIFT 0x00000009
+#define VGT_DEBUG_REG9__pending_es_send_r3_q_MASK 0x00000100L
+#define VGT_DEBUG_REG9__pending_es_send_r3_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG9__pre_r0_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG9__pre_r0_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG9__SPARE0_MASK 0x40000000L
+#define VGT_DEBUG_REG9__SPARE0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG9__valid_indices_r3_MASK 0x00000004L
+#define VGT_DEBUG_REG9__valid_indices_r3__SHIFT 0x00000002
+#define VGT_DEBUG_REG9__valid_pre_r0_q_MASK 0x20000000L
+#define VGT_DEBUG_REG9__valid_pre_r0_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG9__valid_r3_q_MASK 0x10000000L
+#define VGT_DEBUG_REG9__valid_r3_q__SHIFT 0x0000001c
+#define VGT_DMA_BASE__BASE_ADDR_MASK 0xffffffffL
+#define VGT_DMA_BASE__BASE_ADDR__SHIFT 0x00000000
+#define VGT_DMA_BASE_HI__BASE_ADDR_MASK 0x000000ffL
+#define VGT_DMA_BASE_HI__BASE_ADDR__SHIFT 0x00000000
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH_MASK 0x000001ffL
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DMA_INDEX_TYPE__ATC_MASK 0x00000100L
+#define VGT_DMA_INDEX_TYPE__ATC__SHIFT 0x00000008
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE_MASK 0x00000030L
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE__SHIFT 0x00000004
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE_MASK 0x00000003L
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE__SHIFT 0x00000000
+#define VGT_DMA_INDEX_TYPE__NOT_EOP_MASK 0x00000200L
+#define VGT_DMA_INDEX_TYPE__NOT_EOP__SHIFT 0x00000009
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY_MASK 0x000000c0L
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY__SHIFT 0x00000006
+#define VGT_DMA_INDEX_TYPE__REQ_PATH_MASK 0x00000400L
+#define VGT_DMA_INDEX_TYPE__REQ_PATH__SHIFT 0x0000000a
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE_MASK 0x0000000cL
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE__SHIFT 0x00000002
+#define VGT_DMA_MAX_SIZE__MAX_SIZE_MASK 0xffffffffL
+#define VGT_DMA_MAX_SIZE__MAX_SIZE__SHIFT 0x00000000
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffffL
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x00000000
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH_MASK 0x0000003fL
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DMA_SIZE__NUM_INDICES_MASK 0xffffffffL
+#define VGT_DMA_SIZE__NUM_INDICES__SHIFT 0x00000000
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH_MASK 0x0000003fL
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DRAW_INITIATOR__MAJOR_MODE_MASK 0x0000000cL
+#define VGT_DRAW_INITIATOR__MAJOR_MODE__SHIFT 0x00000002
+#define VGT_DRAW_INITIATOR__NOT_EOP_MASK 0x00000020L
+#define VGT_DRAW_INITIATOR__NOT_EOP__SHIFT 0x00000005
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT_MASK 0x00000003L
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT__SHIFT 0x00000000
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX_MASK 0x00000010L
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX__SHIFT 0x00000004
+#define VGT_DRAW_INITIATOR__USE_OPAQUE_MASK 0x00000040L
+#define VGT_DRAW_INITIATOR__USE_OPAQUE__SHIFT 0x00000006
+#define VGT_ENHANCE__MISC_MASK 0xffffffffL
+#define VGT_ENHANCE__MISC__SHIFT 0x00000000
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_ESGS_RING_SIZE__MEM_SIZE_MASK 0xffffffffL
+#define VGT_ESGS_RING_SIZE__MEM_SIZE__SHIFT 0x00000000
+#define VGT_ES_PER_GS__ES_PER_GS_MASK 0x000007ffL
+#define VGT_ES_PER_GS__ES_PER_GS__SHIFT 0x00000000
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW_MASK 0x0fffffffL
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW__SHIFT 0x00000000
+#define VGT_EVENT_INITIATOR__ADDRESS_HI_MASK 0x07fc0000L
+#define VGT_EVENT_INITIATOR__ADDRESS_HI__SHIFT 0x00000012
+#define VGT_EVENT_INITIATOR__EVENT_TYPE_MASK 0x0000003fL
+#define VGT_EVENT_INITIATOR__EVENT_TYPE__SHIFT 0x00000000
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT_MASK 0x08000000L
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT__SHIFT 0x0000001b
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH_MASK 0x003fff00L
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH__SHIFT 0x00000008
+#define VGT_FIFO_DEPTHS__RESERVED_0_MASK 0x00000080L
+#define VGT_FIFO_DEPTHS__RESERVED_0__SHIFT 0x00000007
+#define VGT_FIFO_DEPTHS__RESERVED_1_MASK 0xffc00000L
+#define VGT_FIFO_DEPTHS__RESERVED_1__SHIFT 0x00000016
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH_MASK 0x0000007fL
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH__SHIFT 0x00000000
+#define VGT_GROUP_DECR__DECR_MASK 0x0000000fL
+#define VGT_GROUP_DECR__DECR__SHIFT 0x00000000
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR_MASK 0x0000000fL
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR__SHIFT 0x00000000
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER_MASK 0x00070000L
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER__SHIFT 0x00000010
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE_MASK 0x0000001fL
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE__SHIFT 0x00000000
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER_MASK 0x00004000L
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER__SHIFT 0x0000000e
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS_MASK 0x00008000L
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS__SHIFT 0x0000000f
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN_MASK 0x00000008L
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN__SHIFT 0x00000003
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN_MASK 0x00000001L
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN__SHIFT 0x00000000
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN_MASK 0x00000002L
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN__SHIFT 0x00000001
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN_MASK 0x00000004L
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN__SHIFT 0x00000002
+#define VGT_GROUP_VECT_0_CNTL__SHIFT_MASK 0x00ff0000L
+#define VGT_GROUP_VECT_0_CNTL__SHIFT__SHIFT 0x00000010
+#define VGT_GROUP_VECT_0_CNTL__STRIDE_MASK 0x0000ff00L
+#define VGT_GROUP_VECT_0_CNTL__STRIDE__SHIFT 0x00000008
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV_MASK 0x0f000000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV__SHIFT 0x00000018
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET_MASK 0xf0000000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET__SHIFT 0x0000001c
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV_MASK 0x0000000fL
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV__SHIFT 0x00000000
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET_MASK 0x000000f0L
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET__SHIFT 0x00000004
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV_MASK 0x00000f00L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV__SHIFT 0x00000008
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET_MASK 0x0000f000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET__SHIFT 0x0000000c
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV_MASK 0x000f0000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV__SHIFT 0x00000010
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET_MASK 0x00f00000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET__SHIFT 0x00000014
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN_MASK 0x00000008L
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN__SHIFT 0x00000003
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN_MASK 0x00000001L
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN__SHIFT 0x00000000
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN_MASK 0x00000002L
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN__SHIFT 0x00000001
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN_MASK 0x00000004L
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN__SHIFT 0x00000002
+#define VGT_GROUP_VECT_1_CNTL__SHIFT_MASK 0x00ff0000L
+#define VGT_GROUP_VECT_1_CNTL__SHIFT__SHIFT 0x00000010
+#define VGT_GROUP_VECT_1_CNTL__STRIDE_MASK 0x0000ff00L
+#define VGT_GROUP_VECT_1_CNTL__STRIDE__SHIFT 0x00000008
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV_MASK 0x0f000000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV__SHIFT 0x00000018
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET_MASK 0xf0000000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET__SHIFT 0x0000001c
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV_MASK 0x0000000fL
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV__SHIFT 0x00000000
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET_MASK 0x000000f0L
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET__SHIFT 0x00000004
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV_MASK 0x00000f00L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV__SHIFT 0x00000008
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET_MASK 0x0000f000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET__SHIFT 0x0000000c
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV_MASK 0x000f0000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV__SHIFT 0x00000010
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET_MASK 0x00f00000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET__SHIFT 0x00000014
+#define VGT_GS_INSTANCE_CNT__CNT_MASK 0x000001fcL
+#define VGT_GS_INSTANCE_CNT__CNT__SHIFT 0x00000002
+#define VGT_GS_INSTANCE_CNT__ENABLE_MASK 0x00000001L
+#define VGT_GS_INSTANCE_CNT__ENABLE__SHIFT 0x00000000
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT_MASK 0x000007ffL
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT__SHIFT 0x00000000
+#define VGT_GS_MODE__COMPUTE_MODE_MASK 0x00004000L
+#define VGT_GS_MODE__COMPUTE_MODE__SHIFT 0x0000000e
+#define VGT_GS_MODE__CUT_MODE_MASK 0x00000030L
+#define VGT_GS_MODE__CUT_MODE__SHIFT 0x00000004
+#define VGT_GS_MODE__ELEMENT_INFO_EN_MASK 0x00010000L
+#define VGT_GS_MODE__ELEMENT_INFO_EN__SHIFT 0x00000010
+#define VGT_GS_MODE__ES_PASSTHRU_MASK 0x00002000L
+#define VGT_GS_MODE__ES_PASSTHRU__SHIFT 0x0000000d
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE_MASK 0x00080000L
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE__SHIFT 0x00000013
+#define VGT_GS_MODE__FAST_COMPUTE_MODE_MASK 0x00008000L
+#define VGT_GS_MODE__FAST_COMPUTE_MODE__SHIFT 0x0000000f
+#define VGT_GS_MODE__GS_C_PACK_EN_MASK 0x00000800L
+#define VGT_GS_MODE__GS_C_PACK_EN__SHIFT 0x0000000b
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE_MASK 0x00100000L
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE__SHIFT 0x00000014
+#define VGT_GS_MODE__MODE_MASK 0x00000007L
+#define VGT_GS_MODE__MODE__SHIFT 0x00000000
+#define VGT_GS_MODE__ONCHIP_MASK 0x00600000L
+#define VGT_GS_MODE__ONCHIP__SHIFT 0x00000015
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI_MASK 0x00020000L
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI__SHIFT 0x00000011
+#define VGT_GS_MODE__RESERVED_0_MASK 0x00000008L
+#define VGT_GS_MODE__RESERVED_0__SHIFT 0x00000003
+#define VGT_GS_MODE__RESERVED_1_MASK 0x000007c0L
+#define VGT_GS_MODE__RESERVED_1__SHIFT 0x00000006
+#define VGT_GS_MODE__RESERVED_2_MASK 0x00001000L
+#define VGT_GS_MODE__RESERVED_2__SHIFT 0x0000000c
+#define VGT_GS_MODE__SUPPRESS_CUTS_MASK 0x00040000L
+#define VGT_GS_MODE__SUPPRESS_CUTS__SHIFT 0x00000012
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1_MASK 0x00003f00L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1__SHIFT 0x00000008
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2_MASK 0x003f0000L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2__SHIFT 0x00000010
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3_MASK 0x0fc00000L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3__SHIFT 0x00000016
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_MASK 0x0000003fL
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE__SHIFT 0x00000000
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM_MASK 0x80000000L
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM__SHIFT 0x0000001f
+#define VGT_GS_PER_ES__GS_PER_ES_MASK 0x000007ffL
+#define VGT_GS_PER_ES__GS_PER_ES__SHIFT 0x00000000
+#define VGT_GS_PER_VS__GS_PER_VS_MASK 0x0000000fL
+#define VGT_GS_PER_VS__GS_PER_VS__SHIFT 0x00000000
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE_MASK 0x0000001fL
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_1__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_1__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_2__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_2__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_3__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_3__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_SIZE__MEM_SIZE_MASK 0xffffffffL
+#define VGT_GSVS_RING_SIZE__MEM_SIZE__SHIFT 0x00000000
+#define VGT_HOS_CNTL__TESS_MODE_MASK 0x00000003L
+#define VGT_HOS_CNTL__TESS_MODE__SHIFT 0x00000000
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS_MASK 0xffffffffL
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS__SHIFT 0x00000000
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS_MASK 0xffffffffL
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS__SHIFT 0x00000000
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH_MASK 0x000000ffL
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH__SHIFT 0x00000000
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING_MASK 0x0000007fL
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING__SHIFT 0x00000000
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY_MASK 0x00000600L
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY__SHIFT 0x00000009
+#define VGT_IMMED_DATA__DATA_MASK 0xffffffffL
+#define VGT_IMMED_DATA__DATA__SHIFT 0x00000000
+#define VGT_INDEX_TYPE__INDEX_TYPE_MASK 0x00000003L
+#define VGT_INDEX_TYPE__INDEX_TYPE__SHIFT 0x00000000
+#define VGT_INDX_OFFSET__INDX_OFFSET_MASK 0xffffffffL
+#define VGT_INDX_OFFSET__INDX_OFFSET__SHIFT 0x00000000
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE_MASK 0xffffffffL
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE__SHIFT 0x00000000
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE_MASK 0xffffffffL
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE__SHIFT 0x00000000
+#define VGT_LAST_COPY_STATE__DST_STATE_ID_MASK 0x00070000L
+#define VGT_LAST_COPY_STATE__DST_STATE_ID__SHIFT 0x00000010
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP_MASK 0x00003f00L
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP__SHIFT 0x00000008
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP_MASK 0x000fc000L
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP__SHIFT 0x0000000e
+#define VGT_LS_HS_CONFIG__NUM_PATCHES_MASK 0x000000ffL
+#define VGT_LS_HS_CONFIG__NUM_PATCHES__SHIFT 0x00000000
+#define VGT_MAX_VTX_INDX__MAX_INDX_MASK 0xffffffffL
+#define VGT_MAX_VTX_INDX__MAX_INDX__SHIFT 0x00000000
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES_MASK 0x00000003L
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES__SHIFT 0x00000000
+#define VGT_MIN_VTX_INDX__MIN_INDX_MASK 0xffffffffL
+#define VGT_MIN_VTX_INDX__MIN_INDX__SHIFT 0x00000000
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN_MASK 0x00000001L
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN__SHIFT 0x00000000
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX_MASK 0xffffffffL
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX__SHIFT 0x00000000
+#define VGT_NUM_INDICES__NUM_INDICES_MASK 0xffffffffL
+#define VGT_NUM_INDICES__NUM_INDICES__SHIFT 0x00000000
+#define VGT_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffffL
+#define VGT_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x00000000
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST_MASK 0x0000007fL
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST__SHIFT 0x00000000
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT_MASK 0x00000007L
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK_MASK 0x000000ffL
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK__SHIFT 0x00000000
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI_MASK 0x00000002L
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI__SHIFT 0x00000001
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN_MASK 0x00000001L
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN__SHIFT 0x00000000
+#define VGT_PRIMITIVEID_RESET__VALUE_MASK 0xffffffffL
+#define VGT_PRIMITIVEID_RESET__VALUE__SHIFT 0x00000000
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE_MASK 0x0000003fL
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE__SHIFT 0x00000000
+#define VGT_REUSE_OFF__REUSE_OFF_MASK 0x00000001L
+#define VGT_REUSE_OFF__REUSE_OFF__SHIFT 0x00000000
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS_MASK 0x00000100L
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS__SHIFT 0x00000008
+#define VGT_SHADER_STAGES_EN__ES_EN_MASK 0x00000018L
+#define VGT_SHADER_STAGES_EN__ES_EN__SHIFT 0x00000003
+#define VGT_SHADER_STAGES_EN__GS_EN_MASK 0x00000020L
+#define VGT_SHADER_STAGES_EN__GS_EN__SHIFT 0x00000005
+#define VGT_SHADER_STAGES_EN__HS_EN_MASK 0x00000004L
+#define VGT_SHADER_STAGES_EN__HS_EN__SHIFT 0x00000002
+#define VGT_SHADER_STAGES_EN__LS_EN_MASK 0x00000003L
+#define VGT_SHADER_STAGES_EN__LS_EN__SHIFT 0x00000000
+#define VGT_SHADER_STAGES_EN__VS_EN_MASK 0x000000c0L
+#define VGT_SHADER_STAGES_EN__VS_EN__SHIFT 0x00000006
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN_MASK 0x0000000fL
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN_MASK 0x000000f0L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN__SHIFT 0x00000004
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN_MASK 0x00000f00L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN__SHIFT 0x00000008
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN_MASK 0x0000f000L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN__SHIFT 0x0000000c
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK 0x00000070L
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK_MASK 0x00000f00L
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK__SHIFT 0x00000008
+#define VGT_STRMOUT_CONFIG__RAST_STREAM__SHIFT 0x00000004
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN_MASK 0x00000001L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN__SHIFT 0x00000000
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN_MASK 0x00000002L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN__SHIFT 0x00000001
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN_MASK 0x00000004L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN__SHIFT 0x00000002
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN_MASK 0x00000008L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN__SHIFT 0x00000003
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK_MASK 0x80000000L
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK__SHIFT 0x0000001f
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE_MASK 0x000001ffL
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE__SHIFT 0x00000000
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE_MASK 0x00000080L
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE__SHIFT 0x00000007
+#define VGT_SYS_CONFIG__DUAL_CORE_EN_MASK 0x00000001L
+#define VGT_SYS_CONFIG__DUAL_CORE_EN__SHIFT 0x00000000
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP_MASK 0x0000007eL
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP__SHIFT 0x00000001
+#define VGT_TF_MEMORY_BASE__BASE_MASK 0xffffffffL
+#define VGT_TF_MEMORY_BASE__BASE__SHIFT 0x00000000
+#define VGT_TF_PARAM__DEPRECATED_MASK 0x00000200L
+#define VGT_TF_PARAM__DEPRECATED__SHIFT 0x00000009
+#define VGT_TF_PARAM__DISABLE_DONUTS_MASK 0x00004000L
+#define VGT_TF_PARAM__DISABLE_DONUTS__SHIFT 0x0000000e
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD_MASK 0x00003c00L
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD__SHIFT 0x0000000a
+#define VGT_TF_PARAM__PARTITIONING_MASK 0x0000001cL
+#define VGT_TF_PARAM__PARTITIONING__SHIFT 0x00000002
+#define VGT_TF_PARAM__RDREQ_POLICY_MASK 0x00018000L
+#define VGT_TF_PARAM__RDREQ_POLICY__SHIFT 0x0000000f
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS_MASK 0x00000100L
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS__SHIFT 0x00000008
+#define VGT_TF_PARAM__TOPOLOGY_MASK 0x000000e0L
+#define VGT_TF_PARAM__TOPOLOGY__SHIFT 0x00000005
+#define VGT_TF_PARAM__TYPE_MASK 0x00000003L
+#define VGT_TF_PARAM__TYPE__SHIFT 0x00000000
+#define VGT_TF_RING_SIZE__SIZE_MASK 0x0000ffffL
+#define VGT_TF_RING_SIZE__SIZE__SHIFT 0x00000000
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH_MASK 0x000000ffL
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH__SHIFT 0x00000000
+#define VGT_VTX_CNT_EN__VTX_CNT_EN_MASK 0x00000001L
+#define VGT_VTX_CNT_EN__VTX_CNT_EN__SHIFT 0x00000000
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT_MASK 0x000003ffL
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT__SHIFT 0x00000000
+#define WD_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define WD_DEBUG_DATA__DATA__SHIFT 0x00000000
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h
new file mode 100644
index 000000000000..dc4e5b93801d
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h
@@ -0,0 +1,1274 @@
+/*
+ *
+ * Copyright (C) 2016 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 GMC_6_0_D_H
+#define GMC_6_0_D_H
+
+#define ixMC_IO_DEBUG_ACMD_CLKSEL_D0 0x00CE
+#define ixMC_IO_DEBUG_ACMD_CLKSEL_D1 0x00DE
+#define ixMC_IO_DEBUG_ACMD_MISC_D0 0x00AE
+#define ixMC_IO_DEBUG_ACMD_MISC_D1 0x00BE
+#define ixMC_IO_DEBUG_ACMD_OFSCAL_D0 0x00EE
+#define ixMC_IO_DEBUG_ACMD_OFSCAL_D1 0x00FE
+#define ixMC_IO_DEBUG_ACMD_RXPHASE_D0 0x010E
+#define ixMC_IO_DEBUG_ACMD_RXPHASE_D1 0x011E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PD_D0 0x018E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PD_D1 0x019E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PU_D0 0x01AE
+#define ixMC_IO_DEBUG_ACMD_TXBST_PU_D1 0x01BE
+#define ixMC_IO_DEBUG_ACMD_TXPHASE_D0 0x012E
+#define ixMC_IO_DEBUG_ACMD_TXPHASE_D1 0x013E
+#define ixMC_IO_DEBUG_ACMD_TXSLF_D0 0x016E
+#define ixMC_IO_DEBUG_ACMD_TXSLF_D1 0x017E
+#define ixMC_IO_DEBUG_ADDRH_CLKSEL_D0 0x00CD
+#define ixMC_IO_DEBUG_ADDRH_CLKSEL_D1 0x00DD
+#define ixMC_IO_DEBUG_ADDRH_MISC_D0 0x00AD
+#define ixMC_IO_DEBUG_ADDRH_MISC_D1 0x00BD
+#define ixMC_IO_DEBUG_ADDRH_RXPHASE_D0 0x010D
+#define ixMC_IO_DEBUG_ADDRH_RXPHASE_D1 0x011D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PD_D0 0x018D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PD_D1 0x019D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PU_D0 0x01AD
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PU_D1 0x01BD
+#define ixMC_IO_DEBUG_ADDRH_TXPHASE_D0 0x012D
+#define ixMC_IO_DEBUG_ADDRH_TXPHASE_D1 0x013D
+#define ixMC_IO_DEBUG_ADDRH_TXSLF_D0 0x016D
+#define ixMC_IO_DEBUG_ADDRH_TXSLF_D1 0x017D
+#define ixMC_IO_DEBUG_ADDRL_CLKSEL_D0 0x00CC
+#define ixMC_IO_DEBUG_ADDRL_CLKSEL_D1 0x00DC
+#define ixMC_IO_DEBUG_ADDRL_MISC_D0 0x00AC
+#define ixMC_IO_DEBUG_ADDRL_MISC_D1 0x00BC
+#define ixMC_IO_DEBUG_ADDRL_RXPHASE_D0 0x010C
+#define ixMC_IO_DEBUG_ADDRL_RXPHASE_D1 0x011C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PD_D0 0x018C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PD_D1 0x019C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PU_D0 0x01AC
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PU_D1 0x01BC
+#define ixMC_IO_DEBUG_ADDRL_TXPHASE_D0 0x012C
+#define ixMC_IO_DEBUG_ADDRL_TXPHASE_D1 0x013C
+#define ixMC_IO_DEBUG_ADDRL_TXSLF_D0 0x016C
+#define ixMC_IO_DEBUG_ADDRL_TXSLF_D1 0x017C
+#define ixMC_IO_DEBUG_CK_CLKSEL_D0 0x00CB
+#define ixMC_IO_DEBUG_CK_CLKSEL_D1 0x00DB
+#define ixMC_IO_DEBUG_CK_MISC_D0 0x00AB
+#define ixMC_IO_DEBUG_CK_MISC_D1 0x00BB
+#define ixMC_IO_DEBUG_CK_RXPHASE_D0 0x010B
+#define ixMC_IO_DEBUG_CK_RXPHASE_D1 0x011B
+#define ixMC_IO_DEBUG_CK_TXBST_PD_D0 0x018B
+#define ixMC_IO_DEBUG_CK_TXBST_PD_D1 0x019B
+#define ixMC_IO_DEBUG_CK_TXBST_PU_D0 0x01AB
+#define ixMC_IO_DEBUG_CK_TXBST_PU_D1 0x01BB
+#define ixMC_IO_DEBUG_CK_TXPHASE_D0 0x012B
+#define ixMC_IO_DEBUG_CK_TXPHASE_D1 0x013B
+#define ixMC_IO_DEBUG_CK_TXSLF_D0 0x016B
+#define ixMC_IO_DEBUG_CK_TXSLF_D1 0x017B
+#define ixMC_IO_DEBUG_CMD_CLKSEL_D0 0x00CF
+#define ixMC_IO_DEBUG_CMD_CLKSEL_D1 0x00DF
+#define ixMC_IO_DEBUG_CMD_MISC_D0 0x00AF
+#define ixMC_IO_DEBUG_CMD_MISC_D1 0x00BF
+#define ixMC_IO_DEBUG_CMD_OFSCAL_D0 0x00EF
+#define ixMC_IO_DEBUG_CMD_OFSCAL_D1 0x00FF
+#define ixMC_IO_DEBUG_CMD_RX_EQ_D0 0x01CF
+#define ixMC_IO_DEBUG_CMD_RX_EQ_D1 0x01DF
+#define ixMC_IO_DEBUG_CMD_RXPHASE_D0 0x010F
+#define ixMC_IO_DEBUG_CMD_RXPHASE_D1 0x011F
+#define ixMC_IO_DEBUG_CMD_TXBST_PD_D0 0x018F
+#define ixMC_IO_DEBUG_CMD_TXBST_PD_D1 0x019F
+#define ixMC_IO_DEBUG_CMD_TXBST_PU_D0 0x01AF
+#define ixMC_IO_DEBUG_CMD_TXBST_PU_D1 0x01BF
+#define ixMC_IO_DEBUG_CMD_TXPHASE_D0 0x012F
+#define ixMC_IO_DEBUG_CMD_TXPHASE_D1 0x013F
+#define ixMC_IO_DEBUG_CMD_TXSLF_D0 0x016F
+#define ixMC_IO_DEBUG_CMD_TXSLF_D1 0x017F
+#define ixMC_IO_DEBUG_DBI_CDR_PHSIZE_D0 0x014F
+#define ixMC_IO_DEBUG_DBI_CDR_PHSIZE_D1 0x015F
+#define ixMC_IO_DEBUG_DBI_CLKSEL_D0 0x00C8
+#define ixMC_IO_DEBUG_DBI_CLKSEL_D1 0x00D8
+#define ixMC_IO_DEBUG_DBI_MISC_D0 0x00A8
+#define ixMC_IO_DEBUG_DBI_MISC_D1 0x00B8
+#define ixMC_IO_DEBUG_DBI_OFSCAL_D0 0x00E8
+#define ixMC_IO_DEBUG_DBI_OFSCAL_D1 0x00F8
+#define ixMC_IO_DEBUG_DBI_RX_EQ_D0 0x01C8
+#define ixMC_IO_DEBUG_DBI_RX_EQ_D1 0x01D8
+#define ixMC_IO_DEBUG_DBI_RXPHASE_D0 0x0108
+#define ixMC_IO_DEBUG_DBI_RXPHASE_D1 0x0118
+#define ixMC_IO_DEBUG_DBI_RX_VREF_CAL_D0 0x0148
+#define ixMC_IO_DEBUG_DBI_RX_VREF_CAL_D1 0x0158
+#define ixMC_IO_DEBUG_DBI_TXBST_PD_D0 0x0188
+#define ixMC_IO_DEBUG_DBI_TXBST_PD_D1 0x0198
+#define ixMC_IO_DEBUG_DBI_TXBST_PU_D0 0x01A8
+#define ixMC_IO_DEBUG_DBI_TXBST_PU_D1 0x01B8
+#define ixMC_IO_DEBUG_DBI_TXPHASE_D0 0x0128
+#define ixMC_IO_DEBUG_DBI_TXPHASE_D1 0x0138
+#define ixMC_IO_DEBUG_DBI_TXSLF_D0 0x0168
+#define ixMC_IO_DEBUG_DBI_TXSLF_D1 0x0178
+#define ixMC_IO_DEBUG_DQ0_RX_DYN_PM_D0 0x01CD
+#define ixMC_IO_DEBUG_DQ0_RX_DYN_PM_D1 0x01DD
+#define ixMC_IO_DEBUG_DQ0_RX_EQ_PM_D0 0x01CB
+#define ixMC_IO_DEBUG_DQ0_RX_EQ_PM_D1 0x01DB
+#define ixMC_IO_DEBUG_DQ1_RX_DYN_PM_D0 0x01CE
+#define ixMC_IO_DEBUG_DQ1_RX_DYN_PM_D1 0x01DE
+#define ixMC_IO_DEBUG_DQ1_RX_EQ_PM_D0 0x01CC
+#define ixMC_IO_DEBUG_DQ1_RX_EQ_PM_D1 0x01DC
+#define ixMC_IO_DEBUG_DQB0_CDR_PHSIZE_D0 0x014B
+#define ixMC_IO_DEBUG_DQB0_CDR_PHSIZE_D1 0x015B
+#define ixMC_IO_DEBUG_DQB0H_CLKSEL_D0 0x00C1
+#define ixMC_IO_DEBUG_DQB0H_CLKSEL_D1 0x00D1
+#define ixMC_IO_DEBUG_DQB0H_MISC_D0 0x00A1
+#define ixMC_IO_DEBUG_DQB0H_MISC_D1 0x00B1
+#define ixMC_IO_DEBUG_DQB0H_OFSCAL_D0 0x00E1
+#define ixMC_IO_DEBUG_DQB0H_OFSCAL_D1 0x00F1
+#define ixMC_IO_DEBUG_DQB0H_RX_EQ_D0 0x01C1
+#define ixMC_IO_DEBUG_DQB0H_RX_EQ_D1 0x01D1
+#define ixMC_IO_DEBUG_DQB0H_RXPHASE_D0 0x0101
+#define ixMC_IO_DEBUG_DQB0H_RXPHASE_D1 0x0111
+#define ixMC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0 0x0141
+#define ixMC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1 0x0151
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PD_D0 0x0181
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PD_D1 0x0191
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PU_D0 0x01A1
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PU_D1 0x01B1
+#define ixMC_IO_DEBUG_DQB0H_TXPHASE_D0 0x0121
+#define ixMC_IO_DEBUG_DQB0H_TXPHASE_D1 0x0131
+#define ixMC_IO_DEBUG_DQB0H_TXSLF_D0 0x0161
+#define ixMC_IO_DEBUG_DQB0H_TXSLF_D1 0x0171
+#define ixMC_IO_DEBUG_DQB0L_CLKSEL_D0 0x00C0
+#define ixMC_IO_DEBUG_DQB0L_CLKSEL_D1 0x00D0
+#define ixMC_IO_DEBUG_DQB0L_MISC_D0 0x00A0
+#define ixMC_IO_DEBUG_DQB0L_MISC_D1 0x00B0
+#define ixMC_IO_DEBUG_DQB0L_OFSCAL_D0 0x00E0
+#define ixMC_IO_DEBUG_DQB0L_OFSCAL_D1 0x00F0
+#define ixMC_IO_DEBUG_DQB0L_RX_EQ_D0 0x01C0
+#define ixMC_IO_DEBUG_DQB0L_RX_EQ_D1 0x01D0
+#define ixMC_IO_DEBUG_DQB0L_RXPHASE_D0 0x0100
+#define ixMC_IO_DEBUG_DQB0L_RXPHASE_D1 0x0110
+#define ixMC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0 0x0140
+#define ixMC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1 0x0150
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PD_D0 0x0180
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PD_D1 0x0190
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PU_D0 0x01A0
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PU_D1 0x01B0
+#define ixMC_IO_DEBUG_DQB0L_TXPHASE_D0 0x0120
+#define ixMC_IO_DEBUG_DQB0L_TXPHASE_D1 0x0130
+#define ixMC_IO_DEBUG_DQB0L_TXSLF_D0 0x0160
+#define ixMC_IO_DEBUG_DQB0L_TXSLF_D1 0x0170
+#define ixMC_IO_DEBUG_DQB1_CDR_PHSIZE_D0 0x014C
+#define ixMC_IO_DEBUG_DQB1_CDR_PHSIZE_D1 0x015C
+#define ixMC_IO_DEBUG_DQB1H_CLKSEL_D0 0x00C3
+#define ixMC_IO_DEBUG_DQB1H_CLKSEL_D1 0x00D3
+#define ixMC_IO_DEBUG_DQB1H_MISC_D0 0x00A3
+#define ixMC_IO_DEBUG_DQB1H_MISC_D1 0x00B3
+#define ixMC_IO_DEBUG_DQB1H_OFSCAL_D0 0x00E3
+#define ixMC_IO_DEBUG_DQB1H_OFSCAL_D1 0x00F3
+#define ixMC_IO_DEBUG_DQB1H_RX_EQ_D0 0x01C3
+#define ixMC_IO_DEBUG_DQB1H_RX_EQ_D1 0x01D3
+#define ixMC_IO_DEBUG_DQB1H_RXPHASE_D0 0x0103
+#define ixMC_IO_DEBUG_DQB1H_RXPHASE_D1 0x0113
+#define ixMC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0 0x0143
+#define ixMC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1 0x0153
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PD_D0 0x0183
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PD_D1 0x0193
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PU_D0 0x01A3
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PU_D1 0x01B3
+#define ixMC_IO_DEBUG_DQB1H_TXPHASE_D0 0x0123
+#define ixMC_IO_DEBUG_DQB1H_TXPHASE_D1 0x0133
+#define ixMC_IO_DEBUG_DQB1H_TXSLF_D0 0x0163
+#define ixMC_IO_DEBUG_DQB1H_TXSLF_D1 0x0173
+#define ixMC_IO_DEBUG_DQB1L_CLKSEL_D0 0x00C2
+#define ixMC_IO_DEBUG_DQB1L_CLKSEL_D1 0x00D2
+#define ixMC_IO_DEBUG_DQB1L_MISC_D0 0x00A2
+#define ixMC_IO_DEBUG_DQB1L_MISC_D1 0x00B2
+#define ixMC_IO_DEBUG_DQB1L_OFSCAL_D0 0x00E2
+#define ixMC_IO_DEBUG_DQB1L_OFSCAL_D1 0x00F2
+#define ixMC_IO_DEBUG_DQB1L_RX_EQ_D0 0x01C2
+#define ixMC_IO_DEBUG_DQB1L_RX_EQ_D1 0x01D2
+#define ixMC_IO_DEBUG_DQB1L_RXPHASE_D0 0x0102
+#define ixMC_IO_DEBUG_DQB1L_RXPHASE_D1 0x0112
+#define ixMC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0 0x0142
+#define ixMC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1 0x0152
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PD_D0 0x0182
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PD_D1 0x0192
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PU_D0 0x01A2
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PU_D1 0x01B2
+#define ixMC_IO_DEBUG_DQB1L_TXPHASE_D0 0x0122
+#define ixMC_IO_DEBUG_DQB1L_TXPHASE_D1 0x0132
+#define ixMC_IO_DEBUG_DQB1L_TXSLF_D0 0x0162
+#define ixMC_IO_DEBUG_DQB1L_TXSLF_D1 0x0172
+#define ixMC_IO_DEBUG_DQB2_CDR_PHSIZE_D0 0x014D
+#define ixMC_IO_DEBUG_DQB2_CDR_PHSIZE_D1 0x015D
+#define ixMC_IO_DEBUG_DQB2H_CLKSEL_D0 0x00C5
+#define ixMC_IO_DEBUG_DQB2H_CLKSEL_D1 0x00D5
+#define ixMC_IO_DEBUG_DQB2H_MISC_D0 0x00A5
+#define ixMC_IO_DEBUG_DQB2H_MISC_D1 0x00B5
+#define ixMC_IO_DEBUG_DQB2H_OFSCAL_D0 0x00E5
+#define ixMC_IO_DEBUG_DQB2H_OFSCAL_D1 0x00F5
+#define ixMC_IO_DEBUG_DQB2H_RX_EQ_D0 0x01C5
+#define ixMC_IO_DEBUG_DQB2H_RX_EQ_D1 0x01D5
+#define ixMC_IO_DEBUG_DQB2H_RXPHASE_D0 0x0105
+#define ixMC_IO_DEBUG_DQB2H_RXPHASE_D1 0x0115
+#define ixMC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0 0x0145
+#define ixMC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1 0x0155
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PD_D0 0x0185
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PD_D1 0x0195
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PU_D0 0x01A5
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PU_D1 0x01B5
+#define ixMC_IO_DEBUG_DQB2H_TXPHASE_D0 0x0125
+#define ixMC_IO_DEBUG_DQB2H_TXPHASE_D1 0x0135
+#define ixMC_IO_DEBUG_DQB2H_TXSLF_D0 0x0165
+#define ixMC_IO_DEBUG_DQB2H_TXSLF_D1 0x0175
+#define ixMC_IO_DEBUG_DQB2L_CLKSEL_D0 0x00C4
+#define ixMC_IO_DEBUG_DQB2L_CLKSEL_D1 0x00D4
+#define ixMC_IO_DEBUG_DQB2L_MISC_D0 0x00A4
+#define ixMC_IO_DEBUG_DQB2L_MISC_D1 0x00B4
+#define ixMC_IO_DEBUG_DQB2L_OFSCAL_D0 0x00E4
+#define ixMC_IO_DEBUG_DQB2L_OFSCAL_D1 0x00F4
+#define ixMC_IO_DEBUG_DQB2L_RX_EQ_D0 0x01C4
+#define ixMC_IO_DEBUG_DQB2L_RX_EQ_D1 0x01D4
+#define ixMC_IO_DEBUG_DQB2L_RXPHASE_D0 0x0104
+#define ixMC_IO_DEBUG_DQB2L_RXPHASE_D1 0x0114
+#define ixMC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0 0x0144
+#define ixMC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1 0x0154
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PD_D0 0x0184
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PD_D1 0x0194
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PU_D0 0x01A4
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PU_D1 0x01B4
+#define ixMC_IO_DEBUG_DQB2L_TXPHASE_D0 0x0124
+#define ixMC_IO_DEBUG_DQB2L_TXPHASE_D1 0x0134
+#define ixMC_IO_DEBUG_DQB2L_TXSLF_D0 0x0164
+#define ixMC_IO_DEBUG_DQB2L_TXSLF_D1 0x0174
+#define ixMC_IO_DEBUG_DQB3_CDR_PHSIZE_D0 0x014E
+#define ixMC_IO_DEBUG_DQB3_CDR_PHSIZE_D1 0x015E
+#define ixMC_IO_DEBUG_DQB3H_CLKSEL_D0 0x00C7
+#define ixMC_IO_DEBUG_DQB3H_CLKSEL_D1 0x00D7
+#define ixMC_IO_DEBUG_DQB3H_MISC_D0 0x00A7
+#define ixMC_IO_DEBUG_DQB3H_MISC_D1 0x00B7
+#define ixMC_IO_DEBUG_DQB3H_OFSCAL_D0 0x00E7
+#define ixMC_IO_DEBUG_DQB3H_OFSCAL_D1 0x00F7
+#define ixMC_IO_DEBUG_DQB3H_RX_EQ_D0 0x01C7
+#define ixMC_IO_DEBUG_DQB3H_RX_EQ_D1 0x01D7
+#define ixMC_IO_DEBUG_DQB3H_RXPHASE_D0 0x0107
+#define ixMC_IO_DEBUG_DQB3H_RXPHASE_D1 0x0117
+#define ixMC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0 0x0147
+#define ixMC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1 0x0157
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PD_D0 0x0187
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PD_D1 0x0197
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PU_D0 0x01A7
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PU_D1 0x01B7
+#define ixMC_IO_DEBUG_DQB3H_TXPHASE_D0 0x0127
+#define ixMC_IO_DEBUG_DQB3H_TXPHASE_D1 0x0137
+#define ixMC_IO_DEBUG_DQB3H_TXSLF_D0 0x0167
+#define ixMC_IO_DEBUG_DQB3H_TXSLF_D1 0x0177
+#define ixMC_IO_DEBUG_DQB3L_CLKSEL_D0 0x00C6
+#define ixMC_IO_DEBUG_DQB3L_CLKSEL_D1 0x00D6
+#define ixMC_IO_DEBUG_DQB3L_MISC_D0 0x00A6
+#define ixMC_IO_DEBUG_DQB3L_MISC_D1 0x00B6
+#define ixMC_IO_DEBUG_DQB3L_OFSCAL_D0 0x00E6
+#define ixMC_IO_DEBUG_DQB3L_OFSCAL_D1 0x00F6
+#define ixMC_IO_DEBUG_DQB3L_RX_EQ_D0 0x01C6
+#define ixMC_IO_DEBUG_DQB3L_RX_EQ_D1 0x01D6
+#define ixMC_IO_DEBUG_DQB3L_RXPHASE_D0 0x0106
+#define ixMC_IO_DEBUG_DQB3L_RXPHASE_D1 0x0116
+#define ixMC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0 0x0146
+#define ixMC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1 0x0156
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PD_D0 0x0186
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PD_D1 0x0196
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PU_D0 0x01A6
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PU_D1 0x01B6
+#define ixMC_IO_DEBUG_DQB3L_TXPHASE_D0 0x0126
+#define ixMC_IO_DEBUG_DQB3L_TXPHASE_D1 0x0136
+#define ixMC_IO_DEBUG_DQB3L_TXSLF_D0 0x0166
+#define ixMC_IO_DEBUG_DQB3L_TXSLF_D1 0x0176
+#define ixMC_IO_DEBUG_EDC_CDR_PHSIZE_D0 0x00ED
+#define ixMC_IO_DEBUG_EDC_CDR_PHSIZE_D1 0x00FD
+#define ixMC_IO_DEBUG_EDC_CLKSEL_D0 0x00C9
+#define ixMC_IO_DEBUG_EDC_CLKSEL_D1 0x00D9
+#define ixMC_IO_DEBUG_EDC_MISC_D0 0x00A9
+#define ixMC_IO_DEBUG_EDC_MISC_D1 0x00B9
+#define ixMC_IO_DEBUG_EDC_OFSCAL_D0 0x00E9
+#define ixMC_IO_DEBUG_EDC_OFSCAL_D1 0x00F9
+#define ixMC_IO_DEBUG_EDC_RX_DYN_PM_D0 0x00EC
+#define ixMC_IO_DEBUG_EDC_RX_DYN_PM_D1 0x00FC
+#define ixMC_IO_DEBUG_EDC_RX_EQ_D0 0x01C9
+#define ixMC_IO_DEBUG_EDC_RX_EQ_D1 0x01D9
+#define ixMC_IO_DEBUG_EDC_RX_EQ_PM_D0 0x00EB
+#define ixMC_IO_DEBUG_EDC_RX_EQ_PM_D1 0x00FB
+#define ixMC_IO_DEBUG_EDC_RXPHASE_D0 0x0109
+#define ixMC_IO_DEBUG_EDC_RXPHASE_D1 0x0119
+#define ixMC_IO_DEBUG_EDC_RX_VREF_CAL_D0 0x0149
+#define ixMC_IO_DEBUG_EDC_RX_VREF_CAL_D1 0x0159
+#define ixMC_IO_DEBUG_EDC_TXBST_PD_D0 0x0189
+#define ixMC_IO_DEBUG_EDC_TXBST_PD_D1 0x0199
+#define ixMC_IO_DEBUG_EDC_TXBST_PU_D0 0x01A9
+#define ixMC_IO_DEBUG_EDC_TXBST_PU_D1 0x01B9
+#define ixMC_IO_DEBUG_EDC_TXPHASE_D0 0x0129
+#define ixMC_IO_DEBUG_EDC_TXPHASE_D1 0x0139
+#define ixMC_IO_DEBUG_EDC_TXSLF_D0 0x0169
+#define ixMC_IO_DEBUG_EDC_TXSLF_D1 0x0179
+#define ixMC_IO_DEBUG_UP_0 0x0000
+#define ixMC_IO_DEBUG_UP_100 0x0064
+#define ixMC_IO_DEBUG_UP_10 0x000A
+#define ixMC_IO_DEBUG_UP_101 0x0065
+#define ixMC_IO_DEBUG_UP_102 0x0066
+#define ixMC_IO_DEBUG_UP_103 0x0067
+#define ixMC_IO_DEBUG_UP_104 0x0068
+#define ixMC_IO_DEBUG_UP_105 0x0069
+#define ixMC_IO_DEBUG_UP_106 0x006A
+#define ixMC_IO_DEBUG_UP_107 0x006B
+#define ixMC_IO_DEBUG_UP_108 0x006C
+#define ixMC_IO_DEBUG_UP_109 0x006D
+#define ixMC_IO_DEBUG_UP_1 0x0001
+#define ixMC_IO_DEBUG_UP_110 0x006E
+#define ixMC_IO_DEBUG_UP_11 0x000B
+#define ixMC_IO_DEBUG_UP_111 0x006F
+#define ixMC_IO_DEBUG_UP_112 0x0070
+#define ixMC_IO_DEBUG_UP_113 0x0071
+#define ixMC_IO_DEBUG_UP_114 0x0072
+#define ixMC_IO_DEBUG_UP_115 0x0073
+#define ixMC_IO_DEBUG_UP_116 0x0074
+#define ixMC_IO_DEBUG_UP_117 0x0075
+#define ixMC_IO_DEBUG_UP_118 0x0076
+#define ixMC_IO_DEBUG_UP_119 0x0077
+#define ixMC_IO_DEBUG_UP_120 0x0078
+#define ixMC_IO_DEBUG_UP_12 0x000C
+#define ixMC_IO_DEBUG_UP_121 0x0079
+#define ixMC_IO_DEBUG_UP_122 0x007A
+#define ixMC_IO_DEBUG_UP_123 0x007B
+#define ixMC_IO_DEBUG_UP_124 0x007C
+#define ixMC_IO_DEBUG_UP_125 0x007D
+#define ixMC_IO_DEBUG_UP_126 0x007E
+#define ixMC_IO_DEBUG_UP_127 0x007F
+#define ixMC_IO_DEBUG_UP_128 0x0080
+#define ixMC_IO_DEBUG_UP_129 0x0081
+#define ixMC_IO_DEBUG_UP_130 0x0082
+#define ixMC_IO_DEBUG_UP_13 0x000D
+#define ixMC_IO_DEBUG_UP_131 0x0083
+#define ixMC_IO_DEBUG_UP_132 0x0084
+#define ixMC_IO_DEBUG_UP_133 0x0085
+#define ixMC_IO_DEBUG_UP_134 0x0086
+#define ixMC_IO_DEBUG_UP_135 0x0087
+#define ixMC_IO_DEBUG_UP_136 0x0088
+#define ixMC_IO_DEBUG_UP_137 0x0089
+#define ixMC_IO_DEBUG_UP_138 0x008A
+#define ixMC_IO_DEBUG_UP_139 0x008B
+#define ixMC_IO_DEBUG_UP_140 0x008C
+#define ixMC_IO_DEBUG_UP_14 0x000E
+#define ixMC_IO_DEBUG_UP_141 0x008D
+#define ixMC_IO_DEBUG_UP_142 0x008E
+#define ixMC_IO_DEBUG_UP_143 0x008F
+#define ixMC_IO_DEBUG_UP_144 0x0090
+#define ixMC_IO_DEBUG_UP_145 0x0091
+#define ixMC_IO_DEBUG_UP_146 0x0092
+#define ixMC_IO_DEBUG_UP_147 0x0093
+#define ixMC_IO_DEBUG_UP_148 0x0094
+#define ixMC_IO_DEBUG_UP_149 0x0095
+#define ixMC_IO_DEBUG_UP_150 0x0096
+#define ixMC_IO_DEBUG_UP_15 0x000F
+#define ixMC_IO_DEBUG_UP_151 0x0097
+#define ixMC_IO_DEBUG_UP_152 0x0098
+#define ixMC_IO_DEBUG_UP_153 0x0099
+#define ixMC_IO_DEBUG_UP_154 0x009A
+#define ixMC_IO_DEBUG_UP_155 0x009B
+#define ixMC_IO_DEBUG_UP_156 0x009C
+#define ixMC_IO_DEBUG_UP_157 0x009D
+#define ixMC_IO_DEBUG_UP_158 0x009E
+#define ixMC_IO_DEBUG_UP_159 0x009F
+#define ixMC_IO_DEBUG_UP_16 0x0010
+#define ixMC_IO_DEBUG_UP_17 0x0011
+#define ixMC_IO_DEBUG_UP_18 0x0012
+#define ixMC_IO_DEBUG_UP_19 0x0013
+#define ixMC_IO_DEBUG_UP_20 0x0014
+#define ixMC_IO_DEBUG_UP_2 0x0002
+#define ixMC_IO_DEBUG_UP_21 0x0015
+#define ixMC_IO_DEBUG_UP_22 0x0016
+#define ixMC_IO_DEBUG_UP_23 0x0017
+#define ixMC_IO_DEBUG_UP_24 0x0018
+#define ixMC_IO_DEBUG_UP_25 0x0019
+#define ixMC_IO_DEBUG_UP_26 0x001A
+#define ixMC_IO_DEBUG_UP_27 0x001B
+#define ixMC_IO_DEBUG_UP_28 0x001C
+#define ixMC_IO_DEBUG_UP_29 0x001D
+#define ixMC_IO_DEBUG_UP_30 0x001E
+#define ixMC_IO_DEBUG_UP_3 0x0003
+#define ixMC_IO_DEBUG_UP_31 0x001F
+#define ixMC_IO_DEBUG_UP_32 0x0020
+#define ixMC_IO_DEBUG_UP_33 0x0021
+#define ixMC_IO_DEBUG_UP_34 0x0022
+#define ixMC_IO_DEBUG_UP_35 0x0023
+#define ixMC_IO_DEBUG_UP_36 0x0024
+#define ixMC_IO_DEBUG_UP_37 0x0025
+#define ixMC_IO_DEBUG_UP_38 0x0026
+#define ixMC_IO_DEBUG_UP_39 0x0027
+#define ixMC_IO_DEBUG_UP_40 0x0028
+#define ixMC_IO_DEBUG_UP_4 0x0004
+#define ixMC_IO_DEBUG_UP_41 0x0029
+#define ixMC_IO_DEBUG_UP_42 0x002A
+#define ixMC_IO_DEBUG_UP_43 0x002B
+#define ixMC_IO_DEBUG_UP_44 0x002C
+#define ixMC_IO_DEBUG_UP_45 0x002D
+#define ixMC_IO_DEBUG_UP_46 0x002E
+#define ixMC_IO_DEBUG_UP_47 0x002F
+#define ixMC_IO_DEBUG_UP_48 0x0030
+#define ixMC_IO_DEBUG_UP_49 0x0031
+#define ixMC_IO_DEBUG_UP_50 0x0032
+#define ixMC_IO_DEBUG_UP_5 0x0005
+#define ixMC_IO_DEBUG_UP_51 0x0033
+#define ixMC_IO_DEBUG_UP_52 0x0034
+#define ixMC_IO_DEBUG_UP_53 0x0035
+#define ixMC_IO_DEBUG_UP_54 0x0036
+#define ixMC_IO_DEBUG_UP_55 0x0037
+#define ixMC_IO_DEBUG_UP_56 0x0038
+#define ixMC_IO_DEBUG_UP_57 0x0039
+#define ixMC_IO_DEBUG_UP_58 0x003A
+#define ixMC_IO_DEBUG_UP_59 0x003B
+#define ixMC_IO_DEBUG_UP_60 0x003C
+#define ixMC_IO_DEBUG_UP_6 0x0006
+#define ixMC_IO_DEBUG_UP_61 0x003D
+#define ixMC_IO_DEBUG_UP_62 0x003E
+#define ixMC_IO_DEBUG_UP_63 0x003F
+#define ixMC_IO_DEBUG_UP_64 0x0040
+#define ixMC_IO_DEBUG_UP_65 0x0041
+#define ixMC_IO_DEBUG_UP_66 0x0042
+#define ixMC_IO_DEBUG_UP_67 0x0043
+#define ixMC_IO_DEBUG_UP_68 0x0044
+#define ixMC_IO_DEBUG_UP_69 0x0045
+#define ixMC_IO_DEBUG_UP_70 0x0046
+#define ixMC_IO_DEBUG_UP_7 0x0007
+#define ixMC_IO_DEBUG_UP_71 0x0047
+#define ixMC_IO_DEBUG_UP_72 0x0048
+#define ixMC_IO_DEBUG_UP_73 0x0049
+#define ixMC_IO_DEBUG_UP_74 0x004A
+#define ixMC_IO_DEBUG_UP_75 0x004B
+#define ixMC_IO_DEBUG_UP_76 0x004C
+#define ixMC_IO_DEBUG_UP_77 0x004D
+#define ixMC_IO_DEBUG_UP_78 0x004E
+#define ixMC_IO_DEBUG_UP_79 0x004F
+#define ixMC_IO_DEBUG_UP_80 0x0050
+#define ixMC_IO_DEBUG_UP_8 0x0008
+#define ixMC_IO_DEBUG_UP_81 0x0051
+#define ixMC_IO_DEBUG_UP_82 0x0052
+#define ixMC_IO_DEBUG_UP_83 0x0053
+#define ixMC_IO_DEBUG_UP_84 0x0054
+#define ixMC_IO_DEBUG_UP_85 0x0055
+#define ixMC_IO_DEBUG_UP_86 0x0056
+#define ixMC_IO_DEBUG_UP_87 0x0057
+#define ixMC_IO_DEBUG_UP_88 0x0058
+#define ixMC_IO_DEBUG_UP_89 0x0059
+#define ixMC_IO_DEBUG_UP_90 0x005A
+#define ixMC_IO_DEBUG_UP_9 0x0009
+#define ixMC_IO_DEBUG_UP_91 0x005B
+#define ixMC_IO_DEBUG_UP_92 0x005C
+#define ixMC_IO_DEBUG_UP_93 0x005D
+#define ixMC_IO_DEBUG_UP_94 0x005E
+#define ixMC_IO_DEBUG_UP_95 0x005F
+#define ixMC_IO_DEBUG_UP_96 0x0060
+#define ixMC_IO_DEBUG_UP_97 0x0061
+#define ixMC_IO_DEBUG_UP_98 0x0062
+#define ixMC_IO_DEBUG_UP_99 0x0063
+#define ixMC_IO_DEBUG_WCDR_CDR_PHSIZE_D0 0x01EA
+#define ixMC_IO_DEBUG_WCDR_CDR_PHSIZE_D1 0x01FA
+#define ixMC_IO_DEBUG_WCDR_CLKSEL_D0 0x01E1
+#define ixMC_IO_DEBUG_WCDR_CLKSEL_D1 0x01F1
+#define ixMC_IO_DEBUG_WCDR_MISC_D0 0x01E0
+#define ixMC_IO_DEBUG_WCDR_MISC_D1 0x01F0
+#define ixMC_IO_DEBUG_WCDR_OFSCAL_D0 0x01E2
+#define ixMC_IO_DEBUG_WCDR_OFSCAL_D1 0x01F2
+#define ixMC_IO_DEBUG_WCDR_RX_DYN_PM_D0 0x01EC
+#define ixMC_IO_DEBUG_WCDR_RX_DYN_PM_D1 0x01FC
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_D0 0x01E9
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_D1 0x01F9
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_PM_D0 0x01EB
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_PM_D1 0x01FB
+#define ixMC_IO_DEBUG_WCDR_RXPHASE_D0 0x01E3
+#define ixMC_IO_DEBUG_WCDR_RXPHASE_D1 0x01F3
+#define ixMC_IO_DEBUG_WCDR_RX_VREF_CAL_D0 0x01E5
+#define ixMC_IO_DEBUG_WCDR_RX_VREF_CAL_D1 0x01F5
+#define ixMC_IO_DEBUG_WCDR_TXBST_PD_D0 0x01E7
+#define ixMC_IO_DEBUG_WCDR_TXBST_PD_D1 0x01F7
+#define ixMC_IO_DEBUG_WCDR_TXBST_PU_D0 0x01E8
+#define ixMC_IO_DEBUG_WCDR_TXBST_PU_D1 0x01F8
+#define ixMC_IO_DEBUG_WCDR_TXPHASE_D0 0x01E4
+#define ixMC_IO_DEBUG_WCDR_TXPHASE_D1 0x01F4
+#define ixMC_IO_DEBUG_WCDR_TXSLF_D0 0x01E6
+#define ixMC_IO_DEBUG_WCDR_TXSLF_D1 0x01F6
+#define ixMC_IO_DEBUG_WCK_CLKSEL_D0 0x00CA
+#define ixMC_IO_DEBUG_WCK_CLKSEL_D1 0x00DA
+#define ixMC_IO_DEBUG_WCK_MISC_D0 0x00AA
+#define ixMC_IO_DEBUG_WCK_MISC_D1 0x00BA
+#define ixMC_IO_DEBUG_WCK_OFSCAL_D0 0x00EA
+#define ixMC_IO_DEBUG_WCK_OFSCAL_D1 0x00FA
+#define ixMC_IO_DEBUG_WCK_RX_EQ_D0 0x01CA
+#define ixMC_IO_DEBUG_WCK_RX_EQ_D1 0x01DA
+#define ixMC_IO_DEBUG_WCK_RXPHASE_D0 0x010A
+#define ixMC_IO_DEBUG_WCK_RXPHASE_D1 0x011A
+#define ixMC_IO_DEBUG_WCK_RX_VREF_CAL_D0 0x014A
+#define ixMC_IO_DEBUG_WCK_RX_VREF_CAL_D1 0x015A
+#define ixMC_IO_DEBUG_WCK_TXBST_PD_D0 0x018A
+#define ixMC_IO_DEBUG_WCK_TXBST_PD_D1 0x019A
+#define ixMC_IO_DEBUG_WCK_TXBST_PU_D0 0x01AA
+#define ixMC_IO_DEBUG_WCK_TXBST_PU_D1 0x01BA
+#define ixMC_IO_DEBUG_WCK_TXPHASE_D0 0x012A
+#define ixMC_IO_DEBUG_WCK_TXPHASE_D1 0x013A
+#define ixMC_IO_DEBUG_WCK_TXSLF_D0 0x016A
+#define ixMC_IO_DEBUG_WCK_TXSLF_D1 0x017A
+#define ixMC_TSM_DEBUG_BCNT0 0x0003
+#define ixMC_TSM_DEBUG_BCNT10 0x000D
+#define ixMC_TSM_DEBUG_BCNT1 0x0004
+#define ixMC_TSM_DEBUG_BCNT2 0x0005
+#define ixMC_TSM_DEBUG_BCNT3 0x0006
+#define ixMC_TSM_DEBUG_BCNT4 0x0007
+#define ixMC_TSM_DEBUG_BCNT5 0x0008
+#define ixMC_TSM_DEBUG_BCNT6 0x0009
+#define ixMC_TSM_DEBUG_BCNT7 0x000A
+#define ixMC_TSM_DEBUG_BCNT8 0x000B
+#define ixMC_TSM_DEBUG_BCNT9 0x000C
+#define ixMC_TSM_DEBUG_BKPT 0x0013
+#define ixMC_TSM_DEBUG_FLAG 0x0001
+#define ixMC_TSM_DEBUG_GCNT 0x0000
+#define ixMC_TSM_DEBUG_MISC 0x0002
+#define ixMC_TSM_DEBUG_ST01 0x0010
+#define ixMC_TSM_DEBUG_ST23 0x0011
+#define ixMC_TSM_DEBUG_ST45 0x0012
+#define mmATC_ATS_CNTL 0x0CC9
+#define mmATC_ATS_DEBUG 0x0CCA
+#define mmATC_ATS_DEFAULT_PAGE_CNTL 0x0CD1
+#define mmATC_ATS_DEFAULT_PAGE_LOW 0x0CD0
+#define mmATC_ATS_FAULT_CNTL 0x0CCD
+#define mmATC_ATS_FAULT_DEBUG 0x0CCB
+#define mmATC_ATS_FAULT_STATUS_ADDR 0x0CCF
+#define mmATC_ATS_FAULT_STATUS_INFO 0x0CCE
+#define mmATC_ATS_STATUS 0x0CCC
+#define mmATC_L1_ADDRESS_OFFSET 0x0CDD
+#define mmATC_L1_CNTL 0x0CDC
+#define mmATC_L1RD_DEBUG_TLB 0x0CDE
+#define mmATC_L1RD_STATUS 0x0CE0
+#define mmATC_L1WR_DEBUG_TLB 0x0CDF
+#define mmATC_L1WR_STATUS 0x0CE1
+#define mmATC_L2_CNTL 0x0CD5
+#define mmATC_L2_DEBUG 0x0CD7
+#define mmATC_MISC_CG 0x0CD4
+#define mmATC_VM_APERTURE0_CNTL 0x0CC4
+#define mmATC_VM_APERTURE0_CNTL2 0x0CC6
+#define mmATC_VM_APERTURE0_HIGH_ADDR 0x0CC2
+#define mmATC_VM_APERTURE0_LOW_ADDR 0x0CC0
+#define mmATC_VM_APERTURE1_CNTL 0x0CC5
+#define mmATC_VM_APERTURE1_CNTL2 0x0CC7
+#define mmATC_VM_APERTURE1_HIGH_ADDR 0x0CC3
+#define mmATC_VM_APERTURE1_LOW_ADDR 0x0CC1
+#define mmATC_VMID0_PASID_MAPPING 0x0CE7
+#define mmATC_VMID10_PASID_MAPPING 0x0CF1
+#define mmATC_VMID11_PASID_MAPPING 0x0CF2
+#define mmATC_VMID12_PASID_MAPPING 0x0CF3
+#define mmATC_VMID13_PASID_MAPPING 0x0CF4
+#define mmATC_VMID14_PASID_MAPPING 0x0CF5
+#define mmATC_VMID15_PASID_MAPPING 0x0CF6
+#define mmATC_VMID1_PASID_MAPPING 0x0CE8
+#define mmATC_VMID2_PASID_MAPPING 0x0CE9
+#define mmATC_VMID3_PASID_MAPPING 0x0CEA
+#define mmATC_VMID4_PASID_MAPPING 0x0CEB
+#define mmATC_VMID5_PASID_MAPPING 0x0CEC
+#define mmATC_VMID6_PASID_MAPPING 0x0CED
+#define mmATC_VMID7_PASID_MAPPING 0x0CEE
+#define mmATC_VMID8_PASID_MAPPING 0x0CEF
+#define mmATC_VMID9_PASID_MAPPING 0x0CF0
+#define mmATC_VMID_PASID_MAPPING_UPDATE_STATUS 0x0CE6
+#define mmCC_MC_MAX_CHANNEL 0x096E
+#define mmDLL_CNTL 0x0AE9
+#define mmGMCON_DEBUG 0x0D5F
+#define mmGMCON_MISC 0x0D43
+#define mmGMCON_MISC2 0x0D44
+#define mmGMCON_MISC3 0x0D51
+#define mmGMCON_PERF_MON_CNTL0 0x0D4A
+#define mmGMCON_PERF_MON_CNTL1 0x0D4B
+#define mmGMCON_PERF_MON_RSLT0 0x0D4C
+#define mmGMCON_PERF_MON_RSLT1 0x0D4D
+#define mmGMCON_PGFSM_CONFIG 0x0D4E
+#define mmGMCON_PGFSM_READ 0x0D50
+#define mmGMCON_PGFSM_WRITE 0x0D4F
+#define mmGMCON_RENG_EXECUTE 0x0D42
+#define mmGMCON_RENG_RAM_DATA 0x0D41
+#define mmGMCON_RENG_RAM_INDEX 0x0D40
+#define mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET0 0x0D48
+#define mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET1 0x0D49
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE0 0x0D45
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE1 0x0D46
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE2 0x0D47
+#define mmMC_ARB_ADDR_HASH 0x09DC
+#define mmMC_ARB_AGE_RD 0x09E9
+#define mmMC_ARB_AGE_WR 0x09EA
+#define mmMC_ARB_BANKMAP 0x09D7
+#define mmMC_ARB_BURST_TIME 0x0A02
+#define mmMC_ARB_CAC_CNTL 0x09D4
+#define mmMC_ARB_CG 0x09FA
+#define mmMC_ARB_DRAM_TIMING 0x09DD
+#define mmMC_ARB_DRAM_TIMING_1 0x09FC
+#define mmMC_ARB_DRAM_TIMING2 0x09DE
+#define mmMC_ARB_DRAM_TIMING2_1 0x09FF
+#define mmMC_ARB_FED_CNTL 0x09C1
+#define mmMC_ARB_GDEC_RD_CNTL 0x09EE
+#define mmMC_ARB_GDEC_WR_CNTL 0x09EF
+#define mmMC_ARB_GECC2 0x09C9
+#define mmMC_ARB_GECC2_CLI 0x09CA
+#define mmMC_ARB_GECC2_DEBUG 0x09C4
+#define mmMC_ARB_GECC2_DEBUG2 0x09C5
+#define mmMC_ARB_GECC2_MISC 0x09C3
+#define mmMC_ARB_GECC2_STATUS 0x09C2
+#define mmMC_ARB_LAZY0_RD 0x09E5
+#define mmMC_ARB_LAZY0_WR 0x09E6
+#define mmMC_ARB_LAZY1_RD 0x09E7
+#define mmMC_ARB_LAZY1_WR 0x09E8
+#define mmMC_ARB_LM_RD 0x09F0
+#define mmMC_ARB_LM_WR 0x09F1
+#define mmMC_ARB_MINCLKS 0x09DA
+#define mmMC_ARB_MISC 0x09D6
+#define mmMC_ARB_MISC2 0x09D5
+#define mmMC_ARB_PM_CNTL 0x09ED
+#define mmMC_ARB_POP 0x09D9
+#define mmMC_ARB_RAMCFG 0x09D8
+#define mmMC_ARB_REMREQ 0x09F2
+#define mmMC_ARB_REPLAY 0x09F3
+#define mmMC_ARB_RET_CREDITS_RD 0x09F4
+#define mmMC_ARB_RET_CREDITS_WR 0x09F5
+#define mmMC_ARB_RFSH_CNTL 0x09EB
+#define mmMC_ARB_RFSH_RATE 0x09EC
+#define mmMC_ARB_RTT_CNTL0 0x09D0
+#define mmMC_ARB_RTT_CNTL1 0x09D1
+#define mmMC_ARB_RTT_CNTL2 0x09D2
+#define mmMC_ARB_RTT_DATA 0x09CF
+#define mmMC_ARB_RTT_DEBUG 0x09D3
+#define mmMC_ARB_SQM_CNTL 0x09DB
+#define mmMC_ARB_TM_CNTL_RD 0x09E3
+#define mmMC_ARB_TM_CNTL_WR 0x09E4
+#define mmMC_ARB_WCDR 0x09FB
+#define mmMC_ARB_WCDR_2 0x09CE
+#define mmMC_ARB_WTM_CNTL_RD 0x09DF
+#define mmMC_ARB_WTM_CNTL_WR 0x09E0
+#define mmMC_ARB_WTM_GRPWT_RD 0x09E1
+#define mmMC_ARB_WTM_GRPWT_WR 0x09E2
+#define mmMC_BIST_AUTO_CNTL 0x0A06
+#define mmMC_BIST_CMD_CNTL 0x0A8E
+#define mmMC_BIST_CMP_CNTL 0x0A8D
+#define mmMC_BIST_CMP_CNTL_2 0x0AB6
+#define mmMC_BIST_CNTL 0x0A05
+#define mmMC_BIST_DATA_MASK 0x0A12
+#define mmMC_BIST_DATA_WORD0 0x0A0A
+#define mmMC_BIST_DATA_WORD1 0x0A0B
+#define mmMC_BIST_DATA_WORD2 0x0A0C
+#define mmMC_BIST_DATA_WORD3 0x0A0D
+#define mmMC_BIST_DATA_WORD4 0x0A0E
+#define mmMC_BIST_DATA_WORD5 0x0A0F
+#define mmMC_BIST_DATA_WORD6 0x0A10
+#define mmMC_BIST_DATA_WORD7 0x0A11
+#define mmMC_BIST_DIR_CNTL 0x0A07
+#define mmMC_BIST_EADDR 0x0A09
+#define mmMC_BIST_MISMATCH_ADDR 0x0A13
+#define mmMC_BIST_RDATA_EDC 0x0A1D
+#define mmMC_BIST_RDATA_MASK 0x0A1C
+#define mmMC_BIST_RDATA_WORD0 0x0A14
+#define mmMC_BIST_RDATA_WORD1 0x0A15
+#define mmMC_BIST_RDATA_WORD2 0x0A16
+#define mmMC_BIST_RDATA_WORD3 0x0A17
+#define mmMC_BIST_RDATA_WORD4 0x0A18
+#define mmMC_BIST_RDATA_WORD5 0x0A19
+#define mmMC_BIST_RDATA_WORD6 0x0A1A
+#define mmMC_BIST_RDATA_WORD7 0x0A1B
+#define mmMC_BIST_SADDR 0x0A08
+#define mmMC_CG_CONFIG 0x096F
+#define mmMC_CG_CONFIG_MCD 0x0829
+#define mmMC_CG_DATAPORT 0x0A21
+#define mmMC_CITF_CNTL 0x0970
+#define mmMC_CITF_CREDITS_ARB_RD 0x0972
+#define mmMC_CITF_CREDITS_ARB_WR 0x0973
+#define mmMC_CITF_CREDITS_VM 0x0971
+#define mmMC_CITF_CREDITS_XBAR 0x0989
+#define mmMC_CITF_DAGB_CNTL 0x0974
+#define mmMC_CITF_DAGB_DLY 0x0977
+#define mmMC_CITF_INT_CREDITS 0x0975
+#define mmMC_CITF_INT_CREDITS_WR 0x097D
+#define mmMC_CITF_MISC_RD_CG 0x0992
+#define mmMC_CITF_MISC_VM_CG 0x0994
+#define mmMC_CITF_MISC_WR_CG 0x0993
+#define mmMC_CITF_PERF_MON_CNTL2 0x098E
+#define mmMC_CITF_PERF_MON_RSLT2 0x0991
+#define mmMC_CITF_REMREQ 0x097A
+#define mmMC_CITF_RET_MODE 0x0976
+#define mmMC_CITF_WTM_RD_CNTL 0x097F
+#define mmMC_CITF_WTM_WR_CNTL 0x0980
+#define mmMC_CITF_XTRA_ENABLE 0x096D
+#define mmMC_CONFIG 0x0800
+#define mmMC_CONFIG_MCD 0x0828
+#define mmMC_HUB_MISC_DBG 0x0831
+#define mmMC_HUB_MISC_FRAMING 0x0834
+#define mmMC_HUB_MISC_HUB_CG 0x082E
+#define mmMC_HUB_MISC_IDLE_STATUS 0x0847
+#define mmMC_HUB_MISC_OVERRIDE 0x0833
+#define mmMC_HUB_MISC_POWER 0x082D
+#define mmMC_HUB_MISC_SIP_CG 0x0830
+#define mmMC_HUB_MISC_STATUS 0x0832
+#define mmMC_HUB_MISC_VM_CG 0x082F
+#define mmMC_HUB_RDREQ_CNTL 0x083B
+#define mmMC_HUB_RDREQ_CREDITS 0x0844
+#define mmMC_HUB_RDREQ_CREDITS2 0x0845
+#define mmMC_HUB_RDREQ_DMIF 0x0863
+#define mmMC_HUB_RDREQ_DMIF_LIMIT 0x0848
+#define mmMC_HUB_RDREQ_GBL0 0x0856
+#define mmMC_HUB_RDREQ_GBL1 0x0857
+#define mmMC_HUB_RDREQ_HDP 0x085B
+#define mmMC_HUB_RDREQ_MCDW 0x0851
+#define mmMC_HUB_RDREQ_MCDX 0x0852
+#define mmMC_HUB_RDREQ_MCDY 0x0853
+#define mmMC_HUB_RDREQ_MCDZ 0x0854
+#define mmMC_HUB_RDREQ_MCIF 0x0864
+#define mmMC_HUB_RDREQ_RLC 0x085D
+#define mmMC_HUB_RDREQ_SEM 0x085E
+#define mmMC_HUB_RDREQ_SIP 0x0855
+#define mmMC_HUB_RDREQ_SMU 0x0858
+#define mmMC_HUB_RDREQ_STATUS 0x0839
+#define mmMC_HUB_RDREQ_UMC 0x0860
+#define mmMC_HUB_RDREQ_UVD 0x0861
+#define mmMC_HUB_RDREQ_VCE 0x085F
+#define mmMC_HUB_RDREQ_VCEU 0x0866
+#define mmMC_HUB_RDREQ_VMC 0x0865
+#define mmMC_HUB_RDREQ_WTM_CNTL 0x083D
+#define mmMC_HUB_RDREQ_XDMAM 0x0882
+#define mmMC_HUB_SHARED_DAGB_DLY 0x0846
+#define mmMC_HUB_WDP_BP 0x0837
+#define mmMC_HUB_WDP_CNTL 0x0835
+#define mmMC_HUB_WDP_CREDITS 0x083F
+#define mmMC_HUB_WDP_ERR 0x0836
+#define mmMC_HUB_WDP_GBL0 0x0841
+#define mmMC_HUB_WDP_GBL1 0x0842
+#define mmMC_HUB_WDP_HDP 0x0879
+#define mmMC_HUB_WDP_IH 0x0872
+#define mmMC_HUB_WDP_MCDW 0x0867
+#define mmMC_HUB_WDP_MCDX 0x0868
+#define mmMC_HUB_WDP_MCDY 0x0869
+#define mmMC_HUB_WDP_MCDZ 0x086A
+#define mmMC_HUB_WDP_MCIF 0x086F
+#define mmMC_HUB_WDP_MGPU 0x0843
+#define mmMC_HUB_WDP_MGPU2 0x0840
+#define mmMC_HUB_WDP_RLC 0x0873
+#define mmMC_HUB_WDP_SEM 0x0874
+#define mmMC_HUB_WDP_SH0 0x086E
+#define mmMC_HUB_WDP_SH1 0x0876
+#define mmMC_HUB_WDP_SIP 0x086B
+#define mmMC_HUB_WDP_SMU 0x0875
+#define mmMC_HUB_WDP_STATUS 0x0838
+#define mmMC_HUB_WDP_UMC 0x0877
+#define mmMC_HUB_WDP_UVD 0x0878
+#define mmMC_HUB_WDP_VCE 0x0870
+#define mmMC_HUB_WDP_VCEU 0x087F
+#define mmMC_HUB_WDP_WTM_CNTL 0x083E
+#define mmMC_HUB_WDP_XDMA 0x0881
+#define mmMC_HUB_WDP_XDMAM 0x0880
+#define mmMC_HUB_WDP_XDP 0x0871
+#define mmMC_HUB_WRRET_CNTL 0x083C
+#define mmMC_HUB_WRRET_MCDW 0x087B
+#define mmMC_HUB_WRRET_MCDX 0x087C
+#define mmMC_HUB_WRRET_MCDY 0x087D
+#define mmMC_HUB_WRRET_MCDZ 0x087E
+#define mmMC_HUB_WRRET_STATUS 0x083A
+#define mmMC_IMP_CNTL 0x0A36
+#define mmMC_IMP_DEBUG 0x0A37
+#define mmMC_IMP_DQ_STATUS 0x0ABC
+#define mmMC_IMP_STATUS 0x0A38
+#define mmMC_IO_APHY_STR_CNTL_D0 0x0A97
+#define mmMC_IO_APHY_STR_CNTL_D1 0x0A98
+#define mmMC_IO_CDRCNTL1_D0 0x0ADD
+#define mmMC_IO_CDRCNTL1_D1 0x0ADE
+#define mmMC_IO_CDRCNTL2_D0 0x0AE4
+#define mmMC_IO_CDRCNTL2_D1 0x0AE5
+#define mmMC_IO_CDRCNTL_D0 0x0A55
+#define mmMC_IO_CDRCNTL_D1 0x0A56
+#define mmMC_IO_DPHY_STR_CNTL_D0 0x0A4E
+#define mmMC_IO_DPHY_STR_CNTL_D1 0x0A54
+#define mmMC_IO_PAD_CNTL 0x0A73
+#define mmMC_IO_PAD_CNTL_D0 0x0A74
+#define mmMC_IO_PAD_CNTL_D1 0x0A75
+#define mmMC_IO_RXCNTL1_DPHY0_D0 0x0ADF
+#define mmMC_IO_RXCNTL1_DPHY0_D1 0x0AE1
+#define mmMC_IO_RXCNTL1_DPHY1_D0 0x0AE0
+#define mmMC_IO_RXCNTL1_DPHY1_D1 0x0AE2
+#define mmMC_IO_RXCNTL_DPHY0_D0 0x0A4C
+#define mmMC_IO_RXCNTL_DPHY0_D1 0x0A52
+#define mmMC_IO_RXCNTL_DPHY1_D0 0x0A4D
+#define mmMC_IO_RXCNTL_DPHY1_D1 0x0A53
+#define mmMC_IO_TXCNTL_APHY_D0 0x0A4B
+#define mmMC_IO_TXCNTL_APHY_D1 0x0A51
+#define mmMC_IO_TXCNTL_DPHY0_D0 0x0A49
+#define mmMC_IO_TXCNTL_DPHY0_D1 0x0A4F
+#define mmMC_IO_TXCNTL_DPHY1_D0 0x0A4A
+#define mmMC_IO_TXCNTL_DPHY1_D1 0x0A50
+#define mmMCLK_PWRMGT_CNTL 0x0AE8
+#define mmMC_MEM_POWER_LS 0x082A
+#define mmMC_NPL_STATUS 0x0A76
+#define mmMC_PHY_TIMING_2 0x0ACE
+#define mmMC_PHY_TIMING_D0 0x0ACC
+#define mmMC_PHY_TIMING_D1 0x0ACD
+#define mmMC_PMG_AUTO_CFG 0x0A35
+#define mmMC_PMG_AUTO_CMD 0x0A34
+#define mmMC_PMG_CFG 0x0A84
+#define mmMC_PMG_CMD_EMRS 0x0A83
+#define mmMC_PMG_CMD_MRS 0x0AAB
+#define mmMC_PMG_CMD_MRS1 0x0AD1
+#define mmMC_PMG_CMD_MRS2 0x0AD7
+#define mmMC_RD_CB 0x0981
+#define mmMC_RD_DB 0x0982
+#define mmMC_RD_GRP_EXT 0x0978
+#define mmMC_RD_GRP_GFX 0x0803
+#define mmMC_RD_GRP_LCL 0x098A
+#define mmMC_RD_GRP_OTH 0x0807
+#define mmMC_RD_GRP_SYS 0x0805
+#define mmMC_RD_HUB 0x0985
+#define mmMC_RD_TC0 0x0983
+#define mmMC_RD_TC1 0x0984
+#define mmMC_RPB_ARB_CNTL 0x0951
+#define mmMC_RPB_BIF_CNTL 0x0952
+#define mmMC_RPB_CID_QUEUE_EX 0x095A
+#define mmMC_RPB_CID_QUEUE_EX_DATA 0x095B
+#define mmMC_RPB_CID_QUEUE_RD 0x0957
+#define mmMC_RPB_CID_QUEUE_WR 0x0956
+#define mmMC_RPB_CONF 0x094D
+#define mmMC_RPB_DBG1 0x094F
+#define mmMC_RPB_EFF_CNTL 0x0950
+#define mmMC_RPB_IF_CONF 0x094E
+#define mmMC_RPB_PERF_COUNTER_CNTL 0x0958
+#define mmMC_RPB_PERF_COUNTER_STATUS 0x0959
+#define mmMC_RPB_RD_SWITCH_CNTL 0x0955
+#define mmMC_RPB_WR_COMBINE_CNTL 0x0954
+#define mmMC_RPB_WR_SWITCH_CNTL 0x0953
+#define mmMC_SEQ_BIT_REMAP_B0_D0 0x0AA3
+#define mmMC_SEQ_BIT_REMAP_B0_D1 0x0AA7
+#define mmMC_SEQ_BIT_REMAP_B1_D0 0x0AA4
+#define mmMC_SEQ_BIT_REMAP_B1_D1 0x0AA8
+#define mmMC_SEQ_BIT_REMAP_B2_D0 0x0AA5
+#define mmMC_SEQ_BIT_REMAP_B2_D1 0x0AA9
+#define mmMC_SEQ_BIT_REMAP_B3_D0 0x0AA6
+#define mmMC_SEQ_BIT_REMAP_B3_D1 0x0AAA
+#define mmMC_SEQ_BYTE_REMAP_D0 0x0A93
+#define mmMC_SEQ_BYTE_REMAP_D1 0x0A94
+#define mmMC_SEQ_CAS_TIMING 0x0A29
+#define mmMC_SEQ_CAS_TIMING_LP 0x0A9C
+#define mmMC_SEQ_CG 0x0A9A
+#define mmMC_SEQ_CMD 0x0A31
+#define mmMC_SEQ_CNTL 0x0A25
+#define mmMC_SEQ_CNTL_2 0x0AD4
+#define mmMC_SEQ_DRAM 0x0A26
+#define mmMC_SEQ_DRAM_2 0x0A27
+#define mmMC_SEQ_DRAM_ERROR_INSERTION 0x0ACB
+#define mmMC_SEQ_FIFO_CTL 0x0A57
+#define mmMC_SEQ_IO_DEBUG_DATA 0x0A92
+#define mmMC_SEQ_IO_DEBUG_INDEX 0x0A91
+#define mmMC_SEQ_IO_RDBI 0x0AB4
+#define mmMC_SEQ_IO_REDC 0x0AB5
+#define mmMC_SEQ_IO_RESERVE_D0 0x0AB7
+#define mmMC_SEQ_IO_RESERVE_D1 0x0AB8
+#define mmMC_SEQ_IO_RWORD0 0x0AAC
+#define mmMC_SEQ_IO_RWORD1 0x0AAD
+#define mmMC_SEQ_IO_RWORD2 0x0AAE
+#define mmMC_SEQ_IO_RWORD3 0x0AAF
+#define mmMC_SEQ_IO_RWORD4 0x0AB0
+#define mmMC_SEQ_IO_RWORD5 0x0AB1
+#define mmMC_SEQ_IO_RWORD6 0x0AB2
+#define mmMC_SEQ_IO_RWORD7 0x0AB3
+#define mmMC_SEQ_MISC0 0x0A80
+#define mmMC_SEQ_MISC1 0x0A81
+#define mmMC_SEQ_MISC3 0x0A8B
+#define mmMC_SEQ_MISC4 0x0A8C
+#define mmMC_SEQ_MISC5 0x0A95
+#define mmMC_SEQ_MISC6 0x0A96
+#define mmMC_SEQ_MISC7 0x0A99
+#define mmMC_SEQ_MISC8 0x0A5F
+#define mmMC_SEQ_MISC9 0x0AE7
+#define mmMC_SEQ_MISC_TIMING 0x0A2A
+#define mmMC_SEQ_MISC_TIMING2 0x0A2B
+#define mmMC_SEQ_MISC_TIMING2_LP 0x0A9E
+#define mmMC_SEQ_MISC_TIMING_LP 0x0A9D
+#define mmMC_SEQ_MPLL_OVERRIDE 0x0A22
+#define mmMC_SEQ_PERF_CNTL 0x0A77
+#define mmMC_SEQ_PERF_CNTL_1 0x0AFD
+#define mmMC_SEQ_PERF_SEQ_CNT_A_I0 0x0A79
+#define mmMC_SEQ_PERF_SEQ_CNT_A_I1 0x0A7A
+#define mmMC_SEQ_PERF_SEQ_CNT_B_I0 0x0A7B
+#define mmMC_SEQ_PERF_SEQ_CNT_B_I1 0x0A7C
+#define mmMC_SEQ_PERF_SEQ_CNT_C_I0 0x0AD9
+#define mmMC_SEQ_PERF_SEQ_CNT_C_I1 0x0ADA
+#define mmMC_SEQ_PERF_SEQ_CNT_D_I0 0x0ADB
+#define mmMC_SEQ_PERF_SEQ_CNT_D_I1 0x0ADC
+#define mmMC_SEQ_PERF_SEQ_CTL 0x0A78
+#define mmMC_SEQ_PMG_CMD_EMRS_LP 0x0AA1
+#define mmMC_SEQ_PMG_CMD_MRS1_LP 0x0AD2
+#define mmMC_SEQ_PMG_CMD_MRS2_LP 0x0AD8
+#define mmMC_SEQ_PMG_CMD_MRS_LP 0x0AA2
+#define mmMC_SEQ_PMG_PG_HWCNTL 0x0AB9
+#define mmMC_SEQ_PMG_PG_SWCNTL_0 0x0ABA
+#define mmMC_SEQ_PMG_PG_SWCNTL_1 0x0ABB
+#define mmMC_SEQ_PMG_TIMING 0x0A2C
+#define mmMC_SEQ_PMG_TIMING_LP 0x0AD3
+#define mmMC_SEQ_RAS_TIMING 0x0A28
+#define mmMC_SEQ_RAS_TIMING_LP 0x0A9B
+#define mmMC_SEQ_RD_CTL_D0 0x0A2D
+#define mmMC_SEQ_RD_CTL_D0_LP 0x0AC7
+#define mmMC_SEQ_RD_CTL_D1 0x0A2E
+#define mmMC_SEQ_RD_CTL_D1_LP 0x0AC8
+#define mmMC_SEQ_RESERVE_0_S 0x0A1E
+#define mmMC_SEQ_RESERVE_1_S 0x0A1F
+#define mmMC_SEQ_RESERVE_M 0x0A82
+#define mmMC_SEQ_RXFRAMING_BYTE0_D0 0x0A67
+#define mmMC_SEQ_RXFRAMING_BYTE0_D1 0x0A6D
+#define mmMC_SEQ_RXFRAMING_BYTE1_D0 0x0A68
+#define mmMC_SEQ_RXFRAMING_BYTE1_D1 0x0A6E
+#define mmMC_SEQ_RXFRAMING_BYTE2_D0 0x0A69
+#define mmMC_SEQ_RXFRAMING_BYTE2_D1 0x0A6F
+#define mmMC_SEQ_RXFRAMING_BYTE3_D0 0x0A6A
+#define mmMC_SEQ_RXFRAMING_BYTE3_D1 0x0A70
+#define mmMC_SEQ_RXFRAMING_DBI_D0 0x0A6B
+#define mmMC_SEQ_RXFRAMING_DBI_D1 0x0A71
+#define mmMC_SEQ_RXFRAMING_EDC_D0 0x0A6C
+#define mmMC_SEQ_RXFRAMING_EDC_D1 0x0A72
+#define mmMC_SEQ_STATUS_M 0x0A7D
+#define mmMC_SEQ_STATUS_S 0x0A20
+#define mmMC_SEQ_SUP_CNTL 0x0A32
+#define mmMC_SEQ_SUP_DEC_STAT 0x0A88
+#define mmMC_SEQ_SUP_GP0_STAT 0x0A8F
+#define mmMC_SEQ_SUP_GP1_STAT 0x0A90
+#define mmMC_SEQ_SUP_GP2_STAT 0x0A85
+#define mmMC_SEQ_SUP_GP3_STAT 0x0A86
+#define mmMC_SEQ_SUP_IR_STAT 0x0A87
+#define mmMC_SEQ_SUP_PGM 0x0A33
+#define mmMC_SEQ_SUP_PGM_STAT 0x0A89
+#define mmMC_SEQ_SUP_R_PGM 0x0A8A
+#define mmMC_SEQ_TCG_CNTL 0x0ABD
+#define mmMC_SEQ_TIMER_RD 0x0ACA
+#define mmMC_SEQ_TIMER_WR 0x0AC9
+#define mmMC_SEQ_TRAIN_CAPTURE 0x0A3E
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD 0x0A3B
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD2 0x0AFE
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD3 0x0AFF
+#define mmMC_SEQ_TRAIN_TIMING 0x0A40
+#define mmMC_SEQ_TRAIN_WAKEUP_CLEAR 0x0A3F
+#define mmMC_SEQ_TRAIN_WAKEUP_CNTL 0x0A3A
+#define mmMC_SEQ_TRAIN_WAKEUP_EDGE 0x0A3C
+#define mmMC_SEQ_TRAIN_WAKEUP_MASK 0x0A3D
+#define mmMC_SEQ_TSM_BCNT 0x0AC2
+#define mmMC_SEQ_TSM_CTRL 0x0ABE
+#define mmMC_SEQ_TSM_DBI 0x0AC6
+#define mmMC_SEQ_TSM_DEBUG_DATA 0x0AD0
+#define mmMC_SEQ_TSM_DEBUG_INDEX 0x0ACF
+#define mmMC_SEQ_TSM_EDC 0x0AC5
+#define mmMC_SEQ_TSM_FLAG 0x0AC3
+#define mmMC_SEQ_TSM_GCNT 0x0ABF
+#define mmMC_SEQ_TSM_MISC 0x0AE6
+#define mmMC_SEQ_TSM_NCNT 0x0AC1
+#define mmMC_SEQ_TSM_OCNT 0x0AC0
+#define mmMC_SEQ_TSM_UPDATE 0x0AC4
+#define mmMC_SEQ_TSM_WCDR 0x0AE3
+#define mmMC_SEQ_TXFRAMING_BYTE0_D0 0x0A58
+#define mmMC_SEQ_TXFRAMING_BYTE0_D1 0x0A60
+#define mmMC_SEQ_TXFRAMING_BYTE1_D0 0x0A59
+#define mmMC_SEQ_TXFRAMING_BYTE1_D1 0x0A61
+#define mmMC_SEQ_TXFRAMING_BYTE2_D0 0x0A5A
+#define mmMC_SEQ_TXFRAMING_BYTE2_D1 0x0A62
+#define mmMC_SEQ_TXFRAMING_BYTE3_D0 0x0A5B
+#define mmMC_SEQ_TXFRAMING_BYTE3_D1 0x0A63
+#define mmMC_SEQ_TXFRAMING_DBI_D0 0x0A5C
+#define mmMC_SEQ_TXFRAMING_DBI_D1 0x0A64
+#define mmMC_SEQ_TXFRAMING_EDC_D0 0x0A5D
+#define mmMC_SEQ_TXFRAMING_EDC_D1 0x0A65
+#define mmMC_SEQ_TXFRAMING_FCK_D0 0x0A5E
+#define mmMC_SEQ_TXFRAMING_FCK_D1 0x0A66
+#define mmMC_SEQ_VENDOR_ID_I0 0x0A7E
+#define mmMC_SEQ_VENDOR_ID_I1 0x0A7F
+#define mmMC_SEQ_WCDR_CTRL 0x0A39
+#define mmMC_SEQ_WR_CTL_2 0x0AD5
+#define mmMC_SEQ_WR_CTL_2_LP 0x0AD6
+#define mmMC_SEQ_WR_CTL_D0 0x0A2F
+#define mmMC_SEQ_WR_CTL_D0_LP 0x0A9F
+#define mmMC_SEQ_WR_CTL_D1 0x0A30
+#define mmMC_SEQ_WR_CTL_D1_LP 0x0AA0
+#define mmMC_SHARED_BLACKOUT_CNTL 0x082B
+#define mmMC_SHARED_CHMAP 0x0801
+#define mmMC_SHARED_CHREMAP 0x0802
+#define mmMC_TRAIN_EDCCDR_R_D0 0x0A41
+#define mmMC_TRAIN_EDCCDR_R_D1 0x0A42
+#define mmMC_TRAIN_EDC_STATUS_D0 0x0A45
+#define mmMC_TRAIN_EDC_STATUS_D1 0x0A48
+#define mmMC_TRAIN_PRBSERR_0_D0 0x0A43
+#define mmMC_TRAIN_PRBSERR_0_D1 0x0A46
+#define mmMC_TRAIN_PRBSERR_1_D0 0x0A44
+#define mmMC_TRAIN_PRBSERR_1_D1 0x0A47
+#define mmMC_TRAIN_PRBSERR_2_D0 0x0AFB
+#define mmMC_TRAIN_PRBSERR_2_D1 0x0AFC
+#define mmMC_VM_AGP_BASE 0x080C
+#define mmMC_VM_AGP_BOT 0x080B
+#define mmMC_VM_AGP_TOP 0x080A
+#define mmMC_VM_DC_WRITE_CNTL 0x0810
+#define mmMC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR 0x0815
+#define mmMC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR 0x0811
+#define mmMC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR 0x0816
+#define mmMC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR 0x0812
+#define mmMC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR 0x0817
+#define mmMC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR 0x0813
+#define mmMC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR 0x0818
+#define mmMC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR 0x0814
+#define mmMC_VM_FB_LOCATION 0x0809
+#define mmMC_VM_FB_OFFSET 0x081A
+#define mmMC_VM_MB_L1_TLB0_DEBUG 0x0891
+#define mmMC_VM_MB_L1_TLB0_STATUS 0x0895
+#define mmMC_VM_MB_L1_TLB1_STATUS 0x0896
+#define mmMC_VM_MB_L1_TLB2_DEBUG 0x0893
+#define mmMC_VM_MB_L1_TLB2_STATUS 0x0897
+#define mmMC_VM_MB_L1_TLB3_DEBUG 0x08A5
+#define mmMC_VM_MB_L1_TLB3_STATUS 0x08A6
+#define mmMC_VM_MB_L2ARBITER_L2_CREDITS 0x08A1
+#define mmMC_VM_MD_L1_TLB0_DEBUG 0x0998
+#define mmMC_VM_MD_L1_TLB0_STATUS 0x099B
+#define mmMC_VM_MD_L1_TLB1_DEBUG 0x0999
+#define mmMC_VM_MD_L1_TLB1_STATUS 0x099C
+#define mmMC_VM_MD_L1_TLB2_DEBUG 0x099A
+#define mmMC_VM_MD_L1_TLB2_STATUS 0x099D
+#define mmMC_VM_MD_L1_TLB3_DEBUG 0x09A7
+#define mmMC_VM_MD_L1_TLB3_STATUS 0x09A8
+#define mmMC_VM_MD_L2ARBITER_L2_CREDITS 0x09A4
+#define mmMC_VM_MX_L1_TLB_CNTL 0x0819
+#define mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x080F
+#define mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x080E
+#define mmMC_VM_SYSTEM_APERTURE_LOW_ADDR 0x080D
+#define mmMC_WR_CB 0x0986
+#define mmMC_WR_DB 0x0987
+#define mmMC_WR_GRP_EXT 0x0979
+#define mmMC_WR_GRP_GFX 0x0804
+#define mmMC_WR_GRP_LCL 0x098B
+#define mmMC_WR_GRP_OTH 0x0808
+#define mmMC_WR_GRP_SYS 0x0806
+#define mmMC_WR_HUB 0x0988
+#define mmMC_WR_TC0 0x097B
+#define mmMC_WR_TC1 0x097C
+#define mmMC_XBAR_ADDR_DEC 0x0C80
+#define mmMC_XBAR_ARB 0x0C8D
+#define mmMC_XBAR_ARB_MAX_BURST 0x0C8E
+#define mmMC_XBAR_CHTRIREMAP 0x0C8B
+#define mmMC_XBAR_PERF_MON_CNTL0 0x0C8F
+#define mmMC_XBAR_PERF_MON_CNTL1 0x0C90
+#define mmMC_XBAR_PERF_MON_CNTL2 0x0C91
+#define mmMC_XBAR_PERF_MON_MAX_THSH 0x0C96
+#define mmMC_XBAR_PERF_MON_RSLT0 0x0C92
+#define mmMC_XBAR_PERF_MON_RSLT1 0x0C93
+#define mmMC_XBAR_PERF_MON_RSLT2 0x0C94
+#define mmMC_XBAR_PERF_MON_RSLT3 0x0C95
+#define mmMC_XBAR_RDREQ_CREDIT 0x0C83
+#define mmMC_XBAR_RDREQ_PRI_CREDIT 0x0C84
+#define mmMC_XBAR_RDRET_CREDIT1 0x0C87
+#define mmMC_XBAR_RDRET_CREDIT2 0x0C88
+#define mmMC_XBAR_RDRET_PRI_CREDIT1 0x0C89
+#define mmMC_XBAR_RDRET_PRI_CREDIT2 0x0C8A
+#define mmMC_XBAR_REMOTE 0x0C81
+#define mmMC_XBAR_SPARE0 0x0C97
+#define mmMC_XBAR_SPARE1 0x0C98
+#define mmMC_XBAR_TWOCHAN 0x0C8C
+#define mmMC_XBAR_WRREQ_CREDIT 0x0C82
+#define mmMC_XBAR_WRRET_CREDIT1 0x0C85
+#define mmMC_XBAR_WRRET_CREDIT2 0x0C86
+#define mmMC_XPB_CLG_CFG0 0x08E9
+#define mmMC_XPB_CLG_CFG10 0x08F3
+#define mmMC_XPB_CLG_CFG1 0x08EA
+#define mmMC_XPB_CLG_CFG11 0x08F4
+#define mmMC_XPB_CLG_CFG12 0x08F5
+#define mmMC_XPB_CLG_CFG13 0x08F6
+#define mmMC_XPB_CLG_CFG14 0x08F7
+#define mmMC_XPB_CLG_CFG15 0x08F8
+#define mmMC_XPB_CLG_CFG16 0x08F9
+#define mmMC_XPB_CLG_CFG17 0x08FA
+#define mmMC_XPB_CLG_CFG18 0x08FB
+#define mmMC_XPB_CLG_CFG19 0x08FC
+#define mmMC_XPB_CLG_CFG20 0x0928
+#define mmMC_XPB_CLG_CFG2 0x08EB
+#define mmMC_XPB_CLG_CFG21 0x0929
+#define mmMC_XPB_CLG_CFG22 0x092A
+#define mmMC_XPB_CLG_CFG23 0x092B
+#define mmMC_XPB_CLG_CFG24 0x092C
+#define mmMC_XPB_CLG_CFG25 0x092D
+#define mmMC_XPB_CLG_CFG26 0x092E
+#define mmMC_XPB_CLG_CFG27 0x092F
+#define mmMC_XPB_CLG_CFG28 0x0930
+#define mmMC_XPB_CLG_CFG29 0x0931
+#define mmMC_XPB_CLG_CFG30 0x0932
+#define mmMC_XPB_CLG_CFG3 0x08EC
+#define mmMC_XPB_CLG_CFG31 0x0933
+#define mmMC_XPB_CLG_CFG32 0x0936
+#define mmMC_XPB_CLG_CFG33 0x0937
+#define mmMC_XPB_CLG_CFG34 0x0938
+#define mmMC_XPB_CLG_CFG35 0x0939
+#define mmMC_XPB_CLG_CFG36 0x093A
+#define mmMC_XPB_CLG_CFG4 0x08ED
+#define mmMC_XPB_CLG_CFG5 0x08EE
+#define mmMC_XPB_CLG_CFG6 0x08EF
+#define mmMC_XPB_CLG_CFG7 0x08F0
+#define mmMC_XPB_CLG_CFG8 0x08F1
+#define mmMC_XPB_CLG_CFG9 0x08F2
+#define mmMC_XPB_CLG_EXTRA 0x08FD
+#define mmMC_XPB_CLG_EXTRA_RD 0x0935
+#define mmMC_XPB_CLK_GAT 0x091E
+#define mmMC_XPB_INTF_CFG 0x091F
+#define mmMC_XPB_INTF_CFG2 0x0934
+#define mmMC_XPB_INTF_STS 0x0920
+#define mmMC_XPB_LB_ADDR 0x08FE
+#define mmMC_XPB_MAP_INVERT_FLUSH_NUM_LSB 0x0923
+#define mmMC_XPB_MISC_CFG 0x0927
+#define mmMC_XPB_P2P_BAR0 0x0904
+#define mmMC_XPB_P2P_BAR1 0x0905
+#define mmMC_XPB_P2P_BAR2 0x0906
+#define mmMC_XPB_P2P_BAR3 0x0907
+#define mmMC_XPB_P2P_BAR4 0x0908
+#define mmMC_XPB_P2P_BAR5 0x0909
+#define mmMC_XPB_P2P_BAR6 0x090A
+#define mmMC_XPB_P2P_BAR7 0x090B
+#define mmMC_XPB_P2P_BAR_CFG 0x0903
+#define mmMC_XPB_P2P_BAR_DEBUG 0x090D
+#define mmMC_XPB_P2P_BAR_DELTA_ABOVE 0x090E
+#define mmMC_XPB_P2P_BAR_DELTA_BELOW 0x090F
+#define mmMC_XPB_P2P_BAR_SETUP 0x090C
+#define mmMC_XPB_PEER_SYS_BAR0 0x0910
+#define mmMC_XPB_PEER_SYS_BAR1 0x0911
+#define mmMC_XPB_PEER_SYS_BAR2 0x0912
+#define mmMC_XPB_PEER_SYS_BAR3 0x0913
+#define mmMC_XPB_PEER_SYS_BAR4 0x0914
+#define mmMC_XPB_PEER_SYS_BAR5 0x0915
+#define mmMC_XPB_PEER_SYS_BAR6 0x0916
+#define mmMC_XPB_PEER_SYS_BAR7 0x0917
+#define mmMC_XPB_PEER_SYS_BAR8 0x0918
+#define mmMC_XPB_PEER_SYS_BAR9 0x0919
+#define mmMC_XPB_PERF_KNOBS 0x0924
+#define mmMC_XPB_PIPE_STS 0x0921
+#define mmMC_XPB_RTR_DEST_MAP0 0x08DB
+#define mmMC_XPB_RTR_DEST_MAP1 0x08DC
+#define mmMC_XPB_RTR_DEST_MAP2 0x08DD
+#define mmMC_XPB_RTR_DEST_MAP3 0x08DE
+#define mmMC_XPB_RTR_DEST_MAP4 0x08DF
+#define mmMC_XPB_RTR_DEST_MAP5 0x08E0
+#define mmMC_XPB_RTR_DEST_MAP6 0x08E1
+#define mmMC_XPB_RTR_DEST_MAP7 0x08E2
+#define mmMC_XPB_RTR_DEST_MAP8 0x08E3
+#define mmMC_XPB_RTR_DEST_MAP9 0x08E4
+#define mmMC_XPB_RTR_SRC_APRTR0 0x08CD
+#define mmMC_XPB_RTR_SRC_APRTR1 0x08CE
+#define mmMC_XPB_RTR_SRC_APRTR2 0x08CF
+#define mmMC_XPB_RTR_SRC_APRTR3 0x08D0
+#define mmMC_XPB_RTR_SRC_APRTR4 0x08D1
+#define mmMC_XPB_RTR_SRC_APRTR5 0x08D2
+#define mmMC_XPB_RTR_SRC_APRTR6 0x08D3
+#define mmMC_XPB_RTR_SRC_APRTR7 0x08D4
+#define mmMC_XPB_RTR_SRC_APRTR8 0x08D5
+#define mmMC_XPB_RTR_SRC_APRTR9 0x08D6
+#define mmMC_XPB_STICKY 0x0925
+#define mmMC_XPB_STICKY_W1C 0x0926
+#define mmMC_XPB_SUB_CTRL 0x0922
+#define mmMC_XPB_UNC_THRESH_HST 0x08FF
+#define mmMC_XPB_UNC_THRESH_SID 0x0900
+#define mmMC_XPB_WCB_CFG 0x0902
+#define mmMC_XPB_WCB_STS 0x0901
+#define mmMC_XPB_XDMA_PEER_SYS_BAR0 0x091A
+#define mmMC_XPB_XDMA_PEER_SYS_BAR1 0x091B
+#define mmMC_XPB_XDMA_PEER_SYS_BAR2 0x091C
+#define mmMC_XPB_XDMA_PEER_SYS_BAR3 0x091D
+#define mmMC_XPB_XDMA_RTR_DEST_MAP0 0x08E5
+#define mmMC_XPB_XDMA_RTR_DEST_MAP1 0x08E6
+#define mmMC_XPB_XDMA_RTR_DEST_MAP2 0x08E7
+#define mmMC_XPB_XDMA_RTR_DEST_MAP3 0x08E8
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR0 0x08D7
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR1 0x08D8
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR2 0x08D9
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR3 0x08DA
+#define mmMPLL_AD_FUNC_CNTL 0x0AF0
+#define mmMPLL_AD_STATUS 0x0AF6
+#define mmMPLL_CNTL_MODE 0x0AEC
+#define mmMPLL_CONTROL 0x0AF5
+#define mmMPLL_DQ_0_0_STATUS 0x0AF7
+#define mmMPLL_DQ_0_1_STATUS 0x0AF8
+#define mmMPLL_DQ_1_0_STATUS 0x0AF9
+#define mmMPLL_DQ_1_1_STATUS 0x0AFA
+#define mmMPLL_DQ_FUNC_CNTL 0x0AF1
+#define mmMPLL_FUNC_CNTL 0x0AED
+#define mmMPLL_FUNC_CNTL_1 0x0AEE
+#define mmMPLL_FUNC_CNTL_2 0x0AEF
+#define mmMPLL_SEQ_UCODE_1 0x0AEA
+#define mmMPLL_SEQ_UCODE_2 0x0AEB
+#define mmMPLL_SS1 0x0AF3
+#define mmMPLL_SS2 0x0AF4
+#define mmMPLL_TIME 0x0AF2
+#define mmVM_CONTEXT0_CNTL 0x0504
+#define mmVM_CONTEXT0_CNTL2 0x050C
+#define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x054F
+#define mmVM_CONTEXT0_PAGE_TABLE_END_ADDR 0x055F
+#define mmVM_CONTEXT0_PAGE_TABLE_START_ADDR 0x0557
+#define mmVM_CONTEXT0_PROTECTION_FAULT_ADDR 0x053E
+#define mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x0546
+#define mmVM_CONTEXT0_PROTECTION_FAULT_STATUS 0x0536
+#define mmVM_CONTEXT10_PAGE_TABLE_BASE_ADDR 0x0510
+#define mmVM_CONTEXT11_PAGE_TABLE_BASE_ADDR 0x0511
+#define mmVM_CONTEXT12_PAGE_TABLE_BASE_ADDR 0x0512
+#define mmVM_CONTEXT13_PAGE_TABLE_BASE_ADDR 0x0513
+#define mmVM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x0514
+#define mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x0515
+#define mmVM_CONTEXT1_CNTL 0x0505
+#define mmVM_CONTEXT1_CNTL2 0x050D
+#define mmVM_CONTEXT1_PAGE_TABLE_BASE_ADDR 0x0550
+#define mmVM_CONTEXT1_PAGE_TABLE_END_ADDR 0x0560
+#define mmVM_CONTEXT1_PAGE_TABLE_START_ADDR 0x0558
+#define mmVM_CONTEXT1_PROTECTION_FAULT_ADDR 0x053F
+#define mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x0547
+#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0537
+#define mmVM_CONTEXT2_PAGE_TABLE_BASE_ADDR 0x0551
+#define mmVM_CONTEXT3_PAGE_TABLE_BASE_ADDR 0x0552
+#define mmVM_CONTEXT4_PAGE_TABLE_BASE_ADDR 0x0553
+#define mmVM_CONTEXT5_PAGE_TABLE_BASE_ADDR 0x0554
+#define mmVM_CONTEXT6_PAGE_TABLE_BASE_ADDR 0x0555
+#define mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR 0x0556
+#define mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR 0x050E
+#define mmVM_CONTEXT9_PAGE_TABLE_BASE_ADDR 0x050F
+#define mmVM_CONTEXTS_DISABLE 0x0535
+#define mmVM_DEBUG 0x056F
+#define mmVM_DUMMY_PAGE_FAULT_ADDR 0x0507
+#define mmVM_DUMMY_PAGE_FAULT_CNTL 0x0506
+#define mmVM_FAULT_CLIENT_ID 0x054E
+#define mmVM_INVALIDATE_REQUEST 0x051E
+#define mmVM_INVALIDATE_RESPONSE 0x051F
+#define mmVM_L2_BANK_SELECT_MASKA 0x0572
+#define mmVM_L2_BANK_SELECT_MASKB 0x0573
+#define mmVM_L2_CG 0x0570
+#define mmVM_L2_CNTL 0x0500
+#define mmVM_L2_CNTL2 0x0501
+#define mmVM_L2_CNTL3 0x0502
+#define mmVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR 0x0576
+#define mmVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR 0x0575
+#define mmVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET 0x0577
+#define mmVM_L2_STATUS 0x0503
+#define mmVM_PRT_APERTURE0_HIGH_ADDR 0x0530
+#define mmVM_PRT_APERTURE0_LOW_ADDR 0x052C
+#define mmVM_PRT_APERTURE1_HIGH_ADDR 0x0531
+#define mmVM_PRT_APERTURE1_LOW_ADDR 0x052D
+#define mmVM_PRT_APERTURE2_HIGH_ADDR 0x0532
+#define mmVM_PRT_APERTURE2_LOW_ADDR 0x052E
+#define mmVM_PRT_APERTURE3_HIGH_ADDR 0x0533
+#define mmVM_PRT_APERTURE3_LOW_ADDR 0x052F
+#define mmVM_PRT_CNTL 0x0534
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h
new file mode 100644
index 000000000000..0f6c6c8d089b
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h
@@ -0,0 +1,11895 @@
+/*
+ *
+ * Copyright (C) 2016 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 GMC_6_0_SH_MASK_H
+#define GMC_6_0_SH_MASK_H
+
+#define ATC_ATS_CNTL__CREDITS_ATS_RPB_MASK 0x00003f00L
+#define ATC_ATS_CNTL__CREDITS_ATS_RPB__SHIFT 0x00000008
+#define ATC_ATS_CNTL__DEBUG_ECO_MASK 0x000f0000L
+#define ATC_ATS_CNTL__DEBUG_ECO__SHIFT 0x00000010
+#define ATC_ATS_CNTL__DISABLE_ATC_MASK 0x00000001L
+#define ATC_ATS_CNTL__DISABLE_ATC__SHIFT 0x00000000
+#define ATC_ATS_CNTL__DISABLE_PASID_MASK 0x00000004L
+#define ATC_ATS_CNTL__DISABLE_PASID__SHIFT 0x00000002
+#define ATC_ATS_CNTL__DISABLE_PRI_MASK 0x00000002L
+#define ATC_ATS_CNTL__DISABLE_PRI__SHIFT 0x00000001
+#define ATC_ATS_DEBUG__ADDRESS_TRANSLATION_REQUEST_WRITE_PERMS_MASK 0x00000004L
+#define ATC_ATS_DEBUG__ADDRESS_TRANSLATION_REQUEST_WRITE_PERMS__SHIFT 0x00000002
+#define ATC_ATS_DEBUG__DISALLOW_ERR_TO_DONE_MASK 0x00004000L
+#define ATC_ATS_DEBUG__DISALLOW_ERR_TO_DONE__SHIFT 0x0000000e
+#define ATC_ATS_DEBUG__EXE_BIT_MASK 0x00000080L
+#define ATC_ATS_DEBUG__EXE_BIT__SHIFT 0x00000007
+#define ATC_ATS_DEBUG__IDENT_RETURN_MASK 0x00000002L
+#define ATC_ATS_DEBUG__IDENT_RETURN__SHIFT 0x00000001
+#define ATC_ATS_DEBUG__IGNORE_FED_MASK 0x00008000L
+#define ATC_ATS_DEBUG__IGNORE_FED__SHIFT 0x0000000f
+#define ATC_ATS_DEBUG__INVALIDATE_ALL_MASK 0x00000001L
+#define ATC_ATS_DEBUG__INVALIDATE_ALL__SHIFT 0x00000000
+#define ATC_ATS_DEBUG__INVALIDATION_REQUESTS_DISALLOWED_WHEN_ATC_IS_DISABLED_MASK 0x00010000L
+#define ATC_ATS_DEBUG__INVALIDATION_REQUESTS_DISALLOWED_WHEN_ATC_IS_DISABLED__SHIFT 0x00000010
+#define ATC_ATS_DEBUG__NUM_REQUESTS_AT_ERR_MASK 0x00003c00L
+#define ATC_ATS_DEBUG__NUM_REQUESTS_AT_ERR__SHIFT 0x0000000a
+#define ATC_ATS_DEBUG__PAGE_REQUEST_PERMS_MASK 0x00000100L
+#define ATC_ATS_DEBUG__PAGE_REQUEST_PERMS__SHIFT 0x00000008
+#define ATC_ATS_DEBUG__PAGE_REQUESTS_USE_RELAXED_ORDERING_MASK 0x00000020L
+#define ATC_ATS_DEBUG__PAGE_REQUESTS_USE_RELAXED_ORDERING__SHIFT 0x00000005
+#define ATC_ATS_DEBUG__PRIV_BIT_MASK 0x00000040L
+#define ATC_ATS_DEBUG__PRIV_BIT__SHIFT 0x00000006
+#define ATC_ATS_DEBUG__UNTRANSLATED_ONLY_REQUESTS_CARRY_SIZE_MASK 0x00000200L
+#define ATC_ATS_DEBUG__UNTRANSLATED_ONLY_REQUESTS_CARRY_SIZE__SHIFT 0x00000009
+#define ATC_ATS_DEFAULT_PAGE_CNTL__DEFAULT_PAGE_HIGH_MASK 0x0000003cL
+#define ATC_ATS_DEFAULT_PAGE_CNTL__DEFAULT_PAGE_HIGH__SHIFT 0x00000002
+#define ATC_ATS_DEFAULT_PAGE_CNTL__SEND_DEFAULT_PAGE_MASK 0x00000001L
+#define ATC_ATS_DEFAULT_PAGE_CNTL__SEND_DEFAULT_PAGE__SHIFT 0x00000000
+#define ATC_ATS_DEFAULT_PAGE_LOW__DEFAULT_PAGE_MASK 0xffffffffL
+#define ATC_ATS_DEFAULT_PAGE_LOW__DEFAULT_PAGE__SHIFT 0x00000000
+#define ATC_ATS_FAULT_CNTL__FAULT_CRASH_TABLE_MASK 0x03f00000L
+#define ATC_ATS_FAULT_CNTL__FAULT_CRASH_TABLE__SHIFT 0x00000014
+#define ATC_ATS_FAULT_CNTL__FAULT_INTERRUPT_TABLE_MASK 0x0000fc00L
+#define ATC_ATS_FAULT_CNTL__FAULT_INTERRUPT_TABLE__SHIFT 0x0000000a
+#define ATC_ATS_FAULT_CNTL__FAULT_REGISTER_LOG_MASK 0x0000003fL
+#define ATC_ATS_FAULT_CNTL__FAULT_REGISTER_LOG__SHIFT 0x00000000
+#define ATC_ATS_FAULT_DEBUG__ALLOW_SUBSEQUENT_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000100L
+#define ATC_ATS_FAULT_DEBUG__ALLOW_SUBSEQUENT_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000008
+#define ATC_ATS_FAULT_DEBUG__CLEAR_FAULT_STATUS_ADDR_MASK 0x00010000L
+#define ATC_ATS_FAULT_DEBUG__CLEAR_FAULT_STATUS_ADDR__SHIFT 0x00000010
+#define ATC_ATS_FAULT_DEBUG__CREDITS_ATS_IH_MASK 0x0000001fL
+#define ATC_ATS_FAULT_DEBUG__CREDITS_ATS_IH__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_ADDR__PAGE_ADDR_MASK 0xffffffffL
+#define ATC_ATS_FAULT_STATUS_ADDR__PAGE_ADDR__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO2_MASK 0x00010000L
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO2__SHIFT 0x00000010
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO_MASK 0x00008000L
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO__SHIFT 0x0000000f
+#define ATC_ATS_FAULT_STATUS_INFO__FAULT_TYPE_MASK 0x0000003fL
+#define ATC_ATS_FAULT_STATUS_INFO__FAULT_TYPE__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_INFO__INVALIDATION_MASK 0x00020000L
+#define ATC_ATS_FAULT_STATUS_INFO__INVALIDATION__SHIFT 0x00000011
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_ADDR_HIGH_MASK 0x0f000000L
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_ADDR_HIGH__SHIFT 0x00000018
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_REQUEST_MASK 0x00040000L
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_REQUEST__SHIFT 0x00000012
+#define ATC_ATS_FAULT_STATUS_INFO__STATUS_MASK 0x00f80000L
+#define ATC_ATS_FAULT_STATUS_INFO__STATUS__SHIFT 0x00000013
+#define ATC_ATS_FAULT_STATUS_INFO__VMID_MASK 0x00007c00L
+#define ATC_ATS_FAULT_STATUS_INFO__VMID__SHIFT 0x0000000a
+#define ATC_ATS_STATUS__BUSY_MASK 0x00000001L
+#define ATC_ATS_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_ATS_STATUS__CRASHED_MASK 0x00000002L
+#define ATC_ATS_STATUS__CRASHED__SHIFT 0x00000001
+#define ATC_ATS_STATUS__DEADLOCK_DETECTION_MASK 0x00000004L
+#define ATC_ATS_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000002
+#define ATC_L1_ADDRESS_OFFSET__LOGICAL_ADDRESS_MASK 0xffffffffL
+#define ATC_L1_ADDRESS_OFFSET__LOGICAL_ADDRESS__SHIFT 0x00000000
+#define ATC_L1_CNTL__DONT_NEED_ATS_BEHAVIOR_MASK 0x00000003L
+#define ATC_L1_CNTL__DONT_NEED_ATS_BEHAVIOR__SHIFT 0x00000000
+#define ATC_L1_CNTL__NEED_ATS_BEHAVIOR_MASK 0x00000004L
+#define ATC_L1_CNTL__NEED_ATS_BEHAVIOR__SHIFT 0x00000002
+#define ATC_L1_CNTL__NEED_ATS_SNOOP_DEFAULT_MASK 0x00000010L
+#define ATC_L1_CNTL__NEED_ATS_SNOOP_DEFAULT__SHIFT 0x00000004
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_L2_MASK 0x0003f000L
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_L2__SHIFT 0x0000000c
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_RPB_MASK 0x0ff00000L
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_RPB__SHIFT 0x00000014
+#define ATC_L1RD_DEBUG_TLB__DEBUG_ECO_MASK 0x30000000L
+#define ATC_L1RD_DEBUG_TLB__DEBUG_ECO__SHIFT 0x0000001c
+#define ATC_L1RD_DEBUG_TLB__DISABLE_FRAGMENTS_MASK 0x00000001L
+#define ATC_L1RD_DEBUG_TLB__DISABLE_FRAGMENTS__SHIFT 0x00000000
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_CAM_SIZE_MASK 0x000000f0L
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_CAM_SIZE__SHIFT 0x00000004
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE_MASK 0x00000700L
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE__SHIFT 0x00000008
+#define ATC_L1RD_DEBUG_TLB__INVALIDATE_ALL_MASK 0x40000000L
+#define ATC_L1RD_DEBUG_TLB__INVALIDATE_ALL__SHIFT 0x0000001e
+#define ATC_L1RD_STATUS__BAD_NEED_ATS_MASK 0x00000100L
+#define ATC_L1RD_STATUS__BAD_NEED_ATS__SHIFT 0x00000008
+#define ATC_L1RD_STATUS__BUSY_MASK 0x00000001L
+#define ATC_L1RD_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_L1RD_STATUS__DEADLOCK_DETECTION_MASK 0x00000002L
+#define ATC_L1RD_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000001
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_L2_MASK 0x0003f000L
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_L2__SHIFT 0x0000000c
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_RPB_MASK 0x0ff00000L
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_RPB__SHIFT 0x00000014
+#define ATC_L1WR_DEBUG_TLB__DEBUG_ECO_MASK 0x30000000L
+#define ATC_L1WR_DEBUG_TLB__DEBUG_ECO__SHIFT 0x0000001c
+#define ATC_L1WR_DEBUG_TLB__DISABLE_FRAGMENTS_MASK 0x00000001L
+#define ATC_L1WR_DEBUG_TLB__DISABLE_FRAGMENTS__SHIFT 0x00000000
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_CAM_SIZE_MASK 0x000000f0L
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_CAM_SIZE__SHIFT 0x00000004
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE_MASK 0x00000700L
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE__SHIFT 0x00000008
+#define ATC_L1WR_DEBUG_TLB__INVALIDATE_ALL_MASK 0x40000000L
+#define ATC_L1WR_DEBUG_TLB__INVALIDATE_ALL__SHIFT 0x0000001e
+#define ATC_L1WR_STATUS__BAD_NEED_ATS_MASK 0x00000100L
+#define ATC_L1WR_STATUS__BAD_NEED_ATS__SHIFT 0x00000008
+#define ATC_L1WR_STATUS__BUSY_MASK 0x00000001L
+#define ATC_L1WR_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_L1WR_STATUS__DEADLOCK_DETECTION_MASK 0x00000002L
+#define ATC_L1WR_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000001
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READ_REQUESTS_MASK 0x00000003L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READ_REQUESTS__SHIFT 0x00000000
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READS_DEPENDS_ON_ADDR_MOD_MASK 0x00000400L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READS_DEPENDS_ON_ADDR_MOD__SHIFT 0x0000000a
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITE_REQUESTS_MASK 0x00000030L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITE_REQUESTS__SHIFT 0x00000004
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITES_DEPENDS_ON_ADDR_MOD_MASK 0x00000800L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITES_DEPENDS_ON_ADDR_MOD__SHIFT 0x0000000b
+#define ATC_L2_DEBUG__CREDITS_L2_ATS_MASK 0x0000003fL
+#define ATC_L2_DEBUG__CREDITS_L2_ATS__SHIFT 0x00000000
+#define ATC_MISC_CG__ENABLE_MASK 0x00040000L
+#define ATC_MISC_CG__ENABLE__SHIFT 0x00000012
+#define ATC_MISC_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define ATC_MISC_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define ATC_MISC_CG__OFFDLY_MASK 0x00000fc0L
+#define ATC_MISC_CG__OFFDLY__SHIFT 0x00000006
+#define ATC_VM_APERTURE0_CNTL2__VMIDS_USING_RANGE_MASK 0x0000ffffL
+#define ATC_VM_APERTURE0_CNTL2__VMIDS_USING_RANGE__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_CNTL__ATS_ACCESS_MODE_MASK 0x00000003L
+#define ATC_VM_APERTURE0_CNTL__ATS_ACCESS_MODE__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_HIGH_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE0_HIGH_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_LOW_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE0_LOW_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_CNTL2__VMIDS_USING_RANGE_MASK 0x0000ffffL
+#define ATC_VM_APERTURE1_CNTL2__VMIDS_USING_RANGE__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_CNTL__ATS_ACCESS_MODE_MASK 0x00000003L
+#define ATC_VM_APERTURE1_CNTL__ATS_ACCESS_MODE__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_HIGH_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE1_HIGH_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_LOW_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE1_LOW_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VMID0_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID0_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID0_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID0_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID10_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID10_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID10_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID10_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID11_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID11_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID11_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID11_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID12_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID12_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID12_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID12_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID13_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID13_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID13_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID13_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID14_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID14_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID14_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID14_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID15_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID15_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID15_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID15_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID1_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID1_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID1_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID1_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID2_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID2_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID2_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID2_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID3_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID3_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID3_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID3_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID4_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID4_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID4_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID4_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID5_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID5_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID5_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID5_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID6_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID6_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID6_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID6_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID7_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID7_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID7_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID7_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID8_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID8_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID8_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID8_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID9_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID9_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID9_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID9_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID0_REMAPPING_FINISHED_MASK 0x00000001L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID0_REMAPPING_FINISHED__SHIFT 0x00000000
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID10_REMAPPING_FINISHED_MASK 0x00000400L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID10_REMAPPING_FINISHED__SHIFT 0x0000000a
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID11_REMAPPING_FINISHED_MASK 0x00000800L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID11_REMAPPING_FINISHED__SHIFT 0x0000000b
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID12_REMAPPING_FINISHED_MASK 0x00001000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID12_REMAPPING_FINISHED__SHIFT 0x0000000c
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID13_REMAPPING_FINISHED_MASK 0x00002000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID13_REMAPPING_FINISHED__SHIFT 0x0000000d
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID14_REMAPPING_FINISHED_MASK 0x00004000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID14_REMAPPING_FINISHED__SHIFT 0x0000000e
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID15_REMAPPING_FINISHED_MASK 0x00008000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID15_REMAPPING_FINISHED__SHIFT 0x0000000f
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID1_REMAPPING_FINISHED_MASK 0x00000002L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID1_REMAPPING_FINISHED__SHIFT 0x00000001
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID2_REMAPPING_FINISHED_MASK 0x00000004L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID2_REMAPPING_FINISHED__SHIFT 0x00000002
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID3_REMAPPING_FINISHED_MASK 0x00000008L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID3_REMAPPING_FINISHED__SHIFT 0x00000003
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID4_REMAPPING_FINISHED_MASK 0x00000010L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID4_REMAPPING_FINISHED__SHIFT 0x00000004
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID5_REMAPPING_FINISHED_MASK 0x00000020L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID5_REMAPPING_FINISHED__SHIFT 0x00000005
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID6_REMAPPING_FINISHED_MASK 0x00000040L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID6_REMAPPING_FINISHED__SHIFT 0x00000006
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID7_REMAPPING_FINISHED_MASK 0x00000080L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID7_REMAPPING_FINISHED__SHIFT 0x00000007
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID8_REMAPPING_FINISHED_MASK 0x00000100L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID8_REMAPPING_FINISHED__SHIFT 0x00000008
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID9_REMAPPING_FINISHED_MASK 0x00000200L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID9_REMAPPING_FINISHED__SHIFT 0x00000009
+#define CC_MC_MAX_CHANNEL__NOOFCHAN_MASK 0x0000001eL
+#define CC_MC_MAX_CHANNEL__NOOFCHAN__SHIFT 0x00000001
+#define DLL_CNTL__DLL_LOCK_TIME_MASK 0x003ff000L
+#define DLL_CNTL__DLL_LOCK_TIME__SHIFT 0x0000000c
+#define DLL_CNTL__DLL_RESET_TIME_MASK 0x000003ffL
+#define DLL_CNTL__DLL_RESET_TIME__SHIFT 0x00000000
+#define DLL_CNTL__MRDCK0_BYPASS_MASK 0x01000000L
+#define DLL_CNTL__MRDCK0_BYPASS__SHIFT 0x00000018
+#define DLL_CNTL__MRDCK1_BYPASS_MASK 0x02000000L
+#define DLL_CNTL__MRDCK1_BYPASS__SHIFT 0x00000019
+#define DLL_CNTL__PWR2_MODE_MASK 0x04000000L
+#define DLL_CNTL__PWR2_MODE__SHIFT 0x0000001a
+#define GMCON_DEBUG__GFX_CLEAR_MASK 0x00000002L
+#define GMCON_DEBUG__GFX_CLEAR__SHIFT 0x00000001
+#define GMCON_DEBUG__GFX_STALL_MASK 0x00000001L
+#define GMCON_DEBUG__GFX_STALL__SHIFT 0x00000000
+#define GMCON_DEBUG__MISC_FLAGS_MASK 0x3ffffffcL
+#define GMCON_DEBUG__MISC_FLAGS__SHIFT 0x00000002
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE0_MASK 0x00000007L
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE0__SHIFT 0x00000000
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE1_MASK 0x00000038L
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE1__SHIFT 0x00000003
+#define GMCON_MISC2__RENG_SR_HOLD_THRESHOLD_MASK 0x0000fc00L
+#define GMCON_MISC2__RENG_SR_HOLD_THRESHOLD__SHIFT 0x0000000a
+#define GMCON_MISC2__STCTRL_EXTEND_GMC_OFFLINE_MASK 0x20000000L
+#define GMCON_MISC2__STCTRL_EXTEND_GMC_OFFLINE__SHIFT 0x0000001d
+#define GMCON_MISC2__STCTRL_IGNORE_ARB_BUSY_MASK 0x10000000L
+#define GMCON_MISC2__STCTRL_IGNORE_ARB_BUSY__SHIFT 0x0000001c
+#define GMCON_MISC2__STCTRL_LPT_TARGET_MASK 0x0fff0000L
+#define GMCON_MISC2__STCTRL_LPT_TARGET__SHIFT 0x00000010
+#define GMCON_MISC3__RENG_DISABLE_MCC_MASK 0x0000003fL
+#define GMCON_MISC3__RENG_DISABLE_MCC__SHIFT 0x00000000
+#define GMCON_MISC3__RENG_DISABLE_MCD_MASK 0x00000fc0L
+#define GMCON_MISC3__RENG_DISABLE_MCD__SHIFT 0x00000006
+#define GMCON_MISC3__STCTRL_FORCE_PGFSM_CMD_DONE_MASK 0x00fff000L
+#define GMCON_MISC3__STCTRL_FORCE_PGFSM_CMD_DONE__SHIFT 0x0000000c
+#define GMCON_MISC__ALLOW_DEEP_SLEEP_MODE_MASK 0x30000000L
+#define GMCON_MISC__ALLOW_DEEP_SLEEP_MODE__SHIFT 0x0000001c
+#define GMCON_MISC__CRITICAL_REGS_LOCK_MASK 0x08000000L
+#define GMCON_MISC__CRITICAL_REGS_LOCK__SHIFT 0x0000001b
+#define GMCON_MISC__RENG_EXECUTE_NOW_MODE_MASK 0x00000400L
+#define GMCON_MISC__RENG_EXECUTE_NOW_MODE__SHIFT 0x0000000a
+#define GMCON_MISC__RENG_EXECUTE_ON_REG_UPDATE_MASK 0x00000800L
+#define GMCON_MISC__RENG_EXECUTE_ON_REG_UPDATE__SHIFT 0x0000000b
+#define GMCON_MISC__RENG_SRBM_CREDITS_MCD_MASK 0x0000f000L
+#define GMCON_MISC__RENG_SRBM_CREDITS_MCD__SHIFT 0x0000000c
+#define GMCON_MISC__STCTRL_DISABLE_ALLOW_SR_MASK 0x02000000L
+#define GMCON_MISC__STCTRL_DISABLE_ALLOW_SR__SHIFT 0x00000019
+#define GMCON_MISC__STCTRL_DISABLE_GMC_OFFLINE_MASK 0x04000000L
+#define GMCON_MISC__STCTRL_DISABLE_GMC_OFFLINE__SHIFT 0x0000001a
+#define GMCON_MISC__STCTRL_FORCE_ALLOW_SR_MASK 0x40000000L
+#define GMCON_MISC__STCTRL_FORCE_ALLOW_SR__SHIFT 0x0000001e
+#define GMCON_MISC__STCTRL_GMC_IDLE_THRESHOLD_MASK 0x00060000L
+#define GMCON_MISC__STCTRL_GMC_IDLE_THRESHOLD__SHIFT 0x00000011
+#define GMCON_MISC__STCTRL_IGNORE_ALLOW_STOP_MASK 0x00400000L
+#define GMCON_MISC__STCTRL_IGNORE_ALLOW_STOP__SHIFT 0x00000016
+#define GMCON_MISC__STCTRL_IGNORE_PRE_SR_MASK 0x00200000L
+#define GMCON_MISC__STCTRL_IGNORE_PRE_SR__SHIFT 0x00000015
+#define GMCON_MISC__STCTRL_IGNORE_PROTECTION_FAULT_MASK 0x01000000L
+#define GMCON_MISC__STCTRL_IGNORE_PROTECTION_FAULT__SHIFT 0x00000018
+#define GMCON_MISC__STCTRL_IGNORE_SR_COMMIT_MASK 0x00800000L
+#define GMCON_MISC__STCTRL_IGNORE_SR_COMMIT__SHIFT 0x00000017
+#define GMCON_MISC__STCTRL_SRBM_IDLE_THRESHOLD_MASK 0x00180000L
+#define GMCON_MISC__STCTRL_SRBM_IDLE_THRESHOLD__SHIFT 0x00000013
+#define GMCON_MISC__STCTRL_STUTTER_EN_MASK 0x00010000L
+#define GMCON_MISC__STCTRL_STUTTER_EN__SHIFT 0x00000010
+#define GMCON_PERF_MON_CNTL0__ALLOW_WRAP_MASK 0x10000000L
+#define GMCON_PERF_MON_CNTL0__ALLOW_WRAP__SHIFT 0x0000001c
+#define GMCON_PERF_MON_CNTL0__START_MODE_MASK 0x03000000L
+#define GMCON_PERF_MON_CNTL0__START_MODE__SHIFT 0x00000018
+#define GMCON_PERF_MON_CNTL0__START_THRESH_MASK 0x00000fffL
+#define GMCON_PERF_MON_CNTL0__START_THRESH__SHIFT 0x00000000
+#define GMCON_PERF_MON_CNTL0__STOP_MODE_MASK 0x0c000000L
+#define GMCON_PERF_MON_CNTL0__STOP_MODE__SHIFT 0x0000001a
+#define GMCON_PERF_MON_CNTL0__STOP_THRESH_MASK 0x00fff000L
+#define GMCON_PERF_MON_CNTL0__STOP_THRESH__SHIFT 0x0000000c
+#define GMCON_PERF_MON_CNTL1__MON0_ID_MASK 0x00fc0000L
+#define GMCON_PERF_MON_CNTL1__MON0_ID__SHIFT 0x00000012
+#define GMCON_PERF_MON_CNTL1__MON1_ID_MASK 0x3f000000L
+#define GMCON_PERF_MON_CNTL1__MON1_ID__SHIFT 0x00000018
+#define GMCON_PERF_MON_CNTL1__START_TRIG_ID_MASK 0x00000fc0L
+#define GMCON_PERF_MON_CNTL1__START_TRIG_ID__SHIFT 0x00000006
+#define GMCON_PERF_MON_CNTL1__STOP_TRIG_ID_MASK 0x0003f000L
+#define GMCON_PERF_MON_CNTL1__STOP_TRIG_ID__SHIFT 0x0000000c
+#define GMCON_PERF_MON_CNTL1__THRESH_CNTR_ID_MASK 0x0000003fL
+#define GMCON_PERF_MON_CNTL1__THRESH_CNTR_ID__SHIFT 0x00000000
+#define GMCON_PERF_MON_RSLT0__COUNT_MASK 0xffffffffL
+#define GMCON_PERF_MON_RSLT0__COUNT__SHIFT 0x00000000
+#define GMCON_PERF_MON_RSLT1__COUNT_MASK 0xffffffffL
+#define GMCON_PERF_MON_RSLT1__COUNT__SHIFT 0x00000000
+#define GMCON_PGFSM_CONFIG__FSM_ADDR_MASK 0x000000ffL
+#define GMCON_PGFSM_CONFIG__FSM_ADDR__SHIFT 0x00000000
+#define GMCON_PGFSM_CONFIG__P1_SELECT_MASK 0x00000400L
+#define GMCON_PGFSM_CONFIG__P1_SELECT__SHIFT 0x0000000a
+#define GMCON_PGFSM_CONFIG__P2_SELECT_MASK 0x00000800L
+#define GMCON_PGFSM_CONFIG__P2_SELECT__SHIFT 0x0000000b
+#define GMCON_PGFSM_CONFIG__POWER_DOWN_MASK 0x00000100L
+#define GMCON_PGFSM_CONFIG__POWER_DOWN__SHIFT 0x00000008
+#define GMCON_PGFSM_CONFIG__POWER_UP_MASK 0x00000200L
+#define GMCON_PGFSM_CONFIG__POWER_UP__SHIFT 0x00000009
+#define GMCON_PGFSM_CONFIG__READ_MASK 0x00002000L
+#define GMCON_PGFSM_CONFIG__READ__SHIFT 0x0000000d
+#define GMCON_PGFSM_CONFIG__REG_ADDR_MASK 0xf0000000L
+#define GMCON_PGFSM_CONFIG__REG_ADDR__SHIFT 0x0000001c
+#define GMCON_PGFSM_CONFIG__RSRVD_MASK 0x07ffc000L
+#define GMCON_PGFSM_CONFIG__RSRVD__SHIFT 0x0000000e
+#define GMCON_PGFSM_CONFIG__SRBM_OVERRIDE_MASK 0x08000000L
+#define GMCON_PGFSM_CONFIG__SRBM_OVERRIDE__SHIFT 0x0000001b
+#define GMCON_PGFSM_CONFIG__WRITE_MASK 0x00001000L
+#define GMCON_PGFSM_CONFIG__WRITE__SHIFT 0x0000000c
+#define GMCON_PGFSM_READ__PGFSM_SELECT_MASK 0x0f000000L
+#define GMCON_PGFSM_READ__PGFSM_SELECT__SHIFT 0x00000018
+#define GMCON_PGFSM_READ__READ_VALUE_MASK 0x00ffffffL
+#define GMCON_PGFSM_READ__READ_VALUE__SHIFT 0x00000000
+#define GMCON_PGFSM_READ__SERDES_MASTER_BUSY_MASK 0x10000000L
+#define GMCON_PGFSM_READ__SERDES_MASTER_BUSY__SHIFT 0x0000001c
+#define GMCON_PGFSM_WRITE__WRITE_VALUE_MASK 0xffffffffL
+#define GMCON_PGFSM_WRITE__WRITE_VALUE__SHIFT 0x00000000
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_DSP_END_PTR_MASK 0x003ff000L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_DSP_END_PTR__SHIFT 0x0000000c
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_END_PTR_MASK 0xffc00000L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_END_PTR__SHIFT 0x00000016
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_MASK 0x00000002L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW__SHIFT 0x00000001
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_START_PTR_MASK 0x00000ffcL
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_START_PTR__SHIFT 0x00000002
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_ON_PWR_UP_MASK 0x00000001L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_ON_PWR_UP__SHIFT 0x00000000
+#define GMCON_RENG_RAM_DATA__RENG_RAM_DATA_MASK 0xffffffffL
+#define GMCON_RENG_RAM_DATA__RENG_RAM_DATA__SHIFT 0x00000000
+#define GMCON_RENG_RAM_INDEX__RENG_RAM_INDEX_MASK 0x000003ffL
+#define GMCON_RENG_RAM_INDEX__RENG_RAM_INDEX__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL0_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL0__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL1_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL1__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL2_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL2__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL3_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL3__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_BASE0_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_BASE0__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_LIMIT0_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_LIMIT0__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_BASE1_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_BASE1__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_LIMIT1_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_LIMIT1__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_BASE2_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_BASE2__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_LIMIT2_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_LIMIT2__SHIFT 0x00000010
+#define MC_ARB_ADDR_HASH__BANK_XOR_ENABLE_MASK 0x0000000fL
+#define MC_ARB_ADDR_HASH__BANK_XOR_ENABLE__SHIFT 0x00000000
+#define MC_ARB_ADDR_HASH__COL_XOR_MASK 0x00000ff0L
+#define MC_ARB_ADDR_HASH__COL_XOR__SHIFT 0x00000004
+#define MC_ARB_ADDR_HASH__ROW_XOR_MASK 0x0ffff000L
+#define MC_ARB_ADDR_HASH__ROW_XOR__SHIFT 0x0000000c
+#define MC_ARB_AGE_RD__DIVIDE_GROUP0_MASK 0x01000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP0__SHIFT 0x00000018
+#define MC_ARB_AGE_RD__DIVIDE_GROUP1_MASK 0x02000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP1__SHIFT 0x00000019
+#define MC_ARB_AGE_RD__DIVIDE_GROUP2_MASK 0x04000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP2__SHIFT 0x0000001a
+#define MC_ARB_AGE_RD__DIVIDE_GROUP3_MASK 0x08000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP3__SHIFT 0x0000001b
+#define MC_ARB_AGE_RD__DIVIDE_GROUP4_MASK 0x10000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP4__SHIFT 0x0000001c
+#define MC_ARB_AGE_RD__DIVIDE_GROUP5_MASK 0x20000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP5__SHIFT 0x0000001d
+#define MC_ARB_AGE_RD__DIVIDE_GROUP6_MASK 0x40000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP6__SHIFT 0x0000001e
+#define MC_ARB_AGE_RD__DIVIDE_GROUP7_MASK 0x80000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP7__SHIFT 0x0000001f
+#define MC_ARB_AGE_RD__ENABLE_GROUP0_MASK 0x00010000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP0__SHIFT 0x00000010
+#define MC_ARB_AGE_RD__ENABLE_GROUP1_MASK 0x00020000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP1__SHIFT 0x00000011
+#define MC_ARB_AGE_RD__ENABLE_GROUP2_MASK 0x00040000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP2__SHIFT 0x00000012
+#define MC_ARB_AGE_RD__ENABLE_GROUP3_MASK 0x00080000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP3__SHIFT 0x00000013
+#define MC_ARB_AGE_RD__ENABLE_GROUP4_MASK 0x00100000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP4__SHIFT 0x00000014
+#define MC_ARB_AGE_RD__ENABLE_GROUP5_MASK 0x00200000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP5__SHIFT 0x00000015
+#define MC_ARB_AGE_RD__ENABLE_GROUP6_MASK 0x00400000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP6__SHIFT 0x00000016
+#define MC_ARB_AGE_RD__ENABLE_GROUP7_MASK 0x00800000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP7__SHIFT 0x00000017
+#define MC_ARB_AGE_RD__RATE_GROUP0_MASK 0x00000003L
+#define MC_ARB_AGE_RD__RATE_GROUP0__SHIFT 0x00000000
+#define MC_ARB_AGE_RD__RATE_GROUP1_MASK 0x0000000cL
+#define MC_ARB_AGE_RD__RATE_GROUP1__SHIFT 0x00000002
+#define MC_ARB_AGE_RD__RATE_GROUP2_MASK 0x00000030L
+#define MC_ARB_AGE_RD__RATE_GROUP2__SHIFT 0x00000004
+#define MC_ARB_AGE_RD__RATE_GROUP3_MASK 0x000000c0L
+#define MC_ARB_AGE_RD__RATE_GROUP3__SHIFT 0x00000006
+#define MC_ARB_AGE_RD__RATE_GROUP4_MASK 0x00000300L
+#define MC_ARB_AGE_RD__RATE_GROUP4__SHIFT 0x00000008
+#define MC_ARB_AGE_RD__RATE_GROUP5_MASK 0x00000c00L
+#define MC_ARB_AGE_RD__RATE_GROUP5__SHIFT 0x0000000a
+#define MC_ARB_AGE_RD__RATE_GROUP6_MASK 0x00003000L
+#define MC_ARB_AGE_RD__RATE_GROUP6__SHIFT 0x0000000c
+#define MC_ARB_AGE_RD__RATE_GROUP7_MASK 0x0000c000L
+#define MC_ARB_AGE_RD__RATE_GROUP7__SHIFT 0x0000000e
+#define MC_ARB_AGE_WR__DIVIDE_GROUP0_MASK 0x01000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP0__SHIFT 0x00000018
+#define MC_ARB_AGE_WR__DIVIDE_GROUP1_MASK 0x02000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP1__SHIFT 0x00000019
+#define MC_ARB_AGE_WR__DIVIDE_GROUP2_MASK 0x04000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP2__SHIFT 0x0000001a
+#define MC_ARB_AGE_WR__DIVIDE_GROUP3_MASK 0x08000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP3__SHIFT 0x0000001b
+#define MC_ARB_AGE_WR__DIVIDE_GROUP4_MASK 0x10000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP4__SHIFT 0x0000001c
+#define MC_ARB_AGE_WR__DIVIDE_GROUP5_MASK 0x20000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP5__SHIFT 0x0000001d
+#define MC_ARB_AGE_WR__DIVIDE_GROUP6_MASK 0x40000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP6__SHIFT 0x0000001e
+#define MC_ARB_AGE_WR__DIVIDE_GROUP7_MASK 0x80000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP7__SHIFT 0x0000001f
+#define MC_ARB_AGE_WR__ENABLE_GROUP0_MASK 0x00010000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP0__SHIFT 0x00000010
+#define MC_ARB_AGE_WR__ENABLE_GROUP1_MASK 0x00020000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP1__SHIFT 0x00000011
+#define MC_ARB_AGE_WR__ENABLE_GROUP2_MASK 0x00040000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP2__SHIFT 0x00000012
+#define MC_ARB_AGE_WR__ENABLE_GROUP3_MASK 0x00080000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP3__SHIFT 0x00000013
+#define MC_ARB_AGE_WR__ENABLE_GROUP4_MASK 0x00100000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP4__SHIFT 0x00000014
+#define MC_ARB_AGE_WR__ENABLE_GROUP5_MASK 0x00200000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP5__SHIFT 0x00000015
+#define MC_ARB_AGE_WR__ENABLE_GROUP6_MASK 0x00400000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP6__SHIFT 0x00000016
+#define MC_ARB_AGE_WR__ENABLE_GROUP7_MASK 0x00800000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP7__SHIFT 0x00000017
+#define MC_ARB_AGE_WR__RATE_GROUP0_MASK 0x00000003L
+#define MC_ARB_AGE_WR__RATE_GROUP0__SHIFT 0x00000000
+#define MC_ARB_AGE_WR__RATE_GROUP1_MASK 0x0000000cL
+#define MC_ARB_AGE_WR__RATE_GROUP1__SHIFT 0x00000002
+#define MC_ARB_AGE_WR__RATE_GROUP2_MASK 0x00000030L
+#define MC_ARB_AGE_WR__RATE_GROUP2__SHIFT 0x00000004
+#define MC_ARB_AGE_WR__RATE_GROUP3_MASK 0x000000c0L
+#define MC_ARB_AGE_WR__RATE_GROUP3__SHIFT 0x00000006
+#define MC_ARB_AGE_WR__RATE_GROUP4_MASK 0x00000300L
+#define MC_ARB_AGE_WR__RATE_GROUP4__SHIFT 0x00000008
+#define MC_ARB_AGE_WR__RATE_GROUP5_MASK 0x00000c00L
+#define MC_ARB_AGE_WR__RATE_GROUP5__SHIFT 0x0000000a
+#define MC_ARB_AGE_WR__RATE_GROUP6_MASK 0x00003000L
+#define MC_ARB_AGE_WR__RATE_GROUP6__SHIFT 0x0000000c
+#define MC_ARB_AGE_WR__RATE_GROUP7_MASK 0x0000c000L
+#define MC_ARB_AGE_WR__RATE_GROUP7__SHIFT 0x0000000e
+#define MC_ARB_BANKMAP__BANK0_MASK 0x0000000fL
+#define MC_ARB_BANKMAP__BANK0__SHIFT 0x00000000
+#define MC_ARB_BANKMAP__BANK1_MASK 0x000000f0L
+#define MC_ARB_BANKMAP__BANK1__SHIFT 0x00000004
+#define MC_ARB_BANKMAP__BANK2_MASK 0x00000f00L
+#define MC_ARB_BANKMAP__BANK2__SHIFT 0x00000008
+#define MC_ARB_BANKMAP__BANK3_MASK 0x0000f000L
+#define MC_ARB_BANKMAP__BANK3__SHIFT 0x0000000c
+#define MC_ARB_BANKMAP__RANK_MASK 0x000f0000L
+#define MC_ARB_BANKMAP__RANK__SHIFT 0x00000010
+#define MC_ARB_BURST_TIME__STATE0_MASK 0x0000001fL
+#define MC_ARB_BURST_TIME__STATE0__SHIFT 0x00000000
+#define MC_ARB_BURST_TIME__STATE1_MASK 0x000003e0L
+#define MC_ARB_BURST_TIME__STATE1__SHIFT 0x00000005
+#define MC_ARB_BURST_TIME__STATE2_MASK 0x00007c00L
+#define MC_ARB_BURST_TIME__STATE2__SHIFT 0x0000000a
+#define MC_ARB_BURST_TIME__STATE3_MASK 0x000f8000L
+#define MC_ARB_BURST_TIME__STATE3__SHIFT 0x0000000f
+#define MC_ARB_CAC_CNTL__ALLOW_OVERFLOW_MASK 0x00002000L
+#define MC_ARB_CAC_CNTL__ALLOW_OVERFLOW__SHIFT 0x0000000d
+#define MC_ARB_CAC_CNTL__ENABLE_MASK 0x00000001L
+#define MC_ARB_CAC_CNTL__ENABLE__SHIFT 0x00000000
+#define MC_ARB_CAC_CNTL__READ_WEIGHT_MASK 0x0000007eL
+#define MC_ARB_CAC_CNTL__READ_WEIGHT__SHIFT 0x00000001
+#define MC_ARB_CAC_CNTL__WRITE_WEIGHT_MASK 0x00001f80L
+#define MC_ARB_CAC_CNTL__WRITE_WEIGHT__SHIFT 0x00000007
+#define MC_ARB_CG__CG_ARB_REQ_MASK 0x000000ffL
+#define MC_ARB_CG__CG_ARB_REQ__SHIFT 0x00000000
+#define MC_ARB_CG__CG_ARB_RESP_MASK 0x0000ff00L
+#define MC_ARB_CG__CG_ARB_RESP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING_1__ACTRD_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING_1__ACTRD__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING_1__ACTWR_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING_1__ACTWR__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING_1__RASMACTRD_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING_1__RASMACTRD__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING_1__RASMACTWR_MASK 0xff000000L
+#define MC_ARB_DRAM_TIMING_1__RASMACTWR__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2_1__BUS_TURN_MASK 0x1f000000L
+#define MC_ARB_DRAM_TIMING2_1__BUS_TURN__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2_1__RAS2RAS_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING2_1__RAS2RAS__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING2_1__RP_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING2_1__RP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING2_1__WRPLUSRP_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING2_1__WRPLUSRP__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING2__BUS_TURN_MASK 0x1f000000L
+#define MC_ARB_DRAM_TIMING2__BUS_TURN__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2__RAS2RAS_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING2__RAS2RAS__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING2__RP_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING2__RP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING2__WRPLUSRP_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING2__WRPLUSRP__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING__ACTRD_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING__ACTRD__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING__ACTWR_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING__ACTWR__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING__RASMACTRD_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING__RASMACTRD__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING__RASMACTWR_MASK 0xff000000L
+#define MC_ARB_DRAM_TIMING__RASMACTWR__SHIFT 0x00000018
+#define MC_ARB_FED_CNTL__KEEP_POISON_IN_PAGE_MASK 0x00000010L
+#define MC_ARB_FED_CNTL__KEEP_POISON_IN_PAGE__SHIFT 0x00000004
+#define MC_ARB_FED_CNTL__MODE_MASK 0x00000003L
+#define MC_ARB_FED_CNTL__MODE__SHIFT 0x00000000
+#define MC_ARB_FED_CNTL__WR_ERR_MASK 0x0000000cL
+#define MC_ARB_FED_CNTL__WR_ERR__SHIFT 0x00000002
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT0_MASK 0x0000000fL
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT0__SHIFT 0x00000000
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT1_MASK 0x000000f0L
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT1__SHIFT 0x00000004
+#define MC_ARB_GDEC_RD_CNTL__REM_DEFAULT_GRP_MASK 0x00003c00L
+#define MC_ARB_GDEC_RD_CNTL__REM_DEFAULT_GRP__SHIFT 0x0000000a
+#define MC_ARB_GDEC_RD_CNTL__USE_RANK_MASK 0x00000100L
+#define MC_ARB_GDEC_RD_CNTL__USE_RANK__SHIFT 0x00000008
+#define MC_ARB_GDEC_RD_CNTL__USE_RSNO_MASK 0x00000200L
+#define MC_ARB_GDEC_RD_CNTL__USE_RSNO__SHIFT 0x00000009
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT0_MASK 0x0000000fL
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT0__SHIFT 0x00000000
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT1_MASK 0x000000f0L
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT1__SHIFT 0x00000004
+#define MC_ARB_GDEC_WR_CNTL__REM_DEFAULT_GRP_MASK 0x00003c00L
+#define MC_ARB_GDEC_WR_CNTL__REM_DEFAULT_GRP__SHIFT 0x0000000a
+#define MC_ARB_GDEC_WR_CNTL__USE_RANK_MASK 0x00000100L
+#define MC_ARB_GDEC_WR_CNTL__USE_RANK__SHIFT 0x00000008
+#define MC_ARB_GDEC_WR_CNTL__USE_RSNO_MASK 0x00000200L
+#define MC_ARB_GDEC_WR_CNTL__USE_RSNO__SHIFT 0x00000009
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI0_MASK 0x000000ffL
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI0__SHIFT 0x00000000
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI1_MASK 0x0000ff00L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI1__SHIFT 0x00000008
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI2_MASK 0x00ff0000L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI2__SHIFT 0x00000010
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI3_MASK 0xff000000L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI3__SHIFT 0x00000018
+#define MC_ARB_GECC2__CLOSE_BANK_RMW_MASK 0x00004000L
+#define MC_ARB_GECC2__CLOSE_BANK_RMW__SHIFT 0x0000000e
+#define MC_ARB_GECC2__COLFIFO_WATER_MASK 0x001f8000L
+#define MC_ARB_GECC2__COLFIFO_WATER__SHIFT 0x0000000f
+#define MC_ARB_GECC2_DEBUG2__ERR0_START_MASK 0x0000ff00L
+#define MC_ARB_GECC2_DEBUG2__ERR0_START__SHIFT 0x00000008
+#define MC_ARB_GECC2_DEBUG2__ERR1_START_MASK 0x00ff0000L
+#define MC_ARB_GECC2_DEBUG2__ERR1_START__SHIFT 0x00000010
+#define MC_ARB_GECC2_DEBUG2__ERR2_START_MASK 0xff000000L
+#define MC_ARB_GECC2_DEBUG2__ERR2_START__SHIFT 0x00000018
+#define MC_ARB_GECC2_DEBUG2__PERIOD_MASK 0x000000ffL
+#define MC_ARB_GECC2_DEBUG2__PERIOD__SHIFT 0x00000000
+#define MC_ARB_GECC2_DEBUG__DATA_FIELD_MASK 0x00000018L
+#define MC_ARB_GECC2_DEBUG__DATA_FIELD__SHIFT 0x00000003
+#define MC_ARB_GECC2_DEBUG__DIRECTION_MASK 0x00000004L
+#define MC_ARB_GECC2_DEBUG__DIRECTION__SHIFT 0x00000002
+#define MC_ARB_GECC2_DEBUG__NUM_ERR_BITS_MASK 0x00000003L
+#define MC_ARB_GECC2_DEBUG__NUM_ERR_BITS__SHIFT 0x00000000
+#define MC_ARB_GECC2_DEBUG__SW_INJECTION_MASK 0x00000020L
+#define MC_ARB_GECC2_DEBUG__SW_INJECTION__SHIFT 0x00000005
+#define MC_ARB_GECC2__ECC_MODE_MASK 0x00000006L
+#define MC_ARB_GECC2__ECC_MODE__SHIFT 0x00000001
+#define MC_ARB_GECC2__ENABLE_MASK 0x00000001L
+#define MC_ARB_GECC2__ENABLE__SHIFT 0x00000000
+#define MC_ARB_GECC2__EXOR_BANK_SEL_MASK 0x00000060L
+#define MC_ARB_GECC2__EXOR_BANK_SEL__SHIFT 0x00000005
+#define MC_ARB_GECC2_MISC__STREAK_BREAK_MASK 0x0000000fL
+#define MC_ARB_GECC2_MISC__STREAK_BREAK__SHIFT 0x00000000
+#define MC_ARB_GECC2__NO_GECC_CLI_MASK 0x00000780L
+#define MC_ARB_GECC2__NO_GECC_CLI__SHIFT 0x00000007
+#define MC_ARB_GECC2__PAGE_BIT0_MASK 0x00000018L
+#define MC_ARB_GECC2__PAGE_BIT0__SHIFT 0x00000003
+#define MC_ARB_GECC2__READ_ERR_MASK 0x00003800L
+#define MC_ARB_GECC2__READ_ERR__SHIFT 0x0000000b
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR0_MASK 0x00000100L
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR0__SHIFT 0x00000008
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR1_MASK 0x00001000L
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR1__SHIFT 0x0000000c
+#define MC_ARB_GECC2_STATUS__CORR_STS0_MASK 0x00000001L
+#define MC_ARB_GECC2_STATUS__CORR_STS0__SHIFT 0x00000000
+#define MC_ARB_GECC2_STATUS__CORR_STS1_MASK 0x00000010L
+#define MC_ARB_GECC2_STATUS__CORR_STS1__SHIFT 0x00000004
+#define MC_ARB_GECC2_STATUS__FED_CLEAR0_MASK 0x00000400L
+#define MC_ARB_GECC2_STATUS__FED_CLEAR0__SHIFT 0x0000000a
+#define MC_ARB_GECC2_STATUS__FED_CLEAR1_MASK 0x00004000L
+#define MC_ARB_GECC2_STATUS__FED_CLEAR1__SHIFT 0x0000000e
+#define MC_ARB_GECC2_STATUS__FED_STS0_MASK 0x00000004L
+#define MC_ARB_GECC2_STATUS__FED_STS0__SHIFT 0x00000002
+#define MC_ARB_GECC2_STATUS__FED_STS1_MASK 0x00000040L
+#define MC_ARB_GECC2_STATUS__FED_STS1__SHIFT 0x00000006
+#define MC_ARB_GECC2_STATUS__RSVD0_MASK 0x00000008L
+#define MC_ARB_GECC2_STATUS__RSVD0__SHIFT 0x00000003
+#define MC_ARB_GECC2_STATUS__RSVD1_MASK 0x00000080L
+#define MC_ARB_GECC2_STATUS__RSVD1__SHIFT 0x00000007
+#define MC_ARB_GECC2_STATUS__RSVD2_MASK 0x00000800L
+#define MC_ARB_GECC2_STATUS__RSVD2__SHIFT 0x0000000b
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR0_MASK 0x00000200L
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR0__SHIFT 0x00000009
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR1_MASK 0x00002000L
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR1__SHIFT 0x0000000d
+#define MC_ARB_GECC2_STATUS__UNCORR_STS0_MASK 0x00000002L
+#define MC_ARB_GECC2_STATUS__UNCORR_STS0__SHIFT 0x00000001
+#define MC_ARB_GECC2_STATUS__UNCORR_STS1_MASK 0x00000020L
+#define MC_ARB_GECC2_STATUS__UNCORR_STS1__SHIFT 0x00000005
+#define MC_ARB_LAZY0_RD__GROUP0_MASK 0x000000ffL
+#define MC_ARB_LAZY0_RD__GROUP0__SHIFT 0x00000000
+#define MC_ARB_LAZY0_RD__GROUP1_MASK 0x0000ff00L
+#define MC_ARB_LAZY0_RD__GROUP1__SHIFT 0x00000008
+#define MC_ARB_LAZY0_RD__GROUP2_MASK 0x00ff0000L
+#define MC_ARB_LAZY0_RD__GROUP2__SHIFT 0x00000010
+#define MC_ARB_LAZY0_RD__GROUP3_MASK 0xff000000L
+#define MC_ARB_LAZY0_RD__GROUP3__SHIFT 0x00000018
+#define MC_ARB_LAZY0_WR__GROUP0_MASK 0x000000ffL
+#define MC_ARB_LAZY0_WR__GROUP0__SHIFT 0x00000000
+#define MC_ARB_LAZY0_WR__GROUP1_MASK 0x0000ff00L
+#define MC_ARB_LAZY0_WR__GROUP1__SHIFT 0x00000008
+#define MC_ARB_LAZY0_WR__GROUP2_MASK 0x00ff0000L
+#define MC_ARB_LAZY0_WR__GROUP2__SHIFT 0x00000010
+#define MC_ARB_LAZY0_WR__GROUP3_MASK 0xff000000L
+#define MC_ARB_LAZY0_WR__GROUP3__SHIFT 0x00000018
+#define MC_ARB_LAZY1_RD__GROUP4_MASK 0x000000ffL
+#define MC_ARB_LAZY1_RD__GROUP4__SHIFT 0x00000000
+#define MC_ARB_LAZY1_RD__GROUP5_MASK 0x0000ff00L
+#define MC_ARB_LAZY1_RD__GROUP5__SHIFT 0x00000008
+#define MC_ARB_LAZY1_RD__GROUP6_MASK 0x00ff0000L
+#define MC_ARB_LAZY1_RD__GROUP6__SHIFT 0x00000010
+#define MC_ARB_LAZY1_RD__GROUP7_MASK 0xff000000L
+#define MC_ARB_LAZY1_RD__GROUP7__SHIFT 0x00000018
+#define MC_ARB_LAZY1_WR__GROUP4_MASK 0x000000ffL
+#define MC_ARB_LAZY1_WR__GROUP4__SHIFT 0x00000000
+#define MC_ARB_LAZY1_WR__GROUP5_MASK 0x0000ff00L
+#define MC_ARB_LAZY1_WR__GROUP5__SHIFT 0x00000008
+#define MC_ARB_LAZY1_WR__GROUP6_MASK 0x00ff0000L
+#define MC_ARB_LAZY1_WR__GROUP6__SHIFT 0x00000010
+#define MC_ARB_LAZY1_WR__GROUP7_MASK 0xff000000L
+#define MC_ARB_LAZY1_WR__GROUP7__SHIFT 0x00000018
+#define MC_ARB_LM_RD__BANKGROUP_CONFIG_MASK 0x00e00000L
+#define MC_ARB_LM_RD__BANKGROUP_CONFIG__SHIFT 0x00000015
+#define MC_ARB_LM_RD__ENABLE_TWO_LIST_MASK 0x00040000L
+#define MC_ARB_LM_RD__ENABLE_TWO_LIST__SHIFT 0x00000012
+#define MC_ARB_LM_RD__POPIDLE_RST_TWOLIST_MASK 0x00080000L
+#define MC_ARB_LM_RD__POPIDLE_RST_TWOLIST__SHIFT 0x00000013
+#define MC_ARB_LM_RD__SKID1_RST_TWOLIST_MASK 0x00100000L
+#define MC_ARB_LM_RD__SKID1_RST_TWOLIST__SHIFT 0x00000014
+#define MC_ARB_LM_RD__STREAK_BREAK_MASK 0x00010000L
+#define MC_ARB_LM_RD__STREAK_BREAK__SHIFT 0x00000010
+#define MC_ARB_LM_RD__STREAK_LIMIT_MASK 0x000000ffL
+#define MC_ARB_LM_RD__STREAK_LIMIT__SHIFT 0x00000000
+#define MC_ARB_LM_RD__STREAK_LIMIT_UBER_MASK 0x0000ff00L
+#define MC_ARB_LM_RD__STREAK_LIMIT_UBER__SHIFT 0x00000008
+#define MC_ARB_LM_RD__STREAK_UBER_MASK 0x00020000L
+#define MC_ARB_LM_RD__STREAK_UBER__SHIFT 0x00000011
+#define MC_ARB_LM_WR__BANKGROUP_CONFIG_MASK 0x00e00000L
+#define MC_ARB_LM_WR__BANKGROUP_CONFIG__SHIFT 0x00000015
+#define MC_ARB_LM_WR__ENABLE_TWO_LIST_MASK 0x00040000L
+#define MC_ARB_LM_WR__ENABLE_TWO_LIST__SHIFT 0x00000012
+#define MC_ARB_LM_WR__POPIDLE_RST_TWOLIST_MASK 0x00080000L
+#define MC_ARB_LM_WR__POPIDLE_RST_TWOLIST__SHIFT 0x00000013
+#define MC_ARB_LM_WR__SKID1_RST_TWOLIST_MASK 0x00100000L
+#define MC_ARB_LM_WR__SKID1_RST_TWOLIST__SHIFT 0x00000014
+#define MC_ARB_LM_WR__STREAK_BREAK_MASK 0x00010000L
+#define MC_ARB_LM_WR__STREAK_BREAK__SHIFT 0x00000010
+#define MC_ARB_LM_WR__STREAK_LIMIT_MASK 0x000000ffL
+#define MC_ARB_LM_WR__STREAK_LIMIT__SHIFT 0x00000000
+#define MC_ARB_LM_WR__STREAK_LIMIT_UBER_MASK 0x0000ff00L
+#define MC_ARB_LM_WR__STREAK_LIMIT_UBER__SHIFT 0x00000008
+#define MC_ARB_LM_WR__STREAK_UBER_MASK 0x00020000L
+#define MC_ARB_LM_WR__STREAK_UBER__SHIFT 0x00000011
+#define MC_ARB_MINCLKS__ARB_RW_SWITCH_MASK 0x00010000L
+#define MC_ARB_MINCLKS__ARB_RW_SWITCH__SHIFT 0x00000010
+#define MC_ARB_MINCLKS__READ_CLKS_MASK 0x000000ffL
+#define MC_ARB_MINCLKS__READ_CLKS__SHIFT 0x00000000
+#define MC_ARB_MINCLKS__WRITE_CLKS_MASK 0x0000ff00L
+#define MC_ARB_MINCLKS__WRITE_CLKS__SHIFT 0x00000008
+#define MC_ARB_MISC2__ARB_DEBUG29_MASK 0x20000000L
+#define MC_ARB_MISC2__ARB_DEBUG29__SHIFT 0x0000001d
+#define MC_ARB_MISC2__GECC_MASK 0x00040000L
+#define MC_ARB_MISC2__GECC_RST_MASK 0x00080000L
+#define MC_ARB_MISC2__GECC_RST__SHIFT 0x00000013
+#define MC_ARB_MISC2__GECC__SHIFT 0x00000012
+#define MC_ARB_MISC2__GECC_STATUS_MASK 0x00100000L
+#define MC_ARB_MISC2__GECC_STATUS__SHIFT 0x00000014
+#define MC_ARB_MISC2__POP_IDLE_REPLAY_MASK 0x00000800L
+#define MC_ARB_MISC2__POP_IDLE_REPLAY__SHIFT 0x0000000b
+#define MC_ARB_MISC2__RDRET_NO_BP_MASK 0x00002000L
+#define MC_ARB_MISC2__RDRET_NO_BP__SHIFT 0x0000000d
+#define MC_ARB_MISC2__RDRET_NO_REORDERING_MASK 0x00001000L
+#define MC_ARB_MISC2__RDRET_NO_REORDERING__SHIFT 0x0000000c
+#define MC_ARB_MISC2__RDRET_SEQ_SKID_MASK 0x0003c000L
+#define MC_ARB_MISC2__RDRET_SEQ_SKID__SHIFT 0x0000000e
+#define MC_ARB_MISC2__REPLAY_DEBUG_MASK 0x10000000L
+#define MC_ARB_MISC2__REPLAY_DEBUG__SHIFT 0x0000001c
+#define MC_ARB_MISC2__SEQ_RDY_POP_IDLE_MASK 0x40000000L
+#define MC_ARB_MISC2__SEQ_RDY_POP_IDLE__SHIFT 0x0000001e
+#define MC_ARB_MISC2__TAGFIFO_THRESHOLD_MASK 0x01e00000L
+#define MC_ARB_MISC2__TAGFIFO_THRESHOLD__SHIFT 0x00000015
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT4_MASK 0x00000040L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT4__SHIFT 0x00000006
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT5_MASK 0x00000080L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT5__SHIFT 0x00000007
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT6_MASK 0x00000100L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT6__SHIFT 0x00000008
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT7_MASK 0x00000200L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT7__SHIFT 0x00000009
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT8_MASK 0x00000400L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT8__SHIFT 0x0000000a
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_ENABLE_MASK 0x00000020L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_ENABLE__SHIFT 0x00000005
+#define MC_ARB_MISC2__TCCDL4_REPLAY_EOB_MASK 0x80000000L
+#define MC_ARB_MISC2__TCCDL4_REPLAY_EOB__SHIFT 0x0000001f
+#define MC_ARB_MISC2__WCDR_REPLAY_MASKCNT_MASK 0x0e000000L
+#define MC_ARB_MISC2__WCDR_REPLAY_MASKCNT__SHIFT 0x00000019
+#define MC_ARB_MISC__CALI_ENABLE_MASK 0x00100000L
+#define MC_ARB_MISC__CALI_ENABLE__SHIFT 0x00000014
+#define MC_ARB_MISC__CALI_RATES_MASK 0x00600000L
+#define MC_ARB_MISC__CALI_RATES__SHIFT 0x00000015
+#define MC_ARB_MISC__CHAN_COUPLE_MASK 0x000007f8L
+#define MC_ARB_MISC__CHAN_COUPLE__SHIFT 0x00000003
+#define MC_ARB_MISC__DISPURG_NOSW2WR_MASK 0x01000000L
+#define MC_ARB_MISC__DISPURG_NOSW2WR__SHIFT 0x00000018
+#define MC_ARB_MISC__DISPURG_STALL_MASK 0x02000000L
+#define MC_ARB_MISC__DISPURG_STALL__SHIFT 0x00000019
+#define MC_ARB_MISC__DISPURG_THROTTLE_MASK 0x3c000000L
+#define MC_ARB_MISC__DISPURG_THROTTLE__SHIFT 0x0000001a
+#define MC_ARB_MISC__DISPURGVLD_NOWRT_MASK 0x00800000L
+#define MC_ARB_MISC__DISPURGVLD_NOWRT__SHIFT 0x00000017
+#define MC_ARB_MISC__HARSHNESS_MASK 0x0007f800L
+#define MC_ARB_MISC__HARSHNESS__SHIFT 0x0000000b
+#define MC_ARB_MISC__IDLE_RFSH_MASK 0x00000002L
+#define MC_ARB_MISC__IDLE_RFSH__SHIFT 0x00000001
+#define MC_ARB_MISC__SMART_RDWR_SW_MASK 0x00080000L
+#define MC_ARB_MISC__SMART_RDWR_SW__SHIFT 0x00000013
+#define MC_ARB_MISC__STICKY_RFSH_MASK 0x00000001L
+#define MC_ARB_MISC__STICKY_RFSH__SHIFT 0x00000000
+#define MC_ARB_MISC__STUTTER_RFSH_MASK 0x00000004L
+#define MC_ARB_MISC__STUTTER_RFSH__SHIFT 0x00000002
+#define MC_ARB_PM_CNTL__BLKOUT_ON_D1_MASK 0x00000020L
+#define MC_ARB_PM_CNTL__BLKOUT_ON_D1__SHIFT 0x00000005
+#define MC_ARB_PM_CNTL__IDLE_CNT_MASK 0x00f00000L
+#define MC_ARB_PM_CNTL__IDLE_CNT__SHIFT 0x00000014
+#define MC_ARB_PM_CNTL__IDLE_ON_D1_MASK 0x00000040L
+#define MC_ARB_PM_CNTL__IDLE_ON_D1__SHIFT 0x00000006
+#define MC_ARB_PM_CNTL__IDLE_ON_D2_MASK 0x00040000L
+#define MC_ARB_PM_CNTL__IDLE_ON_D2__SHIFT 0x00000012
+#define MC_ARB_PM_CNTL__IDLE_ON_D3_MASK 0x00080000L
+#define MC_ARB_PM_CNTL__IDLE_ON_D3__SHIFT 0x00000013
+#define MC_ARB_PM_CNTL__OVERRIDE_CGSTATE_MASK 0x00000003L
+#define MC_ARB_PM_CNTL__OVERRIDE_CGSTATE__SHIFT 0x00000000
+#define MC_ARB_PM_CNTL__OVRR_CGRFSH_MASK 0x00000004L
+#define MC_ARB_PM_CNTL__OVRR_CGRFSH__SHIFT 0x00000002
+#define MC_ARB_PM_CNTL__OVRR_CGSQM_MASK 0x00000008L
+#define MC_ARB_PM_CNTL__OVRR_CGSQM__SHIFT 0x00000003
+#define MC_ARB_PM_CNTL__OVRR_PM_MASK 0x00000080L
+#define MC_ARB_PM_CNTL__OVRR_PM__SHIFT 0x00000007
+#define MC_ARB_PM_CNTL__OVRR_PM_STATE_MASK 0x00000300L
+#define MC_ARB_PM_CNTL__OVRR_PM_STATE__SHIFT 0x00000008
+#define MC_ARB_PM_CNTL__OVRR_RD_MASK 0x00000400L
+#define MC_ARB_PM_CNTL__OVRR_RD__SHIFT 0x0000000a
+#define MC_ARB_PM_CNTL__OVRR_RD_STATE_MASK 0x00000800L
+#define MC_ARB_PM_CNTL__OVRR_RD_STATE__SHIFT 0x0000000b
+#define MC_ARB_PM_CNTL__OVRR_RFSH_MASK 0x00004000L
+#define MC_ARB_PM_CNTL__OVRR_RFSH__SHIFT 0x0000000e
+#define MC_ARB_PM_CNTL__OVRR_RFSH_STATE_MASK 0x00008000L
+#define MC_ARB_PM_CNTL__OVRR_RFSH_STATE__SHIFT 0x0000000f
+#define MC_ARB_PM_CNTL__OVRR_WR_MASK 0x00001000L
+#define MC_ARB_PM_CNTL__OVRR_WR__SHIFT 0x0000000c
+#define MC_ARB_PM_CNTL__OVRR_WR_STATE_MASK 0x00002000L
+#define MC_ARB_PM_CNTL__OVRR_WR_STATE__SHIFT 0x0000000d
+#define MC_ARB_PM_CNTL__SRFSH_ON_D1_MASK 0x00000010L
+#define MC_ARB_PM_CNTL__SRFSH_ON_D1__SHIFT 0x00000004
+#define MC_ARB_POP__ALLOW_EOB_BY_WRRET_STALL_MASK 0x00080000L
+#define MC_ARB_POP__ALLOW_EOB_BY_WRRET_STALL__SHIFT 0x00000013
+#define MC_ARB_POP__ENABLE_ARB_MASK 0x00000001L
+#define MC_ARB_POP__ENABLE_ARB__SHIFT 0x00000000
+#define MC_ARB_POP__ENABLE_TWO_PAGE_MASK 0x00040000L
+#define MC_ARB_POP__ENABLE_TWO_PAGE__SHIFT 0x00000012
+#define MC_ARB_POP__POP_DEPTH_MASK 0x0000003cL
+#define MC_ARB_POP__POP_DEPTH__SHIFT 0x00000002
+#define MC_ARB_POP__QUICK_STOP_MASK 0x00020000L
+#define MC_ARB_POP__QUICK_STOP__SHIFT 0x00000011
+#define MC_ARB_POP__SKID_DEPTH_MASK 0x00007000L
+#define MC_ARB_POP__SKID_DEPTH__SHIFT 0x0000000c
+#define MC_ARB_POP__SPEC_OPEN_MASK 0x00000002L
+#define MC_ARB_POP__SPEC_OPEN__SHIFT 0x00000001
+#define MC_ARB_POP__WAIT_AFTER_RFSH_MASK 0x00018000L
+#define MC_ARB_POP__WAIT_AFTER_RFSH__SHIFT 0x0000000f
+#define MC_ARB_POP__WRDATAINDEX_DEPTH_MASK 0x00000fc0L
+#define MC_ARB_POP__WRDATAINDEX_DEPTH__SHIFT 0x00000006
+#define MC_ARB_RAMCFG__CHANSIZE_MASK 0x00000100L
+#define MC_ARB_RAMCFG__CHANSIZE__SHIFT 0x00000008
+#define MC_ARB_RAMCFG__NOOFBANK_MASK 0x00000003L
+#define MC_ARB_RAMCFG__NOOFBANK__SHIFT 0x00000000
+#define MC_ARB_RAMCFG__NOOFCOLS_MASK 0x000000c0L
+#define MC_ARB_RAMCFG__NOOFCOLS__SHIFT 0x00000006
+#define MC_ARB_RAMCFG__NOOFGROUPS_MASK 0x00001000L
+#define MC_ARB_RAMCFG__NOOFGROUPS__SHIFT 0x0000000c
+#define MC_ARB_RAMCFG__NOOFRANKS_MASK 0x00000004L
+#define MC_ARB_RAMCFG__NOOFRANKS__SHIFT 0x00000002
+#define MC_ARB_RAMCFG__NOOFROWS_MASK 0x00000038L
+#define MC_ARB_RAMCFG__NOOFROWS__SHIFT 0x00000003
+#define MC_ARB_REMREQ__RD_WATER_MASK 0x000000ffL
+#define MC_ARB_REMREQ__RD_WATER__SHIFT 0x00000000
+#define MC_ARB_REMREQ__WR_LAZY_TIMER_MASK 0x00f00000L
+#define MC_ARB_REMREQ__WR_LAZY_TIMER__SHIFT 0x00000014
+#define MC_ARB_REMREQ__WR_MAXBURST_SIZE_MASK 0x000f0000L
+#define MC_ARB_REMREQ__WR_MAXBURST_SIZE__SHIFT 0x00000010
+#define MC_ARB_REMREQ__WR_WATER_MASK 0x0000ff00L
+#define MC_ARB_REMREQ__WR_WATER__SHIFT 0x00000008
+#define MC_ARB_REPLAY__BOS_ENABLE_WAIT_CYC_MASK 0x00000080L
+#define MC_ARB_REPLAY__BOS_ENABLE_WAIT_CYC__SHIFT 0x00000007
+#define MC_ARB_REPLAY__BOS_WAIT_CYC_MASK 0x00007f00L
+#define MC_ARB_REPLAY__BOS_WAIT_CYC__SHIFT 0x00000008
+#define MC_ARB_REPLAY__BREAK_ON_STALL_MASK 0x00000040L
+#define MC_ARB_REPLAY__BREAK_ON_STALL__SHIFT 0x00000006
+#define MC_ARB_REPLAY__ENABLE_RD_MASK 0x00000001L
+#define MC_ARB_REPLAY__ENABLE_RD__SHIFT 0x00000000
+#define MC_ARB_REPLAY__ENABLE_WR_MASK 0x00000002L
+#define MC_ARB_REPLAY__ENABLE_WR__SHIFT 0x00000001
+#define MC_ARB_REPLAY__IGNORE_WR_CDC_MASK 0x00000020L
+#define MC_ARB_REPLAY__IGNORE_WR_CDC__SHIFT 0x00000005
+#define MC_ARB_REPLAY__RAW_ENABLE_MASK 0x00000010L
+#define MC_ARB_REPLAY__RAW_ENABLE__SHIFT 0x00000004
+#define MC_ARB_REPLAY__WAW_ENABLE_MASK 0x00000008L
+#define MC_ARB_REPLAY__WAW_ENABLE__SHIFT 0x00000003
+#define MC_ARB_REPLAY__WRACK_MODE_MASK 0x00000004L
+#define MC_ARB_REPLAY__WRACK_MODE__SHIFT 0x00000002
+#define MC_ARB_RET_CREDITS_RD__DISP_MASK 0x00ff0000L
+#define MC_ARB_RET_CREDITS_RD__DISP__SHIFT 0x00000010
+#define MC_ARB_RET_CREDITS_RD__HUB_MASK 0x0000ff00L
+#define MC_ARB_RET_CREDITS_RD__HUB__SHIFT 0x00000008
+#define MC_ARB_RET_CREDITS_RD__LCL_MASK 0x000000ffL
+#define MC_ARB_RET_CREDITS_RD__LCL__SHIFT 0x00000000
+#define MC_ARB_RET_CREDITS_RD__RETURN_CREDIT_MASK 0xff000000L
+#define MC_ARB_RET_CREDITS_RD__RETURN_CREDIT__SHIFT 0x00000018
+#define MC_ARB_RET_CREDITS_WR__HUB_MASK 0x0000ff00L
+#define MC_ARB_RET_CREDITS_WR__HUB__SHIFT 0x00000008
+#define MC_ARB_RET_CREDITS_WR__LCL_MASK 0x000000ffL
+#define MC_ARB_RET_CREDITS_WR__LCL__SHIFT 0x00000000
+#define MC_ARB_RET_CREDITS_WR__RETURN_CREDIT_MASK 0x00ff0000L
+#define MC_ARB_RET_CREDITS_WR__RETURN_CREDIT__SHIFT 0x00000010
+#define MC_ARB_RET_CREDITS_WR__WRRET_SEQ_SKID_MASK 0x0f000000L
+#define MC_ARB_RET_CREDITS_WR__WRRET_SEQ_SKID__SHIFT 0x00000018
+#define MC_ARB_RFSH_CNTL__ACCUM_MASK 0x00000800L
+#define MC_ARB_RFSH_CNTL__ACCUM__SHIFT 0x0000000b
+#define MC_ARB_RFSH_CNTL__ENABLE_MASK 0x00000001L
+#define MC_ARB_RFSH_CNTL__ENABLE__SHIFT 0x00000000
+#define MC_ARB_RFSH_CNTL__URG0_MASK 0x0000003eL
+#define MC_ARB_RFSH_CNTL__URG0__SHIFT 0x00000001
+#define MC_ARB_RFSH_CNTL__URG1_MASK 0x000007c0L
+#define MC_ARB_RFSH_CNTL__URG1__SHIFT 0x00000006
+#define MC_ARB_RFSH_RATE__POWERMODE0_MASK 0x000000ffL
+#define MC_ARB_RFSH_RATE__POWERMODE0__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL0__BREAK_ON_HARSH_MASK 0x00000100L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_HARSH__SHIFT 0x00000008
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTRD_MASK 0x00000200L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTRD__SHIFT 0x00000009
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTWR_MASK 0x00000400L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTWR__SHIFT 0x0000000a
+#define MC_ARB_RTT_CNTL0__DATA_CNTL_MASK 0x01000000L
+#define MC_ARB_RTT_CNTL0__DATA_CNTL__SHIFT 0x00000018
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_0_MASK 0x00008000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_0__SHIFT 0x0000000f
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_1_MASK 0x00010000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_1__SHIFT 0x00000010
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_2_MASK 0x00020000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_2__SHIFT 0x00000011
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_3_MASK 0x00040000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_3__SHIFT 0x00000012
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_4_MASK 0x00080000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_4__SHIFT 0x00000013
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_5_MASK 0x00100000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_5__SHIFT 0x00000014
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_6_MASK 0x00200000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_6__SHIFT 0x00000015
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_7_MASK 0x00400000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_7__SHIFT 0x00000016
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_8_MASK 0x00800000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_8__SHIFT 0x00000017
+#define MC_ARB_RTT_CNTL0__ENABLE_MASK 0x00000001L
+#define MC_ARB_RTT_CNTL0__ENABLE__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL0__FLUSH_ON_ENTER_MASK 0x00000010L
+#define MC_ARB_RTT_CNTL0__FLUSH_ON_ENTER__SHIFT 0x00000004
+#define MC_ARB_RTT_CNTL0__HARSH_START_MASK 0x00000020L
+#define MC_ARB_RTT_CNTL0__HARSH_START__SHIFT 0x00000005
+#define MC_ARB_RTT_CNTL0__NEIGHBOR_BIT_MASK 0x02000000L
+#define MC_ARB_RTT_CNTL0__NEIGHBOR_BIT__SHIFT 0x00000019
+#define MC_ARB_RTT_CNTL0__START_IDLE_MASK 0x00000002L
+#define MC_ARB_RTT_CNTL0__START_IDLE__SHIFT 0x00000001
+#define MC_ARB_RTT_CNTL0__START_R2W_MASK 0x0000000cL
+#define MC_ARB_RTT_CNTL0__START_R2W_RFSH_MASK 0x00004000L
+#define MC_ARB_RTT_CNTL0__START_R2W_RFSH__SHIFT 0x0000000e
+#define MC_ARB_RTT_CNTL0__START_R2W__SHIFT 0x00000002
+#define MC_ARB_RTT_CNTL0__TPS_HARSH_PRIORITY_MASK 0x00000040L
+#define MC_ARB_RTT_CNTL0__TPS_HARSH_PRIORITY__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL0__TRAIN_PERIOD_MASK 0x00003800L
+#define MC_ARB_RTT_CNTL0__TRAIN_PERIOD__SHIFT 0x0000000b
+#define MC_ARB_RTT_CNTL0__TWRT_HARSH_PRIORITY_MASK 0x00000080L
+#define MC_ARB_RTT_CNTL0__TWRT_HARSH_PRIORITY__SHIFT 0x00000007
+#define MC_ARB_RTT_CNTL1__WINDOW_DEC_THRESHOLD_MASK 0x000fe000L
+#define MC_ARB_RTT_CNTL1__WINDOW_DEC_THRESHOLD__SHIFT 0x0000000d
+#define MC_ARB_RTT_CNTL1__WINDOW_INC_THRESHOLD_MASK 0x00001fc0L
+#define MC_ARB_RTT_CNTL1__WINDOW_INC_THRESHOLD__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MASK 0x0000001fL
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MAX_MASK 0x01f00000L
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MAX__SHIFT 0x00000014
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MIN_MASK 0x3e000000L
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MIN__SHIFT 0x00000019
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_COUNT_MASK 0xc0000000L
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_COUNT__SHIFT 0x0000001e
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_MASK 0x00000020L
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE__SHIFT 0x00000005
+#define MC_ARB_RTT_CNTL2__FILTER_CNTL_MASK 0x00002000L
+#define MC_ARB_RTT_CNTL2__FILTER_CNTL__SHIFT 0x0000000d
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_SIZE_MASK 0x00001000L
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_SIZE__SHIFT 0x0000000c
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_THRESHOLD_MASK 0x00000fc0L
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_THRESHOLD__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL2__SAMPLE_CNT_MASK 0x0000003fL
+#define MC_ARB_RTT_CNTL2__SAMPLE_CNT__SHIFT 0x00000000
+#define MC_ARB_RTT_DATA__PATTERN_MASK 0x000000ffL
+#define MC_ARB_RTT_DATA__PATTERN__SHIFT 0x00000000
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH0_MASK 0x00000003L
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH0__SHIFT 0x00000000
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH1_MASK 0x0000000cL
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH1__SHIFT 0x00000002
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH0_MASK 0x00000ff0L
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH0__SHIFT 0x00000004
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH1_MASK 0x01fe0000L
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH1__SHIFT 0x00000011
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH0_MASK 0x0001f000L
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH0__SHIFT 0x0000000c
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH1_MASK 0x3e000000L
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH1__SHIFT 0x00000019
+#define MC_ARB_SQM_CNTL__DYN_SQM_ENABLE_MASK 0x00000100L
+#define MC_ARB_SQM_CNTL__DYN_SQM_ENABLE__SHIFT 0x00000008
+#define MC_ARB_SQM_CNTL__MIN_PENAL_MASK 0x000000ffL
+#define MC_ARB_SQM_CNTL__MIN_PENAL__SHIFT 0x00000000
+#define MC_ARB_SQM_CNTL__RATIO_DEBUG_MASK 0xff000000L
+#define MC_ARB_SQM_CNTL__RATIO_DEBUG__SHIFT 0x00000018
+#define MC_ARB_SQM_CNTL__RATIO_MASK 0x00ff0000L
+#define MC_ARB_SQM_CNTL__RATIO__SHIFT 0x00000010
+#define MC_ARB_SQM_CNTL__SQM_RESERVE_MASK 0x0000fe00L
+#define MC_ARB_SQM_CNTL__SQM_RESERVE__SHIFT 0x00000009
+#define MC_ARB_TM_CNTL_RD__BANK_SELECT_MASK 0x00000006L
+#define MC_ARB_TM_CNTL_RD__BANK_SELECT__SHIFT 0x00000001
+#define MC_ARB_TM_CNTL_RD__GROUPBY_RANK_MASK 0x00000001L
+#define MC_ARB_TM_CNTL_RD__GROUPBY_RANK__SHIFT 0x00000000
+#define MC_ARB_TM_CNTL_RD__MATCH_BANK_MASK 0x00000010L
+#define MC_ARB_TM_CNTL_RD__MATCH_BANK__SHIFT 0x00000004
+#define MC_ARB_TM_CNTL_RD__MATCH_RANK_MASK 0x00000008L
+#define MC_ARB_TM_CNTL_RD__MATCH_RANK__SHIFT 0x00000003
+#define MC_ARB_TM_CNTL_WR__BANK_SELECT_MASK 0x00000006L
+#define MC_ARB_TM_CNTL_WR__BANK_SELECT__SHIFT 0x00000001
+#define MC_ARB_TM_CNTL_WR__GROUPBY_RANK_MASK 0x00000001L
+#define MC_ARB_TM_CNTL_WR__GROUPBY_RANK__SHIFT 0x00000000
+#define MC_ARB_TM_CNTL_WR__MATCH_BANK_MASK 0x00000010L
+#define MC_ARB_TM_CNTL_WR__MATCH_BANK__SHIFT 0x00000004
+#define MC_ARB_TM_CNTL_WR__MATCH_RANK_MASK 0x00000008L
+#define MC_ARB_TM_CNTL_WR__MATCH_RANK__SHIFT 0x00000003
+#define MC_ARB_WCDR_2__DEBUG_0_MASK 0x00000200L
+#define MC_ARB_WCDR_2__DEBUG_0__SHIFT 0x00000009
+#define MC_ARB_WCDR_2__DEBUG_1_MASK 0x00000400L
+#define MC_ARB_WCDR_2__DEBUG_1__SHIFT 0x0000000a
+#define MC_ARB_WCDR_2__DEBUG_2_MASK 0x00000800L
+#define MC_ARB_WCDR_2__DEBUG_2__SHIFT 0x0000000b
+#define MC_ARB_WCDR_2__DEBUG_3_MASK 0x00001000L
+#define MC_ARB_WCDR_2__DEBUG_3__SHIFT 0x0000000c
+#define MC_ARB_WCDR_2__DEBUG_4_MASK 0x00002000L
+#define MC_ARB_WCDR_2__DEBUG_4__SHIFT 0x0000000d
+#define MC_ARB_WCDR_2__DEBUG_5_MASK 0x00004000L
+#define MC_ARB_WCDR_2__DEBUG_5__SHIFT 0x0000000e
+#define MC_ARB_WCDR_2__WPRE_INC_STEP_MASK 0x0000000fL
+#define MC_ARB_WCDR_2__WPRE_INC_STEP__SHIFT 0x00000000
+#define MC_ARB_WCDR_2__WPRE_MIN_THRESHOLD_MASK 0x000001f0L
+#define MC_ARB_WCDR_2__WPRE_MIN_THRESHOLD__SHIFT 0x00000004
+#define MC_ARB_WCDR__IDLE_BURST_MASK 0x00001f80L
+#define MC_ARB_WCDR__IDLE_BURST_MODE_MASK 0x00002000L
+#define MC_ARB_WCDR__IDLE_BURST_MODE__SHIFT 0x0000000d
+#define MC_ARB_WCDR__IDLE_BURST__SHIFT 0x00000007
+#define MC_ARB_WCDR__IDLE_DEGLITCH_ENABLE_MASK 0x00010000L
+#define MC_ARB_WCDR__IDLE_DEGLITCH_ENABLE__SHIFT 0x00000010
+#define MC_ARB_WCDR__IDLE_ENABLE_MASK 0x00000001L
+#define MC_ARB_WCDR__IDLE_ENABLE__SHIFT 0x00000000
+#define MC_ARB_WCDR__IDLE_PERIOD_MASK 0x0000007cL
+#define MC_ARB_WCDR__IDLE_PERIOD__SHIFT 0x00000002
+#define MC_ARB_WCDR__IDLE_WAKEUP_MASK 0x0000c000L
+#define MC_ARB_WCDR__IDLE_WAKEUP__SHIFT 0x0000000e
+#define MC_ARB_WCDR__SEQ_IDLE_MASK 0x00000002L
+#define MC_ARB_WCDR__SEQ_IDLE__SHIFT 0x00000001
+#define MC_ARB_WCDR__WPRE_ENABLE_MASK 0x00020000L
+#define MC_ARB_WCDR__WPRE_ENABLE__SHIFT 0x00000011
+#define MC_ARB_WCDR__WPRE_INC_READ_MASK 0x02000000L
+#define MC_ARB_WCDR__WPRE_INC_READ__SHIFT 0x00000019
+#define MC_ARB_WCDR__WPRE_INC_SEQIDLE_MASK 0x08000000L
+#define MC_ARB_WCDR__WPRE_INC_SEQIDLE__SHIFT 0x0000001b
+#define MC_ARB_WCDR__WPRE_INC_SKIDIDLE_MASK 0x04000000L
+#define MC_ARB_WCDR__WPRE_INC_SKIDIDLE__SHIFT 0x0000001a
+#define MC_ARB_WCDR__WPRE_MAX_BURST_MASK 0x01c00000L
+#define MC_ARB_WCDR__WPRE_MAX_BURST__SHIFT 0x00000016
+#define MC_ARB_WCDR__WPRE_THRESHOLD_MASK 0x003c0000L
+#define MC_ARB_WCDR__WPRE_THRESHOLD__SHIFT 0x00000012
+#define MC_ARB_WCDR__WPRE_TWOPAGE_MASK 0x10000000L
+#define MC_ARB_WCDR__WPRE_TWOPAGE__SHIFT 0x0000001c
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP0_MASK 0x00000008L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP0__SHIFT 0x00000003
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP1_MASK 0x00000010L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP1__SHIFT 0x00000004
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP2_MASK 0x00000020L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP2__SHIFT 0x00000005
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP3_MASK 0x00000040L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP4_MASK 0x00000080L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP4__SHIFT 0x00000007
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP5_MASK 0x00000100L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP5__SHIFT 0x00000008
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP6_MASK 0x00000200L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP6__SHIFT 0x00000009
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP7_MASK 0x00000400L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP7__SHIFT 0x0000000a
+#define MC_ARB_WTM_CNTL_RD__HARSH_PRI_MASK 0x00000004L
+#define MC_ARB_WTM_CNTL_RD__HARSH_PRI__SHIFT 0x00000002
+#define MC_ARB_WTM_CNTL_RD__WTMODE_MASK 0x00000003L
+#define MC_ARB_WTM_CNTL_RD__WTMODE__SHIFT 0x00000000
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP0_MASK 0x00000008L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP0__SHIFT 0x00000003
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP1_MASK 0x00000010L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP1__SHIFT 0x00000004
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP2_MASK 0x00000020L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP2__SHIFT 0x00000005
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP3_MASK 0x00000040L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP4_MASK 0x00000080L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP4__SHIFT 0x00000007
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP5_MASK 0x00000100L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP5__SHIFT 0x00000008
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP6_MASK 0x00000200L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP6__SHIFT 0x00000009
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP7_MASK 0x00000400L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP7__SHIFT 0x0000000a
+#define MC_ARB_WTM_CNTL_WR__HARSH_PRI_MASK 0x00000004L
+#define MC_ARB_WTM_CNTL_WR__HARSH_PRI__SHIFT 0x00000002
+#define MC_ARB_WTM_CNTL_WR__WTMODE_MASK 0x00000003L
+#define MC_ARB_WTM_CNTL_WR__WTMODE__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_RD__GRP0_MASK 0x00000003L
+#define MC_ARB_WTM_GRPWT_RD__GRP0__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_RD__GRP1_MASK 0x0000000cL
+#define MC_ARB_WTM_GRPWT_RD__GRP1__SHIFT 0x00000002
+#define MC_ARB_WTM_GRPWT_RD__GRP2_MASK 0x00000030L
+#define MC_ARB_WTM_GRPWT_RD__GRP2__SHIFT 0x00000004
+#define MC_ARB_WTM_GRPWT_RD__GRP3_MASK 0x000000c0L
+#define MC_ARB_WTM_GRPWT_RD__GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_GRPWT_RD__GRP4_MASK 0x00000300L
+#define MC_ARB_WTM_GRPWT_RD__GRP4__SHIFT 0x00000008
+#define MC_ARB_WTM_GRPWT_RD__GRP5_MASK 0x00000c00L
+#define MC_ARB_WTM_GRPWT_RD__GRP5__SHIFT 0x0000000a
+#define MC_ARB_WTM_GRPWT_RD__GRP6_MASK 0x00003000L
+#define MC_ARB_WTM_GRPWT_RD__GRP6__SHIFT 0x0000000c
+#define MC_ARB_WTM_GRPWT_RD__GRP7_MASK 0x0000c000L
+#define MC_ARB_WTM_GRPWT_RD__GRP7__SHIFT 0x0000000e
+#define MC_ARB_WTM_GRPWT_RD__GRP_EXT_MASK 0x00ff0000L
+#define MC_ARB_WTM_GRPWT_RD__GRP_EXT__SHIFT 0x00000010
+#define MC_ARB_WTM_GRPWT_WR__GRP0_MASK 0x00000003L
+#define MC_ARB_WTM_GRPWT_WR__GRP0__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_WR__GRP1_MASK 0x0000000cL
+#define MC_ARB_WTM_GRPWT_WR__GRP1__SHIFT 0x00000002
+#define MC_ARB_WTM_GRPWT_WR__GRP2_MASK 0x00000030L
+#define MC_ARB_WTM_GRPWT_WR__GRP2__SHIFT 0x00000004
+#define MC_ARB_WTM_GRPWT_WR__GRP3_MASK 0x000000c0L
+#define MC_ARB_WTM_GRPWT_WR__GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_GRPWT_WR__GRP4_MASK 0x00000300L
+#define MC_ARB_WTM_GRPWT_WR__GRP4__SHIFT 0x00000008
+#define MC_ARB_WTM_GRPWT_WR__GRP5_MASK 0x00000c00L
+#define MC_ARB_WTM_GRPWT_WR__GRP5__SHIFT 0x0000000a
+#define MC_ARB_WTM_GRPWT_WR__GRP6_MASK 0x00003000L
+#define MC_ARB_WTM_GRPWT_WR__GRP6__SHIFT 0x0000000c
+#define MC_ARB_WTM_GRPWT_WR__GRP7_MASK 0x0000c000L
+#define MC_ARB_WTM_GRPWT_WR__GRP7__SHIFT 0x0000000e
+#define MC_ARB_WTM_GRPWT_WR__GRP_EXT_MASK 0x00ff0000L
+#define MC_ARB_WTM_GRPWT_WR__GRP_EXT__SHIFT 0x00000010
+#define MC_BIST_AUTO_CNTL__ADR_GEN_MASK 0x000000f0L
+#define MC_BIST_AUTO_CNTL__ADR_GEN__SHIFT 0x00000004
+#define MC_BIST_AUTO_CNTL__ADR_RESET_MASK 0x02000000L
+#define MC_BIST_AUTO_CNTL__ADR_RESET__SHIFT 0x00000019
+#define MC_BIST_AUTO_CNTL__LFSR_KEY_MASK 0x00ffff00L
+#define MC_BIST_AUTO_CNTL__LFSR_KEY__SHIFT 0x00000008
+#define MC_BIST_AUTO_CNTL__LFSR_RESET_MASK 0x01000000L
+#define MC_BIST_AUTO_CNTL__LFSR_RESET__SHIFT 0x00000018
+#define MC_BIST_AUTO_CNTL__MOP_MASK 0x00000003L
+#define MC_BIST_AUTO_CNTL__MOP__SHIFT 0x00000000
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_LOOP_MASK 0x00000004L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_LOOP__SHIFT 0x00000002
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_MASK 0x00000002L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE__SHIFT 0x00000001
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_U_MASK 0x00010000L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_U__SHIFT 0x00000010
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_RUN_MASK 0x00020000L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_RUN__SHIFT 0x00000011
+#define MC_BIST_CMD_CNTL__DONE_MASK 0x80000000L
+#define MC_BIST_CMD_CNTL__DONE__SHIFT 0x0000001f
+#define MC_BIST_CMD_CNTL__ENABLE_D0_MASK 0x10000000L
+#define MC_BIST_CMD_CNTL__ENABLE_D0__SHIFT 0x0000001c
+#define MC_BIST_CMD_CNTL__ENABLE_D1_MASK 0x20000000L
+#define MC_BIST_CMD_CNTL__ENABLE_D1__SHIFT 0x0000001d
+#define MC_BIST_CMD_CNTL__LOOP_CNT_MAX_MASK 0x0000fff0L
+#define MC_BIST_CMD_CNTL__LOOP_CNT_MAX__SHIFT 0x00000004
+#define MC_BIST_CMD_CNTL__LOOP_CNT_RD_MASK 0x0ffc0000L
+#define MC_BIST_CMD_CNTL__LOOP_CNT_RD__SHIFT 0x00000012
+#define MC_BIST_CMD_CNTL__LOOP_END_CONDITION_MASK 0x00000008L
+#define MC_BIST_CMD_CNTL__LOOP_END_CONDITION__SHIFT 0x00000003
+#define MC_BIST_CMD_CNTL__RESET_MASK 0x00000001L
+#define MC_BIST_CMD_CNTL__RESET__SHIFT 0x00000000
+#define MC_BIST_CMD_CNTL__STATUS_CH_MASK 0x40000000L
+#define MC_BIST_CMD_CNTL__STATUS_CH__SHIFT 0x0000001e
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_MASK 0x0000001fL
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_RST_MASK 0x00000100L
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_RST__SHIFT 0x00000008
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT__SHIFT 0x00000000
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_MASK 0x0001f000L
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_RST_MASK 0x00100000L
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_RST__SHIFT 0x00000014
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT__SHIFT 0x0000000c
+#define MC_BIST_CMP_CNTL__CMP_MASK 0x00030000L
+#define MC_BIST_CMP_CNTL__CMP_MASK_BIT_MASK 0x00000ff0L
+#define MC_BIST_CMP_CNTL__CMP_MASK_BIT__SHIFT 0x00000004
+#define MC_BIST_CMP_CNTL__CMP_MASK_BYTE_MASK 0x0000000fL
+#define MC_BIST_CMP_CNTL__CMP_MASK_BYTE__SHIFT 0x00000000
+#define MC_BIST_CMP_CNTL__CMP__SHIFT 0x00000010
+#define MC_BIST_CMP_CNTL__DATA_STORE_MODE_MASK 0x00300000L
+#define MC_BIST_CMP_CNTL__DATA_STORE_MODE__SHIFT 0x00000014
+#define MC_BIST_CMP_CNTL__DATA_STORE_SEL_MASK 0x00002000L
+#define MC_BIST_CMP_CNTL__DATA_STORE_SEL__SHIFT 0x0000000d
+#define MC_BIST_CMP_CNTL__DAT_MODE_MASK 0x00040000L
+#define MC_BIST_CMP_CNTL__DAT_MODE__SHIFT 0x00000012
+#define MC_BIST_CMP_CNTL__EDC_STORE_MODE_MASK 0x00080000L
+#define MC_BIST_CMP_CNTL__EDC_STORE_MODE__SHIFT 0x00000013
+#define MC_BIST_CMP_CNTL__EDC_STORE_SEL_MASK 0x00004000L
+#define MC_BIST_CMP_CNTL__EDC_STORE_SEL__SHIFT 0x0000000e
+#define MC_BIST_CMP_CNTL__ENABLE_CMD_FIFO_MASK 0x00008000L
+#define MC_BIST_CMP_CNTL__ENABLE_CMD_FIFO__SHIFT 0x0000000f
+#define MC_BIST_CMP_CNTL__LOAD_RTEDC_MASK 0x00001000L
+#define MC_BIST_CMP_CNTL__LOAD_RTEDC__SHIFT 0x0000000c
+#define MC_BIST_CMP_CNTL__MISMATCH_CNT_MASK 0xffc00000L
+#define MC_BIST_CMP_CNTL__MISMATCH_CNT__SHIFT 0x00000016
+#define MC_BIST_CNTL__ADR_MODE_MASK 0x00000020L
+#define MC_BIST_CNTL__ADR_MODE__SHIFT 0x00000005
+#define MC_BIST_CNTL__DAT_MODE_MASK 0x00000040L
+#define MC_BIST_CNTL__DAT_MODE__SHIFT 0x00000006
+#define MC_BIST_CNTL__DONE_MASK 0x40000000L
+#define MC_BIST_CNTL__DONE__SHIFT 0x0000001e
+#define MC_BIST_CNTL__ENABLE_D0_MASK 0x00001000L
+#define MC_BIST_CNTL__ENABLE_D0__SHIFT 0x0000000c
+#define MC_BIST_CNTL__ENABLE_D1_MASK 0x00002000L
+#define MC_BIST_CNTL__ENABLE_D1__SHIFT 0x0000000d
+#define MC_BIST_CNTL__LOAD_RTDATA_CH_MASK 0x00004000L
+#define MC_BIST_CNTL__LOAD_RTDATA_CH__SHIFT 0x0000000e
+#define MC_BIST_CNTL__LOAD_RTDATA_MASK 0x80000000L
+#define MC_BIST_CNTL__LOAD_RTDATA__SHIFT 0x0000001f
+#define MC_BIST_CNTL__LOOP_CNT_MASK 0x0fff0000L
+#define MC_BIST_CNTL__LOOP_CNT__SHIFT 0x00000010
+#define MC_BIST_CNTL__LOOP_MASK 0x00000c00L
+#define MC_BIST_CNTL__LOOP__SHIFT 0x0000000a
+#define MC_BIST_CNTL__MOP_MODE_MASK 0x00000010L
+#define MC_BIST_CNTL__MOP_MODE__SHIFT 0x00000004
+#define MC_BIST_CNTL__PTR_RST_D0_MASK 0x00000004L
+#define MC_BIST_CNTL__PTR_RST_D0__SHIFT 0x00000002
+#define MC_BIST_CNTL__PTR_RST_D1_MASK 0x00000008L
+#define MC_BIST_CNTL__PTR_RST_D1__SHIFT 0x00000003
+#define MC_BIST_CNTL__RESET_MASK 0x00000001L
+#define MC_BIST_CNTL__RESET__SHIFT 0x00000000
+#define MC_BIST_CNTL__RUN_MASK 0x00000002L
+#define MC_BIST_CNTL__RUN__SHIFT 0x00000001
+#define MC_BIST_DATA_MASK__MASK_MASK 0xffffffffL
+#define MC_BIST_DATA_MASK__MASK__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD0__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD0__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD1__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD1__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD2__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD2__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD3__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD3__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD4__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD4__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD5__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD5__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD6__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD6__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD7__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD7__DATA__SHIFT 0x00000000
+#define MC_BIST_DIR_CNTL__CMD_RTR_D0_MASK 0x00000040L
+#define MC_BIST_DIR_CNTL__CMD_RTR_D0__SHIFT 0x00000006
+#define MC_BIST_DIR_CNTL__CMD_RTR_D1_MASK 0x00000100L
+#define MC_BIST_DIR_CNTL__CMD_RTR_D1__SHIFT 0x00000008
+#define MC_BIST_DIR_CNTL__DATA_LOAD_MASK 0x00000020L
+#define MC_BIST_DIR_CNTL__DATA_LOAD__SHIFT 0x00000005
+#define MC_BIST_DIR_CNTL__DAT_RTR_D0_MASK 0x00000080L
+#define MC_BIST_DIR_CNTL__DAT_RTR_D0__SHIFT 0x00000007
+#define MC_BIST_DIR_CNTL__DAT_RTR_D1_MASK 0x00000200L
+#define MC_BIST_DIR_CNTL__DAT_RTR_D1__SHIFT 0x00000009
+#define MC_BIST_DIR_CNTL__EOB_MASK 0x00000008L
+#define MC_BIST_DIR_CNTL__EOB__SHIFT 0x00000003
+#define MC_BIST_DIR_CNTL__MOP3_MASK 0x00000400L
+#define MC_BIST_DIR_CNTL__MOP3__SHIFT 0x0000000a
+#define MC_BIST_DIR_CNTL__MOP_LOAD_MASK 0x00000010L
+#define MC_BIST_DIR_CNTL__MOP_LOAD__SHIFT 0x00000004
+#define MC_BIST_DIR_CNTL__MOP_MASK 0x00000007L
+#define MC_BIST_DIR_CNTL__MOP__SHIFT 0x00000000
+#define MC_BIST_EADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_EADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_EADDR__COLH_MASK 0x20000000L
+#define MC_BIST_EADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_EADDR__COL_MASK 0x000003ffL
+#define MC_BIST_EADDR__COL__SHIFT 0x00000000
+#define MC_BIST_EADDR__RANK_MASK 0x10000000L
+#define MC_BIST_EADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_EADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_EADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_EADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_EADDR__ROW__SHIFT 0x0000000a
+#define MC_BIST_MISMATCH_ADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_MISMATCH_ADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_MISMATCH_ADDR__COLH_MASK 0x20000000L
+#define MC_BIST_MISMATCH_ADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_MISMATCH_ADDR__COL_MASK 0x000003ffL
+#define MC_BIST_MISMATCH_ADDR__COL__SHIFT 0x00000000
+#define MC_BIST_MISMATCH_ADDR__RANK_MASK 0x10000000L
+#define MC_BIST_MISMATCH_ADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_MISMATCH_ADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_MISMATCH_ADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_MISMATCH_ADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_MISMATCH_ADDR__ROW__SHIFT 0x0000000a
+#define MC_BIST_RDATA_EDC__EDC_MASK 0xffffffffL
+#define MC_BIST_RDATA_EDC__EDC__SHIFT 0x00000000
+#define MC_BIST_RDATA_MASK__MASK_MASK 0xffffffffL
+#define MC_BIST_RDATA_MASK__MASK__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD0__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD0__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD1__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD1__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD2__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD2__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD3__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD3__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD4__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD4__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD5__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD5__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD6__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD6__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD7__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD7__RDATA__SHIFT 0x00000000
+#define MC_BIST_SADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_SADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_SADDR__COLH_MASK 0x20000000L
+#define MC_BIST_SADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_SADDR__COL_MASK 0x000003ffL
+#define MC_BIST_SADDR__COL__SHIFT 0x00000000
+#define MC_BIST_SADDR__RANK_MASK 0x10000000L
+#define MC_BIST_SADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_SADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_SADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_SADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_SADDR__ROW__SHIFT 0x0000000a
+#define MC_CG_CONFIG__INDEX_MASK 0x003fffc0L
+#define MC_CG_CONFIG__INDEX__SHIFT 0x00000006
+#define MC_CG_CONFIG_MCD__INDEX_MASK 0x1fffe000L
+#define MC_CG_CONFIG_MCD__INDEX__SHIFT 0x0000000d
+#define MC_CG_CONFIG_MCD__MCD0_WR_ENABLE_MASK 0x00000001L
+#define MC_CG_CONFIG_MCD__MCD0_WR_ENABLE__SHIFT 0x00000000
+#define MC_CG_CONFIG_MCD__MCD1_WR_ENABLE_MASK 0x00000002L
+#define MC_CG_CONFIG_MCD__MCD1_WR_ENABLE__SHIFT 0x00000001
+#define MC_CG_CONFIG_MCD__MCD2_WR_ENABLE_MASK 0x00000004L
+#define MC_CG_CONFIG_MCD__MCD2_WR_ENABLE__SHIFT 0x00000002
+#define MC_CG_CONFIG_MCD__MCD3_WR_ENABLE_MASK 0x00000008L
+#define MC_CG_CONFIG_MCD__MCD3_WR_ENABLE__SHIFT 0x00000003
+#define MC_CG_CONFIG_MCD__MCD4_WR_ENABLE_MASK 0x00000010L
+#define MC_CG_CONFIG_MCD__MCD4_WR_ENABLE__SHIFT 0x00000004
+#define MC_CG_CONFIG_MCD__MCD5_WR_ENABLE_MASK 0x00000020L
+#define MC_CG_CONFIG_MCD__MCD5_WR_ENABLE__SHIFT 0x00000005
+#define MC_CG_CONFIG_MCD__MC_RD_ENABLE_MASK 0x00000700L
+#define MC_CG_CONFIG_MCD__MC_RD_ENABLE__SHIFT 0x00000008
+#define MC_CG_CONFIG__MCDW_WR_ENABLE_MASK 0x00000001L
+#define MC_CG_CONFIG__MCDW_WR_ENABLE__SHIFT 0x00000000
+#define MC_CG_CONFIG__MCDX_WR_ENABLE_MASK 0x00000002L
+#define MC_CG_CONFIG__MCDX_WR_ENABLE__SHIFT 0x00000001
+#define MC_CG_CONFIG__MCDY_WR_ENABLE_MASK 0x00000004L
+#define MC_CG_CONFIG__MCDY_WR_ENABLE__SHIFT 0x00000002
+#define MC_CG_CONFIG__MCDZ_WR_ENABLE_MASK 0x00000008L
+#define MC_CG_CONFIG__MCDZ_WR_ENABLE__SHIFT 0x00000003
+#define MC_CG_CONFIG__MC_RD_ENABLE_MASK 0x00000030L
+#define MC_CG_CONFIG__MC_RD_ENABLE__SHIFT 0x00000004
+#define MC_CG_DATAPORT__DATA_FIELD_MASK 0xffffffffL
+#define MC_CG_DATAPORT__DATA_FIELD__SHIFT 0x00000000
+#define MC_CITF_CNTL__EXEMPTPM_MASK 0x00000008L
+#define MC_CITF_CNTL__EXEMPTPM__SHIFT 0x00000003
+#define MC_CITF_CNTL__GFX_IDLE_OVERRIDE_MASK 0x00000030L
+#define MC_CITF_CNTL__GFX_IDLE_OVERRIDE__SHIFT 0x00000004
+#define MC_CITF_CNTL__IGNOREPM_MASK 0x00000004L
+#define MC_CITF_CNTL__IGNOREPM__SHIFT 0x00000002
+#define MC_CITF_CNTL__MCD_SRBM_MASK_ENABLE_MASK 0x00000040L
+#define MC_CITF_CNTL__MCD_SRBM_MASK_ENABLE__SHIFT 0x00000006
+#define MC_CITF_CREDITS_ARB_RD__HUB_PRI_MASK 0x02000000L
+#define MC_CITF_CREDITS_ARB_RD__HUB_PRI__SHIFT 0x00000019
+#define MC_CITF_CREDITS_ARB_RD__LCL_PRI_MASK 0x01000000L
+#define MC_CITF_CREDITS_ARB_RD__LCL_PRI__SHIFT 0x00000018
+#define MC_CITF_CREDITS_ARB_RD__READ_HUB_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_ARB_RD__READ_HUB__SHIFT 0x00000008
+#define MC_CITF_CREDITS_ARB_RD__READ_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_ARB_RD__READ_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_ARB_RD__READ_PRI_MASK 0x00ff0000L
+#define MC_CITF_CREDITS_ARB_RD__READ_PRI__SHIFT 0x00000010
+#define MC_CITF_CREDITS_ARB_WR__HUB_PRI_MASK 0x00010000L
+#define MC_CITF_CREDITS_ARB_WR__HUB_PRI__SHIFT 0x00000010
+#define MC_CITF_CREDITS_ARB_WR__LCL_PRI_MASK 0x00020000L
+#define MC_CITF_CREDITS_ARB_WR__LCL_PRI__SHIFT 0x00000011
+#define MC_CITF_CREDITS_ARB_WR__WRITE_HUB_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_ARB_WR__WRITE_HUB__SHIFT 0x00000008
+#define MC_CITF_CREDITS_ARB_WR__WRITE_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_ARB_WR__WRITE_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_VM__READ_ALL_MASK 0x0000003fL
+#define MC_CITF_CREDITS_VM__READ_ALL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_VM__WRITE_ALL_MASK 0x00000fc0L
+#define MC_CITF_CREDITS_VM__WRITE_ALL__SHIFT 0x00000006
+#define MC_CITF_CREDITS_XBAR__READ_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_XBAR__READ_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_XBAR__WRITE_LCL_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_XBAR__WRITE_LCL__SHIFT 0x00000008
+#define MC_CITF_DAGB_CNTL__CENTER_RD_MAX_BURST_MASK 0x0000001eL
+#define MC_CITF_DAGB_CNTL__CENTER_RD_MAX_BURST__SHIFT 0x00000001
+#define MC_CITF_DAGB_CNTL__CENTER_WR_MAX_BURST_MASK 0x000003c0L
+#define MC_CITF_DAGB_CNTL__CENTER_WR_MAX_BURST__SHIFT 0x00000006
+#define MC_CITF_DAGB_CNTL__DISABLE_SELF_INIT_MASK 0x00000020L
+#define MC_CITF_DAGB_CNTL__DISABLE_SELF_INIT__SHIFT 0x00000005
+#define MC_CITF_DAGB_CNTL__JUMP_AHEAD_MASK 0x00000001L
+#define MC_CITF_DAGB_CNTL__JUMP_AHEAD__SHIFT 0x00000000
+#define MC_CITF_DAGB_DLY__CLI_MASK 0x001f0000L
+#define MC_CITF_DAGB_DLY__CLI__SHIFT 0x00000010
+#define MC_CITF_DAGB_DLY__DLY_MASK 0x0000001fL
+#define MC_CITF_DAGB_DLY__DLY__SHIFT 0x00000000
+#define MC_CITF_DAGB_DLY__POS_MASK 0x1f000000L
+#define MC_CITF_DAGB_DLY__POS__SHIFT 0x00000018
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_HP_MASK 0x00fc0000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_HP__SHIFT 0x00000012
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_LP_MASK 0x0003f000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_LP__SHIFT 0x0000000c
+#define MC_CITF_INT_CREDITS__CNTR_RD_LCL_MASK 0x3f000000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_LCL__SHIFT 0x00000018
+#define MC_CITF_INT_CREDITS__REMRDRET_MASK 0x0000003fL
+#define MC_CITF_INT_CREDITS__REMRDRET__SHIFT 0x00000000
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_HUB_MASK 0x0000003fL
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_HUB__SHIFT 0x00000000
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_LCL_MASK 0x00000fc0L
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_LCL__SHIFT 0x00000006
+#define MC_CITF_MISC_RD_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_RD_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_RD_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_RD_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_RD_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_RD_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_RD_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_RD_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_RD_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_MISC_VM_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_VM_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_VM_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_VM_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_VM_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_VM_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_VM_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_VM_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_VM_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_MISC_WR_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_WR_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_WR_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_WR_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_WR_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_WR_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_WR_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_WR_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_WR_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_PERF_MON_CNTL2__CID_MASK 0x000001ffL
+#define MC_CITF_PERF_MON_CNTL2__CID__SHIFT 0x00000000
+#define MC_CITF_PERF_MON_RSLT2__CB_RD_BUSY_MASK 0x00000040L
+#define MC_CITF_PERF_MON_RSLT2__CB_RD_BUSY__SHIFT 0x00000006
+#define MC_CITF_PERF_MON_RSLT2__CB_WR_BUSY_MASK 0x00001000L
+#define MC_CITF_PERF_MON_RSLT2__CB_WR_BUSY__SHIFT 0x0000000c
+#define MC_CITF_PERF_MON_RSLT2__DB_RD_BUSY_MASK 0x00000080L
+#define MC_CITF_PERF_MON_RSLT2__DB_RD_BUSY__SHIFT 0x00000007
+#define MC_CITF_PERF_MON_RSLT2__DB_WR_BUSY_MASK 0x00002000L
+#define MC_CITF_PERF_MON_RSLT2__DB_WR_BUSY__SHIFT 0x0000000d
+#define MC_CITF_PERF_MON_RSLT2__SX_WR_BUSY_MASK 0x00004000L
+#define MC_CITF_PERF_MON_RSLT2__SX_WR_BUSY__SHIFT 0x0000000e
+#define MC_CITF_PERF_MON_RSLT2__TC0_RD_BUSY_MASK 0x00000100L
+#define MC_CITF_PERF_MON_RSLT2__TC0_RD_BUSY__SHIFT 0x00000008
+#define MC_CITF_PERF_MON_RSLT2__TC0_WR_BUSY_MASK 0x00010000L
+#define MC_CITF_PERF_MON_RSLT2__TC0_WR_BUSY__SHIFT 0x00000010
+#define MC_CITF_PERF_MON_RSLT2__TC1_RD_BUSY_MASK 0x00000400L
+#define MC_CITF_PERF_MON_RSLT2__TC1_RD_BUSY__SHIFT 0x0000000a
+#define MC_CITF_PERF_MON_RSLT2__TC1_WR_BUSY_MASK 0x00020000L
+#define MC_CITF_PERF_MON_RSLT2__TC1_WR_BUSY__SHIFT 0x00000011
+#define MC_CITF_PERF_MON_RSLT2__TC2_RD_BUSY_MASK 0x00008000L
+#define MC_CITF_PERF_MON_RSLT2__TC2_RD_BUSY__SHIFT 0x0000000f
+#define MC_CITF_PERF_MON_RSLT2__TC2_WR_BUSY_MASK 0x00040000L
+#define MC_CITF_PERF_MON_RSLT2__TC2_WR_BUSY__SHIFT 0x00000012
+#define MC_CITF_PERF_MON_RSLT2__VC0_RD_BUSY_MASK 0x00000200L
+#define MC_CITF_PERF_MON_RSLT2__VC0_RD_BUSY__SHIFT 0x00000009
+#define MC_CITF_PERF_MON_RSLT2__VC1_RD_BUSY_MASK 0x00000800L
+#define MC_CITF_PERF_MON_RSLT2__VC1_RD_BUSY__SHIFT 0x0000000b
+#define MC_CITF_REMREQ__CREDITS_ENABLE_MASK 0x00004000L
+#define MC_CITF_REMREQ__CREDITS_ENABLE__SHIFT 0x0000000e
+#define MC_CITF_REMREQ__READ_CREDITS_MASK 0x0000007fL
+#define MC_CITF_REMREQ__READ_CREDITS__SHIFT 0x00000000
+#define MC_CITF_REMREQ__WRITE_CREDITS_MASK 0x00003f80L
+#define MC_CITF_REMREQ__WRITE_CREDITS__SHIFT 0x00000007
+#define MC_CITF_RET_MODE__INORDER_RD_MASK 0x00000001L
+#define MC_CITF_RET_MODE__INORDER_RD__SHIFT 0x00000000
+#define MC_CITF_RET_MODE__INORDER_WR_MASK 0x00000002L
+#define MC_CITF_RET_MODE__INORDER_WR__SHIFT 0x00000001
+#define MC_CITF_RET_MODE__LCLPRI_RD_MASK 0x00000010L
+#define MC_CITF_RET_MODE__LCLPRI_RD__SHIFT 0x00000004
+#define MC_CITF_RET_MODE__LCLPRI_WR_MASK 0x00000020L
+#define MC_CITF_RET_MODE__LCLPRI_WR__SHIFT 0x00000005
+#define MC_CITF_RET_MODE__REMPRI_RD_MASK 0x00000004L
+#define MC_CITF_RET_MODE__REMPRI_RD__SHIFT 0x00000002
+#define MC_CITF_RET_MODE__REMPRI_WR_MASK 0x00000008L
+#define MC_CITF_RET_MODE__REMPRI_WR__SHIFT 0x00000003
+#define MC_CITF_WTM_RD_CNTL__DISABLE_REMOTE_MASK 0x01000000L
+#define MC_CITF_WTM_RD_CNTL__DISABLE_REMOTE__SHIFT 0x00000018
+#define MC_CITF_WTM_RD_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_CITF_WTM_RD_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_CITF_WTM_RD_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_CITF_WTM_RD_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_CITF_WTM_RD_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_CITF_WTM_RD_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_CITF_WTM_RD_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_CITF_WTM_RD_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_CITF_WTM_RD_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_CITF_WTM_RD_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_CITF_WTM_RD_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_CITF_WTM_RD_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_CITF_WTM_RD_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_CITF_WTM_RD_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_CITF_WTM_RD_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_CITF_WTM_RD_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_CITF_WTM_WR_CNTL__DISABLE_REMOTE_MASK 0x01000000L
+#define MC_CITF_WTM_WR_CNTL__DISABLE_REMOTE__SHIFT 0x00000018
+#define MC_CITF_WTM_WR_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_CITF_WTM_WR_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_CITF_WTM_WR_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_CITF_WTM_WR_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_CITF_WTM_WR_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_CITF_WTM_WR_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_CITF_WTM_WR_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_CITF_WTM_WR_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_CITF_WTM_WR_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_CITF_WTM_WR_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_CITF_WTM_WR_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_CITF_WTM_WR_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_CITF_WTM_WR_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_CITF_WTM_WR_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_CITF_WTM_WR_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_CITF_WTM_WR_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_CITF_XTRA_ENABLE__ARB_DBG_MASK 0x00000f00L
+#define MC_CITF_XTRA_ENABLE__ARB_DBG__SHIFT 0x00000008
+#define MC_CITF_XTRA_ENABLE__CB1_RD_MASK 0x00000001L
+#define MC_CITF_XTRA_ENABLE__CB1_RD__SHIFT 0x00000000
+#define MC_CITF_XTRA_ENABLE__CB1_WR_MASK 0x00000002L
+#define MC_CITF_XTRA_ENABLE__CB1_WR__SHIFT 0x00000001
+#define MC_CITF_XTRA_ENABLE__DB1_RD_MASK 0x00000004L
+#define MC_CITF_XTRA_ENABLE__DB1_RD__SHIFT 0x00000002
+#define MC_CITF_XTRA_ENABLE__DB1_WR_MASK 0x00000008L
+#define MC_CITF_XTRA_ENABLE__DB1_WR__SHIFT 0x00000003
+#define MC_CITF_XTRA_ENABLE__TC2_RD_MASK 0x00000010L
+#define MC_CITF_XTRA_ENABLE__TC2_RD__SHIFT 0x00000004
+#define MC_CITF_XTRA_ENABLE__TC2_WR_MASK 0x00001000L
+#define MC_CITF_XTRA_ENABLE__TC2_WR__SHIFT 0x0000000c
+#define MC_CONFIG__MCC_INDEX_MODE_ENABLE_MASK 0x80000000L
+#define MC_CONFIG__MCC_INDEX_MODE_ENABLE__SHIFT 0x0000001f
+#define MC_CONFIG_MCD__MCD0_WR_ENABLE_MASK 0x00000001L
+#define MC_CONFIG_MCD__MCD0_WR_ENABLE__SHIFT 0x00000000
+#define MC_CONFIG_MCD__MCD1_WR_ENABLE_MASK 0x00000002L
+#define MC_CONFIG_MCD__MCD1_WR_ENABLE__SHIFT 0x00000001
+#define MC_CONFIG_MCD__MCD2_WR_ENABLE_MASK 0x00000004L
+#define MC_CONFIG_MCD__MCD2_WR_ENABLE__SHIFT 0x00000002
+#define MC_CONFIG_MCD__MCD3_WR_ENABLE_MASK 0x00000008L
+#define MC_CONFIG_MCD__MCD3_WR_ENABLE__SHIFT 0x00000003
+#define MC_CONFIG_MCD__MCD4_WR_ENABLE_MASK 0x00000010L
+#define MC_CONFIG_MCD__MCD4_WR_ENABLE__SHIFT 0x00000004
+#define MC_CONFIG_MCD__MCD5_WR_ENABLE_MASK 0x00000020L
+#define MC_CONFIG_MCD__MCD5_WR_ENABLE__SHIFT 0x00000005
+#define MC_CONFIG_MCD__MCD_INDEX_MODE_ENABLE_MASK 0x80000000L
+#define MC_CONFIG_MCD__MCD_INDEX_MODE_ENABLE__SHIFT 0x0000001f
+#define MC_CONFIG_MCD__MC_RD_ENABLE_MASK 0x00000700L
+#define MC_CONFIG_MCD__MC_RD_ENABLE__SHIFT 0x00000008
+#define MC_CONFIG__MCDW_WR_ENABLE_MASK 0x00000001L
+#define MC_CONFIG__MCDW_WR_ENABLE__SHIFT 0x00000000
+#define MC_CONFIG__MCDX_WR_ENABLE_MASK 0x00000002L
+#define MC_CONFIG__MCDX_WR_ENABLE__SHIFT 0x00000001
+#define MC_CONFIG__MCDY_WR_ENABLE_MASK 0x00000004L
+#define MC_CONFIG__MCDY_WR_ENABLE__SHIFT 0x00000002
+#define MC_CONFIG__MCDZ_WR_ENABLE_MASK 0x00000008L
+#define MC_CONFIG__MCDZ_WR_ENABLE__SHIFT 0x00000003
+#define MC_CONFIG__MC_RD_ENABLE_MASK 0x00000030L
+#define MC_CONFIG__MC_RD_ENABLE__SHIFT 0x00000004
+#define MC_HUB_MISC_DBG__SELECT0_MASK 0x0000000fL
+#define MC_HUB_MISC_DBG__SELECT0__SHIFT 0x00000000
+#define MC_HUB_MISC_DBG__SELECT1_MASK 0x000000f0L
+#define MC_HUB_MISC_DBG__SELECT1__SHIFT 0x00000004
+#define MC_HUB_MISC_FRAMING__BITS_MASK 0xffffffffL
+#define MC_HUB_MISC_FRAMING__BITS__SHIFT 0x00000000
+#define MC_HUB_MISC_HUB_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_HUB_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_HUB_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_HUB_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_HUB_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_HUB_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_HUB_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_HUB_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_READ_MASK 0x00000001L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_READ__SHIFT 0x00000000
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_WRITE_MASK 0x00000002L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_WRITE__SHIFT 0x00000001
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_READ_MASK 0x00000400L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_READ__SHIFT 0x0000000a
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_WRITE_MASK 0x00000800L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_WRITE__SHIFT 0x0000000b
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_READ_MASK 0x00000004L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_READ__SHIFT 0x00000002
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_WRITE_MASK 0x00000008L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_WRITE__SHIFT 0x00000003
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_READ_MASK 0x00010000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_READ__SHIFT 0x00000010
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_WRITE_MASK 0x00020000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_WRITE__SHIFT 0x00000011
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_READ_MASK 0x00040000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_READ__SHIFT 0x00000012
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_WRITE_MASK 0x00080000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_WRITE__SHIFT 0x00000013
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_READ_MASK 0x00000040L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_READ__SHIFT 0x00000006
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_WRITE_MASK 0x00000080L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_WRITE__SHIFT 0x00000007
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_READ_MASK 0x00004000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_READ__SHIFT 0x0000000e
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_WRITE_MASK 0x00008000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_WRITE__SHIFT 0x0000000f
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_READ_MASK 0x00001000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_READ__SHIFT 0x0000000c
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_WRITE_MASK 0x00002000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_WRITE__SHIFT 0x0000000d
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_READ_MASK 0x01000000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_READ__SHIFT 0x00000018
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_WRITE_MASK 0x02000000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_WRITE__SHIFT 0x00000019
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_READ_MASK 0x00100000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_READ__SHIFT 0x00000014
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_WRITE_MASK 0x00200000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_WRITE__SHIFT 0x00000015
+#define MC_HUB_MISC_OVERRIDE__IDLE_MASK 0x00000003L
+#define MC_HUB_MISC_OVERRIDE__IDLE__SHIFT 0x00000000
+#define MC_HUB_MISC_POWER__PM_BLACKOUT_CNTL_MASK 0x00000018L
+#define MC_HUB_MISC_POWER__PM_BLACKOUT_CNTL__SHIFT 0x00000003
+#define MC_HUB_MISC_POWER__SRBM_GATE_OVERRIDE_MASK 0x00000004L
+#define MC_HUB_MISC_POWER__SRBM_GATE_OVERRIDE__SHIFT 0x00000002
+#define MC_HUB_MISC_SIP_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_SIP_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_SIP_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_SIP_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_SIP_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_SIP_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_SIP_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_SIP_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_MISC_STATUS__GFX_BUSY_MASK 0x00002000L
+#define MC_HUB_MISC_STATUS__GFX_BUSY__SHIFT 0x0000000d
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDREQ_MASK 0x00000004L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDREQ__SHIFT 0x00000002
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDRET_MASK 0x00000008L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDRET__SHIFT 0x00000003
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRREQ_MASK 0x00000010L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRREQ__SHIFT 0x00000004
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRRET_MASK 0x00000020L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRRET__SHIFT 0x00000005
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_READ_MASK 0x00000100L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_READ__SHIFT 0x00000008
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_WRITE_MASK 0x00000200L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_WRITE__SHIFT 0x00000009
+#define MC_HUB_MISC_STATUS__OUTSTANDING_READ_MASK 0x00000001L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_READ__SHIFT 0x00000000
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_READ_MASK 0x00000040L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_READ__SHIFT 0x00000006
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_WRITE_MASK 0x00000080L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_WRITE__SHIFT 0x00000007
+#define MC_HUB_MISC_STATUS__OUTSTANDING_WRITE_MASK 0x00000002L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_WRITE__SHIFT 0x00000001
+#define MC_HUB_MISC_STATUS__READ_DEADLOCK_WARNING_MASK 0x00001000L
+#define MC_HUB_MISC_STATUS__READ_DEADLOCK_WARNING__SHIFT 0x0000000c
+#define MC_HUB_MISC_STATUS__RPB_BUSY_MASK 0x00000400L
+#define MC_HUB_MISC_STATUS__RPB_BUSY__SHIFT 0x0000000a
+#define MC_HUB_MISC_STATUS__WRITE_DEADLOCK_WARNING_MASK 0x00000800L
+#define MC_HUB_MISC_STATUS__WRITE_DEADLOCK_WARNING__SHIFT 0x0000000b
+#define MC_HUB_MISC_VM_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_VM_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_VM_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_VM_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_VM_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_VM_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_VM_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_VM_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_VM_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_RDREQ_CNTL__BREAK_HDP_DEADLOCK_MASK 0x00000200L
+#define MC_HUB_RDREQ_CNTL__BREAK_HDP_DEADLOCK__SHIFT 0x00000009
+#define MC_HUB_RDREQ_CNTL__DEBUG_REG_MASK 0x0001fc00L
+#define MC_HUB_RDREQ_CNTL__DEBUG_REG__SHIFT 0x0000000a
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL0_MASK 0x00020000L
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL0__SHIFT 0x00000011
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL1_MASK 0x00040000L
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL1__SHIFT 0x00000012
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL0_MASK 0x00000004L
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL0__SHIFT 0x00000002
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL1_MASK 0x00000008L
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL1__SHIFT 0x00000003
+#define MC_HUB_RDREQ_CNTL__MCDW_STALL_MODE_MASK 0x00000020L
+#define MC_HUB_RDREQ_CNTL__MCDW_STALL_MODE__SHIFT 0x00000005
+#define MC_HUB_RDREQ_CNTL__MCDX_STALL_MODE_MASK 0x00000040L
+#define MC_HUB_RDREQ_CNTL__MCDX_STALL_MODE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_CNTL__MCDY_STALL_MODE_MASK 0x00000080L
+#define MC_HUB_RDREQ_CNTL__MCDY_STALL_MODE__SHIFT 0x00000007
+#define MC_HUB_RDREQ_CNTL__MCDZ_STALL_MODE_MASK 0x00000100L
+#define MC_HUB_RDREQ_CNTL__MCDZ_STALL_MODE__SHIFT 0x00000008
+#define MC_HUB_RDREQ_CNTL__OVERRIDE_STALL_ENABLE_MASK 0x00000010L
+#define MC_HUB_RDREQ_CNTL__OVERRIDE_STALL_ENABLE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_CNTL__PWRXPRESS_MODE_MASK 0x00080000L
+#define MC_HUB_RDREQ_CNTL__PWRXPRESS_MODE__SHIFT 0x00000013
+#define MC_HUB_RDREQ_CNTL__REMOTE_BLACKOUT_MASK 0x00000001L
+#define MC_HUB_RDREQ_CNTL__REMOTE_BLACKOUT__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS2__STOR1_PRI_MASK 0x000000ffL
+#define MC_HUB_RDREQ_CREDITS2__STOR1_PRI__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS__STOR0_MASK 0x00ff0000L
+#define MC_HUB_RDREQ_CREDITS__STOR0__SHIFT 0x00000010
+#define MC_HUB_RDREQ_CREDITS__STOR1_MASK 0xff000000L
+#define MC_HUB_RDREQ_CREDITS__STOR1__SHIFT 0x00000018
+#define MC_HUB_RDREQ_CREDITS__VM0_MASK 0x000000ffL
+#define MC_HUB_RDREQ_CREDITS__VM0__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS__VM1_MASK 0x0000ff00L
+#define MC_HUB_RDREQ_CREDITS__VM1__SHIFT 0x00000008
+#define MC_HUB_RDREQ_DMIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_DMIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_DMIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_DMIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_DMIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_DMIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK 0x00000003L
+#define MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_DMIF_LIMIT__LIMIT_COUNT_MASK 0x0000007cL
+#define MC_HUB_RDREQ_DMIF_LIMIT__LIMIT_COUNT__SHIFT 0x00000002
+#define MC_HUB_RDREQ_DMIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_DMIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_DMIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_DMIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_DMIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_DMIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_GBL0__STALL_THRESHOLD_MASK 0x000000ffL
+#define MC_HUB_RDREQ_GBL0__STALL_THRESHOLD__SHIFT 0x00000000
+#define MC_HUB_RDREQ_GBL1__STALL_THRESHOLD_MASK 0x000000ffL
+#define MC_HUB_RDREQ_GBL1__STALL_THRESHOLD__SHIFT 0x00000000
+#define MC_HUB_RDREQ_HDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_HDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_HDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_HDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_HDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_HDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_HDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_HDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_HDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_HDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_HDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_HDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_MCDW__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDW__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDW__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDW__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDW__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDW__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDW__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDW__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDW__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDW__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDW__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDW__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDW__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDW__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDW__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDW__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDX__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDX__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDX__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDX__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDX__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDX__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDX__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDX__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDX__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDX__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDX__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDX__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDX__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDX__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDX__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDX__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDY__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDY__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDY__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDY__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDY__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDY__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDY__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDY__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDY__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDY__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDY__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDY__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDY__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDY__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDY__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDY__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDZ__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDZ__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDZ__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDZ__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDZ__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDZ__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDZ__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDZ__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDZ__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDZ__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDZ__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDZ__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDZ__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDZ__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDZ__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDZ__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_MCIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_MCIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_MCIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_MCIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_RLC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_RLC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_RLC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_RLC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_RLC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_RLC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_RLC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_RLC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_RLC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_RLC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_RLC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_RLC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_SEM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_SEM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_SEM__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_SEM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SEM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_SEM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_SEM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_SEM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SEM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_SEM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_SEM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_SEM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_SIP__ASK_CREDITS_MASK 0x0000007fL
+#define MC_HUB_RDREQ_SIP__ASK_CREDITS__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SIP__DISPLAY_CREDITS_MASK 0x00007f00L
+#define MC_HUB_RDREQ_SIP__DISPLAY_CREDITS__SHIFT 0x00000008
+#define MC_HUB_RDREQ_SIP__DUMMY_MASK 0x00000080L
+#define MC_HUB_RDREQ_SIP__DUMMY__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SMU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_SMU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_SMU__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_SMU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SMU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_SMU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_SMU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_SMU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SMU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_SMU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_SMU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_SMU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_STATUS__GBL0_BYPASS_STOR_FULL_MASK 0x00000080L
+#define MC_HUB_RDREQ_STATUS__GBL0_BYPASS_STOR_FULL__SHIFT 0x00000007
+#define MC_HUB_RDREQ_STATUS__GBL0_STOR_FULL_MASK 0x00000040L
+#define MC_HUB_RDREQ_STATUS__GBL0_STOR_FULL__SHIFT 0x00000006
+#define MC_HUB_RDREQ_STATUS__GBL0_VM_FULL_MASK 0x00000020L
+#define MC_HUB_RDREQ_STATUS__GBL0_VM_FULL__SHIFT 0x00000005
+#define MC_HUB_RDREQ_STATUS__GBL1_BYPASS_STOR_FULL_MASK 0x00000400L
+#define MC_HUB_RDREQ_STATUS__GBL1_BYPASS_STOR_FULL__SHIFT 0x0000000a
+#define MC_HUB_RDREQ_STATUS__GBL1_STOR_FULL_MASK 0x00000200L
+#define MC_HUB_RDREQ_STATUS__GBL1_STOR_FULL__SHIFT 0x00000009
+#define MC_HUB_RDREQ_STATUS__GBL1_VM_FULL_MASK 0x00000100L
+#define MC_HUB_RDREQ_STATUS__GBL1_VM_FULL__SHIFT 0x00000008
+#define MC_HUB_RDREQ_STATUS__MCDW_RD_AVAIL_MASK 0x00000002L
+#define MC_HUB_RDREQ_STATUS__MCDW_RD_AVAIL__SHIFT 0x00000001
+#define MC_HUB_RDREQ_STATUS__MCDX_RD_AVAIL_MASK 0x00000004L
+#define MC_HUB_RDREQ_STATUS__MCDX_RD_AVAIL__SHIFT 0x00000002
+#define MC_HUB_RDREQ_STATUS__MCDY_RD_AVAIL_MASK 0x00000008L
+#define MC_HUB_RDREQ_STATUS__MCDY_RD_AVAIL__SHIFT 0x00000003
+#define MC_HUB_RDREQ_STATUS__MCDZ_RD_AVAIL_MASK 0x00000010L
+#define MC_HUB_RDREQ_STATUS__MCDZ_RD_AVAIL__SHIFT 0x00000004
+#define MC_HUB_RDREQ_STATUS__PWRXPRESS_ERR_MASK 0x00000800L
+#define MC_HUB_RDREQ_STATUS__PWRXPRESS_ERR__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_STATUS__SIP_AVAIL_MASK 0x00000001L
+#define MC_HUB_RDREQ_STATUS__SIP_AVAIL__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_UMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_UMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_UMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_UMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_UMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_UMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_UMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_UMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_UMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_UMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_UVD__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_UVD__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_UVD__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_UVD__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UVD__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_UVD__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_UVD__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_UVD__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_UVD__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_UVD__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_UVD__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_UVD__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_UVD__VM_BYPASS_MASK 0x00010000L
+#define MC_HUB_RDREQ_UVD__VM_BYPASS__SHIFT 0x00000010
+#define MC_HUB_RDREQ_VCE__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VCE__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VCE__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VCE__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VCE__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VCE__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VCE__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VCE__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VCE__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VCE__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VCE__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VCE__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_VCEU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VCEU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VCEU__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VCEU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VCEU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VCEU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VCEU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VCEU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VCEU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VCEU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VCEU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VCEU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_VMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_HUB_RDREQ_XDMAM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_XDMAM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_XDMAM__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_XDMAM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_XDMAM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_XDMAM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_XDMAM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_XDMAM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_XDMAM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_XDMAM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_XDMAM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_XDMAM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_SHARED_DAGB_DLY__CLI_MASK 0x001f0000L
+#define MC_HUB_SHARED_DAGB_DLY__CLI__SHIFT 0x00000010
+#define MC_HUB_SHARED_DAGB_DLY__DLY_MASK 0x0000003fL
+#define MC_HUB_SHARED_DAGB_DLY__DLY__SHIFT 0x00000000
+#define MC_HUB_SHARED_DAGB_DLY__POS_MASK 0x1f000000L
+#define MC_HUB_SHARED_DAGB_DLY__POS__SHIFT 0x00000018
+#define MC_HUB_WDP_BP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_BP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_BP__RDRET_MASK 0x0003fffeL
+#define MC_HUB_WDP_BP__RDRET__SHIFT 0x00000001
+#define MC_HUB_WDP_BP__WRREQ_MASK 0x3ffc0000L
+#define MC_HUB_WDP_BP__WRREQ__SHIFT 0x00000012
+#define MC_HUB_WDP_CNTL__DEBUG_REG_MASK 0x00001fe0L
+#define MC_HUB_WDP_CNTL__DEBUG_REG__SHIFT 0x00000005
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL0_MASK 0x00002000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL0__SHIFT 0x0000000d
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL1_MASK 0x00004000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL1__SHIFT 0x0000000e
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_INTERNAL_MASK 0x00008000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_INTERNAL__SHIFT 0x0000000f
+#define MC_HUB_WDP_CNTL__DISP_WAIT_EOP_MASK 0x00040000L
+#define MC_HUB_WDP_CNTL__DISP_WAIT_EOP__SHIFT 0x00000012
+#define MC_HUB_WDP_CNTL__FAIR_CH_SW_MASK 0x00010000L
+#define MC_HUB_WDP_CNTL__FAIR_CH_SW__SHIFT 0x00000010
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL0_MASK 0x00000002L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL0__SHIFT 0x00000001
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL1_MASK 0x00000004L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL1__SHIFT 0x00000002
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_INTERNAL_MASK 0x00000008L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_INTERNAL__SHIFT 0x00000003
+#define MC_HUB_WDP_CNTL__LCLWRREQ_BYPASS_MASK 0x00020000L
+#define MC_HUB_WDP_CNTL__LCLWRREQ_BYPASS__SHIFT 0x00000011
+#define MC_HUB_WDP_CNTL__MCD_WAIT_EOP_MASK 0x00080000L
+#define MC_HUB_WDP_CNTL__MCD_WAIT_EOP__SHIFT 0x00000013
+#define MC_HUB_WDP_CNTL__OVERRIDE_STALL_ENABLE_MASK 0x00000010L
+#define MC_HUB_WDP_CNTL__OVERRIDE_STALL_ENABLE__SHIFT 0x00000004
+#define MC_HUB_WDP_CNTL__SIP_WAIT_EOP_MASK 0x00100000L
+#define MC_HUB_WDP_CNTL__SIP_WAIT_EOP__SHIFT 0x00000014
+#define MC_HUB_WDP_CREDITS__STOR0_MASK 0x00ff0000L
+#define MC_HUB_WDP_CREDITS__STOR0__SHIFT 0x00000010
+#define MC_HUB_WDP_CREDITS__STOR1_MASK 0xff000000L
+#define MC_HUB_WDP_CREDITS__STOR1__SHIFT 0x00000018
+#define MC_HUB_WDP_CREDITS__VM0_MASK 0x000000ffL
+#define MC_HUB_WDP_CREDITS__VM0__SHIFT 0x00000000
+#define MC_HUB_WDP_CREDITS__VM1_MASK 0x0000ff00L
+#define MC_HUB_WDP_CREDITS__VM1__SHIFT 0x00000008
+#define MC_HUB_WDP_ERR__MGPU1_TARG_SYS_MASK 0x00000001L
+#define MC_HUB_WDP_ERR__MGPU1_TARG_SYS__SHIFT 0x00000000
+#define MC_HUB_WDP_ERR__MGPU2_TARG_SYS_MASK 0x00000002L
+#define MC_HUB_WDP_ERR__MGPU2_TARG_SYS__SHIFT 0x00000001
+#define MC_HUB_WDP_GBL0__LAZY_TIMER_MASK 0x000000f0L
+#define MC_HUB_WDP_GBL0__LAZY_TIMER__SHIFT 0x00000004
+#define MC_HUB_WDP_GBL0__MAXBURST_MASK 0x0000000fL
+#define MC_HUB_WDP_GBL0__MAXBURST__SHIFT 0x00000000
+#define MC_HUB_WDP_GBL0__STALL_MODE_MASK 0x00010000L
+#define MC_HUB_WDP_GBL0__STALL_MODE__SHIFT 0x00000010
+#define MC_HUB_WDP_GBL0__STALL_THRESHOLD_MASK 0x0000ff00L
+#define MC_HUB_WDP_GBL0__STALL_THRESHOLD__SHIFT 0x00000008
+#define MC_HUB_WDP_GBL1__LAZY_TIMER_MASK 0x000000f0L
+#define MC_HUB_WDP_GBL1__LAZY_TIMER__SHIFT 0x00000004
+#define MC_HUB_WDP_GBL1__MAXBURST_MASK 0x0000000fL
+#define MC_HUB_WDP_GBL1__MAXBURST__SHIFT 0x00000000
+#define MC_HUB_WDP_GBL1__STALL_MODE_MASK 0x00010000L
+#define MC_HUB_WDP_GBL1__STALL_MODE__SHIFT 0x00000010
+#define MC_HUB_WDP_GBL1__STALL_THRESHOLD_MASK 0x0000ff00L
+#define MC_HUB_WDP_GBL1__STALL_THRESHOLD__SHIFT 0x00000008
+#define MC_HUB_WDP_HDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_HDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_HDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_HDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_HDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_HDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_HDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_HDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_HDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_HDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_HDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_HDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_IH__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_IH__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_IH__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_IH__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_IH__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_IH__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_IH__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_IH__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_IH__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_IH__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_IH__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_IH__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_IH__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDW__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDW__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDW__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDW__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDW__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDW__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDW__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDW__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDW__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDW__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDW__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDW__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDW__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDX__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDX__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDX__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDX__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDX__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDX__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDX__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDX__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDX__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDX__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDX__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDX__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDX__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDY__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDY__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDY__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDY__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDY__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDY__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDY__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDY__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDY__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDY__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDY__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDY__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDY__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDZ__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDZ__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDZ__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDZ__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDZ__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDZ__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDZ__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDZ__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDZ__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDZ__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDZ__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDZ__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_MCIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_MCIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_MCIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_MCIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_MCIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_MCIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_MCIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_MCIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_MCIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_MGPU2__CID2_MASK 0x000000ffL
+#define MC_HUB_WDP_MGPU2__CID2__SHIFT 0x00000000
+#define MC_HUB_WDP_MGPU__CID_MASK 0x0000ff00L
+#define MC_HUB_WDP_MGPU__CID__SHIFT 0x00000008
+#define MC_HUB_WDP_MGPU__ENABLE_MASK 0x00800000L
+#define MC_HUB_WDP_MGPU__ENABLE__SHIFT 0x00000017
+#define MC_HUB_WDP_MGPU__MGPU_PRIORITY_TIME_MASK 0x007f0000L
+#define MC_HUB_WDP_MGPU__MGPU_PRIORITY_TIME__SHIFT 0x00000010
+#define MC_HUB_WDP_MGPU__OTH_PRIORITY_TIME_MASK 0x7f000000L
+#define MC_HUB_WDP_MGPU__OTH_PRIORITY_TIME__SHIFT 0x00000018
+#define MC_HUB_WDP_MGPU__STOR_MASK 0x000000ffL
+#define MC_HUB_WDP_MGPU__STOR__SHIFT 0x00000000
+#define MC_HUB_WDP_RLC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_RLC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_RLC__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_RLC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_RLC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_RLC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_RLC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_RLC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_RLC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_RLC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_RLC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_RLC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SEM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SEM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SEM__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SEM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SEM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SEM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SEM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SEM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SEM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SEM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SEM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SEM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SH0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SH0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SH0__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SH0__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SH0__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SH0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SH0__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SH0__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SH0__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SH0__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SH0__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SH0__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SH1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SH1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SH1__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SH1__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SH1__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SH1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SH1__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SH1__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SH1__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SH1__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SH1__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SH1__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SIP__ASK_CREDITS_MASK 0x000001fcL
+#define MC_HUB_WDP_SIP__ASK_CREDITS__SHIFT 0x00000002
+#define MC_HUB_WDP_SIP__STALL_MODE_MASK 0x00000003L
+#define MC_HUB_WDP_SIP__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WDP_SMU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SMU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SMU__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SMU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SMU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SMU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SMU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SMU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SMU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SMU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SMU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SMU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_STATUS__GBL0_BYPASS_STOR_FULL_MASK 0x00000080L
+#define MC_HUB_WDP_STATUS__GBL0_BYPASS_STOR_FULL__SHIFT 0x00000007
+#define MC_HUB_WDP_STATUS__GBL0_STOR_FULL_MASK 0x00000040L
+#define MC_HUB_WDP_STATUS__GBL0_STOR_FULL__SHIFT 0x00000006
+#define MC_HUB_WDP_STATUS__GBL0_VM_FULL_MASK 0x00000020L
+#define MC_HUB_WDP_STATUS__GBL0_VM_FULL__SHIFT 0x00000005
+#define MC_HUB_WDP_STATUS__GBL1_BYPASS_STOR_FULL_MASK 0x00000400L
+#define MC_HUB_WDP_STATUS__GBL1_BYPASS_STOR_FULL__SHIFT 0x0000000a
+#define MC_HUB_WDP_STATUS__GBL1_STOR_FULL_MASK 0x00000200L
+#define MC_HUB_WDP_STATUS__GBL1_STOR_FULL__SHIFT 0x00000009
+#define MC_HUB_WDP_STATUS__GBL1_VM_FULL_MASK 0x00000100L
+#define MC_HUB_WDP_STATUS__GBL1_VM_FULL__SHIFT 0x00000008
+#define MC_HUB_WDP_STATUS__MCDW_RD_AVAIL_MASK 0x00000002L
+#define MC_HUB_WDP_STATUS__MCDW_RD_AVAIL__SHIFT 0x00000001
+#define MC_HUB_WDP_STATUS__MCDW_WR_AVAIL_MASK 0x00000800L
+#define MC_HUB_WDP_STATUS__MCDW_WR_AVAIL__SHIFT 0x0000000b
+#define MC_HUB_WDP_STATUS__MCDX_RD_AVAIL_MASK 0x00000004L
+#define MC_HUB_WDP_STATUS__MCDX_RD_AVAIL__SHIFT 0x00000002
+#define MC_HUB_WDP_STATUS__MCDX_WR_AVAIL_MASK 0x00001000L
+#define MC_HUB_WDP_STATUS__MCDX_WR_AVAIL__SHIFT 0x0000000c
+#define MC_HUB_WDP_STATUS__MCDY_RD_AVAIL_MASK 0x00000008L
+#define MC_HUB_WDP_STATUS__MCDY_RD_AVAIL__SHIFT 0x00000003
+#define MC_HUB_WDP_STATUS__MCDY_WR_AVAIL_MASK 0x00002000L
+#define MC_HUB_WDP_STATUS__MCDY_WR_AVAIL__SHIFT 0x0000000d
+#define MC_HUB_WDP_STATUS__MCDZ_RD_AVAIL_MASK 0x00000010L
+#define MC_HUB_WDP_STATUS__MCDZ_RD_AVAIL__SHIFT 0x00000004
+#define MC_HUB_WDP_STATUS__MCDZ_WR_AVAIL_MASK 0x00004000L
+#define MC_HUB_WDP_STATUS__MCDZ_WR_AVAIL__SHIFT 0x0000000e
+#define MC_HUB_WDP_STATUS__SIP_AVAIL_MASK 0x00000001L
+#define MC_HUB_WDP_STATUS__SIP_AVAIL__SHIFT 0x00000000
+#define MC_HUB_WDP_UMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_UMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_UMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_UMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_UMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_UMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_UMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_UMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_UMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_UMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_UMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_UMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_UVD__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_UVD__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_UVD__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_UVD__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_UVD__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_UVD__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_UVD__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_UVD__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_UVD__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_UVD__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_UVD__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_UVD__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_UVD__VM_BYPASS_MASK 0x00010000L
+#define MC_HUB_WDP_UVD__VM_BYPASS__SHIFT 0x00000010
+#define MC_HUB_WDP_VCE__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_VCE__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_VCE__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_VCE__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_VCE__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_VCE__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_VCE__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_VCE__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_VCE__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_VCE__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_VCE__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_VCE__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_VCEU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_VCEU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_VCEU__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_VCEU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_VCEU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_VCEU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_VCEU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_VCEU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_VCEU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_VCEU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_VCEU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_VCEU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_WTM_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_HUB_WDP_WTM_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_HUB_WDP_WTM_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_HUB_WDP_WTM_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_HUB_WDP_WTM_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_HUB_WDP_WTM_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_HUB_WDP_WTM_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_HUB_WDP_WTM_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_HUB_WDP_WTM_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_HUB_WDP_WTM_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_HUB_WDP_WTM_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_HUB_WDP_WTM_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_HUB_WDP_XDMA__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDMA__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDMA__BYPASS_AVAIL_OVERRIDE_MASK 0x00010000L
+#define MC_HUB_WDP_XDMA__BYPASS_AVAIL_OVERRIDE__SHIFT 0x00000010
+#define MC_HUB_WDP_XDMA__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDMA__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDMA__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDMA__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDMA__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDMA__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDMAM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDMAM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDMAM__BYPASS_AVAIL_OVERRIDE_MASK 0x00010000L
+#define MC_HUB_WDP_XDMAM__BYPASS_AVAIL_OVERRIDE__SHIFT 0x00000010
+#define MC_HUB_WDP_XDMAM__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDMAM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDMAM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDMAM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDMAM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDMAM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDMAM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDMAM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDMAM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDMAM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_XDMA__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDMA__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDMA__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDMA__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_XDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WRRET_CNTL__BP_ENABLE_MASK 0x00200000L
+#define MC_HUB_WRRET_CNTL__BP_ENABLE__SHIFT 0x00000015
+#define MC_HUB_WRRET_CNTL__BP_MASK 0x001ffffeL
+#define MC_HUB_WRRET_CNTL__BP__SHIFT 0x00000001
+#define MC_HUB_WRRET_CNTL__DEBUG_REG_MASK 0x3fc00000L
+#define MC_HUB_WRRET_CNTL__DEBUG_REG__SHIFT 0x00000016
+#define MC_HUB_WRRET_CNTL__DISABLE_SELF_INIT_MASK 0x40000000L
+#define MC_HUB_WRRET_CNTL__DISABLE_SELF_INIT__SHIFT 0x0000001e
+#define MC_HUB_WRRET_CNTL__FAIR_CH_SW_MASK 0x80000000L
+#define MC_HUB_WRRET_CNTL__FAIR_CH_SW__SHIFT 0x0000001f
+#define MC_HUB_WRRET_CNTL__JUMPAHEAD_MASK 0x00000001L
+#define MC_HUB_WRRET_CNTL__JUMPAHEAD__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDW__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDW__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDW__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDW__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDX__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDX__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDX__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDX__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDY__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDY__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDY__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDY__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDZ__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDZ__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDZ__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDZ__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_STATUS__MCDW_AVAIL_MASK 0x00000001L
+#define MC_HUB_WRRET_STATUS__MCDW_AVAIL__SHIFT 0x00000000
+#define MC_HUB_WRRET_STATUS__MCDX_AVAIL_MASK 0x00000002L
+#define MC_HUB_WRRET_STATUS__MCDX_AVAIL__SHIFT 0x00000001
+#define MC_HUB_WRRET_STATUS__MCDY_AVAIL_MASK 0x00000004L
+#define MC_HUB_WRRET_STATUS__MCDY_AVAIL__SHIFT 0x00000002
+#define MC_HUB_WRRET_STATUS__MCDZ_AVAIL_MASK 0x00000008L
+#define MC_HUB_WRRET_STATUS__MCDZ_AVAIL__SHIFT 0x00000003
+#define MC_IMP_CNTL__CAL_PWRON_MASK 0x80000000L
+#define MC_IMP_CNTL__CAL_PWRON__SHIFT 0x0000001f
+#define MC_IMP_CNTL__CAL_VREF_MASK 0x007f0000L
+#define MC_IMP_CNTL__CAL_VREFMODE_MASK 0x00000040L
+#define MC_IMP_CNTL__CAL_VREFMODE__SHIFT 0x00000006
+#define MC_IMP_CNTL__CAL_VREF_SEL_MASK 0x00000020L
+#define MC_IMP_CNTL__CAL_VREF_SEL__SHIFT 0x00000005
+#define MC_IMP_CNTL__CAL_VREF__SHIFT 0x00000010
+#define MC_IMP_CNTL__CAL_WHEN_IDLE_MASK 0x20000000L
+#define MC_IMP_CNTL__CAL_WHEN_IDLE__SHIFT 0x0000001d
+#define MC_IMP_CNTL__CAL_WHEN_REFRESH_MASK 0x40000000L
+#define MC_IMP_CNTL__CAL_WHEN_REFRESH__SHIFT 0x0000001e
+#define MC_IMP_CNTL__CLEAR_TIMEOUT_ERR_MASK 0x00000200L
+#define MC_IMP_CNTL__CLEAR_TIMEOUT_ERR__SHIFT 0x00000009
+#define MC_IMP_CNTL__MEM_IO_SAMPLE_CNT_MASK 0x0000e000L
+#define MC_IMP_CNTL__MEM_IO_SAMPLE_CNT__SHIFT 0x0000000d
+#define MC_IMP_CNTL__MEM_IO_UPDATE_RATE_MASK 0x0000001fL
+#define MC_IMP_CNTL__MEM_IO_UPDATE_RATE__SHIFT 0x00000000
+#define MC_IMP_CNTL__TIMEOUT_ERR_MASK 0x00000100L
+#define MC_IMP_CNTL__TIMEOUT_ERR__SHIFT 0x00000008
+#define MC_IMP_DEBUG__DEBUG_CAL_DONE_MASK 0x80000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_DONE__SHIFT 0x0000001f
+#define MC_IMP_DEBUG__DEBUG_CAL_EN_MASK 0x10000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_EN__SHIFT 0x0000001c
+#define MC_IMP_DEBUG__DEBUG_CAL_INTR_MASK 0x40000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_INTR__SHIFT 0x0000001e
+#define MC_IMP_DEBUG__DEBUG_CAL_START_MASK 0x20000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_START__SHIFT 0x0000001d
+#define MC_IMP_DEBUG__PMVCAL_RESERVED_MASK 0x0fff0000L
+#define MC_IMP_DEBUG__PMVCAL_RESERVED__SHIFT 0x00000010
+#define MC_IMP_DEBUG__TIMEOUT_CNTR_MASK 0x0000ff00L
+#define MC_IMP_DEBUG__TIMEOUT_CNTR__SHIFT 0x00000008
+#define MC_IMP_DEBUG__TSTARTUP_CNTR_MASK 0x000000ffL
+#define MC_IMP_DEBUG__TSTARTUP_CNTR__SHIFT 0x00000000
+#define MC_IMP_DQ_STATUS__CH0_DQ_NSTR_MASK 0x0000ff00L
+#define MC_IMP_DQ_STATUS__CH0_DQ_NSTR__SHIFT 0x00000008
+#define MC_IMP_DQ_STATUS__CH0_DQ_PSTR_MASK 0x000000ffL
+#define MC_IMP_DQ_STATUS__CH0_DQ_PSTR__SHIFT 0x00000000
+#define MC_IMP_DQ_STATUS__CH1_DQ_NSTR_MASK 0xff000000L
+#define MC_IMP_DQ_STATUS__CH1_DQ_NSTR__SHIFT 0x00000018
+#define MC_IMP_DQ_STATUS__CH1_DQ_PSTR_MASK 0x00ff0000L
+#define MC_IMP_DQ_STATUS__CH1_DQ_PSTR__SHIFT 0x00000010
+#define MC_IMP_STATUS__NSTR_ACCUM_VAL_MASK 0xff000000L
+#define MC_IMP_STATUS__NSTR_ACCUM_VAL__SHIFT 0x00000018
+#define MC_IMP_STATUS__NSTR_CAL_MASK 0x00ff0000L
+#define MC_IMP_STATUS__NSTR_CAL__SHIFT 0x00000010
+#define MC_IMP_STATUS__PSTR_ACCUM_VAL_MASK 0x0000ff00L
+#define MC_IMP_STATUS__PSTR_ACCUM_VAL__SHIFT 0x00000008
+#define MC_IMP_STATUS__PSTR_CAL_MASK 0x000000ffL
+#define MC_IMP_STATUS__PSTR_CAL__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D0__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_APHY_STR_CNTL_D0__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_A_STR_MASK 0x10000000L
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_A_STR__SHIFT 0x0000001c
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_D_RD_STR_MASK 0x20000000L
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_D_RD_STR__SHIFT 0x0000001d
+#define MC_IO_APHY_STR_CNTL_D0__NSTR_OFF_A_MASK 0x00000fc0L
+#define MC_IO_APHY_STR_CNTL_D0__NSTR_OFF_A__SHIFT 0x00000006
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_A_MASK 0x0000003fL
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_A__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_D_RD_MASK 0x0003f000L
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_D_RD__SHIFT 0x0000000c
+#define MC_IO_APHY_STR_CNTL_D0__USE_A_CAL_MASK 0x01000000L
+#define MC_IO_APHY_STR_CNTL_D0__USE_A_CAL__SHIFT 0x00000018
+#define MC_IO_APHY_STR_CNTL_D0__USE_D_RD_CAL_MASK 0x02000000L
+#define MC_IO_APHY_STR_CNTL_D0__USE_D_RD_CAL__SHIFT 0x00000019
+#define MC_IO_APHY_STR_CNTL_D1__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_APHY_STR_CNTL_D1__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_A_STR_MASK 0x10000000L
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_A_STR__SHIFT 0x0000001c
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_D_RD_STR_MASK 0x20000000L
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_D_RD_STR__SHIFT 0x0000001d
+#define MC_IO_APHY_STR_CNTL_D1__NSTR_OFF_A_MASK 0x00000fc0L
+#define MC_IO_APHY_STR_CNTL_D1__NSTR_OFF_A__SHIFT 0x00000006
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_A_MASK 0x0000003fL
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_A__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_D_RD_MASK 0x0003f000L
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_D_RD__SHIFT 0x0000000c
+#define MC_IO_APHY_STR_CNTL_D1__USE_A_CAL_MASK 0x01000000L
+#define MC_IO_APHY_STR_CNTL_D1__USE_A_CAL__SHIFT 0x00000018
+#define MC_IO_APHY_STR_CNTL_D1__USE_D_RD_CAL_MASK 0x02000000L
+#define MC_IO_APHY_STR_CNTL_D1__USE_D_RD_CAL__SHIFT 0x00000019
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B0_MASK 0x000000ffL
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B1_MASK 0x0000ff00L
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B1__SHIFT 0x00000008
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B0_MASK 0x00ff0000L
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B0__SHIFT 0x00000010
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B1_MASK 0xff000000L
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B1__SHIFT 0x00000018
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B0_MASK 0x000000ffL
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B1_MASK 0x0000ff00L
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B1__SHIFT 0x00000008
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B0_MASK 0x00ff0000L
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B0__SHIFT 0x00000010
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B1_MASK 0xff000000L
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B1__SHIFT 0x00000018
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL0_MASK 0x00000001L
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL1_MASK 0x00000002L
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL1__SHIFT 0x00000001
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR0_MASK 0x00000004L
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR0__SHIFT 0x00000002
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR1_MASK 0x00000008L
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR1__SHIFT 0x00000003
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS0_MASK 0x00000010L
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS0__SHIFT 0x00000004
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS1_MASK 0x00000020L
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS1__SHIFT 0x00000005
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR0_MASK 0x00000040L
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR0__SHIFT 0x00000006
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR1_MASK 0x00000080L
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR1__SHIFT 0x00000007
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL0_MASK 0x00000001L
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL1_MASK 0x00000002L
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL1__SHIFT 0x00000001
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR0_MASK 0x00000004L
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR0__SHIFT 0x00000002
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR1_MASK 0x00000008L
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR1__SHIFT 0x00000003
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS0_MASK 0x00000010L
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS0__SHIFT 0x00000004
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS1_MASK 0x00000020L
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS1__SHIFT 0x00000005
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR0_MASK 0x00000040L
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR0__SHIFT 0x00000006
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR1_MASK 0x00000080L
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR1__SHIFT 0x00000007
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B0_MASK 0x00400000L
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B0__SHIFT 0x00000016
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B1_MASK 0x00800000L
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B1__SHIFT 0x00000017
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B0_MASK 0x10000000L
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B0__SHIFT 0x0000001c
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B1_MASK 0x20000000L
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B1__SHIFT 0x0000001d
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B0_MASK 0x00100000L
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B0__SHIFT 0x00000014
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B1_MASK 0x00200000L
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B1__SHIFT 0x00000015
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B0_MASK 0x40000000L
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B0__SHIFT 0x0000001e
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B1_MASK 0x80000000L
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B1__SHIFT 0x0000001f
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B01_MASK 0x00000400L
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B01__SHIFT 0x0000000a
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B23_MASK 0x00000800L
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B23__SHIFT 0x0000000b
+#define MC_IO_CDRCNTL_D0__RXCDREN_B01_MASK 0x00000100L
+#define MC_IO_CDRCNTL_D0__RXCDREN_B01__SHIFT 0x00000008
+#define MC_IO_CDRCNTL_D0__RXCDREN_B23_MASK 0x00000200L
+#define MC_IO_CDRCNTL_D0__RXCDREN_B23__SHIFT 0x00000009
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B01_MASK 0x0000f000L
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B01__SHIFT 0x0000000c
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B23_MASK 0x000f0000L
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B23__SHIFT 0x00000010
+#define MC_IO_CDRCNTL_D0__RXPHASE_B01_MASK 0x0000000fL
+#define MC_IO_CDRCNTL_D0__RXPHASE_B01__SHIFT 0x00000000
+#define MC_IO_CDRCNTL_D0__RXPHASE_B23_MASK 0x000000f0L
+#define MC_IO_CDRCNTL_D0__RXPHASE_B23__SHIFT 0x00000004
+#define MC_IO_CDRCNTL_D0__WCDREDC_B0_MASK 0x04000000L
+#define MC_IO_CDRCNTL_D0__WCDREDC_B0__SHIFT 0x0000001a
+#define MC_IO_CDRCNTL_D0__WCDREDC_B1_MASK 0x08000000L
+#define MC_IO_CDRCNTL_D0__WCDREDC_B1__SHIFT 0x0000001b
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B0_MASK 0x01000000L
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B0__SHIFT 0x00000018
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B1_MASK 0x02000000L
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B1__SHIFT 0x00000019
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B0_MASK 0x00400000L
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B0__SHIFT 0x00000016
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B1_MASK 0x00800000L
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B1__SHIFT 0x00000017
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B0_MASK 0x10000000L
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B0__SHIFT 0x0000001c
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B1_MASK 0x20000000L
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B1__SHIFT 0x0000001d
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B0_MASK 0x00100000L
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B0__SHIFT 0x00000014
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B1_MASK 0x00200000L
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B1__SHIFT 0x00000015
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B0_MASK 0x40000000L
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B0__SHIFT 0x0000001e
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B1_MASK 0x80000000L
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B1__SHIFT 0x0000001f
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B01_MASK 0x00000400L
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B01__SHIFT 0x0000000a
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B23_MASK 0x00000800L
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B23__SHIFT 0x0000000b
+#define MC_IO_CDRCNTL_D1__RXCDREN_B01_MASK 0x00000100L
+#define MC_IO_CDRCNTL_D1__RXCDREN_B01__SHIFT 0x00000008
+#define MC_IO_CDRCNTL_D1__RXCDREN_B23_MASK 0x00000200L
+#define MC_IO_CDRCNTL_D1__RXCDREN_B23__SHIFT 0x00000009
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B01_MASK 0x0000f000L
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B01__SHIFT 0x0000000c
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B23_MASK 0x000f0000L
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B23__SHIFT 0x00000010
+#define MC_IO_CDRCNTL_D1__RXPHASE_B01_MASK 0x0000000fL
+#define MC_IO_CDRCNTL_D1__RXPHASE_B01__SHIFT 0x00000000
+#define MC_IO_CDRCNTL_D1__RXPHASE_B23_MASK 0x000000f0L
+#define MC_IO_CDRCNTL_D1__RXPHASE_B23__SHIFT 0x00000004
+#define MC_IO_CDRCNTL_D1__WCDREDC_B0_MASK 0x04000000L
+#define MC_IO_CDRCNTL_D1__WCDREDC_B0__SHIFT 0x0000001a
+#define MC_IO_CDRCNTL_D1__WCDREDC_B1_MASK 0x08000000L
+#define MC_IO_CDRCNTL_D1__WCDREDC_B1__SHIFT 0x0000001b
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B0_MASK 0x01000000L
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B0__SHIFT 0x00000018
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B1_MASK 0x02000000L
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B1__SHIFT 0x00000019
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_100__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_100__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_100__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_100__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_100__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_100__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_100__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_100__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_101__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_101__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_101__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_101__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_101__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_101__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_101__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_101__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_102__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_102__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_102__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_102__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_102__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_102__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_102__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_102__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_103__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_103__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_103__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_103__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_103__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_103__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_103__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_103__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_104__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_104__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_104__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_104__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_104__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_104__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_104__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_104__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_105__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_105__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_105__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_105__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_105__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_105__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_105__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_105__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_106__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_106__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_106__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_106__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_106__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_106__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_106__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_106__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_107__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_107__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_107__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_107__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_107__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_107__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_107__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_107__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_108__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_108__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_108__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_108__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_108__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_108__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_108__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_108__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_109__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_109__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_109__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_109__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_109__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_109__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_109__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_109__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_10__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_10__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_10__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_10__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_10__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_10__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_10__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_10__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_110__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_110__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_110__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_110__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_110__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_110__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_110__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_110__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_111__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_111__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_111__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_111__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_111__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_111__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_111__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_111__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_112__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_112__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_112__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_112__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_112__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_112__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_112__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_112__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_113__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_113__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_113__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_113__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_113__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_113__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_113__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_113__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_114__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_114__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_114__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_114__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_114__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_114__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_114__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_114__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_115__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_115__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_115__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_115__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_115__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_115__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_115__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_115__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_116__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_116__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_116__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_116__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_116__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_116__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_116__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_116__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_117__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_117__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_117__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_117__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_117__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_117__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_117__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_117__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_118__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_118__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_118__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_118__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_118__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_118__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_118__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_118__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_119__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_119__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_119__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_119__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_119__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_119__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_119__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_119__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_11__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_11__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_11__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_11__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_11__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_11__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_11__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_11__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_120__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_120__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_120__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_120__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_120__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_120__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_120__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_120__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_121__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_121__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_121__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_121__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_121__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_121__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_121__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_121__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_122__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_122__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_122__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_122__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_122__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_122__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_122__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_122__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_123__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_123__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_123__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_123__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_123__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_123__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_123__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_123__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_124__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_124__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_124__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_124__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_124__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_124__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_124__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_124__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_125__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_125__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_125__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_125__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_125__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_125__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_125__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_125__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_126__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_126__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_126__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_126__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_126__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_126__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_126__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_126__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_127__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_127__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_127__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_127__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_127__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_127__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_127__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_127__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_128__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_128__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_128__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_128__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_128__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_128__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_128__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_128__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_129__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_129__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_129__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_129__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_129__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_129__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_129__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_129__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_12__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_12__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_12__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_12__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_12__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_12__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_12__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_12__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_130__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_130__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_130__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_130__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_130__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_130__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_130__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_130__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_131__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_131__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_131__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_131__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_131__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_131__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_131__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_131__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_132__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_132__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_132__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_132__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_132__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_132__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_132__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_132__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_133__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_133__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_133__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_133__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_133__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_133__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_133__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_133__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_134__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_134__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_134__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_134__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_134__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_134__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_134__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_134__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_135__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_135__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_135__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_135__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_135__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_135__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_135__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_135__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_136__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_136__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_136__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_136__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_136__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_136__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_136__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_136__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_137__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_137__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_137__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_137__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_137__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_137__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_137__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_137__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_138__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_138__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_138__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_138__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_138__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_138__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_138__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_138__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_139__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_139__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_139__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_139__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_139__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_139__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_139__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_139__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_13__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_13__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_13__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_13__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_13__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_13__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_13__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_13__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_140__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_140__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_140__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_140__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_140__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_140__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_140__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_140__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_141__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_141__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_141__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_141__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_141__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_141__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_141__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_141__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_142__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_142__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_142__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_142__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_142__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_142__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_142__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_142__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_143__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_143__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_143__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_143__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_143__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_143__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_143__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_143__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_144__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_144__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_144__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_144__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_144__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_144__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_144__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_144__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_145__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_145__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_145__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_145__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_145__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_145__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_145__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_145__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_146__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_146__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_146__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_146__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_146__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_146__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_146__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_146__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_147__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_147__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_147__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_147__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_147__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_147__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_147__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_147__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_148__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_148__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_148__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_148__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_148__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_148__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_148__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_148__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_149__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_149__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_149__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_149__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_149__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_149__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_149__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_149__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_14__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_14__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_14__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_14__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_14__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_14__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_14__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_14__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_150__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_150__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_150__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_150__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_150__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_150__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_150__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_150__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_151__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_151__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_151__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_151__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_151__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_151__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_151__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_151__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_152__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_152__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_152__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_152__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_152__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_152__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_152__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_152__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_153__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_153__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_153__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_153__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_153__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_153__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_153__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_153__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_154__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_154__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_154__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_154__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_154__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_154__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_154__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_154__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_155__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_155__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_155__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_155__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_155__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_155__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_155__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_155__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_156__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_156__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_156__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_156__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_156__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_156__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_156__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_156__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_157__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_157__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_157__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_157__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_157__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_157__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_157__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_157__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_158__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_158__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_158__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_158__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_158__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_158__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_158__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_158__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_159__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_159__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_159__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_159__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_159__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_159__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_159__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_159__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_15__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_15__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_15__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_15__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_15__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_15__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_15__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_15__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_16__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_16__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_16__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_16__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_16__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_16__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_16__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_16__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_17__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_17__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_17__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_17__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_17__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_17__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_17__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_17__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_18__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_18__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_18__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_18__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_18__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_18__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_18__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_18__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_19__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_19__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_19__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_19__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_19__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_19__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_19__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_19__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_20__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_20__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_20__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_20__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_20__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_20__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_20__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_20__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_21__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_21__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_21__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_21__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_21__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_21__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_21__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_21__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_22__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_22__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_22__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_22__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_22__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_22__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_22__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_22__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_23__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_23__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_23__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_23__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_23__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_23__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_23__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_23__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_24__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_24__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_24__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_24__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_24__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_24__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_24__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_24__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_25__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_25__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_25__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_25__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_25__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_25__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_25__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_25__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_26__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_26__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_26__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_26__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_26__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_26__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_26__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_26__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_27__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_27__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_27__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_27__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_27__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_27__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_27__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_27__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_28__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_28__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_28__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_28__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_28__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_28__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_28__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_28__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_29__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_29__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_29__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_29__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_29__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_29__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_29__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_29__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_2__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_2__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_2__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_2__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_2__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_2__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_2__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_2__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_30__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_30__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_30__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_30__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_30__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_30__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_30__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_30__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_31__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_31__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_31__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_31__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_31__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_31__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_31__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_31__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_32__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_32__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_32__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_32__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_32__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_32__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_32__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_32__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_33__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_33__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_33__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_33__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_33__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_33__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_33__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_33__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_34__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_34__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_34__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_34__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_34__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_34__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_34__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_34__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_35__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_35__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_35__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_35__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_35__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_35__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_35__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_35__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_36__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_36__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_36__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_36__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_36__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_36__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_36__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_36__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_37__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_37__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_37__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_37__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_37__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_37__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_37__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_37__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_38__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_38__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_38__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_38__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_38__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_38__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_38__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_38__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_39__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_39__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_39__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_39__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_39__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_39__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_39__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_39__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_3__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_3__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_3__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_3__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_3__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_3__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_3__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_3__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_40__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_40__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_40__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_40__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_40__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_40__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_40__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_40__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_41__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_41__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_41__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_41__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_41__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_41__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_41__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_41__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_42__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_42__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_42__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_42__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_42__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_42__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_42__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_42__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_43__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_43__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_43__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_43__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_43__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_43__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_43__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_43__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_44__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_44__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_44__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_44__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_44__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_44__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_44__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_44__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_45__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_45__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_45__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_45__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_45__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_45__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_45__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_45__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_46__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_46__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_46__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_46__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_46__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_46__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_46__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_46__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_47__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_47__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_47__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_47__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_47__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_47__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_47__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_47__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_48__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_48__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_48__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_48__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_48__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_48__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_48__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_48__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_49__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_49__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_49__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_49__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_49__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_49__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_49__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_49__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_4__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_4__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_4__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_4__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_4__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_4__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_4__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_4__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_50__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_50__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_50__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_50__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_50__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_50__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_50__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_50__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_51__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_51__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_51__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_51__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_51__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_51__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_51__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_51__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_52__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_52__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_52__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_52__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_52__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_52__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_52__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_52__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_53__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_53__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_53__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_53__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_53__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_53__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_53__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_53__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_54__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_54__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_54__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_54__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_54__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_54__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_54__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_54__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_55__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_55__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_55__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_55__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_55__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_55__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_55__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_55__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_56__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_56__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_56__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_56__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_56__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_56__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_56__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_56__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_57__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_57__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_57__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_57__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_57__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_57__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_57__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_57__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_58__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_58__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_58__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_58__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_58__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_58__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_58__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_58__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_59__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_59__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_59__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_59__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_59__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_59__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_59__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_59__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_5__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_5__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_5__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_5__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_5__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_5__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_5__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_5__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_60__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_60__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_60__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_60__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_60__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_60__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_60__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_60__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_61__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_61__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_61__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_61__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_61__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_61__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_61__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_61__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_62__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_62__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_62__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_62__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_62__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_62__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_62__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_62__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_63__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_63__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_63__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_63__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_63__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_63__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_63__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_63__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_64__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_64__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_64__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_64__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_64__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_64__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_64__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_64__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_65__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_65__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_65__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_65__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_65__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_65__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_65__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_65__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_66__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_66__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_66__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_66__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_66__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_66__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_66__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_66__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_67__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_67__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_67__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_67__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_67__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_67__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_67__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_67__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_68__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_68__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_68__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_68__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_68__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_68__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_68__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_68__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_69__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_69__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_69__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_69__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_69__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_69__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_69__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_69__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_6__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_6__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_6__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_6__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_6__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_6__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_6__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_6__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_70__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_70__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_70__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_70__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_70__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_70__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_70__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_70__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_71__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_71__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_71__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_71__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_71__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_71__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_71__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_71__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_72__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_72__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_72__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_72__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_72__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_72__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_72__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_72__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_73__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_73__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_73__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_73__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_73__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_73__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_73__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_73__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_74__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_74__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_74__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_74__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_74__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_74__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_74__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_74__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_75__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_75__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_75__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_75__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_75__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_75__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_75__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_75__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_76__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_76__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_76__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_76__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_76__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_76__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_76__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_76__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_77__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_77__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_77__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_77__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_77__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_77__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_77__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_77__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_78__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_78__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_78__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_78__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_78__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_78__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_78__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_78__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_79__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_79__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_79__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_79__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_79__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_79__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_79__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_79__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_7__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_7__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_7__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_7__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_7__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_7__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_7__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_7__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_80__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_80__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_80__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_80__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_80__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_80__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_80__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_80__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_81__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_81__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_81__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_81__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_81__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_81__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_81__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_81__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_82__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_82__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_82__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_82__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_82__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_82__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_82__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_82__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_83__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_83__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_83__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_83__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_83__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_83__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_83__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_83__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_84__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_84__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_84__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_84__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_84__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_84__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_84__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_84__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_85__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_85__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_85__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_85__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_85__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_85__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_85__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_85__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_86__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_86__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_86__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_86__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_86__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_86__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_86__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_86__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_87__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_87__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_87__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_87__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_87__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_87__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_87__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_87__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_88__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_88__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_88__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_88__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_88__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_88__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_88__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_88__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_89__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_89__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_89__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_89__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_89__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_89__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_89__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_89__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_8__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_8__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_8__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_8__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_8__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_8__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_8__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_8__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_90__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_90__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_90__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_90__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_90__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_90__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_90__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_90__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_91__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_91__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_91__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_91__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_91__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_91__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_91__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_91__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_92__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_92__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_92__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_92__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_92__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_92__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_92__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_92__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_93__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_93__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_93__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_93__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_93__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_93__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_93__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_93__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_94__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_94__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_94__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_94__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_94__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_94__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_94__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_94__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_95__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_95__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_95__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_95__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_95__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_95__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_95__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_95__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_96__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_96__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_96__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_96__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_96__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_96__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_96__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_96__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_97__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_97__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_97__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_97__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_97__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_97__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_97__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_97__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_98__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_98__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_98__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_98__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_98__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_98__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_98__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_98__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_99__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_99__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_99__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_99__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_99__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_99__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_99__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_99__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_9__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_9__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_9__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_9__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_9__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_9__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_9__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_9__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D0__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_DPHY_STR_CNTL_D0__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_D_STR_MASK 0x10000000L
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_D_STR__SHIFT 0x0000001c
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_S_STR_MASK 0x20000000L
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_S_STR__SHIFT 0x0000001d
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_D_MASK 0x00000fc0L
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_D__SHIFT 0x00000006
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_S_MASK 0x00fc0000L
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_S__SHIFT 0x00000012
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_D_MASK 0x0000003fL
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_D__SHIFT 0x00000000
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_S_MASK 0x0003f000L
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_S__SHIFT 0x0000000c
+#define MC_IO_DPHY_STR_CNTL_D0__USE_D_CAL_MASK 0x01000000L
+#define MC_IO_DPHY_STR_CNTL_D0__USE_D_CAL__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D0__USE_S_CAL_MASK 0x02000000L
+#define MC_IO_DPHY_STR_CNTL_D0__USE_S_CAL__SHIFT 0x00000019
+#define MC_IO_DPHY_STR_CNTL_D1__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_DPHY_STR_CNTL_D1__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_D_STR_MASK 0x10000000L
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_D_STR__SHIFT 0x0000001c
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_S_STR_MASK 0x20000000L
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_S_STR__SHIFT 0x0000001d
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_D_MASK 0x00000fc0L
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_D__SHIFT 0x00000006
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_S_MASK 0x00fc0000L
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_S__SHIFT 0x00000012
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_D_MASK 0x0000003fL
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_D__SHIFT 0x00000000
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_S_MASK 0x0003f000L
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_S__SHIFT 0x0000000c
+#define MC_IO_DPHY_STR_CNTL_D1__USE_D_CAL_MASK 0x01000000L
+#define MC_IO_DPHY_STR_CNTL_D1__USE_D_CAL__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D1__USE_S_CAL_MASK 0x02000000L
+#define MC_IO_DPHY_STR_CNTL_D1__USE_S_CAL__SHIFT 0x00000019
+#define MC_IO_PAD_CNTL__ATBEN_MASK 0x3f000000L
+#define MC_IO_PAD_CNTL__ATBEN__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL__ATBSEL_D0_MASK 0x80000000L
+#define MC_IO_PAD_CNTL__ATBSEL_D0__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL__ATBSEL_D1_MASK 0x40000000L
+#define MC_IO_PAD_CNTL__ATBSEL_D1__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL__ATBSEL_MASK 0x00f00000L
+#define MC_IO_PAD_CNTL__ATBSEL__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D0__CK_AUTO_EN_MASK 0x00100000L
+#define MC_IO_PAD_CNTL_D0__CK_AUTO_EN__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_N_MASK 0x00c00000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_N__SHIFT 0x00000016
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_P_MASK 0x03000000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_P__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_SEL_MASK 0x00200000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_SEL__SHIFT 0x00000015
+#define MC_IO_PAD_CNTL_D0__DELAY_ADR_SYNC_MASK 0x00000010L
+#define MC_IO_PAD_CNTL_D0__DELAY_ADR_SYNC__SHIFT 0x00000004
+#define MC_IO_PAD_CNTL_D0__DELAY_CLK_SYNC_MASK 0x00000004L
+#define MC_IO_PAD_CNTL_D0__DELAY_CLK_SYNC__SHIFT 0x00000002
+#define MC_IO_PAD_CNTL_D0__DELAY_CMD_SYNC_MASK 0x00000008L
+#define MC_IO_PAD_CNTL_D0__DELAY_CMD_SYNC__SHIFT 0x00000003
+#define MC_IO_PAD_CNTL_D0__DIFF_STR_MASK 0x20000000L
+#define MC_IO_PAD_CNTL_D0__DIFF_STR__SHIFT 0x0000001d
+#define MC_IO_PAD_CNTL_D0__DISABLE_ADR_MASK 0x00002000L
+#define MC_IO_PAD_CNTL_D0__DISABLE_ADR__SHIFT 0x0000000d
+#define MC_IO_PAD_CNTL_D0__DISABLE_CMD_MASK 0x00001000L
+#define MC_IO_PAD_CNTL_D0__DISABLE_CMD__SHIFT 0x0000000c
+#define MC_IO_PAD_CNTL_D0__EN_RD_STR_DLY_MASK 0x00000800L
+#define MC_IO_PAD_CNTL_D0__EN_RD_STR_DLY__SHIFT 0x0000000b
+#define MC_IO_PAD_CNTL_D0__FORCE_EN_RD_STR_MASK 0x00000400L
+#define MC_IO_PAD_CNTL_D0__FORCE_EN_RD_STR__SHIFT 0x0000000a
+#define MC_IO_PAD_CNTL_D0__GDDR_PWRON_MASK 0x40000000L
+#define MC_IO_PAD_CNTL_D0__GDDR_PWRON__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_ADR_MASK 0x00000200L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_ADR__SHIFT 0x00000009
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CLK_MASK 0x00000080L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CLK__SHIFT 0x00000007
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CMD_MASK 0x00000100L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CMD__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CKE_MASK 0x08000000L
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CKE__SHIFT 0x0000001b
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CLK_MASK 0x80000000L
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CLK__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL_D0__UNI_STR_MASK 0x10000000L
+#define MC_IO_PAD_CNTL_D0__UNI_STR__SHIFT 0x0000001c
+#define MC_IO_PAD_CNTL_D0__VREFI_EN_MASK 0x00004000L
+#define MC_IO_PAD_CNTL_D0__VREFI_EN__SHIFT 0x0000000e
+#define MC_IO_PAD_CNTL_D0__VREFI_SEL_MASK 0x000f8000L
+#define MC_IO_PAD_CNTL_D0__VREFI_SEL__SHIFT 0x0000000f
+#define MC_IO_PAD_CNTL_D1__CK_AUTO_EN_MASK 0x00100000L
+#define MC_IO_PAD_CNTL_D1__CK_AUTO_EN__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_N_MASK 0x00c00000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_N__SHIFT 0x00000016
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_P_MASK 0x03000000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_P__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_SEL_MASK 0x00200000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_SEL__SHIFT 0x00000015
+#define MC_IO_PAD_CNTL_D1__DELAY_ADR_SYNC_MASK 0x00000010L
+#define MC_IO_PAD_CNTL_D1__DELAY_ADR_SYNC__SHIFT 0x00000004
+#define MC_IO_PAD_CNTL_D1__DELAY_CLK_SYNC_MASK 0x00000004L
+#define MC_IO_PAD_CNTL_D1__DELAY_CLK_SYNC__SHIFT 0x00000002
+#define MC_IO_PAD_CNTL_D1__DELAY_CMD_SYNC_MASK 0x00000008L
+#define MC_IO_PAD_CNTL_D1__DELAY_CMD_SYNC__SHIFT 0x00000003
+#define MC_IO_PAD_CNTL_D1__DELAY_DATA_SYNC_MASK 0x00000001L
+#define MC_IO_PAD_CNTL_D1__DELAY_DATA_SYNC__SHIFT 0x00000000
+#define MC_IO_PAD_CNTL_D1__DELAY_STR_SYNC_MASK 0x00000002L
+#define MC_IO_PAD_CNTL_D1__DELAY_STR_SYNC__SHIFT 0x00000001
+#define MC_IO_PAD_CNTL_D1__DIFF_STR_MASK 0x20000000L
+#define MC_IO_PAD_CNTL_D1__DIFF_STR__SHIFT 0x0000001d
+#define MC_IO_PAD_CNTL_D1__DISABLE_ADR_MASK 0x00002000L
+#define MC_IO_PAD_CNTL_D1__DISABLE_ADR__SHIFT 0x0000000d
+#define MC_IO_PAD_CNTL_D1__DISABLE_CMD_MASK 0x00001000L
+#define MC_IO_PAD_CNTL_D1__DISABLE_CMD__SHIFT 0x0000000c
+#define MC_IO_PAD_CNTL_D1__EN_RD_STR_DLY_MASK 0x00000800L
+#define MC_IO_PAD_CNTL_D1__EN_RD_STR_DLY__SHIFT 0x0000000b
+#define MC_IO_PAD_CNTL_D1__FORCE_EN_RD_STR_MASK 0x00000400L
+#define MC_IO_PAD_CNTL_D1__FORCE_EN_RD_STR__SHIFT 0x0000000a
+#define MC_IO_PAD_CNTL_D1__GDDR_PWRON_MASK 0x40000000L
+#define MC_IO_PAD_CNTL_D1__GDDR_PWRON__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_ADR_MASK 0x00000200L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_ADR__SHIFT 0x00000009
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CLK_MASK 0x00000080L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CLK__SHIFT 0x00000007
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CMD_MASK 0x00000100L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CMD__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_DATA_MASK 0x00000020L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_DATA__SHIFT 0x00000005
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_STR_MASK 0x00000040L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_STR__SHIFT 0x00000006
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CKE_MASK 0x08000000L
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CKE__SHIFT 0x0000001b
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CLK_MASK 0x80000000L
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CLK__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL_D1__UNI_STR_MASK 0x10000000L
+#define MC_IO_PAD_CNTL_D1__UNI_STR__SHIFT 0x0000001c
+#define MC_IO_PAD_CNTL_D1__VREFI_EN_MASK 0x00004000L
+#define MC_IO_PAD_CNTL_D1__VREFI_EN__SHIFT 0x0000000e
+#define MC_IO_PAD_CNTL_D1__VREFI_SEL_MASK 0x000f8000L
+#define MC_IO_PAD_CNTL_D1__VREFI_SEL__SHIFT 0x0000000f
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MAX_MASK 0x0000ff00L
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MAX__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MIN_MASK 0x000000ffL
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MIN__SHIFT 0x00000000
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D0_MASK 0x00040000L
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D0__SHIFT 0x00000012
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D1_MASK 0x00080000L
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D1__SHIFT 0x00000013
+#define MC_IO_PAD_CNTL__RXPHASE_GRAY_MASK 0x00020000L
+#define MC_IO_PAD_CNTL__RXPHASE_GRAY__SHIFT 0x00000011
+#define MC_IO_PAD_CNTL__TXPHASE_GRAY_MASK 0x00010000L
+#define MC_IO_PAD_CNTL__TXPHASE_GRAY__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D0__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY0_D0__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY0_D0__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY0_D0__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY0_D1__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY0_D1__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY0_D1__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY0_D1__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY1_D0__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY1_D0__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY1_D0__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY1_D0__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY1_D1__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY1_D1__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY1_D1__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY1_D1__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY0_D0__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY0_D0__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY0_D0__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY0_D0__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY0_D0__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY0_D0__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY0_D0__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY0_D0__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY0_D0__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY0_D0__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY0_D0__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY0_D0__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY0_D0__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY0_D0__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY0_D0__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY0_D0__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY0_D1__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY0_D1__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY0_D1__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY0_D1__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY0_D1__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY0_D1__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY0_D1__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY0_D1__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY0_D1__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY0_D1__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY0_D1__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY0_D1__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY0_D1__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY0_D1__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY0_D1__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY0_D1__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY1_D0__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY1_D0__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY1_D0__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY1_D0__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY1_D0__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY1_D0__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY1_D0__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY1_D0__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY1_D0__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY1_D0__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY1_D0__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY1_D0__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY1_D0__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY1_D0__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY1_D0__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY1_D0__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY1_D1__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY1_D1__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY1_D1__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY1_D1__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY1_D1__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY1_D1__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY1_D1__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY1_D1__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY1_D1__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY1_D1__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY1_D1__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY1_D1__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY1_D1__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY1_D1__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY1_D1__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY1_D1__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFSEL__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_APHY_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_APHY_D0__CKE_BIT_MASK 0x40000000L
+#define MC_IO_TXCNTL_APHY_D0__CKE_BIT__SHIFT 0x0000001e
+#define MC_IO_TXCNTL_APHY_D0__CKE_SEL_MASK 0x80000000L
+#define MC_IO_TXCNTL_APHY_D0__CKE_SEL__SHIFT 0x0000001f
+#define MC_IO_TXCNTL_APHY_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_APHY_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_APHY_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_APHY_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_APHY_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_APHY_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_APHY_D0__NDRV_MASK 0x00700000L
+#define MC_IO_TXCNTL_APHY_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_APHY_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_APHY_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D0__PMA_LOOPBACK_MASK 0x0000e000L
+#define MC_IO_TXCNTL_APHY_D0__PMA_LOOPBACK__SHIFT 0x0000000d
+#define MC_IO_TXCNTL_APHY_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_APHY_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_APHY_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_APHY_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_APHY_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_APHY_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_APHY_D0__TXBPASS_SEL_MASK 0x00001000L
+#define MC_IO_TXCNTL_APHY_D0__TXBPASS_SEL__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_DATA_MASK 0x38000000L
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_DATA__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_APHY_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_APHY_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_APHY_D0__TXRESET_MASK 0x02000000L
+#define MC_IO_TXCNTL_APHY_D0__TXRESET__SHIFT 0x00000019
+#define MC_IO_TXCNTL_APHY_D0__YCLKON_MASK 0x00800000L
+#define MC_IO_TXCNTL_APHY_D0__YCLKON__SHIFT 0x00000017
+#define MC_IO_TXCNTL_APHY_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_APHY_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_APHY_D1__CKE_BIT_MASK 0x40000000L
+#define MC_IO_TXCNTL_APHY_D1__CKE_BIT__SHIFT 0x0000001e
+#define MC_IO_TXCNTL_APHY_D1__CKE_SEL_MASK 0x80000000L
+#define MC_IO_TXCNTL_APHY_D1__CKE_SEL__SHIFT 0x0000001f
+#define MC_IO_TXCNTL_APHY_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_APHY_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_APHY_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_APHY_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_APHY_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_APHY_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_APHY_D1__NDRV_MASK 0x00700000L
+#define MC_IO_TXCNTL_APHY_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_APHY_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_APHY_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D1__PMA_LOOPBACK_MASK 0x0000e000L
+#define MC_IO_TXCNTL_APHY_D1__PMA_LOOPBACK__SHIFT 0x0000000d
+#define MC_IO_TXCNTL_APHY_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_APHY_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_APHY_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_APHY_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_APHY_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_APHY_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_APHY_D1__TXBPASS_SEL_MASK 0x00001000L
+#define MC_IO_TXCNTL_APHY_D1__TXBPASS_SEL__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_DATA_MASK 0x38000000L
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_DATA__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_APHY_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_APHY_D1__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_APHY_D1__TXRESET_MASK 0x02000000L
+#define MC_IO_TXCNTL_APHY_D1__TXRESET__SHIFT 0x00000019
+#define MC_IO_TXCNTL_APHY_D1__YCLKON_MASK 0x00800000L
+#define MC_IO_TXCNTL_APHY_D1__YCLKON__SHIFT 0x00000017
+#define MC_IO_TXCNTL_DPHY0_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY0_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY0_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY0_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY0_D0__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY0_D0__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY0_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY0_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY0_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY0_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY0_D0__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY0_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY0_D0__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY0_D0__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY0_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY0_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY0_D0__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY0_D0__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY0_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY0_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY0_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY0_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY0_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY0_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY0_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY0_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY0_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY0_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY0_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY0_D1__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY0_D1__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY0_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY0_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY0_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY0_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY0_D1__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY0_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY0_D1__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY0_D1__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY0_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY0_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY0_D1__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY0_D1__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY0_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY0_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY0_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY0_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY0_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY0_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY0_D1__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY1_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY1_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY1_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY1_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY1_D0__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY1_D0__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY1_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY1_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY1_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY1_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY1_D0__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY1_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY1_D0__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY1_D0__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY1_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY1_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY1_D0__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY1_D0__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY1_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY1_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY1_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY1_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY1_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY1_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY1_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY1_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY1_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY1_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY1_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY1_D1__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY1_D1__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY1_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY1_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY1_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY1_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY1_D1__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY1_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY1_D1__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY1_D1__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY1_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY1_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY1_D1__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY1_D1__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY1_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY1_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY1_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY1_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY1_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY1_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY1_D1__TXPD__SHIFT 0x00000007
+#define MCLK_PWRMGT_CNTL__DLL_READY_MASK 0x00000040L
+#define MCLK_PWRMGT_CNTL__DLL_READY_READ_MASK 0x01000000L
+#define MCLK_PWRMGT_CNTL__DLL_READY_READ__SHIFT 0x00000018
+#define MCLK_PWRMGT_CNTL__DLL_READY__SHIFT 0x00000006
+#define MCLK_PWRMGT_CNTL__DLL_SPEED_MASK 0x0000001fL
+#define MCLK_PWRMGT_CNTL__DLL_SPEED__SHIFT 0x00000000
+#define MCLK_PWRMGT_CNTL__MC_INT_CNTL_MASK 0x00000080L
+#define MCLK_PWRMGT_CNTL__MC_INT_CNTL__SHIFT 0x00000007
+#define MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK 0x00000100L
+#define MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT 0x00000008
+#define MCLK_PWRMGT_CNTL__MRDCK0_RESET_MASK 0x00010000L
+#define MCLK_PWRMGT_CNTL__MRDCK0_RESET__SHIFT 0x00000010
+#define MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK 0x00000200L
+#define MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT 0x00000009
+#define MCLK_PWRMGT_CNTL__MRDCK1_RESET_MASK 0x00020000L
+#define MCLK_PWRMGT_CNTL__MRDCK1_RESET__SHIFT 0x00000011
+#define MC_MEM_POWER_LS__LS_HOLD_MASK 0x00000fc0L
+#define MC_MEM_POWER_LS__LS_HOLD__SHIFT 0x00000006
+#define MC_MEM_POWER_LS__LS_SETUP_MASK 0x0000003fL
+#define MC_MEM_POWER_LS__LS_SETUP__SHIFT 0x00000000
+#define MC_NPL_STATUS__D0_NDELAY_MASK 0x0000000cL
+#define MC_NPL_STATUS__D0_NDELAY__SHIFT 0x00000002
+#define MC_NPL_STATUS__D0_NEARLY_MASK 0x00000020L
+#define MC_NPL_STATUS__D0_NEARLY__SHIFT 0x00000005
+#define MC_NPL_STATUS__D0_PDELAY_MASK 0x00000003L
+#define MC_NPL_STATUS__D0_PDELAY__SHIFT 0x00000000
+#define MC_NPL_STATUS__D0_PEARLY_MASK 0x00000010L
+#define MC_NPL_STATUS__D0_PEARLY__SHIFT 0x00000004
+#define MC_NPL_STATUS__D1_NDELAY_MASK 0x00000300L
+#define MC_NPL_STATUS__D1_NDELAY__SHIFT 0x00000008
+#define MC_NPL_STATUS__D1_NEARLY_MASK 0x00000800L
+#define MC_NPL_STATUS__D1_NEARLY__SHIFT 0x0000000b
+#define MC_NPL_STATUS__D1_PDELAY_MASK 0x000000c0L
+#define MC_NPL_STATUS__D1_PDELAY__SHIFT 0x00000006
+#define MC_NPL_STATUS__D1_PEARLY_MASK 0x00000400L
+#define MC_NPL_STATUS__D1_PEARLY__SHIFT 0x0000000a
+#define MC_PHY_TIMING_2__ADR_CLKEN_D0_MASK 0x00040000L
+#define MC_PHY_TIMING_2__ADR_CLKEN_D0__SHIFT 0x00000012
+#define MC_PHY_TIMING_2__ADR_CLKEN_D1_MASK 0x00080000L
+#define MC_PHY_TIMING_2__ADR_CLKEN_D1__SHIFT 0x00000013
+#define MC_PHY_TIMING_2__IND_LD_CNT_MASK 0x0000007fL
+#define MC_PHY_TIMING_2__IND_LD_CNT__SHIFT 0x00000000
+#define MC_PHY_TIMING_2__RXC0_FRC_MASK 0x00001000L
+#define MC_PHY_TIMING_2__RXC0_FRC__SHIFT 0x0000000c
+#define MC_PHY_TIMING_2__RXC0_INV_MASK 0x00000100L
+#define MC_PHY_TIMING_2__RXC0_INV__SHIFT 0x00000008
+#define MC_PHY_TIMING_2__RXC1_FRC_MASK 0x00002000L
+#define MC_PHY_TIMING_2__RXC1_FRC__SHIFT 0x0000000d
+#define MC_PHY_TIMING_2__RXC1_INV_MASK 0x00000200L
+#define MC_PHY_TIMING_2__RXC1_INV__SHIFT 0x00000009
+#define MC_PHY_TIMING_2__TXC0_FRC_MASK 0x00004000L
+#define MC_PHY_TIMING_2__TXC0_FRC__SHIFT 0x0000000e
+#define MC_PHY_TIMING_2__TXC0_INV_MASK 0x00000400L
+#define MC_PHY_TIMING_2__TXC0_INV__SHIFT 0x0000000a
+#define MC_PHY_TIMING_2__TXC1_FRC_MASK 0x00008000L
+#define MC_PHY_TIMING_2__TXC1_FRC__SHIFT 0x0000000f
+#define MC_PHY_TIMING_2__TXC1_INV_MASK 0x00000800L
+#define MC_PHY_TIMING_2__TXC1_INV__SHIFT 0x0000000b
+#define MC_PHY_TIMING_2__TX_CDREN_D0_MASK 0x00010000L
+#define MC_PHY_TIMING_2__TX_CDREN_D0__SHIFT 0x00000010
+#define MC_PHY_TIMING_2__TX_CDREN_D1_MASK 0x00020000L
+#define MC_PHY_TIMING_2__TX_CDREN_D1__SHIFT 0x00000011
+#define MC_PHY_TIMING_2__WR_DLY_MASK 0x00f00000L
+#define MC_PHY_TIMING_2__WR_DLY__SHIFT 0x00000014
+#define MC_PHY_TIMING_D0__RXC0_DLY_MASK 0x0000000fL
+#define MC_PHY_TIMING_D0__RXC0_DLY__SHIFT 0x00000000
+#define MC_PHY_TIMING_D0__RXC0_EXT_MASK 0x000000f0L
+#define MC_PHY_TIMING_D0__RXC0_EXT__SHIFT 0x00000004
+#define MC_PHY_TIMING_D0__RXC1_DLY_MASK 0x00000f00L
+#define MC_PHY_TIMING_D0__RXC1_DLY__SHIFT 0x00000008
+#define MC_PHY_TIMING_D0__RXC1_EXT_MASK 0x0000f000L
+#define MC_PHY_TIMING_D0__RXC1_EXT__SHIFT 0x0000000c
+#define MC_PHY_TIMING_D0__TXC0_DLY_MASK 0x00070000L
+#define MC_PHY_TIMING_D0__TXC0_DLY__SHIFT 0x00000010
+#define MC_PHY_TIMING_D0__TXC0_EXT_MASK 0x00f00000L
+#define MC_PHY_TIMING_D0__TXC0_EXT__SHIFT 0x00000014
+#define MC_PHY_TIMING_D0__TXC1_DLY_MASK 0x07000000L
+#define MC_PHY_TIMING_D0__TXC1_DLY__SHIFT 0x00000018
+#define MC_PHY_TIMING_D0__TXC1_EXT_MASK 0xf0000000L
+#define MC_PHY_TIMING_D0__TXC1_EXT__SHIFT 0x0000001c
+#define MC_PHY_TIMING_D1__RXC0_DLY_MASK 0x0000000fL
+#define MC_PHY_TIMING_D1__RXC0_DLY__SHIFT 0x00000000
+#define MC_PHY_TIMING_D1__RXC0_EXT_MASK 0x000000f0L
+#define MC_PHY_TIMING_D1__RXC0_EXT__SHIFT 0x00000004
+#define MC_PHY_TIMING_D1__RXC1_DLY_MASK 0x00000f00L
+#define MC_PHY_TIMING_D1__RXC1_DLY__SHIFT 0x00000008
+#define MC_PHY_TIMING_D1__RXC1_EXT_MASK 0x0000f000L
+#define MC_PHY_TIMING_D1__RXC1_EXT__SHIFT 0x0000000c
+#define MC_PHY_TIMING_D1__TXC0_DLY_MASK 0x00070000L
+#define MC_PHY_TIMING_D1__TXC0_DLY__SHIFT 0x00000010
+#define MC_PHY_TIMING_D1__TXC0_EXT_MASK 0x00f00000L
+#define MC_PHY_TIMING_D1__TXC0_EXT__SHIFT 0x00000014
+#define MC_PHY_TIMING_D1__TXC1_DLY_MASK 0x07000000L
+#define MC_PHY_TIMING_D1__TXC1_DLY__SHIFT 0x00000018
+#define MC_PHY_TIMING_D1__TXC1_EXT_MASK 0xf0000000L
+#define MC_PHY_TIMING_D1__TXC1_EXT__SHIFT 0x0000001c
+#define MC_PMG_AUTO_CFG__DLL_CNT_MASK 0xff000000L
+#define MC_PMG_AUTO_CFG__DLL_CNT__SHIFT 0x00000018
+#define MC_PMG_AUTO_CFG__EXIT_ALLOW_STOP_MASK 0x00000800L
+#define MC_PMG_AUTO_CFG__EXIT_ALLOW_STOP__SHIFT 0x0000000b
+#define MC_PMG_AUTO_CFG__MRS_WAIT_CNT_MASK 0x000f0000L
+#define MC_PMG_AUTO_CFG__MRS_WAIT_CNT__SHIFT 0x00000010
+#define MC_PMG_AUTO_CFG__PREA_SRX_MASK 0x00002000L
+#define MC_PMG_AUTO_CFG__PREA_SRX__SHIFT 0x0000000d
+#define MC_PMG_AUTO_CFG__RFS_SRX_MASK 0x00001000L
+#define MC_PMG_AUTO_CFG__RFS_SRX__SHIFT 0x0000000c
+#define MC_PMG_AUTO_CFG__RST_MRS_MASK 0x00000002L
+#define MC_PMG_AUTO_CFG__RST_MRS__SHIFT 0x00000001
+#define MC_PMG_AUTO_CFG__RXPDNB_MASK 0x00400000L
+#define MC_PMG_AUTO_CFG__RXPDNB__SHIFT 0x00000016
+#define MC_PMG_AUTO_CFG__SCDS_MODE_MASK 0x00000400L
+#define MC_PMG_AUTO_CFG__SCDS_MODE__SHIFT 0x0000000a
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_0_MASK 0x00008000L
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_0__SHIFT 0x0000000f
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_1_MASK 0x00800000L
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_1__SHIFT 0x00000017
+#define MC_PMG_AUTO_CFG__SS_ALWAYS_SLF_MASK 0x00000100L
+#define MC_PMG_AUTO_CFG__SS_ALWAYS_SLF__SHIFT 0x00000008
+#define MC_PMG_AUTO_CFG__SS_S_SLF_MASK 0x00000200L
+#define MC_PMG_AUTO_CFG__SS_S_SLF__SHIFT 0x00000009
+#define MC_PMG_AUTO_CFG__STUTTER_EN_MASK 0x00004000L
+#define MC_PMG_AUTO_CFG__STUTTER_EN__SHIFT 0x0000000e
+#define MC_PMG_AUTO_CFG__SYC_CLK_MASK 0x00000001L
+#define MC_PMG_AUTO_CFG__SYC_CLK__SHIFT 0x00000000
+#define MC_PMG_AUTO_CFG__TRI_MIO_MASK 0x00000004L
+#define MC_PMG_AUTO_CFG__TRI_MIO__SHIFT 0x00000002
+#define MC_PMG_AUTO_CFG__WRITE_DURING_DLOCK_MASK 0x00100000L
+#define MC_PMG_AUTO_CFG__WRITE_DURING_DLOCK__SHIFT 0x00000014
+#define MC_PMG_AUTO_CFG__XSR_TMR_MASK 0x000000f0L
+#define MC_PMG_AUTO_CFG__XSR_TMR__SHIFT 0x00000004
+#define MC_PMG_AUTO_CFG__YCLK_ON_MASK 0x00200000L
+#define MC_PMG_AUTO_CFG__YCLK_ON__SHIFT 0x00000015
+#define MC_PMG_AUTO_CMD__ADR_MASK 0x0001ffffL
+#define MC_PMG_AUTO_CMD__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_AUTO_CMD__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_AUTO_CMD__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_AUTO_CMD__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_AUTO_CMD__ADR__SHIFT 0x00000000
+#define MC_PMG_CFG__DPM_WAKE_MASK 0x00000400L
+#define MC_PMG_CFG__DPM_WAKE__SHIFT 0x0000000a
+#define MC_PMG_CFG__EARLY_ACK_ACPI_MASK 0x00400000L
+#define MC_PMG_CFG__EARLY_ACK_ACPI__SHIFT 0x00000016
+#define MC_PMG_CFG__MRS_WAIT_CNT_MASK 0x000f0000L
+#define MC_PMG_CFG__MRS_WAIT_CNT__SHIFT 0x00000010
+#define MC_PMG_CFG__PREA_SRX_MASK 0x00002000L
+#define MC_PMG_CFG__PREA_SRX__SHIFT 0x0000000d
+#define MC_PMG_CFG__RFS_SRX_MASK 0x00001000L
+#define MC_PMG_CFG__RFS_SRX__SHIFT 0x0000000c
+#define MC_PMG_CFG__RST_EMRS_MASK 0x00000004L
+#define MC_PMG_CFG__RST_EMRS__SHIFT 0x00000002
+#define MC_PMG_CFG__RST_MRS1_MASK 0x00000100L
+#define MC_PMG_CFG__RST_MRS1__SHIFT 0x00000008
+#define MC_PMG_CFG__RST_MRS2_MASK 0x00000200L
+#define MC_PMG_CFG__RST_MRS2__SHIFT 0x00000009
+#define MC_PMG_CFG__RST_MRS_MASK 0x00000002L
+#define MC_PMG_CFG__RST_MRS__SHIFT 0x00000001
+#define MC_PMG_CFG__RXPDNB_MASK 0x02000000L
+#define MC_PMG_CFG__RXPDNB__SHIFT 0x00000019
+#define MC_PMG_CFG__SYC_CLK_MASK 0x00000001L
+#define MC_PMG_CFG__SYC_CLK__SHIFT 0x00000000
+#define MC_PMG_CFG__TRI_MIO_MASK 0x00000008L
+#define MC_PMG_CFG__TRI_MIO__SHIFT 0x00000003
+#define MC_PMG_CFG__WRITE_DURING_DLOCK_MASK 0x00100000L
+#define MC_PMG_CFG__WRITE_DURING_DLOCK__SHIFT 0x00000014
+#define MC_PMG_CFG__XSR_TMR_MASK 0x000000f0L
+#define MC_PMG_CFG__XSR_TMR__SHIFT 0x00000004
+#define MC_PMG_CFG__YCLK_ON_MASK 0x00200000L
+#define MC_PMG_CFG__YCLK_ON__SHIFT 0x00000015
+#define MC_PMG_CFG__ZQCL_SEND_MASK 0x0c000000L
+#define MC_PMG_CFG__ZQCL_SEND__SHIFT 0x0000001a
+#define MC_PMG_CMD_EMRS__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_EMRS__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_EMRS__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_EMRS__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_EMRS__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_EMRS__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_EMRS__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_EMRS__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_EMRS__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_EMRS__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_EMRS__END_MASK 0x00100000L
+#define MC_PMG_CMD_EMRS__END__SHIFT 0x00000014
+#define MC_PMG_CMD_EMRS__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_EMRS__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS1__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS1__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS1__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS1__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS1__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS1__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS1__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS1__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS1__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS1__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS1__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS1__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS1__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS1__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS2__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS2__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS2__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS2__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS2__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS2__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS2__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS2__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS2__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS2__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS2__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS2__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS2__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS2__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS__MOP__SHIFT 0x00000010
+#define MC_RD_CB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_CB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_CB__ENABLE_MASK 0x00000001L
+#define MC_RD_CB__ENABLE__SHIFT 0x00000000
+#define MC_RD_CB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_CB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_CB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_CB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_CB__PRESCALE_MASK 0x00000006L
+#define MC_RD_CB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_CB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_CB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_CB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_CB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_CB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_CB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_DB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_DB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_DB__ENABLE_MASK 0x00000001L
+#define MC_RD_DB__ENABLE__SHIFT 0x00000000
+#define MC_RD_DB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_DB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_DB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_DB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_DB__PRESCALE_MASK 0x00000006L
+#define MC_RD_DB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_DB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_DB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_DB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_DB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_DB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_DB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_GRP_EXT__DBSTEN0_MASK 0x0000000fL
+#define MC_RD_GRP_EXT__DBSTEN0__SHIFT 0x00000000
+#define MC_RD_GRP_EXT__TC0_MASK 0x000000f0L
+#define MC_RD_GRP_EXT__TC0__SHIFT 0x00000004
+#define MC_RD_GRP_GFX__CP_MASK 0x0000000fL
+#define MC_RD_GRP_GFX__CP__SHIFT 0x00000000
+#define MC_RD_GRP_GFX__XDMAM_MASK 0x000f0000L
+#define MC_RD_GRP_GFX__XDMAM__SHIFT 0x00000010
+#define MC_RD_GRP_LCL__CB0_MASK 0x0000f000L
+#define MC_RD_GRP_LCL__CB0__SHIFT 0x0000000c
+#define MC_RD_GRP_LCL__CBCMASK0_MASK 0x000f0000L
+#define MC_RD_GRP_LCL__CBCMASK0__SHIFT 0x00000010
+#define MC_RD_GRP_LCL__CBFMASK0_MASK 0x00f00000L
+#define MC_RD_GRP_LCL__CBFMASK0__SHIFT 0x00000014
+#define MC_RD_GRP_LCL__DB0_MASK 0x0f000000L
+#define MC_RD_GRP_LCL__DB0__SHIFT 0x00000018
+#define MC_RD_GRP_LCL__DBHTILE0_MASK 0xf0000000L
+#define MC_RD_GRP_LCL__DBHTILE0__SHIFT 0x0000001c
+#define MC_RD_GRP_OTH__HDP_MASK 0x00000f00L
+#define MC_RD_GRP_OTH__HDP__SHIFT 0x00000008
+#define MC_RD_GRP_OTH__SEM_MASK 0x0000f000L
+#define MC_RD_GRP_OTH__SEM__SHIFT 0x0000000c
+#define MC_RD_GRP_OTH__UMC_MASK 0x000f0000L
+#define MC_RD_GRP_OTH__UMC__SHIFT 0x00000010
+#define MC_RD_GRP_OTH__UVD_EXT0_MASK 0x0000000fL
+#define MC_RD_GRP_OTH__UVD_EXT0__SHIFT 0x00000000
+#define MC_RD_GRP_OTH__UVD_EXT1_MASK 0x0f000000L
+#define MC_RD_GRP_OTH__UVD_EXT1__SHIFT 0x00000018
+#define MC_RD_GRP_OTH__UVD_MASK 0x00f00000L
+#define MC_RD_GRP_OTH__UVD__SHIFT 0x00000014
+#define MC_RD_GRP_SYS__DMIF_MASK 0x0000f000L
+#define MC_RD_GRP_SYS__DMIF__SHIFT 0x0000000c
+#define MC_RD_GRP_SYS__MCIF_MASK 0x000f0000L
+#define MC_RD_GRP_SYS__MCIF__SHIFT 0x00000010
+#define MC_RD_GRP_SYS__RLC_MASK 0x0000000fL
+#define MC_RD_GRP_SYS__RLC__SHIFT 0x00000000
+#define MC_RD_GRP_SYS__SMU_MASK 0x00f00000L
+#define MC_RD_GRP_SYS__SMU__SHIFT 0x00000014
+#define MC_RD_GRP_SYS__VCE_MASK 0x0f000000L
+#define MC_RD_GRP_SYS__VCE__SHIFT 0x00000018
+#define MC_RD_GRP_SYS__VCEU_MASK 0xf0000000L
+#define MC_RD_GRP_SYS__VCEU__SHIFT 0x0000001c
+#define MC_RD_GRP_SYS__VMC_MASK 0x000000f0L
+#define MC_RD_GRP_SYS__VMC__SHIFT 0x00000004
+#define MC_RD_HUB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_HUB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_HUB__ENABLE_MASK 0x00000001L
+#define MC_RD_HUB__ENABLE__SHIFT 0x00000000
+#define MC_RD_HUB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_HUB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_HUB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_HUB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_HUB__PRESCALE_MASK 0x00000006L
+#define MC_RD_HUB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_HUB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_HUB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_HUB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_HUB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_HUB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_HUB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_TC0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_TC0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_TC0__ENABLE_MASK 0x00000001L
+#define MC_RD_TC0__ENABLE__SHIFT 0x00000000
+#define MC_RD_TC0__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_TC0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_TC0__MAX_BURST_MASK 0x00000780L
+#define MC_RD_TC0__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_TC0__PRESCALE_MASK 0x00000006L
+#define MC_RD_TC0__PRESCALE__SHIFT 0x00000001
+#define MC_RD_TC0__STALL_MODE_MASK 0x00000030L
+#define MC_RD_TC0__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_TC0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_TC0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_TC0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_TC0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_TC1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_TC1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_TC1__ENABLE_MASK 0x00000001L
+#define MC_RD_TC1__ENABLE__SHIFT 0x00000000
+#define MC_RD_TC1__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_TC1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_TC1__MAX_BURST_MASK 0x00000780L
+#define MC_RD_TC1__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_TC1__PRESCALE_MASK 0x00000006L
+#define MC_RD_TC1__PRESCALE__SHIFT 0x00000001
+#define MC_RD_TC1__STALL_MODE_MASK 0x00000030L
+#define MC_RD_TC1__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_TC1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_TC1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_TC1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_TC1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RPB_ARB_CNTL__ATC_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_ARB_CNTL__ATC_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_ARB_CNTL__RD_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_ARB_CNTL__RD_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_ARB_CNTL__WR_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_ARB_CNTL__WR_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_BIF_CNTL__ARB_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_BIF_CNTL__ARB_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_BIF_CNTL__XPB_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_BIF_CNTL__XPB_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_EX_DATA__READ_ENTRIES_MASK 0xffff0000L
+#define MC_RPB_CID_QUEUE_EX_DATA__READ_ENTRIES__SHIFT 0x00000010
+#define MC_RPB_CID_QUEUE_EX_DATA__WRITE_ENTRIES_MASK 0x0000ffffL
+#define MC_RPB_CID_QUEUE_EX_DATA__WRITE_ENTRIES__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_EX__OFFSET_MASK 0x0000003eL
+#define MC_RPB_CID_QUEUE_EX__OFFSET__SHIFT 0x00000001
+#define MC_RPB_CID_QUEUE_EX__START_MASK 0x00000001L
+#define MC_RPB_CID_QUEUE_EX__START__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_RD__CLIENT_ID_MASK 0x000000ffL
+#define MC_RPB_CID_QUEUE_RD__CLIENT_ID__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_RD__READ_QUEUE_MASK 0x00000c00L
+#define MC_RPB_CID_QUEUE_RD__READ_QUEUE__SHIFT 0x0000000a
+#define MC_RPB_CID_QUEUE_RD__WRITE_QUEUE_MASK 0x00000300L
+#define MC_RPB_CID_QUEUE_RD__WRITE_QUEUE__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_WR__CLIENT_ID_MASK 0x000000ffL
+#define MC_RPB_CID_QUEUE_WR__CLIENT_ID__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_WR__READ_QUEUE_MASK 0x00001800L
+#define MC_RPB_CID_QUEUE_WR__READ_QUEUE__SHIFT 0x0000000b
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MASK 0x00002000L
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MODE_MASK 0x00000100L
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MODE__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_WR__UPDATE__SHIFT 0x0000000d
+#define MC_RPB_CID_QUEUE_WR__WRITE_QUEUE_MASK 0x00000600L
+#define MC_RPB_CID_QUEUE_WR__WRITE_QUEUE__SHIFT 0x00000009
+#define MC_RPB_CONF__RPB_RD_PCIE_ORDER_MASK 0x00010000L
+#define MC_RPB_CONF__RPB_RD_PCIE_ORDER__SHIFT 0x00000010
+#define MC_RPB_CONF__RPB_WR_PCIE_ORDER_MASK 0x00020000L
+#define MC_RPB_CONF__RPB_WR_PCIE_ORDER__SHIFT 0x00000011
+#define MC_RPB_CONF__XPB_PCIE_ORDER_MASK 0x00008000L
+#define MC_RPB_CONF__XPB_PCIE_ORDER__SHIFT 0x0000000f
+#define MC_RPB_DBG1__DEBUG_BITS_MASK 0xfff00000L
+#define MC_RPB_DBG1__DEBUG_BITS__SHIFT 0x00000014
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_32B_MASK 0x000fff00L
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_32B__SHIFT 0x00000008
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_MASK 0x000000ffL
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD__SHIFT 0x00000000
+#define MC_RPB_EFF_CNTL__RD_LAZY_TIMER_MASK 0x0000ff00L
+#define MC_RPB_EFF_CNTL__RD_LAZY_TIMER__SHIFT 0x00000008
+#define MC_RPB_EFF_CNTL__WR_LAZY_TIMER_MASK 0x000000ffL
+#define MC_RPB_EFF_CNTL__WR_LAZY_TIMER__SHIFT 0x00000000
+#define MC_RPB_IF_CONF__OUTSTANDING_WRRET_ASK_MASK 0x0000ff00L
+#define MC_RPB_IF_CONF__OUTSTANDING_WRRET_ASK__SHIFT 0x00000008
+#define MC_RPB_IF_CONF__RPB_BIF_CREDITS_MASK 0x000000ffL
+#define MC_RPB_IF_CONF__RPB_BIF_CREDITS__SHIFT 0x00000000
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_ALL_PERF_COUNTERS_MASK 0x00000008L
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_ALL_PERF_COUNTERS__SHIFT 0x00000003
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_SELECTED_PERF_COUNTER_MASK 0x00000004L
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_SELECTED_PERF_COUNTER__SHIFT 0x00000002
+#define MC_RPB_PERF_COUNTER_CNTL__ENABLE_PERF_COUNTERS_MASK 0x000001e0L
+#define MC_RPB_PERF_COUNTER_CNTL__ENABLE_PERF_COUNTERS__SHIFT 0x00000005
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_0_MASK 0x00003e00L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_0__SHIFT 0x00000009
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_1_MASK 0x0007c000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_1__SHIFT 0x0000000e
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_2_MASK 0x00f80000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_2__SHIFT 0x00000013
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_3_MASK 0x1f000000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_3__SHIFT 0x00000018
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_SELECT_MASK 0x00000003L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_SELECT__SHIFT 0x00000000
+#define MC_RPB_PERF_COUNTER_CNTL__STOP_ON_COUNTER_SATURATION_MASK 0x00000010L
+#define MC_RPB_PERF_COUNTER_CNTL__STOP_ON_COUNTER_SATURATION__SHIFT 0x00000004
+#define MC_RPB_PERF_COUNTER_STATUS__PERFORMANCE_COUNTER_VALUE_MASK 0xffffffffL
+#define MC_RPB_PERF_COUNTER_STATUS__PERFORMANCE_COUNTER_VALUE__SHIFT 0x00000000
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE0_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE0_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE1_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE1_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE2_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE2_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE3_SWITCH_NUM_MASK 0xff000000L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE3_SWITCH_NUM__SHIFT 0x00000018
+#define MC_RPB_WR_COMBINE_CNTL__WC_ALIGN_MASK 0x00000080L
+#define MC_RPB_WR_COMBINE_CNTL__WC_ALIGN__SHIFT 0x00000007
+#define MC_RPB_WR_COMBINE_CNTL__WC_ENABLE_MASK 0x00000001L
+#define MC_RPB_WR_COMBINE_CNTL__WC_ENABLE__SHIFT 0x00000000
+#define MC_RPB_WR_COMBINE_CNTL__WC_FLUSH_TIMER_MASK 0x00000078L
+#define MC_RPB_WR_COMBINE_CNTL__WC_FLUSH_TIMER__SHIFT 0x00000003
+#define MC_RPB_WR_COMBINE_CNTL__WC_MAX_PACKET_SIZE_MASK 0x00000006L
+#define MC_RPB_WR_COMBINE_CNTL__WC_MAX_PACKET_SIZE__SHIFT 0x00000001
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE0_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE0_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE1_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE1_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE2_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE2_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE3_SWITCH_NUM_MASK 0xff000000L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE3_SWITCH_NUM__SHIFT 0x00000018
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BYTE_REMAP_D0__BYTE0_MASK 0x00000003L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE0__SHIFT 0x00000000
+#define MC_SEQ_BYTE_REMAP_D0__BYTE1_MASK 0x0000000cL
+#define MC_SEQ_BYTE_REMAP_D0__BYTE1__SHIFT 0x00000002
+#define MC_SEQ_BYTE_REMAP_D0__BYTE2_MASK 0x00000030L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE2__SHIFT 0x00000004
+#define MC_SEQ_BYTE_REMAP_D0__BYTE3_MASK 0x000000c0L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE3__SHIFT 0x00000006
+#define MC_SEQ_BYTE_REMAP_D1__BYTE0_MASK 0x00000003L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE0__SHIFT 0x00000000
+#define MC_SEQ_BYTE_REMAP_D1__BYTE1_MASK 0x0000000cL
+#define MC_SEQ_BYTE_REMAP_D1__BYTE1__SHIFT 0x00000002
+#define MC_SEQ_BYTE_REMAP_D1__BYTE2_MASK 0x00000030L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE2__SHIFT 0x00000004
+#define MC_SEQ_BYTE_REMAP_D1__BYTE3_MASK 0x000000c0L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE3__SHIFT 0x00000006
+#define MC_SEQ_CAS_TIMING_LP__TCCDL_MASK 0x00000e00L
+#define MC_SEQ_CAS_TIMING_LP__TCCDL__SHIFT 0x00000009
+#define MC_SEQ_CAS_TIMING_LP__TCL_MASK 0x1f000000L
+#define MC_SEQ_CAS_TIMING_LP__TCL__SHIFT 0x00000018
+#define MC_SEQ_CAS_TIMING_LP__TNOPR_MASK 0x0000000cL
+#define MC_SEQ_CAS_TIMING_LP__TNOPR__SHIFT 0x00000002
+#define MC_SEQ_CAS_TIMING_LP__TNOPW_MASK 0x00000003L
+#define MC_SEQ_CAS_TIMING_LP__TNOPW__SHIFT 0x00000000
+#define MC_SEQ_CAS_TIMING_LP__TR2R_MASK 0x0000f000L
+#define MC_SEQ_CAS_TIMING_LP__TR2R__SHIFT 0x0000000c
+#define MC_SEQ_CAS_TIMING_LP__TR2W_MASK 0x000001f0L
+#define MC_SEQ_CAS_TIMING_LP__TR2W__SHIFT 0x00000004
+#define MC_SEQ_CAS_TIMING_LP__TW2R_MASK 0x001f0000L
+#define MC_SEQ_CAS_TIMING_LP__TW2R__SHIFT 0x00000010
+#define MC_SEQ_CAS_TIMING__TCCDL_MASK 0x00000e00L
+#define MC_SEQ_CAS_TIMING__TCCDL__SHIFT 0x00000009
+#define MC_SEQ_CAS_TIMING__TCL_MASK 0x1f000000L
+#define MC_SEQ_CAS_TIMING__TCL__SHIFT 0x00000018
+#define MC_SEQ_CAS_TIMING__TNOPR_MASK 0x0000000cL
+#define MC_SEQ_CAS_TIMING__TNOPR__SHIFT 0x00000002
+#define MC_SEQ_CAS_TIMING__TNOPW_MASK 0x00000003L
+#define MC_SEQ_CAS_TIMING__TNOPW__SHIFT 0x00000000
+#define MC_SEQ_CAS_TIMING__TR2R_MASK 0x0000f000L
+#define MC_SEQ_CAS_TIMING__TR2R__SHIFT 0x0000000c
+#define MC_SEQ_CAS_TIMING__TR2W_MASK 0x000001f0L
+#define MC_SEQ_CAS_TIMING__TR2W__SHIFT 0x00000004
+#define MC_SEQ_CAS_TIMING__TW2R_MASK 0x001f0000L
+#define MC_SEQ_CAS_TIMING__TW2R__SHIFT 0x00000010
+#define MC_SEQ_CG__CG_SEQ_REQ_MASK 0x000000ffL
+#define MC_SEQ_CG__CG_SEQ_REQ__SHIFT 0x00000000
+#define MC_SEQ_CG__CG_SEQ_RESP_MASK 0x0000ff00L
+#define MC_SEQ_CG__CG_SEQ_RESP__SHIFT 0x00000008
+#define MC_SEQ_CG__SEQ_CG_REQ_MASK 0x00ff0000L
+#define MC_SEQ_CG__SEQ_CG_REQ__SHIFT 0x00000010
+#define MC_SEQ_CG__SEQ_CG_RESP_MASK 0xff000000L
+#define MC_SEQ_CG__SEQ_CG_RESP__SHIFT 0x00000018
+#define MC_SEQ_CMD__ADR_MASK 0x0000ffffL
+#define MC_SEQ_CMD__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_CMD__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_CMD__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_CMD__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_CMD__ADR__SHIFT 0x00000000
+#define MC_SEQ_CMD__CHAN0_MASK 0x01000000L
+#define MC_SEQ_CMD__CHAN0__SHIFT 0x00000018
+#define MC_SEQ_CMD__CHAN1_MASK 0x02000000L
+#define MC_SEQ_CMD__CHAN1__SHIFT 0x00000019
+#define MC_SEQ_CMD__CSB_MASK 0x00600000L
+#define MC_SEQ_CMD__CSB__SHIFT 0x00000015
+#define MC_SEQ_CMD__END_MASK 0x00100000L
+#define MC_SEQ_CMD__END__SHIFT 0x00000014
+#define MC_SEQ_CMD__MOP_MASK 0x000f0000L
+#define MC_SEQ_CMD__MOP__SHIFT 0x00000010
+#define MC_SEQ_CNTL_2__ARB_RTDAT_WMK_MSB_MASK 0x00000300L
+#define MC_SEQ_CNTL_2__ARB_RTDAT_WMK_MSB__SHIFT 0x00000008
+#define MC_SEQ_CNTL_2__DRST_NSTR_MASK 0x0000fc00L
+#define MC_SEQ_CNTL_2__DRST_NSTR__SHIFT 0x0000000a
+#define MC_SEQ_CNTL_2__DRST_PSTR_MASK 0x003f0000L
+#define MC_SEQ_CNTL_2__DRST_PSTR__SHIFT 0x00000010
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D0_MASK 0x0f000000L
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D0__SHIFT 0x00000018
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D1_MASK 0xf0000000L
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D1__SHIFT 0x0000001c
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D0_MASK 0x00400000L
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D0__SHIFT 0x00000016
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D1_MASK 0x00800000L
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D1__SHIFT 0x00000017
+#define MC_SEQ_CNTL__ARB_REQCMD_WMK_MASK 0x00f00000L
+#define MC_SEQ_CNTL__ARB_REQCMD_WMK__SHIFT 0x00000014
+#define MC_SEQ_CNTL__ARB_REQDAT_WMK_MASK 0x0f000000L
+#define MC_SEQ_CNTL__ARB_REQDAT_WMK__SHIFT 0x00000018
+#define MC_SEQ_CNTL__ARB_RTDAT_WMK_MASK 0xf0000000L
+#define MC_SEQ_CNTL__ARB_RTDAT_WMK__SHIFT 0x0000001c
+#define MC_SEQ_CNTL__BANKGROUP_ENB_MASK 0x00040000L
+#define MC_SEQ_CNTL__BANKGROUP_ENB__SHIFT 0x00000012
+#define MC_SEQ_CNTL__BANKGROUP_SIZE_MASK 0x00020000L
+#define MC_SEQ_CNTL__BANKGROUP_SIZE__SHIFT 0x00000011
+#define MC_SEQ_CNTL__CHANNEL_DISABLE_MASK 0x00000300L
+#define MC_SEQ_CNTL__CHANNEL_DISABLE__SHIFT 0x00000008
+#define MC_SEQ_CNTL__DAT_INV_MASK 0x00000040L
+#define MC_SEQ_CNTL__DAT_INV__SHIFT 0x00000006
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_BANK_MASK 0x0000000cL
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_BANK__SHIFT 0x00000002
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_COLS_MASK 0x00000003L
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_COLS__SHIFT 0x00000000
+#define MC_SEQ_CNTL__MSK_DF1_MASK 0x00000080L
+#define MC_SEQ_CNTL__MSK_DF1__SHIFT 0x00000007
+#define MC_SEQ_CNTL__MSKOFF_DAT_TH_MASK 0x00008000L
+#define MC_SEQ_CNTL__MSKOFF_DAT_TH__SHIFT 0x0000000f
+#define MC_SEQ_CNTL__MSKOFF_DAT_TL_MASK 0x00004000L
+#define MC_SEQ_CNTL__MSKOFF_DAT_TL__SHIFT 0x0000000e
+#define MC_SEQ_CNTL__RET_HOLD_EOP_MASK 0x00010000L
+#define MC_SEQ_CNTL__RET_HOLD_EOP__SHIFT 0x00000010
+#define MC_SEQ_CNTL__RTR_OVERRIDE_MASK 0x00080000L
+#define MC_SEQ_CNTL__RTR_OVERRIDE__SHIFT 0x00000013
+#define MC_SEQ_CNTL__SAFE_MODE_MASK 0x00000030L
+#define MC_SEQ_CNTL__SAFE_MODE__SHIFT 0x00000004
+#define MC_SEQ_DRAM_2__ADBI_ACT_MASK 0x04000000L
+#define MC_SEQ_DRAM_2__ADBI_ACT__SHIFT 0x0000001a
+#define MC_SEQ_DRAM_2__ADBI_DF1_MASK 0x02000000L
+#define MC_SEQ_DRAM_2__ADBI_DF1__SHIFT 0x00000019
+#define MC_SEQ_DRAM_2__ADR_DBI_ACM_MASK 0x00000004L
+#define MC_SEQ_DRAM_2__ADR_DBI_ACM__SHIFT 0x00000002
+#define MC_SEQ_DRAM_2__ADR_DBI_MASK 0x00000002L
+#define MC_SEQ_DRAM_2__ADR_DBI__SHIFT 0x00000001
+#define MC_SEQ_DRAM_2__ADR_DDR_MASK 0x00000001L
+#define MC_SEQ_DRAM_2__ADR_DDR__SHIFT 0x00000000
+#define MC_SEQ_DRAM_2__BNK_MRS_MASK 0x00002000L
+#define MC_SEQ_DRAM_2__BNK_MRS__SHIFT 0x0000000d
+#define MC_SEQ_DRAM_2__CMD_QDR_MASK 0x00000008L
+#define MC_SEQ_DRAM_2__CMD_QDR__SHIFT 0x00000003
+#define MC_SEQ_DRAM_2__CS_BY16_MASK 0x80000000L
+#define MC_SEQ_DRAM_2__CS_BY16__SHIFT 0x0000001f
+#define MC_SEQ_DRAM_2__DAT_QDR_MASK 0x00000010L
+#define MC_SEQ_DRAM_2__DAT_QDR__SHIFT 0x00000004
+#define MC_SEQ_DRAM_2__DBI_ACT_MASK 0x10000000L
+#define MC_SEQ_DRAM_2__DBI_ACT__SHIFT 0x0000001c
+#define MC_SEQ_DRAM_2__DBI_DF1_MASK 0x08000000L
+#define MC_SEQ_DRAM_2__DBI_DF1__SHIFT 0x0000001b
+#define MC_SEQ_DRAM_2__DBI_EDC_DF1_MASK 0x20000000L
+#define MC_SEQ_DRAM_2__DBI_EDC_DF1__SHIFT 0x0000001d
+#define MC_SEQ_DRAM_2__DBI_OVR_MASK 0x00004000L
+#define MC_SEQ_DRAM_2__DBI_OVR__SHIFT 0x0000000e
+#define MC_SEQ_DRAM_2__DLL_EST_MASK 0x00001000L
+#define MC_SEQ_DRAM_2__DLL_EST__SHIFT 0x0000000c
+#define MC_SEQ_DRAM_2__DQM_EST_MASK 0x00000080L
+#define MC_SEQ_DRAM_2__DQM_EST__SHIFT 0x00000007
+#define MC_SEQ_DRAM_2__PCH_BNK_MASK 0x01000000L
+#define MC_SEQ_DRAM_2__PCH_BNK__SHIFT 0x00000018
+#define MC_SEQ_DRAM_2__PLL_CLR_MASK 0x00000800L
+#define MC_SEQ_DRAM_2__PLL_CLR__SHIFT 0x0000000b
+#define MC_SEQ_DRAM_2__PLL_CNT_MASK 0x00ff0000L
+#define MC_SEQ_DRAM_2__PLL_CNT__SHIFT 0x00000010
+#define MC_SEQ_DRAM_2__PLL_EST_MASK 0x00000400L
+#define MC_SEQ_DRAM_2__PLL_EST__SHIFT 0x0000000a
+#define MC_SEQ_DRAM_2__RDAT_EDC_MASK 0x00000040L
+#define MC_SEQ_DRAM_2__RDAT_EDC__SHIFT 0x00000006
+#define MC_SEQ_DRAM_2__RD_DQS_MASK 0x00000100L
+#define MC_SEQ_DRAM_2__RD_DQS__SHIFT 0x00000008
+#define MC_SEQ_DRAM_2__TESTCHIP_EN_MASK 0x40000000L
+#define MC_SEQ_DRAM_2__TESTCHIP_EN__SHIFT 0x0000001e
+#define MC_SEQ_DRAM_2__TRI_CLK_MASK 0x00008000L
+#define MC_SEQ_DRAM_2__TRI_CLK__SHIFT 0x0000000f
+#define MC_SEQ_DRAM_2__WDAT_EDC_MASK 0x00000020L
+#define MC_SEQ_DRAM_2__WDAT_EDC__SHIFT 0x00000005
+#define MC_SEQ_DRAM_2__WR_DQS_MASK 0x00000200L
+#define MC_SEQ_DRAM_2__WR_DQS__SHIFT 0x00000009
+#define MC_SEQ_DRAM__ADR_2CK_MASK 0x00000001L
+#define MC_SEQ_DRAM__ADR_2CK__SHIFT 0x00000000
+#define MC_SEQ_DRAM__ADR_DF1_MASK 0x00000004L
+#define MC_SEQ_DRAM__ADR_DF1__SHIFT 0x00000002
+#define MC_SEQ_DRAM__ADR_MUX_MASK 0x00000002L
+#define MC_SEQ_DRAM__ADR_MUX__SHIFT 0x00000001
+#define MC_SEQ_DRAM__AP8_MASK 0x00000008L
+#define MC_SEQ_DRAM__AP8__SHIFT 0x00000003
+#define MC_SEQ_DRAM__BO4_MASK 0x00004000L
+#define MC_SEQ_DRAM__BO4__SHIFT 0x0000000e
+#define MC_SEQ_DRAM__CKE_ACT_MASK 0x00002000L
+#define MC_SEQ_DRAM__CKE_ACT__SHIFT 0x0000000d
+#define MC_SEQ_DRAM__CKE_DYN_MASK 0x00001000L
+#define MC_SEQ_DRAM__CKE_DYN__SHIFT 0x0000000c
+#define MC_SEQ_DRAM__DAT_DF1_MASK 0x00000010L
+#define MC_SEQ_DRAM__DAT_DF1__SHIFT 0x00000004
+#define MC_SEQ_DRAM__DAT_INV_MASK 0x01000000L
+#define MC_SEQ_DRAM__DAT_INV__SHIFT 0x00000018
+#define MC_SEQ_DRAM__DLL_CLR_MASK 0x00008000L
+#define MC_SEQ_DRAM__DLL_CLR__SHIFT 0x0000000f
+#define MC_SEQ_DRAM__DLL_CNT_MASK 0x00ff0000L
+#define MC_SEQ_DRAM__DLL_CNT__SHIFT 0x00000010
+#define MC_SEQ_DRAM__DQM_ACT_MASK 0x00000080L
+#define MC_SEQ_DRAM__DQM_ACT__SHIFT 0x00000007
+#define MC_SEQ_DRAM__DQM_DF1_MASK 0x00000040L
+#define MC_SEQ_DRAM__DQM_DF1__SHIFT 0x00000006
+#define MC_SEQ_DRAM__DQS_DF1_MASK 0x00000020L
+#define MC_SEQ_DRAM__DQS_DF1__SHIFT 0x00000005
+#define MC_SEQ_DRAM_ERROR_INSERTION__RX_MASK 0xffff0000L
+#define MC_SEQ_DRAM_ERROR_INSERTION__RX__SHIFT 0x00000010
+#define MC_SEQ_DRAM_ERROR_INSERTION__TX_MASK 0x0000ffffL
+#define MC_SEQ_DRAM_ERROR_INSERTION__TX__SHIFT 0x00000000
+#define MC_SEQ_DRAM__INV_ACM_MASK 0x02000000L
+#define MC_SEQ_DRAM__INV_ACM__SHIFT 0x00000019
+#define MC_SEQ_DRAM__ODT_ACT_MASK 0x08000000L
+#define MC_SEQ_DRAM__ODT_ACT__SHIFT 0x0000001b
+#define MC_SEQ_DRAM__ODT_ENB_MASK 0x04000000L
+#define MC_SEQ_DRAM__ODT_ENB__SHIFT 0x0000001a
+#define MC_SEQ_DRAM__RST_CTL_MASK 0x10000000L
+#define MC_SEQ_DRAM__RST_CTL__SHIFT 0x0000001c
+#define MC_SEQ_DRAM__STB_CNT_MASK 0x00000f00L
+#define MC_SEQ_DRAM__STB_CNT__SHIFT 0x00000008
+#define MC_SEQ_DRAM__TRI_CKE_MASK 0x40000000L
+#define MC_SEQ_DRAM__TRI_CKE__SHIFT 0x0000001e
+#define MC_SEQ_DRAM__TRI_MIO_DYN_MASK 0x20000000L
+#define MC_SEQ_DRAM__TRI_MIO_DYN__SHIFT 0x0000001d
+#define MC_SEQ_FIFO_CTL__CG_DIS_D0_MASK 0x00000100L
+#define MC_SEQ_FIFO_CTL__CG_DIS_D0__SHIFT 0x00000008
+#define MC_SEQ_FIFO_CTL__CG_DIS_D1_MASK 0x00000200L
+#define MC_SEQ_FIFO_CTL__CG_DIS_D1__SHIFT 0x00000009
+#define MC_SEQ_FIFO_CTL__R_LD_INIT_MASK 0x00000030L
+#define MC_SEQ_FIFO_CTL__R_LD_INIT__SHIFT 0x00000004
+#define MC_SEQ_FIFO_CTL__R_SYC_SEL_MASK 0x000000c0L
+#define MC_SEQ_FIFO_CTL__R_SYC_SEL__SHIFT 0x00000006
+#define MC_SEQ_FIFO_CTL__SYC_DLY_MASK 0x00007000L
+#define MC_SEQ_FIFO_CTL__SYC_DLY__SHIFT 0x0000000c
+#define MC_SEQ_FIFO_CTL__W_ASYC_EXT_MASK 0x00030000L
+#define MC_SEQ_FIFO_CTL__W_ASYC_EXT__SHIFT 0x00000010
+#define MC_SEQ_FIFO_CTL__W_DSYC_EXT_MASK 0x000c0000L
+#define MC_SEQ_FIFO_CTL__W_DSYC_EXT__SHIFT 0x00000012
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D0_MASK 0x00000003L
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D0__SHIFT 0x00000000
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D1_MASK 0x00000c00L
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D1__SHIFT 0x0000000a
+#define MC_SEQ_FIFO_CTL__W_SYC_SEL_MASK 0x0000000cL
+#define MC_SEQ_FIFO_CTL__W_SYC_SEL__SHIFT 0x00000002
+#define MC_SEQ_IO_DEBUG_DATA__IO_DEBUG_DATA_MASK 0xffffffffL
+#define MC_SEQ_IO_DEBUG_DATA__IO_DEBUG_DATA__SHIFT 0x00000000
+#define MC_SEQ_IO_DEBUG_INDEX__IO_DEBUG_INDEX_MASK 0x000001ffL
+#define MC_SEQ_IO_DEBUG_INDEX__IO_DEBUG_INDEX__SHIFT 0x00000000
+#define MC_SEQ_IO_RDBI__MASK_MASK 0xffffffffL
+#define MC_SEQ_IO_RDBI__MASK__SHIFT 0x00000000
+#define MC_SEQ_IO_REDC__EDC_MASK 0xffffffffL
+#define MC_SEQ_IO_REDC__EDC__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D0__APHY_RSV_MASK 0xff000000L
+#define MC_SEQ_IO_RESERVE_D0__APHY_RSV__SHIFT 0x00000018
+#define MC_SEQ_IO_RESERVE_D0__DPHY0_RSV_MASK 0x00000fffL
+#define MC_SEQ_IO_RESERVE_D0__DPHY0_RSV__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D0__DPHY1_RSV_MASK 0x00fff000L
+#define MC_SEQ_IO_RESERVE_D0__DPHY1_RSV__SHIFT 0x0000000c
+#define MC_SEQ_IO_RESERVE_D1__APHY_RSV_MASK 0xff000000L
+#define MC_SEQ_IO_RESERVE_D1__APHY_RSV__SHIFT 0x00000018
+#define MC_SEQ_IO_RESERVE_D1__DPHY0_RSV_MASK 0x00000fffL
+#define MC_SEQ_IO_RESERVE_D1__DPHY0_RSV__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D1__DPHY1_RSV_MASK 0x00fff000L
+#define MC_SEQ_IO_RESERVE_D1__DPHY1_RSV__SHIFT 0x0000000c
+#define MC_SEQ_IO_RWORD0__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD0__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD1__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD1__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD2__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD2__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD3__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD3__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD4__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD4__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD5__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD5__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD6__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD6__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD7__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD7__RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC3__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC3__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC4__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC4__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC5__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC5__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC6__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC6__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC7__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC7__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC8__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC8__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC9__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC9__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2__FAW_MASK 0x00001f00L
+#define MC_SEQ_MISC_TIMING2__FAW__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING2_LP__FAW_MASK 0x00001f00L
+#define MC_SEQ_MISC_TIMING2_LP__FAW__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING2_LP__PA2RDATA_MASK 0x00000007L
+#define MC_SEQ_MISC_TIMING2_LP__PA2RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2_LP__PA2WDATA_MASK 0x00000070L
+#define MC_SEQ_MISC_TIMING2_LP__PA2WDATA__SHIFT 0x00000004
+#define MC_SEQ_MISC_TIMING2_LP__TADR_MASK 0x00e00000L
+#define MC_SEQ_MISC_TIMING2_LP__TADR__SHIFT 0x00000015
+#define MC_SEQ_MISC_TIMING2_LP__TFCKTR_MASK 0x0f000000L
+#define MC_SEQ_MISC_TIMING2_LP__TFCKTR__SHIFT 0x00000018
+#define MC_SEQ_MISC_TIMING2_LP__TREDC_MASK 0x0000e000L
+#define MC_SEQ_MISC_TIMING2_LP__TREDC__SHIFT 0x0000000d
+#define MC_SEQ_MISC_TIMING2_LP__TWDATATR_MASK 0xf0000000L
+#define MC_SEQ_MISC_TIMING2_LP__TWDATATR__SHIFT 0x0000001c
+#define MC_SEQ_MISC_TIMING2_LP__TWEDC_MASK 0x001f0000L
+#define MC_SEQ_MISC_TIMING2_LP__TWEDC__SHIFT 0x00000010
+#define MC_SEQ_MISC_TIMING2__PA2RDATA_MASK 0x00000007L
+#define MC_SEQ_MISC_TIMING2__PA2RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2__PA2WDATA_MASK 0x00000070L
+#define MC_SEQ_MISC_TIMING2__PA2WDATA__SHIFT 0x00000004
+#define MC_SEQ_MISC_TIMING2__T32AW_MASK 0x01e00000L
+#define MC_SEQ_MISC_TIMING2__T32AW__SHIFT 0x00000015
+#define MC_SEQ_MISC_TIMING2__TREDC_MASK 0x0000e000L
+#define MC_SEQ_MISC_TIMING2__TREDC__SHIFT 0x0000000d
+#define MC_SEQ_MISC_TIMING2__TWDATATR_MASK 0xf0000000L
+#define MC_SEQ_MISC_TIMING2__TWDATATR__SHIFT 0x0000001c
+#define MC_SEQ_MISC_TIMING2__TWEDC_MASK 0x001f0000L
+#define MC_SEQ_MISC_TIMING2__TWEDC__SHIFT 0x00000010
+#define MC_SEQ_MISC_TIMING_LP__TRFC_MASK 0x1ff00000L
+#define MC_SEQ_MISC_TIMING_LP__TRFC__SHIFT 0x00000014
+#define MC_SEQ_MISC_TIMING_LP__TRP_MASK 0x000f8000L
+#define MC_SEQ_MISC_TIMING_LP__TRP_RDA_MASK 0x00003f00L
+#define MC_SEQ_MISC_TIMING_LP__TRP_RDA__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING_LP__TRP__SHIFT 0x0000000f
+#define MC_SEQ_MISC_TIMING_LP__TRP_WRA_MASK 0x0000003fL
+#define MC_SEQ_MISC_TIMING_LP__TRP_WRA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING__TRFC_MASK 0x1ff00000L
+#define MC_SEQ_MISC_TIMING__TRFC__SHIFT 0x00000014
+#define MC_SEQ_MISC_TIMING__TRP_MASK 0x000f8000L
+#define MC_SEQ_MISC_TIMING__TRP_RDA_MASK 0x00003f00L
+#define MC_SEQ_MISC_TIMING__TRP_RDA__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING__TRP__SHIFT 0x0000000f
+#define MC_SEQ_MISC_TIMING__TRP_WRA_MASK 0x0000003fL
+#define MC_SEQ_MISC_TIMING__TRP_WRA__SHIFT 0x00000000
+#define MC_SEQ_MPLL_OVERRIDE__AD_PLL_RESET_OVERRIDE_MASK 0x00000001L
+#define MC_SEQ_MPLL_OVERRIDE__AD_PLL_RESET_OVERRIDE__SHIFT 0x00000000
+#define MC_SEQ_MPLL_OVERRIDE__ATGM_CLK_SEL_OVERRIDE_MASK 0x00000020L
+#define MC_SEQ_MPLL_OVERRIDE__ATGM_CLK_SEL_OVERRIDE__SHIFT 0x00000005
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_0_PLL_RESET_OVERRIDE_MASK 0x00000002L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_0_PLL_RESET_OVERRIDE__SHIFT 0x00000001
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_1_PLL_RESET_OVERRIDE_MASK 0x00000004L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_1_PLL_RESET_OVERRIDE__SHIFT 0x00000002
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_0_PLL_RESET_OVERRIDE_MASK 0x00000008L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_0_PLL_RESET_OVERRIDE__SHIFT 0x00000003
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_1_PLL_RESET_OVERRIDE_MASK 0x00000010L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_1_PLL_RESET_OVERRIDE__SHIFT 0x00000004
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_EN_OVERRIDE_MASK 0x00000040L
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_EN_OVERRIDE__SHIFT 0x00000006
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_SEL_OVERRIDE_MASK 0x00000080L
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_SEL_OVERRIDE__SHIFT 0x00000007
+#define MC_SEQ_PERF_CNTL_1__PAUSE_MASK 0x00000001L
+#define MC_SEQ_PERF_CNTL_1__PAUSE__SHIFT 0x00000000
+#define MC_SEQ_PERF_CNTL_1__SEL_A_MSB_MASK 0x00000100L
+#define MC_SEQ_PERF_CNTL_1__SEL_A_MSB__SHIFT 0x00000008
+#define MC_SEQ_PERF_CNTL_1__SEL_B_MSB_MASK 0x00000200L
+#define MC_SEQ_PERF_CNTL_1__SEL_B_MSB__SHIFT 0x00000009
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_C_MSB_MASK 0x00000400L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_C_MSB__SHIFT 0x0000000a
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_D_MSB_MASK 0x00000800L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_D_MSB__SHIFT 0x0000000b
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_A_MSB_MASK 0x00001000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_A_MSB__SHIFT 0x0000000c
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_B_MSB_MASK 0x00002000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_B_MSB__SHIFT 0x0000000d
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_C_MSB_MASK 0x00004000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_C_MSB__SHIFT 0x0000000e
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_D_MSB_MASK 0x00008000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_D_MSB__SHIFT 0x0000000f
+#define MC_SEQ_PERF_CNTL__CNTL_MASK 0xc0000000L
+#define MC_SEQ_PERF_CNTL__CNTL__SHIFT 0x0000001e
+#define MC_SEQ_PERF_CNTL__MONITOR_PERIOD_MASK 0x3fffffffL
+#define MC_SEQ_PERF_CNTL__MONITOR_PERIOD__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_A_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_A_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_A_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_A_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_B_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_B_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_B_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_B_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_C_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_C_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_C_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_C_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_D_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_D_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_D_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_D_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CTL__SEL_A_MASK 0x0000000fL
+#define MC_SEQ_PERF_SEQ_CTL__SEL_A__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CTL__SEL_B_MASK 0x000000f0L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_B__SHIFT 0x00000004
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_C_MASK 0x00000f00L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_C__SHIFT 0x00000008
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_D_MASK 0x0000f000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_D__SHIFT 0x0000000c
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_A_MASK 0x000f0000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_A__SHIFT 0x00000010
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_B_MASK 0x00f00000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_B__SHIFT 0x00000014
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_C_MASK 0x0f000000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_C__SHIFT 0x00000018
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_D_MASK 0xf0000000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_D__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_EMRS_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_EMRS_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_EMRS_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_EMRS_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS1_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS1_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS1_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS1_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS2_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS2_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS2_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS2_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_HWCNTL__ACAO_MASK 0x00040000L
+#define MC_SEQ_PMG_PG_HWCNTL__ACAO__SHIFT 0x00000012
+#define MC_SEQ_PMG_PG_HWCNTL__AC_DLY_MASK 0x00000300L
+#define MC_SEQ_PMG_PG_HWCNTL__AC_DLY__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_HWCNTL__D_DLY_MASK 0x000000c0L
+#define MC_SEQ_PMG_PG_HWCNTL__D_DLY__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_HWCNTL__G_DLY_MASK 0x00003c00L
+#define MC_SEQ_PMG_PG_HWCNTL__G_DLY__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_HWCNTL__PWRGATE_EN_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_HWCNTL__PWRGATE_EN__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_HWCNTL__RXAO_MASK 0x00020000L
+#define MC_SEQ_PMG_PG_HWCNTL__RXAO__SHIFT 0x00000011
+#define MC_SEQ_PMG_PG_HWCNTL__STAGGER_EN_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_HWCNTL__STAGGER_EN__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_HWCNTL__TPGCG_MASK 0x0000003cL
+#define MC_SEQ_PMG_PG_HWCNTL__TPGCG__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_HWCNTL__TXAO_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_HWCNTL__TXAO__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_0__GMCON_SR_COMMIT_MASK 0x80000000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__GMCON_SR_COMMIT__SHIFT 0x0000001f
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMA0_AC_ENB_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMA0_AC_ENB__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_RX_ENB_MASK 0x00000020L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_RX_ENB__SHIFT 0x00000005
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_TX_ENB_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_TX_ENB__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_RX_ENB_MASK 0x00000010L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_RX_ENB__SHIFT 0x00000004
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_TX_ENB_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_TX_ENB__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_RX_ENB_MASK 0x00000040L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_RX_ENB__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_TX_ENB_MASK 0x00000004L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_TX_ENB__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_RX_ENB_MASK 0x00000080L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_RX_ENB__SHIFT 0x00000007
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_TX_ENB_MASK 0x00000008L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_TX_ENB__SHIFT 0x00000003
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_RX_ENB_MASK 0x00002000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_RX_ENB__SHIFT 0x0000000d
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_TX_ENB_MASK 0x00000200L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_TX_ENB__SHIFT 0x00000009
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_RX_ENB_MASK 0x00001000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_RX_ENB__SHIFT 0x0000000c
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_TX_ENB_MASK 0x00000100L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_TX_ENB__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_RX_ENB_MASK 0x00004000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_RX_ENB__SHIFT 0x0000000e
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_TX_ENB_MASK 0x00000400L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_TX_ENB__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_RX_ENB_MASK 0x00008000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_RX_ENB__SHIFT 0x0000000f
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_TX_ENB_MASK 0x00000800L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_TX_ENB__SHIFT 0x0000000b
+#define MC_SEQ_PMG_PG_SWCNTL_1__GMCON_SR_COMMIT_MASK 0x80000000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__GMCON_SR_COMMIT__SHIFT 0x0000001f
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMA1_AC_ENB_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMA1_AC_ENB__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_RX_ENB_MASK 0x00000020L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_RX_ENB__SHIFT 0x00000005
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_TX_ENB_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_TX_ENB__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_RX_ENB_MASK 0x00000010L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_RX_ENB__SHIFT 0x00000004
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_TX_ENB_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_TX_ENB__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_RX_ENB_MASK 0x00000040L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_RX_ENB__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_TX_ENB_MASK 0x00000004L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_TX_ENB__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_RX_ENB_MASK 0x00000080L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_RX_ENB__SHIFT 0x00000007
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_TX_ENB_MASK 0x00000008L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_TX_ENB__SHIFT 0x00000003
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_RX_ENB_MASK 0x00002000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_RX_ENB__SHIFT 0x0000000d
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_TX_ENB_MASK 0x00000200L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_TX_ENB__SHIFT 0x00000009
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_RX_ENB_MASK 0x00001000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_RX_ENB__SHIFT 0x0000000c
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_TX_ENB_MASK 0x00000100L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_TX_ENB__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_RX_ENB_MASK 0x00004000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_RX_ENB__SHIFT 0x0000000e
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_TX_ENB_MASK 0x00000400L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_TX_ENB__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_RX_ENB_MASK 0x00008000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_RX_ENB__SHIFT 0x0000000f
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_TX_ENB_MASK 0x00000800L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_TX_ENB__SHIFT 0x0000000b
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_MASK 0x001c0000L
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE__SHIFT 0x00000012
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_SS_MASK 0xff000000L
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_SS__SHIFT 0x00000018
+#define MC_SEQ_PMG_TIMING_LP__TCKE_MASK 0x0003f000L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MASK 0x00000f00L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MSB_MASK 0x00800000L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MSB__SHIFT 0x00000017
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE__SHIFT 0x00000008
+#define MC_SEQ_PMG_TIMING_LP__TCKE__SHIFT 0x0000000c
+#define MC_SEQ_PMG_TIMING_LP__TCKSRE_MASK 0x00000007L
+#define MC_SEQ_PMG_TIMING_LP__TCKSRE__SHIFT 0x00000000
+#define MC_SEQ_PMG_TIMING_LP__TCKSRX_MASK 0x00000070L
+#define MC_SEQ_PMG_TIMING_LP__TCKSRX__SHIFT 0x00000004
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_MASK 0x001c0000L
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE__SHIFT 0x00000012
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_SS_MASK 0xff000000L
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_SS__SHIFT 0x00000018
+#define MC_SEQ_PMG_TIMING__TCKE_MASK 0x0003f000L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MASK 0x00000f00L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MSB_MASK 0x00800000L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MSB__SHIFT 0x00000017
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE__SHIFT 0x00000008
+#define MC_SEQ_PMG_TIMING__TCKE__SHIFT 0x0000000c
+#define MC_SEQ_PMG_TIMING__TCKSRE_MASK 0x00000007L
+#define MC_SEQ_PMG_TIMING__TCKSRE__SHIFT 0x00000000
+#define MC_SEQ_PMG_TIMING__TCKSRX_MASK 0x00000070L
+#define MC_SEQ_PMG_TIMING__TCKSRX__SHIFT 0x00000004
+#define MC_SEQ_RAS_TIMING_LP__TRCDRA_MASK 0x000f8000L
+#define MC_SEQ_RAS_TIMING_LP__TRCDRA__SHIFT 0x0000000f
+#define MC_SEQ_RAS_TIMING_LP__TRCDR_MASK 0x00007c00L
+#define MC_SEQ_RAS_TIMING_LP__TRCDR__SHIFT 0x0000000a
+#define MC_SEQ_RAS_TIMING_LP__TRCDWA_MASK 0x000003e0L
+#define MC_SEQ_RAS_TIMING_LP__TRCDWA__SHIFT 0x00000005
+#define MC_SEQ_RAS_TIMING_LP__TRCDW_MASK 0x0000001fL
+#define MC_SEQ_RAS_TIMING_LP__TRCDW__SHIFT 0x00000000
+#define MC_SEQ_RAS_TIMING_LP__TRC_MASK 0x7f000000L
+#define MC_SEQ_RAS_TIMING_LP__TRC__SHIFT 0x00000018
+#define MC_SEQ_RAS_TIMING_LP__TRRD_MASK 0x00f00000L
+#define MC_SEQ_RAS_TIMING_LP__TRRD__SHIFT 0x00000014
+#define MC_SEQ_RAS_TIMING__TRCDRA_MASK 0x000f8000L
+#define MC_SEQ_RAS_TIMING__TRCDRA__SHIFT 0x0000000f
+#define MC_SEQ_RAS_TIMING__TRCDR_MASK 0x00007c00L
+#define MC_SEQ_RAS_TIMING__TRCDR__SHIFT 0x0000000a
+#define MC_SEQ_RAS_TIMING__TRCDWA_MASK 0x000003e0L
+#define MC_SEQ_RAS_TIMING__TRCDWA__SHIFT 0x00000005
+#define MC_SEQ_RAS_TIMING__TRCDW_MASK 0x0000001fL
+#define MC_SEQ_RAS_TIMING__TRCDW__SHIFT 0x00000000
+#define MC_SEQ_RAS_TIMING__TRC_MASK 0x7f000000L
+#define MC_SEQ_RAS_TIMING__TRC__SHIFT 0x00000018
+#define MC_SEQ_RAS_TIMING__TRRD_MASK 0x00f00000L
+#define MC_SEQ_RAS_TIMING__TRRD__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0_LP__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D0_LP__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0_LP__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D0_LP__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D0_LP__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D0_LP__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D0_LP__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D0_LP__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D0_LP__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D0_LP__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D0_LP__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D0_LP__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D0_LP__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D0_LP__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D0_LP__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D0_LP__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D0_LP__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D0_LP__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D0__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D0__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D0__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D0__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D0__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D0__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D0__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D0__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D0__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D0__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D0__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D0__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D0__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D0__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D0__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D0__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D0__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D1_LP__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D1_LP__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D1_LP__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D1_LP__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D1_LP__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D1_LP__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D1_LP__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D1_LP__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D1_LP__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D1_LP__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D1_LP__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D1_LP__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D1_LP__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D1_LP__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D1_LP__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D1_LP__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D1_LP__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D1_LP__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D1__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D1__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D1__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D1__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D1__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D1__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D1__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D1__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D1__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D1__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D1__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D1__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D1__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D1__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D1__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D1__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D1__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D1__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RESERVE_0_S__SCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_0_S__SCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RESERVE_1_S__SCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_1_S__SCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RESERVE_M__MCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_M__MCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_STATUS_M__CMD_RDY_D0_MASK 0x00000004L
+#define MC_SEQ_STATUS_M__CMD_RDY_D0__SHIFT 0x00000002
+#define MC_SEQ_STATUS_M__CMD_RDY_D1_MASK 0x00000008L
+#define MC_SEQ_STATUS_M__CMD_RDY_D1__SHIFT 0x00000003
+#define MC_SEQ_STATUS_M__PMG_FSMSTATE_MASK 0x01f00000L
+#define MC_SEQ_STATUS_M__PMG_FSMSTATE__SHIFT 0x00000014
+#define MC_SEQ_STATUS_M__PMG_PWRSTATE_MASK 0x00010000L
+#define MC_SEQ_STATUS_M__PMG_PWRSTATE__SHIFT 0x00000010
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D0_MASK 0x00000001L
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D0__SHIFT 0x00000000
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D1_MASK 0x00000002L
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D1__SHIFT 0x00000001
+#define MC_SEQ_STATUS_M__SEQ0_ARB_CMD_FIFO_EMPTY_MASK 0x00000100L
+#define MC_SEQ_STATUS_M__SEQ0_ARB_CMD_FIFO_EMPTY__SHIFT 0x00000008
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_HYS_MASK 0x02000000L
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_HYS__SHIFT 0x00000019
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_MASK 0x00004000L
+#define MC_SEQ_STATUS_M__SEQ0_BUSY__SHIFT 0x0000000e
+#define MC_SEQ_STATUS_M__SEQ0_RS_DATA_FIFO_FULL_MASK 0x00001000L
+#define MC_SEQ_STATUS_M__SEQ0_RS_DATA_FIFO_FULL__SHIFT 0x0000000c
+#define MC_SEQ_STATUS_M__SEQ1_ARB_CMD_FIFO_EMPTY_MASK 0x00000200L
+#define MC_SEQ_STATUS_M__SEQ1_ARB_CMD_FIFO_EMPTY__SHIFT 0x00000009
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_HYS_MASK 0x04000000L
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_HYS__SHIFT 0x0000001a
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_MASK 0x00008000L
+#define MC_SEQ_STATUS_M__SEQ1_BUSY__SHIFT 0x0000000f
+#define MC_SEQ_STATUS_M__SEQ1_RS_DATA_FIFO_FULL_MASK 0x00002000L
+#define MC_SEQ_STATUS_M__SEQ1_RS_DATA_FIFO_FULL__SHIFT 0x0000000d
+#define MC_SEQ_STATUS_M__SLF_D0_MASK 0x00000010L
+#define MC_SEQ_STATUS_M__SLF_D0__SHIFT 0x00000004
+#define MC_SEQ_STATUS_M__SLF_D1_MASK 0x00000020L
+#define MC_SEQ_STATUS_M__SLF_D1__SHIFT 0x00000005
+#define MC_SEQ_STATUS_M__SS_SLF_D0_MASK 0x00000040L
+#define MC_SEQ_STATUS_M__SS_SLF_D0__SHIFT 0x00000006
+#define MC_SEQ_STATUS_M__SS_SLF_D1_MASK 0x00000080L
+#define MC_SEQ_STATUS_M__SS_SLF_D1__SHIFT 0x00000007
+#define MC_SEQ_STATUS_S__SEQ0_ARB_CMD_FIFO_FULL_MASK 0x00000010L
+#define MC_SEQ_STATUS_S__SEQ0_ARB_CMD_FIFO_FULL__SHIFT 0x00000004
+#define MC_SEQ_STATUS_S__SEQ0_ARB_DATA_FIFO_FULL_MASK 0x00000001L
+#define MC_SEQ_STATUS_S__SEQ0_ARB_DATA_FIFO_FULL__SHIFT 0x00000000
+#define MC_SEQ_STATUS_S__SEQ0_RS_DATA_FIFO_EMPTY_MASK 0x00000100L
+#define MC_SEQ_STATUS_S__SEQ0_RS_DATA_FIFO_EMPTY__SHIFT 0x00000008
+#define MC_SEQ_STATUS_S__SEQ1_ARB_CMD_FIFO_FULL_MASK 0x00000020L
+#define MC_SEQ_STATUS_S__SEQ1_ARB_CMD_FIFO_FULL__SHIFT 0x00000005
+#define MC_SEQ_STATUS_S__SEQ1_ARB_DATA_FIFO_FULL_MASK 0x00000002L
+#define MC_SEQ_STATUS_S__SEQ1_ARB_DATA_FIFO_FULL__SHIFT 0x00000001
+#define MC_SEQ_STATUS_S__SEQ1_RS_DATA_FIFO_EMPTY_MASK 0x00000200L
+#define MC_SEQ_STATUS_S__SEQ1_RS_DATA_FIFO_EMPTY__SHIFT 0x00000009
+#define MC_SEQ_SUP_CNTL__BKPT_CLEAR_MASK 0x00000080L
+#define MC_SEQ_SUP_CNTL__BKPT_CLEAR__SHIFT 0x00000007
+#define MC_SEQ_SUP_CNTL__FAST_WRITE_MASK 0x00000040L
+#define MC_SEQ_SUP_CNTL__FAST_WRITE__SHIFT 0x00000006
+#define MC_SEQ_SUP_CNTL__PGM_CHKSUM_MASK 0xff800000L
+#define MC_SEQ_SUP_CNTL__PGM_CHKSUM__SHIFT 0x00000017
+#define MC_SEQ_SUP_CNTL__PGM_READ_MASK 0x00000020L
+#define MC_SEQ_SUP_CNTL__PGM_READ__SHIFT 0x00000005
+#define MC_SEQ_SUP_CNTL__PGM_WRITE_MASK 0x00000010L
+#define MC_SEQ_SUP_CNTL__PGM_WRITE__SHIFT 0x00000004
+#define MC_SEQ_SUP_CNTL__RESET_PC_MASK 0x00000008L
+#define MC_SEQ_SUP_CNTL__RESET_PC__SHIFT 0x00000003
+#define MC_SEQ_SUP_CNTL__RUN_MASK 0x00000001L
+#define MC_SEQ_SUP_CNTL__RUN__SHIFT 0x00000000
+#define MC_SEQ_SUP_CNTL__SINGLE_STEP_MASK 0x00000002L
+#define MC_SEQ_SUP_CNTL__SINGLE_STEP__SHIFT 0x00000001
+#define MC_SEQ_SUP_CNTL__SW_WAKE_MASK 0x00000004L
+#define MC_SEQ_SUP_CNTL__SW_WAKE__SHIFT 0x00000002
+#define MC_SEQ_SUP_DEC_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_DEC_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP0_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP0_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP1_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP1_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP2_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP2_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP3_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP3_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_IR_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_IR_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_PGM__CNTL_MASK 0xffffffffL
+#define MC_SEQ_SUP_PGM__CNTL__SHIFT 0x00000000
+#define MC_SEQ_SUP_PGM_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_PGM_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_R_PGM__PGM_MASK 0xffffffffL
+#define MC_SEQ_SUP_R_PGM__PGM__SHIFT 0x00000000
+#define MC_SEQ_TCG_CNTL__AREF_BOTH_MASK 0x04000000L
+#define MC_SEQ_TCG_CNTL__AREF_BOTH__SHIFT 0x0000001a
+#define MC_SEQ_TCG_CNTL__AREF_LAST_MASK 0x02000000L
+#define MC_SEQ_TCG_CNTL__AREF_LAST__SHIFT 0x00000019
+#define MC_SEQ_TCG_CNTL__BURST_NUM_MASK 0x00380000L
+#define MC_SEQ_TCG_CNTL__BURST_NUM__SHIFT 0x00000013
+#define MC_SEQ_TCG_CNTL__DATA_CNT_MASK 0x0000f000L
+#define MC_SEQ_TCG_CNTL__DATA_CNT__SHIFT 0x0000000c
+#define MC_SEQ_TCG_CNTL__DONE_MASK 0x80000000L
+#define MC_SEQ_TCG_CNTL__DONE__SHIFT 0x0000001f
+#define MC_SEQ_TCG_CNTL__ENABLE_D0_MASK 0x00000002L
+#define MC_SEQ_TCG_CNTL__ENABLE_D0__SHIFT 0x00000001
+#define MC_SEQ_TCG_CNTL__ENABLE_D1_MASK 0x00000004L
+#define MC_SEQ_TCG_CNTL__ENABLE_D1__SHIFT 0x00000002
+#define MC_SEQ_TCG_CNTL__FRAME_TRAIN_MASK 0x00040000L
+#define MC_SEQ_TCG_CNTL__FRAME_TRAIN__SHIFT 0x00000012
+#define MC_SEQ_TCG_CNTL__INFINITE_CMD_MASK 0x00000080L
+#define MC_SEQ_TCG_CNTL__INFINITE_CMD__SHIFT 0x00000007
+#define MC_SEQ_TCG_CNTL__ISSUE_AREF_MASK 0x00400000L
+#define MC_SEQ_TCG_CNTL__ISSUE_AREF__SHIFT 0x00000016
+#define MC_SEQ_TCG_CNTL__LOAD_FIFO_MASK 0x00010000L
+#define MC_SEQ_TCG_CNTL__LOAD_FIFO__SHIFT 0x00000010
+#define MC_SEQ_TCG_CNTL__MOP_MASK 0x00000f00L
+#define MC_SEQ_TCG_CNTL__MOP__SHIFT 0x00000008
+#define MC_SEQ_TCG_CNTL__NFIFO_MASK 0x00000070L
+#define MC_SEQ_TCG_CNTL__NFIFO__SHIFT 0x00000004
+#define MC_SEQ_TCG_CNTL__RESET_MASK 0x00000001L
+#define MC_SEQ_TCG_CNTL__RESET__SHIFT 0x00000000
+#define MC_SEQ_TCG_CNTL__SHORT_LDFF_MASK 0x00020000L
+#define MC_SEQ_TCG_CNTL__SHORT_LDFF__SHIFT 0x00000011
+#define MC_SEQ_TCG_CNTL__START_MASK 0x00000008L
+#define MC_SEQ_TCG_CNTL__START__SHIFT 0x00000003
+#define MC_SEQ_TCG_CNTL__TXDBI_CNTL_MASK 0x00800000L
+#define MC_SEQ_TCG_CNTL__TXDBI_CNTL__SHIFT 0x00000017
+#define MC_SEQ_TCG_CNTL__VPTR_MASK_MASK 0x01000000L
+#define MC_SEQ_TCG_CNTL__VPTR_MASK__SHIFT 0x00000018
+#define MC_SEQ_TIMER_RD__COUNTER_MASK 0xffffffffL
+#define MC_SEQ_TIMER_RD__COUNTER__SHIFT 0x00000000
+#define MC_SEQ_TIMER_WR__COUNTER_MASK 0xffffffffL
+#define MC_SEQ_TIMER_WR__COUNTER__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_CAPTURE__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_CAPTURE__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_CAPTURE__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_CAPTURE__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_CAPTURE__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_CAPTURE__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_CAPTURE__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_CAPTURE__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_CAPTURE__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_CAPTURE__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_CAPTURE__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_CAPTURE__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_CAPTURE__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_CAPTURE__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_CAPTURE__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_CAPTURE__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_CAPTURE__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_CAPTURE__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_CAPTURE__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_CAPTURE__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_CAPTURE__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_CAPTURE__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_CAPTURE__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_CAPTURE__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_CAPTURE__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_CAPTURE__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_CAPTURE__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_CAPTURE__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_CAPTURE__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_CAPTURE__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_CAPTURE__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_CAPTURE__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_CAPTURE__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_CAPTURE__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_CAPTURE__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_CAPTURE__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_CAPTURE__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_CAPTURE__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_CAPTURE__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_CAPTURE__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_CAPTURE__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_CAPTURE__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_CAPTURE__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_CAPTURE__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_EDC_THRESHOLD2__THRESHOLD_PERIOD_MASK 0xffffffffL
+#define MC_SEQ_TRAIN_EDC_THRESHOLD2__THRESHOLD_PERIOD__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_IN_PROGRESS_MASK 0x00000100L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_IN_PROGRESS__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_STATUS_MASK 0x00000001L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_STATUS__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_IN_PROGRESS_MASK 0x00000200L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_IN_PROGRESS__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_STATUS_MASK 0x00000002L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_STATUS__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CLEAR_RETRAIN_STATUS_MASK 0x00000004L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CLEAR_RETRAIN_STATUS__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_MONITOR_MASK 0x00000030L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_MONITOR__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_VBI_MASK 0x00000008L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_VBI__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__READ_EDC_THRESHOLD_MASK 0xffff0000L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__READ_EDC_THRESHOLD__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__WRITE_EDC_THRESHOLD_MASK 0x0000ffffL
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__WRITE_EDC_THRESHOLD__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_TIMING__TARF2T_MASK 0x000003e0L
+#define MC_SEQ_TRAIN_TIMING__TARF2T__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_TIMING__TLD2LD_MASK 0x000f8000L
+#define MC_SEQ_TRAIN_TIMING__TLD2LD__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_TIMING__TT2ROW_MASK 0x00007c00L
+#define MC_SEQ_TRAIN_TIMING__TT2ROW__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_TIMING__TWT2RT_MASK 0x0000001fL
+#define MC_SEQ_TRAIN_TIMING__TWT2RT__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__CLEARALL_MASK 0x00010000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__CLEARALL__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_ADDR_TRAIN_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_ADDR_TRAIN__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_READ_TRAIN_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_READ_TRAIN__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WAKEUP_EARLY_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WAKEUP_EARLY__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WCK_TRAIN_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WCK_TRAIN__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WRITE_TRAIN_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WRITE_TRAIN__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D0_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D0__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D1_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D1__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D0_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D0__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D1_MASK 0x08000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D1__SHIFT 0x0000001b
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_ADDR_TRAIN_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_ADDR_TRAIN__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_READ_TRAIN_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_READ_TRAIN__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WCK_TRAIN_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WCK_TRAIN__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WRITE_TRAIN_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WRITE_TRAIN__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__DISP_ASTOP_WAKEUP_MASK 0x20000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__DISP_ASTOP_WAKEUP__SHIFT 0x0000001d
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_ADDR_TRAIN_MASK 0x00010000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_ADDR_TRAIN__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_READ_TRAIN_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_READ_TRAIN__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WCK_TRAIN_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WCK_TRAIN__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WRITE_TRAIN_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WRITE_TRAIN__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_ADDR_TRAIN_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_ADDR_TRAIN__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_READ_TRAIN_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_READ_TRAIN__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WCK_TRAIN_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WCK_TRAIN__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WRITE_TRAIN_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WRITE_TRAIN__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D0_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D0__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D1_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D1__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SW_WAKEUP_MASK 0x10000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SW_WAKEUP__SHIFT 0x0000001c
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0_MASK 0x40000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0__SHIFT 0x0000001e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1_MASK 0x80000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1__SHIFT 0x0000001f
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_ADDR_TRAIN_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_ADDR_TRAIN__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_READ_TRAIN_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_READ_TRAIN__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WCK_TRAIN_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WCK_TRAIN__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WRITE_TRAIN_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WRITE_TRAIN__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_MASK__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_MASK__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_MASK__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TSM_BCNT__BCNT_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_BCNT__BCNT_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_BCNT__COMP_VALUE_MASK 0x00ff0000L
+#define MC_SEQ_TSM_BCNT__COMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_BCNT__DONE_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_BCNT__DONE_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_BCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_BCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_BCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_BCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_CTRL__CAPTURE_START_MASK 0x00000002L
+#define MC_SEQ_TSM_CTRL__CAPTURE_START__SHIFT 0x00000001
+#define MC_SEQ_TSM_CTRL__DIRECTION_MASK 0x00000020L
+#define MC_SEQ_TSM_CTRL__DIRECTION__SHIFT 0x00000005
+#define MC_SEQ_TSM_CTRL__DONE_MASK 0x00000004L
+#define MC_SEQ_TSM_CTRL__DONE__SHIFT 0x00000002
+#define MC_SEQ_TSM_CTRL__ERR_MASK 0x00000008L
+#define MC_SEQ_TSM_CTRL__ERR__SHIFT 0x00000003
+#define MC_SEQ_TSM_CTRL__INVERT_MASK 0x00000040L
+#define MC_SEQ_TSM_CTRL__INVERT__SHIFT 0x00000006
+#define MC_SEQ_TSM_CTRL__MASK_BITS_MASK 0x00000080L
+#define MC_SEQ_TSM_CTRL__MASK_BITS__SHIFT 0x00000007
+#define MC_SEQ_TSM_CTRL__POINTER_MASK 0xffff0000L
+#define MC_SEQ_TSM_CTRL__POINTER__SHIFT 0x00000010
+#define MC_SEQ_TSM_CTRL__ROT_INV_MASK 0x00000400L
+#define MC_SEQ_TSM_CTRL__ROT_INV__SHIFT 0x0000000a
+#define MC_SEQ_TSM_CTRL__START_MASK 0x00000001L
+#define MC_SEQ_TSM_CTRL__START__SHIFT 0x00000000
+#define MC_SEQ_TSM_CTRL__STEP_MASK 0x00000010L
+#define MC_SEQ_TSM_CTRL__STEP__SHIFT 0x00000004
+#define MC_SEQ_TSM_CTRL__UPDATE_LOOP_MASK 0x00000300L
+#define MC_SEQ_TSM_CTRL__UPDATE_LOOP__SHIFT 0x00000008
+#define MC_SEQ_TSM_DBI__DBI_MASK 0xffffffffL
+#define MC_SEQ_TSM_DBI__DBI__SHIFT 0x00000000
+#define MC_SEQ_TSM_DEBUG_DATA__TSM_DEBUG_DATA_MASK 0xffffffffL
+#define MC_SEQ_TSM_DEBUG_DATA__TSM_DEBUG_DATA__SHIFT 0x00000000
+#define MC_SEQ_TSM_DEBUG_INDEX__TSM_DEBUG_INDEX_MASK 0x0000001fL
+#define MC_SEQ_TSM_DEBUG_INDEX__TSM_DEBUG_INDEX__SHIFT 0x00000000
+#define MC_SEQ_TSM_EDC__EDC_MASK 0xffffffffL
+#define MC_SEQ_TSM_EDC__EDC__SHIFT 0x00000000
+#define MC_SEQ_TSM_FLAG__ERROR_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_FLAG__ERROR_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_FLAG__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_FLAG__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_FLAG__FLAG_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_FLAG__FLAG_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_FLAG__NBBL_MASK_MASK 0x000f0000L
+#define MC_SEQ_TSM_FLAG__NBBL_MASK__SHIFT 0x00000010
+#define MC_SEQ_TSM_FLAG__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_FLAG__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_GCNT__COMP_VALUE_MASK 0xffff0000L
+#define MC_SEQ_TSM_GCNT__COMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_GCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_GCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_GCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_GCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_GCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_GCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_MISC__WCDR_MASK_MASK 0x000f0000L
+#define MC_SEQ_TSM_MISC__WCDR_MASK__SHIFT 0x00000010
+#define MC_SEQ_TSM_MISC__WCDR_PTR_MASK 0x0000ffffL
+#define MC_SEQ_TSM_MISC__WCDR_PTR__SHIFT 0x00000000
+#define MC_SEQ_TSM_NCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_NCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_NCNT__NIBBLE_SKIP_MASK 0x0f000000L
+#define MC_SEQ_TSM_NCNT__NIBBLE_SKIP__SHIFT 0x00000018
+#define MC_SEQ_TSM_NCNT__RANGE_HIGH_MASK 0x00f00000L
+#define MC_SEQ_TSM_NCNT__RANGE_HIGH__SHIFT 0x00000014
+#define MC_SEQ_TSM_NCNT__RANGE_LOW_MASK 0x000f0000L
+#define MC_SEQ_TSM_NCNT__RANGE_LOW__SHIFT 0x00000010
+#define MC_SEQ_TSM_NCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_NCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_NCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_NCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_OCNT__CMP_VALUE_MASK 0xffff0000L
+#define MC_SEQ_TSM_OCNT__CMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_OCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_OCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_OCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_OCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_OCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_OCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_UPDATE__AREF_COUNT_MASK 0x00ff0000L
+#define MC_SEQ_TSM_UPDATE__AREF_COUNT__SHIFT 0x00000010
+#define MC_SEQ_TSM_UPDATE__CAPTR_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_UPDATE__CAPTR_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_UPDATE__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_UPDATE__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_UPDATE__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_UPDATE__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_UPDATE__UPDT_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_UPDATE__UPDT_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_WCDR__WCDR_MASK 0xffffffffL
+#define MC_SEQ_TSM_WCDR__WCDR__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK3__SHIFT 0x0000000c
+#define MC_SEQ_VENDOR_ID_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_VENDOR_ID_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_VENDOR_ID_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_VENDOR_ID_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_WCDR_CTRL__AREF_EN_MASK 0x00004000L
+#define MC_SEQ_WCDR_CTRL__AREF_EN__SHIFT 0x0000000e
+#define MC_SEQ_WCDR_CTRL__PRBS_EN_MASK 0x00100000L
+#define MC_SEQ_WCDR_CTRL__PRBS_EN__SHIFT 0x00000014
+#define MC_SEQ_WCDR_CTRL__PRBS_RST_MASK 0x00200000L
+#define MC_SEQ_WCDR_CTRL__PRBS_RST__SHIFT 0x00000015
+#define MC_SEQ_WCDR_CTRL__PREAMBLE_MASK 0x0f000000L
+#define MC_SEQ_WCDR_CTRL__PREAMBLE__SHIFT 0x00000018
+#define MC_SEQ_WCDR_CTRL__PRE_MASK_MASK 0xf0000000L
+#define MC_SEQ_WCDR_CTRL__PRE_MASK__SHIFT 0x0000001c
+#define MC_SEQ_WCDR_CTRL__RD_EN_MASK 0x00002000L
+#define MC_SEQ_WCDR_CTRL__RD_EN__SHIFT 0x0000000d
+#define MC_SEQ_WCDR_CTRL__TRAIN_EN_MASK 0x00008000L
+#define MC_SEQ_WCDR_CTRL__TRAIN_EN__SHIFT 0x0000000f
+#define MC_SEQ_WCDR_CTRL__TWCDRL_MASK 0x000f0000L
+#define MC_SEQ_WCDR_CTRL__TWCDRL__SHIFT 0x00000010
+#define MC_SEQ_WCDR_CTRL__WCDR_PRE_MASK 0x000000ffL
+#define MC_SEQ_WCDR_CTRL__WCDR_PRE__SHIFT 0x00000000
+#define MC_SEQ_WCDR_CTRL__WCDR_TIM_MASK 0x00000f00L
+#define MC_SEQ_WCDR_CTRL__WCDR_TIM__SHIFT 0x00000008
+#define MC_SEQ_WCDR_CTRL__WR_EN_MASK 0x00001000L
+#define MC_SEQ_WCDR_CTRL__WR_EN__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D0_MASK 0x00000001L
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D0__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D1_MASK 0x00000008L
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D1__SHIFT 0x00000003
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D0_MASK 0x00000002L
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D0__SHIFT 0x00000001
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D1_MASK 0x00000010L
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D1__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D0_MASK 0x00000001L
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D0__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D1_MASK 0x00000008L
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D1__SHIFT 0x00000003
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D0_MASK 0x00000002L
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D0__SHIFT 0x00000001
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D1_MASK 0x00000010L
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D1__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D0_MASK 0x00000004L
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D0__SHIFT 0x00000002
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D1_MASK 0x00000020L
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D1__SHIFT 0x00000005
+#define MC_SEQ_WR_CTL_2_LP__WCDR_EN_MASK 0x00000040L
+#define MC_SEQ_WR_CTL_2_LP__WCDR_EN__SHIFT 0x00000006
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D0_MASK 0x00000004L
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D0__SHIFT 0x00000002
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D1_MASK 0x00000020L
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D1__SHIFT 0x00000005
+#define MC_SEQ_WR_CTL_2__WCDR_EN_MASK 0x00000040L
+#define MC_SEQ_WR_CTL_2__WCDR_EN__SHIFT 0x00000006
+#define MC_SEQ_WR_CTL_D0__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D0__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D0__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D0__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D0__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D0__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D0__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D0__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D0__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D0__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D0__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D0__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D0__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D0__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D0__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D0__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D0_LP__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D0_LP__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D0_LP__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D0_LP__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D0_LP__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D0_LP__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D0_LP__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D0_LP__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D0_LP__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D0_LP__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D0_LP__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D0_LP__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D0_LP__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D0_LP__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D0_LP__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D0_LP__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D0_LP__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D0_LP__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D0_LP__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D0_LP__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D0_LP__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D0_LP__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D0_LP__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D0__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D0__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D0__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D0__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D0__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D0__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D0__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D0__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D0__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D0__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D1__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D1__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D1__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D1__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D1__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D1__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D1__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D1__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D1__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D1__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D1__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D1__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D1__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D1__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D1__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D1__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D1_LP__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D1_LP__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D1_LP__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D1_LP__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D1_LP__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D1_LP__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D1_LP__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D1_LP__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D1_LP__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D1_LP__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D1_LP__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D1_LP__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D1_LP__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D1_LP__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D1_LP__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D1_LP__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D1_LP__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D1_LP__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D1_LP__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D1_LP__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D1_LP__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D1_LP__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D1_LP__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D1__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D1__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D1__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D1__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D1__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D1__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D1__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D1__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D1__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D1__OEN_SEL__SHIFT 0x00000014
+#define MC_SHARED_BLACKOUT_CNTL__BLACKOUT_MODE_MASK 0x00000007L
+#define MC_SHARED_BLACKOUT_CNTL__BLACKOUT_MODE__SHIFT 0x00000000
+#define MC_SHARED_CHMAP__CHAN0_MASK 0x0000000fL
+#define MC_SHARED_CHMAP__CHAN0__SHIFT 0x00000000
+#define MC_SHARED_CHMAP__CHAN1_MASK 0x000000f0L
+#define MC_SHARED_CHMAP__CHAN1__SHIFT 0x00000004
+#define MC_SHARED_CHMAP__CHAN2_MASK 0x00000f00L
+#define MC_SHARED_CHMAP__CHAN2__SHIFT 0x00000008
+#define MC_SHARED_CHMAP__NOOFCHAN_MASK 0x0000f000L
+#define MC_SHARED_CHMAP__NOOFCHAN__SHIFT 0x0000000c
+#define MC_SHARED_CHREMAP__CHAN0_MASK 0x00000007L
+#define MC_SHARED_CHREMAP__CHAN0__SHIFT 0x00000000
+#define MC_SHARED_CHREMAP__CHAN1_MASK 0x00000038L
+#define MC_SHARED_CHREMAP__CHAN1__SHIFT 0x00000003
+#define MC_SHARED_CHREMAP__CHAN2_MASK 0x000001c0L
+#define MC_SHARED_CHREMAP__CHAN2__SHIFT 0x00000006
+#define MC_SHARED_CHREMAP__CHAN3_MASK 0x00000e00L
+#define MC_SHARED_CHREMAP__CHAN3__SHIFT 0x00000009
+#define MC_SHARED_CHREMAP__CHAN4_MASK 0x00007000L
+#define MC_SHARED_CHREMAP__CHAN4__SHIFT 0x0000000c
+#define MC_SHARED_CHREMAP__CHAN5_MASK 0x00038000L
+#define MC_SHARED_CHREMAP__CHAN5__SHIFT 0x0000000f
+#define MC_SHARED_CHREMAP__CHAN6_MASK 0x001c0000L
+#define MC_SHARED_CHREMAP__CHAN6__SHIFT 0x00000012
+#define MC_SHARED_CHREMAP__CHAN7_MASK 0x00e00000L
+#define MC_SHARED_CHREMAP__CHAN7__SHIFT 0x00000015
+#define MC_TRAIN_EDCCDR_R_D0__EDC0_MASK 0x000000ffL
+#define MC_TRAIN_EDCCDR_R_D0__EDC0__SHIFT 0x00000000
+#define MC_TRAIN_EDCCDR_R_D0__EDC1_MASK 0x0000ff00L
+#define MC_TRAIN_EDCCDR_R_D0__EDC1__SHIFT 0x00000008
+#define MC_TRAIN_EDCCDR_R_D0__EDC2_MASK 0x00ff0000L
+#define MC_TRAIN_EDCCDR_R_D0__EDC2__SHIFT 0x00000010
+#define MC_TRAIN_EDCCDR_R_D0__EDC3_MASK 0xff000000L
+#define MC_TRAIN_EDCCDR_R_D0__EDC3__SHIFT 0x00000018
+#define MC_TRAIN_EDCCDR_R_D1__EDC0_MASK 0x000000ffL
+#define MC_TRAIN_EDCCDR_R_D1__EDC0__SHIFT 0x00000000
+#define MC_TRAIN_EDCCDR_R_D1__EDC1_MASK 0x0000ff00L
+#define MC_TRAIN_EDCCDR_R_D1__EDC1__SHIFT 0x00000008
+#define MC_TRAIN_EDCCDR_R_D1__EDC2_MASK 0x00ff0000L
+#define MC_TRAIN_EDCCDR_R_D1__EDC2__SHIFT 0x00000010
+#define MC_TRAIN_EDCCDR_R_D1__EDC3_MASK 0xff000000L
+#define MC_TRAIN_EDCCDR_R_D1__EDC3__SHIFT 0x00000018
+#define MC_TRAIN_EDC_STATUS_D0__REDC_CNT_MASK 0xffff0000L
+#define MC_TRAIN_EDC_STATUS_D0__REDC_CNT__SHIFT 0x00000010
+#define MC_TRAIN_EDC_STATUS_D0__WEDC_CNT_MASK 0x0000ffffL
+#define MC_TRAIN_EDC_STATUS_D0__WEDC_CNT__SHIFT 0x00000000
+#define MC_TRAIN_EDC_STATUS_D1__REDC_CNT_MASK 0xffff0000L
+#define MC_TRAIN_EDC_STATUS_D1__REDC_CNT__SHIFT 0x00000010
+#define MC_TRAIN_EDC_STATUS_D1__WEDC_CNT_MASK 0x0000ffffL
+#define MC_TRAIN_EDC_STATUS_D1__WEDC_CNT__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_0_D0__DQ_STATUS_MASK 0xffffffffL
+#define MC_TRAIN_PRBSERR_0_D0__DQ_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_0_D1__DQ_STATUS_MASK 0xffffffffL
+#define MC_TRAIN_PRBSERR_0_D1__DQ_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D0__DBI_STATUS_MASK 0x0000000fL
+#define MC_TRAIN_PRBSERR_1_D0__DBI_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D0__EDC_STATUS_MASK 0x000000f0L
+#define MC_TRAIN_PRBSERR_1_D0__EDC_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_1_D0__PMA_PRBSCLR_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMA_PRBSCLR__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_1_D0__PMD0_PRBSCLR_MASK 0x20000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMD0_PRBSCLR__SHIFT 0x0000001d
+#define MC_TRAIN_PRBSERR_1_D0__PMD1_PRBSCLR_MASK 0x40000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMD1_PRBSCLR__SHIFT 0x0000001e
+#define MC_TRAIN_PRBSERR_1_D0__WCDR_STATUS_MASK 0x0000f000L
+#define MC_TRAIN_PRBSERR_1_D0__WCDR_STATUS__SHIFT 0x0000000c
+#define MC_TRAIN_PRBSERR_1_D0__WCK_STATUS_MASK 0x00000f00L
+#define MC_TRAIN_PRBSERR_1_D0__WCK_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_1_D1__DBI_STATUS_MASK 0x0000000fL
+#define MC_TRAIN_PRBSERR_1_D1__DBI_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D1__EDC_STATUS_MASK 0x000000f0L
+#define MC_TRAIN_PRBSERR_1_D1__EDC_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_1_D1__PMA_PRBSCLR_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMA_PRBSCLR__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_1_D1__PMD0_PRBSCLR_MASK 0x20000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMD0_PRBSCLR__SHIFT 0x0000001d
+#define MC_TRAIN_PRBSERR_1_D1__PMD1_PRBSCLR_MASK 0x40000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMD1_PRBSCLR__SHIFT 0x0000001e
+#define MC_TRAIN_PRBSERR_1_D1__WCDR_STATUS_MASK 0x0000f000L
+#define MC_TRAIN_PRBSERR_1_D1__WCDR_STATUS__SHIFT 0x0000000c
+#define MC_TRAIN_PRBSERR_1_D1__WCK_STATUS_MASK 0x00000f00L
+#define MC_TRAIN_PRBSERR_1_D1__WCK_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D0__ABI_STATUS_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_2_D0__ABI_STATUS__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_2_D0__ADDR_STATUS_MASK 0x03ff0000L
+#define MC_TRAIN_PRBSERR_2_D0__ADDR_STATUS__SHIFT 0x00000010
+#define MC_TRAIN_PRBSERR_2_D0__CAS_STATUS_MASK 0x00000400L
+#define MC_TRAIN_PRBSERR_2_D0__CAS_STATUS__SHIFT 0x0000000a
+#define MC_TRAIN_PRBSERR_2_D0__CKB_STATUS_MASK 0x00000002L
+#define MC_TRAIN_PRBSERR_2_D0__CKB_STATUS__SHIFT 0x00000001
+#define MC_TRAIN_PRBSERR_2_D0__CKE_STATUS_MASK 0x00000100L
+#define MC_TRAIN_PRBSERR_2_D0__CKE_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D0__CK_STATUS_MASK 0x00000001L
+#define MC_TRAIN_PRBSERR_2_D0__CK_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_2_D0__CS_STATUS_MASK 0x00000030L
+#define MC_TRAIN_PRBSERR_2_D0__CS_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_2_D0__RAS_STATUS_MASK 0x00000200L
+#define MC_TRAIN_PRBSERR_2_D0__RAS_STATUS__SHIFT 0x00000009
+#define MC_TRAIN_PRBSERR_2_D0__WE_STATUS_MASK 0x00000800L
+#define MC_TRAIN_PRBSERR_2_D0__WE_STATUS__SHIFT 0x0000000b
+#define MC_TRAIN_PRBSERR_2_D1__ABI_STATUS_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_2_D1__ABI_STATUS__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_2_D1__ADDR_STATUS_MASK 0x03ff0000L
+#define MC_TRAIN_PRBSERR_2_D1__ADDR_STATUS__SHIFT 0x00000010
+#define MC_TRAIN_PRBSERR_2_D1__CAS_STATUS_MASK 0x00000400L
+#define MC_TRAIN_PRBSERR_2_D1__CAS_STATUS__SHIFT 0x0000000a
+#define MC_TRAIN_PRBSERR_2_D1__CKB_STATUS_MASK 0x00000002L
+#define MC_TRAIN_PRBSERR_2_D1__CKB_STATUS__SHIFT 0x00000001
+#define MC_TRAIN_PRBSERR_2_D1__CKE_STATUS_MASK 0x00000100L
+#define MC_TRAIN_PRBSERR_2_D1__CKE_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D1__CK_STATUS_MASK 0x00000001L
+#define MC_TRAIN_PRBSERR_2_D1__CK_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_2_D1__CS_STATUS_MASK 0x00000030L
+#define MC_TRAIN_PRBSERR_2_D1__CS_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_2_D1__RAS_STATUS_MASK 0x00000200L
+#define MC_TRAIN_PRBSERR_2_D1__RAS_STATUS__SHIFT 0x00000009
+#define MC_TRAIN_PRBSERR_2_D1__WE_STATUS_MASK 0x00000800L
+#define MC_TRAIN_PRBSERR_2_D1__WE_STATUS__SHIFT 0x0000000b
+#define MC_TSM_DEBUG_BCNT0__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT0__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT0__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT0__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT0__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT0__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT0__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT0__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT10__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT10__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT10__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT10__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT10__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT10__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT10__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT10__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT1__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT1__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT1__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT1__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT1__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT1__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT1__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT1__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT2__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT2__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT2__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT2__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT2__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT2__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT2__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT2__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT3__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT3__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT3__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT3__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT3__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT3__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT3__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT3__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT4__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT4__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT4__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT4__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT4__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT4__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT4__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT4__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT5__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT5__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT5__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT5__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT5__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT5__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT5__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT5__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT6__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT6__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT6__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT6__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT6__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT6__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT6__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT6__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT7__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT7__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT7__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT7__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT7__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT7__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT7__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT7__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT8__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT8__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT8__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT8__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT8__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT8__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT8__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT8__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT9__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT9__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT9__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT9__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT9__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT9__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT9__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT9__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BKPT__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_BKPT__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_FLAG__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_FLAG__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_GCNT__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_GCNT__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_MISC__FLAG_MASK 0x000000ffL
+#define MC_TSM_DEBUG_MISC__FLAG__SHIFT 0x00000000
+#define MC_TSM_DEBUG_MISC__NCNT_RD_MASK 0x00000f00L
+#define MC_TSM_DEBUG_MISC__NCNT_RD__SHIFT 0x00000008
+#define MC_TSM_DEBUG_MISC__NCNT_WR_MASK 0x0000f000L
+#define MC_TSM_DEBUG_MISC__NCNT_WR__SHIFT 0x0000000c
+#define MC_TSM_DEBUG_ST01__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST01__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_ST23__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST23__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_ST45__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST45__DATA__SHIFT 0x00000000
+#define MC_VM_AGP_BASE__AGP_BASE_MASK 0x0003ffffL
+#define MC_VM_AGP_BASE__AGP_BASE__SHIFT 0x00000000
+#define MC_VM_AGP_BOT__AGP_BOT_MASK 0x0003ffffL
+#define MC_VM_AGP_BOT__AGP_BOT__SHIFT 0x00000000
+#define MC_VM_AGP_TOP__AGP_TOP_MASK 0x0003ffffL
+#define MC_VM_AGP_TOP__AGP_TOP__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_LOCAL_MASK 0x00000100L
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_LOCAL__SHIFT 0x00000008
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_SYSTEM_MASK 0x00000200L
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_SYSTEM__SHIFT 0x00000009
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_0_MODE_MASK 0x00000003L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_0_MODE__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_1_MODE_MASK 0x0000000cL
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_1_MODE__SHIFT 0x00000002
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_2_MODE_MASK 0x00000030L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_2_MODE__SHIFT 0x00000004
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_3_MODE_MASK 0x000000c0L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_3_MODE__SHIFT 0x00000006
+#define MC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_FB_LOCATION__FB_BASE_MASK 0x0000ffffL
+#define MC_VM_FB_LOCATION__FB_BASE__SHIFT 0x00000000
+#define MC_VM_FB_LOCATION__FB_TOP_MASK 0xffff0000L
+#define MC_VM_FB_LOCATION__FB_TOP__SHIFT 0x00000010
+#define MC_VM_FB_OFFSET__FB_OFFSET_MASK 0x0003ffffL
+#define MC_VM_FB_OFFSET__FB_OFFSET__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB0_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB0_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB0_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB0_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB0_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB0_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB0_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB0_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB1_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB1_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB2_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB2_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB2_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB2_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB2_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB2_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB2_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB2_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB3_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB3_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB3_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB3_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB3_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB3_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB3_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB3_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L2ARBITER_L2_CREDITS__L2_IF_CREDITS_MASK 0x0000003fL
+#define MC_VM_MB_L2ARBITER_L2_CREDITS__L2_IF_CREDITS__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB0_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB0_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB0_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB0_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB0_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB0_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB0_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB0_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB1_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB1_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB1_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB1_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB1_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB1_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB1_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB1_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB2_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB2_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB2_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB2_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB2_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB2_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB2_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB2_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB3_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB3_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB3_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB3_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB3_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB3_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB3_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB3_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L2ARBITER_L2_CREDITS__L2_IF_CREDITS_MASK 0x0000003fL
+#define MC_VM_MD_L2ARBITER_L2_CREDITS__L2_IF_CREDITS__SHIFT 0x00000000
+#define MC_VM_MX_L1_TLB_CNTL__ECO_BITS_MASK 0x00000780L
+#define MC_VM_MX_L1_TLB_CNTL__ECO_BITS__SHIFT 0x00000007
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL_MASK 0x00000040L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL__SHIFT 0x00000006
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING_MASK 0x00000002L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING__SHIFT 0x00000001
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK 0x00000018L
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE__SHIFT 0x00000003
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS_MASK 0x00000020L
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT 0x00000005
+#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_VM_SYSTEM_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_WR_CB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_CB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_CB__ENABLE_MASK 0x00000001L
+#define MC_WR_CB__ENABLE__SHIFT 0x00000000
+#define MC_WR_CB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_CB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_CB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_CB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_CB__PRESCALE_MASK 0x00000006L
+#define MC_WR_CB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_CB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_CB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_CB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_CB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_CB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_CB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_DB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_DB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_DB__ENABLE_MASK 0x00000001L
+#define MC_WR_DB__ENABLE__SHIFT 0x00000000
+#define MC_WR_DB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_DB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_DB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_DB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_DB__PRESCALE_MASK 0x00000006L
+#define MC_WR_DB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_DB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_DB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_DB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_DB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_DB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_DB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_GRP_EXT__DBSTEN0_MASK 0x0000000fL
+#define MC_WR_GRP_EXT__DBSTEN0__SHIFT 0x00000000
+#define MC_WR_GRP_EXT__TC0_MASK 0x000000f0L
+#define MC_WR_GRP_EXT__TC0__SHIFT 0x00000004
+#define MC_WR_GRP_GFX__CP_MASK 0x0000000fL
+#define MC_WR_GRP_GFX__CP__SHIFT 0x00000000
+#define MC_WR_GRP_GFX__XDMA_MASK 0x0000f000L
+#define MC_WR_GRP_GFX__XDMAM_MASK 0x000f0000L
+#define MC_WR_GRP_GFX__XDMAM__SHIFT 0x00000010
+#define MC_WR_GRP_GFX__XDMA__SHIFT 0x0000000c
+#define MC_WR_GRP_LCL__CB0_MASK 0x0000000fL
+#define MC_WR_GRP_LCL__CB0__SHIFT 0x00000000
+#define MC_WR_GRP_LCL__CBCMASK0_MASK 0x000000f0L
+#define MC_WR_GRP_LCL__CBCMASK0__SHIFT 0x00000004
+#define MC_WR_GRP_LCL__CBFMASK0_MASK 0x00000f00L
+#define MC_WR_GRP_LCL__CBFMASK0__SHIFT 0x00000008
+#define MC_WR_GRP_LCL__CBIMMED0_MASK 0xf0000000L
+#define MC_WR_GRP_LCL__CBIMMED0__SHIFT 0x0000001c
+#define MC_WR_GRP_LCL__DB0_MASK 0x0000f000L
+#define MC_WR_GRP_LCL__DB0__SHIFT 0x0000000c
+#define MC_WR_GRP_LCL__DBHTILE0_MASK 0x000f0000L
+#define MC_WR_GRP_LCL__DBHTILE0__SHIFT 0x00000010
+#define MC_WR_GRP_LCL__SX0_MASK 0x00f00000L
+#define MC_WR_GRP_LCL__SX0__SHIFT 0x00000014
+#define MC_WR_GRP_OTH__HDP_MASK 0x00000f00L
+#define MC_WR_GRP_OTH__HDP__SHIFT 0x00000008
+#define MC_WR_GRP_OTH__SEM_MASK 0x0000f000L
+#define MC_WR_GRP_OTH__SEM__SHIFT 0x0000000c
+#define MC_WR_GRP_OTH__UMC_MASK 0x000f0000L
+#define MC_WR_GRP_OTH__UMC__SHIFT 0x00000010
+#define MC_WR_GRP_OTH__UVD_EXT0_MASK 0x0000000fL
+#define MC_WR_GRP_OTH__UVD_EXT0__SHIFT 0x00000000
+#define MC_WR_GRP_OTH__UVD_EXT1_MASK 0xf0000000L
+#define MC_WR_GRP_OTH__UVD_EXT1__SHIFT 0x0000001c
+#define MC_WR_GRP_OTH__UVD_MASK 0x00f00000L
+#define MC_WR_GRP_OTH__UVD__SHIFT 0x00000014
+#define MC_WR_GRP_OTH__XDP_MASK 0x0f000000L
+#define MC_WR_GRP_OTH__XDP__SHIFT 0x00000018
+#define MC_WR_GRP_SYS__IH_MASK 0x0000000fL
+#define MC_WR_GRP_SYS__IH__SHIFT 0x00000000
+#define MC_WR_GRP_SYS__MCIF_MASK 0x000000f0L
+#define MC_WR_GRP_SYS__MCIF__SHIFT 0x00000004
+#define MC_WR_GRP_SYS__RLC_MASK 0x00000f00L
+#define MC_WR_GRP_SYS__RLC__SHIFT 0x00000008
+#define MC_WR_GRP_SYS__SMU_MASK 0x00f00000L
+#define MC_WR_GRP_SYS__SMU__SHIFT 0x00000014
+#define MC_WR_GRP_SYS__VCE_MASK 0x0f000000L
+#define MC_WR_GRP_SYS__VCE__SHIFT 0x00000018
+#define MC_WR_GRP_SYS__VCEU_MASK 0xf0000000L
+#define MC_WR_GRP_SYS__VCEU__SHIFT 0x0000001c
+#define MC_WR_HUB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_HUB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_HUB__ENABLE_MASK 0x00000001L
+#define MC_WR_HUB__ENABLE__SHIFT 0x00000000
+#define MC_WR_HUB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_HUB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_HUB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_HUB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_HUB__PRESCALE_MASK 0x00000006L
+#define MC_WR_HUB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_HUB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_HUB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_HUB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_HUB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_HUB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_HUB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_TC0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_TC0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_TC0__ENABLE_MASK 0x00000001L
+#define MC_WR_TC0__ENABLE__SHIFT 0x00000000
+#define MC_WR_TC0__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_TC0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_TC0__MAX_BURST_MASK 0x00000780L
+#define MC_WR_TC0__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_TC0__PRESCALE_MASK 0x00000006L
+#define MC_WR_TC0__PRESCALE__SHIFT 0x00000001
+#define MC_WR_TC0__STALL_MODE_MASK 0x00000030L
+#define MC_WR_TC0__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_TC0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_TC0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_TC0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_TC0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_TC1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_TC1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_TC1__ENABLE_MASK 0x00000001L
+#define MC_WR_TC1__ENABLE__SHIFT 0x00000000
+#define MC_WR_TC1__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_TC1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_TC1__MAX_BURST_MASK 0x00000780L
+#define MC_WR_TC1__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_TC1__PRESCALE_MASK 0x00000006L
+#define MC_WR_TC1__PRESCALE__SHIFT 0x00000001
+#define MC_WR_TC1__STALL_MODE_MASK 0x00000030L
+#define MC_WR_TC1__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_TC1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_TC1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_TC1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_TC1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_XBAR_ADDR_DEC__GECC_MASK 0x00000002L
+#define MC_XBAR_ADDR_DEC__GECC__SHIFT 0x00000001
+#define MC_XBAR_ADDR_DEC__NO_DIV_BY_3_MASK 0x00000001L
+#define MC_XBAR_ADDR_DEC__NO_DIV_BY_3__SHIFT 0x00000000
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_COLHI_MASK 0x00000008L
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_COLHI__SHIFT 0x00000003
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_MASK 0x00000004L
+#define MC_XBAR_ADDR_DEC__RB_SPLIT__SHIFT 0x00000002
+#define MC_XBAR_ARB__BREAK_BURST_CID_CHANGE_MASK 0x00000004L
+#define MC_XBAR_ARB__BREAK_BURST_CID_CHANGE__SHIFT 0x00000002
+#define MC_XBAR_ARB__DISABLE_HUB_STALL_HIGHEST_MASK 0x00000002L
+#define MC_XBAR_ARB__DISABLE_HUB_STALL_HIGHEST__SHIFT 0x00000001
+#define MC_XBAR_ARB__HUBRD_HIGHEST_MASK 0x00000001L
+#define MC_XBAR_ARB__HUBRD_HIGHEST__SHIFT 0x00000000
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT0_MASK 0x0000000fL
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT0__SHIFT 0x00000000
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT1_MASK 0x000000f0L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT1__SHIFT 0x00000004
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT2_MASK 0x00000f00L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT2__SHIFT 0x00000008
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT3_MASK 0x0000f000L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT3__SHIFT 0x0000000c
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT0_MASK 0x000f0000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT0__SHIFT 0x00000010
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT1_MASK 0x00f00000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT1__SHIFT 0x00000014
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT2_MASK 0x0f000000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT2__SHIFT 0x00000018
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT3_MASK 0xf0000000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT3__SHIFT 0x0000001c
+#define MC_XBAR_CHTRIREMAP__CH0_MASK 0x00000003L
+#define MC_XBAR_CHTRIREMAP__CH0__SHIFT 0x00000000
+#define MC_XBAR_CHTRIREMAP__CH1_MASK 0x0000000cL
+#define MC_XBAR_CHTRIREMAP__CH1__SHIFT 0x00000002
+#define MC_XBAR_CHTRIREMAP__CH2_MASK 0x00000030L
+#define MC_XBAR_CHTRIREMAP__CH2__SHIFT 0x00000004
+#define MC_XBAR_PERF_MON_CNTL0__ALLOW_WRAP_MASK 0x10000000L
+#define MC_XBAR_PERF_MON_CNTL0__ALLOW_WRAP__SHIFT 0x0000001c
+#define MC_XBAR_PERF_MON_CNTL0__START_MODE_MASK 0x03000000L
+#define MC_XBAR_PERF_MON_CNTL0__START_MODE__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_CNTL0__START_THRESH_MASK 0x00000fffL
+#define MC_XBAR_PERF_MON_CNTL0__START_THRESH__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL0__STOP_MODE_MASK 0x0c000000L
+#define MC_XBAR_PERF_MON_CNTL0__STOP_MODE__SHIFT 0x0000001a
+#define MC_XBAR_PERF_MON_CNTL0__STOP_THRESH_MASK 0x00fff000L
+#define MC_XBAR_PERF_MON_CNTL0__STOP_THRESH__SHIFT 0x0000000c
+#define MC_XBAR_PERF_MON_CNTL1__START_TRIG_ID_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_CNTL1__START_TRIG_ID__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_CNTL1__STOP_TRIG_ID_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_CNTL1__STOP_TRIG_ID__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_CNTL1__THRESH_CNTR_ID_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_CNTL1__THRESH_CNTR_ID__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL2__MON0_ID_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_CNTL2__MON0_ID__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL2__MON1_ID_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_CNTL2__MON1_ID__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_CNTL2__MON2_ID_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_CNTL2__MON2_ID__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_CNTL2__MON3_ID_MASK 0xff000000L
+#define MC_XBAR_PERF_MON_CNTL2__MON3_ID__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_MAX_THSH__MON0_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_MAX_THSH__MON0__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_MAX_THSH__MON1_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON1__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_MAX_THSH__MON2_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON2__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_MAX_THSH__MON3_MASK 0xff000000L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON3__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_RSLT0__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT0__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT1__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT1__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT2__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT2__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT3__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT3__COUNT__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDREQ_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDREQ_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDREQ_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDREQ_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDREQ_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDREQ_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDRET_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDRET_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDRET_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDRET_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDRET_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_CREDIT2__HUB_LP_RDRET_SKID_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_CREDIT2__HUB_LP_RDRET_SKID__SHIFT 0x00000010
+#define MC_XBAR_RDRET_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_RDRET_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_RDRET_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XBAR_REMOTE__RDREQ_EN_GOQ_MASK 0x00000002L
+#define MC_XBAR_REMOTE__RDREQ_EN_GOQ__SHIFT 0x00000001
+#define MC_XBAR_REMOTE__WRREQ_EN_GOQ_MASK 0x00000001L
+#define MC_XBAR_REMOTE__WRREQ_EN_GOQ__SHIFT 0x00000000
+#define MC_XBAR_SPARE0__BIT_MASK 0xffffffffL
+#define MC_XBAR_SPARE0__BIT__SHIFT 0x00000000
+#define MC_XBAR_SPARE1__BIT_MASK 0xffffffffL
+#define MC_XBAR_SPARE1__BIT__SHIFT 0x00000000
+#define MC_XBAR_TWOCHAN__CH0_MASK 0x00000006L
+#define MC_XBAR_TWOCHAN__CH0__SHIFT 0x00000001
+#define MC_XBAR_TWOCHAN__CH1_MASK 0x00000018L
+#define MC_XBAR_TWOCHAN__CH1__SHIFT 0x00000003
+#define MC_XBAR_TWOCHAN__DISABLE_ONEPORT_MASK 0x00000001L
+#define MC_XBAR_TWOCHAN__DISABLE_ONEPORT__SHIFT 0x00000000
+#define MC_XBAR_WRREQ_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_WRREQ_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_WRREQ_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_WRREQ_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_WRREQ_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_WRREQ_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_WRREQ_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_WRREQ_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_WRRET_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_WRRET_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_WRRET_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_WRRET_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_WRRET_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_WRRET_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_WRRET_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_WRRET_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_WRRET_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_WRRET_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_WRRET_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_WRRET_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XPB_CLG_CFG0__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG0__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG0__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG0__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG0__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG0__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG0__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG0__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG0__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG0__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG10__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG10__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG10__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG10__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG10__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG10__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG10__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG10__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG10__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG10__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG11__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG11__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG11__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG11__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG11__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG11__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG11__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG11__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG11__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG11__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG12__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG12__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG12__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG12__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG12__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG12__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG12__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG12__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG12__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG12__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG13__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG13__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG13__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG13__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG13__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG13__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG13__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG13__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG13__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG13__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG14__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG14__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG14__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG14__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG14__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG14__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG14__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG14__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG14__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG14__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG15__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG15__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG15__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG15__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG15__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG15__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG15__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG15__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG15__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG15__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG16__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG16__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG16__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG16__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG16__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG16__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG16__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG16__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG16__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG16__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG17__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG17__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG17__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG17__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG17__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG17__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG17__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG17__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG17__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG17__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG18__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG18__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG18__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG18__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG18__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG18__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG18__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG18__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG18__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG18__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG19__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG19__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG19__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG19__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG19__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG19__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG19__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG19__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG19__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG19__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG1__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG1__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG1__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG1__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG1__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG1__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG1__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG1__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG1__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG1__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG20__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG20__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG20__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG20__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG20__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG20__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG20__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG20__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG20__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG20__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG21__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG21__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG21__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG21__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG21__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG21__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG21__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG21__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG21__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG21__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG22__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG22__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG22__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG22__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG22__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG22__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG22__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG22__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG22__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG22__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG23__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG23__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG23__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG23__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG23__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG23__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG23__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG23__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG23__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG23__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG24__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG24__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG24__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG24__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG24__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG24__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG24__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG24__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG24__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG24__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG25__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG25__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG25__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG25__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG25__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG25__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG25__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG25__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG25__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG25__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG26__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG26__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG26__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG26__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG26__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG26__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG26__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG26__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG26__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG26__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG27__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG27__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG27__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG27__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG27__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG27__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG27__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG27__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG27__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG27__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG28__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG28__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG28__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG28__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG28__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG28__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG28__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG28__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG28__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG28__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG29__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG29__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG29__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG29__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG29__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG29__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG29__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG29__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG29__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG29__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG2__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG2__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG2__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG2__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG2__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG2__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG2__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG2__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG2__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG2__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG30__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG30__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG30__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG30__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG30__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG30__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG30__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG30__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG30__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG30__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG31__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG31__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG31__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG31__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG31__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG31__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG31__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG31__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG31__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG31__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG32__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG32__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG32__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG32__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG32__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG32__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG32__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG32__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG32__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG32__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG33__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG33__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG33__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG33__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG33__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG33__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG33__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG33__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG33__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG33__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG34__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG34__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG34__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG34__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG34__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG34__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG34__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG34__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG34__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG34__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG35__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG35__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG35__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG35__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG35__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG35__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG35__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG35__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG35__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG35__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG36__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG36__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG36__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG36__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG36__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG36__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG36__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG36__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG36__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG36__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG3__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG3__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG3__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG3__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG3__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG3__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG3__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG3__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG3__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG3__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG4__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG4__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG4__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG4__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG4__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG4__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG4__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG4__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG4__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG4__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG5__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG5__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG5__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG5__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG5__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG5__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG5__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG5__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG5__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG5__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG6__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG6__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG6__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG6__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG6__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG6__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG6__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG6__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG6__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG6__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG7__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG7__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG7__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG7__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG7__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG7__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG7__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG7__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG7__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG7__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG8__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG8__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG8__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG8__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG8__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG8__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG8__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG8__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG8__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG8__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG9__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG9__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG9__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG9__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG9__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG9__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG9__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG9__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG9__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG9__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA__CMP0_MASK 0x000000ffL
+#define MC_XPB_CLG_EXTRA__CMP0__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA__CMP1_MASK 0x01fe0000L
+#define MC_XPB_CLG_EXTRA__CMP1__SHIFT 0x00000011
+#define MC_XPB_CLG_EXTRA__MSK0_MASK 0x0000ff00L
+#define MC_XPB_CLG_EXTRA__MSK0__SHIFT 0x00000008
+#define MC_XPB_CLG_EXTRA_RD__CMP0_MASK 0x000000ffL
+#define MC_XPB_CLG_EXTRA_RD__CMP0__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA_RD__CMP1_MASK 0x01fe0000L
+#define MC_XPB_CLG_EXTRA_RD__CMP1__SHIFT 0x00000011
+#define MC_XPB_CLG_EXTRA_RD__MSK0_MASK 0x0000ff00L
+#define MC_XPB_CLG_EXTRA_RD__MSK0__SHIFT 0x00000008
+#define MC_XPB_CLG_EXTRA_RD__VLD0_MASK 0x00010000L
+#define MC_XPB_CLG_EXTRA_RD__VLD0__SHIFT 0x00000010
+#define MC_XPB_CLG_EXTRA_RD__VLD1_MASK 0x02000000L
+#define MC_XPB_CLG_EXTRA_RD__VLD1__SHIFT 0x00000019
+#define MC_XPB_CLG_EXTRA__VLD0_MASK 0x00010000L
+#define MC_XPB_CLG_EXTRA__VLD0__SHIFT 0x00000010
+#define MC_XPB_CLG_EXTRA__VLD1_MASK 0x02000000L
+#define MC_XPB_CLG_EXTRA__VLD1__SHIFT 0x00000019
+#define MC_XPB_CLK_GAT__ENABLE_MASK 0x00040000L
+#define MC_XPB_CLK_GAT__ENABLE__SHIFT 0x00000012
+#define MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_XPB_CLK_GAT__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_XPB_CLK_GAT__OFFDLY_MASK 0x00000fc0L
+#define MC_XPB_CLK_GAT__OFFDLY__SHIFT 0x00000006
+#define MC_XPB_CLK_GAT__ONDLY_MASK 0x0000003fL
+#define MC_XPB_CLK_GAT__ONDLY__SHIFT 0x00000000
+#define MC_XPB_CLK_GAT__RDYDLY_MASK 0x0003f000L
+#define MC_XPB_CLK_GAT__RDYDLY__SHIFT 0x0000000c
+#define MC_XPB_INTF_CFG2__RPB_RDREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_CFG2__RPB_RDREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_SEL_MASK 0x02000000L
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_SEL__SHIFT 0x00000019
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_VAL_MASK 0x04000000L
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_VAL__SHIFT 0x0000001a
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_SEL_MASK 0x00800000L
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_SEL__SHIFT 0x00000017
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_VAL_MASK 0x01000000L
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_VAL__SHIFT 0x00000018
+#define MC_XPB_INTF_CFG__MC_WRRET_ASK_MASK 0x0000ff00L
+#define MC_XPB_INTF_CFG__MC_WRRET_ASK__SHIFT 0x00000008
+#define MC_XPB_INTF_CFG__RPB_WRREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_CFG__RPB_WRREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_CFG__XSP_ORDERING_SEL_MASK 0x40000000L
+#define MC_XPB_INTF_CFG__XSP_ORDERING_SEL__SHIFT 0x0000001e
+#define MC_XPB_INTF_CFG__XSP_ORDERING_VAL_MASK 0x80000000L
+#define MC_XPB_INTF_CFG__XSP_ORDERING_VAL__SHIFT 0x0000001f
+#define MC_XPB_INTF_CFG__XSP_REQ_CRD_MASK 0x007f0000L
+#define MC_XPB_INTF_CFG__XSP_REQ_CRD__SHIFT 0x00000010
+#define MC_XPB_INTF_CFG__XSP_SNOOP_SEL_MASK 0x18000000L
+#define MC_XPB_INTF_CFG__XSP_SNOOP_SEL__SHIFT 0x0000001b
+#define MC_XPB_INTF_CFG__XSP_SNOOP_VAL_MASK 0x20000000L
+#define MC_XPB_INTF_CFG__XSP_SNOOP_VAL__SHIFT 0x0000001d
+#define MC_XPB_INTF_STS__CNS_BUF_BUSY_MASK 0x00040000L
+#define MC_XPB_INTF_STS__CNS_BUF_BUSY__SHIFT 0x00000012
+#define MC_XPB_INTF_STS__CNS_BUF_FULL_MASK 0x00020000L
+#define MC_XPB_INTF_STS__CNS_BUF_FULL__SHIFT 0x00000011
+#define MC_XPB_INTF_STS__HOP_ATTR_BUF_FULL_MASK 0x00010000L
+#define MC_XPB_INTF_STS__HOP_ATTR_BUF_FULL__SHIFT 0x00000010
+#define MC_XPB_INTF_STS__HOP_DATA_BUF_FULL_MASK 0x00008000L
+#define MC_XPB_INTF_STS__HOP_DATA_BUF_FULL__SHIFT 0x0000000f
+#define MC_XPB_INTF_STS__RPB_RDREQ_CRD_MASK 0x07f80000L
+#define MC_XPB_INTF_STS__RPB_RDREQ_CRD__SHIFT 0x00000013
+#define MC_XPB_INTF_STS__RPB_WRREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_STS__RPB_WRREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_STS__XSP_REQ_CRD_MASK 0x00007f00L
+#define MC_XPB_INTF_STS__XSP_REQ_CRD__SHIFT 0x00000008
+#define MC_XPB_LB_ADDR__CMP0_MASK 0x000003ffL
+#define MC_XPB_LB_ADDR__CMP0__SHIFT 0x00000000
+#define MC_XPB_LB_ADDR__CMP1_MASK 0x03f00000L
+#define MC_XPB_LB_ADDR__CMP1__SHIFT 0x00000014
+#define MC_XPB_LB_ADDR__MASK0_MASK 0x000ffc00L
+#define MC_XPB_LB_ADDR__MASK0__SHIFT 0x0000000a
+#define MC_XPB_LB_ADDR__MASK1_MASK 0xfc000000L
+#define MC_XPB_LB_ADDR__MASK1__SHIFT 0x0000001a
+#define MC_XPB_MAP_INVERT_FLUSH_NUM_LSB__ALTER_FLUSH_NUM_MASK 0x0000ffffL
+#define MC_XPB_MAP_INVERT_FLUSH_NUM_LSB__ALTER_FLUSH_NUM__SHIFT 0x00000000
+#define MC_XPB_MISC_CFG__FIELDNAME0_MASK 0x000000ffL
+#define MC_XPB_MISC_CFG__FIELDNAME0__SHIFT 0x00000000
+#define MC_XPB_MISC_CFG__FIELDNAME1_MASK 0x0000ff00L
+#define MC_XPB_MISC_CFG__FIELDNAME1__SHIFT 0x00000008
+#define MC_XPB_MISC_CFG__FIELDNAME2_MASK 0x00ff0000L
+#define MC_XPB_MISC_CFG__FIELDNAME2__SHIFT 0x00000010
+#define MC_XPB_MISC_CFG__FIELDNAME3_MASK 0x7f000000L
+#define MC_XPB_MISC_CFG__FIELDNAME3__SHIFT 0x00000018
+#define MC_XPB_MISC_CFG__TRIGGERNAME_MASK 0x80000000L
+#define MC_XPB_MISC_CFG__TRIGGERNAME__SHIFT 0x0000001f
+#define MC_XPB_P2P_BAR0__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR0__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR0__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR0__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR0__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR0__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR0__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR0__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR0__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR0__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR0__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR0__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR0__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR0__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR0__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR0__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR1__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR1__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR1__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR1__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR1__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR1__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR1__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR1__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR1__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR1__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR1__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR1__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR1__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR1__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR1__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR1__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR2__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR2__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR2__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR2__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR2__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR2__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR2__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR2__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR2__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR2__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR2__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR2__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR2__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR2__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR2__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR2__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR3__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR3__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR3__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR3__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR3__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR3__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR3__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR3__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR3__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR3__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR3__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR3__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR3__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR3__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR3__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR3__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR4__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR4__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR4__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR4__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR4__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR4__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR4__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR4__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR4__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR4__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR4__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR4__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR4__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR4__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR4__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR4__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR5__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR5__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR5__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR5__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR5__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR5__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR5__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR5__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR5__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR5__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR5__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR5__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR5__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR5__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR5__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR5__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR6__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR6__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR6__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR6__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR6__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR6__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR6__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR6__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR6__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR6__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR6__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR6__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR6__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR6__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR6__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR6__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR7__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR7__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR7__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR7__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR7__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR7__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR7__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR7__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR7__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR7__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR7__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR7__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR7__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR7__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR7__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR7__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_CFG__ADDR_SIZE_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR_CFG__ADDR_SIZE__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_CFG__ATC_TRANSLATED_MASK 0x00001000L
+#define MC_XPB_P2P_BAR_CFG__ATC_TRANSLATED__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_CFG__COMPRESS_DIS_MASK 0x00000100L
+#define MC_XPB_P2P_BAR_CFG__COMPRESS_DIS__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_CFG__RD_EN_MASK 0x00000800L
+#define MC_XPB_P2P_BAR_CFG__RD_EN__SHIFT 0x0000000b
+#define MC_XPB_P2P_BAR_CFG__REGBAR_FROM_SYSBAR_MASK 0x00000400L
+#define MC_XPB_P2P_BAR_CFG__REGBAR_FROM_SYSBAR__SHIFT 0x0000000a
+#define MC_XPB_P2P_BAR_CFG__SEND_BAR_MASK 0x00000030L
+#define MC_XPB_P2P_BAR_CFG__SEND_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR_CFG__SEND_DIS_MASK 0x00000080L
+#define MC_XPB_P2P_BAR_CFG__SEND_DIS__SHIFT 0x00000007
+#define MC_XPB_P2P_BAR_CFG__SNOOP_MASK 0x00000040L
+#define MC_XPB_P2P_BAR_CFG__SNOOP__SHIFT 0x00000006
+#define MC_XPB_P2P_BAR_CFG__UPDATE_DIS_MASK 0x00000200L
+#define MC_XPB_P2P_BAR_CFG__UPDATE_DIS__SHIFT 0x00000009
+#define MC_XPB_P2P_BAR_DEBUG__HOST_FLUSH_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR_DEBUG__HOST_FLUSH__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DEBUG__MEM_SYS_BAR_MASK 0x0000f000L
+#define MC_XPB_P2P_BAR_DEBUG__MEM_SYS_BAR__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_DEBUG__SEL_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DEBUG__SEL__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__DELTA_MASK 0x0fffff00L
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__DELTA__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__EN_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__EN__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_DELTA_BELOW__DELTA_MASK 0x0fffff00L
+#define MC_XPB_P2P_BAR_DELTA_BELOW__DELTA__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DELTA_BELOW__EN_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DELTA_BELOW__EN__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_SETUP__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR_SETUP__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR_SETUP__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR_SETUP__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR_SETUP__REG_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR_SETUP__REG_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_SETUP__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR_SETUP__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR_SETUP__SEL_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_SETUP__SEL__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_SETUP__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR_SETUP__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR_SETUP__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR_SETUP__VALID__SHIFT 0x0000000c
+#define MC_XPB_PEER_SYS_BAR0__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR0__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR0__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR0__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR0__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR0__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR1__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR1__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR1__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR1__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR1__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR1__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR2__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR2__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR2__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR2__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR2__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR2__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR3__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR3__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR3__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR3__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR3__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR3__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR4__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR4__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR4__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR4__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR4__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR4__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR5__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR5__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR5__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR5__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR5__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR5__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR6__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR6__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR6__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR6__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR6__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR6__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR7__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR7__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR7__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR7__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR7__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR7__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR8__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR8__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR8__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR8__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR8__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR8__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR9__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR9__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR9__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR9__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR9__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR9__VALID__SHIFT 0x00000000
+#define MC_XPB_PERF_KNOBS__CNS_FIFO_DEPTH_MASK 0x0000003fL
+#define MC_XPB_PERF_KNOBS__CNS_FIFO_DEPTH__SHIFT 0x00000000
+#define MC_XPB_PERF_KNOBS__WCB_HST_FIFO_DEPTH_MASK 0x00000fc0L
+#define MC_XPB_PERF_KNOBS__WCB_HST_FIFO_DEPTH__SHIFT 0x00000006
+#define MC_XPB_PERF_KNOBS__WCB_SID_FIFO_DEPTH_MASK 0x0003f000L
+#define MC_XPB_PERF_KNOBS__WCB_SID_FIFO_DEPTH__SHIFT 0x0000000c
+#define MC_XPB_PIPE_STS__RET_BUF_FULL_MASK 0x00800000L
+#define MC_XPB_PIPE_STS__RET_BUF_FULL__SHIFT 0x00000017
+#define MC_XPB_PIPE_STS__WCB_ANY_PBUF_MASK 0x00000001L
+#define MC_XPB_PIPE_STS__WCB_ANY_PBUF__SHIFT 0x00000000
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_BUF_CNT_MASK 0x000000feL
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_BUF_CNT__SHIFT 0x00000001
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_OBUF_FULL_MASK 0x00200000L
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_OBUF_FULL__SHIFT 0x00000015
+#define MC_XPB_PIPE_STS__WCB_HST_RD_PTR_BUF_FULL_MASK 0x00008000L
+#define MC_XPB_PIPE_STS__WCB_HST_RD_PTR_BUF_FULL__SHIFT 0x0000000f
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_FIFO_FULL_MASK 0x00020000L
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_FIFO_FULL__SHIFT 0x00000011
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_OBUF_FULL_MASK 0x00080000L
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_OBUF_FULL__SHIFT 0x00000013
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_BUF_CNT_MASK 0x00007f00L
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_BUF_CNT__SHIFT 0x00000008
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_OBUF_FULL_MASK 0x00400000L
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_OBUF_FULL__SHIFT 0x00000016
+#define MC_XPB_PIPE_STS__WCB_SID_RD_PTR_BUF_FULL_MASK 0x00010000L
+#define MC_XPB_PIPE_STS__WCB_SID_RD_PTR_BUF_FULL__SHIFT 0x00000010
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_FIFO_FULL_MASK 0x00040000L
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_FIFO_FULL__SHIFT 0x00000012
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_OBUF_FULL_MASK 0x00100000L
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_OBUF_FULL__SHIFT 0x00000014
+#define MC_XPB_PIPE_STS__XPB_CLK_BUSY_BITS_MASK 0xff000000L
+#define MC_XPB_PIPE_STS__XPB_CLK_BUSY_BITS__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP0__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP0__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP0__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP0__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP0__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP0__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP0__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP0__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP1__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP1__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP1__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP1__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP1__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP1__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP1__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP1__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP2__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP2__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP2__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP2__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP2__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP2__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP2__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP2__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP3__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP3__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP3__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP3__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP3__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP3__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP3__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP3__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP4__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP4__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP4__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP4__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP4__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP4__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP4__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP4__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP5__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP5__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP5__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP5__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP5__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP5__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP5__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP5__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP6__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP6__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP6__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP6__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP6__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP6__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP6__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP6__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP7__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP7__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP7__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP7__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP7__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP7__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP7__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP7__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP8__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP8__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP8__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP8__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP8__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP8__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP8__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP8__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP9__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP9__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP9__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP9__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP9__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP9__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP9__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP9__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_SRC_APRTR0__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR0__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR1__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR1__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR2__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR2__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR3__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR3__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR4__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR4__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR5__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR5__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR6__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR6__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR7__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR7__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR8__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR8__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR9__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR9__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_STICKY__BITS_MASK 0xffffffffL
+#define MC_XPB_STICKY__BITS__SHIFT 0x00000000
+#define MC_XPB_STICKY_W1C__BITS_MASK 0xffffffffL
+#define MC_XPB_STICKY_W1C__BITS__SHIFT 0x00000000
+#define MC_XPB_SUB_CTRL__RESET_CGR_MASK 0x00080000L
+#define MC_XPB_SUB_CTRL__RESET_CGR__SHIFT 0x00000013
+#define MC_XPB_SUB_CTRL__RESET_CNS_MASK 0x00000400L
+#define MC_XPB_SUB_CTRL__RESET_CNS__SHIFT 0x0000000a
+#define MC_XPB_SUB_CTRL__RESET_HOP_MASK 0x00010000L
+#define MC_XPB_SUB_CTRL__RESET_HOP__SHIFT 0x00000010
+#define MC_XPB_SUB_CTRL__RESET_HST_MASK 0x00008000L
+#define MC_XPB_SUB_CTRL__RESET_HST__SHIFT 0x0000000f
+#define MC_XPB_SUB_CTRL__RESET_MAP_MASK 0x00002000L
+#define MC_XPB_SUB_CTRL__RESET_MAP__SHIFT 0x0000000d
+#define MC_XPB_SUB_CTRL__RESET_RET_MASK 0x00001000L
+#define MC_XPB_SUB_CTRL__RESET_RET__SHIFT 0x0000000c
+#define MC_XPB_SUB_CTRL__RESET_RTR_MASK 0x00000800L
+#define MC_XPB_SUB_CTRL__RESET_RTR__SHIFT 0x0000000b
+#define MC_XPB_SUB_CTRL__RESET_SID_MASK 0x00020000L
+#define MC_XPB_SUB_CTRL__RESET_SID__SHIFT 0x00000011
+#define MC_XPB_SUB_CTRL__RESET_SRB_MASK 0x00040000L
+#define MC_XPB_SUB_CTRL__RESET_SRB__SHIFT 0x00000012
+#define MC_XPB_SUB_CTRL__RESET_WCB_MASK 0x00004000L
+#define MC_XPB_SUB_CTRL__RESET_WCB__SHIFT 0x0000000e
+#define MC_XPB_SUB_CTRL__STALL_CNS_RTR_REQ_MASK 0x00000002L
+#define MC_XPB_SUB_CTRL__STALL_CNS_RTR_REQ__SHIFT 0x00000001
+#define MC_XPB_SUB_CTRL__STALL_HST_HOP_REQ_MASK 0x00000100L
+#define MC_XPB_SUB_CTRL__STALL_HST_HOP_REQ__SHIFT 0x00000008
+#define MC_XPB_SUB_CTRL__STALL_MAP_WCB_REQ_MASK 0x00000010L
+#define MC_XPB_SUB_CTRL__STALL_MAP_WCB_REQ__SHIFT 0x00000004
+#define MC_XPB_SUB_CTRL__STALL_MC_XSP_REQ_SEND_MASK 0x00000040L
+#define MC_XPB_SUB_CTRL__STALL_MC_XSP_REQ_SEND__SHIFT 0x00000006
+#define MC_XPB_SUB_CTRL__STALL_RTR_MAP_REQ_MASK 0x00000008L
+#define MC_XPB_SUB_CTRL__STALL_RTR_MAP_REQ__SHIFT 0x00000003
+#define MC_XPB_SUB_CTRL__STALL_RTR_RPB_WRREQ_MASK 0x00000004L
+#define MC_XPB_SUB_CTRL__STALL_RTR_RPB_WRREQ__SHIFT 0x00000002
+#define MC_XPB_SUB_CTRL__STALL_WCB_HST_REQ_MASK 0x00000080L
+#define MC_XPB_SUB_CTRL__STALL_WCB_HST_REQ__SHIFT 0x00000007
+#define MC_XPB_SUB_CTRL__STALL_WCB_SID_REQ_MASK 0x00000020L
+#define MC_XPB_SUB_CTRL__STALL_WCB_SID_REQ__SHIFT 0x00000005
+#define MC_XPB_SUB_CTRL__STALL_XPB_RPB_REQ_ATTR_MASK 0x00000200L
+#define MC_XPB_SUB_CTRL__STALL_XPB_RPB_REQ_ATTR__SHIFT 0x00000009
+#define MC_XPB_SUB_CTRL__WRREQ_BYPASS_XPB_MASK 0x00000001L
+#define MC_XPB_SUB_CTRL__WRREQ_BYPASS_XPB__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_HST__CHANGE_PREF_MASK 0x0000003fL
+#define MC_XPB_UNC_THRESH_HST__CHANGE_PREF__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_HST__STRONG_PREF_MASK 0x00000fc0L
+#define MC_XPB_UNC_THRESH_HST__STRONG_PREF__SHIFT 0x00000006
+#define MC_XPB_UNC_THRESH_HST__USE_UNFULL_MASK 0x0003f000L
+#define MC_XPB_UNC_THRESH_HST__USE_UNFULL__SHIFT 0x0000000c
+#define MC_XPB_UNC_THRESH_SID__CHANGE_PREF_MASK 0x0000003fL
+#define MC_XPB_UNC_THRESH_SID__CHANGE_PREF__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_SID__STRONG_PREF_MASK 0x00000fc0L
+#define MC_XPB_UNC_THRESH_SID__STRONG_PREF__SHIFT 0x00000006
+#define MC_XPB_UNC_THRESH_SID__USE_UNFULL_MASK 0x0003f000L
+#define MC_XPB_UNC_THRESH_SID__USE_UNFULL__SHIFT 0x0000000c
+#define MC_XPB_WCB_CFG__HST_MAX_MASK 0x00030000L
+#define MC_XPB_WCB_CFG__HST_MAX__SHIFT 0x00000010
+#define MC_XPB_WCB_CFG__SID_MAX_MASK 0x000c0000L
+#define MC_XPB_WCB_CFG__SID_MAX__SHIFT 0x00000012
+#define MC_XPB_WCB_CFG__TIMEOUT_MASK 0x0000ffffL
+#define MC_XPB_WCB_CFG__TIMEOUT__SHIFT 0x00000000
+#define MC_XPB_WCB_STS__PBUF_VLD_MASK 0x0000ffffL
+#define MC_XPB_WCB_STS__PBUF_VLD__SHIFT 0x00000000
+#define MC_XPB_WCB_STS__WCB_HST_DATA_BUF_CNT_MASK 0x007f0000L
+#define MC_XPB_WCB_STS__WCB_HST_DATA_BUF_CNT__SHIFT 0x00000010
+#define MC_XPB_WCB_STS__WCB_SID_DATA_BUF_CNT_MASK 0x3f800000L
+#define MC_XPB_WCB_STS__WCB_SID_DATA_BUF_CNT__SHIFT 0x00000017
+#define MC_XPB_XDMA_PEER_SYS_BAR0__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR0__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR0__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR0__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR0__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR0__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR1__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR1__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR1__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR1__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR1__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR1__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR2__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR2__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR2__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR2__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR2__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR2__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR3__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR3__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR3__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR3__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR3__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR3__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP0__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP0__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP0__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP1__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP1__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP1__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP2__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP2__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP2__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP3__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP3__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP3__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_SRC_APRTR0__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR0__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR1__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR1__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR2__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR2__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR3__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR3__BASE_ADDR__SHIFT 0x00000000
+#define MPLL_AD_FUNC_CNTL__SPARE_MASK 0xfffffff8L
+#define MPLL_AD_FUNC_CNTL__SPARE__SHIFT 0x00000003
+#define MPLL_AD_FUNC_CNTL__YCLK_POST_DIV_MASK 0x00000007L
+#define MPLL_AD_FUNC_CNTL__YCLK_POST_DIV__SHIFT 0x00000000
+#define MPLL_AD_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_AD_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_AD_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_AD_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_AD_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_AD_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_AD_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_AD_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_AD_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_AD_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_AD_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_AD_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_CNTL_MODE__FAST_LOCK_CNTRL_MASK 0x00600000L
+#define MPLL_CNTL_MODE__FAST_LOCK_CNTRL__SHIFT 0x00000015
+#define MPLL_CNTL_MODE__FAST_LOCK_EN_MASK 0x00100000L
+#define MPLL_CNTL_MODE__FAST_LOCK_EN__SHIFT 0x00000014
+#define MPLL_CNTL_MODE__FORCE_TESTMODE_MASK 0x00020000L
+#define MPLL_CNTL_MODE__FORCE_TESTMODE__SHIFT 0x00000011
+#define MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK 0x80000000L
+#define MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT 0x0000001f
+#define MPLL_CNTL_MODE__INSTR_DELAY_MASK 0x000000ffL
+#define MPLL_CNTL_MODE__INSTR_DELAY__SHIFT 0x00000000
+#define MPLL_CNTL_MODE__MPLL_CHG_STATUS_MASK 0x00010000L
+#define MPLL_CNTL_MODE__MPLL_CHG_STATUS__SHIFT 0x00000010
+#define MPLL_CNTL_MODE__MPLL_CTLREQ_MASK 0x00004000L
+#define MPLL_CNTL_MODE__MPLL_CTLREQ__SHIFT 0x0000000e
+#define MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK 0x00000800L
+#define MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT 0x0000000b
+#define MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK 0x00000100L
+#define MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT 0x00000008
+#define MPLL_CNTL_MODE__QDR_MASK 0x00002000L
+#define MPLL_CNTL_MODE__QDR__SHIFT 0x0000000d
+#define MPLL_CNTL_MODE__SPARE_1_MASK 0x00001000L
+#define MPLL_CNTL_MODE__SPARE_1__SHIFT 0x0000000c
+#define MPLL_CNTL_MODE__SPARE_2_MASK 0x00800000L
+#define MPLL_CNTL_MODE__SPARE_2__SHIFT 0x00000017
+#define MPLL_CNTL_MODE__SPARE_3_MASK 0x70000000L
+#define MPLL_CNTL_MODE__SPARE_3__SHIFT 0x0000001c
+#define MPLL_CNTL_MODE__SS_DSMODE_EN_MASK 0x04000000L
+#define MPLL_CNTL_MODE__SS_DSMODE_EN__SHIFT 0x0000001a
+#define MPLL_CNTL_MODE__SS_SSEN_MASK 0x03000000L
+#define MPLL_CNTL_MODE__SS_SSEN__SHIFT 0x00000018
+#define MPLL_CNTL_MODE__VTOI_BIAS_CNTRL_MASK 0x08000000L
+#define MPLL_CNTL_MODE__VTOI_BIAS_CNTRL__SHIFT 0x0000001b
+#define MPLL_CONTROL__AD_BG_PWRON_MASK 0x00001000L
+#define MPLL_CONTROL__AD_BG_PWRON__SHIFT 0x0000000c
+#define MPLL_CONTROL__AD_PLL_PWRON_MASK 0x00002000L
+#define MPLL_CONTROL__AD_PLL_PWRON__SHIFT 0x0000000d
+#define MPLL_CONTROL__AD_PLL_RESET_MASK 0x00004000L
+#define MPLL_CONTROL__AD_PLL_RESET__SHIFT 0x0000000e
+#define MPLL_CONTROL__DQ_0_0_BG_PWRON_MASK 0x00010000L
+#define MPLL_CONTROL__DQ_0_0_BG_PWRON__SHIFT 0x00000010
+#define MPLL_CONTROL__DQ_0_0_PLL_PWRON_MASK 0x00020000L
+#define MPLL_CONTROL__DQ_0_0_PLL_PWRON__SHIFT 0x00000011
+#define MPLL_CONTROL__DQ_0_0_PLL_RESET_MASK 0x00040000L
+#define MPLL_CONTROL__DQ_0_0_PLL_RESET__SHIFT 0x00000012
+#define MPLL_CONTROL__DQ_0_1_BG_PWRON_MASK 0x00100000L
+#define MPLL_CONTROL__DQ_0_1_BG_PWRON__SHIFT 0x00000014
+#define MPLL_CONTROL__DQ_0_1_PLL_PWRON_MASK 0x00200000L
+#define MPLL_CONTROL__DQ_0_1_PLL_PWRON__SHIFT 0x00000015
+#define MPLL_CONTROL__DQ_0_1_PLL_RESET_MASK 0x00400000L
+#define MPLL_CONTROL__DQ_0_1_PLL_RESET__SHIFT 0x00000016
+#define MPLL_CONTROL__DQ_1_0_BG_PWRON_MASK 0x01000000L
+#define MPLL_CONTROL__DQ_1_0_BG_PWRON__SHIFT 0x00000018
+#define MPLL_CONTROL__DQ_1_0_PLL_PWRON_MASK 0x02000000L
+#define MPLL_CONTROL__DQ_1_0_PLL_PWRON__SHIFT 0x00000019
+#define MPLL_CONTROL__DQ_1_0_PLL_RESET_MASK 0x04000000L
+#define MPLL_CONTROL__DQ_1_0_PLL_RESET__SHIFT 0x0000001a
+#define MPLL_CONTROL__DQ_1_1_BG_PWRON_MASK 0x10000000L
+#define MPLL_CONTROL__DQ_1_1_BG_PWRON__SHIFT 0x0000001c
+#define MPLL_CONTROL__DQ_1_1_PLL_PWRON_MASK 0x20000000L
+#define MPLL_CONTROL__DQ_1_1_PLL_PWRON__SHIFT 0x0000001d
+#define MPLL_CONTROL__DQ_1_1_PLL_RESET_MASK 0x40000000L
+#define MPLL_CONTROL__DQ_1_1_PLL_RESET__SHIFT 0x0000001e
+#define MPLL_CONTROL__GDDR_PWRON_MASK 0x00000001L
+#define MPLL_CONTROL__GDDR_PWRON__SHIFT 0x00000000
+#define MPLL_CONTROL__PLL_BUF_PWRON_TX_MASK 0x00000004L
+#define MPLL_CONTROL__PLL_BUF_PWRON_TX__SHIFT 0x00000002
+#define MPLL_CONTROL__REFCLK_PWRON_MASK 0x00000002L
+#define MPLL_CONTROL__REFCLK_PWRON__SHIFT 0x00000001
+#define MPLL_CONTROL__SPARE_AD_0_MASK 0x00008000L
+#define MPLL_CONTROL__SPARE_AD_0__SHIFT 0x0000000f
+#define MPLL_CONTROL__SPARE_DQ_0_0_MASK 0x00080000L
+#define MPLL_CONTROL__SPARE_DQ_0_0__SHIFT 0x00000013
+#define MPLL_CONTROL__SPARE_DQ_0_1_MASK 0x00800000L
+#define MPLL_CONTROL__SPARE_DQ_0_1__SHIFT 0x00000017
+#define MPLL_CONTROL__SPARE_DQ_1_0_MASK 0x08000000L
+#define MPLL_CONTROL__SPARE_DQ_1_0__SHIFT 0x0000001b
+#define MPLL_CONTROL__SPARE_DQ_1_1_MASK 0x80000000L
+#define MPLL_CONTROL__SPARE_DQ_1_1__SHIFT 0x0000001f
+#define MPLL_DQ_0_0_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_0_0_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_0_0_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_0_0_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_0_0_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_0_0_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_0_0_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_0_0_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_0_1_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_0_1_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_0_1_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_0_1_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_0_1_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_0_1_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_0_1_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_0_1_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_1_0_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_1_0_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_1_0_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_1_0_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_1_0_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_1_0_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_1_0_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_1_0_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_1_1_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_1_1_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_1_1_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_1_1_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_1_1_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_1_1_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_1_1_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_1_1_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_FUNC_CNTL__SPARE_0_MASK 0x00000008L
+#define MPLL_DQ_FUNC_CNTL__SPARE_0__SHIFT 0x00000003
+#define MPLL_DQ_FUNC_CNTL__SPARE_MASK 0xffffffe0L
+#define MPLL_DQ_FUNC_CNTL__SPARE__SHIFT 0x00000005
+#define MPLL_DQ_FUNC_CNTL__YCLK_POST_DIV_MASK 0x00000007L
+#define MPLL_DQ_FUNC_CNTL__YCLK_POST_DIV__SHIFT 0x00000000
+#define MPLL_DQ_FUNC_CNTL__YCLK_SEL_MASK 0x00000010L
+#define MPLL_DQ_FUNC_CNTL__YCLK_SEL__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_1__CLKF_MASK 0x0fff0000L
+#define MPLL_FUNC_CNTL_1__CLKFRAC_MASK 0x0000fff0L
+#define MPLL_FUNC_CNTL_1__CLKFRAC__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_1__CLKF__SHIFT 0x00000010
+#define MPLL_FUNC_CNTL_1__SPARE_0_MASK 0x0000000cL
+#define MPLL_FUNC_CNTL_1__SPARE_0__SHIFT 0x00000002
+#define MPLL_FUNC_CNTL_1__SPARE_1_MASK 0xf0000000L
+#define MPLL_FUNC_CNTL_1__SPARE_1__SHIFT 0x0000001c
+#define MPLL_FUNC_CNTL_1__VCO_MODE_MASK 0x00000003L
+#define MPLL_FUNC_CNTL_1__VCO_MODE__SHIFT 0x00000000
+#define MPLL_FUNC_CNTL_2__BACKUP_2_MASK 0x000e0000L
+#define MPLL_FUNC_CNTL_2__BACKUP_2__SHIFT 0x00000011
+#define MPLL_FUNC_CNTL_2__BACKUP_MASK 0xf8000000L
+#define MPLL_FUNC_CNTL_2__BACKUP__SHIFT 0x0000001b
+#define MPLL_FUNC_CNTL_2__LF_CNTRL_MASK 0x07f00000L
+#define MPLL_FUNC_CNTL_2__LF_CNTRL__SHIFT 0x00000014
+#define MPLL_FUNC_CNTL_2__MPLL_UNLOCK_CLEAR_MASK 0x00000080L
+#define MPLL_FUNC_CNTL_2__MPLL_UNLOCK_CLEAR__SHIFT 0x00000007
+#define MPLL_FUNC_CNTL_2__PFD_RESET_CNTRL_MASK 0x00003000L
+#define MPLL_FUNC_CNTL_2__PFD_RESET_CNTRL__SHIFT 0x0000000c
+#define MPLL_FUNC_CNTL_2__RESET_EN_MASK 0x00000004L
+#define MPLL_FUNC_CNTL_2__RESET_EN__SHIFT 0x00000002
+#define MPLL_FUNC_CNTL_2__RESET_TIMER_MASK 0x00000c00L
+#define MPLL_FUNC_CNTL_2__RESET_TIMER__SHIFT 0x0000000a
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_EN_MASK 0x00000008L
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_EN__SHIFT 0x00000003
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_SRC_MASK 0x00000010L
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_SRC__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_2__TEST_BYPMCLK_MASK 0x00000040L
+#define MPLL_FUNC_CNTL_2__TEST_BYPMCLK__SHIFT 0x00000006
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_FRAC_BYPASS_MASK 0x00000020L
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_FRAC_BYPASS__SHIFT 0x00000005
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_SSC_BYPASS_MASK 0x00000200L
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_SSC_BYPASS__SHIFT 0x00000009
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_CNTRL_MASK 0x00000100L
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_CNTRL__SHIFT 0x00000008
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_EN_MASK 0x00000002L
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_EN__SHIFT 0x00000001
+#define MPLL_FUNC_CNTL_2__VCTRLADC_EN_MASK 0x00000001L
+#define MPLL_FUNC_CNTL_2__VCTRLADC_EN__SHIFT 0x00000000
+#define MPLL_FUNC_CNTL__BG_100ADJ_MASK 0x00000f00L
+#define MPLL_FUNC_CNTL__BG_100ADJ__SHIFT 0x00000008
+#define MPLL_FUNC_CNTL__BG_135ADJ_MASK 0x000f0000L
+#define MPLL_FUNC_CNTL__BG_135ADJ__SHIFT 0x00000010
+#define MPLL_FUNC_CNTL__BWCTRL_MASK 0x0ff00000L
+#define MPLL_FUNC_CNTL__BWCTRL__SHIFT 0x00000014
+#define MPLL_FUNC_CNTL__REG_BIAS_MASK 0xc0000000L
+#define MPLL_FUNC_CNTL__REG_BIAS__SHIFT 0x0000001e
+#define MPLL_FUNC_CNTL__SPARE_0_MASK 0x00000020L
+#define MPLL_FUNC_CNTL__SPARE_0__SHIFT 0x00000005
+#define MPLL_SEQ_UCODE_1__INSTR0_MASK 0x0000000fL
+#define MPLL_SEQ_UCODE_1__INSTR0__SHIFT 0x00000000
+#define MPLL_SEQ_UCODE_1__INSTR1_MASK 0x000000f0L
+#define MPLL_SEQ_UCODE_1__INSTR1__SHIFT 0x00000004
+#define MPLL_SEQ_UCODE_1__INSTR2_MASK 0x00000f00L
+#define MPLL_SEQ_UCODE_1__INSTR2__SHIFT 0x00000008
+#define MPLL_SEQ_UCODE_1__INSTR3_MASK 0x0000f000L
+#define MPLL_SEQ_UCODE_1__INSTR3__SHIFT 0x0000000c
+#define MPLL_SEQ_UCODE_1__INSTR4_MASK 0x000f0000L
+#define MPLL_SEQ_UCODE_1__INSTR4__SHIFT 0x00000010
+#define MPLL_SEQ_UCODE_1__INSTR5_MASK 0x00f00000L
+#define MPLL_SEQ_UCODE_1__INSTR5__SHIFT 0x00000014
+#define MPLL_SEQ_UCODE_1__INSTR6_MASK 0x0f000000L
+#define MPLL_SEQ_UCODE_1__INSTR6__SHIFT 0x00000018
+#define MPLL_SEQ_UCODE_1__INSTR7_MASK 0xf0000000L
+#define MPLL_SEQ_UCODE_1__INSTR7__SHIFT 0x0000001c
+#define MPLL_SEQ_UCODE_2__INSTR10_MASK 0x00000f00L
+#define MPLL_SEQ_UCODE_2__INSTR10__SHIFT 0x00000008
+#define MPLL_SEQ_UCODE_2__INSTR11_MASK 0x0000f000L
+#define MPLL_SEQ_UCODE_2__INSTR11__SHIFT 0x0000000c
+#define MPLL_SEQ_UCODE_2__INSTR12_MASK 0x000f0000L
+#define MPLL_SEQ_UCODE_2__INSTR12__SHIFT 0x00000010
+#define MPLL_SEQ_UCODE_2__INSTR13_MASK 0x00f00000L
+#define MPLL_SEQ_UCODE_2__INSTR13__SHIFT 0x00000014
+#define MPLL_SEQ_UCODE_2__INSTR14_MASK 0x0f000000L
+#define MPLL_SEQ_UCODE_2__INSTR14__SHIFT 0x00000018
+#define MPLL_SEQ_UCODE_2__INSTR15_MASK 0xf0000000L
+#define MPLL_SEQ_UCODE_2__INSTR15__SHIFT 0x0000001c
+#define MPLL_SEQ_UCODE_2__INSTR8_MASK 0x0000000fL
+#define MPLL_SEQ_UCODE_2__INSTR8__SHIFT 0x00000000
+#define MPLL_SEQ_UCODE_2__INSTR9_MASK 0x000000f0L
+#define MPLL_SEQ_UCODE_2__INSTR9__SHIFT 0x00000004
+#define MPLL_SS1__CLKV_MASK 0x03ffffffL
+#define MPLL_SS1__CLKV__SHIFT 0x00000000
+#define MPLL_SS1__SPARE_MASK 0xfc000000L
+#define MPLL_SS1__SPARE__SHIFT 0x0000001a
+#define MPLL_SS2__CLKS_MASK 0x00000fffL
+#define MPLL_SS2__CLKS__SHIFT 0x00000000
+#define MPLL_SS2__SPARE_MASK 0xfffff000L
+#define MPLL_SS2__SPARE__SHIFT 0x0000000c
+#define MPLL_TIME__MPLL_LOCK_TIME_MASK 0x0000ffffL
+#define MPLL_TIME__MPLL_LOCK_TIME__SHIFT 0x00000000
+#define MPLL_TIME__MPLL_RESET_TIME_MASK 0xffff0000L
+#define MPLL_TIME__MPLL_RESET_TIME__SHIFT 0x00000010
+#define VM_CONTEXT0_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000008L
+#define VM_CONTEXT0_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000003
+#define VM_CONTEXT0_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR_MASK 0x00000001L
+#define VM_CONTEXT0_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT_MASK 0x00000002L
+#define VM_CONTEXT0_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT__SHIFT 0x00000001
+#define VM_CONTEXT0_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT_MASK 0x00000004L
+#define VM_CONTEXT0_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT__SHIFT 0x00000002
+#define VM_CONTEXT0_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE_MASK 0x00000010L
+#define VM_CONTEXT0_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE__SHIFT 0x00000004
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000080L
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000007
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000040L
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000006
+#define VM_CONTEXT0_CNTL__ENABLE_CONTEXT_MASK 0x00000001L
+#define VM_CONTEXT0_CNTL__ENABLE_CONTEXT__SHIFT 0x00000000
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_BLOCK_SIZE_MASK 0x0f000000L
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT 0x00000018
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH_MASK 0x00000006L
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH__SHIFT 0x00000001
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000400L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000a
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000200L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000009
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00000800L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000b
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00400000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000016
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00200000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000015
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00800000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000017
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000010L
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000004
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000008L
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000003
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00010000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000010
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00008000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000f
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00020000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000011
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00002000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000d
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00001000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000c
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00004000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000e
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00080000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000013
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00040000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000012
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00100000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000014
+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT0_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID_MASK 0x000ff000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID__SHIFT 0x0000000c
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW_MASK 0x01000000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW__SHIFT 0x00000018
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__PROTECTIONS_MASK 0x000000ffL
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__PROTECTIONS__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__VMID_MASK 0x1e000000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__VMID__SHIFT 0x00000019
+#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000008L
+#define VM_CONTEXT1_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000003
+#define VM_CONTEXT1_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR_MASK 0x00000001L
+#define VM_CONTEXT1_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT_MASK 0x00000002L
+#define VM_CONTEXT1_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT__SHIFT 0x00000001
+#define VM_CONTEXT1_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT_MASK 0x00000004L
+#define VM_CONTEXT1_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT__SHIFT 0x00000002
+#define VM_CONTEXT1_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE_MASK 0x00000010L
+#define VM_CONTEXT1_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE__SHIFT 0x00000004
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000080L
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000007
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000040L
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000006
+#define VM_CONTEXT1_CNTL__ENABLE_CONTEXT_MASK 0x00000001L
+#define VM_CONTEXT1_CNTL__ENABLE_CONTEXT__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE_MASK 0x0f000000L
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT 0x00000018
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH_MASK 0x00000006L
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH__SHIFT 0x00000001
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000400L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000a
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000200L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000009
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00000800L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000b
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00400000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000016
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00200000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000015
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00800000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000017
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000010L
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000004
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000008L
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000003
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00010000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000010
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00008000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000f
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00020000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000011
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00002000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000d
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00001000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000c
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00004000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000e
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00080000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000013
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00040000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000012
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00100000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000014
+#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID_MASK 0x000ff000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID__SHIFT 0x0000000c
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW_MASK 0x01000000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW__SHIFT 0x00000018
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__PROTECTIONS_MASK 0x000000ffL
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__PROTECTIONS__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__VMID_MASK 0x1e000000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__VMID__SHIFT 0x00000019
+#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_0_MASK 0x00000001L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_0__SHIFT 0x00000000
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_10_MASK 0x00000400L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_10__SHIFT 0x0000000a
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_11_MASK 0x00000800L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_11__SHIFT 0x0000000b
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_12_MASK 0x00001000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_12__SHIFT 0x0000000c
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_13_MASK 0x00002000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_13__SHIFT 0x0000000d
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_14_MASK 0x00004000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_14__SHIFT 0x0000000e
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_15_MASK 0x00008000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_15__SHIFT 0x0000000f
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_1_MASK 0x00000002L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_1__SHIFT 0x00000001
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_2_MASK 0x00000004L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_2__SHIFT 0x00000002
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_3_MASK 0x00000008L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_3__SHIFT 0x00000003
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_4_MASK 0x00000010L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_4__SHIFT 0x00000004
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_5_MASK 0x00000020L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_5__SHIFT 0x00000005
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_6_MASK 0x00000040L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_6__SHIFT 0x00000006
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_7_MASK 0x00000080L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_7__SHIFT 0x00000007
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_8_MASK 0x00000100L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_8__SHIFT 0x00000008
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_9_MASK 0x00000200L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_9__SHIFT 0x00000009
+#define VM_DEBUG__FLAGS_MASK 0xffffffffL
+#define VM_DEBUG__FLAGS__SHIFT 0x00000000
+#define VM_DUMMY_PAGE_FAULT_ADDR__DUMMY_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_DUMMY_PAGE_FAULT_ADDR__DUMMY_PAGE_ADDR__SHIFT 0x00000000
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_ADDRESS_LOGICAL_MASK 0x00000002L
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_ADDRESS_LOGICAL__SHIFT 0x00000001
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_COMPARE_MASK_MASK 0x0000000cL
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_COMPARE_MASK__SHIFT 0x00000002
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_FAULT_ENABLE_MASK 0x00000001L
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_FAULT_ENABLE__SHIFT 0x00000000
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK 0x000001ffL
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK_MASK 0x0003fe00L
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK__SHIFT 0x00000009
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT__SHIFT 0x00000000
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_0_MASK 0x00000001L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_0__SHIFT 0x00000000
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_10_MASK 0x00000400L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_10__SHIFT 0x0000000a
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_11_MASK 0x00000800L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_11__SHIFT 0x0000000b
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_12_MASK 0x00001000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_12__SHIFT 0x0000000c
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_13_MASK 0x00002000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_13__SHIFT 0x0000000d
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_14_MASK 0x00004000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_14__SHIFT 0x0000000e
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_15_MASK 0x00008000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_15__SHIFT 0x0000000f
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_1_MASK 0x00000002L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_1__SHIFT 0x00000001
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_2_MASK 0x00000004L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_2__SHIFT 0x00000002
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_3_MASK 0x00000008L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_3__SHIFT 0x00000003
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_4_MASK 0x00000010L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_4__SHIFT 0x00000004
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_5_MASK 0x00000020L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_5__SHIFT 0x00000005
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_6_MASK 0x00000040L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_6__SHIFT 0x00000006
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_7_MASK 0x00000080L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_7__SHIFT 0x00000007
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_8_MASK 0x00000100L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_8__SHIFT 0x00000008
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_9_MASK 0x00000200L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_9__SHIFT 0x00000009
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_0_MASK 0x00000001L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_0__SHIFT 0x00000000
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_10_MASK 0x00000400L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_10__SHIFT 0x0000000a
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_11_MASK 0x00000800L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_11__SHIFT 0x0000000b
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_12_MASK 0x00001000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_12__SHIFT 0x0000000c
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_13_MASK 0x00002000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_13__SHIFT 0x0000000d
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_14_MASK 0x00004000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_14__SHIFT 0x0000000e
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_15_MASK 0x00008000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_15__SHIFT 0x0000000f
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_1_MASK 0x00000002L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_1__SHIFT 0x00000001
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_2_MASK 0x00000004L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_2__SHIFT 0x00000002
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_3_MASK 0x00000008L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_3__SHIFT 0x00000003
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_4_MASK 0x00000010L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_4__SHIFT 0x00000004
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_5_MASK 0x00000020L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_5__SHIFT 0x00000005
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_6_MASK 0x00000040L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_6__SHIFT 0x00000006
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_7_MASK 0x00000080L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_7__SHIFT 0x00000007
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_8_MASK 0x00000100L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_8__SHIFT 0x00000008
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_9_MASK 0x00000200L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_9__SHIFT 0x00000009
+#define VM_L2_BANK_SELECT_MASKA__BANK_SELECT_MASK_MASK 0x0fffffffL
+#define VM_L2_BANK_SELECT_MASKA__BANK_SELECT_MASK__SHIFT 0x00000000
+#define VM_L2_BANK_SELECT_MASKB__BANK_SELECT_MASK_MASK 0x000000ffL
+#define VM_L2_BANK_SELECT_MASKB__BANK_SELECT_MASK__SHIFT 0x00000000
+#define VM_L2_CG__ENABLE_MASK 0x00040000L
+#define VM_L2_CG__ENABLE__SHIFT 0x00000012
+#define VM_L2_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define VM_L2_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define VM_L2_CG__OFFDLY_MASK 0x00000fc0L
+#define VM_L2_CG__OFFDLY__SHIFT 0x00000006
+#define VM_L2_CNTL2__DISABLE_BIGK_CACHE_OPTIMIZATION_MASK 0x00400000L
+#define VM_L2_CNTL2__DISABLE_BIGK_CACHE_OPTIMIZATION__SHIFT 0x00000016
+#define VM_L2_CNTL2__DISABLE_INVALIDATE_PER_DOMAIN_MASK 0x00200000L
+#define VM_L2_CNTL2__DISABLE_INVALIDATE_PER_DOMAIN__SHIFT 0x00000015
+#define VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS_MASK 0x00000001L
+#define VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS__SHIFT 0x00000000
+#define VM_L2_CNTL2__INVALIDATE_CACHE_MODE_MASK 0x0c000000L
+#define VM_L2_CNTL2__INVALIDATE_CACHE_MODE__SHIFT 0x0000001a
+#define VM_L2_CNTL2__INVALIDATE_L2_CACHE_MASK 0x00000002L
+#define VM_L2_CNTL2__INVALIDATE_L2_CACHE__SHIFT 0x00000001
+#define VM_L2_CNTL2__L2_CACHE_BIGK_VMID_MODE_MASK 0x03800000L
+#define VM_L2_CNTL2__L2_CACHE_BIGK_VMID_MODE__SHIFT 0x00000017
+#define VM_L2_CNTL3__BANK_SELECT_MASK 0x0000003fL
+#define VM_L2_CNTL3__BANK_SELECT__SHIFT 0x00000000
+#define VM_L2_CNTL3__L2_CACHE_4K_EFFECTIVE_SIZE_MASK 0x00e00000L
+#define VM_L2_CNTL3__L2_CACHE_4K_EFFECTIVE_SIZE__SHIFT 0x00000015
+#define VM_L2_CNTL3__L2_CACHE_4K_FORCE_MISS_MASK 0x10000000L
+#define VM_L2_CNTL3__L2_CACHE_4K_FORCE_MISS__SHIFT 0x0000001c
+#define VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK 0x00100000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY__SHIFT 0x00000014
+#define VM_L2_CNTL3__L2_CACHE_BIGK_EFFECTIVE_SIZE_MASK 0x0f000000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_EFFECTIVE_SIZE__SHIFT 0x00000018
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FORCE_MISS_MASK 0x20000000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FORCE_MISS__SHIFT 0x0000001d
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE_MASK 0x000f8000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT 0x0000000f
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_MODE_MASK 0x000000c0L
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_MODE__SHIFT 0x00000006
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_WILDCARD_REFERENCE_VALUE_MASK 0x00001f00L
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_WILDCARD_REFERENCE_VALUE__SHIFT 0x00000008
+#define VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE_MASK 0x00180000L
+#define VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT 0x00000013
+#define VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE_MASK 0x00038000L
+#define VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT 0x0000000f
+#define VM_L2_CNTL__ENABLE_L2_CACHE_MASK 0x00000001L
+#define VM_L2_CNTL__ENABLE_L2_CACHE__SHIFT 0x00000000
+#define VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING_MASK 0x00000002L
+#define VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING__SHIFT 0x00000001
+#define VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK 0x00000400L
+#define VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE__SHIFT 0x0000000a
+#define VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK 0x00000200L
+#define VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE__SHIFT 0x00000009
+#define VM_L2_CNTL__IDENTITY_MODE_FRAGMENT_SIZE_MASK 0x03e00000L
+#define VM_L2_CNTL__IDENTITY_MODE_FRAGMENT_SIZE__SHIFT 0x00000015
+#define VM_L2_CNTL__L2_CACHE_4K_SWAP_TAG_INDEX_LSBS_MASK 0x0c000000L
+#define VM_L2_CNTL__L2_CACHE_4K_SWAP_TAG_INDEX_LSBS__SHIFT 0x0000001a
+#define VM_L2_CNTL__L2_CACHE_BIGK_SWAP_TAG_INDEX_LSBS_MASK 0x70000000L
+#define VM_L2_CNTL__L2_CACHE_BIGK_SWAP_TAG_INDEX_LSBS__SHIFT 0x0000001c
+#define VM_L2_CNTL__L2_CACHE_PDE_ENDIAN_SWAP_MODE_MASK 0x00000030L
+#define VM_L2_CNTL__L2_CACHE_PDE_ENDIAN_SWAP_MODE__SHIFT 0x00000004
+#define VM_L2_CNTL__L2_CACHE_PTE_ENDIAN_SWAP_MODE_MASK 0x0000000cL
+#define VM_L2_CNTL__L2_CACHE_PTE_ENDIAN_SWAP_MODE__SHIFT 0x00000002
+#define VM_L2_CNTL__L2_PDE0_CACHE_SPLIT_MODE_MASK 0x00007000L
+#define VM_L2_CNTL__L2_PDE0_CACHE_SPLIT_MODE__SHIFT 0x0000000c
+#define VM_L2_CNTL__L2_PDE0_CACHE_TAG_GENERATION_MODE_MASK 0x00000100L
+#define VM_L2_CNTL__L2_PDE0_CACHE_TAG_GENERATION_MODE__SHIFT 0x00000008
+#define VM_L2_CNTL__PDE_FAULT_CLASSIFICATION_MASK 0x00040000L
+#define VM_L2_CNTL__PDE_FAULT_CLASSIFICATION__SHIFT 0x00000012
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET__PHYSICAL_PAGE_OFFSET_MASK 0x0fffffffL
+#define VM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET__PHYSICAL_PAGE_OFFSET__SHIFT 0x00000000
+#define VM_L2_STATUS__CONTEXT_DOMAIN_BUSY_MASK 0x0001fffeL
+#define VM_L2_STATUS__CONTEXT_DOMAIN_BUSY__SHIFT 0x00000001
+#define VM_L2_STATUS__L2_BUSY_MASK 0x00000001L
+#define VM_L2_STATUS__L2_BUSY__SHIFT 0x00000000
+#define VM_PRT_APERTURE0_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE0_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE0_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE0_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE1_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE1_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE1_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE1_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE2_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE2_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE2_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE2_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE3_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE3_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE3_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE3_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_CNTL__L1_TLB_STORE_INVALID_ENTRIES_MASK 0x00000008L
+#define VM_PRT_CNTL__L1_TLB_STORE_INVALID_ENTRIES__SHIFT 0x00000003
+#define VM_PRT_CNTL__L2_CACHE_STORE_INVALID_ENTRIES_MASK 0x00000004L
+#define VM_PRT_CNTL__L2_CACHE_STORE_INVALID_ENTRIES__SHIFT 0x00000002
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h
new file mode 100644
index 000000000000..edc8a793a95d
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright (C) 2016 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 OSS_1_0_D_H
+#define OSS_1_0_D_H
+
+#define ixCLIENT0_BM 0x0220
+#define ixCLIENT0_CD0 0x0210
+#define ixCLIENT0_CD1 0x0214
+#define ixCLIENT0_CD2 0x0218
+#define ixCLIENT0_CD3 0x021C
+#define ixCLIENT0_CK0 0x0200
+#define ixCLIENT0_CK1 0x0204
+#define ixCLIENT0_CK2 0x0208
+#define ixCLIENT0_CK3 0x020C
+#define ixCLIENT0_K0 0x01F0
+#define ixCLIENT0_K1 0x01F4
+#define ixCLIENT0_K2 0x01F8
+#define ixCLIENT0_K3 0x01FC
+#define ixCLIENT0_OFFSET 0x0224
+#define ixCLIENT0_OFFSET_HI 0x0290
+#define ixCLIENT0_STATUS 0x0228
+#define ixCLIENT1_BM 0x025C
+#define ixCLIENT1_CD0 0x024C
+#define ixCLIENT1_CD1 0x0250
+#define ixCLIENT1_CD2 0x0254
+#define ixCLIENT1_CD3 0x0258
+#define ixCLIENT1_CK0 0x023C
+#define ixCLIENT1_CK1 0x0240
+#define ixCLIENT1_CK2 0x0244
+#define ixCLIENT1_CK3 0x0248
+#define ixCLIENT1_K0 0x022C
+#define ixCLIENT1_K1 0x0230
+#define ixCLIENT1_K2 0x0234
+#define ixCLIENT1_K3 0x0238
+#define ixCLIENT1_OFFSET 0x0260
+#define ixCLIENT1_OFFSET_HI 0x0294
+#define ixCLIENT1_PORT_STATUS 0x0264
+#define ixCLIENT2_BM 0x01E4
+#define ixCLIENT2_CD0 0x01D4
+#define ixCLIENT2_CD1 0x01D8
+#define ixCLIENT2_CD2 0x01DC
+#define ixCLIENT2_CD3 0x01E0
+#define ixCLIENT2_CK0 0x01C4
+#define ixCLIENT2_CK1 0x01C8
+#define ixCLIENT2_CK2 0x01CC
+#define ixCLIENT2_CK3 0x01D0
+#define ixCLIENT2_K0 0x01B4
+#define ixCLIENT2_K1 0x01B8
+#define ixCLIENT2_K2 0x01BC
+#define ixCLIENT2_K3 0x01C0
+#define ixCLIENT2_OFFSET 0x01E8
+#define ixCLIENT2_OFFSET_HI 0x0298
+#define ixCLIENT2_STATUS 0x01EC
+#define ixCLIENT3_BM 0x02D4
+#define ixCLIENT3_CD0 0x02C4
+#define ixCLIENT3_CD1 0x02C8
+#define ixCLIENT3_CD2 0x02CC
+#define ixCLIENT3_CD3 0x02D0
+#define ixCLIENT3_CK0 0x02B4
+#define ixCLIENT3_CK1 0x02B8
+#define ixCLIENT3_CK2 0x02BC
+#define ixCLIENT3_CK3 0x02C0
+#define ixCLIENT3_K0 0x02A4
+#define ixCLIENT3_K1 0x02A8
+#define ixCLIENT3_K2 0x02AC
+#define ixCLIENT3_K3 0x02B0
+#define ixCLIENT3_OFFSET 0x02D8
+#define ixCLIENT3_OFFSET_HI 0x02A0
+#define ixCLIENT3_STATUS 0x02DC
+#define ixDH_TEST 0x0000
+#define ixEXP0 0x0034
+#define ixEXP1 0x0038
+#define ixEXP2 0x003C
+#define ixEXP3 0x0040
+#define ixEXP4 0x0044
+#define ixEXP5 0x0048
+#define ixEXP6 0x004C
+#define ixEXP7 0x0050
+#define ixHFS_SEED0 0x0278
+#define ixHFS_SEED1 0x027C
+#define ixHFS_SEED2 0x0280
+#define ixHFS_SEED3 0x0284
+#define ixKEFUSE0 0x0268
+#define ixKEFUSE1 0x026C
+#define ixKEFUSE2 0x0270
+#define ixKEFUSE3 0x0274
+#define ixKHFS0 0x0004
+#define ixKHFS1 0x0008
+#define ixKHFS2 0x000C
+#define ixKHFS3 0x0010
+#define ixKSESSION0 0x0014
+#define ixKSESSION1 0x0018
+#define ixKSESSION2 0x001C
+#define ixKSESSION3 0x0020
+#define ixKSIG0 0x0024
+#define ixKSIG1 0x0028
+#define ixKSIG2 0x002C
+#define ixKSIG3 0x0030
+#define ixLX0 0x0054
+#define ixLX1 0x0058
+#define ixLX2 0x005C
+#define ixLX3 0x0060
+#define ixRINGOSC_MASK 0x0288
+#define ixSPU_PORT_STATUS 0x029C
+#define mmCC_DRM_ID_STRAPS 0x1559
+#define mmCC_SYS_RB_BACKEND_DISABLE 0x03A0
+#define mmCC_SYS_RB_REDUNDANCY 0x039F
+#define mmCGTT_DRM_CLK_CTRL0 0x1579
+#define mmCP_CONFIG 0x0F92
+#define mmDC_TEST_DEBUG_DATA 0x157D
+#define mmDC_TEST_DEBUG_INDEX 0x157C
+#define mmGC_USER_SYS_RB_BACKEND_DISABLE 0x03A1
+#define mmHDP_ADDR_CONFIG 0x0BD2
+#define mmHDP_DEBUG0 0x0BCC
+#define mmHDP_DEBUG1 0x0BCD
+#define mmHDP_HOST_PATH_CNTL 0x0B00
+#define mmHDP_LAST_SURFACE_HIT 0x0BCE
+#define mmHDP_MEMIO_ADDR 0x0BF7
+#define mmHDP_MEMIO_CNTL 0x0BF6
+#define mmHDP_MEMIO_RD_DATA 0x0BFA
+#define mmHDP_MEMIO_STATUS 0x0BF8
+#define mmHDP_MEMIO_WR_DATA 0x0BF9
+#define mmHDP_MEM_POWER_LS 0x0BD4
+#define mmHDP_MISC_CNTL 0x0BD3
+#define mmHDP_NONSURFACE_BASE 0x0B01
+#define mmHDP_NONSURFACE_INFO 0x0B02
+#define mmHDP_NONSURFACE_PREFETCH 0x0BD5
+#define mmHDP_NONSURFACE_SIZE 0x0B03
+#define mmHDP_NONSURF_FLAGS 0x0BC9
+#define mmHDP_NONSURF_FLAGS_CLR 0x0BCA
+#define mmHDP_OUTSTANDING_REQ 0x0BD1
+#define mmHDP_SC_MULTI_CHIP_CNTL 0x0BD0
+#define mmHDP_SW_SEMAPHORE 0x0BCB
+#define mmHDP_TILING_CONFIG 0x0BCF
+#define mmHDP_XDP_BARS_ADDR_39_36 0x0C44
+#define mmHDP_XDP_BUSY_STS 0x0C3E
+#define mmHDP_XDP_CGTT_BLK_CTRL 0x0C33
+#define mmHDP_XDP_CHKN 0x0C40
+#define mmHDP_XDP_D2H_BAR_UPDATE 0x0C02
+#define mmHDP_XDP_D2H_FLUSH 0x0C01
+#define mmHDP_XDP_D2H_RSVD_10 0x0C0A
+#define mmHDP_XDP_D2H_RSVD_11 0x0C0B
+#define mmHDP_XDP_D2H_RSVD_12 0x0C0C
+#define mmHDP_XDP_D2H_RSVD_13 0x0C0D
+#define mmHDP_XDP_D2H_RSVD_14 0x0C0E
+#define mmHDP_XDP_D2H_RSVD_15 0x0C0F
+#define mmHDP_XDP_D2H_RSVD_16 0x0C10
+#define mmHDP_XDP_D2H_RSVD_17 0x0C11
+#define mmHDP_XDP_D2H_RSVD_18 0x0C12
+#define mmHDP_XDP_D2H_RSVD_19 0x0C13
+#define mmHDP_XDP_D2H_RSVD_20 0x0C14
+#define mmHDP_XDP_D2H_RSVD_21 0x0C15
+#define mmHDP_XDP_D2H_RSVD_22 0x0C16
+#define mmHDP_XDP_D2H_RSVD_23 0x0C17
+#define mmHDP_XDP_D2H_RSVD_24 0x0C18
+#define mmHDP_XDP_D2H_RSVD_25 0x0C19
+#define mmHDP_XDP_D2H_RSVD_26 0x0C1A
+#define mmHDP_XDP_D2H_RSVD_27 0x0C1B
+#define mmHDP_XDP_D2H_RSVD_28 0x0C1C
+#define mmHDP_XDP_D2H_RSVD_29 0x0C1D
+#define mmHDP_XDP_D2H_RSVD_30 0x0C1E
+#define mmHDP_XDP_D2H_RSVD_3 0x0C03
+#define mmHDP_XDP_D2H_RSVD_31 0x0C1F
+#define mmHDP_XDP_D2H_RSVD_32 0x0C20
+#define mmHDP_XDP_D2H_RSVD_33 0x0C21
+#define mmHDP_XDP_D2H_RSVD_34 0x0C22
+#define mmHDP_XDP_D2H_RSVD_4 0x0C04
+#define mmHDP_XDP_D2H_RSVD_5 0x0C05
+#define mmHDP_XDP_D2H_RSVD_6 0x0C06
+#define mmHDP_XDP_D2H_RSVD_7 0x0C07
+#define mmHDP_XDP_D2H_RSVD_8 0x0C08
+#define mmHDP_XDP_D2H_RSVD_9 0x0C09
+#define mmHDP_XDP_DBG_ADDR 0x0C41
+#define mmHDP_XDP_DBG_DATA 0x0C42
+#define mmHDP_XDP_DBG_MASK 0x0C43
+#define mmHDP_XDP_DIRECT2HDP_FIRST 0x0C00
+#define mmHDP_XDP_DIRECT2HDP_LAST 0x0C23
+#define mmHDP_XDP_FLUSH_ARMED_STS 0x0C3C
+#define mmHDP_XDP_FLUSH_CNTR0_STS 0x0C3D
+#define mmHDP_XDP_HDP_IPH_CFG 0x0C31
+#define mmHDP_XDP_HDP_MBX_MC_CFG 0x0C2D
+#define mmHDP_XDP_HDP_MC_CFG 0x0C2E
+#define mmHDP_XDP_HST_CFG 0x0C2F
+#define mmHDP_XDP_P2P_BAR0 0x0C34
+#define mmHDP_XDP_P2P_BAR1 0x0C35
+#define mmHDP_XDP_P2P_BAR2 0x0C36
+#define mmHDP_XDP_P2P_BAR3 0x0C37
+#define mmHDP_XDP_P2P_BAR4 0x0C38
+#define mmHDP_XDP_P2P_BAR5 0x0C39
+#define mmHDP_XDP_P2P_BAR6 0x0C3A
+#define mmHDP_XDP_P2P_BAR7 0x0C3B
+#define mmHDP_XDP_P2P_BAR_CFG 0x0C24
+#define mmHDP_XDP_P2P_MBX_ADDR0 0x0C26
+#define mmHDP_XDP_P2P_MBX_ADDR1 0x0C27
+#define mmHDP_XDP_P2P_MBX_ADDR2 0x0C28
+#define mmHDP_XDP_P2P_MBX_ADDR3 0x0C29
+#define mmHDP_XDP_P2P_MBX_ADDR4 0x0C2A
+#define mmHDP_XDP_P2P_MBX_ADDR5 0x0C2B
+#define mmHDP_XDP_P2P_MBX_ADDR6 0x0C2C
+#define mmHDP_XDP_P2P_MBX_OFFSET 0x0C25
+#define mmHDP_XDP_SID_CFG 0x0C30
+#define mmHDP_XDP_SRBM_CFG 0x0C32
+#define mmHDP_XDP_STICKY 0x0C3F
+#define mmIH_ADVFAULT_CNTL 0x0F8C
+#define mmIH_CNTL 0x0F86
+#define mmIH_LEVEL_STATUS 0x0F87
+#define mmIH_PERFCOUNTER0_RESULT 0x0F8A
+#define mmIH_PERFCOUNTER1_RESULT 0x0F8B
+#define mmIH_PERFMON_CNTL 0x0F89
+#define mmIH_RB_BASE 0x0F81
+#define mmIH_RB_CNTL 0x0F80
+#define mmIH_RB_RPTR 0x0F82
+#define mmIH_RB_WPTR 0x0F83
+#define mmIH_RB_WPTR_ADDR_HI 0x0F84
+#define mmIH_RB_WPTR_ADDR_LO 0x0F85
+#define mmIH_STATUS 0x0F88
+#define mmSEM_MAILBOX 0x0F9B
+#define mmSEM_MAILBOX_CLIENTCONFIG 0x0F9A
+#define mmSEM_MAILBOX_CONTROL 0x0F9C
+#define mmSEM_MCIF_CONFIG 0x0F90
+#define mmSRBM_CAM_DATA 0x0397
+#define mmSRBM_CAM_INDEX 0x0396
+#define mmSRBM_CHIP_REVISION 0x039B
+#define mmSRBM_CNTL 0x0390
+#define mmSRBM_DEBUG 0x03A4
+#define mmSRBM_DEBUG_CNTL 0x0399
+#define mmSRBM_DEBUG_DATA 0x039A
+#define mmSRBM_DEBUG_SNAPSHOT 0x03A5
+#define mmSRBM_GFX_CNTL 0x0391
+#define mmSRBM_INT_ACK 0x03AA
+#define mmSRBM_INT_CNTL 0x03A8
+#define mmSRBM_INT_STATUS 0x03A9
+#define mmSRBM_MC_CLKEN_CNTL 0x03B3
+#define mmSRBM_PERFCOUNTER0_HI 0x0704
+#define mmSRBM_PERFCOUNTER0_LO 0x0703
+#define mmSRBM_PERFCOUNTER0_SELECT 0x0701
+#define mmSRBM_PERFCOUNTER1_HI 0x0706
+#define mmSRBM_PERFCOUNTER1_LO 0x0705
+#define mmSRBM_PERFCOUNTER1_SELECT 0x0702
+#define mmSRBM_PERFMON_CNTL 0x0700
+#define mmSRBM_READ_ERROR 0x03A6
+#define mmSRBM_SOFT_RESET 0x0398
+#define mmSRBM_STATUS 0x0394
+#define mmSRBM_STATUS2 0x0393
+#define mmSRBM_SYS_CLKEN_CNTL 0x03B4
+#define mmSRBM_UVD_CLKEN_CNTL 0x03B6
+#define mmSRBM_VCE_CLKEN_CNTL 0x03B5
+#define mmUVD_CONFIG 0x0F98
+#define mmVCE_CONFIG 0x0F94
+#define mmXDMA_MSTR_MEM_OVERFLOW_CNTL 0x03F8
+
+/* from the old sid.h */
+#define mmDMA_TILING_CONFIG 0x342E
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h
new file mode 100644
index 000000000000..1c540fe136cb
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h
@@ -0,0 +1,1079 @@
+/*
+ *
+ * Copyright (C) 2016 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 OSS_1_0_SH_MASK_H
+#define OSS_1_0_SH_MASK_H
+
+#define CC_DRM_ID_STRAPS__ATI_REV_ID_MASK 0xf0000000L
+#define CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT 0x0000001c
+#define CC_DRM_ID_STRAPS__DEVICE_ID_MASK 0x000ffff0L
+#define CC_DRM_ID_STRAPS__DEVICE_ID__SHIFT 0x00000004
+#define CC_DRM_ID_STRAPS__MAJOR_REV_ID_MASK 0x00f00000L
+#define CC_DRM_ID_STRAPS__MAJOR_REV_ID__SHIFT 0x00000014
+#define CC_DRM_ID_STRAPS__MINOR_REV_ID_MASK 0x0f000000L
+#define CC_DRM_ID_STRAPS__MINOR_REV_ID__SHIFT 0x00000018
+#define CC_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define CC_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define CLIENT0_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT0_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT0_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT0_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT0_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT0_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT0_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT1_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT1_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT1_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT1_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT1_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT1_PORT_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT1_PORT_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT2_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT2_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT2_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT2_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT2_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT2_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT2_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT3_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT3_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT3_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT3_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT3_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT3_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT3_STATUS__RESERVED__SHIFT 0x00000000
+#define CP_CONFIG__CP_RDREQ_URG_MASK 0x00000f00L
+#define CP_CONFIG__CP_RDREQ_URG__SHIFT 0x00000008
+#define CP_CONFIG__CP_REQ_TRAN_MASK 0x00010000L
+#define CP_CONFIG__CP_REQ_TRAN__SHIFT 0x00000010
+#define DC_TEST_DEBUG_DATA__DC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DC_TEST_DEBUG_DATA__DC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DH_TEST__DH_TEST_MASK 0x00000001L
+#define DH_TEST__DH_TEST__SHIFT 0x00000000
+#define EXP0__RESERVED_MASK 0xffffffffL
+#define EXP0__RESERVED__SHIFT 0x00000000
+#define EXP1__RESERVED_MASK 0xffffffffL
+#define EXP1__RESERVED__SHIFT 0x00000000
+#define EXP2__RESERVED_MASK 0xffffffffL
+#define EXP2__RESERVED__SHIFT 0x00000000
+#define EXP3__RESERVED_MASK 0xffffffffL
+#define EXP3__RESERVED__SHIFT 0x00000000
+#define EXP4__RESERVED_MASK 0xffffffffL
+#define EXP4__RESERVED__SHIFT 0x00000000
+#define EXP5__RESERVED_MASK 0xffffffffL
+#define EXP5__RESERVED__SHIFT 0x00000000
+#define EXP6__RESERVED_MASK 0xffffffffL
+#define EXP6__RESERVED__SHIFT 0x00000000
+#define EXP7__RESERVED_MASK 0xffffffffL
+#define EXP7__RESERVED__SHIFT 0x00000000
+#define GC_USER_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define GC_USER_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define HDP_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define HDP_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define HDP_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define HDP_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define HDP_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define HDP_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define HDP_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define HDP_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define HDP_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define HDP_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define HDP_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define HDP_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define HDP_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define HDP_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define HDP_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define HDP_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define HDP_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define HDP_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define HDP_DEBUG0__HDP_DEBUG__SHIFT 0x00000000
+#define HDP_DEBUG1__HDP_DEBUG__SHIFT 0x00000000
+#define HDP_HOST_PATH_CNTL__ALL_SURFACES_DIS_MASK 0x20000000L
+#define HDP_HOST_PATH_CNTL__ALL_SURFACES_DIS__SHIFT 0x0000001d
+#define HDP_HOST_PATH_CNTL__BIF_RDRET_CREDIT_MASK 0x00000007L
+#define HDP_HOST_PATH_CNTL__BIF_RDRET_CREDIT__SHIFT 0x00000000
+#define HDP_HOST_PATH_CNTL__CACHE_INVALIDATE_MASK 0x00400000L
+#define HDP_HOST_PATH_CNTL__CACHE_INVALIDATE__SHIFT 0x00000016
+#define HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK 0x00800000L
+#define HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS__SHIFT 0x00000017
+#define HDP_HOST_PATH_CNTL__LIN_RD_CACHE_DIS_MASK 0x80000000L
+#define HDP_HOST_PATH_CNTL__LIN_RD_CACHE_DIS__SHIFT 0x0000001f
+#define HDP_HOST_PATH_CNTL__MC_WRREQ_CREDIT_MASK 0x000001f8L
+#define HDP_HOST_PATH_CNTL__MC_WRREQ_CREDIT__SHIFT 0x00000003
+#define HDP_HOST_PATH_CNTL__RD_STALL_TIMER_MASK 0x00001800L
+#define HDP_HOST_PATH_CNTL__RD_STALL_TIMER__SHIFT 0x0000000b
+#define HDP_HOST_PATH_CNTL__REG_CLK_ENABLE_COUNT_MASK 0x0f000000L
+#define HDP_HOST_PATH_CNTL__REG_CLK_ENABLE_COUNT__SHIFT 0x00000018
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_EN_MASK 0x00200000L
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_EN__SHIFT 0x00000015
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_TIMER_MASK 0x00180000L
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_TIMER__SHIFT 0x00000013
+#define HDP_HOST_PATH_CNTL__WRITE_THROUGH_CACHE_DIS_MASK 0x40000000L
+#define HDP_HOST_PATH_CNTL__WRITE_THROUGH_CACHE_DIS__SHIFT 0x0000001e
+#define HDP_HOST_PATH_CNTL__WR_STALL_TIMER_MASK 0x00000600L
+#define HDP_HOST_PATH_CNTL__WR_STALL_TIMER__SHIFT 0x00000009
+#define HDP_LAST_SURFACE_HIT__LAST_SURFACE_HIT_MASK 0x0000003fL
+#define HDP_LAST_SURFACE_HIT__LAST_SURFACE_HIT__SHIFT 0x00000000
+#define HDP_MEMIO_ADDR__MEMIO_ADDR_LOWER_MASK 0xffffffffL
+#define HDP_MEMIO_ADDR__MEMIO_ADDR_LOWER__SHIFT 0x00000000
+#define HDP_MEMIO_CNTL__MEMIO_ADDR_UPPER_MASK 0x00003f00L
+#define HDP_MEMIO_CNTL__MEMIO_ADDR_UPPER__SHIFT 0x00000008
+#define HDP_MEMIO_CNTL__MEMIO_BE_MASK 0x0000003cL
+#define HDP_MEMIO_CNTL__MEMIO_BE__SHIFT 0x00000002
+#define HDP_MEMIO_CNTL__MEMIO_CLR_RD_ERROR_MASK 0x00008000L
+#define HDP_MEMIO_CNTL__MEMIO_CLR_RD_ERROR__SHIFT 0x0000000f
+#define HDP_MEMIO_CNTL__MEMIO_CLR_WR_ERROR_MASK 0x00004000L
+#define HDP_MEMIO_CNTL__MEMIO_CLR_WR_ERROR__SHIFT 0x0000000e
+#define HDP_MEMIO_CNTL__MEMIO_OP_MASK 0x00000002L
+#define HDP_MEMIO_CNTL__MEMIO_OP__SHIFT 0x00000001
+#define HDP_MEMIO_CNTL__MEMIO_RD_STROBE_MASK 0x00000080L
+#define HDP_MEMIO_CNTL__MEMIO_RD_STROBE__SHIFT 0x00000007
+#define HDP_MEMIO_CNTL__MEMIO_SEND_MASK 0x00000001L
+#define HDP_MEMIO_CNTL__MEMIO_SEND__SHIFT 0x00000000
+#define HDP_MEMIO_CNTL__MEMIO_WR_STROBE_MASK 0x00000040L
+#define HDP_MEMIO_CNTL__MEMIO_WR_STROBE__SHIFT 0x00000006
+#define HDP_MEMIO_RD_DATA__MEMIO_RD_DATA_MASK 0xffffffffL
+#define HDP_MEMIO_RD_DATA__MEMIO_RD_DATA__SHIFT 0x00000000
+#define HDP_MEMIO_STATUS__MEMIO_RD_ERROR_MASK 0x00000008L
+#define HDP_MEMIO_STATUS__MEMIO_RD_ERROR__SHIFT 0x00000003
+#define HDP_MEMIO_STATUS__MEMIO_RD_STATUS_MASK 0x00000002L
+#define HDP_MEMIO_STATUS__MEMIO_RD_STATUS__SHIFT 0x00000001
+#define HDP_MEMIO_STATUS__MEMIO_WR_ERROR_MASK 0x00000004L
+#define HDP_MEMIO_STATUS__MEMIO_WR_ERROR__SHIFT 0x00000002
+#define HDP_MEMIO_STATUS__MEMIO_WR_STATUS_MASK 0x00000001L
+#define HDP_MEMIO_STATUS__MEMIO_WR_STATUS__SHIFT 0x00000000
+#define HDP_MEMIO_WR_DATA__MEMIO_WR_DATA_MASK 0xffffffffL
+#define HDP_MEMIO_WR_DATA__MEMIO_WR_DATA__SHIFT 0x00000000
+#define HDP_MEM_POWER_LS__LS_ENABLE_MASK 0x00000001L
+#define HDP_MEM_POWER_LS__LS_ENABLE__SHIFT 0x00000000
+#define HDP_MEM_POWER_LS__LS_HOLD_MASK 0x00001f80L
+#define HDP_MEM_POWER_LS__LS_HOLD__SHIFT 0x00000007
+#define HDP_MEM_POWER_LS__LS_SETUP_MASK 0x0000007eL
+#define HDP_MEM_POWER_LS__LS_SETUP__SHIFT 0x00000001
+#define HDP_MISC_CNTL__ADDRLIB_LINEAR_BYPASS_MASK 0x00100000L
+#define HDP_MISC_CNTL__ADDRLIB_LINEAR_BYPASS__SHIFT 0x00000014
+#define HDP_MISC_CNTL__FED_ENABLE_MASK 0x00200000L
+#define HDP_MISC_CNTL__FED_ENABLE__SHIFT 0x00000015
+#define HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE_MASK 0x00000001L
+#define HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE__SHIFT 0x00000000
+#define HDP_MISC_CNTL__HDP_BIF_RDRET_CREDIT_MASK 0x00000780L
+#define HDP_MISC_CNTL__HDP_BIF_RDRET_CREDIT__SHIFT 0x00000007
+#define HDP_MISC_CNTL__MC_RDREQ_CREDIT_MASK 0x0007e000L
+#define HDP_MISC_CNTL__MC_RDREQ_CREDIT__SHIFT 0x0000000d
+#define HDP_MISC_CNTL__MULTIPLE_READS_MASK 0x00000040L
+#define HDP_MISC_CNTL__MULTIPLE_READS__SHIFT 0x00000006
+#define HDP_MISC_CNTL__NO_SPLIT_ARRAY_LINEAR_MASK 0x00001000L
+#define HDP_MISC_CNTL__NO_SPLIT_ARRAY_LINEAR__SHIFT 0x0000000c
+#define HDP_MISC_CNTL__OUTSTANDING_WRITE_COUNT_1024_MASK 0x00000020L
+#define HDP_MISC_CNTL__OUTSTANDING_WRITE_COUNT_1024__SHIFT 0x00000005
+#define HDP_MISC_CNTL__READ_CACHE_INVALIDATE_MASK 0x00080000L
+#define HDP_MISC_CNTL__READ_CACHE_INVALIDATE__SHIFT 0x00000013
+#define HDP_MISC_CNTL__SIMULTANEOUS_READS_WRITES_MASK 0x00000800L
+#define HDP_MISC_CNTL__SIMULTANEOUS_READS_WRITES__SHIFT 0x0000000b
+#define HDP_MISC_CNTL__VM_ID_MASK 0x0000001eL
+#define HDP_MISC_CNTL__VM_ID__SHIFT 0x00000001
+#define HDP_NONSURFACE_BASE__NONSURF_BASE_MASK 0xffffffffL
+#define HDP_NONSURFACE_BASE__NONSURF_BASE__SHIFT 0x00000000
+#define HDP_NONSURFACE_INFO__NONSURF_ADDR_TYPE_MASK 0x00000001L
+#define HDP_NONSURFACE_INFO__NONSURF_ADDR_TYPE__SHIFT 0x00000000
+#define HDP_NONSURFACE_INFO__NONSURF_ARRAY_MODE_MASK 0x0000001eL
+#define HDP_NONSURFACE_INFO__NONSURF_ARRAY_MODE__SHIFT 0x00000001
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_HEIGHT_MASK 0x03000000L
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_HEIGHT__SHIFT 0x00000018
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_WIDTH_MASK 0x00c00000L
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_WIDTH__SHIFT 0x00000016
+#define HDP_NONSURFACE_INFO__NONSURF_ENDIAN_MASK 0x00000060L
+#define HDP_NONSURFACE_INFO__NONSURF_ENDIAN__SHIFT 0x00000005
+#define HDP_NONSURFACE_INFO__NONSURF_MACRO_TILE_ASPECT_MASK 0x0c000000L
+#define HDP_NONSURFACE_INFO__NONSURF_MACRO_TILE_ASPECT__SHIFT 0x0000001a
+#define HDP_NONSURFACE_INFO__NONSURF_MICRO_TILE_MODE_MASK 0x30000000L
+#define HDP_NONSURFACE_INFO__NONSURF_MICRO_TILE_MODE__SHIFT 0x0000001c
+#define HDP_NONSURFACE_INFO__NONSURF_NUM_BANKS_MASK 0x00300000L
+#define HDP_NONSURFACE_INFO__NONSURF_NUM_BANKS__SHIFT 0x00000014
+#define HDP_NONSURFACE_INFO__NONSURF_PIXEL_SIZE_MASK 0x00000380L
+#define HDP_NONSURFACE_INFO__NONSURF_PIXEL_SIZE__SHIFT 0x00000007
+#define HDP_NONSURFACE_INFO__NONSURF_PRIV_MASK 0x00008000L
+#define HDP_NONSURFACE_INFO__NONSURF_PRIV__SHIFT 0x0000000f
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_NUM_MASK 0x00001c00L
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_NUM__SHIFT 0x0000000a
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_SIZE_MASK 0x00006000L
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_SIZE__SHIFT 0x0000000d
+#define HDP_NONSURFACE_INFO__NONSURF_SLICE_TILE_MAX_MSB_MASK 0x40000000L
+#define HDP_NONSURFACE_INFO__NONSURF_SLICE_TILE_MAX_MSB__SHIFT 0x0000001e
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_COMPACT_MASK 0x00010000L
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_COMPACT__SHIFT 0x00000010
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_SPLIT_MASK 0x000e0000L
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_SPLIT__SHIFT 0x00000011
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PIPE_CONFIG_MASK 0xf8000000L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PIPE_CONFIG__SHIFT 0x0000001b
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_DIR_MASK 0x00000038L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_DIR__SHIFT 0x00000003
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_MAX_Z_MASK 0x000ffe00L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_MAX_Z__SHIFT 0x00000009
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_NUM_MASK 0x000001c0L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_NUM__SHIFT 0x00000006
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_PRI_MASK 0x00000007L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_PRI__SHIFT 0x00000000
+#define HDP_NONSURFACE_SIZE__NONSURF_PITCH_TILE_MAX_MASK 0x000007ffL
+#define HDP_NONSURFACE_SIZE__NONSURF_PITCH_TILE_MAX__SHIFT 0x00000000
+#define HDP_NONSURFACE_SIZE__NONSURF_SLICE_TILE_MAX_MASK 0xfffff800L
+#define HDP_NONSURFACE_SIZE__NONSURF_SLICE_TILE_MAX__SHIFT 0x0000000b
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_READ_FLAG_CLR_MASK 0x00000002L
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_READ_FLAG_CLR__SHIFT 0x00000001
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_WRITE_FLAG_CLR_MASK 0x00000001L
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_WRITE_FLAG_CLR__SHIFT 0x00000000
+#define HDP_NONSURF_FLAGS__NONSURF_READ_FLAG_MASK 0x00000002L
+#define HDP_NONSURF_FLAGS__NONSURF_READ_FLAG__SHIFT 0x00000001
+#define HDP_NONSURF_FLAGS__NONSURF_WRITE_FLAG_MASK 0x00000001L
+#define HDP_NONSURF_FLAGS__NONSURF_WRITE_FLAG__SHIFT 0x00000000
+#define HDP_OUTSTANDING_REQ__READ_REQ_MASK 0x0000ff00L
+#define HDP_OUTSTANDING_REQ__READ_REQ__SHIFT 0x00000008
+#define HDP_OUTSTANDING_REQ__WRITE_REQ_MASK 0x000000ffL
+#define HDP_OUTSTANDING_REQ__WRITE_REQ__SHIFT 0x00000000
+#define HDP_SC_MULTI_CHIP_CNTL__LOG2_NUM_CHIPS_MASK 0x00000007L
+#define HDP_SC_MULTI_CHIP_CNTL__LOG2_NUM_CHIPS__SHIFT 0x00000000
+#define HDP_SC_MULTI_CHIP_CNTL__MULTI_CHIP_TILE_SIZE_MASK 0x00000018L
+#define HDP_SC_MULTI_CHIP_CNTL__MULTI_CHIP_TILE_SIZE__SHIFT 0x00000003
+#define HDP_SW_SEMAPHORE__SW_SEMAPHORE_MASK 0xffffffffL
+#define HDP_SW_SEMAPHORE__SW_SEMAPHORE__SHIFT 0x00000000
+#define HDP_TILING_CONFIG__BANK_SWAPS_MASK 0x00003800L
+#define HDP_TILING_CONFIG__BANK_SWAPS__SHIFT 0x0000000b
+#define HDP_TILING_CONFIG__BANK_TILING_MASK 0x00000030L
+#define HDP_TILING_CONFIG__BANK_TILING__SHIFT 0x00000004
+#define HDP_TILING_CONFIG__GROUP_SIZE_MASK 0x000000c0L
+#define HDP_TILING_CONFIG__GROUP_SIZE__SHIFT 0x00000006
+#define HDP_TILING_CONFIG__PIPE_TILING_MASK 0x0000000eL
+#define HDP_TILING_CONFIG__PIPE_TILING__SHIFT 0x00000001
+#define HDP_TILING_CONFIG__ROW_TILING_MASK 0x00000700L
+#define HDP_TILING_CONFIG__ROW_TILING__SHIFT 0x00000008
+#define HDP_TILING_CONFIG__SAMPLE_SPLIT_MASK 0x0000c000L
+#define HDP_TILING_CONFIG__SAMPLE_SPLIT__SHIFT 0x0000000e
+#define HDP_XDP_BARS_ADDR_39_36__BAR0_ADDR_39_36_MASK 0x0000000fL
+#define HDP_XDP_BARS_ADDR_39_36__BAR0_ADDR_39_36__SHIFT 0x00000000
+#define HDP_XDP_BARS_ADDR_39_36__BAR1_ADDR_39_36_MASK 0x000000f0L
+#define HDP_XDP_BARS_ADDR_39_36__BAR1_ADDR_39_36__SHIFT 0x00000004
+#define HDP_XDP_BARS_ADDR_39_36__BAR2_ADDR_39_36_MASK 0x00000f00L
+#define HDP_XDP_BARS_ADDR_39_36__BAR2_ADDR_39_36__SHIFT 0x00000008
+#define HDP_XDP_BARS_ADDR_39_36__BAR3_ADDR_39_36_MASK 0x0000f000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR3_ADDR_39_36__SHIFT 0x0000000c
+#define HDP_XDP_BARS_ADDR_39_36__BAR4_ADDR_39_36_MASK 0x000f0000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR4_ADDR_39_36__SHIFT 0x00000010
+#define HDP_XDP_BARS_ADDR_39_36__BAR5_ADDR_39_36_MASK 0x00f00000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR5_ADDR_39_36__SHIFT 0x00000014
+#define HDP_XDP_BARS_ADDR_39_36__BAR6_ADDR_39_36_MASK 0x0f000000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR6_ADDR_39_36__SHIFT 0x00000018
+#define HDP_XDP_BARS_ADDR_39_36__BAR7_ADDR_39_36_MASK 0xf0000000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR7_ADDR_39_36__SHIFT 0x0000001c
+#define HDP_XDP_BUSY_STS__BUSY_BITS_MASK 0x0003ffffL
+#define HDP_XDP_BUSY_STS__BUSY_BITS__SHIFT 0x00000000
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_0_ON_DELAY_MASK 0x0000000fL
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_0_ON_DELAY__SHIFT 0x00000000
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_1_OFF_DELAY_MASK 0x00000ff0L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_1_OFF_DELAY__SHIFT 0x00000004
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_2_RSVD_MASK 0x3ffff000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_2_RSVD__SHIFT 0x0000000c
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_3_SOFT_CORE_OVERRIDE_MASK 0x40000000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_3_SOFT_CORE_OVERRIDE__SHIFT 0x0000001e
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_4_SOFT_REG_OVERRIDE_MASK 0x80000000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_4_SOFT_REG_OVERRIDE__SHIFT 0x0000001f
+#define HDP_XDP_CHKN__CHKN_0_RSVD_MASK 0x000000ffL
+#define HDP_XDP_CHKN__CHKN_0_RSVD__SHIFT 0x00000000
+#define HDP_XDP_CHKN__CHKN_1_RSVD_MASK 0x0000ff00L
+#define HDP_XDP_CHKN__CHKN_1_RSVD__SHIFT 0x00000008
+#define HDP_XDP_CHKN__CHKN_2_RSVD_MASK 0x00ff0000L
+#define HDP_XDP_CHKN__CHKN_2_RSVD__SHIFT 0x00000010
+#define HDP_XDP_CHKN__CHKN_3_RSVD_MASK 0xff000000L
+#define HDP_XDP_CHKN__CHKN_3_RSVD__SHIFT 0x00000018
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_ADDR_MASK 0x0000ffffL
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_ADDR__SHIFT 0x00000000
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_BAR_NUM_MASK 0x00700000L
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_BAR_NUM__SHIFT 0x00000014
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_FLUSH_NUM_MASK 0x000f0000L
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_FLUSH_NUM__SHIFT 0x00000010
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_ALTER_FLUSH_NUM_MASK 0x00040000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_ALTER_FLUSH_NUM__SHIFT 0x00000012
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_FLUSH_NUM_MASK 0x0000000fL
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_FLUSH_NUM__SHIFT 0x00000000
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ADDR_SEL_MASK 0x00000700L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ADDR_SEL__SHIFT 0x00000008
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ENC_DATA_MASK 0x000000f0L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ENC_DATA__SHIFT 0x00000004
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_0_MASK 0x00080000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_0__SHIFT 0x00000013
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_1_MASK 0x00100000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_1__SHIFT 0x00000014
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_HOST_MASK 0x00010000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_HOST__SHIFT 0x00000010
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_SIDE_MASK 0x00020000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_SIDE__SHIFT 0x00000011
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_XPB_CLG_MASK 0x0000f800L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_XPB_CLG__SHIFT 0x0000000b
+#define HDP_XDP_D2H_RSVD_10__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_10__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_11__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_11__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_12__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_12__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_13__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_13__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_14__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_14__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_15__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_15__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_16__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_16__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_17__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_17__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_18__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_18__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_19__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_19__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_20__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_20__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_21__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_21__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_22__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_22__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_23__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_23__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_24__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_24__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_25__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_25__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_26__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_26__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_27__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_27__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_28__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_28__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_29__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_29__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_30__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_30__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_31__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_31__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_32__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_32__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_33__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_33__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_34__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_34__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_3__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_3__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_4__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_4__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_5__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_5__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_6__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_6__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_7__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_7__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_8__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_8__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_9__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_9__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_DBG_ADDR__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_ADDR__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_ADDR__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_ADDR__STS__SHIFT 0x00000000
+#define HDP_XDP_DBG_DATA__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_DATA__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_DATA__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_DATA__STS__SHIFT 0x00000000
+#define HDP_XDP_DBG_MASK__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_MASK__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_MASK__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_MASK__STS__SHIFT 0x00000000
+#define HDP_XDP_DIRECT2HDP_FIRST__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_DIRECT2HDP_FIRST__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_DIRECT2HDP_LAST__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_DIRECT2HDP_LAST__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_FLUSH_ARMED_STS__FLUSH_ARMED_STS_MASK 0xffffffffL
+#define HDP_XDP_FLUSH_ARMED_STS__FLUSH_ARMED_STS__SHIFT 0x00000000
+#define HDP_XDP_FLUSH_CNTR0_STS__FLUSH_CNTR0_STS_MASK 0x03ffffffL
+#define HDP_XDP_FLUSH_CNTR0_STS__FLUSH_CNTR0_STS__SHIFT 0x00000000
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_INVERSE_PEER_TAG_MATCHING_MASK 0x00001000L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_INVERSE_PEER_TAG_MATCHING__SHIFT 0x0000000c
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_P2P_RD_EN_MASK 0x00002000L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_P2P_RD_EN__SHIFT 0x0000000d
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_SYS_FIFO_DEPTH_OVERRIDE_MASK 0x0000003fL
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_SYS_FIFO_DEPTH_OVERRIDE__SHIFT 0x00000000
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_XDP_FIFO_DEPTH_OVERRIDE_MASK 0x00000fc0L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_XDP_FIFO_DEPTH_OVERRIDE__SHIFT 0x00000006
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_PRIV_MASK 0x00000001L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_PRIV__SHIFT 0x00000000
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_SWAP_MASK 0x00000006L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_SWAP__SHIFT 0x00000001
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_TRAN_MASK 0x00000008L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_TRAN__SHIFT 0x00000003
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_VMID_MASK 0x000000f0L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_VMID__SHIFT 0x00000004
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_PRIV_MASK 0x00000001L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_PRIV__SHIFT 0x00000000
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_SWAP_MASK 0x00000006L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_SWAP__SHIFT 0x00000001
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_TRAN_MASK 0x00000008L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_TRAN__SHIFT 0x00000003
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_VMID_MASK 0x07800000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_VMID__SHIFT 0x00000017
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_MC_STALL_ON_BUF_FULL_MASK_MASK 0x00700000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_MC_STALL_ON_BUF_FULL_MASK__SHIFT 0x00000014
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_PRIV_MASK 0x00000010L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_PRIV__SHIFT 0x00000004
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_SWAP_MASK 0x00000060L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_SWAP__SHIFT 0x00000005
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_TRAN_MASK 0x00000080L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_TRAN__SHIFT 0x00000007
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_VMID_MASK 0x78000000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_VMID__SHIFT 0x0000001b
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XDP_HIGHER_PRI_THRESH_MASK 0x000fc000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XDP_HIGHER_PRI_THRESH__SHIFT 0x0000000e
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XL8R_WRREQ_CRD_OVERRIDE_MASK 0x00003f00L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XL8R_WRREQ_CRD_OVERRIDE__SHIFT 0x00000008
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_EN_MASK 0x00000001L
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_EN__SHIFT 0x00000000
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_TIMER_MASK 0x00000006L
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_TIMER__SHIFT 0x00000001
+#define HDP_XDP_P2P_BAR0__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR0__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR0__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR0__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR0__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR0__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR1__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR1__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR1__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR1__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR1__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR1__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR2__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR2__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR2__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR2__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR2__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR2__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR3__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR3__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR3__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR3__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR3__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR3__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR4__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR4__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR4__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR4__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR4__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR4__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR5__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR5__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR5__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR5__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR5__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR5__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR6__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR6__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR6__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR6__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR6__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR6__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR7__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR7__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR7__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR7__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR7__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR7__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_ADDR_SIZE_MASK 0x0000000fL
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_ADDR_SIZE__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_BAR_FROM_MASK 0x00000030L
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_BAR_FROM__SHIFT 0x00000004
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR0__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR0__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR1__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR1__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR2__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR2__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR3__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR3__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR4__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR4__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR5__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR5__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR6__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR6__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_OFFSET__P2P_MBX_OFFSET_MASK 0x00003fffL
+#define HDP_XDP_P2P_MBX_OFFSET__P2P_MBX_OFFSET__SHIFT 0x00000000
+#define HDP_XDP_SID_CFG__SID_CFG_FLNUM_MSB_SEL_MASK 0x00000018L
+#define HDP_XDP_SID_CFG__SID_CFG_FLNUM_MSB_SEL__SHIFT 0x00000003
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_EN_MASK 0x00000001L
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_EN__SHIFT 0x00000000
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_TIMER_MASK 0x00000006L
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_TIMER__SHIFT 0x00000001
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_ENABLE_COUNT_MASK 0x0000003fL
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_ENABLE_COUNT__SHIFT 0x00000000
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_GATING_DIS_MASK 0x00000040L
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_GATING_DIS__SHIFT 0x00000006
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_WAKE_DYN_CLK_MASK 0x00000080L
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_WAKE_DYN_CLK__SHIFT 0x00000007
+#define HDP_XDP_STICKY__STICKY_STS_MASK 0x0000ffffL
+#define HDP_XDP_STICKY__STICKY_STS__SHIFT 0x00000000
+#define HDP_XDP_STICKY__STICKY_W1C_MASK 0xffff0000L
+#define HDP_XDP_STICKY__STICKY_W1C__SHIFT 0x00000010
+#define HFS_SEED0__RESERVED_MASK 0xffffffffL
+#define HFS_SEED0__RESERVED__SHIFT 0x00000000
+#define HFS_SEED1__RESERVED_MASK 0xffffffffL
+#define HFS_SEED1__RESERVED__SHIFT 0x00000000
+#define HFS_SEED2__RESERVED_MASK 0xffffffffL
+#define HFS_SEED2__RESERVED__SHIFT 0x00000000
+#define HFS_SEED3__RESERVED_MASK 0xffffffffL
+#define HFS_SEED3__RESERVED__SHIFT 0x00000000
+#define IH_ADVFAULT_CNTL__NUM_FAULTS_DROPPED_MASK 0x0000ff00L
+#define IH_ADVFAULT_CNTL__NUM_FAULTS_DROPPED__SHIFT 0x00000008
+#define IH_ADVFAULT_CNTL__WAIT_TIMER_MASK 0x3fff0000L
+#define IH_ADVFAULT_CNTL__WAIT_TIMER__SHIFT 0x00000010
+#define IH_ADVFAULT_CNTL__WATERMARK_ENABLE_MASK 0x00000008L
+#define IH_ADVFAULT_CNTL__WATERMARK_ENABLE__SHIFT 0x00000003
+#define IH_ADVFAULT_CNTL__WATERMARK_MASK 0x00000007L
+#define IH_ADVFAULT_CNTL__WATERMARK_REACHED_MASK 0x00000010L
+#define IH_ADVFAULT_CNTL__WATERMARK_REACHED__SHIFT 0x00000004
+#define IH_ADVFAULT_CNTL__WATERMARK__SHIFT 0x00000000
+#define IH_CNTL__CLIENT_FIFO_HIGHWATER_MASK 0x00000300L
+#define IH_CNTL__CLIENT_FIFO_HIGHWATER__SHIFT 0x00000008
+#define IH_CNTL__ENABLE_INTR_MASK 0x00000001L
+#define IH_CNTL__ENABLE_INTR__SHIFT 0x00000000
+#define IH_CNTL__MC_FIFO_HIGHWATER_MASK 0x00007c00L
+#define IH_CNTL__MC_FIFO_HIGHWATER__SHIFT 0x0000000a
+#define IH_CNTL__MC_SWAP_MASK 0x00000006L
+#define IH_CNTL__MC_SWAP__SHIFT 0x00000001
+#define IH_CNTL__MC_TRAN_MASK 0x00000008L
+#define IH_CNTL__MC_TRAN__SHIFT 0x00000003
+#define IH_CNTL__MC_VMID_MASK 0x1e000000L
+#define IH_CNTL__MC_VMID__SHIFT 0x00000019
+#define IH_CNTL__MC_WR_CLEAN_CNT_MASK 0x01f00000L
+#define IH_CNTL__MC_WR_CLEAN_CNT__SHIFT 0x00000014
+#define IH_CNTL__MC_WRREQ_CREDIT_MASK 0x000f8000L
+#define IH_CNTL__MC_WRREQ_CREDIT__SHIFT 0x0000000f
+#define IH_CNTL__RPTR_REARM_MASK 0x00000010L
+#define IH_CNTL__RPTR_REARM__SHIFT 0x00000004
+#define IH_LEVEL_STATUS__BIF_STATUS_MASK 0x00000010L
+#define IH_LEVEL_STATUS__BIF_STATUS__SHIFT 0x00000004
+#define IH_LEVEL_STATUS__DC_STATUS_MASK 0x00000001L
+#define IH_LEVEL_STATUS__DC_STATUS__SHIFT 0x00000000
+#define IH_LEVEL_STATUS__ROM_STATUS_MASK 0x00000004L
+#define IH_LEVEL_STATUS__ROM_STATUS__SHIFT 0x00000002
+#define IH_LEVEL_STATUS__SRBM_STATUS_MASK 0x00000008L
+#define IH_LEVEL_STATUS__SRBM_STATUS__SHIFT 0x00000003
+#define IH_LEVEL_STATUS__XDMA_STATUS_MASK 0x00000020L
+#define IH_LEVEL_STATUS__XDMA_STATUS__SHIFT 0x00000005
+#define IH_PERFCOUNTER0_RESULT__PERF_COUNT_MASK 0xffffffffL
+#define IH_PERFCOUNTER0_RESULT__PERF_COUNT__SHIFT 0x00000000
+#define IH_PERFCOUNTER1_RESULT__PERF_COUNT_MASK 0xffffffffL
+#define IH_PERFCOUNTER1_RESULT__PERF_COUNT__SHIFT 0x00000000
+#define IH_PERFMON_CNTL__CLEAR0_MASK 0x00000002L
+#define IH_PERFMON_CNTL__CLEAR0__SHIFT 0x00000001
+#define IH_PERFMON_CNTL__CLEAR1_MASK 0x00000200L
+#define IH_PERFMON_CNTL__CLEAR1__SHIFT 0x00000009
+#define IH_PERFMON_CNTL__ENABLE0_MASK 0x00000001L
+#define IH_PERFMON_CNTL__ENABLE0__SHIFT 0x00000000
+#define IH_PERFMON_CNTL__ENABLE1_MASK 0x00000100L
+#define IH_PERFMON_CNTL__ENABLE1__SHIFT 0x00000008
+#define IH_PERFMON_CNTL__PERF_SEL0_MASK 0x000000fcL
+#define IH_PERFMON_CNTL__PERF_SEL0__SHIFT 0x00000002
+#define IH_PERFMON_CNTL__PERF_SEL1_MASK 0x0000fc00L
+#define IH_PERFMON_CNTL__PERF_SEL1__SHIFT 0x0000000a
+#define IH_RB_BASE__ADDR_MASK 0xffffffffL
+#define IH_RB_BASE__ADDR__SHIFT 0x00000000
+#define IH_RB_CNTL__RB_ENABLE_MASK 0x00000001L
+#define IH_RB_CNTL__RB_ENABLE__SHIFT 0x00000000
+#define IH_RB_CNTL__RB_FULL_DRAIN_ENABLE_MASK 0x00000040L
+#define IH_RB_CNTL__RB_FULL_DRAIN_ENABLE__SHIFT 0x00000006
+#define IH_RB_CNTL__RB_GPU_TS_ENABLE_MASK 0x00000080L
+#define IH_RB_CNTL__RB_GPU_TS_ENABLE__SHIFT 0x00000007
+#define IH_RB_CNTL__RB_SIZE_MASK 0x0000003eL
+#define IH_RB_CNTL__RB_SIZE__SHIFT 0x00000001
+#define IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK 0x80000000L
+#define IH_RB_CNTL__WPTR_OVERFLOW_CLEAR__SHIFT 0x0000001f
+#define IH_RB_CNTL__WPTR_OVERFLOW_ENABLE_MASK 0x00010000L
+#define IH_RB_CNTL__WPTR_OVERFLOW_ENABLE__SHIFT 0x00000010
+#define IH_RB_CNTL__WPTR_WRITEBACK_ENABLE_MASK 0x00000100L
+#define IH_RB_CNTL__WPTR_WRITEBACK_ENABLE__SHIFT 0x00000008
+#define IH_RB_CNTL__WPTR_WRITEBACK_TIMER_MASK 0x00003e00L
+#define IH_RB_CNTL__WPTR_WRITEBACK_TIMER__SHIFT 0x00000009
+#define IH_RB_RPTR__OFFSET_MASK 0x0003fffcL
+#define IH_RB_RPTR__OFFSET__SHIFT 0x00000002
+#define IH_RB_WPTR_ADDR_HI__ADDR_MASK 0x000000ffL
+#define IH_RB_WPTR_ADDR_HI__ADDR__SHIFT 0x00000000
+#define IH_RB_WPTR_ADDR_LO__ADDR_MASK 0xfffffffcL
+#define IH_RB_WPTR_ADDR_LO__ADDR__SHIFT 0x00000002
+#define IH_RB_WPTR__OFFSET_MASK 0x0003fffcL
+#define IH_RB_WPTR__OFFSET__SHIFT 0x00000002
+#define IH_RB_WPTR__RB_OVERFLOW_MASK 0x00000001L
+#define IH_RB_WPTR__RB_OVERFLOW__SHIFT 0x00000000
+#define IH_STATUS__BIF_INTERRUPT_LINE_MASK 0x00000400L
+#define IH_STATUS__BIF_INTERRUPT_LINE__SHIFT 0x0000000a
+#define IH_STATUS__IDLE_MASK 0x00000001L
+#define IH_STATUS__IDLE__SHIFT 0x00000000
+#define IH_STATUS__INPUT_IDLE_MASK 0x00000002L
+#define IH_STATUS__INPUT_IDLE__SHIFT 0x00000001
+#define IH_STATUS__MC_WR_CLEAN_PENDING_MASK 0x00000100L
+#define IH_STATUS__MC_WR_CLEAN_PENDING__SHIFT 0x00000008
+#define IH_STATUS__MC_WR_CLEAN_STALL_MASK 0x00000200L
+#define IH_STATUS__MC_WR_CLEAN_STALL__SHIFT 0x00000009
+#define IH_STATUS__MC_WR_IDLE_MASK 0x00000040L
+#define IH_STATUS__MC_WR_IDLE__SHIFT 0x00000006
+#define IH_STATUS__MC_WR_STALL_MASK 0x00000080L
+#define IH_STATUS__MC_WR_STALL__SHIFT 0x00000007
+#define IH_STATUS__RB_FULL_DRAIN_MASK 0x00000010L
+#define IH_STATUS__RB_FULL_DRAIN__SHIFT 0x00000004
+#define IH_STATUS__RB_FULL_MASK 0x00000008L
+#define IH_STATUS__RB_FULL__SHIFT 0x00000003
+#define IH_STATUS__RB_IDLE_MASK 0x00000004L
+#define IH_STATUS__RB_IDLE__SHIFT 0x00000002
+#define IH_STATUS__RB_OVERFLOW_MASK 0x00000020L
+#define IH_STATUS__RB_OVERFLOW__SHIFT 0x00000005
+#define KEFUSE0__RESERVED_MASK 0xffffffffL
+#define KEFUSE0__RESERVED__SHIFT 0x00000000
+#define KEFUSE1__RESERVED_MASK 0xffffffffL
+#define KEFUSE1__RESERVED__SHIFT 0x00000000
+#define KEFUSE2__RESERVED_MASK 0xffffffffL
+#define KEFUSE2__RESERVED__SHIFT 0x00000000
+#define KEFUSE3__RESERVED_MASK 0xffffffffL
+#define KEFUSE3__RESERVED__SHIFT 0x00000000
+#define KHFS0__RESERVED_MASK 0xffffffffL
+#define KHFS0__RESERVED__SHIFT 0x00000000
+#define KHFS1__RESERVED_MASK 0xffffffffL
+#define KHFS1__RESERVED__SHIFT 0x00000000
+#define KHFS2__RESERVED_MASK 0xffffffffL
+#define KHFS2__RESERVED__SHIFT 0x00000000
+#define KHFS3__RESERVED_MASK 0xffffffffL
+#define KHFS3__RESERVED__SHIFT 0x00000000
+#define KSESSION0__RESERVED_MASK 0xffffffffL
+#define KSESSION0__RESERVED__SHIFT 0x00000000
+#define KSESSION1__RESERVED_MASK 0xffffffffL
+#define KSESSION1__RESERVED__SHIFT 0x00000000
+#define KSESSION2__RESERVED_MASK 0xffffffffL
+#define KSESSION2__RESERVED__SHIFT 0x00000000
+#define KSESSION3__RESERVED_MASK 0xffffffffL
+#define KSESSION3__RESERVED__SHIFT 0x00000000
+#define KSIG0__RESERVED_MASK 0xffffffffL
+#define KSIG0__RESERVED__SHIFT 0x00000000
+#define KSIG1__RESERVED_MASK 0xffffffffL
+#define KSIG1__RESERVED__SHIFT 0x00000000
+#define KSIG2__RESERVED_MASK 0xffffffffL
+#define KSIG2__RESERVED__SHIFT 0x00000000
+#define KSIG3__RESERVED_MASK 0xffffffffL
+#define KSIG3__RESERVED__SHIFT 0x00000000
+#define LX0__RESERVED_MASK 0xffffffffL
+#define LX0__RESERVED__SHIFT 0x00000000
+#define LX1__RESERVED_MASK 0xffffffffL
+#define LX1__RESERVED__SHIFT 0x00000000
+#define LX2__RESERVED_MASK 0xffffffffL
+#define LX2__RESERVED__SHIFT 0x00000000
+#define LX3__RESERVED_MASK 0xffffffffL
+#define LX3__RESERVED__SHIFT 0x00000000
+#define RINGOSC_MASK__MASK_MASK 0x0000ffffL
+#define RINGOSC_MASK__MASK__SHIFT 0x00000000
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT0_MASK 0x00000007L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT0__SHIFT 0x00000000
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT1_MASK 0x00000038L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT1__SHIFT 0x00000003
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT2_MASK 0x000001c0L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT2__SHIFT 0x00000006
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT3_MASK 0x00000e00L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT3__SHIFT 0x00000009
+#define SEM_MAILBOX_CLIENTCONFIG__UVD_CLIENT0_MASK 0x00038000L
+#define SEM_MAILBOX_CLIENTCONFIG__UVD_CLIENT0__SHIFT 0x0000000f
+#define SEM_MAILBOX_CLIENTCONFIG__VCE_CLIENT0_MASK 0x00e00000L
+#define SEM_MAILBOX_CLIENTCONFIG__VCE_CLIENT0__SHIFT 0x00000015
+#define SEM_MAILBOX_CONTROL__HOSTPORT_ENABLE_MASK 0x0000ff00L
+#define SEM_MAILBOX_CONTROL__HOSTPORT_ENABLE__SHIFT 0x00000008
+#define SEM_MAILBOX_CONTROL__SIDEPORT_ENABLE_MASK 0x000000ffL
+#define SEM_MAILBOX_CONTROL__SIDEPORT_ENABLE__SHIFT 0x00000000
+#define SEM_MAILBOX__HOSTPORT_MASK 0x0000ff00L
+#define SEM_MAILBOX__HOSTPORT__SHIFT 0x00000008
+#define SEM_MAILBOX__SIDEPORT_MASK 0x000000ffL
+#define SEM_MAILBOX__SIDEPORT__SHIFT 0x00000000
+#define SEM_MCIF_CONFIG__MC_REQ_SWAP_MASK 0x00000003L
+#define SEM_MCIF_CONFIG__MC_REQ_SWAP__SHIFT 0x00000000
+#define SPU_PORT_STATUS__RESERVED_MASK 0xffffffffL
+#define SPU_PORT_STATUS__RESERVED__SHIFT 0x00000000
+#define SRBM_CAM_DATA__CAM_ADDR_MASK 0x0000ffffL
+#define SRBM_CAM_DATA__CAM_ADDR__SHIFT 0x00000000
+#define SRBM_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000L
+#define SRBM_CAM_DATA__CAM_REMAPADDR__SHIFT 0x00000010
+#define SRBM_CAM_INDEX__CAM_INDEX_MASK 0x00000007L
+#define SRBM_CAM_INDEX__CAM_INDEX__SHIFT 0x00000000
+#define SRBM_CHIP_REVISION__CHIP_REVISION_MASK 0x000000ffL
+#define SRBM_CHIP_REVISION__CHIP_REVISION__SHIFT 0x00000000
+#define SRBM_CNTL__COMBINE_SYSTEM_MC_MASK 0x00020000L
+#define SRBM_CNTL__COMBINE_SYSTEM_MC__SHIFT 0x00000011
+#define SRBM_CNTL__PWR_REQUEST_HALT_MASK 0x00010000L
+#define SRBM_CNTL__PWR_REQUEST_HALT__SHIFT 0x00000010
+#define SRBM_CNTL__READ_TIMEOUT_MASK 0x000003ffL
+#define SRBM_CNTL__READ_TIMEOUT__SHIFT 0x00000000
+#define SRBM_DEBUG_CNTL__SRBM_DEBUG_INDEX_MASK 0x0000003fL
+#define SRBM_DEBUG_CNTL__SRBM_DEBUG_INDEX__SHIFT 0x00000000
+#define SRBM_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define SRBM_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define SRBM_DEBUG__DISABLE_READ_TIMEOUT_MASK 0x00000002L
+#define SRBM_DEBUG__DISABLE_READ_TIMEOUT__SHIFT 0x00000001
+#define SRBM_DEBUG__IGNORE_RDY_MASK 0x00000001L
+#define SRBM_DEBUG__IGNORE_RDY__SHIFT 0x00000000
+#define SRBM_DEBUG__MC_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000100L
+#define SRBM_DEBUG__MC_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000008
+#define SRBM_DEBUG_SNAPSHOT__BIF_RDY_MASK 0x00000080L
+#define SRBM_DEBUG_SNAPSHOT__BIF_RDY__SHIFT 0x00000007
+#define SRBM_DEBUG_SNAPSHOT__DC_RDY_MASK 0x00000040L
+#define SRBM_DEBUG_SNAPSHOT__DC_RDY__SHIFT 0x00000006
+#define SRBM_DEBUG__SNAPSHOT_FREE_CNTRS_MASK 0x00000004L
+#define SRBM_DEBUG__SNAPSHOT_FREE_CNTRS__SHIFT 0x00000002
+#define SRBM_DEBUG_SNAPSHOT__GRBM_RDY_MASK 0x00000020L
+#define SRBM_DEBUG_SNAPSHOT__GRBM_RDY__SHIFT 0x00000005
+#define SRBM_DEBUG_SNAPSHOT__MCB_RDY_MASK 0x00000001L
+#define SRBM_DEBUG_SNAPSHOT__MCB_RDY__SHIFT 0x00000000
+#define SRBM_DEBUG_SNAPSHOT__MCC0_RDY_MASK 0x10000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC0_RDY__SHIFT 0x0000001c
+#define SRBM_DEBUG_SNAPSHOT__MCC1_RDY_MASK 0x08000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC1_RDY__SHIFT 0x0000001b
+#define SRBM_DEBUG_SNAPSHOT__MCC2_RDY_MASK 0x04000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC2_RDY__SHIFT 0x0000001a
+#define SRBM_DEBUG_SNAPSHOT__MCC3_RDY_MASK 0x02000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC3_RDY__SHIFT 0x00000019
+#define SRBM_DEBUG_SNAPSHOT__MCC4_RDY_MASK 0x01000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC4_RDY__SHIFT 0x00000018
+#define SRBM_DEBUG_SNAPSHOT__MCC5_RDY_MASK 0x00800000L
+#define SRBM_DEBUG_SNAPSHOT__MCC5_RDY__SHIFT 0x00000017
+#define SRBM_DEBUG_SNAPSHOT__MCC6_RDY_MASK 0x00400000L
+#define SRBM_DEBUG_SNAPSHOT__MCC6_RDY__SHIFT 0x00000016
+#define SRBM_DEBUG_SNAPSHOT__MCC7_RDY_MASK 0x00200000L
+#define SRBM_DEBUG_SNAPSHOT__MCC7_RDY__SHIFT 0x00000015
+#define SRBM_DEBUG_SNAPSHOT__MCD0_RDY_MASK 0x00100000L
+#define SRBM_DEBUG_SNAPSHOT__MCD0_RDY__SHIFT 0x00000014
+#define SRBM_DEBUG_SNAPSHOT__MCD1_RDY_MASK 0x00080000L
+#define SRBM_DEBUG_SNAPSHOT__MCD1_RDY__SHIFT 0x00000013
+#define SRBM_DEBUG_SNAPSHOT__MCD2_RDY_MASK 0x00040000L
+#define SRBM_DEBUG_SNAPSHOT__MCD2_RDY__SHIFT 0x00000012
+#define SRBM_DEBUG_SNAPSHOT__MCD3_RDY_MASK 0x00020000L
+#define SRBM_DEBUG_SNAPSHOT__MCD3_RDY__SHIFT 0x00000011
+#define SRBM_DEBUG_SNAPSHOT__MCD4_RDY_MASK 0x00010000L
+#define SRBM_DEBUG_SNAPSHOT__MCD4_RDY__SHIFT 0x00000010
+#define SRBM_DEBUG_SNAPSHOT__MCD5_RDY_MASK 0x00008000L
+#define SRBM_DEBUG_SNAPSHOT__MCD5_RDY__SHIFT 0x0000000f
+#define SRBM_DEBUG_SNAPSHOT__MCD6_RDY_MASK 0x00004000L
+#define SRBM_DEBUG_SNAPSHOT__MCD6_RDY__SHIFT 0x0000000e
+#define SRBM_DEBUG_SNAPSHOT__MCD7_RDY_MASK 0x00002000L
+#define SRBM_DEBUG_SNAPSHOT__MCD7_RDY__SHIFT 0x0000000d
+#define SRBM_DEBUG_SNAPSHOT__ORB_RDY_MASK 0x00001000L
+#define SRBM_DEBUG_SNAPSHOT__ORB_RDY__SHIFT 0x0000000c
+#define SRBM_DEBUG_SNAPSHOT__REGBB_RDY_MASK 0x00000800L
+#define SRBM_DEBUG_SNAPSHOT__REGBB_RDY__SHIFT 0x0000000b
+#define SRBM_DEBUG_SNAPSHOT__UVD_RDY_MASK 0x00000200L
+#define SRBM_DEBUG_SNAPSHOT__UVD_RDY__SHIFT 0x00000009
+#define SRBM_DEBUG_SNAPSHOT__VCE_RDY_MASK 0x20000000L
+#define SRBM_DEBUG_SNAPSHOT__VCE_RDY__SHIFT 0x0000001d
+#define SRBM_DEBUG_SNAPSHOT__XDMA_RDY_MASK 0x00000100L
+#define SRBM_DEBUG_SNAPSHOT__XDMA_RDY__SHIFT 0x00000008
+#define SRBM_DEBUG_SNAPSHOT__XSP_RDY_MASK 0x00000400L
+#define SRBM_DEBUG_SNAPSHOT__XSP_RDY__SHIFT 0x0000000a
+#define SRBM_DEBUG__SYS_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000010L
+#define SRBM_DEBUG__SYS_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000004
+#define SRBM_DEBUG__UVD_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000040L
+#define SRBM_DEBUG__UVD_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000006
+#define SRBM_DEBUG__VCE_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000020L
+#define SRBM_DEBUG__VCE_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000005
+#define SRBM_GFX_CNTL__VMID_MASK 0x000000f0L
+#define SRBM_GFX_CNTL__VMID__SHIFT 0x00000004
+#define SRBM_INT_ACK__RDERR_INT_ACK_MASK 0x00000001L
+#define SRBM_INT_ACK__RDERR_INT_ACK__SHIFT 0x00000000
+#define SRBM_INT_CNTL__RDERR_INT_MASK_MASK 0x00000001L
+#define SRBM_INT_CNTL__RDERR_INT_MASK__SHIFT 0x00000000
+#define SRBM_INT_STATUS__RDERR_INT_STAT_MASK 0x00000001L
+#define SRBM_INT_STATUS__RDERR_INT_STAT__SHIFT 0x00000000
+#define SRBM_MC_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_MC_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_MC_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_MC_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_HI__PERF_COUNT0_HI_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER0_HI__PERF_COUNT0_HI__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_LO__PERF_COUNT0_LO_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER0_LO__PERF_COUNT0_LO__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x0000003fL
+#define SRBM_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_HI__PERF_COUNT1_HI_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER1_HI__PERF_COUNT1_HI__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_LO__PERF_COUNT1_LO_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER1_LO__PERF_COUNT1_LO__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x0000003fL
+#define SRBM_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SRBM_PERFMON_CNTL__PERFMON_ENABLE_MODE_MASK 0x00000300L
+#define SRBM_PERFMON_CNTL__PERFMON_ENABLE_MODE__SHIFT 0x00000008
+#define SRBM_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define SRBM_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define SRBM_PERFMON_CNTL__PERFMON_STATE_MASK 0x0000000fL
+#define SRBM_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define SRBM_READ_ERROR__READ_ADDRESS_MASK 0x0003fffcL
+#define SRBM_READ_ERROR__READ_ADDRESS__SHIFT 0x00000002
+#define SRBM_READ_ERROR__READ_ERROR_MASK 0x80000000L
+#define SRBM_READ_ERROR__READ_ERROR__SHIFT 0x0000001f
+#define SRBM_READ_ERROR__READ_REQUESTER_GRBM_MASK 0x02000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_GRBM__SHIFT 0x00000019
+#define SRBM_READ_ERROR__READ_REQUESTER_HI_MASK 0x01000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_HI__SHIFT 0x00000018
+#define SRBM_READ_ERROR__READ_REQUESTER_SMU_MASK 0x04000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_SMU__SHIFT 0x0000001a
+#define SRBM_READ_ERROR__READ_REQUESTER_TST_MASK 0x00400000L
+#define SRBM_READ_ERROR__READ_REQUESTER_TST__SHIFT 0x00000016
+#define SRBM_READ_ERROR__READ_REQUESTER_UVD_MASK 0x20000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_UVD__SHIFT 0x0000001d
+#define SRBM_READ_ERROR__READ_REQUESTER_VCE_MASK 0x00100000L
+#define SRBM_READ_ERROR__READ_REQUESTER_VCE__SHIFT 0x00000014
+#define SRBM_SOFT_RESET__SOFT_RESET_BIF_MASK 0x00000002L
+#define SRBM_SOFT_RESET__SOFT_RESET_BIF__SHIFT 0x00000001
+#define SRBM_SOFT_RESET__SOFT_RESET_DC_MASK 0x00000020L
+#define SRBM_SOFT_RESET__SOFT_RESET_DC__SHIFT 0x00000005
+#define SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK 0x00000100L
+#define SRBM_SOFT_RESET__SOFT_RESET_GRBM__SHIFT 0x00000008
+#define SRBM_SOFT_RESET__SOFT_RESET_HDP_MASK 0x00000200L
+#define SRBM_SOFT_RESET__SOFT_RESET_HDP__SHIFT 0x00000009
+#define SRBM_SOFT_RESET__SOFT_RESET_IH_MASK 0x00000400L
+#define SRBM_SOFT_RESET__SOFT_RESET_IH__SHIFT 0x0000000a
+#define SRBM_SOFT_RESET__SOFT_RESET_MC_MASK 0x00000800L
+#define SRBM_SOFT_RESET__SOFT_RESET_MC__SHIFT 0x0000000b
+#define SRBM_SOFT_RESET__SOFT_RESET_ORB_MASK 0x00800000L
+#define SRBM_SOFT_RESET__SOFT_RESET_ORB__SHIFT 0x00000017
+#define SRBM_SOFT_RESET__SOFT_RESET_REGBB_MASK 0x00400000L
+#define SRBM_SOFT_RESET__SOFT_RESET_REGBB__SHIFT 0x00000016
+#define SRBM_SOFT_RESET__SOFT_RESET_ROM_MASK 0x00004000L
+#define SRBM_SOFT_RESET__SOFT_RESET_ROM__SHIFT 0x0000000e
+#define SRBM_SOFT_RESET__SOFT_RESET_SEM_MASK 0x00008000L
+#define SRBM_SOFT_RESET__SOFT_RESET_SEM__SHIFT 0x0000000f
+#define SRBM_SOFT_RESET__SOFT_RESET_TST_MASK 0x00200000L
+#define SRBM_SOFT_RESET__SOFT_RESET_TST__SHIFT 0x00000015
+#define SRBM_SOFT_RESET__SOFT_RESET_UVD_MASK 0x00040000L
+#define SRBM_SOFT_RESET__SOFT_RESET_UVD__SHIFT 0x00000012
+#define SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK 0x01000000L
+#define SRBM_SOFT_RESET__SOFT_RESET_VCE__SHIFT 0x00000018
+#define SRBM_SOFT_RESET__SOFT_RESET_VMC_MASK 0x00020000L
+#define SRBM_SOFT_RESET__SOFT_RESET_VMC__SHIFT 0x00000011
+#define SRBM_SOFT_RESET__SOFT_RESET_XDMA_MASK 0x02000000L
+#define SRBM_SOFT_RESET__SOFT_RESET_XDMA__SHIFT 0x00000019
+#define SRBM_SOFT_RESET__SOFT_RESET_XSP_MASK 0x00080000L
+#define SRBM_SOFT_RESET__SOFT_RESET_XSP__SHIFT 0x00000013
+#define SRBM_STATUS2__TST_RQ_PENDING_MASK 0x00000002L
+#define SRBM_STATUS2__TST_RQ_PENDING__SHIFT 0x00000001
+#define SRBM_STATUS2__VCE_BUSY_MASK 0x00000080L
+#define SRBM_STATUS2__VCE_BUSY__SHIFT 0x00000007
+#define SRBM_STATUS2__VCE_RQ_PENDING_MASK 0x00000008L
+#define SRBM_STATUS2__VCE_RQ_PENDING__SHIFT 0x00000003
+#define SRBM_STATUS2__XDMA_BUSY_MASK 0x00000100L
+#define SRBM_STATUS2__XDMA_BUSY__SHIFT 0x00000008
+#define SRBM_STATUS2__XSP_BUSY_MASK 0x00000010L
+#define SRBM_STATUS2__XSP_BUSY__SHIFT 0x00000004
+#define SRBM_STATUS__BIF_BUSY_MASK 0x20000000L
+#define SRBM_STATUS__BIF_BUSY__SHIFT 0x0000001d
+#define SRBM_STATUS__GRBM_RQ_PENDING_MASK 0x00000020L
+#define SRBM_STATUS__GRBM_RQ_PENDING__SHIFT 0x00000005
+#define SRBM_STATUS__HI_RQ_PENDING_MASK 0x00000040L
+#define SRBM_STATUS__HI_RQ_PENDING__SHIFT 0x00000006
+#define SRBM_STATUS__IH_BUSY_MASK 0x00020000L
+#define SRBM_STATUS__IH_BUSY__SHIFT 0x00000011
+#define SRBM_STATUS__IO_EXTERN_SIGNAL_MASK 0x00000080L
+#define SRBM_STATUS__IO_EXTERN_SIGNAL__SHIFT 0x00000007
+#define SRBM_STATUS__MCB_BUSY_MASK 0x00000200L
+#define SRBM_STATUS__MCB_BUSY__SHIFT 0x00000009
+#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK 0x00000400L
+#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY__SHIFT 0x0000000a
+#define SRBM_STATUS__MCC_BUSY_MASK 0x00000800L
+#define SRBM_STATUS__MCC_BUSY__SHIFT 0x0000000b
+#define SRBM_STATUS__MCD_BUSY_MASK 0x00001000L
+#define SRBM_STATUS__MCD_BUSY__SHIFT 0x0000000c
+#define SRBM_STATUS__SEM_BUSY_MASK 0x00004000L
+#define SRBM_STATUS__SEM_BUSY__SHIFT 0x0000000e
+#define SRBM_STATUS__SMU_RQ_PENDING_MASK 0x00000010L
+#define SRBM_STATUS__SMU_RQ_PENDING__SHIFT 0x00000004
+#define SRBM_STATUS__UVD_BUSY_MASK 0x00080000L
+#define SRBM_STATUS__UVD_BUSY__SHIFT 0x00000013
+#define SRBM_STATUS__UVD_RQ_PENDING_MASK 0x00000002L
+#define SRBM_STATUS__UVD_RQ_PENDING__SHIFT 0x00000001
+#define SRBM_STATUS__VMC_BUSY_MASK 0x00000100L
+#define SRBM_STATUS__VMC_BUSY__SHIFT 0x00000008
+#define SRBM_SYS_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_SYS_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_SYS_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_SYS_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_UVD_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_UVD_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_UVD_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_UVD_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_VCE_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_VCE_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_VCE_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_VCE_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define UVD_CONFIG__UVD_RDREQ_URG_MASK 0x00000f00L
+#define UVD_CONFIG__UVD_RDREQ_URG__SHIFT 0x00000008
+#define UVD_CONFIG__UVD_REQ_TRAN_MASK 0x00010000L
+#define UVD_CONFIG__UVD_REQ_TRAN__SHIFT 0x00000010
+#define VCE_CONFIG__VCE_RDREQ_URG_MASK 0x00000f00L
+#define VCE_CONFIG__VCE_RDREQ_URG__SHIFT 0x00000008
+#define VCE_CONFIG__VCE_REQ_TRAN_MASK 0x00010000L
+#define VCE_CONFIG__VCE_REQ_TRAN__SHIFT 0x00000010
+#define XDMA_MSTR_CNTL__XDMA_MSTR_LAT_TEST_EN_MASK 0x00080000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_LAT_TEST_EN__SHIFT 0x00000013
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_ENABLE_MASK 0x80000000L
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_ENABLE__SHIFT 0x0000001f
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_MASK 0x0000ffffL
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_THRESHOLD_MASK 0x3fff0000L
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_THRESHOLD__SHIFT 0x00000010
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h
new file mode 100644
index 000000000000..6b10be61efc3
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h
@@ -0,0 +1,148 @@
+/*
+ *
+ * Copyright (C) 2016 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 SMU_6_0_D_H
+#define SMU_6_0_D_H
+
+#define ixLCAC_MC0_CNTL 0x011C
+#define ixLCAC_MC0_OVR_SEL 0x011D
+#define ixLCAC_MC0_OVR_VAL 0x011E
+#define ixLCAC_MC1_CNTL 0x011F
+#define ixLCAC_MC1_OVR_SEL 0x0120
+#define ixLCAC_MC1_OVR_VAL 0x0121
+#define ixLCAC_MC2_CNTL 0x0122
+#define ixLCAC_MC2_OVR_SEL 0x0123
+#define ixLCAC_MC2_OVR_VAL 0x0124
+#define ixLCAC_MC3_CNTL 0x0125
+#define ixLCAC_MC3_OVR_SEL 0x0126
+#define ixLCAC_MC3_OVR_VAL 0x0127
+#define ixLCAC_MC4_CNTL 0x0128
+#define ixLCAC_MC4_OVR_SEL 0x0129
+#define ixLCAC_MC4_OVR_VAL 0x012A
+#define ixLCAC_MC5_CNTL 0x012B
+#define ixLCAC_MC5_OVR_SEL 0x012C
+#define ixLCAC_MC5_OVR_VAL 0x012D
+#define ixSMC_PC_C 0x80000370
+#define ixTHM_TMON0_DEBUG 0x03F0
+#define ixTHM_TMON0_INT_DATA 0x0380
+#define ixTHM_TMON0_RDIL0_DATA 0x0300
+#define ixTHM_TMON0_RDIL10_DATA 0x030A
+#define ixTHM_TMON0_RDIL11_DATA 0x030B
+#define ixTHM_TMON0_RDIL12_DATA 0x030C
+#define ixTHM_TMON0_RDIL13_DATA 0x030D
+#define ixTHM_TMON0_RDIL14_DATA 0x030E
+#define ixTHM_TMON0_RDIL15_DATA 0x030F
+#define ixTHM_TMON0_RDIL1_DATA 0x0301
+#define ixTHM_TMON0_RDIL2_DATA 0x0302
+#define ixTHM_TMON0_RDIL3_DATA 0x0303
+#define ixTHM_TMON0_RDIL4_DATA 0x0304
+#define ixTHM_TMON0_RDIL5_DATA 0x0305
+#define ixTHM_TMON0_RDIL6_DATA 0x0306
+#define ixTHM_TMON0_RDIL7_DATA 0x0307
+#define ixTHM_TMON0_RDIL8_DATA 0x0308
+#define ixTHM_TMON0_RDIL9_DATA 0x0309
+#define ixTHM_TMON0_RDIR0_DATA 0x0310
+#define ixTHM_TMON0_RDIR10_DATA 0x031A
+#define ixTHM_TMON0_RDIR11_DATA 0x031B
+#define ixTHM_TMON0_RDIR12_DATA 0x031C
+#define ixTHM_TMON0_RDIR13_DATA 0x031D
+#define ixTHM_TMON0_RDIR14_DATA 0x031E
+#define ixTHM_TMON0_RDIR15_DATA 0x031F
+#define ixTHM_TMON0_RDIR1_DATA 0x0311
+#define ixTHM_TMON0_RDIR2_DATA 0x0312
+#define ixTHM_TMON0_RDIR3_DATA 0x0313
+#define ixTHM_TMON0_RDIR4_DATA 0x0314
+#define ixTHM_TMON0_RDIR5_DATA 0x0315
+#define ixTHM_TMON0_RDIR6_DATA 0x0316
+#define ixTHM_TMON0_RDIR7_DATA 0x0317
+#define ixTHM_TMON0_RDIR8_DATA 0x0318
+#define ixTHM_TMON0_RDIR9_DATA 0x0319
+#define ixTHM_TMON1_DEBUG 0x03F1
+#define ixTHM_TMON1_INT_DATA 0x0381
+#define ixTHM_TMON1_RDIL0_DATA 0x0320
+#define ixTHM_TMON1_RDIL10_DATA 0x032A
+#define ixTHM_TMON1_RDIL11_DATA 0x032B
+#define ixTHM_TMON1_RDIL12_DATA 0x032C
+#define ixTHM_TMON1_RDIL13_DATA 0x032D
+#define ixTHM_TMON1_RDIL14_DATA 0x032E
+#define ixTHM_TMON1_RDIL15_DATA 0x032F
+#define ixTHM_TMON1_RDIL1_DATA 0x0321
+#define ixTHM_TMON1_RDIL2_DATA 0x0322
+#define ixTHM_TMON1_RDIL3_DATA 0x0323
+#define ixTHM_TMON1_RDIL4_DATA 0x0324
+#define ixTHM_TMON1_RDIL5_DATA 0x0325
+#define ixTHM_TMON1_RDIL6_DATA 0x0326
+#define ixTHM_TMON1_RDIL7_DATA 0x0327
+#define ixTHM_TMON1_RDIL8_DATA 0x0328
+#define ixTHM_TMON1_RDIL9_DATA 0x0329
+#define ixTHM_TMON1_RDIR0_DATA 0x0330
+#define ixTHM_TMON1_RDIR10_DATA 0x033A
+#define ixTHM_TMON1_RDIR11_DATA 0x033B
+#define ixTHM_TMON1_RDIR12_DATA 0x033C
+#define ixTHM_TMON1_RDIR13_DATA 0x033D
+#define ixTHM_TMON1_RDIR14_DATA 0x033E
+#define ixTHM_TMON1_RDIR15_DATA 0x033F
+#define ixTHM_TMON1_RDIR1_DATA 0x0331
+#define ixTHM_TMON1_RDIR2_DATA 0x0332
+#define ixTHM_TMON1_RDIR3_DATA 0x0333
+#define ixTHM_TMON1_RDIR4_DATA 0x0334
+#define ixTHM_TMON1_RDIR5_DATA 0x0335
+#define ixTHM_TMON1_RDIR6_DATA 0x0336
+#define ixTHM_TMON1_RDIR7_DATA 0x0337
+#define ixTHM_TMON1_RDIR8_DATA 0x0338
+#define ixTHM_TMON1_RDIR9_DATA 0x0339
+#define mmGPIOPAD_A 0x05E7
+#define mmGPIOPAD_EN 0x05E8
+#define mmGPIOPAD_EXTERN_TRIG_CNTL 0x05F1
+#define mmGPIOPAD_INT_EN 0x05EE
+#define mmGPIOPAD_INT_POLARITY 0x05F0
+#define mmGPIOPAD_INT_STAT 0x05EC
+#define mmGPIOPAD_INT_STAT_AK 0x05ED
+#define mmGPIOPAD_INT_STAT_EN 0x05EB
+#define mmGPIOPAD_INT_TYPE 0x05EF
+#define mmGPIOPAD_MASK 0x05E6
+#define mmGPIOPAD_PD_EN 0x05F4
+#define mmGPIOPAD_PINSTRAPS 0x05EA
+#define mmGPIOPAD_PU_EN 0x05F3
+#define mmGPIOPAD_RCVR_SEL 0x05F2
+#define mmGPIOPAD_STRENGTH 0x05E5
+#define mmGPIOPAD_SW_INT_STAT 0x05E4
+#define mmGPIOPAD_Y 0x05E9
+#define mmSMC_IND_ACCESS_CNTL 0x008A
+#define mmSMC_IND_DATA_0 0x0081
+#define mmSMC_IND_DATA 0x0081
+#define mmSMC_IND_DATA_1 0x0083
+#define mmSMC_IND_DATA_2 0x0085
+#define mmSMC_IND_DATA_3 0x0087
+#define mmSMC_IND_INDEX_0 0x0080
+#define mmSMC_IND_INDEX 0x0080
+#define mmSMC_IND_INDEX_1 0x0082
+#define mmSMC_IND_INDEX_2 0x0084
+#define mmSMC_IND_INDEX_3 0x0086
+#define mmSMC_MESSAGE_0 0x008B
+#define mmSMC_MESSAGE_1 0x008D
+#define mmSMC_MESSAGE_2 0x008F
+#define mmSMC_RESP_0 0x008C
+#define mmSMC_RESP_1 0x008E
+#define mmSMC_RESP_2 0x0090
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h
new file mode 100644
index 000000000000..7d3925b7266e
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h
@@ -0,0 +1,715 @@
+/*
+ *
+ * Copyright (C) 2016 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 SMU_6_0_SH_MASK_H
+#define SMU_6_0_SH_MASK_H
+
+#define CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV_MASK 0x03ffffffL
+#define CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV__SHIFT 0x00000000
+#define CG_SPLL_FUNC_CNTL__SPLL_REF_DIV_MASK 0x000003f0L
+#define CG_SPLL_FUNC_CNTL__SPLL_REF_DIV__SHIFT 0x00000004
+#define GPIOPAD_A__GPIO_A_MASK 0x7fffffffL
+#define GPIOPAD_A__GPIO_A__SHIFT 0x00000000
+#define GPIOPAD_EN__GPIO_EN_MASK 0x7fffffffL
+#define GPIOPAD_EN__GPIO_EN__SHIFT 0x00000000
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_CLR_MASK 0x00000020L
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_CLR__SHIFT 0x00000005
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_READ_MASK 0x00000040L
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_READ__SHIFT 0x00000006
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_SEL_MASK 0x0000001fL
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_SEL__SHIFT 0x00000000
+#define GPIOPAD_INT_EN__GPIO_INT_EN_MASK 0x1fffffffL
+#define GPIOPAD_INT_EN__GPIO_INT_EN__SHIFT 0x00000000
+#define GPIOPAD_INT_EN__SW_INITIATED_INT_EN_MASK 0x80000000L
+#define GPIOPAD_INT_EN__SW_INITIATED_INT_EN__SHIFT 0x0000001f
+#define GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY_MASK 0x1fffffffL
+#define GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY__SHIFT 0x00000000
+#define GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY_MASK 0x80000000L
+#define GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0_MASK 0x00000001L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10_MASK 0x00000400L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10__SHIFT 0x0000000a
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11_MASK 0x00000800L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11__SHIFT 0x0000000b
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12_MASK 0x00001000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12__SHIFT 0x0000000c
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13_MASK 0x00002000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13__SHIFT 0x0000000d
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14_MASK 0x00004000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14__SHIFT 0x0000000e
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15_MASK 0x00008000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15__SHIFT 0x0000000f
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16_MASK 0x00010000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16__SHIFT 0x00000010
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17_MASK 0x00020000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17__SHIFT 0x00000011
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18_MASK 0x00040000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18__SHIFT 0x00000012
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19_MASK 0x00080000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19__SHIFT 0x00000013
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1_MASK 0x00000002L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1__SHIFT 0x00000001
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20_MASK 0x00100000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20__SHIFT 0x00000014
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21_MASK 0x00200000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21__SHIFT 0x00000015
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22_MASK 0x00400000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22__SHIFT 0x00000016
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23_MASK 0x00800000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23__SHIFT 0x00000017
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24_MASK 0x01000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24__SHIFT 0x00000018
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25_MASK 0x02000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25__SHIFT 0x00000019
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26_MASK 0x04000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26__SHIFT 0x0000001a
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27_MASK 0x08000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27__SHIFT 0x0000001b
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28_MASK 0x10000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28__SHIFT 0x0000001c
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2_MASK 0x00000004L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2__SHIFT 0x00000002
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3_MASK 0x00000008L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3__SHIFT 0x00000003
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4_MASK 0x00000010L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4__SHIFT 0x00000004
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5_MASK 0x00000020L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5__SHIFT 0x00000005
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6_MASK 0x00000040L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6__SHIFT 0x00000006
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7_MASK 0x00000080L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7__SHIFT 0x00000007
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8_MASK 0x00000100L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8__SHIFT 0x00000008
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9_MASK 0x00000200L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9__SHIFT 0x00000009
+#define GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK_MASK 0x80000000L
+#define GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN_MASK 0x1fffffffL
+#define GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN_MASK 0x80000000L
+#define GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT__GPIO_INT_STAT_MASK 0x1fffffffL
+#define GPIOPAD_INT_STAT__GPIO_INT_STAT__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT_MASK 0x80000000L
+#define GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT__SHIFT 0x0000001f
+#define GPIOPAD_INT_TYPE__GPIO_INT_TYPE_MASK 0x1fffffffL
+#define GPIOPAD_INT_TYPE__GPIO_INT_TYPE__SHIFT 0x00000000
+#define GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE_MASK 0x80000000L
+#define GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE__SHIFT 0x0000001f
+#define GPIOPAD_MASK__GPIO_MASK_MASK 0x7fffffffL
+#define GPIOPAD_MASK__GPIO_MASK__SHIFT 0x00000000
+#define GPIOPAD_PD_EN__GPIO_PD_EN_MASK 0x7fffffffL
+#define GPIOPAD_PD_EN__GPIO_PD_EN__SHIFT 0x00000000
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0_MASK 0x00000001L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0__SHIFT 0x00000000
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10_MASK 0x00000400L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10__SHIFT 0x0000000a
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11_MASK 0x00000800L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11__SHIFT 0x0000000b
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12_MASK 0x00001000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12__SHIFT 0x0000000c
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13_MASK 0x00002000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13__SHIFT 0x0000000d
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14_MASK 0x00004000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14__SHIFT 0x0000000e
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15_MASK 0x00008000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15__SHIFT 0x0000000f
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16_MASK 0x00010000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16__SHIFT 0x00000010
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17_MASK 0x00020000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17__SHIFT 0x00000011
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18_MASK 0x00040000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18__SHIFT 0x00000012
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19_MASK 0x00080000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19__SHIFT 0x00000013
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1_MASK 0x00000002L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1__SHIFT 0x00000001
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20_MASK 0x00100000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20__SHIFT 0x00000014
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21_MASK 0x00200000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21__SHIFT 0x00000015
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22_MASK 0x00400000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22__SHIFT 0x00000016
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23_MASK 0x00800000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23__SHIFT 0x00000017
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24_MASK 0x01000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24__SHIFT 0x00000018
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25_MASK 0x02000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25__SHIFT 0x00000019
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26_MASK 0x04000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26__SHIFT 0x0000001a
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27_MASK 0x08000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27__SHIFT 0x0000001b
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28_MASK 0x10000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28__SHIFT 0x0000001c
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29_MASK 0x20000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29__SHIFT 0x0000001d
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2_MASK 0x00000004L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2__SHIFT 0x00000002
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30_MASK 0x40000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30__SHIFT 0x0000001e
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3_MASK 0x00000008L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3__SHIFT 0x00000003
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4_MASK 0x00000010L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4__SHIFT 0x00000004
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5_MASK 0x00000020L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5__SHIFT 0x00000005
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6_MASK 0x00000040L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6__SHIFT 0x00000006
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7_MASK 0x00000080L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7__SHIFT 0x00000007
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8_MASK 0x00000100L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8__SHIFT 0x00000008
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9_MASK 0x00000200L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9__SHIFT 0x00000009
+#define GPIOPAD_PU_EN__GPIO_PU_EN_MASK 0x7fffffffL
+#define GPIOPAD_PU_EN__GPIO_PU_EN__SHIFT 0x00000000
+#define GPIOPAD_RCVR_SEL__GPIO_RCVR_SEL_MASK 0x7fffffffL
+#define GPIOPAD_RCVR_SEL__GPIO_RCVR_SEL__SHIFT 0x00000000
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SN_MASK 0x0000000fL
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SN__SHIFT 0x00000000
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SP_MASK 0x000000f0L
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SP__SHIFT 0x00000004
+#define GPIOPAD_SW_INT_STAT__SW_INT_STAT_MASK 0x00000001L
+#define GPIOPAD_SW_INT_STAT__SW_INT_STAT__SHIFT 0x00000000
+#define GPIOPAD_Y__GPIO_Y_MASK 0x7fffffffL
+#define GPIOPAD_Y__GPIO_Y__SHIFT 0x00000000
+#define LCAC_MC0_CNTL__MC0_ENABLE_MASK 0x00000001L
+#define LCAC_MC0_CNTL__MC0_ENABLE__SHIFT 0x00000000
+#define LCAC_MC0_CNTL__MC0_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC0_CNTL__MC0_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC0_OVR_SEL__MC0_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC0_OVR_SEL__MC0_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC0_OVR_VAL__MC0_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC0_OVR_VAL__MC0_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC1_CNTL__MC1_ENABLE_MASK 0x00000001L
+#define LCAC_MC1_CNTL__MC1_ENABLE__SHIFT 0x00000000
+#define LCAC_MC1_CNTL__MC1_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC1_CNTL__MC1_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC1_OVR_SEL__MC1_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC1_OVR_SEL__MC1_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC1_OVR_VAL__MC1_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC1_OVR_VAL__MC1_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC2_CNTL__MC2_ENABLE_MASK 0x00000001L
+#define LCAC_MC2_CNTL__MC2_ENABLE__SHIFT 0x00000000
+#define LCAC_MC2_CNTL__MC2_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC2_CNTL__MC2_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC2_OVR_SEL__MC2_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC2_OVR_SEL__MC2_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC2_OVR_VAL__MC2_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC2_OVR_VAL__MC2_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC3_CNTL__MC3_ENABLE_MASK 0x00000001L
+#define LCAC_MC3_CNTL__MC3_ENABLE__SHIFT 0x00000000
+#define LCAC_MC3_CNTL__MC3_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC3_CNTL__MC3_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC3_OVR_SEL__MC3_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC3_OVR_SEL__MC3_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC3_OVR_VAL__MC3_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC3_OVR_VAL__MC3_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC4_CNTL__MC4_ENABLE_MASK 0x00000001L
+#define LCAC_MC4_CNTL__MC4_ENABLE__SHIFT 0x00000000
+#define LCAC_MC4_CNTL__MC4_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC4_CNTL__MC4_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC4_OVR_SEL__MC4_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC4_OVR_SEL__MC4_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC4_OVR_VAL__MC4_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC4_OVR_VAL__MC4_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC5_CNTL__MC5_ENABLE_MASK 0x00000001L
+#define LCAC_MC5_CNTL__MC5_ENABLE__SHIFT 0x00000000
+#define LCAC_MC5_CNTL__MC5_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC5_CNTL__MC5_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC5_OVR_SEL__MC5_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC5_OVR_SEL__MC5_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC5_OVR_VAL__MC5_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC5_OVR_VAL__MC5_OVR_VAL__SHIFT 0x00000000
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK 0x00000001L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0__SHIFT 0x00000000
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_1_MASK 0x00000100L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_1__SHIFT 0x00000008
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_2_MASK 0x00010000L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_2__SHIFT 0x00000010
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_3_MASK 0x01000000L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_3__SHIFT 0x00000018
+#define SMC_IND_DATA_0__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_0__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_1__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_1__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_2__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_2__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_3__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_3__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_INDEX_0__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_0__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_1__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_1__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_2__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_2__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_3__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_3__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_MESSAGE_0__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_0__SMC_MSG__SHIFT 0x00000000
+#define SMC_MESSAGE_1__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_1__SMC_MSG__SHIFT 0x00000000
+#define SMC_MESSAGE_2__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_2__SMC_MSG__SHIFT 0x00000000
+#define SMC_PC_C__smc_pc_c_MASK 0xffffffffL
+#define SMC_PC_C__smc_pc_c__SHIFT 0x00000000
+#define SMC_RESP_0__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_0__SMC_RESP__SHIFT 0x00000000
+#define SMC_RESP_1__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_1__SMC_RESP__SHIFT 0x00000000
+#define SMC_RESP_2__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_2__SMC_RESP__SHIFT 0x00000000
+#define SPLL_CNTL_MODE__SPLL_CTLREQ_DLY_CNT_MASK 0x000ff000L
+#define SPLL_CNTL_MODE__SPLL_CTLREQ_DLY_CNT__SHIFT 0x0000000c
+#define SPLL_CNTL_MODE__SPLL_ENSAT_MASK 0x00000010L
+#define SPLL_CNTL_MODE__SPLL_ENSAT__SHIFT 0x00000004
+#define SPLL_CNTL_MODE__SPLL_FASTEN_MASK 0x00000008L
+#define SPLL_CNTL_MODE__SPLL_FASTEN__SHIFT 0x00000003
+#define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV_MASK 0x00000002L
+#define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV__SHIFT 0x00000001
+#define SPLL_CNTL_MODE__SPLL_RESET_EN_MASK 0x10000000L
+#define SPLL_CNTL_MODE__SPLL_RESET_EN__SHIFT 0x0000001c
+#define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL_MASK 0x00000001L
+#define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL__SHIFT 0x00000000
+#define SPLL_CNTL_MODE__SPLL_TEST_CLK_EXT_DIV_MASK 0x00000c00L
+#define SPLL_CNTL_MODE__SPLL_TEST_CLK_EXT_DIV__SHIFT 0x0000000a
+#define SPLL_CNTL_MODE__SPLL_TEST_MASK 0x00000004L
+#define SPLL_CNTL_MODE__SPLL_TEST__SHIFT 0x00000002
+#define SPLL_CNTL_MODE__SPLL_VCO_MODE_MASK 0x60000000L
+#define SPLL_CNTL_MODE__SPLL_VCO_MODE__SHIFT 0x0000001d
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX_MASK 0x0f000000L
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX__SHIFT 0x00000018
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__TARG_PCIE_INDEX_MASK 0xf0000000L
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__TARG_PCIE_INDEX__SHIFT 0x0000001c
+#define THM_TMON0_DEBUG__DEBUG_RDI_MASK 0x0000001fL
+#define THM_TMON0_DEBUG__DEBUG_RDI__SHIFT 0x00000000
+#define THM_TMON0_DEBUG__DEBUG_Z_MASK 0x0000ffe0L
+#define THM_TMON0_DEBUG__DEBUG_Z__SHIFT 0x00000005
+#define THM_TMON0_INT_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_INT_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_INT_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_INT_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_INT_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_INT_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_DEBUG__DEBUG_RDI_MASK 0x0000001fL
+#define THM_TMON1_DEBUG__DEBUG_RDI__SHIFT 0x00000000
+#define THM_TMON1_DEBUG__DEBUG_Z_MASK 0x0000ffe0L
+#define THM_TMON1_DEBUG__DEBUG_Z__SHIFT 0x00000005
+#define THM_TMON1_INT_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_INT_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_INT_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_INT_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_INT_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_INT_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR9_DATA__Z__SHIFT 0x00000000
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h
index 3014d4a58c43..a9ef1562f43b 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h
@@ -176,6 +176,8 @@
#define mmSMU1_SMU_SMC_IND_DATA 0x83
#define mmSMU2_SMU_SMC_IND_DATA 0x85
#define mmSMU3_SMU_SMC_IND_DATA 0x87
+#define mmSMC_IND_INDEX_11 0x1AC
+#define mmSMC_IND_DATA_11 0x1AD
#define ixRCU_UC_EVENTS 0xc0000004
#define ixRCU_MISC_CTRL 0xc0000010
#define ixCC_RCU_FUSES 0xc00c0000
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h
index 933917479985..22dd4c2b7290 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h
@@ -87,6 +87,8 @@
#define mmSMC_IND_DATA_6 0x8d
#define mmSMC_IND_INDEX_7 0x8e
#define mmSMC_IND_DATA_7 0x8f
+#define mmSMC_IND_INDEX_11 0x1AC
+#define mmSMC_IND_DATA_11 0x1AD
#define mmSMC_IND_ACCESS_CNTL 0x92
#define mmSMC_MESSAGE_0 0x94
#define mmSMC_RESP_0 0x95
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h
index 44b1855cb8df..eca2b851f25f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h
@@ -90,6 +90,8 @@
#define mmSMC_IND_DATA_6 0x8d
#define mmSMC_IND_INDEX_7 0x8e
#define mmSMC_IND_DATA_7 0x8f
+#define mmSMC_IND_INDEX_11 0x1AC
+#define mmSMC_IND_DATA_11 0x1AD
#define mmSMC_IND_ACCESS_CNTL 0x92
#define mmSMC_MESSAGE_0 0x94
#define mmSMC_RESP_0 0x95
diff --git a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h
new file mode 100644
index 000000000000..5c0e3f3332e5
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright (C) 2016 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 UVD_4_0_D_H
+#define UVD_4_0_D_H
+
+#define ixUVD_CGC_CTRL2 0x00C1
+#define ixUVD_CGC_MEM_CTRL 0x00C0
+#define ixUVD_LMI_ADDR_EXT2 0x00AB
+#define ixUVD_LMI_CACHE_CTRL 0x009B
+#define ixUVD_LMI_SWAP_CNTL2 0x00AA
+#define ixUVD_MIF_CURR_ADDR_CONFIG 0x0048
+#define ixUVD_MIF_RECON1_ADDR_CONFIG 0x0114
+#define ixUVD_MIF_REF_ADDR_CONFIG 0x004C
+#define mmUVD_CGC_CTRL 0x3D2C
+#define mmUVD_CGC_GATE 0x3D2A
+#define mmUVD_CGC_STATUS 0x3D2B
+#define mmUVD_CGC_UDEC_STATUS 0x3D2D
+#define mmUVD_CONTEXT_ID 0x3DBD
+#define mmUVD_CTX_DATA 0x3D29
+#define mmUVD_CTX_INDEX 0x3D28
+#define mmUVD_ENGINE_CNTL 0x3BC6
+#define mmUVD_GPCOM_VCPU_CMD 0x3BC3
+#define mmUVD_GPCOM_VCPU_DATA0 0x3BC4
+#define mmUVD_GPCOM_VCPU_DATA1 0x3BC5
+#define mmUVD_GP_SCRATCH4 0x3D38
+#define mmUVD_LMI_ADDR_EXT 0x3D65
+#define mmUVD_LMI_CTRL 0x3D66
+#define mmUVD_LMI_CTRL2 0x3D3D
+#define mmUVD_LMI_EXT40_ADDR 0x3D26
+#define mmUVD_LMI_STATUS 0x3D67
+#define mmUVD_LMI_SWAP_CNTL 0x3D6D
+#define mmUVD_MASTINT_EN 0x3D40
+#define mmUVD_MPC_CNTL 0x3D77
+#define mmUVD_MPC_SET_ALU 0x3D7E
+#define mmUVD_MPC_SET_MUX 0x3D7D
+#define mmUVD_MPC_SET_MUXA0 0x3D79
+#define mmUVD_MPC_SET_MUXA1 0x3D7A
+#define mmUVD_MPC_SET_MUXB0 0x3D7B
+#define mmUVD_MPC_SET_MUXB1 0x3D7C
+#define mmUVD_MP_SWAP_CNTL 0x3D6F
+#define mmUVD_NO_OP 0x3BFF
+#define mmUVD_PGFSM_CONFIG 0x38F8
+#define mmUVD_PGFSM_READ_TILE1 0x38FA
+#define mmUVD_PGFSM_READ_TILE2 0x38FB
+#define mmUVD_POWER_STATUS 0x38FC
+#define mmUVD_RBC_IB_BASE 0x3DA1
+#define mmUVD_RBC_IB_SIZE 0x3DA2
+#define mmUVD_RBC_IB_SIZE_UPDATE 0x3DF1
+#define mmUVD_RBC_RB_BASE 0x3DA3
+#define mmUVD_RBC_RB_CNTL 0x3DA9
+#define mmUVD_RBC_RB_RPTR 0x3DA4
+#define mmUVD_RBC_RB_RPTR_ADDR 0x3DAA
+#define mmUVD_RBC_RB_WPTR 0x3DA5
+#define mmUVD_RBC_RB_WPTR_CNTL 0x3DA6
+#define mmUVD_SEMA_ADDR_HIGH 0x3BC1
+#define mmUVD_SEMA_ADDR_LOW 0x3BC0
+#define mmUVD_SEMA_CMD 0x3BC2
+#define mmUVD_SEMA_CNTL 0x3D00
+#define mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL 0x3DB3
+#define mmUVD_SEMA_TIMEOUT_STATUS 0x3DB0
+#define mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL 0x3DB2
+#define mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL 0x3DB1
+#define mmUVD_SOFT_RESET 0x3DA0
+#define mmUVD_STATUS 0x3DAF
+#define mmUVD_UDEC_ADDR_CONFIG 0x3BD3
+#define mmUVD_UDEC_DB_ADDR_CONFIG 0x3BD4
+#define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3BD5
+#define mmUVD_VCPU_CACHE_OFFSET0 0x3D36
+#define mmUVD_VCPU_CACHE_OFFSET1 0x3D38
+#define mmUVD_VCPU_CACHE_OFFSET2 0x3D3A
+#define mmUVD_VCPU_CACHE_SIZE0 0x3D37
+#define mmUVD_VCPU_CACHE_SIZE1 0x3D39
+#define mmUVD_VCPU_CACHE_SIZE2 0x3D3B
+#define mmUVD_VCPU_CNTL 0x3D98
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h
new file mode 100644
index 000000000000..8ee3149df5b7
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h
@@ -0,0 +1,795 @@
+/*
+ *
+ * Copyright (C) 2016 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 UVD_4_0_SH_MASK_H
+#define UVD_4_0_SH_MASK_H
+
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK 0x00000001L
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN__SHIFT 0x00000000
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK 0x00000002L
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN__SHIFT 0x00000001
+#define UVD_CGC_CTRL2__GATER_DIV_ID_MASK 0x0000001cL
+#define UVD_CGC_CTRL2__GATER_DIV_ID__SHIFT 0x00000002
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK 0x0000003cL
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT 0x00000002
+#define UVD_CGC_CTRL__CLK_OFF_DELAY_MASK 0x000007c0L
+#define UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT 0x00000006
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK 0x00000001L
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT 0x00000000
+#define UVD_CGC_CTRL__IDCT_MODE_MASK 0x00800000L
+#define UVD_CGC_CTRL__IDCT_MODE__SHIFT 0x00000017
+#define UVD_CGC_CTRL__LBSI_MODE_MASK 0x04000000L
+#define UVD_CGC_CTRL__LBSI_MODE__SHIFT 0x0000001a
+#define UVD_CGC_CTRL__LMI_MC_MODE_MASK 0x00200000L
+#define UVD_CGC_CTRL__LMI_MC_MODE__SHIFT 0x00000015
+#define UVD_CGC_CTRL__LMI_UMC_MODE_MASK 0x00400000L
+#define UVD_CGC_CTRL__LMI_UMC_MODE__SHIFT 0x00000016
+#define UVD_CGC_CTRL__LRBBM_MODE_MASK 0x08000000L
+#define UVD_CGC_CTRL__LRBBM_MODE__SHIFT 0x0000001b
+#define UVD_CGC_CTRL__MPC_MODE_MASK 0x02000000L
+#define UVD_CGC_CTRL__MPC_MODE__SHIFT 0x00000019
+#define UVD_CGC_CTRL__MPEG2_MODE_MASK 0x00040000L
+#define UVD_CGC_CTRL__MPEG2_MODE__SHIFT 0x00000012
+#define UVD_CGC_CTRL__MPRD_MODE_MASK 0x01000000L
+#define UVD_CGC_CTRL__MPRD_MODE__SHIFT 0x00000018
+#define UVD_CGC_CTRL__RBC_MODE_MASK 0x00100000L
+#define UVD_CGC_CTRL__RBC_MODE__SHIFT 0x00000014
+#define UVD_CGC_CTRL__REGS_MODE_MASK 0x00080000L
+#define UVD_CGC_CTRL__REGS_MODE__SHIFT 0x00000013
+#define UVD_CGC_CTRL__SCPU_MODE_MASK 0x40000000L
+#define UVD_CGC_CTRL__SCPU_MODE__SHIFT 0x0000001e
+#define UVD_CGC_CTRL__SYS_MODE_MASK 0x00010000L
+#define UVD_CGC_CTRL__SYS_MODE__SHIFT 0x00000010
+#define UVD_CGC_CTRL__UDEC_CM_MODE_MASK 0x00001000L
+#define UVD_CGC_CTRL__UDEC_CM_MODE__SHIFT 0x0000000c
+#define UVD_CGC_CTRL__UDEC_DB_MODE_MASK 0x00004000L
+#define UVD_CGC_CTRL__UDEC_DB_MODE__SHIFT 0x0000000e
+#define UVD_CGC_CTRL__UDEC_IT_MODE_MASK 0x00002000L
+#define UVD_CGC_CTRL__UDEC_IT_MODE__SHIFT 0x0000000d
+#define UVD_CGC_CTRL__UDEC_MODE_MASK 0x00020000L
+#define UVD_CGC_CTRL__UDEC_MODE__SHIFT 0x00000011
+#define UVD_CGC_CTRL__UDEC_MP_MODE_MASK 0x00008000L
+#define UVD_CGC_CTRL__UDEC_MP_MODE__SHIFT 0x0000000f
+#define UVD_CGC_CTRL__UDEC_RE_MODE_MASK 0x00000800L
+#define UVD_CGC_CTRL__UDEC_RE_MODE__SHIFT 0x0000000b
+#define UVD_CGC_CTRL__VCPU_MODE_MASK 0x20000000L
+#define UVD_CGC_CTRL__VCPU_MODE__SHIFT 0x0000001d
+#define UVD_CGC_CTRL__WCB_MODE_MASK 0x10000000L
+#define UVD_CGC_CTRL__WCB_MODE__SHIFT 0x0000001c
+#define UVD_CGC_GATE__IDCT_MASK 0x00000080L
+#define UVD_CGC_GATE__IDCT__SHIFT 0x00000007
+#define UVD_CGC_GATE__LBSI_MASK 0x00000400L
+#define UVD_CGC_GATE__LBSI__SHIFT 0x0000000a
+#define UVD_CGC_GATE__LMI_MC_MASK 0x00000020L
+#define UVD_CGC_GATE__LMI_MC__SHIFT 0x00000005
+#define UVD_CGC_GATE__LMI_UMC_MASK 0x00000040L
+#define UVD_CGC_GATE__LMI_UMC__SHIFT 0x00000006
+#define UVD_CGC_GATE__LRBBM_MASK 0x00000800L
+#define UVD_CGC_GATE__LRBBM__SHIFT 0x0000000b
+#define UVD_CGC_GATE__MPC_MASK 0x00000200L
+#define UVD_CGC_GATE__MPC__SHIFT 0x00000009
+#define UVD_CGC_GATE__MPEG2_MASK 0x00000004L
+#define UVD_CGC_GATE__MPEG2__SHIFT 0x00000002
+#define UVD_CGC_GATE__MPRD_MASK 0x00000100L
+#define UVD_CGC_GATE__MPRD__SHIFT 0x00000008
+#define UVD_CGC_GATE__RBC_MASK 0x00000010L
+#define UVD_CGC_GATE__RBC__SHIFT 0x00000004
+#define UVD_CGC_GATE__REGS_MASK 0x00000008L
+#define UVD_CGC_GATE__REGS__SHIFT 0x00000003
+#define UVD_CGC_GATE__SCPU_MASK 0x00080000L
+#define UVD_CGC_GATE__SCPU__SHIFT 0x00000013
+#define UVD_CGC_GATE__SYS_MASK 0x00000001L
+#define UVD_CGC_GATE__SYS__SHIFT 0x00000000
+#define UVD_CGC_GATE__UDEC_CM_MASK 0x00002000L
+#define UVD_CGC_GATE__UDEC_CM__SHIFT 0x0000000d
+#define UVD_CGC_GATE__UDEC_DB_MASK 0x00008000L
+#define UVD_CGC_GATE__UDEC_DB__SHIFT 0x0000000f
+#define UVD_CGC_GATE__UDEC_IT_MASK 0x00004000L
+#define UVD_CGC_GATE__UDEC_IT__SHIFT 0x0000000e
+#define UVD_CGC_GATE__UDEC_MASK 0x00000002L
+#define UVD_CGC_GATE__UDEC_MP_MASK 0x00010000L
+#define UVD_CGC_GATE__UDEC_MP__SHIFT 0x00000010
+#define UVD_CGC_GATE__UDEC_RE_MASK 0x00001000L
+#define UVD_CGC_GATE__UDEC_RE__SHIFT 0x0000000c
+#define UVD_CGC_GATE__UDEC__SHIFT 0x00000001
+#define UVD_CGC_GATE__VCPU_MASK 0x00040000L
+#define UVD_CGC_GATE__VCPU__SHIFT 0x00000012
+#define UVD_CGC_GATE__WCB_MASK 0x00020000L
+#define UVD_CGC_GATE__WCB__SHIFT 0x00000011
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN_MASK 0x00002000L
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN__SHIFT 0x0000000d
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN_MASK 0x00000001L
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN__SHIFT 0x00000000
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY_MASK 0x00f00000L
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY__SHIFT 0x00000014
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY_MASK 0x000f0000L
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY__SHIFT 0x00000010
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN_MASK 0x00001000L
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN__SHIFT 0x0000000c
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN_MASK 0x00000002L
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN__SHIFT 0x00000001
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN_MASK 0x00000004L
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN__SHIFT 0x00000002
+#define UVD_CGC_MEM_CTRL__SCPU_LS_EN_MASK 0x00000800L
+#define UVD_CGC_MEM_CTRL__SCPU_LS_EN__SHIFT 0x0000000b
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN_MASK 0x00000200L
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN__SHIFT 0x00000009
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN_MASK 0x00000020L
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN__SHIFT 0x00000005
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN_MASK 0x00000080L
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN__SHIFT 0x00000007
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN_MASK 0x00000040L
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN__SHIFT 0x00000006
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN_MASK 0x00000100L
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN__SHIFT 0x00000008
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN_MASK 0x00000010L
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN__SHIFT 0x00000004
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN_MASK 0x00000400L
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN__SHIFT 0x0000000a
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN_MASK 0x00000008L
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN__SHIFT 0x00000003
+#define UVD_CGC_STATUS__IDCT_SCLK_MASK 0x00004000L
+#define UVD_CGC_STATUS__IDCT_SCLK__SHIFT 0x0000000e
+#define UVD_CGC_STATUS__IDCT_VCLK_MASK 0x00008000L
+#define UVD_CGC_STATUS__IDCT_VCLK__SHIFT 0x0000000f
+#define UVD_CGC_STATUS__LBSI_SCLK_MASK 0x00200000L
+#define UVD_CGC_STATUS__LBSI_SCLK__SHIFT 0x00000015
+#define UVD_CGC_STATUS__LBSI_VCLK_MASK 0x00400000L
+#define UVD_CGC_STATUS__LBSI_VCLK__SHIFT 0x00000016
+#define UVD_CGC_STATUS__LMI_MC_SCLK_MASK 0x00001000L
+#define UVD_CGC_STATUS__LMI_MC_SCLK__SHIFT 0x0000000c
+#define UVD_CGC_STATUS__LMI_UMC_SCLK_MASK 0x00002000L
+#define UVD_CGC_STATUS__LMI_UMC_SCLK__SHIFT 0x0000000d
+#define UVD_CGC_STATUS__LRBBM_SCLK_MASK 0x00800000L
+#define UVD_CGC_STATUS__LRBBM_SCLK__SHIFT 0x00000017
+#define UVD_CGC_STATUS__MPC_DCLK_MASK 0x00100000L
+#define UVD_CGC_STATUS__MPC_DCLK__SHIFT 0x00000014
+#define UVD_CGC_STATUS__MPC_SCLK_MASK 0x00080000L
+#define UVD_CGC_STATUS__MPC_SCLK__SHIFT 0x00000013
+#define UVD_CGC_STATUS__MPEG2_DCLK_MASK 0x00000080L
+#define UVD_CGC_STATUS__MPEG2_DCLK__SHIFT 0x00000007
+#define UVD_CGC_STATUS__MPEG2_SCLK_MASK 0x00000040L
+#define UVD_CGC_STATUS__MPEG2_SCLK__SHIFT 0x00000006
+#define UVD_CGC_STATUS__MPEG2_VCLK_MASK 0x00000100L
+#define UVD_CGC_STATUS__MPEG2_VCLK__SHIFT 0x00000008
+#define UVD_CGC_STATUS__MPRD_DCLK_MASK 0x00020000L
+#define UVD_CGC_STATUS__MPRD_DCLK__SHIFT 0x00000011
+#define UVD_CGC_STATUS__MPRD_SCLK_MASK 0x00010000L
+#define UVD_CGC_STATUS__MPRD_SCLK__SHIFT 0x00000010
+#define UVD_CGC_STATUS__MPRD_VCLK_MASK 0x00040000L
+#define UVD_CGC_STATUS__MPRD_VCLK__SHIFT 0x00000012
+#define UVD_CGC_STATUS__RBC_SCLK_MASK 0x00000800L
+#define UVD_CGC_STATUS__RBC_SCLK__SHIFT 0x0000000b
+#define UVD_CGC_STATUS__REGS_SCLK_MASK 0x00000200L
+#define UVD_CGC_STATUS__REGS_SCLK__SHIFT 0x00000009
+#define UVD_CGC_STATUS__REGS_VCLK_MASK 0x00000400L
+#define UVD_CGC_STATUS__REGS_VCLK__SHIFT 0x0000000a
+#define UVD_CGC_STATUS__SCPU_SCLK_MASK 0x08000000L
+#define UVD_CGC_STATUS__SCPU_SCLK__SHIFT 0x0000001b
+#define UVD_CGC_STATUS__SCPU_VCLK_MASK 0x10000000L
+#define UVD_CGC_STATUS__SCPU_VCLK__SHIFT 0x0000001c
+#define UVD_CGC_STATUS__SYS_DCLK_MASK 0x00000002L
+#define UVD_CGC_STATUS__SYS_DCLK__SHIFT 0x00000001
+#define UVD_CGC_STATUS__SYS_SCLK_MASK 0x00000001L
+#define UVD_CGC_STATUS__SYS_SCLK__SHIFT 0x00000000
+#define UVD_CGC_STATUS__SYS_VCLK_MASK 0x00000004L
+#define UVD_CGC_STATUS__SYS_VCLK__SHIFT 0x00000002
+#define UVD_CGC_STATUS__UDEC_DCLK_MASK 0x00000010L
+#define UVD_CGC_STATUS__UDEC_DCLK__SHIFT 0x00000004
+#define UVD_CGC_STATUS__UDEC_SCLK_MASK 0x00000008L
+#define UVD_CGC_STATUS__UDEC_SCLK__SHIFT 0x00000003
+#define UVD_CGC_STATUS__UDEC_VCLK_MASK 0x00000020L
+#define UVD_CGC_STATUS__UDEC_VCLK__SHIFT 0x00000005
+#define UVD_CGC_STATUS__VCPU_SCLK_MASK 0x02000000L
+#define UVD_CGC_STATUS__VCPU_SCLK__SHIFT 0x00000019
+#define UVD_CGC_STATUS__VCPU_VCLK_MASK 0x04000000L
+#define UVD_CGC_STATUS__VCPU_VCLK__SHIFT 0x0000001a
+#define UVD_CGC_STATUS__WCB_SCLK_MASK 0x01000000L
+#define UVD_CGC_STATUS__WCB_SCLK__SHIFT 0x00000018
+#define UVD_CGC_UDEC_STATUS__CM_DCLK_MASK 0x00000010L
+#define UVD_CGC_UDEC_STATUS__CM_DCLK__SHIFT 0x00000004
+#define UVD_CGC_UDEC_STATUS__CM_SCLK_MASK 0x00000008L
+#define UVD_CGC_UDEC_STATUS__CM_SCLK__SHIFT 0x00000003
+#define UVD_CGC_UDEC_STATUS__CM_VCLK_MASK 0x00000020L
+#define UVD_CGC_UDEC_STATUS__CM_VCLK__SHIFT 0x00000005
+#define UVD_CGC_UDEC_STATUS__DB_DCLK_MASK 0x00000400L
+#define UVD_CGC_UDEC_STATUS__DB_DCLK__SHIFT 0x0000000a
+#define UVD_CGC_UDEC_STATUS__DB_SCLK_MASK 0x00000200L
+#define UVD_CGC_UDEC_STATUS__DB_SCLK__SHIFT 0x00000009
+#define UVD_CGC_UDEC_STATUS__DB_VCLK_MASK 0x00000800L
+#define UVD_CGC_UDEC_STATUS__DB_VCLK__SHIFT 0x0000000b
+#define UVD_CGC_UDEC_STATUS__IT_DCLK_MASK 0x00000080L
+#define UVD_CGC_UDEC_STATUS__IT_DCLK__SHIFT 0x00000007
+#define UVD_CGC_UDEC_STATUS__IT_SCLK_MASK 0x00000040L
+#define UVD_CGC_UDEC_STATUS__IT_SCLK__SHIFT 0x00000006
+#define UVD_CGC_UDEC_STATUS__IT_VCLK_MASK 0x00000100L
+#define UVD_CGC_UDEC_STATUS__IT_VCLK__SHIFT 0x00000008
+#define UVD_CGC_UDEC_STATUS__MP_DCLK_MASK 0x00002000L
+#define UVD_CGC_UDEC_STATUS__MP_DCLK__SHIFT 0x0000000d
+#define UVD_CGC_UDEC_STATUS__MP_SCLK_MASK 0x00001000L
+#define UVD_CGC_UDEC_STATUS__MP_SCLK__SHIFT 0x0000000c
+#define UVD_CGC_UDEC_STATUS__MP_VCLK_MASK 0x00004000L
+#define UVD_CGC_UDEC_STATUS__MP_VCLK__SHIFT 0x0000000e
+#define UVD_CGC_UDEC_STATUS__RE_DCLK_MASK 0x00000002L
+#define UVD_CGC_UDEC_STATUS__RE_DCLK__SHIFT 0x00000001
+#define UVD_CGC_UDEC_STATUS__RE_SCLK_MASK 0x00000001L
+#define UVD_CGC_UDEC_STATUS__RE_SCLK__SHIFT 0x00000000
+#define UVD_CGC_UDEC_STATUS__RE_VCLK_MASK 0x00000004L
+#define UVD_CGC_UDEC_STATUS__RE_VCLK__SHIFT 0x00000002
+#define UVD_CONTEXT_ID__CONTEXT_ID_MASK 0xffffffffL
+#define UVD_CONTEXT_ID__CONTEXT_ID__SHIFT 0x00000000
+#define UVD_CTX_DATA__DATA_MASK 0xffffffffL
+#define UVD_CTX_DATA__DATA__SHIFT 0x00000000
+#define UVD_CTX_INDEX__INDEX_MASK 0x000001ffL
+#define UVD_CTX_INDEX__INDEX__SHIFT 0x00000000
+#define UVD_ENGINE_CNTL__ENGINE_START_MASK 0x00000001L
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE_MASK 0x00000002L
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE__SHIFT 0x00000001
+#define UVD_ENGINE_CNTL__ENGINE_START__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_CMD__CMD_MASK 0x7ffffffeL
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND_MASK 0x00000001L
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_CMD__CMD__SHIFT 0x00000001
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE_MASK 0x80000000L
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE__SHIFT 0x0000001f
+#define UVD_GPCOM_VCPU_DATA0__DATA0_MASK 0xffffffffL
+#define UVD_GPCOM_VCPU_DATA0__DATA0__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_DATA1__DATA1_MASK 0xffffffffL
+#define UVD_GPCOM_VCPU_DATA1__DATA1__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT2__SCPU_ADDR_EXT_MASK 0x0000000fL
+#define UVD_LMI_ADDR_EXT2__SCPU_ADDR_EXT__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT2__SCPU_NC0_ADDR_EXT_MASK 0x00000f00L
+#define UVD_LMI_ADDR_EXT2__SCPU_NC0_ADDR_EXT__SHIFT 0x00000008
+#define UVD_LMI_ADDR_EXT2__SCPU_NC1_ADDR_EXT_MASK 0x0000f000L
+#define UVD_LMI_ADDR_EXT2__SCPU_NC1_ADDR_EXT__SHIFT 0x0000000c
+#define UVD_LMI_ADDR_EXT2__SCPU_VM_ADDR_EXT_MASK 0x000000f0L
+#define UVD_LMI_ADDR_EXT2__SCPU_VM_ADDR_EXT__SHIFT 0x00000004
+#define UVD_LMI_ADDR_EXT__CM_ADDR_EXT_MASK 0x000000f0L
+#define UVD_LMI_ADDR_EXT__CM_ADDR_EXT__SHIFT 0x00000004
+#define UVD_LMI_ADDR_EXT__IT_ADDR_EXT_MASK 0x00000f00L
+#define UVD_LMI_ADDR_EXT__IT_ADDR_EXT__SHIFT 0x00000008
+#define UVD_LMI_ADDR_EXT__MP_ADDR_EXT_MASK 0x00f00000L
+#define UVD_LMI_ADDR_EXT__MP_ADDR_EXT__SHIFT 0x00000014
+#define UVD_LMI_ADDR_EXT__RE_ADDR_EXT_MASK 0x000f0000L
+#define UVD_LMI_ADDR_EXT__RE_ADDR_EXT__SHIFT 0x00000010
+#define UVD_LMI_ADDR_EXT__VCPU_ADDR_EXT_MASK 0x0000000fL
+#define UVD_LMI_ADDR_EXT__VCPU_ADDR_EXT__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT__VCPU_NC0_ADDR_EXT_MASK 0x0f000000L
+#define UVD_LMI_ADDR_EXT__VCPU_NC0_ADDR_EXT__SHIFT 0x00000018
+#define UVD_LMI_ADDR_EXT__VCPU_NC1_ADDR_EXT_MASK 0xf0000000L
+#define UVD_LMI_ADDR_EXT__VCPU_NC1_ADDR_EXT__SHIFT 0x0000001c
+#define UVD_LMI_ADDR_EXT__VCPU_VM_ADDR_EXT_MASK 0x0000f000L
+#define UVD_LMI_ADDR_EXT__VCPU_VM_ADDR_EXT__SHIFT 0x0000000c
+#define UVD_LMI_CACHE_CTRL__CM_EN_MASK 0x00000004L
+#define UVD_LMI_CACHE_CTRL__CM_EN__SHIFT 0x00000002
+#define UVD_LMI_CACHE_CTRL__CM_FLUSH_MASK 0x00000008L
+#define UVD_LMI_CACHE_CTRL__CM_FLUSH__SHIFT 0x00000003
+#define UVD_LMI_CACHE_CTRL__IT_EN_MASK 0x00000001L
+#define UVD_LMI_CACHE_CTRL__IT_EN__SHIFT 0x00000000
+#define UVD_LMI_CACHE_CTRL__IT_FLUSH_MASK 0x00000002L
+#define UVD_LMI_CACHE_CTRL__IT_FLUSH__SHIFT 0x00000001
+#define UVD_LMI_CACHE_CTRL__VCPU_EN_MASK 0x00000010L
+#define UVD_LMI_CACHE_CTRL__VCPU_EN__SHIFT 0x00000004
+#define UVD_LMI_CACHE_CTRL__VCPU_FLUSH_MASK 0x00000020L
+#define UVD_LMI_CACHE_CTRL__VCPU_FLUSH__SHIFT 0x00000005
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT_MASK 0x00000004L
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT__SHIFT 0x00000002
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS_MASK 0x00000080L
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS__SHIFT 0x00000007
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT_MASK 0x00000008L
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT__SHIFT 0x00000003
+#define UVD_LMI_CTRL2__MCIF_WR_WATERMARK_MASK 0x00000070L
+#define UVD_LMI_CTRL2__MCIF_WR_WATERMARK__SHIFT 0x00000004
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL_MASK 0x00000600L
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL__SHIFT 0x00000009
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL_MASK 0x00001800L
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL__SHIFT 0x0000000b
+#define UVD_LMI_CTRL2__SPH_DIS_MASK 0x00000001L
+#define UVD_LMI_CTRL2__SPH_DIS__SHIFT 0x00000000
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN_MASK 0x00008000L
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN__SHIFT 0x0000000f
+#define UVD_LMI_CTRL2__STALL_ARB_MASK 0x00000002L
+#define UVD_LMI_CTRL2__STALL_ARB__SHIFT 0x00000001
+#define UVD_LMI_CTRL2__STALL_ARB_UMC_MASK 0x00000100L
+#define UVD_LMI_CTRL2__STALL_ARB_UMC__SHIFT 0x00000008
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN__SHIFT 0x0000000d
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN_MASK 0x00004000L
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN__SHIFT 0x0000000e
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT_MASK 0x00000800L
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT__SHIFT 0x0000000b
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN_MASK 0x00400000L
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN__SHIFT 0x00000016
+#define UVD_LMI_CTRL__CRC_RESET_MASK 0x00004000L
+#define UVD_LMI_CTRL__CRC_RESET__SHIFT 0x0000000e
+#define UVD_LMI_CTRL__CRC_SEL_MASK 0x000f8000L
+#define UVD_LMI_CTRL__CRC_SEL__SHIFT 0x0000000f
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN__SHIFT 0x0000000d
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN_MASK 0x00800000L
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN__SHIFT 0x00000017
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN_MASK 0x01000000L
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN__SHIFT 0x00000018
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL_MASK 0x00100000L
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL__SHIFT 0x00000014
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN_MASK 0x02000000L
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN__SHIFT 0x00000019
+#define UVD_LMI_CTRL__MASK_MC_URGENT_MASK 0x00001000L
+#define UVD_LMI_CTRL__MASK_MC_URGENT__SHIFT 0x0000000c
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN_MASK 0x04000000L
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN__SHIFT 0x0000001a
+#define UVD_LMI_CTRL__REQ_MODE_MASK 0x00000200L
+#define UVD_LMI_CTRL__REQ_MODE__SHIFT 0x00000009
+#define UVD_LMI_CTRL__RFU_MASK 0xf8000000L
+#define UVD_LMI_CTRL__RFU_MASK 0xfc000000L
+#define UVD_LMI_CTRL__RFU__SHIFT 0x0000001a
+#define UVD_LMI_CTRL__RFU__SHIFT 0x0000001b
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK 0x00200000L
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN__SHIFT 0x00000015
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK 0x00000100L
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN__SHIFT 0x00000008
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_MASK 0x000000ffL
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT 0x00000000
+#define UVD_LMI_EXT40_ADDR__ADDR_MASK 0x000000ffL
+#define UVD_LMI_EXT40_ADDR__ADDR__SHIFT 0x00000000
+#define UVD_LMI_EXT40_ADDR__INDEX_MASK 0x001f0000L
+#define UVD_LMI_EXT40_ADDR__INDEX__SHIFT 0x00000010
+#define UVD_LMI_EXT40_ADDR__WRITE_ADDR_MASK 0x80000000L
+#define UVD_LMI_EXT40_ADDR__WRITE_ADDR__SHIFT 0x0000001f
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN_MASK 0x00001000L
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN__SHIFT 0x0000000c
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN_MASK 0x00002000L
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN__SHIFT 0x0000000d
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE_MASK 0x00000080L
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE__SHIFT 0x00000007
+#define UVD_LMI_STATUS__READ_CLEAN_MASK 0x00000001L
+#define UVD_LMI_STATUS__READ_CLEAN_RAW_MASK 0x00000100L
+#define UVD_LMI_STATUS__READ_CLEAN_RAW__SHIFT 0x00000008
+#define UVD_LMI_STATUS__READ_CLEAN__SHIFT 0x00000000
+#define UVD_LMI_STATUS__UMC_AVP_IDLE_MASK 0x00000800L
+#define UVD_LMI_STATUS__UMC_AVP_IDLE__SHIFT 0x0000000b
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_MASK 0x00000010L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK 0x00000200L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW__SHIFT 0x00000009
+#define UVD_LMI_STATUS__UMC_READ_CLEAN__SHIFT 0x00000004
+#define UVD_LMI_STATUS__UMC_UVD_IDLE_MASK 0x00000400L
+#define UVD_LMI_STATUS__UMC_UVD_IDLE__SHIFT 0x0000000a
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_MASK 0x00000020L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK 0x00000040L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW__SHIFT 0x00000006
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN__SHIFT 0x00000005
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK 0x00000008L
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN__SHIFT 0x00000003
+#define UVD_LMI_STATUS__WRITE_CLEAN_MASK 0x00000002L
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK 0x00000004L
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW__SHIFT 0x00000002
+#define UVD_LMI_STATUS__WRITE_CLEAN__SHIFT 0x00000001
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP_MASK 0x00000003L
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP__SHIFT 0x00000000
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP_MASK 0x0000000cL
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP__SHIFT 0x00000002
+#define UVD_LMI_SWAP_CNTL__CM_MC_SWAP_MASK 0x00000c00L
+#define UVD_LMI_SWAP_CNTL__CM_MC_SWAP__SHIFT 0x0000000a
+#define UVD_LMI_SWAP_CNTL__CSM_MC_SWAP_MASK 0x000c0000L
+#define UVD_LMI_SWAP_CNTL__CSM_MC_SWAP__SHIFT 0x00000012
+#define UVD_LMI_SWAP_CNTL__DB_R_MC_SWAP_MASK 0x0000c000L
+#define UVD_LMI_SWAP_CNTL__DB_R_MC_SWAP__SHIFT 0x0000000e
+#define UVD_LMI_SWAP_CNTL__DB_W_MC_SWAP_MASK 0x00030000L
+#define UVD_LMI_SWAP_CNTL__DBW_MC_SWAP_MASK 0x03000000L
+#define UVD_LMI_SWAP_CNTL__DB_W_MC_SWAP__SHIFT 0x00000010
+#define UVD_LMI_SWAP_CNTL__DBW_MC_SWAP__SHIFT 0x00000018
+#define UVD_LMI_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000cL
+#define UVD_LMI_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x00000002
+#define UVD_LMI_SWAP_CNTL__IT_MC_SWAP_MASK 0x00003000L
+#define UVD_LMI_SWAP_CNTL__IT_MC_SWAP__SHIFT 0x0000000c
+#define UVD_LMI_SWAP_CNTL__MP_MC_SWAP_MASK 0xc0000000L
+#define UVD_LMI_SWAP_CNTL__MP_MC_SWAP__SHIFT 0x0000001e
+#define UVD_LMI_SWAP_CNTL__MP_REF16_MC_SWAP_MASK 0x00c00000L
+#define UVD_LMI_SWAP_CNTL__MP_REF16_MC_SWAP__SHIFT 0x00000016
+#define UVD_LMI_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_LMI_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x00000000
+#define UVD_LMI_SWAP_CNTL__RB_RPTR_MC_SWAP_MASK 0x00000030L
+#define UVD_LMI_SWAP_CNTL__RB_RPTR_MC_SWAP__SHIFT 0x00000004
+#define UVD_LMI_SWAP_CNTL__RB_WR_MC_SWAP_MASK 0x0c000000L
+#define UVD_LMI_SWAP_CNTL__RB_WR_MC_SWAP__SHIFT 0x0000001a
+#define UVD_LMI_SWAP_CNTL__RE_MC_SWAP_MASK 0x30000000L
+#define UVD_LMI_SWAP_CNTL__RE_MC_SWAP__SHIFT 0x0000001c
+#define UVD_LMI_SWAP_CNTL__VCPU_R_MC_SWAP_MASK 0x000000c0L
+#define UVD_LMI_SWAP_CNTL__VCPU_R_MC_SWAP__SHIFT 0x00000006
+#define UVD_LMI_SWAP_CNTL__VCPU_W_MC_SWAP_MASK 0x00000300L
+#define UVD_LMI_SWAP_CNTL__VCPU_W_MC_SWAP__SHIFT 0x00000008
+#define UVD_MASTINT_EN__INT_OVERRUN_MASK 0x007ffff0L
+#define UVD_MASTINT_EN__INT_OVERRUN__SHIFT 0x00000004
+#define UVD_MASTINT_EN__OVERRUN_RST_MASK 0x00000001L
+#define UVD_MASTINT_EN__OVERRUN_RST__SHIFT 0x00000000
+#define UVD_MASTINT_EN__SYS_EN_MASK 0x00000004L
+#define UVD_MASTINT_EN__SYS_EN__SHIFT 0x00000002
+#define UVD_MASTINT_EN__VCPU_EN_MASK 0x00000002L
+#define UVD_MASTINT_EN__VCPU_EN__SHIFT 0x00000001
+#define UVD_MIF_CURR_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_CURR_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_CURR_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_CURR_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_CURR_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_CURR_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_CURR_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_CURR_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MIF_RECON1_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_RECON1_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_RECON1_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_RECON1_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_RECON1_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_RECON1_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_RECON1_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MIF_REF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_REF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_REF_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_REF_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_REF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_REF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_REF_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_REF_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_REF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_REF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MPC_CNTL__AVE_WEIGHT_MASK 0x00030000L
+#define UVD_MPC_CNTL__AVE_WEIGHT__SHIFT 0x00000010
+#define UVD_MPC_CNTL__DBG_MUX_MASK 0x00000700L
+#define UVD_MPC_CNTL__DBG_MUX__SHIFT 0x00000008
+#define UVD_MPC_CNTL__PERF_RST_MASK 0x00000040L
+#define UVD_MPC_CNTL__PERF_RST__SHIFT 0x00000006
+#define UVD_MPC_CNTL__REPLACEMENT_MODE_MASK 0x00000038L
+#define UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT 0x00000003
+#define UVD_MPC_CNTL__URGENT_EN_MASK 0x00040000L
+#define UVD_MPC_CNTL__URGENT_EN__SHIFT 0x00000012
+#define UVD_MPC_SET_ALU__FUNCT_MASK 0x00000007L
+#define UVD_MPC_SET_ALU__FUNCT__SHIFT 0x00000000
+#define UVD_MPC_SET_ALU__OPERAND_MASK 0x00000ff0L
+#define UVD_MPC_SET_ALU__OPERAND__SHIFT 0x00000004
+#define UVD_MPC_SET_MUXA0__VARA_0_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXA0__VARA_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXA0__VARA_1_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXA0__VARA_1__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXA0__VARA_2_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXA0__VARA_2__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXA0__VARA_3_MASK 0x00fc0000L
+#define UVD_MPC_SET_MUXA0__VARA_3__SHIFT 0x00000012
+#define UVD_MPC_SET_MUXA0__VARA_4_MASK 0x3f000000L
+#define UVD_MPC_SET_MUXA0__VARA_4__SHIFT 0x00000018
+#define UVD_MPC_SET_MUXA1__VARA_5_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXA1__VARA_5__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXA1__VARA_6_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXA1__VARA_6__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXA1__VARA_7_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXA1__VARA_7__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXB0__VARB_0_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXB0__VARB_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXB0__VARB_1_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXB0__VARB_1__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXB0__VARB_2_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXB0__VARB_2__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXB0__VARB_3_MASK 0x00fc0000L
+#define UVD_MPC_SET_MUXB0__VARB_3__SHIFT 0x00000012
+#define UVD_MPC_SET_MUXB0__VARB_4_MASK 0x3f000000L
+#define UVD_MPC_SET_MUXB0__VARB_4__SHIFT 0x00000018
+#define UVD_MPC_SET_MUXB1__VARB_5_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXB1__VARB_5__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXB1__VARB_6_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXB1__VARB_6__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXB1__VARB_7_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXB1__VARB_7__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUX__SET_0_MASK 0x00000007L
+#define UVD_MPC_SET_MUX__SET_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUX__SET_1_MASK 0x00000038L
+#define UVD_MPC_SET_MUX__SET_1__SHIFT 0x00000003
+#define UVD_MPC_SET_MUX__SET_2_MASK 0x000001c0L
+#define UVD_MPC_SET_MUX__SET_2__SHIFT 0x00000006
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP_MASK 0x00000003L
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP__SHIFT 0x00000000
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP_MASK 0x00300000L
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP__SHIFT 0x00000014
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP_MASK 0x00c00000L
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP__SHIFT 0x00000016
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP_MASK 0x03000000L
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP__SHIFT 0x00000018
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP_MASK 0x0c000000L
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP__SHIFT 0x0000001a
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP_MASK 0x30000000L
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP__SHIFT 0x0000001c
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP_MASK 0xc0000000L
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP__SHIFT 0x0000001e
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP_MASK 0x0000000cL
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP__SHIFT 0x00000002
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP_MASK 0x00000030L
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP__SHIFT 0x00000004
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP_MASK 0x000000c0L
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP__SHIFT 0x00000006
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP_MASK 0x00000300L
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP__SHIFT 0x00000008
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP_MASK 0x00000c00L
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP__SHIFT 0x0000000a
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP_MASK 0x00003000L
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP__SHIFT 0x0000000c
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP_MASK 0x0000c000L
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP__SHIFT 0x0000000e
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP_MASK 0x00030000L
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP__SHIFT 0x00000010
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP_MASK 0x000c0000L
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP__SHIFT 0x00000012
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR_MASK 0x000000ffL
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR__SHIFT 0x00000000
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT_MASK 0x00000400L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT__SHIFT 0x0000000a
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P2_SELECT_MASK 0x00000800L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P2_SELECT__SHIFT 0x0000000b
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_DOWN_MASK 0x00000100L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_DOWN__SHIFT 0x00000008
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_UP_MASK 0x00000200L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_UP__SHIFT 0x00000009
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_READ_MASK 0x00002000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_READ__SHIFT 0x0000000d
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_REG_ADDR_MASK 0xf0000000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_REG_ADDR__SHIFT 0x0000001c
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_WRITE_MASK 0x00001000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_WRITE__SHIFT 0x0000000c
+#define UVD_PGFSM_READ_TILE1__UVD_PGFSM_READ_TILE1_VALUE_MASK 0x00ffffffL
+#define UVD_PGFSM_READ_TILE1__UVD_PGFSM_READ_TILE1_VALUE__SHIFT 0x00000000
+#define UVD_PGFSM_READ_TILE2__UVD_PGFSM_READ_TILE2_VALUE_MASK 0x00ffffffL
+#define UVD_PGFSM_READ_TILE2__UVD_PGFSM_READ_TILE2_VALUE__SHIFT 0x00000000
+#define UVD_POWER_STATUS__UVD_POWER_STATUS_MASK 0x00000001L
+#define UVD_POWER_STATUS__UVD_POWER_STATUS__SHIFT 0x00000000
+#define UVD_RBC_IB_BASE__IB_BASE_MASK 0xffffffc0L
+#define UVD_RBC_IB_BASE__IB_BASE__SHIFT 0x00000006
+#define UVD_RBC_IB_SIZE__IB_SIZE_MASK 0x007ffff0L
+#define UVD_RBC_IB_SIZE__IB_SIZE__SHIFT 0x00000004
+#define UVD_RBC_RB_BASE__RB_BASE_MASK 0xffffffc0L
+#define UVD_RBC_RB_BASE__RB_BASE__SHIFT 0x00000006
+#define UVD_RBC_RB_CNTL__RB_BLKSZ_MASK 0x00001f00L
+#define UVD_RBC_RB_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define UVD_RBC_RB_CNTL__RB_BUFSZ_MASK 0x0000001fL
+#define UVD_RBC_RB_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK 0x00010000L
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x00000010
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE_MASK 0x01000000L
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE__SHIFT 0x00000018
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x10000000L
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x0000001c
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN_MASK 0x00100000L
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN__SHIFT 0x00000014
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xffffffffL
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000000
+#define UVD_RBC_RB_RPTR__RB_RPTR_MASK 0x007ffff0L
+#define UVD_RBC_RB_RPTR__RB_RPTR__SHIFT 0x00000004
+#define UVD_RBC_RB_WPTR__RB_WPTR_MASK 0x007ffff0L
+#define UVD_RBC_RB_WPTR__RB_WPTR__SHIFT 0x00000004
+#define UVD_SEMA_ADDR_HIGH__ADDR_42_23_MASK 0x000fffffL
+#define UVD_SEMA_ADDR_HIGH__ADDR_42_23__SHIFT 0x00000000
+#define UVD_SEMA_ADDR_LOW__ADDR_22_3_MASK 0x000fffffL
+#define UVD_SEMA_ADDR_LOW__ADDR_22_3__SHIFT 0x00000000
+#define UVD_SEMA_CMD__MODE_MASK 0x00000040L
+#define UVD_SEMA_CMD__MODE__SHIFT 0x00000006
+#define UVD_SEMA_CMD__REQ_CMD_MASK 0x0000000fL
+#define UVD_SEMA_CMD__REQ_CMD__SHIFT 0x00000000
+#define UVD_SEMA_CMD__VMID_EN_MASK 0x00000080L
+#define UVD_SEMA_CMD__VMID_EN__SHIFT 0x00000007
+#define UVD_SEMA_CMD__VMID_MASK 0x00000f00L
+#define UVD_SEMA_CMD__VMID__SHIFT 0x00000008
+#define UVD_SEMA_CMD__WR_PHASE_MASK 0x00000030L
+#define UVD_SEMA_CMD__WR_PHASE__SHIFT 0x00000004
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS_MASK 0x00000002L
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS__SHIFT 0x00000001
+#define UVD_SEMA_CNTL__SEMAPHORE_EN_MASK 0x00000001L
+#define UVD_SEMA_CNTL__SEMAPHORE_EN__SHIFT 0x00000000
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN__SHIFT 0x00000000
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000004L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x00000002
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR_MASK 0x00000008L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR__SHIFT 0x00000003
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT_MASK 0x00000002L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT__SHIFT 0x00000001
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000001L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x00000000
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN__SHIFT 0x00000000
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN__SHIFT 0x00000000
+#define UVD_SOFT_RESET__CSM_SOFT_RESET_MASK 0x00000020L
+#define UVD_SOFT_RESET__CSM_SOFT_RESET__SHIFT 0x00000005
+#define UVD_SOFT_RESET__CXW_SOFT_RESET_MASK 0x00000040L
+#define UVD_SOFT_RESET__CXW_SOFT_RESET__SHIFT 0x00000006
+#define UVD_SOFT_RESET__FWV_SOFT_RESET_MASK 0x00000200L
+#define UVD_SOFT_RESET__FWV_SOFT_RESET__SHIFT 0x00000009
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET_MASK 0x00001000L
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET__SHIFT 0x0000000c
+#define UVD_SOFT_RESET__IH_SOFT_RESET_MASK 0x00000400L
+#define UVD_SOFT_RESET__IH_SOFT_RESET__SHIFT 0x0000000a
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK 0x00000002L
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET__SHIFT 0x00000001
+#define UVD_SOFT_RESET__LCM_SOFT_RESET_MASK 0x00010000L
+#define UVD_SOFT_RESET__LCM_SOFT_RESET__SHIFT 0x00000010
+#define UVD_SOFT_RESET__LMI_SOFT_RESET_MASK 0x00000004L
+#define UVD_SOFT_RESET__LMI_SOFT_RESET__SHIFT 0x00000002
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK 0x00002000L
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET__SHIFT 0x0000000d
+#define UVD_SOFT_RESET__MIF_SOFT_RESET_MASK 0x00008000L
+#define UVD_SOFT_RESET__MIF_SOFT_RESET__SHIFT 0x0000000f
+#define UVD_SOFT_RESET__MPC_SOFT_RESET_MASK 0x00000100L
+#define UVD_SOFT_RESET__MPC_SOFT_RESET__SHIFT 0x00000008
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET_MASK 0x00000800L
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET__SHIFT 0x0000000b
+#define UVD_SOFT_RESET__RBC_SOFT_RESET_MASK 0x00000001L
+#define UVD_SOFT_RESET__RBC_SOFT_RESET__SHIFT 0x00000000
+#define UVD_SOFT_RESET__SPH_SOFT_RESET_MASK 0x00004000L
+#define UVD_SOFT_RESET__SPH_SOFT_RESET__SHIFT 0x0000000e
+#define UVD_SOFT_RESET__TAP_SOFT_RESET_MASK 0x00000080L
+#define UVD_SOFT_RESET__TAP_SOFT_RESET__SHIFT 0x00000007
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET_MASK 0x00000010L
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET__SHIFT 0x00000004
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK 0x00000008L
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET__SHIFT 0x00000003
+#define UVD_STATUS__RBC_BUSY_MASK 0x00000001L
+#define UVD_STATUS__RBC_BUSY__SHIFT 0x00000000
+#define UVD_STATUS__VCPU_REPORT_MASK 0x000000feL
+#define UVD_STATUS__VCPU_REPORT__SHIFT 0x00000001
+#define UVD_UDEC_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_UDEC_DB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_DB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_DB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_DB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_DB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_DB_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_DB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_DB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_UDEC_DBW_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_DBW_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_DBW_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_DBW_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_DBW_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_DBW_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_DBW_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2__SHIFT 0x00000000
+#define UVD_VCPU_CNTL__ABORT_REQ_MASK 0x00000100L
+#define UVD_VCPU_CNTL__ABORT_REQ__SHIFT 0x00000008
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4_MASK 0x00000010L
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4__SHIFT 0x00000004
+#define UVD_VCPU_CNTL__CABAC_MB_ACC_MASK 0x10000000L
+#define UVD_VCPU_CNTL__CABAC_MB_ACC__SHIFT 0x0000001c
+#define UVD_VCPU_CNTL__CLK_ACTIVE_MASK 0x00020000L
+#define UVD_VCPU_CNTL__CLK_ACTIVE__SHIFT 0x00000011
+#define UVD_VCPU_CNTL__CLK_EN_MASK 0x00000200L
+#define UVD_VCPU_CNTL__CLK_EN__SHIFT 0x00000009
+#define UVD_VCPU_CNTL__DBG_MUX_MASK 0x0000e000L
+#define UVD_VCPU_CNTL__DBG_MUX__SHIFT 0x0000000d
+#define UVD_VCPU_CNTL__ECPU_AM32_EN_MASK 0x20000000L
+#define UVD_VCPU_CNTL__ECPU_AM32_EN__SHIFT 0x0000001d
+#define UVD_VCPU_CNTL__IRQ_ERR_MASK 0x0000000fL
+#define UVD_VCPU_CNTL__IRQ_ERR__SHIFT 0x00000000
+#define UVD_VCPU_CNTL__JTAG_EN_MASK 0x00010000L
+#define UVD_VCPU_CNTL__JTAG_EN__SHIFT 0x00000010
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE_MASK 0x00000020L
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE__SHIFT 0x00000005
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET_MASK 0x00000040L
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET__SHIFT 0x00000006
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL_MASK 0x0ff00000L
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT 0x00000014
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET_MASK 0x00000080L
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET__SHIFT 0x00000007
+#define UVD_VCPU_CNTL__TIMEOUT_DIS_MASK 0x00040000L
+#define UVD_VCPU_CNTL__TIMEOUT_DIS__SHIFT 0x00000012
+#define UVD_VCPU_CNTL__TRCE_EN_MASK 0x00000400L
+#define UVD_VCPU_CNTL__TRCE_EN__SHIFT 0x0000000a
+#define UVD_VCPU_CNTL__TRCE_MUX_MASK 0x00001800L
+#define UVD_VCPU_CNTL__TRCE_MUX__SHIFT 0x0000000b
+#define UVD_VCPU_CNTL__WMV9_EN_MASK 0x40000000L
+#define UVD_VCPU_CNTL__WMV9_EN__SHIFT 0x0000001e
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h
new file mode 100644
index 000000000000..2176548e9203
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright (C) 2016 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 VCE_1_0_D_H
+#define VCE_1_0_D_H
+
+#define mmVCE_CLOCK_GATING_A 0x80BE
+#define mmVCE_CLOCK_GATING_B 0x80BF
+#define mmVCE_LMI_CACHE_CTRL 0x83BD
+#define mmVCE_LMI_CTRL 0x83A6
+#define mmVCE_LMI_CTRL2 0x839D
+#define mmVCE_LMI_MISC_CTRL 0x83B5
+#define mmVCE_LMI_STATUS 0x83A7
+#define mmVCE_LMI_SWAP_CNTL 0x83AD
+#define mmVCE_LMI_SWAP_CNTL1 0x83AE
+#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR 0x8397
+#define mmVCE_LMI_VM_CTRL 0x83A8
+#define mmVCE_RB_ARB_CTRL 0x809F
+#define mmVCE_RB_BASE_HI 0x8061
+#define mmVCE_RB_BASE_HI2 0x805C
+#define mmVCE_RB_BASE_LO 0x8060
+#define mmVCE_RB_BASE_LO2 0x805B
+#define mmVCE_RB_RPTR 0x8063
+#define mmVCE_RB_RPTR2 0x805E
+#define mmVCE_RB_SIZE 0x8062
+#define mmVCE_RB_SIZE2 0x805D
+#define mmVCE_RB_WPTR 0x8064
+#define mmVCE_RB_WPTR2 0x805F
+#define mmVCE_SOFT_RESET 0x8048
+#define mmVCE_STATUS 0x8001
+#define mmVCE_SYS_INT_ACK 0x8341
+#define mmVCE_SYS_INT_EN 0x8340
+#define mmVCE_SYS_INT_STATUS 0x8341
+#define mmVCE_UENC_CLOCK_GATING 0x816F
+#define mmVCE_UENC_DMA_DCLK_CTRL 0x8250
+#define mmVCE_UENC_REG_CLOCK_GATING 0x8170
+#define mmVCE_VCPU_CACHE_OFFSET0 0x8009
+#define mmVCE_VCPU_CACHE_OFFSET1 0x800B
+#define mmVCE_VCPU_CACHE_OFFSET2 0x800D
+#define mmVCE_VCPU_CACHE_SIZE0 0x800A
+#define mmVCE_VCPU_CACHE_SIZE1 0x800C
+#define mmVCE_VCPU_CACHE_SIZE2 0x800E
+#define mmVCE_VCPU_CNTL 0x8005
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h
new file mode 100644
index 000000000000..ea5b26b11cb1
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h
@@ -0,0 +1,99 @@
+/*
+ *
+ * Copyright (C) 2016 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 VCE_1_0_SH_MASK_H
+#define VCE_1_0_SH_MASK_H
+
+#define VCE_LMI_CACHE_CTRL__VCPU_EN_MASK 0x00000001L
+#define VCE_LMI_CACHE_CTRL__VCPU_EN__SHIFT 0x00000000
+#define VCE_LMI_CTRL2__STALL_ARB_UMC_MASK 0x00000100L
+#define VCE_LMI_CTRL2__STALL_ARB_UMC__SHIFT 0x00000008
+#define VCE_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK 0x00200000L
+#define VCE_LMI_CTRL__VCPU_DATA_COHERENCY_EN__SHIFT 0x00000015
+#define VCE_LMI_SWAP_CNTL1__RD_MC_CID_SWAP_MASK 0x00003ffcL
+#define VCE_LMI_SWAP_CNTL1__RD_MC_CID_SWAP__SHIFT 0x00000002
+#define VCE_LMI_SWAP_CNTL1__VCPU_R_MC_SWAP_MASK 0x00000003L
+#define VCE_LMI_SWAP_CNTL1__VCPU_R_MC_SWAP__SHIFT 0x00000000
+#define VCE_LMI_SWAP_CNTL__VCPU_W_MC_SWAP_MASK 0x00000003L
+#define VCE_LMI_SWAP_CNTL__VCPU_W_MC_SWAP__SHIFT 0x00000000
+#define VCE_LMI_SWAP_CNTL__WR_MC_CID_SWAP_MASK 0x00003ffcL
+#define VCE_LMI_SWAP_CNTL__WR_MC_CID_SWAP__SHIFT 0x00000002
+#define VCE_LMI_VCPU_CACHE_40BIT_BAR__BAR_MASK 0xffffffffL
+#define VCE_LMI_VCPU_CACHE_40BIT_BAR__BAR__SHIFT 0x00000000
+#define VCE_RB_BASE_HI2__RB_BASE_HI_MASK 0xffffffffL
+#define VCE_RB_BASE_HI2__RB_BASE_HI__SHIFT 0x00000000
+#define VCE_RB_BASE_HI__RB_BASE_HI_MASK 0xffffffffL
+#define VCE_RB_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define VCE_RB_BASE_LO2__RB_BASE_LO_MASK 0xffffffc0L
+#define VCE_RB_BASE_LO2__RB_BASE_LO__SHIFT 0x00000006
+#define VCE_RB_BASE_LO__RB_BASE_LO_MASK 0xffffffc0L
+#define VCE_RB_BASE_LO__RB_BASE_LO__SHIFT 0x00000006
+#define VCE_RB_RPTR2__RB_RPTR_MASK 0x007ffff0L
+#define VCE_RB_RPTR2__RB_RPTR__SHIFT 0x00000004
+#define VCE_RB_RPTR__RB_RPTR_MASK 0x007ffff0L
+#define VCE_RB_RPTR__RB_RPTR__SHIFT 0x00000004
+#define VCE_RB_SIZE2__RB_SIZE_MASK 0x007ffff0L
+#define VCE_RB_SIZE2__RB_SIZE__SHIFT 0x00000004
+#define VCE_RB_SIZE__RB_SIZE_MASK 0x007ffff0L
+#define VCE_RB_SIZE__RB_SIZE__SHIFT 0x00000004
+#define VCE_RB_WPTR2__RB_WPTR_MASK 0x007ffff0L
+#define VCE_RB_WPTR2__RB_WPTR__SHIFT 0x00000004
+#define VCE_RB_WPTR__RB_WPTR_MASK 0x007ffff0L
+#define VCE_RB_WPTR__RB_WPTR__SHIFT 0x00000004
+#define VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK 0x00000001L
+#define VCE_SOFT_RESET__ECPU_SOFT_RESET__SHIFT 0x00000000
+#define VCE_STATUS__JOB_BUSY_MASK 0x00000001L
+#define VCE_STATUS__JOB_BUSY__SHIFT 0x00000000
+#define VCE_STATUS__UENC_BUSY_MASK 0x00000100L
+#define VCE_STATUS__UENC_BUSY__SHIFT 0x00000008
+#define VCE_STATUS__VCPU_REPORT_MASK 0x000000feL
+#define VCE_STATUS__VCPU_REPORT__SHIFT 0x00000001
+#define VCE_SYS_INT_ACK__VCE_SYS_INT_TRAP_INTERRUPT_ACK_MASK 0x00000008L
+#define VCE_SYS_INT_ACK__VCE_SYS_INT_TRAP_INTERRUPT_ACK__SHIFT 0x00000003
+#define VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK 0x00000008L
+#define VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN__SHIFT 0x00000003
+#define VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK 0x00000008L
+#define VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT__SHIFT 0x00000003
+#define VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK 0x00000002L
+#define VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON__SHIFT 0x00000001
+#define VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK 0x00000004L
+#define VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON__SHIFT 0x00000002
+#define VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK 0x00000001L
+#define VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET0__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET0__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET1__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET1__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET2__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET2__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE0__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE0__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE1__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE1__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE2__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE2__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CNTL__CLK_EN_MASK 0x00000001L
+#define VCE_VCPU_CNTL__CLK_EN__SHIFT 0x00000000
+#define VCE_VCPU_CNTL__RBBM_SOFT_RESET_MASK 0x00040000L
+#define VCE_VCPU_CNTL__RBBM_SOFT_RESET__SHIFT 0x00000012
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h
index df7c18b6a02a..e4a1697ec1d3 100755..100644
--- a/drivers/gpu/drm/amd/include/cgs_common.h
+++ b/drivers/gpu/drm/amd/include/cgs_common.h
@@ -106,6 +106,7 @@ enum cgs_ucode_id {
CGS_UCODE_ID_CP_MEC_JT2,
CGS_UCODE_ID_GMCON_RENG,
CGS_UCODE_ID_RLC_G,
+ CGS_UCODE_ID_STORAGE,
CGS_UCODE_ID_MAXIMUM,
};
@@ -619,6 +620,8 @@ typedef int (*cgs_call_acpi_method)(struct cgs_device *cgs_device,
typedef int (*cgs_query_system_info)(struct cgs_device *cgs_device,
struct cgs_system_info *sys_info);
+typedef int (*cgs_is_virtualization_enabled_t)(void *cgs_device);
+
struct cgs_ops {
/* memory management calls (similar to KFD interface) */
cgs_gpu_mem_info_t gpu_mem_info;
@@ -670,6 +673,7 @@ struct cgs_ops {
cgs_call_acpi_method call_acpi_method;
/* get system info */
cgs_query_system_info query_system_info;
+ cgs_is_virtualization_enabled_t is_virtualization_enabled;
};
struct cgs_os_ops; /* To be define in OS-specific CGS header */
@@ -773,4 +777,6 @@ struct cgs_device
CGS_CALL(get_pci_resource, cgs_device, resource_type, size, offset, \
resource_base)
+#define cgs_is_virtualization_enabled(cgs_device) \
+ CGS_CALL(is_virtualization_enabled, cgs_device)
#endif /* _CGS_COMMON_H */
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 7174f7a68266..c81cf1412728 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -41,7 +41,7 @@
#define PP_CHECK_HW(hwmgr) \
do { \
if ((hwmgr) == NULL || (hwmgr)->hwmgr_func == NULL) \
- return -EINVAL; \
+ return 0; \
} while (0)
static int pp_early_init(void *handle)
@@ -115,6 +115,7 @@ static int pp_hw_init(void *handle)
struct pp_instance *pp_handle;
struct pp_smumgr *smumgr;
struct pp_eventmgr *eventmgr;
+ struct pp_hwmgr *hwmgr;
int ret = 0;
if (handle == NULL)
@@ -122,6 +123,7 @@ static int pp_hw_init(void *handle)
pp_handle = (struct pp_instance *)handle;
smumgr = pp_handle->smu_mgr;
+ hwmgr = pp_handle->hwmgr;
if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
smumgr->smumgr_funcs->smu_init == NULL ||
@@ -141,9 +143,11 @@ static int pp_hw_init(void *handle)
return ret;
}
- hw_init_power_state_table(pp_handle->hwmgr);
- eventmgr = pp_handle->eventmgr;
+ PP_CHECK_HW(hwmgr);
+
+ hw_init_power_state_table(hwmgr);
+ eventmgr = pp_handle->eventmgr;
if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
return -EINVAL;
@@ -243,7 +247,9 @@ static int pp_suspend(void *handle)
pp_handle = (struct pp_instance *)handle;
eventmgr = pp_handle->eventmgr;
- pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
+
+ if (eventmgr != NULL)
+ pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
return 0;
}
@@ -273,7 +279,8 @@ static int pp_resume(void *handle)
}
eventmgr = pp_handle->eventmgr;
- pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
+ if (eventmgr != NULL)
+ pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
return 0;
}
@@ -340,8 +347,7 @@ static enum amd_dpm_forced_level pp_dpm_get_performance_level(
hwmgr = ((struct pp_instance *)handle)->hwmgr;
- if (hwmgr == NULL)
- return -EINVAL;
+ PP_CHECK_HW(hwmgr);
return (((struct pp_instance *)handle)->hwmgr->dpm_level);
}
@@ -436,7 +442,8 @@ static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
}
}
-int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
+static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
+ void *input, void *output)
{
int ret = 0;
struct pp_instance *pp_handle;
@@ -447,6 +454,9 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input,
if (pp_handle == NULL)
return -EINVAL;
+ if (pp_handle->eventmgr == NULL)
+ return 0;
+
switch (event_id) {
case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
@@ -475,7 +485,7 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input,
return ret;
}
-enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
+static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
{
struct pp_hwmgr *hwmgr;
struct pp_power_state *state;
@@ -581,6 +591,23 @@ static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
}
+static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
+{
+ struct pp_hwmgr *hwmgr;
+
+ if (handle == NULL)
+ return -EINVAL;
+
+ hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+ PP_CHECK_HW(hwmgr);
+
+ if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
+ return -EINVAL;
+
+ return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
+}
+
static int pp_dpm_get_temperature(void *handle)
{
struct pp_hwmgr *hwmgr;
@@ -820,6 +847,21 @@ static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value)
return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);
}
+static struct amd_vce_state*
+pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
+{
+ struct pp_hwmgr *hwmgr;
+
+ if (handle) {
+ hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+ if (hwmgr && idx < hwmgr->num_vce_state_tables)
+ return &hwmgr->vce_states[idx];
+ }
+
+ return NULL;
+}
+
const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_temperature = pp_dpm_get_temperature,
.load_firmware = pp_dpm_load_fw,
@@ -836,6 +878,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_fan_control_mode = pp_dpm_get_fan_control_mode,
.set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
.get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
+ .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
.get_pp_num_states = pp_dpm_get_pp_num_states,
.get_pp_table = pp_dpm_get_pp_table,
.set_pp_table = pp_dpm_set_pp_table,
@@ -846,6 +889,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
.get_mclk_od = pp_dpm_get_mclk_od,
.set_mclk_od = pp_dpm_set_mclk_od,
.read_sensor = pp_dpm_read_sensor,
+ .get_vce_clock_state = pp_dpm_get_vce_clock_state,
};
static int amd_pp_instance_init(struct amd_pp_init *pp_init,
@@ -864,6 +908,13 @@ static int amd_pp_instance_init(struct amd_pp_init *pp_init,
if (ret)
goto fail_smum;
+
+ amd_pp->pp_handle = handle;
+
+ if ((amdgpu_dpm == 0)
+ || cgs_is_virtualization_enabled(pp_init->device))
+ return 0;
+
ret = hwmgr_init(pp_init, handle);
if (ret)
goto fail_hwmgr;
@@ -872,7 +923,6 @@ static int amd_pp_instance_init(struct amd_pp_init *pp_init,
if (ret)
goto fail_eventmgr;
- amd_pp->pp_handle = handle;
return 0;
fail_eventmgr:
@@ -891,12 +941,13 @@ static int amd_pp_instance_fini(void *handle)
if (instance == NULL)
return -EINVAL;
- eventmgr_fini(instance->eventmgr);
-
- hwmgr_fini(instance->hwmgr);
+ if ((amdgpu_dpm != 0)
+ && !cgs_is_virtualization_enabled(instance->smu_mgr->device)) {
+ eventmgr_fini(instance->eventmgr);
+ hwmgr_fini(instance->hwmgr);
+ }
smum_fini(instance->smu_mgr);
-
kfree(handle);
return 0;
}
@@ -953,6 +1004,10 @@ int amd_powerplay_reset(void *handle)
if (ret)
return ret;
+ if ((amdgpu_dpm == 0)
+ || cgs_is_virtualization_enabled(instance->smu_mgr->device))
+ return 0;
+
hw_init_power_state_table(instance->hwmgr);
if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
@@ -976,6 +1031,8 @@ int amd_powerplay_display_configuration_change(void *handle,
hwmgr = ((struct pp_instance *)handle)->hwmgr;
+ PP_CHECK_HW(hwmgr);
+
phm_store_dal_configuration_data(hwmgr, display_config);
return 0;
@@ -993,6 +1050,8 @@ int amd_powerplay_get_display_power_level(void *handle,
hwmgr = ((struct pp_instance *)handle)->hwmgr;
+ PP_CHECK_HW(hwmgr);
+
return phm_get_dal_power_level(hwmgr, output);
}
@@ -1010,6 +1069,8 @@ int amd_powerplay_get_current_clocks(void *handle,
hwmgr = ((struct pp_instance *)handle)->hwmgr;
+ PP_CHECK_HW(hwmgr);
+
phm_get_dal_power_level(hwmgr, &simple_clocks);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
@@ -1054,6 +1115,8 @@ int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, s
hwmgr = ((struct pp_instance *)handle)->hwmgr;
+ PP_CHECK_HW(hwmgr);
+
result = phm_get_clock_by_type(hwmgr, type, clocks);
return result;
@@ -1072,6 +1135,8 @@ int amd_powerplay_get_display_mode_validation_clocks(void *handle,
hwmgr = ((struct pp_instance *)handle)->hwmgr;
+ PP_CHECK_HW(hwmgr);
+
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
result = phm_get_max_high_clocks(hwmgr, clocks);
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
index b6f45fd01fa6..ec36c0e28388 100644
--- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
@@ -154,7 +154,7 @@ int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_
int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
{
- /* TODO */
+ phm_disable_clock_power_gatings(eventmgr->hwmgr);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
index 2028980f1ed4..b0c63c5f54c9 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
@@ -169,7 +169,7 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
if (bgate) {
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
- AMD_CG_STATE_UNGATE);
+ AMD_CG_STATE_GATE);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
@@ -182,7 +182,7 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
AMD_CG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
- AMD_PG_STATE_GATE);
+ AMD_PG_STATE_UNGATE);
cz_dpm_update_uvd_dpm(hwmgr, false);
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
index 960424913496..4b14f259a147 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
@@ -66,7 +66,7 @@ static const struct cz_power_state *cast_const_PhwCzPowerState(
return (struct cz_power_state *)hw_ps;
}
-uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
+static uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
uint32_t clock, uint32_t msg)
{
int i = 0;
@@ -1017,7 +1017,7 @@ static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input,
return 0;
}
-int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input,
+static int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input,
void *output, void *storage, int result)
{
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
@@ -1225,7 +1225,7 @@ static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
return 0;
}
-int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
+static int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
{
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
@@ -1239,7 +1239,7 @@ int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
return 0;
}
-int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+static int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
{
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
struct phm_clock_voltage_dependency_table *table =
@@ -1277,7 +1277,7 @@ int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
return 0;
}
-int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
{
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
@@ -1533,7 +1533,7 @@ static int cz_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
return result;
}
-int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
+static int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
{
return sizeof(struct cz_power_state);
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
index a6abe81bc843..71822ae73a12 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
@@ -35,7 +35,7 @@ static int phm_run_table(struct pp_hwmgr *hwmgr,
phm_table_function *function;
if (rt_table->function_list == NULL) {
- printk(KERN_INFO "[ powerplay ] this function not implement!\n");
+ pr_debug("[ powerplay ] this function not implement!\n");
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
index 0723758ed065..c355a0f51663 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
@@ -209,6 +209,19 @@ int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
return 0;
}
+int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
+{
+ PHM_FUNC_CHECK(hwmgr);
+
+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_TablelessHardwareInterface)) {
+ if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
+ return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
+ }
+ return 0;
+}
+
+
int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
index e03dcb6ea9c1..dc6700aee18f 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -80,20 +80,17 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
switch (hwmgr->chip_id) {
case CHIP_TOPAZ:
topaz_set_asic_special_caps(hwmgr);
- hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
- PP_VBI_TIME_SUPPORT_MASK |
+ hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
PP_ENABLE_GFX_CG_THRU_SMU);
hwmgr->pp_table_version = PP_TABLE_V0;
break;
case CHIP_TONGA:
tonga_set_asic_special_caps(hwmgr);
- hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
- PP_VBI_TIME_SUPPORT_MASK);
+ hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK;
break;
case CHIP_FIJI:
fiji_set_asic_special_caps(hwmgr);
- hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
- PP_VBI_TIME_SUPPORT_MASK |
+ hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
PP_ENABLE_GFX_CG_THRU_SMU);
break;
case CHIP_POLARIS11:
@@ -685,20 +682,24 @@ void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr)
int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
{
- if (amdgpu_sclk_deep_sleep_en)
+ if (amdgpu_pp_feature_mask & PP_SCLK_DEEP_SLEEP_MASK)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SclkDeepSleep);
else
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SclkDeepSleep);
- if (amdgpu_powercontainment)
+ if (amdgpu_pp_feature_mask & PP_POWER_CONTAINMENT_MASK) {
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
- else
+ phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_CAC);
+ } else {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
-
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_CAC);
+ }
hwmgr->feature_mask = amdgpu_pp_feature_mask;
return 0;
@@ -736,9 +737,6 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
PHM_PlatformCaps_TCPRamping);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
- PHM_PlatformCaps_CAC);
-
- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_RegulatorHot);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
@@ -767,8 +765,6 @@ int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface);
- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
- PHM_PlatformCaps_CAC);
return 0;
}
@@ -791,9 +787,6 @@ int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface);
- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
- PHM_PlatformCaps_CAC);
-
return 0;
}
@@ -810,8 +803,6 @@ int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
- PHM_PlatformCaps_CAC);
- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
index 1944d289f846..f5e8fda964f7 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
@@ -25,6 +25,7 @@
#include "linux/delay.h"
#include "hwmgr.h"
#include "amd_acpi.h"
+#include "pp_acpi.h"
bool acpi_atcs_functions_supported(void *device, uint32_t index)
{
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
index 4477c55a58e3..c45bd2560468 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
@@ -131,7 +131,7 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
/**
* Private Function to get the PowerPlay Table Address.
*/
-const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
+static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
{
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
@@ -1049,7 +1049,7 @@ static int check_powerplay_tables(
return 0;
}
-int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
+static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
{
int result = 0;
const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
@@ -1100,7 +1100,7 @@ int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
return result;
}
-int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
+static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v1_information *pp_table_information =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
@@ -1214,7 +1214,7 @@ static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)
}
static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i,
- struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag)
+ struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag)
{
const ATOM_Tonga_VCE_State_Record *vce_state_record;
ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
@@ -1318,7 +1318,7 @@ int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr,
hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr);
- if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) {
+ if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) {
for (j = 0; j < i; j++)
ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags);
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
index ccf7ebeaf892..a4e9cf429e62 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
@@ -1507,7 +1507,7 @@ static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
return 0;
}
-int get_number_of_vce_state_table_entries(
+static int get_number_of_vce_state_table_entries(
struct pp_hwmgr *hwmgr)
{
const ATOM_PPLIB_POWERPLAYTABLE *table =
@@ -1521,9 +1521,9 @@ int get_number_of_vce_state_table_entries(
return 0;
}
-int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
+static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
unsigned long i,
- struct pp_vce_state *vce_state,
+ struct amd_vce_state *vce_state,
void **clock_info,
unsigned long *flag)
{
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
index 6eb6db199250..a1fc4fcac1e0 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
@@ -75,7 +75,7 @@ int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_uvd_power_gating(hwmgr)) {
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
@@ -91,7 +91,7 @@ int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
+static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr->smumgr,
@@ -99,7 +99,7 @@ int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr->smumgr,
@@ -107,7 +107,7 @@ int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
+static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
{
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SamuPowerGating))
@@ -116,7 +116,7 @@ int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
{
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SamuPowerGating))
@@ -150,14 +150,20 @@ int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
+ cgs_set_powergating_state(hwmgr->device,
+ AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
smu7_update_uvd_dpm(hwmgr, true);
smu7_powerdown_uvd(hwmgr);
} else {
smu7_powerup_uvd(hwmgr);
- smu7_update_uvd_dpm(hwmgr, false);
+ cgs_set_powergating_state(hwmgr->device,
+ AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
+ smu7_update_uvd_dpm(hwmgr, false);
}
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index 08cd0bd3ebe5..a74f60a575ae 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -89,7 +89,7 @@ enum DPM_EVENT_SRC {
static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
-struct smu7_power_state *cast_phw_smu7_power_state(
+static struct smu7_power_state *cast_phw_smu7_power_state(
struct pp_hw_power_state *hw_ps)
{
PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
@@ -99,7 +99,7 @@ struct smu7_power_state *cast_phw_smu7_power_state(
return (struct smu7_power_state *)hw_ps;
}
-const struct smu7_power_state *cast_const_phw_smu7_power_state(
+static const struct smu7_power_state *cast_const_phw_smu7_power_state(
const struct pp_hw_power_state *hw_ps)
{
PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
@@ -115,7 +115,7 @@ const struct smu7_power_state *cast_const_phw_smu7_power_state(
* @param hwmgr the address of the powerplay hardware manager.
* @return always 0
*/
-int smu7_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
+static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
{
cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
@@ -124,7 +124,7 @@ int smu7_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
return 0;
}
-uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
+static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
{
uint32_t speedCntl = 0;
@@ -135,7 +135,7 @@ uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
}
-int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
+static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
{
uint32_t link_width;
@@ -155,7 +155,7 @@ int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
* @param pHwMgr the address of the powerplay hardware manager.
* @return always PP_Result_OK
*/
-int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
+static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
{
if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK)
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable);
@@ -802,7 +802,7 @@ static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
+static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -993,13 +993,6 @@ static int smu7_start_dpm(struct pp_hwmgr *hwmgr)
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
SWRST_COMMAND_1, RESETLC, 0x0);
- PP_ASSERT_WITH_CODE(
- (0 == smum_send_msg_to_smc(hwmgr->smumgr,
- PPSMC_MSG_Voltage_Cntl_Enable)),
- "Failed to enable voltage DPM during DPM Start Function!",
- return -EINVAL);
-
-
if (smu7_enable_sclk_mclk_dpm(hwmgr)) {
printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!");
return -EINVAL;
@@ -1153,7 +1146,7 @@ static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
}
-int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
+static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
data->pcie_performance_request = true;
@@ -1161,7 +1154,7 @@ int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
{
int tmp_result = 0;
int result = 0;
@@ -1352,6 +1345,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
+ struct cgs_system_info sys_info = {0};
+ int result;
data->dll_default_on = false;
data->mclk_dpm0_activity_target = 0xa;
@@ -1426,7 +1421,7 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ControlVDDCI);
- if ((hwmgr->pp_table_version != PP_TABLE_V0)
+ if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
&& (table_info->cac_dtp_table->usClockStretchAmount != 0))
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
@@ -1439,6 +1434,18 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
data->pcie_lane_performance.min = 16;
data->pcie_lane_power_saving.max = 0;
data->pcie_lane_power_saving.min = 16;
+
+ sys_info.size = sizeof(struct cgs_system_info);
+ sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
+ result = cgs_query_system_info(hwmgr->device, &sys_info);
+ if (!result) {
+ if (sys_info.value & AMD_PG_SUPPORT_UVD)
+ phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_UVDPowerGating);
+ if (sys_info.value & AMD_PG_SUPPORT_VCE)
+ phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_VCEPowerGating);
+ }
}
/**
@@ -1865,7 +1872,7 @@ static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
+static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
@@ -1994,8 +2001,9 @@ static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr)
hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
table_info->cac_dtp_table->usTargetOperatingTemp;
- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
- PHM_PlatformCaps_ODFuzzyFanControlSupport);
+ if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK)
+ phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_ODFuzzyFanControlSupport);
}
return 0;
@@ -2259,7 +2267,7 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data;
int result;
@@ -3678,14 +3686,16 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f
PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm);
}
-int smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
+static int
+smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
{
PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1;
}
-int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
+static int
+smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
{
uint32_t num_active_displays = 0;
struct cgs_display_info info = {0};
@@ -3707,7 +3717,7 @@ int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
* @param hwmgr the address of the powerplay hardware manager.
* @return always OK
*/
-int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
+static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
uint32_t num_active_displays = 0;
@@ -3757,7 +3767,7 @@ int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
+static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
{
return smu7_program_display_gap(hwmgr);
}
@@ -3781,13 +3791,14 @@ static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f
PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm);
}
-int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
+static int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
const void *thermal_interrupt_info)
{
return 0;
}
-bool smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
+static bool
+smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
bool is_update_required = false;
@@ -3816,7 +3827,9 @@ static inline bool smu7_are_power_levels_equal(const struct smu7_performance_lev
(pl1->pcie_lane == pl2->pcie_lane));
}
-int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
+static int smu7_check_states_equal(struct pp_hwmgr *hwmgr,
+ const struct pp_hw_power_state *pstate1,
+ const struct pp_hw_power_state *pstate2, bool *equal)
{
const struct smu7_power_state *psa;
const struct smu7_power_state *psb;
@@ -3849,7 +3862,7 @@ int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_sta
return 0;
}
-int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr)
+static int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -3978,7 +3991,7 @@ static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr)
return 0;
}
-int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
+static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
{
int tmp_result, result = 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
index 41b634ffa5b0..26477f0f09dc 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
@@ -603,9 +603,10 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
return 0;
}
-static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
+static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *hwmgr,
+ uint32_t target_tdp)
{
- return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
+ return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
}
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
index 3fb5e57a378b..3a883e6c601a 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
@@ -29,6 +29,8 @@
#include "amd_shared.h"
#include "cgs_common.h"
+extern int amdgpu_dpm;
+
enum amd_pp_sensors {
AMDGPU_PP_SENSOR_GFX_SCLK = 0,
AMDGPU_PP_SENSOR_VDDNB,
@@ -349,6 +351,7 @@ struct amd_powerplay_funcs {
int (*get_fan_control_mode)(void *handle);
int (*set_fan_speed_percent)(void *handle, uint32_t percent);
int (*get_fan_speed_percent)(void *handle, uint32_t *speed);
+ int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm);
int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
int (*get_pp_table)(void *handle, char **table);
int (*set_pp_table)(void *handle, const char *buf, size_t size);
@@ -359,6 +362,7 @@ struct amd_powerplay_funcs {
int (*get_mclk_od)(void *handle);
int (*set_mclk_od)(void *handle, uint32_t value);
int (*read_sensor)(void *handle, int idx, int32_t *value);
+ struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx);
};
struct amd_powerplay {
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
index d4495839c64c..26129972f686 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
@@ -334,6 +334,7 @@ struct phm_clocks {
uint32_t clock[MAX_NUM_CLOCKS];
};
+extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr);
extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr);
extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate);
extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate);
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 4f0fedd1e9d3..6cdb7cbf515e 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -38,8 +38,6 @@ struct pp_hwmgr;
struct phm_fan_speed_info;
struct pp_atomctrl_voltage_table;
-extern int amdgpu_powercontainment;
-extern int amdgpu_sclk_deep_sleep_en;
extern unsigned amdgpu_pp_feature_mask;
#define VOLTAGE_SCALE 4
@@ -85,7 +83,9 @@ enum PP_FEATURE_MASK {
PP_SMC_VOLTAGE_CONTROL_MASK = 0x40,
PP_VBI_TIME_SUPPORT_MASK = 0x80,
PP_ULV_MASK = 0x100,
- PP_ENABLE_GFX_CG_THRU_SMU = 0x200
+ PP_ENABLE_GFX_CG_THRU_SMU = 0x200,
+ PP_CLOCK_STRETCH_MASK = 0x400,
+ PP_OD_FUZZY_FAN_CONTROL_MASK = 0x800
};
enum PHM_BackEnd_Magic {
@@ -367,7 +367,7 @@ struct pp_table_func {
int (*pptable_get_vce_state_table_entry)(
struct pp_hwmgr *hwmgr,
unsigned long i,
- struct pp_vce_state *vce_state,
+ struct amd_vce_state *vce_state,
void **clock_info,
unsigned long *flag);
};
@@ -586,18 +586,6 @@ struct phm_microcode_version_info {
uint32_t NB;
};
-#define PP_MAX_VCE_LEVELS 6
-
-enum PP_VCE_LEVEL {
- PP_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */
- PP_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */
- PP_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */
- PP_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
- PP_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */
- PP_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
-};
-
-
enum PP_TABLE_VERSION {
PP_TABLE_V0 = 0,
PP_TABLE_V1,
@@ -620,7 +608,7 @@ struct pp_hwmgr {
void *hardcode_pp_table;
bool need_pp_table_upload;
- struct pp_vce_state vce_states[PP_MAX_VCE_LEVELS];
+ struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS];
uint32_t num_vce_state_tables;
enum amd_dpm_forced_level dpm_level;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h
index 9ceaed9ac52a..827860fffe78 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/power_state.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h
@@ -156,15 +156,6 @@ struct pp_power_state {
struct pp_hw_power_state hardware;
};
-
-/*Structure to hold a VCE state entry*/
-struct pp_vce_state {
- uint32_t evclk;
- uint32_t ecclk;
- uint32_t sclk;
- uint32_t mclk;
-};
-
enum PP_MMProfilingState {
PP_MMProfilingState_NA = 0,
PP_MMProfilingState_Started,
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
index 3df5de2cdab0..8fe8ba9434ff 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
@@ -21,9 +21,6 @@
*
*/
-extern bool acpi_atcs_functions_supported(void *device,
- uint32_t index);
-extern int acpi_pcie_perf_request(void *device,
- uint8_t perf_req,
- bool advertise);
-extern bool acpi_atcs_notify_pcie_device_ready(void *device);
+bool acpi_atcs_functions_supported(void *device, uint32_t index);
+int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise);
+bool acpi_atcs_notify_pcie_device_ready(void *device);
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c
index 76310ac7ef0d..6aeb1d20cc3b 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c
@@ -1958,6 +1958,12 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
int res;
uint64_t tmp64;
+ if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_MicrocodeFanControl);
+ return 0;
+ }
+
if (smu_data->smu7_data.fan_table_start == 0) {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_MicrocodeFanControl);
@@ -2049,7 +2055,7 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
return 0;
}
-int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
+static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -2125,7 +2131,7 @@ uint32_t fiji_get_offsetof(uint32_t type, uint32_t member)
return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold);
}
}
- printk("cant't get the offset of type %x member %x \n", type, member);
+ printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
return 0;
}
@@ -2150,7 +2156,7 @@ uint32_t fiji_get_mac_definition(uint32_t value)
return SMU73_MAX_LEVELS_MVDD;
}
- printk("cant't get the mac of %x \n", value);
+ printk(KERN_WARNING "can't get the mac of %x\n", value);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
index 02fe1df855a9..26eff56b4a99 100755..100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
@@ -159,7 +159,7 @@ static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr)
return result;
}
-int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
+static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
{
int i, result = -1;
uint32_t reg, data;
@@ -224,7 +224,7 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr)
return result;
}
-int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
+static int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
{
int result = 0;
uint32_t table_start;
@@ -260,7 +260,7 @@ int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
return result;
}
-int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
{
int32_t vr_config;
uint32_t table_start;
@@ -299,7 +299,7 @@ int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
}
/* Work in Progress */
-int fiji_restore_vft_table(struct pp_smumgr *smumgr)
+static int fiji_restore_vft_table(struct pp_smumgr *smumgr)
{
struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
@@ -311,7 +311,7 @@ int fiji_restore_vft_table(struct pp_smumgr *smumgr)
}
/* Work in Progress */
-int fiji_save_vft_table(struct pp_smumgr *smumgr)
+static int fiji_save_vft_table(struct pp_smumgr *smumgr)
{
struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
@@ -322,7 +322,7 @@ int fiji_save_vft_table(struct pp_smumgr *smumgr)
return -EINVAL;
}
-int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
+static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
{
struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
@@ -396,7 +396,8 @@ static int fiji_start_smu(struct pp_smumgr *smumgr)
struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
/* Only start SMC if SMC RAM is not running */
- if (!smu7_is_smc_ram_running(smumgr)) {
+ if (!(smu7_is_smc_ram_running(smumgr)
+ || cgs_is_virtualization_enabled(smumgr->device))) {
fiji_avfs_event_mgr(smumgr, false);
/* Check if SMU is running in protected mode */
@@ -443,6 +444,9 @@ static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr)
uint32_t efuse = 0;
uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1;
+ if (cgs_is_virtualization_enabled(smumgr->device))
+ return 0;
+
if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB,
mask, &efuse)) {
if (efuse)
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c
index 8c889caba420..a24971a33bfd 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c
@@ -2006,6 +2006,12 @@ int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
return 0;
+ if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_MicrocodeFanControl);
+ return 0;
+ }
+
if (0 == smu7_data->fan_table_start) {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
return 0;
@@ -2140,7 +2146,7 @@ uint32_t iceland_get_offsetof(uint32_t type, uint32_t member)
return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold);
}
}
- printk("cant't get the offset of type %x member %x \n", type, member);
+ printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
return 0;
}
@@ -2163,7 +2169,7 @@ uint32_t iceland_get_mac_definition(uint32_t value)
return SMU71_MAX_LEVELS_MVDD;
}
- printk("cant't get the mac of %x \n", value);
+ printk(KERN_WARNING "can't get the mac of %x\n", value);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c
index 71bb2f8dc157..5190e821200c 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c
@@ -1885,6 +1885,12 @@ int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
int res;
uint64_t tmp64;
+ if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_MicrocodeFanControl);
+ return 0;
+ }
+
if (smu_data->smu7_data.fan_table_start == 0) {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_MicrocodeFanControl);
@@ -2174,7 +2180,7 @@ uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member)
return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold);
}
}
- printk("cant't get the offset of type %x member %x \n", type, member);
+ printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
return 0;
}
@@ -2201,7 +2207,7 @@ uint32_t polaris10_get_mac_definition(uint32_t value)
return SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
}
- printk("cant't get the mac of %x \n", value);
+ printk(KERN_WARNING "can't get the mac of %x\n", value);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
index 5c3598ab7dae..f38a68747df0 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
@@ -118,7 +118,7 @@ static int polaris10_perform_btc(struct pp_smumgr *smumgr)
}
-int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
{
uint32_t vr_config;
uint32_t dpm_table_start;
@@ -172,7 +172,8 @@ int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
return 0;
}
-int polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT)
+static int
+polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT)
{
struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
index 6af744f42ec9..f49b5487b951 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
@@ -278,6 +278,9 @@ enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type)
case UCODE_ID_RLC_G:
result = CGS_UCODE_ID_RLC_G;
break;
+ case UCODE_ID_MEC_STORAGE:
+ result = CGS_UCODE_ID_STORAGE;
+ break;
default:
break;
}
@@ -363,12 +366,16 @@ static int smu7_populate_single_firmware_entry(struct pp_smumgr *smumgr,
&info);
if (!result) {
- entry->version = info.version;
+ entry->version = info.fw_version;
entry->id = (uint16_t)fw_type;
entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
entry->meta_data_addr_high = 0;
entry->meta_data_addr_low = 0;
+
+ /* digest need be excluded out */
+ if (cgs_is_virtualization_enabled(smumgr->device))
+ info.image_size -= 20;
entry->data_size_byte = info.image_size;
entry->num_register_entries = 0;
}
@@ -400,8 +407,14 @@ int smu7_request_smu_load_fw(struct pp_smumgr *smumgr)
0x0);
if (smumgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */
- smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_HI, smu_data->smu_buffer.mc_addr_high);
- smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_LO, smu_data->smu_buffer.mc_addr_low);
+ if (!cgs_is_virtualization_enabled(smumgr->device)) {
+ smu7_send_msg_to_smc_with_parameter(smumgr,
+ PPSMC_MSG_SMU_DRAM_ADDR_HI,
+ smu_data->smu_buffer.mc_addr_high);
+ smu7_send_msg_to_smc_with_parameter(smumgr,
+ PPSMC_MSG_SMU_DRAM_ADDR_LO,
+ smu_data->smu_buffer.mc_addr_low);
+ }
fw_to_load = UCODE_ID_RLC_G_MASK
+ UCODE_ID_SDMA0_MASK
+ UCODE_ID_SDMA1_MASK
@@ -452,6 +465,10 @@ int smu7_request_smu_load_fw(struct pp_smumgr *smumgr)
PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr,
UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
"Failed to Get Firmware Entry.", return -EINVAL);
+ if (cgs_is_virtualization_enabled(smumgr->device))
+ PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr,
+ UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
+ "Failed to Get Firmware Entry.", return -EINVAL);
smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high);
smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low);
@@ -532,7 +549,6 @@ int smu7_init(struct pp_smumgr *smumgr)
smu_data = (struct smu7_smumgr *)(smumgr->backend);
smu_data->header_buffer.data_size =
((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
- smu_data->smu_buffer.data_size = 200*4096;
/* Allocate FW image data structure and header buffer and
* send the header buffer address to SMU */
@@ -555,6 +571,10 @@ int smu7_init(struct pp_smumgr *smumgr)
(cgs_handle_t)smu_data->header_buffer.handle);
return -EINVAL);
+ if (cgs_is_virtualization_enabled(smumgr->device))
+ return 0;
+
+ smu_data->smu_buffer.data_size = 200*4096;
smu_allocate_memory(smumgr->device,
smu_data->smu_buffer.data_size,
CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
index 76352f2423ae..919be435b49c 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
@@ -28,8 +28,6 @@
#include <pp_endian.h>
#define SMC_RAM_END 0x40000
-#define mmSMC_IND_INDEX_11 0x01AC
-#define mmSMC_IND_DATA_11 0x01AD
struct smu7_buffer_entry {
uint32_t data_size;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c
index de2a24d85f48..2e1493ce1bb5 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c
@@ -2496,6 +2496,12 @@ int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
PHM_PlatformCaps_MicrocodeFanControl))
return 0;
+ if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_MicrocodeFanControl);
+ return 0;
+ }
+
if (0 == smu_data->smu7_data.fan_table_start) {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_MicrocodeFanControl);
@@ -2651,7 +2657,7 @@ uint32_t tonga_get_offsetof(uint32_t type, uint32_t member)
return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold);
}
}
- printk("cant't get the offset of type %x member %x\n", type, member);
+ printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
return 0;
}
@@ -2675,7 +2681,7 @@ uint32_t tonga_get_mac_definition(uint32_t value)
case SMU_MAX_LEVELS_MVDD:
return SMU72_MAX_LEVELS_MVDD;
}
- printk("cant't get the mac value %x\n", value);
+ printk(KERN_WARNING "can't get the mac value %x\n", value);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
index 5f9124046b9b..eff9a232e72e 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
@@ -140,7 +140,8 @@ static int tonga_start_smu(struct pp_smumgr *smumgr)
int result;
/* Only start SMC if SMC RAM is not running */
- if (!smu7_is_smc_ram_running(smumgr)) {
+ if (!(smu7_is_smc_ram_running(smumgr) ||
+ cgs_is_virtualization_enabled(smumgr->device))) {
/*Check if SMU is running in protected mode*/
if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
SMU_FIRMWARE, SMU_MODE)) {
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
index b961a1c6caf3..dbd4fd3a810b 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
@@ -17,7 +17,7 @@ TRACE_EVENT(amd_sched_job,
TP_STRUCT__entry(
__field(struct amd_sched_entity *, entity)
__field(struct amd_sched_job *, sched_job)
- __field(struct fence *, fence)
+ __field(struct dma_fence *, fence)
__field(const char *, name)
__field(u32, job_count)
__field(int, hw_job_count)
@@ -42,7 +42,7 @@ TRACE_EVENT(amd_sched_process_job,
TP_PROTO(struct amd_sched_fence *fence),
TP_ARGS(fence),
TP_STRUCT__entry(
- __field(struct fence *, fence)
+ __field(struct dma_fence *, fence)
),
TP_fast_assign(
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index ffe1f85ce300..1bf83ed113b3 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -32,7 +32,7 @@
static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity);
static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
-static void amd_sched_process_job(struct fence *f, struct fence_cb *cb);
+static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb);
/* Initialize a given run queue struct */
static void amd_sched_rq_init(struct amd_sched_rq *rq)
@@ -138,7 +138,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
return r;
atomic_set(&entity->fence_seq, 0);
- entity->fence_context = fence_context_alloc(2);
+ entity->fence_context = dma_fence_context_alloc(2);
return 0;
}
@@ -218,32 +218,32 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
kfifo_free(&entity->job_queue);
}
-static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb)
+static void amd_sched_entity_wakeup(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct amd_sched_entity *entity =
container_of(cb, struct amd_sched_entity, cb);
entity->dependency = NULL;
- fence_put(f);
+ dma_fence_put(f);
amd_sched_wakeup(entity->sched);
}
-static void amd_sched_entity_clear_dep(struct fence *f, struct fence_cb *cb)
+static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct amd_sched_entity *entity =
container_of(cb, struct amd_sched_entity, cb);
entity->dependency = NULL;
- fence_put(f);
+ dma_fence_put(f);
}
static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity)
{
struct amd_gpu_scheduler *sched = entity->sched;
- struct fence * fence = entity->dependency;
+ struct dma_fence * fence = entity->dependency;
struct amd_sched_fence *s_fence;
if (fence->context == entity->fence_context) {
/* We can ignore fences from ourself */
- fence_put(entity->dependency);
+ dma_fence_put(entity->dependency);
return false;
}
@@ -254,23 +254,23 @@ static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity)
* Fence is from the same scheduler, only need to wait for
* it to be scheduled
*/
- fence = fence_get(&s_fence->scheduled);
- fence_put(entity->dependency);
+ fence = dma_fence_get(&s_fence->scheduled);
+ dma_fence_put(entity->dependency);
entity->dependency = fence;
- if (!fence_add_callback(fence, &entity->cb,
- amd_sched_entity_clear_dep))
+ if (!dma_fence_add_callback(fence, &entity->cb,
+ amd_sched_entity_clear_dep))
return true;
/* Ignore it when it is already scheduled */
- fence_put(fence);
+ dma_fence_put(fence);
return false;
}
- if (!fence_add_callback(entity->dependency, &entity->cb,
- amd_sched_entity_wakeup))
+ if (!dma_fence_add_callback(entity->dependency, &entity->cb,
+ amd_sched_entity_wakeup))
return true;
- fence_put(entity->dependency);
+ dma_fence_put(entity->dependency);
return false;
}
@@ -351,7 +351,8 @@ static void amd_sched_job_finish(struct work_struct *work)
sched->ops->free_job(s_job);
}
-static void amd_sched_job_finish_cb(struct fence *f, struct fence_cb *cb)
+static void amd_sched_job_finish_cb(struct dma_fence *f,
+ struct dma_fence_cb *cb)
{
struct amd_sched_job *job = container_of(cb, struct amd_sched_job,
finish_cb);
@@ -385,8 +386,8 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched)
spin_lock(&sched->job_list_lock);
list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
- if (fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) {
- fence_put(s_job->s_fence->parent);
+ if (dma_fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) {
+ dma_fence_put(s_job->s_fence->parent);
s_job->s_fence->parent = NULL;
}
}
@@ -407,21 +408,21 @@ void amd_sched_job_recovery(struct amd_gpu_scheduler *sched)
list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
struct amd_sched_fence *s_fence = s_job->s_fence;
- struct fence *fence;
+ struct dma_fence *fence;
spin_unlock(&sched->job_list_lock);
fence = sched->ops->run_job(s_job);
atomic_inc(&sched->hw_rq_count);
if (fence) {
- s_fence->parent = fence_get(fence);
- r = fence_add_callback(fence, &s_fence->cb,
- amd_sched_process_job);
+ s_fence->parent = dma_fence_get(fence);
+ r = dma_fence_add_callback(fence, &s_fence->cb,
+ amd_sched_process_job);
if (r == -ENOENT)
amd_sched_process_job(fence, &s_fence->cb);
else if (r)
DRM_ERROR("fence add callback failed (%d)\n",
r);
- fence_put(fence);
+ dma_fence_put(fence);
} else {
DRM_ERROR("Failed to run job!\n");
amd_sched_process_job(NULL, &s_fence->cb);
@@ -443,8 +444,8 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
struct amd_sched_entity *entity = sched_job->s_entity;
trace_amd_sched_job(sched_job);
- fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb,
- amd_sched_job_finish_cb);
+ dma_fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb,
+ amd_sched_job_finish_cb);
wait_event(entity->sched->job_scheduled,
amd_sched_entity_in(sched_job));
}
@@ -508,7 +509,7 @@ amd_sched_select_entity(struct amd_gpu_scheduler *sched)
return entity;
}
-static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
+static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct amd_sched_fence *s_fence =
container_of(cb, struct amd_sched_fence, cb);
@@ -518,7 +519,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
amd_sched_fence_finished(s_fence);
trace_amd_sched_process_job(s_fence);
- fence_put(&s_fence->finished);
+ dma_fence_put(&s_fence->finished);
wake_up_interruptible(&sched->wake_up_worker);
}
@@ -544,7 +545,7 @@ static int amd_sched_main(void *param)
struct amd_sched_entity *entity = NULL;
struct amd_sched_fence *s_fence;
struct amd_sched_job *sched_job;
- struct fence *fence;
+ struct dma_fence *fence;
wait_event_interruptible(sched->wake_up_worker,
(!amd_sched_blocked(sched) &&
@@ -566,15 +567,15 @@ static int amd_sched_main(void *param)
fence = sched->ops->run_job(sched_job);
amd_sched_fence_scheduled(s_fence);
if (fence) {
- s_fence->parent = fence_get(fence);
- r = fence_add_callback(fence, &s_fence->cb,
- amd_sched_process_job);
+ s_fence->parent = dma_fence_get(fence);
+ r = dma_fence_add_callback(fence, &s_fence->cb,
+ amd_sched_process_job);
if (r == -ENOENT)
amd_sched_process_job(fence, &s_fence->cb);
else if (r)
DRM_ERROR("fence add callback failed (%d)\n",
r);
- fence_put(fence);
+ dma_fence_put(fence);
} else {
DRM_ERROR("Failed to run job!\n");
amd_sched_process_job(NULL, &s_fence->cb);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index 51068e6c3d9a..d8dc681bcda6 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -25,7 +25,7 @@
#define _GPU_SCHEDULER_H_
#include <linux/kfifo.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
struct amd_gpu_scheduler;
struct amd_sched_rq;
@@ -47,8 +47,8 @@ struct amd_sched_entity {
atomic_t fence_seq;
uint64_t fence_context;
- struct fence *dependency;
- struct fence_cb cb;
+ struct dma_fence *dependency;
+ struct dma_fence_cb cb;
};
/**
@@ -63,10 +63,10 @@ struct amd_sched_rq {
};
struct amd_sched_fence {
- struct fence scheduled;
- struct fence finished;
- struct fence_cb cb;
- struct fence *parent;
+ struct dma_fence scheduled;
+ struct dma_fence finished;
+ struct dma_fence_cb cb;
+ struct dma_fence *parent;
struct amd_gpu_scheduler *sched;
spinlock_t lock;
void *owner;
@@ -76,15 +76,15 @@ struct amd_sched_job {
struct amd_gpu_scheduler *sched;
struct amd_sched_entity *s_entity;
struct amd_sched_fence *s_fence;
- struct fence_cb finish_cb;
+ struct dma_fence_cb finish_cb;
struct work_struct finish_work;
struct list_head node;
struct delayed_work work_tdr;
};
-extern const struct fence_ops amd_sched_fence_ops_scheduled;
-extern const struct fence_ops amd_sched_fence_ops_finished;
-static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f)
+extern const struct dma_fence_ops amd_sched_fence_ops_scheduled;
+extern const struct dma_fence_ops amd_sched_fence_ops_finished;
+static inline struct amd_sched_fence *to_amd_sched_fence(struct dma_fence *f)
{
if (f->ops == &amd_sched_fence_ops_scheduled)
return container_of(f, struct amd_sched_fence, scheduled);
@@ -100,8 +100,8 @@ static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f)
* these functions should be implemented in driver side
*/
struct amd_sched_backend_ops {
- struct fence *(*dependency)(struct amd_sched_job *sched_job);
- struct fence *(*run_job)(struct amd_sched_job *sched_job);
+ struct dma_fence *(*dependency)(struct amd_sched_job *sched_job);
+ struct dma_fence *(*run_job)(struct amd_sched_job *sched_job);
void (*timedout_job)(struct amd_sched_job *sched_job);
void (*free_job)(struct amd_sched_job *sched_job);
};
diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c
index 88fc2d662579..33f54d0a5c4f 100644
--- a/drivers/gpu/drm/amd/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c
@@ -61,46 +61,50 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *entity,
spin_lock_init(&fence->lock);
seq = atomic_inc_return(&entity->fence_seq);
- fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled,
- &fence->lock, entity->fence_context, seq);
- fence_init(&fence->finished, &amd_sched_fence_ops_finished,
- &fence->lock, entity->fence_context + 1, seq);
+ dma_fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled,
+ &fence->lock, entity->fence_context, seq);
+ dma_fence_init(&fence->finished, &amd_sched_fence_ops_finished,
+ &fence->lock, entity->fence_context + 1, seq);
return fence;
}
void amd_sched_fence_scheduled(struct amd_sched_fence *fence)
{
- int ret = fence_signal(&fence->scheduled);
+ int ret = dma_fence_signal(&fence->scheduled);
if (!ret)
- FENCE_TRACE(&fence->scheduled, "signaled from irq context\n");
+ DMA_FENCE_TRACE(&fence->scheduled,
+ "signaled from irq context\n");
else
- FENCE_TRACE(&fence->scheduled, "was already signaled\n");
+ DMA_FENCE_TRACE(&fence->scheduled,
+ "was already signaled\n");
}
void amd_sched_fence_finished(struct amd_sched_fence *fence)
{
- int ret = fence_signal(&fence->finished);
+ int ret = dma_fence_signal(&fence->finished);
if (!ret)
- FENCE_TRACE(&fence->finished, "signaled from irq context\n");
+ DMA_FENCE_TRACE(&fence->finished,
+ "signaled from irq context\n");
else
- FENCE_TRACE(&fence->finished, "was already signaled\n");
+ DMA_FENCE_TRACE(&fence->finished,
+ "was already signaled\n");
}
-static const char *amd_sched_fence_get_driver_name(struct fence *fence)
+static const char *amd_sched_fence_get_driver_name(struct dma_fence *fence)
{
return "amd_sched";
}
-static const char *amd_sched_fence_get_timeline_name(struct fence *f)
+static const char *amd_sched_fence_get_timeline_name(struct dma_fence *f)
{
struct amd_sched_fence *fence = to_amd_sched_fence(f);
return (const char *)fence->sched->name;
}
-static bool amd_sched_fence_enable_signaling(struct fence *f)
+static bool amd_sched_fence_enable_signaling(struct dma_fence *f)
{
return true;
}
@@ -114,10 +118,10 @@ static bool amd_sched_fence_enable_signaling(struct fence *f)
*/
static void amd_sched_fence_free(struct rcu_head *rcu)
{
- struct fence *f = container_of(rcu, struct fence, rcu);
+ struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
struct amd_sched_fence *fence = to_amd_sched_fence(f);
- fence_put(fence->parent);
+ dma_fence_put(fence->parent);
kmem_cache_free(sched_fence_slab, fence);
}
@@ -129,7 +133,7 @@ static void amd_sched_fence_free(struct rcu_head *rcu)
* This function is called when the reference count becomes zero.
* It just RCU schedules freeing up the fence.
*/
-static void amd_sched_fence_release_scheduled(struct fence *f)
+static void amd_sched_fence_release_scheduled(struct dma_fence *f)
{
struct amd_sched_fence *fence = to_amd_sched_fence(f);
@@ -143,27 +147,27 @@ static void amd_sched_fence_release_scheduled(struct fence *f)
*
* Drop the extra reference from the scheduled fence to the base fence.
*/
-static void amd_sched_fence_release_finished(struct fence *f)
+static void amd_sched_fence_release_finished(struct dma_fence *f)
{
struct amd_sched_fence *fence = to_amd_sched_fence(f);
- fence_put(&fence->scheduled);
+ dma_fence_put(&fence->scheduled);
}
-const struct fence_ops amd_sched_fence_ops_scheduled = {
+const struct dma_fence_ops amd_sched_fence_ops_scheduled = {
.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,
+ .wait = dma_fence_default_wait,
.release = amd_sched_fence_release_scheduled,
};
-const struct fence_ops amd_sched_fence_ops_finished = {
+const struct dma_fence_ops amd_sched_fence_ops_finished = {
.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,
+ .wait = dma_fence_default_wait,
.release = amd_sched_fence_release_finished,
};
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
index 28e6471257d0..0b6eaa49a1db 100644
--- a/drivers/gpu/drm/arc/arcpgu_drv.c
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -65,9 +65,7 @@ static const struct file_operations arcpgu_drm_ops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c
index 2bf06d71556a..bca3a678c955 100644
--- a/drivers/gpu/drm/arc/arcpgu_sim.c
+++ b/drivers/gpu/drm/arc/arcpgu_sim.c
@@ -41,12 +41,6 @@ static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
return count;
}
-static enum drm_connector_status
-arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
@@ -61,7 +55,6 @@ arcpgu_drm_connector_helper_funcs = {
static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
- .detect = arcpgu_drm_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = arcpgu_drm_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 28341b32067f..7d4e5aa77195 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -222,14 +222,12 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
{
struct hdlcd_drm_private *hdlcd;
struct drm_gem_cma_object *gem;
- unsigned int depth, bpp;
u32 src_w, src_h, dest_w, dest_h;
dma_addr_t scanout_start;
if (!plane->state->fb)
return;
- drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
src_w = plane->state->src_w >> 16;
src_h = plane->state->src_h >> 16;
dest_w = plane->state->crtc_w;
@@ -237,7 +235,8 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
scanout_start = gem->paddr + plane->state->fb->offsets[0] +
plane->state->crtc_y * plane->state->fb->pitches[0] +
- plane->state->crtc_x * bpp / 8;
+ plane->state->crtc_x *
+ drm_format_plane_cpp(plane->state->fb->pixel_format, 0);
hdlcd = plane->dev->dev_private;
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index e138fb51e8ce..e5f4f4a6546d 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -268,9 +268,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = noop_llseek,
@@ -337,14 +335,10 @@ static int hdlcd_drm_bind(struct device *dev)
if (ret)
goto err_free;
- ret = drm_dev_register(drm, 0);
- if (ret)
- goto err_unload;
-
ret = component_bind_all(dev, drm);
if (ret) {
DRM_ERROR("Failed to bind all components\n");
- goto err_unregister;
+ goto err_unload;
}
ret = pm_runtime_set_active(dev);
@@ -371,8 +365,17 @@ static int hdlcd_drm_bind(struct device *dev)
goto err_fbdev;
}
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto err_register;
+
return 0;
+err_register:
+ if (hdlcd->fbdev) {
+ drm_fbdev_cma_fini(hdlcd->fbdev);
+ hdlcd->fbdev = NULL;
+ }
err_fbdev:
drm_kms_helper_poll_fini(drm);
drm_vblank_cleanup(drm);
@@ -380,8 +383,6 @@ err_vblank:
pm_runtime_disable(drm->dev);
err_pm_active:
component_unbind_all(dev, drm);
-err_unregister:
- drm_dev_unregister(drm);
err_unload:
drm_irq_uninstall(drm);
of_reserved_mem_device_release(drm->dev);
@@ -398,6 +399,7 @@ static void hdlcd_drm_unbind(struct device *dev)
struct drm_device *drm = dev_get_drvdata(dev);
struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ drm_dev_unregister(drm);
if (hdlcd->fbdev) {
drm_fbdev_cma_fini(hdlcd->fbdev);
hdlcd->fbdev = NULL;
@@ -411,7 +413,6 @@ static void hdlcd_drm_unbind(struct device *dev)
pm_runtime_disable(drm->dev);
of_reserved_mem_device_release(drm->dev);
drm_mode_config_cleanup(drm);
- drm_dev_unregister(drm);
drm_dev_unref(drm);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
@@ -453,7 +454,8 @@ static int hdlcd_probe(struct platform_device *pdev)
return -EAGAIN;
}
- component_match_add(&pdev->dev, &match, compare_dev, port);
+ drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
+ of_node_put(port);
return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
match);
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 9280358b8f15..32f746e31379 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm)
struct malidp_hw_device *hwdev = malidp->dev;
int ret;
+ atomic_set(&malidp->config_valid, 0);
hwdev->set_config_valid(hwdev);
/* don't wait for config_valid flag if we are in config mode */
if (hwdev->in_config_mode(hwdev))
@@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_commit_modeset_disables(drm, state);
drm_atomic_helper_commit_modeset_enables(drm, state);
- drm_atomic_helper_commit_planes(drm, state,
- DRM_PLANE_COMMIT_ACTIVE_ONLY);
+ drm_atomic_helper_commit_planes(drm, state, 0);
malidp_atomic_commit_hw_done(state);
@@ -155,6 +155,12 @@ static int malidp_init(struct drm_device *drm)
return 0;
}
+static void malidp_fini(struct drm_device *drm)
+{
+ malidp_de_planes_destroy(drm);
+ drm_mode_config_cleanup(drm);
+}
+
static int malidp_irq_init(struct platform_device *pdev)
{
int irq_de, irq_se, ret = 0;
@@ -197,9 +203,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = noop_llseek,
@@ -355,10 +359,6 @@ static int malidp_bind(struct device *dev)
if (ret < 0)
goto init_fail;
- ret = drm_dev_register(drm, 0);
- if (ret)
- goto register_fail;
-
/* Set the CRTC's port so that the encoder component can find it */
ep = of_graph_get_next_endpoint(dev->of_node, NULL);
if (!ep) {
@@ -377,6 +377,8 @@ static int malidp_bind(struct device *dev)
if (ret < 0)
goto irq_init_fail;
+ drm->irq_enabled = true;
+
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n");
@@ -395,23 +397,31 @@ static int malidp_bind(struct device *dev)
}
drm_kms_helper_poll_init(drm);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto register_fail;
+
return 0;
+register_fail:
+ if (malidp->fbdev) {
+ drm_fbdev_cma_fini(malidp->fbdev);
+ malidp->fbdev = NULL;
+ }
fbdev_fail:
drm_vblank_cleanup(drm);
vblank_fail:
malidp_se_irq_fini(drm);
malidp_de_irq_fini(drm);
+ drm->irq_enabled = false;
irq_init_fail:
component_unbind_all(dev, drm);
bind_fail:
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
port_fail:
- drm_dev_unregister(drm);
-register_fail:
- malidp_de_planes_destroy(drm);
- drm_mode_config_cleanup(drm);
+ malidp_fini(drm);
init_fail:
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
@@ -432,6 +442,7 @@ static void malidp_unbind(struct device *dev)
struct malidp_drm *malidp = drm->dev_private;
struct malidp_hw_device *hwdev = malidp->dev;
+ drm_dev_unregister(drm);
if (malidp->fbdev) {
drm_fbdev_cma_fini(malidp->fbdev);
malidp->fbdev = NULL;
@@ -443,9 +454,7 @@ static void malidp_unbind(struct device *dev)
component_unbind_all(dev, drm);
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
- drm_dev_unregister(drm);
- malidp_de_planes_destroy(drm);
- drm_mode_config_cleanup(drm);
+ malidp_fini(drm);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
clk_disable_unprepare(hwdev->mclk);
@@ -493,7 +502,9 @@ static int malidp_platform_probe(struct platform_device *pdev)
return -EAGAIN;
}
- component_match_add(&pdev->dev, &match, malidp_compare_dev, port);
+ drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
+ port);
+ of_node_put(port);
return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
match);
}
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index 271d2fb9711c..9fc8a2e405e4 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -39,6 +39,9 @@ struct malidp_plane_state {
/* size of the required rotation memory if plane is rotated */
u32 rotmem_size;
+ /* internal format ID */
+ u8 format;
+ u8 n_planes;
};
#define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index a6132f1d58c1..4bdf531f7844 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
{
u32 status, count = 100;
+ malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
while (count) {
status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -198,9 +199,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *
static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
{
- unsigned int depth;
- int bpp;
-
/* RGB888 or BGR888 can't be rotated */
if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
return -EINVAL;
@@ -210,9 +208,7 @@ static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
* worth of pixel data. Required size is then:
* size = rotated_width * (bpp / 8) * 8;
*/
- drm_fb_get_bpp_depth(fmt, &depth, &bpp);
-
- return w * bpp;
+ return w * drm_format_plane_cpp(fmt, 0) * 8;
}
static int malidp550_query_hw(struct malidp_hw_device *hwdev)
@@ -271,6 +267,7 @@ static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
{
u32 status, count = 100;
+ malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
while (count) {
status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -441,6 +438,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
},
.input_formats = malidp500_de_formats,
.n_input_formats = ARRAY_SIZE(malidp500_de_formats),
+ .bus_align_bytes = 8,
},
.query_hw = malidp500_query_hw,
.enter_config_mode = malidp500_enter_config_mode,
@@ -473,6 +471,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
},
.input_formats = malidp550_de_formats,
.n_input_formats = ARRAY_SIZE(malidp550_de_formats),
+ .bus_align_bytes = 8,
},
.query_hw = malidp550_query_hw,
.enter_config_mode = malidp550_enter_config_mode,
@@ -506,6 +505,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
},
.input_formats = malidp550_de_formats,
.n_input_formats = ARRAY_SIZE(malidp550_de_formats),
+ .bus_align_bytes = 16,
},
.query_hw = malidp650_query_hw,
.enter_config_mode = malidp550_enter_config_mode,
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 141743e9f3a6..087e1202db3d 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -88,6 +88,9 @@ struct malidp_hw_regmap {
/* list of supported input formats for each layer */
const struct malidp_input_format *input_formats;
const u8 n_input_formats;
+
+ /* pitch alignment requirement in bytes */
+ const u8 bus_align_bytes;
};
struct malidp_hw_device {
@@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm);
u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
u8 layer_id, u32 format);
+static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
+ unsigned int pitch)
+{
+ return !(pitch & (hwdev->map.bus_align_bytes - 1));
+}
+
/*
* background color components are defined as 12bits values,
* they will be shifted right when stored on hardware that
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 82c193e5e0d6..63eec8f37cfc 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -27,6 +27,10 @@
#define LAYER_H_FLIP (1 << 10)
#define LAYER_V_FLIP (1 << 11)
#define LAYER_ROT_MASK (0xf << 8)
+#define LAYER_COMP_MASK (0x3 << 12)
+#define LAYER_COMP_PIXEL (0x3 << 12)
+#define LAYER_COMP_PLANE (0x2 << 12)
+#define MALIDP_LAYER_COMPOSE 0x008
#define MALIDP_LAYER_SIZE 0x00c
#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
@@ -34,6 +38,14 @@
#define MALIDP_LAYER_OFFSET 0x014
#define MALIDP_LAYER_STRIDE 0x018
+/*
+ * This 4-entry look-up-table is used to determine the full 8-bit alpha value
+ * for formats with 1- or 2-bit alpha channels.
+ * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
+ * opacity for 2-bit formats.
+ */
+#define MALIDP_ALPHA_LUT 0xffaa5500
+
static void malidp_de_plane_destroy(struct drm_plane *plane)
{
struct malidp_plane *mp = to_malidp_plane(plane);
@@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane)
devm_kfree(plane->dev->dev, mp);
}
-struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
+static struct
+drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
{
struct malidp_plane_state *state, *m_state;
@@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
m_state = to_malidp_plane_state(plane->state);
__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
state->rotmem_size = m_state->rotmem_size;
+ state->format = m_state->format;
+ state->n_planes = m_state->n_planes;
}
return &state->base;
}
-void malidp_destroy_plane_state(struct drm_plane *plane,
- struct drm_plane_state *state)
+static void malidp_destroy_plane_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
{
struct malidp_plane_state *m_state = to_malidp_plane_state(state);
@@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane,
static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
+ .set_property = drm_atomic_helper_plane_set_property,
.destroy = malidp_de_plane_destroy,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state,
@@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct drm_plane *plane,
{
struct malidp_plane *mp = to_malidp_plane(plane);
struct malidp_plane_state *ms = to_malidp_plane_state(state);
- u8 format_id;
+ struct drm_framebuffer *fb;
+ int i;
u32 src_w, src_h;
if (!state->crtc || !state->fb)
return 0;
- format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
- state->fb->pixel_format);
- if (format_id == MALIDP_INVALID_FORMAT_ID)
+ fb = state->fb;
+
+ ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
+ fb->pixel_format);
+ if (ms->format == MALIDP_INVALID_FORMAT_ID)
return -EINVAL;
+ ms->n_planes = drm_format_num_planes(fb->pixel_format);
+ for (i = 0; i < ms->n_planes; i++) {
+ if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
+ DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
+ fb->pitches[i], i);
+ return -EINVAL;
+ }
+ }
+
src_w = state->src_w >> 16;
src_h = state->src_h >> 16;
@@ -135,17 +163,13 @@ static void malidp_de_plane_update(struct drm_plane *plane,
struct drm_gem_cma_object *obj;
struct malidp_plane *mp;
const struct malidp_hw_regmap *map;
- u8 format_id;
+ struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
u16 ptr;
- u32 format, src_w, src_h, dest_w, dest_h, val = 0;
- int num_planes, i;
+ u32 src_w, src_h, dest_w, dest_h, val;
+ int i;
mp = to_malidp_plane(plane);
-
map = &mp->hwdev->map;
- format = plane->state->fb->pixel_format;
- format_id = malidp_hw_get_format_id(map, mp->layer->id, format);
- num_planes = drm_format_num_planes(format);
/* convert src values from Q16 fixed point to integer */
src_w = plane->state->src_w >> 16;
@@ -158,9 +182,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
dest_h = plane->state->crtc_h;
}
- malidp_hw_write(mp->hwdev, format_id, mp->layer->base);
+ malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
- for (i = 0; i < num_planes; i++) {
+ for (i = 0; i < ms->n_planes; i++) {
/* calculate the offset for the layer's plane registers */
ptr = mp->layer->ptr + (i << 4);
@@ -181,9 +205,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
LAYER_V_VAL(plane->state->crtc_y),
mp->layer->base + MALIDP_LAYER_OFFSET);
- /* first clear the rotation bits in the register */
- malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK,
- mp->layer->base + MALIDP_LAYER_CONTROL);
+ /* first clear the rotation bits */
+ val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
+ val &= ~LAYER_ROT_MASK;
/* setup the rotation and axis flip bits */
if (plane->state->rotation & DRM_ROTATE_MASK)
@@ -193,11 +217,18 @@ static void malidp_de_plane_update(struct drm_plane *plane,
if (plane->state->rotation & DRM_REFLECT_Y)
val |= LAYER_H_FLIP;
+ /*
+ * always enable pixel alpha blending until we have a way to change
+ * blend modes
+ */
+ val &= ~LAYER_COMP_MASK;
+ val |= LAYER_COMP_PIXEL;
+
/* set the 'enable layer' bit */
val |= LAYER_ENABLE;
- malidp_hw_setbits(mp->hwdev, val,
- mp->layer->base + MALIDP_LAYER_CONTROL);
+ malidp_hw_write(mp->hwdev, val,
+ mp->layer->base + MALIDP_LAYER_CONTROL);
}
static void malidp_de_plane_disable(struct drm_plane *plane,
@@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_device *drm)
struct malidp_plane *plane = NULL;
enum drm_plane_type plane_type;
unsigned long crtcs = 1 << drm->mode_config.num_crtc;
+ unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
+ DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
u32 *formats;
int ret, i, j, n;
@@ -254,26 +287,18 @@ int malidp_de_planes_init(struct drm_device *drm)
if (ret < 0)
goto cleanup;
- if (!drm->mode_config.rotation_property) {
- unsigned long flags = DRM_ROTATE_0 |
- DRM_ROTATE_90 |
- DRM_ROTATE_180 |
- DRM_ROTATE_270 |
- DRM_REFLECT_X |
- DRM_REFLECT_Y;
- drm->mode_config.rotation_property =
- drm_mode_create_rotation_property(drm, flags);
- }
- /* SMART layer can't be rotated */
- if (drm->mode_config.rotation_property && (id != DE_SMART))
- drm_object_attach_property(&plane->base.base,
- drm->mode_config.rotation_property,
- DRM_ROTATE_0);
-
drm_plane_helper_add(&plane->base,
&malidp_de_plane_helper_funcs);
plane->hwdev = malidp->dev;
plane->layer = &map->layers[i];
+
+ /* Skip the features which the SMART layer doesn't have */
+ if (id == DE_SMART)
+ continue;
+
+ drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
+ malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
+ plane->layer->base + MALIDP_LAYER_COMPOSE);
}
kfree(formats);
diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index ffd673615772..a18f156c8b66 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -1,5 +1,5 @@
armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
- armada_gem.o armada_overlay.o
+ armada_gem.o armada_overlay.o armada_trace.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 a51f8cbcfe26..95cb3966b2ca 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -18,6 +18,7 @@
#include "armada_fb.h"
#include "armada_gem.h"
#include "armada_hw.h"
+#include "armada_trace.h"
struct armada_frame_work {
struct armada_plane_work work;
@@ -164,19 +165,37 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc)
}
}
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+ int x, int y)
+{
+ u32 addr = drm_fb_obj(fb)->dev_addr;
+ u32 pixel_format = fb->pixel_format;
+ int num_planes = drm_format_num_planes(pixel_format);
+ int i;
+
+ if (num_planes > 3)
+ num_planes = 3;
+
+ for (i = 0; i < num_planes; i++)
+ addrs[i] = addr + fb->offsets[i] + y * fb->pitches[i] +
+ x * drm_format_plane_cpp(pixel_format, i);
+ for (; i < 3; i++)
+ addrs[i] = 0;
+}
+
static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
int x, int y, struct armada_regs *regs, bool interlaced)
{
- struct armada_gem_object *obj = drm_fb_obj(fb);
unsigned pitch = fb->pitches[0];
- unsigned offset = y * pitch + x * fb->bits_per_pixel / 8;
- uint32_t addr_odd, addr_even;
+ u32 addrs[3], addr_odd, addr_even;
unsigned i = 0;
DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
pitch, x, y, fb->bits_per_pixel);
- addr_odd = addr_even = obj->dev_addr + offset;
+ armada_drm_plane_calc_addrs(addrs, fb, x, y);
+
+ addr_odd = addr_even = addrs[0];
if (interlaced) {
addr_even += pitch;
@@ -192,17 +211,18 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
}
static void armada_drm_plane_work_run(struct armada_crtc *dcrtc,
- struct armada_plane *plane)
+ struct drm_plane *plane)
{
- struct armada_plane_work *work = xchg(&plane->work, NULL);
+ struct armada_plane *dplane = drm_to_armada_plane(plane);
+ struct armada_plane_work *work = xchg(&dplane->work, NULL);
/* Handle any pending frame work. */
if (work) {
- work->fn(dcrtc, plane, work);
+ work->fn(dcrtc, dplane, work);
drm_crtc_vblank_put(&dcrtc->crtc);
}
- wake_up(&plane->frame_wait);
+ wake_up(&dplane->frame_wait);
}
int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
@@ -307,14 +327,12 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
{
- 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);
- armada_drm_plane_work_run(dcrtc, plane);
+ armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
}
void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
@@ -416,10 +434,8 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
spin_lock(&dcrtc->irq_lock);
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 (ovl_plane)
+ armada_drm_plane_work_run(dcrtc, ovl_plane);
if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
@@ -449,10 +465,8 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
spin_unlock(&dcrtc->irq_lock);
- if (stat & GRA_FRAME_IRQ) {
- struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
- armada_drm_plane_work_run(dcrtc, plane);
- }
+ if (stat & GRA_FRAME_IRQ)
+ armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
}
static irqreturn_t armada_drm_irq(int irq, void *arg)
@@ -466,6 +480,8 @@ static irqreturn_t armada_drm_irq(int irq, void *arg)
*/
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+ trace_armada_drm_irq(&dcrtc->crtc, stat);
+
/* Mask out those interrupts we haven't enabled */
v = stat & dcrtc->irq_ena;
@@ -531,6 +547,35 @@ static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
return val;
}
+static void armada_drm_primary_set(struct drm_crtc *crtc,
+ struct drm_plane *plane, int x, int y)
+{
+ struct armada_plane_state *state = &drm_to_armada_plane(plane)->state;
+ struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+ struct armada_regs regs[8];
+ bool interlaced = dcrtc->interlaced;
+ unsigned i;
+ u32 ctrl0;
+
+ i = armada_drm_crtc_calc_fb(plane->fb, x, y, regs, interlaced);
+
+ armada_reg_queue_set(regs, i, state->dst_yx, LCD_SPU_GRA_OVSA_HPXL_VLN);
+ armada_reg_queue_set(regs, i, state->src_hw, LCD_SPU_GRA_HPXL_VLN);
+ armada_reg_queue_set(regs, i, state->dst_hw, LCD_SPU_GZM_HPXL_VLN);
+
+ ctrl0 = state->ctrl0;
+ if (interlaced)
+ ctrl0 |= CFG_GRA_FTOGGLE;
+
+ armada_reg_queue_mod(regs, i, ctrl0, CFG_GRAFORMAT |
+ CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
+ CFG_SWAPYU | CFG_YUV2RGB) |
+ CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
+ LCD_SPU_DMA_CTRL0);
+ armada_reg_queue_end(regs, i);
+ armada_drm_crtc_update_regs(dcrtc, regs);
+}
+
/* The mode_config.mutex will be held for this call */
static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *adj,
@@ -547,9 +592,20 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
- i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb,
- x, y, regs, interlaced);
+ val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
+ val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
+ val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
+
+ if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
+ val |= CFG_PALETTE_ENA;
+
+ drm_to_armada_plane(crtc->primary)->state.ctrl0 = val;
+ drm_to_armada_plane(crtc->primary)->state.src_hw =
+ drm_to_armada_plane(crtc->primary)->state.dst_hw =
+ adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
+ drm_to_armada_plane(crtc->primary)->state.dst_yx = 0;
+ i = 0;
rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
lm = adj->crtc_htotal - adj->crtc_hsync_end;
bm = adj->crtc_vsync_start - adj->crtc_vdisplay;
@@ -625,8 +681,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE);
- armada_reg_queue_set(regs, i, val, LCD_SPU_GRA_HPXL_VLN);
- armada_reg_queue_set(regs, i, val, LCD_SPU_GZM_HPXL_VLN);
armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH);
armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH);
armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
@@ -638,22 +692,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
}
- val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
- val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
- val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
-
- if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
- val |= CFG_PALETTE_ENA;
-
- if (interlaced)
- val |= CFG_GRA_FTOGGLE;
-
- armada_reg_queue_mod(regs, i, val, CFG_GRAFORMAT |
- CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
- CFG_SWAPYU | CFG_YUV2RGB) |
- CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
- LCD_SPU_DMA_CTRL0);
-
val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0;
armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1);
@@ -662,6 +700,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
armada_reg_queue_end(regs, i);
armada_drm_crtc_update_regs(dcrtc, regs);
+
+ armada_drm_primary_set(crtc, crtc->primary, x, y);
spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
armada_drm_crtc_update(dcrtc);
@@ -1038,7 +1078,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
* interrupt, so complete it now.
*/
if (dpms_blanked(dcrtc->dpms))
- armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary));
+ armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
return 0;
}
@@ -1172,7 +1212,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
- writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 04fdd22d483b..b08043e8cc3b 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -41,10 +41,18 @@ struct armada_plane_work {
struct armada_plane_work *);
};
+struct armada_plane_state {
+ u32 src_hw;
+ u32 dst_hw;
+ u32 dst_yx;
+ u32 ctrl0;
+};
+
struct armada_plane {
struct drm_plane base;
wait_queue_head_t frame_wait;
struct armada_plane_work *work;
+ struct armada_plane_state state;
};
#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
@@ -54,6 +62,8 @@ int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
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);
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+ int x, int y);
struct armada_crtc {
struct drm_crtc crtc;
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
index d4f7ab0a30d4..90222e60d2d6 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -113,7 +113,7 @@ static int drm_add_fake_info_node(struct drm_minor *minor, struct dentry *ent,
struct drm_info_node *node;
node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
- if (node == NULL) {
+ if (!node) {
debugfs_remove(ent);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index 3b2bb6128d40..77952d559a3c 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -53,6 +53,7 @@ struct armada_variant {
extern const struct armada_variant armada510_ops;
struct armada_private {
+ struct drm_device drm;
struct work_struct fb_unref_work;
DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
struct drm_fb_helper *fbdev;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 1e0e68f608e4..07086b427c22 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -49,106 +49,6 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
spin_unlock_irqrestore(&dev->event_lock, flags);
}
-static int armada_drm_load(struct drm_device *dev, unsigned long flags)
-{
- struct armada_private *priv;
- struct resource *mem = NULL;
- int ret, n;
-
- for (n = 0; ; n++) {
- struct resource *r = platform_get_resource(dev->platformdev,
- IORESOURCE_MEM, n);
- if (!r)
- break;
-
- /* Resources above 64K are graphics memory */
- if (resource_size(r) > SZ_64K)
- mem = r;
- else
- return -EINVAL;
- }
-
- if (!mem)
- return -ENXIO;
-
- if (!devm_request_mem_region(dev->dev, mem->start,
- resource_size(mem), "armada-drm"))
- return -EBUSY;
-
- priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- DRM_ERROR("failed to allocate private\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(dev->platformdev, dev);
- dev->dev_private = priv;
-
- INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
- INIT_KFIFO(priv->fb_unref);
-
- /* Mode setting support */
- drm_mode_config_init(dev);
- dev->mode_config.min_width = 320;
- dev->mode_config.min_height = 200;
-
- /*
- * With vscale enabled, the maximum width is 1920 due to the
- * 1920 by 3 lines RAM
- */
- dev->mode_config.max_width = 1920;
- dev->mode_config.max_height = 2048;
-
- dev->mode_config.preferred_depth = 24;
- dev->mode_config.funcs = &armada_drm_mode_config_funcs;
- drm_mm_init(&priv->linear, mem->start, resource_size(mem));
- mutex_init(&priv->linear_lock);
-
- ret = component_bind_all(dev->dev, dev);
- if (ret)
- goto err_kms;
-
- ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
- if (ret)
- goto err_comp;
-
- dev->irq_enabled = true;
-
- ret = armada_fbdev_init(dev);
- if (ret)
- goto err_comp;
-
- drm_kms_helper_poll_init(dev);
-
- return 0;
-
- err_comp:
- component_unbind_all(dev->dev, dev);
- err_kms:
- drm_mode_config_cleanup(dev);
- drm_mm_takedown(&priv->linear);
- flush_work(&priv->fb_unref_work);
-
- return ret;
-}
-
-static int armada_drm_unload(struct drm_device *dev)
-{
- struct armada_private *priv = dev->dev_private;
-
- drm_kms_helper_poll_fini(dev);
- armada_fbdev_fini(dev);
-
- component_unbind_all(dev->dev, dev);
-
- drm_mode_config_cleanup(dev);
- drm_mm_takedown(&priv->linear);
- flush_work(&priv->fb_unref_work);
- dev->dev_private = NULL;
-
- return 0;
-}
-
/* These are called under the vbl_lock. */
static int armada_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
@@ -186,16 +86,10 @@ static const struct file_operations armada_drm_fops = {
};
static struct drm_driver armada_drm_driver = {
- .load = armada_drm_load,
.lastclose = armada_drm_lastclose,
- .unload = armada_drm_unload,
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = armada_drm_enable_vblank,
.disable_vblank = armada_drm_disable_vblank,
-#ifdef CONFIG_DEBUG_FS
- .debugfs_init = armada_drm_debugfs_init,
- .debugfs_cleanup = armada_drm_debugfs_cleanup,
-#endif
.gem_free_object_unlocked = armada_gem_free_object,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
@@ -218,12 +112,138 @@ static struct drm_driver armada_drm_driver = {
static int armada_drm_bind(struct device *dev)
{
- return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
+ struct armada_private *priv;
+ struct resource *mem = NULL;
+ int ret, n;
+
+ for (n = 0; ; n++) {
+ struct resource *r = platform_get_resource(to_platform_device(dev),
+ IORESOURCE_MEM, n);
+ if (!r)
+ break;
+
+ /* Resources above 64K are graphics memory */
+ if (resource_size(r) > SZ_64K)
+ mem = r;
+ else
+ return -EINVAL;
+ }
+
+ if (!mem)
+ return -ENXIO;
+
+ if (!devm_request_mem_region(dev, mem->start, resource_size(mem),
+ "armada-drm"))
+ return -EBUSY;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ /*
+ * The drm_device structure must be at the start of
+ * armada_private for drm_dev_unref() to work correctly.
+ */
+ BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0);
+
+ ret = drm_dev_init(&priv->drm, &armada_drm_driver, dev);
+ if (ret) {
+ dev_err(dev, "[" DRM_NAME ":%s] drm_dev_init failed: %d\n",
+ __func__, ret);
+ kfree(priv);
+ return ret;
+ }
+
+ priv->drm.platformdev = to_platform_device(dev);
+ priv->drm.dev_private = priv;
+
+ platform_set_drvdata(priv->drm.platformdev, &priv->drm);
+
+ INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
+ INIT_KFIFO(priv->fb_unref);
+
+ /* Mode setting support */
+ drm_mode_config_init(&priv->drm);
+ priv->drm.mode_config.min_width = 320;
+ priv->drm.mode_config.min_height = 200;
+
+ /*
+ * With vscale enabled, the maximum width is 1920 due to the
+ * 1920 by 3 lines RAM
+ */
+ priv->drm.mode_config.max_width = 1920;
+ priv->drm.mode_config.max_height = 2048;
+
+ priv->drm.mode_config.preferred_depth = 24;
+ priv->drm.mode_config.funcs = &armada_drm_mode_config_funcs;
+ drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+ mutex_init(&priv->linear_lock);
+
+ ret = component_bind_all(dev, &priv->drm);
+ if (ret)
+ goto err_kms;
+
+ ret = drm_vblank_init(&priv->drm, priv->drm.mode_config.num_crtc);
+ if (ret)
+ goto err_comp;
+
+ priv->drm.irq_enabled = true;
+
+ ret = armada_fbdev_init(&priv->drm);
+ if (ret)
+ goto err_comp;
+
+ drm_kms_helper_poll_init(&priv->drm);
+
+ ret = drm_dev_register(&priv->drm, 0);
+ if (ret)
+ goto err_poll;
+
+#ifdef CONFIG_DEBUG_FS
+ armada_drm_debugfs_init(priv->drm.primary);
+#endif
+
+ DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+ armada_drm_driver.name, armada_drm_driver.major,
+ armada_drm_driver.minor, armada_drm_driver.patchlevel,
+ armada_drm_driver.date, dev_name(dev),
+ priv->drm.primary->index);
+
+ return 0;
+
+ err_poll:
+ drm_kms_helper_poll_fini(&priv->drm);
+ armada_fbdev_fini(&priv->drm);
+ err_comp:
+ component_unbind_all(dev, &priv->drm);
+ err_kms:
+ drm_mode_config_cleanup(&priv->drm);
+ drm_mm_takedown(&priv->linear);
+ flush_work(&priv->fb_unref_work);
+ drm_dev_unref(&priv->drm);
+ return ret;
}
static void armada_drm_unbind(struct device *dev)
{
- drm_put_dev(dev_get_drvdata(dev));
+ struct drm_device *drm = dev_get_drvdata(dev);
+ struct armada_private *priv = drm->dev_private;
+
+ drm_kms_helper_poll_fini(&priv->drm);
+ armada_fbdev_fini(&priv->drm);
+
+#ifdef CONFIG_DEBUG_FS
+ armada_drm_debugfs_cleanup(priv->drm.primary);
+#endif
+ drm_dev_unregister(&priv->drm);
+
+ component_unbind_all(dev, &priv->drm);
+
+ drm_mode_config_cleanup(&priv->drm);
+ drm_mm_takedown(&priv->linear);
+ flush_work(&priv->fb_unref_work);
+
+ drm_dev_unref(&priv->drm);
}
static int compare_of(struct device *dev, void *data)
@@ -254,7 +274,7 @@ static void armada_add_endpoints(struct device *dev,
continue;
}
- component_match_add(dev, match, compare_of, remote);
+ drm_of_component_match_add(dev, match, compare_of, remote);
of_node_put(remote);
}
}
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index ca73ad8614fe..c5dc06a55883 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -19,16 +19,10 @@
static /*const*/ struct fb_ops armada_fb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
static int armada_fb_create(struct drm_fb_helper *fbh,
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 806791897304..768087ddb046 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -212,7 +212,7 @@ armada_gem_alloc_private_object(struct drm_device *dev, size_t size)
return obj;
}
-struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
+static struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
size_t size)
{
struct armada_gem_object *obj;
@@ -419,7 +419,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
}
/* Prime support */
-struct sg_table *
+static struct sg_table *
armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
@@ -594,11 +594,7 @@ int armada_gem_map_import(struct armada_gem_object *dobj)
int ret;
dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
- DMA_TO_DEVICE);
- if (!dobj->sgt) {
- DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
- return -EINVAL;
- }
+ DMA_TO_DEVICE);
if (IS_ERR(dobj->sgt)) {
ret = PTR_ERR(dobj->sgt);
dobj->sgt = NULL;
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 152b4e716269..6743615232f5 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -15,6 +15,7 @@
#include "armada_hw.h"
#include <drm/armada_drm.h>
#include "armada_ioctlP.h"
+#include "armada_trace.h"
struct armada_ovl_plane_properties {
uint32_t colorkey_yr;
@@ -32,10 +33,6 @@ struct armada_ovl_plane_properties {
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_plane_work work;
struct armada_regs regs[13];
@@ -87,6 +84,8 @@ static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
{
struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base);
+ trace_armada_ovl_plane_work(&dcrtc->crtc, &plane->base);
+
armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
armada_ovl_retire_fb(dplane, NULL);
}
@@ -120,6 +119,10 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
bool visible;
int ret;
+ trace_armada_ovl_plane_update(plane, crtc, fb,
+ crtc_x, crtc_y, crtc_w, crtc_h,
+ src_x, src_y, src_w, src_h);
+
ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip,
DRM_ROTATE_0,
0, INT_MAX, true, false, &visible);
@@ -141,22 +144,22 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
/* FIXME: overlay on an interlaced display */
/* Just updating the position/size? */
- if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
+ if (plane->fb == fb && dplane->base.state.ctrl0 == ctrl0) {
val = (drm_rect_height(&src) & 0xffff0000) |
drm_rect_width(&src) >> 16;
- dplane->src_hw = val;
+ dplane->base.state.src_hw = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
- dplane->dst_hw = val;
+ dplane->base.state.dst_hw = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
val = dest.y1 << 16 | dest.x1;
- dplane->dst_yx = val;
+ dplane->base.state.dst_yx = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
return 0;
- } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
+ } else if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) {
/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66,
dcrtc->base + LCD_SPU_SRAM_PARA1);
@@ -166,9 +169,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
armada_drm_plane_work_cancel(dcrtc, &dplane->base);
if (plane->fb != fb) {
- struct armada_gem_object *obj = drm_fb_obj(fb);
- uint32_t addr[3], pixel_format;
- int i, num_planes, hsub;
+ u32 addrs[3], pixel_format;
+ int num_planes, hsub;
/*
* Take a reference on the new framebuffer - we want to
@@ -182,6 +184,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
src_y = src.y1 >> 16;
src_x = src.x1 >> 16;
+ armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y);
+
pixel_format = fb->pixel_format;
hsub = drm_format_horz_chroma_subsampling(pixel_format);
num_planes = drm_format_num_planes(pixel_format);
@@ -194,24 +198,17 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
if (src_x & (hsub - 1) && num_planes == 1)
ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV);
- for (i = 0; i < num_planes; i++)
- addr[i] = obj->dev_addr + fb->offsets[i] +
- src_y * fb->pitches[i] +
- src_x * drm_format_plane_cpp(pixel_format, i);
- for (; i < ARRAY_SIZE(addr); i++)
- addr[i] = 0;
-
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[0],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0],
LCD_SPU_DMA_START_ADDR_Y0);
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[1],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1],
LCD_SPU_DMA_START_ADDR_U0);
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[2],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2],
LCD_SPU_DMA_START_ADDR_V0);
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[0],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0],
LCD_SPU_DMA_START_ADDR_Y1);
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[1],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1],
LCD_SPU_DMA_START_ADDR_U1);
- armada_reg_queue_set(dplane->vbl.regs, idx, addr[2],
+ armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2],
LCD_SPU_DMA_START_ADDR_V1);
val = fb->pitches[0] << 16 | fb->pitches[0];
@@ -223,28 +220,28 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
}
val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16;
- if (dplane->src_hw != val) {
- dplane->src_hw = val;
+ if (dplane->base.state.src_hw != val) {
+ dplane->base.state.src_hw = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DMA_HPXL_VLN);
}
val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
- if (dplane->dst_hw != val) {
- dplane->dst_hw = val;
+ if (dplane->base.state.dst_hw != val) {
+ dplane->base.state.dst_hw = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DZM_HPXL_VLN);
}
val = dest.y1 << 16 | dest.x1;
- if (dplane->dst_yx != val) {
- dplane->dst_yx = val;
+ if (dplane->base.state.dst_yx != val) {
+ dplane->base.state.dst_yx = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DMA_OVSA_HPXL_VLN);
}
- if (dplane->ctrl0 != ctrl0) {
- dplane->ctrl0 = ctrl0;
+ if (dplane->base.state.ctrl0 != ctrl0) {
+ dplane->base.state.ctrl0 = ctrl0;
armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,
CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE |
CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE |
@@ -275,7 +272,7 @@ static int armada_ovl_plane_disable(struct drm_plane *plane)
armada_drm_crtc_plane_disable(dcrtc, plane);
dcrtc->plane = NULL;
- dplane->ctrl0 = 0;
+ dplane->base.state.ctrl0 = 0;
fb = xchg(&dplane->old_fb, NULL);
if (fb)
diff --git a/drivers/gpu/drm/armada/armada_trace.c b/drivers/gpu/drm/armada/armada_trace.c
new file mode 100644
index 000000000000..068b336ba75f
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_trace.c
@@ -0,0 +1,4 @@
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "armada_trace.h"
+#endif
diff --git a/drivers/gpu/drm/armada/armada_trace.h b/drivers/gpu/drm/armada/armada_trace.h
new file mode 100644
index 000000000000..dc0cba70fd1a
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_trace.h
@@ -0,0 +1,66 @@
+#if !defined(ARMADA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define ARMADA_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <drm/drmP.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM armada
+#define TRACE_INCLUDE_FILE armada_trace
+
+TRACE_EVENT(armada_drm_irq,
+ TP_PROTO(struct drm_crtc *crtc, u32 stat),
+ TP_ARGS(crtc, stat),
+ TP_STRUCT__entry(
+ __field(struct drm_crtc *, crtc)
+ __field(u32, stat)
+ ),
+ TP_fast_assign(
+ __entry->crtc = crtc;
+ __entry->stat = stat;
+ ),
+ TP_printk("crtc %p stat 0x%08x",
+ __entry->crtc, __entry->stat)
+);
+
+TRACE_EVENT(armada_ovl_plane_update,
+ TP_PROTO(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),
+ TP_ARGS(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h),
+ TP_STRUCT__entry(
+ __field(struct drm_plane *, plane)
+ __field(struct drm_crtc *, crtc)
+ __field(struct drm_framebuffer *, fb)
+ ),
+ TP_fast_assign(
+ __entry->plane = plane;
+ __entry->crtc = crtc;
+ __entry->fb = fb;
+ ),
+ TP_printk("plane %p crtc %p fb %p",
+ __entry->plane, __entry->crtc, __entry->fb)
+);
+
+TRACE_EVENT(armada_ovl_plane_work,
+ TP_PROTO(struct drm_crtc *crtc, struct drm_plane *plane),
+ TP_ARGS(crtc, plane),
+ TP_STRUCT__entry(
+ __field(struct drm_plane *, plane)
+ __field(struct drm_crtc *, crtc)
+ ),
+ TP_fast_assign(
+ __entry->plane = plane;
+ __entry->crtc = crtc;
+ ),
+ TP_printk("plane %p crtc %p",
+ __entry->plane, __entry->crtc)
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index f54afd2113a9..fd7c9eec92e4 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -188,9 +188,7 @@ static const struct file_operations ast_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = ast_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.read = drm_read,
};
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index 7a86e24e2687..d6f5ec64c667 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -253,7 +253,7 @@ static int astfb_create(struct drm_fb_helper *helper,
err_release_fbi:
drm_fb_helper_release_fbi(helper);
err_free_vram:
- vfree(afbdev->sysram);
+ vfree(sysram);
return ret;
}
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 5957c3e659fe..e26c98f51eb4 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -839,12 +839,6 @@ static void ast_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
-static enum drm_connector_status
-ast_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
.mode_valid = ast_mode_valid,
.get_modes = ast_get_modes,
@@ -853,7 +847,6 @@ static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
static const struct drm_connector_funcs ast_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = ast_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = ast_connector_destroy,
};
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index 0743e65cb240..2a1368fac1d1 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -230,6 +230,7 @@ struct ttm_bo_driver ast_bo_driver = {
.ttm_tt_populate = ast_ttm_tt_populate,
.ttm_tt_unpopulate = ast_ttm_tt_unpopulate,
.init_mem_type = ast_bo_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = ast_bo_evict_flags,
.move = NULL,
.verify_access = ast_bo_verify_access,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 5f484310bee9..cbd0070265c9 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -464,7 +464,7 @@ atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit)
drm_atomic_helper_cleanup_planes(dev, old_state);
- drm_atomic_state_free(old_state);
+ drm_atomic_state_put(old_state);
/* Complete the commit, wake up any waiter. */
spin_lock(&dc->commit.wait.lock);
@@ -521,6 +521,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
/* Swap the state, this is the point of no return. */
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (async)
queue_work(dc->wq, &commit->work);
else
@@ -748,9 +749,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 9d4c030672f0..246ed1e33d8a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -393,7 +393,7 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 ||
state->base.fb->pixel_format == DRM_FORMAT_NV61) &&
- (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)))
+ drm_rotation_90_or_270(state->base.rotation))
cfg |= ATMEL_HLCDC_YUV422ROT;
atmel_hlcdc_layer_update_cfg(&plane->layer,
@@ -628,7 +628,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
/*
* Swap width and size in case of 90 or 270 degrees rotation
*/
- if (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) {
+ if (drm_rotation_90_or_270(state->base.rotation)) {
tmp = state->crtc_w;
state->crtc_w = state->crtc_h;
state->crtc_h = tmp;
@@ -883,9 +883,9 @@ static int atmel_hlcdc_plane_atomic_get_property(struct drm_plane *p,
return 0;
}
-static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
- const struct atmel_hlcdc_layer_desc *desc,
- struct atmel_hlcdc_plane_properties *props)
+static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
+ const struct atmel_hlcdc_layer_desc *desc,
+ struct atmel_hlcdc_plane_properties *props)
{
struct regmap *regmap = plane->layer.hlcdc->regmap;
@@ -902,10 +902,18 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
ATMEL_HLCDC_LAYER_GA_MASK);
}
- if (desc->layout.xstride && desc->layout.pstride)
- drm_object_attach_property(&plane->base.base,
- plane->base.dev->mode_config.rotation_property,
- DRM_ROTATE_0);
+ if (desc->layout.xstride && desc->layout.pstride) {
+ int ret;
+
+ ret = drm_plane_create_rotation_property(&plane->base,
+ DRM_ROTATE_0,
+ DRM_ROTATE_0 |
+ DRM_ROTATE_90 |
+ DRM_ROTATE_180 |
+ DRM_ROTATE_270);
+ if (ret)
+ return ret;
+ }
if (desc->layout.csc) {
/*
@@ -925,6 +933,8 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2),
0x40040890);
}
+
+ return 0;
}
static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
@@ -1036,7 +1046,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
&atmel_hlcdc_layer_plane_helper_funcs);
/* Set default property values*/
- atmel_hlcdc_plane_init_properties(plane, desc, props);
+ ret = atmel_hlcdc_plane_init_properties(plane, desc, props);
+ if (ret)
+ return ERR_PTR(ret);
return plane;
}
@@ -1054,15 +1066,6 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev)
if (!props->alpha)
return ERR_PTR(-ENOMEM);
- dev->mode_config.rotation_property =
- drm_mode_create_rotation_property(dev,
- DRM_ROTATE_0 |
- DRM_ROTATE_90 |
- DRM_ROTATE_180 |
- DRM_ROTATE_270);
- if (!dev->mode_config.rotation_property)
- return ERR_PTR(-ENOMEM);
-
return props;
}
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index 534227df23f3..15a293e65b31 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -70,9 +70,7 @@ static const struct file_operations bochs_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index e1ec498a6b6e..da790a1c302a 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -22,14 +22,10 @@ static int bochsfb_mmap(struct fb_info *info,
static struct fb_ops bochsfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
.fb_mmap = bochsfb_mmap,
};
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 0b4e5d117043..d5e63eff357b 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -216,12 +216,6 @@ bochs_connector_best_encoder(struct drm_connector *connector)
return NULL;
}
-static enum drm_connector_status bochs_connector_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
.get_modes = bochs_connector_get_modes,
.mode_valid = bochs_connector_mode_valid,
@@ -230,7 +224,6 @@ static const struct drm_connector_helper_funcs bochs_connector_connector_helper_
static const struct drm_connector_funcs bochs_connector_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = bochs_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
};
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 269cfca9ca06..099a3c688c26 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -199,6 +199,7 @@ struct ttm_bo_driver bochs_bo_driver = {
.ttm_tt_populate = ttm_pool_populate,
.ttm_tt_unpopulate = ttm_pool_unpopulate,
.init_mem_type = bochs_bo_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = bochs_bo_evict_flags,
.move = NULL,
.verify_access = bochs_bo_verify_access,
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 10e12e74fc9f..eb8688ec6f18 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -39,6 +39,15 @@ config DRM_DW_HDMI_AHB_AUDIO
Designware HDMI block. This is used in conjunction with
the i.MX6 HDMI driver.
+config DRM_DW_HDMI_I2S_AUDIO
+ tristate "Synopsis Designware I2S Audio interface"
+ depends on SND_SOC
+ depends on DRM_DW_HDMI
+ select SND_SOC_HDMI_CODEC
+ help
+ Support the I2S Audio interface which is part of the Synopsis
+ Designware HDMI block.
+
config DRM_NXP_PTN3460
tristate "NXP PTN3460 DP/LVDS bridge"
depends on OF
@@ -57,6 +66,13 @@ config DRM_PARADE_PS8622
---help---
Parade eDP-LVDS bridge chip driver.
+config DRM_SIL_SII8620
+ tristate "Silicon Image SII8620 HDMI/MHL bridge"
+ depends on OF
+ select DRM_KMS_HELPER
+ help
+ Silicon Image SII8620 HDMI/MHL bridge chip driver.
+
config DRM_SII902X
tristate "Silicon Image sii902x RGB/HDMI bridge"
depends on OF
@@ -74,6 +90,13 @@ config DRM_TOSHIBA_TC358767
---help---
Toshiba TC358767 eDP bridge chip driver.
+config DRM_TI_TFP410
+ tristate "TI TFP410 DVI/HDMI bridge"
+ depends on OF
+ select DRM_KMS_HELPER
+ ---help---
+ Texas Instruments TFP410 DVI/HDMI Transmitter driver
+
source "drivers/gpu/drm/bridge/analogix/Kconfig"
source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index cdf3a3cf765d..2e83a7855399 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -4,9 +4,12 @@ obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
+obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
+obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
diff --git a/drivers/gpu/drm/bridge/adv7511/Kconfig b/drivers/gpu/drm/bridge/adv7511/Kconfig
index d2b0499ab7d7..2fed567f9943 100644
--- a/drivers/gpu/drm/bridge/adv7511/Kconfig
+++ b/drivers/gpu/drm/bridge/adv7511/Kconfig
@@ -6,6 +6,14 @@ config DRM_I2C_ADV7511
help
Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
+config DRM_I2C_ADV7511_AUDIO
+ bool "ADV7511 HDMI Audio driver"
+ depends on DRM_I2C_ADV7511 && SND_SOC
+ select SND_SOC_HDMI_CODEC
+ help
+ Support the ADV7511 HDMI Audio interface. This is used in
+ conjunction with the AV7511 HDMI driver.
+
config DRM_I2C_ADV7533
bool "ADV7533 encoder"
depends on DRM_I2C_ADV7511
diff --git a/drivers/gpu/drm/bridge/adv7511/Makefile b/drivers/gpu/drm/bridge/adv7511/Makefile
index 9019327fff4c..5ba675534f6e 100644
--- a/drivers/gpu/drm/bridge/adv7511/Makefile
+++ b/drivers/gpu/drm/bridge/adv7511/Makefile
@@ -1,3 +1,4 @@
adv7511-y := adv7511_drv.o
+adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 161c923d6162..992d76ce02bb 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -309,6 +309,8 @@ struct adv7511 {
struct drm_display_mode curr_mode;
unsigned int f_tmds;
+ unsigned int f_audio;
+ unsigned int audio_source;
unsigned int current_edid_segment;
uint8_t edid_buf[256];
@@ -334,6 +336,7 @@ struct adv7511 {
bool use_timing_gen;
enum adv7511_type type;
+ struct platform_device *audio_pdev;
};
#ifdef CONFIG_DRM_I2C_ADV7533
@@ -389,4 +392,17 @@ static inline int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
}
#endif
+#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
+int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511);
+void adv7511_audio_exit(struct adv7511 *adv7511);
+#else /*CONFIG_DRM_I2C_ADV7511_AUDIO */
+static inline int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
+{
+ return 0;
+}
+static inline void adv7511_audio_exit(struct adv7511 *adv7511)
+{
+}
+#endif /* CONFIG_DRM_I2C_ADV7511_AUDIO */
+
#endif /* __DRM_I2C_ADV7511_H__ */
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
new file mode 100644
index 000000000000..cf92ebfe6ab7
--- /dev/null
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
@@ -0,0 +1,213 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Copyright (c) 2016, Linaro Limited
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <sound/core.h>
+#include <sound/hdmi-codec.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "adv7511.h"
+
+static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
+ unsigned int *cts, unsigned int *n)
+{
+ switch (fs) {
+ case 32000:
+ *n = 4096;
+ break;
+ case 44100:
+ *n = 6272;
+ break;
+ case 48000:
+ *n = 6144;
+ break;
+ }
+
+ *cts = ((f_tmds * *n) / (128 * fs)) * 1000;
+}
+
+static int adv7511_update_cts_n(struct adv7511 *adv7511)
+{
+ unsigned int cts = 0;
+ unsigned int n = 0;
+
+ adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
+
+ regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
+ regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
+ regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
+
+ regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
+ (cts >> 16) & 0xf);
+ regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
+ (cts >> 8) & 0xff);
+ regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
+ cts & 0xff);
+
+ return 0;
+}
+
+int adv7511_hdmi_hw_params(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
+{
+ struct adv7511 *adv7511 = dev_get_drvdata(dev);
+ unsigned int audio_source, i2s_format = 0;
+ unsigned int invert_clock;
+ unsigned int rate;
+ unsigned int len;
+
+ switch (hparms->sample_rate) {
+ case 32000:
+ rate = ADV7511_SAMPLE_FREQ_32000;
+ break;
+ case 44100:
+ rate = ADV7511_SAMPLE_FREQ_44100;
+ break;
+ case 48000:
+ rate = ADV7511_SAMPLE_FREQ_48000;
+ break;
+ case 88200:
+ rate = ADV7511_SAMPLE_FREQ_88200;
+ break;
+ case 96000:
+ rate = ADV7511_SAMPLE_FREQ_96000;
+ break;
+ case 176400:
+ rate = ADV7511_SAMPLE_FREQ_176400;
+ break;
+ case 192000:
+ rate = ADV7511_SAMPLE_FREQ_192000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (hparms->sample_width) {
+ case 16:
+ len = ADV7511_I2S_SAMPLE_LEN_16;
+ break;
+ case 18:
+ len = ADV7511_I2S_SAMPLE_LEN_18;
+ break;
+ case 20:
+ len = ADV7511_I2S_SAMPLE_LEN_20;
+ break;
+ case 24:
+ len = ADV7511_I2S_SAMPLE_LEN_24;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt->fmt) {
+ case HDMI_I2S:
+ audio_source = ADV7511_AUDIO_SOURCE_I2S;
+ i2s_format = ADV7511_I2S_FORMAT_I2S;
+ break;
+ case HDMI_RIGHT_J:
+ audio_source = ADV7511_AUDIO_SOURCE_I2S;
+ i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
+ break;
+ case HDMI_LEFT_J:
+ audio_source = ADV7511_AUDIO_SOURCE_I2S;
+ i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ invert_clock = fmt->bit_clk_inv;
+
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
+ audio_source << 4);
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
+ invert_clock << 6);
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
+ i2s_format);
+
+ adv7511->audio_source = audio_source;
+
+ adv7511->f_audio = hparms->sample_rate;
+
+ adv7511_update_cts_n(adv7511);
+
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
+ ADV7511_AUDIO_CFG3_LEN_MASK, len);
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
+ ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
+ regmap_write(adv7511->regmap, 0x73, 0x1);
+
+ return 0;
+}
+
+static int audio_startup(struct device *dev, void *data)
+{
+ struct adv7511 *adv7511 = dev_get_drvdata(dev);
+
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
+ BIT(7), 0);
+
+ /* hide Audio infoframe updates */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+ BIT(5), BIT(5));
+ /* enable N/CTS, enable Audio sample packets */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+ BIT(5), BIT(5));
+ /* enable N/CTS */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+ BIT(6), BIT(6));
+ /* not copyrighted */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
+ BIT(5), BIT(5));
+ /* enable audio infoframes */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+ BIT(3), BIT(3));
+ /* AV mute disable */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
+ BIT(7) | BIT(6), BIT(7));
+ /* use Audio infoframe updated info */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
+ BIT(5), 0);
+ return 0;
+}
+
+static void audio_shutdown(struct device *dev, void *data)
+{
+}
+
+static const struct hdmi_codec_ops adv7511_codec_ops = {
+ .hw_params = adv7511_hdmi_hw_params,
+ .audio_shutdown = audio_shutdown,
+ .audio_startup = audio_startup,
+};
+
+static struct hdmi_codec_pdata codec_data = {
+ .ops = &adv7511_codec_ops,
+ .max_i2s_channels = 2,
+ .i2s = 1,
+};
+
+int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
+{
+ adv7511->audio_pdev = platform_device_register_data(dev,
+ HDMI_CODEC_DRV_NAME,
+ PLATFORM_DEVID_AUTO,
+ &codec_data,
+ sizeof(codec_data));
+ return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
+}
+
+void adv7511_audio_exit(struct adv7511 *adv7511)
+{
+ if (adv7511->audio_pdev) {
+ platform_device_unregister(adv7511->audio_pdev);
+ adv7511->audio_pdev = NULL;
+ }
+}
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 8ed3906dd411..8dba729f6ef9 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1037,6 +1037,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
goto err_unregister_cec;
}
+ adv7511_audio_init(dev, adv7511);
+
return 0;
err_unregister_cec:
@@ -1058,6 +1060,8 @@ static int adv7511_remove(struct i2c_client *i2c)
drm_bridge_remove(&adv7511->bridge);
+ adv7511_audio_exit(adv7511);
+
i2c_unregister_device(adv7511->i2c_edid);
kfree(adv7511->edid);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index d7f7b7ce8ebe..8b210373cfa2 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -29,6 +29,7 @@ static const struct reg_sequence adv7533_cec_fixed_registers[] = {
{ 0x17, 0xd0 },
{ 0x24, 0x20 },
{ 0x57, 0x11 },
+ { 0x05, 0xc8 },
};
static const struct regmap_config adv7533_cec_regmap_config = {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 6e0447f329a2..eb9bf8786c24 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -112,7 +112,7 @@ int analogix_dp_enable_psr(struct device *dev)
struct edp_vsc_psr psr_vsc;
if (!dp->psr_support)
- return -EINVAL;
+ return 0;
/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
memset(&psr_vsc, 0, sizeof(psr_vsc));
@@ -135,7 +135,7 @@ int analogix_dp_disable_psr(struct device *dev)
struct edp_vsc_psr psr_vsc;
if (!dp->psr_support)
- return -EINVAL;
+ return 0;
/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
memset(&psr_vsc, 0, sizeof(psr_vsc));
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index cd37ac058675..303083ad28e3 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1162,5 +1162,5 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
msg->reply = DP_AUX_NATIVE_REPLY_ACK;
- return num_transferred;
+ return num_transferred > 0 ? num_transferred : -EBUSY;
}
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..e5706981c934 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
@@ -23,6 +24,7 @@ struct dumb_vga {
struct drm_connector connector;
struct i2c_adapter *ddc;
+ struct regulator *vdd;
};
static inline struct dumb_vga *
@@ -124,8 +126,30 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
return 0;
}
+static void dumb_vga_enable(struct drm_bridge *bridge)
+{
+ struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+ int ret = 0;
+
+ if (vga->vdd)
+ ret = regulator_enable(vga->vdd);
+
+ if (ret)
+ DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+}
+
+static void dumb_vga_disable(struct drm_bridge *bridge)
+{
+ struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+
+ if (vga->vdd)
+ regulator_disable(vga->vdd);
+}
+
static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
.attach = dumb_vga_attach,
+ .enable = dumb_vga_enable,
+ .disable = dumb_vga_disable,
};
static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
@@ -169,6 +193,15 @@ static int dumb_vga_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, vga);
+ vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
+ if (IS_ERR(vga->vdd)) {
+ ret = PTR_ERR(vga->vdd);
+ if (ret == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ vga->vdd = NULL;
+ dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
+ }
+
vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
if (IS_ERR(vga->ddc)) {
if (PTR_ERR(vga->ddc) == -ENODEV) {
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h
index 91f631beecc7..fd1f745c6073 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi-audio.h
+++ b/drivers/gpu/drm/bridge/dw-hdmi-audio.h
@@ -11,4 +11,11 @@ struct dw_hdmi_audio_data {
u8 *eld;
};
+struct dw_hdmi_i2s_audio_data {
+ struct dw_hdmi *hdmi;
+
+ void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
+ u8 (*read)(struct dw_hdmi *hdmi, int offset);
+};
+
#endif
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
new file mode 100644
index 000000000000..aaf287d2e91d
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
@@ -0,0 +1,141 @@
+/*
+ * dw-hdmi-i2s-audio.c
+ *
+ * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 <drm/bridge/dw_hdmi.h>
+
+#include <sound/hdmi-codec.h>
+
+#include "dw-hdmi.h"
+#include "dw-hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-i2s-audio"
+
+static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
+ u8 val, int offset)
+{
+ struct dw_hdmi *hdmi = audio->hdmi;
+
+ audio->write(hdmi, val, offset);
+}
+
+static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
+{
+ struct dw_hdmi *hdmi = audio->hdmi;
+
+ return audio->read(hdmi, offset);
+}
+
+static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
+{
+ struct dw_hdmi_i2s_audio_data *audio = data;
+ struct dw_hdmi *hdmi = audio->hdmi;
+ u8 conf0 = 0;
+ u8 conf1 = 0;
+ u8 inputclkfs = 0;
+
+ /* it cares I2S only */
+ if ((fmt->fmt != HDMI_I2S) ||
+ (fmt->bit_clk_master | fmt->frame_clk_master)) {
+ dev_err(dev, "unsupported format/settings\n");
+ return -EINVAL;
+ }
+
+ inputclkfs = HDMI_AUD_INPUTCLKFS_64FS;
+ conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE;
+
+ switch (hparms->sample_width) {
+ case 16:
+ conf1 = HDMI_AUD_CONF1_WIDTH_16;
+ break;
+ case 24:
+ case 32:
+ conf1 = HDMI_AUD_CONF1_WIDTH_24;
+ break;
+ }
+
+ dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
+
+ hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
+ hdmi_write(audio, conf0, HDMI_AUD_CONF0);
+ hdmi_write(audio, conf1, HDMI_AUD_CONF1);
+
+ dw_hdmi_audio_enable(hdmi);
+
+ return 0;
+}
+
+static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
+{
+ struct dw_hdmi_i2s_audio_data *audio = data;
+ struct dw_hdmi *hdmi = audio->hdmi;
+
+ dw_hdmi_audio_disable(hdmi);
+
+ hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
+}
+
+static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
+ .hw_params = dw_hdmi_i2s_hw_params,
+ .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+ struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
+ struct platform_device_info pdevinfo;
+ struct hdmi_codec_pdata pdata;
+ struct platform_device *platform;
+
+ pdata.ops = &dw_hdmi_i2s_ops;
+ pdata.i2s = 1;
+ pdata.max_i2s_channels = 6;
+ pdata.data = audio;
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo.parent = pdev->dev.parent;
+ pdevinfo.id = PLATFORM_DEVID_AUTO;
+ pdevinfo.name = HDMI_CODEC_DRV_NAME;
+ pdevinfo.data = &pdata;
+ pdevinfo.size_data = sizeof(pdata);
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+
+ platform = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(platform))
+ return PTR_ERR(platform);
+
+ dev_set_drvdata(&pdev->dev, platform);
+
+ return 0;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+ struct platform_device *platform = dev_get_drvdata(&pdev->dev);
+
+ platform_device_unregister(platform);
+
+ return 0;
+}
+
+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,
+ },
+};
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index ab7023e5dfde..235ce7d1583d 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1,14 +1,15 @@
/*
+ * DesignWare High-Definition Multimedia Interface (HDMI) driver
+ *
+ * Copyright (C) 2013-2015 Mentor Graphics Inc.
* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.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.
*
- * Designware High-Definition Multimedia Interface (HDMI) driver
- *
- * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*/
#include <linux/module.h>
#include <linux/irq.h>
@@ -101,6 +102,17 @@ struct hdmi_data_info {
struct hdmi_vmode video_mode;
};
+struct dw_hdmi_i2c {
+ struct i2c_adapter adap;
+
+ struct mutex lock; /* used to serialize data transfers */
+ struct completion cmp;
+ u8 stat;
+
+ u8 slave_reg;
+ bool is_regaddr;
+};
+
struct dw_hdmi {
struct drm_connector connector;
struct drm_encoder *encoder;
@@ -111,6 +123,7 @@ struct dw_hdmi {
struct device *dev;
struct clk *isfr_clk;
struct clk *iahb_clk;
+ struct dw_hdmi_i2c *i2c;
struct hdmi_data_info hdmi_data;
const struct dw_hdmi_plat_data *plat_data;
@@ -198,6 +211,201 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
hdmi_modb(hdmi, data << shift, mask, reg);
}
+static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
+{
+ /* Software reset */
+ hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ);
+
+ /* Set Standard Mode speed (determined to be 100KHz on iMX6) */
+ hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV);
+
+ /* Set done, not acknowledged and arbitration interrupt polarities */
+ hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT);
+ hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL,
+ HDMI_I2CM_CTLINT);
+
+ /* Clear DONE and ERROR interrupts */
+ hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+ HDMI_IH_I2CM_STAT0);
+
+ /* Mute DONE and ERROR interrupts */
+ hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+ HDMI_IH_MUTE_I2CM_STAT0);
+}
+
+static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
+ unsigned char *buf, unsigned int length)
+{
+ struct dw_hdmi_i2c *i2c = hdmi->i2c;
+ int stat;
+
+ if (!i2c->is_regaddr) {
+ dev_dbg(hdmi->dev, "set read register address to 0\n");
+ i2c->slave_reg = 0x00;
+ i2c->is_regaddr = true;
+ }
+
+ while (length--) {
+ reinit_completion(&i2c->cmp);
+
+ hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
+ HDMI_I2CM_OPERATION);
+
+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+ if (!stat)
+ return -EAGAIN;
+
+ /* Check for error condition on the bus */
+ if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+ return -EIO;
+
+ *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
+ }
+
+ return 0;
+}
+
+static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi,
+ unsigned char *buf, unsigned int length)
+{
+ struct dw_hdmi_i2c *i2c = hdmi->i2c;
+ int stat;
+
+ if (!i2c->is_regaddr) {
+ /* Use the first write byte as register address */
+ i2c->slave_reg = buf[0];
+ length--;
+ buf++;
+ i2c->is_regaddr = true;
+ }
+
+ while (length--) {
+ reinit_completion(&i2c->cmp);
+
+ hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO);
+ hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE,
+ HDMI_I2CM_OPERATION);
+
+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+ if (!stat)
+ return -EAGAIN;
+
+ /* Check for error condition on the bus */
+ if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct dw_hdmi *hdmi = i2c_get_adapdata(adap);
+ struct dw_hdmi_i2c *i2c = hdmi->i2c;
+ u8 addr = msgs[0].addr;
+ int i, ret = 0;
+
+ dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
+
+ for (i = 0; i < num; i++) {
+ if (msgs[i].addr != addr) {
+ dev_warn(hdmi->dev,
+ "unsupported transfer, changed slave address\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (msgs[i].len == 0) {
+ dev_dbg(hdmi->dev,
+ "unsupported transfer %d/%d, no data\n",
+ i + 1, num);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ mutex_lock(&i2c->lock);
+
+ /* Unmute DONE and ERROR interrupts */
+ hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0);
+
+ /* Set slave device address taken from the first I2C message */
+ hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE);
+
+ /* Set slave device register address on transfer */
+ i2c->is_regaddr = false;
+
+ for (i = 0; i < num; i++) {
+ dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
+ i + 1, num, msgs[i].len, msgs[i].flags);
+
+ if (msgs[i].flags & I2C_M_RD)
+ ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
+ else
+ ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
+
+ if (ret < 0)
+ break;
+ }
+
+ if (!ret)
+ ret = num;
+
+ /* Mute DONE and ERROR interrupts */
+ hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+ HDMI_IH_MUTE_I2CM_STAT0);
+
+ mutex_unlock(&i2c->lock);
+
+ return ret;
+}
+
+static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm dw_hdmi_algorithm = {
+ .master_xfer = dw_hdmi_i2c_xfer,
+ .functionality = dw_hdmi_i2c_func,
+};
+
+static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
+{
+ struct i2c_adapter *adap;
+ struct dw_hdmi_i2c *i2c;
+ int ret;
+
+ i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_init(&i2c->lock);
+ init_completion(&i2c->cmp);
+
+ adap = &i2c->adap;
+ adap->class = I2C_CLASS_DDC;
+ adap->owner = THIS_MODULE;
+ adap->dev.parent = hdmi->dev;
+ adap->algo = &dw_hdmi_algorithm;
+ strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
+ i2c_set_adapdata(adap, hdmi);
+
+ ret = i2c_add_adapter(adap);
+ if (ret) {
+ dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
+ devm_kfree(hdmi->dev, i2c);
+ return ERR_PTR(ret);
+ }
+
+ hdmi->i2c = i2c;
+
+ dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
+
+ return adap;
+}
+
static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
unsigned int n)
{
@@ -1512,16 +1720,40 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.mode_set = dw_hdmi_bridge_mode_set,
};
+static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
+{
+ struct dw_hdmi_i2c *i2c = hdmi->i2c;
+ unsigned int stat;
+
+ stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0);
+ if (!stat)
+ return IRQ_NONE;
+
+ hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0);
+
+ i2c->stat = stat;
+
+ complete(&i2c->cmp);
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
{
struct dw_hdmi *hdmi = dev_id;
u8 intr_stat;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (hdmi->i2c)
+ ret = dw_hdmi_i2c_irq(hdmi);
intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
- if (intr_stat)
+ if (intr_stat) {
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+ return IRQ_WAKE_THREAD;
+ }
- return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
+ return ret;
}
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
@@ -1639,10 +1871,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
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;
+ u8 config0;
+ u8 config1;
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
@@ -1681,7 +1914,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
if (ddc_node) {
- hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+ hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
of_node_put(ddc_node);
if (!hdmi->ddc) {
dev_dbg(hdmi->dev, "failed to read ddc node\n");
@@ -1693,20 +1926,22 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
}
hdmi->regs = devm_ioremap_resource(dev, iores);
- if (IS_ERR(hdmi->regs))
- return PTR_ERR(hdmi->regs);
+ if (IS_ERR(hdmi->regs)) {
+ ret = PTR_ERR(hdmi->regs);
+ goto err_res;
+ }
hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
if (IS_ERR(hdmi->isfr_clk)) {
ret = PTR_ERR(hdmi->isfr_clk);
dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
- return ret;
+ goto err_res;
}
ret = clk_prepare_enable(hdmi->isfr_clk);
if (ret) {
dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
- return ret;
+ goto err_res;
}
hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
@@ -1744,6 +1979,13 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
*/
hdmi_init_clk_regenerator(hdmi);
+ /* If DDC bus is not specified, try to register HDMI I2C bus */
+ if (!hdmi->ddc) {
+ hdmi->ddc = dw_hdmi_i2c_adapter(hdmi);
+ if (IS_ERR(hdmi->ddc))
+ hdmi->ddc = NULL;
+ }
+
/*
* Configure registers related to HDMI interrupt
* generation before registering IRQ.
@@ -1770,7 +2012,12 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
pdevinfo.parent = dev;
pdevinfo.id = PLATFORM_DEVID_AUTO;
- if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+ config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
+ config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
+
+ if (config1 & HDMI_CONFIG1_AHB) {
+ struct dw_hdmi_audio_data audio;
+
audio.phys = iores->start;
audio.base = hdmi->regs;
audio.irq = irq;
@@ -1782,16 +2029,39 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
pdevinfo.size_data = sizeof(audio);
pdevinfo.dma_mask = DMA_BIT_MASK(32);
hdmi->audio = platform_device_register_full(&pdevinfo);
+ } else if (config0 & HDMI_CONFIG0_I2S) {
+ struct dw_hdmi_i2s_audio_data audio;
+
+ audio.hdmi = hdmi;
+ audio.write = hdmi_writeb;
+ audio.read = hdmi_readb;
+
+ pdevinfo.name = "dw-hdmi-i2s-audio";
+ pdevinfo.data = &audio;
+ pdevinfo.size_data = sizeof(audio);
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+ hdmi->audio = platform_device_register_full(&pdevinfo);
}
+ /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
+ if (hdmi->i2c)
+ dw_hdmi_i2c_init(hdmi);
+
dev_set_drvdata(dev, hdmi);
return 0;
err_iahb:
+ if (hdmi->i2c) {
+ i2c_del_adapter(&hdmi->i2c->adap);
+ hdmi->ddc = NULL;
+ }
+
clk_disable_unprepare(hdmi->iahb_clk);
err_isfr:
clk_disable_unprepare(hdmi->isfr_clk);
+err_res:
+ i2c_put_adapter(hdmi->ddc);
return ret;
}
@@ -1809,13 +2079,18 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
clk_disable_unprepare(hdmi->iahb_clk);
clk_disable_unprepare(hdmi->isfr_clk);
- i2c_put_adapter(hdmi->ddc);
+
+ if (hdmi->i2c)
+ i2c_del_adapter(&hdmi->i2c->adap);
+ else
+ i2c_put_adapter(hdmi->ddc);
}
EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
MODULE_DESCRIPTION("DW HDMI transmitter driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dw-hdmi");
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
index fc9a560429d6..55135bbd0c16 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 {
+/* CONFIG0_ID field values */
+ HDMI_CONFIG0_I2S = 0x10,
+
/* CONFIG1_ID field values */
HDMI_CONFIG1_AHB = 0x01,
@@ -566,6 +569,10 @@ enum {
HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
HDMI_IH_PHY_STAT0_HPD = 0x1,
+/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */
+ HDMI_IH_I2CM_STAT0_DONE = 0x2,
+ HDMI_IH_I2CM_STAT0_ERROR = 0x1,
+
/* IH_MUTE_I2CMPHY_STAT0 field values */
HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
@@ -887,6 +894,17 @@ enum {
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
+/* AUD_CONF0 field values */
+ HDMI_AUD_CONF0_SW_RESET = 0x80,
+ HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F,
+
+/* AUD_CONF1 field values */
+ HDMI_AUD_CONF1_MODE_I2S = 0x00,
+ HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02,
+ HDMI_AUD_CONF1_MODE_LEFT_J = 0x04,
+ HDMI_AUD_CONF1_WIDTH_16 = 0x10,
+ HDMI_AUD_CONF1_WIDTH_24 = 0x18,
+
/* AUD_CTS3 field values */
HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
@@ -901,6 +919,12 @@ enum {
HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+/* HDMI_AUD_INPUTCLKFS field values */
+ HDMI_AUD_INPUTCLKFS_128FS = 0,
+ HDMI_AUD_INPUTCLKFS_256FS = 1,
+ HDMI_AUD_INPUTCLKFS_512FS = 2,
+ HDMI_AUD_INPUTCLKFS_64FS = 4,
+
/* AHB_DMA_CONF0 field values */
HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
@@ -1032,6 +1056,21 @@ enum {
HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+
+/* I2CM_OPERATION field values */
+ HDMI_I2CM_OPERATION_WRITE = 0x10,
+ HDMI_I2CM_OPERATION_READ_EXT = 0x2,
+ HDMI_I2CM_OPERATION_READ = 0x1,
+
+/* I2CM_INT field values */
+ HDMI_I2CM_INT_DONE_POL = 0x8,
+ HDMI_I2CM_INT_DONE_MASK = 0x4,
+
+/* I2CM_CTLINT field values */
+ HDMI_I2CM_CTLINT_NAC_POL = 0x80,
+ HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
+ HDMI_I2CM_CTLINT_ARB_POL = 0x8,
+ HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
};
#endif /* __DW_HDMI_H__ */
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index f1a99938e924..27f98c518dde 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -239,16 +239,9 @@ static const struct drm_connector_helper_funcs ptn3460_connector_helper_funcs =
.get_modes = ptn3460_get_modes,
};
-static enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
- bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_funcs ptn3460_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = ptn3460_detect,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 6f7c2f9860d2..ac8cc5b50d9f 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -477,16 +477,9 @@ static const struct drm_connector_helper_funcs ps8622_connector_helper_funcs = {
.get_modes = ps8622_get_modes,
};
-static enum drm_connector_status ps8622_detect(struct drm_connector *connector,
- bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_funcs ps8622_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = ps8622_detect,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
new file mode 100644
index 000000000000..b2c267df7ee7
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -0,0 +1,1564 @@
+/*
+ * Silicon Image SiI8620 HDMI/MHL bridge driver
+ *
+ * Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.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 <drm/bridge/mhl.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include "sil-sii8620.h"
+
+#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
+
+enum sii8620_mode {
+ CM_DISCONNECTED,
+ CM_DISCOVERY,
+ CM_MHL1,
+ CM_MHL3,
+ CM_ECBUS_S
+};
+
+enum sii8620_sink_type {
+ SINK_NONE,
+ SINK_HDMI,
+ SINK_DVI
+};
+
+enum sii8620_mt_state {
+ MT_STATE_READY,
+ MT_STATE_BUSY,
+ MT_STATE_DONE
+};
+
+struct sii8620 {
+ struct drm_bridge bridge;
+ struct device *dev;
+ struct clk *clk_xtal;
+ struct gpio_desc *gpio_reset;
+ struct gpio_desc *gpio_int;
+ struct regulator_bulk_data supplies[2];
+ struct mutex lock; /* context lock, protects fields below */
+ int error;
+ enum sii8620_mode mode;
+ enum sii8620_sink_type sink_type;
+ u8 cbus_status;
+ u8 stat[MHL_DST_SIZE];
+ u8 xstat[MHL_XDS_SIZE];
+ u8 devcap[MHL_DCAP_SIZE];
+ u8 xdevcap[MHL_XDC_SIZE];
+ u8 avif[19];
+ struct edid *edid;
+ unsigned int gen2_write_burst:1;
+ enum sii8620_mt_state mt_state;
+ struct list_head mt_queue;
+};
+
+struct sii8620_mt_msg;
+
+typedef void (*sii8620_mt_msg_cb)(struct sii8620 *ctx,
+ struct sii8620_mt_msg *msg);
+
+struct sii8620_mt_msg {
+ struct list_head node;
+ u8 reg[4];
+ u8 ret;
+ sii8620_mt_msg_cb send;
+ sii8620_mt_msg_cb recv;
+};
+
+static const u8 sii8620_i2c_page[] = {
+ 0x39, /* Main System */
+ 0x3d, /* TDM and HSIC */
+ 0x49, /* TMDS Receiver, MHL EDID */
+ 0x4d, /* eMSC, HDCP, HSIC */
+ 0x5d, /* MHL Spec */
+ 0x64, /* MHL CBUS */
+ 0x59, /* Hardware TPI (Transmitter Programming Interface) */
+ 0x61, /* eCBUS-S, eCBUS-D */
+};
+
+static void sii8620_fetch_edid(struct sii8620 *ctx);
+static void sii8620_set_upstream_edid(struct sii8620 *ctx);
+static void sii8620_enable_hpd(struct sii8620 *ctx);
+static void sii8620_mhl_disconnected(struct sii8620 *ctx);
+
+static int sii8620_clear_error(struct sii8620 *ctx)
+{
+ int ret = ctx->error;
+
+ ctx->error = 0;
+ return ret;
+}
+
+static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len)
+{
+ struct device *dev = ctx->dev;
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 data = addr;
+ struct i2c_msg msg[] = {
+ {
+ .addr = sii8620_i2c_page[addr >> 8],
+ .flags = client->flags,
+ .len = 1,
+ .buf = &data
+ },
+ {
+ .addr = sii8620_i2c_page[addr >> 8],
+ .flags = client->flags | I2C_M_RD,
+ .len = len,
+ .buf = buf
+ },
+ };
+ int ret;
+
+ if (ctx->error)
+ return;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+ dev_dbg(dev, "read at %04x: %*ph, %d\n", addr, len, buf, ret);
+
+ if (ret != 2) {
+ dev_err(dev, "Read at %#06x of %d bytes failed with code %d.\n",
+ addr, len, ret);
+ ctx->error = ret < 0 ? ret : -EIO;
+ }
+}
+
+static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
+{
+ u8 ret;
+
+ sii8620_read_buf(ctx, addr, &ret, 1);
+ return ret;
+}
+
+static void sii8620_write_buf(struct sii8620 *ctx, u16 addr, const u8 *buf,
+ int len)
+{
+ struct device *dev = ctx->dev;
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 data[2];
+ struct i2c_msg msg = {
+ .addr = sii8620_i2c_page[addr >> 8],
+ .flags = client->flags,
+ .len = len + 1,
+ };
+ int ret;
+
+ if (ctx->error)
+ return;
+
+ if (len > 1) {
+ msg.buf = kmalloc(len + 1, GFP_KERNEL);
+ if (!msg.buf) {
+ ctx->error = -ENOMEM;
+ return;
+ }
+ memcpy(msg.buf + 1, buf, len);
+ } else {
+ msg.buf = data;
+ msg.buf[1] = *buf;
+ }
+
+ msg.buf[0] = addr;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ dev_dbg(dev, "write at %04x: %*ph, %d\n", addr, len, buf, ret);
+
+ if (ret != 1) {
+ dev_err(dev, "Write at %#06x of %*ph failed with code %d.\n",
+ addr, len, buf, ret);
+ ctx->error = ret ?: -EIO;
+ }
+
+ if (len > 1)
+ kfree(msg.buf);
+}
+
+#define sii8620_write(ctx, addr, arr...) \
+({\
+ u8 d[] = { arr }; \
+ sii8620_write_buf(ctx, addr, d, ARRAY_SIZE(d)); \
+})
+
+static void __sii8620_write_seq(struct sii8620 *ctx, const u16 *seq, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i += 2)
+ sii8620_write(ctx, seq[i], seq[i + 1]);
+}
+
+#define sii8620_write_seq(ctx, seq...) \
+({\
+ const u16 d[] = { seq }; \
+ __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
+})
+
+#define sii8620_write_seq_static(ctx, seq...) \
+({\
+ static const u16 d[] = { seq }; \
+ __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
+})
+
+static void sii8620_setbits(struct sii8620 *ctx, u16 addr, u8 mask, u8 val)
+{
+ val = (val & mask) | (sii8620_readb(ctx, addr) & ~mask);
+ sii8620_write(ctx, addr, val);
+}
+
+static void sii8620_mt_cleanup(struct sii8620 *ctx)
+{
+ struct sii8620_mt_msg *msg, *n;
+
+ list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) {
+ list_del(&msg->node);
+ kfree(msg);
+ }
+ ctx->mt_state = MT_STATE_READY;
+}
+
+static void sii8620_mt_work(struct sii8620 *ctx)
+{
+ struct sii8620_mt_msg *msg;
+
+ if (ctx->error)
+ return;
+ if (ctx->mt_state == MT_STATE_BUSY || list_empty(&ctx->mt_queue))
+ return;
+
+ if (ctx->mt_state == MT_STATE_DONE) {
+ ctx->mt_state = MT_STATE_READY;
+ msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg,
+ node);
+ if (msg->recv)
+ msg->recv(ctx, msg);
+ list_del(&msg->node);
+ kfree(msg);
+ }
+
+ if (ctx->mt_state != MT_STATE_READY || list_empty(&ctx->mt_queue))
+ return;
+
+ ctx->mt_state = MT_STATE_BUSY;
+ msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
+ if (msg->send)
+ msg->send(ctx, msg);
+}
+
+static void sii8620_mt_msc_cmd_send(struct sii8620 *ctx,
+ struct sii8620_mt_msg *msg)
+{
+ switch (msg->reg[0]) {
+ case MHL_WRITE_STAT:
+ case MHL_SET_INT:
+ sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2);
+ sii8620_write(ctx, REG_MSC_COMMAND_START,
+ BIT_MSC_COMMAND_START_WRITE_STAT);
+ break;
+ case MHL_MSC_MSG:
+ sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3);
+ sii8620_write(ctx, REG_MSC_COMMAND_START,
+ BIT_MSC_COMMAND_START_MSC_MSG);
+ break;
+ default:
+ dev_err(ctx->dev, "%s: command %#x not supported\n", __func__,
+ msg->reg[0]);
+ }
+}
+
+static struct sii8620_mt_msg *sii8620_mt_msg_new(struct sii8620 *ctx)
+{
+ struct sii8620_mt_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
+
+ if (!msg)
+ ctx->error = -ENOMEM;
+ else
+ list_add_tail(&msg->node, &ctx->mt_queue);
+
+ return msg;
+}
+
+static void sii8620_mt_msc_cmd(struct sii8620 *ctx, u8 cmd, u8 arg1, u8 arg2)
+{
+ struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
+
+ if (!msg)
+ return;
+
+ msg->reg[0] = cmd;
+ msg->reg[1] = arg1;
+ msg->reg[2] = arg2;
+ msg->send = sii8620_mt_msc_cmd_send;
+}
+
+static void sii8620_mt_write_stat(struct sii8620 *ctx, u8 reg, u8 val)
+{
+ sii8620_mt_msc_cmd(ctx, MHL_WRITE_STAT, reg, val);
+}
+
+static inline void sii8620_mt_set_int(struct sii8620 *ctx, u8 irq, u8 mask)
+{
+ sii8620_mt_msc_cmd(ctx, MHL_SET_INT, irq, mask);
+}
+
+static void sii8620_mt_msc_msg(struct sii8620 *ctx, u8 cmd, u8 data)
+{
+ sii8620_mt_msc_cmd(ctx, MHL_MSC_MSG, cmd, data);
+}
+
+static void sii8620_mt_rap(struct sii8620 *ctx, u8 code)
+{
+ sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code);
+}
+
+static void sii8620_mt_read_devcap_send(struct sii8620 *ctx,
+ struct sii8620_mt_msg *msg)
+{
+ u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
+ | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+ | BIT_EDID_CTRL_EDID_MODE_EN;
+
+ if (msg->reg[0] == MHL_READ_XDEVCAP)
+ ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
+
+ sii8620_write_seq(ctx,
+ REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE,
+ REG_EDID_CTRL, ctrl,
+ REG_TPI_CBUS_START, BIT_TPI_CBUS_START_GET_DEVCAP_START
+ );
+}
+
+/* copy src to dst and set changed bits in src */
+static void sii8620_update_array(u8 *dst, u8 *src, int count)
+{
+ while (--count >= 0) {
+ *src ^= *dst;
+ *dst++ ^= *src++;
+ }
+}
+
+static void sii8620_mr_devcap(struct sii8620 *ctx)
+{
+ static const char * const sink_str[] = {
+ [SINK_NONE] = "NONE",
+ [SINK_HDMI] = "HDMI",
+ [SINK_DVI] = "DVI"
+ };
+
+ u8 dcap[MHL_DCAP_SIZE];
+ char sink_name[20];
+ struct device *dev = ctx->dev;
+
+ sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, dcap, MHL_DCAP_SIZE);
+ if (ctx->error < 0)
+ return;
+
+ dev_info(dev, "dcap: %*ph\n", MHL_DCAP_SIZE, dcap);
+ dev_info(dev, "detected dongle MHL %d.%d, ChipID %02x%02x:%02x%02x\n",
+ dcap[MHL_DCAP_MHL_VERSION] / 16,
+ dcap[MHL_DCAP_MHL_VERSION] % 16, dcap[MHL_DCAP_ADOPTER_ID_H],
+ dcap[MHL_DCAP_ADOPTER_ID_L], dcap[MHL_DCAP_DEVICE_ID_H],
+ dcap[MHL_DCAP_DEVICE_ID_L]);
+ sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
+
+ if (!(dcap[MHL_DCAP_CAT] & MHL_DCAP_CAT_SINK))
+ return;
+
+ sii8620_fetch_edid(ctx);
+ if (!ctx->edid) {
+ dev_err(ctx->dev, "Cannot fetch EDID\n");
+ sii8620_mhl_disconnected(ctx);
+ return;
+ }
+
+ if (drm_detect_hdmi_monitor(ctx->edid))
+ ctx->sink_type = SINK_HDMI;
+ else
+ ctx->sink_type = SINK_DVI;
+
+ drm_edid_get_monitor_name(ctx->edid, sink_name, ARRAY_SIZE(sink_name));
+
+ dev_info(dev, "detected sink(type: %s): %s\n",
+ sink_str[ctx->sink_type], sink_name);
+ sii8620_set_upstream_edid(ctx);
+ sii8620_enable_hpd(ctx);
+}
+
+static void sii8620_mr_xdevcap(struct sii8620 *ctx)
+{
+ sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap,
+ MHL_XDC_SIZE);
+
+ sii8620_mt_write_stat(ctx, MHL_XDS_REG(CURR_ECBUS_MODE),
+ MHL_XDS_ECBUS_S | MHL_XDS_SLOT_MODE_8BIT);
+ sii8620_mt_rap(ctx, MHL_RAP_CBUS_MODE_UP);
+}
+
+static void sii8620_mt_read_devcap_recv(struct sii8620 *ctx,
+ struct sii8620_mt_msg *msg)
+{
+ u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
+ | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+ | BIT_EDID_CTRL_EDID_MODE_EN;
+
+ if (msg->reg[0] == MHL_READ_XDEVCAP)
+ ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
+
+ sii8620_write_seq(ctx,
+ REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE | BIT_INTR9_EDID_DONE
+ | BIT_INTR9_EDID_ERROR,
+ REG_EDID_CTRL, ctrl,
+ REG_EDID_FIFO_ADDR, 0
+ );
+
+ if (msg->reg[0] == MHL_READ_XDEVCAP)
+ sii8620_mr_xdevcap(ctx);
+ else
+ sii8620_mr_devcap(ctx);
+}
+
+static void sii8620_mt_read_devcap(struct sii8620 *ctx, bool xdevcap)
+{
+ struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
+
+ if (!msg)
+ return;
+
+ msg->reg[0] = xdevcap ? MHL_READ_XDEVCAP : MHL_READ_DEVCAP;
+ msg->send = sii8620_mt_read_devcap_send;
+ msg->recv = sii8620_mt_read_devcap_recv;
+}
+
+static void sii8620_fetch_edid(struct sii8620 *ctx)
+{
+ u8 lm_ddc, ddc_cmd, int3, cbus;
+ int fetched, i;
+ int edid_len = EDID_LENGTH;
+ u8 *edid;
+
+ sii8620_readb(ctx, REG_CBUS_STATUS);
+ lm_ddc = sii8620_readb(ctx, REG_LM_DDC);
+ ddc_cmd = sii8620_readb(ctx, REG_DDC_CMD);
+
+ sii8620_write_seq(ctx,
+ REG_INTR9_MASK, 0,
+ REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
+ REG_HDCP2X_POLL_CS, 0x71,
+ REG_HDCP2X_CTRL_0, BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX,
+ REG_LM_DDC, lm_ddc | BIT_LM_DDC_SW_TPI_EN_DISABLED,
+ );
+
+ for (i = 0; i < 256; ++i) {
+ u8 ddc_stat = sii8620_readb(ctx, REG_DDC_STATUS);
+
+ if (!(ddc_stat & BIT_DDC_STATUS_DDC_I2C_IN_PROG))
+ break;
+ sii8620_write(ctx, REG_DDC_STATUS,
+ BIT_DDC_STATUS_DDC_FIFO_EMPTY);
+ }
+
+ sii8620_write(ctx, REG_DDC_ADDR, 0x50 << 1);
+
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!edid) {
+ ctx->error = -ENOMEM;
+ return;
+ }
+
+#define FETCH_SIZE 16
+ for (fetched = 0; fetched < edid_len; fetched += FETCH_SIZE) {
+ sii8620_readb(ctx, REG_DDC_STATUS);
+ sii8620_write_seq(ctx,
+ REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_ABORT,
+ REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO,
+ REG_DDC_STATUS, BIT_DDC_STATUS_DDC_FIFO_EMPTY
+ );
+ sii8620_write_seq(ctx,
+ REG_DDC_SEGM, fetched >> 8,
+ REG_DDC_OFFSET, fetched & 0xff,
+ REG_DDC_DIN_CNT1, FETCH_SIZE,
+ REG_DDC_DIN_CNT2, 0,
+ REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK
+ );
+
+ do {
+ int3 = sii8620_readb(ctx, REG_INTR3);
+ cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
+
+ if (int3 & BIT_DDC_CMD_DONE)
+ break;
+
+ if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) {
+ kfree(edid);
+ edid = NULL;
+ goto end;
+ }
+ } while (1);
+
+ sii8620_readb(ctx, REG_DDC_STATUS);
+ while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE)
+ usleep_range(10, 20);
+
+ sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
+ if (fetched + FETCH_SIZE == EDID_LENGTH) {
+ u8 ext = ((struct edid *)edid)->extensions;
+
+ if (ext) {
+ u8 *new_edid;
+
+ edid_len += ext * EDID_LENGTH;
+ new_edid = krealloc(edid, edid_len, GFP_KERNEL);
+ if (!new_edid) {
+ kfree(edid);
+ ctx->error = -ENOMEM;
+ return;
+ }
+ edid = new_edid;
+ }
+ }
+
+ if (fetched + FETCH_SIZE == edid_len)
+ sii8620_write(ctx, REG_INTR3, int3);
+ }
+
+ sii8620_write(ctx, REG_LM_DDC, lm_ddc);
+
+end:
+ kfree(ctx->edid);
+ ctx->edid = (struct edid *)edid;
+}
+
+static void sii8620_set_upstream_edid(struct sii8620 *ctx)
+{
+ sii8620_setbits(ctx, REG_DPD, BIT_DPD_PDNRX12 | BIT_DPD_PDIDCK_N
+ | BIT_DPD_PD_MHL_CLK_N, 0xff);
+
+ sii8620_write_seq_static(ctx,
+ REG_RX_HDMI_CTRL3, 0x00,
+ REG_PKT_FILTER_0, 0xFF,
+ REG_PKT_FILTER_1, 0xFF,
+ REG_ALICE0_BW_I2C, 0x06
+ );
+
+ sii8620_setbits(ctx, REG_RX_HDMI_CLR_BUFFER,
+ BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN, 0xff);
+
+ sii8620_write_seq_static(ctx,
+ REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+ | BIT_EDID_CTRL_EDID_MODE_EN,
+ REG_EDID_FIFO_ADDR, 0,
+ );
+
+ sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid,
+ (ctx->edid->extensions + 1) * EDID_LENGTH);
+
+ sii8620_write_seq_static(ctx,
+ REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID
+ | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+ | BIT_EDID_CTRL_EDID_MODE_EN,
+ REG_INTR5_MASK, BIT_INTR_SCDT_CHANGE,
+ REG_INTR9_MASK, 0
+ );
+}
+
+static void sii8620_xtal_set_rate(struct sii8620 *ctx)
+{
+ static const struct {
+ unsigned int rate;
+ u8 div;
+ u8 tp1;
+ } rates[] = {
+ { 19200, 0x04, 0x53 },
+ { 20000, 0x04, 0x62 },
+ { 24000, 0x05, 0x75 },
+ { 30000, 0x06, 0x92 },
+ { 38400, 0x0c, 0xbc },
+ };
+ unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rates) - 1; ++i)
+ if (rate <= rates[i].rate)
+ break;
+
+ if (rate != rates[i].rate)
+ dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n",
+ rate, rates[i].rate);
+
+ sii8620_write(ctx, REG_DIV_CTL_MAIN, rates[i].div);
+ sii8620_write(ctx, REG_HDCP2X_TP1, rates[i].tp1);
+}
+
+static int sii8620_hw_on(struct sii8620 *ctx)
+{
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret)
+ return ret;
+ usleep_range(10000, 20000);
+ return clk_prepare_enable(ctx->clk_xtal);
+}
+
+static int sii8620_hw_off(struct sii8620 *ctx)
+{
+ clk_disable_unprepare(ctx->clk_xtal);
+ gpiod_set_value(ctx->gpio_reset, 1);
+ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+}
+
+static void sii8620_hw_reset(struct sii8620 *ctx)
+{
+ usleep_range(10000, 20000);
+ gpiod_set_value(ctx->gpio_reset, 0);
+ usleep_range(5000, 20000);
+ gpiod_set_value(ctx->gpio_reset, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value(ctx->gpio_reset, 0);
+ msleep(300);
+}
+
+static void sii8620_cbus_reset(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
+ | BIT_PWD_SRST_CBUS_RST_SW_EN,
+ REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN
+ );
+}
+
+static void sii8620_set_auto_zone(struct sii8620 *ctx)
+{
+ if (ctx->mode != CM_MHL1) {
+ sii8620_write_seq_static(ctx,
+ REG_TX_ZONE_CTL1, 0x0,
+ REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+ | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+ | BIT_MHL_PLL_CTL0_ZONE_MASK_OE
+ );
+ } else {
+ sii8620_write_seq_static(ctx,
+ REG_TX_ZONE_CTL1, VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE,
+ REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+ | BIT_MHL_PLL_CTL0_ZONE_MASK_OE
+ );
+ }
+}
+
+static void sii8620_stop_video(struct sii8620 *ctx)
+{
+ u8 uninitialized_var(val);
+
+ sii8620_write_seq_static(ctx,
+ REG_TPI_INTR_EN, 0,
+ REG_HDCP2X_INTR0_MASK, 0,
+ REG_TPI_COPP_DATA2, 0,
+ REG_TPI_INTR_ST0, ~0,
+ );
+
+ switch (ctx->sink_type) {
+ case SINK_DVI:
+ val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
+ | BIT_TPI_SC_TPI_AV_MUTE;
+ break;
+ case SINK_HDMI:
+ val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
+ | BIT_TPI_SC_TPI_AV_MUTE
+ | BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI;
+ break;
+ default:
+ return;
+ }
+
+ sii8620_write(ctx, REG_TPI_SC, val);
+}
+
+static void sii8620_start_hdmi(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
+ | BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
+ REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE
+ | BIT_VID_OVRRD_M1080P_OVRRD,
+ REG_VID_MODE, 0,
+ REG_MHL_TOP_CTL, 0x1,
+ REG_MHLTX_CTL6, 0xa0,
+ REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
+ REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
+ );
+
+ sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+ MHL_DST_LM_CLK_MODE_NORMAL |
+ MHL_DST_LM_PATH_ENABLED);
+
+ sii8620_set_auto_zone(ctx);
+
+ sii8620_write(ctx, REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
+
+ sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif,
+ ARRAY_SIZE(ctx->avif));
+
+ sii8620_write(ctx, REG_PKT_FILTER_0, 0xa1, 0x2);
+}
+
+static void sii8620_start_video(struct sii8620 *ctx)
+{
+ if (ctx->mode < CM_MHL3)
+ sii8620_stop_video(ctx);
+
+ switch (ctx->sink_type) {
+ case SINK_HDMI:
+ sii8620_start_hdmi(ctx);
+ break;
+ case SINK_DVI:
+ default:
+ break;
+ }
+}
+
+static void sii8620_disable_hpd(struct sii8620 *ctx)
+{
+ sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
+ sii8620_write_seq_static(ctx,
+ REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN,
+ REG_INTR8_MASK, 0
+ );
+}
+
+static void sii8620_enable_hpd(struct sii8620 *ctx)
+{
+ sii8620_setbits(ctx, REG_TMDS_CSTAT_P3,
+ BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS
+ | BIT_TMDS_CSTAT_P3_CLR_AVI, ~0);
+ sii8620_write_seq_static(ctx,
+ REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN
+ | BIT_HPD_CTRL_HPD_HIGH,
+ );
+}
+
+static void sii8620_enable_gen2_write_burst(struct sii8620 *ctx)
+{
+ if (ctx->gen2_write_burst)
+ return;
+
+ sii8620_write_seq_static(ctx,
+ REG_MDT_RCV_TIMEOUT, 100,
+ REG_MDT_RCV_CTRL, BIT_MDT_RCV_CTRL_MDT_RCV_EN
+ );
+ ctx->gen2_write_burst = 1;
+}
+
+static void sii8620_disable_gen2_write_burst(struct sii8620 *ctx)
+{
+ if (!ctx->gen2_write_burst)
+ return;
+
+ sii8620_write_seq_static(ctx,
+ REG_MDT_XMIT_CTRL, 0,
+ REG_MDT_RCV_CTRL, 0
+ );
+ ctx->gen2_write_burst = 0;
+}
+
+static void sii8620_start_gen2_write_burst(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_MDT_INT_1_MASK, BIT_MDT_RCV_TIMEOUT
+ | BIT_MDT_RCV_SM_ABORT_PKT_RCVD | BIT_MDT_RCV_SM_ERROR
+ | BIT_MDT_XMIT_TIMEOUT | BIT_MDT_XMIT_SM_ABORT_PKT_RCVD
+ | BIT_MDT_XMIT_SM_ERROR,
+ REG_MDT_INT_0_MASK, BIT_MDT_XFIFO_EMPTY
+ | BIT_MDT_IDLE_AFTER_HAWB_DISABLE
+ | BIT_MDT_RFIFO_DATA_RDY
+ );
+ sii8620_enable_gen2_write_burst(ctx);
+}
+
+static void sii8620_mhl_discover(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+ | BIT_DISC_CTRL9_DISC_PULSE_PROCEED,
+ REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_5K, VAL_PUP_20K),
+ REG_CBUS_DISC_INTR0_MASK, BIT_MHL3_EST_INT
+ | BIT_MHL_EST_INT
+ | BIT_NOT_MHL_EST_INT
+ | BIT_CBUS_MHL3_DISCON_INT
+ | BIT_CBUS_MHL12_DISCON_INT
+ | BIT_RGND_READY_INT,
+ REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+ | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+ | BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
+ REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
+ | BIT_MHL_DP_CTL0_TX_OE_OVR,
+ REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+ REG_MHL_DP_CTL1, 0xA2,
+ REG_MHL_DP_CTL2, 0x03,
+ REG_MHL_DP_CTL3, 0x35,
+ REG_MHL_DP_CTL5, 0x02,
+ REG_MHL_DP_CTL6, 0x02,
+ REG_MHL_DP_CTL7, 0x03,
+ REG_COC_CTLC, 0xFF,
+ REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
+ | BIT_DPD_OSC_EN | BIT_DPD_PWRON_HSIC,
+ REG_COC_INTR_MASK, BIT_COC_PLL_LOCK_STATUS_CHANGE
+ | BIT_COC_CALIBRATION_DONE,
+ REG_CBUS_INT_1_MASK, BIT_CBUS_MSC_ABORT_RCVD
+ | BIT_CBUS_CMD_ABORT,
+ REG_CBUS_INT_0_MASK, BIT_CBUS_MSC_MT_DONE
+ | BIT_CBUS_HPD_CHG
+ | BIT_CBUS_MSC_MR_WRITE_STAT
+ | BIT_CBUS_MSC_MR_MSC_MSG
+ | BIT_CBUS_MSC_MR_WRITE_BURST
+ | BIT_CBUS_MSC_MR_SET_INT
+ | BIT_CBUS_MSC_MT_DONE_NACK
+ );
+}
+
+static void sii8620_peer_specific_init(struct sii8620 *ctx)
+{
+ if (ctx->mode == CM_MHL3)
+ sii8620_write_seq_static(ctx,
+ REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD,
+ REG_EMSCINTRMASK1,
+ BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR
+ );
+ else
+ sii8620_write_seq_static(ctx,
+ REG_HDCP2X_INTR0_MASK, 0x00,
+ REG_EMSCINTRMASK1, 0x00,
+ REG_HDCP2X_INTR0, 0xFF,
+ REG_INTR1, 0xFF,
+ REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD
+ | BIT_SYS_CTRL1_TX_CTRL_HDMI
+ );
+}
+
+#define SII8620_MHL_VERSION 0x32
+#define SII8620_SCRATCHPAD_SIZE 16
+#define SII8620_INT_STAT_SIZE 0x33
+
+static void sii8620_set_dev_cap(struct sii8620 *ctx)
+{
+ static const u8 devcap[MHL_DCAP_SIZE] = {
+ [MHL_DCAP_MHL_VERSION] = SII8620_MHL_VERSION,
+ [MHL_DCAP_CAT] = MHL_DCAP_CAT_SOURCE | MHL_DCAP_CAT_POWER,
+ [MHL_DCAP_ADOPTER_ID_H] = 0x01,
+ [MHL_DCAP_ADOPTER_ID_L] = 0x41,
+ [MHL_DCAP_VID_LINK_MODE] = MHL_DCAP_VID_LINK_RGB444
+ | MHL_DCAP_VID_LINK_PPIXEL
+ | MHL_DCAP_VID_LINK_16BPP,
+ [MHL_DCAP_AUD_LINK_MODE] = MHL_DCAP_AUD_LINK_2CH,
+ [MHL_DCAP_VIDEO_TYPE] = MHL_DCAP_VT_GRAPHICS,
+ [MHL_DCAP_LOG_DEV_MAP] = MHL_DCAP_LD_GUI,
+ [MHL_DCAP_BANDWIDTH] = 0x0f,
+ [MHL_DCAP_FEATURE_FLAG] = MHL_DCAP_FEATURE_RCP_SUPPORT
+ | MHL_DCAP_FEATURE_RAP_SUPPORT
+ | MHL_DCAP_FEATURE_SP_SUPPORT,
+ [MHL_DCAP_SCRATCHPAD_SIZE] = SII8620_SCRATCHPAD_SIZE,
+ [MHL_DCAP_INT_STAT_SIZE] = SII8620_INT_STAT_SIZE,
+ };
+ static const u8 xdcap[MHL_XDC_SIZE] = {
+ [MHL_XDC_ECBUS_SPEEDS] = MHL_XDC_ECBUS_S_075
+ | MHL_XDC_ECBUS_S_8BIT,
+ [MHL_XDC_TMDS_SPEEDS] = MHL_XDC_TMDS_150
+ | MHL_XDC_TMDS_300 | MHL_XDC_TMDS_600,
+ [MHL_XDC_ECBUS_ROLES] = MHL_XDC_DEV_HOST,
+ [MHL_XDC_LOG_DEV_MAPX] = MHL_XDC_LD_PHONE,
+ };
+
+ sii8620_write_buf(ctx, REG_MHL_DEVCAP_0, devcap, ARRAY_SIZE(devcap));
+ sii8620_write_buf(ctx, REG_MHL_EXTDEVCAP_0, xdcap, ARRAY_SIZE(xdcap));
+}
+
+static void sii8620_mhl_init(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+ REG_CBUS_MSC_COMPAT_CTRL,
+ BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN,
+ );
+
+ sii8620_peer_specific_init(ctx);
+
+ sii8620_disable_hpd(ctx);
+
+ sii8620_write_seq_static(ctx,
+ REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
+ REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+ | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+ REG_TMDS0_CCTRL1, 0x90,
+ REG_TMDS_CLK_EN, 0x01,
+ REG_TMDS_CH_EN, 0x11,
+ REG_BGR_BIAS, 0x87,
+ REG_ALICE0_ZONE_CTRL, 0xE8,
+ REG_ALICE0_MODE_CTRL, 0x04,
+ );
+ sii8620_setbits(ctx, REG_LM_DDC, BIT_LM_DDC_SW_TPI_EN_DISABLED, 0);
+ sii8620_write_seq_static(ctx,
+ REG_TPI_HW_OPT3, 0x76,
+ REG_TMDS_CCTRL, BIT_TMDS_CCTRL_TMDS_OE,
+ REG_TPI_DTD_B2, 79,
+ );
+ sii8620_set_dev_cap(ctx);
+ sii8620_write_seq_static(ctx,
+ REG_MDT_XMIT_TIMEOUT, 100,
+ REG_MDT_XMIT_CTRL, 0x03,
+ REG_MDT_XFIFO_STAT, 0x00,
+ REG_MDT_RCV_TIMEOUT, 100,
+ REG_CBUS_LINK_CTRL_8, 0x1D,
+ );
+
+ sii8620_start_gen2_write_burst(ctx);
+ sii8620_write_seq_static(ctx,
+ REG_BIST_CTRL, 0x00,
+ REG_COC_CTL1, 0x10,
+ REG_COC_CTL2, 0x18,
+ REG_COC_CTLF, 0x07,
+ REG_COC_CTL11, 0xF8,
+ REG_COC_CTL17, 0x61,
+ REG_COC_CTL18, 0x46,
+ REG_COC_CTL19, 0x15,
+ REG_COC_CTL1A, 0x01,
+ REG_MHL_COC_CTL3, BIT_MHL_COC_CTL3_COC_AECHO_EN,
+ REG_MHL_COC_CTL4, 0x2D,
+ REG_MHL_COC_CTL5, 0xF9,
+ REG_MSC_HEARTBEAT_CTRL, 0x27,
+ );
+ sii8620_disable_gen2_write_burst(ctx);
+
+ /* currently MHL3 is not supported, so we force version to 0 */
+ sii8620_mt_write_stat(ctx, MHL_DST_REG(VERSION), 0);
+ sii8620_mt_write_stat(ctx, MHL_DST_REG(CONNECTED_RDY),
+ MHL_DST_CONN_DCAP_RDY | MHL_DST_CONN_XDEVCAPP_SUPP
+ | MHL_DST_CONN_POW_STAT);
+ sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), MHL_INT_RC_DCAP_CHG);
+}
+
+static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
+{
+ if (ctx->mode == mode)
+ return;
+
+ ctx->mode = mode;
+
+ switch (mode) {
+ case CM_MHL1:
+ sii8620_write_seq_static(ctx,
+ REG_CBUS_MSC_COMPAT_CTRL, 0x02,
+ REG_M3_CTRL, VAL_M3_CTRL_MHL1_2_VALUE,
+ REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
+ | BIT_DPD_OSC_EN,
+ REG_COC_INTR_MASK, 0
+ );
+ break;
+ case CM_MHL3:
+ sii8620_write_seq_static(ctx,
+ REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+ REG_COC_CTL0, 0x40,
+ REG_MHL_COC_CTL1, 0x07
+ );
+ break;
+ case CM_DISCONNECTED:
+ break;
+ default:
+ dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode);
+ break;
+ }
+
+ sii8620_set_auto_zone(ctx);
+
+ if (mode != CM_MHL1)
+ return;
+
+ sii8620_write_seq_static(ctx,
+ REG_MHL_DP_CTL0, 0xBC,
+ REG_MHL_DP_CTL1, 0xBB,
+ REG_MHL_DP_CTL3, 0x48,
+ REG_MHL_DP_CTL5, 0x39,
+ REG_MHL_DP_CTL2, 0x2A,
+ REG_MHL_DP_CTL6, 0x2A,
+ REG_MHL_DP_CTL7, 0x08
+ );
+}
+
+static void sii8620_disconnect(struct sii8620 *ctx)
+{
+ sii8620_disable_gen2_write_burst(ctx);
+ sii8620_stop_video(ctx);
+ msleep(50);
+ sii8620_cbus_reset(ctx);
+ sii8620_set_mode(ctx, CM_DISCONNECTED);
+ sii8620_write_seq_static(ctx,
+ REG_COC_CTL0, 0x40,
+ REG_CBUS3_CNVT, 0x84,
+ REG_COC_CTL14, 0x00,
+ REG_COC_CTL0, 0x40,
+ REG_HRXCTRL3, 0x07,
+ REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+ | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+ | BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
+ REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
+ | BIT_MHL_DP_CTL0_TX_OE_OVR,
+ REG_MHL_DP_CTL1, 0xBB,
+ REG_MHL_DP_CTL3, 0x48,
+ REG_MHL_DP_CTL5, 0x3F,
+ REG_MHL_DP_CTL2, 0x2F,
+ REG_MHL_DP_CTL6, 0x2A,
+ REG_MHL_DP_CTL7, 0x03
+ );
+ sii8620_disable_hpd(ctx);
+ sii8620_write_seq_static(ctx,
+ REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+ REG_MHL_COC_CTL1, 0x07,
+ REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+ REG_DISC_CTRL8, 0x00,
+ REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+ | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+ REG_INT_CTRL, 0x00,
+ REG_MSC_HEARTBEAT_CTRL, 0x27,
+ REG_DISC_CTRL1, 0x25,
+ REG_CBUS_DISC_INTR0, (u8)~BIT_RGND_READY_INT,
+ REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT,
+ REG_MDT_INT_1, 0xff,
+ REG_MDT_INT_1_MASK, 0x00,
+ REG_MDT_INT_0, 0xff,
+ REG_MDT_INT_0_MASK, 0x00,
+ REG_COC_INTR, 0xff,
+ REG_COC_INTR_MASK, 0x00,
+ REG_TRXINTH, 0xff,
+ REG_TRXINTMH, 0x00,
+ REG_CBUS_INT_0, 0xff,
+ REG_CBUS_INT_0_MASK, 0x00,
+ REG_CBUS_INT_1, 0xff,
+ REG_CBUS_INT_1_MASK, 0x00,
+ REG_EMSCINTR, 0xff,
+ REG_EMSCINTRMASK, 0x00,
+ REG_EMSCINTR1, 0xff,
+ REG_EMSCINTRMASK1, 0x00,
+ REG_INTR8, 0xff,
+ REG_INTR8_MASK, 0x00,
+ REG_TPI_INTR_ST0, 0xff,
+ REG_TPI_INTR_EN, 0x00,
+ REG_HDCP2X_INTR0, 0xff,
+ REG_HDCP2X_INTR0_MASK, 0x00,
+ REG_INTR9, 0xff,
+ REG_INTR9_MASK, 0x00,
+ REG_INTR3, 0xff,
+ REG_INTR3_MASK, 0x00,
+ REG_INTR5, 0xff,
+ REG_INTR5_MASK, 0x00,
+ REG_INTR2, 0xff,
+ REG_INTR2_MASK, 0x00,
+ );
+ memset(ctx->stat, 0, sizeof(ctx->stat));
+ memset(ctx->xstat, 0, sizeof(ctx->xstat));
+ memset(ctx->devcap, 0, sizeof(ctx->devcap));
+ memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap));
+ ctx->cbus_status = 0;
+ ctx->sink_type = SINK_NONE;
+ kfree(ctx->edid);
+ ctx->edid = NULL;
+ sii8620_mt_cleanup(ctx);
+}
+
+static void sii8620_mhl_disconnected(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+ REG_CBUS_MSC_COMPAT_CTRL,
+ BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN
+ );
+ sii8620_disconnect(ctx);
+}
+
+static void sii8620_irq_disc(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_CBUS_DISC_INTR0);
+
+ if (stat & VAL_CBUS_MHL_DISCON)
+ sii8620_mhl_disconnected(ctx);
+
+ if (stat & BIT_RGND_READY_INT) {
+ u8 stat2 = sii8620_readb(ctx, REG_DISC_STAT2);
+
+ if ((stat2 & MSK_DISC_STAT2_RGND) == VAL_RGND_1K) {
+ sii8620_mhl_discover(ctx);
+ } else {
+ sii8620_write_seq_static(ctx,
+ REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+ | BIT_DISC_CTRL9_NOMHL_EST
+ | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+ REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT
+ | BIT_CBUS_MHL3_DISCON_INT
+ | BIT_CBUS_MHL12_DISCON_INT
+ | BIT_NOT_MHL_EST_INT
+ );
+ }
+ }
+ if (stat & BIT_MHL_EST_INT)
+ sii8620_mhl_init(ctx);
+
+ sii8620_write(ctx, REG_CBUS_DISC_INTR0, stat);
+}
+
+static void sii8620_irq_g2wb(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_MDT_INT_0);
+
+ if (stat & BIT_MDT_IDLE_AFTER_HAWB_DISABLE)
+ dev_dbg(ctx->dev, "HAWB idle\n");
+
+ sii8620_write(ctx, REG_MDT_INT_0, stat);
+}
+
+static void sii8620_status_changed_dcap(struct sii8620 *ctx)
+{
+ if (ctx->stat[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY) {
+ sii8620_set_mode(ctx, CM_MHL1);
+ sii8620_peer_specific_init(ctx);
+ sii8620_write(ctx, REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE
+ | BIT_INTR9_EDID_DONE | BIT_INTR9_EDID_ERROR);
+ }
+}
+
+static void sii8620_status_changed_path(struct sii8620 *ctx)
+{
+ if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) {
+ sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+ MHL_DST_LM_CLK_MODE_NORMAL
+ | MHL_DST_LM_PATH_ENABLED);
+ sii8620_mt_read_devcap(ctx, false);
+ } else {
+ sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+ MHL_DST_LM_CLK_MODE_NORMAL);
+ }
+}
+
+static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
+{
+ u8 st[MHL_DST_SIZE], xst[MHL_XDS_SIZE];
+
+ sii8620_read_buf(ctx, REG_MHL_STAT_0, st, MHL_DST_SIZE);
+ sii8620_read_buf(ctx, REG_MHL_EXTSTAT_0, xst, MHL_XDS_SIZE);
+
+ sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
+ sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
+
+ if (st[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY)
+ sii8620_status_changed_dcap(ctx);
+
+ if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
+ sii8620_status_changed_path(ctx);
+}
+
+static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
+{
+ u8 ints[MHL_INT_SIZE];
+
+ sii8620_read_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
+ sii8620_write_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
+}
+
+static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
+{
+ struct device *dev = ctx->dev;
+
+ if (list_empty(&ctx->mt_queue)) {
+ dev_err(dev, "unexpected MSC MT response\n");
+ return NULL;
+ }
+
+ return list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
+}
+
+static void sii8620_msc_mt_done(struct sii8620 *ctx)
+{
+ struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
+
+ if (!msg)
+ return;
+
+ msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0);
+ ctx->mt_state = MT_STATE_DONE;
+}
+
+static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx)
+{
+ struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
+ u8 buf[2];
+
+ if (!msg)
+ return;
+
+ sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2);
+
+ switch (buf[0]) {
+ case MHL_MSC_MSG_RAPK:
+ msg->ret = buf[1];
+ ctx->mt_state = MT_STATE_DONE;
+ break;
+ default:
+ dev_err(ctx->dev, "%s message type %d,%d not supported",
+ __func__, buf[0], buf[1]);
+ }
+}
+
+static void sii8620_irq_msc(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_CBUS_INT_0);
+
+ if (stat & ~BIT_CBUS_HPD_CHG)
+ sii8620_write(ctx, REG_CBUS_INT_0, stat & ~BIT_CBUS_HPD_CHG);
+
+ if (stat & BIT_CBUS_HPD_CHG) {
+ u8 cbus_stat = sii8620_readb(ctx, REG_CBUS_STATUS);
+
+ if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) {
+ sii8620_write(ctx, REG_CBUS_INT_0, BIT_CBUS_HPD_CHG);
+ } else {
+ stat ^= BIT_CBUS_STATUS_CBUS_HPD;
+ cbus_stat ^= BIT_CBUS_STATUS_CBUS_HPD;
+ }
+ ctx->cbus_status = cbus_stat;
+ }
+
+ if (stat & BIT_CBUS_MSC_MR_WRITE_STAT)
+ sii8620_msc_mr_write_stat(ctx);
+
+ if (stat & BIT_CBUS_MSC_MR_SET_INT)
+ sii8620_msc_mr_set_int(ctx);
+
+ if (stat & BIT_CBUS_MSC_MT_DONE)
+ sii8620_msc_mt_done(ctx);
+
+ if (stat & BIT_CBUS_MSC_MR_MSC_MSG)
+ sii8620_msc_mr_msc_msg(ctx);
+}
+
+static void sii8620_irq_coc(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_COC_INTR);
+
+ sii8620_write(ctx, REG_COC_INTR, stat);
+}
+
+static void sii8620_irq_merr(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_CBUS_INT_1);
+
+ sii8620_write(ctx, REG_CBUS_INT_1, stat);
+}
+
+static void sii8620_irq_edid(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_INTR9);
+
+ sii8620_write(ctx, REG_INTR9, stat);
+
+ if (stat & BIT_INTR9_DEVCAP_DONE)
+ ctx->mt_state = MT_STATE_DONE;
+}
+
+static void sii8620_scdt_high(struct sii8620 *ctx)
+{
+ sii8620_write_seq_static(ctx,
+ REG_INTR8_MASK, BIT_CEA_NEW_AVI | BIT_CEA_NEW_VSI,
+ REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI,
+ );
+}
+
+static void sii8620_scdt_low(struct sii8620 *ctx)
+{
+ sii8620_write(ctx, REG_TMDS_CSTAT_P3,
+ BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS |
+ BIT_TMDS_CSTAT_P3_CLR_AVI);
+
+ sii8620_stop_video(ctx);
+
+ sii8620_write(ctx, REG_INTR8_MASK, 0);
+}
+
+static void sii8620_irq_scdt(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_INTR5);
+
+ if (stat & BIT_INTR_SCDT_CHANGE) {
+ u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
+
+ if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
+ sii8620_scdt_high(ctx);
+ else
+ sii8620_scdt_low(ctx);
+ }
+
+ sii8620_write(ctx, REG_INTR5, stat);
+}
+
+static void sii8620_new_vsi(struct sii8620 *ctx)
+{
+ u8 vsif[11];
+
+ sii8620_write(ctx, REG_RX_HDMI_CTRL2,
+ VAL_RX_HDMI_CTRL2_DEFVAL |
+ BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI);
+ sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, vsif,
+ ARRAY_SIZE(vsif));
+}
+
+static void sii8620_new_avi(struct sii8620 *ctx)
+{
+ sii8620_write(ctx, REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL);
+ sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, ctx->avif,
+ ARRAY_SIZE(ctx->avif));
+}
+
+static void sii8620_irq_infr(struct sii8620 *ctx)
+{
+ u8 stat = sii8620_readb(ctx, REG_INTR8)
+ & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI);
+
+ sii8620_write(ctx, REG_INTR8, stat);
+
+ if (stat & BIT_CEA_NEW_VSI)
+ sii8620_new_vsi(ctx);
+
+ if (stat & BIT_CEA_NEW_AVI)
+ sii8620_new_avi(ctx);
+
+ if (stat & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI))
+ sii8620_start_video(ctx);
+}
+
+/* endian agnostic, non-volatile version of test_bit */
+static bool sii8620_test_bit(unsigned int nr, const u8 *addr)
+{
+ return 1 & (addr[nr / BITS_PER_BYTE] >> (nr % BITS_PER_BYTE));
+}
+
+static irqreturn_t sii8620_irq_thread(int irq, void *data)
+{
+ static const struct {
+ int bit;
+ void (*handler)(struct sii8620 *ctx);
+ } irq_vec[] = {
+ { BIT_FAST_INTR_STAT_DISC, sii8620_irq_disc },
+ { BIT_FAST_INTR_STAT_G2WB, sii8620_irq_g2wb },
+ { BIT_FAST_INTR_STAT_COC, sii8620_irq_coc },
+ { BIT_FAST_INTR_STAT_MSC, sii8620_irq_msc },
+ { BIT_FAST_INTR_STAT_MERR, sii8620_irq_merr },
+ { BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid },
+ { BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt },
+ { BIT_FAST_INTR_STAT_INFR, sii8620_irq_infr },
+ };
+ struct sii8620 *ctx = data;
+ u8 stats[LEN_FAST_INTR_STAT];
+ int i, ret;
+
+ mutex_lock(&ctx->lock);
+
+ sii8620_read_buf(ctx, REG_FAST_INTR_STAT, stats, ARRAY_SIZE(stats));
+ for (i = 0; i < ARRAY_SIZE(irq_vec); ++i)
+ if (sii8620_test_bit(irq_vec[i].bit, stats))
+ irq_vec[i].handler(ctx);
+
+ sii8620_mt_work(ctx);
+
+ ret = sii8620_clear_error(ctx);
+ if (ret) {
+ dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret);
+ sii8620_mhl_disconnected(ctx);
+ }
+ mutex_unlock(&ctx->lock);
+
+ return IRQ_HANDLED;
+}
+
+static void sii8620_cable_in(struct sii8620 *ctx)
+{
+ struct device *dev = ctx->dev;
+ u8 ver[5];
+ int ret;
+
+ ret = sii8620_hw_on(ctx);
+ if (ret) {
+ dev_err(dev, "Error powering on, %d.\n", ret);
+ return;
+ }
+ sii8620_hw_reset(ctx);
+
+ sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
+ ret = sii8620_clear_error(ctx);
+ if (ret) {
+ dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
+ return;
+ }
+
+ dev_info(dev, "ChipID %02x%02x:%02x%02x rev %02x.\n", ver[1], ver[0],
+ ver[3], ver[2], ver[4]);
+
+ sii8620_write(ctx, REG_DPD,
+ BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN);
+
+ sii8620_xtal_set_rate(ctx);
+ sii8620_disconnect(ctx);
+
+ sii8620_write_seq_static(ctx,
+ REG_MHL_CBUS_CTL0, VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG
+ | VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734,
+ REG_MHL_CBUS_CTL1, VAL_MHL_CBUS_CTL1_1115_OHM,
+ REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN,
+ );
+
+ ret = sii8620_clear_error(ctx);
+ if (ret) {
+ dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
+ return;
+ }
+
+ enable_irq(to_i2c_client(ctx->dev)->irq);
+}
+
+static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct sii8620, bridge);
+}
+
+static bool sii8620_mode_fixup(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct sii8620 *ctx = bridge_to_sii8620(bridge);
+ bool ret = false;
+ int max_clock = 74250;
+
+ mutex_lock(&ctx->lock);
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ goto out;
+
+ if (ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL)
+ max_clock = 300000;
+
+ ret = mode->clock <= max_clock;
+
+out:
+ mutex_unlock(&ctx->lock);
+
+ return ret;
+}
+
+static const struct drm_bridge_funcs sii8620_bridge_funcs = {
+ .mode_fixup = sii8620_mode_fixup,
+};
+
+static int sii8620_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct sii8620 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->dev = dev;
+ mutex_init(&ctx->lock);
+ INIT_LIST_HEAD(&ctx->mt_queue);
+
+ ctx->clk_xtal = devm_clk_get(dev, "xtal");
+ if (IS_ERR(ctx->clk_xtal)) {
+ dev_err(dev, "failed to get xtal clock from DT\n");
+ return PTR_ERR(ctx->clk_xtal);
+ }
+
+ if (!client->irq) {
+ dev_err(dev, "no irq provided\n");
+ return -EINVAL;
+ }
+ irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ sii8620_irq_thread,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "sii8620", ctx);
+
+ ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->gpio_reset)) {
+ dev_err(dev, "failed to get reset gpio from DT\n");
+ return PTR_ERR(ctx->gpio_reset);
+ }
+
+ ctx->supplies[0].supply = "cvcc10";
+ ctx->supplies[1].supply = "iovcc18";
+ ret = devm_regulator_bulk_get(dev, 2, ctx->supplies);
+ if (ret)
+ return ret;
+
+ i2c_set_clientdata(client, ctx);
+
+ ctx->bridge.funcs = &sii8620_bridge_funcs;
+ ctx->bridge.of_node = dev->of_node;
+ drm_bridge_add(&ctx->bridge);
+
+ sii8620_cable_in(ctx);
+
+ return 0;
+}
+
+static int sii8620_remove(struct i2c_client *client)
+{
+ struct sii8620 *ctx = i2c_get_clientdata(client);
+
+ disable_irq(to_i2c_client(ctx->dev)->irq);
+ drm_bridge_remove(&ctx->bridge);
+ sii8620_hw_off(ctx);
+
+ return 0;
+}
+
+static const struct of_device_id sii8620_dt_match[] = {
+ { .compatible = "sil,sii8620" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sii8620_dt_match);
+
+static const struct i2c_device_id sii8620_id[] = {
+ { "sii8620", 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, sii8620_id);
+static struct i2c_driver sii8620_driver = {
+ .driver = {
+ .name = "sii8620",
+ .of_match_table = of_match_ptr(sii8620_dt_match),
+ },
+ .probe = sii8620_probe,
+ .remove = sii8620_remove,
+ .id_table = sii8620_id,
+};
+
+module_i2c_driver(sii8620_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.h b/drivers/gpu/drm/bridge/sil-sii8620.h
new file mode 100644
index 000000000000..6ff616a4f6ce
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sil-sii8620.h
@@ -0,0 +1,1517 @@
+/*
+ * Registers of Silicon Image SiI8620 Mobile HD Transmitter
+ *
+ * Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * Based on MHL driver for Android devices.
+ * Copyright (C) 2013-2014 Silicon Image, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SIL_SII8620_H__
+#define __SIL_SII8620_H__
+
+/* Vendor ID Low byte, default value: 0x01 */
+#define REG_VND_IDL 0x0000
+
+/* Vendor ID High byte, default value: 0x00 */
+#define REG_VND_IDH 0x0001
+
+/* Device ID Low byte, default value: 0x60 */
+#define REG_DEV_IDL 0x0002
+
+/* Device ID High byte, default value: 0x86 */
+#define REG_DEV_IDH 0x0003
+
+/* Device Revision, default value: 0x10 */
+#define REG_DEV_REV 0x0004
+
+/* OTP DBYTE510, default value: 0x00 */
+#define REG_OTP_DBYTE510 0x0006
+
+/* System Control #1, default value: 0x00 */
+#define REG_SYS_CTRL1 0x0008
+#define BIT_SYS_CTRL1_OTPVMUTEOVR_SET BIT(7)
+#define BIT_SYS_CTRL1_VSYNCPIN BIT(6)
+#define BIT_SYS_CTRL1_OTPADROPOVR_SET BIT(5)
+#define BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD BIT(4)
+#define BIT_SYS_CTRL1_OTP2XVOVR_EN BIT(3)
+#define BIT_SYS_CTRL1_OTP2XAOVR_EN BIT(2)
+#define BIT_SYS_CTRL1_TX_CTRL_HDMI BIT(1)
+#define BIT_SYS_CTRL1_OTPAMUTEOVR_SET BIT(0)
+
+/* System Control DPD, default value: 0x90 */
+#define REG_DPD 0x000b
+#define BIT_DPD_PWRON_PLL BIT(7)
+#define BIT_DPD_PDNTX12 BIT(6)
+#define BIT_DPD_PDNRX12 BIT(5)
+#define BIT_DPD_OSC_EN BIT(4)
+#define BIT_DPD_PWRON_HSIC BIT(3)
+#define BIT_DPD_PDIDCK_N BIT(2)
+#define BIT_DPD_PD_MHL_CLK_N BIT(1)
+
+/* Dual link Control, default value: 0x00 */
+#define REG_DCTL 0x000d
+#define BIT_DCTL_TDM_LCLK_PHASE BIT(7)
+#define BIT_DCTL_HSIC_CLK_PHASE BIT(6)
+#define BIT_DCTL_CTS_TCK_PHASE BIT(5)
+#define BIT_DCTL_EXT_DDC_SEL BIT(4)
+#define BIT_DCTL_TRANSCODE BIT(3)
+#define BIT_DCTL_HSIC_RX_STROBE_PHASE BIT(2)
+#define BIT_DCTL_HSIC_TX_BIST_START_SEL BIT(1)
+#define BIT_DCTL_TCLKNX_PHASE BIT(0)
+
+/* PWD Software Reset, default value: 0x20 */
+#define REG_PWD_SRST 0x000e
+#define BIT_PWD_SRST_COC_DOC_RST BIT(7)
+#define BIT_PWD_SRST_CBUS_RST_SW BIT(6)
+#define BIT_PWD_SRST_CBUS_RST_SW_EN BIT(5)
+#define BIT_PWD_SRST_MHLFIFO_RST BIT(4)
+#define BIT_PWD_SRST_CBUS_RST BIT(3)
+#define BIT_PWD_SRST_SW_RST_AUTO BIT(2)
+#define BIT_PWD_SRST_HDCP2X_SW_RST BIT(1)
+#define BIT_PWD_SRST_SW_RST BIT(0)
+
+/* AKSV_1, default value: 0x00 */
+#define REG_AKSV_1 0x001d
+
+/* Video H Resolution #1, default value: 0x00 */
+#define REG_H_RESL 0x003a
+
+/* Video Mode, default value: 0x00 */
+#define REG_VID_MODE 0x004a
+#define BIT_VID_MODE_M1080P BIT(6)
+
+/* Video Input Mode, default value: 0xc0 */
+#define REG_VID_OVRRD 0x0051
+#define BIT_VID_OVRRD_PP_AUTO_DISABLE BIT(7)
+#define BIT_VID_OVRRD_M1080P_OVRRD BIT(6)
+#define BIT_VID_OVRRD_MINIVSYNC_ON BIT(5)
+#define BIT_VID_OVRRD_3DCONV_EN_FRAME_PACK BIT(4)
+#define BIT_VID_OVRRD_ENABLE_AUTO_PATH_EN BIT(3)
+#define BIT_VID_OVRRD_ENRGB2YCBCR_OVRRD BIT(2)
+#define BIT_VID_OVRRD_ENDOWNSAMPLE_OVRRD BIT(0)
+
+/* I2C Address reassignment, default value: 0x00 */
+#define REG_PAGE_MHLSPEC_ADDR 0x0057
+#define REG_PAGE7_ADDR 0x0058
+#define REG_PAGE8_ADDR 0x005c
+
+/* Fast Interrupt Status, default value: 0x00 */
+#define REG_FAST_INTR_STAT 0x005f
+#define LEN_FAST_INTR_STAT 7
+#define BIT_FAST_INTR_STAT_TIMR 8
+#define BIT_FAST_INTR_STAT_INT2 9
+#define BIT_FAST_INTR_STAT_DDC 10
+#define BIT_FAST_INTR_STAT_SCDT 11
+#define BIT_FAST_INTR_STAT_INFR 13
+#define BIT_FAST_INTR_STAT_EDID 14
+#define BIT_FAST_INTR_STAT_HDCP 15
+#define BIT_FAST_INTR_STAT_MSC 16
+#define BIT_FAST_INTR_STAT_MERR 17
+#define BIT_FAST_INTR_STAT_G2WB 18
+#define BIT_FAST_INTR_STAT_G2WB_ERR 19
+#define BIT_FAST_INTR_STAT_DISC 28
+#define BIT_FAST_INTR_STAT_BLOCK 30
+#define BIT_FAST_INTR_STAT_LTRN 31
+#define BIT_FAST_INTR_STAT_HDCP2 32
+#define BIT_FAST_INTR_STAT_TDM 42
+#define BIT_FAST_INTR_STAT_COC 51
+
+/* GPIO Control, default value: 0x15 */
+#define REG_GPIO_CTRL1 0x006e
+#define BIT_CTRL1_GPIO_I_8 BIT(5)
+#define BIT_CTRL1_GPIO_OEN_8 BIT(4)
+#define BIT_CTRL1_GPIO_I_7 BIT(3)
+#define BIT_CTRL1_GPIO_OEN_7 BIT(2)
+#define BIT_CTRL1_GPIO_I_6 BIT(1)
+#define BIT_CTRL1_GPIO_OEN_6 BIT(0)
+
+/* Interrupt Control, default value: 0x06 */
+#define REG_INT_CTRL 0x006f
+#define BIT_INT_CTRL_SOFTWARE_WP BIT(7)
+#define BIT_INT_CTRL_INTR_OD BIT(2)
+#define BIT_INT_CTRL_INTR_POLARITY BIT(1)
+
+/* Interrupt State, default value: 0x00 */
+#define REG_INTR_STATE 0x0070
+#define BIT_INTR_STATE_INTR_STATE BIT(0)
+
+/* Interrupt Source #1, default value: 0x00 */
+#define REG_INTR1 0x0071
+
+/* Interrupt Source #2, default value: 0x00 */
+#define REG_INTR2 0x0072
+
+/* Interrupt Source #3, default value: 0x01 */
+#define REG_INTR3 0x0073
+#define BIT_DDC_CMD_DONE BIT(3)
+
+/* Interrupt Source #5, default value: 0x00 */
+#define REG_INTR5 0x0074
+
+/* Interrupt #1 Mask, default value: 0x00 */
+#define REG_INTR1_MASK 0x0075
+
+/* Interrupt #2 Mask, default value: 0x00 */
+#define REG_INTR2_MASK 0x0076
+
+/* Interrupt #3 Mask, default value: 0x00 */
+#define REG_INTR3_MASK 0x0077
+
+/* Interrupt #5 Mask, default value: 0x00 */
+#define REG_INTR5_MASK 0x0078
+#define BIT_INTR_SCDT_CHANGE BIT(0)
+
+/* Hot Plug Connection Control, default value: 0x45 */
+#define REG_HPD_CTRL 0x0079
+#define BIT_HPD_CTRL_HPD_DS_SIGNAL BIT(7)
+#define BIT_HPD_CTRL_HPD_OUT_OD_EN BIT(6)
+#define BIT_HPD_CTRL_HPD_HIGH BIT(5)
+#define BIT_HPD_CTRL_HPD_OUT_OVR_EN BIT(4)
+#define BIT_HPD_CTRL_GPIO_I_1 BIT(3)
+#define BIT_HPD_CTRL_GPIO_OEN_1 BIT(2)
+#define BIT_HPD_CTRL_GPIO_I_0 BIT(1)
+#define BIT_HPD_CTRL_GPIO_OEN_0 BIT(0)
+
+/* GPIO Control, default value: 0x55 */
+#define REG_GPIO_CTRL 0x007a
+#define BIT_CTRL_GPIO_I_5 BIT(7)
+#define BIT_CTRL_GPIO_OEN_5 BIT(6)
+#define BIT_CTRL_GPIO_I_4 BIT(5)
+#define BIT_CTRL_GPIO_OEN_4 BIT(4)
+#define BIT_CTRL_GPIO_I_3 BIT(3)
+#define BIT_CTRL_GPIO_OEN_3 BIT(2)
+#define BIT_CTRL_GPIO_I_2 BIT(1)
+#define BIT_CTRL_GPIO_OEN_2 BIT(0)
+
+/* Interrupt Source 7, default value: 0x00 */
+#define REG_INTR7 0x007b
+
+/* Interrupt Source 8, default value: 0x00 */
+#define REG_INTR8 0x007c
+
+/* Interrupt #7 Mask, default value: 0x00 */
+#define REG_INTR7_MASK 0x007d
+
+/* Interrupt #8 Mask, default value: 0x00 */
+#define REG_INTR8_MASK 0x007e
+#define BIT_CEA_NEW_VSI BIT(2)
+#define BIT_CEA_NEW_AVI BIT(1)
+
+/* IEEE, default value: 0x10 */
+#define REG_TMDS_CCTRL 0x0080
+#define BIT_TMDS_CCTRL_TMDS_OE BIT(4)
+
+/* TMDS Control #4, default value: 0x02 */
+#define REG_TMDS_CTRL4 0x0085
+#define BIT_TMDS_CTRL4_SCDT_CKDT_SEL BIT(1)
+#define BIT_TMDS_CTRL4_TX_EN_BY_SCDT BIT(0)
+
+/* BIST CNTL, default value: 0x00 */
+#define REG_BIST_CTRL 0x00bb
+#define BIT_RXBIST_VGB_EN BIT(7)
+#define BIT_TXBIST_VGB_EN BIT(6)
+#define BIT_BIST_START_SEL BIT(5)
+#define BIT_BIST_START_BIT BIT(4)
+#define BIT_BIST_ALWAYS_ON BIT(3)
+#define BIT_BIST_TRANS BIT(2)
+#define BIT_BIST_RESET BIT(1)
+#define BIT_BIST_EN BIT(0)
+
+/* BIST DURATION0, default value: 0x00 */
+#define REG_BIST_TEST_SEL 0x00bd
+#define MSK_BIST_TEST_SEL_BIST_PATT_SEL 0x0f
+
+/* BIST VIDEO_MODE, default value: 0x00 */
+#define REG_BIST_VIDEO_MODE 0x00be
+#define MSK_BIST_VIDEO_MODE_BIST_VIDEO_MODE_3_0 0x0f
+
+/* BIST DURATION0, default value: 0x00 */
+#define REG_BIST_DURATION_0 0x00bf
+
+/* BIST DURATION1, default value: 0x00 */
+#define REG_BIST_DURATION_1 0x00c0
+
+/* BIST DURATION2, default value: 0x00 */
+#define REG_BIST_DURATION_2 0x00c1
+
+/* BIST 8BIT_PATTERN, default value: 0x00 */
+#define REG_BIST_8BIT_PATTERN 0x00c2
+
+/* LM DDC, default value: 0x80 */
+#define REG_LM_DDC 0x00c7
+#define BIT_LM_DDC_SW_TPI_EN_DISABLED BIT(7)
+
+#define BIT_LM_DDC_VIDEO_MUTE_EN BIT(5)
+#define BIT_LM_DDC_DDC_TPI_SW BIT(2)
+#define BIT_LM_DDC_DDC_GRANT BIT(1)
+#define BIT_LM_DDC_DDC_GPU_REQUEST BIT(0)
+
+/* DDC I2C Manual, default value: 0x03 */
+#define REG_DDC_MANUAL 0x00ec
+#define BIT_DDC_MANUAL_MAN_DDC BIT(7)
+#define BIT_DDC_MANUAL_VP_SEL BIT(6)
+#define BIT_DDC_MANUAL_DSDA BIT(5)
+#define BIT_DDC_MANUAL_DSCL BIT(4)
+#define BIT_DDC_MANUAL_GCP_HW_CTL_EN BIT(3)
+#define BIT_DDC_MANUAL_DDCM_ABORT_WP BIT(2)
+#define BIT_DDC_MANUAL_IO_DSDA BIT(1)
+#define BIT_DDC_MANUAL_IO_DSCL BIT(0)
+
+/* DDC I2C Target Slave Address, default value: 0x00 */
+#define REG_DDC_ADDR 0x00ed
+#define MSK_DDC_ADDR_DDC_ADDR 0xfe
+
+/* DDC I2C Target Segment Address, default value: 0x00 */
+#define REG_DDC_SEGM 0x00ee
+
+/* DDC I2C Target Offset Address, default value: 0x00 */
+#define REG_DDC_OFFSET 0x00ef
+
+/* DDC I2C Data In count #1, default value: 0x00 */
+#define REG_DDC_DIN_CNT1 0x00f0
+
+/* DDC I2C Data In count #2, default value: 0x00 */
+#define REG_DDC_DIN_CNT2 0x00f1
+#define MSK_DDC_DIN_CNT2_DDC_DIN_CNT_9_8 0x03
+
+/* DDC I2C Status, default value: 0x04 */
+#define REG_DDC_STATUS 0x00f2
+#define BIT_DDC_STATUS_DDC_BUS_LOW BIT(6)
+#define BIT_DDC_STATUS_DDC_NO_ACK BIT(5)
+#define BIT_DDC_STATUS_DDC_I2C_IN_PROG BIT(4)
+#define BIT_DDC_STATUS_DDC_FIFO_FULL BIT(3)
+#define BIT_DDC_STATUS_DDC_FIFO_EMPTY BIT(2)
+#define BIT_DDC_STATUS_DDC_FIFO_READ_IN_SUE BIT(1)
+#define BIT_DDC_STATUS_DDC_FIFO_WRITE_IN_USE BIT(0)
+
+/* DDC I2C Command, default value: 0x70 */
+#define REG_DDC_CMD 0x00f3
+#define BIT_DDC_CMD_HDCP_DDC_EN BIT(6)
+#define BIT_DDC_CMD_SDA_DEL_EN BIT(5)
+#define BIT_DDC_CMD_DDC_FLT_EN BIT(4)
+
+#define MSK_DDC_CMD_DDC_CMD 0x0f
+#define VAL_DDC_CMD_ENH_DDC_READ_NO_ACK 0x04
+#define VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO 0x09
+#define VAL_DDC_CMD_DDC_CMD_ABORT 0x0f
+
+/* DDC I2C FIFO Data In/Out, default value: 0x00 */
+#define REG_DDC_DATA 0x00f4
+
+/* DDC I2C Data Out Counter, default value: 0x00 */
+#define REG_DDC_DOUT_CNT 0x00f5
+#define BIT_DDC_DOUT_CNT_DDC_DELAY_CNT_8 BIT(7)
+#define MSK_DDC_DOUT_CNT_DDC_DATA_OUT_CNT 0x1f
+
+/* DDC I2C Delay Count, default value: 0x14 */
+#define REG_DDC_DELAY_CNT 0x00f6
+
+/* Test Control, default value: 0x80 */
+#define REG_TEST_TXCTRL 0x00f7
+#define BIT_TEST_TXCTRL_RCLK_REF_SEL BIT(7)
+#define BIT_TEST_TXCTRL_PCLK_REF_SEL BIT(6)
+#define MSK_TEST_TXCTRL_BYPASS_PLL_CLK 0x3c
+#define BIT_TEST_TXCTRL_HDMI_MODE BIT(1)
+#define BIT_TEST_TXCTRL_TST_PLLCK BIT(0)
+
+/* CBUS Address, default value: 0x00 */
+#define REG_PAGE_CBUS_ADDR 0x00f8
+
+/* I2C Device Address re-assignment */
+#define REG_PAGE1_ADDR 0x00fc
+#define REG_PAGE2_ADDR 0x00fd
+#define REG_PAGE3_ADDR 0x00fe
+#define REG_HW_TPI_ADDR 0x00ff
+
+/* USBT CTRL0, default value: 0x00 */
+#define REG_UTSRST 0x0100
+#define BIT_UTSRST_FC_SRST BIT(5)
+#define BIT_UTSRST_KEEPER_SRST BIT(4)
+#define BIT_UTSRST_HTX_SRST BIT(3)
+#define BIT_UTSRST_TRX_SRST BIT(2)
+#define BIT_UTSRST_TTX_SRST BIT(1)
+#define BIT_UTSRST_HRX_SRST BIT(0)
+
+/* HSIC RX Control3, default value: 0x07 */
+#define REG_HRXCTRL3 0x0104
+#define MSK_HRXCTRL3_HRX_AFFCTRL 0xf0
+#define BIT_HRXCTRL3_HRX_OUT_EN BIT(2)
+#define BIT_HRXCTRL3_STATUS_EN BIT(1)
+#define BIT_HRXCTRL3_HRX_STAY_RESET BIT(0)
+
+/* HSIC RX INT Registers */
+#define REG_HRXINTL 0x0111
+#define REG_HRXINTH 0x0112
+
+/* TDM TX NUMBITS, default value: 0x0c */
+#define REG_TTXNUMB 0x0116
+#define MSK_TTXNUMB_TTX_AFFCTRL_3_0 0xf0
+#define BIT_TTXNUMB_TTX_COM1_AT_SYNC_WAIT BIT(3)
+#define MSK_TTXNUMB_TTX_NUMBPS_2_0 0x07
+
+/* TDM TX NUMSPISYM, default value: 0x04 */
+#define REG_TTXSPINUMS 0x0117
+
+/* TDM TX NUMHSICSYM, default value: 0x14 */
+#define REG_TTXHSICNUMS 0x0118
+
+/* TDM TX NUMTOTSYM, default value: 0x18 */
+#define REG_TTXTOTNUMS 0x0119
+
+/* TDM TX INT Low, default value: 0x00 */
+#define REG_TTXINTL 0x0136
+#define BIT_TTXINTL_TTX_INTR7 BIT(7)
+#define BIT_TTXINTL_TTX_INTR6 BIT(6)
+#define BIT_TTXINTL_TTX_INTR5 BIT(5)
+#define BIT_TTXINTL_TTX_INTR4 BIT(4)
+#define BIT_TTXINTL_TTX_INTR3 BIT(3)
+#define BIT_TTXINTL_TTX_INTR2 BIT(2)
+#define BIT_TTXINTL_TTX_INTR1 BIT(1)
+#define BIT_TTXINTL_TTX_INTR0 BIT(0)
+
+/* TDM TX INT High, default value: 0x00 */
+#define REG_TTXINTH 0x0137
+#define BIT_TTXINTH_TTX_INTR15 BIT(7)
+#define BIT_TTXINTH_TTX_INTR14 BIT(6)
+#define BIT_TTXINTH_TTX_INTR13 BIT(5)
+#define BIT_TTXINTH_TTX_INTR12 BIT(4)
+#define BIT_TTXINTH_TTX_INTR11 BIT(3)
+#define BIT_TTXINTH_TTX_INTR10 BIT(2)
+#define BIT_TTXINTH_TTX_INTR9 BIT(1)
+#define BIT_TTXINTH_TTX_INTR8 BIT(0)
+
+/* TDM RX Control, default value: 0x1c */
+#define REG_TRXCTRL 0x013b
+#define BIT_TRXCTRL_TRX_CLR_WVALLOW BIT(4)
+#define BIT_TRXCTRL_TRX_FROM_SE_COC BIT(3)
+#define MSK_TRXCTRL_TRX_NUMBPS_2_0 0x07
+
+/* TDM RX NUMSPISYM, default value: 0x04 */
+#define REG_TRXSPINUMS 0x013c
+
+/* TDM RX NUMHSICSYM, default value: 0x14 */
+#define REG_TRXHSICNUMS 0x013d
+
+/* TDM RX NUMTOTSYM, default value: 0x18 */
+#define REG_TRXTOTNUMS 0x013e
+
+/* TDM RX Status 2nd, default value: 0x00 */
+#define REG_TRXSTA2 0x015c
+
+/* TDM RX INT Low, default value: 0x00 */
+#define REG_TRXINTL 0x0163
+
+/* TDM RX INT High, default value: 0x00 */
+#define REG_TRXINTH 0x0164
+
+/* TDM RX INTMASK High, default value: 0x00 */
+#define REG_TRXINTMH 0x0166
+
+/* HSIC TX CRTL, default value: 0x00 */
+#define REG_HTXCTRL 0x0169
+#define BIT_HTXCTRL_HTX_ALLSBE_SOP BIT(4)
+#define BIT_HTXCTRL_HTX_RGDINV_USB BIT(3)
+#define BIT_HTXCTRL_HTX_RSPTDM_BUSY BIT(2)
+#define BIT_HTXCTRL_HTX_DRVCONN1 BIT(1)
+#define BIT_HTXCTRL_HTX_DRVRST1 BIT(0)
+
+/* HSIC TX INT Low, default value: 0x00 */
+#define REG_HTXINTL 0x017d
+
+/* HSIC TX INT High, default value: 0x00 */
+#define REG_HTXINTH 0x017e
+
+/* HSIC Keeper, default value: 0x00 */
+#define REG_KEEPER 0x0181
+#define MSK_KEEPER_KEEPER_MODE_1_0 0x03
+
+/* HSIC Flow Control General, default value: 0x02 */
+#define REG_FCGC 0x0183
+#define BIT_FCGC_HSIC_FC_HOSTMODE BIT(1)
+#define BIT_FCGC_HSIC_FC_ENABLE BIT(0)
+
+/* HSIC Flow Control CTR13, default value: 0xfc */
+#define REG_FCCTR13 0x0191
+
+/* HSIC Flow Control CTR14, default value: 0xff */
+#define REG_FCCTR14 0x0192
+
+/* HSIC Flow Control CTR15, default value: 0xff */
+#define REG_FCCTR15 0x0193
+
+/* HSIC Flow Control CTR50, default value: 0x03 */
+#define REG_FCCTR50 0x01b6
+
+/* HSIC Flow Control INTR0, default value: 0x00 */
+#define REG_FCINTR0 0x01ec
+#define REG_FCINTR1 0x01ed
+#define REG_FCINTR2 0x01ee
+#define REG_FCINTR3 0x01ef
+#define REG_FCINTR4 0x01f0
+#define REG_FCINTR5 0x01f1
+#define REG_FCINTR6 0x01f2
+#define REG_FCINTR7 0x01f3
+
+/* TDM Low Latency, default value: 0x20 */
+#define REG_TDMLLCTL 0x01fc
+#define MSK_TDMLLCTL_TRX_LL_SEL_MANUAL 0xc0
+#define MSK_TDMLLCTL_TRX_LL_SEL_MODE 0x30
+#define MSK_TDMLLCTL_TTX_LL_SEL_MANUAL 0x0c
+#define BIT_TDMLLCTL_TTX_LL_TIE_LOW BIT(1)
+#define BIT_TDMLLCTL_TTX_LL_SEL_MODE BIT(0)
+
+/* TMDS 0 Clock Control, default value: 0x10 */
+#define REG_TMDS0_CCTRL1 0x0210
+#define MSK_TMDS0_CCTRL1_TEST_SEL 0xc0
+#define MSK_TMDS0_CCTRL1_CLK1X_CTL 0x30
+
+/* TMDS Clock Enable, default value: 0x00 */
+#define REG_TMDS_CLK_EN 0x0211
+#define BIT_TMDS_CLK_EN_CLK_EN BIT(0)
+
+/* TMDS Channel Enable, default value: 0x00 */
+#define REG_TMDS_CH_EN 0x0212
+#define BIT_TMDS_CH_EN_CH0_EN BIT(4)
+#define BIT_TMDS_CH_EN_CH12_EN BIT(0)
+
+/* BGR_BIAS, default value: 0x07 */
+#define REG_BGR_BIAS 0x0215
+#define BIT_BGR_BIAS_BGR_EN BIT(7)
+#define MSK_BGR_BIAS_BIAS_BGR_D 0x0f
+
+/* TMDS 0 Digital I2C BW, default value: 0x0a */
+#define REG_ALICE0_BW_I2C 0x0231
+
+/* TMDS 0 Digital Zone Control, default value: 0xe0 */
+#define REG_ALICE0_ZONE_CTRL 0x024c
+#define BIT_ALICE0_ZONE_CTRL_ICRST_N BIT(7)
+#define BIT_ALICE0_ZONE_CTRL_USE_INT_DIV20 BIT(6)
+#define MSK_ALICE0_ZONE_CTRL_SZONE_I2C 0x30
+#define MSK_ALICE0_ZONE_CTRL_ZONE_CTRL 0x0f
+
+/* TMDS 0 Digital PLL Mode Control, default value: 0x00 */
+#define REG_ALICE0_MODE_CTRL 0x024d
+#define MSK_ALICE0_MODE_CTRL_PLL_MODE_I2C 0x0c
+#define MSK_ALICE0_MODE_CTRL_DIV20_CTRL 0x03
+
+/* MHL Tx Control 6th, default value: 0xa0 */
+#define REG_MHLTX_CTL6 0x0285
+#define MSK_MHLTX_CTL6_EMI_SEL 0xe0
+#define MSK_MHLTX_CTL6_TX_CLK_SHAPE_9_8 0x03
+
+/* Packet Filter0, default value: 0x00 */
+#define REG_PKT_FILTER_0 0x0290
+#define BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT BIT(7)
+#define BIT_PKT_FILTER_0_DROP_CEA_CP_PKT BIT(6)
+#define BIT_PKT_FILTER_0_DROP_MPEG_PKT BIT(5)
+#define BIT_PKT_FILTER_0_DROP_SPIF_PKT BIT(4)
+#define BIT_PKT_FILTER_0_DROP_AIF_PKT BIT(3)
+#define BIT_PKT_FILTER_0_DROP_AVI_PKT BIT(2)
+#define BIT_PKT_FILTER_0_DROP_CTS_PKT BIT(1)
+#define BIT_PKT_FILTER_0_DROP_GCP_PKT BIT(0)
+
+/* Packet Filter1, default value: 0x00 */
+#define REG_PKT_FILTER_1 0x0291
+#define BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS BIT(7)
+#define BIT_PKT_FILTER_1_AVI_OVERRIDE_DIS BIT(6)
+#define BIT_PKT_FILTER_1_DROP_AUDIO_PKT BIT(3)
+#define BIT_PKT_FILTER_1_DROP_GEN2_PKT BIT(2)
+#define BIT_PKT_FILTER_1_DROP_GEN_PKT BIT(1)
+#define BIT_PKT_FILTER_1_DROP_VSIF_PKT BIT(0)
+
+/* TMDS Clock Status, default value: 0x10 */
+#define REG_TMDS_CSTAT_P3 0x02a0
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_CLR_MUTE BIT(7)
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_SET_MUTE BIT(6)
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_NEW_CP BIT(5)
+#define BIT_TMDS_CSTAT_P3_CLR_AVI BIT(3)
+#define BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS BIT(2)
+#define BIT_TMDS_CSTAT_P3_SCDT BIT(1)
+#define BIT_TMDS_CSTAT_P3_CKDT BIT(0)
+
+/* RX_HDMI Control, default value: 0x10 */
+#define REG_RX_HDMI_CTRL0 0x02a1
+#define BIT_RX_HDMI_CTRL0_BYP_DVIFILT_SYNC BIT(5)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_EN_ITSELF_CLR BIT(4)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_SW_VALUE BIT(3)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_OVERWRITE BIT(2)
+#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE_EN BIT(1)
+#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE BIT(0)
+
+/* RX_HDMI Control, default value: 0x38 */
+#define REG_RX_HDMI_CTRL2 0x02a3
+#define MSK_RX_HDMI_CTRL2_IDLE_CNT 0xf0
+#define VAL_RX_HDMI_CTRL2_IDLE_CNT(n) ((n) << 4)
+#define BIT_RX_HDMI_CTRL2_USE_AV_MUTE BIT(3)
+#define BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI BIT(0)
+
+/* RX_HDMI Control, default value: 0x0f */
+#define REG_RX_HDMI_CTRL3 0x02a4
+#define MSK_RX_HDMI_CTRL3_PP_MODE_CLK_EN 0x0f
+
+/* rx_hdmi Clear Buffer, default value: 0x00 */
+#define REG_RX_HDMI_CLR_BUFFER 0x02ac
+#define MSK_RX_HDMI_CLR_BUFFER_AIF4VSI_CMP 0xc0
+#define BIT_RX_HDMI_CLR_BUFFER_USE_AIF4VSI BIT(5)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_W_AVI BIT(4)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_IEEE_ID_CHK_EN BIT(3)
+#define BIT_RX_HDMI_CLR_BUFFER_SWAP_VSI_IEEE_ID BIT(2)
+#define BIT_RX_HDMI_CLR_BUFFER_AIF_CLR_EN BIT(1)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN BIT(0)
+
+/* RX_HDMI VSI Header1, default value: 0x00 */
+#define REG_RX_HDMI_MON_PKT_HEADER1 0x02b8
+
+/* RX_HDMI VSI MHL Monitor, default value: 0x3c */
+#define REG_RX_HDMI_VSIF_MHL_MON 0x02d7
+
+#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_3D_FORMAT 0x3c
+#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_VID_FORMAT 0x03
+
+/* Interrupt Source 9, default value: 0x00 */
+#define REG_INTR9 0x02e0
+#define BIT_INTR9_EDID_ERROR BIT(6)
+#define BIT_INTR9_EDID_DONE BIT(5)
+#define BIT_INTR9_DEVCAP_DONE BIT(4)
+
+/* Interrupt 9 Mask, default value: 0x00 */
+#define REG_INTR9_MASK 0x02e1
+
+/* TPI CBUS Start, default value: 0x00 */
+#define REG_TPI_CBUS_START 0x02e2
+#define BIT_TPI_CBUS_START_RCP_REQ_START BIT(7)
+#define BIT_TPI_CBUS_START_RCPK_REPLY_START BIT(6)
+#define BIT_TPI_CBUS_START_RCPE_REPLY_START BIT(5)
+#define BIT_TPI_CBUS_START_PUT_LINK_MODE_START BIT(4)
+#define BIT_TPI_CBUS_START_PUT_DCAPCHG_START BIT(3)
+#define BIT_TPI_CBUS_START_PUT_DCAPRDY_START BIT(2)
+#define BIT_TPI_CBUS_START_GET_EDID_START_0 BIT(1)
+#define BIT_TPI_CBUS_START_GET_DEVCAP_START BIT(0)
+
+/* EDID Control, default value: 0x10 */
+#define REG_EDID_CTRL 0x02e3
+#define BIT_EDID_CTRL_EDID_PRIME_VALID BIT(7)
+#define BIT_EDID_CTRL_XDEVCAP_EN BIT(6)
+#define BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP BIT(5)
+#define BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO BIT(4)
+#define BIT_EDID_CTRL_EDID_FIFO_ACCESS_ALWAYS_EN BIT(3)
+#define BIT_EDID_CTRL_EDID_FIFO_BLOCK_SEL BIT(2)
+#define BIT_EDID_CTRL_INVALID_BKSV BIT(1)
+#define BIT_EDID_CTRL_EDID_MODE_EN BIT(0)
+
+/* EDID FIFO Addr, default value: 0x00 */
+#define REG_EDID_FIFO_ADDR 0x02e9
+
+/* EDID FIFO Write Data, default value: 0x00 */
+#define REG_EDID_FIFO_WR_DATA 0x02ea
+
+/* EDID/DEVCAP FIFO Internal Addr, default value: 0x00 */
+#define REG_EDID_FIFO_ADDR_MON 0x02eb
+
+/* EDID FIFO Read Data, default value: 0x00 */
+#define REG_EDID_FIFO_RD_DATA 0x02ec
+
+/* EDID DDC Segment Pointer, default value: 0x00 */
+#define REG_EDID_START_EXT 0x02ed
+
+/* TX IP BIST CNTL and Status, default value: 0x00 */
+#define REG_TX_IP_BIST_CNTLSTA 0x02f2
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_QUARTER_CLK_SEL BIT(6)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_DONE BIT(5)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_ON BIT(4)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_RUN BIT(3)
+#define BIT_TX_IP_BIST_CNTLSTA_TXCLK_HALF_SEL BIT(2)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_EN BIT(1)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_SEL BIT(0)
+
+/* TX IP BIST INST LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_INST_LOW 0x02f3
+#define REG_TX_IP_BIST_INST_HIGH 0x02f4
+
+/* TX IP BIST PATTERN LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_PAT_LOW 0x02f5
+#define REG_TX_IP_BIST_PAT_HIGH 0x02f6
+
+/* TX IP BIST CONFIGURE LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_CONF_LOW 0x02f7
+#define REG_TX_IP_BIST_CONF_HIGH 0x02f8
+
+/* E-MSC General Control, default value: 0x80 */
+#define REG_GENCTL 0x0300
+#define BIT_GENCTL_SPEC_TRANS_DIS BIT(7)
+#define BIT_GENCTL_DIS_XMIT_ERR_STATE BIT(6)
+#define BIT_GENCTL_SPI_MISO_EDGE BIT(5)
+#define BIT_GENCTL_SPI_MOSI_EDGE BIT(4)
+#define BIT_GENCTL_CLR_EMSC_RFIFO BIT(3)
+#define BIT_GENCTL_CLR_EMSC_XFIFO BIT(2)
+#define BIT_GENCTL_START_TRAIN_SEQ BIT(1)
+#define BIT_GENCTL_EMSC_EN BIT(0)
+
+/* E-MSC Comma ErrorCNT, default value: 0x03 */
+#define REG_COMMECNT 0x0305
+#define BIT_COMMECNT_I2C_TO_EMSC_EN BIT(7)
+#define MSK_COMMECNT_COMMA_CHAR_ERR_CNT 0x0f
+
+/* E-MSC RFIFO ByteCnt, default value: 0x00 */
+#define REG_EMSCRFIFOBCNTL 0x031a
+#define REG_EMSCRFIFOBCNTH 0x031b
+
+/* SPI Burst Cnt Status, default value: 0x00 */
+#define REG_SPIBURSTCNT 0x031e
+
+/* SPI Burst Status and SWRST, default value: 0x00 */
+#define REG_SPIBURSTSTAT 0x0322
+#define BIT_SPIBURSTSTAT_SPI_HDCPRST BIT(7)
+#define BIT_SPIBURSTSTAT_SPI_CBUSRST BIT(6)
+#define BIT_SPIBURSTSTAT_SPI_SRST BIT(5)
+#define BIT_SPIBURSTSTAT_EMSC_NORMAL_MODE BIT(0)
+
+/* E-MSC 1st Interrupt, default value: 0x00 */
+#define REG_EMSCINTR 0x0323
+#define BIT_EMSCINTR_EMSC_XFIFO_EMPTY BIT(7)
+#define BIT_EMSCINTR_EMSC_XMIT_ACK_TOUT BIT(6)
+#define BIT_EMSCINTR_EMSC_RFIFO_READ_ERR BIT(5)
+#define BIT_EMSCINTR_EMSC_XFIFO_WRITE_ERR BIT(4)
+#define BIT_EMSCINTR_EMSC_COMMA_CHAR_ERR BIT(3)
+#define BIT_EMSCINTR_EMSC_XMIT_DONE BIT(2)
+#define BIT_EMSCINTR_EMSC_XMIT_GNT_TOUT BIT(1)
+#define BIT_EMSCINTR_SPI_DVLD BIT(0)
+
+/* E-MSC Interrupt Mask, default value: 0x00 */
+#define REG_EMSCINTRMASK 0x0324
+
+/* I2C E-MSC XMIT FIFO Write Port, default value: 0x00 */
+#define REG_EMSC_XMIT_WRITE_PORT 0x032a
+
+/* I2C E-MSC RCV FIFO Write Port, default value: 0x00 */
+#define REG_EMSC_RCV_READ_PORT 0x032b
+
+/* E-MSC 2nd Interrupt, default value: 0x00 */
+#define REG_EMSCINTR1 0x032c
+#define BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR BIT(0)
+
+/* E-MSC Interrupt Mask, default value: 0x00 */
+#define REG_EMSCINTRMASK1 0x032d
+#define BIT_EMSCINTRMASK1_EMSC_INTRMASK1_0 BIT(0)
+
+/* MHL Top Ctl, default value: 0x00 */
+#define REG_MHL_TOP_CTL 0x0330
+#define BIT_MHL_TOP_CTL_MHL3_DOC_SEL BIT(7)
+#define BIT_MHL_TOP_CTL_MHL_PP_SEL BIT(6)
+#define MSK_MHL_TOP_CTL_IF_TIMING_CTL 0x03
+
+/* MHL DataPath 1st Ctl, default value: 0xbc */
+#define REG_MHL_DP_CTL0 0x0331
+#define BIT_MHL_DP_CTL0_DP_OE BIT(7)
+#define BIT_MHL_DP_CTL0_TX_OE_OVR BIT(6)
+#define MSK_MHL_DP_CTL0_TX_OE 0x3f
+
+/* MHL DataPath 2nd Ctl, default value: 0xbb */
+#define REG_MHL_DP_CTL1 0x0332
+#define MSK_MHL_DP_CTL1_CK_SWING_CTL 0xf0
+#define MSK_MHL_DP_CTL1_DT_SWING_CTL 0x0f
+
+/* MHL DataPath 3rd Ctl, default value: 0x2f */
+#define REG_MHL_DP_CTL2 0x0333
+#define BIT_MHL_DP_CTL2_CLK_BYPASS_EN BIT(7)
+#define MSK_MHL_DP_CTL2_DAMP_TERM_SEL 0x30
+#define MSK_MHL_DP_CTL2_CK_TERM_SEL 0x0c
+#define MSK_MHL_DP_CTL2_DT_TERM_SEL 0x03
+
+/* MHL DataPath 4th Ctl, default value: 0x48 */
+#define REG_MHL_DP_CTL3 0x0334
+#define MSK_MHL_DP_CTL3_DT_DRV_VNBC_CTL 0xf0
+#define MSK_MHL_DP_CTL3_DT_DRV_VNB_CTL 0x0f
+
+/* MHL DataPath 5th Ctl, default value: 0x48 */
+#define REG_MHL_DP_CTL4 0x0335
+#define MSK_MHL_DP_CTL4_CK_DRV_VNBC_CTL 0xf0
+#define MSK_MHL_DP_CTL4_CK_DRV_VNB_CTL 0x0f
+
+/* MHL DataPath 6th Ctl, default value: 0x3f */
+#define REG_MHL_DP_CTL5 0x0336
+#define BIT_MHL_DP_CTL5_RSEN_EN_OVR BIT(7)
+#define BIT_MHL_DP_CTL5_RSEN_EN BIT(6)
+#define MSK_MHL_DP_CTL5_DAMP_TERM_VGS_CTL 0x30
+#define MSK_MHL_DP_CTL5_CK_TERM_VGS_CTL 0x0c
+#define MSK_MHL_DP_CTL5_DT_TERM_VGS_CTL 0x03
+
+/* MHL PLL 1st Ctl, default value: 0x05 */
+#define REG_MHL_PLL_CTL0 0x0337
+#define BIT_MHL_PLL_CTL0_AUD_CLK_EN BIT(7)
+
+#define MSK_MHL_PLL_CTL0_AUD_CLK_RATIO 0x70
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_10 0x70
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_6 0x60
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_4 0x50
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2 0x40
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_5 0x30
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_3 0x20
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2_PRIME 0x10
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_1 0x00
+
+#define MSK_MHL_PLL_CTL0_HDMI_CLK_RATIO 0x0c
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_4X 0x0c
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_2X 0x08
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X 0x04
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_HALF_X 0x00
+
+#define BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL BIT(1)
+#define BIT_MHL_PLL_CTL0_ZONE_MASK_OE BIT(0)
+
+/* MHL PLL 3rd Ctl, default value: 0x80 */
+#define REG_MHL_PLL_CTL2 0x0339
+#define BIT_MHL_PLL_CTL2_CLKDETECT_EN BIT(7)
+#define BIT_MHL_PLL_CTL2_MEAS_FVCO BIT(3)
+#define BIT_MHL_PLL_CTL2_PLL_FAST_LOCK BIT(2)
+#define MSK_MHL_PLL_CTL2_PLL_LF_SEL 0x03
+
+/* MHL CBUS 1st Ctl, default value: 0x12 */
+#define REG_MHL_CBUS_CTL0 0x0340
+#define BIT_MHL_CBUS_CTL0_CBUS_RGND_TEST_MODE BIT(7)
+
+#define MSK_MHL_CBUS_CTL0_CBUS_RGND_VTH_CTL 0x30
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734 0x00
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_747 0x10
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_740 0x20
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_754 0x30
+
+#define MSK_MHL_CBUS_CTL0_CBUS_RES_TEST_SEL 0x0c
+
+#define MSK_MHL_CBUS_CTL0_CBUS_DRV_SEL 0x03
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAKEST 0x00
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAK 0x01
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG 0x02
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONGEST 0x03
+
+/* MHL CBUS 2nd Ctl, default value: 0x03 */
+#define REG_MHL_CBUS_CTL1 0x0341
+#define MSK_MHL_CBUS_CTL1_CBUS_RGND_RES_CTL 0x07
+#define VAL_MHL_CBUS_CTL1_0888_OHM 0x00
+#define VAL_MHL_CBUS_CTL1_1115_OHM 0x04
+#define VAL_MHL_CBUS_CTL1_1378_OHM 0x07
+
+/* MHL CoC 1st Ctl, default value: 0xc3 */
+#define REG_MHL_COC_CTL0 0x0342
+#define BIT_MHL_COC_CTL0_COC_BIAS_EN BIT(7)
+#define MSK_MHL_COC_CTL0_COC_BIAS_CTL 0x70
+#define MSK_MHL_COC_CTL0_COC_TERM_CTL 0x07
+
+/* MHL CoC 2nd Ctl, default value: 0x87 */
+#define REG_MHL_COC_CTL1 0x0343
+#define BIT_MHL_COC_CTL1_COC_EN BIT(7)
+#define MSK_MHL_COC_CTL1_COC_DRV_CTL 0x3f
+
+/* MHL CoC 4th Ctl, default value: 0x00 */
+#define REG_MHL_COC_CTL3 0x0345
+#define BIT_MHL_COC_CTL3_COC_AECHO_EN BIT(0)
+
+/* MHL CoC 5th Ctl, default value: 0x28 */
+#define REG_MHL_COC_CTL4 0x0346
+#define MSK_MHL_COC_CTL4_COC_IF_CTL 0xf0
+#define MSK_MHL_COC_CTL4_COC_SLEW_CTL 0x0f
+
+/* MHL CoC 6th Ctl, default value: 0x0d */
+#define REG_MHL_COC_CTL5 0x0347
+
+/* MHL DoC 1st Ctl, default value: 0x18 */
+#define REG_MHL_DOC_CTL0 0x0349
+#define BIT_MHL_DOC_CTL0_DOC_RXDATA_EN BIT(7)
+#define MSK_MHL_DOC_CTL0_DOC_DM_TERM 0x38
+#define MSK_MHL_DOC_CTL0_DOC_OPMODE 0x06
+#define BIT_MHL_DOC_CTL0_DOC_RXBIAS_EN BIT(0)
+
+/* MHL DataPath 7th Ctl, default value: 0x2a */
+#define REG_MHL_DP_CTL6 0x0350
+#define BIT_MHL_DP_CTL6_DP_TAP2_SGN BIT(5)
+#define BIT_MHL_DP_CTL6_DP_TAP2_EN BIT(4)
+#define BIT_MHL_DP_CTL6_DP_TAP1_SGN BIT(3)
+#define BIT_MHL_DP_CTL6_DP_TAP1_EN BIT(2)
+#define BIT_MHL_DP_CTL6_DT_PREDRV_FEEDCAP_EN BIT(1)
+#define BIT_MHL_DP_CTL6_DP_PRE_POST_SEL BIT(0)
+
+/* MHL DataPath 8th Ctl, default value: 0x06 */
+#define REG_MHL_DP_CTL7 0x0351
+#define MSK_MHL_DP_CTL7_DT_DRV_VBIAS_CASCTL 0xf0
+#define MSK_MHL_DP_CTL7_DT_DRV_IREF_CTL 0x0f
+
+/* Tx Zone Ctl1, default value: 0x00 */
+#define REG_TX_ZONE_CTL1 0x0361
+#define VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE 0x08
+
+/* MHL3 Tx Zone Ctl, default value: 0x00 */
+#define REG_MHL3_TX_ZONE_CTL 0x0364
+#define BIT_MHL3_TX_ZONE_CTL_MHL2_INTPLT_ZONE_MANU_EN BIT(7)
+#define MSK_MHL3_TX_ZONE_CTL_MHL3_TX_ZONE 0x03
+
+#define MSK_TX_ZONE_CTL3_TX_ZONE 0x03
+#define VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS 0x00
+#define VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS 0x01
+#define VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS 0x02
+
+/* HDCP Polling Control and Status, default value: 0x70 */
+#define REG_HDCP2X_POLL_CS 0x0391
+
+#define BIT_HDCP2X_POLL_CS_HDCP2X_MSG_SZ_CLR_OPTION BIT(6)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_RPT_READY_CLR_OPTION BIT(5)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_REAUTH_REQ_CLR_OPTION BIT(4)
+#define MSK_HDCP2X_POLL_CS_ 0x0c
+#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_GNT BIT(1)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_EN BIT(0)
+
+/* HDCP Interrupt 0, default value: 0x00 */
+#define REG_HDCP2X_INTR0 0x0398
+
+/* HDCP Interrupt 0 Mask, default value: 0x00 */
+#define REG_HDCP2X_INTR0_MASK 0x0399
+
+/* HDCP General Control 0, default value: 0x02 */
+#define REG_HDCP2X_CTRL_0 0x03a0
+#define BIT_HDCP2X_CTRL_0_HDCP2X_ENCRYPT_EN BIT(7)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_SEL BIT(6)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_OVR BIT(5)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_PRECOMPUTE BIT(4)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_HDMIMODE BIT(3)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_REPEATER BIT(2)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX BIT(1)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_EN BIT(0)
+
+/* HDCP General Control 1, default value: 0x08 */
+#define REG_HDCP2X_CTRL_1 0x03a1
+#define MSK_HDCP2X_CTRL_1_HDCP2X_REAUTH_MSK_3_0 0xf0
+#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_SW BIT(3)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_OVR BIT(2)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_CTL3MSK BIT(1)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_REAUTH_SW BIT(0)
+
+/* HDCP Misc Control, default value: 0x00 */
+#define REG_HDCP2X_MISC_CTRL 0x03a5
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_XFER_START BIT(4)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR_START BIT(3)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR BIT(2)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD_START BIT(1)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD BIT(0)
+
+/* HDCP RPT SMNG K, default value: 0x00 */
+#define REG_HDCP2X_RPT_SMNG_K 0x03a6
+
+/* HDCP RPT SMNG In, default value: 0x00 */
+#define REG_HDCP2X_RPT_SMNG_IN 0x03a7
+
+/* HDCP Auth Status, default value: 0x00 */
+#define REG_HDCP2X_AUTH_STAT 0x03aa
+
+/* HDCP RPT RCVID Out, default value: 0x00 */
+#define REG_HDCP2X_RPT_RCVID_OUT 0x03ac
+
+/* HDCP TP1, default value: 0x62 */
+#define REG_HDCP2X_TP1 0x03b4
+
+/* HDCP GP Out 0, default value: 0x00 */
+#define REG_HDCP2X_GP_OUT0 0x03c7
+
+/* HDCP Repeater RCVR ID 0, default value: 0x00 */
+#define REG_HDCP2X_RPT_RCVR_ID0 0x03d1
+
+/* HDCP DDCM Status, default value: 0x00 */
+#define REG_HDCP2X_DDCM_STS 0x03d8
+#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_ERR_STS_3_0 0xf0
+#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_CTL_CS_3_0 0x0f
+
+/* HDMI2MHL3 Control, default value: 0x0a */
+#define REG_M3_CTRL 0x03e0
+#define BIT_M3_CTRL_H2M_SWRST BIT(4)
+#define BIT_M3_CTRL_SW_MHL3_SEL BIT(3)
+#define BIT_M3_CTRL_M3AV_EN BIT(2)
+#define BIT_M3_CTRL_ENC_TMDS BIT(1)
+#define BIT_M3_CTRL_MHL3_MASTER_EN BIT(0)
+
+#define VAL_M3_CTRL_MHL1_2_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \
+ | BIT_M3_CTRL_ENC_TMDS)
+#define VAL_M3_CTRL_MHL3_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \
+ | BIT_M3_CTRL_M3AV_EN \
+ | BIT_M3_CTRL_ENC_TMDS \
+ | BIT_M3_CTRL_MHL3_MASTER_EN)
+
+/* HDMI2MHL3 Port0 Control, default value: 0x04 */
+#define REG_M3_P0CTRL 0x03e1
+#define BIT_M3_P0CTRL_MHL3_P0_HDCP_ENC_EN BIT(4)
+#define BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN BIT(3)
+#define BIT_M3_P0CTRL_MHL3_P0_HDCP_EN BIT(2)
+#define BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED BIT(1)
+#define BIT_M3_P0CTRL_MHL3_P0_PORT_EN BIT(0)
+
+#define REG_M3_POSTM 0x03e2
+#define MSK_M3_POSTM_RRP_DECODE 0xf8
+#define MSK_M3_POSTM_MHL3_P0_STM_ID 0x07
+
+/* HDMI2MHL3 Scramble Control, default value: 0x41 */
+#define REG_M3_SCTRL 0x03e6
+#define MSK_M3_SCTRL_MHL3_SR_LENGTH 0xf0
+#define BIT_M3_SCTRL_MHL3_SCRAMBLER_EN BIT(0)
+
+/* HSIC Div Ctl, default value: 0x05 */
+#define REG_DIV_CTL_MAIN 0x03f2
+#define MSK_DIV_CTL_MAIN_PRE_DIV_CTL_MAIN 0x1c
+#define MSK_DIV_CTL_MAIN_FB_DIV_CTL_MAIN 0x03
+
+/* MHL Capability 1st Byte, default value: 0x00 */
+#define REG_MHL_DEVCAP_0 0x0400
+
+/* MHL Interrupt 1st Byte, default value: 0x00 */
+#define REG_MHL_INT_0 0x0420
+
+/* Device Status 1st byte, default value: 0x00 */
+#define REG_MHL_STAT_0 0x0430
+
+/* CBUS Scratch Pad 1st Byte, default value: 0x00 */
+#define REG_MHL_SCRPAD_0 0x0440
+
+/* MHL Extended Capability 1st Byte, default value: 0x00 */
+#define REG_MHL_EXTDEVCAP_0 0x0480
+
+/* Device Extended Status 1st byte, default value: 0x00 */
+#define REG_MHL_EXTSTAT_0 0x0490
+
+/* TPI DTD Byte2, default value: 0x00 */
+#define REG_TPI_DTD_B2 0x0602
+
+#define VAL_TPI_QUAN_RANGE_LIMITED 0x01
+#define VAL_TPI_QUAN_RANGE_FULL 0x02
+#define VAL_TPI_FORMAT_RGB 0x00
+#define VAL_TPI_FORMAT_YCBCR444 0x01
+#define VAL_TPI_FORMAT_YCBCR422 0x02
+#define VAL_TPI_FORMAT_INTERNAL_RGB 0x03
+#define VAL_TPI_FORMAT(_fmt, _qr) \
+ (VAL_TPI_FORMAT_##_fmt | (VAL_TPI_QUAN_RANGE_##_qr << 2))
+
+/* Input Format, default value: 0x00 */
+#define REG_TPI_INPUT 0x0609
+#define BIT_TPI_INPUT_EXTENDEDBITMODE BIT(7)
+#define BIT_TPI_INPUT_ENDITHER BIT(6)
+#define MSK_TPI_INPUT_INPUT_QUAN_RANGE 0x0c
+#define MSK_TPI_INPUT_INPUT_FORMAT 0x03
+
+/* Output Format, default value: 0x00 */
+#define REG_TPI_OUTPUT 0x060a
+#define BIT_TPI_OUTPUT_CSCMODE709 BIT(4)
+#define MSK_TPI_OUTPUT_OUTPUT_QUAN_RANGE 0x0c
+#define MSK_TPI_OUTPUT_OUTPUT_FORMAT 0x03
+
+/* TPI AVI Check Sum, default value: 0x00 */
+#define REG_TPI_AVI_CHSUM 0x060c
+
+/* TPI System Control, default value: 0x00 */
+#define REG_TPI_SC 0x061a
+#define BIT_TPI_SC_TPI_UPDATE_FLG BIT(7)
+#define BIT_TPI_SC_TPI_REAUTH_CTL BIT(6)
+#define BIT_TPI_SC_TPI_OUTPUT_MODE_1 BIT(5)
+#define BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN BIT(4)
+#define BIT_TPI_SC_TPI_AV_MUTE BIT(3)
+#define BIT_TPI_SC_DDC_GPU_REQUEST BIT(2)
+#define BIT_TPI_SC_DDC_TPI_SW BIT(1)
+#define BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI BIT(0)
+
+/* TPI COPP Query Data, default value: 0x00 */
+#define REG_TPI_COPP_DATA1 0x0629
+#define BIT_TPI_COPP_DATA1_COPP_GPROT BIT(7)
+#define BIT_TPI_COPP_DATA1_COPP_LPROT BIT(6)
+#define MSK_TPI_COPP_DATA1_COPP_LINK_STATUS 0x30
+#define VAL_TPI_COPP_LINK_STATUS_NORMAL 0x00
+#define VAL_TPI_COPP_LINK_STATUS_LINK_LOST 0x10
+#define VAL_TPI_COPP_LINK_STATUS_RENEGOTIATION_REQ 0x20
+#define VAL_TPI_COPP_LINK_STATUS_LINK_SUSPENDED 0x30
+#define BIT_TPI_COPP_DATA1_COPP_HDCP_REP BIT(3)
+#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_0 BIT(2)
+#define BIT_TPI_COPP_DATA1_COPP_PROTYPE BIT(1)
+#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_1 BIT(0)
+
+/* TPI COPP Control Data, default value: 0x00 */
+#define REG_TPI_COPP_DATA2 0x062a
+#define BIT_TPI_COPP_DATA2_INTR_ENCRYPTION BIT(5)
+#define BIT_TPI_COPP_DATA2_KSV_FORWARD BIT(4)
+#define BIT_TPI_COPP_DATA2_INTERM_RI_CHECK_EN BIT(3)
+#define BIT_TPI_COPP_DATA2_DOUBLE_RI_CHECK BIT(2)
+#define BIT_TPI_COPP_DATA2_DDC_SHORT_RI_RD BIT(1)
+#define BIT_TPI_COPP_DATA2_COPP_PROTLEVEL BIT(0)
+
+/* TPI Interrupt Enable, default value: 0x00 */
+#define REG_TPI_INTR_EN 0x063c
+
+/* TPI Interrupt Status Low Byte, default value: 0x00 */
+#define REG_TPI_INTR_ST0 0x063d
+#define BIT_TPI_INTR_ST0_TPI_AUTH_CHNGE_STAT BIT(7)
+#define BIT_TPI_INTR_ST0_TPI_V_RDY_STAT BIT(6)
+#define BIT_TPI_INTR_ST0_TPI_COPP_CHNGE_STAT BIT(5)
+#define BIT_TPI_INTR_ST0_KSV_FIFO_FIRST_STAT BIT(3)
+#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_DONE_STAT BIT(2)
+#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_ERR_STAT BIT(1)
+#define BIT_TPI_INTR_ST0_READ_BKSV_ERR_STAT BIT(0)
+
+/* TPI DS BCAPS Status, default value: 0x00 */
+#define REG_TPI_DS_BCAPS 0x0644
+
+/* TPI BStatus1, default value: 0x00 */
+#define REG_TPI_BSTATUS1 0x0645
+#define BIT_TPI_BSTATUS1_DS_DEV_EXCEED BIT(7)
+#define MSK_TPI_BSTATUS1_DS_DEV_CNT 0x7f
+
+/* TPI BStatus2, default value: 0x10 */
+#define REG_TPI_BSTATUS2 0x0646
+#define MSK_TPI_BSTATUS2_DS_BSTATUS 0xe0
+#define BIT_TPI_BSTATUS2_DS_HDMI_MODE BIT(4)
+#define BIT_TPI_BSTATUS2_DS_CASC_EXCEED BIT(3)
+#define MSK_TPI_BSTATUS2_DS_DEPTH 0x07
+
+/* TPI HW Optimization Control #3, default value: 0x00 */
+#define REG_TPI_HW_OPT3 0x06bb
+#define BIT_TPI_HW_OPT3_DDC_DEBUG BIT(7)
+#define BIT_TPI_HW_OPT3_RI_CHECK_SKIP BIT(3)
+#define BIT_TPI_HW_OPT3_TPI_DDC_BURST_MODE BIT(2)
+#define MSK_TPI_HW_OPT3_TPI_DDC_REQ_LEVEL 0x03
+
+/* TPI Info Frame Select, default value: 0x00 */
+#define REG_TPI_INFO_FSEL 0x06bf
+#define BIT_TPI_INFO_FSEL_TPI_INFO_EN BIT(7)
+#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT BIT(6)
+#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG BIT(5)
+#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL 0x07
+
+/* TPI Info Byte #0, default value: 0x00 */
+#define REG_TPI_INFO_B0 0x06c0
+
+/* CoC Status, default value: 0x00 */
+#define REG_COC_STAT_0 0x0700
+#define REG_COC_STAT_1 0x0701
+#define REG_COC_STAT_2 0x0702
+#define REG_COC_STAT_3 0x0703
+#define REG_COC_STAT_4 0x0704
+#define REG_COC_STAT_5 0x0705
+
+/* CoC 1st Ctl, default value: 0x40 */
+#define REG_COC_CTL0 0x0710
+
+/* CoC 2nd Ctl, default value: 0x0a */
+#define REG_COC_CTL1 0x0711
+#define MSK_COC_CTL1_COC_CTRL1_7_6 0xc0
+#define MSK_COC_CTL1_COC_CTRL1_5_0 0x3f
+
+/* CoC 3rd Ctl, default value: 0x14 */
+#define REG_COC_CTL2 0x0712
+#define MSK_COC_CTL2_COC_CTRL2_7_6 0xc0
+#define MSK_COC_CTL2_COC_CTRL2_5_0 0x3f
+
+/* CoC 4th Ctl, default value: 0x40 */
+#define REG_COC_CTL3 0x0713
+#define BIT_COC_CTL3_COC_CTRL3_7 BIT(7)
+#define MSK_COC_CTL3_COC_CTRL3_6_0 0x7f
+
+/* CoC 7th Ctl, default value: 0x00 */
+#define REG_COC_CTL6 0x0716
+#define BIT_COC_CTL6_COC_CTRL6_7 BIT(7)
+#define BIT_COC_CTL6_COC_CTRL6_6 BIT(6)
+#define MSK_COC_CTL6_COC_CTRL6_5_0 0x3f
+
+/* CoC 8th Ctl, default value: 0x06 */
+#define REG_COC_CTL7 0x0717
+#define BIT_COC_CTL7_COC_CTRL7_7 BIT(7)
+#define BIT_COC_CTL7_COC_CTRL7_6 BIT(6)
+#define BIT_COC_CTL7_COC_CTRL7_5 BIT(5)
+#define MSK_COC_CTL7_COC_CTRL7_4_3 0x18
+#define MSK_COC_CTL7_COC_CTRL7_2_0 0x07
+
+/* CoC 10th Ctl, default value: 0x00 */
+#define REG_COC_CTL9 0x0719
+
+/* CoC 11th Ctl, default value: 0x00 */
+#define REG_COC_CTLA 0x071a
+
+/* CoC 12th Ctl, default value: 0x00 */
+#define REG_COC_CTLB 0x071b
+
+/* CoC 13th Ctl, default value: 0x0f */
+#define REG_COC_CTLC 0x071c
+
+/* CoC 14th Ctl, default value: 0x0a */
+#define REG_COC_CTLD 0x071d
+#define BIT_COC_CTLD_COC_CTRLD_7 BIT(7)
+#define MSK_COC_CTLD_COC_CTRLD_6_0 0x7f
+
+/* CoC 15th Ctl, default value: 0x0a */
+#define REG_COC_CTLE 0x071e
+#define BIT_COC_CTLE_COC_CTRLE_7 BIT(7)
+#define MSK_COC_CTLE_COC_CTRLE_6_0 0x7f
+
+/* CoC 16th Ctl, default value: 0x00 */
+#define REG_COC_CTLF 0x071f
+#define MSK_COC_CTLF_COC_CTRLF_7_3 0xf8
+#define MSK_COC_CTLF_COC_CTRLF_2_0 0x07
+
+/* CoC 18th Ctl, default value: 0x32 */
+#define REG_COC_CTL11 0x0721
+#define MSK_COC_CTL11_COC_CTRL11_7_4 0xf0
+#define MSK_COC_CTL11_COC_CTRL11_3_0 0x0f
+
+/* CoC 21st Ctl, default value: 0x00 */
+#define REG_COC_CTL14 0x0724
+#define MSK_COC_CTL14_COC_CTRL14_7_4 0xf0
+#define MSK_COC_CTL14_COC_CTRL14_3_0 0x0f
+
+/* CoC 22nd Ctl, default value: 0x00 */
+#define REG_COC_CTL15 0x0725
+#define BIT_COC_CTL15_COC_CTRL15_7 BIT(7)
+#define MSK_COC_CTL15_COC_CTRL15_6_4 0x70
+#define MSK_COC_CTL15_COC_CTRL15_3_0 0x0f
+
+/* CoC Interrupt, default value: 0x00 */
+#define REG_COC_INTR 0x0726
+
+/* CoC Interrupt Mask, default value: 0x00 */
+#define REG_COC_INTR_MASK 0x0727
+#define BIT_COC_PLL_LOCK_STATUS_CHANGE BIT(0)
+#define BIT_COC_CALIBRATION_DONE BIT(1)
+
+/* CoC Misc Ctl, default value: 0x00 */
+#define REG_COC_MISC_CTL0 0x0728
+#define BIT_COC_MISC_CTL0_FSM_MON BIT(7)
+
+/* CoC 24th Ctl, default value: 0x00 */
+#define REG_COC_CTL17 0x072a
+#define MSK_COC_CTL17_COC_CTRL17_7_4 0xf0
+#define MSK_COC_CTL17_COC_CTRL17_3_0 0x0f
+
+/* CoC 25th Ctl, default value: 0x00 */
+#define REG_COC_CTL18 0x072b
+#define MSK_COC_CTL18_COC_CTRL18_7_4 0xf0
+#define MSK_COC_CTL18_COC_CTRL18_3_0 0x0f
+
+/* CoC 26th Ctl, default value: 0x00 */
+#define REG_COC_CTL19 0x072c
+#define MSK_COC_CTL19_COC_CTRL19_7_4 0xf0
+#define MSK_COC_CTL19_COC_CTRL19_3_0 0x0f
+
+/* CoC 27th Ctl, default value: 0x00 */
+#define REG_COC_CTL1A 0x072d
+#define MSK_COC_CTL1A_COC_CTRL1A_7_2 0xfc
+#define MSK_COC_CTL1A_COC_CTRL1A_1_0 0x03
+
+/* DoC 9th Status, default value: 0x00 */
+#define REG_DOC_STAT_8 0x0740
+
+/* DoC 10th Status, default value: 0x00 */
+#define REG_DOC_STAT_9 0x0741
+
+/* DoC 5th CFG, default value: 0x00 */
+#define REG_DOC_CFG4 0x074e
+#define MSK_DOC_CFG4_DBG_STATE_DOC_FSM 0x0f
+
+/* DoC 1st Ctl, default value: 0x40 */
+#define REG_DOC_CTL0 0x0751
+
+/* DoC 7th Ctl, default value: 0x00 */
+#define REG_DOC_CTL6 0x0757
+#define BIT_DOC_CTL6_DOC_CTRL6_7 BIT(7)
+#define BIT_DOC_CTL6_DOC_CTRL6_6 BIT(6)
+#define MSK_DOC_CTL6_DOC_CTRL6_5_4 0x30
+#define MSK_DOC_CTL6_DOC_CTRL6_3_0 0x0f
+
+/* DoC 8th Ctl, default value: 0x00 */
+#define REG_DOC_CTL7 0x0758
+#define BIT_DOC_CTL7_DOC_CTRL7_7 BIT(7)
+#define BIT_DOC_CTL7_DOC_CTRL7_6 BIT(6)
+#define BIT_DOC_CTL7_DOC_CTRL7_5 BIT(5)
+#define MSK_DOC_CTL7_DOC_CTRL7_4_3 0x18
+#define MSK_DOC_CTL7_DOC_CTRL7_2_0 0x07
+
+/* DoC 9th Ctl, default value: 0x00 */
+#define REG_DOC_CTL8 0x076c
+#define BIT_DOC_CTL8_DOC_CTRL8_7 BIT(7)
+#define MSK_DOC_CTL8_DOC_CTRL8_6_4 0x70
+#define MSK_DOC_CTL8_DOC_CTRL8_3_2 0x0c
+#define MSK_DOC_CTL8_DOC_CTRL8_1_0 0x03
+
+/* DoC 10th Ctl, default value: 0x00 */
+#define REG_DOC_CTL9 0x076d
+
+/* DoC 11th Ctl, default value: 0x00 */
+#define REG_DOC_CTLA 0x076e
+
+/* DoC 15th Ctl, default value: 0x00 */
+#define REG_DOC_CTLE 0x0772
+#define BIT_DOC_CTLE_DOC_CTRLE_7 BIT(7)
+#define BIT_DOC_CTLE_DOC_CTRLE_6 BIT(6)
+#define MSK_DOC_CTLE_DOC_CTRLE_5_4 0x30
+#define MSK_DOC_CTLE_DOC_CTRLE_3_0 0x0f
+
+/* Interrupt Mask 1st, default value: 0x00 */
+#define REG_MHL_INT_0_MASK 0x0580
+
+/* Interrupt Mask 2nd, default value: 0x00 */
+#define REG_MHL_INT_1_MASK 0x0581
+
+/* Interrupt Mask 3rd, default value: 0x00 */
+#define REG_MHL_INT_2_MASK 0x0582
+
+/* Interrupt Mask 4th, default value: 0x00 */
+#define REG_MHL_INT_3_MASK 0x0583
+
+/* MDT Receive Time Out, default value: 0x00 */
+#define REG_MDT_RCV_TIMEOUT 0x0584
+
+/* MDT Transmit Time Out, default value: 0x00 */
+#define REG_MDT_XMIT_TIMEOUT 0x0585
+
+/* MDT Receive Control, default value: 0x00 */
+#define REG_MDT_RCV_CTRL 0x0586
+#define BIT_MDT_RCV_CTRL_MDT_RCV_EN BIT(7)
+#define BIT_MDT_RCV_CTRL_MDT_DELAY_RCV_EN BIT(6)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_OVER_WR_EN BIT(4)
+#define BIT_MDT_RCV_CTRL_MDT_XFIFO_OVER_WR_EN BIT(3)
+#define BIT_MDT_RCV_CTRL_MDT_DISABLE BIT(2)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_ALL BIT(1)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_CUR BIT(0)
+
+/* MDT Receive Read Port, default value: 0x00 */
+#define REG_MDT_RCV_READ_PORT 0x0587
+
+/* MDT Transmit Control, default value: 0x70 */
+#define REG_MDT_XMIT_CTRL 0x0588
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_EN BIT(7)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_CMD_MERGE_EN BIT(6)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_BURST_LEN BIT(5)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_AID BIT(4)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_SINGLE_RUN_EN BIT(3)
+#define BIT_MDT_XMIT_CTRL_MDT_CLR_ABORT_WAIT BIT(2)
+#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_ALL BIT(1)
+#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_CUR BIT(0)
+
+/* MDT Receive WRITE Port, default value: 0x00 */
+#define REG_MDT_XMIT_WRITE_PORT 0x0589
+
+/* MDT RFIFO Status, default value: 0x00 */
+#define REG_MDT_RFIFO_STAT 0x058a
+#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CNT 0xe0
+#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CUR_BYTE_CNT 0x1f
+
+/* MDT XFIFO Status, default value: 0x80 */
+#define REG_MDT_XFIFO_STAT 0x058b
+#define MSK_MDT_XFIFO_STAT_MDT_XFIFO_LEVEL_AVAIL 0xe0
+#define BIT_MDT_XFIFO_STAT_MDT_XMIT_PRE_HS_EN BIT(4)
+#define MSK_MDT_XFIFO_STAT_MDT_WRITE_BURST_LEN 0x0f
+
+/* MDT Interrupt 0, default value: 0x0c */
+#define REG_MDT_INT_0 0x058c
+#define BIT_MDT_RFIFO_DATA_RDY BIT(0)
+#define BIT_MDT_IDLE_AFTER_HAWB_DISABLE BIT(2)
+#define BIT_MDT_XFIFO_EMPTY BIT(3)
+
+/* MDT Interrupt 0 Mask, default value: 0x00 */
+#define REG_MDT_INT_0_MASK 0x058d
+
+/* MDT Interrupt 1, default value: 0x00 */
+#define REG_MDT_INT_1 0x058e
+#define BIT_MDT_RCV_TIMEOUT BIT(0)
+#define BIT_MDT_RCV_SM_ABORT_PKT_RCVD BIT(1)
+#define BIT_MDT_RCV_SM_ERROR BIT(2)
+#define BIT_MDT_XMIT_TIMEOUT BIT(5)
+#define BIT_MDT_XMIT_SM_ABORT_PKT_RCVD BIT(6)
+#define BIT_MDT_XMIT_SM_ERROR BIT(7)
+
+/* MDT Interrupt 1 Mask, default value: 0x00 */
+#define REG_MDT_INT_1_MASK 0x058f
+
+/* CBUS Vendor ID, default value: 0x01 */
+#define REG_CBUS_VENDOR_ID 0x0590
+
+/* CBUS Connection Status, default value: 0x00 */
+#define REG_CBUS_STATUS 0x0591
+#define BIT_CBUS_STATUS_MHL_CABLE_PRESENT BIT(4)
+#define BIT_CBUS_STATUS_MSC_HB_SUCCESS BIT(3)
+#define BIT_CBUS_STATUS_CBUS_HPD BIT(2)
+#define BIT_CBUS_STATUS_MHL_MODE BIT(1)
+#define BIT_CBUS_STATUS_CBUS_CONNECTED BIT(0)
+
+/* CBUS Interrupt 1st, default value: 0x00 */
+#define REG_CBUS_INT_0 0x0592
+#define BIT_CBUS_MSC_MT_DONE_NACK BIT(7)
+#define BIT_CBUS_MSC_MR_SET_INT BIT(6)
+#define BIT_CBUS_MSC_MR_WRITE_BURST BIT(5)
+#define BIT_CBUS_MSC_MR_MSC_MSG BIT(4)
+#define BIT_CBUS_MSC_MR_WRITE_STAT BIT(3)
+#define BIT_CBUS_HPD_CHG BIT(2)
+#define BIT_CBUS_MSC_MT_DONE BIT(1)
+#define BIT_CBUS_CNX_CHG BIT(0)
+
+/* CBUS Interrupt Mask 1st, default value: 0x00 */
+#define REG_CBUS_INT_0_MASK 0x0593
+
+/* CBUS Interrupt 2nd, default value: 0x00 */
+#define REG_CBUS_INT_1 0x0594
+#define BIT_CBUS_CMD_ABORT BIT(6)
+#define BIT_CBUS_MSC_ABORT_RCVD BIT(3)
+#define BIT_CBUS_DDC_ABORT BIT(2)
+#define BIT_CBUS_CEC_ABORT BIT(1)
+
+/* CBUS Interrupt Mask 2nd, default value: 0x00 */
+#define REG_CBUS_INT_1_MASK 0x0595
+
+/* CBUS DDC Abort Interrupt, default value: 0x00 */
+#define REG_DDC_ABORT_INT 0x0598
+
+/* CBUS DDC Abort Interrupt Mask, default value: 0x00 */
+#define REG_DDC_ABORT_INT_MASK 0x0599
+
+/* CBUS MSC Requester Abort Interrupt, default value: 0x00 */
+#define REG_MSC_MT_ABORT_INT 0x059a
+
+/* CBUS MSC Requester Abort Interrupt Mask, default value: 0x00 */
+#define REG_MSC_MT_ABORT_INT_MASK 0x059b
+
+/* CBUS MSC Responder Abort Interrupt, default value: 0x00 */
+#define REG_MSC_MR_ABORT_INT 0x059c
+
+/* CBUS MSC Responder Abort Interrupt Mask, default value: 0x00 */
+#define REG_MSC_MR_ABORT_INT_MASK 0x059d
+
+/* CBUS RX DISCOVERY interrupt, default value: 0x00 */
+#define REG_CBUS_RX_DISC_INT0 0x059e
+
+/* CBUS RX DISCOVERY Interrupt Mask, default value: 0x00 */
+#define REG_CBUS_RX_DISC_INT0_MASK 0x059f
+
+/* CBUS_Link_Layer Control #8, default value: 0x00 */
+#define REG_CBUS_LINK_CTRL_8 0x05a7
+
+/* MDT State Machine Status, default value: 0x00 */
+#define REG_MDT_SM_STAT 0x05b5
+#define MSK_MDT_SM_STAT_MDT_RCV_STATE 0xf0
+#define MSK_MDT_SM_STAT_MDT_XMIT_STATE 0x0f
+
+/* CBUS MSC command trigger, default value: 0x00 */
+#define REG_MSC_COMMAND_START 0x05b8
+#define BIT_MSC_COMMAND_START_DEBUG BIT(5)
+#define BIT_MSC_COMMAND_START_WRITE_BURST BIT(4)
+#define BIT_MSC_COMMAND_START_WRITE_STAT BIT(3)
+#define BIT_MSC_COMMAND_START_READ_DEVCAP BIT(2)
+#define BIT_MSC_COMMAND_START_MSC_MSG BIT(1)
+#define BIT_MSC_COMMAND_START_PEER BIT(0)
+
+/* CBUS MSC Command/Offset, default value: 0x00 */
+#define REG_MSC_CMD_OR_OFFSET 0x05b9
+
+/* CBUS MSC Transmit Data */
+#define REG_MSC_1ST_TRANSMIT_DATA 0x05ba
+#define REG_MSC_2ND_TRANSMIT_DATA 0x05bb
+
+/* CBUS MSC Requester Received Data */
+#define REG_MSC_MT_RCVD_DATA0 0x05bc
+#define REG_MSC_MT_RCVD_DATA1 0x05bd
+
+/* CBUS MSC Responder MSC_MSG Received Data */
+#define REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA 0x05bf
+#define REG_MSC_MR_MSC_MSG_RCVD_2ND_DATA 0x05c0
+
+/* CBUS MSC Heartbeat Control, default value: 0x27 */
+#define REG_MSC_HEARTBEAT_CTRL 0x05c4
+#define BIT_MSC_HEARTBEAT_CTRL_MSC_HB_EN BIT(7)
+#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_FAIL_LIMIT 0x70
+#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_PERIOD_MSB 0x0f
+
+/* CBUS MSC Compatibility Control, default value: 0x02 */
+#define REG_CBUS_MSC_COMPAT_CTRL 0x05c7
+#define BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN BIT(7)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_MSC_ON_CBUS BIT(6)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_DDC_ON_CBUS BIT(5)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_DDC_ERRORCODE BIT(3)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_VS1_ERRORCODE BIT(2)
+
+/* CBUS3 Converter Control, default value: 0x24 */
+#define REG_CBUS3_CNVT 0x05dc
+#define MSK_CBUS3_CNVT_CBUS3_RETRYLMT 0xf0
+#define MSK_CBUS3_CNVT_CBUS3_PEERTOUT_SEL 0x0c
+#define BIT_CBUS3_CNVT_TEARCBUS_EN BIT(1)
+#define BIT_CBUS3_CNVT_CBUS3CNVT_EN BIT(0)
+
+/* Discovery Control1, default value: 0x24 */
+#define REG_DISC_CTRL1 0x05e0
+#define BIT_DISC_CTRL1_CBUS_INTR_EN BIT(7)
+#define BIT_DISC_CTRL1_HB_ONLY BIT(6)
+#define MSK_DISC_CTRL1_DISC_ATT 0x30
+#define MSK_DISC_CTRL1_DISC_CYC 0x0c
+#define BIT_DISC_CTRL1_DISC_EN BIT(0)
+
+#define VAL_PUP_OFF 0
+#define VAL_PUP_20K 1
+#define VAL_PUP_5K 2
+
+/* Discovery Control4, default value: 0x80 */
+#define REG_DISC_CTRL4 0x05e3
+#define MSK_DISC_CTRL4_CBUSDISC_PUP_SEL 0xc0
+#define MSK_DISC_CTRL4_CBUSIDLE_PUP_SEL 0x30
+#define VAL_DISC_CTRL4(pup_disc, pup_idle) (((pup_disc) << 6) | (pup_idle << 4))
+
+/* Discovery Control5, default value: 0x03 */
+#define REG_DISC_CTRL5 0x05e4
+#define BIT_DISC_CTRL5_DSM_OVRIDE BIT(3)
+#define MSK_DISC_CTRL5_CBUSMHL_PUP_SEL 0x03
+
+/* Discovery Control8, default value: 0x81 */
+#define REG_DISC_CTRL8 0x05e7
+#define BIT_DISC_CTRL8_NOMHLINT_CLR_BYPASS BIT(7)
+#define BIT_DISC_CTRL8_DELAY_CBUS_INTR_EN BIT(0)
+
+/* Discovery Control9, default value: 0x54 */
+#define REG_DISC_CTRL9 0x05e8
+#define BIT_DISC_CTRL9_MHL3_RSEN_BYP BIT(7)
+#define BIT_DISC_CTRL9_MHL3DISC_EN BIT(6)
+#define BIT_DISC_CTRL9_WAKE_DRVFLT BIT(4)
+#define BIT_DISC_CTRL9_NOMHL_EST BIT(3)
+#define BIT_DISC_CTRL9_DISC_PULSE_PROCEED BIT(2)
+#define BIT_DISC_CTRL9_WAKE_PULSE_BYPASS BIT(1)
+#define BIT_DISC_CTRL9_VBUS_OUTPUT_CAPABILITY_SRC BIT(0)
+
+/* Discovery Status1, default value: 0x00 */
+#define REG_DISC_STAT1 0x05eb
+#define BIT_DISC_STAT1_PSM_OVRIDE BIT(5)
+#define MSK_DISC_STAT1_DISC_SM 0x0f
+
+/* Discovery Status2, default value: 0x00 */
+#define REG_DISC_STAT2 0x05ec
+#define BIT_DISC_STAT2_CBUS_OE_POL BIT(6)
+#define BIT_DISC_STAT2_CBUS_SATUS BIT(5)
+#define BIT_DISC_STAT2_RSEN BIT(4)
+
+#define MSK_DISC_STAT2_MHL_VRSN 0x0c
+#define VAL_DISC_STAT2_DEFAULT 0x00
+#define VAL_DISC_STAT2_MHL1_2 0x04
+#define VAL_DISC_STAT2_MHL3 0x08
+#define VAL_DISC_STAT2_RESERVED 0x0c
+
+#define MSK_DISC_STAT2_RGND 0x03
+#define VAL_RGND_OPEN 0x00
+#define VAL_RGND_2K 0x01
+#define VAL_RGND_1K 0x02
+#define VAL_RGND_SHORT 0x03
+
+/* Interrupt CBUS_reg1 INTR0, default value: 0x00 */
+#define REG_CBUS_DISC_INTR0 0x05ed
+#define BIT_RGND_READY_INT BIT(6)
+#define BIT_CBUS_MHL12_DISCON_INT BIT(5)
+#define BIT_CBUS_MHL3_DISCON_INT BIT(4)
+#define BIT_NOT_MHL_EST_INT BIT(3)
+#define BIT_MHL_EST_INT BIT(2)
+#define BIT_MHL3_EST_INT BIT(1)
+#define VAL_CBUS_MHL_DISCON (BIT_CBUS_MHL12_DISCON_INT \
+ | BIT_CBUS_MHL3_DISCON_INT \
+ | BIT_NOT_MHL_EST_INT)
+
+/* Interrupt CBUS_reg1 INTR0 Mask, default value: 0x00 */
+#define REG_CBUS_DISC_INTR0_MASK 0x05ee
+
+#endif /* __SIL_SII8620_H__ */
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 44d476ea6d2e..de9ffb49e9f6 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -908,7 +908,7 @@ static int tc_main_link_setup(struct tc_data *tc)
goto err_dpcd_read;
if (tmp[0] != tc->assr) {
- dev_warn(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n",
+ dev_dbg(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n",
tc->assr);
/* trying with disabled scrambler */
tc->link.scrambler_dis = 1;
@@ -1038,12 +1038,6 @@ err:
return ret;
}
-static enum drm_connector_status
-tc_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void tc_bridge_pre_enable(struct drm_bridge *bridge)
{
struct tc_data *tc = bridge_to_tc(bridge);
@@ -1168,7 +1162,6 @@ static const struct drm_connector_helper_funcs tc_connector_helper_funcs = {
static const struct drm_connector_funcs tc_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = tc_connector_detect,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
new file mode 100644
index 000000000000..b054ea349952
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 Texas Instruments
+ * Author: Jyri Sarha <jsarha@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+struct tfp410 {
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+
+ struct i2c_adapter *ddc;
+
+ struct device *dev;
+};
+
+static inline struct tfp410 *
+drm_bridge_to_tfp410(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct tfp410, bridge);
+}
+
+static inline struct tfp410 *
+drm_connector_to_tfp410(struct drm_connector *connector)
+{
+ return container_of(connector, struct tfp410, connector);
+}
+
+static int tfp410_get_modes(struct drm_connector *connector)
+{
+ struct tfp410 *dvi = drm_connector_to_tfp410(connector);
+ struct edid *edid;
+ int ret;
+
+ if (!dvi->ddc)
+ goto fallback;
+
+ edid = drm_get_edid(connector, dvi->ddc);
+ if (!edid) {
+ DRM_INFO("EDID read failed. Fallback to standard modes\n");
+ goto fallback;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+
+ return drm_add_edid_modes(connector, edid);
+fallback:
+ /* No EDID, fallback on the XGA standard modes */
+ ret = drm_add_modes_noedid(connector, 1920, 1200);
+
+ /* And prefer a mode pretty much anything can handle */
+ drm_set_preferred_mode(connector, 1024, 768);
+
+ return ret;
+}
+
+static const struct drm_connector_helper_funcs tfp410_con_helper_funcs = {
+ .get_modes = tfp410_get_modes,
+};
+
+static enum drm_connector_status
+tfp410_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct tfp410 *dvi = drm_connector_to_tfp410(connector);
+
+ if (dvi->ddc) {
+ if (drm_probe_ddc(dvi->ddc))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ }
+
+ return connector_status_unknown;
+}
+
+static const struct drm_connector_funcs tfp410_con_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = tfp410_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .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 int tfp410_attach(struct drm_bridge *bridge)
+{
+ struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
+ int ret;
+
+ if (!bridge->encoder) {
+ dev_err(dvi->dev, "Missing encoder\n");
+ return -ENODEV;
+ }
+
+ drm_connector_helper_add(&dvi->connector,
+ &tfp410_con_helper_funcs);
+ ret = drm_connector_init(bridge->dev, &dvi->connector,
+ &tfp410_con_funcs, DRM_MODE_CONNECTOR_HDMIA);
+ if (ret) {
+ dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ drm_mode_connector_attach_encoder(&dvi->connector,
+ bridge->encoder);
+
+ return 0;
+}
+
+static const struct drm_bridge_funcs tfp410_bridge_funcs = {
+ .attach = tfp410_attach,
+};
+
+static int tfp410_get_connector_ddc(struct tfp410 *dvi)
+{
+ struct device_node *ep = NULL, *connector_node = NULL;
+ struct device_node *ddc_phandle = NULL;
+ int ret = 0;
+
+ /* port@1 is the connector node */
+ ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1);
+ if (!ep)
+ goto fail;
+
+ connector_node = of_graph_get_remote_port_parent(ep);
+ if (!connector_node)
+ goto fail;
+
+ ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
+ if (!ddc_phandle)
+ goto fail;
+
+ dvi->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
+ if (dvi->ddc)
+ dev_info(dvi->dev, "Connector's ddc i2c bus found\n");
+ else
+ ret = -EPROBE_DEFER;
+
+fail:
+ of_node_put(ep);
+ of_node_put(connector_node);
+ of_node_put(ddc_phandle);
+ return ret;
+}
+
+static int tfp410_init(struct device *dev)
+{
+ struct tfp410 *dvi;
+ int ret;
+
+ if (!dev->of_node) {
+ dev_err(dev, "device-tree data is missing\n");
+ return -ENXIO;
+ }
+
+ dvi = devm_kzalloc(dev, sizeof(*dvi), GFP_KERNEL);
+ if (!dvi)
+ return -ENOMEM;
+ dev_set_drvdata(dev, dvi);
+
+ dvi->bridge.funcs = &tfp410_bridge_funcs;
+ dvi->bridge.of_node = dev->of_node;
+ dvi->dev = dev;
+
+ ret = tfp410_get_connector_ddc(dvi);
+ if (ret)
+ goto fail;
+
+ ret = drm_bridge_add(&dvi->bridge);
+ if (ret) {
+ dev_err(dev, "drm_bridge_add() failed: %d\n", ret);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ i2c_put_adapter(dvi->ddc);
+ return ret;
+}
+
+static int tfp410_fini(struct device *dev)
+{
+ struct tfp410 *dvi = dev_get_drvdata(dev);
+
+ drm_bridge_remove(&dvi->bridge);
+
+ if (dvi->ddc)
+ i2c_put_adapter(dvi->ddc);
+
+ return 0;
+}
+
+static int tfp410_probe(struct platform_device *pdev)
+{
+ return tfp410_init(&pdev->dev);
+}
+
+static int tfp410_remove(struct platform_device *pdev)
+{
+ return tfp410_fini(&pdev->dev);
+}
+
+static const struct of_device_id tfp410_match[] = {
+ { .compatible = "ti,tfp410" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tfp410_match);
+
+struct platform_driver tfp410_platform_driver = {
+ .probe = tfp410_probe,
+ .remove = tfp410_remove,
+ .driver = {
+ .name = "tfp410-bridge",
+ .of_match_table = tfp410_match,
+ },
+};
+
+#if IS_ENABLED(CONFIG_I2C)
+/* There is currently no i2c functionality. */
+static int tfp410_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int reg;
+
+ if (!client->dev.of_node ||
+ of_property_read_u32(client->dev.of_node, "reg", &reg)) {
+ dev_err(&client->dev,
+ "Can't get i2c reg property from device-tree\n");
+ return -ENXIO;
+ }
+
+ return tfp410_init(&client->dev);
+}
+
+static int tfp410_i2c_remove(struct i2c_client *client)
+{
+ return tfp410_fini(&client->dev);
+}
+
+static const struct i2c_device_id tfp410_i2c_ids[] = {
+ { "tfp410", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tfp410_i2c_ids);
+
+static struct i2c_driver tfp410_i2c_driver = {
+ .driver = {
+ .name = "tfp410",
+ .of_match_table = of_match_ptr(tfp410_match),
+ },
+ .id_table = tfp410_i2c_ids,
+ .probe = tfp410_i2c_probe,
+ .remove = tfp410_i2c_remove,
+};
+#endif /* IS_ENABLED(CONFIG_I2C) */
+
+static struct {
+ uint i2c:1;
+ uint platform:1;
+} tfp410_registered_driver;
+
+static int __init tfp410_module_init(void)
+{
+ int ret;
+
+#if IS_ENABLED(CONFIG_I2C)
+ ret = i2c_add_driver(&tfp410_i2c_driver);
+ if (ret)
+ pr_err("%s: registering i2c driver failed: %d",
+ __func__, ret);
+ else
+ tfp410_registered_driver.i2c = 1;
+#endif
+
+ ret = platform_driver_register(&tfp410_platform_driver);
+ if (ret)
+ pr_err("%s: registering platform driver failed: %d",
+ __func__, ret);
+ else
+ tfp410_registered_driver.platform = 1;
+
+ if (tfp410_registered_driver.i2c ||
+ tfp410_registered_driver.platform)
+ return 0;
+
+ return ret;
+}
+module_init(tfp410_module_init);
+
+static void __exit tfp410_module_exit(void)
+{
+#if IS_ENABLED(CONFIG_I2C)
+ if (tfp410_registered_driver.i2c)
+ i2c_del_driver(&tfp410_i2c_driver);
+#endif
+ if (tfp410_registered_driver.platform)
+ platform_driver_unregister(&tfp410_platform_driver);
+}
+module_exit(tfp410_module_exit);
+
+MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
+MODULE_DESCRIPTION("TI TFP410 DVI bridge driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 6c76d125995b..d893ea21a359 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -126,9 +126,7 @@ static const struct file_operations cirrus_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = cirrus_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
};
static struct drm_driver driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM,
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index daecf1ad76a4..3a6309d7d8e4 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -138,12 +138,12 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
{
struct drm_device *dev = afbdev->helper.dev;
struct cirrus_device *cdev = dev->dev_private;
- u32 bpp, depth;
+ u32 bpp;
u32 size;
struct drm_gem_object *gobj;
-
int ret = 0;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+
+ bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
bpp, mode_cmd->pitches[0]))
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 76bcb43e7c06..2c3c0d4072ce 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -52,10 +52,10 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
struct cirrus_device *cdev = dev->dev_private;
struct drm_gem_object *obj;
struct cirrus_framebuffer *cirrus_fb;
+ u32 bpp;
int ret;
- u32 bpp, depth;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+ bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
bpp, mode_cmd->pitches[0]))
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 17c915d9a03e..9a4a27c1afd2 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -498,12 +498,6 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
return NULL;
}
-static enum drm_connector_status cirrus_vga_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void cirrus_connector_destroy(struct drm_connector *connector)
{
drm_connector_cleanup(connector);
@@ -517,7 +511,6 @@ static const struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs
static const struct drm_connector_funcs cirrus_vga_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = cirrus_vga_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = cirrus_connector_destroy,
};
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c
index 5e7e63ce7bce..d6da848f7c6f 100644
--- a/drivers/gpu/drm/cirrus/cirrus_ttm.c
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -230,6 +230,7 @@ struct ttm_bo_driver cirrus_bo_driver = {
.ttm_tt_populate = cirrus_ttm_tt_populate,
.ttm_tt_unpopulate = cirrus_ttm_tt_unpopulate,
.init_mem_type = cirrus_bo_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = cirrus_bo_evict_flags,
.move = NULL,
.verify_access = cirrus_bo_verify_access,
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index e6862a744210..60697482b94c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -30,6 +30,8 @@
#include <drm/drm_atomic.h>
#include <drm/drm_mode.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_print.h>
+#include <linux/sync_file.h>
#include "drm_crtc_internal.h"
@@ -74,6 +76,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release);
int
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
{
+ kref_init(&state->ref);
+
/* TODO legacy paths should maybe do a better job about
* setting this appropriately?
*/
@@ -215,22 +219,16 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
EXPORT_SYMBOL(drm_atomic_state_clear);
/**
- * drm_atomic_state_free - free all memory for an atomic state
- * @state: atomic state to deallocate
+ * __drm_atomic_state_free - free all memory for an atomic state
+ * @ref: This atomic state to deallocate
*
* This frees all memory associated with an atomic state, including all the
* per-object state for planes, crtcs and connectors.
*/
-void drm_atomic_state_free(struct drm_atomic_state *state)
+void __drm_atomic_state_free(struct kref *ref)
{
- struct drm_device *dev;
- struct drm_mode_config *config;
-
- if (!state)
- return;
-
- dev = state->dev;
- config = &dev->mode_config;
+ struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
+ struct drm_mode_config *config = &state->dev->mode_config;
drm_atomic_state_clear(state);
@@ -243,7 +241,7 @@ void drm_atomic_state_free(struct drm_atomic_state *state)
kfree(state);
}
}
-EXPORT_SYMBOL(drm_atomic_state_free);
+EXPORT_SYMBOL(__drm_atomic_state_free);
/**
* drm_atomic_get_crtc_state - get crtc state
@@ -292,6 +290,23 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
}
EXPORT_SYMBOL(drm_atomic_get_crtc_state);
+static void set_out_fence_for_crtc(struct drm_atomic_state *state,
+ struct drm_crtc *crtc, s64 __user *fence_ptr)
+{
+ state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
+}
+
+static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+ s64 __user *fence_ptr;
+
+ fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
+ state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
+
+ return fence_ptr;
+}
+
/**
* drm_atomic_set_mode_for_crtc - set mode for CRTC
* @state: the CRTC whose incoming state to update
@@ -496,6 +511,16 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
&replaced);
state->color_mgmt_changed |= replaced;
return ret;
+ } else if (property == config->prop_out_fence_ptr) {
+ s64 __user *fence_ptr = u64_to_user_ptr(val);
+
+ if (!fence_ptr)
+ return 0;
+
+ if (put_user(-1, fence_ptr))
+ return -EFAULT;
+
+ set_out_fence_for_crtc(state->state, crtc, fence_ptr);
} else if (crtc->funcs->atomic_set_property)
return crtc->funcs->atomic_set_property(crtc, state, property, val);
else
@@ -538,6 +563,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
*val = (state->ctm) ? state->ctm->base.id : 0;
else if (property == config->gamma_lut_property)
*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
+ else if (property == config->prop_out_fence_ptr)
+ *val = 0;
else if (crtc->funcs->atomic_get_property)
return crtc->funcs->atomic_get_property(crtc, state, property, val);
else
@@ -609,6 +636,28 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
return 0;
}
+static void drm_atomic_crtc_print_state(struct drm_printer *p,
+ const struct drm_crtc_state *state)
+{
+ struct drm_crtc *crtc = state->crtc;
+
+ drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
+ drm_printf(p, "\tenable=%d\n", state->enable);
+ drm_printf(p, "\tactive=%d\n", state->active);
+ drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
+ drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
+ drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
+ drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed);
+ drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
+ drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
+ drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
+ drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
+ drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
+
+ if (crtc->funcs->atomic_print_state)
+ crtc->funcs->atomic_print_state(p, state);
+}
+
/**
* drm_atomic_get_plane_state - get plane state
* @state: global atomic state object
@@ -693,6 +742,17 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
drm_atomic_set_fb_for_plane(state, fb);
if (fb)
drm_framebuffer_unreference(fb);
+ } else if (property == config->prop_in_fence_fd) {
+ if (state->fence)
+ return -EINVAL;
+
+ if (U642I64(val) == -1)
+ return 0;
+
+ state->fence = sync_file_get_fence(val);
+ if (!state->fence)
+ return -EINVAL;
+
} else if (property == config->prop_crtc_id) {
struct drm_crtc *crtc = drm_crtc_find(dev, val);
return drm_atomic_set_crtc_for_plane(state, crtc);
@@ -712,7 +772,9 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
state->src_w = val;
} else if (property == config->prop_src_h) {
state->src_h = val;
- } else if (property == config->rotation_property) {
+ } else if (property == plane->rotation_property) {
+ if (!is_power_of_2(val & DRM_ROTATE_MASK))
+ return -EINVAL;
state->rotation = val;
} else if (property == plane->zpos_property) {
state->zpos = val;
@@ -752,6 +814,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
if (property == config->prop_fb_id) {
*val = (state->fb) ? state->fb->base.id : 0;
+ } else if (property == config->prop_in_fence_fd) {
+ *val = -1;
} else if (property == config->prop_crtc_id) {
*val = (state->crtc) ? state->crtc->base.id : 0;
} else if (property == config->prop_crtc_x) {
@@ -770,7 +834,7 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
*val = state->src_w;
} else if (property == config->prop_src_h) {
*val = state->src_h;
- } else if (property == config->rotation_property) {
+ } else if (property == plane->rotation_property) {
*val = state->rotation;
} else if (property == plane->zpos_property) {
*val = state->zpos;
@@ -840,9 +904,10 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
/* Check whether this plane supports the fb pixel format. */
ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format);
if (ret) {
- char *format_name = drm_get_format_name(state->fb->pixel_format);
- DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", format_name);
- kfree(format_name);
+ struct drm_format_name_buf format_name;
+ DRM_DEBUG_ATOMIC("Invalid pixel format %s\n",
+ drm_get_format_name(state->fb->pixel_format,
+ &format_name));
return ret;
}
@@ -883,6 +948,39 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
return 0;
}
+static void drm_atomic_plane_print_state(struct drm_printer *p,
+ const struct drm_plane_state *state)
+{
+ struct drm_plane *plane = state->plane;
+ struct drm_rect src = drm_plane_state_src(state);
+ struct drm_rect dest = drm_plane_state_dest(state);
+
+ drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
+ drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
+ drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
+ if (state->fb) {
+ struct drm_framebuffer *fb = state->fb;
+ int i, n = drm_format_num_planes(fb->pixel_format);
+ struct drm_format_name_buf format_name;
+
+ drm_printf(p, "\t\tformat=%s\n",
+ drm_get_format_name(fb->pixel_format, &format_name));
+ drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier);
+ drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height);
+ drm_printf(p, "\t\tlayers:\n");
+ for (i = 0; i < n; i++) {
+ drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]);
+ drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]);
+ }
+ }
+ drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
+ drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
+ drm_printf(p, "\trotation=%x\n", state->rotation);
+
+ if (plane->funcs->atomic_print_state)
+ plane->funcs->atomic_print_state(p, state);
+}
+
/**
* drm_atomic_get_connector_state - get connector state
* @state: global atomic state object
@@ -989,15 +1087,53 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
* now?) atomic writes to DPMS property:
*/
return -EINVAL;
+ } else if (property == config->tv_select_subconnector_property) {
+ state->tv.subconnector = val;
+ } else if (property == config->tv_left_margin_property) {
+ state->tv.margins.left = val;
+ } else if (property == config->tv_right_margin_property) {
+ state->tv.margins.right = val;
+ } else if (property == config->tv_top_margin_property) {
+ state->tv.margins.top = val;
+ } else if (property == config->tv_bottom_margin_property) {
+ state->tv.margins.bottom = val;
+ } else if (property == config->tv_mode_property) {
+ state->tv.mode = val;
+ } else if (property == config->tv_brightness_property) {
+ state->tv.brightness = val;
+ } else if (property == config->tv_contrast_property) {
+ state->tv.contrast = val;
+ } else if (property == config->tv_flicker_reduction_property) {
+ state->tv.flicker_reduction = val;
+ } else if (property == config->tv_overscan_property) {
+ state->tv.overscan = val;
+ } else if (property == config->tv_saturation_property) {
+ state->tv.saturation = val;
+ } else if (property == config->tv_hue_property) {
+ state->tv.hue = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
} else {
return -EINVAL;
}
+
+ return 0;
}
EXPORT_SYMBOL(drm_atomic_connector_set_property);
+static void drm_atomic_connector_print_state(struct drm_printer *p,
+ const struct drm_connector_state *state)
+{
+ struct drm_connector *connector = state->connector;
+
+ drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
+ drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
+
+ if (connector->funcs->atomic_print_state)
+ connector->funcs->atomic_print_state(p, state);
+}
+
/**
* drm_atomic_connector_get_property - get property value from connector state
* @connector: the drm connector to set a property on
@@ -1025,6 +1161,30 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = (state->crtc) ? state->crtc->base.id : 0;
} else if (property == config->dpms_property) {
*val = connector->dpms;
+ } else if (property == config->tv_select_subconnector_property) {
+ *val = state->tv.subconnector;
+ } else if (property == config->tv_left_margin_property) {
+ *val = state->tv.margins.left;
+ } else if (property == config->tv_right_margin_property) {
+ *val = state->tv.margins.right;
+ } else if (property == config->tv_top_margin_property) {
+ *val = state->tv.margins.top;
+ } else if (property == config->tv_bottom_margin_property) {
+ *val = state->tv.margins.bottom;
+ } else if (property == config->tv_mode_property) {
+ *val = state->tv.mode;
+ } else if (property == config->tv_brightness_property) {
+ *val = state->tv.brightness;
+ } else if (property == config->tv_contrast_property) {
+ *val = state->tv.contrast;
+ } else if (property == config->tv_flicker_reduction_property) {
+ *val = state->tv.flicker_reduction;
+ } else if (property == config->tv_overscan_property) {
+ *val = state->tv.overscan;
+ } else if (property == config->tv_saturation_property) {
+ *val = state->tv.saturation;
+ } else if (property == config->tv_hue_property) {
+ *val = state->tv.hue;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
@@ -1136,22 +1296,48 @@ void
drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
struct drm_framebuffer *fb)
{
- if (plane_state->fb)
- drm_framebuffer_unreference(plane_state->fb);
- if (fb)
- drm_framebuffer_reference(fb);
- plane_state->fb = fb;
-
if (fb)
DRM_DEBUG_ATOMIC("Set [FB:%d] for plane state %p\n",
fb->base.id, plane_state);
else
DRM_DEBUG_ATOMIC("Set [NOFB] for plane state %p\n",
plane_state);
+
+ drm_framebuffer_assign(&plane_state->fb, fb);
}
EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
/**
+ * drm_atomic_set_fence_for_plane - set fence for plane
+ * @plane_state: atomic state object for the plane
+ * @fence: dma_fence to use for the plane
+ *
+ * Helper to setup the plane_state fence in case it is not set yet.
+ * By using this drivers doesn't need to worry if the user choose
+ * implicit or explicit fencing.
+ *
+ * This function will not set the fence to the state if it was set
+ * via explicit fencing interfaces on the atomic ioctl. It will
+ * all drope the reference to the fence as we not storing it
+ * anywhere.
+ *
+ * Otherwise, if plane_state->fence is not set this function we
+ * just set it with the received implict fence.
+ */
+void
+drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+ struct dma_fence *fence)
+{
+ if (plane_state->fence) {
+ dma_fence_put(fence);
+ return;
+ }
+
+ plane_state->fence = fence;
+}
+EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
+
+/**
* drm_atomic_set_crtc_for_connector - set crtc for connector
* @conn_state: atomic state object for the connector
* @crtc: crtc to use for the connector
@@ -1462,16 +1648,107 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
}
EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
+static void drm_atomic_print_state(const struct drm_atomic_state *state)
+{
+ struct drm_printer p = drm_info_printer(state->dev->dev);
+ struct drm_plane *plane;
+ struct drm_plane_state *plane_state;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector *connector;
+ struct drm_connector_state *connector_state;
+ int i;
+
+ DRM_DEBUG_ATOMIC("checking %p\n", state);
+
+ for_each_plane_in_state(state, plane, plane_state, i)
+ drm_atomic_plane_print_state(&p, plane_state);
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i)
+ drm_atomic_crtc_print_state(&p, crtc_state);
+
+ for_each_connector_in_state(state, connector, connector_state, i)
+ drm_atomic_connector_print_state(&p, connector_state);
+}
+
+/**
+ * drm_state_dump - dump entire device atomic state
+ * @dev: the drm device
+ * @p: where to print the state to
+ *
+ * Just for debugging. Drivers might want an option to dump state
+ * to dmesg in case of error irq's. (Hint, you probably want to
+ * ratelimit this!)
+ *
+ * The caller must drm_modeset_lock_all(), or if this is called
+ * from error irq handler, it should not be enabled by default.
+ * (Ie. if you are debugging errors you might not care that this
+ * is racey. But calling this without all modeset locks held is
+ * not inherently safe.)
+ */
+void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
+{
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_connector *connector;
+
+ if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+ return;
+
+ list_for_each_entry(plane, &config->plane_list, head)
+ drm_atomic_plane_print_state(p, plane->state);
+
+ list_for_each_entry(crtc, &config->crtc_list, head)
+ drm_atomic_crtc_print_state(p, crtc->state);
+
+ list_for_each_entry(connector, &config->connector_list, head)
+ drm_atomic_connector_print_state(p, connector->state);
+}
+EXPORT_SYMBOL(drm_state_dump);
+
+#ifdef CONFIG_DEBUG_FS
+static int drm_state_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ drm_modeset_lock_all(dev);
+ drm_state_dump(dev, &p);
+ drm_modeset_unlock_all(dev);
+
+ return 0;
+}
+
+/* any use in debugfs files to dump individual planes/crtc/etc? */
+static const struct drm_info_list drm_atomic_debugfs_list[] = {
+ {"state", drm_state_info, 0},
+};
+
+int drm_atomic_debugfs_init(struct drm_minor *minor)
+{
+ return drm_debugfs_create_files(drm_atomic_debugfs_list,
+ ARRAY_SIZE(drm_atomic_debugfs_list),
+ minor->debugfs_root, minor);
+}
+
+int drm_atomic_debugfs_cleanup(struct drm_minor *minor)
+{
+ return drm_debugfs_remove_files(drm_atomic_debugfs_list,
+ ARRAY_SIZE(drm_atomic_debugfs_list),
+ minor);
+}
+#endif
+
/*
* The big monstor ioctl
*/
static struct drm_pending_vblank_event *create_vblank_event(
- struct drm_device *dev, struct drm_file *file_priv,
- struct fence *fence, uint64_t user_data)
+ struct drm_device *dev, uint64_t user_data)
{
struct drm_pending_vblank_event *e = NULL;
- int ret;
e = kzalloc(sizeof *e, GFP_KERNEL);
if (!e)
@@ -1481,17 +1758,6 @@ static struct drm_pending_vblank_event *create_vblank_event(
e->event.base.length = sizeof(e->event);
e->event.user_data = user_data;
- if (file_priv) {
- ret = drm_event_reserve_init(dev, file_priv, &e->base,
- &e->event.base);
- if (ret) {
- kfree(e);
- return NULL;
- }
- }
-
- e->base.fence = fence;
-
return e;
}
@@ -1596,6 +1862,203 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_atomic_clean_old_fb);
+/**
+ * DOC: explicit fencing properties
+ *
+ * Explicit fencing allows userspace to control the buffer synchronization
+ * between devices. A Fence or a group of fences are transfered to/from
+ * userspace using Sync File fds and there are two DRM properties for that.
+ * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
+ * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
+ *
+ * As a contrast, with implicit fencing the kernel keeps track of any
+ * ongoing rendering, and automatically ensures that the atomic update waits
+ * for any pending rendering to complete. For shared buffers represented with
+ * a struct &dma_buf this is tracked in &reservation_object structures.
+ * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
+ * whereas explicit fencing is what Android wants.
+ *
+ * "IN_FENCE_FDâ€:
+ * Use this property to pass a fence that DRM should wait on before
+ * proceeding with the Atomic Commit request and show the framebuffer for
+ * the plane on the screen. The fence can be either a normal fence or a
+ * merged one, the sync_file framework will handle both cases and use a
+ * fence_array if a merged fence is received. Passing -1 here means no
+ * fences to wait on.
+ *
+ * If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
+ * it will only check if the Sync File is a valid one.
+ *
+ * On the driver side the fence is stored on the @fence parameter of
+ * struct &drm_plane_state. Drivers which also support implicit fencing
+ * should set the implicit fence using drm_atomic_set_fence_for_plane(),
+ * to make sure there's consistent behaviour between drivers in precedence
+ * of implicit vs. explicit fencing.
+ *
+ * "OUT_FENCE_PTRâ€:
+ * Use this property to pass a file descriptor pointer to DRM. Once the
+ * Atomic Commit request call returns OUT_FENCE_PTR will be filled with
+ * the file descriptor number of a Sync File. This Sync File contains the
+ * CRTC fence that will be signaled when all framebuffers present on the
+ * Atomic Commit * request for that given CRTC are scanned out on the
+ * screen.
+ *
+ * The Atomic Commit request fails if a invalid pointer is passed. If the
+ * Atomic Commit request fails for any other reason the out fence fd
+ * returned will be -1. On a Atomic Commit with the
+ * DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
+ *
+ * Note that out-fences don't have a special interface to drivers and are
+ * internally represented by a struct &drm_pending_vblank_event in struct
+ * &drm_crtc_state, which is also used by the nonblocking atomic commit
+ * helpers and for the DRM event handling for existing userspace.
+ */
+
+struct drm_out_fence_state {
+ s64 __user *out_fence_ptr;
+ struct sync_file *sync_file;
+ int fd;
+};
+
+static int setup_out_fence(struct drm_out_fence_state *fence_state,
+ struct dma_fence *fence)
+{
+ fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+ if (fence_state->fd < 0)
+ return fence_state->fd;
+
+ if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+ return -EFAULT;
+
+ fence_state->sync_file = sync_file_create(fence);
+ if (!fence_state->sync_file)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int prepare_crtc_signaling(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ struct drm_mode_atomic *arg,
+ struct drm_file *file_priv,
+ struct drm_out_fence_state **fence_state,
+ unsigned int *num_fences)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ int i, ret;
+
+ if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
+ return 0;
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ u64 __user *fence_ptr;
+
+ fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
+
+ if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
+ struct drm_pending_vblank_event *e;
+
+ e = create_vblank_event(dev, arg->user_data);
+ if (!e)
+ return -ENOMEM;
+
+ crtc_state->event = e;
+ }
+
+ if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+ struct drm_pending_vblank_event *e = crtc_state->event;
+
+ if (!file_priv)
+ continue;
+
+ ret = drm_event_reserve_init(dev, file_priv, &e->base,
+ &e->event.base);
+ if (ret) {
+ kfree(e);
+ crtc_state->event = NULL;
+ return ret;
+ }
+ }
+
+ if (fence_ptr) {
+ struct dma_fence *fence;
+ struct drm_out_fence_state *f;
+
+ f = krealloc(*fence_state, sizeof(**fence_state) *
+ (*num_fences + 1), GFP_KERNEL);
+ if (!f)
+ return -ENOMEM;
+
+ memset(&f[*num_fences], 0, sizeof(*f));
+
+ f[*num_fences].out_fence_ptr = fence_ptr;
+ *fence_state = f;
+
+ fence = drm_crtc_create_fence(crtc);
+ if (!fence)
+ return -ENOMEM;
+
+ ret = setup_out_fence(&f[(*num_fences)++], fence);
+ if (ret) {
+ dma_fence_put(fence);
+ return ret;
+ }
+
+ crtc_state->event->base.fence = fence;
+ }
+ }
+
+ return 0;
+}
+
+static void complete_crtc_signaling(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ struct drm_out_fence_state *fence_state,
+ unsigned int num_fences,
+ bool install_fds)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ int i;
+
+ if (install_fds) {
+ for (i = 0; i < num_fences; i++)
+ fd_install(fence_state[i].fd,
+ fence_state[i].sync_file->file);
+
+ kfree(fence_state);
+ return;
+ }
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ /*
+ * TEST_ONLY and PAGE_FLIP_EVENT are mutually
+ * exclusive, if they weren't, this code should be
+ * called on success for TEST_ONLY too.
+ */
+ if (crtc_state->event)
+ drm_event_cancel_free(dev, &crtc_state->event->base);
+ }
+
+ if (!fence_state)
+ return;
+
+ for (i = 0; i < num_fences; i++) {
+ if (fence_state[i].sync_file)
+ fput(fence_state[i].sync_file->file);
+ if (fence_state[i].fd >= 0)
+ put_unused_fd(fence_state[i].fd);
+
+ /* If this fails log error to the user */
+ if (fence_state[i].out_fence_ptr &&
+ put_user(-1, fence_state[i].out_fence_ptr))
+ DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
+ }
+
+ kfree(fence_state);
+}
+
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
@@ -1608,11 +2071,10 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_atomic_state *state;
struct drm_modeset_acquire_ctx ctx;
struct drm_plane *plane;
- struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
+ struct drm_out_fence_state *fence_state = NULL;
unsigned plane_mask;
int ret = 0;
- unsigned int i, j;
+ unsigned int i, j, num_fences = 0;
/* disallow for drivers not supporting atomic: */
if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
@@ -1727,50 +2189,30 @@ retry:
drm_mode_object_unreference(obj);
}
- if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- struct drm_pending_vblank_event *e;
-
- e = create_vblank_event(dev, file_priv, NULL,
- arg->user_data);
- if (!e) {
- ret = -ENOMEM;
- goto out;
- }
-
- crtc_state->event = e;
- }
- }
+ ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,
+ &num_fences);
+ if (ret)
+ goto out;
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
/*
* Unlike commit, check_only does not clean up state.
- * Below we call drm_atomic_state_free for it.
+ * Below we call drm_atomic_state_put for it.
*/
ret = drm_atomic_check_only(state);
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
ret = drm_atomic_nonblocking_commit(state);
} else {
+ if (unlikely(drm_debug & DRM_UT_STATE))
+ drm_atomic_print_state(state);
+
ret = drm_atomic_commit(state);
}
out:
drm_atomic_clean_old_fb(dev, plane_mask, ret);
- if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
- /*
- * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
- * if they weren't, this code should be called on success
- * for TEST_ONLY too.
- */
-
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- if (!crtc_state->event)
- continue;
-
- drm_event_cancel_free(dev, &crtc_state->event->base);
- }
- }
+ complete_crtc_signaling(dev, state, fence_state, num_fences, !ret);
if (ret == -EDEADLK) {
drm_atomic_state_clear(state);
@@ -1778,8 +2220,7 @@ out:
goto retry;
}
- if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 21f992605541..583f47f27b36 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -30,7 +30,7 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_atomic_helper.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include "drm_crtc_internal.h"
@@ -458,10 +458,11 @@ mode_fixup(struct drm_atomic_state *state)
* removed from the crtc.
* crtc_state->active_changed is set when crtc_state->active changes,
* which is used for dpms.
+ * See also: drm_atomic_crtc_needs_modeset()
*
* IMPORTANT:
*
- * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a
+ * Drivers which set ->mode_changed (e.g. in their ->atomic_check hooks if a
* plane update can't be done without a full modeset) _must_ call this function
* afterwards after that change. It is permitted to call this function multiple
* times for the same update, e.g. when the ->atomic_check functions depend upon
@@ -510,9 +511,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
for_each_connector_in_state(state, connector, connector_state, i) {
/*
- * This only sets crtc->mode_changed for routing changes,
- * drivers must set crtc->mode_changed themselves when connector
- * properties need to be updated.
+ * This only sets crtc->connectors_changed for routing changes,
+ * drivers must set crtc->connectors_changed themselves when
+ * connector properties need to be updated.
*/
ret = update_connector_routing(state, connector,
connector_state);
@@ -1005,14 +1006,22 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
* drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
* @dev: DRM device
* @state: atomic state object with old state structures
- * @pre_swap: if true, do an interruptible wait
+ * @pre_swap: If true, do an interruptible wait, and @state is the new state.
+ * Otherwise @state is the old state.
*
* For implicit sync, driver should fish the exclusive fence out from the
* incoming fb's and stash it in the drm_plane_state. This is called after
* drm_atomic_helper_swap_state() so it uses the current plane state (and
* just uses the atomic state to find the changed planes)
*
- * Returns zero if success or < 0 if fence_wait() fails.
+ * Note that @pre_swap is needed since the point where we block for fences moves
+ * around depending upon whether an atomic commit is blocking or
+ * non-blocking. For async commit all waiting needs to happen after
+ * drm_atomic_helper_swap_state() is called, but for synchronous commits we want
+ * to wait **before** we do anything that can't be easily rolled back. That is
+ * before we call drm_atomic_helper_swap_state().
+ *
+ * Returns zero if success or < 0 if dma_fence_wait() fails.
*/
int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
struct drm_atomic_state *state,
@@ -1036,11 +1045,11 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
* still interrupt the operation. Instead of blocking until the
* timer expires, make the wait interruptible.
*/
- ret = fence_wait(plane_state->fence, pre_swap);
+ ret = dma_fence_wait(plane_state->fence, pre_swap);
if (ret)
return ret;
- fence_put(plane_state->fence);
+ dma_fence_put(plane_state->fence);
plane_state->fence = NULL;
}
@@ -1146,7 +1155,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
/**
* drm_atomic_helper_commit_tail - commit atomic update to hardware
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
*
* This is the default implemenation for the ->atomic_commit_tail() hook of the
* &drm_mode_config_helper_funcs vtable.
@@ -1157,53 +1166,53 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
*
* For drivers supporting runtime PM the recommended sequence is instead ::
*
- * drm_atomic_helper_commit_modeset_disables(dev, state);
+ * drm_atomic_helper_commit_modeset_disables(dev, old_state);
*
- * drm_atomic_helper_commit_modeset_enables(dev, state);
+ * drm_atomic_helper_commit_modeset_enables(dev, old_state);
*
- * drm_atomic_helper_commit_planes(dev, state,
+ * drm_atomic_helper_commit_planes(dev, old_state,
* DRM_PLANE_COMMIT_ACTIVE_ONLY);
*
* for committing the atomic update to hardware. See the kerneldoc entries for
* these three functions for more details.
*/
-void drm_atomic_helper_commit_tail(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
{
- struct drm_device *dev = state->dev;
+ struct drm_device *dev = old_state->dev;
- drm_atomic_helper_commit_modeset_disables(dev, state);
+ drm_atomic_helper_commit_modeset_disables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, state, 0);
+ drm_atomic_helper_commit_planes(dev, old_state, 0);
- drm_atomic_helper_commit_modeset_enables(dev, state);
+ drm_atomic_helper_commit_modeset_enables(dev, old_state);
- drm_atomic_helper_commit_hw_done(state);
+ drm_atomic_helper_commit_hw_done(old_state);
- drm_atomic_helper_wait_for_vblanks(dev, state);
+ drm_atomic_helper_wait_for_vblanks(dev, old_state);
- drm_atomic_helper_cleanup_planes(dev, state);
+ drm_atomic_helper_cleanup_planes(dev, old_state);
}
EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
-static void commit_tail(struct drm_atomic_state *state)
+static void commit_tail(struct drm_atomic_state *old_state)
{
- struct drm_device *dev = state->dev;
+ struct drm_device *dev = old_state->dev;
struct drm_mode_config_helper_funcs *funcs;
funcs = dev->mode_config.helper_private;
- drm_atomic_helper_wait_for_fences(dev, state, false);
+ drm_atomic_helper_wait_for_fences(dev, old_state, false);
- drm_atomic_helper_wait_for_dependencies(state);
+ drm_atomic_helper_wait_for_dependencies(old_state);
if (funcs && funcs->atomic_commit_tail)
- funcs->atomic_commit_tail(state);
+ funcs->atomic_commit_tail(old_state);
else
- drm_atomic_helper_commit_tail(state);
+ drm_atomic_helper_commit_tail(old_state);
- drm_atomic_helper_commit_cleanup_done(state);
+ drm_atomic_helper_commit_cleanup_done(old_state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(old_state);
}
static void commit_work(struct work_struct *work)
@@ -1225,9 +1234,6 @@ static void commit_work(struct work_struct *work)
* function implements nonblocking commits, using
* drm_atomic_helper_setup_commit() and related functions.
*
- * Note that right now this function does not support nonblocking commits, hence
- * driver writers must implement their own version for now.
- *
* Committing the actual hardware state is done through the
* ->atomic_commit_tail() callback of the &drm_mode_config_helper_funcs vtable,
* or it's default implementation drm_atomic_helper_commit_tail().
@@ -1285,6 +1291,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
* make sure work items don't artifically stall on each another.
*/
+ drm_atomic_state_get(state);
if (nonblock)
queue_work(system_unbound_wq, &state->commit_work);
else
@@ -1496,10 +1503,10 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
/**
* drm_atomic_helper_wait_for_dependencies - wait for required preceeding commits
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
*
* This function waits for all preceeding commits that touch the same CRTC as
- * @state to both be committed to the hardware (as signalled by
+ * @old_state to both be committed to the hardware (as signalled by
* drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled
* by calling drm_crtc_vblank_send_event on the event member of
* &drm_crtc_state).
@@ -1507,7 +1514,7 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
* This is part of the atomic helper support for nonblocking commits, see
* drm_atomic_helper_setup_commit() for an overview.
*/
-void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
+void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
@@ -1515,7 +1522,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
int i;
long ret;
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
spin_lock(&crtc->commit_lock);
commit = preceeding_commit(crtc);
if (commit)
@@ -1546,7 +1553,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
/**
* drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
*
* This function is used to signal completion of the hardware commit step. After
* this step the driver is not allowed to read or change any permanent software
@@ -1559,15 +1566,15 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
* This is part of the atomic helper support for nonblocking commits, see
* drm_atomic_helper_setup_commit() for an overview.
*/
-void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
struct drm_crtc_commit *commit;
int i;
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- commit = state->crtcs[i].commit;
+ for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+ commit = old_state->crtcs[i].commit;
if (!commit)
continue;
@@ -1582,16 +1589,16 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
/**
* drm_atomic_helper_commit_cleanup_done - signal completion of commit
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
*
- * This signals completion of the atomic update @state, including any cleanup
- * work. If used, it must be called right before calling
- * drm_atomic_state_free().
+ * This signals completion of the atomic update @old_state, including any
+ * cleanup work. If used, it must be called right before calling
+ * drm_atomic_state_put().
*
* This is part of the atomic helper support for nonblocking commits, see
* drm_atomic_helper_setup_commit() for an overview.
*/
-void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
@@ -1599,8 +1606,8 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
int i;
long ret;
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- commit = state->crtcs[i].commit;
+ for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+ commit = old_state->crtcs[i].commit;
if (WARN_ON(!commit))
continue;
@@ -2109,18 +2116,13 @@ retry:
state->legacy_cursor_update = true;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2182,18 +2184,13 @@ retry:
goto fail;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2322,18 +2319,13 @@ retry:
goto fail;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2408,7 +2400,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
primary_state->crtc_h = vdisplay;
primary_state->src_x = set->x << 16;
primary_state->src_y = set->y << 16;
- if (primary_state->rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) {
+ if (drm_rotation_90_or_270(primary_state->rotation)) {
primary_state->src_w = vdisplay << 16;
primary_state->src_h = hdisplay << 16;
} else {
@@ -2475,11 +2467,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
}
err = drm_atomic_commit(state);
-
free:
- if (err < 0)
- drm_atomic_state_free(state);
-
+ drm_atomic_state_put(state);
return err;
}
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
@@ -2530,7 +2519,7 @@ retry:
err = drm_atomic_helper_disable_all(dev, &ctx);
if (err < 0) {
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
state = ERR_PTR(err);
goto unlock;
}
@@ -2619,18 +2608,13 @@ retry:
goto fail;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2679,18 +2663,13 @@ retry:
goto fail;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2739,18 +2718,13 @@ retry:
goto fail;
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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2823,18 +2797,13 @@ retry:
}
ret = drm_atomic_nonblocking_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);
-
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -2910,19 +2879,14 @@ retry:
crtc_state->active = active;
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;
-
- connector->dpms = old_mode;
- drm_atomic_state_free(state);
-
+ if (ret != 0)
+ connector->dpms = old_mode;
+ drm_atomic_state_put(state);
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
@@ -3113,6 +3077,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
if (state->fb)
drm_framebuffer_reference(state->fb);
+
+ state->fence = NULL;
}
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
@@ -3151,6 +3117,9 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
{
if (state->fb)
drm_framebuffer_unreference(state->fb);
+
+ if (state->fence)
+ dma_fence_put(state->fence);
}
EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
@@ -3329,7 +3298,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
free:
if (err < 0) {
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
state = ERR_PTR(err);
}
@@ -3444,22 +3413,14 @@ retry:
goto fail;
ret = drm_atomic_commit(state);
- if (ret)
- goto fail;
-
- /* Driver takes ownership of state on successful commit. */
-
- drm_property_unreference_blob(blob);
-
- return 0;
fail:
if (ret == -EDEADLK)
goto backoff;
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
drm_property_unreference_blob(blob);
-
return ret;
+
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 85172a977bf3..1f2412c7ccfd 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -89,7 +89,7 @@
* On top of this basic transformation additional properties can be exposed by
* the driver:
*
- * - Rotation is set up with drm_mode_create_rotation_property(). It adds a
+ * - Rotation is set up with drm_plane_create_rotation_property(). It adds a
* rotation and reflection step between the source and destination rectangles.
* Without this property the rectangle is only scaled, but not rotated or
* reflected.
@@ -105,18 +105,12 @@
*/
/**
- * drm_mode_create_rotation_property - create a new rotation property
- * @dev: DRM device
+ * drm_plane_create_rotation_property - create a new rotation property
+ * @plane: drm plane
+ * @rotation: initial value of the rotation property
* @supported_rotations: bitmask of supported rotations and reflections
*
* This creates a new property with the selected support for transformations.
- * The resulting property should be stored in @rotation_property in
- * &drm_mode_config. It then must be attached to each plane which supports
- * rotations using drm_object_attach_property().
- *
- * FIXME: Probably better if the rotation property is created on each plane,
- * like the zpos property. Otherwise it's not possible to allow different
- * rotation modes on different planes.
*
* Since a rotation by 180° degress is the same as reflecting both along the x
* and the y axis the rotation property is somewhat redundant. Drivers can use
@@ -144,8 +138,9 @@
* rotation. After reflection, the rotation is applied to the image sampled from
* the source rectangle, before scaling it to fit the destination rectangle.
*/
-struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
- unsigned int supported_rotations)
+int drm_plane_create_rotation_property(struct drm_plane *plane,
+ unsigned int rotation,
+ unsigned int supported_rotations)
{
static const struct drm_prop_enum_list props[] = {
{ __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" },
@@ -155,12 +150,28 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
{ __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" },
{ __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" },
};
+ struct drm_property *prop;
+
+ WARN_ON((supported_rotations & DRM_ROTATE_MASK) == 0);
+ WARN_ON(!is_power_of_2(rotation & DRM_ROTATE_MASK));
+ WARN_ON(rotation & ~supported_rotations);
- return drm_property_create_bitmask(dev, 0, "rotation",
+ prop = drm_property_create_bitmask(plane->dev, 0, "rotation",
props, ARRAY_SIZE(props),
supported_rotations);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&plane->base, prop, rotation);
+
+ if (plane->state)
+ plane->state->rotation = rotation;
+
+ plane->rotation_property = prop;
+
+ return 0;
}
-EXPORT_SYMBOL(drm_mode_create_rotation_property);
+EXPORT_SYMBOL(drm_plane_create_rotation_property);
/**
* drm_rotation_simplify() - Try to simplify the rotation
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index d28ffdd2b929..6543ebde501a 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -41,6 +41,10 @@
* nor use all the elements of the LUT (for example the hardware might
* choose to interpolate between LUT[0] and LUT[4]).
*
+ * Setting this to NULL (blob property value set to 0) means a
+ * linear/pass-thru gamma table should be used. This is generally the
+ * driver boot-up state too.
+ *
* “DEGAMMA_LUT_SIZEâ€:
* Unsinged range property to give the size of the lookup table to be set
* on the DEGAMMA_LUT property (the size depends on the underlying
@@ -54,6 +58,10 @@
* lookup through the gamma LUT. The data is interpreted as a struct
* &drm_color_ctm.
*
+ * Setting this to NULL (blob property value set to 0) means a
+ * unit/pass-thru matrix should be used. This is generally the driver
+ * boot-up state too.
+ *
* “GAMMA_LUTâ€:
* Blob property to set the gamma lookup table (LUT) mapping pixel data
* after the transformation matrix to data sent to the connector. The
@@ -62,6 +70,10 @@
* nor use all the elements of the LUT (for example the hardware might
* choose to interpolate between LUT[0] and LUT[4]).
*
+ * Setting this to NULL (blob property value set to 0) means a
+ * linear/pass-thru gamma table should be used. This is generally the
+ * driver boot-up state too.
+ *
* “GAMMA_LUT_SIZEâ€:
* Unsigned range property to give the size of the lookup table to be set
* on the GAMMA_LUT property (the size depends on the underlying hardware).
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 2db7fb510b6c..5a4526289392 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -588,6 +588,50 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
drm_tv_subconnector_enum_list)
+/**
+ * DOC: standard connector properties
+ *
+ * DRM connectors have a few standardized properties:
+ *
+ * EDID:
+ * Blob property which contains the current EDID read from the sink. This
+ * is useful to parse sink identification information like vendor, model
+ * and serial. Drivers should update this property by calling
+ * drm_mode_connector_update_edid_property(), usually after having parsed
+ * the EDID using drm_add_edid_modes(). Userspace cannot change this
+ * property.
+ * DPMS:
+ * Legacy property for setting the power state of the connector. For atomic
+ * drivers this is only provided for backwards compatibility with existing
+ * drivers, it remaps to controlling the "ACTIVE" property on the CRTC the
+ * connector is linked to. Drivers should never set this property directly,
+ * it is handled by the DRM core by calling the ->dpms() callback in
+ * &drm_connector_funcs. Atomic drivers should implement this hook using
+ * drm_atomic_helper_connector_dpms(). This is the only property standard
+ * connector property that userspace can change.
+ * PATH:
+ * Connector path property to identify how this sink is physically
+ * connected. Used by DP MST. This should be set by calling
+ * drm_mode_connector_set_path_property(), in the case of DP MST with the
+ * path property the MST manager created. Userspace cannot change this
+ * property.
+ * TILE:
+ * Connector tile group property to indicate how a set of DRM connector
+ * compose together into one logical screen. This is used by both high-res
+ * external screens (often only using a single cable, but exposing multiple
+ * DP MST sinks), or high-res integrated panels (like dual-link DSI) which
+ * are not gen-locked. Note that for tiled panels which are genlocked, like
+ * dual-link LVDS or dual-link DSI, the driver should try to not expose the
+ * tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
+ * should update this value using drm_mode_connector_set_tile_property().
+ * Userspace cannot change this property.
+ *
+ * Connectors also have one standardized atomic property:
+ *
+ * CRTC_ID:
+ * Mode object ID of the &drm_crtc this connector should be connected to.
+ */
+
int drm_connector_create_standard_properties(struct drm_device *dev)
{
struct drm_property *prop;
@@ -1121,3 +1165,107 @@ out_unlock:
return ret;
}
+
+/**
+ * DOC: Tile group
+ *
+ * Tile groups are used to represent tiled monitors with a unique integer
+ * identifier. Tiled monitors using DisplayID v1.3 have a unique 8-byte handle,
+ * we store this in a tile group, so we have a common identifier for all tiles
+ * in a monitor group. The property is called "TILE". Drivers can manage tile
+ * groups using drm_mode_create_tile_group(), drm_mode_put_tile_group() and
+ * drm_mode_get_tile_group(). But this is only needed for internal panels where
+ * the tile group information is exposed through a non-standard way.
+ */
+
+static void drm_tile_group_free(struct kref *kref)
+{
+ struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
+ struct drm_device *dev = tg->dev;
+ mutex_lock(&dev->mode_config.idr_mutex);
+ idr_remove(&dev->mode_config.tile_idr, tg->id);
+ mutex_unlock(&dev->mode_config.idr_mutex);
+ kfree(tg);
+}
+
+/**
+ * drm_mode_put_tile_group - drop a reference to a tile group.
+ * @dev: DRM device
+ * @tg: tile group to drop reference to.
+ *
+ * drop reference to tile group and free if 0.
+ */
+void drm_mode_put_tile_group(struct drm_device *dev,
+ struct drm_tile_group *tg)
+{
+ kref_put(&tg->refcount, drm_tile_group_free);
+}
+EXPORT_SYMBOL(drm_mode_put_tile_group);
+
+/**
+ * drm_mode_get_tile_group - get a reference to an existing tile group
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Use the unique bytes to get a reference to an existing tile group.
+ *
+ * RETURNS:
+ * tile group or NULL if not found.
+ */
+struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+ char topology[8])
+{
+ struct drm_tile_group *tg;
+ int id;
+ mutex_lock(&dev->mode_config.idr_mutex);
+ idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
+ if (!memcmp(tg->group_data, topology, 8)) {
+ if (!kref_get_unless_zero(&tg->refcount))
+ tg = NULL;
+ mutex_unlock(&dev->mode_config.idr_mutex);
+ return tg;
+ }
+ }
+ mutex_unlock(&dev->mode_config.idr_mutex);
+ return NULL;
+}
+EXPORT_SYMBOL(drm_mode_get_tile_group);
+
+/**
+ * drm_mode_create_tile_group - create a tile group from a displayid description
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Create a tile group for the unique monitor, and get a unique
+ * identifier for the tile group.
+ *
+ * RETURNS:
+ * new tile group or error.
+ */
+struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+ char topology[8])
+{
+ struct drm_tile_group *tg;
+ int ret;
+
+ tg = kzalloc(sizeof(*tg), GFP_KERNEL);
+ if (!tg)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&tg->refcount);
+ memcpy(tg->group_data, topology, 8);
+ tg->dev = dev;
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+ ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
+ if (ret >= 0) {
+ tg->id = ret;
+ } else {
+ kfree(tg);
+ tg = ERR_PTR(ret);
+ }
+
+ mutex_unlock(&dev->mode_config.idr_mutex);
+ return tg;
+}
+EXPORT_SYMBOL(drm_mode_create_tile_group);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 2d7bedf28647..e75f62cd8a65 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -33,6 +33,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/dma-fence.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
@@ -40,23 +41,11 @@
#include <drm/drm_modeset_lock.h>
#include <drm/drm_atomic.h>
#include <drm/drm_auth.h>
-#include <drm/drm_framebuffer.h>
+#include <drm/drm_debugfs_crc.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
-/*
- * Global properties
- */
-static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
- { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
- { DRM_PLANE_TYPE_PRIMARY, "Primary" },
- { DRM_PLANE_TYPE_CURSOR, "Cursor" },
-};
-
-/*
- * Optional properties
- */
/**
* drm_crtc_force_disable - Forcibly turn off a CRTC
* @crtc: CRTC to turn off
@@ -102,8 +91,6 @@ out:
}
EXPORT_SYMBOL(drm_crtc_force_disable_all);
-DEFINE_WW_CLASS(crtc_ww_class);
-
static unsigned int drm_num_crtcs(struct drm_device *dev)
{
unsigned int num = 0;
@@ -116,12 +103,16 @@ static unsigned int drm_num_crtcs(struct drm_device *dev)
return num;
}
-static int drm_crtc_register_all(struct drm_device *dev)
+int drm_crtc_register_all(struct drm_device *dev)
{
struct drm_crtc *crtc;
int ret = 0;
drm_for_each_crtc(crtc, dev) {
+ if (drm_debugfs_crtc_add(crtc))
+ DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n",
+ crtc->name);
+
if (crtc->funcs->late_register)
ret = crtc->funcs->late_register(crtc);
if (ret)
@@ -131,16 +122,84 @@ static int drm_crtc_register_all(struct drm_device *dev)
return 0;
}
-static void drm_crtc_unregister_all(struct drm_device *dev)
+void drm_crtc_unregister_all(struct drm_device *dev)
{
struct drm_crtc *crtc;
drm_for_each_crtc(crtc, dev) {
if (crtc->funcs->early_unregister)
crtc->funcs->early_unregister(crtc);
+ drm_debugfs_crtc_remove(crtc);
}
}
+static int drm_crtc_crc_init(struct drm_crtc *crtc)
+{
+#ifdef CONFIG_DEBUG_FS
+ spin_lock_init(&crtc->crc.lock);
+ init_waitqueue_head(&crtc->crc.wq);
+ crtc->crc.source = kstrdup("auto", GFP_KERNEL);
+ if (!crtc->crc.source)
+ return -ENOMEM;
+#endif
+ return 0;
+}
+
+static void drm_crtc_crc_fini(struct drm_crtc *crtc)
+{
+#ifdef CONFIG_DEBUG_FS
+ kfree(crtc->crc.source);
+#endif
+}
+
+static const struct dma_fence_ops drm_crtc_fence_ops;
+
+static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
+{
+ BUG_ON(fence->ops != &drm_crtc_fence_ops);
+ return container_of(fence->lock, struct drm_crtc, fence_lock);
+}
+
+static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
+{
+ struct drm_crtc *crtc = fence_to_crtc(fence);
+
+ return crtc->dev->driver->name;
+}
+
+static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
+{
+ struct drm_crtc *crtc = fence_to_crtc(fence);
+
+ return crtc->timeline_name;
+}
+
+static bool drm_crtc_fence_enable_signaling(struct dma_fence *fence)
+{
+ return true;
+}
+
+static const struct dma_fence_ops drm_crtc_fence_ops = {
+ .get_driver_name = drm_crtc_fence_get_driver_name,
+ .get_timeline_name = drm_crtc_fence_get_timeline_name,
+ .enable_signaling = drm_crtc_fence_enable_signaling,
+ .wait = dma_fence_default_wait,
+};
+
+struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
+{
+ struct dma_fence *fence;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence)
+ return NULL;
+
+ dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
+ crtc->fence_context, ++crtc->fence_seqno);
+
+ return fence;
+}
+
/**
* drm_crtc_init_with_planes - Initialise a new CRTC object with
* specified primary and cursor planes.
@@ -198,6 +257,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
return -ENOMEM;
}
+ crtc->fence_context = dma_fence_context_alloc(1);
+ spin_lock_init(&crtc->fence_lock);
+ snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
+ "CRTC:%d-%s", crtc->base.id, crtc->name);
+
crtc->base.properties = &crtc->properties;
list_add_tail(&crtc->head, &config->crtc_list);
@@ -205,14 +269,22 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
crtc->primary = primary;
crtc->cursor = cursor;
- if (primary)
+ if (primary && !primary->possible_crtcs)
primary->possible_crtcs = 1 << drm_crtc_index(crtc);
- if (cursor)
+ if (cursor && !cursor->possible_crtcs)
cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
+ ret = drm_crtc_crc_init(crtc);
+ if (ret) {
+ drm_mode_object_unregister(dev, &crtc->base);
+ return ret;
+ }
+
if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
drm_object_attach_property(&crtc->base, config->prop_active, 0);
drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
+ drm_object_attach_property(&crtc->base,
+ config->prop_out_fence_ptr, 0);
}
return 0;
@@ -236,6 +308,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
* the indices on the drm_crtc after us in the crtc_list.
*/
+ drm_crtc_crc_fini(crtc);
+
kfree(crtc->gamma_store);
crtc->gamma_store = NULL;
@@ -255,301 +329,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
}
EXPORT_SYMBOL(drm_crtc_cleanup);
-int drm_modeset_register_all(struct drm_device *dev)
-{
- int ret;
-
- ret = drm_plane_register_all(dev);
- if (ret)
- goto err_plane;
-
- ret = drm_crtc_register_all(dev);
- if (ret)
- goto err_crtc;
-
- ret = drm_encoder_register_all(dev);
- if (ret)
- goto err_encoder;
-
- ret = drm_connector_register_all(dev);
- if (ret)
- goto err_connector;
-
- return 0;
-
-err_connector:
- drm_encoder_unregister_all(dev);
-err_encoder:
- drm_crtc_unregister_all(dev);
-err_crtc:
- drm_plane_unregister_all(dev);
-err_plane:
- return ret;
-}
-
-void drm_modeset_unregister_all(struct drm_device *dev)
-{
- drm_connector_unregister_all(dev);
- drm_encoder_unregister_all(dev);
- drm_crtc_unregister_all(dev);
- drm_plane_unregister_all(dev);
-}
-
-static int drm_mode_create_standard_properties(struct drm_device *dev)
-{
- struct drm_property *prop;
- int ret;
-
- ret = drm_connector_create_standard_properties(dev);
- if (ret)
- return ret;
-
- prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
- "type", drm_plane_type_enum_list,
- ARRAY_SIZE(drm_plane_type_enum_list));
- if (!prop)
- return -ENOMEM;
- dev->mode_config.plane_type_property = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "SRC_X", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_src_x = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "SRC_Y", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_src_y = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "SRC_W", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_src_w = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "SRC_H", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_src_h = prop;
-
- prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
- "CRTC_X", INT_MIN, INT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_crtc_x = prop;
-
- prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
- "CRTC_Y", INT_MIN, INT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_crtc_y = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "CRTC_W", 0, INT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_crtc_w = prop;
-
- prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
- "CRTC_H", 0, INT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_crtc_h = prop;
-
- prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
- "FB_ID", DRM_MODE_OBJECT_FB);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_fb_id = prop;
-
- prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
- "CRTC_ID", DRM_MODE_OBJECT_CRTC);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_crtc_id = prop;
-
- prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
- "ACTIVE");
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_active = prop;
-
- prop = drm_property_create(dev,
- DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
- "MODE_ID", 0);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.prop_mode_id = prop;
-
- prop = drm_property_create(dev,
- DRM_MODE_PROP_BLOB,
- "DEGAMMA_LUT", 0);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.degamma_lut_property = prop;
-
- prop = drm_property_create_range(dev,
- DRM_MODE_PROP_IMMUTABLE,
- "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.degamma_lut_size_property = prop;
-
- prop = drm_property_create(dev,
- DRM_MODE_PROP_BLOB,
- "CTM", 0);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.ctm_property = prop;
-
- prop = drm_property_create(dev,
- DRM_MODE_PROP_BLOB,
- "GAMMA_LUT", 0);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.gamma_lut_property = prop;
-
- prop = drm_property_create_range(dev,
- DRM_MODE_PROP_IMMUTABLE,
- "GAMMA_LUT_SIZE", 0, UINT_MAX);
- if (!prop)
- return -ENOMEM;
- dev->mode_config.gamma_lut_size_property = prop;
-
- return 0;
-}
-
-/**
- * drm_mode_getresources - get graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Construct a set of configuration description structures and return
- * them to the user, including CRTC, connector and framebuffer configuration.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getresources(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_mode_card_res *card_res = data;
- struct list_head *lh;
- struct drm_framebuffer *fb;
- struct drm_connector *connector;
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- int ret = 0;
- int connector_count = 0;
- int crtc_count = 0;
- int fb_count = 0;
- int encoder_count = 0;
- int copied = 0;
- uint32_t __user *fb_id;
- uint32_t __user *crtc_id;
- uint32_t __user *connector_id;
- uint32_t __user *encoder_id;
-
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return -EINVAL;
-
-
- mutex_lock(&file_priv->fbs_lock);
- /*
- * For the non-control nodes we need to limit the list of resources
- * by IDs in the group list for this node
- */
- list_for_each(lh, &file_priv->fbs)
- fb_count++;
-
- /* handle this in 4 parts */
- /* FBs */
- if (card_res->count_fbs >= fb_count) {
- copied = 0;
- fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
- list_for_each_entry(fb, &file_priv->fbs, filp_head) {
- if (put_user(fb->base.id, fb_id + copied)) {
- mutex_unlock(&file_priv->fbs_lock);
- return -EFAULT;
- }
- copied++;
- }
- }
- card_res->count_fbs = fb_count;
- mutex_unlock(&file_priv->fbs_lock);
-
- /* mode_config.mutex protects the connector list against e.g. DP MST
- * connector hot-adding. CRTC/Plane lists are invariant. */
- mutex_lock(&dev->mode_config.mutex);
- drm_for_each_crtc(crtc, dev)
- crtc_count++;
-
- drm_for_each_connector(connector, dev)
- connector_count++;
-
- drm_for_each_encoder(encoder, dev)
- encoder_count++;
-
- card_res->max_height = dev->mode_config.max_height;
- card_res->min_height = dev->mode_config.min_height;
- card_res->max_width = dev->mode_config.max_width;
- card_res->min_width = dev->mode_config.min_width;
-
- /* CRTCs */
- if (card_res->count_crtcs >= crtc_count) {
- copied = 0;
- crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
- drm_for_each_crtc(crtc, dev) {
- if (put_user(crtc->base.id, crtc_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- card_res->count_crtcs = crtc_count;
-
- /* Encoders */
- if (card_res->count_encoders >= encoder_count) {
- copied = 0;
- encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
- drm_for_each_encoder(encoder, dev) {
- if (put_user(encoder->base.id, encoder_id +
- copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- card_res->count_encoders = encoder_count;
-
- /* Connectors */
- if (card_res->count_connectors >= connector_count) {
- copied = 0;
- connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
- drm_for_each_connector(connector, dev) {
- if (put_user(connector->base.id,
- connector_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- card_res->count_connectors = connector_count;
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
/**
* drm_mode_getcrtc - get CRTC configuration
* @dev: drm device for the ioctl
@@ -695,8 +474,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
if (crtc->state &&
- crtc->primary->state->rotation & (DRM_ROTATE_90 |
- DRM_ROTATE_270))
+ drm_rotation_90_or_270(crtc->primary->state->rotation))
swap(hdisplay, vdisplay);
return drm_framebuffer_check_src_coords(x << 16, y << 16,
@@ -796,9 +574,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
ret = drm_plane_check_pixel_format(crtc->primary,
fb->pixel_format);
if (ret) {
- char *format_name = drm_get_format_name(fb->pixel_format);
- DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
- kfree(format_name);
+ struct drm_format_name_buf format_name;
+ DRM_DEBUG_KMS("Invalid pixel format %s\n",
+ drm_get_format_name(fb->pixel_format,
+ &format_name));
goto out;
}
}
@@ -902,362 +681,3 @@ int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
return ret;
}
-
-/**
- * drm_mode_config_reset - call ->reset callbacks
- * @dev: drm device
- *
- * This functions calls all the crtc's, encoder's and connector's ->reset
- * callback. Drivers can use this in e.g. their driver load or resume code to
- * reset hardware and software state.
- */
-void drm_mode_config_reset(struct drm_device *dev)
-{
- struct drm_crtc *crtc;
- struct drm_plane *plane;
- struct drm_encoder *encoder;
- struct drm_connector *connector;
-
- drm_for_each_plane(plane, dev)
- if (plane->funcs->reset)
- plane->funcs->reset(plane);
-
- drm_for_each_crtc(crtc, dev)
- if (crtc->funcs->reset)
- crtc->funcs->reset(crtc);
-
- drm_for_each_encoder(encoder, dev)
- if (encoder->funcs->reset)
- encoder->funcs->reset(encoder);
-
- mutex_lock(&dev->mode_config.mutex);
- drm_for_each_connector(connector, dev)
- if (connector->funcs->reset)
- connector->funcs->reset(connector);
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_mode_config_reset);
-
-/**
- * drm_mode_create_dumb_ioctl - create a dumb backing storage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This creates a new dumb buffer in the driver's backing storage manager (GEM,
- * TTM or something else entirely) and returns the resulting buffer handle. This
- * handle can then be wrapped up into a framebuffer modeset object.
- *
- * Note that userspace is not allowed to use such objects for render
- * acceleration - drivers must create their own private ioctls for such a use
- * case.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_create_dumb_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_create_dumb *args = data;
- u32 cpp, stride, size;
-
- if (!dev->driver->dumb_create)
- return -ENOSYS;
- if (!args->width || !args->height || !args->bpp)
- return -EINVAL;
-
- /* overflow checks for 32bit size calculations */
- /* NOTE: DIV_ROUND_UP() can overflow */
- cpp = DIV_ROUND_UP(args->bpp, 8);
- if (!cpp || cpp > 0xffffffffU / args->width)
- return -EINVAL;
- stride = cpp * args->width;
- if (args->height > 0xffffffffU / stride)
- return -EINVAL;
-
- /* test for wrap-around */
- size = args->height * stride;
- if (PAGE_ALIGN(size) == 0)
- return -EINVAL;
-
- /*
- * handle, pitch and size are output parameters. Zero them out to
- * prevent drivers from accidentally using uninitialized data. Since
- * not all existing userspace is clearing these fields properly we
- * cannot reject IOCTL with garbage in them.
- */
- args->handle = 0;
- args->pitch = 0;
- args->size = 0;
-
- return dev->driver->dumb_create(file_priv, dev, args);
-}
-
-/**
- * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Allocate an offset in the drm device node's address space to be able to
- * memory map a dumb buffer.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_map_dumb *args = data;
-
- /* call driver ioctl to get mmap offset */
- if (!dev->driver->dumb_map_offset)
- return -ENOSYS;
-
- return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
-}
-
-/**
- * drm_mode_destroy_dumb_ioctl - destroy a dumb backing strage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This destroys the userspace handle for the given dumb backing storage buffer.
- * Since buffer objects must be reference counted in the kernel a buffer object
- * won't be immediately freed if a framebuffer modeset object still uses it.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_destroy_dumb *args = data;
-
- if (!dev->driver->dumb_destroy)
- return -ENOSYS;
-
- return dev->driver->dumb_destroy(file_priv, dev, args->handle);
-}
-
-/**
- * drm_mode_config_init - initialize DRM mode_configuration structure
- * @dev: DRM device
- *
- * Initialize @dev's mode_config structure, used for tracking the graphics
- * configuration of @dev.
- *
- * Since this initializes the modeset locks, no locking is possible. Which is no
- * problem, since this should happen single threaded at init time. It is the
- * driver's problem to ensure this guarantee.
- *
- */
-void drm_mode_config_init(struct drm_device *dev)
-{
- mutex_init(&dev->mode_config.mutex);
- drm_modeset_lock_init(&dev->mode_config.connection_mutex);
- mutex_init(&dev->mode_config.idr_mutex);
- mutex_init(&dev->mode_config.fb_lock);
- mutex_init(&dev->mode_config.blob_lock);
- INIT_LIST_HEAD(&dev->mode_config.fb_list);
- INIT_LIST_HEAD(&dev->mode_config.crtc_list);
- INIT_LIST_HEAD(&dev->mode_config.connector_list);
- INIT_LIST_HEAD(&dev->mode_config.encoder_list);
- INIT_LIST_HEAD(&dev->mode_config.property_list);
- INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
- INIT_LIST_HEAD(&dev->mode_config.plane_list);
- idr_init(&dev->mode_config.crtc_idr);
- idr_init(&dev->mode_config.tile_idr);
- ida_init(&dev->mode_config.connector_ida);
-
- drm_modeset_lock_all(dev);
- drm_mode_create_standard_properties(dev);
- drm_modeset_unlock_all(dev);
-
- /* Just to be sure */
- dev->mode_config.num_fb = 0;
- dev->mode_config.num_connector = 0;
- dev->mode_config.num_crtc = 0;
- dev->mode_config.num_encoder = 0;
- dev->mode_config.num_overlay_plane = 0;
- dev->mode_config.num_total_plane = 0;
-}
-EXPORT_SYMBOL(drm_mode_config_init);
-
-/**
- * drm_mode_config_cleanup - free up DRM mode_config info
- * @dev: DRM device
- *
- * Free up all the connectors and CRTCs associated with this DRM device, then
- * free up the framebuffers and associated buffer objects.
- *
- * Note that since this /should/ happen single-threaded at driver/device
- * teardown time, no locking is required. It's the driver's job to ensure that
- * this guarantee actually holds true.
- *
- * FIXME: cleanup any dangling user buffer objects too
- */
-void drm_mode_config_cleanup(struct drm_device *dev)
-{
- struct drm_connector *connector, *ot;
- struct drm_crtc *crtc, *ct;
- struct drm_encoder *encoder, *enct;
- struct drm_framebuffer *fb, *fbt;
- struct drm_property *property, *pt;
- struct drm_property_blob *blob, *bt;
- struct drm_plane *plane, *plt;
-
- list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
- head) {
- encoder->funcs->destroy(encoder);
- }
-
- list_for_each_entry_safe(connector, ot,
- &dev->mode_config.connector_list, head) {
- connector->funcs->destroy(connector);
- }
-
- list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
- head) {
- drm_property_destroy(dev, property);
- }
-
- list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
- head) {
- plane->funcs->destroy(plane);
- }
-
- list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
- crtc->funcs->destroy(crtc);
- }
-
- list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
- head_global) {
- drm_property_unreference_blob(blob);
- }
-
- /*
- * Single-threaded teardown context, so it's not required to grab the
- * fb_lock to protect against concurrent fb_list access. Contrary, it
- * would actually deadlock with the drm_framebuffer_cleanup function.
- *
- * Also, if there are any framebuffers left, that's a driver leak now,
- * so politely WARN about this.
- */
- WARN_ON(!list_empty(&dev->mode_config.fb_list));
- list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- drm_framebuffer_free(&fb->base.refcount);
- }
-
- ida_destroy(&dev->mode_config.connector_ida);
- idr_destroy(&dev->mode_config.tile_idr);
- idr_destroy(&dev->mode_config.crtc_idr);
- drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
-}
-EXPORT_SYMBOL(drm_mode_config_cleanup);
-
-/**
- * DOC: Tile group
- *
- * Tile groups are used to represent tiled monitors with a unique
- * integer identifier. Tiled monitors using DisplayID v1.3 have
- * a unique 8-byte handle, we store this in a tile group, so we
- * have a common identifier for all tiles in a monitor group.
- */
-static void drm_tile_group_free(struct kref *kref)
-{
- struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
- struct drm_device *dev = tg->dev;
- mutex_lock(&dev->mode_config.idr_mutex);
- idr_remove(&dev->mode_config.tile_idr, tg->id);
- mutex_unlock(&dev->mode_config.idr_mutex);
- kfree(tg);
-}
-
-/**
- * drm_mode_put_tile_group - drop a reference to a tile group.
- * @dev: DRM device
- * @tg: tile group to drop reference to.
- *
- * drop reference to tile group and free if 0.
- */
-void drm_mode_put_tile_group(struct drm_device *dev,
- struct drm_tile_group *tg)
-{
- kref_put(&tg->refcount, drm_tile_group_free);
-}
-
-/**
- * drm_mode_get_tile_group - get a reference to an existing tile group
- * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
- *
- * Use the unique bytes to get a reference to an existing tile group.
- *
- * RETURNS:
- * tile group or NULL if not found.
- */
-struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
- char topology[8])
-{
- struct drm_tile_group *tg;
- int id;
- mutex_lock(&dev->mode_config.idr_mutex);
- idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
- if (!memcmp(tg->group_data, topology, 8)) {
- if (!kref_get_unless_zero(&tg->refcount))
- tg = NULL;
- mutex_unlock(&dev->mode_config.idr_mutex);
- return tg;
- }
- }
- mutex_unlock(&dev->mode_config.idr_mutex);
- return NULL;
-}
-EXPORT_SYMBOL(drm_mode_get_tile_group);
-
-/**
- * drm_mode_create_tile_group - create a tile group from a displayid description
- * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
- *
- * Create a tile group for the unique monitor, and get a unique
- * identifier for the tile group.
- *
- * RETURNS:
- * new tile group or error.
- */
-struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
- char topology[8])
-{
- struct drm_tile_group *tg;
- int ret;
-
- tg = kzalloc(sizeof(*tg), GFP_KERNEL);
- if (!tg)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&tg->refcount);
- memcpy(tg->group_data, topology, 8);
- tg->dev = dev;
-
- mutex_lock(&dev->mode_config.idr_mutex);
- ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
- if (ret >= 0) {
- tg->id = ret;
- } else {
- kfree(tg);
- tg = ERR_PTR(ret);
- }
-
- mutex_unlock(&dev->mode_config.idr_mutex);
- return tg;
-}
-EXPORT_SYMBOL(drm_mode_create_tile_group);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index c48ba02c5365..cdf6860c9d22 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -40,10 +40,29 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
int x, int y,
const struct drm_display_mode *mode,
const struct drm_framebuffer *fb);
+int drm_crtc_register_all(struct drm_device *dev);
+void drm_crtc_unregister_all(struct drm_device *dev);
-void drm_fb_release(struct drm_file *file_priv);
+struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc);
+
+/* IOCTLs */
+int drm_mode_getcrtc(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+int drm_mode_setcrtc(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+
+/* drm_mode_config.c */
+int drm_modeset_register_all(struct drm_device *dev);
+void drm_modeset_unregister_all(struct drm_device *dev);
+
+/* IOCTLs */
+int drm_mode_getresources(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
-/* dumb buffer support IOCTLs */
+
+/* drm_dumb_buffers.c */
+/* IOCTLs */
int drm_mode_create_dumb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
@@ -51,14 +70,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
-/* IOCTLs */
-int drm_mode_getresources(struct drm_device *dev,
- void *data, struct drm_file *file_priv);
-int drm_mode_getcrtc(struct drm_device *dev,
- void *data, struct drm_file *file_priv);
-int drm_mode_setcrtc(struct drm_device *dev,
- void *data, struct drm_file *file_priv);
-
/* drm_color_mgmt.c */
/* IOCTLs */
@@ -147,6 +158,8 @@ void drm_framebuffer_free(struct kref *kref);
int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
const struct drm_framebuffer *fb);
+void drm_fb_release(struct drm_file *file_priv);
+
/* IOCTL */
int drm_mode_addfb(struct drm_device *dev,
@@ -166,9 +179,6 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
-int drm_modeset_register_all(struct drm_device *dev);
-void drm_modeset_unregister_all(struct drm_device *dev);
-
/* drm_plane.c */
int drm_plane_register_all(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 1205790ed960..2e3e46a53805 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -36,6 +36,7 @@
#include <linux/export.h>
#include <drm/drmP.h>
#include <drm/drm_edid.h>
+#include <drm/drm_atomic.h>
#include "drm_internal.h"
#if defined(CONFIG_DEBUG_FS)
@@ -163,6 +164,14 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
return ret;
}
+ if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+ ret = drm_atomic_debugfs_init(minor);
+ if (ret) {
+ DRM_ERROR("Failed to create atomic debugfs files\n");
+ return ret;
+ }
+ }
+
if (dev->driver->debugfs_init) {
ret = dev->driver->debugfs_init(minor);
if (ret) {
@@ -219,6 +228,7 @@ EXPORT_SYMBOL(drm_debugfs_remove_files);
int drm_debugfs_cleanup(struct drm_minor *minor)
{
struct drm_device *dev = minor->dev;
+ int ret;
if (!minor->debugfs_root)
return 0;
@@ -226,6 +236,14 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
if (dev->driver->debugfs_cleanup)
dev->driver->debugfs_cleanup(minor);
+ if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+ ret = drm_atomic_debugfs_cleanup(minor);
+ if (ret) {
+ DRM_ERROR("DRM: Failed to remove atomic debugfs entries\n");
+ return ret;
+ }
+ }
+
drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);
debugfs_remove(minor->debugfs_root);
@@ -415,5 +433,37 @@ void drm_debugfs_connector_remove(struct drm_connector *connector)
connector->debugfs_entry = NULL;
}
-#endif /* CONFIG_DEBUG_FS */
+int drm_debugfs_crtc_add(struct drm_crtc *crtc)
+{
+ struct drm_minor *minor = crtc->dev->primary;
+ struct dentry *root;
+ char *name;
+
+ name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index);
+ if (!name)
+ return -ENOMEM;
+ root = debugfs_create_dir(name, minor->debugfs_root);
+ kfree(name);
+ if (!root)
+ return -ENOMEM;
+
+ crtc->debugfs_entry = root;
+
+ if (drm_debugfs_crtc_crc_add(crtc))
+ goto error;
+
+ return 0;
+
+error:
+ drm_debugfs_crtc_remove(crtc);
+ return -ENOMEM;
+}
+
+void drm_debugfs_crtc_remove(struct drm_crtc *crtc)
+{
+ debugfs_remove_recursive(crtc->debugfs_entry);
+ crtc->debugfs_entry = NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
new file mode 100644
index 000000000000..00e771fb7df2
--- /dev/null
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ * Copyright © 2016 Collabora Ltd
+ *
+ * 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.
+ *
+ * Based on code from the i915 driver.
+ * Original author: Damien Lespiau <damien.lespiau@intel.com>
+ *
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <drm/drmP.h>
+#include "drm_internal.h"
+
+/**
+ * DOC: CRC ABI
+ *
+ * DRM device drivers can provide to userspace CRC information of each frame as
+ * it reached a given hardware component (a "source").
+ *
+ * Userspace can control generation of CRCs in a given CRTC by writing to the
+ * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
+ * Accepted values are source names (which are driver-specific) and the "auto"
+ * keyword, which will let the driver select a default source of frame CRCs
+ * for this CRTC.
+ *
+ * Once frame CRC generation is enabled, userspace can capture them by reading
+ * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
+ * number in the first field and then a number of unsigned integer fields
+ * containing the CRC data. Fields are separated by a single space and the number
+ * of CRC fields is source-specific.
+ *
+ * Note that though in some cases the CRC is computed in a specified way and on
+ * the frame contents as supplied by userspace (eDP 1.3), in general the CRC
+ * computation is performed in an unspecified way and on frame contents that have
+ * been already processed in also an unspecified way and thus userspace cannot
+ * rely on being able to generate matching CRC values for the frame contents that
+ * it submits. In this general case, the maximum userspace can do is to compare
+ * the reported CRCs of frames that should have the same contents.
+ */
+
+static int crc_control_show(struct seq_file *m, void *data)
+{
+ struct drm_crtc *crtc = m->private;
+
+ seq_printf(m, "%s\n", crtc->crc.source);
+
+ return 0;
+}
+
+static int crc_control_open(struct inode *inode, struct file *file)
+{
+ struct drm_crtc *crtc = inode->i_private;
+
+ return single_open(file, crc_control_show, crtc);
+}
+
+static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_crtc *crtc = m->private;
+ struct drm_crtc_crc *crc = &crtc->crc;
+ char *source;
+
+ if (len == 0)
+ return 0;
+
+ if (len > PAGE_SIZE - 1) {
+ DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n",
+ PAGE_SIZE);
+ return -E2BIG;
+ }
+
+ source = memdup_user_nul(ubuf, len);
+ if (IS_ERR(source))
+ return PTR_ERR(source);
+
+ if (source[len] == '\n')
+ source[len] = '\0';
+
+ spin_lock_irq(&crc->lock);
+
+ if (crc->opened) {
+ spin_unlock_irq(&crc->lock);
+ kfree(source);
+ return -EBUSY;
+ }
+
+ kfree(crc->source);
+ crc->source = source;
+
+ spin_unlock_irq(&crc->lock);
+
+ *offp += len;
+ return len;
+}
+
+static const struct file_operations drm_crtc_crc_control_fops = {
+ .owner = THIS_MODULE,
+ .open = crc_control_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = crc_control_write
+};
+
+static int crtc_crc_open(struct inode *inode, struct file *filep)
+{
+ struct drm_crtc *crtc = inode->i_private;
+ struct drm_crtc_crc *crc = &crtc->crc;
+ struct drm_crtc_crc_entry *entries = NULL;
+ size_t values_cnt;
+ int ret;
+
+ if (crc->opened)
+ return -EBUSY;
+
+ ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
+ if (ret)
+ return ret;
+
+ if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
+ ret = -EINVAL;
+ goto err_disable;
+ }
+
+ if (WARN_ON(values_cnt == 0)) {
+ ret = -EINVAL;
+ goto err_disable;
+ }
+
+ entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL);
+ if (!entries) {
+ ret = -ENOMEM;
+ goto err_disable;
+ }
+
+ spin_lock_irq(&crc->lock);
+ crc->entries = entries;
+ crc->values_cnt = values_cnt;
+ crc->opened = true;
+ spin_unlock_irq(&crc->lock);
+
+ return 0;
+
+err_disable:
+ crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+ return ret;
+}
+
+static int crtc_crc_release(struct inode *inode, struct file *filep)
+{
+ struct drm_crtc *crtc = filep->f_inode->i_private;
+ struct drm_crtc_crc *crc = &crtc->crc;
+ size_t values_cnt;
+
+ spin_lock_irq(&crc->lock);
+ kfree(crc->entries);
+ crc->entries = NULL;
+ crc->head = 0;
+ crc->tail = 0;
+ crc->values_cnt = 0;
+ crc->opened = false;
+ spin_unlock_irq(&crc->lock);
+
+ crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+
+ return 0;
+}
+
+static int crtc_crc_data_count(struct drm_crtc_crc *crc)
+{
+ assert_spin_locked(&crc->lock);
+ return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
+}
+
+/*
+ * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space
+ * separated, with a newline at the end and null-terminated.
+ */
+#define LINE_LEN(values_cnt) (10 + 11 * values_cnt + 1 + 1)
+#define MAX_LINE_LEN (LINE_LEN(DRM_MAX_CRC_NR))
+
+static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
+ size_t count, loff_t *pos)
+{
+ struct drm_crtc *crtc = filep->f_inode->i_private;
+ struct drm_crtc_crc *crc = &crtc->crc;
+ struct drm_crtc_crc_entry *entry;
+ char buf[MAX_LINE_LEN];
+ int ret, i;
+
+ spin_lock_irq(&crc->lock);
+
+ if (!crc->source) {
+ spin_unlock_irq(&crc->lock);
+ return 0;
+ }
+
+ /* Nothing to read? */
+ while (crtc_crc_data_count(crc) == 0) {
+ if (filep->f_flags & O_NONBLOCK) {
+ spin_unlock_irq(&crc->lock);
+ return -EAGAIN;
+ }
+
+ ret = wait_event_interruptible_lock_irq(crc->wq,
+ crtc_crc_data_count(crc),
+ crc->lock);
+ if (ret) {
+ spin_unlock_irq(&crc->lock);
+ return ret;
+ }
+ }
+
+ /* We know we have an entry to be read */
+ entry = &crc->entries[crc->tail];
+
+ if (count < LINE_LEN(crc->values_cnt)) {
+ spin_unlock_irq(&crc->lock);
+ return -EINVAL;
+ }
+
+ BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR);
+ crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1);
+
+ spin_unlock_irq(&crc->lock);
+
+ if (entry->has_frame_counter)
+ sprintf(buf, "0x%08x", entry->frame);
+ else
+ sprintf(buf, "XXXXXXXXXX");
+
+ for (i = 0; i < crc->values_cnt; i++)
+ sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]);
+ sprintf(buf + 10 + crc->values_cnt * 11, "\n");
+
+ if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt)))
+ return -EFAULT;
+
+ return LINE_LEN(crc->values_cnt);
+}
+
+static const struct file_operations drm_crtc_crc_data_fops = {
+ .owner = THIS_MODULE,
+ .open = crtc_crc_open,
+ .read = crtc_crc_read,
+ .release = crtc_crc_release,
+};
+
+/**
+ * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
+ * @crtc: CRTC to whom the frames will belong
+ *
+ * Adds files to debugfs directory that allows userspace to control the
+ * generation of frame CRCs and to read them.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
+{
+ struct dentry *crc_ent, *ent;
+
+ if (!crtc->funcs->set_crc_source)
+ return 0;
+
+ crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry);
+ if (!crc_ent)
+ return -ENOMEM;
+
+ ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc,
+ &drm_crtc_crc_control_fops);
+ if (!ent)
+ goto error;
+
+ ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc,
+ &drm_crtc_crc_data_fops);
+ if (!ent)
+ goto error;
+
+ return 0;
+
+error:
+ debugfs_remove_recursive(crc_ent);
+
+ return -ENOMEM;
+}
+
+/**
+ * drm_crtc_add_crc_entry - Add entry with CRC information for a frame
+ * @crtc: CRTC to which the frame belongs
+ * @has_frame: whether this entry has a frame number to go with
+ * @frame: number of the frame these CRCs are about
+ * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt
+ *
+ * For each frame, the driver polls the source of CRCs for new data and calls
+ * this function to add them to the buffer from where userspace reads.
+ */
+int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
+ uint32_t frame, uint32_t *crcs)
+{
+ struct drm_crtc_crc *crc = &crtc->crc;
+ struct drm_crtc_crc_entry *entry;
+ int head, tail;
+
+ assert_spin_locked(&crc->lock);
+
+ /* Caller may not have noticed yet that userspace has stopped reading */
+ if (!crc->opened)
+ return -EINVAL;
+
+ head = crc->head;
+ tail = crc->tail;
+
+ if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) {
+ DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
+ return -ENOBUFS;
+ }
+
+ entry = &crc->entries[head];
+ entry->frame = frame;
+ entry->has_frame_counter = has_frame;
+ memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt);
+
+ head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1);
+ crc->head = head;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry);
diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
index a7b2a751f6fe..e02563966271 100644
--- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
+++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
@@ -142,12 +142,25 @@ static bool is_hdmi_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN])
sizeof(dp_dual_mode_hdmi_id)) == 0;
}
+static bool is_type1_adaptor(uint8_t adaptor_id)
+{
+ return adaptor_id == 0 || adaptor_id == 0xff;
+}
+
static bool is_type2_adaptor(uint8_t adaptor_id)
{
return adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 |
DP_DUAL_MODE_REV_TYPE2);
}
+static bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN],
+ const uint8_t adaptor_id)
+{
+ return is_hdmi_adaptor(hdmi_id) &&
+ (adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 |
+ DP_DUAL_MODE_TYPE_HAS_DPCD));
+}
+
/**
* drm_dp_dual_mode_detect - Identify the DP dual mode adaptor
* @adapter: I2C adapter for the DDC bus
@@ -185,6 +198,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter)
*/
ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_HDMI_ID,
hdmi_id, sizeof(hdmi_id));
+ DRM_DEBUG_KMS("DP dual mode HDMI ID: %*pE (err %zd)\n",
+ ret ? 0 : (int)sizeof(hdmi_id), hdmi_id, ret);
if (ret)
return DRM_DP_DUAL_MODE_UNKNOWN;
@@ -202,13 +217,26 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter)
*/
ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,
&adaptor_id, sizeof(adaptor_id));
+ DRM_DEBUG_KMS("DP dual mode adaptor ID: %02x (err %zd)\n",
+ adaptor_id, ret);
if (ret == 0) {
+ if (is_lspcon_adaptor(hdmi_id, adaptor_id))
+ return DRM_DP_DUAL_MODE_LSPCON;
if (is_type2_adaptor(adaptor_id)) {
if (is_hdmi_adaptor(hdmi_id))
return DRM_DP_DUAL_MODE_TYPE2_HDMI;
else
return DRM_DP_DUAL_MODE_TYPE2_DVI;
}
+ /*
+ * If neither a proper type 1 ID nor a broken type 1 adaptor
+ * as described above, assume type 1, but let the user know
+ * that we may have misdetected the type.
+ */
+ if (!is_type1_adaptor(adaptor_id) && adaptor_id != hdmi_id[0])
+ DRM_ERROR("Unexpected DP dual mode adaptor ID %02x\n",
+ adaptor_id);
+
}
if (is_hdmi_adaptor(hdmi_id))
@@ -364,3 +392,96 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
}
}
EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
+
+/**
+ * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
+ * reading offset (0x80, 0x41)
+ * @adapter: I2C-over-aux adapter
+ * @mode: current lspcon mode of operation output variable
+ *
+ * Returns:
+ * 0 on success, sets the current_mode value to appropriate mode
+ * -error on failure
+ */
+int drm_lspcon_get_mode(struct i2c_adapter *adapter,
+ enum drm_lspcon_mode *mode)
+{
+ u8 data;
+ int ret = 0;
+
+ if (!mode) {
+ DRM_ERROR("NULL input\n");
+ return -EINVAL;
+ }
+
+ /* Read Status: i2c over aux */
+ ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE,
+ &data, sizeof(data));
+ if (ret < 0) {
+ DRM_ERROR("LSPCON read(0x80, 0x41) failed\n");
+ return -EFAULT;
+ }
+
+ if (data & DP_DUAL_MODE_LSPCON_MODE_PCON)
+ *mode = DRM_LSPCON_MODE_PCON;
+ else
+ *mode = DRM_LSPCON_MODE_LS;
+ return 0;
+}
+EXPORT_SYMBOL(drm_lspcon_get_mode);
+
+/**
+ * drm_lspcon_set_mode: Change LSPCON's mode of operation by
+ * writing offset (0x80, 0x40)
+ * @adapter: I2C-over-aux adapter
+ * @mode: required mode of operation
+ *
+ * Returns:
+ * 0 on success, -error on failure/timeout
+ */
+int drm_lspcon_set_mode(struct i2c_adapter *adapter,
+ enum drm_lspcon_mode mode)
+{
+ u8 data = 0;
+ int ret;
+ int time_out = 200;
+ enum drm_lspcon_mode current_mode;
+
+ if (mode == DRM_LSPCON_MODE_PCON)
+ data = DP_DUAL_MODE_LSPCON_MODE_PCON;
+
+ /* Change mode */
+ ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_LSPCON_MODE_CHANGE,
+ &data, sizeof(data));
+ if (ret < 0) {
+ DRM_ERROR("LSPCON mode change failed\n");
+ return ret;
+ }
+
+ /*
+ * Confirm mode change by reading the status bit.
+ * Sometimes, it takes a while to change the mode,
+ * so wait and retry until time out or done.
+ */
+ do {
+ ret = drm_lspcon_get_mode(adapter, &current_mode);
+ if (ret) {
+ DRM_ERROR("can't confirm LSPCON mode change\n");
+ return ret;
+ } else {
+ if (current_mode != mode) {
+ msleep(10);
+ time_out -= 10;
+ } else {
+ DRM_DEBUG_KMS("LSPCON mode changed to %s\n",
+ mode == DRM_LSPCON_MODE_LS ?
+ "LS" : "PCON");
+ return 0;
+ }
+ }
+ } while (time_out);
+
+ DRM_ERROR("LSPCON mode change timed out\n");
+ return -ETIMEDOUT;
+}
+EXPORT_SYMBOL(drm_lspcon_set_mode);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 6efdba4993fc..a525751b4559 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -32,7 +32,10 @@
#include <linux/moduleparam.h>
#include <linux/mount.h>
#include <linux/slab.h>
+
+#include <drm/drm_drv.h>
#include <drm/drmP.h>
+
#include "drm_crtc_internal.h"
#include "drm_legacy.h"
#include "drm_internal.h"
@@ -257,10 +260,7 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
drm_debugfs_cleanup(minor);
}
-/**
- * drm_minor_acquire - Acquire a DRM minor
- * @minor_id: Minor ID of the DRM-minor
- *
+/*
* Looks up the given minor-ID and returns the respective DRM-minor object. The
* refence-count of the underlying device is increased so you must release this
* object with drm_minor_release().
@@ -268,10 +268,6 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
* As long as you hold this minor, it is guaranteed that the object and the
* minor->dev pointer will stay valid! However, the device may get unplugged and
* unregistered while you hold the minor.
- *
- * Returns:
- * Pointer to minor-object with increased device-refcount, or PTR_ERR on
- * failure.
*/
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
{
@@ -294,12 +290,6 @@ struct drm_minor *drm_minor_acquire(unsigned int minor_id)
return minor;
}
-/**
- * drm_minor_release - Release DRM minor
- * @minor: Pointer to DRM minor object
- *
- * Release a minor that was previously acquired via drm_minor_acquire().
- */
void drm_minor_release(struct drm_minor *minor)
{
drm_dev_unref(minor->dev);
@@ -313,9 +303,10 @@ void drm_minor_release(struct drm_minor *minor)
* 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. Finally when everything is up
- * and running and ready for userspace the device instance can be published
- * using drm_dev_register().
+ * 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
@@ -337,17 +328,6 @@ void drm_minor_release(struct drm_minor *minor)
* dev_priv field of &drm_device.
*/
-static int drm_dev_set_unique(struct drm_device *dev, const char *name)
-{
- if (!name)
- return -EINVAL;
-
- kfree(dev->unique);
- dev->unique = kstrdup(name, GFP_KERNEL);
-
- return dev->unique ? 0 : -ENOMEM;
-}
-
/**
* drm_put_dev - Unregister and release a DRM device
* @dev: DRM device
@@ -517,12 +497,6 @@ int drm_dev_init(struct drm_device *dev,
goto err_free;
}
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
- if (ret)
- goto err_minors;
- }
-
if (drm_core_check_feature(dev, DRIVER_RENDER)) {
ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
if (ret)
@@ -568,6 +542,9 @@ err_minors:
drm_fs_inode_free(dev->anon_inode);
err_free:
mutex_destroy(&dev->master_mutex);
+ mutex_destroy(&dev->ctxlist_mutex);
+ mutex_destroy(&dev->filelist_mutex);
+ mutex_destroy(&dev->struct_mutex);
return ret;
}
EXPORT_SYMBOL(drm_dev_init);
@@ -630,6 +607,9 @@ static void drm_dev_release(struct kref *ref)
drm_minor_free(dev, DRM_MINOR_CONTROL);
mutex_destroy(&dev->master_mutex);
+ mutex_destroy(&dev->ctxlist_mutex);
+ mutex_destroy(&dev->filelist_mutex);
+ mutex_destroy(&dev->struct_mutex);
kfree(dev->unique);
kfree(dev);
}
@@ -667,6 +647,62 @@ void drm_dev_unref(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_dev_unref);
+static int create_compat_control_link(struct drm_device *dev)
+{
+ struct drm_minor *minor;
+ char *name;
+ int ret;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
+ if (!minor)
+ return 0;
+
+ /*
+ * Some existing userspace out there uses the existing of the controlD*
+ * sysfs files to figure out whether it's a modeset driver. It only does
+ * readdir, hence a symlink is sufficient (and the least confusing
+ * option). Otherwise controlD* is entirely unused.
+ *
+ * Old controlD chardev have been allocated in the range
+ * 64-127.
+ */
+ name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64);
+ if (!name)
+ return -ENOMEM;
+
+ ret = sysfs_create_link(minor->kdev->kobj.parent,
+ &minor->kdev->kobj,
+ name);
+
+ kfree(name);
+
+ return ret;
+}
+
+static void remove_compat_control_link(struct drm_device *dev)
+{
+ struct drm_minor *minor;
+ char *name;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
+ if (!minor)
+ return;
+
+ name = kasprintf(GFP_KERNEL, "controlD%d", minor->index);
+ if (!name)
+ return;
+
+ sysfs_remove_link(minor->kdev->kobj.parent, name);
+
+ kfree(name);
+}
+
/**
* drm_dev_register - Register DRM device
* @dev: Device to register
@@ -705,6 +741,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
if (ret)
goto err_minors;
+ ret = create_compat_control_link(dev);
+ if (ret)
+ goto err_minors;
+
if (dev->driver->load) {
ret = dev->driver->load(dev, flags);
if (ret)
@@ -718,6 +758,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
goto out_unlock;
err_minors:
+ remove_compat_control_link(dev);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
@@ -758,12 +799,33 @@ void drm_dev_unregister(struct drm_device *dev)
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_legacy_rmmap(dev, r_list->map);
+ remove_compat_control_link(dev);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
}
EXPORT_SYMBOL(drm_dev_unregister);
+/**
+ * drm_dev_set_unique - Set the unique name of a DRM device
+ * @dev: device of which to set the unique name
+ * @name: unique name
+ *
+ * Sets the unique name of a DRM device using the specified string. Drivers
+ * can use this at driver probe time if the unique name of the devices they
+ * drive is static.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int drm_dev_set_unique(struct drm_device *dev, const char *name)
+{
+ kfree(dev->unique);
+ dev->unique = kstrdup(name, GFP_KERNEL);
+
+ return dev->unique ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(drm_dev_set_unique);
+
/*
* DRM Core
* The DRM core module initializes all global DRM objects and makes them
diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c
new file mode 100644
index 000000000000..8ac5a1c1d811
--- /dev/null
+++ b/drivers/gpu/drm/drm_dumb_buffers.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2006-2008 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2008 Red Hat Inc.
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, 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 <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * The KMS API doesn't standardize backing storage object creation and leaves it
+ * to driver-specific ioctls. Furthermore actually creating a buffer object even
+ * for GEM-based drivers is done through a driver-specific ioctl - GEM only has
+ * a common userspace interface for sharing and destroying objects. While not an
+ * issue for full-fledged graphics stacks that include device-specific userspace
+ * components (in libdrm for instance), this limit makes DRM-based early boot
+ * graphics unnecessarily complex.
+ *
+ * Dumb objects partly alleviate the problem by providing a standard API to
+ * create dumb buffers suitable for scanout, which can then be used to create
+ * KMS frame buffers.
+ *
+ * To support dumb objects drivers must implement the dumb_create,
+ * dumb_destroy and dumb_map_offset operations from struct &drm_driver. See
+ * there for further details.
+ *
+ * Note that dumb objects may not be used for gpu acceleration, as has been
+ * attempted on some ARM embedded platforms. Such drivers really must have
+ * a hardware-specific ioctl to allocate suitable buffer objects.
+ */
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_mode_create_dumb *args = data;
+ u32 cpp, stride, size;
+
+ if (!dev->driver->dumb_create)
+ return -ENOSYS;
+ if (!args->width || !args->height || !args->bpp)
+ return -EINVAL;
+
+ /* overflow checks for 32bit size calculations */
+ /* NOTE: DIV_ROUND_UP() can overflow */
+ cpp = DIV_ROUND_UP(args->bpp, 8);
+ if (!cpp || cpp > 0xffffffffU / args->width)
+ return -EINVAL;
+ stride = cpp * args->width;
+ if (args->height > 0xffffffffU / stride)
+ return -EINVAL;
+
+ /* test for wrap-around */
+ size = args->height * stride;
+ if (PAGE_ALIGN(size) == 0)
+ return -EINVAL;
+
+ /*
+ * handle, pitch and size are output parameters. Zero them out to
+ * prevent drivers from accidentally using uninitialized data. Since
+ * not all existing userspace is clearing these fields properly we
+ * cannot reject IOCTL with garbage in them.
+ */
+ args->handle = 0;
+ args->pitch = 0;
+ args->size = 0;
+
+ return dev->driver->dumb_create(file_priv, dev, args);
+}
+
+/**
+ * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Allocate an offset in the drm device node's address space to be able to
+ * memory map a dumb buffer.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_mode_map_dumb *args = data;
+
+ /* call driver ioctl to get mmap offset */
+ if (!dev->driver->dumb_map_offset)
+ return -ENOSYS;
+
+ return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
+}
+
+int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_mode_destroy_dumb *args = data;
+
+ if (!dev->driver->dumb_destroy)
+ return -ENOSYS;
+
+ return dev->driver->dumb_destroy(file_priv, dev, args->handle);
+}
+
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ec77bd3e1f08..336be31ff3de 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -957,13 +957,13 @@ static const struct drm_display_mode edid_cea_modes[] = {
798, 858, 0, 480, 489, 495, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
.vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
- /* 58 - 720(1440)x480i@240 */
+ /* 58 - 720(1440)x480i@240Hz */
{ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
801, 858, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
.vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
- /* 59 - 720(1440)x480i@240 */
+ /* 59 - 720(1440)x480i@240Hz */
{ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
801, 858, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
@@ -1260,6 +1260,34 @@ drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
return ret == xfers ? 0 : -1;
}
+static void connector_bad_edid(struct drm_connector *connector,
+ u8 *edid, int num_blocks)
+{
+ int i;
+
+ if (connector->bad_edid_counter++ && !(drm_debug & DRM_UT_KMS))
+ return;
+
+ dev_warn(connector->dev->dev,
+ "%s: EDID is invalid:\n",
+ connector->name);
+ for (i = 0; i < num_blocks; i++) {
+ u8 *block = edid + i * EDID_LENGTH;
+ char prefix[20];
+
+ if (drm_edid_is_zero(block, EDID_LENGTH))
+ sprintf(prefix, "\t[%02x] ZERO ", i);
+ else if (!drm_edid_block_valid(block, i, false, NULL))
+ sprintf(prefix, "\t[%02x] BAD ", i);
+ else
+ sprintf(prefix, "\t[%02x] GOOD ", i);
+
+ print_hex_dump(KERN_WARNING,
+ prefix, DUMP_PREFIX_NONE, 16, 1,
+ block, EDID_LENGTH, false);
+ }
+}
+
/**
* drm_do_get_edid - get EDID data using a custom EDID block read function
* @connector: connector we're probing
@@ -1282,20 +1310,19 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
void *data)
{
int i, j = 0, valid_extensions = 0;
- u8 *block, *new;
- bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
+ u8 *edid, *new;
- if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+ if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
return NULL;
/* base block fetch */
for (i = 0; i < 4; i++) {
- if (get_edid_block(data, block, 0, EDID_LENGTH))
+ if (get_edid_block(data, edid, 0, EDID_LENGTH))
goto out;
- if (drm_edid_block_valid(block, 0, print_bad_edid,
+ if (drm_edid_block_valid(edid, 0, false,
&connector->edid_corrupt))
break;
- if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
+ if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) {
connector->null_edid_counter++;
goto carp;
}
@@ -1304,58 +1331,62 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
goto carp;
/* if there's no extensions, we're done */
- if (block[0x7e] == 0)
- return (struct edid *)block;
+ valid_extensions = edid[0x7e];
+ if (valid_extensions == 0)
+ return (struct edid *)edid;
- new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+ new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
if (!new)
goto out;
- block = new;
+ edid = new;
+
+ for (j = 1; j <= edid[0x7e]; j++) {
+ u8 *block = edid + j * EDID_LENGTH;
- for (j = 1; j <= block[0x7e]; j++) {
for (i = 0; i < 4; i++) {
- if (get_edid_block(data,
- block + (valid_extensions + 1) * EDID_LENGTH,
- j, EDID_LENGTH))
+ if (get_edid_block(data, block, j, EDID_LENGTH))
goto out;
- if (drm_edid_block_valid(block + (valid_extensions + 1)
- * EDID_LENGTH, j,
- print_bad_edid,
- NULL)) {
- valid_extensions++;
+ if (drm_edid_block_valid(block, j, false, NULL))
break;
- }
}
- if (i == 4 && print_bad_edid) {
- dev_warn(connector->dev->dev,
- "%s: Ignoring invalid EDID block %d.\n",
- connector->name, j);
-
- connector->bad_edid_counter++;
- }
+ if (i == 4)
+ valid_extensions--;
}
- if (valid_extensions != block[0x7e]) {
- block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
- block[0x7e] = valid_extensions;
- new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+ if (valid_extensions != edid[0x7e]) {
+ u8 *base;
+
+ connector_bad_edid(connector, edid, edid[0x7e] + 1);
+
+ edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
+ edid[0x7e] = valid_extensions;
+
+ new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
if (!new)
goto out;
- block = new;
- }
- return (struct edid *)block;
+ base = new;
+ for (i = 0; i <= edid[0x7e]; i++) {
+ u8 *block = edid + i * EDID_LENGTH;
-carp:
- if (print_bad_edid) {
- dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
- connector->name, j);
+ if (!drm_edid_block_valid(block, i, false, NULL))
+ continue;
+
+ memcpy(base, block, EDID_LENGTH);
+ base += EDID_LENGTH;
+ }
+
+ kfree(edid);
+ edid = new;
}
- connector->bad_edid_counter++;
+ return (struct edid *)edid;
+
+carp:
+ connector_bad_edid(connector, edid, 1);
out:
- kfree(block);
+ kfree(edid);
return NULL;
}
EXPORT_SYMBOL_GPL(drm_do_get_edid);
@@ -2582,6 +2613,41 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
return clock;
}
+static bool
+cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
+{
+ /*
+ * For certain VICs the spec allows the vertical
+ * front porch to vary by one or two lines.
+ *
+ * cea_modes[] stores the variant with the shortest
+ * vertical front porch. We can adjust the mode to
+ * get the other variants by simply increasing the
+ * vertical front porch length.
+ */
+ BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 ||
+ edid_cea_modes[9].vtotal != 262 ||
+ edid_cea_modes[12].vtotal != 262 ||
+ edid_cea_modes[13].vtotal != 262 ||
+ edid_cea_modes[23].vtotal != 312 ||
+ edid_cea_modes[24].vtotal != 312 ||
+ edid_cea_modes[27].vtotal != 312 ||
+ edid_cea_modes[28].vtotal != 312);
+
+ if (((vic == 8 || vic == 9 ||
+ vic == 12 || vic == 13) && mode->vtotal < 263) ||
+ ((vic == 23 || vic == 24 ||
+ vic == 27 || vic == 28) && mode->vtotal < 314)) {
+ mode->vsync_start++;
+ mode->vsync_end++;
+ mode->vtotal++;
+
+ return true;
+ }
+
+ return false;
+}
+
static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
unsigned int clock_tolerance)
{
@@ -2591,19 +2657,21 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_m
return 0;
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
- const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
+ struct drm_display_mode cea_mode = edid_cea_modes[vic];
unsigned int clock1, clock2;
/* Check both 60Hz and 59.94Hz */
- clock1 = cea_mode->clock;
- clock2 = cea_mode_alternate_clock(cea_mode);
+ clock1 = cea_mode.clock;
+ clock2 = cea_mode_alternate_clock(&cea_mode);
if (abs(to_match->clock - clock1) > clock_tolerance &&
abs(to_match->clock - clock2) > clock_tolerance)
continue;
- if (drm_mode_equal_no_clocks(to_match, cea_mode))
- return vic;
+ do {
+ if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
+ return vic;
+ } while (cea_mode_alternate_timings(vic, &cea_mode));
}
return 0;
@@ -2624,18 +2692,23 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
return 0;
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
- const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
+ struct drm_display_mode cea_mode = edid_cea_modes[vic];
unsigned int clock1, clock2;
/* Check both 60Hz and 59.94Hz */
- clock1 = cea_mode->clock;
- clock2 = cea_mode_alternate_clock(cea_mode);
+ clock1 = cea_mode.clock;
+ clock2 = cea_mode_alternate_clock(&cea_mode);
- if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
- KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
- drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
- return vic;
+ if (KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock1) &&
+ KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock2))
+ continue;
+
+ do {
+ if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
+ return vic;
+ } while (cea_mode_alternate_timings(vic, &cea_mode));
}
+
return 0;
}
EXPORT_SYMBOL(drm_match_cea_mode);
@@ -3580,32 +3653,6 @@ int drm_av_sync_delay(struct drm_connector *connector,
EXPORT_SYMBOL(drm_av_sync_delay);
/**
- * drm_select_eld - select one ELD from multiple HDMI/DP sinks
- * @encoder: the encoder just changed 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.
- *
- * 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_connector *connector;
- struct drm_device *dev = encoder->dev;
-
- WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
- WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
-
- drm_for_each_connector(connector, dev)
- if (connector->encoder == encoder && connector->eld[0])
- return connector;
-
- return NULL;
-}
-EXPORT_SYMBOL(drm_select_eld);
-
-/**
* drm_detect_hdmi_monitor - detect whether monitor is HDMI
* @edid: monitor EDID information
*
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 5c067719164d..992879f15f23 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -110,11 +110,9 @@ int drm_encoder_init(struct drm_device *dev,
{
int ret;
- drm_modeset_lock_all(dev);
-
ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
if (ret)
- goto out_unlock;
+ return ret;
encoder->dev = dev;
encoder->encoder_type = encoder_type;
@@ -142,9 +140,6 @@ out_put:
if (ret)
drm_mode_object_unregister(dev, &encoder->base);
-out_unlock:
- drm_modeset_unlock_all(dev);
-
return ret;
}
EXPORT_SYMBOL(drm_encoder_init);
@@ -164,12 +159,10 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
* the indices on the drm_encoder after us in the encoder_list.
*/
- drm_modeset_lock_all(dev);
drm_mode_object_unregister(dev, &encoder->base);
kfree(encoder->name);
list_del(&encoder->head);
dev->mode_config.num_encoder--;
- drm_modeset_unlock_all(dev);
memset(encoder, 0, sizeof(*encoder));
}
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 1fd6eac1400c..81b3558302b5 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -18,13 +18,16 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
+#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/reservation.h>
#define DEFAULT_FBDEFIO_DELAY_MS 50
@@ -176,20 +179,20 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd,
const struct drm_framebuffer_funcs *funcs)
{
+ const struct drm_format_info *info;
struct drm_fb_cma *fb_cma;
struct drm_gem_cma_object *objs[4];
struct drm_gem_object *obj;
- unsigned int hsub;
- unsigned int vsub;
int ret;
int i;
- hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
- vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
+ info = drm_format_info(mode_cmd->pixel_format);
+ if (!info)
+ return ERR_PTR(-EINVAL);
- for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
- unsigned int width = mode_cmd->width / (i ? hsub : 1);
- unsigned int height = mode_cmd->height / (i ? vsub : 1);
+ for (i = 0; i < info->num_planes; i++) {
+ unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
+ unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
unsigned int min_size;
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
@@ -200,7 +203,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
}
min_size = (height - 1) * mode_cmd->pitches[i]
- + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)
+ + width * info->cpp[i]
+ mode_cmd->offsets[i];
if (obj->size < min_size) {
@@ -265,16 +268,51 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
}
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
+/**
+ * drm_fb_cma_prepare_fb() - Prepare CMA framebuffer
+ * @plane: Which plane
+ * @state: Plane state attach fence to
+ *
+ * This should be put into prepare_fb hook of struct &drm_plane_helper_funcs .
+ *
+ * This function checks if the plane FB has an dma-buf attached, extracts
+ * the exclusive fence and attaches it to plane state for the atomic helper
+ * to wait on.
+ *
+ * There is no need for cleanup_fb for CMA based framebuffer drivers.
+ */
+int drm_fb_cma_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct dma_buf *dma_buf;
+ struct dma_fence *fence;
+
+ if ((plane->state->fb == state->fb) || !state->fb)
+ return 0;
+
+ dma_buf = drm_fb_cma_get_gem_obj(state->fb, 0)->base.dma_buf;
+ if (dma_buf) {
+ fence = reservation_object_get_excl_rcu(dma_buf->resv);
+ drm_atomic_set_fence_for_plane(state, fence);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb);
+
#ifdef CONFIG_DEBUG_FS
static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
{
struct drm_fb_cma *fb_cma = to_fb_cma(fb);
- int i, n = drm_format_num_planes(fb->pixel_format);
+ const struct drm_format_info *info;
+ int i;
seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
(char *)&fb->pixel_format);
- for (i = 0; i < n; i++) {
+ info = drm_format_info(fb->pixel_format);
+
+ for (i = 0; i < info->num_planes; i++) {
seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
i, fb->offsets[i], fb->pitches[i]);
drm_gem_cma_describe(fb_cma->obj[i], m);
@@ -311,14 +349,10 @@ static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
static struct fb_ops drm_fbdev_cma_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
.fb_mmap = drm_fb_cma_mmap,
};
@@ -557,7 +591,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
{
drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
- drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
+ if (fbdev_cma->fb_helper.fbdev)
+ drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
if (fbdev_cma->fb) {
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 6c75e62c0b22..e934b541feea 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -49,6 +49,7 @@ MODULE_PARM_DESC(fbdev_emulation,
"Enable legacy fbdev emulation [default=true]");
static LIST_HEAD(kernel_fb_helper_list);
+static DEFINE_MUTEX(kernel_fb_helper_lock);
/**
* DOC: fbdev helpers
@@ -97,6 +98,10 @@ static LIST_HEAD(kernel_fb_helper_list);
* mmap page writes.
*/
+#define drm_fb_helper_for_each_connector(fbh, i__) \
+ for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \
+ i__ = 0; i__ < (fbh)->connector_count; i__++)
+
/**
* drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
* emulation helper
@@ -130,7 +135,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
mutex_unlock(&dev->mode_config.mutex);
return 0;
fail:
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
struct drm_fb_helper_connector *fb_helper_connector =
fb_helper->connector_info[i];
@@ -256,6 +261,9 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
continue;
funcs = mode_set->crtc->helper_private;
+ if (funcs->mode_set_base_atomic == NULL)
+ continue;
+
drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
funcs->mode_set_base_atomic(mode_set->crtc,
mode_set->fb,
@@ -309,6 +317,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
continue;
}
+ if (funcs->mode_set_base_atomic == NULL)
+ continue;
+
drm_fb_helper_restore_lut_atomic(mode_set->crtc);
funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
crtc->y, LEAVE_ATOMIC_MODE_SET);
@@ -372,9 +383,7 @@ fail:
if (ret == -EDEADLK)
goto backoff;
- if (ret != 0)
- drm_atomic_state_free(state);
-
+ drm_atomic_state_put(state);
return ret;
backoff:
@@ -399,11 +408,10 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
- if (dev->mode_config.rotation_property) {
+ if (plane->rotation_property)
drm_mode_plane_set_obj_prop(plane,
- dev->mode_config.rotation_property,
+ plane->rotation_property,
DRM_ROTATE_0);
- }
}
for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -562,7 +570,7 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
continue;
/* Walk the connectors & encoders on this fb turning them on/off */
- for (j = 0; j < fb_helper->connector_count; j++) {
+ drm_fb_helper_for_each_connector(fb_helper, j) {
connector = fb_helper->connector_info[j]->connector;
connector->funcs->dpms(connector, dpms_mode);
drm_object_property_set_value(&connector->base,
@@ -848,12 +856,14 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
if (!drm_fbdev_emulation)
return;
+ mutex_lock(&kernel_fb_helper_lock);
if (!list_empty(&fb_helper->kernel_fb_list)) {
list_del(&fb_helper->kernel_fb_list);
if (list_empty(&kernel_fb_helper_list)) {
unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
}
}
+ mutex_unlock(&kernel_fb_helper_lock);
drm_fb_helper_crtc_free(fb_helper);
@@ -1238,11 +1248,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
if (var->pixclock != 0 || in_dbg_master())
return -EINVAL;
- /* Need to resize the fb object !!! */
- if (var->bits_per_pixel > fb->bits_per_pixel ||
- var->xres > fb->width || var->yres > fb->height ||
- var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
- DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
+ /*
+ * Changes struct fb_var_screeninfo are currently not pushed back
+ * to KMS, hence fail if different settings are requested.
+ */
+ if (var->bits_per_pixel != fb->bits_per_pixel ||
+ var->xres != fb->width || var->yres != fb->height ||
+ var->xres_virtual != fb->width || var->yres_virtual != fb->height) {
+ DRM_DEBUG("fb userspace requested width/height/bpp different than current fb "
"request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
var->xres, var->yres, var->bits_per_pixel,
var->xres_virtual, var->yres_virtual,
@@ -1388,16 +1401,13 @@ retry:
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);
-
+ drm_atomic_state_put(state);
return ret;
backoff:
@@ -1466,7 +1476,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int ret = 0;
int crtc_count = 0;
int i;
- struct fb_info *info;
struct drm_fb_helper_surface_size sizes;
int gamma_size = 0;
@@ -1482,7 +1491,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
/* first up get a count of crtcs now in use and new min/maxes width/heights */
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
struct drm_cmdline_mode *cmdline_mode;
@@ -1569,8 +1578,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (ret < 0)
return ret;
- info = fb_helper->fbdev;
-
/*
* Set the fb pointer - usually drm_setup_crtcs does this for hotplug
* events, but at init time drm_setup_crtcs needs to be called before
@@ -1582,20 +1589,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (fb_helper->crtc_info[i].mode_set.num_connectors)
fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
-
- info->var.pixclock = 0;
- if (register_framebuffer(info) < 0)
- return -EINVAL;
-
- dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
- info->node, info->fix.id);
-
- if (list_empty(&kernel_fb_helper_list)) {
- register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
- }
-
- list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
-
return 0;
}
@@ -1727,7 +1720,7 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
int count = 0;
int i;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
connector = fb_helper->connector_info[i]->connector;
count += connector->funcs->fill_modes(connector, maxX, maxY);
}
@@ -1827,7 +1820,7 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
struct drm_connector *connector;
int i = 0;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
connector = fb_helper->connector_info[i]->connector;
enabled[i] = drm_connector_enabled(connector, true);
DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
@@ -1838,7 +1831,7 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
if (any_enabled)
return;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
connector = fb_helper->connector_info[i]->connector;
enabled[i] = drm_connector_enabled(connector, false);
}
@@ -1859,7 +1852,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
return false;
count = 0;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
if (enabled[i])
count++;
}
@@ -1870,7 +1863,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
/* check the command line or if nothing common pick 1024x768 */
can_clone = true;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
if (!enabled[i])
continue;
fb_helper_conn = fb_helper->connector_info[i];
@@ -1896,8 +1889,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
can_clone = true;
dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false);
- for (i = 0; i < fb_helper->connector_count; i++) {
-
+ drm_fb_helper_for_each_connector(fb_helper, i) {
if (!enabled[i])
continue;
@@ -1928,7 +1920,7 @@ static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper,
int i;
int hoffset = 0, voffset = 0;
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
fb_helper_conn = fb_helper->connector_info[i];
if (!fb_helper_conn->connector->has_tile)
continue;
@@ -1956,19 +1948,20 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
bool *enabled, int width, int height)
{
struct drm_fb_helper_connector *fb_helper_conn;
- int i;
- uint64_t conn_configured = 0, mask;
+ const u64 mask = BIT_ULL(fb_helper->connector_count) - 1;
+ u64 conn_configured = 0;
int tile_pass = 0;
- mask = (1 << fb_helper->connector_count) - 1;
+ int i;
+
retry:
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
fb_helper_conn = fb_helper->connector_info[i];
- if (conn_configured & (1 << i))
+ if (conn_configured & BIT_ULL(i))
continue;
if (enabled[i] == false) {
- conn_configured |= (1 << i);
+ conn_configured |= BIT_ULL(i);
continue;
}
@@ -2009,7 +2002,7 @@ retry:
}
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
"none");
- conn_configured |= (1 << i);
+ conn_configured |= BIT_ULL(i);
}
if ((conn_configured & mask) != mask) {
@@ -2109,20 +2102,22 @@ out:
return best_score;
}
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
+static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
+ u32 width, u32 height)
{
struct drm_device *dev = fb_helper->dev;
struct drm_fb_helper_crtc **crtcs;
struct drm_display_mode **modes;
struct drm_fb_offset *offsets;
bool *enabled;
- int width, height;
int i;
DRM_DEBUG_KMS("\n");
+ if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
+ DRM_DEBUG_KMS("No connectors reported connected with modes\n");
- width = dev->mode_config.max_width;
- height = dev->mode_config.max_height;
+ /* prevent concurrent modification of connector_count by hotplug */
+ lockdep_assert_held(&fb_helper->dev->mode_config.mutex);
crtcs = kcalloc(fb_helper->connector_count,
sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
@@ -2137,7 +2132,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
goto out;
}
-
drm_enable_connectors(fb_helper, enabled);
if (!(fb_helper->funcs->initial_config &&
@@ -2166,7 +2160,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
drm_fb_helper_modeset_release(fb_helper,
&fb_helper->crtc_info[i].mode_set);
- for (i = 0; i < fb_helper->connector_count; i++) {
+ drm_fb_helper_for_each_connector(fb_helper, i) {
struct drm_display_mode *mode = modes[i];
struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
struct drm_fb_offset *offset = &offsets[i];
@@ -2243,25 +2237,38 @@ out:
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;
+ struct fb_info *info;
+ int ret;
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,
- dev->mode_config.max_height);
+ drm_setup_crtcs(fb_helper,
+ dev->mode_config.max_width,
+ dev->mode_config.max_height);
+ ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
mutex_unlock(&dev->mode_config.mutex);
- /*
- * we shouldn't end up with no modes here.
- */
- if (count == 0)
- dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
+ if (ret)
+ return ret;
+
+ info = fb_helper->fbdev;
+ info->var.pixclock = 0;
+ ret = register_framebuffer(info);
+ if (ret < 0)
+ return ret;
+
+ dev_info(dev->dev, "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ mutex_lock(&kernel_fb_helper_lock);
+ if (list_empty(&kernel_fb_helper_list))
+ register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
- drm_setup_crtcs(fb_helper);
+ list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
+ mutex_unlock(&kernel_fb_helper_lock);
- return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
+ return 0;
}
EXPORT_SYMBOL(drm_fb_helper_initial_config);
@@ -2289,28 +2296,22 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
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);
+ mutex_lock(&dev->mode_config.mutex);
if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
fb_helper->delayed_hotplug = true;
- mutex_unlock(&fb_helper->dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.mutex);
return 0;
}
DRM_DEBUG_KMS("\n");
- max_width = fb_helper->fb->width;
- max_height = fb_helper->fb->height;
+ drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);
- drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height);
- mutex_unlock(&fb_helper->dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.mutex);
- drm_modeset_lock_all(dev);
- drm_setup_crtcs(fb_helper);
- drm_modeset_unlock_all(dev);
drm_fb_helper_set_par(fb_helper->fbdev);
return 0;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index e84faecf5225..5d96de40b63f 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -51,10 +51,11 @@ DEFINE_MUTEX(drm_global_mutex);
* Drivers must define the file operations structure that forms the DRM
* userspace API entry point, even though most of those operations are
* implemented in the DRM core. The mandatory functions are drm_open(),
- * drm_read(), drm_ioctl() and drm_compat_ioctl if CONFIG_COMPAT is enabled.
- * Drivers which implement private ioctls that require 32/64 bit compatibility
- * support must provided their onw .compat_ioctl() handler that processes
- * private ioctls and calls drm_compat_ioctl() for core ioctls.
+ * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled
+ * (note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which
+ * implement private ioctls that require 32/64 bit compatibility support must
+ * provide their own .compat_ioctl() handler that processes private ioctls and
+ * calls drm_compat_ioctl() for core ioctls.
*
* In addition drm_read() and drm_poll() provide support for DRM events. DRM
* events are a generic and extensible means to send asynchronous events to
@@ -75,9 +76,7 @@ DEFINE_MUTEX(drm_global_mutex);
* .open = drm_open,
* .release = drm_release,
* .unlocked_ioctl = drm_ioctl,
- * #ifdef CONFIG_COMPAT
- * .compat_ioctl = drm_compat_ioctl,
- * #endif
+ * .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n
* .poll = drm_poll,
* .read = drm_read,
* .llseek = no_llseek,
@@ -663,6 +662,10 @@ void drm_event_cancel_free(struct drm_device *dev,
list_del(&p->pending_link);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ if (p->fence)
+ dma_fence_put(p->fence);
+
kfree(p);
}
EXPORT_SYMBOL(drm_event_cancel_free);
@@ -692,8 +695,8 @@ void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
}
if (e->fence) {
- fence_signal(e->fence);
- fence_put(e->fence);
+ dma_fence_signal(e->fence);
+ dma_fence_put(e->fence);
}
if (!e->file_priv) {
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 29c56b4331e0..90d2cc8da8eb 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -79,17 +79,13 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
EXPORT_SYMBOL(drm_mode_legacy_fb_format);
/**
- * drm_get_format_name - return a string for drm fourcc format
+ * drm_get_format_name - fill a string with a drm fourcc format's name
* @format: format to compute name of
- *
- * Note that the buffer returned by this function is owned by the caller
- * and will need to be freed using kfree().
+ * @buf: caller-supplied buffer
*/
-char *drm_get_format_name(uint32_t format)
+const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
{
- char *buf = kmalloc(32, GFP_KERNEL);
-
- snprintf(buf, 32,
+ snprintf(buf->str, sizeof(buf->str),
"%c%c%c%c %s-endian (0x%08x)",
printable_char(format & 0xff),
printable_char((format >> 8) & 0xff),
@@ -98,87 +94,109 @@ char *drm_get_format_name(uint32_t format)
format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
format);
- return buf;
+ return buf->str;
}
EXPORT_SYMBOL(drm_get_format_name);
+/*
+ * Internal function to query information for a given format. See
+ * drm_format_info() for the public API.
+ */
+const struct drm_format_info *__drm_format_info(u32 format)
+{
+ static const struct drm_format_info formats[] = {
+ { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
+ { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
+ { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
+ { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
+ { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
+ { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
+ { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
+ { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
+ { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
+ { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+ { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ if (formats[i].format == format)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+
/**
- * drm_fb_get_bpp_depth - get the bpp/depth values for format
+ * drm_format_info - query information for a given format
* @format: pixel format (DRM_FORMAT_*)
- * @depth: storage for the depth value
- * @bpp: storage for the bpp value
*
- * This only supports RGB formats here for compat with code that doesn't use
- * pixel formats directly yet.
+ * The caller should only pass a supported pixel format to this function.
+ * Unsupported pixel formats will generate a warning in the kernel log.
+ *
+ * Returns:
+ * The instance of struct drm_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
*/
-void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
- int *bpp)
+const struct drm_format_info *drm_format_info(u32 format)
{
- char *format_name;
+ const struct drm_format_info *info;
- switch (format) {
- case DRM_FORMAT_C8:
- case DRM_FORMAT_RGB332:
- case DRM_FORMAT_BGR233:
- *depth = 8;
- *bpp = 8;
- break;
- case DRM_FORMAT_XRGB1555:
- case DRM_FORMAT_XBGR1555:
- case DRM_FORMAT_RGBX5551:
- case DRM_FORMAT_BGRX5551:
- case DRM_FORMAT_ARGB1555:
- case DRM_FORMAT_ABGR1555:
- case DRM_FORMAT_RGBA5551:
- case DRM_FORMAT_BGRA5551:
- *depth = 15;
- *bpp = 16;
- break;
- case DRM_FORMAT_RGB565:
- case DRM_FORMAT_BGR565:
- *depth = 16;
- *bpp = 16;
- break;
- case DRM_FORMAT_RGB888:
- case DRM_FORMAT_BGR888:
- *depth = 24;
- *bpp = 24;
- break;
- case DRM_FORMAT_XRGB8888:
- case DRM_FORMAT_XBGR8888:
- case DRM_FORMAT_RGBX8888:
- case DRM_FORMAT_BGRX8888:
- *depth = 24;
- *bpp = 32;
- break;
- case DRM_FORMAT_XRGB2101010:
- case DRM_FORMAT_XBGR2101010:
- case DRM_FORMAT_RGBX1010102:
- case DRM_FORMAT_BGRX1010102:
- case DRM_FORMAT_ARGB2101010:
- case DRM_FORMAT_ABGR2101010:
- case DRM_FORMAT_RGBA1010102:
- case DRM_FORMAT_BGRA1010102:
- *depth = 30;
- *bpp = 32;
- break;
- case DRM_FORMAT_ARGB8888:
- case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_RGBA8888:
- case DRM_FORMAT_BGRA8888:
- *depth = 32;
- *bpp = 32;
- break;
- default:
- format_name = drm_get_format_name(format);
- DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
- kfree(format_name);
- *depth = 0;
- *bpp = 0;
- break;
- }
+ info = __drm_format_info(format);
+ WARN_ON(!info);
+ return info;
}
-EXPORT_SYMBOL(drm_fb_get_bpp_depth);
+EXPORT_SYMBOL(drm_format_info);
/**
* drm_format_num_planes - get the number of planes for format
@@ -189,28 +207,10 @@ EXPORT_SYMBOL(drm_fb_get_bpp_depth);
*/
int drm_format_num_planes(uint32_t format)
{
- switch (format) {
- case DRM_FORMAT_YUV410:
- case DRM_FORMAT_YVU410:
- case DRM_FORMAT_YUV411:
- case DRM_FORMAT_YVU411:
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- case DRM_FORMAT_YUV422:
- case DRM_FORMAT_YVU422:
- case DRM_FORMAT_YUV444:
- case DRM_FORMAT_YVU444:
- return 3;
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- case DRM_FORMAT_NV16:
- case DRM_FORMAT_NV61:
- case DRM_FORMAT_NV24:
- case DRM_FORMAT_NV42:
- return 2;
- default:
- return 1;
- }
+ const struct drm_format_info *info;
+
+ info = drm_format_info(format);
+ return info ? info->num_planes : 1;
}
EXPORT_SYMBOL(drm_format_num_planes);
@@ -224,40 +224,13 @@ EXPORT_SYMBOL(drm_format_num_planes);
*/
int drm_format_plane_cpp(uint32_t format, int plane)
{
- unsigned int depth;
- int bpp;
+ const struct drm_format_info *info;
- if (plane >= drm_format_num_planes(format))
+ info = drm_format_info(format);
+ if (!info || plane >= info->num_planes)
return 0;
- switch (format) {
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_YVYU:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_VYUY:
- return 2;
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- case DRM_FORMAT_NV16:
- case DRM_FORMAT_NV61:
- case DRM_FORMAT_NV24:
- case DRM_FORMAT_NV42:
- return plane ? 2 : 1;
- case DRM_FORMAT_YUV410:
- case DRM_FORMAT_YVU410:
- case DRM_FORMAT_YUV411:
- case DRM_FORMAT_YVU411:
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- case DRM_FORMAT_YUV422:
- case DRM_FORMAT_YVU422:
- case DRM_FORMAT_YUV444:
- case DRM_FORMAT_YVU444:
- return 1;
- default:
- drm_fb_get_bpp_depth(format, &depth, &bpp);
- return bpp >> 3;
- }
+ return info->cpp[plane];
}
EXPORT_SYMBOL(drm_format_plane_cpp);
@@ -271,28 +244,10 @@ EXPORT_SYMBOL(drm_format_plane_cpp);
*/
int drm_format_horz_chroma_subsampling(uint32_t format)
{
- switch (format) {
- case DRM_FORMAT_YUV411:
- case DRM_FORMAT_YVU411:
- case DRM_FORMAT_YUV410:
- case DRM_FORMAT_YVU410:
- return 4;
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_YVYU:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_VYUY:
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- case DRM_FORMAT_NV16:
- case DRM_FORMAT_NV61:
- case DRM_FORMAT_YUV422:
- case DRM_FORMAT_YVU422:
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- return 2;
- default:
- return 1;
- }
+ const struct drm_format_info *info;
+
+ info = drm_format_info(format);
+ return info ? info->hsub : 1;
}
EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
@@ -306,18 +261,10 @@ EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
*/
int drm_format_vert_chroma_subsampling(uint32_t format)
{
- switch (format) {
- case DRM_FORMAT_YUV410:
- case DRM_FORMAT_YVU410:
- return 4;
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- return 2;
- default:
- return 1;
- }
+ const struct drm_format_info *info;
+
+ info = drm_format_info(format);
+ return info ? info->vsub : 1;
}
EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
@@ -332,13 +279,16 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
*/
int drm_format_plane_width(int width, uint32_t format, int plane)
{
- if (plane >= drm_format_num_planes(format))
+ const struct drm_format_info *info;
+
+ info = drm_format_info(format);
+ if (!info || plane >= info->num_planes)
return 0;
if (plane == 0)
return width;
- return width / drm_format_horz_chroma_subsampling(format);
+ return width / info->hsub;
}
EXPORT_SYMBOL(drm_format_plane_width);
@@ -353,12 +303,15 @@ EXPORT_SYMBOL(drm_format_plane_width);
*/
int drm_format_plane_height(int height, uint32_t format, int plane)
{
- if (plane >= drm_format_num_planes(format))
+ const struct drm_format_info *info;
+
+ info = drm_format_info(format);
+ if (!info || plane >= info->num_planes)
return 0;
if (plane == 0)
return height;
- return height / drm_format_vert_chroma_subsampling(format);
+ return height / info->vsub;
}
EXPORT_SYMBOL(drm_format_plane_height);
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 398efd67cb93..cbf0c893f426 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -126,111 +126,34 @@ int drm_mode_addfb(struct drm_device *dev,
return 0;
}
-static int format_check(const struct drm_mode_fb_cmd2 *r)
-{
- uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
- char *format_name;
-
- switch (format) {
- case DRM_FORMAT_C8:
- case DRM_FORMAT_RGB332:
- case DRM_FORMAT_BGR233:
- case DRM_FORMAT_XRGB4444:
- case DRM_FORMAT_XBGR4444:
- case DRM_FORMAT_RGBX4444:
- case DRM_FORMAT_BGRX4444:
- case DRM_FORMAT_ARGB4444:
- case DRM_FORMAT_ABGR4444:
- case DRM_FORMAT_RGBA4444:
- case DRM_FORMAT_BGRA4444:
- case DRM_FORMAT_XRGB1555:
- case DRM_FORMAT_XBGR1555:
- case DRM_FORMAT_RGBX5551:
- case DRM_FORMAT_BGRX5551:
- 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_XRGB8888:
- case DRM_FORMAT_XBGR8888:
- case DRM_FORMAT_RGBX8888:
- case DRM_FORMAT_BGRX8888:
- case DRM_FORMAT_ARGB8888:
- case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_RGBA8888:
- case DRM_FORMAT_BGRA8888:
- case DRM_FORMAT_XRGB2101010:
- case DRM_FORMAT_XBGR2101010:
- case DRM_FORMAT_RGBX1010102:
- case DRM_FORMAT_BGRX1010102:
- case DRM_FORMAT_ARGB2101010:
- case DRM_FORMAT_ABGR2101010:
- case DRM_FORMAT_RGBA1010102:
- case DRM_FORMAT_BGRA1010102:
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_YVYU:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_VYUY:
- case DRM_FORMAT_AYUV:
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- case DRM_FORMAT_NV16:
- case DRM_FORMAT_NV61:
- case DRM_FORMAT_NV24:
- case DRM_FORMAT_NV42:
- case DRM_FORMAT_YUV410:
- case DRM_FORMAT_YVU410:
- case DRM_FORMAT_YUV411:
- case DRM_FORMAT_YVU411:
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- case DRM_FORMAT_YUV422:
- case DRM_FORMAT_YVU422:
- case DRM_FORMAT_YUV444:
- case DRM_FORMAT_YVU444:
- return 0;
- default:
- format_name = drm_get_format_name(r->pixel_format);
- DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
- kfree(format_name);
- return -EINVAL;
- }
-}
-
static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
{
- int ret, hsub, vsub, num_planes, i;
-
- ret = format_check(r);
- if (ret) {
- char *format_name = drm_get_format_name(r->pixel_format);
- DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name);
- kfree(format_name);
- return ret;
+ const struct drm_format_info *info;
+ int i;
+
+ info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
+ if (!info) {
+ struct drm_format_name_buf format_name;
+ DRM_DEBUG_KMS("bad framebuffer format %s\n",
+ drm_get_format_name(r->pixel_format,
+ &format_name));
+ return -EINVAL;
}
- hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
- vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
- num_planes = drm_format_num_planes(r->pixel_format);
-
- if (r->width == 0 || r->width % hsub) {
+ if (r->width == 0 || r->width % info->hsub) {
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
return -EINVAL;
}
- if (r->height == 0 || r->height % vsub) {
+ if (r->height == 0 || r->height % info->vsub) {
DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
return -EINVAL;
}
- for (i = 0; i < num_planes; i++) {
- unsigned int width = r->width / (i != 0 ? hsub : 1);
- unsigned int height = r->height / (i != 0 ? vsub : 1);
- unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
+ for (i = 0; i < info->num_planes; i++) {
+ unsigned int width = r->width / (i != 0 ? info->hsub : 1);
+ unsigned int height = r->height / (i != 0 ? info->vsub : 1);
+ unsigned int cpp = info->cpp[i];
if (!r->handles[i]) {
DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
@@ -254,6 +177,13 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
return -EINVAL;
}
+ if (r->flags & DRM_MODE_FB_MODIFIERS &&
+ r->modifier[i] != r->modifier[0]) {
+ DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
+ r->modifier[i], i);
+ return -EINVAL;
+ }
+
/* modifier specific checks: */
switch (r->modifier[i]) {
case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
@@ -273,7 +203,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
}
}
- for (i = num_planes; i < 4; i++) {
+ for (i = info->num_planes; i < 4; i++) {
if (r->modifier[i]) {
DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
return -EINVAL;
@@ -751,6 +681,11 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
* those used for fbdev. Note that the caller must hold a reference of it's own,
* i.e. the object may not be destroyed through this call (since it'll lead to a
* locking inversion).
+ *
+ * NOTE: This function is deprecated. For driver-private framebuffers it is not
+ * recommended to embed a framebuffer struct info fbdev struct, instead, a
+ * framebuffer pointer is preferred and drm_framebuffer_unreference() should be
+ * called when the framebuffer is to be cleaned up.
*/
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
{
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index e66af289a016..db80ec860e33 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -24,9 +24,6 @@
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 4
-/* drm_irq.c */
-extern unsigned int drm_timestamp_monotonic;
-
/* drm_fops.c */
extern struct mutex drm_global_mutex;
void drm_lastclose(struct drm_device *dev);
@@ -46,12 +43,21 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
struct dma_buf *dma_buf);
+/* drm_drv.c */
+struct drm_minor *drm_minor_acquire(unsigned int minor_id);
+void drm_minor_release(struct drm_minor *minor);
+
/* drm_info.c */
int drm_name_info(struct seq_file *m, void *data);
int drm_clients_info(struct seq_file *m, void* data);
int drm_gem_name_info(struct seq_file *m, void *data);
/* drm_irq.c */
+extern unsigned int drm_timestamp_monotonic;
+
+/* IOCTLS */
+int drm_wait_vblank(struct drm_device *dev, void *data,
+ struct drm_file *filp);
int drm_control(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int drm_modeset_ctl(struct drm_device *dev, void *data,
@@ -100,6 +106,9 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
int drm_debugfs_cleanup(struct drm_minor *minor);
int drm_debugfs_connector_add(struct drm_connector *connector);
void drm_debugfs_connector_remove(struct drm_connector *connector);
+int drm_debugfs_crtc_add(struct drm_crtc *crtc);
+void drm_debugfs_crtc_remove(struct drm_crtc *crtc);
+int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc);
#else
static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id,
struct dentry *root)
@@ -119,4 +128,17 @@ static inline int drm_debugfs_connector_add(struct drm_connector *connector)
static inline void drm_debugfs_connector_remove(struct drm_connector *connector)
{
}
+
+static inline int drm_debugfs_crtc_add(struct drm_crtc *crtc)
+{
+ return 0;
+}
+static inline void drm_debugfs_crtc_remove(struct drm_crtc *crtc)
+{
+}
+
+static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
+{
+ return 0;
+}
#endif
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 71c3473476c7..fed22c2b98b6 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -229,6 +229,22 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
struct drm_crtc *crtc;
req->value = 0;
+
+ /* Only some caps make sense with UMS/render-only drivers. */
+ switch (req->capability) {
+ case DRM_CAP_TIMESTAMP_MONOTONIC:
+ req->value = drm_timestamp_monotonic;
+ return 0;
+ case DRM_CAP_PRIME:
+ req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
+ req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
+ return 0;
+ }
+
+ /* Other caps only work with KMS drivers */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -ENOTSUPP;
+
switch (req->capability) {
case DRM_CAP_DUMB_BUFFER:
if (dev->driver->dumb_create)
@@ -243,23 +259,14 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
case DRM_CAP_DUMB_PREFER_SHADOW:
req->value = dev->mode_config.prefer_shadow;
break;
- case DRM_CAP_PRIME:
- req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
- req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
- break;
- case DRM_CAP_TIMESTAMP_MONOTONIC:
- req->value = drm_timestamp_monotonic;
- break;
case DRM_CAP_ASYNC_PAGE_FLIP:
req->value = dev->mode_config.async_page_flip;
break;
case DRM_CAP_PAGE_FLIP_TARGET:
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- req->value = 1;
- drm_for_each_crtc(crtc, dev) {
- if (!crtc->funcs->page_flip_target)
- req->value = 0;
- }
+ req->value = 1;
+ drm_for_each_crtc(crtc, dev) {
+ if (!crtc->funcs->page_flip_target)
+ req->value = 0;
}
break;
case DRM_CAP_CURSOR_WIDTH:
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index b969a64a1514..273625a85036 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -93,7 +93,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
* Reset the stored timestamp for the current vblank count to correspond
* to the last vblank occurred.
*
- * Only to be called from drm_vblank_on().
+ * Only to be called from drm_crtc_vblank_on().
*
* Note: caller must hold dev->vbl_lock since this reads & writes
* device vblank fields.
@@ -234,6 +234,16 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
}
+static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
+{
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+ if (WARN_ON(pipe >= dev->num_crtcs))
+ return 0;
+
+ return vblank->count;
+}
+
/**
* drm_accurate_vblank_count - retrieve the master vblank counter
* @crtc: which counter to retrieve
@@ -296,7 +306,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
* 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().
+ * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
*/
drm_update_vblank_count(dev, pipe, 0);
@@ -888,31 +898,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
}
/**
- * drm_vblank_count - retrieve "cooked" vblank counter value
- * @dev: DRM device
- * @pipe: index of CRTC for which to retrieve the counter
- *
- * 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.
- *
- * This is the legacy version of drm_crtc_vblank_count().
- *
- * Returns:
- * The software vblank counter.
- */
-u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
-{
- struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
-
- if (WARN_ON(pipe >= dev->num_crtcs))
- return 0;
-
- return vblank->count;
-}
-EXPORT_SYMBOL(drm_vblank_count);
-
-/**
* drm_crtc_vblank_count - retrieve "cooked" vblank counter value
* @crtc: which counter to retrieve
*
@@ -920,8 +905,6 @@ EXPORT_SYMBOL(drm_vblank_count);
* vblank events since the system was booted, including lost events due to
* modesetting activity.
*
- * This is the native KMS version of drm_vblank_count().
- *
* Returns:
* The software vblank counter.
*/
@@ -952,8 +935,10 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
u32 vblank_count;
unsigned int seq;
- if (WARN_ON(pipe >= dev->num_crtcs))
+ if (WARN_ON(pipe >= dev->num_crtcs)) {
+ *vblanktime = (struct timeval) { 0 };
return 0;
+ }
do {
seq = read_seqbegin(&vblank->seqlock);
@@ -1270,21 +1255,20 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
/**
- * drm_vblank_off - disable vblank events on a CRTC
- * @dev: DRM device
- * @pipe: CRTC index
+ * drm_crtc_vblank_off - disable vblank events on a CRTC
+ * @crtc: CRTC in question
*
* Drivers can use this function to shut down the vblank interrupt handling when
* disabling a crtc. This function ensures that the latest vblank frame count is
- * stored so that drm_vblank_on() can restore it again.
+ * stored so that drm_vblank_on can restore it again.
*
* Drivers must use this function when the hardware vblank counter can get
* reset, e.g. when suspending.
- *
- * This is the legacy version of drm_crtc_vblank_off().
*/
-void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
+void drm_crtc_vblank_off(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
struct drm_pending_vblank_event *e, *t;
struct timeval now;
@@ -1300,7 +1284,8 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
pipe, vblank->enabled, vblank->inmodeset);
- /* Avoid redundant vblank disables without previous drm_vblank_on(). */
+ /* Avoid redundant vblank disables without previous
+ * drm_crtc_vblank_on(). */
if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
vblank_disable_and_save(dev, pipe);
@@ -1331,25 +1316,6 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
}
spin_unlock_irqrestore(&dev->event_lock, irqflags);
}
-EXPORT_SYMBOL(drm_vblank_off);
-
-/**
- * drm_crtc_vblank_off - disable vblank events on a CRTC
- * @crtc: CRTC in question
- *
- * Drivers can use this function to shut down the vblank interrupt handling when
- * disabling a crtc. This function ensures that the latest vblank frame count is
- * stored so that drm_vblank_on can restore it again.
- *
- * Drivers must use this function when the hardware vblank counter can get
- * reset, e.g. when suspending.
- *
- * This is the native kms version of drm_vblank_off().
- */
-void drm_crtc_vblank_off(struct drm_crtc *crtc)
-{
- drm_vblank_off(crtc->dev, drm_crtc_index(crtc));
-}
EXPORT_SYMBOL(drm_crtc_vblank_off);
/**
@@ -1385,19 +1351,18 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)
EXPORT_SYMBOL(drm_crtc_vblank_reset);
/**
- * drm_vblank_on - enable vblank events on a CRTC
- * @dev: DRM device
- * @pipe: CRTC index
+ * drm_crtc_vblank_on - enable vblank events on a CRTC
+ * @crtc: CRTC in question
*
* This functions restores the vblank interrupt state captured with
- * drm_vblank_off() again. Note that calls to drm_vblank_on() and
- * drm_vblank_off() can be unbalanced and so can also be unconditionally called
+ * drm_crtc_vblank_off() again. Note that calls to drm_crtc_vblank_on() and
+ * drm_crtc_vblank_off() can be unbalanced and so can also be unconditionally called
* in driver load code to reflect the current hardware state of the crtc.
- *
- * This is the legacy version of drm_crtc_vblank_on().
*/
-void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
+void drm_crtc_vblank_on(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
unsigned long irqflags;
@@ -1424,49 +1389,10 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
WARN_ON(drm_vblank_enable(dev, pipe));
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
-EXPORT_SYMBOL(drm_vblank_on);
-
-/**
- * drm_crtc_vblank_on - enable vblank events on a CRTC
- * @crtc: CRTC in question
- *
- * This functions restores the vblank interrupt state captured with
- * drm_vblank_off() again. Note that calls to drm_vblank_on() and
- * drm_vblank_off() can be unbalanced and so can also be unconditionally called
- * in driver load code to reflect the current hardware state of the crtc.
- *
- * This is the native kms version of drm_vblank_on().
- */
-void drm_crtc_vblank_on(struct drm_crtc *crtc)
-{
- drm_vblank_on(crtc->dev, drm_crtc_index(crtc));
-}
EXPORT_SYMBOL(drm_crtc_vblank_on);
-/**
- * drm_vblank_pre_modeset - account for vblanks across mode sets
- * @dev: DRM device
- * @pipe: CRTC index
- *
- * Account for vblank events across mode setting events, which will likely
- * reset the hardware frame counter.
- *
- * This is done by grabbing a temporary vblank reference to ensure that the
- * vblank interrupt keeps running across the modeset sequence. With this the
- * software-side vblank frame counting will ensure that there are no jumps or
- * discontinuities.
- *
- * Unfortunately this approach is racy and also doesn't work when the vblank
- * interrupt stops running, e.g. across system suspend resume. It is therefore
- * highly recommended that drivers use the newer drm_vblank_off() and
- * drm_vblank_on() instead. drm_vblank_pre_modeset() only works correctly when
- * using "cooked" software vblank frame counters and not relying on any hardware
- * counters.
- *
- * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc
- * again.
- */
-void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)
+static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
+ unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
@@ -1490,17 +1416,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)
vblank->inmodeset |= 0x2;
}
}
-EXPORT_SYMBOL(drm_vblank_pre_modeset);
-/**
- * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes
- * @dev: DRM device
- * @pipe: CRTC index
- *
- * This function again drops the temporary vblank reference acquired in
- * drm_vblank_pre_modeset.
- */
-void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
+static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
+ unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
unsigned long irqflags;
@@ -1523,7 +1441,6 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
vblank->inmodeset = 0;
}
}
-EXPORT_SYMBOL(drm_vblank_post_modeset);
/*
* drm_modeset_ctl - handle vblank event counter changes across mode switch
@@ -1556,10 +1473,10 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
switch (modeset->cmd) {
case _DRM_PRE_MODESET:
- drm_vblank_pre_modeset(dev, pipe);
+ drm_legacy_vblank_pre_modeset(dev, pipe);
break;
case _DRM_POST_MODESET:
- drm_vblank_post_modeset(dev, pipe);
+ drm_legacy_vblank_post_modeset(dev, pipe);
break;
default:
return -EINVAL;
@@ -1594,11 +1511,10 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
spin_lock_irqsave(&dev->event_lock, flags);
/*
- * drm_vblank_off() might have been called after we called
- * drm_vblank_get(). drm_vblank_off() holds event_lock
- * around the vblank disable, so no need for further locking.
- * The reference from drm_vblank_get() protects against
- * vblank disable from another source.
+ * drm_crtc_vblank_off() might have been called after we called
+ * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
+ * vblank disable, so no need for further locking. The reference from
+ * drm_vblank_get() protects against vblank disable from another source.
*/
if (!vblank->enabled) {
ret = -EINVAL;
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index c901f3c5b269..32d43f86a8f2 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -176,7 +176,8 @@ int drm_legacy_lock(struct drm_device *dev, void *data,
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
lock->context, task_pid_nr(current),
- master->lock.hw_lock->lock, lock->flags);
+ master->lock.hw_lock ? master->lock.hw_lock->lock : -1,
+ lock->flags);
add_wait_queue(&master->lock.lock_queue, &entry);
spin_lock_bh(&master->lock.spinlock);
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 11d44a1e0ab3..ca1e344f318d 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -104,6 +104,68 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
u64 end,
enum drm_mm_search_flags flags);
+#ifdef CONFIG_DRM_DEBUG_MM
+#include <linux/stackdepot.h>
+
+#define STACKDEPTH 32
+#define BUFSZ 4096
+
+static noinline void save_stack(struct drm_mm_node *node)
+{
+ unsigned long entries[STACKDEPTH];
+ struct stack_trace trace = {
+ .entries = entries,
+ .max_entries = STACKDEPTH,
+ .skip = 1
+ };
+
+ save_stack_trace(&trace);
+ if (trace.nr_entries != 0 &&
+ trace.entries[trace.nr_entries-1] == ULONG_MAX)
+ trace.nr_entries--;
+
+ /* May be called under spinlock, so avoid sleeping */
+ node->stack = depot_save_stack(&trace, GFP_NOWAIT);
+}
+
+static void show_leaks(struct drm_mm *mm)
+{
+ struct drm_mm_node *node;
+ unsigned long entries[STACKDEPTH];
+ char *buf;
+
+ buf = kmalloc(BUFSZ, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ list_for_each_entry(node, &mm->head_node.node_list, node_list) {
+ struct stack_trace trace = {
+ .entries = entries,
+ .max_entries = STACKDEPTH
+ };
+
+ if (!node->stack) {
+ DRM_ERROR("node [%08llx + %08llx]: unknown owner\n",
+ node->start, node->size);
+ continue;
+ }
+
+ depot_fetch_stack(node->stack, &trace);
+ snprint_stack_trace(buf, BUFSZ, &trace, 0);
+ DRM_ERROR("node [%08llx + %08llx]: inserted at\n%s",
+ node->start, node->size, buf);
+ }
+
+ kfree(buf);
+}
+
+#undef STACKDEPTH
+#undef BUFSZ
+#else
+static void save_stack(struct drm_mm_node *node) { }
+static void show_leaks(struct drm_mm *mm) { }
+#endif
+
#define START(node) ((node)->start)
#define LAST(node) ((node)->start + (node)->size - 1)
@@ -112,19 +174,12 @@ INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
START, LAST, static inline, drm_mm_interval_tree)
struct drm_mm_node *
-drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
+__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
{
return drm_mm_interval_tree_iter_first(&mm->interval_tree,
start, last);
}
-EXPORT_SYMBOL(drm_mm_interval_first);
-
-struct drm_mm_node *
-drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last)
-{
- return drm_mm_interval_tree_iter_next(node, start, last);
-}
-EXPORT_SYMBOL(drm_mm_interval_next);
+EXPORT_SYMBOL(__drm_mm_interval_first);
static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
struct drm_mm_node *node)
@@ -228,6 +283,8 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
}
+
+ save_stack(node);
}
/**
@@ -249,6 +306,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
u64 end = node->start + node->size;
struct drm_mm_node *hole;
u64 hole_start, hole_end;
+ u64 adj_start, adj_end;
if (WARN_ON(node->size == 0))
return -EINVAL;
@@ -270,9 +328,13 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
if (!hole->hole_follows)
return -ENOSPC;
- hole_start = __drm_mm_hole_node_start(hole);
- hole_end = __drm_mm_hole_node_end(hole);
- if (hole_start > node->start || hole_end < end)
+ adj_start = hole_start = __drm_mm_hole_node_start(hole);
+ adj_end = hole_end = __drm_mm_hole_node_end(hole);
+
+ if (mm->color_adjust)
+ mm->color_adjust(hole, node->color, &adj_start, &adj_end);
+
+ if (adj_start > node->start || adj_end < end)
return -ENOSPC;
node->mm = mm;
@@ -293,6 +355,8 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
node->hole_follows = 1;
}
+ save_stack(node);
+
return 0;
}
EXPORT_SYMBOL(drm_mm_reserve_node);
@@ -397,6 +461,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
}
+
+ save_stack(node);
}
/**
@@ -839,6 +905,7 @@ void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
/* Clever trick to avoid a special case in the free hole tracking. */
INIT_LIST_HEAD(&mm->head_node.node_list);
+ mm->head_node.allocated = 0;
mm->head_node.hole_follows = 1;
mm->head_node.scanned_block = 0;
mm->head_node.scanned_prev_free = 0;
@@ -861,10 +928,12 @@ EXPORT_SYMBOL(drm_mm_init);
* Note that it is a bug to call this function on an allocator which is not
* clean.
*/
-void drm_mm_takedown(struct drm_mm * mm)
+void drm_mm_takedown(struct drm_mm *mm)
{
- WARN(!list_empty(&mm->head_node.node_list),
- "Memory manager not clean during takedown.\n");
+ if (WARN(!list_empty(&mm->head_node.node_list),
+ "Memory manager not clean during takedown.\n"))
+ show_leaks(mm);
+
}
EXPORT_SYMBOL(drm_mm_takedown);
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
new file mode 100644
index 000000000000..2735a5847ffa
--- /dev/null
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, 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 <drm/drm_mode_config.h>
+#include <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+
+int drm_modeset_register_all(struct drm_device *dev)
+{
+ int ret;
+
+ ret = drm_plane_register_all(dev);
+ if (ret)
+ goto err_plane;
+
+ ret = drm_crtc_register_all(dev);
+ if (ret)
+ goto err_crtc;
+
+ ret = drm_encoder_register_all(dev);
+ if (ret)
+ goto err_encoder;
+
+ ret = drm_connector_register_all(dev);
+ if (ret)
+ goto err_connector;
+
+ return 0;
+
+err_connector:
+ drm_encoder_unregister_all(dev);
+err_encoder:
+ drm_crtc_unregister_all(dev);
+err_crtc:
+ drm_plane_unregister_all(dev);
+err_plane:
+ return ret;
+}
+
+void drm_modeset_unregister_all(struct drm_device *dev)
+{
+ drm_connector_unregister_all(dev);
+ drm_encoder_unregister_all(dev);
+ drm_crtc_unregister_all(dev);
+ drm_plane_unregister_all(dev);
+}
+
+/**
+ * drm_mode_getresources - get graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Construct a set of configuration description structures and return
+ * them to the user, including CRTC, connector and framebuffer configuration.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getresources(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_card_res *card_res = data;
+ struct list_head *lh;
+ struct drm_framebuffer *fb;
+ struct drm_connector *connector;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ int ret = 0;
+ int connector_count = 0;
+ int crtc_count = 0;
+ int fb_count = 0;
+ int encoder_count = 0;
+ int copied = 0;
+ uint32_t __user *fb_id;
+ uint32_t __user *crtc_id;
+ uint32_t __user *connector_id;
+ uint32_t __user *encoder_id;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+
+ mutex_lock(&file_priv->fbs_lock);
+ /*
+ * For the non-control nodes we need to limit the list of resources
+ * by IDs in the group list for this node
+ */
+ list_for_each(lh, &file_priv->fbs)
+ fb_count++;
+
+ /* handle this in 4 parts */
+ /* FBs */
+ if (card_res->count_fbs >= fb_count) {
+ copied = 0;
+ fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
+ list_for_each_entry(fb, &file_priv->fbs, filp_head) {
+ if (put_user(fb->base.id, fb_id + copied)) {
+ mutex_unlock(&file_priv->fbs_lock);
+ return -EFAULT;
+ }
+ copied++;
+ }
+ }
+ card_res->count_fbs = fb_count;
+ mutex_unlock(&file_priv->fbs_lock);
+
+ /* mode_config.mutex protects the connector list against e.g. DP MST
+ * connector hot-adding. CRTC/Plane lists are invariant. */
+ mutex_lock(&dev->mode_config.mutex);
+ drm_for_each_crtc(crtc, dev)
+ crtc_count++;
+
+ drm_for_each_connector(connector, dev)
+ connector_count++;
+
+ drm_for_each_encoder(encoder, dev)
+ encoder_count++;
+
+ card_res->max_height = dev->mode_config.max_height;
+ card_res->min_height = dev->mode_config.min_height;
+ card_res->max_width = dev->mode_config.max_width;
+ card_res->min_width = dev->mode_config.min_width;
+
+ /* CRTCs */
+ if (card_res->count_crtcs >= crtc_count) {
+ copied = 0;
+ crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
+ drm_for_each_crtc(crtc, dev) {
+ if (put_user(crtc->base.id, crtc_id + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+ }
+ }
+ card_res->count_crtcs = crtc_count;
+
+ /* Encoders */
+ if (card_res->count_encoders >= encoder_count) {
+ copied = 0;
+ encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
+ drm_for_each_encoder(encoder, dev) {
+ if (put_user(encoder->base.id, encoder_id +
+ copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+ }
+ }
+ card_res->count_encoders = encoder_count;
+
+ /* Connectors */
+ if (card_res->count_connectors >= connector_count) {
+ copied = 0;
+ connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
+ drm_for_each_connector(connector, dev) {
+ if (put_user(connector->base.id,
+ connector_id + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+ }
+ }
+ card_res->count_connectors = connector_count;
+
+out:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+}
+
+/**
+ * drm_mode_config_reset - call ->reset callbacks
+ * @dev: drm device
+ *
+ * This functions calls all the crtc's, encoder's and connector's ->reset
+ * callback. Drivers can use this in e.g. their driver load or resume code to
+ * reset hardware and software state.
+ */
+void drm_mode_config_reset(struct drm_device *dev)
+{
+ struct drm_crtc *crtc;
+ struct drm_plane *plane;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
+ drm_for_each_plane(plane, dev)
+ if (plane->funcs->reset)
+ plane->funcs->reset(plane);
+
+ drm_for_each_crtc(crtc, dev)
+ if (crtc->funcs->reset)
+ crtc->funcs->reset(crtc);
+
+ drm_for_each_encoder(encoder, dev)
+ if (encoder->funcs->reset)
+ encoder->funcs->reset(encoder);
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_for_each_connector(connector, dev)
+ if (connector->funcs->reset)
+ connector->funcs->reset(connector);
+ mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_mode_config_reset);
+
+/*
+ * Global properties
+ */
+static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
+ { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
+ { DRM_PLANE_TYPE_PRIMARY, "Primary" },
+ { DRM_PLANE_TYPE_CURSOR, "Cursor" },
+};
+
+static int drm_mode_create_standard_properties(struct drm_device *dev)
+{
+ struct drm_property *prop;
+ int ret;
+
+ ret = drm_connector_create_standard_properties(dev);
+ if (ret)
+ return ret;
+
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
+ "type", drm_plane_type_enum_list,
+ ARRAY_SIZE(drm_plane_type_enum_list));
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.plane_type_property = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_X", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_x = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_Y", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_y = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_W", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_w = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_H", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_h = prop;
+
+ prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+ "CRTC_X", INT_MIN, INT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_crtc_x = prop;
+
+ prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+ "CRTC_Y", INT_MIN, INT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_crtc_y = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "CRTC_W", 0, INT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_crtc_w = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "CRTC_H", 0, INT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_crtc_h = prop;
+
+ prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+ "FB_ID", DRM_MODE_OBJECT_FB);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_fb_id = prop;
+
+ prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+ "IN_FENCE_FD", -1, INT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_in_fence_fd = prop;
+
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+ "OUT_FENCE_PTR", 0, U64_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_out_fence_ptr = prop;
+
+ prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+ "CRTC_ID", DRM_MODE_OBJECT_CRTC);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_crtc_id = prop;
+
+ prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+ "ACTIVE");
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_active = prop;
+
+ prop = drm_property_create(dev,
+ DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
+ "MODE_ID", 0);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_mode_id = prop;
+
+ prop = drm_property_create(dev,
+ DRM_MODE_PROP_BLOB,
+ "DEGAMMA_LUT", 0);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.degamma_lut_property = prop;
+
+ prop = drm_property_create_range(dev,
+ DRM_MODE_PROP_IMMUTABLE,
+ "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.degamma_lut_size_property = prop;
+
+ prop = drm_property_create(dev,
+ DRM_MODE_PROP_BLOB,
+ "CTM", 0);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.ctm_property = prop;
+
+ prop = drm_property_create(dev,
+ DRM_MODE_PROP_BLOB,
+ "GAMMA_LUT", 0);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.gamma_lut_property = prop;
+
+ prop = drm_property_create_range(dev,
+ DRM_MODE_PROP_IMMUTABLE,
+ "GAMMA_LUT_SIZE", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.gamma_lut_size_property = prop;
+
+ return 0;
+}
+
+/**
+ * drm_mode_config_init - initialize DRM mode_configuration structure
+ * @dev: DRM device
+ *
+ * Initialize @dev's mode_config structure, used for tracking the graphics
+ * configuration of @dev.
+ *
+ * Since this initializes the modeset locks, no locking is possible. Which is no
+ * problem, since this should happen single threaded at init time. It is the
+ * driver's problem to ensure this guarantee.
+ *
+ */
+void drm_mode_config_init(struct drm_device *dev)
+{
+ mutex_init(&dev->mode_config.mutex);
+ drm_modeset_lock_init(&dev->mode_config.connection_mutex);
+ mutex_init(&dev->mode_config.idr_mutex);
+ mutex_init(&dev->mode_config.fb_lock);
+ mutex_init(&dev->mode_config.blob_lock);
+ INIT_LIST_HEAD(&dev->mode_config.fb_list);
+ INIT_LIST_HEAD(&dev->mode_config.crtc_list);
+ INIT_LIST_HEAD(&dev->mode_config.connector_list);
+ INIT_LIST_HEAD(&dev->mode_config.encoder_list);
+ INIT_LIST_HEAD(&dev->mode_config.property_list);
+ INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
+ INIT_LIST_HEAD(&dev->mode_config.plane_list);
+ idr_init(&dev->mode_config.crtc_idr);
+ idr_init(&dev->mode_config.tile_idr);
+ ida_init(&dev->mode_config.connector_ida);
+
+ drm_modeset_lock_all(dev);
+ drm_mode_create_standard_properties(dev);
+ drm_modeset_unlock_all(dev);
+
+ /* Just to be sure */
+ dev->mode_config.num_fb = 0;
+ dev->mode_config.num_connector = 0;
+ dev->mode_config.num_crtc = 0;
+ dev->mode_config.num_encoder = 0;
+ dev->mode_config.num_overlay_plane = 0;
+ dev->mode_config.num_total_plane = 0;
+}
+EXPORT_SYMBOL(drm_mode_config_init);
+
+/**
+ * drm_mode_config_cleanup - free up DRM mode_config info
+ * @dev: DRM device
+ *
+ * Free up all the connectors and CRTCs associated with this DRM device, then
+ * free up the framebuffers and associated buffer objects.
+ *
+ * Note that since this /should/ happen single-threaded at driver/device
+ * teardown time, no locking is required. It's the driver's job to ensure that
+ * this guarantee actually holds true.
+ *
+ * FIXME: cleanup any dangling user buffer objects too
+ */
+void drm_mode_config_cleanup(struct drm_device *dev)
+{
+ struct drm_connector *connector, *ot;
+ struct drm_crtc *crtc, *ct;
+ struct drm_encoder *encoder, *enct;
+ struct drm_framebuffer *fb, *fbt;
+ struct drm_property *property, *pt;
+ struct drm_property_blob *blob, *bt;
+ struct drm_plane *plane, *plt;
+
+ list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
+ head) {
+ encoder->funcs->destroy(encoder);
+ }
+
+ list_for_each_entry_safe(connector, ot,
+ &dev->mode_config.connector_list, head) {
+ connector->funcs->destroy(connector);
+ }
+
+ list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
+ head) {
+ drm_property_destroy(dev, property);
+ }
+
+ list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+ head) {
+ plane->funcs->destroy(plane);
+ }
+
+ list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+ crtc->funcs->destroy(crtc);
+ }
+
+ list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
+ head_global) {
+ drm_property_unreference_blob(blob);
+ }
+
+ /*
+ * Single-threaded teardown context, so it's not required to grab the
+ * fb_lock to protect against concurrent fb_list access. Contrary, it
+ * would actually deadlock with the drm_framebuffer_cleanup function.
+ *
+ * Also, if there are any framebuffers left, that's a driver leak now,
+ * so politely WARN about this.
+ */
+ WARN_ON(!list_empty(&dev->mode_config.fb_list));
+ list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
+ drm_framebuffer_free(&fb->base.refcount);
+ }
+
+ ida_destroy(&dev->mode_config.connector_ida);
+ idr_destroy(&dev->mode_config.tile_idr);
+ idr_destroy(&dev->mode_config.crtc_idr);
+ drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
+}
+EXPORT_SYMBOL(drm_mode_config_cleanup);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 53f07ac7c174..ac6a35212501 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -49,13 +49,7 @@
*/
void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
{
- DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
- "0x%x 0x%x\n",
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start,
- mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start,
- mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+ DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
}
EXPORT_SYMBOL(drm_mode_debug_printmodeline);
@@ -165,6 +159,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
unsigned int vfieldrate, hperiod;
int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
int interlace;
+ u64 tmp;
/* allocate the drm_display_mode structure. If failure, we will
* return directly
@@ -322,8 +317,11 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
drm_mode->vsync_end = drm_mode->vsync_start + vsync;
}
/* 15/13. Find pixel clock frequency (kHz for xf86) */
- drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod;
- drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP;
+ tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
+ tmp *= HV_FACTOR * 1000;
+ do_div(tmp, hperiod);
+ tmp -= drm_mode->clock % CVT_CLOCK_STEP;
+ drm_mode->clock = tmp;
/* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */
if (interlaced) {
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index 1d45738f8f98..cc232ac6c950 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -38,7 +38,7 @@
* Some userspace presumes that the first connected connector is the main
* display, where it's supposed to display e.g. the login screen. For
* laptops, this should be the main panel. Use this function to sort all
- * (eDP/LVDS) panels to the front of the connector list, instead of
+ * (eDP/LVDS/DSI) panels to the front of the connector list, instead of
* painstakingly trying to initialize them in the right order.
*/
void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
@@ -51,7 +51,8 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
list_for_each_entry_safe(connector, tmp,
&dev->mode_config.connector_list, head) {
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
- connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+ connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+ connector->connector_type == DRM_MODE_CONNECTOR_DSI)
list_move_tail(&connector->head, &panel_list);
}
@@ -70,17 +71,31 @@ EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
+ const struct drm_format_info *info;
int i;
+ info = drm_format_info(mode_cmd->pixel_format);
+ if (!info || !info->depth) {
+ struct drm_format_name_buf format_name;
+
+ DRM_DEBUG_KMS("non-RGB pixel format %s\n",
+ drm_get_format_name(mode_cmd->pixel_format,
+ &format_name));
+
+ fb->depth = 0;
+ fb->bits_per_pixel = 0;
+ } else {
+ fb->depth = info->depth;
+ fb->bits_per_pixel = info->cpp[0] * 8;
+ }
+
fb->width = mode_cmd->width;
fb->height = mode_cmd->height;
for (i = 0; i < 4; i++) {
fb->pitches[i] = mode_cmd->pitches[i];
fb->offsets[i] = mode_cmd->offsets[i];
- fb->modifier[i] = mode_cmd->modifier[i];
}
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
- &fb->bits_per_pixel);
+ fb->modifier = mode_cmd->modifier[0];
fb->pixel_format = mode_cmd->pixel_format;
fb->flags = mode_cmd->flags;
}
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 61146f5b4f56..3551ae31f143 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -52,14 +52,16 @@
* drm_modeset_drop_locks(&ctx);
* drm_modeset_acquire_fini(&ctx);
*
- * On top of of these per-object locks using &ww_mutex there's also an overall
- * dev->mode_config.lock, for protecting everything else. Mostly this means
- * probe state of connectors, and preventing hotplug add/removal of connectors.
+ * On top of of these per-object locks using &ww_mutex there's also an overall
+ * dev->mode_config.lock, for protecting everything else. Mostly this means
+ * probe state of connectors, and preventing hotplug add/removal of connectors.
*
- * Finally there's a bunch of dedicated locks to protect drm core internal
- * lists and lookup data structures.
+ * Finally there's a bunch of dedicated locks to protect drm core internal
+ * lists and lookup data structures.
*/
+static DEFINE_WW_CLASS(crtc_ww_class);
+
/**
* drm_modeset_lock_all - take all modeset locks
* @dev: DRM device
@@ -398,6 +400,17 @@ int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx *ctx)
EXPORT_SYMBOL(drm_modeset_backoff_interruptible);
/**
+ * drm_modeset_lock_init - initialize lock
+ * @lock: lock to init
+ */
+void drm_modeset_lock_init(struct drm_modeset_lock *lock)
+{
+ ww_mutex_init(&lock->mutex, &crtc_ww_class);
+ INIT_LIST_HEAD(&lock->head);
+}
+EXPORT_SYMBOL(drm_modeset_lock_init);
+
+/**
* drm_modeset_lock - take modeset lock
* @lock: lock to take
* @ctx: acquire ctx
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index bc98bb94264d..47848ed8ca48 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -6,6 +6,11 @@
#include <drm/drm_crtc.h>
#include <drm/drm_of.h>
+static void drm_release_of(struct device *dev, void *data)
+{
+ of_node_put(data);
+}
+
/**
* drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
* @dev: DRM device
@@ -64,6 +69,24 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
/**
+ * drm_of_component_match_add - Add a component helper OF node match rule
+ * @master: master device
+ * @matchptr: component match pointer
+ * @compare: compare function used for matching component
+ * @node: of_node
+ */
+void drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node)
+{
+ of_node_get(node);
+ component_match_add_release(master, matchptr, drm_release_of,
+ compare, node);
+}
+EXPORT_SYMBOL_GPL(drm_of_component_match_add);
+
+/**
* 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
@@ -101,7 +124,7 @@ int drm_of_component_probe(struct device *dev,
continue;
}
- component_match_add(dev, &match, compare_of, port);
+ drm_of_component_match_add(dev, &match, compare_of, port);
of_node_put(port);
}
@@ -140,7 +163,8 @@ int drm_of_component_probe(struct device *dev,
continue;
}
- component_match_add(dev, &match, compare_of, remote);
+ drm_of_component_match_add(dev, &match, compare_of,
+ remote);
of_node_put(remote);
}
of_node_put(port);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 249c0ae52c6d..62b98f386fd1 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -79,7 +79,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
* Zero on success, error code on failure.
*/
int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
- unsigned long possible_crtcs,
+ uint32_t possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats, unsigned int format_count,
enum drm_plane_type type,
@@ -137,6 +137,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
+ drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
@@ -195,7 +196,7 @@ void drm_plane_unregister_all(struct drm_device *dev)
* Zero on success, error code on failure.
*/
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
- unsigned long possible_crtcs,
+ uint32_t possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats, unsigned int format_count,
bool is_primary)
@@ -220,7 +221,8 @@ void drm_plane_cleanup(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_fini(&plane->mutex);
+
kfree(plane->format_types);
drm_mode_object_unregister(dev, &plane->base);
@@ -235,7 +237,6 @@ void drm_plane_cleanup(struct drm_plane *plane)
dev->mode_config.num_total_plane--;
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
dev->mode_config.num_overlay_plane--;
- drm_modeset_unlock_all(dev);
WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
if (plane->state && plane->funcs->atomic_destroy_state)
@@ -479,9 +480,10 @@ static int __setplane_internal(struct drm_plane *plane,
/* Check whether this plane supports the fb pixel format. */
ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
if (ret) {
- char *format_name = drm_get_format_name(fb->pixel_format);
- DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
- kfree(format_name);
+ struct drm_format_name_buf format_name;
+ DRM_DEBUG_KMS("Invalid pixel format %s\n",
+ drm_get_format_name(fb->pixel_format,
+ &format_name));
goto out;
}
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 7899fc1dcdb0..7a7dddf604d7 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -130,15 +130,8 @@ int drm_plane_helper_check_state(struct drm_plane_state *state,
unsigned int rotation = state->rotation;
int hscale, vscale;
- src->x1 = state->src_x;
- src->y1 = state->src_y;
- src->x2 = state->src_x + state->src_w;
- src->y2 = state->src_y + state->src_h;
-
- dst->x1 = state->crtc_x;
- dst->y1 = state->crtc_y;
- dst->x2 = state->crtc_x + state->crtc_w;
- dst->y2 = state->crtc_y + state->crtc_h;
+ *src = drm_plane_state_src(state);
+ *dst = drm_plane_state_dest(state);
if (!fb) {
state->visible = false;
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index b22a94dd7b53..8d77b2462594 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -290,7 +290,8 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
*
* This wraps dma_buf_export() for use by generic GEM drivers that are using
* drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
- * a reference to the drm_device which is released by drm_gem_dmabuf_release().
+ * a reference to the &drm_device and the exported &drm_gem_object (stored in
+ * exp_info->priv) which is released by drm_gem_dmabuf_release().
*
* Returns the new dmabuf.
*/
@@ -300,8 +301,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
struct dma_buf *dma_buf;
dma_buf = dma_buf_export(exp_info);
- if (!IS_ERR(dma_buf))
- drm_dev_ref(dev);
+ if (IS_ERR(dma_buf))
+ return dma_buf;
+
+ drm_dev_ref(dev);
+ drm_gem_object_reference(exp_info->priv);
return dma_buf;
}
@@ -472,8 +476,6 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev,
*/
obj->dma_buf = dmabuf;
get_dma_buf(obj->dma_buf);
- /* Grab a new ref since the callers is now used by the dma-buf */
- drm_gem_object_reference(obj);
return dmabuf;
}
diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
new file mode 100644
index 000000000000..ad3caaa1f48b
--- /dev/null
+++ b/drivers/gpu/drm/drm_print.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * 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:
+ * Rob Clark <robdclark@gmail.com>
+ */
+
+#include <stdarg.h>
+#include <linux/seq_file.h>
+#include <drm/drmP.h>
+#include <drm/drm_print.h>
+
+void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
+{
+ seq_printf(p->arg, "%pV", vaf);
+}
+EXPORT_SYMBOL(__drm_printfn_seq_file);
+
+void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
+{
+ dev_printk(KERN_INFO, p->arg, "[" DRM_NAME "] %pV", vaf);
+}
+EXPORT_SYMBOL(__drm_printfn_info);
+
+/**
+ * drm_printf - print to a &drm_printer stream
+ * @p: the &drm_printer
+ * @f: format string
+ */
+void drm_printf(struct drm_printer *p, const char *f, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, f);
+ vaf.fmt = f;
+ vaf.va = &args;
+ p->printfn(p, &vaf);
+ va_end(args);
+}
+EXPORT_SYMBOL(drm_printf);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index f6b64d7d3528..ac953f037be7 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -152,6 +152,14 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
+static enum drm_connector_status
+drm_connector_detect(struct drm_connector *connector, bool force)
+{
+ return connector->funcs->detect ?
+ connector->funcs->detect(connector, force) :
+ connector_status_connected;
+}
+
/**
* drm_helper_probe_single_connector_modes - get complete set of display modes
* @connector: connector to probe
@@ -239,7 +247,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
if (connector->funcs->force)
connector->funcs->force(connector);
} else {
- connector->status = connector->funcs->detect(connector, true);
+ connector->status = drm_connector_detect(connector, true);
}
/*
@@ -384,7 +392,11 @@ static void output_poll_execute(struct work_struct *work)
if (!drm_kms_helper_poll)
goto out;
- mutex_lock(&dev->mode_config.mutex);
+ if (!mutex_trylock(&dev->mode_config.mutex)) {
+ repoll = true;
+ goto out;
+ }
+
drm_for_each_connector(connector, dev) {
/* Ignore forced connectors. */
@@ -405,7 +417,7 @@ static void output_poll_execute(struct work_struct *work)
repoll = true;
- connector->status = connector->funcs->detect(connector, false);
+ connector->status = drm_connector_detect(connector, false);
if (old_status != connector->status) {
const char *old, *new;
@@ -565,7 +577,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
old_status = connector->status;
- connector->status = connector->funcs->detect(connector, false);
+ connector->status = drm_connector_detect(connector, false);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.id,
connector->name,
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index a4d81cf4ffa0..24be69d29964 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -65,9 +65,9 @@ static bool drm_property_type_valid(struct drm_property *property)
* @num_values: number of pre-defined values
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Returns:
* A pointer to the newly created property on success, NULL on failure.
@@ -125,9 +125,9 @@ EXPORT_SYMBOL(drm_property_create);
* @num_values: number of pre-defined values
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Userspace is only allowed to set one of the predefined values for enumeration
* properties.
@@ -173,9 +173,9 @@ EXPORT_SYMBOL(drm_property_create_enum);
* @supported_bits: bitmask of all supported enumeration values
*
* This creates a new bitmask drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Compared to plain enumeration properties userspace is allowed to set any
* or'ed together combination of the predefined property bitflag values
@@ -245,9 +245,9 @@ static struct drm_property *property_create_range(struct drm_device *dev,
* @max: maximum value of the property
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Userspace is allowed to set any unsigned integer value in the (min, max)
* range inclusive.
@@ -273,9 +273,9 @@ EXPORT_SYMBOL(drm_property_create_range);
* @max: maximum value of the property
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Userspace is allowed to set any signed integer value in the (min, max)
* range inclusive.
@@ -300,9 +300,9 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
* @type: object type from DRM_MODE_OBJECT_* defines
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* Userspace is only allowed to set this to any property value of the given
* @type. Only useful for atomic properties, which is enforced.
@@ -338,9 +338,9 @@ EXPORT_SYMBOL(drm_property_create_object);
* @name: name of the property
*
* This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
*
* This is implemented as a ranged property with only {0, 1} as valid values.
*
@@ -729,7 +729,6 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
struct drm_mode_get_blob *out_resp = data;
struct drm_property_blob *blob;
int ret = 0;
- void __user *blob_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -739,8 +738,9 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
return -ENOENT;
if (out_resp->length == blob->length) {
- blob_ptr = (void __user *)(unsigned long)out_resp->data;
- if (copy_to_user(blob_ptr, blob->data, blob->length)) {
+ if (copy_to_user(u64_to_user_ptr(out_resp->data),
+ blob->data,
+ blob->length)) {
ret = -EFAULT;
goto unref;
}
@@ -757,7 +757,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
{
struct drm_mode_create_blob *out_resp = data;
struct drm_property_blob *blob;
- void __user *blob_ptr;
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -767,8 +766,9 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
if (IS_ERR(blob))
return PTR_ERR(blob);
- blob_ptr = (void __user *)(unsigned long)out_resp->data;
- if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
+ if (copy_from_user(blob->data,
+ u64_to_user_ptr(out_resp->data),
+ out_resp->length)) {
ret = -EFAULT;
goto out_blob;
}
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 73e53a8d1b37..e6057d8cdcd5 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -281,17 +281,10 @@ EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
*/
void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
{
- int w = drm_rect_width(r);
- int h = drm_rect_height(r);
-
if (fixed_point)
- DRM_DEBUG_KMS("%s%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", prefix,
- w >> 16, ((w & 0xffff) * 15625) >> 10,
- h >> 16, ((h & 0xffff) * 15625) >> 10,
- r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
- r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
+ DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
else
- DRM_DEBUG_KMS("%s%dx%d%+d%+d\n", prefix, w, h, r->x1, r->y1);
+ DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
}
EXPORT_SYMBOL(drm_rect_debug_print);
diff --git a/drivers/gpu/drm/etnaviv/cmdstream.xml.h b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
index 8c44ba9a694e..65f1ba1099bd 100644
--- a/drivers/gpu/drm/etnaviv/cmdstream.xml.h
+++ b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
@@ -8,10 +8,34 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- cmdstream.xml ( 12589 bytes, from 2014-02-17 14:57:56)
-- common.xml ( 18437 bytes, from 2015-03-25 11:27:41)
-
-Copyright (C) 2014
+- cmdstream.xml ( 14094 bytes, from 2016-11-11 06:55:14)
+- copyright.xml ( 1597 bytes, from 2016-10-29 07:29:22)
+- common.xml ( 23344 bytes, from 2016-11-10 15:14:07)
+
+Copyright (C) 2012-2016 by the following authors:
+- Wladimir J. van der Laan <laanwj@gmail.com>
+- Christian Gmeiner <christian.gmeiner@gmail.com>
+- Lucas Stach <l.stach@pengutronix.de>
+- Russell King <rmk@arm.linux.org.uk>
+
+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, sub license,
+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 NON-INFRINGEMENT. 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.
*/
@@ -26,6 +50,7 @@ Copyright (C) 2014
#define FE_OPCODE_STALL 0x00000009
#define FE_OPCODE_CALL 0x0000000a
#define FE_OPCODE_RETURN 0x0000000b
+#define FE_OPCODE_DRAW_INSTANCED 0x0000000c
#define FE_OPCODE_CHIP_SELECT 0x0000000d
#define PRIMITIVE_TYPE_POINTS 0x00000001
#define PRIMITIVE_TYPE_LINES 0x00000002
@@ -214,5 +239,32 @@ Copyright (C) 2014
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1 0x00000002
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0 0x00000001
+#define VIV_FE_DRAW_INSTANCED 0x00000000
+
+#define VIV_FE_DRAW_INSTANCED_HEADER 0x00000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP__SHIFT 27
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED 0x60000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_INDEXED 0x00100000
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK 0x000f0000
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT 16
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE(x) (((x) << VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK)
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK 0x0000ffff
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT 0
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(x) (((x) << VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK)
+
+#define VIV_FE_DRAW_INSTANCED_COUNT 0x00000004
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK 0xff000000
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT 24
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(x) (((x) << VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK)
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK 0x00ffffff
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT 0
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(x) (((x) << VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK)
+
+#define VIV_FE_DRAW_INSTANCED_START 0x00000008
+#define VIV_FE_DRAW_INSTANCED_START_INDEX__MASK 0xffffffff
+#define VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT 0
+#define VIV_FE_DRAW_INSTANCED_START_INDEX(x) (((x) << VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT) & VIV_FE_DRAW_INSTANCED_START_INDEX__MASK)
+
#endif /* CMDSTREAM_XML */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
index dcfd565c88d1..2a2e5e366ab7 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
@@ -143,6 +143,7 @@ static bool etnaviv_validate_load_state(struct etna_validation_state *state,
static uint8_t cmd_length[32] = {
[FE_OPCODE_DRAW_PRIMITIVES] = 4,
[FE_OPCODE_DRAW_INDEXED_PRIMITIVES] = 6,
+ [FE_OPCODE_DRAW_INSTANCED] = 4,
[FE_OPCODE_NOP] = 2,
[FE_OPCODE_STALL] = 2,
};
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index aa687669e22b..00368b14d08d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -16,6 +16,7 @@
#include <linux/component.h>
#include <linux/of_platform.h>
+#include <drm/drm_of.h>
#include "etnaviv_drv.h"
#include "etnaviv_gpu.h"
@@ -478,9 +479,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -505,6 +504,7 @@ static struct drm_driver etnaviv_drm_driver = {
.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
.gem_prime_vmap = etnaviv_gem_prime_vmap,
.gem_prime_vunmap = etnaviv_gem_prime_vunmap,
+ .gem_prime_mmap = etnaviv_gem_prime_mmap,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = etnaviv_debugfs_init,
.debugfs_cleanup = etnaviv_debugfs_cleanup,
@@ -629,8 +629,8 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
if (!core_node)
break;
- component_match_add(&pdev->dev, &match, compare_of,
- core_node);
+ drm_of_component_match_add(&pdev->dev, &match,
+ compare_of, core_node);
of_node_put(core_node);
}
} else if (dev->platform_data) {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index 65e057639653..c255eda40526 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -78,6 +78,8 @@ int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
int etnaviv_gem_prime_pin(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
index 2bef501d4a17..af65491a78e2 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -160,7 +160,8 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
file_size += sizeof(*iter.hdr) * n_obj;
/* Allocate the file in vmalloc memory, it's likely to be big */
- iter.start = vmalloc(file_size);
+ iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_HIGHMEM |
+ __GFP_NOWARN | __GFP_NORETRY, PAGE_KERNEL);
if (!iter.start) {
dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
return;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 0370b842d9cc..7d066a91d778 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -409,20 +409,16 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct drm_device *dev = obj->dev;
bool write = !!(op & ETNA_PREP_WRITE);
- int ret;
-
- if (op & ETNA_PREP_NOSYNC) {
- if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv,
- write))
- return -EBUSY;
- } else {
- unsigned long remain = etnaviv_timeout_to_jiffies(timeout);
+ unsigned long remain =
+ op & ETNA_PREP_NOSYNC ? 0 : etnaviv_timeout_to_jiffies(timeout);
+ long lret;
- ret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv,
- write, true, remain);
- if (ret <= 0)
- return ret == 0 ? -ETIMEDOUT : ret;
- }
+ lret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv,
+ write, true, remain);
+ if (lret < 0)
+ return lret;
+ else if (lret == 0)
+ return remain == 0 ? -EBUSY : -ETIMEDOUT;
if (etnaviv_obj->flags & ETNA_BO_CACHED) {
if (!etnaviv_obj->sgt) {
@@ -470,10 +466,10 @@ int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
}
#ifdef CONFIG_DEBUG_FS
-static void etnaviv_gem_describe_fence(struct fence *fence,
+static void etnaviv_gem_describe_fence(struct dma_fence *fence,
const char *type, struct seq_file *m)
{
- if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
seq_printf(m, "\t%9s: %s %s seq %u\n",
type,
fence->ops->get_driver_name(fence),
@@ -486,7 +482,7 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct reservation_object *robj = etnaviv_obj->resv;
struct reservation_object_list *fobj;
- struct fence *fence;
+ struct dma_fence *fence;
unsigned long off = drm_vma_node_start(&obj->vma_node);
seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index b93618c1aa69..62b47972a52e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -23,10 +23,12 @@
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+ int npages = obj->size >> PAGE_SHIFT;
- BUG_ON(!etnaviv_obj->sgt); /* should have already pinned! */
+ if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */
+ return NULL;
- return etnaviv_obj->sgt;
+ return drm_prime_pages_to_sg(etnaviv_obj->pages, npages);
}
void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj)
@@ -39,6 +41,19 @@ void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
/* TODO msm_gem_vunmap() */
}
+int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+ int ret;
+
+ ret = drm_gem_mmap_obj(obj, obj->size, vma);
+ if (ret < 0)
+ return ret;
+
+ return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
+}
+
int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
{
if (!obj->import_attach) {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index b1254f885fed..0a67124bb2a4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -15,7 +15,7 @@
*/
#include <linux/component.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/moduleparam.h>
#include <linux/of_device.h>
#include "etnaviv_dump.h"
@@ -639,6 +639,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
gpu->memory_base = PHYS_OFFSET;
else
gpu->memory_base = dma_mask - SZ_2G + 1;
+ } else if (PHYS_OFFSET >= SZ_2G) {
+ dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n");
+ gpu->memory_base = PHYS_OFFSET;
+ gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
}
ret = etnaviv_hw_reset(gpu);
@@ -882,7 +886,7 @@ static void recover_worker(struct work_struct *work)
for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
if (!gpu->event[i].used)
continue;
- fence_signal(gpu->event[i].fence);
+ dma_fence_signal(gpu->event[i].fence);
gpu->event[i].fence = NULL;
gpu->event[i].used = false;
complete(&gpu->event_free);
@@ -952,55 +956,55 @@ static void hangcheck_disable(struct etnaviv_gpu *gpu)
/* fence object management */
struct etnaviv_fence {
struct etnaviv_gpu *gpu;
- struct fence base;
+ struct dma_fence base;
};
-static inline struct etnaviv_fence *to_etnaviv_fence(struct fence *fence)
+static inline struct etnaviv_fence *to_etnaviv_fence(struct dma_fence *fence)
{
return container_of(fence, struct etnaviv_fence, base);
}
-static const char *etnaviv_fence_get_driver_name(struct fence *fence)
+static const char *etnaviv_fence_get_driver_name(struct dma_fence *fence)
{
return "etnaviv";
}
-static const char *etnaviv_fence_get_timeline_name(struct fence *fence)
+static const char *etnaviv_fence_get_timeline_name(struct dma_fence *fence)
{
struct etnaviv_fence *f = to_etnaviv_fence(fence);
return dev_name(f->gpu->dev);
}
-static bool etnaviv_fence_enable_signaling(struct fence *fence)
+static bool etnaviv_fence_enable_signaling(struct dma_fence *fence)
{
return true;
}
-static bool etnaviv_fence_signaled(struct fence *fence)
+static bool etnaviv_fence_signaled(struct dma_fence *fence)
{
struct etnaviv_fence *f = to_etnaviv_fence(fence);
return fence_completed(f->gpu, f->base.seqno);
}
-static void etnaviv_fence_release(struct fence *fence)
+static void etnaviv_fence_release(struct dma_fence *fence)
{
struct etnaviv_fence *f = to_etnaviv_fence(fence);
kfree_rcu(f, base.rcu);
}
-static const struct fence_ops etnaviv_fence_ops = {
+static const struct dma_fence_ops etnaviv_fence_ops = {
.get_driver_name = etnaviv_fence_get_driver_name,
.get_timeline_name = etnaviv_fence_get_timeline_name,
.enable_signaling = etnaviv_fence_enable_signaling,
.signaled = etnaviv_fence_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = etnaviv_fence_release,
};
-static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
+static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
{
struct etnaviv_fence *f;
@@ -1010,8 +1014,8 @@ static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
f->gpu = gpu;
- fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock,
- gpu->fence_context, ++gpu->next_fence);
+ dma_fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock,
+ gpu->fence_context, ++gpu->next_fence);
return &f->base;
}
@@ -1021,7 +1025,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
{
struct reservation_object *robj = etnaviv_obj->resv;
struct reservation_object_list *fobj;
- struct fence *fence;
+ struct dma_fence *fence;
int i, ret;
if (!exclusive) {
@@ -1039,7 +1043,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
/* Wait on any existing exclusive fence which isn't our own */
fence = reservation_object_get_excl(robj);
if (fence && fence->context != context) {
- ret = fence_wait(fence, true);
+ ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
@@ -1052,7 +1056,7 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
fence = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(robj));
if (fence->context != context) {
- ret = fence_wait(fence, true);
+ ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
@@ -1158,11 +1162,11 @@ static void retire_worker(struct work_struct *work)
mutex_lock(&gpu->lock);
list_for_each_entry_safe(cmdbuf, tmp, &gpu->active_cmd_list, node) {
- if (!fence_is_signaled(cmdbuf->fence))
+ if (!dma_fence_is_signaled(cmdbuf->fence))
break;
list_del(&cmdbuf->node);
- fence_put(cmdbuf->fence);
+ dma_fence_put(cmdbuf->fence);
for (i = 0; i < cmdbuf->nr_bos; i++) {
struct etnaviv_vram_mapping *mapping = cmdbuf->bo_map[i];
@@ -1275,7 +1279,7 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu)
int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)
{
- struct fence *fence;
+ struct dma_fence *fence;
unsigned int event, i;
int ret;
@@ -1391,7 +1395,7 @@ static irqreturn_t irq_handler(int irq, void *data)
}
while ((event = ffs(intr)) != 0) {
- struct fence *fence;
+ struct dma_fence *fence;
event -= 1;
@@ -1401,7 +1405,7 @@ static irqreturn_t irq_handler(int irq, void *data)
fence = gpu->event[event].fence;
gpu->event[event].fence = NULL;
- fence_signal(fence);
+ dma_fence_signal(fence);
/*
* Events can be processed out of order. Eg,
@@ -1553,7 +1557,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
return ret;
gpu->drm = drm;
- gpu->fence_context = fence_context_alloc(1);
+ gpu->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&gpu->fence_spinlock);
INIT_LIST_HEAD(&gpu->active_cmd_list);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 73c278dc3706..8c6b824e9d0a 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -89,7 +89,7 @@ struct etnaviv_chip_identity {
struct etnaviv_event {
bool used;
- struct fence *fence;
+ struct dma_fence *fence;
};
struct etnaviv_cmdbuf;
@@ -163,7 +163,7 @@ struct etnaviv_cmdbuf {
/* vram node used if the cmdbuf is mapped through the MMUv2 */
struct drm_mm_node vram_node;
/* fence after which this buffer is to be disposed */
- struct fence *fence;
+ struct dma_fence *fence;
/* target exec state */
u32 exec_state;
/* per GPU in-flight list */
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 465d344f3391..d706ca4e2f02 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -114,7 +114,7 @@ config DRM_EXYNOS_ROTATOR
config DRM_EXYNOS_GSC
bool "GScaler"
- depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !VIDEO_SAMSUNG_EXYNOS_GSC
+ depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && VIDEO_SAMSUNG_EXYNOS_GSC=n
help
Choose this option if you want to use Exynos GSC for DRM.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index f86e7c846678..739180ac3da5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -69,7 +69,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
drm_atomic_helper_cleanup_planes(dev, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
spin_lock(&priv->lock);
priv->pending &= ~commit->crtcs;
@@ -254,6 +254,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (nonblock)
schedule_work(&commit->work);
else
@@ -365,9 +366,7 @@ static const struct file_operations exynos_drm_driver_fops = {
.poll = drm_poll,
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.release = drm_release,
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 4cfb39d543b4..9f35deb56170 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -63,15 +63,11 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
static struct fb_ops exynos_drm_fb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_mmap = exynos_drm_fb_mmap,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
};
static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 147ef0d298cb..95871577015d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1433,7 +1433,7 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
&img_pos[EXYNOS_DRM_OPS_SRC],
&img_pos[EXYNOS_DRM_OPS_DST]);
if (ret) {
- dev_err(dev, "failed to set precalser.\n");
+ dev_err(dev, "failed to set prescaler.\n");
return ret;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index f2ae72ba7d5a..ea7a18230888 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -231,12 +231,12 @@ struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
int ret;
if (flags & ~(EXYNOS_BO_MASK)) {
- DRM_ERROR("invalid flags.\n");
+ DRM_ERROR("invalid GEM buffer flags: %u\n", flags);
return ERR_PTR(-EINVAL);
}
if (!size) {
- DRM_ERROR("invalid size.\n");
+ DRM_ERROR("invalid GEM buffer size: %lu\n", size);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 52a9d269484e..bef57987759d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1610,7 +1610,7 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
&img_pos[EXYNOS_DRM_OPS_SRC],
&img_pos[EXYNOS_DRM_OPS_DST]);
if (ret) {
- dev_err(dev, "failed to set precalser.\n");
+ dev_err(dev, "failed to set prescaler.\n");
return ret;
}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 38eaa63afb31..5ed8b1effe71 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -47,19 +47,6 @@
#define HOTPLUG_DEBOUNCE_MS 1100
-/* AVI header and aspect ratio */
-#define HDMI_AVI_VERSION 0x02
-#define HDMI_AVI_LENGTH 0x0d
-
-/* AUI header info */
-#define HDMI_AUI_VERSION 0x01
-#define HDMI_AUI_LENGTH 0x0a
-
-/* AVI active format aspect ratio */
-#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x08
-#define AVI_4_3_CENTER_RATIO 0x09
-#define AVI_16_9_CENTER_RATIO 0x0a
-
enum hdmi_type {
HDMI_TYPE13,
HDMI_TYPE14,
@@ -131,7 +118,6 @@ struct hdmi_context {
bool dvi_mode;
struct delayed_work hotplug_work;
struct drm_display_mode current_mode;
- u8 cea_video_id;
const struct hdmi_driver_data *drv_data;
void __iomem *regs;
@@ -681,6 +667,13 @@ static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
}
}
+static inline void hdmi_reg_write_buf(struct hdmi_context *hdata, u32 reg_id,
+ u8 *buf, int size)
+{
+ for (reg_id = hdmi_map_reg(hdata, reg_id); size; --size, reg_id += 4)
+ writel(*buf++, hdata->regs + reg_id);
+}
+
static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
u32 reg_id, u32 value, u32 mask)
{
@@ -762,93 +755,50 @@ static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
return ret;
}
-static u8 hdmi_chksum(struct hdmi_context *hdata,
- u32 start, u8 len, u32 hdr_sum)
-{
- int i;
-
- /* hdr_sum : header0 + header1 + header2
- * start : start address of packet byte1
- * len : packet bytes - 1 */
- for (i = 0; i < len; ++i)
- hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
-
- /* return 2's complement of 8 bit hdr_sum */
- return (u8)(~(hdr_sum & 0xff) + 1);
-}
-
-static void hdmi_reg_infoframe(struct hdmi_context *hdata,
- union hdmi_infoframe *infoframe)
+static void hdmi_reg_infoframes(struct hdmi_context *hdata)
{
- u32 hdr_sum;
- u8 chksum;
- u8 ar;
+ union hdmi_infoframe frm;
+ u8 buf[25];
+ int ret;
if (hdata->dvi_mode) {
- hdmi_reg_writeb(hdata, HDMI_VSI_CON,
- HDMI_VSI_CON_DO_NOT_TRANSMIT);
hdmi_reg_writeb(hdata, HDMI_AVI_CON,
HDMI_AVI_CON_DO_NOT_TRANSMIT);
+ hdmi_reg_writeb(hdata, HDMI_VSI_CON,
+ HDMI_VSI_CON_DO_NOT_TRANSMIT);
hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
return;
}
- switch (infoframe->any.type) {
- case HDMI_INFOFRAME_TYPE_AVI:
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
+ &hdata->current_mode);
+ if (!ret)
+ ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
+ if (ret > 0) {
hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
- hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
- hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
- infoframe->any.version);
- hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
- hdr_sum = infoframe->any.type + infoframe->any.version +
- infoframe->any.length;
-
- /* Output format zero hardcoded ,RGB YBCR selection */
- hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
- AVI_ACTIVE_FORMAT_VALID |
- AVI_UNDERSCANNED_DISPLAY_VALID);
-
- /*
- * Set the aspect ratio as per the mode, mentioned in
- * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
- */
- ar = hdata->current_mode.picture_aspect_ratio;
- switch (ar) {
- case HDMI_PICTURE_ASPECT_4_3:
- ar |= AVI_4_3_CENTER_RATIO;
- break;
- case HDMI_PICTURE_ASPECT_16_9:
- ar |= AVI_16_9_CENTER_RATIO;
- break;
- case HDMI_PICTURE_ASPECT_NONE:
- default:
- ar |= AVI_SAME_AS_PIC_ASPECT_RATIO;
- break;
- }
- hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar);
+ hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret);
+ } else {
+ DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
+ }
- hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id);
+ ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
+ &hdata->current_mode);
+ if (!ret)
+ ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
+ sizeof(buf));
+ if (ret > 0) {
+ hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC);
+ hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, ret);
+ }
- chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
- infoframe->any.length, hdr_sum);
- DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
- hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
- break;
- case HDMI_INFOFRAME_TYPE_AUDIO:
- hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
- hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
- hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
- infoframe->any.version);
- hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
- hdr_sum = infoframe->any.type + infoframe->any.version +
- infoframe->any.length;
- chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
- infoframe->any.length, hdr_sum);
- DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
- hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
- break;
- default:
- break;
+ ret = hdmi_audio_infoframe_init(&frm.audio);
+ if (!ret) {
+ frm.audio.channels = 2;
+ ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf));
+ }
+ if (ret > 0) {
+ hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
+ hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret);
}
}
@@ -1127,8 +1077,6 @@ static void hdmi_start(struct hdmi_context *hdata, bool start)
static void hdmi_conf_init(struct hdmi_context *hdata)
{
- union hdmi_infoframe infoframe;
-
/* disable HPD interrupts from HDMI IP block, use GPIO instead */
hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
@@ -1164,15 +1112,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
} else {
- infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
- infoframe.any.version = HDMI_AVI_VERSION;
- infoframe.any.length = HDMI_AVI_LENGTH;
- hdmi_reg_infoframe(hdata, &infoframe);
-
- infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
- infoframe.any.version = HDMI_AUI_VERSION;
- infoframe.any.length = HDMI_AUI_LENGTH;
- hdmi_reg_infoframe(hdata, &infoframe);
+ hdmi_reg_infoframes(hdata);
/* enable AVI packet every vsync, fixes purple line problem */
hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
@@ -1458,7 +1398,6 @@ static void hdmi_mode_set(struct drm_encoder *encoder,
"INTERLACED" : "PROGRESSIVE");
drm_mode_copy(&hdata->current_mode, m);
- hdata->cea_video_id = drm_match_cea_mode(mode);
}
static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h
index 169667a22bdc..a0507dc18d9e 100644
--- a/drivers/gpu/drm/exynos/regs-hdmi.h
+++ b/drivers/gpu/drm/exynos/regs-hdmi.h
@@ -361,9 +361,11 @@
/* AUI bit definition */
#define HDMI_AUI_CON_NO_TRAN (0 << 0)
+#define HDMI_AUI_CON_EVERY_VSYNC (1 << 1)
/* VSI bit definition */
#define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0)
+#define HDMI_VSI_CON_EVERY_VSYNC (1 << 1)
/* HDCP related registers */
#define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n))
diff --git a/drivers/gpu/drm/fsl-dcu/Makefile b/drivers/gpu/drm/fsl-dcu/Makefile
index b35a292287f3..aca34f656bea 100644
--- a/drivers/gpu/drm/fsl-dcu/Makefile
+++ b/drivers/gpu/drm/fsl-dcu/Makefile
@@ -3,6 +3,5 @@ fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
fsl_dcu_drm_rgb.o \
fsl_dcu_drm_plane.o \
fsl_dcu_drm_crtc.o \
- fsl_dcu_drm_fbdev.o \
fsl_tcon.o
obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu-drm.o
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 cc2fde2ae5ef..537ca159ffe5 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -32,6 +32,9 @@
#include "fsl_dcu_drm_drv.h"
#include "fsl_tcon.h"
+static int legacyfb_depth = 24;
+module_param(legacyfb_depth, int, 0444);
+
static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg)
{
if (reg == DCU_INT_STATUS || reg == DCU_UPDATE_MODE)
@@ -85,7 +88,18 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
goto done;
dev->irq_enabled = true;
- fsl_dcu_fbdev_init(dev);
+ if (legacyfb_depth != 16 && legacyfb_depth != 24 &&
+ legacyfb_depth != 32) {
+ dev_warn(dev->dev,
+ "Invalid legacyfb_depth. Defaulting to 24bpp\n");
+ legacyfb_depth = 24;
+ }
+ fsl_dev->fbdev = drm_fbdev_cma_init(dev, legacyfb_depth, 1, 1);
+ if (IS_ERR(fsl_dev->fbdev)) {
+ ret = PTR_ERR(fsl_dev->fbdev);
+ fsl_dev->fbdev = NULL;
+ goto done;
+ }
return 0;
done:
@@ -106,6 +120,7 @@ static int fsl_dcu_unload(struct drm_device *dev)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+ drm_crtc_force_disable_all(dev);
drm_kms_helper_poll_fini(dev);
if (fsl_dev->fbdev)
@@ -176,9 +191,7 @@ static const struct file_operations fsl_dcu_drm_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -334,11 +347,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
fsl_dev->soc = id->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "could not get memory IO resource\n");
- return -ENODEV;
- }
-
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
@@ -348,7 +356,7 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
fsl_dev->irq = platform_get_irq(pdev, 0);
if (fsl_dev->irq < 0) {
dev_err(dev, "failed to get irq\n");
- return -ENXIO;
+ return fsl_dev->irq;
}
fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
@@ -426,9 +434,9 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev)
{
struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
+ drm_put_dev(fsl_dev->drm);
clk_disable_unprepare(fsl_dev->clk);
clk_unregister(fsl_dev->pix_clk);
- drm_put_dev(fsl_dev->drm);
return 0;
}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
index 3b371fe7491e..e9e9aeecf2eb 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -197,7 +197,6 @@ struct fsl_dcu_drm_device {
struct drm_atomic_state *state;
};
-void fsl_dcu_fbdev_init(struct drm_device *dev);
int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
#endif /* __FSL_DCU_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c
deleted file mode 100644
index 8b8b819ea704..000000000000
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2015 Freescale Semiconductor, Inc.
- *
- * Freescale DCU drm device 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "fsl_dcu_drm_drv.h"
-
-/* initialize fbdev helper */
-void fsl_dcu_fbdev_init(struct drm_device *dev)
-{
- struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
-
- fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
-}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index e1dd75b18118..05a8ee106879 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -58,17 +58,10 @@ static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
-static enum drm_connector_status
-fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.destroy = fsl_dcu_drm_connector_destroy,
- .detect = fsl_dcu_drm_connector_detect,
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.reset = drm_atomic_helper_connector_reset,
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index ea733ab5b1e0..5efdb7fbb7ee 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -387,19 +387,6 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
}
/**
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status cdv_intel_lvds_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/**
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
@@ -521,7 +508,6 @@ static const struct drm_connector_helper_funcs
static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = cdv_intel_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = cdv_intel_lvds_set_property,
.destroy = cdv_intel_lvds_destroy,
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 3a44e705db53..4071b2d1e8cf 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -124,7 +124,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
psbfb->gtt->offset;
- page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ page_num = vma_pages(vma);
address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -185,9 +185,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
static struct fb_ops psbfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = psbfb_copyarea,
@@ -198,9 +196,7 @@ static struct fb_ops psbfb_ops = {
static struct fb_ops psbfb_roll_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
@@ -211,9 +207,7 @@ static struct fb_ops psbfb_roll_ops = {
static struct fb_ops psbfb_unaccel_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
@@ -236,22 +230,20 @@ static int psb_framebuffer_init(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
- u32 bpp, depth;
+ const struct drm_format_info *info;
int ret;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+ /*
+ * Reject unknown formats, YUV formats, and formats with more than
+ * 4 bytes per pixel.
+ */
+ info = drm_format_info(mode_cmd->pixel_format);
+ if (!info || !info->depth || info->cpp[0] > 4)
+ return -EINVAL;
if (mode_cmd->pitches[0] & 63)
return -EINVAL;
- switch (bpp) {
- case 8:
- case 16:
- case 24:
- case 32:
- break;
- default:
- return -EINVAL;
- }
+
drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
fb->gtt = gt;
ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
@@ -298,7 +290,6 @@ static struct drm_framebuffer *psb_framebuffer_create
* psbfb_alloc - allocate frame buffer memory
* @dev: the DRM device
* @aligned_size: space needed
- * @force: fall back to GEM buffers if need be
*
* Allocate the frame buffer. In the usual case we get a GTT range that
* is stolen memory backed and life is simple. If there isn't sufficient
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 8f69225ce2b4..3f4f424196b2 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -76,6 +76,7 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
* psb_gtt_insert - put an object into the GTT
* @dev: our DRM device
* @r: our GTT range
+ * @resume: on resume
*
* Take our preallocated GTT range and insert the GEM object into
* the GTT. This is protected via the gtt mutex which the caller
@@ -130,7 +131,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
* page table entries with the dummy page. This is protected via the gtt
* mutex which the caller must hold.
*/
-void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
{
struct drm_psb_private *dev_priv = dev->dev_private;
u32 __iomem *gtt_slot;
@@ -321,6 +322,7 @@ out:
* @len: length (bytes) of address space required
* @name: resource name
* @backed: resource should be backed by stolen pages
+ * @align: requested alignment
*
* Ask the kernel core to find us a suitable range of addresses
* to use for a GTT mapping.
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 50eb944fb78a..ff37ea585664 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -473,6 +473,7 @@ static const struct file_operations psb_gem_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = psb_unlocked_ioctl,
+ .compat_ioctl = drm_compat_ioctl,
.mmap = drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index b74372760d7f..05d7aaf47eea 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -753,10 +753,6 @@ extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
uint32_t handle, uint64_t *offset);
extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
-extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
/* psb_device.c */
extern const struct psb_ops psb_chip_ops;
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index fd7c91254841..483fdce74e39 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -500,19 +500,6 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
}
/*
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/*
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static int psb_intel_lvds_get_modes(struct drm_connector *connector)
@@ -643,7 +630,6 @@ const struct drm_connector_helper_funcs
const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = psb_intel_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = psb_intel_lvds_set_property,
.destroy = psb_intel_lvds_destroy,
diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
index 558c61b1b8e8..2fd2724b7a7d 100644
--- a/drivers/gpu/drm/hisilicon/Kconfig
+++ b/drivers/gpu/drm/hisilicon/Kconfig
@@ -2,4 +2,5 @@
# hisilicon drm device configuration.
# Please keep this list sorted alphabetically
+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
index e3f6d493c996..c8155bfb1ff1 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -2,4 +2,5 @@
# Makefile for hisilicon drm drivers.
# Please keep this list sorted alphabetically
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
new file mode 100644
index 000000000000..380622a0da35
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -0,0 +1,9 @@
+config DRM_HISI_HIBMC
+ tristate "DRM Support for Hisilicon Hibmc"
+ depends on DRM && PCI
+ select DRM_KMS_HELPER
+ select DRM_TTM
+
+ help
+ Choose this option if you have a Hisilicon Hibmc soc chipset.
+ If M is selected the module will be called hibmc-drm.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
new file mode 100644
index 000000000000..f2e04c035673
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -0,0 +1,4 @@
+ccflags-y := -Iinclude/drm
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_ttm.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
new file mode 100644
index 000000000000..2a1386e33126
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -0,0 +1,477 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+struct hibmc_display_panel_pll {
+ unsigned long M;
+ unsigned long N;
+ unsigned long OD;
+ unsigned long POD;
+};
+
+struct hibmc_dislay_pll_config {
+ unsigned long hdisplay;
+ unsigned long vdisplay;
+ u32 pll1_config_value;
+ u32 pll2_config_value;
+};
+
+static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
+ {800, 600, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
+ {1024, 768, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
+ {1152, 864, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
+ {1280, 768, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
+ {1280, 720, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
+ {1280, 960, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+ {1280, 1024, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+ {1600, 1200, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
+ {1920, 1080, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
+ {1920, 1200, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
+};
+
+#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_crtc *crtc = state->crtc;
+ struct drm_crtc_state *crtc_state;
+ u32 src_w = state->src_w >> 16;
+ u32 src_h = state->src_h >> 16;
+
+ if (!crtc || !fb)
+ return 0;
+
+ crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (src_w != state->crtc_w || src_h != state->crtc_h) {
+ DRM_DEBUG_ATOMIC("scale not support\n");
+ return -EINVAL;
+ }
+
+ if (state->crtc_x < 0 || state->crtc_y < 0) {
+ DRM_DEBUG_ATOMIC("crtc_x/y of drm_plane state is invalid\n");
+ return -EINVAL;
+ }
+
+ if (state->crtc_x + state->crtc_w >
+ crtc_state->adjusted_mode.hdisplay ||
+ state->crtc_y + state->crtc_h >
+ crtc_state->adjusted_mode.vdisplay) {
+ DRM_DEBUG_ATOMIC("visible portion of plane is invalid\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct drm_plane_state *state = plane->state;
+ u32 reg;
+ int ret;
+ u64 gpu_addr = 0;
+ unsigned int line_l;
+ struct hibmc_drm_private *priv = plane->dev->dev_private;
+ struct hibmc_framebuffer *hibmc_fb;
+ struct hibmc_bo *bo;
+
+ if (!state->fb)
+ return;
+
+ hibmc_fb = to_hibmc_framebuffer(state->fb);
+ bo = gem_to_hibmc_bo(hibmc_fb->obj);
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret) {
+ DRM_ERROR("failed to reserve ttm_bo: %d", ret);
+ return;
+ }
+
+ ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+ ttm_bo_unreserve(&bo->bo);
+ if (ret) {
+ DRM_ERROR("failed to pin hibmc_bo: %d", ret);
+ return;
+ }
+
+ writel(gpu_addr, priv->mmio + HIBMC_CRT_FB_ADDRESS);
+
+ reg = state->fb->width * (state->fb->bits_per_pixel / 8);
+ /* now line_pad is 16 */
+ reg = PADDING(16, reg);
+
+ line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+ line_l = PADDING(16, line_l);
+ writel(HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_WIDTH, reg) |
+ HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_OFFS, line_l),
+ priv->mmio + HIBMC_CRT_FB_WIDTH);
+
+ /* SET PIXEL FORMAT */
+ reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL);
+ reg &= ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+ reg |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_FORMAT,
+ state->fb->bits_per_pixel / 16);
+ writel(reg, priv->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static const u32 channel_formats1[] = {
+ DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888
+};
+
+static struct drm_plane_funcs hibmc_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
+ .atomic_check = hibmc_plane_atomic_check,
+ .atomic_update = hibmc_plane_atomic_update,
+};
+
+static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
+{
+ struct drm_device *dev = priv->dev;
+ struct drm_plane *plane;
+ int ret = 0;
+
+ plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
+ if (!plane) {
+ DRM_ERROR("failed to alloc memory when init plane\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ /*
+ * plane init
+ * TODO: Now only support primary plane, overlay planes
+ * need to do.
+ */
+ ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
+ channel_formats1,
+ ARRAY_SIZE(channel_formats1),
+ DRM_PLANE_TYPE_PRIMARY,
+ NULL);
+ if (ret) {
+ DRM_ERROR("failed to init plane: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
+ return plane;
+}
+
+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+ unsigned int reg;
+ struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+ hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+ reg |= HIBMC_CURR_GATE_DISPLAY(1);
+ hibmc_set_current_gate(priv, reg);
+ drm_crtc_vblank_on(crtc);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+ unsigned int reg;
+ struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+ drm_crtc_vblank_off(crtc);
+
+ hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg |= HIBMC_CURR_GATE_LOCALMEM(0);
+ reg |= HIBMC_CURR_GATE_DISPLAY(0);
+ hibmc_set_current_gate(priv, reg);
+}
+
+static unsigned int format_pll_reg(void)
+{
+ unsigned int pllreg = 0;
+ struct hibmc_display_panel_pll pll = {0};
+
+ /*
+ * Note that all PLL's have the same format. Here,
+ * we just use Panel PLL parameter to work out the bit
+ * fields in the register.On returning a 32 bit number, the value can
+ * be applied to any PLL in the calling function.
+ */
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_BYPASS, 0);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_POWER, 1);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_INPUT, 0);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_POD, pll.POD);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_OD, pll.OD);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_N, pll.N);
+ pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_M, pll.M);
+
+ return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+ u32 val;
+ struct hibmc_drm_private *priv = dev->dev_private;
+
+ val = readl(priv->mmio + CRT_PLL1_HS);
+ val &= ~(CRT_PLL1_HS_OUTER_BYPASS(1));
+ writel(val, priv->mmio + CRT_PLL1_HS);
+
+ val = CRT_PLL1_HS_INTER_BYPASS(1) | CRT_PLL1_HS_POWERON(1);
+ writel(val, priv->mmio + CRT_PLL1_HS);
+
+ writel(pll, priv->mmio + CRT_PLL1_HS);
+
+ usleep_range(1000, 2000);
+
+ val = pll & ~(CRT_PLL1_HS_POWERON(1));
+ writel(val, priv->mmio + CRT_PLL1_HS);
+
+ usleep_range(1000, 2000);
+
+ val &= ~(CRT_PLL1_HS_INTER_BYPASS(1));
+ writel(val, priv->mmio + CRT_PLL1_HS);
+
+ usleep_range(1000, 2000);
+
+ val |= CRT_PLL1_HS_OUTER_BYPASS(1);
+ writel(val, priv->mmio + CRT_PLL1_HS);
+}
+
+static void get_pll_config(unsigned long x, unsigned long y,
+ u32 *pll1, u32 *pll2)
+{
+ int i;
+ int count = ARRAY_SIZE(hibmc_pll_table);
+
+ for (i = 0; i < count; i++) {
+ if (hibmc_pll_table[i].hdisplay == x &&
+ hibmc_pll_table[i].vdisplay == y) {
+ *pll1 = hibmc_pll_table[i].pll1_config_value;
+ *pll2 = hibmc_pll_table[i].pll2_config_value;
+ return;
+ }
+ }
+
+ /* if found none, we use default value */
+ *pll1 = CRT_PLL1_HS_25MHZ;
+ *pll2 = CRT_PLL2_HS_25MHZ;
+}
+
+/*
+ * This function takes care the extra registers and bit fields required to
+ * setup a mode in board.
+ * Explanation about Display Control register:
+ * FPGA only supports 7 predefined pixel clocks, and clock select is
+ * in bit 4:0 of new register 0x802a8.
+ */
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+ struct drm_display_mode *mode,
+ unsigned int ctrl)
+{
+ unsigned long x, y;
+ u32 pll1; /* bit[31:0] of PLL */
+ u32 pll2; /* bit[63:32] of PLL */
+ struct hibmc_drm_private *priv = dev->dev_private;
+
+ x = mode->hdisplay;
+ y = mode->vdisplay;
+
+ get_pll_config(x, y, &pll1, &pll2);
+ writel(pll2, priv->mmio + CRT_PLL2_HS);
+ set_vclock_hisilicon(dev, pll1);
+
+ /*
+ * Hisilicon has to set up the top-left and bottom-right
+ * registers as well.
+ * Note that normal chip only use those two register for
+ * auto-centering mode.
+ */
+ writel(HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_TL_TOP, 0) |
+ HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_TL_LEFT, 0),
+ priv->mmio + HIBMC_CRT_AUTO_CENTERING_TL);
+
+ writel(HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM, y - 1) |
+ HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_BR_RIGHT, x - 1),
+ priv->mmio + HIBMC_CRT_AUTO_CENTERING_BR);
+
+ /*
+ * Assume common fields in ctrl have been properly set before
+ * calling this function.
+ * This function only sets the extra fields in ctrl.
+ */
+
+ /* Set bit 25 of display controller: Select CRT or VGA clock */
+ ctrl &= ~HIBMC_CRT_DISP_CTL_CRTSELECT_MASK;
+ ctrl &= ~HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK;
+
+ ctrl |= HIBMC_CRT_DISP_CTL_CRTSELECT(HIBMC_CRTSELECT_CRT);
+
+ /* clock_phase_polarity is 0 */
+ ctrl |= HIBMC_CRT_DISP_CTL_CLOCK_PHASE(0);
+
+ writel(ctrl, priv->mmio + HIBMC_CRT_DISP_CTL);
+
+ return ctrl;
+}
+
+static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ unsigned int val;
+ struct drm_display_mode *mode = &crtc->state->mode;
+ struct drm_device *dev = crtc->dev;
+ struct hibmc_drm_private *priv = dev->dev_private;
+ int width = mode->hsync_end - mode->hsync_start;
+ int height = mode->vsync_end - mode->vsync_start;
+
+ writel(format_pll_reg(), priv->mmio + HIBMC_CRT_PLL_CTRL);
+ writel(HIBMC_FIELD(HIBMC_CRT_HORZ_TOTAL_TOTAL, mode->htotal - 1) |
+ HIBMC_FIELD(HIBMC_CRT_HORZ_TOTAL_DISP_END, mode->hdisplay - 1),
+ priv->mmio + HIBMC_CRT_HORZ_TOTAL);
+
+ writel(HIBMC_FIELD(HIBMC_CRT_HORZ_SYNC_WIDTH, width) |
+ HIBMC_FIELD(HIBMC_CRT_HORZ_SYNC_START, mode->hsync_start - 1),
+ priv->mmio + HIBMC_CRT_HORZ_SYNC);
+
+ writel(HIBMC_FIELD(HIBMC_CRT_VERT_TOTAL_TOTAL, mode->vtotal - 1) |
+ HIBMC_FIELD(HIBMC_CRT_VERT_TOTAL_DISP_END, mode->vdisplay - 1),
+ priv->mmio + HIBMC_CRT_VERT_TOTAL);
+
+ writel(HIBMC_FIELD(HIBMC_CRT_VERT_SYNC_HEIGHT, height) |
+ HIBMC_FIELD(HIBMC_CRT_VERT_SYNC_START, mode->vsync_start - 1),
+ priv->mmio + HIBMC_CRT_VERT_SYNC);
+
+ val = HIBMC_FIELD(HIBMC_CRT_DISP_CTL_VSYNC_PHASE, 0);
+ val |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_HSYNC_PHASE, 0);
+ val |= HIBMC_CRT_DISP_CTL_TIMING(1);
+ val |= HIBMC_CRT_DISP_CTL_PLANE(1);
+
+ display_ctrl_adjust(dev, mode, val);
+}
+
+static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ unsigned int reg;
+ struct drm_device *dev = crtc->dev;
+ struct hibmc_drm_private *priv = dev->dev_private;
+
+ hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg |= HIBMC_CURR_GATE_DISPLAY(1);
+ reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+ hibmc_set_current_gate(priv, reg);
+
+ /* We can add more initialization as needed. */
+}
+
+static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (crtc->state->event)
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ crtc->state->event = NULL;
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+static const struct drm_crtc_funcs hibmc_crtc_funcs = {
+ .page_flip = drm_atomic_helper_page_flip,
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = drm_crtc_cleanup,
+ .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 hibmc_crtc_helper_funcs = {
+ .enable = hibmc_crtc_enable,
+ .disable = hibmc_crtc_disable,
+ .mode_set_nofb = hibmc_crtc_mode_set_nofb,
+ .atomic_begin = hibmc_crtc_atomic_begin,
+ .atomic_flush = hibmc_crtc_atomic_flush,
+};
+
+int hibmc_de_init(struct hibmc_drm_private *priv)
+{
+ struct drm_device *dev = priv->dev;
+ struct drm_crtc *crtc;
+ struct drm_plane *plane;
+ int ret;
+
+ plane = hibmc_plane_init(priv);
+ if (IS_ERR(plane)) {
+ DRM_ERROR("failed to create plane: %ld\n", PTR_ERR(plane));
+ return PTR_ERR(plane);
+ }
+
+ crtc = devm_kzalloc(dev->dev, sizeof(*crtc), GFP_KERNEL);
+ if (!crtc) {
+ DRM_ERROR("failed to alloc memory when init crtc\n");
+ return -ENOMEM;
+ }
+
+ ret = drm_crtc_init_with_planes(dev, crtc, plane,
+ NULL, &hibmc_crtc_funcs, NULL);
+ if (ret) {
+ DRM_ERROR("failed to init crtc: %d\n", ret);
+ return ret;
+ }
+
+ ret = drm_mode_crtc_set_gamma_size(crtc, 256);
+ if (ret) {
+ DRM_ERROR("failed to set gamma size: %d\n", ret);
+ return ret;
+ }
+ drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
new file mode 100644
index 000000000000..7e2043f4348c
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -0,0 +1,456 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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/console.h>
+#include <linux/module.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+static const struct file_operations hibmc_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .compat_ioctl = drm_compat_ioctl,
+ .mmap = hibmc_mmap,
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+ struct hibmc_drm_private *priv =
+ (struct hibmc_drm_private *)dev->dev_private;
+
+ writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1),
+ priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+
+ return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+ struct hibmc_drm_private *priv =
+ (struct hibmc_drm_private *)dev->dev_private;
+
+ writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0),
+ priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+}
+
+irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ struct hibmc_drm_private *priv =
+ (struct hibmc_drm_private *)dev->dev_private;
+ u32 status;
+
+ status = readl(priv->mmio + HIBMC_RAW_INTERRUPT);
+
+ if (status & HIBMC_RAW_INTERRUPT_VBLANK(1)) {
+ writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
+ priv->mmio + HIBMC_RAW_INTERRUPT);
+ drm_handle_vblank(dev, 0);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct drm_driver hibmc_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET |
+ DRIVER_ATOMIC | DRIVER_HAVE_IRQ,
+ .fops = &hibmc_fops,
+ .name = "hibmc",
+ .date = "20160828",
+ .desc = "hibmc drm driver",
+ .major = 1,
+ .minor = 0,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+ .enable_vblank = hibmc_enable_vblank,
+ .disable_vblank = hibmc_disable_vblank,
+ .gem_free_object_unlocked = hibmc_gem_free_object,
+ .dumb_create = hibmc_dumb_create,
+ .dumb_map_offset = hibmc_dumb_mmap_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .irq_handler = hibmc_drm_interrupt,
+};
+
+static int __maybe_unused hibmc_pm_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct hibmc_drm_private *priv = drm_dev->dev_private;
+
+ drm_kms_helper_poll_disable(drm_dev);
+ priv->suspend_state = drm_atomic_helper_suspend(drm_dev);
+ if (IS_ERR(priv->suspend_state)) {
+ DRM_ERROR("drm_atomic_helper_suspend failed: %ld\n",
+ PTR_ERR(priv->suspend_state));
+ drm_kms_helper_poll_enable(drm_dev);
+ return PTR_ERR(priv->suspend_state);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused hibmc_pm_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct hibmc_drm_private *priv = drm_dev->dev_private;
+
+ drm_atomic_helper_resume(drm_dev, priv->suspend_state);
+ drm_kms_helper_poll_enable(drm_dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops hibmc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
+ hibmc_pm_resume)
+};
+
+static int hibmc_kms_init(struct hibmc_drm_private *priv)
+{
+ int ret;
+
+ drm_mode_config_init(priv->dev);
+ priv->mode_config_initialized = true;
+
+ priv->dev->mode_config.min_width = 0;
+ priv->dev->mode_config.min_height = 0;
+ priv->dev->mode_config.max_width = 1920;
+ priv->dev->mode_config.max_height = 1440;
+
+ priv->dev->mode_config.fb_base = priv->fb_base;
+ priv->dev->mode_config.preferred_depth = 24;
+ priv->dev->mode_config.prefer_shadow = 0;
+
+ priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
+
+ ret = hibmc_de_init(priv);
+ if (ret) {
+ DRM_ERROR("failed to init de: %d\n", ret);
+ return ret;
+ }
+
+ ret = hibmc_vdac_init(priv);
+ if (ret) {
+ DRM_ERROR("failed to init vdac: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void hibmc_kms_fini(struct hibmc_drm_private *priv)
+{
+ if (priv->mode_config_initialized) {
+ drm_mode_config_cleanup(priv->dev);
+ priv->mode_config_initialized = false;
+ }
+}
+
+/*
+ * It can operate in one of three modes: 0, 1 or Sleep.
+ */
+void hibmc_set_power_mode(struct hibmc_drm_private *priv,
+ unsigned int power_mode)
+{
+ unsigned int control_value = 0;
+ void __iomem *mmio = priv->mmio;
+ unsigned int input = 1;
+
+ if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
+ return;
+
+ if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP)
+ input = 0;
+
+ control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
+ control_value &= ~(HIBMC_PW_MODE_CTL_MODE_MASK |
+ HIBMC_PW_MODE_CTL_OSC_INPUT_MASK);
+ control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_MODE, power_mode);
+ control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_OSC_INPUT, input);
+ writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
+}
+
+void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)
+{
+ unsigned int gate_reg;
+ unsigned int mode;
+ void __iomem *mmio = priv->mmio;
+
+ /* Get current power mode. */
+ mode = (readl(mmio + HIBMC_POWER_MODE_CTRL) &
+ HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
+
+ switch (mode) {
+ case HIBMC_PW_MODE_CTL_MODE_MODE0:
+ gate_reg = HIBMC_MODE0_GATE;
+ break;
+
+ case HIBMC_PW_MODE_CTL_MODE_MODE1:
+ gate_reg = HIBMC_MODE1_GATE;
+ break;
+
+ default:
+ gate_reg = HIBMC_MODE0_GATE;
+ break;
+ }
+ writel(gate, mmio + gate_reg);
+}
+
+static void hibmc_hw_config(struct hibmc_drm_private *priv)
+{
+ unsigned int reg;
+
+ /* On hardware reset, power mode 0 is default. */
+ hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg |= HIBMC_CURR_GATE_DISPLAY(1);
+ reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+
+ hibmc_set_current_gate(priv, reg);
+
+ /*
+ * Reset the memory controller. If the memory controller
+ * is not reset in chip,the system might hang when sw accesses
+ * the memory.The memory should be resetted after
+ * changing the MXCLK.
+ */
+ reg = readl(priv->mmio + HIBMC_MISC_CTRL);
+ reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+ reg |= HIBMC_MSCCTL_LOCALMEM_RESET(0);
+ writel(reg, priv->mmio + HIBMC_MISC_CTRL);
+
+ reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+ reg |= HIBMC_MSCCTL_LOCALMEM_RESET(1);
+
+ writel(reg, priv->mmio + HIBMC_MISC_CTRL);
+}
+
+static int hibmc_hw_map(struct hibmc_drm_private *priv)
+{
+ struct drm_device *dev = priv->dev;
+ struct pci_dev *pdev = dev->pdev;
+ resource_size_t addr, size, ioaddr, iosize;
+
+ ioaddr = pci_resource_start(pdev, 1);
+ iosize = pci_resource_len(pdev, 1);
+ priv->mmio = devm_ioremap_nocache(dev->dev, ioaddr, iosize);
+ if (!priv->mmio) {
+ DRM_ERROR("Cannot map mmio region\n");
+ return -ENOMEM;
+ }
+
+ addr = pci_resource_start(pdev, 0);
+ size = pci_resource_len(pdev, 0);
+ priv->fb_map = devm_ioremap(dev->dev, addr, size);
+ if (!priv->fb_map) {
+ DRM_ERROR("Cannot map framebuffer\n");
+ return -ENOMEM;
+ }
+ priv->fb_base = addr;
+ priv->fb_size = size;
+
+ return 0;
+}
+
+static int hibmc_hw_init(struct hibmc_drm_private *priv)
+{
+ int ret;
+
+ ret = hibmc_hw_map(priv);
+ if (ret)
+ return ret;
+
+ hibmc_hw_config(priv);
+
+ return 0;
+}
+
+static int hibmc_unload(struct drm_device *dev)
+{
+ struct hibmc_drm_private *priv = dev->dev_private;
+
+ hibmc_fbdev_fini(priv);
+
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
+ if (priv->msi_enabled)
+ pci_disable_msi(dev->pdev);
+ drm_vblank_cleanup(dev);
+
+ hibmc_kms_fini(priv);
+ hibmc_mm_fini(priv);
+ dev->dev_private = NULL;
+ return 0;
+}
+
+static int hibmc_load(struct drm_device *dev)
+{
+ struct hibmc_drm_private *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ DRM_ERROR("no memory to allocate for hibmc_drm_private\n");
+ return -ENOMEM;
+ }
+ dev->dev_private = priv;
+ priv->dev = dev;
+
+ ret = hibmc_hw_init(priv);
+ if (ret)
+ goto err;
+
+ ret = hibmc_mm_init(priv);
+ if (ret)
+ goto err;
+
+ ret = hibmc_kms_init(priv);
+ if (ret)
+ goto err;
+
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret) {
+ DRM_ERROR("failed to initialize vblank: %d\n", ret);
+ goto err;
+ }
+
+ priv->msi_enabled = 0;
+ ret = pci_enable_msi(dev->pdev);
+ if (ret) {
+ DRM_WARN("enabling MSI failed: %d\n", ret);
+ } else {
+ priv->msi_enabled = 1;
+ ret = drm_irq_install(dev, dev->pdev->irq);
+ if (ret)
+ DRM_WARN("install irq failed: %d\n", ret);
+ }
+
+ /* reset all the states of crtc/plane/encoder/connector */
+ drm_mode_config_reset(dev);
+
+ ret = hibmc_fbdev_init(priv);
+ if (ret) {
+ DRM_ERROR("failed to initialize fbdev: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ hibmc_unload(dev);
+ DRM_ERROR("failed to initialize drm driver: %d\n", ret);
+ return ret;
+}
+
+static int hibmc_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct drm_device *dev;
+ int ret;
+
+ dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
+ if (IS_ERR(dev)) {
+ DRM_ERROR("failed to allocate drm_device\n");
+ return PTR_ERR(dev);
+ }
+
+ dev->pdev = pdev;
+ pci_set_drvdata(pdev, dev);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ DRM_ERROR("failed to enable pci device: %d\n", ret);
+ goto err_free;
+ }
+
+ ret = hibmc_load(dev);
+ if (ret) {
+ DRM_ERROR("failed to load hibmc: %d\n", ret);
+ goto err_disable;
+ }
+
+ ret = drm_dev_register(dev, 0);
+ if (ret) {
+ DRM_ERROR("failed to register drv for userspace access: %d\n",
+ ret);
+ goto err_unload;
+ }
+ return 0;
+
+err_unload:
+ hibmc_unload(dev);
+err_disable:
+ pci_disable_device(pdev);
+err_free:
+ drm_dev_unref(dev);
+
+ return ret;
+}
+
+static void hibmc_pci_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_dev_unregister(dev);
+ hibmc_unload(dev);
+ drm_dev_unref(dev);
+}
+
+static struct pci_device_id hibmc_pci_table[] = {
+ {0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+static struct pci_driver hibmc_pci_driver = {
+ .name = "hibmc-drm",
+ .id_table = hibmc_pci_table,
+ .probe = hibmc_pci_probe,
+ .remove = hibmc_pci_remove,
+ .driver.pm = &hibmc_pm_ops,
+};
+
+static int __init hibmc_init(void)
+{
+ return pci_register_driver(&hibmc_pci_driver);
+}
+
+static void __exit hibmc_exit(void)
+{
+ return pci_unregister_driver(&hibmc_pci_driver);
+}
+
+module_init(hibmc_init);
+module_exit(hibmc_exit);
+
+MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
+MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
+MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
new file mode 100644
index 000000000000..e195521eb41e
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -0,0 +1,114 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DRV_H
+#define HIBMC_DRM_DRV_H
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/ttm/ttm_bo_driver.h>
+
+struct hibmc_framebuffer {
+ struct drm_framebuffer fb;
+ struct drm_gem_object *obj;
+};
+
+struct hibmc_fbdev {
+ struct drm_fb_helper helper;
+ struct hibmc_framebuffer *fb;
+ int size;
+};
+
+struct hibmc_drm_private {
+ /* hw */
+ void __iomem *mmio;
+ void __iomem *fb_map;
+ unsigned long fb_base;
+ unsigned long fb_size;
+ bool msi_enabled;
+
+ /* drm */
+ struct drm_device *dev;
+ bool mode_config_initialized;
+ struct drm_atomic_state *suspend_state;
+
+ /* ttm */
+ struct drm_global_reference mem_global_ref;
+ struct ttm_bo_global_ref bo_global_ref;
+ struct ttm_bo_device bdev;
+ bool initialized;
+
+ /* fbdev */
+ struct hibmc_fbdev *fbdev;
+ bool mm_inited;
+};
+
+#define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)
+
+struct hibmc_bo {
+ struct ttm_buffer_object bo;
+ struct ttm_placement placement;
+ struct ttm_bo_kmap_obj kmap;
+ struct drm_gem_object gem;
+ struct ttm_place placements[3];
+ int pin_count;
+};
+
+static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
+{
+ return container_of(bo, struct hibmc_bo, bo);
+}
+
+static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
+{
+ return container_of(gem, struct hibmc_bo, gem);
+}
+
+void hibmc_set_power_mode(struct hibmc_drm_private *priv,
+ unsigned int power_mode);
+void hibmc_set_current_gate(struct hibmc_drm_private *priv,
+ unsigned int gate);
+
+int hibmc_de_init(struct hibmc_drm_private *priv);
+int hibmc_vdac_init(struct hibmc_drm_private *priv);
+int hibmc_fbdev_init(struct hibmc_drm_private *priv);
+void hibmc_fbdev_fini(struct hibmc_drm_private *priv);
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+ struct drm_gem_object **obj);
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj);
+
+int hibmc_mm_init(struct hibmc_drm_private *hibmc);
+void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int hibmc_bo_unpin(struct hibmc_bo *bo);
+void hibmc_gem_free_object(struct drm_gem_object *obj);
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+ u32 handle, u64 *offset);
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern const struct drm_mode_config_funcs hibmc_mode_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
new file mode 100644
index 000000000000..9b0696735ba1
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
@@ -0,0 +1,267 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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 <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include "hibmc_drm_drv.h"
+
+static int hibmcfb_create_object(
+ struct hibmc_drm_private *priv,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object **gobj_p)
+{
+ struct drm_gem_object *gobj;
+ struct drm_device *dev = priv->dev;
+ u32 size;
+ int ret = 0;
+
+ size = mode_cmd->pitches[0] * mode_cmd->height;
+ ret = hibmc_gem_create(dev, size, true, &gobj);
+ if (ret)
+ return ret;
+
+ *gobj_p = gobj;
+ return ret;
+}
+
+static struct fb_ops hibmc_drm_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_fillrect = drm_fb_helper_sys_fillrect,
+ .fb_copyarea = drm_fb_helper_sys_copyarea,
+ .fb_imageblit = drm_fb_helper_sys_imageblit,
+ .fb_pan_display = drm_fb_helper_pan_display,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct hibmc_fbdev *hi_fbdev =
+ container_of(helper, struct hibmc_fbdev, helper);
+ struct hibmc_drm_private *priv = helper->dev->dev_private;
+ struct fb_info *info;
+ struct drm_mode_fb_cmd2 mode_cmd;
+ struct drm_gem_object *gobj = NULL;
+ int ret = 0;
+ int ret1;
+ size_t size;
+ unsigned int bytes_per_pixel;
+ struct hibmc_bo *bo = NULL;
+
+ DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+ sizes->surface_depth = 32;
+
+ bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel;
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+ sizes->surface_depth);
+
+ size = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height);
+
+ ret = hibmcfb_create_object(priv, &mode_cmd, &gobj);
+ if (ret) {
+ DRM_ERROR("failed to create fbcon backing object: %d\n", ret);
+ return -ENOMEM;
+ }
+
+ bo = gem_to_hibmc_bo(gobj);
+
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret) {
+ DRM_ERROR("failed to reserve ttm_bo: %d\n", ret);
+ goto out_unref_gem;
+ }
+
+ ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+ if (ret) {
+ DRM_ERROR("failed to pin fbcon: %d\n", ret);
+ goto out_unreserve_ttm_bo;
+ }
+
+ ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+ if (ret) {
+ DRM_ERROR("failed to kmap fbcon: %d\n", ret);
+ goto out_unpin_bo;
+ }
+ ttm_bo_unreserve(&bo->bo);
+
+ info = drm_fb_helper_alloc_fbi(helper);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
+ DRM_ERROR("failed to allocate fbi: %d\n", ret);
+ goto out_release_fbi;
+ }
+
+ info->par = hi_fbdev;
+
+ hi_fbdev->fb = hibmc_framebuffer_init(priv->dev, &mode_cmd, gobj);
+ if (IS_ERR(hi_fbdev->fb)) {
+ ret = PTR_ERR(info);
+ DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
+ goto out_release_fbi;
+ }
+
+ priv->fbdev->size = size;
+ hi_fbdev->helper.fb = &hi_fbdev->fb->fb;
+
+ strcpy(info->fix.id, "hibmcdrmfb");
+
+ info->flags = FBINFO_DEFAULT;
+ info->fbops = &hibmc_drm_fb_ops;
+
+ drm_fb_helper_fill_fix(info, hi_fbdev->fb->fb.pitches[0],
+ hi_fbdev->fb->fb.depth);
+ drm_fb_helper_fill_var(info, &priv->fbdev->helper, sizes->fb_width,
+ sizes->fb_height);
+
+ info->screen_base = bo->kmap.virtual;
+ info->screen_size = size;
+
+ info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base;
+ info->fix.smem_len = size;
+ return 0;
+
+out_release_fbi:
+ drm_fb_helper_release_fbi(helper);
+ ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret1) {
+ DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1);
+ goto out_unref_gem;
+ }
+ ttm_bo_kunmap(&bo->kmap);
+out_unpin_bo:
+ hibmc_bo_unpin(bo);
+out_unreserve_ttm_bo:
+ ttm_bo_unreserve(&bo->bo);
+out_unref_gem:
+ drm_gem_object_unreference_unlocked(gobj);
+
+ return ret;
+}
+
+static void hibmc_fbdev_destroy(struct hibmc_fbdev *fbdev)
+{
+ struct hibmc_framebuffer *gfb = fbdev->fb;
+ struct drm_fb_helper *fbh = &fbdev->helper;
+
+ drm_fb_helper_unregister_fbi(fbh);
+ drm_fb_helper_release_fbi(fbh);
+
+ drm_fb_helper_fini(fbh);
+
+ if (gfb)
+ drm_framebuffer_unreference(&gfb->fb);
+}
+
+static const struct drm_fb_helper_funcs hibmc_fbdev_helper_funcs = {
+ .fb_probe = hibmc_drm_fb_create,
+};
+
+int hibmc_fbdev_init(struct hibmc_drm_private *priv)
+{
+ int ret;
+ struct fb_var_screeninfo *var;
+ struct fb_fix_screeninfo *fix;
+ struct hibmc_fbdev *hifbdev;
+
+ hifbdev = devm_kzalloc(priv->dev->dev, sizeof(*hifbdev), GFP_KERNEL);
+ if (!hifbdev) {
+ DRM_ERROR("failed to allocate hibmc_fbdev\n");
+ return -ENOMEM;
+ }
+
+ priv->fbdev = hifbdev;
+ drm_fb_helper_prepare(priv->dev, &hifbdev->helper,
+ &hibmc_fbdev_helper_funcs);
+
+ /* Now just one crtc and one channel */
+ ret = drm_fb_helper_init(priv->dev,
+ &hifbdev->helper, 1, 1);
+ if (ret) {
+ DRM_ERROR("failed to initialize fb helper: %d\n", ret);
+ return ret;
+ }
+
+ ret = drm_fb_helper_single_add_all_connectors(&hifbdev->helper);
+ if (ret) {
+ DRM_ERROR("failed to add all connectors: %d\n", ret);
+ goto fini;
+ }
+
+ ret = drm_fb_helper_initial_config(&hifbdev->helper, 16);
+ if (ret) {
+ DRM_ERROR("failed to setup initial conn config: %d\n", ret);
+ goto fini;
+ }
+
+ var = &hifbdev->helper.fbdev->var;
+ fix = &hifbdev->helper.fbdev->fix;
+
+ DRM_DEBUG_DRIVER("Member of info->var is :\n"
+ "xres=%d\n"
+ "yres=%d\n"
+ "xres_virtual=%d\n"
+ "yres_virtual=%d\n"
+ "xoffset=%d\n"
+ "yoffset=%d\n"
+ "bits_per_pixel=%d\n"
+ "...\n", var->xres, var->yres, var->xres_virtual,
+ var->yres_virtual, var->xoffset, var->yoffset,
+ var->bits_per_pixel);
+ DRM_DEBUG_DRIVER("Member of info->fix is :\n"
+ "smem_start=%lx\n"
+ "smem_len=%d\n"
+ "type=%d\n"
+ "type_aux=%d\n"
+ "visual=%d\n"
+ "xpanstep=%d\n"
+ "ypanstep=%d\n"
+ "ywrapstep=%d\n"
+ "line_length=%d\n"
+ "accel=%d\n"
+ "capabilities=%d\n"
+ "...\n", fix->smem_start, fix->smem_len, fix->type,
+ fix->type_aux, fix->visual, fix->xpanstep,
+ fix->ypanstep, fix->ywrapstep, fix->line_length,
+ fix->accel, fix->capabilities);
+
+ return 0;
+
+fini:
+ drm_fb_helper_fini(&hifbdev->helper);
+ return ret;
+}
+
+void hibmc_fbdev_fini(struct hibmc_drm_private *priv)
+{
+ if (!priv->fbdev)
+ return;
+
+ hibmc_fbdev_destroy(priv->fbdev);
+ priv->fbdev = NULL;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
new file mode 100644
index 000000000000..f7035bf3ec1f
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
@@ -0,0 +1,196 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_HW_H
+#define HIBMC_DRM_HW_H
+
+/* register definition */
+#define HIBMC_MISC_CTRL 0x4
+
+#define HIBMC_MSCCTL_LOCALMEM_RESET(x) ((x) << 6)
+#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK 0x40
+
+#define HIBMC_CURRENT_GATE 0x000040
+#define HIBMC_CURR_GATE_DISPLAY(x) ((x) << 2)
+#define HIBMC_CURR_GATE_DISPLAY_MASK 0x4
+
+#define HIBMC_CURR_GATE_LOCALMEM(x) ((x) << 1)
+#define HIBMC_CURR_GATE_LOCALMEM_MASK 0x2
+
+#define HIBMC_MODE0_GATE 0x000044
+#define HIBMC_MODE1_GATE 0x000048
+#define HIBMC_POWER_MODE_CTRL 0x00004C
+
+#define HIBMC_PW_MODE_CTL_OSC_INPUT(x) ((x) << 3)
+#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK 0x8
+
+#define HIBMC_PW_MODE_CTL_MODE(x) ((x) << 0)
+#define HIBMC_PW_MODE_CTL_MODE_MASK 0x03
+#define HIBMC_PW_MODE_CTL_MODE_SHIFT 0
+
+#define HIBMC_PW_MODE_CTL_MODE_MODE0 0
+#define HIBMC_PW_MODE_CTL_MODE_MODE1 1
+#define HIBMC_PW_MODE_CTL_MODE_SLEEP 2
+
+#define HIBMC_PANEL_PLL_CTRL 0x00005C
+#define HIBMC_CRT_PLL_CTRL 0x000060
+
+#define HIBMC_PLL_CTRL_BYPASS(x) ((x) << 18)
+#define HIBMC_PLL_CTRL_BYPASS_MASK 0x40000
+
+#define HIBMC_PLL_CTRL_POWER(x) ((x) << 17)
+#define HIBMC_PLL_CTRL_POWER_MASK 0x20000
+
+#define HIBMC_PLL_CTRL_INPUT(x) ((x) << 16)
+#define HIBMC_PLL_CTRL_INPUT_MASK 0x10000
+
+#define HIBMC_PLL_CTRL_POD(x) ((x) << 14)
+#define HIBMC_PLL_CTRL_POD_MASK 0xC000
+
+#define HIBMC_PLL_CTRL_OD(x) ((x) << 12)
+#define HIBMC_PLL_CTRL_OD_MASK 0x3000
+
+#define HIBMC_PLL_CTRL_N(x) ((x) << 8)
+#define HIBMC_PLL_CTRL_N_MASK 0xF00
+
+#define HIBMC_PLL_CTRL_M(x) ((x) << 0)
+#define HIBMC_PLL_CTRL_M_MASK 0xFF
+
+#define HIBMC_CRT_DISP_CTL 0x80200
+
+#define HIBMC_CRT_DISP_CTL_CRTSELECT(x) ((x) << 25)
+#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK 0x2000000
+
+#define HIBMC_CRTSELECT_CRT 1
+
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x) ((x) << 14)
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK 0x4000
+
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x) ((x) << 13)
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK 0x2000
+
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x) ((x) << 12)
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK 0x1000
+
+#define HIBMC_CRT_DISP_CTL_TIMING(x) ((x) << 8)
+#define HIBMC_CRT_DISP_CTL_TIMING_MASK 0x100
+
+#define HIBMC_CRT_DISP_CTL_PLANE(x) ((x) << 2)
+#define HIBMC_CRT_DISP_CTL_PLANE_MASK 4
+
+#define HIBMC_CRT_DISP_CTL_FORMAT(x) ((x) << 0)
+#define HIBMC_CRT_DISP_CTL_FORMAT_MASK 0x03
+
+#define HIBMC_CRT_FB_ADDRESS 0x080204
+
+#define HIBMC_CRT_FB_WIDTH 0x080208
+#define HIBMC_CRT_FB_WIDTH_WIDTH(x) ((x) << 16)
+#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK 0x3FFF0000
+#define HIBMC_CRT_FB_WIDTH_OFFS(x) ((x) << 0)
+#define HIBMC_CRT_FB_WIDTH_OFFS_MASK 0x3FFF
+
+#define HIBMC_CRT_HORZ_TOTAL 0x08020C
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x) ((x) << 16)
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK 0xFFF0000
+
+#define HIBMC_CRT_HORZ_TOTAL_DISP_END(x) ((x) << 0)
+#define HIBMC_CRT_HORZ_TOTAL_DISP_END_MASK 0xFFF
+
+#define HIBMC_CRT_HORZ_SYNC 0x080210
+#define HIBMC_CRT_HORZ_SYNC_WIDTH(x) ((x) << 16)
+#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK 0xFF0000
+
+#define HIBMC_CRT_HORZ_SYNC_START(x) ((x) << 0)
+#define HIBMC_CRT_HORZ_SYNC_START_MASK 0xFFF
+
+#define HIBMC_CRT_VERT_TOTAL 0x080214
+#define HIBMC_CRT_VERT_TOTAL_TOTAL(x) ((x) << 16)
+#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK 0x7FFF0000
+
+#define HIBMC_CRT_VERT_TOTAL_DISP_END(x) ((x) << 0)
+#define HIBMC_CRT_VERT_TOTAL_DISP_END_MASK 0x7FF
+
+#define HIBMC_CRT_VERT_SYNC 0x080218
+#define HIBMC_CRT_VERT_SYNC_HEIGHT(x) ((x) << 16)
+#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK 0x3F0000
+
+#define HIBMC_CRT_VERT_SYNC_START(x) ((x) << 0)
+#define HIBMC_CRT_VERT_SYNC_START_MASK 0x7FF
+
+/* Auto Centering */
+#define HIBMC_CRT_AUTO_CENTERING_TL 0x080280
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x) ((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MASK 0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x) ((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MASK 0x7FF
+
+#define HIBMC_CRT_AUTO_CENTERING_BR 0x080284
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x) ((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK 0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x) ((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK 0x7FF
+
+/* register to control panel output */
+#define HIBMC_DISPLAY_CONTROL_HISILE 0x80288
+#define HIBMC_DISPLAY_CONTROL_FPVDDEN(x) ((x) << 0)
+#define HIBMC_DISPLAY_CONTROL_PANELDATE(x) ((x) << 1)
+#define HIBMC_DISPLAY_CONTROL_FPEN(x) ((x) << 2)
+#define HIBMC_DISPLAY_CONTROL_VBIASEN(x) ((x) << 3)
+
+#define HIBMC_RAW_INTERRUPT 0x80290
+#define HIBMC_RAW_INTERRUPT_VBLANK(x) ((x) << 2)
+#define HIBMC_RAW_INTERRUPT_VBLANK_MASK 0x4
+
+#define HIBMC_RAW_INTERRUPT_EN 0x80298
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK(x) ((x) << 2)
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK_MASK 0x4
+
+/* register and values for PLL control */
+#define CRT_PLL1_HS 0x802a8
+#define CRT_PLL1_HS_OUTER_BYPASS(x) ((x) << 30)
+#define CRT_PLL1_HS_INTER_BYPASS(x) ((x) << 29)
+#define CRT_PLL1_HS_POWERON(x) ((x) << 24)
+
+#define CRT_PLL1_HS_25MHZ 0x23d40f02
+#define CRT_PLL1_HS_40MHZ 0x23940801
+#define CRT_PLL1_HS_65MHZ 0x23940d01
+#define CRT_PLL1_HS_78MHZ 0x23540F82
+#define CRT_PLL1_HS_74MHZ 0x23941dc2
+#define CRT_PLL1_HS_80MHZ 0x23941001
+#define CRT_PLL1_HS_80MHZ_1152 0x23540fc2
+#define CRT_PLL1_HS_108MHZ 0x23b41b01
+#define CRT_PLL1_HS_162MHZ 0x23480681
+#define CRT_PLL1_HS_148MHZ 0x23541dc2
+#define CRT_PLL1_HS_193MHZ 0x234807c1
+
+#define CRT_PLL2_HS 0x802ac
+#define CRT_PLL2_HS_25MHZ 0x206B851E
+#define CRT_PLL2_HS_40MHZ 0x30000000
+#define CRT_PLL2_HS_65MHZ 0x40000000
+#define CRT_PLL2_HS_78MHZ 0x50E147AE
+#define CRT_PLL2_HS_74MHZ 0x602B6AE7
+#define CRT_PLL2_HS_80MHZ 0x70000000
+#define CRT_PLL2_HS_108MHZ 0x80000000
+#define CRT_PLL2_HS_162MHZ 0xA0000000
+#define CRT_PLL2_HS_148MHZ 0xB0CCCCCD
+#define CRT_PLL2_HS_193MHZ 0xC0872B02
+
+#define HIBMC_FIELD(field, value) (field(value) & field##_MASK)
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
new file mode 100644
index 000000000000..12a18557c5fd
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -0,0 +1,140 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+ return drm_add_modes_noedid(connector, 800, 600);
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+ return drm_encoder_find(connector->dev, connector->encoder_ids[0]);
+}
+
+static const struct drm_connector_helper_funcs
+ hibmc_connector_helper_funcs = {
+ .get_modes = hibmc_connector_get_modes,
+ .mode_valid = hibmc_connector_mode_valid,
+ .best_encoder = hibmc_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs hibmc_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .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 struct drm_connector *
+hibmc_connector_init(struct hibmc_drm_private *priv)
+{
+ struct drm_device *dev = priv->dev;
+ struct drm_connector *connector;
+ int ret;
+
+ connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL);
+ if (!connector) {
+ DRM_ERROR("failed to alloc memory when init connector\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ret = drm_connector_init(dev, connector,
+ &hibmc_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA);
+ if (ret) {
+ DRM_ERROR("failed to init connector: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+ drm_connector_helper_add(connector,
+ &hibmc_connector_helper_funcs);
+
+ return connector;
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ u32 reg;
+ struct drm_device *dev = encoder->dev;
+ struct hibmc_drm_private *priv = dev->dev_private;
+
+ reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+ reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
+ reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
+ reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
+ reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
+ writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+ .mode_set = hibmc_encoder_mode_set,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+int hibmc_vdac_init(struct hibmc_drm_private *priv)
+{
+ struct drm_device *dev = priv->dev;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ int ret;
+
+ connector = hibmc_connector_init(priv);
+ if (IS_ERR(connector)) {
+ DRM_ERROR("failed to create connector: %ld\n",
+ PTR_ERR(connector));
+ return PTR_ERR(connector);
+ }
+
+ encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
+ if (!encoder) {
+ DRM_ERROR("failed to alloc memory when init encoder\n");
+ return -ENOMEM;
+ }
+
+ encoder->possible_crtcs = 0x1;
+ ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs,
+ DRM_MODE_ENCODER_DAC, NULL);
+ if (ret) {
+ DRM_ERROR("failed to init encoder: %d\n", ret);
+ return ret;
+ }
+
+ drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
new file mode 100644
index 000000000000..e76abf61edae
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
@@ -0,0 +1,558 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic_helper.h>
+#include <ttm/ttm_page_alloc.h>
+
+#include "hibmc_drm_drv.h"
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+static inline struct hibmc_drm_private *
+hibmc_bdev(struct ttm_bo_device *bd)
+{
+ return container_of(bd, struct hibmc_drm_private, bdev);
+}
+
+static int
+hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+ return ttm_mem_global_init(ref->object);
+}
+
+static void
+hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+ ttm_mem_global_release(ref->object);
+}
+
+static int hibmc_ttm_global_init(struct hibmc_drm_private *hibmc)
+{
+ int ret;
+
+ hibmc->mem_global_ref.global_type = DRM_GLOBAL_TTM_MEM;
+ hibmc->mem_global_ref.size = sizeof(struct ttm_mem_global);
+ hibmc->mem_global_ref.init = &hibmc_ttm_mem_global_init;
+ hibmc->mem_global_ref.release = &hibmc_ttm_mem_global_release;
+ ret = drm_global_item_ref(&hibmc->mem_global_ref);
+ if (ret) {
+ DRM_ERROR("could not get ref on ttm global: %d\n", ret);
+ return ret;
+ }
+
+ hibmc->bo_global_ref.mem_glob =
+ hibmc->mem_global_ref.object;
+ hibmc->bo_global_ref.ref.global_type = DRM_GLOBAL_TTM_BO;
+ hibmc->bo_global_ref.ref.size = sizeof(struct ttm_bo_global);
+ hibmc->bo_global_ref.ref.init = &ttm_bo_global_init;
+ hibmc->bo_global_ref.ref.release = &ttm_bo_global_release;
+ ret = drm_global_item_ref(&hibmc->bo_global_ref.ref);
+ if (ret) {
+ DRM_ERROR("failed setting up TTM BO subsystem: %d\n", ret);
+ drm_global_item_unref(&hibmc->mem_global_ref);
+ return ret;
+ }
+ return 0;
+}
+
+static void
+hibmc_ttm_global_release(struct hibmc_drm_private *hibmc)
+{
+ drm_global_item_unref(&hibmc->bo_global_ref.ref);
+ drm_global_item_unref(&hibmc->mem_global_ref);
+ hibmc->mem_global_ref.release = NULL;
+}
+
+static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+ struct hibmc_bo *bo = container_of(tbo, struct hibmc_bo, bo);
+
+ drm_gem_object_release(&bo->gem);
+ kfree(bo);
+}
+
+static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
+{
+ return bo->destroy == &hibmc_bo_ttm_destroy;
+}
+
+static int
+hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
+ struct ttm_mem_type_manager *man)
+{
+ switch (type) {
+ case TTM_PL_SYSTEM:
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_MASK_CACHING;
+ man->default_caching = TTM_PL_FLAG_CACHED;
+ break;
+ case TTM_PL_VRAM:
+ man->func = &ttm_bo_manager_func;
+ man->flags = TTM_MEMTYPE_FLAG_FIXED |
+ TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_FLAG_UNCACHED |
+ TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_WC;
+ break;
+ default:
+ DRM_ERROR("unsupported memory type %u\n", type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
+{
+ u32 count = 0;
+ u32 i;
+
+ bo->placement.placement = bo->placements;
+ bo->placement.busy_placement = bo->placements;
+ if (domain & TTM_PL_FLAG_VRAM)
+ bo->placements[count++].flags = TTM_PL_FLAG_WC |
+ TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
+ if (domain & TTM_PL_FLAG_SYSTEM)
+ bo->placements[count++].flags = TTM_PL_MASK_CACHING |
+ TTM_PL_FLAG_SYSTEM;
+ if (!count)
+ bo->placements[count++].flags = TTM_PL_MASK_CACHING |
+ TTM_PL_FLAG_SYSTEM;
+
+ bo->placement.num_placement = count;
+ bo->placement.num_busy_placement = count;
+ for (i = 0; i < count; i++) {
+ bo->placements[i].fpfn = 0;
+ bo->placements[i].lpfn = 0;
+ }
+}
+
+static void
+hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+ struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+ if (!hibmc_ttm_bo_is_hibmc_bo(bo))
+ return;
+
+ hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
+ *pl = hibmcbo->placement;
+}
+
+static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
+ struct file *filp)
+{
+ struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+ return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
+ filp->private_data);
+}
+
+static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+ struct ttm_mem_reg *mem)
+{
+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+ struct hibmc_drm_private *hibmc = hibmc_bdev(bdev);
+
+ mem->bus.addr = NULL;
+ mem->bus.offset = 0;
+ mem->bus.size = mem->num_pages << PAGE_SHIFT;
+ mem->bus.base = 0;
+ mem->bus.is_iomem = false;
+ if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+ return -EINVAL;
+ switch (mem->mem_type) {
+ case TTM_PL_SYSTEM:
+ /* system memory */
+ return 0;
+ case TTM_PL_VRAM:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
+ mem->bus.is_iomem = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
+{
+ ttm_tt_fini(tt);
+ kfree(tt);
+}
+
+static struct ttm_backend_func hibmc_tt_backend_func = {
+ .destroy = &hibmc_ttm_backend_destroy,
+};
+
+static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
+ unsigned long size,
+ u32 page_flags,
+ struct page *dummy_read_page)
+{
+ struct ttm_tt *tt;
+ int ret;
+
+ tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+ if (!tt) {
+ DRM_ERROR("failed to allocate ttm_tt\n");
+ return NULL;
+ }
+ tt->func = &hibmc_tt_backend_func;
+ ret = ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page);
+ if (ret) {
+ DRM_ERROR("failed to initialize ttm_tt: %d\n", ret);
+ kfree(tt);
+ return NULL;
+ }
+ return tt;
+}
+
+static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
+{
+ return ttm_pool_populate(ttm);
+}
+
+static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+ ttm_pool_unpopulate(ttm);
+}
+
+struct ttm_bo_driver hibmc_bo_driver = {
+ .ttm_tt_create = hibmc_ttm_tt_create,
+ .ttm_tt_populate = hibmc_ttm_tt_populate,
+ .ttm_tt_unpopulate = hibmc_ttm_tt_unpopulate,
+ .init_mem_type = hibmc_bo_init_mem_type,
+ .evict_flags = hibmc_bo_evict_flags,
+ .move = NULL,
+ .verify_access = hibmc_bo_verify_access,
+ .io_mem_reserve = &hibmc_ttm_io_mem_reserve,
+ .io_mem_free = NULL,
+ .lru_tail = &ttm_bo_default_lru_tail,
+ .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
+};
+
+int hibmc_mm_init(struct hibmc_drm_private *hibmc)
+{
+ int ret;
+ struct drm_device *dev = hibmc->dev;
+ struct ttm_bo_device *bdev = &hibmc->bdev;
+
+ ret = hibmc_ttm_global_init(hibmc);
+ if (ret)
+ return ret;
+
+ ret = ttm_bo_device_init(&hibmc->bdev,
+ hibmc->bo_global_ref.ref.object,
+ &hibmc_bo_driver,
+ dev->anon_inode->i_mapping,
+ DRM_FILE_PAGE_OFFSET,
+ true);
+ if (ret) {
+ hibmc_ttm_global_release(hibmc);
+ DRM_ERROR("error initializing bo driver: %d\n", ret);
+ return ret;
+ }
+
+ ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+ hibmc->fb_size >> PAGE_SHIFT);
+ if (ret) {
+ hibmc_ttm_global_release(hibmc);
+ DRM_ERROR("failed ttm VRAM init: %d\n", ret);
+ return ret;
+ }
+
+ hibmc->mm_inited = true;
+ return 0;
+}
+
+void hibmc_mm_fini(struct hibmc_drm_private *hibmc)
+{
+ if (!hibmc->mm_inited)
+ return;
+
+ ttm_bo_device_release(&hibmc->bdev);
+ hibmc_ttm_global_release(hibmc);
+ hibmc->mm_inited = false;
+}
+
+static void hibmc_bo_unref(struct hibmc_bo **bo)
+{
+ struct ttm_buffer_object *tbo;
+
+ if ((*bo) == NULL)
+ return;
+
+ tbo = &((*bo)->bo);
+ ttm_bo_unref(&tbo);
+ *bo = NULL;
+}
+
+int hibmc_bo_create(struct drm_device *dev, int size, int align,
+ u32 flags, struct hibmc_bo **phibmcbo)
+{
+ struct hibmc_drm_private *hibmc = dev->dev_private;
+ struct hibmc_bo *hibmcbo;
+ size_t acc_size;
+ int ret;
+
+ hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
+ if (!hibmcbo) {
+ DRM_ERROR("failed to allocate hibmcbo\n");
+ return -ENOMEM;
+ }
+ ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
+ if (ret) {
+ DRM_ERROR("failed to initialize drm gem object: %d\n", ret);
+ kfree(hibmcbo);
+ return ret;
+ }
+
+ hibmcbo->bo.bdev = &hibmc->bdev;
+
+ hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+ acc_size = ttm_bo_dma_acc_size(&hibmc->bdev, size,
+ sizeof(struct hibmc_bo));
+
+ ret = ttm_bo_init(&hibmc->bdev, &hibmcbo->bo, size,
+ ttm_bo_type_device, &hibmcbo->placement,
+ align >> PAGE_SHIFT, false, NULL, acc_size,
+ NULL, NULL, hibmc_bo_ttm_destroy);
+ if (ret) {
+ hibmc_bo_unref(&hibmcbo);
+ DRM_ERROR("failed to initialize ttm_bo: %d\n", ret);
+ return ret;
+ }
+
+ *phibmcbo = hibmcbo;
+ return 0;
+}
+
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+ int i, ret;
+
+ if (bo->pin_count) {
+ bo->pin_count++;
+ if (gpu_addr)
+ *gpu_addr = bo->bo.offset;
+ return 0;
+ }
+
+ hibmc_ttm_placement(bo, pl_flag);
+ for (i = 0; i < bo->placement.num_placement; i++)
+ bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+ ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+ if (ret)
+ return ret;
+
+ bo->pin_count = 1;
+ if (gpu_addr)
+ *gpu_addr = bo->bo.offset;
+ return 0;
+}
+
+int hibmc_bo_unpin(struct hibmc_bo *bo)
+{
+ int i, ret;
+
+ if (!bo->pin_count) {
+ DRM_ERROR("unpin bad %p\n", bo);
+ return 0;
+ }
+ bo->pin_count--;
+ if (bo->pin_count)
+ return 0;
+
+ for (i = 0; i < bo->placement.num_placement ; i++)
+ bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
+ ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+ if (ret) {
+ DRM_ERROR("validate failed for unpin: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *file_priv;
+ struct hibmc_drm_private *hibmc;
+
+ if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+ return -EINVAL;
+
+ file_priv = filp->private_data;
+ hibmc = file_priv->minor->dev->dev_private;
+ return ttm_bo_mmap(filp, vma, &hibmc->bdev);
+}
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+ struct drm_gem_object **obj)
+{
+ struct hibmc_bo *hibmcbo;
+ int ret;
+
+ *obj = NULL;
+
+ size = PAGE_ALIGN(size);
+ if (size == 0) {
+ DRM_ERROR("error: zero size\n");
+ return -EINVAL;
+ }
+
+ ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
+ if (ret) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("failed to allocate GEM object: %d\n", ret);
+ return ret;
+ }
+ *obj = &hibmcbo->gem;
+ return 0;
+}
+
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ struct drm_gem_object *gobj;
+ u32 handle;
+ int ret;
+
+ args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 16);
+ args->size = args->pitch * args->height;
+
+ ret = hibmc_gem_create(dev, args->size, false,
+ &gobj);
+ if (ret) {
+ DRM_ERROR("failed to create GEM object: %d\n", ret);
+ return ret;
+ }
+
+ ret = drm_gem_handle_create(file, gobj, &handle);
+ drm_gem_object_unreference_unlocked(gobj);
+ if (ret) {
+ DRM_ERROR("failed to unreference GEM object: %d\n", ret);
+ return ret;
+ }
+
+ args->handle = handle;
+ return 0;
+}
+
+void hibmc_gem_free_object(struct drm_gem_object *obj)
+{
+ struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
+
+ hibmc_bo_unref(&hibmcbo);
+}
+
+static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
+{
+ return drm_vma_node_offset_addr(&bo->bo.vma_node);
+}
+
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+ u32 handle, u64 *offset)
+{
+ struct drm_gem_object *obj;
+ struct hibmc_bo *bo;
+
+ obj = drm_gem_object_lookup(file, handle);
+ if (!obj)
+ return -ENOENT;
+
+ bo = gem_to_hibmc_bo(obj);
+ *offset = hibmc_bo_mmap_offset(bo);
+
+ drm_gem_object_unreference_unlocked(obj);
+ return 0;
+}
+
+static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+ struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb);
+
+ drm_gem_object_unreference_unlocked(hibmc_fb->obj);
+ drm_framebuffer_cleanup(fb);
+ kfree(hibmc_fb);
+}
+
+static const struct drm_framebuffer_funcs hibmc_fb_funcs = {
+ .destroy = hibmc_user_framebuffer_destroy,
+};
+
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
+{
+ struct hibmc_framebuffer *hibmc_fb;
+ int ret;
+
+ hibmc_fb = kzalloc(sizeof(*hibmc_fb), GFP_KERNEL);
+ if (!hibmc_fb) {
+ DRM_ERROR("failed to allocate hibmc_fb\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ drm_helper_mode_fill_fb_struct(&hibmc_fb->fb, mode_cmd);
+ hibmc_fb->obj = obj;
+ ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs);
+ if (ret) {
+ DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+ kfree(hibmc_fb);
+ return ERR_PTR(ret);
+ }
+
+ return hibmc_fb;
+}
+
+static struct drm_framebuffer *
+hibmc_user_framebuffer_create(struct drm_device *dev,
+ struct drm_file *filp,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ struct drm_gem_object *obj;
+ struct hibmc_framebuffer *hibmc_fb;
+
+ DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
+ mode_cmd->width, mode_cmd->height,
+ (mode_cmd->pixel_format) & 0xff,
+ (mode_cmd->pixel_format >> 8) & 0xff,
+ (mode_cmd->pixel_format >> 16) & 0xff,
+ (mode_cmd->pixel_format >> 24) & 0xff);
+
+ obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
+ if (!obj)
+ return ERR_PTR(-ENOENT);
+
+ hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj);
+ if (IS_ERR(hibmc_fb)) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ERR_PTR((long)hibmc_fb);
+ }
+ return &hibmc_fb->fb;
+}
+
+const struct drm_mode_config_funcs hibmc_mode_funcs = {
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+ .fb_create = hibmc_user_framebuffer_create,
+};
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index 7e7a4d43d6b6..afc2b5d2d5f0 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -608,17 +608,16 @@ static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
u32 ch, u32 y, u32 in_h, u32 fmt)
{
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
- char *format_name;
+ struct drm_format_name_buf format_name;
u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
u32 stride = fb->pitches[0];
u32 addr = (u32)obj->paddr + y * stride;
DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
ch + 1, y, in_h, stride, (u32)obj->paddr);
- format_name = drm_get_format_name(fb->pixel_format);
DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n",
- addr, fb->width, fb->height, fmt, format_name);
- kfree(format_name);
+ addr, fb->width, fb->height, fmt,
+ drm_get_format_name(fb->pixel_format, &format_name));
/* get reg offset */
reg_ctrl = RD_CH_CTRL(ch);
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 90377a609c98..ebd5f4fe4c23 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -24,6 +24,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include "kirin_drm_drv.h"
@@ -151,9 +152,7 @@ static const struct file_operations kirin_drm_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -260,14 +259,13 @@ static struct device_node *kirin_get_remote_node(struct device_node *np)
DRM_ERROR("no valid endpoint node\n");
return ERR_PTR(-ENODEV);
}
- of_node_put(endpoint);
remote = of_graph_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
if (!remote) {
DRM_ERROR("no valid remote node\n");
return ERR_PTR(-ENODEV);
}
- of_node_put(remote);
if (!of_device_is_available(remote)) {
DRM_ERROR("not available for remote node\n");
@@ -294,7 +292,8 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
if (IS_ERR(remote))
return PTR_ERR(remote);
- component_match_add(dev, &match, compare_of, remote);
+ drm_of_component_match_add(dev, &match, compare_of, remote);
+ of_node_put(remote);
return component_master_add_with_match(dev, &kirin_drm_ops, match);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 9798d400d817..86f47e190309 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -41,12 +41,15 @@ struct tda998x_priv {
struct i2c_client *hdmi;
struct mutex mutex;
u16 rev;
+ u8 cec_addr;
u8 current_page;
- int dpms;
- bool is_hdmi_sink;
+ bool is_on;
+ bool supports_infoframes;
+ bool sink_has_audio;
u8 vip_cntrl_0;
u8 vip_cntrl_1;
u8 vip_cntrl_2;
+ unsigned long tmds_clock;
struct tda998x_audio_params audio_params;
struct platform_device *audio_pdev;
@@ -105,6 +108,8 @@ struct tda998x_priv {
# define I2C_MASTER_DIS_FILT (1 << 1)
# define I2C_MASTER_APP_STRT_LAT (1 << 2)
#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */
+# define FEAT_POWERDOWN_PREFILT BIT(0)
+# define FEAT_POWERDOWN_CSC BIT(1)
# define FEAT_POWERDOWN_SPDIF (1 << 3)
#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
@@ -370,35 +375,46 @@ struct tda998x_priv {
static void
cec_write(struct tda998x_priv *priv, u16 addr, u8 val)
{
- struct i2c_client *client = priv->cec;
u8 buf[] = {addr, val};
+ struct i2c_msg msg = {
+ .addr = priv->cec_addr,
+ .len = 2,
+ .buf = buf,
+ };
int ret;
- ret = i2c_master_send(client, buf, sizeof(buf));
+ ret = i2c_transfer(priv->hdmi->adapter, &msg, 1);
if (ret < 0)
- dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
+ dev_err(&priv->hdmi->dev, "Error %d writing to cec:0x%x\n",
+ ret, addr);
}
static u8
cec_read(struct tda998x_priv *priv, u8 addr)
{
- struct i2c_client *client = priv->cec;
u8 val;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = priv->cec_addr,
+ .len = 1,
+ .buf = &addr,
+ }, {
+ .addr = priv->cec_addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val,
+ },
+ };
int ret;
- ret = i2c_master_send(client, &addr, sizeof(addr));
- if (ret < 0)
- goto fail;
-
- ret = i2c_master_recv(client, &val, sizeof(val));
- if (ret < 0)
- goto fail;
+ ret = i2c_transfer(priv->hdmi->adapter, msg, ARRAY_SIZE(msg));
+ if (ret < 0) {
+ dev_err(&priv->hdmi->dev, "Error %d reading from cec:0x%x\n",
+ ret, addr);
+ val = 0;
+ }
return val;
-
-fail:
- dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
- return 0;
}
static int
@@ -579,9 +595,9 @@ tda998x_reset(struct tda998x_priv *priv)
* 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
+ * However, tda998x_connector_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 need to delay probing modes in tda998x_connector_get_modes() after
* we have seen a HPD inactive->active transition. This code implements
* that delay.
*/
@@ -630,28 +646,30 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data)
bool handled = false;
sta = cec_read(priv, REG_CEC_INTSTATUS);
- cec = cec_read(priv, REG_CEC_RXSHPDINT);
- lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
- flag0 = reg_read(priv, REG_INT_FLAGS_0);
- flag1 = reg_read(priv, REG_INT_FLAGS_1);
- flag2 = reg_read(priv, REG_INT_FLAGS_2);
- 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 (sta & CEC_INTSTATUS_HDMI) {
+ cec = cec_read(priv, REG_CEC_RXSHPDINT);
+ lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
+ flag0 = reg_read(priv, REG_INT_FLAGS_0);
+ flag1 = reg_read(priv, REG_INT_FLAGS_1);
+ flag2 = reg_read(priv, REG_INT_FLAGS_2);
+ 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);
- handled = true;
+ if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
+ priv->wq_edid_wait = 0;
+ wake_up(&priv->wq_edid);
+ handled = true;
+ }
}
return IRQ_RETVAL(handled);
@@ -700,6 +718,8 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
}
+/* Audio support */
+
static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
{
if (on) {
@@ -713,8 +733,7 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
static int
tda998x_configure_audio(struct tda998x_priv *priv,
- struct tda998x_audio_params *params,
- unsigned mode_clock)
+ struct tda998x_audio_params *params)
{
u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
u32 n;
@@ -771,7 +790,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
* assume 100MHz requires larger divider.
*/
adiv = AUDIO_DIV_SERCLK_8;
- if (mode_clock > 100000)
+ if (priv->tmds_clock > 100000)
adiv++; /* AUDIO_DIV_SERCLK_16 */
/* S/PDIF asks for a larger divider */
@@ -819,58 +838,281 @@ tda998x_configure_audio(struct tda998x_priv *priv,
return tda998x_write_aif(priv, &params->cea);
}
-/* DRM encoder functions */
+static int tda998x_audio_hw_params(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *daifmt,
+ struct hdmi_codec_params *params)
+{
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
+ int i, ret;
+ struct tda998x_audio_params audio = {
+ .sample_width = params->sample_width,
+ .sample_rate = params->sample_rate,
+ .cea = params->cea,
+ };
+
+ memcpy(audio.status, params->iec.status,
+ min(sizeof(audio.status), sizeof(params->iec.status)));
-static void tda998x_encoder_set_config(struct tda998x_priv *priv,
- const struct tda998x_encoder_params *p)
+ switch (daifmt->fmt) {
+ case HDMI_I2S:
+ if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
+ daifmt->bit_clk_master || daifmt->frame_clk_master) {
+ dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
+ daifmt->bit_clk_inv, daifmt->frame_clk_inv,
+ daifmt->bit_clk_master,
+ daifmt->frame_clk_master);
+ return -EINVAL;
+ }
+ for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+ if (priv->audio_port[i].format == AFMT_I2S)
+ audio.config = priv->audio_port[i].config;
+ audio.format = AFMT_I2S;
+ break;
+ case HDMI_SPDIF:
+ for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+ if (priv->audio_port[i].format == AFMT_SPDIF)
+ audio.config = priv->audio_port[i].config;
+ audio.format = AFMT_SPDIF;
+ break;
+ default:
+ dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
+ return -EINVAL;
+ }
+
+ if (audio.config == 0) {
+ dev_err(dev, "%s: No audio configuration found\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&priv->audio_mutex);
+ if (priv->supports_infoframes && priv->sink_has_audio)
+ ret = tda998x_configure_audio(priv, &audio);
+ else
+ ret = 0;
+
+ if (ret == 0)
+ priv->audio_params = audio;
+ mutex_unlock(&priv->audio_mutex);
+
+ return ret;
+}
+
+static void tda998x_audio_shutdown(struct device *dev, void *data)
{
- priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
- (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
- VIP_CNTRL_0_SWAP_B(p->swap_b) |
- (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
- priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
- (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
- VIP_CNTRL_1_SWAP_D(p->swap_d) |
- (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
- priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
- (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
- VIP_CNTRL_2_SWAP_F(p->swap_f) |
- (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
- priv->audio_params = p->audio_params;
+ mutex_lock(&priv->audio_mutex);
+
+ reg_write(priv, REG_ENA_AP, 0);
+
+ priv->audio_params.format = AFMT_UNUSED;
+
+ mutex_unlock(&priv->audio_mutex);
}
-static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
{
- struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
- /* we only care about on or off: */
- if (mode != DRM_MODE_DPMS_ON)
- mode = DRM_MODE_DPMS_OFF;
+ mutex_lock(&priv->audio_mutex);
- if (mode == priv->dpms)
- return;
+ tda998x_audio_mute(priv, enable);
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- /* enable video ports, audio will be enabled later */
- reg_write(priv, REG_ENA_VP_0, 0xff);
- reg_write(priv, REG_ENA_VP_1, 0xff);
- reg_write(priv, REG_ENA_VP_2, 0xff);
- /* set muxing after enabling ports: */
- reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
- reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
- reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
- break;
- case DRM_MODE_DPMS_OFF:
- /* disable video ports */
- reg_write(priv, REG_ENA_VP_0, 0x00);
- reg_write(priv, REG_ENA_VP_1, 0x00);
- reg_write(priv, REG_ENA_VP_2, 0x00);
- break;
+ mutex_unlock(&priv->audio_mutex);
+ return 0;
+}
+
+static int tda998x_audio_get_eld(struct device *dev, void *data,
+ uint8_t *buf, size_t len)
+{
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+ mutex_lock(&priv->audio_mutex);
+ memcpy(buf, priv->connector.eld,
+ min(sizeof(priv->connector.eld), len));
+ mutex_unlock(&priv->audio_mutex);
+
+ return 0;
+}
+
+static const struct hdmi_codec_ops audio_codec_ops = {
+ .hw_params = tda998x_audio_hw_params,
+ .audio_shutdown = tda998x_audio_shutdown,
+ .digital_mute = tda998x_audio_digital_mute,
+ .get_eld = tda998x_audio_get_eld,
+};
+
+static int tda998x_audio_codec_init(struct tda998x_priv *priv,
+ struct device *dev)
+{
+ struct hdmi_codec_pdata codec_data = {
+ .ops = &audio_codec_ops,
+ .max_i2s_channels = 2,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
+ if (priv->audio_port[i].format == AFMT_I2S &&
+ priv->audio_port[i].config != 0)
+ codec_data.i2s = 1;
+ if (priv->audio_port[i].format == AFMT_SPDIF &&
+ priv->audio_port[i].config != 0)
+ codec_data.spdif = 1;
}
- priv->dpms = mode;
+ priv->audio_pdev = platform_device_register_data(
+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
+ &codec_data, sizeof(codec_data));
+
+ return PTR_ERR_OR_ZERO(priv->audio_pdev);
+}
+
+/* DRM connector functions */
+
+static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
+{
+ if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
+ return drm_atomic_helper_connector_dpms(connector, mode);
+ else
+ return drm_helper_connector_dpms(connector, mode);
+}
+
+static int tda998x_connector_fill_modes(struct drm_connector *connector,
+ uint32_t maxX, uint32_t maxY)
+{
+ struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+ int ret;
+
+ mutex_lock(&priv->audio_mutex);
+ ret = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+
+ if (connector->edid_blob_ptr) {
+ struct edid *edid = (void *)connector->edid_blob_ptr->data;
+
+ priv->sink_has_audio = drm_detect_monitor_audio(edid);
+ } else {
+ priv->sink_has_audio = false;
+ }
+ mutex_unlock(&priv->audio_mutex);
+
+ return ret;
+}
+
+static enum drm_connector_status
+tda998x_connector_detect(struct drm_connector *connector, bool force)
+{
+ 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;
+}
+
+static void tda998x_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs tda998x_connector_funcs = {
+ .dpms = tda998x_connector_dpms,
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = tda998x_connector_fill_modes,
+ .detect = tda998x_connector_detect,
+ .destroy = tda998x_connector_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
+{
+ struct tda998x_priv *priv = data;
+ u8 offset, segptr;
+ int ret, i;
+
+ offset = (blk & 1) ? 128 : 0;
+ segptr = blk / 2;
+
+ reg_write(priv, REG_DDC_ADDR, 0xa0);
+ reg_write(priv, REG_DDC_OFFS, offset);
+ reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
+ reg_write(priv, REG_DDC_SEGM, segptr);
+
+ /* enable reading EDID: */
+ priv->wq_edid_wait = 1;
+ reg_write(priv, REG_EDID_CTRL, 0x1);
+
+ /* flag must be cleared by sw: */
+ reg_write(priv, REG_EDID_CTRL, 0x0);
+
+ /* wait for block read to complete: */
+ if (priv->hdmi->irq) {
+ i = wait_event_timeout(priv->wq_edid,
+ !priv->wq_edid_wait,
+ msecs_to_jiffies(100));
+ if (i < 0) {
+ dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
+ return i;
+ }
+ } else {
+ for (i = 100; i > 0; i--) {
+ msleep(1);
+ ret = reg_read(priv, REG_INT_FLAGS_2);
+ if (ret < 0)
+ return ret;
+ if (ret & INT_FLAGS_2_EDID_BLK_RD)
+ break;
+ }
+ }
+
+ if (i == 0) {
+ dev_err(&priv->hdmi->dev, "read edid timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
+ if (ret != length) {
+ dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
+ blk, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+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);
+
+ edid = drm_do_get_edid(connector, read_edid_block, priv);
+
+ if (priv->rev == TDA19988)
+ reg_set(priv, REG_TX4, TX4_PD_RAM);
+
+ if (!edid) {
+ dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
+ return 0;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ n = drm_add_edid_modes(connector, edid);
+ drm_edid_to_eld(connector, edid);
+
+ kfree(edid);
+
+ return n;
}
static int tda998x_connector_mode_valid(struct drm_connector *connector,
@@ -888,6 +1130,80 @@ static int tda998x_connector_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
+static struct drm_encoder *
+tda998x_connector_best_encoder(struct drm_connector *connector)
+{
+ struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+
+ return &priv->encoder;
+}
+
+static
+const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
+ .get_modes = tda998x_connector_get_modes,
+ .mode_valid = tda998x_connector_mode_valid,
+ .best_encoder = tda998x_connector_best_encoder,
+};
+
+static int tda998x_connector_init(struct tda998x_priv *priv,
+ struct drm_device *drm)
+{
+ struct drm_connector *connector = &priv->connector;
+ int ret;
+
+ connector->interlace_allowed = 1;
+
+ if (priv->hdmi->irq)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ else
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
+ drm_connector_helper_add(connector, &tda998x_connector_helper_funcs);
+ ret = drm_connector_init(drm, connector, &tda998x_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ if (ret)
+ return ret;
+
+ drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
+
+ return 0;
+}
+
+/* DRM encoder functions */
+
+static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+ bool on;
+
+ /* we only care about on or off: */
+ on = mode == DRM_MODE_DPMS_ON;
+
+ if (on == priv->is_on)
+ return;
+
+ if (on) {
+ /* enable video ports, audio will be enabled later */
+ reg_write(priv, REG_ENA_VP_0, 0xff);
+ reg_write(priv, REG_ENA_VP_1, 0xff);
+ reg_write(priv, REG_ENA_VP_2, 0xff);
+ /* set muxing after enabling ports: */
+ reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
+ reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
+ reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
+
+ priv->is_on = true;
+ } else {
+ /* disable video ports */
+ reg_write(priv, REG_ENA_VP_0, 0x00);
+ reg_write(priv, REG_ENA_VP_1, 0x00);
+ reg_write(priv, REG_ENA_VP_2, 0x00);
+
+ priv->is_on = false;
+ }
+}
+
static void
tda998x_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
@@ -971,6 +1287,8 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
div = 3;
}
+ mutex_lock(&priv->audio_mutex);
+
/* mute the audio FIFO: */
reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
@@ -982,6 +1300,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
/* no pre-filter or interpolator: */
reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
HVF_CNTRL_0_INTPOL(0));
+ reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_PREFILT);
reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
VIP_CNTRL_4_BLC(0));
@@ -1004,6 +1323,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
/* set color matrix bypass flag: */
reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
MAT_CONTRL_MAT_SC(1));
+ reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
/* set BIAS tmds value: */
reg_write(priv, REG_ANA_GENERAL, 0x09);
@@ -1064,8 +1384,22 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
/* must be last register set: */
reg_write(priv, REG_TBG_CNTRL_0, 0);
- /* Only setup the info frames if the sink is HDMI */
- if (priv->is_hdmi_sink) {
+ priv->tmds_clock = adjusted_mode->clock;
+
+ /* CEA-861B section 6 says that:
+ * CEA version 1 (CEA-861) has no support for infoframes.
+ * CEA version 2 (CEA-861A) supports version 1 AVI infoframes,
+ * and optional basic audio.
+ * CEA version 3 (CEA-861B) supports version 1 and 2 AVI infoframes,
+ * and optional digital audio, with audio infoframes.
+ *
+ * Since we only support generation of version 2 AVI infoframes,
+ * ignore CEA version 2 and below (iow, behave as if we're a
+ * CEA-861 source.)
+ */
+ priv->supports_infoframes = priv->connector.display_info.cea_rev >= 3;
+
+ if (priv->supports_infoframes) {
/* We need to turn HDMI HDCP stuff on to get audio through */
reg &= ~TBG_CNTRL_1_DWIN_DIS;
reg_write(priv, REG_TBG_CNTRL_1, reg);
@@ -1074,127 +1408,12 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
tda998x_write_avi(priv, adjusted_mode);
- if (priv->audio_params.format != AFMT_UNUSED) {
- mutex_lock(&priv->audio_mutex);
- tda998x_configure_audio(priv,
- &priv->audio_params,
- adjusted_mode->clock);
- mutex_unlock(&priv->audio_mutex);
- }
- }
-}
-
-static enum drm_connector_status
-tda998x_connector_detect(struct drm_connector *connector, bool force)
-{
- 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;
-}
-
-static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
-{
- struct tda998x_priv *priv = data;
- u8 offset, segptr;
- int ret, i;
-
- offset = (blk & 1) ? 128 : 0;
- segptr = blk / 2;
-
- reg_write(priv, REG_DDC_ADDR, 0xa0);
- reg_write(priv, REG_DDC_OFFS, offset);
- reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
- reg_write(priv, REG_DDC_SEGM, segptr);
-
- /* enable reading EDID: */
- priv->wq_edid_wait = 1;
- reg_write(priv, REG_EDID_CTRL, 0x1);
-
- /* flag must be cleared by sw: */
- reg_write(priv, REG_EDID_CTRL, 0x0);
-
- /* wait for block read to complete: */
- if (priv->hdmi->irq) {
- i = wait_event_timeout(priv->wq_edid,
- !priv->wq_edid_wait,
- msecs_to_jiffies(100));
- if (i < 0) {
- dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
- return i;
- }
- } else {
- for (i = 100; i > 0; i--) {
- msleep(1);
- ret = reg_read(priv, REG_INT_FLAGS_2);
- if (ret < 0)
- return ret;
- if (ret & INT_FLAGS_2_EDID_BLK_RD)
- break;
- }
- }
-
- if (i == 0) {
- dev_err(&priv->hdmi->dev, "read edid timeout\n");
- return -ETIMEDOUT;
+ if (priv->audio_params.format != AFMT_UNUSED &&
+ priv->sink_has_audio)
+ tda998x_configure_audio(priv, &priv->audio_params);
}
- ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
- if (ret != length) {
- dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
- blk, ret);
- return ret;
- }
-
- return 0;
-}
-
-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);
-
- edid = drm_do_get_edid(connector, read_edid_block, priv);
-
- if (priv->rev == TDA19988)
- reg_set(priv, REG_TX4, TX4_PD_RAM);
-
- if (!edid) {
- dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
- return 0;
- }
-
- drm_mode_connector_update_edid_property(connector, edid);
- n = drm_add_edid_modes(connector, edid);
- priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
- drm_edid_to_eld(connector, edid);
-
- kfree(edid);
-
- return n;
-}
-
-static void tda998x_encoder_set_polling(struct tda998x_priv *priv,
- struct drm_connector *connector)
-{
- if (priv->hdmi->irq)
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- else
- connector->polled = DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
+ mutex_unlock(&priv->audio_mutex);
}
static void tda998x_destroy(struct tda998x_priv *priv)
@@ -1215,145 +1434,6 @@ static void tda998x_destroy(struct tda998x_priv *priv)
i2c_unregister_device(priv->cec);
}
-static int tda998x_audio_hw_params(struct device *dev, void *data,
- struct hdmi_codec_daifmt *daifmt,
- struct hdmi_codec_params *params)
-{
- struct tda998x_priv *priv = dev_get_drvdata(dev);
- int i, ret;
- struct tda998x_audio_params audio = {
- .sample_width = params->sample_width,
- .sample_rate = params->sample_rate,
- .cea = params->cea,
- };
-
- if (!priv->encoder.crtc)
- return -ENODEV;
-
- memcpy(audio.status, params->iec.status,
- min(sizeof(audio.status), sizeof(params->iec.status)));
-
- switch (daifmt->fmt) {
- case HDMI_I2S:
- if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
- daifmt->bit_clk_master || daifmt->frame_clk_master) {
- dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
- daifmt->bit_clk_inv, daifmt->frame_clk_inv,
- daifmt->bit_clk_master,
- daifmt->frame_clk_master);
- return -EINVAL;
- }
- for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
- if (priv->audio_port[i].format == AFMT_I2S)
- audio.config = priv->audio_port[i].config;
- audio.format = AFMT_I2S;
- break;
- case HDMI_SPDIF:
- for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
- if (priv->audio_port[i].format == AFMT_SPDIF)
- audio.config = priv->audio_port[i].config;
- audio.format = AFMT_SPDIF;
- break;
- default:
- dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
- return -EINVAL;
- }
-
- if (audio.config == 0) {
- dev_err(dev, "%s: No audio configutation found\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&priv->audio_mutex);
- ret = tda998x_configure_audio(priv,
- &audio,
- priv->encoder.crtc->hwmode.clock);
-
- if (ret == 0)
- priv->audio_params = audio;
- mutex_unlock(&priv->audio_mutex);
-
- return ret;
-}
-
-static void tda998x_audio_shutdown(struct device *dev, void *data)
-{
- struct tda998x_priv *priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->audio_mutex);
-
- reg_write(priv, REG_ENA_AP, 0);
-
- priv->audio_params.format = AFMT_UNUSED;
-
- mutex_unlock(&priv->audio_mutex);
-}
-
-int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
-{
- struct tda998x_priv *priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->audio_mutex);
-
- tda998x_audio_mute(priv, enable);
-
- mutex_unlock(&priv->audio_mutex);
- return 0;
-}
-
-static int tda998x_audio_get_eld(struct device *dev, void *data,
- uint8_t *buf, size_t len)
-{
- struct tda998x_priv *priv = dev_get_drvdata(dev);
- struct drm_mode_config *config = &priv->encoder.dev->mode_config;
- struct drm_connector *connector;
- int ret = -ENODEV;
-
- mutex_lock(&config->mutex);
- list_for_each_entry(connector, &config->connector_list, head) {
- if (&priv->encoder == connector->encoder) {
- memcpy(buf, connector->eld,
- min(sizeof(connector->eld), len));
- ret = 0;
- }
- }
- mutex_unlock(&config->mutex);
-
- return ret;
-}
-
-static const struct hdmi_codec_ops audio_codec_ops = {
- .hw_params = tda998x_audio_hw_params,
- .audio_shutdown = tda998x_audio_shutdown,
- .digital_mute = tda998x_audio_digital_mute,
- .get_eld = tda998x_audio_get_eld,
-};
-
-static int tda998x_audio_codec_init(struct tda998x_priv *priv,
- struct device *dev)
-{
- struct hdmi_codec_pdata codec_data = {
- .ops = &audio_codec_ops,
- .max_i2s_channels = 2,
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
- if (priv->audio_port[i].format == AFMT_I2S &&
- priv->audio_port[i].config != 0)
- codec_data.i2s = 1;
- if (priv->audio_port[i].format == AFMT_SPDIF &&
- priv->audio_port[i].config != 0)
- codec_data.spdif = 1;
- }
-
- priv->audio_pdev = platform_device_register_data(
- dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
- &codec_data, sizeof(codec_data));
-
- return PTR_ERR_OR_ZERO(priv->audio_pdev);
-}
-
/* I2C driver functions */
static int tda998x_get_audio_ports(struct tda998x_priv *priv,
@@ -1403,22 +1483,21 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
struct device_node *np = client->dev.of_node;
u32 video;
int rev_lo, rev_hi, ret;
- unsigned short cec_addr;
+
+ mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
+ /* CEC I2C address bound to TDA998x I2C addr by configuration pins */
+ priv->cec_addr = 0x34 + (client->addr & 0x03);
priv->current_page = 0xff;
priv->hdmi = client;
- /* CEC I2C address bound to TDA998x I2C addr by configuration pins */
- cec_addr = 0x34 + (client->addr & 0x03);
- priv->cec = i2c_new_dummy(client->adapter, cec_addr);
+ priv->cec = i2c_new_dummy(client->adapter, priv->cec_addr);
if (!priv->cec)
return -ENODEV;
- 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,
@@ -1478,7 +1557,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
/* initialize the optional IRQ */
if (client->irq) {
- int irqf_trigger;
+ unsigned long irq_flags;
/* init read EDID waitqueue and HDP work */
init_waitqueue_head(&priv->wq_edid);
@@ -1488,11 +1567,11 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
reg_read(priv, REG_INT_FLAGS_1);
reg_read(priv, REG_INT_FLAGS_2);
- irqf_trigger =
+ irq_flags =
irqd_get_trigger_type(irq_get_irq_data(client->irq));
+ irq_flags |= IRQF_SHARED | IRQF_ONESHOT;
ret = request_threaded_irq(client->irq, NULL,
- tda998x_irq_thread,
- irqf_trigger | IRQF_ONESHOT,
+ tda998x_irq_thread, irq_flags,
"tda998x", priv);
if (ret) {
dev_err(&client->dev,
@@ -1519,8 +1598,6 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
priv->vip_cntrl_2 = video;
}
- mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
-
ret = tda998x_get_audio_ports(priv, np);
if (ret)
goto fail;
@@ -1567,45 +1644,25 @@ static const struct drm_encoder_funcs tda998x_encoder_funcs = {
.destroy = tda998x_encoder_destroy,
};
-static struct drm_encoder *
-tda998x_connector_best_encoder(struct drm_connector *connector)
-{
- struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
-
- return &priv->encoder;
-}
-
-static
-const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
- .get_modes = tda998x_connector_get_modes,
- .mode_valid = tda998x_connector_mode_valid,
- .best_encoder = tda998x_connector_best_encoder,
-};
-
-static void tda998x_connector_destroy(struct drm_connector *connector)
+static void tda998x_set_config(struct tda998x_priv *priv,
+ const struct tda998x_encoder_params *p)
{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
+ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
+ (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
+ VIP_CNTRL_0_SWAP_B(p->swap_b) |
+ (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
+ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
+ (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
+ VIP_CNTRL_1_SWAP_D(p->swap_d) |
+ (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
+ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
+ (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
+ VIP_CNTRL_2_SWAP_F(p->swap_f) |
+ (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
-static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
-{
- if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
- return drm_atomic_helper_connector_dpms(connector, mode);
- else
- return drm_helper_connector_dpms(connector, mode);
+ priv->audio_params = p->audio_params;
}
-static const struct drm_connector_funcs tda998x_connector_funcs = {
- .dpms = tda998x_connector_dpms,
- .reset = drm_atomic_helper_connector_reset,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .detect = tda998x_connector_detect,
- .destroy = tda998x_connector_destroy,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
static int tda998x_bind(struct device *dev, struct device *master, void *data)
{
struct tda998x_encoder_params *params = dev->platform_data;
@@ -1630,7 +1687,6 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data)
crtcs = 1 << 0;
}
- priv->connector.interlace_allowed = 1;
priv->encoder.possible_crtcs = crtcs;
ret = tda998x_create(client, priv);
@@ -1638,9 +1694,7 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data)
return ret;
if (!dev->of_node && params)
- tda998x_encoder_set_config(priv, params);
-
- tda998x_encoder_set_polling(priv, &priv->connector);
+ tda998x_set_config(priv, params);
drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
@@ -1648,24 +1702,12 @@ static int tda998x_bind(struct device *dev, struct device *master, void *data)
if (ret)
goto err_encoder;
- drm_connector_helper_add(&priv->connector,
- &tda998x_connector_helper_funcs);
- ret = drm_connector_init(drm, &priv->connector,
- &tda998x_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
+ ret = tda998x_connector_init(priv, drm);
if (ret)
goto err_connector;
- ret = drm_connector_register(&priv->connector);
- if (ret)
- goto err_sysfs;
-
- drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
-
return 0;
-err_sysfs:
- drm_connector_cleanup(&priv->connector);
err_connector:
drm_encoder_cleanup(&priv->encoder);
err_encoder:
@@ -1678,7 +1720,6 @@ static void tda998x_unbind(struct device *dev, struct device *master,
{
struct tda998x_priv *priv = dev_get_drvdata(dev);
- drm_connector_unregister(&priv->connector);
drm_connector_cleanup(&priv->connector);
drm_encoder_cleanup(&priv->encoder);
tda998x_destroy(priv);
@@ -1692,6 +1733,10 @@ static const struct component_ops tda998x_ops = {
static int
tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_warn(&client->dev, "adapter does not support I2C\n");
+ return -EIO;
+ }
return component_add(&client->dev, &tda998x_ops);
}
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index d91856779beb..ab4e6cbe1f8b 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -113,9 +113,7 @@ static const struct file_operations i810_buffer_fops = {
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
.mmap = i810_mmap_buffers,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index 0be55dc1ef4b..02504a7cfaf2 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -49,9 +49,7 @@ static const struct file_operations i810_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = drm_legacy_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 7769e469118f..5ddde7349fbd 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -11,6 +11,7 @@ config DRM_I915
select DRM_KMS_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
+ select RELAY
# i915 depends on ACPI_VIDEO when ACPI is enabled
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
select BACKLIGHT_LCD_SUPPORT if ACPI
@@ -24,28 +25,59 @@ config DRM_I915
including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G,
G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3,
Core i5, Core i7 as well as Atom CPUs with integrated graphics.
- If M is selected, the module will be called i915. AGP support
- is required for this driver to work. This driver is used by
- the Intel driver in X.org 6.8 and XFree86 4.4 and above. It
- replaces the older i830 module that supported a subset of the
- hardware in older X.org releases.
+
+ This driver is used by the Intel driver in X.org 6.8 and
+ XFree86 4.4 and above. It replaces the older i830 module that
+ supported a subset of the hardware in older X.org releases.
Note that the older i810/i815 chipsets require the use of the
i810 driver instead, and the Atom z5xx series has an entirely
different implementation.
-config DRM_I915_PRELIMINARY_HW_SUPPORT
- bool "Enable preliminary support for prerelease Intel hardware by default"
+ If "M" is selected, the module will be called i915.
+
+config DRM_I915_ALPHA_SUPPORT
+ bool "Enable alpha quality support for new Intel hardware by default"
depends on DRM_I915
default n
help
- Choose this option if you have prerelease Intel hardware and want the
- i915 driver to support it by default. You can enable such support at
- runtime with the module option i915.preliminary_hw_support=1; this
- option changes the default for that module option.
+ Choose this option if you have new Intel hardware and want to enable
+ the alpha quality i915 driver support for the hardware in this kernel
+ version. You can also enable the support at runtime using the module
+ parameter i915.alpha_support=1; this option changes the default for
+ that module parameter.
+
+ It is recommended to upgrade to a kernel version with proper support
+ as soon as it is available. Generally fixes for platforms with alpha
+ support are not backported to older kernels.
If in doubt, say "N".
+config DRM_I915_CAPTURE_ERROR
+ bool "Enable capturing GPU state following a hang"
+ depends on DRM_I915
+ default y
+ help
+ This option enables capturing the GPU state when a hang is detected.
+ This information is vital for triaging hangs and assists in debugging.
+ Please report any hang to
+ https://bugs.freedesktop.org/enter_bug.cgi?product=DRI
+ for triaging.
+
+ If in doubt, say "Y".
+
+config DRM_I915_COMPRESS_ERROR
+ bool "Compress GPU error state"
+ depends on DRM_I915_CAPTURE_ERROR
+ select ZLIB_DEFLATE
+ default y
+ help
+ This option selects ZLIB_DEFLATE if it isn't already
+ selected and causes any error state captured upon a GPU hang
+ to be compressed using zlib.
+
+ If in doubt, say "Y".
+
config DRM_I915_USERPTR
bool "Always enable userptr support"
depends on DRM_I915
@@ -60,6 +92,7 @@ config DRM_I915_USERPTR
config DRM_I915_GVT
bool "Enable Intel GVT-g graphics virtualization host support"
depends on DRM_I915
+ depends on 64BIT
default n
help
Choose this option if you want to enable Intel GVT-g graphics
@@ -79,6 +112,15 @@ config DRM_I915_GVT
If in doubt, say "N".
+config DRM_I915_GVT_KVMGT
+ tristate "Enable KVM/VFIO support for Intel GVT-g"
+ depends on DRM_I915_GVT
+ depends on KVM
+ default n
+ help
+ Choose this option if you want to enable KVMGT support for
+ Intel GVT-g.
+
menu "drm/i915 Debugging"
depends on DRM_I915
depends on EXPERT
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index cee87bfd10c4..51ba630a134b 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -21,6 +21,7 @@ config DRM_I915_DEBUG
select PREEMPT_COUNT
select X86_MSR # used by igt/pm_rpm
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
+ select DRM_DEBUG_MM if DRM=y
default n
help
Choose this option to turn on extra driver debugging that may affect
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a998c2bce70a..3dea46af9fe6 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -33,19 +33,22 @@ i915-y += i915_cmd_parser.o \
i915_gem_dmabuf.o \
i915_gem_evict.o \
i915_gem_execbuffer.o \
- i915_gem_fence.o \
+ i915_gem_fence_reg.o \
i915_gem_gtt.o \
+ i915_gem_internal.o \
i915_gem.o \
i915_gem_render_state.o \
i915_gem_request.o \
i915_gem_shrinker.o \
i915_gem_stolen.o \
i915_gem_tiling.o \
+ i915_gem_timeline.o \
i915_gem_userptr.o \
- i915_gpu_error.o \
i915_trace_points.o \
+ i915_vma.o \
intel_breadcrumbs.o \
intel_engine_cs.o \
+ intel_hangcheck.o \
intel_lrc.o \
intel_mocs.o \
intel_ringbuffer.o \
@@ -102,11 +105,15 @@ i915-y += dvo_ch7017.o \
intel_dvo.o \
intel_hdmi.o \
intel_i2c.o \
+ intel_lspcon.o \
intel_lvds.o \
intel_panel.o \
intel_sdvo.o \
intel_tv.o
+# Post-mortem debug and GPU hang state capture
+i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
+
# virtual gpu code
i915-y += i915_vgpu.o
diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
index d0f21a6ad60d..8a46a7f31d53 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -1,5 +1,10 @@
GVT_DIR := gvt
-GVT_SOURCE := gvt.o
+GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
+ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
+ execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
-ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall
-i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall
+i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+
+CFLAGS_kvmgt.o := -Wno-unused-function
+obj-$(CONFIG_DRM_I915_GVT_KVMGT) += $(GVT_DIR)/kvmgt.o
diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
new file mode 100644
index 000000000000..0d41ebc4aea6
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Dexuan Cui
+ *
+ * Contributors:
+ * Pei Zhang <pei.zhang@intel.com>
+ * Min He <min.he@intel.com>
+ * Niu Bing <bing.niu@intel.com>
+ * Yulei Zhang <yulei.zhang@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define MB_TO_BYTES(mb) ((mb) << 20ULL)
+#define BYTES_TO_MB(b) ((b) >> 20ULL)
+
+#define HOST_LOW_GM_SIZE MB_TO_BYTES(128)
+#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384)
+#define HOST_FENCE 4
+
+static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ u32 alloc_flag, search_flag;
+ u64 start, end, size;
+ struct drm_mm_node *node;
+ int retried = 0;
+ int ret;
+
+ if (high_gm) {
+ search_flag = DRM_MM_SEARCH_BELOW;
+ alloc_flag = DRM_MM_CREATE_TOP;
+ node = &vgpu->gm.high_gm_node;
+ size = vgpu_hidden_sz(vgpu);
+ start = gvt_hidden_gmadr_base(gvt);
+ end = gvt_hidden_gmadr_end(gvt);
+ } else {
+ search_flag = DRM_MM_SEARCH_DEFAULT;
+ alloc_flag = DRM_MM_CREATE_DEFAULT;
+ node = &vgpu->gm.low_gm_node;
+ size = vgpu_aperture_sz(vgpu);
+ start = gvt_aperture_gmadr_base(gvt);
+ end = gvt_aperture_gmadr_end(gvt);
+ }
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+search_again:
+ ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm,
+ node, size, 4096, 0,
+ start, end, search_flag,
+ alloc_flag);
+ if (ret) {
+ ret = i915_gem_evict_something(&dev_priv->ggtt.base,
+ size, 4096, 0, start, end, 0);
+ if (ret == 0 && ++retried < 3)
+ goto search_again;
+
+ gvt_err("fail to alloc %s gm space from host, retried %d\n",
+ high_gm ? "high" : "low", retried);
+ }
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ return ret;
+}
+
+static int alloc_vgpu_gm(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ int ret;
+
+ ret = alloc_gm(vgpu, false);
+ if (ret)
+ return ret;
+
+ ret = alloc_gm(vgpu, true);
+ if (ret)
+ goto out_free_aperture;
+
+ gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id,
+ vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu));
+
+ gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id,
+ vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu));
+
+ return 0;
+out_free_aperture:
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ drm_mm_remove_node(&vgpu->gm.low_gm_node);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ return ret;
+}
+
+static void free_vgpu_gm(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ drm_mm_remove_node(&vgpu->gm.low_gm_node);
+ drm_mm_remove_node(&vgpu->gm.high_gm_node);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+/**
+ * intel_vgpu_write_fence - write fence registers owned by a vGPU
+ * @vgpu: vGPU instance
+ * @fence: vGPU fence register number
+ * @value: Fence register value to be written
+ *
+ * This function is used to write fence registers owned by a vGPU. The vGPU
+ * fence register number will be translated into HW fence register number.
+ *
+ */
+void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
+ u32 fence, u64 value)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ struct drm_i915_fence_reg *reg;
+ i915_reg_t fence_reg_lo, fence_reg_hi;
+
+ assert_rpm_wakelock_held(dev_priv);
+
+ if (WARN_ON(fence > vgpu_fence_sz(vgpu)))
+ return;
+
+ reg = vgpu->fence.regs[fence];
+ if (WARN_ON(!reg))
+ return;
+
+ fence_reg_lo = FENCE_REG_GEN6_LO(reg->id);
+ fence_reg_hi = FENCE_REG_GEN6_HI(reg->id);
+
+ I915_WRITE(fence_reg_lo, 0);
+ POSTING_READ(fence_reg_lo);
+
+ I915_WRITE(fence_reg_hi, upper_32_bits(value));
+ I915_WRITE(fence_reg_lo, lower_32_bits(value));
+ POSTING_READ(fence_reg_lo);
+}
+
+static void free_vgpu_fence(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ struct drm_i915_fence_reg *reg;
+ u32 i;
+
+ if (WARN_ON(!vgpu_fence_sz(vgpu)))
+ return;
+
+ intel_runtime_pm_get(dev_priv);
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+ reg = vgpu->fence.regs[i];
+ intel_vgpu_write_fence(vgpu, i, 0);
+ list_add_tail(&reg->link,
+ &dev_priv->mm.fence_list);
+ }
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+
+ intel_runtime_pm_put(dev_priv);
+}
+
+static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ struct drm_i915_fence_reg *reg;
+ int i;
+ struct list_head *pos, *q;
+
+ intel_runtime_pm_get(dev_priv);
+
+ /* Request fences from host */
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ i = 0;
+ list_for_each_safe(pos, q, &dev_priv->mm.fence_list) {
+ reg = list_entry(pos, struct drm_i915_fence_reg, link);
+ if (reg->pin_count || reg->vma)
+ continue;
+ list_del(pos);
+ vgpu->fence.regs[i] = reg;
+ intel_vgpu_write_fence(vgpu, i, 0);
+ if (++i == vgpu_fence_sz(vgpu))
+ break;
+ }
+ if (i != vgpu_fence_sz(vgpu))
+ goto out_free_fence;
+
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ intel_runtime_pm_put(dev_priv);
+ return 0;
+out_free_fence:
+ /* Return fences to host, if fail */
+ for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+ reg = vgpu->fence.regs[i];
+ if (!reg)
+ continue;
+ list_add_tail(&reg->link,
+ &dev_priv->mm.fence_list);
+ }
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ intel_runtime_pm_put(dev_priv);
+ return -ENOSPC;
+}
+
+static void free_resource(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+
+ gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu);
+ gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu);
+ gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu);
+}
+
+static int alloc_resource(struct intel_vgpu *vgpu,
+ struct intel_vgpu_creation_params *param)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ unsigned long request, avail, max, taken;
+ const char *item;
+
+ if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
+ gvt_err("Invalid vGPU creation params\n");
+ return -EINVAL;
+ }
+
+ item = "low GM space";
+ max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
+ taken = gvt->gm.vgpu_allocated_low_gm_size;
+ avail = max - taken;
+ request = MB_TO_BYTES(param->low_gm_sz);
+
+ if (request > avail)
+ goto no_enough_resource;
+
+ vgpu_aperture_sz(vgpu) = request;
+
+ item = "high GM space";
+ max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
+ taken = gvt->gm.vgpu_allocated_high_gm_size;
+ avail = max - taken;
+ request = MB_TO_BYTES(param->high_gm_sz);
+
+ if (request > avail)
+ goto no_enough_resource;
+
+ vgpu_hidden_sz(vgpu) = request;
+
+ item = "fence";
+ max = gvt_fence_sz(gvt) - HOST_FENCE;
+ taken = gvt->fence.vgpu_allocated_fence_num;
+ avail = max - taken;
+ request = param->fence_sz;
+
+ if (request > avail)
+ goto no_enough_resource;
+
+ vgpu_fence_sz(vgpu) = request;
+
+ gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz);
+ gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz);
+ gvt->fence.vgpu_allocated_fence_num += param->fence_sz;
+ return 0;
+
+no_enough_resource:
+ gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item);
+ gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n",
+ vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail),
+ BYTES_TO_MB(max), BYTES_TO_MB(taken));
+ return -ENOSPC;
+}
+
+/**
+ * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is used to free the HW resource owned by a vGPU.
+ *
+ */
+void intel_vgpu_free_resource(struct intel_vgpu *vgpu)
+{
+ free_vgpu_gm(vgpu);
+ free_vgpu_fence(vgpu);
+ free_resource(vgpu);
+}
+
+/**
+ * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
+ * @vgpu: vGPU
+ * @param: vGPU creation params
+ *
+ * This function is used to allocate HW resource for a vGPU. User specifies
+ * the resource configuration through the creation params.
+ *
+ * Returns:
+ * zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
+ struct intel_vgpu_creation_params *param)
+{
+ int ret;
+
+ ret = alloc_resource(vgpu, param);
+ if (ret)
+ return ret;
+
+ ret = alloc_vgpu_gm(vgpu);
+ if (ret)
+ goto out_free_resource;
+
+ ret = alloc_vgpu_fence(vgpu);
+ if (ret)
+ goto out_free_vgpu_gm;
+
+ return 0;
+
+out_free_vgpu_gm:
+ free_vgpu_gm(vgpu);
+out_free_resource:
+ free_resource(vgpu);
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
new file mode 100644
index 000000000000..db516382a4d4
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+enum {
+ INTEL_GVT_PCI_BAR_GTTMMIO = 0,
+ INTEL_GVT_PCI_BAR_APERTURE,
+ INTEL_GVT_PCI_BAR_PIO,
+ INTEL_GVT_PCI_BAR_MAX,
+};
+
+/**
+ * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ if (WARN_ON(bytes > 4))
+ return -EINVAL;
+
+ if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ))
+ return -EINVAL;
+
+ memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes);
+ return 0;
+}
+
+static int map_aperture(struct intel_vgpu *vgpu, bool map)
+{
+ u64 first_gfn, first_mfn;
+ u64 val;
+ int ret;
+
+ if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
+ return 0;
+
+ val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2];
+ if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
+ else
+ val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
+
+ first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT;
+ first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+
+ ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn,
+ first_mfn,
+ vgpu_aperture_sz(vgpu) >>
+ PAGE_SHIFT, map);
+ if (ret)
+ return ret;
+
+ vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
+ return 0;
+}
+
+static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap)
+{
+ u64 start, end;
+ u64 val;
+ int ret;
+
+ if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked)
+ return 0;
+
+ val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0];
+ if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
+ else
+ start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
+
+ start &= ~GENMASK(3, 0);
+ end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1;
+
+ ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap);
+ if (ret)
+ return ret;
+
+ vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap;
+ return 0;
+}
+
+static int emulate_pci_command_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u8 old = vgpu_cfg_space(vgpu)[offset];
+ u8 new = *(u8 *)p_data;
+ u8 changed = old ^ new;
+ int ret;
+
+ if (!(changed & PCI_COMMAND_MEMORY))
+ return 0;
+
+ if (old & PCI_COMMAND_MEMORY) {
+ ret = trap_gttmmio(vgpu, false);
+ if (ret)
+ return ret;
+ ret = map_aperture(vgpu, false);
+ if (ret)
+ return ret;
+ } else {
+ ret = trap_gttmmio(vgpu, true);
+ if (ret)
+ return ret;
+ ret = map_aperture(vgpu, true);
+ if (ret)
+ return ret;
+ }
+
+ memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+ return 0;
+}
+
+static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ unsigned int bar_index =
+ (rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8;
+ u32 new = *(u32 *)(p_data);
+ bool lo = IS_ALIGNED(offset, 8);
+ u64 size;
+ int ret = 0;
+ bool mmio_enabled =
+ vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY;
+
+ if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX))
+ return -EINVAL;
+
+ if (new == 0xffffffff) {
+ /*
+ * Power-up software can determine how much address
+ * space the device requires by writing a value of
+ * all 1's to the register and then reading the value
+ * back. The device will return 0's in all don't-care
+ * address bits.
+ */
+ size = vgpu->cfg_space.bar[bar_index].size;
+ if (lo) {
+ new = rounddown(new, size);
+ } else {
+ u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)];
+ /* for 32bit mode bar it returns all-0 in upper 32
+ * bit, for 64bit mode bar it will calculate the
+ * size with lower 32bit and return the corresponding
+ * value
+ */
+ if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ new &= (~(size-1)) >> 32;
+ else
+ new = 0;
+ }
+ /*
+ * Unmapp & untrap the BAR, since guest hasn't configured a
+ * valid GPA
+ */
+ switch (bar_index) {
+ case INTEL_GVT_PCI_BAR_GTTMMIO:
+ ret = trap_gttmmio(vgpu, false);
+ break;
+ case INTEL_GVT_PCI_BAR_APERTURE:
+ ret = map_aperture(vgpu, false);
+ break;
+ }
+ intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+ } else {
+ /*
+ * Unmapp & untrap the old BAR first, since guest has
+ * re-configured the BAR
+ */
+ switch (bar_index) {
+ case INTEL_GVT_PCI_BAR_GTTMMIO:
+ ret = trap_gttmmio(vgpu, false);
+ break;
+ case INTEL_GVT_PCI_BAR_APERTURE:
+ ret = map_aperture(vgpu, false);
+ break;
+ }
+ intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+ /* Track the new BAR */
+ if (mmio_enabled) {
+ switch (bar_index) {
+ case INTEL_GVT_PCI_BAR_GTTMMIO:
+ ret = trap_gttmmio(vgpu, true);
+ break;
+ case INTEL_GVT_PCI_BAR_APERTURE:
+ ret = map_aperture(vgpu, true);
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/**
+ * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ int ret;
+
+ if (WARN_ON(bytes > 4))
+ return -EINVAL;
+
+ if (WARN_ON(offset + bytes >= INTEL_GVT_MAX_CFG_SPACE_SZ))
+ return -EINVAL;
+
+ /* First check if it's PCI_COMMAND */
+ if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) {
+ if (WARN_ON(bytes > 2))
+ return -EINVAL;
+ return emulate_pci_command_write(vgpu, offset, p_data, bytes);
+ }
+
+ switch (rounddown(offset, 4)) {
+ case PCI_BASE_ADDRESS_0:
+ case PCI_BASE_ADDRESS_1:
+ case PCI_BASE_ADDRESS_2:
+ case PCI_BASE_ADDRESS_3:
+ if (WARN_ON(!IS_ALIGNED(offset, 4)))
+ return -EINVAL;
+ return emulate_pci_bar_write(vgpu, offset, p_data, bytes);
+
+ case INTEL_GVT_PCI_SWSCI:
+ if (WARN_ON(!IS_ALIGNED(offset, 4)))
+ return -EINVAL;
+ ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data);
+ if (ret)
+ return ret;
+ break;
+
+ case INTEL_GVT_PCI_OPREGION:
+ if (WARN_ON(!IS_ALIGNED(offset, 4)))
+ return -EINVAL;
+ ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data);
+ if (ret)
+ return ret;
+
+ memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+ break;
+ default:
+ memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+ break;
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
new file mode 100644
index 000000000000..d26a092c70e8
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -0,0 +1,2831 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Kevin Tian <kevin.tian@intel.com>
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Yulei Zhang <yulei.zhang@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include <linux/slab.h>
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+#include "trace.h"
+
+#define INVALID_OP (~0U)
+
+#define OP_LEN_MI 9
+#define OP_LEN_2D 10
+#define OP_LEN_3D_MEDIA 16
+#define OP_LEN_MFX_VC 16
+#define OP_LEN_VEBOX 16
+
+#define CMD_TYPE(cmd) (((cmd) >> 29) & 7)
+
+struct sub_op_bits {
+ int hi;
+ int low;
+};
+struct decode_info {
+ char *name;
+ int op_len;
+ int nr_sub_op;
+ struct sub_op_bits *sub_op;
+};
+
+#define MAX_CMD_BUDGET 0x7fffffff
+#define MI_WAIT_FOR_PLANE_C_FLIP_PENDING (1<<15)
+#define MI_WAIT_FOR_PLANE_B_FLIP_PENDING (1<<9)
+#define MI_WAIT_FOR_PLANE_A_FLIP_PENDING (1<<1)
+
+#define MI_WAIT_FOR_SPRITE_C_FLIP_PENDING (1<<20)
+#define MI_WAIT_FOR_SPRITE_B_FLIP_PENDING (1<<10)
+#define MI_WAIT_FOR_SPRITE_A_FLIP_PENDING (1<<2)
+
+/* Render Command Map */
+
+/* MI_* command Opcode (28:23) */
+#define OP_MI_NOOP 0x0
+#define OP_MI_SET_PREDICATE 0x1 /* HSW+ */
+#define OP_MI_USER_INTERRUPT 0x2
+#define OP_MI_WAIT_FOR_EVENT 0x3
+#define OP_MI_FLUSH 0x4
+#define OP_MI_ARB_CHECK 0x5
+#define OP_MI_RS_CONTROL 0x6 /* HSW+ */
+#define OP_MI_REPORT_HEAD 0x7
+#define OP_MI_ARB_ON_OFF 0x8
+#define OP_MI_URB_ATOMIC_ALLOC 0x9 /* HSW+ */
+#define OP_MI_BATCH_BUFFER_END 0xA
+#define OP_MI_SUSPEND_FLUSH 0xB
+#define OP_MI_PREDICATE 0xC /* IVB+ */
+#define OP_MI_TOPOLOGY_FILTER 0xD /* IVB+ */
+#define OP_MI_SET_APPID 0xE /* IVB+ */
+#define OP_MI_RS_CONTEXT 0xF /* HSW+ */
+#define OP_MI_LOAD_SCAN_LINES_INCL 0x12 /* HSW+ */
+#define OP_MI_DISPLAY_FLIP 0x14
+#define OP_MI_SEMAPHORE_MBOX 0x16
+#define OP_MI_SET_CONTEXT 0x18
+#define OP_MI_MATH 0x1A
+#define OP_MI_URB_CLEAR 0x19
+#define OP_MI_SEMAPHORE_SIGNAL 0x1B /* BDW+ */
+#define OP_MI_SEMAPHORE_WAIT 0x1C /* BDW+ */
+
+#define OP_MI_STORE_DATA_IMM 0x20
+#define OP_MI_STORE_DATA_INDEX 0x21
+#define OP_MI_LOAD_REGISTER_IMM 0x22
+#define OP_MI_UPDATE_GTT 0x23
+#define OP_MI_STORE_REGISTER_MEM 0x24
+#define OP_MI_FLUSH_DW 0x26
+#define OP_MI_CLFLUSH 0x27
+#define OP_MI_REPORT_PERF_COUNT 0x28
+#define OP_MI_LOAD_REGISTER_MEM 0x29 /* HSW+ */
+#define OP_MI_LOAD_REGISTER_REG 0x2A /* HSW+ */
+#define OP_MI_RS_STORE_DATA_IMM 0x2B /* HSW+ */
+#define OP_MI_LOAD_URB_MEM 0x2C /* HSW+ */
+#define OP_MI_STORE_URM_MEM 0x2D /* HSW+ */
+#define OP_MI_2E 0x2E /* BDW+ */
+#define OP_MI_2F 0x2F /* BDW+ */
+#define OP_MI_BATCH_BUFFER_START 0x31
+
+/* Bit definition for dword 0 */
+#define _CMDBIT_BB_START_IN_PPGTT (1UL << 8)
+
+#define OP_MI_CONDITIONAL_BATCH_BUFFER_END 0x36
+
+#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2))
+#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U))
+#define BATCH_BUFFER_ADR_SPACE_BIT(x) (((x) >> 8) & 1U)
+#define BATCH_BUFFER_2ND_LEVEL_BIT(x) ((x) >> 22 & 1U)
+
+/* 2D command: Opcode (28:22) */
+#define OP_2D(x) ((2<<7) | x)
+
+#define OP_XY_SETUP_BLT OP_2D(0x1)
+#define OP_XY_SETUP_CLIP_BLT OP_2D(0x3)
+#define OP_XY_SETUP_MONO_PATTERN_SL_BLT OP_2D(0x11)
+#define OP_XY_PIXEL_BLT OP_2D(0x24)
+#define OP_XY_SCANLINES_BLT OP_2D(0x25)
+#define OP_XY_TEXT_BLT OP_2D(0x26)
+#define OP_XY_TEXT_IMMEDIATE_BLT OP_2D(0x31)
+#define OP_XY_COLOR_BLT OP_2D(0x50)
+#define OP_XY_PAT_BLT OP_2D(0x51)
+#define OP_XY_MONO_PAT_BLT OP_2D(0x52)
+#define OP_XY_SRC_COPY_BLT OP_2D(0x53)
+#define OP_XY_MONO_SRC_COPY_BLT OP_2D(0x54)
+#define OP_XY_FULL_BLT OP_2D(0x55)
+#define OP_XY_FULL_MONO_SRC_BLT OP_2D(0x56)
+#define OP_XY_FULL_MONO_PATTERN_BLT OP_2D(0x57)
+#define OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT OP_2D(0x58)
+#define OP_XY_MONO_PAT_FIXED_BLT OP_2D(0x59)
+#define OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT OP_2D(0x71)
+#define OP_XY_PAT_BLT_IMMEDIATE OP_2D(0x72)
+#define OP_XY_SRC_COPY_CHROMA_BLT OP_2D(0x73)
+#define OP_XY_FULL_IMMEDIATE_PATTERN_BLT OP_2D(0x74)
+#define OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT OP_2D(0x75)
+#define OP_XY_PAT_CHROMA_BLT OP_2D(0x76)
+#define OP_XY_PAT_CHROMA_BLT_IMMEDIATE OP_2D(0x77)
+
+/* 3D/Media Command: Pipeline Type(28:27) Opcode(26:24) Sub Opcode(23:16) */
+#define OP_3D_MEDIA(sub_type, opcode, sub_opcode) \
+ ((3 << 13) | ((sub_type) << 11) | ((opcode) << 8) | (sub_opcode))
+
+#define OP_STATE_PREFETCH OP_3D_MEDIA(0x0, 0x0, 0x03)
+
+#define OP_STATE_BASE_ADDRESS OP_3D_MEDIA(0x0, 0x1, 0x01)
+#define OP_STATE_SIP OP_3D_MEDIA(0x0, 0x1, 0x02)
+#define OP_3D_MEDIA_0_1_4 OP_3D_MEDIA(0x0, 0x1, 0x04)
+
+#define OP_3DSTATE_VF_STATISTICS_GM45 OP_3D_MEDIA(0x1, 0x0, 0x0B)
+
+#define OP_PIPELINE_SELECT OP_3D_MEDIA(0x1, 0x1, 0x04)
+
+#define OP_MEDIA_VFE_STATE OP_3D_MEDIA(0x2, 0x0, 0x0)
+#define OP_MEDIA_CURBE_LOAD OP_3D_MEDIA(0x2, 0x0, 0x1)
+#define OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD OP_3D_MEDIA(0x2, 0x0, 0x2)
+#define OP_MEDIA_GATEWAY_STATE OP_3D_MEDIA(0x2, 0x0, 0x3)
+#define OP_MEDIA_STATE_FLUSH OP_3D_MEDIA(0x2, 0x0, 0x4)
+
+#define OP_MEDIA_OBJECT OP_3D_MEDIA(0x2, 0x1, 0x0)
+#define OP_MEDIA_OBJECT_PRT OP_3D_MEDIA(0x2, 0x1, 0x2)
+#define OP_MEDIA_OBJECT_WALKER OP_3D_MEDIA(0x2, 0x1, 0x3)
+#define OP_GPGPU_WALKER OP_3D_MEDIA(0x2, 0x1, 0x5)
+
+#define OP_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x0, 0x04) /* IVB+ */
+#define OP_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x05) /* IVB+ */
+#define OP_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x06) /* IVB+ */
+#define OP_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x07) /* IVB+ */
+#define OP_3DSTATE_VERTEX_BUFFERS OP_3D_MEDIA(0x3, 0x0, 0x08)
+#define OP_3DSTATE_VERTEX_ELEMENTS OP_3D_MEDIA(0x3, 0x0, 0x09)
+#define OP_3DSTATE_INDEX_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x0A)
+#define OP_3DSTATE_VF_STATISTICS OP_3D_MEDIA(0x3, 0x0, 0x0B)
+#define OP_3DSTATE_VF OP_3D_MEDIA(0x3, 0x0, 0x0C) /* HSW+ */
+#define OP_3DSTATE_CC_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0E)
+#define OP_3DSTATE_SCISSOR_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0F)
+#define OP_3DSTATE_VS OP_3D_MEDIA(0x3, 0x0, 0x10)
+#define OP_3DSTATE_GS OP_3D_MEDIA(0x3, 0x0, 0x11)
+#define OP_3DSTATE_CLIP OP_3D_MEDIA(0x3, 0x0, 0x12)
+#define OP_3DSTATE_SF OP_3D_MEDIA(0x3, 0x0, 0x13)
+#define OP_3DSTATE_WM OP_3D_MEDIA(0x3, 0x0, 0x14)
+#define OP_3DSTATE_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x15)
+#define OP_3DSTATE_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x16)
+#define OP_3DSTATE_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x17)
+#define OP_3DSTATE_SAMPLE_MASK OP_3D_MEDIA(0x3, 0x0, 0x18)
+#define OP_3DSTATE_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x19) /* IVB+ */
+#define OP_3DSTATE_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x1A) /* IVB+ */
+#define OP_3DSTATE_HS OP_3D_MEDIA(0x3, 0x0, 0x1B) /* IVB+ */
+#define OP_3DSTATE_TE OP_3D_MEDIA(0x3, 0x0, 0x1C) /* IVB+ */
+#define OP_3DSTATE_DS OP_3D_MEDIA(0x3, 0x0, 0x1D) /* IVB+ */
+#define OP_3DSTATE_STREAMOUT OP_3D_MEDIA(0x3, 0x0, 0x1E) /* IVB+ */
+#define OP_3DSTATE_SBE OP_3D_MEDIA(0x3, 0x0, 0x1F) /* IVB+ */
+#define OP_3DSTATE_PS OP_3D_MEDIA(0x3, 0x0, 0x20) /* IVB+ */
+#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP OP_3D_MEDIA(0x3, 0x0, 0x21) /* IVB+ */
+#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC OP_3D_MEDIA(0x3, 0x0, 0x23) /* IVB+ */
+#define OP_3DSTATE_BLEND_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x24) /* IVB+ */
+#define OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x25) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x26) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x27) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x28) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x29) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2A) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x2B) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x2C) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x2D) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x2E) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2F) /* IVB+ */
+#define OP_3DSTATE_URB_VS OP_3D_MEDIA(0x3, 0x0, 0x30) /* IVB+ */
+#define OP_3DSTATE_URB_HS OP_3D_MEDIA(0x3, 0x0, 0x31) /* IVB+ */
+#define OP_3DSTATE_URB_DS OP_3D_MEDIA(0x3, 0x0, 0x32) /* IVB+ */
+#define OP_3DSTATE_URB_GS OP_3D_MEDIA(0x3, 0x0, 0x33) /* IVB+ */
+#define OP_3DSTATE_GATHER_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x34) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x35) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x36) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x37) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x38) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTF_VS OP_3D_MEDIA(0x3, 0x0, 0x39) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTF_PS OP_3D_MEDIA(0x3, 0x0, 0x3A) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTI_VS OP_3D_MEDIA(0x3, 0x0, 0x3B) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTI_PS OP_3D_MEDIA(0x3, 0x0, 0x3C) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTB_VS OP_3D_MEDIA(0x3, 0x0, 0x3D) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTB_PS OP_3D_MEDIA(0x3, 0x0, 0x3E) /* HSW+ */
+#define OP_3DSTATE_DX9_LOCAL_VALID_VS OP_3D_MEDIA(0x3, 0x0, 0x3F) /* HSW+ */
+#define OP_3DSTATE_DX9_LOCAL_VALID_PS OP_3D_MEDIA(0x3, 0x0, 0x40) /* HSW+ */
+#define OP_3DSTATE_DX9_GENERATE_ACTIVE_VS OP_3D_MEDIA(0x3, 0x0, 0x41) /* HSW+ */
+#define OP_3DSTATE_DX9_GENERATE_ACTIVE_PS OP_3D_MEDIA(0x3, 0x0, 0x42) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_VS OP_3D_MEDIA(0x3, 0x0, 0x43) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_GS OP_3D_MEDIA(0x3, 0x0, 0x44) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_HS OP_3D_MEDIA(0x3, 0x0, 0x45) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_DS OP_3D_MEDIA(0x3, 0x0, 0x46) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_PS OP_3D_MEDIA(0x3, 0x0, 0x47) /* HSW+ */
+
+#define OP_3DSTATE_VF_INSTANCING OP_3D_MEDIA(0x3, 0x0, 0x49) /* BDW+ */
+#define OP_3DSTATE_VF_SGVS OP_3D_MEDIA(0x3, 0x0, 0x4A) /* BDW+ */
+#define OP_3DSTATE_VF_TOPOLOGY OP_3D_MEDIA(0x3, 0x0, 0x4B) /* BDW+ */
+#define OP_3DSTATE_WM_CHROMAKEY OP_3D_MEDIA(0x3, 0x0, 0x4C) /* BDW+ */
+#define OP_3DSTATE_PS_BLEND OP_3D_MEDIA(0x3, 0x0, 0x4D) /* BDW+ */
+#define OP_3DSTATE_WM_DEPTH_STENCIL OP_3D_MEDIA(0x3, 0x0, 0x4E) /* BDW+ */
+#define OP_3DSTATE_PS_EXTRA OP_3D_MEDIA(0x3, 0x0, 0x4F) /* BDW+ */
+#define OP_3DSTATE_RASTER OP_3D_MEDIA(0x3, 0x0, 0x50) /* BDW+ */
+#define OP_3DSTATE_SBE_SWIZ OP_3D_MEDIA(0x3, 0x0, 0x51) /* BDW+ */
+#define OP_3DSTATE_WM_HZ_OP OP_3D_MEDIA(0x3, 0x0, 0x52) /* BDW+ */
+#define OP_3DSTATE_COMPONENT_PACKING OP_3D_MEDIA(0x3, 0x0, 0x55) /* SKL+ */
+
+#define OP_3DSTATE_DRAWING_RECTANGLE OP_3D_MEDIA(0x3, 0x1, 0x00)
+#define OP_3DSTATE_SAMPLER_PALETTE_LOAD0 OP_3D_MEDIA(0x3, 0x1, 0x02)
+#define OP_3DSTATE_CHROMA_KEY OP_3D_MEDIA(0x3, 0x1, 0x04)
+#define OP_SNB_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x05)
+#define OP_3DSTATE_POLY_STIPPLE_OFFSET OP_3D_MEDIA(0x3, 0x1, 0x06)
+#define OP_3DSTATE_POLY_STIPPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x07)
+#define OP_3DSTATE_LINE_STIPPLE OP_3D_MEDIA(0x3, 0x1, 0x08)
+#define OP_3DSTATE_AA_LINE_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x0A)
+#define OP_3DSTATE_GS_SVB_INDEX OP_3D_MEDIA(0x3, 0x1, 0x0B)
+#define OP_3DSTATE_SAMPLER_PALETTE_LOAD1 OP_3D_MEDIA(0x3, 0x1, 0x0C)
+#define OP_3DSTATE_MULTISAMPLE_BDW OP_3D_MEDIA(0x3, 0x0, 0x0D)
+#define OP_SNB_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0E)
+#define OP_SNB_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0F)
+#define OP_SNB_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x10)
+#define OP_3DSTATE_MONOFILTER_SIZE OP_3D_MEDIA(0x3, 0x1, 0x11)
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS OP_3D_MEDIA(0x3, 0x1, 0x12) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS OP_3D_MEDIA(0x3, 0x1, 0x13) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS OP_3D_MEDIA(0x3, 0x1, 0x14) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS OP_3D_MEDIA(0x3, 0x1, 0x15) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS OP_3D_MEDIA(0x3, 0x1, 0x16) /* IVB+ */
+#define OP_3DSTATE_SO_DECL_LIST OP_3D_MEDIA(0x3, 0x1, 0x17)
+#define OP_3DSTATE_SO_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x18)
+#define OP_3DSTATE_BINDING_TABLE_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x19) /* HSW+ */
+#define OP_3DSTATE_GATHER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1A) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1B) /* HSW+ */
+#define OP_3DSTATE_SAMPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x1C)
+#define OP_PIPE_CONTROL OP_3D_MEDIA(0x3, 0x2, 0x00)
+#define OP_3DPRIMITIVE OP_3D_MEDIA(0x3, 0x3, 0x00)
+
+/* VCCP Command Parser */
+
+/*
+ * Below MFX and VBE cmd definition is from vaapi intel driver project (BSD License)
+ * git://anongit.freedesktop.org/vaapi/intel-driver
+ * src/i965_defines.h
+ *
+ */
+
+#define OP_MFX(pipeline, op, sub_opa, sub_opb) \
+ (3 << 13 | \
+ (pipeline) << 11 | \
+ (op) << 8 | \
+ (sub_opa) << 5 | \
+ (sub_opb))
+
+#define OP_MFX_PIPE_MODE_SELECT OP_MFX(2, 0, 0, 0) /* ALL */
+#define OP_MFX_SURFACE_STATE OP_MFX(2, 0, 0, 1) /* ALL */
+#define OP_MFX_PIPE_BUF_ADDR_STATE OP_MFX(2, 0, 0, 2) /* ALL */
+#define OP_MFX_IND_OBJ_BASE_ADDR_STATE OP_MFX(2, 0, 0, 3) /* ALL */
+#define OP_MFX_BSP_BUF_BASE_ADDR_STATE OP_MFX(2, 0, 0, 4) /* ALL */
+#define OP_2_0_0_5 OP_MFX(2, 0, 0, 5) /* ALL */
+#define OP_MFX_STATE_POINTER OP_MFX(2, 0, 0, 6) /* ALL */
+#define OP_MFX_QM_STATE OP_MFX(2, 0, 0, 7) /* IVB+ */
+#define OP_MFX_FQM_STATE OP_MFX(2, 0, 0, 8) /* IVB+ */
+#define OP_MFX_PAK_INSERT_OBJECT OP_MFX(2, 0, 2, 8) /* IVB+ */
+#define OP_MFX_STITCH_OBJECT OP_MFX(2, 0, 2, 0xA) /* IVB+ */
+
+#define OP_MFD_IT_OBJECT OP_MFX(2, 0, 1, 9) /* ALL */
+
+#define OP_MFX_WAIT OP_MFX(1, 0, 0, 0) /* IVB+ */
+#define OP_MFX_AVC_IMG_STATE OP_MFX(2, 1, 0, 0) /* ALL */
+#define OP_MFX_AVC_QM_STATE OP_MFX(2, 1, 0, 1) /* ALL */
+#define OP_MFX_AVC_DIRECTMODE_STATE OP_MFX(2, 1, 0, 2) /* ALL */
+#define OP_MFX_AVC_SLICE_STATE OP_MFX(2, 1, 0, 3) /* ALL */
+#define OP_MFX_AVC_REF_IDX_STATE OP_MFX(2, 1, 0, 4) /* ALL */
+#define OP_MFX_AVC_WEIGHTOFFSET_STATE OP_MFX(2, 1, 0, 5) /* ALL */
+#define OP_MFD_AVC_PICID_STATE OP_MFX(2, 1, 1, 5) /* HSW+ */
+#define OP_MFD_AVC_DPB_STATE OP_MFX(2, 1, 1, 6) /* IVB+ */
+#define OP_MFD_AVC_SLICEADDR OP_MFX(2, 1, 1, 7) /* IVB+ */
+#define OP_MFD_AVC_BSD_OBJECT OP_MFX(2, 1, 1, 8) /* ALL */
+#define OP_MFC_AVC_PAK_OBJECT OP_MFX(2, 1, 2, 9) /* ALL */
+
+#define OP_MFX_VC1_PRED_PIPE_STATE OP_MFX(2, 2, 0, 1) /* ALL */
+#define OP_MFX_VC1_DIRECTMODE_STATE OP_MFX(2, 2, 0, 2) /* ALL */
+#define OP_MFD_VC1_SHORT_PIC_STATE OP_MFX(2, 2, 1, 0) /* IVB+ */
+#define OP_MFD_VC1_LONG_PIC_STATE OP_MFX(2, 2, 1, 1) /* IVB+ */
+#define OP_MFD_VC1_BSD_OBJECT OP_MFX(2, 2, 1, 8) /* ALL */
+
+#define OP_MFX_MPEG2_PIC_STATE OP_MFX(2, 3, 0, 0) /* ALL */
+#define OP_MFX_MPEG2_QM_STATE OP_MFX(2, 3, 0, 1) /* ALL */
+#define OP_MFD_MPEG2_BSD_OBJECT OP_MFX(2, 3, 1, 8) /* ALL */
+#define OP_MFC_MPEG2_SLICEGROUP_STATE OP_MFX(2, 3, 2, 3) /* ALL */
+#define OP_MFC_MPEG2_PAK_OBJECT OP_MFX(2, 3, 2, 9) /* ALL */
+
+#define OP_MFX_2_6_0_0 OP_MFX(2, 6, 0, 0) /* IVB+ */
+#define OP_MFX_2_6_0_8 OP_MFX(2, 6, 0, 8) /* IVB+ */
+#define OP_MFX_2_6_0_9 OP_MFX(2, 6, 0, 9) /* IVB+ */
+
+#define OP_MFX_JPEG_PIC_STATE OP_MFX(2, 7, 0, 0)
+#define OP_MFX_JPEG_HUFF_TABLE_STATE OP_MFX(2, 7, 0, 2)
+#define OP_MFD_JPEG_BSD_OBJECT OP_MFX(2, 7, 1, 8)
+
+#define OP_VEB(pipeline, op, sub_opa, sub_opb) \
+ (3 << 13 | \
+ (pipeline) << 11 | \
+ (op) << 8 | \
+ (sub_opa) << 5 | \
+ (sub_opb))
+
+#define OP_VEB_SURFACE_STATE OP_VEB(2, 4, 0, 0)
+#define OP_VEB_STATE OP_VEB(2, 4, 0, 2)
+#define OP_VEB_DNDI_IECP_STATE OP_VEB(2, 4, 0, 3)
+
+struct parser_exec_state;
+
+typedef int (*parser_cmd_handler)(struct parser_exec_state *s);
+
+#define GVT_CMD_HASH_BITS 7
+
+/* which DWords need address fix */
+#define ADDR_FIX_1(x1) (1 << (x1))
+#define ADDR_FIX_2(x1, x2) (ADDR_FIX_1(x1) | ADDR_FIX_1(x2))
+#define ADDR_FIX_3(x1, x2, x3) (ADDR_FIX_1(x1) | ADDR_FIX_2(x2, x3))
+#define ADDR_FIX_4(x1, x2, x3, x4) (ADDR_FIX_1(x1) | ADDR_FIX_3(x2, x3, x4))
+#define ADDR_FIX_5(x1, x2, x3, x4, x5) (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5))
+
+struct cmd_info {
+ char *name;
+ u32 opcode;
+
+#define F_LEN_MASK (1U<<0)
+#define F_LEN_CONST 1U
+#define F_LEN_VAR 0U
+
+/*
+ * command has its own ip advance logic
+ * e.g. MI_BATCH_START, MI_BATCH_END
+ */
+#define F_IP_ADVANCE_CUSTOM (1<<1)
+
+#define F_POST_HANDLE (1<<2)
+ u32 flag;
+
+#define R_RCS (1 << RCS)
+#define R_VCS1 (1 << VCS)
+#define R_VCS2 (1 << VCS2)
+#define R_VCS (R_VCS1 | R_VCS2)
+#define R_BCS (1 << BCS)
+#define R_VECS (1 << VECS)
+#define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS)
+ /* rings that support this cmd: BLT/RCS/VCS/VECS */
+ uint16_t rings;
+
+ /* devices that support this cmd: SNB/IVB/HSW/... */
+ uint16_t devices;
+
+ /* which DWords are address that need fix up.
+ * bit 0 means a 32-bit non address operand in command
+ * bit 1 means address operand, which could be 32-bit
+ * or 64-bit depending on different architectures.(
+ * defined by "gmadr_bytes_in_cmd" in intel_gvt.
+ * No matter the address length, each address only takes
+ * one bit in the bitmap.
+ */
+ uint16_t addr_bitmap;
+
+ /* flag == F_LEN_CONST : command length
+ * flag == F_LEN_VAR : length bias bits
+ * Note: length is in DWord
+ */
+ uint8_t len;
+
+ parser_cmd_handler handler;
+};
+
+struct cmd_entry {
+ struct hlist_node hlist;
+ struct cmd_info *info;
+};
+
+enum {
+ RING_BUFFER_INSTRUCTION,
+ BATCH_BUFFER_INSTRUCTION,
+ BATCH_BUFFER_2ND_LEVEL,
+};
+
+enum {
+ GTT_BUFFER,
+ PPGTT_BUFFER
+};
+
+struct parser_exec_state {
+ struct intel_vgpu *vgpu;
+ int ring_id;
+
+ int buf_type;
+
+ /* batch buffer address type */
+ int buf_addr_type;
+
+ /* graphics memory address of ring buffer start */
+ unsigned long ring_start;
+ unsigned long ring_size;
+ unsigned long ring_head;
+ unsigned long ring_tail;
+
+ /* instruction graphics memory address */
+ unsigned long ip_gma;
+
+ /* mapped va of the instr_gma */
+ void *ip_va;
+ void *rb_va;
+
+ void *ret_bb_va;
+ /* next instruction when return from batch buffer to ring buffer */
+ unsigned long ret_ip_gma_ring;
+
+ /* next instruction when return from 2nd batch buffer to batch buffer */
+ unsigned long ret_ip_gma_bb;
+
+ /* batch buffer address type (GTT or PPGTT)
+ * used when ret from 2nd level batch buffer
+ */
+ int saved_buf_addr_type;
+
+ struct cmd_info *info;
+
+ struct intel_vgpu_workload *workload;
+};
+
+#define gmadr_dw_number(s) \
+ (s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2)
+
+static unsigned long bypass_scan_mask = 0;
+static bool bypass_batch_buffer_scan = true;
+
+/* ring ALL, type = 0 */
+static struct sub_op_bits sub_op_mi[] = {
+ {31, 29},
+ {28, 23},
+};
+
+static struct decode_info decode_info_mi = {
+ "MI",
+ OP_LEN_MI,
+ ARRAY_SIZE(sub_op_mi),
+ sub_op_mi,
+};
+
+/* ring RCS, command type 2 */
+static struct sub_op_bits sub_op_2d[] = {
+ {31, 29},
+ {28, 22},
+};
+
+static struct decode_info decode_info_2d = {
+ "2D",
+ OP_LEN_2D,
+ ARRAY_SIZE(sub_op_2d),
+ sub_op_2d,
+};
+
+/* ring RCS, command type 3 */
+static struct sub_op_bits sub_op_3d_media[] = {
+ {31, 29},
+ {28, 27},
+ {26, 24},
+ {23, 16},
+};
+
+static struct decode_info decode_info_3d_media = {
+ "3D_Media",
+ OP_LEN_3D_MEDIA,
+ ARRAY_SIZE(sub_op_3d_media),
+ sub_op_3d_media,
+};
+
+/* ring VCS, command type 3 */
+static struct sub_op_bits sub_op_mfx_vc[] = {
+ {31, 29},
+ {28, 27},
+ {26, 24},
+ {23, 21},
+ {20, 16},
+};
+
+static struct decode_info decode_info_mfx_vc = {
+ "MFX_VC",
+ OP_LEN_MFX_VC,
+ ARRAY_SIZE(sub_op_mfx_vc),
+ sub_op_mfx_vc,
+};
+
+/* ring VECS, command type 3 */
+static struct sub_op_bits sub_op_vebox[] = {
+ {31, 29},
+ {28, 27},
+ {26, 24},
+ {23, 21},
+ {20, 16},
+};
+
+static struct decode_info decode_info_vebox = {
+ "VEBOX",
+ OP_LEN_VEBOX,
+ ARRAY_SIZE(sub_op_vebox),
+ sub_op_vebox,
+};
+
+static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
+ [RCS] = {
+ &decode_info_mi,
+ NULL,
+ NULL,
+ &decode_info_3d_media,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ [VCS] = {
+ &decode_info_mi,
+ NULL,
+ NULL,
+ &decode_info_mfx_vc,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ [BCS] = {
+ &decode_info_mi,
+ NULL,
+ &decode_info_2d,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ [VECS] = {
+ &decode_info_mi,
+ NULL,
+ NULL,
+ &decode_info_vebox,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ [VCS2] = {
+ &decode_info_mi,
+ NULL,
+ NULL,
+ &decode_info_mfx_vc,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+};
+
+static inline u32 get_opcode(u32 cmd, int ring_id)
+{
+ struct decode_info *d_info;
+
+ if (ring_id >= I915_NUM_ENGINES)
+ return INVALID_OP;
+
+ d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
+ if (d_info == NULL)
+ return INVALID_OP;
+
+ return cmd >> (32 - d_info->op_len);
+}
+
+static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt,
+ unsigned int opcode, int ring_id)
+{
+ struct cmd_entry *e;
+
+ hash_for_each_possible(gvt->cmd_table, e, hlist, opcode) {
+ if ((opcode == e->info->opcode) &&
+ (e->info->rings & (1 << ring_id)))
+ return e->info;
+ }
+ return NULL;
+}
+
+static inline struct cmd_info *get_cmd_info(struct intel_gvt *gvt,
+ u32 cmd, int ring_id)
+{
+ u32 opcode;
+
+ opcode = get_opcode(cmd, ring_id);
+ if (opcode == INVALID_OP)
+ return NULL;
+
+ return find_cmd_entry(gvt, opcode, ring_id);
+}
+
+static inline u32 sub_op_val(u32 cmd, u32 hi, u32 low)
+{
+ return (cmd >> low) & ((1U << (hi - low + 1)) - 1);
+}
+
+static inline void print_opcode(u32 cmd, int ring_id)
+{
+ struct decode_info *d_info;
+ int i;
+
+ if (ring_id >= I915_NUM_ENGINES)
+ return;
+
+ d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
+ if (d_info == NULL)
+ return;
+
+ gvt_err("opcode=0x%x %s sub_ops:",
+ cmd >> (32 - d_info->op_len), d_info->name);
+
+ for (i = 0; i < d_info->nr_sub_op; i++)
+ pr_err("0x%x ", sub_op_val(cmd, d_info->sub_op[i].hi,
+ d_info->sub_op[i].low));
+
+ pr_err("\n");
+}
+
+static inline u32 *cmd_ptr(struct parser_exec_state *s, int index)
+{
+ return s->ip_va + (index << 2);
+}
+
+static inline u32 cmd_val(struct parser_exec_state *s, int index)
+{
+ return *cmd_ptr(s, index);
+}
+
+static void parser_exec_state_dump(struct parser_exec_state *s)
+{
+ int cnt = 0;
+ int i;
+
+ gvt_err(" vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)"
+ " ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id,
+ s->ring_id, s->ring_start, s->ring_start + s->ring_size,
+ s->ring_head, s->ring_tail);
+
+ gvt_err(" %s %s ip_gma(%08lx) ",
+ s->buf_type == RING_BUFFER_INSTRUCTION ?
+ "RING_BUFFER" : "BATCH_BUFFER",
+ s->buf_addr_type == GTT_BUFFER ?
+ "GTT" : "PPGTT", s->ip_gma);
+
+ if (s->ip_va == NULL) {
+ gvt_err(" ip_va(NULL)");
+ return;
+ }
+
+ gvt_err(" ip_va=%p: %08x %08x %08x %08x\n",
+ s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
+ cmd_val(s, 2), cmd_val(s, 3));
+
+ print_opcode(cmd_val(s, 0), s->ring_id);
+
+ /* print the whole page to trace */
+ pr_err(" ip_va=%p: %08x %08x %08x %08x\n",
+ s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
+ cmd_val(s, 2), cmd_val(s, 3));
+
+ s->ip_va = (u32 *)((((u64)s->ip_va) >> 12) << 12);
+
+ while (cnt < 1024) {
+ pr_err("ip_va=%p: ", s->ip_va);
+ for (i = 0; i < 8; i++)
+ pr_err("%08x ", cmd_val(s, i));
+ pr_err("\n");
+
+ s->ip_va += 8 * sizeof(u32);
+ cnt += 8;
+ }
+}
+
+static inline void update_ip_va(struct parser_exec_state *s)
+{
+ unsigned long len = 0;
+
+ if (WARN_ON(s->ring_head == s->ring_tail))
+ return;
+
+ if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+ unsigned long ring_top = s->ring_start + s->ring_size;
+
+ if (s->ring_head > s->ring_tail) {
+ if (s->ip_gma >= s->ring_head && s->ip_gma < ring_top)
+ len = (s->ip_gma - s->ring_head);
+ else if (s->ip_gma >= s->ring_start &&
+ s->ip_gma <= s->ring_tail)
+ len = (ring_top - s->ring_head) +
+ (s->ip_gma - s->ring_start);
+ } else
+ len = (s->ip_gma - s->ring_head);
+
+ s->ip_va = s->rb_va + len;
+ } else {/* shadow batch buffer */
+ s->ip_va = s->ret_bb_va;
+ }
+}
+
+static inline int ip_gma_set(struct parser_exec_state *s,
+ unsigned long ip_gma)
+{
+ WARN_ON(!IS_ALIGNED(ip_gma, 4));
+
+ s->ip_gma = ip_gma;
+ update_ip_va(s);
+ return 0;
+}
+
+static inline int ip_gma_advance(struct parser_exec_state *s,
+ unsigned int dw_len)
+{
+ s->ip_gma += (dw_len << 2);
+
+ if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+ if (s->ip_gma >= s->ring_start + s->ring_size)
+ s->ip_gma -= s->ring_size;
+ update_ip_va(s);
+ } else {
+ s->ip_va += (dw_len << 2);
+ }
+
+ return 0;
+}
+
+static inline int get_cmd_length(struct cmd_info *info, u32 cmd)
+{
+ if ((info->flag & F_LEN_MASK) == F_LEN_CONST)
+ return info->len;
+ else
+ return (cmd & ((1U << info->len) - 1)) + 2;
+ return 0;
+}
+
+static inline int cmd_length(struct parser_exec_state *s)
+{
+ return get_cmd_length(s->info, cmd_val(s, 0));
+}
+
+/* do not remove this, some platform may need clflush here */
+#define patch_value(s, addr, val) do { \
+ *addr = val; \
+} while (0)
+
+static bool is_shadowed_mmio(unsigned int offset)
+{
+ bool ret = false;
+
+ if ((offset == 0x2168) || /*BB current head register UDW */
+ (offset == 0x2140) || /*BB current header register */
+ (offset == 0x211c) || /*second BB header register UDW */
+ (offset == 0x2114)) { /*second BB header register UDW */
+ ret = true;
+ }
+ return ret;
+}
+
+static int cmd_reg_handler(struct parser_exec_state *s,
+ unsigned int offset, unsigned int index, char *cmd)
+{
+ struct intel_vgpu *vgpu = s->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+
+ if (offset + 4 > gvt->device_info.mmio_size) {
+ gvt_err("%s access to (%x) outside of MMIO range\n",
+ cmd, offset);
+ return -EINVAL;
+ }
+
+ if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) {
+ gvt_err("vgpu%d: %s access to non-render register (%x)\n",
+ s->vgpu->id, cmd, offset);
+ return 0;
+ }
+
+ if (is_shadowed_mmio(offset)) {
+ gvt_err("vgpu%d: found access of shadowed MMIO %x\n",
+ s->vgpu->id, offset);
+ return 0;
+ }
+
+ if (offset == i915_mmio_reg_offset(DERRMR) ||
+ offset == i915_mmio_reg_offset(FORCEWAKE_MT)) {
+ /* Writing to HW VGT_PVINFO_PAGE offset will be discarded */
+ patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE);
+ }
+
+ /* TODO: Update the global mask if this MMIO is a masked-MMIO */
+ intel_gvt_mmio_set_cmd_accessed(gvt, offset);
+ return 0;
+}
+
+#define cmd_reg(s, i) \
+ (cmd_val(s, i) & GENMASK(22, 2))
+
+#define cmd_reg_inhibit(s, i) \
+ (cmd_val(s, i) & GENMASK(22, 18))
+
+#define cmd_gma(s, i) \
+ (cmd_val(s, i) & GENMASK(31, 2))
+
+#define cmd_gma_hi(s, i) \
+ (cmd_val(s, i) & GENMASK(15, 0))
+
+static int cmd_handler_lri(struct parser_exec_state *s)
+{
+ int i, ret = 0;
+ int cmd_len = cmd_length(s);
+ struct intel_gvt *gvt = s->vgpu->gvt;
+
+ for (i = 1; i < cmd_len; i += 2) {
+ if (IS_BROADWELL(gvt->dev_priv) &&
+ (s->ring_id != RCS)) {
+ if (s->ring_id == BCS &&
+ cmd_reg(s, i) ==
+ i915_mmio_reg_offset(DERRMR))
+ ret |= 0;
+ else
+ ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0;
+ }
+ if (ret)
+ break;
+ ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lri");
+ }
+ return ret;
+}
+
+static int cmd_handler_lrr(struct parser_exec_state *s)
+{
+ int i, ret = 0;
+ int cmd_len = cmd_length(s);
+
+ for (i = 1; i < cmd_len; i += 2) {
+ if (IS_BROADWELL(s->vgpu->gvt->dev_priv))
+ ret |= ((cmd_reg_inhibit(s, i) ||
+ (cmd_reg_inhibit(s, i + 1)))) ?
+ -EINVAL : 0;
+ if (ret)
+ break;
+ ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrr-src");
+ ret |= cmd_reg_handler(s, cmd_reg(s, i + 1), i, "lrr-dst");
+ }
+ return ret;
+}
+
+static inline int cmd_address_audit(struct parser_exec_state *s,
+ unsigned long guest_gma, int op_size, bool index_mode);
+
+static int cmd_handler_lrm(struct parser_exec_state *s)
+{
+ struct intel_gvt *gvt = s->vgpu->gvt;
+ int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd;
+ unsigned long gma;
+ int i, ret = 0;
+ int cmd_len = cmd_length(s);
+
+ for (i = 1; i < cmd_len;) {
+ if (IS_BROADWELL(gvt->dev_priv))
+ ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0;
+ if (ret)
+ break;
+ ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrm");
+ if (cmd_val(s, 0) & (1 << 22)) {
+ gma = cmd_gma(s, i + 1);
+ if (gmadr_bytes == 8)
+ gma |= (cmd_gma_hi(s, i + 2)) << 32;
+ ret |= cmd_address_audit(s, gma, sizeof(u32), false);
+ }
+ i += gmadr_dw_number(s) + 1;
+ }
+ return ret;
+}
+
+static int cmd_handler_srm(struct parser_exec_state *s)
+{
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+ unsigned long gma;
+ int i, ret = 0;
+ int cmd_len = cmd_length(s);
+
+ for (i = 1; i < cmd_len;) {
+ ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "srm");
+ if (cmd_val(s, 0) & (1 << 22)) {
+ gma = cmd_gma(s, i + 1);
+ if (gmadr_bytes == 8)
+ gma |= (cmd_gma_hi(s, i + 2)) << 32;
+ ret |= cmd_address_audit(s, gma, sizeof(u32), false);
+ }
+ i += gmadr_dw_number(s) + 1;
+ }
+ return ret;
+}
+
+struct cmd_interrupt_event {
+ int pipe_control_notify;
+ int mi_flush_dw;
+ int mi_user_interrupt;
+};
+
+static struct cmd_interrupt_event cmd_interrupt_events[] = {
+ [RCS] = {
+ .pipe_control_notify = RCS_PIPE_CONTROL,
+ .mi_flush_dw = INTEL_GVT_EVENT_RESERVED,
+ .mi_user_interrupt = RCS_MI_USER_INTERRUPT,
+ },
+ [BCS] = {
+ .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+ .mi_flush_dw = BCS_MI_FLUSH_DW,
+ .mi_user_interrupt = BCS_MI_USER_INTERRUPT,
+ },
+ [VCS] = {
+ .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+ .mi_flush_dw = VCS_MI_FLUSH_DW,
+ .mi_user_interrupt = VCS_MI_USER_INTERRUPT,
+ },
+ [VCS2] = {
+ .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+ .mi_flush_dw = VCS2_MI_FLUSH_DW,
+ .mi_user_interrupt = VCS2_MI_USER_INTERRUPT,
+ },
+ [VECS] = {
+ .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+ .mi_flush_dw = VECS_MI_FLUSH_DW,
+ .mi_user_interrupt = VECS_MI_USER_INTERRUPT,
+ },
+};
+
+static int cmd_handler_pipe_control(struct parser_exec_state *s)
+{
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+ unsigned long gma;
+ bool index_mode = false;
+ unsigned int post_sync;
+ int ret = 0;
+
+ post_sync = (cmd_val(s, 1) & PIPE_CONTROL_POST_SYNC_OP_MASK) >> 14;
+
+ /* LRI post sync */
+ if (cmd_val(s, 1) & PIPE_CONTROL_MMIO_WRITE)
+ ret = cmd_reg_handler(s, cmd_reg(s, 2), 1, "pipe_ctrl");
+ /* post sync */
+ else if (post_sync) {
+ if (post_sync == 2)
+ ret = cmd_reg_handler(s, 0x2350, 1, "pipe_ctrl");
+ else if (post_sync == 3)
+ ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl");
+ else if (post_sync == 1) {
+ /* check ggtt*/
+ if ((cmd_val(s, 2) & (1 << 2))) {
+ gma = cmd_val(s, 2) & GENMASK(31, 3);
+ if (gmadr_bytes == 8)
+ gma |= (cmd_gma_hi(s, 3)) << 32;
+ /* Store Data Index */
+ if (cmd_val(s, 1) & (1 << 21))
+ index_mode = true;
+ ret |= cmd_address_audit(s, gma, sizeof(u64),
+ index_mode);
+ }
+ }
+ }
+
+ if (ret)
+ return ret;
+
+ if (cmd_val(s, 1) & PIPE_CONTROL_NOTIFY)
+ set_bit(cmd_interrupt_events[s->ring_id].pipe_control_notify,
+ s->workload->pending_events);
+ return 0;
+}
+
+static int cmd_handler_mi_user_interrupt(struct parser_exec_state *s)
+{
+ set_bit(cmd_interrupt_events[s->ring_id].mi_user_interrupt,
+ s->workload->pending_events);
+ return 0;
+}
+
+static int cmd_advance_default(struct parser_exec_state *s)
+{
+ return ip_gma_advance(s, cmd_length(s));
+}
+
+static int cmd_handler_mi_batch_buffer_end(struct parser_exec_state *s)
+{
+ int ret;
+
+ if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) {
+ s->buf_type = BATCH_BUFFER_INSTRUCTION;
+ ret = ip_gma_set(s, s->ret_ip_gma_bb);
+ s->buf_addr_type = s->saved_buf_addr_type;
+ } else {
+ s->buf_type = RING_BUFFER_INSTRUCTION;
+ s->buf_addr_type = GTT_BUFFER;
+ if (s->ret_ip_gma_ring >= s->ring_start + s->ring_size)
+ s->ret_ip_gma_ring -= s->ring_size;
+ ret = ip_gma_set(s, s->ret_ip_gma_ring);
+ }
+ return ret;
+}
+
+struct mi_display_flip_command_info {
+ int pipe;
+ int plane;
+ int event;
+ i915_reg_t stride_reg;
+ i915_reg_t ctrl_reg;
+ i915_reg_t surf_reg;
+ u64 stride_val;
+ u64 tile_val;
+ u64 surf_val;
+ bool async_flip;
+};
+
+struct plane_code_mapping {
+ int pipe;
+ int plane;
+ int event;
+};
+
+static int gen8_decode_mi_display_flip(struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+ struct plane_code_mapping gen8_plane_code[] = {
+ [0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE},
+ [1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE},
+ [2] = {PIPE_A, PLANE_B, SPRITE_A_FLIP_DONE},
+ [3] = {PIPE_B, PLANE_B, SPRITE_B_FLIP_DONE},
+ [4] = {PIPE_C, PLANE_A, PRIMARY_C_FLIP_DONE},
+ [5] = {PIPE_C, PLANE_B, SPRITE_C_FLIP_DONE},
+ };
+ u32 dword0, dword1, dword2;
+ u32 v;
+
+ dword0 = cmd_val(s, 0);
+ dword1 = cmd_val(s, 1);
+ dword2 = cmd_val(s, 2);
+
+ v = (dword0 & GENMASK(21, 19)) >> 19;
+ if (WARN_ON(v >= ARRAY_SIZE(gen8_plane_code)))
+ return -EINVAL;
+
+ info->pipe = gen8_plane_code[v].pipe;
+ info->plane = gen8_plane_code[v].plane;
+ info->event = gen8_plane_code[v].event;
+ info->stride_val = (dword1 & GENMASK(15, 6)) >> 6;
+ info->tile_val = (dword1 & 0x1);
+ info->surf_val = (dword2 & GENMASK(31, 12)) >> 12;
+ info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1);
+
+ if (info->plane == PLANE_A) {
+ info->ctrl_reg = DSPCNTR(info->pipe);
+ info->stride_reg = DSPSTRIDE(info->pipe);
+ info->surf_reg = DSPSURF(info->pipe);
+ } else if (info->plane == PLANE_B) {
+ info->ctrl_reg = SPRCTL(info->pipe);
+ info->stride_reg = SPRSTRIDE(info->pipe);
+ info->surf_reg = SPRSURF(info->pipe);
+ } else {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int skl_decode_mi_display_flip(struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+ u32 dword0 = cmd_val(s, 0);
+ u32 dword1 = cmd_val(s, 1);
+ u32 dword2 = cmd_val(s, 2);
+ u32 plane = (dword0 & GENMASK(12, 8)) >> 8;
+
+ switch (plane) {
+ case MI_DISPLAY_FLIP_SKL_PLANE_1_A:
+ info->pipe = PIPE_A;
+ info->event = PRIMARY_A_FLIP_DONE;
+ break;
+ case MI_DISPLAY_FLIP_SKL_PLANE_1_B:
+ info->pipe = PIPE_B;
+ info->event = PRIMARY_B_FLIP_DONE;
+ break;
+ case MI_DISPLAY_FLIP_SKL_PLANE_1_C:
+ info->pipe = PIPE_C;
+ info->event = PRIMARY_C_FLIP_DONE;
+ break;
+ default:
+ gvt_err("unknown plane code %d\n", plane);
+ return -EINVAL;
+ }
+
+ info->pipe = PRIMARY_PLANE;
+ info->stride_val = (dword1 & GENMASK(15, 6)) >> 6;
+ info->tile_val = (dword1 & GENMASK(2, 0));
+ info->surf_val = (dword2 & GENMASK(31, 12)) >> 12;
+ info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1);
+
+ info->ctrl_reg = DSPCNTR(info->pipe);
+ info->stride_reg = DSPSTRIDE(info->pipe);
+ info->surf_reg = DSPSURF(info->pipe);
+
+ return 0;
+}
+
+static int gen8_check_mi_display_flip(struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+ u32 stride, tile;
+
+ if (!info->async_flip)
+ return 0;
+
+ if (IS_SKYLAKE(dev_priv)) {
+ stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0);
+ tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) &
+ GENMASK(12, 10)) >> 10;
+ } else {
+ stride = (vgpu_vreg(s->vgpu, info->stride_reg) &
+ GENMASK(15, 6)) >> 6;
+ tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & (1 << 10)) >> 10;
+ }
+
+ if (stride != info->stride_val)
+ gvt_dbg_cmd("cannot change stride during async flip\n");
+
+ if (tile != info->tile_val)
+ gvt_dbg_cmd("cannot change tile during async flip\n");
+
+ return 0;
+}
+
+static int gen8_update_plane_mmio_from_mi_display_flip(
+ struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+ struct intel_vgpu *vgpu = s->vgpu;
+
+ set_mask_bits(&vgpu_vreg(vgpu, info->surf_reg), GENMASK(31, 12),
+ info->surf_val << 12);
+ if (IS_SKYLAKE(dev_priv)) {
+ set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(9, 0),
+ info->stride_val);
+ set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(12, 10),
+ info->tile_val << 10);
+ } else {
+ set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(15, 6),
+ info->stride_val << 6);
+ set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(10, 10),
+ info->tile_val << 10);
+ }
+
+ vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(info->pipe))++;
+ intel_vgpu_trigger_virtual_event(vgpu, info->event);
+ return 0;
+}
+
+static int decode_mi_display_flip(struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+ if (IS_BROADWELL(dev_priv))
+ return gen8_decode_mi_display_flip(s, info);
+ if (IS_SKYLAKE(dev_priv))
+ return skl_decode_mi_display_flip(s, info);
+
+ return -ENODEV;
+}
+
+static int check_mi_display_flip(struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+ if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+ return gen8_check_mi_display_flip(s, info);
+ return -ENODEV;
+}
+
+static int update_plane_mmio_from_mi_display_flip(
+ struct parser_exec_state *s,
+ struct mi_display_flip_command_info *info)
+{
+ struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+ if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+ return gen8_update_plane_mmio_from_mi_display_flip(s, info);
+ return -ENODEV;
+}
+
+static int cmd_handler_mi_display_flip(struct parser_exec_state *s)
+{
+ struct mi_display_flip_command_info info;
+ int ret;
+ int i;
+ int len = cmd_length(s);
+
+ ret = decode_mi_display_flip(s, &info);
+ if (ret) {
+ gvt_err("fail to decode MI display flip command\n");
+ return ret;
+ }
+
+ ret = check_mi_display_flip(s, &info);
+ if (ret) {
+ gvt_err("invalid MI display flip command\n");
+ return ret;
+ }
+
+ ret = update_plane_mmio_from_mi_display_flip(s, &info);
+ if (ret) {
+ gvt_err("fail to update plane mmio\n");
+ return ret;
+ }
+
+ for (i = 0; i < len; i++)
+ patch_value(s, cmd_ptr(s, i), MI_NOOP);
+ return 0;
+}
+
+static bool is_wait_for_flip_pending(u32 cmd)
+{
+ return cmd & (MI_WAIT_FOR_PLANE_A_FLIP_PENDING |
+ MI_WAIT_FOR_PLANE_B_FLIP_PENDING |
+ MI_WAIT_FOR_PLANE_C_FLIP_PENDING |
+ MI_WAIT_FOR_SPRITE_A_FLIP_PENDING |
+ MI_WAIT_FOR_SPRITE_B_FLIP_PENDING |
+ MI_WAIT_FOR_SPRITE_C_FLIP_PENDING);
+}
+
+static int cmd_handler_mi_wait_for_event(struct parser_exec_state *s)
+{
+ u32 cmd = cmd_val(s, 0);
+
+ if (!is_wait_for_flip_pending(cmd))
+ return 0;
+
+ patch_value(s, cmd_ptr(s, 0), MI_NOOP);
+ return 0;
+}
+
+static unsigned long get_gma_bb_from_cmd(struct parser_exec_state *s, int index)
+{
+ unsigned long addr;
+ unsigned long gma_high, gma_low;
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+
+ if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8))
+ return INTEL_GVT_INVALID_ADDR;
+
+ gma_low = cmd_val(s, index) & BATCH_BUFFER_ADDR_MASK;
+ if (gmadr_bytes == 4) {
+ addr = gma_low;
+ } else {
+ gma_high = cmd_val(s, index + 1) & BATCH_BUFFER_ADDR_HIGH_MASK;
+ addr = (((unsigned long)gma_high) << 32) | gma_low;
+ }
+ return addr;
+}
+
+static inline int cmd_address_audit(struct parser_exec_state *s,
+ unsigned long guest_gma, int op_size, bool index_mode)
+{
+ struct intel_vgpu *vgpu = s->vgpu;
+ u32 max_surface_size = vgpu->gvt->device_info.max_surface_size;
+ int i;
+ int ret;
+
+ if (op_size > max_surface_size) {
+ gvt_err("command address audit fail name %s\n", s->info->name);
+ return -EINVAL;
+ }
+
+ if (index_mode) {
+ if (guest_gma >= GTT_PAGE_SIZE / sizeof(u64)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) ||
+ (!vgpu_gmadr_is_valid(s->vgpu,
+ guest_gma + op_size - 1))) {
+ ret = -EINVAL;
+ goto err;
+ }
+ return 0;
+err:
+ gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
+ s->info->name, guest_gma, op_size);
+
+ pr_err("cmd dump: ");
+ for (i = 0; i < cmd_length(s); i++) {
+ if (!(i % 4))
+ pr_err("\n%08x ", cmd_val(s, i));
+ else
+ pr_err("%08x ", cmd_val(s, i));
+ }
+ pr_err("\nvgpu%d: aperture 0x%llx - 0x%llx, hidden 0x%llx - 0x%llx\n",
+ vgpu->id,
+ vgpu_aperture_gmadr_base(vgpu),
+ vgpu_aperture_gmadr_end(vgpu),
+ vgpu_hidden_gmadr_base(vgpu),
+ vgpu_hidden_gmadr_end(vgpu));
+ return ret;
+}
+
+static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s)
+{
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+ int op_size = (cmd_length(s) - 3) * sizeof(u32);
+ int core_id = (cmd_val(s, 2) & (1 << 0)) ? 1 : 0;
+ unsigned long gma, gma_low, gma_high;
+ int ret = 0;
+
+ /* check ppggt */
+ if (!(cmd_val(s, 0) & (1 << 22)))
+ return 0;
+
+ gma = cmd_val(s, 2) & GENMASK(31, 2);
+
+ if (gmadr_bytes == 8) {
+ gma_low = cmd_val(s, 1) & GENMASK(31, 2);
+ gma_high = cmd_val(s, 2) & GENMASK(15, 0);
+ gma = (gma_high << 32) | gma_low;
+ core_id = (cmd_val(s, 1) & (1 << 0)) ? 1 : 0;
+ }
+ ret = cmd_address_audit(s, gma + op_size * core_id, op_size, false);
+ return ret;
+}
+
+static inline int unexpected_cmd(struct parser_exec_state *s)
+{
+ gvt_err("vgpu%d: Unexpected %s in command buffer!\n",
+ s->vgpu->id, s->info->name);
+ return -EINVAL;
+}
+
+static int cmd_handler_mi_semaphore_wait(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_report_perf_count(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_op_2e(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_op_2f(struct parser_exec_state *s)
+{
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+ int op_size = (1 << ((cmd_val(s, 0) & GENMASK(20, 19)) >> 19)) *
+ sizeof(u32);
+ unsigned long gma, gma_high;
+ int ret = 0;
+
+ if (!(cmd_val(s, 0) & (1 << 22)))
+ return ret;
+
+ gma = cmd_val(s, 1) & GENMASK(31, 2);
+ if (gmadr_bytes == 8) {
+ gma_high = cmd_val(s, 2) & GENMASK(15, 0);
+ gma = (gma_high << 32) | gma;
+ }
+ ret = cmd_address_audit(s, gma, op_size, false);
+ return ret;
+}
+
+static int cmd_handler_mi_store_data_index(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_clflush(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_conditional_batch_buffer_end(
+ struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_update_gtt(struct parser_exec_state *s)
+{
+ return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_flush_dw(struct parser_exec_state *s)
+{
+ int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+ unsigned long gma;
+ bool index_mode = false;
+ int ret = 0;
+
+ /* Check post-sync and ppgtt bit */
+ if (((cmd_val(s, 0) >> 14) & 0x3) && (cmd_val(s, 1) & (1 << 2))) {
+ gma = cmd_val(s, 1) & GENMASK(31, 3);
+ if (gmadr_bytes == 8)
+ gma |= (cmd_val(s, 2) & GENMASK(15, 0)) << 32;
+ /* Store Data Index */
+ if (cmd_val(s, 0) & (1 << 21))
+ index_mode = true;
+ ret = cmd_address_audit(s, gma, sizeof(u64), index_mode);
+ }
+ /* Check notify bit */
+ if ((cmd_val(s, 0) & (1 << 8)))
+ set_bit(cmd_interrupt_events[s->ring_id].mi_flush_dw,
+ s->workload->pending_events);
+ return ret;
+}
+
+static void addr_type_update_snb(struct parser_exec_state *s)
+{
+ if ((s->buf_type == RING_BUFFER_INSTRUCTION) &&
+ (BATCH_BUFFER_ADR_SPACE_BIT(cmd_val(s, 0)) == 1)) {
+ s->buf_addr_type = PPGTT_BUFFER;
+ }
+}
+
+
+static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm,
+ unsigned long gma, unsigned long end_gma, void *va)
+{
+ unsigned long copy_len, offset;
+ unsigned long len = 0;
+ unsigned long gpa;
+
+ while (gma != end_gma) {
+ gpa = intel_vgpu_gma_to_gpa(mm, gma);
+ if (gpa == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("invalid gma address: %lx\n", gma);
+ return -EFAULT;
+ }
+
+ offset = gma & (GTT_PAGE_SIZE - 1);
+
+ copy_len = (end_gma - gma) >= (GTT_PAGE_SIZE - offset) ?
+ GTT_PAGE_SIZE - offset : end_gma - gma;
+
+ intel_gvt_hypervisor_read_gpa(vgpu, gpa, va + len, copy_len);
+
+ len += copy_len;
+ gma += copy_len;
+ }
+ return 0;
+}
+
+
+/*
+ * Check whether a batch buffer needs to be scanned. Currently
+ * the only criteria is based on privilege.
+ */
+static int batch_buffer_needs_scan(struct parser_exec_state *s)
+{
+ struct intel_gvt *gvt = s->vgpu->gvt;
+
+ if (bypass_batch_buffer_scan)
+ return 0;
+
+ if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+ /* BDW decides privilege based on address space */
+ if (cmd_val(s, 0) & (1 << 8))
+ return 0;
+ }
+ return 1;
+}
+
+static uint32_t find_bb_size(struct parser_exec_state *s)
+{
+ unsigned long gma = 0;
+ struct cmd_info *info;
+ uint32_t bb_size = 0;
+ uint32_t cmd_len = 0;
+ bool met_bb_end = false;
+ u32 cmd;
+
+ /* get the start gm address of the batch buffer */
+ gma = get_gma_bb_from_cmd(s, 1);
+ cmd = cmd_val(s, 0);
+
+ info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+ if (info == NULL) {
+ gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+ cmd, get_opcode(cmd, s->ring_id));
+ return -EINVAL;
+ }
+ do {
+ copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
+ gma, gma + 4, &cmd);
+ info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+ if (info == NULL) {
+ gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+ cmd, get_opcode(cmd, s->ring_id));
+ return -EINVAL;
+ }
+
+ if (info->opcode == OP_MI_BATCH_BUFFER_END) {
+ met_bb_end = true;
+ } else if (info->opcode == OP_MI_BATCH_BUFFER_START) {
+ if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) {
+ /* chained batch buffer */
+ met_bb_end = true;
+ }
+ }
+ cmd_len = get_cmd_length(info, cmd) << 2;
+ bb_size += cmd_len;
+ gma += cmd_len;
+
+ } while (!met_bb_end);
+
+ return bb_size;
+}
+
+static int perform_bb_shadow(struct parser_exec_state *s)
+{
+ struct intel_shadow_bb_entry *entry_obj;
+ unsigned long gma = 0;
+ uint32_t bb_size;
+ void *dst = NULL;
+ int ret = 0;
+
+ /* get the start gm address of the batch buffer */
+ gma = get_gma_bb_from_cmd(s, 1);
+
+ /* get the size of the batch buffer */
+ bb_size = find_bb_size(s);
+
+ /* allocate shadow batch buffer */
+ entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL);
+ if (entry_obj == NULL)
+ return -ENOMEM;
+
+ entry_obj->obj =
+ i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm),
+ roundup(bb_size, PAGE_SIZE));
+ if (IS_ERR(entry_obj->obj)) {
+ ret = PTR_ERR(entry_obj->obj);
+ goto free_entry;
+ }
+ entry_obj->len = bb_size;
+ INIT_LIST_HEAD(&entry_obj->list);
+
+ dst = i915_gem_object_pin_map(entry_obj->obj, I915_MAP_WB);
+ if (IS_ERR(dst)) {
+ ret = PTR_ERR(dst);
+ goto put_obj;
+ }
+
+ ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false);
+ if (ret) {
+ gvt_err("failed to set shadow batch to CPU\n");
+ goto unmap_src;
+ }
+
+ entry_obj->va = dst;
+ entry_obj->bb_start_cmd_va = s->ip_va;
+
+ /* copy batch buffer to shadow batch buffer*/
+ ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
+ gma, gma + bb_size,
+ dst);
+ if (ret) {
+ gvt_err("fail to copy guest ring buffer\n");
+ goto unmap_src;
+ }
+
+ list_add(&entry_obj->list, &s->workload->shadow_bb);
+ /*
+ * ip_va saves the virtual address of the shadow batch buffer, while
+ * ip_gma saves the graphics address of the original batch buffer.
+ * As the shadow batch buffer is just a copy from the originial one,
+ * it should be right to use shadow batch buffer'va and original batch
+ * buffer's gma in pair. After all, we don't want to pin the shadow
+ * buffer here (too early).
+ */
+ s->ip_va = dst;
+ s->ip_gma = gma;
+
+ return 0;
+
+unmap_src:
+ i915_gem_object_unpin_map(entry_obj->obj);
+put_obj:
+ i915_gem_object_put(entry_obj->obj);
+free_entry:
+ kfree(entry_obj);
+ return ret;
+}
+
+static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)
+{
+ bool second_level;
+ int ret = 0;
+
+ if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) {
+ gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n");
+ return -EINVAL;
+ }
+
+ second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1;
+ if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) {
+ gvt_err("Jumping to 2nd level BB from RB is not allowed\n");
+ return -EINVAL;
+ }
+
+ s->saved_buf_addr_type = s->buf_addr_type;
+ addr_type_update_snb(s);
+ if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+ s->ret_ip_gma_ring = s->ip_gma + cmd_length(s) * sizeof(u32);
+ s->buf_type = BATCH_BUFFER_INSTRUCTION;
+ } else if (second_level) {
+ s->buf_type = BATCH_BUFFER_2ND_LEVEL;
+ s->ret_ip_gma_bb = s->ip_gma + cmd_length(s) * sizeof(u32);
+ s->ret_bb_va = s->ip_va + cmd_length(s) * sizeof(u32);
+ }
+
+ if (batch_buffer_needs_scan(s)) {
+ ret = perform_bb_shadow(s);
+ if (ret < 0)
+ gvt_err("invalid shadow batch buffer\n");
+ } else {
+ /* emulate a batch buffer end to do return right */
+ ret = cmd_handler_mi_batch_buffer_end(s);
+ if (ret < 0)
+ return ret;
+ }
+
+ return ret;
+}
+
+static struct cmd_info cmd_info[] = {
+ {"MI_NOOP", OP_MI_NOOP, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+ {"MI_SET_PREDICATE", OP_MI_SET_PREDICATE, F_LEN_CONST, R_ALL, D_ALL,
+ 0, 1, NULL},
+
+ {"MI_USER_INTERRUPT", OP_MI_USER_INTERRUPT, F_LEN_CONST, R_ALL, D_ALL,
+ 0, 1, cmd_handler_mi_user_interrupt},
+
+ {"MI_WAIT_FOR_EVENT", OP_MI_WAIT_FOR_EVENT, F_LEN_CONST, R_RCS | R_BCS,
+ D_ALL, 0, 1, cmd_handler_mi_wait_for_event},
+
+ {"MI_FLUSH", OP_MI_FLUSH, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+ {"MI_ARB_CHECK", OP_MI_ARB_CHECK, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_RS_CONTROL", OP_MI_RS_CONTROL, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_REPORT_HEAD", OP_MI_REPORT_HEAD, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_ARB_ON_OFF", OP_MI_ARB_ON_OFF, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_URB_ATOMIC_ALLOC", OP_MI_URB_ATOMIC_ALLOC, F_LEN_CONST, R_RCS,
+ D_ALL, 0, 1, NULL},
+
+ {"MI_BATCH_BUFFER_END", OP_MI_BATCH_BUFFER_END,
+ F_IP_ADVANCE_CUSTOM | F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+ cmd_handler_mi_batch_buffer_end},
+
+ {"MI_SUSPEND_FLUSH", OP_MI_SUSPEND_FLUSH, F_LEN_CONST, R_ALL, D_ALL,
+ 0, 1, NULL},
+
+ {"MI_PREDICATE", OP_MI_PREDICATE, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_TOPOLOGY_FILTER", OP_MI_TOPOLOGY_FILTER, F_LEN_CONST, R_ALL,
+ D_ALL, 0, 1, NULL},
+
+ {"MI_SET_APPID", OP_MI_SET_APPID, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_RS_CONTEXT", OP_MI_RS_CONTEXT, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+ NULL},
+
+ {"MI_DISPLAY_FLIP", OP_MI_DISPLAY_FLIP, F_LEN_VAR | F_POST_HANDLE,
+ R_RCS | R_BCS, D_ALL, 0, 8, cmd_handler_mi_display_flip},
+
+ {"MI_SEMAPHORE_MBOX", OP_MI_SEMAPHORE_MBOX, F_LEN_VAR, R_ALL, D_ALL,
+ 0, 8, NULL},
+
+ {"MI_MATH", OP_MI_MATH, F_LEN_VAR, R_ALL, D_ALL, 0, 8, NULL},
+
+ {"MI_URB_CLEAR", OP_MI_URB_CLEAR, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"ME_SEMAPHORE_SIGNAL", OP_MI_SEMAPHORE_SIGNAL, F_LEN_VAR, R_ALL,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"ME_SEMAPHORE_WAIT", OP_MI_SEMAPHORE_WAIT, F_LEN_VAR, R_ALL, D_BDW_PLUS,
+ ADDR_FIX_1(2), 8, cmd_handler_mi_semaphore_wait},
+
+ {"MI_STORE_DATA_IMM", OP_MI_STORE_DATA_IMM, F_LEN_VAR, R_ALL, D_BDW_PLUS,
+ ADDR_FIX_1(1), 10, cmd_handler_mi_store_data_imm},
+
+ {"MI_STORE_DATA_INDEX", OP_MI_STORE_DATA_INDEX, F_LEN_VAR, R_ALL, D_ALL,
+ 0, 8, cmd_handler_mi_store_data_index},
+
+ {"MI_LOAD_REGISTER_IMM", OP_MI_LOAD_REGISTER_IMM, F_LEN_VAR, R_ALL,
+ D_ALL, 0, 8, cmd_handler_lri},
+
+ {"MI_UPDATE_GTT", OP_MI_UPDATE_GTT, F_LEN_VAR, R_ALL, D_BDW_PLUS, 0, 10,
+ cmd_handler_mi_update_gtt},
+
+ {"MI_STORE_REGISTER_MEM", OP_MI_STORE_REGISTER_MEM, F_LEN_VAR, R_ALL,
+ D_ALL, ADDR_FIX_1(2), 8, cmd_handler_srm},
+
+ {"MI_FLUSH_DW", OP_MI_FLUSH_DW, F_LEN_VAR, R_ALL, D_ALL, 0, 6,
+ cmd_handler_mi_flush_dw},
+
+ {"MI_CLFLUSH", OP_MI_CLFLUSH, F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(1),
+ 10, cmd_handler_mi_clflush},
+
+ {"MI_REPORT_PERF_COUNT", OP_MI_REPORT_PERF_COUNT, F_LEN_VAR, R_ALL,
+ D_ALL, ADDR_FIX_1(1), 6, cmd_handler_mi_report_perf_count},
+
+ {"MI_LOAD_REGISTER_MEM", OP_MI_LOAD_REGISTER_MEM, F_LEN_VAR, R_ALL,
+ D_ALL, ADDR_FIX_1(2), 8, cmd_handler_lrm},
+
+ {"MI_LOAD_REGISTER_REG", OP_MI_LOAD_REGISTER_REG, F_LEN_VAR, R_ALL,
+ D_ALL, 0, 8, cmd_handler_lrr},
+
+ {"MI_RS_STORE_DATA_IMM", OP_MI_RS_STORE_DATA_IMM, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"MI_LOAD_URB_MEM", OP_MI_LOAD_URB_MEM, F_LEN_VAR, R_RCS, D_ALL,
+ ADDR_FIX_1(2), 8, NULL},
+
+ {"MI_STORE_URM_MEM", OP_MI_STORE_URM_MEM, F_LEN_VAR, R_RCS, D_ALL,
+ ADDR_FIX_1(2), 8, NULL},
+
+ {"MI_OP_2E", OP_MI_2E, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_2(1, 2),
+ 8, cmd_handler_mi_op_2e},
+
+ {"MI_OP_2F", OP_MI_2F, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_1(1),
+ 8, cmd_handler_mi_op_2f},
+
+ {"MI_BATCH_BUFFER_START", OP_MI_BATCH_BUFFER_START,
+ F_IP_ADVANCE_CUSTOM, R_ALL, D_ALL, 0, 8,
+ cmd_handler_mi_batch_buffer_start},
+
+ {"MI_CONDITIONAL_BATCH_BUFFER_END", OP_MI_CONDITIONAL_BATCH_BUFFER_END,
+ F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(2), 8,
+ cmd_handler_mi_conditional_batch_buffer_end},
+
+ {"MI_LOAD_SCAN_LINES_INCL", OP_MI_LOAD_SCAN_LINES_INCL, F_LEN_CONST,
+ R_RCS | R_BCS, D_ALL, 0, 2, NULL},
+
+ {"XY_SETUP_BLT", OP_XY_SETUP_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_2(4, 7), 8, NULL},
+
+ {"XY_SETUP_CLIP_BLT", OP_XY_SETUP_CLIP_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ 0, 8, NULL},
+
+ {"XY_SETUP_MONO_PATTERN_SL_BLT", OP_XY_SETUP_MONO_PATTERN_SL_BLT,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_PIXEL_BLT", OP_XY_PIXEL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL},
+
+ {"XY_SCANLINES_BLT", OP_XY_SCANLINES_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ 0, 8, NULL},
+
+ {"XY_TEXT_BLT", OP_XY_TEXT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_1(3), 8, NULL},
+
+ {"XY_TEXT_IMMEDIATE_BLT", OP_XY_TEXT_IMMEDIATE_BLT, F_LEN_VAR, R_BCS,
+ D_ALL, 0, 8, NULL},
+
+ {"XY_COLOR_BLT", OP_XY_COLOR_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_PAT_BLT", OP_XY_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_2(4, 5), 8, NULL},
+
+ {"XY_MONO_PAT_BLT", OP_XY_MONO_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_SRC_COPY_BLT", OP_XY_SRC_COPY_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_2(4, 7), 8, NULL},
+
+ {"XY_MONO_SRC_COPY_BLT", OP_XY_MONO_SRC_COPY_BLT, F_LEN_VAR, R_BCS,
+ D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+ {"XY_FULL_BLT", OP_XY_FULL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL},
+
+ {"XY_FULL_MONO_SRC_BLT", OP_XY_FULL_MONO_SRC_BLT, F_LEN_VAR, R_BCS,
+ D_ALL, ADDR_FIX_3(4, 5, 8), 8, NULL},
+
+ {"XY_FULL_MONO_PATTERN_BLT", OP_XY_FULL_MONO_PATTERN_BLT, F_LEN_VAR,
+ R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+ {"XY_FULL_MONO_PATTERN_MONO_SRC_BLT",
+ OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+ {"XY_MONO_PAT_FIXED_BLT", OP_XY_MONO_PAT_FIXED_BLT, F_LEN_VAR, R_BCS,
+ D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_MONO_SRC_COPY_IMMEDIATE_BLT", OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_PAT_BLT_IMMEDIATE", OP_XY_PAT_BLT_IMMEDIATE, F_LEN_VAR, R_BCS,
+ D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+ {"XY_SRC_COPY_CHROMA_BLT", OP_XY_SRC_COPY_CHROMA_BLT, F_LEN_VAR, R_BCS,
+ D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+ {"XY_FULL_IMMEDIATE_PATTERN_BLT", OP_XY_FULL_IMMEDIATE_PATTERN_BLT,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+ {"XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT",
+ OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+ {"XY_PAT_CHROMA_BLT", OP_XY_PAT_CHROMA_BLT, F_LEN_VAR, R_BCS, D_ALL,
+ ADDR_FIX_2(4, 5), 8, NULL},
+
+ {"XY_PAT_CHROMA_BLT_IMMEDIATE", OP_XY_PAT_CHROMA_BLT_IMMEDIATE,
+ F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+ {"3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP",
+ OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_VIEWPORT_STATE_POINTERS_CC",
+ OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BLEND_STATE_POINTERS",
+ OP_3DSTATE_BLEND_STATE_POINTERS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DEPTH_STENCIL_STATE_POINTERS",
+ OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POINTERS_VS",
+ OP_3DSTATE_BINDING_TABLE_POINTERS_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POINTERS_HS",
+ OP_3DSTATE_BINDING_TABLE_POINTERS_HS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POINTERS_DS",
+ OP_3DSTATE_BINDING_TABLE_POINTERS_DS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POINTERS_GS",
+ OP_3DSTATE_BINDING_TABLE_POINTERS_GS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POINTERS_PS",
+ OP_3DSTATE_BINDING_TABLE_POINTERS_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_STATE_POINTERS_VS",
+ OP_3DSTATE_SAMPLER_STATE_POINTERS_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_STATE_POINTERS_HS",
+ OP_3DSTATE_SAMPLER_STATE_POINTERS_HS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_STATE_POINTERS_DS",
+ OP_3DSTATE_SAMPLER_STATE_POINTERS_DS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_STATE_POINTERS_GS",
+ OP_3DSTATE_SAMPLER_STATE_POINTERS_GS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_STATE_POINTERS_PS",
+ OP_3DSTATE_SAMPLER_STATE_POINTERS_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_URB_VS", OP_3DSTATE_URB_VS, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"3DSTATE_URB_HS", OP_3DSTATE_URB_HS, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"3DSTATE_URB_DS", OP_3DSTATE_URB_DS, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"3DSTATE_URB_GS", OP_3DSTATE_URB_GS, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"3DSTATE_GATHER_CONSTANT_VS", OP_3DSTATE_GATHER_CONSTANT_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GATHER_CONSTANT_GS", OP_3DSTATE_GATHER_CONSTANT_GS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GATHER_CONSTANT_HS", OP_3DSTATE_GATHER_CONSTANT_HS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GATHER_CONSTANT_DS", OP_3DSTATE_GATHER_CONSTANT_DS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GATHER_CONSTANT_PS", OP_3DSTATE_GATHER_CONSTANT_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_CONSTANTF_VS", OP_3DSTATE_DX9_CONSTANTF_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL},
+
+ {"3DSTATE_DX9_CONSTANTF_PS", OP_3DSTATE_DX9_CONSTANTF_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL},
+
+ {"3DSTATE_DX9_CONSTANTI_VS", OP_3DSTATE_DX9_CONSTANTI_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_CONSTANTI_PS", OP_3DSTATE_DX9_CONSTANTI_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_CONSTANTB_VS", OP_3DSTATE_DX9_CONSTANTB_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_CONSTANTB_PS", OP_3DSTATE_DX9_CONSTANTB_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_LOCAL_VALID_VS", OP_3DSTATE_DX9_LOCAL_VALID_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_LOCAL_VALID_PS", OP_3DSTATE_DX9_LOCAL_VALID_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_GENERATE_ACTIVE_VS", OP_3DSTATE_DX9_GENERATE_ACTIVE_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DX9_GENERATE_ACTIVE_PS", OP_3DSTATE_DX9_GENERATE_ACTIVE_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_EDIT_VS", OP_3DSTATE_BINDING_TABLE_EDIT_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_BINDING_TABLE_EDIT_GS", OP_3DSTATE_BINDING_TABLE_EDIT_GS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_BINDING_TABLE_EDIT_HS", OP_3DSTATE_BINDING_TABLE_EDIT_HS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_BINDING_TABLE_EDIT_DS", OP_3DSTATE_BINDING_TABLE_EDIT_DS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_BINDING_TABLE_EDIT_PS", OP_3DSTATE_BINDING_TABLE_EDIT_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_VF_INSTANCING", OP_3DSTATE_VF_INSTANCING, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_VF_SGVS", OP_3DSTATE_VF_SGVS, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+ NULL},
+
+ {"3DSTATE_VF_TOPOLOGY", OP_3DSTATE_VF_TOPOLOGY, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_WM_CHROMAKEY", OP_3DSTATE_WM_CHROMAKEY, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_PS_BLEND", OP_3DSTATE_PS_BLEND, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0,
+ 8, NULL},
+
+ {"3DSTATE_WM_DEPTH_STENCIL", OP_3DSTATE_WM_DEPTH_STENCIL, F_LEN_VAR,
+ R_RCS, D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_PS_EXTRA", OP_3DSTATE_PS_EXTRA, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0,
+ 8, NULL},
+
+ {"3DSTATE_RASTER", OP_3DSTATE_RASTER, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+ NULL},
+
+ {"3DSTATE_SBE_SWIZ", OP_3DSTATE_SBE_SWIZ, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+ NULL},
+
+ {"3DSTATE_WM_HZ_OP", OP_3DSTATE_WM_HZ_OP, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+ NULL},
+
+ {"3DSTATE_VERTEX_BUFFERS", OP_3DSTATE_VERTEX_BUFFERS, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_VERTEX_ELEMENTS", OP_3DSTATE_VERTEX_ELEMENTS, F_LEN_VAR,
+ R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_INDEX_BUFFER", OP_3DSTATE_INDEX_BUFFER, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, ADDR_FIX_1(2), 8, NULL},
+
+ {"3DSTATE_VF_STATISTICS", OP_3DSTATE_VF_STATISTICS, F_LEN_CONST,
+ R_RCS, D_ALL, 0, 1, NULL},
+
+ {"3DSTATE_VF", OP_3DSTATE_VF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CC_STATE_POINTERS", OP_3DSTATE_CC_STATE_POINTERS, F_LEN_VAR,
+ R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SCISSOR_STATE_POINTERS", OP_3DSTATE_SCISSOR_STATE_POINTERS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GS", OP_3DSTATE_GS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CLIP", OP_3DSTATE_CLIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_WM", OP_3DSTATE_WM, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CONSTANT_GS", OP_3DSTATE_CONSTANT_GS, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_CONSTANT_PS", OP_3DSTATE_CONSTANT_PS, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLE_MASK", OP_3DSTATE_SAMPLE_MASK, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CONSTANT_HS", OP_3DSTATE_CONSTANT_HS, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_CONSTANT_DS", OP_3DSTATE_CONSTANT_DS, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_HS", OP_3DSTATE_HS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_TE", OP_3DSTATE_TE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DS", OP_3DSTATE_DS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_STREAMOUT", OP_3DSTATE_STREAMOUT, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SBE", OP_3DSTATE_SBE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PS", OP_3DSTATE_PS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_DRAWING_RECTANGLE", OP_3DSTATE_DRAWING_RECTANGLE, F_LEN_VAR,
+ R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_PALETTE_LOAD0", OP_3DSTATE_SAMPLER_PALETTE_LOAD0,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CHROMA_KEY", OP_3DSTATE_CHROMA_KEY, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"3DSTATE_DEPTH_BUFFER", OP_3DSTATE_DEPTH_BUFFER, F_LEN_VAR, R_RCS,
+ D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+ {"3DSTATE_POLY_STIPPLE_OFFSET", OP_3DSTATE_POLY_STIPPLE_OFFSET,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_POLY_STIPPLE_PATTERN", OP_3DSTATE_POLY_STIPPLE_PATTERN,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_LINE_STIPPLE", OP_3DSTATE_LINE_STIPPLE, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_AA_LINE_PARAMS", OP_3DSTATE_AA_LINE_PARAMS, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_GS_SVB_INDEX", OP_3DSTATE_GS_SVB_INDEX, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SAMPLER_PALETTE_LOAD1", OP_3DSTATE_SAMPLER_PALETTE_LOAD1,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_MULTISAMPLE", OP_3DSTATE_MULTISAMPLE_BDW, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"3DSTATE_STENCIL_BUFFER", OP_3DSTATE_STENCIL_BUFFER, F_LEN_VAR, R_RCS,
+ D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+ {"3DSTATE_HIER_DEPTH_BUFFER", OP_3DSTATE_HIER_DEPTH_BUFFER, F_LEN_VAR,
+ R_RCS, D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+ {"3DSTATE_CLEAR_PARAMS", OP_3DSTATE_CLEAR_PARAMS, F_LEN_VAR,
+ R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PUSH_CONSTANT_ALLOC_VS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PUSH_CONSTANT_ALLOC_HS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PUSH_CONSTANT_ALLOC_DS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PUSH_CONSTANT_ALLOC_GS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_PUSH_CONSTANT_ALLOC_PS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_MONOFILTER_SIZE", OP_3DSTATE_MONOFILTER_SIZE, F_LEN_VAR,
+ R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SO_DECL_LIST", OP_3DSTATE_SO_DECL_LIST, F_LEN_VAR, R_RCS,
+ D_ALL, 0, 9, NULL},
+
+ {"3DSTATE_SO_BUFFER", OP_3DSTATE_SO_BUFFER, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+ ADDR_FIX_2(2, 4), 8, NULL},
+
+ {"3DSTATE_BINDING_TABLE_POOL_ALLOC",
+ OP_3DSTATE_BINDING_TABLE_POOL_ALLOC,
+ F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+ {"3DSTATE_GATHER_POOL_ALLOC", OP_3DSTATE_GATHER_POOL_ALLOC,
+ F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+ {"3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC",
+ OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC,
+ F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+ {"3DSTATE_SAMPLE_PATTERN", OP_3DSTATE_SAMPLE_PATTERN, F_LEN_VAR, R_RCS,
+ D_BDW_PLUS, 0, 8, NULL},
+
+ {"PIPE_CONTROL", OP_PIPE_CONTROL, F_LEN_VAR, R_RCS, D_ALL,
+ ADDR_FIX_1(2), 8, cmd_handler_pipe_control},
+
+ {"3DPRIMITIVE", OP_3DPRIMITIVE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"PIPELINE_SELECT", OP_PIPELINE_SELECT, F_LEN_CONST, R_RCS, D_ALL, 0,
+ 1, NULL},
+
+ {"STATE_PREFETCH", OP_STATE_PREFETCH, F_LEN_VAR, R_RCS, D_ALL,
+ ADDR_FIX_1(1), 8, NULL},
+
+ {"STATE_SIP", OP_STATE_SIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"STATE_BASE_ADDRESS", OP_STATE_BASE_ADDRESS, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+ ADDR_FIX_5(1, 3, 4, 5, 6), 8, NULL},
+
+ {"OP_3D_MEDIA_0_1_4", OP_3D_MEDIA_0_1_4, F_LEN_VAR, R_RCS, D_ALL,
+ ADDR_FIX_1(1), 8, NULL},
+
+ {"3DSTATE_VS", OP_3DSTATE_VS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_SF", OP_3DSTATE_SF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+ {"3DSTATE_CONSTANT_VS", OP_3DSTATE_CONSTANT_VS, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+ 0, 8, NULL},
+
+ {"3DSTATE_COMPONENT_PACKING", OP_3DSTATE_COMPONENT_PACKING, F_LEN_VAR, R_RCS,
+ D_SKL_PLUS, 0, 8, NULL},
+
+ {"MEDIA_INTERFACE_DESCRIPTOR_LOAD", OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD,
+ F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL},
+
+ {"MEDIA_GATEWAY_STATE", OP_MEDIA_GATEWAY_STATE, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 16, NULL},
+
+ {"MEDIA_STATE_FLUSH", OP_MEDIA_STATE_FLUSH, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 16, NULL},
+
+ {"MEDIA_OBJECT", OP_MEDIA_OBJECT, F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL},
+
+ {"MEDIA_CURBE_LOAD", OP_MEDIA_CURBE_LOAD, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 16, NULL},
+
+ {"MEDIA_OBJECT_PRT", OP_MEDIA_OBJECT_PRT, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 16, NULL},
+
+ {"MEDIA_OBJECT_WALKER", OP_MEDIA_OBJECT_WALKER, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 16, NULL},
+
+ {"GPGPU_WALKER", OP_GPGPU_WALKER, F_LEN_VAR, R_RCS, D_ALL,
+ 0, 8, NULL},
+
+ {"MEDIA_VFE_STATE", OP_MEDIA_VFE_STATE, F_LEN_VAR, R_RCS, D_ALL, 0, 16,
+ NULL},
+
+ {"3DSTATE_VF_STATISTICS_GM45", OP_3DSTATE_VF_STATISTICS_GM45,
+ F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+ {"MFX_PIPE_MODE_SELECT", OP_MFX_PIPE_MODE_SELECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_SURFACE_STATE", OP_MFX_SURFACE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_PIPE_BUF_ADDR_STATE", OP_MFX_PIPE_BUF_ADDR_STATE, F_LEN_VAR,
+ R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+ {"MFX_IND_OBJ_BASE_ADDR_STATE", OP_MFX_IND_OBJ_BASE_ADDR_STATE,
+ F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+ {"MFX_BSP_BUF_BASE_ADDR_STATE", OP_MFX_BSP_BUF_BASE_ADDR_STATE,
+ F_LEN_VAR, R_VCS, D_BDW_PLUS, ADDR_FIX_3(1, 3, 5), 12, NULL},
+
+ {"OP_2_0_0_5", OP_2_0_0_5, F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+ {"MFX_STATE_POINTER", OP_MFX_STATE_POINTER, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_QM_STATE", OP_MFX_QM_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_FQM_STATE", OP_MFX_FQM_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_PAK_INSERT_OBJECT", OP_MFX_PAK_INSERT_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_STITCH_OBJECT", OP_MFX_STITCH_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_IT_OBJECT", OP_MFD_IT_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_WAIT", OP_MFX_WAIT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 6, NULL},
+
+ {"MFX_AVC_IMG_STATE", OP_MFX_AVC_IMG_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_AVC_QM_STATE", OP_MFX_AVC_QM_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_AVC_DIRECTMODE_STATE", OP_MFX_AVC_DIRECTMODE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_AVC_SLICE_STATE", OP_MFX_AVC_SLICE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_AVC_REF_IDX_STATE", OP_MFX_AVC_REF_IDX_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_AVC_WEIGHTOFFSET_STATE", OP_MFX_AVC_WEIGHTOFFSET_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_AVC_PICID_STATE", OP_MFD_AVC_PICID_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+ {"MFD_AVC_DPB_STATE", OP_MFD_AVC_DPB_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_AVC_BSD_OBJECT", OP_MFD_AVC_BSD_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_AVC_SLICEADDR", OP_MFD_AVC_SLICEADDR, F_LEN_VAR,
+ R_VCS, D_ALL, ADDR_FIX_1(2), 12, NULL},
+
+ {"MFC_AVC_PAK_OBJECT", OP_MFC_AVC_PAK_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_VC1_PRED_PIPE_STATE", OP_MFX_VC1_PRED_PIPE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_VC1_DIRECTMODE_STATE", OP_MFX_VC1_DIRECTMODE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_VC1_SHORT_PIC_STATE", OP_MFD_VC1_SHORT_PIC_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_VC1_LONG_PIC_STATE", OP_MFD_VC1_LONG_PIC_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_VC1_BSD_OBJECT", OP_MFD_VC1_BSD_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFC_MPEG2_SLICEGROUP_STATE", OP_MFC_MPEG2_SLICEGROUP_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFC_MPEG2_PAK_OBJECT", OP_MFC_MPEG2_PAK_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_MPEG2_PIC_STATE", OP_MFX_MPEG2_PIC_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_MPEG2_QM_STATE", OP_MFX_MPEG2_QM_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_MPEG2_BSD_OBJECT", OP_MFD_MPEG2_BSD_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_2_6_0_0", OP_MFX_2_6_0_0, F_LEN_VAR, R_VCS, D_ALL,
+ 0, 16, NULL},
+
+ {"MFX_2_6_0_9", OP_MFX_2_6_0_9, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL},
+
+ {"MFX_2_6_0_8", OP_MFX_2_6_0_8, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL},
+
+ {"MFX_JPEG_PIC_STATE", OP_MFX_JPEG_PIC_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFX_JPEG_HUFF_TABLE_STATE", OP_MFX_JPEG_HUFF_TABLE_STATE, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"MFD_JPEG_BSD_OBJECT", OP_MFD_JPEG_BSD_OBJECT, F_LEN_VAR,
+ R_VCS, D_ALL, 0, 12, NULL},
+
+ {"VEBOX_STATE", OP_VEB_STATE, F_LEN_VAR, R_VECS, D_ALL, 0, 12, NULL},
+
+ {"VEBOX_SURFACE_STATE", OP_VEB_SURFACE_STATE, F_LEN_VAR, R_VECS, D_ALL,
+ 0, 12, NULL},
+
+ {"VEB_DI_IECP", OP_VEB_DNDI_IECP_STATE, F_LEN_VAR, R_VECS, D_BDW_PLUS,
+ 0, 20, NULL},
+};
+
+static void add_cmd_entry(struct intel_gvt *gvt, struct cmd_entry *e)
+{
+ hash_add(gvt->cmd_table, &e->hlist, e->info->opcode);
+}
+
+#define GVT_MAX_CMD_LENGTH 20 /* In Dword */
+
+static void trace_cs_command(struct parser_exec_state *s,
+ cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler)
+{
+ /* This buffer is used by ftrace to store all commands copied from
+ * guest gma space. Sometimes commands can cross pages, this should
+ * not be handled in ftrace logic. So this is just used as a
+ * 'bounce buffer'
+ */
+ u32 cmd_trace_buf[GVT_MAX_CMD_LENGTH];
+ int i;
+ u32 cmd_len = cmd_length(s);
+ /* The chosen value of GVT_MAX_CMD_LENGTH are just based on
+ * following two considerations:
+ * 1) From observation, most common ring commands is not that long.
+ * But there are execeptions. So it indeed makes sence to observe
+ * longer commands.
+ * 2) From the performance and debugging point of view, dumping all
+ * contents of very commands is not necessary.
+ * We mgith shrink GVT_MAX_CMD_LENGTH or remove this trace event in
+ * future for performance considerations.
+ */
+ if (unlikely(cmd_len > GVT_MAX_CMD_LENGTH)) {
+ gvt_dbg_cmd("cmd length exceed tracing limitation!\n");
+ cmd_len = GVT_MAX_CMD_LENGTH;
+ }
+
+ for (i = 0; i < cmd_len; i++)
+ cmd_trace_buf[i] = cmd_val(s, i);
+
+ trace_gvt_command(s->vgpu->id, s->ring_id, s->ip_gma, cmd_trace_buf,
+ cmd_len, s->buf_type == RING_BUFFER_INSTRUCTION,
+ cost_pre_cmd_handler, cost_cmd_handler);
+}
+
+/* call the cmd handler, and advance ip */
+static int cmd_parser_exec(struct parser_exec_state *s)
+{
+ struct cmd_info *info;
+ u32 cmd;
+ int ret = 0;
+ cycles_t t0, t1, t2;
+ struct parser_exec_state s_before_advance_custom;
+
+ t0 = get_cycles();
+
+ cmd = cmd_val(s, 0);
+
+ info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+ if (info == NULL) {
+ gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+ cmd, get_opcode(cmd, s->ring_id));
+ return -EINVAL;
+ }
+
+ gvt_dbg_cmd("%s\n", info->name);
+
+ s->info = info;
+
+ t1 = get_cycles();
+
+ memcpy(&s_before_advance_custom, s, sizeof(struct parser_exec_state));
+
+ if (info->handler) {
+ ret = info->handler(s);
+ if (ret < 0) {
+ gvt_err("%s handler error\n", info->name);
+ return ret;
+ }
+ }
+ t2 = get_cycles();
+
+ trace_cs_command(&s_before_advance_custom, t1 - t0, t2 - t1);
+
+ if (!(info->flag & F_IP_ADVANCE_CUSTOM)) {
+ ret = cmd_advance_default(s);
+ if (ret) {
+ gvt_err("%s IP advance error\n", info->name);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static inline bool gma_out_of_range(unsigned long gma,
+ unsigned long gma_head, unsigned int gma_tail)
+{
+ if (gma_tail >= gma_head)
+ return (gma < gma_head) || (gma > gma_tail);
+ else
+ return (gma > gma_tail) && (gma < gma_head);
+}
+
+static int command_scan(struct parser_exec_state *s,
+ unsigned long rb_head, unsigned long rb_tail,
+ unsigned long rb_start, unsigned long rb_len)
+{
+
+ unsigned long gma_head, gma_tail, gma_bottom;
+ int ret = 0;
+
+ gma_head = rb_start + rb_head;
+ gma_tail = rb_start + rb_tail;
+ gma_bottom = rb_start + rb_len;
+
+ gvt_dbg_cmd("scan_start: start=%lx end=%lx\n", gma_head, gma_tail);
+
+ while (s->ip_gma != gma_tail) {
+ if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+ if (!(s->ip_gma >= rb_start) ||
+ !(s->ip_gma < gma_bottom)) {
+ gvt_err("ip_gma %lx out of ring scope."
+ "(base:0x%lx, bottom: 0x%lx)\n",
+ s->ip_gma, rb_start,
+ gma_bottom);
+ parser_exec_state_dump(s);
+ return -EINVAL;
+ }
+ if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) {
+ gvt_err("ip_gma %lx out of range."
+ "base 0x%lx head 0x%lx tail 0x%lx\n",
+ s->ip_gma, rb_start,
+ rb_head, rb_tail);
+ parser_exec_state_dump(s);
+ break;
+ }
+ }
+ ret = cmd_parser_exec(s);
+ if (ret) {
+ gvt_err("cmd parser error\n");
+ parser_exec_state_dump(s);
+ break;
+ }
+ }
+
+ gvt_dbg_cmd("scan_end\n");
+
+ return ret;
+}
+
+static int scan_workload(struct intel_vgpu_workload *workload)
+{
+ unsigned long gma_head, gma_tail, gma_bottom;
+ struct parser_exec_state s;
+ int ret = 0;
+
+ /* ring base is page aligned */
+ if (WARN_ON(!IS_ALIGNED(workload->rb_start, GTT_PAGE_SIZE)))
+ return -EINVAL;
+
+ gma_head = workload->rb_start + workload->rb_head;
+ gma_tail = workload->rb_start + workload->rb_tail;
+ gma_bottom = workload->rb_start + _RING_CTL_BUF_SIZE(workload->rb_ctl);
+
+ s.buf_type = RING_BUFFER_INSTRUCTION;
+ s.buf_addr_type = GTT_BUFFER;
+ s.vgpu = workload->vgpu;
+ s.ring_id = workload->ring_id;
+ s.ring_start = workload->rb_start;
+ s.ring_size = _RING_CTL_BUF_SIZE(workload->rb_ctl);
+ s.ring_head = gma_head;
+ s.ring_tail = gma_tail;
+ s.rb_va = workload->shadow_ring_buffer_va;
+ s.workload = workload;
+
+ if ((bypass_scan_mask & (1 << workload->ring_id)) ||
+ gma_head == gma_tail)
+ return 0;
+
+ ret = ip_gma_set(&s, gma_head);
+ if (ret)
+ goto out;
+
+ ret = command_scan(&s, workload->rb_head, workload->rb_tail,
+ workload->rb_start, _RING_CTL_BUF_SIZE(workload->rb_ctl));
+
+out:
+ return ret;
+}
+
+static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+
+ unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail;
+ struct parser_exec_state s;
+ int ret = 0;
+
+ /* ring base is page aligned */
+ if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE)))
+ return -EINVAL;
+
+ ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t);
+ ring_size = round_up(wa_ctx->indirect_ctx.size + CACHELINE_BYTES,
+ PAGE_SIZE);
+ gma_head = wa_ctx->indirect_ctx.guest_gma;
+ gma_tail = wa_ctx->indirect_ctx.guest_gma + ring_tail;
+ gma_bottom = wa_ctx->indirect_ctx.guest_gma + ring_size;
+
+ s.buf_type = RING_BUFFER_INSTRUCTION;
+ s.buf_addr_type = GTT_BUFFER;
+ s.vgpu = wa_ctx->workload->vgpu;
+ s.ring_id = wa_ctx->workload->ring_id;
+ s.ring_start = wa_ctx->indirect_ctx.guest_gma;
+ s.ring_size = ring_size;
+ s.ring_head = gma_head;
+ s.ring_tail = gma_tail;
+ s.rb_va = wa_ctx->indirect_ctx.shadow_va;
+ s.workload = wa_ctx->workload;
+
+ ret = ip_gma_set(&s, gma_head);
+ if (ret)
+ goto out;
+
+ ret = command_scan(&s, 0, ring_tail,
+ wa_ctx->indirect_ctx.guest_gma, ring_size);
+out:
+ return ret;
+}
+
+static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ int ring_id = workload->ring_id;
+ struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx;
+ struct intel_ring *ring = shadow_ctx->engine[ring_id].ring;
+ unsigned long gma_head, gma_tail, gma_top, guest_rb_size;
+ unsigned int copy_len = 0;
+ int ret;
+
+ guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl);
+
+ /* calculate workload ring buffer size */
+ workload->rb_len = (workload->rb_tail + guest_rb_size -
+ workload->rb_head) % guest_rb_size;
+
+ gma_head = workload->rb_start + workload->rb_head;
+ gma_tail = workload->rb_start + workload->rb_tail;
+ gma_top = workload->rb_start + guest_rb_size;
+
+ /* allocate shadow ring buffer */
+ ret = intel_ring_begin(workload->req, workload->rb_len / 4);
+ if (ret)
+ return ret;
+
+ /* get shadow ring buffer va */
+ workload->shadow_ring_buffer_va = ring->vaddr + ring->tail;
+
+ /* head > tail --> copy head <-> top */
+ if (gma_head > gma_tail) {
+ ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
+ gma_head, gma_top,
+ workload->shadow_ring_buffer_va);
+ if (ret) {
+ gvt_err("fail to copy guest ring buffer\n");
+ return ret;
+ }
+ copy_len = gma_top - gma_head;
+ gma_head = workload->rb_start;
+ }
+
+ /* copy head or start <-> tail */
+ ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
+ gma_head, gma_tail,
+ workload->shadow_ring_buffer_va + copy_len);
+ if (ret) {
+ gvt_err("fail to copy guest ring buffer\n");
+ return ret;
+ }
+ ring->tail += workload->rb_len;
+ intel_ring_advance(ring);
+ return 0;
+}
+
+int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
+{
+ int ret;
+
+ ret = shadow_workload_ring_buffer(workload);
+ if (ret) {
+ gvt_err("fail to shadow workload ring_buffer\n");
+ return ret;
+ }
+
+ ret = scan_workload(workload);
+ if (ret) {
+ gvt_err("scan workload error\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ struct drm_device *dev = &wa_ctx->workload->vgpu->gvt->dev_priv->drm;
+ int ctx_size = wa_ctx->indirect_ctx.size;
+ unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma;
+ struct drm_i915_gem_object *obj;
+ int ret = 0;
+ void *map;
+
+ obj = i915_gem_object_create(dev,
+ roundup(ctx_size + CACHELINE_BYTES,
+ PAGE_SIZE));
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ /* get the va of the shadow batch buffer */
+ map = i915_gem_object_pin_map(obj, I915_MAP_WB);
+ if (IS_ERR(map)) {
+ gvt_err("failed to vmap shadow indirect ctx\n");
+ ret = PTR_ERR(map);
+ goto put_obj;
+ }
+
+ ret = i915_gem_object_set_to_cpu_domain(obj, false);
+ if (ret) {
+ gvt_err("failed to set shadow indirect ctx to CPU\n");
+ goto unmap_src;
+ }
+
+ ret = copy_gma_to_hva(wa_ctx->workload->vgpu,
+ wa_ctx->workload->vgpu->gtt.ggtt_mm,
+ guest_gma, guest_gma + ctx_size,
+ map);
+ if (ret) {
+ gvt_err("fail to copy guest indirect ctx\n");
+ goto unmap_src;
+ }
+
+ wa_ctx->indirect_ctx.obj = obj;
+ wa_ctx->indirect_ctx.shadow_va = map;
+ return 0;
+
+unmap_src:
+ i915_gem_object_unpin_map(obj);
+put_obj:
+ i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+ return ret;
+}
+
+static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ uint32_t per_ctx_start[CACHELINE_DWORDS] = {0};
+ unsigned char *bb_start_sva;
+
+ per_ctx_start[0] = 0x18800001;
+ per_ctx_start[1] = wa_ctx->per_ctx.guest_gma;
+
+ bb_start_sva = (unsigned char *)wa_ctx->indirect_ctx.shadow_va +
+ wa_ctx->indirect_ctx.size;
+
+ memcpy(bb_start_sva, per_ctx_start, CACHELINE_BYTES);
+
+ return 0;
+}
+
+int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ int ret;
+
+ if (wa_ctx->indirect_ctx.size == 0)
+ return 0;
+
+ ret = shadow_indirect_ctx(wa_ctx);
+ if (ret) {
+ gvt_err("fail to shadow indirect ctx\n");
+ return ret;
+ }
+
+ combine_wa_ctx(wa_ctx);
+
+ ret = scan_wa_ctx(wa_ctx);
+ if (ret) {
+ gvt_err("scan wa ctx error\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt,
+ unsigned int opcode, int rings)
+{
+ struct cmd_info *info = NULL;
+ unsigned int ring;
+
+ for_each_set_bit(ring, (unsigned long *)&rings, I915_NUM_ENGINES) {
+ info = find_cmd_entry(gvt, opcode, ring);
+ if (info)
+ break;
+ }
+ return info;
+}
+
+static int init_cmd_table(struct intel_gvt *gvt)
+{
+ int i;
+ struct cmd_entry *e;
+ struct cmd_info *info;
+ unsigned int gen_type;
+
+ gen_type = intel_gvt_get_device_type(gvt);
+
+ for (i = 0; i < ARRAY_SIZE(cmd_info); i++) {
+ if (!(cmd_info[i].devices & gen_type))
+ continue;
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+
+ e->info = &cmd_info[i];
+ info = find_cmd_entry_any_ring(gvt,
+ e->info->opcode, e->info->rings);
+ if (info) {
+ gvt_err("%s %s duplicated\n", e->info->name,
+ info->name);
+ return -EEXIST;
+ }
+
+ INIT_HLIST_NODE(&e->hlist);
+ add_cmd_entry(gvt, e);
+ gvt_dbg_cmd("add %-30s op %04x flag %x devs %02x rings %02x\n",
+ e->info->name, e->info->opcode, e->info->flag,
+ e->info->devices, e->info->rings);
+ }
+ return 0;
+}
+
+static void clean_cmd_table(struct intel_gvt *gvt)
+{
+ struct hlist_node *tmp;
+ struct cmd_entry *e;
+ int i;
+
+ hash_for_each_safe(gvt->cmd_table, i, tmp, e, hlist)
+ kfree(e);
+
+ hash_init(gvt->cmd_table);
+}
+
+void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt)
+{
+ clean_cmd_table(gvt);
+}
+
+int intel_gvt_init_cmd_parser(struct intel_gvt *gvt)
+{
+ int ret;
+
+ ret = init_cmd_table(gvt);
+ if (ret) {
+ intel_gvt_clean_cmd_parser(gvt);
+ return ret;
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.h b/drivers/gpu/drm/i915/gvt/cmd_parser.h
new file mode 100644
index 000000000000..bed33514103c
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Kevin Tian <kevin.tian@intel.com>
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Yulei Zhang <yulei.zhang@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+#ifndef _GVT_CMD_PARSER_H_
+#define _GVT_CMD_PARSER_H_
+
+#define GVT_CMD_HASH_BITS 7
+
+void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt);
+
+int intel_gvt_init_cmd_parser(struct intel_gvt *gvt);
+
+int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
+
+int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h
index 7ef412be665f..68cba7bd980a 100644
--- a/drivers/gpu/drm/i915/gvt/debug.h
+++ b/drivers/gpu/drm/i915/gvt/debug.h
@@ -24,11 +24,34 @@
#ifndef __GVT_DEBUG_H__
#define __GVT_DEBUG_H__
+#define gvt_err(fmt, args...) \
+ DRM_ERROR("gvt: "fmt, ##args)
+
#define gvt_dbg_core(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args)
-/*
- * Other GVT debug stuff will be introduced in the GVT device model patches.
- */
+#define gvt_dbg_irq(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args)
+
+#define gvt_dbg_mm(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args)
+
+#define gvt_dbg_mmio(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args)
+
+#define gvt_dbg_dpy(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args)
+
+#define gvt_dbg_el(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args)
+
+#define gvt_dbg_sched(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args)
+
+#define gvt_dbg_render(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args)
+
+#define gvt_dbg_cmd(fmt, args...) \
+ DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args)
#endif
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
new file mode 100644
index 000000000000..c0c884aeb30e
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Terrence Xu <terrence.xu@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static int get_edp_pipe(struct intel_vgpu *vgpu)
+{
+ u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP);
+ int pipe = -1;
+
+ switch (data & TRANS_DDI_EDP_INPUT_MASK) {
+ case TRANS_DDI_EDP_INPUT_A_ON:
+ case TRANS_DDI_EDP_INPUT_A_ONOFF:
+ pipe = PIPE_A;
+ break;
+ case TRANS_DDI_EDP_INPUT_B_ONOFF:
+ pipe = PIPE_B;
+ break;
+ case TRANS_DDI_EDP_INPUT_C_ONOFF:
+ pipe = PIPE_C;
+ break;
+ }
+ return pipe;
+}
+
+static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ if (!(vgpu_vreg(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE))
+ return 0;
+
+ if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE))
+ return 0;
+ return 1;
+}
+
+static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES))
+ return -EINVAL;
+
+ if (vgpu_vreg(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE)
+ return 1;
+
+ if (edp_pipe_is_enabled(vgpu) &&
+ get_edp_pipe(vgpu) == pipe)
+ return 1;
+ return 0;
+}
+
+/* EDID with 1024x768 as its resolution */
+static unsigned char virtual_dp_monitor_edid[] = {
+ /*Header*/
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ /* Vendor & Product Identification */
+ 0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17,
+ /* Version & Revision */
+ 0x01, 0x04,
+ /* Basic Display Parameters & Features */
+ 0xa5, 0x34, 0x20, 0x78, 0x23,
+ /* Color Characteristics */
+ 0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54,
+ /* Established Timings: maximum resolution is 1024x768 */
+ 0x21, 0x08, 0x00,
+ /* Standard Timings. All invalid */
+ 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x01,
+ /* 18 Byte Data Blocks 1: invalid */
+ 0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0,
+ 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a,
+ /* 18 Byte Data Blocks 2: invalid */
+ 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ /* 18 Byte Data Blocks 3: invalid */
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
+ 0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20,
+ /* 18 Byte Data Blocks 4: invalid */
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30,
+ 0x44, 0x58, 0x51, 0x0a, 0x20, 0x20,
+ /* Extension Block Count */
+ 0x00,
+ /* Checksum */
+ 0xef,
+};
+
+#define DPCD_HEADER_SIZE 0xb
+
+static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = {
+ 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT |
+ SDE_PORTC_HOTPLUG_CPT |
+ SDE_PORTD_HOTPLUG_CPT);
+
+ if (IS_SKYLAKE(dev_priv))
+ vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
+ SDE_PORTE_HOTPLUG_SPT);
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B))
+ vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C))
+ vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D))
+ vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
+
+ if (IS_SKYLAKE(dev_priv) &&
+ intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
+ vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT;
+ }
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+ if (IS_BROADWELL(dev_priv))
+ vgpu_vreg(vgpu, GEN8_DE_PORT_ISR) |=
+ GEN8_PORT_DP_A_HOTPLUG;
+ else
+ vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT;
+ }
+}
+
+static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)
+{
+ struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
+
+ kfree(port->edid);
+ port->edid = NULL;
+
+ kfree(port->dpcd);
+ port->dpcd = NULL;
+}
+
+static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
+ int type)
+{
+ struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
+
+ port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);
+ if (!port->edid)
+ return -ENOMEM;
+
+ port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL);
+ if (!port->dpcd) {
+ kfree(port->edid);
+ return -ENOMEM;
+ }
+
+ memcpy(port->edid->edid_block, virtual_dp_monitor_edid,
+ EDID_SIZE);
+ port->edid->data_valid = true;
+
+ memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE);
+ port->dpcd->data_valid = true;
+ port->dpcd->data[DPCD_SINK_COUNT] = 0x1;
+ port->type = type;
+
+ emulate_monitor_status_change(vgpu);
+ return 0;
+}
+
+/**
+ * intel_gvt_check_vblank_emulation - check if vblank emulation timer should
+ * be turned on/off when a virtual pipe is enabled/disabled.
+ * @gvt: a GVT device
+ *
+ * This function is used to turn on/off vblank timer according to currently
+ * enabled/disabled virtual pipes.
+ *
+ */
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt)
+{
+ struct intel_gvt_irq *irq = &gvt->irq;
+ struct intel_vgpu *vgpu;
+ bool have_enabled_pipe = false;
+ int pipe, id;
+
+ if (WARN_ON(!mutex_is_locked(&gvt->lock)))
+ return;
+
+ hrtimer_cancel(&irq->vblank_timer.timer);
+
+ for_each_active_vgpu(gvt, vgpu, id) {
+ for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
+ have_enabled_pipe =
+ pipe_is_enabled(vgpu, pipe);
+ if (have_enabled_pipe)
+ break;
+ }
+ }
+
+ if (have_enabled_pipe)
+ hrtimer_start(&irq->vblank_timer.timer,
+ ktime_add_ns(ktime_get(), irq->vblank_timer.period),
+ HRTIMER_MODE_ABS);
+}
+
+static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct intel_vgpu_irq *irq = &vgpu->irq;
+ int vblank_event[] = {
+ [PIPE_A] = PIPE_A_VBLANK,
+ [PIPE_B] = PIPE_B_VBLANK,
+ [PIPE_C] = PIPE_C_VBLANK,
+ };
+ int event;
+
+ if (pipe < PIPE_A || pipe > PIPE_C)
+ return;
+
+ for_each_set_bit(event, irq->flip_done_event[pipe],
+ INTEL_GVT_EVENT_MAX) {
+ clear_bit(event, irq->flip_done_event[pipe]);
+ if (!pipe_is_enabled(vgpu, pipe))
+ continue;
+
+ vgpu_vreg(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++;
+ intel_vgpu_trigger_virtual_event(vgpu, event);
+ }
+
+ if (pipe_is_enabled(vgpu, pipe)) {
+ vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(pipe))++;
+ intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]);
+ }
+}
+
+static void emulate_vblank(struct intel_vgpu *vgpu)
+{
+ int pipe;
+
+ for_each_pipe(vgpu->gvt->dev_priv, pipe)
+ emulate_vblank_on_pipe(vgpu, pipe);
+}
+
+/**
+ * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device
+ * @gvt: a GVT device
+ *
+ * This function is used to trigger vblank interrupts for vGPUs on GVT device
+ *
+ */
+void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
+{
+ struct intel_vgpu *vgpu;
+ int id;
+
+ if (WARN_ON(!mutex_is_locked(&gvt->lock)))
+ return;
+
+ for_each_active_vgpu(gvt, vgpu, id)
+ emulate_vblank(vgpu);
+}
+
+/**
+ * intel_vgpu_clean_display - clean vGPU virtual display emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to clean vGPU virtual display emulation stuffs
+ *
+ */
+void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ if (IS_SKYLAKE(dev_priv))
+ clean_virtual_dp_monitor(vgpu, PORT_D);
+ else
+ clean_virtual_dp_monitor(vgpu, PORT_B);
+}
+
+/**
+ * intel_vgpu_init_display- initialize vGPU virtual display emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize vGPU virtual display emulation stuffs
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_init_display(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ intel_vgpu_init_i2c_edid(vgpu);
+
+ if (IS_SKYLAKE(dev_priv))
+ return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D);
+ else
+ return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B);
+}
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
new file mode 100644
index 000000000000..7a60cb848268
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Terrence Xu <terrence.xu@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_DISPLAY_H_
+#define _GVT_DISPLAY_H_
+
+#define SBI_REG_MAX 20
+#define DPCD_SIZE 0x700
+
+#define intel_vgpu_port(vgpu, port) \
+ (&(vgpu->display.ports[port]))
+
+#define intel_vgpu_has_monitor_on_port(vgpu, port) \
+ (intel_vgpu_port(vgpu, port)->edid && \
+ intel_vgpu_port(vgpu, port)->edid->data_valid)
+
+#define intel_vgpu_port_is_dp(vgpu, port) \
+ ((intel_vgpu_port(vgpu, port)->type == GVT_DP_A) || \
+ (intel_vgpu_port(vgpu, port)->type == GVT_DP_B) || \
+ (intel_vgpu_port(vgpu, port)->type == GVT_DP_C) || \
+ (intel_vgpu_port(vgpu, port)->type == GVT_DP_D))
+
+#define INTEL_GVT_MAX_UEVENT_VARS 3
+
+/* DPCD start */
+#define DPCD_SIZE 0x700
+
+/* DPCD */
+#define DP_SET_POWER 0x600
+#define DP_SET_POWER_D0 0x1
+#define AUX_NATIVE_WRITE 0x8
+#define AUX_NATIVE_READ 0x9
+
+#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
+#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
+#define AUX_NATIVE_REPLY_NAK (0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
+
+#define AUX_BURST_SIZE 16
+
+/* DPCD addresses */
+#define DPCD_REV 0x000
+#define DPCD_MAX_LINK_RATE 0x001
+#define DPCD_MAX_LANE_COUNT 0x002
+
+#define DPCD_TRAINING_PATTERN_SET 0x102
+#define DPCD_SINK_COUNT 0x200
+#define DPCD_LANE0_1_STATUS 0x202
+#define DPCD_LANE2_3_STATUS 0x203
+#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204
+#define DPCD_SINK_STATUS 0x205
+
+/* link training */
+#define DPCD_TRAINING_PATTERN_SET_MASK 0x03
+#define DPCD_LINK_TRAINING_DISABLED 0x00
+#define DPCD_TRAINING_PATTERN_1 0x01
+#define DPCD_TRAINING_PATTERN_2 0x02
+
+#define DPCD_CP_READY_MASK (1 << 6)
+
+/* lane status */
+#define DPCD_LANES_CR_DONE 0x11
+#define DPCD_LANES_EQ_DONE 0x22
+#define DPCD_SYMBOL_LOCKED 0x44
+
+#define DPCD_INTERLANE_ALIGN_DONE 0x01
+
+#define DPCD_SINK_IN_SYNC 0x03
+/* DPCD end */
+
+#define SBI_RESPONSE_MASK 0x3
+#define SBI_RESPONSE_SHIFT 0x1
+#define SBI_STAT_MASK 0x1
+#define SBI_STAT_SHIFT 0x0
+#define SBI_OPCODE_SHIFT 8
+#define SBI_OPCODE_MASK (0xff << SBI_OPCODE_SHIFT)
+#define SBI_CMD_IORD 2
+#define SBI_CMD_IOWR 3
+#define SBI_CMD_CRRD 6
+#define SBI_CMD_CRWR 7
+#define SBI_ADDR_OFFSET_SHIFT 16
+#define SBI_ADDR_OFFSET_MASK (0xffff << SBI_ADDR_OFFSET_SHIFT)
+
+struct intel_vgpu_sbi_register {
+ unsigned int offset;
+ u32 value;
+};
+
+struct intel_vgpu_sbi {
+ int number;
+ struct intel_vgpu_sbi_register registers[SBI_REG_MAX];
+};
+
+enum intel_gvt_plane_type {
+ PRIMARY_PLANE = 0,
+ CURSOR_PLANE,
+ SPRITE_PLANE,
+ MAX_PLANE
+};
+
+struct intel_vgpu_dpcd_data {
+ bool data_valid;
+ u8 data[DPCD_SIZE];
+};
+
+enum intel_vgpu_port_type {
+ GVT_CRT = 0,
+ GVT_DP_A,
+ GVT_DP_B,
+ GVT_DP_C,
+ GVT_DP_D,
+ GVT_HDMI_B,
+ GVT_HDMI_C,
+ GVT_HDMI_D,
+ GVT_PORT_MAX
+};
+
+struct intel_vgpu_port {
+ /* per display EDID information */
+ struct intel_vgpu_edid_data *edid;
+ /* per display DPCD information */
+ struct intel_vgpu_dpcd_data *dpcd;
+ int type;
+};
+
+void intel_gvt_emulate_vblank(struct intel_gvt *gvt);
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt);
+
+int intel_vgpu_init_display(struct intel_vgpu *vgpu);
+void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
new file mode 100644
index 000000000000..bda85dff7b2a
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/edid.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Terrence Xu <terrence.xu@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define GMBUS1_TOTAL_BYTES_SHIFT 16
+#define GMBUS1_TOTAL_BYTES_MASK 0x1ff
+#define gmbus1_total_byte_count(v) (((v) >> \
+ GMBUS1_TOTAL_BYTES_SHIFT) & GMBUS1_TOTAL_BYTES_MASK)
+#define gmbus1_slave_addr(v) (((v) & 0xff) >> 1)
+#define gmbus1_slave_index(v) (((v) >> 8) & 0xff)
+#define gmbus1_bus_cycle(v) (((v) >> 25) & 0x7)
+
+/* GMBUS0 bits definitions */
+#define _GMBUS_PIN_SEL_MASK (0x7)
+
+static unsigned char edid_get_byte(struct intel_vgpu *vgpu)
+{
+ struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid;
+ unsigned char chr = 0;
+
+ if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) {
+ gvt_err("Driver tries to read EDID without proper sequence!\n");
+ return 0;
+ }
+ if (edid->current_edid_read >= EDID_SIZE) {
+ gvt_err("edid_get_byte() exceeds the size of EDID!\n");
+ return 0;
+ }
+
+ if (!edid->edid_available) {
+ gvt_err("Reading EDID but EDID is not available!\n");
+ return 0;
+ }
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, edid->port)) {
+ struct intel_vgpu_edid_data *edid_data =
+ intel_vgpu_port(vgpu, edid->port)->edid;
+
+ chr = edid_data->edid_block[edid->current_edid_read];
+ edid->current_edid_read++;
+ } else {
+ gvt_err("No EDID available during the reading?\n");
+ }
+ return chr;
+}
+
+static inline int get_port_from_gmbus0(u32 gmbus0)
+{
+ int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK;
+ int port = -EINVAL;
+
+ if (port_select == 2)
+ port = PORT_E;
+ else if (port_select == 4)
+ port = PORT_C;
+ else if (port_select == 5)
+ port = PORT_B;
+ else if (port_select == 6)
+ port = PORT_D;
+ return port;
+}
+
+static void reset_gmbus_controller(struct intel_vgpu *vgpu)
+{
+ vgpu_vreg(vgpu, PCH_GMBUS2) = GMBUS_HW_RDY;
+ if (!vgpu->display.i2c_edid.edid_available)
+ vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER;
+ vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE;
+}
+
+/* GMBUS0 */
+static int gmbus0_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ int port, pin_select;
+
+ memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+
+ pin_select = vgpu_vreg(vgpu, offset) & _GMBUS_PIN_SEL_MASK;
+
+ intel_vgpu_init_i2c_edid(vgpu);
+
+ if (pin_select == 0)
+ return 0;
+
+ port = get_port_from_gmbus0(pin_select);
+ if (WARN_ON(port < 0))
+ return 0;
+
+ vgpu->display.i2c_edid.state = I2C_GMBUS;
+ vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE;
+
+ vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE;
+ vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY | GMBUS_HW_WAIT_PHASE;
+
+ if (intel_vgpu_has_monitor_on_port(vgpu, port) &&
+ !intel_vgpu_port_is_dp(vgpu, port)) {
+ vgpu->display.i2c_edid.port = port;
+ vgpu->display.i2c_edid.edid_available = true;
+ vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_SATOER;
+ } else
+ vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER;
+ return 0;
+}
+
+static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+ u32 slave_addr;
+ u32 wvalue = *(u32 *)p_data;
+
+ if (vgpu_vreg(vgpu, offset) & GMBUS_SW_CLR_INT) {
+ if (!(wvalue & GMBUS_SW_CLR_INT)) {
+ vgpu_vreg(vgpu, offset) &= ~GMBUS_SW_CLR_INT;
+ reset_gmbus_controller(vgpu);
+ }
+ /*
+ * TODO: "This bit is cleared to zero when an event
+ * causes the HW_RDY bit transition to occur "
+ */
+ } else {
+ /*
+ * per bspec setting this bit can cause:
+ * 1) INT status bit cleared
+ * 2) HW_RDY bit asserted
+ */
+ if (wvalue & GMBUS_SW_CLR_INT) {
+ vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_INT;
+ vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY;
+ }
+
+ /* For virtualization, we suppose that HW is always ready,
+ * so GMBUS_SW_RDY should always be cleared
+ */
+ if (wvalue & GMBUS_SW_RDY)
+ wvalue &= ~GMBUS_SW_RDY;
+
+ i2c_edid->gmbus.total_byte_count =
+ gmbus1_total_byte_count(wvalue);
+ slave_addr = gmbus1_slave_addr(wvalue);
+
+ /* vgpu gmbus only support EDID */
+ if (slave_addr == EDID_ADDR) {
+ i2c_edid->slave_selected = true;
+ } else if (slave_addr != 0) {
+ gvt_dbg_dpy(
+ "vgpu%d: unsupported gmbus slave addr(0x%x)\n"
+ " gmbus operations will be ignored.\n",
+ vgpu->id, slave_addr);
+ }
+
+ if (wvalue & GMBUS_CYCLE_INDEX)
+ i2c_edid->current_edid_read =
+ gmbus1_slave_index(wvalue);
+
+ i2c_edid->gmbus.cycle_type = gmbus1_bus_cycle(wvalue);
+ switch (gmbus1_bus_cycle(wvalue)) {
+ case GMBUS_NOCYCLE:
+ break;
+ case GMBUS_STOP:
+ /* From spec:
+ * This can only cause a STOP to be generated
+ * if a GMBUS cycle is generated, the GMBUS is
+ * currently in a data/wait/idle phase, or it is in a
+ * WAIT phase
+ */
+ if (gmbus1_bus_cycle(vgpu_vreg(vgpu, offset))
+ != GMBUS_NOCYCLE) {
+ intel_vgpu_init_i2c_edid(vgpu);
+ /* After the 'stop' cycle, hw state would become
+ * 'stop phase' and then 'idle phase' after a
+ * few milliseconds. In emulation, we just set
+ * it as 'idle phase' ('stop phase' is not
+ * visible in gmbus interface)
+ */
+ i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE;
+ vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE;
+ }
+ break;
+ case NIDX_NS_W:
+ case IDX_NS_W:
+ case NIDX_STOP:
+ case IDX_STOP:
+ /* From hw spec the GMBUS phase
+ * transition like this:
+ * START (-->INDEX) -->DATA
+ */
+ i2c_edid->gmbus.phase = GMBUS_DATA_PHASE;
+ vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE;
+ break;
+ default:
+ gvt_err("Unknown/reserved GMBUS cycle detected!\n");
+ break;
+ }
+ /*
+ * From hw spec the WAIT state will be
+ * cleared:
+ * (1) in a new GMBUS cycle
+ * (2) by generating a stop
+ */
+ vgpu_vreg(vgpu, offset) = wvalue;
+ }
+ return 0;
+}
+
+static int gmbus3_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ WARN_ON(1);
+ return 0;
+}
+
+static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ int i;
+ unsigned char byte_data;
+ struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+ int byte_left = i2c_edid->gmbus.total_byte_count -
+ i2c_edid->current_edid_read;
+ int byte_count = byte_left;
+ u32 reg_data = 0;
+
+ /* Data can only be recevied if previous settings correct */
+ if (vgpu_vreg(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) {
+ if (byte_left <= 0) {
+ memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+ return 0;
+ }
+
+ if (byte_count > 4)
+ byte_count = 4;
+ for (i = 0; i < byte_count; i++) {
+ byte_data = edid_get_byte(vgpu);
+ reg_data |= (byte_data << (i << 3));
+ }
+
+ memcpy(&vgpu_vreg(vgpu, offset), &reg_data, byte_count);
+ memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+
+ if (byte_left <= 4) {
+ switch (i2c_edid->gmbus.cycle_type) {
+ case NIDX_STOP:
+ case IDX_STOP:
+ i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE;
+ break;
+ case NIDX_NS_W:
+ case IDX_NS_W:
+ default:
+ i2c_edid->gmbus.phase = GMBUS_WAIT_PHASE;
+ break;
+ }
+ intel_vgpu_init_i2c_edid(vgpu);
+ }
+ /*
+ * Read GMBUS3 during send operation,
+ * return the latest written value
+ */
+ } else {
+ memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+ gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n",
+ vgpu->id);
+ }
+ return 0;
+}
+
+static int gmbus2_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 value = vgpu_vreg(vgpu, offset);
+
+ if (!(vgpu_vreg(vgpu, offset) & GMBUS_INUSE))
+ vgpu_vreg(vgpu, offset) |= GMBUS_INUSE;
+ memcpy(p_data, (void *)&value, bytes);
+ return 0;
+}
+
+static int gmbus2_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 wvalue = *(u32 *)p_data;
+
+ if (wvalue & GMBUS_INUSE)
+ vgpu_vreg(vgpu, offset) &= ~GMBUS_INUSE;
+ /* All other bits are read-only */
+ return 0;
+}
+
+/**
+ * intel_gvt_i2c_handle_gmbus_read - emulate gmbus register mmio read
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate gmbus register mmio read
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ if (WARN_ON(bytes > 8 && (offset & (bytes - 1))))
+ return -EINVAL;
+
+ if (offset == i915_mmio_reg_offset(PCH_GMBUS2))
+ return gmbus2_mmio_read(vgpu, offset, p_data, bytes);
+ else if (offset == i915_mmio_reg_offset(PCH_GMBUS3))
+ return gmbus3_mmio_read(vgpu, offset, p_data, bytes);
+
+ memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+ return 0;
+}
+
+/**
+ * intel_gvt_i2c_handle_gmbus_write - emulate gmbus register mmio write
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate gmbus register mmio write
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ if (WARN_ON(bytes > 8 && (offset & (bytes - 1))))
+ return -EINVAL;
+
+ if (offset == i915_mmio_reg_offset(PCH_GMBUS0))
+ return gmbus0_mmio_write(vgpu, offset, p_data, bytes);
+ else if (offset == i915_mmio_reg_offset(PCH_GMBUS1))
+ return gmbus1_mmio_write(vgpu, offset, p_data, bytes);
+ else if (offset == i915_mmio_reg_offset(PCH_GMBUS2))
+ return gmbus2_mmio_write(vgpu, offset, p_data, bytes);
+ else if (offset == i915_mmio_reg_offset(PCH_GMBUS3))
+ return gmbus3_mmio_write(vgpu, offset, p_data, bytes);
+
+ memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+ return 0;
+}
+
+enum {
+ AUX_CH_CTL = 0,
+ AUX_CH_DATA1,
+ AUX_CH_DATA2,
+ AUX_CH_DATA3,
+ AUX_CH_DATA4,
+ AUX_CH_DATA5
+};
+
+static inline int get_aux_ch_reg(unsigned int offset)
+{
+ int reg;
+
+ switch (offset & 0xff) {
+ case 0x10:
+ reg = AUX_CH_CTL;
+ break;
+ case 0x14:
+ reg = AUX_CH_DATA1;
+ break;
+ case 0x18:
+ reg = AUX_CH_DATA2;
+ break;
+ case 0x1c:
+ reg = AUX_CH_DATA3;
+ break;
+ case 0x20:
+ reg = AUX_CH_DATA4;
+ break;
+ case 0x24:
+ reg = AUX_CH_DATA5;
+ break;
+ default:
+ reg = -1;
+ break;
+ }
+ return reg;
+}
+
+#define AUX_CTL_MSG_LENGTH(reg) \
+ ((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \
+ DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT)
+
+/**
+ * intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate AUX channel register write
+ *
+ */
+void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
+ int port_idx,
+ unsigned int offset,
+ void *p_data)
+{
+ struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+ int msg_length, ret_msg_size;
+ int msg, addr, ctrl, op;
+ u32 value = *(u32 *)p_data;
+ int aux_data_for_write = 0;
+ int reg = get_aux_ch_reg(offset);
+
+ if (reg != AUX_CH_CTL) {
+ vgpu_vreg(vgpu, offset) = value;
+ return;
+ }
+
+ msg_length = AUX_CTL_MSG_LENGTH(value);
+ // check the msg in DATA register.
+ msg = vgpu_vreg(vgpu, offset + 4);
+ addr = (msg >> 8) & 0xffff;
+ ctrl = (msg >> 24) & 0xff;
+ op = ctrl >> 4;
+ if (!(value & DP_AUX_CH_CTL_SEND_BUSY)) {
+ /* The ctl write to clear some states */
+ return;
+ }
+
+ /* Always set the wanted value for vms. */
+ ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1);
+ vgpu_vreg(vgpu, offset) =
+ DP_AUX_CH_CTL_DONE |
+ ((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) &
+ DP_AUX_CH_CTL_MESSAGE_SIZE_MASK);
+
+ if (msg_length == 3) {
+ if (!(op & GVT_AUX_I2C_MOT)) {
+ /* stop */
+ intel_vgpu_init_i2c_edid(vgpu);
+ } else {
+ /* start or restart */
+ i2c_edid->aux_ch.i2c_over_aux_ch = true;
+ i2c_edid->aux_ch.aux_ch_mot = true;
+ if (addr == 0) {
+ /* reset the address */
+ intel_vgpu_init_i2c_edid(vgpu);
+ } else if (addr == EDID_ADDR) {
+ i2c_edid->state = I2C_AUX_CH;
+ i2c_edid->port = port_idx;
+ i2c_edid->slave_selected = true;
+ if (intel_vgpu_has_monitor_on_port(vgpu,
+ port_idx) &&
+ intel_vgpu_port_is_dp(vgpu, port_idx))
+ i2c_edid->edid_available = true;
+ }
+ }
+ } else if ((op & 0x1) == GVT_AUX_I2C_WRITE) {
+ /* TODO
+ * We only support EDID reading from I2C_over_AUX. And
+ * we do not expect the index mode to be used. Right now
+ * the WRITE operation is ignored. It is good enough to
+ * support the gfx driver to do EDID access.
+ */
+ } else {
+ if (WARN_ON((op & 0x1) != GVT_AUX_I2C_READ))
+ return;
+ if (WARN_ON(msg_length != 4))
+ return;
+ if (i2c_edid->edid_available && i2c_edid->slave_selected) {
+ unsigned char val = edid_get_byte(vgpu);
+
+ aux_data_for_write = (val << 16);
+ }
+ }
+ /* write the return value in AUX_CH_DATA reg which includes:
+ * ACK of I2C_WRITE
+ * returned byte if it is READ
+ */
+ aux_data_for_write |= GVT_AUX_I2C_REPLY_ACK << 24;
+ vgpu_vreg(vgpu, offset + 4) = aux_data_for_write;
+}
+
+/**
+ * intel_vgpu_init_i2c_edid - initialize vGPU i2c edid emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize vGPU i2c edid emulation stuffs
+ *
+ */
+void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu)
+{
+ struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid;
+
+ edid->state = I2C_NOT_SPECIFIED;
+
+ edid->port = -1;
+ edid->slave_selected = false;
+ edid->edid_available = false;
+ edid->current_edid_read = 0;
+
+ memset(&edid->gmbus, 0, sizeof(struct intel_vgpu_i2c_gmbus));
+
+ edid->aux_ch.i2c_over_aux_ch = false;
+ edid->aux_ch.aux_ch_mot = false;
+}
diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h
new file mode 100644
index 000000000000..f6dfc8b795ec
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/edid.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Terrence Xu <terrence.xu@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_EDID_H_
+#define _GVT_EDID_H_
+
+#define EDID_SIZE 128
+#define EDID_ADDR 0x50 /* Linux hvm EDID addr */
+
+#define GVT_AUX_NATIVE_WRITE 0x8
+#define GVT_AUX_NATIVE_READ 0x9
+#define GVT_AUX_I2C_WRITE 0x0
+#define GVT_AUX_I2C_READ 0x1
+#define GVT_AUX_I2C_STATUS 0x2
+#define GVT_AUX_I2C_MOT 0x4
+#define GVT_AUX_I2C_REPLY_ACK 0x0
+
+struct intel_vgpu_edid_data {
+ bool data_valid;
+ unsigned char edid_block[EDID_SIZE];
+};
+
+enum gmbus_cycle_type {
+ GMBUS_NOCYCLE = 0x0,
+ NIDX_NS_W = 0x1,
+ IDX_NS_W = 0x3,
+ GMBUS_STOP = 0x4,
+ NIDX_STOP = 0x5,
+ IDX_STOP = 0x7
+};
+
+/*
+ * States of GMBUS
+ *
+ * GMBUS0-3 could be related to the EDID virtualization. Another two GMBUS
+ * registers, GMBUS4 (interrupt mask) and GMBUS5 (2 byte indes register), are
+ * not considered here. Below describes the usage of GMBUS registers that are
+ * cared by the EDID virtualization
+ *
+ * GMBUS0:
+ * R/W
+ * port selection. value of bit0 - bit2 corresponds to the GPIO registers.
+ *
+ * GMBUS1:
+ * R/W Protect
+ * Command and Status.
+ * bit0 is the direction bit: 1 is read; 0 is write.
+ * bit1 - bit7 is slave 7-bit address.
+ * bit16 - bit24 total byte count (ignore?)
+ *
+ * GMBUS2:
+ * Most of bits are read only except bit 15 (IN_USE)
+ * Status register
+ * bit0 - bit8 current byte count
+ * bit 11: hardware ready;
+ *
+ * GMBUS3:
+ * Read/Write
+ * Data for transfer
+ */
+
+/* From hw specs, Other phases like START, ADDRESS, INDEX
+ * are invisible to GMBUS MMIO interface. So no definitions
+ * in below enum types
+ */
+enum gvt_gmbus_phase {
+ GMBUS_IDLE_PHASE = 0,
+ GMBUS_DATA_PHASE,
+ GMBUS_WAIT_PHASE,
+ //GMBUS_STOP_PHASE,
+ GMBUS_MAX_PHASE
+};
+
+struct intel_vgpu_i2c_gmbus {
+ unsigned int total_byte_count; /* from GMBUS1 */
+ enum gmbus_cycle_type cycle_type;
+ enum gvt_gmbus_phase phase;
+};
+
+struct intel_vgpu_i2c_aux_ch {
+ bool i2c_over_aux_ch;
+ bool aux_ch_mot;
+};
+
+enum i2c_state {
+ I2C_NOT_SPECIFIED = 0,
+ I2C_GMBUS = 1,
+ I2C_AUX_CH = 2
+};
+
+/* I2C sequences cannot interleave.
+ * GMBUS and AUX_CH sequences cannot interleave.
+ */
+struct intel_vgpu_i2c_edid {
+ enum i2c_state state;
+
+ unsigned int port;
+ bool slave_selected;
+ bool edid_available;
+ unsigned int current_edid_read;
+
+ struct intel_vgpu_i2c_gmbus gmbus;
+ struct intel_vgpu_i2c_aux_ch aux_ch;
+};
+
+void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu);
+
+int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes);
+
+int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes);
+
+void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
+ int port_idx,
+ unsigned int offset,
+ void *p_data);
+
+#endif /*_GVT_EDID_H_*/
diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c
new file mode 100644
index 000000000000..f32bb6f6495c
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/execlist.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define _EL_OFFSET_STATUS 0x234
+#define _EL_OFFSET_STATUS_BUF 0x370
+#define _EL_OFFSET_STATUS_PTR 0x3A0
+
+#define execlist_ring_mmio(gvt, ring_id, offset) \
+ (gvt->dev_priv->engine[ring_id]->mmio_base + (offset))
+
+#define valid_context(ctx) ((ctx)->valid)
+#define same_context(a, b) (((a)->context_id == (b)->context_id) && \
+ ((a)->lrca == (b)->lrca))
+
+static int context_switch_events[] = {
+ [RCS] = RCS_AS_CONTEXT_SWITCH,
+ [BCS] = BCS_AS_CONTEXT_SWITCH,
+ [VCS] = VCS_AS_CONTEXT_SWITCH,
+ [VCS2] = VCS2_AS_CONTEXT_SWITCH,
+ [VECS] = VECS_AS_CONTEXT_SWITCH,
+};
+
+static int ring_id_to_context_switch_event(int ring_id)
+{
+ if (WARN_ON(ring_id < RCS && ring_id >
+ ARRAY_SIZE(context_switch_events)))
+ return -EINVAL;
+
+ return context_switch_events[ring_id];
+}
+
+static void switch_virtual_execlist_slot(struct intel_vgpu_execlist *execlist)
+{
+ gvt_dbg_el("[before] running slot %d/context %x pending slot %d\n",
+ execlist->running_slot ?
+ execlist->running_slot->index : -1,
+ execlist->running_context ?
+ execlist->running_context->context_id : 0,
+ execlist->pending_slot ?
+ execlist->pending_slot->index : -1);
+
+ execlist->running_slot = execlist->pending_slot;
+ execlist->pending_slot = NULL;
+ execlist->running_context = execlist->running_context ?
+ &execlist->running_slot->ctx[0] : NULL;
+
+ gvt_dbg_el("[after] running slot %d/context %x pending slot %d\n",
+ execlist->running_slot ?
+ execlist->running_slot->index : -1,
+ execlist->running_context ?
+ execlist->running_context->context_id : 0,
+ execlist->pending_slot ?
+ execlist->pending_slot->index : -1);
+}
+
+static void emulate_execlist_status(struct intel_vgpu_execlist *execlist)
+{
+ struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+ struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;
+ struct execlist_ctx_descriptor_format *desc = execlist->running_context;
+ struct intel_vgpu *vgpu = execlist->vgpu;
+ struct execlist_status_format status;
+ int ring_id = execlist->ring_id;
+ u32 status_reg = execlist_ring_mmio(vgpu->gvt,
+ ring_id, _EL_OFFSET_STATUS);
+
+ status.ldw = vgpu_vreg(vgpu, status_reg);
+ status.udw = vgpu_vreg(vgpu, status_reg + 4);
+
+ if (running) {
+ status.current_execlist_pointer = !!running->index;
+ status.execlist_write_pointer = !!!running->index;
+ status.execlist_0_active = status.execlist_0_valid =
+ !!!(running->index);
+ status.execlist_1_active = status.execlist_1_valid =
+ !!(running->index);
+ } else {
+ status.context_id = 0;
+ status.execlist_0_active = status.execlist_0_valid = 0;
+ status.execlist_1_active = status.execlist_1_valid = 0;
+ }
+
+ status.context_id = desc ? desc->context_id : 0;
+ status.execlist_queue_full = !!(pending);
+
+ vgpu_vreg(vgpu, status_reg) = status.ldw;
+ vgpu_vreg(vgpu, status_reg + 4) = status.udw;
+
+ gvt_dbg_el("vgpu%d: status reg offset %x ldw %x udw %x\n",
+ vgpu->id, status_reg, status.ldw, status.udw);
+}
+
+static void emulate_csb_update(struct intel_vgpu_execlist *execlist,
+ struct execlist_context_status_format *status,
+ bool trigger_interrupt_later)
+{
+ struct intel_vgpu *vgpu = execlist->vgpu;
+ int ring_id = execlist->ring_id;
+ struct execlist_context_status_pointer_format ctx_status_ptr;
+ u32 write_pointer;
+ u32 ctx_status_ptr_reg, ctx_status_buf_reg, offset;
+
+ ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+ _EL_OFFSET_STATUS_PTR);
+ ctx_status_buf_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+ _EL_OFFSET_STATUS_BUF);
+
+ ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
+
+ write_pointer = ctx_status_ptr.write_ptr;
+
+ if (write_pointer == 0x7)
+ write_pointer = 0;
+ else {
+ ++write_pointer;
+ write_pointer %= 0x6;
+ }
+
+ offset = ctx_status_buf_reg + write_pointer * 8;
+
+ vgpu_vreg(vgpu, offset) = status->ldw;
+ vgpu_vreg(vgpu, offset + 4) = status->udw;
+
+ ctx_status_ptr.write_ptr = write_pointer;
+ vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
+
+ gvt_dbg_el("vgpu%d: w pointer %u reg %x csb l %x csb h %x\n",
+ vgpu->id, write_pointer, offset, status->ldw, status->udw);
+
+ if (trigger_interrupt_later)
+ return;
+
+ intel_vgpu_trigger_virtual_event(vgpu,
+ ring_id_to_context_switch_event(execlist->ring_id));
+}
+
+static int emulate_execlist_ctx_schedule_out(
+ struct intel_vgpu_execlist *execlist,
+ struct execlist_ctx_descriptor_format *ctx)
+{
+ struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+ struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;
+ struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0];
+ struct execlist_ctx_descriptor_format *ctx1 = &running->ctx[1];
+ struct execlist_context_status_format status;
+
+ memset(&status, 0, sizeof(status));
+
+ gvt_dbg_el("schedule out context id %x\n", ctx->context_id);
+
+ if (WARN_ON(!same_context(ctx, execlist->running_context))) {
+ gvt_err("schedule out context is not running context,"
+ "ctx id %x running ctx id %x\n",
+ ctx->context_id,
+ execlist->running_context->context_id);
+ return -EINVAL;
+ }
+
+ /* ctx1 is valid, ctx0/ctx is scheduled-out -> element switch */
+ if (valid_context(ctx1) && same_context(ctx0, ctx)) {
+ gvt_dbg_el("ctx 1 valid, ctx/ctx 0 is scheduled-out\n");
+
+ execlist->running_context = ctx1;
+
+ emulate_execlist_status(execlist);
+
+ status.context_complete = status.element_switch = 1;
+ status.context_id = ctx->context_id;
+
+ emulate_csb_update(execlist, &status, false);
+ /*
+ * ctx1 is not valid, ctx == ctx0
+ * ctx1 is valid, ctx1 == ctx
+ * --> last element is finished
+ * emulate:
+ * active-to-idle if there is *no* pending execlist
+ * context-complete if there *is* pending execlist
+ */
+ } else if ((!valid_context(ctx1) && same_context(ctx0, ctx))
+ || (valid_context(ctx1) && same_context(ctx1, ctx))) {
+ gvt_dbg_el("need to switch virtual execlist slot\n");
+
+ switch_virtual_execlist_slot(execlist);
+
+ emulate_execlist_status(execlist);
+
+ status.context_complete = status.active_to_idle = 1;
+ status.context_id = ctx->context_id;
+
+ if (!pending) {
+ emulate_csb_update(execlist, &status, false);
+ } else {
+ emulate_csb_update(execlist, &status, true);
+
+ memset(&status, 0, sizeof(status));
+
+ status.idle_to_active = 1;
+ status.context_id = 0;
+
+ emulate_csb_update(execlist, &status, false);
+ }
+ } else {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct intel_vgpu_execlist_slot *get_next_execlist_slot(
+ struct intel_vgpu_execlist *execlist)
+{
+ struct intel_vgpu *vgpu = execlist->vgpu;
+ int ring_id = execlist->ring_id;
+ u32 status_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+ _EL_OFFSET_STATUS);
+ struct execlist_status_format status;
+
+ status.ldw = vgpu_vreg(vgpu, status_reg);
+ status.udw = vgpu_vreg(vgpu, status_reg + 4);
+
+ if (status.execlist_queue_full) {
+ gvt_err("virtual execlist slots are full\n");
+ return NULL;
+ }
+
+ return &execlist->slot[status.execlist_write_pointer];
+}
+
+static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist,
+ struct execlist_ctx_descriptor_format ctx[2])
+{
+ struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+ struct intel_vgpu_execlist_slot *slot =
+ get_next_execlist_slot(execlist);
+
+ struct execlist_ctx_descriptor_format *ctx0, *ctx1;
+ struct execlist_context_status_format status;
+
+ gvt_dbg_el("emulate schedule-in\n");
+
+ if (!slot) {
+ gvt_err("no available execlist slot\n");
+ return -EINVAL;
+ }
+
+ memset(&status, 0, sizeof(status));
+ memset(slot->ctx, 0, sizeof(slot->ctx));
+
+ slot->ctx[0] = ctx[0];
+ slot->ctx[1] = ctx[1];
+
+ gvt_dbg_el("alloc slot index %d ctx 0 %x ctx 1 %x\n",
+ slot->index, ctx[0].context_id,
+ ctx[1].context_id);
+
+ /*
+ * no running execlist, make this write bundle as running execlist
+ * -> idle-to-active
+ */
+ if (!running) {
+ gvt_dbg_el("no current running execlist\n");
+
+ execlist->running_slot = slot;
+ execlist->pending_slot = NULL;
+ execlist->running_context = &slot->ctx[0];
+
+ gvt_dbg_el("running slot index %d running context %x\n",
+ execlist->running_slot->index,
+ execlist->running_context->context_id);
+
+ emulate_execlist_status(execlist);
+
+ status.idle_to_active = 1;
+ status.context_id = 0;
+
+ emulate_csb_update(execlist, &status, false);
+ return 0;
+ }
+
+ ctx0 = &running->ctx[0];
+ ctx1 = &running->ctx[1];
+
+ gvt_dbg_el("current running slot index %d ctx 0 %x ctx 1 %x\n",
+ running->index, ctx0->context_id, ctx1->context_id);
+
+ /*
+ * already has an running execlist
+ * a. running ctx1 is valid,
+ * ctx0 is finished, and running ctx1 == new execlist ctx[0]
+ * b. running ctx1 is not valid,
+ * ctx0 == new execlist ctx[0]
+ * ----> lite-restore + preempted
+ */
+ if ((valid_context(ctx1) && same_context(ctx1, &slot->ctx[0]) &&
+ /* condition a */
+ (!same_context(ctx0, execlist->running_context))) ||
+ (!valid_context(ctx1) &&
+ same_context(ctx0, &slot->ctx[0]))) { /* condition b */
+ gvt_dbg_el("need to switch virtual execlist slot\n");
+
+ execlist->pending_slot = slot;
+ switch_virtual_execlist_slot(execlist);
+
+ emulate_execlist_status(execlist);
+
+ status.lite_restore = status.preempted = 1;
+ status.context_id = ctx[0].context_id;
+
+ emulate_csb_update(execlist, &status, false);
+ } else {
+ gvt_dbg_el("emulate as pending slot\n");
+ /*
+ * otherwise
+ * --> emulate pending execlist exist + but no preemption case
+ */
+ execlist->pending_slot = slot;
+ emulate_execlist_status(execlist);
+ }
+ return 0;
+}
+
+static void free_workload(struct intel_vgpu_workload *workload)
+{
+ intel_vgpu_unpin_mm(workload->shadow_mm);
+ intel_gvt_mm_unreference(workload->shadow_mm);
+ kmem_cache_free(workload->vgpu->workloads, workload);
+}
+
+#define get_desc_from_elsp_dwords(ed, i) \
+ ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2]))
+
+
+#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2))
+#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U))
+static int set_gma_to_bb_cmd(struct intel_shadow_bb_entry *entry_obj,
+ unsigned long add, int gmadr_bytes)
+{
+ if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8))
+ return -1;
+
+ *((u32 *)(entry_obj->bb_start_cmd_va + (1 << 2))) = add &
+ BATCH_BUFFER_ADDR_MASK;
+ if (gmadr_bytes == 8) {
+ *((u32 *)(entry_obj->bb_start_cmd_va + (2 << 2))) =
+ add & BATCH_BUFFER_ADDR_HIGH_MASK;
+ }
+
+ return 0;
+}
+
+static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
+{
+ int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+
+ /* pin the gem object to ggtt */
+ if (!list_empty(&workload->shadow_bb)) {
+ struct intel_shadow_bb_entry *entry_obj =
+ list_first_entry(&workload->shadow_bb,
+ struct intel_shadow_bb_entry,
+ list);
+ struct intel_shadow_bb_entry *temp;
+
+ list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb,
+ list) {
+ struct i915_vma *vma;
+
+ vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0,
+ 4, 0);
+ if (IS_ERR(vma)) {
+ gvt_err("Cannot pin\n");
+ return;
+ }
+
+ /* FIXME: we are not tracking our pinned VMA leaving it
+ * up to the core to fix up the stray pin_count upon
+ * free.
+ */
+
+ /* update the relocate gma with shadow batch buffer*/
+ set_gma_to_bb_cmd(entry_obj,
+ i915_ggtt_offset(vma),
+ gmadr_bytes);
+ }
+ }
+}
+
+static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ int ring_id = wa_ctx->workload->ring_id;
+ struct i915_gem_context *shadow_ctx =
+ wa_ctx->workload->vgpu->shadow_ctx;
+ struct drm_i915_gem_object *ctx_obj =
+ shadow_ctx->engine[ring_id].state->obj;
+ struct execlist_ring_context *shadow_ring_context;
+ struct page *page;
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ shadow_ring_context = kmap_atomic(page);
+
+ shadow_ring_context->bb_per_ctx_ptr.val =
+ (shadow_ring_context->bb_per_ctx_ptr.val &
+ (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma;
+ shadow_ring_context->rcs_indirect_ctx.val =
+ (shadow_ring_context->rcs_indirect_ctx.val &
+ (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma;
+
+ kunmap_atomic(shadow_ring_context);
+ return 0;
+}
+
+static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ struct i915_vma *vma;
+ unsigned char *per_ctx_va =
+ (unsigned char *)wa_ctx->indirect_ctx.shadow_va +
+ wa_ctx->indirect_ctx.size;
+
+ if (wa_ctx->indirect_ctx.size == 0)
+ return;
+
+ vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL,
+ 0, CACHELINE_BYTES, 0);
+ if (IS_ERR(vma)) {
+ gvt_err("Cannot pin indirect ctx obj\n");
+ return;
+ }
+
+ /* FIXME: we are not tracking our pinned VMA leaving it
+ * up to the core to fix up the stray pin_count upon
+ * free.
+ */
+
+ wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma);
+
+ wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1);
+ memset(per_ctx_va, 0, CACHELINE_BYTES);
+
+ update_wa_ctx_2_shadow_ctx(wa_ctx);
+}
+
+static int prepare_execlist_workload(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ struct execlist_ctx_descriptor_format ctx[2];
+ int ring_id = workload->ring_id;
+
+ intel_vgpu_pin_mm(workload->shadow_mm);
+ intel_vgpu_sync_oos_pages(workload->vgpu);
+ intel_vgpu_flush_post_shadow(workload->vgpu);
+ prepare_shadow_batch_buffer(workload);
+ prepare_shadow_wa_ctx(&workload->wa_ctx);
+ if (!workload->emulate_schedule_in)
+ return 0;
+
+ ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1);
+ ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0);
+
+ return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx);
+}
+
+static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload)
+{
+ /* release all the shadow batch buffer */
+ if (!list_empty(&workload->shadow_bb)) {
+ struct intel_shadow_bb_entry *entry_obj =
+ list_first_entry(&workload->shadow_bb,
+ struct intel_shadow_bb_entry,
+ list);
+ struct intel_shadow_bb_entry *temp;
+
+ list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb,
+ list) {
+ i915_gem_object_unpin_map(entry_obj->obj);
+ i915_gem_object_put(entry_obj->obj);
+ list_del(&entry_obj->list);
+ kfree(entry_obj);
+ }
+ }
+}
+
+static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+ if (wa_ctx->indirect_ctx.size == 0)
+ return;
+
+ i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
+ i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+}
+
+static int complete_execlist_workload(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ struct intel_vgpu_execlist *execlist =
+ &vgpu->execlist[workload->ring_id];
+ struct intel_vgpu_workload *next_workload;
+ struct list_head *next = workload_q_head(vgpu, workload->ring_id)->next;
+ bool lite_restore = false;
+ int ret;
+
+ gvt_dbg_el("complete workload %p status %d\n", workload,
+ workload->status);
+
+ release_shadow_batch_buffer(workload);
+ release_shadow_wa_ctx(&workload->wa_ctx);
+
+ if (workload->status || vgpu->resetting)
+ goto out;
+
+ if (!list_empty(workload_q_head(vgpu, workload->ring_id))) {
+ struct execlist_ctx_descriptor_format *this_desc, *next_desc;
+
+ next_workload = container_of(next,
+ struct intel_vgpu_workload, list);
+ this_desc = &workload->ctx_desc;
+ next_desc = &next_workload->ctx_desc;
+
+ lite_restore = same_context(this_desc, next_desc);
+ }
+
+ if (lite_restore) {
+ gvt_dbg_el("next context == current - no schedule-out\n");
+ free_workload(workload);
+ return 0;
+ }
+
+ ret = emulate_execlist_ctx_schedule_out(execlist, &workload->ctx_desc);
+ if (ret)
+ goto err;
+out:
+ free_workload(workload);
+ return 0;
+err:
+ free_workload(workload);
+ return ret;
+}
+
+#define RING_CTX_OFF(x) \
+ offsetof(struct execlist_ring_context, x)
+
+static void read_guest_pdps(struct intel_vgpu *vgpu,
+ u64 ring_context_gpa, u32 pdp[8])
+{
+ u64 gpa;
+ int i;
+
+ gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val);
+
+ for (i = 0; i < 8; i++)
+ intel_gvt_hypervisor_read_gpa(vgpu,
+ gpa + i * 8, &pdp[7 - i], 4);
+}
+
+static int prepare_mm(struct intel_vgpu_workload *workload)
+{
+ struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
+ struct intel_vgpu_mm *mm;
+ int page_table_level;
+ u32 pdp[8];
+
+ if (desc->addressing_mode == 1) { /* legacy 32-bit */
+ page_table_level = 3;
+ } else if (desc->addressing_mode == 3) { /* legacy 64 bit */
+ page_table_level = 4;
+ } else {
+ gvt_err("Advanced Context mode(SVM) is not supported!\n");
+ return -EINVAL;
+ }
+
+ read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp);
+
+ mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp);
+ if (mm) {
+ intel_gvt_mm_reference(mm);
+ } else {
+
+ mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT,
+ pdp, page_table_level, 0);
+ if (IS_ERR(mm)) {
+ gvt_err("fail to create mm object.\n");
+ return PTR_ERR(mm);
+ }
+ }
+ workload->shadow_mm = mm;
+ return 0;
+}
+
+#define get_last_workload(q) \
+ (list_empty(q) ? NULL : container_of(q->prev, \
+ struct intel_vgpu_workload, list))
+
+static int submit_context(struct intel_vgpu *vgpu, int ring_id,
+ struct execlist_ctx_descriptor_format *desc,
+ bool emulate_schedule_in)
+{
+ struct list_head *q = workload_q_head(vgpu, ring_id);
+ struct intel_vgpu_workload *last_workload = get_last_workload(q);
+ struct intel_vgpu_workload *workload = NULL;
+ u64 ring_context_gpa;
+ u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx;
+ int ret;
+
+ ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+ (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT));
+ if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("invalid guest context LRCA: %x\n", desc->lrca);
+ return -EINVAL;
+ }
+
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(ring_header.val), &head, 4);
+
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(ring_tail.val), &tail, 4);
+
+ head &= RB_HEAD_OFF_MASK;
+ tail &= RB_TAIL_OFF_MASK;
+
+ if (last_workload && same_context(&last_workload->ctx_desc, desc)) {
+ gvt_dbg_el("ring id %d cur workload == last\n", ring_id);
+ gvt_dbg_el("ctx head %x real head %lx\n", head,
+ last_workload->rb_tail);
+ /*
+ * cannot use guest context head pointer here,
+ * as it might not be updated at this time
+ */
+ head = last_workload->rb_tail;
+ }
+
+ gvt_dbg_el("ring id %d begin a new workload\n", ring_id);
+
+ workload = kmem_cache_zalloc(vgpu->workloads, GFP_KERNEL);
+ if (!workload)
+ return -ENOMEM;
+
+ /* record some ring buffer register values for scan and shadow */
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(rb_start.val), &start, 4);
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(rb_ctrl.val), &ctl, 4);
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4);
+
+ INIT_LIST_HEAD(&workload->list);
+ INIT_LIST_HEAD(&workload->shadow_bb);
+
+ init_waitqueue_head(&workload->shadow_ctx_status_wq);
+ atomic_set(&workload->shadow_ctx_active, 0);
+
+ workload->vgpu = vgpu;
+ workload->ring_id = ring_id;
+ workload->ctx_desc = *desc;
+ workload->ring_context_gpa = ring_context_gpa;
+ workload->rb_head = head;
+ workload->rb_tail = tail;
+ workload->rb_start = start;
+ workload->rb_ctl = ctl;
+ workload->prepare = prepare_execlist_workload;
+ workload->complete = complete_execlist_workload;
+ workload->status = -EINPROGRESS;
+ workload->emulate_schedule_in = emulate_schedule_in;
+
+ if (ring_id == RCS) {
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4);
+ intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+ RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4);
+
+ workload->wa_ctx.indirect_ctx.guest_gma =
+ indirect_ctx & INDIRECT_CTX_ADDR_MASK;
+ workload->wa_ctx.indirect_ctx.size =
+ (indirect_ctx & INDIRECT_CTX_SIZE_MASK) *
+ CACHELINE_BYTES;
+ workload->wa_ctx.per_ctx.guest_gma =
+ per_ctx & PER_CTX_ADDR_MASK;
+ workload->wa_ctx.workload = workload;
+
+ WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1));
+ }
+
+ if (emulate_schedule_in)
+ memcpy(&workload->elsp_dwords,
+ &vgpu->execlist[ring_id].elsp_dwords,
+ sizeof(workload->elsp_dwords));
+
+ gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n",
+ workload, ring_id, head, tail, start, ctl);
+
+ gvt_dbg_el("workload %p emulate schedule_in %d\n", workload,
+ emulate_schedule_in);
+
+ ret = prepare_mm(workload);
+ if (ret) {
+ kmem_cache_free(vgpu->workloads, workload);
+ return ret;
+ }
+
+ queue_workload(workload);
+ return 0;
+}
+
+int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id];
+ struct execlist_ctx_descriptor_format *desc[2], valid_desc[2];
+ unsigned long valid_desc_bitmap = 0;
+ bool emulate_schedule_in = true;
+ int ret;
+ int i;
+
+ memset(valid_desc, 0, sizeof(valid_desc));
+
+ desc[0] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1);
+ desc[1] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0);
+
+ for (i = 0; i < 2; i++) {
+ if (!desc[i]->valid)
+ continue;
+
+ if (!desc[i]->privilege_access) {
+ gvt_err("vgpu%d: unexpected GGTT elsp submission\n",
+ vgpu->id);
+ return -EINVAL;
+ }
+
+ /* TODO: add another guest context checks here. */
+ set_bit(i, &valid_desc_bitmap);
+ valid_desc[i] = *desc[i];
+ }
+
+ if (!valid_desc_bitmap) {
+ gvt_err("vgpu%d: no valid desc in a elsp submission\n",
+ vgpu->id);
+ return -EINVAL;
+ }
+
+ if (!test_bit(0, (void *)&valid_desc_bitmap) &&
+ test_bit(1, (void *)&valid_desc_bitmap)) {
+ gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n",
+ vgpu->id);
+ return -EINVAL;
+ }
+
+ /* submit workload */
+ for_each_set_bit(i, (void *)&valid_desc_bitmap, 2) {
+ ret = submit_context(vgpu, ring_id, &valid_desc[i],
+ emulate_schedule_in);
+ if (ret) {
+ gvt_err("vgpu%d: fail to schedule workload\n",
+ vgpu->id);
+ return ret;
+ }
+ emulate_schedule_in = false;
+ }
+ return 0;
+}
+
+static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id];
+ struct execlist_context_status_pointer_format ctx_status_ptr;
+ u32 ctx_status_ptr_reg;
+
+ memset(execlist, 0, sizeof(*execlist));
+
+ execlist->vgpu = vgpu;
+ execlist->ring_id = ring_id;
+ execlist->slot[0].index = 0;
+ execlist->slot[1].index = 1;
+
+ ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+ _EL_OFFSET_STATUS_PTR);
+
+ ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
+ ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7;
+ vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
+}
+
+void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)
+{
+ kmem_cache_destroy(vgpu->workloads);
+}
+
+int intel_vgpu_init_execlist(struct intel_vgpu *vgpu)
+{
+ enum intel_engine_id i;
+ struct intel_engine_cs *engine;
+
+ /* each ring has a virtual execlist engine */
+ for_each_engine(engine, vgpu->gvt->dev_priv, i) {
+ init_vgpu_execlist(vgpu, i);
+ INIT_LIST_HEAD(&vgpu->workload_q_head[i]);
+ }
+
+ vgpu->workloads = kmem_cache_create("gvt-g vgpu workload",
+ sizeof(struct intel_vgpu_workload), 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL);
+
+ if (!vgpu->workloads)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
+ unsigned long engine_mask)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct intel_engine_cs *engine;
+ struct intel_vgpu_workload *pos, *n;
+ unsigned int tmp;
+
+ for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
+ /* free the unsubmited workload in the queue */
+ list_for_each_entry_safe(pos, n,
+ &vgpu->workload_q_head[engine->id], list) {
+ list_del_init(&pos->list);
+ free_workload(pos);
+ }
+
+ init_vgpu_execlist(vgpu, engine->id);
+ }
+}
diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h
new file mode 100644
index 000000000000..7eced40a1e30
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/execlist.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ *
+ */
+
+#ifndef _GVT_EXECLIST_H_
+#define _GVT_EXECLIST_H_
+
+struct execlist_ctx_descriptor_format {
+ union {
+ u32 udw;
+ u32 context_id;
+ };
+ union {
+ u32 ldw;
+ struct {
+ u32 valid : 1;
+ u32 force_pd_restore : 1;
+ u32 force_restore : 1;
+ u32 addressing_mode : 2;
+ u32 llc_coherency : 1;
+ u32 fault_handling : 2;
+ u32 privilege_access : 1;
+ u32 reserved : 3;
+ u32 lrca : 20;
+ };
+ };
+};
+
+struct execlist_status_format {
+ union {
+ u32 ldw;
+ struct {
+ u32 current_execlist_pointer :1;
+ u32 execlist_write_pointer :1;
+ u32 execlist_queue_full :1;
+ u32 execlist_1_valid :1;
+ u32 execlist_0_valid :1;
+ u32 last_ctx_switch_reason :9;
+ u32 current_active_elm_status :2;
+ u32 arbitration_enable :1;
+ u32 execlist_1_active :1;
+ u32 execlist_0_active :1;
+ u32 reserved :13;
+ };
+ };
+ union {
+ u32 udw;
+ u32 context_id;
+ };
+};
+
+struct execlist_context_status_pointer_format {
+ union {
+ u32 dw;
+ struct {
+ u32 write_ptr :3;
+ u32 reserved :5;
+ u32 read_ptr :3;
+ u32 reserved2 :5;
+ u32 mask :16;
+ };
+ };
+};
+
+struct execlist_context_status_format {
+ union {
+ u32 ldw;
+ struct {
+ u32 idle_to_active :1;
+ u32 preempted :1;
+ u32 element_switch :1;
+ u32 active_to_idle :1;
+ u32 context_complete :1;
+ u32 wait_on_sync_flip :1;
+ u32 wait_on_vblank :1;
+ u32 wait_on_semaphore :1;
+ u32 wait_on_scanline :1;
+ u32 reserved :2;
+ u32 semaphore_wait_mode :1;
+ u32 display_plane :3;
+ u32 lite_restore :1;
+ u32 reserved_2 :16;
+ };
+ };
+ union {
+ u32 udw;
+ u32 context_id;
+ };
+};
+
+struct execlist_mmio_pair {
+ u32 addr;
+ u32 val;
+};
+
+/* The first 52 dwords in register state context */
+struct execlist_ring_context {
+ u32 nop1;
+ u32 lri_cmd_1;
+ struct execlist_mmio_pair ctx_ctrl;
+ struct execlist_mmio_pair ring_header;
+ struct execlist_mmio_pair ring_tail;
+ struct execlist_mmio_pair rb_start;
+ struct execlist_mmio_pair rb_ctrl;
+ struct execlist_mmio_pair bb_cur_head_UDW;
+ struct execlist_mmio_pair bb_cur_head_LDW;
+ struct execlist_mmio_pair bb_state;
+ struct execlist_mmio_pair second_bb_addr_UDW;
+ struct execlist_mmio_pair second_bb_addr_LDW;
+ struct execlist_mmio_pair second_bb_state;
+ struct execlist_mmio_pair bb_per_ctx_ptr;
+ struct execlist_mmio_pair rcs_indirect_ctx;
+ struct execlist_mmio_pair rcs_indirect_ctx_offset;
+ u32 nop2;
+ u32 nop3;
+ u32 nop4;
+ u32 lri_cmd_2;
+ struct execlist_mmio_pair ctx_timestamp;
+ struct execlist_mmio_pair pdp3_UDW;
+ struct execlist_mmio_pair pdp3_LDW;
+ struct execlist_mmio_pair pdp2_UDW;
+ struct execlist_mmio_pair pdp2_LDW;
+ struct execlist_mmio_pair pdp1_UDW;
+ struct execlist_mmio_pair pdp1_LDW;
+ struct execlist_mmio_pair pdp0_UDW;
+ struct execlist_mmio_pair pdp0_LDW;
+};
+
+struct intel_vgpu_elsp_dwords {
+ u32 data[4];
+ u32 index;
+};
+
+struct intel_vgpu_execlist_slot {
+ struct execlist_ctx_descriptor_format ctx[2];
+ u32 index;
+};
+
+struct intel_vgpu_execlist {
+ struct intel_vgpu_execlist_slot slot[2];
+ struct intel_vgpu_execlist_slot *running_slot;
+ struct intel_vgpu_execlist_slot *pending_slot;
+ struct execlist_ctx_descriptor_format *running_context;
+ int ring_id;
+ struct intel_vgpu *vgpu;
+ struct intel_vgpu_elsp_dwords elsp_dwords;
+};
+
+void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu);
+
+int intel_vgpu_init_execlist(struct intel_vgpu *vgpu);
+
+int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id);
+
+void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
+ unsigned long engine_mask);
+
+#endif /*_GVT_EXECLIST_H_*/
diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c
new file mode 100644
index 000000000000..2fae2a2ca96f
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/firmware.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Changbin Du <changbin.du@intel.com>
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/crc32.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+#define FIRMWARE_VERSION (0x0)
+
+struct gvt_firmware_header {
+ u64 magic;
+ u32 crc32; /* protect the data after this field */
+ u32 version;
+ u64 cfg_space_size;
+ u64 cfg_space_offset; /* offset in the file */
+ u64 mmio_size;
+ u64 mmio_offset; /* offset in the file */
+ unsigned char data[1];
+};
+
+#define RD(offset) (readl(mmio + offset.reg))
+#define WR(v, offset) (writel(v, mmio + offset.reg))
+
+static void bdw_forcewake_get(void __iomem *mmio)
+{
+ WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT);
+
+ RD(ECOBUS);
+
+ if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL) == 0, 50))
+ gvt_err("fail to wait forcewake idle\n");
+
+ WR(_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL), FORCEWAKE_MT);
+
+ if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL), 50))
+ gvt_err("fail to wait forcewake ack\n");
+
+ if (wait_for((RD(GEN6_GT_THREAD_STATUS_REG) &
+ GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 50))
+ gvt_err("fail to wait c0 wake up\n");
+}
+
+#undef RD
+#undef WR
+
+#define dev_to_drm_minor(d) dev_get_drvdata((d))
+
+static ssize_t
+gvt_firmware_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t offset, size_t count)
+{
+ memcpy(buf, attr->private + offset, count);
+ return count;
+}
+
+static struct bin_attribute firmware_attr = {
+ .attr = {.name = "gvt_firmware", .mode = (S_IRUSR)},
+ .read = gvt_firmware_read,
+ .write = NULL,
+ .mmap = NULL,
+};
+
+static int expose_firmware_sysfs(struct intel_gvt *gvt,
+ void __iomem *mmio)
+{
+ struct intel_gvt_device_info *info = &gvt->device_info;
+ struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+ struct intel_gvt_mmio_info *e;
+ struct gvt_firmware_header *h;
+ void *firmware;
+ void *p;
+ unsigned long size;
+ int i;
+ int ret;
+
+ size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
+ firmware = vmalloc(size);
+ if (!firmware)
+ return -ENOMEM;
+
+ h = firmware;
+
+ h->magic = VGT_MAGIC;
+ h->version = FIRMWARE_VERSION;
+ h->cfg_space_size = info->cfg_space_size;
+ h->cfg_space_offset = offsetof(struct gvt_firmware_header, data);
+ h->mmio_size = info->mmio_size;
+ h->mmio_offset = h->cfg_space_offset + h->cfg_space_size;
+
+ p = firmware + h->cfg_space_offset;
+
+ for (i = 0; i < h->cfg_space_size; i += 4)
+ pci_read_config_dword(pdev, i, p + i);
+
+ memcpy(gvt->firmware.cfg_space, p, info->cfg_space_size);
+
+ p = firmware + h->mmio_offset;
+
+ hash_for_each(gvt->mmio.mmio_info_table, i, e, node) {
+ int j;
+
+ for (j = 0; j < e->length; j += 4)
+ *(u32 *)(p + e->offset + j) =
+ readl(mmio + e->offset + j);
+ }
+
+ memcpy(gvt->firmware.mmio, p, info->mmio_size);
+
+ firmware_attr.size = size;
+ firmware_attr.private = firmware;
+
+ ret = device_create_bin_file(&pdev->dev, &firmware_attr);
+ if (ret) {
+ vfree(firmware);
+ return ret;
+ }
+ return 0;
+}
+
+static void clean_firmware_sysfs(struct intel_gvt *gvt)
+{
+ struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+
+ device_remove_bin_file(&pdev->dev, &firmware_attr);
+ vfree(firmware_attr.private);
+}
+
+/**
+ * intel_gvt_free_firmware - free GVT firmware
+ * @gvt: intel gvt device
+ *
+ */
+void intel_gvt_free_firmware(struct intel_gvt *gvt)
+{
+ if (!gvt->firmware.firmware_loaded)
+ clean_firmware_sysfs(gvt);
+
+ kfree(gvt->firmware.cfg_space);
+ kfree(gvt->firmware.mmio);
+}
+
+static int verify_firmware(struct intel_gvt *gvt,
+ const struct firmware *fw)
+{
+ struct intel_gvt_device_info *info = &gvt->device_info;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
+ struct gvt_firmware_header *h;
+ unsigned long id, crc32_start;
+ const void *mem;
+ const char *item;
+ u64 file, request;
+
+ h = (struct gvt_firmware_header *)fw->data;
+
+ crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
+ mem = fw->data + crc32_start;
+
+#define VERIFY(s, a, b) do { \
+ item = (s); file = (u64)(a); request = (u64)(b); \
+ if ((a) != (b)) \
+ goto invalid_firmware; \
+} while (0)
+
+ VERIFY("magic number", h->magic, VGT_MAGIC);
+ VERIFY("version", h->version, FIRMWARE_VERSION);
+ VERIFY("crc32", h->crc32, crc32_le(0, mem, fw->size - crc32_start));
+ VERIFY("cfg space size", h->cfg_space_size, info->cfg_space_size);
+ VERIFY("mmio size", h->mmio_size, info->mmio_size);
+
+ mem = (fw->data + h->cfg_space_offset);
+
+ id = *(u16 *)(mem + PCI_VENDOR_ID);
+ VERIFY("vender id", id, pdev->vendor);
+
+ id = *(u16 *)(mem + PCI_DEVICE_ID);
+ VERIFY("device id", id, pdev->device);
+
+ id = *(u8 *)(mem + PCI_REVISION_ID);
+ VERIFY("revision id", id, pdev->revision);
+
+#undef VERIFY
+ return 0;
+
+invalid_firmware:
+ gvt_dbg_core("Invalid firmware: %s [file] 0x%llx [request] 0x%llx\n",
+ item, file, request);
+ return -EINVAL;
+}
+
+#define GVT_FIRMWARE_PATH "i915/gvt"
+
+/**
+ * intel_gvt_load_firmware - load GVT firmware
+ * @gvt: intel gvt device
+ *
+ */
+int intel_gvt_load_firmware(struct intel_gvt *gvt)
+{
+ struct intel_gvt_device_info *info = &gvt->device_info;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
+ struct intel_gvt_firmware *firmware = &gvt->firmware;
+ struct gvt_firmware_header *h;
+ const struct firmware *fw;
+ char *path;
+ void __iomem *mmio;
+ void *mem;
+ int ret;
+
+ path = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!path)
+ return -ENOMEM;
+
+ mem = kmalloc(info->cfg_space_size, GFP_KERNEL);
+ if (!mem) {
+ kfree(path);
+ return -ENOMEM;
+ }
+
+ firmware->cfg_space = mem;
+
+ mem = kmalloc(info->mmio_size, GFP_KERNEL);
+ if (!mem) {
+ kfree(path);
+ kfree(firmware->cfg_space);
+ return -ENOMEM;
+ }
+
+ firmware->mmio = mem;
+
+ mmio = pci_iomap(pdev, info->mmio_bar, info->mmio_size);
+ if (!mmio) {
+ kfree(path);
+ kfree(firmware->cfg_space);
+ kfree(firmware->mmio);
+ return -EINVAL;
+ }
+
+ if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv))
+ bdw_forcewake_get(mmio);
+
+ sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state",
+ GVT_FIRMWARE_PATH, pdev->vendor, pdev->device,
+ pdev->revision);
+
+ gvt_dbg_core("request hw state firmware %s...\n", path);
+
+ ret = request_firmware(&fw, path, &dev_priv->drm.pdev->dev);
+ kfree(path);
+
+ if (ret)
+ goto expose_firmware;
+
+ gvt_dbg_core("success.\n");
+
+ ret = verify_firmware(gvt, fw);
+ if (ret)
+ goto out_free_fw;
+
+ gvt_dbg_core("verified.\n");
+
+ h = (struct gvt_firmware_header *)fw->data;
+
+ memcpy(firmware->cfg_space, fw->data + h->cfg_space_offset,
+ h->cfg_space_size);
+ memcpy(firmware->mmio, fw->data + h->mmio_offset,
+ h->mmio_size);
+
+ release_firmware(fw);
+ firmware->firmware_loaded = true;
+ pci_iounmap(pdev, mmio);
+ return 0;
+
+out_free_fw:
+ release_firmware(fw);
+expose_firmware:
+ expose_firmware_sysfs(gvt, mmio);
+ pci_iounmap(pdev, mmio);
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
new file mode 100644
index 000000000000..7eaaf1c9ed2b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -0,0 +1,2244 @@
+/*
+ * GTT virtualization
+ *
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ * Xiao Zheng <xiao.zheng@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+#include "trace.h"
+
+static bool enable_out_of_sync = false;
+static int preallocated_oos_pages = 8192;
+
+/*
+ * validate a gm address and related range size,
+ * translate it to host gm address
+ */
+bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size)
+{
+ if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size
+ && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) {
+ gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n",
+ vgpu->id, addr, size);
+ return false;
+ }
+ return true;
+}
+
+/* translate a guest gmadr to host gmadr */
+int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr)
+{
+ if (WARN(!vgpu_gmadr_is_valid(vgpu, g_addr),
+ "invalid guest gmadr %llx\n", g_addr))
+ return -EACCES;
+
+ if (vgpu_gmadr_is_aperture(vgpu, g_addr))
+ *h_addr = vgpu_aperture_gmadr_base(vgpu)
+ + (g_addr - vgpu_aperture_offset(vgpu));
+ else
+ *h_addr = vgpu_hidden_gmadr_base(vgpu)
+ + (g_addr - vgpu_hidden_offset(vgpu));
+ return 0;
+}
+
+/* translate a host gmadr to guest gmadr */
+int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr)
+{
+ if (WARN(!gvt_gmadr_is_valid(vgpu->gvt, h_addr),
+ "invalid host gmadr %llx\n", h_addr))
+ return -EACCES;
+
+ if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr))
+ *g_addr = vgpu_aperture_gmadr_base(vgpu)
+ + (h_addr - gvt_aperture_gmadr_base(vgpu->gvt));
+ else
+ *g_addr = vgpu_hidden_gmadr_base(vgpu)
+ + (h_addr - gvt_hidden_gmadr_base(vgpu->gvt));
+ return 0;
+}
+
+int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
+ unsigned long *h_index)
+{
+ u64 h_addr;
+ int ret;
+
+ ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << GTT_PAGE_SHIFT,
+ &h_addr);
+ if (ret)
+ return ret;
+
+ *h_index = h_addr >> GTT_PAGE_SHIFT;
+ return 0;
+}
+
+int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
+ unsigned long *g_index)
+{
+ u64 g_addr;
+ int ret;
+
+ ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << GTT_PAGE_SHIFT,
+ &g_addr);
+ if (ret)
+ return ret;
+
+ *g_index = g_addr >> GTT_PAGE_SHIFT;
+ return 0;
+}
+
+#define gtt_type_is_entry(type) \
+ (type > GTT_TYPE_INVALID && type < GTT_TYPE_PPGTT_ENTRY \
+ && type != GTT_TYPE_PPGTT_PTE_ENTRY \
+ && type != GTT_TYPE_PPGTT_ROOT_ENTRY)
+
+#define gtt_type_is_pt(type) \
+ (type >= GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX)
+
+#define gtt_type_is_pte_pt(type) \
+ (type == GTT_TYPE_PPGTT_PTE_PT)
+
+#define gtt_type_is_root_pointer(type) \
+ (gtt_type_is_entry(type) && type > GTT_TYPE_PPGTT_ROOT_ENTRY)
+
+#define gtt_init_entry(e, t, p, v) do { \
+ (e)->type = t; \
+ (e)->pdev = p; \
+ memcpy(&(e)->val64, &v, sizeof(v)); \
+} while (0)
+
+/*
+ * Mappings between GTT_TYPE* enumerations.
+ * Following information can be found according to the given type:
+ * - type of next level page table
+ * - type of entry inside this level page table
+ * - type of entry with PSE set
+ *
+ * If the given type doesn't have such a kind of information,
+ * e.g. give a l4 root entry type, then request to get its PSE type,
+ * give a PTE page table type, then request to get its next level page
+ * table type, as we know l4 root entry doesn't have a PSE bit,
+ * and a PTE page table doesn't have a next level page table type,
+ * GTT_TYPE_INVALID will be returned. This is useful when traversing a
+ * page table.
+ */
+
+struct gtt_type_table_entry {
+ int entry_type;
+ int next_pt_type;
+ int pse_entry_type;
+};
+
+#define GTT_TYPE_TABLE_ENTRY(type, e_type, npt_type, pse_type) \
+ [type] = { \
+ .entry_type = e_type, \
+ .next_pt_type = npt_type, \
+ .pse_entry_type = pse_type, \
+ }
+
+static struct gtt_type_table_entry gtt_type_table[] = {
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+ GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+ GTT_TYPE_PPGTT_PML4_PT,
+ GTT_TYPE_INVALID),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_PT,
+ GTT_TYPE_PPGTT_PML4_ENTRY,
+ GTT_TYPE_PPGTT_PDP_PT,
+ GTT_TYPE_INVALID),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_ENTRY,
+ GTT_TYPE_PPGTT_PML4_ENTRY,
+ GTT_TYPE_PPGTT_PDP_PT,
+ GTT_TYPE_INVALID),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_PT,
+ GTT_TYPE_PPGTT_PDP_ENTRY,
+ GTT_TYPE_PPGTT_PDE_PT,
+ GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+ GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+ GTT_TYPE_PPGTT_PDE_PT,
+ GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_ENTRY,
+ GTT_TYPE_PPGTT_PDP_ENTRY,
+ GTT_TYPE_PPGTT_PDE_PT,
+ GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_PT,
+ GTT_TYPE_PPGTT_PDE_ENTRY,
+ GTT_TYPE_PPGTT_PTE_PT,
+ GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_ENTRY,
+ GTT_TYPE_PPGTT_PDE_ENTRY,
+ GTT_TYPE_PPGTT_PTE_PT,
+ GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT,
+ GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+ GTT_TYPE_INVALID,
+ GTT_TYPE_INVALID),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+ GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+ GTT_TYPE_INVALID,
+ GTT_TYPE_INVALID),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY,
+ GTT_TYPE_PPGTT_PDE_ENTRY,
+ GTT_TYPE_INVALID,
+ GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_1G_ENTRY,
+ GTT_TYPE_PPGTT_PDP_ENTRY,
+ GTT_TYPE_INVALID,
+ GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+ GTT_TYPE_TABLE_ENTRY(GTT_TYPE_GGTT_PTE,
+ GTT_TYPE_GGTT_PTE,
+ GTT_TYPE_INVALID,
+ GTT_TYPE_INVALID),
+};
+
+static inline int get_next_pt_type(int type)
+{
+ return gtt_type_table[type].next_pt_type;
+}
+
+static inline int get_entry_type(int type)
+{
+ return gtt_type_table[type].entry_type;
+}
+
+static inline int get_pse_type(int type)
+{
+ return gtt_type_table[type].pse_entry_type;
+}
+
+static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index)
+{
+ void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
+ u64 pte;
+
+#ifdef readq
+ pte = readq(addr);
+#else
+ pte = ioread32(addr);
+ pte |= (u64)ioread32(addr + 4) << 32;
+#endif
+ return pte;
+}
+
+static void write_pte64(struct drm_i915_private *dev_priv,
+ unsigned long index, u64 pte)
+{
+ void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
+
+#ifdef writeq
+ writeq(pte, addr);
+#else
+ iowrite32((u32)pte, addr);
+ iowrite32(pte >> 32, addr + 4);
+#endif
+ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
+ POSTING_READ(GFX_FLSH_CNTL_GEN6);
+}
+
+static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
+ struct intel_gvt_gtt_entry *e,
+ unsigned long index, bool hypervisor_access, unsigned long gpa,
+ struct intel_vgpu *vgpu)
+{
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ int ret;
+
+ if (WARN_ON(info->gtt_entry_size != 8))
+ return e;
+
+ if (hypervisor_access) {
+ ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa +
+ (index << info->gtt_entry_size_shift),
+ &e->val64, 8);
+ WARN_ON(ret);
+ } else if (!pt) {
+ e->val64 = read_pte64(vgpu->gvt->dev_priv, index);
+ } else {
+ e->val64 = *((u64 *)pt + index);
+ }
+ return e;
+}
+
+static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
+ struct intel_gvt_gtt_entry *e,
+ unsigned long index, bool hypervisor_access, unsigned long gpa,
+ struct intel_vgpu *vgpu)
+{
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ int ret;
+
+ if (WARN_ON(info->gtt_entry_size != 8))
+ return e;
+
+ if (hypervisor_access) {
+ ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa +
+ (index << info->gtt_entry_size_shift),
+ &e->val64, 8);
+ WARN_ON(ret);
+ } else if (!pt) {
+ write_pte64(vgpu->gvt->dev_priv, index, e->val64);
+ } else {
+ *((u64 *)pt + index) = e->val64;
+ }
+ return e;
+}
+
+#define GTT_HAW 46
+
+#define ADDR_1G_MASK (((1UL << (GTT_HAW - 30 + 1)) - 1) << 30)
+#define ADDR_2M_MASK (((1UL << (GTT_HAW - 21 + 1)) - 1) << 21)
+#define ADDR_4K_MASK (((1UL << (GTT_HAW - 12 + 1)) - 1) << 12)
+
+static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
+{
+ unsigned long pfn;
+
+ if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY)
+ pfn = (e->val64 & ADDR_1G_MASK) >> 12;
+ else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY)
+ pfn = (e->val64 & ADDR_2M_MASK) >> 12;
+ else
+ pfn = (e->val64 & ADDR_4K_MASK) >> 12;
+ return pfn;
+}
+
+static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, unsigned long pfn)
+{
+ if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) {
+ e->val64 &= ~ADDR_1G_MASK;
+ pfn &= (ADDR_1G_MASK >> 12);
+ } else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) {
+ e->val64 &= ~ADDR_2M_MASK;
+ pfn &= (ADDR_2M_MASK >> 12);
+ } else {
+ e->val64 &= ~ADDR_4K_MASK;
+ pfn &= (ADDR_4K_MASK >> 12);
+ }
+
+ e->val64 |= (pfn << 12);
+}
+
+static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e)
+{
+ /* Entry doesn't have PSE bit. */
+ if (get_pse_type(e->type) == GTT_TYPE_INVALID)
+ return false;
+
+ e->type = get_entry_type(e->type);
+ if (!(e->val64 & (1 << 7)))
+ return false;
+
+ e->type = get_pse_type(e->type);
+ return true;
+}
+
+static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e)
+{
+ /*
+ * i915 writes PDP root pointer registers without present bit,
+ * it also works, so we need to treat root pointer entry
+ * specifically.
+ */
+ if (e->type == GTT_TYPE_PPGTT_ROOT_L3_ENTRY
+ || e->type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY)
+ return (e->val64 != 0);
+ else
+ return (e->val64 & (1 << 0));
+}
+
+static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e)
+{
+ e->val64 &= ~(1 << 0);
+}
+
+/*
+ * Per-platform GMA routines.
+ */
+static unsigned long gma_to_ggtt_pte_index(unsigned long gma)
+{
+ unsigned long x = (gma >> GTT_PAGE_SHIFT);
+
+ trace_gma_index(__func__, gma, x);
+ return x;
+}
+
+#define DEFINE_PPGTT_GMA_TO_INDEX(prefix, ename, exp) \
+static unsigned long prefix##_gma_to_##ename##_index(unsigned long gma) \
+{ \
+ unsigned long x = (exp); \
+ trace_gma_index(__func__, gma, x); \
+ return x; \
+}
+
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pte, (gma >> 12 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pde, (gma >> 21 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, l3_pdp, (gma >> 30 & 0x3));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, l4_pdp, (gma >> 30 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pml4, (gma >> 39 & 0x1ff));
+
+static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
+ .get_entry = gtt_get_entry64,
+ .set_entry = gtt_set_entry64,
+ .clear_present = gtt_entry_clear_present,
+ .test_present = gen8_gtt_test_present,
+ .test_pse = gen8_gtt_test_pse,
+ .get_pfn = gen8_gtt_get_pfn,
+ .set_pfn = gen8_gtt_set_pfn,
+};
+
+static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = {
+ .gma_to_ggtt_pte_index = gma_to_ggtt_pte_index,
+ .gma_to_pte_index = gen8_gma_to_pte_index,
+ .gma_to_pde_index = gen8_gma_to_pde_index,
+ .gma_to_l3_pdp_index = gen8_gma_to_l3_pdp_index,
+ .gma_to_l4_pdp_index = gen8_gma_to_l4_pdp_index,
+ .gma_to_pml4_index = gen8_gma_to_pml4_index,
+};
+
+static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
+ struct intel_gvt_gtt_entry *m)
+{
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ unsigned long gfn, mfn;
+
+ *m = *p;
+
+ if (!ops->test_present(p))
+ return 0;
+
+ gfn = ops->get_pfn(p);
+
+ mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
+ if (mfn == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("fail to translate gfn: 0x%lx\n", gfn);
+ return -ENXIO;
+ }
+
+ ops->set_pfn(m, mfn);
+ return 0;
+}
+
+/*
+ * MM helpers.
+ */
+struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
+ void *page_table, struct intel_gvt_gtt_entry *e,
+ unsigned long index)
+{
+ struct intel_gvt *gvt = mm->vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+ e->type = mm->page_table_entry_type;
+
+ ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
+ ops->test_pse(e);
+ return e;
+}
+
+struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
+ void *page_table, struct intel_gvt_gtt_entry *e,
+ unsigned long index)
+{
+ struct intel_gvt *gvt = mm->vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+ return ops->set_entry(page_table, e, index, false, 0, mm->vgpu);
+}
+
+/*
+ * PPGTT shadow page table helpers.
+ */
+static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
+ struct intel_vgpu_ppgtt_spt *spt,
+ void *page_table, int type,
+ struct intel_gvt_gtt_entry *e, unsigned long index,
+ bool guest)
+{
+ struct intel_gvt *gvt = spt->vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+ e->type = get_entry_type(type);
+
+ if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
+ return e;
+
+ ops->get_entry(page_table, e, index, guest,
+ spt->guest_page.gfn << GTT_PAGE_SHIFT,
+ spt->vgpu);
+ ops->test_pse(e);
+ return e;
+}
+
+static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
+ struct intel_vgpu_ppgtt_spt *spt,
+ void *page_table, int type,
+ struct intel_gvt_gtt_entry *e, unsigned long index,
+ bool guest)
+{
+ struct intel_gvt *gvt = spt->vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+ if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
+ return e;
+
+ return ops->set_entry(page_table, e, index, guest,
+ spt->guest_page.gfn << GTT_PAGE_SHIFT,
+ spt->vgpu);
+}
+
+#define ppgtt_get_guest_entry(spt, e, index) \
+ ppgtt_spt_get_entry(spt, NULL, \
+ spt->guest_page_type, e, index, true)
+
+#define ppgtt_set_guest_entry(spt, e, index) \
+ ppgtt_spt_set_entry(spt, NULL, \
+ spt->guest_page_type, e, index, true)
+
+#define ppgtt_get_shadow_entry(spt, e, index) \
+ ppgtt_spt_get_entry(spt, spt->shadow_page.vaddr, \
+ spt->shadow_page.type, e, index, false)
+
+#define ppgtt_set_shadow_entry(spt, e, index) \
+ ppgtt_spt_set_entry(spt, spt->shadow_page.vaddr, \
+ spt->shadow_page.type, e, index, false)
+
+/**
+ * intel_vgpu_init_guest_page - init a guest page data structure
+ * @vgpu: a vGPU
+ * @p: a guest page data structure
+ * @gfn: guest memory page frame number
+ * @handler: function will be called when target guest memory page has
+ * been modified.
+ *
+ * This function is called when user wants to track a guest memory page.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *p,
+ unsigned long gfn,
+ int (*handler)(void *, u64, void *, int),
+ void *data)
+{
+ INIT_HLIST_NODE(&p->node);
+
+ p->writeprotection = false;
+ p->gfn = gfn;
+ p->handler = handler;
+ p->data = data;
+ p->oos_page = NULL;
+ p->write_cnt = 0;
+
+ hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn);
+ return 0;
+}
+
+static int detach_oos_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_oos_page *oos_page);
+
+/**
+ * intel_vgpu_clean_guest_page - release the resource owned by guest page data
+ * structure
+ * @vgpu: a vGPU
+ * @p: a tracked guest page
+ *
+ * This function is called when user tries to stop tracking a guest memory
+ * page.
+ */
+void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *p)
+{
+ if (!hlist_unhashed(&p->node))
+ hash_del(&p->node);
+
+ if (p->oos_page)
+ detach_oos_page(vgpu, p->oos_page);
+
+ if (p->writeprotection)
+ intel_gvt_hypervisor_unset_wp_page(vgpu, p);
+}
+
+/**
+ * intel_vgpu_find_guest_page - find a guest page data structure by GFN.
+ * @vgpu: a vGPU
+ * @gfn: guest memory page frame number
+ *
+ * This function is called when emulation logic wants to know if a trapped GFN
+ * is a tracked guest page.
+ *
+ * Returns:
+ * Pointer to guest page data structure, NULL if failed.
+ */
+struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
+ struct intel_vgpu *vgpu, unsigned long gfn)
+{
+ struct intel_vgpu_guest_page *p;
+
+ hash_for_each_possible(vgpu->gtt.guest_page_hash_table,
+ p, node, gfn) {
+ if (p->gfn == gfn)
+ return p;
+ }
+ return NULL;
+}
+
+static inline int init_shadow_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_shadow_page *p, int type)
+{
+ p->vaddr = page_address(p->page);
+ p->type = type;
+
+ INIT_HLIST_NODE(&p->node);
+
+ p->mfn = intel_gvt_hypervisor_virt_to_mfn(p->vaddr);
+ if (p->mfn == INTEL_GVT_INVALID_ADDR)
+ return -EFAULT;
+
+ hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn);
+ return 0;
+}
+
+static inline void clean_shadow_page(struct intel_vgpu_shadow_page *p)
+{
+ if (!hlist_unhashed(&p->node))
+ hash_del(&p->node);
+}
+
+static inline struct intel_vgpu_shadow_page *find_shadow_page(
+ struct intel_vgpu *vgpu, unsigned long mfn)
+{
+ struct intel_vgpu_shadow_page *p;
+
+ hash_for_each_possible(vgpu->gtt.shadow_page_hash_table,
+ p, node, mfn) {
+ if (p->mfn == mfn)
+ return p;
+ }
+ return NULL;
+}
+
+#define guest_page_to_ppgtt_spt(ptr) \
+ container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page)
+
+#define shadow_page_to_ppgtt_spt(ptr) \
+ container_of(ptr, struct intel_vgpu_ppgtt_spt, shadow_page)
+
+static void *alloc_spt(gfp_t gfp_mask)
+{
+ struct intel_vgpu_ppgtt_spt *spt;
+
+ spt = kzalloc(sizeof(*spt), gfp_mask);
+ if (!spt)
+ return NULL;
+
+ spt->shadow_page.page = alloc_page(gfp_mask);
+ if (!spt->shadow_page.page) {
+ kfree(spt);
+ return NULL;
+ }
+ return spt;
+}
+
+static void free_spt(struct intel_vgpu_ppgtt_spt *spt)
+{
+ __free_page(spt->shadow_page.page);
+ kfree(spt);
+}
+
+static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+ trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type);
+
+ clean_shadow_page(&spt->shadow_page);
+ intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page);
+ list_del_init(&spt->post_shadow_list);
+
+ free_spt(spt);
+}
+
+static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu)
+{
+ struct hlist_node *n;
+ struct intel_vgpu_shadow_page *sp;
+ int i;
+
+ hash_for_each_safe(vgpu->gtt.shadow_page_hash_table, i, n, sp, node)
+ ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp));
+}
+
+static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
+ u64 pa, void *p_data, int bytes);
+
+static int ppgtt_write_protection_handler(void *gp, u64 pa,
+ void *p_data, int bytes)
+{
+ struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp;
+ int ret;
+
+ if (bytes != 4 && bytes != 8)
+ return -EINVAL;
+
+ if (!gpt->writeprotection)
+ return -EINVAL;
+
+ ret = ppgtt_handle_guest_write_page_table_bytes(gp,
+ pa, p_data, bytes);
+ if (ret)
+ return ret;
+ return ret;
+}
+
+static int reclaim_one_mm(struct intel_gvt *gvt);
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page(
+ struct intel_vgpu *vgpu, int type, unsigned long gfn)
+{
+ struct intel_vgpu_ppgtt_spt *spt = NULL;
+ int ret;
+
+retry:
+ spt = alloc_spt(GFP_KERNEL | __GFP_ZERO);
+ if (!spt) {
+ if (reclaim_one_mm(vgpu->gvt))
+ goto retry;
+
+ gvt_err("fail to allocate ppgtt shadow page\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ spt->vgpu = vgpu;
+ spt->guest_page_type = type;
+ atomic_set(&spt->refcount, 1);
+ INIT_LIST_HEAD(&spt->post_shadow_list);
+
+ /*
+ * TODO: guest page type may be different with shadow page type,
+ * when we support PSE page in future.
+ */
+ ret = init_shadow_page(vgpu, &spt->shadow_page, type);
+ if (ret) {
+ gvt_err("fail to initialize shadow page for spt\n");
+ goto err;
+ }
+
+ ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page,
+ gfn, ppgtt_write_protection_handler, NULL);
+ if (ret) {
+ gvt_err("fail to initialize guest page for spt\n");
+ goto err;
+ }
+
+ trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
+ return spt;
+err:
+ ppgtt_free_shadow_page(spt);
+ return ERR_PTR(ret);
+}
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(
+ struct intel_vgpu *vgpu, unsigned long mfn)
+{
+ struct intel_vgpu_shadow_page *p = find_shadow_page(vgpu, mfn);
+
+ if (p)
+ return shadow_page_to_ppgtt_spt(p);
+
+ gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n",
+ vgpu->id, mfn);
+ return NULL;
+}
+
+#define pt_entry_size_shift(spt) \
+ ((spt)->vgpu->gvt->device_info.gtt_entry_size_shift)
+
+#define pt_entries(spt) \
+ (GTT_PAGE_SIZE >> pt_entry_size_shift(spt))
+
+#define for_each_present_guest_entry(spt, e, i) \
+ for (i = 0; i < pt_entries(spt); i++) \
+ if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
+ ppgtt_get_guest_entry(spt, e, i)))
+
+#define for_each_present_shadow_entry(spt, e, i) \
+ for (i = 0; i < pt_entries(spt); i++) \
+ if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
+ ppgtt_get_shadow_entry(spt, e, i)))
+
+static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+ int v = atomic_read(&spt->refcount);
+
+ trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1));
+
+ atomic_inc(&spt->refcount);
+}
+
+static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt);
+
+static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
+ struct intel_gvt_gtt_entry *e)
+{
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ struct intel_vgpu_ppgtt_spt *s;
+ intel_gvt_gtt_type_t cur_pt_type;
+
+ if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type))))
+ return -EINVAL;
+
+ if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY
+ && e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
+ cur_pt_type = get_next_pt_type(e->type) + 1;
+ if (ops->get_pfn(e) ==
+ vgpu->gtt.scratch_pt[cur_pt_type].page_mfn)
+ return 0;
+ }
+ s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
+ if (!s) {
+ gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n",
+ vgpu->id, ops->get_pfn(e));
+ return -ENXIO;
+ }
+ return ppgtt_invalidate_shadow_page(s);
+}
+
+static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+ struct intel_gvt_gtt_entry e;
+ unsigned long index;
+ int ret;
+ int v = atomic_read(&spt->refcount);
+
+ trace_spt_change(spt->vgpu->id, "die", spt,
+ spt->guest_page.gfn, spt->shadow_page.type);
+
+ trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
+
+ if (atomic_dec_return(&spt->refcount) > 0)
+ return 0;
+
+ if (gtt_type_is_pte_pt(spt->shadow_page.type))
+ goto release;
+
+ for_each_present_shadow_entry(spt, &e, index) {
+ if (!gtt_type_is_pt(get_next_pt_type(e.type))) {
+ gvt_err("GVT doesn't support pse bit for now\n");
+ return -EINVAL;
+ }
+ ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
+ spt->vgpu, &e);
+ if (ret)
+ goto fail;
+ }
+release:
+ trace_spt_change(spt->vgpu->id, "release", spt,
+ spt->guest_page.gfn, spt->shadow_page.type);
+ ppgtt_free_shadow_page(spt);
+ return 0;
+fail:
+ gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n",
+ spt->vgpu->id, spt, e.val64, e.type);
+ return ret;
+}
+
+static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt);
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
+ struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *we)
+{
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ struct intel_vgpu_ppgtt_spt *s = NULL;
+ struct intel_vgpu_guest_page *g;
+ int ret;
+
+ if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we));
+ if (g) {
+ s = guest_page_to_ppgtt_spt(g);
+ ppgtt_get_shadow_page(s);
+ } else {
+ int type = get_next_pt_type(we->type);
+
+ s = ppgtt_alloc_shadow_page(vgpu, type, ops->get_pfn(we));
+ if (IS_ERR(s)) {
+ ret = PTR_ERR(s);
+ goto fail;
+ }
+
+ ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page);
+ if (ret)
+ goto fail;
+
+ ret = ppgtt_populate_shadow_page(s);
+ if (ret)
+ goto fail;
+
+ trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn,
+ s->shadow_page.type);
+ }
+ return s;
+fail:
+ gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+ vgpu->id, s, we->val64, we->type);
+ return ERR_PTR(ret);
+}
+
+static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
+ struct intel_vgpu_ppgtt_spt *s, struct intel_gvt_gtt_entry *ge)
+{
+ struct intel_gvt_gtt_pte_ops *ops = s->vgpu->gvt->gtt.pte_ops;
+
+ se->type = ge->type;
+ se->val64 = ge->val64;
+
+ ops->set_pfn(se, s->shadow_page.mfn);
+}
+
+static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_vgpu_ppgtt_spt *s;
+ struct intel_gvt_gtt_entry se, ge;
+ unsigned long i;
+ int ret;
+
+ trace_spt_change(spt->vgpu->id, "born", spt,
+ spt->guest_page.gfn, spt->shadow_page.type);
+
+ if (gtt_type_is_pte_pt(spt->shadow_page.type)) {
+ for_each_present_guest_entry(spt, &ge, i) {
+ ret = gtt_entry_p2m(vgpu, &ge, &se);
+ if (ret)
+ goto fail;
+ ppgtt_set_shadow_entry(spt, &se, i);
+ }
+ return 0;
+ }
+
+ for_each_present_guest_entry(spt, &ge, i) {
+ if (!gtt_type_is_pt(get_next_pt_type(ge.type))) {
+ gvt_err("GVT doesn't support pse bit now\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
+ if (IS_ERR(s)) {
+ ret = PTR_ERR(s);
+ goto fail;
+ }
+ ppgtt_get_shadow_entry(spt, &se, i);
+ ppgtt_generate_shadow_entry(&se, s, &ge);
+ ppgtt_set_shadow_entry(spt, &se, i);
+ }
+ return 0;
+fail:
+ gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+ vgpu->id, spt, ge.val64, ge.type);
+ return ret;
+}
+
+static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
+ unsigned long index)
+{
+ struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+ struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ struct intel_gvt_gtt_entry e;
+ int ret;
+
+ ppgtt_get_shadow_entry(spt, &e, index);
+
+ trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, e.val64,
+ index);
+
+ if (!ops->test_present(&e))
+ return 0;
+
+ if (ops->get_pfn(&e) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
+ return 0;
+
+ if (gtt_type_is_pt(get_next_pt_type(e.type))) {
+ struct intel_vgpu_ppgtt_spt *s =
+ ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));
+ if (!s) {
+ gvt_err("fail to find guest page\n");
+ ret = -ENXIO;
+ goto fail;
+ }
+ ret = ppgtt_invalidate_shadow_page(s);
+ if (ret)
+ goto fail;
+ }
+ ops->set_pfn(&e, vgpu->gtt.scratch_pt[sp->type].page_mfn);
+ ppgtt_set_shadow_entry(spt, &e, index);
+ return 0;
+fail:
+ gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+ vgpu->id, spt, e.val64, e.type);
+ return ret;
+}
+
+static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
+ struct intel_gvt_gtt_entry *we, unsigned long index)
+{
+ struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+ struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_gvt_gtt_entry m;
+ struct intel_vgpu_ppgtt_spt *s;
+ int ret;
+
+ trace_gpt_change(spt->vgpu->id, "add", spt, sp->type,
+ we->val64, index);
+
+ if (gtt_type_is_pt(get_next_pt_type(we->type))) {
+ s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, we);
+ if (IS_ERR(s)) {
+ ret = PTR_ERR(s);
+ goto fail;
+ }
+ ppgtt_get_shadow_entry(spt, &m, index);
+ ppgtt_generate_shadow_entry(&m, s, we);
+ ppgtt_set_shadow_entry(spt, &m, index);
+ } else {
+ ret = gtt_entry_p2m(vgpu, we, &m);
+ if (ret)
+ goto fail;
+ ppgtt_set_shadow_entry(spt, &m, index);
+ }
+ return 0;
+fail:
+ gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id,
+ spt, we->val64, we->type);
+ return ret;
+}
+
+static int sync_oos_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_oos_page *oos_page)
+{
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+ struct intel_vgpu_ppgtt_spt *spt =
+ guest_page_to_ppgtt_spt(oos_page->guest_page);
+ struct intel_gvt_gtt_entry old, new, m;
+ int index;
+ int ret;
+
+ trace_oos_change(vgpu->id, "sync", oos_page->id,
+ oos_page->guest_page, spt->guest_page_type);
+
+ old.type = new.type = get_entry_type(spt->guest_page_type);
+ old.val64 = new.val64 = 0;
+
+ for (index = 0; index < (GTT_PAGE_SIZE >> info->gtt_entry_size_shift);
+ index++) {
+ ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu);
+ ops->get_entry(NULL, &new, index, true,
+ oos_page->guest_page->gfn << PAGE_SHIFT, vgpu);
+
+ if (old.val64 == new.val64
+ && !test_and_clear_bit(index, spt->post_shadow_bitmap))
+ continue;
+
+ trace_oos_sync(vgpu->id, oos_page->id,
+ oos_page->guest_page, spt->guest_page_type,
+ new.val64, index);
+
+ ret = gtt_entry_p2m(vgpu, &new, &m);
+ if (ret)
+ return ret;
+
+ ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu);
+ ppgtt_set_shadow_entry(spt, &m, index);
+ }
+
+ oos_page->guest_page->write_cnt = 0;
+ list_del_init(&spt->post_shadow_list);
+ return 0;
+}
+
+static int detach_oos_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_oos_page *oos_page)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_vgpu_ppgtt_spt *spt =
+ guest_page_to_ppgtt_spt(oos_page->guest_page);
+
+ trace_oos_change(vgpu->id, "detach", oos_page->id,
+ oos_page->guest_page, spt->guest_page_type);
+
+ oos_page->guest_page->write_cnt = 0;
+ oos_page->guest_page->oos_page = NULL;
+ oos_page->guest_page = NULL;
+
+ list_del_init(&oos_page->vm_list);
+ list_move_tail(&oos_page->list, &gvt->gtt.oos_page_free_list_head);
+
+ return 0;
+}
+
+static int attach_oos_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_oos_page *oos_page,
+ struct intel_vgpu_guest_page *gpt)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ int ret;
+
+ ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT,
+ oos_page->mem, GTT_PAGE_SIZE);
+ if (ret)
+ return ret;
+
+ oos_page->guest_page = gpt;
+ gpt->oos_page = oos_page;
+
+ list_move_tail(&oos_page->list, &gvt->gtt.oos_page_use_list_head);
+
+ trace_oos_change(vgpu->id, "attach", gpt->oos_page->id,
+ gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+ return 0;
+}
+
+static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *gpt)
+{
+ int ret;
+
+ ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt);
+ if (ret)
+ return ret;
+
+ trace_oos_change(vgpu->id, "set page sync", gpt->oos_page->id,
+ gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+
+ list_del_init(&gpt->oos_page->vm_list);
+ return sync_oos_page(vgpu, gpt->oos_page);
+}
+
+static int ppgtt_allocate_oos_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *gpt)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct intel_vgpu_oos_page *oos_page = gpt->oos_page;
+ int ret;
+
+ WARN(oos_page, "shadow PPGTT page has already has a oos page\n");
+
+ if (list_empty(&gtt->oos_page_free_list_head)) {
+ oos_page = container_of(gtt->oos_page_use_list_head.next,
+ struct intel_vgpu_oos_page, list);
+ ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page);
+ if (ret)
+ return ret;
+ ret = detach_oos_page(vgpu, oos_page);
+ if (ret)
+ return ret;
+ } else
+ oos_page = container_of(gtt->oos_page_free_list_head.next,
+ struct intel_vgpu_oos_page, list);
+ return attach_oos_page(vgpu, oos_page, gpt);
+}
+
+static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *gpt)
+{
+ struct intel_vgpu_oos_page *oos_page = gpt->oos_page;
+
+ if (WARN(!oos_page, "shadow PPGTT page should have a oos page\n"))
+ return -EINVAL;
+
+ trace_oos_change(vgpu->id, "set page out of sync", gpt->oos_page->id,
+ gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+
+ list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head);
+ return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt);
+}
+
+/**
+ * intel_vgpu_sync_oos_pages - sync all the out-of-synced shadow for vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is called before submitting a guest workload to host,
+ * to sync all the out-of-synced shadow for vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu)
+{
+ struct list_head *pos, *n;
+ struct intel_vgpu_oos_page *oos_page;
+ int ret;
+
+ if (!enable_out_of_sync)
+ return 0;
+
+ list_for_each_safe(pos, n, &vgpu->gtt.oos_page_list_head) {
+ oos_page = container_of(pos,
+ struct intel_vgpu_oos_page, vm_list);
+ ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/*
+ * The heart of PPGTT shadow page table.
+ */
+static int ppgtt_handle_guest_write_page_table(
+ struct intel_vgpu_guest_page *gpt,
+ struct intel_gvt_gtt_entry *we, unsigned long index)
+{
+ struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+
+ int ret;
+ int new_present;
+
+ new_present = ops->test_present(we);
+
+ ret = ppgtt_handle_guest_entry_removal(gpt, index);
+ if (ret)
+ goto fail;
+
+ if (new_present) {
+ ret = ppgtt_handle_guest_entry_add(gpt, we, index);
+ if (ret)
+ goto fail;
+ }
+ return 0;
+fail:
+ gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n",
+ vgpu->id, spt, we->val64, we->type);
+ return ret;
+}
+
+static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt)
+{
+ return enable_out_of_sync
+ && gtt_type_is_pte_pt(
+ guest_page_to_ppgtt_spt(gpt)->guest_page_type)
+ && gpt->write_cnt >= 2;
+}
+
+static void ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt,
+ unsigned long index)
+{
+ set_bit(index, spt->post_shadow_bitmap);
+ if (!list_empty(&spt->post_shadow_list))
+ return;
+
+ list_add_tail(&spt->post_shadow_list,
+ &spt->vgpu->gtt.post_shadow_list_head);
+}
+
+/**
+ * intel_vgpu_flush_post_shadow - flush the post shadow transactions
+ * @vgpu: a vGPU
+ *
+ * This function is called before submitting a guest workload to host,
+ * to flush all the post shadows for a vGPU.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu)
+{
+ struct list_head *pos, *n;
+ struct intel_vgpu_ppgtt_spt *spt;
+ struct intel_gvt_gtt_entry ge;
+ unsigned long index;
+ int ret;
+
+ list_for_each_safe(pos, n, &vgpu->gtt.post_shadow_list_head) {
+ spt = container_of(pos, struct intel_vgpu_ppgtt_spt,
+ post_shadow_list);
+
+ for_each_set_bit(index, spt->post_shadow_bitmap,
+ GTT_ENTRY_NUM_IN_ONE_PAGE) {
+ ppgtt_get_guest_entry(spt, &ge, index);
+
+ ret = ppgtt_handle_guest_write_page_table(
+ &spt->guest_page, &ge, index);
+ if (ret)
+ return ret;
+ clear_bit(index, spt->post_shadow_bitmap);
+ }
+ list_del_init(&spt->post_shadow_list);
+ }
+ return 0;
+}
+
+static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
+ u64 pa, void *p_data, int bytes)
+{
+ struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp;
+ struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+ struct intel_vgpu *vgpu = spt->vgpu;
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ struct intel_gvt_gtt_entry we;
+ unsigned long index;
+ int ret;
+
+ index = (pa & (PAGE_SIZE - 1)) >> info->gtt_entry_size_shift;
+
+ ppgtt_get_guest_entry(spt, &we, index);
+
+ ops->test_pse(&we);
+
+ if (bytes == info->gtt_entry_size) {
+ ret = ppgtt_handle_guest_write_page_table(gpt, &we, index);
+ if (ret)
+ return ret;
+ } else {
+ if (!test_bit(index, spt->post_shadow_bitmap)) {
+ ret = ppgtt_handle_guest_entry_removal(gpt, index);
+ if (ret)
+ return ret;
+ }
+
+ ppgtt_set_post_shadow(spt, index);
+ }
+
+ if (!enable_out_of_sync)
+ return 0;
+
+ gpt->write_cnt++;
+
+ if (gpt->oos_page)
+ ops->set_entry(gpt->oos_page->mem, &we, index,
+ false, 0, vgpu);
+
+ if (can_do_out_of_sync(gpt)) {
+ if (!gpt->oos_page)
+ ppgtt_allocate_oos_page(vgpu, gpt);
+
+ ret = ppgtt_set_guest_page_oos(vgpu, gpt);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+/*
+ * mm page table allocation policy for bdw+
+ * - for ggtt, only virtual page table will be allocated.
+ * - for ppgtt, dedicated virtual/shadow page table will be allocated.
+ */
+static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm)
+{
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ const struct intel_gvt_device_info *info = &gvt->device_info;
+ void *mem;
+
+ if (mm->type == INTEL_GVT_MM_PPGTT) {
+ mm->page_table_entry_cnt = 4;
+ mm->page_table_entry_size = mm->page_table_entry_cnt *
+ info->gtt_entry_size;
+ mem = kzalloc(mm->has_shadow_page_table ?
+ mm->page_table_entry_size * 2
+ : mm->page_table_entry_size,
+ GFP_ATOMIC);
+ if (!mem)
+ return -ENOMEM;
+ mm->virtual_page_table = mem;
+ if (!mm->has_shadow_page_table)
+ return 0;
+ mm->shadow_page_table = mem + mm->page_table_entry_size;
+ } else if (mm->type == INTEL_GVT_MM_GGTT) {
+ mm->page_table_entry_cnt =
+ (gvt_ggtt_gm_sz(gvt) >> GTT_PAGE_SHIFT);
+ mm->page_table_entry_size = mm->page_table_entry_cnt *
+ info->gtt_entry_size;
+ mem = vzalloc(mm->page_table_entry_size);
+ if (!mem)
+ return -ENOMEM;
+ mm->virtual_page_table = mem;
+ }
+ return 0;
+}
+
+static void gen8_mm_free_page_table(struct intel_vgpu_mm *mm)
+{
+ if (mm->type == INTEL_GVT_MM_PPGTT) {
+ kfree(mm->virtual_page_table);
+ } else if (mm->type == INTEL_GVT_MM_GGTT) {
+ if (mm->virtual_page_table)
+ vfree(mm->virtual_page_table);
+ }
+ mm->virtual_page_table = mm->shadow_page_table = NULL;
+}
+
+static void invalidate_mm(struct intel_vgpu_mm *mm)
+{
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
+ struct intel_gvt_gtt_entry se;
+ int i;
+
+ if (WARN_ON(!mm->has_shadow_page_table || !mm->shadowed))
+ return;
+
+ for (i = 0; i < mm->page_table_entry_cnt; i++) {
+ ppgtt_get_shadow_root_entry(mm, &se, i);
+ if (!ops->test_present(&se))
+ continue;
+ ppgtt_invalidate_shadow_page_by_shadow_entry(
+ vgpu, &se);
+ se.val64 = 0;
+ ppgtt_set_shadow_root_entry(mm, &se, i);
+
+ trace_gpt_change(vgpu->id, "destroy root pointer",
+ NULL, se.type, se.val64, i);
+ }
+ mm->shadowed = false;
+}
+
+/**
+ * intel_vgpu_destroy_mm - destroy a mm object
+ * @mm: a kref object
+ *
+ * This function is used to destroy a mm object for vGPU
+ *
+ */
+void intel_vgpu_destroy_mm(struct kref *mm_ref)
+{
+ struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref);
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+
+ if (!mm->initialized)
+ goto out;
+
+ list_del(&mm->list);
+ list_del(&mm->lru_list);
+
+ if (mm->has_shadow_page_table)
+ invalidate_mm(mm);
+
+ gtt->mm_free_page_table(mm);
+out:
+ kfree(mm);
+}
+
+static int shadow_mm(struct intel_vgpu_mm *mm)
+{
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
+ struct intel_vgpu_ppgtt_spt *spt;
+ struct intel_gvt_gtt_entry ge, se;
+ int i;
+ int ret;
+
+ if (WARN_ON(!mm->has_shadow_page_table || mm->shadowed))
+ return 0;
+
+ mm->shadowed = true;
+
+ for (i = 0; i < mm->page_table_entry_cnt; i++) {
+ ppgtt_get_guest_root_entry(mm, &ge, i);
+ if (!ops->test_present(&ge))
+ continue;
+
+ trace_gpt_change(vgpu->id, __func__, NULL,
+ ge.type, ge.val64, i);
+
+ spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
+ if (IS_ERR(spt)) {
+ gvt_err("fail to populate guest root pointer\n");
+ ret = PTR_ERR(spt);
+ goto fail;
+ }
+ ppgtt_generate_shadow_entry(&se, spt, &ge);
+ ppgtt_set_shadow_root_entry(mm, &se, i);
+
+ trace_gpt_change(vgpu->id, "populate root pointer",
+ NULL, se.type, se.val64, i);
+ }
+ return 0;
+fail:
+ invalidate_mm(mm);
+ return ret;
+}
+
+/**
+ * intel_vgpu_create_mm - create a mm object for a vGPU
+ * @vgpu: a vGPU
+ * @mm_type: mm object type, should be PPGTT or GGTT
+ * @virtual_page_table: page table root pointers. Could be NULL if user wants
+ * to populate shadow later.
+ * @page_table_level: describe the page table level of the mm object
+ * @pde_base_index: pde root pointer base in GGTT MMIO.
+ *
+ * This function is used to create a mm object for a vGPU.
+ *
+ * Returns:
+ * Zero on success, negative error code in pointer if failed.
+ */
+struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
+ int mm_type, void *virtual_page_table, int page_table_level,
+ u32 pde_base_index)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct intel_vgpu_mm *mm;
+ int ret;
+
+ mm = kzalloc(sizeof(*mm), GFP_ATOMIC);
+ if (!mm) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ mm->type = mm_type;
+
+ if (page_table_level == 1)
+ mm->page_table_entry_type = GTT_TYPE_GGTT_PTE;
+ else if (page_table_level == 3)
+ mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
+ else if (page_table_level == 4)
+ mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
+ else {
+ WARN_ON(1);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ mm->page_table_level = page_table_level;
+ mm->pde_base_index = pde_base_index;
+
+ mm->vgpu = vgpu;
+ mm->has_shadow_page_table = !!(mm_type == INTEL_GVT_MM_PPGTT);
+
+ kref_init(&mm->ref);
+ atomic_set(&mm->pincount, 0);
+ INIT_LIST_HEAD(&mm->list);
+ INIT_LIST_HEAD(&mm->lru_list);
+ list_add_tail(&mm->list, &vgpu->gtt.mm_list_head);
+
+ ret = gtt->mm_alloc_page_table(mm);
+ if (ret) {
+ gvt_err("fail to allocate page table for mm\n");
+ goto fail;
+ }
+
+ mm->initialized = true;
+
+ if (virtual_page_table)
+ memcpy(mm->virtual_page_table, virtual_page_table,
+ mm->page_table_entry_size);
+
+ if (mm->has_shadow_page_table) {
+ ret = shadow_mm(mm);
+ if (ret)
+ goto fail;
+ list_add_tail(&mm->lru_list, &gvt->gtt.mm_lru_list_head);
+ }
+ return mm;
+fail:
+ gvt_err("fail to create mm\n");
+ if (mm)
+ intel_gvt_mm_unreference(mm);
+ return ERR_PTR(ret);
+}
+
+/**
+ * intel_vgpu_unpin_mm - decrease the pin count of a vGPU mm object
+ * @mm: a vGPU mm object
+ *
+ * This function is called when user doesn't want to use a vGPU mm object
+ */
+void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm)
+{
+ if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
+ return;
+
+ atomic_dec(&mm->pincount);
+}
+
+/**
+ * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object
+ * @vgpu: a vGPU
+ *
+ * This function is called when user wants to use a vGPU mm object. If this
+ * mm object hasn't been shadowed yet, the shadow will be populated at this
+ * time.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm)
+{
+ int ret;
+
+ if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
+ return 0;
+
+ atomic_inc(&mm->pincount);
+
+ if (!mm->shadowed) {
+ ret = shadow_mm(mm);
+ if (ret)
+ return ret;
+ }
+
+ list_del_init(&mm->lru_list);
+ list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head);
+ return 0;
+}
+
+static int reclaim_one_mm(struct intel_gvt *gvt)
+{
+ struct intel_vgpu_mm *mm;
+ struct list_head *pos, *n;
+
+ list_for_each_safe(pos, n, &gvt->gtt.mm_lru_list_head) {
+ mm = container_of(pos, struct intel_vgpu_mm, lru_list);
+
+ if (mm->type != INTEL_GVT_MM_PPGTT)
+ continue;
+ if (atomic_read(&mm->pincount))
+ continue;
+
+ list_del_init(&mm->lru_list);
+ invalidate_mm(mm);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * GMA translation APIs.
+ */
+static inline int ppgtt_get_next_level_entry(struct intel_vgpu_mm *mm,
+ struct intel_gvt_gtt_entry *e, unsigned long index, bool guest)
+{
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ struct intel_vgpu_ppgtt_spt *s;
+
+ if (WARN_ON(!mm->has_shadow_page_table))
+ return -EINVAL;
+
+ s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
+ if (!s)
+ return -ENXIO;
+
+ if (!guest)
+ ppgtt_get_shadow_entry(s, e, index);
+ else
+ ppgtt_get_guest_entry(s, e, index);
+ return 0;
+}
+
+/**
+ * intel_vgpu_gma_to_gpa - translate a gma to GPA
+ * @mm: mm object. could be a PPGTT or GGTT mm object
+ * @gma: graphics memory address in this mm object
+ *
+ * This function is used to translate a graphics memory address in specific
+ * graphics memory space to guest physical address.
+ *
+ * Returns:
+ * Guest physical address on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
+{
+ struct intel_vgpu *vgpu = mm->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_gtt_pte_ops *pte_ops = gvt->gtt.pte_ops;
+ struct intel_gvt_gtt_gma_ops *gma_ops = gvt->gtt.gma_ops;
+ unsigned long gpa = INTEL_GVT_INVALID_ADDR;
+ unsigned long gma_index[4];
+ struct intel_gvt_gtt_entry e;
+ int i, index;
+ int ret;
+
+ if (mm->type != INTEL_GVT_MM_GGTT && mm->type != INTEL_GVT_MM_PPGTT)
+ return INTEL_GVT_INVALID_ADDR;
+
+ if (mm->type == INTEL_GVT_MM_GGTT) {
+ if (!vgpu_gmadr_is_valid(vgpu, gma))
+ goto err;
+
+ ggtt_get_guest_entry(mm, &e,
+ gma_ops->gma_to_ggtt_pte_index(gma));
+ gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
+ + (gma & ~GTT_PAGE_MASK);
+
+ trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa);
+ return gpa;
+ }
+
+ switch (mm->page_table_level) {
+ case 4:
+ ppgtt_get_shadow_root_entry(mm, &e, 0);
+ gma_index[0] = gma_ops->gma_to_pml4_index(gma);
+ gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma);
+ gma_index[2] = gma_ops->gma_to_pde_index(gma);
+ gma_index[3] = gma_ops->gma_to_pte_index(gma);
+ index = 4;
+ break;
+ case 3:
+ ppgtt_get_shadow_root_entry(mm, &e,
+ gma_ops->gma_to_l3_pdp_index(gma));
+ gma_index[0] = gma_ops->gma_to_pde_index(gma);
+ gma_index[1] = gma_ops->gma_to_pte_index(gma);
+ index = 2;
+ break;
+ case 2:
+ ppgtt_get_shadow_root_entry(mm, &e,
+ gma_ops->gma_to_pde_index(gma));
+ gma_index[0] = gma_ops->gma_to_pte_index(gma);
+ index = 1;
+ break;
+ default:
+ WARN_ON(1);
+ goto err;
+ }
+
+ /* walk into the shadow page table and get gpa from guest entry */
+ for (i = 0; i < index; i++) {
+ ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i],
+ (i == index - 1));
+ if (ret)
+ goto err;
+ }
+
+ gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
+ + (gma & ~GTT_PAGE_MASK);
+
+ trace_gma_translate(vgpu->id, "ppgtt", 0,
+ mm->page_table_level, gma, gpa);
+ return gpa;
+err:
+ gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma);
+ return INTEL_GVT_INVALID_ADDR;
+}
+
+static int emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
+ unsigned int off, void *p_data, unsigned int bytes)
+{
+ struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ unsigned long index = off >> info->gtt_entry_size_shift;
+ struct intel_gvt_gtt_entry e;
+
+ if (bytes != 4 && bytes != 8)
+ return -EINVAL;
+
+ ggtt_get_guest_entry(ggtt_mm, &e, index);
+ memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)),
+ bytes);
+ return 0;
+}
+
+/**
+ * intel_vgpu_emulate_gtt_mmio_read - emulate GTT MMIO register read
+ * @vgpu: a vGPU
+ * @off: register offset
+ * @p_data: data will be returned to guest
+ * @bytes: data length
+ *
+ * This function is used to emulate the GTT MMIO register read
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
+ void *p_data, unsigned int bytes)
+{
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ int ret;
+
+ if (bytes != 4 && bytes != 8)
+ return -EINVAL;
+
+ off -= info->gtt_start_offset;
+ ret = emulate_gtt_mmio_read(vgpu, off, p_data, bytes);
+ return ret;
+}
+
+static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+ void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ const struct intel_gvt_device_info *info = &gvt->device_info;
+ struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
+ struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+ unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
+ unsigned long gma;
+ struct intel_gvt_gtt_entry e, m;
+ int ret;
+
+ if (bytes != 4 && bytes != 8)
+ return -EINVAL;
+
+ gma = g_gtt_index << GTT_PAGE_SHIFT;
+
+ /* the VM may configure the whole GM space when ballooning is used */
+ if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma),
+ "vgpu%d: found oob ggtt write, offset %x\n",
+ vgpu->id, off)) {
+ return 0;
+ }
+
+ ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index);
+
+ memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
+ bytes);
+
+ if (ops->test_present(&e)) {
+ ret = gtt_entry_p2m(vgpu, &e, &m);
+ if (ret) {
+ gvt_err("vgpu%d: fail to translate guest gtt entry\n",
+ vgpu->id);
+ return ret;
+ }
+ } else {
+ m = e;
+ m.val64 = 0;
+ }
+
+ ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index);
+ ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
+ return 0;
+}
+
+/*
+ * intel_vgpu_emulate_gtt_mmio_write - emulate GTT MMIO register write
+ * @vgpu: a vGPU
+ * @off: register offset
+ * @p_data: data from guest write
+ * @bytes: data length
+ *
+ * This function is used to emulate the GTT MMIO register write
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+ void *p_data, unsigned int bytes)
+{
+ const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+ int ret;
+
+ if (bytes != 4 && bytes != 8)
+ return -EINVAL;
+
+ off -= info->gtt_start_offset;
+ ret = emulate_gtt_mmio_write(vgpu, off, p_data, bytes);
+ return ret;
+}
+
+static int alloc_scratch_pages(struct intel_vgpu *vgpu,
+ intel_gvt_gtt_type_t type)
+{
+ struct intel_vgpu_gtt *gtt = &vgpu->gtt;
+ struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+ int page_entry_num = GTT_PAGE_SIZE >>
+ vgpu->gvt->device_info.gtt_entry_size_shift;
+ struct page *scratch_pt;
+ unsigned long mfn;
+ int i;
+ void *p;
+
+ if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX))
+ return -EINVAL;
+
+ scratch_pt = alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
+ if (!scratch_pt) {
+ gvt_err("fail to allocate scratch page\n");
+ return -ENOMEM;
+ }
+
+ p = kmap_atomic(scratch_pt);
+ mfn = intel_gvt_hypervisor_virt_to_mfn(p);
+ if (mfn == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("fail to translate vaddr:0x%llx\n", (u64)p);
+ kunmap_atomic(p);
+ __free_page(scratch_pt);
+ return -EFAULT;
+ }
+ gtt->scratch_pt[type].page_mfn = mfn;
+ gtt->scratch_pt[type].page = scratch_pt;
+ gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n",
+ vgpu->id, type, mfn);
+
+ /* Build the tree by full filled the scratch pt with the entries which
+ * point to the next level scratch pt or scratch page. The
+ * scratch_pt[type] indicate the scratch pt/scratch page used by the
+ * 'type' pt.
+ * e.g. scratch_pt[GTT_TYPE_PPGTT_PDE_PT] is used by
+ * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scatch_pt it self
+ * is GTT_TYPE_PPGTT_PTE_PT, and full filled by scratch page mfn.
+ */
+ if (type > GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) {
+ struct intel_gvt_gtt_entry se;
+
+ memset(&se, 0, sizeof(struct intel_gvt_gtt_entry));
+ se.type = get_entry_type(type - 1);
+ ops->set_pfn(&se, gtt->scratch_pt[type - 1].page_mfn);
+
+ /* The entry parameters like present/writeable/cache type
+ * set to the same as i915's scratch page tree.
+ */
+ se.val64 |= _PAGE_PRESENT | _PAGE_RW;
+ if (type == GTT_TYPE_PPGTT_PDE_PT)
+ se.val64 |= PPAT_CACHED_INDEX;
+
+ for (i = 0; i < page_entry_num; i++)
+ ops->set_entry(p, &se, i, false, 0, vgpu);
+ }
+
+ kunmap_atomic(p);
+
+ return 0;
+}
+
+static int release_scratch_page_tree(struct intel_vgpu *vgpu)
+{
+ int i;
+
+ for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+ if (vgpu->gtt.scratch_pt[i].page != NULL) {
+ __free_page(vgpu->gtt.scratch_pt[i].page);
+ vgpu->gtt.scratch_pt[i].page = NULL;
+ vgpu->gtt.scratch_pt[i].page_mfn = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int create_scratch_page_tree(struct intel_vgpu *vgpu)
+{
+ int i, ret;
+
+ for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+ ret = alloc_scratch_pages(vgpu, i);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ release_scratch_page_tree(vgpu);
+ return ret;
+}
+
+/**
+ * intel_vgpu_init_gtt - initialize per-vGPU graphics memory virulization
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize per-vGPU graphics memory virtualization
+ * components.
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
+{
+ struct intel_vgpu_gtt *gtt = &vgpu->gtt;
+ struct intel_vgpu_mm *ggtt_mm;
+
+ hash_init(gtt->guest_page_hash_table);
+ hash_init(gtt->shadow_page_hash_table);
+
+ INIT_LIST_HEAD(&gtt->mm_list_head);
+ INIT_LIST_HEAD(&gtt->oos_page_list_head);
+ INIT_LIST_HEAD(&gtt->post_shadow_list_head);
+
+ ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
+ NULL, 1, 0);
+ if (IS_ERR(ggtt_mm)) {
+ gvt_err("fail to create mm for ggtt.\n");
+ return PTR_ERR(ggtt_mm);
+ }
+
+ gtt->ggtt_mm = ggtt_mm;
+
+ return create_scratch_page_tree(vgpu);
+}
+
+/**
+ * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization
+ * @vgpu: a vGPU
+ *
+ * This function is used to clean up per-vGPU graphics memory virtualization
+ * components.
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu)
+{
+ struct list_head *pos, *n;
+ struct intel_vgpu_mm *mm;
+
+ ppgtt_free_all_shadow_page(vgpu);
+ release_scratch_page_tree(vgpu);
+
+ list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) {
+ mm = container_of(pos, struct intel_vgpu_mm, list);
+ vgpu->gvt->gtt.mm_free_page_table(mm);
+ list_del(&mm->list);
+ list_del(&mm->lru_list);
+ kfree(mm);
+ }
+}
+
+static void clean_spt_oos(struct intel_gvt *gvt)
+{
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct list_head *pos, *n;
+ struct intel_vgpu_oos_page *oos_page;
+
+ WARN(!list_empty(&gtt->oos_page_use_list_head),
+ "someone is still using oos page\n");
+
+ list_for_each_safe(pos, n, &gtt->oos_page_free_list_head) {
+ oos_page = container_of(pos, struct intel_vgpu_oos_page, list);
+ list_del(&oos_page->list);
+ kfree(oos_page);
+ }
+}
+
+static int setup_spt_oos(struct intel_gvt *gvt)
+{
+ struct intel_gvt_gtt *gtt = &gvt->gtt;
+ struct intel_vgpu_oos_page *oos_page;
+ int i;
+ int ret;
+
+ INIT_LIST_HEAD(&gtt->oos_page_free_list_head);
+ INIT_LIST_HEAD(&gtt->oos_page_use_list_head);
+
+ for (i = 0; i < preallocated_oos_pages; i++) {
+ oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL);
+ if (!oos_page) {
+ gvt_err("fail to pre-allocate oos page\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ INIT_LIST_HEAD(&oos_page->list);
+ INIT_LIST_HEAD(&oos_page->vm_list);
+ oos_page->id = i;
+ list_add_tail(&oos_page->list, &gtt->oos_page_free_list_head);
+ }
+
+ gvt_dbg_mm("%d oos pages preallocated\n", i);
+
+ return 0;
+fail:
+ clean_spt_oos(gvt);
+ return ret;
+}
+
+/**
+ * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ * @root_entry: PPGTT page table root pointers
+ *
+ * This function is used to find a PPGTT mm object from mm object pool
+ *
+ * Returns:
+ * pointer to mm object on success, NULL if failed.
+ */
+struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level, void *root_entry)
+{
+ struct list_head *pos;
+ struct intel_vgpu_mm *mm;
+ u64 *src, *dst;
+
+ list_for_each(pos, &vgpu->gtt.mm_list_head) {
+ mm = container_of(pos, struct intel_vgpu_mm, list);
+ if (mm->type != INTEL_GVT_MM_PPGTT)
+ continue;
+
+ if (mm->page_table_level != page_table_level)
+ continue;
+
+ src = root_entry;
+ dst = mm->virtual_page_table;
+
+ if (page_table_level == 3) {
+ if (src[0] == dst[0]
+ && src[1] == dst[1]
+ && src[2] == dst[2]
+ && src[3] == dst[3])
+ return mm;
+ } else {
+ if (src[0] == dst[0])
+ return mm;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from
+ * g2v notification
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ *
+ * This function is used to create a PPGTT mm object from a guest to GVT-g
+ * notification.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level)
+{
+ u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0]));
+ struct intel_vgpu_mm *mm;
+
+ if (WARN_ON((page_table_level != 4) && (page_table_level != 3)))
+ return -EINVAL;
+
+ mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
+ if (mm) {
+ intel_gvt_mm_reference(mm);
+ } else {
+ mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT,
+ pdp, page_table_level, 0);
+ if (IS_ERR(mm)) {
+ gvt_err("fail to create mm\n");
+ return PTR_ERR(mm);
+ }
+ }
+ return 0;
+}
+
+/**
+ * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from
+ * g2v notification
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ *
+ * This function is used to create a PPGTT mm object from a guest to GVT-g
+ * notification.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level)
+{
+ u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0]));
+ struct intel_vgpu_mm *mm;
+
+ if (WARN_ON((page_table_level != 4) && (page_table_level != 3)))
+ return -EINVAL;
+
+ mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
+ if (!mm) {
+ gvt_err("fail to find ppgtt instance.\n");
+ return -EINVAL;
+ }
+ intel_gvt_mm_unreference(mm);
+ return 0;
+}
+
+/**
+ * intel_gvt_init_gtt - initialize mm components of a GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the initialization stage, to initialize
+ * the mm components of a GVT device.
+ *
+ * Returns:
+ * zero on success, negative error code if failed.
+ */
+int intel_gvt_init_gtt(struct intel_gvt *gvt)
+{
+ int ret;
+
+ gvt_dbg_core("init gtt\n");
+
+ if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+ gvt->gtt.pte_ops = &gen8_gtt_pte_ops;
+ gvt->gtt.gma_ops = &gen8_gtt_gma_ops;
+ gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table;
+ gvt->gtt.mm_free_page_table = gen8_mm_free_page_table;
+ } else {
+ return -ENODEV;
+ }
+
+ if (enable_out_of_sync) {
+ ret = setup_spt_oos(gvt);
+ if (ret) {
+ gvt_err("fail to initialize SPT oos\n");
+ return ret;
+ }
+ }
+ INIT_LIST_HEAD(&gvt->gtt.mm_lru_list_head);
+ return 0;
+}
+
+/**
+ * intel_gvt_clean_gtt - clean up mm components of a GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the driver unloading stage, to clean up the
+ * the mm components of a GVT device.
+ *
+ */
+void intel_gvt_clean_gtt(struct intel_gvt *gvt)
+{
+ if (enable_out_of_sync)
+ clean_spt_oos(gvt);
+}
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
new file mode 100644
index 000000000000..d250013bc37b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ * Xiao Zheng <xiao.zheng@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#ifndef _GVT_GTT_H_
+#define _GVT_GTT_H_
+
+#define GTT_PAGE_SHIFT 12
+#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT)
+#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1))
+
+struct intel_vgpu_mm;
+
+#define INTEL_GVT_GTT_HASH_BITS 8
+#define INTEL_GVT_INVALID_ADDR (~0UL)
+
+struct intel_gvt_gtt_entry {
+ u64 val64;
+ int type;
+};
+
+struct intel_gvt_gtt_pte_ops {
+ struct intel_gvt_gtt_entry *(*get_entry)(void *pt,
+ struct intel_gvt_gtt_entry *e,
+ unsigned long index, bool hypervisor_access, unsigned long gpa,
+ struct intel_vgpu *vgpu);
+ struct intel_gvt_gtt_entry *(*set_entry)(void *pt,
+ struct intel_gvt_gtt_entry *e,
+ unsigned long index, bool hypervisor_access, unsigned long gpa,
+ struct intel_vgpu *vgpu);
+ bool (*test_present)(struct intel_gvt_gtt_entry *e);
+ void (*clear_present)(struct intel_gvt_gtt_entry *e);
+ bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+ void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
+ unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
+};
+
+struct intel_gvt_gtt_gma_ops {
+ unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma);
+ unsigned long (*gma_to_pte_index)(unsigned long gma);
+ unsigned long (*gma_to_pde_index)(unsigned long gma);
+ unsigned long (*gma_to_l3_pdp_index)(unsigned long gma);
+ unsigned long (*gma_to_l4_pdp_index)(unsigned long gma);
+ unsigned long (*gma_to_pml4_index)(unsigned long gma);
+};
+
+struct intel_gvt_gtt {
+ struct intel_gvt_gtt_pte_ops *pte_ops;
+ struct intel_gvt_gtt_gma_ops *gma_ops;
+ int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm);
+ void (*mm_free_page_table)(struct intel_vgpu_mm *mm);
+ struct list_head oos_page_use_list_head;
+ struct list_head oos_page_free_list_head;
+ struct list_head mm_lru_list_head;
+};
+
+enum {
+ INTEL_GVT_MM_GGTT = 0,
+ INTEL_GVT_MM_PPGTT,
+};
+
+typedef enum {
+ GTT_TYPE_INVALID = -1,
+
+ GTT_TYPE_GGTT_PTE,
+
+ GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+ GTT_TYPE_PPGTT_PTE_2M_ENTRY,
+ GTT_TYPE_PPGTT_PTE_1G_ENTRY,
+
+ GTT_TYPE_PPGTT_PTE_ENTRY,
+
+ GTT_TYPE_PPGTT_PDE_ENTRY,
+ GTT_TYPE_PPGTT_PDP_ENTRY,
+ GTT_TYPE_PPGTT_PML4_ENTRY,
+
+ GTT_TYPE_PPGTT_ROOT_ENTRY,
+
+ GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+ GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+
+ GTT_TYPE_PPGTT_ENTRY,
+
+ GTT_TYPE_PPGTT_PTE_PT,
+ GTT_TYPE_PPGTT_PDE_PT,
+ GTT_TYPE_PPGTT_PDP_PT,
+ GTT_TYPE_PPGTT_PML4_PT,
+
+ GTT_TYPE_MAX,
+} intel_gvt_gtt_type_t;
+
+struct intel_vgpu_mm {
+ int type;
+ bool initialized;
+ bool shadowed;
+
+ int page_table_entry_type;
+ u32 page_table_entry_size;
+ u32 page_table_entry_cnt;
+ void *virtual_page_table;
+ void *shadow_page_table;
+
+ int page_table_level;
+ bool has_shadow_page_table;
+ u32 pde_base_index;
+
+ struct list_head list;
+ struct kref ref;
+ atomic_t pincount;
+ struct list_head lru_list;
+ struct intel_vgpu *vgpu;
+};
+
+extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(
+ struct intel_vgpu_mm *mm,
+ void *page_table, struct intel_gvt_gtt_entry *e,
+ unsigned long index);
+
+extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(
+ struct intel_vgpu_mm *mm,
+ void *page_table, struct intel_gvt_gtt_entry *e,
+ unsigned long index);
+
+#define ggtt_get_guest_entry(mm, e, index) \
+ intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
+
+#define ggtt_set_guest_entry(mm, e, index) \
+ intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
+
+#define ggtt_get_shadow_entry(mm, e, index) \
+ intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
+
+#define ggtt_set_shadow_entry(mm, e, index) \
+ intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
+
+#define ppgtt_get_guest_root_entry(mm, e, index) \
+ intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
+
+#define ppgtt_set_guest_root_entry(mm, e, index) \
+ intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
+
+#define ppgtt_get_shadow_root_entry(mm, e, index) \
+ intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
+
+#define ppgtt_set_shadow_root_entry(mm, e, index) \
+ intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
+
+extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
+ int mm_type, void *virtual_page_table, int page_table_level,
+ u32 pde_base_index);
+extern void intel_vgpu_destroy_mm(struct kref *mm_ref);
+
+struct intel_vgpu_guest_page;
+
+struct intel_vgpu_scratch_pt {
+ struct page *page;
+ unsigned long page_mfn;
+};
+
+
+struct intel_vgpu_gtt {
+ struct intel_vgpu_mm *ggtt_mm;
+ unsigned long active_ppgtt_mm_bitmap;
+ struct list_head mm_list_head;
+ DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
+ DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
+ atomic_t n_write_protected_guest_page;
+ struct list_head oos_page_list_head;
+ struct list_head post_shadow_list_head;
+ struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
+
+};
+
+extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
+extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
+
+extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
+extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
+
+extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level, void *root_entry);
+
+struct intel_vgpu_oos_page;
+
+struct intel_vgpu_shadow_page {
+ void *vaddr;
+ struct page *page;
+ int type;
+ struct hlist_node node;
+ unsigned long mfn;
+};
+
+struct intel_vgpu_guest_page {
+ struct hlist_node node;
+ bool writeprotection;
+ unsigned long gfn;
+ int (*handler)(void *, u64, void *, int);
+ void *data;
+ unsigned long write_cnt;
+ struct intel_vgpu_oos_page *oos_page;
+};
+
+struct intel_vgpu_oos_page {
+ struct intel_vgpu_guest_page *guest_page;
+ struct list_head list;
+ struct list_head vm_list;
+ int id;
+ unsigned char mem[GTT_PAGE_SIZE];
+};
+
+#define GTT_ENTRY_NUM_IN_ONE_PAGE 512
+
+struct intel_vgpu_ppgtt_spt {
+ struct intel_vgpu_shadow_page shadow_page;
+ struct intel_vgpu_guest_page guest_page;
+ int guest_page_type;
+ atomic_t refcount;
+ struct intel_vgpu *vgpu;
+ DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
+ struct list_head post_shadow_list;
+};
+
+int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *guest_page,
+ unsigned long gfn,
+ int (*handler)(void *gp, u64, void *, int),
+ void *data);
+
+void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *guest_page);
+
+int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *guest_page);
+
+void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *guest_page);
+
+struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
+ struct intel_vgpu *vgpu, unsigned long gfn);
+
+int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
+
+int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu);
+
+static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm)
+{
+ kref_get(&mm->ref);
+}
+
+static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm)
+{
+ kref_put(&mm->ref, intel_vgpu_destroy_mm);
+}
+
+int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm);
+
+void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm);
+
+unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
+ unsigned long gma);
+
+struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level, void *root_entry);
+
+int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level);
+
+int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
+ int page_table_level);
+
+int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
+ unsigned int off, void *p_data, unsigned int bytes);
+
+int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int off, void *p_data, unsigned int bytes);
+
+#endif /* _GVT_GTT_H_ */
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 927f4579f5b6..398877c3d2fd 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -19,12 +19,23 @@
* 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Eddie Dong <eddie.dong@intel.com>
+ *
+ * Contributors:
+ * Niu Bing <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
*/
#include <linux/types.h>
#include <xen/xen.h>
+#include <linux/kthread.h>
#include "i915_drv.h"
+#include "gvt.h"
struct intel_gvt_host intel_gvt_host;
@@ -33,6 +44,16 @@ static const char * const supported_hypervisors[] = {
[INTEL_GVT_HYPERVISOR_KVM] = "KVM",
};
+static const struct intel_gvt_ops intel_gvt_ops = {
+ .emulate_cfg_read = intel_vgpu_emulate_cfg_read,
+ .emulate_cfg_write = intel_vgpu_emulate_cfg_write,
+ .emulate_mmio_read = intel_vgpu_emulate_mmio_read,
+ .emulate_mmio_write = intel_vgpu_emulate_mmio_write,
+ .vgpu_create = intel_gvt_create_vgpu,
+ .vgpu_destroy = intel_gvt_destroy_vgpu,
+ .vgpu_reset = intel_gvt_reset_vgpu,
+};
+
/**
* intel_gvt_init_host - Load MPT modules and detect if we're running in host
* @gvt: intel gvt device
@@ -47,6 +68,8 @@ static const char * const supported_hypervisors[] = {
*/
int intel_gvt_init_host(void)
{
+ int ret;
+
if (intel_gvt_host.initialized)
return 0;
@@ -61,10 +84,12 @@ int intel_gvt_init_host(void)
symbol_get(xengt_mpt), "xengt");
intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN;
} else {
+#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
/* not in Xen. Try KVMGT */
intel_gvt_host.mpt = try_then_request_module(
- symbol_get(kvmgt_mpt), "kvm");
+ symbol_get(kvmgt_mpt), "kvmgt");
intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM;
+#endif
}
/* Fail to load MPT modules - bail out */
@@ -72,7 +97,8 @@ int intel_gvt_init_host(void)
return -EINVAL;
/* Try to detect if we're running in host instead of VM. */
- if (!intel_gvt_hypervisor_detect_host())
+ ret = intel_gvt_hypervisor_detect_host();
+ if (ret)
return -ENODEV;
gvt_dbg_core("Running with hypervisor %s in host mode\n",
@@ -84,9 +110,67 @@ int intel_gvt_init_host(void)
static void init_device_info(struct intel_gvt *gvt)
{
- if (IS_BROADWELL(gvt->dev_priv))
- gvt->device_info.max_support_vgpus = 8;
- /* This function will grow large in GVT device model patches. */
+ struct intel_gvt_device_info *info = &gvt->device_info;
+ struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+
+ if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+ info->max_support_vgpus = 8;
+ info->cfg_space_size = 256;
+ info->mmio_size = 2 * 1024 * 1024;
+ info->mmio_bar = 0;
+ info->gtt_start_offset = 8 * 1024 * 1024;
+ info->gtt_entry_size = 8;
+ info->gtt_entry_size_shift = 3;
+ info->gmadr_bytes_in_cmd = 8;
+ info->max_surface_size = 36 * 1024 * 1024;
+ }
+ info->msi_cap_offset = pdev->msi_cap;
+}
+
+static int gvt_service_thread(void *data)
+{
+ struct intel_gvt *gvt = (struct intel_gvt *)data;
+ int ret;
+
+ gvt_dbg_core("service thread start\n");
+
+ while (!kthread_should_stop()) {
+ ret = wait_event_interruptible(gvt->service_thread_wq,
+ kthread_should_stop() || gvt->service_request);
+
+ if (kthread_should_stop())
+ break;
+
+ if (WARN_ONCE(ret, "service thread is waken up by signal.\n"))
+ continue;
+
+ if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK,
+ (void *)&gvt->service_request)) {
+ mutex_lock(&gvt->lock);
+ intel_gvt_emulate_vblank(gvt);
+ mutex_unlock(&gvt->lock);
+ }
+ }
+
+ return 0;
+}
+
+static void clean_service_thread(struct intel_gvt *gvt)
+{
+ kthread_stop(gvt->service_thread);
+}
+
+static int init_service_thread(struct intel_gvt *gvt)
+{
+ init_waitqueue_head(&gvt->service_thread_wq);
+
+ gvt->service_thread = kthread_run(gvt_service_thread,
+ gvt, "gvt_service_thread");
+ if (IS_ERR(gvt->service_thread)) {
+ gvt_err("fail to start service thread.\n");
+ return PTR_ERR(gvt->service_thread);
+ }
+ return 0;
}
/**
@@ -99,14 +183,26 @@ static void init_device_info(struct intel_gvt *gvt)
*/
void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
{
- struct intel_gvt *gvt = &dev_priv->gvt;
+ struct intel_gvt *gvt = to_gvt(dev_priv);
- if (WARN_ON(!gvt->initialized))
+ if (WARN_ON(!gvt))
return;
- /* Other de-initialization of GVT components will be introduced. */
+ clean_service_thread(gvt);
+ intel_gvt_clean_cmd_parser(gvt);
+ intel_gvt_clean_sched_policy(gvt);
+ intel_gvt_clean_workload_scheduler(gvt);
+ intel_gvt_clean_opregion(gvt);
+ intel_gvt_clean_gtt(gvt);
+ intel_gvt_clean_irq(gvt);
+ intel_gvt_clean_mmio_info(gvt);
+ intel_gvt_free_firmware(gvt);
+
+ intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
+ intel_gvt_clean_vgpu_types(gvt);
- gvt->initialized = false;
+ kfree(dev_priv->gvt);
+ dev_priv->gvt = NULL;
}
/**
@@ -122,7 +218,9 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
*/
int intel_gvt_init_device(struct drm_i915_private *dev_priv)
{
- struct intel_gvt *gvt = &dev_priv->gvt;
+ struct intel_gvt *gvt;
+ int ret;
+
/*
* Cannot initialize GVT device without intel_gvt_host gets
* initialized first.
@@ -130,16 +228,91 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
if (WARN_ON(!intel_gvt_host.initialized))
return -EINVAL;
- if (WARN_ON(gvt->initialized))
+ if (WARN_ON(dev_priv->gvt))
return -EEXIST;
+ gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL);
+ if (!gvt)
+ return -ENOMEM;
+
gvt_dbg_core("init gvt device\n");
+ mutex_init(&gvt->lock);
+ gvt->dev_priv = dev_priv;
+
init_device_info(gvt);
- /*
- * Other initialization of GVT components will be introduce here.
- */
- gvt_dbg_core("gvt device creation is done\n");
- gvt->initialized = true;
+
+ ret = intel_gvt_setup_mmio_info(gvt);
+ if (ret)
+ return ret;
+
+ ret = intel_gvt_load_firmware(gvt);
+ if (ret)
+ goto out_clean_mmio_info;
+
+ ret = intel_gvt_init_irq(gvt);
+ if (ret)
+ goto out_free_firmware;
+
+ ret = intel_gvt_init_gtt(gvt);
+ if (ret)
+ goto out_clean_irq;
+
+ ret = intel_gvt_init_opregion(gvt);
+ if (ret)
+ goto out_clean_gtt;
+
+ ret = intel_gvt_init_workload_scheduler(gvt);
+ if (ret)
+ goto out_clean_opregion;
+
+ ret = intel_gvt_init_sched_policy(gvt);
+ if (ret)
+ goto out_clean_workload_scheduler;
+
+ ret = intel_gvt_init_cmd_parser(gvt);
+ if (ret)
+ goto out_clean_sched_policy;
+
+ ret = init_service_thread(gvt);
+ if (ret)
+ goto out_clean_cmd_parser;
+
+ ret = intel_gvt_init_vgpu_types(gvt);
+ if (ret)
+ goto out_clean_thread;
+
+ ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt,
+ &intel_gvt_ops);
+ if (ret) {
+ gvt_err("failed to register gvt-g host device: %d\n", ret);
+ goto out_clean_types;
+ }
+
+ gvt_dbg_core("gvt device initialization is done\n");
+ dev_priv->gvt = gvt;
return 0;
+
+out_clean_types:
+ intel_gvt_clean_vgpu_types(gvt);
+out_clean_thread:
+ clean_service_thread(gvt);
+out_clean_cmd_parser:
+ intel_gvt_clean_cmd_parser(gvt);
+out_clean_sched_policy:
+ intel_gvt_clean_sched_policy(gvt);
+out_clean_workload_scheduler:
+ intel_gvt_clean_workload_scheduler(gvt);
+out_clean_opregion:
+ intel_gvt_clean_opregion(gvt);
+out_clean_gtt:
+ intel_gvt_clean_gtt(gvt);
+out_clean_irq:
+ intel_gvt_clean_irq(gvt);
+out_free_firmware:
+ intel_gvt_free_firmware(gvt);
+out_clean_mmio_info:
+ intel_gvt_clean_mmio_info(gvt);
+ kfree(gvt);
+ return ret;
}
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index fb619a6e519d..b1a7c8dd4b5f 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -19,6 +19,15 @@
* 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Eddie Dong <eddie.dong@intel.com>
+ *
+ * Contributors:
+ * Niu Bing <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
*/
#ifndef _GVT_H_
@@ -26,6 +35,17 @@
#include "debug.h"
#include "hypercall.h"
+#include "mmio.h"
+#include "reg.h"
+#include "interrupt.h"
+#include "gtt.h"
+#include "display.h"
+#include "edid.h"
+#include "execlist.h"
+#include "scheduler.h"
+#include "sched_policy.h"
+#include "render.h"
+#include "cmd_parser.h"
#define GVT_MAX_VGPU 8
@@ -45,25 +65,381 @@ extern struct intel_gvt_host intel_gvt_host;
/* Describe per-platform limitations. */
struct intel_gvt_device_info {
u32 max_support_vgpus;
- /* This data structure will grow bigger in GVT device model patches */
+ u32 cfg_space_size;
+ u32 mmio_size;
+ u32 mmio_bar;
+ unsigned long msi_cap_offset;
+ u32 gtt_start_offset;
+ u32 gtt_entry_size;
+ u32 gtt_entry_size_shift;
+ int gmadr_bytes_in_cmd;
+ u32 max_surface_size;
+};
+
+/* GM resources owned by a vGPU */
+struct intel_vgpu_gm {
+ u64 aperture_sz;
+ u64 hidden_sz;
+ struct drm_mm_node low_gm_node;
+ struct drm_mm_node high_gm_node;
+};
+
+#define INTEL_GVT_MAX_NUM_FENCES 32
+
+/* Fences owned by a vGPU */
+struct intel_vgpu_fence {
+ struct drm_i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES];
+ u32 base;
+ u32 size;
+};
+
+struct intel_vgpu_mmio {
+ void *vreg;
+ void *sreg;
+ bool disable_warn_untrack;
+};
+
+#define INTEL_GVT_MAX_CFG_SPACE_SZ 256
+#define INTEL_GVT_MAX_BAR_NUM 4
+
+struct intel_vgpu_pci_bar {
+ u64 size;
+ bool tracked;
+};
+
+struct intel_vgpu_cfg_space {
+ unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ];
+ struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM];
+};
+
+#define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space)
+
+#define INTEL_GVT_MAX_PIPE 4
+
+struct intel_vgpu_irq {
+ bool irq_warn_once[INTEL_GVT_EVENT_MAX];
+ DECLARE_BITMAP(flip_done_event[INTEL_GVT_MAX_PIPE],
+ INTEL_GVT_EVENT_MAX);
+};
+
+struct intel_vgpu_opregion {
+ void *va;
+ u32 gfn[INTEL_GVT_OPREGION_PAGES];
+ struct page *pages[INTEL_GVT_OPREGION_PAGES];
+};
+
+#define vgpu_opregion(vgpu) (&(vgpu->opregion))
+
+#define INTEL_GVT_MAX_PORT 5
+
+struct intel_vgpu_display {
+ struct intel_vgpu_i2c_edid i2c_edid;
+ struct intel_vgpu_port ports[INTEL_GVT_MAX_PORT];
+ struct intel_vgpu_sbi sbi;
};
struct intel_vgpu {
struct intel_gvt *gvt;
int id;
unsigned long handle; /* vGPU handle used by hypervisor MPT modules */
+ bool active;
+ bool resetting;
+ void *sched_data;
+
+ struct intel_vgpu_fence fence;
+ struct intel_vgpu_gm gm;
+ struct intel_vgpu_cfg_space cfg_space;
+ struct intel_vgpu_mmio mmio;
+ struct intel_vgpu_irq irq;
+ struct intel_vgpu_gtt gtt;
+ struct intel_vgpu_opregion opregion;
+ struct intel_vgpu_display display;
+ struct intel_vgpu_execlist execlist[I915_NUM_ENGINES];
+ struct list_head workload_q_head[I915_NUM_ENGINES];
+ struct kmem_cache *workloads;
+ atomic_t running_workload_num;
+ DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
+ struct i915_gem_context *shadow_ctx;
+ struct notifier_block shadow_ctx_notifier_block;
+
+#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
+ struct {
+ struct device *mdev;
+ struct vfio_region *region;
+ int num_regions;
+ struct eventfd_ctx *intx_trigger;
+ struct eventfd_ctx *msi_trigger;
+ struct rb_root cache;
+ struct mutex cache_lock;
+ void *vfio_group;
+ struct notifier_block iommu_notifier;
+ } vdev;
+#endif
+};
+
+struct intel_gvt_gm {
+ unsigned long vgpu_allocated_low_gm_size;
+ unsigned long vgpu_allocated_high_gm_size;
+};
+
+struct intel_gvt_fence {
+ unsigned long vgpu_allocated_fence_num;
+};
+
+#define INTEL_GVT_MMIO_HASH_BITS 9
+
+struct intel_gvt_mmio {
+ u32 *mmio_attribute;
+ DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS);
+};
+
+struct intel_gvt_firmware {
+ void *cfg_space;
+ void *mmio;
+ bool firmware_loaded;
+};
+
+struct intel_gvt_opregion {
+ void __iomem *opregion_va;
+ u32 opregion_pa;
+};
+
+#define NR_MAX_INTEL_VGPU_TYPES 20
+struct intel_vgpu_type {
+ char name[16];
+ unsigned int max_instance;
+ unsigned int avail_instance;
+ unsigned int low_gm_size;
+ unsigned int high_gm_size;
+ unsigned int fence;
};
struct intel_gvt {
struct mutex lock;
- bool initialized;
-
struct drm_i915_private *dev_priv;
struct idr vgpu_idr; /* vGPU IDR pool */
struct intel_gvt_device_info device_info;
+ struct intel_gvt_gm gm;
+ struct intel_gvt_fence fence;
+ struct intel_gvt_mmio mmio;
+ struct intel_gvt_firmware firmware;
+ struct intel_gvt_irq irq;
+ struct intel_gvt_gtt gtt;
+ struct intel_gvt_opregion opregion;
+ struct intel_gvt_workload_scheduler scheduler;
+ DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
+ struct intel_vgpu_type *types;
+ unsigned int num_types;
+
+ struct task_struct *service_thread;
+ wait_queue_head_t service_thread_wq;
+ unsigned long service_request;
+};
+
+static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
+{
+ return i915->gvt;
+}
+
+enum {
+ INTEL_GVT_REQUEST_EMULATE_VBLANK = 0,
};
+static inline void intel_gvt_request_service(struct intel_gvt *gvt,
+ int service)
+{
+ set_bit(service, (void *)&gvt->service_request);
+ wake_up(&gvt->service_thread_wq);
+}
+
+void intel_gvt_free_firmware(struct intel_gvt *gvt);
+int intel_gvt_load_firmware(struct intel_gvt *gvt);
+
+/* Aperture/GM space definitions for GVT device */
+#define MB_TO_BYTES(mb) ((mb) << 20ULL)
+#define BYTES_TO_MB(b) ((b) >> 20ULL)
+
+#define HOST_LOW_GM_SIZE MB_TO_BYTES(128)
+#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384)
+#define HOST_FENCE 4
+
+/* Aperture/GM space definitions for GVT device */
+#define gvt_aperture_sz(gvt) (gvt->dev_priv->ggtt.mappable_end)
+#define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base)
+
+#define gvt_ggtt_gm_sz(gvt) (gvt->dev_priv->ggtt.base.total)
+#define gvt_ggtt_sz(gvt) \
+ ((gvt->dev_priv->ggtt.base.total >> PAGE_SHIFT) << 3)
+#define gvt_hidden_sz(gvt) (gvt_ggtt_gm_sz(gvt) - gvt_aperture_sz(gvt))
+
+#define gvt_aperture_gmadr_base(gvt) (0)
+#define gvt_aperture_gmadr_end(gvt) (gvt_aperture_gmadr_base(gvt) \
+ + gvt_aperture_sz(gvt) - 1)
+
+#define gvt_hidden_gmadr_base(gvt) (gvt_aperture_gmadr_base(gvt) \
+ + gvt_aperture_sz(gvt))
+#define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \
+ + gvt_hidden_sz(gvt) - 1)
+
+#define gvt_fence_sz(gvt) (gvt->dev_priv->num_fence_regs)
+
+/* Aperture/GM space definitions for vGPU */
+#define vgpu_aperture_offset(vgpu) ((vgpu)->gm.low_gm_node.start)
+#define vgpu_hidden_offset(vgpu) ((vgpu)->gm.high_gm_node.start)
+#define vgpu_aperture_sz(vgpu) ((vgpu)->gm.aperture_sz)
+#define vgpu_hidden_sz(vgpu) ((vgpu)->gm.hidden_sz)
+
+#define vgpu_aperture_pa_base(vgpu) \
+ (gvt_aperture_pa_base(vgpu->gvt) + vgpu_aperture_offset(vgpu))
+
+#define vgpu_ggtt_gm_sz(vgpu) ((vgpu)->gm.aperture_sz + (vgpu)->gm.hidden_sz)
+
+#define vgpu_aperture_pa_end(vgpu) \
+ (vgpu_aperture_pa_base(vgpu) + vgpu_aperture_sz(vgpu) - 1)
+
+#define vgpu_aperture_gmadr_base(vgpu) (vgpu_aperture_offset(vgpu))
+#define vgpu_aperture_gmadr_end(vgpu) \
+ (vgpu_aperture_gmadr_base(vgpu) + vgpu_aperture_sz(vgpu) - 1)
+
+#define vgpu_hidden_gmadr_base(vgpu) (vgpu_hidden_offset(vgpu))
+#define vgpu_hidden_gmadr_end(vgpu) \
+ (vgpu_hidden_gmadr_base(vgpu) + vgpu_hidden_sz(vgpu) - 1)
+
+#define vgpu_fence_base(vgpu) (vgpu->fence.base)
+#define vgpu_fence_sz(vgpu) (vgpu->fence.size)
+
+struct intel_vgpu_creation_params {
+ __u64 handle;
+ __u64 low_gm_sz; /* in MB */
+ __u64 high_gm_sz; /* in MB */
+ __u64 fence_sz;
+ __s32 primary;
+ __u64 vgpu_id;
+};
+
+int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
+ struct intel_vgpu_creation_params *param);
+void intel_vgpu_free_resource(struct intel_vgpu *vgpu);
+void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
+ u32 fence, u64 value);
+
+/* Macros for easily accessing vGPU virtual/shadow register */
+#define vgpu_vreg(vgpu, reg) \
+ (*(u32 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg8(vgpu, reg) \
+ (*(u8 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg16(vgpu, reg) \
+ (*(u16 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg64(vgpu, reg) \
+ (*(u64 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg(vgpu, reg) \
+ (*(u32 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg8(vgpu, reg) \
+ (*(u8 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg16(vgpu, reg) \
+ (*(u16 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg64(vgpu, reg) \
+ (*(u64 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+
+#define for_each_active_vgpu(gvt, vgpu, id) \
+ idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) \
+ for_each_if(vgpu->active)
+
+static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu,
+ u32 offset, u32 val, bool low)
+{
+ u32 *pval;
+
+ /* BAR offset should be 32 bits algiend */
+ offset = rounddown(offset, 4);
+ pval = (u32 *)(vgpu_cfg_space(vgpu) + offset);
+
+ if (low) {
+ /*
+ * only update bit 31 - bit 4,
+ * leave the bit 3 - bit 0 unchanged.
+ */
+ *pval = (val & GENMASK(31, 4)) | (*pval & GENMASK(3, 0));
+ } else {
+ *pval = val;
+ }
+}
+
+int intel_gvt_init_vgpu_types(struct intel_gvt *gvt);
+void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt);
+
+struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
+ struct intel_vgpu_type *type);
+void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
+void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu);
+
+
+/* validating GM functions */
+#define vgpu_gmadr_is_aperture(vgpu, gmadr) \
+ ((gmadr >= vgpu_aperture_gmadr_base(vgpu)) && \
+ (gmadr <= vgpu_aperture_gmadr_end(vgpu)))
+
+#define vgpu_gmadr_is_hidden(vgpu, gmadr) \
+ ((gmadr >= vgpu_hidden_gmadr_base(vgpu)) && \
+ (gmadr <= vgpu_hidden_gmadr_end(vgpu)))
+
+#define vgpu_gmadr_is_valid(vgpu, gmadr) \
+ ((vgpu_gmadr_is_aperture(vgpu, gmadr) || \
+ (vgpu_gmadr_is_hidden(vgpu, gmadr))))
+
+#define gvt_gmadr_is_aperture(gvt, gmadr) \
+ ((gmadr >= gvt_aperture_gmadr_base(gvt)) && \
+ (gmadr <= gvt_aperture_gmadr_end(gvt)))
+
+#define gvt_gmadr_is_hidden(gvt, gmadr) \
+ ((gmadr >= gvt_hidden_gmadr_base(gvt)) && \
+ (gmadr <= gvt_hidden_gmadr_end(gvt)))
+
+#define gvt_gmadr_is_valid(gvt, gmadr) \
+ (gvt_gmadr_is_aperture(gvt, gmadr) || \
+ gvt_gmadr_is_hidden(gvt, gmadr))
+
+bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size);
+int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr);
+int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr);
+int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
+ unsigned long *h_index);
+int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
+ unsigned long *g_index);
+
+int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes);
+
+int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes);
+
+void intel_gvt_clean_opregion(struct intel_gvt *gvt);
+int intel_gvt_init_opregion(struct intel_gvt *gvt);
+
+void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
+
+int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
+int setup_vgpu_mmio(struct intel_vgpu *vgpu);
+void populate_pvinfo_page(struct intel_vgpu *vgpu);
+
+struct intel_gvt_ops {
+ int (*emulate_cfg_read)(struct intel_vgpu *, unsigned int, void *,
+ unsigned int);
+ int (*emulate_cfg_write)(struct intel_vgpu *, unsigned int, void *,
+ unsigned int);
+ int (*emulate_mmio_read)(struct intel_vgpu *, u64, void *,
+ unsigned int);
+ int (*emulate_mmio_write)(struct intel_vgpu *, u64, void *,
+ unsigned int);
+ struct intel_vgpu *(*vgpu_create)(struct intel_gvt *,
+ struct intel_vgpu_type *);
+ void (*vgpu_destroy)(struct intel_vgpu *);
+ void (*vgpu_reset)(struct intel_vgpu *);
+};
+
+
#include "mpt.h"
#endif
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
new file mode 100644
index 000000000000..522809710312
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -0,0 +1,2848 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Eddie Dong <eddie.dong@intel.com>
+ * Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Pei Zhang <pei.zhang@intel.com>
+ * Niu Bing <bing.niu@intel.com>
+ * Ping Gao <ping.a.gao@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+/* XXX FIXME i915 has changed PP_XXX definition */
+#define PCH_PP_STATUS _MMIO(0xc7200)
+#define PCH_PP_CONTROL _MMIO(0xc7204)
+#define PCH_PP_ON_DELAYS _MMIO(0xc7208)
+#define PCH_PP_OFF_DELAYS _MMIO(0xc720c)
+#define PCH_PP_DIVISOR _MMIO(0xc7210)
+
+/* Register contains RO bits */
+#define F_RO (1 << 0)
+/* Register contains graphics address */
+#define F_GMADR (1 << 1)
+/* Mode mask registers with high 16 bits as the mask bits */
+#define F_MODE_MASK (1 << 2)
+/* This reg can be accessed by GPU commands */
+#define F_CMD_ACCESS (1 << 3)
+/* This reg has been accessed by a VM */
+#define F_ACCESSED (1 << 4)
+/* This reg has been accessed through GPU commands */
+#define F_CMD_ACCESSED (1 << 5)
+/* This reg could be accessed by unaligned address */
+#define F_UNALIGN (1 << 6)
+
+unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt)
+{
+ if (IS_BROADWELL(gvt->dev_priv))
+ return D_BDW;
+ else if (IS_SKYLAKE(gvt->dev_priv))
+ return D_SKL;
+
+ return 0;
+}
+
+bool intel_gvt_match_device(struct intel_gvt *gvt,
+ unsigned long device)
+{
+ return intel_gvt_get_device_type(gvt) & device;
+}
+
+static void read_vreg(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+}
+
+static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+}
+
+static int new_mmio_info(struct intel_gvt *gvt,
+ u32 offset, u32 flags, u32 size,
+ u32 addr_mask, u32 ro_mask, u32 device,
+ void *read, void *write)
+{
+ struct intel_gvt_mmio_info *info, *p;
+ u32 start, end, i;
+
+ if (!intel_gvt_match_device(gvt, device))
+ return 0;
+
+ if (WARN_ON(!IS_ALIGNED(offset, 4)))
+ return -EINVAL;
+
+ start = offset;
+ end = offset + size;
+
+ for (i = start; i < end; i += 4) {
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->offset = i;
+ p = intel_gvt_find_mmio_info(gvt, info->offset);
+ if (p)
+ gvt_err("dup mmio definition offset %x\n",
+ info->offset);
+ info->size = size;
+ info->length = (i + 4) < end ? 4 : (end - i);
+ info->addr_mask = addr_mask;
+ info->device = device;
+ info->read = read ? read : intel_vgpu_default_mmio_read;
+ info->write = write ? write : intel_vgpu_default_mmio_write;
+ gvt->mmio.mmio_attribute[info->offset / 4] = flags;
+ INIT_HLIST_NODE(&info->node);
+ hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset);
+ }
+ return 0;
+}
+
+static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)
+{
+ enum intel_engine_id id;
+ struct intel_engine_cs *engine;
+
+ reg &= ~GENMASK(11, 0);
+ for_each_engine(engine, gvt->dev_priv, id) {
+ if (engine->mmio_base == reg)
+ return id;
+ }
+ return -1;
+}
+
+#define offset_to_fence_num(offset) \
+ ((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3)
+
+#define fence_num_to_offset(num) \
+ (num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0)))
+
+static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,
+ unsigned int fence_num, void *p_data, unsigned int bytes)
+{
+ if (fence_num >= vgpu_fence_sz(vgpu)) {
+ gvt_err("vgpu%d: found oob fence register access\n",
+ vgpu->id);
+ gvt_err("vgpu%d: total fence num %d access fence num %d\n",
+ vgpu->id, vgpu_fence_sz(vgpu), fence_num);
+ memset(p_data, 0, bytes);
+ }
+ return 0;
+}
+
+static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
+ void *p_data, unsigned int bytes)
+{
+ int ret;
+
+ ret = sanitize_fence_mmio_access(vgpu, offset_to_fence_num(off),
+ p_data, bytes);
+ if (ret)
+ return ret;
+ read_vreg(vgpu, off, p_data, bytes);
+ return 0;
+}
+
+static int fence_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+ void *p_data, unsigned int bytes)
+{
+ unsigned int fence_num = offset_to_fence_num(off);
+ int ret;
+
+ ret = sanitize_fence_mmio_access(vgpu, fence_num, p_data, bytes);
+ if (ret)
+ return ret;
+ write_vreg(vgpu, off, p_data, bytes);
+
+ intel_vgpu_write_fence(vgpu, fence_num,
+ vgpu_vreg64(vgpu, fence_num_to_offset(fence_num)));
+ return 0;
+}
+
+#define CALC_MODE_MASK_REG(old, new) \
+ (((new) & GENMASK(31, 16)) \
+ | ((((old) & GENMASK(15, 0)) & ~((new) >> 16)) \
+ | ((new) & ((new) >> 16))))
+
+static int mul_force_wake_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 old, new;
+ uint32_t ack_reg_offset;
+
+ old = vgpu_vreg(vgpu, offset);
+ new = CALC_MODE_MASK_REG(old, *(u32 *)p_data);
+
+ if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
+ switch (offset) {
+ case FORCEWAKE_RENDER_GEN9_REG:
+ ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG;
+ break;
+ case FORCEWAKE_BLITTER_GEN9_REG:
+ ack_reg_offset = FORCEWAKE_ACK_BLITTER_GEN9_REG;
+ break;
+ case FORCEWAKE_MEDIA_GEN9_REG:
+ ack_reg_offset = FORCEWAKE_ACK_MEDIA_GEN9_REG;
+ break;
+ default:
+ /*should not hit here*/
+ gvt_err("invalid forcewake offset 0x%x\n", offset);
+ return 1;
+ }
+ } else {
+ ack_reg_offset = FORCEWAKE_ACK_HSW_REG;
+ }
+
+ vgpu_vreg(vgpu, offset) = new;
+ vgpu_vreg(vgpu, ack_reg_offset) = (new & GENMASK(15, 0));
+ return 0;
+}
+
+static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes, unsigned long bitmap)
+{
+ struct intel_gvt_workload_scheduler *scheduler =
+ &vgpu->gvt->scheduler;
+
+ vgpu->resetting = true;
+
+ intel_vgpu_stop_schedule(vgpu);
+ /*
+ * The current_vgpu will set to NULL after stopping the
+ * scheduler when the reset is triggered by current vgpu.
+ */
+ if (scheduler->current_vgpu == NULL) {
+ mutex_unlock(&vgpu->gvt->lock);
+ intel_gvt_wait_vgpu_idle(vgpu);
+ mutex_lock(&vgpu->gvt->lock);
+ }
+
+ intel_vgpu_reset_execlist(vgpu, bitmap);
+
+ /* full GPU reset */
+ if (bitmap == 0xff) {
+ mutex_unlock(&vgpu->gvt->lock);
+ intel_vgpu_clean_gtt(vgpu);
+ mutex_lock(&vgpu->gvt->lock);
+ setup_vgpu_mmio(vgpu);
+ populate_pvinfo_page(vgpu);
+ intel_vgpu_init_gtt(vgpu);
+ }
+
+ vgpu->resetting = false;
+
+ return 0;
+}
+
+static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 data;
+ u64 bitmap = 0;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (data & GEN6_GRDOM_FULL) {
+ gvt_dbg_mmio("vgpu%d: request full GPU reset\n", vgpu->id);
+ bitmap = 0xff;
+ }
+ if (data & GEN6_GRDOM_RENDER) {
+ gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id);
+ bitmap |= (1 << RCS);
+ }
+ if (data & GEN6_GRDOM_MEDIA) {
+ gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id);
+ bitmap |= (1 << VCS);
+ }
+ if (data & GEN6_GRDOM_BLT) {
+ gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id);
+ bitmap |= (1 << BCS);
+ }
+ if (data & GEN6_GRDOM_VECS) {
+ gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id);
+ bitmap |= (1 << VECS);
+ }
+ if (data & GEN8_GRDOM_MEDIA2) {
+ gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
+ if (HAS_BSD2(vgpu->gvt->dev_priv))
+ bitmap |= (1 << VCS2);
+ }
+ return handle_device_reset(vgpu, offset, p_data, bytes, bitmap);
+}
+
+static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ return intel_gvt_i2c_handle_gmbus_read(vgpu, offset, p_data, bytes);
+}
+
+static int gmbus_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ return intel_gvt_i2c_handle_gmbus_write(vgpu, offset, p_data, bytes);
+}
+
+static int pch_pp_control_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & PANEL_POWER_ON) {
+ vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_ON;
+ vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_SEQUENCE_STATE_ON_IDLE;
+ vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_SEQUENCE_POWER_DOWN;
+ vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_CYCLE_DELAY_ACTIVE;
+
+ } else
+ vgpu_vreg(vgpu, PCH_PP_STATUS) &=
+ ~(PP_ON | PP_SEQUENCE_POWER_DOWN
+ | PP_CYCLE_DELAY_ACTIVE);
+ return 0;
+}
+
+static int transconf_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & TRANS_ENABLE)
+ vgpu_vreg(vgpu, offset) |= TRANS_STATE_ENABLE;
+ else
+ vgpu_vreg(vgpu, offset) &= ~TRANS_STATE_ENABLE;
+ return 0;
+}
+
+static int lcpll_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & LCPLL_PLL_DISABLE)
+ vgpu_vreg(vgpu, offset) &= ~LCPLL_PLL_LOCK;
+ else
+ vgpu_vreg(vgpu, offset) |= LCPLL_PLL_LOCK;
+
+ if (vgpu_vreg(vgpu, offset) & LCPLL_CD_SOURCE_FCLK)
+ vgpu_vreg(vgpu, offset) |= LCPLL_CD_SOURCE_FCLK_DONE;
+ else
+ vgpu_vreg(vgpu, offset) &= ~LCPLL_CD_SOURCE_FCLK_DONE;
+
+ return 0;
+}
+
+static int dpy_reg_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ *(u32 *)p_data = (1 << 17);
+ return 0;
+}
+
+static int dpy_reg_mmio_read_2(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ *(u32 *)p_data = 3;
+ return 0;
+}
+
+static int dpy_reg_mmio_read_3(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ *(u32 *)p_data = (0x2f << 16);
+ return 0;
+}
+
+static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (data & PIPECONF_ENABLE)
+ vgpu_vreg(vgpu, offset) |= I965_PIPECONF_ACTIVE;
+ else
+ vgpu_vreg(vgpu, offset) &= ~I965_PIPECONF_ACTIVE;
+ intel_gvt_check_vblank_emulation(vgpu->gvt);
+ return 0;
+}
+
+static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & DDI_BUF_CTL_ENABLE) {
+ vgpu_vreg(vgpu, offset) &= ~DDI_BUF_IS_IDLE;
+ } else {
+ vgpu_vreg(vgpu, offset) |= DDI_BUF_IS_IDLE;
+ if (offset == i915_mmio_reg_offset(DDI_BUF_CTL(PORT_E)))
+ vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E))
+ &= ~DP_TP_STATUS_AUTOTRAIN_DONE;
+ }
+ return 0;
+}
+
+static int fdi_rx_iir_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ vgpu_vreg(vgpu, offset) &= ~*(u32 *)p_data;
+ return 0;
+}
+
+#define FDI_LINK_TRAIN_PATTERN1 0
+#define FDI_LINK_TRAIN_PATTERN2 1
+
+static int fdi_auto_training_started(struct intel_vgpu *vgpu)
+{
+ u32 ddi_buf_ctl = vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_E));
+ u32 rx_ctl = vgpu_vreg(vgpu, _FDI_RXA_CTL);
+ u32 tx_ctl = vgpu_vreg(vgpu, DP_TP_CTL(PORT_E));
+
+ if ((ddi_buf_ctl & DDI_BUF_CTL_ENABLE) &&
+ (rx_ctl & FDI_RX_ENABLE) &&
+ (rx_ctl & FDI_AUTO_TRAINING) &&
+ (tx_ctl & DP_TP_CTL_ENABLE) &&
+ (tx_ctl & DP_TP_CTL_FDI_AUTOTRAIN))
+ return 1;
+ else
+ return 0;
+}
+
+static int check_fdi_rx_train_status(struct intel_vgpu *vgpu,
+ enum pipe pipe, unsigned int train_pattern)
+{
+ i915_reg_t fdi_rx_imr, fdi_tx_ctl, fdi_rx_ctl;
+ unsigned int fdi_rx_check_bits, fdi_tx_check_bits;
+ unsigned int fdi_rx_train_bits, fdi_tx_train_bits;
+ unsigned int fdi_iir_check_bits;
+
+ fdi_rx_imr = FDI_RX_IMR(pipe);
+ fdi_tx_ctl = FDI_TX_CTL(pipe);
+ fdi_rx_ctl = FDI_RX_CTL(pipe);
+
+ if (train_pattern == FDI_LINK_TRAIN_PATTERN1) {
+ fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_1_CPT;
+ fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_1;
+ fdi_iir_check_bits = FDI_RX_BIT_LOCK;
+ } else if (train_pattern == FDI_LINK_TRAIN_PATTERN2) {
+ fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_2_CPT;
+ fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2;
+ fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK;
+ } else {
+ gvt_err("Invalid train pattern %d\n", train_pattern);
+ return -EINVAL;
+ }
+
+ fdi_rx_check_bits = FDI_RX_ENABLE | fdi_rx_train_bits;
+ fdi_tx_check_bits = FDI_TX_ENABLE | fdi_tx_train_bits;
+
+ /* If imr bit has been masked */
+ if (vgpu_vreg(vgpu, fdi_rx_imr) & fdi_iir_check_bits)
+ return 0;
+
+ if (((vgpu_vreg(vgpu, fdi_tx_ctl) & fdi_tx_check_bits)
+ == fdi_tx_check_bits)
+ && ((vgpu_vreg(vgpu, fdi_rx_ctl) & fdi_rx_check_bits)
+ == fdi_rx_check_bits))
+ return 1;
+ else
+ return 0;
+}
+
+#define INVALID_INDEX (~0U)
+
+static unsigned int calc_index(unsigned int offset, unsigned int start,
+ unsigned int next, unsigned int end, i915_reg_t i915_end)
+{
+ unsigned int range = next - start;
+
+ if (!end)
+ end = i915_mmio_reg_offset(i915_end);
+ if (offset < start || offset > end)
+ return INVALID_INDEX;
+ offset -= start;
+ return offset / range;
+}
+
+#define FDI_RX_CTL_TO_PIPE(offset) \
+ calc_index(offset, _FDI_RXA_CTL, _FDI_RXB_CTL, 0, FDI_RX_CTL(PIPE_C))
+
+#define FDI_TX_CTL_TO_PIPE(offset) \
+ calc_index(offset, _FDI_TXA_CTL, _FDI_TXB_CTL, 0, FDI_TX_CTL(PIPE_C))
+
+#define FDI_RX_IMR_TO_PIPE(offset) \
+ calc_index(offset, _FDI_RXA_IMR, _FDI_RXB_IMR, 0, FDI_RX_IMR(PIPE_C))
+
+static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ i915_reg_t fdi_rx_iir;
+ unsigned int index;
+ int ret;
+
+ if (FDI_RX_CTL_TO_PIPE(offset) != INVALID_INDEX)
+ index = FDI_RX_CTL_TO_PIPE(offset);
+ else if (FDI_TX_CTL_TO_PIPE(offset) != INVALID_INDEX)
+ index = FDI_TX_CTL_TO_PIPE(offset);
+ else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)
+ index = FDI_RX_IMR_TO_PIPE(offset);
+ else {
+ gvt_err("Unsupport registers %x\n", offset);
+ return -EINVAL;
+ }
+
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ fdi_rx_iir = FDI_RX_IIR(index);
+
+ ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN1);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_BIT_LOCK;
+
+ ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN2);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_SYMBOL_LOCK;
+
+ if (offset == _FDI_RXA_CTL)
+ if (fdi_auto_training_started(vgpu))
+ vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) |=
+ DP_TP_STATUS_AUTOTRAIN_DONE;
+ return 0;
+}
+
+#define DP_TP_CTL_TO_PORT(offset) \
+ calc_index(offset, _DP_TP_CTL_A, _DP_TP_CTL_B, 0, DP_TP_CTL(PORT_E))
+
+static int dp_tp_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ i915_reg_t status_reg;
+ unsigned int index;
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ index = DP_TP_CTL_TO_PORT(offset);
+ data = (vgpu_vreg(vgpu, offset) & GENMASK(10, 8)) >> 8;
+ if (data == 0x2) {
+ status_reg = DP_TP_STATUS(index);
+ vgpu_vreg(vgpu, status_reg) |= (1 << 25);
+ }
+ return 0;
+}
+
+static int dp_tp_status_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 reg_val;
+ u32 sticky_mask;
+
+ reg_val = *((u32 *)p_data);
+ sticky_mask = GENMASK(27, 26) | (1 << 24);
+
+ vgpu_vreg(vgpu, offset) = (reg_val & ~sticky_mask) |
+ (vgpu_vreg(vgpu, offset) & sticky_mask);
+ vgpu_vreg(vgpu, offset) &= ~(reg_val & sticky_mask);
+ return 0;
+}
+
+static int pch_adpa_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (data & ADPA_CRT_HOTPLUG_FORCE_TRIGGER)
+ vgpu_vreg(vgpu, offset) &= ~ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+ return 0;
+}
+
+static int south_chicken2_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (data & FDI_MPHY_IOSFSB_RESET_CTL)
+ vgpu_vreg(vgpu, offset) |= FDI_MPHY_IOSFSB_RESET_STATUS;
+ else
+ vgpu_vreg(vgpu, offset) &= ~FDI_MPHY_IOSFSB_RESET_STATUS;
+ return 0;
+}
+
+#define DSPSURF_TO_PIPE(offset) \
+ calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C))
+
+static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ unsigned int index = DSPSURF_TO_PIPE(offset);
+ i915_reg_t surflive_reg = DSPSURFLIVE(index);
+ int flip_event[] = {
+ [PIPE_A] = PRIMARY_A_FLIP_DONE,
+ [PIPE_B] = PRIMARY_B_FLIP_DONE,
+ [PIPE_C] = PRIMARY_C_FLIP_DONE,
+ };
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+
+ set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
+ return 0;
+}
+
+#define SPRSURF_TO_PIPE(offset) \
+ calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C))
+
+static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ unsigned int index = SPRSURF_TO_PIPE(offset);
+ i915_reg_t surflive_reg = SPRSURFLIVE(index);
+ int flip_event[] = {
+ [PIPE_A] = SPRITE_A_FLIP_DONE,
+ [PIPE_B] = SPRITE_B_FLIP_DONE,
+ [PIPE_C] = SPRITE_C_FLIP_DONE,
+ };
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+
+ set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
+ return 0;
+}
+
+static int trigger_aux_channel_interrupt(struct intel_vgpu *vgpu,
+ unsigned int reg)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ enum intel_gvt_event_type event;
+
+ if (reg == _DPA_AUX_CH_CTL)
+ event = AUX_CHANNEL_A;
+ else if (reg == _PCH_DPB_AUX_CH_CTL || reg == _DPB_AUX_CH_CTL)
+ event = AUX_CHANNEL_B;
+ else if (reg == _PCH_DPC_AUX_CH_CTL || reg == _DPC_AUX_CH_CTL)
+ event = AUX_CHANNEL_C;
+ else if (reg == _PCH_DPD_AUX_CH_CTL || reg == _DPD_AUX_CH_CTL)
+ event = AUX_CHANNEL_D;
+ else {
+ WARN_ON(true);
+ return -EINVAL;
+ }
+
+ intel_vgpu_trigger_virtual_event(vgpu, event);
+ return 0;
+}
+
+static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value,
+ unsigned int reg, int len, bool data_valid)
+{
+ /* mark transaction done */
+ value |= DP_AUX_CH_CTL_DONE;
+ value &= ~DP_AUX_CH_CTL_SEND_BUSY;
+ value &= ~DP_AUX_CH_CTL_RECEIVE_ERROR;
+
+ if (data_valid)
+ value &= ~DP_AUX_CH_CTL_TIME_OUT_ERROR;
+ else
+ value |= DP_AUX_CH_CTL_TIME_OUT_ERROR;
+
+ /* message size */
+ value &= ~(0xf << 20);
+ value |= (len << 20);
+ vgpu_vreg(vgpu, reg) = value;
+
+ if (value & DP_AUX_CH_CTL_INTERRUPT)
+ return trigger_aux_channel_interrupt(vgpu, reg);
+ return 0;
+}
+
+static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd,
+ uint8_t t)
+{
+ if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) {
+ /* training pattern 1 for CR */
+ /* set LANE0_CR_DONE, LANE1_CR_DONE */
+ dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_CR_DONE;
+ /* set LANE2_CR_DONE, LANE3_CR_DONE */
+ dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_CR_DONE;
+ } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
+ DPCD_TRAINING_PATTERN_2) {
+ /* training pattern 2 for EQ */
+ /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane0_1 */
+ dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_EQ_DONE;
+ dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_SYMBOL_LOCKED;
+ /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane2_3 */
+ dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_EQ_DONE;
+ dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_SYMBOL_LOCKED;
+ /* set INTERLANE_ALIGN_DONE */
+ dpcd->data[DPCD_LANE_ALIGN_STATUS_UPDATED] |=
+ DPCD_INTERLANE_ALIGN_DONE;
+ } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
+ DPCD_LINK_TRAINING_DISABLED) {
+ /* finish link training */
+ /* set sink status as synchronized */
+ dpcd->data[DPCD_SINK_STATUS] = DPCD_SINK_IN_SYNC;
+ }
+}
+
+#define _REG_HSW_DP_AUX_CH_CTL(dp) \
+ ((dp) ? (_PCH_DPB_AUX_CH_CTL + ((dp)-1)*0x100) : 0x64010)
+
+#define _REG_SKL_DP_AUX_CH_CTL(dp) (0x64010 + (dp) * 0x100)
+
+#define OFFSET_TO_DP_AUX_PORT(offset) (((offset) & 0xF00) >> 8)
+
+#define dpy_is_valid_port(port) \
+ (((port) >= PORT_A) && ((port) < I915_MAX_PORTS))
+
+static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ struct intel_vgpu_display *display = &vgpu->display;
+ int msg, addr, ctrl, op, len;
+ int port_index = OFFSET_TO_DP_AUX_PORT(offset);
+ struct intel_vgpu_dpcd_data *dpcd = NULL;
+ struct intel_vgpu_port *port = NULL;
+ u32 data;
+
+ if (!dpy_is_valid_port(port_index)) {
+ gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id);
+ return 0;
+ }
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (IS_SKYLAKE(vgpu->gvt->dev_priv) &&
+ offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) {
+ /* SKL DPB/C/D aux ctl register changed */
+ return 0;
+ } else if (IS_BROADWELL(vgpu->gvt->dev_priv) &&
+ offset != _REG_HSW_DP_AUX_CH_CTL(port_index)) {
+ /* write to the data registers */
+ return 0;
+ }
+
+ if (!(data & DP_AUX_CH_CTL_SEND_BUSY)) {
+ /* just want to clear the sticky bits */
+ vgpu_vreg(vgpu, offset) = 0;
+ return 0;
+ }
+
+ port = &display->ports[port_index];
+ dpcd = port->dpcd;
+
+ /* read out message from DATA1 register */
+ msg = vgpu_vreg(vgpu, offset + 4);
+ addr = (msg >> 8) & 0xffff;
+ ctrl = (msg >> 24) & 0xff;
+ len = msg & 0xff;
+ op = ctrl >> 4;
+
+ if (op == GVT_AUX_NATIVE_WRITE) {
+ int t;
+ uint8_t buf[16];
+
+ if ((addr + len + 1) >= DPCD_SIZE) {
+ /*
+ * Write request exceeds what we supported,
+ * DCPD spec: When a Source Device is writing a DPCD
+ * address not supported by the Sink Device, the Sink
+ * Device shall reply with AUX NACK and “M†equal to
+ * zero.
+ */
+
+ /* NAK the write */
+ vgpu_vreg(vgpu, offset + 4) = AUX_NATIVE_REPLY_NAK;
+ dp_aux_ch_ctl_trans_done(vgpu, data, offset, 2, true);
+ return 0;
+ }
+
+ /*
+ * Write request format: (command + address) occupies
+ * 3 bytes, followed by (len + 1) bytes of data.
+ */
+ if (WARN_ON((len + 4) > AUX_BURST_SIZE))
+ return -EINVAL;
+
+ /* unpack data from vreg to buf */
+ for (t = 0; t < 4; t++) {
+ u32 r = vgpu_vreg(vgpu, offset + 8 + t * 4);
+
+ buf[t * 4] = (r >> 24) & 0xff;
+ buf[t * 4 + 1] = (r >> 16) & 0xff;
+ buf[t * 4 + 2] = (r >> 8) & 0xff;
+ buf[t * 4 + 3] = r & 0xff;
+ }
+
+ /* write to virtual DPCD */
+ if (dpcd && dpcd->data_valid) {
+ for (t = 0; t <= len; t++) {
+ int p = addr + t;
+
+ dpcd->data[p] = buf[t];
+ /* check for link training */
+ if (p == DPCD_TRAINING_PATTERN_SET)
+ dp_aux_ch_ctl_link_training(dpcd,
+ buf[t]);
+ }
+ }
+
+ /* ACK the write */
+ vgpu_vreg(vgpu, offset + 4) = 0;
+ dp_aux_ch_ctl_trans_done(vgpu, data, offset, 1,
+ dpcd && dpcd->data_valid);
+ return 0;
+ }
+
+ if (op == GVT_AUX_NATIVE_READ) {
+ int idx, i, ret = 0;
+
+ if ((addr + len + 1) >= DPCD_SIZE) {
+ /*
+ * read request exceeds what we supported
+ * DPCD spec: A Sink Device receiving a Native AUX CH
+ * read request for an unsupported DPCD address must
+ * reply with an AUX ACK and read data set equal to
+ * zero instead of replying with AUX NACK.
+ */
+
+ /* ACK the READ*/
+ vgpu_vreg(vgpu, offset + 4) = 0;
+ vgpu_vreg(vgpu, offset + 8) = 0;
+ vgpu_vreg(vgpu, offset + 12) = 0;
+ vgpu_vreg(vgpu, offset + 16) = 0;
+ vgpu_vreg(vgpu, offset + 20) = 0;
+
+ dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2,
+ true);
+ return 0;
+ }
+
+ for (idx = 1; idx <= 5; idx++) {
+ /* clear the data registers */
+ vgpu_vreg(vgpu, offset + 4 * idx) = 0;
+ }
+
+ /*
+ * Read reply format: ACK (1 byte) plus (len + 1) bytes of data.
+ */
+ if (WARN_ON((len + 2) > AUX_BURST_SIZE))
+ return -EINVAL;
+
+ /* read from virtual DPCD to vreg */
+ /* first 4 bytes: [ACK][addr][addr+1][addr+2] */
+ if (dpcd && dpcd->data_valid) {
+ for (i = 1; i <= (len + 1); i++) {
+ int t;
+
+ t = dpcd->data[addr + i - 1];
+ t <<= (24 - 8 * (i % 4));
+ ret |= t;
+
+ if ((i % 4 == 3) || (i == (len + 1))) {
+ vgpu_vreg(vgpu, offset +
+ (i / 4 + 1) * 4) = ret;
+ ret = 0;
+ }
+ }
+ }
+ dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2,
+ dpcd && dpcd->data_valid);
+ return 0;
+ }
+
+ /* i2c transaction starts */
+ intel_gvt_i2c_handle_aux_ch_write(vgpu, port_index, offset, p_data);
+
+ if (data & DP_AUX_CH_CTL_INTERRUPT)
+ trigger_aux_channel_interrupt(vgpu, offset);
+ return 0;
+}
+
+static int vga_control_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ bool vga_disable;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ vga_disable = vgpu_vreg(vgpu, offset) & VGA_DISP_DISABLE;
+
+ gvt_dbg_core("vgpu%d: %s VGA mode\n", vgpu->id,
+ vga_disable ? "Disable" : "Enable");
+ return 0;
+}
+
+static u32 read_virtual_sbi_register(struct intel_vgpu *vgpu,
+ unsigned int sbi_offset)
+{
+ struct intel_vgpu_display *display = &vgpu->display;
+ int num = display->sbi.number;
+ int i;
+
+ for (i = 0; i < num; ++i)
+ if (display->sbi.registers[i].offset == sbi_offset)
+ break;
+
+ if (i == num)
+ return 0;
+
+ return display->sbi.registers[i].value;
+}
+
+static void write_virtual_sbi_register(struct intel_vgpu *vgpu,
+ unsigned int offset, u32 value)
+{
+ struct intel_vgpu_display *display = &vgpu->display;
+ int num = display->sbi.number;
+ int i;
+
+ for (i = 0; i < num; ++i) {
+ if (display->sbi.registers[i].offset == offset)
+ break;
+ }
+
+ if (i == num) {
+ if (num == SBI_REG_MAX) {
+ gvt_err("vgpu%d: SBI caching meets maximum limits\n",
+ vgpu->id);
+ return;
+ }
+ display->sbi.number++;
+ }
+
+ display->sbi.registers[i].offset = offset;
+ display->sbi.registers[i].value = value;
+}
+
+static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >>
+ SBI_OPCODE_SHIFT) == SBI_CMD_CRRD) {
+ unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) &
+ SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT;
+ vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu,
+ sbi_offset);
+ }
+ read_vreg(vgpu, offset, p_data, bytes);
+ return 0;
+}
+
+static bool sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ data &= ~(SBI_STAT_MASK << SBI_STAT_SHIFT);
+ data |= SBI_READY;
+
+ data &= ~(SBI_RESPONSE_MASK << SBI_RESPONSE_SHIFT);
+ data |= SBI_RESPONSE_SUCCESS;
+
+ vgpu_vreg(vgpu, offset) = data;
+
+ if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >>
+ SBI_OPCODE_SHIFT) == SBI_CMD_CRWR) {
+ unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) &
+ SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT;
+
+ write_virtual_sbi_register(vgpu, sbi_offset,
+ vgpu_vreg(vgpu, SBI_DATA));
+ }
+ return 0;
+}
+
+#define _vgtif_reg(x) \
+ (VGT_PVINFO_PAGE + offsetof(struct vgt_if, x))
+
+static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ bool invalid_read = false;
+
+ read_vreg(vgpu, offset, p_data, bytes);
+
+ switch (offset) {
+ case _vgtif_reg(magic) ... _vgtif_reg(vgt_id):
+ if (offset + bytes > _vgtif_reg(vgt_id) + 4)
+ invalid_read = true;
+ break;
+ case _vgtif_reg(avail_rs.mappable_gmadr.base) ...
+ _vgtif_reg(avail_rs.fence_num):
+ if (offset + bytes >
+ _vgtif_reg(avail_rs.fence_num) + 4)
+ invalid_read = true;
+ break;
+ case 0x78010: /* vgt_caps */
+ case 0x7881c:
+ break;
+ default:
+ invalid_read = true;
+ break;
+ }
+ if (invalid_read)
+ gvt_err("invalid pvinfo read: [%x:%x] = %x\n",
+ offset, bytes, *(u32 *)p_data);
+ return 0;
+}
+
+static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
+{
+ int ret = 0;
+
+ switch (notification) {
+ case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE:
+ ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 3);
+ break;
+ case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY:
+ ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 3);
+ break;
+ case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE:
+ ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 4);
+ break;
+ case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY:
+ ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 4);
+ break;
+ case VGT_G2V_EXECLIST_CONTEXT_CREATE:
+ case VGT_G2V_EXECLIST_CONTEXT_DESTROY:
+ case 1: /* Remove this in guest driver. */
+ break;
+ default:
+ gvt_err("Invalid PV notification %d\n", notification);
+ }
+ return ret;
+}
+
+static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
+ char *env[3] = {NULL, NULL, NULL};
+ char vmid_str[20];
+ char display_ready_str[20];
+
+ snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d\n", ready);
+ env[0] = display_ready_str;
+
+ snprintf(vmid_str, 20, "VMID=%d", vgpu->id);
+ env[1] = vmid_str;
+
+ return kobject_uevent_env(kobj, KOBJ_ADD, env);
+}
+
+static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 data;
+ int ret;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ switch (offset) {
+ case _vgtif_reg(display_ready):
+ send_display_ready_uevent(vgpu, data ? 1 : 0);
+ break;
+ case _vgtif_reg(g2v_notify):
+ ret = handle_g2v_notification(vgpu, data);
+ break;
+ /* add xhot and yhot to handled list to avoid error log */
+ case 0x78830:
+ case 0x78834:
+ case _vgtif_reg(pdp[0].lo):
+ case _vgtif_reg(pdp[0].hi):
+ case _vgtif_reg(pdp[1].lo):
+ case _vgtif_reg(pdp[1].hi):
+ case _vgtif_reg(pdp[2].lo):
+ case _vgtif_reg(pdp[2].hi):
+ case _vgtif_reg(pdp[3].lo):
+ case _vgtif_reg(pdp[3].hi):
+ case _vgtif_reg(execlist_context_descriptor_lo):
+ case _vgtif_reg(execlist_context_descriptor_hi):
+ break;
+ default:
+ gvt_err("invalid pvinfo write offset %x bytes %x data %x\n",
+ offset, bytes, data);
+ break;
+ }
+ return 0;
+}
+
+static int pf_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 val = *(u32 *)p_data;
+
+ if ((offset == _PS_1A_CTRL || offset == _PS_2A_CTRL ||
+ offset == _PS_1B_CTRL || offset == _PS_2B_CTRL ||
+ offset == _PS_1C_CTRL) && (val & PS_PLANE_SEL_MASK) != 0) {
+ WARN_ONCE(true, "VM(%d): guest is trying to scaling a plane\n",
+ vgpu->id);
+ return 0;
+ }
+
+ return intel_vgpu_default_mmio_write(vgpu, offset, p_data, bytes);
+}
+
+static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_ENABLE_REQUEST)
+ vgpu_vreg(vgpu, offset) |= HSW_PWR_WELL_STATE_ENABLED;
+ else
+ vgpu_vreg(vgpu, offset) &= ~HSW_PWR_WELL_STATE_ENABLED;
+ return 0;
+}
+
+static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+
+ if (vgpu_vreg(vgpu, offset) & FPGA_DBG_RM_NOCLAIM)
+ vgpu_vreg(vgpu, offset) &= ~FPGA_DBG_RM_NOCLAIM;
+ return 0;
+}
+
+static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 mode;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ mode = vgpu_vreg(vgpu, offset);
+
+ if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) {
+ WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n",
+ vgpu->id);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int gen9_trtte_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ u32 trtte = *(u32 *)p_data;
+
+ if ((trtte & 1) && (trtte & (1 << 1)) == 0) {
+ WARN(1, "VM(%d): Use physical address for TRTT!\n",
+ vgpu->id);
+ return -EINVAL;
+ }
+ write_vreg(vgpu, offset, p_data, bytes);
+ /* TRTTE is not per-context */
+ I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset));
+
+ return 0;
+}
+
+static int gen9_trtt_chicken_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ u32 val = *(u32 *)p_data;
+
+ if (val & 1) {
+ /* unblock hw logic */
+ I915_WRITE(_MMIO(offset), val);
+ }
+ write_vreg(vgpu, offset, p_data, bytes);
+ return 0;
+}
+
+static int dpll_status_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 v = 0;
+
+ if (vgpu_vreg(vgpu, 0x46010) & (1 << 31))
+ v |= (1 << 0);
+
+ if (vgpu_vreg(vgpu, 0x46014) & (1 << 31))
+ v |= (1 << 8);
+
+ if (vgpu_vreg(vgpu, 0x46040) & (1 << 31))
+ v |= (1 << 16);
+
+ if (vgpu_vreg(vgpu, 0x46060) & (1 << 31))
+ v |= (1 << 24);
+
+ vgpu_vreg(vgpu, offset) = v;
+
+ return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+}
+
+static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 value = *(u32 *)p_data;
+ u32 cmd = value & 0xff;
+ u32 *data0 = &vgpu_vreg(vgpu, GEN6_PCODE_DATA);
+
+ switch (cmd) {
+ case 0x6:
+ /**
+ * "Read memory latency" command on gen9.
+ * Below memory latency values are read
+ * from skylake platform.
+ */
+ if (!*data0)
+ *data0 = 0x1e1a1100;
+ else
+ *data0 = 0x61514b3d;
+ break;
+ case 0x5:
+ *data0 |= 0x1;
+ break;
+ }
+
+ gvt_dbg_core("VM(%d) write %x to mailbox, return data0 %x\n",
+ vgpu->id, value, *data0);
+
+ value &= ~(1 << 31);
+ return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes);
+}
+
+static int skl_power_well_ctl_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 v = *(u32 *)p_data;
+
+ v &= (1 << 31) | (1 << 29) | (1 << 9) |
+ (1 << 7) | (1 << 5) | (1 << 3) | (1 << 1);
+ v |= (v >> 1);
+
+ return intel_vgpu_default_mmio_write(vgpu, offset, &v, bytes);
+}
+
+static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ i915_reg_t reg = {.reg = offset};
+
+ switch (offset) {
+ case 0x4ddc:
+ vgpu_vreg(vgpu, offset) = 0x8000003c;
+ /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */
+ I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+ break;
+ case 0x42080:
+ vgpu_vreg(vgpu, offset) = 0x8000;
+ /* WaCompressedResourceDisplayNewHashMode:skl */
+ I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 v = *(u32 *)p_data;
+
+ /* other bits are MBZ. */
+ v &= (1 << 31) | (1 << 30);
+ v & (1 << 31) ? (v |= (1 << 30)) : (v &= ~(1 << 30));
+
+ vgpu_vreg(vgpu, offset) = v;
+
+ return 0;
+}
+
+static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset));
+ return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+}
+
+static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+ struct intel_vgpu_execlist *execlist;
+ u32 data = *(u32 *)p_data;
+ int ret = 0;
+
+ if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1))
+ return -EINVAL;
+
+ execlist = &vgpu->execlist[ring_id];
+
+ execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data;
+ if (execlist->elsp_dwords.index == 3) {
+ ret = intel_vgpu_submit_execlist(vgpu, ring_id);
+ if(ret)
+ gvt_err("fail submit workload on ring %d\n", ring_id);
+ }
+
+ ++execlist->elsp_dwords.index;
+ execlist->elsp_dwords.index &= 0x3;
+ return ret;
+}
+
+static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ u32 data = *(u32 *)p_data;
+ int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+ bool enable_execlist;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))
+ || (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) {
+ enable_execlist = !!(data & GFX_RUN_LIST_ENABLE);
+
+ gvt_dbg_core("EXECLIST %s on ring %d\n",
+ (enable_execlist ? "enabling" : "disabling"),
+ ring_id);
+
+ if (enable_execlist)
+ intel_vgpu_start_schedule(vgpu);
+ }
+ return 0;
+}
+
+static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ int rc = 0;
+ unsigned int id = 0;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ vgpu_vreg(vgpu, offset) = 0;
+
+ switch (offset) {
+ case 0x4260:
+ id = RCS;
+ break;
+ case 0x4264:
+ id = VCS;
+ break;
+ case 0x4268:
+ id = VCS2;
+ break;
+ case 0x426c:
+ id = BCS;
+ break;
+ case 0x4270:
+ id = VECS;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ set_bit(id, (void *)vgpu->tlb_handle_pending);
+
+ return rc;
+}
+
+static int ring_reset_ctl_write(struct intel_vgpu *vgpu,
+ unsigned int offset, void *p_data, unsigned int bytes)
+{
+ u32 data;
+
+ write_vreg(vgpu, offset, p_data, bytes);
+ data = vgpu_vreg(vgpu, offset);
+
+ if (data & _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET))
+ data |= RESET_CTL_READY_TO_RESET;
+ else if (data & _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET))
+ data &= ~RESET_CTL_READY_TO_RESET;
+
+ vgpu_vreg(vgpu, offset) = data;
+ return 0;
+}
+
+#define MMIO_F(reg, s, f, am, rm, d, r, w) do { \
+ ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \
+ f, s, am, rm, d, r, w); \
+ if (ret) \
+ return ret; \
+} while (0)
+
+#define MMIO_D(reg, d) \
+ MMIO_F(reg, 4, 0, 0, 0, d, NULL, NULL)
+
+#define MMIO_DH(reg, d, r, w) \
+ MMIO_F(reg, 4, 0, 0, 0, d, r, w)
+
+#define MMIO_DFH(reg, d, f, r, w) \
+ MMIO_F(reg, 4, f, 0, 0, d, r, w)
+
+#define MMIO_GM(reg, d, r, w) \
+ MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w)
+
+#define MMIO_RO(reg, d, f, rm, r, w) \
+ MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w)
+
+#define MMIO_RING_F(prefix, s, f, am, rm, d, r, w) do { \
+ MMIO_F(prefix(RENDER_RING_BASE), s, f, am, rm, d, r, w); \
+ MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \
+ MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \
+ MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \
+} while (0)
+
+#define MMIO_RING_D(prefix, d) \
+ MMIO_RING_F(prefix, 4, 0, 0, 0, d, NULL, NULL)
+
+#define MMIO_RING_DFH(prefix, d, f, r, w) \
+ MMIO_RING_F(prefix, 4, f, 0, 0, d, r, w)
+
+#define MMIO_RING_GM(prefix, d, r, w) \
+ MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w)
+
+#define MMIO_RING_RO(prefix, d, f, rm, r, w) \
+ MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w)
+
+static int init_generic_mmio_info(struct intel_gvt *gvt)
+{
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ int ret;
+
+ MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler);
+
+ MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DFH(SDEIER, D_ALL, 0, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(SDEISR, D_ALL);
+
+ MMIO_RING_D(RING_HWSTAM, D_ALL);
+
+ MMIO_GM(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+ MMIO_GM(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+ MMIO_GM(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+ MMIO_GM(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+
+#define RING_REG(base) (base + 0x28)
+ MMIO_RING_D(RING_REG, D_ALL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x134)
+ MMIO_RING_D(RING_REG, D_ALL);
+#undef RING_REG
+
+ MMIO_GM(0x2148, D_ALL, NULL, NULL);
+ MMIO_GM(CCID, D_ALL, NULL, NULL);
+ MMIO_GM(0x12198, D_ALL, NULL, NULL);
+ MMIO_D(GEN7_CXT_SIZE, D_ALL);
+
+ MMIO_RING_D(RING_TAIL, D_ALL);
+ MMIO_RING_D(RING_HEAD, D_ALL);
+ MMIO_RING_D(RING_CTL, D_ALL);
+ MMIO_RING_D(RING_ACTHD, D_ALL);
+ MMIO_RING_GM(RING_START, D_ALL, NULL, NULL);
+
+ /* RING MODE */
+#define RING_REG(base) (base + 0x29c)
+ MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write);
+#undef RING_REG
+
+ MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS,
+ ring_timestamp_mmio_read, NULL);
+ MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS,
+ ring_timestamp_mmio_read, NULL);
+
+ MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(CACHE_MODE_1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+
+ MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(0x2088, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(0x2470, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_D(GAM_ECOCHK, D_ALL);
+ MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_D(0x9030, D_ALL);
+ MMIO_D(0x20a0, D_ALL);
+ MMIO_D(0x2420, D_ALL);
+ MMIO_D(0x2430, D_ALL);
+ MMIO_D(0x2434, D_ALL);
+ MMIO_D(0x2438, D_ALL);
+ MMIO_D(0x243c, D_ALL);
+ MMIO_DFH(0x7018, D_ALL, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(HALF_SLICE_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0xe100, D_ALL, F_MODE_MASK, NULL, NULL);
+
+ /* display */
+ MMIO_F(0x60220, 0x20, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_D(0x602a0, D_ALL);
+
+ MMIO_D(0x65050, D_ALL);
+ MMIO_D(0x650b4, D_ALL);
+
+ MMIO_D(0xc4040, D_ALL);
+ MMIO_D(DERRMR, D_ALL);
+
+ MMIO_D(PIPEDSL(PIPE_A), D_ALL);
+ MMIO_D(PIPEDSL(PIPE_B), D_ALL);
+ MMIO_D(PIPEDSL(PIPE_C), D_ALL);
+ MMIO_D(PIPEDSL(_PIPE_EDP), D_ALL);
+
+ MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, pipeconf_mmio_write);
+ MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, pipeconf_mmio_write);
+ MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, pipeconf_mmio_write);
+ MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, pipeconf_mmio_write);
+
+ MMIO_D(PIPESTAT(PIPE_A), D_ALL);
+ MMIO_D(PIPESTAT(PIPE_B), D_ALL);
+ MMIO_D(PIPESTAT(PIPE_C), D_ALL);
+ MMIO_D(PIPESTAT(_PIPE_EDP), D_ALL);
+
+ MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_A), D_ALL);
+ MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_B), D_ALL);
+ MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_C), D_ALL);
+ MMIO_D(PIPE_FLIPCOUNT_G4X(_PIPE_EDP), D_ALL);
+
+ MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_A), D_ALL);
+ MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_B), D_ALL);
+ MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_C), D_ALL);
+ MMIO_D(PIPE_FRMCOUNT_G4X(_PIPE_EDP), D_ALL);
+
+ MMIO_D(CURCNTR(PIPE_A), D_ALL);
+ MMIO_D(CURCNTR(PIPE_B), D_ALL);
+ MMIO_D(CURCNTR(PIPE_C), D_ALL);
+
+ MMIO_D(CURPOS(PIPE_A), D_ALL);
+ MMIO_D(CURPOS(PIPE_B), D_ALL);
+ MMIO_D(CURPOS(PIPE_C), D_ALL);
+
+ MMIO_D(CURBASE(PIPE_A), D_ALL);
+ MMIO_D(CURBASE(PIPE_B), D_ALL);
+ MMIO_D(CURBASE(PIPE_C), D_ALL);
+
+ MMIO_D(0x700ac, D_ALL);
+ MMIO_D(0x710ac, D_ALL);
+ MMIO_D(0x720ac, D_ALL);
+
+ MMIO_D(0x70090, D_ALL);
+ MMIO_D(0x70094, D_ALL);
+ MMIO_D(0x70098, D_ALL);
+ MMIO_D(0x7009c, D_ALL);
+
+ MMIO_D(DSPCNTR(PIPE_A), D_ALL);
+ MMIO_D(DSPADDR(PIPE_A), D_ALL);
+ MMIO_D(DSPSTRIDE(PIPE_A), D_ALL);
+ MMIO_D(DSPPOS(PIPE_A), D_ALL);
+ MMIO_D(DSPSIZE(PIPE_A), D_ALL);
+ MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write);
+ MMIO_D(DSPOFFSET(PIPE_A), D_ALL);
+ MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL);
+
+ MMIO_D(DSPCNTR(PIPE_B), D_ALL);
+ MMIO_D(DSPADDR(PIPE_B), D_ALL);
+ MMIO_D(DSPSTRIDE(PIPE_B), D_ALL);
+ MMIO_D(DSPPOS(PIPE_B), D_ALL);
+ MMIO_D(DSPSIZE(PIPE_B), D_ALL);
+ MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write);
+ MMIO_D(DSPOFFSET(PIPE_B), D_ALL);
+ MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL);
+
+ MMIO_D(DSPCNTR(PIPE_C), D_ALL);
+ MMIO_D(DSPADDR(PIPE_C), D_ALL);
+ MMIO_D(DSPSTRIDE(PIPE_C), D_ALL);
+ MMIO_D(DSPPOS(PIPE_C), D_ALL);
+ MMIO_D(DSPSIZE(PIPE_C), D_ALL);
+ MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write);
+ MMIO_D(DSPOFFSET(PIPE_C), D_ALL);
+ MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL);
+
+ MMIO_D(SPRCTL(PIPE_A), D_ALL);
+ MMIO_D(SPRLINOFF(PIPE_A), D_ALL);
+ MMIO_D(SPRSTRIDE(PIPE_A), D_ALL);
+ MMIO_D(SPRPOS(PIPE_A), D_ALL);
+ MMIO_D(SPRSIZE(PIPE_A), D_ALL);
+ MMIO_D(SPRKEYVAL(PIPE_A), D_ALL);
+ MMIO_D(SPRKEYMSK(PIPE_A), D_ALL);
+ MMIO_DH(SPRSURF(PIPE_A), D_ALL, NULL, spr_surf_mmio_write);
+ MMIO_D(SPRKEYMAX(PIPE_A), D_ALL);
+ MMIO_D(SPROFFSET(PIPE_A), D_ALL);
+ MMIO_D(SPRSCALE(PIPE_A), D_ALL);
+ MMIO_D(SPRSURFLIVE(PIPE_A), D_ALL);
+
+ MMIO_D(SPRCTL(PIPE_B), D_ALL);
+ MMIO_D(SPRLINOFF(PIPE_B), D_ALL);
+ MMIO_D(SPRSTRIDE(PIPE_B), D_ALL);
+ MMIO_D(SPRPOS(PIPE_B), D_ALL);
+ MMIO_D(SPRSIZE(PIPE_B), D_ALL);
+ MMIO_D(SPRKEYVAL(PIPE_B), D_ALL);
+ MMIO_D(SPRKEYMSK(PIPE_B), D_ALL);
+ MMIO_DH(SPRSURF(PIPE_B), D_ALL, NULL, spr_surf_mmio_write);
+ MMIO_D(SPRKEYMAX(PIPE_B), D_ALL);
+ MMIO_D(SPROFFSET(PIPE_B), D_ALL);
+ MMIO_D(SPRSCALE(PIPE_B), D_ALL);
+ MMIO_D(SPRSURFLIVE(PIPE_B), D_ALL);
+
+ MMIO_D(SPRCTL(PIPE_C), D_ALL);
+ MMIO_D(SPRLINOFF(PIPE_C), D_ALL);
+ MMIO_D(SPRSTRIDE(PIPE_C), D_ALL);
+ MMIO_D(SPRPOS(PIPE_C), D_ALL);
+ MMIO_D(SPRSIZE(PIPE_C), D_ALL);
+ MMIO_D(SPRKEYVAL(PIPE_C), D_ALL);
+ MMIO_D(SPRKEYMSK(PIPE_C), D_ALL);
+ MMIO_DH(SPRSURF(PIPE_C), D_ALL, NULL, spr_surf_mmio_write);
+ MMIO_D(SPRKEYMAX(PIPE_C), D_ALL);
+ MMIO_D(SPROFFSET(PIPE_C), D_ALL);
+ MMIO_D(SPRSCALE(PIPE_C), D_ALL);
+ MMIO_D(SPRSURFLIVE(PIPE_C), D_ALL);
+
+ MMIO_F(LGC_PALETTE(PIPE_A, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(LGC_PALETTE(PIPE_B, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(LGC_PALETTE(PIPE_C, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(HTOTAL(TRANSCODER_A), D_ALL);
+ MMIO_D(HBLANK(TRANSCODER_A), D_ALL);
+ MMIO_D(HSYNC(TRANSCODER_A), D_ALL);
+ MMIO_D(VTOTAL(TRANSCODER_A), D_ALL);
+ MMIO_D(VBLANK(TRANSCODER_A), D_ALL);
+ MMIO_D(VSYNC(TRANSCODER_A), D_ALL);
+ MMIO_D(BCLRPAT(TRANSCODER_A), D_ALL);
+ MMIO_D(VSYNCSHIFT(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPESRC(TRANSCODER_A), D_ALL);
+
+ MMIO_D(HTOTAL(TRANSCODER_B), D_ALL);
+ MMIO_D(HBLANK(TRANSCODER_B), D_ALL);
+ MMIO_D(HSYNC(TRANSCODER_B), D_ALL);
+ MMIO_D(VTOTAL(TRANSCODER_B), D_ALL);
+ MMIO_D(VBLANK(TRANSCODER_B), D_ALL);
+ MMIO_D(VSYNC(TRANSCODER_B), D_ALL);
+ MMIO_D(BCLRPAT(TRANSCODER_B), D_ALL);
+ MMIO_D(VSYNCSHIFT(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPESRC(TRANSCODER_B), D_ALL);
+
+ MMIO_D(HTOTAL(TRANSCODER_C), D_ALL);
+ MMIO_D(HBLANK(TRANSCODER_C), D_ALL);
+ MMIO_D(HSYNC(TRANSCODER_C), D_ALL);
+ MMIO_D(VTOTAL(TRANSCODER_C), D_ALL);
+ MMIO_D(VBLANK(TRANSCODER_C), D_ALL);
+ MMIO_D(VSYNC(TRANSCODER_C), D_ALL);
+ MMIO_D(BCLRPAT(TRANSCODER_C), D_ALL);
+ MMIO_D(VSYNCSHIFT(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPESRC(TRANSCODER_C), D_ALL);
+
+ MMIO_D(HTOTAL(TRANSCODER_EDP), D_ALL);
+ MMIO_D(HBLANK(TRANSCODER_EDP), D_ALL);
+ MMIO_D(HSYNC(TRANSCODER_EDP), D_ALL);
+ MMIO_D(VTOTAL(TRANSCODER_EDP), D_ALL);
+ MMIO_D(VBLANK(TRANSCODER_EDP), D_ALL);
+ MMIO_D(VSYNC(TRANSCODER_EDP), D_ALL);
+ MMIO_D(BCLRPAT(TRANSCODER_EDP), D_ALL);
+ MMIO_D(VSYNCSHIFT(TRANSCODER_EDP), D_ALL);
+
+ MMIO_D(PIPE_DATA_M1(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_DATA_N1(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_DATA_M2(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_DATA_N2(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_LINK_M1(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_LINK_N1(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_LINK_M2(TRANSCODER_A), D_ALL);
+ MMIO_D(PIPE_LINK_N2(TRANSCODER_A), D_ALL);
+
+ MMIO_D(PIPE_DATA_M1(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_DATA_N1(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_DATA_M2(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_DATA_N2(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_LINK_M1(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_LINK_N1(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_LINK_M2(TRANSCODER_B), D_ALL);
+ MMIO_D(PIPE_LINK_N2(TRANSCODER_B), D_ALL);
+
+ MMIO_D(PIPE_DATA_M1(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_DATA_N1(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_DATA_M2(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_DATA_N2(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_LINK_M1(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_LINK_N1(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_LINK_M2(TRANSCODER_C), D_ALL);
+ MMIO_D(PIPE_LINK_N2(TRANSCODER_C), D_ALL);
+
+ MMIO_D(PIPE_DATA_M1(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_DATA_N1(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_DATA_M2(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_DATA_N2(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_LINK_M1(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_LINK_N1(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_LINK_M2(TRANSCODER_EDP), D_ALL);
+ MMIO_D(PIPE_LINK_N2(TRANSCODER_EDP), D_ALL);
+
+ MMIO_D(PF_CTL(PIPE_A), D_ALL);
+ MMIO_D(PF_WIN_SZ(PIPE_A), D_ALL);
+ MMIO_D(PF_WIN_POS(PIPE_A), D_ALL);
+ MMIO_D(PF_VSCALE(PIPE_A), D_ALL);
+ MMIO_D(PF_HSCALE(PIPE_A), D_ALL);
+
+ MMIO_D(PF_CTL(PIPE_B), D_ALL);
+ MMIO_D(PF_WIN_SZ(PIPE_B), D_ALL);
+ MMIO_D(PF_WIN_POS(PIPE_B), D_ALL);
+ MMIO_D(PF_VSCALE(PIPE_B), D_ALL);
+ MMIO_D(PF_HSCALE(PIPE_B), D_ALL);
+
+ MMIO_D(PF_CTL(PIPE_C), D_ALL);
+ MMIO_D(PF_WIN_SZ(PIPE_C), D_ALL);
+ MMIO_D(PF_WIN_POS(PIPE_C), D_ALL);
+ MMIO_D(PF_VSCALE(PIPE_C), D_ALL);
+ MMIO_D(PF_HSCALE(PIPE_C), D_ALL);
+
+ MMIO_D(WM0_PIPEA_ILK, D_ALL);
+ MMIO_D(WM0_PIPEB_ILK, D_ALL);
+ MMIO_D(WM0_PIPEC_IVB, D_ALL);
+ MMIO_D(WM1_LP_ILK, D_ALL);
+ MMIO_D(WM2_LP_ILK, D_ALL);
+ MMIO_D(WM3_LP_ILK, D_ALL);
+ MMIO_D(WM1S_LP_ILK, D_ALL);
+ MMIO_D(WM2S_LP_IVB, D_ALL);
+ MMIO_D(WM3S_LP_IVB, D_ALL);
+
+ MMIO_D(BLC_PWM_CPU_CTL2, D_ALL);
+ MMIO_D(BLC_PWM_CPU_CTL, D_ALL);
+ MMIO_D(BLC_PWM_PCH_CTL1, D_ALL);
+ MMIO_D(BLC_PWM_PCH_CTL2, D_ALL);
+
+ MMIO_D(0x48268, D_ALL);
+
+ MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, gmbus_mmio_read,
+ gmbus_mmio_write);
+ MMIO_F(PCH_GPIOA, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0xe4f00, 0x28, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+ dp_aux_ch_ctl_mmio_write);
+ MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+ dp_aux_ch_ctl_mmio_write);
+ MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+ dp_aux_ch_ctl_mmio_write);
+
+ MMIO_RO(PCH_ADPA, D_ALL, 0, ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, pch_adpa_mmio_write);
+
+ MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, transconf_mmio_write);
+ MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, transconf_mmio_write);
+
+ MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, fdi_rx_iir_mmio_write);
+ MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, fdi_rx_iir_mmio_write);
+ MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, fdi_rx_iir_mmio_write);
+ MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status);
+ MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status);
+ MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status);
+ MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status);
+ MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status);
+ MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status);
+
+ MMIO_D(_PCH_TRANS_HTOTAL_A, D_ALL);
+ MMIO_D(_PCH_TRANS_HBLANK_A, D_ALL);
+ MMIO_D(_PCH_TRANS_HSYNC_A, D_ALL);
+ MMIO_D(_PCH_TRANS_VTOTAL_A, D_ALL);
+ MMIO_D(_PCH_TRANS_VBLANK_A, D_ALL);
+ MMIO_D(_PCH_TRANS_VSYNC_A, D_ALL);
+ MMIO_D(_PCH_TRANS_VSYNCSHIFT_A, D_ALL);
+
+ MMIO_D(_PCH_TRANS_HTOTAL_B, D_ALL);
+ MMIO_D(_PCH_TRANS_HBLANK_B, D_ALL);
+ MMIO_D(_PCH_TRANS_HSYNC_B, D_ALL);
+ MMIO_D(_PCH_TRANS_VTOTAL_B, D_ALL);
+ MMIO_D(_PCH_TRANS_VBLANK_B, D_ALL);
+ MMIO_D(_PCH_TRANS_VSYNC_B, D_ALL);
+ MMIO_D(_PCH_TRANS_VSYNCSHIFT_B, D_ALL);
+
+ MMIO_D(_PCH_TRANSA_DATA_M1, D_ALL);
+ MMIO_D(_PCH_TRANSA_DATA_N1, D_ALL);
+ MMIO_D(_PCH_TRANSA_DATA_M2, D_ALL);
+ MMIO_D(_PCH_TRANSA_DATA_N2, D_ALL);
+ MMIO_D(_PCH_TRANSA_LINK_M1, D_ALL);
+ MMIO_D(_PCH_TRANSA_LINK_N1, D_ALL);
+ MMIO_D(_PCH_TRANSA_LINK_M2, D_ALL);
+ MMIO_D(_PCH_TRANSA_LINK_N2, D_ALL);
+
+ MMIO_D(TRANS_DP_CTL(PIPE_A), D_ALL);
+ MMIO_D(TRANS_DP_CTL(PIPE_B), D_ALL);
+ MMIO_D(TRANS_DP_CTL(PIPE_C), D_ALL);
+
+ MMIO_D(TVIDEO_DIP_CTL(PIPE_A), D_ALL);
+ MMIO_D(TVIDEO_DIP_DATA(PIPE_A), D_ALL);
+ MMIO_D(TVIDEO_DIP_GCP(PIPE_A), D_ALL);
+
+ MMIO_D(TVIDEO_DIP_CTL(PIPE_B), D_ALL);
+ MMIO_D(TVIDEO_DIP_DATA(PIPE_B), D_ALL);
+ MMIO_D(TVIDEO_DIP_GCP(PIPE_B), D_ALL);
+
+ MMIO_D(TVIDEO_DIP_CTL(PIPE_C), D_ALL);
+ MMIO_D(TVIDEO_DIP_DATA(PIPE_C), D_ALL);
+ MMIO_D(TVIDEO_DIP_GCP(PIPE_C), D_ALL);
+
+ MMIO_D(_FDI_RXA_MISC, D_ALL);
+ MMIO_D(_FDI_RXB_MISC, D_ALL);
+ MMIO_D(_FDI_RXA_TUSIZE1, D_ALL);
+ MMIO_D(_FDI_RXA_TUSIZE2, D_ALL);
+ MMIO_D(_FDI_RXB_TUSIZE1, D_ALL);
+ MMIO_D(_FDI_RXB_TUSIZE2, D_ALL);
+
+ MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, pch_pp_control_mmio_write);
+ MMIO_D(PCH_PP_DIVISOR, D_ALL);
+ MMIO_D(PCH_PP_STATUS, D_ALL);
+ MMIO_D(PCH_LVDS, D_ALL);
+ MMIO_D(_PCH_DPLL_A, D_ALL);
+ MMIO_D(_PCH_DPLL_B, D_ALL);
+ MMIO_D(_PCH_FPA0, D_ALL);
+ MMIO_D(_PCH_FPA1, D_ALL);
+ MMIO_D(_PCH_FPB0, D_ALL);
+ MMIO_D(_PCH_FPB1, D_ALL);
+ MMIO_D(PCH_DREF_CONTROL, D_ALL);
+ MMIO_D(PCH_RAWCLK_FREQ, D_ALL);
+ MMIO_D(PCH_DPLL_SEL, D_ALL);
+
+ MMIO_D(0x61208, D_ALL);
+ MMIO_D(0x6120c, D_ALL);
+ MMIO_D(PCH_PP_ON_DELAYS, D_ALL);
+ MMIO_D(PCH_PP_OFF_DELAYS, D_ALL);
+
+ MMIO_DH(0xe651c, D_ALL, dpy_reg_mmio_read, NULL);
+ MMIO_DH(0xe661c, D_ALL, dpy_reg_mmio_read, NULL);
+ MMIO_DH(0xe671c, D_ALL, dpy_reg_mmio_read, NULL);
+ MMIO_DH(0xe681c, D_ALL, dpy_reg_mmio_read, NULL);
+ MMIO_DH(0xe6c04, D_ALL, dpy_reg_mmio_read_2, NULL);
+ MMIO_DH(0xe6e1c, D_ALL, dpy_reg_mmio_read_3, NULL);
+
+ MMIO_RO(PCH_PORT_HOTPLUG, D_ALL, 0,
+ PORTA_HOTPLUG_STATUS_MASK
+ | PORTB_HOTPLUG_STATUS_MASK
+ | PORTC_HOTPLUG_STATUS_MASK
+ | PORTD_HOTPLUG_STATUS_MASK,
+ NULL, NULL);
+
+ MMIO_DH(LCPLL_CTL, D_ALL, NULL, lcpll_ctl_mmio_write);
+ MMIO_D(FUSE_STRAP, D_ALL);
+ MMIO_D(DIGITAL_PORT_HOTPLUG_CNTRL, D_ALL);
+
+ MMIO_D(DISP_ARB_CTL, D_ALL);
+ MMIO_D(DISP_ARB_CTL2, D_ALL);
+
+ MMIO_D(ILK_DISPLAY_CHICKEN1, D_ALL);
+ MMIO_D(ILK_DISPLAY_CHICKEN2, D_ALL);
+ MMIO_D(ILK_DSPCLK_GATE_D, D_ALL);
+
+ MMIO_D(SOUTH_CHICKEN1, D_ALL);
+ MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, south_chicken2_mmio_write);
+ MMIO_D(_TRANSA_CHICKEN1, D_ALL);
+ MMIO_D(_TRANSB_CHICKEN1, D_ALL);
+ MMIO_D(SOUTH_DSPCLK_GATE_D, D_ALL);
+ MMIO_D(_TRANSA_CHICKEN2, D_ALL);
+ MMIO_D(_TRANSB_CHICKEN2, D_ALL);
+
+ MMIO_D(ILK_DPFC_CB_BASE, D_ALL);
+ MMIO_D(ILK_DPFC_CONTROL, D_ALL);
+ MMIO_D(ILK_DPFC_RECOMP_CTL, D_ALL);
+ MMIO_D(ILK_DPFC_STATUS, D_ALL);
+ MMIO_D(ILK_DPFC_FENCE_YOFF, D_ALL);
+ MMIO_D(ILK_DPFC_CHICKEN, D_ALL);
+ MMIO_D(ILK_FBC_RT_BASE, D_ALL);
+
+ MMIO_D(IPS_CTL, D_ALL);
+
+ MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BY(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BU(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BV(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_MODE(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_A), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_A), D_ALL);
+
+ MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BY(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BU(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BV(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_MODE(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_B), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_B), D_ALL);
+
+ MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BY(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BU(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_COEFF_BV(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_MODE(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_C), D_ALL);
+ MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_C), D_ALL);
+
+ MMIO_D(PREC_PAL_INDEX(PIPE_A), D_ALL);
+ MMIO_D(PREC_PAL_DATA(PIPE_A), D_ALL);
+ MMIO_F(PREC_PAL_GC_MAX(PIPE_A, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(PREC_PAL_INDEX(PIPE_B), D_ALL);
+ MMIO_D(PREC_PAL_DATA(PIPE_B), D_ALL);
+ MMIO_F(PREC_PAL_GC_MAX(PIPE_B, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(PREC_PAL_INDEX(PIPE_C), D_ALL);
+ MMIO_D(PREC_PAL_DATA(PIPE_C), D_ALL);
+ MMIO_F(PREC_PAL_GC_MAX(PIPE_C, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(0x60110, D_ALL);
+ MMIO_D(0x61110, D_ALL);
+ MMIO_F(0x70400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x71400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x72400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x70440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+ MMIO_F(0x71440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+ MMIO_F(0x72440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+ MMIO_F(0x7044c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+ MMIO_F(0x7144c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+ MMIO_F(0x7244c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+
+ MMIO_D(PIPE_WM_LINETIME(PIPE_A), D_ALL);
+ MMIO_D(PIPE_WM_LINETIME(PIPE_B), D_ALL);
+ MMIO_D(PIPE_WM_LINETIME(PIPE_C), D_ALL);
+ MMIO_D(SPLL_CTL, D_ALL);
+ MMIO_D(_WRPLL_CTL1, D_ALL);
+ MMIO_D(_WRPLL_CTL2, D_ALL);
+ MMIO_D(PORT_CLK_SEL(PORT_A), D_ALL);
+ MMIO_D(PORT_CLK_SEL(PORT_B), D_ALL);
+ MMIO_D(PORT_CLK_SEL(PORT_C), D_ALL);
+ MMIO_D(PORT_CLK_SEL(PORT_D), D_ALL);
+ MMIO_D(PORT_CLK_SEL(PORT_E), D_ALL);
+ MMIO_D(TRANS_CLK_SEL(TRANSCODER_A), D_ALL);
+ MMIO_D(TRANS_CLK_SEL(TRANSCODER_B), D_ALL);
+ MMIO_D(TRANS_CLK_SEL(TRANSCODER_C), D_ALL);
+
+ MMIO_D(HSW_NDE_RSTWRN_OPT, D_ALL);
+ MMIO_D(0x46508, D_ALL);
+
+ MMIO_D(0x49080, D_ALL);
+ MMIO_D(0x49180, D_ALL);
+ MMIO_D(0x49280, D_ALL);
+
+ MMIO_F(0x49090, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x49190, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x49290, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(GAMMA_MODE(PIPE_A), D_ALL);
+ MMIO_D(GAMMA_MODE(PIPE_B), D_ALL);
+ MMIO_D(GAMMA_MODE(PIPE_C), D_ALL);
+
+ MMIO_D(PIPE_MULT(PIPE_A), D_ALL);
+ MMIO_D(PIPE_MULT(PIPE_B), D_ALL);
+ MMIO_D(PIPE_MULT(PIPE_C), D_ALL);
+
+ MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_A), D_ALL);
+ MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_B), D_ALL);
+ MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_C), D_ALL);
+
+ MMIO_DH(SFUSE_STRAP, D_ALL, NULL, NULL);
+ MMIO_D(SBI_ADDR, D_ALL);
+ MMIO_DH(SBI_DATA, D_ALL, sbi_data_mmio_read, NULL);
+ MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, sbi_ctl_mmio_write);
+ MMIO_D(PIXCLK_GATE, D_ALL);
+
+ MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL,
+ dp_aux_ch_ctl_mmio_write);
+
+ MMIO_DH(DDI_BUF_CTL(PORT_A), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+ MMIO_DH(DDI_BUF_CTL(PORT_B), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+ MMIO_DH(DDI_BUF_CTL(PORT_C), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+ MMIO_DH(DDI_BUF_CTL(PORT_D), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+ MMIO_DH(DDI_BUF_CTL(PORT_E), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+
+ MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, dp_tp_ctl_mmio_write);
+ MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, dp_tp_ctl_mmio_write);
+ MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, dp_tp_ctl_mmio_write);
+ MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, dp_tp_ctl_mmio_write);
+ MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, dp_tp_ctl_mmio_write);
+
+ MMIO_DH(DP_TP_STATUS(PORT_A), D_ALL, NULL, dp_tp_status_mmio_write);
+ MMIO_DH(DP_TP_STATUS(PORT_B), D_ALL, NULL, dp_tp_status_mmio_write);
+ MMIO_DH(DP_TP_STATUS(PORT_C), D_ALL, NULL, dp_tp_status_mmio_write);
+ MMIO_DH(DP_TP_STATUS(PORT_D), D_ALL, NULL, dp_tp_status_mmio_write);
+ MMIO_DH(DP_TP_STATUS(PORT_E), D_ALL, NULL, NULL);
+
+ MMIO_F(_DDI_BUF_TRANS_A, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x64e60, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x64eC0, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x64f20, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x64f80, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(HSW_AUD_CFG(PIPE_A), D_ALL);
+ MMIO_D(HSW_AUD_PIN_ELD_CP_VLD, D_ALL);
+
+ MMIO_DH(_TRANS_DDI_FUNC_CTL_A, D_ALL, NULL, NULL);
+ MMIO_DH(_TRANS_DDI_FUNC_CTL_B, D_ALL, NULL, NULL);
+ MMIO_DH(_TRANS_DDI_FUNC_CTL_C, D_ALL, NULL, NULL);
+ MMIO_DH(_TRANS_DDI_FUNC_CTL_EDP, D_ALL, NULL, NULL);
+
+ MMIO_D(_TRANSA_MSA_MISC, D_ALL);
+ MMIO_D(_TRANSB_MSA_MISC, D_ALL);
+ MMIO_D(_TRANSC_MSA_MISC, D_ALL);
+ MMIO_D(_TRANS_EDP_MSA_MISC, D_ALL);
+
+ MMIO_DH(FORCEWAKE, D_ALL, NULL, NULL);
+ MMIO_D(FORCEWAKE_ACK, D_ALL);
+ MMIO_D(GEN6_GT_CORE_STATUS, D_ALL);
+ MMIO_D(GEN6_GT_THREAD_STATUS_REG, D_ALL);
+ MMIO_D(GTFIFODBG, D_ALL);
+ MMIO_D(GTFIFOCTL, D_ALL);
+ MMIO_DH(FORCEWAKE_MT, D_PRE_SKL, NULL, mul_force_wake_write);
+ MMIO_DH(FORCEWAKE_ACK_HSW, D_HSW | D_BDW, NULL, NULL);
+ MMIO_D(ECOBUS, D_ALL);
+ MMIO_DH(GEN6_RC_CONTROL, D_ALL, NULL, NULL);
+ MMIO_DH(GEN6_RC_STATE, D_ALL, NULL, NULL);
+ MMIO_D(GEN6_RPNSWREQ, D_ALL);
+ MMIO_D(GEN6_RC_VIDEO_FREQ, D_ALL);
+ MMIO_D(GEN6_RP_DOWN_TIMEOUT, D_ALL);
+ MMIO_D(GEN6_RP_INTERRUPT_LIMITS, D_ALL);
+ MMIO_D(GEN6_RPSTAT1, D_ALL);
+ MMIO_D(GEN6_RP_CONTROL, D_ALL);
+ MMIO_D(GEN6_RP_UP_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_RP_DOWN_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_RP_CUR_UP_EI, D_ALL);
+ MMIO_D(GEN6_RP_CUR_UP, D_ALL);
+ MMIO_D(GEN6_RP_PREV_UP, D_ALL);
+ MMIO_D(GEN6_RP_CUR_DOWN_EI, D_ALL);
+ MMIO_D(GEN6_RP_CUR_DOWN, D_ALL);
+ MMIO_D(GEN6_RP_PREV_DOWN, D_ALL);
+ MMIO_D(GEN6_RP_UP_EI, D_ALL);
+ MMIO_D(GEN6_RP_DOWN_EI, D_ALL);
+ MMIO_D(GEN6_RP_IDLE_HYSTERSIS, D_ALL);
+ MMIO_D(GEN6_RC1_WAKE_RATE_LIMIT, D_ALL);
+ MMIO_D(GEN6_RC6_WAKE_RATE_LIMIT, D_ALL);
+ MMIO_D(GEN6_RC6pp_WAKE_RATE_LIMIT, D_ALL);
+ MMIO_D(GEN6_RC_EVALUATION_INTERVAL, D_ALL);
+ MMIO_D(GEN6_RC_IDLE_HYSTERSIS, D_ALL);
+ MMIO_D(GEN6_RC_SLEEP, D_ALL);
+ MMIO_D(GEN6_RC1e_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_RC6_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL);
+ MMIO_D(GEN6_PMINTRMSK, D_ALL);
+ MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+ MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+ MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+ MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+ MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+ MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+
+ MMIO_D(RSTDBYCTL, D_ALL);
+
+ MMIO_DH(GEN6_GDRST, D_ALL, NULL, gdrst_mmio_write);
+ MMIO_F(FENCE_REG_GEN6_LO(0), 0x80, 0, 0, 0, D_ALL, fence_mmio_read, fence_mmio_write);
+ MMIO_F(VGT_PVINFO_PAGE, VGT_PVINFO_SIZE, F_UNALIGN, 0, 0, D_ALL, pvinfo_mmio_read, pvinfo_mmio_write);
+ MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, vga_control_mmio_write);
+
+ MMIO_F(MCHBAR_MIRROR_BASE_SNB, 0x40000, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(TILECTL, D_ALL);
+
+ MMIO_D(GEN6_UCGCTL1, D_ALL);
+ MMIO_D(GEN6_UCGCTL2, D_ALL);
+
+ MMIO_F(0x4f000, 0x90, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_SKL);
+ MMIO_D(GEN6_PCODE_DATA, D_ALL);
+ MMIO_D(0x13812c, D_ALL);
+ MMIO_DH(GEN7_ERR_INT, D_ALL, NULL, NULL);
+ MMIO_D(HSW_EDRAM_CAP, D_ALL);
+ MMIO_D(HSW_IDICR, D_ALL);
+ MMIO_DH(GFX_FLSH_CNTL_GEN6, D_ALL, NULL, NULL);
+
+ MMIO_D(0x3c, D_ALL);
+ MMIO_D(0x860, D_ALL);
+ MMIO_D(ECOSKPD, D_ALL);
+ MMIO_D(0x121d0, D_ALL);
+ MMIO_D(GEN6_BLITTER_ECOSKPD, D_ALL);
+ MMIO_D(0x41d0, D_ALL);
+ MMIO_D(GAC_ECO_BITS, D_ALL);
+ MMIO_D(0x6200, D_ALL);
+ MMIO_D(0x6204, D_ALL);
+ MMIO_D(0x6208, D_ALL);
+ MMIO_D(0x7118, D_ALL);
+ MMIO_D(0x7180, D_ALL);
+ MMIO_D(0x7408, D_ALL);
+ MMIO_D(0x7c00, D_ALL);
+ MMIO_D(GEN6_MBCTL, D_ALL);
+ MMIO_D(0x911c, D_ALL);
+ MMIO_D(0x9120, D_ALL);
+ MMIO_DFH(GEN7_UCGCTL4, D_ALL, F_CMD_ACCESS, NULL, NULL);
+
+ MMIO_D(GAB_CTL, D_ALL);
+ MMIO_D(0x48800, D_ALL);
+ MMIO_D(0xce044, D_ALL);
+ MMIO_D(0xe6500, D_ALL);
+ MMIO_D(0xe6504, D_ALL);
+ MMIO_D(0xe6600, D_ALL);
+ MMIO_D(0xe6604, D_ALL);
+ MMIO_D(0xe6700, D_ALL);
+ MMIO_D(0xe6704, D_ALL);
+ MMIO_D(0xe6800, D_ALL);
+ MMIO_D(0xe6804, D_ALL);
+ MMIO_D(PCH_GMBUS4, D_ALL);
+ MMIO_D(PCH_GMBUS5, D_ALL);
+
+ MMIO_D(0x902c, D_ALL);
+ MMIO_D(0xec008, D_ALL);
+ MMIO_D(0xec00c, D_ALL);
+ MMIO_D(0xec008 + 0x18, D_ALL);
+ MMIO_D(0xec00c + 0x18, D_ALL);
+ MMIO_D(0xec008 + 0x18 * 2, D_ALL);
+ MMIO_D(0xec00c + 0x18 * 2, D_ALL);
+ MMIO_D(0xec008 + 0x18 * 3, D_ALL);
+ MMIO_D(0xec00c + 0x18 * 3, D_ALL);
+ MMIO_D(0xec408, D_ALL);
+ MMIO_D(0xec40c, D_ALL);
+ MMIO_D(0xec408 + 0x18, D_ALL);
+ MMIO_D(0xec40c + 0x18, D_ALL);
+ MMIO_D(0xec408 + 0x18 * 2, D_ALL);
+ MMIO_D(0xec40c + 0x18 * 2, D_ALL);
+ MMIO_D(0xec408 + 0x18 * 3, D_ALL);
+ MMIO_D(0xec40c + 0x18 * 3, D_ALL);
+ MMIO_D(0xfc810, D_ALL);
+ MMIO_D(0xfc81c, D_ALL);
+ MMIO_D(0xfc828, D_ALL);
+ MMIO_D(0xfc834, D_ALL);
+ MMIO_D(0xfcc00, D_ALL);
+ MMIO_D(0xfcc0c, D_ALL);
+ MMIO_D(0xfcc18, D_ALL);
+ MMIO_D(0xfcc24, D_ALL);
+ MMIO_D(0xfd000, D_ALL);
+ MMIO_D(0xfd00c, D_ALL);
+ MMIO_D(0xfd018, D_ALL);
+ MMIO_D(0xfd024, D_ALL);
+ MMIO_D(0xfd034, D_ALL);
+
+ MMIO_DH(FPGA_DBG, D_ALL, NULL, fpga_dbg_mmio_write);
+ MMIO_D(0x2054, D_ALL);
+ MMIO_D(0x12054, D_ALL);
+ MMIO_D(0x22054, D_ALL);
+ MMIO_D(0x1a054, D_ALL);
+
+ MMIO_D(0x44070, D_ALL);
+
+ MMIO_D(0x215c, D_HSW_PLUS);
+ MMIO_DFH(0x2178, D_ALL, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x217c, D_ALL, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x12178, D_ALL, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x1217c, D_ALL, F_CMD_ACCESS, NULL, NULL);
+
+ MMIO_F(0x2290, 8, 0, 0, 0, D_HSW_PLUS, NULL, NULL);
+ MMIO_D(OACONTROL, D_HSW);
+ MMIO_D(0x2b00, D_BDW_PLUS);
+ MMIO_D(0x2360, D_BDW_PLUS);
+ MMIO_F(0x5200, 32, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x5240, 32, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(0x5280, 16, 0, 0, 0, D_ALL, NULL, NULL);
+
+ MMIO_DFH(0x1c17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x1c178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_D(BCS_SWCTRL, D_ALL);
+
+ MMIO_F(HS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(DS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(IA_VERTICES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(IA_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(VS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(GS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(GS_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(CL_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+ MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+ MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+ MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+ MMIO_DH(0x426c, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+ MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+ MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+
+ return 0;
+}
+
+static int init_broadwell_mmio_info(struct intel_gvt *gvt)
+{
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ int ret;
+
+ MMIO_DH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_imr_handler);
+
+ MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_GT_ISR(0), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_GT_IMR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_GT_IER(1), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_GT_IIR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_GT_ISR(1), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_GT_IMR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_GT_IER(2), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_GT_IIR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_GT_ISR(2), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_GT_IMR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_GT_IER(3), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_GT_IIR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_GT_ISR(3), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_A), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_DE_PIPE_IER(PIPE_A), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_A), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_DE_PIPE_ISR(PIPE_A), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_B), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_DE_PIPE_IER(PIPE_B), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_B), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_DE_PIPE_ISR(PIPE_B), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_C), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_DE_PIPE_IER(PIPE_C), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_C), D_BDW_PLUS, NULL,
+ intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_DE_PIPE_ISR(PIPE_C), D_BDW_PLUS);
+
+ MMIO_DH(GEN8_DE_PORT_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_DE_PORT_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_DE_PORT_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_DE_PORT_ISR, D_BDW_PLUS);
+
+ MMIO_DH(GEN8_DE_MISC_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_DE_MISC_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_DE_MISC_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_DE_MISC_ISR, D_BDW_PLUS);
+
+ MMIO_DH(GEN8_PCU_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+ MMIO_DH(GEN8_PCU_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+ MMIO_DH(GEN8_PCU_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+ MMIO_D(GEN8_PCU_ISR, D_BDW_PLUS);
+
+ MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL,
+ intel_vgpu_reg_master_irq_handler);
+
+ MMIO_D(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_D(0x1c134, D_BDW_PLUS);
+
+ MMIO_D(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_D(RING_HEAD(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_GM(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);
+ MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+ MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write);
+ MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
+ NULL, NULL);
+ MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
+ NULL, NULL);
+ MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
+ ring_timestamp_mmio_read, NULL);
+
+ MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS);
+
+#define RING_REG(base) (base + 0xd0)
+ MMIO_RING_F(RING_REG, 4, F_RO, 0,
+ ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
+ ring_reset_ctl_write);
+ MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0,
+ ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
+ ring_reset_ctl_write);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x230)
+ MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write);
+ MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x234)
+ MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL);
+ MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, ~0LL, D_BDW_PLUS, NULL, NULL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x244)
+ MMIO_RING_D(RING_REG, D_BDW_PLUS);
+ MMIO_D(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x370)
+ MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL);
+ MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS,
+ NULL, NULL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x3a0)
+ MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+ MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+#undef RING_REG
+
+ MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS);
+ MMIO_D(PIPEMISC(PIPE_B), D_BDW_PLUS);
+ MMIO_D(PIPEMISC(PIPE_C), D_BDW_PLUS);
+ MMIO_D(0x1c1d0, D_BDW_PLUS);
+ MMIO_D(GEN6_MBCUNIT_SNPCR, D_BDW_PLUS);
+ MMIO_D(GEN7_MISCCPCTL, D_BDW_PLUS);
+ MMIO_D(0x1c054, D_BDW_PLUS);
+
+ MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);
+ MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
+
+ MMIO_D(GAMTARBMODE, D_BDW_PLUS);
+
+#define RING_REG(base) (base + 0x270)
+ MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
+ MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
+#undef RING_REG
+
+ MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL);
+ MMIO_GM(0x1c080, D_BDW_PLUS, NULL, NULL);
+
+ MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+
+ MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW);
+ MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW);
+ MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW);
+
+ MMIO_D(WM_MISC, D_BDW);
+ MMIO_D(BDW_EDP_PSR_BASE, D_BDW);
+
+ MMIO_D(0x66c00, D_BDW_PLUS);
+ MMIO_D(0x66c04, D_BDW_PLUS);
+
+ MMIO_D(HSW_GTT_CACHE_EN, D_BDW_PLUS);
+
+ MMIO_D(GEN8_EU_DISABLE0, D_BDW_PLUS);
+ MMIO_D(GEN8_EU_DISABLE1, D_BDW_PLUS);
+ MMIO_D(GEN8_EU_DISABLE2, D_BDW_PLUS);
+
+ MMIO_D(0xfdc, D_BDW);
+ MMIO_DFH(GEN8_ROW_CHICKEN, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_D(GEN7_ROW_CHICKEN2, D_BDW_PLUS);
+ MMIO_D(GEN8_UCGCTL6, D_BDW_PLUS);
+
+ MMIO_D(0xb1f0, D_BDW);
+ MMIO_D(0xb1c0, D_BDW);
+ MMIO_DFH(GEN8_L3SQCREG4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_D(0xb100, D_BDW);
+ MMIO_D(0xb10c, D_BDW);
+ MMIO_D(0xb110, D_BDW);
+
+ MMIO_DFH(0x24d0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x24d4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x24d8, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x24dc, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+
+ MMIO_D(0x83a4, D_BDW);
+ MMIO_D(GEN8_L3_LRA_1_GPGPU, D_BDW_PLUS);
+
+ MMIO_D(0x8430, D_BDW);
+
+ MMIO_D(0x110000, D_BDW_PLUS);
+
+ MMIO_D(0x48400, D_BDW_PLUS);
+
+ MMIO_D(0x6e570, D_BDW_PLUS);
+ MMIO_D(0x65f10, D_BDW_PLUS);
+
+ MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+
+ MMIO_D(0x2248, D_BDW);
+
+ return 0;
+}
+
+static int init_skl_mmio_info(struct intel_gvt *gvt)
+{
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ int ret;
+
+ MMIO_DH(FORCEWAKE_RENDER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+ MMIO_DH(FORCEWAKE_ACK_RENDER_GEN9, D_SKL_PLUS, NULL, NULL);
+ MMIO_DH(FORCEWAKE_BLITTER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+ MMIO_DH(FORCEWAKE_ACK_BLITTER_GEN9, D_SKL_PLUS, NULL, NULL);
+ MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+ MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL);
+
+ MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+ MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+ MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+
+ MMIO_D(HSW_PWR_WELL_BIOS, D_SKL);
+ MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write);
+
+ MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, mailbox_write);
+ MMIO_D(0xa210, D_SKL_PLUS);
+ MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
+ MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
+ MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write);
+ MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write);
+ MMIO_D(0x45504, D_SKL);
+ MMIO_D(0x45520, D_SKL);
+ MMIO_D(0x46000, D_SKL);
+ MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write);
+ MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write);
+ MMIO_D(0x6C040, D_SKL);
+ MMIO_D(0x6C048, D_SKL);
+ MMIO_D(0x6C050, D_SKL);
+ MMIO_D(0x6C044, D_SKL);
+ MMIO_D(0x6C04C, D_SKL);
+ MMIO_D(0x6C054, D_SKL);
+ MMIO_D(0x6c058, D_SKL);
+ MMIO_D(0x6c05c, D_SKL);
+ MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL);
+
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+ MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write);
+ MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+ MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL);
+ MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL);
+ MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL);
+
+ MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+ MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+ MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+ MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL);
+
+ MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL);
+ MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL);
+ MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
+ MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL);
+
+ MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL);
+ MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL);
+
+ MMIO_D(0x70380, D_SKL);
+ MMIO_D(0x71380, D_SKL);
+ MMIO_D(0x72380, D_SKL);
+ MMIO_D(0x7039c, D_SKL);
+
+ MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL);
+ MMIO_D(0x8f074, D_SKL);
+ MMIO_D(0x8f004, D_SKL);
+ MMIO_D(0x8f034, D_SKL);
+
+ MMIO_D(0xb11c, D_SKL);
+
+ MMIO_D(0x51000, D_SKL);
+ MMIO_D(0x6c00c, D_SKL);
+
+ MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
+ MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
+
+ MMIO_D(0xd08, D_SKL);
+ MMIO_D(0x20e0, D_SKL);
+ MMIO_D(0x20ec, D_SKL);
+
+ /* TRTT */
+ MMIO_D(0x4de0, D_SKL);
+ MMIO_D(0x4de4, D_SKL);
+ MMIO_D(0x4de8, D_SKL);
+ MMIO_D(0x4dec, D_SKL);
+ MMIO_D(0x4df0, D_SKL);
+ MMIO_DH(0x4df4, D_SKL, NULL, gen9_trtte_write);
+ MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write);
+
+ MMIO_D(0x45008, D_SKL);
+
+ MMIO_D(0x46430, D_SKL);
+
+ MMIO_D(0x46520, D_SKL);
+
+ MMIO_D(0xc403c, D_SKL);
+ MMIO_D(0xb004, D_SKL);
+ MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write);
+
+ MMIO_D(0x65900, D_SKL);
+ MMIO_D(0x1082c0, D_SKL);
+ MMIO_D(0x4068, D_SKL);
+ MMIO_D(0x67054, D_SKL);
+ MMIO_D(0x6e560, D_SKL);
+ MMIO_D(0x6e554, D_SKL);
+ MMIO_D(0x2b20, D_SKL);
+ MMIO_D(0x65f00, D_SKL);
+ MMIO_D(0x65f08, D_SKL);
+ MMIO_D(0x320f0, D_SKL);
+
+ MMIO_D(_REG_VCS2_EXCC, D_SKL);
+ MMIO_D(0x70034, D_SKL);
+ MMIO_D(0x71034, D_SKL);
+ MMIO_D(0x72034, D_SKL);
+
+ MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL);
+ MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL);
+ MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL);
+ MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL);
+ MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL);
+ MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL);
+
+ MMIO_D(0x44500, D_SKL);
+ return 0;
+}
+
+/**
+ * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset
+ * @gvt: GVT device
+ * @offset: register offset
+ *
+ * This function is used to find the MMIO information entry from hash table
+ *
+ * Returns:
+ * pointer to MMIO information entry, NULL if not exists
+ */
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
+ unsigned int offset)
+{
+ struct intel_gvt_mmio_info *e;
+
+ WARN_ON(!IS_ALIGNED(offset, 4));
+
+ hash_for_each_possible(gvt->mmio.mmio_info_table, e, node, offset) {
+ if (e->offset == offset)
+ return e;
+ }
+ return NULL;
+}
+
+/**
+ * intel_gvt_clean_mmio_info - clean up MMIO information table for GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the driver unloading stage, to clean up the MMIO
+ * information table of GVT device
+ *
+ */
+void intel_gvt_clean_mmio_info(struct intel_gvt *gvt)
+{
+ struct hlist_node *tmp;
+ struct intel_gvt_mmio_info *e;
+ int i;
+
+ hash_for_each_safe(gvt->mmio.mmio_info_table, i, tmp, e, node)
+ kfree(e);
+
+ vfree(gvt->mmio.mmio_attribute);
+ gvt->mmio.mmio_attribute = NULL;
+}
+
+/**
+ * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the initialization stage, to setup the MMIO
+ * information table for GVT device
+ *
+ * Returns:
+ * zero on success, negative if failed.
+ */
+int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
+{
+ struct intel_gvt_device_info *info = &gvt->device_info;
+ struct drm_i915_private *dev_priv = gvt->dev_priv;
+ int ret;
+
+ gvt->mmio.mmio_attribute = vzalloc(info->mmio_size);
+ if (!gvt->mmio.mmio_attribute)
+ return -ENOMEM;
+
+ ret = init_generic_mmio_info(gvt);
+ if (ret)
+ goto err;
+
+ if (IS_BROADWELL(dev_priv)) {
+ ret = init_broadwell_mmio_info(gvt);
+ if (ret)
+ goto err;
+ } else if (IS_SKYLAKE(dev_priv)) {
+ ret = init_broadwell_mmio_info(gvt);
+ if (ret)
+ goto err;
+ ret = init_skl_mmio_info(gvt);
+ if (ret)
+ goto err;
+ }
+ return 0;
+err:
+ intel_gvt_clean_mmio_info(gvt);
+ return ret;
+}
+
+/**
+ * intel_gvt_mmio_set_accessed - mark a MMIO has been accessed
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset)
+{
+ gvt->mmio.mmio_attribute[offset >> 2] |=
+ F_ACCESSED;
+}
+
+/**
+ * intel_gvt_mmio_is_cmd_accessed - mark a MMIO could be accessed by command
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt,
+ unsigned int offset)
+{
+ return gvt->mmio.mmio_attribute[offset >> 2] &
+ F_CMD_ACCESS;
+}
+
+/**
+ * intel_gvt_mmio_is_unalign - mark a MMIO could be accessed unaligned
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt,
+ unsigned int offset)
+{
+ return gvt->mmio.mmio_attribute[offset >> 2] &
+ F_UNALIGN;
+}
+
+/**
+ * intel_gvt_mmio_set_cmd_accessed - mark a MMIO has been accessed by command
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt,
+ unsigned int offset)
+{
+ gvt->mmio.mmio_attribute[offset >> 2] |=
+ F_CMD_ACCESSED;
+}
+
+/**
+ * intel_gvt_mmio_has_mode_mask - if a MMIO has a mode mask
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ * Returns:
+ * True if a MMIO has a mode mask in its higher 16 bits, false if it isn't.
+ *
+ */
+bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset)
+{
+ return gvt->mmio.mmio_attribute[offset >> 2] &
+ F_MODE_MASK;
+}
+
+/**
+ * intel_vgpu_default_mmio_read - default MMIO read handler
+ * @vgpu: a vGPU
+ * @offset: access offset
+ * @p_data: data return buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ read_vreg(vgpu, offset, p_data, bytes);
+ return 0;
+}
+
+/**
+ * intel_t_default_mmio_write - default MMIO write handler
+ * @vgpu: a vGPU
+ * @offset: access offset
+ * @p_data: write data buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes)
+{
+ write_vreg(vgpu, offset, p_data, bytes);
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h
index 254df8bf1f35..30e543f5a703 100644
--- a/drivers/gpu/drm/i915/gvt/hypercall.h
+++ b/drivers/gpu/drm/i915/gvt/hypercall.h
@@ -19,6 +19,15 @@
* 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Dexuan Cui
+ * Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
*/
#ifndef _GVT_HYPERCALL_H_
@@ -30,6 +39,23 @@
*/
struct intel_gvt_mpt {
int (*detect_host)(void);
+ int (*host_init)(struct device *dev, void *gvt, const void *ops);
+ void (*host_exit)(struct device *dev, void *gvt);
+ int (*attach_vgpu)(void *vgpu, unsigned long *handle);
+ void (*detach_vgpu)(unsigned long handle);
+ int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
+ unsigned long (*from_virt_to_mfn)(void *p);
+ int (*set_wp_page)(unsigned long handle, u64 gfn);
+ int (*unset_wp_page)(unsigned long handle, u64 gfn);
+ int (*read_gpa)(unsigned long handle, unsigned long gpa, void *buf,
+ unsigned long len);
+ int (*write_gpa)(unsigned long handle, unsigned long gpa, void *buf,
+ unsigned long len);
+ unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn);
+ int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
+ unsigned long mfn, unsigned int nr, bool map);
+ int (*set_trap_area)(unsigned long handle, u64 start, u64 end,
+ bool map);
};
extern struct intel_gvt_mpt xengt_mpt;
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
new file mode 100644
index 000000000000..f7be02ac4be1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/interrupt.c
@@ -0,0 +1,741 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Min he <min.he@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+/* common offset among interrupt control registers */
+#define regbase_to_isr(base) (base)
+#define regbase_to_imr(base) (base + 0x4)
+#define regbase_to_iir(base) (base + 0x8)
+#define regbase_to_ier(base) (base + 0xC)
+
+#define iir_to_regbase(iir) (iir - 0x8)
+#define ier_to_regbase(ier) (ier - 0xC)
+
+#define get_event_virt_handler(irq, e) (irq->events[e].v_handler)
+#define get_irq_info(irq, e) (irq->events[e].info)
+
+#define irq_to_gvt(irq) \
+ container_of(irq, struct intel_gvt, irq)
+
+static void update_upstream_irq(struct intel_vgpu *vgpu,
+ struct intel_gvt_irq_info *info);
+
+static const char * const irq_name[INTEL_GVT_EVENT_MAX] = {
+ [RCS_MI_USER_INTERRUPT] = "Render CS MI USER INTERRUPT",
+ [RCS_DEBUG] = "Render EU debug from SVG",
+ [RCS_MMIO_SYNC_FLUSH] = "Render MMIO sync flush status",
+ [RCS_CMD_STREAMER_ERR] = "Render CS error interrupt",
+ [RCS_PIPE_CONTROL] = "Render PIPE CONTROL notify",
+ [RCS_WATCHDOG_EXCEEDED] = "Render CS Watchdog counter exceeded",
+ [RCS_PAGE_DIRECTORY_FAULT] = "Render page directory faults",
+ [RCS_AS_CONTEXT_SWITCH] = "Render AS Context Switch Interrupt",
+
+ [VCS_MI_USER_INTERRUPT] = "Video CS MI USER INTERRUPT",
+ [VCS_MMIO_SYNC_FLUSH] = "Video MMIO sync flush status",
+ [VCS_CMD_STREAMER_ERR] = "Video CS error interrupt",
+ [VCS_MI_FLUSH_DW] = "Video MI FLUSH DW notify",
+ [VCS_WATCHDOG_EXCEEDED] = "Video CS Watchdog counter exceeded",
+ [VCS_PAGE_DIRECTORY_FAULT] = "Video page directory faults",
+ [VCS_AS_CONTEXT_SWITCH] = "Video AS Context Switch Interrupt",
+ [VCS2_MI_USER_INTERRUPT] = "VCS2 Video CS MI USER INTERRUPT",
+ [VCS2_MI_FLUSH_DW] = "VCS2 Video MI FLUSH DW notify",
+ [VCS2_AS_CONTEXT_SWITCH] = "VCS2 Context Switch Interrupt",
+
+ [BCS_MI_USER_INTERRUPT] = "Blitter CS MI USER INTERRUPT",
+ [BCS_MMIO_SYNC_FLUSH] = "Billter MMIO sync flush status",
+ [BCS_CMD_STREAMER_ERR] = "Blitter CS error interrupt",
+ [BCS_MI_FLUSH_DW] = "Blitter MI FLUSH DW notify",
+ [BCS_PAGE_DIRECTORY_FAULT] = "Blitter page directory faults",
+ [BCS_AS_CONTEXT_SWITCH] = "Blitter AS Context Switch Interrupt",
+
+ [VECS_MI_FLUSH_DW] = "Video Enhanced Streamer MI FLUSH DW notify",
+ [VECS_AS_CONTEXT_SWITCH] = "VECS Context Switch Interrupt",
+
+ [PIPE_A_FIFO_UNDERRUN] = "Pipe A FIFO underrun",
+ [PIPE_A_CRC_ERR] = "Pipe A CRC error",
+ [PIPE_A_CRC_DONE] = "Pipe A CRC done",
+ [PIPE_A_VSYNC] = "Pipe A vsync",
+ [PIPE_A_LINE_COMPARE] = "Pipe A line compare",
+ [PIPE_A_ODD_FIELD] = "Pipe A odd field",
+ [PIPE_A_EVEN_FIELD] = "Pipe A even field",
+ [PIPE_A_VBLANK] = "Pipe A vblank",
+ [PIPE_B_FIFO_UNDERRUN] = "Pipe B FIFO underrun",
+ [PIPE_B_CRC_ERR] = "Pipe B CRC error",
+ [PIPE_B_CRC_DONE] = "Pipe B CRC done",
+ [PIPE_B_VSYNC] = "Pipe B vsync",
+ [PIPE_B_LINE_COMPARE] = "Pipe B line compare",
+ [PIPE_B_ODD_FIELD] = "Pipe B odd field",
+ [PIPE_B_EVEN_FIELD] = "Pipe B even field",
+ [PIPE_B_VBLANK] = "Pipe B vblank",
+ [PIPE_C_VBLANK] = "Pipe C vblank",
+ [DPST_PHASE_IN] = "DPST phase in event",
+ [DPST_HISTOGRAM] = "DPST histogram event",
+ [GSE] = "GSE",
+ [DP_A_HOTPLUG] = "DP A Hotplug",
+ [AUX_CHANNEL_A] = "AUX Channel A",
+ [PERF_COUNTER] = "Performance counter",
+ [POISON] = "Poison",
+ [GTT_FAULT] = "GTT fault",
+ [PRIMARY_A_FLIP_DONE] = "Primary Plane A flip done",
+ [PRIMARY_B_FLIP_DONE] = "Primary Plane B flip done",
+ [PRIMARY_C_FLIP_DONE] = "Primary Plane C flip done",
+ [SPRITE_A_FLIP_DONE] = "Sprite Plane A flip done",
+ [SPRITE_B_FLIP_DONE] = "Sprite Plane B flip done",
+ [SPRITE_C_FLIP_DONE] = "Sprite Plane C flip done",
+
+ [PCU_THERMAL] = "PCU Thermal Event",
+ [PCU_PCODE2DRIVER_MAILBOX] = "PCU pcode2driver mailbox event",
+
+ [FDI_RX_INTERRUPTS_TRANSCODER_A] = "FDI RX Interrupts Combined A",
+ [AUDIO_CP_CHANGE_TRANSCODER_A] = "Audio CP Change Transcoder A",
+ [AUDIO_CP_REQUEST_TRANSCODER_A] = "Audio CP Request Transcoder A",
+ [FDI_RX_INTERRUPTS_TRANSCODER_B] = "FDI RX Interrupts Combined B",
+ [AUDIO_CP_CHANGE_TRANSCODER_B] = "Audio CP Change Transcoder B",
+ [AUDIO_CP_REQUEST_TRANSCODER_B] = "Audio CP Request Transcoder B",
+ [FDI_RX_INTERRUPTS_TRANSCODER_C] = "FDI RX Interrupts Combined C",
+ [AUDIO_CP_CHANGE_TRANSCODER_C] = "Audio CP Change Transcoder C",
+ [AUDIO_CP_REQUEST_TRANSCODER_C] = "Audio CP Request Transcoder C",
+ [ERR_AND_DBG] = "South Error and Debug Interupts Combined",
+ [GMBUS] = "Gmbus",
+ [SDVO_B_HOTPLUG] = "SDVO B hotplug",
+ [CRT_HOTPLUG] = "CRT Hotplug",
+ [DP_B_HOTPLUG] = "DisplayPort/HDMI/DVI B Hotplug",
+ [DP_C_HOTPLUG] = "DisplayPort/HDMI/DVI C Hotplug",
+ [DP_D_HOTPLUG] = "DisplayPort/HDMI/DVI D Hotplug",
+ [AUX_CHANNEL_B] = "AUX Channel B",
+ [AUX_CHANNEL_C] = "AUX Channel C",
+ [AUX_CHANNEL_D] = "AUX Channel D",
+ [AUDIO_POWER_STATE_CHANGE_B] = "Audio Power State change Port B",
+ [AUDIO_POWER_STATE_CHANGE_C] = "Audio Power State change Port C",
+ [AUDIO_POWER_STATE_CHANGE_D] = "Audio Power State change Port D",
+
+ [INTEL_GVT_EVENT_RESERVED] = "RESERVED EVENTS!!!",
+};
+
+static inline struct intel_gvt_irq_info *regbase_to_irq_info(
+ struct intel_gvt *gvt,
+ unsigned int reg)
+{
+ struct intel_gvt_irq *irq = &gvt->irq;
+ int i;
+
+ for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) {
+ if (i915_mmio_reg_offset(irq->info[i]->reg_base) == reg)
+ return irq->info[i];
+ }
+
+ return NULL;
+}
+
+/**
+ * intel_vgpu_reg_imr_handler - Generic IMR register emulation write handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IMR register bit change
+ * behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+ u32 changed, masked, unmasked;
+ u32 imr = *(u32 *)p_data;
+
+ gvt_dbg_irq("write IMR %x with val %x\n",
+ reg, imr);
+
+ gvt_dbg_irq("old vIMR %x\n", vgpu_vreg(vgpu, reg));
+
+ /* figure out newly masked/unmasked bits */
+ changed = vgpu_vreg(vgpu, reg) ^ imr;
+ masked = (vgpu_vreg(vgpu, reg) & changed) ^ changed;
+ unmasked = masked ^ changed;
+
+ gvt_dbg_irq("changed %x, masked %x, unmasked %x\n",
+ changed, masked, unmasked);
+
+ vgpu_vreg(vgpu, reg) = imr;
+
+ ops->check_pending_irq(vgpu);
+ gvt_dbg_irq("IRQ: new vIMR %x\n", vgpu_vreg(vgpu, reg));
+ return 0;
+}
+
+/**
+ * intel_vgpu_reg_master_irq_handler - master IRQ write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the master IRQ register on gen8+.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+ u32 changed, enabled, disabled;
+ u32 ier = *(u32 *)p_data;
+ u32 virtual_ier = vgpu_vreg(vgpu, reg);
+
+ gvt_dbg_irq("write master irq reg %x with val %x\n",
+ reg, ier);
+
+ gvt_dbg_irq("old vreg %x\n", vgpu_vreg(vgpu, reg));
+
+ /*
+ * GEN8_MASTER_IRQ is a special irq register,
+ * only bit 31 is allowed to be modified
+ * and treated as an IER bit.
+ */
+ ier &= GEN8_MASTER_IRQ_CONTROL;
+ virtual_ier &= GEN8_MASTER_IRQ_CONTROL;
+ vgpu_vreg(vgpu, reg) &= ~GEN8_MASTER_IRQ_CONTROL;
+ vgpu_vreg(vgpu, reg) |= ier;
+
+ /* figure out newly enabled/disable bits */
+ changed = virtual_ier ^ ier;
+ enabled = (virtual_ier & changed) ^ changed;
+ disabled = enabled ^ changed;
+
+ gvt_dbg_irq("changed %x, enabled %x, disabled %x\n",
+ changed, enabled, disabled);
+
+ ops->check_pending_irq(vgpu);
+ gvt_dbg_irq("new vreg %x\n", vgpu_vreg(vgpu, reg));
+ return 0;
+}
+
+/**
+ * intel_vgpu_reg_ier_handler - Generic IER write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IER register behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+ struct intel_gvt_irq_info *info;
+ u32 changed, enabled, disabled;
+ u32 ier = *(u32 *)p_data;
+
+ gvt_dbg_irq("write IER %x with val %x\n",
+ reg, ier);
+
+ gvt_dbg_irq("old vIER %x\n", vgpu_vreg(vgpu, reg));
+
+ /* figure out newly enabled/disable bits */
+ changed = vgpu_vreg(vgpu, reg) ^ ier;
+ enabled = (vgpu_vreg(vgpu, reg) & changed) ^ changed;
+ disabled = enabled ^ changed;
+
+ gvt_dbg_irq("changed %x, enabled %x, disabled %x\n",
+ changed, enabled, disabled);
+ vgpu_vreg(vgpu, reg) = ier;
+
+ info = regbase_to_irq_info(gvt, ier_to_regbase(reg));
+ if (WARN_ON(!info))
+ return -EINVAL;
+
+ if (info->has_upstream_irq)
+ update_upstream_irq(vgpu, info);
+
+ ops->check_pending_irq(vgpu);
+ gvt_dbg_irq("new vIER %x\n", vgpu_vreg(vgpu, reg));
+ return 0;
+}
+
+/**
+ * intel_vgpu_reg_iir_handler - Generic IIR write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IIR register behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg,
+ void *p_data, unsigned int bytes)
+{
+ struct intel_gvt_irq_info *info = regbase_to_irq_info(vgpu->gvt,
+ iir_to_regbase(reg));
+ u32 iir = *(u32 *)p_data;
+
+ gvt_dbg_irq("write IIR %x with val %x\n", reg, iir);
+
+ if (WARN_ON(!info))
+ return -EINVAL;
+
+ vgpu_vreg(vgpu, reg) &= ~iir;
+
+ if (info->has_upstream_irq)
+ update_upstream_irq(vgpu, info);
+ return 0;
+}
+
+static struct intel_gvt_irq_map gen8_irq_map[] = {
+ { INTEL_GVT_IRQ_INFO_MASTER, 0, INTEL_GVT_IRQ_INFO_GT0, 0xffff },
+ { INTEL_GVT_IRQ_INFO_MASTER, 1, INTEL_GVT_IRQ_INFO_GT0, 0xffff0000 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 2, INTEL_GVT_IRQ_INFO_GT1, 0xffff },
+ { INTEL_GVT_IRQ_INFO_MASTER, 3, INTEL_GVT_IRQ_INFO_GT1, 0xffff0000 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 4, INTEL_GVT_IRQ_INFO_GT2, 0xffff },
+ { INTEL_GVT_IRQ_INFO_MASTER, 6, INTEL_GVT_IRQ_INFO_GT3, 0xffff },
+ { INTEL_GVT_IRQ_INFO_MASTER, 16, INTEL_GVT_IRQ_INFO_DE_PIPE_A, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 17, INTEL_GVT_IRQ_INFO_DE_PIPE_B, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 18, INTEL_GVT_IRQ_INFO_DE_PIPE_C, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 20, INTEL_GVT_IRQ_INFO_DE_PORT, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 22, INTEL_GVT_IRQ_INFO_DE_MISC, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 23, INTEL_GVT_IRQ_INFO_PCH, ~0 },
+ { INTEL_GVT_IRQ_INFO_MASTER, 30, INTEL_GVT_IRQ_INFO_PCU, ~0 },
+ { -1, -1, ~0 },
+};
+
+static void update_upstream_irq(struct intel_vgpu *vgpu,
+ struct intel_gvt_irq_info *info)
+{
+ struct intel_gvt_irq *irq = &vgpu->gvt->irq;
+ struct intel_gvt_irq_map *map = irq->irq_map;
+ struct intel_gvt_irq_info *up_irq_info = NULL;
+ u32 set_bits = 0;
+ u32 clear_bits = 0;
+ int bit;
+ u32 val = vgpu_vreg(vgpu,
+ regbase_to_iir(i915_mmio_reg_offset(info->reg_base)))
+ & vgpu_vreg(vgpu,
+ regbase_to_ier(i915_mmio_reg_offset(info->reg_base)));
+
+ if (!info->has_upstream_irq)
+ return;
+
+ for (map = irq->irq_map; map->up_irq_bit != -1; map++) {
+ if (info->group != map->down_irq_group)
+ continue;
+
+ if (!up_irq_info)
+ up_irq_info = irq->info[map->up_irq_group];
+ else
+ WARN_ON(up_irq_info != irq->info[map->up_irq_group]);
+
+ bit = map->up_irq_bit;
+
+ if (val & map->down_irq_bitmask)
+ set_bits |= (1 << bit);
+ else
+ clear_bits |= (1 << bit);
+ }
+
+ WARN_ON(!up_irq_info);
+
+ if (up_irq_info->group == INTEL_GVT_IRQ_INFO_MASTER) {
+ u32 isr = i915_mmio_reg_offset(up_irq_info->reg_base);
+
+ vgpu_vreg(vgpu, isr) &= ~clear_bits;
+ vgpu_vreg(vgpu, isr) |= set_bits;
+ } else {
+ u32 iir = regbase_to_iir(
+ i915_mmio_reg_offset(up_irq_info->reg_base));
+ u32 imr = regbase_to_imr(
+ i915_mmio_reg_offset(up_irq_info->reg_base));
+
+ vgpu_vreg(vgpu, iir) |= (set_bits & ~vgpu_vreg(vgpu, imr));
+ }
+
+ if (up_irq_info->has_upstream_irq)
+ update_upstream_irq(vgpu, up_irq_info);
+}
+
+static void init_irq_map(struct intel_gvt_irq *irq)
+{
+ struct intel_gvt_irq_map *map;
+ struct intel_gvt_irq_info *up_info, *down_info;
+ int up_bit;
+
+ for (map = irq->irq_map; map->up_irq_bit != -1; map++) {
+ up_info = irq->info[map->up_irq_group];
+ up_bit = map->up_irq_bit;
+ down_info = irq->info[map->down_irq_group];
+
+ set_bit(up_bit, up_info->downstream_irq_bitmap);
+ down_info->has_upstream_irq = true;
+
+ gvt_dbg_irq("[up] grp %d bit %d -> [down] grp %d bitmask %x\n",
+ up_info->group, up_bit,
+ down_info->group, map->down_irq_bitmask);
+ }
+}
+
+/* =======================vEvent injection===================== */
+static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
+{
+ return intel_gvt_hypervisor_inject_msi(vgpu);
+}
+
+static void propagate_event(struct intel_gvt_irq *irq,
+ enum intel_gvt_event_type event, struct intel_vgpu *vgpu)
+{
+ struct intel_gvt_irq_info *info;
+ unsigned int reg_base;
+ int bit;
+
+ info = get_irq_info(irq, event);
+ if (WARN_ON(!info))
+ return;
+
+ reg_base = i915_mmio_reg_offset(info->reg_base);
+ bit = irq->events[event].bit;
+
+ if (!test_bit(bit, (void *)&vgpu_vreg(vgpu,
+ regbase_to_imr(reg_base)))) {
+ gvt_dbg_irq("set bit (%d) for (%s) for vgpu (%d)\n",
+ bit, irq_name[event], vgpu->id);
+ set_bit(bit, (void *)&vgpu_vreg(vgpu,
+ regbase_to_iir(reg_base)));
+ }
+}
+
+/* =======================vEvent Handlers===================== */
+static void handle_default_event_virt(struct intel_gvt_irq *irq,
+ enum intel_gvt_event_type event, struct intel_vgpu *vgpu)
+{
+ if (!vgpu->irq.irq_warn_once[event]) {
+ gvt_dbg_core("vgpu%d: IRQ receive event %d (%s)\n",
+ vgpu->id, event, irq_name[event]);
+ vgpu->irq.irq_warn_once[event] = true;
+ }
+ propagate_event(irq, event, vgpu);
+}
+
+/* =====================GEN specific logic======================= */
+/* GEN8 interrupt routines. */
+
+#define DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(regname, regbase) \
+static struct intel_gvt_irq_info gen8_##regname##_info = { \
+ .name = #regname"-IRQ", \
+ .reg_base = (regbase), \
+ .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = \
+ INTEL_GVT_EVENT_RESERVED}, \
+}
+
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt0, GEN8_GT_ISR(0));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt1, GEN8_GT_ISR(1));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt2, GEN8_GT_ISR(2));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt3, GEN8_GT_ISR(3));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_a, GEN8_DE_PIPE_ISR(PIPE_A));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_b, GEN8_DE_PIPE_ISR(PIPE_B));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_c, GEN8_DE_PIPE_ISR(PIPE_C));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_port, GEN8_DE_PORT_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_misc, GEN8_DE_MISC_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(pcu, GEN8_PCU_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(master, GEN8_MASTER_IRQ);
+
+static struct intel_gvt_irq_info gvt_base_pch_info = {
+ .name = "PCH-IRQ",
+ .reg_base = SDEISR,
+ .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] =
+ INTEL_GVT_EVENT_RESERVED},
+};
+
+static void gen8_check_pending_irq(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt_irq *irq = &vgpu->gvt->irq;
+ int i;
+
+ if (!(vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) &
+ GEN8_MASTER_IRQ_CONTROL))
+ return;
+
+ for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) {
+ struct intel_gvt_irq_info *info = irq->info[i];
+ u32 reg_base;
+
+ if (!info->has_upstream_irq)
+ continue;
+
+ reg_base = i915_mmio_reg_offset(info->reg_base);
+ if ((vgpu_vreg(vgpu, regbase_to_iir(reg_base))
+ & vgpu_vreg(vgpu, regbase_to_ier(reg_base))))
+ update_upstream_irq(vgpu, info);
+ }
+
+ if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ))
+ & ~GEN8_MASTER_IRQ_CONTROL)
+ inject_virtual_interrupt(vgpu);
+}
+
+static void gen8_init_irq(
+ struct intel_gvt_irq *irq)
+{
+ struct intel_gvt *gvt = irq_to_gvt(irq);
+
+#define SET_BIT_INFO(s, b, e, i) \
+ do { \
+ s->events[e].bit = b; \
+ s->events[e].info = s->info[i]; \
+ s->info[i]->bit_to_event[b] = e;\
+ } while (0)
+
+#define SET_IRQ_GROUP(s, g, i) \
+ do { \
+ s->info[g] = i; \
+ (i)->group = g; \
+ set_bit(g, s->irq_info_bitmap); \
+ } while (0)
+
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_MASTER, &gen8_master_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT0, &gen8_gt0_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT1, &gen8_gt1_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT2, &gen8_gt2_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT3, &gen8_gt3_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_A, &gen8_de_pipe_a_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_B, &gen8_de_pipe_b_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_C, &gen8_de_pipe_c_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PORT, &gen8_de_port_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_MISC, &gen8_de_misc_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCU, &gen8_pcu_info);
+ SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCH, &gvt_base_pch_info);
+
+ /* GEN8 level 2 interrupts. */
+
+ /* GEN8 interrupt GT0 events */
+ SET_BIT_INFO(irq, 0, RCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0);
+ SET_BIT_INFO(irq, 4, RCS_PIPE_CONTROL, INTEL_GVT_IRQ_INFO_GT0);
+ SET_BIT_INFO(irq, 8, RCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0);
+
+ SET_BIT_INFO(irq, 16, BCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0);
+ SET_BIT_INFO(irq, 20, BCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT0);
+ SET_BIT_INFO(irq, 24, BCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0);
+
+ /* GEN8 interrupt GT1 events */
+ SET_BIT_INFO(irq, 0, VCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT1);
+ SET_BIT_INFO(irq, 4, VCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT1);
+ SET_BIT_INFO(irq, 8, VCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT1);
+
+ if (HAS_BSD2(gvt->dev_priv)) {
+ SET_BIT_INFO(irq, 16, VCS2_MI_USER_INTERRUPT,
+ INTEL_GVT_IRQ_INFO_GT1);
+ SET_BIT_INFO(irq, 20, VCS2_MI_FLUSH_DW,
+ INTEL_GVT_IRQ_INFO_GT1);
+ SET_BIT_INFO(irq, 24, VCS2_AS_CONTEXT_SWITCH,
+ INTEL_GVT_IRQ_INFO_GT1);
+ }
+
+ /* GEN8 interrupt GT3 events */
+ SET_BIT_INFO(irq, 0, VECS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT3);
+ SET_BIT_INFO(irq, 4, VECS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT3);
+ SET_BIT_INFO(irq, 8, VECS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT3);
+
+ SET_BIT_INFO(irq, 0, PIPE_A_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+ SET_BIT_INFO(irq, 0, PIPE_B_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+ SET_BIT_INFO(irq, 0, PIPE_C_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+
+ /* GEN8 interrupt DE PORT events */
+ SET_BIT_INFO(irq, 0, AUX_CHANNEL_A, INTEL_GVT_IRQ_INFO_DE_PORT);
+ SET_BIT_INFO(irq, 3, DP_A_HOTPLUG, INTEL_GVT_IRQ_INFO_DE_PORT);
+
+ /* GEN8 interrupt DE MISC events */
+ SET_BIT_INFO(irq, 0, GSE, INTEL_GVT_IRQ_INFO_DE_MISC);
+
+ /* PCH events */
+ SET_BIT_INFO(irq, 17, GMBUS, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 19, CRT_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 21, DP_B_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 22, DP_C_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 23, DP_D_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+
+ if (IS_BROADWELL(gvt->dev_priv)) {
+ SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_PCH);
+ SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_PCH);
+
+ SET_BIT_INFO(irq, 4, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+ SET_BIT_INFO(irq, 5, SPRITE_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+
+ SET_BIT_INFO(irq, 4, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+ SET_BIT_INFO(irq, 5, SPRITE_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+
+ SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+ SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+ } else if (IS_SKYLAKE(gvt->dev_priv)) {
+ SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT);
+ SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT);
+ SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT);
+
+ SET_BIT_INFO(irq, 3, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+ SET_BIT_INFO(irq, 3, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+ SET_BIT_INFO(irq, 3, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+ }
+
+ /* GEN8 interrupt PCU events */
+ SET_BIT_INFO(irq, 24, PCU_THERMAL, INTEL_GVT_IRQ_INFO_PCU);
+ SET_BIT_INFO(irq, 25, PCU_PCODE2DRIVER_MAILBOX, INTEL_GVT_IRQ_INFO_PCU);
+}
+
+static struct intel_gvt_irq_ops gen8_irq_ops = {
+ .init_irq = gen8_init_irq,
+ .check_pending_irq = gen8_check_pending_irq,
+};
+
+/**
+ * intel_vgpu_trigger_virtual_event - Trigger a virtual event for a vGPU
+ * @vgpu: a vGPU
+ * @event: interrupt event
+ *
+ * This function is used to trigger a virtual interrupt event for vGPU.
+ * The caller provides the event to be triggered, the framework itself
+ * will emulate the IRQ register bit change.
+ *
+ */
+void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
+ enum intel_gvt_event_type event)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_irq *irq = &gvt->irq;
+ gvt_event_virt_handler_t handler;
+ struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+
+ handler = get_event_virt_handler(irq, event);
+ WARN_ON(!handler);
+
+ handler(irq, event, vgpu);
+
+ ops->check_pending_irq(vgpu);
+}
+
+static void init_events(
+ struct intel_gvt_irq *irq)
+{
+ int i;
+
+ for (i = 0; i < INTEL_GVT_EVENT_MAX; i++) {
+ irq->events[i].info = NULL;
+ irq->events[i].v_handler = handle_default_event_virt;
+ }
+}
+
+static enum hrtimer_restart vblank_timer_fn(struct hrtimer *data)
+{
+ struct intel_gvt_vblank_timer *vblank_timer;
+ struct intel_gvt_irq *irq;
+ struct intel_gvt *gvt;
+
+ vblank_timer = container_of(data, struct intel_gvt_vblank_timer, timer);
+ irq = container_of(vblank_timer, struct intel_gvt_irq, vblank_timer);
+ gvt = container_of(irq, struct intel_gvt, irq);
+
+ intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EMULATE_VBLANK);
+ hrtimer_add_expires_ns(&vblank_timer->timer, vblank_timer->period);
+ return HRTIMER_RESTART;
+}
+
+/**
+ * intel_gvt_clean_irq - clean up GVT-g IRQ emulation subsystem
+ * @gvt: a GVT device
+ *
+ * This function is called at driver unloading stage, to clean up GVT-g IRQ
+ * emulation subsystem.
+ *
+ */
+void intel_gvt_clean_irq(struct intel_gvt *gvt)
+{
+ struct intel_gvt_irq *irq = &gvt->irq;
+
+ hrtimer_cancel(&irq->vblank_timer.timer);
+}
+
+#define VBLNAK_TIMER_PERIOD 16000000
+
+/**
+ * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem
+ * @gvt: a GVT device
+ *
+ * This function is called at driver loading stage, to initialize the GVT-g IRQ
+ * emulation subsystem.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_gvt_init_irq(struct intel_gvt *gvt)
+{
+ struct intel_gvt_irq *irq = &gvt->irq;
+ struct intel_gvt_vblank_timer *vblank_timer = &irq->vblank_timer;
+
+ gvt_dbg_core("init irq framework\n");
+
+ if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+ irq->ops = &gen8_irq_ops;
+ irq->irq_map = gen8_irq_map;
+ } else {
+ WARN_ON(1);
+ return -ENODEV;
+ }
+
+ /* common event initialization */
+ init_events(irq);
+
+ /* gen specific initialization */
+ irq->ops->init_irq(irq);
+
+ init_irq_map(irq);
+
+ hrtimer_init(&vblank_timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ vblank_timer->timer.function = vblank_timer_fn;
+ vblank_timer->period = VBLNAK_TIMER_PERIOD;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h
new file mode 100644
index 000000000000..5313fb1b33e1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/interrupt.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Min he <min.he@intel.com>
+ *
+ */
+
+#ifndef _GVT_INTERRUPT_H_
+#define _GVT_INTERRUPT_H_
+
+enum intel_gvt_event_type {
+ RCS_MI_USER_INTERRUPT = 0,
+ RCS_DEBUG,
+ RCS_MMIO_SYNC_FLUSH,
+ RCS_CMD_STREAMER_ERR,
+ RCS_PIPE_CONTROL,
+ RCS_L3_PARITY_ERR,
+ RCS_WATCHDOG_EXCEEDED,
+ RCS_PAGE_DIRECTORY_FAULT,
+ RCS_AS_CONTEXT_SWITCH,
+ RCS_MONITOR_BUFF_HALF_FULL,
+
+ VCS_MI_USER_INTERRUPT,
+ VCS_MMIO_SYNC_FLUSH,
+ VCS_CMD_STREAMER_ERR,
+ VCS_MI_FLUSH_DW,
+ VCS_WATCHDOG_EXCEEDED,
+ VCS_PAGE_DIRECTORY_FAULT,
+ VCS_AS_CONTEXT_SWITCH,
+
+ VCS2_MI_USER_INTERRUPT,
+ VCS2_MI_FLUSH_DW,
+ VCS2_AS_CONTEXT_SWITCH,
+
+ BCS_MI_USER_INTERRUPT,
+ BCS_MMIO_SYNC_FLUSH,
+ BCS_CMD_STREAMER_ERR,
+ BCS_MI_FLUSH_DW,
+ BCS_PAGE_DIRECTORY_FAULT,
+ BCS_AS_CONTEXT_SWITCH,
+
+ VECS_MI_USER_INTERRUPT,
+ VECS_MI_FLUSH_DW,
+ VECS_AS_CONTEXT_SWITCH,
+
+ PIPE_A_FIFO_UNDERRUN,
+ PIPE_B_FIFO_UNDERRUN,
+ PIPE_A_CRC_ERR,
+ PIPE_B_CRC_ERR,
+ PIPE_A_CRC_DONE,
+ PIPE_B_CRC_DONE,
+ PIPE_A_ODD_FIELD,
+ PIPE_B_ODD_FIELD,
+ PIPE_A_EVEN_FIELD,
+ PIPE_B_EVEN_FIELD,
+ PIPE_A_LINE_COMPARE,
+ PIPE_B_LINE_COMPARE,
+ PIPE_C_LINE_COMPARE,
+ PIPE_A_VBLANK,
+ PIPE_B_VBLANK,
+ PIPE_C_VBLANK,
+ PIPE_A_VSYNC,
+ PIPE_B_VSYNC,
+ PIPE_C_VSYNC,
+ PRIMARY_A_FLIP_DONE,
+ PRIMARY_B_FLIP_DONE,
+ PRIMARY_C_FLIP_DONE,
+ SPRITE_A_FLIP_DONE,
+ SPRITE_B_FLIP_DONE,
+ SPRITE_C_FLIP_DONE,
+
+ PCU_THERMAL,
+ PCU_PCODE2DRIVER_MAILBOX,
+
+ DPST_PHASE_IN,
+ DPST_HISTOGRAM,
+ GSE,
+ DP_A_HOTPLUG,
+ AUX_CHANNEL_A,
+ PERF_COUNTER,
+ POISON,
+ GTT_FAULT,
+ ERROR_INTERRUPT_COMBINED,
+
+ FDI_RX_INTERRUPTS_TRANSCODER_A,
+ AUDIO_CP_CHANGE_TRANSCODER_A,
+ AUDIO_CP_REQUEST_TRANSCODER_A,
+ FDI_RX_INTERRUPTS_TRANSCODER_B,
+ AUDIO_CP_CHANGE_TRANSCODER_B,
+ AUDIO_CP_REQUEST_TRANSCODER_B,
+ FDI_RX_INTERRUPTS_TRANSCODER_C,
+ AUDIO_CP_CHANGE_TRANSCODER_C,
+ AUDIO_CP_REQUEST_TRANSCODER_C,
+ ERR_AND_DBG,
+ GMBUS,
+ SDVO_B_HOTPLUG,
+ CRT_HOTPLUG,
+ DP_B_HOTPLUG,
+ DP_C_HOTPLUG,
+ DP_D_HOTPLUG,
+ AUX_CHANNEL_B,
+ AUX_CHANNEL_C,
+ AUX_CHANNEL_D,
+ AUDIO_POWER_STATE_CHANGE_B,
+ AUDIO_POWER_STATE_CHANGE_C,
+ AUDIO_POWER_STATE_CHANGE_D,
+
+ INTEL_GVT_EVENT_RESERVED,
+ INTEL_GVT_EVENT_MAX,
+};
+
+struct intel_gvt_irq;
+struct intel_gvt;
+
+typedef void (*gvt_event_virt_handler_t)(struct intel_gvt_irq *irq,
+ enum intel_gvt_event_type event, struct intel_vgpu *vgpu);
+
+struct intel_gvt_irq_ops {
+ void (*init_irq)(struct intel_gvt_irq *irq);
+ void (*check_pending_irq)(struct intel_vgpu *vgpu);
+};
+
+/* the list of physical interrupt control register groups */
+enum intel_gvt_irq_type {
+ INTEL_GVT_IRQ_INFO_GT,
+ INTEL_GVT_IRQ_INFO_DPY,
+ INTEL_GVT_IRQ_INFO_PCH,
+ INTEL_GVT_IRQ_INFO_PM,
+
+ INTEL_GVT_IRQ_INFO_MASTER,
+ INTEL_GVT_IRQ_INFO_GT0,
+ INTEL_GVT_IRQ_INFO_GT1,
+ INTEL_GVT_IRQ_INFO_GT2,
+ INTEL_GVT_IRQ_INFO_GT3,
+ INTEL_GVT_IRQ_INFO_DE_PIPE_A,
+ INTEL_GVT_IRQ_INFO_DE_PIPE_B,
+ INTEL_GVT_IRQ_INFO_DE_PIPE_C,
+ INTEL_GVT_IRQ_INFO_DE_PORT,
+ INTEL_GVT_IRQ_INFO_DE_MISC,
+ INTEL_GVT_IRQ_INFO_AUD,
+ INTEL_GVT_IRQ_INFO_PCU,
+
+ INTEL_GVT_IRQ_INFO_MAX,
+};
+
+#define INTEL_GVT_IRQ_BITWIDTH 32
+
+/* device specific interrupt bit definitions */
+struct intel_gvt_irq_info {
+ char *name;
+ i915_reg_t reg_base;
+ enum intel_gvt_event_type bit_to_event[INTEL_GVT_IRQ_BITWIDTH];
+ unsigned long warned;
+ int group;
+ DECLARE_BITMAP(downstream_irq_bitmap, INTEL_GVT_IRQ_BITWIDTH);
+ bool has_upstream_irq;
+};
+
+/* per-event information */
+struct intel_gvt_event_info {
+ int bit; /* map to register bit */
+ int policy; /* forwarding policy */
+ struct intel_gvt_irq_info *info; /* register info */
+ gvt_event_virt_handler_t v_handler; /* for v_event */
+};
+
+struct intel_gvt_irq_map {
+ int up_irq_group;
+ int up_irq_bit;
+ int down_irq_group;
+ u32 down_irq_bitmask;
+};
+
+struct intel_gvt_vblank_timer {
+ struct hrtimer timer;
+ u64 period;
+};
+
+/* structure containing device specific IRQ state */
+struct intel_gvt_irq {
+ struct intel_gvt_irq_ops *ops;
+ struct intel_gvt_irq_info *info[INTEL_GVT_IRQ_INFO_MAX];
+ DECLARE_BITMAP(irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX);
+ struct intel_gvt_event_info events[INTEL_GVT_EVENT_MAX];
+ DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX);
+ struct intel_gvt_irq_map *irq_map;
+ struct intel_gvt_vblank_timer vblank_timer;
+};
+
+int intel_gvt_init_irq(struct intel_gvt *gvt);
+void intel_gvt_clean_irq(struct intel_gvt *gvt);
+
+void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
+ enum intel_gvt_event_type event);
+
+int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg,
+ void *p_data, unsigned int bytes);
+int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes);
+int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes);
+int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu,
+ unsigned int reg, void *p_data, unsigned int bytes);
+
+int gvt_ring_id_to_pipe_control_notify_event(int ring_id);
+int gvt_ring_id_to_mi_flush_dw_event(int ring_id);
+int gvt_ring_id_to_mi_user_interrupt_event(int ring_id);
+
+#endif /* _GVT_INTERRUPT_H_ */
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
new file mode 100644
index 000000000000..dc0365033157
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -0,0 +1,597 @@
+/*
+ * KVMGT - the implementation of Intel mediated pass-through framework for KVM
+ *
+ * Copyright(c) 2014-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Kevin Tian <kevin.tian@intel.com>
+ * Jike Song <jike.song@intel.com>
+ * Xiaoguang Chen <xiaoguang.chen@intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/eventfd.h>
+#include <linux/uuid.h>
+#include <linux/kvm_host.h>
+#include <linux/vfio.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static inline long kvmgt_pin_pages(struct device *dev, unsigned long *user_pfn,
+ long npage, int prot, unsigned long *phys_pfn)
+{
+ return 0;
+}
+static inline long kvmgt_unpin_pages(struct device *dev, unsigned long *pfn,
+ long npage)
+{
+ return 0;
+}
+
+static const struct intel_gvt_ops *intel_gvt_ops;
+
+
+/* helper macros copied from vfio-pci */
+#define VFIO_PCI_OFFSET_SHIFT 40
+#define VFIO_PCI_OFFSET_TO_INDEX(off) (off >> VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_OFFSET_MASK (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
+
+struct vfio_region {
+ u32 type;
+ u32 subtype;
+ size_t size;
+ u32 flags;
+};
+
+struct kvmgt_pgfn {
+ gfn_t gfn;
+ struct hlist_node hnode;
+};
+
+struct kvmgt_guest_info {
+ struct kvm *kvm;
+ struct intel_vgpu *vgpu;
+ struct kvm_page_track_notifier_node track_node;
+#define NR_BKT (1 << 18)
+ struct hlist_head ptable[NR_BKT];
+#undef NR_BKT
+};
+
+struct gvt_dma {
+ struct rb_node node;
+ gfn_t gfn;
+ kvm_pfn_t pfn;
+};
+
+static struct gvt_dma *__gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+ struct rb_node *node = vgpu->vdev.cache.rb_node;
+ struct gvt_dma *ret = NULL;
+
+ while (node) {
+ struct gvt_dma *itr = rb_entry(node, struct gvt_dma, node);
+
+ if (gfn < itr->gfn)
+ node = node->rb_left;
+ else if (gfn > itr->gfn)
+ node = node->rb_right;
+ else {
+ ret = itr;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static kvm_pfn_t gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+ struct gvt_dma *entry;
+
+ mutex_lock(&vgpu->vdev.cache_lock);
+ entry = __gvt_cache_find(vgpu, gfn);
+ mutex_unlock(&vgpu->vdev.cache_lock);
+
+ return entry == NULL ? 0 : entry->pfn;
+}
+
+static void gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn, kvm_pfn_t pfn)
+{
+ struct gvt_dma *new, *itr;
+ struct rb_node **link = &vgpu->vdev.cache.rb_node, *parent = NULL;
+
+ new = kzalloc(sizeof(struct gvt_dma), GFP_KERNEL);
+ if (!new)
+ return;
+
+ new->gfn = gfn;
+ new->pfn = pfn;
+
+ mutex_lock(&vgpu->vdev.cache_lock);
+ while (*link) {
+ parent = *link;
+ itr = rb_entry(parent, struct gvt_dma, node);
+
+ if (gfn == itr->gfn)
+ goto out;
+ else if (gfn < itr->gfn)
+ link = &parent->rb_left;
+ else
+ link = &parent->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, link);
+ rb_insert_color(&new->node, &vgpu->vdev.cache);
+ mutex_unlock(&vgpu->vdev.cache_lock);
+ return;
+
+out:
+ mutex_unlock(&vgpu->vdev.cache_lock);
+ kfree(new);
+}
+
+static void __gvt_cache_remove_entry(struct intel_vgpu *vgpu,
+ struct gvt_dma *entry)
+{
+ rb_erase(&entry->node, &vgpu->vdev.cache);
+ kfree(entry);
+}
+
+static void gvt_cache_remove(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+ struct device *dev = vgpu->vdev.mdev;
+ struct gvt_dma *this;
+ unsigned long pfn;
+
+ mutex_lock(&vgpu->vdev.cache_lock);
+ this = __gvt_cache_find(vgpu, gfn);
+ if (!this) {
+ mutex_unlock(&vgpu->vdev.cache_lock);
+ return;
+ }
+
+ pfn = this->pfn;
+ WARN_ON((kvmgt_unpin_pages(dev, &pfn, 1) != 1));
+ __gvt_cache_remove_entry(vgpu, this);
+ mutex_unlock(&vgpu->vdev.cache_lock);
+}
+
+static void gvt_cache_init(struct intel_vgpu *vgpu)
+{
+ vgpu->vdev.cache = RB_ROOT;
+ mutex_init(&vgpu->vdev.cache_lock);
+}
+
+static void gvt_cache_destroy(struct intel_vgpu *vgpu)
+{
+ struct gvt_dma *dma;
+ struct rb_node *node = NULL;
+ struct device *dev = vgpu->vdev.mdev;
+ unsigned long pfn;
+
+ mutex_lock(&vgpu->vdev.cache_lock);
+ while ((node = rb_first(&vgpu->vdev.cache))) {
+ dma = rb_entry(node, struct gvt_dma, node);
+ pfn = dma->pfn;
+
+ kvmgt_unpin_pages(dev, &pfn, 1);
+ __gvt_cache_remove_entry(vgpu, dma);
+ }
+ mutex_unlock(&vgpu->vdev.cache_lock);
+}
+
+static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
+ const char *name)
+{
+ int i;
+ struct intel_vgpu_type *t;
+ const char *driver_name = dev_driver_string(
+ &gvt->dev_priv->drm.pdev->dev);
+
+ for (i = 0; i < gvt->num_types; i++) {
+ t = &gvt->types[i];
+ if (!strncmp(t->name, name + strlen(driver_name) + 1,
+ sizeof(t->name)))
+ return t;
+ }
+
+ return NULL;
+}
+
+static struct attribute *type_attrs[] = {
+ NULL,
+};
+
+static struct attribute_group *intel_vgpu_type_groups[] = {
+ [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
+};
+
+static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
+{
+ int i, j;
+ struct intel_vgpu_type *type;
+ struct attribute_group *group;
+
+ for (i = 0; i < gvt->num_types; i++) {
+ type = &gvt->types[i];
+
+ group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+ if (WARN_ON(!group))
+ goto unwind;
+
+ group->name = type->name;
+ group->attrs = type_attrs;
+ intel_vgpu_type_groups[i] = group;
+ }
+
+ return true;
+
+unwind:
+ for (j = 0; j < i; j++) {
+ group = intel_vgpu_type_groups[j];
+ kfree(group);
+ }
+
+ return false;
+}
+
+static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
+{
+ int i;
+ struct attribute_group *group;
+
+ for (i = 0; i < gvt->num_types; i++) {
+ group = intel_vgpu_type_groups[i];
+ kfree(group);
+ }
+}
+
+static void kvmgt_protect_table_init(struct kvmgt_guest_info *info)
+{
+ hash_init(info->ptable);
+}
+
+static void kvmgt_protect_table_destroy(struct kvmgt_guest_info *info)
+{
+ struct kvmgt_pgfn *p;
+ struct hlist_node *tmp;
+ int i;
+
+ hash_for_each_safe(info->ptable, i, tmp, p, hnode) {
+ hash_del(&p->hnode);
+ kfree(p);
+ }
+}
+
+static struct kvmgt_pgfn *
+__kvmgt_protect_table_find(struct kvmgt_guest_info *info, gfn_t gfn)
+{
+ struct kvmgt_pgfn *p, *res = NULL;
+
+ hash_for_each_possible(info->ptable, p, hnode, gfn) {
+ if (gfn == p->gfn) {
+ res = p;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static bool kvmgt_gfn_is_write_protected(struct kvmgt_guest_info *info,
+ gfn_t gfn)
+{
+ struct kvmgt_pgfn *p;
+
+ p = __kvmgt_protect_table_find(info, gfn);
+ return !!p;
+}
+
+static void kvmgt_protect_table_add(struct kvmgt_guest_info *info, gfn_t gfn)
+{
+ struct kvmgt_pgfn *p;
+
+ if (kvmgt_gfn_is_write_protected(info, gfn))
+ return;
+
+ p = kmalloc(sizeof(struct kvmgt_pgfn), GFP_ATOMIC);
+ if (WARN(!p, "gfn: 0x%llx\n", gfn))
+ return;
+
+ p->gfn = gfn;
+ hash_add(info->ptable, &p->hnode, gfn);
+}
+
+static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
+ gfn_t gfn)
+{
+ struct kvmgt_pgfn *p;
+
+ p = __kvmgt_protect_table_find(info, gfn);
+ if (p) {
+ hash_del(&p->hnode);
+ kfree(p);
+ }
+}
+
+static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
+{
+ if (!intel_gvt_init_vgpu_type_groups(gvt))
+ return -EFAULT;
+
+ intel_gvt_ops = ops;
+
+ /* MDEV is not yet available */
+ return -ENODEV;
+}
+
+static void kvmgt_host_exit(struct device *dev, void *gvt)
+{
+ intel_gvt_cleanup_vgpu_type_groups(gvt);
+}
+
+static int kvmgt_write_protect_add(unsigned long handle, u64 gfn)
+{
+ struct kvmgt_guest_info *info = (struct kvmgt_guest_info *)handle;
+ struct kvm *kvm = info->kvm;
+ struct kvm_memory_slot *slot;
+ int idx;
+
+ idx = srcu_read_lock(&kvm->srcu);
+ slot = gfn_to_memslot(kvm, gfn);
+
+ spin_lock(&kvm->mmu_lock);
+
+ if (kvmgt_gfn_is_write_protected(info, gfn))
+ goto out;
+
+ kvm_slot_page_track_add_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
+ kvmgt_protect_table_add(info, gfn);
+
+out:
+ spin_unlock(&kvm->mmu_lock);
+ srcu_read_unlock(&kvm->srcu, idx);
+ return 0;
+}
+
+static int kvmgt_write_protect_remove(unsigned long handle, u64 gfn)
+{
+ struct kvmgt_guest_info *info = (struct kvmgt_guest_info *)handle;
+ struct kvm *kvm = info->kvm;
+ struct kvm_memory_slot *slot;
+ int idx;
+
+ idx = srcu_read_lock(&kvm->srcu);
+ slot = gfn_to_memslot(kvm, gfn);
+
+ spin_lock(&kvm->mmu_lock);
+
+ if (!kvmgt_gfn_is_write_protected(info, gfn))
+ goto out;
+
+ kvm_slot_page_track_remove_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
+ kvmgt_protect_table_del(info, gfn);
+
+out:
+ spin_unlock(&kvm->mmu_lock);
+ srcu_read_unlock(&kvm->srcu, idx);
+ return 0;
+}
+
+static void kvmgt_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+ const u8 *val, int len,
+ struct kvm_page_track_notifier_node *node)
+{
+ struct kvmgt_guest_info *info = container_of(node,
+ struct kvmgt_guest_info, track_node);
+
+ if (kvmgt_gfn_is_write_protected(info, gpa_to_gfn(gpa)))
+ intel_gvt_ops->emulate_mmio_write(info->vgpu, gpa,
+ (void *)val, len);
+}
+
+static void kvmgt_page_track_flush_slot(struct kvm *kvm,
+ struct kvm_memory_slot *slot,
+ struct kvm_page_track_notifier_node *node)
+{
+ int i;
+ gfn_t gfn;
+ struct kvmgt_guest_info *info = container_of(node,
+ struct kvmgt_guest_info, track_node);
+
+ spin_lock(&kvm->mmu_lock);
+ for (i = 0; i < slot->npages; i++) {
+ gfn = slot->base_gfn + i;
+ if (kvmgt_gfn_is_write_protected(info, gfn)) {
+ kvm_slot_page_track_remove_page(kvm, slot, gfn,
+ KVM_PAGE_TRACK_WRITE);
+ kvmgt_protect_table_del(info, gfn);
+ }
+ }
+ spin_unlock(&kvm->mmu_lock);
+}
+
+static bool kvmgt_check_guest(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ char s[12];
+ unsigned int *i;
+
+ eax = KVM_CPUID_SIGNATURE;
+ ebx = ecx = edx = 0;
+
+ asm volatile ("cpuid"
+ : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
+ :
+ : "cc", "memory");
+ i = (unsigned int *)s;
+ i[0] = ebx;
+ i[1] = ecx;
+ i[2] = edx;
+
+ return !strncmp(s, "KVMKVMKVM", strlen("KVMKVMKVM"));
+}
+
+/**
+ * NOTE:
+ * It's actually impossible to check if we are running in KVM host,
+ * since the "KVM host" is simply native. So we only dectect guest here.
+ */
+static int kvmgt_detect_host(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+ if (intel_iommu_gfx_mapped) {
+ gvt_err("Hardware IOMMU compatibility not yet supported, try to boot with intel_iommu=igfx_off\n");
+ return -ENODEV;
+ }
+#endif
+ return kvmgt_check_guest() ? -ENODEV : 0;
+}
+
+static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
+{
+ /* nothing to do here */
+ return 0;
+}
+
+static void kvmgt_detach_vgpu(unsigned long handle)
+{
+ /* nothing to do here */
+}
+
+static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
+{
+ struct kvmgt_guest_info *info = (struct kvmgt_guest_info *)handle;
+ struct intel_vgpu *vgpu = info->vgpu;
+
+ if (vgpu->vdev.msi_trigger)
+ return eventfd_signal(vgpu->vdev.msi_trigger, 1) == 1;
+
+ return false;
+}
+
+static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
+{
+ unsigned long pfn;
+ struct kvmgt_guest_info *info = (struct kvmgt_guest_info *)handle;
+ int rc;
+
+ pfn = gvt_cache_find(info->vgpu, gfn);
+ if (pfn != 0)
+ return pfn;
+
+ rc = kvmgt_pin_pages(info->vgpu->vdev.mdev, &gfn, 1,
+ IOMMU_READ | IOMMU_WRITE, &pfn);
+ if (rc != 1) {
+ gvt_err("vfio_pin_pages failed for gfn: 0x%lx\n", gfn);
+ return 0;
+ }
+
+ gvt_cache_add(info->vgpu, gfn, pfn);
+ return pfn;
+}
+
+static void *kvmgt_gpa_to_hva(unsigned long handle, unsigned long gpa)
+{
+ unsigned long pfn;
+ gfn_t gfn = gpa_to_gfn(gpa);
+
+ pfn = kvmgt_gfn_to_pfn(handle, gfn);
+ if (!pfn)
+ return NULL;
+
+ return (char *)pfn_to_kaddr(pfn) + offset_in_page(gpa);
+}
+
+static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
+ void *buf, unsigned long len, bool write)
+{
+ void *hva = NULL;
+
+ hva = kvmgt_gpa_to_hva(handle, gpa);
+ if (!hva)
+ return -EFAULT;
+
+ if (write)
+ memcpy(hva, buf, len);
+ else
+ memcpy(buf, hva, len);
+
+ return 0;
+}
+
+static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,
+ void *buf, unsigned long len)
+{
+ return kvmgt_rw_gpa(handle, gpa, buf, len, false);
+}
+
+static int kvmgt_write_gpa(unsigned long handle, unsigned long gpa,
+ void *buf, unsigned long len)
+{
+ return kvmgt_rw_gpa(handle, gpa, buf, len, true);
+}
+
+static unsigned long kvmgt_virt_to_pfn(void *addr)
+{
+ return PFN_DOWN(__pa(addr));
+}
+
+struct intel_gvt_mpt kvmgt_mpt = {
+ .detect_host = kvmgt_detect_host,
+ .host_init = kvmgt_host_init,
+ .host_exit = kvmgt_host_exit,
+ .attach_vgpu = kvmgt_attach_vgpu,
+ .detach_vgpu = kvmgt_detach_vgpu,
+ .inject_msi = kvmgt_inject_msi,
+ .from_virt_to_mfn = kvmgt_virt_to_pfn,
+ .set_wp_page = kvmgt_write_protect_add,
+ .unset_wp_page = kvmgt_write_protect_remove,
+ .read_gpa = kvmgt_read_gpa,
+ .write_gpa = kvmgt_write_gpa,
+ .gfn_to_mfn = kvmgt_gfn_to_pfn,
+};
+EXPORT_SYMBOL_GPL(kvmgt_mpt);
+
+static int __init kvmgt_init(void)
+{
+ return 0;
+}
+
+static void __exit kvmgt_exit(void)
+{
+}
+
+module_init(kvmgt_init);
+module_exit(kvmgt_exit);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
new file mode 100644
index 000000000000..09c9450a1946
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/mmio.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Kevin Tian <kevin.tian@intel.com>
+ * Dexuan Cui
+ *
+ * Contributors:
+ * Tina Zhang <tina.zhang@intel.com>
+ * Min He <min.he@intel.com>
+ * Niu Bing <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+/**
+ * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset
+ * @vgpu: a vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)
+{
+ u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) &
+ ~GENMASK(3, 0);
+ return gpa - gttmmio_gpa;
+}
+
+#define reg_is_mmio(gvt, reg) \
+ (reg >= 0 && reg < gvt->device_info.mmio_size)
+
+#define reg_is_gtt(gvt, reg) \
+ (reg >= gvt->device_info.gtt_start_offset \
+ && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))
+
+/**
+ * intel_vgpu_emulate_mmio_read - emulate MMIO read
+ * @vgpu: a vGPU
+ * @pa: guest physical address
+ * @p_data: data return buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
+ void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_mmio_info *mmio;
+ unsigned int offset = 0;
+ int ret = -EINVAL;
+
+ mutex_lock(&gvt->lock);
+
+ if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
+ struct intel_vgpu_guest_page *gp;
+
+ gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
+ if (gp) {
+ ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,
+ p_data, bytes);
+ if (ret) {
+ gvt_err("vgpu%d: guest page read error %d, "
+ "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
+ vgpu->id, ret,
+ gp->gfn, pa, *(u32 *)p_data, bytes);
+ }
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+ }
+
+ offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
+
+ if (WARN_ON(bytes > 8))
+ goto err;
+
+ if (reg_is_gtt(gvt, offset)) {
+ if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8)))
+ goto err;
+ if (WARN_ON(bytes != 4 && bytes != 8))
+ goto err;
+ if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1)))
+ goto err;
+
+ ret = intel_vgpu_emulate_gtt_mmio_read(vgpu, offset,
+ p_data, bytes);
+ if (ret)
+ goto err;
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+
+ if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) {
+ ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, p_data, bytes);
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+
+ if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1)))
+ goto err;
+
+ mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
+ if (!mmio && !vgpu->mmio.disable_warn_untrack) {
+ gvt_err("vgpu%d: read untracked MMIO %x len %d val %x\n",
+ vgpu->id, offset, bytes, *(u32 *)p_data);
+
+ if (offset == 0x206c) {
+ gvt_err("------------------------------------------\n");
+ gvt_err("vgpu%d: likely triggers a gfx reset\n",
+ vgpu->id);
+ gvt_err("------------------------------------------\n");
+ vgpu->mmio.disable_warn_untrack = true;
+ }
+ }
+
+ if (!intel_gvt_mmio_is_unalign(gvt, offset)) {
+ if (WARN_ON(!IS_ALIGNED(offset, bytes)))
+ goto err;
+ }
+
+ if (mmio) {
+ if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) {
+ if (WARN_ON(offset + bytes > mmio->offset + mmio->size))
+ goto err;
+ if (WARN_ON(mmio->offset != offset))
+ goto err;
+ }
+ ret = mmio->read(vgpu, offset, p_data, bytes);
+ } else
+ ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+
+ if (ret)
+ goto err;
+
+ intel_gvt_mmio_set_accessed(gvt, offset);
+ mutex_unlock(&gvt->lock);
+ return 0;
+err:
+ gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n",
+ vgpu->id, offset, bytes);
+ mutex_unlock(&gvt->lock);
+ return ret;
+}
+
+/**
+ * intel_vgpu_emulate_mmio_write - emulate MMIO write
+ * @vgpu: a vGPU
+ * @pa: guest physical address
+ * @p_data: write data buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
+ void *p_data, unsigned int bytes)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_mmio_info *mmio;
+ unsigned int offset = 0;
+ u32 old_vreg = 0, old_sreg = 0;
+ int ret = -EINVAL;
+
+ mutex_lock(&gvt->lock);
+
+ if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
+ struct intel_vgpu_guest_page *gp;
+
+ gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
+ if (gp) {
+ ret = gp->handler(gp, pa, p_data, bytes);
+ if (ret) {
+ gvt_err("vgpu%d: guest page write error %d, "
+ "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
+ vgpu->id, ret,
+ gp->gfn, pa, *(u32 *)p_data, bytes);
+ }
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+ }
+
+ offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
+
+ if (WARN_ON(bytes > 8))
+ goto err;
+
+ if (reg_is_gtt(gvt, offset)) {
+ if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8)))
+ goto err;
+ if (WARN_ON(bytes != 4 && bytes != 8))
+ goto err;
+ if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1)))
+ goto err;
+
+ ret = intel_vgpu_emulate_gtt_mmio_write(vgpu, offset,
+ p_data, bytes);
+ if (ret)
+ goto err;
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+
+ if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) {
+ ret = intel_gvt_hypervisor_write_gpa(vgpu, pa, p_data, bytes);
+ mutex_unlock(&gvt->lock);
+ return ret;
+ }
+
+ mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
+ if (!mmio && !vgpu->mmio.disable_warn_untrack)
+ gvt_err("vgpu%d: write untracked MMIO %x len %d val %x\n",
+ vgpu->id, offset, bytes, *(u32 *)p_data);
+
+ if (!intel_gvt_mmio_is_unalign(gvt, offset)) {
+ if (WARN_ON(!IS_ALIGNED(offset, bytes)))
+ goto err;
+ }
+
+ if (mmio) {
+ u64 ro_mask = mmio->ro_mask;
+
+ if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) {
+ if (WARN_ON(offset + bytes > mmio->offset + mmio->size))
+ goto err;
+ if (WARN_ON(mmio->offset != offset))
+ goto err;
+ }
+
+ if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) {
+ old_vreg = vgpu_vreg(vgpu, offset);
+ old_sreg = vgpu_sreg(vgpu, offset);
+ }
+
+ if (!ro_mask) {
+ ret = mmio->write(vgpu, offset, p_data, bytes);
+ } else {
+ /* Protect RO bits like HW */
+ u64 data = 0;
+
+ /* all register bits are RO. */
+ if (ro_mask == ~(u64)0) {
+ gvt_err("vgpu%d: try to write RO reg %x\n",
+ vgpu->id, offset);
+ ret = 0;
+ goto out;
+ }
+ /* keep the RO bits in the virtual register */
+ memcpy(&data, p_data, bytes);
+ data &= ~mmio->ro_mask;
+ data |= vgpu_vreg(vgpu, offset) & mmio->ro_mask;
+ ret = mmio->write(vgpu, offset, &data, bytes);
+ }
+
+ /* higher 16bits of mode ctl regs are mask bits for change */
+ if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) {
+ u32 mask = vgpu_vreg(vgpu, offset) >> 16;
+
+ vgpu_vreg(vgpu, offset) = (old_vreg & ~mask)
+ | (vgpu_vreg(vgpu, offset) & mask);
+ vgpu_sreg(vgpu, offset) = (old_sreg & ~mask)
+ | (vgpu_sreg(vgpu, offset) & mask);
+ }
+ } else
+ ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data,
+ bytes);
+ if (ret)
+ goto err;
+out:
+ intel_gvt_mmio_set_accessed(gvt, offset);
+ mutex_unlock(&gvt->lock);
+ return 0;
+err:
+ gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n",
+ vgpu->id, offset, bytes);
+ mutex_unlock(&gvt->lock);
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h
new file mode 100644
index 000000000000..87d5b5e366a3
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/mmio.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Ke Yu
+ * Kevin Tian <kevin.tian@intel.com>
+ * Dexuan Cui
+ *
+ * Contributors:
+ * Tina Zhang <tina.zhang@intel.com>
+ * Min He <min.he@intel.com>
+ * Niu Bing <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_MMIO_H_
+#define _GVT_MMIO_H_
+
+struct intel_gvt;
+struct intel_vgpu;
+
+#define D_SNB (1 << 0)
+#define D_IVB (1 << 1)
+#define D_HSW (1 << 2)
+#define D_BDW (1 << 3)
+#define D_SKL (1 << 4)
+
+#define D_GEN9PLUS (D_SKL)
+#define D_GEN8PLUS (D_BDW | D_SKL)
+#define D_GEN75PLUS (D_HSW | D_BDW | D_SKL)
+#define D_GEN7PLUS (D_IVB | D_HSW | D_BDW | D_SKL)
+
+#define D_SKL_PLUS (D_SKL)
+#define D_BDW_PLUS (D_BDW | D_SKL)
+#define D_HSW_PLUS (D_HSW | D_BDW | D_SKL)
+#define D_IVB_PLUS (D_IVB | D_HSW | D_BDW | D_SKL)
+
+#define D_PRE_BDW (D_SNB | D_IVB | D_HSW)
+#define D_PRE_SKL (D_SNB | D_IVB | D_HSW | D_BDW)
+#define D_ALL (D_SNB | D_IVB | D_HSW | D_BDW | D_SKL)
+
+struct intel_gvt_mmio_info {
+ u32 offset;
+ u32 size;
+ u32 length;
+ u32 addr_mask;
+ u64 ro_mask;
+ u32 device;
+ int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int);
+ int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int);
+ u32 addr_range;
+ struct hlist_node node;
+};
+
+unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt);
+bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device);
+
+int intel_gvt_setup_mmio_info(struct intel_gvt *gvt);
+void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);
+
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
+ unsigned int offset);
+#define INTEL_GVT_MMIO_OFFSET(reg) ({ \
+ typeof(reg) __reg = reg; \
+ u32 *offset = (u32 *)&__reg; \
+ *offset; \
+})
+
+int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa);
+
+int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, u64 pa,
+ void *p_data, unsigned int bytes);
+int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, u64 pa,
+ void *p_data, unsigned int bytes);
+bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt,
+ unsigned int offset);
+bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, unsigned int offset);
+void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset);
+void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt,
+ unsigned int offset);
+bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset);
+int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes);
+int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+ void *p_data, unsigned int bytes);
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h
index 03601e3ffa7c..1af5830c0a56 100644
--- a/drivers/gpu/drm/i915/gvt/mpt.h
+++ b/drivers/gpu/drm/i915/gvt/mpt.h
@@ -19,6 +19,15 @@
* 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Dexuan Cui
+ * Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
*/
#ifndef _GVT_MPT_H_
@@ -46,4 +55,254 @@ static inline int intel_gvt_hypervisor_detect_host(void)
return intel_gvt_host.mpt->detect_host();
}
+/**
+ * intel_gvt_hypervisor_host_init - init GVT-g host side
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+static inline int intel_gvt_hypervisor_host_init(struct device *dev,
+ void *gvt, const void *ops)
+{
+ /* optional to provide */
+ if (!intel_gvt_host.mpt->host_init)
+ return 0;
+
+ return intel_gvt_host.mpt->host_init(dev, gvt, ops);
+}
+
+/**
+ * intel_gvt_hypervisor_host_exit - exit GVT-g host side
+ */
+static inline void intel_gvt_hypervisor_host_exit(struct device *dev,
+ void *gvt)
+{
+ /* optional to provide */
+ if (!intel_gvt_host.mpt->host_exit)
+ return;
+
+ intel_gvt_host.mpt->host_exit(dev, gvt);
+}
+
+/**
+ * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU
+ * related stuffs inside hypervisor.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu)
+{
+ /* optional to provide */
+ if (!intel_gvt_host.mpt->attach_vgpu)
+ return 0;
+
+ return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle);
+}
+
+/**
+ * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU
+ * related stuffs inside hypervisor.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
+{
+ /* optional to provide */
+ if (!intel_gvt_host.mpt->detach_vgpu)
+ return;
+
+ intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+}
+
+#define MSI_CAP_CONTROL(offset) (offset + 2)
+#define MSI_CAP_ADDRESS(offset) (offset + 4)
+#define MSI_CAP_DATA(offset) (offset + 8)
+#define MSI_CAP_EN 0x1
+
+/**
+ * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu)
+{
+ unsigned long offset = vgpu->gvt->device_info.msi_cap_offset;
+ u16 control, data;
+ u32 addr;
+ int ret;
+
+ control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset));
+ addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset));
+ data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset));
+
+ /* Do not generate MSI if MSIEN is disable */
+ if (!(control & MSI_CAP_EN))
+ return 0;
+
+ if (WARN(control & GENMASK(15, 1), "only support one MSI format\n"))
+ return -EINVAL;
+
+ gvt_dbg_irq("vgpu%d: inject msi address %x data%x\n", vgpu->id, addr,
+ data);
+
+ ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN
+ * @p: host kernel virtual address
+ *
+ * Returns:
+ * MFN on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p)
+{
+ return intel_gvt_host.mpt->from_virt_to_mfn(p);
+}
+
+/**
+ * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected
+ * @vgpu: a vGPU
+ * @p: intel_vgpu_guest_page
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *p)
+{
+ int ret;
+
+ if (p->writeprotection)
+ return 0;
+
+ ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn);
+ if (ret)
+ return ret;
+ p->writeprotection = true;
+ atomic_inc(&vgpu->gtt.n_write_protected_guest_page);
+ return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a
+ * guest page
+ * @vgpu: a vGPU
+ * @p: intel_vgpu_guest_page
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu,
+ struct intel_vgpu_guest_page *p)
+{
+ int ret;
+
+ if (!p->writeprotection)
+ return 0;
+
+ ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn);
+ if (ret)
+ return ret;
+ p->writeprotection = false;
+ atomic_dec(&vgpu->gtt.n_write_protected_guest_page);
+ return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer
+ * @vgpu: a vGPU
+ * @gpa: guest physical address
+ * @buf: host data buffer
+ * @len: data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu,
+ unsigned long gpa, void *buf, unsigned long len)
+{
+ return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len);
+}
+
+/**
+ * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA
+ * @vgpu: a vGPU
+ * @gpa: guest physical address
+ * @buf: host data buffer
+ * @len: data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu,
+ unsigned long gpa, void *buf, unsigned long len)
+{
+ return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len);
+}
+
+/**
+ * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN
+ * @vgpu: a vGPU
+ * @gpfn: guest pfn
+ *
+ * Returns:
+ * MFN on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn(
+ struct intel_vgpu *vgpu, unsigned long gfn)
+{
+ return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn);
+}
+
+/**
+ * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
+ * @vgpu: a vGPU
+ * @gfn: guest PFN
+ * @mfn: host PFN
+ * @nr: amount of PFNs
+ * @map: map or unmap
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_map_gfn_to_mfn(
+ struct intel_vgpu *vgpu, unsigned long gfn,
+ unsigned long mfn, unsigned int nr,
+ bool map)
+{
+ /* a MPT implementation could have MMIO mapped elsewhere */
+ if (!intel_gvt_host.mpt->map_gfn_to_mfn)
+ return 0;
+
+ return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr,
+ map);
+}
+
+/**
+ * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region
+ * @vgpu: a vGPU
+ * @start: the beginning of the guest physical address region
+ * @end: the end of the guest physical address region
+ * @map: map or unmap
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_set_trap_area(
+ struct intel_vgpu *vgpu, u64 start, u64 end, bool map)
+{
+ /* a MPT implementation could have MMIO trapped elsewhere */
+ if (!intel_gvt_host.mpt->set_trap_area)
+ return 0;
+
+ return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map);
+}
+
#endif /* _GVT_MPT_H_ */
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
new file mode 100644
index 000000000000..d2a0fbc896c3
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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/acpi.h>
+#include "i915_drv.h"
+#include "gvt.h"
+
+static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
+{
+ void __iomem *host_va = vgpu->gvt->opregion.opregion_va;
+ u8 *buf;
+ int i;
+
+ if (WARN((vgpu_opregion(vgpu)->va),
+ "vgpu%d: opregion has been initialized already.\n",
+ vgpu->id))
+ return -EINVAL;
+
+ vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_ATOMIC |
+ GFP_DMA32 | __GFP_ZERO,
+ INTEL_GVT_OPREGION_PORDER);
+
+ if (!vgpu_opregion(vgpu)->va)
+ return -ENOMEM;
+
+ memcpy_fromio(vgpu_opregion(vgpu)->va, host_va,
+ INTEL_GVT_OPREGION_SIZE);
+
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+ vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+
+ /* for unknown reason, the value in LID field is incorrect
+ * which block the windows guest, so workaround it by force
+ * setting it to "OPEN"
+ */
+ buf = (u8 *)vgpu_opregion(vgpu)->va;
+ buf[INTEL_GVT_OPREGION_CLID] = 0x3;
+
+ return 0;
+}
+
+static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
+{
+ u64 mfn;
+ int i, ret;
+
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) {
+ mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)
+ + i * PAGE_SIZE);
+ if (mfn == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("fail to get MFN from VA\n");
+ return -EINVAL;
+ }
+ ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
+ vgpu_opregion(vgpu)->gfn[i],
+ mfn, 1, map);
+ if (ret) {
+ gvt_err("fail to map GFN to MFN, errno: %d\n", ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/**
+ * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
+{
+ gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id);
+
+ if (!vgpu_opregion(vgpu)->va)
+ return;
+
+ if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+ map_vgpu_opregion(vgpu, false);
+ free_pages((unsigned long)vgpu_opregion(vgpu)->va,
+ INTEL_GVT_OPREGION_PORDER);
+
+ vgpu_opregion(vgpu)->va = NULL;
+ }
+}
+
+/**
+ * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
+ * @vgpu: a vGPU
+ * @gpa: guest physical address of opregion
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
+{
+ int ret;
+
+ gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
+
+ if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+ gvt_dbg_core("emulate opregion from kernel\n");
+
+ ret = init_vgpu_opregion(vgpu, gpa);
+ if (ret)
+ return ret;
+
+ ret = map_vgpu_opregion(vgpu, true);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * intel_gvt_clean_opregion - clean host opergion related stuffs
+ * @gvt: a GVT device
+ *
+ */
+void intel_gvt_clean_opregion(struct intel_gvt *gvt)
+{
+ memunmap(gvt->opregion.opregion_va);
+ gvt->opregion.opregion_va = NULL;
+}
+
+/**
+ * intel_gvt_init_opregion - initialize host opergion related stuffs
+ * @gvt: a GVT device
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_gvt_init_opregion(struct intel_gvt *gvt)
+{
+ gvt_dbg_core("init host opregion\n");
+
+ pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION,
+ &gvt->opregion.opregion_pa);
+
+ gvt->opregion.opregion_va = memremap(gvt->opregion.opregion_pa,
+ INTEL_GVT_OPREGION_SIZE, MEMREMAP_WB);
+ if (!gvt->opregion.opregion_va) {
+ gvt_err("fail to map host opregion\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+#define GVT_OPREGION_FUNC(scic) \
+ ({ \
+ u32 __ret; \
+ __ret = (scic & OPREGION_SCIC_FUNC_MASK) >> \
+ OPREGION_SCIC_FUNC_SHIFT; \
+ __ret; \
+ })
+
+#define GVT_OPREGION_SUBFUNC(scic) \
+ ({ \
+ u32 __ret; \
+ __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >> \
+ OPREGION_SCIC_SUBFUNC_SHIFT; \
+ __ret; \
+ })
+
+static const char *opregion_func_name(u32 func)
+{
+ const char *name = NULL;
+
+ switch (func) {
+ case 0 ... 3:
+ case 5:
+ case 7 ... 15:
+ name = "Reserved";
+ break;
+
+ case 4:
+ name = "Get BIOS Data";
+ break;
+
+ case 6:
+ name = "System BIOS Callbacks";
+ break;
+
+ default:
+ name = "Unknown";
+ break;
+ }
+ return name;
+}
+
+static const char *opregion_subfunc_name(u32 subfunc)
+{
+ const char *name = NULL;
+
+ switch (subfunc) {
+ case 0:
+ name = "Supported Calls";
+ break;
+
+ case 1:
+ name = "Requested Callbacks";
+ break;
+
+ case 2 ... 3:
+ case 8 ... 9:
+ name = "Reserved";
+ break;
+
+ case 5:
+ name = "Boot Display";
+ break;
+
+ case 6:
+ name = "TV-Standard/Video-Connector";
+ break;
+
+ case 7:
+ name = "Internal Graphics";
+ break;
+
+ case 10:
+ name = "Spread Spectrum Clocks";
+ break;
+
+ case 11:
+ name = "Get AKSV";
+ break;
+
+ default:
+ name = "Unknown";
+ break;
+ }
+ return name;
+};
+
+static bool querying_capabilities(u32 scic)
+{
+ u32 func, subfunc;
+
+ func = GVT_OPREGION_FUNC(scic);
+ subfunc = GVT_OPREGION_SUBFUNC(scic);
+
+ if ((func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA &&
+ subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)
+ || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA &&
+ subfunc == INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS)
+ || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS &&
+ subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * intel_vgpu_emulate_opregion_request - emulating OpRegion request
+ * @vgpu: a vGPU
+ * @swsci: SWSCI request
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
+{
+ u32 *scic, *parm;
+ u32 func, subfunc;
+
+ scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC;
+ parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
+
+ if (!(swsci & SWSCI_SCI_SELECT)) {
+ gvt_err("vgpu%d: requesting SMI service\n", vgpu->id);
+ return 0;
+ }
+ /* ignore non 0->1 trasitions */
+ if ((vgpu_cfg_space(vgpu)[INTEL_GVT_PCI_SWSCI]
+ & SWSCI_SCI_TRIGGER) ||
+ !(swsci & SWSCI_SCI_TRIGGER)) {
+ return 0;
+ }
+
+ func = GVT_OPREGION_FUNC(*scic);
+ subfunc = GVT_OPREGION_SUBFUNC(*scic);
+ if (!querying_capabilities(*scic)) {
+ gvt_err("vgpu%d: requesting runtime service: func \"%s\","
+ " subfunc \"%s\"\n",
+ vgpu->id,
+ opregion_func_name(func),
+ opregion_subfunc_name(subfunc));
+ /*
+ * emulate exit status of function call, '0' means
+ * "failure, generic, unsupported or unknown cause"
+ */
+ *scic &= ~OPREGION_SCIC_EXIT_MASK;
+ return 0;
+ }
+
+ *scic = 0;
+ *parm = 0;
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h
new file mode 100644
index 000000000000..0dfe789d8f02
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/reg.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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 _GVT_REG_H
+#define _GVT_REG_H
+
+#define INTEL_GVT_PCI_CLASS_VGA_OTHER 0x80
+
+#define INTEL_GVT_PCI_GMCH_CONTROL 0x50
+#define BDW_GMCH_GMS_SHIFT 8
+#define BDW_GMCH_GMS_MASK 0xff
+
+#define INTEL_GVT_PCI_SWSCI 0xe8
+#define SWSCI_SCI_SELECT (1 << 15)
+#define SWSCI_SCI_TRIGGER 1
+
+#define INTEL_GVT_PCI_OPREGION 0xfc
+
+#define INTEL_GVT_OPREGION_CLID 0x1AC
+#define INTEL_GVT_OPREGION_SCIC 0x200
+#define OPREGION_SCIC_FUNC_MASK 0x1E
+#define OPREGION_SCIC_FUNC_SHIFT 1
+#define OPREGION_SCIC_SUBFUNC_MASK 0xFF00
+#define OPREGION_SCIC_SUBFUNC_SHIFT 8
+#define OPREGION_SCIC_EXIT_MASK 0xE0
+#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA 4
+#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS 6
+#define INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS 0
+#define INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS 1
+#define INTEL_GVT_OPREGION_PARM 0x204
+
+#define INTEL_GVT_OPREGION_PAGES 2
+#define INTEL_GVT_OPREGION_PORDER 1
+#define INTEL_GVT_OPREGION_SIZE (2 * 4096)
+
+#define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B)
+
+#define _REG_VECS_EXCC 0x1A028
+#define _REG_VCS2_EXCC 0x1c028
+
+#define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100)
+#define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100)
+
+#define GFX_MODE_BIT_SET_IN_MASK(val, bit) \
+ ((((bit) & 0xffff0000) == 0) && !!((val) & (((bit) << 16))))
+
+#define FORCEWAKE_RENDER_GEN9_REG 0xa278
+#define FORCEWAKE_ACK_RENDER_GEN9_REG 0x0D84
+#define FORCEWAKE_BLITTER_GEN9_REG 0xa188
+#define FORCEWAKE_ACK_BLITTER_GEN9_REG 0x130044
+#define FORCEWAKE_MEDIA_GEN9_REG 0xa270
+#define FORCEWAKE_ACK_MEDIA_GEN9_REG 0x0D88
+#define FORCEWAKE_ACK_HSW_REG 0x130044
+
+#define RB_HEAD_OFF_MASK ((1U << 21) - (1U << 2))
+#define RB_TAIL_OFF_MASK ((1U << 21) - (1U << 3))
+#define RB_TAIL_SIZE_MASK ((1U << 21) - (1U << 12))
+#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE)
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c
new file mode 100644
index 000000000000..44136b1f3aab
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/render.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+struct render_mmio {
+ int ring_id;
+ i915_reg_t reg;
+ u32 mask;
+ bool in_context;
+ u32 value;
+};
+
+static struct render_mmio gen8_render_mmio_list[] = {
+ {RCS, _MMIO(0x229c), 0xffff, false},
+ {RCS, _MMIO(0x2248), 0x0, false},
+ {RCS, _MMIO(0x2098), 0x0, false},
+ {RCS, _MMIO(0x20c0), 0xffff, true},
+ {RCS, _MMIO(0x24d0), 0, false},
+ {RCS, _MMIO(0x24d4), 0, false},
+ {RCS, _MMIO(0x24d8), 0, false},
+ {RCS, _MMIO(0x24dc), 0, false},
+ {RCS, _MMIO(0x7004), 0xffff, true},
+ {RCS, _MMIO(0x7008), 0xffff, true},
+ {RCS, _MMIO(0x7000), 0xffff, true},
+ {RCS, _MMIO(0x7010), 0xffff, true},
+ {RCS, _MMIO(0x7300), 0xffff, true},
+ {RCS, _MMIO(0x83a4), 0xffff, true},
+
+ {BCS, _MMIO(0x2229c), 0xffff, false},
+ {BCS, _MMIO(0x2209c), 0xffff, false},
+ {BCS, _MMIO(0x220c0), 0xffff, false},
+ {BCS, _MMIO(0x22098), 0x0, false},
+ {BCS, _MMIO(0x22028), 0x0, false},
+};
+
+static struct render_mmio gen9_render_mmio_list[] = {
+ {RCS, _MMIO(0x229c), 0xffff, false},
+ {RCS, _MMIO(0x2248), 0x0, false},
+ {RCS, _MMIO(0x2098), 0x0, false},
+ {RCS, _MMIO(0x20c0), 0xffff, true},
+ {RCS, _MMIO(0x24d0), 0, false},
+ {RCS, _MMIO(0x24d4), 0, false},
+ {RCS, _MMIO(0x24d8), 0, false},
+ {RCS, _MMIO(0x24dc), 0, false},
+ {RCS, _MMIO(0x7004), 0xffff, true},
+ {RCS, _MMIO(0x7008), 0xffff, true},
+ {RCS, _MMIO(0x7000), 0xffff, true},
+ {RCS, _MMIO(0x7010), 0xffff, true},
+ {RCS, _MMIO(0x7300), 0xffff, true},
+ {RCS, _MMIO(0x83a4), 0xffff, true},
+
+ {RCS, _MMIO(0x40e0), 0, false},
+ {RCS, _MMIO(0x40e4), 0, false},
+ {RCS, _MMIO(0x2580), 0xffff, true},
+ {RCS, _MMIO(0x7014), 0xffff, true},
+ {RCS, _MMIO(0x20ec), 0xffff, false},
+ {RCS, _MMIO(0xb118), 0, false},
+ {RCS, _MMIO(0xe100), 0xffff, true},
+ {RCS, _MMIO(0xe180), 0xffff, true},
+ {RCS, _MMIO(0xe184), 0xffff, true},
+ {RCS, _MMIO(0xe188), 0xffff, true},
+ {RCS, _MMIO(0xe194), 0xffff, true},
+ {RCS, _MMIO(0x4de0), 0, false},
+ {RCS, _MMIO(0x4de4), 0, false},
+ {RCS, _MMIO(0x4de8), 0, false},
+ {RCS, _MMIO(0x4dec), 0, false},
+ {RCS, _MMIO(0x4df0), 0, false},
+ {RCS, _MMIO(0x4df4), 0, false},
+
+ {BCS, _MMIO(0x2229c), 0xffff, false},
+ {BCS, _MMIO(0x2209c), 0xffff, false},
+ {BCS, _MMIO(0x220c0), 0xffff, false},
+ {BCS, _MMIO(0x22098), 0x0, false},
+ {BCS, _MMIO(0x22028), 0x0, false},
+
+ {VCS2, _MMIO(0x1c028), 0xffff, false},
+
+ {VECS, _MMIO(0x1a028), 0xffff, false},
+};
+
+static u32 gen9_render_mocs[I915_NUM_ENGINES][64];
+static u32 gen9_render_mocs_L3[32];
+
+static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ enum forcewake_domains fw;
+ i915_reg_t reg;
+ u32 regs[] = {
+ [RCS] = 0x4260,
+ [VCS] = 0x4264,
+ [VCS2] = 0x4268,
+ [BCS] = 0x426c,
+ [VECS] = 0x4270,
+ };
+
+ if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+ return;
+
+ if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending))
+ return;
+
+ reg = _MMIO(regs[ring_id]);
+
+ /* WaForceWakeRenderDuringMmioTLBInvalidate:skl
+ * we need to put a forcewake when invalidating RCS TLB caches,
+ * otherwise device can go to RC6 state and interrupt invalidation
+ * process
+ */
+ fw = intel_uncore_forcewake_for_reg(dev_priv, reg,
+ FW_REG_READ | FW_REG_WRITE);
+ if (ring_id == RCS && IS_SKYLAKE(dev_priv))
+ fw |= FORCEWAKE_RENDER;
+
+ intel_uncore_forcewake_get(dev_priv, fw);
+
+ I915_WRITE_FW(reg, 0x1);
+
+ if (wait_for_atomic((I915_READ_FW(reg) == 0), 50))
+ gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id);
+ else
+ vgpu_vreg(vgpu, regs[ring_id]) = 0;
+
+ intel_uncore_forcewake_put(dev_priv, fw);
+
+ gvt_dbg_core("invalidate TLB for ring %d\n", ring_id);
+}
+
+static void load_mocs(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ i915_reg_t offset, l3_offset;
+ u32 regs[] = {
+ [RCS] = 0xc800,
+ [VCS] = 0xc900,
+ [VCS2] = 0xca00,
+ [BCS] = 0xcc00,
+ [VECS] = 0xcb00,
+ };
+ int i;
+
+ if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+ return;
+
+ if (!IS_SKYLAKE(dev_priv))
+ return;
+
+ offset.reg = regs[ring_id];
+ for (i = 0; i < 64; i++) {
+ gen9_render_mocs[ring_id][i] = I915_READ(offset);
+ I915_WRITE(offset, vgpu_vreg(vgpu, offset));
+ POSTING_READ(offset);
+ offset.reg += 4;
+ }
+
+ if (ring_id == RCS) {
+ l3_offset.reg = 0xb020;
+ for (i = 0; i < 32; i++) {
+ gen9_render_mocs_L3[i] = I915_READ(l3_offset);
+ I915_WRITE(l3_offset, vgpu_vreg(vgpu, offset));
+ POSTING_READ(l3_offset);
+ l3_offset.reg += 4;
+ }
+ }
+}
+
+static void restore_mocs(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ i915_reg_t offset, l3_offset;
+ u32 regs[] = {
+ [RCS] = 0xc800,
+ [VCS] = 0xc900,
+ [VCS2] = 0xca00,
+ [BCS] = 0xcc00,
+ [VECS] = 0xcb00,
+ };
+ int i;
+
+ if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+ return;
+
+ if (!IS_SKYLAKE(dev_priv))
+ return;
+
+ offset.reg = regs[ring_id];
+ for (i = 0; i < 64; i++) {
+ vgpu_vreg(vgpu, offset) = I915_READ(offset);
+ I915_WRITE(offset, gen9_render_mocs[ring_id][i]);
+ POSTING_READ(offset);
+ offset.reg += 4;
+ }
+
+ if (ring_id == RCS) {
+ l3_offset.reg = 0xb020;
+ for (i = 0; i < 32; i++) {
+ vgpu_vreg(vgpu, l3_offset) = I915_READ(l3_offset);
+ I915_WRITE(l3_offset, gen9_render_mocs_L3[i]);
+ POSTING_READ(l3_offset);
+ l3_offset.reg += 4;
+ }
+ }
+}
+
+void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct render_mmio *mmio;
+ u32 v;
+ int i, array_size;
+
+ if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
+ mmio = gen9_render_mmio_list;
+ array_size = ARRAY_SIZE(gen9_render_mmio_list);
+ load_mocs(vgpu, ring_id);
+ } else {
+ mmio = gen8_render_mmio_list;
+ array_size = ARRAY_SIZE(gen8_render_mmio_list);
+ }
+
+ for (i = 0; i < array_size; i++, mmio++) {
+ if (mmio->ring_id != ring_id)
+ continue;
+
+ mmio->value = I915_READ(mmio->reg);
+ if (mmio->mask)
+ v = vgpu_vreg(vgpu, mmio->reg) | (mmio->mask << 16);
+ else
+ v = vgpu_vreg(vgpu, mmio->reg);
+
+ I915_WRITE(mmio->reg, v);
+ POSTING_READ(mmio->reg);
+
+ gvt_dbg_render("load reg %x old %x new %x\n",
+ i915_mmio_reg_offset(mmio->reg),
+ mmio->value, v);
+ }
+ handle_tlb_pending_event(vgpu, ring_id);
+}
+
+void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct render_mmio *mmio;
+ u32 v;
+ int i, array_size;
+
+ if (IS_SKYLAKE(dev_priv)) {
+ mmio = gen9_render_mmio_list;
+ array_size = ARRAY_SIZE(gen9_render_mmio_list);
+ restore_mocs(vgpu, ring_id);
+ } else {
+ mmio = gen8_render_mmio_list;
+ array_size = ARRAY_SIZE(gen8_render_mmio_list);
+ }
+
+ for (i = 0; i < array_size; i++, mmio++) {
+ if (mmio->ring_id != ring_id)
+ continue;
+
+ vgpu_vreg(vgpu, mmio->reg) = I915_READ(mmio->reg);
+
+ if (mmio->mask) {
+ vgpu_vreg(vgpu, mmio->reg) &= ~(mmio->mask << 16);
+ v = mmio->value | (mmio->mask << 16);
+ } else
+ v = mmio->value;
+
+ I915_WRITE(mmio->reg, v);
+ POSTING_READ(mmio->reg);
+
+ gvt_dbg_render("restore reg %x old %x new %x\n",
+ i915_mmio_reg_offset(mmio->reg),
+ mmio->value, v);
+ }
+}
diff --git a/drivers/gpu/drm/i915/gvt/render.h b/drivers/gpu/drm/i915/gvt/render.h
new file mode 100644
index 000000000000..dac1a3cc458b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/render.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Changbin Du <changbin.du@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#ifndef __GVT_RENDER_H__
+#define __GVT_RENDER_H__
+
+void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id);
+
+void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c
new file mode 100644
index 000000000000..678b0be85376
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/sched_policy.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Anhua Xu
+ * Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu)
+{
+ enum intel_engine_id i;
+ struct intel_engine_cs *engine;
+
+ for_each_engine(engine, vgpu->gvt->dev_priv, i) {
+ if (!list_empty(workload_q_head(vgpu, i)))
+ return true;
+ }
+
+ return false;
+}
+
+static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
+{
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ enum intel_engine_id i;
+ struct intel_engine_cs *engine;
+
+ /* no target to schedule */
+ if (!scheduler->next_vgpu)
+ return;
+
+ gvt_dbg_sched("try to schedule next vgpu %d\n",
+ scheduler->next_vgpu->id);
+
+ /*
+ * after the flag is set, workload dispatch thread will
+ * stop dispatching workload for current vgpu
+ */
+ scheduler->need_reschedule = true;
+
+ /* still have uncompleted workload? */
+ for_each_engine(engine, gvt->dev_priv, i) {
+ if (scheduler->current_workload[i]) {
+ gvt_dbg_sched("still have running workload\n");
+ return;
+ }
+ }
+
+ gvt_dbg_sched("switch to next vgpu %d\n",
+ scheduler->next_vgpu->id);
+
+ /* switch current vgpu */
+ scheduler->current_vgpu = scheduler->next_vgpu;
+ scheduler->next_vgpu = NULL;
+
+ scheduler->need_reschedule = false;
+
+ /* wake up workload dispatch thread */
+ for_each_engine(engine, gvt->dev_priv, i)
+ wake_up(&scheduler->waitq[i]);
+}
+
+struct tbs_vgpu_data {
+ struct list_head list;
+ struct intel_vgpu *vgpu;
+ /* put some per-vgpu sched stats here */
+};
+
+struct tbs_sched_data {
+ struct intel_gvt *gvt;
+ struct delayed_work work;
+ unsigned long period;
+ struct list_head runq_head;
+};
+
+#define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000)
+
+static void tbs_sched_func(struct work_struct *work)
+{
+ struct tbs_sched_data *sched_data = container_of(work,
+ struct tbs_sched_data, work.work);
+ struct tbs_vgpu_data *vgpu_data;
+
+ struct intel_gvt *gvt = sched_data->gvt;
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+ struct intel_vgpu *vgpu = NULL;
+ struct list_head *pos, *head;
+
+ mutex_lock(&gvt->lock);
+
+ /* no vgpu or has already had a target */
+ if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
+ goto out;
+
+ if (scheduler->current_vgpu) {
+ vgpu_data = scheduler->current_vgpu->sched_data;
+ head = &vgpu_data->list;
+ } else {
+ gvt_dbg_sched("no current vgpu search from q head\n");
+ head = &sched_data->runq_head;
+ }
+
+ /* search a vgpu with pending workload */
+ list_for_each(pos, head) {
+ if (pos == &sched_data->runq_head)
+ continue;
+
+ vgpu_data = container_of(pos, struct tbs_vgpu_data, list);
+ if (!vgpu_has_pending_workload(vgpu_data->vgpu))
+ continue;
+
+ vgpu = vgpu_data->vgpu;
+ break;
+ }
+
+ if (vgpu) {
+ scheduler->next_vgpu = vgpu;
+ gvt_dbg_sched("pick next vgpu %d\n", vgpu->id);
+ }
+out:
+ if (scheduler->next_vgpu) {
+ gvt_dbg_sched("try to schedule next vgpu %d\n",
+ scheduler->next_vgpu->id);
+ try_to_schedule_next_vgpu(gvt);
+ }
+
+ /*
+ * still have vgpu on runq
+ * or last schedule haven't finished due to running workload
+ */
+ if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
+ schedule_delayed_work(&sched_data->work, sched_data->period);
+
+ mutex_unlock(&gvt->lock);
+}
+
+static int tbs_sched_init(struct intel_gvt *gvt)
+{
+ struct intel_gvt_workload_scheduler *scheduler =
+ &gvt->scheduler;
+
+ struct tbs_sched_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&data->runq_head);
+ INIT_DELAYED_WORK(&data->work, tbs_sched_func);
+ data->period = GVT_DEFAULT_TIME_SLICE;
+ data->gvt = gvt;
+
+ scheduler->sched_data = data;
+ return 0;
+}
+
+static void tbs_sched_clean(struct intel_gvt *gvt)
+{
+ struct intel_gvt_workload_scheduler *scheduler =
+ &gvt->scheduler;
+ struct tbs_sched_data *data = scheduler->sched_data;
+
+ cancel_delayed_work(&data->work);
+ kfree(data);
+ scheduler->sched_data = NULL;
+}
+
+static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu)
+{
+ struct tbs_vgpu_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->vgpu = vgpu;
+ INIT_LIST_HEAD(&data->list);
+
+ vgpu->sched_data = data;
+ return 0;
+}
+
+static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu)
+{
+ kfree(vgpu->sched_data);
+ vgpu->sched_data = NULL;
+}
+
+static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
+{
+ struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data;
+ struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
+
+ if (!list_empty(&vgpu_data->list))
+ return;
+
+ list_add_tail(&vgpu_data->list, &sched_data->runq_head);
+ schedule_delayed_work(&sched_data->work, sched_data->period);
+}
+
+static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu)
+{
+ struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
+
+ list_del_init(&vgpu_data->list);
+}
+
+static struct intel_gvt_sched_policy_ops tbs_schedule_ops = {
+ .init = tbs_sched_init,
+ .clean = tbs_sched_clean,
+ .init_vgpu = tbs_sched_init_vgpu,
+ .clean_vgpu = tbs_sched_clean_vgpu,
+ .start_schedule = tbs_sched_start_schedule,
+ .stop_schedule = tbs_sched_stop_schedule,
+};
+
+int intel_gvt_init_sched_policy(struct intel_gvt *gvt)
+{
+ gvt->scheduler.sched_ops = &tbs_schedule_ops;
+
+ return gvt->scheduler.sched_ops->init(gvt);
+}
+
+void intel_gvt_clean_sched_policy(struct intel_gvt *gvt)
+{
+ gvt->scheduler.sched_ops->clean(gvt);
+}
+
+int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu)
+{
+ return vgpu->gvt->scheduler.sched_ops->init_vgpu(vgpu);
+}
+
+void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu)
+{
+ vgpu->gvt->scheduler.sched_ops->clean_vgpu(vgpu);
+}
+
+void intel_vgpu_start_schedule(struct intel_vgpu *vgpu)
+{
+ gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id);
+
+ vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu);
+}
+
+void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt_workload_scheduler *scheduler =
+ &vgpu->gvt->scheduler;
+
+ gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id);
+
+ scheduler->sched_ops->stop_schedule(vgpu);
+
+ if (scheduler->next_vgpu == vgpu)
+ scheduler->next_vgpu = NULL;
+
+ if (scheduler->current_vgpu == vgpu) {
+ /* stop workload dispatching */
+ scheduler->need_reschedule = true;
+ scheduler->current_vgpu = NULL;
+ }
+}
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.h b/drivers/gpu/drm/i915/gvt/sched_policy.h
new file mode 100644
index 000000000000..bb8b9097e41a
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/sched_policy.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Anhua Xu
+ * Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef __GVT_SCHED_POLICY__
+#define __GVT_SCHED_POLICY__
+
+struct intel_gvt_sched_policy_ops {
+ int (*init)(struct intel_gvt *gvt);
+ void (*clean)(struct intel_gvt *gvt);
+ int (*init_vgpu)(struct intel_vgpu *vgpu);
+ void (*clean_vgpu)(struct intel_vgpu *vgpu);
+ void (*start_schedule)(struct intel_vgpu *vgpu);
+ void (*stop_schedule)(struct intel_vgpu *vgpu);
+};
+
+int intel_gvt_init_sched_policy(struct intel_gvt *gvt);
+
+void intel_gvt_clean_sched_policy(struct intel_gvt *gvt);
+
+int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu);
+
+void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu);
+
+void intel_vgpu_start_schedule(struct intel_vgpu *vgpu);
+
+void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
new file mode 100644
index 000000000000..4db242250235
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Chanbin Du <changbin.du@intel.com>
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <linux/kthread.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define RING_CTX_OFF(x) \
+ offsetof(struct execlist_ring_context, x)
+
+static void set_context_pdp_root_pointer(
+ struct execlist_ring_context *ring_context,
+ u32 pdp[8])
+{
+ struct execlist_mmio_pair *pdp_pair = &ring_context->pdp3_UDW;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ pdp_pair[i].val = pdp[7 - i];
+}
+
+static int populate_shadow_context(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ int ring_id = workload->ring_id;
+ struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+ struct drm_i915_gem_object *ctx_obj =
+ shadow_ctx->engine[ring_id].state->obj;
+ struct execlist_ring_context *shadow_ring_context;
+ struct page *page;
+ void *dst;
+ unsigned long context_gpa, context_page_num;
+ int i;
+
+ gvt_dbg_sched("ring id %d workload lrca %x", ring_id,
+ workload->ctx_desc.lrca);
+
+ context_page_num = intel_lr_context_size(
+ gvt->dev_priv->engine[ring_id]);
+
+ context_page_num = context_page_num >> PAGE_SHIFT;
+
+ if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS)
+ context_page_num = 19;
+
+ i = 2;
+
+ while (i < context_page_num) {
+ context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+ (u32)((workload->ctx_desc.lrca + i) <<
+ GTT_PAGE_SHIFT));
+ if (context_gpa == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("Invalid guest context descriptor\n");
+ return -EINVAL;
+ }
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i);
+ dst = kmap(page);
+ intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst,
+ GTT_PAGE_SIZE);
+ kunmap(page);
+ i++;
+ }
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ shadow_ring_context = kmap(page);
+
+#define COPY_REG(name) \
+ intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \
+ + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
+
+ COPY_REG(ctx_ctrl);
+ COPY_REG(ctx_timestamp);
+
+ if (ring_id == RCS) {
+ COPY_REG(bb_per_ctx_ptr);
+ COPY_REG(rcs_indirect_ctx);
+ COPY_REG(rcs_indirect_ctx_offset);
+ }
+#undef COPY_REG
+
+ set_context_pdp_root_pointer(shadow_ring_context,
+ workload->shadow_mm->shadow_page_table);
+
+ intel_gvt_hypervisor_read_gpa(vgpu,
+ workload->ring_context_gpa +
+ sizeof(*shadow_ring_context),
+ (void *)shadow_ring_context +
+ sizeof(*shadow_ring_context),
+ GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
+
+ kunmap(page);
+ return 0;
+}
+
+static int shadow_context_status_change(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct intel_vgpu *vgpu = container_of(nb,
+ struct intel_vgpu, shadow_ctx_notifier_block);
+ struct drm_i915_gem_request *req =
+ (struct drm_i915_gem_request *)data;
+ struct intel_gvt_workload_scheduler *scheduler =
+ &vgpu->gvt->scheduler;
+ struct intel_vgpu_workload *workload =
+ scheduler->current_workload[req->engine->id];
+
+ switch (action) {
+ case INTEL_CONTEXT_SCHEDULE_IN:
+ intel_gvt_load_render_mmio(workload->vgpu,
+ workload->ring_id);
+ atomic_set(&workload->shadow_ctx_active, 1);
+ break;
+ case INTEL_CONTEXT_SCHEDULE_OUT:
+ intel_gvt_restore_render_mmio(workload->vgpu,
+ workload->ring_id);
+ atomic_set(&workload->shadow_ctx_active, 0);
+ break;
+ default:
+ WARN_ON(1);
+ return NOTIFY_OK;
+ }
+ wake_up(&workload->shadow_ctx_status_wq);
+ return NOTIFY_OK;
+}
+
+static int dispatch_workload(struct intel_vgpu_workload *workload)
+{
+ int ring_id = workload->ring_id;
+ struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+ struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
+ struct drm_i915_gem_request *rq;
+ int ret;
+
+ gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n",
+ ring_id, workload);
+
+ shadow_ctx->desc_template = workload->ctx_desc.addressing_mode <<
+ GEN8_CTX_ADDRESSING_MODE_SHIFT;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+
+ rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
+ if (IS_ERR(rq)) {
+ gvt_err("fail to allocate gem request\n");
+ ret = PTR_ERR(rq);
+ goto out;
+ }
+
+ gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq);
+
+ workload->req = i915_gem_request_get(rq);
+
+ ret = intel_gvt_scan_and_shadow_workload(workload);
+ if (ret)
+ goto out;
+
+ ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
+ if (ret)
+ goto out;
+
+ ret = populate_shadow_context(workload);
+ if (ret)
+ goto out;
+
+ if (workload->prepare) {
+ ret = workload->prepare(workload);
+ if (ret)
+ goto out;
+ }
+
+ gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
+ ring_id, workload->req);
+
+ ret = 0;
+ workload->dispatched = true;
+out:
+ if (ret)
+ workload->status = ret;
+
+ if (!IS_ERR_OR_NULL(rq))
+ i915_add_request_no_flush(rq);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ return ret;
+}
+
+static struct intel_vgpu_workload *pick_next_workload(
+ struct intel_gvt *gvt, int ring_id)
+{
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ struct intel_vgpu_workload *workload = NULL;
+
+ mutex_lock(&gvt->lock);
+
+ /*
+ * no current vgpu / will be scheduled out / no workload
+ * bail out
+ */
+ if (!scheduler->current_vgpu) {
+ gvt_dbg_sched("ring id %d stop - no current vgpu\n", ring_id);
+ goto out;
+ }
+
+ if (scheduler->need_reschedule) {
+ gvt_dbg_sched("ring id %d stop - will reschedule\n", ring_id);
+ goto out;
+ }
+
+ if (list_empty(workload_q_head(scheduler->current_vgpu, ring_id))) {
+ gvt_dbg_sched("ring id %d stop - no available workload\n",
+ ring_id);
+ goto out;
+ }
+
+ /*
+ * still have current workload, maybe the workload disptacher
+ * fail to submit it for some reason, resubmit it.
+ */
+ if (scheduler->current_workload[ring_id]) {
+ workload = scheduler->current_workload[ring_id];
+ gvt_dbg_sched("ring id %d still have current workload %p\n",
+ ring_id, workload);
+ goto out;
+ }
+
+ /*
+ * pick a workload as current workload
+ * once current workload is set, schedule policy routines
+ * will wait the current workload is finished when trying to
+ * schedule out a vgpu.
+ */
+ scheduler->current_workload[ring_id] = container_of(
+ workload_q_head(scheduler->current_vgpu, ring_id)->next,
+ struct intel_vgpu_workload, list);
+
+ workload = scheduler->current_workload[ring_id];
+
+ gvt_dbg_sched("ring id %d pick new workload %p\n", ring_id, workload);
+
+ atomic_inc(&workload->vgpu->running_workload_num);
+out:
+ mutex_unlock(&gvt->lock);
+ return workload;
+}
+
+static void update_guest_context(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ struct intel_gvt *gvt = vgpu->gvt;
+ int ring_id = workload->ring_id;
+ struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+ struct drm_i915_gem_object *ctx_obj =
+ shadow_ctx->engine[ring_id].state->obj;
+ struct execlist_ring_context *shadow_ring_context;
+ struct page *page;
+ void *src;
+ unsigned long context_gpa, context_page_num;
+ int i;
+
+ gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id,
+ workload->ctx_desc.lrca);
+
+ context_page_num = intel_lr_context_size(
+ gvt->dev_priv->engine[ring_id]);
+
+ context_page_num = context_page_num >> PAGE_SHIFT;
+
+ if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS)
+ context_page_num = 19;
+
+ i = 2;
+
+ while (i < context_page_num) {
+ context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+ (u32)((workload->ctx_desc.lrca + i) <<
+ GTT_PAGE_SHIFT));
+ if (context_gpa == INTEL_GVT_INVALID_ADDR) {
+ gvt_err("invalid guest context descriptor\n");
+ return;
+ }
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i);
+ src = kmap(page);
+ intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src,
+ GTT_PAGE_SIZE);
+ kunmap(page);
+ i++;
+ }
+
+ intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa +
+ RING_CTX_OFF(ring_header.val), &workload->rb_tail, 4);
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ shadow_ring_context = kmap(page);
+
+#define COPY_REG(name) \
+ intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + \
+ RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
+
+ COPY_REG(ctx_ctrl);
+ COPY_REG(ctx_timestamp);
+
+#undef COPY_REG
+
+ intel_gvt_hypervisor_write_gpa(vgpu,
+ workload->ring_context_gpa +
+ sizeof(*shadow_ring_context),
+ (void *)shadow_ring_context +
+ sizeof(*shadow_ring_context),
+ GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
+
+ kunmap(page);
+}
+
+static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
+{
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ struct intel_vgpu_workload *workload;
+ int event;
+
+ mutex_lock(&gvt->lock);
+
+ workload = scheduler->current_workload[ring_id];
+
+ if (!workload->status && !workload->vgpu->resetting) {
+ wait_event(workload->shadow_ctx_status_wq,
+ !atomic_read(&workload->shadow_ctx_active));
+
+ update_guest_context(workload);
+
+ for_each_set_bit(event, workload->pending_events,
+ INTEL_GVT_EVENT_MAX)
+ intel_vgpu_trigger_virtual_event(workload->vgpu,
+ event);
+ }
+
+ gvt_dbg_sched("ring id %d complete workload %p status %d\n",
+ ring_id, workload, workload->status);
+
+ scheduler->current_workload[ring_id] = NULL;
+
+ atomic_dec(&workload->vgpu->running_workload_num);
+
+ list_del_init(&workload->list);
+ workload->complete(workload);
+
+ wake_up(&scheduler->workload_complete_wq);
+ mutex_unlock(&gvt->lock);
+}
+
+struct workload_thread_param {
+ struct intel_gvt *gvt;
+ int ring_id;
+};
+
+static DEFINE_MUTEX(scheduler_mutex);
+
+static int workload_thread(void *priv)
+{
+ struct workload_thread_param *p = (struct workload_thread_param *)priv;
+ struct intel_gvt *gvt = p->gvt;
+ int ring_id = p->ring_id;
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ struct intel_vgpu_workload *workload = NULL;
+ long lret;
+ int ret;
+ bool need_force_wake = IS_SKYLAKE(gvt->dev_priv);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+ kfree(p);
+
+ gvt_dbg_core("workload thread for ring %d started\n", ring_id);
+
+ while (!kthread_should_stop()) {
+ add_wait_queue(&scheduler->waitq[ring_id], &wait);
+ do {
+ workload = pick_next_workload(gvt, ring_id);
+ if (workload)
+ break;
+ wait_woken(&wait, TASK_INTERRUPTIBLE,
+ MAX_SCHEDULE_TIMEOUT);
+ } while (!kthread_should_stop());
+ remove_wait_queue(&scheduler->waitq[ring_id], &wait);
+
+ if (!workload)
+ break;
+
+ mutex_lock(&scheduler_mutex);
+
+ gvt_dbg_sched("ring id %d next workload %p vgpu %d\n",
+ workload->ring_id, workload,
+ workload->vgpu->id);
+
+ intel_runtime_pm_get(gvt->dev_priv);
+
+ gvt_dbg_sched("ring id %d will dispatch workload %p\n",
+ workload->ring_id, workload);
+
+ if (need_force_wake)
+ intel_uncore_forcewake_get(gvt->dev_priv,
+ FORCEWAKE_ALL);
+
+ mutex_lock(&gvt->lock);
+ ret = dispatch_workload(workload);
+ mutex_unlock(&gvt->lock);
+
+ if (ret) {
+ gvt_err("fail to dispatch workload, skip\n");
+ goto complete;
+ }
+
+ gvt_dbg_sched("ring id %d wait workload %p\n",
+ workload->ring_id, workload);
+
+ lret = i915_wait_request(workload->req,
+ 0, MAX_SCHEDULE_TIMEOUT);
+ if (lret < 0) {
+ workload->status = lret;
+ gvt_err("fail to wait workload, skip\n");
+ } else {
+ workload->status = 0;
+ }
+
+complete:
+ gvt_dbg_sched("will complete workload %p\n, status: %d\n",
+ workload, workload->status);
+
+ complete_current_workload(gvt, ring_id);
+
+ if (workload->req)
+ i915_gem_request_put(fetch_and_zero(&workload->req));
+
+ if (need_force_wake)
+ intel_uncore_forcewake_put(gvt->dev_priv,
+ FORCEWAKE_ALL);
+
+ intel_runtime_pm_put(gvt->dev_priv);
+
+ mutex_unlock(&scheduler_mutex);
+
+ }
+ return 0;
+}
+
+void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+ if (atomic_read(&vgpu->running_workload_num)) {
+ gvt_dbg_sched("wait vgpu idle\n");
+
+ wait_event(scheduler->workload_complete_wq,
+ !atomic_read(&vgpu->running_workload_num));
+ }
+}
+
+void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
+{
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ int i;
+
+ gvt_dbg_core("clean workload scheduler\n");
+
+ for (i = 0; i < I915_NUM_ENGINES; i++) {
+ if (scheduler->thread[i]) {
+ kthread_stop(scheduler->thread[i]);
+ scheduler->thread[i] = NULL;
+ }
+ }
+}
+
+int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
+{
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+ struct workload_thread_param *param = NULL;
+ int ret;
+ int i;
+
+ gvt_dbg_core("init workload scheduler\n");
+
+ init_waitqueue_head(&scheduler->workload_complete_wq);
+
+ for (i = 0; i < I915_NUM_ENGINES; i++) {
+ /* check ring mask at init time */
+ if (!HAS_ENGINE(gvt->dev_priv, i))
+ continue;
+
+ init_waitqueue_head(&scheduler->waitq[i]);
+
+ param = kzalloc(sizeof(*param), GFP_KERNEL);
+ if (!param) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ param->gvt = gvt;
+ param->ring_id = i;
+
+ scheduler->thread[i] = kthread_run(workload_thread, param,
+ "gvt workload %d", i);
+ if (IS_ERR(scheduler->thread[i])) {
+ gvt_err("fail to create workload thread\n");
+ ret = PTR_ERR(scheduler->thread[i]);
+ goto err;
+ }
+ }
+ return 0;
+err:
+ intel_gvt_clean_workload_scheduler(gvt);
+ kfree(param);
+ param = NULL;
+ return ret;
+}
+
+void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+ atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier,
+ &vgpu->shadow_ctx_notifier_block);
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+
+ /* a little hacky to mark as ctx closed */
+ vgpu->shadow_ctx->closed = true;
+ i915_gem_context_put(vgpu->shadow_ctx);
+
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)
+{
+ atomic_set(&vgpu->running_workload_num, 0);
+
+ vgpu->shadow_ctx = i915_gem_context_create_gvt(
+ &vgpu->gvt->dev_priv->drm);
+ if (IS_ERR(vgpu->shadow_ctx))
+ return PTR_ERR(vgpu->shadow_ctx);
+
+ vgpu->shadow_ctx->engine[RCS].initialised = true;
+
+ vgpu->shadow_ctx_notifier_block.notifier_call =
+ shadow_context_status_change;
+
+ atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier,
+ &vgpu->shadow_ctx_notifier_block);
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h
new file mode 100644
index 000000000000..3b30c28bff51
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/scheduler.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ * Ping Gao <ping.a.gao@intel.com>
+ * Tina Zhang <tina.zhang@intel.com>
+ * Chanbin Du <changbin.du@intel.com>
+ * Min He <min.he@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#ifndef _GVT_SCHEDULER_H_
+#define _GVT_SCHEDULER_H_
+
+struct intel_gvt_workload_scheduler {
+ struct intel_vgpu *current_vgpu;
+ struct intel_vgpu *next_vgpu;
+ struct intel_vgpu_workload *current_workload[I915_NUM_ENGINES];
+ bool need_reschedule;
+
+ wait_queue_head_t workload_complete_wq;
+ struct task_struct *thread[I915_NUM_ENGINES];
+ wait_queue_head_t waitq[I915_NUM_ENGINES];
+
+ void *sched_data;
+ struct intel_gvt_sched_policy_ops *sched_ops;
+};
+
+#define INDIRECT_CTX_ADDR_MASK 0xffffffc0
+#define INDIRECT_CTX_SIZE_MASK 0x3f
+struct shadow_indirect_ctx {
+ struct drm_i915_gem_object *obj;
+ unsigned long guest_gma;
+ unsigned long shadow_gma;
+ void *shadow_va;
+ uint32_t size;
+};
+
+#define PER_CTX_ADDR_MASK 0xfffff000
+struct shadow_per_ctx {
+ unsigned long guest_gma;
+ unsigned long shadow_gma;
+};
+
+struct intel_shadow_wa_ctx {
+ struct intel_vgpu_workload *workload;
+ struct shadow_indirect_ctx indirect_ctx;
+ struct shadow_per_ctx per_ctx;
+
+};
+
+struct intel_vgpu_workload {
+ struct intel_vgpu *vgpu;
+ int ring_id;
+ struct drm_i915_gem_request *req;
+ /* if this workload has been dispatched to i915? */
+ bool dispatched;
+ int status;
+
+ struct intel_vgpu_mm *shadow_mm;
+
+ /* different submission model may need different handler */
+ int (*prepare)(struct intel_vgpu_workload *);
+ int (*complete)(struct intel_vgpu_workload *);
+ struct list_head list;
+
+ DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX);
+ void *shadow_ring_buffer_va;
+
+ /* execlist context information */
+ struct execlist_ctx_descriptor_format ctx_desc;
+ struct execlist_ring_context *ring_context;
+ unsigned long rb_head, rb_tail, rb_ctl, rb_start, rb_len;
+ bool restore_inhibit;
+ struct intel_vgpu_elsp_dwords elsp_dwords;
+ bool emulate_schedule_in;
+ atomic_t shadow_ctx_active;
+ wait_queue_head_t shadow_ctx_status_wq;
+ u64 ring_context_gpa;
+
+ /* shadow batch buffer */
+ struct list_head shadow_bb;
+ struct intel_shadow_wa_ctx wa_ctx;
+};
+
+/* Intel shadow batch buffer is a i915 gem object */
+struct intel_shadow_bb_entry {
+ struct list_head list;
+ struct drm_i915_gem_object *obj;
+ void *va;
+ unsigned long len;
+ void *bb_start_cmd_va;
+};
+
+#define workload_q_head(vgpu, ring_id) \
+ (&(vgpu->workload_q_head[ring_id]))
+
+#define queue_workload(workload) do { \
+ list_add_tail(&workload->list, \
+ workload_q_head(workload->vgpu, workload->ring_id)); \
+ wake_up(&workload->vgpu->gvt-> \
+ scheduler.waitq[workload->ring_id]); \
+} while (0)
+
+int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt);
+
+void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt);
+
+void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu);
+
+int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu);
+
+void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h
new file mode 100644
index 000000000000..53a2d10cf3f1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/trace.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright © 2011-2016 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:
+ * Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#if !defined(_GVT_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _GVT_TRACE_H_
+
+#include <linux/types.h>
+#include <linux/stringify.h>
+#include <linux/tracepoint.h>
+#include <asm/tsc.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM gvt
+
+TRACE_EVENT(spt_alloc,
+ TP_PROTO(int id, void *spt, int type, unsigned long mfn,
+ unsigned long gpt_gfn),
+
+ TP_ARGS(id, spt, type, mfn, gpt_gfn),
+
+ TP_STRUCT__entry(
+ __field(int, id)
+ __field(void *, spt)
+ __field(int, type)
+ __field(unsigned long, mfn)
+ __field(unsigned long, gpt_gfn)
+ ),
+
+ TP_fast_assign(
+ __entry->id = id;
+ __entry->spt = spt;
+ __entry->type = type;
+ __entry->mfn = mfn;
+ __entry->gpt_gfn = gpt_gfn;
+ ),
+
+ TP_printk("VM%d [alloc] spt %p type %d mfn 0x%lx gfn 0x%lx\n",
+ __entry->id,
+ __entry->spt,
+ __entry->type,
+ __entry->mfn,
+ __entry->gpt_gfn)
+);
+
+TRACE_EVENT(spt_free,
+ TP_PROTO(int id, void *spt, int type),
+
+ TP_ARGS(id, spt, type),
+
+ TP_STRUCT__entry(
+ __field(int, id)
+ __field(void *, spt)
+ __field(int, type)
+ ),
+
+ TP_fast_assign(
+ __entry->id = id;
+ __entry->spt = spt;
+ __entry->type = type;
+ ),
+
+ TP_printk("VM%u [free] spt %p type %d\n",
+ __entry->id,
+ __entry->spt,
+ __entry->type)
+);
+
+#define MAX_BUF_LEN 256
+
+TRACE_EVENT(gma_index,
+ TP_PROTO(const char *prefix, unsigned long gma,
+ unsigned long index),
+
+ TP_ARGS(prefix, gma, index),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "%s gma 0x%lx index 0x%lx\n", prefix, gma, index);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(gma_translate,
+ TP_PROTO(int id, char *type, int ring_id, int pt_level,
+ unsigned long gma, unsigned long gpa),
+
+ TP_ARGS(id, type, ring_id, pt_level, gma, gpa),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d %s ring %d pt_level %d gma 0x%lx -> gpa 0x%lx\n",
+ id, type, ring_id, pt_level, gma, gpa);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(spt_refcount,
+ TP_PROTO(int id, char *action, void *spt, int before, int after),
+
+ TP_ARGS(id, action, spt, before, after),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d [%s] spt %p before %d -> after %d\n",
+ id, action, spt, before, after);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(spt_change,
+ TP_PROTO(int id, char *action, void *spt, unsigned long gfn,
+ int type),
+
+ TP_ARGS(id, action, spt, gfn, type),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d [%s] spt %p gfn 0x%lx type %d\n",
+ id, action, spt, gfn, type);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(gpt_change,
+ TP_PROTO(int id, const char *tag, void *spt, int type, u64 v,
+ unsigned long index),
+
+ TP_ARGS(id, tag, spt, type, v, index),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d [%s] spt %p type %d entry 0x%llx index 0x%lx\n",
+ id, tag, spt, type, v, index);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(oos_change,
+ TP_PROTO(int id, const char *tag, int page_id, void *gpt, int type),
+
+ TP_ARGS(id, tag, page_id, gpt, type),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d [oos %s] page id %d gpt %p type %d\n",
+ id, tag, page_id, gpt, type);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(oos_sync,
+ TP_PROTO(int id, int page_id, void *gpt, int type, u64 v,
+ unsigned long index),
+
+ TP_ARGS(id, page_id, gpt, type, v, index),
+
+ TP_STRUCT__entry(
+ __array(char, buf, MAX_BUF_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->buf, MAX_BUF_LEN,
+ "VM%d [oos sync] page id %d gpt %p type %d entry 0x%llx index 0x%lx\n",
+ id, page_id, gpt, type, v, index);
+ ),
+
+ TP_printk("%s", __entry->buf)
+);
+
+#define MAX_CMD_STR_LEN 256
+TRACE_EVENT(gvt_command,
+ TP_PROTO(u8 vm_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len, bool ring_buffer_cmd, cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler),
+
+ TP_ARGS(vm_id, ring_id, ip_gma, cmd_va, cmd_len, ring_buffer_cmd, cost_pre_cmd_handler, cost_cmd_handler),
+
+ TP_STRUCT__entry(
+ __field(u8, vm_id)
+ __field(u8, ring_id)
+ __field(int, i)
+ __array(char, tmp_buf, MAX_CMD_STR_LEN)
+ __array(char, cmd_str, MAX_CMD_STR_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->vm_id = vm_id;
+ __entry->ring_id = ring_id;
+ __entry->cmd_str[0] = '\0';
+ snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "VM(%d) Ring(%d): %s ip(%08x) pre handler cost (%llu), handler cost (%llu) ", vm_id, ring_id, ring_buffer_cmd ? "RB":"BB", ip_gma, cost_pre_cmd_handler, cost_cmd_handler);
+ strcat(__entry->cmd_str, __entry->tmp_buf);
+ entry->i = 0;
+ while (cmd_len > 0) {
+ if (cmd_len >= 8) {
+ snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x %08x %08x %08x %08x ",
+ cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3],
+ cmd_va[__entry->i+4], cmd_va[__entry->i+5], cmd_va[__entry->i+6], cmd_va[__entry->i+7]);
+ __entry->i += 8;
+ cmd_len -= 8;
+ strcat(__entry->cmd_str, __entry->tmp_buf);
+ } else if (cmd_len >= 4) {
+ snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x ",
+ cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3]);
+ __entry->i += 4;
+ cmd_len -= 4;
+ strcat(__entry->cmd_str, __entry->tmp_buf);
+ } else if (cmd_len >= 2) {
+ snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x ", cmd_va[__entry->i], cmd_va[__entry->i+1]);
+ __entry->i += 2;
+ cmd_len -= 2;
+ strcat(__entry->cmd_str, __entry->tmp_buf);
+ } else if (cmd_len == 1) {
+ snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x ", cmd_va[__entry->i]);
+ __entry->i += 1;
+ cmd_len -= 1;
+ strcat(__entry->cmd_str, __entry->tmp_buf);
+ }
+ }
+ strcat(__entry->cmd_str, "\n");
+ ),
+
+ TP_printk("%s", __entry->cmd_str)
+);
+#endif /* _GVT_TRACE_H_ */
+
+/* This part must be out of protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.h b/drivers/gpu/drm/i915/gvt/trace_points.c
index 91315557e421..a3deed692b9c 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/trace_points.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Intel Corporation
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -16,30 +16,21 @@
* 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.
+ * 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:
+ * Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ * Zhi Wang <zhi.a.wang@intel.com>
*
*/
-#ifndef _I915_GEM_DMABUF_H_
-#define _I915_GEM_DMABUF_H_
-
-#include <linux/dma-buf.h>
-
-static inline struct reservation_object *
-i915_gem_object_get_dmabuf_resv(struct drm_i915_gem_object *obj)
-{
- struct dma_buf *dma_buf;
-
- if (obj->base.dma_buf)
- dma_buf = obj->base.dma_buf;
- else if (obj->base.import_attach)
- dma_buf = obj->base.import_attach->dmabuf;
- else
- return NULL;
-
- return dma_buf->resv;
-}
+#include "trace.h"
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
#endif
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
new file mode 100644
index 000000000000..536d2b9d5777
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Eddie Dong <eddie.dong@intel.com>
+ * Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ * Ping Gao <ping.a.gao@intel.com>
+ * Zhi Wang <zhi.a.wang@intel.com>
+ * Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+static void clean_vgpu_mmio(struct intel_vgpu *vgpu)
+{
+ vfree(vgpu->mmio.vreg);
+ vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;
+}
+
+int setup_vgpu_mmio(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ const struct intel_gvt_device_info *info = &gvt->device_info;
+
+ if (vgpu->mmio.vreg)
+ memset(vgpu->mmio.vreg, 0, info->mmio_size * 2);
+ else {
+ vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
+ if (!vgpu->mmio.vreg)
+ return -ENOMEM;
+ }
+
+ vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;
+
+ memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);
+ memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);
+
+ vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;
+
+ /* set the bit 0:2(Core C-State ) to C0 */
+ vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;
+ return 0;
+}
+
+static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu,
+ struct intel_vgpu_creation_params *param)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+ const struct intel_gvt_device_info *info = &gvt->device_info;
+ u16 *gmch_ctl;
+ int i;
+
+ memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
+ info->cfg_space_size);
+
+ if (!param->primary) {
+ vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
+ INTEL_GVT_PCI_CLASS_VGA_OTHER;
+ vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
+ INTEL_GVT_PCI_CLASS_VGA_OTHER;
+ }
+
+ /* Show guest that there isn't any stolen memory.*/
+ gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
+ *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
+
+ intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
+ gvt_aperture_pa_base(gvt), true);
+
+ vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
+ | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER);
+ /*
+ * Clear the bar upper 32bit and let guest to assign the new value
+ */
+ memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
+ memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
+ memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
+
+ for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
+ vgpu->cfg_space.bar[i].size = pci_resource_len(
+ gvt->dev_priv->drm.pdev, i * 2);
+ vgpu->cfg_space.bar[i].tracked = false;
+ }
+}
+
+void populate_pvinfo_page(struct intel_vgpu *vgpu)
+{
+ /* setup the ballooning information */
+ vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC;
+ vgpu_vreg(vgpu, vgtif_reg(version_major)) = 1;
+ vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0;
+ vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0;
+ vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id;
+ vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
+ vgpu_aperture_gmadr_base(vgpu);
+ vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) =
+ vgpu_aperture_sz(vgpu);
+ vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) =
+ vgpu_hidden_gmadr_base(vgpu);
+ vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) =
+ vgpu_hidden_sz(vgpu);
+
+ vgpu_vreg(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu);
+
+ gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id);
+ gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n",
+ vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu));
+ gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n",
+ vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu));
+ gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu));
+
+ WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
+}
+
+/**
+ * intel_gvt_init_vgpu_types - initialize vGPU type list
+ * @gvt : GVT device
+ *
+ * Initialize vGPU type list based on available resource.
+ *
+ */
+int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
+{
+ unsigned int num_types;
+ unsigned int i, low_avail;
+ unsigned int min_low;
+
+ /* vGPU type name is defined as GVTg_Vx_y which contains
+ * physical GPU generation type and 'y' means maximum vGPU
+ * instances user can create on one physical GPU for this
+ * type.
+ *
+ * Depend on physical SKU resource, might see vGPU types like
+ * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create
+ * different types of vGPU on same physical GPU depending on
+ * available resource. Each vGPU type will have "avail_instance"
+ * to indicate how many vGPU instance can be created for this
+ * type.
+ *
+ * Currently use static size here as we init type earlier..
+ */
+ low_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE;
+ num_types = 4;
+
+ gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type),
+ GFP_KERNEL);
+ if (!gvt->types)
+ return -ENOMEM;
+
+ min_low = MB_TO_BYTES(32);
+ for (i = 0; i < num_types; ++i) {
+ if (low_avail / min_low == 0)
+ break;
+ gvt->types[i].low_gm_size = min_low;
+ gvt->types[i].high_gm_size = 3 * gvt->types[i].low_gm_size;
+ gvt->types[i].fence = 4;
+ gvt->types[i].max_instance = low_avail / min_low;
+ gvt->types[i].avail_instance = gvt->types[i].max_instance;
+
+ if (IS_GEN8(gvt->dev_priv))
+ sprintf(gvt->types[i].name, "GVTg_V4_%u",
+ gvt->types[i].max_instance);
+ else if (IS_GEN9(gvt->dev_priv))
+ sprintf(gvt->types[i].name, "GVTg_V5_%u",
+ gvt->types[i].max_instance);
+
+ min_low <<= 1;
+ gvt_dbg_core("type[%d]: %s max %u avail %u low %u high %u fence %u\n",
+ i, gvt->types[i].name, gvt->types[i].max_instance,
+ gvt->types[i].avail_instance,
+ gvt->types[i].low_gm_size,
+ gvt->types[i].high_gm_size, gvt->types[i].fence);
+ }
+
+ gvt->num_types = i;
+ return 0;
+}
+
+void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
+{
+ kfree(gvt->types);
+}
+
+static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
+{
+ int i;
+ unsigned int low_gm_avail, high_gm_avail, fence_avail;
+ unsigned int low_gm_min, high_gm_min, fence_min, total_min;
+
+ /* Need to depend on maxium hw resource size but keep on
+ * static config for now.
+ */
+ low_gm_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE -
+ gvt->gm.vgpu_allocated_low_gm_size;
+ high_gm_avail = MB_TO_BYTES(256) * 3 - HOST_HIGH_GM_SIZE -
+ gvt->gm.vgpu_allocated_high_gm_size;
+ fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
+ gvt->fence.vgpu_allocated_fence_num;
+
+ for (i = 0; i < gvt->num_types; i++) {
+ low_gm_min = low_gm_avail / gvt->types[i].low_gm_size;
+ high_gm_min = high_gm_avail / gvt->types[i].high_gm_size;
+ fence_min = fence_avail / gvt->types[i].fence;
+ total_min = min(min(low_gm_min, high_gm_min), fence_min);
+ gvt->types[i].avail_instance = min(gvt->types[i].max_instance,
+ total_min);
+
+ gvt_dbg_core("update type[%d]: %s max %u avail %u low %u high %u fence %u\n",
+ i, gvt->types[i].name, gvt->types[i].max_instance,
+ gvt->types[i].avail_instance, gvt->types[i].low_gm_size,
+ gvt->types[i].high_gm_size, gvt->types[i].fence);
+ }
+}
+
+/**
+ * intel_gvt_destroy_vgpu - destroy a virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to destroy a virtual GPU.
+ *
+ */
+void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
+{
+ struct intel_gvt *gvt = vgpu->gvt;
+
+ mutex_lock(&gvt->lock);
+
+ vgpu->active = false;
+ idr_remove(&gvt->vgpu_idr, vgpu->id);
+
+ if (atomic_read(&vgpu->running_workload_num)) {
+ mutex_unlock(&gvt->lock);
+ intel_gvt_wait_vgpu_idle(vgpu);
+ mutex_lock(&gvt->lock);
+ }
+
+ intel_vgpu_stop_schedule(vgpu);
+ intel_vgpu_clean_sched_policy(vgpu);
+ intel_vgpu_clean_gvt_context(vgpu);
+ intel_vgpu_clean_execlist(vgpu);
+ intel_vgpu_clean_display(vgpu);
+ intel_vgpu_clean_opregion(vgpu);
+ intel_vgpu_clean_gtt(vgpu);
+ intel_gvt_hypervisor_detach_vgpu(vgpu);
+ intel_vgpu_free_resource(vgpu);
+ clean_vgpu_mmio(vgpu);
+ vfree(vgpu);
+
+ intel_gvt_update_vgpu_types(gvt);
+ mutex_unlock(&gvt->lock);
+}
+
+static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
+ struct intel_vgpu_creation_params *param)
+{
+ struct intel_vgpu *vgpu;
+ int ret;
+
+ gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n",
+ param->handle, param->low_gm_sz, param->high_gm_sz,
+ param->fence_sz);
+
+ vgpu = vzalloc(sizeof(*vgpu));
+ if (!vgpu)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&gvt->lock);
+
+ ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL);
+ if (ret < 0)
+ goto out_free_vgpu;
+
+ vgpu->id = ret;
+ vgpu->handle = param->handle;
+ vgpu->gvt = gvt;
+ bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
+
+ setup_vgpu_cfg_space(vgpu, param);
+
+ ret = setup_vgpu_mmio(vgpu);
+ if (ret)
+ goto out_free_vgpu;
+
+ ret = intel_vgpu_alloc_resource(vgpu, param);
+ if (ret)
+ goto out_clean_vgpu_mmio;
+
+ populate_pvinfo_page(vgpu);
+
+ ret = intel_gvt_hypervisor_attach_vgpu(vgpu);
+ if (ret)
+ goto out_clean_vgpu_resource;
+
+ ret = intel_vgpu_init_gtt(vgpu);
+ if (ret)
+ goto out_detach_hypervisor_vgpu;
+
+ ret = intel_vgpu_init_display(vgpu);
+ if (ret)
+ goto out_clean_gtt;
+
+ ret = intel_vgpu_init_execlist(vgpu);
+ if (ret)
+ goto out_clean_display;
+
+ ret = intel_vgpu_init_gvt_context(vgpu);
+ if (ret)
+ goto out_clean_execlist;
+
+ ret = intel_vgpu_init_sched_policy(vgpu);
+ if (ret)
+ goto out_clean_shadow_ctx;
+
+ vgpu->active = true;
+ mutex_unlock(&gvt->lock);
+
+ return vgpu;
+
+out_clean_shadow_ctx:
+ intel_vgpu_clean_gvt_context(vgpu);
+out_clean_execlist:
+ intel_vgpu_clean_execlist(vgpu);
+out_clean_display:
+ intel_vgpu_clean_display(vgpu);
+out_clean_gtt:
+ intel_vgpu_clean_gtt(vgpu);
+out_detach_hypervisor_vgpu:
+ intel_gvt_hypervisor_detach_vgpu(vgpu);
+out_clean_vgpu_resource:
+ intel_vgpu_free_resource(vgpu);
+out_clean_vgpu_mmio:
+ clean_vgpu_mmio(vgpu);
+out_free_vgpu:
+ vfree(vgpu);
+ mutex_unlock(&gvt->lock);
+ return ERR_PTR(ret);
+}
+
+/**
+ * intel_gvt_create_vgpu - create a virtual GPU
+ * @gvt: GVT device
+ * @type: type of the vGPU to create
+ *
+ * This function is called when user wants to create a virtual GPU.
+ *
+ * Returns:
+ * pointer to intel_vgpu, error pointer if failed.
+ */
+struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
+ struct intel_vgpu_type *type)
+{
+ struct intel_vgpu_creation_params param;
+ struct intel_vgpu *vgpu;
+
+ param.handle = 0;
+ param.primary = 1;
+ param.low_gm_sz = type->low_gm_size;
+ param.high_gm_sz = type->high_gm_size;
+ param.fence_sz = type->fence;
+
+ /* XXX current param based on MB */
+ param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz);
+ param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz);
+
+ vgpu = __intel_gvt_create_vgpu(gvt, &param);
+ if (IS_ERR(vgpu))
+ return vgpu;
+
+ /* calculate left instance change for types */
+ intel_gvt_update_vgpu_types(gvt);
+
+ return vgpu;
+}
+
+/**
+ * intel_gvt_reset_vgpu - reset a virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to reset a virtual GPU.
+ *
+ */
+void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu)
+{
+}
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 70980f82a15b..f5039f4f988f 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -1290,7 +1290,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
}
if (ret == 0 && needs_clflush_after)
- drm_clflush_virt_range(shadow_batch_obj->mapping, batch_len);
+ drm_clflush_virt_range(shadow_batch_obj->mm.mapping, batch_len);
i915_gem_object_unpin_map(shadow_batch_obj);
return ret;
@@ -1308,10 +1308,11 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
bool active = false;
/* If the command parser is not enabled, report 0 - unsupported */
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
if (intel_engine_needs_cmd_parser(engine)) {
active = true;
break;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 27b0e34dadec..791bfc760075 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -79,10 +79,8 @@ static int i915_capabilities(struct seq_file *m, void *data)
seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv));
seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv));
#define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
-#define SEP_SEMICOLON ;
- DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
+ DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
#undef PRINT_FLAG
-#undef SEP_SEMICOLON
return 0;
}
@@ -109,12 +107,12 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj)
static char get_global_flag(struct drm_i915_gem_object *obj)
{
- return i915_gem_object_to_ggtt(obj, NULL) ? 'g' : ' ';
+ return !list_empty(&obj->userfault_link) ? 'g' : ' ';
}
static char get_pin_mapped_flag(struct drm_i915_gem_object *obj)
{
- return obj->mapping ? 'M' : ' ';
+ return obj->mm.mapping ? 'M' : ' ';
}
static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj)
@@ -138,11 +136,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
struct i915_vma *vma;
unsigned int frontbuffer_bits;
int pin_count = 0;
- enum intel_engine_id id;
lockdep_assert_held(&obj->base.dev->struct_mutex);
- seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x [ ",
+ seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s",
&obj->base,
get_active_flag(obj),
get_pin_flag(obj),
@@ -151,17 +148,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
get_pin_mapped_flag(obj),
obj->base.size / 1024,
obj->base.read_domains,
- obj->base.write_domain);
- for_each_engine_id(engine, dev_priv, id)
- seq_printf(m, "%x ",
- i915_gem_active_get_seqno(&obj->last_read[id],
- &obj->base.dev->struct_mutex));
- seq_printf(m, "] %x %s%s%s",
- i915_gem_active_get_seqno(&obj->last_write,
- &obj->base.dev->struct_mutex),
+ obj->base.write_domain,
i915_cache_level_str(dev_priv, obj->cache_level),
- obj->dirty ? " dirty" : "",
- obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
+ obj->mm.dirty ? " dirty" : "",
+ obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : "");
if (obj->base.name)
seq_printf(m, " (name: %d)", obj->base.name);
list_for_each_entry(vma, &obj->vma_list, obj_link) {
@@ -188,18 +178,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
}
if (obj->stolen)
seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
- if (obj->pin_display || obj->fault_mappable) {
- char s[3], *t = s;
- if (obj->pin_display)
- *t++ = 'p';
- if (obj->fault_mappable)
- *t++ = 'f';
- *t = '\0';
- seq_printf(m, " (%s mappable)", s);
- }
-
- engine = i915_gem_active_get_engine(&obj->last_write,
- &dev_priv->drm.struct_mutex);
+
+ engine = i915_gem_object_last_write_engine(obj);
if (engine)
seq_printf(m, " (%s)", engine->name);
@@ -237,7 +217,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
return ret;
total_obj_size = total_gtt_size = count = 0;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
if (obj->stolen == NULL)
continue;
@@ -247,7 +227,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
total_gtt_size += i915_gem_obj_total_ggtt_size(obj);
count++;
}
- list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
if (obj->stolen == NULL)
continue;
@@ -334,11 +314,12 @@ static void print_batch_pool_stats(struct seq_file *m,
struct drm_i915_gem_object *obj;
struct file_stats stats;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int j;
memset(&stats, 0, sizeof(stats));
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
list_for_each_entry(obj,
&engine->batch_pool.cache_list[j],
@@ -402,23 +383,23 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
if (ret)
return ret;
- seq_printf(m, "%u objects, %zu bytes\n",
+ seq_printf(m, "%u objects, %llu bytes\n",
dev_priv->mm.object_count,
dev_priv->mm.object_memory);
size = count = 0;
mapped_size = mapped_count = 0;
purgeable_size = purgeable_count = 0;
- list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
size += obj->base.size;
++count;
- if (obj->madv == I915_MADV_DONTNEED) {
+ if (obj->mm.madv == I915_MADV_DONTNEED) {
purgeable_size += obj->base.size;
++purgeable_count;
}
- if (obj->mapping) {
+ if (obj->mm.mapping) {
mapped_count++;
mapped_size += obj->base.size;
}
@@ -426,7 +407,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
size = count = dpy_size = dpy_count = 0;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
size += obj->base.size;
++count;
@@ -435,12 +416,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
++dpy_count;
}
- if (obj->madv == I915_MADV_DONTNEED) {
+ if (obj->mm.madv == I915_MADV_DONTNEED) {
purgeable_size += obj->base.size;
++purgeable_count;
}
- if (obj->mapping) {
+ if (obj->mm.mapping) {
mapped_count++;
mapped_size += obj->base.size;
}
@@ -512,7 +493,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
return ret;
total_obj_size = total_gtt_size = count = 0;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
if (show_pin_display_only && !obj->pin_display)
continue;
@@ -566,12 +547,12 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
pipe, plane);
}
if (work->flip_queued_req) {
- struct intel_engine_cs *engine = i915_gem_request_get_engine(work->flip_queued_req);
+ struct intel_engine_cs *engine = work->flip_queued_req->engine;
seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n",
engine->name,
- i915_gem_request_get_seqno(work->flip_queued_req),
- dev_priv->next_seqno,
+ work->flip_queued_req->global_seqno,
+ atomic_read(&dev_priv->gt.global_timeline.next_seqno),
intel_engine_get_seqno(engine),
i915_gem_request_completed(work->flip_queued_req));
} else
@@ -607,6 +588,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
struct drm_device *dev = &dev_priv->drm;
struct drm_i915_gem_object *obj;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int total = 0;
int ret, j;
@@ -614,7 +596,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
if (ret)
return ret;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
int count;
@@ -645,12 +627,24 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
return 0;
}
+static void print_request(struct seq_file *m,
+ struct drm_i915_gem_request *rq,
+ const char *prefix)
+{
+ seq_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
+ rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
+ rq->priotree.priority,
+ jiffies_to_msecs(jiffies - rq->emitted_jiffies),
+ rq->timeline->common->name);
+}
+
static int i915_gem_request_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct drm_device *dev = &dev_priv->drm;
- struct intel_engine_cs *engine;
struct drm_i915_gem_request *req;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int ret, any;
ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -658,29 +652,18 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
return ret;
any = 0;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
int count;
count = 0;
- list_for_each_entry(req, &engine->request_list, link)
+ list_for_each_entry(req, &engine->timeline->requests, link)
count++;
if (count == 0)
continue;
seq_printf(m, "%s requests: %d\n", engine->name, count);
- list_for_each_entry(req, &engine->request_list, link) {
- struct pid *pid = req->ctx->pid;
- struct task_struct *task;
-
- rcu_read_lock();
- task = pid ? pid_task(pid, PIDTYPE_PID) : NULL;
- seq_printf(m, " %x @ %d: %s [%d]\n",
- req->fence.seqno,
- (int) (jiffies - req->emitted_jiffies),
- task ? task->comm : "<unknown>",
- task ? task->pid : -1);
- rcu_read_unlock();
- }
+ list_for_each_entry(req, &engine->timeline->requests, link)
+ print_request(m, req, " ");
any++;
}
@@ -701,22 +684,23 @@ static void i915_ring_seqno_info(struct seq_file *m,
seq_printf(m, "Current sequence (%s): %x\n",
engine->name, intel_engine_get_seqno(engine));
- spin_lock(&b->lock);
+ spin_lock_irq(&b->lock);
for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
struct intel_wait *w = container_of(rb, typeof(*w), node);
seq_printf(m, "Waiting (%s): %s [%d] on %x\n",
engine->name, w->tsk->comm, w->tsk->pid, w->seqno);
}
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
}
static int i915_gem_seqno_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
i915_ring_seqno_info(m, engine);
return 0;
@@ -727,6 +711,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int i, pipe;
intel_runtime_pm_get(dev_priv);
@@ -743,17 +728,32 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
I915_READ(VLV_IIR_RW));
seq_printf(m, "Display IMR:\t%08x\n",
I915_READ(VLV_IMR));
- for_each_pipe(dev_priv, pipe)
+ for_each_pipe(dev_priv, pipe) {
+ enum intel_display_power_domain power_domain;
+
+ power_domain = POWER_DOMAIN_PIPE(pipe);
+ if (!intel_display_power_get_if_enabled(dev_priv,
+ power_domain)) {
+ seq_printf(m, "Pipe %c power disabled\n",
+ pipe_name(pipe));
+ continue;
+ }
+
seq_printf(m, "Pipe %c stat:\t%08x\n",
pipe_name(pipe),
I915_READ(PIPESTAT(pipe)));
+ intel_display_power_put(dev_priv, power_domain);
+ }
+
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
seq_printf(m, "Port hotplug:\t%08x\n",
I915_READ(PORT_HOTPLUG_EN));
seq_printf(m, "DPFLIPSTAT:\t%08x\n",
I915_READ(VLV_DPFLIPSTAT));
seq_printf(m, "DPINVGTT:\t%08x\n",
I915_READ(DPINVGTT));
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
for (i = 0; i < 4; i++) {
seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
@@ -895,7 +895,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
seq_printf(m, "Graphics Interrupt mask: %08x\n",
I915_READ(GTIMR));
}
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
if (INTEL_GEN(dev_priv) >= 6) {
seq_printf(m,
"Graphics Interrupt mask (%s): %08x\n",
@@ -935,26 +935,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
return 0;
}
-static int i915_hws_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = m->private;
- struct drm_i915_private *dev_priv = node_to_i915(node);
- struct intel_engine_cs *engine;
- const u32 *hws;
- int i;
-
- engine = &dev_priv->engine[(uintptr_t)node->info_ent->data];
- hws = engine->status_page.page_addr;
- if (hws == NULL)
- return 0;
-
- for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
- seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- i * 4,
- hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
- }
- return 0;
-}
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
static ssize_t
i915_error_state_write(struct file *filp,
@@ -1038,19 +1019,14 @@ static const struct file_operations i915_error_state_fops = {
.release = i915_error_state_release,
};
+#endif
+
static int
i915_next_seqno_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
- int ret;
-
- ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
- if (ret)
- return ret;
-
- *val = dev_priv->next_seqno;
- mutex_unlock(&dev_priv->drm.struct_mutex);
+ *val = 1 + atomic_read(&dev_priv->gt.global_timeline.next_seqno);
return 0;
}
@@ -1065,7 +1041,7 @@ i915_next_seqno_set(void *data, u64 val)
if (ret)
return ret;
- ret = i915_gem_set_seqno(dev, val);
+ ret = i915_gem_set_global_seqno(dev, val);
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -1277,15 +1253,42 @@ out:
return ret;
}
+static void i915_instdone_info(struct drm_i915_private *dev_priv,
+ struct seq_file *m,
+ struct intel_instdone *instdone)
+{
+ int slice;
+ int subslice;
+
+ seq_printf(m, "\t\tINSTDONE: 0x%08x\n",
+ instdone->instdone);
+
+ if (INTEL_GEN(dev_priv) <= 3)
+ return;
+
+ seq_printf(m, "\t\tSC_INSTDONE: 0x%08x\n",
+ instdone->slice_common);
+
+ if (INTEL_GEN(dev_priv) <= 6)
+ return;
+
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+ seq_printf(m, "\t\tSAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice, instdone->sampler[slice][subslice]);
+
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+ seq_printf(m, "\t\tROW_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice, instdone->row[slice][subslice]);
+}
+
static int i915_hangcheck_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_engine_cs *engine;
u64 acthd[I915_NUM_ENGINES];
u32 seqno[I915_NUM_ENGINES];
- u32 instdone[I915_NUM_INSTDONE_REG];
+ struct intel_instdone instdone;
enum intel_engine_id id;
- int j;
if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
seq_printf(m, "Wedged\n");
@@ -1303,12 +1306,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
intel_runtime_pm_get(dev_priv);
- for_each_engine_id(engine, dev_priv, id) {
+ for_each_engine(engine, dev_priv, id) {
acthd[id] = intel_engine_get_active_head(engine);
seqno[id] = intel_engine_get_seqno(engine);
}
- i915_get_extra_instdone(dev_priv, instdone);
+ intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
intel_runtime_pm_put(dev_priv);
@@ -1319,16 +1322,27 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
} else
seq_printf(m, "Hangcheck inactive\n");
- for_each_engine_id(engine, dev_priv, id) {
+ for_each_engine(engine, dev_priv, id) {
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
+ struct rb_node *rb;
+
seq_printf(m, "%s:\n", engine->name);
seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
- engine->hangcheck.seqno,
- seqno[id],
- engine->last_submitted_seqno);
+ engine->hangcheck.seqno, seqno[id],
+ intel_engine_last_submit(engine));
seq_printf(m, "\twaiters? %s, fake irq active? %s\n",
yesno(intel_engine_has_waiter(engine)),
yesno(test_bit(engine->id,
&dev_priv->gpu_error.missed_irq_rings)));
+ spin_lock_irq(&b->lock);
+ for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+ struct intel_wait *w = container_of(rb, typeof(*w), node);
+
+ seq_printf(m, "\t%s [%d] waiting for %x\n",
+ w->tsk->comm, w->tsk->pid, w->seqno);
+ }
+ spin_unlock_irq(&b->lock);
+
seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n",
(long long)engine->hangcheck.acthd,
(long long)acthd[id]);
@@ -1336,18 +1350,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
seq_printf(m, "\taction = %d\n", engine->hangcheck.action);
if (engine->id == RCS) {
- seq_puts(m, "\tinstdone read =");
+ seq_puts(m, "\tinstdone read =\n");
- for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
- seq_printf(m, " 0x%08x", instdone[j]);
+ i915_instdone_info(dev_priv, m, &instdone);
- seq_puts(m, "\n\tinstdone accu =");
+ seq_puts(m, "\tinstdone accu =\n");
- for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
- seq_printf(m, " 0x%08x",
- engine->hangcheck.instdone[j]);
-
- seq_puts(m, "\n");
+ i915_instdone_info(dev_priv, m,
+ &engine->hangcheck.instdone);
}
}
@@ -1357,14 +1367,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
static int ironlake_drpc_info(struct seq_file *m)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
u32 rgvmodectl, rstdbyctl;
u16 crstandvid;
- int ret;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
intel_runtime_pm_get(dev_priv);
rgvmodectl = I915_READ(MEMMODECTL);
@@ -1372,7 +1377,6 @@ static int ironlake_drpc_info(struct seq_file *m)
crstandvid = I915_READ16(CRSTANDVID);
intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
seq_printf(m, "Boost freq: %d\n",
@@ -1635,10 +1639,13 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
seq_printf(m, "FBC disabled: %s\n",
dev_priv->fbc.no_fbc_reason);
- if (INTEL_GEN(dev_priv) >= 7)
+ if (intel_fbc_is_active(dev_priv) && INTEL_GEN(dev_priv) >= 7) {
+ uint32_t mask = INTEL_GEN(dev_priv) >= 8 ?
+ BDW_FBC_COMPRESSION_MASK :
+ IVB_FBC_COMPRESSION_MASK;
seq_printf(m, "Compressing: %s\n",
- yesno(I915_READ(FBC_STATUS2) &
- FBC_COMPRESSION_MASK));
+ yesno(I915_READ(FBC_STATUS2) & mask));
+ }
mutex_unlock(&dev_priv->fbc.lock);
intel_runtime_pm_put(dev_priv);
@@ -1717,6 +1724,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
bool sr_enabled = false;
intel_runtime_pm_get(dev_priv);
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
if (HAS_PCH_SPLIT(dev_priv))
sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
@@ -1730,10 +1738,10 @@ static int i915_sr_status(struct seq_file *m, void *unused)
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
intel_runtime_pm_put(dev_priv);
- seq_printf(m, "self-refresh: %s\n",
- sr_enabled ? "enabled" : "disabled");
+ seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
return 0;
}
@@ -1867,7 +1875,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
fbdev_fb->base.height,
fbdev_fb->base.depth,
fbdev_fb->base.bits_per_pixel,
- fbdev_fb->base.modifier[0],
+ fbdev_fb->base.modifier,
drm_framebuffer_read_refcount(&fbdev_fb->base));
describe_obj(m, fbdev_fb->obj);
seq_putc(m, '\n');
@@ -1885,7 +1893,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
fb->base.height,
fb->base.depth,
fb->base.bits_per_pixel,
- fb->base.modifier[0],
+ fb->base.modifier,
drm_framebuffer_read_refcount(&fb->base));
describe_obj(m, fb->obj);
seq_putc(m, '\n');
@@ -1909,6 +1917,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
struct drm_device *dev = &dev_priv->drm;
struct intel_engine_cs *engine;
struct i915_gem_context *ctx;
+ enum intel_engine_id id;
int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1935,7 +1944,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, '\n');
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
struct intel_context *ce = &ctx->engine[engine->id];
seq_printf(m, "%s: ", engine->name);
@@ -1974,7 +1983,7 @@ static void i915_dump_lrc_obj(struct seq_file *m,
seq_printf(m, "\tBound in GGTT at 0x%08x\n",
i915_ggtt_offset(vma));
- if (i915_gem_object_get_pages(vma->obj)) {
+ if (i915_gem_object_pin_pages(vma->obj)) {
seq_puts(m, "\tFailed to get pages for context object\n\n");
return;
}
@@ -1993,6 +2002,7 @@ static void i915_dump_lrc_obj(struct seq_file *m,
kunmap_atomic(reg_state);
}
+ i915_gem_object_unpin_pages(vma->obj);
seq_putc(m, '\n');
}
@@ -2002,6 +2012,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
struct drm_device *dev = &dev_priv->drm;
struct intel_engine_cs *engine;
struct i915_gem_context *ctx;
+ enum intel_engine_id id;
int ret;
if (!i915.enable_execlists) {
@@ -2014,7 +2025,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
return ret;
list_for_each_entry(ctx, &dev_priv->context_list, link)
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
i915_dump_lrc_obj(m, ctx, engine);
mutex_unlock(&dev->struct_mutex);
@@ -2022,84 +2033,6 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
return 0;
}
-static int i915_execlists(struct seq_file *m, void *data)
-{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
- struct intel_engine_cs *engine;
- u32 status_pointer;
- u8 read_pointer;
- u8 write_pointer;
- u32 status;
- u32 ctx_id;
- struct list_head *cursor;
- int i, ret;
-
- if (!i915.enable_execlists) {
- seq_puts(m, "Logical Ring Contexts are disabled\n");
- return 0;
- }
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
-
- intel_runtime_pm_get(dev_priv);
-
- for_each_engine(engine, dev_priv) {
- struct drm_i915_gem_request *head_req = NULL;
- int count = 0;
-
- seq_printf(m, "%s\n", engine->name);
-
- status = I915_READ(RING_EXECLIST_STATUS_LO(engine));
- ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine));
- seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n",
- status, ctx_id);
-
- status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
- seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer);
-
- read_pointer = GEN8_CSB_READ_PTR(status_pointer);
- write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
- if (read_pointer > write_pointer)
- write_pointer += GEN8_CSB_ENTRIES;
- seq_printf(m, "\tRead pointer: 0x%08X, write pointer 0x%08X\n",
- read_pointer, write_pointer);
-
- for (i = 0; i < GEN8_CSB_ENTRIES; i++) {
- status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i));
- ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i));
-
- seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n",
- i, status, ctx_id);
- }
-
- spin_lock_bh(&engine->execlist_lock);
- list_for_each(cursor, &engine->execlist_queue)
- count++;
- head_req = list_first_entry_or_null(&engine->execlist_queue,
- struct drm_i915_gem_request,
- execlist_link);
- spin_unlock_bh(&engine->execlist_lock);
-
- seq_printf(m, "\t%d requests in queue\n", count);
- if (head_req) {
- seq_printf(m, "\tHead request context: %u\n",
- head_req->ctx->hw_id);
- seq_printf(m, "\tHead request tail: %u\n",
- head_req->tail);
- }
-
- seq_putc(m, '\n');
- }
-
- intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
static const char *swizzle_string(unsigned swizzle)
{
switch (swizzle) {
@@ -2127,12 +2060,7 @@ static const char *swizzle_string(unsigned swizzle)
static int i915_swizzle_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
- int ret;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
intel_runtime_pm_get(dev_priv);
seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
@@ -2172,7 +2100,6 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
seq_puts(m, "L-shaped memory detected\n");
intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -2201,14 +2128,15 @@ static int per_file_ctx(int id, void *ptr, void *data)
static void gen8_ppgtt_info(struct seq_file *m,
struct drm_i915_private *dev_priv)
{
- struct intel_engine_cs *engine;
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int i;
if (!ppgtt)
return;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
seq_printf(m, "%s\n", engine->name);
for (i = 0; i < 4; i++) {
u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
@@ -2223,11 +2151,12 @@ static void gen6_ppgtt_info(struct seq_file *m,
struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
if (IS_GEN6(dev_priv))
seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
seq_printf(m, "%s\n", engine->name);
if (IS_GEN7(dev_priv))
seq_printf(m, "GFX_MODE: 0x%08x\n",
@@ -2296,9 +2225,10 @@ out_unlock:
static int count_irq_waiters(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int count = 0;
- for_each_engine(engine, i915)
+ for_each_engine(engine, i915, id)
count += intel_engine_has_waiter(engine);
return count;
@@ -2325,8 +2255,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
struct drm_file *file;
seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled);
- seq_printf(m, "GPU busy? %s [%x]\n",
- yesno(dev_priv->gt.awake), dev_priv->gt.active_engines);
+ seq_printf(m, "GPU busy? %s [%d requests]\n",
+ yesno(dev_priv->gt.awake), dev_priv->gt.active_requests);
seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv));
seq_printf(m, "Frequency requested %d\n",
intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
@@ -2361,7 +2291,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
if (INTEL_GEN(dev_priv) >= 6 &&
dev_priv->rps.enabled &&
- dev_priv->gt.active_engines) {
+ dev_priv->gt.active_requests) {
u32 rpup, rpupei;
u32 rpdown, rpdownei;
@@ -2442,6 +2372,32 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
return 0;
}
+static void i915_guc_log_info(struct seq_file *m,
+ struct drm_i915_private *dev_priv)
+{
+ struct intel_guc *guc = &dev_priv->guc;
+
+ seq_puts(m, "\nGuC logging stats:\n");
+
+ seq_printf(m, "\tISR: flush count %10u, overflow count %10u\n",
+ guc->log.flush_count[GUC_ISR_LOG_BUFFER],
+ guc->log.total_overflow_count[GUC_ISR_LOG_BUFFER]);
+
+ seq_printf(m, "\tDPC: flush count %10u, overflow count %10u\n",
+ guc->log.flush_count[GUC_DPC_LOG_BUFFER],
+ guc->log.total_overflow_count[GUC_DPC_LOG_BUFFER]);
+
+ seq_printf(m, "\tCRASH: flush count %10u, overflow count %10u\n",
+ guc->log.flush_count[GUC_CRASH_DUMP_LOG_BUFFER],
+ guc->log.total_overflow_count[GUC_CRASH_DUMP_LOG_BUFFER]);
+
+ seq_printf(m, "\tTotal flush interrupt count: %u\n",
+ guc->log.flush_interrupt_count);
+
+ seq_printf(m, "\tCapture miss count: %u\n",
+ guc->log.capture_miss_count);
+}
+
static void i915_guc_client_info(struct seq_file *m,
struct drm_i915_private *dev_priv,
struct i915_guc_client *client)
@@ -2461,7 +2417,7 @@ static void i915_guc_client_info(struct seq_file *m,
seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
seq_printf(m, "\tLast submission result: %d\n", client->retcode);
- for_each_engine_id(engine, dev_priv, id) {
+ for_each_engine(engine, dev_priv, id) {
u64 submissions = client->submissions[id];
tot += submissions;
seq_printf(m, "\tSubmissions: %llu %s\n",
@@ -2504,7 +2460,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
seq_printf(m, "\nGuC submissions:\n");
- for_each_engine_id(engine, dev_priv, id) {
+ for_each_engine(engine, dev_priv, id) {
u64 submissions = guc.submissions[id];
total += submissions;
seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
@@ -2515,6 +2471,8 @@ static int i915_guc_info(struct seq_file *m, void *data)
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
i915_guc_client_info(m, dev_priv, &client);
+ i915_guc_log_info(m, dev_priv);
+
/* Add more as required ... */
return 0;
@@ -2526,10 +2484,10 @@ static int i915_guc_log_dump(struct seq_file *m, void *data)
struct drm_i915_gem_object *obj;
int i = 0, pg;
- if (!dev_priv->guc.log_vma)
+ if (!dev_priv->guc.log.vma)
return 0;
- obj = dev_priv->guc.log_vma->obj;
+ obj = dev_priv->guc.log.vma->obj;
for (pg = 0; pg < obj->base.size / PAGE_SIZE; pg++) {
u32 *log = kmap_atomic(i915_gem_object_get_page(obj, pg));
@@ -2546,6 +2504,44 @@ static int i915_guc_log_dump(struct seq_file *m, void *data)
return 0;
}
+static int i915_guc_log_control_get(void *data, u64 *val)
+{
+ struct drm_device *dev = data;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (!dev_priv->guc.log.vma)
+ return -EINVAL;
+
+ *val = i915.guc_log_level;
+
+ return 0;
+}
+
+static int i915_guc_log_control_set(void *data, u64 val)
+{
+ struct drm_device *dev = data;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ int ret;
+
+ if (!dev_priv->guc.log.vma)
+ return -EINVAL;
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ intel_runtime_pm_get(dev_priv);
+ ret = i915_guc_log_control(dev_priv, val);
+ intel_runtime_pm_put(dev_priv);
+
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_control_fops,
+ i915_guc_log_control_get, i915_guc_log_control_set,
+ "%lld\n");
+
static int i915_edp_psr_status(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -2575,11 +2571,22 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
else {
for_each_pipe(dev_priv, pipe) {
+ enum transcoder cpu_transcoder =
+ intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+ enum intel_display_power_domain power_domain;
+
+ power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+ if (!intel_display_power_get_if_enabled(dev_priv,
+ power_domain))
+ continue;
+
stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) &
VLV_EDP_PSR_CURR_STATE_MASK;
if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) ||
(stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE))
enabled = true;
+
+ intel_display_power_put(dev_priv, power_domain);
}
}
@@ -3004,7 +3011,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
struct drm_plane_state *state;
struct drm_plane *plane = &intel_plane->base;
- char *format_name;
+ struct drm_format_name_buf format_name;
if (!plane->state) {
seq_puts(m, "plane->state is NULL!\n");
@@ -3014,9 +3021,9 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
state = plane->state;
if (state->fb) {
- format_name = drm_get_format_name(state->fb->pixel_format);
+ drm_get_format_name(state->fb->pixel_format, &format_name);
} else {
- format_name = kstrdup("N/A", GFP_KERNEL);
+ sprintf(format_name.str, "N/A");
}
seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
@@ -3032,10 +3039,8 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
((state->src_w & 0xffff) * 15625) >> 10,
(state->src_h >> 16),
((state->src_h & 0xffff) * 15625) >> 10,
- format_name,
+ format_name.str,
plane_rotation(state->rotation));
-
- kfree(format_name);
}
}
@@ -3121,6 +3126,146 @@ static int i915_display_info(struct seq_file *m, void *unused)
return 0;
}
+static int i915_engine_info(struct seq_file *m, void *unused)
+{
+ struct drm_i915_private *dev_priv = node_to_i915(m->private);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ intel_runtime_pm_get(dev_priv);
+
+ for_each_engine(engine, dev_priv, id) {
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
+ struct drm_i915_gem_request *rq;
+ struct rb_node *rb;
+ u64 addr;
+
+ seq_printf(m, "%s\n", engine->name);
+ seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n",
+ intel_engine_get_seqno(engine),
+ intel_engine_last_submit(engine),
+ engine->hangcheck.seqno,
+ engine->hangcheck.score);
+
+ rcu_read_lock();
+
+ seq_printf(m, "\tRequests:\n");
+
+ rq = list_first_entry(&engine->timeline->requests,
+ struct drm_i915_gem_request, link);
+ if (&rq->link != &engine->timeline->requests)
+ print_request(m, rq, "\t\tfirst ");
+
+ rq = list_last_entry(&engine->timeline->requests,
+ struct drm_i915_gem_request, link);
+ if (&rq->link != &engine->timeline->requests)
+ print_request(m, rq, "\t\tlast ");
+
+ rq = i915_gem_find_active_request(engine);
+ if (rq) {
+ print_request(m, rq, "\t\tactive ");
+ seq_printf(m,
+ "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
+ rq->head, rq->postfix, rq->tail,
+ rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
+ rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
+ }
+
+ seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
+ I915_READ(RING_START(engine->mmio_base)),
+ rq ? i915_ggtt_offset(rq->ring->vma) : 0);
+ seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n",
+ I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
+ rq ? rq->ring->head : 0);
+ seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n",
+ I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
+ rq ? rq->ring->tail : 0);
+ seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n",
+ I915_READ(RING_CTL(engine->mmio_base)),
+ I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
+
+ rcu_read_unlock();
+
+ addr = intel_engine_get_active_head(engine);
+ seq_printf(m, "\tACTHD: 0x%08x_%08x\n",
+ upper_32_bits(addr), lower_32_bits(addr));
+ addr = intel_engine_get_last_batch_head(engine);
+ seq_printf(m, "\tBBADDR: 0x%08x_%08x\n",
+ upper_32_bits(addr), lower_32_bits(addr));
+
+ if (i915.enable_execlists) {
+ u32 ptr, read, write;
+ struct rb_node *rb;
+
+ seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
+ I915_READ(RING_EXECLIST_STATUS_LO(engine)),
+ I915_READ(RING_EXECLIST_STATUS_HI(engine)));
+
+ ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
+ read = GEN8_CSB_READ_PTR(ptr);
+ write = GEN8_CSB_WRITE_PTR(ptr);
+ seq_printf(m, "\tExeclist CSB read %d, write %d\n",
+ read, write);
+ if (read >= GEN8_CSB_ENTRIES)
+ read = 0;
+ if (write >= GEN8_CSB_ENTRIES)
+ write = 0;
+ if (read > write)
+ write += GEN8_CSB_ENTRIES;
+ while (read < write) {
+ unsigned int idx = ++read % GEN8_CSB_ENTRIES;
+
+ seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n",
+ idx,
+ I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
+ I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)));
+ }
+
+ rcu_read_lock();
+ rq = READ_ONCE(engine->execlist_port[0].request);
+ if (rq)
+ print_request(m, rq, "\t\tELSP[0] ");
+ else
+ seq_printf(m, "\t\tELSP[0] idle\n");
+ rq = READ_ONCE(engine->execlist_port[1].request);
+ if (rq)
+ print_request(m, rq, "\t\tELSP[1] ");
+ else
+ seq_printf(m, "\t\tELSP[1] idle\n");
+ rcu_read_unlock();
+
+ spin_lock_irq(&engine->timeline->lock);
+ for (rb = engine->execlist_first; rb; rb = rb_next(rb)) {
+ rq = rb_entry(rb, typeof(*rq), priotree.node);
+ print_request(m, rq, "\t\tQ ");
+ }
+ spin_unlock_irq(&engine->timeline->lock);
+ } else if (INTEL_GEN(dev_priv) > 6) {
+ seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE(engine)));
+ seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE_READ(engine)));
+ seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
+ I915_READ(RING_PP_DIR_DCLV(engine)));
+ }
+
+ spin_lock_irq(&b->lock);
+ for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+ struct intel_wait *w = container_of(rb, typeof(*w), node);
+
+ seq_printf(m, "\t%s [%d] waiting for %x\n",
+ w->tsk->comm, w->tsk->pid, w->seqno);
+ }
+ spin_unlock_irq(&b->lock);
+
+ seq_puts(m, "\n");
+ }
+
+ intel_runtime_pm_put(dev_priv);
+
+ return 0;
+}
+
static int i915_semaphore_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -3147,7 +3292,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0);
seqno = (uint64_t *)kmap_atomic(page);
- for_each_engine_id(engine, dev_priv, id) {
+ for_each_engine(engine, dev_priv, id) {
uint64_t offset;
seq_printf(m, "%s\n", engine->name);
@@ -3172,22 +3317,13 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
kunmap_atomic(seqno);
} else {
seq_puts(m, " Last signal:");
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
for (j = 0; j < num_rings; j++)
seq_printf(m, "0x%08x\n",
I915_READ(engine->semaphore.mbox.signal[j]));
seq_putc(m, '\n');
}
- seq_puts(m, "\nSync seqno:\n");
- for_each_engine(engine, dev_priv) {
- for (j = 0; j < num_rings; j++)
- seq_printf(m, " 0x%08x ",
- engine->semaphore.sync_seqno[j]);
- seq_putc(m, '\n');
- }
- seq_putc(m, '\n');
-
intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex);
return 0;
@@ -3236,7 +3372,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
intel_runtime_pm_get(dev_priv);
seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
- for_each_engine_id(engine, dev_priv, id)
+ for_each_engine(engine, dev_priv, id)
seq_printf(m, "HW whitelist count for %s: %d\n",
engine->name, workarounds->hw_whitelist_count[id]);
for (i = 0; i < workarounds->count; ++i) {
@@ -3280,7 +3416,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
for_each_pipe(dev_priv, pipe) {
seq_printf(m, "Pipe %c\n", pipe_name(pipe));
- for_each_plane(dev_priv, pipe, plane) {
+ for_each_universal_plane(dev_priv, pipe, plane) {
entry = &ddb->plane[pipe][plane];
seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane + 1,
entry->start, entry->end,
@@ -3914,8 +4050,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
bool enable)
{
struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc =
- to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
struct intel_crtc_state *pipe_config;
struct drm_atomic_state *state;
int ret = 0;
@@ -3941,10 +4076,9 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
ret = drm_atomic_commit(state);
out:
- drm_modeset_unlock_all(dev);
WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
- if (ret)
- drm_atomic_state_free(state);
+ drm_modeset_unlock_all(dev);
+ drm_atomic_state_put(state);
}
static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
@@ -3982,10 +4116,8 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
enum pipe pipe,
enum intel_pipe_crc_source source)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
- struct intel_crtc *crtc =
- to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
enum intel_display_power_domain power_domain;
u32 val = 0; /* shut up gcc */
int ret;
@@ -4056,15 +4188,15 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
/* real source -> none transition */
if (source == INTEL_PIPE_CRC_SOURCE_NONE) {
struct intel_pipe_crc_entry *entries;
- struct intel_crtc *crtc =
- to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
pipe_name(pipe));
drm_modeset_lock(&crtc->base.mutex, NULL);
if (crtc->base.state->active)
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
drm_modeset_unlock(&crtc->base.mutex);
spin_lock_irq(&pipe_crc->lock);
@@ -4463,7 +4595,7 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
else if (IS_VALLEYVIEW(dev_priv))
num_levels = 1;
else
- num_levels = ilk_wm_max_level(dev) + 1;
+ num_levels = ilk_wm_max_level(dev_priv) + 1;
drm_modeset_lock_all(dev);
@@ -4579,7 +4711,7 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
else if (IS_VALLEYVIEW(dev_priv))
num_levels = 1;
else
- num_levels = ilk_wm_max_level(dev) + 1;
+ num_levels = ilk_wm_max_level(dev_priv) + 1;
if (len >= sizeof(tmp))
return -EINVAL;
@@ -4704,13 +4836,9 @@ i915_wedged_set(void *data, u64 val)
if (i915_reset_in_progress(&dev_priv->gpu_error))
return -EAGAIN;
- intel_runtime_pm_get(dev_priv);
-
i915_handle_error(dev_priv, val,
"Manually setting wedged to %llu", val);
- intel_runtime_pm_put(dev_priv);
-
return 0;
}
@@ -4778,10 +4906,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops,
#define DROP_BOUND 0x2
#define DROP_RETIRE 0x4
#define DROP_ACTIVE 0x8
-#define DROP_ALL (DROP_UNBOUND | \
- DROP_BOUND | \
- DROP_RETIRE | \
- DROP_ACTIVE)
+#define DROP_FREED 0x10
+#define DROP_ALL (DROP_UNBOUND | \
+ DROP_BOUND | \
+ DROP_RETIRE | \
+ DROP_ACTIVE | \
+ DROP_FREED)
static int
i915_drop_caches_get(void *data, u64 *val)
{
@@ -4825,6 +4955,11 @@ i915_drop_caches_set(void *data, u64 val)
unlock:
mutex_unlock(&dev->struct_mutex);
+ if (val & DROP_FREED) {
+ synchronize_rcu();
+ flush_work(&dev_priv->mm.free_work);
+ }
+
return ret;
}
@@ -4945,22 +5080,16 @@ static int
i915_cache_sharing_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
- struct drm_device *dev = &dev_priv->drm;
u32 snpcr;
- int ret;
if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv)))
return -ENODEV;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
intel_runtime_pm_get(dev_priv);
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -5253,10 +5382,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_seqno", i915_gem_seqno_info, 0},
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
{"i915_gem_interrupt", i915_interrupt_info, 0},
- {"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
- {"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
- {"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},
@@ -5275,7 +5400,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
{"i915_context_status", i915_context_status, 0},
{"i915_dump_lrc", i915_dump_lrc, 0},
- {"i915_execlists", i915_execlists, 0},
{"i915_forcewake_domains", i915_forcewake_domains, 0},
{"i915_swizzle_info", i915_swizzle_info, 0},
{"i915_ppgtt_info", i915_ppgtt_info, 0},
@@ -5287,6 +5411,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_power_domain_info", i915_power_domain_info, 0},
{"i915_dmc_info", i915_dmc_info, 0},
{"i915_display_info", i915_display_info, 0},
+ {"i915_engine_info", i915_engine_info, 0},
{"i915_semaphore_status", i915_semaphore_status, 0},
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
{"i915_dp_mst_info", i915_dp_mst_info, 0},
@@ -5309,7 +5434,9 @@ static const struct i915_debugfs_files {
{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
{"i915_ring_test_irq", &i915_ring_test_irq_fops},
{"i915_gem_drop_caches", &i915_drop_caches_fops},
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
{"i915_error_state", &i915_error_state_fops},
+#endif
{"i915_next_seqno", &i915_next_seqno_fops},
{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
@@ -5318,7 +5445,8 @@ static const struct i915_debugfs_files {
{"i915_fbc_false_color", &i915_fbc_fc_fops},
{"i915_dp_test_data", &i915_displayport_test_data_fops},
{"i915_dp_test_type", &i915_displayport_test_type_fops},
- {"i915_dp_test_active", &i915_displayport_test_active_fops}
+ {"i915_dp_test_active", &i915_displayport_test_active_fops},
+ {"i915_guc_log_control", &i915_guc_log_control_fops}
};
void intel_display_crc_init(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 18dfdd5c1b3b..445fec9c2841 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -114,7 +114,7 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv)
fmt, ##__VA_ARGS__)
-static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
+static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv)
{
enum intel_pch ret = PCH_NOP;
@@ -125,16 +125,16 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
* make an educated guess as to which PCH is really there.
*/
- if (IS_GEN5(dev)) {
+ if (IS_GEN5(dev_priv)) {
ret = PCH_IBX;
DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
- } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
+ } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
ret = PCH_CPT;
DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
- } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
ret = PCH_LPT;
DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
- } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
ret = PCH_SPT;
DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
}
@@ -150,7 +150,7 @@ static void intel_detect_pch(struct drm_device *dev)
/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
* (which really amounts to a PCH but no South Display).
*/
- if (INTEL_INFO(dev)->num_pipes == 0) {
+ if (INTEL_INFO(dev_priv)->num_pipes == 0) {
dev_priv->pch_type = PCH_NOP;
return;
}
@@ -174,40 +174,46 @@ static void intel_detect_pch(struct drm_device *dev)
if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_IBX;
DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
- WARN_ON(!IS_GEN5(dev));
+ WARN_ON(!IS_GEN5(dev_priv));
} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_CPT;
DRM_DEBUG_KMS("Found CougarPoint PCH\n");
- WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
+ WARN_ON(!(IS_GEN6(dev_priv) ||
+ IS_IVYBRIDGE(dev_priv)));
} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
/* PantherPoint is CPT compatible */
dev_priv->pch_type = PCH_CPT;
DRM_DEBUG_KMS("Found PantherPoint PCH\n");
- WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
+ WARN_ON(!(IS_GEN6(dev_priv) ||
+ IS_IVYBRIDGE(dev_priv)));
} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_LPT;
DRM_DEBUG_KMS("Found LynxPoint PCH\n");
- WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
- WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev));
+ WARN_ON(!IS_HASWELL(dev_priv) &&
+ !IS_BROADWELL(dev_priv));
+ WARN_ON(IS_HSW_ULT(dev_priv) ||
+ IS_BDW_ULT(dev_priv));
} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_LPT;
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
- WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
- WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev));
+ WARN_ON(!IS_HASWELL(dev_priv) &&
+ !IS_BROADWELL(dev_priv));
+ WARN_ON(!IS_HSW_ULT(dev_priv) &&
+ !IS_BDW_ULT(dev_priv));
} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
- WARN_ON(!IS_SKYLAKE(dev) &&
- !IS_KABYLAKE(dev));
+ WARN_ON(!IS_SKYLAKE(dev_priv) &&
+ !IS_KABYLAKE(dev_priv));
} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
- WARN_ON(!IS_SKYLAKE(dev) &&
- !IS_KABYLAKE(dev));
+ WARN_ON(!IS_SKYLAKE(dev_priv) &&
+ !IS_KABYLAKE(dev_priv));
} else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_KBP;
DRM_DEBUG_KMS("Found KabyPoint PCH\n");
- WARN_ON(!IS_KABYLAKE(dev));
+ WARN_ON(!IS_KABYLAKE(dev_priv));
} else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
(id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
@@ -215,7 +221,8 @@ static void intel_detect_pch(struct drm_device *dev)
PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
pch->subsystem_device ==
PCI_SUBDEVICE_ID_QEMU)) {
- dev_priv->pch_type = intel_virt_detect_pch(dev);
+ dev_priv->pch_type =
+ intel_virt_detect_pch(dev_priv);
} else
continue;
@@ -255,16 +262,16 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = dev_priv->overlay ? 1 : 0;
break;
case I915_PARAM_HAS_BSD:
- value = intel_engine_initialized(&dev_priv->engine[VCS]);
+ value = !!dev_priv->engine[VCS];
break;
case I915_PARAM_HAS_BLT:
- value = intel_engine_initialized(&dev_priv->engine[BCS]);
+ value = !!dev_priv->engine[BCS];
break;
case I915_PARAM_HAS_VEBOX:
- value = intel_engine_initialized(&dev_priv->engine[VECS]);
+ value = !!dev_priv->engine[VECS];
break;
case I915_PARAM_HAS_BSD2:
- value = intel_engine_initialized(&dev_priv->engine[VCS2]);
+ value = !!dev_priv->engine[VCS2];
break;
case I915_PARAM_HAS_EXEC_CONSTANTS:
value = INTEL_GEN(dev_priv) >= 4;
@@ -316,6 +323,10 @@ static int i915_getparam(struct drm_device *dev, void *data,
*/
value = i915_gem_mmap_gtt_version();
break;
+ case I915_PARAM_HAS_SCHEDULER:
+ value = dev_priv->engine[RCS] &&
+ dev_priv->engine[RCS]->schedule;
+ break;
case I915_PARAM_MMAP_VERSION:
/* Remember to bump this if the version changes! */
case I915_PARAM_HAS_GEM:
@@ -367,12 +378,12 @@ static int
intel_alloc_mchbar_resource(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+ int reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
u32 temp_lo, temp_hi = 0;
u64 mchbar_addr;
int ret;
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
@@ -399,7 +410,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
return ret;
}
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
upper_32_bits(dev_priv->mch_res.start));
@@ -413,16 +424,16 @@ static void
intel_setup_mchbar(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+ int mchbar_reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
u32 temp;
bool enabled;
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return;
dev_priv->mchbar_need_disable = false;
- if (IS_I915G(dev) || IS_I915GM(dev)) {
+ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
enabled = !!(temp & DEVEN_MCHBAR_EN);
} else {
@@ -440,7 +451,7 @@ intel_setup_mchbar(struct drm_device *dev)
dev_priv->mchbar_need_disable = true;
/* Space is allocated or reserved, so enable it. */
- if (IS_I915G(dev) || IS_I915GM(dev)) {
+ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
temp | DEVEN_MCHBAR_EN);
} else {
@@ -453,10 +464,10 @@ static void
intel_teardown_mchbar(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+ int mchbar_reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
if (dev_priv->mchbar_need_disable) {
- if (IS_I915G(dev) || IS_I915GM(dev)) {
+ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
u32 deven_val;
pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
@@ -484,7 +495,7 @@ static unsigned int i915_vga_set_decode(void *cookie, bool state)
{
struct drm_device *dev = cookie;
- intel_modeset_vga_set_state(dev, state);
+ intel_modeset_vga_set_state(to_i915(dev), state);
if (state)
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
@@ -530,40 +541,17 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
.can_switch = i915_switcheroo_can_switch,
};
-static void i915_gem_fini(struct drm_device *dev)
+static void i915_gem_fini(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ i915_gem_cleanup_engines(&dev_priv->drm);
+ i915_gem_context_fini(&dev_priv->drm);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
- /*
- * Neither the BIOS, ourselves or any other kernel
- * expects the system to be in execlists mode on startup,
- * so we need to reset the GPU back to legacy mode. And the only
- * known way to disable logical contexts is through a GPU reset.
- *
- * So in order to leave the system in a known default configuration,
- * always reset the GPU upon unload. Afterwards we then clean up the
- * GEM state tracking, flushing off the requests and leaving the
- * system in a known idle state.
- *
- * Note that is of the upmost importance that the GPU is idle and
- * all stray writes are flushed *before* we dismantle the backing
- * storage for the pinned objects.
- *
- * However, since we are uncertain that reseting the GPU on older
- * machines is a good idea, we don't - just in case it leaves the
- * machine in an unusable condition.
- */
- if (HAS_HW_CONTEXTS(dev)) {
- int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
- WARN_ON(reset && reset != -ENODEV);
- }
-
- mutex_lock(&dev->struct_mutex);
- i915_gem_cleanup_engines(dev);
- i915_gem_context_fini(dev);
- mutex_unlock(&dev->struct_mutex);
+ rcu_barrier();
+ flush_work(&dev_priv->mm.free_work);
- WARN_ON(!list_empty(&to_i915(dev)->context_list));
+ WARN_ON(!list_empty(&dev_priv->context_list));
}
static int i915_load_modeset_init(struct drm_device *dev)
@@ -611,7 +599,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
/* Important: The output setup functions called by modeset_init need
* working irqs for e.g. gmbus and dp aux transfers. */
- intel_modeset_init(dev);
+ ret = intel_modeset_init(dev);
+ if (ret)
+ goto cleanup_irq;
intel_guc_init(dev);
@@ -621,7 +611,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
intel_modeset_gem_init(dev);
- if (INTEL_INFO(dev)->num_pipes == 0)
+ if (INTEL_INFO(dev_priv)->num_pipes == 0)
return 0;
ret = intel_fbdev_init(dev);
@@ -636,7 +626,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
return 0;
cleanup_gem:
- i915_gem_fini(dev);
+ if (i915_gem_suspend(dev))
+ DRM_ERROR("failed to idle hardware; continuing to unload!\n");
+ i915_gem_fini(dev_priv);
cleanup_irq:
intel_guc_fini(dev);
drm_irq_uninstall(dev);
@@ -771,6 +763,19 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
destroy_workqueue(dev_priv->wq);
}
+/*
+ * We don't keep the workarounds for pre-production hardware, so we expect our
+ * driver to fail on these machines in one way or another. A little warning on
+ * dmesg may help both the user and the bug triagers.
+ */
+static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
+{
+ if (IS_HSW_EARLY_SDV(dev_priv) ||
+ IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
+ DRM_ERROR("This is a pre-production stepping. "
+ "It may not be fully functional.\n");
+}
+
/**
* i915_driver_init_early - setup state not requiring device access
* @dev_priv: device private
@@ -829,25 +834,24 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
intel_init_dpio(dev_priv);
intel_power_domains_init(dev_priv);
intel_irq_init(dev_priv);
+ intel_hangcheck_init(dev_priv);
intel_init_display_hooks(dev_priv);
intel_init_clock_gating_hooks(dev_priv);
intel_init_audio_hooks(dev_priv);
- i915_gem_load_init(&dev_priv->drm);
+ ret = i915_gem_load_init(&dev_priv->drm);
+ if (ret < 0)
+ goto err_gvt;
intel_display_crc_init(dev_priv);
intel_device_info_dump(dev_priv);
- /* Not all pre-production machines fall into this category, only the
- * very first ones. Almost everything should work, except for maybe
- * suspend/resume. And we don't implement workarounds that affect only
- * pre-production machines. */
- if (IS_HSW_EARLY_SDV(dev_priv))
- DRM_INFO("This is an early pre-production Haswell machine. "
- "It may not be fully functional.\n");
+ intel_detect_preproduction_hw(dev_priv);
return 0;
+err_gvt:
+ intel_gvt_cleanup(dev_priv);
err_workqueues:
i915_workqueues_cleanup(dev_priv);
return ret;
@@ -870,7 +874,7 @@ static int i915_mmio_setup(struct drm_device *dev)
int mmio_bar;
int mmio_size;
- mmio_bar = IS_GEN2(dev) ? 1 : 0;
+ mmio_bar = IS_GEN2(dev_priv) ? 1 : 0;
/*
* Before gen4, the registers and the GTT are behind different BARs.
* However, from gen4 onwards, the registers and the GTT are shared
@@ -879,7 +883,7 @@ static int i915_mmio_setup(struct drm_device *dev)
* the register BAR remains the same size for all the earlier
* generations up to Ironlake.
*/
- if (INTEL_INFO(dev)->gen < 5)
+ if (INTEL_GEN(dev_priv) < 5)
mmio_size = 512 * 1024;
else
mmio_size = 2 * 1024 * 1024;
@@ -982,7 +986,6 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv)
static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
- struct drm_device *dev = &dev_priv->drm;
int ret;
if (i915_inject_load_failure())
@@ -1023,7 +1026,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
pci_set_master(pdev);
/* overlay on gen2 is broken and can't address above 1G */
- if (IS_GEN2(dev)) {
+ if (IS_GEN2(dev_priv)) {
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
if (ret) {
DRM_ERROR("failed to set DMA mask\n");
@@ -1040,7 +1043,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
* behaviour if any general state is accessed within a page above 4GB,
* which also needs to be handled carefully.
*/
- if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) {
+ if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv)) {
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
@@ -1070,7 +1073,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
* be lost or delayed, but we use them anyways to avoid
* stuck interrupts on some machines.
*/
- if (!IS_I945G(dev) && !IS_I945GM(dev)) {
+ if (!IS_I945G(dev_priv) && !IS_I945GM(dev_priv)) {
if (pci_enable_msi(pdev) < 0)
DRM_DEBUG_DRIVER("can't enable MSI");
}
@@ -1121,6 +1124,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
/* Reveal our presence to userspace */
if (drm_dev_register(dev, 0) == 0) {
i915_debugfs_register(dev_priv);
+ i915_guc_register(dev_priv);
i915_setup_sysfs(dev_priv);
} else
DRM_ERROR("Failed to register driver for userspace access!\n");
@@ -1159,6 +1163,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
intel_opregion_unregister(dev_priv);
i915_teardown_sysfs(dev_priv);
+ i915_guc_unregister(dev_priv);
i915_debugfs_unregister(dev_priv);
drm_dev_unregister(&dev_priv->drm);
@@ -1167,8 +1172,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
/**
* i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
+ * @pdev: PCI device
+ * @ent: matching PCI ID entry
*
* The driver load routine has to do several things:
* - drive output discovery via intel_modeset_init()
@@ -1242,6 +1247,10 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
driver.name, driver.major, driver.minor, driver.patchlevel,
driver.date, pci_name(pdev), dev_priv->drm.primary->index);
+ if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+ DRM_INFO("DRM_I915_DEBUG enabled\n");
+ if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+ DRM_INFO("DRM_I915_DEBUG_GEM enabled\n");
intel_runtime_pm_put(dev_priv);
@@ -1309,7 +1318,7 @@ void i915_driver_unload(struct drm_device *dev)
drain_workqueue(dev_priv->wq);
intel_guc_fini(dev);
- i915_gem_fini(dev);
+ i915_gem_fini(dev_priv);
intel_fbc_cleanup_cfb(dev_priv);
intel_power_domains_fini(dev_priv);
@@ -1431,9 +1440,9 @@ static int i915_drm_suspend(struct drm_device *dev)
intel_suspend_encoders(dev_priv);
- intel_suspend_hw(dev);
+ intel_suspend_hw(dev_priv);
- i915_gem_suspend_gtt_mappings(dev);
+ i915_gem_suspend_gtt_mappings(dev_priv);
i915_save_state(dev);
@@ -1507,7 +1516,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
* Fujitsu FSC S7110
* Acer Aspire 1830T
*/
- if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
+ if (!(hibernation && INTEL_GEN(dev_priv) < 6))
pci_set_power_state(pdev, PCI_D3hot);
dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
@@ -1595,6 +1604,8 @@ static int i915_drm_resume(struct drm_device *dev)
intel_display_resume(dev);
+ drm_kms_helper_poll_enable(dev);
+
/*
* ... but also need to make sure that hotplug processing
* doesn't cause havoc. Like in the driver load code we don't
@@ -1602,8 +1613,6 @@ static int i915_drm_resume(struct drm_device *dev)
* notifications.
* */
intel_hpd_init(dev_priv);
- /* Config may have changed between suspend and resume */
- drm_helper_hpd_irq_event(dev);
intel_opregion_register(dev_priv);
@@ -1616,7 +1625,6 @@ static int i915_drm_resume(struct drm_device *dev)
intel_opregion_notify_adapter(dev_priv, PCI_D0);
intel_autoenable_gt_powersave(dev_priv);
- drm_kms_helper_poll_enable(dev);
enable_rpm_wakeref_asserts(dev_priv);
@@ -1721,6 +1729,22 @@ int i915_resume_switcheroo(struct drm_device *dev)
return i915_drm_resume(dev);
}
+static void disable_engines_irq(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ /* Ensure irq handler finishes, and not run again. */
+ disable_irq(dev_priv->drm.irq);
+ for_each_engine(engine, dev_priv, id)
+ tasklet_kill(&engine->irq_tasklet);
+}
+
+static void enable_engines_irq(struct drm_i915_private *dev_priv)
+{
+ enable_irq(dev_priv->drm.irq);
+}
+
/**
* i915_reset - reset chip after a hang
* @dev: drm device to reset
@@ -1754,7 +1778,11 @@ void i915_reset(struct drm_i915_private *dev_priv)
error->reset_count++;
pr_notice("drm/i915: Resetting chip after gpu hang\n");
+
+ disable_engines_irq(dev_priv);
ret = intel_gpu_reset(dev_priv, ALL_ENGINES);
+ enable_engines_irq(dev_priv);
+
if (ret) {
if (ret != -ENODEV)
DRM_ERROR("Failed to reset chip: %i\n", ret);
@@ -2240,7 +2268,6 @@ err1:
static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
bool rpm_resume)
{
- struct drm_device *dev = &dev_priv->drm;
int err;
int ret;
@@ -2264,10 +2291,8 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
vlv_check_no_gt_access(dev_priv);
- if (rpm_resume) {
- intel_init_clock_gating(dev);
- i915_gem_restore_fences(dev);
- }
+ if (rpm_resume)
+ intel_init_clock_gating(dev_priv);
return ret;
}
@@ -2282,37 +2307,18 @@ static int intel_runtime_suspend(struct device *kdev)
if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6())))
return -ENODEV;
- if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+ if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv)))
return -ENODEV;
DRM_DEBUG_KMS("Suspending device\n");
- /*
- * We could deadlock here in case another thread holding struct_mutex
- * calls RPM suspend concurrently, since the RPM suspend will wait
- * first for this RPM suspend to finish. In this case the concurrent
- * RPM resume will be followed by its RPM suspend counterpart. Still
- * for consistency return -EAGAIN, which will reschedule this suspend.
- */
- if (!mutex_trylock(&dev->struct_mutex)) {
- DRM_DEBUG_KMS("device lock contention, deffering suspend\n");
- /*
- * Bump the expiration timestamp, otherwise the suspend won't
- * be rescheduled.
- */
- pm_runtime_mark_last_busy(kdev);
-
- return -EAGAIN;
- }
-
disable_rpm_wakeref_asserts(dev_priv);
/*
* We are safe here against re-faults, since the fault handler takes
* an RPM reference.
*/
- i915_gem_release_all_mmaps(dev_priv);
- mutex_unlock(&dev->struct_mutex);
+ i915_gem_runtime_suspend(dev_priv);
intel_guc_suspend(dev);
@@ -2386,7 +2392,7 @@ static int intel_runtime_resume(struct device *kdev)
struct drm_i915_private *dev_priv = to_i915(dev);
int ret = 0;
- if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+ if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv)))
return -ENODEV;
DRM_DEBUG_KMS("Resuming device\n");
@@ -2404,7 +2410,7 @@ static int intel_runtime_resume(struct device *kdev)
if (IS_GEN6(dev_priv))
intel_init_pch_refclk(dev);
- if (IS_BROXTON(dev)) {
+ if (IS_BROXTON(dev_priv)) {
bxt_disable_dc9(dev_priv);
bxt_display_core_init(dev_priv, true);
if (dev_priv->csr.dmc_payload &&
@@ -2420,7 +2426,7 @@ static int intel_runtime_resume(struct device *kdev)
* No point of rolling back things in case of an error, as the best
* we can do is to hope that things will still work (and disable RPM).
*/
- i915_gem_init_swizzling(dev);
+ i915_gem_init_swizzling(dev_priv);
intel_runtime_pm_enable_interrupts(dev_priv);
@@ -2495,9 +2501,7 @@ static const struct file_operations i915_driver_fops = {
.mmap = drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
-#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
@@ -2577,7 +2581,7 @@ static struct drm_driver driver = {
.set_busid = drm_pci_set_busid,
.gem_close_object = i915_gem_close_object,
- .gem_free_object = i915_gem_free_object,
+ .gem_free_object_unlocked = i915_gem_free_object,
.gem_vm_ops = &i915_gem_vm_ops,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 685e9e065287..56002a52936d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -41,6 +41,7 @@
#include <linux/intel-iommu.h>
#include <linux/kref.h>
#include <linux/pm_qos.h>
+#include <linux/reservation.h>
#include <linux/shmem_fs.h>
#include <drm/drmP.h>
@@ -59,9 +60,14 @@
#include "intel_ringbuffer.h"
#include "i915_gem.h"
+#include "i915_gem_fence_reg.h"
+#include "i915_gem_object.h"
#include "i915_gem_gtt.h"
#include "i915_gem_render_state.h"
#include "i915_gem_request.h"
+#include "i915_gem_timeline.h"
+
+#include "i915_vma.h"
#include "intel_gvt.h"
@@ -70,7 +76,8 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20160919"
+#define DRIVER_DATE "20161121"
+#define DRIVER_TIMESTAMP 1479717903
#undef WARN_ON
/* Many gcc seem to no see through this and fall over :( */
@@ -122,6 +129,11 @@ static inline const char *onoff(bool v)
return v ? "on" : "off";
}
+static inline const char *enableddisabled(bool v)
+{
+ return v ? "enabled" : "disabled";
+}
+
enum pipe {
INVALID_PIPE = -1,
PIPE_A = 0,
@@ -182,9 +194,10 @@ enum plane {
};
#define plane_name(p) ((p) + 'A')
-#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A')
+#define sprite_name(p, s) ((p) * INTEL_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
enum port {
+ PORT_NONE = -1,
PORT_A = 0,
PORT_B,
PORT_C,
@@ -310,7 +323,7 @@ struct i915_hotplug {
#define for_each_pipe_masked(__dev_priv, __p, __mask) \
for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \
for_each_if ((__mask) & (1 << (__p)))
-#define for_each_plane(__dev_priv, __pipe, __p) \
+#define for_each_universal_plane(__dev_priv, __pipe, __p) \
for ((__p) = 0; \
(__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \
(__p)++)
@@ -455,23 +468,6 @@ struct intel_opregion {
struct intel_overlay;
struct intel_overlay_error_state;
-struct drm_i915_fence_reg {
- struct list_head link;
- struct drm_i915_private *i915;
- struct i915_vma *vma;
- int pin_count;
- int id;
- /**
- * Whether the tiling parameters for the currently
- * associated fence register have changed. Note that
- * for the purposes of tracking tiling changes we also
- * treat the unfenced register, the register slot that
- * the object occupies whilst it executes a fenced
- * command (such as BLT on gen2/3), as a "fence".
- */
- bool dirty;
-};
-
struct sdvo_device_mapping {
u8 initialized;
u8 dvo_port;
@@ -483,6 +479,7 @@ struct sdvo_device_mapping {
struct intel_connector;
struct intel_encoder;
+struct intel_atomic_state;
struct intel_crtc_state;
struct intel_initial_plane_config;
struct intel_crtc;
@@ -490,16 +487,20 @@ struct intel_limit;
struct dpll;
struct drm_i915_display_funcs {
- int (*get_display_clock_speed)(struct drm_device *dev);
- int (*get_fifo_size)(struct drm_device *dev, int plane);
+ int (*get_display_clock_speed)(struct drm_i915_private *dev_priv);
+ int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
int (*compute_intermediate_wm)(struct drm_device *dev,
struct intel_crtc *intel_crtc,
struct intel_crtc_state *newstate);
- void (*initial_watermarks)(struct intel_crtc_state *cstate);
- void (*optimize_watermarks)(struct intel_crtc_state *cstate);
+ void (*initial_watermarks)(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate);
+ void (*atomic_update_watermarks)(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate);
+ void (*optimize_watermarks)(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate);
int (*compute_global_watermarks)(struct drm_atomic_state *state);
- void (*update_wm)(struct drm_crtc *crtc);
+ void (*update_wm)(struct intel_crtc *crtc);
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
/* Returns the active state of the crtc, and if the crtc is active,
@@ -521,7 +522,7 @@ struct drm_i915_display_funcs {
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);
+ void (*init_clock_gating)(struct drm_i915_private *dev_priv);
int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj,
@@ -558,6 +559,18 @@ enum forcewake_domains {
#define FW_REG_READ (1)
#define FW_REG_WRITE (2)
+enum decoupled_power_domain {
+ GEN9_DECOUPLED_PD_BLITTER = 0,
+ GEN9_DECOUPLED_PD_RENDER,
+ GEN9_DECOUPLED_PD_MEDIA,
+ GEN9_DECOUPLED_PD_ALL
+};
+
+enum decoupled_ops {
+ GEN9_DECOUPLED_OP_WRITE = 0,
+ GEN9_DECOUPLED_OP_READ
+};
+
enum forcewake_domains
intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
i915_reg_t reg, unsigned int op);
@@ -581,13 +594,25 @@ struct intel_uncore_funcs {
uint32_t val, bool trace);
};
+struct intel_forcewake_range {
+ u32 start;
+ u32 end;
+
+ enum forcewake_domains domains;
+};
+
struct intel_uncore {
spinlock_t lock; /** lock is also taken in irq contexts. */
+ const struct intel_forcewake_range *fw_domains_table;
+ unsigned int fw_domains_table_entries;
+
struct intel_uncore_funcs funcs;
unsigned fifo_count;
+
enum forcewake_domains fw_domains;
+ enum forcewake_domains fw_domains_active;
struct intel_uncore_forcewake_domain {
struct drm_i915_private *i915;
@@ -633,54 +658,55 @@ struct intel_csr {
uint32_t allowed_dc_mask;
};
-#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
- func(is_mobile) sep \
- func(is_i85x) sep \
- func(is_i915g) sep \
- func(is_i945gm) sep \
- func(is_g33) sep \
- func(hws_needs_physical) sep \
- func(is_g4x) sep \
- func(is_pineview) sep \
- func(is_broadwater) sep \
- func(is_crestline) sep \
- func(is_ivybridge) sep \
- func(is_valleyview) sep \
- func(is_cherryview) sep \
- func(is_haswell) sep \
- func(is_broadwell) sep \
- func(is_skylake) sep \
- func(is_broxton) sep \
- func(is_kabylake) sep \
- func(is_preliminary) sep \
- func(has_fbc) sep \
- func(has_psr) sep \
- func(has_runtime_pm) sep \
- func(has_csr) sep \
- func(has_resource_streamer) sep \
- func(has_rc6) sep \
- func(has_rc6p) sep \
- func(has_dp_mst) sep \
- func(has_gmbus_irq) sep \
- func(has_hw_contexts) sep \
- func(has_logical_ring_contexts) sep \
- func(has_l3_dpf) sep \
- func(has_gmch_display) sep \
- func(has_guc) sep \
- func(has_pipe_cxsr) sep \
- func(has_hotplug) sep \
- func(cursor_needs_physical) sep \
- func(has_overlay) sep \
- func(overlay_needs_physical) sep \
- func(supports_tv) sep \
- func(has_llc) sep \
- func(has_snoop) sep \
- func(has_ddi) sep \
- func(has_fpga_dbg) sep \
- func(has_pooled_eu)
-
-#define DEFINE_FLAG(name) u8 name:1
-#define SEP_SEMICOLON ;
+#define DEV_INFO_FOR_EACH_FLAG(func) \
+ /* Keep is_* in chronological order */ \
+ func(is_mobile); \
+ func(is_i85x); \
+ func(is_i915g); \
+ func(is_i945gm); \
+ func(is_g33); \
+ func(is_g4x); \
+ func(is_pineview); \
+ func(is_broadwater); \
+ func(is_crestline); \
+ func(is_ivybridge); \
+ func(is_valleyview); \
+ func(is_cherryview); \
+ func(is_haswell); \
+ func(is_broadwell); \
+ func(is_skylake); \
+ func(is_broxton); \
+ func(is_kabylake); \
+ func(is_alpha_support); \
+ /* Keep has_* in alphabetical order */ \
+ func(has_64bit_reloc); \
+ func(has_csr); \
+ func(has_ddi); \
+ func(has_dp_mst); \
+ func(has_fbc); \
+ func(has_fpga_dbg); \
+ func(has_gmbus_irq); \
+ func(has_gmch_display); \
+ func(has_guc); \
+ func(has_hotplug); \
+ func(has_hw_contexts); \
+ func(has_l3_dpf); \
+ func(has_llc); \
+ func(has_logical_ring_contexts); \
+ func(has_overlay); \
+ func(has_pipe_cxsr); \
+ func(has_pooled_eu); \
+ func(has_psr); \
+ func(has_rc6); \
+ func(has_rc6p); \
+ func(has_resource_streamer); \
+ func(has_runtime_pm); \
+ func(has_snoop); \
+ func(cursor_needs_physical); \
+ func(hws_needs_physical); \
+ func(overlay_needs_physical); \
+ func(supports_tv); \
+ func(has_decoupled_mmio)
struct sseu_dev_info {
u8 slice_mask;
@@ -709,7 +735,9 @@ struct intel_device_info {
u16 gen_mask;
u8 ring_mask; /* Rings supported by the HW */
u8 num_rings;
- DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
+#define DEFINE_FLAG(name) u8 name:1
+ DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
+#undef DEFINE_FLAG
u16 ddb_size; /* in blocks */
/* Register offsets for the various display pipes and transcoders */
int pipe_offsets[I915_MAX_TRANSCODERS];
@@ -726,14 +754,15 @@ struct intel_device_info {
} color;
};
-#undef DEFINE_FLAG
-#undef SEP_SEMICOLON
-
struct intel_display_error_state;
struct drm_i915_error_state {
struct kref ref;
struct timeval time;
+ struct timeval boottime;
+ struct timeval uptime;
+
+ struct drm_i915_private *i915;
char error_msg[128];
bool simulated;
@@ -759,11 +788,12 @@ struct drm_i915_error_state {
u32 gam_ecochk;
u32 gab_ctl;
u32 gfx_mode;
- u32 extra_instdone[I915_NUM_INSTDONE_REG];
+
u64 fence[I915_MAX_NUM_FENCES];
struct intel_overlay_error_state *overlay;
struct intel_display_error_state *display;
struct drm_i915_error_object *semaphore;
+ struct drm_i915_error_object *guc_log;
struct drm_i915_error_engine {
int engine_id;
@@ -775,12 +805,14 @@ struct drm_i915_error_state {
struct i915_address_space *vm;
int num_requests;
+ /* position of active request inside the ring */
+ u32 rq_head, rq_post, rq_tail;
+
/* our own tracking of ring head and tail */
u32 cpu_ring_head;
u32 cpu_ring_tail;
u32 last_seqno;
- u32 semaphore_seqno[I915_NUM_ENGINES - 1];
/* Register state */
u32 start;
@@ -791,7 +823,6 @@ struct drm_i915_error_state {
u32 hws;
u32 ipeir;
u32 ipehr;
- u32 instdone;
u32 bbstate;
u32 instpm;
u32 instps;
@@ -802,11 +833,13 @@ struct drm_i915_error_state {
u64 faddr;
u32 rc_psmi; /* sleep state */
u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
+ struct intel_instdone instdone;
struct drm_i915_error_object {
- int page_count;
u64 gtt_offset;
u64 gtt_size;
+ int page_count;
+ int unused;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
@@ -815,10 +848,11 @@ struct drm_i915_error_state {
struct drm_i915_error_request {
long jiffies;
pid_t pid;
+ u32 context;
u32 seqno;
u32 head;
u32 tail;
- } *requests;
+ } *requests, execlist[2];
struct drm_i915_error_waiter {
char comm[TASK_COMM_LEN];
@@ -914,6 +948,7 @@ struct i915_gem_context {
struct drm_i915_file_private *file_priv;
struct i915_hw_ppgtt *ppgtt;
struct pid *pid;
+ const char *name;
struct i915_ctx_hang_stats hang_stats;
@@ -924,6 +959,7 @@ struct i915_gem_context {
/* Unique identifier for this context, used by the hw for tracking */
unsigned int hw_id;
u32 user_handle;
+ int priority; /* greater priorities are serviced first */
u32 ggtt_alignment;
@@ -972,6 +1008,9 @@ struct intel_fbc {
bool enabled;
bool active;
+ bool underrun_detected;
+ struct work_struct underrun_work;
+
struct intel_fbc_state_cache {
struct {
unsigned int mode_flags;
@@ -1297,6 +1336,12 @@ struct i915_power_well {
/* cached hw enabled state */
bool hw_enabled;
unsigned long domains;
+ /* unique identifier for this power well */
+ unsigned long id;
+ /*
+ * Arbitraty data associated with this power well. Platform and power
+ * well specific.
+ */
unsigned long data;
const struct i915_power_well_ops *ops;
};
@@ -1334,11 +1379,22 @@ struct i915_gem_mm {
struct list_head bound_list;
/**
* List of objects which are not bound to the GTT (thus
- * are idle and not used by the GPU) but still have
- * (presumably uncached) pages still attached.
+ * are idle and not used by the GPU). These objects may or may
+ * not actually have any pages attached.
*/
struct list_head unbound_list;
+ /** List of all objects in gtt_space, currently mmaped by userspace.
+ * All objects within this list must also be on bound_list.
+ */
+ struct list_head userfault_list;
+
+ /**
+ * List of objects which are pending destruction.
+ */
+ struct llist_head free_list;
+ struct work_struct free_work;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
@@ -1368,7 +1424,7 @@ struct i915_gem_mm {
/* accounting, useful for userland debugging */
spinlock_t object_stat_lock;
- size_t object_memory;
+ u64 object_memory;
u32 object_count;
};
@@ -1387,6 +1443,9 @@ struct i915_error_state_file_priv {
struct drm_i915_error_state *error;
};
+#define I915_RESET_TIMEOUT (10 * HZ) /* 10s */
+#define I915_FENCE_TIMEOUT (10 * HZ) /* 10s */
+
struct i915_gpu_error {
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
@@ -1620,7 +1679,6 @@ 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];
};
@@ -1628,15 +1686,12 @@ struct skl_ddb_allocation {
struct skl_wm_values {
unsigned dirty_pipes;
struct skl_ddb_allocation ddb;
- uint32_t wm_linetime[I915_MAX_PIPES];
- uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8];
- uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES];
};
struct skl_wm_level {
- bool plane_en[I915_MAX_PLANES];
- uint16_t plane_res_b[I915_MAX_PLANES];
- uint8_t plane_res_l[I915_MAX_PLANES];
+ bool plane_en;
+ uint16_t plane_res_b;
+ uint8_t plane_res_l;
};
/*
@@ -1664,7 +1719,6 @@ struct skl_wm_level {
*/
struct i915_runtime_pm {
atomic_t wakeref_count;
- atomic_t atomic_seq;
bool suspended;
bool irqs_enabled;
};
@@ -1748,6 +1802,7 @@ struct drm_i915_private {
struct kmem_cache *objects;
struct kmem_cache *vmas;
struct kmem_cache *requests;
+ struct kmem_cache *dependencies;
const struct intel_device_info info;
@@ -1759,7 +1814,7 @@ struct drm_i915_private {
struct i915_virtual_gpu vgpu;
- struct intel_gvt gvt;
+ struct intel_gvt *gvt;
struct intel_guc guc;
@@ -1787,9 +1842,8 @@ struct drm_i915_private {
struct pci_dev *bridge_dev;
struct i915_gem_context *kernel_context;
- struct intel_engine_cs engine[I915_NUM_ENGINES];
+ struct intel_engine_cs *engine[I915_NUM_ENGINES];
struct i915_vma *semaphore;
- u32 next_seqno;
struct drm_dma_handle *status_page_dmah;
struct resource mch_res;
@@ -1814,8 +1868,10 @@ struct drm_i915_private {
u32 de_irq_mask[I915_MAX_PIPES];
};
u32 gt_irq_mask;
- u32 pm_irq_mask;
+ u32 pm_imr;
+ u32 pm_ier;
u32 pm_rps_events;
+ u32 pm_guc_events;
u32 pipestat_irq_mask[I915_MAX_PIPES];
struct i915_hotplug hotplug;
@@ -1892,8 +1948,8 @@ struct drm_i915_private {
/* Kernel Modesetting */
- struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
- struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
+ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
+ struct intel_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
wait_queue_head_t pending_flip_queue;
#ifdef CONFIG_DEBUG_FS
@@ -2009,13 +2065,6 @@ struct drm_i915_private {
*/
uint16_t skl_latency[8];
- /*
- * The skl_wm_values structure is a bit too big for stack
- * allocation, so we keep the staging struct where we store
- * intermediate results here instead.
- */
- struct skl_wm_values skl_results;
-
/* current hardware state */
union {
struct ilk_wm_values hw;
@@ -2047,6 +2096,10 @@ struct drm_i915_private {
void (*resume)(struct drm_i915_private *);
void (*cleanup_engine)(struct intel_engine_cs *engine);
+ struct list_head timelines;
+ struct i915_gem_timeline global_timeline;
+ u32 active_requests;
+
/**
* Is the GPU currently considered idle, or busy executing
* userspace requests? Whilst idle, we allow runtime power
@@ -2054,7 +2107,6 @@ struct drm_i915_private {
* In order to reduce the effect on performance, there
* is a slight delay before we do so.
*/
- unsigned int active_engines;
bool awake;
/**
@@ -2074,12 +2126,15 @@ struct drm_i915_private {
* off the idle_work.
*/
struct delayed_work idle_work;
+
+ ktime_t last_init_time;
} gt;
/* perform PHY state sanity checks? */
bool chv_phy_assert[2];
- struct intel_encoder *dig_port_map[I915_MAX_PORTS];
+ /* Used to save the pipe-to-encoder mapping for audio */
+ struct intel_encoder *av_enc_map[I915_MAX_PIPES];
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
@@ -2103,19 +2158,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
}
/* Simple iterator over all initialised engines */
-#define for_each_engine(engine__, dev_priv__) \
- for ((engine__) = &(dev_priv__)->engine[0]; \
- (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
- (engine__)++) \
- for_each_if (intel_engine_initialized(engine__))
-
-/* Iterator with engine_id */
-#define for_each_engine_id(engine__, dev_priv__, id__) \
- for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \
- (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
- (engine__)++) \
- for_each_if (((id__) = (engine__)->id, \
- intel_engine_initialized(engine__)))
+#define for_each_engine(engine__, dev_priv__, id__) \
+ for ((id__) = 0; \
+ (id__) < I915_NUM_ENGINES; \
+ (id__)++) \
+ for_each_if ((engine__) = (dev_priv__)->engine[(id__)])
#define __mask_next_bit(mask) ({ \
int __idx = ffs(mask) - 1; \
@@ -2126,7 +2173,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
/* Iterator over subset of engines selected by mask */
#define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \
for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \
- tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )
+ tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )
enum hdmi_force_audio {
HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */
@@ -2137,30 +2184,6 @@ enum hdmi_force_audio {
#define I915_GTT_OFFSET_NONE ((u32)-1)
-struct drm_i915_gem_object_ops {
- unsigned int flags;
-#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
-
- /* Interface between the GEM object and its backing storage.
- * get_pages() is called once prior to the use of the associated set
- * of pages before to binding them into the GTT, and put_pages() is
- * called after we no longer need them. As we expect there to be
- * associated cost with migrating pages between the backing storage
- * and making them available for the GPU (e.g. clflush), we may hold
- * onto the pages after they are no longer referenced by the GPU
- * in case they may be used again shortly (for example migrating the
- * pages to a different memory domain within the GTT). put_pages()
- * will therefore most likely be called when the object itself is
- * being released or under memory pressure (where we attempt to
- * reap pages for the shrinker).
- */
- int (*get_pages)(struct drm_i915_gem_object *);
- void (*put_pages)(struct drm_i915_gem_object *);
-
- int (*dmabuf_export)(struct drm_i915_gem_object *);
- void (*release)(struct drm_i915_gem_object *);
-};
-
/*
* Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is
* considered to be the frontbuffer for the given plane interface-wise. This
@@ -2182,232 +2205,6 @@ struct drm_i915_gem_object_ops {
#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
(0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
-struct drm_i915_gem_object {
- struct drm_gem_object base;
-
- const struct drm_i915_gem_object_ops *ops;
-
- /** List of VMAs backed by this object */
- struct list_head vma_list;
-
- /** Stolen memory for this object, instead of being backed by shmem. */
- struct drm_mm_node *stolen;
- struct list_head global_list;
-
- /** Used in execbuf to temporarily hold a ref */
- struct list_head obj_exec_link;
-
- struct list_head batch_pool_link;
-
- unsigned long flags;
- /**
- * This is set if the object is on the active lists (has pending
- * rendering and so a non-zero seqno), and is not set if it i s on
- * inactive (ready to be unbound) list.
- */
-#define I915_BO_ACTIVE_SHIFT 0
-#define I915_BO_ACTIVE_MASK ((1 << I915_NUM_ENGINES) - 1)
-#define __I915_BO_ACTIVE(bo) \
- ((READ_ONCE((bo)->flags) >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK)
-
- /**
- * This is set if the object has been written to since last bound
- * to the GTT
- */
- unsigned int dirty:1;
-
- /**
- * Advice: are the backing pages purgeable?
- */
- unsigned int madv:2;
-
- /**
- * Whether the current gtt mapping needs to be mappable (and isn't just
- * mappable by accident). Track pin and fault separate for a more
- * accurate mappable working set.
- */
- unsigned int fault_mappable:1;
-
- /*
- * Is the object to be mapped as read-only to the GPU
- * Only honoured if hardware has relevant pte bit
- */
- unsigned long gt_ro:1;
- unsigned int cache_level:3;
- unsigned int cache_dirty:1;
-
- atomic_t frontbuffer_bits;
- unsigned int frontbuffer_ggtt_origin; /* write once */
-
- /** Current tiling stride for the object, if it's tiled. */
- unsigned int tiling_and_stride;
-#define FENCE_MINIMUM_STRIDE 128 /* See i915_tiling_ok() */
-#define TILING_MASK (FENCE_MINIMUM_STRIDE-1)
-#define STRIDE_MASK (~TILING_MASK)
-
- /** Count of VMA actually bound by this object */
- unsigned int bind_count;
- unsigned int pin_display;
-
- struct sg_table *pages;
- int pages_pin_count;
- struct get_page {
- struct scatterlist *sg;
- int last;
- } get_page;
- void *mapping;
-
- /** Breadcrumb of last rendering to the buffer.
- * There can only be one writer, but we allow for multiple readers.
- * If there is a writer that necessarily implies that all other
- * read requests are complete - but we may only be lazily clearing
- * the read requests. A read request is naturally the most recent
- * request on a ring, so we may have two different write and read
- * requests on one ring where the write request is older than the
- * read request. This allows for the CPU to read from an active
- * buffer by only waiting for the write to complete.
- */
- struct i915_gem_active last_read[I915_NUM_ENGINES];
- struct i915_gem_active last_write;
-
- /** References from framebuffers, locks out tiling changes. */
- unsigned long framebuffer_references;
-
- /** Record of address bit 17 of each page at last unbind. */
- unsigned long *bit_17;
-
- struct i915_gem_userptr {
- uintptr_t ptr;
- unsigned read_only :1;
- unsigned workers :4;
-#define I915_GEM_USERPTR_MAX_WORKERS 15
-
- struct i915_mm_struct *mm;
- struct i915_mmu_object *mmu_object;
- struct work_struct *work;
- } userptr;
-
- /** for phys allocated objects */
- struct drm_dma_handle *phys_handle;
-};
-
-static inline struct drm_i915_gem_object *
-to_intel_bo(struct drm_gem_object *gem)
-{
- /* Assert that to_intel_bo(NULL) == NULL */
- BUILD_BUG_ON(offsetof(struct drm_i915_gem_object, base));
-
- return container_of(gem, struct drm_i915_gem_object, base);
-}
-
-static inline struct drm_i915_gem_object *
-i915_gem_object_lookup(struct drm_file *file, u32 handle)
-{
- return to_intel_bo(drm_gem_object_lookup(file, handle));
-}
-
-__deprecated
-extern struct drm_gem_object *
-drm_gem_object_lookup(struct drm_file *file, u32 handle);
-
-__attribute__((nonnull))
-static inline struct drm_i915_gem_object *
-i915_gem_object_get(struct drm_i915_gem_object *obj)
-{
- drm_gem_object_reference(&obj->base);
- return obj;
-}
-
-__deprecated
-extern void drm_gem_object_reference(struct drm_gem_object *);
-
-__attribute__((nonnull))
-static inline void
-i915_gem_object_put(struct drm_i915_gem_object *obj)
-{
- drm_gem_object_unreference(&obj->base);
-}
-
-__deprecated
-extern void drm_gem_object_unreference(struct drm_gem_object *);
-
-__attribute__((nonnull))
-static inline void
-i915_gem_object_put_unlocked(struct drm_i915_gem_object *obj)
-{
- drm_gem_object_unreference_unlocked(&obj->base);
-}
-
-__deprecated
-extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
-
-static inline bool
-i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
-{
- return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
-}
-
-static inline unsigned long
-i915_gem_object_get_active(const struct drm_i915_gem_object *obj)
-{
- return (obj->flags >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK;
-}
-
-static inline bool
-i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
-{
- return i915_gem_object_get_active(obj);
-}
-
-static inline void
-i915_gem_object_set_active(struct drm_i915_gem_object *obj, int engine)
-{
- obj->flags |= BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline void
-i915_gem_object_clear_active(struct drm_i915_gem_object *obj, int engine)
-{
- obj->flags &= ~BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline bool
-i915_gem_object_has_active_engine(const struct drm_i915_gem_object *obj,
- int engine)
-{
- return obj->flags & BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline unsigned int
-i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
-{
- return obj->tiling_and_stride & TILING_MASK;
-}
-
-static inline bool
-i915_gem_object_is_tiled(struct drm_i915_gem_object *obj)
-{
- return i915_gem_object_get_tiling(obj) != I915_TILING_NONE;
-}
-
-static inline unsigned int
-i915_gem_object_get_stride(struct drm_i915_gem_object *obj)
-{
- return obj->tiling_and_stride & STRIDE_MASK;
-}
-
-static inline struct i915_vma *i915_vma_get(struct i915_vma *vma)
-{
- i915_gem_object_get(vma->obj);
- return vma;
-}
-
-static inline void i915_vma_put(struct i915_vma *vma)
-{
- lockdep_assert_held(&vma->vm->dev->struct_mutex);
- i915_gem_object_put(vma->obj);
-}
-
/*
* Optimised SGL iterator for GEM objects
*/
@@ -2434,6 +2231,14 @@ static __always_inline struct sgt_iter {
return s;
}
+static inline struct scatterlist *____sg_next(struct scatterlist *sg)
+{
+ ++sg;
+ if (unlikely(sg_is_chain(sg)))
+ sg = sg_chain_ptr(sg);
+ return sg;
+}
+
/**
* __sg_next - return the next scatterlist entry in a list
* @sg: The current sg entry
@@ -2448,9 +2253,7 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg)
#ifdef CONFIG_DEBUG_SG
BUG_ON(sg->sg_magic != SG_MAGIC);
#endif
- return sg_is_last(sg) ? NULL :
- likely(!sg_is_chain(++sg)) ? sg :
- sg_chain_ptr(sg);
+ return sg_is_last(sg) ? NULL : ____sg_next(sg);
}
/**
@@ -2574,23 +2377,19 @@ struct drm_i915_cmd_table {
int count;
};
-/* Note that the (struct drm_i915_private *) cast is just to shut up gcc. */
-#define __I915__(p) ({ \
- struct drm_i915_private *__p; \
- if (__builtin_types_compatible_p(typeof(*p), struct drm_i915_private)) \
- __p = (struct drm_i915_private *)p; \
- else if (__builtin_types_compatible_p(typeof(*p), struct drm_device)) \
- __p = to_i915((struct drm_device *)p); \
- else \
- BUILD_BUG(); \
- __p; \
-})
-#define INTEL_INFO(p) (&__I915__(p)->info)
-#define INTEL_GEN(p) (INTEL_INFO(p)->gen)
-#define INTEL_DEVID(p) (INTEL_INFO(p)->device_id)
+static inline const struct intel_device_info *
+intel_info(const struct drm_i915_private *dev_priv)
+{
+ return &dev_priv->info;
+}
+
+#define INTEL_INFO(dev_priv) intel_info((dev_priv))
+
+#define INTEL_GEN(dev_priv) ((dev_priv)->info.gen)
+#define INTEL_DEVID(dev_priv) ((dev_priv)->info.device_id)
#define REVID_FOREVER 0xff
-#define INTEL_REVID(p) (__I915__(p)->drm.pdev->revision)
+#define INTEL_REVID(dev_priv) ((dev_priv)->drm.pdev->revision)
#define GEN_FOREVER (0)
/*
@@ -2598,7 +2397,7 @@ struct drm_i915_cmd_table {
*
* Use GEN_FOREVER for unbound start and or end.
*/
-#define IS_GEN(p, s, e) ({ \
+#define IS_GEN(dev_priv, s, e) ({ \
unsigned int __s = (s), __e = (e); \
BUILD_BUG_ON(!__builtin_constant_p(s)); \
BUILD_BUG_ON(!__builtin_constant_p(e)); \
@@ -2608,7 +2407,7 @@ struct drm_i915_cmd_table {
__e = BITS_PER_LONG - 1; \
else \
__e = (e) - 1; \
- !!(INTEL_INFO(p)->gen_mask & GENMASK((__e), (__s))); \
+ !!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \
})
/*
@@ -2619,75 +2418,75 @@ struct drm_i915_cmd_table {
#define IS_REVID(p, since, until) \
(INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
-#define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577)
-#define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562)
-#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x)
-#define IS_I865G(dev) (INTEL_DEVID(dev) == 0x2572)
-#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g)
-#define IS_I915GM(dev) (INTEL_DEVID(dev) == 0x2592)
-#define IS_I945G(dev) (INTEL_DEVID(dev) == 0x2772)
-#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm)
-#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater)
-#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline)
-#define IS_GM45(dev) (INTEL_DEVID(dev) == 0x2A42)
-#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x)
-#define IS_PINEVIEW_G(dev) (INTEL_DEVID(dev) == 0xa001)
-#define IS_PINEVIEW_M(dev) (INTEL_DEVID(dev) == 0xa011)
-#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview)
-#define IS_G33(dev) (INTEL_INFO(dev)->is_g33)
-#define IS_IRONLAKE_M(dev) (INTEL_DEVID(dev) == 0x0046)
-#define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge)
-#define IS_IVB_GT1(dev) (INTEL_DEVID(dev) == 0x0156 || \
- INTEL_DEVID(dev) == 0x0152 || \
- INTEL_DEVID(dev) == 0x015a)
-#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
-#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview)
-#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
-#define IS_BROADWELL(dev) (INTEL_INFO(dev)->is_broadwell)
-#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake)
-#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton)
-#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake)
-#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
-#define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \
- (INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
-#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \
- ((INTEL_DEVID(dev) & 0xf) == 0x6 || \
- (INTEL_DEVID(dev) & 0xf) == 0xb || \
- (INTEL_DEVID(dev) & 0xf) == 0xe))
+#define IS_I830(dev_priv) (INTEL_DEVID(dev_priv) == 0x3577)
+#define IS_845G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2562)
+#define IS_I85X(dev_priv) ((dev_priv)->info.is_i85x)
+#define IS_I865G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2572)
+#define IS_I915G(dev_priv) ((dev_priv)->info.is_i915g)
+#define IS_I915GM(dev_priv) (INTEL_DEVID(dev_priv) == 0x2592)
+#define IS_I945G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2772)
+#define IS_I945GM(dev_priv) ((dev_priv)->info.is_i945gm)
+#define IS_BROADWATER(dev_priv) ((dev_priv)->info.is_broadwater)
+#define IS_CRESTLINE(dev_priv) ((dev_priv)->info.is_crestline)
+#define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42)
+#define IS_G4X(dev_priv) ((dev_priv)->info.is_g4x)
+#define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001)
+#define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011)
+#define IS_PINEVIEW(dev_priv) ((dev_priv)->info.is_pineview)
+#define IS_G33(dev_priv) ((dev_priv)->info.is_g33)
+#define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046)
+#define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.is_ivybridge)
+#define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \
+ INTEL_DEVID(dev_priv) == 0x0152 || \
+ INTEL_DEVID(dev_priv) == 0x015a)
+#define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.is_valleyview)
+#define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.is_cherryview)
+#define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell)
+#define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell)
+#define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake)
+#define IS_BROXTON(dev_priv) ((dev_priv)->info.is_broxton)
+#define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake)
+#define IS_MOBILE(dev_priv) ((dev_priv)->info.is_mobile)
+#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
+#define IS_BDW_ULT(dev_priv) (IS_BROADWELL(dev_priv) && \
+ ((INTEL_DEVID(dev_priv) & 0xf) == 0x6 || \
+ (INTEL_DEVID(dev_priv) & 0xf) == 0xb || \
+ (INTEL_DEVID(dev_priv) & 0xf) == 0xe))
/* ULX machines are also considered ULT. */
-#define IS_BDW_ULX(dev) (IS_BROADWELL(dev) && \
- (INTEL_DEVID(dev) & 0xf) == 0xe)
-#define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \
- (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
-#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \
- (INTEL_DEVID(dev) & 0xFF00) == 0x0A00)
-#define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \
- (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
+#define IS_BDW_ULX(dev_priv) (IS_BROADWELL(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0xf) == 0xe)
+#define IS_BDW_GT3(dev_priv) (IS_BROADWELL(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
+#define IS_HSW_ULT(dev_priv) (IS_HASWELL(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00)
+#define IS_HSW_GT3(dev_priv) (IS_HASWELL(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
/* ULX machines are also considered ULT. */
-#define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \
- INTEL_DEVID(dev) == 0x0A1E)
-#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \
- INTEL_DEVID(dev) == 0x1913 || \
- INTEL_DEVID(dev) == 0x1916 || \
- INTEL_DEVID(dev) == 0x1921 || \
- INTEL_DEVID(dev) == 0x1926)
-#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \
- INTEL_DEVID(dev) == 0x1915 || \
- INTEL_DEVID(dev) == 0x191E)
-#define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \
- INTEL_DEVID(dev) == 0x5913 || \
- INTEL_DEVID(dev) == 0x5916 || \
- INTEL_DEVID(dev) == 0x5921 || \
- INTEL_DEVID(dev) == 0x5926)
-#define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \
- INTEL_DEVID(dev) == 0x5915 || \
- INTEL_DEVID(dev) == 0x591E)
-#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 IS_HSW_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x0A0E || \
+ INTEL_DEVID(dev_priv) == 0x0A1E)
+#define IS_SKL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x1906 || \
+ INTEL_DEVID(dev_priv) == 0x1913 || \
+ INTEL_DEVID(dev_priv) == 0x1916 || \
+ INTEL_DEVID(dev_priv) == 0x1921 || \
+ INTEL_DEVID(dev_priv) == 0x1926)
+#define IS_SKL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x190E || \
+ INTEL_DEVID(dev_priv) == 0x1915 || \
+ INTEL_DEVID(dev_priv) == 0x191E)
+#define IS_KBL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x5906 || \
+ INTEL_DEVID(dev_priv) == 0x5913 || \
+ INTEL_DEVID(dev_priv) == 0x5916 || \
+ INTEL_DEVID(dev_priv) == 0x5921 || \
+ INTEL_DEVID(dev_priv) == 0x5926)
+#define IS_KBL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x590E || \
+ INTEL_DEVID(dev_priv) == 0x5915 || \
+ INTEL_DEVID(dev_priv) == 0x591E)
+#define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
+#define IS_SKL_GT4(dev_priv) (IS_SKYLAKE(dev_priv) && \
+ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0030)
+
+#define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support)
#define SKL_REVID_A0 0x0
#define SKL_REVID_B0 0x1
@@ -2705,7 +2504,8 @@ struct drm_i915_cmd_table {
#define BXT_REVID_B0 0x3
#define BXT_REVID_C0 0x9
-#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until))
+#define IS_BXT_REVID(dev_priv, since, until) \
+ (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until))
#define KBL_REVID_A0 0x0
#define KBL_REVID_B0 0x1
@@ -2713,8 +2513,8 @@ struct drm_i915_cmd_table {
#define KBL_REVID_D0 0x3
#define KBL_REVID_E0 0x4
-#define IS_KBL_REVID(p, since, until) \
- (IS_KABYLAKE(p) && IS_REVID(p, since, until))
+#define IS_KBL_REVID(dev_priv, since, until) \
+ (IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until))
/*
* The genX designation typically refers to the render engine, so render
@@ -2722,14 +2522,14 @@ struct drm_i915_cmd_table {
* have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular
* chips, etc.).
*/
-#define IS_GEN2(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(1)))
-#define IS_GEN3(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(2)))
-#define IS_GEN4(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(3)))
-#define IS_GEN5(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(4)))
-#define IS_GEN6(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(5)))
-#define IS_GEN7(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(6)))
-#define IS_GEN8(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(7)))
-#define IS_GEN9(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(8)))
+#define IS_GEN2(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(1)))
+#define IS_GEN3(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(2)))
+#define IS_GEN4(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(3)))
+#define IS_GEN5(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(4)))
+#define IS_GEN6(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(5)))
+#define IS_GEN7(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(6)))
+#define IS_GEN8(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(7)))
+#define IS_GEN9(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(8)))
#define ENGINE_MASK(id) BIT(id)
#define RENDER_RING ENGINE_MASK(RCS)
@@ -2740,31 +2540,34 @@ struct drm_i915_cmd_table {
#define ALL_ENGINES (~0)
#define HAS_ENGINE(dev_priv, id) \
- (!!(INTEL_INFO(dev_priv)->ring_mask & ENGINE_MASK(id)))
+ (!!((dev_priv)->info.ring_mask & ENGINE_MASK(id)))
#define HAS_BSD(dev_priv) HAS_ENGINE(dev_priv, VCS)
#define HAS_BSD2(dev_priv) HAS_ENGINE(dev_priv, VCS2)
#define HAS_BLT(dev_priv) HAS_ENGINE(dev_priv, BCS)
#define HAS_VEBOX(dev_priv) HAS_ENGINE(dev_priv, VECS)
-#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc)
-#define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop)
-#define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED))
-#define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \
- HAS_EDRAM(dev))
-#define HWS_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->hws_needs_physical)
+#define HAS_LLC(dev_priv) ((dev_priv)->info.has_llc)
+#define HAS_SNOOP(dev_priv) ((dev_priv)->info.has_snoop)
+#define HAS_EDRAM(dev_priv) (!!((dev_priv)->edram_cap & EDRAM_ENABLED))
+#define HAS_WT(dev_priv) ((IS_HASWELL(dev_priv) || \
+ IS_BROADWELL(dev_priv)) && HAS_EDRAM(dev_priv))
-#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts)
-#define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->has_logical_ring_contexts)
-#define USES_PPGTT(dev) (i915.enable_ppgtt)
-#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt >= 2)
-#define USES_FULL_48BIT_PPGTT(dev) (i915.enable_ppgtt == 3)
+#define HWS_NEEDS_PHYSICAL(dev_priv) ((dev_priv)->info.hws_needs_physical)
-#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
-#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
+#define HAS_HW_CONTEXTS(dev_priv) ((dev_priv)->info.has_hw_contexts)
+#define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \
+ ((dev_priv)->info.has_logical_ring_contexts)
+#define USES_PPGTT(dev_priv) (i915.enable_ppgtt)
+#define USES_FULL_PPGTT(dev_priv) (i915.enable_ppgtt >= 2)
+#define USES_FULL_48BIT_PPGTT(dev_priv) (i915.enable_ppgtt == 3)
+
+#define HAS_OVERLAY(dev_priv) ((dev_priv)->info.has_overlay)
+#define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
+ ((dev_priv)->info.overlay_needs_physical)
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
-#define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev))
+#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_845G(dev_priv))
/* WaRsDisableCoarsePowerGating:skl,bxt */
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
@@ -2778,46 +2581,49 @@ struct drm_i915_cmd_table {
* legacy irq no. is shared with another device. The kernel then disables that
* interrupt source and so prevents the other device from working properly.
*/
-#define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
-#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->has_gmbus_irq)
+#define HAS_AUX_IRQ(dev_priv) ((dev_priv)->info.gen >= 5)
+#define HAS_GMBUS_IRQ(dev_priv) ((dev_priv)->info.has_gmbus_irq)
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
* rows, which changed the alignment requirements and fence programming.
*/
-#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
- IS_I915GM(dev)))
-#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv)
-#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
+#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \
+ !(IS_I915G(dev_priv) || \
+ IS_I915GM(dev_priv)))
+#define SUPPORTS_TV(dev_priv) ((dev_priv)->info.supports_tv)
+#define I915_HAS_HOTPLUG(dev_priv) ((dev_priv)->info.has_hotplug)
+
+#define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2)
+#define HAS_PIPE_CXSR(dev_priv) ((dev_priv)->info.has_pipe_cxsr)
+#define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc)
-#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
-#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
-#define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
-#define HAS_IPS(dev) (IS_HSW_ULT(dev) || IS_BROADWELL(dev))
+#define HAS_DP_MST(dev_priv) ((dev_priv)->info.has_dp_mst)
-#define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst)
+#define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi)
+#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) ((dev_priv)->info.has_fpga_dbg)
+#define HAS_PSR(dev_priv) ((dev_priv)->info.has_psr)
+#define HAS_RC6(dev_priv) ((dev_priv)->info.has_rc6)
+#define HAS_RC6p(dev_priv) ((dev_priv)->info.has_rc6p)
-#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
-#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
-#define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr)
-#define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm)
-#define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
-#define HAS_RC6p(dev) (INTEL_INFO(dev)->has_rc6p)
+#define HAS_CSR(dev_priv) ((dev_priv)->info.has_csr)
-#define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr)
+#define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm)
+#define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc)
/*
* For now, anything with a GuC requires uCode loading, and then supports
* command submission once loaded. But these are logically independent
* properties, so we have separate macros to test them.
*/
-#define HAS_GUC(dev) (INTEL_INFO(dev)->has_guc)
-#define HAS_GUC_UCODE(dev) (HAS_GUC(dev))
-#define HAS_GUC_SCHED(dev) (HAS_GUC(dev))
+#define HAS_GUC(dev_priv) ((dev_priv)->info.has_guc)
+#define HAS_GUC_UCODE(dev_priv) (HAS_GUC(dev_priv))
+#define HAS_GUC_SCHED(dev_priv) (HAS_GUC(dev_priv))
-#define HAS_RESOURCE_STREAMER(dev) (INTEL_INFO(dev)->has_resource_streamer)
+#define HAS_RESOURCE_STREAMER(dev_priv) ((dev_priv)->info.has_resource_streamer)
-#define HAS_POOLED_EU(dev) (INTEL_INFO(dev)->has_pooled_eu)
+#define HAS_POOLED_EU(dev_priv) ((dev_priv)->info.has_pooled_eu)
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
@@ -2832,26 +2638,33 @@ struct drm_i915_cmd_table {
#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000
#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
-#define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
-#define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP)
-#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_LPT_H(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_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)
-#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
+#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
+#define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP)
+#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT)
+#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT)
+#define HAS_PCH_LPT_LP(dev_priv) \
+ ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
+#define HAS_PCH_LPT_H(dev_priv) \
+ ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
+#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT)
+#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX)
+#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
+#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE)
-#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display)
+#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display)
+
+#define HAS_LSPCON(dev_priv) (IS_GEN9(dev_priv))
/* DPF == dynamic parity feature */
-#define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf)
-#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
+#define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf)
+#define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \
+ 2 : HAS_L3_DPF(dev_priv))
#define GT_FREQUENCY_MULTIPLIER 50
#define GEN9_FREQ_SCALER 3
+#define HAS_DECOUPLED_MMIO(dev_priv) (INTEL_INFO(dev_priv)->has_decoupled_mmio)
+
#include "i915_trace.h"
static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
@@ -2882,6 +2695,8 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
#ifdef CONFIG_COMPAT
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
+#else
+#define i915_compat_ioctl NULL
#endif
extern const struct dev_pm_ops i915_pm_ops;
@@ -2893,6 +2708,7 @@ extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
extern void i915_reset(struct drm_i915_private *dev_priv);
extern int intel_guc_reset(struct drm_i915_private *dev_priv);
extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
+extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -2974,7 +2790,7 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
{
- return dev_priv->gvt.initialized;
+ return dev_priv->gvt;
}
static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv)
@@ -3076,7 +2892,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-void i915_gem_load_init(struct drm_device *dev);
+int i915_gem_load_init(struct drm_device *dev);
void i915_gem_load_cleanup(struct drm_device *dev);
void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
int i915_gem_freeze(struct drm_i915_private *dev_priv);
@@ -3087,7 +2903,7 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj);
void i915_gem_object_init(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_object_ops *ops);
struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
- size_t size);
+ u64 size);
struct drm_i915_gem_object *i915_gem_object_create_from_data(
struct drm_device *dev, const void *data, size_t size);
void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
@@ -3100,77 +2916,86 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
u64 alignment,
u64 flags);
-int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
- u32 flags);
-void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
-int __must_check i915_vma_unbind(struct i915_vma *vma);
-void i915_vma_close(struct i915_vma *vma);
-void i915_vma_destroy(struct i915_vma *vma);
-
int i915_gem_object_unbind(struct drm_i915_gem_object *obj);
-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);
-int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv);
-static inline int __sg_page_count(struct scatterlist *sg)
+static inline int __sg_page_count(const struct scatterlist *sg)
{
return sg->length >> PAGE_SHIFT;
}
+struct scatterlist *
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+ unsigned int n, unsigned int *offset);
+
+struct page *
+i915_gem_object_get_page(struct drm_i915_gem_object *obj,
+ unsigned int n);
+
struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n);
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+ unsigned int n);
-static inline dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, int n)
+dma_addr_t
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
+ unsigned long n);
+
+void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages);
+int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
+
+static inline int __must_check
+i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
{
- if (n < obj->get_page.last) {
- obj->get_page.sg = obj->pages->sgl;
- obj->get_page.last = 0;
- }
+ might_lock(&obj->mm.lock);
- while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) {
- obj->get_page.last += __sg_page_count(obj->get_page.sg++);
- if (unlikely(sg_is_chain(obj->get_page.sg)))
- obj->get_page.sg = sg_chain_ptr(obj->get_page.sg);
- }
+ if (atomic_inc_not_zero(&obj->mm.pages_pin_count))
+ return 0;
- return sg_dma_address(obj->get_page.sg) + ((n - obj->get_page.last) << PAGE_SHIFT);
+ return __i915_gem_object_get_pages(obj);
}
-static inline struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
+static inline void
+__i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
{
- if (WARN_ON(n >= obj->base.size >> PAGE_SHIFT))
- return NULL;
-
- if (n < obj->get_page.last) {
- obj->get_page.sg = obj->pages->sgl;
- obj->get_page.last = 0;
- }
+ GEM_BUG_ON(!obj->mm.pages);
- while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) {
- obj->get_page.last += __sg_page_count(obj->get_page.sg++);
- if (unlikely(sg_is_chain(obj->get_page.sg)))
- obj->get_page.sg = sg_chain_ptr(obj->get_page.sg);
- }
+ atomic_inc(&obj->mm.pages_pin_count);
+}
- return nth_page(sg_page(obj->get_page.sg), n - obj->get_page.last);
+static inline bool
+i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj)
+{
+ return atomic_read(&obj->mm.pages_pin_count);
}
-static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
+static inline void
+__i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
{
- BUG_ON(obj->pages == NULL);
- obj->pages_pin_count++;
+ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+ GEM_BUG_ON(!obj->mm.pages);
+
+ atomic_dec(&obj->mm.pages_pin_count);
+ GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
}
-static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
+static inline void
+i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
{
- BUG_ON(obj->pages_pin_count == 0);
- obj->pages_pin_count--;
+ __i915_gem_object_unpin_pages(obj);
}
+enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock */
+ I915_MM_NORMAL = 0,
+ I915_MM_SHRINKER
+};
+
+void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+ enum i915_mm_subclass subclass);
+void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj);
+
enum i915_map_type {
I915_MAP_WB = 0,
I915_MAP_WC,
@@ -3186,8 +3011,8 @@ enum i915_map_type {
* the kernel address space. Based on the @type of mapping, the PTE will be
* set to either WriteBack or WriteCombine (via pgprot_t).
*
- * The caller must hold the struct_mutex, and is responsible for calling
- * i915_gem_object_unpin_map() when the mapping is no longer required.
+ * The caller is responsible for calling i915_gem_object_unpin_map() when the
+ * mapping is no longer required.
*
* Returns the pointer through which to access the mapped object, or an
* ERR_PTR() on error.
@@ -3203,12 +3028,9 @@ void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
* with your access, call i915_gem_object_unpin_map() to release the pin
* upon the mapping. Once the pin count reaches zero, that mapping may be
* removed.
- *
- * The caller must hold the struct_mutex.
*/
static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj)
{
- lockdep_assert_held(&obj->base.dev->struct_mutex);
i915_gem_object_unpin_pages(obj);
}
@@ -3241,7 +3063,7 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
struct drm_i915_gem_object *new,
unsigned frontbuffer_bits);
-int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
+int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
struct drm_i915_gem_request *
i915_gem_find_active_request(struct intel_engine_cs *engine);
@@ -3270,19 +3092,25 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
void i915_gem_reset(struct drm_i915_private *dev_priv);
void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
-bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
+void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
int __must_check i915_gem_init(struct drm_device *dev);
int __must_check i915_gem_init_hw(struct drm_device *dev);
-void i915_gem_init_swizzling(struct drm_device *dev);
+void i915_gem_init_swizzling(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_engines(struct drm_device *dev);
int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
unsigned int flags);
int __must_check i915_gem_suspend(struct drm_device *dev);
void i915_gem_resume(struct drm_device *dev);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-int __must_check
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
- bool readonly);
+int i915_gem_object_wait(struct drm_i915_gem_object *obj,
+ unsigned int flags,
+ long timeout,
+ struct intel_rps_client *rps);
+int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+ unsigned int flags,
+ int priority);
+#define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
+
int __must_check
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
bool write);
@@ -3342,57 +3170,17 @@ i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
}
-/* i915_gem_fence.c */
+/* i915_gem_fence_reg.c */
int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma);
-/**
- * i915_vma_pin_fence - pin fencing state
- * @vma: vma to pin fencing for
- *
- * This pins the fencing state (whether tiled or untiled) to make sure the
- * vma (and its object) is ready to be used as a scanout target. Fencing
- * status must be synchronize first by calling i915_vma_get_fence():
- *
- * The resulting fence pin reference must be released again with
- * i915_vma_unpin_fence().
- *
- * Returns:
- *
- * True if the vma has a fence, false otherwise.
- */
-static inline bool
-i915_vma_pin_fence(struct i915_vma *vma)
-{
- if (vma->fence) {
- vma->fence->pin_count++;
- return true;
- } else
- return false;
-}
-
-/**
- * i915_vma_unpin_fence - unpin fencing state
- * @vma: vma to unpin fencing for
- *
- * This releases the fence pin reference acquired through
- * i915_vma_pin_fence. It will handle both objects with and without an
- * attached fence correctly, callers do not need to distinguish this.
- */
-static inline void
-i915_vma_unpin_fence(struct i915_vma *vma)
-{
- if (vma->fence) {
- GEM_BUG_ON(vma->fence->pin_count <= 0);
- vma->fence->pin_count--;
- }
-}
-
-void i915_gem_restore_fences(struct drm_device *dev);
+void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
-void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
-void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
-void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
+void i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv);
+void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
+ struct sg_table *pages);
+void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
+ struct sg_table *pages);
/* i915_gem_context.c */
int __must_check i915_gem_context_init(struct drm_device *dev);
@@ -3402,6 +3190,9 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct drm_i915_gem_request *req);
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
+struct i915_vma *
+i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
+ unsigned int flags);
void i915_gem_context_free(struct kref *ctx_ref);
struct drm_i915_gem_object *
i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
@@ -3435,6 +3226,16 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx)
kref_put(&ctx->ref, i915_gem_context_free);
}
+static inline struct intel_timeline *
+i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
+ struct intel_engine_cs *engine)
+{
+ struct i915_address_space *vm;
+
+ vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base;
+ return &vm->timeline.engine[engine->id];
+}
+
static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
{
return c->user_handle == DEFAULT_CONTEXT_HANDLE;
@@ -3478,7 +3279,7 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
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);
+int i915_gem_init_stolen(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_stolen(struct drm_device *dev);
struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
@@ -3488,6 +3289,11 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
u32 gtt_offset,
u32 size);
+/* i915_gem_internal.c */
+struct drm_i915_gem_object *
+i915_gem_object_create_internal(struct drm_i915_private *dev_priv,
+ unsigned int size);
+
/* i915_gem_shrinker.c */
unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
unsigned long target,
@@ -3526,6 +3332,8 @@ static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
#endif
/* i915_gpu_error.c */
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
@@ -3546,7 +3354,20 @@ void i915_error_state_get(struct drm_device *dev,
void i915_error_state_put(struct i915_error_state_file_priv *error_priv);
void i915_destroy_error_state(struct drm_device *dev);
-void i915_get_extra_instdone(struct drm_i915_private *dev_priv, uint32_t *instdone);
+#else
+
+static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
+ u32 engine_mask,
+ const char *error_msg)
+{
+}
+
+static inline void i915_destroy_error_state(struct drm_device *dev)
+{
+}
+
+#endif
+
const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
/* i915_cmd_parser.c */
@@ -3596,6 +3417,9 @@ bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum por
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
enum port port);
+bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
+ enum port port);
+
/* intel_opregion.c */
#ifdef CONFIG_ACPI
@@ -3652,15 +3476,16 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv);
/* modesetting */
extern void intel_modeset_init_hw(struct drm_device *dev);
-extern void intel_modeset_init(struct drm_device *dev);
+extern int intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_gem_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
extern int intel_connector_register(struct drm_connector *);
extern void intel_connector_unregister(struct drm_connector *);
-extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
+extern int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv,
+ bool state);
extern void intel_display_resume(struct drm_device *dev);
-extern void i915_redisable_vga(struct drm_device *dev);
-extern void i915_redisable_vga_power_on(struct drm_device *dev);
+extern void i915_redisable_vga(struct drm_i915_private *dev_priv);
+extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv);
extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val);
extern void intel_init_pch_refclk(struct drm_device *dev);
extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
@@ -3679,7 +3504,7 @@ extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
extern struct intel_display_error_state *
intel_display_capture_error_state(struct drm_i915_private *dev_priv);
extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
- struct drm_device *dev,
+ struct drm_i915_private *dev_priv,
struct intel_display_error_state *error);
int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val);
@@ -3707,6 +3532,23 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
/* intel_dpio_phy.c */
+void bxt_port_to_phy_channel(enum port port,
+ enum dpio_phy *phy, enum dpio_channel *ch);
+void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
+ enum port port, u32 margin, u32 scale,
+ u32 enable, u32 deemphasis);
+void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
+void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
+bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy);
+bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy);
+uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
+ uint8_t lane_count);
+void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
+ uint8_t lane_lat_optim_mask);
+uint8_t bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
+
void chv_set_phy_signal_level(struct intel_encoder *encoder,
u32 deemph_reg_value, u32 margin_reg_value,
bool uniq_trans_scale);
@@ -3796,11 +3638,30 @@ __raw_write(64, q)
#undef __raw_write
/* These are untraced mmio-accessors that are only valid to be used inside
- * critical sections inside IRQ handlers where forcewake is explicitly
+ * critical sections, such as inside IRQ handlers, where forcewake is explicitly
* controlled.
+ *
* Think twice, and think again, before using these.
- * Note: Should only be used between intel_uncore_forcewake_irqlock() and
- * intel_uncore_forcewake_irqunlock().
+ *
+ * As an example, these accessors can possibly be used between:
+ *
+ * spin_lock_irq(&dev_priv->uncore.lock);
+ * intel_uncore_forcewake_get__locked();
+ *
+ * and
+ *
+ * intel_uncore_forcewake_put__locked();
+ * spin_unlock_irq(&dev_priv->uncore.lock);
+ *
+ *
+ * Note: some registers may not need forcewake held, so
+ * intel_uncore_forcewake_{get,put} can be omitted, see
+ * intel_uncore_forcewake_for_reg().
+ *
+ * Certain architectures will die if the same cacheline is concurrently accessed
+ * by different clients (e.g. on Ivybridge). Access to registers should
+ * therefore generally be serialised, by either the dev_priv->uncore.lock or
+ * a more localised lock guarding all access to that bank of registers.
*/
#define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__))
#define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__))
@@ -3812,11 +3673,11 @@ __raw_write(64, q)
#define INTEL_BROADCAST_RGB_FULL 1
#define INTEL_BROADCAST_RGB_LIMITED 2
-static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
+static inline i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv)
{
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return VLV_VGACNTRL;
- else if (INTEL_INFO(dev)->gen >= 5)
+ else if (INTEL_GEN(dev_priv) >= 5)
return CPU_VGACNTRL;
else
return VGACNTRL;
@@ -3877,7 +3738,7 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req)
/* Before we do the heavier coherent read of the seqno,
* check the value (hopefully) in the CPU cacheline.
*/
- if (i915_gem_request_completed(req))
+ if (__i915_gem_request_completed(req))
return true;
/* Ensure our read of the seqno is coherent so that we
@@ -3928,7 +3789,7 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req)
wake_up_process(tsk);
rcu_read_unlock();
- if (i915_gem_request_completed(req))
+ if (__i915_gem_request_completed(req))
return true;
}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 00eb4814b913..d0dcaf35b429 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -29,12 +29,12 @@
#include <drm/drm_vma_manager.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
#include "i915_vgpu.h"
#include "i915_trace.h"
#include "intel_drv.h"
#include "intel_frontbuffer.h"
#include "intel_mocs.h"
+#include <linux/dma-fence-array.h>
#include <linux/reservation.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
@@ -42,13 +42,14 @@
#include <linux/pci.h>
#include <linux/dma-buf.h>
+static void i915_gem_flush_free_objects(struct drm_i915_private *i915);
static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
static bool cpu_cache_is_coherent(struct drm_device *dev,
enum i915_cache_level level)
{
- return HAS_LLC(dev) || level != I915_CACHE_NONE;
+ return HAS_LLC(to_i915(dev)) || level != I915_CACHE_NONE;
}
static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
@@ -63,13 +64,13 @@ static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
}
static int
-insert_mappable_node(struct drm_i915_private *i915,
+insert_mappable_node(struct i915_ggtt *ggtt,
struct drm_mm_node *node, u32 size)
{
memset(node, 0, sizeof(*node));
- return drm_mm_insert_node_in_range_generic(&i915->ggtt.base.mm, node,
- size, 0, 0, 0,
- i915->ggtt.mappable_end,
+ return drm_mm_insert_node_in_range_generic(&ggtt->base.mm, node,
+ size, 0, -1,
+ 0, ggtt->mappable_end,
DRM_MM_SEARCH_DEFAULT,
DRM_MM_CREATE_DEFAULT);
}
@@ -82,7 +83,7 @@ remove_mappable_node(struct drm_mm_node *node)
/* some bookkeeping */
static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
- size_t size)
+ u64 size)
{
spin_lock(&dev_priv->mm.object_stat_lock);
dev_priv->mm.object_count++;
@@ -91,7 +92,7 @@ static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
}
static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
- size_t size)
+ u64 size)
{
spin_lock(&dev_priv->mm.object_stat_lock);
dev_priv->mm.object_count--;
@@ -104,6 +105,8 @@ i915_gem_wait_for_error(struct i915_gpu_error *error)
{
int ret;
+ might_sleep();
+
if (!i915_reset_in_progress(error))
return 0;
@@ -114,7 +117,7 @@ i915_gem_wait_for_error(struct i915_gpu_error *error)
*/
ret = wait_event_interruptible_timeout(error->reset_queue,
!i915_reset_in_progress(error),
- 10*HZ);
+ I915_RESET_TIMEOUT);
if (ret == 0) {
DRM_ERROR("Timed out waiting for the gpu reset to complete\n");
return -EIO;
@@ -167,7 +170,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
return 0;
}
-static int
+static struct sg_table *
i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
{
struct address_space *mapping = obj->base.filp->f_mapping;
@@ -177,7 +180,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
int i;
if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
struct page *page;
@@ -185,7 +188,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
page = shmem_read_mapping_page(mapping, i);
if (IS_ERR(page))
- return PTR_ERR(page);
+ return ERR_CAST(page);
src = kmap_atomic(page);
memcpy(vaddr, src, PAGE_SIZE);
@@ -200,11 +203,11 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
if (sg_alloc_table(st, 1, GFP_KERNEL)) {
kfree(st);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
sg = st->sgl;
@@ -214,29 +217,33 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
sg_dma_address(sg) = obj->phys_handle->busaddr;
sg_dma_len(sg) = obj->base.size;
- obj->pages = st;
- return 0;
+ return st;
}
static void
-i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj)
+__i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
- int ret;
+ GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED);
- BUG_ON(obj->madv == __I915_MADV_PURGED);
+ if (obj->mm.madv == I915_MADV_DONTNEED)
+ obj->mm.dirty = false;
- ret = i915_gem_object_set_to_cpu_domain(obj, true);
- if (WARN_ON(ret)) {
- /* In the event of a disaster, abandon all caches and
- * hope for the best.
- */
- obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
- }
+ if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 &&
+ !cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
+ drm_clflush_sg(pages);
+
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+}
- if (obj->madv == I915_MADV_DONTNEED)
- obj->dirty = 0;
+static void
+i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
+{
+ __i915_gem_object_release_shmem(obj, pages);
- if (obj->dirty) {
+ if (obj->mm.dirty) {
struct address_space *mapping = obj->base.filp->f_mapping;
char *vaddr = obj->phys_handle->vaddr;
int i;
@@ -255,22 +262,23 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj)
kunmap_atomic(dst);
set_page_dirty(page);
- if (obj->madv == I915_MADV_WILLNEED)
+ if (obj->mm.madv == I915_MADV_WILLNEED)
mark_page_accessed(page);
put_page(page);
vaddr += PAGE_SIZE;
}
- obj->dirty = 0;
+ obj->mm.dirty = false;
}
- sg_free_table(obj->pages);
- kfree(obj->pages);
+ sg_free_table(pages);
+ kfree(pages);
}
static void
i915_gem_object_release_phys(struct drm_i915_gem_object *obj)
{
drm_pci_free(obj->base.dev, obj->phys_handle);
+ i915_gem_object_unpin_pages(obj);
}
static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {
@@ -292,7 +300,12 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj)
* must wait for all rendering to complete to the object (as unbinding
* must anyway), and retire the requests.
*/
- ret = i915_gem_object_wait_rendering(obj, false);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ I915_WAIT_ALL,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
@@ -311,90 +324,209 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj)
return ret;
}
-/**
- * Ensures that all rendering to the object has completed and the object is
- * safe to unbind from the GTT or access from the CPU.
- * @obj: i915 gem object
- * @readonly: waiting for just read access or read-write access
- */
-int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
- bool readonly)
+static long
+i915_gem_object_wait_fence(struct dma_fence *fence,
+ unsigned int flags,
+ long timeout,
+ struct intel_rps_client *rps)
{
- struct reservation_object *resv;
- struct i915_gem_active *active;
- unsigned long active_mask;
- int idx;
+ struct drm_i915_gem_request *rq;
- lockdep_assert_held(&obj->base.dev->struct_mutex);
+ BUILD_BUG_ON(I915_WAIT_INTERRUPTIBLE != 0x1);
- if (!readonly) {
- active = obj->last_read;
- active_mask = i915_gem_object_get_active(obj);
- } else {
- active_mask = 1;
- active = &obj->last_write;
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return timeout;
+
+ if (!dma_fence_is_i915(fence))
+ return dma_fence_wait_timeout(fence,
+ flags & I915_WAIT_INTERRUPTIBLE,
+ timeout);
+
+ rq = to_request(fence);
+ if (i915_gem_request_completed(rq))
+ goto out;
+
+ /* This client is about to stall waiting for the GPU. In many cases
+ * this is undesirable and limits the throughput of the system, as
+ * many clients cannot continue processing user input/output whilst
+ * blocked. RPS autotuning may take tens of milliseconds to respond
+ * to the GPU load and thus incurs additional latency for the client.
+ * We can circumvent that by promoting the GPU frequency to maximum
+ * before we wait. This makes the GPU throttle up much more quickly
+ * (good for benchmarks and user experience, e.g. window animations),
+ * but at a cost of spending more power processing the workload
+ * (bad for battery). Not all clients even want their results
+ * immediately and for them we should just let the GPU select its own
+ * frequency to maximise efficiency. To prevent a single client from
+ * forcing the clocks too high for the whole system, we only allow
+ * each client to waitboost once in a busy period.
+ */
+ if (rps) {
+ if (INTEL_GEN(rq->i915) >= 6)
+ gen6_rps_boost(rq->i915, rps, rq->emitted_jiffies);
+ else
+ rps = NULL;
}
- for_each_active(active_mask, idx) {
+ timeout = i915_wait_request(rq, flags, timeout);
+
+out:
+ if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq))
+ i915_gem_request_retire_upto(rq);
+
+ if (rps && rq->global_seqno == intel_engine_last_submit(rq->engine)) {
+ /* The GPU is now idle and this client has stalled.
+ * Since no other client has submitted a request in the
+ * meantime, assume that this client is the only one
+ * supplying work to the GPU but is unable to keep that
+ * work supplied because it is waiting. Since the GPU is
+ * then never kept fully busy, RPS autoclocking will
+ * keep the clocks relatively low, causing further delays.
+ * Compensate by giving the synchronous client credit for
+ * a waitboost next time.
+ */
+ spin_lock(&rq->i915->rps.client_lock);
+ list_del_init(&rps->link);
+ spin_unlock(&rq->i915->rps.client_lock);
+ }
+
+ return timeout;
+}
+
+static long
+i915_gem_object_wait_reservation(struct reservation_object *resv,
+ unsigned int flags,
+ long timeout,
+ struct intel_rps_client *rps)
+{
+ struct dma_fence *excl;
+
+ if (flags & I915_WAIT_ALL) {
+ struct dma_fence **shared;
+ unsigned int count, i;
int ret;
- ret = i915_gem_active_wait(&active[idx],
- &obj->base.dev->struct_mutex);
+ ret = reservation_object_get_fences_rcu(resv,
+ &excl, &count, &shared);
if (ret)
return ret;
- }
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (resv) {
- long err;
+ for (i = 0; i < count; i++) {
+ timeout = i915_gem_object_wait_fence(shared[i],
+ flags, timeout,
+ rps);
+ if (timeout <= 0)
+ break;
- err = reservation_object_wait_timeout_rcu(resv, !readonly, true,
- MAX_SCHEDULE_TIMEOUT);
- if (err < 0)
- return err;
+ dma_fence_put(shared[i]);
+ }
+
+ for (; i < count; i++)
+ dma_fence_put(shared[i]);
+ kfree(shared);
+ } else {
+ excl = reservation_object_get_excl_rcu(resv);
}
- return 0;
+ if (excl && timeout > 0)
+ timeout = i915_gem_object_wait_fence(excl, flags, timeout, rps);
+
+ dma_fence_put(excl);
+
+ return timeout;
}
-/* A nonblocking variant of the above wait. Must be called prior to
- * acquiring the mutex for the object, as the object state may change
- * during this call. A reference must be held by the caller for the object.
- */
-static __must_check int
-__unsafe_wait_rendering(struct drm_i915_gem_object *obj,
- struct intel_rps_client *rps,
- bool readonly)
+static void __fence_set_priority(struct dma_fence *fence, int prio)
{
- struct i915_gem_active *active;
- unsigned long active_mask;
- int idx;
+ struct drm_i915_gem_request *rq;
+ struct intel_engine_cs *engine;
- active_mask = __I915_BO_ACTIVE(obj);
- if (!active_mask)
- return 0;
+ if (!dma_fence_is_i915(fence))
+ return;
+
+ rq = to_request(fence);
+ engine = rq->engine;
+ if (!engine->schedule)
+ return;
+
+ engine->schedule(rq, prio);
+}
+
+static void fence_set_priority(struct dma_fence *fence, int prio)
+{
+ /* Recurse once into a fence-array */
+ if (dma_fence_is_array(fence)) {
+ struct dma_fence_array *array = to_dma_fence_array(fence);
+ int i;
- if (!readonly) {
- active = obj->last_read;
+ for (i = 0; i < array->num_fences; i++)
+ __fence_set_priority(array->fences[i], prio);
} else {
- active_mask = 1;
- active = &obj->last_write;
+ __fence_set_priority(fence, prio);
}
+}
+
+int
+i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+ unsigned int flags,
+ int prio)
+{
+ struct dma_fence *excl;
- for_each_active(active_mask, idx) {
+ if (flags & I915_WAIT_ALL) {
+ struct dma_fence **shared;
+ unsigned int count, i;
int ret;
- ret = i915_gem_active_wait_unlocked(&active[idx],
- I915_WAIT_INTERRUPTIBLE,
- NULL, rps);
+ ret = reservation_object_get_fences_rcu(obj->resv,
+ &excl, &count, &shared);
if (ret)
return ret;
+
+ for (i = 0; i < count; i++) {
+ fence_set_priority(shared[i], prio);
+ dma_fence_put(shared[i]);
+ }
+
+ kfree(shared);
+ } else {
+ excl = reservation_object_get_excl_rcu(obj->resv);
}
+ if (excl) {
+ fence_set_priority(excl, prio);
+ dma_fence_put(excl);
+ }
return 0;
}
+/**
+ * Waits for rendering to the object to be completed
+ * @obj: i915 gem object
+ * @flags: how to wait (under a lock, for all rendering or just for writes etc)
+ * @timeout: how long to wait
+ * @rps: client (user process) to charge for any waitboosting
+ */
+int
+i915_gem_object_wait(struct drm_i915_gem_object *obj,
+ unsigned int flags,
+ long timeout,
+ struct intel_rps_client *rps)
+{
+ might_sleep();
+#if IS_ENABLED(CONFIG_LOCKDEP)
+ GEM_BUG_ON(debug_locks &&
+ !!lockdep_is_held(&obj->base.dev->struct_mutex) !=
+ !!(flags & I915_WAIT_LOCKED));
+#endif
+ GEM_BUG_ON(timeout < 0);
+
+ timeout = i915_gem_object_wait_reservation(obj->resv,
+ flags, timeout,
+ rps);
+ return timeout < 0 ? timeout : 0;
+}
+
static struct intel_rps_client *to_rps_client(struct drm_file *file)
{
struct drm_i915_file_private *fpriv = file->driver_priv;
@@ -416,7 +548,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
return 0;
}
- if (obj->madv != I915_MADV_WILLNEED)
+ if (obj->mm.madv != I915_MADV_WILLNEED)
return -EFAULT;
if (obj->base.filp == NULL)
@@ -426,9 +558,9 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
if (ret)
return ret;
- ret = i915_gem_object_put_pages(obj);
- if (ret)
- return ret;
+ __i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+ if (obj->mm.pages)
+ return -EBUSY;
/* create a new object */
phys = drm_pci_alloc(obj->base.dev, obj->base.size, align);
@@ -438,23 +570,29 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
obj->phys_handle = phys;
obj->ops = &i915_gem_phys_ops;
- return i915_gem_object_get_pages(obj);
+ return i915_gem_object_pin_pages(obj);
}
static int
i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
struct drm_i915_gem_pwrite *args,
- struct drm_file *file_priv)
+ struct drm_file *file)
{
struct drm_device *dev = obj->base.dev;
void *vaddr = obj->phys_handle->vaddr + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);
- int ret = 0;
+ int ret;
/* We manually control the domain here and pretend that it
* remains coherent i.e. in the GTT domain, like shmem_pwrite.
*/
- ret = i915_gem_object_wait_rendering(obj, false);
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ I915_WAIT_ALL,
+ MAX_SCHEDULE_TIMEOUT,
+ to_rps_client(file));
if (ret)
return ret;
@@ -516,7 +654,7 @@ i915_gem_create(struct drm_file *file,
ret = drm_gem_handle_create(file, &obj->base, &handle);
/* drop reference from allocate - handle holds it now */
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
if (ret)
return ret;
@@ -548,6 +686,8 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_create *args = data;
+ i915_gem_flush_free_objects(to_i915(dev));
+
return i915_gem_create(file, dev,
args->size, &args->handle);
}
@@ -614,21 +754,24 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
{
int ret;
- *needs_clflush = 0;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+ *needs_clflush = 0;
if (!i915_gem_object_has_struct_page(obj))
return -ENODEV;
- ret = i915_gem_object_wait_rendering(obj, true);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
- ret = i915_gem_object_get_pages(obj);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
return ret;
- i915_gem_object_pin_pages(obj);
-
i915_gem_object_flush_gtt_write_domain(obj);
/* If we're not in the cpu read domain, set ourself into the gtt
@@ -661,20 +804,25 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj,
{
int ret;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
*needs_clflush = 0;
if (!i915_gem_object_has_struct_page(obj))
return -ENODEV;
- ret = i915_gem_object_wait_rendering(obj, false);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ I915_WAIT_ALL,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
- ret = i915_gem_object_get_pages(obj);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
return ret;
- i915_gem_object_pin_pages(obj);
-
i915_gem_object_flush_gtt_write_domain(obj);
/* If we're not in the cpu write domain, set ourself into the
@@ -704,7 +852,7 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj,
obj->cache_dirty = true;
intel_fb_obj_invalidate(obj, ORIGIN_CPU);
- obj->dirty = 1;
+ obj->mm.dirty = true;
/* return with the pages pinned */
return 0;
@@ -713,32 +861,6 @@ err_unpin:
return ret;
}
-/* Per-page copy function for the shmem pread fastpath.
- * Flushes invalid cachelines before reading the target if
- * needs_clflush is set. */
-static int
-shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length,
- char __user *user_data,
- bool page_do_bit17_swizzling, bool needs_clflush)
-{
- char *vaddr;
- int ret;
-
- if (unlikely(page_do_bit17_swizzling))
- return -EINVAL;
-
- vaddr = kmap_atomic(page);
- if (needs_clflush)
- drm_clflush_virt_range(vaddr + shmem_page_offset,
- page_length);
- ret = __copy_to_user_inatomic(user_data,
- vaddr + shmem_page_offset,
- page_length);
- kunmap_atomic(vaddr);
-
- return ret ? -EFAULT : 0;
-}
-
static void
shmem_clflush_swizzled_range(char *addr, unsigned long length,
bool swizzled)
@@ -764,7 +886,7 @@ shmem_clflush_swizzled_range(char *addr, unsigned long length,
/* Only difference to the fast-path function is that this can handle bit17
* and uses non-atomic copy and kmap functions. */
static int
-shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
+shmem_pread_slow(struct page *page, int offset, int length,
char __user *user_data,
bool page_do_bit17_swizzling, bool needs_clflush)
{
@@ -773,60 +895,130 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
vaddr = kmap(page);
if (needs_clflush)
- shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
- page_length,
+ shmem_clflush_swizzled_range(vaddr + offset, length,
page_do_bit17_swizzling);
if (page_do_bit17_swizzling)
- ret = __copy_to_user_swizzled(user_data,
- vaddr, shmem_page_offset,
- page_length);
+ ret = __copy_to_user_swizzled(user_data, vaddr, offset, length);
else
- ret = __copy_to_user(user_data,
- vaddr + shmem_page_offset,
- page_length);
+ ret = __copy_to_user(user_data, vaddr + offset, length);
kunmap(page);
return ret ? - EFAULT : 0;
}
-static inline unsigned long
-slow_user_access(struct io_mapping *mapping,
- uint64_t page_base, int page_offset,
- char __user *user_data,
- unsigned long length, bool pwrite)
+static int
+shmem_pread(struct page *page, int offset, int length, char __user *user_data,
+ bool page_do_bit17_swizzling, bool needs_clflush)
+{
+ int ret;
+
+ ret = -ENODEV;
+ if (!page_do_bit17_swizzling) {
+ char *vaddr = kmap_atomic(page);
+
+ if (needs_clflush)
+ drm_clflush_virt_range(vaddr + offset, length);
+ ret = __copy_to_user_inatomic(user_data, vaddr + offset, length);
+ kunmap_atomic(vaddr);
+ }
+ if (ret == 0)
+ return 0;
+
+ return shmem_pread_slow(page, offset, length, user_data,
+ page_do_bit17_swizzling, needs_clflush);
+}
+
+static int
+i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
+ struct drm_i915_gem_pread *args)
+{
+ char __user *user_data;
+ u64 remain;
+ unsigned int obj_do_bit17_swizzling;
+ unsigned int needs_clflush;
+ unsigned int idx, offset;
+ int ret;
+
+ obj_do_bit17_swizzling = 0;
+ if (i915_gem_object_needs_bit17_swizzle(obj))
+ obj_do_bit17_swizzling = BIT(17);
+
+ ret = mutex_lock_interruptible(&obj->base.dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
+ mutex_unlock(&obj->base.dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ remain = args->size;
+ user_data = u64_to_user_ptr(args->data_ptr);
+ offset = offset_in_page(args->offset);
+ for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
+ struct page *page = i915_gem_object_get_page(obj, idx);
+ int length;
+
+ length = remain;
+ if (offset + length > PAGE_SIZE)
+ length = PAGE_SIZE - offset;
+
+ ret = shmem_pread(page, offset, length, user_data,
+ page_to_phys(page) & obj_do_bit17_swizzling,
+ needs_clflush);
+ if (ret)
+ break;
+
+ remain -= length;
+ user_data += length;
+ offset = 0;
+ }
+
+ i915_gem_obj_finish_shmem_access(obj);
+ return ret;
+}
+
+static inline bool
+gtt_user_read(struct io_mapping *mapping,
+ loff_t base, int offset,
+ char __user *user_data, int length)
{
- void __iomem *ioaddr;
void *vaddr;
- uint64_t unwritten;
+ unsigned long unwritten;
- ioaddr = io_mapping_map_wc(mapping, page_base, PAGE_SIZE);
/* We can use the cpu mem copy function because this is X86. */
- vaddr = (void __force *)ioaddr + page_offset;
- if (pwrite)
- unwritten = __copy_from_user(vaddr, user_data, length);
- else
- unwritten = __copy_to_user(user_data, vaddr, length);
-
- io_mapping_unmap(ioaddr);
+ vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base);
+ unwritten = __copy_to_user_inatomic(user_data, vaddr + offset, length);
+ io_mapping_unmap_atomic(vaddr);
+ if (unwritten) {
+ vaddr = (void __force *)
+ io_mapping_map_wc(mapping, base, PAGE_SIZE);
+ unwritten = copy_to_user(user_data, vaddr + offset, length);
+ io_mapping_unmap(vaddr);
+ }
return unwritten;
}
static int
-i915_gem_gtt_pread(struct drm_device *dev,
- struct drm_i915_gem_object *obj, uint64_t size,
- uint64_t data_offset, uint64_t data_ptr)
+i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
+ const struct drm_i915_gem_pread *args)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- struct i915_vma *vma;
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ struct i915_ggtt *ggtt = &i915->ggtt;
struct drm_mm_node node;
- char __user *user_data;
- uint64_t remain;
- uint64_t offset;
+ struct i915_vma *vma;
+ void __user *user_data;
+ u64 remain, offset;
int ret;
- vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
+ ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+ if (ret)
+ return ret;
+
+ intel_runtime_pm_get(i915);
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
+ PIN_MAPPABLE | PIN_NONBLOCK);
if (!IS_ERR(vma)) {
node.start = i915_ggtt_offset(vma);
node.allocated = false;
@@ -837,35 +1029,21 @@ i915_gem_gtt_pread(struct drm_device *dev,
}
}
if (IS_ERR(vma)) {
- ret = insert_mappable_node(dev_priv, &node, PAGE_SIZE);
+ ret = insert_mappable_node(ggtt, &node, PAGE_SIZE);
if (ret)
- goto out;
-
- ret = i915_gem_object_get_pages(obj);
- if (ret) {
- remove_mappable_node(&node);
- goto out;
- }
-
- i915_gem_object_pin_pages(obj);
+ goto out_unlock;
+ GEM_BUG_ON(!node.allocated);
}
ret = i915_gem_object_set_to_gtt_domain(obj, false);
if (ret)
goto out_unpin;
- user_data = u64_to_user_ptr(data_ptr);
- remain = size;
- offset = data_offset;
+ mutex_unlock(&i915->drm.struct_mutex);
- mutex_unlock(&dev->struct_mutex);
- if (likely(!i915.prefault_disable)) {
- ret = fault_in_pages_writeable(user_data, remain);
- if (ret) {
- mutex_lock(&dev->struct_mutex);
- goto out_unpin;
- }
- }
+ user_data = u64_to_user_ptr(args->data_ptr);
+ remain = args->size;
+ offset = args->offset;
while (remain > 0) {
/* Operation in this page
@@ -882,19 +1060,14 @@ i915_gem_gtt_pread(struct drm_device *dev,
wmb();
ggtt->base.insert_page(&ggtt->base,
i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT),
- node.start,
- I915_CACHE_NONE, 0);
+ node.start, I915_CACHE_NONE, 0);
wmb();
} else {
page_base += offset & PAGE_MASK;
}
- /* This is a slow read/write as it tries to read from
- * and write to user memory which may result into page
- * faults, and so we cannot perform this under struct_mutex.
- */
- if (slow_user_access(&ggtt->mappable, page_base,
- page_offset, user_data,
- page_length, false)) {
+
+ if (gtt_user_read(&ggtt->mappable, page_base, page_offset,
+ user_data, page_length)) {
ret = -EFAULT;
break;
}
@@ -904,111 +1077,19 @@ i915_gem_gtt_pread(struct drm_device *dev,
offset += page_length;
}
- mutex_lock(&dev->struct_mutex);
- if (ret == 0 && (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) {
- /* The user has modified the object whilst we tried
- * reading from it, and we now have no idea what domain
- * the pages should be in. As we have just been touching
- * them directly, flush everything back to the GTT
- * domain.
- */
- ret = i915_gem_object_set_to_gtt_domain(obj, false);
- }
-
+ mutex_lock(&i915->drm.struct_mutex);
out_unpin:
if (node.allocated) {
wmb();
ggtt->base.clear_range(&ggtt->base,
- node.start, node.size,
- true);
- i915_gem_object_unpin_pages(obj);
+ node.start, node.size);
remove_mappable_node(&node);
} else {
i915_vma_unpin(vma);
}
-out:
- return ret;
-}
-
-static int
-i915_gem_shmem_pread(struct drm_device *dev,
- struct drm_i915_gem_object *obj,
- struct drm_i915_gem_pread *args,
- struct drm_file *file)
-{
- char __user *user_data;
- ssize_t remain;
- loff_t offset;
- int shmem_page_offset, page_length, ret = 0;
- int obj_do_bit17_swizzling, page_do_bit17_swizzling;
- int prefaulted = 0;
- int needs_clflush = 0;
- struct sg_page_iter sg_iter;
-
- ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
- if (ret)
- return ret;
-
- obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
- user_data = u64_to_user_ptr(args->data_ptr);
- offset = args->offset;
- remain = args->size;
-
- for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
- offset >> PAGE_SHIFT) {
- struct page *page = sg_page_iter_page(&sg_iter);
-
- if (remain <= 0)
- break;
-
- /* Operation in this page
- *
- * shmem_page_offset = offset within page in shmem file
- * page_length = bytes to copy for this page
- */
- shmem_page_offset = offset_in_page(offset);
- page_length = remain;
- if ((shmem_page_offset + page_length) > PAGE_SIZE)
- page_length = PAGE_SIZE - shmem_page_offset;
-
- page_do_bit17_swizzling = obj_do_bit17_swizzling &&
- (page_to_phys(page) & (1 << 17)) != 0;
-
- ret = shmem_pread_fast(page, shmem_page_offset, page_length,
- user_data, page_do_bit17_swizzling,
- needs_clflush);
- if (ret == 0)
- goto next_page;
-
- mutex_unlock(&dev->struct_mutex);
-
- if (likely(!i915.prefault_disable) && !prefaulted) {
- ret = fault_in_pages_writeable(user_data, remain);
- /* Userspace is tricking us, but we've already clobbered
- * its pages with the prefault and promised to write the
- * data up to the first fault. Hence ignore any errors
- * and just continue. */
- (void)ret;
- prefaulted = 1;
- }
-
- ret = shmem_pread_slow(page, shmem_page_offset, page_length,
- user_data, page_do_bit17_swizzling,
- needs_clflush);
-
- mutex_lock(&dev->struct_mutex);
-
- if (ret)
- goto out;
-
-next_page:
- remain -= page_length;
- user_data += page_length;
- offset += page_length;
- }
-
-out:
- i915_gem_obj_finish_shmem_access(obj);
+out_unlock:
+ intel_runtime_pm_put(i915);
+ mutex_unlock(&i915->drm.struct_mutex);
return ret;
}
@@ -1027,7 +1108,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_pread *args = data;
struct drm_i915_gem_object *obj;
- int ret = 0;
+ int ret;
if (args->size == 0)
return 0;
@@ -1045,36 +1126,29 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
if (args->offset > obj->base.size ||
args->size > obj->base.size - args->offset) {
ret = -EINVAL;
- goto err;
+ goto out;
}
trace_i915_gem_object_pread(obj, args->offset, args->size);
- ret = __unsafe_wait_rendering(obj, to_rps_client(file), true);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE,
+ MAX_SCHEDULE_TIMEOUT,
+ to_rps_client(file));
if (ret)
- goto err;
+ goto out;
- ret = i915_mutex_lock_interruptible(dev);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
- goto err;
-
- ret = i915_gem_shmem_pread(dev, obj, args, file);
+ goto out;
- /* pread for non shmem backed objects */
- if (ret == -EFAULT || ret == -ENODEV) {
- intel_runtime_pm_get(to_i915(dev));
- ret = i915_gem_gtt_pread(dev, obj, args->size,
- args->offset, args->data_ptr);
- intel_runtime_pm_put(to_i915(dev));
- }
+ ret = i915_gem_shmem_pread(obj, args);
+ if (ret == -EFAULT || ret == -ENODEV)
+ ret = i915_gem_gtt_pread(obj, args);
+ i915_gem_object_unpin_pages(obj);
+out:
i915_gem_object_put(obj);
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-
-err:
- i915_gem_object_put_unlocked(obj);
return ret;
}
@@ -1082,51 +1156,52 @@ err:
* page faults in the source data
*/
-static inline int
-fast_user_write(struct io_mapping *mapping,
- loff_t page_base, int page_offset,
- char __user *user_data,
- int length)
+static inline bool
+ggtt_write(struct io_mapping *mapping,
+ loff_t base, int offset,
+ char __user *user_data, int length)
{
- void __iomem *vaddr_atomic;
void *vaddr;
unsigned long unwritten;
- vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
/* We can use the cpu mem copy function because this is X86. */
- vaddr = (void __force*)vaddr_atomic + page_offset;
- unwritten = __copy_from_user_inatomic_nocache(vaddr,
+ vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base);
+ unwritten = __copy_from_user_inatomic_nocache(vaddr + offset,
user_data, length);
- io_mapping_unmap_atomic(vaddr_atomic);
+ io_mapping_unmap_atomic(vaddr);
+ if (unwritten) {
+ vaddr = (void __force *)
+ io_mapping_map_wc(mapping, base, PAGE_SIZE);
+ unwritten = copy_from_user(vaddr + offset, user_data, length);
+ io_mapping_unmap(vaddr);
+ }
+
return unwritten;
}
/**
* This is the fast pwrite path, where we copy the data directly from the
* user into the GTT, uncached.
- * @i915: i915 device private data
- * @obj: i915 gem object
+ * @obj: i915 GEM object
* @args: pwrite arguments structure
- * @file: drm file pointer
*/
static int
-i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
- struct drm_i915_gem_object *obj,
- struct drm_i915_gem_pwrite *args,
- struct drm_file *file)
+i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
+ const struct drm_i915_gem_pwrite *args)
{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
struct i915_ggtt *ggtt = &i915->ggtt;
- struct drm_device *dev = obj->base.dev;
- struct i915_vma *vma;
struct drm_mm_node node;
- uint64_t remain, offset;
- char __user *user_data;
+ struct i915_vma *vma;
+ u64 remain, offset;
+ void __user *user_data;
int ret;
- bool hit_slow_path = false;
- if (i915_gem_object_is_tiled(obj))
- return -EFAULT;
+ ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+ if (ret)
+ return ret;
+ intel_runtime_pm_get(i915);
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
PIN_MAPPABLE | PIN_NONBLOCK);
if (!IS_ERR(vma)) {
@@ -1139,25 +1214,19 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
}
}
if (IS_ERR(vma)) {
- ret = insert_mappable_node(i915, &node, PAGE_SIZE);
+ ret = insert_mappable_node(ggtt, &node, PAGE_SIZE);
if (ret)
- goto out;
-
- ret = i915_gem_object_get_pages(obj);
- if (ret) {
- remove_mappable_node(&node);
- goto out;
- }
-
- i915_gem_object_pin_pages(obj);
+ goto out_unlock;
+ GEM_BUG_ON(!node.allocated);
}
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret)
goto out_unpin;
+ mutex_unlock(&i915->drm.struct_mutex);
+
intel_fb_obj_invalidate(obj, ORIGIN_CPU);
- obj->dirty = true;
user_data = u64_to_user_ptr(args->data_ptr);
offset = args->offset;
@@ -1170,8 +1239,8 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
* page_length = bytes to copy for this page
*/
u32 page_base = node.start;
- unsigned page_offset = offset_in_page(offset);
- unsigned page_length = PAGE_SIZE - page_offset;
+ unsigned int page_offset = offset_in_page(offset);
+ unsigned int page_length = PAGE_SIZE - page_offset;
page_length = remain < page_length ? remain : page_length;
if (node.allocated) {
wmb(); /* flush the write before we modify the GGTT */
@@ -1188,92 +1257,36 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
* If the object is non-shmem backed, we retry again with the
* path that handles page fault.
*/
- if (fast_user_write(&ggtt->mappable, page_base,
- page_offset, user_data, page_length)) {
- hit_slow_path = true;
- mutex_unlock(&dev->struct_mutex);
- if (slow_user_access(&ggtt->mappable,
- page_base,
- page_offset, user_data,
- page_length, true)) {
- ret = -EFAULT;
- mutex_lock(&dev->struct_mutex);
- goto out_flush;
- }
-
- mutex_lock(&dev->struct_mutex);
+ if (ggtt_write(&ggtt->mappable, page_base, page_offset,
+ user_data, page_length)) {
+ ret = -EFAULT;
+ break;
}
remain -= page_length;
user_data += page_length;
offset += page_length;
}
-
-out_flush:
- if (hit_slow_path) {
- if (ret == 0 &&
- (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) {
- /* The user has modified the object whilst we tried
- * reading from it, and we now have no idea what domain
- * the pages should be in. As we have just been touching
- * them directly, flush everything back to the GTT
- * domain.
- */
- ret = i915_gem_object_set_to_gtt_domain(obj, false);
- }
- }
-
intel_fb_obj_flush(obj, false, ORIGIN_CPU);
+
+ mutex_lock(&i915->drm.struct_mutex);
out_unpin:
if (node.allocated) {
wmb();
ggtt->base.clear_range(&ggtt->base,
- node.start, node.size,
- true);
- i915_gem_object_unpin_pages(obj);
+ node.start, node.size);
remove_mappable_node(&node);
} else {
i915_vma_unpin(vma);
}
-out:
+out_unlock:
+ intel_runtime_pm_put(i915);
+ mutex_unlock(&i915->drm.struct_mutex);
return ret;
}
-/* Per-page copy function for the shmem pwrite fastpath.
- * Flushes invalid cachelines before writing to the target if
- * needs_clflush_before is set and flushes out any written cachelines after
- * writing if needs_clflush is set. */
-static int
-shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length,
- char __user *user_data,
- bool page_do_bit17_swizzling,
- bool needs_clflush_before,
- bool needs_clflush_after)
-{
- char *vaddr;
- int ret;
-
- if (unlikely(page_do_bit17_swizzling))
- return -EINVAL;
-
- vaddr = kmap_atomic(page);
- if (needs_clflush_before)
- drm_clflush_virt_range(vaddr + shmem_page_offset,
- page_length);
- ret = __copy_from_user_inatomic(vaddr + shmem_page_offset,
- user_data, page_length);
- if (needs_clflush_after)
- drm_clflush_virt_range(vaddr + shmem_page_offset,
- page_length);
- kunmap_atomic(vaddr);
-
- return ret ? -EFAULT : 0;
-}
-
-/* Only difference to the fast-path function is that this can handle bit17
- * and uses non-atomic copy and kmap functions. */
static int
-shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
+shmem_pwrite_slow(struct page *page, int offset, int length,
char __user *user_data,
bool page_do_bit17_swizzling,
bool needs_clflush_before,
@@ -1284,124 +1297,114 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
vaddr = kmap(page);
if (unlikely(needs_clflush_before || page_do_bit17_swizzling))
- shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
- page_length,
+ shmem_clflush_swizzled_range(vaddr + offset, length,
page_do_bit17_swizzling);
if (page_do_bit17_swizzling)
- ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
- user_data,
- page_length);
+ ret = __copy_from_user_swizzled(vaddr, offset, user_data,
+ length);
else
- ret = __copy_from_user(vaddr + shmem_page_offset,
- user_data,
- page_length);
+ ret = __copy_from_user(vaddr + offset, user_data, length);
if (needs_clflush_after)
- shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
- page_length,
+ shmem_clflush_swizzled_range(vaddr + offset, length,
page_do_bit17_swizzling);
kunmap(page);
return ret ? -EFAULT : 0;
}
+/* Per-page copy function for the shmem pwrite fastpath.
+ * Flushes invalid cachelines before writing to the target if
+ * needs_clflush_before is set and flushes out any written cachelines after
+ * writing if needs_clflush is set.
+ */
static int
-i915_gem_shmem_pwrite(struct drm_device *dev,
- struct drm_i915_gem_object *obj,
- struct drm_i915_gem_pwrite *args,
- struct drm_file *file)
+shmem_pwrite(struct page *page, int offset, int len, char __user *user_data,
+ bool page_do_bit17_swizzling,
+ bool needs_clflush_before,
+ bool needs_clflush_after)
{
- ssize_t remain;
- loff_t offset;
- char __user *user_data;
- int shmem_page_offset, page_length, ret = 0;
- int obj_do_bit17_swizzling, page_do_bit17_swizzling;
- int hit_slowpath = 0;
- unsigned int needs_clflush;
- struct sg_page_iter sg_iter;
+ int ret;
- ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
- if (ret)
- return ret;
+ ret = -ENODEV;
+ if (!page_do_bit17_swizzling) {
+ char *vaddr = kmap_atomic(page);
- obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
- user_data = u64_to_user_ptr(args->data_ptr);
- offset = args->offset;
- remain = args->size;
+ if (needs_clflush_before)
+ drm_clflush_virt_range(vaddr + offset, len);
+ ret = __copy_from_user_inatomic(vaddr + offset, user_data, len);
+ if (needs_clflush_after)
+ drm_clflush_virt_range(vaddr + offset, len);
- for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
- offset >> PAGE_SHIFT) {
- struct page *page = sg_page_iter_page(&sg_iter);
- int partial_cacheline_write;
+ kunmap_atomic(vaddr);
+ }
+ if (ret == 0)
+ return ret;
- if (remain <= 0)
- break;
+ return shmem_pwrite_slow(page, offset, len, user_data,
+ page_do_bit17_swizzling,
+ needs_clflush_before,
+ needs_clflush_after);
+}
- /* Operation in this page
- *
- * shmem_page_offset = offset within page in shmem file
- * page_length = bytes to copy for this page
- */
- shmem_page_offset = offset_in_page(offset);
-
- page_length = remain;
- if ((shmem_page_offset + page_length) > PAGE_SIZE)
- page_length = PAGE_SIZE - shmem_page_offset;
-
- /* If we don't overwrite a cacheline completely we need to be
- * careful to have up-to-date data by first clflushing. Don't
- * overcomplicate things and flush the entire patch. */
- partial_cacheline_write = needs_clflush & CLFLUSH_BEFORE &&
- ((shmem_page_offset | page_length)
- & (boot_cpu_data.x86_clflush_size - 1));
-
- page_do_bit17_swizzling = obj_do_bit17_swizzling &&
- (page_to_phys(page) & (1 << 17)) != 0;
-
- ret = shmem_pwrite_fast(page, shmem_page_offset, page_length,
- user_data, page_do_bit17_swizzling,
- partial_cacheline_write,
- needs_clflush & CLFLUSH_AFTER);
- if (ret == 0)
- goto next_page;
-
- hit_slowpath = 1;
- mutex_unlock(&dev->struct_mutex);
- ret = shmem_pwrite_slow(page, shmem_page_offset, page_length,
- user_data, page_do_bit17_swizzling,
- partial_cacheline_write,
- needs_clflush & CLFLUSH_AFTER);
+static int
+i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
+ const struct drm_i915_gem_pwrite *args)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ void __user *user_data;
+ u64 remain;
+ unsigned int obj_do_bit17_swizzling;
+ unsigned int partial_cacheline_write;
+ unsigned int needs_clflush;
+ unsigned int offset, idx;
+ int ret;
- mutex_lock(&dev->struct_mutex);
+ ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+ if (ret)
+ return ret;
- if (ret)
- goto out;
+ ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
+ mutex_unlock(&i915->drm.struct_mutex);
+ if (ret)
+ return ret;
-next_page:
- remain -= page_length;
- user_data += page_length;
- offset += page_length;
- }
+ obj_do_bit17_swizzling = 0;
+ if (i915_gem_object_needs_bit17_swizzle(obj))
+ obj_do_bit17_swizzling = BIT(17);
-out:
- i915_gem_obj_finish_shmem_access(obj);
+ /* If we don't overwrite a cacheline completely we need to be
+ * careful to have up-to-date data by first clflushing. Don't
+ * overcomplicate things and flush the entire patch.
+ */
+ partial_cacheline_write = 0;
+ if (needs_clflush & CLFLUSH_BEFORE)
+ partial_cacheline_write = boot_cpu_data.x86_clflush_size - 1;
- if (hit_slowpath) {
- /*
- * Fixup: Flush cpu caches in case we didn't flush the dirty
- * cachelines in-line while writing and the object moved
- * out of the cpu write domain while we've dropped the lock.
- */
- if (!(needs_clflush & CLFLUSH_AFTER) &&
- obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
- if (i915_gem_clflush_object(obj, obj->pin_display))
- needs_clflush |= CLFLUSH_AFTER;
- }
- }
+ user_data = u64_to_user_ptr(args->data_ptr);
+ remain = args->size;
+ offset = offset_in_page(args->offset);
+ for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
+ struct page *page = i915_gem_object_get_page(obj, idx);
+ int length;
+
+ length = remain;
+ if (offset + length > PAGE_SIZE)
+ length = PAGE_SIZE - offset;
+
+ ret = shmem_pwrite(page, offset, length, user_data,
+ page_to_phys(page) & obj_do_bit17_swizzling,
+ (offset | length) & partial_cacheline_write,
+ needs_clflush & CLFLUSH_AFTER);
+ if (ret)
+ break;
- if (needs_clflush & CLFLUSH_AFTER)
- i915_gem_chipset_flush(to_i915(dev));
+ remain -= length;
+ user_data += length;
+ offset = 0;
+ }
intel_fb_obj_flush(obj, false, ORIGIN_CPU);
+ i915_gem_obj_finish_shmem_access(obj);
return ret;
}
@@ -1417,7 +1420,6 @@ int
i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_pwrite *args = data;
struct drm_i915_gem_object *obj;
int ret;
@@ -1430,13 +1432,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
args->size))
return -EFAULT;
- if (likely(!i915.prefault_disable)) {
- ret = fault_in_pages_readable(u64_to_user_ptr(args->data_ptr),
- args->size);
- if (ret)
- return -EFAULT;
- }
-
obj = i915_gem_object_lookup(file, args->handle);
if (!obj)
return -ENOENT;
@@ -1450,15 +1445,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
trace_i915_gem_object_pwrite(obj, args->offset, args->size);
- ret = __unsafe_wait_rendering(obj, to_rps_client(file), false);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_ALL,
+ MAX_SCHEDULE_TIMEOUT,
+ to_rps_client(file));
if (ret)
goto err;
- intel_runtime_pm_get(dev_priv);
-
- ret = i915_mutex_lock_interruptible(dev);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
- goto err_rpm;
+ goto err;
ret = -EFAULT;
/* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -1468,30 +1465,23 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
* perspective, requiring manual detiling by the client.
*/
if (!i915_gem_object_has_struct_page(obj) ||
- cpu_write_needs_clflush(obj)) {
- ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file);
+ cpu_write_needs_clflush(obj))
/* Note that the gtt paths might fail with non-page-backed user
* pointers (e.g. gtt mappings when moving data between
- * textures). Fallback to the shmem path in that case. */
- }
+ * textures). Fallback to the shmem path in that case.
+ */
+ ret = i915_gem_gtt_pwrite_fast(obj, args);
if (ret == -EFAULT || ret == -ENOSPC) {
if (obj->phys_handle)
ret = i915_gem_phys_pwrite(obj, args, file);
else
- ret = i915_gem_shmem_pwrite(dev, obj, args, file);
+ ret = i915_gem_shmem_pwrite(obj, args);
}
- i915_gem_object_put(obj);
- mutex_unlock(&dev->struct_mutex);
- intel_runtime_pm_put(dev_priv);
-
- return ret;
-
-err_rpm:
- intel_runtime_pm_put(dev_priv);
+ i915_gem_object_unpin_pages(obj);
err:
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return ret;
}
@@ -1502,6 +1492,30 @@ write_origin(struct drm_i915_gem_object *obj, unsigned domain)
obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
}
+static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
+{
+ struct drm_i915_private *i915;
+ struct list_head *list;
+ struct i915_vma *vma;
+
+ list_for_each_entry(vma, &obj->vma_list, obj_link) {
+ if (!i915_vma_is_ggtt(vma))
+ continue;
+
+ if (i915_vma_is_active(vma))
+ continue;
+
+ if (!drm_mm_node_allocated(&vma->node))
+ continue;
+
+ list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+ }
+
+ i915 = to_i915(obj->base.dev);
+ list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list;
+ list_move_tail(&obj->global_link, list);
+}
+
/**
* Called when user space prepares to use an object with the CPU, either
* through the mmap ioctl's mapping or a GTT mapping.
@@ -1517,7 +1531,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_object *obj;
uint32_t read_domains = args->read_domains;
uint32_t write_domain = args->write_domain;
- int ret;
+ int err;
/* Only handle setting domains to types used by the CPU. */
if ((write_domain | read_domains) & I915_GEM_GPU_DOMAINS)
@@ -1537,29 +1551,48 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
* We will repeat the flush holding the lock in the normal manner
* to catch cases where we are gazumped.
*/
- ret = __unsafe_wait_rendering(obj, to_rps_client(file), !write_domain);
- if (ret)
- goto err;
+ err = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ (write_domain ? I915_WAIT_ALL : 0),
+ MAX_SCHEDULE_TIMEOUT,
+ to_rps_client(file));
+ if (err)
+ goto out;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- goto err;
+ /* Flush and acquire obj->pages so that we are coherent through
+ * direct access in memory with previous cached writes through
+ * shmemfs and that our cache domain tracking remains valid.
+ * For example, if the obj->filp was moved to swap without us
+ * being notified and releasing the pages, we would mistakenly
+ * continue to assume that the obj remained out of the CPU cached
+ * domain.
+ */
+ err = i915_gem_object_pin_pages(obj);
+ if (err)
+ goto out;
+
+ err = i915_mutex_lock_interruptible(dev);
+ if (err)
+ goto out_unpin;
if (read_domains & I915_GEM_DOMAIN_GTT)
- ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
+ err = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
else
- ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+ err = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+
+ /* And bump the LRU for this access */
+ i915_gem_object_bump_inactive_ggtt(obj);
+
+ mutex_unlock(&dev->struct_mutex);
if (write_domain != 0)
intel_fb_obj_invalidate(obj, write_origin(obj, write_domain));
+out_unpin:
+ i915_gem_object_unpin_pages(obj);
+out:
i915_gem_object_put(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
-
-err:
- i915_gem_object_put_unlocked(obj);
- return ret;
+ return err;
}
/**
@@ -1589,7 +1622,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
}
}
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return err;
}
@@ -1635,7 +1668,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
* pages from.
*/
if (!obj->base.filp) {
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return -EINVAL;
}
@@ -1647,7 +1680,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct vm_area_struct *vma;
if (down_write_killable(&mm->mmap_sem)) {
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return -EINTR;
}
vma = find_vma(mm, addr);
@@ -1661,7 +1694,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
/* This may race, but that's ok, it only gets set */
WRITE_ONCE(obj->frontbuffer_ggtt_origin, ORIGIN_CPU);
}
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
if (IS_ERR((void *)addr))
return addr;
@@ -1773,7 +1806,14 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
* repeat the flush holding the lock in the normal manner to catch cases
* where we are gazumped.
*/
- ret = __unsafe_wait_rendering(obj, NULL, !write);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
+ if (ret)
+ goto err;
+
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
goto err;
@@ -1784,7 +1824,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
goto err_rpm;
/* Access to snoopable pages through the GTT is incoherent. */
- if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
+ if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv)) {
ret = -EFAULT;
goto err_unlock;
}
@@ -1813,8 +1853,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
view.params.partial.offset = rounddown(page_offset, chunk_size);
view.params.partial.size =
min_t(unsigned int, chunk_size,
- (area->vm_end - area->vm_start) / PAGE_SIZE -
- view.params.partial.offset);
+ vma_pages(area) - view.params.partial.offset);
/* If the partial covers the entire object, just create a
* normal VMA.
@@ -1842,22 +1881,25 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
if (ret)
goto err_unpin;
+ /* Mark as being mmapped into userspace for later revocation */
+ assert_rpm_wakelock_held(dev_priv);
+ if (list_empty(&obj->userfault_link))
+ list_add(&obj->userfault_link, &dev_priv->mm.userfault_list);
+
/* Finally, remap it using the new GTT offset */
ret = remap_io_mapping(area,
area->vm_start + (vma->ggtt_view.params.partial.offset << PAGE_SHIFT),
(ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT,
min_t(u64, vma->size, area->vm_end - area->vm_start),
&ggtt->mappable);
- if (ret)
- goto err_unpin;
- obj->fault_mappable = true;
err_unpin:
__i915_vma_unpin(vma);
err_unlock:
mutex_unlock(&dev->struct_mutex);
err_rpm:
intel_runtime_pm_put(dev_priv);
+ i915_gem_object_unpin_pages(obj);
err:
switch (ret) {
case -EIO:
@@ -1919,15 +1961,23 @@ err:
void
i915_gem_release_mmap(struct drm_i915_gem_object *obj)
{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
/* Serialisation between user GTT access and our code depends upon
* revoking the CPU's PTE whilst the mutex is held. The next user
* pagefault then has to wait until we release the mutex.
+ *
+ * Note that RPM complicates somewhat by adding an additional
+ * requirement that operations to the GGTT be made holding the RPM
+ * wakeref.
*/
- lockdep_assert_held(&obj->base.dev->struct_mutex);
+ lockdep_assert_held(&i915->drm.struct_mutex);
+ intel_runtime_pm_get(i915);
- if (!obj->fault_mappable)
- return;
+ if (list_empty(&obj->userfault_link))
+ goto out;
+ list_del_init(&obj->userfault_link);
drm_vma_node_unmap(&obj->base.vma_node,
obj->base.dev->anon_inode->i_mapping);
@@ -1940,16 +1990,45 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
*/
wmb();
- obj->fault_mappable = false;
+out:
+ intel_runtime_pm_put(i915);
}
-void
-i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
{
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj, *on;
+ int i;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
- i915_gem_release_mmap(obj);
+ /*
+ * Only called during RPM suspend. All users of the userfault_list
+ * must be holding an RPM wakeref to ensure that this can not
+ * run concurrently with themselves (and use the struct_mutex for
+ * protection between themselves).
+ */
+
+ list_for_each_entry_safe(obj, on,
+ &dev_priv->mm.userfault_list, userfault_link) {
+ list_del_init(&obj->userfault_link);
+ drm_vma_node_unmap(&obj->base.vma_node,
+ obj->base.dev->anon_inode->i_mapping);
+ }
+
+ /* The fence will be lost when the device powers down. If any were
+ * in use by hardware (i.e. they are pinned), we should not be powering
+ * down! All other fences will be reacquired by the user upon waking.
+ */
+ for (i = 0; i < dev_priv->num_fence_regs; i++) {
+ struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
+
+ if (WARN_ON(reg->pin_count))
+ continue;
+
+ if (!reg->vma)
+ continue;
+
+ GEM_BUG_ON(!list_empty(&reg->vma->obj->userfault_link));
+ reg->dirty = true;
+ }
}
/**
@@ -2063,7 +2142,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
if (ret == 0)
*offset = drm_vma_node_offset_addr(&obj->base.vma_node);
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return ret;
}
@@ -2106,16 +2185,18 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
* backing pages, *now*.
*/
shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
- obj->madv = __I915_MADV_PURGED;
+ obj->mm.madv = __I915_MADV_PURGED;
}
/* Try to discard unwanted pages */
-static void
-i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
+void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
{
struct address_space *mapping;
- switch (obj->madv) {
+ lockdep_assert_held(&obj->mm.lock);
+ GEM_BUG_ON(obj->mm.pages);
+
+ switch (obj->mm.madv) {
case I915_MADV_DONTNEED:
i915_gem_object_truncate(obj);
case __I915_MADV_PURGED:
@@ -2130,85 +2211,119 @@ i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
}
static void
-i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
+i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
struct sgt_iter sgt_iter;
struct page *page;
- int ret;
- BUG_ON(obj->madv == __I915_MADV_PURGED);
+ __i915_gem_object_release_shmem(obj, pages);
- ret = i915_gem_object_set_to_cpu_domain(obj, true);
- if (WARN_ON(ret)) {
- /* In the event of a disaster, abandon all caches and
- * hope for the best.
- */
- i915_gem_clflush_object(obj, true);
- obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
- }
-
- i915_gem_gtt_finish_object(obj);
+ i915_gem_gtt_finish_pages(obj, pages);
if (i915_gem_object_needs_bit17_swizzle(obj))
- i915_gem_object_save_bit_17_swizzle(obj);
-
- if (obj->madv == I915_MADV_DONTNEED)
- obj->dirty = 0;
+ i915_gem_object_save_bit_17_swizzle(obj, pages);
- for_each_sgt_page(page, sgt_iter, obj->pages) {
- if (obj->dirty)
+ for_each_sgt_page(page, sgt_iter, pages) {
+ if (obj->mm.dirty)
set_page_dirty(page);
- if (obj->madv == I915_MADV_WILLNEED)
+ if (obj->mm.madv == I915_MADV_WILLNEED)
mark_page_accessed(page);
put_page(page);
}
- obj->dirty = 0;
+ obj->mm.dirty = false;
- sg_free_table(obj->pages);
- kfree(obj->pages);
+ sg_free_table(pages);
+ kfree(pages);
}
-int
-i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
+static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj)
{
- const struct drm_i915_gem_object_ops *ops = obj->ops;
+ struct radix_tree_iter iter;
+ void **slot;
- if (obj->pages == NULL)
- return 0;
+ radix_tree_for_each_slot(slot, &obj->mm.get_page.radix, &iter, 0)
+ radix_tree_delete(&obj->mm.get_page.radix, iter.index);
+}
- if (obj->pages_pin_count)
- return -EBUSY;
+void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+ enum i915_mm_subclass subclass)
+{
+ struct sg_table *pages;
+
+ if (i915_gem_object_has_pinned_pages(obj))
+ return;
GEM_BUG_ON(obj->bind_count);
+ if (!READ_ONCE(obj->mm.pages))
+ return;
+
+ /* May be called by shrinker from within get_pages() (on another bo) */
+ mutex_lock_nested(&obj->mm.lock, subclass);
+ if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
+ goto unlock;
/* ->put_pages might need to allocate memory for the bit17 swizzle
* array, hence protect them from being reaped by removing them from gtt
* lists early. */
- list_del(&obj->global_list);
+ pages = fetch_and_zero(&obj->mm.pages);
+ GEM_BUG_ON(!pages);
- if (obj->mapping) {
+ if (obj->mm.mapping) {
void *ptr;
- ptr = ptr_mask_bits(obj->mapping);
+ ptr = ptr_mask_bits(obj->mm.mapping);
if (is_vmalloc_addr(ptr))
vunmap(ptr);
else
kunmap(kmap_to_page(ptr));
- obj->mapping = NULL;
+ obj->mm.mapping = NULL;
}
- ops->put_pages(obj);
- obj->pages = NULL;
+ __i915_gem_object_reset_page_iter(obj);
- i915_gem_object_invalidate(obj);
+ obj->ops->put_pages(obj, pages);
+unlock:
+ mutex_unlock(&obj->mm.lock);
+}
+static unsigned int swiotlb_max_size(void)
+{
+#if IS_ENABLED(CONFIG_SWIOTLB)
+ return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE);
+#else
return 0;
+#endif
}
-static int
+static void i915_sg_trim(struct sg_table *orig_st)
+{
+ struct sg_table new_st;
+ struct scatterlist *sg, *new_sg;
+ unsigned int i;
+
+ if (orig_st->nents == orig_st->orig_nents)
+ return;
+
+ if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL))
+ return;
+
+ new_sg = new_st.sgl;
+ for_each_sg(orig_st->sgl, sg, orig_st->nents, i) {
+ sg_set_page(new_sg, sg_page(sg), sg->length, 0);
+ /* called before being DMA mapped, no need to copy sg->dma_* */
+ new_sg = sg_next(new_sg);
+ }
+
+ sg_free_table(orig_st);
+
+ *orig_st = new_st;
+}
+
+static struct sg_table *
i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
@@ -2219,6 +2334,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
struct sgt_iter sgt_iter;
struct page *page;
unsigned long last_pfn = 0; /* suppress gcc warning */
+ unsigned int max_segment;
int ret;
gfp_t gfp;
@@ -2226,17 +2342,21 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
* wasn't in the GTT, there shouldn't be any way it could have been in
* a GPU cache
*/
- BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
- BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
+ GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
+ GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
+
+ max_segment = swiotlb_max_size();
+ if (!max_segment)
+ max_segment = rounddown(UINT_MAX, PAGE_SIZE);
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
page_count = obj->base.size / PAGE_SIZE;
if (sg_alloc_table(st, page_count, GFP_KERNEL)) {
kfree(st);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
/* Get the list of pages out of our struct file. They'll be pinned
@@ -2264,22 +2384,15 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
* our own buffer, now let the real VM do its job and
* go down in flames if truly OOM.
*/
- i915_gem_shrink_all(dev_priv);
page = shmem_read_mapping_page(mapping, i);
if (IS_ERR(page)) {
ret = PTR_ERR(page);
goto err_sg;
}
}
-#ifdef CONFIG_SWIOTLB
- if (swiotlb_nr_tbl()) {
- st->nents++;
- sg_set_page(sg, page, PAGE_SIZE, 0);
- sg = sg_next(sg);
- continue;
- }
-#endif
- if (!i || page_to_pfn(page) != last_pfn + 1) {
+ if (!i ||
+ sg->length >= max_segment ||
+ page_to_pfn(page) != last_pfn + 1) {
if (i)
sg = sg_next(sg);
st->nents++;
@@ -2292,24 +2405,20 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
/* Check that the i965g/gm workaround works. */
WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL));
}
-#ifdef CONFIG_SWIOTLB
- if (!swiotlb_nr_tbl())
-#endif
+ if (sg) /* loop terminated early; short sg table */
sg_mark_end(sg);
- obj->pages = st;
- ret = i915_gem_gtt_prepare_object(obj);
+ /* Trim unused sg entries to avoid wasting memory. */
+ i915_sg_trim(st);
+
+ ret = i915_gem_gtt_prepare_pages(obj, st);
if (ret)
goto err_pages;
if (i915_gem_object_needs_bit17_swizzle(obj))
- i915_gem_object_do_bit_17_swizzle(obj);
+ i915_gem_object_do_bit_17_swizzle(obj, st);
- if (i915_gem_object_is_tiled(obj) &&
- dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
- i915_gem_object_pin_pages(obj);
-
- return 0;
+ return st;
err_sg:
sg_mark_end(sg);
@@ -2330,43 +2439,73 @@ err_pages:
if (ret == -ENOSPC)
ret = -ENOMEM;
- return ret;
+ return ERR_PTR(ret);
}
-/* Ensure that the associated pages are gathered from the backing storage
- * and pinned into our object. i915_gem_object_get_pages() may be called
- * multiple times before they are released by a single call to
- * i915_gem_object_put_pages() - once the pages are no longer referenced
- * either as a result of memory pressure (reaping pages under the shrinker)
- * or as the object is itself released.
- */
-int
-i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
- const struct drm_i915_gem_object_ops *ops = obj->ops;
- int ret;
+ lockdep_assert_held(&obj->mm.lock);
- if (obj->pages)
- return 0;
+ obj->mm.get_page.sg_pos = pages->sgl;
+ obj->mm.get_page.sg_idx = 0;
+
+ obj->mm.pages = pages;
- if (obj->madv != I915_MADV_WILLNEED) {
+ if (i915_gem_object_is_tiled(obj) &&
+ to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
+ GEM_BUG_ON(obj->mm.quirked);
+ __i915_gem_object_pin_pages(obj);
+ obj->mm.quirked = true;
+ }
+}
+
+static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+{
+ struct sg_table *pages;
+
+ GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+
+ if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
DRM_DEBUG("Attempting to obtain a purgeable object\n");
return -EFAULT;
}
- BUG_ON(obj->pages_pin_count);
+ pages = obj->ops->get_pages(obj);
+ if (unlikely(IS_ERR(pages)))
+ return PTR_ERR(pages);
- ret = ops->get_pages(obj);
- if (ret)
- return ret;
+ __i915_gem_object_set_pages(obj, pages);
+ return 0;
+}
+
+/* Ensure that the associated pages are gathered from the backing storage
+ * and pinned into our object. i915_gem_object_pin_pages() may be called
+ * multiple times before they are released by a single call to
+ * i915_gem_object_unpin_pages() - once the pages are no longer referenced
+ * either as a result of memory pressure (reaping pages under the shrinker)
+ * or as the object is itself released.
+ */
+int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+{
+ int err;
- list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list);
+ err = mutex_lock_interruptible(&obj->mm.lock);
+ if (err)
+ return err;
- obj->get_page.sg = obj->pages->sgl;
- obj->get_page.last = 0;
+ if (unlikely(!obj->mm.pages)) {
+ err = ____i915_gem_object_get_pages(obj);
+ if (err)
+ goto unlock;
- return 0;
+ smp_mb__before_atomic();
+ }
+ atomic_inc(&obj->mm.pages_pin_count);
+
+unlock:
+ mutex_unlock(&obj->mm.lock);
+ return err;
}
/* The 'mapping' part of i915_gem_object_pin_map() below */
@@ -2374,7 +2513,7 @@ static void *i915_gem_object_map(const struct drm_i915_gem_object *obj,
enum i915_map_type type)
{
unsigned long n_pages = obj->base.size >> PAGE_SHIFT;
- struct sg_table *sgt = obj->pages;
+ struct sg_table *sgt = obj->mm.pages;
struct sgt_iter sgt_iter;
struct page *page;
struct page *stack_pages[32];
@@ -2425,21 +2564,31 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
void *ptr;
int ret;
- lockdep_assert_held(&obj->base.dev->struct_mutex);
GEM_BUG_ON(!i915_gem_object_has_struct_page(obj));
- ret = i915_gem_object_get_pages(obj);
+ ret = mutex_lock_interruptible(&obj->mm.lock);
if (ret)
return ERR_PTR(ret);
- i915_gem_object_pin_pages(obj);
- pinned = obj->pages_pin_count > 1;
+ pinned = true;
+ if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
+ if (unlikely(!obj->mm.pages)) {
+ ret = ____i915_gem_object_get_pages(obj);
+ if (ret)
+ goto err_unlock;
+
+ smp_mb__before_atomic();
+ }
+ atomic_inc(&obj->mm.pages_pin_count);
+ pinned = false;
+ }
+ GEM_BUG_ON(!obj->mm.pages);
- ptr = ptr_unpack_bits(obj->mapping, has_type);
+ ptr = ptr_unpack_bits(obj->mm.mapping, has_type);
if (ptr && has_type != type) {
if (pinned) {
ret = -EBUSY;
- goto err;
+ goto err_unpin;
}
if (is_vmalloc_addr(ptr))
@@ -2447,59 +2596,28 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
else
kunmap(kmap_to_page(ptr));
- ptr = obj->mapping = NULL;
+ ptr = obj->mm.mapping = NULL;
}
if (!ptr) {
ptr = i915_gem_object_map(obj, type);
if (!ptr) {
ret = -ENOMEM;
- goto err;
+ goto err_unpin;
}
- obj->mapping = ptr_pack_bits(ptr, type);
+ obj->mm.mapping = ptr_pack_bits(ptr, type);
}
+out_unlock:
+ mutex_unlock(&obj->mm.lock);
return ptr;
-err:
- i915_gem_object_unpin_pages(obj);
- return ERR_PTR(ret);
-}
-
-static void
-i915_gem_object_retire__write(struct i915_gem_active *active,
- struct drm_i915_gem_request *request)
-{
- struct drm_i915_gem_object *obj =
- container_of(active, struct drm_i915_gem_object, last_write);
-
- intel_fb_obj_flush(obj, true, ORIGIN_CS);
-}
-
-static void
-i915_gem_object_retire__read(struct i915_gem_active *active,
- struct drm_i915_gem_request *request)
-{
- int idx = request->engine->id;
- struct drm_i915_gem_object *obj =
- container_of(active, struct drm_i915_gem_object, last_read[idx]);
-
- GEM_BUG_ON(!i915_gem_object_has_active_engine(obj, idx));
-
- i915_gem_object_clear_active(obj, idx);
- if (i915_gem_object_is_active(obj))
- return;
-
- /* Bump our place on the bound list to keep it roughly in LRU order
- * so that we don't steal from recently used but inactive objects
- * (unless we are forced to ofc!)
- */
- if (obj->bind_count)
- list_move_tail(&obj->global_list,
- &request->i915->mm.bound_list);
-
- i915_gem_object_put(obj);
+err_unpin:
+ atomic_dec(&obj->mm.pages_pin_count);
+err_unlock:
+ ptr = ERR_PTR(ret);
+ goto out_unlock;
}
static bool i915_context_is_banned(const struct i915_gem_context *ctx)
@@ -2546,13 +2664,10 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
* extra delay for a recent interrupt is pointless. Hence, we do
* not need an engine->irq_seqno_barrier() before the seqno reads.
*/
- list_for_each_entry(request, &engine->request_list, link) {
- if (i915_gem_request_completed(request))
+ list_for_each_entry(request, &engine->timeline->requests, link) {
+ if (__i915_gem_request_completed(request))
continue;
- if (!i915_sw_fence_done(&request->submit))
- break;
-
return request;
}
@@ -2580,10 +2695,9 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
{
struct drm_i915_gem_request *request;
struct i915_gem_context *incomplete_ctx;
+ struct intel_timeline *timeline;
bool ring_hung;
- /* Ensure irq handler finishes, and not run again. */
- tasklet_kill(&engine->irq_tasklet);
if (engine->irq_seqno_barrier)
engine->irq_seqno_barrier(engine);
@@ -2592,12 +2706,15 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
return;
ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
+ if (engine->hangcheck.seqno != intel_engine_get_seqno(engine))
+ ring_hung = false;
+
i915_set_reset_status(request->ctx, ring_hung);
if (!ring_hung)
return;
DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n",
- engine->name, request->fence.seqno);
+ engine->name, request->global_seqno);
/* Setup the CS to resume from the breadcrumb of the hung request */
engine->reset_hw(engine, request);
@@ -2614,21 +2731,28 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
if (i915_gem_context_is_default(incomplete_ctx))
return;
- list_for_each_entry_continue(request, &engine->request_list, link)
+ list_for_each_entry_continue(request, &engine->timeline->requests, link)
if (request->ctx == incomplete_ctx)
reset_request(request);
+
+ timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine);
+ list_for_each_entry(request, &timeline->requests, link)
+ reset_request(request);
}
void i915_gem_reset(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
i915_gem_retire_requests(dev_priv);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
i915_gem_reset_engine(engine);
- i915_gem_restore_fences(&dev_priv->drm);
+ i915_gem_restore_fences(dev_priv);
if (dev_priv->gt.awake) {
intel_sanitize_gt_powersave(dev_priv);
@@ -2640,6 +2764,8 @@ void i915_gem_reset(struct drm_i915_private *dev_priv)
static void nop_submit_request(struct drm_i915_gem_request *request)
{
+ i915_gem_request_submit(request);
+ intel_engine_init_global_seqno(request->engine, request->global_seqno);
}
static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
@@ -2650,7 +2776,8 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
* (lockless) lookup doesn't try and wait upon the request as we
* reset it.
*/
- intel_engine_init_seqno(engine, engine->last_submitted_seqno);
+ intel_engine_init_global_seqno(engine,
+ intel_engine_last_submit(engine));
/*
* Clear the execlists queue up before freeing the requests, as those
@@ -2659,26 +2786,30 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
*/
if (i915.enable_execlists) {
- spin_lock(&engine->execlist_lock);
- INIT_LIST_HEAD(&engine->execlist_queue);
+ unsigned long flags;
+
+ spin_lock_irqsave(&engine->timeline->lock, flags);
+
i915_gem_request_put(engine->execlist_port[0].request);
i915_gem_request_put(engine->execlist_port[1].request);
memset(engine->execlist_port, 0, sizeof(engine->execlist_port));
- spin_unlock(&engine->execlist_lock);
- }
+ engine->execlist_queue = RB_ROOT;
+ engine->execlist_first = NULL;
- engine->i915->gt.active_engines &= ~intel_engine_flag(engine);
+ spin_unlock_irqrestore(&engine->timeline->lock, flags);
+ }
}
void i915_gem_set_wedged(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
lockdep_assert_held(&dev_priv->drm.struct_mutex);
set_bit(I915_WEDGED, &dev_priv->gpu_error.flags);
i915_gem_context_lost(dev_priv);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
i915_gem_cleanup_engine(engine);
mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0);
@@ -2717,12 +2848,20 @@ i915_gem_idle_work_handler(struct work_struct *work)
container_of(work, typeof(*dev_priv), gt.idle_work.work);
struct drm_device *dev = &dev_priv->drm;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
bool rearm_hangcheck;
if (!READ_ONCE(dev_priv->gt.awake))
return;
- if (READ_ONCE(dev_priv->gt.active_engines))
+ /*
+ * Wait for last execlists context complete, but bail out in case a
+ * new request is submitted.
+ */
+ wait_for(READ_ONCE(dev_priv->gt.active_requests) ||
+ intel_execlists_idle(dev_priv), 10);
+
+ if (READ_ONCE(dev_priv->gt.active_requests))
return;
rearm_hangcheck =
@@ -2736,10 +2875,20 @@ i915_gem_idle_work_handler(struct work_struct *work)
goto out_rearm;
}
- if (dev_priv->gt.active_engines)
+ /*
+ * New request retired after this work handler started, extend active
+ * period until next instance of the work.
+ */
+ if (work_pending(work))
+ goto out_unlock;
+
+ if (dev_priv->gt.active_requests)
goto out_unlock;
- for_each_engine(engine, dev_priv)
+ if (wait_for(intel_execlists_idle(dev_priv), 10))
+ DRM_ERROR("Timeout waiting for engines to idle\n");
+
+ for_each_engine(engine, dev_priv, id)
i915_gem_batch_pool_fini(&engine->batch_pool);
GEM_BUG_ON(!dev_priv->gt.awake);
@@ -2769,9 +2918,26 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file)
list_for_each_entry_safe(vma, vn, &obj->vma_list, obj_link)
if (vma->vm->file == fpriv)
i915_vma_close(vma);
+
+ if (i915_gem_object_is_active(obj) &&
+ !i915_gem_object_has_active_reference(obj)) {
+ i915_gem_object_set_active_reference(obj);
+ i915_gem_object_get(obj);
+ }
mutex_unlock(&obj->base.dev->struct_mutex);
}
+static unsigned long to_wait_timeout(s64 timeout_ns)
+{
+ if (timeout_ns < 0)
+ return MAX_SCHEDULE_TIMEOUT;
+
+ if (timeout_ns == 0)
+ return 0;
+
+ return nsecs_to_jiffies_timeout(timeout_ns);
+}
+
/**
* i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT
* @dev: drm device pointer
@@ -2800,10 +2966,9 @@ int
i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
{
struct drm_i915_gem_wait *args = data;
- struct intel_rps_client *rps = to_rps_client(file);
struct drm_i915_gem_object *obj;
- unsigned long active;
- int idx, ret = 0;
+ ktime_t start;
+ long ret;
if (args->flags != 0)
return -EINVAL;
@@ -2812,133 +2977,29 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (!obj)
return -ENOENT;
- active = __I915_BO_ACTIVE(obj);
- for_each_active(active, idx) {
- s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL;
- ret = i915_gem_active_wait_unlocked(&obj->last_read[idx],
- I915_WAIT_INTERRUPTIBLE,
- timeout, rps);
- if (ret)
- break;
- }
-
- i915_gem_object_put_unlocked(obj);
- return ret;
-}
-
-static void __i915_vma_iounmap(struct i915_vma *vma)
-{
- GEM_BUG_ON(i915_vma_is_pinned(vma));
-
- if (vma->iomap == NULL)
- return;
-
- io_mapping_unmap(vma->iomap);
- vma->iomap = NULL;
-}
-
-int i915_vma_unbind(struct i915_vma *vma)
-{
- struct drm_i915_gem_object *obj = vma->obj;
- unsigned long active;
- int ret;
-
- /* First wait upon any activity as retiring the request may
- * have side-effects such as unpinning or even unbinding this vma.
- */
- active = i915_vma_get_active(vma);
- if (active) {
- int idx;
-
- /* When a closed VMA is retired, it is unbound - eek.
- * In order to prevent it from being recursively closed,
- * take a pin on the vma so that the second unbind is
- * aborted.
- */
- __i915_vma_pin(vma);
+ start = ktime_get();
- for_each_active(active, idx) {
- ret = i915_gem_active_retire(&vma->last_read[idx],
- &vma->vm->dev->struct_mutex);
- if (ret)
- break;
- }
-
- __i915_vma_unpin(vma);
- if (ret)
- return ret;
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL,
+ to_wait_timeout(args->timeout_ns),
+ to_rps_client(file));
- GEM_BUG_ON(i915_vma_is_active(vma));
+ if (args->timeout_ns > 0) {
+ args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
+ if (args->timeout_ns < 0)
+ args->timeout_ns = 0;
}
- if (i915_vma_is_pinned(vma))
- return -EBUSY;
-
- if (!drm_mm_node_allocated(&vma->node))
- goto destroy;
-
- GEM_BUG_ON(obj->bind_count == 0);
- GEM_BUG_ON(!obj->pages);
-
- if (i915_vma_is_map_and_fenceable(vma)) {
- /* release the fence reg _after_ flushing */
- ret = i915_vma_put_fence(vma);
- if (ret)
- return ret;
-
- /* Force a pagefault for domain tracking on next user access */
- i915_gem_release_mmap(obj);
-
- __i915_vma_iounmap(vma);
- vma->flags &= ~I915_VMA_CAN_FENCE;
- }
-
- if (likely(!vma->vm->closed)) {
- trace_i915_vma_unbind(vma);
- vma->vm->unbind_vma(vma);
- }
- vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
-
- drm_mm_remove_node(&vma->node);
- list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
-
- if (vma->pages != obj->pages) {
- GEM_BUG_ON(!vma->pages);
- sg_free_table(vma->pages);
- kfree(vma->pages);
- }
- vma->pages = NULL;
-
- /* Since the unbound list is global, only move to that list if
- * no more VMAs exist. */
- if (--obj->bind_count == 0)
- list_move_tail(&obj->global_list,
- &to_i915(obj->base.dev)->mm.unbound_list);
-
- /* And finally now the object is completely decoupled from this vma,
- * we can drop its hold on the backing storage and allow it to be
- * reaped by the shrinker.
- */
- i915_gem_object_unpin_pages(obj);
-
-destroy:
- if (unlikely(i915_vma_is_closed(vma)))
- i915_vma_destroy(vma);
-
- return 0;
+ i915_gem_object_put(obj);
+ return ret;
}
-int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
- unsigned int flags)
+static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags)
{
- struct intel_engine_cs *engine;
- int ret;
-
- for_each_engine(engine, dev_priv) {
- if (engine->last_context == NULL)
- continue;
+ int ret, i;
- ret = intel_engine_idle(engine, flags);
+ for (i = 0; i < ARRAY_SIZE(tl->engine); i++) {
+ ret = i915_gem_active_wait(&tl->engine[i].last_request, flags);
if (ret)
return ret;
}
@@ -2946,187 +3007,45 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
return 0;
}
-static bool i915_gem_valid_gtt_space(struct i915_vma *vma,
- unsigned long cache_level)
-{
- struct drm_mm_node *gtt_space = &vma->node;
- struct drm_mm_node *other;
-
- /*
- * On some machines we have to be careful when putting differing types
- * of snoopable memory together to avoid the prefetcher crossing memory
- * domains and dying. During vm initialisation, we decide whether or not
- * these constraints apply and set the drm_mm.color_adjust
- * appropriately.
- */
- if (vma->vm->mm.color_adjust == NULL)
- return true;
-
- if (!drm_mm_node_allocated(gtt_space))
- return true;
-
- if (list_empty(&gtt_space->node_list))
- return true;
-
- other = list_entry(gtt_space->node_list.prev, struct drm_mm_node, node_list);
- if (other->allocated && !other->hole_follows && other->color != cache_level)
- return false;
-
- other = list_entry(gtt_space->node_list.next, struct drm_mm_node, node_list);
- if (other->allocated && !gtt_space->hole_follows && other->color != cache_level)
- return false;
-
- return true;
-}
-
-/**
- * i915_vma_insert - finds a slot for the vma in its address space
- * @vma: the vma
- * @size: requested size in bytes (can be larger than the VMA)
- * @alignment: required alignment
- * @flags: mask of PIN_* flags to use
- *
- * First we try to allocate some free space that meets the requirements for
- * the VMA. Failiing that, if the flags permit, it will evict an old VMA,
- * preferrably the oldest idle entry to make room for the new VMA.
- *
- * Returns:
- * 0 on success, negative error code otherwise.
- */
-static int
-i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
{
- struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
- struct drm_i915_gem_object *obj = vma->obj;
- u64 start, end;
int ret;
- GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
- GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
-
- size = max(size, vma->size);
- if (flags & PIN_MAPPABLE)
- size = i915_gem_get_ggtt_size(dev_priv, size,
- i915_gem_object_get_tiling(obj));
-
- alignment = max(max(alignment, vma->display_alignment),
- i915_gem_get_ggtt_alignment(dev_priv, size,
- i915_gem_object_get_tiling(obj),
- flags & PIN_MAPPABLE));
-
- start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
-
- end = vma->vm->total;
- if (flags & PIN_MAPPABLE)
- end = min_t(u64, end, dev_priv->ggtt.mappable_end);
- if (flags & PIN_ZONE_4G)
- end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
-
- /* If binding the object/GGTT view requires more space than the entire
- * aperture has, reject it early before evicting everything in a vain
- * attempt to find space.
- */
- if (size > end) {
- DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu [object=%zd] > %s aperture=%llu\n",
- size, obj->base.size,
- flags & PIN_MAPPABLE ? "mappable" : "total",
- end);
- return -E2BIG;
- }
-
- ret = i915_gem_object_get_pages(obj);
- if (ret)
- return ret;
-
- i915_gem_object_pin_pages(obj);
+ if (flags & I915_WAIT_LOCKED) {
+ struct i915_gem_timeline *tl;
- if (flags & PIN_OFFSET_FIXED) {
- u64 offset = flags & PIN_OFFSET_MASK;
- if (offset & (alignment - 1) || offset > end - size) {
- ret = -EINVAL;
- goto err_unpin;
- }
+ lockdep_assert_held(&i915->drm.struct_mutex);
- vma->node.start = offset;
- vma->node.size = size;
- vma->node.color = obj->cache_level;
- ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
- if (ret) {
- ret = i915_gem_evict_for_vma(vma);
- if (ret == 0)
- ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+ list_for_each_entry(tl, &i915->gt.timelines, link) {
+ ret = wait_for_timeline(tl, flags);
if (ret)
- goto err_unpin;
+ return ret;
}
} else {
- u32 search_flag, alloc_flag;
-
- 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;
- }
-
- /* We only allocate in PAGE_SIZE/GTT_PAGE_SIZE (4096) chunks,
- * so we know that we always have a minimum alignment of 4096.
- * The drm_mm range manager is optimised to return results
- * with zero alignment, so where possible use the optimal
- * path.
- */
- if (alignment <= 4096)
- alignment = 0;
-
-search_free:
- ret = drm_mm_insert_node_in_range_generic(&vma->vm->mm,
- &vma->node,
- size, alignment,
- obj->cache_level,
- start, end,
- search_flag,
- alloc_flag);
- if (ret) {
- ret = i915_gem_evict_something(vma->vm, size, alignment,
- obj->cache_level,
- start, end,
- flags);
- if (ret == 0)
- goto search_free;
-
- goto err_unpin;
- }
+ ret = wait_for_timeline(&i915->gt.global_timeline, flags);
+ if (ret)
+ return ret;
}
- GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
-
- list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
- list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
- obj->bind_count++;
return 0;
-
-err_unpin:
- i915_gem_object_unpin_pages(obj);
- return ret;
}
-bool
-i915_gem_clflush_object(struct drm_i915_gem_object *obj,
- bool force)
+void i915_gem_clflush_object(struct drm_i915_gem_object *obj,
+ bool force)
{
/* If we don't have a page list set up, then we're not pinned
* to GPU, and we can ignore the cache flush because it'll happen
* again at bind time.
*/
- if (obj->pages == NULL)
- return false;
+ if (!obj->mm.pages)
+ return;
/*
* Stolen memory is always coherent with the GPU as it is explicitly
* marked as wc by the system, or the system is cache-coherent.
*/
if (obj->stolen || obj->phys_handle)
- return false;
+ return;
/* If the GPU is snooping the contents of the CPU cache,
* we do not need to manually clear the CPU cache lines. However,
@@ -3138,14 +3057,12 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj,
*/
if (!force && cpu_cache_is_coherent(obj->base.dev, obj->cache_level)) {
obj->cache_dirty = true;
- return false;
+ return;
}
trace_i915_gem_object_clflush(obj);
- drm_clflush_sg(obj->pages);
+ drm_clflush_sg(obj->mm.pages);
obj->cache_dirty = false;
-
- return true;
}
/** Flushes the GTT write domain for the object if it's dirty. */
@@ -3174,7 +3091,7 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
*/
wmb();
if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv))
- POSTING_READ(RING_ACTHD(dev_priv->engine[RCS].mmio_base));
+ POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base));
intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT));
@@ -3191,9 +3108,7 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
if (obj->base.write_domain != I915_GEM_DOMAIN_CPU)
return;
- if (i915_gem_clflush_object(obj, obj->pin_display))
- i915_gem_chipset_flush(to_i915(obj->base.dev));
-
+ i915_gem_clflush_object(obj, obj->pin_display);
intel_fb_obj_flush(obj, false, ORIGIN_CPU);
obj->base.write_domain = 0;
@@ -3202,24 +3117,6 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
I915_GEM_DOMAIN_CPU);
}
-static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
-{
- struct i915_vma *vma;
-
- list_for_each_entry(vma, &obj->vma_list, obj_link) {
- if (!i915_vma_is_ggtt(vma))
- continue;
-
- if (i915_vma_is_active(vma))
- continue;
-
- if (!drm_mm_node_allocated(&vma->node))
- continue;
-
- list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
- }
-}
-
/**
* Moves a single object to the GTT read, and possibly write domain.
* @obj: object to act on
@@ -3234,7 +3131,14 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
uint32_t old_write_domain, old_read_domains;
int ret;
- ret = i915_gem_object_wait_rendering(obj, !write);
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ (write ? I915_WAIT_ALL : 0),
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
@@ -3249,7 +3153,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
* continue to assume that the obj remained out of the CPU cached
* domain.
*/
- ret = i915_gem_object_get_pages(obj);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
return ret;
@@ -3268,21 +3172,19 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
/* It should now be out of any other write domains, and we can update
* the domain values for our changes.
*/
- BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+ GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
if (write) {
obj->base.read_domains = I915_GEM_DOMAIN_GTT;
obj->base.write_domain = I915_GEM_DOMAIN_GTT;
- obj->dirty = 1;
+ obj->mm.dirty = true;
}
trace_i915_gem_object_change_domain(obj,
old_read_domains,
old_write_domain);
- /* And bump the LRU for this access */
- i915_gem_object_bump_inactive_ggtt(obj);
-
+ i915_gem_object_unpin_pages(obj);
return 0;
}
@@ -3305,10 +3207,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level)
{
struct i915_vma *vma;
- int ret = 0;
+ int ret;
+
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
if (obj->cache_level == cache_level)
- goto out;
+ return 0;
/* Inspect the list of currently bound VMA and unbind any that would
* be invalid given the new cache-level. This is principally to
@@ -3351,11 +3255,17 @@ restart:
* 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);
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ I915_WAIT_ALL,
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
- if (!HAS_LLC(obj->base.dev) && cache_level != I915_CACHE_NONE) {
+ if (!HAS_LLC(to_i915(obj->base.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
@@ -3397,20 +3307,14 @@ restart:
}
}
+ if (obj->base.write_domain == I915_GEM_DOMAIN_CPU &&
+ cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
+ obj->cache_dirty = true;
+
list_for_each_entry(vma, &obj->vma_list, obj_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 && cpu_write_needs_clflush(obj)) {
- if (i915_gem_clflush_object(obj, true))
- i915_gem_chipset_flush(to_i915(obj->base.dev));
- }
-
return 0;
}
@@ -3419,10 +3323,14 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_caching *args = data;
struct drm_i915_gem_object *obj;
+ int err = 0;
- obj = i915_gem_object_lookup(file, args->handle);
- if (!obj)
- return -ENOENT;
+ rcu_read_lock();
+ obj = i915_gem_object_lookup_rcu(file, args->handle);
+ if (!obj) {
+ err = -ENOENT;
+ goto out;
+ }
switch (obj->cache_level) {
case I915_CACHE_LLC:
@@ -3438,15 +3346,15 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
args->caching = I915_CACHING_NONE;
break;
}
-
- i915_gem_object_put_unlocked(obj);
- return 0;
+out:
+ rcu_read_unlock();
+ return err;
}
int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *i915 = to_i915(dev);
struct drm_i915_gem_caching *args = data;
struct drm_i915_gem_object *obj;
enum i915_cache_level level;
@@ -3463,23 +3371,21 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
* cacheline, whereas normally such cachelines would get
* invalidated.
*/
- if (!HAS_LLC(dev) && !HAS_SNOOP(dev))
+ if (!HAS_LLC(i915) && !HAS_SNOOP(i915))
return -ENODEV;
level = I915_CACHE_LLC;
break;
case I915_CACHING_DISPLAY:
- level = HAS_WT(dev) ? I915_CACHE_WT : I915_CACHE_NONE;
+ level = HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE;
break;
default:
return -EINVAL;
}
- intel_runtime_pm_get(dev_priv);
-
ret = i915_mutex_lock_interruptible(dev);
if (ret)
- goto rpm_put;
+ return ret;
obj = i915_gem_object_lookup(file, args->handle);
if (!obj) {
@@ -3488,13 +3394,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
}
ret = i915_gem_object_set_cache_level(obj, level);
-
i915_gem_object_put(obj);
unlock:
mutex_unlock(&dev->struct_mutex);
-rpm_put:
- intel_runtime_pm_put(dev_priv);
-
return ret;
}
@@ -3512,6 +3414,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 old_read_domains, old_write_domain;
int ret;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
/* Mark the pin_display early so that we account for the
* display coherency whilst setting up the cache domains.
*/
@@ -3527,7 +3431,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
* with that bit in the PTE to main memory with just one PIPE_CONTROL.
*/
ret = i915_gem_object_set_cache_level(obj,
- HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE);
+ HAS_WT(to_i915(obj->base.dev)) ?
+ I915_CACHE_WT : I915_CACHE_NONE);
if (ret) {
vma = ERR_PTR(ret);
goto err_unpin_display;
@@ -3565,7 +3470,11 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
- i915_gem_object_flush_cpu_write_domain(obj);
+ /* Treat this as an end-of-frame, like intel_user_framebuffer_dirty() */
+ if (obj->cache_dirty) {
+ i915_gem_clflush_object(obj, true);
+ intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
+ }
old_write_domain = obj->base.write_domain;
old_read_domains = obj->base.read_domains;
@@ -3590,6 +3499,8 @@ err_unpin_display:
void
i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
{
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+
if (WARN_ON(vma->obj->pin_display == 0))
return;
@@ -3617,7 +3528,14 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
uint32_t old_write_domain, old_read_domains;
int ret;
- ret = i915_gem_object_wait_rendering(obj, !write);
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+ ret = i915_gem_object_wait(obj,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED |
+ (write ? I915_WAIT_ALL : 0),
+ MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (ret)
return ret;
@@ -3639,7 +3557,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
/* It should now be out of any other write domains, and we can update
* the domain values for our changes.
*/
- BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
+ GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
/* If we're writing through the CPU, then the GPU read domains will
* need to be invalidated at next use.
@@ -3673,11 +3591,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
struct drm_i915_file_private *file_priv = file->driver_priv;
unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES;
struct drm_i915_gem_request *request, *target = NULL;
- int ret;
-
- ret = i915_gem_wait_for_error(&dev_priv->gpu_error);
- if (ret)
- return ret;
+ long ret;
/* ABI: return -EIO if already wedged */
if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -3704,103 +3618,12 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
if (target == NULL)
return 0;
- ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, NULL, NULL);
+ ret = i915_wait_request(target,
+ I915_WAIT_INTERRUPTIBLE,
+ MAX_SCHEDULE_TIMEOUT);
i915_gem_request_put(target);
- return ret;
-}
-
-static bool
-i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
-{
- if (!drm_mm_node_allocated(&vma->node))
- return false;
-
- if (vma->node.size < size)
- return true;
-
- if (alignment && vma->node.start & (alignment - 1))
- return true;
-
- if (flags & PIN_MAPPABLE && !i915_vma_is_map_and_fenceable(vma))
- return true;
-
- if (flags & PIN_OFFSET_BIAS &&
- vma->node.start < (flags & PIN_OFFSET_MASK))
- return true;
-
- if (flags & PIN_OFFSET_FIXED &&
- vma->node.start != (flags & PIN_OFFSET_MASK))
- return true;
-
- return false;
-}
-
-void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
-{
- struct drm_i915_gem_object *obj = vma->obj;
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
- bool mappable, fenceable;
- u32 fence_size, fence_alignment;
-
- fence_size = i915_gem_get_ggtt_size(dev_priv,
- vma->size,
- i915_gem_object_get_tiling(obj));
- fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
- vma->size,
- i915_gem_object_get_tiling(obj),
- true);
-
- fenceable = (vma->node.size == fence_size &&
- (vma->node.start & (fence_alignment - 1)) == 0);
-
- mappable = (vma->node.start + fence_size <=
- dev_priv->ggtt.mappable_end);
-
- /*
- * Explicitly disable for rotated VMA since the display does not
- * need the fence and the VMA is not accessible to other users.
- */
- if (mappable && fenceable &&
- vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)
- vma->flags |= I915_VMA_CAN_FENCE;
- else
- vma->flags &= ~I915_VMA_CAN_FENCE;
-}
-
-int __i915_vma_do_pin(struct i915_vma *vma,
- u64 size, u64 alignment, u64 flags)
-{
- unsigned int bound = vma->flags;
- int ret;
-
- GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
- GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma));
-
- if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
- ret = -EBUSY;
- goto err;
- }
-
- if ((bound & I915_VMA_BIND_MASK) == 0) {
- ret = i915_vma_insert(vma, size, alignment, flags);
- if (ret)
- goto err;
- }
-
- ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
- if (ret)
- goto err;
-
- if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)
- __i915_vma_set_map_and_fenceable(vma);
-
- GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
- return 0;
-
-err:
- __i915_vma_unpin(vma);
- return ret;
+ return ret < 0 ? ret : 0;
}
struct i915_vma *
@@ -3810,10 +3633,13 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
u64 alignment,
u64 flags)
{
- struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+ struct i915_address_space *vm = &dev_priv->ggtt.base;
struct i915_vma *vma;
int ret;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
vma = i915_gem_obj_lookup_or_create_vma(obj, vm, view);
if (IS_ERR(vma))
return vma;
@@ -3823,6 +3649,41 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
(i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
return ERR_PTR(-ENOSPC);
+ if (flags & PIN_MAPPABLE) {
+ u32 fence_size;
+
+ fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
+ i915_gem_object_get_tiling(obj));
+ /* If the required space is larger than the available
+ * aperture, we will not able to find a slot for the
+ * object and unbinding the object now will be in
+ * vain. Worse, doing so may cause us to ping-pong
+ * the object in and out of the Global GTT and
+ * waste a lot of cycles under the mutex.
+ */
+ if (fence_size > dev_priv->ggtt.mappable_end)
+ return ERR_PTR(-E2BIG);
+
+ /* If NONBLOCK is set the caller is optimistically
+ * trying to cache the full object within the mappable
+ * aperture, and *must* have a fallback in place for
+ * situations where we cannot bind the object. We
+ * can be a little more lax here and use the fallback
+ * more often to avoid costly migrations of ourselves
+ * and other objects within the aperture.
+ *
+ * Half-the-aperture is used as a simple heuristic.
+ * More interesting would to do search for a free
+ * block prior to making the commitment to unbind.
+ * That caters for the self-harm case, and with a
+ * little more heuristics (e.g. NOFAULT, NOEVICT)
+ * we could try to minimise harm to others.
+ */
+ if (flags & PIN_NONBLOCK &&
+ fence_size > dev_priv->ggtt.mappable_end / 2)
+ return ERR_PTR(-ENOSPC);
+ }
+
WARN(i915_vma_is_pinned(vma),
"bo is already pinned in ggtt with incorrect alignment:"
" offset=%08x, req.alignment=%llx,"
@@ -3869,83 +3730,42 @@ static __always_inline unsigned int __busy_write_id(unsigned int id)
}
static __always_inline unsigned int
-__busy_set_if_active(const struct i915_gem_active *active,
+__busy_set_if_active(const struct dma_fence *fence,
unsigned int (*flag)(unsigned int id))
{
- struct drm_i915_gem_request *request;
+ struct drm_i915_gem_request *rq;
- request = rcu_dereference(active->request);
- if (!request || i915_gem_request_completed(request))
- return 0;
-
- /* This is racy. See __i915_gem_active_get_rcu() for an in detail
- * discussion of how to handle the race correctly, but for reporting
- * the busy state we err on the side of potentially reporting the
- * wrong engine as being busy (but we guarantee that the result
- * is at least self-consistent).
- *
- * As we use SLAB_DESTROY_BY_RCU, the request may be reallocated
- * whilst we are inspecting it, even under the RCU read lock as we are.
- * This means that there is a small window for the engine and/or the
- * seqno to have been overwritten. The seqno will always be in the
- * future compared to the intended, and so we know that if that
- * seqno is idle (on whatever engine) our request is idle and the
- * return 0 above is correct.
- *
- * The issue is that if the engine is switched, it is just as likely
- * to report that it is busy (but since the switch happened, we know
- * the request should be idle). So there is a small chance that a busy
- * result is actually the wrong engine.
- *
- * So why don't we care?
+ /* We have to check the current hw status of the fence as the uABI
+ * guarantees forward progress. We could rely on the idle worker
+ * to eventually flush us, but to minimise latency just ask the
+ * hardware.
*
- * For starters, the busy ioctl is a heuristic that is by definition
- * racy. Even with perfect serialisation in the driver, the hardware
- * state is constantly advancing - the state we report to the user
- * is stale.
- *
- * The critical information for the busy-ioctl is whether the object
- * is idle as userspace relies on that to detect whether its next
- * access will stall, or if it has missed submitting commands to
- * the hardware allowing the GPU to stall. We never generate a
- * false-positive for idleness, thus busy-ioctl is reliable at the
- * most fundamental level, and we maintain the guarantee that a
- * busy object left to itself will eventually become idle (and stay
- * idle!).
- *
- * We allow ourselves the leeway of potentially misreporting the busy
- * state because that is an optimisation heuristic that is constantly
- * in flux. Being quickly able to detect the busy/idle state is much
- * more important than accurate logging of exactly which engines were
- * busy.
- *
- * For accuracy in reporting the engine, we could use
- *
- * result = 0;
- * request = __i915_gem_active_get_rcu(active);
- * if (request) {
- * if (!i915_gem_request_completed(request))
- * result = flag(request->engine->exec_id);
- * i915_gem_request_put(request);
- * }
- *
- * but that still remains susceptible to both hardware and userspace
- * races. So we accept making the result of that race slightly worse,
- * given the rarity of the race and its low impact on the result.
+ * Note we only report on the status of native fences.
*/
- return flag(READ_ONCE(request->engine->exec_id));
+ if (!dma_fence_is_i915(fence))
+ return 0;
+
+ /* opencode to_request() in order to avoid const warnings */
+ rq = container_of(fence, struct drm_i915_gem_request, fence);
+ if (i915_gem_request_completed(rq))
+ return 0;
+
+ return flag(rq->engine->exec_id);
}
static __always_inline unsigned int
-busy_check_reader(const struct i915_gem_active *active)
+busy_check_reader(const struct dma_fence *fence)
{
- return __busy_set_if_active(active, __busy_read_flag);
+ return __busy_set_if_active(fence, __busy_read_flag);
}
static __always_inline unsigned int
-busy_check_writer(const struct i915_gem_active *active)
+busy_check_writer(const struct dma_fence *fence)
{
- return __busy_set_if_active(active, __busy_write_id);
+ if (!fence)
+ return 0;
+
+ return __busy_set_if_active(fence, __busy_write_id);
}
int
@@ -3954,64 +3774,58 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_busy *args = data;
struct drm_i915_gem_object *obj;
- unsigned long active;
+ struct reservation_object_list *list;
+ unsigned int seq;
+ int err;
- obj = i915_gem_object_lookup(file, args->handle);
+ err = -ENOENT;
+ rcu_read_lock();
+ obj = i915_gem_object_lookup_rcu(file, args->handle);
if (!obj)
- return -ENOENT;
+ goto out;
- args->busy = 0;
- active = __I915_BO_ACTIVE(obj);
- if (active) {
- int idx;
+ /* A discrepancy here is that we do not report the status of
+ * non-i915 fences, i.e. even though we may report the object as idle,
+ * a call to set-domain may still stall waiting for foreign rendering.
+ * This also means that wait-ioctl may report an object as busy,
+ * where busy-ioctl considers it idle.
+ *
+ * We trade the ability to warn of foreign fences to report on which
+ * i915 engines are active for the object.
+ *
+ * Alternatively, we can trade that extra information on read/write
+ * activity with
+ * args->busy =
+ * !reservation_object_test_signaled_rcu(obj->resv, true);
+ * to report the overall busyness. This is what the wait-ioctl does.
+ *
+ */
+retry:
+ seq = raw_read_seqcount(&obj->resv->seq);
- /* Yes, the lookups are intentionally racy.
- *
- * First, we cannot simply rely on __I915_BO_ACTIVE. We have
- * to regard the value as stale and as our ABI guarantees
- * forward progress, we confirm the status of each active
- * request with the hardware.
- *
- * Even though we guard the pointer lookup by RCU, that only
- * guarantees that the pointer and its contents remain
- * dereferencable and does *not* mean that the request we
- * have is the same as the one being tracked by the object.
- *
- * Consider that we lookup the request just as it is being
- * retired and freed. We take a local copy of the pointer,
- * but before we add its engine into the busy set, the other
- * thread reallocates it and assigns it to a task on another
- * engine with a fresh and incomplete seqno. Guarding against
- * that requires careful serialisation and reference counting,
- * i.e. using __i915_gem_active_get_request_rcu(). We don't,
- * instead we expect that if the result is busy, which engines
- * are busy is not completely reliable - we only guarantee
- * that the object was busy.
- */
- rcu_read_lock();
+ /* Translate the exclusive fence to the READ *and* WRITE engine */
+ args->busy = busy_check_writer(rcu_dereference(obj->resv->fence_excl));
- for_each_active(active, idx)
- args->busy |= busy_check_reader(&obj->last_read[idx]);
+ /* Translate shared fences to READ set of engines */
+ list = rcu_dereference(obj->resv->fence);
+ if (list) {
+ unsigned int shared_count = list->shared_count, i;
- /* For ABI sanity, we only care that the write engine is in
- * the set of read engines. This should be ensured by the
- * ordering of setting last_read/last_write in
- * i915_vma_move_to_active(), and then in reverse in retire.
- * However, for good measure, we always report the last_write
- * request as a busy read as well as being a busy write.
- *
- * We don't care that the set of active read/write engines
- * may change during construction of the result, as it is
- * equally liable to change before userspace can inspect
- * the result.
- */
- args->busy |= busy_check_writer(&obj->last_write);
+ for (i = 0; i < shared_count; ++i) {
+ struct dma_fence *fence =
+ rcu_dereference(list->shared[i]);
- rcu_read_unlock();
+ args->busy |= busy_check_reader(fence);
+ }
}
- i915_gem_object_put_unlocked(obj);
- return 0;
+ if (args->busy && read_seqcount_retry(&obj->resv->seq, seq))
+ goto retry;
+
+ err = 0;
+out:
+ rcu_read_unlock();
+ return err;
}
int
@@ -4028,7 +3842,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_madvise *args = data;
struct drm_i915_gem_object *obj;
- int ret;
+ int err;
switch (args->madv) {
case I915_MADV_DONTNEED:
@@ -4038,77 +3852,111 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
-
obj = i915_gem_object_lookup(file_priv, args->handle);
- if (!obj) {
- ret = -ENOENT;
- goto unlock;
- }
+ if (!obj)
+ return -ENOENT;
- if (obj->pages &&
+ err = mutex_lock_interruptible(&obj->mm.lock);
+ if (err)
+ goto out;
+
+ if (obj->mm.pages &&
i915_gem_object_is_tiled(obj) &&
dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
- if (obj->madv == I915_MADV_WILLNEED)
- i915_gem_object_unpin_pages(obj);
- if (args->madv == I915_MADV_WILLNEED)
- i915_gem_object_pin_pages(obj);
+ if (obj->mm.madv == I915_MADV_WILLNEED) {
+ GEM_BUG_ON(!obj->mm.quirked);
+ __i915_gem_object_unpin_pages(obj);
+ obj->mm.quirked = false;
+ }
+ if (args->madv == I915_MADV_WILLNEED) {
+ GEM_BUG_ON(obj->mm.quirked);
+ __i915_gem_object_pin_pages(obj);
+ obj->mm.quirked = true;
+ }
}
- if (obj->madv != __I915_MADV_PURGED)
- obj->madv = args->madv;
+ if (obj->mm.madv != __I915_MADV_PURGED)
+ obj->mm.madv = args->madv;
/* if the object is no longer attached, discard its backing storage */
- if (obj->madv == I915_MADV_DONTNEED && obj->pages == NULL)
+ if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages)
i915_gem_object_truncate(obj);
- args->retained = obj->madv != __I915_MADV_PURGED;
+ args->retained = obj->mm.madv != __I915_MADV_PURGED;
+ mutex_unlock(&obj->mm.lock);
+out:
i915_gem_object_put(obj);
-unlock:
- mutex_unlock(&dev->struct_mutex);
- return ret;
+ return err;
+}
+
+static void
+frontbuffer_retire(struct i915_gem_active *active,
+ struct drm_i915_gem_request *request)
+{
+ struct drm_i915_gem_object *obj =
+ container_of(active, typeof(*obj), frontbuffer_write);
+
+ intel_fb_obj_flush(obj, true, ORIGIN_CS);
}
void i915_gem_object_init(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_object_ops *ops)
{
- int i;
+ mutex_init(&obj->mm.lock);
- INIT_LIST_HEAD(&obj->global_list);
- for (i = 0; i < I915_NUM_ENGINES; i++)
- init_request_active(&obj->last_read[i],
- i915_gem_object_retire__read);
- init_request_active(&obj->last_write,
- i915_gem_object_retire__write);
+ INIT_LIST_HEAD(&obj->global_link);
+ INIT_LIST_HEAD(&obj->userfault_link);
INIT_LIST_HEAD(&obj->obj_exec_link);
INIT_LIST_HEAD(&obj->vma_list);
INIT_LIST_HEAD(&obj->batch_pool_link);
obj->ops = ops;
+ reservation_object_init(&obj->__builtin_resv);
+ obj->resv = &obj->__builtin_resv;
+
obj->frontbuffer_ggtt_origin = ORIGIN_GTT;
- obj->madv = I915_MADV_WILLNEED;
+ init_request_active(&obj->frontbuffer_write, frontbuffer_retire);
+
+ obj->mm.madv = I915_MADV_WILLNEED;
+ INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
+ mutex_init(&obj->mm.get_page.lock);
i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size);
}
static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
- .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
+ .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+ I915_GEM_OBJECT_IS_SHRINKABLE,
.get_pages = i915_gem_object_get_pages_gtt,
.put_pages = i915_gem_object_put_pages_gtt,
};
-struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
- size_t size)
+/* Note we don't consider signbits :| */
+#define overflows_type(x, T) \
+ (sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE))
+
+struct drm_i915_gem_object *
+i915_gem_object_create(struct drm_device *dev, u64 size)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj;
struct address_space *mapping;
gfp_t mask;
int ret;
+ /* There is a prevalence of the assumption that we fit the object's
+ * page count inside a 32bit _signed_ variable. Let's document this and
+ * catch if we ever need to fix it. In the meantime, if you do spot
+ * such a local variable, please consider fixing!
+ */
+ if (WARN_ON(size >> PAGE_SHIFT > INT_MAX))
+ return ERR_PTR(-E2BIG);
+
+ if (overflows_type(size, obj->base.size))
+ return ERR_PTR(-E2BIG);
+
obj = i915_gem_object_alloc(dev);
if (obj == NULL)
return ERR_PTR(-ENOMEM);
@@ -4118,7 +3966,7 @@ struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
goto fail;
mask = GFP_HIGHUSER | __GFP_RECLAIMABLE;
- if (IS_CRESTLINE(dev) || IS_BROADWATER(dev)) {
+ if (IS_CRESTLINE(dev_priv) || IS_BROADWATER(dev_priv)) {
/* 965gm cannot relocate objects above 4GiB. */
mask &= ~__GFP_HIGHMEM;
mask |= __GFP_DMA32;
@@ -4132,7 +3980,7 @@ struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
obj->base.write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU;
- if (HAS_LLC(dev)) {
+ if (HAS_LLC(dev_priv)) {
/* On some devices, we can have the GPU use the LLC (the CPU
* cache) for about a 10% performance improvement
* compared to uncached. Graphics requests other than
@@ -4155,7 +4003,6 @@ struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
fail:
i915_gem_object_free(obj);
-
return ERR_PTR(ret);
}
@@ -4167,7 +4014,7 @@ static bool discard_backing_storage(struct drm_i915_gem_object *obj)
* back the contents from the GPU.
*/
- if (obj->madv != I915_MADV_WILLNEED)
+ if (obj->mm.madv != I915_MADV_WILLNEED)
return false;
if (obj->base.filp == NULL)
@@ -4183,16 +4030,72 @@ static bool discard_backing_storage(struct drm_i915_gem_object *obj)
return atomic_long_read(&obj->base.filp->f_count) == 1;
}
-void i915_gem_free_object(struct drm_gem_object *gem_obj)
+static void __i915_gem_free_objects(struct drm_i915_private *i915,
+ struct llist_node *freed)
{
- struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
- struct drm_device *dev = obj->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_vma *vma, *next;
+ struct drm_i915_gem_object *obj, *on;
- intel_runtime_pm_get(dev_priv);
+ mutex_lock(&i915->drm.struct_mutex);
+ intel_runtime_pm_get(i915);
+ llist_for_each_entry(obj, freed, freed) {
+ struct i915_vma *vma, *vn;
+
+ trace_i915_gem_object_destroy(obj);
+
+ GEM_BUG_ON(i915_gem_object_is_active(obj));
+ list_for_each_entry_safe(vma, vn,
+ &obj->vma_list, obj_link) {
+ GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+ GEM_BUG_ON(i915_vma_is_active(vma));
+ vma->flags &= ~I915_VMA_PIN_MASK;
+ i915_vma_close(vma);
+ }
+ GEM_BUG_ON(!list_empty(&obj->vma_list));
+ GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree));
+
+ list_del(&obj->global_link);
+ }
+ intel_runtime_pm_put(i915);
+ mutex_unlock(&i915->drm.struct_mutex);
+
+ llist_for_each_entry_safe(obj, on, freed, freed) {
+ GEM_BUG_ON(obj->bind_count);
+ GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
+
+ if (obj->ops->release)
+ obj->ops->release(obj);
+
+ if (WARN_ON(i915_gem_object_has_pinned_pages(obj)))
+ atomic_set(&obj->mm.pages_pin_count, 0);
+ __i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+ GEM_BUG_ON(obj->mm.pages);
+
+ if (obj->base.import_attach)
+ drm_prime_gem_destroy(&obj->base, NULL);
+
+ reservation_object_fini(&obj->__builtin_resv);
+ drm_gem_object_release(&obj->base);
+ i915_gem_info_remove_obj(i915, obj->base.size);
+
+ kfree(obj->bit_17);
+ i915_gem_object_free(obj);
+ }
+}
+
+static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
+{
+ struct llist_node *freed;
+
+ freed = llist_del_all(&i915->mm.free_list);
+ if (unlikely(freed))
+ __i915_gem_free_objects(i915, freed);
+}
- trace_i915_gem_object_destroy(obj);
+static void __i915_gem_free_work(struct work_struct *work)
+{
+ struct drm_i915_private *i915 =
+ container_of(work, struct drm_i915_private, mm.free_work);
+ struct llist_node *freed;
/* All file-owned VMA should have been released by this point through
* i915_gem_close_object(), or earlier by i915_gem_context_close().
@@ -4201,47 +4104,62 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
* the GTT either for the user or for scanout). Those VMA still need to
* unbound now.
*/
- list_for_each_entry_safe(vma, next, &obj->vma_list, obj_link) {
- GEM_BUG_ON(!i915_vma_is_ggtt(vma));
- GEM_BUG_ON(i915_vma_is_active(vma));
- vma->flags &= ~I915_VMA_PIN_MASK;
- i915_vma_close(vma);
- }
- GEM_BUG_ON(obj->bind_count);
- /* Stolen objects don't hold a ref, but do hold pin count. Fix that up
- * before progressing. */
- if (obj->stolen)
- i915_gem_object_unpin_pages(obj);
+ while ((freed = llist_del_all(&i915->mm.free_list)))
+ __i915_gem_free_objects(i915, freed);
+}
- WARN_ON(atomic_read(&obj->frontbuffer_bits));
+static void __i915_gem_free_object_rcu(struct rcu_head *head)
+{
+ struct drm_i915_gem_object *obj =
+ container_of(head, typeof(*obj), rcu);
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
- if (obj->pages && obj->madv == I915_MADV_WILLNEED &&
- dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES &&
- i915_gem_object_is_tiled(obj))
- i915_gem_object_unpin_pages(obj);
+ /* We can't simply use call_rcu() from i915_gem_free_object()
+ * as we need to block whilst unbinding, and the call_rcu
+ * task may be called from softirq context. So we take a
+ * detour through a worker.
+ */
+ if (llist_add(&obj->freed, &i915->mm.free_list))
+ schedule_work(&i915->mm.free_work);
+}
- if (WARN_ON(obj->pages_pin_count))
- obj->pages_pin_count = 0;
- if (discard_backing_storage(obj))
- obj->madv = I915_MADV_DONTNEED;
- i915_gem_object_put_pages(obj);
+void i915_gem_free_object(struct drm_gem_object *gem_obj)
+{
+ struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
- BUG_ON(obj->pages);
+ if (obj->mm.quirked)
+ __i915_gem_object_unpin_pages(obj);
- if (obj->base.import_attach)
- drm_prime_gem_destroy(&obj->base, NULL);
+ if (discard_backing_storage(obj))
+ obj->mm.madv = I915_MADV_DONTNEED;
+
+ /* Before we free the object, make sure any pure RCU-only
+ * read-side critical sections are complete, e.g.
+ * i915_gem_busy_ioctl(). For the corresponding synchronized
+ * lookup see i915_gem_object_lookup_rcu().
+ */
+ call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+}
- if (obj->ops->release)
- obj->ops->release(obj);
+void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj)
+{
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
- drm_gem_object_release(&obj->base);
- i915_gem_info_remove_obj(dev_priv, obj->base.size);
+ GEM_BUG_ON(i915_gem_object_has_active_reference(obj));
+ if (i915_gem_object_is_active(obj))
+ i915_gem_object_set_active_reference(obj);
+ else
+ i915_gem_object_put(obj);
+}
- kfree(obj->bit_17);
- i915_gem_object_free(obj);
+static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- intel_runtime_pm_put(dev_priv);
+ for_each_engine(engine, dev_priv, id)
+ GEM_BUG_ON(engine->last_context != dev_priv->kernel_context);
}
int i915_gem_suspend(struct drm_device *dev)
@@ -4272,18 +4190,46 @@ int i915_gem_suspend(struct drm_device *dev)
goto err;
i915_gem_retire_requests(dev_priv);
+ GEM_BUG_ON(dev_priv->gt.active_requests);
+ assert_kernel_context_is_current(dev_priv);
i915_gem_context_lost(dev_priv);
mutex_unlock(&dev->struct_mutex);
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
cancel_delayed_work_sync(&dev_priv->gt.retire_work);
flush_delayed_work(&dev_priv->gt.idle_work);
+ flush_work(&dev_priv->mm.free_work);
/* Assert that we sucessfully flushed all the work and
* reset the GPU back to its idle, low power state.
*/
WARN_ON(dev_priv->gt.awake);
+ WARN_ON(!intel_execlists_idle(dev_priv));
+
+ /*
+ * Neither the BIOS, ourselves or any other kernel
+ * expects the system to be in execlists mode on startup,
+ * so we need to reset the GPU back to legacy mode. And the only
+ * known way to disable logical contexts is through a GPU reset.
+ *
+ * So in order to leave the system in a known default configuration,
+ * always reset the GPU upon unload and suspend. Afterwards we then
+ * clean up the GEM state tracking, flushing off the requests and
+ * leaving the system in a known idle state.
+ *
+ * Note that is of the upmost importance that the GPU is idle and
+ * all stray writes are flushed *before* we dismantle the backing
+ * storage for the pinned objects.
+ *
+ * However, since we are uncertain that resetting the GPU on older
+ * machines is a good idea, we don't - just in case it leaves the
+ * machine in an unusable condition.
+ */
+ if (HAS_HW_CONTEXTS(dev_priv)) {
+ int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
+ WARN_ON(reset && reset != -ENODEV);
+ }
return 0;
@@ -4296,8 +4242,10 @@ void i915_gem_resume(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ WARN_ON(dev_priv->gt.awake);
+
mutex_lock(&dev->struct_mutex);
- i915_gem_restore_gtt_mappings(dev);
+ i915_gem_restore_gtt_mappings(dev_priv);
/* As we didn't flush the kernel context before suspend, we cannot
* guarantee that the context image is complete. So let's just reset
@@ -4308,55 +4256,51 @@ void i915_gem_resume(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);
}
-void i915_gem_init_swizzling(struct drm_device *dev)
+void i915_gem_init_swizzling(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (INTEL_INFO(dev)->gen < 5 ||
+ if (INTEL_GEN(dev_priv) < 5 ||
dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
return;
I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
DISP_TILE_SURFACE_SWIZZLING);
- if (IS_GEN5(dev))
+ if (IS_GEN5(dev_priv))
return;
I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev_priv))
I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
- else if (IS_GEN7(dev))
+ else if (IS_GEN7(dev_priv))
I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
- else if (IS_GEN8(dev))
+ else if (IS_GEN8(dev_priv))
I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW));
else
BUG();
}
-static void init_unused_ring(struct drm_device *dev, u32 base)
+static void init_unused_ring(struct drm_i915_private *dev_priv, u32 base)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(RING_CTL(base), 0);
I915_WRITE(RING_HEAD(base), 0);
I915_WRITE(RING_TAIL(base), 0);
I915_WRITE(RING_START(base), 0);
}
-static void init_unused_rings(struct drm_device *dev)
-{
- if (IS_I830(dev)) {
- init_unused_ring(dev, PRB1_BASE);
- init_unused_ring(dev, SRB0_BASE);
- init_unused_ring(dev, SRB1_BASE);
- init_unused_ring(dev, SRB2_BASE);
- init_unused_ring(dev, SRB3_BASE);
- } else if (IS_GEN2(dev)) {
- init_unused_ring(dev, SRB0_BASE);
- init_unused_ring(dev, SRB1_BASE);
- } else if (IS_GEN3(dev)) {
- init_unused_ring(dev, PRB1_BASE);
- init_unused_ring(dev, PRB2_BASE);
+static void init_unused_rings(struct drm_i915_private *dev_priv)
+{
+ if (IS_I830(dev_priv)) {
+ init_unused_ring(dev_priv, PRB1_BASE);
+ init_unused_ring(dev_priv, SRB0_BASE);
+ init_unused_ring(dev_priv, SRB1_BASE);
+ init_unused_ring(dev_priv, SRB2_BASE);
+ init_unused_ring(dev_priv, SRB3_BASE);
+ } else if (IS_GEN2(dev_priv)) {
+ init_unused_ring(dev_priv, SRB0_BASE);
+ init_unused_ring(dev_priv, SRB1_BASE);
+ } else if (IS_GEN3(dev_priv)) {
+ init_unused_ring(dev_priv, PRB1_BASE);
+ init_unused_ring(dev_priv, PRB2_BASE);
}
}
@@ -4365,31 +4309,34 @@ i915_gem_init_hw(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int ret;
+ dev_priv->gt.last_init_time = ktime_get();
+
/* Double layer security blanket, see i915_gem_init() */
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
- if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9)
+ if (HAS_EDRAM(dev_priv) && INTEL_GEN(dev_priv) < 9)
I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
- if (IS_HASWELL(dev))
- I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ?
+ if (IS_HASWELL(dev_priv))
+ I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ?
LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
- if (HAS_PCH_NOP(dev)) {
- if (IS_IVYBRIDGE(dev)) {
+ if (HAS_PCH_NOP(dev_priv)) {
+ if (IS_IVYBRIDGE(dev_priv)) {
u32 temp = I915_READ(GEN7_MSG_CTL);
temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
I915_WRITE(GEN7_MSG_CTL, temp);
- } else if (INTEL_INFO(dev)->gen >= 7) {
+ } else if (INTEL_GEN(dev_priv) >= 7) {
u32 temp = I915_READ(HSW_NDE_RSTWRN_OPT);
temp &= ~RESET_PCH_HANDSHAKE_ENABLE;
I915_WRITE(HSW_NDE_RSTWRN_OPT, temp);
}
}
- i915_gem_init_swizzling(dev);
+ i915_gem_init_swizzling(dev_priv);
/*
* At least 830 can leave some of the unused rings
@@ -4397,18 +4344,18 @@ i915_gem_init_hw(struct drm_device *dev)
* will prevent c3 entry. Makes sure all unused rings
* are totally idle.
*/
- init_unused_rings(dev);
+ init_unused_rings(dev_priv);
BUG_ON(!dev_priv->kernel_context);
- ret = i915_ppgtt_init_hw(dev);
+ ret = i915_ppgtt_init_hw(dev_priv);
if (ret) {
DRM_ERROR("PPGTT enable HW failed %d\n", ret);
goto out;
}
/* Need to do basic initialisation of all rings first: */
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
ret = engine->init_hw(engine);
if (ret)
goto out;
@@ -4507,21 +4454,15 @@ i915_gem_cleanup_engines(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
dev_priv->gt.cleanup_engine(engine);
}
-static void
-init_engine_lists(struct intel_engine_cs *engine)
-{
- INIT_LIST_HEAD(&engine->request_list);
-}
-
void
i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
int i;
if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
@@ -4545,41 +4486,52 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
fence->id = i;
list_add_tail(&fence->link, &dev_priv->mm.fence_list);
}
- i915_gem_restore_fences(dev);
+ i915_gem_restore_fences(dev_priv);
- i915_gem_detect_bit_6_swizzle(dev);
+ i915_gem_detect_bit_6_swizzle(dev_priv);
}
-void
+int
i915_gem_load_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int i;
+ int err = -ENOMEM;
+
+ dev_priv->objects = KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN);
+ if (!dev_priv->objects)
+ goto err_out;
+
+ dev_priv->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
+ if (!dev_priv->vmas)
+ goto err_objects;
+
+ dev_priv->requests = KMEM_CACHE(drm_i915_gem_request,
+ SLAB_HWCACHE_ALIGN |
+ SLAB_RECLAIM_ACCOUNT |
+ SLAB_DESTROY_BY_RCU);
+ if (!dev_priv->requests)
+ goto err_vmas;
- dev_priv->objects =
- kmem_cache_create("i915_gem_object",
- sizeof(struct drm_i915_gem_object), 0,
- SLAB_HWCACHE_ALIGN,
- NULL);
- dev_priv->vmas =
- kmem_cache_create("i915_gem_vma",
- sizeof(struct i915_vma), 0,
- SLAB_HWCACHE_ALIGN,
- NULL);
- dev_priv->requests =
- kmem_cache_create("i915_gem_request",
- sizeof(struct drm_i915_gem_request), 0,
- SLAB_HWCACHE_ALIGN |
- SLAB_RECLAIM_ACCOUNT |
- SLAB_DESTROY_BY_RCU,
- NULL);
+ dev_priv->dependencies = KMEM_CACHE(i915_dependency,
+ SLAB_HWCACHE_ALIGN |
+ SLAB_RECLAIM_ACCOUNT);
+ if (!dev_priv->dependencies)
+ goto err_requests;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ INIT_LIST_HEAD(&dev_priv->gt.timelines);
+ err = i915_gem_timeline_init__global(dev_priv);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ if (err)
+ goto err_dependencies;
INIT_LIST_HEAD(&dev_priv->context_list);
+ INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work);
+ init_llist_head(&dev_priv->mm.free_list);
INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
INIT_LIST_HEAD(&dev_priv->mm.bound_list);
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
- for (i = 0; i < I915_NUM_ENGINES; i++)
- init_engine_lists(&dev_priv->engine[i]);
+ INIT_LIST_HEAD(&dev_priv->mm.userfault_list);
INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
i915_gem_retire_work_handler);
INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
@@ -4596,12 +4548,33 @@ i915_gem_load_init(struct drm_device *dev)
atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0);
spin_lock_init(&dev_priv->fb_tracking.lock);
+
+ return 0;
+
+err_dependencies:
+ kmem_cache_destroy(dev_priv->dependencies);
+err_requests:
+ kmem_cache_destroy(dev_priv->requests);
+err_vmas:
+ kmem_cache_destroy(dev_priv->vmas);
+err_objects:
+ kmem_cache_destroy(dev_priv->objects);
+err_out:
+ return err;
}
void i915_gem_load_cleanup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ WARN_ON(!llist_empty(&dev_priv->mm.free_list));
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ i915_gem_timeline_fini(&dev_priv->gt.global_timeline);
+ WARN_ON(!list_empty(&dev_priv->gt.timelines));
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+
+ kmem_cache_destroy(dev_priv->dependencies);
kmem_cache_destroy(dev_priv->requests);
kmem_cache_destroy(dev_priv->vmas);
kmem_cache_destroy(dev_priv->objects);
@@ -4650,7 +4623,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND);
for (p = phases; *p; p++) {
- list_for_each_entry(obj, *p, global_list) {
+ list_for_each_entry(obj, *p, global_link) {
obj->base.read_domains = I915_GEM_DOMAIN_CPU;
obj->base.write_domain = I915_GEM_DOMAIN_CPU;
}
@@ -4686,7 +4659,7 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file)
struct drm_i915_file_private *file_priv;
int ret;
- DRM_DEBUG_DRIVER("\n");
+ DRM_DEBUG("\n");
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
if (!file_priv)
@@ -4742,21 +4715,6 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
}
}
-/* Like i915_gem_object_get_page(), but mark the returned page dirty */
-struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
-{
- struct page *page;
-
- /* Only default objects have per-page dirty tracking */
- if (WARN_ON(!i915_gem_object_has_struct_page(obj)))
- return NULL;
-
- page = i915_gem_object_get_page(obj, n);
- set_page_dirty(page);
- return page;
-}
-
/* Allocate a new GEM object and fill it with the supplied data */
struct drm_i915_gem_object *
i915_gem_object_create_from_data(struct drm_device *dev,
@@ -4775,14 +4733,13 @@ i915_gem_object_create_from_data(struct drm_device *dev,
if (ret)
goto fail;
- ret = i915_gem_object_get_pages(obj);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
goto fail;
- i915_gem_object_pin_pages(obj);
- sg = obj->pages;
+ sg = obj->mm.pages;
bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
- obj->dirty = 1; /* Backing store is now out of date */
+ obj->mm.dirty = true; /* Backing store is now out of date */
i915_gem_object_unpin_pages(obj);
if (WARN_ON(bytes != size)) {
@@ -4797,3 +4754,156 @@ fail:
i915_gem_object_put(obj);
return ERR_PTR(ret);
}
+
+struct scatterlist *
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+ unsigned int n,
+ unsigned int *offset)
+{
+ struct i915_gem_object_page_iter *iter = &obj->mm.get_page;
+ struct scatterlist *sg;
+ unsigned int idx, count;
+
+ might_sleep();
+ GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
+ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+
+ /* As we iterate forward through the sg, we record each entry in a
+ * radixtree for quick repeated (backwards) lookups. If we have seen
+ * this index previously, we will have an entry for it.
+ *
+ * Initial lookup is O(N), but this is amortized to O(1) for
+ * sequential page access (where each new request is consecutive
+ * to the previous one). Repeated lookups are O(lg(obj->base.size)),
+ * i.e. O(1) with a large constant!
+ */
+ if (n < READ_ONCE(iter->sg_idx))
+ goto lookup;
+
+ mutex_lock(&iter->lock);
+
+ /* We prefer to reuse the last sg so that repeated lookup of this
+ * (or the subsequent) sg are fast - comparing against the last
+ * sg is faster than going through the radixtree.
+ */
+
+ sg = iter->sg_pos;
+ idx = iter->sg_idx;
+ count = __sg_page_count(sg);
+
+ while (idx + count <= n) {
+ unsigned long exception, i;
+ int ret;
+
+ /* If we cannot allocate and insert this entry, or the
+ * individual pages from this range, cancel updating the
+ * sg_idx so that on this lookup we are forced to linearly
+ * scan onwards, but on future lookups we will try the
+ * insertion again (in which case we need to be careful of
+ * the error return reporting that we have already inserted
+ * this index).
+ */
+ ret = radix_tree_insert(&iter->radix, idx, sg);
+ if (ret && ret != -EEXIST)
+ goto scan;
+
+ exception =
+ RADIX_TREE_EXCEPTIONAL_ENTRY |
+ idx << RADIX_TREE_EXCEPTIONAL_SHIFT;
+ for (i = 1; i < count; i++) {
+ ret = radix_tree_insert(&iter->radix, idx + i,
+ (void *)exception);
+ if (ret && ret != -EEXIST)
+ goto scan;
+ }
+
+ idx += count;
+ sg = ____sg_next(sg);
+ count = __sg_page_count(sg);
+ }
+
+scan:
+ iter->sg_pos = sg;
+ iter->sg_idx = idx;
+
+ mutex_unlock(&iter->lock);
+
+ if (unlikely(n < idx)) /* insertion completed by another thread */
+ goto lookup;
+
+ /* In case we failed to insert the entry into the radixtree, we need
+ * to look beyond the current sg.
+ */
+ while (idx + count <= n) {
+ idx += count;
+ sg = ____sg_next(sg);
+ count = __sg_page_count(sg);
+ }
+
+ *offset = n - idx;
+ return sg;
+
+lookup:
+ rcu_read_lock();
+
+ sg = radix_tree_lookup(&iter->radix, n);
+ GEM_BUG_ON(!sg);
+
+ /* If this index is in the middle of multi-page sg entry,
+ * the radixtree will contain an exceptional entry that points
+ * to the start of that range. We will return the pointer to
+ * the base page and the offset of this page within the
+ * sg entry's range.
+ */
+ *offset = 0;
+ if (unlikely(radix_tree_exception(sg))) {
+ unsigned long base =
+ (unsigned long)sg >> RADIX_TREE_EXCEPTIONAL_SHIFT;
+
+ sg = radix_tree_lookup(&iter->radix, base);
+ GEM_BUG_ON(!sg);
+
+ *offset = n - base;
+ }
+
+ rcu_read_unlock();
+
+ return sg;
+}
+
+struct page *
+i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
+{
+ struct scatterlist *sg;
+ unsigned int offset;
+
+ GEM_BUG_ON(!i915_gem_object_has_struct_page(obj));
+
+ sg = i915_gem_object_get_sg(obj, n, &offset);
+ return nth_page(sg_page(sg), offset);
+}
+
+/* Like i915_gem_object_get_page(), but mark the returned page dirty */
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+ unsigned int n)
+{
+ struct page *page;
+
+ page = i915_gem_object_get_page(obj, n);
+ if (!obj->mm.dirty)
+ set_page_dirty(page);
+
+ return page;
+}
+
+dma_addr_t
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
+ unsigned long n)
+{
+ struct scatterlist *sg;
+ unsigned int offset;
+
+ sg = i915_gem_object_get_sg(obj, n, &offset);
+ return sg_dma_address(sg) + (offset << PAGE_SHIFT);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h
index 8292e797d9b5..51ec793f2e20 100644
--- a/drivers/gpu/drm/i915/i915_gem.h
+++ b/drivers/gpu/drm/i915/i915_gem.h
@@ -28,7 +28,9 @@
#ifdef CONFIG_DRM_I915_DEBUG_GEM
#define GEM_BUG_ON(expr) BUG_ON(expr)
#else
-#define GEM_BUG_ON(expr)
+#define GEM_BUG_ON(expr) do { } while (0)
#endif
+#define I915_NUM_ENGINES 5
+
#endif /* __I915_GEM_H__ */
diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c
index ed989596d9a3..b3bc119ec1bb 100644
--- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c
+++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c
@@ -73,7 +73,7 @@ void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool)
list_for_each_entry_safe(obj, next,
&pool->cache_list[n],
batch_pool_link)
- i915_gem_object_put(obj);
+ __i915_gem_object_release_unless_active(obj);
INIT_LIST_HEAD(&pool->cache_list[n]);
}
@@ -97,9 +97,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
size_t size)
{
struct drm_i915_gem_object *obj = NULL;
- struct drm_i915_gem_object *tmp, *next;
+ struct drm_i915_gem_object *tmp;
struct list_head *list;
- int n;
+ int n, ret;
lockdep_assert_held(&pool->engine->i915->drm.struct_mutex);
@@ -112,40 +112,35 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
n = ARRAY_SIZE(pool->cache_list) - 1;
list = &pool->cache_list[n];
- list_for_each_entry_safe(tmp, next, list, batch_pool_link) {
+ list_for_each_entry(tmp, list, batch_pool_link) {
/* The batches are strictly LRU ordered */
- if (!i915_gem_active_is_idle(&tmp->last_read[pool->engine->id],
- &tmp->base.dev->struct_mutex))
+ if (i915_gem_object_is_active(tmp))
break;
- /* While we're looping, do some clean up */
- if (tmp->madv == __I915_MADV_PURGED) {
- list_del(&tmp->batch_pool_link);
- i915_gem_object_put(tmp);
- continue;
- }
+ GEM_BUG_ON(!reservation_object_test_signaled_rcu(tmp->resv,
+ true));
if (tmp->base.size >= size) {
+ /* Clear the set of shared fences early */
+ ww_mutex_lock(&tmp->resv->lock, NULL);
+ reservation_object_add_excl_fence(tmp->resv, NULL);
+ ww_mutex_unlock(&tmp->resv->lock);
+
obj = tmp;
break;
}
}
if (obj == NULL) {
- int ret;
-
- obj = i915_gem_object_create(&pool->engine->i915->drm, size);
+ obj = i915_gem_object_create_internal(pool->engine->i915, size);
if (IS_ERR(obj))
return obj;
-
- ret = i915_gem_object_get_pages(obj);
- if (ret)
- return ERR_PTR(ret);
-
- obj->madv = I915_MADV_DONTNEED;
}
+ ret = i915_gem_object_pin_pages(obj);
+ if (ret)
+ return ERR_PTR(ret);
+
list_move_tail(&obj->batch_pool_link, list);
- i915_gem_object_pin_pages(obj);
return obj;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index df10f4e95736..1f94b8d6d83d 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -155,9 +155,10 @@ void i915_gem_context_free(struct kref *ctx_ref)
if (ce->ring)
intel_ring_free(ce->ring);
- i915_vma_put(ce->state);
+ __i915_gem_object_release_unless_active(ce->state->obj);
}
+ kfree(ctx->name);
put_pid(ctx->pid);
list_del(&ctx->link);
@@ -192,7 +193,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
* This is only applicable for Ivy Bridge devices since
* later platforms don't have L3 control bits in the PTE.
*/
- if (IS_IVYBRIDGE(dev)) {
+ if (IS_IVYBRIDGE(to_i915(dev))) {
ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
/* Failure shouldn't ever happen this early */
if (WARN_ON(ret)) {
@@ -303,19 +304,28 @@ __create_hw_context(struct drm_device *dev,
}
/* Default context will never have a file_priv */
- if (file_priv != NULL) {
+ ret = DEFAULT_CONTEXT_HANDLE;
+ if (file_priv) {
ret = idr_alloc(&file_priv->context_idr, ctx,
DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL);
if (ret < 0)
goto err_out;
- } else
- ret = DEFAULT_CONTEXT_HANDLE;
+ }
+ ctx->user_handle = ret;
ctx->file_priv = file_priv;
- if (file_priv)
+ if (file_priv) {
ctx->pid = get_task_pid(current, PIDTYPE_PID);
+ ctx->name = kasprintf(GFP_KERNEL, "%s[%d]/%x",
+ current->comm,
+ pid_nr(ctx->pid),
+ ctx->user_handle);
+ if (!ctx->name) {
+ ret = -ENOMEM;
+ goto err_pid;
+ }
+ }
- ctx->user_handle = ret;
/* NB: Mark all slices as needing a remap so that when the context first
* loads it will restore whatever remap state already exists. If there
* is no remap info, it will be a NOP. */
@@ -329,6 +339,9 @@ __create_hw_context(struct drm_device *dev,
return ctx;
+err_pid:
+ put_pid(ctx->pid);
+ idr_remove(&file_priv->context_idr, ctx->user_handle);
err_out:
context_close(ctx);
return ERR_PTR(ret);
@@ -352,9 +365,9 @@ i915_gem_create_context(struct drm_device *dev,
return ctx;
if (USES_FULL_PPGTT(dev)) {
- struct i915_hw_ppgtt *ppgtt =
- i915_ppgtt_create(to_i915(dev), file_priv);
+ struct i915_hw_ppgtt *ppgtt;
+ ppgtt = i915_ppgtt_create(to_i915(dev), file_priv, ctx->name);
if (IS_ERR(ppgtt)) {
DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
PTR_ERR(ppgtt));
@@ -463,6 +476,7 @@ int i915_gem_context_init(struct drm_device *dev)
return PTR_ERR(ctx);
}
+ ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
dev_priv->kernel_context = ctx;
DRM_DEBUG_DRIVER("%s context support initialized\n",
@@ -474,10 +488,11 @@ int i915_gem_context_init(struct drm_device *dev)
void i915_gem_context_lost(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
lockdep_assert_held(&dev_priv->drm.struct_mutex);
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
if (engine->last_context) {
i915_gem_context_unpin(engine->last_context, engine);
engine->last_context = NULL;
@@ -492,13 +507,13 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
if (!i915_gem_context_is_default(ctx))
continue;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
ctx->engine[engine->id].initialised = false;
ctx->remap_slice = ALL_L3_SLICES(dev_priv);
}
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
struct intel_context *kce =
&dev_priv->kernel_context->engine[engine->id];
@@ -563,6 +578,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
struct drm_i915_private *dev_priv = req->i915;
struct intel_ring *ring = req->ring;
struct intel_engine_cs *engine = req->engine;
+ enum intel_engine_id id;
u32 flags = hw_flags | MI_MM_SPACE_GTT;
const int num_rings =
/* Use an extended w/a on ivb+ if signalling from other rings */
@@ -605,7 +621,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
intel_ring_emit(ring,
MI_LOAD_REGISTER_IMM(num_rings));
- for_each_engine(signaller, dev_priv) {
+ for_each_engine(signaller, dev_priv, id) {
if (signaller == engine)
continue;
@@ -634,7 +650,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
intel_ring_emit(ring,
MI_LOAD_REGISTER_IMM(num_rings));
- for_each_engine(signaller, dev_priv) {
+ for_each_engine(signaller, dev_priv, id) {
if (signaller == engine)
continue;
@@ -749,12 +765,36 @@ needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
return false;
}
+struct i915_vma *
+i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
+ unsigned int flags)
+{
+ struct i915_vma *vma = ctx->engine[RCS].state;
+ int ret;
+
+ /* Clear this page out of any CPU caches for coherent swap-in/out.
+ * We only want to do this on the first bind so that we do not stall
+ * on an active context (which by nature is already on the GPU).
+ */
+ if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
+ ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ ret = i915_vma_pin(vma, 0, ctx->ggtt_alignment, PIN_GLOBAL | flags);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return vma;
+}
+
static int do_rcs_switch(struct drm_i915_gem_request *req)
{
struct i915_gem_context *to = req->ctx;
struct intel_engine_cs *engine = req->engine;
struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
- struct i915_vma *vma = to->engine[RCS].state;
+ struct i915_vma *vma;
struct i915_gem_context *from;
u32 hw_flags;
int ret, i;
@@ -762,17 +802,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
if (skip_rcs_switch(ppgtt, engine, to))
return 0;
- /* Clear this page out of any CPU caches for coherent swap-in/out. */
- if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
- ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
- if (ret)
- return ret;
- }
-
/* Trying to pin first makes error handling easier. */
- ret = i915_vma_pin(vma, 0, to->ggtt_alignment, PIN_GLOBAL);
- if (ret)
- return ret;
+ vma = i915_gem_context_pin_legacy(to, 0);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
/*
* Pin can switch back to the default context if we end up calling into
@@ -929,21 +962,33 @@ int i915_switch_context(struct drm_i915_gem_request *req)
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ struct i915_gem_timeline *timeline;
+ enum intel_engine_id id;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
struct drm_i915_gem_request *req;
int ret;
- if (engine->last_context == NULL)
- continue;
-
- if (engine->last_context == dev_priv->kernel_context)
- continue;
-
req = i915_gem_request_alloc(engine, dev_priv->kernel_context);
if (IS_ERR(req))
return PTR_ERR(req);
+ /* Queue this switch after all other activity */
+ list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
+ struct drm_i915_gem_request *prev;
+ struct intel_timeline *tl;
+
+ tl = &timeline->engine[engine->id];
+ prev = i915_gem_active_raw(&tl->last_request,
+ &dev_priv->drm.struct_mutex);
+ if (prev)
+ i915_sw_fence_await_sw_fence_gfp(&req->submit,
+ &prev->submit,
+ GFP_KERNEL);
+ }
+
ret = i915_switch_context(req);
i915_add_request_no_flush(req);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 97c9d68b45df..5e38299b5df6 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -44,51 +44,42 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
struct scatterlist *src, *dst;
int ret, i;
- ret = i915_mutex_lock_interruptible(obj->base.dev);
+ ret = i915_gem_object_pin_pages(obj);
if (ret)
goto err;
- ret = i915_gem_object_get_pages(obj);
- if (ret)
- goto err_unlock;
-
- i915_gem_object_pin_pages(obj);
-
/* Copy sg so that we make an independent mapping */
st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
if (st == NULL) {
ret = -ENOMEM;
- goto err_unpin;
+ goto err_unpin_pages;
}
- ret = sg_alloc_table(st, obj->pages->nents, GFP_KERNEL);
+ ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL);
if (ret)
goto err_free;
- src = obj->pages->sgl;
+ src = obj->mm.pages->sgl;
dst = st->sgl;
- for (i = 0; i < obj->pages->nents; i++) {
+ for (i = 0; i < obj->mm.pages->nents; i++) {
sg_set_page(dst, sg_page(src), src->length, 0);
dst = sg_next(dst);
src = sg_next(src);
}
if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
- ret =-ENOMEM;
+ ret = -ENOMEM;
goto err_free_sg;
}
- mutex_unlock(&obj->base.dev->struct_mutex);
return st;
err_free_sg:
sg_free_table(st);
err_free:
kfree(st);
-err_unpin:
+err_unpin_pages:
i915_gem_object_unpin_pages(obj);
-err_unlock:
- mutex_unlock(&obj->base.dev->struct_mutex);
err:
return ERR_PTR(ret);
}
@@ -103,36 +94,21 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
sg_free_table(sg);
kfree(sg);
- mutex_lock(&obj->base.dev->struct_mutex);
i915_gem_object_unpin_pages(obj);
- mutex_unlock(&obj->base.dev->struct_mutex);
}
static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
- struct drm_device *dev = obj->base.dev;
- void *addr;
- int ret;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ERR_PTR(ret);
-
- addr = i915_gem_object_pin_map(obj, I915_MAP_WB);
- mutex_unlock(&dev->struct_mutex);
-
- return addr;
+ return i915_gem_object_pin_map(obj, I915_MAP_WB);
}
static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
- struct drm_device *dev = obj->base.dev;
- mutex_lock(&dev->struct_mutex);
i915_gem_object_unpin_map(obj);
- mutex_unlock(&dev->struct_mutex);
}
static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
@@ -179,32 +155,45 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
struct drm_device *dev = obj->base.dev;
- int ret;
bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
+ int err;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
+ err = i915_gem_object_pin_pages(obj);
+ if (err)
+ return err;
+
+ err = i915_mutex_lock_interruptible(dev);
+ if (err)
+ goto out;
- ret = i915_gem_object_set_to_cpu_domain(obj, write);
+ err = i915_gem_object_set_to_cpu_domain(obj, write);
mutex_unlock(&dev->struct_mutex);
- return ret;
+
+out:
+ i915_gem_object_unpin_pages(obj);
+ return err;
}
static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
struct drm_device *dev = obj->base.dev;
- int ret;
+ int err;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
+ err = i915_gem_object_pin_pages(obj);
+ if (err)
+ return err;
- ret = i915_gem_object_set_to_gtt_domain(obj, false);
+ err = i915_mutex_lock_interruptible(dev);
+ if (err)
+ goto out;
+
+ err = i915_gem_object_set_to_gtt_domain(obj, false);
mutex_unlock(&dev->struct_mutex);
- return ret;
+out:
+ i915_gem_object_unpin_pages(obj);
+ return err;
}
static const struct dma_buf_ops i915_dmabuf_ops = {
@@ -222,60 +211,17 @@ static const struct dma_buf_ops i915_dmabuf_ops = {
.end_cpu_access = i915_gem_end_cpu_access,
};
-static void export_fences(struct drm_i915_gem_object *obj,
- struct dma_buf *dma_buf)
-{
- struct reservation_object *resv = dma_buf->resv;
- struct drm_i915_gem_request *req;
- unsigned long active;
- int idx;
-
- active = __I915_BO_ACTIVE(obj);
- if (!active)
- return;
-
- /* Serialise with execbuf to prevent concurrent fence-loops */
- mutex_lock(&obj->base.dev->struct_mutex);
-
- /* Mark the object for future fences before racily adding old fences */
- obj->base.dma_buf = dma_buf;
-
- ww_mutex_lock(&resv->lock, NULL);
-
- for_each_active(active, idx) {
- req = i915_gem_active_get(&obj->last_read[idx],
- &obj->base.dev->struct_mutex);
- if (!req)
- continue;
-
- if (reservation_object_reserve_shared(resv) == 0)
- reservation_object_add_shared_fence(resv, &req->fence);
-
- i915_gem_request_put(req);
- }
-
- req = i915_gem_active_get(&obj->last_write,
- &obj->base.dev->struct_mutex);
- if (req) {
- reservation_object_add_excl_fence(resv, &req->fence);
- i915_gem_request_put(req);
- }
-
- ww_mutex_unlock(&resv->lock);
- mutex_unlock(&obj->base.dev->struct_mutex);
-}
-
struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags)
{
struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
- struct dma_buf *dma_buf;
exp_info.ops = &i915_dmabuf_ops;
exp_info.size = gem_obj->size;
exp_info.flags = flags;
exp_info.priv = gem_obj;
+ exp_info.resv = obj->resv;
if (obj->ops->dmabuf_export) {
int ret = obj->ops->dmabuf_export(obj);
@@ -283,30 +229,21 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
return ERR_PTR(ret);
}
- dma_buf = drm_gem_dmabuf_export(dev, &exp_info);
- if (IS_ERR(dma_buf))
- return dma_buf;
-
- export_fences(obj, dma_buf);
- return dma_buf;
+ return drm_gem_dmabuf_export(dev, &exp_info);
}
-static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
+static struct sg_table *
+i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
{
- struct sg_table *sg;
-
- sg = dma_buf_map_attachment(obj->base.import_attach, DMA_BIDIRECTIONAL);
- if (IS_ERR(sg))
- return PTR_ERR(sg);
-
- obj->pages = sg;
- return 0;
+ return dma_buf_map_attachment(obj->base.import_attach,
+ DMA_BIDIRECTIONAL);
}
-static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj)
+static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
- dma_buf_unmap_attachment(obj->base.import_attach,
- obj->pages, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_attachment(obj->base.import_attach, pages,
+ DMA_BIDIRECTIONAL);
}
static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
@@ -350,6 +287,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops);
obj->base.import_attach = attach;
+ obj->resv = dma_buf->resv;
/* We use GTT as shorthand for a coherent domain, one that is
* neither in the GPU cache nor in the CPU cache, where all
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 5b6f81c1dbca..bd08814b015c 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -33,13 +33,17 @@
#include "intel_drv.h"
#include "i915_trace.h"
-static bool
-gpu_is_idle(struct drm_i915_private *dev_priv)
+static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
{
+ struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ for_each_engine(engine, dev_priv, id) {
+ struct intel_timeline *tl;
- for_each_engine(engine, dev_priv) {
- if (intel_engine_is_active(engine))
+ tl = &ggtt->base.timeline.engine[engine->id];
+ if (i915_gem_active_isset(&tl->last_request))
return false;
}
@@ -55,7 +59,7 @@ mark_free(struct i915_vma *vma, unsigned int flags, struct list_head *unwind)
if (WARN_ON(!list_empty(&vma->exec_list)))
return false;
- if (flags & PIN_NONFAULT && vma->obj->fault_mappable)
+ if (flags & PIN_NONFAULT && !list_empty(&vma->obj->userfault_link))
return false;
list_add(&vma->exec_list, unwind);
@@ -102,6 +106,7 @@ i915_gem_evict_something(struct i915_address_space *vm,
struct i915_vma *vma, *next;
int ret;
+ lockdep_assert_held(&vm->dev->struct_mutex);
trace_i915_gem_evict(vm, min_size, alignment, flags);
/*
@@ -152,7 +157,7 @@ search_again:
if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
return -ENOSPC;
- if (gpu_is_idle(dev_priv)) {
+ if (ggtt_is_idle(dev_priv)) {
/* If we still have pending pageflip completions, drop
* back to userspace to give our workqueues time to
* acquire our locks and unpin the old scanouts.
@@ -212,6 +217,8 @@ i915_gem_evict_for_vma(struct i915_vma *target)
{
struct drm_mm_node *node, *next;
+ lockdep_assert_held(&target->vm->dev->struct_mutex);
+
list_for_each_entry_safe(node, next,
&target->vm->mm.head_node.node_list,
node_list) {
@@ -265,7 +272,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
struct i915_vma *vma, *next;
int ret;
- WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex));
+ lockdep_assert_held(&vm->dev->struct_mutex);
trace_i915_gem_evict_vm(vm);
if (do_idle) {
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a218c2e395e7..097d9d8c2315 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -34,7 +34,6 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
#include "i915_trace.h"
#include "intel_drv.h"
#include "intel_frontbuffer.h"
@@ -288,7 +287,7 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
if (DBG_USE_CPU_RELOC)
return DBG_USE_CPU_RELOC > 0;
- return (HAS_LLC(obj->base.dev) ||
+ return (HAS_LLC(to_i915(obj->base.dev)) ||
obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
obj->cache_level != I915_CACHE_NONE);
}
@@ -332,7 +331,8 @@ static void reloc_cache_init(struct reloc_cache *cache,
cache->page = -1;
cache->vaddr = 0;
cache->i915 = i915;
- cache->use_64bit_reloc = INTEL_GEN(cache->i915) >= 8;
+ /* Must be a variable in the struct to allow GCC to unroll. */
+ cache->use_64bit_reloc = HAS_64BIT_RELOC(i915);
cache->node.allocated = false;
}
@@ -370,8 +370,7 @@ static void reloc_cache_fini(struct reloc_cache *cache)
ggtt->base.clear_range(&ggtt->base,
cache->node.start,
- cache->node.size,
- true);
+ cache->node.size);
drm_mm_remove_node(&cache->node);
} else {
i915_vma_unpin((struct i915_vma *)cache->node.mm);
@@ -419,17 +418,8 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
unsigned long offset;
void *vaddr;
- if (cache->node.allocated) {
- wmb();
- ggtt->base.insert_page(&ggtt->base,
- i915_gem_object_get_dma_address(obj, page),
- cache->node.start, I915_CACHE_NONE, 0);
- cache->page = page;
- return unmask_page(cache->vaddr);
- }
-
if (cache->vaddr) {
- io_mapping_unmap_atomic(unmask_page(cache->vaddr));
+ io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr));
} else {
struct i915_vma *vma;
int ret;
@@ -467,6 +457,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
offset = cache->node.start;
if (cache->node.allocated) {
+ wmb();
ggtt->base.insert_page(&ggtt->base,
i915_gem_object_get_dma_address(obj, page),
offset, I915_CACHE_NONE, 0);
@@ -474,7 +465,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
offset += page << PAGE_SHIFT;
}
- vaddr = io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset);
+ vaddr = (void __force *) io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset);
cache->page = page;
cache->vaddr = (unsigned long)vaddr;
@@ -552,27 +543,13 @@ repeat:
return 0;
}
-static bool object_is_idle(struct drm_i915_gem_object *obj)
-{
- unsigned long active = i915_gem_object_get_active(obj);
- int idx;
-
- for_each_active(active, idx) {
- if (!i915_gem_active_is_idle(&obj->last_read[idx],
- &obj->base.dev->struct_mutex))
- return false;
- }
-
- return true;
-}
-
static int
i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
struct eb_vmas *eb,
struct drm_i915_gem_relocation_entry *reloc,
struct reloc_cache *cache)
{
- struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct drm_gem_object *target_obj;
struct drm_i915_gem_object *target_i915_obj;
struct i915_vma *target_vma;
@@ -591,7 +568,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
* pipe_control writes because the gpu doesn't properly redirect them
* through the ppgtt for non_secure batchbuffers. */
- if (unlikely(IS_GEN6(dev) &&
+ if (unlikely(IS_GEN6(dev_priv) &&
reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) {
ret = i915_vma_bind(target_vma, target_i915_obj->cache_level,
PIN_GLOBAL);
@@ -649,10 +626,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
return -EINVAL;
}
- /* We can't wait for rendering with pagefaults disabled */
- if (pagefault_disabled() && !object_is_idle(obj))
- return -EFAULT;
-
ret = relocate_entry(obj, reloc, cache, target_offset);
if (ret)
return ret;
@@ -679,12 +652,23 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
remain = entry->relocation_count;
while (remain) {
struct drm_i915_gem_relocation_entry *r = stack_reloc;
- int count = remain;
- if (count > ARRAY_SIZE(stack_reloc))
- count = ARRAY_SIZE(stack_reloc);
+ unsigned long unwritten;
+ unsigned int count;
+
+ count = min_t(unsigned int, remain, ARRAY_SIZE(stack_reloc));
remain -= count;
- if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]))) {
+ /* This is the fast path and we cannot handle a pagefault
+ * whilst holding the struct mutex lest the user pass in the
+ * relocations contained within a mmaped bo. For in such a case
+ * we, the page fault handler would call i915_gem_fault() and
+ * we would try to acquire the struct mutex again. Obviously
+ * this is bad and so lockdep complains vehemently.
+ */
+ pagefault_disable();
+ unwritten = __copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]));
+ pagefault_enable();
+ if (unlikely(unwritten)) {
ret = -EFAULT;
goto out;
}
@@ -696,11 +680,26 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
if (ret)
goto out;
- if (r->presumed_offset != offset &&
- __put_user(r->presumed_offset,
- &user_relocs->presumed_offset)) {
- ret = -EFAULT;
- goto out;
+ if (r->presumed_offset != offset) {
+ pagefault_disable();
+ unwritten = __put_user(r->presumed_offset,
+ &user_relocs->presumed_offset);
+ pagefault_enable();
+ if (unlikely(unwritten)) {
+ /* Note that reporting an error now
+ * leaves everything in an inconsistent
+ * state as we have *already* changed
+ * the relocation value inside the
+ * object. As we have not changed the
+ * reloc.presumed_offset or will not
+ * change the execobject.offset, on the
+ * call we may not rewrite the value
+ * inside the object, leaving it
+ * dangling and causing a GPU hang.
+ */
+ ret = -EFAULT;
+ goto out;
+ }
}
user_relocs++;
@@ -740,20 +739,11 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb)
struct i915_vma *vma;
int ret = 0;
- /* This is the fast path and we cannot handle a pagefault whilst
- * holding the struct mutex lest the user pass in the relocations
- * contained within a mmaped bo. For in such a case we, the page
- * fault handler would call i915_gem_fault() and we would try to
- * acquire the struct mutex again. Obviously this is bad and so
- * lockdep complains vehemently.
- */
- pagefault_disable();
list_for_each_entry(vma, &eb->vmas, exec_list) {
ret = i915_gem_execbuffer_relocate_vma(vma, eb);
if (ret)
break;
}
- pagefault_enable();
return ret;
}
@@ -843,7 +833,7 @@ need_reloc_mappable(struct i915_vma *vma)
return false;
/* See also use_cpu_reloc() */
- if (HAS_LLC(vma->obj->base.dev))
+ if (HAS_LLC(to_i915(vma->obj->base.dev)))
return false;
if (vma->obj->base.write_domain == I915_GEM_DOMAIN_CPU)
@@ -1111,44 +1101,20 @@ err:
return ret;
}
-static unsigned int eb_other_engines(struct drm_i915_gem_request *req)
-{
- unsigned int mask;
-
- mask = ~intel_engine_flag(req->engine) & I915_BO_ACTIVE_MASK;
- mask <<= I915_BO_ACTIVE_SHIFT;
-
- return mask;
-}
-
static int
i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
struct list_head *vmas)
{
- const unsigned int other_rings = eb_other_engines(req);
struct i915_vma *vma;
int ret;
list_for_each_entry(vma, vmas, exec_list) {
struct drm_i915_gem_object *obj = vma->obj;
- struct reservation_object *resv;
- if (obj->flags & other_rings) {
- ret = i915_gem_request_await_object
- (req, obj, obj->base.pending_write_domain);
- if (ret)
- return ret;
- }
-
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (resv) {
- ret = i915_sw_fence_await_reservation
- (&req->submit, resv, &i915_fence_ops,
- obj->base.pending_write_domain, 10*HZ,
- GFP_KERNEL | __GFP_NOWARN);
- if (ret < 0)
- return ret;
- }
+ ret = i915_gem_request_await_object
+ (req, obj, obj->base.pending_write_domain);
+ if (ret)
+ return ret;
if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
i915_gem_clflush_object(obj, false);
@@ -1296,8 +1262,6 @@ void i915_vma_move_to_active(struct i915_vma *vma,
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
- obj->dirty = 1; /* be paranoid */
-
/* Add a reference if we're newly entering the active list.
* The order in which we add operations to the retirement queue is
* vital here: mark_active adds to the start of the callback list,
@@ -1305,15 +1269,15 @@ void i915_vma_move_to_active(struct i915_vma *vma,
* add the active reference first and queue for it to be dropped
* *last*.
*/
- if (!i915_gem_object_is_active(obj))
- i915_gem_object_get(obj);
- i915_gem_object_set_active(obj, idx);
- i915_gem_active_set(&obj->last_read[idx], req);
+ if (!i915_vma_is_active(vma))
+ obj->active_count++;
+ i915_vma_set_active(vma, idx);
+ i915_gem_active_set(&vma->last_read[idx], req);
+ list_move_tail(&vma->vm_link, &vma->vm->active_list);
if (flags & EXEC_OBJECT_WRITE) {
- i915_gem_active_set(&obj->last_write, req);
-
- intel_fb_obj_invalidate(obj, ORIGIN_CS);
+ if (intel_fb_obj_invalidate(obj, ORIGIN_CS))
+ i915_gem_active_set(&obj->frontbuffer_write, req);
/* update for the implicit flush after a batch */
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
@@ -1323,21 +1287,13 @@ void i915_vma_move_to_active(struct i915_vma *vma,
if (flags & EXEC_OBJECT_NEEDS_FENCE)
i915_gem_active_set(&vma->last_fence, req);
-
- i915_vma_set_active(vma, idx);
- i915_gem_active_set(&vma->last_read[idx], req);
- list_move_tail(&vma->vm_link, &vma->vm->active_list);
}
static void eb_export_fence(struct drm_i915_gem_object *obj,
struct drm_i915_gem_request *req,
unsigned int flags)
{
- struct reservation_object *resv;
-
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (!resv)
- return;
+ struct reservation_object *resv = obj->resv;
/* Ignore errors from failing to allocate the new fence, we can't
* handle an error right now. Worst case should be missed
@@ -1607,12 +1563,12 @@ eb_select_engine(struct drm_i915_private *dev_priv,
return NULL;
}
- engine = &dev_priv->engine[_VCS(bsd_idx)];
+ engine = dev_priv->engine[_VCS(bsd_idx)];
} else {
- engine = &dev_priv->engine[user_ring_map[user_ring_id]];
+ engine = dev_priv->engine[user_ring_map[user_ring_id]];
}
- if (!intel_engine_initialized(engine)) {
+ if (!engine) {
DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id);
return NULL;
}
@@ -1667,7 +1623,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
}
if (args->flags & I915_EXEC_RESOURCE_STREAMER) {
- if (!HAS_RESOURCE_STREAMER(dev)) {
+ if (!HAS_RESOURCE_STREAMER(dev_priv)) {
DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
return -EINVAL;
}
@@ -1921,7 +1877,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
exec2_list[i].alignment = exec_list[i].alignment;
exec2_list[i].offset = exec_list[i].offset;
- if (INTEL_INFO(dev)->gen < 4)
+ if (INTEL_GEN(to_i915(dev)) < 4)
exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
else
exec2_list[i].flags = 0;
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index 2c7ba0ee127c..0efa3571afc3 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -343,6 +343,9 @@ i915_vma_get_fence(struct i915_vma *vma)
struct drm_i915_fence_reg *fence;
struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
+ /* Note that we revoke fences on runtime suspend. Therefore the user
+ * must keep the device awake whilst using the fence.
+ */
assert_rpm_wakelock_held(to_i915(vma->vm->dev));
/* Just update our place in the LRU if our fence is getting reused. */
@@ -365,22 +368,16 @@ i915_vma_get_fence(struct i915_vma *vma)
/**
* i915_gem_restore_fences - restore fence state
- * @dev: DRM device
+ * @dev_priv: i915 device private
*
* Restore the hw fence state to match the software tracking again, to be called
- * after a gpu reset and on resume.
+ * after a gpu reset and on resume. Note that on runtime suspend we only cancel
+ * the fences, to be reacquired by the user later.
*/
-void i915_gem_restore_fences(struct drm_device *dev)
+void i915_gem_restore_fences(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
int i;
- /* Note that this may be called outside of struct_mutex, by
- * runtime suspend/resume. The barrier we require is enforced by
- * rpm itself - all access to fences/GTT are only within an rpm
- * wakeref, and to acquire that wakeref you must pass through here.
- */
-
for (i = 0; i < dev_priv->num_fence_regs; i++) {
struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
struct i915_vma *vma = reg->vma;
@@ -391,7 +388,7 @@ void i915_gem_restore_fences(struct drm_device *dev)
*/
if (vma && !i915_gem_object_is_tiled(vma->obj)) {
GEM_BUG_ON(!reg->dirty);
- GEM_BUG_ON(vma->obj->fault_mappable);
+ GEM_BUG_ON(!list_empty(&vma->obj->userfault_link));
list_move(&reg->link, &dev_priv->mm.fence_list);
vma->fence = NULL;
@@ -453,19 +450,18 @@ void i915_gem_restore_fences(struct drm_device *dev)
/**
* i915_gem_detect_bit_6_swizzle - detect bit 6 swizzling pattern
- * @dev: DRM device
+ * @dev_priv: i915 device private
*
* Detects bit 6 swizzling of address lookup between IGD access and CPU
* access through main memory.
*/
void
-i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
+i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) {
+ if (INTEL_GEN(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) {
/*
* On BDW+, swizzling is not used. We leave the CPU memory
* controller in charge of optimizing memory accesses without
@@ -475,7 +471,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
*/
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
- } else if (INTEL_INFO(dev)->gen >= 6) {
+ } else if (INTEL_GEN(dev_priv) >= 6) {
if (dev_priv->preserve_bios_swizzle) {
if (I915_READ(DISP_ARB_CTL) &
DISP_TILE_SURFACE_SWIZZLING) {
@@ -504,19 +500,20 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
}
}
- } else if (IS_GEN5(dev)) {
+ } else if (IS_GEN5(dev_priv)) {
/* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup.
*/
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
- } else if (IS_GEN2(dev)) {
+ } else if (IS_GEN2(dev_priv)) {
/* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
*/
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
- } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) {
+ } else if (IS_MOBILE(dev_priv) || (IS_GEN3(dev_priv) &&
+ !IS_G33(dev_priv))) {
uint32_t dcc;
/* On 9xx chipsets, channel interleave by the CPU is
@@ -554,7 +551,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
/* check for L-shaped memory aka modified enhanced addressing */
- if (IS_GEN4(dev) &&
+ if (IS_GEN4(dev_priv) &&
!(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
@@ -645,6 +642,7 @@ i915_gem_swizzle_page(struct page *page)
/**
* i915_gem_object_do_bit_17_swizzle - fixup bit 17 swizzling
* @obj: i915 GEM buffer object
+ * @pages: the scattergather list of physical pages
*
* This function fixes up the swizzling in case any page frame number for this
* object has changed in bit 17 since that state has been saved with
@@ -655,7 +653,8 @@ i915_gem_swizzle_page(struct page *page)
* by swapping them out and back in again).
*/
void
-i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
+i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
struct sgt_iter sgt_iter;
struct page *page;
@@ -665,10 +664,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
return;
i = 0;
- for_each_sgt_page(page, sgt_iter, obj->pages) {
+ for_each_sgt_page(page, sgt_iter, pages) {
char new_bit_17 = page_to_phys(page) >> 17;
- if ((new_bit_17 & 0x1) !=
- (test_bit(i, obj->bit_17) != 0)) {
+ if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) {
i915_gem_swizzle_page(page);
set_page_dirty(page);
}
@@ -679,17 +677,19 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
/**
* i915_gem_object_save_bit_17_swizzle - save bit 17 swizzling
* @obj: i915 GEM buffer object
+ * @pages: the scattergather list of physical pages
*
* This function saves the bit 17 of each page frame number so that swizzling
* can be fixed up later on with i915_gem_object_do_bit_17_swizzle(). This must
* be called before the backing storage can be unpinned.
*/
void
-i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
+i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
+ const unsigned int page_count = obj->base.size >> PAGE_SHIFT;
struct sgt_iter sgt_iter;
struct page *page;
- int page_count = obj->base.size >> PAGE_SHIFT;
int i;
if (obj->bit_17 == NULL) {
@@ -704,7 +704,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
i = 0;
- for_each_sgt_page(page, sgt_iter, obj->pages) {
+ for_each_sgt_page(page, sgt_iter, pages) {
if (page_to_phys(page) & (1 << 17))
__set_bit(i, obj->bit_17);
else
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.h b/drivers/gpu/drm/i915/i915_gem_fence_reg.h
new file mode 100644
index 000000000000..22c4a2d01adf
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2016 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 __I915_FENCE_REG_H__
+#define __I915_FENCE_REG_H__
+
+#include <linux/list.h>
+
+struct drm_i915_private;
+struct i915_vma;
+
+struct drm_i915_fence_reg {
+ struct list_head link;
+ struct drm_i915_private *i915;
+ struct i915_vma *vma;
+ int pin_count;
+ int id;
+ /**
+ * Whether the tiling parameters for the currently
+ * associated fence register have changed. Note that
+ * for the purposes of tracking tiling changes we also
+ * treat the unfenced register, the register slot that
+ * the object occupies whilst it executes a fenced
+ * command (such as BLT on gen2/3), as a "fence".
+ */
+ bool dirty;
+};
+
+#endif
+
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 0bb4232f66bc..b4bde1452f2a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -31,6 +31,7 @@
#include "i915_vgpu.h"
#include "i915_trace.h"
#include "intel_drv.h"
+#include "intel_frontbuffer.h"
#define I915_GFP_DMA (GFP_KERNEL | __GFP_HIGHMEM)
@@ -95,13 +96,6 @@
*
*/
-static inline struct i915_ggtt *
-i915_vm_to_ggtt(struct i915_address_space *vm)
-{
- GEM_BUG_ON(!i915_is_ggtt(vm));
- return container_of(vm, struct i915_ggtt, base);
-}
-
static int
i915_get_ggtt_vma_pages(struct i915_vma *vma);
@@ -175,7 +169,7 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
{
u32 pte_flags = 0;
- vma->pages = vma->obj->pages;
+ vma->pages = vma->obj->mm.pages;
/* Currently applicable only to VLV */
if (vma->obj->gt_ro)
@@ -191,15 +185,13 @@ static void ppgtt_unbind_vma(struct i915_vma *vma)
{
vma->vm->clear_range(vma->vm,
vma->node.start,
- vma->size,
- true);
+ vma->size);
}
static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
- bool valid)
+ enum i915_cache_level level)
{
- gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0;
+ gen8_pte_t pte = _PAGE_PRESENT | _PAGE_RW;
pte |= addr;
switch (level) {
@@ -234,9 +226,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
static gen6_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 unused)
+ u32 unused)
{
- gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+ gen6_pte_t pte = GEN6_PTE_VALID;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) {
@@ -256,9 +248,9 @@ static gen6_pte_t snb_pte_encode(dma_addr_t addr,
static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 unused)
+ u32 unused)
{
- gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+ gen6_pte_t pte = GEN6_PTE_VALID;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) {
@@ -280,9 +272,9 @@ static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
static gen6_pte_t byt_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 flags)
+ u32 flags)
{
- gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+ gen6_pte_t pte = GEN6_PTE_VALID;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
if (!(flags & PTE_READ_ONLY))
@@ -296,9 +288,9 @@ static gen6_pte_t byt_pte_encode(dma_addr_t addr,
static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 unused)
+ u32 unused)
{
- gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+ gen6_pte_t pte = GEN6_PTE_VALID;
pte |= HSW_PTE_ADDR_ENCODE(addr);
if (level != I915_CACHE_NONE)
@@ -309,9 +301,9 @@ static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
static gen6_pte_t iris_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 unused)
+ u32 unused)
{
- gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+ gen6_pte_t pte = GEN6_PTE_VALID;
pte |= HSW_PTE_ADDR_ENCODE(addr);
switch (level) {
@@ -328,10 +320,10 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr,
return pte;
}
-static int __setup_page_dma(struct drm_device *dev,
+static int __setup_page_dma(struct drm_i915_private *dev_priv,
struct i915_page_dma *p, gfp_t flags)
{
- struct device *kdev = &dev->pdev->dev;
+ struct device *kdev = &dev_priv->drm.pdev->dev;
p->page = alloc_page(flags);
if (!p->page)
@@ -348,14 +340,16 @@ static int __setup_page_dma(struct drm_device *dev,
return 0;
}
-static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
+static int setup_page_dma(struct drm_i915_private *dev_priv,
+ struct i915_page_dma *p)
{
- return __setup_page_dma(dev, p, I915_GFP_DMA);
+ return __setup_page_dma(dev_priv, p, I915_GFP_DMA);
}
-static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
+static void cleanup_page_dma(struct drm_i915_private *dev_priv,
+ struct i915_page_dma *p)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
if (WARN_ON(!p->page))
return;
@@ -373,27 +367,29 @@ static void *kmap_page_dma(struct i915_page_dma *p)
/* We use the flushing unmap only with ppgtt structures:
* page directories, page tables and scratch pages.
*/
-static void kunmap_page_dma(struct drm_device *dev, void *vaddr)
+static void kunmap_page_dma(struct drm_i915_private *dev_priv, void *vaddr)
{
/* There are only few exceptions for gen >=6. chv and bxt.
* And we are not sure about the latter so play safe for now.
*/
- if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
+ if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
drm_clflush_virt_range(vaddr, PAGE_SIZE);
kunmap_atomic(vaddr);
}
#define kmap_px(px) kmap_page_dma(px_base(px))
-#define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr))
+#define kunmap_px(ppgtt, vaddr) \
+ kunmap_page_dma(to_i915((ppgtt)->base.dev), (vaddr))
-#define setup_px(dev, px) setup_page_dma((dev), px_base(px))
-#define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px))
-#define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v))
-#define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v))
+#define setup_px(dev_priv, px) setup_page_dma((dev_priv), px_base(px))
+#define cleanup_px(dev_priv, px) cleanup_page_dma((dev_priv), px_base(px))
+#define fill_px(dev_priv, px, v) fill_page_dma((dev_priv), px_base(px), (v))
+#define fill32_px(dev_priv, px, v) \
+ fill_page_dma_32((dev_priv), px_base(px), (v))
-static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p,
- const uint64_t val)
+static void fill_page_dma(struct drm_i915_private *dev_priv,
+ struct i915_page_dma *p, const uint64_t val)
{
int i;
uint64_t * const vaddr = kmap_page_dma(p);
@@ -401,38 +397,37 @@ static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p,
for (i = 0; i < 512; i++)
vaddr[i] = val;
- kunmap_page_dma(dev, vaddr);
+ kunmap_page_dma(dev_priv, vaddr);
}
-static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p,
- const uint32_t val32)
+static void fill_page_dma_32(struct drm_i915_private *dev_priv,
+ struct i915_page_dma *p, const uint32_t val32)
{
uint64_t v = val32;
v = v << 32 | val32;
- fill_page_dma(dev, p, v);
+ fill_page_dma(dev_priv, p, v);
}
static int
-setup_scratch_page(struct drm_device *dev,
+setup_scratch_page(struct drm_i915_private *dev_priv,
struct i915_page_dma *scratch,
gfp_t gfp)
{
- return __setup_page_dma(dev, scratch, gfp | __GFP_ZERO);
+ return __setup_page_dma(dev_priv, scratch, gfp | __GFP_ZERO);
}
-static void cleanup_scratch_page(struct drm_device *dev,
+static void cleanup_scratch_page(struct drm_i915_private *dev_priv,
struct i915_page_dma *scratch)
{
- cleanup_page_dma(dev, scratch);
+ cleanup_page_dma(dev_priv, scratch);
}
-static struct i915_page_table *alloc_pt(struct drm_device *dev)
+static struct i915_page_table *alloc_pt(struct drm_i915_private *dev_priv)
{
struct i915_page_table *pt;
- const size_t count = INTEL_INFO(dev)->gen >= 8 ?
- GEN8_PTES : GEN6_PTES;
+ const size_t count = INTEL_GEN(dev_priv) >= 8 ? GEN8_PTES : GEN6_PTES;
int ret = -ENOMEM;
pt = kzalloc(sizeof(*pt), GFP_KERNEL);
@@ -445,7 +440,7 @@ static struct i915_page_table *alloc_pt(struct drm_device *dev)
if (!pt->used_ptes)
goto fail_bitmap;
- ret = setup_px(dev, pt);
+ ret = setup_px(dev_priv, pt);
if (ret)
goto fail_page_m;
@@ -459,9 +454,10 @@ fail_bitmap:
return ERR_PTR(ret);
}
-static void free_pt(struct drm_device *dev, struct i915_page_table *pt)
+static void free_pt(struct drm_i915_private *dev_priv,
+ struct i915_page_table *pt)
{
- cleanup_px(dev, pt);
+ cleanup_px(dev_priv, pt);
kfree(pt->used_ptes);
kfree(pt);
}
@@ -472,9 +468,9 @@ static void gen8_initialize_pt(struct i915_address_space *vm,
gen8_pte_t scratch_pte;
scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, true);
+ I915_CACHE_LLC);
- fill_px(vm->dev, pt, scratch_pte);
+ fill_px(to_i915(vm->dev), pt, scratch_pte);
}
static void gen6_initialize_pt(struct i915_address_space *vm,
@@ -485,12 +481,12 @@ static void gen6_initialize_pt(struct i915_address_space *vm,
WARN_ON(vm->scratch_page.daddr == 0);
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, true, 0);
+ I915_CACHE_LLC, 0);
- fill32_px(vm->dev, pt, scratch_pte);
+ fill32_px(to_i915(vm->dev), pt, scratch_pte);
}
-static struct i915_page_directory *alloc_pd(struct drm_device *dev)
+static struct i915_page_directory *alloc_pd(struct drm_i915_private *dev_priv)
{
struct i915_page_directory *pd;
int ret = -ENOMEM;
@@ -504,7 +500,7 @@ static struct i915_page_directory *alloc_pd(struct drm_device *dev)
if (!pd->used_pdes)
goto fail_bitmap;
- ret = setup_px(dev, pd);
+ ret = setup_px(dev_priv, pd);
if (ret)
goto fail_page_m;
@@ -518,10 +514,11 @@ fail_bitmap:
return ERR_PTR(ret);
}
-static void free_pd(struct drm_device *dev, struct i915_page_directory *pd)
+static void free_pd(struct drm_i915_private *dev_priv,
+ struct i915_page_directory *pd)
{
if (px_page(pd)) {
- cleanup_px(dev, pd);
+ cleanup_px(dev_priv, pd);
kfree(pd->used_pdes);
kfree(pd);
}
@@ -534,13 +531,13 @@ static void gen8_initialize_pd(struct i915_address_space *vm,
scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC);
- fill_px(vm->dev, pd, scratch_pde);
+ fill_px(to_i915(vm->dev), pd, scratch_pde);
}
-static int __pdp_init(struct drm_device *dev,
+static int __pdp_init(struct drm_i915_private *dev_priv,
struct i915_page_directory_pointer *pdp)
{
- size_t pdpes = I915_PDPES_PER_PDP(dev);
+ size_t pdpes = I915_PDPES_PER_PDP(dev_priv);
pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes),
sizeof(unsigned long),
@@ -569,22 +566,22 @@ static void __pdp_fini(struct i915_page_directory_pointer *pdp)
}
static struct
-i915_page_directory_pointer *alloc_pdp(struct drm_device *dev)
+i915_page_directory_pointer *alloc_pdp(struct drm_i915_private *dev_priv)
{
struct i915_page_directory_pointer *pdp;
int ret = -ENOMEM;
- WARN_ON(!USES_FULL_48BIT_PPGTT(dev));
+ WARN_ON(!USES_FULL_48BIT_PPGTT(dev_priv));
pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
if (!pdp)
return ERR_PTR(-ENOMEM);
- ret = __pdp_init(dev, pdp);
+ ret = __pdp_init(dev_priv, pdp);
if (ret)
goto fail_bitmap;
- ret = setup_px(dev, pdp);
+ ret = setup_px(dev_priv, pdp);
if (ret)
goto fail_page_m;
@@ -598,12 +595,12 @@ fail_bitmap:
return ERR_PTR(ret);
}
-static void free_pdp(struct drm_device *dev,
+static void free_pdp(struct drm_i915_private *dev_priv,
struct i915_page_directory_pointer *pdp)
{
__pdp_fini(pdp);
- if (USES_FULL_48BIT_PPGTT(dev)) {
- cleanup_px(dev, pdp);
+ if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+ cleanup_px(dev_priv, pdp);
kfree(pdp);
}
}
@@ -615,7 +612,7 @@ static void gen8_initialize_pdp(struct i915_address_space *vm,
scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
- fill_px(vm->dev, pdp, scratch_pdpe);
+ fill_px(to_i915(vm->dev), pdp, scratch_pdpe);
}
static void gen8_initialize_pml4(struct i915_address_space *vm,
@@ -626,7 +623,7 @@ static void gen8_initialize_pml4(struct i915_address_space *vm,
scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
I915_CACHE_LLC);
- fill_px(vm->dev, pml4, scratch_pml4e);
+ fill_px(to_i915(vm->dev), pml4, scratch_pml4e);
}
static void
@@ -637,7 +634,7 @@ gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt,
{
gen8_ppgtt_pdpe_t *page_directorypo;
- if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+ if (!USES_FULL_48BIT_PPGTT(to_i915(ppgtt->base.dev)))
return;
page_directorypo = kmap_px(pdp);
@@ -653,7 +650,7 @@ gen8_setup_page_directory_pointer(struct i915_hw_ppgtt *ppgtt,
{
gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4);
- WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev));
+ WARN_ON(!USES_FULL_48BIT_PPGTT(to_i915(ppgtt->base.dev)));
pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC);
kunmap_px(ppgtt, pagemap);
}
@@ -706,85 +703,172 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt,
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)
+/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
+ * the page table structures, we mark them dirty so that
+ * context switching/execlist queuing code takes extra steps
+ * to ensure that tlbs are flushed.
+ */
+static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
+{
+ ppgtt->pd_dirty_rings = INTEL_INFO(to_i915(ppgtt->base.dev))->ring_mask;
+}
+
+/* Removes entries from a single page table, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries.
+ */
+static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm,
+ struct i915_page_table *pt,
+ uint64_t start,
+ uint64_t length)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+ unsigned int num_entries = gen8_pte_count(start, length);
+ unsigned int pte = gen8_pte_index(start);
+ unsigned int pte_end = pte + num_entries;
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;
+ gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
+ I915_CACHE_LLC);
- if (WARN_ON(!pdp))
- return;
+ if (WARN_ON(!px_page(pt)))
+ return false;
- while (num_entries) {
- struct i915_page_directory *pd;
- struct i915_page_table *pt;
+ GEM_BUG_ON(pte_end > GEN8_PTES);
- if (WARN_ON(!pdp->page_directory[pdpe]))
- break;
+ bitmap_clear(pt->used_ptes, pte, num_entries);
+
+ if (bitmap_empty(pt->used_ptes, GEN8_PTES)) {
+ free_pt(to_i915(vm->dev), pt);
+ return true;
+ }
- pd = pdp->page_directory[pdpe];
+ pt_vaddr = kmap_px(pt);
+ while (pte < pte_end)
+ pt_vaddr[pte++] = scratch_pte;
+
+ kunmap_px(ppgtt, pt_vaddr);
+
+ return false;
+}
+
+/* Removes entries from a single page dir, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries
+ */
+static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm,
+ struct i915_page_directory *pd,
+ uint64_t start,
+ uint64_t length)
+{
+ struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+ struct i915_page_table *pt;
+ uint64_t pde;
+ gen8_pde_t *pde_vaddr;
+ gen8_pde_t scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt),
+ I915_CACHE_LLC);
+
+ gen8_for_each_pde(pt, pd, start, length, pde) {
if (WARN_ON(!pd->page_table[pde]))
break;
- pt = pd->page_table[pde];
+ if (gen8_ppgtt_clear_pt(vm, pt, start, length)) {
+ __clear_bit(pde, pd->used_pdes);
+ pde_vaddr = kmap_px(pd);
+ pde_vaddr[pde] = scratch_pde;
+ kunmap_px(ppgtt, pde_vaddr);
+ }
+ }
- if (WARN_ON(!px_page(pt)))
- break;
+ if (bitmap_empty(pd->used_pdes, I915_PDES)) {
+ free_pd(to_i915(vm->dev), pd);
+ return true;
+ }
- last_pte = pte + num_entries;
- if (last_pte > GEN8_PTES)
- last_pte = GEN8_PTES;
+ return false;
+}
- pt_vaddr = kmap_px(pt);
+/* Removes entries from a single page dir pointer, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries
+ */
+static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
+ struct i915_page_directory_pointer *pdp,
+ uint64_t start,
+ uint64_t length)
+{
+ struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
+ struct i915_page_directory *pd;
+ uint64_t pdpe;
+ gen8_ppgtt_pdpe_t *pdpe_vaddr;
+ gen8_ppgtt_pdpe_t scratch_pdpe =
+ gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
- for (i = pte; i < last_pte; i++) {
- pt_vaddr[i] = scratch_pte;
- num_entries--;
+ gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
+ if (WARN_ON(!pdp->page_directory[pdpe]))
+ break;
+
+ if (gen8_ppgtt_clear_pd(vm, pd, start, length)) {
+ __clear_bit(pdpe, pdp->used_pdpes);
+ if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+ pdpe_vaddr = kmap_px(pdp);
+ pdpe_vaddr[pdpe] = scratch_pdpe;
+ kunmap_px(ppgtt, pdpe_vaddr);
+ }
}
+ }
- kunmap_px(ppgtt, pt_vaddr);
+ mark_tlbs_dirty(ppgtt);
- pte = 0;
- if (++pde == I915_PDES) {
- if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
- break;
- pde = 0;
- }
+ if (USES_FULL_48BIT_PPGTT(dev_priv) &&
+ bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(dev_priv))) {
+ free_pdp(dev_priv, pdp);
+ return true;
}
+
+ return false;
}
-static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
- uint64_t start,
- uint64_t length,
- bool use_scratch)
+/* Removes entries from a single pml4.
+ * This is the top-level structure in 4-level page tables used on gen8+.
+ * Empty entries are always scratch pml4e.
+ */
+static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm,
+ struct i915_pml4 *pml4,
+ uint64_t start,
+ uint64_t length)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, use_scratch);
+ struct i915_page_directory_pointer *pdp;
+ uint64_t pml4e;
+ gen8_ppgtt_pml4e_t *pml4e_vaddr;
+ gen8_ppgtt_pml4e_t scratch_pml4e =
+ gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC);
- if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
- gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
- scratch_pte);
- } else {
- uint64_t pml4e;
- struct i915_page_directory_pointer *pdp;
+ GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(to_i915(vm->dev)));
- gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
- gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
- scratch_pte);
+ gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
+ if (WARN_ON(!pml4->pdps[pml4e]))
+ break;
+
+ if (gen8_ppgtt_clear_pdp(vm, pdp, start, length)) {
+ __clear_bit(pml4e, pml4->used_pml4es);
+ pml4e_vaddr = kmap_px(pml4);
+ pml4e_vaddr[pml4e] = scratch_pml4e;
+ kunmap_px(ppgtt, pml4e_vaddr);
}
}
}
+static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
+ uint64_t start, uint64_t length)
+{
+ struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+
+ if (USES_FULL_48BIT_PPGTT(to_i915(vm->dev)))
+ gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length);
+ else
+ gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length);
+}
+
static void
gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
struct i915_page_directory_pointer *pdp,
@@ -809,12 +893,12 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
pt_vaddr[pte] =
gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
- cache_level, true);
+ cache_level);
if (++pte == GEN8_PTES) {
kunmap_px(ppgtt, pt_vaddr);
pt_vaddr = NULL;
if (++pde == I915_PDES) {
- if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
+ if (++pdpe == I915_PDPES_PER_PDP(to_i915(vm->dev)))
break;
pde = 0;
}
@@ -837,7 +921,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
- if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+ if (!USES_FULL_48BIT_PPGTT(to_i915(vm->dev))) {
gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start,
cache_level);
} else {
@@ -852,7 +936,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
}
}
-static void gen8_free_page_tables(struct drm_device *dev,
+static void gen8_free_page_tables(struct drm_i915_private *dev_priv,
struct i915_page_directory *pd)
{
int i;
@@ -864,34 +948,34 @@ static void gen8_free_page_tables(struct drm_device *dev,
if (WARN_ON(!pd->page_table[i]))
continue;
- free_pt(dev, pd->page_table[i]);
+ free_pt(dev_priv, pd->page_table[i]);
pd->page_table[i] = NULL;
}
}
static int gen8_init_scratch(struct i915_address_space *vm)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
int ret;
- ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
+ ret = setup_scratch_page(dev_priv, &vm->scratch_page, I915_GFP_DMA);
if (ret)
return ret;
- vm->scratch_pt = alloc_pt(dev);
+ vm->scratch_pt = alloc_pt(dev_priv);
if (IS_ERR(vm->scratch_pt)) {
ret = PTR_ERR(vm->scratch_pt);
goto free_scratch_page;
}
- vm->scratch_pd = alloc_pd(dev);
+ vm->scratch_pd = alloc_pd(dev_priv);
if (IS_ERR(vm->scratch_pd)) {
ret = PTR_ERR(vm->scratch_pd);
goto free_pt;
}
- if (USES_FULL_48BIT_PPGTT(dev)) {
- vm->scratch_pdp = alloc_pdp(dev);
+ if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+ vm->scratch_pdp = alloc_pdp(dev_priv);
if (IS_ERR(vm->scratch_pdp)) {
ret = PTR_ERR(vm->scratch_pdp);
goto free_pd;
@@ -900,17 +984,17 @@ static int gen8_init_scratch(struct i915_address_space *vm)
gen8_initialize_pt(vm, vm->scratch_pt);
gen8_initialize_pd(vm, vm->scratch_pd);
- if (USES_FULL_48BIT_PPGTT(dev))
+ if (USES_FULL_48BIT_PPGTT(dev_priv))
gen8_initialize_pdp(vm, vm->scratch_pdp);
return 0;
free_pd:
- free_pd(dev, vm->scratch_pd);
+ free_pd(dev_priv, vm->scratch_pd);
free_pt:
- free_pt(dev, vm->scratch_pt);
+ free_pt(dev_priv, vm->scratch_pt);
free_scratch_page:
- cleanup_scratch_page(dev, &vm->scratch_page);
+ cleanup_scratch_page(dev_priv, &vm->scratch_page);
return ret;
}
@@ -948,54 +1032,56 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
static void gen8_free_scratch(struct i915_address_space *vm)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(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);
- cleanup_scratch_page(dev, &vm->scratch_page);
+ if (USES_FULL_48BIT_PPGTT(dev_priv))
+ free_pdp(dev_priv, vm->scratch_pdp);
+ free_pd(dev_priv, vm->scratch_pd);
+ free_pt(dev_priv, vm->scratch_pt);
+ cleanup_scratch_page(dev_priv, &vm->scratch_page);
}
-static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev,
+static void gen8_ppgtt_cleanup_3lvl(struct drm_i915_private *dev_priv,
struct i915_page_directory_pointer *pdp)
{
int i;
- for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) {
+ for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev_priv)) {
if (WARN_ON(!pdp->page_directory[i]))
continue;
- gen8_free_page_tables(dev, pdp->page_directory[i]);
- free_pd(dev, pdp->page_directory[i]);
+ gen8_free_page_tables(dev_priv, pdp->page_directory[i]);
+ free_pd(dev_priv, pdp->page_directory[i]);
}
- free_pdp(dev, pdp);
+ free_pdp(dev_priv, pdp);
}
static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
{
+ struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
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]);
+ gen8_ppgtt_cleanup_3lvl(dev_priv, ppgtt->pml4.pdps[i]);
}
- cleanup_px(ppgtt->base.dev, &ppgtt->pml4);
+ cleanup_px(dev_priv, &ppgtt->pml4);
}
static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
{
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- if (intel_vgpu_active(to_i915(vm->dev)))
+ if (intel_vgpu_active(dev_priv))
gen8_ppgtt_notify_vgt(ppgtt, false);
- if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
- gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp);
+ if (!USES_FULL_48BIT_PPGTT(dev_priv))
+ gen8_ppgtt_cleanup_3lvl(dev_priv, &ppgtt->pdp);
else
gen8_ppgtt_cleanup_4lvl(ppgtt);
@@ -1026,7 +1112,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
uint64_t length,
unsigned long *new_pts)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_page_table *pt;
uint32_t pde;
@@ -1038,7 +1124,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
continue;
}
- pt = alloc_pt(dev);
+ pt = alloc_pt(dev_priv);
if (IS_ERR(pt))
goto unwind_out;
@@ -1052,7 +1138,7 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
unwind_out:
for_each_set_bit(pde, new_pts, I915_PDES)
- free_pt(dev, pd->page_table[pde]);
+ free_pt(dev_priv, pd->page_table[pde]);
return -ENOMEM;
}
@@ -1087,10 +1173,10 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
uint64_t length,
unsigned long *new_pds)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_page_directory *pd;
uint32_t pdpe;
- uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+ uint32_t pdpes = I915_PDPES_PER_PDP(dev_priv);
WARN_ON(!bitmap_empty(new_pds, pdpes));
@@ -1098,7 +1184,7 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
if (test_bit(pdpe, pdp->used_pdpes))
continue;
- pd = alloc_pd(dev);
+ pd = alloc_pd(dev_priv);
if (IS_ERR(pd))
goto unwind_out;
@@ -1112,7 +1198,7 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
unwind_out:
for_each_set_bit(pdpe, new_pds, pdpes)
- free_pd(dev, pdp->page_directory[pdpe]);
+ free_pd(dev_priv, pdp->page_directory[pdpe]);
return -ENOMEM;
}
@@ -1140,7 +1226,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
uint64_t length,
unsigned long *new_pdps)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_page_directory_pointer *pdp;
uint32_t pml4e;
@@ -1148,7 +1234,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
if (!test_bit(pml4e, pml4->used_pml4es)) {
- pdp = alloc_pdp(dev);
+ pdp = alloc_pdp(dev_priv);
if (IS_ERR(pdp))
goto unwind_out;
@@ -1166,7 +1252,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
unwind_out:
for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
- free_pdp(dev, pml4->pdps[pml4e]);
+ free_pdp(dev_priv, pml4->pdps[pml4e]);
return -ENOMEM;
}
@@ -1208,16 +1294,6 @@ err_out:
return -ENOMEM;
}
-/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
- * the page table structures, we mark them dirty so that
- * context switching/execlist queuing code takes extra steps
- * to ensure that tlbs are flushed.
- */
-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_3lvl(struct i915_address_space *vm,
struct i915_page_directory_pointer *pdp,
uint64_t start,
@@ -1225,12 +1301,12 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
unsigned long *new_page_dirs, *new_page_tables;
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_page_directory *pd;
const uint64_t orig_start = start;
const uint64_t orig_length = length;
uint32_t pdpe;
- uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+ uint32_t pdpes = I915_PDPES_PER_PDP(dev_priv);
int ret;
/* Wrap is never okay since we can only represent 48b, and we don't
@@ -1318,11 +1394,12 @@ err_out:
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]);
+ free_pt(dev_priv,
+ pdp->page_directory[pdpe]->page_table[temp]);
}
for_each_set_bit(pdpe, new_page_dirs, pdpes)
- free_pd(dev, pdp->page_directory[pdpe]);
+ free_pd(dev_priv, pdp->page_directory[pdpe]);
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
mark_tlbs_dirty(ppgtt);
@@ -1373,7 +1450,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
err_out:
for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
- gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]);
+ gen8_ppgtt_cleanup_3lvl(to_i915(vm->dev), pml4->pdps[pml4e]);
return ret;
}
@@ -1383,7 +1460,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm,
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- if (USES_FULL_48BIT_PPGTT(vm->dev))
+ if (USES_FULL_48BIT_PPGTT(to_i915(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);
@@ -1452,9 +1529,9 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
uint64_t start = ppgtt->base.start;
uint64_t length = ppgtt->base.total;
gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, true);
+ I915_CACHE_LLC);
- if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+ if (!USES_FULL_48BIT_PPGTT(to_i915(vm->dev))) {
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
} else {
uint64_t pml4e;
@@ -1474,7 +1551,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *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);
+ uint32_t pdpes = I915_PDPES_PER_PDP(to_i915(ppgtt->base.dev));
int ret;
/* We allocate temp bitmap for page tables for no gain
@@ -1507,6 +1584,7 @@ static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt)
*/
static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
{
+ struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
int ret;
ret = gen8_init_scratch(&ppgtt->base);
@@ -1522,8 +1600,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
ppgtt->base.bind_vma = ppgtt_bind_vma;
ppgtt->debug_dump = gen8_dump_ppgtt;
- if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
- ret = setup_px(ppgtt->base.dev, &ppgtt->pml4);
+ if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+ ret = setup_px(dev_priv, &ppgtt->pml4);
if (ret)
goto free_scratch;
@@ -1532,7 +1610,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
ppgtt->base.total = 1ULL << 48;
ppgtt->switch_mm = gen8_48b_mm_switch;
} else {
- ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp);
+ ret = __pdp_init(dev_priv, &ppgtt->pdp);
if (ret)
goto free_scratch;
@@ -1542,14 +1620,14 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
0, 0,
GEN8_PML4E_SHIFT);
- if (intel_vgpu_active(to_i915(ppgtt->base.dev))) {
+ if (intel_vgpu_active(dev_priv)) {
ret = gen8_preallocate_top_level_pdps(ppgtt);
if (ret)
goto free_scratch;
}
}
- if (intel_vgpu_active(to_i915(ppgtt->base.dev)))
+ if (intel_vgpu_active(dev_priv))
gen8_ppgtt_notify_vgt(ppgtt, true);
return 0;
@@ -1569,7 +1647,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
uint32_t start = ppgtt->base.start, length = ppgtt->base.total;
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, true, 0);
+ I915_CACHE_LLC, 0);
gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) {
u32 expected;
@@ -1724,29 +1802,30 @@ static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
return 0;
}
-static void gen8_ppgtt_enable(struct drm_device *dev)
+static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv) {
- u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
+ for_each_engine(engine, dev_priv, id) {
+ u32 four_level = USES_FULL_48BIT_PPGTT(dev_priv) ?
+ GEN8_GFX_PPGTT_48B : 0;
I915_WRITE(RING_MODE_GEN7(engine),
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
}
}
-static void gen7_ppgtt_enable(struct drm_device *dev)
+static void gen7_ppgtt_enable(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_engine_cs *engine;
uint32_t ecochk, ecobits;
+ enum intel_engine_id id;
ecobits = I915_READ(GAC_ECO_BITS);
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
ecochk = I915_READ(GAM_ECOCHK);
- if (IS_HASWELL(dev)) {
+ if (IS_HASWELL(dev_priv)) {
ecochk |= ECOCHK_PPGTT_WB_HSW;
} else {
ecochk |= ECOCHK_PPGTT_LLC_IVB;
@@ -1754,16 +1833,15 @@ static void gen7_ppgtt_enable(struct drm_device *dev)
}
I915_WRITE(GAM_ECOCHK, ecochk);
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
/* GFX_MODE is per-ring on gen7+ */
I915_WRITE(RING_MODE_GEN7(engine),
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
}
}
-static void gen6_ppgtt_enable(struct drm_device *dev)
+static void gen6_ppgtt_enable(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t ecochk, gab_ctl, ecobits;
ecobits = I915_READ(GAC_ECO_BITS);
@@ -1782,8 +1860,7 @@ static void gen6_ppgtt_enable(struct drm_device *dev)
/* PPGTT support for Sandybdrige/Gen6 and later */
static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
uint64_t start,
- uint64_t length,
- bool use_scratch)
+ uint64_t length)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen6_pte_t *pt_vaddr, scratch_pte;
@@ -1794,7 +1871,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned last_pte, i;
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, true, 0);
+ I915_CACHE_LLC, 0);
while (num_entries) {
last_pte = first_pte + num_entries;
@@ -1832,7 +1909,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
pt_vaddr[act_pte] =
- vm->pte_encode(addr, cache_level, true, flags);
+ vm->pte_encode(addr, cache_level, flags);
if (++act_pte == GEN6_PTES) {
kunmap_px(ppgtt, pt_vaddr);
@@ -1850,8 +1927,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
uint64_t start_in, uint64_t length_in)
{
DECLARE_BITMAP(new_page_tables, I915_PDES);
- struct drm_device *dev = vm->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct i915_page_table *pt;
@@ -1881,7 +1957,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
/* We've already allocated a page table */
WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
- pt = alloc_pt(dev);
+ pt = alloc_pt(dev_priv);
if (IS_ERR(pt)) {
ret = PTR_ERR(pt);
goto unwind_out;
@@ -1929,7 +2005,7 @@ unwind_out:
struct i915_page_table *pt = ppgtt->pd.page_table[pde];
ppgtt->pd.page_table[pde] = vm->scratch_pt;
- free_pt(vm->dev, pt);
+ free_pt(dev_priv, pt);
}
mark_tlbs_dirty(ppgtt);
@@ -1938,16 +2014,16 @@ unwind_out:
static int gen6_init_scratch(struct i915_address_space *vm)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
int ret;
- ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
+ ret = setup_scratch_page(dev_priv, &vm->scratch_page, I915_GFP_DMA);
if (ret)
return ret;
- vm->scratch_pt = alloc_pt(dev);
+ vm->scratch_pt = alloc_pt(dev_priv);
if (IS_ERR(vm->scratch_pt)) {
- cleanup_scratch_page(dev, &vm->scratch_page);
+ cleanup_scratch_page(dev_priv, &vm->scratch_page);
return PTR_ERR(vm->scratch_pt);
}
@@ -1958,17 +2034,17 @@ static int gen6_init_scratch(struct i915_address_space *vm)
static void gen6_free_scratch(struct i915_address_space *vm)
{
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
- free_pt(dev, vm->scratch_pt);
- cleanup_scratch_page(dev, &vm->scratch_page);
+ free_pt(dev_priv, vm->scratch_pt);
+ cleanup_scratch_page(dev_priv, &vm->scratch_page);
}
static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct i915_page_directory *pd = &ppgtt->pd;
- struct drm_device *dev = vm->dev;
+ struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_page_table *pt;
uint32_t pde;
@@ -1976,7 +2052,7 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
gen6_for_all_pdes(pt, pd, pde)
if (pt != vm->scratch_pt)
- free_pt(dev, pt);
+ free_pt(dev_priv, pt);
gen6_free_scratch(vm);
}
@@ -1984,8 +2060,7 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
{
struct i915_address_space *vm = &ppgtt->base;
- struct drm_device *dev = ppgtt->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool retried = false;
int ret;
@@ -2050,17 +2125,16 @@ static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
{
- struct drm_device *dev = ppgtt->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
int ret;
ppgtt->base.pte_encode = ggtt->base.pte_encode;
- if (intel_vgpu_active(dev_priv) || IS_GEN6(dev))
+ if (intel_vgpu_active(dev_priv) || IS_GEN6(dev_priv))
ppgtt->switch_mm = gen6_mm_switch;
- else if (IS_HASWELL(dev))
+ else if (IS_HASWELL(dev_priv))
ppgtt->switch_mm = hsw_mm_switch;
- else if (IS_GEN7(dev))
+ else if (IS_GEN7(dev_priv))
ppgtt->switch_mm = gen7_mm_switch;
else
BUG();
@@ -2111,8 +2185,10 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
}
static void i915_address_space_init(struct i915_address_space *vm,
- struct drm_i915_private *dev_priv)
+ struct drm_i915_private *dev_priv,
+ const char *name)
{
+ i915_gem_timeline_init(dev_priv, &vm->timeline, name);
drm_mm_init(&vm->mm, vm->start, vm->total);
INIT_LIST_HEAD(&vm->active_list);
INIT_LIST_HEAD(&vm->inactive_list);
@@ -2120,44 +2196,50 @@ static void i915_address_space_init(struct i915_address_space *vm,
list_add_tail(&vm->global_link, &dev_priv->vm_list);
}
-static void gtt_write_workarounds(struct drm_device *dev)
+static void i915_address_space_fini(struct i915_address_space *vm)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
+ i915_gem_timeline_fini(&vm->timeline);
+ drm_mm_takedown(&vm->mm);
+ list_del(&vm->global_link);
+}
+static void gtt_write_workarounds(struct drm_i915_private *dev_priv)
+{
/* This function is for gtt related workarounds. This function is
* called on driver load and after a GPU reset, so you can place
* workarounds here even if they get overwritten by GPU reset.
*/
/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */
- if (IS_BROADWELL(dev))
+ if (IS_BROADWELL(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
- else if (IS_CHERRYVIEW(dev))
+ else if (IS_CHERRYVIEW(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
- else if (IS_SKYLAKE(dev))
+ else if (IS_SKYLAKE(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
}
static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
struct drm_i915_private *dev_priv,
- struct drm_i915_file_private *file_priv)
+ struct drm_i915_file_private *file_priv,
+ const char *name)
{
int ret;
ret = __hw_ppgtt_init(ppgtt, dev_priv);
if (ret == 0) {
kref_init(&ppgtt->ref);
- i915_address_space_init(&ppgtt->base, dev_priv);
+ i915_address_space_init(&ppgtt->base, dev_priv, name);
ppgtt->base.file = file_priv;
}
return ret;
}
-int i915_ppgtt_init_hw(struct drm_device *dev)
+int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv)
{
- gtt_write_workarounds(dev);
+ gtt_write_workarounds(dev_priv);
/* In the case of execlists, PPGTT is enabled by the context descriptor
* and the PDPs are contained within the context itself. We don't
@@ -2165,24 +2247,25 @@ int i915_ppgtt_init_hw(struct drm_device *dev)
if (i915.enable_execlists)
return 0;
- if (!USES_PPGTT(dev))
+ if (!USES_PPGTT(dev_priv))
return 0;
- if (IS_GEN6(dev))
- gen6_ppgtt_enable(dev);
- else if (IS_GEN7(dev))
- gen7_ppgtt_enable(dev);
- else if (INTEL_INFO(dev)->gen >= 8)
- gen8_ppgtt_enable(dev);
+ if (IS_GEN6(dev_priv))
+ gen6_ppgtt_enable(dev_priv);
+ else if (IS_GEN7(dev_priv))
+ gen7_ppgtt_enable(dev_priv);
+ else if (INTEL_GEN(dev_priv) >= 8)
+ gen8_ppgtt_enable(dev_priv);
else
- MISSING_CASE(INTEL_INFO(dev)->gen);
+ MISSING_CASE(INTEL_GEN(dev_priv));
return 0;
}
struct i915_hw_ppgtt *
i915_ppgtt_create(struct drm_i915_private *dev_priv,
- struct drm_i915_file_private *fpriv)
+ struct drm_i915_file_private *fpriv,
+ const char *name)
{
struct i915_hw_ppgtt *ppgtt;
int ret;
@@ -2191,7 +2274,7 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv,
if (!ppgtt)
return ERR_PTR(-ENOMEM);
- ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv);
+ ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv, name);
if (ret) {
kfree(ppgtt);
return ERR_PTR(ret);
@@ -2202,7 +2285,7 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv,
return ppgtt;
}
-void i915_ppgtt_release(struct kref *kref)
+void i915_ppgtt_release(struct kref *kref)
{
struct i915_hw_ppgtt *ppgtt =
container_of(kref, struct i915_hw_ppgtt, ref);
@@ -2214,8 +2297,7 @@ void i915_ppgtt_release(struct kref *kref)
WARN_ON(!list_empty(&ppgtt->base.inactive_list));
WARN_ON(!list_empty(&ppgtt->base.unbound_list));
- list_del(&ppgtt->base.global_link);
- drm_mm_takedown(&ppgtt->base.mm);
+ i915_address_space_fini(&ppgtt->base);
ppgtt->base.cleanup(&ppgtt->base);
kfree(ppgtt);
@@ -2239,11 +2321,12 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv)
void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
if (INTEL_INFO(dev_priv)->gen < 6)
return;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
u32 fault_reg;
fault_reg = I915_READ(RING_FAULT_REG(engine));
if (fault_reg & RING_FAULT_VALID) {
@@ -2260,7 +2343,10 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
fault_reg & ~RING_FAULT_VALID);
}
}
- POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS]));
+
+ /* Engine specific init may not have been done till this point. */
+ if (dev_priv->engine[RCS])
+ POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
}
static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
@@ -2273,33 +2359,32 @@ static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
}
}
-void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
+void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
/* Don't bother messing with faults pre GEN6 as we have little
* documentation supporting that it's a good idea.
*/
- if (INTEL_INFO(dev)->gen < 6)
+ if (INTEL_GEN(dev_priv) < 6)
return;
i915_check_and_clear_faults(dev_priv);
- ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
- true);
+ ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
i915_ggtt_flush(dev_priv);
}
-int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
+int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
- if (!dma_map_sg(&obj->base.dev->pdev->dev,
- obj->pages->sgl, obj->pages->nents,
- PCI_DMA_BIDIRECTIONAL))
- return -ENOSPC;
+ if (dma_map_sg(&obj->base.dev->pdev->dev,
+ pages->sgl, pages->nents,
+ PCI_DMA_BIDIRECTIONAL))
+ return 0;
- return 0;
+ return -ENOSPC;
}
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
@@ -2317,16 +2402,11 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
gen8_pte_t __iomem *pte =
(gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
(offset >> PAGE_SHIFT);
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
- gen8_set_pte(pte, gen8_pte_encode(addr, level, true));
+ gen8_set_pte(pte, gen8_pte_encode(addr, level));
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2340,15 +2420,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
gen8_pte_t __iomem *gtt_entries;
gen8_pte_t gtt_entry;
dma_addr_t addr;
- int rpm_atomic_seq;
int i = 0;
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
for_each_sgt_dma(addr, sgt_iter, st) {
- gtt_entry = gen8_pte_encode(addr, level, true);
+ gtt_entry = gen8_pte_encode(addr, level);
gen8_set_pte(&gtt_entries[i++], gtt_entry);
}
@@ -2368,8 +2445,6 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
*/
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
struct insert_entries {
@@ -2408,16 +2483,11 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
gen6_pte_t __iomem *pte =
(gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
(offset >> PAGE_SHIFT);
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
- iowrite32(vm->pte_encode(addr, level, true, flags), pte);
+ iowrite32(vm->pte_encode(addr, level, flags), pte);
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
/*
@@ -2437,15 +2507,12 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
gen6_pte_t __iomem *gtt_entries;
gen6_pte_t gtt_entry;
dma_addr_t addr;
- int rpm_atomic_seq;
int i = 0;
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
for_each_sgt_dma(addr, sgt_iter, st) {
- gtt_entry = vm->pte_encode(addr, level, true, flags);
+ gtt_entry = vm->pte_encode(addr, level, flags);
iowrite32(gtt_entry, &gtt_entries[i++]);
}
@@ -2464,23 +2531,16 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
*/
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
static void nop_clear_range(struct i915_address_space *vm,
- uint64_t start,
- uint64_t length,
- bool use_scratch)
+ uint64_t start, uint64_t length)
{
}
static void gen8_ggtt_clear_range(struct i915_address_space *vm,
- uint64_t start,
- uint64_t length,
- bool use_scratch)
+ uint64_t start, uint64_t length)
{
- struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
unsigned first_entry = start >> PAGE_SHIFT;
unsigned num_entries = length >> PAGE_SHIFT;
@@ -2488,9 +2548,6 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
int i;
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
if (WARN(num_entries > max_entries,
"First entry = %d; Num entries = %d (max=%d)\n",
@@ -2498,21 +2555,16 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
num_entries = max_entries;
scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC,
- use_scratch);
+ I915_CACHE_LLC);
for (i = 0; i < num_entries; i++)
gen8_set_pte(&gtt_base[i], scratch_pte);
readl(gtt_base);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
uint64_t start,
- uint64_t length,
- bool use_scratch)
+ uint64_t length)
{
- struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
unsigned first_entry = start >> PAGE_SHIFT;
unsigned num_entries = length >> PAGE_SHIFT;
@@ -2520,9 +2572,6 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
int i;
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
if (WARN(num_entries > max_entries,
"First entry = %d; Num entries = %d (max=%d)\n",
@@ -2530,13 +2579,11 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
num_entries = max_entries;
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
- I915_CACHE_LLC, use_scratch, 0);
+ I915_CACHE_LLC, 0);
for (i = 0; i < num_entries; i++)
iowrite32(scratch_pte, &gtt_base[i]);
readl(gtt_base);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
static void i915_ggtt_insert_page(struct i915_address_space *vm,
@@ -2545,16 +2592,10 @@ static void i915_ggtt_insert_page(struct i915_address_space *vm,
enum i915_cache_level cache_level,
u32 unused)
{
- struct drm_i915_private *dev_priv = to_i915(vm->dev);
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
}
static void i915_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2562,40 +2603,25 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level cache_level, u32 unused)
{
- struct drm_i915_private *dev_priv = to_i915(vm->dev);
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
-
}
static void i915_ggtt_clear_range(struct i915_address_space *vm,
uint64_t start,
- uint64_t length,
- bool unused)
+ uint64_t length)
{
- struct drm_i915_private *dev_priv = to_i915(vm->dev);
- unsigned first_entry = start >> PAGE_SHIFT;
- unsigned num_entries = length >> PAGE_SHIFT;
- int rpm_atomic_seq;
-
- rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
- intel_gtt_clear_range(first_entry, num_entries);
-
- assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
+ intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT);
}
static int ggtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
{
+ struct drm_i915_private *i915 = to_i915(vma->vm->dev);
struct drm_i915_gem_object *obj = vma->obj;
u32 pte_flags = 0;
int ret;
@@ -2608,8 +2634,10 @@ static int ggtt_bind_vma(struct i915_vma *vma,
if (obj->gt_ro)
pte_flags |= PTE_READ_ONLY;
+ intel_runtime_pm_get(i915);
vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
cache_level, pte_flags);
+ intel_runtime_pm_put(i915);
/*
* Without aliasing PPGTT there's no difference between
@@ -2625,6 +2653,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
{
+ struct drm_i915_private *i915 = to_i915(vma->vm->dev);
u32 pte_flags;
int ret;
@@ -2639,14 +2668,15 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
if (flags & I915_VMA_GLOBAL_BIND) {
+ intel_runtime_pm_get(i915);
vma->vm->insert_entries(vma->vm,
vma->pages, vma->node.start,
cache_level, pte_flags);
+ intel_runtime_pm_put(i915);
}
if (flags & I915_VMA_LOCAL_BIND) {
- struct i915_hw_ppgtt *appgtt =
- to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+ struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
appgtt->base.insert_entries(&appgtt->base,
vma->pages, vma->node.start,
cache_level, pte_flags);
@@ -2657,21 +2687,24 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
static void ggtt_unbind_vma(struct i915_vma *vma)
{
- struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+ struct drm_i915_private *i915 = to_i915(vma->vm->dev);
+ struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
const u64 size = min(vma->size, vma->node.size);
- if (vma->flags & I915_VMA_GLOBAL_BIND)
+ if (vma->flags & I915_VMA_GLOBAL_BIND) {
+ intel_runtime_pm_get(i915);
vma->vm->clear_range(vma->vm,
- vma->node.start, size,
- true);
+ vma->node.start, size);
+ intel_runtime_pm_put(i915);
+ }
if (vma->flags & I915_VMA_LOCAL_BIND && appgtt)
appgtt->base.clear_range(&appgtt->base,
- vma->node.start, size,
- true);
+ vma->node.start, size);
}
-void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
+void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct device *kdev = &dev_priv->drm.pdev->dev;
@@ -2685,8 +2718,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
}
}
- dma_unmap_sg(kdev, obj->pages->sgl, obj->pages->nents,
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL);
}
static void i915_gtt_color_adjust(struct drm_mm_node *node,
@@ -2717,6 +2749,7 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
*/
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned long hole_start, hole_end;
+ struct i915_hw_ppgtt *ppgtt;
struct drm_mm_node *entry;
int ret;
@@ -2724,45 +2757,48 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
if (ret)
return ret;
+ /* Reserve a mappable slot for our lockless error capture */
+ ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
+ &ggtt->error_capture,
+ 4096, 0, -1,
+ 0, ggtt->mappable_end,
+ 0, 0);
+ if (ret)
+ return ret;
+
/* Clear any non-preallocated blocks */
drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
hole_start, hole_end);
ggtt->base.clear_range(&ggtt->base, hole_start,
- hole_end - hole_start, true);
+ hole_end - hole_start);
}
/* And finally clear the reserved guard page */
ggtt->base.clear_range(&ggtt->base,
- ggtt->base.total - PAGE_SIZE, PAGE_SIZE,
- true);
+ ggtt->base.total - PAGE_SIZE, PAGE_SIZE);
if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
- struct i915_hw_ppgtt *ppgtt;
-
ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
- if (!ppgtt)
- return -ENOMEM;
+ if (!ppgtt) {
+ ret = -ENOMEM;
+ goto err;
+ }
ret = __hw_ppgtt_init(ppgtt, dev_priv);
- if (ret) {
- kfree(ppgtt);
- return ret;
- }
+ if (ret)
+ goto err_ppgtt;
- if (ppgtt->base.allocate_va_range)
+ if (ppgtt->base.allocate_va_range) {
ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0,
ppgtt->base.total);
- if (ret) {
- ppgtt->base.cleanup(&ppgtt->base);
- kfree(ppgtt);
- return ret;
+ if (ret)
+ goto err_ppgtt_cleanup;
}
ppgtt->base.clear_range(&ppgtt->base,
ppgtt->base.start,
- ppgtt->base.total,
- true);
+ ppgtt->base.total);
dev_priv->mm.aliasing_ppgtt = ppgtt;
WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
@@ -2770,6 +2806,14 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
}
return 0;
+
+err_ppgtt_cleanup:
+ ppgtt->base.cleanup(&ppgtt->base);
+err_ppgtt:
+ kfree(ppgtt);
+err:
+ drm_mm_remove_node(&ggtt->error_capture);
+ return ret;
}
/**
@@ -2788,11 +2832,15 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
i915_gem_cleanup_stolen(&dev_priv->drm);
+ if (drm_mm_node_allocated(&ggtt->error_capture))
+ drm_mm_remove_node(&ggtt->error_capture);
+
if (drm_mm_initialized(&ggtt->base.mm)) {
intel_vgt_deballoon(dev_priv);
- drm_mm_takedown(&ggtt->base.mm);
- list_del(&ggtt->base.global_link);
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ i915_address_space_fini(&ggtt->base);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
}
ggtt->base.cleanup(&ggtt->base);
@@ -2881,6 +2929,7 @@ static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl)
static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
{
+ struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
struct pci_dev *pdev = ggtt->base.dev->pdev;
phys_addr_t phys_addr;
int ret;
@@ -2895,7 +2944,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
* resort to an uncached mapping. The WC issue is easily caught by the
* readback check when writing GTT PTE entries.
*/
- if (IS_BROXTON(ggtt->base.dev))
+ if (IS_BROXTON(dev_priv))
ggtt->gsm = ioremap_nocache(phys_addr, size);
else
ggtt->gsm = ioremap_wc(phys_addr, size);
@@ -2904,9 +2953,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
return -ENOMEM;
}
- ret = setup_scratch_page(ggtt->base.dev,
- &ggtt->base.scratch_page,
- GFP_DMA32);
+ ret = setup_scratch_page(dev_priv, &ggtt->base.scratch_page, GFP_DMA32);
if (ret) {
DRM_ERROR("Scratch setup failed\n");
/* iounmap will also get called at remove, but meh */
@@ -2995,7 +3042,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
iounmap(ggtt->gsm);
- cleanup_scratch_page(vm->dev, &vm->scratch_page);
+ cleanup_scratch_page(to_i915(vm->dev), &vm->scratch_page);
}
static int gen8_gmch_probe(struct i915_ggtt *ggtt)
@@ -3190,11 +3237,13 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
/* Subtract the guard page before address space initialization to
* shrink the range used by drm_mm.
*/
+ mutex_lock(&dev_priv->drm.struct_mutex);
ggtt->base.total -= PAGE_SIZE;
- i915_address_space_init(&ggtt->base, dev_priv);
+ i915_address_space_init(&ggtt->base, dev_priv, "[global]");
ggtt->base.total += PAGE_SIZE;
if (!HAS_LLC(dev_priv))
ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
+ mutex_unlock(&dev_priv->drm.struct_mutex);
if (!io_mapping_init_wc(&dev_priv->ggtt.mappable,
dev_priv->ggtt.mappable_base,
@@ -3209,7 +3258,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
* Initialise stolen early so that we may reserve preallocated
* objects for the BIOS to KMS transition.
*/
- ret = i915_gem_init_stolen(&dev_priv->drm);
+ ret = i915_gem_init_stolen(dev_priv);
if (ret)
goto out_gtt_cleanup;
@@ -3228,23 +3277,21 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
return 0;
}
-void i915_gem_restore_gtt_mappings(struct drm_device *dev)
+void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_object *obj, *on;
i915_check_and_clear_faults(dev_priv);
/* First fill our portion of the GTT with scratch pages */
- ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
- true);
+ ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */
/* clflush objects bound into the GGTT and rebind them. */
list_for_each_entry_safe(obj, on,
- &dev_priv->mm.bound_list, global_list) {
+ &dev_priv->mm.bound_list, global_link) {
bool ggtt_bound = false;
struct i915_vma *vma;
@@ -3266,8 +3313,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
ggtt->base.closed = false;
- if (INTEL_INFO(dev)->gen >= 8) {
- if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
+ if (INTEL_GEN(dev_priv) >= 8) {
+ if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
chv_setup_private_ppat(dev_priv);
else
bdw_setup_private_ppat(dev_priv);
@@ -3275,7 +3322,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
return;
}
- if (USES_PPGTT(dev)) {
+ if (USES_PPGTT(dev_priv)) {
struct i915_address_space *vm;
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
@@ -3296,137 +3343,28 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
i915_ggtt_flush(dev_priv);
}
-static void
-i915_vma_retire(struct i915_gem_active *active,
- struct drm_i915_gem_request *rq)
-{
- const unsigned int idx = rq->engine->id;
- struct i915_vma *vma =
- container_of(active, struct i915_vma, last_read[idx]);
-
- GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
-
- i915_vma_clear_active(vma, idx);
- if (i915_vma_is_active(vma))
- return;
-
- list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
- if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
- WARN_ON(i915_vma_unbind(vma));
-}
-
-void i915_vma_destroy(struct i915_vma *vma)
-{
- GEM_BUG_ON(vma->node.allocated);
- GEM_BUG_ON(i915_vma_is_active(vma));
- GEM_BUG_ON(!i915_vma_is_closed(vma));
- GEM_BUG_ON(vma->fence);
-
- list_del(&vma->vm_link);
- if (!i915_vma_is_ggtt(vma))
- i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
-
- kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
-}
-
-void i915_vma_close(struct i915_vma *vma)
-{
- GEM_BUG_ON(i915_vma_is_closed(vma));
- vma->flags |= I915_VMA_CLOSED;
-
- list_del_init(&vma->obj_link);
- if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
- WARN_ON(i915_vma_unbind(vma));
-}
-
-static struct i915_vma *
-__i915_vma_create(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm,
- const struct i915_ggtt_view *view)
-{
- struct i915_vma *vma;
- int i;
-
- GEM_BUG_ON(vm->closed);
-
- vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
- if (vma == NULL)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&vma->exec_list);
- for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
- init_request_active(&vma->last_read[i], i915_vma_retire);
- init_request_active(&vma->last_fence, NULL);
- list_add(&vma->vm_link, &vm->unbound_list);
- vma->vm = vm;
- vma->obj = obj;
- vma->size = obj->base.size;
-
- if (view) {
- vma->ggtt_view = *view;
- if (view->type == I915_GGTT_VIEW_PARTIAL) {
- vma->size = view->params.partial.size;
- vma->size <<= PAGE_SHIFT;
- } else if (view->type == I915_GGTT_VIEW_ROTATED) {
- vma->size =
- intel_rotation_info_size(&view->params.rotated);
- vma->size <<= PAGE_SHIFT;
- }
- }
-
- if (i915_is_ggtt(vm)) {
- vma->flags |= I915_VMA_GGTT;
- } else {
- i915_ppgtt_get(i915_vm_to_ppgtt(vm));
- }
-
- list_add_tail(&vma->obj_link, &obj->vma_list);
- return vma;
-}
-
-static inline bool vma_matches(struct i915_vma *vma,
- struct i915_address_space *vm,
- const struct i915_ggtt_view *view)
-{
- if (vma->vm != vm)
- return false;
-
- if (!i915_vma_is_ggtt(vma))
- return true;
-
- if (!view)
- return vma->ggtt_view.type == 0;
-
- if (vma->ggtt_view.type != view->type)
- return false;
-
- return memcmp(&vma->ggtt_view.params,
- &view->params,
- sizeof(view->params)) == 0;
-}
-
-struct i915_vma *
-i915_vma_create(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm,
- const struct i915_ggtt_view *view)
-{
- GEM_BUG_ON(view && !i915_is_ggtt(vm));
- GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view));
-
- return __i915_vma_create(obj, vm, view);
-}
-
struct i915_vma *
i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
struct i915_address_space *vm,
const struct i915_ggtt_view *view)
{
- struct i915_vma *vma;
+ struct rb_node *rb;
- list_for_each_entry_reverse(vma, &obj->vma_list, obj_link)
- if (vma_matches(vma, vm, view))
+ rb = obj->vma_tree.rb_node;
+ while (rb) {
+ struct i915_vma *vma = rb_entry(rb, struct i915_vma, obj_node);
+ long cmp;
+
+ cmp = i915_vma_compare(vma, vm, view);
+ if (cmp == 0)
return vma;
+ if (cmp < 0)
+ rb = rb->rb_right;
+ else
+ rb = rb->rb_left;
+ }
+
return NULL;
}
@@ -3437,11 +3375,14 @@ i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
{
struct i915_vma *vma;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
GEM_BUG_ON(view && !i915_is_ggtt(vm));
vma = i915_gem_obj_to_vma(obj, vm, view);
- if (!vma)
- vma = __i915_vma_create(obj, vm, view);
+ if (!vma) {
+ vma = i915_vma_create(obj, vm, view);
+ GEM_BUG_ON(vma != i915_gem_obj_to_vma(obj, vm, view));
+ }
GEM_BUG_ON(i915_vma_is_closed(vma));
return vma;
@@ -3507,7 +3448,7 @@ intel_rotate_fb_obj_pages(const struct intel_rotation_info *rot_info,
/* Populate source page list from the object. */
i = 0;
- for_each_sgt_dma(dma_addr, sgt_iter, obj->pages)
+ for_each_sgt_dma(dma_addr, sgt_iter, obj->mm.pages)
page_addr_list[i++] = dma_addr;
GEM_BUG_ON(i != n_pages);
@@ -3543,35 +3484,47 @@ intel_partial_pages(const struct i915_ggtt_view *view,
struct drm_i915_gem_object *obj)
{
struct sg_table *st;
- struct scatterlist *sg;
- struct sg_page_iter obj_sg_iter;
+ struct scatterlist *sg, *iter;
+ unsigned int count = view->params.partial.size;
+ unsigned int offset;
int ret = -ENOMEM;
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (!st)
goto err_st_alloc;
- ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
+ ret = sg_alloc_table(st, count, GFP_KERNEL);
if (ret)
goto err_sg_alloc;
+ iter = i915_gem_object_get_sg(obj,
+ view->params.partial.offset,
+ &offset);
+ GEM_BUG_ON(!iter);
+
sg = st->sgl;
st->nents = 0;
- for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
- view->params.partial.offset)
- {
- if (st->nents >= view->params.partial.size)
- break;
+ do {
+ unsigned int len;
- sg_set_page(sg, NULL, PAGE_SIZE, 0);
- sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
- sg_dma_len(sg) = PAGE_SIZE;
+ len = min(iter->length - (offset << PAGE_SHIFT),
+ count << PAGE_SHIFT);
+ sg_set_page(sg, NULL, len, 0);
+ sg_dma_address(sg) =
+ sg_dma_address(iter) + (offset << PAGE_SHIFT);
+ sg_dma_len(sg) = len;
- sg = sg_next(sg);
st->nents++;
- }
+ count -= len >> PAGE_SHIFT;
+ if (count == 0) {
+ sg_mark_end(sg);
+ return st;
+ }
- return st;
+ sg = __sg_next(sg);
+ iter = __sg_next(iter);
+ offset = 0;
+ } while (1);
err_sg_alloc:
kfree(st);
@@ -3584,11 +3537,18 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
{
int ret = 0;
+ /* The vma->pages are only valid within the lifespan of the borrowed
+ * obj->mm.pages. When the obj->mm.pages sg_table is regenerated, so
+ * must be the vma->pages. A simple rule is that vma->pages must only
+ * be accessed when the obj->mm.pages are pinned.
+ */
+ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj));
+
if (vma->pages)
return 0;
if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
- vma->pages = vma->obj->pages;
+ vma->pages = vma->obj->mm.pages;
else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
vma->pages =
intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj);
@@ -3612,94 +3572,3 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
return ret;
}
-/**
- * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
- * @vma: VMA to map
- * @cache_level: mapping cache level
- * @flags: flags like global or local mapping
- *
- * DMA addresses are taken from the scatter-gather table of this object (or of
- * this VMA in case of non-default GGTT views) and PTE entries set up.
- * Note that DMA addresses are also the only part of the SG table we care about.
- */
-int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
- u32 flags)
-{
- u32 bind_flags;
- u32 vma_flags;
- int ret;
-
- if (WARN_ON(flags == 0))
- return -EINVAL;
-
- bind_flags = 0;
- if (flags & PIN_GLOBAL)
- bind_flags |= I915_VMA_GLOBAL_BIND;
- if (flags & PIN_USER)
- bind_flags |= I915_VMA_LOCAL_BIND;
-
- vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
- if (flags & PIN_UPDATE)
- bind_flags |= vma_flags;
- else
- bind_flags &= ~vma_flags;
- if (bind_flags == 0)
- return 0;
-
- if (vma_flags == 0 && vma->vm->allocate_va_range) {
- trace_i915_va_alloc(vma);
- ret = vma->vm->allocate_va_range(vma->vm,
- vma->node.start,
- vma->node.size);
- if (ret)
- return ret;
- }
-
- ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
- if (ret)
- return ret;
-
- vma->flags |= bind_flags;
- return 0;
-}
-
-void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
-{
- void __iomem *ptr;
-
- /* Access through the GTT requires the device to be awake. */
- assert_rpm_wakelock_held(to_i915(vma->vm->dev));
-
- lockdep_assert_held(&vma->vm->dev->struct_mutex);
- if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
- return IO_ERR_PTR(-ENODEV);
-
- GEM_BUG_ON(!i915_vma_is_ggtt(vma));
- GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
-
- ptr = vma->iomap;
- if (ptr == NULL) {
- ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable,
- vma->node.start,
- vma->node.size);
- if (ptr == NULL)
- return IO_ERR_PTR(-ENOMEM);
-
- vma->iomap = ptr;
- }
-
- __i915_vma_pin(vma);
- return ptr;
-}
-
-void i915_vma_unpin_and_release(struct i915_vma **p_vma)
-{
- struct i915_vma *vma;
-
- vma = fetch_and_zero(p_vma);
- if (!vma)
- return;
-
- i915_vma_unpin(vma);
- i915_vma_put(vma);
-}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index ec78be2f8c77..4f35be4c26c7 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -35,7 +35,9 @@
#define __I915_GEM_GTT_H__
#include <linux/io-mapping.h>
+#include <linux/mm.h>
+#include "i915_gem_timeline.h"
#include "i915_gem_request.h"
#define I915_FENCE_REG_NONE -1
@@ -118,8 +120,8 @@ typedef uint64_t gen8_ppgtt_pml4e_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 I915_PDPES_PER_PDP(dev_priv) (USES_FULL_48BIT_PPGTT(dev_priv) ?\
+ GEN8_PML4ES_PER_PML4 : GEN8_LEGACY_PDPES)
#define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD)
#define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */
@@ -138,6 +140,8 @@ typedef uint64_t gen8_ppgtt_pml4e_t;
#define GEN8_PPAT_ELLC_OVERRIDE (0<<2)
#define GEN8_PPAT(i, x) ((uint64_t) (x) << ((i) * 8))
+struct sg_table;
+
enum i915_ggtt_view_type {
I915_GGTT_VIEW_NORMAL = 0,
I915_GGTT_VIEW_ROTATED,
@@ -168,133 +172,7 @@ extern const struct i915_ggtt_view i915_ggtt_view_rotated;
enum i915_cache_level;
-/**
- * A VMA represents a GEM BO that is bound into an address space. Therefore, a
- * VMA's presence cannot be guaranteed before binding, or after unbinding the
- * object into/from the address space.
- *
- * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
- * will always be <= an objects lifetime. So object refcounting should cover us.
- */
-struct i915_vma {
- struct drm_mm_node node;
- struct drm_i915_gem_object *obj;
- struct i915_address_space *vm;
- struct drm_i915_fence_reg *fence;
- struct sg_table *pages;
- void __iomem *iomap;
- u64 size;
- u64 display_alignment;
-
- unsigned int flags;
- /**
- * How many users have pinned this object in GTT space. The following
- * users can each hold at most one reference: pwrite/pread, execbuffer
- * (objects are not allowed multiple times for the same batchbuffer),
- * and the framebuffer code. When switching/pageflipping, the
- * framebuffer code has at most two buffers pinned per crtc.
- *
- * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
- * bits with absolutely no headroom. So use 4 bits.
- */
-#define I915_VMA_PIN_MASK 0xf
-#define I915_VMA_PIN_OVERFLOW BIT(5)
-
- /** Flags and address space this VMA is bound to */
-#define I915_VMA_GLOBAL_BIND BIT(6)
-#define I915_VMA_LOCAL_BIND BIT(7)
-#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)
-
-#define I915_VMA_GGTT BIT(8)
-#define I915_VMA_CAN_FENCE BIT(9)
-#define I915_VMA_CLOSED BIT(10)
-
- unsigned int active;
- struct i915_gem_active last_read[I915_NUM_ENGINES];
- struct i915_gem_active last_fence;
-
- /**
- * Support different GGTT views into the same object.
- * This means there can be multiple VMA mappings per object and per VM.
- * i915_ggtt_view_type is used to distinguish between those entries.
- * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
- * assumed in GEM functions which take no ggtt view parameter.
- */
- struct i915_ggtt_view ggtt_view;
-
- /** This object's place on the active/inactive lists */
- struct list_head vm_link;
-
- struct list_head obj_link; /* Link in the object's VMA list */
-
- /** This vma's place in the batchbuffer or on the eviction list */
- struct list_head exec_list;
-
- /**
- * Used for performing relocations during execbuffer insertion.
- */
- struct hlist_node exec_node;
- unsigned long exec_handle;
- struct drm_i915_gem_exec_object2 *exec_entry;
-};
-
-struct i915_vma *
-i915_vma_create(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm,
- const struct i915_ggtt_view *view);
-void i915_vma_unpin_and_release(struct i915_vma **p_vma);
-
-static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
-{
- return vma->flags & I915_VMA_GGTT;
-}
-
-static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
-{
- return vma->flags & I915_VMA_CAN_FENCE;
-}
-
-static inline bool i915_vma_is_closed(const struct i915_vma *vma)
-{
- return vma->flags & I915_VMA_CLOSED;
-}
-
-static inline unsigned int i915_vma_get_active(const struct i915_vma *vma)
-{
- return vma->active;
-}
-
-static inline bool i915_vma_is_active(const struct i915_vma *vma)
-{
- return i915_vma_get_active(vma);
-}
-
-static inline void i915_vma_set_active(struct i915_vma *vma,
- unsigned int engine)
-{
- vma->active |= BIT(engine);
-}
-
-static inline void i915_vma_clear_active(struct i915_vma *vma,
- unsigned int engine)
-{
- vma->active &= ~BIT(engine);
-}
-
-static inline bool i915_vma_has_active_engine(const struct i915_vma *vma,
- unsigned int engine)
-{
- return vma->active & BIT(engine);
-}
-
-static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
-{
- GEM_BUG_ON(!i915_vma_is_ggtt(vma));
- GEM_BUG_ON(!vma->node.allocated);
- GEM_BUG_ON(upper_32_bits(vma->node.start));
- GEM_BUG_ON(upper_32_bits(vma->node.start + vma->node.size - 1));
- return lower_32_bits(vma->node.start);
-}
+struct i915_vma;
struct i915_page_dma {
struct page *page;
@@ -341,6 +219,7 @@ struct i915_pml4 {
struct i915_address_space {
struct drm_mm mm;
+ struct i915_gem_timeline timeline;
struct drm_device *dev;
/* Every address space belongs to a struct file - except for the global
* GTT that is owned by the driver (and so @file is set to NULL). In
@@ -395,7 +274,7 @@ struct i915_address_space {
/* FIXME: Need a more generic return type */
gen6_pte_t (*pte_encode)(dma_addr_t addr,
enum i915_cache_level level,
- bool valid, u32 flags); /* Create a valid PTE */
+ u32 flags); /* Create a valid PTE */
/* flags for pte_encode */
#define PTE_READ_ONLY (1<<0)
int (*allocate_va_range)(struct i915_address_space *vm,
@@ -403,8 +282,7 @@ struct i915_address_space {
uint64_t length);
void (*clear_range)(struct i915_address_space *vm,
uint64_t start,
- uint64_t length,
- bool use_scratch);
+ uint64_t length);
void (*insert_page)(struct i915_address_space *vm,
dma_addr_t addr,
uint64_t offset,
@@ -450,6 +328,8 @@ struct i915_ggtt {
bool do_idle_maps;
int mtrr;
+
+ struct drm_mm_node error_capture;
};
struct i915_hw_ppgtt {
@@ -602,16 +482,24 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n)
px_dma(ppgtt->base.scratch_pd);
}
+static inline struct i915_ggtt *
+i915_vm_to_ggtt(struct i915_address_space *vm)
+{
+ GEM_BUG_ON(!i915_is_ggtt(vm));
+ return container_of(vm, struct i915_ggtt, base);
+}
+
int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv);
int i915_ggtt_init_hw(struct drm_i915_private *dev_priv);
int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv);
int i915_gem_init_ggtt(struct drm_i915_private *dev_priv);
void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv);
-int i915_ppgtt_init_hw(struct drm_device *dev);
+int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
void i915_ppgtt_release(struct kref *kref);
struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv,
- struct drm_i915_file_private *fpriv);
+ struct drm_i915_file_private *fpriv,
+ const char *name);
static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
{
if (ppgtt)
@@ -624,11 +512,13 @@ static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt)
}
void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);
-void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
-void i915_gem_restore_gtt_mappings(struct drm_device *dev);
+void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv);
+void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv);
-int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
-void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages);
+void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages);
/* Flags used by pin/bind&friends. */
#define PIN_NONBLOCK BIT(0)
@@ -646,88 +536,4 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
#define PIN_OFFSET_FIXED BIT(11)
#define PIN_OFFSET_MASK (~4095)
-int __i915_vma_do_pin(struct i915_vma *vma,
- u64 size, u64 alignment, u64 flags);
-static inline int __must_check
-i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
-{
- BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW);
- BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
- BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
-
- /* Pin early to prevent the shrinker/eviction logic from destroying
- * our vma as we insert and bind.
- */
- if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0))
- return 0;
-
- return __i915_vma_do_pin(vma, size, alignment, flags);
-}
-
-static inline int i915_vma_pin_count(const struct i915_vma *vma)
-{
- return vma->flags & I915_VMA_PIN_MASK;
-}
-
-static inline bool i915_vma_is_pinned(const struct i915_vma *vma)
-{
- return i915_vma_pin_count(vma);
-}
-
-static inline void __i915_vma_pin(struct i915_vma *vma)
-{
- vma->flags++;
- GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW);
-}
-
-static inline void __i915_vma_unpin(struct i915_vma *vma)
-{
- GEM_BUG_ON(!i915_vma_is_pinned(vma));
- vma->flags--;
-}
-
-static inline void i915_vma_unpin(struct i915_vma *vma)
-{
- GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
- __i915_vma_unpin(vma);
-}
-
-/**
- * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
- * @vma: VMA to iomap
- *
- * The passed in VMA has to be pinned in the global GTT mappable region.
- * An extra pinning of the VMA is acquired for the return iomapping,
- * the caller must call i915_vma_unpin_iomap to relinquish the pinning
- * after the iomapping is no longer required.
- *
- * Callers must hold the struct_mutex.
- *
- * Returns a valid iomapped pointer or ERR_PTR.
- */
-void __iomem *i915_vma_pin_iomap(struct i915_vma *vma);
-#define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x))
-
-/**
- * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap
- * @vma: VMA to unpin
- *
- * Unpins the previously iomapped VMA from i915_vma_pin_iomap().
- *
- * Callers must hold the struct_mutex. This function is only valid to be
- * called on a VMA previously iomapped by the caller with i915_vma_pin_iomap().
- */
-static inline void i915_vma_unpin_iomap(struct i915_vma *vma)
-{
- lockdep_assert_held(&vma->vm->dev->struct_mutex);
- GEM_BUG_ON(vma->iomap == NULL);
- i915_vma_unpin(vma);
-}
-
-static inline struct page *i915_vma_first_page(struct i915_vma *vma)
-{
- GEM_BUG_ON(!vma->pages);
- return sg_page(vma->pages->sgl);
-}
-
#endif
diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c
new file mode 100644
index 000000000000..4b3ff3e5b911
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_internal.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2014-2016 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 <drm/drmP.h>
+#include <drm/i915_drm.h>
+#include "i915_drv.h"
+
+#define QUIET (__GFP_NORETRY | __GFP_NOWARN)
+
+/* convert swiotlb segment size into sensible units (pages)! */
+#define IO_TLB_SEGPAGES (IO_TLB_SEGSIZE << IO_TLB_SHIFT >> PAGE_SHIFT)
+
+static void internal_free_pages(struct sg_table *st)
+{
+ struct scatterlist *sg;
+
+ for (sg = st->sgl; sg; sg = __sg_next(sg))
+ __free_pages(sg_page(sg), get_order(sg->length));
+
+ sg_free_table(st);
+ kfree(st);
+}
+
+static struct sg_table *
+i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ unsigned int npages = obj->base.size / PAGE_SIZE;
+ struct sg_table *st;
+ struct scatterlist *sg;
+ int max_order;
+ gfp_t gfp;
+
+ st = kmalloc(sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return ERR_PTR(-ENOMEM);
+
+ if (sg_alloc_table(st, npages, GFP_KERNEL)) {
+ kfree(st);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sg = st->sgl;
+ st->nents = 0;
+
+ max_order = MAX_ORDER;
+#ifdef CONFIG_SWIOTLB
+ if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */
+ max_order = min(max_order, ilog2(IO_TLB_SEGPAGES));
+#endif
+
+ gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE;
+ if (IS_CRESTLINE(i915) || IS_BROADWATER(i915)) {
+ /* 965gm cannot relocate objects above 4GiB. */
+ gfp &= ~__GFP_HIGHMEM;
+ gfp |= __GFP_DMA32;
+ }
+
+ do {
+ int order = min(fls(npages) - 1, max_order);
+ struct page *page;
+
+ do {
+ page = alloc_pages(gfp | (order ? QUIET : 0), order);
+ if (page)
+ break;
+ if (!order--)
+ goto err;
+
+ /* Limit subsequent allocations as well */
+ max_order = order;
+ } while (1);
+
+ sg_set_page(sg, page, PAGE_SIZE << order, 0);
+ st->nents++;
+
+ npages -= 1 << order;
+ if (!npages) {
+ sg_mark_end(sg);
+ break;
+ }
+
+ sg = __sg_next(sg);
+ } while (1);
+
+ if (i915_gem_gtt_prepare_pages(obj, st))
+ goto err;
+
+ /* Mark the pages as dontneed whilst they are still pinned. As soon
+ * as they are unpinned they are allowed to be reaped by the shrinker,
+ * and the caller is expected to repopulate - the contents of this
+ * object are only valid whilst active and pinned.
+ */
+ obj->mm.madv = I915_MADV_DONTNEED;
+ return st;
+
+err:
+ sg_mark_end(sg);
+ internal_free_pages(st);
+ return ERR_PTR(-ENOMEM);
+}
+
+static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
+{
+ i915_gem_gtt_finish_pages(obj, pages);
+ internal_free_pages(pages);
+
+ obj->mm.dirty = false;
+ obj->mm.madv = I915_MADV_WILLNEED;
+}
+
+static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = {
+ .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+ I915_GEM_OBJECT_IS_SHRINKABLE,
+ .get_pages = i915_gem_object_get_pages_internal,
+ .put_pages = i915_gem_object_put_pages_internal,
+};
+
+/**
+ * Creates a new object that wraps some internal memory for private use.
+ * This object is not backed by swappable storage, and as such its contents
+ * are volatile and only valid whilst pinned. If the object is reaped by the
+ * shrinker, its pages and data will be discarded. Equally, it is not a full
+ * GEM object and so not valid for access from userspace. This makes it useful
+ * for hardware interfaces like ringbuffers (which are pinned from the time
+ * the request is written to the time the hardware stops accessing it), but
+ * not for contexts (which need to be preserved when not active for later
+ * reuse). Note that it is not cleared upon allocation.
+ */
+struct drm_i915_gem_object *
+i915_gem_object_create_internal(struct drm_i915_private *i915,
+ unsigned int size)
+{
+ struct drm_i915_gem_object *obj;
+
+ obj = i915_gem_object_alloc(&i915->drm);
+ if (!obj)
+ return ERR_PTR(-ENOMEM);
+
+ drm_gem_private_object_init(&i915->drm, &obj->base, size);
+ i915_gem_object_init(obj, &i915_gem_object_internal_ops);
+
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+ obj->cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
+
+ return obj;
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
new file mode 100644
index 000000000000..6a368de9d81e
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2016 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 __I915_GEM_OBJECT_H__
+#define __I915_GEM_OBJECT_H__
+
+#include <linux/reservation.h>
+
+#include <drm/drm_vma_manager.h>
+#include <drm/drm_gem.h>
+#include <drm/drmP.h>
+
+#include <drm/i915_drm.h>
+
+struct drm_i915_gem_object_ops {
+ unsigned int flags;
+#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
+#define I915_GEM_OBJECT_IS_SHRINKABLE 0x2
+
+ /* Interface between the GEM object and its backing storage.
+ * get_pages() is called once prior to the use of the associated set
+ * of pages before to binding them into the GTT, and put_pages() is
+ * called after we no longer need them. As we expect there to be
+ * associated cost with migrating pages between the backing storage
+ * and making them available for the GPU (e.g. clflush), we may hold
+ * onto the pages after they are no longer referenced by the GPU
+ * in case they may be used again shortly (for example migrating the
+ * pages to a different memory domain within the GTT). put_pages()
+ * will therefore most likely be called when the object itself is
+ * being released or under memory pressure (where we attempt to
+ * reap pages for the shrinker).
+ */
+ struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
+ void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
+
+ int (*dmabuf_export)(struct drm_i915_gem_object *);
+ void (*release)(struct drm_i915_gem_object *);
+};
+
+struct drm_i915_gem_object {
+ struct drm_gem_object base;
+
+ const struct drm_i915_gem_object_ops *ops;
+
+ /** List of VMAs backed by this object */
+ struct list_head vma_list;
+ struct rb_root vma_tree;
+
+ /** Stolen memory for this object, instead of being backed by shmem. */
+ struct drm_mm_node *stolen;
+ struct list_head global_link;
+ union {
+ struct rcu_head rcu;
+ struct llist_node freed;
+ };
+
+ /**
+ * Whether the object is currently in the GGTT mmap.
+ */
+ struct list_head userfault_link;
+
+ /** Used in execbuf to temporarily hold a ref */
+ struct list_head obj_exec_link;
+
+ struct list_head batch_pool_link;
+
+ unsigned long flags;
+
+ /**
+ * Have we taken a reference for the object for incomplete GPU
+ * activity?
+ */
+#define I915_BO_ACTIVE_REF 0
+
+ /*
+ * Is the object to be mapped as read-only to the GPU
+ * Only honoured if hardware has relevant pte bit
+ */
+ unsigned long gt_ro:1;
+ unsigned int cache_level:3;
+ unsigned int cache_dirty:1;
+
+ atomic_t frontbuffer_bits;
+ unsigned int frontbuffer_ggtt_origin; /* write once */
+ struct i915_gem_active frontbuffer_write;
+
+ /** Current tiling stride for the object, if it's tiled. */
+ unsigned int tiling_and_stride;
+#define FENCE_MINIMUM_STRIDE 128 /* See i915_tiling_ok() */
+#define TILING_MASK (FENCE_MINIMUM_STRIDE-1)
+#define STRIDE_MASK (~TILING_MASK)
+
+ /** Count of VMA actually bound by this object */
+ unsigned int bind_count;
+ unsigned int active_count;
+ unsigned int pin_display;
+
+ struct {
+ struct mutex lock; /* protects the pages and their use */
+ atomic_t pages_pin_count;
+
+ struct sg_table *pages;
+ void *mapping;
+
+ struct i915_gem_object_page_iter {
+ struct scatterlist *sg_pos;
+ unsigned int sg_idx; /* in pages, but 32bit eek! */
+
+ struct radix_tree_root radix;
+ struct mutex lock; /* protects this cache */
+ } get_page;
+
+ /**
+ * Advice: are the backing pages purgeable?
+ */
+ unsigned int madv:2;
+
+ /**
+ * This is set if the object has been written to since the
+ * pages were last acquired.
+ */
+ bool dirty:1;
+
+ /**
+ * This is set if the object has been pinned due to unknown
+ * swizzling.
+ */
+ bool quirked:1;
+ } mm;
+
+ /** Breadcrumb of last rendering to the buffer.
+ * There can only be one writer, but we allow for multiple readers.
+ * If there is a writer that necessarily implies that all other
+ * read requests are complete - but we may only be lazily clearing
+ * the read requests. A read request is naturally the most recent
+ * request on a ring, so we may have two different write and read
+ * requests on one ring where the write request is older than the
+ * read request. This allows for the CPU to read from an active
+ * buffer by only waiting for the write to complete.
+ */
+ struct reservation_object *resv;
+
+ /** References from framebuffers, locks out tiling changes. */
+ unsigned long framebuffer_references;
+
+ /** Record of address bit 17 of each page at last unbind. */
+ unsigned long *bit_17;
+
+ struct i915_gem_userptr {
+ uintptr_t ptr;
+ unsigned read_only :1;
+
+ struct i915_mm_struct *mm;
+ struct i915_mmu_object *mmu_object;
+ struct work_struct *work;
+ } userptr;
+
+ /** for phys allocated objects */
+ struct drm_dma_handle *phys_handle;
+
+ struct reservation_object __builtin_resv;
+};
+
+static inline struct drm_i915_gem_object *
+to_intel_bo(struct drm_gem_object *gem)
+{
+ /* Assert that to_intel_bo(NULL) == NULL */
+ BUILD_BUG_ON(offsetof(struct drm_i915_gem_object, base));
+
+ return container_of(gem, struct drm_i915_gem_object, base);
+}
+
+/**
+ * i915_gem_object_lookup_rcu - look up a temporary GEM object from its handle
+ * @filp: DRM file private date
+ * @handle: userspace handle
+ *
+ * Returns:
+ *
+ * A pointer to the object named by the handle if such exists on @filp, NULL
+ * otherwise. This object is only valid whilst under the RCU read lock, and
+ * note carefully the object may be in the process of being destroyed.
+ */
+static inline struct drm_i915_gem_object *
+i915_gem_object_lookup_rcu(struct drm_file *file, u32 handle)
+{
+#ifdef CONFIG_LOCKDEP
+ WARN_ON(debug_locks && !lock_is_held(&rcu_lock_map));
+#endif
+ return idr_find(&file->object_idr, handle);
+}
+
+static inline struct drm_i915_gem_object *
+i915_gem_object_lookup(struct drm_file *file, u32 handle)
+{
+ struct drm_i915_gem_object *obj;
+
+ rcu_read_lock();
+ obj = i915_gem_object_lookup_rcu(file, handle);
+ if (obj && !kref_get_unless_zero(&obj->base.refcount))
+ obj = NULL;
+ rcu_read_unlock();
+
+ return obj;
+}
+
+__deprecated
+extern struct drm_gem_object *
+drm_gem_object_lookup(struct drm_file *file, u32 handle);
+
+__attribute__((nonnull))
+static inline struct drm_i915_gem_object *
+i915_gem_object_get(struct drm_i915_gem_object *obj)
+{
+ drm_gem_object_reference(&obj->base);
+ return obj;
+}
+
+__deprecated
+extern void drm_gem_object_reference(struct drm_gem_object *);
+
+__attribute__((nonnull))
+static inline void
+i915_gem_object_put(struct drm_i915_gem_object *obj)
+{
+ __drm_gem_object_unreference(&obj->base);
+}
+
+__deprecated
+extern void drm_gem_object_unreference(struct drm_gem_object *);
+
+__deprecated
+extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
+
+static inline bool
+i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
+{
+ return atomic_read(&obj->base.refcount.refcount) == 0;
+}
+
+static inline bool
+i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
+{
+ return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
+}
+
+static inline bool
+i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
+{
+ return obj->ops->flags & I915_GEM_OBJECT_IS_SHRINKABLE;
+}
+
+static inline bool
+i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
+{
+ return obj->active_count;
+}
+
+static inline bool
+i915_gem_object_has_active_reference(const struct drm_i915_gem_object *obj)
+{
+ return test_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+static inline void
+i915_gem_object_set_active_reference(struct drm_i915_gem_object *obj)
+{
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+ __set_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+static inline void
+i915_gem_object_clear_active_reference(struct drm_i915_gem_object *obj)
+{
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+ __clear_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj);
+
+static inline unsigned int
+i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
+{
+ return obj->tiling_and_stride & TILING_MASK;
+}
+
+static inline bool
+i915_gem_object_is_tiled(struct drm_i915_gem_object *obj)
+{
+ return i915_gem_object_get_tiling(obj) != I915_TILING_NONE;
+}
+
+static inline unsigned int
+i915_gem_object_get_stride(struct drm_i915_gem_object *obj)
+{
+ return obj->tiling_and_stride & STRIDE_MASK;
+}
+
+static inline struct intel_engine_cs *
+i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj)
+{
+ struct intel_engine_cs *engine = NULL;
+ struct dma_fence *fence;
+
+ rcu_read_lock();
+ fence = reservation_object_get_excl_rcu(obj->resv);
+ rcu_read_unlock();
+
+ if (fence && dma_fence_is_i915(fence) && !dma_fence_is_signaled(fence))
+ engine = to_request(fence)->engine;
+ dma_fence_put(fence);
+
+ return engine;
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index 95b7e9afd5f8..5af19b0bf713 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -28,17 +28,19 @@
#include "i915_drv.h"
#include "intel_renderstate.h"
-struct render_state {
+struct intel_render_state {
const struct intel_renderstate_rodata *rodata;
struct i915_vma *vma;
- u32 aux_batch_size;
- u32 aux_batch_offset;
+ u32 batch_offset;
+ u32 batch_size;
+ u32 aux_offset;
+ u32 aux_size;
};
static const struct intel_renderstate_rodata *
-render_state_get_rodata(const struct drm_i915_gem_request *req)
+render_state_get_rodata(const struct intel_engine_cs *engine)
{
- switch (INTEL_GEN(req->i915)) {
+ switch (INTEL_GEN(engine->i915)) {
case 6:
return &gen6_null_state;
case 7:
@@ -63,29 +65,26 @@ render_state_get_rodata(const struct drm_i915_gem_request *req)
*/
#define OUT_BATCH(batch, i, val) \
do { \
- if (WARN_ON((i) >= PAGE_SIZE / sizeof(u32))) { \
- ret = -ENOSPC; \
- goto err_out; \
- } \
+ if ((i) >= PAGE_SIZE / sizeof(u32)) \
+ goto err; \
(batch)[(i)++] = (val); \
} while(0)
-static int render_state_setup(struct render_state *so)
+static int render_state_setup(struct intel_render_state *so,
+ struct drm_i915_private *i915)
{
- struct drm_device *dev = so->vma->vm->dev;
const struct intel_renderstate_rodata *rodata = so->rodata;
- const bool has_64bit_reloc = INTEL_GEN(dev) >= 8;
+ struct drm_i915_gem_object *obj = so->vma->obj;
unsigned int i = 0, reloc_index = 0;
- struct page *page;
+ unsigned int needs_clflush;
u32 *d;
int ret;
- ret = i915_gem_object_set_to_cpu_domain(so->vma->obj, true);
+ ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
if (ret)
return ret;
- page = i915_gem_object_get_dirty_page(so->vma->obj, 0);
- d = kmap(page);
+ d = kmap_atomic(i915_gem_object_get_dirty_page(obj, 0));
while (i < rodata->batch_items) {
u32 s = rodata->batch[i];
@@ -93,12 +92,10 @@ static int render_state_setup(struct render_state *so)
if (i * 4 == rodata->reloc[reloc_index]) {
u64 r = s + so->vma->node.start;
s = lower_32_bits(r);
- if (has_64bit_reloc) {
+ if (HAS_64BIT_RELOC(i915)) {
if (i + 1 >= rodata->batch_items ||
- rodata->batch[i + 1] != 0) {
- ret = -EINVAL;
- goto err_out;
- }
+ rodata->batch[i + 1] != 0)
+ goto err;
d[i++] = s;
s = upper_32_bits(r);
@@ -110,12 +107,20 @@ static int render_state_setup(struct render_state *so)
d[i++] = s;
}
+ if (rodata->reloc[reloc_index] != -1) {
+ DRM_ERROR("only %d relocs resolved\n", reloc_index);
+ goto err;
+ }
+
+ so->batch_offset = so->vma->node.start;
+ so->batch_size = rodata->batch_items * sizeof(u32);
+
while (i % CACHELINE_DWORDS)
OUT_BATCH(d, i, MI_NOOP);
- so->aux_batch_offset = i * sizeof(u32);
+ so->aux_offset = i * sizeof(u32);
- if (HAS_POOLED_EU(dev)) {
+ if (HAS_POOLED_EU(i915)) {
/*
* We always program 3x6 pool config but depending upon which
* subslice is disabled HW drops down to appropriate config
@@ -143,88 +148,133 @@ static int render_state_setup(struct render_state *so)
}
OUT_BATCH(d, i, MI_BATCH_BUFFER_END);
- so->aux_batch_size = (i * sizeof(u32)) - so->aux_batch_offset;
-
+ so->aux_size = i * sizeof(u32) - so->aux_offset;
+ so->aux_offset += so->batch_offset;
/*
* Since we are sending length, we need to strictly conform to
* all requirements. For Gen2 this must be a multiple of 8.
*/
- so->aux_batch_size = ALIGN(so->aux_batch_size, 8);
-
- kunmap(page);
-
- ret = i915_gem_object_set_to_gtt_domain(so->vma->obj, false);
- if (ret)
- return ret;
-
- if (rodata->reloc[reloc_index] != -1) {
- DRM_ERROR("only %d relocs resolved\n", reloc_index);
- return -EINVAL;
- }
+ so->aux_size = ALIGN(so->aux_size, 8);
- return 0;
+ if (needs_clflush)
+ drm_clflush_virt_range(d, i * sizeof(u32));
+ kunmap_atomic(d);
-err_out:
- kunmap(page);
+ ret = i915_gem_object_set_to_gtt_domain(obj, false);
+out:
+ i915_gem_obj_finish_shmem_access(obj);
return ret;
+
+err:
+ kunmap_atomic(d);
+ ret = -EINVAL;
+ goto out;
}
#undef OUT_BATCH
-int i915_gem_render_state_init(struct drm_i915_gem_request *req)
+int i915_gem_render_state_init(struct intel_engine_cs *engine)
{
- struct render_state so;
+ struct intel_render_state *so;
+ const struct intel_renderstate_rodata *rodata;
struct drm_i915_gem_object *obj;
int ret;
- if (WARN_ON(req->engine->id != RCS))
- return -ENOENT;
+ if (engine->id != RCS)
+ return 0;
- so.rodata = render_state_get_rodata(req);
- if (!so.rodata)
+ rodata = render_state_get_rodata(engine);
+ if (!rodata)
return 0;
- if (so.rodata->batch_items * 4 > 4096)
+ if (rodata->batch_items * 4 > 4096)
return -EINVAL;
- obj = i915_gem_object_create(&req->i915->drm, 4096);
- if (IS_ERR(obj))
- return PTR_ERR(obj);
+ so = kmalloc(sizeof(*so), GFP_KERNEL);
+ if (!so)
+ return -ENOMEM;
- so.vma = i915_vma_create(obj, &req->i915->ggtt.base, NULL);
- if (IS_ERR(so.vma)) {
- ret = PTR_ERR(so.vma);
- goto err_obj;
+ obj = i915_gem_object_create_internal(engine->i915, 4096);
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
+ goto err_free;
}
- ret = i915_vma_pin(so.vma, 0, 0, PIN_GLOBAL);
- if (ret)
+ so->vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL);
+ if (IS_ERR(so->vma)) {
+ ret = PTR_ERR(so->vma);
goto err_obj;
+ }
+
+ so->rodata = rodata;
+ engine->render_state = so;
+ return 0;
+
+err_obj:
+ i915_gem_object_put(obj);
+err_free:
+ kfree(so);
+ return ret;
+}
+
+int i915_gem_render_state_emit(struct drm_i915_gem_request *req)
+{
+ struct intel_render_state *so;
+ int ret;
+
+ lockdep_assert_held(&req->i915->drm.struct_mutex);
- ret = render_state_setup(&so);
+ so = req->engine->render_state;
+ if (!so)
+ return 0;
+
+ /* Recreate the page after shrinking */
+ if (!so->vma->obj->mm.pages)
+ so->batch_offset = -1;
+
+ ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
if (ret)
- goto err_unpin;
+ return ret;
+
+ if (so->vma->node.start != so->batch_offset) {
+ ret = render_state_setup(so, req->i915);
+ if (ret)
+ goto err_unpin;
+ }
- ret = req->engine->emit_bb_start(req, so.vma->node.start,
- so.rodata->batch_items * 4,
+ ret = req->engine->emit_bb_start(req,
+ so->batch_offset, so->batch_size,
I915_DISPATCH_SECURE);
if (ret)
goto err_unpin;
- if (so.aux_batch_size > 8) {
+ if (so->aux_size > 8) {
ret = req->engine->emit_bb_start(req,
- (so.vma->node.start +
- so.aux_batch_offset),
- so.aux_batch_size,
+ so->aux_offset, so->aux_size,
I915_DISPATCH_SECURE);
if (ret)
goto err_unpin;
}
- i915_vma_move_to_active(so.vma, req, 0);
+ i915_vma_move_to_active(so->vma, req, 0);
err_unpin:
- i915_vma_unpin(so.vma);
-err_obj:
- i915_gem_object_put(obj);
+ i915_vma_unpin(so->vma);
return ret;
}
+
+void i915_gem_render_state_fini(struct intel_engine_cs *engine)
+{
+ struct intel_render_state *so;
+ struct drm_i915_gem_object *obj;
+
+ so = fetch_and_zero(&engine->render_state);
+ if (!so)
+ return;
+
+ obj = so->vma->obj;
+
+ i915_vma_close(so->vma);
+ __i915_gem_object_release_unless_active(obj);
+
+ kfree(so);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.h b/drivers/gpu/drm/i915/i915_gem_render_state.h
index 18cce3f06e9c..87481845799d 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.h
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.h
@@ -26,6 +26,8 @@
struct drm_i915_gem_request;
-int i915_gem_render_state_init(struct drm_i915_gem_request *req);
+int i915_gem_render_state_init(struct intel_engine_cs *engine);
+int i915_gem_render_state_emit(struct drm_i915_gem_request *req);
+void i915_gem_render_state_fini(struct intel_engine_cs *engine);
#endif /* _I915_GEM_RENDER_STATE_H_ */
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 8832f8ec1583..b8f403faadbb 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -23,31 +23,26 @@
*/
#include <linux/prefetch.h>
+#include <linux/dma-fence-array.h>
#include "i915_drv.h"
-static const char *i915_fence_get_driver_name(struct fence *fence)
+static const char *i915_fence_get_driver_name(struct dma_fence *fence)
{
return "i915";
}
-static const char *i915_fence_get_timeline_name(struct fence *fence)
+static const char *i915_fence_get_timeline_name(struct dma_fence *fence)
{
- /* Timelines are bound by eviction to a VM. However, since
- * we only have a global seqno at the moment, we only have
- * a single timeline. Note that each timeline will have
- * multiple execution contexts (fence contexts) as we allow
- * engines within a single timeline to execute in parallel.
- */
- return "global";
+ return to_request(fence)->timeline->common->name;
}
-static bool i915_fence_signaled(struct fence *fence)
+static bool i915_fence_signaled(struct dma_fence *fence)
{
return i915_gem_request_completed(to_request(fence));
}
-static bool i915_fence_enable_signaling(struct fence *fence)
+static bool i915_fence_enable_signaling(struct dma_fence *fence)
{
if (i915_fence_signaled(fence))
return false;
@@ -56,63 +51,27 @@ static bool i915_fence_enable_signaling(struct fence *fence)
return true;
}
-static signed long i915_fence_wait(struct fence *fence,
+static signed long i915_fence_wait(struct dma_fence *fence,
bool interruptible,
- signed long timeout_jiffies)
+ signed long timeout)
{
- s64 timeout_ns, *timeout;
- int ret;
-
- if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT) {
- timeout_ns = jiffies_to_nsecs(timeout_jiffies);
- timeout = &timeout_ns;
- } else {
- timeout = NULL;
- }
-
- ret = i915_wait_request(to_request(fence),
- interruptible, timeout,
- NO_WAITBOOST);
- if (ret == -ETIME)
- return 0;
-
- if (ret < 0)
- return ret;
-
- if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT)
- timeout_jiffies = nsecs_to_jiffies(timeout_ns);
-
- return timeout_jiffies;
+ return i915_wait_request(to_request(fence), interruptible, timeout);
}
-static void i915_fence_value_str(struct fence *fence, char *str, int size)
-{
- snprintf(str, size, "%u", fence->seqno);
-}
-
-static void i915_fence_timeline_value_str(struct fence *fence, char *str,
- int size)
-{
- snprintf(str, size, "%u",
- intel_engine_get_seqno(to_request(fence)->engine));
-}
-
-static void i915_fence_release(struct fence *fence)
+static void i915_fence_release(struct dma_fence *fence)
{
struct drm_i915_gem_request *req = to_request(fence);
kmem_cache_free(req->i915->requests, req);
}
-const struct fence_ops i915_fence_ops = {
+const struct dma_fence_ops i915_fence_ops = {
.get_driver_name = i915_fence_get_driver_name,
.get_timeline_name = i915_fence_get_timeline_name,
.enable_signaling = i915_fence_enable_signaling,
.signaled = i915_fence_signaled,
.wait = i915_fence_wait,
.release = i915_fence_release,
- .fence_value_str = i915_fence_value_str,
- .timeline_value_str = i915_fence_timeline_value_str,
};
int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
@@ -154,6 +113,82 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
spin_unlock(&file_priv->mm.lock);
}
+static struct i915_dependency *
+i915_dependency_alloc(struct drm_i915_private *i915)
+{
+ return kmem_cache_alloc(i915->dependencies, GFP_KERNEL);
+}
+
+static void
+i915_dependency_free(struct drm_i915_private *i915,
+ struct i915_dependency *dep)
+{
+ kmem_cache_free(i915->dependencies, dep);
+}
+
+static void
+__i915_priotree_add_dependency(struct i915_priotree *pt,
+ struct i915_priotree *signal,
+ struct i915_dependency *dep,
+ unsigned long flags)
+{
+ INIT_LIST_HEAD(&dep->dfs_link);
+ list_add(&dep->wait_link, &signal->waiters_list);
+ list_add(&dep->signal_link, &pt->signalers_list);
+ dep->signaler = signal;
+ dep->flags = flags;
+}
+
+static int
+i915_priotree_add_dependency(struct drm_i915_private *i915,
+ struct i915_priotree *pt,
+ struct i915_priotree *signal)
+{
+ struct i915_dependency *dep;
+
+ dep = i915_dependency_alloc(i915);
+ if (!dep)
+ return -ENOMEM;
+
+ __i915_priotree_add_dependency(pt, signal, dep, I915_DEPENDENCY_ALLOC);
+ return 0;
+}
+
+static void
+i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt)
+{
+ struct i915_dependency *dep, *next;
+
+ GEM_BUG_ON(!RB_EMPTY_NODE(&pt->node));
+
+ /* Everyone we depended upon (the fences we wait to be signaled)
+ * should retire before us and remove themselves from our list.
+ * However, retirement is run independently on each timeline and
+ * so we may be called out-of-order.
+ */
+ list_for_each_entry_safe(dep, next, &pt->signalers_list, signal_link) {
+ list_del(&dep->wait_link);
+ if (dep->flags & I915_DEPENDENCY_ALLOC)
+ i915_dependency_free(i915, dep);
+ }
+
+ /* Remove ourselves from everyone who depends upon us */
+ list_for_each_entry_safe(dep, next, &pt->waiters_list, wait_link) {
+ list_del(&dep->signal_link);
+ if (dep->flags & I915_DEPENDENCY_ALLOC)
+ i915_dependency_free(i915, dep);
+ }
+}
+
+static void
+i915_priotree_init(struct i915_priotree *pt)
+{
+ INIT_LIST_HEAD(&pt->signalers_list);
+ INIT_LIST_HEAD(&pt->waiters_list);
+ RB_CLEAR_NODE(&pt->node);
+ pt->priority = INT_MIN;
+}
+
void i915_gem_retire_noop(struct i915_gem_active *active,
struct drm_i915_gem_request *request)
{
@@ -164,8 +199,17 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
{
struct i915_gem_active *active, *next;
+ lockdep_assert_held(&request->i915->drm.struct_mutex);
+ GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit));
+ GEM_BUG_ON(!i915_sw_fence_signaled(&request->execute));
+ GEM_BUG_ON(!i915_gem_request_completed(request));
+ GEM_BUG_ON(!request->i915->gt.active_requests);
+
trace_i915_gem_request_retire(request);
- list_del(&request->link);
+
+ spin_lock_irq(&request->engine->timeline->lock);
+ list_del_init(&request->link);
+ spin_unlock_irq(&request->engine->timeline->lock);
/* We know the GPU must have read the request to have
* sent us the seqno + interrupt, so use the position
@@ -177,6 +221,12 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
*/
list_del(&request->ring_link);
request->ring->last_retired_head = request->postfix;
+ if (!--request->i915->gt.active_requests) {
+ GEM_BUG_ON(!request->i915->gt.awake);
+ mod_delayed_work(request->i915->wq,
+ &request->i915->gt.idle_work,
+ msecs_to_jiffies(100));
+ }
/* Walk through the active list, calling retire on each. This allows
* objects to track their GPU activity and mark themselves as idle
@@ -214,6 +264,10 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
}
i915_gem_context_put(request->ctx);
+
+ dma_fence_signal(&request->fence);
+
+ i915_priotree_fini(request->i915, &request->priotree);
i915_gem_request_put(request);
}
@@ -223,10 +277,11 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req)
struct drm_i915_gem_request *tmp;
lockdep_assert_held(&req->i915->drm.struct_mutex);
- GEM_BUG_ON(list_empty(&req->link));
+ if (list_empty(&req->link))
+ return;
do {
- tmp = list_first_entry(&engine->request_list,
+ tmp = list_first_entry(&engine->timeline->requests,
typeof(*tmp), link);
i915_gem_request_retire(tmp);
@@ -253,39 +308,50 @@ static int i915_gem_check_wedge(struct drm_i915_private *dev_priv)
return 0;
}
-static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno)
+static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno)
{
+ struct i915_gem_timeline *timeline = &i915->gt.global_timeline;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int ret;
/* Carefully retire all requests without writing to the rings */
- for_each_engine(engine, dev_priv) {
- ret = intel_engine_idle(engine,
- I915_WAIT_INTERRUPTIBLE |
- I915_WAIT_LOCKED);
- if (ret)
- return ret;
- }
- i915_gem_retire_requests(dev_priv);
+ ret = i915_gem_wait_for_idle(i915,
+ I915_WAIT_INTERRUPTIBLE |
+ I915_WAIT_LOCKED);
+ if (ret)
+ return ret;
+
+ i915_gem_retire_requests(i915);
+ GEM_BUG_ON(i915->gt.active_requests > 1);
/* If the seqno wraps around, we need to clear the breadcrumb rbtree */
- if (!i915_seqno_passed(seqno, dev_priv->next_seqno)) {
- while (intel_kick_waiters(dev_priv) ||
- intel_kick_signalers(dev_priv))
- yield();
+ if (!i915_seqno_passed(seqno, atomic_read(&timeline->next_seqno))) {
+ while (intel_breadcrumbs_busy(i915))
+ cond_resched(); /* spin until threads are complete */
}
+ atomic_set(&timeline->next_seqno, seqno);
/* Finally reset hw state */
- for_each_engine(engine, dev_priv)
- intel_engine_init_seqno(engine, seqno);
+ for_each_engine(engine, i915, id)
+ intel_engine_init_global_seqno(engine, seqno);
+
+ list_for_each_entry(timeline, &i915->gt.timelines, link) {
+ for_each_engine(engine, i915, id) {
+ struct intel_timeline *tl = &timeline->engine[id];
+
+ memset(tl->sync_seqno, 0, sizeof(tl->sync_seqno));
+ }
+ }
return 0;
}
-int i915_gem_set_seqno(struct drm_device *dev, u32 seqno)
+int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int ret;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
if (seqno == 0)
return -EINVAL;
@@ -293,29 +359,87 @@ int i915_gem_set_seqno(struct drm_device *dev, u32 seqno)
/* HWS page needs to be set less than what we
* will inject to ring
*/
- ret = i915_gem_init_seqno(dev_priv, seqno - 1);
- if (ret)
+ return i915_gem_init_global_seqno(dev_priv, seqno - 1);
+}
+
+static int reserve_global_seqno(struct drm_i915_private *i915)
+{
+ u32 active_requests = ++i915->gt.active_requests;
+ u32 next_seqno = atomic_read(&i915->gt.global_timeline.next_seqno);
+ int ret;
+
+ /* Reservation is fine until we need to wrap around */
+ if (likely(next_seqno + active_requests > next_seqno))
+ return 0;
+
+ ret = i915_gem_init_global_seqno(i915, 0);
+ if (ret) {
+ i915->gt.active_requests--;
return ret;
+ }
- dev_priv->next_seqno = seqno;
return 0;
}
-static int i915_gem_get_seqno(struct drm_i915_private *dev_priv, u32 *seqno)
+static u32 __timeline_get_seqno(struct i915_gem_timeline *tl)
{
- /* reserve 0 for non-seqno */
- if (unlikely(dev_priv->next_seqno == 0)) {
- int ret;
+ /* next_seqno only incremented under a mutex */
+ return ++tl->next_seqno.counter;
+}
- ret = i915_gem_init_seqno(dev_priv, 0);
- if (ret)
- return ret;
+static u32 timeline_get_seqno(struct i915_gem_timeline *tl)
+{
+ return atomic_inc_return(&tl->next_seqno);
+}
- dev_priv->next_seqno = 1;
- }
+void __i915_gem_request_submit(struct drm_i915_gem_request *request)
+{
+ struct intel_engine_cs *engine = request->engine;
+ struct intel_timeline *timeline;
+ u32 seqno;
- *seqno = dev_priv->next_seqno++;
- return 0;
+ /* Transfer from per-context onto the global per-engine timeline */
+ timeline = engine->timeline;
+ GEM_BUG_ON(timeline == request->timeline);
+ assert_spin_locked(&timeline->lock);
+
+ seqno = timeline_get_seqno(timeline->common);
+ GEM_BUG_ON(!seqno);
+ GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno));
+
+ GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, seqno));
+ request->previous_seqno = timeline->last_submitted_seqno;
+ timeline->last_submitted_seqno = seqno;
+
+ /* We may be recursing from the signal callback of another i915 fence */
+ spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING);
+ request->global_seqno = seqno;
+ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags))
+ intel_engine_enable_signaling(request);
+ spin_unlock(&request->lock);
+
+ GEM_BUG_ON(!request->global_seqno);
+ engine->emit_breadcrumb(request,
+ request->ring->vaddr + request->postfix);
+
+ spin_lock(&request->timeline->lock);
+ list_move_tail(&request->link, &timeline->requests);
+ spin_unlock(&request->timeline->lock);
+
+ i915_sw_fence_commit(&request->execute);
+}
+
+void i915_gem_request_submit(struct drm_i915_gem_request *request)
+{
+ struct intel_engine_cs *engine = request->engine;
+ unsigned long flags;
+
+ /* Will be called from irq-context when using foreign fences. */
+ spin_lock_irqsave(&engine->timeline->lock, flags);
+
+ __i915_gem_request_submit(request);
+
+ spin_unlock_irqrestore(&engine->timeline->lock, flags);
}
static int __i915_sw_fence_call
@@ -324,15 +448,31 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
struct drm_i915_gem_request *request =
container_of(fence, typeof(*request), submit);
- /* Will be called from irq-context when using foreign DMA fences */
-
switch (state) {
case FENCE_COMPLETE:
- request->engine->last_submitted_seqno = request->fence.seqno;
request->engine->submit_request(request);
break;
case FENCE_FREE:
+ i915_gem_request_put(request);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int __i915_sw_fence_call
+execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
+{
+ struct drm_i915_gem_request *request =
+ container_of(fence, typeof(*request), execute);
+
+ switch (state) {
+ case FENCE_COMPLETE:
+ break;
+
+ case FENCE_FREE:
+ i915_gem_request_put(request);
break;
}
@@ -357,9 +497,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
{
struct drm_i915_private *dev_priv = engine->i915;
struct drm_i915_gem_request *req;
- u32 seqno;
int ret;
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
/* ABI: Before userspace accesses the GPU (e.g. execbuffer), report
* EIO if the GPU is already wedged, or EAGAIN to drop the struct_mutex
* and restart.
@@ -368,10 +509,14 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
if (ret)
return ERR_PTR(ret);
+ ret = reserve_global_seqno(dev_priv);
+ if (ret)
+ return ERR_PTR(ret);
+
/* Move the oldest request to the slab-cache (if not in use!) */
- req = list_first_entry_or_null(&engine->request_list,
+ req = list_first_entry_or_null(&engine->timeline->requests,
typeof(*req), link);
- if (req && i915_gem_request_completed(req))
+ if (req && __i915_gem_request_completed(req))
i915_gem_request_retire(req);
/* Beware: Dragons be flying overhead.
@@ -382,13 +527,13 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
* of being read by __i915_gem_active_get_rcu(). As such,
* we have to be very careful when overwriting the contents. During
* the RCU lookup, we change chase the request->engine pointer,
- * read the request->fence.seqno and increment the reference count.
+ * read the request->global_seqno and increment the reference count.
*
* The reference count is incremented atomically. If it is zero,
* the lookup knows the request is unallocated and complete. Otherwise,
* it is either still in use, or has been reallocated and reset
- * with fence_init(). This increment is safe for release as we check
- * that the request we have a reference to and matches the active
+ * with dma_fence_init(). This increment is safe for release as we
+ * check that the request we have a reference to and matches the active
* request.
*
* Before we increment the refcount, we chase the request->engine
@@ -403,21 +548,32 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
* Do not use kmem_cache_zalloc() here!
*/
req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL);
- if (!req)
- return ERR_PTR(-ENOMEM);
+ if (!req) {
+ ret = -ENOMEM;
+ goto err_unreserve;
+ }
- ret = i915_gem_get_seqno(dev_priv, &seqno);
- if (ret)
- goto err;
+ req->timeline = i915_gem_context_lookup_timeline(ctx, engine);
+ GEM_BUG_ON(req->timeline == engine->timeline);
spin_lock_init(&req->lock);
- fence_init(&req->fence,
- &i915_fence_ops,
- &req->lock,
- engine->fence_context,
- seqno);
+ dma_fence_init(&req->fence,
+ &i915_fence_ops,
+ &req->lock,
+ req->timeline->fence_context,
+ __timeline_get_seqno(req->timeline->common));
+
+ /* We bump the ref for the fence chain */
+ i915_sw_fence_init(&i915_gem_request_get(req)->submit, submit_notify);
+ i915_sw_fence_init(&i915_gem_request_get(req)->execute, execute_notify);
+
+ /* Ensure that the execute fence completes after the submit fence -
+ * as we complete the execute fence from within the submit fence
+ * callback, its completion would otherwise be visible first.
+ */
+ i915_sw_fence_await_sw_fence(&req->execute, &req->submit, &req->execq);
- i915_sw_fence_init(&req->submit, submit_notify);
+ i915_priotree_init(&req->priotree);
INIT_LIST_HEAD(&req->active_list);
req->i915 = dev_priv;
@@ -425,6 +581,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
req->ctx = i915_gem_context_get(ctx);
/* No zalloc, must clear what we need by hand */
+ req->global_seqno = 0;
req->previous_context = NULL;
req->file_priv = NULL;
req->batch = NULL;
@@ -437,6 +594,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
* away, e.g. because a GPU scheduler has deferred it.
*/
req->reserved_space = MIN_SPACE_FOR_ADD_REQUEST;
+ GEM_BUG_ON(req->reserved_space < engine->emit_breadcrumb_sz);
if (i915.enable_execlists)
ret = intel_logical_ring_alloc_request_extras(req);
@@ -456,8 +614,9 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
err_ctx:
i915_gem_context_put(ctx);
-err:
kmem_cache_free(dev_priv->requests, req);
+err_unreserve:
+ dev_priv->gt.active_requests--;
return ERR_PTR(ret);
}
@@ -465,15 +624,36 @@ static int
i915_gem_request_await_request(struct drm_i915_gem_request *to,
struct drm_i915_gem_request *from)
{
- int idx, ret;
+ int ret;
GEM_BUG_ON(to == from);
- if (to->engine == from->engine)
+ if (to->engine->schedule) {
+ ret = i915_priotree_add_dependency(to->i915,
+ &to->priotree,
+ &from->priotree);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (to->timeline == from->timeline)
return 0;
- idx = intel_engine_sync_index(from->engine, to->engine);
- if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx])
+ if (to->engine == from->engine) {
+ ret = i915_sw_fence_await_sw_fence_gfp(&to->submit,
+ &from->submit,
+ GFP_KERNEL);
+ return ret < 0 ? ret : 0;
+ }
+
+ if (!from->global_seqno) {
+ ret = i915_sw_fence_await_dma_fence(&to->submit,
+ &from->fence, 0,
+ GFP_KERNEL);
+ return ret < 0 ? ret : 0;
+ }
+
+ if (from->global_seqno <= to->timeline->sync_seqno[from->engine->id])
return 0;
trace_i915_gem_ring_sync_to(to, from);
@@ -491,7 +671,54 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to,
return ret;
}
- from->engine->semaphore.sync_seqno[idx] = from->fence.seqno;
+ to->timeline->sync_seqno[from->engine->id] = from->global_seqno;
+ return 0;
+}
+
+int
+i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req,
+ struct dma_fence *fence)
+{
+ struct dma_fence_array *array;
+ int ret;
+ int i;
+
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return 0;
+
+ if (dma_fence_is_i915(fence))
+ return i915_gem_request_await_request(req, to_request(fence));
+
+ if (!dma_fence_is_array(fence)) {
+ ret = i915_sw_fence_await_dma_fence(&req->submit,
+ fence, I915_FENCE_TIMEOUT,
+ GFP_KERNEL);
+ return ret < 0 ? ret : 0;
+ }
+
+ /* Note that if the fence-array was created in signal-on-any mode,
+ * we should *not* decompose it into its individual fences. However,
+ * we don't currently store which mode the fence-array is operating
+ * in. Fortunately, the only user of signal-on-any is private to
+ * amdgpu and we should not see any incoming fence-array from
+ * sync-file being in signal-on-any mode.
+ */
+
+ array = to_dma_fence_array(fence);
+ for (i = 0; i < array->num_fences; i++) {
+ struct dma_fence *child = array->fences[i];
+
+ if (dma_fence_is_i915(child))
+ ret = i915_gem_request_await_request(req,
+ to_request(child));
+ else
+ ret = i915_sw_fence_await_dma_fence(&req->submit,
+ child, I915_FENCE_TIMEOUT,
+ GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
@@ -520,43 +747,52 @@ i915_gem_request_await_object(struct drm_i915_gem_request *to,
struct drm_i915_gem_object *obj,
bool write)
{
- struct i915_gem_active *active;
- unsigned long active_mask;
- int idx;
+ struct dma_fence *excl;
+ int ret = 0;
if (write) {
- active_mask = i915_gem_object_get_active(obj);
- active = obj->last_read;
+ struct dma_fence **shared;
+ unsigned int count, i;
+
+ ret = reservation_object_get_fences_rcu(obj->resv,
+ &excl, &count, &shared);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < count; i++) {
+ ret = i915_gem_request_await_dma_fence(to, shared[i]);
+ if (ret)
+ break;
+
+ dma_fence_put(shared[i]);
+ }
+
+ for (; i < count; i++)
+ dma_fence_put(shared[i]);
+ kfree(shared);
} else {
- active_mask = 1;
- active = &obj->last_write;
+ excl = reservation_object_get_excl_rcu(obj->resv);
}
- for_each_active(active_mask, idx) {
- struct drm_i915_gem_request *request;
- int ret;
-
- request = i915_gem_active_peek(&active[idx],
- &obj->base.dev->struct_mutex);
- if (!request)
- continue;
+ if (excl) {
+ if (ret == 0)
+ ret = i915_gem_request_await_dma_fence(to, excl);
- ret = i915_gem_request_await_request(to, request);
- if (ret)
- return ret;
+ dma_fence_put(excl);
}
- return 0;
+ return ret;
}
static void i915_gem_mark_busy(const struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
- dev_priv->gt.active_engines |= intel_engine_flag(engine);
if (dev_priv->gt.awake)
return;
+ GEM_BUG_ON(!dev_priv->gt.active_requests);
+
intel_runtime_pm_get_noresume(dev_priv);
dev_priv->gt.awake = true;
@@ -579,11 +815,11 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
{
struct intel_engine_cs *engine = request->engine;
struct intel_ring *ring = request->ring;
+ struct intel_timeline *timeline = request->timeline;
struct drm_i915_gem_request *prev;
- u32 request_start;
- u32 reserved_tail;
- int ret;
+ int err;
+ lockdep_assert_held(&request->i915->drm.struct_mutex);
trace_i915_gem_request_add(request);
/*
@@ -591,8 +827,6 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
* should already have been reserved in the ring buffer. Let the ring
* know that it is time to use that space up.
*/
- request_start = ring->tail;
- reserved_tail = request->reserved_space;
request->reserved_space = 0;
/*
@@ -603,10 +837,10 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
* what.
*/
if (flush_caches) {
- ret = engine->emit_flush(request, EMIT_FLUSH);
+ err = engine->emit_flush(request, EMIT_FLUSH);
/* Not allowed to fail! */
- WARN(ret, "engine->emit_flush() failed: %d!\n", ret);
+ WARN(err, "engine->emit_flush() failed: %d!\n", err);
}
/* Record the position of the start of the breadcrumb so that
@@ -614,20 +848,10 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
* GPU processing the request, we never over-estimate the
* position of the ring's HEAD.
*/
+ err = intel_ring_begin(request, engine->emit_breadcrumb_sz);
+ GEM_BUG_ON(err);
request->postfix = ring->tail;
-
- /* Not allowed to fail! */
- ret = engine->emit_request(request);
- WARN(ret, "(%s)->emit_request failed: %d!\n", engine->name, ret);
-
- /* Sanity check that the reserved size was large enough. */
- ret = ring->tail - request_start;
- if (ret < 0)
- ret += ring->size;
- WARN_ONCE(ret > reserved_tail,
- "Not enough space reserved (%d bytes) "
- "for adding the request (%d bytes)\n",
- reserved_tail, ret);
+ ring->tail += engine->emit_breadcrumb_sz * sizeof(u32);
/* Seal the request and mark it as pending execution. Note that
* we may inspect this state, without holding any locks, during
@@ -635,21 +859,46 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
* see a more recent value in the hws than we are tracking.
*/
- prev = i915_gem_active_raw(&engine->last_request,
+ prev = i915_gem_active_raw(&timeline->last_request,
&request->i915->drm.struct_mutex);
- if (prev)
+ if (prev) {
i915_sw_fence_await_sw_fence(&request->submit, &prev->submit,
&request->submitq);
+ if (engine->schedule)
+ __i915_priotree_add_dependency(&request->priotree,
+ &prev->priotree,
+ &request->dep,
+ 0);
+ }
+
+ spin_lock_irq(&timeline->lock);
+ list_add_tail(&request->link, &timeline->requests);
+ spin_unlock_irq(&timeline->lock);
+
+ GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno,
+ request->fence.seqno));
+
+ timeline->last_submitted_seqno = request->fence.seqno;
+ i915_gem_active_set(&timeline->last_request, request);
- request->emitted_jiffies = jiffies;
- request->previous_seqno = engine->last_pending_seqno;
- engine->last_pending_seqno = request->fence.seqno;
- i915_gem_active_set(&engine->last_request, request);
- list_add_tail(&request->link, &engine->request_list);
list_add_tail(&request->ring_link, &ring->request_list);
+ request->emitted_jiffies = jiffies;
i915_gem_mark_busy(engine);
+ /* Let the backend know a new request has arrived that may need
+ * to adjust the existing execution schedule due to a high priority
+ * request - i.e. we may want to preempt the current request in order
+ * to run a high priority dependency chain *before* we can execute this
+ * request.
+ *
+ * This is called before the request is ready to run so that we can
+ * decide whether to preempt the entire chain so that it is ready to
+ * run at the earliest possible convenience.
+ */
+ if (engine->schedule)
+ engine->schedule(request, request->ctx->priority);
+
local_bh_disable();
i915_sw_fence_commit(&request->submit);
local_bh_enable(); /* Kick the execlists tasklet if just scheduled */
@@ -714,7 +963,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req,
timeout_us += local_clock_us(&cpu);
do {
- if (i915_gem_request_completed(req))
+ if (__i915_gem_request_completed(req))
return true;
if (signal_pending_state(state, current))
@@ -723,82 +972,108 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req,
if (busywait_stop(timeout_us, cpu))
break;
- cpu_relax_lowlatency();
+ cpu_relax();
} while (!need_resched());
return false;
}
+static long
+__i915_request_wait_for_execute(struct drm_i915_gem_request *request,
+ unsigned int flags,
+ long timeout)
+{
+ const int state = flags & I915_WAIT_INTERRUPTIBLE ?
+ TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+ wait_queue_head_t *q = &request->i915->gpu_error.wait_queue;
+ DEFINE_WAIT(reset);
+ DEFINE_WAIT(wait);
+
+ if (flags & I915_WAIT_LOCKED)
+ add_wait_queue(q, &reset);
+
+ do {
+ prepare_to_wait(&request->execute.wait, &wait, state);
+
+ if (i915_sw_fence_done(&request->execute))
+ break;
+
+ if (flags & I915_WAIT_LOCKED &&
+ i915_reset_in_progress(&request->i915->gpu_error)) {
+ __set_current_state(TASK_RUNNING);
+ i915_reset(request->i915);
+ reset_wait_queue(q, &reset);
+ continue;
+ }
+
+ if (signal_pending_state(state, current)) {
+ timeout = -ERESTARTSYS;
+ break;
+ }
+
+ timeout = io_schedule_timeout(timeout);
+ } while (timeout);
+ finish_wait(&request->execute.wait, &wait);
+
+ if (flags & I915_WAIT_LOCKED)
+ remove_wait_queue(q, &reset);
+
+ return timeout;
+}
+
/**
* i915_wait_request - wait until execution of request has finished
- * @req: duh!
+ * @req: the request to wait upon
* @flags: how to wait
- * @timeout: in - how long to wait (NULL forever); out - how much time remaining
- * @rps: client to charge for RPS boosting
+ * @timeout: how long to wait in jiffies
+ *
+ * i915_wait_request() waits for the request to be completed, for a
+ * maximum of @timeout jiffies (with MAX_SCHEDULE_TIMEOUT implying an
+ * unbounded wait).
*
- * Note: It is of utmost importance that the passed in seqno and reset_counter
- * values have been read by the caller in an smp safe manner. Where read-side
- * locks are involved, it is sufficient to read the reset_counter before
- * unlocking the lock that protects the seqno. For lockless tricks, the
- * reset_counter _must_ be read before, and an appropriate smp_rmb must be
- * inserted.
+ * If the caller holds the struct_mutex, the caller must pass I915_WAIT_LOCKED
+ * in via the flags, and vice versa if the struct_mutex is not held, the caller
+ * must not specify that the wait is locked.
*
- * Returns 0 if the request was found within the alloted time. Else returns the
- * errno with remaining time filled in timeout argument.
+ * Returns the remaining time (in jiffies) if the request completed, which may
+ * be zero or -ETIME if the request is unfinished after the timeout expires.
+ * May return -EINTR is called with I915_WAIT_INTERRUPTIBLE and a signal is
+ * pending before the request completes.
*/
-int i915_wait_request(struct drm_i915_gem_request *req,
- unsigned int flags,
- s64 *timeout,
- struct intel_rps_client *rps)
+long i915_wait_request(struct drm_i915_gem_request *req,
+ unsigned int flags,
+ long timeout)
{
const int state = flags & I915_WAIT_INTERRUPTIBLE ?
TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
DEFINE_WAIT(reset);
struct intel_wait wait;
- unsigned long timeout_remain;
- int ret = 0;
might_sleep();
#if IS_ENABLED(CONFIG_LOCKDEP)
- GEM_BUG_ON(!!lockdep_is_held(&req->i915->drm.struct_mutex) !=
+ GEM_BUG_ON(debug_locks &&
+ !!lockdep_is_held(&req->i915->drm.struct_mutex) !=
!!(flags & I915_WAIT_LOCKED));
#endif
+ GEM_BUG_ON(timeout < 0);
if (i915_gem_request_completed(req))
- return 0;
-
- timeout_remain = MAX_SCHEDULE_TIMEOUT;
- if (timeout) {
- if (WARN_ON(*timeout < 0))
- return -EINVAL;
+ return timeout;
- if (*timeout == 0)
- return -ETIME;
-
- /* Record current time in case interrupted, or wedged */
- timeout_remain = nsecs_to_jiffies_timeout(*timeout);
- *timeout += ktime_get_raw_ns();
- }
+ if (!timeout)
+ return -ETIME;
trace_i915_gem_request_wait_begin(req);
- /* This client is about to stall waiting for the GPU. In many cases
- * this is undesirable and limits the throughput of the system, as
- * many clients cannot continue processing user input/output whilst
- * blocked. RPS autotuning may take tens of milliseconds to respond
- * to the GPU load and thus incurs additional latency for the client.
- * We can circumvent that by promoting the GPU frequency to maximum
- * before we wait. This makes the GPU throttle up much more quickly
- * (good for benchmarks and user experience, e.g. window animations),
- * but at a cost of spending more power processing the workload
- * (bad for battery). Not all clients even want their results
- * immediately and for them we should just let the GPU select its own
- * frequency to maximise efficiency. To prevent a single client from
- * forcing the clocks too high for the whole system, we only allow
- * each client to waitboost once in a busy period.
- */
- if (IS_RPS_CLIENT(rps) && INTEL_GEN(req->i915) >= 6)
- gen6_rps_boost(req->i915, rps, req->emitted_jiffies);
+ if (!i915_sw_fence_done(&req->execute)) {
+ timeout = __i915_request_wait_for_execute(req, flags, timeout);
+ if (timeout < 0)
+ goto complete;
+
+ GEM_BUG_ON(!i915_sw_fence_done(&req->execute));
+ }
+ GEM_BUG_ON(!i915_sw_fence_done(&req->submit));
+ GEM_BUG_ON(!req->global_seqno);
/* Optimistic short spin before touching IRQs */
if (i915_spin_request(req, state, 5))
@@ -808,7 +1083,7 @@ int i915_wait_request(struct drm_i915_gem_request *req,
if (flags & I915_WAIT_LOCKED)
add_wait_queue(&req->i915->gpu_error.wait_queue, &reset);
- intel_wait_init(&wait, req->fence.seqno);
+ intel_wait_init(&wait, req->global_seqno);
if (intel_engine_add_wait(req->engine, &wait))
/* In order to check that we haven't missed the interrupt
* as we enabled it, we need to kick ourselves to do a
@@ -818,16 +1093,17 @@ int i915_wait_request(struct drm_i915_gem_request *req,
for (;;) {
if (signal_pending_state(state, current)) {
- ret = -ERESTARTSYS;
+ timeout = -ERESTARTSYS;
break;
}
- timeout_remain = io_schedule_timeout(timeout_remain);
- if (timeout_remain == 0) {
- ret = -ETIME;
+ if (!timeout) {
+ timeout = -ETIME;
break;
}
+ timeout = io_schedule_timeout(timeout);
+
if (intel_wait_complete(&wait))
break;
@@ -874,74 +1150,32 @@ wakeup:
complete:
trace_i915_gem_request_wait_end(req);
- if (timeout) {
- *timeout -= ktime_get_raw_ns();
- if (*timeout < 0)
- *timeout = 0;
-
- /*
- * Apparently ktime isn't accurate enough and occasionally has a
- * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch
- * things up to make the test happy. We allow up to 1 jiffy.
- *
- * This is a regrssion from the timespec->ktime conversion.
- */
- if (ret == -ETIME && *timeout < jiffies_to_usecs(1)*1000)
- *timeout = 0;
- }
-
- if (IS_RPS_USER(rps) &&
- req->fence.seqno == req->engine->last_submitted_seqno) {
- /* The GPU is now idle and this client has stalled.
- * Since no other client has submitted a request in the
- * meantime, assume that this client is the only one
- * supplying work to the GPU but is unable to keep that
- * work supplied because it is waiting. Since the GPU is
- * then never kept fully busy, RPS autoclocking will
- * keep the clocks relatively low, causing further delays.
- * Compensate by giving the synchronous client credit for
- * a waitboost next time.
- */
- spin_lock(&req->i915->rps.client_lock);
- list_del_init(&rps->link);
- spin_unlock(&req->i915->rps.client_lock);
- }
-
- return ret;
+ return timeout;
}
-static bool engine_retire_requests(struct intel_engine_cs *engine)
+static void engine_retire_requests(struct intel_engine_cs *engine)
{
struct drm_i915_gem_request *request, *next;
- list_for_each_entry_safe(request, next, &engine->request_list, link) {
- if (!i915_gem_request_completed(request))
- return false;
+ list_for_each_entry_safe(request, next,
+ &engine->timeline->requests, link) {
+ if (!__i915_gem_request_completed(request))
+ return;
i915_gem_request_retire(request);
}
-
- return true;
}
void i915_gem_retire_requests(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
- unsigned int tmp;
+ enum intel_engine_id id;
lockdep_assert_held(&dev_priv->drm.struct_mutex);
- if (dev_priv->gt.active_engines == 0)
+ if (!dev_priv->gt.active_requests)
return;
- GEM_BUG_ON(!dev_priv->gt.awake);
-
- for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines, tmp)
- if (engine_retire_requests(engine))
- dev_priv->gt.active_engines &= ~intel_engine_flag(engine);
-
- if (dev_priv->gt.active_engines == 0)
- queue_delayed_work(dev_priv->wq,
- &dev_priv->gt.idle_work,
- msecs_to_jiffies(100));
+ for_each_engine(engine, dev_priv, id)
+ engine_retire_requests(engine);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 974bd7bcc801..e2b077df2da0 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -25,11 +25,14 @@
#ifndef I915_GEM_REQUEST_H
#define I915_GEM_REQUEST_H
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include "i915_gem.h"
#include "i915_sw_fence.h"
+struct drm_file;
+struct drm_i915_gem_object;
+
struct intel_wait {
struct rb_node node;
struct task_struct *tsk;
@@ -41,6 +44,33 @@ struct intel_signal_node {
struct intel_wait wait;
};
+struct i915_dependency {
+ struct i915_priotree *signaler;
+ struct list_head signal_link;
+ struct list_head wait_link;
+ struct list_head dfs_link;
+ unsigned long flags;
+#define I915_DEPENDENCY_ALLOC BIT(0)
+};
+
+/* Requests exist in a complex web of interdependencies. Each request
+ * has to wait for some other request to complete before it is ready to be run
+ * (e.g. we have to wait until the pixels have been rendering into a texture
+ * before we can copy from it). We track the readiness of a request in terms
+ * of fences, but we also need to keep the dependency tree for the lifetime
+ * of the request (beyond the life of an individual fence). We use the tree
+ * at various points to reorder the requests whilst keeping the requests
+ * in order with respect to their various dependencies.
+ */
+struct i915_priotree {
+ struct list_head signalers_list; /* those before us, we depend upon */
+ struct list_head waiters_list; /* those after us, they depend upon us */
+ struct rb_node node;
+ int priority;
+#define I915_PRIORITY_MAX 1024
+#define I915_PRIORITY_MIN (-I915_PRIORITY_MAX)
+};
+
/**
* Request queue structure.
*
@@ -62,7 +92,7 @@ struct intel_signal_node {
* The requests are reference counted.
*/
struct drm_i915_gem_request {
- struct fence fence;
+ struct dma_fence fence;
spinlock_t lock;
/** On Which ring this request was generated */
@@ -81,10 +111,39 @@ struct drm_i915_gem_request {
struct i915_gem_context *ctx;
struct intel_engine_cs *engine;
struct intel_ring *ring;
+ struct intel_timeline *timeline;
struct intel_signal_node signaling;
+ /* Fences for the various phases in the request's lifetime.
+ *
+ * The submit fence is used to await upon all of the request's
+ * dependencies. When it is signaled, the request is ready to run.
+ * It is used by the driver to then queue the request for execution.
+ *
+ * The execute fence is used to signal when the request has been
+ * sent to hardware.
+ *
+ * It is illegal for the submit fence of one request to wait upon the
+ * execute fence of an earlier request. It should be sufficient to
+ * wait upon the submit fence of the earlier request.
+ */
struct i915_sw_fence submit;
+ struct i915_sw_fence execute;
wait_queue_t submitq;
+ wait_queue_t execq;
+
+ /* A list of everyone we wait upon, and everyone who waits upon us.
+ * Even though we will not be submitted to the hardware before the
+ * submit fence is signaled (it waits for all external events as well
+ * as our own requests), the scheduler still needs to know the
+ * dependency tree for the lifetime of the request (from execbuf
+ * to retirement), i.e. bidirectional dependency information for the
+ * request not tied to individual fences.
+ */
+ struct i915_priotree priotree;
+ struct i915_dependency dep;
+
+ u32 global_seqno;
/** GEM sequence number associated with the previous request,
* when the HWS breadcrumb is equal to this the GPU is processing
@@ -140,14 +199,11 @@ struct drm_i915_gem_request {
struct drm_i915_file_private *file_priv;
/** file_priv list entry for this request */
struct list_head client_list;
-
- /** Link in the execlist submission queue, guarded by execlist_lock. */
- struct list_head execlist_link;
};
-extern const struct fence_ops i915_fence_ops;
+extern const struct dma_fence_ops i915_fence_ops;
-static inline bool fence_is_i915(struct fence *fence)
+static inline bool dma_fence_is_i915(const struct dma_fence *fence)
{
return fence->ops == &i915_fence_ops;
}
@@ -159,43 +215,31 @@ int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
struct drm_file *file);
void i915_gem_request_retire_upto(struct drm_i915_gem_request *req);
-static inline u32
-i915_gem_request_get_seqno(struct drm_i915_gem_request *req)
-{
- return req ? req->fence.seqno : 0;
-}
-
-static inline struct intel_engine_cs *
-i915_gem_request_get_engine(struct drm_i915_gem_request *req)
-{
- return req ? req->engine : NULL;
-}
-
static inline struct drm_i915_gem_request *
-to_request(struct fence *fence)
+to_request(struct dma_fence *fence)
{
/* We assume that NULL fence/request are interoperable */
BUILD_BUG_ON(offsetof(struct drm_i915_gem_request, fence) != 0);
- GEM_BUG_ON(fence && !fence_is_i915(fence));
+ GEM_BUG_ON(fence && !dma_fence_is_i915(fence));
return container_of(fence, struct drm_i915_gem_request, fence);
}
static inline struct drm_i915_gem_request *
i915_gem_request_get(struct drm_i915_gem_request *req)
{
- return to_request(fence_get(&req->fence));
+ return to_request(dma_fence_get(&req->fence));
}
static inline struct drm_i915_gem_request *
i915_gem_request_get_rcu(struct drm_i915_gem_request *req)
{
- return to_request(fence_get_rcu(&req->fence));
+ return to_request(dma_fence_get_rcu(&req->fence));
}
static inline void
i915_gem_request_put(struct drm_i915_gem_request *req)
{
- fence_put(&req->fence);
+ dma_fence_put(&req->fence);
}
static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst,
@@ -214,6 +258,8 @@ int
i915_gem_request_await_object(struct drm_i915_gem_request *to,
struct drm_i915_gem_object *obj,
bool write);
+int i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req,
+ struct dma_fence *fence);
void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches);
#define i915_add_request(req) \
@@ -221,18 +267,21 @@ void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches);
#define i915_add_request_no_flush(req) \
__i915_add_request(req, false)
+void __i915_gem_request_submit(struct drm_i915_gem_request *request);
+void i915_gem_request_submit(struct drm_i915_gem_request *request);
+
struct intel_rps_client;
#define NO_WAITBOOST ERR_PTR(-1)
#define IS_RPS_CLIENT(p) (!IS_ERR(p))
#define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p))
-int i915_wait_request(struct drm_i915_gem_request *req,
- unsigned int flags,
- s64 *timeout,
- struct intel_rps_client *rps)
+long i915_wait_request(struct drm_i915_gem_request *req,
+ unsigned int flags,
+ long timeout)
__attribute__((nonnull(1)));
#define I915_WAIT_INTERRUPTIBLE BIT(0)
#define I915_WAIT_LOCKED BIT(1) /* struct_mutex held, handle GPU reset */
+#define I915_WAIT_ALL BIT(2) /* used by i915_gem_object_wait() */
static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine);
@@ -245,17 +294,37 @@ static inline bool i915_seqno_passed(u32 seq1, u32 seq2)
}
static inline bool
-i915_gem_request_started(const struct drm_i915_gem_request *req)
+__i915_gem_request_started(const struct drm_i915_gem_request *req)
{
+ GEM_BUG_ON(!req->global_seqno);
return i915_seqno_passed(intel_engine_get_seqno(req->engine),
req->previous_seqno);
}
static inline bool
-i915_gem_request_completed(const struct drm_i915_gem_request *req)
+i915_gem_request_started(const struct drm_i915_gem_request *req)
{
+ if (!req->global_seqno)
+ return false;
+
+ return __i915_gem_request_started(req);
+}
+
+static inline bool
+__i915_gem_request_completed(const struct drm_i915_gem_request *req)
+{
+ GEM_BUG_ON(!req->global_seqno);
return i915_seqno_passed(intel_engine_get_seqno(req->engine),
- req->fence.seqno);
+ req->global_seqno);
+}
+
+static inline bool
+i915_gem_request_completed(const struct drm_i915_gem_request *req)
+{
+ if (!req->global_seqno)
+ return false;
+
+ return __i915_gem_request_completed(req);
}
bool __i915_spin_request(const struct drm_i915_gem_request *request,
@@ -263,7 +332,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *request,
static inline bool i915_spin_request(const struct drm_i915_gem_request *request,
int state, unsigned long timeout_us)
{
- return (i915_gem_request_started(request) &&
+ return (__i915_gem_request_started(request) &&
__i915_spin_request(request, state, timeout_us));
}
@@ -497,7 +566,7 @@ __i915_gem_active_get_rcu(const struct i915_gem_active *active)
* compiler.
*
* The atomic operation at the heart of
- * i915_gem_request_get_rcu(), see fence_get_rcu(), is
+ * i915_gem_request_get_rcu(), see dma_fence_get_rcu(), is
* atomic_inc_not_zero() which is only a full memory barrier
* when successful. That is, if i915_gem_request_get_rcu()
* returns the request (and so with the reference counted
@@ -552,53 +621,13 @@ i915_gem_active_isset(const struct i915_gem_active *active)
}
/**
- * i915_gem_active_is_idle - report whether the active tracker is idle
- * @active - the active tracker
- *
- * i915_gem_active_is_idle() returns true if the active tracker is currently
- * unassigned or if the request is complete (but not yet retired). Requires
- * the caller to hold struct_mutex (but that can be relaxed if desired).
- */
-static inline bool
-i915_gem_active_is_idle(const struct i915_gem_active *active,
- struct mutex *mutex)
-{
- return !i915_gem_active_peek(active, mutex);
-}
-
-/**
* i915_gem_active_wait - waits until the request is completed
* @active - the active request on which to wait
- *
- * i915_gem_active_wait() waits until the request is completed before
- * returning. Note that it does not guarantee that the request is
- * retired first, see i915_gem_active_retire().
- *
- * i915_gem_active_wait() returns immediately if the active
- * request is already complete.
- */
-static inline int __must_check
-i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex)
-{
- struct drm_i915_gem_request *request;
-
- request = i915_gem_active_peek(active, mutex);
- if (!request)
- return 0;
-
- return i915_wait_request(request,
- I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
- NULL, NULL);
-}
-
-/**
- * i915_gem_active_wait_unlocked - waits until the request is completed
- * @active - the active request on which to wait
* @flags - how to wait
* @timeout - how long to wait at most
* @rps - userspace client to charge for a waitboost
*
- * i915_gem_active_wait_unlocked() waits until the request is completed before
+ * i915_gem_active_wait() waits until the request is completed before
* returning, without requiring any locks to be held. Note that it does not
* retire any requests before returning.
*
@@ -614,21 +643,18 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex)
* Returns 0 if successful, or a negative error code.
*/
static inline int
-i915_gem_active_wait_unlocked(const struct i915_gem_active *active,
- unsigned int flags,
- s64 *timeout,
- struct intel_rps_client *rps)
+i915_gem_active_wait(const struct i915_gem_active *active, unsigned int flags)
{
struct drm_i915_gem_request *request;
- int ret = 0;
+ long ret = 0;
request = i915_gem_active_get_unlocked(active);
if (request) {
- ret = i915_wait_request(request, flags, timeout, rps);
+ ret = i915_wait_request(request, flags, MAX_SCHEDULE_TIMEOUT);
i915_gem_request_put(request);
}
- return ret;
+ return ret < 0 ? ret : 0;
}
/**
@@ -645,7 +671,7 @@ i915_gem_active_retire(struct i915_gem_active *active,
struct mutex *mutex)
{
struct drm_i915_gem_request *request;
- int ret;
+ long ret;
request = i915_gem_active_raw(active, mutex);
if (!request)
@@ -653,8 +679,8 @@ i915_gem_active_retire(struct i915_gem_active *active,
ret = i915_wait_request(request,
I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
- NULL, NULL);
- if (ret)
+ MAX_SCHEDULE_TIMEOUT);
+ if (ret < 0)
return ret;
list_del_init(&active->link);
@@ -665,24 +691,6 @@ i915_gem_active_retire(struct i915_gem_active *active,
return 0;
}
-/* Convenience functions for peeking at state inside active's request whilst
- * guarded by the struct_mutex.
- */
-
-static inline uint32_t
-i915_gem_active_get_seqno(const struct i915_gem_active *active,
- struct mutex *mutex)
-{
- return i915_gem_request_get_seqno(i915_gem_active_peek(active, mutex));
-}
-
-static inline struct intel_engine_cs *
-i915_gem_active_get_engine(const struct i915_gem_active *active,
- struct mutex *mutex)
-{
- return i915_gem_request_get_engine(i915_gem_active_peek(active, mutex));
-}
-
#define for_each_active(mask, idx) \
for (; mask ? idx = ffs(mask) - 1, 1 : 0; mask &= ~BIT(idx))
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 1c237d02f30b..401006b4c6a3 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -35,17 +35,22 @@
#include "i915_drv.h"
#include "i915_trace.h"
-static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
+static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
{
- if (!mutex_is_locked(mutex))
+ switch (mutex_trylock_recursive(&dev->struct_mutex)) {
+ case MUTEX_TRYLOCK_FAILED:
return false;
-#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
- return mutex->owner == task;
-#else
- /* Since UP may be pre-empted, we cannot assume that we own the lock */
- return false;
-#endif
+ case MUTEX_TRYLOCK_SUCCESS:
+ *unlock = true;
+ return true;
+
+ case MUTEX_TRYLOCK_RECURSIVE:
+ *unlock = false;
+ return true;
+ }
+
+ BUG();
}
static bool any_vma_pinned(struct drm_i915_gem_object *obj)
@@ -66,8 +71,11 @@ static bool swap_available(void)
static bool can_release_pages(struct drm_i915_gem_object *obj)
{
- /* Only shmemfs objects are backed by swap */
- if (!obj->base.filp)
+ if (!obj->mm.pages)
+ return false;
+
+ /* Consider only shrinkable ojects. */
+ if (!i915_gem_object_is_shrinkable(obj))
return false;
/* Only report true if by unbinding the object and putting its pages
@@ -78,7 +86,7 @@ static bool can_release_pages(struct drm_i915_gem_object *obj)
* to the GPU, simply unbinding from the GPU is not going to succeed
* in releasing our pin count on the pages themselves.
*/
- if (obj->pages_pin_count > obj->bind_count)
+ if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count)
return false;
if (any_vma_pinned(obj))
@@ -88,7 +96,14 @@ static bool can_release_pages(struct drm_i915_gem_object *obj)
* discard the contents (because the user has marked them as being
* purgeable) or if we can move their contents out to swap.
*/
- return swap_available() || obj->madv == I915_MADV_DONTNEED;
+ return swap_available() || obj->mm.madv == I915_MADV_DONTNEED;
+}
+
+static bool unsafe_drop_pages(struct drm_i915_gem_object *obj)
+{
+ if (i915_gem_object_unbind(obj) == 0)
+ __i915_gem_object_put_pages(obj, I915_MM_SHRINKER);
+ return !READ_ONCE(obj->mm.pages);
}
/**
@@ -128,6 +143,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
{ NULL, 0 },
}, *phase;
unsigned long count = 0;
+ bool unlock;
+
+ if (!i915_gem_shrinker_lock(&dev_priv->drm, &unlock))
+ return 0;
trace_i915_gem_shrink(dev_priv, target, flags);
i915_gem_retire_requests(dev_priv);
@@ -171,40 +190,51 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
while (count < target &&
(obj = list_first_entry_or_null(phase->list,
typeof(*obj),
- global_list))) {
- list_move_tail(&obj->global_list, &still_in_list);
+ global_link))) {
+ list_move_tail(&obj->global_link, &still_in_list);
+ if (!obj->mm.pages) {
+ list_del_init(&obj->global_link);
+ continue;
+ }
if (flags & I915_SHRINK_PURGEABLE &&
- obj->madv != I915_MADV_DONTNEED)
+ obj->mm.madv != I915_MADV_DONTNEED)
continue;
if (flags & I915_SHRINK_VMAPS &&
- !is_vmalloc_addr(obj->mapping))
+ !is_vmalloc_addr(obj->mm.mapping))
continue;
- if ((flags & I915_SHRINK_ACTIVE) == 0 &&
- i915_gem_object_is_active(obj))
+ if (!(flags & I915_SHRINK_ACTIVE) &&
+ (i915_gem_object_is_active(obj) ||
+ obj->framebuffer_references))
continue;
if (!can_release_pages(obj))
continue;
- i915_gem_object_get(obj);
-
- /* For the unbound phase, this should be a no-op! */
- i915_gem_object_unbind(obj);
- if (i915_gem_object_put_pages(obj) == 0)
- count += obj->base.size >> PAGE_SHIFT;
-
- i915_gem_object_put(obj);
+ if (unsafe_drop_pages(obj)) {
+ /* May arrive from get_pages on another bo */
+ mutex_lock_nested(&obj->mm.lock,
+ I915_MM_SHRINKER);
+ if (!obj->mm.pages) {
+ __i915_gem_object_invalidate(obj);
+ list_del_init(&obj->global_link);
+ count += obj->base.size >> PAGE_SHIFT;
+ }
+ mutex_unlock(&obj->mm.lock);
+ }
}
- list_splice(&still_in_list, phase->list);
+ list_splice_tail(&still_in_list, phase->list);
}
if (flags & I915_SHRINK_BOUND)
intel_runtime_pm_put(dev_priv);
i915_gem_retire_requests(dev_priv);
+ if (unlock)
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+
/* expedite the RCU grace period to free some request slabs */
synchronize_rcu_expedited();
@@ -238,19 +268,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
return freed;
}
-static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
-{
- if (!mutex_trylock(&dev->struct_mutex)) {
- if (!mutex_is_locked_by(&dev->struct_mutex, current))
- return false;
-
- *unlock = false;
- } else
- *unlock = true;
-
- return true;
-}
-
static unsigned long
i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
@@ -267,11 +284,11 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
i915_gem_retire_requests(dev_priv);
count = 0;
- list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
+ list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link)
if (can_release_pages(obj))
count += obj->base.size >> PAGE_SHIFT;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
if (!i915_gem_object_is_active(obj) && can_release_pages(obj))
count += obj->base.size >> PAGE_SHIFT;
}
@@ -372,13 +389,19 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
* being pointed to by hardware.
*/
unbound = bound = unevictable = 0;
- list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
+ if (!obj->mm.pages)
+ continue;
+
if (!can_release_pages(obj))
unevictable += obj->base.size >> PAGE_SHIFT;
else
unbound += obj->base.size >> PAGE_SHIFT;
}
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
+ if (!obj->mm.pages)
+ continue;
+
if (!can_release_pages(obj))
unevictable += obj->base.size >> PAGE_SHIFT;
else
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 59989e8ee5dc..ebaa941c83af 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -89,9 +89,8 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
mutex_unlock(&dev_priv->mm.stolen_lock);
}
-static unsigned long i915_stolen_to_physical(struct drm_device *dev)
+static unsigned long i915_stolen_to_physical(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct resource *r;
@@ -109,13 +108,13 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
*
*/
base = 0;
- if (INTEL_INFO(dev)->gen >= 3) {
+ if (INTEL_GEN(dev_priv) >= 3) {
u32 bsm;
pci_read_config_dword(pdev, INTEL_BSM, &bsm);
base = bsm & INTEL_BSM_MASK;
- } else if (IS_I865G(dev)) {
+ } else if (IS_I865G(dev_priv)) {
u32 tseg_size = 0;
u16 toud = 0;
u8 tmp;
@@ -138,7 +137,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
I865_TOUD, &toud);
base = (toud << 16) + tseg_size;
- } else if (IS_I85X(dev)) {
+ } else if (IS_I85X(dev_priv)) {
u32 tseg_size = 0;
u32 tom;
u8 tmp;
@@ -154,7 +153,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
tom = tmp * MB(32);
base = tom - tseg_size - ggtt->stolen_size;
- } else if (IS_845G(dev)) {
+ } else if (IS_845G(dev_priv)) {
u32 tseg_size = 0;
u32 tom;
u8 tmp;
@@ -178,7 +177,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
tom = tmp * MB(32);
base = tom - tseg_size - ggtt->stolen_size;
- } else if (IS_I830(dev)) {
+ } else if (IS_I830(dev_priv)) {
u32 tseg_size = 0;
u32 tom;
u8 tmp;
@@ -204,7 +203,8 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
return 0;
/* make sure we don't clobber the GTT if it's within stolen memory */
- if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) {
+ if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) &&
+ !IS_G4X(dev_priv)) {
struct {
u32 start, end;
} stolen[2] = {
@@ -214,7 +214,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
u64 ggtt_start, ggtt_end;
ggtt_start = I915_READ(PGTBL_CTL);
- if (IS_GEN4(dev))
+ if (IS_GEN4(dev_priv))
ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
(ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
else
@@ -252,7 +252,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
* kernel. So if the region is already marked as busy, something
* is seriously wrong.
*/
- r = devm_request_mem_region(dev->dev, base, ggtt->stolen_size,
+ r = devm_request_mem_region(dev_priv->drm.dev, base, ggtt->stolen_size,
"Graphics Stolen Memory");
if (r == NULL) {
/*
@@ -263,14 +263,14 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
* PCI bus, but have an off-by-one error. Hence retry the
* reservation starting from 1 instead of 0.
*/
- r = devm_request_mem_region(dev->dev, base + 1,
+ r = devm_request_mem_region(dev_priv->drm.dev, base + 1,
ggtt->stolen_size - 1,
"Graphics Stolen Memory");
/*
* GEN3 firmware likes to smash pci bridges into the stolen
* range. Apparently this works.
*/
- if (r == NULL && !IS_GEN3(dev)) {
+ if (r == NULL && !IS_GEN3(dev_priv)) {
DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
base, base + (uint32_t)ggtt->stolen_size);
base = 0;
@@ -407,9 +407,8 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
*size = stolen_top - *base;
}
-int i915_gem_init_stolen(struct drm_device *dev)
+int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned long reserved_total, reserved_base = 0, reserved_size;
unsigned long stolen_top;
@@ -417,7 +416,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
mutex_init(&dev_priv->mm.stolen_lock);
#ifdef CONFIG_INTEL_IOMMU
- if (intel_iommu_gfx_mapped && INTEL_INFO(dev)->gen < 8) {
+ if (intel_iommu_gfx_mapped && INTEL_GEN(dev_priv) < 8) {
DRM_INFO("DMAR active, disabling use of stolen memory\n");
return 0;
}
@@ -426,7 +425,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
if (ggtt->stolen_size == 0)
return 0;
- dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
+ dev_priv->mm.stolen_base = i915_stolen_to_physical(dev_priv);
if (dev_priv->mm.stolen_base == 0)
return 0;
@@ -437,7 +436,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
case 3:
break;
case 4:
- if (IS_G4X(dev))
+ if (IS_G4X(dev_priv))
g4x_get_stolen_reserved(dev_priv, &reserved_base,
&reserved_size);
break;
@@ -456,7 +455,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
break;
default:
if (IS_BROADWELL(dev_priv) ||
- IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
+ IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
bdw_get_stolen_reserved(dev_priv, &reserved_base,
&reserved_size);
else
@@ -514,12 +513,10 @@ i915_pages_create_for_stolen(struct drm_device *dev,
u32 offset, u32 size)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct sg_table *st;
struct scatterlist *sg;
- DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
- BUG_ON(offset > ggtt->stolen_size - size);
+ GEM_BUG_ON(offset > dev_priv->ggtt.stolen_size - size);
/* We hide that we have no struct page backing our stolen object
* by wrapping the contiguous physical allocation with a fake
@@ -528,11 +525,11 @@ i915_pages_create_for_stolen(struct drm_device *dev,
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL)
- return NULL;
+ return ERR_PTR(-ENOMEM);
if (sg_alloc_table(st, 1, GFP_KERNEL)) {
kfree(st);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
sg = st->sgl;
@@ -545,31 +542,36 @@ i915_pages_create_for_stolen(struct drm_device *dev,
return st;
}
-static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
+static struct sg_table *
+i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
{
- BUG();
- return -EINVAL;
+ return i915_pages_create_for_stolen(obj->base.dev,
+ obj->stolen->start,
+ obj->stolen->size);
}
-static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj)
+static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
- /* Should only be called during free */
- sg_free_table(obj->pages);
- kfree(obj->pages);
+ /* Should only be called from i915_gem_object_release_stolen() */
+ sg_free_table(pages);
+ kfree(pages);
}
-
static void
i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+ struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen);
- if (obj->stolen) {
- i915_gem_stolen_remove_node(dev_priv, obj->stolen);
- kfree(obj->stolen);
- obj->stolen = NULL;
- }
+ GEM_BUG_ON(!stolen);
+
+ __i915_gem_object_unpin_pages(obj);
+
+ i915_gem_stolen_remove_node(dev_priv, stolen);
+ kfree(stolen);
}
+
static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
.get_pages = i915_gem_object_get_pages_stolen,
.put_pages = i915_gem_object_put_pages_stolen,
@@ -589,19 +591,13 @@ _i915_gem_object_create_stolen(struct drm_device *dev,
drm_gem_private_object_init(dev, &obj->base, stolen->size);
i915_gem_object_init(obj, &i915_gem_object_stolen_ops);
- obj->pages = i915_pages_create_for_stolen(dev,
- stolen->start, stolen->size);
- if (obj->pages == NULL)
- goto cleanup;
-
- obj->get_page.sg = obj->pages->sgl;
- obj->get_page.last = 0;
-
- i915_gem_object_pin_pages(obj);
obj->stolen = stolen;
-
obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT;
- obj->cache_level = HAS_LLC(dev) ? I915_CACHE_LLC : I915_CACHE_NONE;
+ obj->cache_level = HAS_LLC(to_i915(dev)) ?
+ I915_CACHE_LLC : I915_CACHE_NONE;
+
+ if (i915_gem_object_pin_pages(obj))
+ goto cleanup;
return obj;
@@ -621,7 +617,6 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return NULL;
- DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
if (size == 0)
return NULL;
@@ -697,10 +692,14 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
if (gtt_offset == I915_GTT_OFFSET_NONE)
return obj;
+ ret = i915_gem_object_pin_pages(obj);
+ if (ret)
+ goto err;
+
vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
- goto err;
+ goto err_pages;
}
/* To simplify the initialisation sequence between KMS and GTT,
@@ -714,20 +713,20 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
if (ret) {
DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
- goto err;
+ goto err_pages;
}
- vma->pages = obj->pages;
+ vma->pages = obj->mm.pages;
vma->flags |= I915_VMA_GLOBAL_BIND;
__i915_vma_set_map_and_fenceable(vma);
list_move_tail(&vma->vm_link, &ggtt->base.inactive_list);
+ list_move_tail(&obj->global_link, &dev_priv->mm.bound_list);
obj->bind_count++;
- list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
- i915_gem_object_pin_pages(obj);
-
return obj;
+err_pages:
+ i915_gem_object_unpin_pages(obj);
err:
i915_gem_object_put(obj);
return NULL;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index a14b1e3d4c78..c85e7b06bdba 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -60,7 +60,8 @@
/* Check pitch constriants for all chips & tiling formats */
static bool
-i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
+i915_tiling_ok(struct drm_i915_private *dev_priv,
+ int stride, int size, int tiling_mode)
{
int tile_width;
@@ -71,8 +72,8 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
if (tiling_mode > I915_TILING_LAST)
return false;
- if (IS_GEN2(dev) ||
- (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
+ if (IS_GEN2(dev_priv) ||
+ (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev_priv)))
tile_width = 128;
else
tile_width = 512;
@@ -80,17 +81,17 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
/* check maximum stride & object size */
/* i965+ stores the end address of the gtt mapping in the fence
* reg, so dont bother to check the size */
- if (INTEL_INFO(dev)->gen >= 7) {
+ if (INTEL_GEN(dev_priv) >= 7) {
if (stride / 128 > GEN7_FENCE_MAX_PITCH_VAL)
return false;
- } else if (INTEL_INFO(dev)->gen >= 4) {
+ } else if (INTEL_GEN(dev_priv) >= 4) {
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
return false;
} else {
if (stride > 8192)
return false;
- if (IS_GEN3(dev)) {
+ if (IS_GEN3(dev_priv)) {
if (size > I830_FENCE_MAX_SIZE_VAL << 20)
return false;
} else {
@@ -103,7 +104,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
return false;
/* 965+ just needs multiples of tile width */
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
if (stride & (tile_width - 1))
return false;
return true;
@@ -198,14 +199,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
if (!obj)
return -ENOENT;
- if (!i915_tiling_ok(dev,
+ if (!i915_tiling_ok(dev_priv,
args->stride, obj->base.size, args->tiling_mode)) {
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return -EINVAL;
}
- intel_runtime_pm_get(dev_priv);
-
mutex_lock(&dev->struct_mutex);
if (obj->pin_display || obj->framebuffer_references) {
err = -EBUSY;
@@ -260,14 +259,22 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
if (!err) {
struct i915_vma *vma;
- if (obj->pages &&
- obj->madv == I915_MADV_WILLNEED &&
+ mutex_lock(&obj->mm.lock);
+ if (obj->mm.pages &&
+ obj->mm.madv == I915_MADV_WILLNEED &&
dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
- if (args->tiling_mode == I915_TILING_NONE)
- i915_gem_object_unpin_pages(obj);
- if (!i915_gem_object_is_tiled(obj))
- i915_gem_object_pin_pages(obj);
+ if (args->tiling_mode == I915_TILING_NONE) {
+ GEM_BUG_ON(!obj->mm.quirked);
+ __i915_gem_object_unpin_pages(obj);
+ obj->mm.quirked = false;
+ }
+ if (!i915_gem_object_is_tiled(obj)) {
+ GEM_BUG_ON(!obj->mm.quirked);
+ __i915_gem_object_pin_pages(obj);
+ obj->mm.quirked = true;
+ }
}
+ mutex_unlock(&obj->mm.lock);
list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (!vma->fence)
@@ -301,8 +308,6 @@ err:
i915_gem_object_put(obj);
mutex_unlock(&dev->struct_mutex);
- intel_runtime_pm_put(dev_priv);
-
return err;
}
@@ -326,12 +331,19 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
struct drm_i915_gem_get_tiling *args = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj;
+ int err = -ENOENT;
+
+ rcu_read_lock();
+ obj = i915_gem_object_lookup_rcu(file, args->handle);
+ if (obj) {
+ args->tiling_mode =
+ READ_ONCE(obj->tiling_and_stride) & TILING_MASK;
+ err = 0;
+ }
+ rcu_read_unlock();
+ if (unlikely(err))
+ return err;
- obj = i915_gem_object_lookup(file, args->handle);
- if (!obj)
- return -ENOENT;
-
- args->tiling_mode = READ_ONCE(obj->tiling_and_stride) & TILING_MASK;
switch (args->tiling_mode) {
case I915_TILING_X:
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -339,11 +351,10 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
case I915_TILING_Y:
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
break;
+ default:
case I915_TILING_NONE:
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
break;
- default:
- DRM_ERROR("unknown tiling mode\n");
}
/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
@@ -356,6 +367,5 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
- i915_gem_object_put_unlocked(obj);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c
new file mode 100644
index 000000000000..bf8a471b61e6
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_timeline.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2016 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 "i915_drv.h"
+
+static int __i915_gem_timeline_init(struct drm_i915_private *i915,
+ struct i915_gem_timeline *timeline,
+ const char *name,
+ struct lock_class_key *lockclass,
+ const char *lockname)
+{
+ unsigned int i;
+ u64 fences;
+
+ lockdep_assert_held(&i915->drm.struct_mutex);
+
+ timeline->i915 = i915;
+ timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL);
+ if (!timeline->name)
+ return -ENOMEM;
+
+ list_add(&timeline->link, &i915->gt.timelines);
+
+ /* Called during early_init before we know how many engines there are */
+ fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine));
+ for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) {
+ struct intel_timeline *tl = &timeline->engine[i];
+
+ tl->fence_context = fences++;
+ tl->common = timeline;
+#ifdef CONFIG_DEBUG_SPINLOCK
+ __raw_spin_lock_init(&tl->lock.rlock, lockname, lockclass);
+#else
+ spin_lock_init(&tl->lock);
+#endif
+ init_request_active(&tl->last_request, NULL);
+ INIT_LIST_HEAD(&tl->requests);
+ }
+
+ return 0;
+}
+
+int i915_gem_timeline_init(struct drm_i915_private *i915,
+ struct i915_gem_timeline *timeline,
+ const char *name)
+{
+ static struct lock_class_key class;
+
+ return __i915_gem_timeline_init(i915, timeline, name,
+ &class, "&timeline->lock");
+}
+
+int i915_gem_timeline_init__global(struct drm_i915_private *i915)
+{
+ static struct lock_class_key class;
+
+ return __i915_gem_timeline_init(i915,
+ &i915->gt.global_timeline,
+ "[execution]",
+ &class, "&global_timeline->lock");
+}
+
+void i915_gem_timeline_fini(struct i915_gem_timeline *tl)
+{
+ lockdep_assert_held(&tl->i915->drm.struct_mutex);
+
+ list_del(&tl->link);
+ kfree(tl->name);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h
new file mode 100644
index 000000000000..98d99a62b4ae
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_timeline.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2016 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 I915_GEM_TIMELINE_H
+#define I915_GEM_TIMELINE_H
+
+#include <linux/list.h>
+
+#include "i915_gem_request.h"
+
+struct i915_gem_timeline;
+
+struct intel_timeline {
+ u64 fence_context;
+ u32 last_submitted_seqno;
+
+ spinlock_t lock;
+
+ /**
+ * List of breadcrumbs associated with GPU requests currently
+ * outstanding.
+ */
+ struct list_head requests;
+
+ /* Contains an RCU guarded pointer to the last request. No reference is
+ * held to the request, users must carefully acquire a reference to
+ * the request using i915_gem_active_get_request_rcu(), or hold the
+ * struct_mutex.
+ */
+ struct i915_gem_active last_request;
+ u32 sync_seqno[I915_NUM_ENGINES];
+
+ struct i915_gem_timeline *common;
+};
+
+struct i915_gem_timeline {
+ struct list_head link;
+ atomic_t next_seqno;
+
+ struct drm_i915_private *i915;
+ const char *name;
+
+ struct intel_timeline engine[I915_NUM_ENGINES];
+};
+
+int i915_gem_timeline_init(struct drm_i915_private *i915,
+ struct i915_gem_timeline *tl,
+ const char *name);
+int i915_gem_timeline_init__global(struct drm_i915_private *i915);
+void i915_gem_timeline_fini(struct i915_gem_timeline *tl);
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index c6f780f5abc9..107ddf51065e 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -61,33 +61,26 @@ struct i915_mmu_object {
bool attached;
};
-static void wait_rendering(struct drm_i915_gem_object *obj)
-{
- unsigned long active = __I915_BO_ACTIVE(obj);
- int idx;
-
- for_each_active(active, idx)
- i915_gem_active_wait_unlocked(&obj->last_read[idx],
- 0, NULL, NULL);
-}
-
static void cancel_userptr(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;
- wait_rendering(obj);
+ i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT, NULL);
mutex_lock(&dev->struct_mutex);
/* Cancel any active worker and force us to re-evaluate gup */
obj->userptr.work = NULL;
- if (obj->pages != NULL) {
- /* We are inside a kthread context and can't be interrupted */
- WARN_ON(i915_gem_object_unbind(obj));
- WARN_ON(i915_gem_object_put_pages(obj));
- }
+ /* We are inside a kthread context and can't be interrupted */
+ if (i915_gem_object_unbind(obj) == 0)
+ __i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+ WARN_ONCE(obj->mm.pages,
+ "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n",
+ obj->bind_count,
+ atomic_read(&obj->mm.pages_pin_count),
+ obj->pin_display);
i915_gem_object_put(obj);
mutex_unlock(&dev->struct_mutex);
@@ -436,24 +429,25 @@ err:
return ret;
}
-static int
+static struct sg_table *
__i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj,
struct page **pvec, int num_pages)
{
+ struct sg_table *pages;
int ret;
- ret = st_set_pages(&obj->pages, pvec, num_pages);
+ ret = st_set_pages(&pages, pvec, num_pages);
if (ret)
- return ret;
+ return ERR_PTR(ret);
- ret = i915_gem_gtt_prepare_object(obj);
+ ret = i915_gem_gtt_prepare_pages(obj, pages);
if (ret) {
- sg_free_table(obj->pages);
- kfree(obj->pages);
- obj->pages = NULL;
+ sg_free_table(pages);
+ kfree(pages);
+ return ERR_PTR(ret);
}
- return ret;
+ return pages;
}
static int
@@ -497,7 +491,6 @@ __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 npages = obj->base.size >> PAGE_SHIFT;
struct page **pvec;
int pinned, ret;
@@ -533,33 +526,32 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
}
}
- mutex_lock(&dev->struct_mutex);
+ mutex_lock(&obj->mm.lock);
if (obj->userptr.work == &work->work) {
+ struct sg_table *pages = ERR_PTR(ret);
+
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;
+ pages = __i915_gem_userptr_set_pages(obj, pvec, npages);
+ if (!IS_ERR(pages)) {
+ __i915_gem_object_set_pages(obj, pages);
pinned = 0;
+ pages = NULL;
}
}
- obj->userptr.work = ERR_PTR(ret);
- }
- obj->userptr.workers--;
- i915_gem_object_put(obj);
- mutex_unlock(&dev->struct_mutex);
+ obj->userptr.work = ERR_CAST(pages);
+ }
+ mutex_unlock(&obj->mm.lock);
release_pages(pvec, pinned, 0);
drm_free_large(pvec);
+ i915_gem_object_put(obj);
put_task_struct(work->task);
kfree(work);
}
-static int
+static struct sg_table *
__i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj,
bool *active)
{
@@ -584,15 +576,11 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj,
* 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;
+ return ERR_PTR(-ENOMEM);
obj->userptr.work = &work->work;
- obj->userptr.workers++;
work->obj = i915_gem_object_get(obj);
@@ -603,14 +591,15 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj,
schedule_work(&work->work);
*active = true;
- return -EAGAIN;
+ return ERR_PTR(-EAGAIN);
}
-static int
+static struct sg_table *
i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
{
const int num_pages = obj->base.size >> PAGE_SHIFT;
struct page **pvec;
+ struct sg_table *pages;
int pinned, ret;
bool active;
@@ -634,15 +623,15 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
if (obj->userptr.work) {
/* active flag should still be held for the pending work */
if (IS_ERR(obj->userptr.work))
- return PTR_ERR(obj->userptr.work);
+ return ERR_CAST(obj->userptr.work);
else
- return -EAGAIN;
+ return ERR_PTR(-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;
+ return ERR_PTR(ret);
pvec = NULL;
pinned = 0;
@@ -651,7 +640,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
GFP_TEMPORARY);
if (pvec == NULL) {
__i915_gem_userptr_set_active(obj, false);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages,
@@ -660,21 +649,22 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
active = false;
if (pinned < 0)
- ret = pinned, pinned = 0;
+ pages = ERR_PTR(pinned), pinned = 0;
else if (pinned < num_pages)
- ret = __i915_gem_userptr_get_pages_schedule(obj, &active);
+ pages = __i915_gem_userptr_get_pages_schedule(obj, &active);
else
- ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
- if (ret) {
+ pages = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
+ if (IS_ERR(pages)) {
__i915_gem_userptr_set_active(obj, active);
release_pages(pvec, pinned, 0);
}
drm_free_large(pvec);
- return ret;
+ return pages;
}
static void
-i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj)
+i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *pages)
{
struct sgt_iter sgt_iter;
struct page *page;
@@ -682,22 +672,22 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj)
BUG_ON(obj->userptr.work != NULL);
__i915_gem_userptr_set_active(obj, false);
- if (obj->madv != I915_MADV_WILLNEED)
- obj->dirty = 0;
+ if (obj->mm.madv != I915_MADV_WILLNEED)
+ obj->mm.dirty = false;
- i915_gem_gtt_finish_object(obj);
+ i915_gem_gtt_finish_pages(obj, pages);
- for_each_sgt_page(page, sgt_iter, obj->pages) {
- if (obj->dirty)
+ for_each_sgt_page(page, sgt_iter, pages) {
+ if (obj->mm.dirty)
set_page_dirty(page);
mark_page_accessed(page);
put_page(page);
}
- obj->dirty = 0;
+ obj->mm.dirty = false;
- sg_free_table(obj->pages);
- kfree(obj->pages);
+ sg_free_table(pages);
+ kfree(pages);
}
static void
@@ -717,7 +707,8 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
}
static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
- .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
+ .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+ I915_GEM_OBJECT_IS_SHRINKABLE,
.get_pages = i915_gem_userptr_get_pages,
.put_pages = i915_gem_userptr_put_pages,
.dmabuf_export = i915_gem_userptr_dmabuf_export,
@@ -762,12 +753,13 @@ 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 = to_i915(dev);
struct drm_i915_gem_userptr *args = data;
struct drm_i915_gem_object *obj;
int ret;
u32 handle;
- if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) {
+ if (!HAS_LLC(dev_priv) && !HAS_SNOOP(dev_priv)) {
/* We cannot support coherent userptr objects on hw without
* LLC and broken snooping.
*/
@@ -816,7 +808,7 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
ret = drm_gem_handle_create(file, &obj->base, &handle);
/* drop reference from allocate - handle holds it now */
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 334f15df7c8d..ae84aa4b1467 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -28,6 +28,8 @@
*/
#include <generated/utsrelease.h>
+#include <linux/stop_machine.h>
+#include <linux/zlib.h>
#include "i915_drv.h"
static const char *engine_str(int engine)
@@ -172,6 +174,110 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e,
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
#define err_puts(e, s) i915_error_puts(e, s)
+#ifdef CONFIG_DRM_I915_COMPRESS_ERROR
+
+static bool compress_init(struct z_stream_s *zstream)
+{
+ memset(zstream, 0, sizeof(*zstream));
+
+ zstream->workspace =
+ kmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (!zstream->workspace)
+ return false;
+
+ if (zlib_deflateInit(zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
+ kfree(zstream->workspace);
+ return false;
+ }
+
+ return true;
+}
+
+static int compress_page(struct z_stream_s *zstream,
+ void *src,
+ struct drm_i915_error_object *dst)
+{
+ zstream->next_in = src;
+ zstream->avail_in = PAGE_SIZE;
+
+ do {
+ if (zstream->avail_out == 0) {
+ unsigned long page;
+
+ page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page)
+ return -ENOMEM;
+
+ dst->pages[dst->page_count++] = (void *)page;
+
+ zstream->next_out = (void *)page;
+ zstream->avail_out = PAGE_SIZE;
+ }
+
+ if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
+ return -EIO;
+ } while (zstream->avail_in);
+
+ /* Fallback to uncompressed if we increase size? */
+ if (0 && zstream->total_out > zstream->total_in)
+ return -E2BIG;
+
+ return 0;
+}
+
+static void compress_fini(struct z_stream_s *zstream,
+ struct drm_i915_error_object *dst)
+{
+ if (dst) {
+ zlib_deflate(zstream, Z_FINISH);
+ dst->unused = zstream->avail_out;
+ }
+
+ zlib_deflateEnd(zstream);
+ kfree(zstream->workspace);
+}
+
+static void err_compression_marker(struct drm_i915_error_state_buf *m)
+{
+ err_puts(m, ":");
+}
+
+#else
+
+static bool compress_init(struct z_stream_s *zstream)
+{
+ return true;
+}
+
+static int compress_page(struct z_stream_s *zstream,
+ void *src,
+ struct drm_i915_error_object *dst)
+{
+ unsigned long page;
+
+ page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page)
+ return -ENOMEM;
+
+ dst->pages[dst->page_count++] =
+ memcpy((void *)page, src, PAGE_SIZE);
+
+ return 0;
+}
+
+static void compress_fini(struct z_stream_s *zstream,
+ struct drm_i915_error_object *dst)
+{
+}
+
+static void err_compression_marker(struct drm_i915_error_state_buf *m)
+{
+ err_puts(m, "~");
+}
+
+#endif
+
static void print_error_buffers(struct drm_i915_error_state_buf *m,
const char *name,
struct drm_i915_error_buffer *err,
@@ -228,13 +334,57 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a)
return "unknown";
}
+static void error_print_instdone(struct drm_i915_error_state_buf *m,
+ struct drm_i915_error_engine *ee)
+{
+ int slice;
+ int subslice;
+
+ err_printf(m, " INSTDONE: 0x%08x\n",
+ ee->instdone.instdone);
+
+ if (ee->engine_id != RCS || INTEL_GEN(m->i915) <= 3)
+ return;
+
+ err_printf(m, " SC_INSTDONE: 0x%08x\n",
+ ee->instdone.slice_common);
+
+ if (INTEL_GEN(m->i915) <= 6)
+ return;
+
+ for_each_instdone_slice_subslice(m->i915, slice, subslice)
+ err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice,
+ ee->instdone.sampler[slice][subslice]);
+
+ for_each_instdone_slice_subslice(m->i915, slice, subslice)
+ err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice,
+ ee->instdone.row[slice][subslice]);
+}
+
+static void error_print_request(struct drm_i915_error_state_buf *m,
+ const char *prefix,
+ struct drm_i915_error_request *erq)
+{
+ if (!erq->seqno)
+ return;
+
+ err_printf(m, "%s pid %d, seqno %8x:%08x, emitted %dms ago, head %08x, tail %08x\n",
+ prefix, erq->pid,
+ erq->context, erq->seqno,
+ jiffies_to_msecs(jiffies - erq->jiffies),
+ erq->head, erq->tail);
+}
+
static void error_print_engine(struct drm_i915_error_state_buf *m,
struct drm_i915_error_engine *ee)
{
err_printf(m, "%s command stream:\n", engine_str(ee->engine_id));
err_printf(m, " START: 0x%08x\n", ee->start);
- err_printf(m, " HEAD: 0x%08x\n", ee->head);
- err_printf(m, " TAIL: 0x%08x\n", ee->tail);
+ err_printf(m, " HEAD: 0x%08x [0x%08x]\n", ee->head, ee->rq_head);
+ err_printf(m, " TAIL: 0x%08x [0x%08x, 0x%08x]\n",
+ ee->tail, ee->rq_post, ee->rq_tail);
err_printf(m, " CTL: 0x%08x\n", ee->ctl);
err_printf(m, " MODE: 0x%08x\n", ee->mode);
err_printf(m, " HWS: 0x%08x\n", ee->hws);
@@ -242,7 +392,9 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
(u32)(ee->acthd>>32), (u32)ee->acthd);
err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir);
err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr);
- err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone);
+
+ error_print_instdone(m, ee);
+
if (ee->batchbuffer) {
u64 start = ee->batchbuffer->gtt_offset;
u64 end = start + ee->batchbuffer->gtt_size;
@@ -263,17 +415,13 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
if (INTEL_GEN(m->i915) >= 6) {
err_printf(m, " RC PSMI: 0x%08x\n", ee->rc_psmi);
err_printf(m, " FAULT_REG: 0x%08x\n", ee->fault_reg);
- err_printf(m, " SYNC_0: 0x%08x [last synced 0x%08x]\n",
- ee->semaphore_mboxes[0],
- ee->semaphore_seqno[0]);
- err_printf(m, " SYNC_1: 0x%08x [last synced 0x%08x]\n",
- ee->semaphore_mboxes[1],
- ee->semaphore_seqno[1]);
- if (HAS_VEBOX(m->i915)) {
- err_printf(m, " SYNC_2: 0x%08x [last synced 0x%08x]\n",
- ee->semaphore_mboxes[2],
- ee->semaphore_seqno[2]);
- }
+ err_printf(m, " SYNC_0: 0x%08x\n",
+ ee->semaphore_mboxes[0]);
+ err_printf(m, " SYNC_1: 0x%08x\n",
+ ee->semaphore_mboxes[1]);
+ if (HAS_VEBOX(m->i915))
+ err_printf(m, " SYNC_2: 0x%08x\n",
+ ee->semaphore_mboxes[2]);
}
if (USES_PPGTT(m->i915)) {
err_printf(m, " GFX_MODE: 0x%08x\n", ee->vm_info.gfx_mode);
@@ -296,6 +444,8 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
err_printf(m, " hangcheck: %s [%d]\n",
hangcheck_action_to_str(ee->hangcheck_action),
ee->hangcheck_score);
+ error_print_request(m, " ELSP[0]: ", &ee->execlist[0]);
+ error_print_request(m, " ELSP[1]: ", &ee->execlist[1]);
}
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -307,40 +457,83 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
va_end(args);
}
+static int
+ascii85_encode_len(int len)
+{
+ return DIV_ROUND_UP(len, 4);
+}
+
+static bool
+ascii85_encode(u32 in, char *out)
+{
+ int i;
+
+ if (in == 0)
+ return false;
+
+ out[5] = '\0';
+ for (i = 5; i--; ) {
+ out[i] = '!' + in % 85;
+ in /= 85;
+ }
+
+ return true;
+}
+
static void print_error_obj(struct drm_i915_error_state_buf *m,
+ struct intel_engine_cs *engine,
+ const char *name,
struct drm_i915_error_object *obj)
{
- int page, offset, elt;
+ char out[6];
+ int page;
+
+ if (!obj)
+ return;
- for (page = offset = 0; page < obj->page_count; page++) {
- for (elt = 0; elt < PAGE_SIZE/4; elt++) {
- err_printf(m, "%08x : %08x\n", offset,
- obj->pages[page][elt]);
- offset += 4;
+ if (name) {
+ err_printf(m, "%s --- %s = 0x%08x %08x\n",
+ engine ? engine->name : "global", name,
+ upper_32_bits(obj->gtt_offset),
+ lower_32_bits(obj->gtt_offset));
+ }
+
+ err_compression_marker(m);
+ for (page = 0; page < obj->page_count; page++) {
+ int i, len;
+
+ len = PAGE_SIZE;
+ if (page == obj->page_count - 1)
+ len -= obj->unused;
+ len = ascii85_encode_len(len);
+
+ for (i = 0; i < len; i++) {
+ if (ascii85_encode(obj->pages[page][i], out))
+ err_puts(m, out);
+ else
+ err_puts(m, "z");
}
}
+ err_puts(m, "\n");
}
static void err_print_capabilities(struct drm_i915_error_state_buf *m,
const struct intel_device_info *info)
{
#define PRINT_FLAG(x) err_printf(m, #x ": %s\n", yesno(info->x))
-#define SEP_SEMICOLON ;
- DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
+ DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
#undef PRINT_FLAG
-#undef SEP_SEMICOLON
}
int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
const struct i915_error_state_file_priv *error_priv)
{
- struct drm_device *dev = error_priv->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(error_priv->dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
struct drm_i915_error_state *error = error_priv->error;
struct drm_i915_error_object *obj;
- int i, j, offset, elt;
int max_hangcheck_score;
+ int i, j;
if (!error) {
err_printf(m, "no error state collected\n");
@@ -348,9 +541,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
err_printf(m, "%s\n", error->error_msg);
- err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
- error->time.tv_usec);
err_printf(m, "Kernel: " UTS_RELEASE "\n");
+ err_printf(m, "Time: %ld s %ld us\n",
+ error->time.tv_sec, error->time.tv_usec);
+ err_printf(m, "Boottime: %ld s %ld us\n",
+ error->boottime.tv_sec, error->boottime.tv_usec);
+ err_printf(m, "Uptime: %ld s %ld us\n",
+ error->uptime.tv_sec, error->uptime.tv_usec);
err_print_capabilities(m, &error->device_info);
max_hangcheck_score = 0;
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
@@ -375,7 +572,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
pdev->subsystem_device);
err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
- if (HAS_CSR(dev)) {
+ if (HAS_CSR(dev_priv)) {
struct intel_csr *csr = &dev_priv->csr;
err_printf(m, "DMC loaded: %s\n",
@@ -387,11 +584,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, "EIR: 0x%08x\n", error->eir);
err_printf(m, "IER: 0x%08x\n", error->ier);
- if (INTEL_INFO(dev)->gen >= 8) {
+ if (INTEL_GEN(dev_priv) >= 8) {
for (i = 0; i < 4; i++)
err_printf(m, "GTIER gt %d: 0x%08x\n", i,
error->gtier[i]);
- } else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev))
+ } else if (HAS_PCH_SPLIT(dev_priv) || IS_VALLEYVIEW(dev_priv))
err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]);
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
@@ -402,21 +599,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < dev_priv->num_fence_regs; i++)
err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
- for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
- err_printf(m, " INSTDONE_%d: 0x%08x\n", i,
- error->extra_instdone[i]);
-
- if (INTEL_INFO(dev)->gen >= 6) {
+ if (INTEL_GEN(dev_priv) >= 6) {
err_printf(m, "ERROR: 0x%08x\n", error->error);
- if (INTEL_INFO(dev)->gen >= 8)
+ if (INTEL_GEN(dev_priv) >= 8)
err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
}
- if (IS_GEN7(dev))
+ if (IS_GEN7(dev_priv))
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
@@ -438,7 +631,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
len += scnprintf(buf + len, sizeof(buf), "%s%s",
first ? "" : ", ",
- dev_priv->engine[j].name);
+ dev_priv->engine[j]->name);
first = 0;
}
scnprintf(buf + len, sizeof(buf), ")");
@@ -456,7 +649,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
obj = ee->batchbuffer;
if (obj) {
- err_puts(m, dev_priv->engine[i].name);
+ err_puts(m, dev_priv->engine[i]->name);
if (ee->pid != -1)
err_printf(m, " (submitted by %s [%d])",
ee->comm,
@@ -464,37 +657,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
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 = ee->wa_batchbuffer;
- if (obj) {
- err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
- dev_priv->engine[i].name,
- lower_32_bits(obj->gtt_offset));
- print_error_obj(m, obj);
+ print_error_obj(m, dev_priv->engine[i], NULL, obj);
}
if (ee->num_requests) {
err_printf(m, "%s --- %d requests\n",
- dev_priv->engine[i].name,
+ dev_priv->engine[i]->name,
ee->num_requests);
- for (j = 0; j < ee->num_requests; j++) {
- err_printf(m, " pid %d, seqno 0x%08x, emitted %ld, head 0x%08x, tail 0x%08x\n",
- ee->requests[j].pid,
- ee->requests[j].seqno,
- ee->requests[j].jiffies,
- ee->requests[j].head,
- ee->requests[j].tail);
- }
+ for (j = 0; j < ee->num_requests; j++)
+ error_print_request(m, " ", &ee->requests[j]);
}
if (IS_ERR(ee->waiters)) {
err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
- dev_priv->engine[i].name);
+ dev_priv->engine[i]->name);
} else if (ee->num_waiters) {
err_printf(m, "%s --- %d waiters\n",
- dev_priv->engine[i].name,
+ dev_priv->engine[i]->name,
ee->num_waiters);
for (j = 0; j < ee->num_waiters; j++) {
err_printf(m, " seqno 0x%08x for %s [%d]\n",
@@ -504,83 +683,31 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
}
- if ((obj = ee->ringbuffer)) {
- err_printf(m, "%s --- ringbuffer = 0x%08x\n",
- dev_priv->engine[i].name,
- lower_32_bits(obj->gtt_offset));
- print_error_obj(m, obj);
- }
+ print_error_obj(m, dev_priv->engine[i],
+ "ringbuffer", ee->ringbuffer);
- if ((obj = ee->hws_page)) {
- u64 hws_offset = obj->gtt_offset;
- u32 *hws_page = &obj->pages[0][0];
+ print_error_obj(m, dev_priv->engine[i],
+ "HW Status", ee->hws_page);
- 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->engine[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,
- hws_page[elt],
- hws_page[elt+1],
- hws_page[elt+2],
- hws_page[elt+3]);
- offset += 16;
- }
- }
+ print_error_obj(m, dev_priv->engine[i],
+ "HW context", ee->ctx);
- obj = ee->wa_ctx;
- if (obj) {
- u64 wa_ctx_offset = obj->gtt_offset;
- u32 *wa_ctx_page = &obj->pages[0][0];
- struct intel_engine_cs *engine = &dev_priv->engine[RCS];
- u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
- engine->wa_ctx.per_ctx.size);
-
- err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
- dev_priv->engine[i].name, wa_ctx_offset);
- offset = 0;
- for (elt = 0; elt < wa_ctx_size; elt += 4) {
- err_printf(m, "[%04x] %08x %08x %08x %08x\n",
- offset,
- wa_ctx_page[elt + 0],
- wa_ctx_page[elt + 1],
- wa_ctx_page[elt + 2],
- wa_ctx_page[elt + 3]);
- offset += 16;
- }
- }
+ print_error_obj(m, dev_priv->engine[i],
+ "WA context", ee->wa_ctx);
- if ((obj = ee->ctx)) {
- err_printf(m, "%s --- HW Context = 0x%08x\n",
- dev_priv->engine[i].name,
- lower_32_bits(obj->gtt_offset));
- print_error_obj(m, obj);
- }
+ print_error_obj(m, dev_priv->engine[i],
+ "WA batchbuffer", ee->wa_batchbuffer);
}
- if ((obj = error->semaphore)) {
- 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,
- obj->pages[0][elt],
- obj->pages[0][elt+1],
- obj->pages[0][elt+2],
- obj->pages[0][elt+3]);
- }
- }
+ print_error_obj(m, NULL, "Semaphores", error->semaphore);
+
+ print_error_obj(m, NULL, "GuC log buffer", error->guc_log);
if (error->overlay)
intel_overlay_print_error_state(m, error->overlay);
if (error->display)
- intel_display_print_error_state(m, dev, error->display);
+ intel_display_print_error_state(m, dev_priv, error->display);
out:
if (m->bytes == 0 && m->err)
@@ -629,7 +756,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj)
return;
for (page = 0; page < obj->page_count; page++)
- kfree(obj->pages[page]);
+ free_page((unsigned long)obj->pages[page]);
kfree(obj);
}
@@ -656,6 +783,7 @@ static void i915_error_state_free(struct kref *error_ref)
}
i915_error_object_free(error->semaphore);
+ i915_error_object_free(error->guc_log);
for (i = 0; i < ARRAY_SIZE(error->active_bo); i++)
kfree(error->active_bo[i]);
@@ -667,104 +795,63 @@ static void i915_error_state_free(struct kref *error_ref)
}
static struct drm_i915_error_object *
-i915_error_object_create(struct drm_i915_private *dev_priv,
+i915_error_object_create(struct drm_i915_private *i915,
struct i915_vma *vma)
{
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- struct drm_i915_gem_object *src;
+ struct i915_ggtt *ggtt = &i915->ggtt;
+ const u64 slot = ggtt->error_capture.start;
struct drm_i915_error_object *dst;
- int num_pages;
- bool use_ggtt;
- int i = 0;
- u64 reloc_offset;
+ struct z_stream_s zstream;
+ unsigned long num_pages;
+ struct sgt_iter iter;
+ dma_addr_t dma;
if (!vma)
return NULL;
- src = vma->obj;
- if (!src->pages)
- return NULL;
-
- num_pages = src->base.size >> PAGE_SHIFT;
-
- dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
+ num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT;
+ num_pages = DIV_ROUND_UP(10 * num_pages, 8); /* worstcase zlib growth */
+ dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *),
+ GFP_ATOMIC | __GFP_NOWARN);
if (!dst)
return NULL;
dst->gtt_offset = vma->node.start;
dst->gtt_size = vma->node.size;
+ dst->page_count = 0;
+ dst->unused = 0;
- reloc_offset = dst->gtt_offset;
- use_ggtt = (src->cache_level == I915_CACHE_NONE &&
- (vma->flags & I915_VMA_GLOBAL_BIND) &&
- reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
-
- /* Cannot access stolen address directly, try to use the aperture */
- if (src->stolen) {
- use_ggtt = true;
-
- if (!(vma->flags & I915_VMA_GLOBAL_BIND))
- goto unwind;
-
- reloc_offset = vma->node.start;
- if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
- goto unwind;
+ if (!compress_init(&zstream)) {
+ kfree(dst);
+ return NULL;
}
- /* Cannot access snooped pages through the aperture */
- if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
- !HAS_LLC(dev_priv))
- goto unwind;
-
- dst->page_count = num_pages;
- while (num_pages--) {
- unsigned long flags;
- void *d;
-
- d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
- if (d == NULL)
- goto unwind;
-
- local_irq_save(flags);
- if (use_ggtt) {
- void __iomem *s;
-
- /* Simply ignore tiling or any overlapping fence.
- * It's part of the error state, and this hopefully
- * captures what the GPU read.
- */
-
- s = io_mapping_map_atomic_wc(&ggtt->mappable,
- reloc_offset);
- memcpy_fromio(d, s, PAGE_SIZE);
- io_mapping_unmap_atomic(s);
- } else {
- struct page *page;
- void *s;
-
- page = i915_gem_object_get_page(src, i);
-
- drm_clflush_pages(&page, 1);
+ for_each_sgt_dma(dma, iter, vma->pages) {
+ void __iomem *s;
+ int ret;
- s = kmap_atomic(page);
- memcpy(d, s, PAGE_SIZE);
- kunmap_atomic(s);
+ ggtt->base.insert_page(&ggtt->base, dma, slot,
+ I915_CACHE_NONE, 0);
- drm_clflush_pages(&page, 1);
- }
- local_irq_restore(flags);
+ s = io_mapping_map_atomic_wc(&ggtt->mappable, slot);
+ ret = compress_page(&zstream, (void __force *)s, dst);
+ io_mapping_unmap_atomic(s);
- dst->pages[i++] = d;
- reloc_offset += PAGE_SIZE;
+ if (ret)
+ goto unwind;
}
-
- return dst;
+ goto out;
unwind:
- while (i--)
- kfree(dst->pages[i]);
+ while (dst->page_count--)
+ free_page((unsigned long)dst->pages[dst->page_count]);
kfree(dst);
- return NULL;
+ dst = NULL;
+
+out:
+ compress_fini(&zstream, dst);
+ ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE);
+ return dst;
}
/* The error capture is special as tries to run underneath the normal
@@ -773,16 +860,19 @@ unwind:
static inline uint32_t
__active_get_seqno(struct i915_gem_active *active)
{
- return i915_gem_request_get_seqno(__i915_gem_active_peek(active));
+ struct drm_i915_gem_request *request;
+
+ request = __i915_gem_active_peek(active);
+ return request ? request->global_seqno : 0;
}
static inline int
__active_get_engine_id(struct i915_gem_active *active)
{
- struct intel_engine_cs *engine;
+ struct drm_i915_gem_request *request;
- engine = i915_gem_request_get_engine(__i915_gem_active_peek(active));
- return engine ? engine->id : -1;
+ request = __i915_gem_active_peek(active);
+ return request ? request->engine->id : -1;
}
static void capture_bo(struct drm_i915_error_buffer *err,
@@ -795,17 +885,17 @@ static void capture_bo(struct drm_i915_error_buffer *err,
err->name = obj->base.name;
for (i = 0; i < I915_NUM_ENGINES; i++)
- err->rseqno[i] = __active_get_seqno(&obj->last_read[i]);
- err->wseqno = __active_get_seqno(&obj->last_write);
- err->engine = __active_get_engine_id(&obj->last_write);
+ err->rseqno[i] = __active_get_seqno(&vma->last_read[i]);
+ err->wseqno = __active_get_seqno(&obj->frontbuffer_write);
+ err->engine = __active_get_engine_id(&obj->frontbuffer_write);
err->gtt_offset = vma->node.start;
err->read_domains = obj->base.read_domains;
err->write_domain = obj->base.write_domain;
err->fence_reg = vma->fence ? vma->fence->id : -1;
err->tiling = i915_gem_object_get_tiling(obj);
- err->dirty = obj->dirty;
- err->purgeable = obj->madv != I915_MADV_WILLNEED;
+ err->dirty = obj->mm.dirty;
+ err->purgeable = obj->mm.madv != I915_MADV_WILLNEED;
err->userptr = obj->userptr.mm != NULL;
err->cache_level = obj->cache_level;
}
@@ -855,7 +945,8 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv,
if (engine_id)
*engine_id = i;
- return error->engine[i].ipehr ^ error->engine[i].instdone;
+ return error->engine[i].ipehr ^
+ error->engine[i].instdone.instdone;
}
}
@@ -879,6 +970,26 @@ static void i915_gem_record_fences(struct drm_i915_private *dev_priv,
}
}
+static inline u32
+gen8_engine_sync_index(struct intel_engine_cs *engine,
+ struct intel_engine_cs *other)
+{
+ int idx;
+
+ /*
+ * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2;
+ * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs;
+ * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs;
+ * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs;
+ * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
+ */
+
+ idx = (other - engine) - 1;
+ if (idx < 0)
+ idx += I915_NUM_ENGINES;
+
+ return idx;
+}
static void gen8_record_semaphore_state(struct drm_i915_error_state *error,
struct intel_engine_cs *engine,
@@ -891,7 +1002,7 @@ static void gen8_record_semaphore_state(struct drm_i915_error_state *error,
if (!error->semaphore)
return;
- for_each_engine_id(to, dev_priv, id) {
+ for_each_engine(to, dev_priv, id) {
int idx;
u16 signal_offset;
u32 *tmp;
@@ -902,10 +1013,9 @@ static void gen8_record_semaphore_state(struct drm_i915_error_state *error,
signal_offset =
(GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1)) / 4;
tmp = error->semaphore->pages[0];
- idx = intel_engine_sync_index(engine, to);
+ idx = gen8_engine_sync_index(engine, to);
ee->semaphore_mboxes[idx] = tmp[signal_offset];
- ee->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx];
}
}
@@ -916,14 +1026,9 @@ static void gen6_record_semaphore_state(struct intel_engine_cs *engine,
ee->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base));
ee->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base));
- ee->semaphore_seqno[0] = engine->semaphore.sync_seqno[0];
- ee->semaphore_seqno[1] = engine->semaphore.sync_seqno[1];
-
- if (HAS_VEBOX(dev_priv)) {
+ if (HAS_VEBOX(dev_priv))
ee->semaphore_mboxes[2] =
I915_READ(RING_SYNC_2(engine->mmio_base));
- ee->semaphore_seqno[2] = engine->semaphore.sync_seqno[2];
- }
}
static void error_record_engine_waiters(struct intel_engine_cs *engine,
@@ -940,7 +1045,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine,
if (RB_EMPTY_ROOT(&b->waiters))
return;
- if (!spin_trylock(&b->lock)) {
+ if (!spin_trylock_irq(&b->lock)) {
ee->waiters = ERR_PTR(-EDEADLK);
return;
}
@@ -948,7 +1053,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine,
count = 0;
for (rb = rb_first(&b->waiters); rb != NULL; rb = rb_next(rb))
count++;
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
waiter = NULL;
if (count)
@@ -958,7 +1063,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine,
if (!waiter)
return;
- if (!spin_trylock(&b->lock)) {
+ if (!spin_trylock_irq(&b->lock)) {
kfree(waiter);
ee->waiters = ERR_PTR(-EDEADLK);
return;
@@ -976,7 +1081,7 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine,
if (++ee->num_waiters == count)
break;
}
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
}
static void error_record_engine_registers(struct drm_i915_error_state *error,
@@ -998,7 +1103,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base));
ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base));
ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
- ee->instdone = I915_READ(RING_INSTDONE(engine->mmio_base));
ee->instps = I915_READ(RING_INSTPS(engine->mmio_base));
ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
if (INTEL_GEN(dev_priv) >= 8) {
@@ -1010,14 +1114,15 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
ee->faddr = I915_READ(DMA_FADD_I8XX);
ee->ipeir = I915_READ(IPEIR);
ee->ipehr = I915_READ(IPEHR);
- ee->instdone = I915_READ(GEN2_INSTDONE);
}
+ intel_engine_get_instdone(engine, &ee->instdone);
+
ee->waiting = intel_engine_has_waiter(engine);
ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
ee->acthd = intel_engine_get_active_head(engine);
ee->seqno = intel_engine_get_seqno(engine);
- ee->last_seqno = engine->last_submitted_seqno;
+ ee->last_seqno = intel_engine_last_submit(engine);
ee->start = I915_READ_START(engine);
ee->head = I915_READ_HEAD(engine);
ee->tail = I915_READ_TAIL(engine);
@@ -1079,6 +1184,20 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
}
}
+static void record_request(struct drm_i915_gem_request *request,
+ struct drm_i915_error_request *erq)
+{
+ erq->context = request->ctx->hw_id;
+ erq->seqno = request->global_seqno;
+ erq->jiffies = request->emitted_jiffies;
+ erq->head = request->head;
+ erq->tail = request->tail;
+
+ rcu_read_lock();
+ erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0;
+ rcu_read_unlock();
+}
+
static void engine_record_requests(struct intel_engine_cs *engine,
struct drm_i915_gem_request *first,
struct drm_i915_error_engine *ee)
@@ -1088,7 +1207,7 @@ static void engine_record_requests(struct intel_engine_cs *engine,
count = 0;
request = first;
- list_for_each_entry_from(request, &engine->request_list, link)
+ list_for_each_entry_from(request, &engine->timeline->requests, link)
count++;
if (!count)
return;
@@ -1101,9 +1220,7 @@ static void engine_record_requests(struct intel_engine_cs *engine,
count = 0;
request = first;
- list_for_each_entry_from(request, &engine->request_list, link) {
- struct drm_i915_error_request *erq;
-
+ list_for_each_entry_from(request, &engine->timeline->requests, link) {
if (count >= ee->num_requests) {
/*
* If the ring request list was changed in
@@ -1123,19 +1240,22 @@ static void engine_record_requests(struct intel_engine_cs *engine,
break;
}
- erq = &ee->requests[count++];
- erq->seqno = request->fence.seqno;
- erq->jiffies = request->emitted_jiffies;
- erq->head = request->head;
- erq->tail = request->tail;
-
- rcu_read_lock();
- erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0;
- rcu_read_unlock();
+ record_request(request, &ee->requests[count++]);
}
ee->num_requests = count;
}
+static void error_record_engine_execlists(struct intel_engine_cs *engine,
+ struct drm_i915_error_engine *ee)
+{
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++)
+ if (engine->execlist_port[n].request)
+ record_request(engine->execlist_port[n].request,
+ &ee->execlist[n]);
+}
+
static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
@@ -1146,20 +1266,21 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
i915_error_object_create(dev_priv, dev_priv->semaphore);
for (i = 0; i < I915_NUM_ENGINES; i++) {
- struct intel_engine_cs *engine = &dev_priv->engine[i];
+ struct intel_engine_cs *engine = dev_priv->engine[i];
struct drm_i915_error_engine *ee = &error->engine[i];
struct drm_i915_gem_request *request;
ee->pid = -1;
ee->engine_id = -1;
- if (!intel_engine_initialized(engine))
+ if (!engine)
continue;
ee->engine_id = i;
error_record_engine_registers(error, engine, ee);
error_record_engine_waiters(engine, ee);
+ error_record_engine_execlists(engine, ee);
request = i915_gem_find_active_request(engine);
if (request) {
@@ -1202,6 +1323,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
error->simulated |=
request->ctx->flags & CONTEXT_NO_ERROR_CAPTURE;
+ ee->rq_head = request->head;
+ ee->rq_post = request->postfix;
+ ee->rq_tail = request->tail;
+
ring = request->ring;
ee->cpu_ring_head = ring->head;
ee->cpu_ring_tail = ring->tail;
@@ -1302,11 +1427,21 @@ static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv,
error->pinned_bo = bo;
}
+static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error)
+{
+ /* Capturing log buf contents won't be useful if logging was disabled */
+ if (!dev_priv->guc.log.vma || (i915.guc_log_level < 0))
+ return;
+
+ error->guc_log = i915_error_object_create(dev_priv,
+ dev_priv->guc.log.vma);
+}
+
/* Capture all registers which don't fit into another category. */
static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
- struct drm_device *dev = &dev_priv->drm;
int i;
/* General organization
@@ -1318,62 +1453,60 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
*/
/* 1: Registers specific to a single generation */
- if (IS_VALLEYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv)) {
error->gtier[0] = I915_READ(GTIER);
error->ier = I915_READ(VLV_IER);
error->forcewake = I915_READ_FW(FORCEWAKE_VLV);
}
- if (IS_GEN7(dev))
+ if (IS_GEN7(dev_priv))
error->err_int = I915_READ(GEN7_ERR_INT);
- if (INTEL_INFO(dev)->gen >= 8) {
+ if (INTEL_GEN(dev_priv) >= 8) {
error->fault_data0 = I915_READ(GEN8_FAULT_TLB_DATA0);
error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1);
}
- if (IS_GEN6(dev)) {
+ if (IS_GEN6(dev_priv)) {
error->forcewake = I915_READ_FW(FORCEWAKE);
error->gab_ctl = I915_READ(GAB_CTL);
error->gfx_mode = I915_READ(GFX_MODE);
}
/* 2: Registers which belong to multiple generations */
- if (INTEL_INFO(dev)->gen >= 7)
+ if (INTEL_GEN(dev_priv) >= 7)
error->forcewake = I915_READ_FW(FORCEWAKE_MT);
- if (INTEL_INFO(dev)->gen >= 6) {
+ if (INTEL_GEN(dev_priv) >= 6) {
error->derrmr = I915_READ(DERRMR);
error->error = I915_READ(ERROR_GEN6);
error->done_reg = I915_READ(DONE_REG);
}
/* 3: Feature specific registers */
- if (IS_GEN6(dev) || IS_GEN7(dev)) {
+ if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
error->gam_ecochk = I915_READ(GAM_ECOCHK);
error->gac_eco = I915_READ(GAC_ECO_BITS);
}
/* 4: Everything else */
- if (HAS_HW_CONTEXTS(dev))
+ if (HAS_HW_CONTEXTS(dev_priv))
error->ccid = I915_READ(CCID);
- if (INTEL_INFO(dev)->gen >= 8) {
+ if (INTEL_GEN(dev_priv) >= 8) {
error->ier = I915_READ(GEN8_DE_MISC_IER);
for (i = 0; i < 4; i++)
error->gtier[i] = I915_READ(GEN8_GT_IER(i));
- } else if (HAS_PCH_SPLIT(dev)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
error->ier = I915_READ(DEIER);
error->gtier[0] = I915_READ(GTIER);
- } else if (IS_GEN2(dev)) {
+ } else if (IS_GEN2(dev_priv)) {
error->ier = I915_READ16(IER);
- } else if (!IS_VALLEYVIEW(dev)) {
+ } else if (!IS_VALLEYVIEW(dev_priv)) {
error->ier = I915_READ(IER);
}
error->eir = I915_READ(EIR);
error->pgtbl_er = I915_READ(PGTBL_ER);
-
- i915_get_extra_instdone(dev_priv, error->extra_instdone);
}
static void i915_error_capture_msg(struct drm_i915_private *dev_priv,
@@ -1418,6 +1551,32 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
sizeof(error->device_info));
}
+static int capture(void *data)
+{
+ struct drm_i915_error_state *error = data;
+
+ i915_capture_gen_state(error->i915, error);
+ i915_capture_reg_state(error->i915, error);
+ i915_gem_record_fences(error->i915, error);
+ i915_gem_record_rings(error->i915, error);
+ i915_capture_active_buffers(error->i915, error);
+ i915_capture_pinned_buffers(error->i915, error);
+ i915_gem_capture_guc_log_buffer(error->i915, error);
+
+ do_gettimeofday(&error->time);
+ error->boottime = ktime_to_timeval(ktime_get_boottime());
+ error->uptime =
+ ktime_to_timeval(ktime_sub(ktime_get(),
+ error->i915->gt.last_init_time));
+
+ error->overlay = intel_overlay_capture_error_state(error->i915);
+ error->display = intel_display_capture_error_state(error->i915);
+
+ return 0;
+}
+
+#define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x))
+
/**
* i915_capture_error_state - capture an error record for later analysis
* @dev: drm device
@@ -1435,6 +1594,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error;
unsigned long flags;
+ if (!i915.error_capture)
+ return;
+
if (READ_ONCE(dev_priv->gpu_error.first_error))
return;
@@ -1446,18 +1608,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
}
kref_init(&error->ref);
+ error->i915 = dev_priv;
- i915_capture_gen_state(dev_priv, error);
- i915_capture_reg_state(dev_priv, error);
- i915_gem_record_fences(dev_priv, error);
- i915_gem_record_rings(dev_priv, error);
- i915_capture_active_buffers(dev_priv, error);
- i915_capture_pinned_buffers(dev_priv, error);
-
- do_gettimeofday(&error->time);
-
- error->overlay = intel_overlay_capture_error_state(dev_priv);
- error->display = intel_display_capture_error_state(dev_priv);
+ stop_machine(capture, error, NULL);
i915_error_capture_msg(dev_priv, error, engine_mask, error_msg);
DRM_INFO("%s\n", error->error_msg);
@@ -1476,7 +1629,8 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
return;
}
- if (!warned) {
+ if (!warned &&
+ ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
@@ -1497,7 +1651,6 @@ void i915_error_state_get(struct drm_device *dev,
if (error_priv->error)
kref_get(&error_priv->error->ref);
spin_unlock_irq(&dev_priv->gpu_error.lock);
-
}
void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
@@ -1519,33 +1672,3 @@ void i915_destroy_error_state(struct drm_device *dev)
if (error)
kref_put(&error->ref, i915_error_state_free);
}
-
-const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
-{
- switch (type) {
- case I915_CACHE_NONE: return " uncached";
- case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
- case I915_CACHE_L3_LLC: return " L3+LLC";
- case I915_CACHE_WT: return " WT";
- default: return "";
- }
-}
-
-/* NB: please notice the memset */
-void i915_get_extra_instdone(struct drm_i915_private *dev_priv,
- uint32_t *instdone)
-{
- memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
-
- if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
- instdone[0] = I915_READ(GEN2_INSTDONE);
- else if (IS_GEN4(dev_priv) || IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) {
- instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
- instdone[1] = I915_READ(GEN4_INSTDONE1);
- } else if (INTEL_GEN(dev_priv) >= 7) {
- 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_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 3106dcc06fe9..4462112725ef 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -23,6 +23,8 @@
*/
#include <linux/firmware.h>
#include <linux/circ_buf.h>
+#include <linux/debugfs.h>
+#include <linux/relay.h>
#include "i915_drv.h"
#include "intel_guc.h"
@@ -85,6 +87,7 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
if (WARN_ON(len < 1 || len > 15))
return -EINVAL;
+ mutex_lock(&guc->action_lock);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
dev_priv->guc.action_count += 1;
@@ -123,6 +126,7 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
dev_priv->guc.action_status = status;
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+ mutex_unlock(&guc->action_lock);
return ret;
}
@@ -170,6 +174,35 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
return host2guc_action(guc, data, ARRAY_SIZE(data));
}
+static int host2guc_logbuffer_flush_complete(struct intel_guc *guc)
+{
+ u32 data[1];
+
+ data[0] = HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE;
+
+ return host2guc_action(guc, data, 1);
+}
+
+static int host2guc_force_logbuffer_flush(struct intel_guc *guc)
+{
+ u32 data[2];
+
+ data[0] = HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH;
+ data[1] = 0;
+
+ return host2guc_action(guc, data, 2);
+}
+
+static int host2guc_logging_control(struct intel_guc *guc, u32 control_val)
+{
+ u32 data[2];
+
+ data[0] = HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING;
+ data[1] = control_val;
+
+ return host2guc_action(guc, data, 2);
+}
+
/*
* Initialise, update, or clear doorbell data shared with the GuC
*
@@ -187,7 +220,7 @@ static int guc_update_doorbell_id(struct intel_guc *guc,
struct guc_context_desc desc;
size_t len;
- doorbell = client->client_base + client->doorbell_offset;
+ doorbell = client->vaddr + client->doorbell_offset;
if (client->doorbell_id != GUC_INVALID_DOORBELL_ID &&
test_bit(client->doorbell_id, doorbell_bitmap)) {
@@ -293,7 +326,7 @@ static void guc_proc_desc_init(struct intel_guc *guc,
{
struct guc_process_desc *desc;
- desc = client->client_base + client->proc_desc_offset;
+ desc = client->vaddr + client->proc_desc_offset;
memset(desc, 0, sizeof(*desc));
@@ -380,8 +413,8 @@ static void guc_ctx_desc_init(struct intel_guc *guc,
gfx_addr = i915_ggtt_offset(client->vma);
desc.db_trigger_phy = sg_dma_address(client->vma->pages->sgl) +
client->doorbell_offset;
- desc.db_trigger_cpu = (uintptr_t)client->client_base +
- client->doorbell_offset;
+ desc.db_trigger_cpu =
+ (uintptr_t)client->vaddr + client->doorbell_offset;
desc.db_trigger_uk = gfx_addr + client->doorbell_offset;
desc.process_desc = gfx_addr + client->proc_desc_offset;
desc.wq_addr = gfx_addr + client->wq_offset;
@@ -432,7 +465,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
{
const size_t wqi_size = sizeof(struct guc_wq_item);
struct i915_guc_client *gc = request->i915->guc.execbuf_client;
- struct guc_process_desc *desc = gc->client_base + gc->proc_desc_offset;
+ struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset;
u32 freespace;
int ret;
@@ -473,10 +506,9 @@ static void guc_wq_item_append(struct i915_guc_client *gc,
struct intel_engine_cs *engine = rq->engine;
struct guc_process_desc *desc;
struct guc_wq_item *wqi;
- void *base;
- u32 freespace, tail, wq_off, wq_page;
+ u32 freespace, tail, wq_off;
- desc = gc->client_base + gc->proc_desc_offset;
+ desc = gc->vaddr + gc->proc_desc_offset;
/* Free space is guaranteed, see i915_guc_wq_reserve() above */
freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
@@ -506,10 +538,7 @@ static void guc_wq_item_append(struct i915_guc_client *gc,
gc->wq_rsvd -= wqi_size;
/* WQ starts from the page after doorbell / process_desc */
- wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT;
- wq_off &= PAGE_SIZE - 1;
- base = kmap_atomic(i915_gem_object_get_page(gc->vma->obj, wq_page));
- wqi = (struct guc_wq_item *)((char *)base + wq_off);
+ wqi = gc->vaddr + wq_off + GUC_DB_SIZE;
/* Now fill in the 4-word work queue item */
wqi->header = WQ_TYPE_INORDER |
@@ -521,9 +550,7 @@ static void guc_wq_item_append(struct i915_guc_client *gc,
wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine);
wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
- wqi->fence_id = rq->fence.seqno;
-
- kunmap_atomic(base);
+ wqi->fence_id = rq->global_seqno;
}
static int guc_ring_doorbell(struct i915_guc_client *gc)
@@ -533,7 +560,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
union guc_doorbell_qw *db;
int attempt = 2, ret = -EAGAIN;
- desc = gc->client_base + gc->proc_desc_offset;
+ desc = gc->vaddr + gc->proc_desc_offset;
/* Update the tail so it is visible to GuC */
desc->tail = gc->wq_tail;
@@ -549,7 +576,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
db_exc.cookie = 1;
/* pointer of current doorbell cacheline */
- db = gc->client_base + gc->doorbell_offset;
+ db = gc->vaddr + gc->doorbell_offset;
while (attempt--) {
/* lets ring the doorbell */
@@ -601,13 +628,31 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
*/
static void i915_guc_submit(struct drm_i915_gem_request *rq)
{
- unsigned int engine_id = rq->engine->id;
+ struct drm_i915_private *dev_priv = rq->i915;
+ struct intel_engine_cs *engine = rq->engine;
+ unsigned int engine_id = engine->id;
struct intel_guc *guc = &rq->i915->guc;
struct i915_guc_client *client = guc->execbuf_client;
int b_ret;
+ /* We keep the previous context alive until we retire the following
+ * request. This ensures that any the context object is still pinned
+ * for any residual writes the HW makes into it on the context switch
+ * into the next object following the breadcrumb. Otherwise, we may
+ * retire the context too early.
+ */
+ rq->previous_context = engine->last_context;
+ engine->last_context = rq->ctx;
+
+ i915_gem_request_submit(rq);
+
spin_lock(&client->wq_lock);
guc_wq_item_append(client, rq);
+
+ /* WA to flush out the pending GMADR writes to ring buffer. */
+ if (i915_vma_is_map_and_fenceable(rq->ring->vma))
+ POSTING_READ_FW(GUC_STATUS);
+
b_ret = guc_ring_doorbell(client);
client->submissions[engine_id] += 1;
@@ -616,7 +661,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq)
client->b_fail += 1;
guc->submissions[engine_id] += 1;
- guc->last_seqno[engine_id] = rq->fence.seqno;
+ guc->last_seqno[engine_id] = rq->global_seqno;
spin_unlock(&client->wq_lock);
}
@@ -685,14 +730,14 @@ guc_client_free(struct drm_i915_private *dev_priv,
* Be sure to drop any locks
*/
- if (client->client_base) {
+ if (client->vaddr) {
/*
* If we got as far as setting up a doorbell, make sure we
* shut it down before unmapping & deallocating the memory.
*/
guc_disable_doorbell(guc, client);
- kunmap(kmap_to_page(client->client_base));
+ i915_gem_object_unpin_map(client->vma->obj);
}
i915_vma_unpin_and_release(&client->vma);
@@ -781,6 +826,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
struct i915_guc_client *client;
struct intel_guc *guc = &dev_priv->guc;
struct i915_vma *vma;
+ void *vaddr;
uint16_t db_id;
client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -807,7 +853,12 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
/* We'll keep just the first (doorbell/proc) page permanently kmap'd. */
client->vma = vma;
- client->client_base = kmap(i915_vma_first_page(vma));
+
+ vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
+ if (IS_ERR(vaddr))
+ goto err;
+
+ client->vaddr = vaddr;
spin_lock_init(&client->wq_lock);
client->wq_offset = GUC_DB_SIZE;
@@ -847,15 +898,411 @@ err:
return NULL;
}
+/*
+ * Sub buffer switch callback. Called whenever relay has to switch to a new
+ * sub buffer, relay stays on the same sub buffer if 0 is returned.
+ */
+static int subbuf_start_callback(struct rchan_buf *buf,
+ void *subbuf,
+ void *prev_subbuf,
+ size_t prev_padding)
+{
+ /* Use no-overwrite mode by default, where relay will stop accepting
+ * new data if there are no empty sub buffers left.
+ * There is no strict synchronization enforced by relay between Consumer
+ * and Producer. In overwrite mode, there is a possibility of getting
+ * inconsistent/garbled data, the producer could be writing on to the
+ * same sub buffer from which Consumer is reading. This can't be avoided
+ * unless Consumer is fast enough and can always run in tandem with
+ * Producer.
+ */
+ if (relay_buf_full(buf))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * file_create() callback. Creates relay file in debugfs.
+ */
+static struct dentry *create_buf_file_callback(const char *filename,
+ struct dentry *parent,
+ umode_t mode,
+ struct rchan_buf *buf,
+ int *is_global)
+{
+ struct dentry *buf_file;
+
+ /* This to enable the use of a single buffer for the relay channel and
+ * correspondingly have a single file exposed to User, through which
+ * it can collect the logs in order without any post-processing.
+ * Need to set 'is_global' even if parent is NULL for early logging.
+ */
+ *is_global = 1;
+
+ if (!parent)
+ return NULL;
+
+ /* Not using the channel filename passed as an argument, since for each
+ * channel relay appends the corresponding CPU number to the filename
+ * passed in relay_open(). This should be fine as relay just needs a
+ * dentry of the file associated with the channel buffer and that file's
+ * name need not be same as the filename passed as an argument.
+ */
+ buf_file = debugfs_create_file("guc_log", mode,
+ parent, buf, &relay_file_operations);
+ return buf_file;
+}
+
+/*
+ * file_remove() default callback. Removes relay file in debugfs.
+ */
+static int remove_buf_file_callback(struct dentry *dentry)
+{
+ debugfs_remove(dentry);
+ return 0;
+}
+
+/* relay channel callbacks */
+static struct rchan_callbacks relay_callbacks = {
+ .subbuf_start = subbuf_start_callback,
+ .create_buf_file = create_buf_file_callback,
+ .remove_buf_file = remove_buf_file_callback,
+};
+
+static void guc_log_remove_relay_file(struct intel_guc *guc)
+{
+ relay_close(guc->log.relay_chan);
+}
+
+static int guc_log_create_relay_channel(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct rchan *guc_log_relay_chan;
+ size_t n_subbufs, subbuf_size;
+
+ /* Keep the size of sub buffers same as shared log buffer */
+ subbuf_size = guc->log.vma->obj->base.size;
+
+ /* Store up to 8 snapshots, which is large enough to buffer sufficient
+ * boot time logs and provides enough leeway to User, in terms of
+ * latency, for consuming the logs from relay. Also doesn't take
+ * up too much memory.
+ */
+ n_subbufs = 8;
+
+ guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size,
+ n_subbufs, &relay_callbacks, dev_priv);
+ if (!guc_log_relay_chan) {
+ DRM_ERROR("Couldn't create relay chan for GuC logging\n");
+ return -ENOMEM;
+ }
+
+ GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size);
+ guc->log.relay_chan = guc_log_relay_chan;
+ return 0;
+}
+
+static int guc_log_create_relay_file(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct dentry *log_dir;
+ int ret;
+
+ /* For now create the log file in /sys/kernel/debug/dri/0 dir */
+ log_dir = dev_priv->drm.primary->debugfs_root;
+
+ /* If /sys/kernel/debug/dri/0 location do not exist, then debugfs is
+ * not mounted and so can't create the relay file.
+ * The relay API seems to fit well with debugfs only, for availing relay
+ * there are 3 requirements which can be met for debugfs file only in a
+ * straightforward/clean manner :-
+ * i) Need the associated dentry pointer of the file, while opening the
+ * relay channel.
+ * ii) Should be able to use 'relay_file_operations' fops for the file.
+ * iii) Set the 'i_private' field of file's inode to the pointer of
+ * relay channel buffer.
+ */
+ if (!log_dir) {
+ DRM_ERROR("Debugfs dir not available yet for GuC log file\n");
+ return -ENODEV;
+ }
+
+ ret = relay_late_setup_files(guc->log.relay_chan, "guc_log", log_dir);
+ if (ret) {
+ DRM_ERROR("Couldn't associate relay chan with file %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void guc_move_to_next_buf(struct intel_guc *guc)
+{
+ /* Make sure the updates made in the sub buffer are visible when
+ * Consumer sees the following update to offset inside the sub buffer.
+ */
+ smp_wmb();
+
+ /* All data has been written, so now move the offset of sub buffer. */
+ relay_reserve(guc->log.relay_chan, guc->log.vma->obj->base.size);
+
+ /* Switch to the next sub buffer */
+ relay_flush(guc->log.relay_chan);
+}
+
+static void *guc_get_write_buffer(struct intel_guc *guc)
+{
+ if (!guc->log.relay_chan)
+ return NULL;
+
+ /* Just get the base address of a new sub buffer and copy data into it
+ * ourselves. NULL will be returned in no-overwrite mode, if all sub
+ * buffers are full. Could have used the relay_write() to indirectly
+ * copy the data, but that would have been bit convoluted, as we need to
+ * write to only certain locations inside a sub buffer which cannot be
+ * done without using relay_reserve() along with relay_write(). So its
+ * better to use relay_reserve() alone.
+ */
+ return relay_reserve(guc->log.relay_chan, 0);
+}
+
+static bool
+guc_check_log_buf_overflow(struct intel_guc *guc,
+ enum guc_log_buffer_type type, unsigned int full_cnt)
+{
+ unsigned int prev_full_cnt = guc->log.prev_overflow_count[type];
+ bool overflow = false;
+
+ if (full_cnt != prev_full_cnt) {
+ overflow = true;
+
+ guc->log.prev_overflow_count[type] = full_cnt;
+ guc->log.total_overflow_count[type] += full_cnt - prev_full_cnt;
+
+ if (full_cnt < prev_full_cnt) {
+ /* buffer_full_cnt is a 4 bit counter */
+ guc->log.total_overflow_count[type] += 16;
+ }
+ DRM_ERROR_RATELIMITED("GuC log buffer overflow\n");
+ }
+
+ return overflow;
+}
+
+static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type)
+{
+ switch (type) {
+ case GUC_ISR_LOG_BUFFER:
+ return (GUC_LOG_ISR_PAGES + 1) * PAGE_SIZE;
+ case GUC_DPC_LOG_BUFFER:
+ return (GUC_LOG_DPC_PAGES + 1) * PAGE_SIZE;
+ case GUC_CRASH_DUMP_LOG_BUFFER:
+ return (GUC_LOG_CRASH_PAGES + 1) * PAGE_SIZE;
+ default:
+ MISSING_CASE(type);
+ }
+
+ return 0;
+}
+
+static void guc_read_update_log_buffer(struct intel_guc *guc)
+{
+ unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt;
+ struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state;
+ struct guc_log_buffer_state log_buf_state_local;
+ enum guc_log_buffer_type type;
+ void *src_data, *dst_data;
+ bool new_overflow;
+
+ if (WARN_ON(!guc->log.buf_addr))
+ return;
+
+ /* Get the pointer to shared GuC log buffer */
+ log_buf_state = src_data = guc->log.buf_addr;
+
+ /* Get the pointer to local buffer to store the logs */
+ log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc);
+
+ /* Actual logs are present from the 2nd page */
+ src_data += PAGE_SIZE;
+ dst_data += PAGE_SIZE;
+
+ for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
+ /* Make a copy of the state structure, inside GuC log buffer
+ * (which is uncached mapped), on the stack to avoid reading
+ * from it multiple times.
+ */
+ memcpy(&log_buf_state_local, log_buf_state,
+ sizeof(struct guc_log_buffer_state));
+ buffer_size = guc_get_log_buffer_size(type);
+ read_offset = log_buf_state_local.read_ptr;
+ write_offset = log_buf_state_local.sampled_write_ptr;
+ full_cnt = log_buf_state_local.buffer_full_cnt;
+
+ /* Bookkeeping stuff */
+ guc->log.flush_count[type] += log_buf_state_local.flush_to_file;
+ new_overflow = guc_check_log_buf_overflow(guc, type, full_cnt);
+
+ /* Update the state of shared log buffer */
+ log_buf_state->read_ptr = write_offset;
+ log_buf_state->flush_to_file = 0;
+ log_buf_state++;
+
+ if (unlikely(!log_buf_snapshot_state))
+ continue;
+
+ /* First copy the state structure in snapshot buffer */
+ memcpy(log_buf_snapshot_state, &log_buf_state_local,
+ sizeof(struct guc_log_buffer_state));
+
+ /* The write pointer could have been updated by GuC firmware,
+ * after sending the flush interrupt to Host, for consistency
+ * set write pointer value to same value of sampled_write_ptr
+ * in the snapshot buffer.
+ */
+ log_buf_snapshot_state->write_ptr = write_offset;
+ log_buf_snapshot_state++;
+
+ /* Now copy the actual logs. */
+ if (unlikely(new_overflow)) {
+ /* copy the whole buffer in case of overflow */
+ read_offset = 0;
+ write_offset = buffer_size;
+ } else if (unlikely((read_offset > buffer_size) ||
+ (write_offset > buffer_size))) {
+ DRM_ERROR("invalid log buffer state\n");
+ /* copy whole buffer as offsets are unreliable */
+ read_offset = 0;
+ write_offset = buffer_size;
+ }
+
+ /* Just copy the newly written data */
+ if (read_offset > write_offset) {
+ i915_memcpy_from_wc(dst_data, src_data, write_offset);
+ bytes_to_copy = buffer_size - read_offset;
+ } else {
+ bytes_to_copy = write_offset - read_offset;
+ }
+ i915_memcpy_from_wc(dst_data + read_offset,
+ src_data + read_offset, bytes_to_copy);
+
+ src_data += buffer_size;
+ dst_data += buffer_size;
+ }
+
+ if (log_buf_snapshot_state)
+ guc_move_to_next_buf(guc);
+ else {
+ /* Used rate limited to avoid deluge of messages, logs might be
+ * getting consumed by User at a slow rate.
+ */
+ DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n");
+ guc->log.capture_miss_count++;
+ }
+}
+
+static void guc_capture_logs_work(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, guc.log.flush_work);
+
+ i915_guc_capture_logs(dev_priv);
+}
+
+static void guc_log_cleanup(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+ /* First disable the flush interrupt */
+ gen9_disable_guc_interrupts(dev_priv);
+
+ if (guc->log.flush_wq)
+ destroy_workqueue(guc->log.flush_wq);
+
+ guc->log.flush_wq = NULL;
+
+ if (guc->log.relay_chan)
+ guc_log_remove_relay_file(guc);
+
+ guc->log.relay_chan = NULL;
+
+ if (guc->log.buf_addr)
+ i915_gem_object_unpin_map(guc->log.vma->obj);
+
+ guc->log.buf_addr = NULL;
+}
+
+static int guc_log_create_extras(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ void *vaddr;
+ int ret;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+ /* Nothing to do */
+ if (i915.guc_log_level < 0)
+ return 0;
+
+ if (!guc->log.buf_addr) {
+ /* Create a WC (Uncached for read) vmalloc mapping of log
+ * buffer pages, so that we can directly get the data
+ * (up-to-date) from memory.
+ */
+ vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC);
+ if (IS_ERR(vaddr)) {
+ ret = PTR_ERR(vaddr);
+ DRM_ERROR("Couldn't map log buffer pages %d\n", ret);
+ return ret;
+ }
+
+ guc->log.buf_addr = vaddr;
+ }
+
+ if (!guc->log.relay_chan) {
+ /* Create a relay channel, so that we have buffers for storing
+ * the GuC firmware logs, the channel will be linked with a file
+ * later on when debugfs is registered.
+ */
+ ret = guc_log_create_relay_channel(guc);
+ if (ret)
+ return ret;
+ }
+
+ if (!guc->log.flush_wq) {
+ INIT_WORK(&guc->log.flush_work, guc_capture_logs_work);
+
+ /*
+ * GuC log buffer flush work item has to do register access to
+ * send the ack to GuC and this work item, if not synced before
+ * suspend, can potentially get executed after the GFX device is
+ * suspended.
+ * By marking the WQ as freezable, we don't have to bother about
+ * flushing of this work item from the suspend hooks, the pending
+ * work item if any will be either executed before the suspend
+ * or scheduled later on resume. This way the handling of work
+ * item can be kept same between system suspend & rpm suspend.
+ */
+ guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log",
+ WQ_HIGHPRI | WQ_FREEZABLE);
+ if (guc->log.flush_wq == NULL) {
+ DRM_ERROR("Couldn't allocate the wq for GuC logging\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
static void guc_log_create(struct intel_guc *guc)
{
struct i915_vma *vma;
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;
@@ -865,8 +1312,18 @@ static void guc_log_create(struct intel_guc *guc)
GUC_LOG_ISR_PAGES + 1 +
GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT;
- vma = guc->log_vma;
+ vma = guc->log.vma;
if (!vma) {
+ /* We require SSE 4.1 for fast reads from the GuC log buffer and
+ * it should be present on the chipsets supporting GuC based
+ * submisssions.
+ */
+ if (WARN_ON(!i915_memcpy_from_wc(NULL, NULL, 0))) {
+ /* logging will not be enabled */
+ i915.guc_log_level = -1;
+ return;
+ }
+
vma = guc_allocate_vma(guc, size);
if (IS_ERR(vma)) {
/* logging will be off */
@@ -874,7 +1331,14 @@ static void guc_log_create(struct intel_guc *guc)
return;
}
- guc->log_vma = vma;
+ guc->log.vma = vma;
+
+ if (guc_log_create_extras(guc)) {
+ guc_log_cleanup(guc);
+ i915_vma_unpin_and_release(&guc->log.vma);
+ i915.guc_log_level = -1;
+ return;
+ }
}
/* each allocated unit is a page */
@@ -884,7 +1348,37 @@ static void guc_log_create(struct intel_guc *guc)
(GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
offset = i915_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */
- guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
+ guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
+}
+
+static int guc_log_late_setup(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ int ret;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+ if (i915.guc_log_level < 0)
+ return -EINVAL;
+
+ /* If log_level was set as -1 at boot time, then setup needed to
+ * handle log buffer flush interrupts would not have been done yet,
+ * so do that now.
+ */
+ ret = guc_log_create_extras(guc);
+ if (ret)
+ goto err;
+
+ ret = guc_log_create_relay_file(guc);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ guc_log_cleanup(guc);
+ /* logging will remain off */
+ i915.guc_log_level = -1;
+ return ret;
}
static void guc_policies_init(struct guc_policies *policies)
@@ -917,6 +1411,7 @@ static void guc_addon_create(struct intel_guc *guc)
struct guc_policies *policies;
struct guc_mmio_reg_state *reg_state;
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
struct page *page;
u32 size;
@@ -944,10 +1439,10 @@ static void guc_addon_create(struct intel_guc *guc)
* so its address won't change after we've told the GuC where
* to find it.
*/
- engine = &dev_priv->engine[RCS];
+ engine = dev_priv->engine[RCS];
ads->golden_context_lrca = engine->status_page.ggtt_offset;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine);
/* GuC scheduling policies */
@@ -960,7 +1455,7 @@ static void guc_addon_create(struct intel_guc *guc)
/* MMIO reg state */
reg_state = (void *)policies + sizeof(struct guc_policies);
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
reg_state->mmio_white_list[engine->guc_id].mmio_start =
engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
@@ -1005,6 +1500,7 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
guc->ctx_pool_vma = vma;
ida_init(&guc->ctx_ids);
+ mutex_init(&guc->action_lock);
guc_log_create(guc);
guc_addon_create(guc);
@@ -1014,9 +1510,10 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
{
struct intel_guc *guc = &dev_priv->guc;
+ struct drm_i915_gem_request *request;
struct i915_guc_client *client;
struct intel_engine_cs *engine;
- struct drm_i915_gem_request *request;
+ enum intel_engine_id id;
/* client for execbuf submission */
client = guc_client_alloc(dev_priv,
@@ -1033,11 +1530,13 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
guc_init_doorbell_hw(guc);
/* Take over from manual control of ELSP (execlists) */
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
engine->submit_request = i915_guc_submit;
+ engine->schedule = NULL;
/* Replay the current set of previously submitted requests */
- list_for_each_entry(request, &engine->request_list, link) {
+ list_for_each_entry(request,
+ &engine->timeline->requests, link) {
client->wq_rsvd += sizeof(struct guc_wq_item);
if (i915_sw_fence_done(&request->submit))
i915_guc_submit(request);
@@ -1066,7 +1565,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
struct intel_guc *guc = &dev_priv->guc;
i915_vma_unpin_and_release(&guc->ads_vma);
- i915_vma_unpin_and_release(&guc->log_vma);
+ i915_vma_unpin_and_release(&guc->log.vma);
if (guc->ctx_pool_vma)
ida_destroy(&guc->ctx_ids);
@@ -1087,6 +1586,8 @@ int intel_guc_suspend(struct drm_device *dev)
if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
return 0;
+ gen9_disable_guc_interrupts(dev_priv);
+
ctx = dev_priv->kernel_context;
data[0] = HOST2GUC_ACTION_ENTER_S_STATE;
@@ -1113,6 +1614,9 @@ int intel_guc_resume(struct drm_device *dev)
if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
return 0;
+ if (i915.guc_log_level >= 0)
+ gen9_enable_guc_interrupts(dev_priv);
+
ctx = dev_priv->kernel_context;
data[0] = HOST2GUC_ACTION_EXIT_S_STATE;
@@ -1122,3 +1626,104 @@ int intel_guc_resume(struct drm_device *dev)
return host2guc_action(guc, data, ARRAY_SIZE(data));
}
+
+void i915_guc_capture_logs(struct drm_i915_private *dev_priv)
+{
+ guc_read_update_log_buffer(&dev_priv->guc);
+
+ /* Generally device is expected to be active only at this
+ * time, so get/put should be really quick.
+ */
+ intel_runtime_pm_get(dev_priv);
+ host2guc_logbuffer_flush_complete(&dev_priv->guc);
+ intel_runtime_pm_put(dev_priv);
+}
+
+void i915_guc_flush_logs(struct drm_i915_private *dev_priv)
+{
+ if (!i915.enable_guc_submission || (i915.guc_log_level < 0))
+ return;
+
+ /* First disable the interrupts, will be renabled afterwards */
+ gen9_disable_guc_interrupts(dev_priv);
+
+ /* Before initiating the forceful flush, wait for any pending/ongoing
+ * flush to complete otherwise forceful flush may not actually happen.
+ */
+ flush_work(&dev_priv->guc.log.flush_work);
+
+ /* Ask GuC to update the log buffer state */
+ host2guc_force_logbuffer_flush(&dev_priv->guc);
+
+ /* GuC would have updated log buffer by now, so capture it */
+ i915_guc_capture_logs(dev_priv);
+}
+
+void i915_guc_unregister(struct drm_i915_private *dev_priv)
+{
+ if (!i915.enable_guc_submission)
+ return;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ guc_log_cleanup(&dev_priv->guc);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+void i915_guc_register(struct drm_i915_private *dev_priv)
+{
+ if (!i915.enable_guc_submission)
+ return;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ guc_log_late_setup(&dev_priv->guc);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val)
+{
+ union guc_log_control log_param;
+ int ret;
+
+ log_param.value = control_val;
+
+ if (log_param.verbosity < GUC_LOG_VERBOSITY_MIN ||
+ log_param.verbosity > GUC_LOG_VERBOSITY_MAX)
+ return -EINVAL;
+
+ /* This combination doesn't make sense & won't have any effect */
+ if (!log_param.logging_enabled && (i915.guc_log_level < 0))
+ return 0;
+
+ ret = host2guc_logging_control(&dev_priv->guc, log_param.value);
+ if (ret < 0) {
+ DRM_DEBUG_DRIVER("host2guc action failed %d\n", ret);
+ return ret;
+ }
+
+ i915.guc_log_level = log_param.verbosity;
+
+ /* If log_level was set as -1 at boot time, then the relay channel file
+ * wouldn't have been created by now and interrupts also would not have
+ * been enabled.
+ */
+ if (!dev_priv->guc.log.relay_chan) {
+ ret = guc_log_late_setup(&dev_priv->guc);
+ if (!ret)
+ gen9_enable_guc_interrupts(dev_priv);
+ } else if (!log_param.logging_enabled) {
+ /* Once logging is disabled, GuC won't generate logs & send an
+ * interrupt. But there could be some data in the log buffer
+ * which is yet to be captured. So request GuC to update the log
+ * buffer state and then collect the left over logs.
+ */
+ i915_guc_flush_logs(dev_priv);
+
+ /* As logging is disabled, update log level to reflect that */
+ i915.guc_log_level = -1;
+ } else {
+ /* In case interrupts were disabled, enable them now */
+ gen9_enable_guc_interrupts(dev_priv);
+ }
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3fc286cd1157..07ca71cabb2b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -170,6 +170,7 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv,
} while (0)
static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
+static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
/* For display hotplug interrupt */
static inline void
@@ -303,18 +304,18 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
assert_spin_locked(&dev_priv->irq_lock);
- new_val = dev_priv->pm_irq_mask;
+ new_val = dev_priv->pm_imr;
new_val &= ~interrupt_mask;
new_val |= (~enabled_irq_mask & interrupt_mask);
- if (new_val != dev_priv->pm_irq_mask) {
- dev_priv->pm_irq_mask = new_val;
- I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_irq_mask);
+ if (new_val != dev_priv->pm_imr) {
+ dev_priv->pm_imr = new_val;
+ I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr);
POSTING_READ(gen6_pm_imr(dev_priv));
}
}
-void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
{
if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
@@ -322,28 +323,54 @@ void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
snb_update_pm_irq(dev_priv, mask, mask);
}
-static void __gen6_disable_pm_irq(struct drm_i915_private *dev_priv,
- uint32_t mask)
+static void __gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
{
snb_update_pm_irq(dev_priv, mask, 0);
}
-void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
{
if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
- __gen6_disable_pm_irq(dev_priv, mask);
+ __gen6_mask_pm_irq(dev_priv, mask);
}
-void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv)
+void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask)
{
i915_reg_t reg = gen6_pm_iir(dev_priv);
- spin_lock_irq(&dev_priv->irq_lock);
- I915_WRITE(reg, dev_priv->pm_rps_events);
- I915_WRITE(reg, dev_priv->pm_rps_events);
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ I915_WRITE(reg, reset_mask);
+ I915_WRITE(reg, reset_mask);
POSTING_READ(reg);
+}
+
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask)
+{
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ dev_priv->pm_ier |= enable_mask;
+ I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier);
+ gen6_unmask_pm_irq(dev_priv, enable_mask);
+ /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */
+}
+
+void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask)
+{
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ dev_priv->pm_ier &= ~disable_mask;
+ __gen6_mask_pm_irq(dev_priv, disable_mask);
+ I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier);
+ /* though a barrier is missing here, but don't really need a one */
+}
+
+void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ gen6_reset_pm_iir(dev_priv, dev_priv->pm_rps_events);
dev_priv->rps.pm_iir = 0;
spin_unlock_irq(&dev_priv->irq_lock);
}
@@ -357,8 +384,6 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
WARN_ON_ONCE(dev_priv->rps.pm_iir);
WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events);
dev_priv->rps.interrupts_enabled = true;
- I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) |
- dev_priv->pm_rps_events);
gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
spin_unlock_irq(&dev_priv->irq_lock);
@@ -379,9 +404,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u));
- __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
- I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) &
- ~dev_priv->pm_rps_events);
+ gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
spin_unlock_irq(&dev_priv->irq_lock);
synchronize_irq(dev_priv->drm.irq);
@@ -395,6 +418,38 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
gen6_reset_rps_interrupts(dev_priv);
}
+void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ gen6_reset_pm_iir(dev_priv, dev_priv->pm_guc_events);
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ if (!dev_priv->guc.interrupts_enabled) {
+ WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) &
+ dev_priv->pm_guc_events);
+ dev_priv->guc.interrupts_enabled = true;
+ gen6_enable_pm_irq(dev_priv, dev_priv->pm_guc_events);
+ }
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ dev_priv->guc.interrupts_enabled = false;
+
+ gen6_disable_pm_irq(dev_priv, dev_priv->pm_guc_events);
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+ synchronize_irq(dev_priv->drm.irq);
+
+ gen9_reset_guc_interrupts(dev_priv);
+}
+
/**
* bdw_update_port_irq - update DE port interrupt
* @dev_priv: driver private
@@ -670,8 +725,8 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
struct drm_i915_private *dev_priv = to_i915(dev);
i915_reg_t high_frame, low_frame;
u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
- struct intel_crtc *intel_crtc =
- to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
const struct drm_display_mode *mode = &intel_crtc->base.hwmode;
htotal = mode->crtc_htotal;
@@ -776,8 +831,8 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
const struct drm_display_mode *mode)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
int position;
int vbl_start, vbl_end, hsync_start, htotal, vtotal;
bool in_vbl = true;
@@ -912,21 +967,22 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
struct timeval *vblank_time,
unsigned flags)
{
- struct drm_crtc *crtc;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_crtc *crtc;
- if (pipe >= INTEL_INFO(dev)->num_pipes) {
+ if (pipe >= INTEL_INFO(dev_priv)->num_pipes) {
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
/* Get drm_crtc to timestamp: */
- crtc = intel_get_crtc_for_pipe(dev, pipe);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc == NULL) {
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
- if (!crtc->hwmode.crtc_clock) {
+ if (!crtc->base.hwmode.crtc_clock) {
DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
return -EBUSY;
}
@@ -934,7 +990,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
/* Helper routine in DRM core does all the work: */
return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
vblank_time, flags,
- &crtc->hwmode);
+ &crtc->base.hwmode);
}
static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
@@ -1058,8 +1114,9 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
static bool any_waiters(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
if (intel_engine_has_waiter(engine))
return true;
@@ -1084,7 +1141,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
pm_iir = dev_priv->rps.pm_iir;
dev_priv->rps.pm_iir = 0;
/* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
- gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+ gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events);
client_boost = dev_priv->rps.client_boost;
dev_priv->rps.client_boost = false;
spin_unlock_irq(&dev_priv->irq_lock);
@@ -1257,20 +1314,20 @@ static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv,
u32 gt_iir)
{
if (gt_iir & GT_RENDER_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[RCS]);
+ notify_ring(dev_priv->engine[RCS]);
if (gt_iir & ILK_BSD_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[VCS]);
+ notify_ring(dev_priv->engine[VCS]);
}
static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
u32 gt_iir)
{
if (gt_iir & GT_RENDER_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[RCS]);
+ notify_ring(dev_priv->engine[RCS]);
if (gt_iir & GT_BSD_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[VCS]);
+ notify_ring(dev_priv->engine[VCS]);
if (gt_iir & GT_BLT_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[BCS]);
+ notify_ring(dev_priv->engine[BCS]);
if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
GT_BSD_CS_ERROR_INTERRUPT |
@@ -1323,11 +1380,13 @@ static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv,
DRM_ERROR("The master control interrupt lied (GT3)!\n");
}
- if (master_ctl & GEN8_GT_PM_IRQ) {
+ if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) {
gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2));
- if (gt_iir[2] & dev_priv->pm_rps_events) {
+ if (gt_iir[2] & (dev_priv->pm_rps_events |
+ dev_priv->pm_guc_events)) {
I915_WRITE_FW(GEN8_GT_IIR(2),
- gt_iir[2] & dev_priv->pm_rps_events);
+ gt_iir[2] & (dev_priv->pm_rps_events |
+ dev_priv->pm_guc_events));
ret = IRQ_HANDLED;
} else
DRM_ERROR("The master control interrupt lied (PM)!\n");
@@ -1340,25 +1399,28 @@ static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
u32 gt_iir[4])
{
if (gt_iir[0]) {
- gen8_cs_irq_handler(&dev_priv->engine[RCS],
+ gen8_cs_irq_handler(dev_priv->engine[RCS],
gt_iir[0], GEN8_RCS_IRQ_SHIFT);
- gen8_cs_irq_handler(&dev_priv->engine[BCS],
+ gen8_cs_irq_handler(dev_priv->engine[BCS],
gt_iir[0], GEN8_BCS_IRQ_SHIFT);
}
if (gt_iir[1]) {
- gen8_cs_irq_handler(&dev_priv->engine[VCS],
+ gen8_cs_irq_handler(dev_priv->engine[VCS],
gt_iir[1], GEN8_VCS1_IRQ_SHIFT);
- gen8_cs_irq_handler(&dev_priv->engine[VCS2],
+ gen8_cs_irq_handler(dev_priv->engine[VCS2],
gt_iir[1], GEN8_VCS2_IRQ_SHIFT);
}
if (gt_iir[3])
- gen8_cs_irq_handler(&dev_priv->engine[VECS],
+ gen8_cs_irq_handler(dev_priv->engine[VECS],
gt_iir[3], GEN8_VECS_IRQ_SHIFT);
if (gt_iir[2] & dev_priv->pm_rps_events)
gen6_rps_irq_handler(dev_priv, gt_iir[2]);
+
+ if (gt_iir[2] & dev_priv->pm_guc_events)
+ gen9_guc_irq_handler(dev_priv, gt_iir[2]);
}
static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
@@ -1585,7 +1647,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
{
if (pm_iir & dev_priv->pm_rps_events) {
spin_lock(&dev_priv->irq_lock);
- gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+ gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
if (dev_priv->rps.interrupts_enabled) {
dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
schedule_work(&dev_priv->rps.work);
@@ -1598,13 +1660,48 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
if (HAS_VEBOX(dev_priv)) {
if (pm_iir & PM_VEBOX_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[VECS]);
+ notify_ring(dev_priv->engine[VECS]);
if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
}
}
+static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
+{
+ if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) {
+ /* Sample the log buffer flush related bits & clear them out now
+ * itself from the message identity register to minimize the
+ * probability of losing a flush interrupt, when there are back
+ * to back flush interrupts.
+ * There can be a new flush interrupt, for different log buffer
+ * type (like for ISR), whilst Host is handling one (for DPC).
+ * Since same bit is used in message register for ISR & DPC, it
+ * could happen that GuC sets the bit for 2nd interrupt but Host
+ * clears out the bit on handling the 1st interrupt.
+ */
+ u32 msg, flush;
+
+ msg = I915_READ(SOFT_SCRATCH(15));
+ flush = msg & (GUC2HOST_MSG_CRASH_DUMP_POSTED |
+ GUC2HOST_MSG_FLUSH_LOG_BUFFER);
+ if (flush) {
+ /* Clear the message bits that are handled */
+ I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
+
+ /* Handle flush interrupt in bottom half */
+ queue_work(dev_priv->guc.log.flush_wq,
+ &dev_priv->guc.log.flush_work);
+
+ dev_priv->guc.log.flush_interrupt_count++;
+ } else {
+ /* Not clearing of unhandled event bits won't result in
+ * re-triggering of the interrupt.
+ */
+ }
+ }
+}
+
static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
@@ -2407,7 +2504,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
if (fault_errors)
- DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
+ DRM_ERROR("Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
fault_errors);
}
@@ -2551,92 +2648,52 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
wake_up_all(&dev_priv->gpu_error.reset_queue);
}
-static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv)
+static inline void
+i915_err_print_instdone(struct drm_i915_private *dev_priv,
+ struct intel_instdone *instdone)
{
- uint32_t instdone[I915_NUM_INSTDONE_REG];
- u32 eir = I915_READ(EIR);
- int pipe, i;
+ int slice;
+ int subslice;
+
+ pr_err(" INSTDONE: 0x%08x\n", instdone->instdone);
+
+ if (INTEL_GEN(dev_priv) <= 3)
+ return;
+
+ pr_err(" SC_INSTDONE: 0x%08x\n", instdone->slice_common);
- if (!eir)
+ if (INTEL_GEN(dev_priv) <= 6)
return;
- pr_err("render error detected, EIR: 0x%08x\n", eir);
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+ pr_err(" SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice, instdone->sampler[slice][subslice]);
- i915_get_extra_instdone(dev_priv, instdone);
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+ pr_err(" ROW_INSTDONE[%d][%d]: 0x%08x\n",
+ slice, subslice, instdone->row[slice][subslice]);
+}
- if (IS_G4X(dev_priv)) {
- if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
- u32 ipeir = I915_READ(IPEIR_I965);
-
- pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
- pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
- for (i = 0; i < ARRAY_SIZE(instdone); i++)
- pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]);
- pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS));
- pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
- I915_WRITE(IPEIR_I965, ipeir);
- POSTING_READ(IPEIR_I965);
- }
- if (eir & GM45_ERROR_PAGE_TABLE) {
- u32 pgtbl_err = I915_READ(PGTBL_ER);
- pr_err("page table error\n");
- pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err);
- I915_WRITE(PGTBL_ER, pgtbl_err);
- POSTING_READ(PGTBL_ER);
- }
- }
+static void i915_clear_error_registers(struct drm_i915_private *dev_priv)
+{
+ u32 eir;
- if (!IS_GEN2(dev_priv)) {
- if (eir & I915_ERROR_PAGE_TABLE) {
- u32 pgtbl_err = I915_READ(PGTBL_ER);
- pr_err("page table error\n");
- pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err);
- I915_WRITE(PGTBL_ER, pgtbl_err);
- POSTING_READ(PGTBL_ER);
- }
- }
+ if (!IS_GEN2(dev_priv))
+ I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER));
- if (eir & I915_ERROR_MEMORY_REFRESH) {
- pr_err("memory refresh error:\n");
- for_each_pipe(dev_priv, pipe)
- pr_err("pipe %c stat: 0x%08x\n",
- pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
- /* pipestat has already been acked */
- }
- if (eir & I915_ERROR_INSTRUCTION) {
- pr_err("instruction error\n");
- pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM));
- for (i = 0; i < ARRAY_SIZE(instdone); i++)
- pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]);
- if (INTEL_GEN(dev_priv) < 4) {
- u32 ipeir = I915_READ(IPEIR);
-
- pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR));
- pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR));
- pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD));
- I915_WRITE(IPEIR, ipeir);
- POSTING_READ(IPEIR);
- } else {
- u32 ipeir = I915_READ(IPEIR_I965);
-
- pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
- pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
- pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS));
- pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
- I915_WRITE(IPEIR_I965, ipeir);
- POSTING_READ(IPEIR_I965);
- }
- }
+ if (INTEL_GEN(dev_priv) < 4)
+ I915_WRITE(IPEIR, I915_READ(IPEIR));
+ else
+ I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965));
- I915_WRITE(EIR, eir);
- POSTING_READ(EIR);
+ I915_WRITE(EIR, I915_READ(EIR));
eir = I915_READ(EIR);
if (eir) {
/*
* some errors might have become stuck,
* mask them.
*/
- DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
+ DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir);
I915_WRITE(EMR, I915_READ(EMR) | eir);
I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
}
@@ -2665,7 +2722,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
va_end(args);
i915_capture_error_state(dev_priv, engine_mask, error_msg);
- i915_report_and_clear_eir(dev_priv);
+ i915_clear_error_registers(dev_priv);
if (!engine_mask)
return;
@@ -2694,45 +2751,40 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
-static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- if (INTEL_INFO(dev)->gen >= 4)
- i915_enable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_STATUS);
- else
- i915_enable_pipestat(dev_priv, pipe,
- PIPE_VBLANK_INTERRUPT_STATUS);
+ i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
return 0;
}
-static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
- uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
- DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- ilk_enable_display_irq(dev_priv, bit);
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
return 0;
}
-static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
+ uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+ DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_enable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_STATUS);
+ ilk_enable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
return 0;
@@ -2753,38 +2805,36 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned 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, unsigned int pipe)
+static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_disable_pipestat(dev_priv, pipe,
- PIPE_VBLANK_INTERRUPT_STATUS |
- PIPE_START_VBLANK_INTERRUPT_STATUS);
+ i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
- uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
- DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- ilk_disable_display_irq(dev_priv, bit);
+ i915_disable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
+ uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+ DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_disable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_STATUS);
+ ilk_disable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
@@ -2798,411 +2848,14 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-static bool
-ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr)
-{
- if (INTEL_GEN(engine->i915) >= 8) {
- return (ipehr >> 23) == 0x1c;
- } else {
- ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
- return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
- MI_SEMAPHORE_REGISTER);
- }
-}
-
-static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
- u64 offset)
-{
- struct drm_i915_private *dev_priv = engine->i915;
- struct intel_engine_cs *signaller;
-
- if (INTEL_GEN(dev_priv) >= 8) {
- for_each_engine(signaller, dev_priv) {
- if (engine == signaller)
- continue;
-
- if (offset == signaller->semaphore.signal_ggtt[engine->hw_id])
- return signaller;
- }
- } else {
- u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
-
- for_each_engine(signaller, dev_priv) {
- if(engine == signaller)
- continue;
-
- if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id])
- return signaller;
- }
- }
-
- DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n",
- engine->name, ipehr, offset);
-
- return ERR_PTR(-ENODEV);
-}
-
-static struct intel_engine_cs *
-semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
+static void ibx_irq_reset(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = engine->i915;
- void __iomem *vaddr;
- u32 cmd, ipehr, head;
- 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 (engine->buffer == NULL)
- return NULL;
-
- ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
- if (!ipehr_is_semaphore_wait(engine, ipehr))
- return NULL;
-
- /*
- * HEAD is likely pointing to the dword after the actual command,
- * so scan backwards until we find the MBOX. But limit it to just 3
- * or 4 dwords depending on the semaphore wait command size.
- * Note that we don't care about ACTHD here since that might
- * point at at batch, and semaphores are always emitted into the
- * ringbuffer itself.
- */
- head = I915_READ_HEAD(engine) & HEAD_ADDR;
- backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4;
- vaddr = (void __iomem *)engine->buffer->vaddr;
-
- for (i = backwards; i; --i) {
- /*
- * Be paranoid and presume the hw has gone off into the wild -
- * our ring is smaller than what the hardware (and hence
- * HEAD_ADDR) allows. Also handles wrap-around.
- */
- head &= engine->buffer->size - 1;
-
- /* This here seems to blow up */
- cmd = ioread32(vaddr + head);
- if (cmd == ipehr)
- break;
-
- head -= 4;
- }
-
- if (!i)
- return NULL;
-
- *seqno = ioread32(vaddr + head + 4) + 1;
- if (INTEL_GEN(dev_priv) >= 8) {
- offset = ioread32(vaddr + head + 12);
- offset <<= 32;
- offset |= ioread32(vaddr + head + 8);
- }
- return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
-}
-
-static int semaphore_passed(struct intel_engine_cs *engine)
-{
- struct drm_i915_private *dev_priv = engine->i915;
- struct intel_engine_cs *signaller;
- u32 seqno;
-
- engine->hangcheck.deadlock++;
-
- signaller = semaphore_waits_for(engine, &seqno);
- if (signaller == NULL)
- return -1;
-
- if (IS_ERR(signaller))
- return 0;
-
- /* Prevent pathological recursion due to driver bugs */
- if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
- return -1;
-
- if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno))
- return 1;
-
- /* cursory check for an unkickable deadlock */
- if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
- semaphore_passed(signaller) < 0)
- return -1;
-
- return 0;
-}
-
-static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
-{
- struct intel_engine_cs *engine;
-
- for_each_engine(engine, dev_priv)
- engine->hangcheck.deadlock = 0;
-}
-
-static bool subunits_stuck(struct intel_engine_cs *engine)
-{
- u32 instdone[I915_NUM_INSTDONE_REG];
- bool stuck;
- int i;
-
- if (engine->id != RCS)
- return true;
-
- i915_get_extra_instdone(engine->i915, instdone);
-
- /* There might be unstable subunit states even when
- * actual head is not moving. Filter out the unstable ones by
- * accumulating the undone -> done transitions and only
- * consider those as progress.
- */
- stuck = true;
- for (i = 0; i < I915_NUM_INSTDONE_REG; i++) {
- const u32 tmp = instdone[i] | engine->hangcheck.instdone[i];
-
- if (tmp != engine->hangcheck.instdone[i])
- stuck = false;
-
- engine->hangcheck.instdone[i] |= tmp;
- }
-
- return stuck;
-}
-
-static enum intel_engine_hangcheck_action
-head_stuck(struct intel_engine_cs *engine, u64 acthd)
-{
- if (acthd != engine->hangcheck.acthd) {
-
- /* Clear subunit states on head movement */
- memset(engine->hangcheck.instdone, 0,
- sizeof(engine->hangcheck.instdone));
-
- return HANGCHECK_ACTIVE;
- }
-
- if (!subunits_stuck(engine))
- return HANGCHECK_ACTIVE;
-
- return HANGCHECK_HUNG;
-}
-
-static enum intel_engine_hangcheck_action
-engine_stuck(struct intel_engine_cs *engine, u64 acthd)
-{
- struct drm_i915_private *dev_priv = engine->i915;
- enum intel_engine_hangcheck_action ha;
- u32 tmp;
-
- ha = head_stuck(engine, acthd);
- if (ha != HANGCHECK_HUNG)
- return ha;
-
- if (IS_GEN2(dev_priv))
- return HANGCHECK_HUNG;
-
- /* Is the chip hanging on a WAIT_FOR_EVENT?
- * If so we can simply poke the RB_WAIT bit
- * and break the hang. This should work on
- * all but the second generation chipsets.
- */
- tmp = I915_READ_CTL(engine);
- if (tmp & RING_WAIT) {
- i915_handle_error(dev_priv, 0,
- "Kicking stuck wait on %s",
- engine->name);
- I915_WRITE_CTL(engine, tmp);
- return HANGCHECK_KICK;
- }
-
- if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) {
- switch (semaphore_passed(engine)) {
- default:
- return HANGCHECK_HUNG;
- case 1:
- i915_handle_error(dev_priv, 0,
- "Kicking stuck semaphore on %s",
- engine->name);
- I915_WRITE_CTL(engine, tmp);
- return HANGCHECK_KICK;
- case 0:
- return HANGCHECK_WAIT;
- }
- }
-
- return HANGCHECK_HUNG;
-}
-
-/*
- * This is called when the chip hasn't reported back with completed
- * batchbuffers in a long time. We keep track per ring seqno progress and
- * if there are no progress, hangcheck score for that ring is increased.
- * Further, acthd is inspected to see if the ring is stuck. On stuck case
- * we kick the ring. If we see no progress on three subsequent calls
- * we assume chip is wedged and try to fix it by resetting the chip.
- */
-static void i915_hangcheck_elapsed(struct work_struct *work)
-{
- struct drm_i915_private *dev_priv =
- container_of(work, typeof(*dev_priv),
- gpu_error.hangcheck_work.work);
- struct intel_engine_cs *engine;
- unsigned int hung = 0, stuck = 0;
- int busy_count = 0;
-#define BUSY 1
-#define KICK 5
-#define HUNG 20
-#define ACTIVE_DECAY 15
-
- if (!i915.enable_hangcheck)
- return;
-
- if (!READ_ONCE(dev_priv->gt.awake))
- return;
-
- /* As enabling the GPU requires fairly extensive mmio access,
- * periodically arm the mmio checker to see if we are triggering
- * any invalid access.
- */
- intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
-
- for_each_engine(engine, dev_priv) {
- bool busy = intel_engine_has_waiter(engine);
- u64 acthd;
- u32 seqno;
- u32 submit;
-
- semaphore_clear_deadlocks(dev_priv);
-
- /* We don't strictly need an irq-barrier here, as we are not
- * serving an interrupt request, be paranoid in case the
- * barrier has side-effects (such as preventing a broken
- * cacheline snoop) and so be sure that we can see the seqno
- * advance. If the seqno should stick, due to a stale
- * cacheline, we would erroneously declare the GPU hung.
- */
- if (engine->irq_seqno_barrier)
- engine->irq_seqno_barrier(engine);
-
- acthd = intel_engine_get_active_head(engine);
- seqno = intel_engine_get_seqno(engine);
- submit = READ_ONCE(engine->last_submitted_seqno);
-
- if (engine->hangcheck.seqno == seqno) {
- if (i915_seqno_passed(seqno, submit)) {
- engine->hangcheck.action = HANGCHECK_IDLE;
- } else {
- /* We always increment the hangcheck score
- * if the engine is busy and still processing
- * the same request, so that no single request
- * can run indefinitely (such as a chain of
- * batches). The only time we do not increment
- * the hangcheck score on this ring, if this
- * engine is in a legitimate wait for another
- * engine. In that case the waiting engine is a
- * victim and we want to be sure we catch the
- * right culprit. Then every time we do kick
- * the ring, add a small increment to the
- * score so that we can catch a batch that is
- * being repeatedly kicked and so responsible
- * for stalling the machine.
- */
- engine->hangcheck.action =
- engine_stuck(engine, acthd);
-
- switch (engine->hangcheck.action) {
- case HANGCHECK_IDLE:
- case HANGCHECK_WAIT:
- break;
- case HANGCHECK_ACTIVE:
- engine->hangcheck.score += BUSY;
- break;
- case HANGCHECK_KICK:
- engine->hangcheck.score += KICK;
- break;
- case HANGCHECK_HUNG:
- engine->hangcheck.score += HUNG;
- break;
- }
- }
-
- if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
- hung |= intel_engine_flag(engine);
- if (engine->hangcheck.action != HANGCHECK_HUNG)
- stuck |= intel_engine_flag(engine);
- }
- } else {
- engine->hangcheck.action = HANGCHECK_ACTIVE;
-
- /* Gradually reduce the count so that we catch DoS
- * attempts across multiple batches.
- */
- if (engine->hangcheck.score > 0)
- engine->hangcheck.score -= ACTIVE_DECAY;
- if (engine->hangcheck.score < 0)
- engine->hangcheck.score = 0;
-
- /* Clear head and subunit states on seqno movement */
- acthd = 0;
-
- memset(engine->hangcheck.instdone, 0,
- sizeof(engine->hangcheck.instdone));
- }
-
- engine->hangcheck.seqno = seqno;
- engine->hangcheck.acthd = acthd;
- busy_count += busy;
- }
-
- if (hung) {
- char msg[80];
- unsigned int tmp;
- int len;
-
- /* If some rings hung but others were still busy, only
- * blame the hanging rings in the synopsis.
- */
- if (stuck != hung)
- hung &= ~stuck;
- len = scnprintf(msg, sizeof(msg),
- "%s on ", stuck == hung ? "No progress" : "Hang");
- for_each_engine_masked(engine, dev_priv, hung, tmp)
- len += scnprintf(msg + len, sizeof(msg) - len,
- "%s, ", engine->name);
- msg[len-2] = '\0';
-
- return i915_handle_error(dev_priv, hung, msg);
- }
-
- /* Reset timer in case GPU hangs without another request being added */
- if (busy_count)
- i915_queue_hangcheck(dev_priv);
-}
-
-static void ibx_irq_reset(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (HAS_PCH_NOP(dev))
+ if (HAS_PCH_NOP(dev_priv))
return;
GEN5_IRQ_RESET(SDE);
- if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
+ if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
I915_WRITE(SERR_INT, 0xffffffff);
}
@@ -3218,7 +2871,7 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- if (HAS_PCH_NOP(dev))
+ if (HAS_PCH_NOP(dev_priv))
return;
WARN_ON(I915_READ(SDEIER) != 0);
@@ -3226,12 +2879,10 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev)
POSTING_READ(SDEIER);
}
-static void gen5_gt_irq_reset(struct drm_device *dev)
+static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
GEN5_IRQ_RESET(GT);
- if (INTEL_INFO(dev)->gen >= 6)
+ if (INTEL_GEN(dev_priv) >= 6)
GEN5_IRQ_RESET(GEN6_PM);
}
@@ -3293,12 +2944,12 @@ static void ironlake_irq_reset(struct drm_device *dev)
I915_WRITE(HWSTAM, 0xffffffff);
GEN5_IRQ_RESET(DE);
- if (IS_GEN7(dev))
+ if (IS_GEN7(dev_priv))
I915_WRITE(GEN7_ERR_INT, 0xffffffff);
- gen5_gt_irq_reset(dev);
+ gen5_gt_irq_reset(dev_priv);
- ibx_irq_reset(dev);
+ ibx_irq_reset(dev_priv);
}
static void valleyview_irq_preinstall(struct drm_device *dev)
@@ -3308,7 +2959,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
I915_WRITE(VLV_MASTER_IER, 0);
POSTING_READ(VLV_MASTER_IER);
- gen5_gt_irq_reset(dev);
+ gen5_gt_irq_reset(dev_priv);
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display_irqs_enabled)
@@ -3343,8 +2994,8 @@ static void gen8_irq_reset(struct drm_device *dev)
GEN5_IRQ_RESET(GEN8_DE_MISC_);
GEN5_IRQ_RESET(GEN8_PCU_);
- if (HAS_PCH_SPLIT(dev))
- ibx_irq_reset(dev);
+ if (HAS_PCH_SPLIT(dev_priv))
+ ibx_irq_reset(dev_priv);
}
void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
@@ -3532,10 +3183,10 @@ static void ibx_irq_postinstall(struct drm_device *dev)
struct drm_i915_private *dev_priv = to_i915(dev);
u32 mask;
- if (HAS_PCH_NOP(dev))
+ if (HAS_PCH_NOP(dev_priv))
return;
- if (HAS_PCH_IBX(dev))
+ if (HAS_PCH_IBX(dev_priv))
mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
else
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
@@ -3552,14 +3203,14 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
pm_irqs = gt_irqs = 0;
dev_priv->gt_irq_mask = ~0;
- if (HAS_L3_DPF(dev)) {
+ if (HAS_L3_DPF(dev_priv)) {
/* L3 parity interrupt is always unmasked. */
- dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev);
- gt_irqs |= GT_PARITY_ERROR(dev);
+ dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv);
+ gt_irqs |= GT_PARITY_ERROR(dev_priv);
}
gt_irqs |= GT_RENDER_USER_INTERRUPT;
- if (IS_GEN5(dev)) {
+ if (IS_GEN5(dev_priv)) {
gt_irqs |= ILK_BSD_USER_INTERRUPT;
} else {
gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
@@ -3567,16 +3218,18 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs);
- if (INTEL_INFO(dev)->gen >= 6) {
+ if (INTEL_GEN(dev_priv) >= 6) {
/*
* RPS interrupts will get enabled/disabled on demand when RPS
* itself is enabled/disabled.
*/
- if (HAS_VEBOX(dev))
+ if (HAS_VEBOX(dev_priv)) {
pm_irqs |= PM_VEBOX_USER_INTERRUPT;
+ dev_priv->pm_ier |= PM_VEBOX_USER_INTERRUPT;
+ }
- dev_priv->pm_irq_mask = 0xffffffff;
- GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_irq_mask, pm_irqs);
+ dev_priv->pm_imr = 0xffffffff;
+ GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs);
}
}
@@ -3585,7 +3238,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
struct drm_i915_private *dev_priv = to_i915(dev);
u32 display_mask, extra_mask;
- if (INTEL_INFO(dev)->gen >= 7) {
+ if (INTEL_GEN(dev_priv) >= 7) {
display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB |
DE_PLANEB_FLIP_DONE_IVB |
@@ -3616,7 +3269,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
ibx_irq_postinstall(dev);
- if (IS_IRONLAKE_M(dev)) {
+ if (IS_IRONLAKE_M(dev_priv)) {
/* Enable PCU event interrupts
*
* spinlocking not required here for correctness since interrupt
@@ -3696,14 +3349,15 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
if (HAS_L3_DPF(dev_priv))
gt_interrupts[0] |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- dev_priv->pm_irq_mask = 0xffffffff;
+ dev_priv->pm_ier = 0x0;
+ dev_priv->pm_imr = ~dev_priv->pm_ier;
GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]);
GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]);
/*
* RPS interrupts will get enabled/disabled on demand when RPS itself
- * is enabled/disabled.
+ * is enabled/disabled. Same wil be the case for GuC interrupts.
*/
- GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0);
+ GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier);
GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]);
}
@@ -3756,13 +3410,13 @@ static int gen8_irq_postinstall(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
ibx_irq_pre_postinstall(dev);
gen8_gt_irq_postinstall(dev_priv);
gen8_de_irq_postinstall(dev_priv);
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
ibx_irq_postinstall(dev);
I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -3808,7 +3462,7 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
I915_WRITE(VLV_MASTER_IER, 0);
POSTING_READ(VLV_MASTER_IER);
- gen5_gt_irq_reset(dev);
+ gen5_gt_irq_reset(dev_priv);
I915_WRITE(HWSTAM, 0xffffffff);
@@ -3971,7 +3625,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
new_iir = I915_READ16(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[RCS]);
+ notify_ring(dev_priv->engine[RCS]);
for_each_pipe(dev_priv, pipe) {
int plane = pipe;
@@ -4020,7 +3674,7 @@ static void i915_irq_preinstall(struct drm_device * dev)
struct drm_i915_private *dev_priv = to_i915(dev);
int pipe;
- if (I915_HAS_HOTPLUG(dev)) {
+ if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
@@ -4054,7 +3708,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
I915_USER_INTERRUPT;
- if (I915_HAS_HOTPLUG(dev)) {
+ if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
POSTING_READ(PORT_HOTPLUG_EN);
@@ -4168,7 +3822,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
new_iir = I915_READ(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[RCS]);
+ notify_ring(dev_priv->engine[RCS]);
for_each_pipe(dev_priv, pipe) {
int plane = pipe;
@@ -4222,7 +3876,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
struct drm_i915_private *dev_priv = to_i915(dev);
int pipe;
- if (I915_HAS_HOTPLUG(dev)) {
+ if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
@@ -4400,9 +4054,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
new_iir = I915_READ(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[RCS]);
+ notify_ring(dev_priv->engine[RCS]);
if (iir & I915_BSD_USER_INTERRUPT)
- notify_ring(&dev_priv->engine[VCS]);
+ notify_ring(dev_priv->engine[VCS]);
for_each_pipe(dev_priv, pipe) {
if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -4487,6 +4141,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
+ if (HAS_GUC_SCHED(dev_priv))
+ dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT;
+
/* Let's track the enabled rps events */
if (IS_VALLEYVIEW(dev_priv))
/* WaGsvRC0ResidencyMethod:vlv */
@@ -4508,9 +4165,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
if (INTEL_INFO(dev_priv)->gen >= 8)
dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_GUC;
- INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
- i915_hangcheck_elapsed);
-
if (IS_GEN2(dev_priv)) {
/* Gen2 doesn't have a hardware frame counter */
dev->max_vblank_count = 0;
@@ -4539,16 +4193,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->irq_preinstall = cherryview_irq_preinstall;
dev->driver->irq_postinstall = cherryview_irq_postinstall;
dev->driver->irq_uninstall = cherryview_irq_uninstall;
- dev->driver->enable_vblank = valleyview_enable_vblank;
- dev->driver->disable_vblank = valleyview_disable_vblank;
+ dev->driver->enable_vblank = i965_enable_vblank;
+ dev->driver->disable_vblank = i965_disable_vblank;
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
} else if (IS_VALLEYVIEW(dev_priv)) {
dev->driver->irq_handler = valleyview_irq_handler;
dev->driver->irq_preinstall = valleyview_irq_preinstall;
dev->driver->irq_postinstall = valleyview_irq_postinstall;
dev->driver->irq_uninstall = valleyview_irq_uninstall;
- dev->driver->enable_vblank = valleyview_enable_vblank;
- dev->driver->disable_vblank = valleyview_disable_vblank;
+ dev->driver->enable_vblank = i965_enable_vblank;
+ dev->driver->disable_vblank = i965_disable_vblank;
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
} else if (INTEL_INFO(dev_priv)->gen >= 8) {
dev->driver->irq_handler = gen8_irq_handler;
@@ -4557,13 +4211,13 @@ 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 (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
- else if (HAS_PCH_SPT(dev) || HAS_PCH_KBP(dev))
+ else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv))
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)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
dev->driver->irq_handler = ironlake_irq_handler;
dev->driver->irq_preinstall = ironlake_irq_reset;
dev->driver->irq_postinstall = ironlake_irq_postinstall;
@@ -4577,21 +4231,25 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->irq_postinstall = i8xx_irq_postinstall;
dev->driver->irq_handler = i8xx_irq_handler;
dev->driver->irq_uninstall = i8xx_irq_uninstall;
+ dev->driver->enable_vblank = i8xx_enable_vblank;
+ dev->driver->disable_vblank = i8xx_disable_vblank;
} else if (IS_GEN3(dev_priv)) {
dev->driver->irq_preinstall = i915_irq_preinstall;
dev->driver->irq_postinstall = i915_irq_postinstall;
dev->driver->irq_uninstall = i915_irq_uninstall;
dev->driver->irq_handler = i915_irq_handler;
+ dev->driver->enable_vblank = i8xx_enable_vblank;
+ dev->driver->disable_vblank = i8xx_disable_vblank;
} else {
dev->driver->irq_preinstall = i965_irq_preinstall;
dev->driver->irq_postinstall = i965_irq_postinstall;
dev->driver->irq_uninstall = i965_irq_uninstall;
dev->driver->irq_handler = i965_irq_handler;
+ dev->driver->enable_vblank = i965_enable_vblank;
+ dev->driver->disable_vblank = i965_disable_vblank;
}
if (I915_HAS_HOTPLUG(dev_priv))
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
- dev->driver->enable_vblank = i915_enable_vblank;
- dev->driver->disable_vblank = i915_disable_vblank;
}
}
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 768ad89d9cd4..d46ffe7086bc 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -39,7 +39,7 @@ struct i915_params i915 __read_mostly = {
.enable_hangcheck = true,
.enable_ppgtt = -1,
.enable_psr = -1,
- .preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
+ .alpha_support = IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT),
.disable_power_well = -1,
.enable_ips = 1,
.fastboot = 0,
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
.load_detect_test = 0,
.force_reset_modeset_test = 0,
.reset = true,
+ .error_capture = true,
.invert_brightness = 0,
.disable_display = 0,
.enable_cmd_parser = 1,
@@ -115,6 +116,14 @@ 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)");
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+module_param_named(error_capture, i915.error_capture, bool, 0600);
+MODULE_PARM_DESC(error_capture,
+ "Record the GPU state following a hang. "
+ "This information in /sys/class/drm/card<N>/error is vital for "
+ "triaging and debugging hangs.");
+#endif
+
module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644);
MODULE_PARM_DESC(enable_hangcheck,
"Periodically check GPU activity for detecting hangs. "
@@ -136,9 +145,10 @@ MODULE_PARM_DESC(enable_psr, "Enable PSR "
"(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) "
"Default: -1 (use per-chip default)");
-module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0400);
-MODULE_PARM_DESC(preliminary_hw_support,
- "Enable preliminary hardware support.");
+module_param_named_unsafe(alpha_support, i915.alpha_support, int, 0400);
+MODULE_PARM_DESC(alpha_support,
+ "Enable alpha quality driver support for latest hardware. "
+ "See also CONFIG_DRM_I915_ALPHA_SUPPORT.");
module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400);
MODULE_PARM_DESC(disable_power_well,
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 3a0dd78ddb38..817ad959941e 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -40,7 +40,7 @@ struct i915_params {
int enable_ppgtt;
int enable_execlists;
int enable_psr;
- unsigned int preliminary_hw_support;
+ unsigned int alpha_support;
int disable_power_well;
int enable_ips;
int invert_brightness;
@@ -59,6 +59,7 @@ struct i915_params {
bool load_detect_test;
bool force_reset_modeset_test;
bool reset;
+ bool error_capture;
bool disable_display;
bool verbose_state_checks;
bool nuclear_pageflip;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 31e6edd08dd0..fce8e198bc76 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -288,7 +288,8 @@ static const struct intel_device_info intel_haswell_info = {
#define BDW_FEATURES \
HSW_FEATURES, \
BDW_COLORS, \
- .has_logical_ring_contexts = 1
+ .has_logical_ring_contexts = 1, \
+ .has_64bit_reloc = 1
static const struct intel_device_info intel_broadwell_info = {
BDW_FEATURES,
@@ -308,6 +309,7 @@ static const struct intel_device_info intel_cherryview_info = {
.has_hotplug = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.is_cherryview = 1,
+ .has_64bit_reloc = 1,
.has_psr = 1,
.has_runtime_pm = 1,
.has_resource_streamer = 1,
@@ -347,6 +349,7 @@ static const struct intel_device_info intel_broxton_info = {
.has_hotplug = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.num_pipes = 3,
+ .has_64bit_reloc = 1,
.has_ddi = 1,
.has_fpga_dbg = 1,
.has_fbc = 1,
@@ -360,6 +363,7 @@ static const struct intel_device_info intel_broxton_info = {
.has_hw_contexts = 1,
.has_logical_ring_contexts = 1,
.has_guc = 1,
+ .has_decoupled_mmio = 1,
.ddb_size = 512,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -436,9 +440,10 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct intel_device_info *intel_info =
(struct intel_device_info *) ent->driver_data;
- if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
- DRM_INFO("This hardware requires preliminary hardware support.\n"
- "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
+ if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) {
+ DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n"
+ "See CONFIG_DRM_I915_ALPHA_SUPPORT or i915.alpha_support module parameter\n"
+ "to enable support in this kernel version, or check for kernel updates.\n");
return -ENODEV;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 70d96162def6..c70c07a7b586 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -86,8 +86,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define DEVEN 0x54
#define DEVEN_MCHBAR_EN (1 << 28)
-#define BSM 0x5c
-#define BSM_MASK (0xFFFF << 20)
+/* BSM in include/drm/i915_drm.h */
#define HPLLCC 0xc0 /* 85x only */
#define GC_CLOCK_CONTROL_MASK (0x7 << 0)
@@ -831,96 +830,7 @@ enum skl_disp_power_wells {
#define CCK_FREQUENCY_STATUS_SHIFT 8
#define CCK_FREQUENCY_VALUES (0x1f << 0)
-/**
- * DOC: DPIO
- *
- * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI
- * ports. DPIO is the name given to such a display PHY. These PHYs
- * don't follow the standard programming model using direct MMIO
- * registers, and instead their registers must be accessed trough IOSF
- * sideband. VLV has one such PHY for driving ports B and C, and CHV
- * adds another PHY for driving port D. Each PHY responds to specific
- * IOSF-SB port.
- *
- * Each display PHY is made up of one or two channels. Each channel
- * houses a common lane part which contains the PLL and other common
- * logic. CH0 common lane also contains the IOSF-SB logic for the
- * Common Register Interface (CRI) ie. the DPIO registers. CRI clock
- * must be running when any DPIO registers are accessed.
- *
- * In addition to having their own registers, the PHYs are also
- * controlled through some dedicated signals from the display
- * controller. These include PLL reference clock enable, PLL enable,
- * and CRI clock selection, for example.
- *
- * Eeach channel also has two splines (also called data lanes), and
- * each spline is made up of one Physical Access Coding Sub-Layer
- * (PCS) block and two TX lanes. So each channel has two PCS blocks
- * and four TX lanes. The TX lanes are used as DP lanes or TMDS
- * data/clock pairs depending on the output type.
- *
- * Additionally the PHY also contains an AUX lane with AUX blocks
- * for each channel. This is used for DP AUX communication, but
- * this fact isn't really relevant for the driver since AUX is
- * controlled from the display controller side. No DPIO registers
- * need to be accessed during AUX communication,
- *
- * Generally on VLV/CHV the common lane corresponds to the pipe and
- * the spline (PCS/TX) corresponds to the port.
- *
- * For dual channel PHY (VLV/CHV):
- *
- * pipe A == CMN/PLL/REF CH0
- *
- * pipe B == CMN/PLL/REF CH1
- *
- * port B == PCS/TX CH0
- *
- * port C == PCS/TX CH1
- *
- * This is especially important when we cross the streams
- * ie. drive port B with pipe B, or port C with pipe A.
- *
- * For single channel PHY (CHV):
- *
- * pipe C == CMN/PLL/REF CH0
- *
- * port D == PCS/TX CH0
- *
- * On BXT the entire PHY channel corresponds to the port. That means
- * the PLL is also now associated with the port rather than the pipe,
- * and so the clock needs to be routed to the appropriate transcoder.
- * Port A PLL is directly connected to transcoder EDP and port B/C
- * PLLs can be routed to any transcoder A/B/C.
- *
- * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
- * digital port D (CHV) or port A (BXT). ::
- *
- *
- * Dual channel PHY (VLV/CHV/BXT)
- * ---------------------------------
- * | CH0 | CH1 |
- * | CMN/PLL/REF | CMN/PLL/REF |
- * |---------------|---------------| Display PHY
- * | PCS01 | PCS23 | PCS01 | PCS23 |
- * |-------|-------|-------|-------|
- * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
- * ---------------------------------
- * | DDI0 | DDI1 | DP/HDMI ports
- * ---------------------------------
- *
- * Single channel PHY (CHV/BXT)
- * -----------------
- * | CH0 |
- * | CMN/PLL/REF |
- * |---------------| Display PHY
- * | PCS01 | PCS23 |
- * |-------|-------|
- * |TX0|TX1|TX2|TX3|
- * -----------------
- * | DDI2 | DP/HDMI port
- * -----------------
- */
+/* DPIO registers */
#define DPIO_DEVFN 0
#define DPIO_CTL _MMIO(VLV_DISPLAY_BASE + 0x2110)
@@ -1276,7 +1186,19 @@ enum skl_disp_power_wells {
#define DPIO_UPAR_SHIFT 30
/* BXT PHY registers */
-#define _BXT_PHY(phy, a, b) _MMIO_PIPE((phy), (a), (b))
+#define _BXT_PHY0_BASE 0x6C000
+#define _BXT_PHY1_BASE 0x162000
+#define BXT_PHY_BASE(phy) _PIPE((phy), _BXT_PHY0_BASE, \
+ _BXT_PHY1_BASE)
+
+#define _BXT_PHY(phy, reg) \
+ _MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg))
+
+#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \
+ (BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE, \
+ (reg_ch1) - _BXT_PHY0_BASE))
+#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \
+ _MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1))
#define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090)
#define GT_DISPLAY_POWER_ON(phy) (1 << (phy))
@@ -1293,8 +1215,8 @@ enum skl_disp_power_wells {
#define _PHY_CTL_FAMILY_EDP 0x64C80
#define _PHY_CTL_FAMILY_DDI 0x64C90
#define COMMON_RESET_DIS (1 << 31)
-#define BXT_PHY_CTL_FAMILY(phy) _BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \
- _PHY_CTL_FAMILY_EDP)
+#define BXT_PHY_CTL_FAMILY(phy) _MMIO_PIPE((phy), _PHY_CTL_FAMILY_DDI, \
+ _PHY_CTL_FAMILY_EDP)
/* BXT PHY PLL registers */
#define _PORT_PLL_A 0x46074
@@ -1314,18 +1236,18 @@ enum skl_disp_power_wells {
#define PORT_PLL_P2_SHIFT 8
#define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT)
#define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT)
-#define BXT_PORT_PLL_EBB_0(port) _MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \
- _PORT_PLL_EBB_0_B, \
- _PORT_PLL_EBB_0_C)
+#define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PLL_EBB_0_B, \
+ _PORT_PLL_EBB_0_C)
#define _PORT_PLL_EBB_4_A 0x162038
#define _PORT_PLL_EBB_4_B 0x6C038
#define _PORT_PLL_EBB_4_C 0x6C344
#define PORT_PLL_10BIT_CLK_ENABLE (1 << 13)
#define PORT_PLL_RECALIBRATE (1 << 14)
-#define BXT_PORT_PLL_EBB_4(port) _MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \
- _PORT_PLL_EBB_4_B, \
- _PORT_PLL_EBB_4_C)
+#define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PLL_EBB_4_B, \
+ _PORT_PLL_EBB_4_C)
#define _PORT_PLL_0_A 0x162100
#define _PORT_PLL_0_B 0x6C100
@@ -1356,57 +1278,56 @@ enum skl_disp_power_wells {
#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_BASE(port) _PORT3(port, _PORT_PLL_0_A, \
- _PORT_PLL_0_B, \
- _PORT_PLL_0_C)
-#define BXT_PORT_PLL(port, idx) _MMIO(_PORT_PLL_BASE(port) + (idx) * 4)
+#define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \
+ _PORT_PLL_0_B, \
+ _PORT_PLL_0_C)
+#define BXT_PORT_PLL(phy, ch, idx) _MMIO(_PORT_PLL_BASE(phy, ch) + \
+ (idx) * 4)
/* BXT PHY common lane registers */
#define _PORT_CL1CM_DW0_A 0x162000
#define _PORT_CL1CM_DW0_BC 0x6C000
#define PHY_POWER_GOOD (1 << 16)
#define PHY_RESERVED (1 << 7)
-#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \
- _PORT_CL1CM_DW0_A)
+#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC)
#define _PORT_CL1CM_DW9_A 0x162024
#define _PORT_CL1CM_DW9_BC 0x6C024
#define IREF0RC_OFFSET_SHIFT 8
#define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT)
-#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC, \
- _PORT_CL1CM_DW9_A)
+#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC)
#define _PORT_CL1CM_DW10_A 0x162028
#define _PORT_CL1CM_DW10_BC 0x6C028
#define IREF1RC_OFFSET_SHIFT 8
#define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT)
-#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \
- _PORT_CL1CM_DW10_A)
+#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC)
#define _PORT_CL1CM_DW28_A 0x162070
#define _PORT_CL1CM_DW28_BC 0x6C070
#define OCL1_POWER_DOWN_EN (1 << 23)
#define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22)
#define SUS_CLK_CONFIG 0x3
-#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \
- _PORT_CL1CM_DW28_A)
+#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC)
#define _PORT_CL1CM_DW30_A 0x162078
#define _PORT_CL1CM_DW30_BC 0x6C078
#define OCL2_LDOFUSE_PWR_DIS (1 << 6)
-#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \
- _PORT_CL1CM_DW30_A)
+#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC)
-/* Defined for PHY0 only */
-#define BXT_PORT_CL2CM_DW6_BC _MMIO(0x6C358)
+/* The spec defines this only for BXT PHY0, but lets assume that this
+ * would exist for PHY1 too if it had a second channel.
+ */
+#define _PORT_CL2CM_DW6_A 0x162358
+#define _PORT_CL2CM_DW6_BC 0x6C358
+#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC)
#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28)
/* BXT PHY Ref registers */
#define _PORT_REF_DW3_A 0x16218C
#define _PORT_REF_DW3_BC 0x6C18C
#define GRC_DONE (1 << 22)
-#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC, \
- _PORT_REF_DW3_A)
+#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC)
#define _PORT_REF_DW6_A 0x162198
#define _PORT_REF_DW6_BC 0x6C198
@@ -1417,15 +1338,13 @@ enum skl_disp_power_wells {
#define GRC_CODE_SLOW_SHIFT 8
#define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT)
#define GRC_CODE_NOM_MASK 0xFF
-#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC, \
- _PORT_REF_DW6_A)
+#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC)
#define _PORT_REF_DW8_A 0x1621A0
#define _PORT_REF_DW8_BC 0x6C1A0
#define GRC_DIS (1 << 15)
#define GRC_RDY_OVRD (1 << 1)
-#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC, \
- _PORT_REF_DW8_A)
+#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC)
/* BXT PHY PCS registers */
#define _PORT_PCS_DW10_LN01_A 0x162428
@@ -1434,12 +1353,13 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW10_GRP_A 0x162C28
#define _PORT_PCS_DW10_GRP_B 0x6CC28
#define _PORT_PCS_DW10_GRP_C 0x6CE28
-#define BXT_PORT_PCS_DW10_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \
- _PORT_PCS_DW10_LN01_B, \
- _PORT_PCS_DW10_LN01_C)
-#define BXT_PORT_PCS_DW10_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A, \
- _PORT_PCS_DW10_GRP_B, \
- _PORT_PCS_DW10_GRP_C)
+#define BXT_PORT_PCS_DW10_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PCS_DW10_LN01_B, \
+ _PORT_PCS_DW10_LN01_C)
+#define BXT_PORT_PCS_DW10_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PCS_DW10_GRP_B, \
+ _PORT_PCS_DW10_GRP_C)
+
#define TX2_SWING_CALC_INIT (1 << 31)
#define TX1_SWING_CALC_INIT (1 << 30)
@@ -1454,15 +1374,15 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW12_GRP_C 0x6CE30
#define LANESTAGGER_STRAP_OVRD (1 << 6)
#define LANE_STAGGER_MASK 0x1F
-#define BXT_PORT_PCS_DW12_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \
- _PORT_PCS_DW12_LN01_B, \
- _PORT_PCS_DW12_LN01_C)
-#define BXT_PORT_PCS_DW12_LN23(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \
- _PORT_PCS_DW12_LN23_B, \
- _PORT_PCS_DW12_LN23_C)
-#define BXT_PORT_PCS_DW12_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \
- _PORT_PCS_DW12_GRP_B, \
- _PORT_PCS_DW12_GRP_C)
+#define BXT_PORT_PCS_DW12_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PCS_DW12_LN01_B, \
+ _PORT_PCS_DW12_LN01_C)
+#define BXT_PORT_PCS_DW12_LN23(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PCS_DW12_LN23_B, \
+ _PORT_PCS_DW12_LN23_C)
+#define BXT_PORT_PCS_DW12_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_PCS_DW12_GRP_B, \
+ _PORT_PCS_DW12_GRP_C)
/* BXT PHY TX registers */
#define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \
@@ -1474,12 +1394,12 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW2_GRP_A 0x162D08
#define _PORT_TX_DW2_GRP_B 0x6CD08
#define _PORT_TX_DW2_GRP_C 0x6CF08
-#define BXT_PORT_TX_DW2_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW2_GRP_A, \
- _PORT_TX_DW2_GRP_B, \
- _PORT_TX_DW2_GRP_C)
-#define BXT_PORT_TX_DW2_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW2_LN0_A, \
- _PORT_TX_DW2_LN0_B, \
- _PORT_TX_DW2_LN0_C)
+#define BXT_PORT_TX_DW2_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW2_LN0_B, \
+ _PORT_TX_DW2_LN0_C)
+#define BXT_PORT_TX_DW2_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW2_GRP_B, \
+ _PORT_TX_DW2_GRP_C)
#define MARGIN_000_SHIFT 16
#define MARGIN_000 (0xFF << MARGIN_000_SHIFT)
#define UNIQ_TRANS_SCALE_SHIFT 8
@@ -1491,12 +1411,12 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW3_GRP_A 0x162D0C
#define _PORT_TX_DW3_GRP_B 0x6CD0C
#define _PORT_TX_DW3_GRP_C 0x6CF0C
-#define BXT_PORT_TX_DW3_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW3_GRP_A, \
- _PORT_TX_DW3_GRP_B, \
- _PORT_TX_DW3_GRP_C)
-#define BXT_PORT_TX_DW3_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW3_LN0_A, \
- _PORT_TX_DW3_LN0_B, \
- _PORT_TX_DW3_LN0_C)
+#define BXT_PORT_TX_DW3_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW3_LN0_B, \
+ _PORT_TX_DW3_LN0_C)
+#define BXT_PORT_TX_DW3_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW3_GRP_B, \
+ _PORT_TX_DW3_GRP_C)
#define SCALE_DCOMP_METHOD (1 << 26)
#define UNIQUE_TRANGE_EN_METHOD (1 << 27)
@@ -1506,12 +1426,12 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW4_GRP_A 0x162D10
#define _PORT_TX_DW4_GRP_B 0x6CD10
#define _PORT_TX_DW4_GRP_C 0x6CF10
-#define BXT_PORT_TX_DW4_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW4_LN0_A, \
- _PORT_TX_DW4_LN0_B, \
- _PORT_TX_DW4_LN0_C)
-#define BXT_PORT_TX_DW4_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW4_GRP_A, \
- _PORT_TX_DW4_GRP_B, \
- _PORT_TX_DW4_GRP_C)
+#define BXT_PORT_TX_DW4_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW4_LN0_B, \
+ _PORT_TX_DW4_LN0_C)
+#define BXT_PORT_TX_DW4_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \
+ _PORT_TX_DW4_GRP_B, \
+ _PORT_TX_DW4_GRP_C)
#define DEEMPH_SHIFT 24
#define DE_EMPHASIS (0xFF << DEEMPH_SHIFT)
@@ -1520,10 +1440,10 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW14_LN0_C 0x6C938
#define LATENCY_OPTIM_SHIFT 30
#define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT)
-#define BXT_PORT_TX_DW14_LN(port, lane) _MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A, \
- _PORT_TX_DW14_LN0_B, \
- _PORT_TX_DW14_LN0_C) + \
- _BXT_LANE_OFFSET(lane))
+#define BXT_PORT_TX_DW14_LN(phy, ch, lane) \
+ _MMIO(_BXT_PHY_CH(phy, ch, _PORT_TX_DW14_LN0_B, \
+ _PORT_TX_DW14_LN0_C) + \
+ _BXT_LANE_OFFSET(lane))
/* UAIMI scratch pad register 1 */
#define UAIMI_SPR1 _MMIO(0x4F074)
@@ -1605,6 +1525,7 @@ enum skl_disp_power_wells {
#define RING_HEAD(base) _MMIO((base)+0x34)
#define RING_START(base) _MMIO((base)+0x38)
#define RING_CTL(base) _MMIO((base)+0x3c)
+#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
#define RING_SYNC_0(base) _MMIO((base)+0x40)
#define RING_SYNC_1(base) _MMIO((base)+0x44)
#define RING_SYNC_2(base) _MMIO((base)+0x48)
@@ -1708,7 +1629,11 @@ enum skl_disp_power_wells {
#define GEN7_SC_INSTDONE _MMIO(0x7100)
#define GEN7_SAMPLER_INSTDONE _MMIO(0xe160)
#define GEN7_ROW_INSTDONE _MMIO(0xe164)
-#define I915_NUM_INSTDONE_REG 4
+#define GEN8_MCR_SELECTOR _MMIO(0xfdc)
+#define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26)
+#define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3)
+#define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24)
+#define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3)
#define RING_IPEIR(base) _MMIO((base)+0x64)
#define RING_IPEHR(base) _MMIO((base)+0x68)
/*
@@ -2089,9 +2014,9 @@ enum skl_disp_power_wells {
#define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */
#define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */
-#define GT_PARITY_ERROR(dev) \
+#define GT_PARITY_ERROR(dev_priv) \
(GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \
- (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
+ (IS_HASWELL(dev_priv) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
/* These are all the "old" interrupts */
#define ILK_BSD_USER_INTERRUPT (1<<5)
@@ -2184,8 +2109,9 @@ enum skl_disp_power_wells {
#define FBC_FENCE_OFF _MMIO(0x3218) /* BSpec typo has 321Bh */
#define FBC_TAG(i) _MMIO(0x3300 + (i) * 4)
-#define FBC_STATUS2 _MMIO(0x43214)
-#define FBC_COMPRESSION_MASK 0x7ff
+#define FBC_STATUS2 _MMIO(0x43214)
+#define IVB_FBC_COMPRESSION_MASK 0x7ff
+#define BDW_FBC_COMPRESSION_MASK 0xfff
#define FBC_LL_SIZE (1536)
@@ -6011,6 +5937,7 @@ enum {
#define GEN8_DE_PIPE_A_IRQ (1<<16)
#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+(pipe)))
#define GEN8_GT_VECS_IRQ (1<<6)
+#define GEN8_GT_GUC_IRQ (1<<5)
#define GEN8_GT_PM_IRQ (1<<4)
#define GEN8_GT_VCS2_IRQ (1<<3)
#define GEN8_GT_VCS1_IRQ (1<<2)
@@ -6022,6 +5949,16 @@ enum {
#define GEN8_GT_IIR(which) _MMIO(0x44308 + (0x10 * (which)))
#define GEN8_GT_IER(which) _MMIO(0x4430c + (0x10 * (which)))
+#define GEN9_GUC_TO_HOST_INT_EVENT (1<<31)
+#define GEN9_GUC_EXEC_ERROR_EVENT (1<<30)
+#define GEN9_GUC_DISPLAY_EVENT (1<<29)
+#define GEN9_GUC_SEMA_SIGNAL_EVENT (1<<28)
+#define GEN9_GUC_IOMMU_MSG_EVENT (1<<27)
+#define GEN9_GUC_DB_RING_EVENT (1<<26)
+#define GEN9_GUC_DMA_DONE_EVENT (1<<25)
+#define GEN9_GUC_FATAL_ERROR_EVENT (1<<24)
+#define GEN9_GUC_NOTIFICATION_EVENT (1<<23)
+
#define GEN8_RCS_IRQ_SHIFT 0
#define GEN8_BCS_IRQ_SHIFT 16
#define GEN8_VCS1_IRQ_SHIFT 0
@@ -7327,6 +7264,10 @@ enum {
#define AUD_CONFIG_UPPER_N_MASK (0xff << 20)
#define AUD_CONFIG_LOWER_N_SHIFT 4
#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4)
+#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK)
+#define AUD_CONFIG_N(n) \
+ (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \
+ (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT))
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16)
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16)
@@ -7350,6 +7291,13 @@ enum {
#define _HSW_AUD_MISC_CTRL_B 0x65110
#define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
+#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
+#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
+#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
+#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
+#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
+#define AUD_CONFIG_M_MASK 0xfffff
+
#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4
#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4
#define HSW_AUD_DIP_ELD_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B)
@@ -7394,6 +7342,13 @@ enum {
#define SKL_FUSE_PG1_DIST_STATUS (1<<26)
#define SKL_FUSE_PG2_DIST_STATUS (1<<25)
+/* Decoupled MMIO register pair for kernel driver */
+#define GEN9_DECOUPLED_REG0_DW0 _MMIO(0xF00)
+#define GEN9_DECOUPLED_REG0_DW1 _MMIO(0xF04)
+#define GEN9_DECOUPLED_DW1_GO (1<<31)
+#define GEN9_DECOUPLED_PD_SHIFT 28
+#define GEN9_DECOUPLED_OP_SHIFT 24
+
/* Per-pipe DDI Function Control */
#define _TRANS_DDI_FUNC_CTL_A 0x60400
#define _TRANS_DDI_FUNC_CTL_B 0x61400
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index a0af170062b1..b0e1e7ca75da 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -29,35 +29,31 @@
#include "intel_drv.h"
#include "i915_reg.h"
-static void i915_save_display(struct drm_device *dev)
+static void i915_save_display(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* Display arbitration control */
- if (INTEL_INFO(dev)->gen <= 4)
+ if (INTEL_GEN(dev_priv) <= 4)
dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
/* save FBC interval */
- if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+ if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv))
dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
}
-static void i915_restore_display(struct drm_device *dev)
+static void i915_restore_display(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* Display arbitration */
- if (INTEL_INFO(dev)->gen <= 4)
+ if (INTEL_GEN(dev_priv) <= 4)
I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
/* only restore FBC info on the platform that supports FBC*/
intel_fbc_global_disable(dev_priv);
/* restore FBC interval */
- if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+ if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv))
I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
- i915_redisable_vga(dev);
+ i915_redisable_vga(dev_priv);
}
int i915_save_state(struct drm_device *dev)
@@ -68,14 +64,14 @@ int i915_save_state(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
- i915_save_display(dev);
+ i915_save_display(dev_priv);
- if (IS_GEN4(dev))
+ if (IS_GEN4(dev_priv))
pci_read_config_word(pdev, GCDGMBUS,
&dev_priv->regfile.saveGCDGMBUS);
/* Cache mode state */
- if (INTEL_INFO(dev)->gen < 7)
+ if (INTEL_GEN(dev_priv) < 7)
dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
/* Memory Arbitration state */
@@ -114,15 +110,15 @@ int i915_restore_state(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
- i915_gem_restore_fences(dev);
+ i915_gem_restore_fences(dev_priv);
- if (IS_GEN4(dev))
+ if (IS_GEN4(dev_priv))
pci_write_config_word(pdev, GCDGMBUS,
dev_priv->regfile.saveGCDGMBUS);
- i915_restore_display(dev);
+ i915_restore_display(dev_priv);
/* Cache mode state */
- if (INTEL_INFO(dev)->gen < 7)
+ if (INTEL_GEN(dev_priv) < 7)
I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 |
0xffff0000);
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 1e5cbc585ca2..147420ccf49c 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -8,11 +8,13 @@
*/
#include <linux/slab.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/reservation.h>
#include "i915_sw_fence.h"
+#define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
+
static DEFINE_SPINLOCK(i915_sw_fence_lock);
static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
@@ -114,11 +116,14 @@ static void i915_sw_fence_await(struct i915_sw_fence *fence)
WARN_ON(atomic_inc_return(&fence->pending) <= 1);
}
-void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn)
+void __i915_sw_fence_init(struct i915_sw_fence *fence,
+ i915_sw_fence_notify_t fn,
+ const char *name,
+ struct lock_class_key *key)
{
BUG_ON((unsigned long)fn & ~I915_SW_FENCE_MASK);
- init_waitqueue_head(&fence->wait);
+ __init_waitqueue_head(&fence->wait, name, key);
kref_init(&fence->kref);
atomic_set(&fence->pending, 1);
fence->flags = (unsigned long)fn;
@@ -135,6 +140,8 @@ static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *
list_del(&wq->task_list);
__i915_sw_fence_complete(wq->private, key);
i915_sw_fence_put(wq->private);
+ if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
+ kfree(wq);
return 0;
}
@@ -192,9 +199,9 @@ static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
return err;
}
-int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
- struct i915_sw_fence *signaler,
- wait_queue_t *wq)
+static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+ struct i915_sw_fence *signaler,
+ wait_queue_t *wq, gfp_t gfp)
{
unsigned long flags;
int pending;
@@ -206,8 +213,22 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
return -EINVAL;
+ pending = 0;
+ if (!wq) {
+ wq = kmalloc(sizeof(*wq), gfp);
+ if (!wq) {
+ if (!gfpflags_allow_blocking(gfp))
+ return -ENOMEM;
+
+ i915_sw_fence_wait(signaler);
+ return 0;
+ }
+
+ pending |= I915_SW_FENCE_FLAG_ALLOC;
+ }
+
INIT_LIST_HEAD(&wq->task_list);
- wq->flags = 0;
+ wq->flags = pending;
wq->func = i915_sw_fence_wake;
wq->private = i915_sw_fence_get(fence);
@@ -226,49 +247,64 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
return pending;
}
-struct dma_fence_cb {
- struct fence_cb base;
+int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+ struct i915_sw_fence *signaler,
+ wait_queue_t *wq)
+{
+ return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
+}
+
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+ struct i915_sw_fence *signaler,
+ gfp_t gfp)
+{
+ return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
+}
+
+struct i915_sw_dma_fence_cb {
+ struct dma_fence_cb base;
struct i915_sw_fence *fence;
- struct fence *dma;
+ struct dma_fence *dma;
struct timer_list timer;
};
static void timer_i915_sw_fence_wake(unsigned long data)
{
- struct dma_fence_cb *cb = (struct dma_fence_cb *)data;
+ struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data;
printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n",
cb->dma->ops->get_driver_name(cb->dma),
cb->dma->ops->get_timeline_name(cb->dma),
cb->dma->seqno);
- fence_put(cb->dma);
+ dma_fence_put(cb->dma);
cb->dma = NULL;
i915_sw_fence_commit(cb->fence);
cb->timer.function = NULL;
}
-static void dma_i915_sw_fence_wake(struct fence *dma, struct fence_cb *data)
+static void dma_i915_sw_fence_wake(struct dma_fence *dma,
+ struct dma_fence_cb *data)
{
- struct dma_fence_cb *cb = container_of(data, typeof(*cb), base);
+ struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
del_timer_sync(&cb->timer);
if (cb->timer.function)
i915_sw_fence_commit(cb->fence);
- fence_put(cb->dma);
+ dma_fence_put(cb->dma);
kfree(cb);
}
int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
- struct fence *dma,
+ struct dma_fence *dma,
unsigned long timeout,
gfp_t gfp)
{
- struct dma_fence_cb *cb;
+ struct i915_sw_dma_fence_cb *cb;
int ret;
- if (fence_is_signaled(dma))
+ if (dma_fence_is_signaled(dma))
return 0;
cb = kmalloc(sizeof(*cb), gfp);
@@ -276,7 +312,7 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
if (!gfpflags_allow_blocking(gfp))
return -ENOMEM;
- return fence_wait(dma, false);
+ return dma_fence_wait(dma, false);
}
cb->fence = i915_sw_fence_get(fence);
@@ -287,11 +323,11 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
timer_i915_sw_fence_wake, (unsigned long)cb,
TIMER_IRQSAFE);
if (timeout) {
- cb->dma = fence_get(dma);
+ cb->dma = dma_fence_get(dma);
mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout));
}
- ret = fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake);
+ ret = dma_fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake);
if (ret == 0) {
ret = 1;
} else {
@@ -305,16 +341,16 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct reservation_object *resv,
- const struct fence_ops *exclude,
+ const struct dma_fence_ops *exclude,
bool write,
unsigned long timeout,
gfp_t gfp)
{
- struct fence *excl;
+ struct dma_fence *excl;
int ret = 0, pending;
if (write) {
- struct fence **shared;
+ struct dma_fence **shared;
unsigned int count, i;
ret = reservation_object_get_fences_rcu(resv,
@@ -339,7 +375,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
}
for (i = 0; i < count; i++)
- fence_put(shared[i]);
+ dma_fence_put(shared[i]);
kfree(shared);
} else {
excl = reservation_object_get_excl_rcu(resv);
@@ -356,7 +392,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
ret |= pending;
}
- fence_put(excl);
+ dma_fence_put(excl);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index 373141602ca4..0f3185ef7f4e 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -16,8 +16,8 @@
#include <linux/wait.h>
struct completion;
-struct fence;
-struct fence_ops;
+struct dma_fence;
+struct dma_fence_ops;
struct reservation_object;
struct i915_sw_fence {
@@ -40,26 +40,54 @@ typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *,
enum i915_sw_fence_notify state);
#define __i915_sw_fence_call __aligned(4)
-void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn);
+void __i915_sw_fence_init(struct i915_sw_fence *fence,
+ i915_sw_fence_notify_t fn,
+ const char *name,
+ struct lock_class_key *key);
+#ifdef CONFIG_LOCKDEP
+#define i915_sw_fence_init(fence, fn) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __i915_sw_fence_init((fence), (fn), #fence, &__key); \
+} while (0)
+#else
+#define i915_sw_fence_init(fence, fn) \
+ __i915_sw_fence_init((fence), (fn), NULL, NULL)
+#endif
+
void i915_sw_fence_commit(struct i915_sw_fence *fence);
int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
struct i915_sw_fence *after,
wait_queue_t *wq);
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+ struct i915_sw_fence *after,
+ gfp_t gfp);
int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
- struct fence *dma,
+ struct dma_fence *dma,
unsigned long timeout,
gfp_t gfp);
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct reservation_object *resv,
- const struct fence_ops *exclude,
+ const struct dma_fence_ops *exclude,
bool write,
unsigned long timeout,
gfp_t gfp);
+static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence)
+{
+ return atomic_read(&fence->pending) <= 0;
+}
+
static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
{
return atomic_read(&fence->pending) < 0;
}
+static inline void i915_sw_fence_wait(struct i915_sw_fence *fence)
+{
+ wait_event(fence->wait, i915_sw_fence_done(fence));
+}
+
#endif /* _I915_SW_FENCE_H_ */
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 1012eeea1324..47590ab08d7e 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -514,6 +514,8 @@ static const struct attribute *vlv_attrs[] = {
NULL,
};
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
@@ -571,6 +573,21 @@ static struct bin_attribute error_state_attr = {
.write = error_state_write,
};
+static void i915_setup_error_capture(struct device *kdev)
+{
+ if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr))
+ DRM_ERROR("error_state sysfs setup failed\n");
+}
+
+static void i915_teardown_error_capture(struct device *kdev)
+{
+ sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
+}
+#else
+static void i915_setup_error_capture(struct device *kdev) {}
+static void i915_teardown_error_capture(struct device *kdev) {}
+#endif
+
void i915_setup_sysfs(struct drm_i915_private *dev_priv)
{
struct device *kdev = dev_priv->drm.primary->kdev;
@@ -617,17 +634,15 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
if (ret)
DRM_ERROR("RPS sysfs setup failed\n");
- ret = sysfs_create_bin_file(&kdev->kobj,
- &error_state_attr);
- if (ret)
- DRM_ERROR("error_state sysfs setup failed\n");
+ i915_setup_error_capture(kdev);
}
void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
{
struct device *kdev = dev_priv->drm.primary->kdev;
- sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
+ i915_teardown_error_capture(kdev);
+
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
sysfs_remove_files(&kdev->kobj, vlv_attrs);
else
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 178798002a73..c5d210ebaa9a 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -466,7 +466,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
__entry->dev = from->i915->drm.primary->index;
__entry->sync_from = from->engine->id;
__entry->sync_to = to->engine->id;
- __entry->seqno = from->fence.seqno;
+ __entry->seqno = from->global_seqno;
),
TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u",
@@ -489,9 +489,9 @@ TRACE_EVENT(i915_gem_ring_dispatch,
TP_fast_assign(
__entry->dev = req->i915->drm.primary->index;
__entry->ring = req->engine->id;
- __entry->seqno = req->fence.seqno;
+ __entry->seqno = req->global_seqno;
__entry->flags = flags;
- fence_enable_sw_signaling(&req->fence);
+ dma_fence_enable_sw_signaling(&req->fence);
),
TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x",
@@ -534,7 +534,7 @@ DECLARE_EVENT_CLASS(i915_gem_request,
TP_fast_assign(
__entry->dev = req->i915->drm.primary->index;
__entry->ring = req->engine->id;
- __entry->seqno = req->fence.seqno;
+ __entry->seqno = req->global_seqno;
),
TP_printk("dev=%u, ring=%u, seqno=%u",
@@ -596,7 +596,7 @@ TRACE_EVENT(i915_gem_request_wait_begin,
TP_fast_assign(
__entry->dev = req->i915->drm.primary->index;
__entry->ring = req->engine->id;
- __entry->seqno = req->fence.seqno;
+ __entry->seqno = req->global_seqno;
__entry->blocking =
mutex_is_locked(&req->i915->drm.struct_mutex);
),
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
new file mode 100644
index 000000000000..a792dcb902b5
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright © 2016 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 "i915_vma.h"
+
+#include "i915_drv.h"
+#include "intel_ringbuffer.h"
+#include "intel_frontbuffer.h"
+
+#include <drm/drm_gem.h>
+
+static void
+i915_vma_retire(struct i915_gem_active *active,
+ struct drm_i915_gem_request *rq)
+{
+ const unsigned int idx = rq->engine->id;
+ struct i915_vma *vma =
+ container_of(active, struct i915_vma, last_read[idx]);
+ struct drm_i915_gem_object *obj = vma->obj;
+
+ GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
+
+ i915_vma_clear_active(vma, idx);
+ if (i915_vma_is_active(vma))
+ return;
+
+ list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+ if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
+ WARN_ON(i915_vma_unbind(vma));
+
+ GEM_BUG_ON(!i915_gem_object_is_active(obj));
+ if (--obj->active_count)
+ return;
+
+ /* Bump our place on the bound list to keep it roughly in LRU order
+ * so that we don't steal from recently used but inactive objects
+ * (unless we are forced to ofc!)
+ */
+ if (obj->bind_count)
+ list_move_tail(&obj->global_link, &rq->i915->mm.bound_list);
+
+ obj->mm.dirty = true; /* be paranoid */
+
+ if (i915_gem_object_has_active_reference(obj)) {
+ i915_gem_object_clear_active_reference(obj);
+ i915_gem_object_put(obj);
+ }
+}
+
+static struct i915_vma *
+__i915_vma_create(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
+{
+ struct i915_vma *vma;
+ struct rb_node *rb, **p;
+ int i;
+
+ GEM_BUG_ON(vm->closed);
+
+ vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
+ if (vma == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&vma->exec_list);
+ for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
+ init_request_active(&vma->last_read[i], i915_vma_retire);
+ init_request_active(&vma->last_fence, NULL);
+ list_add(&vma->vm_link, &vm->unbound_list);
+ vma->vm = vm;
+ vma->obj = obj;
+ vma->size = obj->base.size;
+
+ if (view) {
+ vma->ggtt_view = *view;
+ if (view->type == I915_GGTT_VIEW_PARTIAL) {
+ vma->size = view->params.partial.size;
+ vma->size <<= PAGE_SHIFT;
+ } else if (view->type == I915_GGTT_VIEW_ROTATED) {
+ vma->size =
+ intel_rotation_info_size(&view->params.rotated);
+ vma->size <<= PAGE_SHIFT;
+ }
+ }
+
+ if (i915_is_ggtt(vm)) {
+ vma->flags |= I915_VMA_GGTT;
+ list_add(&vma->obj_link, &obj->vma_list);
+ } else {
+ i915_ppgtt_get(i915_vm_to_ppgtt(vm));
+ list_add_tail(&vma->obj_link, &obj->vma_list);
+ }
+
+ rb = NULL;
+ p = &obj->vma_tree.rb_node;
+ while (*p) {
+ struct i915_vma *pos;
+
+ rb = *p;
+ pos = rb_entry(rb, struct i915_vma, obj_node);
+ if (i915_vma_compare(pos, vm, view) < 0)
+ p = &rb->rb_right;
+ else
+ p = &rb->rb_left;
+ }
+ rb_link_node(&vma->obj_node, rb, p);
+ rb_insert_color(&vma->obj_node, &obj->vma_tree);
+
+ return vma;
+}
+
+struct i915_vma *
+i915_vma_create(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
+{
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+ GEM_BUG_ON(view && !i915_is_ggtt(vm));
+ GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view));
+
+ return __i915_vma_create(obj, vm, view);
+}
+
+/**
+ * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
+ * @vma: VMA to map
+ * @cache_level: mapping cache level
+ * @flags: flags like global or local mapping
+ *
+ * DMA addresses are taken from the scatter-gather table of this object (or of
+ * this VMA in case of non-default GGTT views) and PTE entries set up.
+ * Note that DMA addresses are also the only part of the SG table we care about.
+ */
+int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
+ u32 flags)
+{
+ u32 bind_flags;
+ u32 vma_flags;
+ int ret;
+
+ if (WARN_ON(flags == 0))
+ return -EINVAL;
+
+ bind_flags = 0;
+ if (flags & PIN_GLOBAL)
+ bind_flags |= I915_VMA_GLOBAL_BIND;
+ if (flags & PIN_USER)
+ bind_flags |= I915_VMA_LOCAL_BIND;
+
+ vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
+ if (flags & PIN_UPDATE)
+ bind_flags |= vma_flags;
+ else
+ bind_flags &= ~vma_flags;
+ if (bind_flags == 0)
+ return 0;
+
+ if (vma_flags == 0 && vma->vm->allocate_va_range) {
+ trace_i915_va_alloc(vma);
+ ret = vma->vm->allocate_va_range(vma->vm,
+ vma->node.start,
+ vma->node.size);
+ if (ret)
+ return ret;
+ }
+
+ ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
+ if (ret)
+ return ret;
+
+ vma->flags |= bind_flags;
+ return 0;
+}
+
+void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
+{
+ void __iomem *ptr;
+
+ /* Access through the GTT requires the device to be awake. */
+ assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+ if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
+ return IO_ERR_PTR(-ENODEV);
+
+ GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+ GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
+
+ ptr = vma->iomap;
+ if (ptr == NULL) {
+ ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable,
+ vma->node.start,
+ vma->node.size);
+ if (ptr == NULL)
+ return IO_ERR_PTR(-ENOMEM);
+
+ vma->iomap = ptr;
+ }
+
+ __i915_vma_pin(vma);
+ return ptr;
+}
+
+void i915_vma_unpin_and_release(struct i915_vma **p_vma)
+{
+ struct i915_vma *vma;
+ struct drm_i915_gem_object *obj;
+
+ vma = fetch_and_zero(p_vma);
+ if (!vma)
+ return;
+
+ obj = vma->obj;
+
+ i915_vma_unpin(vma);
+ i915_vma_close(vma);
+
+ __i915_gem_object_release_unless_active(obj);
+}
+
+bool
+i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+ if (!drm_mm_node_allocated(&vma->node))
+ return false;
+
+ if (vma->node.size < size)
+ return true;
+
+ if (alignment && vma->node.start & (alignment - 1))
+ return true;
+
+ if (flags & PIN_MAPPABLE && !i915_vma_is_map_and_fenceable(vma))
+ return true;
+
+ if (flags & PIN_OFFSET_BIAS &&
+ vma->node.start < (flags & PIN_OFFSET_MASK))
+ return true;
+
+ if (flags & PIN_OFFSET_FIXED &&
+ vma->node.start != (flags & PIN_OFFSET_MASK))
+ return true;
+
+ return false;
+}
+
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
+{
+ struct drm_i915_gem_object *obj = vma->obj;
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+ bool mappable, fenceable;
+ u32 fence_size, fence_alignment;
+
+ fence_size = i915_gem_get_ggtt_size(dev_priv,
+ vma->size,
+ i915_gem_object_get_tiling(obj));
+ fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
+ vma->size,
+ i915_gem_object_get_tiling(obj),
+ true);
+
+ fenceable = (vma->node.size == fence_size &&
+ (vma->node.start & (fence_alignment - 1)) == 0);
+
+ mappable = (vma->node.start + fence_size <=
+ dev_priv->ggtt.mappable_end);
+
+ /*
+ * Explicitly disable for rotated VMA since the display does not
+ * need the fence and the VMA is not accessible to other users.
+ */
+ if (mappable && fenceable &&
+ vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)
+ vma->flags |= I915_VMA_CAN_FENCE;
+ else
+ vma->flags &= ~I915_VMA_CAN_FENCE;
+}
+
+bool i915_gem_valid_gtt_space(struct i915_vma *vma,
+ unsigned long cache_level)
+{
+ struct drm_mm_node *gtt_space = &vma->node;
+ struct drm_mm_node *other;
+
+ /*
+ * On some machines we have to be careful when putting differing types
+ * of snoopable memory together to avoid the prefetcher crossing memory
+ * domains and dying. During vm initialisation, we decide whether or not
+ * these constraints apply and set the drm_mm.color_adjust
+ * appropriately.
+ */
+ if (vma->vm->mm.color_adjust == NULL)
+ return true;
+
+ if (!drm_mm_node_allocated(gtt_space))
+ return true;
+
+ if (list_empty(&gtt_space->node_list))
+ return true;
+
+ other = list_entry(gtt_space->node_list.prev, struct drm_mm_node, node_list);
+ if (other->allocated && !other->hole_follows && other->color != cache_level)
+ return false;
+
+ other = list_entry(gtt_space->node_list.next, struct drm_mm_node, node_list);
+ if (other->allocated && !gtt_space->hole_follows && other->color != cache_level)
+ return false;
+
+ return true;
+}
+
+/**
+ * i915_vma_insert - finds a slot for the vma in its address space
+ * @vma: the vma
+ * @size: requested size in bytes (can be larger than the VMA)
+ * @alignment: required alignment
+ * @flags: mask of PIN_* flags to use
+ *
+ * First we try to allocate some free space that meets the requirements for
+ * the VMA. Failiing that, if the flags permit, it will evict an old VMA,
+ * preferrably the oldest idle entry to make room for the new VMA.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+static int
+i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+ struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
+ struct drm_i915_gem_object *obj = vma->obj;
+ u64 start, end;
+ int ret;
+
+ GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
+ GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
+
+ size = max(size, vma->size);
+ if (flags & PIN_MAPPABLE)
+ size = i915_gem_get_ggtt_size(dev_priv, size,
+ i915_gem_object_get_tiling(obj));
+
+ alignment = max(max(alignment, vma->display_alignment),
+ i915_gem_get_ggtt_alignment(dev_priv, size,
+ i915_gem_object_get_tiling(obj),
+ flags & PIN_MAPPABLE));
+
+ start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
+
+ end = vma->vm->total;
+ if (flags & PIN_MAPPABLE)
+ end = min_t(u64, end, dev_priv->ggtt.mappable_end);
+ if (flags & PIN_ZONE_4G)
+ end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
+
+ /* If binding the object/GGTT view requires more space than the entire
+ * aperture has, reject it early before evicting everything in a vain
+ * attempt to find space.
+ */
+ if (size > end) {
+ DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu [object=%zd] > %s aperture=%llu\n",
+ size, obj->base.size,
+ flags & PIN_MAPPABLE ? "mappable" : "total",
+ end);
+ return -E2BIG;
+ }
+
+ ret = i915_gem_object_pin_pages(obj);
+ if (ret)
+ return ret;
+
+ if (flags & PIN_OFFSET_FIXED) {
+ u64 offset = flags & PIN_OFFSET_MASK;
+ if (offset & (alignment - 1) || offset > end - size) {
+ ret = -EINVAL;
+ goto err_unpin;
+ }
+
+ vma->node.start = offset;
+ vma->node.size = size;
+ vma->node.color = obj->cache_level;
+ ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+ if (ret) {
+ ret = i915_gem_evict_for_vma(vma);
+ if (ret == 0)
+ ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+ if (ret)
+ goto err_unpin;
+ }
+ } else {
+ u32 search_flag, alloc_flag;
+
+ 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;
+ }
+
+ /* We only allocate in PAGE_SIZE/GTT_PAGE_SIZE (4096) chunks,
+ * so we know that we always have a minimum alignment of 4096.
+ * The drm_mm range manager is optimised to return results
+ * with zero alignment, so where possible use the optimal
+ * path.
+ */
+ if (alignment <= 4096)
+ alignment = 0;
+
+search_free:
+ ret = drm_mm_insert_node_in_range_generic(&vma->vm->mm,
+ &vma->node,
+ size, alignment,
+ obj->cache_level,
+ start, end,
+ search_flag,
+ alloc_flag);
+ if (ret) {
+ ret = i915_gem_evict_something(vma->vm, size, alignment,
+ obj->cache_level,
+ start, end,
+ flags);
+ if (ret == 0)
+ goto search_free;
+
+ goto err_unpin;
+ }
+
+ GEM_BUG_ON(vma->node.start < start);
+ GEM_BUG_ON(vma->node.start + vma->node.size > end);
+ }
+ GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
+
+ list_move_tail(&obj->global_link, &dev_priv->mm.bound_list);
+ list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+ obj->bind_count++;
+ GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
+
+ return 0;
+
+err_unpin:
+ i915_gem_object_unpin_pages(obj);
+ return ret;
+}
+
+int __i915_vma_do_pin(struct i915_vma *vma,
+ u64 size, u64 alignment, u64 flags)
+{
+ unsigned int bound = vma->flags;
+ int ret;
+
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+ GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
+ GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma));
+
+ if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ if ((bound & I915_VMA_BIND_MASK) == 0) {
+ ret = i915_vma_insert(vma, size, alignment, flags);
+ if (ret)
+ goto err;
+ }
+
+ ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
+ if (ret)
+ goto err;
+
+ if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)
+ __i915_vma_set_map_and_fenceable(vma);
+
+ GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
+ return 0;
+
+err:
+ __i915_vma_unpin(vma);
+ return ret;
+}
+
+void i915_vma_destroy(struct i915_vma *vma)
+{
+ GEM_BUG_ON(vma->node.allocated);
+ GEM_BUG_ON(i915_vma_is_active(vma));
+ GEM_BUG_ON(!i915_vma_is_closed(vma));
+ GEM_BUG_ON(vma->fence);
+
+ list_del(&vma->vm_link);
+ if (!i915_vma_is_ggtt(vma))
+ i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
+
+ kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
+}
+
+void i915_vma_close(struct i915_vma *vma)
+{
+ GEM_BUG_ON(i915_vma_is_closed(vma));
+ vma->flags |= I915_VMA_CLOSED;
+
+ list_del(&vma->obj_link);
+ rb_erase(&vma->obj_node, &vma->obj->vma_tree);
+
+ if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
+ WARN_ON(i915_vma_unbind(vma));
+}
+
+static void __i915_vma_iounmap(struct i915_vma *vma)
+{
+ GEM_BUG_ON(i915_vma_is_pinned(vma));
+
+ if (vma->iomap == NULL)
+ return;
+
+ io_mapping_unmap(vma->iomap);
+ vma->iomap = NULL;
+}
+
+int i915_vma_unbind(struct i915_vma *vma)
+{
+ struct drm_i915_gem_object *obj = vma->obj;
+ unsigned long active;
+ int ret;
+
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+ /* First wait upon any activity as retiring the request may
+ * have side-effects such as unpinning or even unbinding this vma.
+ */
+ active = i915_vma_get_active(vma);
+ if (active) {
+ int idx;
+
+ /* When a closed VMA is retired, it is unbound - eek.
+ * In order to prevent it from being recursively closed,
+ * take a pin on the vma so that the second unbind is
+ * aborted.
+ *
+ * Even more scary is that the retire callback may free
+ * the object (last active vma). To prevent the explosion
+ * we defer the actual object free to a worker that can
+ * only proceed once it acquires the struct_mutex (which
+ * we currently hold, therefore it cannot free this object
+ * before we are finished).
+ */
+ __i915_vma_pin(vma);
+
+ for_each_active(active, idx) {
+ ret = i915_gem_active_retire(&vma->last_read[idx],
+ &vma->vm->dev->struct_mutex);
+ if (ret)
+ break;
+ }
+
+ __i915_vma_unpin(vma);
+ if (ret)
+ return ret;
+
+ GEM_BUG_ON(i915_vma_is_active(vma));
+ }
+
+ if (i915_vma_is_pinned(vma))
+ return -EBUSY;
+
+ if (!drm_mm_node_allocated(&vma->node))
+ goto destroy;
+
+ GEM_BUG_ON(obj->bind_count == 0);
+ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+
+ if (i915_vma_is_map_and_fenceable(vma)) {
+ /* release the fence reg _after_ flushing */
+ ret = i915_vma_put_fence(vma);
+ if (ret)
+ return ret;
+
+ /* Force a pagefault for domain tracking on next user access */
+ i915_gem_release_mmap(obj);
+
+ __i915_vma_iounmap(vma);
+ vma->flags &= ~I915_VMA_CAN_FENCE;
+ }
+
+ if (likely(!vma->vm->closed)) {
+ trace_i915_vma_unbind(vma);
+ vma->vm->unbind_vma(vma);
+ }
+ vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
+
+ drm_mm_remove_node(&vma->node);
+ list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
+
+ if (vma->pages != obj->mm.pages) {
+ GEM_BUG_ON(!vma->pages);
+ sg_free_table(vma->pages);
+ kfree(vma->pages);
+ }
+ vma->pages = NULL;
+
+ /* Since the unbound list is global, only move to that list if
+ * no more VMAs exist. */
+ if (--obj->bind_count == 0)
+ list_move_tail(&obj->global_link,
+ &to_i915(obj->base.dev)->mm.unbound_list);
+
+ /* And finally now the object is completely decoupled from this vma,
+ * we can drop its hold on the backing storage and allow it to be
+ * reaped by the shrinker.
+ */
+ i915_gem_object_unpin_pages(obj);
+
+destroy:
+ if (unlikely(i915_vma_is_closed(vma)))
+ i915_vma_destroy(vma);
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
new file mode 100644
index 000000000000..85446f0b0b3f
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_vma.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright © 2016 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 __I915_VMA_H__
+#define __I915_VMA_H__
+
+#include <linux/io-mapping.h>
+
+#include <drm/drm_mm.h>
+
+#include "i915_gem_gtt.h"
+#include "i915_gem_fence_reg.h"
+#include "i915_gem_object.h"
+#include "i915_gem_request.h"
+
+
+enum i915_cache_level;
+
+/**
+ * A VMA represents a GEM BO that is bound into an address space. Therefore, a
+ * VMA's presence cannot be guaranteed before binding, or after unbinding the
+ * object into/from the address space.
+ *
+ * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
+ * will always be <= an objects lifetime. So object refcounting should cover us.
+ */
+struct i915_vma {
+ struct drm_mm_node node;
+ struct drm_i915_gem_object *obj;
+ struct i915_address_space *vm;
+ struct drm_i915_fence_reg *fence;
+ struct sg_table *pages;
+ void __iomem *iomap;
+ u64 size;
+ u64 display_alignment;
+
+ unsigned int flags;
+ /**
+ * How many users have pinned this object in GTT space. The following
+ * users can each hold at most one reference: pwrite/pread, execbuffer
+ * (objects are not allowed multiple times for the same batchbuffer),
+ * and the framebuffer code. When switching/pageflipping, the
+ * framebuffer code has at most two buffers pinned per crtc.
+ *
+ * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
+ * bits with absolutely no headroom. So use 4 bits.
+ */
+#define I915_VMA_PIN_MASK 0xf
+#define I915_VMA_PIN_OVERFLOW BIT(5)
+
+ /** Flags and address space this VMA is bound to */
+#define I915_VMA_GLOBAL_BIND BIT(6)
+#define I915_VMA_LOCAL_BIND BIT(7)
+#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)
+
+#define I915_VMA_GGTT BIT(8)
+#define I915_VMA_CAN_FENCE BIT(9)
+#define I915_VMA_CLOSED BIT(10)
+
+ unsigned int active;
+ struct i915_gem_active last_read[I915_NUM_ENGINES];
+ struct i915_gem_active last_fence;
+
+ /**
+ * Support different GGTT views into the same object.
+ * This means there can be multiple VMA mappings per object and per VM.
+ * i915_ggtt_view_type is used to distinguish between those entries.
+ * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
+ * assumed in GEM functions which take no ggtt view parameter.
+ */
+ struct i915_ggtt_view ggtt_view;
+
+ /** This object's place on the active/inactive lists */
+ struct list_head vm_link;
+
+ struct list_head obj_link; /* Link in the object's VMA list */
+ struct rb_node obj_node;
+
+ /** This vma's place in the batchbuffer or on the eviction list */
+ struct list_head exec_list;
+
+ /**
+ * Used for performing relocations during execbuffer insertion.
+ */
+ struct hlist_node exec_node;
+ unsigned long exec_handle;
+ struct drm_i915_gem_exec_object2 *exec_entry;
+};
+
+struct i915_vma *
+i915_vma_create(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view);
+
+void i915_vma_unpin_and_release(struct i915_vma **p_vma);
+
+static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
+{
+ return vma->flags & I915_VMA_GGTT;
+}
+
+static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
+{
+ return vma->flags & I915_VMA_CAN_FENCE;
+}
+
+static inline bool i915_vma_is_closed(const struct i915_vma *vma)
+{
+ return vma->flags & I915_VMA_CLOSED;
+}
+
+static inline unsigned int i915_vma_get_active(const struct i915_vma *vma)
+{
+ return vma->active;
+}
+
+static inline bool i915_vma_is_active(const struct i915_vma *vma)
+{
+ return i915_vma_get_active(vma);
+}
+
+static inline void i915_vma_set_active(struct i915_vma *vma,
+ unsigned int engine)
+{
+ vma->active |= BIT(engine);
+}
+
+static inline void i915_vma_clear_active(struct i915_vma *vma,
+ unsigned int engine)
+{
+ vma->active &= ~BIT(engine);
+}
+
+static inline bool i915_vma_has_active_engine(const struct i915_vma *vma,
+ unsigned int engine)
+{
+ return vma->active & BIT(engine);
+}
+
+static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
+{
+ GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+ GEM_BUG_ON(!vma->node.allocated);
+ GEM_BUG_ON(upper_32_bits(vma->node.start));
+ GEM_BUG_ON(upper_32_bits(vma->node.start + vma->node.size - 1));
+ return lower_32_bits(vma->node.start);
+}
+
+static inline struct i915_vma *i915_vma_get(struct i915_vma *vma)
+{
+ i915_gem_object_get(vma->obj);
+ return vma;
+}
+
+static inline void i915_vma_put(struct i915_vma *vma)
+{
+ i915_gem_object_put(vma->obj);
+}
+
+static inline long
+i915_vma_compare(struct i915_vma *vma,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
+{
+ GEM_BUG_ON(view && !i915_is_ggtt(vm));
+
+ if (vma->vm != vm)
+ return vma->vm - vm;
+
+ if (!view)
+ return vma->ggtt_view.type;
+
+ if (vma->ggtt_view.type != view->type)
+ return vma->ggtt_view.type - view->type;
+
+ return memcmp(&vma->ggtt_view.params,
+ &view->params,
+ sizeof(view->params));
+}
+
+int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
+ u32 flags);
+bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level);
+bool
+i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags);
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
+int __must_check i915_vma_unbind(struct i915_vma *vma);
+void i915_vma_close(struct i915_vma *vma);
+void i915_vma_destroy(struct i915_vma *vma);
+
+int __i915_vma_do_pin(struct i915_vma *vma,
+ u64 size, u64 alignment, u64 flags);
+static inline int __must_check
+i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+ BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW);
+ BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
+ BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
+
+ /* Pin early to prevent the shrinker/eviction logic from destroying
+ * our vma as we insert and bind.
+ */
+ if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0))
+ return 0;
+
+ return __i915_vma_do_pin(vma, size, alignment, flags);
+}
+
+static inline int i915_vma_pin_count(const struct i915_vma *vma)
+{
+ return vma->flags & I915_VMA_PIN_MASK;
+}
+
+static inline bool i915_vma_is_pinned(const struct i915_vma *vma)
+{
+ return i915_vma_pin_count(vma);
+}
+
+static inline void __i915_vma_pin(struct i915_vma *vma)
+{
+ vma->flags++;
+ GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW);
+}
+
+static inline void __i915_vma_unpin(struct i915_vma *vma)
+{
+ GEM_BUG_ON(!i915_vma_is_pinned(vma));
+ vma->flags--;
+}
+
+static inline void i915_vma_unpin(struct i915_vma *vma)
+{
+ GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
+ __i915_vma_unpin(vma);
+}
+
+/**
+ * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
+ * @vma: VMA to iomap
+ *
+ * The passed in VMA has to be pinned in the global GTT mappable region.
+ * An extra pinning of the VMA is acquired for the return iomapping,
+ * the caller must call i915_vma_unpin_iomap to relinquish the pinning
+ * after the iomapping is no longer required.
+ *
+ * Callers must hold the struct_mutex.
+ *
+ * Returns a valid iomapped pointer or ERR_PTR.
+ */
+void __iomem *i915_vma_pin_iomap(struct i915_vma *vma);
+#define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x))
+
+/**
+ * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap
+ * @vma: VMA to unpin
+ *
+ * Unpins the previously iomapped VMA from i915_vma_pin_iomap().
+ *
+ * Callers must hold the struct_mutex. This function is only valid to be
+ * called on a VMA previously iomapped by the caller with i915_vma_pin_iomap().
+ */
+static inline void i915_vma_unpin_iomap(struct i915_vma *vma)
+{
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+ GEM_BUG_ON(vma->iomap == NULL);
+ i915_vma_unpin(vma);
+}
+
+static inline struct page *i915_vma_first_page(struct i915_vma *vma)
+{
+ GEM_BUG_ON(!vma->pages);
+ return sg_page(vma->pages->sgl);
+}
+
+/**
+ * i915_vma_pin_fence - pin fencing state
+ * @vma: vma to pin fencing for
+ *
+ * This pins the fencing state (whether tiled or untiled) to make sure the
+ * vma (and its object) is ready to be used as a scanout target. Fencing
+ * status must be synchronize first by calling i915_vma_get_fence():
+ *
+ * The resulting fence pin reference must be released again with
+ * i915_vma_unpin_fence().
+ *
+ * Returns:
+ *
+ * True if the vma has a fence, false otherwise.
+ */
+static inline bool
+i915_vma_pin_fence(struct i915_vma *vma)
+{
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+ if (vma->fence) {
+ vma->fence->pin_count++;
+ return true;
+ } else
+ return false;
+}
+
+/**
+ * i915_vma_unpin_fence - unpin fencing state
+ * @vma: vma to unpin fencing for
+ *
+ * This releases the fence pin reference acquired through
+ * i915_vma_pin_fence. It will handle both objects with and without an
+ * attached fence correctly, callers do not need to distinguish this.
+ */
+static inline void
+i915_vma_unpin_fence(struct i915_vma *vma)
+{
+ lockdep_assert_held(&vma->vm->dev->struct_mutex);
+ if (vma->fence) {
+ GEM_BUG_ON(vma->fence->pin_count <= 0);
+ vma->fence->pin_count--;
+ }
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index b82de3072d4f..dbe9fb41ae53 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -84,7 +84,6 @@ intel_plane_duplicate_state(struct drm_plane *plane)
state = &intel_state->base;
__drm_atomic_helper_plane_duplicate_state(plane, state);
- intel_state->wait_req = NULL;
return state;
}
@@ -101,13 +100,13 @@ void
intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
- WARN_ON(state && to_intel_plane_state(state)->wait_req);
drm_atomic_helper_plane_destroy_state(plane, state);
}
static int intel_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct drm_crtc *crtc = state->crtc;
struct intel_crtc *intel_crtc;
struct intel_crtc_state *crtc_state;
@@ -142,10 +141,11 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
intel_state->clip.y2 =
crtc_state->base.enable ? crtc_state->pipe_src_h : 0;
- if (state->fb && intel_rotation_90_or_270(state->rotation)) {
- char *format_name;
- if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) {
+ if (state->fb && drm_rotation_90_or_270(state->rotation)) {
+ struct drm_format_name_buf format_name;
+
+ if (state->fb->modifier != I915_FORMAT_MOD_Y_TILED &&
+ state->fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
return -EINVAL;
}
@@ -158,9 +158,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
switch (state->fb->pixel_format) {
case DRM_FORMAT_C8:
case DRM_FORMAT_RGB565:
- format_name = drm_get_format_name(state->fb->pixel_format);
- DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", format_name);
- kfree(format_name);
+ DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
+ drm_get_format_name(state->fb->pixel_format,
+ &format_name));
return -EINVAL;
default:
@@ -168,6 +168,14 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
}
}
+ /* CHV ignores the mirror bit when the rotate bit is set :( */
+ if (IS_CHERRYVIEW(dev_priv) &&
+ state->rotation & DRM_ROTATE_180 &&
+ state->rotation & DRM_REFLECT_X) {
+ DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
+ return -EINVAL;
+ }
+
intel_state->base.visible = false;
ret = intel_plane->check_plane(plane, crtc_state, intel_state);
if (ret)
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 6c70a5bfd7d8..49f10538d4aa 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -57,6 +57,63 @@
* struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver.
*/
+/* DP N/M table */
+#define LC_540M 540000
+#define LC_270M 270000
+#define LC_162M 162000
+
+struct dp_aud_n_m {
+ int sample_rate;
+ int clock;
+ u16 m;
+ u16 n;
+};
+
+/* Values according to DP 1.4 Table 2-104 */
+static const struct dp_aud_n_m dp_aud_n_m[] = {
+ { 32000, LC_162M, 1024, 10125 },
+ { 44100, LC_162M, 784, 5625 },
+ { 48000, LC_162M, 512, 3375 },
+ { 64000, LC_162M, 2048, 10125 },
+ { 88200, LC_162M, 1568, 5625 },
+ { 96000, LC_162M, 1024, 3375 },
+ { 128000, LC_162M, 4096, 10125 },
+ { 176400, LC_162M, 3136, 5625 },
+ { 192000, LC_162M, 2048, 3375 },
+ { 32000, LC_270M, 1024, 16875 },
+ { 44100, LC_270M, 784, 9375 },
+ { 48000, LC_270M, 512, 5625 },
+ { 64000, LC_270M, 2048, 16875 },
+ { 88200, LC_270M, 1568, 9375 },
+ { 96000, LC_270M, 1024, 5625 },
+ { 128000, LC_270M, 4096, 16875 },
+ { 176400, LC_270M, 3136, 9375 },
+ { 192000, LC_270M, 2048, 5625 },
+ { 32000, LC_540M, 1024, 33750 },
+ { 44100, LC_540M, 784, 18750 },
+ { 48000, LC_540M, 512, 11250 },
+ { 64000, LC_540M, 2048, 33750 },
+ { 88200, LC_540M, 1568, 18750 },
+ { 96000, LC_540M, 1024, 11250 },
+ { 128000, LC_540M, 4096, 33750 },
+ { 176400, LC_540M, 3136, 18750 },
+ { 192000, LC_540M, 2048, 11250 },
+};
+
+static const struct dp_aud_n_m *
+audio_config_dp_get_n_m(struct intel_crtc *intel_crtc, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) {
+ if (rate == dp_aud_n_m[i].sample_rate &&
+ intel_crtc->config->port_clock == dp_aud_n_m[i].clock)
+ return &dp_aud_n_m[i];
+ }
+
+ return NULL;
+}
+
static const struct {
int clock;
u32 config;
@@ -81,7 +138,7 @@ static const struct {
int clock;
int n;
int cts;
-} aud_ncts[] = {
+} hdmi_aud_ncts[] = {
{ 44100, TMDS_296M, 4459, 234375 },
{ 44100, TMDS_297M, 4704, 247500 },
{ 48000, TMDS_296M, 5824, 281250 },
@@ -121,45 +178,20 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
return hdmi_audio_clock[i].config;
}
-static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
+static int audio_config_hdmi_get_n(const struct drm_display_mode *adjusted_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;
+ for (i = 0; i < ARRAY_SIZE(hdmi_aud_ncts); i++) {
+ if (rate == hdmi_aud_ncts[i].sample_rate &&
+ adjusted_mode->crtc_clock == hdmi_aud_ncts[i].clock) {
+ return hdmi_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_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
- return true;
- else
- return false;
-}
-
static bool intel_eld_uptodate(struct drm_connector *connector,
i915_reg_t reg_eldv, uint32_t bits_eldv,
i915_reg_t reg_elda, uint32_t bits_elda,
@@ -245,6 +277,100 @@ static void g4x_audio_codec_enable(struct drm_connector *connector,
I915_WRITE(G4X_AUD_CNTL_ST, tmp);
}
+static void
+hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+ const struct drm_display_mode *adjusted_mode)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+ struct i915_audio_component *acomp = dev_priv->audio_component;
+ int rate = acomp ? acomp->aud_sample_rate[port] : 0;
+ const struct dp_aud_n_m *nm = audio_config_dp_get_n_m(intel_crtc, rate);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 tmp;
+
+ if (nm)
+ DRM_DEBUG_KMS("using Maud %u, Naud %u\n", nm->m, nm->n);
+ else
+ DRM_DEBUG_KMS("using automatic Maud, Naud\n");
+
+ tmp = I915_READ(HSW_AUD_CFG(pipe));
+ tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+ tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+ tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+ tmp |= AUD_CONFIG_N_VALUE_INDEX;
+
+ if (nm) {
+ tmp &= ~AUD_CONFIG_N_MASK;
+ tmp |= AUD_CONFIG_N(nm->n);
+ tmp |= AUD_CONFIG_N_PROG_ENABLE;
+ }
+
+ I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp &= ~AUD_CONFIG_M_MASK;
+ tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+ tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+
+ if (nm) {
+ tmp |= nm->m;
+ tmp |= AUD_M_CTS_M_VALUE_INDEX;
+ tmp |= AUD_M_CTS_M_PROG_ENABLE;
+ }
+
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+}
+
+static void
+hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+ const struct drm_display_mode *adjusted_mode)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+ struct i915_audio_component *acomp = dev_priv->audio_component;
+ int rate = acomp ? acomp->aud_sample_rate[port] : 0;
+ enum pipe pipe = intel_crtc->pipe;
+ int n;
+ u32 tmp;
+
+ tmp = I915_READ(HSW_AUD_CFG(pipe));
+ tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+ tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+ tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+ tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
+
+ n = audio_config_hdmi_get_n(adjusted_mode, rate);
+ if (n != 0) {
+ DRM_DEBUG_KMS("using N %d\n", n);
+
+ tmp &= ~AUD_CONFIG_N_MASK;
+ tmp |= AUD_CONFIG_N(n);
+ tmp |= AUD_CONFIG_N_PROG_ENABLE;
+ } else {
+ DRM_DEBUG_KMS("using automatic N\n");
+ }
+
+ I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+ /*
+ * Let's disable "Enable CTS or M Prog bit"
+ * and let HW calculate the value
+ */
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+ tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+}
+
+static void
+hsw_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+ const struct drm_display_mode *adjusted_mode)
+{
+ if (intel_crtc_has_dp_encoder(intel_crtc->config))
+ hsw_dp_audio_config_update(intel_crtc, port, adjusted_mode);
+ else
+ hsw_hdmi_audio_config_update(intel_crtc, port, adjusted_mode);
+}
+
static void hsw_audio_codec_disable(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -276,20 +402,16 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
}
static void hsw_audio_codec_enable(struct drm_connector *connector,
- struct intel_encoder *encoder,
+ struct intel_encoder *intel_encoder,
const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
enum pipe pipe = intel_crtc->pipe;
- struct i915_audio_component *acomp = dev_priv->audio_component;
+ enum port port = intel_encoder->port;
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));
@@ -325,42 +447,17 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
/* Enable timestamps */
- tmp = I915_READ(HSW_AUD_CFG(pipe));
- tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
- tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
- if (intel_crtc_has_dp_encoder(intel_crtc->config))
- tmp |= AUD_CONFIG_N_VALUE_INDEX;
- else
- 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);
+ hsw_audio_config_update(intel_crtc, port, adjusted_mode);
mutex_unlock(&dev_priv->av_mutex);
}
-static void ilk_audio_codec_disable(struct intel_encoder *encoder)
+static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
- enum port port = enc_to_dig_port(&encoder->base)->port;
+ struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
enum pipe pipe = intel_crtc->pipe;
+ enum port port = intel_encoder->port;
uint32_t tmp, eldv;
i915_reg_t aud_config, aud_cntrl_st2;
@@ -400,13 +497,13 @@ 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 intel_encoder *intel_encoder,
const struct drm_display_mode *adjusted_mode)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
- enum port port = enc_to_dig_port(&encoder->base)->port;
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
enum pipe pipe = intel_crtc->pipe;
+ enum port port = intel_encoder->port;
uint8_t *eld = connector->eld;
uint32_t tmp, eldv;
int len, i;
@@ -425,13 +522,13 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
* infrastructure is not there yet.
*/
- if (HAS_PCH_IBX(connector->dev)) {
+ if (HAS_PCH_IBX(dev_priv)) {
hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
aud_config = IBX_AUD_CFG(pipe);
aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
- } else if (IS_VALLEYVIEW(connector->dev) ||
- IS_CHERRYVIEW(connector->dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv)) {
hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
aud_config = VLV_AUD_CFG(pipe);
aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
@@ -480,24 +577,26 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
/**
* intel_audio_codec_enable - Enable the audio codec for HD audio
* @intel_encoder: encoder on which to enable audio
+ * @crtc_state: pointer to the current crtc state.
+ * @conn_state: pointer to the current connector state.
*
* The enable sequences may only be performed after enabling the transcoder and
* port, and after completed link training.
*/
-void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
+void intel_audio_codec_enable(struct intel_encoder *intel_encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
{
struct drm_encoder *encoder = &intel_encoder->base;
- struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
- const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
struct drm_connector *connector;
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct i915_audio_component *acomp = dev_priv->audio_component;
- struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
- enum port port = intel_dig_port->port;
+ enum port port = intel_encoder->port;
+ enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
- connector = drm_select_eld(encoder);
- if (!connector)
+ connector = conn_state->connector;
+ if (!connector || !connector->eld[0])
return;
DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -508,7 +607,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
/* ELD Conn_Type */
connector->eld[5] &= ~(3 << 2);
- if (intel_crtc_has_dp_encoder(crtc->config))
+ if (intel_crtc_has_dp_encoder(crtc_state))
connector->eld[5] |= (1 << 2);
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
@@ -518,13 +617,19 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
adjusted_mode);
mutex_lock(&dev_priv->av_mutex);
- intel_dig_port->audio_connector = connector;
+ intel_encoder->audio_connector = connector;
+
/* referred in audio callbacks */
- dev_priv->dig_port_map[port] = intel_encoder;
+ dev_priv->av_enc_map[pipe] = intel_encoder;
mutex_unlock(&dev_priv->av_mutex);
+ /* audio drivers expect pipe = -1 to indicate Non-MST cases */
+ if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+ pipe = -1;
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
- acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
+ acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
+ (int) port, (int) pipe);
}
/**
@@ -537,22 +642,27 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
{
struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct i915_audio_component *acomp = dev_priv->audio_component;
- struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
- enum port port = intel_dig_port->port;
+ enum port port = intel_encoder->port;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = crtc->pipe;
if (dev_priv->display.audio_codec_disable)
dev_priv->display.audio_codec_disable(intel_encoder);
mutex_lock(&dev_priv->av_mutex);
- intel_dig_port->audio_connector = NULL;
- dev_priv->dig_port_map[port] = NULL;
+ intel_encoder->audio_connector = NULL;
+ dev_priv->av_enc_map[pipe] = NULL;
mutex_unlock(&dev_priv->av_mutex);
+ /* audio drivers expect pipe = -1 to indicate Non-MST cases */
+ if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+ pipe = -1;
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
- acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
+ acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
+ (int) port, (int) pipe);
}
/**
@@ -627,74 +737,68 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
return dev_priv->cdclk_freq;
}
-static int i915_audio_component_sync_audio_rate(struct device *kdev,
- int port, int rate)
+static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
+ int port, int pipe)
+{
+
+ if (WARN_ON(pipe >= I915_MAX_PIPES))
+ return NULL;
+
+ /* MST */
+ if (pipe >= 0)
+ return dev_priv->av_enc_map[pipe];
+
+ /* Non-MST */
+ for_each_pipe(dev_priv, pipe) {
+ struct intel_encoder *encoder;
+
+ encoder = dev_priv->av_enc_map[pipe];
+ if (encoder == NULL)
+ continue;
+
+ if (port == encoder->port)
+ return encoder;
+ }
+
+ return NULL;
+}
+
+static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
+ int pipe, int rate)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_encoder *intel_encoder;
struct intel_crtc *crtc;
- struct drm_display_mode *mode;
+ struct drm_display_mode *adjusted_mode;
struct i915_audio_component *acomp = dev_priv->audio_component;
- enum pipe pipe = INVALID_PIPE;
- u32 tmp;
- int n;
int err = 0;
- /* HSW, BDW, SKL, KBL need this fix */
- if (!IS_SKYLAKE(dev_priv) &&
- !IS_KABYLAKE(dev_priv) &&
- !IS_BROADWELL(dev_priv) &&
- !IS_HASWELL(dev_priv))
+ if (!HAS_DDI(dev_priv))
return 0;
i915_audio_component_get_power(kdev);
mutex_lock(&dev_priv->av_mutex);
+
/* 1. get the pipe */
- intel_encoder = dev_priv->dig_port_map[port];
- /* intel_encoder might be NULL for DP MST */
+ intel_encoder = get_saved_enc(dev_priv, port, pipe);
if (!intel_encoder || !intel_encoder->base.crtc ||
- intel_encoder->type != INTEL_OUTPUT_HDMI) {
- DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
+ (intel_encoder->type != INTEL_OUTPUT_HDMI &&
+ intel_encoder->type != INTEL_OUTPUT_DP)) {
+ DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port));
err = -ENODEV;
goto unlock;
}
+
+ /* pipe passed from the audio driver will be -1 for Non-MST case */
crtc = to_intel_crtc(intel_encoder->base.crtc);
pipe = crtc->pipe;
- if (pipe == INVALID_PIPE) {
- DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
- err = -ENODEV;
- goto unlock;
- }
- DRM_DEBUG_KMS("pipe %c connects port %c\n",
- pipe_name(pipe), port_name(port));
- mode = &crtc->config->base.adjusted_mode;
+ adjusted_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);
- goto unlock;
- }
-
- 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);
- goto unlock;
- }
-
- /* 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);
+ hsw_audio_config_update(crtc, port, adjusted_mode);
unlock:
mutex_unlock(&dev_priv->av_mutex);
@@ -703,27 +807,29 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev,
}
static int i915_audio_component_get_eld(struct device *kdev, int port,
- bool *enabled,
+ int pipe, bool *enabled,
unsigned char *buf, int max_bytes)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_encoder *intel_encoder;
- struct intel_digital_port *intel_dig_port;
const u8 *eld;
int ret = -EINVAL;
mutex_lock(&dev_priv->av_mutex);
- intel_encoder = dev_priv->dig_port_map[port];
- /* intel_encoder might be NULL for DP MST */
- if (intel_encoder) {
- ret = 0;
- intel_dig_port = enc_to_dig_port(&intel_encoder->base);
- *enabled = intel_dig_port->audio_connector != NULL;
- if (*enabled) {
- eld = intel_dig_port->audio_connector->eld;
- ret = drm_eld_size(eld);
- memcpy(buf, eld, min(max_bytes, ret));
- }
+
+ intel_encoder = get_saved_enc(dev_priv, port, pipe);
+ if (!intel_encoder) {
+ DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port));
+ mutex_unlock(&dev_priv->av_mutex);
+ return ret;
+ }
+
+ ret = 0;
+ *enabled = intel_encoder->audio_connector != NULL;
+ if (*enabled) {
+ eld = intel_encoder->audio_connector->eld;
+ ret = drm_eld_size(eld);
+ memcpy(buf, eld, min(max_bytes, ret));
}
mutex_unlock(&dev_priv->av_mutex);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index cf2560708e03..7ffab1abc518 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -996,6 +996,10 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv,
goto err;
}
+ /* Log about presence of sequences we won't run. */
+ if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF)
+ DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id);
+
dev_priv->vbt.dsi.sequence[seq_id] = data + index;
if (sequence->version >= 3)
@@ -1805,3 +1809,52 @@ intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
return false;
}
+
+/**
+ * intel_bios_is_lspcon_present - if LSPCON is attached on %port
+ * @dev_priv: i915 device instance
+ * @port: port to check
+ *
+ * Return true if LSPCON is present on this port
+ */
+bool
+intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ int i;
+
+ if (!HAS_LSPCON(dev_priv))
+ return false;
+
+ for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+ if (!dev_priv->vbt.child_dev[i].common.lspcon)
+ continue;
+
+ switch (dev_priv->vbt.child_dev[i].common.dvo_port) {
+ case DVO_PORT_DPA:
+ case DVO_PORT_HDMIA:
+ if (port == PORT_A)
+ return true;
+ break;
+ case DVO_PORT_DPB:
+ case DVO_PORT_HDMIB:
+ if (port == PORT_B)
+ return true;
+ break;
+ case DVO_PORT_DPC:
+ case DVO_PORT_HDMIC:
+ if (port == PORT_C)
+ return true;
+ break;
+ case DVO_PORT_DPD:
+ case DVO_PORT_HDMID:
+ if (port == PORT_D)
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 495611b7068d..c9c46a538edb 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -83,16 +83,18 @@ static void irq_enable(struct intel_engine_cs *engine)
*/
engine->breadcrumbs.irq_posted = true;
- spin_lock_irq(&engine->i915->irq_lock);
+ /* Caller disables interrupts */
+ spin_lock(&engine->i915->irq_lock);
engine->irq_enable(engine);
- spin_unlock_irq(&engine->i915->irq_lock);
+ spin_unlock(&engine->i915->irq_lock);
}
static void irq_disable(struct intel_engine_cs *engine)
{
- spin_lock_irq(&engine->i915->irq_lock);
+ /* Caller disables interrupts */
+ spin_lock(&engine->i915->irq_lock);
engine->irq_disable(engine);
- spin_unlock_irq(&engine->i915->irq_lock);
+ spin_unlock(&engine->i915->irq_lock);
engine->breadcrumbs.irq_posted = false;
}
@@ -293,9 +295,9 @@ bool intel_engine_add_wait(struct intel_engine_cs *engine,
struct intel_breadcrumbs *b = &engine->breadcrumbs;
bool first;
- spin_lock(&b->lock);
+ spin_lock_irq(&b->lock);
first = __intel_engine_add_wait(engine, wait);
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
return first;
}
@@ -326,7 +328,7 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine,
if (RB_EMPTY_NODE(&wait->node))
return;
- spin_lock(&b->lock);
+ spin_lock_irq(&b->lock);
if (RB_EMPTY_NODE(&wait->node))
goto out_unlock;
@@ -400,7 +402,7 @@ out_unlock:
GEM_BUG_ON(rb_first(&b->waiters) !=
(b->first_wait ? &b->first_wait->node : NULL));
GEM_BUG_ON(!rcu_access_pointer(b->irq_seqno_bh) ^ RB_EMPTY_ROOT(&b->waiters));
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
}
static bool signal_complete(struct drm_i915_gem_request *request)
@@ -464,7 +466,7 @@ static int intel_breadcrumbs_signaler(void *arg)
&request->signaling.wait);
local_bh_disable();
- fence_signal(&request->fence);
+ dma_fence_signal(&request->fence);
local_bh_enable(); /* kick start the tasklets */
/* Find the next oldest signal. Note that as we have
@@ -473,14 +475,14 @@ static int intel_breadcrumbs_signaler(void *arg)
* we just completed - so double check we are still
* the oldest before picking the next one.
*/
- spin_lock(&b->lock);
+ spin_lock_irq(&b->lock);
if (request == b->first_signal) {
struct rb_node *rb =
rb_next(&request->signaling.node);
b->first_signal = rb ? to_signaler(rb) : NULL;
}
rb_erase(&request->signaling.node, &b->signals);
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
i915_gem_request_put(request);
} else {
@@ -502,11 +504,20 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request)
struct rb_node *parent, **p;
bool first, wakeup;
- /* locked by fence_enable_sw_signaling() */
+ /* Note that we may be called from an interrupt handler on another
+ * device (e.g. nouveau signaling a fence completion causing us
+ * to submit a request, and so enable signaling). As such,
+ * we need to make sure that all other users of b->lock protect
+ * against interrupts, i.e. use spin_lock_irqsave.
+ */
+
+ /* locked by dma_fence_enable_sw_signaling() (irqsafe fence->lock) */
assert_spin_locked(&request->lock);
+ if (!request->global_seqno)
+ return;
request->signaling.wait.tsk = b->signaler;
- request->signaling.wait.seqno = request->fence.seqno;
+ request->signaling.wait.seqno = request->global_seqno;
i915_gem_request_get(request);
spin_lock(&b->lock);
@@ -530,8 +541,8 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request)
p = &b->signals.rb_node;
while (*p) {
parent = *p;
- if (i915_seqno_passed(request->fence.seqno,
- to_signaler(parent)->fence.seqno)) {
+ if (i915_seqno_passed(request->global_seqno,
+ to_signaler(parent)->global_seqno)) {
p = &parent->rb_right;
first = false;
} else {
@@ -592,7 +603,7 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
struct intel_breadcrumbs *b = &engine->breadcrumbs;
cancel_fake_irq(engine);
- spin_lock(&b->lock);
+ spin_lock_irq(&b->lock);
__intel_breadcrumbs_disable_irq(b);
if (intel_engine_has_waiter(engine)) {
@@ -605,7 +616,7 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
irq_disable(engine);
}
- spin_unlock(&b->lock);
+ spin_unlock_irq(&b->lock);
}
void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
@@ -618,33 +629,28 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
cancel_fake_irq(engine);
}
-unsigned int intel_kick_waiters(struct drm_i915_private *i915)
+unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
unsigned int mask = 0;
- /* To avoid the task_struct disappearing beneath us as we wake up
- * the process, we must first inspect the task_struct->state under the
- * RCU lock, i.e. as we call wake_up_process() we must be holding the
- * rcu_read_lock().
- */
- for_each_engine(engine, i915)
- if (unlikely(intel_engine_wakeup(engine)))
- mask |= intel_engine_flag(engine);
+ for_each_engine(engine, i915, id) {
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
- return mask;
-}
+ spin_lock_irq(&b->lock);
-unsigned int intel_kick_signalers(struct drm_i915_private *i915)
-{
- struct intel_engine_cs *engine;
- unsigned int mask = 0;
+ if (b->first_wait) {
+ wake_up_process(b->first_wait->tsk);
+ mask |= intel_engine_flag(engine);
+ }
- for_each_engine(engine, i915) {
- if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) {
- wake_up_process(engine->breadcrumbs.signaler);
+ if (b->first_signal) {
+ wake_up_process(b->signaler);
mask |= intel_engine_flag(engine);
}
+
+ spin_unlock_irq(&b->lock);
}
return mask;
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
index 95a72771eea6..d81232b79f00 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -95,8 +95,7 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
{
struct drm_crtc *crtc = crtc_state->crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int i, pipe = intel_crtc->pipe;
uint16_t coeffs[9] = { 0, };
@@ -180,7 +179,7 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
- if (INTEL_INFO(dev)->gen > 6) {
+ if (INTEL_GEN(dev_priv) > 6) {
uint16_t postoff = 0;
if (intel_crtc_state->limited_color_range)
@@ -273,7 +272,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
enum pipe pipe = intel_crtc->pipe;
int i;
- if (HAS_GMCH_DISPLAY(dev)) {
+ if (HAS_GMCH_DISPLAY(dev_priv)) {
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
assert_dsi_pll_enabled(dev_priv);
else
@@ -288,7 +287,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
(drm_color_lut_extract(lut[i].green, 8) << 8) |
drm_color_lut_extract(lut[i].blue, 8);
- if (HAS_GMCH_DISPLAY(dev))
+ if (HAS_GMCH_DISPLAY(dev_priv))
I915_WRITE(PALETTE(pipe, i), word);
else
I915_WRITE(LGC_PALETTE(pipe, i), word);
@@ -297,7 +296,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
for (i = 0; i < 256; i++) {
uint32_t word = (i << 16) | (i << 8) | i;
- if (HAS_GMCH_DISPLAY(dev))
+ if (HAS_GMCH_DISPLAY(dev_priv))
I915_WRITE(PALETTE(pipe, i), word);
else
I915_WRITE(LGC_PALETTE(pipe, i), word);
@@ -326,7 +325,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state)
* 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.
*/
- if (IS_HASWELL(dev) && intel_crtc_state->ips_enabled &&
+ if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled &&
(intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
hsw_disable_ips(intel_crtc);
reenable_ips = true;
@@ -345,11 +344,10 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state)
static void broadwell_load_luts(struct drm_crtc_state *state)
{
struct drm_crtc *crtc = state->crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
- uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+ uint32_t i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
if (crtc_state_is_legacy(state)) {
haswell_load_luts(state);
@@ -428,8 +426,7 @@ static void broadwell_load_luts(struct drm_crtc_state *state)
static void cherryview_load_luts(struct drm_crtc_state *state)
{
struct drm_crtc *crtc = state->crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
struct drm_color_lut *lut;
uint32_t i, lut_size;
@@ -446,7 +443,7 @@ static void cherryview_load_luts(struct drm_crtc_state *state)
if (state->degamma_lut) {
lut = (struct drm_color_lut *) state->degamma_lut->data;
- lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+ lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
for (i = 0; i < lut_size; i++) {
/* Write LUT in U0.14 format. */
word0 =
@@ -461,7 +458,7 @@ static void cherryview_load_luts(struct drm_crtc_state *state)
if (state->gamma_lut) {
lut = (struct drm_color_lut *) state->gamma_lut->data;
- lut_size = INTEL_INFO(dev)->color.gamma_lut_size;
+ lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
for (i = 0; i < lut_size; i++) {
/* Write LUT in U0.10 format. */
word0 =
@@ -497,12 +494,12 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state)
int intel_color_check(struct drm_crtc *crtc,
struct drm_crtc_state *crtc_state)
{
- struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
size_t gamma_length, degamma_length;
- degamma_length = INTEL_INFO(dev)->color.degamma_lut_size *
+ degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size *
sizeof(struct drm_color_lut);
- gamma_length = INTEL_INFO(dev)->color.gamma_lut_size *
+ gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size *
sizeof(struct drm_color_lut);
/*
@@ -529,19 +526,18 @@ int intel_color_check(struct drm_crtc *crtc,
void intel_color_init(struct drm_crtc *crtc)
{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
drm_mode_crtc_set_gamma_size(crtc, 256);
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
dev_priv->display.load_luts = cherryview_load_luts;
- } else if (IS_HASWELL(dev)) {
+ } else if (IS_HASWELL(dev_priv)) {
dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
dev_priv->display.load_luts = haswell_load_luts;
- } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
- IS_BROXTON(dev) || IS_KABYLAKE(dev)) {
+ } else if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) ||
+ IS_BROXTON(dev_priv) || IS_KABYLAKE(dev_priv)) {
dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
dev_priv->display.load_luts = broadwell_load_luts;
} else {
@@ -549,10 +545,10 @@ void intel_color_init(struct drm_crtc *crtc)
}
/* Enable color management support when we have degamma & gamma LUTs. */
- if (INTEL_INFO(dev)->color.degamma_lut_size != 0 &&
- INTEL_INFO(dev)->color.gamma_lut_size != 0)
+ if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
+ INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
drm_crtc_enable_color_mgmt(crtc,
- INTEL_INFO(dev)->color.degamma_lut_size,
- true,
- INTEL_INFO(dev)->color.gamma_lut_size);
+ INTEL_INFO(dev_priv)->color.degamma_lut_size,
+ true,
+ INTEL_INFO(dev_priv)->color.gamma_lut_size);
}
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index dfbcf16b41df..86ecec5601d4 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -84,7 +84,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
if (!(tmp & ADPA_DAC_ENABLE))
goto out;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
*pipe = PORT_TO_PIPE_CPT(tmp);
else
*pipe = PORT_TO_PIPE(tmp);
@@ -147,14 +147,13 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int mode)
{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
u32 adpa;
- if (INTEL_INFO(dev)->gen >= 5)
+ if (INTEL_GEN(dev_priv) >= 5)
adpa = ADPA_HOTPLUG_BITS;
else
adpa = 0;
@@ -165,16 +164,16 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
/* For CPT allow 3 pipe config, for others just use A or B */
- if (HAS_PCH_LPT(dev))
+ if (HAS_PCH_LPT(dev_priv))
; /* Those bits don't exist here */
- else if (HAS_PCH_CPT(dev))
+ else if (HAS_PCH_CPT(dev_priv))
adpa |= PORT_TRANS_SEL_CPT(crtc->pipe);
else if (crtc->pipe == 0)
adpa |= ADPA_PIPE_A_SELECT;
else
adpa |= ADPA_PIPE_B_SELECT;
- if (!HAS_PCH_SPLIT(dev))
+ if (!HAS_PCH_SPLIT(dev_priv))
I915_WRITE(BCLRPAT(crtc->pipe), 0);
switch (mode) {
@@ -241,7 +240,8 @@ intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct drm_device *dev = connector->dev;
- int max_dotclk = to_i915(dev)->max_dotclk_freq;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ int max_dotclk = dev_priv->max_dotclk_freq;
int max_clock;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -250,15 +250,15 @@ intel_crt_mode_valid(struct drm_connector *connector,
if (mode->clock < 25000)
return MODE_CLOCK_LOW;
- if (HAS_PCH_LPT(dev))
+ if (HAS_PCH_LPT(dev_priv))
max_clock = 180000;
- else if (IS_VALLEYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv))
/*
* 270 MHz due to current DPLL limits,
* DAC limit supposedly 355 MHz.
*/
max_clock = 270000;
- else if (IS_GEN3(dev) || IS_GEN4(dev))
+ else if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv))
max_clock = 400000;
else
max_clock = 350000;
@@ -269,7 +269,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
return MODE_CLOCK_HIGH;
/* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */
- if (HAS_PCH_LPT(dev) &&
+ if (HAS_PCH_LPT(dev_priv) &&
(ironlake_get_lanes_required(mode->clock, 270000, 24) > 2))
return MODE_CLOCK_HIGH;
@@ -280,13 +280,13 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
pipe_config->has_pch_encoder = true;
/* LPT FDI RX only supports 8bpc. */
- if (HAS_PCH_LPT(dev)) {
+ if (HAS_PCH_LPT(dev_priv)) {
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
DRM_DEBUG_KMS("LPT only supports 24bpp\n");
return false;
@@ -296,7 +296,7 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
}
/* FDI must always be 2.7 GHz */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
pipe_config->port_clock = 135000 * 2;
return true;
@@ -312,7 +312,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
/* The first time through, trigger an explicit detection cycle */
if (crt->force_hotplug_required) {
- bool turn_off_dac = HAS_PCH_SPLIT(dev);
+ bool turn_off_dac = HAS_PCH_SPLIT(dev_priv);
u32 save_adpa;
crt->force_hotplug_required = 0;
@@ -419,10 +419,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
bool ret = false;
int i, tries = 0;
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
return intel_ironlake_crt_detect_hotplug(connector);
- if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv))
return valleyview_crt_detect_hotplug(connector);
/*
@@ -430,7 +430,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
* to get a reliable result.
*/
- if (IS_G4X(dev) && !IS_GM45(dev))
+ if (IS_G4X(dev_priv) && !IS_GM45(dev_priv))
tries = 2;
else
tries = 1;
@@ -566,13 +566,13 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe)
/* Set the border color to purple. */
I915_WRITE(bclrpat_reg, 0x500050);
- if (!IS_GEN2(dev)) {
+ if (!IS_GEN2(dev_priv)) {
uint32_t pipeconf = I915_READ(pipeconf_reg);
I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
POSTING_READ(pipeconf_reg);
/* Wait for next Vblank to substitue
* border color for Color info */
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
st00 = I915_READ8(_VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :
@@ -643,11 +643,36 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe)
return status;
}
+static int intel_spurious_crt_detect_dmi_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_DRIVER("Skipping CRT detection for %s\n", id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id intel_spurious_crt_detect[] = {
+ {
+ .callback = intel_spurious_crt_detect_dmi_callback,
+ .ident = "ACER ZGB",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+ },
+ },
+ {
+ .callback = intel_spurious_crt_detect_dmi_callback,
+ .ident = "Intel DZ77BH-55K",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "DZ77BH-55K"),
+ },
+ },
+ { }
+};
+
static enum drm_connector_status
intel_crt_detect(struct drm_connector *connector, bool force)
{
- struct drm_device *dev = connector->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(connector);
struct intel_encoder *intel_encoder = &crt->base;
enum intel_display_power_domain power_domain;
@@ -659,10 +684,14 @@ intel_crt_detect(struct drm_connector *connector, bool force)
connector->base.id, connector->name,
force);
+ /* Skip machines without VGA that falsely report hotplug events */
+ if (dmi_check_system(intel_spurious_crt_detect))
+ return connector_status_disconnected;
+
power_domain = intel_display_port_power_domain(intel_encoder);
intel_display_power_get(dev_priv, power_domain);
- if (I915_HAS_HOTPLUG(dev)) {
+ if (I915_HAS_HOTPLUG(dev_priv)) {
/* We can not rely on the HPD pin always being correctly wired
* up, for example many KVM do not pass it through, and so
* only trust an assertion that the monitor is connected.
@@ -684,7 +713,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
* broken monitor (without edid) to work behind a broken kvm (that fails
* to have the right resistors for HP detection) needs to fix this up.
* For now just bail out. */
- if (I915_HAS_HOTPLUG(dev) && !i915.load_detect_test) {
+ if (I915_HAS_HOTPLUG(dev_priv) && !i915.load_detect_test) {
status = connector_status_disconnected;
goto out;
}
@@ -700,7 +729,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
if (intel_crt_detect_ddc(connector))
status = connector_status_connected;
- else if (INTEL_INFO(dev)->gen < 4)
+ else if (INTEL_GEN(dev_priv) < 4)
status = intel_crt_load_detect(crt,
to_intel_crtc(connector->state->crtc)->pipe);
else if (i915.load_detect_test)
@@ -740,7 +769,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
ret = intel_crt_ddc_get_modes(connector, i2c);
- if (ret || !IS_G4X(dev))
+ if (ret || !IS_G4X(dev_priv))
goto out;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
@@ -762,11 +791,10 @@ static int intel_crt_set_property(struct drm_connector *connector,
void intel_crt_reset(struct drm_encoder *encoder)
{
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct intel_crt *crt = intel_encoder_to_crt(to_intel_encoder(encoder));
- if (INTEL_INFO(dev)->gen >= 5) {
+ if (INTEL_GEN(dev_priv) >= 5) {
u32 adpa;
adpa = I915_READ(crt->adpa_reg);
@@ -808,32 +836,6 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
.destroy = intel_encoder_destroy,
};
-static int intel_no_crt_dmi_callback(const struct dmi_system_id *id)
-{
- DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
- return 1;
-}
-
-static const struct dmi_system_id intel_no_crt[] = {
- {
- .callback = intel_no_crt_dmi_callback,
- .ident = "ACER ZGB",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
- },
- },
- {
- .callback = intel_no_crt_dmi_callback,
- .ident = "DELL XPS 8700",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"),
- },
- },
- { }
-};
-
void intel_crt_init(struct drm_device *dev)
{
struct drm_connector *connector;
@@ -843,13 +845,9 @@ void intel_crt_init(struct drm_device *dev)
i915_reg_t adpa_reg;
u32 adpa;
- /* Skip machines without VGA that falsely report hotplug events */
- if (dmi_check_system(intel_no_crt))
- return;
-
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
adpa_reg = PCH_ADPA;
- else if (IS_VALLEYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv))
adpa_reg = VLV_ADPA;
else
adpa_reg = ADPA;
@@ -893,12 +891,12 @@ void intel_crt_init(struct drm_device *dev)
crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI);
- if (IS_I830(dev))
+ if (IS_I830(dev_priv))
crt->base.crtc_mask = (1 << 0);
else
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
connector->interlace_allowed = 0;
else
connector->interlace_allowed = 1;
@@ -907,20 +905,23 @@ void intel_crt_init(struct drm_device *dev)
crt->adpa_reg = adpa_reg;
crt->base.compute_config = intel_crt_compute_config;
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
crt->base.disable = pch_disable_crt;
crt->base.post_disable = pch_post_disable_crt;
} else {
crt->base.disable = intel_disable_crt;
}
crt->base.enable = intel_enable_crt;
- if (I915_HAS_HOTPLUG(dev))
+ if (I915_HAS_HOTPLUG(dev_priv) &&
+ !dmi_check_system(intel_spurious_crt_detect))
crt->base.hpd_pin = HPD_CRT;
- if (HAS_DDI(dev)) {
+ if (HAS_DDI(dev_priv)) {
+ crt->base.port = PORT_E;
crt->base.get_config = hsw_crt_get_config;
crt->base.get_hw_state = intel_ddi_get_hw_state;
crt->base.post_disable = hsw_post_disable_crt;
} else {
+ crt->base.port = PORT_NONE;
crt->base.get_config = intel_crt_get_config;
crt->base.get_hw_state = intel_crt_get_hw_state;
}
@@ -928,7 +929,7 @@ void intel_crt_init(struct drm_device *dev)
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
- if (!I915_HAS_HOTPLUG(dev))
+ if (!I915_HAS_HOTPLUG(dev_priv))
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
/*
@@ -941,7 +942,7 @@ void intel_crt_init(struct drm_device *dev)
* polarity and link reversal bits or not, instead of relying on the
* BIOS.
*/
- if (HAS_PCH_LPT(dev)) {
+ if (HAS_PCH_LPT(dev_priv)) {
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
FDI_RX_LINK_REVERSAL_OVERRIDE;
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index 1ea0e1f43397..d7a04bca8c28 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -168,12 +168,6 @@ struct stepping_info {
char substepping;
};
-static const struct stepping_info kbl_stepping_info[] = {
- {'A', '0'}, {'B', '0'}, {'C', '0'},
- {'D', '0'}, {'E', '0'}, {'F', '0'},
- {'G', '0'}, {'H', '0'}, {'I', '0'},
-};
-
static const struct stepping_info skl_stepping_info[] = {
{'A', '0'}, {'B', '0'}, {'C', '0'},
{'D', '0'}, {'E', '0'}, {'F', '0'},
@@ -194,10 +188,7 @@ intel_get_stepping_info(struct drm_i915_private *dev_priv)
const struct stepping_info *si;
unsigned int size;
- if (IS_KABYLAKE(dev_priv)) {
- size = ARRAY_SIZE(kbl_stepping_info);
- si = kbl_stepping_info;
- } else if (IS_SKYLAKE(dev_priv)) {
+ if (IS_SKYLAKE(dev_priv)) {
size = ARRAY_SIZE(skl_stepping_info);
si = skl_stepping_info;
} else if (IS_BROXTON(dev_priv)) {
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 15d47c87def6..10ec9d4b7d45 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -167,8 +167,47 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
{ 0x80005012, 0x000000C0, 0x3 },
};
+/* Kabylake H and S */
+static const struct ddi_buf_trans kbl_ddi_translations_dp[] = {
+ { 0x00002016, 0x000000A0, 0x0 },
+ { 0x00005012, 0x0000009B, 0x0 },
+ { 0x00007011, 0x00000088, 0x0 },
+ { 0x80009010, 0x000000C0, 0x1 },
+ { 0x00002016, 0x0000009B, 0x0 },
+ { 0x00005012, 0x00000088, 0x0 },
+ { 0x80007011, 0x000000C0, 0x1 },
+ { 0x00002016, 0x00000097, 0x0 },
+ { 0x80005012, 0x000000C0, 0x1 },
+};
+
+/* Kabylake U */
+static const struct ddi_buf_trans kbl_u_ddi_translations_dp[] = {
+ { 0x0000201B, 0x000000A1, 0x0 },
+ { 0x00005012, 0x00000088, 0x0 },
+ { 0x80007011, 0x000000CD, 0x3 },
+ { 0x80009010, 0x000000C0, 0x3 },
+ { 0x0000201B, 0x0000009D, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 },
+ { 0x80007011, 0x000000C0, 0x3 },
+ { 0x00002016, 0x0000004F, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 },
+};
+
+/* Kabylake Y */
+static const struct ddi_buf_trans kbl_y_ddi_translations_dp[] = {
+ { 0x00001017, 0x000000A1, 0x0 },
+ { 0x00005012, 0x00000088, 0x0 },
+ { 0x80007011, 0x000000CD, 0x3 },
+ { 0x8000800F, 0x000000C0, 0x3 },
+ { 0x00001017, 0x0000009D, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 },
+ { 0x80007011, 0x000000C0, 0x3 },
+ { 0x00001017, 0x0000004C, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 },
+};
+
/*
- * Skylake H and S
+ * Skylake/Kabylake H and S
* eDP 1.4 low vswing translation parameters
*/
static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
@@ -185,7 +224,7 @@ static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
};
/*
- * Skylake U
+ * Skylake/Kabylake U
* eDP 1.4 low vswing translation parameters
*/
static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = {
@@ -202,7 +241,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = {
};
/*
- * Skylake Y
+ * Skylake/Kabylake Y
* eDP 1.4 low vswing translation parameters
*/
static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = {
@@ -218,7 +257,7 @@ static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = {
{ 0x00000018, 0x0000008A, 0x0 },
};
-/* Skylake U, H and S */
+/* Skylake/Kabylake U, H and S */
static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
{ 0x00000018, 0x000000AC, 0x0 },
{ 0x00005012, 0x0000009D, 0x0 },
@@ -233,7 +272,7 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
{ 0x80000018, 0x000000C0, 0x1 },
};
-/* Skylake Y */
+/* Skylake/Kabylake Y */
static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = {
{ 0x00000018, 0x000000A1, 0x0 },
{ 0x00005012, 0x000000DF, 0x0 },
@@ -334,10 +373,10 @@ bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
static const struct ddi_buf_trans *
skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
{
- if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
+ if (IS_SKL_ULX(dev_priv)) {
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
return skl_y_ddi_translations_dp;
- } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) {
+ } else if (IS_SKL_ULT(dev_priv)) {
*n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
return skl_u_ddi_translations_dp;
} else {
@@ -347,6 +386,21 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
}
static const struct ddi_buf_trans *
+kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
+{
+ if (IS_KBL_ULX(dev_priv)) {
+ *n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp);
+ return kbl_y_ddi_translations_dp;
+ } else if (IS_KBL_ULT(dev_priv)) {
+ *n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp);
+ return kbl_u_ddi_translations_dp;
+ } else {
+ *n_entries = ARRAY_SIZE(kbl_ddi_translations_dp);
+ return kbl_ddi_translations_dp;
+ }
+}
+
+static const struct ddi_buf_trans *
skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
{
if (dev_priv->vbt.edp.low_vswing) {
@@ -362,7 +416,10 @@ skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
}
}
- return skl_get_buf_trans_dp(dev_priv, n_entries);
+ if (IS_KABYLAKE(dev_priv))
+ return kbl_get_buf_trans_dp(dev_priv, n_entries);
+ else
+ return skl_get_buf_trans_dp(dev_priv, n_entries);
}
static const struct ddi_buf_trans *
@@ -430,21 +487,18 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder)
if (IS_BROXTON(dev_priv))
return;
- if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+ if (IS_KABYLAKE(dev_priv)) {
+ ddi_translations_fdi = NULL;
+ ddi_translations_dp =
+ kbl_get_buf_trans_dp(dev_priv, &n_dp_entries);
+ ddi_translations_edp =
+ skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
+ } else if (IS_SKYLAKE(dev_priv)) {
ddi_translations_fdi = NULL;
ddi_translations_dp =
skl_get_buf_trans_dp(dev_priv, &n_dp_entries);
ddi_translations_edp =
skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
-
- /* If we're boosting the current, set bit 31 of trans1 */
- if (dev_priv->vbt.ddi_port_info[port].dp_boost_level)
- iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
-
- if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
- port != PORT_A && port != PORT_E &&
- n_edp_entries > 9))
- n_edp_entries = 9;
} else if (IS_BROADWELL(dev_priv)) {
ddi_translations_fdi = bdw_ddi_translations_fdi;
ddi_translations_dp = bdw_ddi_translations_dp;
@@ -464,6 +518,17 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder)
n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
}
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+ /* If we're boosting the current, set bit 31 of trans1 */
+ if (dev_priv->vbt.ddi_port_info[port].dp_boost_level)
+ iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
+
+ if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
+ port != PORT_A && port != PORT_E &&
+ n_edp_entries > 9))
+ n_edp_entries = 9;
+ }
+
switch (encoder->type) {
case INTEL_OUTPUT_EDP:
ddi_translations = ddi_translations_edp;
@@ -1020,13 +1085,13 @@ static void bxt_ddi_clock_get(struct intel_encoder *encoder,
void intel_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (INTEL_INFO(dev)->gen <= 8)
+ if (INTEL_GEN(dev_priv) <= 8)
hsw_ddi_clock_get(encoder, pipe_config);
- else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
skl_ddi_clock_get(encoder, pipe_config);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
bxt_ddi_clock_get(encoder, pipe_config);
}
@@ -1081,14 +1146,14 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc,
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
struct intel_encoder *intel_encoder =
intel_ddi_get_crtc_new_encoder(crtc_state);
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
return skl_ddi_pll_select(intel_crtc, crtc_state,
intel_encoder);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
return bxt_ddi_pll_select(intel_crtc, crtc_state,
intel_encoder);
else
@@ -1189,7 +1254,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
* eDP when not using the panel fitter, and when not
* using motion blur mitigation (which we don't
* support). */
- if (IS_HASWELL(dev) &&
+ if (IS_HASWELL(dev_priv) &&
(intel_crtc->config->pch_pfit.enabled ||
intel_crtc->config->pch_pfit.force_thru))
temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
@@ -1434,7 +1499,12 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level)
if (dp_iboost) {
iboost = dp_iboost;
} else {
- ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries);
+ if (IS_KABYLAKE(dev_priv))
+ ddi_translations = kbl_get_buf_trans_dp(dev_priv,
+ &n_entries);
+ else
+ ddi_translations = skl_get_buf_trans_dp(dev_priv,
+ &n_entries);
iboost = ddi_translations[level].i_boost;
}
} else if (type == INTEL_OUTPUT_EDP) {
@@ -1477,7 +1547,6 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
{
const struct bxt_ddi_buf_trans *ddi_translations;
u32 n_entries, i;
- uint32_t val;
if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
@@ -1506,38 +1575,11 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
}
}
- /*
- * While we write to the group register to program all lanes at once we
- * can read only lane registers and we pick lanes 0/1 for that.
- */
- val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
- val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
- I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
-
- val = I915_READ(BXT_PORT_TX_DW2_LN0(port));
- val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
- val |= ddi_translations[level].margin << MARGIN_000_SHIFT |
- ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT;
- I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val);
-
- val = I915_READ(BXT_PORT_TX_DW3_LN0(port));
- val &= ~SCALE_DCOMP_METHOD;
- if (ddi_translations[level].enable)
- 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));
- val &= ~DE_EMPHASIS;
- val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT;
- I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val);
-
- val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
- val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
- I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
+ bxt_ddi_phy_set_signal_level(dev_priv, port,
+ ddi_translations[level].margin,
+ ddi_translations[level].scale,
+ ddi_translations[level].enable,
+ ddi_translations[level].deemphasis);
}
static uint32_t translate_signal_level(int signal_levels)
@@ -1711,8 +1753,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder,
struct drm_connector_state *old_conn_state)
{
struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
enum port port = intel_ddi_get_encoder_port(intel_encoder);
int type = intel_encoder->type;
uint32_t val;
@@ -1742,10 +1783,10 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder,
intel_edp_panel_off(intel_dp);
}
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
DPLL_CTRL2_DDI_CLK_OFF(port)));
- else if (INTEL_INFO(dev)->gen < 9)
+ else if (INTEL_GEN(dev_priv) < 9)
I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
if (type == INTEL_OUTPUT_HDMI) {
@@ -1795,8 +1836,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder,
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
enum port port = intel_ddi_get_encoder_port(intel_encoder);
int type = intel_encoder->type;
@@ -1814,7 +1854,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder,
} else if (type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- if (port == PORT_A && INTEL_INFO(dev)->gen < 9)
+ if (port == PORT_A && INTEL_GEN(dev_priv) < 9)
intel_dp_stop_link_train(intel_dp);
intel_edp_backlight_on(intel_dp);
@@ -1824,7 +1864,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder,
if (intel_crtc->config->has_audio) {
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
- intel_audio_codec_enable(intel_encoder);
+ intel_audio_codec_enable(intel_encoder, pipe_config, conn_state);
}
}
@@ -1853,332 +1893,14 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder,
}
}
-bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
- enum dpio_phy phy)
-{
- enum port port;
-
- if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
- return false;
-
- if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
- (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
- DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n",
- phy);
-
- return false;
- }
-
- if (phy == DPIO_PHY1 &&
- !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) {
- DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n");
-
- return false;
- }
-
- if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
- DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n",
- phy);
-
- return false;
- }
-
- for_each_port_masked(port,
- phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) :
- BIT(PORT_A)) {
- u32 tmp = I915_READ(BXT_PHY_CTL(port));
-
- if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
- DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
- "for port %c powered down "
- "(PHY_CTL %08x)\n",
- phy, port_name(port), tmp);
-
- return false;
- }
- }
-
- return true;
-}
-
-static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
- u32 val = I915_READ(BXT_PORT_REF_DW6(phy));
-
- return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
-}
-
-static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
- enum dpio_phy phy)
-{
- if (intel_wait_for_register(dev_priv,
- BXT_PORT_REF_DW3(phy),
- GRC_DONE, GRC_DONE,
- 10))
- DRM_ERROR("timeout waiting for PHY%d GRC\n", phy);
-}
-
-void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
- u32 val;
-
- if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
- /* Still read out the GRC value for state verification */
- if (phy == DPIO_PHY0)
- dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy);
-
- if (bxt_ddi_phy_verify_state(dev_priv, phy)) {
- DRM_DEBUG_DRIVER("DDI PHY %d already enabled, "
- "won't reprogram it\n", phy);
-
- return;
- }
-
- DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, "
- "force reprogramming it\n", phy);
- }
-
- val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
- val |= GT_DISPLAY_POWER_ON(phy);
- I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
-
- /*
- * The PHY registers start out inaccessible and respond to reads with
- * all 1s. Eventually they become accessible as they power up, then
- * the reserved bit will give the default 0. Poll on the reserved bit
- * becoming 0 to find when the PHY is accessible.
- * HW team confirmed that the time to reach phypowergood status is
- * anywhere between 50 us and 100us.
- */
- if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
- (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
- DRM_ERROR("timeout during PHY%d power on\n", phy);
- }
-
- /* Program PLL Rcomp code offset */
- val = I915_READ(BXT_PORT_CL1CM_DW9(phy));
- val &= ~IREF0RC_OFFSET_MASK;
- val |= 0xE4 << IREF0RC_OFFSET_SHIFT;
- I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val);
-
- val = I915_READ(BXT_PORT_CL1CM_DW10(phy));
- val &= ~IREF1RC_OFFSET_MASK;
- val |= 0xE4 << IREF1RC_OFFSET_SHIFT;
- I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val);
-
- /* Program power gating */
- val = I915_READ(BXT_PORT_CL1CM_DW28(phy));
- val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN |
- SUS_CLK_CONFIG;
- I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);
-
- if (phy == DPIO_PHY0) {
- val = I915_READ(BXT_PORT_CL2CM_DW6_BC);
- val |= DW6_OLDO_DYN_PWR_DOWN_EN;
- I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val);
- }
-
- val = I915_READ(BXT_PORT_CL1CM_DW30(phy));
- val &= ~OCL2_LDOFUSE_PWR_DIS;
- /*
- * On PHY1 disable power on the second channel, since no port is
- * connected there. On PHY0 both channels have a port, so leave it
- * enabled.
- * TODO: port C is only connected on BXT-P, so on BXT0/1 we should
- * power down the second channel on PHY0 as well.
- *
- * FIXME: Clarify programming of the following, the register is
- * read-only with bit 6 fixed at 0 at least in stepping A.
- */
- if (phy == DPIO_PHY1)
- val |= OCL2_LDOFUSE_PWR_DIS;
- I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val);
-
- if (phy == DPIO_PHY0) {
- uint32_t grc_code;
- /*
- * PHY0 isn't connected to an RCOMP resistor so copy over
- * the corresponding calibrated value from PHY1, and disable
- * the automatic calibration on PHY0.
- */
- val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1);
- grc_code = val << GRC_CODE_FAST_SHIFT |
- val << GRC_CODE_SLOW_SHIFT |
- val;
- I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code);
-
- val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0));
- val |= GRC_DIS | GRC_RDY_OVRD;
- I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val);
- }
-
- val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
- val |= COMMON_RESET_DIS;
- I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
-
- if (phy == DPIO_PHY1)
- bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1);
-}
-
-void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
- uint32_t val;
-
- val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
- val &= ~COMMON_RESET_DIS;
- I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
-
- val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
- val &= ~GT_DISPLAY_POWER_ON(phy);
- I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
-}
-
-static bool __printf(6, 7)
-__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
- i915_reg_t reg, u32 mask, u32 expected,
- const char *reg_fmt, ...)
-{
- struct va_format vaf;
- va_list args;
- u32 val;
-
- val = I915_READ(reg);
- if ((val & mask) == expected)
- return true;
-
- va_start(args, reg_fmt);
- vaf.fmt = reg_fmt;
- vaf.va = &args;
-
- DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: "
- "current %08x, expected %08x (mask %08x)\n",
- phy, &vaf, reg.reg, val, (val & ~mask) | expected,
- mask);
-
- va_end(args);
-
- return false;
-}
-
-bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
- enum dpio_phy phy)
-{
- uint32_t mask;
- bool ok;
-
-#define _CHK(reg, mask, exp, fmt, ...) \
- __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \
- ## __VA_ARGS__)
-
- if (!bxt_ddi_phy_is_enabled(dev_priv, phy))
- return false;
-
- ok = true;
-
- /* PLL Rcomp code offset */
- ok &= _CHK(BXT_PORT_CL1CM_DW9(phy),
- IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT,
- "BXT_PORT_CL1CM_DW9(%d)", phy);
- ok &= _CHK(BXT_PORT_CL1CM_DW10(phy),
- IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT,
- "BXT_PORT_CL1CM_DW10(%d)", phy);
-
- /* Power gating */
- mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG;
- ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
- "BXT_PORT_CL1CM_DW28(%d)", phy);
-
- if (phy == DPIO_PHY0)
- ok &= _CHK(BXT_PORT_CL2CM_DW6_BC,
- DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
- "BXT_PORT_CL2CM_DW6_BC");
-
- /*
- * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS,
- * at least on stepping A this bit is read-only and fixed at 0.
- */
-
- if (phy == DPIO_PHY0) {
- u32 grc_code = dev_priv->bxt_phy_grc;
-
- grc_code = grc_code << GRC_CODE_FAST_SHIFT |
- grc_code << GRC_CODE_SLOW_SHIFT |
- grc_code;
- mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK |
- GRC_CODE_NOM_MASK;
- ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code,
- "BXT_PORT_REF_DW6(%d)", DPIO_PHY0);
-
- mask = GRC_DIS | GRC_RDY_OVRD;
- ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask,
- "BXT_PORT_REF_DW8(%d)", DPIO_PHY0);
- }
-
- return ok;
-#undef _CHK
-}
-
-static uint8_t
-bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
- struct intel_crtc_state *pipe_config)
-{
- switch (pipe_config->lane_count) {
- case 1:
- return 0;
- case 2:
- return BIT(2) | BIT(0);
- case 4:
- return BIT(3) | BIT(2) | BIT(0);
- default:
- MISSING_CASE(pipe_config->lane_count);
-
- return 0;
- }
-}
-
static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
- struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
- enum port port = dport->port;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
- int lane;
-
- for (lane = 0; lane < 4; lane++) {
- u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane));
-
- /*
- * Note that on CHV this flag is called UPAR, but has
- * the same function.
- */
- val &= ~LATENCY_OPTIM;
- if (intel_crtc->config->lane_lat_optim_mask & BIT(lane))
- val |= LATENCY_OPTIM;
-
- I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val);
- }
-}
-
-static uint8_t
-bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
-{
- struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
- struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
- enum port port = dport->port;
- int lane;
- uint8_t mask;
-
- mask = 0;
- for (lane = 0; lane < 4; lane++) {
- u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane));
-
- if (val & LATENCY_OPTIM)
- mask |= BIT(lane);
- }
+ uint8_t mask = intel_crtc->config->lane_lat_optim_mask;
- return mask;
+ bxt_ddi_phy_set_lane_optim_mask(encoder, mask);
}
void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
@@ -2347,7 +2069,7 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder,
if (IS_BROXTON(dev_priv) && ret)
pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_calc_lane_lat_optim_mask(encoder,
- pipe_config);
+ pipe_config->lane_count);
return ret;
@@ -2438,7 +2160,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
- bool init_hdmi, init_dp;
+ bool init_hdmi, init_dp, init_lspcon = false;
int max_lanes;
if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) {
@@ -2470,6 +2192,19 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
dev_priv->vbt.ddi_port_info[port].supports_hdmi);
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
+
+ if (intel_bios_is_lspcon_present(dev_priv, port)) {
+ /*
+ * Lspcon device needs to be driven with DP connector
+ * with special detection sequence. So make sure DP
+ * is initialized before lspcon.
+ */
+ init_dp = true;
+ init_lspcon = true;
+ init_hdmi = false;
+ DRM_DEBUG_KMS("VBT says port %c has lspcon\n", port_name(port));
+ }
+
if (!init_dp && !init_hdmi) {
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
port_name(port));
@@ -2509,7 +2244,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
* configuration so that we use the proper lane count for our
* calculations.
*/
- if (IS_BROXTON(dev) && port == PORT_A) {
+ if (IS_BROXTON(dev_priv) && port == PORT_A) {
if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) {
DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n");
intel_dig_port->saved_port_bits |= DDI_A_4_LANES;
@@ -2520,6 +2255,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_dig_port->max_lanes = max_lanes;
intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
+ intel_encoder->port = port;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = 0;
@@ -2532,7 +2268,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
* On BXT A0/A1, sw needs to activate DDIA HPD logic and
* interrupts to check the external panel connection.
*/
- if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B)
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && port == PORT_B)
dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port;
else
dev_priv->hotplug.irq_port[port] = intel_dig_port;
@@ -2545,6 +2281,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
goto err;
}
+ if (init_lspcon) {
+ if (lspcon_init(intel_dig_port))
+ /* TODO: handle hdmi info frame part */
+ DRM_DEBUG_KMS("LSPCON init success on port %c\n",
+ port_name(port));
+ else
+ /*
+ * LSPCON init faied, but DP init was success, so
+ * lets try to drive as DP++ port.
+ */
+ DRM_ERROR("LSPCON init failed on port %c\n",
+ port_name(port));
+ }
+
return;
err:
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index 1b20e160bc1f..185e3bbc9ec9 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -28,20 +28,14 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv)
{
const struct intel_device_info *info = &dev_priv->info;
-#define PRINT_S(name) "%s"
-#define SEP_EMPTY
-#define PRINT_FLAG(name) info->name ? #name "," : ""
-#define SEP_COMMA ,
- DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
- DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
+ DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x",
info->gen,
dev_priv->drm.pdev->device,
- dev_priv->drm.pdev->revision,
- DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
-#undef PRINT_S
-#undef SEP_EMPTY
+ dev_priv->drm.pdev->revision);
+#define PRINT_FLAG(name) \
+ DRM_DEBUG_DRIVER("i915 device info: " #name ": %s", yesno(info->name))
+ DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
#undef PRINT_FLAG
-#undef SEP_COMMA
}
static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
@@ -288,12 +282,13 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
info->num_sprites[PIPE_A] = 2;
info->num_sprites[PIPE_B] = 2;
info->num_sprites[PIPE_C] = 1;
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
for_each_pipe(dev_priv, pipe)
info->num_sprites[pipe] = 2;
- else
+ } else if (INTEL_GEN(dev_priv) >= 5) {
for_each_pipe(dev_priv, pipe)
info->num_sprites[pipe] = 1;
+ }
if (i915.disable_display) {
DRM_INFO("Display disabled (module parameter)\n");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3cb70d73239b..cf5cff7b03b8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -37,7 +37,6 @@
#include "intel_frontbuffer.h"
#include <drm/i915_drm.h>
#include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
#include "intel_dsi.h"
#include "i915_trace.h"
#include <drm/drm_atomic.h>
@@ -116,8 +115,9 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
-static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state);
+static void skl_init_scalers(struct drm_i915_private *dev_priv,
+ struct intel_crtc *crtc,
+ struct intel_crtc_state *crtc_state);
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);
@@ -600,7 +600,7 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
* the given connectors.
*/
-static bool intel_PLL_is_valid(struct drm_device *dev,
+static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv,
const struct intel_limit *limit,
const struct dpll *clock)
{
@@ -613,12 +613,13 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
INTELPllInvalid("m1 out of range\n");
- if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
- !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
+ if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) &&
+ !IS_CHERRYVIEW(dev_priv) && !IS_BROXTON(dev_priv))
if (clock->m1 <= clock->m2)
INTELPllInvalid("m1 <= m2\n");
- if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
+ if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+ !IS_BROXTON(dev_priv)) {
if (clock->p < limit->p.min || limit->p.max < clock->p)
INTELPllInvalid("p out of range\n");
if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -698,7 +699,8 @@ i9xx_find_best_dpll(const struct intel_limit *limit,
int this_err;
i9xx_calc_dpll_params(refclk, &clock);
- if (!intel_PLL_is_valid(dev, limit,
+ if (!intel_PLL_is_valid(to_i915(dev),
+ limit,
&clock))
continue;
if (match_clock &&
@@ -753,7 +755,8 @@ pnv_find_best_dpll(const struct intel_limit *limit,
int this_err;
pnv_calc_dpll_params(refclk, &clock);
- if (!intel_PLL_is_valid(dev, limit,
+ if (!intel_PLL_is_valid(to_i915(dev),
+ limit,
&clock))
continue;
if (match_clock &&
@@ -813,7 +816,8 @@ g4x_find_best_dpll(const struct intel_limit *limit,
int this_err;
i9xx_calc_dpll_params(refclk, &clock);
- if (!intel_PLL_is_valid(dev, limit,
+ if (!intel_PLL_is_valid(to_i915(dev),
+ limit,
&clock))
continue;
@@ -845,7 +849,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
* For CHV ignore the error and consider only the P value.
* Prefer a bigger P value based on HW requirements.
*/
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(to_i915(dev))) {
*error_ppm = 0;
return calculated_clock->p > best_clock->p;
@@ -909,7 +913,8 @@ vlv_find_best_dpll(const struct intel_limit *limit,
vlv_calc_dpll_params(refclk, &clock);
- if (!intel_PLL_is_valid(dev, limit,
+ if (!intel_PLL_is_valid(to_i915(dev),
+ limit,
&clock))
continue;
@@ -977,7 +982,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
chv_calc_dpll_params(refclk, &clock);
- if (!intel_PLL_is_valid(dev, limit, &clock))
+ if (!intel_PLL_is_valid(to_i915(dev), limit, &clock))
continue;
if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
@@ -1003,10 +1008,8 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
target_clock, refclk, NULL, best_clock);
}
-bool intel_crtc_active(struct drm_crtc *crtc)
+bool intel_crtc_active(struct intel_crtc *crtc)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
/* Be paranoid as we can arrive here with only partial
* state retrieved from the hardware during setup.
*
@@ -1020,27 +1023,25 @@ bool intel_crtc_active(struct drm_crtc *crtc)
* crtc->state->active once we have proper CRTC states wired up
* for atomic.
*/
- return intel_crtc->active && crtc->primary->state->fb &&
- intel_crtc->config->base.adjusted_mode.crtc_clock;
+ return crtc->active && crtc->base.primary->state->fb &&
+ crtc->config->base.adjusted_mode.crtc_clock;
}
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
- return intel_crtc->config->cpu_transcoder;
+ return crtc->config->cpu_transcoder;
}
-static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
+static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
i915_reg_t reg = PIPEDSL(pipe);
u32 line1, line2;
u32 line_mask;
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
line_mask = DSL_LINEMASK_GEN2;
else
line_mask = DSL_LINEMASK_GEN3;
@@ -1070,12 +1071,11 @@ static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
*/
static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
enum pipe pipe = crtc->pipe;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
i915_reg_t reg = PIPECONF(cpu_transcoder);
/* Wait for the Pipe State to go off */
@@ -1085,7 +1085,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
WARN(1, "pipe_off wait timed out\n");
} else {
/* Wait for the display line to settle */
- if (wait_for(pipe_dsl_stopped(dev, pipe), 100))
+ if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
WARN(1, "pipe_off wait timed out\n");
}
}
@@ -1187,19 +1187,17 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
onoff(state), onoff(cur_state));
}
-void assert_panel_unlocked(struct drm_i915_private *dev_priv,
- enum pipe pipe)
+void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- struct drm_device *dev = &dev_priv->drm;
i915_reg_t pp_reg;
u32 val;
enum pipe panel_pipe = PIPE_A;
bool locked = true;
- if (WARN_ON(HAS_DDI(dev)))
+ if (WARN_ON(HAS_DDI(dev_priv)))
return;
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
u32 port_sel;
pp_reg = PP_CONTROL(0);
@@ -1209,7 +1207,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
panel_pipe = PIPE_B;
/* XXX: else fix for eDP */
- } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
/* presumably write lock depends on pipe, not port select */
pp_reg = PP_CONTROL(pipe);
panel_pipe = pipe;
@@ -1232,10 +1230,9 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
static void assert_cursor(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- struct drm_device *dev = &dev_priv->drm;
bool cur_state;
- if (IS_845G(dev) || IS_I865G(dev))
+ if (IS_845G(dev_priv) || IS_I865G(dev_priv))
cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
else
cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
@@ -1294,11 +1291,10 @@ static void assert_plane(struct drm_i915_private *dev_priv,
static void assert_planes_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_device *dev = &dev_priv->drm;
int i;
/* Primary planes are fixed to pipes on gen4+ */
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
u32 val = I915_READ(DSPCNTR(pipe));
I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
"plane %c assertion failure, should be disabled but not\n",
@@ -1320,29 +1316,28 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_device *dev = &dev_priv->drm;
int sprite;
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
for_each_sprite(dev_priv, 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) || IS_CHERRYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
for_each_sprite(dev_priv, pipe, sprite) {
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) {
+ } else if (INTEL_GEN(dev_priv) >= 7) {
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) {
+ } else if (INTEL_GEN(dev_priv) >= 5) {
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",
@@ -1596,12 +1591,12 @@ static void chv_enable_pll(struct intel_crtc *crtc,
}
}
-static int intel_num_dvo_pipes(struct drm_device *dev)
+static int intel_num_dvo_pipes(struct drm_i915_private *dev_priv)
{
struct intel_crtc *crtc;
int count = 0;
- for_each_intel_crtc(dev, crtc) {
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
count += crtc->base.state->active &&
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO);
}
@@ -1611,19 +1606,18 @@ static int intel_num_dvo_pipes(struct drm_device *dev)
static void i9xx_enable_pll(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
i915_reg_t reg = DPLL(crtc->pipe);
u32 dpll = crtc->config->dpll_hw_state.dpll;
assert_pipe_disabled(dev_priv, crtc->pipe);
/* PLL is protected by panel, make sure we can write it */
- if (IS_MOBILE(dev) && !IS_I830(dev))
+ if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
assert_panel_unlocked(dev_priv, crtc->pipe);
/* Enable DVO 2x clock on both PLLs if necessary */
- if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) {
+ if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev_priv) > 0) {
/*
* It appears to be important that we don't enable this
* for the current pipe before otherwise configuring the
@@ -1648,7 +1642,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
POSTING_READ(reg);
udelay(150);
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
I915_WRITE(DPLL_MD(crtc->pipe),
crtc->config->dpll_hw_state.dpll_md);
} else {
@@ -1683,14 +1677,13 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
*/
static void i9xx_disable_pll(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
/* Disable DVO 2x clock on both PLLs if necessary */
- if (IS_I830(dev) &&
+ if (IS_I830(dev_priv) &&
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO) &&
- !intel_num_dvo_pipes(dev)) {
+ !intel_num_dvo_pipes(dev_priv)) {
I915_WRITE(DPLL(PIPE_B),
I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
I915_WRITE(DPLL(PIPE_A),
@@ -1786,9 +1779,8 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_device *dev = &dev_priv->drm;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
i915_reg_t reg;
uint32_t val, pipeconf_val;
@@ -1799,7 +1791,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
assert_fdi_tx_enabled(dev_priv, pipe);
assert_fdi_rx_enabled(dev_priv, pipe);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
/* Workaround: Set the timing override bit before enabling the
* pch transcoder. */
reg = TRANS_CHICKEN2(pipe);
@@ -1877,7 +1869,6 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_device *dev = &dev_priv->drm;
i915_reg_t reg;
uint32_t val;
@@ -1898,7 +1889,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
50))
DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
/* Workaround: Clear the timing override chicken bit again. */
reg = TRANS_CHICKEN2(pipe);
val = I915_READ(reg);
@@ -1926,6 +1917,18 @@ void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
}
+enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+ WARN_ON(!crtc->config->has_pch_encoder);
+
+ if (HAS_PCH_LPT(dev_priv))
+ return TRANSCODER_A;
+ else
+ return (enum transcoder) crtc->pipe;
+}
+
/**
* intel_enable_pipe - enable a pipe, asserting requirements
* @crtc: crtc responsible for the pipe
@@ -1939,7 +1942,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe = crtc->pipe;
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
- enum pipe pch_transcoder;
i915_reg_t reg;
u32 val;
@@ -1949,11 +1951,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
assert_cursor_disabled(dev_priv, pipe);
assert_sprites_disabled(dev_priv, pipe);
- if (HAS_PCH_LPT(dev_priv))
- pch_transcoder = TRANSCODER_A;
- else
- pch_transcoder = pipe;
-
/*
* A pipe without a PLL won't actually be able to drive bits from
* a plane. On ILK+ the pipe PLLs are integrated, so we don't
@@ -1967,7 +1964,8 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
} else {
if (crtc->config->has_pch_encoder) {
/* if driving the PCH, we need FDI enabled */
- assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
+ assert_fdi_rx_pll_enabled(dev_priv,
+ (enum pipe) intel_crtc_pch_transcoder(crtc));
assert_fdi_tx_pll_enabled(dev_priv,
(enum pipe) cpu_transcoder);
}
@@ -2139,7 +2137,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
const struct drm_framebuffer *fb,
unsigned int rotation)
{
- if (intel_rotation_90_or_270(rotation)) {
+ if (drm_rotation_90_or_270(rotation)) {
*view = i915_ggtt_view_rotated;
view->params.rotated = to_intel_framebuffer(fb)->rot_info;
} else {
@@ -2191,7 +2189,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
- alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
+ alignment = intel_surf_alignment(dev_priv, fb->modifier);
intel_fill_fb_ggtt_view(&view, fb, rotation);
@@ -2260,7 +2258,7 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
unsigned int rotation)
{
- if (intel_rotation_90_or_270(rotation))
+ if (drm_rotation_90_or_270(rotation))
return to_intel_framebuffer(fb)->rotated[plane].pitch;
else
return fb->pitches[plane];
@@ -2296,7 +2294,7 @@ void intel_add_fb_offsets(int *x, int *y,
const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb);
unsigned int rotation = state->base.rotation;
- if (intel_rotation_90_or_270(rotation)) {
+ if (drm_rotation_90_or_270(rotation)) {
*x += intel_fb->rotated[plane].x;
*y += intel_fb->rotated[plane].y;
} else {
@@ -2352,15 +2350,15 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
WARN_ON(new_offset > old_offset);
- if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
+ if (fb->modifier != DRM_FORMAT_MOD_NONE) {
unsigned int tile_size, tile_width, tile_height;
unsigned int pitch_tiles;
tile_size = intel_tile_size(dev_priv);
intel_tile_dims(dev_priv, &tile_width, &tile_height,
- fb->modifier[plane], cpp);
+ fb->modifier, cpp);
- if (intel_rotation_90_or_270(rotation)) {
+ if (drm_rotation_90_or_270(rotation)) {
pitch_tiles = pitch / tile_height;
swap(tile_width, tile_height);
} else {
@@ -2401,7 +2399,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
unsigned int rotation,
u32 alignment)
{
- uint64_t fb_modifier = fb->modifier[plane];
+ uint64_t fb_modifier = fb->modifier;
unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
u32 offset, offset_aligned;
@@ -2416,7 +2414,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
intel_tile_dims(dev_priv, &tile_width, &tile_height,
fb_modifier, cpp);
- if (intel_rotation_90_or_270(rotation)) {
+ if (drm_rotation_90_or_270(rotation)) {
pitch_tiles = pitch / tile_height;
swap(tile_width, tile_height);
} else {
@@ -2460,7 +2458,7 @@ u32 intel_compute_tile_offset(int *x, int *y,
if (fb->pixel_format == DRM_FORMAT_NV12 && plane == 1)
alignment = 4096;
else
- alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+ alignment = intel_surf_alignment(dev_priv, fb->modifier);
return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
rotation, alignment);
@@ -2542,13 +2540,13 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
DRM_ROTATE_0, tile_size);
offset /= tile_size;
- if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
+ if (fb->modifier != DRM_FORMAT_MOD_NONE) {
unsigned int tile_width, tile_height;
unsigned int pitch_tiles;
struct drm_rect r;
intel_tile_dims(dev_priv, &tile_width, &tile_height,
- fb->modifier[i], cpp);
+ fb->modifier, cpp);
rot_info->plane[i].offset = offset;
rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
@@ -2707,7 +2705,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
mode_cmd.width = fb->width;
mode_cmd.height = fb->height;
mode_cmd.pitches[0] = fb->pitches[0];
- mode_cmd.modifier[0] = fb->modifier[0];
+ mode_cmd.modifier[0] = fb->modifier;
mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
@@ -2817,14 +2815,8 @@ valid_fb:
plane_state->crtc_w = fb->width;
plane_state->crtc_h = fb->height;
- intel_state->base.src.x1 = plane_state->src_x;
- intel_state->base.src.y1 = plane_state->src_y;
- intel_state->base.src.x2 = plane_state->src_x + plane_state->src_w;
- intel_state->base.src.y2 = plane_state->src_y + plane_state->src_h;
- intel_state->base.dst.x1 = plane_state->crtc_x;
- intel_state->base.dst.y1 = plane_state->crtc_y;
- intel_state->base.dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
- intel_state->base.dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
+ intel_state->base.src = drm_plane_state_src(plane_state);
+ intel_state->base.dst = drm_plane_state_dest(plane_state);
obj = intel_fb_obj(fb);
if (i915_gem_object_is_tiled(obj))
@@ -2843,7 +2835,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
{
int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
- switch (fb->modifier[plane]) {
+ switch (fb->modifier) {
case DRM_FORMAT_MOD_NONE:
case I915_FORMAT_MOD_X_TILED:
switch (cpp) {
@@ -2874,7 +2866,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
}
break;
default:
- MISSING_CASE(fb->modifier[plane]);
+ MISSING_CASE(fb->modifier);
}
return 2048;
@@ -2902,7 +2894,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
intel_add_fb_offsets(&x, &y, plane_state, 0);
offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
- alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
+ alignment = intel_surf_alignment(dev_priv, fb->modifier);
/*
* AUX surface offset is specified as the distance from the
@@ -2919,7 +2911,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
*
* TODO: linear and Y-tiled seem fine, Yf untested,
*/
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) {
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
while ((x + w) * cpp > fb->pitches[0]) {
@@ -2976,7 +2968,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
int ret;
/* Rotate src coordinates to match rotated GTT view */
- if (intel_rotation_90_or_270(rotation))
+ if (drm_rotation_90_or_270(rotation))
drm_rect_rotate(&plane_state->base.src,
fb->width << 16, fb->height << 16,
DRM_ROTATE_270);
@@ -3006,11 +2998,9 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- struct drm_device *dev = primary->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(primary->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int plane = intel_crtc->plane;
u32 linear_offset;
u32 dspcntr;
@@ -3023,7 +3013,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
dspcntr |= DISPLAY_PLANE_ENABLE;
- if (INTEL_INFO(dev)->gen < 4) {
+ if (INTEL_GEN(dev_priv) < 4) {
if (intel_crtc->pipe == PIPE_B)
dspcntr |= DISPPLANE_SEL_PIPE_B;
@@ -3034,7 +3024,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
((crtc_state->pipe_src_h - 1) << 16) |
(crtc_state->pipe_src_w - 1));
I915_WRITE(DSPPOS(plane), 0);
- } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
+ } else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) {
I915_WRITE(PRIMSIZE(plane),
((crtc_state->pipe_src_h - 1) << 16) |
(crtc_state->pipe_src_w - 1));
@@ -3069,28 +3059,34 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
}
if (INTEL_GEN(dev_priv) >= 4 &&
- fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ fb->modifier == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
- if (IS_G4X(dev))
+ if (rotation & DRM_ROTATE_180)
+ dspcntr |= DISPPLANE_ROTATE_180;
+
+ if (rotation & DRM_REFLECT_X)
+ dspcntr |= DISPPLANE_MIRROR;
+
+ if (IS_G4X(dev_priv))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
intel_add_fb_offsets(&x, &y, plane_state, 0);
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
intel_crtc->dspaddr_offset =
intel_compute_tile_offset(&x, &y, plane_state, 0);
- if (rotation == DRM_ROTATE_180) {
- dspcntr |= DISPPLANE_ROTATE_180;
-
- x += (crtc_state->pipe_src_w - 1);
- y += (crtc_state->pipe_src_h - 1);
+ if (rotation & DRM_ROTATE_180) {
+ x += crtc_state->pipe_src_w - 1;
+ y += crtc_state->pipe_src_h - 1;
+ } else if (rotation & DRM_REFLECT_X) {
+ x += crtc_state->pipe_src_w - 1;
}
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
- if (INTEL_INFO(dev)->gen < 4)
+ if (INTEL_GEN(dev_priv) < 4)
intel_crtc->dspaddr_offset = linear_offset;
intel_crtc->adjusted_x = x;
@@ -3099,14 +3095,17 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
I915_WRITE(reg, dspcntr);
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
I915_WRITE(DSPSURF(plane),
intel_fb_gtt_offset(fb, rotation) +
intel_crtc->dspaddr_offset);
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(DSPLINOFF(plane), linear_offset);
- } else
- I915_WRITE(DSPADDR(plane), i915_gem_object_ggtt_offset(obj, NULL) + linear_offset);
+ } else {
+ I915_WRITE(DSPADDR(plane),
+ intel_fb_gtt_offset(fb, rotation) +
+ intel_crtc->dspaddr_offset);
+ }
POSTING_READ(reg);
}
@@ -3145,7 +3144,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
dspcntr = DISPPLANE_GAMMA_ENABLE;
dspcntr |= DISPLAY_PLANE_ENABLE;
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
switch (fb->pixel_format) {
@@ -3171,10 +3170,13 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
BUG();
}
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
- if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
+ if (rotation & DRM_ROTATE_180)
+ dspcntr |= DISPPLANE_ROTATE_180;
+
+ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
intel_add_fb_offsets(&x, &y, plane_state, 0);
@@ -3182,13 +3184,11 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
intel_crtc->dspaddr_offset =
intel_compute_tile_offset(&x, &y, plane_state, 0);
- if (rotation == DRM_ROTATE_180) {
- dspcntr |= DISPPLANE_ROTATE_180;
-
- if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
- x += (crtc_state->pipe_src_w - 1);
- y += (crtc_state->pipe_src_h - 1);
- }
+ /* HSW+ does this automagically in hardware */
+ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) &&
+ rotation & DRM_ROTATE_180) {
+ x += crtc_state->pipe_src_w - 1;
+ y += crtc_state->pipe_src_h - 1;
}
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -3202,7 +3202,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSURF(plane),
intel_fb_gtt_offset(fb, rotation) +
intel_crtc->dspaddr_offset);
- if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
} else {
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
@@ -3277,12 +3277,12 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
* The stride is either expressed as a multiple of 64 bytes chunks for
* linear buffers or in number of tiles for tiled buffers.
*/
- if (intel_rotation_90_or_270(rotation)) {
+ if (drm_rotation_90_or_270(rotation)) {
int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
- stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp);
+ stride /= intel_tile_height(dev_priv, fb->modifier, cpp);
} else {
- stride /= intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+ stride /= intel_fb_stride_alignment(dev_priv, fb->modifier,
fb->pixel_format);
}
@@ -3378,7 +3378,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
- const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
int pipe = intel_crtc->pipe;
u32 plane_ctl;
unsigned int rotation = plane_state->base.rotation;
@@ -3399,7 +3398,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
PLANE_CTL_PIPE_CSC_ENABLE;
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
- plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
+ plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
plane_ctl |= skl_plane_ctl_rotation(rotation);
@@ -3414,9 +3413,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
intel_crtc->adjusted_x = src_x;
intel_crtc->adjusted_y = src_y;
- if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base))
- skl_write_plane_wm(intel_crtc, wm, 0);
-
I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x);
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
@@ -3451,13 +3447,6 @@ static void skylake_disable_primary_plane(struct drm_plane *primary,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- /*
- * We only populate skl_results on watermark updates, and if the
- * plane's visiblity isn't actually changing neither is its watermarks.
- */
- if (!crtc->primary->state->visible)
- skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0);
-
I915_WRITE(PLANE_CTL(pipe, 0), 0);
I915_WRITE(PLANE_SURF(pipe, 0), 0);
POSTING_READ(PLANE_SURF(pipe, 0));
@@ -3507,7 +3496,7 @@ __intel_display_resume(struct drm_device *dev,
int i, ret;
intel_modeset_setup_hw_state(dev);
- i915_redisable_vga(dev);
+ i915_redisable_vga(to_i915(dev));
if (!state)
return 0;
@@ -3585,7 +3574,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
return;
err:
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
}
void intel_finish_reset(struct drm_i915_private *dev_priv)
@@ -3604,8 +3593,6 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
dev_priv->modeset_restore_state = NULL;
- dev_priv->modeset_restore_state = NULL;
-
/* reset doesn't touch the display */
if (!gpu_reset_clobbers_display(dev_priv)) {
if (!state) {
@@ -3647,6 +3634,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
intel_hpd_init(dev_priv);
}
+ if (state)
+ drm_atomic_state_put(state);
drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
mutex_unlock(&dev->mode_config.mutex);
@@ -3684,8 +3673,7 @@ static bool intel_crtc_has_pending_flip(struct drm_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 = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc->base.state);
@@ -3710,12 +3698,12 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
(pipe_config->pipe_src_h - 1));
/* on skylake this is done by detaching scalers */
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
skl_detach_scalers(crtc);
if (pipe_config->pch_pfit.enabled)
skylake_pfit_enable(crtc);
- } else if (HAS_PCH_SPLIT(dev)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
if (pipe_config->pch_pfit.enabled)
ironlake_pfit_enable(crtc);
else if (old_crtc_state->pch_pfit.enabled)
@@ -3735,7 +3723,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
/* enable normal train */
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
- if (IS_IVYBRIDGE(dev)) {
+ if (IS_IVYBRIDGE(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_NONE_IVB;
temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
} else {
@@ -3746,7 +3734,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_NORMAL_CPT;
} else {
@@ -3760,7 +3748,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
udelay(1000);
/* IVB wants error correction enabled */
- if (IS_IVYBRIDGE(dev))
+ if (IS_IVYBRIDGE(dev_priv))
I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE |
FDI_FE_ERRC_ENABLE);
}
@@ -3904,7 +3892,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
} else {
@@ -3948,7 +3936,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE;
temp |= FDI_LINK_TRAIN_PATTERN_2;
- if (IS_GEN6(dev)) {
+ if (IS_GEN6(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
/* SNB-B */
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
@@ -3957,7 +3945,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
} else {
@@ -4211,7 +4199,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
udelay(100);
/* Ironlake workaround, disable clock pointer after downing FDI */
- if (HAS_PCH_IBX(dev))
+ if (HAS_PCH_IBX(dev_priv))
I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
/* still set train pattern 1 */
@@ -4223,7 +4211,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
} else {
@@ -4241,6 +4229,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
bool intel_has_pending_fb_unpin(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *crtc;
/* Note that we don't need to be called with mode_config.lock here
@@ -4255,7 +4244,7 @@ bool intel_has_pending_fb_unpin(struct drm_device *dev)
continue;
if (crtc->flip_work)
- intel_wait_for_vblank(dev, crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
return true;
}
@@ -4546,7 +4535,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
assert_pch_transcoder_disabled(dev_priv, pipe);
- if (IS_IVYBRIDGE(dev))
+ if (IS_IVYBRIDGE(dev_priv))
ivybridge_update_fdi_bc_bifurcation(intel_crtc);
/* Write the TU size bits before fdi link training, so that error
@@ -4559,7 +4548,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
/* We need to program the right clock selection before writing the pixel
* mutliplier into the DPLL. */
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
u32 sel;
temp = I915_READ(PCH_DPLL_SEL);
@@ -4589,7 +4578,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_fdi_normal_train(crtc);
/* For PCH DP, enable TRANS_DP_CTL */
- if (HAS_PCH_CPT(dev) && intel_crtc_has_dp_encoder(intel_crtc->config)) {
+ if (HAS_PCH_CPT(dev_priv) &&
+ intel_crtc_has_dp_encoder(intel_crtc->config)) {
const struct drm_display_mode *adjusted_mode =
&intel_crtc->config->base.adjusted_mode;
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
@@ -4668,7 +4658,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
to_intel_crtc(crtc_state->base.crtc);
int need_scaling;
- need_scaling = intel_rotation_90_or_270(rotation) ?
+ need_scaling = drm_rotation_90_or_270(rotation) ?
(src_h != dst_w || src_w != dst_h):
(src_w != dst_w || src_h != dst_h);
@@ -4729,13 +4719,8 @@ 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);
const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
- DRM_DEBUG_KMS("Updating scaler for [CRTC:%d:%s] scaler_user index %u.%u\n",
- intel_crtc->base.base.id, intel_crtc->base.name,
- intel_crtc->pipe, SKL_CRTC_INDEX);
-
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,
@@ -4756,7 +4741,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct intel_plane *intel_plane =
to_intel_plane(plane_state->base.plane);
struct drm_framebuffer *fb = plane_state->base.fb;
@@ -4764,10 +4748,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
bool force_detach = !fb || !plane_state->base.visible;
- DRM_DEBUG_KMS("Updating scaler for [PLANE:%d:%s] scaler_user index %u.%u\n",
- intel_plane->base.base.id, intel_plane->base.name,
- intel_crtc->pipe, drm_plane_index(&intel_plane->base));
-
ret = skl_update_scaler(crtc_state, force_detach,
drm_plane_index(&intel_plane->base),
&plane_state->scaler_id,
@@ -4859,7 +4839,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
* as some pre-programmed values are broken,
* e.g. x201.
*/
- if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+ if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv))
I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
PF_PIPE_SEL_IVB(pipe));
else
@@ -4884,7 +4864,7 @@ void hsw_enable_ips(struct intel_crtc *crtc)
*/
assert_plane_enabled(dev_priv, crtc->plane);
- if (IS_BROADWELL(dev)) {
+ if (IS_BROADWELL(dev_priv)) {
mutex_lock(&dev_priv->rps.hw_lock);
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000));
mutex_unlock(&dev_priv->rps.hw_lock);
@@ -4916,7 +4896,7 @@ void hsw_disable_ips(struct intel_crtc *crtc)
return;
assert_plane_enabled(dev_priv, crtc->plane);
- if (IS_BROADWELL(dev)) {
+ if (IS_BROADWELL(dev_priv)) {
mutex_lock(&dev_priv->rps.hw_lock);
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
mutex_unlock(&dev_priv->rps.hw_lock);
@@ -4931,7 +4911,7 @@ void hsw_disable_ips(struct intel_crtc *crtc)
}
/* We need to wait for a vblank before we can disable the plane. */
- intel_wait_for_vblank(dev, crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
}
static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
@@ -4985,7 +4965,7 @@ intel_post_enable_primary(struct drm_crtc *crtc)
* FIXME: Need to fix the logic to work when we turn off all planes
* but leave the pipe running.
*/
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
/* Underruns don't always raise interrupts, so check manually. */
@@ -5008,7 +4988,7 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
* FIXME: Need to fix the logic to work when we turn off all planes
* but leave the pipe running.
*/
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
/*
@@ -5040,10 +5020,10 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
* event which is after the vblank start event, so we need to have a
* wait-for-vblank between disabling the plane and the pipe.
*/
- if (HAS_GMCH_DISPLAY(dev)) {
+ if (HAS_GMCH_DISPLAY(dev_priv)) {
intel_set_memory_cxsr(dev_priv, false);
dev_priv->wm.vlv.cxsr = false;
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
}
}
@@ -5062,7 +5042,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
crtc->wm.cxsr_allowed = true;
if (pipe_config->update_wm_post && pipe_config->base.active)
- intel_update_watermarks(&crtc->base);
+ intel_update_watermarks(crtc);
if (old_pri_state) {
struct intel_plane_state *primary_state =
@@ -5091,6 +5071,8 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
struct drm_plane_state *old_pri_state =
drm_atomic_get_existing_plane_state(old_state, primary);
bool modeset = needs_modeset(&pipe_config->base);
+ struct intel_atomic_state *old_intel_state =
+ to_intel_atomic_state(old_state);
if (old_pri_state) {
struct intel_plane_state *primary_state =
@@ -5105,7 +5087,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
intel_pre_disable_primary(&crtc->base);
}
- if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev)) {
+ if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) {
crtc->wm.cxsr_allowed = false;
/*
@@ -5120,7 +5102,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
if (old_crtc_state->base.active) {
intel_set_memory_cxsr(dev_priv, false);
dev_priv->wm.vlv.cxsr = false;
- intel_wait_for_vblank(dev, crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
}
}
@@ -5133,7 +5115,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
*/
if (pipe_config->disable_lp_wm) {
ilk_disable_lp_wm(dev);
- intel_wait_for_vblank(dev, crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
}
/*
@@ -5158,9 +5140,10 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
* us to.
*/
if (dev_priv->display.initial_watermarks != NULL)
- dev_priv->display.initial_watermarks(pipe_config);
+ dev_priv->display.initial_watermarks(old_intel_state,
+ pipe_config);
else if (pipe_config->update_wm_pre)
- intel_update_watermarks(&crtc->base);
+ intel_update_watermarks(crtc);
}
static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -5314,6 +5297,8 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
+ struct intel_atomic_state *old_intel_state =
+ to_intel_atomic_state(old_state);
if (WARN_ON(intel_crtc->active))
return;
@@ -5372,7 +5357,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
intel_color_load_luts(&pipe_config->base);
if (dev_priv->display.initial_watermarks != NULL)
- dev_priv->display.initial_watermarks(intel_crtc->config);
+ dev_priv->display.initial_watermarks(old_intel_state, intel_crtc->config);
intel_enable_pipe(intel_crtc);
if (intel_crtc->config->has_pch_encoder)
@@ -5383,12 +5368,12 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
intel_encoders_enable(crtc, pipe_config, old_state);
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
cpt_verify_modeset(dev, intel_crtc->pipe);
/* Must wait for vblank to avoid spurious PCH FIFO underruns */
if (intel_crtc->config->has_pch_encoder)
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
}
@@ -5396,18 +5381,19 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
/* IPS only exists on ULT machines and is tied to pipe A. */
static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
{
- return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
+ return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
}
static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc = pipe_config->base.crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe, hsw_workaround_pipe;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+ struct intel_atomic_state *old_intel_state =
+ to_intel_atomic_state(old_state);
if (WARN_ON(intel_crtc->active))
return;
@@ -5462,7 +5448,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
if (!transcoder_is_dsi(cpu_transcoder))
intel_ddi_enable_pipe_clock(intel_crtc);
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
skylake_pfit_enable(intel_crtc);
else
ironlake_pfit_enable(intel_crtc);
@@ -5478,9 +5464,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
intel_ddi_enable_transcoder_func(crtc);
if (dev_priv->display.initial_watermarks != NULL)
- dev_priv->display.initial_watermarks(pipe_config);
+ dev_priv->display.initial_watermarks(old_intel_state,
+ pipe_config);
else
- intel_update_watermarks(crtc);
+ intel_update_watermarks(intel_crtc);
/* XXX: Do the pipe assertions at the right place for BXT DSI. */
if (!transcoder_is_dsi(cpu_transcoder))
@@ -5489,7 +5476,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
if (intel_crtc->config->has_pch_encoder)
lpt_pch_enable(crtc);
- if (intel_crtc->config->dp_encoder_is_mst)
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
intel_ddi_set_vc_payload_alloc(crtc, true);
assert_vblank_disabled(crtc);
@@ -5498,8 +5485,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
intel_encoders_enable(crtc, pipe_config, old_state);
if (intel_crtc->config->has_pch_encoder) {
- intel_wait_for_vblank(dev, pipe);
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
true);
@@ -5508,9 +5495,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
/* If we change the relative order between pipe/planes enabling, we need
* to change the workaround. */
hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
- if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
- intel_wait_for_vblank(dev, hsw_workaround_pipe);
- intel_wait_for_vblank(dev, hsw_workaround_pipe);
+ if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) {
+ intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
+ intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
}
}
@@ -5565,7 +5552,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
if (intel_crtc->config->has_pch_encoder) {
ironlake_disable_pch_transcoder(dev_priv, pipe);
- if (HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_CPT(dev_priv)) {
i915_reg_t reg;
u32 temp;
@@ -5594,8 +5581,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc = old_crtc_state->base.crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
@@ -5612,13 +5598,13 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
if (!transcoder_is_dsi(cpu_transcoder))
intel_disable_pipe(intel_crtc);
- if (intel_crtc->config->dp_encoder_is_mst)
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
intel_ddi_set_vc_payload_alloc(crtc, false);
if (!transcoder_is_dsi(cpu_transcoder))
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
skylake_scaler_disable(intel_crtc);
else
ironlake_pfit_disable(intel_crtc, false);
@@ -5699,13 +5685,13 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port)
enum intel_display_power_domain
intel_display_port_power_domain(struct intel_encoder *intel_encoder)
{
- struct drm_device *dev = intel_encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
struct intel_digital_port *intel_dig_port;
switch (intel_encoder->type) {
case INTEL_OUTPUT_UNKNOWN:
/* Only DDI platforms should ever use this output type */
- WARN_ON_ONCE(!HAS_DDI(dev));
+ WARN_ON_ONCE(!HAS_DDI(dev_priv));
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_HDMI:
case INTEL_OUTPUT_EDP:
@@ -5726,7 +5712,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder)
enum intel_display_power_domain
intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
{
- struct drm_device *dev = intel_encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
struct intel_digital_port *intel_dig_port;
switch (intel_encoder->type) {
@@ -5739,7 +5725,7 @@ intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
* what's the status of the given connectors, play safe and
* run the DP detection too.
*/
- WARN_ON_ONCE(!HAS_DDI(dev));
+ WARN_ON_ONCE(!HAS_DDI(dev_priv));
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_EDP:
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
@@ -5831,11 +5817,9 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
static int skl_calc_cdclk(int max_pixclk, int vco);
-static void intel_update_max_cdclk(struct drm_device *dev)
+static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
int max_cdclk, vco;
@@ -5857,9 +5841,9 @@ static void intel_update_max_cdclk(struct drm_device *dev)
max_cdclk = 308571;
dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
- } else if (IS_BROXTON(dev)) {
+ } else if (IS_BROXTON(dev_priv)) {
dev_priv->max_cdclk_freq = 624000;
- } else if (IS_BROADWELL(dev)) {
+ } else if (IS_BROADWELL(dev_priv)) {
/*
* FIXME with extra cooling we can allow
* 540 MHz for ULX and 675 Mhz for ULT.
@@ -5868,15 +5852,15 @@ static void intel_update_max_cdclk(struct drm_device *dev)
*/
if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
dev_priv->max_cdclk_freq = 450000;
- else if (IS_BDW_ULX(dev))
+ else if (IS_BDW_ULX(dev_priv))
dev_priv->max_cdclk_freq = 450000;
- else if (IS_BDW_ULT(dev))
+ else if (IS_BDW_ULT(dev_priv))
dev_priv->max_cdclk_freq = 540000;
else
dev_priv->max_cdclk_freq = 675000;
- } else if (IS_CHERRYVIEW(dev)) {
+ } else if (IS_CHERRYVIEW(dev_priv)) {
dev_priv->max_cdclk_freq = 320000;
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
dev_priv->max_cdclk_freq = 400000;
} else {
/* otherwise assume cdclk is fixed */
@@ -5892,11 +5876,9 @@ static void intel_update_max_cdclk(struct drm_device *dev)
dev_priv->max_dotclk_freq);
}
-static void intel_update_cdclk(struct drm_device *dev)
+static void intel_update_cdclk(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+ dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev_priv);
if (INTEL_GEN(dev_priv) >= 9)
DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
@@ -6057,14 +6039,14 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
return;
}
- intel_update_cdclk(&dev_priv->drm);
+ intel_update_cdclk(dev_priv);
}
static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
{
u32 cdctl, expected;
- intel_update_cdclk(&dev_priv->drm);
+ intel_update_cdclk(dev_priv);
if (dev_priv->cdclk_pll.vco == 0 ||
dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -6197,7 +6179,7 @@ void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
dev_priv->skl_preferred_vco_freq = vco;
if (changed)
- intel_update_max_cdclk(&dev_priv->drm);
+ intel_update_max_cdclk(dev_priv);
}
static void
@@ -6283,7 +6265,6 @@ static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
{
- struct drm_device *dev = &dev_priv->drm;
u32 freq_select, pcu_ack;
WARN_ON((cdclk == 24000) != (vco == 0));
@@ -6334,7 +6315,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
mutex_unlock(&dev_priv->rps.hw_lock);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
}
static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
@@ -6381,7 +6362,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
goto sanitize;
- intel_update_cdclk(&dev_priv->drm);
+ intel_update_cdclk(dev_priv);
/* Is PLL enabled and locked ? */
if (dev_priv->cdclk_pll.vco == 0 ||
dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -6415,7 +6396,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev);
u32 val, cmd;
- WARN_ON(dev_priv->display.get_display_clock_speed(dev)
+ WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
!= dev_priv->cdclk_freq);
if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
@@ -6472,7 +6453,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
mutex_unlock(&dev_priv->sb_lock);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
}
static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
@@ -6480,7 +6461,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = to_i915(dev);
u32 val, cmd;
- WARN_ON(dev_priv->display.get_display_clock_speed(dev)
+ WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
!= dev_priv->cdclk_freq);
switch (cdclk) {
@@ -6513,7 +6494,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
}
mutex_unlock(&dev_priv->rps.hw_lock);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
}
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
@@ -6676,7 +6657,7 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
*/
intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
cherryview_set_cdclk(dev, req_cdclk);
else
valleyview_set_cdclk(dev, req_cdclk);
@@ -6704,7 +6685,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
intel_set_pipe_timings(intel_crtc);
intel_set_pipe_src_size(intel_crtc);
- if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
+ if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
struct drm_i915_private *dev_priv = to_i915(dev);
I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
@@ -6719,7 +6700,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
chv_prepare_pll(intel_crtc, intel_crtc->config);
chv_enable_pll(intel_crtc, intel_crtc->config);
} else {
@@ -6733,7 +6714,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
intel_color_load_luts(&pipe_config->base);
- intel_update_watermarks(crtc);
+ intel_update_watermarks(intel_crtc);
intel_enable_pipe(intel_crtc);
assert_vblank_disabled(crtc);
@@ -6775,7 +6756,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
intel_crtc->active = true;
- if (!IS_GEN2(dev))
+ if (!IS_GEN2(dev_priv))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_encoders_pre_enable(crtc, pipe_config, old_state);
@@ -6786,7 +6767,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
intel_color_load_luts(&pipe_config->base);
- intel_update_watermarks(crtc);
+ intel_update_watermarks(intel_crtc);
intel_enable_pipe(intel_crtc);
assert_vblank_disabled(crtc);
@@ -6823,8 +6804,8 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
* On gen2 planes are double buffered but the pipe isn't, so we must
* wait for planes to fully turn off before disabling the pipe.
*/
- if (IS_GEN2(dev))
- intel_wait_for_vblank(dev, pipe);
+ if (IS_GEN2(dev_priv))
+ intel_wait_for_vblank(dev_priv, pipe);
intel_encoders_disable(crtc, old_crtc_state, old_state);
@@ -6838,9 +6819,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
intel_encoders_post_disable(crtc, old_crtc_state, old_state);
if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
chv_disable_pll(dev_priv, pipe);
- else if (IS_VALLEYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv))
vlv_disable_pll(dev_priv, pipe);
else
i9xx_disable_pll(intel_crtc);
@@ -6848,7 +6829,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
- if (!IS_GEN2(dev))
+ if (!IS_GEN2(dev_priv))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
}
@@ -6886,7 +6867,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
dev_priv->display.crtc_disable(crtc_state, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
crtc->base.id, crtc->name);
@@ -6902,7 +6883,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
encoder->base.crtc = NULL;
intel_fbc_disable(intel_crtc);
- intel_update_watermarks(crtc);
+ intel_update_watermarks(intel_crtc);
intel_disable_shared_dpll(intel_crtc);
domains = intel_crtc->enabled_power_domains;
@@ -7028,6 +7009,7 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
struct intel_crtc_state *pipe_config)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_atomic_state *state = pipe_config->base.state;
struct intel_crtc *other_crtc;
struct intel_crtc_state *other_crtc_state;
@@ -7040,7 +7022,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
return -EINVAL;
}
- if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
if (pipe_config->fdi_lanes > 2) {
DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
pipe_config->fdi_lanes);
@@ -7050,7 +7032,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
}
}
- if (INTEL_INFO(dev)->num_pipes == 2)
+ if (INTEL_INFO(dev_priv)->num_pipes == 2)
return 0;
/* Ivybridge 3 pipe is really complicated */
@@ -7061,7 +7043,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
if (pipe_config->fdi_lanes <= 2)
return 0;
- other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_C));
+ other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C);
other_crtc_state =
intel_atomic_get_crtc_state(state, other_crtc);
if (IS_ERR(other_crtc_state))
@@ -7080,7 +7062,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
return -EINVAL;
}
- other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_B));
+ other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B);
other_crtc_state =
intel_atomic_get_crtc_state(state, other_crtc);
if (IS_ERR(other_crtc_state))
@@ -7191,7 +7173,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int clock_limit = dev_priv->max_dotclk_freq;
- if (INTEL_INFO(dev)->gen < 4) {
+ if (INTEL_GEN(dev_priv) < 4) {
clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
/*
@@ -7225,11 +7207,11 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
/* Cantiga+ cannot handle modes with a hsync front porch of 0.
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
*/
- if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
+ if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
return -EINVAL;
- if (HAS_IPS(dev))
+ if (HAS_IPS(dev_priv))
hsw_compute_ips_config(crtc, pipe_config);
if (pipe_config->has_pch_encoder)
@@ -7238,10 +7220,9 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
return 0;
}
-static int skylake_get_display_clock_speed(struct drm_device *dev)
+static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- uint32_t cdctl;
+ u32 cdctl;
skl_dpll0_update(dev_priv);
@@ -7300,9 +7281,8 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
dev_priv->cdclk_pll.ref;
}
-static int broxton_get_display_clock_speed(struct drm_device *dev)
+static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
u32 divider;
int div, vco;
@@ -7335,9 +7315,8 @@ static int broxton_get_display_clock_speed(struct drm_device *dev)
return DIV_ROUND_CLOSEST(vco, div);
}
-static int broadwell_get_display_clock_speed(struct drm_device *dev)
+static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
@@ -7355,9 +7334,8 @@ static int broadwell_get_display_clock_speed(struct drm_device *dev)
return 675000;
}
-static int haswell_get_display_clock_speed(struct drm_device *dev)
+static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
@@ -7367,41 +7345,41 @@ static int haswell_get_display_clock_speed(struct drm_device *dev)
return 450000;
else if (freq == LCPLL_CLK_FREQ_450)
return 450000;
- else if (IS_HSW_ULT(dev))
+ else if (IS_HSW_ULT(dev_priv))
return 337500;
else
return 540000;
}
-static int valleyview_get_display_clock_speed(struct drm_device *dev)
+static int valleyview_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- return vlv_get_cck_clock_hpll(to_i915(dev), "cdclk",
+ return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
CCK_DISPLAY_CLOCK_CONTROL);
}
-static int ilk_get_display_clock_speed(struct drm_device *dev)
+static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 450000;
}
-static int i945_get_display_clock_speed(struct drm_device *dev)
+static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 400000;
}
-static int i915_get_display_clock_speed(struct drm_device *dev)
+static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 333333;
}
-static int i9xx_misc_get_display_clock_speed(struct drm_device *dev)
+static int i9xx_misc_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 200000;
}
-static int pnv_get_display_clock_speed(struct drm_device *dev)
+static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
@@ -7424,9 +7402,9 @@ static int pnv_get_display_clock_speed(struct drm_device *dev)
}
}
-static int i915gm_get_display_clock_speed(struct drm_device *dev)
+static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
@@ -7444,14 +7422,14 @@ static int i915gm_get_display_clock_speed(struct drm_device *dev)
}
}
-static int i865_get_display_clock_speed(struct drm_device *dev)
+static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 266667;
}
-static int i85x_get_display_clock_speed(struct drm_device *dev)
+static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
u16 hpllcc = 0;
/*
@@ -7487,14 +7465,13 @@ static int i85x_get_display_clock_speed(struct drm_device *dev)
return 0;
}
-static int i830_get_display_clock_speed(struct drm_device *dev)
+static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
return 133333;
}
-static unsigned int intel_hpll_vco(struct drm_device *dev)
+static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
static const unsigned int blb_vco[8] = {
[0] = 3200000,
[1] = 4000000,
@@ -7537,20 +7514,20 @@ static unsigned int intel_hpll_vco(struct drm_device *dev)
uint8_t tmp = 0;
/* FIXME other chipsets? */
- if (IS_GM45(dev))
+ if (IS_GM45(dev_priv))
vco_table = ctg_vco;
- else if (IS_G4X(dev))
+ else if (IS_G4X(dev_priv))
vco_table = elk_vco;
- else if (IS_CRESTLINE(dev))
+ else if (IS_CRESTLINE(dev_priv))
vco_table = cl_vco;
- else if (IS_PINEVIEW(dev))
+ else if (IS_PINEVIEW(dev_priv))
vco_table = pnv_vco;
- else if (IS_G33(dev))
+ else if (IS_G33(dev_priv))
vco_table = blb_vco;
else
return 0;
- tmp = I915_READ(IS_MOBILE(dev) ? HPLLVCO_MOBILE : HPLLVCO);
+ tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
vco = vco_table[tmp & 0x7];
if (vco == 0)
@@ -7561,10 +7538,10 @@ static unsigned int intel_hpll_vco(struct drm_device *dev)
return vco;
}
-static int gm45_get_display_clock_speed(struct drm_device *dev)
+static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+ struct pci_dev *pdev = dev_priv->drm.pdev;
+ unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
uint16_t tmp = 0;
pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7584,14 +7561,14 @@ static int gm45_get_display_clock_speed(struct drm_device *dev)
}
}
-static int i965gm_get_display_clock_speed(struct drm_device *dev)
+static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
static const uint8_t div_3200[] = { 16, 10, 8 };
static const uint8_t div_4000[] = { 20, 12, 10 };
static const uint8_t div_5333[] = { 24, 16, 14 };
const uint8_t *div_table;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+ unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
uint16_t tmp = 0;
pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7622,15 +7599,15 @@ fail:
return 200000;
}
-static int g33_get_display_clock_speed(struct drm_device *dev)
+static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev->pdev;
+ struct pci_dev *pdev = dev_priv->drm.pdev;
static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 };
static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
const uint8_t *div_table;
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+ unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
uint16_t tmp = 0;
pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7719,10 +7696,10 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct dpll *reduced_clock)
{
- struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 fp, fp2 = 0;
- if (IS_PINEVIEW(dev)) {
+ if (IS_PINEVIEW(dev_priv)) {
fp = pnv_dpll_compute_fp(&crtc_state->dpll);
if (reduced_clock)
fp2 = pnv_dpll_compute_fp(reduced_clock);
@@ -7790,12 +7767,11 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n,
struct intel_link_m_n *m2_n2)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
int pipe = crtc->pipe;
enum transcoder transcoder = crtc->config->cpu_transcoder;
- if (INTEL_INFO(dev)->gen >= 5) {
+ if (INTEL_GEN(dev_priv) >= 5) {
I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
@@ -7804,8 +7780,8 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
* for gen < 8) and if DRRS is supported (to make sure the
* registers are not unnecessarily accessed).
*/
- if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
- crtc->config->has_drrs) {
+ if (m2_n2 && (IS_CHERRYVIEW(dev_priv) ||
+ INTEL_GEN(dev_priv) < 8) && crtc->config->has_drrs) {
I915_WRITE(PIPE_DATA_M2(transcoder),
TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
@@ -8092,11 +8068,10 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
* in cases where we need the PLL enabled even when @pipe is not going to
* be enabled.
*/
-int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
+int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll)
{
- struct intel_crtc *crtc =
- to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
struct intel_crtc_state *pipe_config;
pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
@@ -8107,7 +8082,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
pipe_config->pixel_multiplier = 1;
pipe_config->dpll = *dpll;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
chv_compute_dpll(crtc, pipe_config);
chv_prepare_pll(crtc, pipe_config);
chv_enable_pll(crtc, pipe_config);
@@ -8130,20 +8105,19 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
* Disable the PLL for @pipe. To be used in cases where we need
* the PLL enabled even when @pipe is not going to be enabled.
*/
-void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
+void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- if (IS_CHERRYVIEW(dev))
- chv_disable_pll(to_i915(dev), pipe);
+ if (IS_CHERRYVIEW(dev_priv))
+ chv_disable_pll(dev_priv, pipe);
else
- vlv_disable_pll(to_i915(dev), pipe);
+ vlv_disable_pll(dev_priv, pipe);
}
static void i9xx_compute_dpll(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct dpll *reduced_clock)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dpll;
struct dpll *clock = &crtc_state->dpll;
@@ -8156,7 +8130,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
else
dpll |= DPLLB_MODE_DAC_SERIAL;
- if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+ if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv)) {
dpll |= (crtc_state->pixel_multiplier - 1)
<< SDVO_MULTIPLIER_SHIFT_HIRES;
}
@@ -8169,11 +8143,11 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
dpll |= DPLL_SDVO_HIGH_SPEED;
/* compute bitmask from p1 value */
- if (IS_PINEVIEW(dev))
+ if (IS_PINEVIEW(dev_priv))
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
else {
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
- if (IS_G4X(dev) && reduced_clock)
+ if (IS_G4X(dev_priv) && reduced_clock)
dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
}
switch (clock->p2) {
@@ -8190,7 +8164,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
break;
}
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
if (crtc_state->sdvo_tv_clock)
@@ -8204,7 +8178,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
dpll |= DPLL_VCO_ENABLE;
crtc_state->dpll_hw_state.dpll = dpll;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
u32 dpll_md = (crtc_state->pixel_multiplier - 1)
<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
crtc_state->dpll_hw_state.dpll_md = dpll_md;
@@ -8235,7 +8209,8 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
dpll |= PLL_P2_DIVIDE_BY_4;
}
- if (!IS_I830(dev) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
+ if (!IS_I830(dev_priv) &&
+ intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
dpll |= DPLL_DVO_2X_MODE;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
@@ -8250,8 +8225,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
{
- struct drm_device *dev = intel_crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
enum pipe pipe = intel_crtc->pipe;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
@@ -8277,7 +8251,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
vsyncshift += adjusted_mode->crtc_htotal;
}
- if (INTEL_INFO(dev)->gen > 3)
+ if (INTEL_GEN(dev_priv) > 3)
I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift);
I915_WRITE(HTOTAL(cpu_transcoder),
@@ -8304,7 +8278,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
* programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is
* documented on the DDI_FUNC_CTL register description, EDP Input Select
* bits. */
- if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP &&
+ if (IS_HASWELL(dev_priv) && cpu_transcoder == TRANSCODER_EDP &&
(pipe == PIPE_B || pipe == PIPE_C))
I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
@@ -8400,8 +8374,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
{
- struct drm_device *dev = intel_crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
uint32_t pipeconf;
pipeconf = 0;
@@ -8414,7 +8387,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
pipeconf |= PIPECONF_DOUBLE_WIDE;
/* only g4x and later have fancy bpc/dither controls */
- if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv)) {
/* Bspec claims that we can't use dithering for 30bpp pipes. */
if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
pipeconf |= PIPECONF_DITHER_EN |
@@ -8436,7 +8410,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
}
}
- if (HAS_PIPE_CXSR(dev)) {
+ if (HAS_PIPE_CXSR(dev_priv)) {
if (intel_crtc->lowfreq_avail) {
DRM_DEBUG_KMS("enabling CxSR downclocking\n");
pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
@@ -8446,7 +8420,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
}
if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
- if (INTEL_INFO(dev)->gen < 4 ||
+ if (INTEL_GEN(dev_priv) < 4 ||
intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_SDVO))
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
else
@@ -8454,7 +8428,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
} else
pipeconf |= PIPECONF_PROGRESSIVE;
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc->config->limited_color_range)
pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
@@ -8654,11 +8628,11 @@ static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
static void i9xx_get_pfit_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
uint32_t tmp;
- if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
+ if (INTEL_GEN(dev_priv) <= 3 &&
+ (IS_I830(dev_priv) || !IS_MOBILE(dev_priv)))
return;
tmp = I915_READ(PFIT_CONTROL);
@@ -8666,7 +8640,7 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
return;
/* Check whether the pfit is attached to our pipe. */
- if (INTEL_INFO(dev)->gen < 4) {
+ if (INTEL_GEN(dev_priv) < 4) {
if (crtc->pipe != PIPE_B)
return;
} else {
@@ -8730,10 +8704,10 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
fb = &intel_fb->base;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
if (val & DISPPLANE_TILED) {
plane_config->tiling = I915_TILING_X;
- fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+ fb->modifier = I915_FORMAT_MOD_X_TILED;
}
}
@@ -8742,7 +8716,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
fb->pixel_format = fourcc;
fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
if (plane_config->tiling)
offset = I915_READ(DSPTILEOFF(plane));
else
@@ -8762,7 +8736,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
aligned_height = intel_fb_align_height(dev, fb->height,
fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier);
plane_config->size = fb->pitches[0] * aligned_height;
@@ -8811,8 +8785,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum intel_display_power_domain power_domain;
uint32_t tmp;
bool ret;
@@ -8830,7 +8803,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
goto out;
- if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv)) {
switch (tmp & PIPECONF_BPC_MASK) {
case PIPECONF_6BPC:
pipe_config->pipe_bpp = 18;
@@ -8846,11 +8820,11 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
}
}
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
(tmp & PIPECONF_COLOR_RANGE_SELECT))
pipe_config->limited_color_range = true;
- if (INTEL_INFO(dev)->gen < 4)
+ if (INTEL_GEN(dev_priv) < 4)
pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
intel_get_pipe_timings(crtc, pipe_config);
@@ -8858,9 +8832,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
i9xx_get_pfit_config(crtc, pipe_config);
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
/* No way to read it out on pipes B and C */
- if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A)
+ if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A)
tmp = dev_priv->chv_dpll_md[crtc->pipe];
else
tmp = I915_READ(DPLL_MD(crtc->pipe));
@@ -8868,7 +8842,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
>> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
pipe_config->dpll_hw_state.dpll_md = tmp;
- } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+ } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
+ IS_G33(dev_priv)) {
tmp = I915_READ(DPLL(crtc->pipe));
pipe_config->pixel_multiplier =
((tmp & SDVO_MULTIPLIER_MASK)
@@ -8880,13 +8855,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
pipe_config->pixel_multiplier = 1;
}
pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
- if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+ if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
/*
* DPLL_DVO_2X_MODE must be enabled for both DPLLs
* on 830. Filter it out here so that we don't
* report errors due to that.
*/
- if (IS_I830(dev))
+ if (IS_I830(dev_priv))
pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
@@ -8898,9 +8873,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
DPLL_PORTB_READY_MASK);
}
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
chv_crtc_clock_get(crtc, pipe_config);
- else if (IS_VALLEYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv))
vlv_crtc_clock_get(crtc, pipe_config);
else
i9xx_crtc_clock_get(crtc, pipe_config);
@@ -8951,7 +8926,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
}
}
- if (HAS_PCH_IBX(dev)) {
+ if (HAS_PCH_IBX(dev_priv)) {
has_ck505 = dev_priv->vbt.display_clock_mode;
can_ssc = has_ck505;
} else {
@@ -9199,7 +9174,8 @@ 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(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n"))
+ if (WARN(HAS_PCH_LPT_LP(dev_priv) &&
+ with_fdi, "LP PCH doesn't have FDI\n"))
with_fdi = false;
mutex_lock(&dev_priv->sb_lock);
@@ -9222,7 +9198,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread,
}
}
- reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
+ reg = HAS_PCH_LPT_LP(dev_priv) ? 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);
@@ -9238,7 +9214,7 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
mutex_lock(&dev_priv->sb_lock);
- reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
+ reg = HAS_PCH_LPT_LP(dev_priv) ? 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);
@@ -9346,9 +9322,11 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
*/
void intel_init_pch_refclk(struct drm_device *dev)
{
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
ironlake_init_pch_refclk(dev);
- else if (HAS_PCH_LPT(dev))
+ else if (HAS_PCH_LPT(dev_priv))
lpt_init_pch_refclk(dev);
}
@@ -9477,7 +9455,7 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
if ((intel_panel_use_ssc(dev_priv) &&
dev_priv->vbt.lvds_ssc_freq == 100000) ||
- (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
+ (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev)))
factor = 25;
} else if (crtc_state->sdvo_tv_clock)
factor = 20;
@@ -9651,11 +9629,10 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n,
struct intel_link_m_n *m2_n2)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- if (INTEL_INFO(dev)->gen >= 5) {
+ if (INTEL_GEN(dev_priv) >= 5) {
m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder));
m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder));
m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
@@ -9667,7 +9644,7 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
* gen < 8) and if DRRS is supported (to make sure the
* registers are not unnecessarily read).
*/
- if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
+ if (m2_n2 && INTEL_GEN(dev_priv) < 8 &&
crtc->config->has_drrs) {
m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
m2_n2->link_n = I915_READ(PIPE_LINK_N2(transcoder));
@@ -9771,17 +9748,17 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
tiling = val & PLANE_CTL_TILED_MASK;
switch (tiling) {
case PLANE_CTL_TILED_LINEAR:
- fb->modifier[0] = DRM_FORMAT_MOD_NONE;
+ fb->modifier = DRM_FORMAT_MOD_NONE;
break;
case PLANE_CTL_TILED_X:
plane_config->tiling = I915_TILING_X;
- fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+ fb->modifier = I915_FORMAT_MOD_X_TILED;
break;
case PLANE_CTL_TILED_Y:
- fb->modifier[0] = I915_FORMAT_MOD_Y_TILED;
+ fb->modifier = I915_FORMAT_MOD_Y_TILED;
break;
case PLANE_CTL_TILED_YF:
- fb->modifier[0] = I915_FORMAT_MOD_Yf_TILED;
+ fb->modifier = I915_FORMAT_MOD_Yf_TILED;
break;
default:
MISSING_CASE(tiling);
@@ -9798,13 +9775,13 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
fb->width = ((val >> 0) & 0x1fff) + 1;
val = I915_READ(PLANE_STRIDE(pipe, 0));
- stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+ stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier,
fb->pixel_format);
fb->pitches[0] = (val & 0x3ff) * stride_mult;
aligned_height = intel_fb_align_height(dev, fb->height,
fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier);
plane_config->size = fb->pitches[0] * aligned_height;
@@ -9837,7 +9814,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
/* We currently do not free assignements of panel fitters on
* ivb/hsw (since we don't use the higher upscaling modes which
* differentiates them) so just WARN about this case for now. */
- if (IS_GEN7(dev)) {
+ if (IS_GEN7(dev_priv)) {
WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
PF_PIPE_SEL_IVB(crtc->pipe));
}
@@ -9869,10 +9846,10 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
fb = &intel_fb->base;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
if (val & DISPPLANE_TILED) {
plane_config->tiling = I915_TILING_X;
- fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+ fb->modifier = I915_FORMAT_MOD_X_TILED;
}
}
@@ -9882,7 +9859,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
base = I915_READ(DSPSURF(pipe)) & 0xfffff000;
- if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
offset = I915_READ(DSPOFFSET(pipe));
} else {
if (plane_config->tiling)
@@ -9901,7 +9878,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
aligned_height = intel_fb_align_height(dev, fb->height,
fb->pixel_format,
- fb->modifier[0]);
+ fb->modifier);
plane_config->size = fb->pitches[0] * aligned_height;
@@ -10026,7 +10003,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
"CPU PWM1 enabled\n");
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev_priv))
I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
"CPU PWM2 enabled\n");
I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
@@ -10046,9 +10023,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
-
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev_priv))
return I915_READ(D_COMP_HSW);
else
return I915_READ(D_COMP_BDW);
@@ -10056,9 +10031,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
{
- struct drm_device *dev = &dev_priv->drm;
-
- if (IS_HASWELL(dev)) {
+ if (IS_HASWELL(dev_priv)) {
mutex_lock(&dev_priv->rps.hw_lock);
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
val))
@@ -10173,7 +10146,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
}
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
- intel_update_cdclk(&dev_priv->drm);
+ intel_update_cdclk(dev_priv);
}
/*
@@ -10206,7 +10179,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
DRM_DEBUG_KMS("Enabling package C8+\n");
- if (HAS_PCH_LPT_LP(dev)) {
+ if (HAS_PCH_LPT_LP(dev_priv)) {
val = I915_READ(SOUTH_DSPCLK_GATE_D);
val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -10226,7 +10199,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
hsw_restore_lcpll(dev_priv);
lpt_init_pch_refclk(dev);
- if (HAS_PCH_LPT_LP(dev)) {
+ if (HAS_PCH_LPT_LP(dev_priv)) {
val = I915_READ(SOUTH_DSPCLK_GATE_D);
val |= PCH_LP_PARTITION_LEVEL_DISABLE;
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -10376,7 +10349,7 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
WARN(cdclk != dev_priv->cdclk_freq,
"cdclk requested %d kHz but got %d kHz\n",
@@ -10663,8 +10636,7 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll;
enum port port;
uint32_t tmp;
@@ -10673,9 +10645,9 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
skylake_get_ddi_pll(dev_priv, port, pipe_config);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
bxt_get_ddi_pll(dev_priv, port, pipe_config);
else
haswell_get_ddi_pll(dev_priv, port, pipe_config);
@@ -10691,7 +10663,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
* DDI E. So just check whether this pipe is wired to DDI E and whether
* the PCH transcoder is on.
*/
- if (INTEL_INFO(dev)->gen < 9 &&
+ if (INTEL_GEN(dev_priv) < 9 &&
(port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
pipe_config->has_pch_encoder = true;
@@ -10706,8 +10678,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
static bool haswell_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum intel_display_power_domain power_domain;
unsigned long power_domain_mask;
bool active;
@@ -10740,11 +10711,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
pipe_config->gamma_mode =
I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
- if (INTEL_INFO(dev)->gen >= 9) {
- skl_init_scalers(dev, crtc, pipe_config);
- }
+ if (INTEL_GEN(dev_priv) >= 9) {
+ skl_init_scalers(dev_priv, crtc, pipe_config);
- if (INTEL_INFO(dev)->gen >= 9) {
pipe_config->scaler_state.scaler_id = -1;
pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
}
@@ -10752,13 +10721,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
power_domain_mask |= BIT(power_domain);
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
skylake_get_pfit_config(crtc, pipe_config);
else
ironlake_get_pfit_config(crtc, pipe_config);
}
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev_priv))
pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
(I915_READ(IPS_CTL) & IPS_ENABLE);
@@ -10846,13 +10815,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
int pipe = intel_crtc->pipe;
uint32_t cntl = 0;
- if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc))
- skl_write_cursor_wm(intel_crtc, wm);
-
if (plane_state && plane_state->base.visible) {
cntl = MCURSOR_GAMMA_ENABLE;
switch (plane_state->base.crtc_w) {
@@ -10871,10 +10836,10 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
}
cntl |= pipe << 28; /* Connect to correct pipe */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
cntl |= CURSOR_PIPE_CSC_ENABLE;
- if (plane_state->base.rotation == DRM_ROTATE_180)
+ if (plane_state->base.rotation & DRM_ROTATE_180)
cntl |= CURSOR_ROTATE_180;
}
@@ -10919,8 +10884,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
pos |= y << CURSOR_Y_SHIFT;
/* ILK+ do this automagically */
- if (HAS_GMCH_DISPLAY(dev) &&
- plane_state->base.rotation == DRM_ROTATE_180) {
+ if (HAS_GMCH_DISPLAY(dev_priv) &&
+ plane_state->base.rotation & DRM_ROTATE_180) {
base += (plane_state->base.crtc_h *
plane_state->base.crtc_w - 1) * 4;
}
@@ -10928,13 +10893,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
I915_WRITE(CURPOS(pipe), pos);
- if (IS_845G(dev) || IS_I865G(dev))
+ if (IS_845G(dev_priv) || IS_I865G(dev_priv))
i845_update_cursor(crtc, base, plane_state);
else
i9xx_update_cursor(crtc, base, plane_state);
}
-static bool cursor_size_ok(struct drm_device *dev,
+static bool cursor_size_ok(struct drm_i915_private *dev_priv,
uint32_t width, uint32_t height)
{
if (width == 0 || height == 0)
@@ -10946,11 +10911,11 @@ static bool cursor_size_ok(struct drm_device *dev,
* the precision of the register. Everything else requires
* square cursors, limited to a few power-of-two sizes.
*/
- if (IS_845G(dev) || IS_I865G(dev)) {
+ if (IS_845G(dev_priv) || IS_I865G(dev_priv)) {
if ((width & 63) != 0)
return false;
- if (width > (IS_845G(dev) ? 64 : 512))
+ if (width > (IS_845G(dev_priv) ? 64 : 512))
return false;
if (height > 1023)
@@ -10959,7 +10924,7 @@ static bool cursor_size_ok(struct drm_device *dev,
switch (width | height) {
case 256:
case 128:
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
return false;
case 64:
break;
@@ -11053,7 +11018,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
fb = intel_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb))
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return fb;
}
@@ -11138,6 +11103,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_crtc *crtc = NULL;
struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_framebuffer *fb;
struct drm_mode_config *config = &dev->mode_config;
struct drm_atomic_state *state = NULL, *restore_state = NULL;
@@ -11290,13 +11256,18 @@ found:
old->restore_state = restore_state;
/* let the connector get through one full cycle before testing */
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
return true;
fail:
- drm_atomic_state_free(state);
- drm_atomic_state_free(restore_state);
- restore_state = state = NULL;
+ if (state) {
+ drm_atomic_state_put(state);
+ state = NULL;
+ }
+ if (restore_state) {
+ drm_atomic_state_put(restore_state);
+ restore_state = NULL;
+ }
if (ret == -EDEADLK) {
drm_modeset_backoff(ctx);
@@ -11324,10 +11295,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
return;
ret = drm_atomic_commit(state);
- if (ret) {
+ if (ret)
DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret);
- drm_atomic_state_free(state);
- }
+ drm_atomic_state_put(state);
}
static int i9xx_pll_refclk(struct drm_device *dev,
@@ -11338,9 +11308,9 @@ static int i9xx_pll_refclk(struct drm_device *dev,
if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
return dev_priv->vbt.lvds_ssc_freq;
- else if (HAS_PCH_SPLIT(dev))
+ else if (HAS_PCH_SPLIT(dev_priv))
return 120000;
- else if (!IS_GEN2(dev))
+ else if (!IS_GEN2(dev_priv))
return 96000;
else
return 48000;
@@ -11365,7 +11335,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
fp = pipe_config->dpll_hw_state.fp1;
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
- if (IS_PINEVIEW(dev)) {
+ if (IS_PINEVIEW(dev_priv)) {
clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
} else {
@@ -11373,8 +11343,8 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
}
- if (!IS_GEN2(dev)) {
- if (IS_PINEVIEW(dev))
+ if (!IS_GEN2(dev_priv)) {
+ if (IS_PINEVIEW(dev_priv))
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
else
@@ -11396,12 +11366,12 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
return;
}
- if (IS_PINEVIEW(dev))
+ if (IS_PINEVIEW(dev_priv))
port_clock = pnv_calc_dpll_params(refclk, &clock);
else
port_clock = i9xx_calc_dpll_params(refclk, &clock);
} else {
- u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
+ u32 lvds = IS_I830(dev_priv) ? 0 : I915_READ(LVDS);
bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
if (is_lvds) {
@@ -11602,7 +11572,7 @@ static bool __pageflip_finished_cs(struct intel_crtc *crtc,
* really needed there. But since ctg has the registers,
* include it in the check anyway.
*/
- if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev))
+ if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
return true;
/*
@@ -11665,8 +11635,7 @@ static bool pageflip_finished(struct intel_crtc *crtc,
void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
{
struct drm_device *dev = &dev_priv->drm;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
struct intel_flip_work *work;
unsigned long flags;
@@ -11679,12 +11648,12 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
* lost pageflips) so needs the full irqsave spinlocks.
*/
spin_lock_irqsave(&dev->event_lock, flags);
- work = intel_crtc->flip_work;
+ work = crtc->flip_work;
if (work != NULL &&
!is_mmio_work(work) &&
- pageflip_finished(intel_crtc, work))
- page_flip_completed(intel_crtc);
+ pageflip_finished(crtc, work))
+ page_flip_completed(crtc);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
@@ -11692,8 +11661,7 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
{
struct drm_device *dev = &dev_priv->drm;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
struct intel_flip_work *work;
unsigned long flags;
@@ -11706,12 +11674,12 @@ void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
* lost pageflips) so needs the full irqsave spinlocks.
*/
spin_lock_irqsave(&dev->event_lock, flags);
- work = intel_crtc->flip_work;
+ work = crtc->flip_work;
if (work != NULL &&
is_mmio_work(work) &&
- pageflip_finished(intel_crtc, work))
- page_flip_completed(intel_crtc);
+ pageflip_finished(crtc, work))
+ page_flip_completed(crtc);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
@@ -11816,7 +11784,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
intel_ring_emit(ring, fb->pitches[0]);
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset |
- intel_fb_modifier_to_tiling(fb->modifier[0]));
+ intel_fb_modifier_to_tiling(fb->modifier));
/* XXX Enabling the panel-fitter across page-flip is so far
* untested on non-native modes, so ignore it for now.
@@ -11849,7 +11817,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
intel_ring_emit(ring, fb->pitches[0] |
- intel_fb_modifier_to_tiling(fb->modifier[0]));
+ intel_fb_modifier_to_tiling(fb->modifier));
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
/* Contrary to the suggestions in the documentation,
@@ -11872,6 +11840,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
struct drm_i915_gem_request *req,
uint32_t flags)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_ring *ring = req->ring;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
uint32_t plane_bit = 0;
@@ -11900,7 +11869,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
* 48bits addresses, and we need a NOOP for the batch size to
* stay even.
*/
- if (IS_GEN8(dev))
+ if (IS_GEN8(dev_priv))
len += 2;
}
@@ -11937,7 +11906,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
DERRMR_PIPEB_PRI_FLIP_DONE |
DERRMR_PIPEC_PRI_FLIP_DONE));
- if (IS_GEN8(dev))
+ if (IS_GEN8(dev_priv))
intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT);
else
@@ -11946,7 +11915,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit_reg(ring, DERRMR);
intel_ring_emit(ring,
i915_ggtt_offset(req->engine->scratch) + 256);
- if (IS_GEN8(dev)) {
+ if (IS_GEN8(dev_priv)) {
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
}
@@ -11954,7 +11923,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
intel_ring_emit(ring, fb->pitches[0] |
- intel_fb_modifier_to_tiling(fb->modifier[0]));
+ intel_fb_modifier_to_tiling(fb->modifier));
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
intel_ring_emit(ring, (MI_NOOP));
@@ -11964,8 +11933,6 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
static bool use_mmio_flip(struct intel_engine_cs *engine,
struct drm_i915_gem_object *obj)
{
- struct reservation_object *resv;
-
/*
* This is not being used for older platforms, because
* non-availability of flip done interrupt forces us to use
@@ -11987,12 +11954,7 @@ static bool use_mmio_flip(struct intel_engine_cs *engine,
else if (i915.enable_execlists)
return true;
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (resv && !reservation_object_test_signaled_rcu(resv, false))
- return true;
-
- return engine != i915_gem_active_get_engine(&obj->last_write,
- &obj->base.dev->struct_mutex);
+ return engine != i915_gem_object_last_write_engine(obj);
}
static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
@@ -12007,7 +11969,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
ctl = I915_READ(PLANE_CTL(pipe, 0));
ctl &= ~PLANE_CTL_TILED_MASK;
- switch (fb->modifier[0]) {
+ switch (fb->modifier) {
case DRM_FORMAT_MOD_NONE:
break;
case I915_FORMAT_MOD_X_TILED:
@@ -12020,7 +11982,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
ctl |= PLANE_CTL_TILED_YF;
break;
default:
- MISSING_CASE(fb->modifier[0]);
+ MISSING_CASE(fb->modifier);
}
/*
@@ -12045,7 +12007,7 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
dspcntr = I915_READ(reg);
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
else
dspcntr &= ~DISPPLANE_TILED;
@@ -12065,17 +12027,8 @@ static void intel_mmio_flip_work_func(struct work_struct *w)
struct intel_framebuffer *intel_fb =
to_intel_framebuffer(crtc->base.primary->fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
- struct reservation_object *resv;
- if (work->flip_queued_req)
- WARN_ON(i915_wait_request(work->flip_queued_req,
- 0, NULL, NO_WAITBOOST));
-
- /* For framebuffer backed by dmabuf, wait for fence */
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (resv)
- WARN_ON(reservation_object_wait_timeout_rcu(resv, false, false,
- MAX_SCHEDULE_TIMEOUT) < 0);
+ WARN_ON(i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT, NULL) < 0);
intel_pipe_update_start(crtc);
@@ -12138,8 +12091,7 @@ static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv,
void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
{
struct drm_device *dev = &dev_priv->drm;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
struct intel_flip_work *work;
WARN_ON(!in_interrupt());
@@ -12148,19 +12100,19 @@ void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
return;
spin_lock(&dev->event_lock);
- work = intel_crtc->flip_work;
+ work = crtc->flip_work;
if (work != NULL && !is_mmio_work(work) &&
- __pageflip_stall_check_cs(dev_priv, intel_crtc, work)) {
+ __pageflip_stall_check_cs(dev_priv, crtc, work)) {
WARN_ONCE(1,
"Kicking stuck page flip: queued at %d, now %d\n",
- work->flip_queued_vblank, intel_crtc_get_vblank_counter(intel_crtc));
- page_flip_completed(intel_crtc);
+ work->flip_queued_vblank, intel_crtc_get_vblank_counter(crtc));
+ page_flip_completed(crtc);
work = NULL;
}
if (work != NULL && !is_mmio_work(work) &&
- intel_crtc_get_vblank_counter(intel_crtc) - work->flip_queued_vblank > 1)
+ intel_crtc_get_vblank_counter(crtc) - work->flip_queued_vblank > 1)
intel_queue_rps_boost_for_request(work->flip_queued_req);
spin_unlock(&dev->event_lock);
}
@@ -12200,7 +12152,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
* TILEOFF/LINOFF registers can't be changed via MI display flips.
* Note that pitch changes could also affect these register.
*/
- if (INTEL_INFO(dev)->gen > 3 &&
+ if (INTEL_GEN(dev_priv) > 3 &&
(fb->offsets[0] != crtc->primary->fb->offsets[0] ||
fb->pitches[0] != crtc->primary->fb->pitches[0]))
return -EINVAL;
@@ -12265,23 +12217,22 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
atomic_inc(&intel_crtc->unpin_work_count);
- if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+ if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
- engine = &dev_priv->engine[BCS];
- if (fb->modifier[0] != old_fb->modifier[0])
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ engine = dev_priv->engine[BCS];
+ if (fb->modifier != old_fb->modifier)
/* vlv: DISPLAY_FLIP fails to change tiling */
engine = NULL;
- } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
- engine = &dev_priv->engine[BCS];
- } else if (INTEL_INFO(dev)->gen >= 7) {
- engine = i915_gem_active_get_engine(&obj->last_write,
- &obj->base.dev->struct_mutex);
+ } else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
+ engine = dev_priv->engine[BCS];
+ } else if (INTEL_GEN(dev_priv) >= 7) {
+ engine = i915_gem_object_last_write_engine(obj);
if (engine == NULL || engine->id != RCS)
- engine = &dev_priv->engine[BCS];
+ engine = dev_priv->engine[BCS];
} else {
- engine = &dev_priv->engine[RCS];
+ engine = dev_priv->engine[RCS];
}
mmio_flip = use_mmio_flip(engine, obj);
@@ -12309,10 +12260,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (mmio_flip) {
INIT_WORK(&work->mmio_work, intel_mmio_flip_work_func);
-
- work->flip_queued_req = i915_gem_active_get(&obj->last_write,
- &obj->base.dev->struct_mutex);
- schedule_work(&work->mmio_work);
+ queue_work(system_unbound_wq, &work->mmio_work);
} else {
request = i915_gem_request_alloc(engine, engine->last_context);
if (IS_ERR(request)) {
@@ -12335,6 +12283,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
i915_add_request_no_flush(request);
}
+ i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
i915_gem_track_fb(intel_fb_obj(old_fb), obj,
to_intel_plane(primary)->frontbuffer_bit);
mutex_unlock(&dev->struct_mutex);
@@ -12358,7 +12307,7 @@ cleanup:
crtc->primary->fb = old_fb;
update_state_fb(crtc->primary);
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
drm_framebuffer_unreference(work->old_fb);
spin_lock_irq(&dev->event_lock);
@@ -12396,8 +12345,7 @@ retry:
goto retry;
}
- if (ret)
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
if (ret == 0 && event) {
spin_lock_irq(&dev->event_lock);
@@ -12432,7 +12380,7 @@ static bool intel_wm_need_update(struct drm_plane *plane,
if (!cur->base.fb || !new->base.fb)
return false;
- if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
+ if (cur->base.fb->modifier != new->base.fb->modifier ||
cur->base.rotation != new->base.rotation ||
drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
@@ -12471,7 +12419,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
struct drm_framebuffer *fb = plane_state->fb;
int ret;
- if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
+ if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
ret = skl_update_scaler_plane(
to_intel_crtc_state(crtc_state),
to_intel_plane_state(plane_state));
@@ -12538,7 +12486,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
/* Pre-gen9 platforms need two-step watermark updates */
if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
- INTEL_INFO(dev)->gen < 9 && dev_priv->display.optimize_watermarks)
+ INTEL_GEN(dev_priv) < 9 && dev_priv->display.optimize_watermarks)
to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
if (visible || was_visible)
@@ -12550,7 +12498,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
* cstate->update_wm was already set above, so this flag will
* take effect when we commit and program watermarks.
*/
- if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) &&
+ if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
needs_scaling(to_intel_plane_state(plane_state)) &&
!needs_scaling(old_plane_state))
pipe_config->disable_lp_wm = true;
@@ -12643,7 +12591,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
* old state and the new state. We can program these
* immediately.
*/
- ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
+ ret = dev_priv->display.compute_intermediate_wm(dev,
intel_crtc,
pipe_config);
if (ret) {
@@ -12655,7 +12603,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
pipe_config->wm.ilk.intermediate = pipe_config->wm.ilk.optimal;
}
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
if (mode_changed)
ret = skl_update_scaler_crtc(pipe_config);
@@ -12726,15 +12674,16 @@ static int
compute_baseline_pipe_bpp(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct drm_atomic_state *state;
struct drm_connector *connector;
struct drm_connector_state *connector_state;
int bpp, i;
- if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
+ if ((IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv)))
bpp = 10*3;
- else if (INTEL_INFO(dev)->gen >= 5)
+ else if (INTEL_GEN(dev_priv) >= 5)
bpp = 12*3;
else
bpp = 8*3;
@@ -12767,73 +12716,81 @@ static void intel_dump_crtc_timings(const struct drm_display_mode *mode)
mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags);
}
+static inline void
+intel_dump_m_n_config(struct intel_crtc_state *pipe_config, char *id,
+ unsigned int lane_count, struct intel_link_m_n *m_n)
+{
+ DRM_DEBUG_KMS("%s: lanes: %i; gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+ id, lane_count,
+ m_n->gmch_m, m_n->gmch_n,
+ m_n->link_m, m_n->link_n, m_n->tu);
+}
+
static void intel_dump_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config,
const char *context)
{
struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_plane *plane;
struct intel_plane *intel_plane;
struct intel_plane_state *state;
struct drm_framebuffer *fb;
- DRM_DEBUG_KMS("[CRTC:%d:%s]%s config %p for pipe %c\n",
- crtc->base.base.id, crtc->base.name,
- context, pipe_config, pipe_name(crtc->pipe));
+ DRM_DEBUG_KMS("[CRTC:%d:%s]%s\n",
+ crtc->base.base.id, crtc->base.name, context);
- DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder));
- DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
+ DRM_DEBUG_KMS("cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n",
+ transcoder_name(pipe_config->cpu_transcoder),
pipe_config->pipe_bpp, pipe_config->dither);
- DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
- pipe_config->has_pch_encoder,
- pipe_config->fdi_lanes,
- 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, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
- intel_crtc_has_dp_encoder(pipe_config),
- 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, lanes: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
- intel_crtc_has_dp_encoder(pipe_config),
- 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,
- pipe_config->dp_m2_n2.link_n,
- pipe_config->dp_m2_n2.tu);
+
+ if (pipe_config->has_pch_encoder)
+ intel_dump_m_n_config(pipe_config, "fdi",
+ pipe_config->fdi_lanes,
+ &pipe_config->fdi_m_n);
+
+ if (intel_crtc_has_dp_encoder(pipe_config)) {
+ intel_dump_m_n_config(pipe_config, "dp m_n",
+ pipe_config->lane_count, &pipe_config->dp_m_n);
+ if (pipe_config->has_drrs)
+ intel_dump_m_n_config(pipe_config, "dp m2_n2",
+ pipe_config->lane_count,
+ &pipe_config->dp_m2_n2);
+ }
DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
- pipe_config->has_audio,
- pipe_config->has_infoframe);
+ pipe_config->has_audio, pipe_config->has_infoframe);
DRM_DEBUG_KMS("requested mode:\n");
drm_mode_debug_printmodeline(&pipe_config->base.mode);
DRM_DEBUG_KMS("adjusted mode:\n");
drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
- DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
- DRM_DEBUG_KMS("pipe src size: %dx%d\n",
+ DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d\n",
+ pipe_config->port_clock,
pipe_config->pipe_src_w, pipe_config->pipe_src_h);
- DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
- crtc->num_scalers,
- pipe_config->scaler_state.scaler_users,
- pipe_config->scaler_state.scaler_id);
- DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
- pipe_config->gmch_pfit.control,
- pipe_config->gmch_pfit.pgm_ratios,
- pipe_config->gmch_pfit.lvds_border_bits);
- DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
- pipe_config->pch_pfit.pos,
- pipe_config->pch_pfit.size,
- pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
- DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
- DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
-
- if (IS_BROXTON(dev)) {
+
+ if (INTEL_GEN(dev_priv) >= 9)
+ DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
+ crtc->num_scalers,
+ pipe_config->scaler_state.scaler_users,
+ pipe_config->scaler_state.scaler_id);
+
+ if (HAS_GMCH_DISPLAY(dev_priv))
+ DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
+ pipe_config->gmch_pfit.control,
+ pipe_config->gmch_pfit.pgm_ratios,
+ pipe_config->gmch_pfit.lvds_border_bits);
+ else
+ DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
+ pipe_config->pch_pfit.pos,
+ pipe_config->pch_pfit.size,
+ enableddisabled(pipe_config->pch_pfit.enabled));
+
+ DRM_DEBUG_KMS("ips: %i, double wide: %i\n",
+ pipe_config->ips_enabled, pipe_config->double_wide);
+
+ if (IS_BROXTON(dev_priv)) {
DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
"pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
"pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
@@ -12848,13 +12805,13 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->dpll_hw_state.pll9,
pipe_config->dpll_hw_state.pll10,
pipe_config->dpll_hw_state.pcsdw12);
- } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
DRM_DEBUG_KMS("dpll_hw_state: "
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
pipe_config->dpll_hw_state.ctrl1,
pipe_config->dpll_hw_state.cfgcr1,
pipe_config->dpll_hw_state.cfgcr2);
- } else if (HAS_DDI(dev)) {
+ } else if (HAS_DDI(dev_priv)) {
DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
pipe_config->dpll_hw_state.wrpll,
pipe_config->dpll_hw_state.spll);
@@ -12869,7 +12826,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
DRM_DEBUG_KMS("planes on this crtc\n");
list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
- char *format_name;
+ struct drm_format_name_buf format_name;
intel_plane = to_intel_plane(plane);
if (intel_plane->pipe != crtc->pipe)
continue;
@@ -12882,23 +12839,20 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
continue;
}
- format_name = drm_get_format_name(fb->pixel_format);
-
- DRM_DEBUG_KMS("[PLANE:%d:%s] enabled",
- plane->base.id, plane->name);
- DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s",
- fb->base.id, fb->width, fb->height, format_name);
- DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
- state->scaler_id,
- state->base.src.x1 >> 16,
- state->base.src.y1 >> 16,
- drm_rect_width(&state->base.src) >> 16,
- drm_rect_height(&state->base.src) >> 16,
- state->base.dst.x1, state->base.dst.y1,
- drm_rect_width(&state->base.dst),
- drm_rect_height(&state->base.dst));
-
- kfree(format_name);
+ DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d, fb = %ux%u format = %s\n",
+ plane->base.id, plane->name,
+ fb->base.id, fb->width, fb->height,
+ drm_get_format_name(fb->pixel_format, &format_name));
+ if (INTEL_GEN(dev_priv) >= 9)
+ DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
+ state->scaler_id,
+ state->base.src.x1 >> 16,
+ state->base.src.y1 >> 16,
+ drm_rect_width(&state->base.src) >> 16,
+ drm_rect_height(&state->base.src) >> 16,
+ state->base.dst.x1, state->base.dst.y1,
+ drm_rect_width(&state->base.dst),
+ drm_rect_height(&state->base.dst));
}
}
@@ -12932,7 +12886,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
switch (encoder->type) {
unsigned int port_mask;
case INTEL_OUTPUT_UNKNOWN:
- if (WARN_ON(!HAS_DDI(dev)))
+ if (WARN_ON(!HAS_DDI(to_i915(dev))))
break;
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_HDMI:
@@ -13213,7 +13167,7 @@ intel_compare_link_m_n(const struct intel_link_m_n *m_n,
}
static bool
-intel_pipe_config_compare(struct drm_device *dev,
+intel_pipe_config_compare(struct drm_i915_private *dev_priv,
struct intel_crtc_state *current_config,
struct intel_crtc_state *pipe_config,
bool adjust)
@@ -13337,7 +13291,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(lane_count);
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
- if (INTEL_INFO(dev)->gen < 8) {
+ if (INTEL_GEN(dev_priv) < 8) {
PIPE_CONF_CHECK_M_N(dp_m_n);
if (current_config->has_drrs)
@@ -13363,8 +13317,8 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(pixel_multiplier);
PIPE_CONF_CHECK_I(has_hdmi_sink);
- if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
- IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
PIPE_CONF_CHECK_I(limited_color_range);
PIPE_CONF_CHECK_I(has_infoframe);
@@ -13386,7 +13340,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_X(gmch_pfit.control);
/* pfit ratios are autocomputed by the hw on gen4+ */
- if (INTEL_INFO(dev)->gen < 4)
+ if (INTEL_GEN(dev_priv) < 4)
PIPE_CONF_CHECK_X(gmch_pfit.pgm_ratios);
PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
@@ -13404,7 +13358,7 @@ intel_pipe_config_compare(struct drm_device *dev,
}
/* BDW+ don't expose a synchronous way to read the state */
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev_priv))
PIPE_CONF_CHECK_I(ips_enabled);
PIPE_CONF_CHECK_I(double_wide);
@@ -13423,7 +13377,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_X(dsi_pll.ctrl);
PIPE_CONF_CHECK_X(dsi_pll.div);
- if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
+ if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)
PIPE_CONF_CHECK_I(pipe_bpp);
PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock);
@@ -13461,33 +13415,67 @@ static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,
static void verify_wm_state(struct drm_crtc *crtc,
struct drm_crtc_state *new_state)
{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct skl_ddb_allocation hw_ddb, *sw_ddb;
- struct skl_ddb_entry *hw_entry, *sw_entry;
+ struct skl_pipe_wm hw_wm, *sw_wm;
+ struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
+ struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const enum pipe pipe = intel_crtc->pipe;
- int plane;
+ int plane, level, max_level = ilk_wm_max_level(dev_priv);
- if (INTEL_INFO(dev)->gen < 9 || !new_state->active)
+ if (INTEL_GEN(dev_priv) < 9 || !new_state->active)
return;
+ skl_pipe_wm_get_hw_state(crtc, &hw_wm);
+ sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
+
skl_ddb_get_hw_state(dev_priv, &hw_ddb);
sw_ddb = &dev_priv->wm.skl_hw.ddb;
/* planes */
- for_each_plane(dev_priv, pipe, plane) {
- hw_entry = &hw_ddb.plane[pipe][plane];
- sw_entry = &sw_ddb->plane[pipe][plane];
+ for_each_universal_plane(dev_priv, pipe, plane) {
+ hw_plane_wm = &hw_wm.planes[plane];
+ sw_plane_wm = &sw_wm->planes[plane];
+
+ /* Watermarks */
+ for (level = 0; level <= max_level; level++) {
+ if (skl_wm_level_equals(&hw_plane_wm->wm[level],
+ &sw_plane_wm->wm[level]))
+ continue;
- if (skl_ddb_entry_equal(hw_entry, sw_entry))
- continue;
+ DRM_ERROR("mismatch in WM pipe %c plane %d level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ pipe_name(pipe), plane + 1, level,
+ sw_plane_wm->wm[level].plane_en,
+ sw_plane_wm->wm[level].plane_res_b,
+ sw_plane_wm->wm[level].plane_res_l,
+ hw_plane_wm->wm[level].plane_en,
+ hw_plane_wm->wm[level].plane_res_b,
+ hw_plane_wm->wm[level].plane_res_l);
+ }
- DRM_ERROR("mismatch in DDB state pipe %c plane %d "
- "(expected (%u,%u), found (%u,%u))\n",
- pipe_name(pipe), plane + 1,
- sw_entry->start, sw_entry->end,
- hw_entry->start, hw_entry->end);
+ if (!skl_wm_level_equals(&hw_plane_wm->trans_wm,
+ &sw_plane_wm->trans_wm)) {
+ DRM_ERROR("mismatch in trans WM pipe %c plane %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ pipe_name(pipe), plane + 1,
+ sw_plane_wm->trans_wm.plane_en,
+ sw_plane_wm->trans_wm.plane_res_b,
+ sw_plane_wm->trans_wm.plane_res_l,
+ hw_plane_wm->trans_wm.plane_en,
+ hw_plane_wm->trans_wm.plane_res_b,
+ hw_plane_wm->trans_wm.plane_res_l);
+ }
+
+ /* DDB */
+ hw_ddb_entry = &hw_ddb.plane[pipe][plane];
+ sw_ddb_entry = &sw_ddb->plane[pipe][plane];
+
+ if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
+ DRM_ERROR("mismatch in DDB state pipe %c plane %d (expected (%u,%u), found (%u,%u))\n",
+ pipe_name(pipe), plane + 1,
+ sw_ddb_entry->start, sw_ddb_entry->end,
+ hw_ddb_entry->start, hw_ddb_entry->end);
+ }
}
/*
@@ -13497,25 +13485,60 @@ static void verify_wm_state(struct drm_crtc *crtc,
* once the plane becomes visible, we can skip this check
*/
if (intel_crtc->cursor_addr) {
- hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
- sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
+ hw_plane_wm = &hw_wm.planes[PLANE_CURSOR];
+ sw_plane_wm = &sw_wm->planes[PLANE_CURSOR];
- if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
- DRM_ERROR("mismatch in DDB state pipe %c cursor "
- "(expected (%u,%u), found (%u,%u))\n",
+ /* Watermarks */
+ for (level = 0; level <= max_level; level++) {
+ if (skl_wm_level_equals(&hw_plane_wm->wm[level],
+ &sw_plane_wm->wm[level]))
+ continue;
+
+ DRM_ERROR("mismatch in WM pipe %c cursor level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ pipe_name(pipe), level,
+ sw_plane_wm->wm[level].plane_en,
+ sw_plane_wm->wm[level].plane_res_b,
+ sw_plane_wm->wm[level].plane_res_l,
+ hw_plane_wm->wm[level].plane_en,
+ hw_plane_wm->wm[level].plane_res_b,
+ hw_plane_wm->wm[level].plane_res_l);
+ }
+
+ if (!skl_wm_level_equals(&hw_plane_wm->trans_wm,
+ &sw_plane_wm->trans_wm)) {
+ DRM_ERROR("mismatch in trans WM pipe %c cursor (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ pipe_name(pipe),
+ sw_plane_wm->trans_wm.plane_en,
+ sw_plane_wm->trans_wm.plane_res_b,
+ sw_plane_wm->trans_wm.plane_res_l,
+ hw_plane_wm->trans_wm.plane_en,
+ hw_plane_wm->trans_wm.plane_res_b,
+ hw_plane_wm->trans_wm.plane_res_l);
+ }
+
+ /* DDB */
+ hw_ddb_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
+ sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
+
+ if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
+ DRM_ERROR("mismatch in DDB state pipe %c cursor (expected (%u,%u), found (%u,%u))\n",
pipe_name(pipe),
- sw_entry->start, sw_entry->end,
- hw_entry->start, hw_entry->end);
+ sw_ddb_entry->start, sw_ddb_entry->end,
+ hw_ddb_entry->start, hw_ddb_entry->end);
}
}
}
static void
-verify_connector_state(struct drm_device *dev, struct drm_crtc *crtc)
+verify_connector_state(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
{
struct drm_connector *connector;
+ struct drm_connector_state *old_conn_state;
+ int i;
- drm_for_each_connector(connector, dev) {
+ for_each_connector_in_state(state, connector, old_conn_state, i) {
struct drm_encoder *encoder = connector->encoder;
struct drm_connector_state *state = connector->state;
@@ -13630,7 +13653,7 @@ verify_crtc_state(struct drm_crtc *crtc,
intel_pipe_config_sanity_check(dev_priv, pipe_config);
sw_config = to_intel_crtc_state(crtc->state);
- if (!intel_pipe_config_compare(dev, sw_config,
+ if (!intel_pipe_config_compare(dev_priv, sw_config,
pipe_config, false)) {
I915_STATE_WARN(1, "pipe state doesn't match!\n");
intel_dump_pipe_config(intel_crtc, pipe_config,
@@ -13723,15 +13746,16 @@ verify_shared_dpll_state(struct drm_device *dev, struct drm_crtc *crtc,
static void
intel_modeset_verify_crtc(struct drm_crtc *crtc,
- struct drm_crtc_state *old_state,
- struct drm_crtc_state *new_state)
+ struct drm_atomic_state *state,
+ struct drm_crtc_state *old_state,
+ struct drm_crtc_state *new_state)
{
if (!needs_modeset(new_state) &&
!to_intel_crtc_state(new_state)->update_pipe)
return;
verify_wm_state(crtc, new_state);
- verify_connector_state(crtc->dev, crtc);
+ verify_connector_state(crtc->dev, state, crtc);
verify_crtc_state(crtc, old_state, new_state);
verify_shared_dpll_state(crtc->dev, crtc, old_state, new_state);
}
@@ -13747,16 +13771,17 @@ verify_disabled_dpll_state(struct drm_device *dev)
}
static void
-intel_modeset_verify_disabled(struct drm_device *dev)
+intel_modeset_verify_disabled(struct drm_device *dev,
+ struct drm_atomic_state *state)
{
verify_encoder_state(dev);
- verify_connector_state(dev, NULL);
+ verify_connector_state(dev, state, NULL);
verify_disabled_dpll_state(dev);
}
static void update_scanline_offset(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
/*
* The scanline counter increments at the leading edge of hsync.
@@ -13776,7 +13801,7 @@ static void update_scanline_offset(struct intel_crtc *crtc)
* there's an extra 1 line difference. So we need to add two instead of
* one to the value.
*/
- if (IS_GEN2(dev)) {
+ if (IS_GEN2(dev_priv)) {
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
int vtotal;
@@ -13785,7 +13810,7 @@ static void update_scanline_offset(struct intel_crtc *crtc)
vtotal /= 2;
crtc->scanline_offset = vtotal - 1;
- } else if (HAS_DDI(dev) &&
+ } else if (HAS_DDI(dev_priv) &&
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
crtc->scanline_offset = 2;
} else
@@ -13970,8 +13995,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n",
intel_state->cdclk, intel_state->dev_cdclk);
- } else
+ } else {
to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
+ }
intel_modeset_clear_plls(state);
@@ -14048,7 +14074,7 @@ static int intel_atomic_check(struct drm_device *dev,
}
if (i915.fastboot &&
- intel_pipe_config_compare(dev,
+ intel_pipe_config_compare(dev_priv,
to_intel_crtc_state(crtc->state),
pipe_config, true)) {
crtc_state->mode_changed = false;
@@ -14072,8 +14098,9 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
return ret;
- } else
- intel_state->cdclk = dev_priv->cdclk_freq;
+ } else {
+ intel_state->cdclk = dev_priv->atomic_cdclk_freq;
+ }
ret = drm_atomic_helper_check_planes(dev, state);
if (ret)
@@ -14084,13 +14111,10 @@ static int intel_atomic_check(struct drm_device *dev,
}
static int intel_atomic_prepare_commit(struct drm_device *dev,
- struct drm_atomic_state *state,
- bool nonblock)
+ struct drm_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_plane_state *plane_state;
struct drm_crtc_state *crtc_state;
- struct drm_plane *plane;
struct drm_crtc *crtc;
int i, ret;
@@ -14113,28 +14137,6 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
ret = drm_atomic_helper_prepare_planes(dev, state);
mutex_unlock(&dev->struct_mutex);
- if (!ret && !nonblock) {
- for_each_plane_in_state(state, plane, plane_state, i) {
- struct intel_plane_state *intel_plane_state =
- to_intel_plane_state(plane_state);
-
- if (!intel_plane_state->wait_req)
- continue;
-
- ret = i915_wait_request(intel_plane_state->wait_req,
- I915_WAIT_INTERRUPTIBLE,
- NULL, NULL);
- if (ret) {
- /* Any hang should be swallowed by the wait */
- WARN_ON(ret == -EIO);
- mutex_lock(&dev->struct_mutex);
- drm_atomic_helper_cleanup_planes(dev, state);
- mutex_unlock(&dev->struct_mutex);
- break;
- }
- }
- }
-
return ret;
}
@@ -14160,22 +14162,24 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev,
return;
for_each_pipe(dev_priv, pipe) {
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
if (!((1 << pipe) & crtc_mask))
continue;
- ret = drm_crtc_vblank_get(crtc);
+ ret = drm_crtc_vblank_get(&crtc->base);
if (WARN_ON(ret != 0)) {
crtc_mask &= ~(1 << pipe);
continue;
}
- last_vblank_count[pipe] = drm_crtc_vblank_count(crtc);
+ last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base);
}
for_each_pipe(dev_priv, pipe) {
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+ pipe);
long lret;
if (!((1 << pipe) & crtc_mask))
@@ -14183,12 +14187,12 @@ static void intel_atomic_wait_for_vblanks(struct drm_device *dev,
lret = wait_event_timeout(dev->vblank[pipe].queue,
last_vblank_count[pipe] !=
- drm_crtc_vblank_count(crtc),
+ drm_crtc_vblank_count(&crtc->base),
msecs_to_jiffies(50));
WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe));
- drm_crtc_vblank_put(crtc);
+ drm_crtc_vblank_put(&crtc->base);
}
}
@@ -14262,16 +14266,23 @@ static void intel_update_crtcs(struct drm_atomic_state *state,
static void skl_update_crtcs(struct drm_atomic_state *state,
unsigned int *crtc_vblank_mask)
{
- struct drm_device *dev = state->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(state->dev);
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_crtc *crtc;
+ struct intel_crtc *intel_crtc;
struct drm_crtc_state *old_crtc_state;
- struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
- struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
+ struct intel_crtc_state *cstate;
unsigned int updated = 0;
bool progress;
enum pipe pipe;
+ int i;
+
+ const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {};
+
+ for_each_crtc_in_state(state, crtc, old_crtc_state, i)
+ /* ignore allocations for crtc's that have been turned off. */
+ if (crtc->state->active)
+ entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb;
/*
* Whenever the number of active pipes changes, we need to make sure we
@@ -14280,21 +14291,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
* cause pipe underruns and other bad stuff.
*/
do {
- int i;
progress = false;
for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
bool vbl_wait = false;
unsigned int cmask = drm_crtc_mask(crtc);
- pipe = to_intel_crtc(crtc)->pipe;
- if (updated & cmask || !crtc->state->active)
+ intel_crtc = to_intel_crtc(crtc);
+ cstate = to_intel_crtc_state(crtc->state);
+ pipe = intel_crtc->pipe;
+
+ if (updated & cmask || !cstate->base.active)
continue;
- if (skl_ddb_allocation_overlaps(state, cur_ddb, new_ddb,
- pipe))
+
+ if (skl_ddb_allocation_overlaps(entries, &cstate->wm.skl.ddb, i))
continue;
updated |= cmask;
+ entries[i] = &cstate->wm.skl.ddb;
/*
* If this is an already active pipe, it's DDB changed,
@@ -14302,7 +14316,8 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
* then we need to wait for a vblank to pass for the
* new ddb allocation to take effect.
*/
- if (!skl_ddb_allocation_equals(cur_ddb, new_ddb, pipe) &&
+ if (!skl_ddb_entry_equal(&cstate->wm.skl.ddb,
+ &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb) &&
!crtc->state->active_changed &&
intel_state->wm_results.dirty_pipes != updated)
vbl_wait = true;
@@ -14311,7 +14326,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
crtc_vblank_mask);
if (vbl_wait)
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
progress = true;
}
@@ -14326,37 +14341,15 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
struct drm_crtc_state *old_crtc_state;
struct drm_crtc *crtc;
struct intel_crtc_state *intel_cstate;
- struct drm_plane *plane;
- struct drm_plane_state *plane_state;
bool hw_check = intel_state->modeset;
unsigned long put_domains[I915_MAX_PIPES] = {};
unsigned crtc_vblank_mask = 0;
- int i, ret;
-
- for_each_plane_in_state(state, plane, plane_state, i) {
- struct intel_plane_state *intel_plane_state =
- to_intel_plane_state(plane->state);
-
- if (!intel_plane_state->wait_req)
- continue;
-
- ret = i915_wait_request(intel_plane_state->wait_req,
- 0, NULL, NULL);
- /* EIO should be eaten, and we can't get interrupted in the
- * worker, and blocking commits have waited already. */
- WARN_ON(ret);
- }
+ int i;
drm_atomic_helper_wait_for_dependencies(state);
- if (intel_state->modeset) {
- memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
- sizeof(intel_state->min_pixclk));
- dev_priv->active_crtcs = intel_state->active_crtcs;
- dev_priv->atomic_cdclk_freq = intel_state->cdclk;
-
+ if (intel_state->modeset)
intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
- }
for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -14389,8 +14382,17 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
intel_check_cpu_fifo_underruns(dev_priv);
intel_check_pch_fifo_underruns(dev_priv);
- if (!crtc->state->active)
- intel_update_watermarks(crtc);
+ if (!crtc->state->active) {
+ /*
+ * Make sure we don't call initial_watermarks
+ * for ILK-style watermark updates.
+ */
+ if (dev_priv->display.atomic_update_watermarks)
+ dev_priv->display.initial_watermarks(intel_state,
+ to_intel_crtc_state(crtc->state));
+ else
+ intel_update_watermarks(intel_crtc);
+ }
}
}
@@ -14413,7 +14415,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
if (!intel_can_enable_sagv(state))
intel_disable_sagv(dev_priv);
- intel_modeset_verify_disabled(dev);
+ intel_modeset_verify_disabled(dev, state);
}
/* Complete the events for pipes that have now been disabled */
@@ -14456,7 +14458,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
intel_cstate = to_intel_crtc_state(crtc->state);
if (dev_priv->display.optimize_watermarks)
- dev_priv->display.optimize_watermarks(intel_cstate);
+ dev_priv->display.optimize_watermarks(intel_state,
+ intel_cstate);
}
for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
@@ -14465,7 +14468,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
if (put_domains[i])
modeset_put_power_domains(dev_priv, put_domains[i]);
- intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
+ intel_modeset_verify_crtc(crtc, state, old_crtc_state, crtc->state);
}
if (intel_state->modeset && intel_can_enable_sagv(state))
@@ -14482,7 +14485,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_commit_cleanup_done(state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
/* As one of the primary mmio accessors, KMS has a high likelihood
* of triggering bugs in unclaimed access. After we finish
@@ -14500,12 +14503,33 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
static void intel_atomic_commit_work(struct work_struct *work)
{
- struct drm_atomic_state *state = container_of(work,
- struct drm_atomic_state,
- commit_work);
+ struct drm_atomic_state *state =
+ container_of(work, struct drm_atomic_state, commit_work);
+
intel_atomic_commit_tail(state);
}
+static int __i915_sw_fence_call
+intel_atomic_commit_ready(struct i915_sw_fence *fence,
+ enum i915_sw_fence_notify notify)
+{
+ struct intel_atomic_state *state =
+ container_of(fence, struct intel_atomic_state, commit_ready);
+
+ switch (notify) {
+ case FENCE_COMPLETE:
+ if (state->base.commit_work.func)
+ queue_work(system_unbound_wq, &state->base.commit_work);
+ break;
+
+ case FENCE_FREE:
+ drm_atomic_state_put(&state->base);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static void intel_atomic_track_fbs(struct drm_atomic_state *state)
{
struct drm_plane_state *old_plane_state;
@@ -14527,10 +14551,6 @@ static void intel_atomic_track_fbs(struct drm_atomic_state *state)
* This function commits a top-level state object that has been validated
* with drm_atomic_helper_check().
*
- * FIXME: Atomic modeset support for i915 is not yet complete. At the moment
- * nonblocking commits are only safe for pure plane updates. Everything else
- * should work though.
- *
* RETURNS
* Zero for success or -errno.
*/
@@ -14542,33 +14562,42 @@ static int intel_atomic_commit(struct drm_device *dev,
struct drm_i915_private *dev_priv = to_i915(dev);
int ret = 0;
- if (intel_state->modeset && nonblock) {
- DRM_DEBUG_KMS("nonblocking commit for modeset not yet implemented.\n");
- return -EINVAL;
- }
-
ret = drm_atomic_helper_setup_commit(state, nonblock);
if (ret)
return ret;
- INIT_WORK(&state->commit_work, intel_atomic_commit_work);
+ drm_atomic_state_get(state);
+ i915_sw_fence_init(&intel_state->commit_ready,
+ intel_atomic_commit_ready);
- ret = intel_atomic_prepare_commit(dev, state, nonblock);
+ ret = intel_atomic_prepare_commit(dev, state);
if (ret) {
DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
+ i915_sw_fence_commit(&intel_state->commit_ready);
return ret;
}
drm_atomic_helper_swap_state(state, true);
dev_priv->wm.distrust_bios_wm = false;
- dev_priv->wm.skl_results = intel_state->wm_results;
intel_shared_dpll_commit(state);
intel_atomic_track_fbs(state);
- if (nonblock)
- queue_work(system_unbound_wq, &state->commit_work);
- else
+ if (intel_state->modeset) {
+ memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
+ sizeof(intel_state->min_pixclk));
+ dev_priv->active_crtcs = intel_state->active_crtcs;
+ dev_priv->atomic_cdclk_freq = intel_state->cdclk;
+ }
+
+ drm_atomic_state_get(state);
+ INIT_WORK(&state->commit_work,
+ nonblock ? intel_atomic_commit_work : NULL);
+
+ i915_sw_fence_commit(&intel_state->commit_ready);
+ if (!nonblock) {
+ i915_sw_fence_wait(&intel_state->commit_ready);
intel_atomic_commit_tail(state);
+ }
return 0;
}
@@ -14606,9 +14635,8 @@ retry:
goto retry;
}
- if (ret)
out:
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
}
/*
@@ -14681,19 +14709,21 @@ int
intel_prepare_plane_fb(struct drm_plane *plane,
struct drm_plane_state *new_state)
{
- struct drm_device *dev = plane->dev;
+ struct intel_atomic_state *intel_state =
+ to_intel_atomic_state(new_state->state);
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct drm_framebuffer *fb = new_state->fb;
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
- struct reservation_object *resv;
- int ret = 0;
+ int ret;
if (!obj && !old_obj)
return 0;
if (old_obj) {
struct drm_crtc_state *crtc_state =
- drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
+ drm_atomic_get_existing_crtc_state(new_state->state,
+ plane->state->crtc);
/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
@@ -14706,52 +14736,58 @@ intel_prepare_plane_fb(struct drm_plane *plane,
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
- if (needs_modeset(crtc_state))
- ret = i915_gem_object_wait_rendering(old_obj, true);
- if (ret) {
- /* GPU hangs should have been swallowed by the wait */
- WARN_ON(ret == -EIO);
- return ret;
+ if (needs_modeset(crtc_state)) {
+ ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
+ old_obj->resv, NULL,
+ false, 0,
+ GFP_KERNEL);
+ if (ret < 0)
+ return ret;
}
}
+ if (new_state->fence) { /* explicit fencing */
+ ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready,
+ new_state->fence,
+ I915_FENCE_TIMEOUT,
+ GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+ }
+
if (!obj)
return 0;
- /* For framebuffer backed by dmabuf, wait for fence */
- resv = i915_gem_object_get_dmabuf_resv(obj);
- if (resv) {
- long lret;
-
- lret = reservation_object_wait_timeout_rcu(resv, false, true,
- MAX_SCHEDULE_TIMEOUT);
- if (lret == -ERESTARTSYS)
- return lret;
+ if (!new_state->fence) { /* implicit fencing */
+ ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
+ obj->resv, NULL,
+ false, I915_FENCE_TIMEOUT,
+ GFP_KERNEL);
+ if (ret < 0)
+ return ret;
- WARN(lret < 0, "waiting returns %li\n", lret);
+ i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
}
if (plane->type == DRM_PLANE_TYPE_CURSOR &&
- INTEL_INFO(dev)->cursor_needs_physical) {
- int align = IS_I830(dev) ? 16 * 1024 : 256;
+ INTEL_INFO(dev_priv)->cursor_needs_physical) {
+ int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
ret = i915_gem_object_attach_phys(obj, align);
- if (ret)
+ if (ret) {
DRM_DEBUG_KMS("failed to attach phys object\n");
+ return ret;
+ }
} else {
struct i915_vma *vma;
vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
- if (IS_ERR(vma))
- ret = PTR_ERR(vma);
- }
-
- if (ret == 0) {
- to_intel_plane_state(new_state)->wait_req =
- i915_gem_active_get(&obj->last_write,
- &obj->base.dev->struct_mutex);
+ if (IS_ERR(vma)) {
+ DRM_DEBUG_KMS("failed to pin object\n");
+ return PTR_ERR(vma);
+ }
}
- return ret;
+ return 0;
}
/**
@@ -14767,9 +14803,8 @@ void
intel_cleanup_plane_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
- struct drm_device *dev = plane->dev;
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct intel_plane_state *old_intel_state;
- struct intel_plane_state *intel_state = to_intel_plane_state(plane->state);
struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
@@ -14779,11 +14814,8 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
return;
if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
- !INTEL_INFO(dev)->cursor_needs_physical))
+ !INTEL_INFO(dev_priv)->cursor_needs_physical))
intel_unpin_fb_obj(old_state->fb, old_state->rotation);
-
- i915_gem_request_assign(&intel_state->wait_req, NULL);
- i915_gem_request_assign(&old_intel_state->wait_req, NULL);
}
int
@@ -14858,30 +14890,34 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_crtc_state *old_intel_state =
+ struct intel_crtc_state *intel_cstate =
+ to_intel_crtc_state(crtc->state);
+ struct intel_crtc_state *old_intel_cstate =
to_intel_crtc_state(old_crtc_state);
+ struct intel_atomic_state *old_intel_state =
+ to_intel_atomic_state(old_crtc_state->state);
bool modeset = needs_modeset(crtc->state);
- enum pipe pipe = intel_crtc->pipe;
/* Perform vblank evasion around commit operation */
intel_pipe_update_start(intel_crtc);
if (modeset)
- return;
+ goto out;
if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) {
intel_color_set_csc(crtc->state);
intel_color_load_luts(crtc->state);
}
- if (to_intel_crtc_state(crtc->state)->update_pipe)
- intel_update_pipe_config(intel_crtc, old_intel_state);
- else if (INTEL_GEN(dev_priv) >= 9) {
+ if (intel_cstate->update_pipe)
+ intel_update_pipe_config(intel_crtc, old_intel_cstate);
+ else if (INTEL_GEN(dev_priv) >= 9)
skl_detach_scalers(intel_crtc);
- I915_WRITE(PIPE_WM_LINETIME(pipe),
- dev_priv->wm.skl_hw.wm_linetime[pipe]);
- }
+out:
+ if (dev_priv->display.atomic_update_watermarks)
+ dev_priv->display.atomic_update_watermarks(old_intel_state,
+ intel_cstate);
}
static void intel_finish_crtc_commit(struct drm_crtc *crtc,
@@ -14901,9 +14937,6 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
*/
void intel_plane_destroy(struct drm_plane *plane)
{
- if (!plane)
- return;
-
drm_plane_cleanup(plane);
kfree(to_intel_plane(plane));
}
@@ -14917,53 +14950,63 @@ const struct drm_plane_funcs intel_plane_funcs = {
.atomic_set_property = intel_plane_atomic_set_property,
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
-
};
-static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
- int pipe)
+static struct intel_plane *
+intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_plane *primary = NULL;
struct intel_plane_state *state = NULL;
const uint32_t *intel_primary_formats;
+ unsigned int supported_rotations;
unsigned int num_formats;
int ret;
primary = kzalloc(sizeof(*primary), GFP_KERNEL);
- if (!primary)
+ if (!primary) {
+ ret = -ENOMEM;
goto fail;
+ }
state = intel_create_plane_state(&primary->base);
- if (!state)
+ if (!state) {
+ ret = -ENOMEM;
goto fail;
+ }
+
primary->base.state = &state->base;
primary->can_scale = false;
primary->max_downscale = 1;
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
primary->can_scale = true;
state->scaler_id = -1;
}
primary->pipe = pipe;
- primary->plane = pipe;
+ /*
+ * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
+ * port is hooked to pipe B. Hence we want plane A feeding pipe B.
+ */
+ if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4)
+ primary->plane = (enum plane) !pipe;
+ else
+ primary->plane = (enum plane) pipe;
primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
primary->check_plane = intel_check_primary_plane;
- if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
- primary->plane = !pipe;
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
intel_primary_formats = skl_primary_formats;
num_formats = ARRAY_SIZE(skl_primary_formats);
primary->update_plane = skylake_update_primary_plane;
primary->disable_plane = skylake_disable_primary_plane;
- } else if (HAS_PCH_SPLIT(dev)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
intel_primary_formats = i965_primary_formats;
num_formats = ARRAY_SIZE(i965_primary_formats);
primary->update_plane = ironlake_update_primary_plane;
primary->disable_plane = i9xx_disable_primary_plane;
- } else if (INTEL_INFO(dev)->gen >= 4) {
+ } else if (INTEL_GEN(dev_priv) >= 4) {
intel_primary_formats = i965_primary_formats;
num_formats = ARRAY_SIZE(i965_primary_formats);
@@ -14977,57 +15020,56 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
primary->disable_plane = i9xx_disable_primary_plane;
}
- if (INTEL_INFO(dev)->gen >= 9)
- ret = drm_universal_plane_init(dev, &primary->base, 0,
- &intel_plane_funcs,
+ if (INTEL_GEN(dev_priv) >= 9)
+ ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+ 0, &intel_plane_funcs,
intel_primary_formats, num_formats,
DRM_PLANE_TYPE_PRIMARY,
"plane 1%c", pipe_name(pipe));
- else if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
- ret = drm_universal_plane_init(dev, &primary->base, 0,
- &intel_plane_funcs,
+ else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+ ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+ 0, &intel_plane_funcs,
intel_primary_formats, num_formats,
DRM_PLANE_TYPE_PRIMARY,
"primary %c", pipe_name(pipe));
else
- ret = drm_universal_plane_init(dev, &primary->base, 0,
- &intel_plane_funcs,
+ ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+ 0, &intel_plane_funcs,
intel_primary_formats, num_formats,
DRM_PLANE_TYPE_PRIMARY,
"plane %c", plane_name(primary->plane));
if (ret)
goto fail;
- if (INTEL_INFO(dev)->gen >= 4)
- intel_create_rotation_property(dev, primary);
+ if (INTEL_GEN(dev_priv) >= 9) {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_90 |
+ DRM_ROTATE_180 | DRM_ROTATE_270;
+ } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_180 |
+ DRM_REFLECT_X;
+ } else if (INTEL_GEN(dev_priv) >= 4) {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_180;
+ } else {
+ supported_rotations = DRM_ROTATE_0;
+ }
+
+ if (INTEL_GEN(dev_priv) >= 4)
+ drm_plane_create_rotation_property(&primary->base,
+ DRM_ROTATE_0,
+ supported_rotations);
drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
- return &primary->base;
+ return primary;
fail:
kfree(state);
kfree(primary);
- return NULL;
-}
-
-void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
-{
- if (!dev->mode_config.rotation_property) {
- unsigned long flags = DRM_ROTATE_0 |
- DRM_ROTATE_180;
-
- if (INTEL_INFO(dev)->gen >= 9)
- flags |= DRM_ROTATE_90 | DRM_ROTATE_270;
-
- dev->mode_config.rotation_property =
- drm_mode_create_rotation_property(dev, flags);
- }
- if (dev->mode_config.rotation_property)
- drm_object_attach_property(&plane->base.base,
- dev->mode_config.rotation_property,
- plane->base.state->rotation);
+ return ERR_PTR(ret);
}
static int
@@ -15054,7 +15096,8 @@ intel_check_cursor_plane(struct drm_plane *plane,
return 0;
/* Check for which cursor types we support */
- if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) {
+ if (!cursor_size_ok(to_i915(plane->dev), state->base.crtc_w,
+ state->base.crtc_h)) {
DRM_DEBUG("Cursor dimension %dx%d not supported\n",
state->base.crtc_w, state->base.crtc_h);
return -EINVAL;
@@ -15066,7 +15109,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
return -ENOMEM;
}
- if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
+ if (fb->modifier != DRM_FORMAT_MOD_NONE) {
DRM_DEBUG_KMS("cursor cannot be tiled\n");
return -EINVAL;
}
@@ -15081,7 +15124,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
* display power well must be turned off and on again.
* Refuse the put the cursor into that compromised position.
*/
- if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
+ if (IS_CHERRYVIEW(to_i915(plane->dev)) && pipe == PIPE_C &&
state->base.visible && state->base.crtc_x < 0) {
DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
return -EINVAL;
@@ -15107,13 +15150,13 @@ intel_update_cursor_plane(struct drm_plane *plane,
{
struct drm_crtc *crtc = crtc_state->base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_device *dev = plane->dev;
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
uint32_t addr;
if (!obj)
addr = 0;
- else if (!INTEL_INFO(dev)->cursor_needs_physical)
+ else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
addr = i915_gem_object_ggtt_offset(obj, NULL);
else
addr = obj->phys_handle->busaddr;
@@ -15122,20 +15165,25 @@ intel_update_cursor_plane(struct drm_plane *plane,
intel_crtc_update_cursor(crtc, state);
}
-static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
- int pipe)
+static struct intel_plane *
+intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_plane *cursor = NULL;
struct intel_plane_state *state = NULL;
int ret;
cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
- if (!cursor)
+ if (!cursor) {
+ ret = -ENOMEM;
goto fail;
+ }
state = intel_create_plane_state(&cursor->base);
- if (!state)
+ if (!state) {
+ ret = -ENOMEM;
goto fail;
+ }
+
cursor->base.state = &state->base;
cursor->can_scale = false;
@@ -15147,8 +15195,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
cursor->update_plane = intel_update_cursor_plane;
cursor->disable_plane = intel_disable_cursor_plane;
- ret = drm_universal_plane_init(dev, &cursor->base, 0,
- &intel_plane_funcs,
+ ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
+ 0, &intel_plane_funcs,
intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats),
DRM_PLANE_TYPE_CURSOR,
@@ -15156,102 +15204,106 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
if (ret)
goto fail;
- if (INTEL_INFO(dev)->gen >= 4) {
- if (!dev->mode_config.rotation_property)
- dev->mode_config.rotation_property =
- drm_mode_create_rotation_property(dev,
- DRM_ROTATE_0 |
- DRM_ROTATE_180);
- if (dev->mode_config.rotation_property)
- drm_object_attach_property(&cursor->base.base,
- dev->mode_config.rotation_property,
- state->base.rotation);
- }
+ if (INTEL_GEN(dev_priv) >= 4)
+ drm_plane_create_rotation_property(&cursor->base,
+ DRM_ROTATE_0,
+ DRM_ROTATE_0 |
+ DRM_ROTATE_180);
- if (INTEL_INFO(dev)->gen >=9)
+ if (INTEL_GEN(dev_priv) >= 9)
state->scaler_id = -1;
drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
- return &cursor->base;
+ return cursor;
fail:
kfree(state);
kfree(cursor);
- return NULL;
+ return ERR_PTR(ret);
}
-static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state)
+static void skl_init_scalers(struct drm_i915_private *dev_priv,
+ struct intel_crtc *crtc,
+ struct intel_crtc_state *crtc_state)
{
+ struct intel_crtc_scaler_state *scaler_state =
+ &crtc_state->scaler_state;
int i;
- struct intel_scaler *intel_scaler;
- struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
- for (i = 0; i < intel_crtc->num_scalers; i++) {
- intel_scaler = &scaler_state->scalers[i];
- intel_scaler->in_use = 0;
- intel_scaler->mode = PS_SCALER_MODE_DYN;
+ for (i = 0; i < crtc->num_scalers; i++) {
+ struct intel_scaler *scaler = &scaler_state->scalers[i];
+
+ scaler->in_use = 0;
+ scaler->mode = PS_SCALER_MODE_DYN;
}
scaler_state->scaler_id = -1;
}
-static void intel_crtc_init(struct drm_device *dev, int pipe)
+static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc;
struct intel_crtc_state *crtc_state = NULL;
- struct drm_plane *primary = NULL;
- struct drm_plane *cursor = NULL;
- int ret;
+ struct intel_plane *primary = NULL;
+ struct intel_plane *cursor = NULL;
+ int sprite, ret;
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
- if (intel_crtc == NULL)
- return;
+ if (!intel_crtc)
+ return -ENOMEM;
crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
- if (!crtc_state)
+ if (!crtc_state) {
+ ret = -ENOMEM;
goto fail;
+ }
intel_crtc->config = crtc_state;
intel_crtc->base.state = &crtc_state->base;
crtc_state->base.crtc = &intel_crtc->base;
/* initialize shared scalers */
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
if (pipe == PIPE_C)
intel_crtc->num_scalers = 1;
else
intel_crtc->num_scalers = SKL_NUM_SCALERS;
- skl_init_scalers(dev, intel_crtc, crtc_state);
+ skl_init_scalers(dev_priv, intel_crtc, crtc_state);
}
- primary = intel_primary_plane_create(dev, pipe);
- if (!primary)
+ primary = intel_primary_plane_create(dev_priv, pipe);
+ if (IS_ERR(primary)) {
+ ret = PTR_ERR(primary);
goto fail;
+ }
+
+ for_each_sprite(dev_priv, pipe, sprite) {
+ struct intel_plane *plane;
- cursor = intel_cursor_plane_create(dev, pipe);
- if (!cursor)
+ plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
+ if (IS_ERR(plane)) {
+ ret = PTR_ERR(plane);
+ goto fail;
+ }
+ }
+
+ cursor = intel_cursor_plane_create(dev_priv, pipe);
+ if (IS_ERR(cursor)) {
+ ret = PTR_ERR(cursor);
goto fail;
+ }
- ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
- cursor, &intel_crtc_funcs,
+ ret = drm_crtc_init_with_planes(&dev_priv->drm, &intel_crtc->base,
+ &primary->base, &cursor->base,
+ &intel_crtc_funcs,
"pipe %c", pipe_name(pipe));
if (ret)
goto fail;
- /*
- * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
- * is hooked to pipe B. Hence we want plane A feeding pipe B.
- */
intel_crtc->pipe = pipe;
- intel_crtc->plane = pipe;
- if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) {
- DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
- intel_crtc->plane = !pipe;
- }
+ intel_crtc->plane = primary->plane;
intel_crtc->cursor_base = ~0;
intel_crtc->cursor_cntl = ~0;
@@ -15261,21 +15313,26 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
- dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
- dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
+ dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc;
+ dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc;
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
intel_color_init(&intel_crtc->base);
WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
- return;
+
+ return 0;
fail:
- intel_plane_destroy(primary);
- intel_plane_destroy(cursor);
+ /*
+ * drm_mode_config_cleanup() will free up any
+ * crtcs/planes already initialized.
+ */
kfree(crtc_state);
kfree(intel_crtc);
+
+ return ret;
}
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
@@ -15325,40 +15382,37 @@ static int intel_encoder_clones(struct intel_encoder *encoder)
return index_mask;
}
-static bool has_edp_a(struct drm_device *dev)
+static bool has_edp_a(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (!IS_MOBILE(dev))
+ if (!IS_MOBILE(dev_priv))
return false;
if ((I915_READ(DP_A) & DP_DETECTED) == 0)
return false;
- if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
+ if (IS_GEN5(dev_priv) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
return false;
return true;
}
-static bool intel_crt_present(struct drm_device *dev)
+static bool intel_crt_present(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
return false;
- if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
+ if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
return false;
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
return false;
- if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
+ if (HAS_PCH_LPT_H(dev_priv) &&
+ I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
return false;
/* DDI E can't be used if DDI A requires 4 lanes */
- if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
+ if (HAS_DDI(dev_priv) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
return false;
if (!dev_priv->vbt.int_crt_support)
@@ -15418,10 +15472,10 @@ static void intel_setup_outputs(struct drm_device *dev)
*/
intel_lvds_init(dev);
- if (intel_crt_present(dev))
+ if (intel_crt_present(dev_priv))
intel_crt_init(dev);
- if (IS_BROXTON(dev)) {
+ if (IS_BROXTON(dev_priv)) {
/*
* FIXME: Broxton doesn't support port detection via the
* DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
@@ -15432,7 +15486,7 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_ddi_init(dev, PORT_C);
intel_dsi_init(dev);
- } else if (HAS_DDI(dev)) {
+ } else if (HAS_DDI(dev_priv)) {
int found;
/*
@@ -15442,7 +15496,7 @@ static void intel_setup_outputs(struct drm_device *dev)
*/
found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
/* WaIgnoreDDIAStrap: skl */
- if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ if (found || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
intel_ddi_init(dev, PORT_A);
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -15458,17 +15512,17 @@ static void intel_setup_outputs(struct drm_device *dev)
/*
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
*/
- if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
+ if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
intel_ddi_init(dev, PORT_E);
- } else if (HAS_PCH_SPLIT(dev)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
int found;
- dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
+ dpd_is_edp = intel_dp_is_edp(dev_priv, PORT_D);
- if (has_edp_a(dev))
+ if (has_edp_a(dev_priv))
intel_dp_init(dev, DP_A, PORT_A);
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
@@ -15491,7 +15545,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_DP_D) & DP_DETECTED)
intel_dp_init(dev, PCH_DP_D, PORT_D);
- } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
bool has_edp, has_port;
/*
@@ -15509,21 +15563,21 @@ static void intel_setup_outputs(struct drm_device *dev)
* trust the port type the VBT declares as we've seen at least
* HDMI ports that the VBT claim are DP or eDP.
*/
- has_edp = intel_dp_is_edp(dev, PORT_B);
+ has_edp = intel_dp_is_edp(dev_priv, PORT_B);
has_port = intel_bios_is_port_present(dev_priv, PORT_B);
if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
- has_edp = intel_dp_is_edp(dev, PORT_C);
+ has_edp = intel_dp_is_edp(dev_priv, PORT_C);
has_port = intel_bios_is_port_present(dev_priv, PORT_C);
if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
/*
* eDP not supported on port D,
* so no need to worry about it
@@ -15536,18 +15590,18 @@ static void intel_setup_outputs(struct drm_device *dev)
}
intel_dsi_init(dev);
- } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
+ } else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) {
bool found = false;
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
DRM_DEBUG_KMS("probing SDVOB\n");
found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
- if (!found && IS_G4X(dev)) {
+ if (!found && IS_G4X(dev_priv)) {
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
}
- if (!found && IS_G4X(dev))
+ if (!found && IS_G4X(dev_priv))
intel_dp_init(dev, DP_B, PORT_B);
}
@@ -15560,21 +15614,20 @@ static void intel_setup_outputs(struct drm_device *dev)
if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
- if (IS_G4X(dev)) {
+ if (IS_G4X(dev_priv)) {
DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
}
- if (IS_G4X(dev))
+ if (IS_G4X(dev_priv))
intel_dp_init(dev, DP_C, PORT_C);
}
- if (IS_G4X(dev) &&
- (I915_READ(DP_D) & DP_DETECTED))
+ if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED))
intel_dp_init(dev, DP_D, PORT_D);
- } else if (IS_GEN2(dev))
+ } else if (IS_GEN2(dev_priv))
intel_dvo_init(dev);
- if (SUPPORTS_TV(dev))
+ if (SUPPORTS_TV(dev_priv))
intel_tv_init(dev);
intel_psr_init(dev);
@@ -15629,6 +15682,8 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj = intel_fb->obj;
mutex_lock(&dev->struct_mutex);
+ if (obj->pin_display && obj->cache_dirty)
+ i915_gem_clflush_object(obj, true);
intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
mutex_unlock(&dev->struct_mutex);
@@ -15642,10 +15697,10 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
};
static
-u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
- uint32_t pixel_format)
+u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
+ uint64_t fb_modifier, uint32_t pixel_format)
{
- u32 gen = INTEL_INFO(dev)->gen;
+ u32 gen = INTEL_INFO(dev_priv)->gen;
if (gen >= 9) {
int cpp = drm_format_plane_cpp(pixel_format, 0);
@@ -15654,7 +15709,8 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
* pixels and 32K bytes."
*/
return min(8192 * cpp, 32768);
- } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+ } else if (gen >= 5 && !IS_VALLEYVIEW(dev_priv) &&
+ !IS_CHERRYVIEW(dev_priv)) {
return 32*1024;
} else if (gen >= 4) {
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
@@ -15681,7 +15737,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
unsigned int tiling = i915_gem_object_get_tiling(obj);
int ret;
u32 pitch_limit, stride_alignment;
- char *format_name;
+ struct drm_format_name_buf format_name;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -15708,7 +15764,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
switch (mode_cmd->modifier[0]) {
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
- if (INTEL_INFO(dev)->gen < 9) {
+ if (INTEL_GEN(dev_priv) < 9) {
DRM_DEBUG("Unsupported tiling 0x%llx!\n",
mode_cmd->modifier[0]);
return -EINVAL;
@@ -15741,7 +15797,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
return -EINVAL;
}
- pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
+ pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->modifier[0],
mode_cmd->pixel_format);
if (mode_cmd->pitches[0] > pitch_limit) {
DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
@@ -15771,37 +15827,33 @@ static int intel_framebuffer_init(struct drm_device *dev,
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XRGB1555:
- if (INTEL_INFO(dev)->gen > 3) {
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ if (INTEL_GEN(dev_priv) > 3) {
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
break;
case DRM_FORMAT_ABGR8888:
- if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
- INTEL_INFO(dev)->gen < 9) {
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+ INTEL_GEN(dev_priv) < 9) {
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_XBGR2101010:
- if (INTEL_INFO(dev)->gen < 4) {
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ if (INTEL_GEN(dev_priv) < 4) {
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
break;
case DRM_FORMAT_ABGR2101010:
- if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
break;
@@ -15809,17 +15861,15 @@ static int intel_framebuffer_init(struct drm_device *dev,
case DRM_FORMAT_UYVY:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_VYUY:
- if (INTEL_INFO(dev)->gen < 5) {
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ if (INTEL_GEN(dev_priv) < 5) {
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
break;
default:
- format_name = drm_get_format_name(mode_cmd->pixel_format);
- DRM_DEBUG("unsupported pixel format: %s\n", format_name);
- kfree(format_name);
+ DRM_DEBUG("unsupported pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
@@ -15860,17 +15910,11 @@ intel_user_framebuffer_create(struct drm_device *dev,
fb = intel_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb))
- i915_gem_object_put_unlocked(obj);
+ i915_gem_object_put(obj);
return fb;
}
-#ifndef CONFIG_DRM_FBDEV_EMULATION
-static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
-{
-}
-#endif
-
static const struct drm_mode_config_funcs intel_mode_funcs = {
.fb_create = intel_user_framebuffer_create,
.output_poll_changed = intel_fbdev_output_poll_changed,
@@ -16246,12 +16290,11 @@ static void intel_init_quirks(struct drm_device *dev)
}
/* Disable the VGA plane that we never use */
-static void i915_disable_vga(struct drm_device *dev)
+static void i915_disable_vga(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
u8 sr1;
- i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
@@ -16269,11 +16312,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
- intel_init_clock_gating(dev);
+ intel_init_clock_gating(dev_priv);
}
/*
@@ -16290,6 +16333,7 @@ static void sanitize_watermarks(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_atomic_state *state;
+ struct intel_atomic_state *intel_state;
struct drm_crtc *crtc;
struct drm_crtc_state *cstate;
struct drm_modeset_acquire_ctx ctx;
@@ -16318,12 +16362,14 @@ retry:
if (WARN_ON(IS_ERR(state)))
goto fail;
+ intel_state = to_intel_atomic_state(state);
+
/*
* Hardware readout is the only time we don't want to calculate
* intermediate watermarks (since we don't trust the current
* watermarks).
*/
- to_intel_atomic_state(state)->skip_intermediate_wm = true;
+ intel_state->skip_intermediate_wm = true;
ret = intel_atomic_check(dev, state);
if (ret) {
@@ -16339,7 +16385,7 @@ retry:
* BIOS-programmed watermarks untouched and hope for the best.
*/
WARN(true, "Could not determine valid watermarks for inherited state\n");
- goto fail;
+ goto put_state;
}
/* Write calculated watermark values back */
@@ -16347,20 +16393,20 @@ retry:
struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
cs->wm.need_postvbl_update = true;
- dev_priv->display.optimize_watermarks(cs);
+ dev_priv->display.optimize_watermarks(intel_state, cs);
}
- drm_atomic_state_free(state);
+put_state:
+ drm_atomic_state_put(state);
fail:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
}
-void intel_modeset_init(struct drm_device *dev)
+int intel_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
- int sprite, ret;
enum pipe pipe;
struct intel_crtc *crtc;
@@ -16378,10 +16424,10 @@ void intel_modeset_init(struct drm_device *dev)
intel_init_quirks(dev);
- intel_init_pm(dev);
+ intel_init_pm(dev_priv);
- if (INTEL_INFO(dev)->num_pipes == 0)
- return;
+ if (INTEL_INFO(dev_priv)->num_pipes == 0)
+ return 0;
/*
* There may be no VBT; and if the BIOS enabled SSC we can
@@ -16389,7 +16435,7 @@ void intel_modeset_init(struct drm_device *dev)
* BIOS isn't using it, don't assume it will work even if the VBT
* indicates as much.
*/
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
DREF_SSC1_ENABLE);
@@ -16401,10 +16447,10 @@ void intel_modeset_init(struct drm_device *dev)
}
}
- if (IS_GEN2(dev)) {
+ if (IS_GEN2(dev_priv)) {
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
- } else if (IS_GEN3(dev)) {
+ } else if (IS_GEN3(dev_priv)) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
} else {
@@ -16412,10 +16458,10 @@ void intel_modeset_init(struct drm_device *dev)
dev->mode_config.max_height = 8192;
}
- if (IS_845G(dev) || IS_I865G(dev)) {
- dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512;
+ if (IS_845G(dev_priv) || IS_I865G(dev_priv)) {
+ dev->mode_config.cursor_width = IS_845G(dev_priv) ? 64 : 512;
dev->mode_config.cursor_height = 1023;
- } else if (IS_GEN2(dev)) {
+ } else if (IS_GEN2(dev_priv)) {
dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
} else {
@@ -16426,29 +16472,30 @@ void intel_modeset_init(struct drm_device *dev)
dev->mode_config.fb_base = ggtt->mappable_base;
DRM_DEBUG_KMS("%d display pipe%s available.\n",
- INTEL_INFO(dev)->num_pipes,
- INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
+ INTEL_INFO(dev_priv)->num_pipes,
+ INTEL_INFO(dev_priv)->num_pipes > 1 ? "s" : "");
for_each_pipe(dev_priv, pipe) {
- intel_crtc_init(dev, pipe);
- for_each_sprite(dev_priv, pipe, sprite) {
- ret = intel_plane_init(dev, pipe, sprite);
- if (ret)
- DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
- pipe_name(pipe), sprite_name(pipe, sprite), ret);
+ int ret;
+
+ ret = intel_crtc_init(dev_priv, pipe);
+ if (ret) {
+ drm_mode_config_cleanup(dev);
+ return ret;
}
}
intel_update_czclk(dev_priv);
- intel_update_cdclk(dev);
+ intel_update_cdclk(dev_priv);
+ dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
intel_shared_dpll_init(dev);
if (dev_priv->max_cdclk_freq == 0)
- intel_update_max_cdclk(dev);
+ intel_update_max_cdclk(dev_priv);
/* Just disable it once at startup */
- i915_disable_vga(dev);
+ i915_disable_vga(dev_priv);
intel_setup_outputs(dev);
drm_modeset_lock_all(dev);
@@ -16484,6 +16531,8 @@ void intel_modeset_init(struct drm_device *dev)
* since the watermark calculation done here will use pstate->fb.
*/
sanitize_watermarks(dev);
+
+ return 0;
}
static void intel_enable_pipe_a(struct drm_device *dev)
@@ -16513,11 +16562,10 @@ static void intel_enable_pipe_a(struct drm_device *dev)
static bool
intel_check_plane_mapping(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 val;
- if (INTEL_INFO(dev)->num_pipes == 1)
+ if (INTEL_INFO(dev_priv)->num_pipes == 1)
return true;
val = I915_READ(DSPCNTR(!crtc->plane));
@@ -16591,7 +16639,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
/* We need to sanitize the plane -> pipe mapping first because this will
* disable the crtc (and hence change the state) if it is wrong. Note
* that gen4+ has a fixed plane -> pipe mapping. */
- if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
+ if (INTEL_GEN(dev_priv) < 4 && !intel_check_plane_mapping(crtc)) {
bool plane;
DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n",
@@ -16621,7 +16669,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
if (crtc->active && !intel_crtc_has_encoders(crtc))
intel_crtc_disable_noatomic(&crtc->base);
- if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
+ if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) {
/*
* We start out with underrun reporting disabled to avoid races.
* For correct bookkeeping mark this on active crtcs.
@@ -16693,21 +16741,18 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
* the crtc fixup. */
}
-void i915_redisable_vga_power_on(struct drm_device *dev)
+void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
- i915_disable_vga(dev);
+ i915_disable_vga(dev_priv);
}
}
-void i915_redisable_vga(struct drm_device *dev)
+void i915_redisable_vga(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* This function can be called both from intel_modeset_setup_hw_state or
* at a very early point in our resume sequence, where the power well
* structures are not yet restored. Since this function is at a very
@@ -16718,7 +16763,7 @@ void i915_redisable_vga(struct drm_device *dev)
if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
return;
- i915_redisable_vga_power_on(dev);
+ i915_redisable_vga_power_on(dev_priv);
intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
}
@@ -16790,7 +16835,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
crtc->base.base.id, crtc->base.name,
- crtc->active ? "enabled" : "disabled");
+ enableddisabled(crtc->active));
}
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
@@ -16813,7 +16858,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
pipe = 0;
if (encoder->get_hw_state(encoder, &pipe)) {
- crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+
encoder->base.crtc = &crtc->base;
crtc->config->output_types |= 1 << encoder->type;
encoder->get_config(encoder, crtc->config);
@@ -16822,9 +16868,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
}
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
- encoder->base.base.id,
- encoder->base.name,
- encoder->base.crtc ? "enabled" : "disabled",
+ encoder->base.base.id, encoder->base.name,
+ enableddisabled(encoder->base.crtc),
pipe_name(pipe));
}
@@ -16853,9 +16898,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
connector->base.encoder = NULL;
}
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
- connector->base.base.id,
- connector->base.name,
- connector->base.encoder ? "enabled" : "disabled");
+ connector->base.base.id, connector->base.name,
+ enableddisabled(connector->base.encoder));
}
for_each_intel_crtc(dev, crtc) {
@@ -16914,7 +16958,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
}
for_each_pipe(dev_priv, pipe) {
- crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+
intel_sanitize_crtc(crtc);
intel_dump_pipe_config(crtc, crtc->config,
"[setup_hw_state]");
@@ -16934,11 +16979,11 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
pll->on = false;
}
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_wm_get_hw_state(dev);
- else if (IS_GEN9(dev))
+ else if (IS_GEN9(dev_priv))
skl_wm_get_hw_state(dev);
- else if (HAS_PCH_SPLIT(dev))
+ else if (HAS_PCH_SPLIT(dev_priv))
ilk_wm_get_hw_state(dev);
for_each_intel_crtc(dev, crtc) {
@@ -16988,10 +17033,9 @@ void intel_display_resume(struct drm_device *dev)
drm_modeset_acquire_fini(&ctx);
mutex_unlock(&dev->mode_config.mutex);
- if (ret) {
+ if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret);
- drm_atomic_state_free(state);
- }
+ drm_atomic_state_put(state);
}
void intel_modeset_gem_init(struct drm_device *dev)
@@ -17103,10 +17147,9 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
/*
* set vga decode state - true == enable VGA decode
*/
-int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
+int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv, bool state)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
+ unsigned reg = INTEL_GEN(dev_priv) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
u16 gmch_ctrl;
if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
@@ -17130,6 +17173,8 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
return 0;
}
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
struct intel_display_error_state {
u32 power_well_driver;
@@ -17258,17 +17303,16 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
void
intel_display_print_error_state(struct drm_i915_error_state_buf *m,
- struct drm_device *dev,
+ struct drm_i915_private *dev_priv,
struct intel_display_error_state *error)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
int i;
if (!error)
return;
- err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev_priv)->num_pipes);
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
err_printf(m, "PWR_WELL_CTL2: %08x\n",
error->power_well_driver);
for_each_pipe(dev_priv, i) {
@@ -17281,13 +17325,13 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, "Plane [%d]:\n", i);
err_printf(m, " CNTR: %08x\n", error->plane[i].control);
err_printf(m, " STRIDE: %08x\n", error->plane[i].stride);
- if (INTEL_INFO(dev)->gen <= 3) {
+ if (INTEL_GEN(dev_priv) <= 3) {
err_printf(m, " SIZE: %08x\n", error->plane[i].size);
err_printf(m, " POS: %08x\n", error->plane[i].pos);
}
- if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+ if (INTEL_GEN(dev_priv) <= 7 && !IS_HASWELL(dev_priv))
err_printf(m, " ADDR: %08x\n", error->plane[i].addr);
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
err_printf(m, " SURF: %08x\n", error->plane[i].surface);
err_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset);
}
@@ -17312,3 +17356,5 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
}
}
+
+#endif
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index bf344d08356a..90283edcafba 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -213,6 +213,81 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
return max_dotclk;
}
+static int
+intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
+{
+ if (intel_dp->num_sink_rates) {
+ *sink_rates = intel_dp->sink_rates;
+ return intel_dp->num_sink_rates;
+ }
+
+ *sink_rates = default_rates;
+
+ return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
+}
+
+static int
+intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+ int size;
+
+ if (IS_BROXTON(dev_priv)) {
+ *source_rates = bxt_rates;
+ size = ARRAY_SIZE(bxt_rates);
+ } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+ *source_rates = skl_rates;
+ size = ARRAY_SIZE(skl_rates);
+ } else {
+ *source_rates = default_rates;
+ size = ARRAY_SIZE(default_rates);
+ }
+
+ /* This depends on the fact that 5.4 is last value in the array */
+ if (!intel_dp_source_supports_hbr2(intel_dp))
+ size--;
+
+ return size;
+}
+
+static int intersect_rates(const int *source_rates, int source_len,
+ const int *sink_rates, int sink_len,
+ int *common_rates)
+{
+ int i = 0, j = 0, k = 0;
+
+ while (i < source_len && j < sink_len) {
+ if (source_rates[i] == sink_rates[j]) {
+ if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
+ return k;
+ common_rates[k] = source_rates[i];
+ ++k;
+ ++i;
+ ++j;
+ } else if (source_rates[i] < sink_rates[j]) {
+ ++i;
+ } else {
+ ++j;
+ }
+ }
+ return k;
+}
+
+static int intel_dp_common_rates(struct intel_dp *intel_dp,
+ int *common_rates)
+{
+ const int *source_rates, *sink_rates;
+ int source_len, sink_len;
+
+ sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+ source_len = intel_dp_source_rates(intel_dp, &source_rates);
+
+ return intersect_rates(source_rates, source_len,
+ sink_rates, sink_len,
+ common_rates);
+}
+
static enum drm_mode_status
intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
@@ -320,8 +395,7 @@ static void
vlv_power_sequencer_kick(struct intel_dp *intel_dp)
{
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 = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
enum pipe pipe = intel_dp->pps_pipe;
bool pll_enabled, release_cl_override = false;
enum dpio_phy phy = DPIO_PHY(pipe);
@@ -344,7 +418,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
DP |= DP_PORT_WIDTH(1);
DP |= DP_LINK_TRAIN_PAT_1;
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
DP |= DP_PIPE_SELECT_CHV(pipe);
else if (pipe == PIPE_B)
DP |= DP_PIPEB_SELECT;
@@ -356,10 +430,10 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
* So enable temporarily it if it's not already enabled.
*/
if (!pll_enabled) {
- release_cl_override = IS_CHERRYVIEW(dev) &&
+ release_cl_override = IS_CHERRYVIEW(dev_priv) &&
!chv_phy_powergate_ch(dev_priv, phy, ch, true);
- if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
+ if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ?
&chv_dpll[0].dpll : &vlv_dpll[0].dpll)) {
DRM_ERROR("Failed to force on pll for pipe %c!\n",
pipe_name(pipe));
@@ -383,7 +457,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
POSTING_READ(intel_dp->output_reg);
if (!pll_enabled) {
- vlv_force_pll_off(dev, pipe);
+ vlv_force_pll_off(dev_priv, pipe);
if (release_cl_override)
chv_phy_powergate_ch(dev_priv, phy, ch, false);
@@ -570,8 +644,8 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
struct drm_device *dev = &dev_priv->drm;
struct intel_encoder *encoder;
- if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
- !IS_BROXTON(dev)))
+ if (WARN_ON(!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+ !IS_BROXTON(dev_priv)))
return;
/*
@@ -591,7 +665,7 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
continue;
intel_dp = enc_to_intel_dp(&encoder->base);
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
intel_dp->pps_reset = true;
else
intel_dp->pps_pipe = INVALID_PIPE;
@@ -664,7 +738,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
pps_lock(intel_dp);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
i915_reg_t pp_ctrl_reg, pp_div_reg;
u32 pp_div;
@@ -692,7 +766,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
lockdep_assert_held(&dev_priv->pps_mutex);
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_dp->pps_pipe == INVALID_PIPE)
return false;
@@ -706,7 +780,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
lockdep_assert_held(&dev_priv->pps_mutex);
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_dp->pps_pipe == INVALID_PIPE)
return false;
@@ -821,15 +895,16 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
uint32_t aux_clock_divider)
{
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 =
+ to_i915(intel_dig_port->base.base.dev);
uint32_t precharge, timeout;
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev_priv))
precharge = 3;
else
precharge = 5;
- if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A)
+ if (IS_BROADWELL(dev_priv) && intel_dig_port->port == PORT_A)
timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
else
timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
@@ -867,14 +942,14 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
uint8_t *recv, int recv_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 = to_i915(dev);
+ struct drm_i915_private *dev_priv =
+ to_i915(intel_dig_port->base.base.dev);
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
uint32_t aux_clock_divider;
int i, ret, recv_bytes;
uint32_t status;
int try, clock = 0;
- bool has_aux_irq = HAS_AUX_IRQ(dev);
+ bool has_aux_irq = HAS_AUX_IRQ(dev_priv);
bool vdd;
pps_lock(intel_dp);
@@ -1147,7 +1222,7 @@ static enum port intel_aux_port(struct drm_i915_private *dev_priv,
}
static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
- enum port port)
+ enum port port)
{
switch (port) {
case PORT_B:
@@ -1161,7 +1236,7 @@ static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv,
- enum port port, int index)
+ enum port port, int index)
{
switch (port) {
case PORT_B:
@@ -1175,7 +1250,7 @@ static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv,
- enum port port)
+ enum port port)
{
switch (port) {
case PORT_A:
@@ -1191,7 +1266,7 @@ static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
- enum port port, int index)
+ enum port port, int index)
{
switch (port) {
case PORT_A:
@@ -1207,7 +1282,7 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
- enum port port)
+ enum port port)
{
switch (port) {
case PORT_A:
@@ -1222,7 +1297,7 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
- enum port port, int index)
+ enum port port, int index)
{
switch (port) {
case PORT_A:
@@ -1237,7 +1312,7 @@ static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
- enum port port)
+ enum port port)
{
if (INTEL_INFO(dev_priv)->gen >= 9)
return skl_aux_ctl_reg(dev_priv, port);
@@ -1248,7 +1323,7 @@ static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
}
static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
- enum port port, int index)
+ enum port port, int index)
{
if (INTEL_INFO(dev_priv)->gen >= 9)
return skl_aux_data_reg(dev_priv, port, index);
@@ -1290,78 +1365,37 @@ intel_dp_aux_init(struct intel_dp *intel_dp)
intel_dp->aux.transfer = intel_dp_aux_transfer;
}
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
- if (intel_dp->num_sink_rates) {
- *sink_rates = intel_dp->sink_rates;
- return intel_dp->num_sink_rates;
- }
-
- *sink_rates = default_rates;
-
- return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
-}
-
bool intel_dp_source_supports_hbr2(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;
-
- /* WaDisableHBR2:skl */
- if (IS_SKL_REVID(dev, 0, SKL_REVID_B0))
- return false;
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
- if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
- (INTEL_INFO(dev)->gen >= 9))
+ if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) ||
+ IS_BROADWELL(dev_priv) || (INTEL_GEN(dev_priv) >= 9))
return true;
else
return false;
}
-static int
-intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = dig_port->base.base.dev;
- int size;
-
- if (IS_BROXTON(dev)) {
- *source_rates = bxt_rates;
- size = ARRAY_SIZE(bxt_rates);
- } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
- *source_rates = skl_rates;
- size = ARRAY_SIZE(skl_rates);
- } else {
- *source_rates = default_rates;
- size = ARRAY_SIZE(default_rates);
- }
-
- /* This depends on the fact that 5.4 is last value in the array */
- if (!intel_dp_source_supports_hbr2(intel_dp))
- size--;
-
- return size;
-}
-
static void
intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
const struct dp_link_dpll *divisor = NULL;
int i, count = 0;
- if (IS_G4X(dev)) {
+ if (IS_G4X(dev_priv)) {
divisor = gen4_dpll;
count = ARRAY_SIZE(gen4_dpll);
- } else if (HAS_PCH_SPLIT(dev)) {
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
divisor = pch_dpll;
count = ARRAY_SIZE(pch_dpll);
- } else if (IS_CHERRYVIEW(dev)) {
+ } else if (IS_CHERRYVIEW(dev_priv)) {
divisor = chv_dpll;
count = ARRAY_SIZE(chv_dpll);
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
divisor = vlv_dpll;
count = ARRAY_SIZE(vlv_dpll);
}
@@ -1377,43 +1411,6 @@ intel_dp_set_clock(struct intel_encoder *encoder,
}
}
-static int intersect_rates(const int *source_rates, int source_len,
- const int *sink_rates, int sink_len,
- int *common_rates)
-{
- int i = 0, j = 0, k = 0;
-
- while (i < source_len && j < sink_len) {
- if (source_rates[i] == sink_rates[j]) {
- if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
- return k;
- common_rates[k] = source_rates[i];
- ++k;
- ++i;
- ++j;
- } else if (source_rates[i] < sink_rates[j]) {
- ++i;
- } else {
- ++j;
- }
- }
- return k;
-}
-
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
- int *common_rates)
-{
- const int *source_rates, *sink_rates;
- int source_len, sink_len;
-
- sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
- source_len = intel_dp_source_rates(intel_dp, &source_rates);
-
- return intersect_rates(source_rates, source_len,
- sink_rates, sink_len,
- common_rates);
-}
-
static void snprintf_int_array(char *str, size_t len,
const int *array, int nelem)
{
@@ -1453,42 +1450,35 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("common rates: %s\n", str);
}
-static void intel_dp_print_hw_revision(struct intel_dp *intel_dp)
+bool
+__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc)
{
- uint8_t rev;
- int len;
-
- if ((drm_debug & DRM_UT_KMS) == 0)
- return;
-
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_PRESENT))
- return;
-
- len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1);
- if (len < 0)
- return;
+ u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI :
+ DP_SINK_OUI;
- DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf);
+ return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) ==
+ sizeof(*desc);
}
-static void intel_dp_print_sw_revision(struct intel_dp *intel_dp)
+bool intel_dp_read_desc(struct intel_dp *intel_dp)
{
- uint8_t rev[2];
- int len;
-
- if ((drm_debug & DRM_UT_KMS) == 0)
- return;
+ struct intel_dp_desc *desc = &intel_dp->desc;
+ bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] &
+ DP_OUI_SUPPORT;
+ int dev_id_len;
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_PRESENT))
- return;
+ if (!__intel_dp_read_desc(intel_dp, desc))
+ return false;
- len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2);
- if (len < 0)
- return;
+ dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id));
+ DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n",
+ drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink",
+ (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)",
+ dev_id_len, desc->device_id,
+ desc->hw_rev >> 4, desc->hw_rev & 0xf,
+ desc->sw_major_rev, desc->sw_minor_rev);
- DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]);
+ return true;
}
static int rate_to_index(int find, const int *rates)
@@ -1552,8 +1542,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
enum port port = dp_to_dig_port(intel_dp)->port;
@@ -1578,7 +1567,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
max_clock = common_len - 1;
- if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
+ if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
pipe_config->has_pch_encoder = true;
pipe_config->has_drrs = false;
@@ -1588,14 +1577,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
adjusted_mode);
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
int ret;
ret = skl_update_scaler_crtc(pipe_config);
if (ret)
return ret;
}
- if (HAS_GMCH_DISPLAY(dev))
+ if (HAS_GMCH_DISPLAY(dev_priv))
intel_gmch_panel_fitting(intel_crtc, pipe_config,
intel_connector->panel.fitting_mode);
else
@@ -1720,7 +1709,7 @@ found:
to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
}
- if (!HAS_DDI(dev))
+ if (!HAS_DDI(dev_priv))
intel_dp_set_clock(encoder, pipe_config);
return true;
@@ -1778,7 +1767,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
/* Split out the IBX/CPU vs CPT settings */
- if (IS_GEN7(dev) && port == PORT_A) {
+ if (IS_GEN7(dev_priv) && port == PORT_A) {
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
intel_dp->DP |= DP_SYNC_HS_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -1789,7 +1778,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
intel_dp->DP |= DP_ENHANCED_FRAMING;
intel_dp->DP |= crtc->pipe << 29;
- } else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+ } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
u32 trans_dp;
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
@@ -1801,8 +1790,7 @@ 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) &&
- !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range)
+ if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
intel_dp->DP |= DP_COLOR_RANGE_16_235;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -1814,7 +1802,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
intel_dp->DP |= DP_ENHANCED_FRAMING;
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe);
else if (crtc->pipe == PIPE_B)
intel_dp->DP |= DP_PIPEB_SELECT;
@@ -2123,7 +2111,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
pp = ironlake_get_pp_control(intel_dp);
- if (IS_GEN5(dev)) {
+ if (IS_GEN5(dev_priv)) {
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
I915_WRITE(pp_ctrl_reg, pp);
@@ -2131,7 +2119,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
}
pp |= PANEL_POWER_ON;
- if (!IS_GEN5(dev))
+ if (!IS_GEN5(dev_priv))
pp |= PANEL_POWER_RESET;
I915_WRITE(pp_ctrl_reg, pp);
@@ -2140,7 +2128,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
wait_panel_on(intel_dp);
intel_dp->last_power_on = jiffies;
- if (IS_GEN5(dev)) {
+ if (IS_GEN5(dev_priv)) {
pp |= PANEL_POWER_RESET; /* restore panel reset bit */
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -2372,7 +2360,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp,
* 2. Program DP PLL enable
*/
if (IS_GEN5(dev_priv))
- intel_wait_for_vblank_if_active(&dev_priv->drm, !crtc->pipe);
+ intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe);
intel_dp->DP |= DP_PLL_ENABLE;
@@ -2453,9 +2441,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
if (!(tmp & DP_PORT_EN))
goto out;
- if (IS_GEN7(dev) && port == PORT_A) {
+ if (IS_GEN7(dev_priv) && port == PORT_A) {
*pipe = PORT_TO_PIPE_CPT(tmp);
- } else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+ } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
enum pipe p;
for_each_pipe(dev_priv, p) {
@@ -2470,7 +2458,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
i915_mmio_reg_offset(intel_dp->output_reg));
- } else if (IS_CHERRYVIEW(dev)) {
+ } else if (IS_CHERRYVIEW(dev_priv)) {
*pipe = DP_PORT_TO_PIPE_CHV(tmp);
} else {
*pipe = PORT_TO_PIPE(tmp);
@@ -2498,7 +2486,7 @@ 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) {
+ if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe));
if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
@@ -2524,8 +2512,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
pipe_config->base.adjusted_mode.flags |= flags;
- if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
- !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235)
+ if (IS_G4X(dev_priv) && tmp & DP_COLOR_RANGE_16_235)
pipe_config->limited_color_range = true;
pipe_config->lane_count =
@@ -2645,7 +2632,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
DRM_DEBUG_KMS("Using DP training pattern TPS%d\n",
dp_train_pat & DP_TRAINING_PATTERN_MASK);
- if (HAS_DDI(dev)) {
+ if (HAS_DDI(dev_priv)) {
uint32_t temp = I915_READ(DP_TP_CTL(port));
if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
@@ -2671,8 +2658,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
}
I915_WRITE(DP_TP_CTL(port), temp);
- } else if ((IS_GEN7(dev) && port == PORT_A) ||
- (HAS_PCH_CPT(dev) && port != PORT_A)) {
+ } else if ((IS_GEN7(dev_priv) && port == PORT_A) ||
+ (HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
*DP &= ~DP_LINK_TRAIN_MASK_CPT;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
@@ -2692,7 +2679,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
}
} else {
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
*DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
*DP &= ~DP_LINK_TRAIN_MASK;
@@ -2708,7 +2695,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
*DP |= DP_LINK_TRAIN_PAT_2;
break;
case DP_TRAINING_PATTERN_3:
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
*DP |= DP_LINK_TRAIN_PAT_3_CHV;
} else {
DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n");
@@ -2744,7 +2731,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp,
}
static void intel_enable_dp(struct intel_encoder *encoder,
- struct intel_crtc_state *pipe_config)
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
struct drm_device *dev = encoder->base.dev;
@@ -2758,7 +2746,7 @@ static void intel_enable_dp(struct intel_encoder *encoder,
pps_lock(intel_dp);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_init_panel_power_sequencer(intel_dp);
intel_dp_enable_port(intel_dp, pipe_config);
@@ -2769,10 +2757,10 @@ static void intel_enable_dp(struct intel_encoder *encoder,
pps_unlock(intel_dp);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
unsigned int lane_mask = 0x0;
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count);
vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
@@ -2786,7 +2774,7 @@ static void intel_enable_dp(struct intel_encoder *encoder,
if (pipe_config->has_audio) {
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
pipe_name(pipe));
- intel_audio_codec_enable(encoder);
+ intel_audio_codec_enable(encoder, pipe_config, conn_state);
}
}
@@ -2796,7 +2784,7 @@ static void g4x_enable_dp(struct intel_encoder *encoder,
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
- intel_enable_dp(encoder, pipe_config);
+ intel_enable_dp(encoder, pipe_config, conn_state);
intel_edp_backlight_on(intel_dp);
}
@@ -2933,7 +2921,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder,
{
vlv_phy_pre_encoder_enable(encoder);
- intel_enable_dp(encoder, pipe_config);
+ intel_enable_dp(encoder, pipe_config, conn_state);
}
static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder,
@@ -2951,7 +2939,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder,
{
chv_phy_pre_encoder_enable(encoder);
- intel_enable_dp(encoder, pipe_config);
+ intel_enable_dp(encoder, pipe_config, conn_state);
/* Second common lane will stay alive on its own now */
chv_phy_release_cl2_override(encoder);
@@ -2988,21 +2976,20 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
uint8_t
intel_dp_voltage_max(struct intel_dp *intel_dp)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
enum port port = dp_to_dig_port(intel_dp)->port;
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
- else if (INTEL_INFO(dev)->gen >= 9) {
+ else if (INTEL_GEN(dev_priv) >= 9) {
if (dev_priv->vbt.edp.low_vswing && port == PORT_A)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
- } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
- else if (IS_GEN7(dev) && port == PORT_A)
+ else if (IS_GEN7(dev_priv) && port == PORT_A)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
- else if (HAS_PCH_CPT(dev) && port != PORT_A)
+ else if (HAS_PCH_CPT(dev_priv) && port != PORT_A)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
else
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -3011,10 +2998,10 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
uint8_t
intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
enum port port = dp_to_dig_port(intel_dp)->port;
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3027,7 +3014,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
default:
return DP_TRAIN_PRE_EMPH_LEVEL_0;
}
- } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3039,7 +3026,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
default:
return DP_TRAIN_PRE_EMPH_LEVEL_0;
}
- } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3051,7 +3038,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
default:
return DP_TRAIN_PRE_EMPH_LEVEL_0;
}
- } else if (IS_GEN7(dev) && port == PORT_A) {
+ } else if (IS_GEN7(dev_priv) && port == PORT_A) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
return DP_TRAIN_PRE_EMPH_LEVEL_2;
@@ -3352,21 +3339,21 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
uint32_t signal_levels, mask = 0;
uint8_t train_set = intel_dp->train_set[0];
- if (HAS_DDI(dev)) {
+ if (HAS_DDI(dev_priv)) {
signal_levels = ddi_signal_levels(intel_dp);
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
signal_levels = 0;
else
mask = DDI_BUF_EMP_MASK;
- } else if (IS_CHERRYVIEW(dev)) {
+ } else if (IS_CHERRYVIEW(dev_priv)) {
signal_levels = chv_signal_levels(intel_dp);
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
signal_levels = vlv_signal_levels(intel_dp);
- } else if (IS_GEN7(dev) && port == PORT_A) {
+ } else if (IS_GEN7(dev_priv) && port == PORT_A) {
signal_levels = gen7_edp_signal_levels(train_set);
mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
- } else if (IS_GEN6(dev) && port == PORT_A) {
+ } else if (IS_GEN6(dev_priv) && port == PORT_A) {
signal_levels = gen6_edp_signal_levels(train_set);
mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
} else {
@@ -3411,7 +3398,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
enum port port = intel_dig_port->port;
uint32_t val;
- if (!HAS_DDI(dev))
+ if (!HAS_DDI(dev_priv))
return;
val = I915_READ(DP_TP_CTL(port));
@@ -3446,7 +3433,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t DP = intel_dp->DP;
- if (WARN_ON(HAS_DDI(dev)))
+ if (WARN_ON(HAS_DDI(dev_priv)))
return;
if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
@@ -3454,12 +3441,12 @@ intel_dp_link_down(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("\n");
- if ((IS_GEN7(dev) && port == PORT_A) ||
- (HAS_PCH_CPT(dev) && port != PORT_A)) {
+ if ((IS_GEN7(dev_priv) && port == PORT_A) ||
+ (HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
DP &= ~DP_LINK_TRAIN_MASK_CPT;
DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
} else {
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
DP &= ~DP_LINK_TRAIN_MASK;
@@ -3477,7 +3464,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
* to transcoder A after disabling it to allow the
* matching HDMI port to be enabled on transcoder A.
*/
- if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
+ if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) {
/*
* We get CPU/PCH FIFO underruns on the other pipe when
* doing the workaround. Sweep them under the rug.
@@ -3495,7 +3482,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
I915_WRITE(intel_dp->output_reg, DP);
POSTING_READ(intel_dp->output_reg);
- intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+ intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
@@ -3505,7 +3492,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
intel_dp->DP = DP;
}
-static bool
+bool
intel_dp_read_dpcd(struct intel_dp *intel_dp)
{
if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
@@ -3529,6 +3516,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
if (!intel_dp_read_dpcd(intel_dp))
return false;
+ intel_dp_read_desc(intel_dp);
+
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
@@ -3616,8 +3605,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
if (!is_edp(intel_dp) && !intel_dp->sink_count)
return false;
- if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_PRESENT))
+ if (!drm_dp_is_branch(intel_dp->dpcd))
return true; /* native DP sink */
if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
@@ -3631,23 +3619,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
return true;
}
-static void
-intel_dp_probe_oui(struct intel_dp *intel_dp)
-{
- u8 buf[3];
-
- if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
- return;
-
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
- DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
- buf[0], buf[1], buf[2]);
-
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
- DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
- buf[0], buf[1], buf[2]);
-}
-
static bool
intel_dp_can_mst(struct intel_dp *intel_dp)
{
@@ -3691,7 +3662,7 @@ intel_dp_configure_mst(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 drm_device *dev = dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
int ret = 0;
@@ -3712,7 +3683,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
}
do {
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
if (drm_dp_dpcd_readb(&intel_dp->aux,
DP_TEST_SINK_MISC, &buf) < 0) {
@@ -3735,7 +3706,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
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 drm_device *dev = dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
int ret;
@@ -3763,14 +3734,14 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
return -EIO;
}
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
return 0;
}
int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
{
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 = to_i915(dig_port->base.base.dev);
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
int count, ret;
@@ -3781,7 +3752,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
return ret;
do {
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
if (drm_dp_dpcd_readb(&intel_dp->aux,
DP_TEST_SINK_MISC, &buf) < 0) {
@@ -3998,6 +3969,31 @@ go_again:
}
static void
+intel_dp_retrain_link(struct intel_dp *intel_dp)
+{
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+
+ /* Suppress underruns caused by re-training */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
+ if (crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv,
+ intel_crtc_pch_transcoder(crtc), false);
+
+ intel_dp_start_link_train(intel_dp);
+ intel_dp_stop_link_train(intel_dp);
+
+ /* Keep underrun reporting disabled until things are stable */
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
+
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+ if (crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv,
+ intel_crtc_pch_transcoder(crtc), true);
+}
+
+static void
intel_dp_check_link_status(struct intel_dp *intel_dp)
{
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
@@ -4017,13 +4013,18 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
if (!to_intel_crtc(intel_encoder->base.crtc)->active)
return;
+ /* FIXME: we need to synchronize this sort of stuff with hardware
+ * readout */
+ if (WARN_ON_ONCE(!intel_dp->lane_count))
+ return;
+
/* if link training is requested we should perform it always */
if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
(!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
intel_encoder->base.name);
- intel_dp_start_link_train(intel_dp);
- intel_dp_stop_link_train(intel_dp);
+
+ intel_dp_retrain_link(intel_dp);
}
}
@@ -4105,7 +4106,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
return connector_status_connected;
/* if there's no downstream port, we're done */
- if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+ if (!drm_dp_is_branch(dpcd))
return connector_status_connected;
/* If we're HPD-aware, SINK_COUNT changes dynamically */
@@ -4396,10 +4397,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
intel_dp_print_rates(intel_dp);
- intel_dp_probe_oui(intel_dp);
-
- intel_dp_print_hw_revision(intel_dp);
- intel_dp_print_sw_revision(intel_dp);
+ intel_dp_read_desc(intel_dp);
intel_dp_configure_mst(intel_dp);
@@ -4755,11 +4753,16 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
void intel_dp_encoder_reset(struct drm_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+ struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
if (!HAS_DDI(dev_priv))
intel_dp->DP = I915_READ(intel_dp->output_reg);
+ if (IS_GEN9(dev_priv) && lspcon->active)
+ lspcon_resume(lspcon);
+
if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
return;
@@ -4866,15 +4869,13 @@ put_power:
}
/* check the VBT to see whether the eDP is on another port */
-bool intel_dp_is_edp(struct drm_device *dev, enum port port)
+bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/*
* 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)
+ if (INTEL_GEN(dev_priv) < 5)
return false;
if (port == PORT_A)
@@ -5073,7 +5074,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
(seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
/* Compute the divisor for the pp clock, simply match the Bspec
* formula. */
- if (IS_BROXTON(dev)) {
+ if (IS_BROXTON(dev_priv)) {
pp_div = I915_READ(regs.pp_ctrl);
pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK;
pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000)
@@ -5086,9 +5087,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
/* Haswell doesn't have any port selection bits for the panel
* power sequencer any more. */
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
port_sel = PANEL_PORT_SELECT_VLV(port);
- } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+ } else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
if (port == PORT_A)
port_sel = PANEL_PORT_SELECT_DPA;
else
@@ -5099,7 +5100,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_WRITE(regs.pp_on, pp_on);
I915_WRITE(regs.pp_off, pp_off);
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
I915_WRITE(regs.pp_ctrl, pp_div);
else
I915_WRITE(regs.pp_div, pp_div);
@@ -5107,7 +5108,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
I915_READ(regs.pp_on),
I915_READ(regs.pp_off),
- IS_BROXTON(dev) ?
+ IS_BROXTON(dev_priv) ?
(I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) :
I915_READ(regs.pp_div));
}
@@ -5115,7 +5116,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
static void intel_dp_pps_init(struct drm_device *dev,
struct intel_dp *intel_dp)
{
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
vlv_initial_power_sequencer_setup(intel_dp);
} else {
intel_dp_init_panel_power_sequencer(dev, intel_dp);
@@ -5474,7 +5477,7 @@ intel_dp_drrs_init(struct intel_connector *intel_connector,
INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
mutex_init(&dev_priv->drrs.mutex);
- if (INTEL_INFO(dev)->gen <= 6) {
+ if (INTEL_GEN(dev_priv) <= 6) {
DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
return NULL;
}
@@ -5585,7 +5588,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
mutex_unlock(&dev->mode_config.mutex);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
intel_dp->edp_notifier.notifier_call = edp_notify_handler;
register_reboot_notifier(&intel_dp->edp_notifier);
@@ -5594,7 +5597,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
* If the current pipe isn't valid, try the PPS pipe, and if that
* fails just assume pipe A.
*/
- if (IS_CHERRYVIEW(dev))
+ if (IS_CHERRYVIEW(dev_priv))
pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP);
else
pipe = PORT_TO_PIPE(intel_dp->DP);
@@ -5648,28 +5651,28 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
intel_dp->pps_pipe = INVALID_PIPE;
/* intel_dp vfuncs */
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
- else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
- else if (HAS_PCH_SPLIT(dev))
+ else if (HAS_PCH_SPLIT(dev_priv))
intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
else
intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
else
intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
/* Preserve the current hw state. */
intel_dp->DP = I915_READ(intel_dp->output_reg);
intel_dp->attached_connector = intel_connector;
- if (intel_dp_is_edp(dev, port))
+ if (intel_dp_is_edp(dev_priv, port))
type = DRM_MODE_CONNECTOR_eDP;
else
type = DRM_MODE_CONNECTOR_DisplayPort;
@@ -5683,7 +5686,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
intel_encoder->type = INTEL_OUTPUT_EDP;
/* eDP only on port B and/or C on vlv/chv */
- if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if (WARN_ON((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
is_edp(intel_dp) && port != PORT_B && port != PORT_C))
return false;
@@ -5704,7 +5707,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
intel_connector_attach_encoder(intel_connector, intel_encoder);
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
else
intel_connector->get_hw_state = intel_connector_get_hw_state;
@@ -5716,7 +5719,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
break;
case PORT_B:
intel_encoder->hpd_pin = HPD_PORT_B;
- if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
intel_encoder->hpd_pin = HPD_PORT_A;
break;
case PORT_C:
@@ -5733,7 +5736,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
}
/* init MST on ports that can support it */
- if (HAS_DP_MST(dev) && !is_edp(intel_dp) &&
+ if (HAS_DP_MST(dev_priv) && !is_edp(intel_dp) &&
(port == PORT_B || port == PORT_C || port == PORT_D))
intel_dp_mst_encoder_init(intel_dig_port,
intel_connector->base.base.id);
@@ -5750,7 +5753,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
* 0xd. Failure to do so will result in spurious interrupts being
* generated on the port when a cable is not attached.
*/
- if (IS_G4X(dev) && !IS_GM45(dev)) {
+ if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) {
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
}
@@ -5793,13 +5796,13 @@ bool intel_dp_init(struct drm_device *dev,
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
intel_encoder->suspend = intel_dp_encoder_suspend;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
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)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
intel_encoder->pre_enable = vlv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
@@ -5807,7 +5810,7 @@ bool intel_dp_init(struct drm_device *dev,
} else {
intel_encoder->pre_enable = g4x_pre_enable_dp;
intel_encoder->enable = g4x_enable_dp;
- if (INTEL_INFO(dev)->gen >= 5)
+ if (INTEL_GEN(dev_priv) >= 5)
intel_encoder->post_disable = ilk_post_disable_dp;
}
@@ -5816,7 +5819,7 @@ bool intel_dp_init(struct drm_device *dev,
intel_dig_port->max_lanes = 4;
intel_encoder->type = INTEL_OUTPUT_DP;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
if (port == PORT_D)
intel_encoder->crtc_mask = 1 << 2;
else
@@ -5825,6 +5828,7 @@ bool intel_dp_init(struct drm_device *dev,
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
}
intel_encoder->cloneable = 0;
+ intel_encoder->port = port;
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
dev_priv->hotplug.irq_port[port] = intel_dig_port;
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
index c438b02184cb..0048b520baf7 100644
--- a/drivers/gpu/drm/i915/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
@@ -225,9 +225,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
* Intel platforms that support HBR2 also support TPS3. TPS3 support is
* also mandatory for downstream devices that support HBR2. However, not
* all sinks follow the spec.
- *
- * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
- * supported in source but still not enabled.
*/
source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 54a9d7610d8f..b029d1026a28 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -43,7 +43,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int mst_pbn;
- pipe_config->dp_encoder_is_mst = true;
pipe_config->has_pch_encoder = false;
bpp = 24;
/*
@@ -523,6 +522,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum
DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe));
intel_encoder->type = INTEL_OUTPUT_DP_MST;
+ intel_encoder->port = intel_dig_port->port;
intel_encoder->crtc_mask = 0x7;
intel_encoder->cloneable = 0;
diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c
index 047f48748944..7a8e82dabbf2 100644
--- a/drivers/gpu/drm/i915/intel_dpio_phy.c
+++ b/drivers/gpu/drm/i915/intel_dpio_phy.c
@@ -23,6 +23,565 @@
#include "intel_drv.h"
+/**
+ * DOC: DPIO
+ *
+ * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI
+ * ports. DPIO is the name given to such a display PHY. These PHYs
+ * don't follow the standard programming model using direct MMIO
+ * registers, and instead their registers must be accessed trough IOSF
+ * sideband. VLV has one such PHY for driving ports B and C, and CHV
+ * adds another PHY for driving port D. Each PHY responds to specific
+ * IOSF-SB port.
+ *
+ * Each display PHY is made up of one or two channels. Each channel
+ * houses a common lane part which contains the PLL and other common
+ * logic. CH0 common lane also contains the IOSF-SB logic for the
+ * Common Register Interface (CRI) ie. the DPIO registers. CRI clock
+ * must be running when any DPIO registers are accessed.
+ *
+ * In addition to having their own registers, the PHYs are also
+ * controlled through some dedicated signals from the display
+ * controller. These include PLL reference clock enable, PLL enable,
+ * and CRI clock selection, for example.
+ *
+ * Eeach channel also has two splines (also called data lanes), and
+ * each spline is made up of one Physical Access Coding Sub-Layer
+ * (PCS) block and two TX lanes. So each channel has two PCS blocks
+ * and four TX lanes. The TX lanes are used as DP lanes or TMDS
+ * data/clock pairs depending on the output type.
+ *
+ * Additionally the PHY also contains an AUX lane with AUX blocks
+ * for each channel. This is used for DP AUX communication, but
+ * this fact isn't really relevant for the driver since AUX is
+ * controlled from the display controller side. No DPIO registers
+ * need to be accessed during AUX communication,
+ *
+ * Generally on VLV/CHV the common lane corresponds to the pipe and
+ * the spline (PCS/TX) corresponds to the port.
+ *
+ * For dual channel PHY (VLV/CHV):
+ *
+ * pipe A == CMN/PLL/REF CH0
+ *
+ * pipe B == CMN/PLL/REF CH1
+ *
+ * port B == PCS/TX CH0
+ *
+ * port C == PCS/TX CH1
+ *
+ * This is especially important when we cross the streams
+ * ie. drive port B with pipe B, or port C with pipe A.
+ *
+ * For single channel PHY (CHV):
+ *
+ * pipe C == CMN/PLL/REF CH0
+ *
+ * port D == PCS/TX CH0
+ *
+ * On BXT the entire PHY channel corresponds to the port. That means
+ * the PLL is also now associated with the port rather than the pipe,
+ * and so the clock needs to be routed to the appropriate transcoder.
+ * Port A PLL is directly connected to transcoder EDP and port B/C
+ * PLLs can be routed to any transcoder A/B/C.
+ *
+ * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
+ * digital port D (CHV) or port A (BXT). ::
+ *
+ *
+ * Dual channel PHY (VLV/CHV/BXT)
+ * ---------------------------------
+ * | CH0 | CH1 |
+ * | CMN/PLL/REF | CMN/PLL/REF |
+ * |---------------|---------------| Display PHY
+ * | PCS01 | PCS23 | PCS01 | PCS23 |
+ * |-------|-------|-------|-------|
+ * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
+ * ---------------------------------
+ * | DDI0 | DDI1 | DP/HDMI ports
+ * ---------------------------------
+ *
+ * Single channel PHY (CHV/BXT)
+ * -----------------
+ * | CH0 |
+ * | CMN/PLL/REF |
+ * |---------------| Display PHY
+ * | PCS01 | PCS23 |
+ * |-------|-------|
+ * |TX0|TX1|TX2|TX3|
+ * -----------------
+ * | DDI2 | DP/HDMI port
+ * -----------------
+ */
+
+/**
+ * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy
+ */
+struct bxt_ddi_phy_info {
+ /**
+ * @dual_channel: true if this phy has a second channel.
+ */
+ bool dual_channel;
+
+ /**
+ * @rcomp_phy: If -1, indicates this phy has its own rcomp resistor.
+ * Otherwise the GRC value will be copied from the phy indicated by
+ * this field.
+ */
+ enum dpio_phy rcomp_phy;
+
+ /**
+ * @channel: struct containing per channel information.
+ */
+ struct {
+ /**
+ * @port: which port maps to this channel.
+ */
+ enum port port;
+ } channel[2];
+};
+
+static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
+ [DPIO_PHY0] = {
+ .dual_channel = true,
+ .rcomp_phy = DPIO_PHY1,
+
+ .channel = {
+ [DPIO_CH0] = { .port = PORT_B },
+ [DPIO_CH1] = { .port = PORT_C },
+ }
+ },
+ [DPIO_PHY1] = {
+ .dual_channel = false,
+ .rcomp_phy = -1,
+
+ .channel = {
+ [DPIO_CH0] = { .port = PORT_A },
+ }
+ },
+};
+
+static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
+{
+ return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
+ BIT(phy_info->channel[DPIO_CH0].port);
+}
+
+void bxt_port_to_phy_channel(enum port port,
+ enum dpio_phy *phy, enum dpio_channel *ch)
+{
+ const struct bxt_ddi_phy_info *phy_info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) {
+ phy_info = &bxt_ddi_phy_info[i];
+
+ if (port == phy_info->channel[DPIO_CH0].port) {
+ *phy = i;
+ *ch = DPIO_CH0;
+ return;
+ }
+
+ if (phy_info->dual_channel &&
+ port == phy_info->channel[DPIO_CH1].port) {
+ *phy = i;
+ *ch = DPIO_CH1;
+ return;
+ }
+ }
+
+ WARN(1, "PHY not found for PORT %c", port_name(port));
+ *phy = DPIO_PHY0;
+ *ch = DPIO_CH0;
+}
+
+void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
+ enum port port, u32 margin, u32 scale,
+ u32 enable, u32 deemphasis)
+{
+ u32 val;
+ enum dpio_phy phy;
+ enum dpio_channel ch;
+
+ bxt_port_to_phy_channel(port, &phy, &ch);
+
+ /*
+ * While we write to the group register to program all lanes at once we
+ * can read only lane registers and we pick lanes 0/1 for that.
+ */
+ val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
+ val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
+ I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
+
+ val = I915_READ(BXT_PORT_TX_DW2_LN0(phy, ch));
+ val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
+ val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT;
+ I915_WRITE(BXT_PORT_TX_DW2_GRP(phy, ch), val);
+
+ val = I915_READ(BXT_PORT_TX_DW3_LN0(phy, ch));
+ val &= ~SCALE_DCOMP_METHOD;
+ if (enable)
+ 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(phy, ch), val);
+
+ val = I915_READ(BXT_PORT_TX_DW4_LN0(phy, ch));
+ val &= ~DE_EMPHASIS;
+ val |= deemphasis << DEEMPH_SHIFT;
+ I915_WRITE(BXT_PORT_TX_DW4_GRP(phy, ch), val);
+
+ val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
+ val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
+ I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
+}
+
+bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+ enum port port;
+
+ if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
+ return false;
+
+ if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+ (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
+ DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n",
+ phy);
+
+ return false;
+ }
+
+ if (phy_info->rcomp_phy == -1 &&
+ !(I915_READ(BXT_PORT_REF_DW3(phy)) & GRC_DONE)) {
+ DRM_DEBUG_DRIVER("DDI PHY %d powered, but GRC isn't done\n",
+ phy);
+
+ return false;
+ }
+
+ if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
+ DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n",
+ phy);
+
+ return false;
+ }
+
+ for_each_port_masked(port, bxt_phy_port_mask(phy_info)) {
+ u32 tmp = I915_READ(BXT_PHY_CTL(port));
+
+ if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
+ DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
+ "for port %c powered down "
+ "(PHY_CTL %08x)\n",
+ phy, port_name(port), tmp);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+ u32 val = I915_READ(BXT_PORT_REF_DW6(phy));
+
+ return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
+}
+
+static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ if (intel_wait_for_register(dev_priv,
+ BXT_PORT_REF_DW3(phy),
+ GRC_DONE, GRC_DONE,
+ 10))
+ DRM_ERROR("timeout waiting for PHY%d GRC\n", phy);
+}
+
+static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+ u32 val;
+
+ if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
+ /* Still read out the GRC value for state verification */
+ if (phy_info->rcomp_phy != -1)
+ dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy);
+
+ if (bxt_ddi_phy_verify_state(dev_priv, phy)) {
+ DRM_DEBUG_DRIVER("DDI PHY %d already enabled, "
+ "won't reprogram it\n", phy);
+
+ return;
+ }
+
+ DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, "
+ "force reprogramming it\n", phy);
+ }
+
+ val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
+ val |= GT_DISPLAY_POWER_ON(phy);
+ I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
+
+ /*
+ * The PHY registers start out inaccessible and respond to reads with
+ * all 1s. Eventually they become accessible as they power up, then
+ * the reserved bit will give the default 0. Poll on the reserved bit
+ * becoming 0 to find when the PHY is accessible.
+ * HW team confirmed that the time to reach phypowergood status is
+ * anywhere between 50 us and 100us.
+ */
+ if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+ (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
+ DRM_ERROR("timeout during PHY%d power on\n", phy);
+ }
+
+ /* Program PLL Rcomp code offset */
+ val = I915_READ(BXT_PORT_CL1CM_DW9(phy));
+ val &= ~IREF0RC_OFFSET_MASK;
+ val |= 0xE4 << IREF0RC_OFFSET_SHIFT;
+ I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val);
+
+ val = I915_READ(BXT_PORT_CL1CM_DW10(phy));
+ val &= ~IREF1RC_OFFSET_MASK;
+ val |= 0xE4 << IREF1RC_OFFSET_SHIFT;
+ I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val);
+
+ /* Program power gating */
+ val = I915_READ(BXT_PORT_CL1CM_DW28(phy));
+ val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN |
+ SUS_CLK_CONFIG;
+ I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);
+
+ if (phy_info->dual_channel) {
+ val = I915_READ(BXT_PORT_CL2CM_DW6(phy));
+ val |= DW6_OLDO_DYN_PWR_DOWN_EN;
+ I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val);
+ }
+
+ if (phy_info->rcomp_phy != -1) {
+ uint32_t grc_code;
+ /*
+ * PHY0 isn't connected to an RCOMP resistor so copy over
+ * the corresponding calibrated value from PHY1, and disable
+ * the automatic calibration on PHY0.
+ */
+ val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv,
+ phy_info->rcomp_phy);
+ grc_code = val << GRC_CODE_FAST_SHIFT |
+ val << GRC_CODE_SLOW_SHIFT |
+ val;
+ I915_WRITE(BXT_PORT_REF_DW6(phy), grc_code);
+
+ val = I915_READ(BXT_PORT_REF_DW8(phy));
+ val |= GRC_DIS | GRC_RDY_OVRD;
+ I915_WRITE(BXT_PORT_REF_DW8(phy), val);
+ }
+
+ val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
+ val |= COMMON_RESET_DIS;
+ I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
+
+ if (phy_info->rcomp_phy == -1)
+ bxt_phy_wait_grc_done(dev_priv, phy);
+
+}
+
+void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+ uint32_t val;
+
+ val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
+ val &= ~COMMON_RESET_DIS;
+ I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
+
+ val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
+ val &= ~GT_DISPLAY_POWER_ON(phy);
+ I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
+}
+
+void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+ const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+ enum dpio_phy rcomp_phy = phy_info->rcomp_phy;
+ bool was_enabled;
+
+ lockdep_assert_held(&dev_priv->power_domains.lock);
+
+ if (rcomp_phy != -1) {
+ was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy);
+
+ /*
+ * We need to copy the GRC calibration value from rcomp_phy,
+ * so make sure it's powered up.
+ */
+ if (!was_enabled)
+ _bxt_ddi_phy_init(dev_priv, rcomp_phy);
+ }
+
+ _bxt_ddi_phy_init(dev_priv, phy);
+
+ if (rcomp_phy != -1 && !was_enabled)
+ bxt_ddi_phy_uninit(dev_priv, phy_info->rcomp_phy);
+}
+
+static bool __printf(6, 7)
+__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+ i915_reg_t reg, u32 mask, u32 expected,
+ const char *reg_fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ u32 val;
+
+ val = I915_READ(reg);
+ if ((val & mask) == expected)
+ return true;
+
+ va_start(args, reg_fmt);
+ vaf.fmt = reg_fmt;
+ vaf.va = &args;
+
+ DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: "
+ "current %08x, expected %08x (mask %08x)\n",
+ phy, &vaf, reg.reg, val, (val & ~mask) | expected,
+ mask);
+
+ va_end(args);
+
+ return false;
+}
+
+bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+ uint32_t mask;
+ bool ok;
+
+#define _CHK(reg, mask, exp, fmt, ...) \
+ __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \
+ ## __VA_ARGS__)
+
+ if (!bxt_ddi_phy_is_enabled(dev_priv, phy))
+ return false;
+
+ ok = true;
+
+ /* PLL Rcomp code offset */
+ ok &= _CHK(BXT_PORT_CL1CM_DW9(phy),
+ IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT,
+ "BXT_PORT_CL1CM_DW9(%d)", phy);
+ ok &= _CHK(BXT_PORT_CL1CM_DW10(phy),
+ IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT,
+ "BXT_PORT_CL1CM_DW10(%d)", phy);
+
+ /* Power gating */
+ mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG;
+ ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
+ "BXT_PORT_CL1CM_DW28(%d)", phy);
+
+ if (phy_info->dual_channel)
+ ok &= _CHK(BXT_PORT_CL2CM_DW6(phy),
+ DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
+ "BXT_PORT_CL2CM_DW6(%d)", phy);
+
+ if (phy_info->rcomp_phy != -1) {
+ u32 grc_code = dev_priv->bxt_phy_grc;
+
+ grc_code = grc_code << GRC_CODE_FAST_SHIFT |
+ grc_code << GRC_CODE_SLOW_SHIFT |
+ grc_code;
+ mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK |
+ GRC_CODE_NOM_MASK;
+ ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code,
+ "BXT_PORT_REF_DW6(%d)", phy);
+
+ mask = GRC_DIS | GRC_RDY_OVRD;
+ ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask,
+ "BXT_PORT_REF_DW8(%d)", phy);
+ }
+
+ return ok;
+#undef _CHK
+}
+
+uint8_t
+bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
+ uint8_t lane_count)
+{
+ switch (lane_count) {
+ case 1:
+ return 0;
+ case 2:
+ return BIT(2) | BIT(0);
+ case 4:
+ return BIT(3) | BIT(2) | BIT(0);
+ default:
+ MISSING_CASE(lane_count);
+
+ return 0;
+ }
+}
+
+void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
+ uint8_t lane_lat_optim_mask)
+{
+ struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+ struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
+ enum port port = dport->port;
+ enum dpio_phy phy;
+ enum dpio_channel ch;
+ int lane;
+
+ bxt_port_to_phy_channel(port, &phy, &ch);
+
+ for (lane = 0; lane < 4; lane++) {
+ u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
+
+ /*
+ * Note that on CHV this flag is called UPAR, but has
+ * the same function.
+ */
+ val &= ~LATENCY_OPTIM;
+ if (lane_lat_optim_mask & BIT(lane))
+ val |= LATENCY_OPTIM;
+
+ I915_WRITE(BXT_PORT_TX_DW14_LN(phy, ch, lane), val);
+ }
+}
+
+uint8_t
+bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+ struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
+ enum port port = dport->port;
+ enum dpio_phy phy;
+ enum dpio_channel ch;
+ int lane;
+ uint8_t mask;
+
+ bxt_port_to_phy_channel(port, &phy, &ch);
+
+ mask = 0;
+ for (lane = 0; lane < 4; lane++) {
+ u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
+
+ if (val & LATENCY_OPTIM)
+ mask |= BIT(lane);
+ }
+
+ return mask;
+}
+
+
void chv_set_phy_signal_level(struct intel_encoder *encoder,
u32 deemph_reg_value, u32 margin_reg_value,
bool uniq_trans_scale)
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 1c59ca50c430..58a756f2f224 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -188,13 +188,12 @@ out:
void intel_disable_shared_dpll(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll = crtc->config->shared_dpll;
unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
/* PCH only available on ILK+ */
- if (INTEL_INFO(dev)->gen < 5)
+ if (INTEL_GEN(dev_priv) < 5)
return;
if (pll == NULL)
@@ -1371,6 +1370,10 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
{
uint32_t temp;
enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
+ enum dpio_phy phy;
+ enum dpio_channel ch;
+
+ bxt_port_to_phy_channel(port, &phy, &ch);
/* Non-SSC reference */
temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
@@ -1378,72 +1381,72 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
/* Disable 10 bit clock */
- temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+ temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
- I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+ I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
/* Write P1 & P2 */
- temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
+ temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
temp |= pll->config.hw_state.ebb0;
- I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
+ I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
/* Write M2 integer */
- temp = I915_READ(BXT_PORT_PLL(port, 0));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
temp &= ~PORT_PLL_M2_MASK;
temp |= pll->config.hw_state.pll0;
- I915_WRITE(BXT_PORT_PLL(port, 0), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
/* Write N */
- temp = I915_READ(BXT_PORT_PLL(port, 1));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
temp &= ~PORT_PLL_N_MASK;
temp |= pll->config.hw_state.pll1;
- I915_WRITE(BXT_PORT_PLL(port, 1), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
/* Write M2 fraction */
- temp = I915_READ(BXT_PORT_PLL(port, 2));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
temp &= ~PORT_PLL_M2_FRAC_MASK;
temp |= pll->config.hw_state.pll2;
- I915_WRITE(BXT_PORT_PLL(port, 2), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
/* Write M2 fraction enable */
- temp = I915_READ(BXT_PORT_PLL(port, 3));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
temp &= ~PORT_PLL_M2_FRAC_ENABLE;
temp |= pll->config.hw_state.pll3;
- I915_WRITE(BXT_PORT_PLL(port, 3), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
/* Write coeff */
- temp = I915_READ(BXT_PORT_PLL(port, 6));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
temp &= ~PORT_PLL_PROP_COEFF_MASK;
temp &= ~PORT_PLL_INT_COEFF_MASK;
temp &= ~PORT_PLL_GAIN_CTL_MASK;
temp |= pll->config.hw_state.pll6;
- I915_WRITE(BXT_PORT_PLL(port, 6), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
/* Write calibration val */
- temp = I915_READ(BXT_PORT_PLL(port, 8));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
temp &= ~PORT_PLL_TARGET_CNT_MASK;
temp |= pll->config.hw_state.pll8;
- I915_WRITE(BXT_PORT_PLL(port, 8), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
- temp = I915_READ(BXT_PORT_PLL(port, 9));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
temp |= pll->config.hw_state.pll9;
- I915_WRITE(BXT_PORT_PLL(port, 9), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
- temp = I915_READ(BXT_PORT_PLL(port, 10));
+ temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
temp &= ~PORT_PLL_DCO_AMP_MASK;
temp |= pll->config.hw_state.pll10;
- I915_WRITE(BXT_PORT_PLL(port, 10), temp);
+ I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
/* Recalibrate with new settings */
- temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+ temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
temp |= PORT_PLL_RECALIBRATE;
- I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+ I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
temp |= pll->config.hw_state.ebb4;
- I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+ I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
/* Enable PLL */
temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
@@ -1459,11 +1462,11 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
* While we write to the group register to program all lanes at once we
* can read only lane registers and we pick lanes 0/1 for that.
*/
- temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+ temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
temp &= ~LANE_STAGGER_MASK;
temp &= ~LANESTAGGER_STRAP_OVRD;
temp |= pll->config.hw_state.pcsdw12;
- I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
+ I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
}
static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
@@ -1485,6 +1488,10 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
uint32_t val;
bool ret;
+ enum dpio_phy phy;
+ enum dpio_channel ch;
+
+ bxt_port_to_phy_channel(port, &phy, &ch);
if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
return false;
@@ -1495,36 +1502,36 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
if (!(val & PORT_PLL_ENABLE))
goto out;
- hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
+ hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
- hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
+ hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
- hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
+ hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
hw_state->pll0 &= PORT_PLL_M2_MASK;
- hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
+ hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
hw_state->pll1 &= PORT_PLL_N_MASK;
- hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
+ hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
- hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
+ hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
- hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
+ hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
PORT_PLL_INT_COEFF_MASK |
PORT_PLL_GAIN_CTL_MASK;
- hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
+ hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
- hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
+ hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
- hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
+ hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
PORT_PLL_DCO_AMP_MASK;
@@ -1533,11 +1540,11 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
* can read only lane registers. We configure all lanes the same way, so
* 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)
+ hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
+ if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != 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)));
+ I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
ret = true;
@@ -1851,13 +1858,13 @@ void intel_shared_dpll_init(struct drm_device *dev)
const struct dpll_info *dpll_info;
int i;
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
dpll_mgr = &skl_pll_mgr;
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
dpll_mgr = &bxt_pll_mgr;
- else if (HAS_DDI(dev))
+ else if (HAS_DDI(dev_priv))
dpll_mgr = &hsw_pll_mgr;
- else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+ else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
dpll_mgr = &pch_pll_mgr;
if (!dpll_mgr) {
@@ -1883,7 +1890,7 @@ void intel_shared_dpll_init(struct drm_device *dev)
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
/* FIXME: Move this to a more suitable place */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
intel_ddi_pll_init(dev);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a19ec06f9e42..cd132c216a67 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -206,6 +206,7 @@ struct intel_encoder {
struct drm_encoder base;
enum intel_output_type type;
+ enum port port;
unsigned int cloneable;
void (*hot_plug)(struct intel_encoder *);
bool (*compute_config)(struct intel_encoder *,
@@ -247,6 +248,8 @@ struct intel_encoder {
void (*suspend)(struct intel_encoder *);
int crtc_mask;
enum hpd_pin hpd_pin;
+ /* for communication with audio component; protected by av_mutex */
+ const struct drm_connector *audio_connector;
};
struct intel_panel {
@@ -291,6 +294,9 @@ struct intel_connector {
*/
struct intel_encoder *encoder;
+ /* ACPI device id for ACPI and driver cooperation */
+ u32 acpi_device_id;
+
/* Reads out the current hw, returning true if the connector is enabled
* and active (i.e. dpms ON state). */
bool (*get_hw_state)(struct intel_connector *);
@@ -362,6 +368,8 @@ struct intel_atomic_state {
/* Gen9+ only */
struct skl_wm_values wm_results;
+
+ struct i915_sw_fence commit_ready;
};
struct intel_plane_state {
@@ -398,9 +406,6 @@ struct intel_plane_state {
int scaler_id;
struct drm_intel_sprite_colorkey ckey;
-
- /* async flip related structures */
- struct drm_i915_gem_request *wait_req;
};
struct intel_initial_plane_config {
@@ -465,9 +470,13 @@ struct intel_pipe_wm {
bool sprites_scaled;
};
-struct skl_pipe_wm {
+struct skl_plane_wm {
struct skl_wm_level wm[8];
struct skl_wm_level trans_wm;
+};
+
+struct skl_pipe_wm {
+ struct skl_plane_wm planes[I915_MAX_PLANES];
uint32_t linetime;
};
@@ -493,14 +502,7 @@ struct intel_crtc_wm_state {
struct {
/* gen9+ only needs 1-step wm programming */
struct skl_pipe_wm optimal;
-
- /* cached plane data rate */
- unsigned plane_data_rate[I915_MAX_PLANES];
- unsigned plane_y_data_rate[I915_MAX_PLANES];
-
- /* minimum block allocation */
- uint16_t minimum_blocks[I915_MAX_PLANES];
- uint16_t minimum_y_blocks[I915_MAX_PLANES];
+ struct skl_ddb_entry ddb;
} skl;
};
@@ -653,7 +655,6 @@ struct intel_crtc_state {
bool double_wide;
- bool dp_encoder_is_mst;
int pbn;
struct intel_crtc_scaler_state scaler_state;
@@ -723,7 +724,6 @@ struct intel_crtc {
/* watermarks currently being used */
union {
struct intel_pipe_wm ilk;
- struct skl_pipe_wm skl;
} active;
/* allow CxSR on this pipe */
@@ -796,22 +796,22 @@ struct intel_plane {
};
struct intel_watermark_params {
- unsigned long fifo_size;
- unsigned long max_wm;
- unsigned long default_wm;
- unsigned long guard_size;
- unsigned long cacheline_size;
+ u16 fifo_size;
+ u16 max_wm;
+ u8 default_wm;
+ u8 guard_size;
+ u8 cacheline_size;
};
struct cxsr_latency {
- int is_desktop;
- int is_ddr3;
- unsigned long fsb_freq;
- unsigned long mem_freq;
- unsigned long display_sr;
- unsigned long display_hpll_disable;
- unsigned long cursor_sr;
- unsigned long cursor_hpll_disable;
+ bool is_desktop : 1;
+ bool is_ddr3 : 1;
+ u16 fsb_freq;
+ u16 mem_freq;
+ u16 display_sr;
+ u16 display_hpll_disable;
+ u16 cursor_sr;
+ u16 cursor_hpll_disable;
};
#define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base)
@@ -872,6 +872,14 @@ enum link_m_n_set {
M2_N2
};
+struct intel_dp_desc {
+ u8 oui[3];
+ u8 device_id[6];
+ u8 hw_rev;
+ u8 sw_major_rev;
+ u8 sw_minor_rev;
+} __packed;
+
struct intel_dp {
i915_reg_t output_reg;
i915_reg_t aux_ch_ctl_reg;
@@ -894,6 +902,8 @@ struct intel_dp {
/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
uint8_t num_sink_rates;
int sink_rates[DP_MAX_SUPPORTED_RATES];
+ /* sink or branch descriptor */
+ struct intel_dp_desc desc;
struct drm_dp_aux aux;
uint8_t train_set[4];
int panel_power_up_delay;
@@ -950,17 +960,22 @@ struct intel_dp {
bool compliance_test_active;
};
+struct intel_lspcon {
+ bool active;
+ enum drm_lspcon_mode mode;
+ bool desc_valid;
+};
+
struct intel_digital_port {
struct intel_encoder base;
enum port port;
u32 saved_port_bits;
struct intel_dp dp;
struct intel_hdmi hdmi;
+ struct intel_lspcon lspcon;
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
bool release_cl2_override;
uint8_t max_lanes;
- /* for communication with audio component; protected by av_mutex */
- const struct drm_connector *audio_connector;
};
struct intel_dp_mst_encoder {
@@ -1012,17 +1027,15 @@ vlv_pipe_to_channel(enum pipe pipe)
}
}
-static inline struct drm_crtc *
-intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
+static inline struct intel_crtc *
+intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
return dev_priv->pipe_to_crtc_mapping[pipe];
}
-static inline struct drm_crtc *
-intel_get_crtc_for_plane(struct drm_device *dev, int plane)
+static inline struct intel_crtc *
+intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum plane plane)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
return dev_priv->plane_to_crtc_mapping[plane];
}
@@ -1082,15 +1095,6 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
return container_of(intel_hdmi, struct intel_digital_port, hdmi);
}
-/*
- * Returns the number of planes for this pipe, ie the number of sprites + 1
- * (primary plane). This doesn't count the cursor plane then.
- */
-static inline unsigned int intel_num_planes(struct intel_crtc *crtc)
-{
- return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1;
-}
-
/* intel_fifo_underrun.c */
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum pipe pipe, bool enable);
@@ -1107,6 +1111,9 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
/* i915_irq.c */
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 mask);
+void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
+void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv);
@@ -1129,6 +1136,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
unsigned int pipe_mask);
void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
unsigned int pipe_mask);
+void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv);
+void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv);
+void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv);
/* intel_crt.c */
void intel_crt_init(struct drm_device *dev);
@@ -1176,12 +1186,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
/* intel_audio.c */
void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
-void intel_audio_codec_enable(struct intel_encoder *encoder);
+void intel_audio_codec_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state);
void intel_audio_codec_disable(struct intel_encoder *encoder);
void i915_audio_component_init(struct drm_i915_private *dev_priv);
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
/* intel_display.c */
+enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
void intel_update_rawclk(struct drm_i915_private *dev_priv);
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
@@ -1230,18 +1243,17 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
(1 << INTEL_OUTPUT_EDP));
}
static inline void
-intel_wait_for_vblank(struct drm_device *dev, int pipe)
+intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- drm_wait_one_vblank(dev, pipe);
+ drm_wait_one_vblank(&dev_priv->drm, pipe);
}
static inline void
-intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe)
+intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, int pipe)
{
- const struct intel_crtc *crtc =
- to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+ const struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc->active)
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev_priv, pipe);
}
u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
@@ -1285,21 +1297,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
uint64_t fb_modifier, unsigned int cpp);
-static inline bool
-intel_rotation_90_or_270(unsigned int rotation)
-{
- return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270);
-}
-
-void intel_create_rotation_property(struct drm_device *dev,
- struct intel_plane *plane);
-
void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe);
-int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
+int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll);
-void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
+void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
/* modesetting asserts */
@@ -1327,12 +1330,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv);
void hsw_disable_pc8(struct drm_i915_private *dev_priv);
void bxt_init_cdclk(struct drm_i915_private *dev_priv);
void bxt_uninit_cdclk(struct drm_i915_private *dev_priv);
-void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
- enum dpio_phy phy);
-bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
- enum dpio_phy phy);
void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv);
void bxt_enable_dc9(struct drm_i915_private *dev_priv);
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
@@ -1350,7 +1347,7 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
struct dpll *best_clock);
int chv_calc_dpll_params(int refclk, struct dpll *pll_clock);
-bool intel_crtc_active(struct drm_crtc *crtc);
+bool intel_crtc_active(struct intel_crtc *crtc);
void hsw_enable_ips(struct intel_crtc *crtc);
void hsw_disable_ips(struct intel_crtc *crtc);
enum intel_display_power_domain
@@ -1396,7 +1393,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc);
bool intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state);
-bool intel_dp_is_edp(struct drm_device *dev, enum port port);
+bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port);
enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
bool long_hpd);
void intel_edp_backlight_on(struct intel_dp *intel_dp);
@@ -1443,6 +1440,11 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
return ~((1 << lane_count) - 1) & 0xf;
}
+bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
+bool __intel_dp_read_desc(struct intel_dp *intel_dp,
+ struct intel_dp_desc *desc);
+bool intel_dp_read_desc(struct intel_dp *intel_dp);
+
/* intel_dp_aux_backlight.c */
int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
@@ -1487,6 +1489,10 @@ static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bo
{
}
+static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
+{
+}
+
static inline void intel_fbdev_restore_mode(struct drm_device *dev)
{
}
@@ -1513,6 +1519,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);
void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
+void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv);
/* intel_hdmi.c */
void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port);
@@ -1642,23 +1649,6 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access");
}
-static inline int
-assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
-{
- int seq = atomic_read(&dev_priv->pm.atomic_seq);
-
- assert_rpm_wakelock_held(dev_priv);
-
- return seq;
-}
-
-static inline void
-assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
-{
- WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
- "HW access outside of RPM atomic section\n");
-}
-
/**
* disable_rpm_wakeref_asserts - disable the RPM assert checks
* @dev_priv: i915 device instance
@@ -1714,11 +1704,11 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
/* intel_pm.c */
-void intel_init_clock_gating(struct drm_device *dev);
-void intel_suspend_hw(struct drm_device *dev);
-int ilk_wm_max_level(const struct drm_device *dev);
-void intel_update_watermarks(struct drm_crtc *crtc);
-void intel_init_pm(struct drm_device *dev);
+void intel_init_clock_gating(struct drm_i915_private *dev_priv);
+void intel_suspend_hw(struct drm_i915_private *dev_priv);
+int ilk_wm_max_level(const struct drm_i915_private *dev_priv);
+void intel_update_watermarks(struct intel_crtc *crtc);
+void intel_init_pm(struct drm_i915_private *dev_priv);
void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv);
void intel_pm_setup(struct drm_device *dev);
void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
@@ -1742,21 +1732,16 @@ void ilk_wm_get_hw_state(struct drm_device *dev);
void skl_wm_get_hw_state(struct drm_device *dev);
void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
struct skl_ddb_allocation *ddb /* out */);
+void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+ struct skl_pipe_wm *out);
bool intel_can_enable_sagv(struct drm_atomic_state *state);
int intel_enable_sagv(struct drm_i915_private *dev_priv);
int intel_disable_sagv(struct drm_i915_private *dev_priv);
-bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old,
- const struct skl_ddb_allocation *new,
- enum pipe pipe);
-bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state,
- const struct skl_ddb_allocation *old,
- const struct skl_ddb_allocation *new,
- enum pipe pipe);
-void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
- const struct skl_wm_values *wm);
-void skl_write_plane_wm(struct intel_crtc *intel_crtc,
- const struct skl_wm_values *wm,
- int plane);
+bool skl_wm_level_equals(const struct skl_wm_level *l1,
+ const struct skl_wm_level *l2);
+bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
+ const struct skl_ddb_entry *ddb,
+ int ignore);
uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
bool ilk_disable_lp_wm(struct drm_device *dev);
int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6);
@@ -1773,7 +1758,8 @@ bool intel_sdvo_init(struct drm_device *dev,
/* intel_sprite.c */
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
-int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
+struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
+ 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);
@@ -1835,4 +1821,7 @@ int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
void intel_color_set_csc(struct drm_crtc_state *crtc_state);
void intel_color_load_luts(struct drm_crtc_state *crtc_state);
+/* intel_lspcon.c */
+bool lspcon_init(struct intel_digital_port *intel_dig_port);
+void lspcon_resume(struct intel_lspcon *lspcon);
#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index b2e3d3a334f7..5b72c50d6f76 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -437,11 +437,11 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder)
static void intel_dsi_device_ready(struct intel_encoder *encoder)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_dsi_device_ready(encoder);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
bxt_dsi_device_ready(encoder);
}
@@ -464,7 +464,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
}
for_each_dsi_port(port, intel_dsi->ports) {
- i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
u32 temp;
@@ -494,7 +494,7 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
- i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
u32 temp;
@@ -656,7 +656,6 @@ 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 = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
@@ -664,7 +663,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
DRM_DEBUG_KMS("\n");
for_each_dsi_port(port, intel_dsi->ports) {
/* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */
- i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A);
u32 val;
@@ -741,7 +740,6 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
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;
enum port port;
bool active = false;
@@ -762,7 +760,7 @@ 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) {
- i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
+ i915_reg_t ctrl_reg = IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
@@ -771,7 +769,8 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
* bit in port C control register does not get set. As a
* workaround, check pipe B conf instead.
*/
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && port == PORT_C)
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ port == PORT_C)
enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE;
/* Try command mode if video mode not enabled */
@@ -970,11 +969,11 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
static void intel_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 pclk;
DRM_DEBUG_KMS("\n");
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
bxt_dsi_get_pipe_config(encoder, pipe_config);
pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
@@ -1066,7 +1065,7 @@ 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)) {
+ if (IS_BROXTON(dev_priv)) {
/*
* Program hdisplay and vdisplay on MIPI transcoder.
* This is different from calculated hactive and
@@ -1138,7 +1137,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
}
for_each_dsi_port(port, intel_dsi->ports) {
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
/*
* escape clock divider, 20MHz, shared for A and C.
* device ready must be off when doing this! txclkesc?
@@ -1153,7 +1152,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
tmp &= ~READ_REQUEST_PRIORITY_MASK;
I915_WRITE(MIPI_CTRL(port), tmp |
READ_REQUEST_PRIORITY_HIGH);
- } else if (IS_BROXTON(dev)) {
+ } else if (IS_BROXTON(dev_priv)) {
enum pipe pipe = intel_crtc->pipe;
tmp = I915_READ(MIPI_CTRL(port));
@@ -1242,7 +1241,7 @@ 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)) {
+ if (IS_BROXTON(dev_priv) && (!intel_dsi->dual_link)) {
/*
* BXT spec says write MIPI_INIT_COUNT for
* both the ports, even if only one is
@@ -1299,12 +1298,6 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
}
}
-static enum drm_connector_status
-intel_dsi_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static int intel_dsi_get_modes(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -1346,7 +1339,7 @@ static int intel_dsi_set_property(struct drm_connector *connector,
DRM_DEBUG_KMS("no scaling not supported\n");
return -EINVAL;
}
- if (HAS_GMCH_DISPLAY(dev) &&
+ if (HAS_GMCH_DISPLAY(to_i915(dev)) &&
val == DRM_MODE_SCALE_CENTER) {
DRM_DEBUG_KMS("centering not supported\n");
return -EINVAL;
@@ -1408,7 +1401,6 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs
static const struct drm_connector_funcs intel_dsi_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
- .detect = intel_dsi_detect,
.late_register = intel_connector_register,
.early_unregister = intel_connector_unregister,
.destroy = intel_dsi_connector_destroy,
@@ -1450,9 +1442,9 @@ void intel_dsi_init(struct drm_device *dev)
if (!intel_bios_is_dsi_present(dev_priv, &port))
return;
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
- } else if (IS_BROXTON(dev)) {
+ } else if (IS_BROXTON(dev_priv)) {
dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
} else {
DRM_ERROR("Unsupported Mipi device to reg base");
@@ -1488,6 +1480,7 @@ void intel_dsi_init(struct drm_device *dev)
intel_connector->get_hw_state = intel_connector_get_hw_state;
+ intel_encoder->port = port;
/*
* On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
* port C. BXT isn't limited like this.
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
index cd154ce6b6c1..0d8ff0034b88 100644
--- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
@@ -126,6 +126,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
u16 len;
enum port port;
+ DRM_DEBUG_KMS("\n");
+
flags = *data++;
type = *data++;
@@ -199,6 +201,8 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data)
{
u32 delay = *((const u32 *) data);
+ DRM_DEBUG_KMS("\n");
+
usleep_range(delay, delay + 10);
data += 4;
@@ -307,6 +311,8 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
u8 gpio_source, gpio_index;
bool value;
+ DRM_DEBUG_KMS("\n");
+
if (dev_priv->vbt.dsi.seq_version >= 3)
data++;
@@ -331,18 +337,36 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
return data;
}
-static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data)
+static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data)
{
+ DRM_DEBUG_KMS("Skipping I2C element execution\n");
+
return data + *(data + 6) + 7;
}
+static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data)
+{
+ DRM_DEBUG_KMS("Skipping SPI element execution\n");
+
+ return data + *(data + 5) + 6;
+}
+
+static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data)
+{
+ DRM_DEBUG_KMS("Skipping PMIC element execution\n");
+
+ return data + 15;
+}
+
typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi,
const u8 *data);
static const fn_mipi_elem_exec exec_elem[] = {
[MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet,
[MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay,
[MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio,
- [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip,
+ [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c,
+ [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi,
+ [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic,
};
/*
@@ -385,11 +409,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id)
return;
data = dev_priv->vbt.dsi.sequence[seq_id];
- if (!data) {
- DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n",
- seq_id, sequence_name(seq_id));
+ if (!data)
return;
- }
WARN_ON(*data != seq_id);
@@ -420,7 +441,15 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id)
operation_size = *data++;
if (mipi_elem_exec) {
+ const u8 *next = data + operation_size;
+
data = mipi_elem_exec(intel_dsi, data);
+
+ /* Consistency check if we have size. */
+ if (operation_size && data != next) {
+ DRM_ERROR("Inconsistent operation size\n");
+ return;
+ }
} else if (operation_size) {
/* We have size, skip. */
DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n",
@@ -438,6 +467,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id)
static int vbt_panel_prepare(struct drm_panel *panel)
{
generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET);
+ generic_exec_sequence(panel, MIPI_SEQ_POWER_ON);
+ generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET);
generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP);
return 0;
@@ -445,7 +476,8 @@ static int vbt_panel_prepare(struct drm_panel *panel)
static int vbt_panel_unprepare(struct drm_panel *panel)
{
- generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET);
+ generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET);
+ generic_exec_sequence(panel, MIPI_SEQ_POWER_OFF);
return 0;
}
@@ -453,12 +485,14 @@ static int vbt_panel_unprepare(struct drm_panel *panel)
static int vbt_panel_enable(struct drm_panel *panel)
{
generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON);
+ generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_ON);
return 0;
}
static int vbt_panel_disable(struct drm_panel *panel)
{
+ generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_OFF);
generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF);
return 0;
@@ -740,9 +774,8 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
8);
intel_dsi->clk_hs_to_lp_count += extra_byte_count;
- DRM_DEBUG_KMS("Eot %s\n", intel_dsi->eotp_pkt ? "enabled" : "disabled");
- DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ?
- "disabled" : "enabled");
+ DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt));
+ DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop));
DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
@@ -761,8 +794,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
DRM_DEBUG_KMS("BTA %s\n",
- intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA ?
- "disabled" : "enabled");
+ enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
/* delays in VBT are in unit of 100us, so need to convert
* here in ms
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index 6ab58a01b18e..56eff6004bc0 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -351,7 +351,7 @@ static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
struct intel_crtc_state *config)
{
- if (IS_BROXTON(encoder->base.dev))
+ if (IS_BROXTON(to_i915(encoder->base.dev)))
return bxt_dsi_get_pclk(encoder, pipe_bpp, config);
else
return vlv_dsi_get_pclk(encoder, pipe_bpp, config);
@@ -515,11 +515,11 @@ bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
int intel_compute_dsi_pll(struct intel_encoder *encoder,
struct intel_crtc_state *config)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return vlv_compute_dsi_pll(encoder, config);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
return bxt_compute_dsi_pll(encoder, config);
return -ENODEV;
@@ -528,21 +528,21 @@ int intel_compute_dsi_pll(struct intel_encoder *encoder,
void intel_enable_dsi_pll(struct intel_encoder *encoder,
const struct intel_crtc_state *config)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_enable_dsi_pll(encoder, config);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
bxt_enable_dsi_pll(encoder, config);
}
void intel_disable_dsi_pll(struct intel_encoder *encoder)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_disable_dsi_pll(encoder);
- else if (IS_BROXTON(dev))
+ else if (IS_BROXTON(dev_priv))
bxt_disable_dsi_pll(encoder);
}
@@ -564,10 +564,10 @@ static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
bxt_dsi_reset_clocks(encoder, port);
- else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
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 2e452c505e7e..708645443046 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -393,12 +393,12 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
* its timings to get how the BIOS set up the panel.
*/
if (dvo_val & DVO_ENABLE) {
- struct drm_crtc *crtc;
+ struct intel_crtc *crtc;
int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0;
- crtc = intel_get_crtc_for_pipe(dev, pipe);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc) {
- mode = intel_crtc_mode_get(dev, crtc);
+ mode = intel_crtc_mode_get(dev, &crtc->base);
if (mode) {
mode->type |= DRM_MODE_TYPE_PREFERRED;
if (dvo_val & DVO_HSYNC_ACTIVE_HIGH)
@@ -412,16 +412,14 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
return mode;
}
-static char intel_dvo_port_name(i915_reg_t dvo_reg)
+static enum port intel_dvo_port(i915_reg_t dvo_reg)
{
if (i915_mmio_reg_equal(dvo_reg, DVOA))
- return 'A';
+ return PORT_A;
else if (i915_mmio_reg_equal(dvo_reg, DVOB))
- return 'B';
- else if (i915_mmio_reg_equal(dvo_reg, DVOC))
- return 'C';
+ return PORT_B;
else
- return '?';
+ return PORT_C;
}
void intel_dvo_init(struct drm_device *dev)
@@ -464,6 +462,7 @@ void intel_dvo_init(struct drm_device *dev)
bool dvoinit;
enum pipe pipe;
uint32_t dpll[I915_MAX_PIPES];
+ enum port port;
/* Allow the I2C driver info to specify the GPIO to be used in
* special cases, but otherwise default to what's defined
@@ -511,12 +510,15 @@ void intel_dvo_init(struct drm_device *dev)
if (!dvoinit)
continue;
+ port = intel_dvo_port(dvo->dvo_reg);
drm_encoder_init(dev, &intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type,
- "DVO %c", intel_dvo_port_name(dvo->dvo_reg));
+ "DVO %c", port_name(port));
intel_encoder->type = INTEL_OUTPUT_DVO;
+ intel_encoder->port = port;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 025e232a4205..3da4d466e332 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -82,12 +82,17 @@ static const struct engine_info {
},
};
-static struct intel_engine_cs *
+static int
intel_engine_setup(struct drm_i915_private *dev_priv,
enum intel_engine_id id)
{
const struct engine_info *info = &intel_engines[id];
- struct intel_engine_cs *engine = &dev_priv->engine[id];
+ struct intel_engine_cs *engine;
+
+ GEM_BUG_ON(dev_priv->engine[id]);
+ engine = kzalloc(sizeof(*engine), GFP_KERNEL);
+ if (!engine)
+ return -ENOMEM;
engine->id = id;
engine->i915 = dev_priv;
@@ -97,7 +102,11 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
engine->mmio_base = info->mmio_base;
engine->irq_shift = info->irq_shift;
- return engine;
+ /* Nothing to do here, execute in order of dependencies */
+ engine->schedule = NULL;
+
+ dev_priv->engine[id] = engine;
+ return 0;
}
/**
@@ -110,13 +119,16 @@ int intel_engines_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
+ unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
unsigned int mask = 0;
int (*init)(struct intel_engine_cs *engine);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
unsigned int i;
int ret;
- WARN_ON(INTEL_INFO(dev_priv)->ring_mask == 0);
- WARN_ON(INTEL_INFO(dev_priv)->ring_mask &
+ WARN_ON(ring_mask == 0);
+ WARN_ON(ring_mask &
GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
@@ -131,7 +143,11 @@ int intel_engines_init(struct drm_device *dev)
if (!init)
continue;
- ret = init(intel_engine_setup(dev_priv, i));
+ ret = intel_engine_setup(dev_priv, i);
+ if (ret)
+ goto cleanup;
+
+ ret = init(dev_priv->engine[i]);
if (ret)
goto cleanup;
@@ -143,7 +159,7 @@ int intel_engines_init(struct drm_device *dev)
* are added to the driver by a warning and disabling the forgotten
* engines.
*/
- if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask))
+ if (WARN_ON(mask != ring_mask))
device_info->ring_mask = mask;
device_info->num_rings = hweight32(mask);
@@ -151,17 +167,17 @@ int intel_engines_init(struct drm_device *dev)
return 0;
cleanup:
- for (i = 0; i < I915_NUM_ENGINES; i++) {
+ for_each_engine(engine, dev_priv, id) {
if (i915.enable_execlists)
- intel_logical_ring_cleanup(&dev_priv->engine[i]);
+ intel_logical_ring_cleanup(engine);
else
- intel_engine_cleanup(&dev_priv->engine[i]);
+ intel_engine_cleanup(engine);
}
return ret;
}
-void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
+void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
{
struct drm_i915_private *dev_priv = engine->i915;
@@ -191,13 +207,13 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
I915_NUM_ENGINES * gen8_semaphore_seqno_size);
kunmap(page);
}
- memset(engine->semaphore.sync_seqno, 0,
- sizeof(engine->semaphore.sync_seqno));
intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
if (engine->irq_seqno_barrier)
engine->irq_seqno_barrier(engine);
- engine->last_submitted_seqno = seqno;
+
+ GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request));
+ engine->timeline->last_submitted_seqno = seqno;
engine->hangcheck.seqno = seqno;
@@ -207,15 +223,9 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
intel_engine_wakeup(engine);
}
-void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
-{
- memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
-}
-
-static void intel_engine_init_requests(struct intel_engine_cs *engine)
+static void intel_engine_init_timeline(struct intel_engine_cs *engine)
{
- init_request_active(&engine->last_request, NULL);
- INIT_LIST_HEAD(&engine->request_list);
+ engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
}
/**
@@ -229,12 +239,10 @@ static void intel_engine_init_requests(struct intel_engine_cs *engine)
*/
void intel_engine_setup_common(struct intel_engine_cs *engine)
{
- INIT_LIST_HEAD(&engine->execlist_queue);
- spin_lock_init(&engine->execlist_lock);
-
- engine->fence_context = fence_context_alloc(1);
+ engine->execlist_queue = RB_ROOT;
+ engine->execlist_first = NULL;
- intel_engine_init_requests(engine);
+ intel_engine_init_timeline(engine);
intel_engine_init_hangcheck(engine);
i915_gem_batch_pool_init(engine, &engine->batch_pool);
@@ -251,7 +259,7 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)
obj = i915_gem_object_create_stolen(&engine->i915->drm, size);
if (!obj)
- obj = i915_gem_object_create(&engine->i915->drm, size);
+ obj = i915_gem_object_create_internal(engine->i915, size);
if (IS_ERR(obj)) {
DRM_ERROR("Failed to allocate scratch page\n");
return PTR_ERR(obj);
@@ -301,6 +309,10 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
if (ret)
return ret;
+ ret = i915_gem_render_state_init(engine);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -315,7 +327,142 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
{
intel_engine_cleanup_scratch(engine);
+ i915_gem_render_state_fini(engine);
intel_engine_fini_breadcrumbs(engine);
intel_engine_cleanup_cmd_parser(engine);
i915_gem_batch_pool_fini(&engine->batch_pool);
}
+
+u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ u64 acthd;
+
+ if (INTEL_GEN(dev_priv) >= 8)
+ acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
+ RING_ACTHD_UDW(engine->mmio_base));
+ else if (INTEL_GEN(dev_priv) >= 4)
+ acthd = I915_READ(RING_ACTHD(engine->mmio_base));
+ else
+ acthd = I915_READ(ACTHD);
+
+ return acthd;
+}
+
+u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ u64 bbaddr;
+
+ if (INTEL_GEN(dev_priv) >= 8)
+ bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base),
+ RING_BBADDR_UDW(engine->mmio_base));
+ else
+ bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
+
+ return bbaddr;
+}
+
+const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
+{
+ switch (type) {
+ case I915_CACHE_NONE: return " uncached";
+ case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
+ case I915_CACHE_L3_LLC: return " L3+LLC";
+ case I915_CACHE_WT: return " WT";
+ default: return "";
+ }
+}
+
+static inline uint32_t
+read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
+ int subslice, i915_reg_t reg)
+{
+ uint32_t mcr;
+ uint32_t ret;
+ enum forcewake_domains fw_domains;
+
+ fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg,
+ FW_REG_READ);
+ fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
+ GEN8_MCR_SELECTOR,
+ FW_REG_READ | FW_REG_WRITE);
+
+ spin_lock_irq(&dev_priv->uncore.lock);
+ intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
+
+ mcr = I915_READ_FW(GEN8_MCR_SELECTOR);
+ /*
+ * The HW expects the slice and sublice selectors to be reset to 0
+ * after reading out the registers.
+ */
+ WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK));
+ mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
+ mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
+ I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
+
+ ret = I915_READ_FW(reg);
+
+ mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
+ I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
+
+ intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
+ spin_unlock_irq(&dev_priv->uncore.lock);
+
+ return ret;
+}
+
+/* NB: please notice the memset */
+void intel_engine_get_instdone(struct intel_engine_cs *engine,
+ struct intel_instdone *instdone)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ u32 mmio_base = engine->mmio_base;
+ int slice;
+ int subslice;
+
+ memset(instdone, 0, sizeof(*instdone));
+
+ switch (INTEL_GEN(dev_priv)) {
+ default:
+ instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+ if (engine->id != RCS)
+ break;
+
+ instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
+ instdone->sampler[slice][subslice] =
+ read_subslice_reg(dev_priv, slice, subslice,
+ GEN7_SAMPLER_INSTDONE);
+ instdone->row[slice][subslice] =
+ read_subslice_reg(dev_priv, slice, subslice,
+ GEN7_ROW_INSTDONE);
+ }
+ break;
+ case 7:
+ instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+ if (engine->id != RCS)
+ break;
+
+ instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
+ instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE);
+ instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE);
+
+ break;
+ case 6:
+ case 5:
+ case 4:
+ instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+ if (engine->id == RCS)
+ /* HACK: Using the wrong struct member */
+ instdone->slice_common = I915_READ(GEN4_INSTDONE1);
+ break;
+ case 3:
+ case 2:
+ instdone->instdone = I915_READ(GEN2_INSTDONE);
+ break;
+ }
+}
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index c43dd9abce79..62f215b12eb5 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -48,17 +48,17 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv)
static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
{
- return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
+ return IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8;
}
static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv)
{
- return INTEL_INFO(dev_priv)->gen < 4;
+ return INTEL_GEN(dev_priv) < 4;
}
static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv)
{
- return INTEL_INFO(dev_priv)->gen <= 3;
+ return INTEL_GEN(dev_priv) <= 3;
}
/*
@@ -84,7 +84,7 @@ static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,
{
int w, h;
- if (intel_rotation_90_or_270(cache->plane.rotation)) {
+ if (drm_rotation_90_or_270(cache->plane.rotation)) {
w = cache->plane.src_h;
h = cache->plane.src_w;
} else {
@@ -351,7 +351,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv)
{
- if (INTEL_INFO(dev_priv)->gen >= 5)
+ if (INTEL_GEN(dev_priv) >= 5)
return ilk_fbc_is_active(dev_priv);
else if (IS_GM45(dev_priv))
return g4x_fbc_is_active(dev_priv);
@@ -365,9 +365,9 @@ static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv)
fbc->active = true;
- if (INTEL_INFO(dev_priv)->gen >= 7)
+ if (INTEL_GEN(dev_priv) >= 7)
gen7_fbc_activate(dev_priv);
- else if (INTEL_INFO(dev_priv)->gen >= 5)
+ else if (INTEL_GEN(dev_priv) >= 5)
ilk_fbc_activate(dev_priv);
else if (IS_GM45(dev_priv))
g4x_fbc_activate(dev_priv);
@@ -381,7 +381,7 @@ static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv)
fbc->active = false;
- if (INTEL_INFO(dev_priv)->gen >= 5)
+ if (INTEL_GEN(dev_priv) >= 5)
ilk_fbc_deactivate(dev_priv);
else if (IS_GM45(dev_priv))
g4x_fbc_deactivate(dev_priv);
@@ -561,7 +561,7 @@ again:
ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
4096, 0, end);
- if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
+ if (ret && INTEL_GEN(dev_priv) <= 4) {
return 0;
} else if (ret) {
compression_threshold <<= 1;
@@ -594,7 +594,7 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
fbc->threshold = ret;
- if (INTEL_INFO(dev_priv)->gen >= 5)
+ if (INTEL_GEN(dev_priv) >= 5)
I915_WRITE(ILK_DPFC_CB_BASE, fbc->compressed_fb.start);
else if (IS_GM45(dev_priv)) {
I915_WRITE(DPFC_CB_BASE, fbc->compressed_fb.start);
@@ -708,10 +708,10 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
struct intel_fbc *fbc = &dev_priv->fbc;
unsigned int effective_w, effective_h, max_w, max_h;
- if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
+ if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) {
max_w = 4096;
max_h = 4096;
- } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
+ } else if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
max_w = 4096;
max_h = 2048;
} else {
@@ -776,6 +776,14 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache;
+ /* We don't need to use a state cache here since this information is
+ * global for all CRTC.
+ */
+ if (fbc->underrun_detected) {
+ fbc->no_fbc_reason = "underrun detected";
+ return false;
+ }
+
if (!cache->plane.visible) {
fbc->no_fbc_reason = "primary plane not visible";
return false;
@@ -804,7 +812,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
fbc->no_fbc_reason = "framebuffer not tiled or fenced";
return false;
}
- if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
+ if (INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv) &&
cache->plane.rotation != DRM_ROTATE_0) {
fbc->no_fbc_reason = "rotation unsupported";
return false;
@@ -846,9 +854,8 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return true;
}
-static bool intel_fbc_can_choose(struct intel_crtc *crtc)
+static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_fbc *fbc = &dev_priv->fbc;
if (intel_vgpu_active(dev_priv)) {
@@ -861,13 +868,8 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
return false;
}
- if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
- fbc->no_fbc_reason = "no enabled pipes can have FBC";
- return false;
- }
-
- if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) {
- fbc->no_fbc_reason = "no enabled planes can have FBC";
+ if (fbc->underrun_detected) {
+ fbc->no_fbc_reason = "underrun detected";
return false;
}
@@ -1053,23 +1055,19 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv,
struct drm_atomic_state *state)
{
struct intel_fbc *fbc = &dev_priv->fbc;
- struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
struct drm_plane *plane;
struct drm_plane_state *plane_state;
- bool fbc_crtc_present = false;
- int i, j;
+ bool crtc_chosen = false;
+ int i;
mutex_lock(&fbc->lock);
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- if (fbc->crtc == to_intel_crtc(crtc)) {
- fbc_crtc_present = true;
- break;
- }
- }
- /* This atomic commit doesn't involve the CRTC currently tied to FBC. */
- if (!fbc_crtc_present && fbc->crtc != NULL)
+ /* Does this atomic commit involve the CRTC currently tied to FBC? */
+ if (fbc->crtc &&
+ !drm_atomic_get_existing_crtc_state(state, &fbc->crtc->base))
+ goto out;
+
+ if (!intel_fbc_can_enable(dev_priv))
goto out;
/* Simply choose the first CRTC that is compatible and has a visible
@@ -1079,25 +1077,29 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv,
for_each_plane_in_state(state, plane, plane_state, i) {
struct intel_plane_state *intel_plane_state =
to_intel_plane_state(plane_state);
+ struct intel_crtc_state *intel_crtc_state;
+ struct intel_crtc *crtc = to_intel_crtc(plane_state->crtc);
if (!intel_plane_state->base.visible)
continue;
- for_each_crtc_in_state(state, crtc, crtc_state, j) {
- struct intel_crtc_state *intel_crtc_state =
- to_intel_crtc_state(crtc_state);
+ if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
+ continue;
- if (plane_state->crtc != crtc)
- continue;
+ if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A)
+ continue;
- if (!intel_fbc_can_choose(to_intel_crtc(crtc)))
- break;
+ intel_crtc_state = to_intel_crtc_state(
+ drm_atomic_get_existing_crtc_state(state, &crtc->base));
- intel_crtc_state->enable_fbc = true;
- goto out;
- }
+ intel_crtc_state->enable_fbc = true;
+ crtc_chosen = true;
+ break;
}
+ if (!crtc_chosen)
+ fbc->no_fbc_reason = "no suitable CRTC for FBC";
+
out:
mutex_unlock(&fbc->lock);
}
@@ -1223,6 +1225,59 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv)
cancel_work_sync(&fbc->work.work);
}
+static void intel_fbc_underrun_work_fn(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, fbc.underrun_work);
+ struct intel_fbc *fbc = &dev_priv->fbc;
+
+ mutex_lock(&fbc->lock);
+
+ /* Maybe we were scheduled twice. */
+ if (fbc->underrun_detected)
+ goto out;
+
+ DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n");
+ fbc->underrun_detected = true;
+
+ intel_fbc_deactivate(dev_priv);
+out:
+ mutex_unlock(&fbc->lock);
+}
+
+/**
+ * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
+ * @dev_priv: i915 device instance
+ *
+ * Without FBC, most underruns are harmless and don't really cause too many
+ * problems, except for an annoying message on dmesg. With FBC, underruns can
+ * become black screens or even worse, especially when paired with bad
+ * watermarks. So in order for us to be on the safe side, completely disable FBC
+ * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe
+ * already suggests that watermarks may be bad, so try to be as safe as
+ * possible.
+ *
+ * This function is called from the IRQ handler.
+ */
+void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv)
+{
+ struct intel_fbc *fbc = &dev_priv->fbc;
+
+ if (!fbc_supported(dev_priv))
+ return;
+
+ /* There's no guarantee that underrun_detected won't be set to true
+ * right after this check and before the work is scheduled, but that's
+ * not a problem since we'll check it again under the work function
+ * while FBC is locked. This check here is just to prevent us from
+ * unnecessarily scheduling the work, and it relies on the fact that we
+ * never switch underrun_detect back to false after it's true. */
+ if (READ_ONCE(fbc->underrun_detected))
+ return;
+
+ schedule_work(&fbc->underrun_work);
+}
+
/**
* intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking
* @dev_priv: i915 device instance
@@ -1240,7 +1295,7 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
return;
for_each_intel_crtc(&dev_priv->drm, crtc)
- if (intel_crtc_active(&crtc->base) &&
+ if (intel_crtc_active(crtc) &&
to_intel_plane_state(crtc->base.primary->state)->base.visible)
dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
}
@@ -1294,6 +1349,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
enum pipe pipe;
INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
+ INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
mutex_init(&fbc->lock);
fbc->enabled = false;
fbc->active = false;
@@ -1319,7 +1375,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
}
/* This value was pulled out of someone's hat */
- if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv))
+ if (INTEL_GEN(dev_priv) <= 4 && !IS_GM45(dev_priv))
I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
/* We still don't have any sort of hardware state readout for FBC, so
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index b7098f98bb67..beb08982dc0b 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -102,16 +102,13 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
static struct fb_ops intelfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_set_par = intel_fbdev_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_pan_display = intel_fbdev_pan_display,
.fb_blank = intel_fbdev_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
static int intelfb_alloc(struct drm_fb_helper *helper,
@@ -359,7 +356,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
struct drm_fb_offset *offsets,
bool *enabled, int width, int height)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
unsigned long conn_configured, mask;
unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
int i, j;
@@ -512,7 +509,7 @@ retry:
* fbdev helper library.
*/
if (num_connectors_enabled != num_connectors_detected &&
- num_connectors_enabled < INTEL_INFO(dev)->num_pipes) {
+ num_connectors_enabled < INTEL_INFO(dev_priv)->num_pipes) {
DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
num_connectors_detected);
@@ -636,7 +633,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
cur_size = intel_fb_align_height(dev, cur_size,
fb->base.pixel_format,
- fb->base.modifier[0]);
+ fb->base.modifier);
cur_size *= fb->base.pitches[0];
DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
pipe_name(intel_crtc->pipe),
@@ -700,11 +697,11 @@ static void intel_fbdev_suspend_worker(struct work_struct *work)
int intel_fbdev_init(struct drm_device *dev)
{
- struct intel_fbdev *ifbdev;
struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_fbdev *ifbdev;
int ret;
- if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
+ if (WARN_ON(INTEL_INFO(dev_priv)->num_pipes == 0))
return -ENODEV;
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
@@ -717,7 +714,7 @@ int intel_fbdev_init(struct drm_device *dev)
ifbdev->preferred_bpp = 32;
ret = drm_fb_helper_init(dev, &ifbdev->helper,
- INTEL_INFO(dev)->num_pipes, 4);
+ INTEL_INFO(dev_priv)->num_pipes, 4);
if (ret) {
kfree(ifbdev);
return ret;
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 2aa744081f09..e660d8b4bbc3 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -57,7 +57,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
- crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc->cpu_fifo_underrun_disabled)
return false;
@@ -75,7 +75,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
- crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc->pch_fifo_underrun_disabled)
return false;
@@ -245,22 +245,21 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
bool old;
assert_spin_locked(&dev_priv->irq_lock);
- old = !intel_crtc->cpu_fifo_underrun_disabled;
- intel_crtc->cpu_fifo_underrun_disabled = !enable;
+ old = !crtc->cpu_fifo_underrun_disabled;
+ crtc->cpu_fifo_underrun_disabled = !enable;
- if (HAS_GMCH_DISPLAY(dev))
+ if (HAS_GMCH_DISPLAY(dev_priv))
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
- else if (IS_GEN5(dev) || IS_GEN6(dev))
+ else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
- else if (IS_GEN7(dev))
+ else if (IS_GEN7(dev_priv))
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
- else if (IS_GEN8(dev) || IS_GEN9(dev))
+ else if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv))
broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
return old;
@@ -314,8 +313,8 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder,
bool enable)
{
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc =
+ intel_get_crtc_for_pipe(dev_priv, (enum pipe) pch_transcoder);
unsigned long flags;
bool old;
@@ -330,8 +329,8 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
spin_lock_irqsave(&dev_priv->irq_lock, flags);
- old = !intel_crtc->pch_fifo_underrun_disabled;
- intel_crtc->pch_fifo_underrun_disabled = !enable;
+ old = !crtc->pch_fifo_underrun_disabled;
+ crtc->pch_fifo_underrun_disabled = !enable;
if (HAS_PCH_IBX(dev_priv))
ibx_set_fifo_underrun_reporting(&dev_priv->drm,
@@ -358,7 +357,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
/* We may be called too early in init, thanks BIOS! */
if (crtc == NULL)
@@ -366,12 +365,14 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
/* GMCH can't disable fifo underruns, filter them. */
if (HAS_GMCH_DISPLAY(dev_priv) &&
- to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
+ crtc->cpu_fifo_underrun_disabled)
return;
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
DRM_ERROR("CPU pipe %c FIFO underrun\n",
pipe_name(pipe));
+
+ intel_fbc_handle_fifo_underrun_irq(dev_priv);
}
/**
diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.h b/drivers/gpu/drm/i915/intel_frontbuffer.h
index 76ceb539f9f0..7bab41218cf7 100644
--- a/drivers/gpu/drm/i915/intel_frontbuffer.h
+++ b/drivers/gpu/drm/i915/intel_frontbuffer.h
@@ -53,16 +53,17 @@ void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
* until the rendering completes or a flip on this frontbuffer plane is
* scheduled.
*/
-static inline void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+static inline bool intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
unsigned int frontbuffer_bits;
frontbuffer_bits = atomic_read(&obj->frontbuffer_bits);
if (!frontbuffer_bits)
- return;
+ return false;
__intel_fb_obj_invalidate(obj, origin, frontbuffer_bits);
+ return true;
}
/**
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 5cdf7aa75be5..0053258e03d3 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -64,7 +64,7 @@ struct drm_i915_gem_request;
*/
struct i915_guc_client {
struct i915_vma *vma;
- void *client_base; /* first page (only) of above */
+ void *vaddr;
struct i915_gem_context *owner;
struct intel_guc *guc;
@@ -123,10 +123,28 @@ struct intel_guc_fw {
uint32_t ucode_offset;
};
+struct intel_guc_log {
+ uint32_t flags;
+ struct i915_vma *vma;
+ void *buf_addr;
+ struct workqueue_struct *flush_wq;
+ struct work_struct flush_work;
+ struct rchan *relay_chan;
+
+ /* logging related stats */
+ u32 capture_miss_count;
+ u32 flush_interrupt_count;
+ u32 prev_overflow_count[GUC_MAX_LOG_BUFFER];
+ u32 total_overflow_count[GUC_MAX_LOG_BUFFER];
+ u32 flush_count[GUC_MAX_LOG_BUFFER];
+};
+
struct intel_guc {
struct intel_guc_fw guc_fw;
- uint32_t log_flags;
- struct i915_vma *log_vma;
+ struct intel_guc_log log;
+
+ /* GuC2Host interrupt related state */
+ bool interrupts_enabled;
struct i915_vma *ads_vma;
struct i915_vma *ctx_pool_vma;
@@ -146,6 +164,9 @@ struct intel_guc {
uint64_t submissions[I915_NUM_ENGINES];
uint32_t last_seqno[I915_NUM_ENGINES];
+
+ /* To serialize the Host2GuC actions */
+ struct mutex action_lock;
};
/* intel_guc_loader.c */
@@ -163,5 +184,10 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *rq);
void i915_guc_wq_unreserve(struct drm_i915_gem_request *request);
void i915_guc_submission_disable(struct drm_i915_private *dev_priv);
void i915_guc_submission_fini(struct drm_i915_private *dev_priv);
+void i915_guc_capture_logs(struct drm_i915_private *dev_priv);
+void i915_guc_flush_logs(struct drm_i915_private *dev_priv);
+void i915_guc_register(struct drm_i915_private *dev_priv);
+void i915_guc_unregister(struct drm_i915_private *dev_priv);
+int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val);
#endif
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index e40db2d2ae99..324ea902558b 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -104,9 +104,9 @@
#define GUC_LOG_ALLOC_IN_MEGABYTE (1 << 3)
#define GUC_LOG_CRASH_PAGES 1
#define GUC_LOG_CRASH_SHIFT 4
-#define GUC_LOG_DPC_PAGES 3
+#define GUC_LOG_DPC_PAGES 7
#define GUC_LOG_DPC_SHIFT 6
-#define GUC_LOG_ISR_PAGES 3
+#define GUC_LOG_ISR_PAGES 7
#define GUC_LOG_ISR_SHIFT 9
#define GUC_LOG_BUF_ADDR_SHIFT 12
@@ -419,15 +419,87 @@ struct guc_ads {
u32 reserved2[4];
} __packed;
+/* GuC logging structures */
+
+enum guc_log_buffer_type {
+ GUC_ISR_LOG_BUFFER,
+ GUC_DPC_LOG_BUFFER,
+ GUC_CRASH_DUMP_LOG_BUFFER,
+ GUC_MAX_LOG_BUFFER
+};
+
+/**
+ * DOC: GuC Log buffer Layout
+ *
+ * Page0 +-------------------------------+
+ * | ISR state header (32 bytes) |
+ * | DPC state header |
+ * | Crash dump state header |
+ * Page1 +-------------------------------+
+ * | ISR logs |
+ * Page9 +-------------------------------+
+ * | DPC logs |
+ * Page17 +-------------------------------+
+ * | Crash Dump logs |
+ * +-------------------------------+
+ *
+ * Below state structure is used for coordination of retrieval of GuC firmware
+ * logs. Separate state is maintained for each log buffer type.
+ * read_ptr points to the location where i915 read last in log buffer and
+ * is read only for GuC firmware. write_ptr is incremented by GuC with number
+ * of bytes written for each log entry and is read only for i915.
+ * When any type of log buffer becomes half full, GuC sends a flush interrupt.
+ * GuC firmware expects that while it is writing to 2nd half of the buffer,
+ * first half would get consumed by Host and then get a flush completed
+ * acknowledgment from Host, so that it does not end up doing any overwrite
+ * causing loss of logs. So when buffer gets half filled & i915 has requested
+ * for interrupt, GuC will set flush_to_file field, set the sampled_write_ptr
+ * to the value of write_ptr and raise the interrupt.
+ * On receiving the interrupt i915 should read the buffer, clear flush_to_file
+ * field and also update read_ptr with the value of sample_write_ptr, before
+ * sending an acknowledgment to GuC. marker & version fields are for internal
+ * usage of GuC and opaque to i915. buffer_full_cnt field is incremented every
+ * time GuC detects the log buffer overflow.
+ */
+struct guc_log_buffer_state {
+ u32 marker[2];
+ u32 read_ptr;
+ u32 write_ptr;
+ u32 size;
+ u32 sampled_write_ptr;
+ union {
+ struct {
+ u32 flush_to_file:1;
+ u32 buffer_full_cnt:4;
+ u32 reserved:27;
+ };
+ u32 flags;
+ };
+ u32 version;
+} __packed;
+
+union guc_log_control {
+ struct {
+ u32 logging_enabled:1;
+ u32 reserved1:3;
+ u32 verbosity:4;
+ u32 reserved2:24;
+ };
+ u32 value;
+} __packed;
+
/* 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_LOG_BUFFER_FILE_FLUSH_COMPLETE = 0x30,
+ HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH = 0x302,
HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
+ HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING = 0x0E000,
HOST2GUC_ACTION_LIMIT
};
@@ -449,4 +521,10 @@ enum guc2host_status {
GUC2HOST_STATUS_GENERIC_FAIL = GUC2HOST_STATUS(0x0000F000)
};
+/* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */
+enum guc2host_message {
+ GUC2HOST_MSG_CRASH_DUMP_POSTED = (1 << 1),
+ GUC2HOST_MSG_FLUSH_LOG_BUFFER = (1 << 3)
+};
+
#endif
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 6fd39efb7894..34d6ad2cf7c1 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -100,12 +100,13 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status)
static void guc_interrupts_release(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int irqs;
/* tell all command streamers NOT to forward interrupts or vblank to GuC */
irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER);
irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MODE_GEN7(engine), irqs);
/* route all GT interrupts to the host */
@@ -117,12 +118,13 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv)
static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
int irqs;
u32 tmp;
/* tell all command streamers to forward interrupts (but not vblank) to GuC */
irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MODE_GEN7(engine), irqs);
/* route USER_INTERRUPT to Host, all others are sent to GuC. */
@@ -209,11 +211,13 @@ static void guc_params_init(struct drm_i915_private *dev_priv)
params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER |
GUC_CTL_VCS2_ENABLED;
+ params[GUC_CTL_LOG_PARAMS] = guc->log.flags;
+
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;
- }
+ } else
+ params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED;
if (guc->ads_vma) {
u32 ads = i915_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT;
@@ -347,7 +351,6 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
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->drm;
struct i915_vma *vma;
int ret;
@@ -375,24 +378,22 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
/* Enable MIA caching. GuC clock gating is disabled. */
I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
- /* WaDisableMinuteIaClockGating:skl,bxt */
- if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
+ /* WaDisableMinuteIaClockGating:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
~GUC_ENABLE_MIA_CLOCK_GATING));
}
- /* WaC6DisallowByGfxPause*/
- if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) ||
- IS_BXT_REVID(dev, 0, BXT_REVID_B0))
+ /* WaC6DisallowByGfxPause:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
I915_WRITE(GEN6_GFXPAUSE, 0x30FFF);
- if (IS_BROXTON(dev))
+ if (IS_BROXTON(dev_priv))
I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
else
I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
- if (IS_GEN9(dev)) {
+ if (IS_GEN9(dev_priv)) {
/* DOP Clock Gating Enable for GuC clocks */
I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE |
I915_READ(GEN7_MISCCPCTL)));
@@ -484,6 +485,7 @@ int intel_guc_setup(struct drm_device *dev)
}
guc_interrupts_release(dev_priv);
+ gen9_reset_guc_interrupts(dev_priv);
guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
@@ -528,6 +530,9 @@ int intel_guc_setup(struct drm_device *dev)
intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
if (i915.enable_guc_submission) {
+ if (i915.guc_log_level >= 0)
+ gen9_enable_guc_interrupts(dev_priv);
+
err = i915_guc_submission_enable(dev_priv);
if (err)
goto fail;
@@ -561,7 +566,7 @@ fail:
ret = 0;
}
- if (err == 0 && !HAS_GUC_UCODE(dev))
+ if (err == 0 && !HAS_GUC_UCODE(dev_priv))
; /* Don't mention the GuC! */
else if (err == 0)
DRM_INFO("GuC firmware load skipped\n");
@@ -720,23 +725,28 @@ void intel_guc_init(struct drm_device *dev)
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
const char *fw_path;
- /* A negative value means "use platform default" */
- if (i915.enable_guc_loading < 0)
- i915.enable_guc_loading = HAS_GUC_UCODE(dev);
- if (i915.enable_guc_submission < 0)
- i915.enable_guc_submission = HAS_GUC_SCHED(dev);
+ if (!HAS_GUC(dev_priv)) {
+ i915.enable_guc_loading = 0;
+ i915.enable_guc_submission = 0;
+ } else {
+ /* A negative value means "use platform default" */
+ if (i915.enable_guc_loading < 0)
+ i915.enable_guc_loading = HAS_GUC_UCODE(dev_priv);
+ if (i915.enable_guc_submission < 0)
+ i915.enable_guc_submission = HAS_GUC_SCHED(dev_priv);
+ }
- if (!HAS_GUC_UCODE(dev)) {
+ if (!HAS_GUC_UCODE(dev_priv)) {
fw_path = NULL;
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev_priv)) {
fw_path = I915_SKL_GUC_UCODE;
guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR;
guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR;
- } else if (IS_BROXTON(dev)) {
+ } else if (IS_BROXTON(dev_priv)) {
fw_path = I915_BXT_GUC_UCODE;
guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR;
guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR;
- } else if (IS_KABYLAKE(dev)) {
+ } else if (IS_KABYLAKE(dev_priv)) {
fw_path = I915_KBL_GUC_UCODE;
guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR;
guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR;
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c
index 434f4d5c553d..290384e86c63 100644
--- a/drivers/gpu/drm/i915/intel_gvt.c
+++ b/drivers/gpu/drm/i915/intel_gvt.c
@@ -31,14 +31,20 @@
* GPU among multiple virtual machines on a time-sharing basis. Each
* virtual machine is presented a virtual GPU (vGPU), which has equivalent
* features as the underlying physical GPU (pGPU), so i915 driver can run
- * seamlessly in a virtual machine. This file provides the englightments
- * of GVT and the necessary components used by GVT in i915 driver.
+ * seamlessly in a virtual machine.
+ *
+ * To virtualize GPU resources GVT-g driver depends on hypervisor technology
+ * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability
+ * and be virtualized within GVT-g device module. More architectural design
+ * doc is available on https://01.org/group/2230/documentation-list.
*/
static bool is_supported_device(struct drm_i915_private *dev_priv)
{
if (IS_BROADWELL(dev_priv))
return true;
+ if (IS_SKYLAKE(dev_priv))
+ return true;
return false;
}
diff --git a/drivers/gpu/drm/i915/intel_gvt.h b/drivers/gpu/drm/i915/intel_gvt.h
index 960211df74db..25df2d65b985 100644
--- a/drivers/gpu/drm/i915/intel_gvt.h
+++ b/drivers/gpu/drm/i915/intel_gvt.h
@@ -24,7 +24,7 @@
#ifndef _INTEL_GVT_H_
#define _INTEL_GVT_H_
-#include "gvt/gvt.h"
+struct intel_gvt;
#ifdef CONFIG_DRM_I915_GVT
int intel_gvt_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c
new file mode 100644
index 000000000000..53df5b11bff4
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_hangcheck.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright © 2016 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 "i915_drv.h"
+
+static bool
+ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr)
+{
+ if (INTEL_GEN(engine->i915) >= 8) {
+ return (ipehr >> 23) == 0x1c;
+ } else {
+ ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
+ return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
+ MI_SEMAPHORE_REGISTER);
+ }
+}
+
+static struct intel_engine_cs *
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
+ u64 offset)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct intel_engine_cs *signaller;
+ enum intel_engine_id id;
+
+ if (INTEL_GEN(dev_priv) >= 8) {
+ for_each_engine(signaller, dev_priv, id) {
+ if (engine == signaller)
+ continue;
+
+ if (offset == signaller->semaphore.signal_ggtt[engine->hw_id])
+ return signaller;
+ }
+ } else {
+ u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
+
+ for_each_engine(signaller, dev_priv, id) {
+ if(engine == signaller)
+ continue;
+
+ if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id])
+ return signaller;
+ }
+ }
+
+ DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n",
+ engine->name, ipehr, offset);
+
+ return ERR_PTR(-ENODEV);
+}
+
+static struct intel_engine_cs *
+semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ void __iomem *vaddr;
+ u32 cmd, ipehr, head;
+ 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 (engine->buffer == NULL)
+ return NULL;
+
+ ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+ if (!ipehr_is_semaphore_wait(engine, ipehr))
+ return NULL;
+
+ /*
+ * HEAD is likely pointing to the dword after the actual command,
+ * so scan backwards until we find the MBOX. But limit it to just 3
+ * or 4 dwords depending on the semaphore wait command size.
+ * Note that we don't care about ACTHD here since that might
+ * point at at batch, and semaphores are always emitted into the
+ * ringbuffer itself.
+ */
+ head = I915_READ_HEAD(engine) & HEAD_ADDR;
+ backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4;
+ vaddr = (void __iomem *)engine->buffer->vaddr;
+
+ for (i = backwards; i; --i) {
+ /*
+ * Be paranoid and presume the hw has gone off into the wild -
+ * our ring is smaller than what the hardware (and hence
+ * HEAD_ADDR) allows. Also handles wrap-around.
+ */
+ head &= engine->buffer->size - 1;
+
+ /* This here seems to blow up */
+ cmd = ioread32(vaddr + head);
+ if (cmd == ipehr)
+ break;
+
+ head -= 4;
+ }
+
+ if (!i)
+ return NULL;
+
+ *seqno = ioread32(vaddr + head + 4) + 1;
+ if (INTEL_GEN(dev_priv) >= 8) {
+ offset = ioread32(vaddr + head + 12);
+ offset <<= 32;
+ offset |= ioread32(vaddr + head + 8);
+ }
+ return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
+}
+
+static int semaphore_passed(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct intel_engine_cs *signaller;
+ u32 seqno;
+
+ engine->hangcheck.deadlock++;
+
+ signaller = semaphore_waits_for(engine, &seqno);
+ if (signaller == NULL)
+ return -1;
+
+ if (IS_ERR(signaller))
+ return 0;
+
+ /* Prevent pathological recursion due to driver bugs */
+ if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
+ return -1;
+
+ if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno))
+ return 1;
+
+ /* cursory check for an unkickable deadlock */
+ if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
+ semaphore_passed(signaller) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ for_each_engine(engine, dev_priv, id)
+ engine->hangcheck.deadlock = 0;
+}
+
+static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone)
+{
+ u32 tmp = current_instdone | *old_instdone;
+ bool unchanged;
+
+ unchanged = tmp == *old_instdone;
+ *old_instdone |= tmp;
+
+ return unchanged;
+}
+
+static bool subunits_stuck(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct intel_instdone instdone;
+ struct intel_instdone *accu_instdone = &engine->hangcheck.instdone;
+ bool stuck;
+ int slice;
+ int subslice;
+
+ if (engine->id != RCS)
+ return true;
+
+ intel_engine_get_instdone(engine, &instdone);
+
+ /* There might be unstable subunit states even when
+ * actual head is not moving. Filter out the unstable ones by
+ * accumulating the undone -> done transitions and only
+ * consider those as progress.
+ */
+ stuck = instdone_unchanged(instdone.instdone,
+ &accu_instdone->instdone);
+ stuck &= instdone_unchanged(instdone.slice_common,
+ &accu_instdone->slice_common);
+
+ for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
+ stuck &= instdone_unchanged(instdone.sampler[slice][subslice],
+ &accu_instdone->sampler[slice][subslice]);
+ stuck &= instdone_unchanged(instdone.row[slice][subslice],
+ &accu_instdone->row[slice][subslice]);
+ }
+
+ return stuck;
+}
+
+static enum intel_engine_hangcheck_action
+head_stuck(struct intel_engine_cs *engine, u64 acthd)
+{
+ if (acthd != engine->hangcheck.acthd) {
+
+ /* Clear subunit states on head movement */
+ memset(&engine->hangcheck.instdone, 0,
+ sizeof(engine->hangcheck.instdone));
+
+ return HANGCHECK_ACTIVE;
+ }
+
+ if (!subunits_stuck(engine))
+ return HANGCHECK_ACTIVE;
+
+ return HANGCHECK_HUNG;
+}
+
+static enum intel_engine_hangcheck_action
+engine_stuck(struct intel_engine_cs *engine, u64 acthd)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ enum intel_engine_hangcheck_action ha;
+ u32 tmp;
+
+ ha = head_stuck(engine, acthd);
+ if (ha != HANGCHECK_HUNG)
+ return ha;
+
+ if (IS_GEN2(dev_priv))
+ return HANGCHECK_HUNG;
+
+ /* Is the chip hanging on a WAIT_FOR_EVENT?
+ * If so we can simply poke the RB_WAIT bit
+ * and break the hang. This should work on
+ * all but the second generation chipsets.
+ */
+ tmp = I915_READ_CTL(engine);
+ if (tmp & RING_WAIT) {
+ i915_handle_error(dev_priv, 0,
+ "Kicking stuck wait on %s",
+ engine->name);
+ I915_WRITE_CTL(engine, tmp);
+ return HANGCHECK_KICK;
+ }
+
+ if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) {
+ switch (semaphore_passed(engine)) {
+ default:
+ return HANGCHECK_HUNG;
+ case 1:
+ i915_handle_error(dev_priv, 0,
+ "Kicking stuck semaphore on %s",
+ engine->name);
+ I915_WRITE_CTL(engine, tmp);
+ return HANGCHECK_KICK;
+ case 0:
+ return HANGCHECK_WAIT;
+ }
+ }
+
+ return HANGCHECK_HUNG;
+}
+
+/*
+ * This is called when the chip hasn't reported back with completed
+ * batchbuffers in a long time. We keep track per ring seqno progress and
+ * if there are no progress, hangcheck score for that ring is increased.
+ * Further, acthd is inspected to see if the ring is stuck. On stuck case
+ * we kick the ring. If we see no progress on three subsequent calls
+ * we assume chip is wedged and try to fix it by resetting the chip.
+ */
+static void i915_hangcheck_elapsed(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, typeof(*dev_priv),
+ gpu_error.hangcheck_work.work);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ unsigned int hung = 0, stuck = 0;
+ int busy_count = 0;
+#define BUSY 1
+#define KICK 5
+#define HUNG 20
+#define ACTIVE_DECAY 15
+
+ if (!i915.enable_hangcheck)
+ return;
+
+ if (!READ_ONCE(dev_priv->gt.awake))
+ return;
+
+ /* As enabling the GPU requires fairly extensive mmio access,
+ * periodically arm the mmio checker to see if we are triggering
+ * any invalid access.
+ */
+ intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
+
+ for_each_engine(engine, dev_priv, id) {
+ bool busy = intel_engine_has_waiter(engine);
+ u64 acthd;
+ u32 seqno;
+ u32 submit;
+
+ semaphore_clear_deadlocks(dev_priv);
+
+ /* We don't strictly need an irq-barrier here, as we are not
+ * serving an interrupt request, be paranoid in case the
+ * barrier has side-effects (such as preventing a broken
+ * cacheline snoop) and so be sure that we can see the seqno
+ * advance. If the seqno should stick, due to a stale
+ * cacheline, we would erroneously declare the GPU hung.
+ */
+ if (engine->irq_seqno_barrier)
+ engine->irq_seqno_barrier(engine);
+
+ acthd = intel_engine_get_active_head(engine);
+ seqno = intel_engine_get_seqno(engine);
+ submit = intel_engine_last_submit(engine);
+
+ if (engine->hangcheck.seqno == seqno) {
+ if (i915_seqno_passed(seqno, submit)) {
+ engine->hangcheck.action = HANGCHECK_IDLE;
+ } else {
+ /* We always increment the hangcheck score
+ * if the engine is busy and still processing
+ * the same request, so that no single request
+ * can run indefinitely (such as a chain of
+ * batches). The only time we do not increment
+ * the hangcheck score on this ring, if this
+ * engine is in a legitimate wait for another
+ * engine. In that case the waiting engine is a
+ * victim and we want to be sure we catch the
+ * right culprit. Then every time we do kick
+ * the ring, add a small increment to the
+ * score so that we can catch a batch that is
+ * being repeatedly kicked and so responsible
+ * for stalling the machine.
+ */
+ engine->hangcheck.action =
+ engine_stuck(engine, acthd);
+
+ switch (engine->hangcheck.action) {
+ case HANGCHECK_IDLE:
+ case HANGCHECK_WAIT:
+ break;
+ case HANGCHECK_ACTIVE:
+ engine->hangcheck.score += BUSY;
+ break;
+ case HANGCHECK_KICK:
+ engine->hangcheck.score += KICK;
+ break;
+ case HANGCHECK_HUNG:
+ engine->hangcheck.score += HUNG;
+ break;
+ }
+ }
+
+ if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
+ hung |= intel_engine_flag(engine);
+ if (engine->hangcheck.action != HANGCHECK_HUNG)
+ stuck |= intel_engine_flag(engine);
+ }
+ } else {
+ engine->hangcheck.action = HANGCHECK_ACTIVE;
+
+ /* Gradually reduce the count so that we catch DoS
+ * attempts across multiple batches.
+ */
+ if (engine->hangcheck.score > 0)
+ engine->hangcheck.score -= ACTIVE_DECAY;
+ if (engine->hangcheck.score < 0)
+ engine->hangcheck.score = 0;
+
+ /* Clear head and subunit states on seqno movement */
+ acthd = 0;
+
+ memset(&engine->hangcheck.instdone, 0,
+ sizeof(engine->hangcheck.instdone));
+ }
+
+ engine->hangcheck.seqno = seqno;
+ engine->hangcheck.acthd = acthd;
+ busy_count += busy;
+ }
+
+ if (hung) {
+ char msg[80];
+ unsigned int tmp;
+ int len;
+
+ /* If some rings hung but others were still busy, only
+ * blame the hanging rings in the synopsis.
+ */
+ if (stuck != hung)
+ hung &= ~stuck;
+ len = scnprintf(msg, sizeof(msg),
+ "%s on ", stuck == hung ? "No progress" : "Hang");
+ for_each_engine_masked(engine, dev_priv, hung, tmp)
+ len += scnprintf(msg + len, sizeof(msg) - len,
+ "%s, ", engine->name);
+ msg[len-2] = '\0';
+
+ return i915_handle_error(dev_priv, hung, msg);
+ }
+
+ /* Reset timer in case GPU hangs without another request being added */
+ if (busy_count)
+ i915_queue_hangcheck(dev_priv);
+}
+
+void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
+{
+ memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
+}
+
+void intel_hangcheck_init(struct drm_i915_private *i915)
+{
+ INIT_DELAYED_WORK(&i915->gpu_error.hangcheck_work,
+ i915_hangcheck_elapsed);
+}
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 13c306173f27..fb88e32e25a3 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -50,7 +50,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t enabled_bits;
- enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
+ enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits,
"HDMI port enabled, expecting disabled\n");
@@ -864,7 +864,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder)
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
hdmi_val = SDVO_ENCODING_HDMI;
- if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range)
+ if (!HAS_PCH_SPLIT(dev_priv) && 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;
@@ -879,9 +879,9 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder)
if (crtc->config->has_hdmi_sink)
hdmi_val |= HDMI_MODE_SELECT_HDMI;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
- else if (IS_CHERRYVIEW(dev))
+ else if (IS_CHERRYVIEW(dev_priv))
hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe);
else
hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
@@ -911,9 +911,9 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
if (!(tmp & SDVO_ENABLE))
goto out;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
*pipe = PORT_TO_PIPE_CPT(tmp);
- else if (IS_CHERRYVIEW(dev))
+ else if (IS_CHERRYVIEW(dev_priv))
*pipe = SDVO_PORT_TO_PIPE_CHV(tmp);
else
*pipe = PORT_TO_PIPE(tmp);
@@ -956,7 +956,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
if (tmp & SDVO_AUDIO_ENABLE)
pipe_config->has_audio = true;
- if (!HAS_PCH_SPLIT(dev) &&
+ if (!HAS_PCH_SPLIT(dev_priv) &&
tmp & HDMI_COLOR_RANGE_16_235)
pipe_config->limited_color_range = true;
@@ -975,14 +975,16 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
pipe_config->lane_count = 4;
}
-static void intel_enable_hdmi_audio(struct intel_encoder *encoder)
+static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state)
{
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
WARN_ON(!crtc->config->has_hdmi_sink);
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
pipe_name(crtc->pipe));
- intel_audio_codec_enable(encoder);
+ intel_audio_codec_enable(encoder, pipe_config, conn_state);
}
static void g4x_enable_hdmi(struct intel_encoder *encoder,
@@ -991,21 +993,20 @@ static void g4x_enable_hdmi(struct intel_encoder *encoder,
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
u32 temp;
temp = I915_READ(intel_hdmi->hdmi_reg);
temp |= SDVO_ENABLE;
- if (crtc->config->has_audio)
+ if (pipe_config->has_audio)
temp |= SDVO_AUDIO_ENABLE;
I915_WRITE(intel_hdmi->hdmi_reg, temp);
POSTING_READ(intel_hdmi->hdmi_reg);
- if (crtc->config->has_audio)
- intel_enable_hdmi_audio(encoder);
+ if (pipe_config->has_audio)
+ intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
}
static void ibx_enable_hdmi(struct intel_encoder *encoder,
@@ -1040,8 +1041,8 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder,
* FIXME: BSpec says this should be done at the end of
* of the modeset sequence, so not sure if this isn't too soon.
*/
- if (crtc->config->pipe_bpp > 24 &&
- crtc->config->pixel_multiplier > 1) {
+ if (pipe_config->pipe_bpp > 24 &&
+ pipe_config->pixel_multiplier > 1) {
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
POSTING_READ(intel_hdmi->hdmi_reg);
@@ -1055,8 +1056,8 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder,
POSTING_READ(intel_hdmi->hdmi_reg);
}
- if (crtc->config->has_audio)
- intel_enable_hdmi_audio(encoder);
+ if (pipe_config->has_audio)
+ intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
}
static void cpt_enable_hdmi(struct intel_encoder *encoder,
@@ -1073,7 +1074,7 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
temp = I915_READ(intel_hdmi->hdmi_reg);
temp |= SDVO_ENABLE;
- if (crtc->config->has_audio)
+ if (pipe_config->has_audio)
temp |= SDVO_AUDIO_ENABLE;
/*
@@ -1086,7 +1087,7 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
* 4. enable HDMI clock gating
*/
- if (crtc->config->pipe_bpp > 24) {
+ if (pipe_config->pipe_bpp > 24) {
I915_WRITE(TRANS_CHICKEN1(pipe),
I915_READ(TRANS_CHICKEN1(pipe)) |
TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
@@ -1098,7 +1099,7 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
I915_WRITE(intel_hdmi->hdmi_reg, temp);
POSTING_READ(intel_hdmi->hdmi_reg);
- if (crtc->config->pipe_bpp > 24) {
+ if (pipe_config->pipe_bpp > 24) {
temp &= ~SDVO_COLOR_FORMAT_MASK;
temp |= HDMI_COLOR_FORMAT_12bpc;
@@ -1110,8 +1111,8 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
}
- if (crtc->config->has_audio)
- intel_enable_hdmi_audio(encoder);
+ if (pipe_config->has_audio)
+ intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
}
static void vlv_enable_hdmi(struct intel_encoder *encoder,
@@ -1141,7 +1142,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder,
* to transcoder A after disabling it to allow the
* matching DP port to be enabled on transcoder A.
*/
- if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) {
+ if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
/*
* We get CPU/PCH FIFO underruns on the other pipe when
* doing the workaround. Sweep them under the rug.
@@ -1164,7 +1165,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder,
I915_WRITE(intel_hdmi->hdmi_reg, temp);
POSTING_READ(intel_hdmi->hdmi_reg);
- intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+ intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
@@ -1178,9 +1179,7 @@ static void g4x_disable_hdmi(struct intel_encoder *encoder,
struct intel_crtc_state *old_crtc_state,
struct drm_connector_state *old_conn_state)
{
- struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-
- if (crtc->config->has_audio)
+ if (old_crtc_state->has_audio)
intel_audio_codec_disable(encoder);
intel_disable_hdmi(encoder, old_crtc_state, old_conn_state);
@@ -1190,9 +1189,7 @@ static void pch_disable_hdmi(struct intel_encoder *encoder,
struct intel_crtc_state *old_crtc_state,
struct drm_connector_state *old_conn_state)
{
- struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-
- if (crtc->config->has_audio)
+ if (old_crtc_state->has_audio)
intel_audio_codec_disable(encoder);
}
@@ -1241,7 +1238,7 @@ static enum drm_mode_status
hdmi_port_clock_valid(struct intel_hdmi *hdmi,
int clock, bool respect_downstream_limits)
{
- struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+ struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi));
if (clock < 25000)
return MODE_CLOCK_LOW;
@@ -1249,11 +1246,11 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
return MODE_CLOCK_HIGH;
/* BXT DPLL can't generate 223-240 MHz */
- if (IS_BROXTON(dev) && clock > 223333 && clock < 240000)
+ if (IS_BROXTON(dev_priv) && clock > 223333 && clock < 240000)
return MODE_CLOCK_RANGE;
/* CHV DPLL can't generate 216-240 MHz */
- if (IS_CHERRYVIEW(dev) && clock > 216000 && clock < 240000)
+ if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
return MODE_CLOCK_RANGE;
return MODE_OK;
@@ -1265,6 +1262,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
{
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+ struct drm_i915_private *dev_priv = to_i915(dev);
enum drm_mode_status status;
int clock;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
@@ -1287,7 +1285,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
status = hdmi_port_clock_valid(hdmi, clock, true);
/* if we can't do 8bpc we may still be able to do 12bpc */
- if (!HAS_GMCH_DISPLAY(dev) && status != MODE_OK)
+ if (!HAS_GMCH_DISPLAY(dev_priv) && status != MODE_OK)
status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true);
return status;
@@ -1297,7 +1295,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
{
struct drm_device *dev = crtc_state->base.crtc->dev;
- if (HAS_GMCH_DISPLAY(dev))
+ if (HAS_GMCH_DISPLAY(to_i915(dev)))
return false;
/*
@@ -1312,7 +1310,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
int clock_12bpc = clock_8bpc * 3 / 2;
@@ -1339,7 +1337,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
clock_12bpc *= 2;
}
- if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
+ if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
pipe_config->has_pch_encoder = true;
if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio)
@@ -1644,13 +1642,12 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
- const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
intel_hdmi_prepare(encoder);
intel_hdmi->set_infoframes(&encoder->base,
- intel_crtc->config->has_hdmi_sink,
+ pipe_config->has_hdmi_sink,
adjusted_mode);
}
@@ -1662,9 +1659,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
struct intel_hdmi *intel_hdmi = &dport->hdmi;
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_crtc *intel_crtc =
- to_intel_crtc(encoder->base.crtc);
- const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
vlv_phy_pre_encoder_enable(encoder);
@@ -1673,7 +1668,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
0x2b247878);
intel_hdmi->set_infoframes(&encoder->base,
- intel_crtc->config->has_hdmi_sink,
+ pipe_config->has_hdmi_sink,
adjusted_mode);
g4x_enable_hdmi(encoder, pipe_config, conn_state);
@@ -1896,19 +1891,19 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
return;
}
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
intel_hdmi->write_infoframe = vlv_write_infoframe;
intel_hdmi->set_infoframes = vlv_set_infoframes;
intel_hdmi->infoframe_enabled = vlv_infoframe_enabled;
- } else if (IS_G4X(dev)) {
+ } else if (IS_G4X(dev_priv)) {
intel_hdmi->write_infoframe = g4x_write_infoframe;
intel_hdmi->set_infoframes = g4x_set_infoframes;
intel_hdmi->infoframe_enabled = g4x_infoframe_enabled;
- } else if (HAS_DDI(dev)) {
+ } else if (HAS_DDI(dev_priv)) {
intel_hdmi->write_infoframe = hsw_write_infoframe;
intel_hdmi->set_infoframes = hsw_set_infoframes;
intel_hdmi->infoframe_enabled = hsw_infoframe_enabled;
- } else if (HAS_PCH_IBX(dev)) {
+ } else if (HAS_PCH_IBX(dev_priv)) {
intel_hdmi->write_infoframe = ibx_write_infoframe;
intel_hdmi->set_infoframes = ibx_set_infoframes;
intel_hdmi->infoframe_enabled = ibx_infoframe_enabled;
@@ -1918,7 +1913,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_hdmi->infoframe_enabled = cpt_infoframe_enabled;
}
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
else
intel_connector->get_hw_state = intel_connector_get_hw_state;
@@ -1932,7 +1927,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
* 0xd. Failure to do so will result in spurious interrupts being
* generated on the port when a cable is not attached.
*/
- if (IS_G4X(dev) && !IS_GM45(dev)) {
+ if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) {
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
}
@@ -1941,6 +1936,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
void intel_hdmi_init(struct drm_device *dev,
i915_reg_t hdmi_reg, enum port port)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
@@ -1961,7 +1957,7 @@ void intel_hdmi_init(struct drm_device *dev,
DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port));
intel_encoder->compute_config = intel_hdmi_compute_config;
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
intel_encoder->disable = pch_disable_hdmi;
intel_encoder->post_disable = pch_post_disable_hdmi;
} else {
@@ -1969,29 +1965,30 @@ void intel_hdmi_init(struct drm_device *dev,
}
intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
intel_encoder->get_config = intel_hdmi_get_config;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev_priv)) {
intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable;
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)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
intel_encoder->pre_enable = vlv_hdmi_pre_enable;
intel_encoder->enable = vlv_enable_hdmi;
intel_encoder->post_disable = vlv_hdmi_post_disable;
} else {
intel_encoder->pre_enable = intel_hdmi_pre_enable;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
intel_encoder->enable = cpt_enable_hdmi;
- else if (HAS_PCH_IBX(dev))
+ else if (HAS_PCH_IBX(dev_priv))
intel_encoder->enable = ibx_enable_hdmi;
else
intel_encoder->enable = g4x_enable_hdmi;
}
intel_encoder->type = INTEL_OUTPUT_HDMI;
- if (IS_CHERRYVIEW(dev)) {
+ intel_encoder->port = port;
+ if (IS_CHERRYVIEW(dev_priv)) {
if (port == PORT_D)
intel_encoder->crtc_mask = 1 << 2;
else
@@ -2005,7 +2002,7 @@ void intel_hdmi_init(struct drm_device *dev,
* to work on real hardware. And since g4x can send infoframes to
* only one port anyway, nothing is lost by allowing it.
*/
- if (IS_G4X(dev))
+ if (IS_G4X(dev_priv))
intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
intel_dig_port->port = port;
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index 334d47b5811a..3d546c019de0 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -501,7 +501,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
if (intel_connector->mst_port)
continue;
- if (!connector->polled && I915_HAS_HOTPLUG(dev) &&
+ if (!connector->polled && I915_HAS_HOTPLUG(dev_priv) &&
intel_connector->encoder->hpd_pin > HPD_NONE) {
connector->polled = enabled ?
DRM_CONNECTOR_POLL_CONNECT |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 79aab9ad6faa..83f260bb4eef 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -138,11 +138,10 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
static u32 get_reserved(struct intel_gmbus *bus)
{
struct drm_i915_private *dev_priv = bus->dev_priv;
- struct drm_device *dev = &dev_priv->drm;
u32 reserved = 0;
/* On most chips, these bits must be preserved in software. */
- if (!IS_I830(dev) && !IS_845G(dev))
+ if (!IS_I830(dev_priv) && !IS_845G(dev_priv))
reserved = I915_READ_NOTRACE(bus->gpio_reg) &
(GPIO_DATA_PULLUP_DISABLE |
GPIO_CLOCK_PULLUP_DISABLE);
@@ -468,13 +467,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
struct intel_gmbus,
adapter);
struct drm_i915_private *dev_priv = bus->dev_priv;
- const unsigned int fw =
- intel_uncore_forcewake_for_reg(dev_priv, GMBUS0,
- FW_REG_READ | FW_REG_WRITE);
int i = 0, inc, try = 0;
int ret = 0;
- intel_uncore_forcewake_get(dev_priv, fw);
retry:
I915_WRITE_FW(GMBUS0, bus->reg0);
@@ -576,7 +571,6 @@ timeout:
ret = -EAGAIN;
out:
- intel_uncore_forcewake_put(dev_priv, fw);
return ret;
}
@@ -633,10 +627,10 @@ int intel_setup_gmbus(struct drm_device *dev)
unsigned int pin;
int ret;
- if (HAS_PCH_NOP(dev))
+ if (HAS_PCH_NOP(dev_priv))
return 0;
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
else if (!HAS_GMCH_DISPLAY(dev_priv))
dev_priv->gpio_mmio_base =
@@ -674,7 +668,7 @@ int intel_setup_gmbus(struct drm_device *dev)
bus->reg0 = pin | GMBUS_RATE_100KHZ;
/* gmbus seems to be broken on i830 */
- if (IS_I830(dev))
+ if (IS_I830(dev_priv))
bus->force_bit = 1;
intel_gpio_setup(bus, pin);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 0adb879833ff..0a09024d6ca3 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -275,8 +275,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915;
engine->disable_lite_restore_wa =
- (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) &&
+ IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) &&
(engine->id == VCS || engine->id == VCS2);
engine->ctx_desc_template = GEN8_CTX_VALID;
@@ -366,7 +365,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq)
struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt;
u32 *reg_state = ce->lrc_reg_state;
- reg_state[CTX_RING_TAIL+1] = intel_ring_offset(rq->ring, rq->tail);
+ reg_state[CTX_RING_TAIL+1] = rq->tail;
/* True 32b PPGTT with dynamic page allocation: update PDP
* registers and point the unallocated PDPs to scratch page.
@@ -433,15 +432,17 @@ static bool can_merge_ctx(const struct i915_gem_context *prev,
static void execlists_dequeue(struct intel_engine_cs *engine)
{
- struct drm_i915_gem_request *cursor, *last;
+ struct drm_i915_gem_request *last;
struct execlist_port *port = engine->execlist_port;
+ unsigned long flags;
+ struct rb_node *rb;
bool submit = false;
last = port->request;
if (last)
/* WaIdleLiteRestore:bdw,skl
* Apply the wa NOOPs to prevent ring:HEAD == req:TAIL
- * as we resubmit the request. See gen8_emit_request()
+ * as we resubmit the request. See gen8_emit_breadcrumb()
* for where we prepare the padding after the end of the
* request.
*/
@@ -470,8 +471,12 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* and context switches) submission.
*/
- spin_lock(&engine->execlist_lock);
- list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) {
+ spin_lock_irqsave(&engine->timeline->lock, flags);
+ rb = engine->execlist_first;
+ while (rb) {
+ struct drm_i915_gem_request *cursor =
+ rb_entry(rb, typeof(*cursor), priotree.node);
+
/* Can we combine this request with the current port? It has to
* be the same context/ringbuffer and not have any exceptions
* (e.g. GVT saying never to combine contexts).
@@ -494,7 +499,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* context (even though a different request) to
* the second port.
*/
- if (ctx_single_port_submission(cursor->ctx))
+ if (ctx_single_port_submission(last->ctx) ||
+ ctx_single_port_submission(cursor->ctx))
break;
GEM_BUG_ON(last->ctx == cursor->ctx);
@@ -502,17 +508,30 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
i915_gem_request_assign(&port->request, last);
port++;
}
+
+ rb = rb_next(rb);
+ rb_erase(&cursor->priotree.node, &engine->execlist_queue);
+ RB_CLEAR_NODE(&cursor->priotree.node);
+ cursor->priotree.priority = INT_MAX;
+
+ /* We keep the previous context alive until we retire the
+ * following request. This ensures that any the context object
+ * is still pinned for any residual writes the HW makes into it
+ * on the context switch into the next object following the
+ * breadcrumb. Otherwise, we may retire the context too early.
+ */
+ cursor->previous_context = engine->last_context;
+ engine->last_context = cursor->ctx;
+
+ __i915_gem_request_submit(cursor);
last = cursor;
submit = true;
}
if (submit) {
- /* Decouple all the requests submitted from the queue */
- engine->execlist_queue.next = &cursor->execlist_link;
- cursor->execlist_link.prev = &engine->execlist_queue;
-
i915_gem_request_assign(&port->request, last);
+ engine->execlist_first = rb;
}
- spin_unlock(&engine->execlist_lock);
+ spin_unlock_irqrestore(&engine->timeline->lock, flags);
if (submit)
execlists_submit_ports(engine);
@@ -523,6 +542,28 @@ static bool execlists_elsp_idle(struct intel_engine_cs *engine)
return !engine->execlist_port[0].request;
}
+/**
+ * intel_execlists_idle() - Determine if all engine submission ports are idle
+ * @dev_priv: i915 device private
+ *
+ * Return true if there are no requests pending on any of the submission ports
+ * of any engines.
+ */
+bool intel_execlists_idle(struct drm_i915_private *dev_priv)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ if (!i915.enable_execlists)
+ return true;
+
+ for_each_engine(engine, dev_priv, id)
+ if (!execlists_elsp_idle(engine))
+ return false;
+
+ return true;
+}
+
static bool execlists_elsp_ready(struct intel_engine_cs *engine)
{
int port;
@@ -593,18 +634,147 @@ static void intel_lrc_irq_handler(unsigned long data)
intel_uncore_forcewake_put(dev_priv, engine->fw_domains);
}
+static bool insert_request(struct i915_priotree *pt, struct rb_root *root)
+{
+ struct rb_node **p, *rb;
+ bool first = true;
+
+ /* most positive priority is scheduled first, equal priorities fifo */
+ rb = NULL;
+ p = &root->rb_node;
+ while (*p) {
+ struct i915_priotree *pos;
+
+ rb = *p;
+ pos = rb_entry(rb, typeof(*pos), node);
+ if (pt->priority > pos->priority) {
+ p = &rb->rb_left;
+ } else {
+ p = &rb->rb_right;
+ first = false;
+ }
+ }
+ rb_link_node(&pt->node, rb, p);
+ rb_insert_color(&pt->node, root);
+
+ return first;
+}
+
static void execlists_submit_request(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *engine = request->engine;
unsigned long flags;
- spin_lock_irqsave(&engine->execlist_lock, flags);
+ /* Will be called from irq-context when using foreign fences. */
+ spin_lock_irqsave(&engine->timeline->lock, flags);
- list_add_tail(&request->execlist_link, &engine->execlist_queue);
+ if (insert_request(&request->priotree, &engine->execlist_queue))
+ engine->execlist_first = &request->priotree.node;
if (execlists_elsp_idle(engine))
tasklet_hi_schedule(&engine->irq_tasklet);
- spin_unlock_irqrestore(&engine->execlist_lock, flags);
+ spin_unlock_irqrestore(&engine->timeline->lock, flags);
+}
+
+static struct intel_engine_cs *
+pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)
+{
+ struct intel_engine_cs *engine;
+
+ engine = container_of(pt,
+ struct drm_i915_gem_request,
+ priotree)->engine;
+ if (engine != locked) {
+ if (locked)
+ spin_unlock_irq(&locked->timeline->lock);
+ spin_lock_irq(&engine->timeline->lock);
+ }
+
+ return engine;
+}
+
+static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
+{
+ static DEFINE_MUTEX(lock);
+ struct intel_engine_cs *engine = NULL;
+ struct i915_dependency *dep, *p;
+ struct i915_dependency stack;
+ LIST_HEAD(dfs);
+
+ if (prio <= READ_ONCE(request->priotree.priority))
+ return;
+
+ /* Need global lock to use the temporary link inside i915_dependency */
+ mutex_lock(&lock);
+
+ stack.signaler = &request->priotree;
+ list_add(&stack.dfs_link, &dfs);
+
+ /* Recursively bump all dependent priorities to match the new request.
+ *
+ * A naive approach would be to use recursion:
+ * static void update_priorities(struct i915_priotree *pt, prio) {
+ * list_for_each_entry(dep, &pt->signalers_list, signal_link)
+ * update_priorities(dep->signal, prio)
+ * insert_request(pt);
+ * }
+ * but that may have unlimited recursion depth and so runs a very
+ * real risk of overunning the kernel stack. Instead, we build
+ * a flat list of all dependencies starting with the current request.
+ * As we walk the list of dependencies, we add all of its dependencies
+ * to the end of the list (this may include an already visited
+ * request) and continue to walk onwards onto the new dependencies. The
+ * end result is a topological list of requests in reverse order, the
+ * last element in the list is the request we must execute first.
+ */
+ list_for_each_entry_safe(dep, p, &dfs, dfs_link) {
+ struct i915_priotree *pt = dep->signaler;
+
+ list_for_each_entry(p, &pt->signalers_list, signal_link)
+ if (prio > READ_ONCE(p->signaler->priority))
+ list_move_tail(&p->dfs_link, &dfs);
+
+ p = list_next_entry(dep, dfs_link);
+ if (!RB_EMPTY_NODE(&pt->node))
+ continue;
+
+ engine = pt_lock_engine(pt, engine);
+
+ /* If it is not already in the rbtree, we can update the
+ * priority inplace and skip over it (and its dependencies)
+ * if it is referenced *again* as we descend the dfs.
+ */
+ if (prio > pt->priority && RB_EMPTY_NODE(&pt->node)) {
+ pt->priority = prio;
+ list_del_init(&dep->dfs_link);
+ }
+ }
+
+ /* Fifo and depth-first replacement ensure our deps execute before us */
+ list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
+ struct i915_priotree *pt = dep->signaler;
+
+ INIT_LIST_HEAD(&dep->dfs_link);
+
+ engine = pt_lock_engine(pt, engine);
+
+ if (prio <= pt->priority)
+ continue;
+
+ GEM_BUG_ON(RB_EMPTY_NODE(&pt->node));
+
+ pt->priority = prio;
+ rb_erase(&pt->node, &engine->execlist_queue);
+ if (insert_request(pt, &engine->execlist_queue))
+ engine->execlist_first = &pt->node;
+ }
+
+ if (engine)
+ spin_unlock_irq(&engine->timeline->lock);
+
+ mutex_unlock(&lock);
+
+ /* XXX Do we need to preempt to make room for us and our deps? */
}
int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
@@ -672,46 +842,6 @@ err_unpin:
return ret;
}
-/*
- * intel_logical_ring_advance() - advance the tail and prepare for submission
- * @request: Request to advance the logical ringbuffer of.
- *
- * The tail is updated in our logical ringbuffer struct, not in the actual context. What
- * really happens during submission is that the context and current tail will be placed
- * on a queue waiting for the ELSP to be ready to accept a new context submission. At that
- * point, the tail *inside* the context is updated and the ELSP written to.
- */
-static int
-intel_logical_ring_advance(struct drm_i915_gem_request *request)
-{
- struct intel_ring *ring = request->ring;
- struct intel_engine_cs *engine = request->engine;
-
- intel_ring_advance(ring);
- request->tail = ring->tail;
-
- /*
- * Here we add two extra NOOPs as padding to avoid
- * lite restore of a context with HEAD==TAIL.
- *
- * Caller must reserve WA_TAIL_DWORDS for us!
- */
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_advance(ring);
- request->wa_tail = ring->tail;
-
- /* We keep the previous context alive until we retire the following
- * request. This ensures that any the context object is still pinned
- * for any residual writes the HW makes into it on the context switch
- * into the next object following the breadcrumb. Otherwise, we may
- * retire the context too early.
- */
- request->previous_context = engine->last_context;
- engine->last_context = request->ctx;
- return 0;
-}
-
static int intel_lr_context_pin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
@@ -745,7 +875,7 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
ce->lrc_reg_state[CTX_RING_BUFFER_START+1] =
i915_ggtt_offset(ce->ring->vma);
- ce->state->obj->dirty = true;
+ ce->state->obj->mm.dirty = true;
/* Invalidate GuC TLB. */
if (i915.enable_guc_submission) {
@@ -853,13 +983,12 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
/*
- * WaDisableLSQCROPERFforOCL:skl,kbl
+ * WaDisableLSQCROPERFforOCL:kbl
* This WA is implemented in skl_init_clock_gating() but since
* this batch updates GEN8_L3SQCREG4 with default value we need to
* set this bit here to retain the WA during flush.
*/
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) ||
- IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
+ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
@@ -1002,9 +1131,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine,
struct drm_i915_private *dev_priv = engine->i915;
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
- /* WaDisableCtxRestoreArbitration:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+ /* WaDisableCtxRestoreArbitration:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
@@ -1075,9 +1203,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
{
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
- /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
- if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
+ /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+ if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0);
wa_ctx_emit(batch, index,
@@ -1104,9 +1231,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
wa_ctx_emit(batch, index, MI_NOOP);
}
- /* WaDisableCtxRestoreArbitration:skl,bxt */
- if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
+ /* WaDisableCtxRestoreArbitration:bxt */
+ if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE);
wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END);
@@ -1250,8 +1376,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
intel_engine_init_hangcheck(engine);
- if (!execlists_elsp_idle(engine))
+ /* After a GPU reset, we may have requests to replay */
+ if (!execlists_elsp_idle(engine)) {
+ engine->execlist_port[0].count = 0;
+ engine->execlist_port[1].count = 0;
execlists_submit_ports(engine);
+ }
return 0;
}
@@ -1326,10 +1456,7 @@ static void reset_common_ring(struct intel_engine_cs *engine,
memset(&port[1], 0, sizeof(port[1]));
}
- /* CS is stopped, and we will resubmit both ports on resume */
GEM_BUG_ON(request->ctx != port[0].request->ctx);
- port[0].count = 0;
- port[1].count = 0;
/* Reset WaIdleLiteRestore:bdw,skl as well */
request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32);
@@ -1570,39 +1697,35 @@ static void bxt_a_seqno_barrier(struct intel_engine_cs *engine)
* used as a workaround for not being allowed to do lite
* restore with HEAD==TAIL (WaIdleLiteRestore).
*/
-
-static int gen8_emit_request(struct drm_i915_gem_request *request)
+static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *out)
{
- struct intel_ring *ring = request->ring;
- int ret;
-
- ret = intel_ring_begin(request, 6 + WA_TAIL_DWORDS);
- if (ret)
- return ret;
+ *out++ = MI_NOOP;
+ *out++ = MI_NOOP;
+ request->wa_tail = intel_ring_offset(request->ring, out);
+}
+static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request,
+ u32 *out)
+{
/* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5));
- intel_ring_emit(ring, (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
- intel_ring_emit(ring,
- intel_hws_seqno_address(request->engine) |
- MI_FLUSH_DW_USE_GTT);
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, request->fence.seqno);
- intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_emit(ring, MI_NOOP);
- return intel_logical_ring_advance(request);
-}
+ *out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
+ *out++ = intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT;
+ *out++ = 0;
+ *out++ = request->global_seqno;
+ *out++ = MI_USER_INTERRUPT;
+ *out++ = MI_NOOP;
+ request->tail = intel_ring_offset(request->ring, out);
-static int gen8_emit_request_render(struct drm_i915_gem_request *request)
-{
- struct intel_ring *ring = request->ring;
- int ret;
+ gen8_emit_wa_tail(request, out);
+}
- ret = intel_ring_begin(request, 8 + WA_TAIL_DWORDS);
- if (ret)
- return ret;
+static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS;
+static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request,
+ u32 *out)
+{
/* We're using qword write, seqno should be aligned to 8 bytes. */
BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1);
@@ -1610,21 +1733,24 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request)
* need a prior CS_STALL, which is emitted by the flush
* following the batch.
*/
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
- intel_ring_emit(ring,
- (PIPE_CONTROL_GLOBAL_GTT_IVB |
- PIPE_CONTROL_CS_STALL |
- PIPE_CONTROL_QW_WRITE));
- intel_ring_emit(ring, intel_hws_seqno_address(request->engine));
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, i915_gem_request_get_seqno(request));
+ *out++ = GFX_OP_PIPE_CONTROL(6);
+ *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+ PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_QW_WRITE);
+ *out++ = intel_hws_seqno_address(request->engine);
+ *out++ = 0;
+ *out++ = request->global_seqno;
/* We're thrashing one dword of HWS. */
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_emit(ring, MI_NOOP);
- return intel_logical_ring_advance(request);
+ *out++ = 0;
+ *out++ = MI_USER_INTERRUPT;
+ *out++ = MI_NOOP;
+ request->tail = intel_ring_offset(request->ring, out);
+
+ gen8_emit_wa_tail(request, out);
}
+static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS;
+
static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
{
int ret;
@@ -1641,7 +1767,7 @@ static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
if (ret)
DRM_ERROR("MOCS failed to program: expect performance issues.\n");
- return i915_gem_render_state_init(req);
+ return i915_gem_render_state_emit(req);
}
/**
@@ -1652,9 +1778,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv;
- if (!intel_engine_initialized(engine))
- return;
-
/*
* Tasklet cannot be active at this point due intel_mark_active/idle
* so this is just for documentation.
@@ -1681,14 +1804,19 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
lrc_destroy_wa_ctx_obj(engine);
engine->i915 = NULL;
+ dev_priv->engine[engine->id] = NULL;
+ kfree(engine);
}
void intel_execlists_enable_submission(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id) {
engine->submit_request = execlists_submit_request;
+ engine->schedule = execlists_schedule;
+ }
}
static void
@@ -1698,8 +1826,10 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine)
engine->init_hw = gen8_init_common_ring;
engine->reset_hw = reset_common_ring;
engine->emit_flush = gen8_emit_flush;
- engine->emit_request = gen8_emit_request;
+ engine->emit_breadcrumb = gen8_emit_breadcrumb;
+ engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_sz;
engine->submit_request = execlists_submit_request;
+ engine->schedule = execlists_schedule;
engine->irq_enable = gen8_logical_ring_enable_irq;
engine->irq_disable = gen8_logical_ring_disable_irq;
@@ -1820,7 +1950,8 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
engine->init_hw = gen8_init_render_ring;
engine->init_context = gen8_init_rcs_context;
engine->emit_flush = gen8_emit_flush_render;
- engine->emit_request = gen8_emit_request_render;
+ engine->emit_breadcrumb = gen8_emit_breadcrumb_render;
+ engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_render_sz;
ret = intel_engine_create_scratch(engine, 4096);
if (ret)
@@ -1945,7 +2076,7 @@ static void execlists_init_reg_state(u32 *reg_state,
RING_START(engine->mmio_base), 0);
ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL,
RING_CTL(engine->mmio_base),
- ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID);
+ RING_CTL_SIZE(ring->size) | RING_VALID);
ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U,
RING_BBADDR_UDW(engine->mmio_base), 0);
ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L,
@@ -2046,7 +2177,7 @@ populate_lr_context(struct i915_gem_context *ctx,
DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret);
return ret;
}
- ctx_obj->dirty = true;
+ ctx_obj->mm.dirty = true;
/* The second page of the context object contains some fields which must
* be set up prior to the first execution. */
@@ -2153,30 +2284,43 @@ error_deref_obj:
void intel_lr_context_resume(struct drm_i915_private *dev_priv)
{
- struct i915_gem_context *ctx = dev_priv->kernel_context;
struct intel_engine_cs *engine;
+ struct i915_gem_context *ctx;
+ enum intel_engine_id id;
+
+ /* Because we emit WA_TAIL_DWORDS there may be a disparity
+ * between our bookkeeping in ce->ring->head and ce->ring->tail and
+ * that stored in context. As we only write new commands from
+ * ce->ring->tail onwards, everything before that is junk. If the GPU
+ * starts reading from its RING_HEAD from the context, it may try to
+ * execute that junk and die.
+ *
+ * So to avoid that we reset the context images upon resume. For
+ * simplicity, we just zero everything out.
+ */
+ list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ for_each_engine(engine, dev_priv, id) {
+ struct intel_context *ce = &ctx->engine[engine->id];
+ u32 *reg;
- for_each_engine(engine, dev_priv) {
- struct intel_context *ce = &ctx->engine[engine->id];
- void *vaddr;
- uint32_t *reg_state;
-
- if (!ce->state)
- continue;
-
- vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
- if (WARN_ON(IS_ERR(vaddr)))
- continue;
+ if (!ce->state)
+ continue;
- reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+ reg = i915_gem_object_pin_map(ce->state->obj,
+ I915_MAP_WB);
+ if (WARN_ON(IS_ERR(reg)))
+ continue;
- reg_state[CTX_RING_HEAD+1] = 0;
- reg_state[CTX_RING_TAIL+1] = 0;
+ reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg);
+ reg[CTX_RING_HEAD+1] = 0;
+ reg[CTX_RING_TAIL+1] = 0;
- ce->state->obj->dirty = true;
- i915_gem_object_unpin_map(ce->state->obj);
+ ce->state->obj->mm.dirty = true;
+ i915_gem_object_unpin_map(ce->state->obj);
- ce->ring->head = 0;
- ce->ring->tail = 0;
+ ce->ring->head = ce->ring->tail = 0;
+ ce->ring->last_retired_head = -1;
+ intel_ring_update_space(ce->ring);
+ }
}
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 4fed8165f98a..c1f546180ba2 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -95,5 +95,6 @@ uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
int enable_execlists);
void intel_execlists_enable_submission(struct drm_i915_private *dev_priv);
+bool intel_execlists_idle(struct drm_i915_private *dev_priv);
#endif /* _INTEL_LRC_H_ */
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
new file mode 100644
index 000000000000..daa523410953
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright © 2016 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 <drm/drm_edid.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_dual_mode_helper.h>
+#include "intel_drv.h"
+
+static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
+{
+ struct intel_digital_port *dig_port =
+ container_of(lspcon, struct intel_digital_port, lspcon);
+
+ return &dig_port->dp;
+}
+
+static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
+{
+ enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID;
+ struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+ if (drm_lspcon_get_mode(adapter, &current_mode))
+ DRM_ERROR("Error reading LSPCON mode\n");
+ else
+ DRM_DEBUG_KMS("Current LSPCON mode %s\n",
+ current_mode == DRM_LSPCON_MODE_PCON ? "PCON" : "LS");
+ return current_mode;
+}
+
+static int lspcon_change_mode(struct intel_lspcon *lspcon,
+ enum drm_lspcon_mode mode, bool force)
+{
+ int err;
+ enum drm_lspcon_mode current_mode;
+ struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+ err = drm_lspcon_get_mode(adapter, &current_mode);
+ if (err) {
+ DRM_ERROR("Error reading LSPCON mode\n");
+ return err;
+ }
+
+ if (current_mode == mode) {
+ DRM_DEBUG_KMS("Current mode = desired LSPCON mode\n");
+ return 0;
+ }
+
+ err = drm_lspcon_set_mode(adapter, mode);
+ if (err < 0) {
+ DRM_ERROR("LSPCON mode change failed\n");
+ return err;
+ }
+
+ lspcon->mode = mode;
+ DRM_DEBUG_KMS("LSPCON mode changed done\n");
+ return 0;
+}
+
+static bool lspcon_probe(struct intel_lspcon *lspcon)
+{
+ enum drm_dp_dual_mode_type adaptor_type;
+ struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+ /* Lets probe the adaptor and check its type */
+ adaptor_type = drm_dp_dual_mode_detect(adapter);
+ if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) {
+ DRM_DEBUG_KMS("No LSPCON detected, found %s\n",
+ drm_dp_get_dual_mode_type_name(adaptor_type));
+ return false;
+ }
+
+ /* Yay ... got a LSPCON device */
+ DRM_DEBUG_KMS("LSPCON detected\n");
+ lspcon->mode = lspcon_get_current_mode(lspcon);
+ lspcon->active = true;
+ return true;
+}
+
+static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
+{
+ struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
+ unsigned long start = jiffies;
+
+ if (!lspcon->desc_valid)
+ return;
+
+ while (1) {
+ struct intel_dp_desc desc;
+
+ /*
+ * The w/a only applies in PCON mode and we don't expect any
+ * AUX errors.
+ */
+ if (!__intel_dp_read_desc(intel_dp, &desc))
+ return;
+
+ if (!memcmp(&intel_dp->desc, &desc, sizeof(desc))) {
+ DRM_DEBUG_KMS("LSPCON recovering in PCON mode after %u ms\n",
+ jiffies_to_msecs(jiffies - start));
+ return;
+ }
+
+ if (time_after(jiffies, start + msecs_to_jiffies(1000)))
+ break;
+
+ usleep_range(10000, 15000);
+ }
+
+ DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
+}
+
+void lspcon_resume(struct intel_lspcon *lspcon)
+{
+ lspcon_resume_in_pcon_wa(lspcon);
+
+ if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true))
+ DRM_ERROR("LSPCON resume failed\n");
+ else
+ DRM_DEBUG_KMS("LSPCON resume success\n");
+}
+
+bool lspcon_init(struct intel_digital_port *intel_dig_port)
+{
+ struct intel_dp *dp = &intel_dig_port->dp;
+ struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (!IS_GEN9(dev_priv)) {
+ DRM_ERROR("LSPCON is supported on GEN9 only\n");
+ return false;
+ }
+
+ lspcon->active = false;
+ lspcon->mode = DRM_LSPCON_MODE_INVALID;
+
+ if (!lspcon_probe(lspcon)) {
+ DRM_ERROR("Failed to probe lspcon\n");
+ return false;
+ }
+
+ /*
+ * In the SW state machine, lets Put LSPCON in PCON mode only.
+ * In this way, it will work with both HDMI 1.4 sinks as well as HDMI
+ * 2.0 sinks.
+ */
+ if (lspcon->active && lspcon->mode != DRM_LSPCON_MODE_PCON) {
+ if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON,
+ true) < 0) {
+ DRM_ERROR("LSPCON mode change to PCON failed\n");
+ return false;
+ }
+ }
+
+ if (!intel_dp_read_dpcd(dp)) {
+ DRM_ERROR("LSPCON DPCD read failed\n");
+ return false;
+ }
+
+ lspcon->desc_valid = intel_dp_read_desc(dp);
+
+ DRM_DEBUG_KMS("Success: LSPCON init\n");
+ return true;
+}
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e1d47d51ea47..d12ef0047d49 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -106,7 +106,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
if (!(tmp & LVDS_PORT_EN))
goto out;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
*pipe = PORT_TO_PIPE_CPT(tmp);
else
*pipe = PORT_TO_PIPE(tmp);
@@ -122,8 +122,7 @@ out:
static void intel_lvds_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
u32 tmp, flags = 0;
@@ -139,12 +138,12 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
pipe_config->base.adjusted_mode.flags |= flags;
- if (INTEL_INFO(dev)->gen < 5)
+ if (INTEL_GEN(dev_priv) < 5)
pipe_config->gmch_pfit.lvds_border_bits =
tmp & LVDS_BORDER_ENABLE;
/* gen2/3 store dither state in pfit control, needs to match */
- if (INTEL_INFO(dev)->gen < 4) {
+ if (INTEL_GEN(dev_priv) < 4) {
tmp = I915_READ(PFIT_CONTROL);
pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
@@ -396,7 +395,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct drm_device *dev = intel_encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
struct intel_lvds_encoder *lvds_encoder =
to_lvds_encoder(&intel_encoder->base);
struct intel_connector *intel_connector =
@@ -406,7 +405,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
unsigned int lvds_bpp;
/* Should never happen!! */
- if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
+ if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
DRM_ERROR("Can't support LVDS on pipe A\n");
return false;
}
@@ -431,7 +430,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
adjusted_mode);
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
pipe_config->has_pch_encoder = true;
intel_pch_panel_fitting(intel_crtc, pipe_config,
@@ -566,7 +565,7 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
* and as part of the cleanup in the hw state restore we also redisable
* the vga plane.
*/
- if (!HAS_PCH_SPLIT(dev))
+ if (!HAS_PCH_SPLIT(dev_priv))
intel_display_resume(dev);
dev_priv->modeset_restore = MODESET_DONE;
@@ -949,16 +948,17 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
}
-static bool intel_lvds_supported(struct drm_device *dev)
+static bool intel_lvds_supported(struct drm_i915_private *dev_priv)
{
/* With the introduction of the PCH we gained a dedicated
* LVDS presence pin, use it. */
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
return true;
/* Otherwise LVDS was only attached to mobile products,
* except for the inglorious 830gm */
- if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
+ if (INTEL_GEN(dev_priv) <= 4 &&
+ IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
return true;
return false;
@@ -984,27 +984,27 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *fixed_mode = NULL;
struct drm_display_mode *downclock_mode = NULL;
struct edid *edid;
- struct drm_crtc *crtc;
+ struct intel_crtc *crtc;
i915_reg_t lvds_reg;
u32 lvds;
int pipe;
u8 pin;
- if (!intel_lvds_supported(dev))
+ if (!intel_lvds_supported(dev_priv))
return;
/* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds))
return;
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
lvds_reg = PCH_LVDS;
else
lvds_reg = LVDS;
lvds = I915_READ(lvds_reg);
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
if ((lvds & LVDS_DETECTED) == 0)
return;
if (dev_priv->vbt.edp.support) {
@@ -1064,12 +1064,13 @@ void intel_lvds_init(struct drm_device *dev)
intel_connector->get_hw_state = intel_connector_get_hw_state;
intel_connector_attach_encoder(intel_connector, intel_encoder);
- intel_encoder->type = INTEL_OUTPUT_LVDS;
+ intel_encoder->type = INTEL_OUTPUT_LVDS;
+ intel_encoder->port = PORT_NONE;
intel_encoder->cloneable = 0;
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
- else if (IS_GEN4(dev))
+ else if (IS_GEN4(dev_priv))
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
else
intel_encoder->crtc_mask = (1 << 1);
@@ -1157,14 +1158,14 @@ void intel_lvds_init(struct drm_device *dev)
*/
/* Ironlake: FIXME if still fail, not try pipe mode now */
- if (HAS_PCH_SPLIT(dev))
+ if (HAS_PCH_SPLIT(dev_priv))
goto failed;
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
- crtc = intel_get_crtc_for_pipe(dev, pipe);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (crtc && (lvds & LVDS_PORT_EN)) {
- fixed_mode = intel_crtc_mode_get(dev, crtc);
+ fixed_mode = intel_crtc_mode_get(dev, &crtc->base);
if (fixed_mode) {
DRM_DEBUG_KMS("using current (BIOS) mode: ");
drm_mode_debug_printmodeline(fixed_mode);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 7acbbbf97833..f4429f67a4e3 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -642,24 +642,6 @@ static struct notifier_block intel_opregion_notifier = {
* (version 3)
*/
-static u32 get_did(struct intel_opregion *opregion, int i)
-{
- u32 did;
-
- if (i < ARRAY_SIZE(opregion->acpi->didl)) {
- did = opregion->acpi->didl[i];
- } else {
- i -= ARRAY_SIZE(opregion->acpi->didl);
-
- if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
- return 0;
-
- did = opregion->acpi->did2[i];
- }
-
- return did;
-}
-
static void set_did(struct intel_opregion *opregion, int i, u32 val)
{
if (i < ARRAY_SIZE(opregion->acpi->didl)) {
@@ -674,11 +656,11 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
}
}
-static u32 acpi_display_type(struct drm_connector *connector)
+static u32 acpi_display_type(struct intel_connector *connector)
{
u32 display_type;
- switch (connector->connector_type) {
+ switch (connector->base.connector_type) {
case DRM_MODE_CONNECTOR_VGA:
case DRM_MODE_CONNECTOR_DVIA:
display_type = ACPI_DISPLAY_TYPE_VGA;
@@ -707,7 +689,7 @@ static u32 acpi_display_type(struct drm_connector *connector)
display_type = ACPI_DISPLAY_TYPE_OTHER;
break;
default:
- MISSING_CASE(connector->connector_type);
+ MISSING_CASE(connector->base.connector_type);
display_type = ACPI_DISPLAY_TYPE_OTHER;
break;
}
@@ -718,34 +700,9 @@ static u32 acpi_display_type(struct drm_connector *connector)
static void intel_didl_outputs(struct drm_i915_private *dev_priv)
{
struct intel_opregion *opregion = &dev_priv->opregion;
- struct pci_dev *pdev = dev_priv->drm.pdev;
- struct drm_connector *connector;
- acpi_handle handle;
- struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
- unsigned long long device_id;
- acpi_status status;
- u32 temp, max_outputs;
- int i = 0;
-
- handle = ACPI_HANDLE(&pdev->dev);
- if (!handle || acpi_bus_get_device(handle, &acpi_dev))
- return;
-
- if (acpi_is_video_device(handle))
- acpi_video_bus = acpi_dev;
- else {
- list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
- if (acpi_is_video_device(acpi_cdev->handle)) {
- acpi_video_bus = acpi_cdev;
- break;
- }
- }
- }
-
- if (!acpi_video_bus) {
- DRM_DEBUG_KMS("No ACPI video bus found\n");
- return;
- }
+ struct intel_connector *connector;
+ int i = 0, max_outputs;
+ int display_index[16] = {};
/*
* In theory, did2, the extended didl, gets added at opregion version
@@ -757,64 +714,58 @@ static void intel_didl_outputs(struct drm_i915_private *dev_priv)
max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
ARRAY_SIZE(opregion->acpi->did2);
- list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
- if (i >= max_outputs) {
- DRM_DEBUG_KMS("More than %u outputs detected via ACPI\n",
- max_outputs);
- return;
- }
- status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
- NULL, &device_id);
- if (ACPI_SUCCESS(status)) {
- if (!device_id)
- goto blind_set;
- set_did(opregion, i++, (u32)(device_id & 0x0f0f));
- }
+ for_each_intel_connector(&dev_priv->drm, connector) {
+ u32 device_id, type;
+
+ device_id = acpi_display_type(connector);
+
+ /* Use display type specific display index. */
+ type = (device_id & ACPI_DISPLAY_TYPE_MASK)
+ >> ACPI_DISPLAY_TYPE_SHIFT;
+ device_id |= display_index[type]++ << ACPI_DISPLAY_INDEX_SHIFT;
+
+ connector->acpi_device_id = device_id;
+ if (i < max_outputs)
+ set_did(opregion, i, device_id);
+ i++;
}
-end:
DRM_DEBUG_KMS("%d outputs detected\n", i);
+ if (i > max_outputs)
+ DRM_ERROR("More than %d outputs in connector list\n",
+ max_outputs);
+
/* If fewer than max outputs, the list must be null terminated */
if (i < max_outputs)
set_did(opregion, i, 0);
- return;
-
-blind_set:
- i = 0;
- list_for_each_entry(connector,
- &dev_priv->drm.mode_config.connector_list, head) {
- int display_type = acpi_display_type(connector);
-
- if (i >= max_outputs) {
- DRM_DEBUG_KMS("More than %u outputs in connector list\n",
- max_outputs);
- return;
- }
-
- temp = get_did(opregion, i);
- set_did(opregion, i, temp | (1 << 31) | display_type | i);
- i++;
- }
- goto end;
}
static void intel_setup_cadls(struct drm_i915_private *dev_priv)
{
struct intel_opregion *opregion = &dev_priv->opregion;
+ struct intel_connector *connector;
int i = 0;
- u32 disp_id;
-
- /* Initialize the CADL field by duplicating the DIDL values.
- * Technically, this is not always correct as display outputs may exist,
- * but not active. This initialization is necessary for some Clevo
- * laptops that check this field before processing the brightness and
- * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
- * there are less than eight devices. */
- do {
- disp_id = get_did(opregion, i);
- opregion->acpi->cadl[i] = disp_id;
- } while (++i < 8 && disp_id != 0);
+
+ /*
+ * Initialize the CADL field from the connector device ids. This is
+ * essentially the same as copying from the DIDL. Technically, this is
+ * not always correct as display outputs may exist, but not active. This
+ * initialization is necessary for some Clevo laptops that check this
+ * field before processing the brightness and display switching hotkeys.
+ *
+ * Note that internal panels should be at the front of the connector
+ * list already, ensuring they're not left out.
+ */
+ for_each_intel_connector(&dev_priv->drm, connector) {
+ if (i >= ARRAY_SIZE(opregion->acpi->cadl))
+ break;
+ opregion->acpi->cadl[i++] = connector->acpi_device_id;
+ }
+
+ /* If fewer than 8 active devices, the list must be null terminated */
+ if (i < ARRAY_SIZE(opregion->acpi->cadl))
+ opregion->acpi->cadl[i] = 0;
}
void intel_opregion_register(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index a24bc8c7889f..fd0e4dac7cc1 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -233,7 +233,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
static struct drm_i915_gem_request *alloc_request(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
- struct intel_engine_cs *engine = &dev_priv->engine[RCS];
+ struct intel_engine_cs *engine = dev_priv->engine[RCS];
return i915_gem_request_alloc(engine, dev_priv->kernel_context);
}
@@ -1222,7 +1222,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
out_unlock:
mutex_unlock(&dev->struct_mutex);
drm_modeset_unlock_all(dev);
- i915_gem_object_put_unlocked(new_bo);
+ i915_gem_object_put(new_bo);
out_free:
kfree(params);
@@ -1466,10 +1466,12 @@ void intel_cleanup_overlay(struct drm_i915_private *dev_priv)
* hardware should be off already */
WARN_ON(dev_priv->overlay->active);
- i915_gem_object_put_unlocked(dev_priv->overlay->reg_bo);
+ i915_gem_object_put(dev_priv->overlay->reg_bo);
kfree(dev_priv->overlay);
}
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
struct intel_overlay_error_state {
struct overlay_registers regs;
unsigned long base;
@@ -1587,3 +1589,5 @@ intel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
P(UVSCALEV);
#undef P
}
+
+#endif
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index be4b4d546fd9..08ab6d762ca4 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -304,7 +304,7 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
struct intel_crtc_state *pipe_config,
int fitting_mode)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
@@ -325,7 +325,7 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
break;
case DRM_MODE_SCALE_ASPECT:
/* Scale but preserve the aspect ratio */
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
i965_scale_aspect(pipe_config, &pfit_control);
else
i9xx_scale_aspect(pipe_config, &pfit_control,
@@ -339,7 +339,7 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
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)
+ if (INTEL_GEN(dev_priv) >= 4)
pfit_control |= PFIT_SCALING_AUTO;
else
pfit_control |= (VERT_AUTO_SCALE |
@@ -355,7 +355,7 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
/* 965+ wants fuzzy fitting */
/* FIXME: handle multiple panels by failing gracefully */
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
PFIT_FILTER_FUZZY);
@@ -366,7 +366,7 @@ out:
}
/* Make sure pre-965 set dither correctly for 18bpp panels. */
- if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
+ if (INTEL_GEN(dev_priv) < 4 && pipe_config->pipe_bpp == 18)
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
pipe_config->gmch_pfit.control = pfit_control;
@@ -1722,7 +1722,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n",
connector->name,
- panel->backlight.enabled ? "enabled" : "disabled",
+ enableddisabled(panel->backlight.enabled),
panel->backlight.level, panel->backlight.max);
return 0;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index db24f898853c..d67974eb127a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,7 @@
#include "intel_drv.h"
#include "../../../platform/x86/intel_ips.h"
#include <linux/module.h>
+#include <drm/drm_atomic_helper.h>
/**
* DOC: RC6
@@ -55,10 +56,8 @@
#define INTEL_RC6p_ENABLE (1<<1)
#define INTEL_RC6pp_ENABLE (1<<2)
-static void gen9_init_clock_gating(struct drm_device *dev)
+static void gen9_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl */
I915_WRITE(CHICKEN_PAR1_1,
I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP);
@@ -81,11 +80,9 @@ static void gen9_init_clock_gating(struct drm_device *dev)
ILK_DPFC_DISABLE_DUMMY0);
}
-static void bxt_init_clock_gating(struct drm_device *dev)
+static void bxt_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- gen9_init_clock_gating(dev);
+ gen9_init_clock_gating(dev_priv);
/* WaDisableSDEUnitClockGating:bxt */
I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
@@ -107,9 +104,8 @@ static void bxt_init_clock_gating(struct drm_device *dev)
PWM1_GATING_DIS | PWM2_GATING_DIS);
}
-static void i915_pineview_get_mem_freq(struct drm_device *dev)
+static void i915_pineview_get_mem_freq(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
u32 tmp;
tmp = I915_READ(CLKCFG);
@@ -146,9 +142,8 @@ static void i915_pineview_get_mem_freq(struct drm_device *dev)
dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
}
-static void i915_ironlake_get_mem_freq(struct drm_device *dev)
+static void i915_ironlake_get_mem_freq(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
u16 ddrpll, csipll;
ddrpll = I915_READ16(DDRMPLL1);
@@ -252,8 +247,8 @@ static const struct cxsr_latency cxsr_latency_table[] = {
{0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */
};
-static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
- int is_ddr3,
+static const struct cxsr_latency *intel_get_cxsr_latency(bool is_desktop,
+ bool is_ddr3,
int fsb,
int mem)
{
@@ -319,27 +314,26 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable)
void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
{
- struct drm_device *dev = &dev_priv->drm;
u32 val;
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
POSTING_READ(FW_BLC_SELF_VLV);
dev_priv->wm.vlv.cxsr = enable;
- } else if (IS_G4X(dev) || IS_CRESTLINE(dev)) {
+ } else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) {
I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0);
POSTING_READ(FW_BLC_SELF);
- } else if (IS_PINEVIEW(dev)) {
+ } else if (IS_PINEVIEW(dev_priv)) {
val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN;
val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0;
I915_WRITE(DSPFW3, val);
POSTING_READ(DSPFW3);
- } else if (IS_I945G(dev) || IS_I945GM(dev)) {
+ } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) {
val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
_MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
I915_WRITE(FW_BLC_SELF, val);
POSTING_READ(FW_BLC_SELF);
- } else if (IS_I915GM(dev)) {
+ } else if (IS_I915GM(dev_priv)) {
/*
* FIXME can't find a bit like this for 915G, and
* and yet it does have the related watermark in
@@ -353,8 +347,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
return;
}
- DRM_DEBUG_KMS("memory self-refresh is %s\n",
- enable ? "enabled" : "disabled");
+ DRM_DEBUG_KMS("memory self-refresh is %s\n", enableddisabled(enable));
}
@@ -377,10 +370,9 @@ static const int pessimal_latency_ns = 5000;
#define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \
((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8))
-static int vlv_get_fifo_size(struct drm_device *dev,
+static int vlv_get_fifo_size(struct drm_i915_private *dev_priv,
enum pipe pipe, int plane)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
int sprite0_start, sprite1_start, size;
switch (pipe) {
@@ -429,9 +421,8 @@ static int vlv_get_fifo_size(struct drm_device *dev,
return size;
}
-static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
+static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dsparb = I915_READ(DSPARB);
int size;
@@ -445,9 +436,8 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
return size;
}
-static int i830_get_fifo_size(struct drm_device *dev, int plane)
+static int i830_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dsparb = I915_READ(DSPARB);
int size;
@@ -462,9 +452,8 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane)
return size;
}
-static int i845_get_fifo_size(struct drm_device *dev, int plane)
+static int i845_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dsparb = I915_READ(DSPARB);
int size;
@@ -624,11 +613,11 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
return wm_size;
}
-static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv)
{
- struct drm_crtc *crtc, *enabled = NULL;
+ struct intel_crtc *crtc, *enabled = NULL;
- for_each_crtc(dev, crtc) {
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
if (intel_crtc_active(crtc)) {
if (enabled)
return NULL;
@@ -639,27 +628,31 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
return enabled;
}
-static void pineview_update_wm(struct drm_crtc *unused_crtc)
+static void pineview_update_wm(struct intel_crtc *unused_crtc)
{
- struct drm_device *dev = unused_crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *crtc;
+ struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+ struct intel_crtc *crtc;
const struct cxsr_latency *latency;
u32 reg;
unsigned long wm;
- latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
- dev_priv->fsb_freq, dev_priv->mem_freq);
+ latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
+ dev_priv->is_ddr3,
+ dev_priv->fsb_freq,
+ dev_priv->mem_freq);
if (!latency) {
DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
intel_set_memory_cxsr(dev_priv, false);
return;
}
- crtc = single_enabled_crtc(dev);
+ crtc = single_enabled_crtc(dev_priv);
if (crtc) {
- const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
- int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc->config->base.adjusted_mode;
+ const struct drm_framebuffer *fb =
+ crtc->base.primary->state->fb;
+ int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
int clock = adjusted_mode->crtc_clock;
/* Display SR */
@@ -706,7 +699,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
}
}
-static bool g4x_compute_wm0(struct drm_device *dev,
+static bool g4x_compute_wm0(struct drm_i915_private *dev_priv,
int plane,
const struct intel_watermark_params *display,
int display_latency_ns,
@@ -715,24 +708,26 @@ static bool g4x_compute_wm0(struct drm_device *dev,
int *plane_wm,
int *cursor_wm)
{
- struct drm_crtc *crtc;
+ struct intel_crtc *crtc;
const struct drm_display_mode *adjusted_mode;
+ const struct drm_framebuffer *fb;
int htotal, hdisplay, clock, cpp;
int line_time_us, line_count;
int entries, tlb_miss;
- crtc = intel_get_crtc_for_plane(dev, plane);
+ crtc = intel_get_crtc_for_plane(dev_priv, plane);
if (!intel_crtc_active(crtc)) {
*cursor_wm = cursor->guard_size;
*plane_wm = display->guard_size;
return false;
}
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+ adjusted_mode = &crtc->config->base.adjusted_mode;
+ fb = crtc->base.primary->state->fb;
clock = adjusted_mode->crtc_clock;
htotal = adjusted_mode->crtc_htotal;
- hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
- cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+ hdisplay = crtc->config->pipe_src_w;
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
/* Use the small buffer method to calculate plane watermark */
entries = ((clock * cpp / 1000) * display_latency_ns) / 1000;
@@ -747,7 +742,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
/* Use the large buffer method to calculate cursor watermark */
line_time_us = max(htotal * 1000 / clock, 1);
line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
- entries = line_count * crtc->cursor->state->crtc_w * cpp;
+ entries = line_count * crtc->base.cursor->state->crtc_w * cpp;
tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
if (tlb_miss > 0)
entries += tlb_miss;
@@ -766,7 +761,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
* can be programmed into the associated watermark register, that watermark
* must be disabled.
*/
-static bool g4x_check_srwm(struct drm_device *dev,
+static bool g4x_check_srwm(struct drm_i915_private *dev_priv,
int display_wm, int cursor_wm,
const struct intel_watermark_params *display,
const struct intel_watermark_params *cursor)
@@ -775,13 +770,13 @@ static bool g4x_check_srwm(struct drm_device *dev,
display_wm, cursor_wm);
if (display_wm > display->max_wm) {
- DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n",
+ DRM_DEBUG_KMS("display watermark is too large(%d/%u), disabling\n",
display_wm, display->max_wm);
return false;
}
if (cursor_wm > cursor->max_wm) {
- DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n",
+ DRM_DEBUG_KMS("cursor watermark is too large(%d/%u), disabling\n",
cursor_wm, cursor->max_wm);
return false;
}
@@ -794,15 +789,16 @@ static bool g4x_check_srwm(struct drm_device *dev,
return true;
}
-static bool g4x_compute_srwm(struct drm_device *dev,
+static bool g4x_compute_srwm(struct drm_i915_private *dev_priv,
int plane,
int latency_ns,
const struct intel_watermark_params *display,
const struct intel_watermark_params *cursor,
int *display_wm, int *cursor_wm)
{
- struct drm_crtc *crtc;
+ struct intel_crtc *crtc;
const struct drm_display_mode *adjusted_mode;
+ const struct drm_framebuffer *fb;
int hdisplay, htotal, cpp, clock;
unsigned long line_time_us;
int line_count, line_size;
@@ -814,12 +810,13 @@ static bool g4x_compute_srwm(struct drm_device *dev,
return false;
}
- crtc = intel_get_crtc_for_plane(dev, plane);
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+ crtc = intel_get_crtc_for_plane(dev_priv, plane);
+ adjusted_mode = &crtc->config->base.adjusted_mode;
+ fb = crtc->base.primary->state->fb;
clock = adjusted_mode->crtc_clock;
htotal = adjusted_mode->crtc_htotal;
- hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
- cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+ hdisplay = crtc->config->pipe_src_w;
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
line_time_us = max(htotal * 1000 / clock, 1);
line_count = (latency_ns / line_time_us + 1000) / 1000;
@@ -833,11 +830,11 @@ static bool g4x_compute_srwm(struct drm_device *dev,
*display_wm = entries + display->guard_size;
/* calculate the self-refresh watermark for display cursor */
- entries = line_count * cpp * crtc->cursor->state->crtc_w;
+ entries = line_count * cpp * crtc->base.cursor->state->crtc_w;
entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
*cursor_wm = entries + cursor->guard_size;
- return g4x_check_srwm(dev,
+ return g4x_check_srwm(dev_priv,
*display_wm, *cursor_wm,
display, cursor);
}
@@ -937,10 +934,8 @@ static unsigned int vlv_wm_method2(unsigned int pixel_rate,
return ret;
}
-static void vlv_setup_wm_latency(struct drm_device *dev)
+static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* all latencies in usec */
dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3;
@@ -1065,7 +1060,8 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
for (level = 0; level < wm_state->num_levels; level++) {
struct drm_device *dev = crtc->base.dev;
- const int sr_fifo_size = INTEL_INFO(dev)->num_pipes * 512 - 1;
+ const int sr_fifo_size =
+ INTEL_INFO(to_i915(dev))->num_pipes * 512 - 1;
struct intel_plane *plane;
wm_state->sr[level].plane = sr_fifo_size - wm_state->sr[level].plane;
@@ -1095,15 +1091,16 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
static void vlv_compute_wm(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct vlv_wm_state *wm_state = &crtc->wm_state;
struct intel_plane *plane;
- int sr_fifo_size = INTEL_INFO(dev)->num_pipes * 512 - 1;
+ int sr_fifo_size = INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
int level;
memset(wm_state, 0, sizeof(*wm_state));
wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
- wm_state->num_levels = to_i915(dev)->wm.max_level + 1;
+ wm_state->num_levels = dev_priv->wm.max_level + 1;
wm_state->num_active_planes = 0;
@@ -1183,7 +1180,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
}
/* clear any (partially) filled invalid levels */
- for (level = wm_state->num_levels; level < to_i915(dev)->wm.max_level + 1; level++) {
+ for (level = wm_state->num_levels; level < dev_priv->wm.max_level + 1; level++) {
memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
}
@@ -1327,20 +1324,19 @@ static void vlv_merge_wm(struct drm_device *dev,
}
}
-static void vlv_update_wm(struct drm_crtc *crtc)
+static void vlv_update_wm(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->dev;
+ struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
+ enum pipe pipe = crtc->pipe;
struct vlv_wm_values wm = {};
- vlv_compute_wm(intel_crtc);
+ vlv_compute_wm(crtc);
vlv_merge_wm(dev, &wm);
if (memcmp(&dev_priv->wm.vlv, &wm, sizeof(wm)) == 0) {
/* FIXME should be part of crtc atomic commit */
- vlv_pipe_set_fifo_size(intel_crtc);
+ vlv_pipe_set_fifo_size(crtc);
return;
}
@@ -1356,9 +1352,9 @@ static void vlv_update_wm(struct drm_crtc *crtc)
intel_set_memory_cxsr(dev_priv, false);
/* FIXME should be part of crtc atomic commit */
- vlv_pipe_set_fifo_size(intel_crtc);
+ vlv_pipe_set_fifo_size(crtc);
- vlv_write_wm_values(intel_crtc, &wm);
+ vlv_write_wm_values(crtc, &wm);
DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
"sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n",
@@ -1382,30 +1378,29 @@ static void vlv_update_wm(struct drm_crtc *crtc)
#define single_plane_enabled(mask) is_power_of_2(mask)
-static void g4x_update_wm(struct drm_crtc *crtc)
+static void g4x_update_wm(struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
static const int sr_latency_ns = 12000;
- struct drm_i915_private *dev_priv = to_i915(dev);
int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
int plane_sr, cursor_sr;
unsigned int enabled = 0;
bool cxsr_enabled;
- if (g4x_compute_wm0(dev, PIPE_A,
+ if (g4x_compute_wm0(dev_priv, PIPE_A,
&g4x_wm_info, pessimal_latency_ns,
&g4x_cursor_wm_info, pessimal_latency_ns,
&planea_wm, &cursora_wm))
enabled |= 1 << PIPE_A;
- if (g4x_compute_wm0(dev, PIPE_B,
+ if (g4x_compute_wm0(dev_priv, PIPE_B,
&g4x_wm_info, pessimal_latency_ns,
&g4x_cursor_wm_info, pessimal_latency_ns,
&planeb_wm, &cursorb_wm))
enabled |= 1 << PIPE_B;
if (single_plane_enabled(enabled) &&
- g4x_compute_srwm(dev, ffs(enabled) - 1,
+ g4x_compute_srwm(dev_priv, ffs(enabled) - 1,
sr_latency_ns,
&g4x_wm_info,
&g4x_cursor_wm_info,
@@ -1440,25 +1435,27 @@ static void g4x_update_wm(struct drm_crtc *crtc)
intel_set_memory_cxsr(dev_priv, true);
}
-static void i965_update_wm(struct drm_crtc *unused_crtc)
+static void i965_update_wm(struct intel_crtc *unused_crtc)
{
- struct drm_device *dev = unused_crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *crtc;
+ struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+ struct intel_crtc *crtc;
int srwm = 1;
int cursor_sr = 16;
bool cxsr_enabled;
/* Calc sr entries for one plane configs */
- crtc = single_enabled_crtc(dev);
+ crtc = single_enabled_crtc(dev_priv);
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 =
+ &crtc->config->base.adjusted_mode;
+ const struct drm_framebuffer *fb =
+ crtc->base.primary->state->fb;
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
- int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
- int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+ int hdisplay = crtc->config->pipe_src_w;
+ int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
unsigned long line_time_us;
int entries;
@@ -1476,7 +1473,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
entries, srwm);
entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
- cpp * crtc->cursor->state->crtc_w;
+ cpp * crtc->base.cursor->state->crtc_w;
entries = DIV_ROUND_UP(entries,
i965_cursor_wm_info.cacheline_size);
cursor_sr = i965_cursor_wm_info.fifo_size -
@@ -1514,34 +1511,38 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
#undef FW_WM
-static void i9xx_update_wm(struct drm_crtc *unused_crtc)
+static void i9xx_update_wm(struct intel_crtc *unused_crtc)
{
- struct drm_device *dev = unused_crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
const struct intel_watermark_params *wm_info;
uint32_t fwater_lo;
uint32_t fwater_hi;
int cwm, srwm = 1;
int fifo_size;
int planea_wm, planeb_wm;
- struct drm_crtc *crtc, *enabled = NULL;
+ struct intel_crtc *crtc, *enabled = NULL;
- if (IS_I945GM(dev))
+ if (IS_I945GM(dev_priv))
wm_info = &i945_wm_info;
- else if (!IS_GEN2(dev))
+ else if (!IS_GEN2(dev_priv))
wm_info = &i915_wm_info;
else
wm_info = &i830_a_wm_info;
- fifo_size = dev_priv->display.get_fifo_size(dev, 0);
- crtc = intel_get_crtc_for_plane(dev, 0);
+ fifo_size = dev_priv->display.get_fifo_size(dev_priv, 0);
+ crtc = intel_get_crtc_for_plane(dev_priv, 0);
if (intel_crtc_active(crtc)) {
- const struct drm_display_mode *adjusted_mode;
- int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
- if (IS_GEN2(dev))
+ const struct drm_display_mode *adjusted_mode =
+ &crtc->config->base.adjusted_mode;
+ const struct drm_framebuffer *fb =
+ crtc->base.primary->state->fb;
+ int cpp;
+
+ if (IS_GEN2(dev_priv))
cpp = 4;
+ else
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
wm_info, fifo_size, cpp,
pessimal_latency_ns);
@@ -1552,18 +1553,23 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
planea_wm = wm_info->max_wm;
}
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev_priv))
wm_info = &i830_bc_wm_info;
- fifo_size = dev_priv->display.get_fifo_size(dev, 1);
- crtc = intel_get_crtc_for_plane(dev, 1);
+ fifo_size = dev_priv->display.get_fifo_size(dev_priv, 1);
+ crtc = intel_get_crtc_for_plane(dev_priv, 1);
if (intel_crtc_active(crtc)) {
- const struct drm_display_mode *adjusted_mode;
- int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
- if (IS_GEN2(dev))
+ const struct drm_display_mode *adjusted_mode =
+ &crtc->config->base.adjusted_mode;
+ const struct drm_framebuffer *fb =
+ crtc->base.primary->state->fb;
+ int cpp;
+
+ if (IS_GEN2(dev_priv))
cpp = 4;
+ else
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
wm_info, fifo_size, cpp,
pessimal_latency_ns);
@@ -1579,10 +1585,10 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
- if (IS_I915GM(dev) && enabled) {
+ if (IS_I915GM(dev_priv) && enabled) {
struct drm_i915_gem_object *obj;
- obj = intel_fb_obj(enabled->primary->state->fb);
+ obj = intel_fb_obj(enabled->base.primary->state->fb);
/* self-refresh seems busted with untiled */
if (!i915_gem_object_is_tiled(obj))
@@ -1598,19 +1604,24 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
intel_set_memory_cxsr(dev_priv, false);
/* Calc sr entries for one plane configs */
- if (HAS_FW_BLC(dev) && enabled) {
+ if (HAS_FW_BLC(dev_priv) && 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 =
+ &enabled->config->base.adjusted_mode;
+ const struct drm_framebuffer *fb =
+ enabled->base.primary->state->fb;
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
- int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w;
- int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0);
+ int hdisplay = enabled->config->pipe_src_w;
+ int cpp;
unsigned long line_time_us;
int entries;
- if (IS_I915GM(dev) || IS_I945GM(dev))
+ if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
cpp = 4;
+ else
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
line_time_us = max(htotal * 1000 / clock, 1);
@@ -1623,7 +1634,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
if (srwm < 0)
srwm = 1;
- if (IS_I945G(dev) || IS_I945GM(dev))
+ if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
I915_WRITE(FW_BLC_SELF,
FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
else
@@ -1647,23 +1658,22 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
intel_set_memory_cxsr(dev_priv, true);
}
-static void i845_update_wm(struct drm_crtc *unused_crtc)
+static void i845_update_wm(struct intel_crtc *unused_crtc)
{
- struct drm_device *dev = unused_crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *crtc;
+ struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+ struct intel_crtc *crtc;
const struct drm_display_mode *adjusted_mode;
uint32_t fwater_lo;
int planea_wm;
- crtc = single_enabled_crtc(dev);
+ crtc = single_enabled_crtc(dev_priv);
if (crtc == NULL)
return;
- adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+ adjusted_mode = &crtc->config->base.adjusted_mode;
planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
&i845_wm_info,
- dev_priv->display.get_fifo_size(dev, 0),
+ dev_priv->display.get_fifo_size(dev_priv, 0),
4, pessimal_latency_ns);
fwater_lo = I915_READ(FW_BLC) & ~0xfff;
fwater_lo |= (3<<8) | planea_wm;
@@ -1852,23 +1862,25 @@ static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->base.dst), cpp);
}
-static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
+static unsigned int
+ilk_display_fifo_size(const struct drm_i915_private *dev_priv)
{
- if (INTEL_INFO(dev)->gen >= 8)
+ if (INTEL_GEN(dev_priv) >= 8)
return 3072;
- else if (INTEL_INFO(dev)->gen >= 7)
+ else if (INTEL_GEN(dev_priv) >= 7)
return 768;
else
return 512;
}
-static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
- int level, bool is_sprite)
+static unsigned int
+ilk_plane_wm_reg_max(const struct drm_i915_private *dev_priv,
+ int level, bool is_sprite)
{
- if (INTEL_INFO(dev)->gen >= 8)
+ if (INTEL_GEN(dev_priv) >= 8)
/* BDW primary/sprite plane watermarks */
return level == 0 ? 255 : 2047;
- else if (INTEL_INFO(dev)->gen >= 7)
+ else if (INTEL_GEN(dev_priv) >= 7)
/* IVB/HSW primary/sprite plane watermarks */
return level == 0 ? 127 : 1023;
else if (!is_sprite)
@@ -1879,18 +1891,18 @@ static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
return level == 0 ? 63 : 255;
}
-static unsigned int ilk_cursor_wm_reg_max(const struct drm_device *dev,
- int level)
+static unsigned int
+ilk_cursor_wm_reg_max(const struct drm_i915_private *dev_priv, int level)
{
- if (INTEL_INFO(dev)->gen >= 7)
+ if (INTEL_GEN(dev_priv) >= 7)
return level == 0 ? 63 : 255;
else
return level == 0 ? 31 : 63;
}
-static unsigned int ilk_fbc_wm_reg_max(const struct drm_device *dev)
+static unsigned int ilk_fbc_wm_reg_max(const struct drm_i915_private *dev_priv)
{
- if (INTEL_INFO(dev)->gen >= 8)
+ if (INTEL_GEN(dev_priv) >= 8)
return 31;
else
return 15;
@@ -1903,7 +1915,8 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
enum intel_ddb_partitioning ddb_partitioning,
bool is_sprite)
{
- unsigned int fifo_size = ilk_display_fifo_size(dev);
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ unsigned int fifo_size = ilk_display_fifo_size(dev_priv);
/* if sprites aren't enabled, sprites get nothing */
if (is_sprite && !config->sprites_enabled)
@@ -1911,14 +1924,14 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
/* HSW allows LP1+ watermarks even with multiple pipes */
if (level == 0 || config->num_pipes_active > 1) {
- fifo_size /= INTEL_INFO(dev)->num_pipes;
+ fifo_size /= INTEL_INFO(dev_priv)->num_pipes;
/*
* For some reason the non self refresh
* FIFO size is only half of the self
* refresh FIFO size on ILK/SNB.
*/
- if (INTEL_INFO(dev)->gen <= 6)
+ if (INTEL_GEN(dev_priv) <= 6)
fifo_size /= 2;
}
@@ -1934,7 +1947,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
}
/* clamp to max that the registers can hold */
- return min(fifo_size, ilk_plane_wm_reg_max(dev, level, is_sprite));
+ return min(fifo_size, ilk_plane_wm_reg_max(dev_priv, level, is_sprite));
}
/* Calculate the maximum cursor plane watermark */
@@ -1947,7 +1960,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
return 64;
/* otherwise just report max that registers can hold */
- return ilk_cursor_wm_reg_max(dev, level);
+ return ilk_cursor_wm_reg_max(to_i915(dev), level);
}
static void ilk_compute_wm_maximums(const struct drm_device *dev,
@@ -1959,17 +1972,17 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
max->cur = ilk_cursor_wm_max(dev, level, config);
- max->fbc = ilk_fbc_wm_reg_max(dev);
+ max->fbc = ilk_fbc_wm_reg_max(to_i915(dev));
}
-static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
+static void ilk_compute_wm_reg_maximums(const struct drm_i915_private *dev_priv,
int level,
struct ilk_wm_maximums *max)
{
- max->pri = ilk_plane_wm_reg_max(dev, level, false);
- max->spr = ilk_plane_wm_reg_max(dev, level, true);
- max->cur = ilk_cursor_wm_reg_max(dev, level);
- max->fbc = ilk_fbc_wm_reg_max(dev);
+ max->pri = ilk_plane_wm_reg_max(dev_priv, level, false);
+ max->spr = ilk_plane_wm_reg_max(dev_priv, level, true);
+ max->cur = ilk_cursor_wm_reg_max(dev_priv, level);
+ max->fbc = ilk_fbc_wm_reg_max(dev_priv);
}
static bool ilk_validate_wm_level(int level,
@@ -2076,14 +2089,13 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
PIPE_WM_LINETIME_TIME(linetime);
}
-static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
+static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
+ uint16_t wm[8])
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (IS_GEN9(dev)) {
+ if (IS_GEN9(dev_priv)) {
uint32_t val;
int ret, i;
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
/* read the first set of memory latencies[0:3] */
val = 0; /* data0 to be programmed to 0 for first set */
@@ -2155,7 +2167,7 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
}
}
- } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
uint64_t sskpd = I915_READ64(MCH_SSKPD);
wm[0] = (sskpd >> 56) & 0xFF;
@@ -2165,14 +2177,14 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
wm[2] = (sskpd >> 12) & 0xFF;
wm[3] = (sskpd >> 20) & 0x1FF;
wm[4] = (sskpd >> 32) & 0x1FF;
- } else if (INTEL_INFO(dev)->gen >= 6) {
+ } else if (INTEL_GEN(dev_priv) >= 6) {
uint32_t sskpd = I915_READ(MCH_SSKPD);
wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
- } else if (INTEL_INFO(dev)->gen >= 5) {
+ } else if (INTEL_GEN(dev_priv) >= 5) {
uint32_t mltr = I915_READ(MLTR_ILK);
/* ILK primary LP0 latency is 700 ns */
@@ -2182,42 +2194,44 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
}
}
-static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
+static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv,
+ uint16_t wm[5])
{
/* ILK sprite LP0 latency is 1300 ns */
- if (IS_GEN5(dev))
+ if (IS_GEN5(dev_priv))
wm[0] = 13;
}
-static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
+static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv,
+ uint16_t wm[5])
{
/* ILK cursor LP0 latency is 1300 ns */
- if (IS_GEN5(dev))
+ if (IS_GEN5(dev_priv))
wm[0] = 13;
/* WaDoubleCursorLP3Latency:ivb */
- if (IS_IVYBRIDGE(dev))
+ if (IS_IVYBRIDGE(dev_priv))
wm[3] *= 2;
}
-int ilk_wm_max_level(const struct drm_device *dev)
+int ilk_wm_max_level(const struct drm_i915_private *dev_priv)
{
/* how many WM levels are we expecting */
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
return 7;
- else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
return 4;
- else if (INTEL_INFO(dev)->gen >= 6)
+ else if (INTEL_GEN(dev_priv) >= 6)
return 3;
else
return 2;
}
-static void intel_print_wm_latency(struct drm_device *dev,
+static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
const char *name,
const uint16_t wm[8])
{
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
for (level = 0; level <= max_level; level++) {
unsigned int latency = wm[level];
@@ -2232,7 +2246,7 @@ static void intel_print_wm_latency(struct drm_device *dev,
* - latencies are in us on gen9.
* - before then, WM1+ latency values are in 0.5us units
*/
- if (IS_GEN9(dev))
+ if (IS_GEN9(dev_priv))
latency *= 10;
else if (level > 0)
latency *= 5;
@@ -2246,7 +2260,7 @@ static void intel_print_wm_latency(struct drm_device *dev,
static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
uint16_t wm[5], uint16_t min)
{
- int level, max_level = ilk_wm_max_level(&dev_priv->drm);
+ int level, max_level = ilk_wm_max_level(dev_priv);
if (wm[0] >= min)
return false;
@@ -2258,9 +2272,8 @@ static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
return true;
}
-static void snb_wm_latency_quirk(struct drm_device *dev)
+static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
bool changed;
/*
@@ -2275,39 +2288,35 @@ static void snb_wm_latency_quirk(struct drm_device *dev)
return;
DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n");
- intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
- intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
- intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+ intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+ intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+ intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
}
-static void ilk_setup_wm_latency(struct drm_device *dev)
+static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- intel_read_wm_latency(dev, dev_priv->wm.pri_latency);
+ intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency);
memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency,
sizeof(dev_priv->wm.pri_latency));
memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency,
sizeof(dev_priv->wm.pri_latency));
- intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
- intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
+ intel_fixup_spr_wm_latency(dev_priv, dev_priv->wm.spr_latency);
+ intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency);
- intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
- intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
- intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+ intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+ intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+ intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
- if (IS_GEN6(dev))
- snb_wm_latency_quirk(dev);
+ if (IS_GEN6(dev_priv))
+ snb_wm_latency_quirk(dev_priv);
}
-static void skl_setup_wm_latency(struct drm_device *dev)
+static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- intel_read_wm_latency(dev, dev_priv->wm.skl_latency);
- intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
+ intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency);
+ intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency);
}
static bool ilk_validate_pipe_wm(struct drm_device *dev,
@@ -2345,7 +2354,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
struct intel_plane_state *pristate = NULL;
struct intel_plane_state *sprstate = NULL;
struct intel_plane_state *curstate = NULL;
- int level, max_level = ilk_wm_max_level(dev), usable_level;
+ int level, max_level = ilk_wm_max_level(dev_priv), usable_level;
struct ilk_wm_maximums max;
pipe_wm = &cstate->wm.ilk.optimal;
@@ -2377,7 +2386,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
usable_level = max_level;
/* ILK/SNB: LP2+ watermarks only w/o sprites */
- if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+ if (INTEL_GEN(dev_priv) <= 6 && pipe_wm->sprites_enabled)
usable_level = 1;
/* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
@@ -2390,13 +2399,13 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm));
pipe_wm->wm[0] = pipe_wm->raw_wm[0];
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
pipe_wm->linetime = hsw_compute_linetime_wm(cstate);
if (!ilk_validate_pipe_wm(dev, pipe_wm))
return -EINVAL;
- ilk_compute_wm_reg_maximums(dev, 1, &max);
+ ilk_compute_wm_reg_maximums(dev_priv, 1, &max);
for (level = 1; level <= max_level; level++) {
struct intel_wm_level *wm = &pipe_wm->raw_wm[level];
@@ -2432,7 +2441,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
{
struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate;
struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(to_i915(dev));
/*
* Start with the final, target watermarks, then combine with the
@@ -2516,16 +2525,16 @@ static void ilk_wm_merge(struct drm_device *dev,
struct intel_pipe_wm *merged)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
int last_enabled_level = max_level;
/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
- if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
+ if ((INTEL_GEN(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) &&
config->num_pipes_active > 1)
last_enabled_level = 0;
/* ILK: FBC WM must be disabled always */
- merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
+ merged->fbc_wm_enabled = INTEL_GEN(dev_priv) >= 6;
/* merge each WM1+ level */
for (level = 1; level <= max_level; level++) {
@@ -2556,7 +2565,7 @@ static void ilk_wm_merge(struct drm_device *dev,
* What we should check here is whether FBC can be
* enabled sometime later.
*/
- if (IS_GEN5(dev) && !merged->fbc_wm_enabled &&
+ if (IS_GEN5(dev_priv) && !merged->fbc_wm_enabled &&
intel_fbc_is_active(dev_priv)) {
for (level = 2; level <= max_level; level++) {
struct intel_wm_level *wm = &merged->wm[level];
@@ -2577,7 +2586,7 @@ static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
return 2 * level;
else
return dev_priv->wm.pri_latency[level];
@@ -2588,6 +2597,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
enum intel_ddb_partitioning partitioning,
struct ilk_wm_values *results)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc;
int level, wm_lp;
@@ -2614,7 +2624,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
if (r->enable)
results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
- if (INTEL_INFO(dev)->gen >= 8)
+ if (INTEL_GEN(dev_priv) >= 8)
results->wm_lp[wm_lp - 1] |=
r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
else
@@ -2625,7 +2635,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
* Always set WM1S_LP_EN when spr_val != 0, even if the
* level is disabled. Doing otherwise could cause underruns.
*/
- if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
+ if (INTEL_GEN(dev_priv) <= 6 && r->spr_val) {
WARN_ON(wm_lp != 1);
results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
} else
@@ -2656,7 +2666,7 @@ static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
struct intel_pipe_wm *r1,
struct intel_pipe_wm *r2)
{
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(to_i915(dev));
int level1 = 0, level2 = 0;
for (level = 1; level <= max_level; level++) {
@@ -2775,7 +2785,6 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
struct ilk_wm_values *results)
{
- struct drm_device *dev = &dev_priv->drm;
struct ilk_wm_values *previous = &dev_priv->wm.hw;
unsigned int dirty;
uint32_t val;
@@ -2801,7 +2810,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
if (dirty & WM_DIRTY_DDB) {
- if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
val = I915_READ(WM_MISC);
if (results->partitioning == INTEL_DDB_PART_1_2)
val &= ~WM_MISC_DATA_PARTITION_5_6;
@@ -2831,7 +2840,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
previous->wm_lp_spr[0] != results->wm_lp_spr[0])
I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
- if (INTEL_INFO(dev)->gen >= 7) {
+ if (INTEL_GEN(dev_priv) >= 7) {
if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
@@ -2879,6 +2888,21 @@ skl_wm_plane_id(const struct intel_plane *plane)
}
}
+/*
+ * FIXME: We still don't have the proper code detect if we need to apply the WA,
+ * so assume we'll always need it in order to avoid underruns.
+ */
+static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+
+ if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) ||
+ IS_KABYLAKE(dev_priv))
+ return true;
+
+ return false;
+}
+
static bool
intel_has_sagv(struct drm_i915_private *dev_priv)
{
@@ -2999,9 +3023,12 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
struct drm_device *dev = state->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
- struct drm_crtc *crtc;
+ struct intel_crtc *crtc;
+ struct intel_plane *plane;
+ struct intel_crtc_state *cstate;
+ struct skl_plane_wm *wm;
enum pipe pipe;
- int level, plane;
+ int level, latency;
if (!intel_has_sagv(dev_priv))
return false;
@@ -3019,27 +3046,37 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
/* Since we're now guaranteed to only have one active CRTC... */
pipe = ffs(intel_state->active_crtcs) - 1;
- crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+ cstate = to_intel_crtc_state(crtc->base.state);
- if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE)
+ if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
return false;
- for_each_plane(dev_priv, pipe, plane) {
+ for_each_intel_plane_on_crtc(dev, crtc, plane) {
+ wm = &cstate->wm.skl.optimal.planes[skl_wm_plane_id(plane)];
+
/* Skip this plane if it's not enabled */
- if (intel_state->wm_results.plane[pipe][plane][0] == 0)
+ if (!wm->wm[0].plane_en)
continue;
/* Find the highest enabled wm level for this plane */
- for (level = ilk_wm_max_level(dev);
- intel_state->wm_results.plane[pipe][plane][level] == 0; --level)
+ for (level = ilk_wm_max_level(dev_priv);
+ !wm->wm[level].plane_en; --level)
{ }
+ latency = dev_priv->wm.skl_latency[level];
+
+ if (skl_needs_memory_bw_wa(intel_state) &&
+ plane->base.state->fb->modifier ==
+ I915_FORMAT_MOD_X_TILED)
+ latency += 15;
+
/*
* If any of the planes on this pipe don't enable wm levels
* that incur memory latencies higher then 30µs we can't enable
* the SAGV
*/
- if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME)
+ if (latency < SKL_SAGV_BLOCK_TIME)
return false;
}
@@ -3058,7 +3095,6 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
struct drm_crtc *for_crtc = cstate->base.crtc;
unsigned int pipe_size, ddb_size;
int nth_active_pipe;
- int pipe = to_intel_crtc(for_crtc)->pipe;
if (WARN_ON(!state) || !cstate->base.active) {
alloc->start = 0;
@@ -3086,7 +3122,11 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
* we currently hold.
*/
if (!intel_state->active_pipe_changes) {
- *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
+ /*
+ * alloc may be cleared by clear_intel_crtc_state,
+ * copy from old state to be sure
+ */
+ *alloc = to_intel_crtc_state(for_crtc->state)->wm.skl.ddb;
return;
}
@@ -3129,7 +3169,7 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
continue;
- for_each_plane(dev_priv, pipe, plane) {
+ for_each_universal_plane(dev_priv, pipe, plane) {
val = I915_READ(PLANE_BUF_CFG(pipe, plane));
skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane],
val);
@@ -3173,7 +3213,7 @@ skl_plane_downscale_amount(const struct intel_plane_state *pstate)
src_h = drm_rect_height(&pstate->base.src);
dst_w = drm_rect_width(&pstate->base.dst);
dst_h = drm_rect_height(&pstate->base.dst);
- if (intel_rotation_90_or_270(pstate->base.rotation))
+ if (drm_rotation_90_or_270(pstate->base.rotation))
swap(dst_w, dst_h);
downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
@@ -3204,7 +3244,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
width = drm_rect_width(&intel_pstate->base.src) >> 16;
height = drm_rect_height(&intel_pstate->base.src) >> 16;
- if (intel_rotation_90_or_270(pstate->rotation))
+ if (drm_rotation_90_or_270(pstate->rotation))
swap(width, height);
/* for planar format */
@@ -3231,49 +3271,39 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
* 3 * 4096 * 8192 * 4 < 2^32
*/
static unsigned int
-skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
+skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
+ unsigned *plane_data_rate,
+ unsigned *plane_y_data_rate)
{
struct drm_crtc_state *cstate = &intel_cstate->base;
struct drm_atomic_state *state = cstate->state;
- struct drm_crtc *crtc = cstate->crtc;
- struct drm_device *dev = crtc->dev;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- const struct drm_plane *plane;
+ struct drm_plane *plane;
const struct intel_plane *intel_plane;
- struct drm_plane_state *pstate;
+ const struct drm_plane_state *pstate;
unsigned int rate, total_data_rate = 0;
int id;
- int i;
if (WARN_ON(!state))
return 0;
/* Calculate and cache data rate for each plane */
- for_each_plane_in_state(state, plane, pstate, i) {
+ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) {
id = skl_wm_plane_id(to_intel_plane(plane));
intel_plane = to_intel_plane(plane);
- if (intel_plane->pipe != intel_crtc->pipe)
- continue;
-
/* packed/uv */
rate = skl_plane_relative_data_rate(intel_cstate,
pstate, 0);
- intel_cstate->wm.skl.plane_data_rate[id] = rate;
+ plane_data_rate[id] = rate;
+
+ total_data_rate += rate;
/* y-plane */
rate = skl_plane_relative_data_rate(intel_cstate,
pstate, 1);
- intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
- }
-
- /* Calculate CRTC's total data rate from cached values */
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- int id = skl_wm_plane_id(intel_plane);
+ plane_y_data_rate[id] = rate;
- /* packed/uv */
- total_data_rate += intel_cstate->wm.skl.plane_data_rate[id];
- total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id];
+ total_data_rate += rate;
}
return total_data_rate;
@@ -3297,14 +3327,14 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
return 0;
/* For Non Y-tile return 8-blocks */
- if (fb->modifier[0] != I915_FORMAT_MOD_Y_TILED &&
- fb->modifier[0] != I915_FORMAT_MOD_Yf_TILED)
+ if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
+ fb->modifier != I915_FORMAT_MOD_Yf_TILED)
return 8;
src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
src_h = drm_rect_height(&intel_pstate->base.src) >> 16;
- if (intel_rotation_90_or_270(pstate->rotation))
+ if (drm_rotation_90_or_270(pstate->rotation))
swap(src_w, src_h);
/* Halve UV plane width and height for NV12 */
@@ -3318,7 +3348,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
else
plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0);
- if (intel_rotation_90_or_270(pstate->rotation)) {
+ if (drm_rotation_90_or_270(pstate->rotation)) {
switch (plane_bpp) {
case 1:
min_scanlines = 32;
@@ -3342,6 +3372,30 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3;
}
+static void
+skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active,
+ uint16_t *minimum, uint16_t *y_minimum)
+{
+ const struct drm_plane_state *pstate;
+ struct drm_plane *plane;
+
+ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) {
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ int id = skl_wm_plane_id(intel_plane);
+
+ if (id == PLANE_CURSOR)
+ continue;
+
+ if (!pstate->visible)
+ continue;
+
+ minimum[id] = skl_ddb_min_alloc(pstate, 0);
+ y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
+ }
+
+ minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active);
+}
+
static int
skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct skl_ddb_allocation *ddb /* out */)
@@ -3350,17 +3404,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_plane *intel_plane;
- struct drm_plane *plane;
- struct drm_plane_state *pstate;
enum pipe pipe = intel_crtc->pipe;
- struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
- uint16_t alloc_size, start, cursor_blocks;
- uint16_t *minimum = cstate->wm.skl.minimum_blocks;
- uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks;
+ struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb;
+ uint16_t alloc_size, start;
+ uint16_t minimum[I915_MAX_PLANES] = {};
+ uint16_t y_minimum[I915_MAX_PLANES] = {};
unsigned int total_data_rate;
int num_active;
int id, i;
+ unsigned plane_data_rate[I915_MAX_PLANES] = {};
+ unsigned plane_y_data_rate[I915_MAX_PLANES] = {};
/* Clear the partitioning for disabled planes. */
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -3370,7 +3423,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
return 0;
if (!cstate->base.active) {
- ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
+ alloc->start = alloc->end = 0;
return 0;
}
@@ -3381,57 +3434,43 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
return 0;
}
- cursor_blocks = skl_cursor_allocation(num_active);
- ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks;
- ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
-
- alloc_size -= cursor_blocks;
-
- /* 1. Allocate the mininum required blocks for each active plane */
- for_each_plane_in_state(state, plane, pstate, i) {
- intel_plane = to_intel_plane(plane);
- id = skl_wm_plane_id(intel_plane);
-
- if (intel_plane->pipe != pipe)
- continue;
-
- if (!to_intel_plane_state(pstate)->base.visible) {
- minimum[id] = 0;
- y_minimum[id] = 0;
- continue;
- }
- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
- minimum[id] = 0;
- y_minimum[id] = 0;
- continue;
- }
+ skl_ddb_calc_min(cstate, num_active, minimum, y_minimum);
- minimum[id] = skl_ddb_min_alloc(pstate, 0);
- y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
- }
+ /*
+ * 1. Allocate the mininum required blocks for each active plane
+ * and allocate the cursor, it doesn't require extra allocation
+ * proportional to the data rate.
+ */
- for (i = 0; i < PLANE_CURSOR; i++) {
+ for (i = 0; i < I915_MAX_PLANES; i++) {
alloc_size -= minimum[i];
alloc_size -= y_minimum[i];
}
+ ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
+ ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
+
/*
* 2. Distribute the remaining space in proportion to the amount of
* data each plane needs to fetch from memory.
*
* FIXME: we may not allocate every single block here.
*/
- total_data_rate = skl_get_total_relative_data_rate(cstate);
+ total_data_rate = skl_get_total_relative_data_rate(cstate,
+ plane_data_rate,
+ plane_y_data_rate);
if (total_data_rate == 0)
return 0;
start = alloc->start;
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ for (id = 0; id < I915_MAX_PLANES; id++) {
unsigned int data_rate, y_data_rate;
uint16_t plane_blocks, y_plane_blocks = 0;
- int id = skl_wm_plane_id(intel_plane);
- data_rate = cstate->wm.skl.plane_data_rate[id];
+ if (id == PLANE_CURSOR)
+ continue;
+
+ data_rate = plane_data_rate[id];
/*
* allocation for (packed formats) or (uv-plane part of planar format):
@@ -3453,7 +3492,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
/*
* allocation for y_plane part of planar format:
*/
- y_data_rate = cstate->wm.skl.plane_y_data_rate[id];
+ y_data_rate = plane_y_data_rate[id];
y_plane_blocks = y_minimum[id];
y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
@@ -3549,22 +3588,28 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
uint32_t width = 0, height = 0;
uint32_t plane_pixel_rate;
uint32_t y_tile_minimum, y_min_scanlines;
+ struct intel_atomic_state *state =
+ to_intel_atomic_state(cstate->base.state);
+ bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) {
*enabled = false;
return 0;
}
+ if (apply_memory_bw_wa && fb->modifier == I915_FORMAT_MOD_X_TILED)
+ latency += 15;
+
width = drm_rect_width(&intel_pstate->base.src) >> 16;
height = drm_rect_height(&intel_pstate->base.src) >> 16;
- if (intel_rotation_90_or_270(pstate->rotation))
+ if (drm_rotation_90_or_270(pstate->rotation))
swap(width, height);
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
- if (intel_rotation_90_or_270(pstate->rotation)) {
+ if (drm_rotation_90_or_270(pstate->rotation)) {
int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
drm_format_plane_cpp(fb->pixel_format, 1) :
drm_format_plane_cpp(fb->pixel_format, 0);
@@ -3576,23 +3621,27 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
case 2:
y_min_scanlines = 8;
break;
- default:
- WARN(1, "Unsupported pixel depth for rotation");
case 4:
y_min_scanlines = 4;
break;
+ default:
+ MISSING_CASE(cpp);
+ return -EINVAL;
}
} else {
y_min_scanlines = 4;
}
+ if (apply_memory_bw_wa)
+ y_min_scanlines *= 2;
+
plane_bytes_per_line = width * cpp;
- if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+ if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
plane_blocks_per_line =
DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512);
plane_blocks_per_line /= y_min_scanlines;
- } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) {
+ } else if (fb->modifier == DRM_FORMAT_MOD_NONE) {
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512)
+ 1;
} else {
@@ -3607,11 +3656,14 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
y_tile_minimum = plane_blocks_per_line * y_min_scanlines;
- if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+ if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
selected_result = max(method2, y_tile_minimum);
} else {
- if ((ddb_allocation / plane_blocks_per_line) >= 1)
+ if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) &&
+ (plane_bytes_per_line / 512 < 1))
+ selected_result = method2;
+ else if ((ddb_allocation / plane_blocks_per_line) >= 1)
selected_result = min(method1, method2);
else
selected_result = method1;
@@ -3621,8 +3673,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
if (level >= 1 && level <= 7) {
- if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+ if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+ fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
res_blocks += y_tile_minimum;
res_lines += y_min_scanlines;
} else {
@@ -3661,67 +3713,52 @@ static int
skl_compute_wm_level(const struct drm_i915_private *dev_priv,
struct skl_ddb_allocation *ddb,
struct intel_crtc_state *cstate,
+ struct intel_plane *intel_plane,
int level,
struct skl_wm_level *result)
{
struct drm_atomic_state *state = cstate->base.state;
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
- struct drm_plane *plane;
- struct intel_plane *intel_plane;
- struct intel_plane_state *intel_pstate;
+ struct drm_plane *plane = &intel_plane->base;
+ struct intel_plane_state *intel_pstate = NULL;
uint16_t ddb_blocks;
enum pipe pipe = intel_crtc->pipe;
int ret;
+ int i = skl_wm_plane_id(intel_plane);
+
+ if (state)
+ intel_pstate =
+ intel_atomic_get_existing_plane_state(state,
+ intel_plane);
/*
- * We'll only calculate watermarks for planes that are actually
- * enabled, so make sure all other planes are set as disabled.
+ * Note: If we start supporting multiple pending atomic commits against
+ * the same planes/CRTC's in the future, plane->state will no longer be
+ * the correct pre-state to use for the calculations here and we'll
+ * need to change where we get the 'unchanged' plane data from.
+ *
+ * For now this is fine because we only allow one queued commit against
+ * a CRTC. Even if the plane isn't modified by this transaction and we
+ * don't have a plane lock, we still have the CRTC's lock, so we know
+ * that no other transactions are racing with us to update it.
*/
- memset(result, 0, sizeof(*result));
-
- for_each_intel_plane_mask(&dev_priv->drm,
- intel_plane,
- cstate->base.plane_mask) {
- int i = skl_wm_plane_id(intel_plane);
-
- plane = &intel_plane->base;
- intel_pstate = NULL;
- if (state)
- intel_pstate =
- intel_atomic_get_existing_plane_state(state,
- intel_plane);
-
- /*
- * Note: If we start supporting multiple pending atomic commits
- * against the same planes/CRTC's in the future, plane->state
- * will no longer be the correct pre-state to use for the
- * calculations here and we'll need to change where we get the
- * 'unchanged' plane data from.
- *
- * For now this is fine because we only allow one queued commit
- * against a CRTC. Even if the plane isn't modified by this
- * transaction and we don't have a plane lock, we still have
- * the CRTC's lock, so we know that no other transactions are
- * racing with us to update it.
- */
- if (!intel_pstate)
- intel_pstate = to_intel_plane_state(plane->state);
+ if (!intel_pstate)
+ intel_pstate = to_intel_plane_state(plane->state);
- WARN_ON(!intel_pstate->base.fb);
+ WARN_ON(!intel_pstate->base.fb);
- ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
+ ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
- ret = skl_compute_plane_wm(dev_priv,
- cstate,
- intel_pstate,
- ddb_blocks,
- level,
- &result->plane_res_b[i],
- &result->plane_res_l[i],
- &result->plane_en[i]);
- if (ret)
- return ret;
- }
+ ret = skl_compute_plane_wm(dev_priv,
+ cstate,
+ intel_pstate,
+ ddb_blocks,
+ level,
+ &result->plane_res_b,
+ &result->plane_res_l,
+ &result->plane_en);
+ if (ret)
+ return ret;
return 0;
}
@@ -3729,32 +3766,28 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
static uint32_t
skl_compute_linetime_wm(struct intel_crtc_state *cstate)
{
+ uint32_t pixel_rate;
+
if (!cstate->base.active)
return 0;
- if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0))
+ pixel_rate = ilk_pipe_pixel_rate(cstate);
+
+ if (WARN_ON(pixel_rate == 0))
return 0;
return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
- ilk_pipe_pixel_rate(cstate));
+ pixel_rate);
}
static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
struct skl_wm_level *trans_wm /* out */)
{
- struct drm_crtc *crtc = cstate->base.crtc;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_plane *intel_plane;
-
if (!cstate->base.active)
return;
/* Until we know more, just disable transition WMs */
- for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) {
- int i = skl_wm_plane_id(intel_plane);
-
- trans_wm->plane_en[i] = false;
- }
+ trans_wm->plane_en = false;
}
static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
@@ -3763,77 +3796,34 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
{
struct drm_device *dev = cstate->base.crtc->dev;
const struct drm_i915_private *dev_priv = to_i915(dev);
- int level, max_level = ilk_wm_max_level(dev);
+ struct intel_plane *intel_plane;
+ struct skl_plane_wm *wm;
+ int level, max_level = ilk_wm_max_level(dev_priv);
int ret;
- for (level = 0; level <= max_level; level++) {
- ret = skl_compute_wm_level(dev_priv, ddb, cstate,
- level, &pipe_wm->wm[level]);
- if (ret)
- return ret;
- }
- pipe_wm->linetime = skl_compute_linetime_wm(cstate);
-
- skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
-
- return 0;
-}
-
-static void skl_compute_wm_results(struct drm_device *dev,
- struct skl_pipe_wm *p_wm,
- struct skl_wm_values *r,
- struct intel_crtc *intel_crtc)
-{
- int level, max_level = ilk_wm_max_level(dev);
- enum pipe pipe = intel_crtc->pipe;
- uint32_t temp;
- int i;
-
- for (level = 0; level <= max_level; level++) {
- for (i = 0; i < intel_num_planes(intel_crtc); i++) {
- temp = 0;
-
- temp |= p_wm->wm[level].plane_res_l[i] <<
- PLANE_WM_LINES_SHIFT;
- temp |= p_wm->wm[level].plane_res_b[i];
- if (p_wm->wm[level].plane_en[i])
- temp |= PLANE_WM_EN;
+ /*
+ * We'll only calculate watermarks for planes that are actually
+ * enabled, so make sure all other planes are set as disabled.
+ */
+ memset(pipe_wm->planes, 0, sizeof(pipe_wm->planes));
- r->plane[pipe][i][level] = temp;
+ for_each_intel_plane_mask(&dev_priv->drm,
+ intel_plane,
+ cstate->base.plane_mask) {
+ wm = &pipe_wm->planes[skl_wm_plane_id(intel_plane)];
+
+ for (level = 0; level <= max_level; level++) {
+ ret = skl_compute_wm_level(dev_priv, ddb, cstate,
+ intel_plane, level,
+ &wm->wm[level]);
+ if (ret)
+ return ret;
}
-
- temp = 0;
-
- 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].plane_en[PLANE_CURSOR])
- temp |= PLANE_WM_EN;
-
- r->plane[pipe][PLANE_CURSOR][level] = temp;
-
+ skl_compute_transition_wm(cstate, &wm->trans_wm);
}
+ pipe_wm->linetime = skl_compute_linetime_wm(cstate);
- /* transition WMs */
- for (i = 0; i < intel_num_planes(intel_crtc); i++) {
- temp = 0;
- temp |= p_wm->trans_wm.plane_res_l[i] << PLANE_WM_LINES_SHIFT;
- temp |= p_wm->trans_wm.plane_res_b[i];
- if (p_wm->trans_wm.plane_en[i])
- temp |= PLANE_WM_EN;
-
- r->plane_trans[pipe][i] = temp;
- }
-
- temp = 0;
- 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->plane_trans[pipe][PLANE_CURSOR] = temp;
-
- r->wm_linetime[pipe] = p_wm->linetime;
+ return 0;
}
static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
@@ -3846,53 +3836,77 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
I915_WRITE(reg, 0);
}
-void skl_write_plane_wm(struct intel_crtc *intel_crtc,
- const struct skl_wm_values *wm,
- int plane)
+static void skl_write_wm_level(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
+ const struct skl_wm_level *level)
+{
+ uint32_t val = 0;
+
+ if (level->plane_en) {
+ val |= PLANE_WM_EN;
+ val |= level->plane_res_b;
+ val |= level->plane_res_l << PLANE_WM_LINES_SHIFT;
+ }
+
+ I915_WRITE(reg, val);
+}
+
+static void skl_write_plane_wm(struct intel_crtc *intel_crtc,
+ const struct skl_plane_wm *wm,
+ const struct skl_ddb_allocation *ddb,
+ int plane)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
enum pipe pipe = intel_crtc->pipe;
for (level = 0; level <= max_level; level++) {
- I915_WRITE(PLANE_WM(pipe, plane, level),
- wm->plane[pipe][plane][level]);
+ skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane, level),
+ &wm->wm[level]);
}
- I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]);
+ skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane),
+ &wm->trans_wm);
skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane),
- &wm->ddb.plane[pipe][plane]);
+ &ddb->plane[pipe][plane]);
skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane),
- &wm->ddb.y_plane[pipe][plane]);
+ &ddb->y_plane[pipe][plane]);
}
-void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
- const struct skl_wm_values *wm)
+static void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
+ const struct skl_plane_wm *wm,
+ const struct skl_ddb_allocation *ddb)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
enum pipe pipe = intel_crtc->pipe;
for (level = 0; level <= max_level; level++) {
- I915_WRITE(CUR_WM(pipe, level),
- wm->plane[pipe][PLANE_CURSOR][level]);
+ skl_write_wm_level(dev_priv, CUR_WM(pipe, level),
+ &wm->wm[level]);
}
- I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]);
+ skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm);
skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe),
- &wm->ddb.plane[pipe][PLANE_CURSOR]);
+ &ddb->plane[pipe][PLANE_CURSOR]);
}
-bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old,
- const struct skl_ddb_allocation *new,
- enum pipe pipe)
+bool skl_wm_level_equals(const struct skl_wm_level *l1,
+ const struct skl_wm_level *l2)
{
- return new->pipe[pipe].start == old->pipe[pipe].start &&
- new->pipe[pipe].end == old->pipe[pipe].end;
+ if (l1->plane_en != l2->plane_en)
+ return false;
+
+ /* If both planes aren't enabled, the rest shouldn't matter */
+ if (!l1->plane_en)
+ return true;
+
+ return (l1->plane_res_l == l2->plane_res_l &&
+ l1->plane_res_b == l2->plane_res_b);
}
static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a,
@@ -3901,35 +3915,26 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a,
return a->start < b->end && b->start < a->end;
}
-bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state,
- const struct skl_ddb_allocation *old,
- const struct skl_ddb_allocation *new,
- enum pipe pipe)
+bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
+ const struct skl_ddb_entry *ddb,
+ int ignore)
{
- struct drm_device *dev = state->dev;
- struct intel_crtc *intel_crtc;
- enum pipe otherp;
-
- for_each_intel_crtc(dev, intel_crtc) {
- otherp = intel_crtc->pipe;
-
- if (otherp == pipe)
- continue;
+ int i;
- if (skl_ddb_entries_overlap(&new->pipe[pipe],
- &old->pipe[otherp]))
+ for (i = 0; i < I915_MAX_PIPES; i++)
+ if (i != ignore && entries[i] &&
+ skl_ddb_entries_overlap(ddb, entries[i]))
return true;
- }
return false;
}
static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
- struct skl_ddb_allocation *ddb, /* out */
+ const struct skl_pipe_wm *old_pipe_wm,
struct skl_pipe_wm *pipe_wm, /* out */
+ struct skl_ddb_allocation *ddb, /* out */
bool *changed /* out */)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
int ret;
@@ -3937,7 +3942,7 @@ static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
if (ret)
return ret;
- if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
+ if (!memcmp(old_pipe_wm, pipe_wm, sizeof(*pipe_wm)))
*changed = false;
else
*changed = true;
@@ -3958,7 +3963,7 @@ pipes_modified(struct drm_atomic_state *state)
return ret;
}
-int
+static int
skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
{
struct drm_atomic_state *state = cstate->base.state;
@@ -3976,7 +3981,7 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc));
- drm_for_each_plane_mask(plane, dev, crtc->state->plane_mask) {
+ drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) {
id = skl_wm_plane_id(to_intel_plane(plane));
if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][id],
@@ -4076,19 +4081,50 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst,
struct skl_wm_values *src,
enum pipe pipe)
{
- dst->wm_linetime[pipe] = src->wm_linetime[pipe];
- memcpy(dst->plane[pipe], src->plane[pipe],
- sizeof(dst->plane[pipe]));
- memcpy(dst->plane_trans[pipe], src->plane_trans[pipe],
- sizeof(dst->plane_trans[pipe]));
-
- dst->ddb.pipe[pipe] = src->ddb.pipe[pipe];
memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe],
sizeof(dst->ddb.y_plane[pipe]));
memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe],
sizeof(dst->ddb.plane[pipe]));
}
+static void
+skl_print_wm_changes(const struct drm_atomic_state *state)
+{
+ const struct drm_device *dev = state->dev;
+ const struct drm_i915_private *dev_priv = to_i915(dev);
+ const struct intel_atomic_state *intel_state =
+ to_intel_atomic_state(state);
+ const struct drm_crtc *crtc;
+ const struct drm_crtc_state *cstate;
+ const struct intel_plane *intel_plane;
+ const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb;
+ const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
+ int id;
+ int i;
+
+ for_each_crtc_in_state(state, crtc, cstate, i) {
+ const struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum pipe pipe = intel_crtc->pipe;
+
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ const struct skl_ddb_entry *old, *new;
+
+ id = skl_wm_plane_id(intel_plane);
+ old = &old_ddb->plane[pipe][id];
+ new = &new_ddb->plane[pipe][id];
+
+ if (skl_ddb_entry_equal(old, new))
+ continue;
+
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n",
+ intel_plane->base.base.id,
+ intel_plane->base.name,
+ old->start, old->end,
+ new->start, new->end);
+ }
+ }
+}
+
static int
skl_compute_wm(struct drm_atomic_state *state)
{
@@ -4131,13 +4167,14 @@ skl_compute_wm(struct drm_atomic_state *state)
* no suitable watermark values can be found.
*/
for_each_crtc_in_state(state, crtc, cstate, i) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *intel_cstate =
to_intel_crtc_state(cstate);
+ const struct skl_pipe_wm *old_pipe_wm =
+ &to_intel_crtc_state(crtc->state)->wm.skl.optimal;
pipe_wm = &intel_cstate->wm.skl.optimal;
- ret = skl_update_pipe_wm(cstate, &results->ddb, pipe_wm,
- &changed);
+ ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm,
+ &results->ddb, &changed);
if (ret)
return ret;
@@ -4149,44 +4186,51 @@ skl_compute_wm(struct drm_atomic_state *state)
continue;
intel_cstate->update_wm_pre = true;
- skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc);
}
+ skl_print_wm_changes(state);
+
return 0;
}
-static void skl_update_wm(struct drm_crtc *crtc)
+static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct skl_wm_values *results = &dev_priv->wm.skl_results;
- struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw;
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+ struct intel_crtc *crtc = to_intel_crtc(cstate->base.crtc);
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
- enum pipe pipe = intel_crtc->pipe;
+ const struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
+ enum pipe pipe = crtc->pipe;
+ int plane;
- if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0)
+ if (!(state->wm_results.dirty_pipes & drm_crtc_mask(&crtc->base)))
return;
- intel_crtc->wm.active.skl = *pipe_wm;
+ I915_WRITE(PIPE_WM_LINETIME(pipe), pipe_wm->linetime);
- mutex_lock(&dev_priv->wm.wm_mutex);
+ for_each_universal_plane(dev_priv, pipe, plane)
+ skl_write_plane_wm(crtc, &pipe_wm->planes[plane], ddb, plane);
- /*
- * If this pipe isn't active already, we're going to be enabling it
- * very soon. Since it's safe to update a pipe's ddb allocation while
- * the pipe's shut off, just do so here. Already active pipes will have
- * their watermarks updated once we update their planes.
- */
- if (crtc->state->active_changed) {
- int plane;
+ skl_write_cursor_wm(crtc, &pipe_wm->planes[PLANE_CURSOR], ddb);
+}
+
+static void skl_initial_wm(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+ struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct skl_wm_values *results = &state->wm_results;
+ struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw;
+ enum pipe pipe = intel_crtc->pipe;
- for (plane = 0; plane < intel_num_planes(intel_crtc); plane++)
- skl_write_plane_wm(intel_crtc, results, plane);
+ if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0)
+ return;
- skl_write_cursor_wm(intel_crtc, results);
- }
+ mutex_lock(&dev_priv->wm.wm_mutex);
+
+ if (cstate->base.active_changed)
+ skl_atomic_update_crtc_wm(state, cstate);
skl_copy_wm_for_pipe(hw_vals, results, pipe);
@@ -4226,7 +4270,7 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
/* 5/6 split only in single pipe config on IVB+ */
- if (INTEL_INFO(dev)->gen >= 7 &&
+ if (INTEL_GEN(dev_priv) >= 7 &&
config.num_pipes_active == 1 && config.sprites_enabled) {
ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
@@ -4244,7 +4288,8 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
ilk_write_wm_values(dev_priv, &results);
}
-static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
+static void ilk_initial_watermarks(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate)
{
struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
@@ -4255,7 +4300,8 @@ static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
mutex_unlock(&dev_priv->wm.wm_mutex);
}
-static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
+static void ilk_optimize_watermarks(struct intel_atomic_state *state,
+ struct intel_crtc_state *cstate)
{
struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
@@ -4268,114 +4314,75 @@ static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
mutex_unlock(&dev_priv->wm.wm_mutex);
}
-static void skl_pipe_wm_active_state(uint32_t val,
- struct skl_pipe_wm *active,
- bool is_transwm,
- bool is_cursor,
- int i,
- int level)
+static inline void skl_wm_level_from_reg_val(uint32_t val,
+ struct skl_wm_level *level)
{
- bool is_enabled = (val & PLANE_WM_EN) != 0;
-
- if (!is_transwm) {
- if (!is_cursor) {
- active->wm[level].plane_en[i] = is_enabled;
- active->wm[level].plane_res_b[i] =
- val & PLANE_WM_BLOCKS_MASK;
- active->wm[level].plane_res_l[i] =
- (val >> PLANE_WM_LINES_SHIFT) &
- PLANE_WM_LINES_MASK;
- } else {
- 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].plane_res_l[PLANE_CURSOR] =
- (val >> PLANE_WM_LINES_SHIFT) &
- PLANE_WM_LINES_MASK;
- }
- } else {
- if (!is_cursor) {
- active->trans_wm.plane_en[i] = is_enabled;
- active->trans_wm.plane_res_b[i] =
- val & PLANE_WM_BLOCKS_MASK;
- active->trans_wm.plane_res_l[i] =
- (val >> PLANE_WM_LINES_SHIFT) &
- PLANE_WM_LINES_MASK;
- } else {
- 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.plane_res_l[PLANE_CURSOR] =
- (val >> PLANE_WM_LINES_SHIFT) &
- PLANE_WM_LINES_MASK;
- }
- }
+ level->plane_en = val & PLANE_WM_EN;
+ level->plane_res_b = val & PLANE_WM_BLOCKS_MASK;
+ level->plane_res_l = (val >> PLANE_WM_LINES_SHIFT) &
+ PLANE_WM_LINES_MASK;
}
-static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
+void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+ struct skl_pipe_wm *out)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- struct skl_pipe_wm *active = &cstate->wm.skl.optimal;
+ struct intel_plane *intel_plane;
+ struct skl_plane_wm *wm;
enum pipe pipe = intel_crtc->pipe;
- int level, i, max_level;
- uint32_t temp;
-
- max_level = ilk_wm_max_level(dev);
-
- hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
-
- for (level = 0; level <= max_level; level++) {
- for (i = 0; i < intel_num_planes(intel_crtc); i++)
- hw->plane[pipe][i][level] =
- I915_READ(PLANE_WM(pipe, i, 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->plane_trans[pipe][PLANE_CURSOR] = I915_READ(CUR_WM_TRANS(pipe));
+ int level, id, max_level;
+ uint32_t val;
- if (!intel_crtc->active)
- return;
+ max_level = ilk_wm_max_level(dev_priv);
- hw->dirty_pipes |= drm_crtc_mask(crtc);
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ id = skl_wm_plane_id(intel_plane);
+ wm = &out->planes[id];
- active->linetime = hw->wm_linetime[pipe];
+ for (level = 0; level <= max_level; level++) {
+ if (id != PLANE_CURSOR)
+ val = I915_READ(PLANE_WM(pipe, id, level));
+ else
+ val = I915_READ(CUR_WM(pipe, level));
- for (level = 0; level <= max_level; level++) {
- for (i = 0; i < intel_num_planes(intel_crtc); i++) {
- temp = hw->plane[pipe][i][level];
- skl_pipe_wm_active_state(temp, active, false,
- false, i, level);
+ skl_wm_level_from_reg_val(val, &wm->wm[level]);
}
- temp = hw->plane[pipe][PLANE_CURSOR][level];
- skl_pipe_wm_active_state(temp, active, false, true, i, level);
- }
- for (i = 0; i < intel_num_planes(intel_crtc); i++) {
- temp = hw->plane_trans[pipe][i];
- skl_pipe_wm_active_state(temp, active, true, false, i, 0);
+ if (id != PLANE_CURSOR)
+ val = I915_READ(PLANE_WM_TRANS(pipe, id));
+ else
+ val = I915_READ(CUR_WM_TRANS(pipe));
+
+ skl_wm_level_from_reg_val(val, &wm->trans_wm);
}
- temp = hw->plane_trans[pipe][PLANE_CURSOR];
- skl_pipe_wm_active_state(temp, active, true, true, i, 0);
+ if (!intel_crtc->active)
+ return;
- intel_crtc->wm.active.skl = *active;
+ out->linetime = I915_READ(PIPE_WM_LINETIME(pipe));
}
void skl_wm_get_hw_state(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
struct drm_crtc *crtc;
+ struct intel_crtc *intel_crtc;
+ struct intel_crtc_state *cstate;
skl_ddb_get_hw_state(dev_priv, ddb);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- skl_pipe_wm_get_hw_state(crtc);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ intel_crtc = to_intel_crtc(crtc);
+ cstate = to_intel_crtc_state(crtc->state);
+
+ skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal);
+
+ if (intel_crtc->active)
+ hw->dirty_pipes |= drm_crtc_mask(crtc);
+ }
if (dev_priv->active_crtcs) {
/* Fully recompute DDB on first atomic commit */
@@ -4402,7 +4409,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
};
hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
memset(active, 0, sizeof(*active));
@@ -4424,7 +4431,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
active->linetime = hw->wm_linetime[pipe];
} else {
- int level, max_level = ilk_wm_max_level(dev);
+ int level, max_level = ilk_wm_max_level(dev_priv);
/*
* For inactive pipes, all watermark levels
@@ -4536,11 +4543,11 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
plane->wm.fifo_size = 63;
break;
case DRM_PLANE_TYPE_PRIMARY:
- plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, 0);
+ plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, 0);
break;
case DRM_PLANE_TYPE_OVERLAY:
sprite = plane->plane;
- plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, sprite + 1);
+ plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, sprite + 1);
break;
}
}
@@ -4605,15 +4612,15 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
- if (INTEL_INFO(dev)->gen >= 7) {
+ if (INTEL_GEN(dev_priv) >= 7) {
hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
}
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
- else if (IS_IVYBRIDGE(dev))
+ else if (IS_IVYBRIDGE(dev_priv))
hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
@@ -4653,9 +4660,9 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
* We don't use the sprite, so we can ignore that. And on Crestline we have
* to set the non-SR watermarks to 8.
*/
-void intel_update_watermarks(struct drm_crtc *crtc)
+void intel_update_watermarks(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
if (dev_priv->display.update_wm)
dev_priv->display.update_wm(crtc);
@@ -5357,6 +5364,7 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv)
static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
uint32_t rc6_mask = 0;
/* 1a: Software RC state - RC0 */
@@ -5378,7 +5386,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
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_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
if (HAS_GUC(dev_priv))
@@ -5394,9 +5402,8 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
if (intel_enable_rc6() & INTEL_RC6_ENABLE)
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE));
- /* WaRsUseTimeoutMode */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+ /* WaRsUseTimeoutMode:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
GEN7_RC_CTL_TO_MODE |
@@ -5424,6 +5431,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
static void gen8_enable_rps(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
uint32_t rc6_mask = 0;
/* 1a: Software RC state - RC0 */
@@ -5440,7 +5448,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
I915_WRITE(GEN6_RC_SLEEP, 0);
if (IS_BROADWELL(dev_priv))
@@ -5500,6 +5508,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv)
static void gen6_enable_rps(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
u32 rc6vids, rc6_mask = 0;
u32 gtfifodbg;
int rc6_mode;
@@ -5533,7 +5542,7 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
I915_WRITE(GEN6_RC_SLEEP, 0);
@@ -5570,10 +5579,6 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000);
I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
- ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
- if (ret)
- DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
-
reset_rps(dev_priv, gen6_set_rps);
rc6vids = 0;
@@ -5863,7 +5868,7 @@ static void valleyview_cleanup_pctx(struct drm_i915_private *dev_priv)
if (WARN_ON(!dev_priv->vlv_pctx))
return;
- i915_gem_object_put_unlocked(dev_priv->vlv_pctx);
+ i915_gem_object_put(dev_priv->vlv_pctx);
dev_priv->vlv_pctx = NULL;
}
@@ -5982,6 +5987,7 @@ static void valleyview_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
static void cherryview_enable_rps(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
u32 gtfifodbg, val, rc6_mode = 0, pcbr;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -6008,7 +6014,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
I915_WRITE(GEN6_RC_SLEEP, 0);
@@ -6070,6 +6076,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv)
static void valleyview_enable_rps(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
u32 gtfifodbg, val, rc6_mode = 0;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -6109,7 +6116,7 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
- for_each_engine(engine, dev_priv)
+ for_each_engine(engine, dev_priv, id)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
@@ -6792,7 +6799,7 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work)
if (READ_ONCE(dev_priv->rps.enabled))
goto out;
- rcs = &dev_priv->engine[RCS];
+ rcs = dev_priv->engine[RCS];
if (rcs->last_context)
goto out;
@@ -6845,10 +6852,8 @@ void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv)
}
}
-static void ibx_init_clock_gating(struct drm_device *dev)
+static void ibx_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/*
* On Ibex Peak and Cougar Point, we need to disable clock
* gating for the panel power sequencer or it will fail to
@@ -6857,9 +6862,8 @@ static void ibx_init_clock_gating(struct drm_device *dev)
I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
}
-static void g4x_disable_trickle_feed(struct drm_device *dev)
+static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
@@ -6872,10 +6876,8 @@ static void g4x_disable_trickle_feed(struct drm_device *dev)
}
}
-static void ilk_init_lp_watermarks(struct drm_device *dev)
+static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN);
I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN);
I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
@@ -6886,9 +6888,8 @@ static void ilk_init_lp_watermarks(struct drm_device *dev)
*/
}
-static void ironlake_init_clock_gating(struct drm_device *dev)
+static void ironlake_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
/*
@@ -6920,7 +6921,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
(I915_READ(DISP_ARB_CTL) |
DISP_FBC_WM_DIS));
- ilk_init_lp_watermarks(dev);
+ ilk_init_lp_watermarks(dev_priv);
/*
* Based on the document from hardware guys the following bits
@@ -6929,7 +6930,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
* The bit 22 of 0x42004
* The bit 7,8,9 of 0x42020.
*/
- if (IS_IRONLAKE_M(dev)) {
+ if (IS_IRONLAKE_M(dev_priv)) {
/* WaFbcAsynchFlipDisableFbcQueue:ilk */
I915_WRITE(ILK_DISPLAY_CHICKEN1,
I915_READ(ILK_DISPLAY_CHICKEN1) |
@@ -6955,14 +6956,13 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
/* WaDisable_RenderCache_OperationalFlush:ilk */
I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
- g4x_disable_trickle_feed(dev);
+ g4x_disable_trickle_feed(dev_priv);
- ibx_init_clock_gating(dev);
+ ibx_init_clock_gating(dev_priv);
}
-static void cpt_init_clock_gating(struct drm_device *dev)
+static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
int pipe;
uint32_t val;
@@ -6997,9 +6997,8 @@ static void cpt_init_clock_gating(struct drm_device *dev)
}
}
-static void gen6_check_mch_setup(struct drm_device *dev)
+static void gen6_check_mch_setup(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t tmp;
tmp = I915_READ(MCH_SSKPD);
@@ -7008,9 +7007,8 @@ static void gen6_check_mch_setup(struct drm_device *dev)
tmp);
}
-static void gen6_init_clock_gating(struct drm_device *dev)
+static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate);
@@ -7037,7 +7035,7 @@ static void gen6_init_clock_gating(struct drm_device *dev)
I915_WRITE(GEN6_GT_MODE,
_MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
- ilk_init_lp_watermarks(dev);
+ ilk_init_lp_watermarks(dev_priv);
I915_WRITE(CACHE_MODE_0,
_MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
@@ -7098,11 +7096,11 @@ static void gen6_init_clock_gating(struct drm_device *dev)
ILK_DPARBUNIT_CLOCK_GATE_ENABLE |
ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
- g4x_disable_trickle_feed(dev);
+ g4x_disable_trickle_feed(dev_priv);
- cpt_init_clock_gating(dev);
+ cpt_init_clock_gating(dev_priv);
- gen6_check_mch_setup(dev);
+ gen6_check_mch_setup(dev_priv);
}
static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
@@ -7123,15 +7121,13 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
I915_WRITE(GEN7_FF_THREAD_MODE, reg);
}
-static void lpt_init_clock_gating(struct drm_device *dev)
+static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/*
* TODO: this bit should only be enabled when really needed, then
* disabled when not needed anymore in order to save power.
*/
- if (HAS_PCH_LPT_LP(dev))
+ if (HAS_PCH_LPT_LP(dev_priv))
I915_WRITE(SOUTH_DSPCLK_GATE_D,
I915_READ(SOUTH_DSPCLK_GATE_D) |
PCH_LP_PARTITION_LEVEL_DISABLE);
@@ -7142,11 +7138,9 @@ static void lpt_init_clock_gating(struct drm_device *dev)
TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
}
-static void lpt_suspend_hw(struct drm_device *dev)
+static void lpt_suspend_hw(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (HAS_PCH_LPT_LP(dev)) {
+ if (HAS_PCH_LPT_LP(dev_priv)) {
uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D);
val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
@@ -7177,11 +7171,9 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv,
I915_WRITE(GEN7_MISCCPCTL, misccpctl);
}
-static void kabylake_init_clock_gating(struct drm_device *dev)
+static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- gen9_init_clock_gating(dev);
+ gen9_init_clock_gating(dev_priv);
/* WaDisableSDEUnitClockGating:kbl */
if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
@@ -7198,11 +7190,9 @@ static void kabylake_init_clock_gating(struct drm_device *dev)
ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
}
-static void skylake_init_clock_gating(struct drm_device *dev)
+static void skylake_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- gen9_init_clock_gating(dev);
+ gen9_init_clock_gating(dev_priv);
/* WAC6entrylatency:skl */
I915_WRITE(FBC_LLC_READ_CTRL, I915_READ(FBC_LLC_READ_CTRL) |
@@ -7213,12 +7203,11 @@ static void skylake_init_clock_gating(struct drm_device *dev)
ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
}
-static void broadwell_init_clock_gating(struct drm_device *dev)
+static void broadwell_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe;
- ilk_init_lp_watermarks(dev);
+ ilk_init_lp_watermarks(dev_priv);
/* WaSwitchSolVfFArbitrationPriority:bdw */
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -7261,14 +7250,12 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1)
| KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
- lpt_init_clock_gating(dev);
+ lpt_init_clock_gating(dev_priv);
}
-static void haswell_init_clock_gating(struct drm_device *dev)
+static void haswell_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- ilk_init_lp_watermarks(dev);
+ ilk_init_lp_watermarks(dev_priv);
/* L3 caching of data atomics doesn't work -- disable it. */
I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
@@ -7317,15 +7304,14 @@ static void haswell_init_clock_gating(struct drm_device *dev)
I915_WRITE(CHICKEN_PAR1_1,
I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES);
- lpt_init_clock_gating(dev);
+ lpt_init_clock_gating(dev_priv);
}
-static void ivybridge_init_clock_gating(struct drm_device *dev)
+static void ivybridge_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t snpcr;
- ilk_init_lp_watermarks(dev);
+ ilk_init_lp_watermarks(dev_priv);
I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
@@ -7339,7 +7325,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
CHICKEN3_DGMG_DONE_FIX_DISABLE);
/* WaDisablePSDDualDispatchEnable:ivb */
- if (IS_IVB_GT1(dev))
+ if (IS_IVB_GT1(dev_priv))
I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
_MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
@@ -7355,7 +7341,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
GEN7_WA_FOR_GEN7_L3_CONTROL);
I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
GEN7_WA_L3_CHICKEN_MODE);
- if (IS_IVB_GT1(dev))
+ if (IS_IVB_GT1(dev_priv))
I915_WRITE(GEN7_ROW_CHICKEN2,
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
else {
@@ -7382,7 +7368,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
- g4x_disable_trickle_feed(dev);
+ g4x_disable_trickle_feed(dev_priv);
gen7_setup_fixed_func_scheduler(dev_priv);
@@ -7412,16 +7398,14 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
snpcr |= GEN6_MBC_SNPCR_MED;
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
- if (!HAS_PCH_NOP(dev))
- cpt_init_clock_gating(dev);
+ if (!HAS_PCH_NOP(dev_priv))
+ cpt_init_clock_gating(dev_priv);
- gen6_check_mch_setup(dev);
+ gen6_check_mch_setup(dev_priv);
}
-static void valleyview_init_clock_gating(struct drm_device *dev)
+static void valleyview_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* WaDisableEarlyCull:vlv */
I915_WRITE(_3D_CHICKEN3,
_MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
@@ -7500,10 +7484,8 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS);
}
-static void cherryview_init_clock_gating(struct drm_device *dev)
+static void cherryview_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
/* WaVSRefCountFullforceMissDisable:chv */
/* WaDSRefCountFullforceMissDisable:chv */
I915_WRITE(GEN7_FF_THREAD_MODE,
@@ -7536,9 +7518,8 @@ static void cherryview_init_clock_gating(struct drm_device *dev)
I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
}
-static void g4x_init_clock_gating(struct drm_device *dev)
+static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t dspclk_gate;
I915_WRITE(RENCLK_GATE_D1, 0);
@@ -7549,7 +7530,7 @@ static void g4x_init_clock_gating(struct drm_device *dev)
dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
OVRUNIT_CLOCK_GATE_DISABLE |
OVCUNIT_CLOCK_GATE_DISABLE;
- if (IS_GM45(dev))
+ if (IS_GM45(dev_priv))
dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
@@ -7560,13 +7541,11 @@ static void g4x_init_clock_gating(struct drm_device *dev)
/* WaDisable_RenderCache_OperationalFlush:g4x */
I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
- g4x_disable_trickle_feed(dev);
+ g4x_disable_trickle_feed(dev_priv);
}
-static void crestline_init_clock_gating(struct drm_device *dev)
+static void crestline_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
I915_WRITE(RENCLK_GATE_D2, 0);
I915_WRITE(DSPCLK_GATE_D, 0);
@@ -7579,10 +7558,8 @@ static void crestline_init_clock_gating(struct drm_device *dev)
I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
}
-static void broadwater_init_clock_gating(struct drm_device *dev)
+static void broadwater_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
I965_RCC_CLOCK_GATE_DISABLE |
I965_RCPB_CLOCK_GATE_DISABLE |
@@ -7596,16 +7573,15 @@ static void broadwater_init_clock_gating(struct drm_device *dev)
I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
}
-static void gen3_init_clock_gating(struct drm_device *dev)
+static void gen3_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
u32 dstate = I915_READ(D_STATE);
dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
DSTATE_DOT_CLOCK_GATING;
I915_WRITE(D_STATE, dstate);
- if (IS_PINEVIEW(dev))
+ if (IS_PINEVIEW(dev_priv))
I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY));
/* IIR "flip pending" means done if this bit is set */
@@ -7621,10 +7597,8 @@ static void gen3_init_clock_gating(struct drm_device *dev)
_MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
}
-static void i85x_init_clock_gating(struct drm_device *dev)
+static void i85x_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
/* interrupts should cause a wake up from C3 */
@@ -7635,10 +7609,8 @@ static void i85x_init_clock_gating(struct drm_device *dev)
_MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE));
}
-static void i830_init_clock_gating(struct drm_device *dev)
+static void i830_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(MEM_MODE,
@@ -7646,20 +7618,18 @@ static void i830_init_clock_gating(struct drm_device *dev)
_MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE));
}
-void intel_init_clock_gating(struct drm_device *dev)
+void intel_init_clock_gating(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- dev_priv->display.init_clock_gating(dev);
+ dev_priv->display.init_clock_gating(dev_priv);
}
-void intel_suspend_hw(struct drm_device *dev)
+void intel_suspend_hw(struct drm_i915_private *dev_priv)
{
- if (HAS_PCH_LPT(dev))
- lpt_suspend_hw(dev);
+ if (HAS_PCH_LPT(dev_priv))
+ lpt_suspend_hw(dev_priv);
}
-static void nop_init_clock_gating(struct drm_device *dev)
+static void nop_init_clock_gating(struct drm_i915_private *dev_priv)
{
DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n");
}
@@ -7714,29 +7684,28 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
}
/* Set up chip specific power management-related functions */
-void intel_init_pm(struct drm_device *dev)
+void intel_init_pm(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
intel_fbc_init(dev_priv);
/* For cxsr */
- if (IS_PINEVIEW(dev))
- i915_pineview_get_mem_freq(dev);
- else if (IS_GEN5(dev))
- i915_ironlake_get_mem_freq(dev);
+ if (IS_PINEVIEW(dev_priv))
+ i915_pineview_get_mem_freq(dev_priv);
+ else if (IS_GEN5(dev_priv))
+ i915_ironlake_get_mem_freq(dev_priv);
/* For FIFO watermark updates */
- if (INTEL_INFO(dev)->gen >= 9) {
- skl_setup_wm_latency(dev);
- dev_priv->display.update_wm = skl_update_wm;
+ if (INTEL_GEN(dev_priv) >= 9) {
+ skl_setup_wm_latency(dev_priv);
+ dev_priv->display.initial_watermarks = skl_initial_wm;
+ dev_priv->display.atomic_update_watermarks = skl_atomic_update_crtc_wm;
dev_priv->display.compute_global_watermarks = skl_compute_wm;
- } else if (HAS_PCH_SPLIT(dev)) {
- ilk_setup_wm_latency(dev);
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
+ ilk_setup_wm_latency(dev_priv);
- if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] &&
+ if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] &&
dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
- (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
+ (!IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[0] &&
dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
dev_priv->display.compute_intermediate_wm =
@@ -7749,14 +7718,14 @@ void intel_init_pm(struct drm_device *dev)
DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n");
}
- } else if (IS_CHERRYVIEW(dev)) {
- vlv_setup_wm_latency(dev);
+ } else if (IS_CHERRYVIEW(dev_priv)) {
+ vlv_setup_wm_latency(dev_priv);
dev_priv->display.update_wm = vlv_update_wm;
- } else if (IS_VALLEYVIEW(dev)) {
- vlv_setup_wm_latency(dev);
+ } else if (IS_VALLEYVIEW(dev_priv)) {
+ vlv_setup_wm_latency(dev_priv);
dev_priv->display.update_wm = vlv_update_wm;
- } else if (IS_PINEVIEW(dev)) {
- if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+ } else if (IS_PINEVIEW(dev_priv)) {
+ if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
dev_priv->is_ddr3,
dev_priv->fsb_freq,
dev_priv->mem_freq)) {
@@ -7770,15 +7739,15 @@ void intel_init_pm(struct drm_device *dev)
dev_priv->display.update_wm = NULL;
} else
dev_priv->display.update_wm = pineview_update_wm;
- } else if (IS_G4X(dev)) {
+ } else if (IS_G4X(dev_priv)) {
dev_priv->display.update_wm = g4x_update_wm;
- } else if (IS_GEN4(dev)) {
+ } else if (IS_GEN4(dev_priv)) {
dev_priv->display.update_wm = i965_update_wm;
- } else if (IS_GEN3(dev)) {
+ } else if (IS_GEN3(dev_priv)) {
dev_priv->display.update_wm = i9xx_update_wm;
dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
- } else if (IS_GEN2(dev)) {
- if (INTEL_INFO(dev)->num_pipes == 1) {
+ } else if (IS_GEN2(dev_priv)) {
+ if (INTEL_INFO(dev_priv)->num_pipes == 1) {
dev_priv->display.update_wm = i845_update_wm;
dev_priv->display.get_fifo_size = i845_get_fifo_size;
} else {
@@ -8026,5 +7995,4 @@ void intel_pm_setup(struct drm_device *dev)
dev_priv->pm.suspended = false;
atomic_set(&dev_priv->pm.wakeref_count, 0);
- atomic_set(&dev_priv->pm.atomic_seq, 0);
}
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 108ba1e5d658..7b488e2793d9 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -268,7 +268,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
if (dev_priv->psr.link_standby)
@@ -344,7 +344,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
* ones. Since by Display design transcoder EDP is tied to port A
* we can safely escape based on the port A.
*/
- if (HAS_DDI(dev) && dig_port->port != PORT_A) {
+ if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) {
DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
return false;
}
@@ -354,20 +354,20 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
return false;
}
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
!dev_priv->psr.link_standby) {
DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n");
return false;
}
- if (IS_HASWELL(dev) &&
+ if (IS_HASWELL(dev_priv) &&
I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) &
S3D_ENABLE) {
DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
return false;
}
- if (IS_HASWELL(dev) &&
+ if (IS_HASWELL(dev_priv) &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
return false;
@@ -402,7 +402,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
lockdep_assert_held(&dev_priv->psr.lock);
/* Enable/Re-enable PSR on the host */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
/* On HSW+ after we enable PSR on source it will activate it
* as soon as it match configure idle_frame count. So
* we just actually enable it here on activation time.
@@ -427,7 +427,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
- if (!HAS_PSR(dev)) {
+ if (!HAS_PSR(dev_priv)) {
DRM_DEBUG_KMS("PSR not supported on this platform\n");
return;
}
@@ -448,7 +448,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
dev_priv->psr.busy_frontbuffer_bits = 0;
- if (HAS_DDI(dev)) {
+ if (HAS_DDI(dev_priv)) {
hsw_psr_setup_vsc(intel_dp);
if (dev_priv->psr.psr2_support) {
@@ -472,7 +472,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
/* Enable PSR on the panel */
hsw_psr_enable_sink(intel_dp);
- if (INTEL_INFO(dev)->gen >= 9)
+ if (INTEL_GEN(dev_priv) >= 9)
intel_psr_activate(intel_dp);
} else {
vlv_psr_setup_vsc(intel_dp);
@@ -498,7 +498,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
* - On HSW/BDW we get a recoverable frozen screen until next
* exit-activate sequence.
*/
- if (INTEL_INFO(dev)->gen < 9)
+ if (INTEL_GEN(dev_priv) < 9)
schedule_delayed_work(&dev_priv->psr.work,
msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
@@ -580,7 +580,7 @@ void intel_psr_disable(struct intel_dp *intel_dp)
}
/* Disable PSR on Source */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev_priv))
hsw_psr_disable(intel_dp);
else
vlv_psr_disable(intel_dp);
@@ -827,17 +827,17 @@ void intel_psr_init(struct drm_device *dev)
/* Per platform default */
if (i915.enable_psr == -1) {
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
i915.enable_psr = 1;
else
i915.enable_psr = 0;
}
/* Set link_standby x link_off defaults */
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
/* HSW and BDW require workarounds that we don't implement. */
dev_priv->psr.link_standby = false;
- else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
/* On VLV and CHV only standby mode is supported. */
dev_priv->psr.link_standby = true;
else
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ed9955dce156..aeb637dc1fdf 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -405,22 +405,6 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
return gen8_emit_pipe_control(req, flags, scratch_addr);
}
-u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
-{
- struct drm_i915_private *dev_priv = engine->i915;
- u64 acthd;
-
- if (INTEL_GEN(dev_priv) >= 8)
- acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
- RING_ACTHD_UDW(engine->mmio_base));
- else if (INTEL_GEN(dev_priv) >= 4)
- acthd = I915_READ(RING_ACTHD(engine->mmio_base));
- else
- acthd = I915_READ(ACTHD);
-
- return acthd;
-}
-
static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
@@ -585,9 +569,7 @@ static int init_ring_common(struct intel_engine_cs *engine)
I915_WRITE_TAIL(engine, ring->tail);
(void)I915_READ_TAIL(engine);
- I915_WRITE_CTL(engine,
- ((ring->size - PAGE_SIZE) & RING_NR_PAGES)
- | RING_VALID);
+ I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID);
/* If the head is still not zero, the ring is dead */
if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base),
@@ -666,7 +648,7 @@ static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
if (ret != 0)
return ret;
- ret = i915_gem_render_state_init(req);
+ ret = i915_gem_render_state_emit(req);
if (ret)
return ret;
@@ -851,15 +833,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine)
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
- /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+ /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
GEN9_DG_MIRROR_FIX_ENABLE);
- /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+ /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
GEN9_RHWO_OPTIMIZATION_DISABLE);
/*
@@ -869,10 +849,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine)
*/
}
- /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */
/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
- GEN9_ENABLE_YV12_BUGFIX |
GEN9_ENABLE_GPGPU_PREEMPTION);
/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
@@ -884,9 +862,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine)
WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
GEN9_CCS_TLB_PREFETCH_ENABLE);
- /* WaDisableMaskBasedCammingInRCC:skl,bxt */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+ /* WaDisableMaskBasedCammingInRCC:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
PIXEL_MASK_CAMMING_DISABLE);
@@ -1003,47 +980,12 @@ static int skl_init_workarounds(struct intel_engine_cs *engine)
* until D0 which is the default case so this is equivalent to
* !WaDisablePerCtxtPreemptionGranularityControl:skl
*/
- if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) {
- I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
- _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
- }
-
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
- /* 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 (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0))
- /* WaDisableLSQCROPERFforOCL:skl */
- I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_RO_PERF_DIS);
+ I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
+ _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
/* WaEnableGapsTsvCreditFix:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) {
- I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
- GEN9_GAPS_TSV_CREDIT_DISABLE));
- }
-
- /* WaDisablePowerCompilerClockGating:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0))
- WA_SET_BIT_MASKED(HIZ_CHICKEN,
- BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
-
- /* WaBarrierPerformanceFixDisable:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
- WA_SET_BIT_MASKED(HDC_CHICKEN0,
- HDC_FENCE_DEST_SLM_DISABLE |
- HDC_BARRIER_PERFORMANCE_DISABLE);
-
- /* WaDisableSbeCacheDispatchPortSharing:skl */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
- WA_SET_BIT_MASKED(
- GEN7_HALF_SLICE_CHICKEN1,
- GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
+ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+ GEN9_GAPS_TSV_CREDIT_DISABLE));
/* WaDisableGafsUnitClkGating:skl */
WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
@@ -1271,91 +1213,64 @@ static void render_ring_cleanup(struct intel_engine_cs *engine)
i915_vma_unpin_and_release(&dev_priv->semaphore);
}
-static int gen8_rcs_signal(struct drm_i915_gem_request *req)
+static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *out)
{
- struct intel_ring *ring = req->ring;
struct drm_i915_private *dev_priv = req->i915;
struct intel_engine_cs *waiter;
enum intel_engine_id id;
- int ret, num_rings;
-
- num_rings = INTEL_INFO(dev_priv)->num_rings;
- ret = intel_ring_begin(req, (num_rings-1) * 8);
- if (ret)
- return ret;
- for_each_engine_id(waiter, dev_priv, id) {
+ for_each_engine(waiter, dev_priv, id) {
u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
continue;
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
- intel_ring_emit(ring,
- PIPE_CONTROL_GLOBAL_GTT_IVB |
- PIPE_CONTROL_QW_WRITE |
- PIPE_CONTROL_CS_STALL);
- intel_ring_emit(ring, lower_32_bits(gtt_offset));
- intel_ring_emit(ring, upper_32_bits(gtt_offset));
- intel_ring_emit(ring, req->fence.seqno);
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring,
- MI_SEMAPHORE_SIGNAL |
- MI_SEMAPHORE_TARGET(waiter->hw_id));
- intel_ring_emit(ring, 0);
+ *out++ = GFX_OP_PIPE_CONTROL(6);
+ *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+ PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_CS_STALL);
+ *out++ = lower_32_bits(gtt_offset);
+ *out++ = upper_32_bits(gtt_offset);
+ *out++ = req->global_seqno;
+ *out++ = 0;
+ *out++ = (MI_SEMAPHORE_SIGNAL |
+ MI_SEMAPHORE_TARGET(waiter->hw_id));
+ *out++ = 0;
}
- intel_ring_advance(ring);
- return 0;
+ return out;
}
-static int gen8_xcs_signal(struct drm_i915_gem_request *req)
+static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *out)
{
- struct intel_ring *ring = req->ring;
struct drm_i915_private *dev_priv = req->i915;
struct intel_engine_cs *waiter;
enum intel_engine_id id;
- int ret, num_rings;
- num_rings = INTEL_INFO(dev_priv)->num_rings;
- ret = intel_ring_begin(req, (num_rings-1) * 6);
- if (ret)
- return ret;
-
- for_each_engine_id(waiter, dev_priv, id) {
+ for_each_engine(waiter, dev_priv, id) {
u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
continue;
- intel_ring_emit(ring,
- (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
- intel_ring_emit(ring,
- lower_32_bits(gtt_offset) |
- MI_FLUSH_DW_USE_GTT);
- intel_ring_emit(ring, upper_32_bits(gtt_offset));
- intel_ring_emit(ring, req->fence.seqno);
- intel_ring_emit(ring,
- MI_SEMAPHORE_SIGNAL |
- MI_SEMAPHORE_TARGET(waiter->hw_id));
- intel_ring_emit(ring, 0);
+ *out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
+ *out++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT;
+ *out++ = upper_32_bits(gtt_offset);
+ *out++ = req->global_seqno;
+ *out++ = (MI_SEMAPHORE_SIGNAL |
+ MI_SEMAPHORE_TARGET(waiter->hw_id));
+ *out++ = 0;
}
- intel_ring_advance(ring);
- return 0;
+ return out;
}
-static int gen6_signal(struct drm_i915_gem_request *req)
+static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *out)
{
- struct intel_ring *ring = req->ring;
struct drm_i915_private *dev_priv = req->i915;
struct intel_engine_cs *engine;
- int ret, num_rings;
-
- num_rings = INTEL_INFO(dev_priv)->num_rings;
- ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2));
- if (ret)
- return ret;
+ enum intel_engine_id id;
+ int num_rings = 0;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
i915_reg_t mbox_reg;
if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK))
@@ -1363,101 +1278,80 @@ static int gen6_signal(struct drm_i915_gem_request *req)
mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id];
if (i915_mmio_reg_valid(mbox_reg)) {
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit_reg(ring, mbox_reg);
- intel_ring_emit(ring, req->fence.seqno);
+ *out++ = MI_LOAD_REGISTER_IMM(1);
+ *out++ = i915_mmio_reg_offset(mbox_reg);
+ *out++ = req->global_seqno;
+ num_rings++;
}
}
+ if (num_rings & 1)
+ *out++ = MI_NOOP;
- /* If num_dwords was rounded, make sure the tail pointer is correct */
- if (num_rings % 2 == 0)
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_advance(ring);
-
- return 0;
+ return out;
}
static void i9xx_submit_request(struct drm_i915_gem_request *request)
{
struct drm_i915_private *dev_priv = request->i915;
- I915_WRITE_TAIL(request->engine,
- intel_ring_offset(request->ring, request->tail));
+ i915_gem_request_submit(request);
+
+ I915_WRITE_TAIL(request->engine, request->tail);
}
-static int i9xx_emit_request(struct drm_i915_gem_request *req)
+static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req,
+ u32 *out)
{
- struct intel_ring *ring = req->ring;
- int ret;
-
- ret = intel_ring_begin(req, 4);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
- intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- intel_ring_emit(ring, req->fence.seqno);
- intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_advance(ring);
+ *out++ = MI_STORE_DWORD_INDEX;
+ *out++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT;
+ *out++ = req->global_seqno;
+ *out++ = MI_USER_INTERRUPT;
- req->tail = ring->tail;
-
- return 0;
+ req->tail = intel_ring_offset(req->ring, out);
}
+static const int i9xx_emit_breadcrumb_sz = 4;
+
/**
- * gen6_sema_emit_request - Update the semaphore mailbox registers
+ * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers
*
* @request - request to write to the ring
*
* Update the mailbox registers in the *other* rings with the current seqno.
* This acts like a signal in the canonical semaphore.
*/
-static int gen6_sema_emit_request(struct drm_i915_gem_request *req)
+static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req,
+ u32 *out)
{
- int ret;
-
- ret = req->engine->semaphore.signal(req);
- if (ret)
- return ret;
-
- return i9xx_emit_request(req);
+ return i9xx_emit_breadcrumb(req,
+ req->engine->semaphore.signal(req, out));
}
-static int gen8_render_emit_request(struct drm_i915_gem_request *req)
+static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req,
+ u32 *out)
{
struct intel_engine_cs *engine = req->engine;
- struct intel_ring *ring = req->ring;
- int ret;
- if (engine->semaphore.signal) {
- ret = engine->semaphore.signal(req);
- if (ret)
- return ret;
- }
+ if (engine->semaphore.signal)
+ out = engine->semaphore.signal(req, out);
- ret = intel_ring_begin(req, 8);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
- intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB |
+ *out++ = GFX_OP_PIPE_CONTROL(6);
+ *out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
PIPE_CONTROL_CS_STALL |
- PIPE_CONTROL_QW_WRITE));
- intel_ring_emit(ring, intel_hws_seqno_address(engine));
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, i915_gem_request_get_seqno(req));
+ PIPE_CONTROL_QW_WRITE);
+ *out++ = intel_hws_seqno_address(engine);
+ *out++ = 0;
+ *out++ = req->global_seqno;
/* We're thrashing one dword of HWS. */
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_advance(ring);
-
- req->tail = ring->tail;
+ *out++ = 0;
+ *out++ = MI_USER_INTERRUPT;
+ *out++ = MI_NOOP;
- return 0;
+ req->tail = intel_ring_offset(req->ring, out);
}
+static const int gen8_render_emit_breadcrumb_sz = 8;
+
/**
* intel_ring_sync - sync the waiter to the signaller on seqno
*
@@ -1484,7 +1378,7 @@ gen8_ring_sync_to(struct drm_i915_gem_request *req,
MI_SEMAPHORE_WAIT |
MI_SEMAPHORE_GLOBAL_GTT |
MI_SEMAPHORE_SAD_GTE_SDD);
- intel_ring_emit(ring, signal->fence.seqno);
+ intel_ring_emit(ring, signal->global_seqno);
intel_ring_emit(ring, lower_32_bits(offset));
intel_ring_emit(ring, upper_32_bits(offset));
intel_ring_advance(ring);
@@ -1522,7 +1416,7 @@ gen6_ring_sync_to(struct drm_i915_gem_request *req,
* seqno is >= the last seqno executed. However for hardware the
* comparison is strictly greater than.
*/
- intel_ring_emit(ring, signal->fence.seqno - 1);
+ intel_ring_emit(ring, signal->global_seqno - 1);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
@@ -1665,7 +1559,7 @@ hsw_vebox_irq_enable(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915;
I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
- gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
+ gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask);
}
static void
@@ -1674,7 +1568,7 @@ hsw_vebox_irq_disable(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915;
I915_WRITE_IMR(engine, ~0);
- gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
+ gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask);
}
static void
@@ -1819,14 +1713,19 @@ static void cleanup_phys_status_page(struct intel_engine_cs *engine)
static void cleanup_status_page(struct intel_engine_cs *engine)
{
struct i915_vma *vma;
+ struct drm_i915_gem_object *obj;
vma = fetch_and_zero(&engine->status_page.vma);
if (!vma)
return;
+ obj = vma->obj;
+
i915_vma_unpin(vma);
- i915_gem_object_unpin_map(vma->obj);
- i915_vma_put(vma);
+ i915_vma_close(vma);
+
+ i915_gem_object_unpin_map(obj);
+ __i915_gem_object_release_unless_active(obj);
}
static int init_status_page(struct intel_engine_cs *engine)
@@ -1834,9 +1733,10 @@ static int init_status_page(struct intel_engine_cs *engine)
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
unsigned int flags;
+ void *vaddr;
int ret;
- obj = i915_gem_object_create(&engine->i915->drm, 4096);
+ obj = i915_gem_object_create_internal(engine->i915, 4096);
if (IS_ERR(obj)) {
DRM_ERROR("Failed to allocate status page\n");
return PTR_ERR(obj);
@@ -1869,15 +1769,22 @@ static int init_status_page(struct intel_engine_cs *engine)
if (ret)
goto err;
+ vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
+ if (IS_ERR(vaddr)) {
+ ret = PTR_ERR(vaddr);
+ goto err_unpin;
+ }
+
engine->status_page.vma = vma;
engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
- engine->status_page.page_addr =
- i915_gem_object_pin_map(obj, I915_MAP_WB);
+ engine->status_page.page_addr = memset(vaddr, 0, 4096);
DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
engine->name, i915_ggtt_offset(vma));
return 0;
+err_unpin:
+ i915_vma_unpin(vma);
err:
i915_gem_object_put(obj);
return ret;
@@ -1989,6 +1896,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
struct i915_vma *vma;
GEM_BUG_ON(!is_power_of_2(size));
+ GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring)
@@ -2023,7 +1931,11 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
void
intel_ring_free(struct intel_ring *ring)
{
- i915_vma_put(ring->vma);
+ struct drm_i915_gem_object *obj = ring->vma->obj;
+
+ i915_vma_close(ring->vma);
+ __i915_gem_object_release_unless_active(obj);
+
kfree(ring);
}
@@ -2039,14 +1951,13 @@ static int intel_ring_context_pin(struct i915_gem_context *ctx,
return 0;
if (ce->state) {
- ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false);
- if (ret)
- goto error;
+ struct i915_vma *vma;
- ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment,
- PIN_GLOBAL | PIN_HIGH);
- if (ret)
+ vma = i915_gem_context_pin_legacy(ctx, PIN_HIGH);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto error;
+ }
}
/* The kernel context is only used as a placeholder for flushing the
@@ -2093,9 +2004,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
intel_engine_setup_common(engine);
- memset(engine->semaphore.sync_seqno, 0,
- sizeof(engine->semaphore.sync_seqno));
-
ret = intel_engine_init_common(engine);
if (ret)
goto error;
@@ -2146,9 +2054,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv;
- if (!intel_engine_initialized(engine))
- return;
-
dev_priv = engine->i915;
if (engine->buffer) {
@@ -2175,13 +2080,16 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
intel_ring_context_unpin(dev_priv->kernel_context, engine);
engine->i915 = NULL;
+ dev_priv->engine[engine->id] = NULL;
+ kfree(engine);
}
void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- for_each_engine(engine, dev_priv) {
+ for_each_engine(engine, dev_priv, id) {
engine->buffer->head = engine->buffer->tail;
engine->buffer->last_retired_head = -1;
}
@@ -2211,7 +2119,9 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
{
struct intel_ring *ring = req->ring;
struct drm_i915_gem_request *target;
- int ret;
+ long timeout;
+
+ lockdep_assert_held(&req->i915->drm.struct_mutex);
intel_ring_update_space(ring);
if (ring->space >= bytes)
@@ -2241,11 +2151,11 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
if (WARN_ON(&target->ring_link == &ring->request_list))
return -ENOSPC;
- ret = i915_wait_request(target,
- I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
- NULL, NO_WAITBOOST);
- if (ret)
- return ret;
+ timeout = i915_wait_request(target,
+ I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
+ MAX_SCHEDULE_TIMEOUT);
+ if (timeout < 0)
+ return timeout;
i915_gem_request_retire_upto(target);
@@ -2674,9 +2584,22 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
engine->init_hw = init_ring_common;
engine->reset_hw = reset_ring_common;
- engine->emit_request = i9xx_emit_request;
- if (i915.semaphores)
- engine->emit_request = gen6_sema_emit_request;
+ engine->emit_breadcrumb = i9xx_emit_breadcrumb;
+ engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz;
+ if (i915.semaphores) {
+ int num_rings;
+
+ engine->emit_breadcrumb = gen6_sema_emit_breadcrumb;
+
+ num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
+ if (INTEL_GEN(dev_priv) >= 8) {
+ engine->emit_breadcrumb_sz += num_rings * 6;
+ } else {
+ engine->emit_breadcrumb_sz += num_rings * 3;
+ if (num_rings & 1)
+ engine->emit_breadcrumb_sz++;
+ }
+ }
engine->submit_request = i9xx_submit_request;
if (INTEL_GEN(dev_priv) >= 8)
@@ -2703,10 +2626,18 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
if (INTEL_GEN(dev_priv) >= 8) {
engine->init_context = intel_rcs_ctx_init;
- engine->emit_request = gen8_render_emit_request;
+ engine->emit_breadcrumb = gen8_render_emit_breadcrumb;
+ engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz;
engine->emit_flush = gen8_render_ring_flush;
- if (i915.semaphores)
+ if (i915.semaphores) {
+ int num_rings;
+
engine->semaphore.signal = gen8_rcs_signal;
+
+ num_rings =
+ hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
+ engine->emit_breadcrumb_sz += num_rings * 6;
+ }
} else if (INTEL_GEN(dev_priv) >= 6) {
engine->init_context = intel_rcs_ctx_init;
engine->emit_flush = gen7_render_ring_flush;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index ec0b4a0c605d..3466b4e77e7c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -4,6 +4,7 @@
#include <linux/hashtable.h>
#include "i915_gem_batch_pool.h"
#include "i915_gem_request.h"
+#include "i915_gem_timeline.h"
#define I915_CMD_HASH_ORDER 9
@@ -73,13 +74,40 @@ enum intel_engine_hangcheck_action {
#define HANGCHECK_SCORE_RING_HUNG 31
+#define I915_MAX_SLICES 3
+#define I915_MAX_SUBSLICES 3
+
+#define instdone_slice_mask(dev_priv__) \
+ (INTEL_GEN(dev_priv__) == 7 ? \
+ 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask)
+
+#define instdone_subslice_mask(dev_priv__) \
+ (INTEL_GEN(dev_priv__) == 7 ? \
+ 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask)
+
+#define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \
+ for ((slice__) = 0, (subslice__) = 0; \
+ (slice__) < I915_MAX_SLICES; \
+ (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \
+ (slice__) += ((subslice__) == 0)) \
+ for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \
+ (BIT(subslice__) & instdone_subslice_mask(dev_priv__)))
+
+struct intel_instdone {
+ u32 instdone;
+ /* The following exist only in the RCS engine */
+ u32 slice_common;
+ u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES];
+ u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES];
+};
+
struct intel_engine_hangcheck {
u64 acthd;
u32 seqno;
int score;
enum intel_engine_hangcheck_action action;
int deadlock;
- u32 instdone[I915_NUM_INSTDONE_REG];
+ struct intel_instdone instdone;
};
struct intel_ring {
@@ -130,6 +158,7 @@ struct i915_ctx_workarounds {
};
struct drm_i915_gem_request;
+struct intel_render_state;
struct intel_engine_cs {
struct drm_i915_private *i915;
@@ -141,7 +170,6 @@ struct intel_engine_cs {
VCS2, /* Keep instances of the same type engine together. */
VECS
} id;
-#define I915_NUM_ENGINES 5
#define _VCS(n) (VCS + (n))
unsigned int exec_id;
enum intel_engine_hw_id {
@@ -152,10 +180,12 @@ struct intel_engine_cs {
VCS2_HW
} hw_id;
enum intel_engine_hw_id guc_id; /* XXX same as hw_id? */
- u64 fence_context;
u32 mmio_base;
unsigned int irq_shift;
struct intel_ring *buffer;
+ struct intel_timeline *timeline;
+
+ struct intel_render_state *render_state;
/* Rather than have every client wait upon all user interrupts,
* with the herd waking after every interrupt and each doing the
@@ -177,7 +207,7 @@ struct intel_engine_cs {
struct task_struct __rcu *irq_seqno_bh; /* bh for interrupts */
bool irq_posted;
- spinlock_t lock; /* protects the lists of requests */
+ spinlock_t lock; /* protects the lists of requests; irqsafe */
struct rb_root waiters; /* sorted by retirement, priority */
struct rb_root signals; /* sorted by retirement */
struct intel_wait *first_wait; /* oldest waiter by retirement */
@@ -225,7 +255,9 @@ struct intel_engine_cs {
#define I915_DISPATCH_SECURE BIT(0)
#define I915_DISPATCH_PINNED BIT(1)
#define I915_DISPATCH_RS BIT(2)
- int (*emit_request)(struct drm_i915_gem_request *req);
+ void (*emit_breadcrumb)(struct drm_i915_gem_request *req,
+ u32 *out);
+ int emit_breadcrumb_sz;
/* Pass the request to the hardware queue (e.g. directly into
* the legacy ringbuffer or to the end of an execlist).
@@ -235,6 +267,15 @@ struct intel_engine_cs {
*/
void (*submit_request)(struct drm_i915_gem_request *req);
+ /* Call when the priority on a request has changed and it and its
+ * dependencies may need rescheduling. Note the request itself may
+ * not be ready to run!
+ *
+ * Called under the struct_mutex.
+ */
+ void (*schedule)(struct drm_i915_gem_request *request,
+ int priority);
+
/* Some chipsets are not quite as coherent as advertised and need
* an expensive kick to force a true read of the up-to-date seqno.
* However, the up-to-date seqno is not always required and the last
@@ -282,8 +323,6 @@ struct intel_engine_cs {
* ie. transpose of f(x, y)
*/
struct {
- u32 sync_seqno[I915_NUM_ENGINES-1];
-
union {
#define GEN6_SEMAPHORE_LAST VECS_HW
#define GEN6_NUM_SEMAPHORES (GEN6_SEMAPHORE_LAST + 1)
@@ -300,43 +339,22 @@ struct intel_engine_cs {
/* AKA wait() */
int (*sync_to)(struct drm_i915_gem_request *req,
struct drm_i915_gem_request *signal);
- int (*signal)(struct drm_i915_gem_request *req);
+ u32 *(*signal)(struct drm_i915_gem_request *req, u32 *out);
} semaphore;
/* Execlists */
struct tasklet_struct irq_tasklet;
- spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */
struct execlist_port {
struct drm_i915_gem_request *request;
unsigned int count;
} execlist_port[2];
- struct list_head execlist_queue;
+ struct rb_root execlist_queue;
+ struct rb_node *execlist_first;
unsigned int fw_domains;
bool disable_lite_restore_wa;
bool preempt_wa;
u32 ctx_desc_template;
- /**
- * List of breadcrumbs associated with GPU requests currently
- * outstanding.
- */
- struct list_head request_list;
-
- /**
- * Seqno of request most recently submitted to request_list.
- * Used exclusively by hang checker to avoid grabbing lock while
- * inspecting request list.
- */
- u32 last_submitted_seqno;
- u32 last_pending_seqno;
-
- /* An RCU guarded pointer to the last request. No reference is
- * held to the request, users must carefully acquire a reference to
- * the request using i915_gem_active_get_rcu(), or hold the
- * struct_mutex.
- */
- struct i915_gem_active last_request;
-
struct i915_gem_context *last_context;
struct intel_engine_hangcheck hangcheck;
@@ -368,39 +386,12 @@ struct intel_engine_cs {
u32 (*get_cmd_length_mask)(u32 cmd_header);
};
-static inline bool
-intel_engine_initialized(const struct intel_engine_cs *engine)
-{
- return engine->i915 != NULL;
-}
-
static inline unsigned
intel_engine_flag(const struct intel_engine_cs *engine)
{
return 1 << engine->id;
}
-static inline u32
-intel_engine_sync_index(struct intel_engine_cs *engine,
- struct intel_engine_cs *other)
-{
- int idx;
-
- /*
- * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2;
- * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs;
- * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs;
- * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs;
- * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
- */
-
- idx = (other - engine) - 1;
- if (idx < 0)
- idx += I915_NUM_ENGINES;
-
- return idx;
-}
-
static inline void
intel_flush_status_page(struct intel_engine_cs *engine, int reg)
{
@@ -483,30 +474,23 @@ static inline void intel_ring_advance(struct intel_ring *ring)
*/
}
-static inline u32 intel_ring_offset(struct intel_ring *ring, u32 value)
+static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr)
{
/* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */
- return value & (ring->size - 1);
+ u32 offset = addr - ring->vaddr;
+ return offset & (ring->size - 1);
}
int __intel_ring_space(int head, int tail, int size);
void intel_ring_update_space(struct intel_ring *ring);
-void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno);
+void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
void intel_engine_setup_common(struct intel_engine_cs *engine);
int intel_engine_init_common(struct intel_engine_cs *engine);
int intel_engine_create_scratch(struct intel_engine_cs *engine, int size);
void intel_engine_cleanup_common(struct intel_engine_cs *engine);
-static inline int intel_engine_idle(struct intel_engine_cs *engine,
- unsigned int flags)
-{
- /* Wait upon the last request to be completed */
- return i915_gem_active_wait_unlocked(&engine->last_request,
- flags, NULL, NULL);
-}
-
int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine);
@@ -514,13 +498,30 @@ int intel_init_blt_ring_buffer(struct intel_engine_cs *engine);
int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine);
u64 intel_engine_get_active_head(struct intel_engine_cs *engine);
+u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine);
+
static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine)
{
return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
}
+static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine)
+{
+ /* We are only peeking at the tail of the submit queue (and not the
+ * queue itself) in order to gain a hint as to the current active
+ * state of the engine. Callers are not expected to be taking
+ * engine->timeline->lock, nor are they expected to be concerned
+ * wtih serialising this hint with anything, so document it as
+ * a hint and nothing more.
+ */
+ return READ_ONCE(engine->timeline->last_submitted_seqno);
+}
+
int init_workarounds_ring(struct intel_engine_cs *engine);
+void intel_engine_get_instdone(struct intel_engine_cs *engine,
+ struct intel_instdone *instdone);
+
/*
* Arbitrary size for largest possible 'add request' sequence. The code paths
* are complex and variable. Empirical measurement shows that the worst case
@@ -586,12 +587,6 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine)
void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
-unsigned int intel_kick_waiters(struct drm_i915_private *i915);
-unsigned int intel_kick_signalers(struct drm_i915_private *i915);
-
-static inline bool intel_engine_is_active(struct intel_engine_cs *engine)
-{
- return i915_gem_active_isset(&engine->last_request);
-}
+unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915);
#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index a38c2fefe85a..356c662ad453 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -288,7 +288,6 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv,
static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
- struct drm_device *dev = &dev_priv->drm;
/*
* After we re-enable the power well, if we touch VGA register 0x3d5
@@ -304,7 +303,7 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
- if (IS_BROADWELL(dev))
+ if (IS_BROADWELL(dev_priv))
gen8_irq_power_well_post_enable(dev_priv,
1 << PIPE_C | 1 << PIPE_B);
}
@@ -331,7 +330,7 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
* sure vgacon can keep working normally without triggering interrupts
* and error messages.
*/
- if (power_well->data == SKL_DISP_PW_2) {
+ if (power_well->id == SKL_DISP_PW_2) {
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
@@ -344,7 +343,7 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- if (power_well->data == SKL_DISP_PW_2)
+ if (power_well->id == SKL_DISP_PW_2)
gen8_irq_power_well_pre_disable(dev_priv,
1 << PIPE_C | 1 << PIPE_B);
}
@@ -659,7 +658,7 @@ static void
gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum skl_disp_power_wells power_well_id = power_well->data;
+ enum skl_disp_power_wells power_well_id = power_well->id;
u32 val;
u32 mask;
@@ -704,7 +703,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
tmp = I915_READ(HSW_PWR_WELL_DRIVER);
fuse_status = I915_READ(SKL_FUSE_STATUS);
- switch (power_well->data) {
+ switch (power_well->id) {
case SKL_DISP_PW_1:
if (intel_wait_for_register(dev_priv,
SKL_FUSE_STATUS,
@@ -728,13 +727,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
case SKL_DISP_PW_MISC_IO:
break;
default:
- WARN(1, "Unknown power well %lu\n", power_well->data);
+ WARN(1, "Unknown power well %lu\n", power_well->id);
return;
}
- req_mask = SKL_POWER_WELL_REQ(power_well->data);
+ req_mask = SKL_POWER_WELL_REQ(power_well->id);
enable_requested = tmp & req_mask;
- state_mask = SKL_POWER_WELL_STATE(power_well->data);
+ state_mask = SKL_POWER_WELL_STATE(power_well->id);
is_enabled = tmp & state_mask;
if (!enable && enable_requested)
@@ -770,14 +769,14 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
power_well->name, enable ? "enable" : "disable");
if (check_fuse_status) {
- if (power_well->data == SKL_DISP_PW_1) {
+ if (power_well->id == SKL_DISP_PW_1) {
if (intel_wait_for_register(dev_priv,
SKL_FUSE_STATUS,
SKL_FUSE_PG1_DIST_STATUS,
SKL_FUSE_PG1_DIST_STATUS,
1))
DRM_ERROR("PG1 distributing status timeout\n");
- } else if (power_well->data == SKL_DISP_PW_2) {
+ } else if (power_well->id == SKL_DISP_PW_2) {
if (intel_wait_for_register(dev_priv,
SKL_FUSE_STATUS,
SKL_FUSE_PG2_DIST_STATUS,
@@ -819,8 +818,8 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
static bool skl_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- uint32_t mask = SKL_POWER_WELL_REQ(power_well->data) |
- SKL_POWER_WELL_STATE(power_well->data);
+ uint32_t mask = SKL_POWER_WELL_REQ(power_well->id) |
+ SKL_POWER_WELL_STATE(power_well->id);
return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask;
}
@@ -846,45 +845,22 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv,
skl_set_power_well(dev_priv, power_well, false);
}
-static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well)
-{
- enum skl_disp_power_wells power_well_id = power_well->data;
-
- return power_well_id == BXT_DPIO_CMN_A ? DPIO_PHY1 : DPIO_PHY0;
-}
-
static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum skl_disp_power_wells power_well_id = power_well->data;
- struct i915_power_well *cmn_a_well = NULL;
-
- if (power_well_id == BXT_DPIO_CMN_BC) {
- /*
- * We need to copy the GRC calibration value from the eDP PHY,
- * so make sure it's powered up.
- */
- cmn_a_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
- intel_power_well_get(dev_priv, cmn_a_well);
- }
-
- bxt_ddi_phy_init(dev_priv, bxt_power_well_to_phy(power_well));
-
- if (cmn_a_well)
- intel_power_well_put(dev_priv, cmn_a_well);
+ bxt_ddi_phy_init(dev_priv, power_well->data);
}
static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- bxt_ddi_phy_uninit(dev_priv, bxt_power_well_to_phy(power_well));
+ bxt_ddi_phy_uninit(dev_priv, power_well->data);
}
static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- return bxt_ddi_phy_is_enabled(dev_priv,
- bxt_power_well_to_phy(power_well));
+ return bxt_ddi_phy_is_enabled(dev_priv, power_well->data);
}
static void bxt_dpio_cmn_power_well_sync_hw(struct drm_i915_private *dev_priv,
@@ -903,13 +879,11 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
if (power_well->count > 0)
- bxt_ddi_phy_verify_state(dev_priv,
- bxt_power_well_to_phy(power_well));
+ bxt_ddi_phy_verify_state(dev_priv, power_well->data);
power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);
if (power_well->count > 0)
- bxt_ddi_phy_verify_state(dev_priv,
- bxt_power_well_to_phy(power_well));
+ bxt_ddi_phy_verify_state(dev_priv, power_well->data);
}
static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
@@ -933,7 +907,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
WARN_ON(dev_priv->cdclk_freq !=
- dev_priv->display.get_display_clock_speed(&dev_priv->drm));
+ dev_priv->display.get_display_clock_speed(dev_priv));
gen9_assert_dbuf_enabled(dev_priv);
@@ -976,7 +950,7 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
static void vlv_set_power_well(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well, bool enable)
{
- enum punit_power_well power_well_id = power_well->data;
+ enum punit_power_well power_well_id = power_well->id;
u32 mask;
u32 state;
u32 ctrl;
@@ -1030,7 +1004,7 @@ static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- int power_well_id = power_well->data;
+ int power_well_id = power_well->id;
bool enabled = false;
u32 mask;
u32 state;
@@ -1092,7 +1066,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
*
* CHV DPLL B/C have some issues if VGA mode is enabled.
*/
- for_each_pipe(&dev_priv->drm, pipe) {
+ for_each_pipe(dev_priv, pipe) {
u32 val = I915_READ(DPLL(pipe));
val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
@@ -1123,7 +1097,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
intel_crt_reset(&encoder->base);
}
- i915_redisable_vga_power_on(&dev_priv->drm);
+ i915_redisable_vga_power_on(dev_priv);
intel_pps_unlock_regs_wa(dev_priv);
}
@@ -1147,7 +1121,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
vlv_set_power_well(dev_priv, power_well, true);
@@ -1157,7 +1131,7 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
vlv_display_power_well_deinit(dev_priv);
@@ -1167,7 +1141,7 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
/* since ref/cri clock was enabled */
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
@@ -1193,7 +1167,7 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
{
enum pipe pipe;
- WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
for_each_pipe(dev_priv, pipe)
assert_pll_disabled(dev_priv, pipe);
@@ -1216,7 +1190,7 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr
struct i915_power_well *power_well;
power_well = &power_domains->power_wells[i];
- if (power_well->data == power_well_id)
+ if (power_well->id == power_well_id)
return power_well;
}
@@ -1340,10 +1314,10 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
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);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
+ power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
- if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+ if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
pipe = PIPE_A;
phy = DPIO_PHY0;
} else {
@@ -1371,7 +1345,7 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
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) {
+ if (power_well->id == 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);
@@ -1402,10 +1376,10 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
{
enum dpio_phy phy;
- WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
- power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
+ WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
+ power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
- if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+ if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
phy = DPIO_PHY0;
assert_pll_disabled(dev_priv, PIPE_A);
assert_pll_disabled(dev_priv, PIPE_B);
@@ -1554,7 +1528,7 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum pipe pipe = power_well->data;
+ enum pipe pipe = power_well->id;
bool enabled;
u32 state, ctrl;
@@ -1584,7 +1558,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well,
bool enable)
{
- enum pipe pipe = power_well->data;
+ enum pipe pipe = power_well->id;
u32 state;
u32 ctrl;
@@ -1617,7 +1591,7 @@ out:
static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PIPE_A);
+ WARN_ON_ONCE(power_well->id != PIPE_A);
chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0);
}
@@ -1625,7 +1599,7 @@ static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PIPE_A);
+ WARN_ON_ONCE(power_well->id != PIPE_A);
chv_set_pipe_power_well(dev_priv, power_well, true);
@@ -1635,7 +1609,7 @@ static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- WARN_ON_ONCE(power_well->data != PIPE_A);
+ WARN_ON_ONCE(power_well->id != PIPE_A);
vlv_display_power_well_deinit(dev_priv);
@@ -1979,12 +1953,12 @@ static struct i915_power_well vlv_power_wells[] = {
.always_on = 1,
.domains = POWER_DOMAIN_MASK,
.ops = &i9xx_always_on_power_well_ops,
- .data = PUNIT_POWER_WELL_ALWAYS_ON,
+ .id = PUNIT_POWER_WELL_ALWAYS_ON,
},
{
.name = "display",
.domains = VLV_DISPLAY_POWER_DOMAINS,
- .data = PUNIT_POWER_WELL_DISP2D,
+ .id = PUNIT_POWER_WELL_DISP2D,
.ops = &vlv_display_power_well_ops,
},
{
@@ -1994,7 +1968,7 @@ static struct i915_power_well vlv_power_wells[] = {
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
- .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
+ .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
},
{
.name = "dpio-tx-b-23",
@@ -2003,7 +1977,7 @@ static struct i915_power_well vlv_power_wells[] = {
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
- .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
+ .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
},
{
.name = "dpio-tx-c-01",
@@ -2012,7 +1986,7 @@ static struct i915_power_well vlv_power_wells[] = {
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
- .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
+ .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
},
{
.name = "dpio-tx-c-23",
@@ -2021,12 +1995,12 @@ static struct i915_power_well vlv_power_wells[] = {
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
- .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
+ .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
},
{
.name = "dpio-common",
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
- .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
+ .id = PUNIT_POWER_WELL_DPIO_CMN_BC,
.ops = &vlv_dpio_cmn_power_well_ops,
},
};
@@ -2046,19 +2020,19 @@ static struct i915_power_well chv_power_wells[] = {
* required for any pipe to work.
*/
.domains = CHV_DISPLAY_POWER_DOMAINS,
- .data = PIPE_A,
+ .id = PIPE_A,
.ops = &chv_pipe_power_well_ops,
},
{
.name = "dpio-common-bc",
.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
- .data = PUNIT_POWER_WELL_DPIO_CMN_BC,
+ .id = PUNIT_POWER_WELL_DPIO_CMN_BC,
.ops = &chv_dpio_cmn_power_well_ops,
},
{
.name = "dpio-common-d",
.domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
- .data = PUNIT_POWER_WELL_DPIO_CMN_D,
+ .id = PUNIT_POWER_WELL_DPIO_CMN_D,
.ops = &chv_dpio_cmn_power_well_ops,
},
};
@@ -2081,57 +2055,57 @@ static struct i915_power_well skl_power_wells[] = {
.always_on = 1,
.domains = POWER_DOMAIN_MASK,
.ops = &i9xx_always_on_power_well_ops,
- .data = SKL_DISP_PW_ALWAYS_ON,
+ .id = SKL_DISP_PW_ALWAYS_ON,
},
{
.name = "power well 1",
/* Handled by the DMC firmware */
.domains = 0,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_1,
+ .id = SKL_DISP_PW_1,
},
{
.name = "MISC IO power well",
/* Handled by the DMC firmware */
.domains = 0,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_MISC_IO,
+ .id = SKL_DISP_PW_MISC_IO,
},
{
.name = "DC off",
.domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS,
.ops = &gen9_dc_off_power_well_ops,
- .data = SKL_DISP_PW_DC_OFF,
+ .id = SKL_DISP_PW_DC_OFF,
},
{
.name = "power well 2",
.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_2,
+ .id = SKL_DISP_PW_2,
},
{
.name = "DDI A/E power well",
.domains = SKL_DISPLAY_DDI_A_E_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_DDI_A_E,
+ .id = SKL_DISP_PW_DDI_A_E,
},
{
.name = "DDI B power well",
.domains = SKL_DISPLAY_DDI_B_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_DDI_B,
+ .id = SKL_DISP_PW_DDI_B,
},
{
.name = "DDI C power well",
.domains = SKL_DISPLAY_DDI_C_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_DDI_C,
+ .id = SKL_DISP_PW_DDI_C,
},
{
.name = "DDI D power well",
.domains = SKL_DISPLAY_DDI_D_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_DDI_D,
+ .id = SKL_DISP_PW_DDI_D,
},
};
@@ -2146,31 +2120,33 @@ static struct i915_power_well bxt_power_wells[] = {
.name = "power well 1",
.domains = 0,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_1,
+ .id = SKL_DISP_PW_1,
},
{
.name = "DC off",
.domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS,
.ops = &gen9_dc_off_power_well_ops,
- .data = SKL_DISP_PW_DC_OFF,
+ .id = SKL_DISP_PW_DC_OFF,
},
{
.name = "power well 2",
.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
- .data = SKL_DISP_PW_2,
+ .id = SKL_DISP_PW_2,
},
{
.name = "dpio-common-a",
.domains = BXT_DPIO_CMN_A_POWER_DOMAINS,
.ops = &bxt_dpio_cmn_power_well_ops,
- .data = BXT_DPIO_CMN_A,
+ .id = BXT_DPIO_CMN_A,
+ .data = DPIO_PHY1,
},
{
.name = "dpio-common-bc",
.domains = BXT_DPIO_CMN_BC_POWER_DOMAINS,
.ops = &bxt_dpio_cmn_power_well_ops,
- .data = BXT_DPIO_CMN_BC,
+ .id = BXT_DPIO_CMN_BC,
+ .data = DPIO_PHY0,
},
};
@@ -2592,20 +2568,19 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
*/
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
{
- struct drm_device *dev = &dev_priv->drm;
struct i915_power_domains *power_domains = &dev_priv->power_domains;
power_domains->initializing = true;
- if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
skl_display_core_init(dev_priv, resume);
- } else if (IS_BROXTON(dev)) {
+ } else if (IS_BROXTON(dev_priv)) {
bxt_display_core_init(dev_priv, resume);
- } else if (IS_CHERRYVIEW(dev)) {
+ } else if (IS_CHERRYVIEW(dev_priv)) {
mutex_lock(&power_domains->lock);
chv_phy_control_init(dev_priv);
mutex_unlock(&power_domains->lock);
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev_priv)) {
mutex_lock(&power_domains->lock);
vlv_cmnlane_wa(dev_priv);
mutex_unlock(&power_domains->lock);
@@ -2740,8 +2715,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
struct device *kdev = &pdev->dev;
assert_rpm_wakelock_held(dev_priv);
- if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
- atomic_inc(&dev_priv->pm.atomic_seq);
+ atomic_dec(&dev_priv->pm.wakeref_count);
pm_runtime_mark_last_busy(kdev);
pm_runtime_put_autosuspend(kdev);
@@ -2760,7 +2734,6 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
- struct drm_device *dev = &dev_priv->drm;
struct device *kdev = &pdev->dev;
pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
@@ -2772,7 +2745,7 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
* so the driver's own RPM reference tracking asserts also work on
* platforms without RPM support.
*/
- if (!HAS_RUNTIME_PM(dev)) {
+ if (!HAS_RUNTIME_PM(dev_priv)) {
pm_runtime_dont_use_autosuspend(kdev);
pm_runtime_get_sync(kdev);
} else {
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c551024d4871..27808e91cb5a 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -251,7 +251,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
* HW workaround, need to write this twice for issue
* that may result in first write getting masked.
*/
- if (HAS_PCH_IBX(dev)) {
+ if (HAS_PCH_IBX(dev_priv)) {
I915_WRITE(intel_sdvo->sdvo_reg, val);
POSTING_READ(intel_sdvo->sdvo_reg);
}
@@ -307,7 +307,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
static const struct _sdvo_cmd_name {
u8 cmd;
const char *name;
-} sdvo_cmd_names[] = {
+} __attribute__ ((packed)) sdvo_cmd_names[] = {
SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
@@ -1133,7 +1133,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
pipe_config->pipe_bpp = 8*3;
- if (HAS_PCH_SPLIT(encoder->base.dev))
+ if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
pipe_config->has_pch_encoder = true;
/* We need to construct preferred input timings based on our
@@ -1195,8 +1195,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
- struct drm_device *dev = intel_encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
struct drm_display_mode *mode = &crtc_state->base.mode;
@@ -1269,13 +1268,13 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
return;
/* Set the SDVO control regs. */
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
/* The real mode polarity is set by the SDVO commands, using
* struct intel_sdvo_dtd. */
sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
- if (!HAS_PCH_SPLIT(dev) && crtc_state->limited_color_range)
+ if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range)
sdvox |= HDMI_COLOR_RANGE_16_235;
- if (INTEL_INFO(dev)->gen < 5)
+ if (INTEL_GEN(dev_priv) < 5)
sdvox |= SDVO_BORDER_ENABLE;
} else {
sdvox = I915_READ(intel_sdvo->sdvo_reg);
@@ -1286,7 +1285,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
}
- if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_CPT)
sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe);
else
sdvox |= SDVO_PIPE_SEL(crtc->pipe);
@@ -1294,9 +1293,10 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
if (intel_sdvo->has_hdmi_audio)
sdvox |= SDVO_AUDIO_ENABLE;
- if (INTEL_INFO(dev)->gen >= 4) {
+ if (INTEL_GEN(dev_priv) >= 4) {
/* done in crtc_mode_set as the dpll_md reg must be written early */
- } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+ } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
+ IS_G33(dev_priv)) {
/* done in crtc_mode_set as it lives inside the dpll register */
} else {
sdvox |= (crtc_state->pixel_multiplier - 1)
@@ -1304,7 +1304,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
}
if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL &&
- INTEL_INFO(dev)->gen < 5)
+ INTEL_GEN(dev_priv) < 5)
sdvox |= SDVO_STALL_SELECT;
intel_sdvo_write_sdvox(intel_sdvo, sdvox);
}
@@ -1339,7 +1339,7 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
if (!(tmp & SDVO_ENABLE) && (active_outputs == 0))
return false;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev_priv))
*pipe = PORT_TO_PIPE_CPT(tmp);
else
*pipe = PORT_TO_PIPE(tmp);
@@ -1389,7 +1389,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
* encoder->get_config we so already have a valid pixel multplier on all
* other platfroms.
*/
- if (IS_I915G(dev) || IS_I915GM(dev)) {
+ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
pipe_config->pixel_multiplier =
((sdvox & SDVO_PORT_MULTIPLY_MASK)
>> SDVO_PORT_MULTIPLY_SHIFT) + 1;
@@ -1471,7 +1471,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder,
temp &= ~SDVO_ENABLE;
intel_sdvo_write_sdvox(intel_sdvo, temp);
- intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+ intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
@@ -1508,7 +1508,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder,
intel_sdvo_write_sdvox(intel_sdvo, temp);
for (i = 0; i < 2; i++)
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
/* Warn if the device reported failure to sync.
@@ -1595,15 +1595,15 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
{
- struct drm_device *dev = intel_sdvo->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev);
uint16_t hotplug;
- if (!I915_HAS_HOTPLUG(dev))
+ if (!I915_HAS_HOTPLUG(dev_priv))
return 0;
/* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
* on the line. */
- if (IS_I945G(dev) || IS_I945GM(dev))
+ if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
return 0;
if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
@@ -2410,10 +2410,10 @@ static void
intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_connector *connector)
{
- struct drm_device *dev = connector->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(connector->base.base.dev);
intel_attach_force_audio_property(&connector->base.base);
- if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) {
+ if (INTEL_GEN(dev_priv) >= 4 && IS_MOBILE(dev_priv)) {
intel_attach_broadcast_rgb_property(&connector->base.base);
intel_sdvo->color_range_auto = true;
}
@@ -2981,6 +2981,7 @@ bool intel_sdvo_init(struct drm_device *dev,
/* encoder type will be decided later */
intel_encoder = &intel_sdvo->base;
intel_encoder->type = INTEL_OUTPUT_SDVO;
+ intel_encoder->port = port;
drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0,
"SDVO %c", port_name(port));
@@ -2996,7 +2997,7 @@ bool intel_sdvo_init(struct drm_device *dev,
}
intel_encoder->compute_config = intel_sdvo_compute_config;
- if (HAS_PCH_SPLIT(dev)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
intel_encoder->disable = pch_disable_sdvo;
intel_encoder->post_disable = pch_post_disable_sdvo;
} else {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index dbed12c484c9..8f131a08d440 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -203,9 +203,6 @@ skl_update_plane(struct drm_plane *drm_plane,
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_plane *intel_plane = to_intel_plane(drm_plane);
struct drm_framebuffer *fb = plane_state->base.fb;
- const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
- struct drm_crtc *crtc = crtc_state->base.crtc;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const int pipe = intel_plane->pipe;
const int plane = intel_plane->plane + 1;
u32 plane_ctl;
@@ -227,13 +224,10 @@ skl_update_plane(struct drm_plane *drm_plane,
PLANE_CTL_PIPE_CSC_ENABLE;
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
- plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
+ plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
plane_ctl |= skl_plane_ctl_rotation(rotation);
- if (wm->dirty_pipes & drm_crtc_mask(crtc))
- skl_write_plane_wm(intel_crtc, wm, plane);
-
if (key->flags) {
I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
@@ -292,14 +286,6 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
const int pipe = intel_plane->pipe;
const int plane = intel_plane->plane + 1;
- /*
- * We only populate skl_results on watermark updates, and if the
- * plane's visiblity isn't actually changing neither is its watermarks.
- */
- if (!dplane->state->visible)
- skl_write_plane_wm(to_intel_crtc(crtc),
- &dev_priv->wm.skl_results, plane);
-
I915_WRITE(PLANE_CTL(pipe, plane), 0);
I915_WRITE(PLANE_SURF(pipe, plane), 0);
@@ -420,9 +406,15 @@ vlv_update_plane(struct drm_plane *dplane,
*/
sprctl |= SP_GAMMA_ENABLE;
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
sprctl |= SP_TILED;
+ if (rotation & DRM_ROTATE_180)
+ sprctl |= SP_ROTATE_180;
+
+ if (rotation & DRM_REFLECT_X)
+ sprctl |= SP_MIRROR;
+
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -432,11 +424,11 @@ vlv_update_plane(struct drm_plane *dplane,
intel_add_fb_offsets(&x, &y, plane_state, 0);
sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
- if (rotation == DRM_ROTATE_180) {
- sprctl |= SP_ROTATE_180;
-
+ if (rotation & DRM_ROTATE_180) {
x += src_w;
y += src_h;
+ } else if (rotation & DRM_REFLECT_X) {
+ x += src_w;
}
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -450,13 +442,13 @@ vlv_update_plane(struct drm_plane *dplane,
if (key->flags & I915_SET_COLORKEY_SOURCE)
sprctl |= SP_SOURCE_KEY;
- if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
+ if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
chv_update_csc(intel_plane, fb->pixel_format);
I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
else
I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
@@ -539,15 +531,18 @@ ivb_update_plane(struct drm_plane *plane,
*/
sprctl |= SPRITE_GAMMA_ENABLE;
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
sprctl |= SPRITE_TILED;
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (rotation & DRM_ROTATE_180)
+ sprctl |= SPRITE_ROTATE_180;
+
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
else
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
sprctl |= SPRITE_PIPE_CSC_ENABLE;
/* Sizes are 0 based */
@@ -562,14 +557,11 @@ ivb_update_plane(struct drm_plane *plane,
intel_add_fb_offsets(&x, &y, plane_state, 0);
sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
- if (rotation == DRM_ROTATE_180) {
- sprctl |= SPRITE_ROTATE_180;
-
- /* HSW and BDW does this automagically in hardware */
- if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
- x += src_w;
- y += src_h;
- }
+ /* HSW+ does this automagically in hardware */
+ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) &&
+ rotation & DRM_ROTATE_180) {
+ x += src_w;
+ y += src_h;
}
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -590,9 +582,9 @@ ivb_update_plane(struct drm_plane *plane,
/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
* register */
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
- else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
else
I915_WRITE(SPRLINOFF(pipe), linear_offset);
@@ -677,10 +669,13 @@ ilk_update_plane(struct drm_plane *plane,
*/
dvscntr |= DVS_GAMMA_ENABLE;
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dvscntr |= DVS_TILED;
- if (IS_GEN6(dev))
+ if (rotation & DRM_ROTATE_180)
+ dvscntr |= DVS_ROTATE_180;
+
+ if (IS_GEN6(dev_priv))
dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
/* Sizes are 0 based */
@@ -696,9 +691,7 @@ ilk_update_plane(struct drm_plane *plane,
intel_add_fb_offsets(&x, &y, plane_state, 0);
dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
- if (rotation == DRM_ROTATE_180) {
- dvscntr |= DVS_ROTATE_180;
-
+ if (rotation & DRM_ROTATE_180) {
x += src_w;
y += src_h;
}
@@ -719,7 +712,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
- if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+ if (fb->modifier == I915_FORMAT_MOD_X_TILED)
I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
else
I915_WRITE(DVSLINOFF(pipe), linear_offset);
@@ -753,7 +746,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
struct intel_crtc_state *crtc_state,
struct intel_plane_state *state)
{
- struct drm_device *dev = plane->dev;
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct drm_crtc *crtc = state->base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -769,15 +762,8 @@ intel_check_sprite_plane(struct drm_plane *plane,
bool can_scale;
int ret;
- src->x1 = state->base.src_x;
- src->y1 = state->base.src_y;
- src->x2 = state->base.src_x + state->base.src_w;
- src->y2 = state->base.src_y + state->base.src_h;
-
- dst->x1 = state->base.crtc_x;
- dst->y1 = state->base.crtc_y;
- dst->x2 = state->base.crtc_x + state->base.crtc_w;
- dst->y2 = state->base.crtc_y + state->base.crtc_h;
+ *src = drm_plane_state_src(&state->base);
+ *dst = drm_plane_state_dest(&state->base);
if (!fb) {
state->base.visible = false;
@@ -797,7 +783,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
}
/* setup can_scale, min_scale, max_scale */
- if (INTEL_INFO(dev)->gen >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
/* use scaler when colorkey is not required */
if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
can_scale = 1;
@@ -913,7 +899,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
- if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 ||
+ if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
width_bytes > 4096 || fb->pitches[0] > 4096)) {
DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
return -EINVAL;
@@ -932,7 +918,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
dst->y1 = crtc_y;
dst->y2 = crtc_y + crtc_h;
- if (INTEL_GEN(dev) >= 9) {
+ if (INTEL_GEN(dev_priv) >= 9) {
ret = skl_check_plane_surface(state);
if (ret)
return ret;
@@ -944,6 +930,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_intel_sprite_colorkey *set = data;
struct drm_plane *plane;
struct drm_plane_state *plane_state;
@@ -955,7 +942,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
return -EINVAL;
- if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
set->flags & I915_SET_COLORKEY_DESTINATION)
return -EINVAL;
@@ -987,9 +974,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
drm_modeset_backoff(&ctx);
}
- if (ret)
- drm_atomic_state_free(state);
-
+ drm_atomic_state_put(state);
out:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -1039,19 +1024,18 @@ static uint32_t skl_plane_formats[] = {
DRM_FORMAT_VYUY,
};
-int
-intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
+struct intel_plane *
+intel_sprite_plane_create(struct drm_i915_private *dev_priv,
+ enum pipe pipe, int plane)
{
struct intel_plane *intel_plane = NULL;
struct intel_plane_state *state = NULL;
unsigned long possible_crtcs;
const uint32_t *plane_formats;
+ unsigned int supported_rotations;
int num_plane_formats;
int ret;
- if (INTEL_INFO(dev)->gen < 5)
- return -ENODEV;
-
intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
if (!intel_plane) {
ret = -ENOMEM;
@@ -1065,26 +1049,26 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
}
intel_plane->base.state = &state->base;
- switch (INTEL_INFO(dev)->gen) {
- case 5:
- case 6:
+ if (INTEL_GEN(dev_priv) >= 9) {
intel_plane->can_scale = true;
- intel_plane->max_downscale = 16;
- intel_plane->update_plane = ilk_update_plane;
- intel_plane->disable_plane = ilk_disable_plane;
+ state->scaler_id = -1;
- if (IS_GEN6(dev)) {
- plane_formats = snb_plane_formats;
- num_plane_formats = ARRAY_SIZE(snb_plane_formats);
- } else {
- plane_formats = ilk_plane_formats;
- num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
- }
- break;
+ intel_plane->update_plane = skl_update_plane;
+ intel_plane->disable_plane = skl_disable_plane;
+
+ plane_formats = skl_plane_formats;
+ num_plane_formats = ARRAY_SIZE(skl_plane_formats);
+ } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ intel_plane->can_scale = false;
+ intel_plane->max_downscale = 1;
- case 7:
- case 8:
- if (IS_IVYBRIDGE(dev)) {
+ intel_plane->update_plane = vlv_update_plane;
+ intel_plane->disable_plane = vlv_disable_plane;
+
+ plane_formats = vlv_plane_formats;
+ num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
+ } else if (INTEL_GEN(dev_priv) >= 7) {
+ if (IS_IVYBRIDGE(dev_priv)) {
intel_plane->can_scale = true;
intel_plane->max_downscale = 2;
} else {
@@ -1092,33 +1076,38 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
intel_plane->max_downscale = 1;
}
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
- intel_plane->update_plane = vlv_update_plane;
- intel_plane->disable_plane = vlv_disable_plane;
+ intel_plane->update_plane = ivb_update_plane;
+ intel_plane->disable_plane = ivb_disable_plane;
- plane_formats = vlv_plane_formats;
- num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
- } else {
- intel_plane->update_plane = ivb_update_plane;
- intel_plane->disable_plane = ivb_disable_plane;
+ plane_formats = snb_plane_formats;
+ num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+ } else {
+ intel_plane->can_scale = true;
+ intel_plane->max_downscale = 16;
+
+ intel_plane->update_plane = ilk_update_plane;
+ intel_plane->disable_plane = ilk_disable_plane;
+ if (IS_GEN6(dev_priv)) {
plane_formats = snb_plane_formats;
num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+ } else {
+ plane_formats = ilk_plane_formats;
+ num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
}
- break;
- case 9:
- intel_plane->can_scale = true;
- intel_plane->update_plane = skl_update_plane;
- intel_plane->disable_plane = skl_disable_plane;
- state->scaler_id = -1;
+ }
- plane_formats = skl_plane_formats;
- num_plane_formats = ARRAY_SIZE(skl_plane_formats);
- break;
- default:
- MISSING_CASE(INTEL_INFO(dev)->gen);
- ret = -ENODEV;
- goto fail;
+ if (INTEL_GEN(dev_priv) >= 9) {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_90 |
+ DRM_ROTATE_180 | DRM_ROTATE_270;
+ } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_180 |
+ DRM_REFLECT_X;
+ } else {
+ supported_rotations =
+ DRM_ROTATE_0 | DRM_ROTATE_180;
}
intel_plane->pipe = pipe;
@@ -1128,30 +1117,32 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
possible_crtcs = (1 << pipe);
- if (INTEL_INFO(dev)->gen >= 9)
- ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
- &intel_plane_funcs,
+ if (INTEL_GEN(dev_priv) >= 9)
+ ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
+ possible_crtcs, &intel_plane_funcs,
plane_formats, num_plane_formats,
DRM_PLANE_TYPE_OVERLAY,
"plane %d%c", plane + 2, pipe_name(pipe));
else
- ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
- &intel_plane_funcs,
+ ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
+ possible_crtcs, &intel_plane_funcs,
plane_formats, num_plane_formats,
DRM_PLANE_TYPE_OVERLAY,
"sprite %c", sprite_name(pipe, plane));
if (ret)
goto fail;
- intel_create_rotation_property(dev, intel_plane);
+ drm_plane_create_rotation_property(&intel_plane->base,
+ DRM_ROTATE_0,
+ supported_rotations);
drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
- return 0;
+ return intel_plane;
fail:
kfree(state);
kfree(intel_plane);
- return ret;
+ return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index d960e4866595..78cdfc6833d6 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -86,7 +86,8 @@ struct intel_tv {
};
struct video_levels {
- int blank, black, burst;
+ u16 blank, black;
+ u8 burst;
};
struct color_conversion {
@@ -339,34 +340,43 @@ static const struct video_levels component_levels = {
struct tv_mode {
const char *name;
- int clock;
- int refresh; /* in millihertz (for precision) */
+
+ u32 clock;
+ u16 refresh; /* in millihertz (for precision) */
u32 oversample;
- int hsync_end, hblank_start, hblank_end, htotal;
- bool progressive, trilevel_sync, component_only;
- int vsync_start_f1, vsync_start_f2, vsync_len;
- bool veq_ena;
- int veq_start_f1, veq_start_f2, veq_len;
- int vi_end_f1, vi_end_f2, nbr_end;
- bool burst_ena;
- int hburst_start, hburst_len;
- int vburst_start_f1, vburst_end_f1;
- int vburst_start_f2, vburst_end_f2;
- int vburst_start_f3, vburst_end_f3;
- int vburst_start_f4, vburst_end_f4;
+ u8 hsync_end;
+ u16 hblank_start, hblank_end, htotal;
+ bool progressive : 1, trilevel_sync : 1, component_only : 1;
+ u8 vsync_start_f1, vsync_start_f2, vsync_len;
+ bool veq_ena : 1;
+ u8 veq_start_f1, veq_start_f2, veq_len;
+ u8 vi_end_f1, vi_end_f2;
+ u16 nbr_end;
+ bool burst_ena : 1;
+ u8 hburst_start, hburst_len;
+ u8 vburst_start_f1;
+ u16 vburst_end_f1;
+ u8 vburst_start_f2;
+ u16 vburst_end_f2;
+ u8 vburst_start_f3;
+ u16 vburst_end_f3;
+ u8 vburst_start_f4;
+ u16 vburst_end_f4;
/*
* subcarrier programming
*/
- int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
+ u16 dda2_size, dda3_size;
+ u8 dda1_inc;
+ u16 dda2_inc, dda3_inc;
u32 sc_reset;
- bool pal_burst;
+ bool pal_burst : 1;
/*
* blank/black levels
*/
const struct video_levels *composite_levels, *svideo_levels;
const struct color_conversion *composite_color, *svideo_color;
const u32 *filter_table;
- int max_srcw;
+ u16 max_srcw;
};
@@ -846,7 +856,7 @@ intel_enable_tv(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = to_i915(dev);
/* Prevents vblank waits from timing out in intel_tv_detect_type() */
- intel_wait_for_vblank(encoder->base.dev,
+ intel_wait_for_vblank(dev_priv,
to_intel_crtc(encoder->base.crtc)->pipe);
I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
@@ -1019,8 +1029,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
struct intel_tv *intel_tv = enc_to_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
@@ -1095,7 +1104,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder,
tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
/* Enable two fixes for the chips that need them. */
- if (IS_I915GM(dev))
+ if (IS_I915GM(dev_priv))
tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
@@ -1106,7 +1115,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder,
set_color_conversion(dev_priv, color_conversion);
- if (INTEL_INFO(dev)->gen >= 4)
+ if (INTEL_GEN(dev_priv) >= 4)
I915_WRITE(TV_CLR_KNOBS, 0x00404000);
else
I915_WRITE(TV_CLR_KNOBS, 0x00606000);
@@ -1220,7 +1229,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
* The TV sense state should be cleared to zero on cantiga platform. Otherwise
* the TV is misdetected. This is hardware requirement.
*/
- if (IS_GM45(dev))
+ if (IS_GM45(dev_priv))
tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
@@ -1228,7 +1237,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
I915_WRITE(TV_DAC, tv_dac);
POSTING_READ(TV_DAC);
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
type = -1;
tv_dac = I915_READ(TV_DAC);
@@ -1258,7 +1267,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
POSTING_READ(TV_CTL);
/* For unknown reasons the hw barfs if we don't do this vblank wait. */
- intel_wait_for_vblank(dev, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
/* Restore interrupt config */
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
@@ -1610,7 +1619,9 @@ intel_tv_init(struct drm_device *dev)
intel_connector->get_hw_state = intel_connector_get_hw_state;
intel_connector_attach_encoder(intel_connector, intel_encoder);
+
intel_encoder->type = INTEL_OUTPUT_TVOUT;
+ intel_encoder->port = PORT_NONE;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
intel_encoder->cloneable = 0;
intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index ee2306a79747..d7be0d94ba4d 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -231,19 +231,21 @@ intel_uncore_fw_release_timer(struct hrtimer *timer)
{
struct intel_uncore_forcewake_domain *domain =
container_of(timer, struct intel_uncore_forcewake_domain, timer);
+ struct drm_i915_private *dev_priv = domain->i915;
unsigned long irqflags;
- assert_rpm_device_not_suspended(domain->i915);
+ assert_rpm_device_not_suspended(dev_priv);
- spin_lock_irqsave(&domain->i915->uncore.lock, irqflags);
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (WARN_ON(domain->wake_count == 0))
domain->wake_count++;
- if (--domain->wake_count == 0)
- domain->i915->uncore.funcs.force_wake_put(domain->i915,
- 1 << domain->id);
+ if (--domain->wake_count == 0) {
+ dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask);
+ dev_priv->uncore.fw_domains_active &= ~domain->mask;
+ }
- spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags);
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
return HRTIMER_NORESTART;
}
@@ -254,7 +256,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv,
unsigned long irqflags;
struct intel_uncore_forcewake_domain *domain;
int retry_count = 100;
- enum forcewake_domains fw = 0, active_domains;
+ enum forcewake_domains fw, active_domains;
/* Hold uncore.lock across reset to prevent any register access
* with forcewake not set correctly. Wait until all pending
@@ -291,10 +293,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv,
WARN_ON(active_domains);
- for_each_fw_domain(domain, dev_priv)
- if (domain->wake_count)
- fw |= domain->mask;
-
+ fw = dev_priv->uncore.fw_domains_active;
if (fw)
dev_priv->uncore.funcs.force_wake_put(dev_priv, fw);
@@ -403,6 +402,8 @@ check_for_unclaimed_mmio(struct drm_i915_private *dev_priv)
static void __intel_uncore_early_sanitize(struct drm_i915_private *dev_priv,
bool restore_forcewake)
{
+ struct intel_device_info *info = mkwrite_device_info(dev_priv);
+
/* clear out unclaimed reg detection bit */
if (check_for_unclaimed_mmio(dev_priv))
DRM_DEBUG("unclaimed mmio detected on uncore init, clearing\n");
@@ -420,6 +421,10 @@ static void __intel_uncore_early_sanitize(struct drm_i915_private *dev_priv,
GT_FIFO_CTL_RC6_POLICY_STALL);
}
+ /* Enable Decoupled MMIO only on BXT C stepping onwards */
+ if (!IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
+ info->has_decoupled_mmio = false;
+
intel_uncore_forcewake_reset(dev_priv, restore_forcewake);
}
@@ -443,9 +448,6 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
{
struct intel_uncore_forcewake_domain *domain;
- if (!dev_priv->uncore.funcs.force_wake_get)
- return;
-
fw_domains &= dev_priv->uncore.fw_domains;
for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
@@ -453,8 +455,10 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
fw_domains &= ~domain->mask;
}
- if (fw_domains)
+ if (fw_domains) {
dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+ dev_priv->uncore.fw_domains_active |= fw_domains;
+ }
}
/**
@@ -509,9 +513,6 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv,
{
struct intel_uncore_forcewake_domain *domain;
- if (!dev_priv->uncore.funcs.force_wake_put)
- return;
-
fw_domains &= dev_priv->uncore.fw_domains;
for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
@@ -567,13 +568,10 @@ void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv,
void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
{
- struct intel_uncore_forcewake_domain *domain;
-
if (!dev_priv->uncore.funcs.force_wake_get)
return;
- for_each_fw_domain(domain, dev_priv)
- WARN_ON(domain->wake_count);
+ WARN_ON(dev_priv->uncore.fw_domains_active);
}
/* We give fast paths for the really cool registers */
@@ -589,49 +587,148 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
__fwd; \
})
-#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
+static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry)
+{
+ if (offset < entry->start)
+ return -1;
+ else if (offset > entry->end)
+ return 1;
+ else
+ return 0;
+}
-#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x2000, 0x4000) || \
- REG_RANGE((reg), 0x5000, 0x8000) || \
- REG_RANGE((reg), 0xB000, 0x12000) || \
- REG_RANGE((reg), 0x2E000, 0x30000))
+/* Copied and "macroized" from lib/bsearch.c */
+#define BSEARCH(key, base, num, cmp) ({ \
+ unsigned int start__ = 0, end__ = (num); \
+ typeof(base) result__ = NULL; \
+ while (start__ < end__) { \
+ unsigned int mid__ = start__ + (end__ - start__) / 2; \
+ int ret__ = (cmp)((key), (base) + mid__); \
+ if (ret__ < 0) { \
+ end__ = mid__; \
+ } else if (ret__ > 0) { \
+ start__ = mid__ + 1; \
+ } else { \
+ result__ = (base) + mid__; \
+ break; \
+ } \
+ } \
+ result__; \
+})
+
+static enum forcewake_domains
+find_fw_domain(struct drm_i915_private *dev_priv, u32 offset)
+{
+ const struct intel_forcewake_range *entry;
+
+ entry = BSEARCH(offset,
+ dev_priv->uncore.fw_domains_table,
+ dev_priv->uncore.fw_domains_table_entries,
+ fw_range_cmp);
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x12000, 0x14000) || \
- REG_RANGE((reg), 0x22000, 0x24000) || \
- REG_RANGE((reg), 0x30000, 0x40000))
+ return entry ? entry->domains : 0;
+}
-#define __vlv_reg_read_fw_domains(offset) \
+static void
+intel_fw_table_check(struct drm_i915_private *dev_priv)
+{
+ const struct intel_forcewake_range *ranges;
+ unsigned int num_ranges;
+ s32 prev;
+ unsigned int i;
+
+ if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+ return;
+
+ ranges = dev_priv->uncore.fw_domains_table;
+ if (!ranges)
+ return;
+
+ num_ranges = dev_priv->uncore.fw_domains_table_entries;
+
+ for (i = 0, prev = -1; i < num_ranges; i++, ranges++) {
+ WARN_ON_ONCE(IS_GEN9(dev_priv) &&
+ (prev + 1) != (s32)ranges->start);
+ WARN_ON_ONCE(prev >= (s32)ranges->start);
+ prev = ranges->start;
+ WARN_ON_ONCE(prev >= (s32)ranges->end);
+ prev = ranges->end;
+ }
+}
+
+#define GEN_FW_RANGE(s, e, d) \
+ { .start = (s), .end = (e), .domains = (d) }
+
+#define HAS_FWTABLE(dev_priv) \
+ (IS_GEN9(dev_priv) || \
+ IS_CHERRYVIEW(dev_priv) || \
+ IS_VALLEYVIEW(dev_priv))
+
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __vlv_fw_ranges[] = {
+ GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x5000, 0x7fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xb000, 0x11fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA),
+};
+
+#define __fwtable_reg_read_fw_domains(offset) \
({ \
enum forcewake_domains __fwd = 0; \
- if (!NEEDS_FORCE_WAKE(offset)) \
- __fwd = 0; \
- else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_MEDIA; \
+ if (NEEDS_FORCE_WAKE((offset))) \
+ __fwd = find_fw_domain(dev_priv, offset); \
__fwd; \
})
+/* *Must* be sorted by offset! See intel_shadow_table_check(). */
static const i915_reg_t gen8_shadowed_regs[] = {
- GEN6_RPNSWREQ,
- GEN6_RC_VIDEO_FREQ,
- RING_TAIL(RENDER_RING_BASE),
- RING_TAIL(GEN6_BSD_RING_BASE),
- RING_TAIL(VEBOX_RING_BASE),
- RING_TAIL(BLT_RING_BASE),
+ RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
+ GEN6_RPNSWREQ, /* 0xA008 */
+ GEN6_RC_VIDEO_FREQ, /* 0xA00C */
+ RING_TAIL(GEN6_BSD_RING_BASE), /* 0x12000 (base) */
+ RING_TAIL(VEBOX_RING_BASE), /* 0x1a000 (base) */
+ RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
/* TODO: Other registers are not yet used */
};
+static void intel_shadow_table_check(void)
+{
+ const i915_reg_t *reg = gen8_shadowed_regs;
+ s32 prev;
+ u32 offset;
+ unsigned int i;
+
+ if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+ return;
+
+ for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) {
+ offset = i915_mmio_reg_offset(*reg);
+ WARN_ON_ONCE(prev >= (s32)offset);
+ prev = offset;
+ }
+}
+
+static int mmio_reg_cmp(u32 key, const i915_reg_t *reg)
+{
+ u32 offset = i915_mmio_reg_offset(*reg);
+
+ if (key < offset)
+ return -1;
+ else if (key > offset)
+ return 1;
+ else
+ return 0;
+}
+
static bool is_gen8_shadowed(u32 offset)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
- if (offset == gen8_shadowed_regs[i].reg)
- return true;
+ const i915_reg_t *regs = gen8_shadowed_regs;
- return false;
+ return BSEARCH(offset, regs, ARRAY_SIZE(gen8_shadowed_regs),
+ mmio_reg_cmp);
}
#define __gen8_reg_write_fw_domains(offset) \
@@ -644,143 +741,70 @@ static bool is_gen8_shadowed(u32 offset)
__fwd; \
})
-#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x2000, 0x4000) || \
- REG_RANGE((reg), 0x5200, 0x8000) || \
- REG_RANGE((reg), 0x8300, 0x8500) || \
- REG_RANGE((reg), 0xB000, 0xB480) || \
- REG_RANGE((reg), 0xE000, 0xE800))
-
-#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x8800, 0x8900) || \
- REG_RANGE((reg), 0xD000, 0xD800) || \
- REG_RANGE((reg), 0x12000, 0x14000) || \
- REG_RANGE((reg), 0x1A000, 0x1C000) || \
- REG_RANGE((reg), 0x1E800, 0x1EA00) || \
- REG_RANGE((reg), 0x30000, 0x38000))
-
-#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x4000, 0x5000) || \
- REG_RANGE((reg), 0x8000, 0x8300) || \
- REG_RANGE((reg), 0x8500, 0x8600) || \
- REG_RANGE((reg), 0x9000, 0xB000) || \
- REG_RANGE((reg), 0xF000, 0x10000))
-
-#define __chv_reg_read_fw_domains(offset) \
-({ \
- enum forcewake_domains __fwd = 0; \
- if (!NEEDS_FORCE_WAKE(offset)) \
- __fwd = 0; \
- else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
- __fwd; \
-})
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __chv_fw_ranges[] = {
+ GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x8800, 0x88ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x1a000, 0x1bfff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x1e800, 0x1e9ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA),
+};
-#define __chv_reg_write_fw_domains(offset) \
+#define __fwtable_reg_write_fw_domains(offset) \
({ \
enum forcewake_domains __fwd = 0; \
- if (!NEEDS_FORCE_WAKE(offset) || is_gen8_shadowed(offset)) \
- __fwd = 0; \
- else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+ if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \
+ __fwd = find_fw_domain(dev_priv, offset); \
__fwd; \
})
-#define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \
- REG_RANGE((reg), 0xB00, 0x2000)
-
-#define FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x2000, 0x2700) || \
- REG_RANGE((reg), 0x3000, 0x4000) || \
- REG_RANGE((reg), 0x5200, 0x8000) || \
- REG_RANGE((reg), 0x8140, 0x8160) || \
- REG_RANGE((reg), 0x8300, 0x8500) || \
- REG_RANGE((reg), 0x8C00, 0x8D00) || \
- REG_RANGE((reg), 0xB000, 0xB480) || \
- REG_RANGE((reg), 0xE000, 0xE900) || \
- REG_RANGE((reg), 0x24400, 0x24800))
-
-#define FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) \
- (REG_RANGE((reg), 0x8130, 0x8140) || \
- REG_RANGE((reg), 0x8800, 0x8A00) || \
- REG_RANGE((reg), 0xD000, 0xD800) || \
- REG_RANGE((reg), 0x12000, 0x14000) || \
- REG_RANGE((reg), 0x1A000, 0x1EA00) || \
- REG_RANGE((reg), 0x30000, 0x40000))
-
-#define FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg) \
- REG_RANGE((reg), 0x9400, 0x9800)
-
-#define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \
- ((reg) < 0x40000 && \
- !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \
- !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \
- !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \
- !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg))
-
-#define SKL_NEEDS_FORCE_WAKE(reg) \
- ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
-
-#define __gen9_reg_read_fw_domains(offset) \
-({ \
- enum forcewake_domains __fwd; \
- if (!SKL_NEEDS_FORCE_WAKE(offset)) \
- __fwd = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
- else \
- __fwd = FORCEWAKE_BLITTER; \
- __fwd; \
-})
-
-static const i915_reg_t gen9_shadowed_regs[] = {
- RING_TAIL(RENDER_RING_BASE),
- RING_TAIL(GEN6_BSD_RING_BASE),
- RING_TAIL(VEBOX_RING_BASE),
- RING_TAIL(BLT_RING_BASE),
- GEN6_RPNSWREQ,
- GEN6_RC_VIDEO_FREQ,
- /* TODO: Other registers are not yet used */
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __gen9_fw_ranges[] = {
+ GEN_FW_RANGE(0x0, 0xaff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */
+ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8000, 0x812f, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8160, 0x82ff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8500, 0x87ff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x8a00, 0x8bff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x8d00, 0x93ff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x9800, 0xafff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xb480, 0xcfff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0xd800, 0xdfff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xe900, 0x11fff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x14000, 0x19fff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA),
+ GEN_FW_RANGE(0x1ea00, 0x243ff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x24800, 0x2ffff, FORCEWAKE_BLITTER),
+ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA),
};
-static bool is_gen9_shadowed(u32 offset)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++)
- if (offset == gen9_shadowed_regs[i].reg)
- return true;
-
- return false;
-}
-
-#define __gen9_reg_write_fw_domains(offset) \
-({ \
- enum forcewake_domains __fwd; \
- if (!SKL_NEEDS_FORCE_WAKE(offset) || is_gen9_shadowed(offset)) \
- __fwd = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
- __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
- else \
- __fwd = FORCEWAKE_BLITTER; \
- __fwd; \
-})
-
static void
ilk_dummy_write(struct drm_i915_private *dev_priv)
{
@@ -815,6 +839,66 @@ unclaimed_reg_debug(struct drm_i915_private *dev_priv,
__unclaimed_reg_debug(dev_priv, reg, read, before);
}
+static const enum decoupled_power_domain fw2dpd_domain[] = {
+ GEN9_DECOUPLED_PD_RENDER,
+ GEN9_DECOUPLED_PD_BLITTER,
+ GEN9_DECOUPLED_PD_ALL,
+ GEN9_DECOUPLED_PD_MEDIA,
+ GEN9_DECOUPLED_PD_ALL,
+ GEN9_DECOUPLED_PD_ALL,
+ GEN9_DECOUPLED_PD_ALL
+};
+
+/*
+ * Decoupled MMIO access for only 1 DWORD
+ */
+static void __gen9_decoupled_mmio_access(struct drm_i915_private *dev_priv,
+ u32 reg,
+ enum forcewake_domains fw_domain,
+ enum decoupled_ops operation)
+{
+ enum decoupled_power_domain dp_domain;
+ u32 ctrl_reg_data = 0;
+
+ dp_domain = fw2dpd_domain[fw_domain - 1];
+
+ ctrl_reg_data |= reg;
+ ctrl_reg_data |= (operation << GEN9_DECOUPLED_OP_SHIFT);
+ ctrl_reg_data |= (dp_domain << GEN9_DECOUPLED_PD_SHIFT);
+ ctrl_reg_data |= GEN9_DECOUPLED_DW1_GO;
+ __raw_i915_write32(dev_priv, GEN9_DECOUPLED_REG0_DW1, ctrl_reg_data);
+
+ if (wait_for_atomic((__raw_i915_read32(dev_priv,
+ GEN9_DECOUPLED_REG0_DW1) &
+ GEN9_DECOUPLED_DW1_GO) == 0,
+ FORCEWAKE_ACK_TIMEOUT_MS))
+ DRM_ERROR("Decoupled MMIO wait timed out\n");
+}
+
+static inline u32
+__gen9_decoupled_mmio_read32(struct drm_i915_private *dev_priv,
+ u32 reg,
+ enum forcewake_domains fw_domain)
+{
+ __gen9_decoupled_mmio_access(dev_priv, reg, fw_domain,
+ GEN9_DECOUPLED_OP_READ);
+
+ return __raw_i915_read32(dev_priv, GEN9_DECOUPLED_REG0_DW0);
+}
+
+static inline void
+__gen9_decoupled_mmio_write(struct drm_i915_private *dev_priv,
+ u32 reg, u32 data,
+ enum forcewake_domains fw_domain)
+{
+
+ __raw_i915_write32(dev_priv, GEN9_DECOUPLED_REG0_DW0, data);
+
+ __gen9_decoupled_mmio_access(dev_priv, reg, fw_domain,
+ GEN9_DECOUPLED_OP_WRITE);
+}
+
+
#define GEN2_READ_HEADER(x) \
u##x val = 0; \
assert_rpm_wakelock_held(dev_priv);
@@ -869,26 +953,30 @@ __gen2_read(64)
trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
return val
-static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
- enum forcewake_domains fw_domains)
+static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv,
+ enum forcewake_domains fw_domains)
{
struct intel_uncore_forcewake_domain *domain;
+ for_each_fw_domain_masked(domain, fw_domains, dev_priv)
+ fw_domain_arm_timer(domain);
+
+ dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+ dev_priv->uncore.fw_domains_active |= fw_domains;
+}
+
+static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
+ enum forcewake_domains fw_domains)
+{
if (WARN_ON(!fw_domains))
return;
- /* Ideally GCC would be constant-fold and eliminate this loop */
- for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
- if (domain->wake_count) {
- fw_domains &= ~domain->mask;
- continue;
- }
-
- fw_domain_arm_timer(domain);
- }
+ /* Turn on all requested but inactive supported forcewake domains. */
+ fw_domains &= dev_priv->uncore.fw_domains;
+ fw_domains &= ~dev_priv->uncore.fw_domains_active;
if (fw_domains)
- dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+ ___force_wake_auto(dev_priv, fw_domains);
}
#define __gen6_read(x) \
@@ -903,62 +991,50 @@ gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
GEN6_READ_FOOTER; \
}
-#define __vlv_read(x) \
+#define __fwtable_read(x) \
static u##x \
-vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+fwtable_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_READ_HEADER(x); \
- fw_engine = __vlv_reg_read_fw_domains(offset); \
+ fw_engine = __fwtable_reg_read_fw_domains(offset); \
if (fw_engine) \
__force_wake_auto(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
-#define __chv_read(x) \
+#define __gen9_decoupled_read(x) \
static u##x \
-chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+gen9_decoupled_read##x(struct drm_i915_private *dev_priv, \
+ i915_reg_t reg, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_READ_HEADER(x); \
- fw_engine = __chv_reg_read_fw_domains(offset); \
- if (fw_engine) \
- __force_wake_auto(dev_priv, fw_engine); \
- val = __raw_i915_read##x(dev_priv, reg); \
- GEN6_READ_FOOTER; \
-}
-
-#define __gen9_read(x) \
-static u##x \
-gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
- enum forcewake_domains fw_engine; \
- GEN6_READ_HEADER(x); \
- fw_engine = __gen9_reg_read_fw_domains(offset); \
- if (fw_engine) \
- __force_wake_auto(dev_priv, fw_engine); \
- val = __raw_i915_read##x(dev_priv, reg); \
+ fw_engine = __fwtable_reg_read_fw_domains(offset); \
+ if (fw_engine & ~dev_priv->uncore.fw_domains_active) { \
+ unsigned i; \
+ u32 *ptr_data = (u32 *) &val; \
+ for (i = 0; i < x/32; i++, offset += sizeof(u32), ptr_data++) \
+ *ptr_data = __gen9_decoupled_mmio_read32(dev_priv, \
+ offset, \
+ fw_engine); \
+ } else { \
+ val = __raw_i915_read##x(dev_priv, reg); \
+ } \
GEN6_READ_FOOTER; \
}
-__gen9_read(8)
-__gen9_read(16)
-__gen9_read(32)
-__gen9_read(64)
-__chv_read(8)
-__chv_read(16)
-__chv_read(32)
-__chv_read(64)
-__vlv_read(8)
-__vlv_read(16)
-__vlv_read(32)
-__vlv_read(64)
+__gen9_decoupled_read(32)
+__gen9_decoupled_read(64)
+__fwtable_read(8)
+__fwtable_read(16)
+__fwtable_read(32)
+__fwtable_read(64)
__gen6_read(8)
__gen6_read(16)
__gen6_read(32)
__gen6_read(64)
-#undef __gen9_read
-#undef __chv_read
-#undef __vlv_read
+#undef __fwtable_read
#undef __gen6_read
#undef GEN6_READ_FOOTER
#undef GEN6_READ_HEADER
@@ -1054,21 +1130,6 @@ gen6_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool
GEN6_WRITE_FOOTER; \
}
-#define __hsw_write(x) \
-static void \
-hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
- u32 __fifo_ret = 0; \
- GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE(offset)) { \
- __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
- } \
- __raw_i915_write##x(dev_priv, reg, val); \
- if (unlikely(__fifo_ret)) { \
- gen6_gt_check_fifodbg(dev_priv); \
- } \
- GEN6_WRITE_FOOTER; \
-}
-
#define __gen8_write(x) \
static void \
gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
@@ -1081,51 +1142,49 @@ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool
GEN6_WRITE_FOOTER; \
}
-#define __chv_write(x) \
+#define __fwtable_write(x) \
static void \
-chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
+fwtable_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_WRITE_HEADER; \
- fw_engine = __chv_reg_write_fw_domains(offset); \
+ fw_engine = __fwtable_reg_write_fw_domains(offset); \
if (fw_engine) \
__force_wake_auto(dev_priv, fw_engine); \
__raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
-#define __gen9_write(x) \
+#define __gen9_decoupled_write(x) \
static void \
-gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \
+gen9_decoupled_write##x(struct drm_i915_private *dev_priv, \
+ i915_reg_t reg, u##x val, \
bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_WRITE_HEADER; \
- fw_engine = __gen9_reg_write_fw_domains(offset); \
- if (fw_engine) \
- __force_wake_auto(dev_priv, fw_engine); \
- __raw_i915_write##x(dev_priv, reg, val); \
+ fw_engine = __fwtable_reg_write_fw_domains(offset); \
+ if (fw_engine & ~dev_priv->uncore.fw_domains_active) \
+ __gen9_decoupled_mmio_write(dev_priv, \
+ offset, \
+ val, \
+ fw_engine); \
+ else \
+ __raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
-__gen9_write(8)
-__gen9_write(16)
-__gen9_write(32)
-__chv_write(8)
-__chv_write(16)
-__chv_write(32)
+__gen9_decoupled_write(32)
+__fwtable_write(8)
+__fwtable_write(16)
+__fwtable_write(32)
__gen8_write(8)
__gen8_write(16)
__gen8_write(32)
-__hsw_write(8)
-__hsw_write(16)
-__hsw_write(32)
__gen6_write(8)
__gen6_write(16)
__gen6_write(32)
-#undef __gen9_write
-#undef __chv_write
+#undef __fwtable_write
#undef __gen8_write
-#undef __hsw_write
#undef __gen6_write
#undef GEN6_WRITE_FOOTER
#undef GEN6_WRITE_HEADER
@@ -1314,6 +1373,13 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv)
WARN_ON(dev_priv->uncore.fw_domains == 0);
}
+#define ASSIGN_FW_DOMAINS_TABLE(d) \
+{ \
+ dev_priv->uncore.fw_domains_table = \
+ (struct intel_forcewake_range *)(d); \
+ dev_priv->uncore.fw_domains_table_entries = ARRAY_SIZE((d)); \
+}
+
void intel_uncore_init(struct drm_i915_private *dev_priv)
{
i915_check_vgpu(dev_priv);
@@ -1327,13 +1393,23 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
switch (INTEL_INFO(dev_priv)->gen) {
default:
case 9:
- ASSIGN_WRITE_MMIO_VFUNCS(gen9);
- ASSIGN_READ_MMIO_VFUNCS(gen9);
+ ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(fwtable);
+ if (HAS_DECOUPLED_MMIO(dev_priv)) {
+ dev_priv->uncore.funcs.mmio_readl =
+ gen9_decoupled_read32;
+ dev_priv->uncore.funcs.mmio_readq =
+ gen9_decoupled_read64;
+ dev_priv->uncore.funcs.mmio_writel =
+ gen9_decoupled_write32;
+ }
break;
case 8:
if (IS_CHERRYVIEW(dev_priv)) {
- ASSIGN_WRITE_MMIO_VFUNCS(chv);
- ASSIGN_READ_MMIO_VFUNCS(chv);
+ ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(fwtable);
} else {
ASSIGN_WRITE_MMIO_VFUNCS(gen8);
@@ -1342,14 +1418,11 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
break;
case 7:
case 6:
- if (IS_HASWELL(dev_priv)) {
- ASSIGN_WRITE_MMIO_VFUNCS(hsw);
- } else {
- ASSIGN_WRITE_MMIO_VFUNCS(gen6);
- }
+ ASSIGN_WRITE_MMIO_VFUNCS(gen6);
if (IS_VALLEYVIEW(dev_priv)) {
- ASSIGN_READ_MMIO_VFUNCS(vlv);
+ ASSIGN_FW_DOMAINS_TABLE(__vlv_fw_ranges);
+ ASSIGN_READ_MMIO_VFUNCS(fwtable);
} else {
ASSIGN_READ_MMIO_VFUNCS(gen6);
}
@@ -1366,6 +1439,10 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
break;
}
+ intel_fw_table_check(dev_priv);
+ if (INTEL_GEN(dev_priv) >= 8)
+ intel_shadow_table_check();
+
if (intel_vgpu_active(dev_priv)) {
ASSIGN_WRITE_MMIO_VFUNCS(vgpu);
ASSIGN_READ_MMIO_VFUNCS(vgpu);
@@ -1408,7 +1485,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) &&
- (INTEL_INFO(dev)->gen_mask & entry->gen_bitmask))
+ (INTEL_INFO(dev_priv)->gen_mask & entry->gen_bitmask))
break;
}
@@ -1815,35 +1892,16 @@ static enum forcewake_domains
intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv,
i915_reg_t reg)
{
+ u32 offset = i915_mmio_reg_offset(reg);
enum forcewake_domains fw_domains;
- if (intel_vgpu_active(dev_priv))
- return 0;
-
- switch (INTEL_GEN(dev_priv)) {
- case 9:
- fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg));
- break;
- case 8:
- if (IS_CHERRYVIEW(dev_priv))
- fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
- else
- fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
- break;
- case 7:
- case 6:
- if (IS_VALLEYVIEW(dev_priv))
- fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
- else
- fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
- break;
- default:
- MISSING_CASE(INTEL_INFO(dev_priv)->gen);
- case 5: /* forcewake was introduced with gen6 */
- case 4:
- case 3:
- case 2:
- return 0;
+ if (HAS_FWTABLE(dev_priv)) {
+ fw_domains = __fwtable_reg_read_fw_domains(offset);
+ } else if (INTEL_GEN(dev_priv) >= 6) {
+ fw_domains = __gen6_reg_read_fw_domains(offset);
+ } else {
+ WARN_ON(!IS_GEN(dev_priv, 2, 5));
+ fw_domains = 0;
}
WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
@@ -1855,32 +1913,18 @@ static enum forcewake_domains
intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv,
i915_reg_t reg)
{
+ u32 offset = i915_mmio_reg_offset(reg);
enum forcewake_domains fw_domains;
- if (intel_vgpu_active(dev_priv))
- return 0;
-
- switch (INTEL_GEN(dev_priv)) {
- case 9:
- fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg));
- break;
- case 8:
- if (IS_CHERRYVIEW(dev_priv))
- fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg));
- else
- fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg));
- break;
- case 7:
- case 6:
+ if (HAS_FWTABLE(dev_priv) && !IS_VALLEYVIEW(dev_priv)) {
+ fw_domains = __fwtable_reg_write_fw_domains(offset);
+ } else if (IS_GEN8(dev_priv)) {
+ fw_domains = __gen8_reg_write_fw_domains(offset);
+ } else if (IS_GEN(dev_priv, 6, 7)) {
fw_domains = FORCEWAKE_RENDER;
- break;
- default:
- MISSING_CASE(INTEL_INFO(dev_priv)->gen);
- case 5:
- case 4:
- case 3:
- case 2:
- return 0;
+ } else {
+ WARN_ON(!IS_GEN(dev_priv, 2, 5));
+ fw_domains = 0;
}
WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
@@ -1910,6 +1954,9 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
WARN_ON(!op);
+ if (intel_vgpu_active(dev_priv))
+ return 0;
+
if (op & FW_REG_READ)
fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg);
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 9672b579f950..33404295b447 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -18,7 +18,6 @@
#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/reservation.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@@ -151,38 +150,11 @@ static int imx_drm_atomic_check(struct drm_device *dev,
return ret;
}
-static int imx_drm_atomic_commit(struct drm_device *dev,
- struct drm_atomic_state *state,
- bool nonblock)
-{
- struct drm_plane_state *plane_state;
- struct drm_plane *plane;
- struct dma_buf *dma_buf;
- int i;
-
- /*
- * If the plane fb has an dma-buf attached, fish out the exclusive
- * fence for the atomic helper to wait on.
- */
- for_each_plane_in_state(state, plane, plane_state, i) {
- if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
- dma_buf = drm_fb_cma_get_gem_obj(plane_state->fb,
- 0)->base.dma_buf;
- if (!dma_buf)
- continue;
- plane_state->fence =
- reservation_object_get_excl_rcu(dma_buf->resv);
- }
- }
-
- return drm_atomic_helper_commit(dev, state, nonblock);
-}
-
static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
.fb_create = drm_fb_cma_create,
.output_poll_changed = imx_drm_output_poll_changed,
.atomic_check = imx_drm_atomic_check,
- .atomic_commit = imx_drm_atomic_commit,
+ .atomic_commit = drm_atomic_helper_commit,
};
static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 3ce391c239b0..516d06490465 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -101,12 +101,6 @@ struct imx_ldb {
const struct bus_mux *lvds_mux;
};
-static enum drm_connector_status imx_ldb_connector_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch,
u32 bus_format)
{
@@ -319,18 +313,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
struct imx_ldb *ldb = imx_ldb_ch->ldb;
int mux, ret;
- /*
- * imx_ldb_encoder_disable is called by
- * drm_helper_disable_unused_functions without
- * the encoder being enabled before.
- */
- if (imx_ldb_ch == &ldb->channel[0] &&
- (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0)
- return;
- else if (imx_ldb_ch == &ldb->channel[1] &&
- (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
- return;
-
drm_panel_disable(imx_ldb_ch->panel);
if (imx_ldb_ch == &ldb->channel[0])
@@ -409,7 +391,6 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
static const struct drm_connector_funcs imx_ldb_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = imx_ldb_connector_detect,
.destroy = imx_drm_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index 8fc088843e55..3b602ee33c44 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -227,12 +227,6 @@ static int tve_setup_vga(struct imx_tve *tve)
TVE_TVDAC_TEST_MODE_MASK, 1);
}
-static enum drm_connector_status imx_tve_connector_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static int imx_tve_connector_get_modes(struct drm_connector *connector)
{
struct imx_tve *tve = con_to_tve(connector);
@@ -352,7 +346,6 @@ static int imx_tve_atomic_check(struct drm_encoder *encoder,
static const struct drm_connector_funcs imx_tve_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = imx_tve_connector_detect,
.destroy = imx_drm_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index d5864ed4d772..e74a0ad52950 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -50,6 +50,12 @@ static const uint32_t ipu_plane_formats[] = {
DRM_FORMAT_YVYU,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
+ DRM_FORMAT_YUV422,
+ DRM_FORMAT_YVU422,
+ DRM_FORMAT_YUV444,
+ DRM_FORMAT_YVU444,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV16,
DRM_FORMAT_RGB565,
};
@@ -64,13 +70,14 @@ drm_plane_state_to_eba(struct drm_plane_state *state)
{
struct drm_framebuffer *fb = state->fb;
struct drm_gem_cma_object *cma_obj;
+ int x = state->src_x >> 16;
+ int y = state->src_y >> 16;
cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
BUG_ON(!cma_obj);
- return cma_obj->paddr + fb->offsets[0] +
- fb->pitches[0] * (state->src_y >> 16) +
- (fb->bits_per_pixel >> 3) * (state->src_x >> 16);
+ return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y +
+ drm_format_plane_cpp(fb->pixel_format, 0) * x;
}
static inline unsigned long
@@ -79,13 +86,17 @@ drm_plane_state_to_ubo(struct drm_plane_state *state)
struct drm_framebuffer *fb = state->fb;
struct drm_gem_cma_object *cma_obj;
unsigned long eba = drm_plane_state_to_eba(state);
+ int x = state->src_x >> 16;
+ int y = state->src_y >> 16;
cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
BUG_ON(!cma_obj);
- return cma_obj->paddr + fb->offsets[1] +
- fb->pitches[1] * (state->src_y >> 16) / 2 +
- (state->src_x >> 16) / 2 - eba;
+ x /= drm_format_horz_chroma_subsampling(fb->pixel_format);
+ y /= drm_format_vert_chroma_subsampling(fb->pixel_format);
+
+ return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
+ drm_format_plane_cpp(fb->pixel_format, 1) * x - eba;
}
static inline unsigned long
@@ -94,69 +105,17 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
struct drm_framebuffer *fb = state->fb;
struct drm_gem_cma_object *cma_obj;
unsigned long eba = drm_plane_state_to_eba(state);
+ int x = state->src_x >> 16;
+ int y = state->src_y >> 16;
cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
BUG_ON(!cma_obj);
- return cma_obj->paddr + fb->offsets[2] +
- fb->pitches[2] * (state->src_y >> 16) / 2 +
- (state->src_x >> 16) / 2 - eba;
-}
-
-static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane)
-{
- struct drm_plane *plane = &ipu_plane->base;
- struct drm_plane_state *state = plane->state;
- struct drm_crtc_state *crtc_state = state->crtc->state;
- struct drm_framebuffer *fb = state->fb;
- unsigned long eba, ubo, vbo;
- int active;
-
- eba = drm_plane_state_to_eba(state);
-
- switch (fb->pixel_format) {
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- if (!drm_atomic_crtc_needs_modeset(crtc_state))
- break;
+ x /= drm_format_horz_chroma_subsampling(fb->pixel_format);
+ y /= drm_format_vert_chroma_subsampling(fb->pixel_format);
- /*
- * Multiplanar formats have to meet the following restrictions:
- * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
- * - EBA, UBO and VBO are a multiple of 8
- * - UBO and VBO are unsigned and not larger than 0xfffff8
- * - Only EBA may be changed while scanout is active
- * - The strides of U and V planes must be identical.
- */
- ubo = drm_plane_state_to_ubo(state);
- vbo = drm_plane_state_to_vbo(state);
-
- if (fb->pixel_format == DRM_FORMAT_YUV420)
- ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
- fb->pitches[1], ubo, vbo);
- else
- ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
- fb->pitches[1], vbo, ubo);
-
- dev_dbg(ipu_plane->base.dev->dev,
- "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
- state->src_x >> 16, state->src_y >> 16);
- break;
- default:
- dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
- eba, state->src_x >> 16, state->src_y >> 16);
-
- break;
- }
-
- if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
- active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
- ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
- ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
- } else {
- ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
- ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
- }
+ return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
+ drm_format_plane_cpp(fb->pixel_format, 2) * x - eba;
}
void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
@@ -339,6 +298,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
switch (fb->pixel_format) {
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
/*
* Multiplanar formats have to meet the following restrictions:
* - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
@@ -347,27 +310,34 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
* - Only EBA may be changed while scanout is active
* - The strides of U and V planes must be identical.
*/
- ubo = drm_plane_state_to_ubo(state);
vbo = drm_plane_state_to_vbo(state);
- if ((ubo & 0x7) || (vbo & 0x7))
- return -EINVAL;
-
- if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
+ if (vbo & 0x7 || vbo > 0xfffff8)
return -EINVAL;
- if (old_fb &&
- (old_fb->pixel_format == DRM_FORMAT_YUV420 ||
- old_fb->pixel_format == DRM_FORMAT_YVU420)) {
- old_ubo = drm_plane_state_to_ubo(old_state);
+ if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
old_vbo = drm_plane_state_to_vbo(old_state);
- if (ubo != old_ubo || vbo != old_vbo)
- return -EINVAL;
+ if (vbo != old_vbo)
+ crtc_state->mode_changed = true;
}
if (fb->pitches[1] != fb->pitches[2])
return -EINVAL;
+ /* fall-through */
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV16:
+ ubo = drm_plane_state_to_ubo(state);
+
+ if (ubo & 0x7 || ubo > 0xfffff8)
+ return -EINVAL;
+
+ if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
+ old_ubo = drm_plane_state_to_ubo(old_state);
+ if (ubo != old_ubo)
+ crtc_state->mode_changed = true;
+ }
+
if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
return -EINVAL;
@@ -399,15 +369,19 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
{
struct ipu_plane *ipu_plane = to_ipu_plane(plane);
struct drm_plane_state *state = plane->state;
+ struct drm_crtc_state *crtc_state = state->crtc->state;
+ struct drm_framebuffer *fb = state->fb;
+ unsigned long eba, ubo, vbo;
enum ipu_color_space ics;
+ int active;
- if (old_state->fb) {
- struct drm_crtc_state *crtc_state = state->crtc->state;
+ eba = drm_plane_state_to_eba(state);
- if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
- ipu_plane_atomic_set_base(ipu_plane);
- return;
- }
+ if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
+ active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
+ ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
+ ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
+ return;
}
switch (ipu_plane->dp_flow) {
@@ -451,11 +425,50 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
- ipu_plane_atomic_set_base(ipu_plane);
+ switch (fb->pixel_format) {
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YUV422:
+ case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
+ ubo = drm_plane_state_to_ubo(state);
+ vbo = drm_plane_state_to_vbo(state);
+ if (fb->pixel_format == DRM_FORMAT_YVU420 ||
+ fb->pixel_format == DRM_FORMAT_YVU422 ||
+ fb->pixel_format == DRM_FORMAT_YVU444)
+ swap(ubo, vbo);
+
+ ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+ fb->pitches[1], ubo, vbo);
+
+ dev_dbg(ipu_plane->base.dev->dev,
+ "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
+ state->src_x >> 16, state->src_y >> 16);
+ break;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV16:
+ ubo = drm_plane_state_to_ubo(state);
+
+ ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+ fb->pitches[1], ubo, ubo);
+
+ dev_dbg(ipu_plane->base.dev->dev,
+ "phy = %lu %lu, x = %d, y = %d", eba, ubo,
+ state->src_x >> 16, state->src_y >> 16);
+ break;
+ default:
+ dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
+ eba, state->src_x >> 16, state->src_y >> 16);
+ break;
+ }
+ ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
+ ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
ipu_plane_enable(ipu_plane);
}
static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
+ .prepare_fb = drm_fb_cma_prepare_fb,
.atomic_check = ipu_plane_atomic_check,
.atomic_disable = ipu_plane_atomic_disable,
.atomic_update = ipu_plane_atomic_update,
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index d796ada2a47a..8582a83c0d9b 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -49,12 +49,6 @@ static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e)
return container_of(e, struct imx_parallel_display, encoder);
}
-static enum drm_connector_status imx_pd_connector_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static int imx_pd_connector_get_modes(struct drm_connector *connector)
{
struct imx_parallel_display *imxpd = con_to_imxpd(connector);
@@ -143,7 +137,6 @@ static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
static const struct drm_connector_funcs imx_pd_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = imx_pd_connector_detect,
.destroy = imx_drm_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index cf83f6507ec8..4b7fe7eaec01 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -18,6 +18,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
#include <linux/component.h>
#include <linux/iommu.h>
#include <linux/of_address.h>
@@ -83,7 +84,7 @@ static void mtk_atomic_complete(struct mtk_drm_private *private,
drm_atomic_helper_wait_for_vblanks(drm, state);
drm_atomic_helper_cleanup_planes(drm, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
}
static void mtk_atomic_work(struct work_struct *work)
@@ -110,6 +111,7 @@ static int mtk_atomic_commit(struct drm_device *drm,
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (async)
mtk_atomic_schedule(private, state);
else
@@ -247,16 +249,14 @@ static const struct file_operations mtk_drm_fops = {
.mmap = mtk_drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
};
static struct drm_driver mtk_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
DRIVER_ATOMIC,
- .get_vblank_counter = drm_vblank_count,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = mtk_drm_crtc_enable_vblank,
.disable_vblank = mtk_drm_crtc_disable_vblank,
@@ -415,7 +415,8 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type == MTK_DPI) {
dev_info(dev, "Adding component match for %s\n",
node->full_name);
- component_match_add(dev, &match, compare_of, node);
+ drm_of_component_match_add(dev, &match, compare_of,
+ node);
} else {
struct mtk_ddp_comp *comp;
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index eaa5a2240c0c..2c42f90809d8 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -594,12 +594,6 @@ static void mtk_dsi_encoder_enable(struct drm_encoder *encoder)
mtk_output_dsi_enable(dsi);
}
-static enum drm_connector_status mtk_dsi_connector_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
{
struct mtk_dsi *dsi = connector_to_dsi(connector);
@@ -616,7 +610,6 @@ static const struct drm_encoder_helper_funcs mtk_dsi_encoder_helper_funcs = {
static const struct drm_connector_funcs mtk_dsi_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
- .detect = mtk_dsi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
new file mode 100644
index 000000000000..99719afcc77f
--- /dev/null
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -0,0 +1,9 @@
+config DRM_MESON
+ tristate "DRM Support for Amlogic Meson Display Controller"
+ depends on DRM && OF && (ARM || ARM64)
+ depends on ARCH_MESON || COMPILE_TEST
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
+ select VIDEOMODE_HELPERS
+ select REGMAP_MMIO
diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
new file mode 100644
index 000000000000..2591978b8aad
--- /dev/null
+++ b/drivers/gpu/drm/meson/Makefile
@@ -0,0 +1,4 @@
+meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
+meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
+
+obj-$(CONFIG_DRM_MESON) += meson.o
diff --git a/drivers/gpu/drm/meson/meson_canvas.c b/drivers/gpu/drm/meson/meson_canvas.c
new file mode 100644
index 000000000000..4109e36c297f
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_canvas.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "meson_drv.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+/*
+ * CANVAS is a memory zone where physical memory frames information
+ * are stored for the VIU to scanout.
+ */
+
+/* DMC Registers */
+#define DMC_CAV_LUT_DATAL 0x48 /* 0x12 offset in data sheet */
+#define CANVAS_WIDTH_LBIT 29
+#define CANVAS_WIDTH_LWID 3
+#define DMC_CAV_LUT_DATAH 0x4c /* 0x13 offset in data sheet */
+#define CANVAS_WIDTH_HBIT 0
+#define CANVAS_HEIGHT_BIT 9
+#define CANVAS_BLKMODE_BIT 24
+#define DMC_CAV_LUT_ADDR 0x50 /* 0x14 offset in data sheet */
+#define CANVAS_LUT_WR_EN (0x2 << 8)
+#define CANVAS_LUT_RD_EN (0x1 << 8)
+
+void meson_canvas_setup(struct meson_drm *priv,
+ uint32_t canvas_index, uint32_t addr,
+ uint32_t stride, uint32_t height,
+ unsigned int wrap,
+ unsigned int blkmode)
+{
+ unsigned int val;
+
+ regmap_write(priv->dmc, DMC_CAV_LUT_DATAL,
+ (((addr + 7) >> 3)) |
+ (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT));
+
+ regmap_write(priv->dmc, DMC_CAV_LUT_DATAH,
+ ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) <<
+ CANVAS_WIDTH_HBIT) |
+ (height << CANVAS_HEIGHT_BIT) |
+ (wrap << 22) |
+ (blkmode << CANVAS_BLKMODE_BIT));
+
+ regmap_write(priv->dmc, DMC_CAV_LUT_ADDR,
+ CANVAS_LUT_WR_EN | canvas_index);
+
+ /* Force a read-back to make sure everything is flushed. */
+ regmap_read(priv->dmc, DMC_CAV_LUT_DATAH, &val);
+}
diff --git a/drivers/gpu/drm/meson/meson_canvas.h b/drivers/gpu/drm/meson/meson_canvas.h
new file mode 100644
index 000000000000..af1759da4b27
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_canvas.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Canvas LUT Memory */
+
+#ifndef __MESON_CANVAS_H
+#define __MESON_CANVAS_H
+
+#define MESON_CANVAS_ID_OSD1 0x4e
+
+/* Canvas configuration. */
+#define MESON_CANVAS_WRAP_NONE 0x00
+#define MESON_CANVAS_WRAP_X 0x01
+#define MESON_CANVAS_WRAP_Y 0x02
+
+#define MESON_CANVAS_BLKMODE_LINEAR 0x00
+#define MESON_CANVAS_BLKMODE_32x32 0x01
+#define MESON_CANVAS_BLKMODE_64x64 0x02
+
+void meson_canvas_setup(struct meson_drm *priv,
+ uint32_t canvas_index, uint32_t addr,
+ uint32_t stride, uint32_t height,
+ unsigned int wrap,
+ unsigned int blkmode);
+
+#endif /* __MESON_CANVAS_H */
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
new file mode 100644
index 000000000000..749770e5c65f
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "meson_crtc.h"
+#include "meson_plane.h"
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_registers.h"
+
+/* CRTC definition */
+
+struct meson_crtc {
+ struct drm_crtc base;
+ struct drm_pending_vblank_event *event;
+ struct meson_drm *priv;
+};
+#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
+
+/* CRTC */
+
+static const struct drm_crtc_funcs meson_crtc_funcs = {
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .destroy = drm_crtc_cleanup,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .set_config = drm_atomic_helper_set_config,
+};
+
+static void meson_crtc_enable(struct drm_crtc *crtc)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ struct drm_plane *plane = meson_crtc->priv->primary_plane;
+ struct meson_drm *priv = meson_crtc->priv;
+
+ /* Enable VPP Postblend */
+ writel(plane->state->crtc_w,
+ priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
+
+ writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
+ priv->io_base + _REG(VPP_MISC));
+
+ priv->viu.osd1_enabled = true;
+}
+
+static void meson_crtc_disable(struct drm_crtc *crtc)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ struct meson_drm *priv = meson_crtc->priv;
+
+ priv->viu.osd1_enabled = false;
+
+ /* Disable VPP Postblend */
+ writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ if (crtc->state->event && !crtc->state->active) {
+ spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+
+ crtc->state->event = NULL;
+ }
+}
+
+static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ unsigned long flags;
+
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ meson_crtc->event = crtc->state->event;
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+}
+
+static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ struct meson_drm *priv = meson_crtc->priv;
+
+ if (priv->viu.osd1_enabled)
+ priv->viu.osd1_commit = true;
+}
+
+static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
+ .enable = meson_crtc_enable,
+ .disable = meson_crtc_disable,
+ .atomic_begin = meson_crtc_atomic_begin,
+ .atomic_flush = meson_crtc_atomic_flush,
+};
+
+void meson_crtc_irq(struct meson_drm *priv)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
+ unsigned long flags;
+
+ /* Update the OSD registers */
+ if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
+ writel_relaxed(priv->viu.osd1_ctrl_stat,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
+ writel_relaxed(priv->viu.osd1_blk0_cfg[0],
+ priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
+ writel_relaxed(priv->viu.osd1_blk0_cfg[1],
+ priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
+ writel_relaxed(priv->viu.osd1_blk0_cfg[2],
+ priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
+ writel_relaxed(priv->viu.osd1_blk0_cfg[3],
+ priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
+ writel_relaxed(priv->viu.osd1_blk0_cfg[4],
+ priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
+
+ /* If output is interlace, make use of the Scaler */
+ if (priv->viu.osd1_interlace) {
+ struct drm_plane *plane = priv->primary_plane;
+ struct drm_plane_state *state = plane->state;
+ struct drm_rect dest = {
+ .x1 = state->crtc_x,
+ .y1 = state->crtc_y,
+ .x2 = state->crtc_x + state->crtc_w,
+ .y2 = state->crtc_y + state->crtc_h,
+ };
+
+ meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
+ } else
+ meson_vpp_disable_interlace_vscaler_osd1(priv);
+
+ /* Enable OSD1 */
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
+ priv->io_base + _REG(VPP_MISC));
+
+ priv->viu.osd1_commit = false;
+ }
+
+ drm_crtc_handle_vblank(priv->crtc);
+
+ spin_lock_irqsave(&priv->drm->event_lock, flags);
+ if (meson_crtc->event) {
+ drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
+ drm_crtc_vblank_put(priv->crtc);
+ meson_crtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&priv->drm->event_lock, flags);
+}
+
+int meson_crtc_create(struct meson_drm *priv)
+{
+ struct meson_crtc *meson_crtc;
+ struct drm_crtc *crtc;
+ int ret;
+
+ meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
+ GFP_KERNEL);
+ if (!meson_crtc)
+ return -ENOMEM;
+
+ meson_crtc->priv = priv;
+ crtc = &meson_crtc->base;
+ ret = drm_crtc_init_with_planes(priv->drm, crtc,
+ priv->primary_plane, NULL,
+ &meson_crtc_funcs, "meson_crtc");
+ if (ret) {
+ dev_err(priv->drm->dev, "Failed to init CRTC\n");
+ return ret;
+ }
+
+ drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
+
+ priv->crtc = crtc;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/meson/meson_crtc.h b/drivers/gpu/drm/meson/meson_crtc.h
new file mode 100644
index 000000000000..b62b9e51764d
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_crtc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_CRTC_H
+#define __MESON_CRTC_H
+
+#include "meson_drv.h"
+
+int meson_crtc_create(struct meson_drm *priv);
+
+void meson_crtc_irq(struct meson_drm *priv);
+
+#endif /* __MESON_CRTC_H */
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
new file mode 100644
index 000000000000..ff1f6019b97b
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_fb_helper.h>
+
+#include "meson_drv.h"
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_venc_cvbs.h"
+
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_venc.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+#define DRIVER_NAME "meson"
+#define DRIVER_DESC "Amlogic Meson DRM driver"
+
+/*
+ * Video Processing Unit
+ *
+ * VPU Handles the Global Video Processing, it includes management of the
+ * clocks gates, blocks reset lines and power domains.
+ *
+ * What is missing :
+ * - Full reset of entire video processing HW blocks
+ * - Scaling and setup of the VPU clock
+ * - Bus clock gates
+ * - Powering up video processing HW blocks
+ * - Powering Up HDMI controller and PHY
+ */
+
+static void meson_fb_output_poll_changed(struct drm_device *dev)
+{
+ struct meson_drm *priv = dev->dev_private;
+
+ drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs meson_mode_config_funcs = {
+ .output_poll_changed = meson_fb_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+ .fb_create = drm_fb_cma_create,
+};
+
+static int meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+ struct meson_drm *priv = dev->dev_private;
+
+ meson_venc_enable_vsync(priv);
+
+ return 0;
+}
+
+static void meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+ struct meson_drm *priv = dev->dev_private;
+
+ meson_venc_disable_vsync(priv);
+}
+
+static irqreturn_t meson_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct meson_drm *priv = dev->dev_private;
+
+ (void)readl_relaxed(priv->io_base + _REG(VENC_INTFLAG));
+
+ meson_crtc_irq(priv);
+
+ return IRQ_HANDLED;
+}
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = no_llseek,
+ .mmap = drm_gem_cma_mmap,
+};
+
+static struct drm_driver meson_driver = {
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
+ DRIVER_MODESET | DRIVER_PRIME |
+ DRIVER_ATOMIC,
+
+ /* Vblank */
+ .enable_vblank = meson_enable_vblank,
+ .disable_vblank = meson_disable_vblank,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+
+ /* IRQ */
+ .irq_handler = meson_irq,
+
+ /* PRIME 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,
+
+ /* GEM Ops */
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .gem_free_object_unlocked = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+
+ /* Misc */
+ .fops = &fops,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = "20161109",
+ .major = 1,
+ .minor = 0,
+};
+
+static bool meson_vpu_has_available_connectors(struct device *dev)
+{
+ struct device_node *ep, *remote;
+
+ /* Parses each endpoint and check if remote exists */
+ for_each_endpoint_of_node(dev->of_node, ep) {
+ /* If the endpoint node exists, consider it enabled */
+ remote = of_graph_get_remote_port(ep);
+ if (remote)
+ return true;
+ }
+
+ return false;
+}
+
+static struct regmap_config meson_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x1000,
+};
+
+static int meson_drv_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_drm *priv;
+ struct drm_device *drm;
+ struct resource *res;
+ void __iomem *regs;
+ int ret;
+
+ /* Checks if an output connector is available */
+ if (!meson_vpu_has_available_connectors(dev)) {
+ dev_err(dev, "No output connector available\n");
+ return -ENODEV;
+ }
+
+ drm = drm_dev_alloc(&meson_driver, dev);
+ if (IS_ERR(drm))
+ return PTR_ERR(drm);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto free_drm;
+ }
+ drm->dev_private = priv;
+ priv->drm = drm;
+ priv->dev = dev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu");
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ priv->io_base = regs;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi");
+ /* Simply ioremap since it may be a shared register zone */
+ regs = devm_ioremap(dev, res->start, resource_size(res));
+ if (!regs)
+ return -EADDRNOTAVAIL;
+
+ priv->hhi = devm_regmap_init_mmio(dev, regs,
+ &meson_regmap_config);
+ if (IS_ERR(priv->hhi)) {
+ dev_err(&pdev->dev, "Couldn't create the HHI regmap\n");
+ return PTR_ERR(priv->hhi);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
+ /* Simply ioremap since it may be a shared register zone */
+ regs = devm_ioremap(dev, res->start, resource_size(res));
+ if (!regs)
+ return -EADDRNOTAVAIL;
+
+ priv->dmc = devm_regmap_init_mmio(dev, regs,
+ &meson_regmap_config);
+ if (IS_ERR(priv->dmc)) {
+ dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
+ return PTR_ERR(priv->dmc);
+ }
+
+ priv->vsync_irq = platform_get_irq(pdev, 0);
+
+ drm_vblank_init(drm, 1);
+ drm_mode_config_init(drm);
+
+ /* Encoder Initialization */
+
+ ret = meson_venc_cvbs_create(priv);
+ if (ret)
+ goto free_drm;
+
+ /* Hardware Initialization */
+
+ meson_venc_init(priv);
+ meson_vpp_init(priv);
+ meson_viu_init(priv);
+
+ ret = meson_plane_create(priv);
+ if (ret)
+ goto free_drm;
+
+ ret = meson_crtc_create(priv);
+ if (ret)
+ goto free_drm;
+
+ ret = drm_irq_install(drm, priv->vsync_irq);
+ if (ret)
+ goto free_drm;
+
+ drm_mode_config_reset(drm);
+ drm->mode_config.max_width = 8192;
+ drm->mode_config.max_height = 8192;
+ drm->mode_config.funcs = &meson_mode_config_funcs;
+
+ priv->fbdev = drm_fbdev_cma_init(drm, 32,
+ drm->mode_config.num_crtc,
+ drm->mode_config.num_connector);
+ if (IS_ERR(priv->fbdev)) {
+ ret = PTR_ERR(priv->fbdev);
+ goto free_drm;
+ }
+
+ drm_kms_helper_poll_init(drm);
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto free_drm;
+
+ return 0;
+
+free_drm:
+ drm_dev_unref(drm);
+
+ return ret;
+}
+
+static int meson_drv_remove(struct platform_device *pdev)
+{
+ struct drm_device *drm = dev_get_drvdata(&pdev->dev);
+ struct meson_drm *priv = drm->dev_private;
+
+ drm_dev_unregister(drm);
+ drm_kms_helper_poll_fini(drm);
+ drm_fbdev_cma_fini(priv->fbdev);
+ drm_mode_config_cleanup(drm);
+ drm_vblank_cleanup(drm);
+ drm_dev_unref(drm);
+
+ return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+ { .compatible = "amlogic,meson-gxbb-vpu" },
+ { .compatible = "amlogic,meson-gxl-vpu" },
+ { .compatible = "amlogic,meson-gxm-vpu" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
+static struct platform_driver meson_drm_platform_driver = {
+ .probe = meson_drv_probe,
+ .remove = meson_drv_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .of_match_table = dt_match,
+ },
+};
+
+module_platform_driver(meson_drm_platform_driver);
+
+MODULE_AUTHOR("Jasper St. Pierre <jstpierre@mecheye.net>");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
new file mode 100644
index 000000000000..6195327c51ca
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * 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 __MESON_DRV_H
+#define __MESON_DRV_H
+
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <drm/drmP.h>
+
+struct meson_drm {
+ struct device *dev;
+ void __iomem *io_base;
+ struct regmap *hhi;
+ struct regmap *dmc;
+ int vsync_irq;
+
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ struct drm_fbdev_cma *fbdev;
+ struct drm_plane *primary_plane;
+
+ /* Components Data */
+ struct {
+ bool osd1_enabled;
+ bool osd1_interlace;
+ bool osd1_commit;
+ uint32_t osd1_ctrl_stat;
+ uint32_t osd1_blk0_cfg[5];
+ } viu;
+
+ struct {
+ unsigned int current_mode;
+ } venc;
+};
+
+static inline int meson_vpu_is_compatible(struct meson_drm *priv,
+ const char *compat)
+{
+ return of_device_is_compatible(priv->dev->of_node, compat);
+}
+
+#endif /* __MESON_DRV_H */
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
new file mode 100644
index 000000000000..4942ca090b46
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+
+#include "meson_plane.h"
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+struct meson_plane {
+ struct drm_plane base;
+ struct meson_drm *priv;
+};
+#define to_meson_plane(x) container_of(x, struct meson_plane, base)
+
+static int meson_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_rect clip = { 0, };
+
+ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ clip.x2 = crtc_state->mode.hdisplay;
+ clip.y2 = crtc_state->mode.vdisplay;
+
+ return drm_plane_helper_check_state(state, &clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+}
+
+/* Takes a fixed 16.16 number and converts it to integer. */
+static inline int64_t fixed16_to_int(int64_t value)
+{
+ return value >> 16;
+}
+
+static void meson_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct meson_plane *meson_plane = to_meson_plane(plane);
+ struct drm_plane_state *state = plane->state;
+ struct drm_framebuffer *fb = state->fb;
+ struct meson_drm *priv = meson_plane->priv;
+ struct drm_gem_cma_object *gem;
+ struct drm_rect src = {
+ .x1 = (state->src_x),
+ .y1 = (state->src_y),
+ .x2 = (state->src_x + state->src_w),
+ .y2 = (state->src_y + state->src_h),
+ };
+ struct drm_rect dest = {
+ .x1 = state->crtc_x,
+ .y1 = state->crtc_y,
+ .x2 = state->crtc_x + state->crtc_w,
+ .y2 = state->crtc_y + state->crtc_h,
+ };
+ unsigned long flags;
+
+ /*
+ * Update Coordinates
+ * Update Formats
+ * Update Buffer
+ * Enable Plane
+ */
+ spin_lock_irqsave(&priv->drm->event_lock, flags);
+
+ /* Enable OSD and BLK0, set max global alpha */
+ priv->viu.osd1_ctrl_stat = OSD_ENABLE |
+ (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
+ OSD_BLK0_ENABLE;
+
+ /* Set up BLK0 to point to the right canvas */
+ priv->viu.osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) |
+ OSD_ENDIANNESS_LE);
+
+ /* On GXBB, Use the old non-HDR RGB2YUV converter */
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+ priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
+
+ switch (fb->pixel_format) {
+ case DRM_FORMAT_XRGB8888:
+ /* For XRGB, replace the pixel's alpha by 0xFF */
+ writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+ priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
+ OSD_COLOR_MATRIX_32_ARGB;
+ break;
+ case DRM_FORMAT_ARGB8888:
+ /* For ARGB, use the pixel's alpha */
+ writel_bits_relaxed(OSD_REPLACE_EN, 0,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+ priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
+ OSD_COLOR_MATRIX_32_ARGB;
+ break;
+ case DRM_FORMAT_RGB888:
+ priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
+ OSD_COLOR_MATRIX_24_RGB;
+ break;
+ case DRM_FORMAT_RGB565:
+ priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
+ OSD_COLOR_MATRIX_16_RGB565;
+ break;
+ };
+
+ if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
+ priv->viu.osd1_interlace = true;
+
+ dest.y1 /= 2;
+ dest.y2 /= 2;
+ } else
+ priv->viu.osd1_interlace = false;
+
+ /*
+ * The format of these registers is (x2 << 16 | x1),
+ * where x2 is exclusive.
+ * e.g. +30x1920 would be (1919 << 16) | 30
+ */
+ priv->viu.osd1_blk0_cfg[1] = ((fixed16_to_int(src.x2) - 1) << 16) |
+ fixed16_to_int(src.x1);
+ priv->viu.osd1_blk0_cfg[2] = ((fixed16_to_int(src.y2) - 1) << 16) |
+ fixed16_to_int(src.y1);
+ priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
+ priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
+
+ /* Update Canvas with buffer address */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+ meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
+ gem->paddr, fb->pitches[0],
+ fb->height, MESON_CANVAS_WRAP_NONE,
+ MESON_CANVAS_BLKMODE_LINEAR);
+
+ spin_unlock_irqrestore(&priv->drm->event_lock, flags);
+}
+
+static void meson_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct meson_plane *meson_plane = to_meson_plane(plane);
+ struct meson_drm *priv = meson_plane->priv;
+
+ /* Disable OSD1 */
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+}
+
+static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
+ .atomic_check = meson_plane_atomic_check,
+ .atomic_disable = meson_plane_atomic_disable,
+ .atomic_update = meson_plane_atomic_update,
+};
+
+static const struct drm_plane_funcs meson_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const uint32_t supported_drm_formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
+};
+
+int meson_plane_create(struct meson_drm *priv)
+{
+ struct meson_plane *meson_plane;
+ struct drm_plane *plane;
+
+ meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
+ GFP_KERNEL);
+ if (!meson_plane)
+ return -ENOMEM;
+
+ meson_plane->priv = priv;
+ plane = &meson_plane->base;
+
+ drm_universal_plane_init(priv->drm, plane, 0xFF,
+ &meson_plane_funcs,
+ supported_drm_formats,
+ ARRAY_SIZE(supported_drm_formats),
+ DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
+
+ drm_plane_helper_add(plane, &meson_plane_helper_funcs);
+
+ priv->primary_plane = plane;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/meson/meson_plane.h b/drivers/gpu/drm/meson/meson_plane.h
new file mode 100644
index 000000000000..e26b8b0aa1fa
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_plane.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_PLANE_H
+#define __MESON_PLANE_H
+
+#include "meson_drv.h"
+
+int meson_plane_create(struct meson_drm *priv);
+
+#endif /* __MESON_PLANE_H */
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
new file mode 100644
index 000000000000..6adf9c13fafa
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -0,0 +1,1395 @@
+/*
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_REGISTERS_H
+#define __MESON_REGISTERS_H
+
+/* Shift all registers by 2 */
+#define _REG(reg) ((reg) << 2)
+
+#define writel_bits_relaxed(mask, val, addr) \
+ writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
+
+/* vpp2 */
+#define VPP2_DUMMY_DATA 0x1900
+#define VPP2_LINE_IN_LENGTH 0x1901
+#define VPP2_PIC_IN_HEIGHT 0x1902
+#define VPP2_SCALE_COEF_IDX 0x1903
+#define VPP2_SCALE_COEF 0x1904
+#define VPP2_VSC_REGION12_STARTP 0x1905
+#define VPP2_VSC_REGION34_STARTP 0x1906
+#define VPP2_VSC_REGION4_ENDP 0x1907
+#define VPP2_VSC_START_PHASE_STEP 0x1908
+#define VPP2_VSC_REGION0_PHASE_SLOPE 0x1909
+#define VPP2_VSC_REGION1_PHASE_SLOPE 0x190a
+#define VPP2_VSC_REGION3_PHASE_SLOPE 0x190b
+#define VPP2_VSC_REGION4_PHASE_SLOPE 0x190c
+#define VPP2_VSC_PHASE_CTRL 0x190d
+#define VPP2_VSC_INI_PHASE 0x190e
+#define VPP2_HSC_REGION12_STARTP 0x1910
+#define VPP2_HSC_REGION34_STARTP 0x1911
+#define VPP2_HSC_REGION4_ENDP 0x1912
+#define VPP2_HSC_START_PHASE_STEP 0x1913
+#define VPP2_HSC_REGION0_PHASE_SLOPE 0x1914
+#define VPP2_HSC_REGION1_PHASE_SLOPE 0x1915
+#define VPP2_HSC_REGION3_PHASE_SLOPE 0x1916
+#define VPP2_HSC_REGION4_PHASE_SLOPE 0x1917
+#define VPP2_HSC_PHASE_CTRL 0x1918
+#define VPP2_SC_MISC 0x1919
+#define VPP2_PREBLEND_VD1_H_START_END 0x191a
+#define VPP2_PREBLEND_VD1_V_START_END 0x191b
+#define VPP2_POSTBLEND_VD1_H_START_END 0x191c
+#define VPP2_POSTBLEND_VD1_V_START_END 0x191d
+#define VPP2_PREBLEND_H_SIZE 0x1920
+#define VPP2_POSTBLEND_H_SIZE 0x1921
+#define VPP2_HOLD_LINES 0x1922
+#define VPP2_BLEND_ONECOLOR_CTRL 0x1923
+#define VPP2_PREBLEND_CURRENT_XY 0x1924
+#define VPP2_POSTBLEND_CURRENT_XY 0x1925
+#define VPP2_MISC 0x1926
+#define VPP2_OFIFO_SIZE 0x1927
+#define VPP2_FIFO_STATUS 0x1928
+#define VPP2_SMOKE_CTRL 0x1929
+#define VPP2_SMOKE1_VAL 0x192a
+#define VPP2_SMOKE2_VAL 0x192b
+#define VPP2_SMOKE1_H_START_END 0x192d
+#define VPP2_SMOKE1_V_START_END 0x192e
+#define VPP2_SMOKE2_H_START_END 0x192f
+#define VPP2_SMOKE2_V_START_END 0x1930
+#define VPP2_SCO_FIFO_CTRL 0x1933
+#define VPP2_HSC_PHASE_CTRL1 0x1934
+#define VPP2_HSC_INI_PAT_CTRL 0x1935
+#define VPP2_VADJ_CTRL 0x1940
+#define VPP2_VADJ1_Y 0x1941
+#define VPP2_VADJ1_MA_MB 0x1942
+#define VPP2_VADJ1_MC_MD 0x1943
+#define VPP2_VADJ2_Y 0x1944
+#define VPP2_VADJ2_MA_MB 0x1945
+#define VPP2_VADJ2_MC_MD 0x1946
+#define VPP2_MATRIX_PROBE_COLOR 0x195c
+#define VPP2_MATRIX_HL_COLOR 0x195d
+#define VPP2_MATRIX_PROBE_POS 0x195e
+#define VPP2_MATRIX_CTRL 0x195f
+#define VPP2_MATRIX_COEF00_01 0x1960
+#define VPP2_MATRIX_COEF02_10 0x1961
+#define VPP2_MATRIX_COEF11_12 0x1962
+#define VPP2_MATRIX_COEF20_21 0x1963
+#define VPP2_MATRIX_COEF22 0x1964
+#define VPP2_MATRIX_OFFSET0_1 0x1965
+#define VPP2_MATRIX_OFFSET2 0x1966
+#define VPP2_MATRIX_PRE_OFFSET0_1 0x1967
+#define VPP2_MATRIX_PRE_OFFSET2 0x1968
+#define VPP2_DUMMY_DATA1 0x1969
+#define VPP2_GAINOFF_CTRL0 0x196a
+#define VPP2_GAINOFF_CTRL1 0x196b
+#define VPP2_GAINOFF_CTRL2 0x196c
+#define VPP2_GAINOFF_CTRL3 0x196d
+#define VPP2_GAINOFF_CTRL4 0x196e
+#define VPP2_CHROMA_ADDR_PORT 0x1970
+#define VPP2_CHROMA_DATA_PORT 0x1971
+#define VPP2_GCLK_CTRL0 0x1972
+#define VPP2_GCLK_CTRL1 0x1973
+#define VPP2_SC_GCLK_CTRL 0x1974
+#define VPP2_MISC1 0x1976
+#define VPP2_DNLP_CTRL_00 0x1981
+#define VPP2_DNLP_CTRL_01 0x1982
+#define VPP2_DNLP_CTRL_02 0x1983
+#define VPP2_DNLP_CTRL_03 0x1984
+#define VPP2_DNLP_CTRL_04 0x1985
+#define VPP2_DNLP_CTRL_05 0x1986
+#define VPP2_DNLP_CTRL_06 0x1987
+#define VPP2_DNLP_CTRL_07 0x1988
+#define VPP2_DNLP_CTRL_08 0x1989
+#define VPP2_DNLP_CTRL_09 0x198a
+#define VPP2_DNLP_CTRL_10 0x198b
+#define VPP2_DNLP_CTRL_11 0x198c
+#define VPP2_DNLP_CTRL_12 0x198d
+#define VPP2_DNLP_CTRL_13 0x198e
+#define VPP2_DNLP_CTRL_14 0x198f
+#define VPP2_DNLP_CTRL_15 0x1990
+#define VPP2_VE_ENABLE_CTRL 0x19a1
+#define VPP2_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x19a2
+#define VPP2_VE_DEMO_CENTER_BAR 0x19a3
+#define VPP2_VE_H_V_SIZE 0x19a4
+#define VPP2_VDO_MEAS_CTRL 0x19a8
+#define VPP2_VDO_MEAS_VS_COUNT_HI 0x19a9
+#define VPP2_VDO_MEAS_VS_COUNT_LO 0x19aa
+#define VPP2_OSD_VSC_PHASE_STEP 0x19c0
+#define VPP2_OSD_VSC_INI_PHASE 0x19c1
+#define VPP2_OSD_VSC_CTRL0 0x19c2
+#define VPP2_OSD_HSC_PHASE_STEP 0x19c3
+#define VPP2_OSD_HSC_INI_PHASE 0x19c4
+#define VPP2_OSD_HSC_CTRL0 0x19c5
+#define VPP2_OSD_HSC_INI_PAT_CTRL 0x19c6
+#define VPP2_OSD_SC_DUMMY_DATA 0x19c7
+#define VPP2_OSD_SC_CTRL0 0x19c8
+#define VPP2_OSD_SCI_WH_M1 0x19c9
+#define VPP2_OSD_SCO_H_START_END 0x19ca
+#define VPP2_OSD_SCO_V_START_END 0x19cb
+#define VPP2_OSD_SCALE_COEF_IDX 0x19cc
+#define VPP2_OSD_SCALE_COEF 0x19cd
+#define VPP2_INT_LINE_NUM 0x19ce
+
+/* viu */
+#define VIU_ADDR_START 0x1a00
+#define VIU_ADDR_END 0x1aff
+#define VIU_SW_RESET 0x1a01
+#define VIU_MISC_CTRL0 0x1a06
+#define VIU_MISC_CTRL1 0x1a07
+#define D2D3_INTF_LENGTH 0x1a08
+#define D2D3_INTF_CTRL0 0x1a09
+#define VIU_OSD1_CTRL_STAT 0x1a10
+#define VIU_OSD1_CTRL_STAT2 0x1a2d
+#define VIU_OSD1_COLOR_ADDR 0x1a11
+#define VIU_OSD1_COLOR 0x1a12
+#define VIU_OSD1_TCOLOR_AG0 0x1a17
+#define VIU_OSD1_TCOLOR_AG1 0x1a18
+#define VIU_OSD1_TCOLOR_AG2 0x1a19
+#define VIU_OSD1_TCOLOR_AG3 0x1a1a
+#define VIU_OSD1_BLK0_CFG_W0 0x1a1b
+#define VIU_OSD1_BLK1_CFG_W0 0x1a1f
+#define VIU_OSD1_BLK2_CFG_W0 0x1a23
+#define VIU_OSD1_BLK3_CFG_W0 0x1a27
+#define VIU_OSD1_BLK0_CFG_W1 0x1a1c
+#define VIU_OSD1_BLK1_CFG_W1 0x1a20
+#define VIU_OSD1_BLK2_CFG_W1 0x1a24
+#define VIU_OSD1_BLK3_CFG_W1 0x1a28
+#define VIU_OSD1_BLK0_CFG_W2 0x1a1d
+#define VIU_OSD1_BLK1_CFG_W2 0x1a21
+#define VIU_OSD1_BLK2_CFG_W2 0x1a25
+#define VIU_OSD1_BLK3_CFG_W2 0x1a29
+#define VIU_OSD1_BLK0_CFG_W3 0x1a1e
+#define VIU_OSD1_BLK1_CFG_W3 0x1a22
+#define VIU_OSD1_BLK2_CFG_W3 0x1a26
+#define VIU_OSD1_BLK3_CFG_W3 0x1a2a
+#define VIU_OSD1_BLK0_CFG_W4 0x1a13
+#define VIU_OSD1_BLK1_CFG_W4 0x1a14
+#define VIU_OSD1_BLK2_CFG_W4 0x1a15
+#define VIU_OSD1_BLK3_CFG_W4 0x1a16
+#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b
+#define VIU_OSD1_TEST_RDDATA 0x1a2c
+#define VIU_OSD1_PROT_CTRL 0x1a2e
+#define VIU_OSD2_CTRL_STAT 0x1a30
+#define VIU_OSD2_CTRL_STAT2 0x1a4d
+#define VIU_OSD2_COLOR_ADDR 0x1a31
+#define VIU_OSD2_COLOR 0x1a32
+#define VIU_OSD2_HL1_H_START_END 0x1a33
+#define VIU_OSD2_HL1_V_START_END 0x1a34
+#define VIU_OSD2_HL2_H_START_END 0x1a35
+#define VIU_OSD2_HL2_V_START_END 0x1a36
+#define VIU_OSD2_TCOLOR_AG0 0x1a37
+#define VIU_OSD2_TCOLOR_AG1 0x1a38
+#define VIU_OSD2_TCOLOR_AG2 0x1a39
+#define VIU_OSD2_TCOLOR_AG3 0x1a3a
+#define VIU_OSD2_BLK0_CFG_W0 0x1a3b
+#define VIU_OSD2_BLK1_CFG_W0 0x1a3f
+#define VIU_OSD2_BLK2_CFG_W0 0x1a43
+#define VIU_OSD2_BLK3_CFG_W0 0x1a47
+#define VIU_OSD2_BLK0_CFG_W1 0x1a3c
+#define VIU_OSD2_BLK1_CFG_W1 0x1a40
+#define VIU_OSD2_BLK2_CFG_W1 0x1a44
+#define VIU_OSD2_BLK3_CFG_W1 0x1a48
+#define VIU_OSD2_BLK0_CFG_W2 0x1a3d
+#define VIU_OSD2_BLK1_CFG_W2 0x1a41
+#define VIU_OSD2_BLK2_CFG_W2 0x1a45
+#define VIU_OSD2_BLK3_CFG_W2 0x1a49
+#define VIU_OSD2_BLK0_CFG_W3 0x1a3e
+#define VIU_OSD2_BLK1_CFG_W3 0x1a42
+#define VIU_OSD2_BLK2_CFG_W3 0x1a46
+#define VIU_OSD2_BLK3_CFG_W3 0x1a4a
+#define VIU_OSD2_BLK0_CFG_W4 0x1a64
+#define VIU_OSD2_BLK1_CFG_W4 0x1a65
+#define VIU_OSD2_BLK2_CFG_W4 0x1a66
+#define VIU_OSD2_BLK3_CFG_W4 0x1a67
+#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
+#define VIU_OSD2_TEST_RDDATA 0x1a4c
+#define VIU_OSD2_PROT_CTRL 0x1a4e
+
+#define VD1_IF0_GEN_REG 0x1a50
+#define VD1_IF0_CANVAS0 0x1a51
+#define VD1_IF0_CANVAS1 0x1a52
+#define VD1_IF0_LUMA_X0 0x1a53
+#define VD1_IF0_LUMA_Y0 0x1a54
+#define VD1_IF0_CHROMA_X0 0x1a55
+#define VD1_IF0_CHROMA_Y0 0x1a56
+#define VD1_IF0_LUMA_X1 0x1a57
+#define VD1_IF0_LUMA_Y1 0x1a58
+#define VD1_IF0_CHROMA_X1 0x1a59
+#define VD1_IF0_CHROMA_Y1 0x1a5a
+#define VD1_IF0_RPT_LOOP 0x1a5b
+#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c
+#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d
+#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e
+#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f
+#define VD1_IF0_LUMA_PSEL 0x1a60
+#define VD1_IF0_CHROMA_PSEL 0x1a61
+#define VD1_IF0_DUMMY_PIXEL 0x1a62
+#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63
+#define VD1_IF0_RANGE_MAP_Y 0x1a6a
+#define VD1_IF0_RANGE_MAP_CB 0x1a6b
+#define VD1_IF0_RANGE_MAP_CR 0x1a6c
+#define VD1_IF0_GEN_REG2 0x1a6d
+#define VD1_IF0_PROT_CNTL 0x1a6e
+#define VIU_VD1_FMT_CTRL 0x1a68
+#define VIU_VD1_FMT_W 0x1a69
+#define VD2_IF0_GEN_REG 0x1a70
+#define VD2_IF0_CANVAS0 0x1a71
+#define VD2_IF0_CANVAS1 0x1a72
+#define VD2_IF0_LUMA_X0 0x1a73
+#define VD2_IF0_LUMA_Y0 0x1a74
+#define VD2_IF0_CHROMA_X0 0x1a75
+#define VD2_IF0_CHROMA_Y0 0x1a76
+#define VD2_IF0_LUMA_X1 0x1a77
+#define VD2_IF0_LUMA_Y1 0x1a78
+#define VD2_IF0_CHROMA_X1 0x1a79
+#define VD2_IF0_CHROMA_Y1 0x1a7a
+#define VD2_IF0_RPT_LOOP 0x1a7b
+#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c
+#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d
+#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e
+#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f
+#define VD2_IF0_LUMA_PSEL 0x1a80
+#define VD2_IF0_CHROMA_PSEL 0x1a81
+#define VD2_IF0_DUMMY_PIXEL 0x1a82
+#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83
+#define VD2_IF0_RANGE_MAP_Y 0x1a8a
+#define VD2_IF0_RANGE_MAP_CB 0x1a8b
+#define VD2_IF0_RANGE_MAP_CR 0x1a8c
+#define VD2_IF0_GEN_REG2 0x1a8d
+#define VD2_IF0_PROT_CNTL 0x1a8e
+#define VIU_VD2_FMT_CTRL 0x1a88
+#define VIU_VD2_FMT_W 0x1a89
+
+/* VIU Matrix Registers */
+#define VIU_OSD1_MATRIX_CTRL 0x1a90
+#define VIU_OSD1_MATRIX_COEF00_01 0x1a91
+#define VIU_OSD1_MATRIX_COEF02_10 0x1a92
+#define VIU_OSD1_MATRIX_COEF11_12 0x1a93
+#define VIU_OSD1_MATRIX_COEF20_21 0x1a94
+#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95
+#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96
+#define VIU_OSD1_MATRIX_OFFSET2 0x1a97
+#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98
+#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99
+#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d
+#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
+#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
+#define VIU_OSD1_EOTF_CTL 0x1ad4
+#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
+#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
+#define VIU_OSD1_EOTF_COEF11_12 0x1ad7
+#define VIU_OSD1_EOTF_COEF20_21 0x1ad8
+#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9
+#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada
+#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb
+#define VIU_OSD1_OETF_CTL 0x1adc
+#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
+#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
+
+/* vpp */
+#define VPP_DUMMY_DATA 0x1d00
+#define VPP_LINE_IN_LENGTH 0x1d01
+#define VPP_PIC_IN_HEIGHT 0x1d02
+#define VPP_SCALE_COEF_IDX 0x1d03
+#define VPP_SCALE_COEF 0x1d04
+#define VPP_VSC_REGION12_STARTP 0x1d05
+#define VPP_VSC_REGION34_STARTP 0x1d06
+#define VPP_VSC_REGION4_ENDP 0x1d07
+#define VPP_VSC_START_PHASE_STEP 0x1d08
+#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09
+#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a
+#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b
+#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c
+#define VPP_VSC_PHASE_CTRL 0x1d0d
+#define VPP_VSC_INI_PHASE 0x1d0e
+#define VPP_HSC_REGION12_STARTP 0x1d10
+#define VPP_HSC_REGION34_STARTP 0x1d11
+#define VPP_HSC_REGION4_ENDP 0x1d12
+#define VPP_HSC_START_PHASE_STEP 0x1d13
+#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14
+#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15
+#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16
+#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
+#define VPP_HSC_PHASE_CTRL 0x1d18
+#define VPP_SC_MISC 0x1d19
+#define VPP_PREBLEND_VD1_H_START_END 0x1d1a
+#define VPP_PREBLEND_VD1_V_START_END 0x1d1b
+#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
+#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d
+#define VPP_BLEND_VD2_H_START_END 0x1d1e
+#define VPP_BLEND_VD2_V_START_END 0x1d1f
+#define VPP_PREBLEND_H_SIZE 0x1d20
+#define VPP_POSTBLEND_H_SIZE 0x1d21
+#define VPP_HOLD_LINES 0x1d22
+#define VPP_BLEND_ONECOLOR_CTRL 0x1d23
+#define VPP_PREBLEND_CURRENT_XY 0x1d24
+#define VPP_POSTBLEND_CURRENT_XY 0x1d25
+#define VPP_MISC 0x1d26
+#define VPP_PREBLEND_ENABLE BIT(6)
+#define VPP_POSTBLEND_ENABLE BIT(7)
+#define VPP_OSD2_ALPHA_PREMULT BIT(8)
+#define VPP_OSD1_ALPHA_PREMULT BIT(9)
+#define VPP_VD1_POSTBLEND BIT(10)
+#define VPP_VD2_POSTBLEND BIT(11)
+#define VPP_OSD1_POSTBLEND BIT(12)
+#define VPP_OSD2_POSTBLEND BIT(13)
+#define VPP_VD1_PREBLEND BIT(14)
+#define VPP_VD2_PREBLEND BIT(15)
+#define VPP_OSD1_PREBLEND BIT(16)
+#define VPP_OSD2_PREBLEND BIT(17)
+#define VPP_OFIFO_SIZE 0x1d27
+#define VPP_FIFO_STATUS 0x1d28
+#define VPP_SMOKE_CTRL 0x1d29
+#define VPP_SMOKE1_VAL 0x1d2a
+#define VPP_SMOKE2_VAL 0x1d2b
+#define VPP_SMOKE3_VAL 0x1d2c
+#define VPP_SMOKE1_H_START_END 0x1d2d
+#define VPP_SMOKE1_V_START_END 0x1d2e
+#define VPP_SMOKE2_H_START_END 0x1d2f
+#define VPP_SMOKE2_V_START_END 0x1d30
+#define VPP_SMOKE3_H_START_END 0x1d31
+#define VPP_SMOKE3_V_START_END 0x1d32
+#define VPP_SCO_FIFO_CTRL 0x1d33
+#define VPP_HSC_PHASE_CTRL1 0x1d34
+#define VPP_HSC_INI_PAT_CTRL 0x1d35
+#define VPP_VADJ_CTRL 0x1d40
+#define VPP_VADJ1_Y 0x1d41
+#define VPP_VADJ1_MA_MB 0x1d42
+#define VPP_VADJ1_MC_MD 0x1d43
+#define VPP_VADJ2_Y 0x1d44
+#define VPP_VADJ2_MA_MB 0x1d45
+#define VPP_VADJ2_MC_MD 0x1d46
+#define VPP_HSHARP_CTRL 0x1d50
+#define VPP_HSHARP_LUMA_THRESH01 0x1d51
+#define VPP_HSHARP_LUMA_THRESH23 0x1d52
+#define VPP_HSHARP_CHROMA_THRESH01 0x1d53
+#define VPP_HSHARP_CHROMA_THRESH23 0x1d54
+#define VPP_HSHARP_LUMA_GAIN 0x1d55
+#define VPP_HSHARP_CHROMA_GAIN 0x1d56
+#define VPP_MATRIX_PROBE_COLOR 0x1d5c
+#define VPP_MATRIX_HL_COLOR 0x1d5d
+#define VPP_MATRIX_PROBE_POS 0x1d5e
+#define VPP_MATRIX_CTRL 0x1d5f
+#define VPP_MATRIX_COEF00_01 0x1d60
+#define VPP_MATRIX_COEF02_10 0x1d61
+#define VPP_MATRIX_COEF11_12 0x1d62
+#define VPP_MATRIX_COEF20_21 0x1d63
+#define VPP_MATRIX_COEF22 0x1d64
+#define VPP_MATRIX_OFFSET0_1 0x1d65
+#define VPP_MATRIX_OFFSET2 0x1d66
+#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67
+#define VPP_MATRIX_PRE_OFFSET2 0x1d68
+#define VPP_DUMMY_DATA1 0x1d69
+#define VPP_GAINOFF_CTRL0 0x1d6a
+#define VPP_GAINOFF_CTRL1 0x1d6b
+#define VPP_GAINOFF_CTRL2 0x1d6c
+#define VPP_GAINOFF_CTRL3 0x1d6d
+#define VPP_GAINOFF_CTRL4 0x1d6e
+#define VPP_CHROMA_ADDR_PORT 0x1d70
+#define VPP_CHROMA_DATA_PORT 0x1d71
+#define VPP_GCLK_CTRL0 0x1d72
+#define VPP_GCLK_CTRL1 0x1d73
+#define VPP_SC_GCLK_CTRL 0x1d74
+#define VPP_MISC1 0x1d76
+#define VPP_BLACKEXT_CTRL 0x1d80
+#define VPP_DNLP_CTRL_00 0x1d81
+#define VPP_DNLP_CTRL_01 0x1d82
+#define VPP_DNLP_CTRL_02 0x1d83
+#define VPP_DNLP_CTRL_03 0x1d84
+#define VPP_DNLP_CTRL_04 0x1d85
+#define VPP_DNLP_CTRL_05 0x1d86
+#define VPP_DNLP_CTRL_06 0x1d87
+#define VPP_DNLP_CTRL_07 0x1d88
+#define VPP_DNLP_CTRL_08 0x1d89
+#define VPP_DNLP_CTRL_09 0x1d8a
+#define VPP_DNLP_CTRL_10 0x1d8b
+#define VPP_DNLP_CTRL_11 0x1d8c
+#define VPP_DNLP_CTRL_12 0x1d8d
+#define VPP_DNLP_CTRL_13 0x1d8e
+#define VPP_DNLP_CTRL_14 0x1d8f
+#define VPP_DNLP_CTRL_15 0x1d90
+#define VPP_PEAKING_HGAIN 0x1d91
+#define VPP_PEAKING_VGAIN 0x1d92
+#define VPP_PEAKING_NLP_1 0x1d93
+#define VPP_DOLBY_CTRL 0x1d93
+#define VPP_PEAKING_NLP_2 0x1d94
+#define VPP_PEAKING_NLP_3 0x1d95
+#define VPP_PEAKING_NLP_4 0x1d96
+#define VPP_PEAKING_NLP_5 0x1d97
+#define VPP_SHARP_LIMIT 0x1d98
+#define VPP_VLTI_CTRL 0x1d99
+#define VPP_HLTI_CTRL 0x1d9a
+#define VPP_CTI_CTRL 0x1d9b
+#define VPP_BLUE_STRETCH_1 0x1d9c
+#define VPP_BLUE_STRETCH_2 0x1d9d
+#define VPP_BLUE_STRETCH_3 0x1d9e
+#define VPP_CCORING_CTRL 0x1da0
+#define VPP_VE_ENABLE_CTRL 0x1da1
+#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2
+#define VPP_VE_DEMO_CENTER_BAR 0x1da3
+#define VPP_VE_H_V_SIZE 0x1da4
+#define VPP_VDO_MEAS_CTRL 0x1da8
+#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9
+#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa
+#define VPP_INPUT_CTRL 0x1dab
+#define VPP_CTI_CTRL2 0x1dac
+#define VPP_PEAKING_SAT_THD1 0x1dad
+#define VPP_PEAKING_SAT_THD2 0x1dae
+#define VPP_PEAKING_SAT_THD3 0x1daf
+#define VPP_PEAKING_SAT_THD4 0x1db0
+#define VPP_PEAKING_SAT_THD5 0x1db1
+#define VPP_PEAKING_SAT_THD6 0x1db2
+#define VPP_PEAKING_SAT_THD7 0x1db3
+#define VPP_PEAKING_SAT_THD8 0x1db4
+#define VPP_PEAKING_SAT_THD9 0x1db5
+#define VPP_PEAKING_GAIN_ADD1 0x1db6
+#define VPP_PEAKING_GAIN_ADD2 0x1db7
+#define VPP_PEAKING_DNLP 0x1db8
+#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9
+#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba
+#define VPP_FRONT_HLTI_CTRL 0x1dbb
+#define VPP_FRONT_CTI_CTRL 0x1dbc
+#define VPP_FRONT_CTI_CTRL2 0x1dbd
+#define VPP_OSD_VSC_PHASE_STEP 0x1dc0
+#define VPP_OSD_VSC_INI_PHASE 0x1dc1
+#define VPP_OSD_VSC_CTRL0 0x1dc2
+#define VPP_OSD_HSC_PHASE_STEP 0x1dc3
+#define VPP_OSD_HSC_INI_PHASE 0x1dc4
+#define VPP_OSD_HSC_CTRL0 0x1dc5
+#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6
+#define VPP_OSD_SC_DUMMY_DATA 0x1dc7
+#define VPP_OSD_SC_CTRL0 0x1dc8
+#define VPP_OSD_SCI_WH_M1 0x1dc9
+#define VPP_OSD_SCO_H_START_END 0x1dca
+#define VPP_OSD_SCO_V_START_END 0x1dcb
+#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
+#define VPP_OSD_SCALE_COEF 0x1dcd
+#define VPP_INT_LINE_NUM 0x1dce
+
+/* viu2 */
+#define VIU2_ADDR_START 0x1e00
+#define VIU2_ADDR_END 0x1eff
+#define VIU2_SW_RESET 0x1e01
+#define VIU2_OSD1_CTRL_STAT 0x1e10
+#define VIU2_OSD1_CTRL_STAT2 0x1e2d
+#define VIU2_OSD1_COLOR_ADDR 0x1e11
+#define VIU2_OSD1_COLOR 0x1e12
+#define VIU2_OSD1_TCOLOR_AG0 0x1e17
+#define VIU2_OSD1_TCOLOR_AG1 0x1e18
+#define VIU2_OSD1_TCOLOR_AG2 0x1e19
+#define VIU2_OSD1_TCOLOR_AG3 0x1e1a
+#define VIU2_OSD1_BLK0_CFG_W0 0x1e1b
+#define VIU2_OSD1_BLK1_CFG_W0 0x1e1f
+#define VIU2_OSD1_BLK2_CFG_W0 0x1e23
+#define VIU2_OSD1_BLK3_CFG_W0 0x1e27
+#define VIU2_OSD1_BLK0_CFG_W1 0x1e1c
+#define VIU2_OSD1_BLK1_CFG_W1 0x1e20
+#define VIU2_OSD1_BLK2_CFG_W1 0x1e24
+#define VIU2_OSD1_BLK3_CFG_W1 0x1e28
+#define VIU2_OSD1_BLK0_CFG_W2 0x1e1d
+#define VIU2_OSD1_BLK1_CFG_W2 0x1e21
+#define VIU2_OSD1_BLK2_CFG_W2 0x1e25
+#define VIU2_OSD1_BLK3_CFG_W2 0x1e29
+#define VIU2_OSD1_BLK0_CFG_W3 0x1e1e
+#define VIU2_OSD1_BLK1_CFG_W3 0x1e22
+#define VIU2_OSD1_BLK2_CFG_W3 0x1e26
+#define VIU2_OSD1_BLK3_CFG_W3 0x1e2a
+#define VIU2_OSD1_BLK0_CFG_W4 0x1e13
+#define VIU2_OSD1_BLK1_CFG_W4 0x1e14
+#define VIU2_OSD1_BLK2_CFG_W4 0x1e15
+#define VIU2_OSD1_BLK3_CFG_W4 0x1e16
+#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e2b
+#define VIU2_OSD1_TEST_RDDATA 0x1e2c
+#define VIU2_OSD1_PROT_CTRL 0x1e2e
+#define VIU2_OSD2_CTRL_STAT 0x1e30
+#define VIU2_OSD2_CTRL_STAT2 0x1e4d
+#define VIU2_OSD2_COLOR_ADDR 0x1e31
+#define VIU2_OSD2_COLOR 0x1e32
+#define VIU2_OSD2_HL1_H_START_END 0x1e33
+#define VIU2_OSD2_HL1_V_START_END 0x1e34
+#define VIU2_OSD2_HL2_H_START_END 0x1e35
+#define VIU2_OSD2_HL2_V_START_END 0x1e36
+#define VIU2_OSD2_TCOLOR_AG0 0x1e37
+#define VIU2_OSD2_TCOLOR_AG1 0x1e38
+#define VIU2_OSD2_TCOLOR_AG2 0x1e39
+#define VIU2_OSD2_TCOLOR_AG3 0x1e3a
+#define VIU2_OSD2_BLK0_CFG_W0 0x1e3b
+#define VIU2_OSD2_BLK1_CFG_W0 0x1e3f
+#define VIU2_OSD2_BLK2_CFG_W0 0x1e43
+#define VIU2_OSD2_BLK3_CFG_W0 0x1e47
+#define VIU2_OSD2_BLK0_CFG_W1 0x1e3c
+#define VIU2_OSD2_BLK1_CFG_W1 0x1e40
+#define VIU2_OSD2_BLK2_CFG_W1 0x1e44
+#define VIU2_OSD2_BLK3_CFG_W1 0x1e48
+#define VIU2_OSD2_BLK0_CFG_W2 0x1e3d
+#define VIU2_OSD2_BLK1_CFG_W2 0x1e41
+#define VIU2_OSD2_BLK2_CFG_W2 0x1e45
+#define VIU2_OSD2_BLK3_CFG_W2 0x1e49
+#define VIU2_OSD2_BLK0_CFG_W3 0x1e3e
+#define VIU2_OSD2_BLK1_CFG_W3 0x1e42
+#define VIU2_OSD2_BLK2_CFG_W3 0x1e46
+#define VIU2_OSD2_BLK3_CFG_W3 0x1e4a
+#define VIU2_OSD2_BLK0_CFG_W4 0x1e64
+#define VIU2_OSD2_BLK1_CFG_W4 0x1e65
+#define VIU2_OSD2_BLK2_CFG_W4 0x1e66
+#define VIU2_OSD2_BLK3_CFG_W4 0x1e67
+#define VIU2_OSD2_FIFO_CTRL_STAT 0x1e4b
+#define VIU2_OSD2_TEST_RDDATA 0x1e4c
+#define VIU2_OSD2_PROT_CTRL 0x1e4e
+#define VIU2_VD1_IF0_GEN_REG 0x1e50
+#define VIU2_VD1_IF0_CANVAS0 0x1e51
+#define VIU2_VD1_IF0_CANVAS1 0x1e52
+#define VIU2_VD1_IF0_LUMA_X0 0x1e53
+#define VIU2_VD1_IF0_LUMA_Y0 0x1e54
+#define VIU2_VD1_IF0_CHROMA_X0 0x1e55
+#define VIU2_VD1_IF0_CHROMA_Y0 0x1e56
+#define VIU2_VD1_IF0_LUMA_X1 0x1e57
+#define VIU2_VD1_IF0_LUMA_Y1 0x1e58
+#define VIU2_VD1_IF0_CHROMA_X1 0x1e59
+#define VIU2_VD1_IF0_CHROMA_Y1 0x1e5a
+#define VIU2_VD1_IF0_RPT_LOOP 0x1e5b
+#define VIU2_VD1_IF0_LUMA0_RPT_PAT 0x1e5c
+#define VIU2_VD1_IF0_CHROMA0_RPT_PAT 0x1e5d
+#define VIU2_VD1_IF0_LUMA1_RPT_PAT 0x1e5e
+#define VIU2_VD1_IF0_CHROMA1_RPT_PAT 0x1e5f
+#define VIU2_VD1_IF0_LUMA_PSEL 0x1e60
+#define VIU2_VD1_IF0_CHROMA_PSEL 0x1e61
+#define VIU2_VD1_IF0_DUMMY_PIXEL 0x1e62
+#define VIU2_VD1_IF0_LUMA_FIFO_SIZE 0x1e63
+#define VIU2_VD1_IF0_RANGE_MAP_Y 0x1e6a
+#define VIU2_VD1_IF0_RANGE_MAP_CB 0x1e6b
+#define VIU2_VD1_IF0_RANGE_MAP_CR 0x1e6c
+#define VIU2_VD1_IF0_GEN_REG2 0x1e6d
+#define VIU2_VD1_IF0_PROT_CNTL 0x1e6e
+#define VIU2_VD1_FMT_CTRL 0x1e68
+#define VIU2_VD1_FMT_W 0x1e69
+
+/* encode */
+#define ENCP_VFIFO2VD_CTL 0x1b58
+#define ENCP_VFIFO2VD_PIXEL_START 0x1b59
+#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a
+#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b
+#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c
+#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d
+#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e
+#define VENC_SYNC_ROUTE 0x1b60
+#define VENC_VIDEO_EXSRC 0x1b61
+#define VENC_DVI_SETTING 0x1b62
+#define VENC_C656_CTRL 0x1b63
+#define VENC_UPSAMPLE_CTRL0 0x1b64
+#define VENC_UPSAMPLE_CTRL1 0x1b65
+#define VENC_UPSAMPLE_CTRL2 0x1b66
+#define TCON_INVERT_CTL 0x1b67
+#define VENC_VIDEO_PROG_MODE 0x1b68
+#define VENC_ENCI_LINE 0x1b69
+#define VENC_ENCI_PIXEL 0x1b6a
+#define VENC_ENCP_LINE 0x1b6b
+#define VENC_ENCP_PIXEL 0x1b6c
+#define VENC_STATA 0x1b6d
+#define VENC_INTCTRL 0x1b6e
+#define VENC_INTFLAG 0x1b6f
+#define VENC_VIDEO_TST_EN 0x1b70
+#define VENC_VIDEO_TST_MDSEL 0x1b71
+#define VENC_VIDEO_TST_Y 0x1b72
+#define VENC_VIDEO_TST_CB 0x1b73
+#define VENC_VIDEO_TST_CR 0x1b74
+#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75
+#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
+#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
+#define VENC_VDAC_DACSEL0 0x1b78
+#define VENC_VDAC_DACSEL1 0x1b79
+#define VENC_VDAC_DACSEL2 0x1b7a
+#define VENC_VDAC_DACSEL3 0x1b7b
+#define VENC_VDAC_DACSEL4 0x1b7c
+#define VENC_VDAC_DACSEL5 0x1b7d
+#define VENC_VDAC_SETTING 0x1b7e
+#define VENC_VDAC_TST_VAL 0x1b7f
+#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0
+#define VENC_VDAC_DAC0_OFFSET 0x1bf1
+#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2
+#define VENC_VDAC_DAC1_OFFSET 0x1bf3
+#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4
+#define VENC_VDAC_DAC2_OFFSET 0x1bf5
+#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6
+#define VENC_VDAC_DAC3_OFFSET 0x1bf7
+#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8
+#define VENC_VDAC_DAC4_OFFSET 0x1bf9
+#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
+#define VENC_VDAC_DAC5_OFFSET 0x1bfb
+#define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define ENCL_TCON_INVERT_CTL 0x1bfd
+#define ENCP_VIDEO_EN 0x1b80
+#define ENCP_VIDEO_SYNC_MODE 0x1b81
+#define ENCP_MACV_EN 0x1b82
+#define ENCP_VIDEO_Y_SCL 0x1b83
+#define ENCP_VIDEO_PB_SCL 0x1b84
+#define ENCP_VIDEO_PR_SCL 0x1b85
+#define ENCP_VIDEO_SYNC_SCL 0x1b86
+#define ENCP_VIDEO_MACV_SCL 0x1b87
+#define ENCP_VIDEO_Y_OFFST 0x1b88
+#define ENCP_VIDEO_PB_OFFST 0x1b89
+#define ENCP_VIDEO_PR_OFFST 0x1b8a
+#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
+#define ENCP_VIDEO_MACV_OFFST 0x1b8c
+#define ENCP_VIDEO_MODE 0x1b8d
+#define ENCP_VIDEO_MODE_ADV 0x1b8e
+#define ENCP_DBG_PX_RST 0x1b90
+#define ENCP_DBG_LN_RST 0x1b91
+#define ENCP_DBG_PX_INT 0x1b92
+#define ENCP_DBG_LN_INT 0x1b93
+#define ENCP_VIDEO_YFP1_HTIME 0x1b94
+#define ENCP_VIDEO_YFP2_HTIME 0x1b95
+#define ENCP_VIDEO_YC_DLY 0x1b96
+#define ENCP_VIDEO_MAX_PXCNT 0x1b97
+#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
+#define ENCP_VIDEO_HSPULS_END 0x1b99
+#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
+#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
+#define ENCP_VIDEO_VSPULS_END 0x1b9c
+#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
+#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
+#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
+#define ENCP_VIDEO_EQPULS_END 0x1ba0
+#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
+#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
+#define ENCP_VIDEO_HAVON_END 0x1ba3
+#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
+#define ENCP_VIDEO_VAVON_ELINE 0x1baf
+#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
+#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
+#define ENCP_VIDEO_HSO_END 0x1ba8
+#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
+#define ENCP_VIDEO_VSO_END 0x1baa
+#define ENCP_VIDEO_VSO_BLINE 0x1bab
+#define ENCP_VIDEO_VSO_ELINE 0x1bac
+#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
+#define ENCP_VIDEO_MAX_LNCNT 0x1bae
+#define ENCP_VIDEO_SY_VAL 0x1bb0
+#define ENCP_VIDEO_SY2_VAL 0x1bb1
+#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
+#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
+#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
+#define ENCP_VIDEO_HOFFST 0x1bb5
+#define ENCP_VIDEO_VOFFST 0x1bb6
+#define ENCP_VIDEO_RGB_CTRL 0x1bb7
+#define ENCP_VIDEO_FILT_CTRL 0x1bb8
+#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
+#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
+#define ENCP_VIDEO_MATRIX_CB 0x1bbb
+#define ENCP_VIDEO_MATRIX_CR 0x1bbc
+#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
+#define ENCP_MACV_BLANKY_VAL 0x1bc0
+#define ENCP_MACV_MAXY_VAL 0x1bc1
+#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2
+#define ENCP_MACV_PSSYNC_STRT 0x1bc3
+#define ENCP_MACV_AGC_STRT 0x1bc4
+#define ENCP_MACV_AGC_END 0x1bc5
+#define ENCP_MACV_WAVE_END 0x1bc6
+#define ENCP_MACV_STRTLINE 0x1bc7
+#define ENCP_MACV_ENDLINE 0x1bc8
+#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9
+#define ENCP_MACV_TS_CNT_MAX_H 0x1bca
+#define ENCP_MACV_TIME_DOWN 0x1bcb
+#define ENCP_MACV_TIME_LO 0x1bcc
+#define ENCP_MACV_TIME_UP 0x1bcd
+#define ENCP_MACV_TIME_RST 0x1bce
+#define ENCP_VBI_CTRL 0x1bd0
+#define ENCP_VBI_SETTING 0x1bd1
+#define ENCP_VBI_BEGIN 0x1bd2
+#define ENCP_VBI_WIDTH 0x1bd3
+#define ENCP_VBI_HVAL 0x1bd4
+#define ENCP_VBI_DATA0 0x1bd5
+#define ENCP_VBI_DATA1 0x1bd6
+#define C656_HS_ST 0x1be0
+#define C656_HS_ED 0x1be1
+#define C656_VS_LNST_E 0x1be2
+#define C656_VS_LNST_O 0x1be3
+#define C656_VS_LNED_E 0x1be4
+#define C656_VS_LNED_O 0x1be5
+#define C656_FS_LNST 0x1be6
+#define C656_FS_LNED 0x1be7
+#define ENCI_VIDEO_MODE 0x1b00
+#define ENCI_VIDEO_MODE_ADV 0x1b01
+#define ENCI_VIDEO_FSC_ADJ 0x1b02
+#define ENCI_VIDEO_BRIGHT 0x1b03
+#define ENCI_VIDEO_CONT 0x1b04
+#define ENCI_VIDEO_SAT 0x1b05
+#define ENCI_VIDEO_HUE 0x1b06
+#define ENCI_VIDEO_SCH 0x1b07
+#define ENCI_SYNC_MODE 0x1b08
+#define ENCI_SYNC_CTRL 0x1b09
+#define ENCI_SYNC_HSO_BEGIN 0x1b0a
+#define ENCI_SYNC_HSO_END 0x1b0b
+#define ENCI_SYNC_VSO_EVN 0x1b0c
+#define ENCI_SYNC_VSO_ODD 0x1b0d
+#define ENCI_SYNC_VSO_EVNLN 0x1b0e
+#define ENCI_SYNC_VSO_ODDLN 0x1b0f
+#define ENCI_SYNC_HOFFST 0x1b10
+#define ENCI_SYNC_VOFFST 0x1b11
+#define ENCI_SYNC_ADJ 0x1b12
+#define ENCI_RGB_SETTING 0x1b13
+#define ENCI_DE_H_BEGIN 0x1b16
+#define ENCI_DE_H_END 0x1b17
+#define ENCI_DE_V_BEGIN_EVEN 0x1b18
+#define ENCI_DE_V_END_EVEN 0x1b19
+#define ENCI_DE_V_BEGIN_ODD 0x1b1a
+#define ENCI_DE_V_END_ODD 0x1b1b
+#define ENCI_VBI_SETTING 0x1b20
+#define ENCI_VBI_CCDT_EVN 0x1b21
+#define ENCI_VBI_CCDT_ODD 0x1b22
+#define ENCI_VBI_CC525_LN 0x1b23
+#define ENCI_VBI_CC625_LN 0x1b24
+#define ENCI_VBI_WSSDT 0x1b25
+#define ENCI_VBI_WSS_LN 0x1b26
+#define ENCI_VBI_CGMSDT_L 0x1b27
+#define ENCI_VBI_CGMSDT_H 0x1b28
+#define ENCI_VBI_CGMS_LN 0x1b29
+#define ENCI_VBI_TTX_HTIME 0x1b2a
+#define ENCI_VBI_TTX_LN 0x1b2b
+#define ENCI_VBI_TTXDT0 0x1b2c
+#define ENCI_VBI_TTXDT1 0x1b2d
+#define ENCI_VBI_TTXDT2 0x1b2e
+#define ENCI_VBI_TTXDT3 0x1b2f
+#define ENCI_MACV_N0 0x1b30
+#define ENCI_MACV_N1 0x1b31
+#define ENCI_MACV_N2 0x1b32
+#define ENCI_MACV_N3 0x1b33
+#define ENCI_MACV_N4 0x1b34
+#define ENCI_MACV_N5 0x1b35
+#define ENCI_MACV_N6 0x1b36
+#define ENCI_MACV_N7 0x1b37
+#define ENCI_MACV_N8 0x1b38
+#define ENCI_MACV_N9 0x1b39
+#define ENCI_MACV_N10 0x1b3a
+#define ENCI_MACV_N11 0x1b3b
+#define ENCI_MACV_N12 0x1b3c
+#define ENCI_MACV_N13 0x1b3d
+#define ENCI_MACV_N14 0x1b3e
+#define ENCI_MACV_N15 0x1b3f
+#define ENCI_MACV_N16 0x1b40
+#define ENCI_MACV_N17 0x1b41
+#define ENCI_MACV_N18 0x1b42
+#define ENCI_MACV_N19 0x1b43
+#define ENCI_MACV_N20 0x1b44
+#define ENCI_MACV_N21 0x1b45
+#define ENCI_MACV_N22 0x1b46
+#define ENCI_DBG_PX_RST 0x1b48
+#define ENCI_DBG_FLDLN_RST 0x1b49
+#define ENCI_DBG_PX_INT 0x1b4a
+#define ENCI_DBG_FLDLN_INT 0x1b4b
+#define ENCI_DBG_MAXPX 0x1b4c
+#define ENCI_DBG_MAXLN 0x1b4d
+#define ENCI_MACV_MAX_AMP 0x1b50
+#define ENCI_MACV_PULSE_LO 0x1b51
+#define ENCI_MACV_PULSE_HI 0x1b52
+#define ENCI_MACV_BKP_MAX 0x1b53
+#define ENCI_CFILT_CTRL 0x1b54
+#define ENCI_CFILT7 0x1b55
+#define ENCI_YC_DELAY 0x1b56
+#define ENCI_VIDEO_EN 0x1b57
+#define ENCI_DVI_HSO_BEGIN 0x1c00
+#define ENCI_DVI_HSO_END 0x1c01
+#define ENCI_DVI_VSO_BLINE_EVN 0x1c02
+#define ENCI_DVI_VSO_BLINE_ODD 0x1c03
+#define ENCI_DVI_VSO_ELINE_EVN 0x1c04
+#define ENCI_DVI_VSO_ELINE_ODD 0x1c05
+#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06
+#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07
+#define ENCI_DVI_VSO_END_EVN 0x1c08
+#define ENCI_DVI_VSO_END_ODD 0x1c09
+#define ENCI_CFILT_CTRL2 0x1c0a
+#define ENCI_DACSEL_0 0x1c0b
+#define ENCI_DACSEL_1 0x1c0c
+#define ENCP_DACSEL_0 0x1c0d
+#define ENCP_DACSEL_1 0x1c0e
+#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f
+#define ENCI_TST_EN 0x1c10
+#define ENCI_TST_MDSEL 0x1c11
+#define ENCI_TST_Y 0x1c12
+#define ENCI_TST_CB 0x1c13
+#define ENCI_TST_CR 0x1c14
+#define ENCI_TST_CLRBAR_STRT 0x1c15
+#define ENCI_TST_CLRBAR_WIDTH 0x1c16
+#define ENCI_TST_VDCNT_STSET 0x1c17
+#define ENCI_VFIFO2VD_CTL 0x1c18
+#define ENCI_VFIFO2VD_PIXEL_START 0x1c19
+#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
+#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
+#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c
+#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d
+#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e
+#define ENCI_VFIFO2VD_CTL2 0x1c1f
+#define ENCT_VFIFO2VD_CTL 0x1c20
+#define ENCT_VFIFO2VD_PIXEL_START 0x1c21
+#define ENCT_VFIFO2VD_PIXEL_END 0x1c22
+#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23
+#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24
+#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25
+#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26
+#define ENCT_VFIFO2VD_CTL2 0x1c27
+#define ENCT_TST_EN 0x1c28
+#define ENCT_TST_MDSEL 0x1c29
+#define ENCT_TST_Y 0x1c2a
+#define ENCT_TST_CB 0x1c2b
+#define ENCT_TST_CR 0x1c2c
+#define ENCT_TST_CLRBAR_STRT 0x1c2d
+#define ENCT_TST_CLRBAR_WIDTH 0x1c2e
+#define ENCT_TST_VDCNT_STSET 0x1c2f
+#define ENCP_DVI_HSO_BEGIN 0x1c30
+#define ENCP_DVI_HSO_END 0x1c31
+#define ENCP_DVI_VSO_BLINE_EVN 0x1c32
+#define ENCP_DVI_VSO_BLINE_ODD 0x1c33
+#define ENCP_DVI_VSO_ELINE_EVN 0x1c34
+#define ENCP_DVI_VSO_ELINE_ODD 0x1c35
+#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36
+#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37
+#define ENCP_DVI_VSO_END_EVN 0x1c38
+#define ENCP_DVI_VSO_END_ODD 0x1c39
+#define ENCP_DE_H_BEGIN 0x1c3a
+#define ENCP_DE_H_END 0x1c3b
+#define ENCP_DE_V_BEGIN_EVEN 0x1c3c
+#define ENCP_DE_V_END_EVEN 0x1c3d
+#define ENCP_DE_V_BEGIN_ODD 0x1c3e
+#define ENCP_DE_V_END_ODD 0x1c3f
+#define ENCI_SYNC_LINE_LENGTH 0x1c40
+#define ENCI_SYNC_PIXEL_EN 0x1c41
+#define ENCI_SYNC_TO_LINE_EN 0x1c42
+#define ENCI_SYNC_TO_PIXEL 0x1c43
+#define ENCP_SYNC_LINE_LENGTH 0x1c44
+#define ENCP_SYNC_PIXEL_EN 0x1c45
+#define ENCP_SYNC_TO_LINE_EN 0x1c46
+#define ENCP_SYNC_TO_PIXEL 0x1c47
+#define ENCT_SYNC_LINE_LENGTH 0x1c48
+#define ENCT_SYNC_PIXEL_EN 0x1c49
+#define ENCT_SYNC_TO_LINE_EN 0x1c4a
+#define ENCT_SYNC_TO_PIXEL 0x1c4b
+#define ENCL_SYNC_LINE_LENGTH 0x1c4c
+#define ENCL_SYNC_PIXEL_EN 0x1c4d
+#define ENCL_SYNC_TO_LINE_EN 0x1c4e
+#define ENCL_SYNC_TO_PIXEL 0x1c4f
+#define ENCP_VFIFO2VD_CTL2 0x1c50
+#define VENC_DVI_SETTING_MORE 0x1c51
+#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54
+#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55
+#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
+#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
+#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
+#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
+#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
+#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c
+#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d
+#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e
+#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f
+#define ENCT_VIDEO_EN 0x1c60
+#define ENCT_VIDEO_Y_SCL 0x1c61
+#define ENCT_VIDEO_PB_SCL 0x1c62
+#define ENCT_VIDEO_PR_SCL 0x1c63
+#define ENCT_VIDEO_Y_OFFST 0x1c64
+#define ENCT_VIDEO_PB_OFFST 0x1c65
+#define ENCT_VIDEO_PR_OFFST 0x1c66
+#define ENCT_VIDEO_MODE 0x1c67
+#define ENCT_VIDEO_MODE_ADV 0x1c68
+#define ENCT_DBG_PX_RST 0x1c69
+#define ENCT_DBG_LN_RST 0x1c6a
+#define ENCT_DBG_PX_INT 0x1c6b
+#define ENCT_DBG_LN_INT 0x1c6c
+#define ENCT_VIDEO_YFP1_HTIME 0x1c6d
+#define ENCT_VIDEO_YFP2_HTIME 0x1c6e
+#define ENCT_VIDEO_YC_DLY 0x1c6f
+#define ENCT_VIDEO_MAX_PXCNT 0x1c70
+#define ENCT_VIDEO_HAVON_END 0x1c71
+#define ENCT_VIDEO_HAVON_BEGIN 0x1c72
+#define ENCT_VIDEO_VAVON_ELINE 0x1c73
+#define ENCT_VIDEO_VAVON_BLINE 0x1c74
+#define ENCT_VIDEO_HSO_BEGIN 0x1c75
+#define ENCT_VIDEO_HSO_END 0x1c76
+#define ENCT_VIDEO_VSO_BEGIN 0x1c77
+#define ENCT_VIDEO_VSO_END 0x1c78
+#define ENCT_VIDEO_VSO_BLINE 0x1c79
+#define ENCT_VIDEO_VSO_ELINE 0x1c7a
+#define ENCT_VIDEO_MAX_LNCNT 0x1c7b
+#define ENCT_VIDEO_BLANKY_VAL 0x1c7c
+#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d
+#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e
+#define ENCT_VIDEO_HOFFST 0x1c7f
+#define ENCT_VIDEO_VOFFST 0x1c80
+#define ENCT_VIDEO_RGB_CTRL 0x1c81
+#define ENCT_VIDEO_FILT_CTRL 0x1c82
+#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83
+#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84
+#define ENCT_VIDEO_MATRIX_CB 0x1c85
+#define ENCT_VIDEO_MATRIX_CR 0x1c86
+#define ENCT_VIDEO_RGBIN_CTRL 0x1c87
+#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88
+#define ENCT_DACSEL_0 0x1c89
+#define ENCT_DACSEL_1 0x1c8a
+#define ENCL_VFIFO2VD_CTL 0x1c90
+#define ENCL_VFIFO2VD_PIXEL_START 0x1c91
+#define ENCL_VFIFO2VD_PIXEL_END 0x1c92
+#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93
+#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94
+#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95
+#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96
+#define ENCL_VFIFO2VD_CTL2 0x1c97
+#define ENCL_TST_EN 0x1c98
+#define ENCL_TST_MDSEL 0x1c99
+#define ENCL_TST_Y 0x1c9a
+#define ENCL_TST_CB 0x1c9b
+#define ENCL_TST_CR 0x1c9c
+#define ENCL_TST_CLRBAR_STRT 0x1c9d
+#define ENCL_TST_CLRBAR_WIDTH 0x1c9e
+#define ENCL_TST_VDCNT_STSET 0x1c9f
+#define ENCL_VIDEO_EN 0x1ca0
+#define ENCL_VIDEO_Y_SCL 0x1ca1
+#define ENCL_VIDEO_PB_SCL 0x1ca2
+#define ENCL_VIDEO_PR_SCL 0x1ca3
+#define ENCL_VIDEO_Y_OFFST 0x1ca4
+#define ENCL_VIDEO_PB_OFFST 0x1ca5
+#define ENCL_VIDEO_PR_OFFST 0x1ca6
+#define ENCL_VIDEO_MODE 0x1ca7
+#define ENCL_VIDEO_MODE_ADV 0x1ca8
+#define ENCL_DBG_PX_RST 0x1ca9
+#define ENCL_DBG_LN_RST 0x1caa
+#define ENCL_DBG_PX_INT 0x1cab
+#define ENCL_DBG_LN_INT 0x1cac
+#define ENCL_VIDEO_YFP1_HTIME 0x1cad
+#define ENCL_VIDEO_YFP2_HTIME 0x1cae
+#define ENCL_VIDEO_YC_DLY 0x1caf
+#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
+#define ENCL_VIDEO_HAVON_END 0x1cb1
+#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
+#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
+#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
+#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
+#define ENCL_VIDEO_HSO_END 0x1cb6
+#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
+#define ENCL_VIDEO_VSO_END 0x1cb8
+#define ENCL_VIDEO_VSO_BLINE 0x1cb9
+#define ENCL_VIDEO_VSO_ELINE 0x1cba
+#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
+#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
+#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
+#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
+#define ENCL_VIDEO_HOFFST 0x1cbf
+#define ENCL_VIDEO_VOFFST 0x1cc0
+#define ENCL_VIDEO_RGB_CTRL 0x1cc1
+#define ENCL_VIDEO_FILT_CTRL 0x1cc2
+#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
+#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
+#define ENCL_VIDEO_MATRIX_CB 0x1cc5
+#define ENCL_VIDEO_MATRIX_CR 0x1cc6
+#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
+#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
+#define ENCL_DACSEL_0 0x1cc9
+#define ENCL_DACSEL_1 0x1cca
+#define RDMA_AHB_START_ADDR_MAN 0x1100
+#define RDMA_AHB_END_ADDR_MAN 0x1101
+#define RDMA_AHB_START_ADDR_1 0x1102
+#define RDMA_AHB_END_ADDR_1 0x1103
+#define RDMA_AHB_START_ADDR_2 0x1104
+#define RDMA_AHB_END_ADDR_2 0x1105
+#define RDMA_AHB_START_ADDR_3 0x1106
+#define RDMA_AHB_END_ADDR_3 0x1107
+#define RDMA_AHB_START_ADDR_4 0x1108
+#define RDMA_AHB_END_ADDR_4 0x1109
+#define RDMA_AHB_START_ADDR_5 0x110a
+#define RDMA_AHB_END_ADDR_5 0x110b
+#define RDMA_AHB_START_ADDR_6 0x110c
+#define RDMA_AHB_END_ADDR_6 0x110d
+#define RDMA_AHB_START_ADDR_7 0x110e
+#define RDMA_AHB_END_ADDR_7 0x110f
+#define RDMA_ACCESS_AUTO 0x1110
+#define RDMA_ACCESS_AUTO2 0x1111
+#define RDMA_ACCESS_AUTO3 0x1112
+#define RDMA_ACCESS_MAN 0x1113
+#define RDMA_CTRL 0x1114
+#define RDMA_STATUS 0x1115
+#define RDMA_STATUS2 0x1116
+#define RDMA_STATUS3 0x1117
+#define L_GAMMA_CNTL_PORT 0x1400
+#define L_GAMMA_DATA_PORT 0x1401
+#define L_GAMMA_ADDR_PORT 0x1402
+#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
+#define L_RGB_BASE_ADDR 0x1405
+#define L_RGB_COEFF_ADDR 0x1406
+#define L_POL_CNTL_ADDR 0x1407
+#define L_DITH_CNTL_ADDR 0x1408
+#define L_GAMMA_PROBE_CTRL 0x1409
+#define L_GAMMA_PROBE_COLOR_L 0x140a
+#define L_GAMMA_PROBE_COLOR_H 0x140b
+#define L_GAMMA_PROBE_HL_COLOR 0x140c
+#define L_GAMMA_PROBE_POS_X 0x140d
+#define L_GAMMA_PROBE_POS_Y 0x140e
+#define L_STH1_HS_ADDR 0x1410
+#define L_STH1_HE_ADDR 0x1411
+#define L_STH1_VS_ADDR 0x1412
+#define L_STH1_VE_ADDR 0x1413
+#define L_STH2_HS_ADDR 0x1414
+#define L_STH2_HE_ADDR 0x1415
+#define L_STH2_VS_ADDR 0x1416
+#define L_STH2_VE_ADDR 0x1417
+#define L_OEH_HS_ADDR 0x1418
+#define L_OEH_HE_ADDR 0x1419
+#define L_OEH_VS_ADDR 0x141a
+#define L_OEH_VE_ADDR 0x141b
+#define L_VCOM_HSWITCH_ADDR 0x141c
+#define L_VCOM_VS_ADDR 0x141d
+#define L_VCOM_VE_ADDR 0x141e
+#define L_CPV1_HS_ADDR 0x141f
+#define L_CPV1_HE_ADDR 0x1420
+#define L_CPV1_VS_ADDR 0x1421
+#define L_CPV1_VE_ADDR 0x1422
+#define L_CPV2_HS_ADDR 0x1423
+#define L_CPV2_HE_ADDR 0x1424
+#define L_CPV2_VS_ADDR 0x1425
+#define L_CPV2_VE_ADDR 0x1426
+#define L_STV1_HS_ADDR 0x1427
+#define L_STV1_HE_ADDR 0x1428
+#define L_STV1_VS_ADDR 0x1429
+#define L_STV1_VE_ADDR 0x142a
+#define L_STV2_HS_ADDR 0x142b
+#define L_STV2_HE_ADDR 0x142c
+#define L_STV2_VS_ADDR 0x142d
+#define L_STV2_VE_ADDR 0x142e
+#define L_OEV1_HS_ADDR 0x142f
+#define L_OEV1_HE_ADDR 0x1430
+#define L_OEV1_VS_ADDR 0x1431
+#define L_OEV1_VE_ADDR 0x1432
+#define L_OEV2_HS_ADDR 0x1433
+#define L_OEV2_HE_ADDR 0x1434
+#define L_OEV2_VS_ADDR 0x1435
+#define L_OEV2_VE_ADDR 0x1436
+#define L_OEV3_HS_ADDR 0x1437
+#define L_OEV3_HE_ADDR 0x1438
+#define L_OEV3_VS_ADDR 0x1439
+#define L_OEV3_VE_ADDR 0x143a
+#define L_LCD_PWR_ADDR 0x143b
+#define L_LCD_PWM0_LO_ADDR 0x143c
+#define L_LCD_PWM0_HI_ADDR 0x143d
+#define L_LCD_PWM1_LO_ADDR 0x143e
+#define L_LCD_PWM1_HI_ADDR 0x143f
+#define L_INV_CNT_ADDR 0x1440
+#define L_TCON_MISC_SEL_ADDR 0x1441
+#define L_DUAL_PORT_CNTL_ADDR 0x1442
+#define MLVDS_CLK_CTL1_HI 0x1443
+#define MLVDS_CLK_CTL1_LO 0x1444
+#define L_TCON_DOUBLE_CTL 0x1449
+#define L_TCON_PATTERN_HI 0x144a
+#define L_TCON_PATTERN_LO 0x144b
+#define LDIM_BL_ADDR_PORT 0x144e
+#define LDIM_BL_DATA_PORT 0x144f
+#define L_DE_HS_ADDR 0x1451
+#define L_DE_HE_ADDR 0x1452
+#define L_DE_VS_ADDR 0x1453
+#define L_DE_VE_ADDR 0x1454
+#define L_HSYNC_HS_ADDR 0x1455
+#define L_HSYNC_HE_ADDR 0x1456
+#define L_HSYNC_VS_ADDR 0x1457
+#define L_HSYNC_VE_ADDR 0x1458
+#define L_VSYNC_HS_ADDR 0x1459
+#define L_VSYNC_HE_ADDR 0x145a
+#define L_VSYNC_VS_ADDR 0x145b
+#define L_VSYNC_VE_ADDR 0x145c
+#define L_LCD_MCU_CTL 0x145d
+#define DUAL_MLVDS_CTL 0x1460
+#define DUAL_MLVDS_LINE_START 0x1461
+#define DUAL_MLVDS_LINE_END 0x1462
+#define DUAL_MLVDS_PIXEL_W_START_L 0x1463
+#define DUAL_MLVDS_PIXEL_W_END_L 0x1464
+#define DUAL_MLVDS_PIXEL_W_START_R 0x1465
+#define DUAL_MLVDS_PIXEL_W_END_R 0x1466
+#define DUAL_MLVDS_PIXEL_R_START_L 0x1467
+#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468
+#define DUAL_MLVDS_PIXEL_R_START_R 0x1469
+#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a
+#define V_INVERSION_PIXEL 0x1470
+#define V_INVERSION_LINE 0x1471
+#define V_INVERSION_CONTROL 0x1472
+#define MLVDS2_CONTROL 0x1474
+#define MLVDS2_CONFIG_HI 0x1475
+#define MLVDS2_CONFIG_LO 0x1476
+#define MLVDS2_DUAL_GATE_WR_START 0x1477
+#define MLVDS2_DUAL_GATE_WR_END 0x1478
+#define MLVDS2_DUAL_GATE_RD_START 0x1479
+#define MLVDS2_DUAL_GATE_RD_END 0x147a
+#define MLVDS2_SECOND_RESET_CTL 0x147b
+#define MLVDS2_DUAL_GATE_CTL_HI 0x147c
+#define MLVDS2_DUAL_GATE_CTL_LO 0x147d
+#define MLVDS2_RESET_CONFIG_HI 0x147e
+#define MLVDS2_RESET_CONFIG_LO 0x147f
+#define GAMMA_CNTL_PORT 0x1480
+#define GAMMA_DATA_PORT 0x1481
+#define GAMMA_ADDR_PORT 0x1482
+#define GAMMA_VCOM_HSWITCH_ADDR 0x1483
+#define RGB_BASE_ADDR 0x1485
+#define RGB_COEFF_ADDR 0x1486
+#define POL_CNTL_ADDR 0x1487
+#define DITH_CNTL_ADDR 0x1488
+#define GAMMA_PROBE_CTRL 0x1489
+#define GAMMA_PROBE_COLOR_L 0x148a
+#define GAMMA_PROBE_COLOR_H 0x148b
+#define GAMMA_PROBE_HL_COLOR 0x148c
+#define GAMMA_PROBE_POS_X 0x148d
+#define GAMMA_PROBE_POS_Y 0x148e
+#define STH1_HS_ADDR 0x1490
+#define STH1_HE_ADDR 0x1491
+#define STH1_VS_ADDR 0x1492
+#define STH1_VE_ADDR 0x1493
+#define STH2_HS_ADDR 0x1494
+#define STH2_HE_ADDR 0x1495
+#define STH2_VS_ADDR 0x1496
+#define STH2_VE_ADDR 0x1497
+#define OEH_HS_ADDR 0x1498
+#define OEH_HE_ADDR 0x1499
+#define OEH_VS_ADDR 0x149a
+#define OEH_VE_ADDR 0x149b
+#define VCOM_HSWITCH_ADDR 0x149c
+#define VCOM_VS_ADDR 0x149d
+#define VCOM_VE_ADDR 0x149e
+#define CPV1_HS_ADDR 0x149f
+#define CPV1_HE_ADDR 0x14a0
+#define CPV1_VS_ADDR 0x14a1
+#define CPV1_VE_ADDR 0x14a2
+#define CPV2_HS_ADDR 0x14a3
+#define CPV2_HE_ADDR 0x14a4
+#define CPV2_VS_ADDR 0x14a5
+#define CPV2_VE_ADDR 0x14a6
+#define STV1_HS_ADDR 0x14a7
+#define STV1_HE_ADDR 0x14a8
+#define STV1_VS_ADDR 0x14a9
+#define STV1_VE_ADDR 0x14aa
+#define STV2_HS_ADDR 0x14ab
+#define STV2_HE_ADDR 0x14ac
+#define STV2_VS_ADDR 0x14ad
+#define STV2_VE_ADDR 0x14ae
+#define OEV1_HS_ADDR 0x14af
+#define OEV1_HE_ADDR 0x14b0
+#define OEV1_VS_ADDR 0x14b1
+#define OEV1_VE_ADDR 0x14b2
+#define OEV2_HS_ADDR 0x14b3
+#define OEV2_HE_ADDR 0x14b4
+#define OEV2_VS_ADDR 0x14b5
+#define OEV2_VE_ADDR 0x14b6
+#define OEV3_HS_ADDR 0x14b7
+#define OEV3_HE_ADDR 0x14b8
+#define OEV3_VS_ADDR 0x14b9
+#define OEV3_VE_ADDR 0x14ba
+#define LCD_PWR_ADDR 0x14bb
+#define LCD_PWM0_LO_ADDR 0x14bc
+#define LCD_PWM0_HI_ADDR 0x14bd
+#define LCD_PWM1_LO_ADDR 0x14be
+#define LCD_PWM1_HI_ADDR 0x14bf
+#define INV_CNT_ADDR 0x14c0
+#define TCON_MISC_SEL_ADDR 0x14c1
+#define DUAL_PORT_CNTL_ADDR 0x14c2
+#define MLVDS_CONTROL 0x14c3
+#define MLVDS_RESET_PATTERN_HI 0x14c4
+#define MLVDS_RESET_PATTERN_LO 0x14c5
+#define MLVDS_RESET_PATTERN_EXT 0x14c6
+#define MLVDS_CONFIG_HI 0x14c7
+#define MLVDS_CONFIG_LO 0x14c8
+#define TCON_DOUBLE_CTL 0x14c9
+#define TCON_PATTERN_HI 0x14ca
+#define TCON_PATTERN_LO 0x14cb
+#define TCON_CONTROL_HI 0x14cc
+#define TCON_CONTROL_LO 0x14cd
+#define LVDS_BLANK_DATA_HI 0x14ce
+#define LVDS_BLANK_DATA_LO 0x14cf
+#define LVDS_PACK_CNTL_ADDR 0x14d0
+#define DE_HS_ADDR 0x14d1
+#define DE_HE_ADDR 0x14d2
+#define DE_VS_ADDR 0x14d3
+#define DE_VE_ADDR 0x14d4
+#define HSYNC_HS_ADDR 0x14d5
+#define HSYNC_HE_ADDR 0x14d6
+#define HSYNC_VS_ADDR 0x14d7
+#define HSYNC_VE_ADDR 0x14d8
+#define VSYNC_HS_ADDR 0x14d9
+#define VSYNC_HE_ADDR 0x14da
+#define VSYNC_VS_ADDR 0x14db
+#define VSYNC_VE_ADDR 0x14dc
+#define LCD_MCU_CTL 0x14dd
+#define LCD_MCU_DATA_0 0x14de
+#define LCD_MCU_DATA_1 0x14df
+#define LVDS_GEN_CNTL 0x14e0
+#define LVDS_PHY_CNTL0 0x14e1
+#define LVDS_PHY_CNTL1 0x14e2
+#define LVDS_PHY_CNTL2 0x14e3
+#define LVDS_PHY_CNTL3 0x14e4
+#define LVDS_PHY_CNTL4 0x14e5
+#define LVDS_PHY_CNTL5 0x14e6
+#define LVDS_SRG_TEST 0x14e8
+#define LVDS_BIST_MUX0 0x14e9
+#define LVDS_BIST_MUX1 0x14ea
+#define LVDS_BIST_FIXED0 0x14eb
+#define LVDS_BIST_FIXED1 0x14ec
+#define LVDS_BIST_CNTL0 0x14ed
+#define LVDS_CLKB_CLKA 0x14ee
+#define LVDS_PHY_CLK_CNTL 0x14ef
+#define LVDS_SER_EN 0x14f0
+#define LVDS_PHY_CNTL6 0x14f1
+#define LVDS_PHY_CNTL7 0x14f2
+#define LVDS_PHY_CNTL8 0x14f3
+#define MLVDS_CLK_CTL0_HI 0x14f4
+#define MLVDS_CLK_CTL0_LO 0x14f5
+#define MLVDS_DUAL_GATE_WR_START 0x14f6
+#define MLVDS_DUAL_GATE_WR_END 0x14f7
+#define MLVDS_DUAL_GATE_RD_START 0x14f8
+#define MLVDS_DUAL_GATE_RD_END 0x14f9
+#define MLVDS_SECOND_RESET_CTL 0x14fa
+#define MLVDS_DUAL_GATE_CTL_HI 0x14fb
+#define MLVDS_DUAL_GATE_CTL_LO 0x14fc
+#define MLVDS_RESET_CONFIG_HI 0x14fd
+#define MLVDS_RESET_CONFIG_LO 0x14fe
+#define VPU_OSD1_MMC_CTRL 0x2701
+#define VPU_OSD2_MMC_CTRL 0x2702
+#define VPU_VD1_MMC_CTRL 0x2703
+#define VPU_VD2_MMC_CTRL 0x2704
+#define VPU_DI_IF1_MMC_CTRL 0x2705
+#define VPU_DI_MEM_MMC_CTRL 0x2706
+#define VPU_DI_INP_MMC_CTRL 0x2707
+#define VPU_DI_MTNRD_MMC_CTRL 0x2708
+#define VPU_DI_CHAN2_MMC_CTRL 0x2709
+#define VPU_DI_MTNWR_MMC_CTRL 0x270a
+#define VPU_DI_NRWR_MMC_CTRL 0x270b
+#define VPU_DI_DIWR_MMC_CTRL 0x270c
+#define VPU_VDIN0_MMC_CTRL 0x270d
+#define VPU_VDIN1_MMC_CTRL 0x270e
+#define VPU_BT656_MMC_CTRL 0x270f
+#define VPU_TVD3D_MMC_CTRL 0x2710
+#define VPU_TVDVBI_MMC_CTRL 0x2711
+#define VPU_TVDVBI_VSLATCH_ADDR 0x2712
+#define VPU_TVDVBI_WRRSP_ADDR 0x2713
+#define VPU_VDIN_PRE_ARB_CTRL 0x2714
+#define VPU_VDISP_PRE_ARB_CTRL 0x2715
+#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716
+#define VPU_OSD3_MMC_CTRL 0x2717
+#define VPU_OSD4_MMC_CTRL 0x2718
+#define VPU_VD3_MMC_CTRL 0x2719
+#define VPU_VIU_VENC_MUX_CTRL 0x271a
+#define VIU1_SEL_VENC_MASK 0x3
+#define VIU1_SEL_VENC_ENCL 0
+#define VIU1_SEL_VENC_ENCI 1
+#define VIU1_SEL_VENC_ENCP 2
+#define VIU1_SEL_VENC_ENCT 3
+#define VIU2_SEL_VENC_MASK 0xc
+#define VIU2_SEL_VENC_ENCL 0
+#define VIU2_SEL_VENC_ENCI (1 << 2)
+#define VIU2_SEL_VENC_ENCP (2 << 2)
+#define VIU2_SEL_VENC_ENCT (3 << 2)
+#define VPU_HDMI_SETTING 0x271b
+#define ENCI_INFO_READ 0x271c
+#define ENCP_INFO_READ 0x271d
+#define ENCT_INFO_READ 0x271e
+#define ENCL_INFO_READ 0x271f
+#define VPU_SW_RESET 0x2720
+#define VPU_D2D3_MMC_CTRL 0x2721
+#define VPU_CONT_MMC_CTRL 0x2722
+#define VPU_CLK_GATE 0x2723
+#define VPU_RDMA_MMC_CTRL 0x2724
+#define VPU_MEM_PD_REG0 0x2725
+#define VPU_MEM_PD_REG1 0x2726
+#define VPU_HDMI_DATA_OVR 0x2727
+#define VPU_PROT1_MMC_CTRL 0x2728
+#define VPU_PROT2_MMC_CTRL 0x2729
+#define VPU_PROT3_MMC_CTRL 0x272a
+#define VPU_ARB4_V1_MMC_CTRL 0x272b
+#define VPU_ARB4_V2_MMC_CTRL 0x272c
+#define VPU_VPU_PWM_V0 0x2730
+#define VPU_VPU_PWM_V1 0x2731
+#define VPU_VPU_PWM_V2 0x2732
+#define VPU_VPU_PWM_V3 0x2733
+#define VPU_VPU_PWM_H0 0x2734
+#define VPU_VPU_PWM_H1 0x2735
+#define VPU_VPU_PWM_H2 0x2736
+#define VPU_VPU_PWM_H3 0x2737
+#define VPU_MISC_CTRL 0x2740
+#define VPU_ISP_GCLK_CTRL0 0x2741
+#define VPU_ISP_GCLK_CTRL1 0x2742
+#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
+#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
+#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
+
+#define VPU_PROT1_CLK_GATE 0x2750
+#define VPU_PROT1_GEN_CNTL 0x2751
+#define VPU_PROT1_X_START_END 0x2752
+#define VPU_PROT1_Y_START_END 0x2753
+#define VPU_PROT1_Y_LEN_STEP 0x2754
+#define VPU_PROT1_RPT_LOOP 0x2755
+#define VPU_PROT1_RPT_PAT 0x2756
+#define VPU_PROT1_DDR 0x2757
+#define VPU_PROT1_RBUF_ROOM 0x2758
+#define VPU_PROT1_STAT_0 0x2759
+#define VPU_PROT1_STAT_1 0x275a
+#define VPU_PROT1_STAT_2 0x275b
+#define VPU_PROT1_REQ_ONOFF 0x275c
+#define VPU_PROT2_CLK_GATE 0x2760
+#define VPU_PROT2_GEN_CNTL 0x2761
+#define VPU_PROT2_X_START_END 0x2762
+#define VPU_PROT2_Y_START_END 0x2763
+#define VPU_PROT2_Y_LEN_STEP 0x2764
+#define VPU_PROT2_RPT_LOOP 0x2765
+#define VPU_PROT2_RPT_PAT 0x2766
+#define VPU_PROT2_DDR 0x2767
+#define VPU_PROT2_RBUF_ROOM 0x2768
+#define VPU_PROT2_STAT_0 0x2769
+#define VPU_PROT2_STAT_1 0x276a
+#define VPU_PROT2_STAT_2 0x276b
+#define VPU_PROT2_REQ_ONOFF 0x276c
+#define VPU_PROT3_CLK_GATE 0x2770
+#define VPU_PROT3_GEN_CNTL 0x2771
+#define VPU_PROT3_X_START_END 0x2772
+#define VPU_PROT3_Y_START_END 0x2773
+#define VPU_PROT3_Y_LEN_STEP 0x2774
+#define VPU_PROT3_RPT_LOOP 0x2775
+#define VPU_PROT3_RPT_PAT 0x2776
+#define VPU_PROT3_DDR 0x2777
+#define VPU_PROT3_RBUF_ROOM 0x2778
+#define VPU_PROT3_STAT_0 0x2779
+#define VPU_PROT3_STAT_1 0x277a
+#define VPU_PROT3_STAT_2 0x277b
+#define VPU_PROT3_REQ_ONOFF 0x277c
+
+/* osd super scale */
+#define OSDSR_HV_SIZEIN 0x3130
+#define OSDSR_CTRL_MODE 0x3131
+#define OSDSR_ABIC_HCOEF 0x3132
+#define OSDSR_YBIC_HCOEF 0x3133
+#define OSDSR_CBIC_HCOEF 0x3134
+#define OSDSR_ABIC_VCOEF 0x3135
+#define OSDSR_YBIC_VCOEF 0x3136
+#define OSDSR_CBIC_VCOEF 0x3137
+#define OSDSR_VAR_PARA 0x3138
+#define OSDSR_CONST_PARA 0x3139
+#define OSDSR_RKE_EXTWIN 0x313a
+#define OSDSR_UK_GRAD2DDIAG_TH_RATE 0x313b
+#define OSDSR_UK_GRAD2DDIAG_LIMIT 0x313c
+#define OSDSR_UK_GRAD2DADJA_TH_RATE 0x313d
+#define OSDSR_UK_GRAD2DADJA_LIMIT 0x313e
+#define OSDSR_UK_BST_GAIN 0x313f
+#define OSDSR_HVBLEND_TH 0x3140
+#define OSDSR_DEMO_WIND_TB 0x3141
+#define OSDSR_DEMO_WIND_LR 0x3142
+#define OSDSR_INT_BLANK_NUM 0x3143
+#define OSDSR_FRM_END_STAT 0x3144
+#define OSDSR_ABIC_HCOEF0 0x3145
+#define OSDSR_YBIC_HCOEF0 0x3146
+#define OSDSR_CBIC_HCOEF0 0x3147
+#define OSDSR_ABIC_VCOEF0 0x3148
+#define OSDSR_YBIC_VCOEF0 0x3149
+#define OSDSR_CBIC_VCOEF0 0x314a
+
+#endif /* __MESON_REGISTERS_H */
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
new file mode 100644
index 000000000000..252cfd4b19b1
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_vclk.h"
+
+/*
+ * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
+ * We handle the following encodings :
+ * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
+ *
+ * What is missing :
+ * - HDMI Pixel Clocks generation
+ */
+
+/* HHI Registers */
+#define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
+#define VID_PLL_EN BIT(19)
+#define VID_PLL_BYPASS BIT(18)
+#define VID_PLL_PRESET BIT(15)
+#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
+#define VCLK2_DIV_MASK 0xff
+#define VCLK2_DIV_EN BIT(16)
+#define VCLK2_DIV_RESET BIT(17)
+#define CTS_VDAC_SEL_MASK (0xf << 28)
+#define CTS_VDAC_SEL_SHIFT 28
+#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
+#define VCLK2_EN BIT(19)
+#define VCLK2_SEL_MASK (0x7 << 16)
+#define VCLK2_SEL_SHIFT 16
+#define VCLK2_SOFT_RESET BIT(15)
+#define VCLK2_DIV1_EN BIT(0)
+#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
+#define CTS_ENCI_SEL_MASK (0xf << 28)
+#define CTS_ENCI_SEL_SHIFT 28
+#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
+#define CTS_ENCI_EN BIT(0)
+#define CTS_VDAC_EN BIT(4)
+
+#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
+
+#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
+#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
+#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
+#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
+
+#define HDMI_PLL_RESET BIT(28)
+#define HDMI_PLL_LOCK BIT(31)
+
+/*
+ * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
+ *
+ * TOFIX: Refactor into table to also handle HDMI frequency and paths
+ */
+static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
+{
+ unsigned int val;
+
+ /* Setup PLL to output 1.485GHz */
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
+
+ /* Reset PLL */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET, HDMI_PLL_RESET);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET, 0);
+ }
+
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+ (val & HDMI_PLL_LOCK), 10, 0);
+
+ /* Disable VCLK2 */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
+
+ /* Disable vid_pll output clock */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+ /* Enable vid_pll bypass to HDMI pll */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_BYPASS, VID_PLL_BYPASS);
+ /* Enable the vid_pll output clock */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_EN, VID_PLL_EN);
+
+ /* Setup the VCLK2 divider value to achieve 27MHz */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ VCLK2_DIV_MASK, (55 - 1));
+
+ /* select vid_pll for vclk2 */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+ /* enable vclk2 gate */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
+
+ /* select vclk_div1 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
+ /* select vclk_div1 for vdac */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
+
+ /* release vclk2_div_reset and enable vclk2_div */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
+
+ /* enable vclk2_div1 gate */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_DIV1_EN, VCLK2_DIV1_EN);
+
+ /* reset vclk2 */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SOFT_RESET, 0);
+
+ /* enable enci_clk */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_ENCI_EN, CTS_ENCI_EN);
+ /* enable vdac_clk */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_VDAC_EN, CTS_VDAC_EN);
+}
+
+void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ unsigned int freq)
+{
+ if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS)
+ meson_venci_cvbs_clock_config(priv);
+}
diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
new file mode 100644
index 000000000000..ec62735996de
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_vclk.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Video Clock */
+
+#ifndef __MESON_VCLK_H
+#define __MESON_VCLK_H
+
+enum {
+ MESON_VCLK_TARGET_CVBS = 0,
+};
+
+/* 27MHz is the CVBS Pixel Clock */
+#define MESON_VCLK_CVBS 27000
+
+void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ unsigned int freq);
+
+#endif /* __MESON_VCLK_H */
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
new file mode 100644
index 000000000000..d836b2274531
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_venc.h"
+#include "meson_vpp.h"
+#include "meson_vclk.h"
+#include "meson_registers.h"
+
+/*
+ * VENC Handle the pixels encoding to the output formats.
+ * We handle the following encodings :
+ * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
+ *
+ * What is missing :
+ * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
+ * - Setup of more clock rates for HDMI modes
+ * - LCD Panel encoding via ENCL
+ * - TV Panel encoding via ENCT
+ */
+
+struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
+ .mode_tag = MESON_VENC_MODE_CVBS_PAL,
+ .hso_begin = 3,
+ .hso_end = 129,
+ .vso_even = 3,
+ .vso_odd = 260,
+ .macv_max_amp = 7,
+ .video_prog_mode = 0xff,
+ .video_mode = 0x13,
+ .sch_adjust = 0x28,
+ .yc_delay = 0x343,
+ .pixel_start = 251,
+ .pixel_end = 1691,
+ .top_field_line_start = 22,
+ .top_field_line_end = 310,
+ .bottom_field_line_start = 23,
+ .bottom_field_line_end = 311,
+ .video_saturation = 9,
+ .video_contrast = 0,
+ .video_brightness = 0,
+ .video_hue = 0,
+ .analog_sync_adj = 0x8080,
+};
+
+struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
+ .mode_tag = MESON_VENC_MODE_CVBS_NTSC,
+ .hso_begin = 5,
+ .hso_end = 129,
+ .vso_even = 3,
+ .vso_odd = 260,
+ .macv_max_amp = 0xb,
+ .video_prog_mode = 0xf0,
+ .video_mode = 0x8,
+ .sch_adjust = 0x20,
+ .yc_delay = 0x333,
+ .pixel_start = 227,
+ .pixel_end = 1667,
+ .top_field_line_start = 18,
+ .top_field_line_end = 258,
+ .bottom_field_line_start = 19,
+ .bottom_field_line_end = 259,
+ .video_saturation = 18,
+ .video_contrast = 3,
+ .video_brightness = 0,
+ .video_hue = 0,
+ .analog_sync_adj = 0x9c00,
+};
+
+void meson_venci_cvbs_mode_set(struct meson_drm *priv,
+ struct meson_cvbs_enci_mode *mode)
+{
+ if (mode->mode_tag == priv->venc.current_mode)
+ return;
+
+ /* CVBS Filter settings */
+ writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
+ writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+
+ /* Digital Video Select : Interlace, clk27 clk, external */
+ writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
+
+ /* Reset Video Mode */
+ writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
+ writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+ /* Horizontal sync signal output */
+ writel_relaxed(mode->hso_begin,
+ priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
+ writel_relaxed(mode->hso_end,
+ priv->io_base + _REG(ENCI_SYNC_HSO_END));
+
+ /* Vertical Sync lines */
+ writel_relaxed(mode->vso_even,
+ priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
+ writel_relaxed(mode->vso_odd,
+ priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
+
+ /* Macrovision max amplitude change */
+ writel_relaxed(0x8100 + mode->macv_max_amp,
+ priv->io_base + _REG(ENCI_MACV_MAX_AMP));
+
+ /* Video mode */
+ writel_relaxed(mode->video_prog_mode,
+ priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
+ writel_relaxed(mode->video_mode,
+ priv->io_base + _REG(ENCI_VIDEO_MODE));
+
+ /* Advanced Video Mode :
+ * Demux shifting 0x2
+ * Blank line end at line17/22
+ * High bandwidth Luma Filter
+ * Low bandwidth Chroma Filter
+ * Bypass luma low pass filter
+ * No macrovision on CSYNC
+ */
+ writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+ writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
+
+ /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
+ writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
+
+ /* 0x3 Y, C, and Component Y delay */
+ writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
+
+ /* Timings */
+ writel_relaxed(mode->pixel_start,
+ priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
+ writel_relaxed(mode->pixel_end,
+ priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
+
+ writel_relaxed(mode->top_field_line_start,
+ priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
+ writel_relaxed(mode->top_field_line_end,
+ priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
+
+ writel_relaxed(mode->bottom_field_line_start,
+ priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
+ writel_relaxed(mode->bottom_field_line_end,
+ priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
+
+ /* Internal Venc, Internal VIU Sync, Internal Vencoder */
+ writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
+
+ /* UNreset Interlaced TV Encoder */
+ writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
+
+ /* Enable Vfifo2vd, Y_Cb_Y_Cr select */
+ writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+
+ /* Power UP Dacs */
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
+
+ /* Video Upsampling */
+ writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
+ writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
+ writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
+
+ /* Select Interlace Y DACs */
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
+ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
+
+ /* Select ENCI for VIU */
+ meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
+
+ /* Enable ENCI FIFO */
+ writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
+
+ /* Select ENCI DACs 0, 1, 4, and 5 */
+ writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
+ writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
+
+ /* Interlace video enable */
+ writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+
+ /* Configure Video Saturation / Contrast / Brightness / Hue */
+ writel_relaxed(mode->video_saturation,
+ priv->io_base + _REG(ENCI_VIDEO_SAT));
+ writel_relaxed(mode->video_contrast,
+ priv->io_base + _REG(ENCI_VIDEO_CONT));
+ writel_relaxed(mode->video_brightness,
+ priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
+ writel_relaxed(mode->video_hue,
+ priv->io_base + _REG(ENCI_VIDEO_HUE));
+
+ /* Enable DAC0 Filter */
+ writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
+ writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
+
+ /* 0 in Macrovision register 0 */
+ writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
+
+ /* Analog Synchronization and color burst value adjust */
+ writel_relaxed(mode->analog_sync_adj,
+ priv->io_base + _REG(ENCI_SYNC_ADJ));
+
+ /* Setup 27MHz vclk2 for ENCI and VDAC */
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS);
+
+ priv->venc.current_mode = mode->mode_tag;
+}
+
+/* Returns the current ENCI field polarity */
+unsigned int meson_venci_get_field(struct meson_drm *priv)
+{
+ return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
+}
+
+void meson_venc_enable_vsync(struct meson_drm *priv)
+{
+ writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
+}
+
+void meson_venc_disable_vsync(struct meson_drm *priv)
+{
+ writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
+}
+
+void meson_venc_init(struct meson_drm *priv)
+{
+ /* Disable all encoders */
+ writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+ writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+ writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+ /* Disable VSync IRQ */
+ meson_venc_disable_vsync(priv);
+
+ priv->venc.current_mode = MESON_VENC_MODE_NONE;
+}
diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
new file mode 100644
index 000000000000..77d4a7d82c44
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_venc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Video Encoders
+ * - ENCI : Interlace Video Encoder
+ * - ENCI_DVI : Interlace Video Encoder for DVI/HDMI
+ * - ENCP : Progressive Video Encoder
+ */
+
+#ifndef __MESON_VENC_H
+#define __MESON_VENC_H
+
+enum {
+ MESON_VENC_MODE_NONE = 0,
+ MESON_VENC_MODE_CVBS_PAL,
+ MESON_VENC_MODE_CVBS_NTSC,
+};
+
+struct meson_cvbs_enci_mode {
+ unsigned int mode_tag;
+ unsigned int hso_begin; /* HSO begin position */
+ unsigned int hso_end; /* HSO end position */
+ unsigned int vso_even; /* VSO even line */
+ unsigned int vso_odd; /* VSO odd line */
+ unsigned int macv_max_amp; /* Macrovision max amplitude */
+ unsigned int video_prog_mode;
+ unsigned int video_mode;
+ unsigned int sch_adjust;
+ unsigned int yc_delay;
+ unsigned int pixel_start;
+ unsigned int pixel_end;
+ unsigned int top_field_line_start;
+ unsigned int top_field_line_end;
+ unsigned int bottom_field_line_start;
+ unsigned int bottom_field_line_end;
+ unsigned int video_saturation;
+ unsigned int video_contrast;
+ unsigned int video_brightness;
+ unsigned int video_hue;
+ unsigned int analog_sync_adj;
+};
+
+/* CVBS Timings and Parameters */
+extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal;
+extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
+
+void meson_venci_cvbs_mode_set(struct meson_drm *priv,
+ struct meson_cvbs_enci_mode *mode);
+unsigned int meson_venci_get_field(struct meson_drm *priv);
+
+void meson_venc_enable_vsync(struct meson_drm *priv);
+void meson_venc_disable_vsync(struct meson_drm *priv);
+
+void meson_venc_init(struct meson_drm *priv);
+
+#endif /* __MESON_VENC_H */
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
new file mode 100644
index 000000000000..c809c085fd78
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "meson_venc_cvbs.h"
+#include "meson_venc.h"
+#include "meson_registers.h"
+
+/* HHI VDAC Registers */
+#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
+
+struct meson_venc_cvbs {
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+ struct meson_drm *priv;
+};
+#define encoder_to_meson_venc_cvbs(x) \
+ container_of(x, struct meson_venc_cvbs, encoder)
+
+#define connector_to_meson_venc_cvbs(x) \
+ container_of(x, struct meson_venc_cvbs, connector)
+
+/* Supported Modes */
+
+struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
+ { /* PAL */
+ .enci = &meson_cvbs_enci_pal,
+ .mode = {
+ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 732, 795, 864, 0, 576, 580, 586, 625, 0,
+ DRM_MODE_FLAG_INTERLACE),
+ .vrefresh = 50,
+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
+ },
+ },
+ { /* NTSC */
+ .enci = &meson_cvbs_enci_ntsc,
+ .mode = {
+ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 739, 801, 858, 0, 480, 488, 494, 525, 0,
+ DRM_MODE_FLAG_INTERLACE),
+ .vrefresh = 60,
+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
+ },
+ },
+};
+
+/* Connector */
+
+static void meson_cvbs_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+meson_cvbs_connector_detect(struct drm_connector *connector, bool force)
+{
+ /* FIXME: Add load-detect or jack-detect if possible */
+ return connector_status_connected;
+}
+
+static int meson_cvbs_connector_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode;
+ int i;
+
+ for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+ struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+ mode = drm_mode_duplicate(dev, &meson_mode->mode);
+ if (!mode) {
+ DRM_ERROR("Failed to create a new display mode\n");
+ return 0;
+ }
+
+ drm_mode_probed_add(connector, mode);
+ }
+
+ return i;
+}
+
+static int meson_cvbs_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ /* Validate the modes added in get_modes */
+ return MODE_OK;
+}
+
+static const struct drm_connector_funcs meson_cvbs_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = meson_cvbs_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = meson_cvbs_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 meson_cvbs_connector_helper_funcs = {
+ .get_modes = meson_cvbs_connector_get_modes,
+ .mode_valid = meson_cvbs_connector_mode_valid,
+};
+
+/* Encoder */
+
+static void meson_venc_cvbs_encoder_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs meson_venc_cvbs_encoder_funcs = {
+ .destroy = meson_venc_cvbs_encoder_destroy,
+};
+
+static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ int i;
+
+ for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+ struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+ if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
+{
+ struct meson_venc_cvbs *meson_venc_cvbs =
+ encoder_to_meson_venc_cvbs(encoder);
+ struct meson_drm *priv = meson_venc_cvbs->priv;
+
+ /* Disable CVBS VDAC */
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+}
+
+static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
+{
+ struct meson_venc_cvbs *meson_venc_cvbs =
+ encoder_to_meson_venc_cvbs(encoder);
+ struct meson_drm *priv = meson_venc_cvbs->priv;
+
+ /* VDAC0 source is not from ATV */
+ writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
+
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+}
+
+static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct meson_venc_cvbs *meson_venc_cvbs =
+ encoder_to_meson_venc_cvbs(encoder);
+ int i;
+
+ for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+ struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+ if (drm_mode_equal(mode, &meson_mode->mode)) {
+ meson_venci_cvbs_mode_set(meson_venc_cvbs->priv,
+ meson_mode->enci);
+ break;
+ }
+ }
+}
+
+static const struct drm_encoder_helper_funcs
+ meson_venc_cvbs_encoder_helper_funcs = {
+ .atomic_check = meson_venc_cvbs_encoder_atomic_check,
+ .disable = meson_venc_cvbs_encoder_disable,
+ .enable = meson_venc_cvbs_encoder_enable,
+ .mode_set = meson_venc_cvbs_encoder_mode_set,
+};
+
+static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv)
+{
+ struct device_node *ep, *remote;
+
+ /* CVBS VDAC output is on the first port, first endpoint */
+ ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0);
+ if (!ep)
+ return false;
+
+
+ /* If the endpoint node exists, consider it enabled */
+ remote = of_graph_get_remote_port(ep);
+ if (remote) {
+ of_node_put(ep);
+ return true;
+ }
+
+ of_node_put(ep);
+ of_node_put(remote);
+
+ return false;
+}
+
+int meson_venc_cvbs_create(struct meson_drm *priv)
+{
+ struct drm_device *drm = priv->drm;
+ struct meson_venc_cvbs *meson_venc_cvbs;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ int ret;
+
+ if (!meson_venc_cvbs_connector_is_available(priv)) {
+ dev_info(drm->dev, "CVBS Output connector not available\n");
+ return -ENODEV;
+ }
+
+ meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),
+ GFP_KERNEL);
+ if (!meson_venc_cvbs)
+ return -ENOMEM;
+
+ meson_venc_cvbs->priv = priv;
+ encoder = &meson_venc_cvbs->encoder;
+ connector = &meson_venc_cvbs->connector;
+
+ /* Connector */
+
+ drm_connector_helper_add(connector,
+ &meson_cvbs_connector_helper_funcs);
+
+ ret = drm_connector_init(drm, connector, &meson_cvbs_connector_funcs,
+ DRM_MODE_CONNECTOR_Composite);
+ if (ret) {
+ dev_err(priv->dev, "Failed to init CVBS connector\n");
+ return ret;
+ }
+
+ connector->interlace_allowed = 1;
+
+ /* Encoder */
+
+ drm_encoder_helper_add(encoder, &meson_venc_cvbs_encoder_helper_funcs);
+
+ ret = drm_encoder_init(drm, encoder, &meson_venc_cvbs_encoder_funcs,
+ DRM_MODE_ENCODER_TVDAC, "meson_venc_cvbs");
+ if (ret) {
+ dev_err(priv->dev, "Failed to init CVBS encoder\n");
+ return ret;
+ }
+
+ encoder->possible_crtcs = BIT(0);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.h b/drivers/gpu/drm/meson/meson_venc_cvbs.h
new file mode 100644
index 000000000000..9256ccf9d931
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_VENC_CVBS_H
+#define __MESON_VENC_CVBS_H
+
+#include "meson_drv.h"
+#include "meson_venc.h"
+
+struct meson_cvbs_mode {
+ struct meson_cvbs_enci_mode *enci;
+ struct drm_display_mode mode;
+};
+
+#define MESON_CVBS_MODES_COUNT 2
+
+/* Modes supported by the CVBS output */
+extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT];
+
+int meson_venc_cvbs_create(struct meson_drm *priv);
+
+#endif /* __MESON_VENC_CVBS_H */
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
new file mode 100644
index 000000000000..a6de8ba7af19
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_viu.h"
+#include "meson_vpp.h"
+#include "meson_venc.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+/*
+ * VIU Handles the Pixel scanout and the basic Colorspace conversions
+ * We handle the following features :
+ * - OSD1 RGB565/RGB888/xRGB8888 scanout
+ * - RGB conversion to x/cb/cr
+ * - Progressive or Interlace buffer scanout
+ * - OSD1 Commit on Vsync
+ * - HDR OSD matrix for GXL/GXM
+ *
+ * What is missing :
+ * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
+ * - YUV4:2:2 Y0CbY1Cr scanout
+ * - Conversion to YUV 4:4:4 from 4:2:2 input
+ * - Colorkey Alpha matching
+ * - Big endian scanout
+ * - X/Y reverse scanout
+ * - Global alpha setup
+ * - OSD2 support, would need interlace switching on vsync
+ * - OSD1 full scaling to support TV overscan
+ */
+
+/* OSD csc defines */
+
+enum viu_matrix_sel_e {
+ VIU_MATRIX_OSD_EOTF = 0,
+ VIU_MATRIX_OSD,
+};
+
+enum viu_lut_sel_e {
+ VIU_LUT_OSD_EOTF = 0,
+ VIU_LUT_OSD_OETF,
+};
+
+#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
+#define MATRIX_5X3_COEF_SIZE 24
+
+#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
+#define EOTF_COEFF_SIZE 10
+#define EOTF_COEFF_RIGHTSHIFT 1
+
+static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
+ 0, 0, 0, /* pre offset */
+ COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765),
+ COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500),
+ COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116),
+ 0, 0, 0, /* 10'/11'/12' */
+ 0, 0, 0, /* 20'/21'/22' */
+ 64, 512, 512, /* offset */
+ 0, 0, 0 /* mode, right_shift, clip_en */
+};
+
+/* eotf matrix: bypass */
+static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
+ EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0),
+ EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0),
+ EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0),
+ EOTF_COEFF_RIGHTSHIFT /* right shift */
+};
+
+void meson_viu_set_osd_matrix(struct meson_drm *priv,
+ enum viu_matrix_sel_e m_select,
+ int *m, bool csc_on)
+{
+ if (m_select == VIU_MATRIX_OSD) {
+ /* osd matrix, VIU_MATRIX_0 */
+ writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
+ writel(m[2] & 0xfff,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
+ writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
+ writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
+ writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
+ writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
+
+ if (m[21]) {
+ writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
+ priv->io_base +
+ _REG(VIU_OSD1_MATRIX_COEF22_30));
+ writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
+ priv->io_base +
+ _REG(VIU_OSD1_MATRIX_COEF31_32));
+ writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
+ priv->io_base +
+ _REG(VIU_OSD1_MATRIX_COEF40_41));
+ writel(m[17] & 0x1fff, priv->io_base +
+ _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+ } else
+ writel((m[11] & 0x1fff) << 16, priv->io_base +
+ _REG(VIU_OSD1_MATRIX_COEF22_30));
+
+ writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
+ priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
+ writel(m[20] & 0xfff,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
+
+ writel_bits_relaxed(3 << 30, m[21] << 30,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+ writel_bits_relaxed(7 << 16, m[22] << 16,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+
+ /* 23 reserved for clipping control */
+ writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
+ writel_bits_relaxed(BIT(1), 0,
+ priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
+ } else if (m_select == VIU_MATRIX_OSD_EOTF) {
+ int i;
+
+ /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
+ for (i = 0; i < 5; i++)
+ writel(((m[i * 2] & 0x1fff) << 16) |
+ (m[i * 2 + 1] & 0x1fff), priv->io_base +
+ _REG(VIU_OSD1_EOTF_CTL + i + 1));
+
+ writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
+ priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
+ writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
+ priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
+ }
+}
+
+#define OSD_EOTF_LUT_SIZE 33
+#define OSD_OETF_LUT_SIZE 41
+
+void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
+ unsigned int *r_map, unsigned int *g_map,
+ unsigned int *b_map,
+ bool csc_on)
+{
+ unsigned int addr_port;
+ unsigned int data_port;
+ unsigned int ctrl_port;
+ int i;
+
+ if (lut_sel == VIU_LUT_OSD_EOTF) {
+ addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
+ data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
+ ctrl_port = VIU_OSD1_EOTF_CTL;
+ } else if (lut_sel == VIU_LUT_OSD_OETF) {
+ addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
+ data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
+ ctrl_port = VIU_OSD1_OETF_CTL;
+ } else
+ return;
+
+ if (lut_sel == VIU_LUT_OSD_OETF) {
+ writel(0, priv->io_base + _REG(addr_port));
+
+ for (i = 0; i < 20; i++)
+ writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
+ priv->io_base + _REG(data_port));
+
+ writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
+ priv->io_base + _REG(data_port));
+
+ for (i = 0; i < 20; i++)
+ writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
+ priv->io_base + _REG(data_port));
+
+ for (i = 0; i < 20; i++)
+ writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
+ priv->io_base + _REG(data_port));
+
+ writel(b_map[OSD_OETF_LUT_SIZE - 1],
+ priv->io_base + _REG(data_port));
+
+ if (csc_on)
+ writel_bits_relaxed(0x7 << 29, 7 << 29,
+ priv->io_base + _REG(ctrl_port));
+ else
+ writel_bits_relaxed(0x7 << 29, 0,
+ priv->io_base + _REG(ctrl_port));
+ } else if (lut_sel == VIU_LUT_OSD_EOTF) {
+ writel(0, priv->io_base + _REG(addr_port));
+
+ for (i = 0; i < 20; i++)
+ writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
+ priv->io_base + _REG(data_port));
+
+ writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
+ priv->io_base + _REG(data_port));
+
+ for (i = 0; i < 20; i++)
+ writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
+ priv->io_base + _REG(data_port));
+
+ for (i = 0; i < 20; i++)
+ writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
+ priv->io_base + _REG(data_port));
+
+ writel(b_map[OSD_EOTF_LUT_SIZE - 1],
+ priv->io_base + _REG(data_port));
+
+ if (csc_on)
+ writel_bits_relaxed(7 << 27, 7 << 27,
+ priv->io_base + _REG(ctrl_port));
+ else
+ writel_bits_relaxed(7 << 27, 0,
+ priv->io_base + _REG(ctrl_port));
+
+ writel_bits_relaxed(BIT(31), BIT(31),
+ priv->io_base + _REG(ctrl_port));
+ }
+}
+
+/* eotf lut: linear */
+static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
+ 0x0000, 0x0200, 0x0400, 0x0600,
+ 0x0800, 0x0a00, 0x0c00, 0x0e00,
+ 0x1000, 0x1200, 0x1400, 0x1600,
+ 0x1800, 0x1a00, 0x1c00, 0x1e00,
+ 0x2000, 0x2200, 0x2400, 0x2600,
+ 0x2800, 0x2a00, 0x2c00, 0x2e00,
+ 0x3000, 0x3200, 0x3400, 0x3600,
+ 0x3800, 0x3a00, 0x3c00, 0x3e00,
+ 0x4000
+};
+
+/* osd oetf lut: linear */
+static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
+ 0, 0, 0, 0,
+ 0, 32, 64, 96,
+ 128, 160, 196, 224,
+ 256, 288, 320, 352,
+ 384, 416, 448, 480,
+ 512, 544, 576, 608,
+ 640, 672, 704, 736,
+ 768, 800, 832, 864,
+ 896, 928, 960, 992,
+ 1023, 1023, 1023, 1023,
+ 1023
+};
+
+static void meson_viu_load_matrix(struct meson_drm *priv)
+{
+ /* eotf lut bypass */
+ meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
+ eotf_33_linear_mapping, /* R */
+ eotf_33_linear_mapping, /* G */
+ eotf_33_linear_mapping, /* B */
+ false);
+
+ /* eotf matrix bypass */
+ meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
+ eotf_bypass_coeff,
+ false);
+
+ /* oetf lut bypass */
+ meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
+ oetf_41_linear_mapping, /* R */
+ oetf_41_linear_mapping, /* G */
+ oetf_41_linear_mapping, /* B */
+ false);
+
+ /* osd matrix RGB709 to YUV709 limit */
+ meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
+ RGB709_to_YUV709l_coeff,
+ true);
+}
+
+void meson_viu_init(struct meson_drm *priv)
+{
+ uint32_t reg;
+
+ /* Disable OSDs */
+ writel_bits_relaxed(BIT(0) | BIT(21), 0,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
+ writel_bits_relaxed(BIT(0) | BIT(21), 0,
+ priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
+
+ /* On GXL/GXM, Use the 10bit HDR conversion matrix */
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ meson_viu_load_matrix(priv);
+
+ /* Initialize OSD1 fifo control register */
+ reg = BIT(0) | /* Urgent DDR request priority */
+ (4 << 5) | /* hold_fifo_lines */
+ (3 << 10) | /* burst length 64 */
+ (32 << 12) | /* fifo_depth_val: 32*8=256 */
+ (2 << 22) | /* 4 words in 1 burst */
+ (2 << 24);
+ writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
+ writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
+
+ /* Set OSD alpha replace value */
+ writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
+ 0xff << OSD_REPLACE_SHIFT,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+ writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
+ 0xff << OSD_REPLACE_SHIFT,
+ priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
+
+ priv->viu.osd1_enabled = false;
+ priv->viu.osd1_commit = false;
+ priv->viu.osd1_interlace = false;
+}
diff --git a/drivers/gpu/drm/meson/meson_viu.h b/drivers/gpu/drm/meson/meson_viu.h
new file mode 100644
index 000000000000..073b1910bd1b
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_viu.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Video Input Unit */
+
+#ifndef __MESON_VIU_H
+#define __MESON_VIU_H
+
+/* OSDx_BLKx_CFG */
+#define OSD_CANVAS_SEL 16
+
+#define OSD_ENDIANNESS_LE BIT(15)
+#define OSD_ENDIANNESS_BE (0)
+
+#define OSD_BLK_MODE_422 (0x03 << 8)
+#define OSD_BLK_MODE_16 (0x04 << 8)
+#define OSD_BLK_MODE_32 (0x05 << 8)
+#define OSD_BLK_MODE_24 (0x07 << 8)
+
+#define OSD_OUTPUT_COLOR_RGB BIT(7)
+#define OSD_OUTPUT_COLOR_YUV (0)
+
+#define OSD_COLOR_MATRIX_32_RGBA (0x00 << 2)
+#define OSD_COLOR_MATRIX_32_ARGB (0x01 << 2)
+#define OSD_COLOR_MATRIX_32_ABGR (0x02 << 2)
+#define OSD_COLOR_MATRIX_32_BGRA (0x03 << 2)
+
+#define OSD_COLOR_MATRIX_24_RGB (0x00 << 2)
+
+#define OSD_COLOR_MATRIX_16_RGB655 (0x00 << 2)
+#define OSD_COLOR_MATRIX_16_RGB565 (0x04 << 2)
+
+#define OSD_INTERLACE_ENABLED BIT(1)
+#define OSD_INTERLACE_ODD BIT(0)
+#define OSD_INTERLACE_EVEN (0)
+
+/* OSDx_CTRL_STAT */
+#define OSD_ENABLE BIT(21)
+#define OSD_BLK0_ENABLE BIT(0)
+
+#define OSD_GLOBAL_ALPHA_SHIFT 12
+
+/* OSDx_CTRL_STAT2 */
+#define OSD_REPLACE_EN BIT(14)
+#define OSD_REPLACE_SHIFT 6
+
+void meson_viu_init(struct meson_drm *priv);
+
+#endif /* __MESON_VIU_H */
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
new file mode 100644
index 000000000000..671909d8672e
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_vpp.h"
+#include "meson_registers.h"
+
+/*
+ * VPP Handles all the Post Processing after the Scanout from the VIU
+ * We handle the following post processings :
+ * - Postblend : Blends the OSD1 only
+ * We exclude OSD2, VS1, VS1 and Preblend output
+ * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
+ * use it only for interlace scanout
+ * - Intermediate FIFO with default Amlogic values
+ *
+ * What is missing :
+ * - Preblend for video overlay pre-scaling
+ * - OSD2 support for cursor framebuffer
+ * - Video pre-scaling before postblend
+ * - Full Vertical/Horizontal OSD scaling to support TV overscan
+ * - HDR conversion
+ */
+
+void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
+{
+ writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
+}
+
+/*
+ * When the output is interlaced, the OSD must switch between
+ * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
+ * at each vsync.
+ * But the vertical scaler can provide such funtionnality if
+ * is configured for 2:1 scaling with interlace options enabled.
+ */
+void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
+ struct drm_rect *input)
+{
+ writel_relaxed(BIT(3) /* Enable scaler */ |
+ BIT(2), /* Select OSD1 */
+ priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+
+ writel_relaxed(((drm_rect_width(input) - 1) << 16) |
+ (drm_rect_height(input) - 1),
+ priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
+ /* 2:1 scaling */
+ writel_relaxed(((input->x1) << 16) | (input->x2),
+ priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
+ writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
+ priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
+
+ /* 2:1 scaling values */
+ writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
+ writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
+
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+
+ writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
+ (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
+ (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
+ (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
+ (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
+ BIT(23) /* osd_prog_interlace */ |
+ BIT(24), /* Enable vertical scaler */
+ priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+}
+
+void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
+{
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+}
+
+static unsigned int vpp_filter_coefs_4point_bspline[] = {
+ 0x15561500, 0x14561600, 0x13561700, 0x12561800,
+ 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
+ 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
+ 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
+ 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
+ 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
+ 0x05473301, 0x05463401, 0x04453601, 0x04433702,
+ 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
+ 0x033d3d03
+};
+
+static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv,
+ const unsigned int *coefs,
+ bool is_horizontal)
+{
+ int i;
+
+ writel_relaxed(is_horizontal ? BIT(8) : 0,
+ priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
+ for (i = 0; i < 33; i++)
+ writel_relaxed(coefs[i],
+ priv->io_base + _REG(VPP_OSD_SCALE_COEF));
+}
+
+void meson_vpp_init(struct meson_drm *priv)
+{
+ /* set dummy data default YUV black */
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) {
+ writel_bits_relaxed(0xff << 16, 0xff << 16,
+ priv->io_base + _REG(VIU_MISC_CTRL1));
+ writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
+ writel_relaxed(0x1020080,
+ priv->io_base + _REG(VPP_DUMMY_DATA1));
+ }
+
+ /* Initialize vpu fifo control registers */
+ writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
+ 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
+ writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
+
+ /* Turn off preblend */
+ writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Turn off POSTBLEND */
+ writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Force all planes off */
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
+ VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Disable Scalers */
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+ writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+
+ /* Write in the proper filter coefficients. */
+ meson_vpp_write_scaling_filter_coefs(priv,
+ vpp_filter_coefs_4point_bspline, false);
+ meson_vpp_write_scaling_filter_coefs(priv,
+ vpp_filter_coefs_4point_bspline, true);
+}
diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h
new file mode 100644
index 000000000000..ede3b26e0f22
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_vpp.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Video Post Process */
+
+#ifndef __MESON_VPP_H
+#define __MESON_VPP_H
+
+/* Mux VIU/VPP to ENCI */
+#define MESON_VIU_VPP_MUX_ENCI 0x5
+
+void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux);
+
+void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
+ struct drm_rect *input);
+void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv);
+
+void meson_vpp_init(struct meson_drm *priv);
+
+#endif /* __MESON_VPP_H */
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 1443b3a34775..b0b874264f9d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -82,9 +82,7 @@ static const struct file_operations mgag200_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = mgag200_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.read = drm_read,
};
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 6b21cb27e1cc..3a03ac4045d8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1658,12 +1658,6 @@ static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
return NULL;
}
-static enum drm_connector_status mga_vga_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void mga_connector_destroy(struct drm_connector *connector)
{
struct mga_connector *mga_connector = to_mga_connector(connector);
@@ -1680,7 +1674,6 @@ static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs =
static const struct drm_connector_funcs mga_vga_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = mga_vga_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = mga_connector_destroy,
};
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c
index dcf7d11ac380..5e20220ef4c6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_ttm.c
+++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c
@@ -230,6 +230,7 @@ struct ttm_bo_driver mgag200_bo_driver = {
.ttm_tt_populate = mgag200_ttm_tt_populate,
.ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate,
.init_mem_type = mgag200_bo_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = mgag200_bo_evict_flags,
.move = NULL,
.verify_access = mgag200_bo_verify_access,
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 4e2806cf778c..028c24df2291 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -6,6 +6,8 @@ msm-y := \
adreno/adreno_gpu.o \
adreno/a3xx_gpu.o \
adreno/a4xx_gpu.o \
+ adreno/a5xx_gpu.o \
+ adreno/a5xx_power.o \
hdmi/hdmi.o \
hdmi/hdmi_audio.o \
hdmi/hdmi_bridge.o \
@@ -37,6 +39,7 @@ msm-y := \
mdp/mdp5/mdp5_irq.o \
mdp/mdp5/mdp5_mdss.o \
mdp/mdp5/mdp5_kms.o \
+ mdp/mdp5/mdp5_pipe.o \
mdp/mdp5/mdp5_plane.o \
mdp/mdp5/mdp5_smp.o \
msm_atomic.o \
@@ -48,6 +51,7 @@ msm-y := \
msm_gem_prime.o \
msm_gem_shrinker.o \
msm_gem_submit.o \
+ msm_gem_vma.o \
msm_gpu.o \
msm_iommu.o \
msm_perf.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index fee24297fb92..4be092f911f9 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -8,16 +8,17 @@ 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 ( 398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 431 bytes, from 2016-04-26 17:56:44)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
-- /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 ( 11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
- /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:
+Copyright (C) 2013-2016 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
- Ilia Mirkin <imirkin@alum.mit.edu> (imirkin)
@@ -206,12 +207,12 @@ enum a2xx_rb_copy_sample_select {
};
enum a2xx_rb_blend_opcode {
- BLEND_DST_PLUS_SRC = 0,
- BLEND_SRC_MINUS_DST = 1,
- BLEND_MIN_DST_SRC = 2,
- BLEND_MAX_DST_SRC = 3,
- BLEND_DST_MINUS_SRC = 4,
- BLEND_DST_PLUS_SRC_BIAS = 5,
+ BLEND2_DST_PLUS_SRC = 0,
+ BLEND2_SRC_MINUS_DST = 1,
+ BLEND2_MIN_DST_SRC = 2,
+ BLEND2_MAX_DST_SRC = 3,
+ BLEND2_DST_MINUS_SRC = 4,
+ BLEND2_DST_PLUS_SRC_BIAS = 5,
};
enum adreno_mmu_clnt_beh {
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index 27dabd5e57fb..a066c8b9eccd 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 ( 398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 431 bytes, from 2016-04-26 17:56:44)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
-- /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 ( 11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2016 by the following authors:
@@ -129,10 +130,14 @@ enum a3xx_tex_fmt {
TFMT_Z16_UNORM = 9,
TFMT_X8Z24_UNORM = 10,
TFMT_Z32_FLOAT = 11,
- TFMT_NV12_UV_TILED = 17,
- TFMT_NV12_Y_TILED = 19,
- TFMT_NV12_UV = 21,
- TFMT_NV12_Y = 23,
+ TFMT_UV_64X32 = 16,
+ TFMT_VU_64X32 = 17,
+ TFMT_Y_64X32 = 18,
+ TFMT_NV12_64X32 = 19,
+ TFMT_UV_LINEAR = 20,
+ TFMT_VU_LINEAR = 21,
+ TFMT_Y_LINEAR = 22,
+ TFMT_NV12_LINEAR = 23,
TFMT_I420_Y = 24,
TFMT_I420_U = 26,
TFMT_I420_V = 27,
@@ -525,14 +530,6 @@ enum a3xx_uche_perfcounter_select {
UCHE_UCHEPERF_ACTIVE_CYCLES = 20,
};
-enum a3xx_rb_blend_opcode {
- BLEND_DST_PLUS_SRC = 0,
- BLEND_SRC_MINUS_DST = 1,
- BLEND_DST_MINUS_SRC = 2,
- BLEND_MIN_DST_SRC = 3,
- BLEND_MAX_DST_SRC = 4,
-};
-
enum a3xx_intp_mode {
SMOOTH = 0,
FLAT = 1,
@@ -1393,13 +1390,14 @@ static inline uint32_t A3XX_RB_COPY_CONTROL_MODE(enum adreno_rb_copy_control_mod
{
return ((val) << A3XX_RB_COPY_CONTROL_MODE__SHIFT) & A3XX_RB_COPY_CONTROL_MODE__MASK;
}
+#define A3XX_RB_COPY_CONTROL_MSAA_SRGB_DOWNSAMPLE 0x00000080
#define A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK 0x00000f00
#define A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT 8
static inline uint32_t A3XX_RB_COPY_CONTROL_FASTCLEAR(uint32_t val)
{
return ((val) << A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT) & A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK;
}
-#define A3XX_RB_COPY_CONTROL_UNK12 0x00001000
+#define A3XX_RB_COPY_CONTROL_DEPTH32_RESOLVE 0x00001000
#define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK 0xffffc000
#define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT 14
static inline uint32_t A3XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
@@ -1472,7 +1470,7 @@ static inline uint32_t A3XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
{
return ((val) << A3XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A3XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
}
-#define A3XX_RB_DEPTH_CONTROL_BF_ENABLE 0x00000080
+#define A3XX_RB_DEPTH_CONTROL_Z_CLAMP_ENABLE 0x00000080
#define A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE 0x80000000
#define REG_A3XX_RB_DEPTH_CLEAR 0x00002101
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index fd266ed963b6..b999349b7d2d 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -41,7 +41,7 @@ extern bool hang_debug;
static void a3xx_dump(struct msm_gpu *gpu);
-static void a3xx_me_init(struct msm_gpu *gpu)
+static bool a3xx_me_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb;
@@ -65,7 +65,7 @@ static void a3xx_me_init(struct msm_gpu *gpu)
OUT_RING(ring, 0x00000000);
gpu->funcs->flush(gpu);
- gpu->funcs->idle(gpu);
+ return gpu->funcs->idle(gpu);
}
static int a3xx_hw_init(struct msm_gpu *gpu)
@@ -294,15 +294,20 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
/* clear ME_HALT to start micro engine */
gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
- a3xx_me_init(gpu);
-
- return 0;
+ return a3xx_me_init(gpu) ? 0 : -EINVAL;
}
static void a3xx_recover(struct msm_gpu *gpu)
{
+ int i;
+
adreno_dump_info(gpu);
+ for (i = 0; i < 8; i++) {
+ printk("CP_SCRATCH_REG%d: %u\n", i,
+ gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+ }
+
/* dump registers before resetting gpu, if enabled: */
if (hang_debug)
a3xx_dump(gpu);
@@ -330,17 +335,22 @@ static void a3xx_destroy(struct msm_gpu *gpu)
kfree(a3xx_gpu);
}
-static void a3xx_idle(struct msm_gpu *gpu)
+static bool a3xx_idle(struct msm_gpu *gpu)
{
/* wait for ringbuffer to drain: */
- adreno_idle(gpu);
+ if (!adreno_idle(gpu))
+ return false;
/* then wait for GPU to finish: */
if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
- A3XX_RBBM_STATUS_GPU_BUSY)))
+ A3XX_RBBM_STATUS_GPU_BUSY))) {
DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
- /* TODO maybe we need to reset GPU here to recover from hang? */
+ /* TODO maybe we need to reset GPU here to recover from hang? */
+ return false;
+ }
+
+ return true;
}
static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
@@ -419,91 +429,13 @@ static void a3xx_dump(struct msm_gpu *gpu)
}
/* Register offset defines for A3XX */
static const unsigned int a3xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
- REG_ADRENO_DEFINE(REG_ADRENO_CP_DEBUG, REG_AXXX_CP_DEBUG),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_WADDR, REG_AXXX_CP_ME_RAM_WADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_DATA, REG_AXXX_CP_ME_RAM_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_DATA,
- REG_A3XX_CP_PFP_UCODE_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_ADDR,
- REG_A3XX_CP_PFP_UCODE_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_WFI_PEND_CTR, REG_A3XX_CP_WFI_PEND_CTR),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),
+ REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR),
+ REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_CTRL, REG_A3XX_CP_PROTECT_CTRL),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_CNTL, REG_AXXX_CP_ME_CNTL),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BASE, REG_AXXX_CP_IB1_BASE),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BUFSZ, REG_AXXX_CP_IB1_BUFSZ),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BASE, REG_AXXX_CP_IB2_BASE),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BUFSZ, REG_AXXX_CP_IB2_BUFSZ),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_TIMESTAMP, REG_AXXX_CP_SCRATCH_REG0),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_RADDR, REG_AXXX_CP_ME_RAM_RADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_ADDR, REG_AXXX_SCRATCH_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_UMSK, REG_AXXX_SCRATCH_UMSK),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_ADDR, REG_A3XX_CP_ROQ_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_DATA, REG_A3XX_CP_ROQ_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_ADDR, REG_A3XX_CP_MERCIU_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA, REG_A3XX_CP_MERCIU_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA2, REG_A3XX_CP_MERCIU_DATA2),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_ADDR, REG_A3XX_CP_MEQ_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_DATA, REG_A3XX_CP_MEQ_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_HW_FAULT, REG_A3XX_CP_HW_FAULT),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_STATUS,
- REG_A3XX_CP_PROTECT_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_STATUS, REG_A3XX_RBBM_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_CTL,
- REG_A3XX_RBBM_PERFCTR_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
- REG_A3XX_RBBM_PERFCTR_LOAD_CMD0),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
- REG_A3XX_RBBM_PERFCTR_LOAD_CMD1),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
- REG_A3XX_RBBM_PERFCTR_PWR_1_LO),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_MASK, REG_A3XX_RBBM_INT_0_MASK),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_STATUS,
- REG_A3XX_RBBM_INT_0_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ERROR_STATUS,
- REG_A3XX_RBBM_AHB_ERROR_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_CMD, REG_A3XX_RBBM_AHB_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_CLEAR_CMD,
- REG_A3XX_RBBM_INT_CLEAR_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_CLOCK_CTL, REG_A3XX_RBBM_CLOCK_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_SEL,
- REG_A3XX_VPC_VPC_DEBUG_RAM_SEL),
- REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_READ,
- REG_A3XX_VPC_VPC_DEBUG_RAM_READ),
- REG_ADRENO_DEFINE(REG_ADRENO_VSC_SIZE_ADDRESS,
- REG_A3XX_VSC_SIZE_ADDRESS),
- REG_ADRENO_DEFINE(REG_ADRENO_VFD_CONTROL_0, REG_A3XX_VFD_CONTROL_0),
- REG_ADRENO_DEFINE(REG_ADRENO_VFD_INDEX_MAX, REG_A3XX_VFD_INDEX_MAX),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
- REG_A3XX_SP_VS_PVT_MEM_ADDR_REG),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
- REG_A3XX_SP_FS_PVT_MEM_ADDR_REG),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_OBJ_START_REG,
- REG_A3XX_SP_VS_OBJ_START_REG),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_OBJ_START_REG,
- REG_A3XX_SP_FS_OBJ_START_REG),
- REG_ADRENO_DEFINE(REG_ADRENO_PA_SC_AA_CONFIG, REG_A3XX_PA_SC_AA_CONFIG),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PM_OVERRIDE2,
- REG_A3XX_RBBM_PM_OVERRIDE2),
- REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_REG2, REG_AXXX_CP_SCRATCH_REG2),
- REG_ADRENO_DEFINE(REG_ADRENO_SQ_GPR_MANAGEMENT,
- REG_A3XX_SQ_GPR_MANAGEMENT),
- REG_ADRENO_DEFINE(REG_ADRENO_SQ_INST_STORE_MANAGMENT,
- REG_A3XX_SQ_INST_STORE_MANAGMENT),
- REG_ADRENO_DEFINE(REG_ADRENO_TP0_CHICKEN, REG_A3XX_TP0_CHICKEN),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_RBBM_CTL, REG_A3XX_RBBM_RBBM_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_SW_RESET_CMD,
- REG_A3XX_RBBM_SW_RESET_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_UCHE_INVALIDATE0,
- REG_A3XX_UCHE_CACHE_INVALIDATE0_REG),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
- REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_LO),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
- REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_HI),
};
static const struct adreno_gpu_funcs funcs = {
@@ -583,7 +515,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
#endif
}
- if (!gpu->mmu) {
+ if (!gpu->aspace) {
/* TODO we think it is possible to configure the GPU to
* restrict access to VRAM carveout. But the required
* registers are unknown. For now just bail out and
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index 3220b91f559a..4ce21b902779 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 ( 398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 431 bytes, from 2016-04-26 17:56:44)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
-- /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 ( 11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2016 by the following authors:
@@ -46,6 +47,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
enum a4xx_color_fmt {
RB4_A8_UNORM = 1,
RB4_R8_UNORM = 2,
+ RB4_R8_SNORM = 3,
+ RB4_R8_UINT = 4,
+ RB4_R8_SINT = 5,
RB4_R4G4B4A4_UNORM = 8,
RB4_R5G5B5A1_UNORM = 10,
RB4_R5G6B5_UNORM = 14,
@@ -89,17 +93,10 @@ enum a4xx_color_fmt {
enum a4xx_tile_mode {
TILE4_LINEAR = 0,
+ TILE4_2 = 2,
TILE4_3 = 3,
};
-enum a4xx_rb_blend_opcode {
- BLEND_DST_PLUS_SRC = 0,
- BLEND_SRC_MINUS_DST = 1,
- BLEND_DST_MINUS_SRC = 2,
- BLEND_MIN_DST_SRC = 3,
- BLEND_MAX_DST_SRC = 4,
-};
-
enum a4xx_vtx_fmt {
VFMT4_32_FLOAT = 1,
VFMT4_32_32_FLOAT = 2,
@@ -940,6 +937,7 @@ static inline uint32_t A4XX_RB_MODE_CONTROL_HEIGHT(uint32_t val)
{
return ((val >> 5) << A4XX_RB_MODE_CONTROL_HEIGHT__SHIFT) & A4XX_RB_MODE_CONTROL_HEIGHT__MASK;
}
+#define A4XX_RB_MODE_CONTROL_ENABLE_GMEM 0x00010000
#define REG_A4XX_RB_RENDER_CONTROL 0x000020a1
#define A4XX_RB_RENDER_CONTROL_BINNING_PASS 0x00000001
@@ -1043,7 +1041,7 @@ static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_b
}
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK 0x000000e0
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT 5
-static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
+static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
}
@@ -1061,7 +1059,7 @@ static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb
}
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK 0x00e00000
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT 21
-static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
+static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
}
@@ -1073,12 +1071,18 @@ static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_r
}
#define REG_A4XX_RB_BLEND_RED 0x000020f0
-#define A4XX_RB_BLEND_RED_UINT__MASK 0x0000ffff
+#define A4XX_RB_BLEND_RED_UINT__MASK 0x000000ff
#define A4XX_RB_BLEND_RED_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_RED_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_RED_UINT__SHIFT) & A4XX_RB_BLEND_RED_UINT__MASK;
}
+#define A4XX_RB_BLEND_RED_SINT__MASK 0x0000ff00
+#define A4XX_RB_BLEND_RED_SINT__SHIFT 8
+static inline uint32_t A4XX_RB_BLEND_RED_SINT(uint32_t val)
+{
+ return ((val) << A4XX_RB_BLEND_RED_SINT__SHIFT) & A4XX_RB_BLEND_RED_SINT__MASK;
+}
#define A4XX_RB_BLEND_RED_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_RED_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_RED_FLOAT(float val)
@@ -1095,12 +1099,18 @@ static inline uint32_t A4XX_RB_BLEND_RED_F32(float val)
}
#define REG_A4XX_RB_BLEND_GREEN 0x000020f2
-#define A4XX_RB_BLEND_GREEN_UINT__MASK 0x0000ffff
+#define A4XX_RB_BLEND_GREEN_UINT__MASK 0x000000ff
#define A4XX_RB_BLEND_GREEN_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_GREEN_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_GREEN_UINT__SHIFT) & A4XX_RB_BLEND_GREEN_UINT__MASK;
}
+#define A4XX_RB_BLEND_GREEN_SINT__MASK 0x0000ff00
+#define A4XX_RB_BLEND_GREEN_SINT__SHIFT 8
+static inline uint32_t A4XX_RB_BLEND_GREEN_SINT(uint32_t val)
+{
+ return ((val) << A4XX_RB_BLEND_GREEN_SINT__SHIFT) & A4XX_RB_BLEND_GREEN_SINT__MASK;
+}
#define A4XX_RB_BLEND_GREEN_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_GREEN_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_GREEN_FLOAT(float val)
@@ -1117,12 +1127,18 @@ static inline uint32_t A4XX_RB_BLEND_GREEN_F32(float val)
}
#define REG_A4XX_RB_BLEND_BLUE 0x000020f4
-#define A4XX_RB_BLEND_BLUE_UINT__MASK 0x0000ffff
+#define A4XX_RB_BLEND_BLUE_UINT__MASK 0x000000ff
#define A4XX_RB_BLEND_BLUE_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_BLUE_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_BLUE_UINT__SHIFT) & A4XX_RB_BLEND_BLUE_UINT__MASK;
}
+#define A4XX_RB_BLEND_BLUE_SINT__MASK 0x0000ff00
+#define A4XX_RB_BLEND_BLUE_SINT__SHIFT 8
+static inline uint32_t A4XX_RB_BLEND_BLUE_SINT(uint32_t val)
+{
+ return ((val) << A4XX_RB_BLEND_BLUE_SINT__SHIFT) & A4XX_RB_BLEND_BLUE_SINT__MASK;
+}
#define A4XX_RB_BLEND_BLUE_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_BLUE_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_BLUE_FLOAT(float val)
@@ -1139,12 +1155,18 @@ static inline uint32_t A4XX_RB_BLEND_BLUE_F32(float val)
}
#define REG_A4XX_RB_BLEND_ALPHA 0x000020f6
-#define A4XX_RB_BLEND_ALPHA_UINT__MASK 0x0000ffff
+#define A4XX_RB_BLEND_ALPHA_UINT__MASK 0x000000ff
#define A4XX_RB_BLEND_ALPHA_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_ALPHA_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_ALPHA_UINT__SHIFT) & A4XX_RB_BLEND_ALPHA_UINT__MASK;
}
+#define A4XX_RB_BLEND_ALPHA_SINT__MASK 0x0000ff00
+#define A4XX_RB_BLEND_ALPHA_SINT__SHIFT 8
+static inline uint32_t A4XX_RB_BLEND_ALPHA_SINT(uint32_t val)
+{
+ return ((val) << A4XX_RB_BLEND_ALPHA_SINT__SHIFT) & A4XX_RB_BLEND_ALPHA_SINT__MASK;
+}
#define A4XX_RB_BLEND_ALPHA_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_ALPHA_FLOAT(float val)
@@ -1348,7 +1370,7 @@ static inline uint32_t A4XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
{
return ((val) << A4XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A4XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
}
-#define A4XX_RB_DEPTH_CONTROL_BF_ENABLE 0x00000080
+#define A4XX_RB_DEPTH_CONTROL_Z_CLAMP_ENABLE 0x00000080
#define A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE 0x00010000
#define A4XX_RB_DEPTH_CONTROL_FORCE_FRAGZ_TO_FS 0x00020000
#define A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE 0x80000000
@@ -2177,11 +2199,23 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)
#define REG_A4XX_CP_DRAW_STATE_ADDR 0x00000232
-#define REG_A4XX_CP_PROTECT_REG_0 0x00000240
-
static inline uint32_t REG_A4XX_CP_PROTECT(uint32_t i0) { return 0x00000240 + 0x1*i0; }
static inline uint32_t REG_A4XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000240 + 0x1*i0; }
+#define A4XX_CP_PROTECT_REG_BASE_ADDR__MASK 0x0001ffff
+#define A4XX_CP_PROTECT_REG_BASE_ADDR__SHIFT 0
+static inline uint32_t A4XX_CP_PROTECT_REG_BASE_ADDR(uint32_t val)
+{
+ return ((val) << A4XX_CP_PROTECT_REG_BASE_ADDR__SHIFT) & A4XX_CP_PROTECT_REG_BASE_ADDR__MASK;
+}
+#define A4XX_CP_PROTECT_REG_MASK_LEN__MASK 0x1f000000
+#define A4XX_CP_PROTECT_REG_MASK_LEN__SHIFT 24
+static inline uint32_t A4XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
+{
+ return ((val) << A4XX_CP_PROTECT_REG_MASK_LEN__SHIFT) & A4XX_CP_PROTECT_REG_MASK_LEN__MASK;
+}
+#define A4XX_CP_PROTECT_REG_TRAP_WRITE 0x20000000
+#define A4XX_CP_PROTECT_REG_TRAP_READ 0x40000000
#define REG_A4XX_CP_PROTECT_CTRL 0x00000250
@@ -2272,7 +2306,7 @@ static inline uint32_t A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
-#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
+#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0000fc00
#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
@@ -2420,7 +2454,7 @@ static inline uint32_t A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
-#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
+#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0000fc00
#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
@@ -3117,6 +3151,8 @@ static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_GS(uint32_t val)
#define REG_A4XX_GRAS_CL_CLIP_CNTL 0x00002000
#define A4XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE 0x00008000
+#define A4XX_GRAS_CL_CLIP_CNTL_ZNEAR_CLIP_DISABLE 0x00010000
+#define A4XX_GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE 0x00020000
#define A4XX_GRAS_CL_CLIP_CNTL_ZERO_GB_SCALE_Z 0x00400000
#define REG_A4XX_GRAS_CLEAR_CNTL 0x00002003
@@ -3253,6 +3289,7 @@ static inline uint32_t A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(float val)
return ((((int32_t)(val * 4.0))) << A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK;
}
#define A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET 0x00000800
+#define A4XX_GRAS_SU_MODE_CONTROL_MSAA_ENABLE 0x00002000
#define A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS 0x00100000
#define REG_A4XX_GRAS_SC_CONTROL 0x0000207b
@@ -3670,6 +3707,8 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
#define REG_A4XX_PC_BINNING_COMMAND 0x00000d00
#define A4XX_PC_BINNING_COMMAND_BINNING_ENABLE 0x00000001
+#define REG_A4XX_PC_TESSFACTOR_ADDR 0x00000d08
+
#define REG_A4XX_PC_DRAWCALL_SETUP_OVERRIDE 0x00000d0c
#define REG_A4XX_PC_PERFCTR_PC_SEL_0 0x00000d10
@@ -3690,6 +3729,20 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
#define REG_A4XX_PC_BIN_BASE 0x000021c0
+#define REG_A4XX_PC_VSTREAM_CONTROL 0x000021c2
+#define A4XX_PC_VSTREAM_CONTROL_SIZE__MASK 0x003f0000
+#define A4XX_PC_VSTREAM_CONTROL_SIZE__SHIFT 16
+static inline uint32_t A4XX_PC_VSTREAM_CONTROL_SIZE(uint32_t val)
+{
+ return ((val) << A4XX_PC_VSTREAM_CONTROL_SIZE__SHIFT) & A4XX_PC_VSTREAM_CONTROL_SIZE__MASK;
+}
+#define A4XX_PC_VSTREAM_CONTROL_N__MASK 0x07c00000
+#define A4XX_PC_VSTREAM_CONTROL_N__SHIFT 22
+static inline uint32_t A4XX_PC_VSTREAM_CONTROL_N(uint32_t val)
+{
+ return ((val) << A4XX_PC_VSTREAM_CONTROL_N__SHIFT) & A4XX_PC_VSTREAM_CONTROL_N__MASK;
+}
+
#define REG_A4XX_PC_PRIM_VTX_CNTL 0x000021c4
#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK 0x0000000f
#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT 0
@@ -3752,12 +3805,8 @@ static inline uint32_t A4XX_PC_HS_PARAM_SPACING(enum a4xx_tess_spacing val)
{
return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK;
}
-#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK 0x01800000
-#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT 23
-static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
-{
- return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK;
-}
+#define A4XX_PC_HS_PARAM_CW 0x00800000
+#define A4XX_PC_HS_PARAM_CONNECTED 0x01000000
#define REG_A4XX_VBIF_VERSION 0x00003000
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index d0d3c7baa8fe..511bc855cc7f 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -113,7 +113,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu)
}
-static void a4xx_me_init(struct msm_gpu *gpu)
+static bool a4xx_me_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb;
@@ -137,7 +137,7 @@ static void a4xx_me_init(struct msm_gpu *gpu)
OUT_RING(ring, 0x00000000);
gpu->funcs->flush(gpu);
- gpu->funcs->idle(gpu);
+ return gpu->funcs->idle(gpu);
}
static int a4xx_hw_init(struct msm_gpu *gpu)
@@ -292,15 +292,20 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
/* clear ME_HALT to start micro engine */
gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
- a4xx_me_init(gpu);
-
- return 0;
+ return a4xx_me_init(gpu) ? 0 : -EINVAL;
}
static void a4xx_recover(struct msm_gpu *gpu)
{
+ int i;
+
adreno_dump_info(gpu);
+ for (i = 0; i < 8; i++) {
+ printk("CP_SCRATCH_REG%d: %u\n", i,
+ gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+ }
+
/* dump registers before resetting gpu, if enabled: */
if (hang_debug)
a4xx_dump(gpu);
@@ -328,17 +333,21 @@ static void a4xx_destroy(struct msm_gpu *gpu)
kfree(a4xx_gpu);
}
-static void a4xx_idle(struct msm_gpu *gpu)
+static bool a4xx_idle(struct msm_gpu *gpu)
{
/* wait for ringbuffer to drain: */
- adreno_idle(gpu);
+ if (!adreno_idle(gpu))
+ return false;
/* then wait for GPU to finish: */
if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
- A4XX_RBBM_STATUS_GPU_BUSY)))
+ A4XX_RBBM_STATUS_GPU_BUSY))) {
DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
+ /* TODO maybe we need to reset GPU here to recover from hang? */
+ return false;
+ }
- /* TODO maybe we need to reset GPU here to recover from hang? */
+ return true;
}
static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
@@ -460,87 +469,13 @@ static void a4xx_show(struct msm_gpu *gpu, struct seq_file *m)
/* Register offset defines for A4XX, in order of enum adreno_regs */
static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
- REG_ADRENO_DEFINE(REG_ADRENO_CP_DEBUG, REG_A4XX_CP_DEBUG),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_WADDR, REG_A4XX_CP_ME_RAM_WADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_DATA, REG_A4XX_CP_ME_RAM_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_DATA,
- REG_A4XX_CP_PFP_UCODE_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_ADDR,
- REG_A4XX_CP_PFP_UCODE_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_WFI_PEND_CTR, REG_A4XX_CP_WFI_PEND_CTR),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
+ REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR),
+ REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_CTRL, REG_A4XX_CP_PROTECT_CTRL),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_CNTL, REG_A4XX_CP_ME_CNTL),
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BASE, REG_A4XX_CP_IB1_BASE),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BUFSZ, REG_A4XX_CP_IB1_BUFSZ),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BASE, REG_A4XX_CP_IB2_BASE),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BUFSZ, REG_A4XX_CP_IB2_BUFSZ),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_TIMESTAMP, REG_AXXX_CP_SCRATCH_REG0),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_RADDR, REG_A4XX_CP_ME_RAM_RADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_ADDR, REG_A4XX_CP_ROQ_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_DATA, REG_A4XX_CP_ROQ_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_ADDR, REG_A4XX_CP_MERCIU_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA, REG_A4XX_CP_MERCIU_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA2, REG_A4XX_CP_MERCIU_DATA2),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_ADDR, REG_A4XX_CP_MEQ_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_DATA, REG_A4XX_CP_MEQ_DATA),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_HW_FAULT, REG_A4XX_CP_HW_FAULT),
- REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_STATUS,
- REG_A4XX_CP_PROTECT_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_ADDR, REG_A4XX_CP_SCRATCH_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_UMSK, REG_A4XX_CP_SCRATCH_UMASK),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_STATUS, REG_A4XX_RBBM_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_CTL,
- REG_A4XX_RBBM_PERFCTR_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
- REG_A4XX_RBBM_PERFCTR_LOAD_CMD0),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
- REG_A4XX_RBBM_PERFCTR_LOAD_CMD1),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2,
- REG_A4XX_RBBM_PERFCTR_LOAD_CMD2),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
- REG_A4XX_RBBM_PERFCTR_PWR_1_LO),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_MASK, REG_A4XX_RBBM_INT_0_MASK),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_STATUS,
- REG_A4XX_RBBM_INT_0_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ERROR_STATUS,
- REG_A4XX_RBBM_AHB_ERROR_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_CMD, REG_A4XX_RBBM_AHB_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_CLOCK_CTL, REG_A4XX_RBBM_CLOCK_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS,
- REG_A4XX_RBBM_AHB_ME_SPLIT_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS,
- REG_A4XX_RBBM_AHB_PFP_SPLIT_STATUS),
- REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_SEL,
- REG_A4XX_VPC_DEBUG_RAM_SEL),
- REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_READ,
- REG_A4XX_VPC_DEBUG_RAM_READ),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_CLEAR_CMD,
- REG_A4XX_RBBM_INT_CLEAR_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_VSC_SIZE_ADDRESS,
- REG_A4XX_VSC_SIZE_ADDRESS),
- REG_ADRENO_DEFINE(REG_ADRENO_VFD_CONTROL_0, REG_A4XX_VFD_CONTROL_0),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
- REG_A4XX_SP_VS_PVT_MEM_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
- REG_A4XX_SP_FS_PVT_MEM_ADDR),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_OBJ_START_REG,
- REG_A4XX_SP_VS_OBJ_START),
- REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_OBJ_START_REG,
- REG_A4XX_SP_FS_OBJ_START),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_RBBM_CTL, REG_A4XX_RBBM_RBBM_CTL),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_SW_RESET_CMD,
- REG_A4XX_RBBM_SW_RESET_CMD),
- REG_ADRENO_DEFINE(REG_ADRENO_UCHE_INVALIDATE0,
- REG_A4XX_UCHE_INVALIDATE0),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
- REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_LO),
- REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
- REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_HI),
};
static void a4xx_dump(struct msm_gpu *gpu)
@@ -587,16 +522,8 @@ static int a4xx_pm_suspend(struct msm_gpu *gpu) {
static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
{
- uint32_t hi, lo, tmp;
-
- tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
- do {
- hi = tmp;
- lo = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
- tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
- } while (tmp != hi);
-
- *value = (((uint64_t)hi) << 32) | lo;
+ *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO,
+ REG_A4XX_RBBM_PERFCTR_CP_0_HI);
return 0;
}
@@ -672,7 +599,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
#endif
}
- if (!gpu->mmu) {
+ if (!gpu->aspace) {
/* TODO we think it is possible to configure the GPU to
* restrict access to VRAM carveout. But the required
* registers are unknown. For now just bail out and
diff --git a/drivers/gpu/drm/msm/adreno/a5xx.xml.h b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
new file mode 100644
index 000000000000..b6fe763ddf34
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
@@ -0,0 +1,3757 @@
+#ifndef A5XX_XML
+#define A5XX_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+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 ( 431 bytes, from 2016-04-26 17:56:44)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
+
+Copyright (C) 2013-2016 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+- Ilia Mirkin <imirkin@alum.mit.edu> (imirkin)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum a5xx_color_fmt {
+ RB5_R8_UNORM = 3,
+ RB5_R4G4B4A4_UNORM = 8,
+ RB5_R5G5B5A1_UNORM = 10,
+ RB5_R5G6B5_UNORM = 14,
+ RB5_R16_FLOAT = 23,
+ RB5_R8G8B8A8_UNORM = 48,
+ RB5_R8G8B8_UNORM = 49,
+ RB5_R8G8B8A8_UINT = 51,
+ RB5_R10G10B10A2_UINT = 58,
+ RB5_R16G16_FLOAT = 69,
+ RB5_R32_FLOAT = 74,
+ RB5_R16G16B16A16_FLOAT = 98,
+ RB5_R32G32_FLOAT = 103,
+ RB5_R32G32B32A32_FLOAT = 130,
+};
+
+enum a5xx_tile_mode {
+ TILE5_LINEAR = 0,
+ TILE5_2 = 2,
+ TILE5_3 = 3,
+};
+
+enum a5xx_vtx_fmt {
+ VFMT5_8_UNORM = 3,
+ VFMT5_8_SNORM = 4,
+ VFMT5_8_UINT = 5,
+ VFMT5_8_SINT = 6,
+ VFMT5_8_8_UNORM = 15,
+ VFMT5_8_8_SNORM = 16,
+ VFMT5_8_8_UINT = 17,
+ VFMT5_8_8_SINT = 18,
+ VFMT5_16_UNORM = 21,
+ VFMT5_16_SNORM = 22,
+ VFMT5_16_FLOAT = 23,
+ VFMT5_16_UINT = 24,
+ VFMT5_16_SINT = 25,
+ VFMT5_8_8_8_UNORM = 33,
+ VFMT5_8_8_8_SNORM = 34,
+ VFMT5_8_8_8_UINT = 35,
+ VFMT5_8_8_8_SINT = 36,
+ VFMT5_8_8_8_8_UNORM = 48,
+ VFMT5_8_8_8_8_SNORM = 50,
+ VFMT5_8_8_8_8_UINT = 51,
+ VFMT5_8_8_8_8_SINT = 52,
+ VFMT5_16_16_UNORM = 67,
+ VFMT5_16_16_SNORM = 68,
+ VFMT5_16_16_FLOAT = 69,
+ VFMT5_16_16_UINT = 70,
+ VFMT5_16_16_SINT = 71,
+ VFMT5_32_UNORM = 72,
+ VFMT5_32_SNORM = 73,
+ VFMT5_32_FLOAT = 74,
+ VFMT5_32_UINT = 75,
+ VFMT5_32_SINT = 76,
+ VFMT5_32_FIXED = 77,
+ VFMT5_16_16_16_UNORM = 88,
+ VFMT5_16_16_16_SNORM = 89,
+ VFMT5_16_16_16_FLOAT = 90,
+ VFMT5_16_16_16_UINT = 91,
+ VFMT5_16_16_16_SINT = 92,
+ VFMT5_16_16_16_16_UNORM = 96,
+ VFMT5_16_16_16_16_SNORM = 97,
+ VFMT5_16_16_16_16_FLOAT = 98,
+ VFMT5_16_16_16_16_UINT = 99,
+ VFMT5_16_16_16_16_SINT = 100,
+ VFMT5_32_32_UNORM = 101,
+ VFMT5_32_32_SNORM = 102,
+ VFMT5_32_32_FLOAT = 103,
+ VFMT5_32_32_UINT = 104,
+ VFMT5_32_32_SINT = 105,
+ VFMT5_32_32_FIXED = 106,
+ VFMT5_32_32_32_UNORM = 112,
+ VFMT5_32_32_32_SNORM = 113,
+ VFMT5_32_32_32_UINT = 114,
+ VFMT5_32_32_32_SINT = 115,
+ VFMT5_32_32_32_FLOAT = 116,
+ VFMT5_32_32_32_FIXED = 117,
+ VFMT5_32_32_32_32_UNORM = 128,
+ VFMT5_32_32_32_32_SNORM = 129,
+ VFMT5_32_32_32_32_FLOAT = 130,
+ VFMT5_32_32_32_32_UINT = 131,
+ VFMT5_32_32_32_32_SINT = 132,
+ VFMT5_32_32_32_32_FIXED = 133,
+};
+
+enum a5xx_tex_fmt {
+ TFMT5_A8_UNORM = 2,
+ TFMT5_8_UNORM = 3,
+ TFMT5_4_4_4_4_UNORM = 8,
+ TFMT5_5_5_5_1_UNORM = 10,
+ TFMT5_5_6_5_UNORM = 14,
+ TFMT5_8_8_UNORM = 15,
+ TFMT5_8_8_SNORM = 16,
+ TFMT5_L8_A8_UNORM = 19,
+ TFMT5_16_FLOAT = 23,
+ TFMT5_8_8_8_8_UNORM = 48,
+ TFMT5_8_8_8_UNORM = 49,
+ TFMT5_8_8_8_SNORM = 50,
+ TFMT5_9_9_9_E5_FLOAT = 53,
+ TFMT5_10_10_10_2_UNORM = 54,
+ TFMT5_11_11_10_FLOAT = 66,
+ TFMT5_16_16_FLOAT = 69,
+ TFMT5_32_FLOAT = 74,
+ TFMT5_16_16_16_16_FLOAT = 98,
+ TFMT5_32_32_FLOAT = 103,
+ TFMT5_32_32_32_32_FLOAT = 130,
+ TFMT5_X8Z24_UNORM = 160,
+};
+
+enum a5xx_tex_fetchsize {
+ TFETCH5_1_BYTE = 0,
+ TFETCH5_2_BYTE = 1,
+ TFETCH5_4_BYTE = 2,
+ TFETCH5_8_BYTE = 3,
+ TFETCH5_16_BYTE = 4,
+};
+
+enum a5xx_depth_format {
+ DEPTH5_NONE = 0,
+ DEPTH5_16 = 1,
+ DEPTH5_24_8 = 2,
+ DEPTH5_32 = 4,
+};
+
+enum a5xx_blit_buf {
+ BLIT_MRT0 = 0,
+ BLIT_MRT1 = 1,
+ BLIT_MRT2 = 2,
+ BLIT_MRT3 = 3,
+ BLIT_MRT4 = 4,
+ BLIT_MRT5 = 5,
+ BLIT_MRT6 = 6,
+ BLIT_MRT7 = 7,
+ BLIT_ZS = 8,
+ BLIT_Z32 = 9,
+};
+
+enum a5xx_tex_filter {
+ A5XX_TEX_NEAREST = 0,
+ A5XX_TEX_LINEAR = 1,
+ A5XX_TEX_ANISO = 2,
+};
+
+enum a5xx_tex_clamp {
+ A5XX_TEX_REPEAT = 0,
+ A5XX_TEX_CLAMP_TO_EDGE = 1,
+ A5XX_TEX_MIRROR_REPEAT = 2,
+ A5XX_TEX_CLAMP_TO_BORDER = 3,
+ A5XX_TEX_MIRROR_CLAMP = 4,
+};
+
+enum a5xx_tex_aniso {
+ A5XX_TEX_ANISO_1 = 0,
+ A5XX_TEX_ANISO_2 = 1,
+ A5XX_TEX_ANISO_4 = 2,
+ A5XX_TEX_ANISO_8 = 3,
+ A5XX_TEX_ANISO_16 = 4,
+};
+
+enum a5xx_tex_swiz {
+ A5XX_TEX_X = 0,
+ A5XX_TEX_Y = 1,
+ A5XX_TEX_Z = 2,
+ A5XX_TEX_W = 3,
+ A5XX_TEX_ZERO = 4,
+ A5XX_TEX_ONE = 5,
+};
+
+enum a5xx_tex_type {
+ A5XX_TEX_1D = 0,
+ A5XX_TEX_2D = 1,
+ A5XX_TEX_CUBE = 2,
+ A5XX_TEX_3D = 3,
+};
+
+#define A5XX_INT0_RBBM_GPU_IDLE 0x00000001
+#define A5XX_INT0_RBBM_AHB_ERROR 0x00000002
+#define A5XX_INT0_RBBM_TRANSFER_TIMEOUT 0x00000004
+#define A5XX_INT0_RBBM_ME_MS_TIMEOUT 0x00000008
+#define A5XX_INT0_RBBM_PFP_MS_TIMEOUT 0x00000010
+#define A5XX_INT0_RBBM_ETS_MS_TIMEOUT 0x00000020
+#define A5XX_INT0_RBBM_ATB_ASYNC_OVERFLOW 0x00000040
+#define A5XX_INT0_RBBM_GPC_ERROR 0x00000080
+#define A5XX_INT0_CP_SW 0x00000100
+#define A5XX_INT0_CP_HW_ERROR 0x00000200
+#define A5XX_INT0_CP_CCU_FLUSH_DEPTH_TS 0x00000400
+#define A5XX_INT0_CP_CCU_FLUSH_COLOR_TS 0x00000800
+#define A5XX_INT0_CP_CCU_RESOLVE_TS 0x00001000
+#define A5XX_INT0_CP_IB2 0x00002000
+#define A5XX_INT0_CP_IB1 0x00004000
+#define A5XX_INT0_CP_RB 0x00008000
+#define A5XX_INT0_CP_UNUSED_1 0x00010000
+#define A5XX_INT0_CP_RB_DONE_TS 0x00020000
+#define A5XX_INT0_CP_WT_DONE_TS 0x00040000
+#define A5XX_INT0_UNKNOWN_1 0x00080000
+#define A5XX_INT0_CP_CACHE_FLUSH_TS 0x00100000
+#define A5XX_INT0_UNUSED_2 0x00200000
+#define A5XX_INT0_RBBM_ATB_BUS_OVERFLOW 0x00400000
+#define A5XX_INT0_MISC_HANG_DETECT 0x00800000
+#define A5XX_INT0_UCHE_OOB_ACCESS 0x01000000
+#define A5XX_INT0_UCHE_TRAP_INTR 0x02000000
+#define A5XX_INT0_DEBBUS_INTR_0 0x04000000
+#define A5XX_INT0_DEBBUS_INTR_1 0x08000000
+#define A5XX_INT0_GPMU_VOLTAGE_DROOP 0x10000000
+#define A5XX_INT0_GPMU_FIRMWARE 0x20000000
+#define A5XX_INT0_ISDB_CPU_IRQ 0x40000000
+#define A5XX_INT0_ISDB_UNDER_DEBUG 0x80000000
+#define A5XX_CP_INT_CP_OPCODE_ERROR 0x00000001
+#define A5XX_CP_INT_CP_RESERVED_BIT_ERROR 0x00000002
+#define A5XX_CP_INT_CP_HW_FAULT_ERROR 0x00000004
+#define A5XX_CP_INT_CP_DMA_ERROR 0x00000008
+#define A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR 0x00000010
+#define A5XX_CP_INT_CP_AHB_ERROR 0x00000020
+#define REG_A5XX_CP_RB_BASE 0x00000800
+
+#define REG_A5XX_CP_RB_BASE_HI 0x00000801
+
+#define REG_A5XX_CP_RB_CNTL 0x00000802
+
+#define REG_A5XX_CP_RB_RPTR_ADDR 0x00000804
+
+#define REG_A5XX_CP_RB_RPTR_ADDR_HI 0x00000805
+
+#define REG_A5XX_CP_RB_RPTR 0x00000806
+
+#define REG_A5XX_CP_RB_WPTR 0x00000807
+
+#define REG_A5XX_CP_PFP_STAT_ADDR 0x00000808
+
+#define REG_A5XX_CP_PFP_STAT_DATA 0x00000809
+
+#define REG_A5XX_CP_DRAW_STATE_ADDR 0x0000080b
+
+#define REG_A5XX_CP_DRAW_STATE_DATA 0x0000080c
+
+#define REG_A5XX_CP_CRASH_SCRIPT_BASE_LO 0x00000817
+
+#define REG_A5XX_CP_CRASH_SCRIPT_BASE_HI 0x00000818
+
+#define REG_A5XX_CP_CRASH_DUMP_CNTL 0x00000819
+
+#define REG_A5XX_CP_ME_STAT_ADDR 0x0000081a
+
+#define REG_A5XX_CP_ROQ_THRESHOLDS_1 0x0000081f
+
+#define REG_A5XX_CP_ROQ_THRESHOLDS_2 0x00000820
+
+#define REG_A5XX_CP_ROQ_DBG_ADDR 0x00000821
+
+#define REG_A5XX_CP_ROQ_DBG_DATA 0x00000822
+
+#define REG_A5XX_CP_MEQ_DBG_ADDR 0x00000823
+
+#define REG_A5XX_CP_MEQ_DBG_DATA 0x00000824
+
+#define REG_A5XX_CP_MEQ_THRESHOLDS 0x00000825
+
+#define REG_A5XX_CP_MERCIU_SIZE 0x00000826
+
+#define REG_A5XX_CP_MERCIU_DBG_ADDR 0x00000827
+
+#define REG_A5XX_CP_MERCIU_DBG_DATA_1 0x00000828
+
+#define REG_A5XX_CP_MERCIU_DBG_DATA_2 0x00000829
+
+#define REG_A5XX_CP_PFP_UCODE_DBG_ADDR 0x0000082a
+
+#define REG_A5XX_CP_PFP_UCODE_DBG_DATA 0x0000082b
+
+#define REG_A5XX_CP_ME_UCODE_DBG_ADDR 0x0000082f
+
+#define REG_A5XX_CP_ME_UCODE_DBG_DATA 0x00000830
+
+#define REG_A5XX_CP_CNTL 0x00000831
+
+#define REG_A5XX_CP_PFP_ME_CNTL 0x00000832
+
+#define REG_A5XX_CP_CHICKEN_DBG 0x00000833
+
+#define REG_A5XX_CP_PFP_INSTR_BASE_LO 0x00000835
+
+#define REG_A5XX_CP_PFP_INSTR_BASE_HI 0x00000836
+
+#define REG_A5XX_CP_ME_INSTR_BASE_LO 0x00000838
+
+#define REG_A5XX_CP_ME_INSTR_BASE_HI 0x00000839
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_CNTL 0x0000083b
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO 0x0000083c
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI 0x0000083d
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO 0x0000083e
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_HI 0x0000083f
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO 0x00000840
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI 0x00000841
+
+#define REG_A5XX_CP_ADDR_MODE_CNTL 0x00000860
+
+#define REG_A5XX_CP_ME_STAT_DATA 0x00000b14
+
+#define REG_A5XX_CP_WFI_PEND_CTR 0x00000b15
+
+#define REG_A5XX_CP_INTERRUPT_STATUS 0x00000b18
+
+#define REG_A5XX_CP_HW_FAULT 0x00000b1a
+
+#define REG_A5XX_CP_PROTECT_STATUS 0x00000b1c
+
+#define REG_A5XX_CP_IB1_BASE 0x00000b1f
+
+#define REG_A5XX_CP_IB1_BASE_HI 0x00000b20
+
+#define REG_A5XX_CP_IB1_BUFSZ 0x00000b21
+
+#define REG_A5XX_CP_IB2_BASE 0x00000b22
+
+#define REG_A5XX_CP_IB2_BASE_HI 0x00000b23
+
+#define REG_A5XX_CP_IB2_BUFSZ 0x00000b24
+
+static inline uint32_t REG_A5XX_CP_SCRATCH(uint32_t i0) { return 0x00000b78 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000b78 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_PROTECT(uint32_t i0) { return 0x00000880 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000880 + 0x1*i0; }
+#define A5XX_CP_PROTECT_REG_BASE_ADDR__MASK 0x0001ffff
+#define A5XX_CP_PROTECT_REG_BASE_ADDR__SHIFT 0
+static inline uint32_t A5XX_CP_PROTECT_REG_BASE_ADDR(uint32_t val)
+{
+ return ((val) << A5XX_CP_PROTECT_REG_BASE_ADDR__SHIFT) & A5XX_CP_PROTECT_REG_BASE_ADDR__MASK;
+}
+#define A5XX_CP_PROTECT_REG_MASK_LEN__MASK 0x1f000000
+#define A5XX_CP_PROTECT_REG_MASK_LEN__SHIFT 24
+static inline uint32_t A5XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
+{
+ return ((val) << A5XX_CP_PROTECT_REG_MASK_LEN__SHIFT) & A5XX_CP_PROTECT_REG_MASK_LEN__MASK;
+}
+#define A5XX_CP_PROTECT_REG_TRAP_WRITE 0x20000000
+#define A5XX_CP_PROTECT_REG_TRAP_READ 0x40000000
+
+#define REG_A5XX_CP_PROTECT_CNTL 0x000008a0
+
+#define REG_A5XX_CP_AHB_FAULT 0x00000b1b
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_0 0x00000bb0
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_1 0x00000bb1
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_2 0x00000bb2
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_3 0x00000bb3
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_4 0x00000bb4
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_5 0x00000bb5
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_6 0x00000bb6
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_7 0x00000bb7
+
+#define REG_A5XX_VSC_ADDR_MODE_CNTL 0x00000bc1
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_0 0x00000bba
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_1 0x00000bbb
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_2 0x00000bbc
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_3 0x00000bbd
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_A 0x00000004
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_B 0x00000005
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_C 0x00000006
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_D 0x00000007
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CNTLT 0x00000008
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CNTLM 0x00000009
+
+#define REG_A5XX_RBBM_CFG_DEBBUS_CTLTM_ENABLE_SHIFT 0x00000018
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OPL 0x0000000a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OPE 0x0000000b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_0 0x0000000c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_1 0x0000000d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_2 0x0000000e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_3 0x0000000f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_0 0x00000010
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_1 0x00000011
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_2 0x00000012
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_3 0x00000013
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_BYTEL_0 0x00000014
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_BYTEL_1 0x00000015
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_0 0x00000016
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_1 0x00000017
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_2 0x00000018
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_3 0x00000019
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_0 0x0000001a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_1 0x0000001b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_2 0x0000001c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_3 0x0000001d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_NIBBLEE 0x0000001e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_PTRC0 0x0000001f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_PTRC1 0x00000020
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_LOADREG 0x00000021
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IDX 0x00000022
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CLRC 0x00000023
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_LOADIVT 0x00000024
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0000002f
+
+#define REG_A5XX_RBBM_INT_CLEAR_CMD 0x00000037
+
+#define REG_A5XX_RBBM_INT_0_MASK 0x00000038
+#define A5XX_RBBM_INT_0_MASK_RBBM_GPU_IDLE 0x00000001
+#define A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR 0x00000002
+#define A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT 0x00000004
+#define A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT 0x00000008
+#define A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT 0x00000010
+#define A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT 0x00000020
+#define A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW 0x00000040
+#define A5XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR 0x00000080
+#define A5XX_RBBM_INT_0_MASK_CP_SW 0x00000100
+#define A5XX_RBBM_INT_0_MASK_CP_HW_ERROR 0x00000200
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_DEPTH_TS 0x00000400
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_COLOR_TS 0x00000800
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_RESOLVE_TS 0x00001000
+#define A5XX_RBBM_INT_0_MASK_CP_IB2 0x00002000
+#define A5XX_RBBM_INT_0_MASK_CP_IB1 0x00004000
+#define A5XX_RBBM_INT_0_MASK_CP_RB 0x00008000
+#define A5XX_RBBM_INT_0_MASK_CP_RB_DONE_TS 0x00020000
+#define A5XX_RBBM_INT_0_MASK_CP_WT_DONE_TS 0x00040000
+#define A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS 0x00100000
+#define A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW 0x00400000
+#define A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT 0x00800000
+#define A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS 0x01000000
+#define A5XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR 0x02000000
+#define A5XX_RBBM_INT_0_MASK_DEBBUS_INTR_0 0x04000000
+#define A5XX_RBBM_INT_0_MASK_DEBBUS_INTR_1 0x08000000
+#define A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP 0x10000000
+#define A5XX_RBBM_INT_0_MASK_GPMU_FIRMWARE 0x20000000
+#define A5XX_RBBM_INT_0_MASK_ISDB_CPU_IRQ 0x40000000
+#define A5XX_RBBM_INT_0_MASK_ISDB_UNDER_DEBUG 0x80000000
+
+#define REG_A5XX_RBBM_AHB_DBG_CNTL 0x0000003f
+
+#define REG_A5XX_RBBM_EXT_VBIF_DBG_CNTL 0x00000041
+
+#define REG_A5XX_RBBM_SW_RESET_CMD 0x00000043
+
+#define REG_A5XX_RBBM_BLOCK_SW_RESET_CMD 0x00000045
+
+#define REG_A5XX_RBBM_BLOCK_SW_RESET_CMD2 0x00000046
+
+#define REG_A5XX_RBBM_DBG_LO_HI_GPIO 0x00000048
+
+#define REG_A5XX_RBBM_EXT_TRACE_BUS_CNTL 0x00000049
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP0 0x0000004a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP1 0x0000004b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP2 0x0000004c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP3 0x0000004d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP0 0x0000004e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP1 0x0000004f
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP2 0x00000050
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP3 0x00000051
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP0 0x00000052
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP1 0x00000053
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP2 0x00000054
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP3 0x00000055
+
+#define REG_A5XX_RBBM_READ_AHB_THROUGH_DBG 0x00000059
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_UCHE 0x0000005a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_UCHE 0x0000005b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_UCHE 0x0000005c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL4_UCHE 0x0000005d
+
+#define REG_A5XX_RBBM_CLOCK_HYST_UCHE 0x0000005e
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_UCHE 0x0000005f
+
+#define REG_A5XX_RBBM_CLOCK_MODE_GPC 0x00000060
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_GPC 0x00000061
+
+#define REG_A5XX_RBBM_CLOCK_HYST_GPC 0x00000062
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM 0x00000063
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM 0x00000064
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM 0x00000065
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_HLSQ 0x00000066
+
+#define REG_A5XX_RBBM_CLOCK_CNTL 0x00000067
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP0 0x00000068
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP1 0x00000069
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP2 0x0000006a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP3 0x0000006b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP0 0x0000006c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP1 0x0000006d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP2 0x0000006e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP3 0x0000006f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP0 0x00000070
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP1 0x00000071
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP2 0x00000072
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP3 0x00000073
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP0 0x00000074
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP1 0x00000075
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP2 0x00000076
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP3 0x00000077
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB0 0x00000078
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB1 0x00000079
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB2 0x0000007a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB3 0x0000007b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB0 0x0000007c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB1 0x0000007d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB2 0x0000007e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB3 0x0000007f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RAC 0x00000080
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RAC 0x00000081
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU0 0x00000082
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU1 0x00000083
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU2 0x00000084
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU3 0x00000085
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0 0x00000086
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1 0x00000087
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2 0x00000088
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3 0x00000089
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RAC 0x0000008a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RAC 0x0000008b
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0 0x0000008c
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1 0x0000008d
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2 0x0000008e
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3 0x0000008f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_VFD 0x00000090
+
+#define REG_A5XX_RBBM_CLOCK_MODE_VFD 0x00000091
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_VFD 0x00000092
+
+#define REG_A5XX_RBBM_AHB_CNTL0 0x00000093
+
+#define REG_A5XX_RBBM_AHB_CNTL1 0x00000094
+
+#define REG_A5XX_RBBM_AHB_CNTL2 0x00000095
+
+#define REG_A5XX_RBBM_AHB_CMD 0x00000096
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11 0x0000009c
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12 0x0000009d
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13 0x0000009e
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14 0x0000009f
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15 0x000000a0
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16 0x000000a1
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17 0x000000a2
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18 0x000000a3
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP0 0x000000a4
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP1 0x000000a5
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP2 0x000000a6
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP3 0x000000a7
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP0 0x000000a8
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP1 0x000000a9
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP2 0x000000aa
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP3 0x000000ab
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP0 0x000000ac
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP1 0x000000ad
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP2 0x000000ae
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP3 0x000000af
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP0 0x000000b0
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP1 0x000000b1
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP2 0x000000b2
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP3 0x000000b3
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP0 0x000000b4
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP1 0x000000b5
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP2 0x000000b6
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP3 0x000000b7
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP0 0x000000b8
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP1 0x000000b9
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP2 0x000000ba
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP3 0x000000bb
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_GPMU 0x000000c8
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_GPMU 0x000000c9
+
+#define REG_A5XX_RBBM_CLOCK_HYST_GPMU 0x000000ca
+
+#define REG_A5XX_RBBM_PERFCTR_CP_0_LO 0x000003a0
+
+#define REG_A5XX_RBBM_PERFCTR_CP_0_HI 0x000003a1
+
+#define REG_A5XX_RBBM_PERFCTR_CP_1_LO 0x000003a2
+
+#define REG_A5XX_RBBM_PERFCTR_CP_1_HI 0x000003a3
+
+#define REG_A5XX_RBBM_PERFCTR_CP_2_LO 0x000003a4
+
+#define REG_A5XX_RBBM_PERFCTR_CP_2_HI 0x000003a5
+
+#define REG_A5XX_RBBM_PERFCTR_CP_3_LO 0x000003a6
+
+#define REG_A5XX_RBBM_PERFCTR_CP_3_HI 0x000003a7
+
+#define REG_A5XX_RBBM_PERFCTR_CP_4_LO 0x000003a8
+
+#define REG_A5XX_RBBM_PERFCTR_CP_4_HI 0x000003a9
+
+#define REG_A5XX_RBBM_PERFCTR_CP_5_LO 0x000003aa
+
+#define REG_A5XX_RBBM_PERFCTR_CP_5_HI 0x000003ab
+
+#define REG_A5XX_RBBM_PERFCTR_CP_6_LO 0x000003ac
+
+#define REG_A5XX_RBBM_PERFCTR_CP_6_HI 0x000003ad
+
+#define REG_A5XX_RBBM_PERFCTR_CP_7_LO 0x000003ae
+
+#define REG_A5XX_RBBM_PERFCTR_CP_7_HI 0x000003af
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_0_LO 0x000003b0
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_0_HI 0x000003b1
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_1_LO 0x000003b2
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_1_HI 0x000003b3
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_2_LO 0x000003b4
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_2_HI 0x000003b5
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_3_LO 0x000003b6
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_3_HI 0x000003b7
+
+#define REG_A5XX_RBBM_PERFCTR_PC_0_LO 0x000003b8
+
+#define REG_A5XX_RBBM_PERFCTR_PC_0_HI 0x000003b9
+
+#define REG_A5XX_RBBM_PERFCTR_PC_1_LO 0x000003ba
+
+#define REG_A5XX_RBBM_PERFCTR_PC_1_HI 0x000003bb
+
+#define REG_A5XX_RBBM_PERFCTR_PC_2_LO 0x000003bc
+
+#define REG_A5XX_RBBM_PERFCTR_PC_2_HI 0x000003bd
+
+#define REG_A5XX_RBBM_PERFCTR_PC_3_LO 0x000003be
+
+#define REG_A5XX_RBBM_PERFCTR_PC_3_HI 0x000003bf
+
+#define REG_A5XX_RBBM_PERFCTR_PC_4_LO 0x000003c0
+
+#define REG_A5XX_RBBM_PERFCTR_PC_4_HI 0x000003c1
+
+#define REG_A5XX_RBBM_PERFCTR_PC_5_LO 0x000003c2
+
+#define REG_A5XX_RBBM_PERFCTR_PC_5_HI 0x000003c3
+
+#define REG_A5XX_RBBM_PERFCTR_PC_6_LO 0x000003c4
+
+#define REG_A5XX_RBBM_PERFCTR_PC_6_HI 0x000003c5
+
+#define REG_A5XX_RBBM_PERFCTR_PC_7_LO 0x000003c6
+
+#define REG_A5XX_RBBM_PERFCTR_PC_7_HI 0x000003c7
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_0_LO 0x000003c8
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_0_HI 0x000003c9
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_1_LO 0x000003ca
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_1_HI 0x000003cb
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_2_LO 0x000003cc
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_2_HI 0x000003cd
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_3_LO 0x000003ce
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_3_HI 0x000003cf
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_4_LO 0x000003d0
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_4_HI 0x000003d1
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_5_LO 0x000003d2
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_5_HI 0x000003d3
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_6_LO 0x000003d4
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_6_HI 0x000003d5
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_7_LO 0x000003d6
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_7_HI 0x000003d7
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_0_LO 0x000003d8
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_0_HI 0x000003d9
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_1_LO 0x000003da
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_1_HI 0x000003db
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_2_LO 0x000003dc
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_2_HI 0x000003dd
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_3_LO 0x000003de
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_3_HI 0x000003df
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_4_LO 0x000003e0
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_4_HI 0x000003e1
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_5_LO 0x000003e2
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_5_HI 0x000003e3
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_6_LO 0x000003e4
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_6_HI 0x000003e5
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_7_LO 0x000003e6
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_7_HI 0x000003e7
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_0_LO 0x000003e8
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_0_HI 0x000003e9
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_1_LO 0x000003ea
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_1_HI 0x000003eb
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_2_LO 0x000003ec
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_2_HI 0x000003ed
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_3_LO 0x000003ee
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_3_HI 0x000003ef
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_0_LO 0x000003f0
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_0_HI 0x000003f1
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_1_LO 0x000003f2
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_1_HI 0x000003f3
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_2_LO 0x000003f4
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_2_HI 0x000003f5
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_3_LO 0x000003f6
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_3_HI 0x000003f7
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_0_LO 0x000003f8
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_0_HI 0x000003f9
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_1_LO 0x000003fa
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_1_HI 0x000003fb
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_2_LO 0x000003fc
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_2_HI 0x000003fd
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_3_LO 0x000003fe
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_3_HI 0x000003ff
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_0_LO 0x00000400
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_0_HI 0x00000401
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_1_LO 0x00000402
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_1_HI 0x00000403
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_2_LO 0x00000404
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_2_HI 0x00000405
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_3_LO 0x00000406
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_3_HI 0x00000407
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_0_LO 0x00000408
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_0_HI 0x00000409
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_1_LO 0x0000040a
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_1_HI 0x0000040b
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_2_LO 0x0000040c
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_2_HI 0x0000040d
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_3_LO 0x0000040e
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_3_HI 0x0000040f
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_4_LO 0x00000410
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_4_HI 0x00000411
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_5_LO 0x00000412
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_5_HI 0x00000413
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_6_LO 0x00000414
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_6_HI 0x00000415
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_7_LO 0x00000416
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_7_HI 0x00000417
+
+#define REG_A5XX_RBBM_PERFCTR_TP_0_LO 0x00000418
+
+#define REG_A5XX_RBBM_PERFCTR_TP_0_HI 0x00000419
+
+#define REG_A5XX_RBBM_PERFCTR_TP_1_LO 0x0000041a
+
+#define REG_A5XX_RBBM_PERFCTR_TP_1_HI 0x0000041b
+
+#define REG_A5XX_RBBM_PERFCTR_TP_2_LO 0x0000041c
+
+#define REG_A5XX_RBBM_PERFCTR_TP_2_HI 0x0000041d
+
+#define REG_A5XX_RBBM_PERFCTR_TP_3_LO 0x0000041e
+
+#define REG_A5XX_RBBM_PERFCTR_TP_3_HI 0x0000041f
+
+#define REG_A5XX_RBBM_PERFCTR_TP_4_LO 0x00000420
+
+#define REG_A5XX_RBBM_PERFCTR_TP_4_HI 0x00000421
+
+#define REG_A5XX_RBBM_PERFCTR_TP_5_LO 0x00000422
+
+#define REG_A5XX_RBBM_PERFCTR_TP_5_HI 0x00000423
+
+#define REG_A5XX_RBBM_PERFCTR_TP_6_LO 0x00000424
+
+#define REG_A5XX_RBBM_PERFCTR_TP_6_HI 0x00000425
+
+#define REG_A5XX_RBBM_PERFCTR_TP_7_LO 0x00000426
+
+#define REG_A5XX_RBBM_PERFCTR_TP_7_HI 0x00000427
+
+#define REG_A5XX_RBBM_PERFCTR_SP_0_LO 0x00000428
+
+#define REG_A5XX_RBBM_PERFCTR_SP_0_HI 0x00000429
+
+#define REG_A5XX_RBBM_PERFCTR_SP_1_LO 0x0000042a
+
+#define REG_A5XX_RBBM_PERFCTR_SP_1_HI 0x0000042b
+
+#define REG_A5XX_RBBM_PERFCTR_SP_2_LO 0x0000042c
+
+#define REG_A5XX_RBBM_PERFCTR_SP_2_HI 0x0000042d
+
+#define REG_A5XX_RBBM_PERFCTR_SP_3_LO 0x0000042e
+
+#define REG_A5XX_RBBM_PERFCTR_SP_3_HI 0x0000042f
+
+#define REG_A5XX_RBBM_PERFCTR_SP_4_LO 0x00000430
+
+#define REG_A5XX_RBBM_PERFCTR_SP_4_HI 0x00000431
+
+#define REG_A5XX_RBBM_PERFCTR_SP_5_LO 0x00000432
+
+#define REG_A5XX_RBBM_PERFCTR_SP_5_HI 0x00000433
+
+#define REG_A5XX_RBBM_PERFCTR_SP_6_LO 0x00000434
+
+#define REG_A5XX_RBBM_PERFCTR_SP_6_HI 0x00000435
+
+#define REG_A5XX_RBBM_PERFCTR_SP_7_LO 0x00000436
+
+#define REG_A5XX_RBBM_PERFCTR_SP_7_HI 0x00000437
+
+#define REG_A5XX_RBBM_PERFCTR_SP_8_LO 0x00000438
+
+#define REG_A5XX_RBBM_PERFCTR_SP_8_HI 0x00000439
+
+#define REG_A5XX_RBBM_PERFCTR_SP_9_LO 0x0000043a
+
+#define REG_A5XX_RBBM_PERFCTR_SP_9_HI 0x0000043b
+
+#define REG_A5XX_RBBM_PERFCTR_SP_10_LO 0x0000043c
+
+#define REG_A5XX_RBBM_PERFCTR_SP_10_HI 0x0000043d
+
+#define REG_A5XX_RBBM_PERFCTR_SP_11_LO 0x0000043e
+
+#define REG_A5XX_RBBM_PERFCTR_SP_11_HI 0x0000043f
+
+#define REG_A5XX_RBBM_PERFCTR_RB_0_LO 0x00000440
+
+#define REG_A5XX_RBBM_PERFCTR_RB_0_HI 0x00000441
+
+#define REG_A5XX_RBBM_PERFCTR_RB_1_LO 0x00000442
+
+#define REG_A5XX_RBBM_PERFCTR_RB_1_HI 0x00000443
+
+#define REG_A5XX_RBBM_PERFCTR_RB_2_LO 0x00000444
+
+#define REG_A5XX_RBBM_PERFCTR_RB_2_HI 0x00000445
+
+#define REG_A5XX_RBBM_PERFCTR_RB_3_LO 0x00000446
+
+#define REG_A5XX_RBBM_PERFCTR_RB_3_HI 0x00000447
+
+#define REG_A5XX_RBBM_PERFCTR_RB_4_LO 0x00000448
+
+#define REG_A5XX_RBBM_PERFCTR_RB_4_HI 0x00000449
+
+#define REG_A5XX_RBBM_PERFCTR_RB_5_LO 0x0000044a
+
+#define REG_A5XX_RBBM_PERFCTR_RB_5_HI 0x0000044b
+
+#define REG_A5XX_RBBM_PERFCTR_RB_6_LO 0x0000044c
+
+#define REG_A5XX_RBBM_PERFCTR_RB_6_HI 0x0000044d
+
+#define REG_A5XX_RBBM_PERFCTR_RB_7_LO 0x0000044e
+
+#define REG_A5XX_RBBM_PERFCTR_RB_7_HI 0x0000044f
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_0_LO 0x00000450
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_0_HI 0x00000451
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_1_LO 0x00000452
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_1_HI 0x00000453
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_0_LO 0x00000454
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_0_HI 0x00000455
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_1_LO 0x00000456
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_1_HI 0x00000457
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_2_LO 0x00000458
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_2_HI 0x00000459
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_3_LO 0x0000045a
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_3_HI 0x0000045b
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_0_LO 0x0000045c
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_0_HI 0x0000045d
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_1_LO 0x0000045e
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_1_HI 0x0000045f
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_2_LO 0x00000460
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_2_HI 0x00000461
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_3_LO 0x00000462
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_3_HI 0x00000463
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0 0x0000046b
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_1 0x0000046c
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_2 0x0000046d
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_3 0x0000046e
+
+#define REG_A5XX_RBBM_ALWAYSON_COUNTER_LO 0x000004d2
+
+#define REG_A5XX_RBBM_ALWAYSON_COUNTER_HI 0x000004d3
+
+#define REG_A5XX_RBBM_STATUS 0x000004f5
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB 0x80000000
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB_CP 0x40000000
+#define A5XX_RBBM_STATUS_HLSQ_BUSY 0x20000000
+#define A5XX_RBBM_STATUS_VSC_BUSY 0x10000000
+#define A5XX_RBBM_STATUS_TPL1_BUSY 0x08000000
+#define A5XX_RBBM_STATUS_SP_BUSY 0x04000000
+#define A5XX_RBBM_STATUS_UCHE_BUSY 0x02000000
+#define A5XX_RBBM_STATUS_VPC_BUSY 0x01000000
+#define A5XX_RBBM_STATUS_VFDP_BUSY 0x00800000
+#define A5XX_RBBM_STATUS_VFD_BUSY 0x00400000
+#define A5XX_RBBM_STATUS_TESS_BUSY 0x00200000
+#define A5XX_RBBM_STATUS_PC_VSD_BUSY 0x00100000
+#define A5XX_RBBM_STATUS_PC_DCALL_BUSY 0x00080000
+#define A5XX_RBBM_STATUS_GPMU_SLAVE_BUSY 0x00040000
+#define A5XX_RBBM_STATUS_DCOM_BUSY 0x00020000
+#define A5XX_RBBM_STATUS_COM_BUSY 0x00010000
+#define A5XX_RBBM_STATUS_LRZ_BUZY 0x00008000
+#define A5XX_RBBM_STATUS_A2D_DSP_BUSY 0x00004000
+#define A5XX_RBBM_STATUS_CCUFCHE_BUSY 0x00002000
+#define A5XX_RBBM_STATUS_RB_BUSY 0x00001000
+#define A5XX_RBBM_STATUS_RAS_BUSY 0x00000800
+#define A5XX_RBBM_STATUS_TSE_BUSY 0x00000400
+#define A5XX_RBBM_STATUS_VBIF_BUSY 0x00000200
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB_HYST 0x00000100
+#define A5XX_RBBM_STATUS_CP_BUSY_IGN_HYST 0x00000080
+#define A5XX_RBBM_STATUS_CP_BUSY 0x00000040
+#define A5XX_RBBM_STATUS_GPMU_MASTER_BUSY 0x00000020
+#define A5XX_RBBM_STATUS_CP_CRASH_BUSY 0x00000010
+#define A5XX_RBBM_STATUS_CP_ETS_BUSY 0x00000008
+#define A5XX_RBBM_STATUS_CP_PFP_BUSY 0x00000004
+#define A5XX_RBBM_STATUS_CP_ME_BUSY 0x00000002
+#define A5XX_RBBM_STATUS_HI_BUSY 0x00000001
+
+#define REG_A5XX_RBBM_STATUS3 0x00000530
+
+#define REG_A5XX_RBBM_INT_0_STATUS 0x000004e1
+
+#define REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS 0x000004f0
+
+#define REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS 0x000004f1
+
+#define REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS 0x000004f3
+
+#define REG_A5XX_RBBM_AHB_ERROR_STATUS 0x000004f4
+
+#define REG_A5XX_RBBM_PERFCTR_CNTL 0x00000464
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD0 0x00000465
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD1 0x00000466
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD2 0x00000467
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD3 0x00000468
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_VALUE_LO 0x00000469
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_VALUE_HI 0x0000046a
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0 0x0000046b
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_1 0x0000046c
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_2 0x0000046d
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_3 0x0000046e
+
+#define REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED 0x0000046f
+
+#define REG_A5XX_RBBM_AHB_ERROR 0x000004ed
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_EVENT_LOGIC 0x00000504
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OVER 0x00000505
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT0 0x00000506
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT1 0x00000507
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT2 0x00000508
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT3 0x00000509
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT4 0x0000050a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT5 0x0000050b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_ADDR 0x0000050c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF0 0x0000050d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF1 0x0000050e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF2 0x0000050f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF3 0x00000510
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF4 0x00000511
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MISR0 0x00000512
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MISR1 0x00000513
+
+#define REG_A5XX_RBBM_ISDB_CNT 0x00000533
+
+#define REG_A5XX_RBBM_SECVID_TRUST_CONFIG 0x0000f000
+
+#define REG_A5XX_RBBM_SECVID_TRUST_CNTL 0x0000f400
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO 0x0000f800
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI 0x0000f801
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE 0x0000f802
+
+#define REG_A5XX_RBBM_SECVID_TSB_CNTL 0x0000f803
+
+#define REG_A5XX_RBBM_SECVID_TSB_COMP_STATUS_LO 0x0000f804
+
+#define REG_A5XX_RBBM_SECVID_TSB_COMP_STATUS_HI 0x0000f805
+
+#define REG_A5XX_RBBM_SECVID_TSB_UCHE_STATUS_LO 0x0000f806
+
+#define REG_A5XX_RBBM_SECVID_TSB_UCHE_STATUS_HI 0x0000f807
+
+#define REG_A5XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL 0x0000f810
+
+#define REG_A5XX_VSC_PIPE_DATA_LENGTH_0 0x00000c00
+
+#define REG_A5XX_VSC_PERFCTR_VSC_SEL_0 0x00000c60
+
+#define REG_A5XX_VSC_PERFCTR_VSC_SEL_1 0x00000c61
+
+#define REG_A5XX_VSC_BIN_SIZE 0x00000cdd
+#define A5XX_VSC_BIN_SIZE_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_VSC_BIN_SIZE_X__MASK 0x00007fff
+#define A5XX_VSC_BIN_SIZE_X__SHIFT 0
+static inline uint32_t A5XX_VSC_BIN_SIZE_X(uint32_t val)
+{
+ return ((val) << A5XX_VSC_BIN_SIZE_X__SHIFT) & A5XX_VSC_BIN_SIZE_X__MASK;
+}
+#define A5XX_VSC_BIN_SIZE_Y__MASK 0x7fff0000
+#define A5XX_VSC_BIN_SIZE_Y__SHIFT 16
+static inline uint32_t A5XX_VSC_BIN_SIZE_Y(uint32_t val)
+{
+ return ((val) << A5XX_VSC_BIN_SIZE_Y__SHIFT) & A5XX_VSC_BIN_SIZE_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_ADDR_MODE_CNTL 0x00000c81
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_0 0x00000c90
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_1 0x00000c91
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_2 0x00000c92
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_3 0x00000c93
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_0 0x00000c94
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_1 0x00000c95
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_2 0x00000c96
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_3 0x00000c97
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_0 0x00000c98
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_1 0x00000c99
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_2 0x00000c9a
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_3 0x00000c9b
+
+#define REG_A5XX_RB_DBG_ECO_CNTL 0x00000cc4
+
+#define REG_A5XX_RB_ADDR_MODE_CNTL 0x00000cc5
+
+#define REG_A5XX_RB_MODE_CNTL 0x00000cc6
+
+#define REG_A5XX_RB_CCU_CNTL 0x00000cc7
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_0 0x00000cd0
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_1 0x00000cd1
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_2 0x00000cd2
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_3 0x00000cd3
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_4 0x00000cd4
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_5 0x00000cd5
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_6 0x00000cd6
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_7 0x00000cd7
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_0 0x00000cd8
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_1 0x00000cd9
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_2 0x00000cda
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_3 0x00000cdb
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_0 0x00000ce0
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_1 0x00000ce1
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_2 0x00000ce2
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_3 0x00000ce3
+
+#define REG_A5XX_RB_POWERCTR_CCU_SEL_0 0x00000ce4
+
+#define REG_A5XX_RB_POWERCTR_CCU_SEL_1 0x00000ce5
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_0 0x00000cec
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_1 0x00000ced
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_2 0x00000cee
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_3 0x00000cef
+
+#define REG_A5XX_PC_DBG_ECO_CNTL 0x00000d00
+#define A5XX_PC_DBG_ECO_CNTL_TWOPASSUSEWFI 0x00000100
+
+#define REG_A5XX_PC_ADDR_MODE_CNTL 0x00000d01
+
+#define REG_A5XX_PC_MODE_CNTL 0x00000d02
+
+#define REG_A5XX_UNKNOWN_0D08 0x00000d08
+
+#define REG_A5XX_UNKNOWN_0D09 0x00000d09
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_0 0x00000d10
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_1 0x00000d11
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_2 0x00000d12
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_3 0x00000d13
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_4 0x00000d14
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_5 0x00000d15
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_6 0x00000d16
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_7 0x00000d17
+
+#define REG_A5XX_HLSQ_TIMEOUT_THRESHOLD_0 0x00000e00
+
+#define REG_A5XX_HLSQ_TIMEOUT_THRESHOLD_1 0x00000e01
+
+#define REG_A5XX_HLSQ_ADDR_MODE_CNTL 0x00000e05
+
+#define REG_A5XX_HLSQ_MODE_CNTL 0x00000e06
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_0 0x00000e10
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_1 0x00000e11
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_2 0x00000e12
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_3 0x00000e13
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_4 0x00000e14
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_5 0x00000e15
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_6 0x00000e16
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_7 0x00000e17
+
+#define REG_A5XX_HLSQ_SPTP_RDSEL 0x00000f08
+
+#define REG_A5XX_HLSQ_DBG_READ_SEL 0x0000bc00
+
+#define REG_A5XX_HLSQ_DBG_AHB_READ_APERTURE 0x0000a000
+
+#define REG_A5XX_VFD_ADDR_MODE_CNTL 0x00000e41
+
+#define REG_A5XX_VFD_MODE_CNTL 0x00000e42
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_0 0x00000e50
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_1 0x00000e51
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_2 0x00000e52
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_3 0x00000e53
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_4 0x00000e54
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_5 0x00000e55
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_6 0x00000e56
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_7 0x00000e57
+
+#define REG_A5XX_VPC_DBG_ECO_CNTL 0x00000e60
+
+#define REG_A5XX_VPC_ADDR_MODE_CNTL 0x00000e61
+
+#define REG_A5XX_VPC_MODE_CNTL 0x00000e62
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_0 0x00000e64
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_1 0x00000e65
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_2 0x00000e66
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_3 0x00000e67
+
+#define REG_A5XX_UCHE_ADDR_MODE_CNTL 0x00000e80
+
+#define REG_A5XX_UCHE_SVM_CNTL 0x00000e82
+
+#define REG_A5XX_UCHE_WRITE_THRU_BASE_LO 0x00000e87
+
+#define REG_A5XX_UCHE_WRITE_THRU_BASE_HI 0x00000e88
+
+#define REG_A5XX_UCHE_TRAP_BASE_LO 0x00000e89
+
+#define REG_A5XX_UCHE_TRAP_BASE_HI 0x00000e8a
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MIN_LO 0x00000e8b
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MIN_HI 0x00000e8c
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MAX_LO 0x00000e8d
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MAX_HI 0x00000e8e
+
+#define REG_A5XX_UCHE_DBG_ECO_CNTL_2 0x00000e8f
+
+#define REG_A5XX_UCHE_DBG_ECO_CNTL 0x00000e90
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MIN_LO 0x00000e91
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MIN_HI 0x00000e92
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MAX_LO 0x00000e93
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MAX_HI 0x00000e94
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE 0x00000e95
+
+#define REG_A5XX_UCHE_CACHE_WAYS 0x00000e96
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_0 0x00000ea0
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_1 0x00000ea1
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_2 0x00000ea2
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_3 0x00000ea3
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_4 0x00000ea4
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_5 0x00000ea5
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_6 0x00000ea6
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_7 0x00000ea7
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_0 0x00000ea8
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_1 0x00000ea9
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_2 0x00000eaa
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_3 0x00000eab
+
+#define REG_A5XX_UCHE_TRAP_LOG_LO 0x00000eb1
+
+#define REG_A5XX_UCHE_TRAP_LOG_HI 0x00000eb2
+
+#define REG_A5XX_SP_DBG_ECO_CNTL 0x00000ec0
+
+#define REG_A5XX_SP_ADDR_MODE_CNTL 0x00000ec1
+
+#define REG_A5XX_SP_MODE_CNTL 0x00000ec2
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_0 0x00000ed0
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_1 0x00000ed1
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_2 0x00000ed2
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_3 0x00000ed3
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_4 0x00000ed4
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_5 0x00000ed5
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_6 0x00000ed6
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_7 0x00000ed7
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_8 0x00000ed8
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_9 0x00000ed9
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_10 0x00000eda
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_11 0x00000edb
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_0 0x00000edc
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_1 0x00000edd
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_2 0x00000ede
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_3 0x00000edf
+
+#define REG_A5XX_TPL1_ADDR_MODE_CNTL 0x00000f01
+
+#define REG_A5XX_TPL1_MODE_CNTL 0x00000f02
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_0 0x00000f10
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_1 0x00000f11
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_2 0x00000f12
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_3 0x00000f13
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_4 0x00000f14
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_5 0x00000f15
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_6 0x00000f16
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_7 0x00000f17
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_0 0x00000f18
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_1 0x00000f19
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_2 0x00000f1a
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_3 0x00000f1b
+
+#define REG_A5XX_VBIF_VERSION 0x00003000
+
+#define REG_A5XX_VBIF_CLKON 0x00003001
+
+#define REG_A5XX_VBIF_ABIT_SORT 0x00003028
+
+#define REG_A5XX_VBIF_ABIT_SORT_CONF 0x00003029
+
+#define REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB 0x00003049
+
+#define REG_A5XX_VBIF_GATE_OFF_WRREQ_EN 0x0000302a
+
+#define REG_A5XX_VBIF_IN_RD_LIM_CONF0 0x0000302c
+
+#define REG_A5XX_VBIF_IN_RD_LIM_CONF1 0x0000302d
+
+#define REG_A5XX_VBIF_XIN_HALT_CTRL0 0x00003080
+
+#define REG_A5XX_VBIF_XIN_HALT_CTRL1 0x00003081
+
+#define REG_A5XX_VBIF_TEST_BUS_OUT_CTRL 0x00003084
+
+#define REG_A5XX_VBIF_TEST_BUS1_CTRL0 0x00003085
+
+#define REG_A5XX_VBIF_TEST_BUS1_CTRL1 0x00003086
+
+#define REG_A5XX_VBIF_TEST_BUS2_CTRL0 0x00003087
+
+#define REG_A5XX_VBIF_TEST_BUS2_CTRL1 0x00003088
+
+#define REG_A5XX_VBIF_TEST_BUS_OUT 0x0000308c
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL0 0x000030d0
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL1 0x000030d1
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL2 0x000030d2
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL3 0x000030d3
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW0 0x000030d8
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW1 0x000030d9
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW2 0x000030da
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW3 0x000030db
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH0 0x000030e0
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH1 0x000030e1
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH2 0x000030e2
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH3 0x000030e3
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN0 0x00003100
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN1 0x00003101
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN2 0x00003102
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW0 0x00003110
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW1 0x00003111
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW2 0x00003112
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH0 0x00003118
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH1 0x00003119
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH2 0x0000311a
+
+#define REG_A5XX_GPMU_INST_RAM_BASE 0x00008800
+
+#define REG_A5XX_GPMU_DATA_RAM_BASE 0x00009800
+
+#define REG_A5XX_GPMU_SP_POWER_CNTL 0x0000a881
+
+#define REG_A5XX_GPMU_RBCCU_CLOCK_CNTL 0x0000a886
+
+#define REG_A5XX_GPMU_RBCCU_POWER_CNTL 0x0000a887
+
+#define REG_A5XX_GPMU_SP_PWR_CLK_STATUS 0x0000a88b
+#define A5XX_GPMU_SP_PWR_CLK_STATUS_PWR_ON 0x00100000
+
+#define REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS 0x0000a88d
+#define A5XX_GPMU_RBCCU_PWR_CLK_STATUS_PWR_ON 0x00100000
+
+#define REG_A5XX_GPMU_PWR_COL_STAGGER_DELAY 0x0000a891
+
+#define REG_A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL 0x0000a892
+
+#define REG_A5XX_GPMU_PWR_COL_INTER_FRAME_HYST 0x0000a893
+
+#define REG_A5XX_GPMU_PWR_COL_BINNING_CTRL 0x0000a894
+
+#define REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL 0x0000a8a3
+
+#define REG_A5XX_GPMU_WFI_CONFIG 0x0000a8c1
+
+#define REG_A5XX_GPMU_RBBM_INTR_INFO 0x0000a8d6
+
+#define REG_A5XX_GPMU_CM3_SYSRESET 0x0000a8d8
+
+#define REG_A5XX_GPMU_GENERAL_0 0x0000a8e0
+
+#define REG_A5XX_GPMU_GENERAL_1 0x0000a8e1
+
+#define REG_A5XX_SP_POWER_COUNTER_0_LO 0x0000a840
+
+#define REG_A5XX_SP_POWER_COUNTER_0_HI 0x0000a841
+
+#define REG_A5XX_SP_POWER_COUNTER_1_LO 0x0000a842
+
+#define REG_A5XX_SP_POWER_COUNTER_1_HI 0x0000a843
+
+#define REG_A5XX_SP_POWER_COUNTER_2_LO 0x0000a844
+
+#define REG_A5XX_SP_POWER_COUNTER_2_HI 0x0000a845
+
+#define REG_A5XX_SP_POWER_COUNTER_3_LO 0x0000a846
+
+#define REG_A5XX_SP_POWER_COUNTER_3_HI 0x0000a847
+
+#define REG_A5XX_TP_POWER_COUNTER_0_LO 0x0000a848
+
+#define REG_A5XX_TP_POWER_COUNTER_0_HI 0x0000a849
+
+#define REG_A5XX_TP_POWER_COUNTER_1_LO 0x0000a84a
+
+#define REG_A5XX_TP_POWER_COUNTER_1_HI 0x0000a84b
+
+#define REG_A5XX_TP_POWER_COUNTER_2_LO 0x0000a84c
+
+#define REG_A5XX_TP_POWER_COUNTER_2_HI 0x0000a84d
+
+#define REG_A5XX_TP_POWER_COUNTER_3_LO 0x0000a84e
+
+#define REG_A5XX_TP_POWER_COUNTER_3_HI 0x0000a84f
+
+#define REG_A5XX_RB_POWER_COUNTER_0_LO 0x0000a850
+
+#define REG_A5XX_RB_POWER_COUNTER_0_HI 0x0000a851
+
+#define REG_A5XX_RB_POWER_COUNTER_1_LO 0x0000a852
+
+#define REG_A5XX_RB_POWER_COUNTER_1_HI 0x0000a853
+
+#define REG_A5XX_RB_POWER_COUNTER_2_LO 0x0000a854
+
+#define REG_A5XX_RB_POWER_COUNTER_2_HI 0x0000a855
+
+#define REG_A5XX_RB_POWER_COUNTER_3_LO 0x0000a856
+
+#define REG_A5XX_RB_POWER_COUNTER_3_HI 0x0000a857
+
+#define REG_A5XX_CCU_POWER_COUNTER_0_LO 0x0000a858
+
+#define REG_A5XX_CCU_POWER_COUNTER_0_HI 0x0000a859
+
+#define REG_A5XX_CCU_POWER_COUNTER_1_LO 0x0000a85a
+
+#define REG_A5XX_CCU_POWER_COUNTER_1_HI 0x0000a85b
+
+#define REG_A5XX_UCHE_POWER_COUNTER_0_LO 0x0000a85c
+
+#define REG_A5XX_UCHE_POWER_COUNTER_0_HI 0x0000a85d
+
+#define REG_A5XX_UCHE_POWER_COUNTER_1_LO 0x0000a85e
+
+#define REG_A5XX_UCHE_POWER_COUNTER_1_HI 0x0000a85f
+
+#define REG_A5XX_UCHE_POWER_COUNTER_2_LO 0x0000a860
+
+#define REG_A5XX_UCHE_POWER_COUNTER_2_HI 0x0000a861
+
+#define REG_A5XX_UCHE_POWER_COUNTER_3_LO 0x0000a862
+
+#define REG_A5XX_UCHE_POWER_COUNTER_3_HI 0x0000a863
+
+#define REG_A5XX_CP_POWER_COUNTER_0_LO 0x0000a864
+
+#define REG_A5XX_CP_POWER_COUNTER_0_HI 0x0000a865
+
+#define REG_A5XX_CP_POWER_COUNTER_1_LO 0x0000a866
+
+#define REG_A5XX_CP_POWER_COUNTER_1_HI 0x0000a867
+
+#define REG_A5XX_CP_POWER_COUNTER_2_LO 0x0000a868
+
+#define REG_A5XX_CP_POWER_COUNTER_2_HI 0x0000a869
+
+#define REG_A5XX_CP_POWER_COUNTER_3_LO 0x0000a86a
+
+#define REG_A5XX_CP_POWER_COUNTER_3_HI 0x0000a86b
+
+#define REG_A5XX_GPMU_POWER_COUNTER_0_LO 0x0000a86c
+
+#define REG_A5XX_GPMU_POWER_COUNTER_0_HI 0x0000a86d
+
+#define REG_A5XX_GPMU_POWER_COUNTER_1_LO 0x0000a86e
+
+#define REG_A5XX_GPMU_POWER_COUNTER_1_HI 0x0000a86f
+
+#define REG_A5XX_GPMU_POWER_COUNTER_2_LO 0x0000a870
+
+#define REG_A5XX_GPMU_POWER_COUNTER_2_HI 0x0000a871
+
+#define REG_A5XX_GPMU_POWER_COUNTER_3_LO 0x0000a872
+
+#define REG_A5XX_GPMU_POWER_COUNTER_3_HI 0x0000a873
+
+#define REG_A5XX_GPMU_POWER_COUNTER_4_LO 0x0000a874
+
+#define REG_A5XX_GPMU_POWER_COUNTER_4_HI 0x0000a875
+
+#define REG_A5XX_GPMU_POWER_COUNTER_5_LO 0x0000a876
+
+#define REG_A5XX_GPMU_POWER_COUNTER_5_HI 0x0000a877
+
+#define REG_A5XX_GPMU_POWER_COUNTER_ENABLE 0x0000a878
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_LO 0x0000a879
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_HI 0x0000a87a
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_RESET 0x0000a87b
+
+#define REG_A5XX_GPMU_POWER_COUNTER_SELECT_0 0x0000a87c
+
+#define REG_A5XX_GPMU_POWER_COUNTER_SELECT_1 0x0000a87d
+
+#define REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL 0x0000a8a3
+
+#define REG_A5XX_GPMU_THROTTLE_UNMASK_FORCE_CTRL 0x0000a8a8
+
+#define REG_A5XX_GPMU_TEMP_SENSOR_ID 0x0000ac00
+
+#define REG_A5XX_GPMU_TEMP_SENSOR_CONFIG 0x0000ac01
+
+#define REG_A5XX_GPMU_TEMP_VAL 0x0000ac02
+
+#define REG_A5XX_GPMU_DELTA_TEMP_THRESHOLD 0x0000ac03
+
+#define REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_STATUS 0x0000ac05
+
+#define REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK 0x0000ac06
+
+#define REG_A5XX_GPMU_LEAKAGE_TEMP_COEFF_0_1 0x0000ac40
+
+#define REG_A5XX_GPMU_LEAKAGE_TEMP_COEFF_2_3 0x0000ac41
+
+#define REG_A5XX_GPMU_LEAKAGE_VTG_COEFF_0_1 0x0000ac42
+
+#define REG_A5XX_GPMU_LEAKAGE_VTG_COEFF_2_3 0x0000ac43
+
+#define REG_A5XX_GPMU_BASE_LEAKAGE 0x0000ac46
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE 0x0000ac60
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_STATUS 0x0000ac61
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK 0x0000ac62
+
+#define REG_A5XX_GPMU_GPMU_PWR_THRESHOLD 0x0000ac80
+
+#define REG_A5XX_GPMU_GPMU_LLM_GLM_SLEEP_CTRL 0x0000acc4
+
+#define REG_A5XX_GPMU_GPMU_LLM_GLM_SLEEP_STATUS 0x0000acc5
+
+#define REG_A5XX_GDPM_CONFIG1 0x0000b80c
+
+#define REG_A5XX_GDPM_CONFIG2 0x0000b80d
+
+#define REG_A5XX_GDPM_INT_EN 0x0000b80f
+
+#define REG_A5XX_GDPM_INT_MASK 0x0000b811
+
+#define REG_A5XX_GPMU_BEC_ENABLE 0x0000b9a0
+
+#define REG_A5XX_GPU_CS_SENSOR_GENERAL_STATUS 0x0000c41a
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_0 0x0000c41d
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_2 0x0000c41f
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_4 0x0000c421
+
+#define REG_A5XX_GPU_CS_ENABLE_REG 0x0000c520
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_CONTROL1 0x0000c557
+
+#define REG_A5XX_GRAS_CL_CNTL 0x0000e000
+
+#define REG_A5XX_UNKNOWN_E001 0x0000e001
+
+#define REG_A5XX_UNKNOWN_E004 0x0000e004
+
+#define REG_A5XX_GRAS_CNTL 0x0000e005
+#define A5XX_GRAS_CNTL_VARYING 0x00000001
+
+#define REG_A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ 0x0000e006
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__MASK 0x000003ff
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__SHIFT) & A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__MASK;
+}
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__MASK 0x000ffc00
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__SHIFT 10
+static inline uint32_t A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__SHIFT) & A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_XOFFSET_0 0x0000e010
+#define A5XX_GRAS_CL_VPORT_XOFFSET_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_XOFFSET_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_XOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_XSCALE_0 0x0000e011
+#define A5XX_GRAS_CL_VPORT_XSCALE_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_XSCALE_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_XSCALE_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_XSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_XSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_YOFFSET_0 0x0000e012
+#define A5XX_GRAS_CL_VPORT_YOFFSET_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_YOFFSET_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_YOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_YSCALE_0 0x0000e013
+#define A5XX_GRAS_CL_VPORT_YSCALE_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_YSCALE_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_YSCALE_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_YSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_YSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_ZOFFSET_0 0x0000e014
+#define A5XX_GRAS_CL_VPORT_ZOFFSET_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_ZOFFSET_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_ZOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_ZSCALE_0 0x0000e015
+#define A5XX_GRAS_CL_VPORT_ZSCALE_0__MASK 0xffffffff
+#define A5XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT 0
+static inline uint32_t A5XX_GRAS_CL_VPORT_ZSCALE_0(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_ZSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_CNTL 0x0000e090
+#define A5XX_GRAS_SU_CNTL_FRONT_CW 0x00000004
+#define A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK 0x000007f8
+#define A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__SHIFT 3
+static inline uint32_t A5XX_GRAS_SU_CNTL_LINEHALFWIDTH(float val)
+{
+ return ((((int32_t)(val * 4.0))) << A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__SHIFT) & A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK;
+}
+#define A5XX_GRAS_SU_CNTL_POLY_OFFSET 0x00000800
+#define A5XX_GRAS_SU_CNTL_MSAA_ENABLE 0x00002000
+
+#define REG_A5XX_GRAS_SU_POINT_MINMAX 0x0000e091
+#define A5XX_GRAS_SU_POINT_MINMAX_MIN__MASK 0x0000ffff
+#define A5XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_POINT_MINMAX_MIN(float val)
+{
+ return ((((uint32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A5XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
+}
+#define A5XX_GRAS_SU_POINT_MINMAX_MAX__MASK 0xffff0000
+#define A5XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT 16
+static inline uint32_t A5XX_GRAS_SU_POINT_MINMAX_MAX(float val)
+{
+ return ((((uint32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A5XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POINT_SIZE 0x0000e092
+#define A5XX_GRAS_SU_POINT_SIZE__MASK 0xffffffff
+#define A5XX_GRAS_SU_POINT_SIZE__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_POINT_SIZE(float val)
+{
+ return ((((int32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_SIZE__SHIFT) & A5XX_GRAS_SU_POINT_SIZE__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E093 0x0000e093
+
+#define REG_A5XX_GRAS_SU_DEPTH_PLANE_CNTL 0x0000e094
+#define A5XX_GRAS_SU_DEPTH_PLANE_CNTL_ALPHA_TEST_ENABLE 0x00000001
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_SCALE 0x0000e095
+#define A5XX_GRAS_SU_POLY_OFFSET_SCALE__MASK 0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_SCALE(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_SCALE__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000e096
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK 0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP 0x0000e097
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__MASK 0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(float val)
+{
+ return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO 0x0000e098
+#define A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK 0x00000007
+#define A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT 0
+static inline uint32_t A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(enum a5xx_depth_format val)
+{
+ return ((val) << A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT) & A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_CONSERVATIVE_RAS_CNTL 0x0000e099
+
+#define REG_A5XX_GRAS_SC_CNTL 0x0000e0a0
+#define A5XX_GRAS_SC_CNTL_SAMPLES_PASSED 0x00008000
+
+#define REG_A5XX_GRAS_SC_BIN_CNTL 0x0000e0a1
+
+#define REG_A5XX_GRAS_SC_RAS_MSAA_CNTL 0x0000e0a2
+#define A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_DEST_MSAA_CNTL 0x0000e0a3
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE 0x00000004
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_CNTL 0x0000e0a4
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0 0x0000e0aa
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__MASK;
+}
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0 0x0000e0ab
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__MASK;
+}
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0 0x0000e0ca
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__MASK;
+}
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0 0x0000e0cb
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__MASK;
+}
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL 0x0000e0ea
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK;
+}
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_WINDOW_SCISSOR_BR 0x0000e0eb
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK 0x00007fff
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT 0
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK;
+}
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK 0x7fff0000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT 16
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
+{
+ return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_LRZ_CNTL 0x0000e100
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_BASE_LO 0x0000e101
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_BASE_HI 0x0000e102
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_PITCH 0x0000e103
+
+#define REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO 0x0000e104
+
+#define REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI 0x0000e105
+
+#define REG_A5XX_RB_CNTL 0x0000e140
+#define A5XX_RB_CNTL_WIDTH__MASK 0x000000ff
+#define A5XX_RB_CNTL_WIDTH__SHIFT 0
+static inline uint32_t A5XX_RB_CNTL_WIDTH(uint32_t val)
+{
+ return ((val >> 5) << A5XX_RB_CNTL_WIDTH__SHIFT) & A5XX_RB_CNTL_WIDTH__MASK;
+}
+#define A5XX_RB_CNTL_HEIGHT__MASK 0x0001fe00
+#define A5XX_RB_CNTL_HEIGHT__SHIFT 9
+static inline uint32_t A5XX_RB_CNTL_HEIGHT(uint32_t val)
+{
+ return ((val >> 5) << A5XX_RB_CNTL_HEIGHT__SHIFT) & A5XX_RB_CNTL_HEIGHT__MASK;
+}
+#define A5XX_RB_CNTL_BYPASS 0x00020000
+
+#define REG_A5XX_RB_RENDER_CNTL 0x0000e141
+#define A5XX_RB_RENDER_CNTL_SAMPLES_PASSED 0x00000040
+#define A5XX_RB_RENDER_CNTL_FLAG_DEPTH 0x00004000
+#define A5XX_RB_RENDER_CNTL_FLAG_DEPTH2 0x00008000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS__MASK 0x00ff0000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT 16
+static inline uint32_t A5XX_RB_RENDER_CNTL_FLAG_MRTS(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT) & A5XX_RB_RENDER_CNTL_FLAG_MRTS__MASK;
+}
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS2__MASK 0xff000000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS2__SHIFT 24
+static inline uint32_t A5XX_RB_RENDER_CNTL_FLAG_MRTS2(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_CNTL_FLAG_MRTS2__SHIFT) & A5XX_RB_RENDER_CNTL_FLAG_MRTS2__MASK;
+}
+
+#define REG_A5XX_RB_RAS_MSAA_CNTL 0x0000e142
+#define A5XX_RB_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_RB_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_RB_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_RB_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_RB_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_RB_DEST_MSAA_CNTL 0x0000e143
+#define A5XX_RB_DEST_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_RB_DEST_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_RB_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_RB_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_RB_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE 0x00000004
+
+#define REG_A5XX_RB_RENDER_CONTROL0 0x0000e144
+#define A5XX_RB_RENDER_CONTROL0_VARYING 0x00000001
+#define A5XX_RB_RENDER_CONTROL0_XCOORD 0x00000040
+#define A5XX_RB_RENDER_CONTROL0_YCOORD 0x00000080
+#define A5XX_RB_RENDER_CONTROL0_ZCOORD 0x00000100
+#define A5XX_RB_RENDER_CONTROL0_WCOORD 0x00000200
+
+#define REG_A5XX_RB_RENDER_CONTROL1 0x0000e145
+#define A5XX_RB_RENDER_CONTROL1_FACENESS 0x00000002
+
+#define REG_A5XX_RB_FS_OUTPUT_CNTL 0x0000e146
+#define A5XX_RB_FS_OUTPUT_CNTL_MRT__MASK 0x0000000f
+#define A5XX_RB_FS_OUTPUT_CNTL_MRT__SHIFT 0
+static inline uint32_t A5XX_RB_FS_OUTPUT_CNTL_MRT(uint32_t val)
+{
+ return ((val) << A5XX_RB_FS_OUTPUT_CNTL_MRT__SHIFT) & A5XX_RB_FS_OUTPUT_CNTL_MRT__MASK;
+}
+#define A5XX_RB_FS_OUTPUT_CNTL_FRAG_WRITES_Z 0x00000020
+
+#define REG_A5XX_RB_RENDER_COMPONENTS 0x0000e147
+#define A5XX_RB_RENDER_COMPONENTS_RT0__MASK 0x0000000f
+#define A5XX_RB_RENDER_COMPONENTS_RT0__SHIFT 0
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT0__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT1__MASK 0x000000f0
+#define A5XX_RB_RENDER_COMPONENTS_RT1__SHIFT 4
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT1(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT1__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT2__MASK 0x00000f00
+#define A5XX_RB_RENDER_COMPONENTS_RT2__SHIFT 8
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT2(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT2__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT3__MASK 0x0000f000
+#define A5XX_RB_RENDER_COMPONENTS_RT3__SHIFT 12
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT3(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT3__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT4__MASK 0x000f0000
+#define A5XX_RB_RENDER_COMPONENTS_RT4__SHIFT 16
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT4(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT4__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT5__MASK 0x00f00000
+#define A5XX_RB_RENDER_COMPONENTS_RT5__SHIFT 20
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT5(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT5__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT6__MASK 0x0f000000
+#define A5XX_RB_RENDER_COMPONENTS_RT6__SHIFT 24
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT6(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT6__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT7__MASK 0xf0000000
+#define A5XX_RB_RENDER_COMPONENTS_RT7__SHIFT 28
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT7(uint32_t val)
+{
+ return ((val) << A5XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT7__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT(uint32_t i0) { return 0x0000e150 + 0x7*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_CONTROL(uint32_t i0) { return 0x0000e150 + 0x7*i0; }
+#define A5XX_RB_MRT_CONTROL_BLEND 0x00000001
+#define A5XX_RB_MRT_CONTROL_BLEND2 0x00000002
+#define A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK 0x00000780
+#define A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT 7
+static inline uint32_t A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE(uint32_t val)
+{
+ return ((val) << A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT) & A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BLEND_CONTROL(uint32_t i0) { return 0x0000e151 + 0x7*i0; }
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK 0x0000001f
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_blend_factor val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK 0x000000e0
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT 5
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK 0x00001f00
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT 8
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(enum adreno_rb_blend_factor val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK 0x001f0000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT 16
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb_blend_factor val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK 0x00e00000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT 21
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK 0x1f000000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT 24
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_rb_blend_factor val)
+{
+ return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BUF_INFO(uint32_t i0) { return 0x0000e152 + 0x7*i0; }
+#define A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK 0x00000300
+#define A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT 8
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a5xx_tile_mode val)
+{
+ return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK 0x00006000
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT 13
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00008000
+
+static inline uint32_t REG_A5XX_RB_MRT_PITCH(uint32_t i0) { return 0x0000e153 + 0x7*i0; }
+#define A5XX_RB_MRT_PITCH__MASK 0xffffffff
+#define A5XX_RB_MRT_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_MRT_PITCH__SHIFT) & A5XX_RB_MRT_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_ARRAY_PITCH(uint32_t i0) { return 0x0000e154 + 0x7*i0; }
+#define A5XX_RB_MRT_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_MRT_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_MRT_ARRAY_PITCH__SHIFT) & A5XX_RB_MRT_ARRAY_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BASE_LO(uint32_t i0) { return 0x0000e155 + 0x7*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_BASE_HI(uint32_t i0) { return 0x0000e156 + 0x7*i0; }
+
+#define REG_A5XX_RB_BLEND_RED 0x0000e1a0
+#define A5XX_RB_BLEND_RED_UINT__MASK 0x000000ff
+#define A5XX_RB_BLEND_RED_UINT__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_RED_UINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_RED_UINT__SHIFT) & A5XX_RB_BLEND_RED_UINT__MASK;
+}
+#define A5XX_RB_BLEND_RED_SINT__MASK 0x0000ff00
+#define A5XX_RB_BLEND_RED_SINT__SHIFT 8
+static inline uint32_t A5XX_RB_BLEND_RED_SINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_RED_SINT__SHIFT) & A5XX_RB_BLEND_RED_SINT__MASK;
+}
+#define A5XX_RB_BLEND_RED_FLOAT__MASK 0xffff0000
+#define A5XX_RB_BLEND_RED_FLOAT__SHIFT 16
+static inline uint32_t A5XX_RB_BLEND_RED_FLOAT(float val)
+{
+ return ((util_float_to_half(val)) << A5XX_RB_BLEND_RED_FLOAT__SHIFT) & A5XX_RB_BLEND_RED_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_RED_F32 0x0000e1a1
+#define A5XX_RB_BLEND_RED_F32__MASK 0xffffffff
+#define A5XX_RB_BLEND_RED_F32__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_RED_F32(float val)
+{
+ return ((fui(val)) << A5XX_RB_BLEND_RED_F32__SHIFT) & A5XX_RB_BLEND_RED_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_GREEN 0x0000e1a2
+#define A5XX_RB_BLEND_GREEN_UINT__MASK 0x000000ff
+#define A5XX_RB_BLEND_GREEN_UINT__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_GREEN_UINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_GREEN_UINT__SHIFT) & A5XX_RB_BLEND_GREEN_UINT__MASK;
+}
+#define A5XX_RB_BLEND_GREEN_SINT__MASK 0x0000ff00
+#define A5XX_RB_BLEND_GREEN_SINT__SHIFT 8
+static inline uint32_t A5XX_RB_BLEND_GREEN_SINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_GREEN_SINT__SHIFT) & A5XX_RB_BLEND_GREEN_SINT__MASK;
+}
+#define A5XX_RB_BLEND_GREEN_FLOAT__MASK 0xffff0000
+#define A5XX_RB_BLEND_GREEN_FLOAT__SHIFT 16
+static inline uint32_t A5XX_RB_BLEND_GREEN_FLOAT(float val)
+{
+ return ((util_float_to_half(val)) << A5XX_RB_BLEND_GREEN_FLOAT__SHIFT) & A5XX_RB_BLEND_GREEN_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_GREEN_F32 0x0000e1a3
+#define A5XX_RB_BLEND_GREEN_F32__MASK 0xffffffff
+#define A5XX_RB_BLEND_GREEN_F32__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_GREEN_F32(float val)
+{
+ return ((fui(val)) << A5XX_RB_BLEND_GREEN_F32__SHIFT) & A5XX_RB_BLEND_GREEN_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_BLUE 0x0000e1a4
+#define A5XX_RB_BLEND_BLUE_UINT__MASK 0x000000ff
+#define A5XX_RB_BLEND_BLUE_UINT__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_BLUE_UINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_BLUE_UINT__SHIFT) & A5XX_RB_BLEND_BLUE_UINT__MASK;
+}
+#define A5XX_RB_BLEND_BLUE_SINT__MASK 0x0000ff00
+#define A5XX_RB_BLEND_BLUE_SINT__SHIFT 8
+static inline uint32_t A5XX_RB_BLEND_BLUE_SINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_BLUE_SINT__SHIFT) & A5XX_RB_BLEND_BLUE_SINT__MASK;
+}
+#define A5XX_RB_BLEND_BLUE_FLOAT__MASK 0xffff0000
+#define A5XX_RB_BLEND_BLUE_FLOAT__SHIFT 16
+static inline uint32_t A5XX_RB_BLEND_BLUE_FLOAT(float val)
+{
+ return ((util_float_to_half(val)) << A5XX_RB_BLEND_BLUE_FLOAT__SHIFT) & A5XX_RB_BLEND_BLUE_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_BLUE_F32 0x0000e1a5
+#define A5XX_RB_BLEND_BLUE_F32__MASK 0xffffffff
+#define A5XX_RB_BLEND_BLUE_F32__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_BLUE_F32(float val)
+{
+ return ((fui(val)) << A5XX_RB_BLEND_BLUE_F32__SHIFT) & A5XX_RB_BLEND_BLUE_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_ALPHA 0x0000e1a6
+#define A5XX_RB_BLEND_ALPHA_UINT__MASK 0x000000ff
+#define A5XX_RB_BLEND_ALPHA_UINT__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_ALPHA_UINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_ALPHA_UINT__SHIFT) & A5XX_RB_BLEND_ALPHA_UINT__MASK;
+}
+#define A5XX_RB_BLEND_ALPHA_SINT__MASK 0x0000ff00
+#define A5XX_RB_BLEND_ALPHA_SINT__SHIFT 8
+static inline uint32_t A5XX_RB_BLEND_ALPHA_SINT(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_ALPHA_SINT__SHIFT) & A5XX_RB_BLEND_ALPHA_SINT__MASK;
+}
+#define A5XX_RB_BLEND_ALPHA_FLOAT__MASK 0xffff0000
+#define A5XX_RB_BLEND_ALPHA_FLOAT__SHIFT 16
+static inline uint32_t A5XX_RB_BLEND_ALPHA_FLOAT(float val)
+{
+ return ((util_float_to_half(val)) << A5XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A5XX_RB_BLEND_ALPHA_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_ALPHA_F32 0x0000e1a7
+#define A5XX_RB_BLEND_ALPHA_F32__MASK 0xffffffff
+#define A5XX_RB_BLEND_ALPHA_F32__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_ALPHA_F32(float val)
+{
+ return ((fui(val)) << A5XX_RB_BLEND_ALPHA_F32__SHIFT) & A5XX_RB_BLEND_ALPHA_F32__MASK;
+}
+
+#define REG_A5XX_RB_ALPHA_CONTROL 0x0000e1a8
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK 0x000000ff
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT 0
+static inline uint32_t A5XX_RB_ALPHA_CONTROL_ALPHA_REF(uint32_t val)
+{
+ return ((val) << A5XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT) & A5XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK;
+}
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST 0x00000100
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK 0x00000e00
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT 9
+static inline uint32_t A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare_func val)
+{
+ return ((val) << A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_CNTL 0x0000e1a9
+#define A5XX_RB_BLEND_CNTL_ENABLE_BLEND__MASK 0x000000ff
+#define A5XX_RB_BLEND_CNTL_ENABLE_BLEND__SHIFT 0
+static inline uint32_t A5XX_RB_BLEND_CNTL_ENABLE_BLEND(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_CNTL_ENABLE_BLEND__SHIFT) & A5XX_RB_BLEND_CNTL_ENABLE_BLEND__MASK;
+}
+#define A5XX_RB_BLEND_CNTL_INDEPENDENT_BLEND 0x00000100
+#define A5XX_RB_BLEND_CNTL_SAMPLE_MASK__MASK 0xffff0000
+#define A5XX_RB_BLEND_CNTL_SAMPLE_MASK__SHIFT 16
+static inline uint32_t A5XX_RB_BLEND_CNTL_SAMPLE_MASK(uint32_t val)
+{
+ return ((val) << A5XX_RB_BLEND_CNTL_SAMPLE_MASK__SHIFT) & A5XX_RB_BLEND_CNTL_SAMPLE_MASK__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_PLANE_CNTL 0x0000e1b0
+#define A5XX_RB_DEPTH_PLANE_CNTL_FRAG_WRITES_Z 0x00000001
+
+#define REG_A5XX_RB_DEPTH_CNTL 0x0000e1b1
+#define A5XX_RB_DEPTH_CNTL_Z_ENABLE 0x00000001
+#define A5XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE 0x00000002
+#define A5XX_RB_DEPTH_CNTL_ZFUNC__MASK 0x0000001c
+#define A5XX_RB_DEPTH_CNTL_ZFUNC__SHIFT 2
+static inline uint32_t A5XX_RB_DEPTH_CNTL_ZFUNC(enum adreno_compare_func val)
+{
+ return ((val) << A5XX_RB_DEPTH_CNTL_ZFUNC__SHIFT) & A5XX_RB_DEPTH_CNTL_ZFUNC__MASK;
+}
+#define A5XX_RB_DEPTH_CNTL_Z_TEST_ENABLE 0x00000040
+
+#define REG_A5XX_RB_DEPTH_BUFFER_INFO 0x0000e1b2
+#define A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK 0x00000007
+#define A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT 0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(enum a5xx_depth_format val)
+{
+ return ((val) << A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT) & A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_BUFFER_BASE_LO 0x0000e1b3
+
+#define REG_A5XX_RB_DEPTH_BUFFER_BASE_HI 0x0000e1b4
+
+#define REG_A5XX_RB_DEPTH_BUFFER_PITCH 0x0000e1b5
+#define A5XX_RB_DEPTH_BUFFER_PITCH__MASK 0xffffffff
+#define A5XX_RB_DEPTH_BUFFER_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_PITCH(uint32_t val)
+{
+ return ((val >> 5) << A5XX_RB_DEPTH_BUFFER_PITCH__SHIFT) & A5XX_RB_DEPTH_BUFFER_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH 0x0000e1b6
+#define A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 5) << A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__SHIFT) & A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_CONTROL 0x0000e1c0
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE 0x00000001
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF 0x00000002
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_READ 0x00000004
+#define A5XX_RB_STENCIL_CONTROL_FUNC__MASK 0x00000700
+#define A5XX_RB_STENCIL_CONTROL_FUNC__SHIFT 8
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FUNC(enum adreno_compare_func val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_FUNC__SHIFT) & A5XX_RB_STENCIL_CONTROL_FUNC__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FAIL__MASK 0x00003800
+#define A5XX_RB_STENCIL_CONTROL_FAIL__SHIFT 11
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FAIL(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_FAIL__SHIFT) & A5XX_RB_STENCIL_CONTROL_FAIL__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZPASS__MASK 0x0001c000
+#define A5XX_RB_STENCIL_CONTROL_ZPASS__SHIFT 14
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZPASS(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_ZPASS__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZPASS__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL__MASK 0x000e0000
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT 17
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZFAIL(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZFAIL__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FUNC_BF__MASK 0x00700000
+#define A5XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT 20
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FUNC_BF(enum adreno_compare_func val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_FUNC_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FAIL_BF__MASK 0x03800000
+#define A5XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT 23
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FAIL_BF(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_FAIL_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK 0x1c000000
+#define A5XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT 26
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZPASS_BF(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK 0xe0000000
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT 29
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op val)
+{
+ return ((val) << A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_INFO 0x0000e1c1
+#define A5XX_RB_STENCIL_INFO_SEPARATE_STENCIL 0x00000001
+
+#define REG_A5XX_RB_STENCIL_BASE_LO 0x0000e1c2
+
+#define REG_A5XX_RB_STENCIL_BASE_HI 0x0000e1c3
+
+#define REG_A5XX_RB_STENCIL_PITCH 0x0000e1c4
+#define A5XX_RB_STENCIL_PITCH__MASK 0xffffffff
+#define A5XX_RB_STENCIL_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_STENCIL_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_STENCIL_PITCH__SHIFT) & A5XX_RB_STENCIL_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_ARRAY_PITCH 0x0000e1c5
+#define A5XX_RB_STENCIL_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_STENCIL_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_STENCIL_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_STENCIL_ARRAY_PITCH__SHIFT) & A5XX_RB_STENCIL_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCILREFMASK 0x0000e1c6
+#define A5XX_RB_STENCILREFMASK_STENCILREF__MASK 0x000000ff
+#define A5XX_RB_STENCILREFMASK_STENCILREF__SHIFT 0
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILREF(uint32_t val)
+{
+ return ((val) << A5XX_RB_STENCILREFMASK_STENCILREF__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILREF__MASK;
+}
+#define A5XX_RB_STENCILREFMASK_STENCILMASK__MASK 0x0000ff00
+#define A5XX_RB_STENCILREFMASK_STENCILMASK__SHIFT 8
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILMASK(uint32_t val)
+{
+ return ((val) << A5XX_RB_STENCILREFMASK_STENCILMASK__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILMASK__MASK;
+}
+#define A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK 0x00ff0000
+#define A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT 16
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILWRITEMASK(uint32_t val)
+{
+ return ((val) << A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E1C7 0x0000e1c7
+
+#define REG_A5XX_RB_WINDOW_OFFSET 0x0000e1d0
+#define A5XX_RB_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_RB_WINDOW_OFFSET_X__MASK 0x00007fff
+#define A5XX_RB_WINDOW_OFFSET_X__SHIFT 0
+static inline uint32_t A5XX_RB_WINDOW_OFFSET_X(uint32_t val)
+{
+ return ((val) << A5XX_RB_WINDOW_OFFSET_X__SHIFT) & A5XX_RB_WINDOW_OFFSET_X__MASK;
+}
+#define A5XX_RB_WINDOW_OFFSET_Y__MASK 0x7fff0000
+#define A5XX_RB_WINDOW_OFFSET_Y__SHIFT 16
+static inline uint32_t A5XX_RB_WINDOW_OFFSET_Y(uint32_t val)
+{
+ return ((val) << A5XX_RB_WINDOW_OFFSET_Y__SHIFT) & A5XX_RB_WINDOW_OFFSET_Y__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_CNTL 0x0000e210
+#define A5XX_RB_BLIT_CNTL_BUF__MASK 0x0000003f
+#define A5XX_RB_BLIT_CNTL_BUF__SHIFT 0
+static inline uint32_t A5XX_RB_BLIT_CNTL_BUF(enum a5xx_blit_buf val)
+{
+ return ((val) << A5XX_RB_BLIT_CNTL_BUF__SHIFT) & A5XX_RB_BLIT_CNTL_BUF__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_1 0x0000e211
+#define A5XX_RB_RESOLVE_CNTL_1_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_RB_RESOLVE_CNTL_1_X__MASK 0x00007fff
+#define A5XX_RB_RESOLVE_CNTL_1_X__SHIFT 0
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_1_X(uint32_t val)
+{
+ return ((val) << A5XX_RB_RESOLVE_CNTL_1_X__SHIFT) & A5XX_RB_RESOLVE_CNTL_1_X__MASK;
+}
+#define A5XX_RB_RESOLVE_CNTL_1_Y__MASK 0x7fff0000
+#define A5XX_RB_RESOLVE_CNTL_1_Y__SHIFT 16
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_1_Y(uint32_t val)
+{
+ return ((val) << A5XX_RB_RESOLVE_CNTL_1_Y__SHIFT) & A5XX_RB_RESOLVE_CNTL_1_Y__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_2 0x0000e212
+#define A5XX_RB_RESOLVE_CNTL_2_WINDOW_OFFSET_DISABLE 0x80000000
+#define A5XX_RB_RESOLVE_CNTL_2_X__MASK 0x00007fff
+#define A5XX_RB_RESOLVE_CNTL_2_X__SHIFT 0
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_2_X(uint32_t val)
+{
+ return ((val) << A5XX_RB_RESOLVE_CNTL_2_X__SHIFT) & A5XX_RB_RESOLVE_CNTL_2_X__MASK;
+}
+#define A5XX_RB_RESOLVE_CNTL_2_Y__MASK 0x7fff0000
+#define A5XX_RB_RESOLVE_CNTL_2_Y__SHIFT 16
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_2_Y(uint32_t val)
+{
+ return ((val) << A5XX_RB_RESOLVE_CNTL_2_Y__SHIFT) & A5XX_RB_RESOLVE_CNTL_2_Y__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_3 0x0000e213
+
+#define REG_A5XX_RB_BLIT_DST_LO 0x0000e214
+
+#define REG_A5XX_RB_BLIT_DST_HI 0x0000e215
+
+#define REG_A5XX_RB_BLIT_DST_PITCH 0x0000e216
+#define A5XX_RB_BLIT_DST_PITCH__MASK 0xffffffff
+#define A5XX_RB_BLIT_DST_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_BLIT_DST_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_BLIT_DST_PITCH__SHIFT) & A5XX_RB_BLIT_DST_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_DST_ARRAY_PITCH 0x0000e217
+#define A5XX_RB_BLIT_DST_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_BLIT_DST_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_BLIT_DST_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_BLIT_DST_ARRAY_PITCH__SHIFT) & A5XX_RB_BLIT_DST_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW0 0x0000e218
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW1 0x0000e219
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW2 0x0000e21a
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW3 0x0000e21b
+
+#define REG_A5XX_RB_CLEAR_CNTL 0x0000e21c
+#define A5XX_RB_CLEAR_CNTL_FAST_CLEAR 0x00000002
+#define A5XX_RB_CLEAR_CNTL_MASK__MASK 0x000000f0
+#define A5XX_RB_CLEAR_CNTL_MASK__SHIFT 4
+static inline uint32_t A5XX_RB_CLEAR_CNTL_MASK(uint32_t val)
+{
+ return ((val) << A5XX_RB_CLEAR_CNTL_MASK__SHIFT) & A5XX_RB_CLEAR_CNTL_MASK__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO 0x0000e240
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_HI 0x0000e241
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_PITCH 0x0000e242
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER(uint32_t i0) { return 0x0000e243 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ADDR_LO(uint32_t i0) { return 0x0000e243 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ADDR_HI(uint32_t i0) { return 0x0000e244 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_PITCH(uint32_t i0) { return 0x0000e245 + 0x4*i0; }
+#define A5XX_RB_MRT_FLAG_BUFFER_PITCH__MASK 0xffffffff
+#define A5XX_RB_MRT_FLAG_BUFFER_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_FLAG_BUFFER_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_MRT_FLAG_BUFFER_PITCH__SHIFT) & A5XX_RB_MRT_FLAG_BUFFER_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(uint32_t i0) { return 0x0000e246 + 0x4*i0; }
+#define A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__SHIFT) & A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_LO 0x0000e263
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_HI 0x0000e264
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_PITCH 0x0000e265
+#define A5XX_RB_BLIT_FLAG_DST_PITCH__MASK 0xffffffff
+#define A5XX_RB_BLIT_FLAG_DST_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_BLIT_FLAG_DST_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_BLIT_FLAG_DST_PITCH__SHIFT) & A5XX_RB_BLIT_FLAG_DST_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH 0x0000e266
+#define A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__MASK 0xffffffff
+#define A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 6) << A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__SHIFT) & A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_VPC_CNTL_0 0x0000e280
+#define A5XX_VPC_CNTL_0_STRIDE_IN_VPC__MASK 0x0000007f
+#define A5XX_VPC_CNTL_0_STRIDE_IN_VPC__SHIFT 0
+static inline uint32_t A5XX_VPC_CNTL_0_STRIDE_IN_VPC(uint32_t val)
+{
+ return ((val) << A5XX_VPC_CNTL_0_STRIDE_IN_VPC__SHIFT) & A5XX_VPC_CNTL_0_STRIDE_IN_VPC__MASK;
+}
+#define A5XX_VPC_CNTL_0_VARYING 0x00000800
+
+static inline uint32_t REG_A5XX_VPC_VARYING_INTERP(uint32_t i0) { return 0x0000e282 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_INTERP_MODE(uint32_t i0) { return 0x0000e282 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x0000e28a + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x0000e28a + 0x1*i0; }
+
+#define REG_A5XX_UNKNOWN_E292 0x0000e292
+
+#define REG_A5XX_UNKNOWN_E293 0x0000e293
+
+static inline uint32_t REG_A5XX_VPC_VAR(uint32_t i0) { return 0x0000e294 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VAR_DISABLE(uint32_t i0) { return 0x0000e294 + 0x1*i0; }
+
+#define REG_A5XX_VPC_GS_SIV_CNTL 0x0000e298
+
+#define REG_A5XX_UNKNOWN_E29A 0x0000e29a
+
+#define REG_A5XX_VPC_PACK 0x0000e29d
+#define A5XX_VPC_PACK_NUMNONPOSVAR__MASK 0x000000ff
+#define A5XX_VPC_PACK_NUMNONPOSVAR__SHIFT 0
+static inline uint32_t A5XX_VPC_PACK_NUMNONPOSVAR(uint32_t val)
+{
+ return ((val) << A5XX_VPC_PACK_NUMNONPOSVAR__SHIFT) & A5XX_VPC_PACK_NUMNONPOSVAR__MASK;
+}
+
+#define REG_A5XX_VPC_FS_PRIMITIVEID_CNTL 0x0000e2a0
+
+#define REG_A5XX_UNKNOWN_E2A1 0x0000e2a1
+
+#define REG_A5XX_VPC_SO_OVERRIDE 0x0000e2a2
+
+#define REG_A5XX_VPC_SO_BUFFER_BASE_LO_0 0x0000e2a7
+
+#define REG_A5XX_VPC_SO_BUFFER_BASE_HI_0 0x0000e2a8
+
+#define REG_A5XX_VPC_SO_BUFFER_SIZE_0 0x0000e2a9
+
+#define REG_A5XX_UNKNOWN_E2AB 0x0000e2ab
+
+#define REG_A5XX_VPC_SO_FLUSH_BASE_LO_0 0x0000e2ac
+
+#define REG_A5XX_VPC_SO_FLUSH_BASE_HI_0 0x0000e2ad
+
+#define REG_A5XX_UNKNOWN_E2AE 0x0000e2ae
+
+#define REG_A5XX_UNKNOWN_E2B2 0x0000e2b2
+
+#define REG_A5XX_UNKNOWN_E2B9 0x0000e2b9
+
+#define REG_A5XX_UNKNOWN_E2C0 0x0000e2c0
+
+#define REG_A5XX_PC_PRIMITIVE_CNTL 0x0000e384
+#define A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK 0x0000007f
+#define A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT 0
+static inline uint32_t A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC(uint32_t val)
+{
+ return ((val) << A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT) & A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK;
+}
+
+#define REG_A5XX_PC_PRIM_VTX_CNTL 0x0000e385
+#define A5XX_PC_PRIM_VTX_CNTL_PSIZE 0x00000800
+
+#define REG_A5XX_PC_RASTER_CNTL 0x0000e388
+
+#define REG_A5XX_UNKNOWN_E389 0x0000e389
+
+#define REG_A5XX_PC_RESTART_INDEX 0x0000e38c
+
+#define REG_A5XX_UNKNOWN_E38D 0x0000e38d
+
+#define REG_A5XX_PC_GS_PARAM 0x0000e38e
+
+#define REG_A5XX_PC_HS_PARAM 0x0000e38f
+
+#define REG_A5XX_PC_POWER_CNTL 0x0000e3b0
+
+#define REG_A5XX_VFD_CONTROL_0 0x0000e400
+#define A5XX_VFD_CONTROL_0_VTXCNT__MASK 0x0000003f
+#define A5XX_VFD_CONTROL_0_VTXCNT__SHIFT 0
+static inline uint32_t A5XX_VFD_CONTROL_0_VTXCNT(uint32_t val)
+{
+ return ((val) << A5XX_VFD_CONTROL_0_VTXCNT__SHIFT) & A5XX_VFD_CONTROL_0_VTXCNT__MASK;
+}
+
+#define REG_A5XX_VFD_CONTROL_1 0x0000e401
+#define A5XX_VFD_CONTROL_1_REGID4INST__MASK 0x0000ff00
+#define A5XX_VFD_CONTROL_1_REGID4INST__SHIFT 8
+static inline uint32_t A5XX_VFD_CONTROL_1_REGID4INST(uint32_t val)
+{
+ return ((val) << A5XX_VFD_CONTROL_1_REGID4INST__SHIFT) & A5XX_VFD_CONTROL_1_REGID4INST__MASK;
+}
+#define A5XX_VFD_CONTROL_1_REGID4VTX__MASK 0x00ff0000
+#define A5XX_VFD_CONTROL_1_REGID4VTX__SHIFT 16
+static inline uint32_t A5XX_VFD_CONTROL_1_REGID4VTX(uint32_t val)
+{
+ return ((val) << A5XX_VFD_CONTROL_1_REGID4VTX__SHIFT) & A5XX_VFD_CONTROL_1_REGID4VTX__MASK;
+}
+
+#define REG_A5XX_VFD_CONTROL_2 0x0000e402
+
+#define REG_A5XX_VFD_CONTROL_3 0x0000e403
+
+#define REG_A5XX_VFD_CONTROL_4 0x0000e404
+
+#define REG_A5XX_VFD_CONTROL_5 0x0000e405
+
+#define REG_A5XX_VFD_INDEX_OFFSET 0x0000e408
+
+#define REG_A5XX_VFD_INSTANCE_START_OFFSET 0x0000e409
+
+static inline uint32_t REG_A5XX_VFD_FETCH(uint32_t i0) { return 0x0000e40a + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_BASE_LO(uint32_t i0) { return 0x0000e40a + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_BASE_HI(uint32_t i0) { return 0x0000e40b + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_SIZE(uint32_t i0) { return 0x0000e40c + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_STRIDE(uint32_t i0) { return 0x0000e40d + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DECODE(uint32_t i0) { return 0x0000e48a + 0x2*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DECODE_INSTR(uint32_t i0) { return 0x0000e48a + 0x2*i0; }
+#define A5XX_VFD_DECODE_INSTR_IDX__MASK 0x0000001f
+#define A5XX_VFD_DECODE_INSTR_IDX__SHIFT 0
+static inline uint32_t A5XX_VFD_DECODE_INSTR_IDX(uint32_t val)
+{
+ return ((val) << A5XX_VFD_DECODE_INSTR_IDX__SHIFT) & A5XX_VFD_DECODE_INSTR_IDX__MASK;
+}
+#define A5XX_VFD_DECODE_INSTR_FORMAT__MASK 0x3ff00000
+#define A5XX_VFD_DECODE_INSTR_FORMAT__SHIFT 20
+static inline uint32_t A5XX_VFD_DECODE_INSTR_FORMAT(enum a5xx_vtx_fmt val)
+{
+ return ((val) << A5XX_VFD_DECODE_INSTR_FORMAT__SHIFT) & A5XX_VFD_DECODE_INSTR_FORMAT__MASK;
+}
+#define A5XX_VFD_DECODE_INSTR_SWAP__MASK 0xc0000000
+#define A5XX_VFD_DECODE_INSTR_SWAP__SHIFT 30
+static inline uint32_t A5XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A5XX_VFD_DECODE_INSTR_SWAP__MASK;
+}
+
+static inline uint32_t REG_A5XX_VFD_DECODE_STEP_RATE(uint32_t i0) { return 0x0000e48b + 0x2*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DEST_CNTL(uint32_t i0) { return 0x0000e4ca + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DEST_CNTL_INSTR(uint32_t i0) { return 0x0000e4ca + 0x1*i0; }
+#define A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__MASK 0x0000000f
+#define A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__SHIFT 0
+static inline uint32_t A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK(uint32_t val)
+{
+ return ((val) << A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__SHIFT) & A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__MASK;
+}
+#define A5XX_VFD_DEST_CNTL_INSTR_REGID__MASK 0x00000ff0
+#define A5XX_VFD_DEST_CNTL_INSTR_REGID__SHIFT 4
+static inline uint32_t A5XX_VFD_DEST_CNTL_INSTR_REGID(uint32_t val)
+{
+ return ((val) << A5XX_VFD_DEST_CNTL_INSTR_REGID__SHIFT) & A5XX_VFD_DEST_CNTL_INSTR_REGID__MASK;
+}
+
+#define REG_A5XX_VFD_POWER_CNTL 0x0000e4f0
+
+#define REG_A5XX_SP_SP_CNTL 0x0000e580
+
+#define REG_A5XX_SP_VS_CONTROL_REG 0x0000e584
+#define A5XX_SP_VS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_FS_CONTROL_REG 0x0000e585
+#define A5XX_SP_FS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_HS_CONTROL_REG 0x0000e586
+#define A5XX_SP_HS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_DS_CONTROL_REG 0x0000e587
+#define A5XX_SP_DS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_GS_CONTROL_REG 0x0000e588
+#define A5XX_SP_GS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_CS_CONFIG 0x0000e589
+
+#define REG_A5XX_SP_VS_CONFIG_MAX_CONST 0x0000e58a
+
+#define REG_A5XX_SP_FS_CONFIG_MAX_CONST 0x0000e58b
+
+#define REG_A5XX_SP_VS_CTRL_REG0 0x0000e590
+#define A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
+#define A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
+static inline uint32_t A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0000fc00
+#define A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
+static inline uint32_t A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_VS_CTRL_REG0_VARYING 0x00010000
+#define A5XX_SP_VS_CTRL_REG0_PIXLODENABLE 0x00100000
+
+#define REG_A5XX_SP_PRIMITIVE_CNTL 0x0000e592
+#define A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK 0x0000001f
+#define A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT 0
+static inline uint32_t A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC(uint32_t val)
+{
+ return ((val >> 2) << A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT) & A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_VS_OUT(uint32_t i0) { return 0x0000e593 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_VS_OUT_REG(uint32_t i0) { return 0x0000e593 + 0x1*i0; }
+#define A5XX_SP_VS_OUT_REG_A_REGID__MASK 0x000000ff
+#define A5XX_SP_VS_OUT_REG_A_REGID__SHIFT 0
+static inline uint32_t A5XX_SP_VS_OUT_REG_A_REGID(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_OUT_REG_A_REGID__SHIFT) & A5XX_SP_VS_OUT_REG_A_REGID__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_A_COMPMASK__MASK 0x00000f00
+#define A5XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT 8
+static inline uint32_t A5XX_SP_VS_OUT_REG_A_COMPMASK(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT) & A5XX_SP_VS_OUT_REG_A_COMPMASK__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_B_REGID__MASK 0x00ff0000
+#define A5XX_SP_VS_OUT_REG_B_REGID__SHIFT 16
+static inline uint32_t A5XX_SP_VS_OUT_REG_B_REGID(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_OUT_REG_B_REGID__SHIFT) & A5XX_SP_VS_OUT_REG_B_REGID__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_B_COMPMASK__MASK 0x0f000000
+#define A5XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT 24
+static inline uint32_t A5XX_SP_VS_OUT_REG_B_COMPMASK(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT) & A5XX_SP_VS_OUT_REG_B_COMPMASK__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_VS_VPC_DST(uint32_t i0) { return 0x0000e5a3 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_VS_VPC_DST_REG(uint32_t i0) { return 0x0000e5a3 + 0x1*i0; }
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK 0x000000ff
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT 0
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC0(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK 0x0000ff00
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT 8
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC1(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK 0x00ff0000
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT 16
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC2(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK 0xff000000
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT 24
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC3(uint32_t val)
+{
+ return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E5AB 0x0000e5ab
+
+#define REG_A5XX_SP_VS_OBJ_START_LO 0x0000e5ac
+
+#define REG_A5XX_SP_VS_OBJ_START_HI 0x0000e5ad
+
+#define REG_A5XX_SP_FS_CTRL_REG0 0x0000e5c0
+#define A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
+#define A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
+static inline uint32_t A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0000fc00
+#define A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
+static inline uint32_t A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_FS_CTRL_REG0_VARYING 0x00010000
+#define A5XX_SP_FS_CTRL_REG0_PIXLODENABLE 0x00100000
+
+#define REG_A5XX_UNKNOWN_E5C2 0x0000e5c2
+
+#define REG_A5XX_SP_FS_OBJ_START_LO 0x0000e5c3
+
+#define REG_A5XX_SP_FS_OBJ_START_HI 0x0000e5c4
+
+#define REG_A5XX_SP_BLEND_CNTL 0x0000e5c9
+
+#define REG_A5XX_SP_FS_OUTPUT_CNTL 0x0000e5ca
+#define A5XX_SP_FS_OUTPUT_CNTL_MRT__MASK 0x0000000f
+#define A5XX_SP_FS_OUTPUT_CNTL_MRT__SHIFT 0
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_MRT(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_OUTPUT_CNTL_MRT__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_MRT__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__MASK 0x00001fe0
+#define A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__SHIFT 5
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__MASK 0x001fe000
+#define A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__SHIFT 13
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_FS_OUTPUT(uint32_t i0) { return 0x0000e5cb + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_FS_OUTPUT_REG(uint32_t i0) { return 0x0000e5cb + 0x1*i0; }
+#define A5XX_SP_FS_OUTPUT_REG_REGID__MASK 0x000000ff
+#define A5XX_SP_FS_OUTPUT_REG_REGID__SHIFT 0
+static inline uint32_t A5XX_SP_FS_OUTPUT_REG_REGID(uint32_t val)
+{
+ return ((val) << A5XX_SP_FS_OUTPUT_REG_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_REG_REGID__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_REG_HALF_PRECISION 0x00000100
+
+static inline uint32_t REG_A5XX_SP_FS_MRT(uint32_t i0) { return 0x0000e5d3 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_FS_MRT_REG(uint32_t i0) { return 0x0000e5d3 + 0x1*i0; }
+#define A5XX_SP_FS_MRT_REG_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_SP_FS_MRT_REG_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_SP_FS_MRT_REG_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_SP_FS_MRT_REG_COLOR_FORMAT__SHIFT) & A5XX_SP_FS_MRT_REG_COLOR_FORMAT__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E5DB 0x0000e5db
+
+#define REG_A5XX_SP_CS_CNTL_0 0x0000e5f0
+
+#define REG_A5XX_UNKNOWN_E600 0x0000e600
+
+#define REG_A5XX_UNKNOWN_E640 0x0000e640
+
+#define REG_A5XX_TPL1_TP_RAS_MSAA_CNTL 0x0000e704
+#define A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_TPL1_TP_DEST_MSAA_CNTL 0x0000e705
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__MASK 0x00000003
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__SHIFT 0
+static inline uint32_t A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+ return ((val) << A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE 0x00000004
+
+#define REG_A5XX_TPL1_VS_TEX_COUNT 0x0000e700
+
+#define REG_A5XX_TPL1_VS_TEX_SAMP_LO 0x0000e722
+
+#define REG_A5XX_TPL1_VS_TEX_SAMP_HI 0x0000e723
+
+#define REG_A5XX_TPL1_VS_TEX_CONST_LO 0x0000e72a
+
+#define REG_A5XX_TPL1_VS_TEX_CONST_HI 0x0000e72b
+
+#define REG_A5XX_TPL1_FS_TEX_COUNT 0x0000e750
+
+#define REG_A5XX_TPL1_FS_TEX_SAMP_LO 0x0000e75a
+
+#define REG_A5XX_TPL1_FS_TEX_SAMP_HI 0x0000e75b
+
+#define REG_A5XX_TPL1_FS_TEX_CONST_LO 0x0000e75e
+
+#define REG_A5XX_TPL1_FS_TEX_CONST_HI 0x0000e75f
+
+#define REG_A5XX_TPL1_TP_FS_ROTATION_CNTL 0x0000e764
+
+#define REG_A5XX_HLSQ_CONTROL_0_REG 0x0000e784
+
+#define REG_A5XX_HLSQ_CONTROL_1_REG 0x0000e785
+#define A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__MASK 0x0000003f
+#define A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__SHIFT 0
+static inline uint32_t A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__SHIFT) & A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_2_REG 0x0000e786
+#define A5XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK 0x000000ff
+#define A5XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT 0
+static inline uint32_t A5XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A5XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_3_REG 0x0000e787
+#define A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__MASK 0x000000ff
+#define A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__SHIFT 0
+static inline uint32_t A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__SHIFT) & A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_4_REG 0x0000e788
+#define A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__MASK 0x00ff0000
+#define A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__SHIFT 16
+static inline uint32_t A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__SHIFT) & A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__MASK;
+}
+#define A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__MASK 0xff000000
+#define A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__SHIFT 24
+static inline uint32_t A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__SHIFT) & A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_UPDATE_CNTL 0x0000e78a
+
+#define REG_A5XX_HLSQ_VS_CONTROL_REG 0x0000e78b
+#define A5XX_HLSQ_VS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_FS_CONTROL_REG 0x0000e78c
+#define A5XX_HLSQ_FS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_HS_CONTROL_REG 0x0000e78d
+#define A5XX_HLSQ_HS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_DS_CONTROL_REG 0x0000e78e
+#define A5XX_HLSQ_DS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_GS_CONTROL_REG 0x0000e78f
+#define A5XX_HLSQ_GS_CONTROL_REG_ENABLED 0x00000001
+#define A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x000000fe
+#define A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 1
+static inline uint32_t A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00007f00
+#define A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 8
+static inline uint32_t A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_CONFIG 0x0000e790
+
+#define REG_A5XX_HLSQ_VS_CNTL 0x0000e791
+#define A5XX_HLSQ_VS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_VS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_VS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_VS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_VS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_FS_CNTL 0x0000e792
+#define A5XX_HLSQ_FS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_FS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_FS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_FS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_FS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_HS_CNTL 0x0000e793
+#define A5XX_HLSQ_HS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_HS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_HS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_HS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_HS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_DS_CNTL 0x0000e794
+#define A5XX_HLSQ_DS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_DS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_DS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_DS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_DS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_GS_CNTL 0x0000e795
+#define A5XX_HLSQ_GS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_GS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_GS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_GS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_GS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_CNTL 0x0000e796
+#define A5XX_HLSQ_CS_CNTL_INSTRLEN__MASK 0xfffffffe
+#define A5XX_HLSQ_CS_CNTL_INSTRLEN__SHIFT 1
+static inline uint32_t A5XX_HLSQ_CS_CNTL_INSTRLEN(uint32_t val)
+{
+ return ((val) << A5XX_HLSQ_CS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_CS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_X 0x0000e7b9
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_Y 0x0000e7ba
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_Z 0x0000e7bb
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_0 0x0000e7b0
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_1 0x0000e7b1
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_2 0x0000e7b2
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_3 0x0000e7b3
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_4 0x0000e7b4
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_5 0x0000e7b5
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_6 0x0000e7b6
+
+#define REG_A5XX_HLSQ_CS_CNTL_0 0x0000e7b7
+
+#define REG_A5XX_HLSQ_CS_CNTL_1 0x0000e7b8
+
+#define REG_A5XX_UNKNOWN_E7C0 0x0000e7c0
+
+#define REG_A5XX_HLSQ_VS_CONSTLEN 0x0000e7c3
+
+#define REG_A5XX_HLSQ_VS_INSTRLEN 0x0000e7c4
+
+#define REG_A5XX_UNKNOWN_E7C5 0x0000e7c5
+
+#define REG_A5XX_UNKNOWN_E7CA 0x0000e7ca
+
+#define REG_A5XX_HLSQ_FS_CONSTLEN 0x0000e7d7
+
+#define REG_A5XX_HLSQ_FS_INSTRLEN 0x0000e7d8
+
+#define REG_A5XX_HLSQ_HS_CONSTLEN 0x0000e7c8
+
+#define REG_A5XX_HLSQ_HS_INSTRLEN 0x0000e7c9
+
+#define REG_A5XX_HLSQ_DS_CONSTLEN 0x0000e7cd
+
+#define REG_A5XX_HLSQ_DS_INSTRLEN 0x0000e7ce
+
+#define REG_A5XX_UNKNOWN_E7CF 0x0000e7cf
+
+#define REG_A5XX_HLSQ_GS_CONSTLEN 0x0000e7d2
+
+#define REG_A5XX_HLSQ_GS_INSTRLEN 0x0000e7d3
+
+#define REG_A5XX_UNKNOWN_E7D4 0x0000e7d4
+
+#define REG_A5XX_UNKNOWN_E7D9 0x0000e7d9
+
+#define REG_A5XX_HLSQ_CONTEXT_SWITCH_CS_SW_3 0x0000e7dc
+
+#define REG_A5XX_HLSQ_CONTEXT_SWITCH_CS_SW_4 0x0000e7dd
+
+#define REG_A5XX_RB_2D_DST_FILL 0x00002101
+
+#define REG_A5XX_RB_2D_SRC_INFO 0x00002107
+#define A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_2D_SRC_INFO_COLOR_SWAP__MASK 0x00000c00
+#define A5XX_RB_2D_SRC_INFO_COLOR_SWAP__SHIFT 10
+static inline uint32_t A5XX_RB_2D_SRC_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_RB_2D_SRC_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_2D_SRC_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_RB_2D_SRC_LO 0x00002108
+
+#define REG_A5XX_RB_2D_SRC_HI 0x00002109
+
+#define REG_A5XX_RB_2D_DST_INFO 0x00002110
+#define A5XX_RB_2D_DST_INFO_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_RB_2D_DST_INFO_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_RB_2D_DST_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_RB_2D_DST_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_2D_DST_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_2D_DST_INFO_COLOR_SWAP__MASK 0x00000c00
+#define A5XX_RB_2D_DST_INFO_COLOR_SWAP__SHIFT 10
+static inline uint32_t A5XX_RB_2D_DST_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_RB_2D_DST_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_2D_DST_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_RB_2D_SRC_FLAGS_LO 0x00002140
+
+#define REG_A5XX_RB_2D_SRC_FLAGS_HI 0x00002141
+
+#define REG_A5XX_RB_2D_DST_LO 0x00002111
+
+#define REG_A5XX_RB_2D_DST_HI 0x00002112
+
+#define REG_A5XX_RB_2D_DST_FLAGS_LO 0x00002143
+
+#define REG_A5XX_RB_2D_DST_FLAGS_HI 0x00002144
+
+#define REG_A5XX_GRAS_2D_SRC_INFO 0x00002181
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__SHIFT) & A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__MASK 0x00000c00
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__SHIFT 10
+static inline uint32_t A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__SHIFT) & A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_GRAS_2D_DST_INFO 0x00002182
+#define A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__MASK 0x000000ff
+#define A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__SHIFT 0
+static inline uint32_t A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+ return ((val) << A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__SHIFT) & A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__MASK 0x00000c00
+#define A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__SHIFT 10
+static inline uint32_t A5XX_GRAS_2D_DST_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__SHIFT) & A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_0 0x00000000
+#define A5XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR 0x00000001
+#define A5XX_TEX_SAMP_0_XY_MAG__MASK 0x00000006
+#define A5XX_TEX_SAMP_0_XY_MAG__SHIFT 1
+static inline uint32_t A5XX_TEX_SAMP_0_XY_MAG(enum a5xx_tex_filter val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_XY_MAG__SHIFT) & A5XX_TEX_SAMP_0_XY_MAG__MASK;
+}
+#define A5XX_TEX_SAMP_0_XY_MIN__MASK 0x00000018
+#define A5XX_TEX_SAMP_0_XY_MIN__SHIFT 3
+static inline uint32_t A5XX_TEX_SAMP_0_XY_MIN(enum a5xx_tex_filter val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_XY_MIN__SHIFT) & A5XX_TEX_SAMP_0_XY_MIN__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_S__MASK 0x000000e0
+#define A5XX_TEX_SAMP_0_WRAP_S__SHIFT 5
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_S(enum a5xx_tex_clamp val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_WRAP_S__SHIFT) & A5XX_TEX_SAMP_0_WRAP_S__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_T__MASK 0x00000700
+#define A5XX_TEX_SAMP_0_WRAP_T__SHIFT 8
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_T(enum a5xx_tex_clamp val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_WRAP_T__SHIFT) & A5XX_TEX_SAMP_0_WRAP_T__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_R__MASK 0x00003800
+#define A5XX_TEX_SAMP_0_WRAP_R__SHIFT 11
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_R(enum a5xx_tex_clamp val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_WRAP_R__SHIFT) & A5XX_TEX_SAMP_0_WRAP_R__MASK;
+}
+#define A5XX_TEX_SAMP_0_ANISO__MASK 0x0001c000
+#define A5XX_TEX_SAMP_0_ANISO__SHIFT 14
+static inline uint32_t A5XX_TEX_SAMP_0_ANISO(enum a5xx_tex_aniso val)
+{
+ return ((val) << A5XX_TEX_SAMP_0_ANISO__SHIFT) & A5XX_TEX_SAMP_0_ANISO__MASK;
+}
+#define A5XX_TEX_SAMP_0_LOD_BIAS__MASK 0xfff80000
+#define A5XX_TEX_SAMP_0_LOD_BIAS__SHIFT 19
+static inline uint32_t A5XX_TEX_SAMP_0_LOD_BIAS(float val)
+{
+ return ((((int32_t)(val * 256.0))) << A5XX_TEX_SAMP_0_LOD_BIAS__SHIFT) & A5XX_TEX_SAMP_0_LOD_BIAS__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_1 0x00000001
+#define A5XX_TEX_SAMP_1_COMPARE_FUNC__MASK 0x0000000e
+#define A5XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT 1
+static inline uint32_t A5XX_TEX_SAMP_1_COMPARE_FUNC(enum adreno_compare_func val)
+{
+ return ((val) << A5XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT) & A5XX_TEX_SAMP_1_COMPARE_FUNC__MASK;
+}
+#define A5XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF 0x00000010
+#define A5XX_TEX_SAMP_1_UNNORM_COORDS 0x00000020
+#define A5XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR 0x00000040
+#define A5XX_TEX_SAMP_1_MAX_LOD__MASK 0x000fff00
+#define A5XX_TEX_SAMP_1_MAX_LOD__SHIFT 8
+static inline uint32_t A5XX_TEX_SAMP_1_MAX_LOD(float val)
+{
+ return ((((uint32_t)(val * 256.0))) << A5XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A5XX_TEX_SAMP_1_MAX_LOD__MASK;
+}
+#define A5XX_TEX_SAMP_1_MIN_LOD__MASK 0xfff00000
+#define A5XX_TEX_SAMP_1_MIN_LOD__SHIFT 20
+static inline uint32_t A5XX_TEX_SAMP_1_MIN_LOD(float val)
+{
+ return ((((uint32_t)(val * 256.0))) << A5XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A5XX_TEX_SAMP_1_MIN_LOD__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_2 0x00000002
+
+#define REG_A5XX_TEX_SAMP_3 0x00000003
+
+#define REG_A5XX_TEX_CONST_0 0x00000000
+#define A5XX_TEX_CONST_0_TILE_MODE__MASK 0x00000003
+#define A5XX_TEX_CONST_0_TILE_MODE__SHIFT 0
+static inline uint32_t A5XX_TEX_CONST_0_TILE_MODE(enum a5xx_tile_mode val)
+{
+ return ((val) << A5XX_TEX_CONST_0_TILE_MODE__SHIFT) & A5XX_TEX_CONST_0_TILE_MODE__MASK;
+}
+#define A5XX_TEX_CONST_0_SRGB 0x00000004
+#define A5XX_TEX_CONST_0_SWIZ_X__MASK 0x00000070
+#define A5XX_TEX_CONST_0_SWIZ_X__SHIFT 4
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_X(enum a5xx_tex_swiz val)
+{
+ return ((val) << A5XX_TEX_CONST_0_SWIZ_X__SHIFT) & A5XX_TEX_CONST_0_SWIZ_X__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_Y__MASK 0x00000380
+#define A5XX_TEX_CONST_0_SWIZ_Y__SHIFT 7
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_Y(enum a5xx_tex_swiz val)
+{
+ return ((val) << A5XX_TEX_CONST_0_SWIZ_Y__SHIFT) & A5XX_TEX_CONST_0_SWIZ_Y__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_Z__MASK 0x00001c00
+#define A5XX_TEX_CONST_0_SWIZ_Z__SHIFT 10
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_Z(enum a5xx_tex_swiz val)
+{
+ return ((val) << A5XX_TEX_CONST_0_SWIZ_Z__SHIFT) & A5XX_TEX_CONST_0_SWIZ_Z__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_W__MASK 0x0000e000
+#define A5XX_TEX_CONST_0_SWIZ_W__SHIFT 13
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_W(enum a5xx_tex_swiz val)
+{
+ return ((val) << A5XX_TEX_CONST_0_SWIZ_W__SHIFT) & A5XX_TEX_CONST_0_SWIZ_W__MASK;
+}
+#define A5XX_TEX_CONST_0_FMT__MASK 0x3fc00000
+#define A5XX_TEX_CONST_0_FMT__SHIFT 22
+static inline uint32_t A5XX_TEX_CONST_0_FMT(enum a5xx_tex_fmt val)
+{
+ return ((val) << A5XX_TEX_CONST_0_FMT__SHIFT) & A5XX_TEX_CONST_0_FMT__MASK;
+}
+#define A5XX_TEX_CONST_0_SWAP__MASK 0xc0000000
+#define A5XX_TEX_CONST_0_SWAP__SHIFT 30
+static inline uint32_t A5XX_TEX_CONST_0_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A5XX_TEX_CONST_0_SWAP__SHIFT) & A5XX_TEX_CONST_0_SWAP__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_1 0x00000001
+#define A5XX_TEX_CONST_1_WIDTH__MASK 0x00007fff
+#define A5XX_TEX_CONST_1_WIDTH__SHIFT 0
+static inline uint32_t A5XX_TEX_CONST_1_WIDTH(uint32_t val)
+{
+ return ((val) << A5XX_TEX_CONST_1_WIDTH__SHIFT) & A5XX_TEX_CONST_1_WIDTH__MASK;
+}
+#define A5XX_TEX_CONST_1_HEIGHT__MASK 0x3fff8000
+#define A5XX_TEX_CONST_1_HEIGHT__SHIFT 15
+static inline uint32_t A5XX_TEX_CONST_1_HEIGHT(uint32_t val)
+{
+ return ((val) << A5XX_TEX_CONST_1_HEIGHT__SHIFT) & A5XX_TEX_CONST_1_HEIGHT__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_2 0x00000002
+#define A5XX_TEX_CONST_2_FETCHSIZE__MASK 0x0000000f
+#define A5XX_TEX_CONST_2_FETCHSIZE__SHIFT 0
+static inline uint32_t A5XX_TEX_CONST_2_FETCHSIZE(enum a5xx_tex_fetchsize val)
+{
+ return ((val) << A5XX_TEX_CONST_2_FETCHSIZE__SHIFT) & A5XX_TEX_CONST_2_FETCHSIZE__MASK;
+}
+#define A5XX_TEX_CONST_2_PITCH__MASK 0x1fffff80
+#define A5XX_TEX_CONST_2_PITCH__SHIFT 7
+static inline uint32_t A5XX_TEX_CONST_2_PITCH(uint32_t val)
+{
+ return ((val) << A5XX_TEX_CONST_2_PITCH__SHIFT) & A5XX_TEX_CONST_2_PITCH__MASK;
+}
+#define A5XX_TEX_CONST_2_TYPE__MASK 0x60000000
+#define A5XX_TEX_CONST_2_TYPE__SHIFT 29
+static inline uint32_t A5XX_TEX_CONST_2_TYPE(enum a5xx_tex_type val)
+{
+ return ((val) << A5XX_TEX_CONST_2_TYPE__SHIFT) & A5XX_TEX_CONST_2_TYPE__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_3 0x00000003
+#define A5XX_TEX_CONST_3_ARRAY_PITCH__MASK 0x00003fff
+#define A5XX_TEX_CONST_3_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A5XX_TEX_CONST_3_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 12) << A5XX_TEX_CONST_3_ARRAY_PITCH__SHIFT) & A5XX_TEX_CONST_3_ARRAY_PITCH__MASK;
+}
+#define A5XX_TEX_CONST_3_FLAG 0x10000000
+
+#define REG_A5XX_TEX_CONST_4 0x00000004
+#define A5XX_TEX_CONST_4_BASE_LO__MASK 0xffffffe0
+#define A5XX_TEX_CONST_4_BASE_LO__SHIFT 5
+static inline uint32_t A5XX_TEX_CONST_4_BASE_LO(uint32_t val)
+{
+ return ((val >> 5) << A5XX_TEX_CONST_4_BASE_LO__SHIFT) & A5XX_TEX_CONST_4_BASE_LO__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_5 0x00000005
+#define A5XX_TEX_CONST_5_BASE_HI__MASK 0x0001ffff
+#define A5XX_TEX_CONST_5_BASE_HI__SHIFT 0
+static inline uint32_t A5XX_TEX_CONST_5_BASE_HI(uint32_t val)
+{
+ return ((val) << A5XX_TEX_CONST_5_BASE_HI__SHIFT) & A5XX_TEX_CONST_5_BASE_HI__MASK;
+}
+#define A5XX_TEX_CONST_5_DEPTH__MASK 0x3ffe0000
+#define A5XX_TEX_CONST_5_DEPTH__SHIFT 17
+static inline uint32_t A5XX_TEX_CONST_5_DEPTH(uint32_t val)
+{
+ return ((val) << A5XX_TEX_CONST_5_DEPTH__SHIFT) & A5XX_TEX_CONST_5_DEPTH__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_6 0x00000006
+
+#define REG_A5XX_TEX_CONST_7 0x00000007
+
+#define REG_A5XX_TEX_CONST_8 0x00000008
+
+#define REG_A5XX_TEX_CONST_9 0x00000009
+
+#define REG_A5XX_TEX_CONST_10 0x0000000a
+
+#define REG_A5XX_TEX_CONST_11 0x0000000b
+
+
+#endif /* A5XX_XML */
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
new file mode 100644
index 000000000000..b8647198c11c
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -0,0 +1,888 @@
+/* Copyright (c) 2016 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 "msm_gem.h"
+#include "a5xx_gpu.h"
+
+extern bool hang_debug;
+static void a5xx_dump(struct msm_gpu *gpu);
+
+static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+ struct msm_file_private *ctx)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct msm_drm_private *priv = gpu->dev->dev_private;
+ struct msm_ringbuffer *ring = gpu->rb;
+ unsigned int i, ibs = 0;
+
+ for (i = 0; i < submit->nr_cmds; i++) {
+ switch (submit->cmd[i].type) {
+ case MSM_SUBMIT_CMD_IB_TARGET_BUF:
+ break;
+ case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
+ if (priv->lastctx == ctx)
+ break;
+ case MSM_SUBMIT_CMD_BUF:
+ OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
+ OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
+ OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
+ OUT_RING(ring, submit->cmd[i].size);
+ ibs++;
+ break;
+ }
+ }
+
+ OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
+ OUT_RING(ring, submit->fence->seqno);
+
+ OUT_PKT7(ring, CP_EVENT_WRITE, 4);
+ OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
+ OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence)));
+ OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence)));
+ OUT_RING(ring, submit->fence->seqno);
+
+ gpu->funcs->flush(gpu);
+}
+
+struct a5xx_hwcg {
+ u32 offset;
+ u32 value;
+};
+
+static const struct a5xx_hwcg a530_hwcg[] = {
+ {REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
+ {REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
+ {REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
+ {REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
+ {REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
+ {REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
+ {REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
+ {REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
+ {REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
+ {REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
+ {REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
+ {REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
+ {REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
+ {REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
+ {REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
+ {REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
+ {REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
+ {REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
+ {REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
+ {REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
+ {REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
+ {REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+ {REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
+ {REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
+ {REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
+ {REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
+ {REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
+ {REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
+ {REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
+ {REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
+ {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
+ {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
+ {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
+ {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
+ {REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
+ {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
+ {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
+ {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
+ {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
+ {REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
+ {REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+ {REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
+};
+
+static const struct {
+ int (*test)(struct adreno_gpu *gpu);
+ const struct a5xx_hwcg *regs;
+ unsigned int count;
+} a5xx_hwcg_regs[] = {
+ { adreno_is_a530, a530_hwcg, ARRAY_SIZE(a530_hwcg), },
+};
+
+static void _a5xx_enable_hwcg(struct msm_gpu *gpu,
+ const struct a5xx_hwcg *regs, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ gpu_write(gpu, regs[i].offset, regs[i].value);
+
+ gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0xAAA8AA00);
+ gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, 0x182);
+}
+
+static void a5xx_enable_hwcg(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(a5xx_hwcg_regs); i++) {
+ if (a5xx_hwcg_regs[i].test(adreno_gpu)) {
+ _a5xx_enable_hwcg(gpu, a5xx_hwcg_regs[i].regs,
+ a5xx_hwcg_regs[i].count);
+ return;
+ }
+ }
+}
+
+static int a5xx_me_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct msm_ringbuffer *ring = gpu->rb;
+
+ OUT_PKT7(ring, CP_ME_INIT, 8);
+
+ OUT_RING(ring, 0x0000002F);
+
+ /* Enable multiple hardware contexts */
+ OUT_RING(ring, 0x00000003);
+
+ /* Enable error detection */
+ OUT_RING(ring, 0x20000000);
+
+ /* Don't enable header dump */
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+
+ /* Specify workarounds for various microcode issues */
+ if (adreno_is_a530(adreno_gpu)) {
+ /* Workaround for token end syncs
+ * Force a WFI after every direct-render 3D mode draw and every
+ * 2D mode 3 draw
+ */
+ OUT_RING(ring, 0x0000000B);
+ } else {
+ /* No workarounds enabled */
+ OUT_RING(ring, 0x00000000);
+ }
+
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+
+ gpu->funcs->flush(gpu);
+
+ return gpu->funcs->idle(gpu) ? 0 : -EINVAL;
+}
+
+static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
+ const struct firmware *fw, u64 *iova)
+{
+ struct drm_device *drm = gpu->dev;
+ struct drm_gem_object *bo;
+ void *ptr;
+
+ mutex_lock(&drm->struct_mutex);
+ bo = msm_gem_new(drm, fw->size - 4, MSM_BO_UNCACHED);
+ mutex_unlock(&drm->struct_mutex);
+
+ if (IS_ERR(bo))
+ return bo;
+
+ ptr = msm_gem_get_vaddr(bo);
+ if (!ptr) {
+ drm_gem_object_unreference_unlocked(bo);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (iova) {
+ int ret = msm_gem_get_iova(bo, gpu->id, iova);
+
+ if (ret) {
+ drm_gem_object_unreference_unlocked(bo);
+ return ERR_PTR(ret);
+ }
+ }
+
+ memcpy(ptr, &fw->data[4], fw->size - 4);
+
+ msm_gem_put_vaddr(bo);
+ return bo;
+}
+
+static int a5xx_ucode_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+ int ret;
+
+ if (!a5xx_gpu->pm4_bo) {
+ a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
+ &a5xx_gpu->pm4_iova);
+
+ if (IS_ERR(a5xx_gpu->pm4_bo)) {
+ ret = PTR_ERR(a5xx_gpu->pm4_bo);
+ a5xx_gpu->pm4_bo = NULL;
+ dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ if (!a5xx_gpu->pfp_bo) {
+ a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
+ &a5xx_gpu->pfp_iova);
+
+ if (IS_ERR(a5xx_gpu->pfp_bo)) {
+ ret = PTR_ERR(a5xx_gpu->pfp_bo);
+ a5xx_gpu->pfp_bo = NULL;
+ dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
+ REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
+
+ gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
+ REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
+
+ return 0;
+}
+
+#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
+ A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
+ A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
+ A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
+ A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
+ A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
+
+static int a5xx_hw_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ int ret;
+
+ gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
+
+ /* Make all blocks contribute to the GPU BUSY perf counter */
+ gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
+ /* Enable RBBM error reporting bits */
+ gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
+
+ if (adreno_gpu->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
+ /*
+ * Mask out the activity signals from RB1-3 to avoid false
+ * positives
+ */
+
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
+ 0xF0000000);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
+ 0xFFFFFFFF);
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
+ 0xFFFFFFFF);
+ }
+
+ /* Enable fault detection */
+ gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
+ (1 << 30) | 0xFFFF);
+
+ /* Turn on performance counters */
+ gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
+
+ /* Increase VFD cache access so LRZ and other data gets evicted less */
+ gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
+
+ /* Disable L2 bypass in the UCHE */
+ gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
+ gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
+ gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
+ gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
+
+ /* Set the GMEM VA range (0 to gpu->gmem) */
+ gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
+ gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
+ gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
+ 0x00100000 + adreno_gpu->gmem - 1);
+ gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
+
+ gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
+ gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
+ gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
+ gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
+
+ gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
+
+ if (adreno_gpu->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
+ gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
+
+ gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
+
+ /* Enable USE_RETENTION_FLOPS */
+ gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
+
+ /* Enable ME/PFP split notification */
+ gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
+
+ /* Enable HWCG */
+ a5xx_enable_hwcg(gpu);
+
+ gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
+
+ /* Set the highest bank bit */
+ gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
+ gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
+
+ /* Protect registers from the CP */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
+
+ /* RBBM */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
+
+ /* Content protect */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
+ ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
+ 16));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
+ ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
+
+ /* CP */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
+
+ /* RB */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
+
+ /* VPC */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
+
+ /* UCHE */
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
+
+ if (adreno_is_a530(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
+ ADRENO_PROTECT_RW(0x10000, 0x8000));
+
+ gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
+ /*
+ * Disable the trusted memory range - we don't actually supported secure
+ * memory rendering at this point in time and we don't want to block off
+ * part of the virtual memory space.
+ */
+ gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
+ REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
+ gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
+
+ /* Load the GPMU firmware before starting the HW init */
+ a5xx_gpmu_ucode_init(gpu);
+
+ ret = adreno_hw_init(gpu);
+ if (ret)
+ return ret;
+
+ ret = a5xx_ucode_init(gpu);
+ if (ret)
+ return ret;
+
+ /* Disable the interrupts through the initial bringup stage */
+ gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
+
+ /* Clear ME_HALT to start the micro engine */
+ gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
+ ret = a5xx_me_init(gpu);
+ if (ret)
+ return ret;
+
+ ret = a5xx_power_init(gpu);
+ if (ret)
+ return ret;
+
+ /*
+ * Send a pipeline event stat to get misbehaving counters to start
+ * ticking correctly
+ */
+ if (adreno_is_a530(adreno_gpu)) {
+ OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
+ OUT_RING(gpu->rb, 0x0F);
+
+ gpu->funcs->flush(gpu);
+ if (!gpu->funcs->idle(gpu))
+ return -EINVAL;
+ }
+
+ /* Put the GPU into unsecure mode */
+ gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
+
+ return 0;
+}
+
+static void a5xx_recover(struct msm_gpu *gpu)
+{
+ int i;
+
+ adreno_dump_info(gpu);
+
+ for (i = 0; i < 8; i++) {
+ printk("CP_SCRATCH_REG%d: %u\n", i,
+ gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
+ }
+
+ if (hang_debug)
+ a5xx_dump(gpu);
+
+ gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
+ gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
+ gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
+ adreno_recover(gpu);
+}
+
+static void a5xx_destroy(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+
+ DBG("%s", gpu->name);
+
+ if (a5xx_gpu->pm4_bo) {
+ if (a5xx_gpu->pm4_iova)
+ msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->id);
+ drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
+ }
+
+ if (a5xx_gpu->pfp_bo) {
+ if (a5xx_gpu->pfp_iova)
+ msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->id);
+ drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
+ }
+
+ if (a5xx_gpu->gpmu_bo) {
+ if (a5xx_gpu->gpmu_bo)
+ msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);
+ drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
+ }
+
+ adreno_gpu_cleanup(adreno_gpu);
+ kfree(a5xx_gpu);
+}
+
+static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
+{
+ if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
+ return false;
+
+ /*
+ * Nearly every abnormality ends up pausing the GPU and triggering a
+ * fault so we can safely just watch for this one interrupt to fire
+ */
+ return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
+ A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
+}
+
+static bool a5xx_idle(struct msm_gpu *gpu)
+{
+ /* wait for CP to drain ringbuffer: */
+ if (!adreno_idle(gpu))
+ return false;
+
+ if (spin_until(_a5xx_check_idle(gpu))) {
+ DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
+ gpu->name, __builtin_return_address(0),
+ gpu_read(gpu, REG_A5XX_RBBM_STATUS),
+ gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
+
+ return false;
+ }
+
+ return true;
+}
+
+static void a5xx_cp_err_irq(struct msm_gpu *gpu)
+{
+ u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
+
+ if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
+ u32 val;
+
+ gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
+
+ /*
+ * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
+ * read it twice
+ */
+
+ gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
+ val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
+
+ dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
+ val);
+ }
+
+ if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
+ dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
+ gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
+
+ if (status & A5XX_CP_INT_CP_DMA_ERROR)
+ dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
+
+ if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
+ u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
+
+ dev_err_ratelimited(gpu->dev->dev,
+ "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
+ val & (1 << 24) ? "WRITE" : "READ",
+ (val & 0xFFFFF) >> 2, val);
+ }
+
+ if (status & A5XX_CP_INT_CP_AHB_ERROR) {
+ u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
+ const char *access[16] = { "reserved", "reserved",
+ "timestamp lo", "timestamp hi", "pfp read", "pfp write",
+ "", "", "me read", "me write", "", "", "crashdump read",
+ "crashdump write" };
+
+ dev_err_ratelimited(gpu->dev->dev,
+ "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
+ status & 0xFFFFF, access[(status >> 24) & 0xF],
+ (status & (1 << 31)), status);
+ }
+}
+
+static void a5xx_rbbm_err_irq(struct msm_gpu *gpu)
+{
+ u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
+ u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
+
+ dev_err_ratelimited(gpu->dev->dev,
+ "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
+ val & (1 << 28) ? "WRITE" : "READ",
+ (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
+ (val >> 24) & 0xF);
+
+ /* Clear the error */
+ gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
+ }
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
+ gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
+ gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
+ gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
+
+ if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
+ dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
+}
+
+static void a5xx_uche_err_irq(struct msm_gpu *gpu)
+{
+ uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
+
+ addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
+
+ dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
+ addr);
+}
+
+static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
+{
+ dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
+}
+
+#define RBBM_ERROR_MASK \
+ (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
+ A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
+ A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
+
+static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
+{
+ u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
+
+ gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD, status);
+
+ if (status & RBBM_ERROR_MASK)
+ a5xx_rbbm_err_irq(gpu);
+
+ if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
+ a5xx_cp_err_irq(gpu);
+
+ if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
+ a5xx_uche_err_irq(gpu);
+
+ if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
+ a5xx_gpmu_err_irq(gpu);
+
+ if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
+ msm_gpu_retire(gpu);
+
+ return IRQ_HANDLED;
+}
+
+static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
+ REG_A5XX_CP_RB_RPTR_ADDR_HI),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
+ REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
+};
+
+static const u32 a5xx_registers[] = {
+ 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
+ 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
+ 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
+ 0x04E0, 0x0533, 0x0540, 0x0555, 0xF400, 0xF400, 0xF800, 0xF807,
+ 0x0800, 0x081A, 0x081F, 0x0841, 0x0860, 0x0860, 0x0880, 0x08A0,
+ 0x0B00, 0x0B12, 0x0B15, 0x0B28, 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD,
+ 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53, 0x0C60, 0x0C61, 0x0C80, 0x0C82,
+ 0x0C84, 0x0C85, 0x0C90, 0x0C98, 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2,
+ 0x2180, 0x2185, 0x2580, 0x2585, 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7,
+ 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8, 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8,
+ 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E, 0x2100, 0x211E, 0x2140, 0x2145,
+ 0x2500, 0x251E, 0x2540, 0x2545, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
+ 0x0D30, 0x0D30, 0x20C0, 0x20C0, 0x24C0, 0x24C0, 0x0E40, 0x0E43,
+ 0x0E4A, 0x0E4A, 0x0E50, 0x0E57, 0x0E60, 0x0E7C, 0x0E80, 0x0E8E,
+ 0x0E90, 0x0E96, 0x0EA0, 0x0EA8, 0x0EB0, 0x0EB2, 0xE140, 0xE147,
+ 0xE150, 0xE187, 0xE1A0, 0xE1A9, 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7,
+ 0xE1D0, 0xE1D1, 0xE200, 0xE201, 0xE210, 0xE21C, 0xE240, 0xE268,
+ 0xE000, 0xE006, 0xE010, 0xE09A, 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB,
+ 0xE100, 0xE105, 0xE380, 0xE38F, 0xE3B0, 0xE3B0, 0xE400, 0xE405,
+ 0xE408, 0xE4E9, 0xE4F0, 0xE4F0, 0xE280, 0xE280, 0xE282, 0xE2A3,
+ 0xE2A5, 0xE2C2, 0xE940, 0xE947, 0xE950, 0xE987, 0xE9A0, 0xE9A9,
+ 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7, 0xE9D0, 0xE9D1, 0xEA00, 0xEA01,
+ 0xEA10, 0xEA1C, 0xEA40, 0xEA68, 0xE800, 0xE806, 0xE810, 0xE89A,
+ 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB, 0xE900, 0xE905, 0xEB80, 0xEB8F,
+ 0xEBB0, 0xEBB0, 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0,
+ 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, 0xA800, 0xA8FF,
+ 0xAC60, 0xAC60, 0xB000, 0xB97F, 0xB9A0, 0xB9BF,
+ ~0
+};
+
+static void a5xx_dump(struct msm_gpu *gpu)
+{
+ dev_info(gpu->dev->dev, "status: %08x\n",
+ gpu_read(gpu, REG_A5XX_RBBM_STATUS));
+ adreno_dump(gpu);
+}
+
+static int a5xx_pm_resume(struct msm_gpu *gpu)
+{
+ int ret;
+
+ /* Turn on the core power */
+ ret = msm_gpu_pm_resume(gpu);
+ if (ret)
+ return ret;
+
+ /* Turn the RBCCU domain first to limit the chances of voltage droop */
+ gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
+
+ /* Wait 3 usecs before polling */
+ udelay(3);
+
+ ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
+ (1 << 20), (1 << 20));
+ if (ret) {
+ DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
+ gpu->name,
+ gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
+ return ret;
+ }
+
+ /* Turn on the SP domain */
+ gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
+ ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
+ (1 << 20), (1 << 20));
+ if (ret)
+ DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
+ gpu->name);
+
+ return ret;
+}
+
+static int a5xx_pm_suspend(struct msm_gpu *gpu)
+{
+ /* Clear the VBIF pipe before shutting down */
+ gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
+ spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
+
+ gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
+
+ /*
+ * Reset the VBIF before power collapse to avoid issue with FIFO
+ * entries
+ */
+ gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
+ gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
+
+ return msm_gpu_pm_suspend(gpu);
+}
+
+static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+{
+ *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
+ REG_A5XX_RBBM_PERFCTR_CP_0_HI);
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
+{
+ gpu->funcs->pm_resume(gpu);
+
+ seq_printf(m, "status: %08x\n",
+ gpu_read(gpu, REG_A5XX_RBBM_STATUS));
+ gpu->funcs->pm_suspend(gpu);
+
+ adreno_show(gpu, m);
+}
+#endif
+
+static const struct adreno_gpu_funcs funcs = {
+ .base = {
+ .get_param = adreno_get_param,
+ .hw_init = a5xx_hw_init,
+ .pm_suspend = a5xx_pm_suspend,
+ .pm_resume = a5xx_pm_resume,
+ .recover = a5xx_recover,
+ .last_fence = adreno_last_fence,
+ .submit = a5xx_submit,
+ .flush = adreno_flush,
+ .idle = a5xx_idle,
+ .irq = a5xx_irq,
+ .destroy = a5xx_destroy,
+ .show = a5xx_show,
+ },
+ .get_timestamp = a5xx_get_timestamp,
+};
+
+struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ struct platform_device *pdev = priv->gpu_pdev;
+ struct a5xx_gpu *a5xx_gpu = NULL;
+ struct adreno_gpu *adreno_gpu;
+ struct msm_gpu *gpu;
+ int ret;
+
+ if (!pdev) {
+ dev_err(dev->dev, "No A5XX device is defined\n");
+ return ERR_PTR(-ENXIO);
+ }
+
+ a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
+ if (!a5xx_gpu)
+ return ERR_PTR(-ENOMEM);
+
+ adreno_gpu = &a5xx_gpu->base;
+ gpu = &adreno_gpu->base;
+
+ a5xx_gpu->pdev = pdev;
+ adreno_gpu->registers = a5xx_registers;
+ adreno_gpu->reg_offsets = a5xx_register_offsets;
+
+ a5xx_gpu->lm_leakage = 0x4E001A;
+
+ ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
+ if (ret) {
+ a5xx_destroy(&(a5xx_gpu->base.base));
+ return ERR_PTR(ret);
+ }
+
+ return gpu;
+}
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
new file mode 100644
index 000000000000..1590f845d554
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2016 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 __A5XX_GPU_H__
+#define __A5XX_GPU_H__
+
+#include "adreno_gpu.h"
+
+/* Bringing over the hack from the previous targets */
+#undef ROP_COPY
+#undef ROP_XOR
+
+#include "a5xx.xml.h"
+
+struct a5xx_gpu {
+ struct adreno_gpu base;
+ struct platform_device *pdev;
+
+ struct drm_gem_object *pm4_bo;
+ uint64_t pm4_iova;
+
+ struct drm_gem_object *pfp_bo;
+ uint64_t pfp_iova;
+
+ struct drm_gem_object *gpmu_bo;
+ uint64_t gpmu_iova;
+ uint32_t gpmu_dwords;
+
+ uint32_t lm_leakage;
+};
+
+#define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base)
+
+int a5xx_power_init(struct msm_gpu *gpu);
+void a5xx_gpmu_ucode_init(struct msm_gpu *gpu);
+
+static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs,
+ uint32_t reg, uint32_t mask, uint32_t value)
+{
+ while (usecs--) {
+ udelay(1);
+ if ((gpu_read(gpu, reg) & mask) == value)
+ return 0;
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+
+#endif /* __A5XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c
new file mode 100644
index 000000000000..72d52c71f769
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -0,0 +1,344 @@
+/* Copyright (c) 2016 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/pm_opp.h>
+#include "a5xx_gpu.h"
+
+/*
+ * The GPMU data block is a block of shared registers that can be used to
+ * communicate back and forth. These "registers" are by convention with the GPMU
+ * firwmare and not bound to any specific hardware design
+ */
+
+#define AGC_INIT_BASE REG_A5XX_GPMU_DATA_RAM_BASE
+#define AGC_INIT_MSG_MAGIC (AGC_INIT_BASE + 5)
+#define AGC_MSG_BASE (AGC_INIT_BASE + 7)
+
+#define AGC_MSG_STATE (AGC_MSG_BASE + 0)
+#define AGC_MSG_COMMAND (AGC_MSG_BASE + 1)
+#define AGC_MSG_PAYLOAD_SIZE (AGC_MSG_BASE + 3)
+#define AGC_MSG_PAYLOAD(_o) ((AGC_MSG_BASE + 5) + (_o))
+
+#define AGC_POWER_CONFIG_PRODUCTION_ID 1
+#define AGC_INIT_MSG_VALUE 0xBABEFACE
+
+static struct {
+ uint32_t reg;
+ uint32_t value;
+} a5xx_sequence_regs[] = {
+ { 0xB9A1, 0x00010303 },
+ { 0xB9A2, 0x13000000 },
+ { 0xB9A3, 0x00460020 },
+ { 0xB9A4, 0x10000000 },
+ { 0xB9A5, 0x040A1707 },
+ { 0xB9A6, 0x00010000 },
+ { 0xB9A7, 0x0E000904 },
+ { 0xB9A8, 0x10000000 },
+ { 0xB9A9, 0x01165000 },
+ { 0xB9AA, 0x000E0002 },
+ { 0xB9AB, 0x03884141 },
+ { 0xB9AC, 0x10000840 },
+ { 0xB9AD, 0x572A5000 },
+ { 0xB9AE, 0x00000003 },
+ { 0xB9AF, 0x00000000 },
+ { 0xB9B0, 0x10000000 },
+ { 0xB828, 0x6C204010 },
+ { 0xB829, 0x6C204011 },
+ { 0xB82A, 0x6C204012 },
+ { 0xB82B, 0x6C204013 },
+ { 0xB82C, 0x6C204014 },
+ { 0xB90F, 0x00000004 },
+ { 0xB910, 0x00000002 },
+ { 0xB911, 0x00000002 },
+ { 0xB912, 0x00000002 },
+ { 0xB913, 0x00000002 },
+ { 0xB92F, 0x00000004 },
+ { 0xB930, 0x00000005 },
+ { 0xB931, 0x00000005 },
+ { 0xB932, 0x00000005 },
+ { 0xB933, 0x00000005 },
+ { 0xB96F, 0x00000001 },
+ { 0xB970, 0x00000003 },
+ { 0xB94F, 0x00000004 },
+ { 0xB950, 0x0000000B },
+ { 0xB951, 0x0000000B },
+ { 0xB952, 0x0000000B },
+ { 0xB953, 0x0000000B },
+ { 0xB907, 0x00000019 },
+ { 0xB927, 0x00000019 },
+ { 0xB947, 0x00000019 },
+ { 0xB967, 0x00000019 },
+ { 0xB987, 0x00000019 },
+ { 0xB906, 0x00220001 },
+ { 0xB926, 0x00220001 },
+ { 0xB946, 0x00220001 },
+ { 0xB966, 0x00220001 },
+ { 0xB986, 0x00300000 },
+ { 0xAC40, 0x0340FF41 },
+ { 0xAC41, 0x03BEFED0 },
+ { 0xAC42, 0x00331FED },
+ { 0xAC43, 0x021FFDD3 },
+ { 0xAC44, 0x5555AAAA },
+ { 0xAC45, 0x5555AAAA },
+ { 0xB9BA, 0x00000008 },
+};
+
+/*
+ * Get the actual voltage value for the operating point at the specified
+ * frequency
+ */
+static inline uint32_t _get_mvolts(struct msm_gpu *gpu, uint32_t freq)
+{
+ struct drm_device *dev = gpu->dev;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct platform_device *pdev = priv->gpu_pdev;
+ struct dev_pm_opp *opp;
+
+ opp = dev_pm_opp_find_freq_exact(&pdev->dev, freq, true);
+
+ return (!IS_ERR(opp)) ? dev_pm_opp_get_voltage(opp) / 1000 : 0;
+}
+
+/* Setup thermal limit management */
+static void a5xx_lm_setup(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+ unsigned int i;
+
+ /* Write the block of sequence registers */
+ for (i = 0; i < ARRAY_SIZE(a5xx_sequence_regs); i++)
+ gpu_write(gpu, a5xx_sequence_regs[i].reg,
+ a5xx_sequence_regs[i].value);
+
+ /* Hard code the A530 GPU thermal sensor ID for the GPMU */
+ gpu_write(gpu, REG_A5XX_GPMU_TEMP_SENSOR_ID, 0x60007);
+ gpu_write(gpu, REG_A5XX_GPMU_DELTA_TEMP_THRESHOLD, 0x01);
+ gpu_write(gpu, REG_A5XX_GPMU_TEMP_SENSOR_CONFIG, 0x01);
+
+ /* Until we get clock scaling 0 is always the active power level */
+ gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE, 0x80000000 | 0);
+
+ gpu_write(gpu, REG_A5XX_GPMU_BASE_LEAKAGE, a5xx_gpu->lm_leakage);
+
+ /* The threshold is fixed at 6000 for A530 */
+ gpu_write(gpu, REG_A5XX_GPMU_GPMU_PWR_THRESHOLD, 0x80000000 | 6000);
+
+ gpu_write(gpu, REG_A5XX_GPMU_BEC_ENABLE, 0x10001FFF);
+ gpu_write(gpu, REG_A5XX_GDPM_CONFIG1, 0x00201FF1);
+
+ /* Write the voltage table */
+ gpu_write(gpu, REG_A5XX_GPMU_BEC_ENABLE, 0x10001FFF);
+ gpu_write(gpu, REG_A5XX_GDPM_CONFIG1, 0x201FF1);
+
+ gpu_write(gpu, AGC_MSG_STATE, 1);
+ gpu_write(gpu, AGC_MSG_COMMAND, AGC_POWER_CONFIG_PRODUCTION_ID);
+
+ /* Write the max power - hard coded to 5448 for A530 */
+ gpu_write(gpu, AGC_MSG_PAYLOAD(0), 5448);
+ gpu_write(gpu, AGC_MSG_PAYLOAD(1), 1);
+
+ /*
+ * For now just write the one voltage level - we will do more when we
+ * can do scaling
+ */
+ gpu_write(gpu, AGC_MSG_PAYLOAD(2), _get_mvolts(gpu, gpu->fast_rate));
+ gpu_write(gpu, AGC_MSG_PAYLOAD(3), gpu->fast_rate / 1000000);
+
+ gpu_write(gpu, AGC_MSG_PAYLOAD_SIZE, 4 * sizeof(uint32_t));
+ gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE);
+}
+
+/* Enable SP/TP cpower collapse */
+static void a5xx_pc_init(struct msm_gpu *gpu)
+{
+ gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL, 0x7F);
+ gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_BINNING_CTRL, 0);
+ gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_INTER_FRAME_HYST, 0xA0080);
+ gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_STAGGER_DELAY, 0x600040);
+}
+
+/* Enable the GPMU microcontroller */
+static int a5xx_gpmu_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+ struct msm_ringbuffer *ring = gpu->rb;
+
+ if (!a5xx_gpu->gpmu_dwords)
+ return 0;
+
+ /* Turn off protected mode for this operation */
+ OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+ OUT_RING(ring, 0);
+
+ /* Kick off the IB to load the GPMU microcode */
+ OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
+ OUT_RING(ring, lower_32_bits(a5xx_gpu->gpmu_iova));
+ OUT_RING(ring, upper_32_bits(a5xx_gpu->gpmu_iova));
+ OUT_RING(ring, a5xx_gpu->gpmu_dwords);
+
+ /* Turn back on protected mode */
+ OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+ OUT_RING(ring, 1);
+
+ gpu->funcs->flush(gpu);
+
+ if (!gpu->funcs->idle(gpu)) {
+ DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n",
+ gpu->name);
+ return -EINVAL;
+ }
+
+ gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014);
+
+ /* Kick off the GPMU */
+ gpu_write(gpu, REG_A5XX_GPMU_CM3_SYSRESET, 0x0);
+
+ /*
+ * Wait for the GPMU to respond. It isn't fatal if it doesn't, we just
+ * won't have advanced power collapse.
+ */
+ if (spin_usecs(gpu, 25, REG_A5XX_GPMU_GENERAL_0, 0xFFFFFFFF,
+ 0xBABEFACE))
+ DRM_ERROR("%s: GPMU firmware initialization timed out\n",
+ gpu->name);
+
+ return 0;
+}
+
+/* Enable limits management */
+static void a5xx_lm_enable(struct msm_gpu *gpu)
+{
+ gpu_write(gpu, REG_A5XX_GDPM_INT_MASK, 0x0);
+ gpu_write(gpu, REG_A5XX_GDPM_INT_EN, 0x0A);
+ gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK, 0x01);
+ gpu_write(gpu, REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK, 0x50000);
+ gpu_write(gpu, REG_A5XX_GPMU_THROTTLE_UNMASK_FORCE_CTRL, 0x30000);
+
+ gpu_write(gpu, REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL, 0x011);
+}
+
+int a5xx_power_init(struct msm_gpu *gpu)
+{
+ int ret;
+
+ /* Set up the limits management */
+ a5xx_lm_setup(gpu);
+
+ /* Set up SP/TP power collpase */
+ a5xx_pc_init(gpu);
+
+ /* Start the GPMU */
+ ret = a5xx_gpmu_init(gpu);
+ if (ret)
+ return ret;
+
+ /* Start the limits management */
+ a5xx_lm_enable(gpu);
+
+ return 0;
+}
+
+void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+ struct drm_device *drm = gpu->dev;
+ const struct firmware *fw;
+ uint32_t dwords = 0, offset = 0, bosize;
+ unsigned int *data, *ptr, *cmds;
+ unsigned int cmds_size;
+
+ if (a5xx_gpu->gpmu_bo)
+ return;
+
+ /* Get the firmware */
+ if (request_firmware(&fw, adreno_gpu->info->gpmufw, drm->dev)) {
+ DRM_ERROR("%s: Could not get GPMU firmware. GPMU will not be active\n",
+ gpu->name);
+ return;
+ }
+
+ data = (unsigned int *) fw->data;
+
+ /*
+ * The first dword is the size of the remaining data in dwords. Use it
+ * as a checksum of sorts and make sure it matches the actual size of
+ * the firmware that we read
+ */
+
+ if (fw->size < 8 || (data[0] < 2) || (data[0] >= (fw->size >> 2)))
+ goto out;
+
+ /* The second dword is an ID - look for 2 (GPMU_FIRMWARE_ID) */
+ if (data[1] != 2)
+ goto out;
+
+ cmds = data + data[2] + 3;
+ cmds_size = data[0] - data[2] - 2;
+
+ /*
+ * A single type4 opcode can only have so many values attached so
+ * add enough opcodes to load the all the commands
+ */
+ bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2;
+
+ mutex_lock(&drm->struct_mutex);
+ a5xx_gpu->gpmu_bo = msm_gem_new(drm, bosize, MSM_BO_UNCACHED);
+ mutex_unlock(&drm->struct_mutex);
+
+ if (IS_ERR(a5xx_gpu->gpmu_bo))
+ goto err;
+
+ if (msm_gem_get_iova(a5xx_gpu->gpmu_bo, gpu->id, &a5xx_gpu->gpmu_iova))
+ goto err;
+
+ ptr = msm_gem_get_vaddr(a5xx_gpu->gpmu_bo);
+ if (!ptr)
+ goto err;
+
+ while (cmds_size > 0) {
+ int i;
+ uint32_t _size = cmds_size > TYPE4_MAX_PAYLOAD ?
+ TYPE4_MAX_PAYLOAD : cmds_size;
+
+ ptr[dwords++] = PKT4(REG_A5XX_GPMU_INST_RAM_BASE + offset,
+ _size);
+
+ for (i = 0; i < _size; i++)
+ ptr[dwords++] = *cmds++;
+
+ offset += _size;
+ cmds_size -= _size;
+ }
+
+ msm_gem_put_vaddr(a5xx_gpu->gpmu_bo);
+ a5xx_gpu->gpmu_dwords = dwords;
+
+ goto out;
+
+err:
+ if (a5xx_gpu->gpmu_iova)
+ msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);
+ if (a5xx_gpu->gpmu_bo)
+ drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
+
+ a5xx_gpu->gpmu_bo = NULL;
+ a5xx_gpu->gpmu_iova = 0;
+ a5xx_gpu->gpmu_dwords = 0;
+
+out:
+ /* No need to keep that firmware laying around anymore */
+ release_firmware(fw);
+}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index e81481d1b7df..4a33ba6f1244 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 ( 398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 431 bytes, from 2016-04-26 17:56:44)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
-- /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 ( 11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2016 by the following authors:
@@ -172,6 +173,14 @@ enum a3xx_color_swap {
XYZW = 3,
};
+enum a3xx_rb_blend_opcode {
+ BLEND_DST_PLUS_SRC = 0,
+ BLEND_SRC_MINUS_DST = 1,
+ BLEND_DST_MINUS_SRC = 2,
+ BLEND_MIN_DST_SRC = 3,
+ BLEND_MAX_DST_SRC = 4,
+};
+
#define REG_AXXX_CP_RB_BASE 0x000001c0
#define REG_AXXX_CP_RB_CNTL 0x000001c1
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 5127b75dbf40..893eb2b2531b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -25,9 +25,6 @@ bool hang_debug = false;
MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
module_param_named(hang_debug, hang_debug, bool, 0600);
-struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
-struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
-
static const struct adreno_info gpulist[] = {
{
.rev = ADRENO_REV(3, 0, 5, ANY_ID),
@@ -77,6 +74,15 @@ static const struct adreno_info gpulist[] = {
.pfpfw = "a420_pfp.fw",
.gmem = (SZ_1M + SZ_512K),
.init = a4xx_gpu_init,
+ }, {
+ .rev = ADRENO_REV(5, 3, 0, ANY_ID),
+ .revn = 530,
+ .name = "A530",
+ .pm4fw = "a530_pm4.fw",
+ .pfpfw = "a530_pfp.fw",
+ .gmem = SZ_1M,
+ .init = a5xx_gpu_init,
+ .gpmufw = "a530v3_gpmu.fw2",
},
};
@@ -86,6 +92,8 @@ MODULE_FIRMWARE("a330_pm4.fw");
MODULE_FIRMWARE("a330_pfp.fw");
MODULE_FIRMWARE("a420_pm4.fw");
MODULE_FIRMWARE("a420_pfp.fw");
+MODULE_FIRMWARE("a530_fm4.fw");
+MODULE_FIRMWARE("a530_pfp.fw");
static inline bool _rev_match(uint8_t entry, uint8_t id)
{
@@ -148,12 +156,16 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
gpu->funcs->pm_resume(gpu);
mutex_unlock(&dev->struct_mutex);
+
+ disable_irq(gpu->irq);
+
ret = gpu->funcs->hw_init(gpu);
if (ret) {
dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
gpu->funcs->destroy(gpu);
gpu = NULL;
} else {
+ enable_irq(gpu->irq);
/* give inactive pm a chance to kick in: */
msm_gpu_retire(gpu);
}
@@ -169,12 +181,20 @@ static void set_gpu_pdev(struct drm_device *dev,
priv->gpu_pdev = pdev;
}
+static const struct {
+ const char *str;
+ uint32_t flag;
+} quirks[] = {
+ { "qcom,gpu-quirk-two-pass-use-wfi", ADRENO_QUIRK_TWO_PASS_USE_WFI },
+ { "qcom,gpu-quirk-fault-detect-mask", ADRENO_QUIRK_FAULT_DETECT_MASK },
+};
+
static int adreno_bind(struct device *dev, struct device *master, void *data)
{
static struct adreno_platform_config config = {};
struct device_node *child, *node = dev->of_node;
u32 val;
- int ret;
+ int ret, i;
ret = of_property_read_u32(node, "qcom,chipid", &val);
if (ret) {
@@ -208,6 +228,10 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
return -ENXIO;
}
+ for (i = 0; i < ARRAY_SIZE(quirks); i++)
+ if (of_property_read_bool(node, quirks[i].str))
+ config.quirks |= quirks[i].flag;
+
dev->platform_data = &config;
set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
return 0;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index f386f463278d..a18126150e11 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -22,7 +22,7 @@
#include "msm_mmu.h"
#define RB_SIZE SZ_32K
-#define RB_BLKSIZE 16
+#define RB_BLKSIZE 32
int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
{
@@ -54,9 +54,6 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
}
}
-#define rbmemptr(adreno_gpu, member) \
- ((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member))
-
int adreno_hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -79,11 +76,14 @@ int adreno_hw_init(struct msm_gpu *gpu)
(adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0));
/* Setup ringbuffer address: */
- adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_BASE, gpu->rb_iova);
+ adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE,
+ REG_ADRENO_CP_RB_BASE_HI, gpu->rb_iova);
- if (!adreno_is_a430(adreno_gpu))
- adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
- rbmemptr(adreno_gpu, rptr));
+ if (!adreno_is_a430(adreno_gpu)) {
+ adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
+ REG_ADRENO_CP_RB_RPTR_ADDR_HI,
+ rbmemptr(adreno_gpu, rptr));
+ }
return 0;
}
@@ -126,11 +126,14 @@ void adreno_recover(struct msm_gpu *gpu)
adreno_gpu->memptrs->wptr = 0;
gpu->funcs->pm_resume(gpu);
+
+ disable_irq(gpu->irq);
ret = gpu->funcs->hw_init(gpu);
if (ret) {
dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
/* hmm, oh well? */
}
+ enable_irq(gpu->irq);
}
void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
@@ -218,19 +221,18 @@ void adreno_flush(struct msm_gpu *gpu)
adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr);
}
-void adreno_idle(struct msm_gpu *gpu)
+bool adreno_idle(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
uint32_t wptr = get_wptr(gpu->rb);
- int ret;
/* wait for CP to drain ringbuffer: */
- ret = spin_until(get_rptr(adreno_gpu) == wptr);
-
- if (ret)
- DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+ if (!spin_until(get_rptr(adreno_gpu) == wptr))
+ return true;
/* TODO maybe we need to reset GPU here to recover from hang? */
+ DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+ return false;
}
#ifdef CONFIG_DEBUG_FS
@@ -278,7 +280,6 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
void adreno_dump_info(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- int i;
printk("revision: %d (%d.%d.%d.%d)\n",
adreno_gpu->info->revn, adreno_gpu->rev.core,
@@ -290,11 +291,6 @@ void adreno_dump_info(struct msm_gpu *gpu)
printk("rptr: %d\n", get_rptr(adreno_gpu));
printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
printk("rb wptr: %d\n", get_wptr(gpu->rb));
-
- for (i = 0; i < 8; i++) {
- printk("CP_SCRATCH_REG%d: %u\n", i,
- gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
- }
}
/* would be nice to not have to duplicate the _show() stuff with printk(): */
@@ -350,6 +346,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
adreno_gpu->gmem = adreno_gpu->info->gmem;
adreno_gpu->revn = adreno_gpu->info->revn;
adreno_gpu->rev = config->rev;
+ adreno_gpu->quirks = config->quirks;
gpu->fast_rate = config->fast_rate;
gpu->slow_rate = config->slow_rate;
@@ -381,7 +378,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret;
}
- mmu = gpu->mmu;
+ mmu = gpu->aspace->mmu;
if (mmu) {
ret = mmu->funcs->attach(mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index a54f6e036b4a..e8d55b0306ed 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -28,6 +28,9 @@
#include "adreno_pm4.xml.h"
#define REG_ADRENO_DEFINE(_offset, _reg) [_offset] = (_reg) + 1
+#define REG_SKIP ~0
+#define REG_ADRENO_SKIP(_offset) [_offset] = REG_SKIP
+
/**
* adreno_regs: List of registers that are used in across all
* 3D devices. Each device type has different offset value for the same
@@ -35,73 +38,21 @@
* and are indexed by the enumeration values defined in this enum
*/
enum adreno_regs {
- REG_ADRENO_CP_DEBUG,
- REG_ADRENO_CP_ME_RAM_WADDR,
- REG_ADRENO_CP_ME_RAM_DATA,
- REG_ADRENO_CP_PFP_UCODE_DATA,
- REG_ADRENO_CP_PFP_UCODE_ADDR,
- REG_ADRENO_CP_WFI_PEND_CTR,
REG_ADRENO_CP_RB_BASE,
+ REG_ADRENO_CP_RB_BASE_HI,
REG_ADRENO_CP_RB_RPTR_ADDR,
+ REG_ADRENO_CP_RB_RPTR_ADDR_HI,
REG_ADRENO_CP_RB_RPTR,
REG_ADRENO_CP_RB_WPTR,
- REG_ADRENO_CP_PROTECT_CTRL,
- REG_ADRENO_CP_ME_CNTL,
REG_ADRENO_CP_RB_CNTL,
- REG_ADRENO_CP_IB1_BASE,
- REG_ADRENO_CP_IB1_BUFSZ,
- REG_ADRENO_CP_IB2_BASE,
- REG_ADRENO_CP_IB2_BUFSZ,
- REG_ADRENO_CP_TIMESTAMP,
- REG_ADRENO_CP_ME_RAM_RADDR,
- REG_ADRENO_CP_ROQ_ADDR,
- REG_ADRENO_CP_ROQ_DATA,
- REG_ADRENO_CP_MERCIU_ADDR,
- REG_ADRENO_CP_MERCIU_DATA,
- REG_ADRENO_CP_MERCIU_DATA2,
- REG_ADRENO_CP_MEQ_ADDR,
- REG_ADRENO_CP_MEQ_DATA,
- REG_ADRENO_CP_HW_FAULT,
- REG_ADRENO_CP_PROTECT_STATUS,
- REG_ADRENO_SCRATCH_ADDR,
- REG_ADRENO_SCRATCH_UMSK,
- REG_ADRENO_SCRATCH_REG2,
- REG_ADRENO_RBBM_STATUS,
- REG_ADRENO_RBBM_PERFCTR_CTL,
- REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
- REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
- REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2,
- REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
- REG_ADRENO_RBBM_INT_0_MASK,
- REG_ADRENO_RBBM_INT_0_STATUS,
- REG_ADRENO_RBBM_AHB_ERROR_STATUS,
- REG_ADRENO_RBBM_PM_OVERRIDE2,
- REG_ADRENO_RBBM_AHB_CMD,
- REG_ADRENO_RBBM_INT_CLEAR_CMD,
- REG_ADRENO_RBBM_SW_RESET_CMD,
- REG_ADRENO_RBBM_CLOCK_CTL,
- REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS,
- REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS,
- REG_ADRENO_VPC_DEBUG_RAM_SEL,
- REG_ADRENO_VPC_DEBUG_RAM_READ,
- REG_ADRENO_VSC_SIZE_ADDRESS,
- REG_ADRENO_VFD_CONTROL_0,
- REG_ADRENO_VFD_INDEX_MAX,
- REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
- REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
- REG_ADRENO_SP_VS_OBJ_START_REG,
- REG_ADRENO_SP_FS_OBJ_START_REG,
- REG_ADRENO_PA_SC_AA_CONFIG,
- REG_ADRENO_SQ_GPR_MANAGEMENT,
- REG_ADRENO_SQ_INST_STORE_MANAGMENT,
- REG_ADRENO_TP0_CHICKEN,
- REG_ADRENO_RBBM_RBBM_CTL,
- REG_ADRENO_UCHE_INVALIDATE0,
- REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
- REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
REG_ADRENO_REGISTER_MAX,
};
+enum adreno_quirks {
+ ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
+ ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
+};
+
struct adreno_rev {
uint8_t core;
uint8_t major;
@@ -122,12 +73,16 @@ struct adreno_info {
uint32_t revn;
const char *name;
const char *pm4fw, *pfpfw;
+ const char *gpmufw;
uint32_t gmem;
struct msm_gpu *(*init)(struct drm_device *dev);
};
const struct adreno_info *adreno_info(struct adreno_rev rev);
+#define rbmemptr(adreno_gpu, member) \
+ ((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member))
+
struct adreno_rbmemptrs {
volatile uint32_t rptr;
volatile uint32_t wptr;
@@ -153,7 +108,7 @@ struct adreno_gpu {
// different for z180..
struct adreno_rbmemptrs *memptrs;
struct drm_gem_object *memptrs_bo;
- uint32_t memptrs_iova;
+ uint64_t memptrs_iova;
/*
* Register offsets are different between some GPUs.
@@ -161,6 +116,8 @@ struct adreno_gpu {
* code (a3xx_gpu.c) and stored in this common location.
*/
const unsigned int *reg_offsets;
+
+ uint32_t quirks;
};
#define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base)
@@ -171,6 +128,7 @@ struct adreno_platform_config {
#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *bus_scale_table;
#endif
+ uint32_t quirks;
};
#define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
@@ -234,6 +192,11 @@ static inline int adreno_is_a430(struct adreno_gpu *gpu)
return gpu->revn == 430;
}
+static inline int adreno_is_a530(struct adreno_gpu *gpu)
+{
+ return gpu->revn == 530;
+}
+
int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
int adreno_hw_init(struct msm_gpu *gpu);
uint32_t adreno_last_fence(struct msm_gpu *gpu);
@@ -241,7 +204,7 @@ void adreno_recover(struct msm_gpu *gpu);
void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx);
void adreno_flush(struct msm_gpu *gpu);
-void adreno_idle(struct msm_gpu *gpu);
+bool adreno_idle(struct msm_gpu *gpu);
#ifdef CONFIG_DEBUG_FS
void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
#endif
@@ -278,8 +241,38 @@ OUT_PKT3(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8));
}
+static inline u32 PM4_PARITY(u32 val)
+{
+ return (0x9669 >> (0xF & (val ^
+ (val >> 4) ^ (val >> 8) ^ (val >> 12) ^
+ (val >> 16) ^ ((val) >> 20) ^ (val >> 24) ^
+ (val >> 28)))) & 1;
+}
+
+/* Maximum number of values that can be executed for one opcode */
+#define TYPE4_MAX_PAYLOAD 127
+
+#define PKT4(_reg, _cnt) \
+ (CP_TYPE4_PKT | ((_cnt) << 0) | (PM4_PARITY((_cnt)) << 7) | \
+ (((_reg) & 0x3FFFF) << 8) | (PM4_PARITY((_reg)) << 27))
+
+static inline void
+OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
+{
+ adreno_wait_ring(ring->gpu, cnt + 1);
+ OUT_RING(ring, PKT4(regindx, cnt));
+}
+
+static inline void
+OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
+{
+ adreno_wait_ring(ring->gpu, cnt + 1);
+ OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) |
+ ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23));
+}
+
/*
- * adreno_checkreg_off() - Checks the validity of a register enum
+ * adreno_reg_check() - Checks the validity of a register enum
* @gpu: Pointer to struct adreno_gpu
* @offset_name: The register enum that is checked
*/
@@ -290,6 +283,16 @@ static inline bool adreno_reg_check(struct adreno_gpu *gpu,
!gpu->reg_offsets[offset_name]) {
BUG();
}
+
+ /*
+ * REG_SKIP is a special value that tell us that the register in
+ * question isn't implemented on target but don't trigger a BUG(). This
+ * is used to cleanly implement adreno_gpu_write64() and
+ * adreno_gpu_read64() in a generic fashion
+ */
+ if (gpu->reg_offsets[offset_name] == REG_SKIP)
+ return false;
+
return true;
}
@@ -311,4 +314,39 @@ static inline void adreno_gpu_write(struct adreno_gpu *gpu,
gpu_write(&gpu->base, reg - 1, data);
}
+struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
+struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
+struct msm_gpu *a5xx_gpu_init(struct drm_device *dev);
+
+static inline void adreno_gpu_write64(struct adreno_gpu *gpu,
+ enum adreno_regs lo, enum adreno_regs hi, u64 data)
+{
+ adreno_gpu_write(gpu, lo, lower_32_bits(data));
+ adreno_gpu_write(gpu, hi, upper_32_bits(data));
+}
+
+/*
+ * Given a register and a count, return a value to program into
+ * REG_CP_PROTECT_REG(n) - this will block both reads and writes for _len
+ * registers starting at _reg.
+ *
+ * The register base needs to be a multiple of the length. If it is not, the
+ * hardware will quietly mask off the bits for you and shift the size. For
+ * example, if you intend the protection to start at 0x07 for a length of 4
+ * (0x07-0x0A) the hardware will actually protect (0x04-0x07) which might
+ * expose registers you intended to protect!
+ */
+#define ADRENO_PROTECT_RW(_reg, _len) \
+ ((1 << 30) | (1 << 29) | \
+ ((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
+
+/*
+ * Same as above, but allow reads over the range. For areas of mixed use (such
+ * as performance counters) this allows us to protect a much larger range with a
+ * single register
+ */
+#define ADRENO_PROTECT_RDONLY(_reg, _len) \
+ ((1 << 29) \
+ ((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
+
#endif /* __ADRENO_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index d7477ff867c9..6a2930e75503 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 ( 398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 431 bytes, from 2016-04-26 17:56:44)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
-- /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 ( 11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml ( 90321 bytes, from 2016-11-28 16:50:05)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2016 by the following authors:
@@ -58,6 +59,7 @@ enum vgt_event_type {
RST_PIX_CNT = 13,
RST_VTX_CNT = 14,
TILE_FLUSH = 15,
+ STAT_EVENT = 16,
CACHE_FLUSH_AND_INV_TS_EVENT = 20,
ZPASS_DONE = 21,
CACHE_FLUSH_AND_INV_EVENT = 22,
@@ -65,6 +67,10 @@ enum vgt_event_type {
PERFCOUNTER_STOP = 24,
VS_FETCH_DONE = 27,
FACENESS_FLUSH = 28,
+ UNK_1C = 28,
+ UNK_1D = 29,
+ BLIT = 30,
+ UNK_26 = 38,
};
enum pc_di_primtype {
@@ -82,7 +88,6 @@ enum pc_di_primtype {
DI_PT_LINESTRIP_ADJ = 11,
DI_PT_TRI_ADJ = 12,
DI_PT_TRISTRIP_ADJ = 13,
- DI_PT_PATCHES = 34,
};
enum pc_di_src_sel {
@@ -110,11 +115,15 @@ enum adreno_pm4_packet_type {
CP_TYPE1_PKT = 0x40000000,
CP_TYPE2_PKT = 0x80000000,
CP_TYPE3_PKT = 0xc0000000,
+ CP_TYPE4_PKT = 0x40000000,
+ CP_TYPE7_PKT = 0x70000000,
};
enum adreno_pm4_type3_packets {
CP_ME_INIT = 72,
CP_NOP = 16,
+ CP_PREEMPT_ENABLE = 28,
+ CP_PREEMPT_TOKEN = 30,
CP_INDIRECT_BUFFER = 63,
CP_INDIRECT_BUFFER_PFD = 55,
CP_WAIT_FOR_IDLE = 38,
@@ -163,6 +172,7 @@ enum adreno_pm4_type3_packets {
CP_TEST_TWO_MEMS = 113,
CP_REG_WR_NO_CTXT = 120,
CP_RECORD_PFP_TIMESTAMP = 17,
+ CP_SET_SECURE_MODE = 102,
CP_WAIT_FOR_ME = 19,
CP_SET_DRAW_STATE = 67,
CP_DRAW_INDX_OFFSET = 56,
@@ -178,6 +188,22 @@ enum adreno_pm4_type3_packets {
CP_WAIT_MEM_WRITES = 18,
CP_COND_REG_EXEC = 71,
CP_MEM_TO_REG = 66,
+ CP_EXEC_CS = 51,
+ CP_PERFCOUNTER_ACTION = 80,
+ CP_SMMU_TABLE_UPDATE = 83,
+ CP_CONTEXT_REG_BUNCH = 92,
+ CP_YIELD_ENABLE = 28,
+ CP_SKIP_IB2_ENABLE_GLOBAL = 29,
+ CP_SKIP_IB2_ENABLE_LOCAL = 35,
+ CP_SET_SUBDRAW_SIZE = 53,
+ CP_SET_VISIBILITY_OVERRIDE = 100,
+ CP_PREEMPT_ENABLE_GLOBAL = 105,
+ CP_PREEMPT_ENABLE_LOCAL = 106,
+ CP_CONTEXT_SWITCH_YIELD = 107,
+ CP_SET_RENDER_MODE = 108,
+ CP_COMPUTE_CHECKPOINT = 110,
+ CP_MEM_TO_MEM = 115,
+ CP_BLIT = 44,
IN_IB_PREFETCH_END = 23,
IN_SUBBLK_PREFETCH = 31,
IN_INSTR_PREFETCH = 32,
@@ -196,6 +222,7 @@ enum adreno_state_block {
SB_VERT_SHADER = 4,
SB_GEOM_SHADER = 5,
SB_FRAG_SHADER = 6,
+ SB_COMPUTE_SHADER = 7,
};
enum adreno_state_type {
@@ -218,6 +245,17 @@ enum a4xx_index_size {
INDEX4_SIZE_32_BIT = 2,
};
+enum render_mode_cmd {
+ BYPASS = 1,
+ GMEM = 3,
+ BLIT2D = 5,
+};
+
+enum cp_blit_cmd {
+ BLIT_OP_FILL = 0,
+ BLIT_OP_BLIT = 1,
+};
+
#define REG_CP_LOAD_STATE_0 0x00000000
#define CP_LOAD_STATE_0_DST_OFF__MASK 0x0000ffff
#define CP_LOAD_STATE_0_DST_OFF__SHIFT 0
@@ -258,6 +296,14 @@ static inline uint32_t CP_LOAD_STATE_1_EXT_SRC_ADDR(uint32_t val)
return ((val >> 2) << CP_LOAD_STATE_1_EXT_SRC_ADDR__SHIFT) & CP_LOAD_STATE_1_EXT_SRC_ADDR__MASK;
}
+#define REG_CP_LOAD_STATE_2 0x00000002
+#define CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__MASK 0xffffffff
+#define CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__SHIFT 0
+static inline uint32_t CP_LOAD_STATE_2_EXT_SRC_ADDR_HI(uint32_t val)
+{
+ return ((val) << CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__SHIFT) & CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__MASK;
+}
+
#define REG_CP_DRAW_INDX_0 0x00000000
#define CP_DRAW_INDX_0_VIZ_QUERY__MASK 0xffffffff
#define CP_DRAW_INDX_0_VIZ_QUERY__SHIFT 0
@@ -389,7 +435,12 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel va
{
return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
}
-#define CP_DRAW_INDX_OFFSET_0_TESSELLATE 0x00000100
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK 0x00000300
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT 8
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT) & CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK;
+}
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000c00
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 10
static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
@@ -437,30 +488,40 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_5_INDX_SIZE(uint32_t val)
return ((val) << CP_DRAW_INDX_OFFSET_5_INDX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_5_INDX_SIZE__MASK;
}
-#define REG_CP_SET_DRAW_STATE_0 0x00000000
-#define CP_SET_DRAW_STATE_0_COUNT__MASK 0x0000ffff
-#define CP_SET_DRAW_STATE_0_COUNT__SHIFT 0
-static inline uint32_t CP_SET_DRAW_STATE_0_COUNT(uint32_t val)
+static inline uint32_t REG_CP_SET_DRAW_STATE_(uint32_t i0) { return 0x00000000 + 0x3*i0; }
+
+static inline uint32_t REG_CP_SET_DRAW_STATE__0(uint32_t i0) { return 0x00000000 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__0_COUNT__MASK 0x0000ffff
+#define CP_SET_DRAW_STATE__0_COUNT__SHIFT 0
+static inline uint32_t CP_SET_DRAW_STATE__0_COUNT(uint32_t val)
{
- return ((val) << CP_SET_DRAW_STATE_0_COUNT__SHIFT) & CP_SET_DRAW_STATE_0_COUNT__MASK;
+ return ((val) << CP_SET_DRAW_STATE__0_COUNT__SHIFT) & CP_SET_DRAW_STATE__0_COUNT__MASK;
}
-#define CP_SET_DRAW_STATE_0_DIRTY 0x00010000
-#define CP_SET_DRAW_STATE_0_DISABLE 0x00020000
-#define CP_SET_DRAW_STATE_0_DISABLE_ALL_GROUPS 0x00040000
-#define CP_SET_DRAW_STATE_0_LOAD_IMMED 0x00080000
-#define CP_SET_DRAW_STATE_0_GROUP_ID__MASK 0x1f000000
-#define CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT 24
-static inline uint32_t CP_SET_DRAW_STATE_0_GROUP_ID(uint32_t val)
+#define CP_SET_DRAW_STATE__0_DIRTY 0x00010000
+#define CP_SET_DRAW_STATE__0_DISABLE 0x00020000
+#define CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS 0x00040000
+#define CP_SET_DRAW_STATE__0_LOAD_IMMED 0x00080000
+#define CP_SET_DRAW_STATE__0_GROUP_ID__MASK 0x1f000000
+#define CP_SET_DRAW_STATE__0_GROUP_ID__SHIFT 24
+static inline uint32_t CP_SET_DRAW_STATE__0_GROUP_ID(uint32_t val)
{
- return ((val) << CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE_0_GROUP_ID__MASK;
+ return ((val) << CP_SET_DRAW_STATE__0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE__0_GROUP_ID__MASK;
}
-#define REG_CP_SET_DRAW_STATE_1 0x00000001
-#define CP_SET_DRAW_STATE_1_ADDR__MASK 0xffffffff
-#define CP_SET_DRAW_STATE_1_ADDR__SHIFT 0
-static inline uint32_t CP_SET_DRAW_STATE_1_ADDR(uint32_t val)
+static inline uint32_t REG_CP_SET_DRAW_STATE__1(uint32_t i0) { return 0x00000001 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__1_ADDR_LO__MASK 0xffffffff
+#define CP_SET_DRAW_STATE__1_ADDR_LO__SHIFT 0
+static inline uint32_t CP_SET_DRAW_STATE__1_ADDR_LO(uint32_t val)
{
- return ((val) << CP_SET_DRAW_STATE_1_ADDR__SHIFT) & CP_SET_DRAW_STATE_1_ADDR__MASK;
+ return ((val) << CP_SET_DRAW_STATE__1_ADDR_LO__SHIFT) & CP_SET_DRAW_STATE__1_ADDR_LO__MASK;
+}
+
+static inline uint32_t REG_CP_SET_DRAW_STATE__2(uint32_t i0) { return 0x00000002 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__2_ADDR_HI__MASK 0xffffffff
+#define CP_SET_DRAW_STATE__2_ADDR_HI__SHIFT 0
+static inline uint32_t CP_SET_DRAW_STATE__2_ADDR_HI(uint32_t val)
+{
+ return ((val) << CP_SET_DRAW_STATE__2_ADDR_HI__SHIFT) & CP_SET_DRAW_STATE__2_ADDR_HI__MASK;
}
#define REG_CP_SET_BIN_0 0x00000000
@@ -533,5 +594,192 @@ static inline uint32_t CP_REG_TO_MEM_1_DEST(uint32_t val)
return ((val) << CP_REG_TO_MEM_1_DEST__SHIFT) & CP_REG_TO_MEM_1_DEST__MASK;
}
+#define REG_CP_DISPATCH_COMPUTE_0 0x00000000
+
+#define REG_CP_DISPATCH_COMPUTE_1 0x00000001
+#define CP_DISPATCH_COMPUTE_1_X__MASK 0xffffffff
+#define CP_DISPATCH_COMPUTE_1_X__SHIFT 0
+static inline uint32_t CP_DISPATCH_COMPUTE_1_X(uint32_t val)
+{
+ return ((val) << CP_DISPATCH_COMPUTE_1_X__SHIFT) & CP_DISPATCH_COMPUTE_1_X__MASK;
+}
+
+#define REG_CP_DISPATCH_COMPUTE_2 0x00000002
+#define CP_DISPATCH_COMPUTE_2_Y__MASK 0xffffffff
+#define CP_DISPATCH_COMPUTE_2_Y__SHIFT 0
+static inline uint32_t CP_DISPATCH_COMPUTE_2_Y(uint32_t val)
+{
+ return ((val) << CP_DISPATCH_COMPUTE_2_Y__SHIFT) & CP_DISPATCH_COMPUTE_2_Y__MASK;
+}
+
+#define REG_CP_DISPATCH_COMPUTE_3 0x00000003
+#define CP_DISPATCH_COMPUTE_3_Z__MASK 0xffffffff
+#define CP_DISPATCH_COMPUTE_3_Z__SHIFT 0
+static inline uint32_t CP_DISPATCH_COMPUTE_3_Z(uint32_t val)
+{
+ return ((val) << CP_DISPATCH_COMPUTE_3_Z__SHIFT) & CP_DISPATCH_COMPUTE_3_Z__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_0 0x00000000
+#define CP_SET_RENDER_MODE_0_MODE__MASK 0x000001ff
+#define CP_SET_RENDER_MODE_0_MODE__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_0_MODE(enum render_mode_cmd val)
+{
+ return ((val) << CP_SET_RENDER_MODE_0_MODE__SHIFT) & CP_SET_RENDER_MODE_0_MODE__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_1 0x00000001
+#define CP_SET_RENDER_MODE_1_ADDR_0_LO__MASK 0xffffffff
+#define CP_SET_RENDER_MODE_1_ADDR_0_LO__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_1_ADDR_0_LO(uint32_t val)
+{
+ return ((val) << CP_SET_RENDER_MODE_1_ADDR_0_LO__SHIFT) & CP_SET_RENDER_MODE_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_2 0x00000002
+#define CP_SET_RENDER_MODE_2_ADDR_0_HI__MASK 0xffffffff
+#define CP_SET_RENDER_MODE_2_ADDR_0_HI__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_2_ADDR_0_HI(uint32_t val)
+{
+ return ((val) << CP_SET_RENDER_MODE_2_ADDR_0_HI__SHIFT) & CP_SET_RENDER_MODE_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_3 0x00000003
+#define CP_SET_RENDER_MODE_3_GMEM_ENABLE 0x00000010
+
+#define REG_CP_SET_RENDER_MODE_4 0x00000004
+
+#define REG_CP_SET_RENDER_MODE_5 0x00000005
+#define CP_SET_RENDER_MODE_5_ADDR_1_LEN__MASK 0xffffffff
+#define CP_SET_RENDER_MODE_5_ADDR_1_LEN__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_5_ADDR_1_LEN(uint32_t val)
+{
+ return ((val) << CP_SET_RENDER_MODE_5_ADDR_1_LEN__SHIFT) & CP_SET_RENDER_MODE_5_ADDR_1_LEN__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_6 0x00000006
+#define CP_SET_RENDER_MODE_6_ADDR_1_LO__MASK 0xffffffff
+#define CP_SET_RENDER_MODE_6_ADDR_1_LO__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_6_ADDR_1_LO(uint32_t val)
+{
+ return ((val) << CP_SET_RENDER_MODE_6_ADDR_1_LO__SHIFT) & CP_SET_RENDER_MODE_6_ADDR_1_LO__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_7 0x00000007
+#define CP_SET_RENDER_MODE_7_ADDR_1_HI__MASK 0xffffffff
+#define CP_SET_RENDER_MODE_7_ADDR_1_HI__SHIFT 0
+static inline uint32_t CP_SET_RENDER_MODE_7_ADDR_1_HI(uint32_t val)
+{
+ return ((val) << CP_SET_RENDER_MODE_7_ADDR_1_HI__SHIFT) & CP_SET_RENDER_MODE_7_ADDR_1_HI__MASK;
+}
+
+#define REG_CP_PERFCOUNTER_ACTION_0 0x00000000
+
+#define REG_CP_PERFCOUNTER_ACTION_1 0x00000001
+#define CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__MASK 0xffffffff
+#define CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__SHIFT 0
+static inline uint32_t CP_PERFCOUNTER_ACTION_1_ADDR_0_LO(uint32_t val)
+{
+ return ((val) << CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__SHIFT) & CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_PERFCOUNTER_ACTION_2 0x00000002
+#define CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__MASK 0xffffffff
+#define CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__SHIFT 0
+static inline uint32_t CP_PERFCOUNTER_ACTION_2_ADDR_0_HI(uint32_t val)
+{
+ return ((val) << CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__SHIFT) & CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_0 0x00000000
+#define CP_EVENT_WRITE_0_EVENT__MASK 0x000000ff
+#define CP_EVENT_WRITE_0_EVENT__SHIFT 0
+static inline uint32_t CP_EVENT_WRITE_0_EVENT(enum vgt_event_type val)
+{
+ return ((val) << CP_EVENT_WRITE_0_EVENT__SHIFT) & CP_EVENT_WRITE_0_EVENT__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_1 0x00000001
+#define CP_EVENT_WRITE_1_ADDR_0_LO__MASK 0xffffffff
+#define CP_EVENT_WRITE_1_ADDR_0_LO__SHIFT 0
+static inline uint32_t CP_EVENT_WRITE_1_ADDR_0_LO(uint32_t val)
+{
+ return ((val) << CP_EVENT_WRITE_1_ADDR_0_LO__SHIFT) & CP_EVENT_WRITE_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_2 0x00000002
+#define CP_EVENT_WRITE_2_ADDR_0_HI__MASK 0xffffffff
+#define CP_EVENT_WRITE_2_ADDR_0_HI__SHIFT 0
+static inline uint32_t CP_EVENT_WRITE_2_ADDR_0_HI(uint32_t val)
+{
+ return ((val) << CP_EVENT_WRITE_2_ADDR_0_HI__SHIFT) & CP_EVENT_WRITE_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_3 0x00000003
+
+#define REG_CP_BLIT_0 0x00000000
+#define CP_BLIT_0_OP__MASK 0x0000000f
+#define CP_BLIT_0_OP__SHIFT 0
+static inline uint32_t CP_BLIT_0_OP(enum cp_blit_cmd val)
+{
+ return ((val) << CP_BLIT_0_OP__SHIFT) & CP_BLIT_0_OP__MASK;
+}
+
+#define REG_CP_BLIT_1 0x00000001
+#define CP_BLIT_1_SRC_X1__MASK 0x0000ffff
+#define CP_BLIT_1_SRC_X1__SHIFT 0
+static inline uint32_t CP_BLIT_1_SRC_X1(uint32_t val)
+{
+ return ((val) << CP_BLIT_1_SRC_X1__SHIFT) & CP_BLIT_1_SRC_X1__MASK;
+}
+#define CP_BLIT_1_SRC_Y1__MASK 0xffff0000
+#define CP_BLIT_1_SRC_Y1__SHIFT 16
+static inline uint32_t CP_BLIT_1_SRC_Y1(uint32_t val)
+{
+ return ((val) << CP_BLIT_1_SRC_Y1__SHIFT) & CP_BLIT_1_SRC_Y1__MASK;
+}
+
+#define REG_CP_BLIT_2 0x00000002
+#define CP_BLIT_2_SRC_X2__MASK 0x0000ffff
+#define CP_BLIT_2_SRC_X2__SHIFT 0
+static inline uint32_t CP_BLIT_2_SRC_X2(uint32_t val)
+{
+ return ((val) << CP_BLIT_2_SRC_X2__SHIFT) & CP_BLIT_2_SRC_X2__MASK;
+}
+#define CP_BLIT_2_SRC_Y2__MASK 0xffff0000
+#define CP_BLIT_2_SRC_Y2__SHIFT 16
+static inline uint32_t CP_BLIT_2_SRC_Y2(uint32_t val)
+{
+ return ((val) << CP_BLIT_2_SRC_Y2__SHIFT) & CP_BLIT_2_SRC_Y2__MASK;
+}
+
+#define REG_CP_BLIT_3 0x00000003
+#define CP_BLIT_3_DST_X1__MASK 0x0000ffff
+#define CP_BLIT_3_DST_X1__SHIFT 0
+static inline uint32_t CP_BLIT_3_DST_X1(uint32_t val)
+{
+ return ((val) << CP_BLIT_3_DST_X1__SHIFT) & CP_BLIT_3_DST_X1__MASK;
+}
+#define CP_BLIT_3_DST_Y1__MASK 0xffff0000
+#define CP_BLIT_3_DST_Y1__SHIFT 16
+static inline uint32_t CP_BLIT_3_DST_Y1(uint32_t val)
+{
+ return ((val) << CP_BLIT_3_DST_Y1__SHIFT) & CP_BLIT_3_DST_Y1__MASK;
+}
+
+#define REG_CP_BLIT_4 0x00000004
+#define CP_BLIT_4_DST_X2__MASK 0x0000ffff
+#define CP_BLIT_4_DST_X2__SHIFT 0
+static inline uint32_t CP_BLIT_4_DST_X2(uint32_t val)
+{
+ return ((val) << CP_BLIT_4_DST_X2__SHIFT) & CP_BLIT_4_DST_X2__MASK;
+}
+#define CP_BLIT_4_DST_Y2__MASK 0xffff0000
+#define CP_BLIT_4_DST_Y2__SHIFT 16
+static inline uint32_t CP_BLIT_4_DST_Y2(uint32_t val)
+{
+ return ((val) << CP_BLIT_4_DST_Y2__SHIFT) & CP_BLIT_4_DST_Y2__MASK;
+}
+
#endif /* ADRENO_PM4_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 4958594d5266..39dff7d5e89b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6f240021705b..3819fdefcae2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -982,7 +982,7 @@ static int dsi_tx_buf_alloc(struct msm_dsi_host *msm_host, int size)
struct drm_device *dev = msm_host->dev;
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
int ret;
- u32 iova;
+ uint64_t iova;
if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
mutex_lock(&dev->struct_mutex);
@@ -1147,7 +1147,7 @@ static int dsi_cmd_dma_tx(struct msm_dsi_host *msm_host, int len)
{
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
int ret;
- u32 dma_base;
+ uint64_t dma_base;
bool triggered;
if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 2d999494cdea..8b9f3ebaeba7 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 506434fac993..3fcbb30dc241 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
index f1072c18c81e..d7bf3232dc88 100644
--- a/drivers/gpu/drm/msm/edp/edp.xml.h
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 34c7df6549c1..0a97ff75ed6f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 6eab7d0cf6b5..1b996ede7a65 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 6688e79cc88e..88037889589b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 9527dafc3e69..1c29618f4ddb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -373,7 +373,7 @@ static void update_cursor(struct drm_crtc *crtc)
if (mdp4_crtc->cursor.stale) {
struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo;
struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo;
- uint32_t iova = mdp4_crtc->cursor.next_iova;
+ uint64_t iova = mdp4_crtc->cursor.next_iova;
if (next_bo) {
/* take a obj ref + iova ref when we start scanning out: */
@@ -418,7 +418,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_gem_object *cursor_bo, *old_bo;
unsigned long flags;
- uint32_t iova;
+ uint64_t iova;
int ret;
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
index a521207db8a1..b764d7f10312 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
@@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_print.h>
#include "msm_drv.h"
#include "mdp4_kms.h"
@@ -29,7 +30,16 @@ void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
{
+ struct mdp4_kms *mdp4_kms = container_of(irq, struct mdp4_kms, error_handler);
+ static DEFINE_RATELIMIT_STATE(rs, 5*HZ, 1);
+ extern bool dumpstate;
+
DRM_ERROR_RATELIMITED("errors: %08x\n", irqstatus);
+
+ if (dumpstate && __ratelimit(&rs)) {
+ struct drm_printer p = drm_info_printer(mdp4_kms->dev->dev);
+ drm_state_dump(mdp4_kms->dev, &p);
+ }
}
void mdp4_irq_preinstall(struct msm_kms *kms)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 571a91ee9607..b782efd4b95f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -17,6 +17,7 @@
#include "msm_drv.h"
+#include "msm_gem.h"
#include "msm_mmu.h"
#include "mdp4_kms.h"
@@ -159,17 +160,18 @@ static void mdp4_destroy(struct msm_kms *kms)
{
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
struct device *dev = mdp4_kms->dev->dev;
- struct msm_mmu *mmu = mdp4_kms->mmu;
-
- if (mmu) {
- mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
- mmu->funcs->destroy(mmu);
- }
+ struct msm_gem_address_space *aspace = mdp4_kms->aspace;
if (mdp4_kms->blank_cursor_iova)
msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo);
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
+ }
+
if (mdp4_kms->rpm_enabled)
pm_runtime_disable(dev);
@@ -440,7 +442,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
struct mdp4_platform_config *config = mdp4_get_config(pdev);
struct mdp4_kms *mdp4_kms;
struct msm_kms *kms = NULL;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
int irq, ret;
mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
@@ -531,24 +533,26 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
mdelay(16);
if (config->iommu) {
- mmu = msm_iommu_new(&pdev->dev, config->iommu);
- if (IS_ERR(mmu)) {
- ret = PTR_ERR(mmu);
+ aspace = msm_gem_address_space_create(&pdev->dev,
+ config->iommu, "mdp4");
+ if (IS_ERR(aspace)) {
+ ret = PTR_ERR(aspace);
goto fail;
}
- ret = mmu->funcs->attach(mmu, iommu_ports,
+
+ mdp4_kms->aspace = aspace;
+
+ ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret)
goto fail;
-
- mdp4_kms->mmu = mmu;
} else {
dev_info(dev->dev, "no iommu, fallback to phys "
"contig buffers for scanout\n");
- mmu = NULL;
+ aspace = NULL;
}
- mdp4_kms->id = msm_register_mmu(dev, mmu);
+ mdp4_kms->id = msm_register_address_space(dev, aspace);
if (mdp4_kms->id < 0) {
ret = mdp4_kms->id;
dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
@@ -598,6 +602,10 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
/* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
config.max_clk = 266667000;
config.iommu = iommu_domain_alloc(&platform_bus_type);
+ if (config.iommu) {
+ config.iommu->geometry.aperture_start = 0x1000;
+ config.iommu->geometry.aperture_end = 0xffffffff;
+ }
return &config;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 25fb83997119..62712ca164ee 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -43,7 +43,7 @@ struct mdp4_kms {
struct clk *pclk;
struct clk *lut_clk;
struct clk *axi_clk;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
struct mdp_irq error_handler;
@@ -51,7 +51,7 @@ struct mdp4_kms {
/* empty/blank cursor bo to use when cursor is "disabled" */
struct drm_gem_object *blank_cursor_bo;
- uint32_t blank_cursor_iova;
+ uint64_t blank_cursor_iova;
};
#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 3903dbcda763..911e4690d36a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -40,7 +40,7 @@ enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)
{
bool is_tile = false;
- if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
+ if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
is_tile = true;
if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index ca6ca30650a0..27d5371acee0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -8,9 +8,17 @@ 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:
-- /local/mnt/workspace/source_trees/envytools/rnndb/../rnndb/mdp/mdp5.xml ( 36965 bytes, from 2016-05-10 05:06:30)
-- /local/mnt/workspace/source_trees/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-05-09 06:32:54)
-- /local/mnt/workspace/source_trees/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2016-01-07 08:45:55)
+- /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 ( 1572 bytes, from 2016-02-10 17:07:21)
+- /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 ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
+- /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 ( 41472 bytes, from 2016-01-22 18:18:18)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-20 20:03:14)
Copyright (C) 2013-2016 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 8b4e3004f451..618b2ffed9b4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -550,6 +550,10 @@ static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
static struct mdp5_cfg_platform config = {};
config.iommu = iommu_domain_alloc(&platform_bus_type);
+ if (config.iommu) {
+ config.iommu->geometry.aperture_start = 0x1000;
+ config.iommu->geometry.aperture_end = 0xffffffff;
+ }
return &config;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index c205c360e16d..1ce8a01a5a28 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -27,11 +27,8 @@
#define CURSOR_WIDTH 64
#define CURSOR_HEIGHT 64
-#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
-
struct mdp5_crtc {
struct drm_crtc base;
- char name[8];
int id;
bool enabled;
@@ -102,7 +99,7 @@ static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
- DBG("%s: flush=%08x", mdp5_crtc->name, flush_mask);
+ DBG("%s: flush=%08x", crtc->name, flush_mask);
return mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
}
@@ -136,7 +133,6 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_pending_vblank_event *event;
- struct drm_plane *plane;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
@@ -148,16 +144,12 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
*/
if (!file || (event->base.file_priv == file)) {
mdp5_crtc->event = NULL;
- DBG("%s: send event: %p", mdp5_crtc->name, event);
+ DBG("%s: send event: %p", crtc->name, event);
drm_crtc_send_vblank_event(crtc, event);
}
}
spin_unlock_irqrestore(&dev->event_lock, flags);
- drm_atomic_crtc_for_each_plane(plane, crtc) {
- mdp5_plane_complete_flip(plane);
- }
-
if (mdp5_crtc->ctl && !crtc->state->enable) {
/* set STAGE_UNUSED for all layers */
mdp5_ctl_blend(mdp5_crtc->ctl, NULL, 0, 0);
@@ -295,7 +287,7 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
mode = &crtc->state->adjusted_mode;
DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- mdp5_crtc->name, mode->base.id, mode->name,
+ crtc->name, mode->base.id, mode->name,
mode->vrefresh, mode->clock,
mode->hdisplay, mode->hsync_start,
mode->hsync_end, mode->htotal,
@@ -315,7 +307,7 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
- DBG("%s", mdp5_crtc->name);
+ DBG("%s", crtc->name);
if (WARN_ON(!mdp5_crtc->enabled))
return;
@@ -334,7 +326,7 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
- DBG("%s", mdp5_crtc->name);
+ DBG("%s", crtc->name);
if (WARN_ON(mdp5_crtc->enabled))
return;
@@ -372,7 +364,6 @@ static bool is_fullscreen(struct drm_crtc_state *cstate,
static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
- struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct drm_plane *plane;
struct drm_device *dev = crtc->dev;
@@ -381,7 +372,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
const struct drm_plane_state *pstate;
int cnt = 0, base = 0, i;
- DBG("%s: check", mdp5_crtc->name);
+ DBG("%s: check", crtc->name);
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
pstates[cnt].plane = plane;
@@ -405,14 +396,14 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
if ((cnt + base) >= hw_cfg->lm.nb_stages) {
- dev_err(dev->dev, "too many planes!\n");
+ dev_err(dev->dev, "too many planes! cnt=%d, base=%d\n", cnt, base);
return -EINVAL;
}
for (i = 0; i < cnt; i++) {
pstates[i].state->stage = STAGE_BASE + i + base;
- DBG("%s: assign pipe %s on stage=%d", mdp5_crtc->name,
- pipe2name(mdp5_plane_pipe(pstates[i].plane)),
+ DBG("%s: assign pipe %s on stage=%d", crtc->name,
+ pstates[i].plane->name,
pstates[i].state->stage);
}
@@ -422,8 +413,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
- struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
- DBG("%s: begin", mdp5_crtc->name);
+ DBG("%s: begin", crtc->name);
}
static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -433,7 +423,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
unsigned long flags;
- DBG("%s: event: %p", mdp5_crtc->name, crtc->state->event);
+ DBG("%s: event: %p", crtc->name, crtc->state->event);
WARN_ON(mdp5_crtc->event);
@@ -499,7 +489,8 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct drm_gem_object *cursor_bo, *old_bo = NULL;
- uint32_t blendcfg, cursor_addr, stride;
+ uint32_t blendcfg, stride;
+ uint64_t cursor_addr;
int ret, lm;
enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
@@ -653,7 +644,7 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
{
struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, err);
- DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
+ DBG("%s: error: %08x", mdp5_crtc->base.name, irqstatus);
}
static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
@@ -775,9 +766,6 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
mdp5_crtc->err.irq = mdp5_crtc_err_irq;
- snprintf(mdp5_crtc->name, sizeof(mdp5_crtc->name), "%s:%d",
- pipe2name(mdp5_plane_pipe(plane)), id);
-
drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs,
NULL);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index d53e5510fd7c..3ce8b9dec9c1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -17,6 +17,8 @@
#include <linux/irq.h>
+#include <drm/drm_print.h>
+
#include "msm_drv.h"
#include "mdp5_kms.h"
@@ -30,7 +32,18 @@ void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
{
+ struct mdp5_kms *mdp5_kms = container_of(irq, struct mdp5_kms, error_handler);
+ static DEFINE_RATELIMIT_STATE(rs, 5*HZ, 1);
+ extern bool dumpstate;
+
DRM_ERROR_RATELIMITED("errors: %08x\n", irqstatus);
+
+ if (dumpstate && __ratelimit(&rs)) {
+ struct drm_printer p = drm_info_printer(mdp5_kms->dev->dev);
+ drm_state_dump(mdp5_kms->dev, &p);
+ if (mdp5_kms->smp)
+ mdp5_smp_dump(mdp5_kms->smp, &p);
+ }
}
void mdp5_irq_preinstall(struct msm_kms *kms)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index ed7143d35b25..5f6cd8745dbc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -19,6 +19,7 @@
#include <linux/of_irq.h>
#include "msm_drv.h"
+#include "msm_gem.h"
#include "msm_mmu.h"
#include "mdp5_kms.h"
@@ -71,10 +72,49 @@ static int mdp5_hw_init(struct msm_kms *kms)
return 0;
}
+struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
+{
+ struct msm_drm_private *priv = s->dev->dev_private;
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+ struct msm_kms_state *state = to_kms_state(s);
+ struct mdp5_state *new_state;
+ int ret;
+
+ if (state->state)
+ return state->state;
+
+ ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
+ if (ret)
+ return ERR_PTR(ret);
+
+ new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
+ if (!new_state)
+ return ERR_PTR(-ENOMEM);
+
+ /* Copy state: */
+ new_state->hwpipe = mdp5_kms->state->hwpipe;
+ if (mdp5_kms->smp)
+ new_state->smp = mdp5_kms->state->smp;
+
+ state->state = new_state;
+
+ return new_state;
+}
+
+static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+{
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+ swap(to_kms_state(state)->state, mdp5_kms->state);
+}
+
static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
mdp5_enable(mdp5_kms);
+
+ if (mdp5_kms->smp)
+ mdp5_smp_prepare_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
}
static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
@@ -87,6 +127,9 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s
for_each_plane_in_state(state, plane, plane_state, i)
mdp5_plane_complete_commit(plane, plane_state);
+ if (mdp5_kms->smp)
+ mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
+
mdp5_disable(mdp5_kms);
}
@@ -117,14 +160,66 @@ static int mdp5_set_split_display(struct msm_kms *kms,
static void mdp5_kms_destroy(struct msm_kms *kms)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
- struct msm_mmu *mmu = mdp5_kms->mmu;
+ struct msm_gem_address_space *aspace = mdp5_kms->aspace;
+ int i;
+
+ for (i = 0; i < mdp5_kms->num_hwpipes; i++)
+ mdp5_pipe_destroy(mdp5_kms->hwpipes[i]);
- if (mmu) {
- mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
- mmu->funcs->destroy(mmu);
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
}
}
+#ifdef CONFIG_DEBUG_FS
+static int smp_show(struct seq_file *m, void *arg)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ if (!mdp5_kms->smp) {
+ drm_printf(&p, "no SMP pool\n");
+ return 0;
+ }
+
+ mdp5_smp_dump(mdp5_kms->smp, &p);
+
+ return 0;
+}
+
+static struct drm_info_list mdp5_debugfs_list[] = {
+ {"smp", smp_show },
+};
+
+static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
+{
+ struct drm_device *dev = minor->dev;
+ int ret;
+
+ ret = drm_debugfs_create_files(mdp5_debugfs_list,
+ ARRAY_SIZE(mdp5_debugfs_list),
+ minor->debugfs_root, minor);
+
+ if (ret) {
+ dev_err(dev->dev, "could not install mdp5_debugfs_list\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void mdp5_kms_debugfs_cleanup(struct msm_kms *kms, struct drm_minor *minor)
+{
+ drm_debugfs_remove_files(mdp5_debugfs_list,
+ ARRAY_SIZE(mdp5_debugfs_list), minor);
+}
+#endif
+
static const struct mdp_kms_funcs kms_funcs = {
.base = {
.hw_init = mdp5_hw_init,
@@ -134,6 +229,7 @@ static const struct mdp_kms_funcs kms_funcs = {
.irq = mdp5_irq,
.enable_vblank = mdp5_enable_vblank,
.disable_vblank = mdp5_disable_vblank,
+ .swap_state = mdp5_swap_state,
.prepare_commit = mdp5_prepare_commit,
.complete_commit = mdp5_complete_commit,
.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -141,6 +237,10 @@ static const struct mdp_kms_funcs kms_funcs = {
.round_pixclk = mdp5_round_pixclk,
.set_split_display = mdp5_set_split_display,
.destroy = mdp5_kms_destroy,
+#ifdef CONFIG_DEBUG_FS
+ .debugfs_init = mdp5_kms_debugfs_init,
+ .debugfs_cleanup = mdp5_kms_debugfs_cleanup,
+#endif
},
.set_irqmask = mdp5_set_irqmask,
};
@@ -321,15 +421,6 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
static int modeset_init(struct mdp5_kms *mdp5_kms)
{
- static const enum mdp5_pipe crtcs[] = {
- SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
- };
- static const enum mdp5_pipe vig_planes[] = {
- SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
- };
- static const enum mdp5_pipe dma_planes[] = {
- SSPP_DMA0, SSPP_DMA1,
- };
struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
const struct mdp5_cfg_hw *hw_cfg;
@@ -337,58 +428,35 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
- /* construct CRTCs and their private planes: */
- for (i = 0; i < hw_cfg->pipe_rgb.count; i++) {
+ /* Construct planes equaling the number of hw pipes, and CRTCs
+ * for the N layer-mixers (LM). The first N planes become primary
+ * planes for the CRTCs, with the remainder as overlay planes:
+ */
+ for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+ bool primary = i < mdp5_cfg->lm.count;
struct drm_plane *plane;
struct drm_crtc *crtc;
- plane = mdp5_plane_init(dev, crtcs[i], true,
- hw_cfg->pipe_rgb.base[i], hw_cfg->pipe_rgb.caps);
+ plane = mdp5_plane_init(dev, primary);
if (IS_ERR(plane)) {
ret = PTR_ERR(plane);
- dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
- pipe2name(crtcs[i]), ret);
+ dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
goto fail;
}
+ priv->planes[priv->num_planes++] = plane;
+
+ if (!primary)
+ continue;
crtc = mdp5_crtc_init(dev, plane, i);
if (IS_ERR(crtc)) {
ret = PTR_ERR(crtc);
- dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
- pipe2name(crtcs[i]), ret);
+ dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
goto fail;
}
priv->crtcs[priv->num_crtcs++] = crtc;
}
- /* Construct video planes: */
- for (i = 0; i < hw_cfg->pipe_vig.count; i++) {
- struct drm_plane *plane;
-
- plane = mdp5_plane_init(dev, vig_planes[i], false,
- hw_cfg->pipe_vig.base[i], hw_cfg->pipe_vig.caps);
- if (IS_ERR(plane)) {
- ret = PTR_ERR(plane);
- dev_err(dev->dev, "failed to construct %s plane: %d\n",
- pipe2name(vig_planes[i]), ret);
- goto fail;
- }
- }
-
- /* DMA planes */
- for (i = 0; i < hw_cfg->pipe_dma.count; i++) {
- struct drm_plane *plane;
-
- plane = mdp5_plane_init(dev, dma_planes[i], false,
- hw_cfg->pipe_dma.base[i], hw_cfg->pipe_dma.caps);
- if (IS_ERR(plane)) {
- ret = PTR_ERR(plane);
- dev_err(dev->dev, "failed to construct %s plane: %d\n",
- pipe2name(dma_planes[i]), ret);
- goto fail;
- }
- }
-
/* Construct encoders and modeset initialize connector devices
* for each external display interface.
*/
@@ -564,7 +632,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
struct mdp5_kms *mdp5_kms;
struct mdp5_cfg *config;
struct msm_kms *kms;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
int irq, i, ret;
/* priv->kms would have been populated by the MDP5 driver */
@@ -606,30 +674,29 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
mdelay(16);
if (config->platform.iommu) {
- mmu = msm_iommu_new(&pdev->dev, config->platform.iommu);
- if (IS_ERR(mmu)) {
- ret = PTR_ERR(mmu);
- dev_err(&pdev->dev, "failed to init iommu: %d\n", ret);
- iommu_domain_free(config->platform.iommu);
+ aspace = msm_gem_address_space_create(&pdev->dev,
+ config->platform.iommu, "mdp5");
+ if (IS_ERR(aspace)) {
+ ret = PTR_ERR(aspace);
goto fail;
}
- ret = mmu->funcs->attach(mmu, iommu_ports,
+ mdp5_kms->aspace = aspace;
+
+ ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret) {
dev_err(&pdev->dev, "failed to attach iommu: %d\n",
ret);
- mmu->funcs->destroy(mmu);
goto fail;
}
} else {
dev_info(&pdev->dev,
"no iommu, fallback to phys contig buffers for scanout\n");
- mmu = NULL;
+ aspace = NULL;;
}
- mdp5_kms->mmu = mmu;
- mdp5_kms->id = msm_register_mmu(dev, mmu);
+ mdp5_kms->id = msm_register_address_space(dev, aspace);
if (mdp5_kms->id < 0) {
ret = mdp5_kms->id;
dev_err(&pdev->dev, "failed to register mdp5 iommu: %d\n", ret);
@@ -644,8 +711,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
- dev->mode_config.max_width = config->hw->lm.max_width;
- dev->mode_config.max_height = config->hw->lm.max_height;
+ dev->mode_config.max_width = 0xffff;
+ dev->mode_config.max_height = 0xffff;
dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp;
dev->driver->get_scanout_position = mdp5_get_scanoutpos;
@@ -673,6 +740,69 @@ static void mdp5_destroy(struct platform_device *pdev)
if (mdp5_kms->rpm_enabled)
pm_runtime_disable(&pdev->dev);
+
+ kfree(mdp5_kms->state);
+}
+
+static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
+ const enum mdp5_pipe *pipes, const uint32_t *offsets,
+ uint32_t caps)
+{
+ struct drm_device *dev = mdp5_kms->dev;
+ int i, ret;
+
+ for (i = 0; i < cnt; i++) {
+ struct mdp5_hw_pipe *hwpipe;
+
+ hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps);
+ if (IS_ERR(hwpipe)) {
+ ret = PTR_ERR(hwpipe);
+ dev_err(dev->dev, "failed to construct pipe for %s (%d)\n",
+ pipe2name(pipes[i]), ret);
+ return ret;
+ }
+ hwpipe->idx = mdp5_kms->num_hwpipes;
+ mdp5_kms->hwpipes[mdp5_kms->num_hwpipes++] = hwpipe;
+ }
+
+ return 0;
+}
+
+static int hwpipe_init(struct mdp5_kms *mdp5_kms)
+{
+ static const enum mdp5_pipe rgb_planes[] = {
+ SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
+ };
+ static const enum mdp5_pipe vig_planes[] = {
+ SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
+ };
+ static const enum mdp5_pipe dma_planes[] = {
+ SSPP_DMA0, SSPP_DMA1,
+ };
+ const struct mdp5_cfg_hw *hw_cfg;
+ int ret;
+
+ hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
+
+ /* Construct RGB pipes: */
+ ret = construct_pipes(mdp5_kms, hw_cfg->pipe_rgb.count, rgb_planes,
+ hw_cfg->pipe_rgb.base, hw_cfg->pipe_rgb.caps);
+ if (ret)
+ return ret;
+
+ /* Construct video (VIG) pipes: */
+ ret = construct_pipes(mdp5_kms, hw_cfg->pipe_vig.count, vig_planes,
+ hw_cfg->pipe_vig.base, hw_cfg->pipe_vig.caps);
+ if (ret)
+ return ret;
+
+ /* Construct DMA pipes: */
+ ret = construct_pipes(mdp5_kms, hw_cfg->pipe_dma.count, dma_planes,
+ hw_cfg->pipe_dma.base, hw_cfg->pipe_dma.caps);
+ if (ret)
+ return ret;
+
+ return 0;
}
static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
@@ -696,6 +826,13 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
mdp5_kms->dev = dev;
mdp5_kms->pdev = pdev;
+ drm_modeset_lock_init(&mdp5_kms->state_lock);
+ mdp5_kms->state = kzalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
+ if (!mdp5_kms->state) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
if (IS_ERR(mdp5_kms->mmio)) {
ret = PTR_ERR(mdp5_kms->mmio);
@@ -749,7 +886,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
* this section initializes the SMP:
*/
if (mdp5_kms->caps & MDP_CAP_SMP) {
- mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
+ mdp5_kms->smp = mdp5_smp_init(mdp5_kms, &config->hw->smp);
if (IS_ERR(mdp5_kms->smp)) {
ret = PTR_ERR(mdp5_kms->smp);
mdp5_kms->smp = NULL;
@@ -764,6 +901,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
goto fail;
}
+ ret = hwpipe_init(mdp5_kms);
+ if (ret)
+ goto fail;
+
/* set uninit-ed kms */
priv->kms = &mdp5_kms->base.base;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 03738927be10..17b0cc101171 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -24,8 +24,11 @@
#include "mdp5_cfg.h" /* must be included before mdp5.xml.h */
#include "mdp5.xml.h"
#include "mdp5_ctl.h"
+#include "mdp5_pipe.h"
#include "mdp5_smp.h"
+struct mdp5_state;
+
struct mdp5_kms {
struct mdp_kms base;
@@ -33,13 +36,21 @@ struct mdp5_kms {
struct platform_device *pdev;
+ unsigned num_hwpipes;
+ struct mdp5_hw_pipe *hwpipes[SSPP_MAX];
+
struct mdp5_cfg_handler *cfg;
uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
+ /**
+ * Global atomic state. Do not access directly, use mdp5_get_state()
+ */
+ struct mdp5_state *state;
+ struct drm_modeset_lock state_lock;
/* mapper-id used to request GEM buffer mapped for scanout: */
int id;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
struct mdp5_smp *smp;
struct mdp5_ctl_manager *ctlm;
@@ -65,9 +76,27 @@ struct mdp5_kms {
};
#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
+/* Global atomic state for tracking resources that are shared across
+ * multiple kms objects (planes/crtcs/etc).
+ *
+ * For atomic updates which require modifying global state,
+ */
+struct mdp5_state {
+ struct mdp5_hw_pipe_state hwpipe;
+ struct mdp5_smp_state smp;
+};
+
+struct mdp5_state *__must_check
+mdp5_get_state(struct drm_atomic_state *s);
+
+/* Atomic plane state. Subclasses the base drm_plane_state in order to
+ * track assigned hwpipe and hw specific state.
+ */
struct mdp5_plane_state {
struct drm_plane_state base;
+ struct mdp5_hw_pipe *hwpipe;
+
/* aligned with property */
uint8_t premultiplied;
uint8_t zpos;
@@ -76,11 +105,6 @@ struct mdp5_plane_state {
/* assigned by crtc blender */
enum mdp_mixer_stage_id stage;
- /* some additional transactional status to help us know in the
- * apply path whether we need to update SMP allocation, and
- * whether current update is still pending:
- */
- bool mode_changed : 1;
bool pending : 1;
};
#define to_mdp5_plane_state(x) \
@@ -114,6 +138,18 @@ static inline u32 mdp5_read(struct mdp5_kms *mdp5_kms, u32 reg)
return msm_readl(mdp5_kms->mmio + reg);
}
+static inline const char *stage2name(enum mdp_mixer_stage_id stage)
+{
+ static const char *names[] = {
+#define NAME(n) [n] = #n
+ NAME(STAGE_UNUSED), NAME(STAGE_BASE),
+ NAME(STAGE0), NAME(STAGE1), NAME(STAGE2),
+ NAME(STAGE3), NAME(STAGE4), NAME(STAGE6),
+#undef NAME
+ };
+ return names[stage];
+}
+
static inline const char *pipe2name(enum mdp5_pipe pipe)
{
static const char *names[] = {
@@ -196,13 +232,10 @@ int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
-void mdp5_plane_complete_flip(struct drm_plane *plane);
void mdp5_plane_complete_commit(struct drm_plane *plane,
struct drm_plane_state *state);
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp5_plane_init(struct drm_device *dev,
- enum mdp5_pipe pipe, bool private_plane,
- uint32_t reg_offset, uint32_t caps);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
new file mode 100644
index 000000000000..1ae9dc8d260d
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 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/>.
+ */
+
+#include "mdp5_kms.h"
+
+struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
+ struct drm_plane *plane, uint32_t caps, uint32_t blkcfg)
+{
+ struct msm_drm_private *priv = s->dev->dev_private;
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+ struct mdp5_state *state;
+ struct mdp5_hw_pipe_state *old_state, *new_state;
+ struct mdp5_hw_pipe *hwpipe = NULL;
+ int i;
+
+ state = mdp5_get_state(s);
+ if (IS_ERR(state))
+ return ERR_CAST(state);
+
+ /* grab old_state after mdp5_get_state(), since now we hold lock: */
+ old_state = &mdp5_kms->state->hwpipe;
+ new_state = &state->hwpipe;
+
+ for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+ struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
+
+ /* skip if already in-use.. check both new and old state,
+ * since we cannot immediately re-use a pipe that is
+ * released in the current update in some cases:
+ * (1) mdp5 can have SMP (non-double-buffered)
+ * (2) hw pipe previously assigned to different CRTC
+ * (vblanks might not be aligned)
+ */
+ if (new_state->hwpipe_to_plane[cur->idx] ||
+ old_state->hwpipe_to_plane[cur->idx])
+ continue;
+
+ /* skip if doesn't support some required caps: */
+ if (caps & ~cur->caps)
+ continue;
+
+ /* possible candidate, take the one with the
+ * fewest unneeded caps bits set:
+ */
+ if (!hwpipe || (hweight_long(cur->caps & ~caps) <
+ hweight_long(hwpipe->caps & ~caps)))
+ hwpipe = cur;
+ }
+
+ if (!hwpipe)
+ return ERR_PTR(-ENOMEM);
+
+ if (mdp5_kms->smp) {
+ int ret;
+
+ DBG("%s: alloc SMP blocks", hwpipe->name);
+ ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
+ hwpipe->pipe, blkcfg);
+ if (ret)
+ return ERR_PTR(-ENOMEM);
+
+ hwpipe->blkcfg = blkcfg;
+ }
+
+ DBG("%s: assign to plane %s for caps %x",
+ hwpipe->name, plane->name, caps);
+ new_state->hwpipe_to_plane[hwpipe->idx] = plane;
+
+ return hwpipe;
+}
+
+void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
+{
+ struct msm_drm_private *priv = s->dev->dev_private;
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+ struct mdp5_state *state = mdp5_get_state(s);
+ struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
+
+ if (!hwpipe)
+ return;
+
+ if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
+ return;
+
+ DBG("%s: release from plane %s", hwpipe->name,
+ new_state->hwpipe_to_plane[hwpipe->idx]->name);
+
+ if (mdp5_kms->smp) {
+ DBG("%s: free SMP blocks", hwpipe->name);
+ mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
+ }
+
+ new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
+}
+
+void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
+{
+ kfree(hwpipe);
+}
+
+struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+ uint32_t reg_offset, uint32_t caps)
+{
+ struct mdp5_hw_pipe *hwpipe;
+
+ hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
+ if (!hwpipe)
+ return ERR_PTR(-ENOMEM);
+
+ hwpipe->name = pipe2name(pipe);
+ hwpipe->pipe = pipe;
+ hwpipe->reg_offset = reg_offset;
+ hwpipe->caps = caps;
+ hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
+
+ spin_lock_init(&hwpipe->pipe_lock);
+
+ return hwpipe;
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h
new file mode 100644
index 000000000000..611da7a660c9
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef __MDP5_PIPE_H__
+#define __MDP5_PIPE_H__
+
+#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
+
+/* represents a hw pipe, which is dynamically assigned to a plane */
+struct mdp5_hw_pipe {
+ int idx;
+
+ const char *name;
+ enum mdp5_pipe pipe;
+
+ spinlock_t pipe_lock; /* protect REG_MDP5_PIPE_* registers */
+ uint32_t reg_offset;
+ uint32_t caps;
+
+ uint32_t flush_mask; /* used to commit pipe registers */
+
+ /* number of smp blocks per plane, ie:
+ * nblks_y | (nblks_u << 8) | (nblks_v << 16)
+ */
+ uint32_t blkcfg;
+};
+
+/* global atomic state of assignment between pipes and planes: */
+struct mdp5_hw_pipe_state {
+ struct drm_plane *hwpipe_to_plane[SSPP_MAX];
+};
+
+struct mdp5_hw_pipe *__must_check
+mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane,
+ uint32_t caps, uint32_t blkcfg);
+void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe);
+
+struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+ uint32_t reg_offset, uint32_t caps);
+void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe);
+
+#endif /* __MDP5_PIPE_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 83bf997dda03..c099da7bc212 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -16,19 +16,11 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_print.h>
#include "mdp5_kms.h"
struct mdp5_plane {
struct drm_plane base;
- const char *name;
-
- enum mdp5_pipe pipe;
-
- spinlock_t pipe_lock; /* protect REG_MDP5_PIPE_* registers */
- uint32_t reg_offset;
- uint32_t caps;
-
- uint32_t flush_mask; /* used to commit pipe registers */
uint32_t nformats;
uint32_t formats[32];
@@ -69,21 +61,12 @@ static void mdp5_plane_destroy(struct drm_plane *plane)
static void mdp5_plane_install_rotation_property(struct drm_device *dev,
struct drm_plane *plane)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-
- if (!(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) &&
- !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP))
- return;
-
- if (!dev->mode_config.rotation_property)
- dev->mode_config.rotation_property =
- drm_mode_create_rotation_property(dev,
- DRM_ROTATE_0 | DRM_REFLECT_X | DRM_REFLECT_Y);
-
- if (dev->mode_config.rotation_property)
- drm_object_attach_property(&plane->base,
- dev->mode_config.rotation_property,
- DRM_ROTATE_0);
+ drm_plane_create_rotation_property(plane,
+ DRM_ROTATE_0,
+ DRM_ROTATE_0 |
+ DRM_ROTATE_180 |
+ DRM_REFLECT_X |
+ DRM_REFLECT_Y);
}
/* helper to install properties which are common to planes and crtcs */
@@ -184,6 +167,21 @@ done:
#undef SET_PROPERTY
}
+static void
+mdp5_plane_atomic_print_state(struct drm_printer *p,
+ const struct drm_plane_state *state)
+{
+ struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
+
+ drm_printf(p, "\thwpipe=%s\n", pstate->hwpipe ?
+ pstate->hwpipe->name : "(null)");
+ drm_printf(p, "\tpremultiplied=%u\n", pstate->premultiplied);
+ drm_printf(p, "\tzpos=%u\n", pstate->zpos);
+ drm_printf(p, "\talpha=%u\n", pstate->alpha);
+ drm_printf(p, "\tstage=%s\n", stage2name(pstate->stage));
+ drm_printf(p, "\tpending=%u\n", pstate->pending);
+}
+
static void mdp5_plane_reset(struct drm_plane *plane)
{
struct mdp5_plane_state *mdp5_state;
@@ -222,7 +220,6 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
if (mdp5_state && mdp5_state->base.fb)
drm_framebuffer_reference(mdp5_state->base.fb);
- mdp5_state->mode_changed = false;
mdp5_state->pending = false;
return &mdp5_state->base;
@@ -231,10 +228,12 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
static void mdp5_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
+ struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
+
if (state->fb)
drm_framebuffer_unreference(state->fb);
- kfree(to_mdp5_plane_state(state));
+ kfree(pstate);
}
static const struct drm_plane_funcs mdp5_plane_funcs = {
@@ -247,99 +246,121 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
.reset = mdp5_plane_reset,
.atomic_duplicate_state = mdp5_plane_duplicate_state,
.atomic_destroy_state = mdp5_plane_destroy_state,
+ .atomic_print_state = mdp5_plane_atomic_print_state,
};
static int mdp5_plane_prepare_fb(struct drm_plane *plane,
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);
+ DBG("%s: prepare: FB[%u]", 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_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);
+ DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id);
msm_framebuffer_cleanup(fb, mdp5_kms->id);
}
static int mdp5_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+ struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
struct drm_plane_state *old_state = plane->state;
- const struct mdp_format *format;
- bool vflip, hflip;
+ struct mdp5_cfg *config = mdp5_cfg_get_config(get_kms(plane)->cfg);
+ bool new_hwpipe = false;
+ uint32_t max_width, max_height;
+ uint32_t caps = 0;
- DBG("%s: check (%d -> %d)", mdp5_plane->name,
+ DBG("%s: check (%d -> %d)", plane->name,
plane_enabled(old_state), plane_enabled(state));
+ /* We don't allow faster-than-vblank updates.. if we did add this
+ * some day, we would need to disallow in cases where hwpipe
+ * changes
+ */
+ if (WARN_ON(to_mdp5_plane_state(old_state)->pending))
+ return -EBUSY;
+
+ max_width = config->hw->lm.max_width << 16;
+ max_height = config->hw->lm.max_height << 16;
+
+ /* Make sure source dimensions are within bounds. */
+ if ((state->src_w > max_width) || (state->src_h > max_height)) {
+ struct drm_rect src = drm_plane_state_src(state);
+ DBG("Invalid source size "DRM_RECT_FP_FMT,
+ DRM_RECT_FP_ARG(&src));
+ return -ERANGE;
+ }
+
if (plane_enabled(state)) {
+ unsigned int rotation;
+ const struct mdp_format *format;
+ struct mdp5_kms *mdp5_kms = get_kms(plane);
+ uint32_t blkcfg = 0;
+
format = to_mdp_format(msm_framebuffer_format(state->fb));
- if (MDP_FORMAT_IS_YUV(format) &&
- !pipe_supports_yuv(mdp5_plane->caps)) {
- DBG("Pipe doesn't support YUV\n");
+ if (MDP_FORMAT_IS_YUV(format))
+ caps |= MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC;
- return -EINVAL;
- }
+ if (((state->src_w >> 16) != state->crtc_w) ||
+ ((state->src_h >> 16) != state->crtc_h))
+ caps |= MDP_PIPE_CAP_SCALE;
- if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
- (((state->src_w >> 16) != state->crtc_w) ||
- ((state->src_h >> 16) != state->crtc_h))) {
- DBG("Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
- state->src_w >> 16, state->src_h >> 16,
- state->crtc_w, state->crtc_h);
+ rotation = drm_rotation_simplify(state->rotation,
+ DRM_ROTATE_0 |
+ DRM_REFLECT_X |
+ DRM_REFLECT_Y);
- return -EINVAL;
- }
+ if (rotation & DRM_REFLECT_X)
+ caps |= MDP_PIPE_CAP_HFLIP;
- hflip = !!(state->rotation & DRM_REFLECT_X);
- vflip = !!(state->rotation & DRM_REFLECT_Y);
- if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) ||
- (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) {
- DBG("Pipe doesn't support flip\n");
+ if (rotation & DRM_REFLECT_Y)
+ caps |= MDP_PIPE_CAP_VFLIP;
- return -EINVAL;
- }
- }
+ /* (re)allocate hw pipe if we don't have one or caps-mismatch: */
+ if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
+ new_hwpipe = true;
- if (plane_enabled(state) && plane_enabled(old_state)) {
- /* we cannot change SMP block configuration during scanout: */
- bool full_modeset = false;
- if (state->fb->pixel_format != old_state->fb->pixel_format) {
- DBG("%s: pixel_format change!", mdp5_plane->name);
- full_modeset = true;
- }
- if (state->src_w != old_state->src_w) {
- DBG("%s: src_w change!", mdp5_plane->name);
- full_modeset = true;
- }
- if (to_mdp5_plane_state(old_state)->pending) {
- DBG("%s: still pending!", mdp5_plane->name);
- full_modeset = true;
+ if (mdp5_kms->smp) {
+ const struct mdp_format *format =
+ to_mdp_format(msm_framebuffer_format(state->fb));
+
+ blkcfg = mdp5_smp_calculate(mdp5_kms->smp, format,
+ state->src_w >> 16, false);
+
+ if (mdp5_state->hwpipe && (mdp5_state->hwpipe->blkcfg != blkcfg))
+ new_hwpipe = true;
}
- if (full_modeset) {
- struct drm_crtc_state *crtc_state =
- drm_atomic_get_crtc_state(state->state, state->crtc);
- crtc_state->mode_changed = true;
- to_mdp5_plane_state(state)->mode_changed = true;
+
+ /* (re)assign hwpipe if needed, otherwise keep old one: */
+ if (new_hwpipe) {
+ /* TODO maybe we want to re-assign hwpipe sometimes
+ * in cases when we no-longer need some caps to make
+ * it available for other planes?
+ */
+ struct mdp5_hw_pipe *old_hwpipe = mdp5_state->hwpipe;
+ mdp5_state->hwpipe = mdp5_pipe_assign(state->state,
+ plane, caps, blkcfg);
+ if (IS_ERR(mdp5_state->hwpipe)) {
+ DBG("%s: failed to assign hwpipe!", plane->name);
+ return PTR_ERR(mdp5_state->hwpipe);
+ }
+ mdp5_pipe_release(state->state, old_hwpipe);
}
- } else {
- to_mdp5_plane_state(state)->mode_changed = true;
}
return 0;
@@ -348,16 +369,16 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
static void mdp5_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct drm_plane_state *state = plane->state;
+ struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
- DBG("%s: update", mdp5_plane->name);
+ DBG("%s: update", plane->name);
- if (!plane_enabled(state)) {
- to_mdp5_plane_state(state)->pending = true;
- } else if (to_mdp5_plane_state(state)->mode_changed) {
+ mdp5_state->pending = true;
+
+ if (plane_enabled(state)) {
int ret;
- to_mdp5_plane_state(state)->pending = true;
+
ret = mdp5_plane_mode_set(plane,
state->crtc, state->fb,
state->crtc_x, state->crtc_y,
@@ -366,11 +387,6 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
state->src_w, state->src_h);
/* atomic_check should have ensured that this doesn't fail */
WARN_ON(ret < 0);
- } else {
- unsigned long flags;
- spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
- set_scanout_locked(plane, state->fb);
- spin_unlock_irqrestore(&mdp5_plane->pipe_lock, flags);
}
}
@@ -384,9 +400,9 @@ static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
static void set_scanout_locked(struct drm_plane *plane,
struct drm_framebuffer *fb)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct mdp5_kms *mdp5_kms = get_kms(plane);
- enum mdp5_pipe pipe = mdp5_plane->pipe;
+ struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(plane->state)->hwpipe;
+ enum mdp5_pipe pipe = hwpipe->pipe;
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
@@ -666,18 +682,19 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct drm_plane_state *pstate = plane->state;
+ struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe;
struct mdp5_kms *mdp5_kms = get_kms(plane);
- enum mdp5_pipe pipe = mdp5_plane->pipe;
+ enum mdp5_pipe pipe = hwpipe->pipe;
const struct mdp_format *format;
uint32_t nplanes, config = 0;
uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
- bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
+ bool pe = hwpipe->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;
+ unsigned int rotation;
bool vflip, hflip;
unsigned long flags;
int ret;
@@ -697,27 +714,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
src_w = src_w >> 16;
src_h = src_h >> 16;
- DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp5_plane->name,
+ DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", plane->name,
fb->base.id, src_x, src_y, src_w, src_h,
crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
- /* Request some memory from the SMP: */
- 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,
- * but once atomic modeset/pageflip is in place, the allocation
- * would move into atomic->check_plane_state(), while updating the
- * hw would remain here:
- */
- 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)
return ret;
@@ -726,7 +726,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
if (ret)
return ret;
- if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
+ if (hwpipe->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,
@@ -740,14 +740,18 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
config |= get_scale_config(format, src_h, crtc_h, false);
DBG("scale config = %x", config);
- hflip = !!(pstate->rotation & DRM_REFLECT_X);
- vflip = !!(pstate->rotation & DRM_REFLECT_Y);
+ rotation = drm_rotation_simplify(pstate->rotation,
+ DRM_ROTATE_0 |
+ DRM_REFLECT_X |
+ DRM_REFLECT_Y);
+ hflip = !!(rotation & DRM_REFLECT_X);
+ vflip = !!(rotation & DRM_REFLECT_Y);
- spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
+ spin_lock_irqsave(&hwpipe->pipe_lock, flags);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
- MDP5_PIPE_SRC_IMG_SIZE_WIDTH(fb->width) |
- MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(fb->height));
+ MDP5_PIPE_SRC_IMG_SIZE_WIDTH(min(fb->width, src_w)) |
+ MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(min(fb->height, src_h)));
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_SIZE(pipe),
MDP5_PIPE_SRC_SIZE_WIDTH(src_w) |
@@ -792,12 +796,12 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
/* 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)
+ if (hwpipe->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) {
+ if (hwpipe->caps & MDP_PIPE_CAP_SCALE) {
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
phasex_step[COMP_0]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
@@ -812,7 +816,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
}
- if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
+ if (hwpipe->caps & MDP_PIPE_CAP_CSC) {
if (MDP_FORMAT_IS_YUV(format))
csc_enable(mdp5_kms, pipe,
mdp_get_default_csc_cfg(CSC_YUV2RGB));
@@ -822,56 +826,42 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
set_scanout_locked(plane, fb);
- spin_unlock_irqrestore(&mdp5_plane->pipe_lock, flags);
+ spin_unlock_irqrestore(&hwpipe->pipe_lock, flags);
return ret;
}
-void mdp5_plane_complete_flip(struct drm_plane *plane)
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
{
- struct mdp5_kms *mdp5_kms = get_kms(plane);
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
- enum mdp5_pipe pipe = mdp5_plane->pipe;
+ struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
- DBG("%s: complete flip", mdp5_plane->name);
-
- if (mdp5_kms->smp)
- mdp5_smp_commit(mdp5_kms->smp, pipe);
-
- to_mdp5_plane_state(plane->state)->pending = false;
-}
+ if (WARN_ON(!pstate->hwpipe))
+ return 0;
-enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
-{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
- return mdp5_plane->pipe;
+ return pstate->hwpipe->pipe;
}
uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+ struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
- return mdp5_plane->flush_mask;
+ if (WARN_ON(!pstate->hwpipe))
+ return 0;
+
+ return pstate->hwpipe->flush_mask;
}
/* called after vsync in thread context */
void mdp5_plane_complete_commit(struct drm_plane *plane,
struct drm_plane_state *state)
{
- struct mdp5_kms *mdp5_kms = get_kms(plane);
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
- enum mdp5_pipe pipe = mdp5_plane->pipe;
+ struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
- if (!plane_enabled(plane->state) && mdp5_kms->smp) {
- DBG("%s: free SMP", mdp5_plane->name);
- mdp5_smp_release(mdp5_kms->smp, pipe);
- }
+ pstate->pending = false;
}
/* initialize plane */
-struct drm_plane *mdp5_plane_init(struct drm_device *dev,
- enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset,
- uint32_t caps)
+struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
{
struct drm_plane *plane = NULL;
struct mdp5_plane *mdp5_plane;
@@ -886,19 +876,10 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
plane = &mdp5_plane->base;
- mdp5_plane->pipe = pipe;
- mdp5_plane->name = pipe2name(pipe);
- mdp5_plane->caps = caps;
-
mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
- ARRAY_SIZE(mdp5_plane->formats),
- !pipe_supports_yuv(mdp5_plane->caps));
-
- mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
- mdp5_plane->reg_offset = reg_offset;
- spin_lock_init(&mdp5_plane->pipe_lock);
+ ARRAY_SIZE(mdp5_plane->formats), false);
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+ type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
mdp5_plane->formats, mdp5_plane->nformats,
type, NULL);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
index 27d7b55b52c9..58f712d37e7f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
@@ -21,72 +21,6 @@
#include "mdp5_smp.h"
-/* SMP - Shared Memory Pool
- *
- * These are shared between all the clients, where each plane in a
- * scanout buffer is a SMP client. Ie. scanout of 3 plane I420 on
- * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
- *
- * Based on the size of the attached scanout buffer, a certain # of
- * blocks must be allocated to that client out of the shared pool.
- *
- * In some hw, some blocks are statically allocated for certain pipes
- * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
- *
- * For each block that can be dynamically allocated, it can be either
- * free:
- * The block is free.
- *
- * pending:
- * The block is allocated to some client and not free.
- *
- * configured:
- * The block is allocated to some client, and assigned to that
- * client in MDP5_SMP_ALLOC registers.
- *
- * inuse:
- * The block is being actively used by a client.
- *
- * The updates happen in the following steps:
- *
- * 1) mdp5_smp_request():
- * When plane scanout is setup, calculate required number of
- * blocks needed per client, and request. Blocks neither inuse nor
- * configured nor pending by any other client are added to client's
- * pending set.
- * For shrinking, blocks in pending but not in configured can be freed
- * directly, but those already in configured will be freed later by
- * mdp5_smp_commit.
- *
- * 2) mdp5_smp_configure():
- * As hw is programmed, before FLUSH, MDP5_SMP_ALLOC registers
- * are configured for the union(pending, inuse)
- * Current pending is copied to configured.
- * It is assumed that mdp5_smp_request and mdp5_smp_configure not run
- * concurrently for the same pipe.
- *
- * 3) mdp5_smp_commit():
- * After next vblank, copy configured -> inuse. Optionally update
- * MDP5_SMP_ALLOC registers if there are newly unused blocks
- *
- * 4) mdp5_smp_release():
- * Must be called after the pipe is disabled and no longer uses any SMB
- *
- * On the next vblank after changes have been committed to hw, the
- * client's pending blocks become it's in-use blocks (and no-longer
- * in-use blocks become available to other clients).
- *
- * btw, hurray for confusing overloaded acronyms! :-/
- *
- * NOTE: for atomic modeset/pageflip NONBLOCK operations, step #1
- * should happen at (or before)? atomic->check(). And we'd need
- * an API to discard previous requests if update is aborted or
- * (test-only).
- *
- * TODO would perhaps be nice to have debugfs to dump out kernel
- * inuse and pending state of all clients..
- */
-
struct mdp5_smp {
struct drm_device *dev;
@@ -94,16 +28,8 @@ struct mdp5_smp {
int blk_cnt;
int blk_size;
-
- spinlock_t state_lock;
- mdp5_smp_state_t state; /* to track smp allocation amongst pipes: */
-
- struct mdp5_client_smp_state client_state[MAX_CLIENTS];
};
-static void update_smp_state(struct mdp5_smp *smp,
- u32 cid, mdp5_smp_state_t *assigned);
-
static inline
struct mdp5_kms *get_kms(struct mdp5_smp *smp)
{
@@ -134,57 +60,38 @@ static inline u32 pipe2client(enum mdp5_pipe pipe, int plane)
return mdp5_cfg->smp.clients[pipe] + plane;
}
-/* step #1: update # of blocks pending for the client: */
+/* allocate blocks for the specified request: */
static int smp_request_block(struct mdp5_smp *smp,
+ struct mdp5_smp_state *state,
u32 cid, int nblks)
{
- 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;
+ void *cs = state->client_state[cid];
+ int i, avail, cnt = smp->blk_cnt;
uint8_t reserved;
- unsigned long flags;
- reserved = smp->reserved[cid];
+ /* we shouldn't be requesting blocks for an in-use client: */
+ WARN_ON(bitmap_weight(cs, cnt) > 0);
- spin_lock_irqsave(&smp->state_lock, flags);
+ reserved = smp->reserved[cid];
if (reserved) {
nblks = max(0, nblks - reserved);
DBG("%d MMBs allocated (%d reserved)", nblks, reserved);
}
- avail = cnt - bitmap_weight(smp->state, cnt);
+ avail = cnt - bitmap_weight(state->state, cnt);
if (nblks > avail) {
- dev_err(mdp5_kms->dev->dev, "out of blks (req=%d > avail=%d)\n",
+ dev_err(smp->dev->dev, "out of blks (req=%d > avail=%d)\n",
nblks, avail);
- ret = -ENOSPC;
- goto fail;
+ return -ENOSPC;
}
- cur_nblks = bitmap_weight(ps->pending, cnt);
- if (nblks > cur_nblks) {
- /* grow the existing pending reservation: */
- for (i = cur_nblks; i < nblks; i++) {
- int blk = find_first_zero_bit(smp->state, cnt);
- set_bit(blk, ps->pending);
- set_bit(blk, smp->state);
- }
- } else {
- /* shrink the existing pending reservation: */
- for (i = cur_nblks; i > nblks; i--) {
- int blk = find_first_bit(ps->pending, cnt);
- clear_bit(blk, ps->pending);
-
- /* clear in global smp_state if not in configured
- * otherwise until _commit()
- */
- if (!test_bit(blk, ps->configured))
- clear_bit(blk, smp->state);
- }
+ for (i = 0; i < nblks; i++) {
+ int blk = find_first_zero_bit(state->state, cnt);
+ set_bit(blk, cs);
+ set_bit(blk, state->state);
}
-fail:
- spin_unlock_irqrestore(&smp->state_lock, flags);
return 0;
}
@@ -209,14 +116,15 @@ static void set_fifo_thresholds(struct mdp5_smp *smp,
* decimated width. Ie. SMP buffering sits downstream of decimation (which
* presumably happens during the dma from scanout buffer).
*/
-int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
- const struct mdp_format *format, u32 width, bool hdecim)
+uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
+ const struct mdp_format *format,
+ u32 width, bool hdecim)
{
struct mdp5_kms *mdp5_kms = get_kms(smp);
- struct drm_device *dev = mdp5_kms->dev;
int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
- int i, hsub, nplanes, nlines, nblks, ret;
+ int i, hsub, nplanes, nlines;
u32 fmt = format->base.pixel_format;
+ uint32_t blkcfg = 0;
nplanes = drm_format_num_planes(fmt);
hsub = drm_format_horz_chroma_subsampling(fmt);
@@ -239,7 +147,7 @@ int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
hsub = 1;
}
- for (i = 0, nblks = 0; i < nplanes; i++) {
+ for (i = 0; i < nplanes; i++) {
int n, fetch_stride, cpp;
cpp = drm_format_plane_cpp(fmt, i);
@@ -251,60 +159,72 @@ int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
if (rev == 0)
n = roundup_pow_of_two(n);
+ blkcfg |= (n << (8 * i));
+ }
+
+ return blkcfg;
+}
+
+int mdp5_smp_assign(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+ enum mdp5_pipe pipe, uint32_t blkcfg)
+{
+ struct mdp5_kms *mdp5_kms = get_kms(smp);
+ struct drm_device *dev = mdp5_kms->dev;
+ int i, ret;
+
+ for (i = 0; i < pipe2nclients(pipe); i++) {
+ u32 cid = pipe2client(pipe, i);
+ int n = blkcfg & 0xff;
+
+ if (!n)
+ continue;
+
DBG("%s[%d]: request %d SMP blocks", pipe2name(pipe), i, n);
- ret = smp_request_block(smp, pipe2client(pipe, i), n);
+ ret = smp_request_block(smp, state, cid, n);
if (ret) {
dev_err(dev->dev, "Cannot allocate %d SMP blocks: %d\n",
n, ret);
return ret;
}
- nblks += n;
+ blkcfg >>= 8;
}
- set_fifo_thresholds(smp, pipe, nblks);
+ state->assigned |= (1 << pipe);
return 0;
}
/* Release SMP blocks for all clients of the pipe */
-void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+ enum mdp5_pipe pipe)
{
int i;
- unsigned long flags;
int cnt = smp->blk_cnt;
for (i = 0; i < pipe2nclients(pipe); i++) {
- mdp5_smp_state_t assigned;
u32 cid = pipe2client(pipe, i);
- struct mdp5_client_smp_state *ps = &smp->client_state[cid];
-
- spin_lock_irqsave(&smp->state_lock, flags);
-
- /* clear hw assignment */
- bitmap_or(assigned, ps->inuse, ps->configured, cnt);
- update_smp_state(smp, CID_UNUSED, &assigned);
-
- /* free to global pool */
- bitmap_andnot(smp->state, smp->state, ps->pending, cnt);
- bitmap_andnot(smp->state, smp->state, assigned, cnt);
+ void *cs = state->client_state[cid];
- /* clear client's infor */
- bitmap_zero(ps->pending, cnt);
- bitmap_zero(ps->configured, cnt);
- bitmap_zero(ps->inuse, cnt);
+ /* update global state: */
+ bitmap_andnot(state->state, state->state, cs, cnt);
- spin_unlock_irqrestore(&smp->state_lock, flags);
+ /* clear client's state */
+ bitmap_zero(cs, cnt);
}
- set_fifo_thresholds(smp, pipe, 0);
+ state->released |= (1 << pipe);
}
-static void update_smp_state(struct mdp5_smp *smp,
+/* NOTE: SMP_ALLOC_* regs are *not* double buffered, so release has to
+ * happen after scanout completes.
+ */
+static unsigned update_smp_state(struct mdp5_smp *smp,
u32 cid, mdp5_smp_state_t *assigned)
{
struct mdp5_kms *mdp5_kms = get_kms(smp);
int cnt = smp->blk_cnt;
+ unsigned nblks = 0;
u32 blk, val;
for_each_set_bit(blk, *assigned, cnt) {
@@ -330,62 +250,88 @@ static void update_smp_state(struct mdp5_smp *smp,
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx), val);
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(idx), val);
+
+ nblks++;
}
+
+ return nblks;
}
-/* step #2: configure hw for union(pending, inuse): */
-void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
{
- int cnt = smp->blk_cnt;
- mdp5_smp_state_t assigned;
- int i;
+ enum mdp5_pipe pipe;
- for (i = 0; i < pipe2nclients(pipe); i++) {
- u32 cid = pipe2client(pipe, i);
- struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+ for_each_set_bit(pipe, &state->assigned, sizeof(state->assigned) * 8) {
+ unsigned i, nblks = 0;
- /*
- * if vblank has not happened since last smp_configure
- * skip the configure for now
- */
- if (!bitmap_equal(ps->inuse, ps->configured, cnt))
- continue;
+ for (i = 0; i < pipe2nclients(pipe); i++) {
+ u32 cid = pipe2client(pipe, i);
+ void *cs = state->client_state[cid];
- bitmap_copy(ps->configured, ps->pending, cnt);
- bitmap_or(assigned, ps->inuse, ps->configured, cnt);
- update_smp_state(smp, cid, &assigned);
+ nblks += update_smp_state(smp, cid, cs);
+
+ DBG("assign %s:%u, %u blks",
+ pipe2name(pipe), i, nblks);
+ }
+
+ set_fifo_thresholds(smp, pipe, nblks);
}
+
+ state->assigned = 0;
}
-/* step #3: after vblank, copy configured -> inuse: */
-void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
{
- int cnt = smp->blk_cnt;
- mdp5_smp_state_t released;
- int i;
-
- for (i = 0; i < pipe2nclients(pipe); i++) {
- u32 cid = pipe2client(pipe, i);
- struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+ enum mdp5_pipe pipe;
- /*
- * Figure out if there are any blocks we where previously
- * using, which can be released and made available to other
- * clients:
- */
- if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) {
- unsigned long flags;
+ for_each_set_bit(pipe, &state->released, sizeof(state->released) * 8) {
+ DBG("release %s", pipe2name(pipe));
+ set_fifo_thresholds(smp, pipe, 0);
+ }
- spin_lock_irqsave(&smp->state_lock, flags);
- /* clear released blocks: */
- bitmap_andnot(smp->state, smp->state, released, cnt);
- spin_unlock_irqrestore(&smp->state_lock, flags);
+ state->released = 0;
+}
- update_smp_state(smp, CID_UNUSED, &released);
+void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
+{
+ struct mdp5_kms *mdp5_kms = get_kms(smp);
+ struct mdp5_hw_pipe_state *hwpstate;
+ struct mdp5_smp_state *state;
+ int total = 0, i, j;
+
+ drm_printf(p, "name\tinuse\tplane\n");
+ drm_printf(p, "----\t-----\t-----\n");
+
+ if (drm_can_sleep())
+ drm_modeset_lock(&mdp5_kms->state_lock, NULL);
+
+ /* grab these *after* we hold the state_lock */
+ hwpstate = &mdp5_kms->state->hwpipe;
+ state = &mdp5_kms->state->smp;
+
+ for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+ struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
+ struct drm_plane *plane = hwpstate->hwpipe_to_plane[hwpipe->idx];
+ enum mdp5_pipe pipe = hwpipe->pipe;
+ for (j = 0; j < pipe2nclients(pipe); j++) {
+ u32 cid = pipe2client(pipe, j);
+ void *cs = state->client_state[cid];
+ int inuse = bitmap_weight(cs, smp->blk_cnt);
+
+ drm_printf(p, "%s:%d\t%d\t%s\n",
+ pipe2name(pipe), j, inuse,
+ plane ? plane->name : NULL);
+
+ total += inuse;
}
-
- bitmap_copy(ps->inuse, ps->configured, cnt);
}
+
+ drm_printf(p, "TOTAL:\t%d\t(of %d)\n", total, smp->blk_cnt);
+ drm_printf(p, "AVAIL:\t%d\n", smp->blk_cnt -
+ bitmap_weight(state->state, smp->blk_cnt));
+
+ if (drm_can_sleep())
+ drm_modeset_unlock(&mdp5_kms->state_lock);
}
void mdp5_smp_destroy(struct mdp5_smp *smp)
@@ -393,8 +339,9 @@ void mdp5_smp_destroy(struct mdp5_smp *smp)
kfree(smp);
}
-struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_block *cfg)
+struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg)
{
+ struct mdp5_smp_state *state = &mdp5_kms->state->smp;
struct mdp5_smp *smp = NULL;
int ret;
@@ -404,14 +351,13 @@ struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_blo
goto fail;
}
- smp->dev = dev;
+ smp->dev = mdp5_kms->dev;
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);
+ bitmap_copy(state->state, cfg->reserved_state, smp->blk_cnt);
memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
- spin_lock_init(&smp->state_lock);
return smp;
fail:
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
index 20b87e800ea3..b41d0448fbe8 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
@@ -19,12 +19,53 @@
#ifndef __MDP5_SMP_H__
#define __MDP5_SMP_H__
+#include <drm/drm_print.h>
+
#include "msm_drv.h"
-struct mdp5_client_smp_state {
- mdp5_smp_state_t inuse;
- mdp5_smp_state_t configured;
- mdp5_smp_state_t pending;
+/*
+ * SMP - Shared Memory Pool:
+ *
+ * SMP blocks are shared between all the clients, where each plane in
+ * a scanout buffer is a SMP client. Ie. scanout of 3 plane I420 on
+ * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
+ *
+ * Based on the size of the attached scanout buffer, a certain # of
+ * blocks must be allocated to that client out of the shared pool.
+ *
+ * In some hw, some blocks are statically allocated for certain pipes
+ * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
+ *
+ *
+ * Atomic SMP State:
+ *
+ * On atomic updates that modify SMP configuration, the state is cloned
+ * (copied) and modified. For test-only, or in cases where atomic
+ * update fails (or if we hit ww_mutex deadlock/backoff condition) the
+ * new state is simply thrown away.
+ *
+ * Because the SMP registers are not double buffered, updates are a
+ * two step process:
+ *
+ * 1) in _prepare_commit() we configure things (via read-modify-write)
+ * for the newly assigned pipes, so we don't take away blocks
+ * assigned to pipes that are still scanning out
+ * 2) in _complete_commit(), after vblank/etc, we clear things for the
+ * released clients, since at that point old pipes are no longer
+ * scanning out.
+ */
+struct mdp5_smp_state {
+ /* global state of what blocks are in use: */
+ mdp5_smp_state_t state;
+
+ /* per client state of what blocks they are using: */
+ mdp5_smp_state_t client_state[MAX_CLIENTS];
+
+ /* assigned pipes (hw updated at _prepare_commit()): */
+ unsigned long assigned;
+
+ /* released pipes (hw updated at _complete_commit()): */
+ unsigned long released;
};
struct mdp5_kms;
@@ -36,13 +77,22 @@ struct mdp5_smp;
* which is then used to call the other mdp5_smp_*(handler, ...) functions.
*/
-struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_block *cfg);
+struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms,
+ const struct mdp5_smp_block *cfg);
void mdp5_smp_destroy(struct mdp5_smp *smp);
-int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
- const struct mdp_format *format, u32 width, bool hdecim);
-void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe);
-void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe);
-void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe);
+void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p);
+
+uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
+ const struct mdp_format *format,
+ u32 width, bool hdecim);
+
+int mdp5_smp_assign(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+ enum mdp5_pipe pipe, uint32_t blkcfg);
+void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+ enum mdp5_pipe pipe);
+
+void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state);
+void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state);
#endif /* __MDP5_SMP_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index 452e3518f98b..8994c365e218 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2016-02-10 17:07:21)
- /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 ( 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/mdp/mdp5.xml ( 36965 bytes, from 2016-11-26 23:01:08)
- /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)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 73bae382eac3..30b5d23e53b4 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -141,7 +141,7 @@ static void complete_commit(struct msm_commit *c, bool async)
kms->funcs->complete_commit(kms, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
commit_destroy(c);
}
@@ -217,8 +217,9 @@ int msm_atomic_commit(struct drm_device *dev,
if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
struct drm_gem_object *obj = msm_framebuffer_bo(plane_state->fb, 0);
struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv);
- plane_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);
+ drm_atomic_set_fence_for_plane(plane_state, fence);
}
}
@@ -240,6 +241,10 @@ int msm_atomic_commit(struct drm_device *dev,
drm_atomic_helper_swap_state(state, true);
+ /* swap driver private state while still holding state_lock */
+ if (to_kms_state(state)->state)
+ priv->kms->funcs->swap_state(priv->kms, state);
+
/*
* Everything below can be run asynchronously without the need to grab
* any modeset locks at all under one conditions: It must be guaranteed
@@ -256,6 +261,7 @@ int msm_atomic_commit(struct drm_device *dev,
* current layout.
*/
+ drm_atomic_state_get(state);
if (nonblock) {
queue_work(priv->atomic_wq, &c->work);
return 0;
@@ -269,3 +275,30 @@ error:
drm_atomic_helper_cleanup_planes(dev, state);
return ret;
}
+
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
+{
+ struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+ if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
+ kfree(state);
+ return NULL;
+ }
+
+ return &state->base;
+}
+
+void msm_atomic_state_clear(struct drm_atomic_state *s)
+{
+ struct msm_kms_state *state = to_kms_state(s);
+ drm_atomic_state_default_clear(&state->base);
+ kfree(state->state);
+ state->state = NULL;
+}
+
+void msm_atomic_state_free(struct drm_atomic_state *state)
+{
+ kfree(to_kms_state(state)->state);
+ drm_atomic_state_default_release(state);
+ kfree(state);
+}
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
index 663f2b6ef091..c1b40f5adb60 100644
--- a/drivers/gpu/drm/msm/msm_debugfs.c
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -18,6 +18,8 @@
#ifdef CONFIG_DEBUG_FS
#include "msm_drv.h"
#include "msm_gpu.h"
+#include "msm_kms.h"
+#include "msm_debugfs.h"
static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
{
@@ -141,6 +143,7 @@ int msm_debugfs_late_init(struct drm_device *dev)
int msm_debugfs_init(struct drm_minor *minor)
{
struct drm_device *dev = minor->dev;
+ struct msm_drm_private *priv = dev->dev_private;
int ret;
ret = drm_debugfs_create_files(msm_debugfs_list,
@@ -152,15 +155,25 @@ int msm_debugfs_init(struct drm_minor *minor)
return ret;
}
- return 0;
+ if (priv->kms->funcs->debugfs_init)
+ ret = priv->kms->funcs->debugfs_init(priv->kms, minor);
+
+ return ret;
}
void msm_debugfs_cleanup(struct drm_minor *minor)
{
+ struct drm_device *dev = minor->dev;
+ struct msm_drm_private *priv = dev->dev_private;
+
drm_debugfs_remove_files(msm_debugfs_list,
ARRAY_SIZE(msm_debugfs_list), minor);
- if (!minor->dev->dev_private)
+ if (!priv)
return;
+
+ if (priv->kms->funcs->debugfs_cleanup)
+ priv->kms->funcs->debugfs_cleanup(priv->kms, minor);
+
msm_rd_debugfs_cleanup(minor);
msm_perf_debugfs_cleanup(minor);
}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 46568fc80848..e29bb66f55b1 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -15,6 +15,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_of.h>
+
#include "msm_drv.h"
#include "msm_debugfs.h"
#include "msm_fence.h"
@@ -44,17 +46,21 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
.output_poll_changed = msm_fb_output_poll_changed,
.atomic_check = msm_atomic_check,
.atomic_commit = msm_atomic_commit,
+ .atomic_state_alloc = msm_atomic_state_alloc,
+ .atomic_state_clear = msm_atomic_state_clear,
+ .atomic_state_free = msm_atomic_state_free,
};
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
+int msm_register_address_space(struct drm_device *dev,
+ struct msm_gem_address_space *aspace)
{
struct msm_drm_private *priv = dev->dev_private;
- int idx = priv->num_mmus++;
+ int idx = priv->num_aspaces++;
- if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus)))
+ if (WARN_ON(idx >= ARRAY_SIZE(priv->aspace)))
return -EINVAL;
- priv->mmus[idx] = mmu;
+ priv->aspace[idx] = aspace;
return idx;
}
@@ -77,6 +83,10 @@ static char *vram = "16m";
MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU)");
module_param(vram, charp, 0);
+bool dumpstate = false;
+MODULE_PARM_DESC(dumpstate, "Dump KMS state on errors");
+module_param(dumpstate, bool, 0600);
+
/*
* Util/helpers:
*/
@@ -766,9 +776,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -903,10 +911,8 @@ static int add_components_mdp(struct device *mdp_dev,
* remote-endpoint isn't a component that we need to add
*/
if (of_device_is_compatible(np, "qcom,mdp4") &&
- ep.port == 0) {
- of_node_put(ep_node);
+ ep.port == 0)
continue;
- }
/*
* It's okay if some of the ports don't have a remote endpoint
@@ -914,15 +920,12 @@ static int add_components_mdp(struct device *mdp_dev,
* any external interface.
*/
intf = of_graph_get_remote_port_parent(ep_node);
- if (!intf) {
- of_node_put(ep_node);
+ if (!intf)
continue;
- }
-
- component_match_add(master_dev, matchptr, compare_of, intf);
+ drm_of_component_match_add(master_dev, matchptr, compare_of,
+ intf);
of_node_put(intf);
- of_node_put(ep_node);
}
return 0;
@@ -962,8 +965,8 @@ static int add_display_components(struct device *dev,
put_device(mdp_dev);
/* add the MDP component itself */
- component_match_add(dev, matchptr, compare_of,
- mdp_dev->of_node);
+ drm_of_component_match_add(dev, matchptr, compare_of,
+ mdp_dev->of_node);
} else {
/* MDP4 */
mdp_dev = dev;
@@ -996,7 +999,7 @@ static int add_gpu_components(struct device *dev,
if (!np)
return 0;
- component_match_add(dev, matchptr, compare_of, np);
+ drm_of_component_match_add(dev, matchptr, compare_of, np);
of_node_put(np);
@@ -1035,7 +1038,13 @@ static int msm_pdev_probe(struct platform_device *pdev)
if (ret)
return ret;
- pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ /* on all devices that I am aware of, iommu's which can map
+ * any address the cpu can see are used:
+ */
+ ret = dma_set_mask_and_coherent(&pdev->dev, ~0);
+ if (ret)
+ return ret;
+
return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index d0da52f2a806..ed4dad3ca133 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -52,6 +52,8 @@ struct msm_perf_state;
struct msm_gem_submit;
struct msm_fence_context;
struct msm_fence_cb;
+struct msm_gem_address_space;
+struct msm_gem_vma;
#define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */
@@ -121,12 +123,16 @@ struct msm_drm_private {
uint32_t pending_crtcs;
wait_queue_head_t pending_crtcs_event;
- /* registered MMUs: */
- unsigned int num_mmus;
- struct msm_mmu *mmus[NUM_DOMAINS];
+ /* Registered address spaces.. currently this is fixed per # of
+ * iommu's. Ie. one for display block and one for gpu block.
+ * Eventually, to do per-process gpu pagetables, we'll want one
+ * of these per-process.
+ */
+ unsigned int num_aspaces;
+ struct msm_gem_address_space *aspace[NUM_DOMAINS];
unsigned int num_planes;
- struct drm_plane *planes[8];
+ struct drm_plane *planes[16];
unsigned int num_crtcs;
struct drm_crtc *crtcs[8];
@@ -173,8 +179,22 @@ int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state);
int msm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool nonblock);
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
+void msm_atomic_state_clear(struct drm_atomic_state *state);
+void msm_atomic_state_free(struct drm_atomic_state *state);
+
+int msm_register_address_space(struct drm_device *dev,
+ struct msm_gem_address_space *aspace);
+
+void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt);
+int msm_gem_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
+void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace);
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+ const char *name);
void msm_gem_submit_free(struct msm_gem_submit *submit);
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
@@ -189,9 +209,9 @@ int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
- uint32_t *iova);
-int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova);
-uint32_t msm_gem_iova(struct drm_gem_object *obj, int id);
+ uint64_t *iova);
+int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint64_t *iova);
+uint64_t msm_gem_iova(struct drm_gem_object *obj, int id);
struct page **msm_gem_get_pages(struct drm_gem_object *obj);
void msm_gem_put_pages(struct drm_gem_object *obj);
void msm_gem_put_iova(struct drm_gem_object *obj, int id);
@@ -217,7 +237,7 @@ void msm_gem_vunmap(struct drm_gem_object *obj);
int msm_gem_sync_object(struct drm_gem_object *obj,
struct msm_fence_context *fctx, bool exclusive);
void msm_gem_move_to_active(struct drm_gem_object *obj,
- struct msm_gpu *gpu, bool exclusive, struct fence *fence);
+ struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence);
void msm_gem_move_to_inactive(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
int msm_gem_cpu_fini(struct drm_gem_object *obj);
@@ -303,8 +323,8 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
void msm_writel(u32 data, void __iomem *addr);
u32 msm_readl(const void __iomem *addr);
-#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
+#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
static inline int align_pitch(int width, int bpp)
{
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 95cf8fe72ee5..9acf544e7a8f 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -88,11 +88,11 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id)
{
struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
int ret, i, n = drm_format_num_planes(fb->pixel_format);
- uint32_t iova;
+ uint64_t iova;
for (i = 0; i < n; i++) {
ret = msm_gem_get_iova(msm_fb->planes[i], id, &iova);
- DBG("FB[%u]: iova[%d]: %08x (%d)", fb->base.id, i, iova, ret);
+ DBG("FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index ffd4a338ca12..bffe93498512 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -39,6 +39,7 @@ struct msm_fbdev {
static struct fb_ops msm_fb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
/* Note: to properly handle manual update displays, we wrap the
* basic fbdev ops which write to the framebuffer
@@ -49,12 +50,6 @@ static struct fb_ops msm_fb_ops = {
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_mmap = msm_fbdev_mmap,
-
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
};
static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
@@ -81,7 +76,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
struct drm_framebuffer *fb = NULL;
struct fb_info *fbi = NULL;
struct drm_mode_fb_cmd2 mode_cmd = {0};
- uint32_t paddr;
+ uint64_t paddr;
int ret, size;
DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index a9b9b1c95a2e..3f299c537b77 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -15,7 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include "msm_drv.h"
#include "msm_fence.h"
@@ -32,7 +32,7 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)
fctx->dev = dev;
fctx->name = name;
- fctx->context = fence_context_alloc(1);
+ fctx->context = dma_fence_context_alloc(1);
init_waitqueue_head(&fctx->event);
spin_lock_init(&fctx->spinlock);
@@ -100,52 +100,52 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
struct msm_fence {
struct msm_fence_context *fctx;
- struct fence base;
+ struct dma_fence base;
};
-static inline struct msm_fence *to_msm_fence(struct fence *fence)
+static inline struct msm_fence *to_msm_fence(struct dma_fence *fence)
{
return container_of(fence, struct msm_fence, base);
}
-static const char *msm_fence_get_driver_name(struct fence *fence)
+static const char *msm_fence_get_driver_name(struct dma_fence *fence)
{
return "msm";
}
-static const char *msm_fence_get_timeline_name(struct fence *fence)
+static const char *msm_fence_get_timeline_name(struct dma_fence *fence)
{
struct msm_fence *f = to_msm_fence(fence);
return f->fctx->name;
}
-static bool msm_fence_enable_signaling(struct fence *fence)
+static bool msm_fence_enable_signaling(struct dma_fence *fence)
{
return true;
}
-static bool msm_fence_signaled(struct fence *fence)
+static bool msm_fence_signaled(struct dma_fence *fence)
{
struct msm_fence *f = to_msm_fence(fence);
return fence_completed(f->fctx, f->base.seqno);
}
-static void msm_fence_release(struct fence *fence)
+static void msm_fence_release(struct dma_fence *fence)
{
struct msm_fence *f = to_msm_fence(fence);
kfree_rcu(f, base.rcu);
}
-static const struct fence_ops msm_fence_ops = {
+static const struct dma_fence_ops msm_fence_ops = {
.get_driver_name = msm_fence_get_driver_name,
.get_timeline_name = msm_fence_get_timeline_name,
.enable_signaling = msm_fence_enable_signaling,
.signaled = msm_fence_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = msm_fence_release,
};
-struct fence *
+struct dma_fence *
msm_fence_alloc(struct msm_fence_context *fctx)
{
struct msm_fence *f;
@@ -156,8 +156,8 @@ msm_fence_alloc(struct msm_fence_context *fctx)
f->fctx = fctx;
- fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
- fctx->context, ++fctx->last_fence);
+ dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
+ fctx->context, ++fctx->last_fence);
return &f->base;
}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index ceb5b3d314b4..56061aa1959d 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -41,6 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx,
struct msm_fence_cb *cb, uint32_t fence);
void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
-struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
+struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx);
#endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index b6ac27e31929..cd06cfd94687 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -296,12 +296,8 @@ put_iova(struct drm_gem_object *obj)
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
- struct msm_mmu *mmu = priv->mmus[id];
- if (mmu && msm_obj->domain[id].iova) {
- uint32_t offset = msm_obj->domain[id].iova;
- mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size);
- msm_obj->domain[id].iova = 0;
- }
+ msm_gem_unmap_vma(priv->aspace[id],
+ &msm_obj->domain[id], msm_obj->sgt);
}
}
@@ -313,7 +309,7 @@ put_iova(struct drm_gem_object *obj)
* the refcnt counter needs to be atomic_t.
*/
int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
- uint32_t *iova)
+ uint64_t *iova)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
int ret = 0;
@@ -326,16 +322,8 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
return PTR_ERR(pages);
if (iommu_present(&platform_bus_type)) {
- struct msm_mmu *mmu = priv->mmus[id];
- uint32_t offset;
-
- if (WARN_ON(!mmu))
- return -EINVAL;
-
- offset = (uint32_t)mmap_offset(obj);
- ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
- obj->size, IOMMU_READ | IOMMU_WRITE);
- msm_obj->domain[id].iova = offset;
+ ret = msm_gem_map_vma(priv->aspace[id], &msm_obj->domain[id],
+ msm_obj->sgt, obj->size >> PAGE_SHIFT);
} else {
msm_obj->domain[id].iova = physaddr(obj);
}
@@ -348,7 +336,7 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
}
/* get iova, taking a reference. Should have a matching put */
-int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova)
+int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint64_t *iova)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
int ret;
@@ -370,7 +358,7 @@ int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova)
/* get iova without taking a reference, used in places where you have
* already done a 'msm_gem_get_iova()'.
*/
-uint32_t msm_gem_iova(struct drm_gem_object *obj, int id)
+uint64_t msm_gem_iova(struct drm_gem_object *obj, int id)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
WARN_ON(!msm_obj->domain[id].iova);
@@ -521,7 +509,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj,
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
struct reservation_object_list *fobj;
- struct fence *fence;
+ struct dma_fence *fence;
int i, ret;
if (!exclusive) {
@@ -540,7 +528,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj,
fence = reservation_object_get_excl(msm_obj->resv);
/* don't need to wait on our own fences, since ring is fifo */
if (fence && (fence->context != fctx->context)) {
- ret = fence_wait(fence, true);
+ ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
@@ -553,7 +541,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj,
fence = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(msm_obj->resv));
if (fence->context != fctx->context) {
- ret = fence_wait(fence, true);
+ ret = dma_fence_wait(fence, true);
if (ret)
return ret;
}
@@ -563,7 +551,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj,
}
void msm_gem_move_to_active(struct drm_gem_object *obj,
- struct msm_gpu *gpu, bool exclusive, struct fence *fence)
+ struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED);
@@ -616,10 +604,10 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj)
}
#ifdef CONFIG_DEBUG_FS
-static void describe_fence(struct fence *fence, const char *type,
+static void describe_fence(struct dma_fence *fence, const char *type,
struct seq_file *m)
{
- if (!fence_is_signaled(fence))
+ if (!dma_fence_is_signaled(fence))
seq_printf(m, "\t%9s: %s %s seq %u\n", type,
fence->ops->get_driver_name(fence),
fence->ops->get_timeline_name(fence),
@@ -631,9 +619,11 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
struct msm_gem_object *msm_obj = to_msm_bo(obj);
struct reservation_object *robj = msm_obj->resv;
struct reservation_object_list *fobj;
- struct fence *fence;
+ struct msm_drm_private *priv = obj->dev->dev_private;
+ struct dma_fence *fence;
uint64_t off = drm_vma_node_start(&obj->vma_node);
const char *madv;
+ unsigned id;
WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
@@ -650,10 +640,15 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
break;
}
- seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu%s\n",
+ seq_printf(m, "%08x: %c %2d (%2d) %08llx %p\t",
msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
obj->name, obj->refcount.refcount.counter,
- off, msm_obj->vaddr, obj->size, madv);
+ off, msm_obj->vaddr);
+
+ for (id = 0; id < priv->num_aspaces; id++)
+ seq_printf(m, " %08llx", msm_obj->domain[id].iova);
+
+ seq_printf(m, " %zu%s\n", obj->size, madv);
rcu_read_lock();
fobj = rcu_dereference(robj->fence);
@@ -761,7 +756,6 @@ static int msm_gem_new_impl(struct drm_device *dev,
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_gem_object *msm_obj;
- unsigned sz;
bool use_vram = false;
switch (flags & MSM_BO_CACHE_MASK) {
@@ -783,16 +777,12 @@ static int msm_gem_new_impl(struct drm_device *dev,
if (WARN_ON(use_vram && !priv->vram.size))
return -EINVAL;
- sz = sizeof(*msm_obj);
- if (use_vram)
- sz += sizeof(struct drm_mm_node);
-
- msm_obj = kzalloc(sz, GFP_KERNEL);
+ msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);
if (!msm_obj)
return -ENOMEM;
if (use_vram)
- msm_obj->vram_node = (void *)&msm_obj[1];
+ msm_obj->vram_node = &msm_obj->domain[0].node;
msm_obj->flags = flags;
msm_obj->madv = MSM_MADV_WILLNEED;
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index b2f13cfe945e..7d529516b332 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -24,6 +24,20 @@
/* Additional internal-use only BO flags: */
#define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */
+struct msm_gem_address_space {
+ const char *name;
+ /* NOTE: mm managed at the page level, size is in # of pages
+ * and position mm_node->start is in # of pages:
+ */
+ struct drm_mm mm;
+ struct msm_mmu *mmu;
+};
+
+struct msm_gem_vma {
+ struct drm_mm_node node;
+ uint64_t iova;
+};
+
struct msm_gem_object {
struct drm_gem_object base;
@@ -61,10 +75,7 @@ struct msm_gem_object {
struct sg_table *sgt;
void *vaddr;
- struct {
- // XXX
- uint32_t iova;
- } domain[NUM_DOMAINS];
+ struct msm_gem_vma domain[NUM_DOMAINS];
/* normally (resv == &_resv) except for imported bo's */
struct reservation_object *resv;
@@ -104,7 +115,7 @@ struct msm_gem_submit {
struct list_head node; /* node in gpu submit_list */
struct list_head bo_list;
struct ww_acquire_ctx ticket;
- struct fence *fence;
+ struct dma_fence *fence;
struct pid *pid; /* submitting process */
bool valid; /* true if no cmdstream patching needed */
unsigned int nr_cmds;
@@ -112,13 +123,13 @@ struct msm_gem_submit {
struct {
uint32_t type;
uint32_t size; /* in dwords */
- uint32_t iova;
+ uint64_t iova;
uint32_t idx; /* cmdstream buffer idx in bos[] */
} *cmd; /* array of size nr_cmds */
struct {
uint32_t flags;
struct msm_gem_object *obj;
- uint32_t iova;
+ uint64_t iova;
} bos[0];
};
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 192b2d3a79cb..ab1dd020eb04 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -18,33 +18,24 @@
#include "msm_drv.h"
#include "msm_gem.h"
-static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
+static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
{
- if (!mutex_is_locked(mutex))
+ switch (mutex_trylock_recursive(&dev->struct_mutex)) {
+ case MUTEX_TRYLOCK_FAILED:
return false;
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
- return mutex->owner == task;
-#else
- /* Since UP may be pre-empted, we cannot assume that we own the lock */
- return false;
-#endif
-}
+ case MUTEX_TRYLOCK_SUCCESS:
+ *unlock = true;
+ return true;
-static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
-{
- if (!mutex_trylock(&dev->struct_mutex)) {
- if (!mutex_is_locked_by(&dev->struct_mutex, current))
- return false;
+ case MUTEX_TRYLOCK_RECURSIVE:
*unlock = false;
- } else {
- *unlock = true;
+ return true;
}
- return true;
+ BUG();
}
-
static unsigned long
msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index b6a0f37a65f3..166e84e4f0d4 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -60,7 +60,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
void msm_gem_submit_free(struct msm_gem_submit *submit)
{
- fence_put(submit->fence);
+ dma_fence_put(submit->fence);
list_del(&submit->node);
put_pid(submit->pid);
kfree(submit);
@@ -241,7 +241,7 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
- uint32_t iova;
+ uint64_t iova;
/* if locking succeeded, pin bo: */
ret = msm_gem_get_iova_locked(&msm_obj->base,
@@ -266,7 +266,7 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
}
static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
- struct msm_gem_object **obj, uint32_t *iova, bool *valid)
+ struct msm_gem_object **obj, uint64_t *iova, bool *valid)
{
if (idx >= submit->nr_bos) {
DRM_ERROR("invalid buffer index: %u (out of %u)\n",
@@ -312,7 +312,8 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
struct drm_msm_gem_submit_reloc submit_reloc;
void __user *userptr =
u64_to_user_ptr(relocs + (i * sizeof(submit_reloc)));
- uint32_t iova, off;
+ uint32_t off;
+ uint64_t iova;
bool valid;
ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc));
@@ -380,7 +381,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct msm_file_private *ctx = file->driver_priv;
struct msm_gem_submit *submit;
struct msm_gpu *gpu = priv->gpu;
- struct fence *in_fence = NULL;
+ struct dma_fence *in_fence = NULL;
struct sync_file *sync_file = NULL;
int out_fence_fd = -1;
unsigned i;
@@ -439,7 +440,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
*/
if (in_fence->context != gpu->fctx->context) {
- ret = fence_wait(in_fence, true);
+ ret = dma_fence_wait(in_fence, true);
if (ret)
goto out;
}
@@ -461,7 +462,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
void __user *userptr =
u64_to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
struct msm_gem_object *msm_obj;
- uint32_t iova;
+ uint64_t iova;
ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd));
if (ret) {
@@ -542,7 +543,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
out:
if (in_fence)
- fence_put(in_fence);
+ dma_fence_put(in_fence);
submit_cleanup(submit);
if (ret)
msm_gem_submit_free(submit);
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
new file mode 100644
index 000000000000..a311d26ccb21
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 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/>.
+ */
+
+#include "msm_drv.h"
+#include "msm_gem.h"
+#include "msm_mmu.h"
+
+void
+msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt)
+{
+ if (!vma->iova)
+ return;
+
+ if (aspace->mmu) {
+ unsigned size = vma->node.size << PAGE_SHIFT;
+ aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt, size);
+ }
+
+ drm_mm_remove_node(&vma->node);
+
+ vma->iova = 0;
+}
+
+int
+msm_gem_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+{
+ int ret;
+
+ if (WARN_ON(drm_mm_node_allocated(&vma->node)))
+ return 0;
+
+ ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages,
+ 0, DRM_MM_SEARCH_DEFAULT);
+ if (ret)
+ return ret;
+
+ vma->iova = vma->node.start << PAGE_SHIFT;
+
+ if (aspace->mmu) {
+ unsigned size = npages << PAGE_SHIFT;
+ ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
+ size, IOMMU_READ | IOMMU_WRITE);
+ }
+
+ return ret;
+}
+
+void
+msm_gem_address_space_destroy(struct msm_gem_address_space *aspace)
+{
+ drm_mm_takedown(&aspace->mm);
+ if (aspace->mmu)
+ aspace->mmu->funcs->destroy(aspace->mmu);
+ kfree(aspace);
+}
+
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+ const char *name)
+{
+ struct msm_gem_address_space *aspace;
+
+ aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
+ if (!aspace)
+ return ERR_PTR(-ENOMEM);
+
+ aspace->name = name;
+ aspace->mmu = msm_iommu_new(dev, domain);
+
+ drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
+ (domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
+
+ return aspace;
+}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 5bb09838b5ae..b28527a65d09 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -91,21 +91,20 @@ static int disable_pwrrail(struct msm_gpu *gpu)
static int enable_clk(struct msm_gpu *gpu)
{
- struct clk *rate_clk = NULL;
int i;
- /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
- if (gpu->grp_clks[i]) {
- clk_prepare(gpu->grp_clks[i]);
- rate_clk = gpu->grp_clks[i];
- }
- }
+ if (gpu->grp_clks[0] && gpu->fast_rate)
+ clk_set_rate(gpu->grp_clks[0], gpu->fast_rate);
- if (rate_clk && gpu->fast_rate)
- clk_set_rate(rate_clk, gpu->fast_rate);
+ /* Set the RBBM timer rate to 19.2Mhz */
+ if (gpu->grp_clks[2])
+ clk_set_rate(gpu->grp_clks[2], 19200000);
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+ if (gpu->grp_clks[i])
+ clk_prepare(gpu->grp_clks[i]);
+
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
if (gpu->grp_clks[i])
clk_enable(gpu->grp_clks[i]);
@@ -114,24 +113,22 @@ static int enable_clk(struct msm_gpu *gpu)
static int disable_clk(struct msm_gpu *gpu)
{
- struct clk *rate_clk = NULL;
int i;
- /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
- if (gpu->grp_clks[i]) {
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+ if (gpu->grp_clks[i])
clk_disable(gpu->grp_clks[i]);
- rate_clk = gpu->grp_clks[i];
- }
- }
-
- if (rate_clk && gpu->slow_rate)
- clk_set_rate(rate_clk, gpu->slow_rate);
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
if (gpu->grp_clks[i])
clk_unprepare(gpu->grp_clks[i]);
+ if (gpu->grp_clks[0] && gpu->slow_rate)
+ clk_set_rate(gpu->grp_clks[0], gpu->slow_rate);
+
+ if (gpu->grp_clks[2])
+ clk_set_rate(gpu->grp_clks[2], 0);
+
return 0;
}
@@ -476,7 +473,7 @@ static void retire_submits(struct msm_gpu *gpu)
submit = list_first_entry(&gpu->submit_list,
struct msm_gem_submit, node);
- if (fence_is_signaled(submit->fence)) {
+ if (dma_fence_is_signaled(submit->fence)) {
retire_submit(gpu, submit);
} else {
break;
@@ -528,7 +525,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
- uint32_t iova;
+ uint64_t iova;
/* can't happen yet.. but when we add 2d support we'll have
* to deal w/ cross-ring synchronization:
@@ -563,8 +560,8 @@ static irqreturn_t irq_handler(int irq, void *data)
}
static const char *clk_names[] = {
- "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
- "alt_mem_iface_clk",
+ "core_clk", "iface_clk", "rbbmtimer_clk", "mem_clk",
+ "mem_iface_clk", "alt_mem_iface_clk",
};
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
@@ -656,12 +653,17 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
*/
iommu = iommu_domain_alloc(&platform_bus_type);
if (iommu) {
+ /* TODO 32b vs 64b address space.. */
+ iommu->geometry.aperture_start = SZ_16M;
+ iommu->geometry.aperture_end = 0xffffffff;
+
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);
+ gpu->aspace = msm_gem_address_space_create(&pdev->dev,
+ iommu, "gpu");
+ if (IS_ERR(gpu->aspace)) {
+ ret = PTR_ERR(gpu->aspace);
dev_err(drm->dev, "failed to init iommu: %d\n", ret);
- gpu->mmu = NULL;
+ gpu->aspace = NULL;
iommu_domain_free(iommu);
goto fail;
}
@@ -669,7 +671,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
} else {
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
}
- gpu->id = msm_register_mmu(drm, gpu->mmu);
+ gpu->id = msm_register_address_space(drm, gpu->aspace);
/* Create ringbuffer: */
@@ -705,8 +707,8 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
msm_ringbuffer_destroy(gpu->rb);
}
- if (gpu->mmu)
- gpu->mmu->funcs->destroy(gpu->mmu);
+ if (gpu->aspace)
+ msm_gem_address_space_destroy(gpu->aspace);
if (gpu->fctx)
msm_fence_context_free(gpu->fctx);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index d61d98a6e047..c4c39d3272c7 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -50,7 +50,7 @@ struct msm_gpu_funcs {
void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx);
void (*flush)(struct msm_gpu *gpu);
- void (*idle)(struct msm_gpu *gpu);
+ bool (*idle)(struct msm_gpu *gpu);
irqreturn_t (*irq)(struct msm_gpu *irq);
uint32_t (*last_fence)(struct msm_gpu *gpu);
void (*recover)(struct msm_gpu *gpu);
@@ -80,7 +80,7 @@ struct msm_gpu {
/* ringbuffer: */
struct msm_ringbuffer *rb;
- uint32_t rb_iova;
+ uint64_t rb_iova;
/* list of GEM active objects: */
struct list_head active_list;
@@ -98,7 +98,7 @@ struct msm_gpu {
void __iomem *mmio;
int irq;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
int id;
/* Power Control: */
@@ -154,6 +154,45 @@ static inline u32 gpu_read(struct msm_gpu *gpu, u32 reg)
return msm_readl(gpu->mmio + (reg << 2));
}
+static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
+{
+ uint32_t val = gpu_read(gpu, reg);
+
+ val &= ~mask;
+ gpu_write(gpu, reg, val | or);
+}
+
+static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
+{
+ u64 val;
+
+ /*
+ * Why not a readq here? Two reasons: 1) many of the LO registers are
+ * not quad word aligned and 2) the GPU hardware designers have a bit
+ * of a history of putting registers where they fit, especially in
+ * spins. The longer a GPU family goes the higher the chance that
+ * we'll get burned. We could do a series of validity checks if we
+ * wanted to, but really is a readq() that much better? Nah.
+ */
+
+ /*
+ * For some lo/hi registers (like perfcounters), the hi value is latched
+ * when the lo is read, so make sure to read the lo first to trigger
+ * that
+ */
+ val = (u64) msm_readl(gpu->mmio + (lo << 2));
+ val |= ((u64) msm_readl(gpu->mmio + (hi << 2)) << 32);
+
+ return val;
+}
+
+static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
+{
+ /* Why not a writeq here? Read the screed above */
+ msm_writel(lower_32_bits(val), gpu->mmio + (lo << 2));
+ msm_writel(upper_32_bits(val), gpu->mmio + (hi << 2));
+}
+
int msm_gpu_pm_suspend(struct msm_gpu *gpu);
int msm_gpu_pm_resume(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 3a294d0da3a0..61aaaa1de6eb 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -45,13 +45,13 @@ static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
iommu_detach_device(iommu->domain, mmu->dev);
}
-static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
+static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
struct sg_table *sgt, unsigned len, int prot)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
struct iommu_domain *domain = iommu->domain;
struct scatterlist *sg;
- unsigned int da = iova;
+ unsigned long da = iova;
unsigned int i, j;
int ret;
@@ -62,7 +62,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
dma_addr_t pa = sg_phys(sg) - sg->offset;
size_t bytes = sg->length + sg->offset;
- VERB("map[%d]: %08x %08lx(%zx)", i, da, (unsigned long)pa, bytes);
+ VERB("map[%d]: %08lx %08lx(%zx)", i, da, (unsigned long)pa, bytes);
ret = iommu_map(domain, da, pa, bytes, prot);
if (ret)
@@ -84,13 +84,13 @@ fail:
return ret;
}
-static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
+static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova,
struct sg_table *sgt, unsigned len)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
struct iommu_domain *domain = iommu->domain;
struct scatterlist *sg;
- unsigned int da = iova;
+ unsigned long da = iova;
int i;
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
@@ -101,7 +101,7 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
if (unmapped < bytes)
return unmapped;
- VERB("unmap[%d]: %08x(%zx)", i, da, bytes);
+ VERB("unmap[%d]: %08lx(%zx)", i, da, bytes);
BUG_ON(!PAGE_ALIGNED(bytes));
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 40e41e5cdbc6..e470f4cf8f76 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -40,6 +40,8 @@ struct msm_kms_funcs {
irqreturn_t (*irq)(struct msm_kms *kms);
int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+ /* swap global atomic state: */
+ void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
/* modeset, bracketing atomic_commit(): */
void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
@@ -56,6 +58,11 @@ struct msm_kms_funcs {
bool is_cmd_mode);
/* cleanup: */
void (*destroy)(struct msm_kms *kms);
+#ifdef CONFIG_DEBUG_FS
+ /* debugfs: */
+ int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
+ void (*debugfs_cleanup)(struct msm_kms *kms, struct drm_minor *minor);
+#endif
};
struct msm_kms {
@@ -65,6 +72,18 @@ struct msm_kms {
int irq;
};
+/**
+ * Subclass of drm_atomic_state, to allow kms backend to have driver
+ * private global state. The kms backend can do whatever it wants
+ * with the ->state ptr. On ->atomic_state_clear() the ->state ptr
+ * is kfree'd and set back to NULL.
+ */
+struct msm_kms_state {
+ struct drm_atomic_state base;
+ void *state;
+};
+#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
+
static inline void msm_kms_init(struct msm_kms *kms,
const struct msm_kms_funcs *funcs)
{
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index b8ca9a0e9170..f85c879e68d2 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -23,9 +23,9 @@
struct msm_mmu_funcs {
int (*attach)(struct msm_mmu *mmu, const char * const *names, int cnt);
void (*detach)(struct msm_mmu *mmu, const char * const *names, int cnt);
- int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+ int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
unsigned len, int prot);
- int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+ int (*unmap)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
unsigned len);
void (*destroy)(struct msm_mmu *mmu);
};
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 8487f461f05f..6607456dc626 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -289,7 +289,7 @@ void msm_rd_debugfs_cleanup(struct drm_minor *minor)
static void snapshot_buf(struct msm_rd_state *rd,
struct msm_gem_submit *submit, int idx,
- uint32_t iova, uint32_t size)
+ uint64_t iova, uint32_t size)
{
struct msm_gem_object *obj = submit->bos[idx].obj;
const char *buf;
@@ -306,7 +306,7 @@ static void snapshot_buf(struct msm_rd_state *rd,
}
rd_write_section(rd, RD_GPUADDR,
- (uint32_t[2]){ iova, size }, 8);
+ (uint32_t[3]){ iova, size, iova >> 32 }, 12);
rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
msm_gem_put_vaddr_locked(&obj->base);
diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig
new file mode 100644
index 000000000000..e9a8d90e6723
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/Kconfig
@@ -0,0 +1,19 @@
+config DRM_MXS
+ bool
+ help
+ Choose this option to select drivers for MXS FB devices
+
+config DRM_MXSFB
+ tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
+ depends on DRM && OF
+ depends on COMMON_CLK
+ select DRM_MXS
+ select DRM_KMS_HELPER
+ select DRM_KMS_FB_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_PANEL
+ help
+ Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
+ LCD controller.
+
+ If M is selected the module will be called mxsfb.
diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile
new file mode 100644
index 000000000000..857f3a4545ff
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/Makefile
@@ -0,0 +1,2 @@
+mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
+obj-$(CONFIG_DRM_MXSFB) += mxsfb.o
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
new file mode 100644
index 000000000000..081890336ce7
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * This code is based on drivers/video/fbdev/mxsfb.c :
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of_graph.h>
+#include <linux/platform_data/simplefb.h>
+#include <video/videomode.h>
+
+#include "mxsfb_drv.h"
+#include "mxsfb_regs.h"
+
+static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
+{
+ return (val & mxsfb->devdata->hs_wdth_mask) <<
+ mxsfb->devdata->hs_wdth_shift;
+}
+
+/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+{
+ struct drm_crtc *crtc = &mxsfb->pipe.crtc;
+ struct drm_device *drm = crtc->dev;
+ const u32 format = crtc->primary->state->fb->pixel_format;
+ u32 ctrl, ctrl1;
+
+ ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+
+ /*
+ * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
+ * match the selected mode here. This differs from the original
+ * MXSFB driver, which had the option to configure the bus width
+ * to arbitrary value. This limitation should not pose an issue.
+ */
+
+ /* CTRL1 contains IRQ config and status bits, preserve those. */
+ ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+ ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+
+ switch (format) {
+ case DRM_FORMAT_RGB565:
+ dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+ ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
+ ctrl |= CTRL_SET_WORD_LENGTH(0);
+ ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+ break;
+ case DRM_FORMAT_XRGB8888:
+ dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
+ ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+ ctrl |= CTRL_SET_WORD_LENGTH(3);
+ /* Do not use packed pixels = one pixel per word instead. */
+ ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
+ break;
+ default:
+ dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
+ return -EINVAL;
+ }
+
+ writel(ctrl1, mxsfb->base + LCDC_CTRL1);
+ writel(ctrl, mxsfb->base + LCDC_CTRL);
+
+ return 0;
+}
+
+static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
+{
+ u32 reg;
+
+ if (mxsfb->clk_disp_axi)
+ clk_prepare_enable(mxsfb->clk_disp_axi);
+ clk_prepare_enable(mxsfb->clk);
+ mxsfb_enable_axi_clk(mxsfb);
+
+ /* If it was disabled, re-enable the mode again */
+ writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
+
+ /* Enable the SYNC signals first, then the DMA engine */
+ reg = readl(mxsfb->base + LCDC_VDCTRL4);
+ reg |= VDCTRL4_SYNC_SIGNALS_ON;
+ writel(reg, mxsfb->base + LCDC_VDCTRL4);
+
+ writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+}
+
+static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
+{
+ u32 reg;
+
+ /*
+ * Even if we disable the controller here, it will still continue
+ * until its FIFOs are running out of data
+ */
+ writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
+
+ readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
+ 0, 1000);
+
+ reg = readl(mxsfb->base + LCDC_VDCTRL4);
+ reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
+ writel(reg, mxsfb->base + LCDC_VDCTRL4);
+
+ mxsfb_disable_axi_clk(mxsfb);
+
+ clk_disable_unprepare(mxsfb->clk);
+ if (mxsfb->clk_disp_axi)
+ clk_disable_unprepare(mxsfb->clk_disp_axi);
+}
+
+static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
+{
+ struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
+ const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+ u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
+ int err;
+
+ /*
+ * It seems, you can't re-program the controller if it is still
+ * running. This may lead to shifted pictures (FIFO issue?), so
+ * first stop the controller and drain its FIFOs.
+ */
+ mxsfb_enable_axi_clk(mxsfb);
+
+ /* Clear the FIFOs */
+ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
+
+ err = mxsfb_set_pixel_fmt(mxsfb);
+ if (err)
+ return;
+
+ clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
+
+ writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
+ TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
+ mxsfb->base + mxsfb->devdata->transfer_count);
+
+ vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
+
+ vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* Always in DOTCLOCK mode */
+ VDCTRL0_VSYNC_PERIOD_UNIT |
+ VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
+ VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
+ if (m->flags & DRM_MODE_FLAG_PHSYNC)
+ vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
+ if (m->flags & DRM_MODE_FLAG_PVSYNC)
+ vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
+ if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
+ vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
+ if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
+ vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
+
+ writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
+
+ /* Frame length in lines. */
+ writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
+
+ /* Line length in units of clocks or pixels. */
+ hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
+ writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
+ VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
+ mxsfb->base + LCDC_VDCTRL2);
+
+ writel(SET_HOR_WAIT_CNT(m->crtc_hblank_end - m->crtc_hsync_end) |
+ SET_VERT_WAIT_CNT(m->crtc_vblank_end - m->crtc_vsync_end),
+ mxsfb->base + LCDC_VDCTRL3);
+
+ writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
+ mxsfb->base + LCDC_VDCTRL4);
+
+ mxsfb_disable_axi_clk(mxsfb);
+}
+
+void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
+{
+ mxsfb_crtc_mode_set_nofb(mxsfb);
+ mxsfb_enable_controller(mxsfb);
+}
+
+void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
+{
+ mxsfb_disable_controller(mxsfb);
+}
+
+void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
+ struct drm_plane_state *state)
+{
+ struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_framebuffer *fb = pipe->plane.state->fb;
+ struct drm_pending_vblank_event *event;
+ struct drm_gem_cma_object *gem;
+
+ if (!crtc)
+ return;
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ event = crtc->state->event;
+ if (event) {
+ crtc->state->event = NULL;
+
+ if (drm_crtc_vblank_get(crtc) == 0) {
+ drm_crtc_arm_vblank_event(crtc, event);
+ } else {
+ drm_crtc_send_vblank_event(crtc, event);
+ }
+ }
+ spin_unlock_irq(&crtc->dev->event_lock);
+
+ if (!fb)
+ return;
+
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+ mxsfb_enable_axi_clk(mxsfb);
+ writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
+ mxsfb_disable_axi_clk(mxsfb);
+}
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
new file mode 100644
index 000000000000..79a18bf48b54
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * This code is based on drivers/video/fbdev/mxsfb.c :
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/list.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
+#include <linux/reservation.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "mxsfb_drv.h"
+#include "mxsfb_regs.h"
+
+enum mxsfb_devtype {
+ MXSFB_V3,
+ MXSFB_V4,
+};
+
+static const struct mxsfb_devdata mxsfb_devdata[] = {
+ [MXSFB_V3] = {
+ .transfer_count = LCDC_V3_TRANSFER_COUNT,
+ .cur_buf = LCDC_V3_CUR_BUF,
+ .next_buf = LCDC_V3_NEXT_BUF,
+ .debug0 = LCDC_V3_DEBUG0,
+ .hs_wdth_mask = 0xff,
+ .hs_wdth_shift = 24,
+ .ipversion = 3,
+ },
+ [MXSFB_V4] = {
+ .transfer_count = LCDC_V4_TRANSFER_COUNT,
+ .cur_buf = LCDC_V4_CUR_BUF,
+ .next_buf = LCDC_V4_NEXT_BUF,
+ .debug0 = LCDC_V4_DEBUG0,
+ .hs_wdth_mask = 0x3fff,
+ .hs_wdth_shift = 18,
+ .ipversion = 4,
+ },
+};
+
+static const uint32_t mxsfb_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGB565
+};
+
+static struct mxsfb_drm_private *
+drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
+{
+ return container_of(pipe, struct mxsfb_drm_private, pipe);
+}
+
+void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+ if (mxsfb->clk_axi)
+ clk_prepare_enable(mxsfb->clk_axi);
+}
+
+void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+ if (mxsfb->clk_axi)
+ clk_disable_unprepare(mxsfb->clk_axi);
+}
+
+static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
+ .fb_create = drm_fb_cma_create,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state)
+{
+ struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+ mxsfb_crtc_enable(mxsfb);
+}
+
+static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+ struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+ mxsfb_crtc_disable(mxsfb);
+}
+
+static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *plane_state)
+{
+ struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+ mxsfb_plane_atomic_update(mxsfb, plane_state);
+}
+
+static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *plane_state)
+{
+ return drm_fb_cma_prepare_fb(&pipe->plane, plane_state);
+}
+
+struct drm_simple_display_pipe_funcs mxsfb_funcs = {
+ .enable = mxsfb_pipe_enable,
+ .disable = mxsfb_pipe_disable,
+ .update = mxsfb_pipe_update,
+ .prepare_fb = mxsfb_pipe_prepare_fb,
+};
+
+static int mxsfb_load(struct drm_device *drm, unsigned long flags)
+{
+ struct platform_device *pdev = to_platform_device(drm->dev);
+ struct mxsfb_drm_private *mxsfb;
+ struct resource *res;
+ int ret;
+
+ mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
+ if (!mxsfb)
+ return -ENOMEM;
+
+ drm->dev_private = mxsfb;
+ mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mxsfb->base = devm_ioremap_resource(drm->dev, res);
+ if (IS_ERR(mxsfb->base))
+ return PTR_ERR(mxsfb->base);
+
+ mxsfb->clk = devm_clk_get(drm->dev, NULL);
+ if (IS_ERR(mxsfb->clk))
+ return PTR_ERR(mxsfb->clk);
+
+ mxsfb->clk_axi = devm_clk_get(drm->dev, "axi");
+ if (IS_ERR(mxsfb->clk_axi))
+ mxsfb->clk_axi = NULL;
+
+ mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
+ if (IS_ERR(mxsfb->clk_disp_axi))
+ mxsfb->clk_disp_axi = NULL;
+
+ ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(drm->dev);
+
+ ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+ if (ret < 0) {
+ dev_err(drm->dev, "Failed to initialise vblank\n");
+ goto err_vblank;
+ }
+
+ /* Modeset init */
+ drm_mode_config_init(drm);
+
+ ret = mxsfb_create_output(drm);
+ if (ret < 0) {
+ dev_err(drm->dev, "Failed to create outputs\n");
+ goto err_vblank;
+ }
+
+ ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
+ mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+ &mxsfb->connector);
+ if (ret < 0) {
+ dev_err(drm->dev, "Cannot setup simple display pipe\n");
+ goto err_vblank;
+ }
+
+ ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
+ if (ret) {
+ dev_err(drm->dev, "Cannot connect panel\n");
+ goto err_vblank;
+ }
+
+ drm->mode_config.min_width = MXSFB_MIN_XRES;
+ drm->mode_config.min_height = MXSFB_MIN_YRES;
+ drm->mode_config.max_width = MXSFB_MAX_XRES;
+ drm->mode_config.max_height = MXSFB_MAX_YRES;
+ drm->mode_config.funcs = &mxsfb_mode_config_funcs;
+
+ drm_mode_config_reset(drm);
+
+ pm_runtime_get_sync(drm->dev);
+ ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+ pm_runtime_put_sync(drm->dev);
+
+ if (ret < 0) {
+ dev_err(drm->dev, "Failed to install IRQ handler\n");
+ goto err_irq;
+ }
+
+ drm_kms_helper_poll_init(drm);
+
+ mxsfb->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
+ drm->mode_config.num_connector);
+ if (IS_ERR(mxsfb->fbdev)) {
+ mxsfb->fbdev = NULL;
+ dev_err(drm->dev, "Failed to init FB CMA area\n");
+ goto err_cma;
+ }
+
+ platform_set_drvdata(pdev, drm);
+
+ drm_helper_hpd_irq_event(drm);
+
+ return 0;
+
+err_cma:
+ drm_irq_uninstall(drm);
+err_irq:
+ drm_panel_detach(mxsfb->panel);
+err_vblank:
+ pm_runtime_disable(drm->dev);
+
+ return ret;
+}
+
+static void mxsfb_unload(struct drm_device *drm)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+ if (mxsfb->fbdev)
+ drm_fbdev_cma_fini(mxsfb->fbdev);
+
+ drm_kms_helper_poll_fini(drm);
+ drm_mode_config_cleanup(drm);
+ drm_vblank_cleanup(drm);
+
+ pm_runtime_get_sync(drm->dev);
+ drm_irq_uninstall(drm);
+ pm_runtime_put_sync(drm->dev);
+
+ drm->dev_private = NULL;
+
+ pm_runtime_disable(drm->dev);
+}
+
+static void mxsfb_lastclose(struct drm_device *drm)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+ drm_fbdev_cma_restore_mode(mxsfb->fbdev);
+}
+
+static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+ /* Clear and enable VBLANK IRQ */
+ mxsfb_enable_axi_clk(mxsfb);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
+ mxsfb_disable_axi_clk(mxsfb);
+
+ return 0;
+}
+
+static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+ /* Disable and clear VBLANK IRQ */
+ mxsfb_enable_axi_clk(mxsfb);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+ mxsfb_disable_axi_clk(mxsfb);
+}
+
+static void mxsfb_irq_preinstall(struct drm_device *drm)
+{
+ mxsfb_disable_vblank(drm, 0);
+}
+
+static irqreturn_t mxsfb_irq_handler(int irq, void *data)
+{
+ struct drm_device *drm = data;
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+ u32 reg;
+
+ mxsfb_enable_axi_clk(mxsfb);
+
+ reg = readl(mxsfb->base + LCDC_CTRL1);
+
+ if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
+ drm_crtc_handle_vblank(&mxsfb->pipe.crtc);
+
+ writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+
+ mxsfb_disable_axi_clk(mxsfb);
+
+ return IRQ_HANDLED;
+}
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = noop_llseek,
+ .mmap = drm_gem_cma_mmap,
+};
+
+static struct drm_driver mxsfb_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET |
+ DRIVER_PRIME | DRIVER_ATOMIC |
+ DRIVER_HAVE_IRQ,
+ .lastclose = mxsfb_lastclose,
+ .irq_handler = mxsfb_irq_handler,
+ .irq_preinstall = mxsfb_irq_preinstall,
+ .irq_uninstall = mxsfb_irq_preinstall,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+ .enable_vblank = mxsfb_enable_vblank,
+ .disable_vblank = mxsfb_disable_vblank,
+ .gem_free_object = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .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_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,
+ .fops = &fops,
+ .name = "mxsfb-drm",
+ .desc = "MXSFB Controller DRM",
+ .date = "20160824",
+ .major = 1,
+ .minor = 0,
+};
+
+static const struct platform_device_id mxsfb_devtype[] = {
+ { .name = "imx23-fb", .driver_data = MXSFB_V3, },
+ { .name = "imx28-fb", .driver_data = MXSFB_V4, },
+ { .name = "imx6sx-fb", .driver_data = MXSFB_V4, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static const struct of_device_id mxsfb_dt_ids[] = {
+ { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
+ { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+ { .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+
+static int mxsfb_probe(struct platform_device *pdev)
+{
+ struct drm_device *drm;
+ const struct of_device_id *of_id =
+ of_match_device(mxsfb_dt_ids, &pdev->dev);
+ int ret;
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ if (of_id)
+ pdev->id_entry = of_id->data;
+
+ drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
+ if (!drm)
+ return -ENOMEM;
+
+ ret = mxsfb_load(drm, 0);
+ if (ret)
+ goto err_free;
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto err_unload;
+
+ return 0;
+
+err_unload:
+ mxsfb_unload(drm);
+err_free:
+ drm_dev_unref(drm);
+
+ return ret;
+}
+
+static int mxsfb_remove(struct platform_device *pdev)
+{
+ struct drm_device *drm = platform_get_drvdata(pdev);
+
+ drm_dev_unregister(drm);
+ mxsfb_unload(drm);
+ drm_dev_unref(drm);
+
+ return 0;
+}
+
+static struct platform_driver mxsfb_platform_driver = {
+ .probe = mxsfb_probe,
+ .remove = mxsfb_remove,
+ .id_table = mxsfb_devtype,
+ .driver = {
+ .name = "mxsfb",
+ .of_match_table = mxsfb_dt_ids,
+ },
+};
+
+module_platform_driver(mxsfb_platform_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Freescale MXS DRM/KMS driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
new file mode 100644
index 000000000000..5d0883fc805b
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller 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.
+ */
+
+#ifndef __MXSFB_DRV_H__
+#define __MXSFB_DRV_H__
+
+struct mxsfb_devdata {
+ unsigned int transfer_count;
+ unsigned int cur_buf;
+ unsigned int next_buf;
+ unsigned int debug0;
+ unsigned int hs_wdth_mask;
+ unsigned int hs_wdth_shift;
+ unsigned int ipversion;
+};
+
+struct mxsfb_drm_private {
+ const struct mxsfb_devdata *devdata;
+
+ void __iomem *base; /* registers */
+ struct clk *clk;
+ struct clk *clk_axi;
+ struct clk *clk_disp_axi;
+
+ struct drm_simple_display_pipe pipe;
+ struct drm_connector connector;
+ struct drm_panel *panel;
+ struct drm_fbdev_cma *fbdev;
+};
+
+int mxsfb_setup_crtc(struct drm_device *dev);
+int mxsfb_create_output(struct drm_device *dev);
+
+void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
+void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
+
+void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
+void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
+void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
+ struct drm_plane_state *state);
+
+#endif /* __MXSFB_DRV_H__ */
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
new file mode 100644
index 000000000000..fa8d17399407
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_graph.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drmP.h>
+
+#include "mxsfb_drv.h"
+
+static struct mxsfb_drm_private *
+drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
+{
+ return container_of(connector, struct mxsfb_drm_private, connector);
+}
+
+static int mxsfb_panel_get_modes(struct drm_connector *connector)
+{
+ struct mxsfb_drm_private *mxsfb =
+ drm_connector_to_mxsfb_drm_private(connector);
+
+ if (mxsfb->panel)
+ return mxsfb->panel->funcs->get_modes(mxsfb->panel);
+
+ return 0;
+}
+
+static const struct
+drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
+ .get_modes = mxsfb_panel_get_modes,
+};
+
+static enum drm_connector_status
+mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct mxsfb_drm_private *mxsfb =
+ drm_connector_to_mxsfb_drm_private(connector);
+
+ if (mxsfb->panel)
+ return connector_status_connected;
+
+ return connector_status_disconnected;
+}
+
+static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
+{
+ struct mxsfb_drm_private *mxsfb =
+ drm_connector_to_mxsfb_drm_private(connector);
+
+ if (mxsfb->panel)
+ drm_panel_detach(mxsfb->panel);
+
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = mxsfb_panel_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = mxsfb_panel_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 int mxsfb_attach_endpoint(struct drm_device *drm,
+ const struct of_endpoint *ep)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+ struct device_node *np;
+ struct drm_panel *panel;
+ int ret = -EPROBE_DEFER;
+
+ np = of_graph_get_remote_port_parent(ep->local_node);
+ panel = of_drm_find_panel(np);
+ of_node_put(np);
+
+ if (!panel)
+ return -EPROBE_DEFER;
+
+ mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
+ mxsfb->connector.polled = 0;
+ drm_connector_helper_add(&mxsfb->connector,
+ &mxsfb_panel_connector_helper_funcs);
+ ret = drm_connector_init(drm, &mxsfb->connector,
+ &mxsfb_panel_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown);
+ if (!ret)
+ mxsfb->panel = panel;
+
+ return ret;
+}
+
+int mxsfb_create_output(struct drm_device *drm)
+{
+ struct device_node *ep_np = NULL;
+ struct of_endpoint ep;
+ int ret;
+
+ for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
+ ret = of_graph_parse_endpoint(ep_np, &ep);
+ if (!ret)
+ ret = mxsfb_attach_endpoint(drm, &ep);
+
+ if (ret) {
+ of_node_put(ep_np);
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
new file mode 100644
index 000000000000..31d62cd0d3d7
--- /dev/null
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller 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.
+ */
+
+#ifndef __MXSFB_REGS_H__
+#define __MXSFB_REGS_H__
+
+#define REG_SET 4
+#define REG_CLR 8
+
+#define LCDC_CTRL 0x00
+#define LCDC_CTRL1 0x10
+#define LCDC_V3_TRANSFER_COUNT 0x20
+#define LCDC_V4_TRANSFER_COUNT 0x30
+#define LCDC_V4_CUR_BUF 0x40
+#define LCDC_V4_NEXT_BUF 0x50
+#define LCDC_V3_CUR_BUF 0x30
+#define LCDC_V3_NEXT_BUF 0x40
+#define LCDC_VDCTRL0 0x70
+#define LCDC_VDCTRL1 0x80
+#define LCDC_VDCTRL2 0x90
+#define LCDC_VDCTRL3 0xa0
+#define LCDC_VDCTRL4 0xb0
+#define LCDC_V4_DEBUG0 0x1d0
+#define LCDC_V3_DEBUG0 0x1f0
+
+#define CTRL_SFTRST (1 << 31)
+#define CTRL_CLKGATE (1 << 30)
+#define CTRL_BYPASS_COUNT (1 << 19)
+#define CTRL_VSYNC_MODE (1 << 18)
+#define CTRL_DOTCLK_MODE (1 << 17)
+#define CTRL_DATA_SELECT (1 << 16)
+#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
+#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
+#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
+#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
+#define CTRL_MASTER (1 << 5)
+#define CTRL_DF16 (1 << 3)
+#define CTRL_DF18 (1 << 2)
+#define CTRL_DF24 (1 << 1)
+#define CTRL_RUN (1 << 0)
+
+#define CTRL1_FIFO_CLEAR (1 << 21)
+#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
+#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
+#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
+#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
+
+#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
+#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
+#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
+#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
+
+#define VDCTRL0_ENABLE_PRESENT (1 << 28)
+#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
+#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
+#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
+#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
+#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
+#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
+#define VDCTRL0_HALF_LINE (1 << 19)
+#define VDCTRL0_HALF_LINE_MODE (1 << 18)
+#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+
+#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
+#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
+
+#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
+#define VDCTRL3_VSYNC_ONLY (1 << 28)
+#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
+#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
+#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
+#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
+
+#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
+#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
+#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
+#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
+
+#define DEBUG0_HSYNC (1 < 26)
+#define DEBUG0_VSYNC (1 < 25)
+
+#define MXSFB_MIN_XRES 120
+#define MXSFB_MIN_YRES 120
+#define MXSFB_MAX_XRES 0xffff
+#define MXSFB_MAX_YRES 0xffff
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define TRANSP 3
+
+#define STMLCDIF_8BIT 1 /* pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
+
+#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6)
+#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negative edge sampling */
+
+#endif /* __MXSFB_REGS_H__ */
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild
index 2527bf4ca5d9..fde6e3656636 100644
--- a/drivers/gpu/drm/nouveau/Kbuild
+++ b/drivers/gpu/drm/nouveau/Kbuild
@@ -22,6 +22,7 @@ nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o
nouveau-y += nouveau_drm.o
nouveau-y += nouveau_hwmon.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+nouveau-$(CONFIG_LEDS_CLASS) += nouveau_led.o
nouveau-y += nouveau_nvif.o
nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o
nouveau-y += nouveau_usif.o # userspace <-> nvif
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 0cb7a18cde26..59d1d1c5de5f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -702,7 +702,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc)
if (nv_two_heads(dev))
NVSetOwner(dev, nv_crtc->index);
- drm_vblank_pre_modeset(dev, nv_crtc->index);
+ drm_crtc_vblank_off(crtc);
funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
NVBlankScreen(dev, nv_crtc->index, true);
@@ -734,7 +734,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
#endif
funcs->dpms(crtc, DRM_MODE_DPMS_ON);
- drm_vblank_post_modeset(dev, nv_crtc->index);
+ drm_crtc_vblank_on(crtc);
}
static void nv_crtc_destroy(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index ec444eac6258..a79514d440b3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -33,7 +33,7 @@
#include "nouveau_connector.h"
#include "nouveau_display.h"
#include "nvreg.h"
-
+#include "disp.h"
struct nouveau_plane {
struct drm_plane base;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
index d15c296b5f33..ae49dfd1f97b 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -34,6 +34,8 @@ struct nv50_disp_mthd_v1 {
#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26
#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
__u8 method;
__u16 hasht;
@@ -90,6 +92,21 @@ struct nv50_disp_sor_dp_pwr_v0 {
__u8 pad02[6];
};
+struct nv50_disp_sor_dp_mst_link_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_sor_dp_mst_vcpi_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u8 start_slot;
+ __u8 num_slots;
+ __u16 pbn;
+ __u16 aligned_pbn;
+};
+
struct nv50_disp_pior_pwr_v0 {
__u8 version;
__u8 state;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index e6e9537537cf..82235f30277c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -52,7 +52,7 @@
#define GM107_DISP /* cl5070.h */ 0x00009470
#define GM200_DISP /* cl5070.h */ 0x00009570
#define GP100_DISP /* cl5070.h */ 0x00009770
-#define GP104_DISP /* cl5070.h */ 0x00009870
+#define GP102_DISP /* cl5070.h */ 0x00009870
#define NV31_MPEG 0x00003174
#define G82_MPEG 0x00008274
@@ -90,7 +90,7 @@
#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d
#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d
#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d
-#define GP104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d
+#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d
#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e
#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e
diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h
index 8d815967767f..9e58b305b020 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/object.h
@@ -66,6 +66,35 @@ void nvif_object_unmap(struct nvif_object *);
#define nvif_mthd(a,b,c,d) nvif_object_mthd((a), (b), (c), (d))
+struct nvif_mclass {
+ s32 oclass;
+ int version;
+};
+
+#define nvif_mclass(o,m) ({ \
+ struct nvif_object *object = (o); \
+ struct nvif_sclass *sclass; \
+ const typeof(m[0]) *mclass = (m); \
+ int ret = -ENODEV; \
+ int cnt, i, j; \
+ \
+ cnt = nvif_object_sclass_get(object, &sclass); \
+ if (cnt >= 0) { \
+ for (i = 0; ret < 0 && mclass[i].oclass; i++) { \
+ for (j = 0; j < cnt; j++) { \
+ if (mclass[i].oclass == sclass[j].oclass && \
+ mclass[i].version >= sclass[j].minver && \
+ mclass[i].version <= sclass[j].maxver) { \
+ ret = i; \
+ break; \
+ } \
+ } \
+ } \
+ nvif_object_sclass_put(&sclass); \
+ } \
+ ret; \
+})
+
/*XXX*/
#include <core/object.h>
#define nvxx_object(a) ({ \
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
index d3d26a1e215d..b93f4c1a95e5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
@@ -8,5 +8,5 @@ int gk104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gm107_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
-int gp104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
+int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
index e82049667ce4..970ae753968a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
@@ -33,5 +33,5 @@ int gk110_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gm107_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
-int gp104_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
+int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
index 934b0ae5521d..2ff64a20c0ec 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
@@ -1,6 +1,6 @@
#ifndef __NVBIOS_BOOST_H__
#define __NVBIOS_BOOST_H__
-u16 nvbios_boostTe(struct nvkm_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
+u32 nvbios_boostTe(struct nvkm_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
struct nvbios_boostE {
u8 pstate;
@@ -8,10 +8,10 @@ struct nvbios_boostE {
u32 max;
};
-u16 nvbios_boostEe(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *);
-u16 nvbios_boostEp(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *,
+u32 nvbios_boostEe(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *);
+u32 nvbios_boostEp(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *,
struct nvbios_boostE *);
-u16 nvbios_boostEm(struct nvkm_bios *, u8, u8 *, u8 *, u8 *, u8 *,
+u32 nvbios_boostEm(struct nvkm_bios *, u8, u8 *, u8 *, u8 *, u8 *,
struct nvbios_boostE *);
struct nvbios_boostS {
@@ -21,7 +21,7 @@ struct nvbios_boostS {
u32 max;
};
-u16 nvbios_boostSe(struct nvkm_bios *, int, u16, u8 *, u8 *, u8, u8);
-u16 nvbios_boostSp(struct nvkm_bios *, int, u16, u8 *, u8 *, u8, u8,
+u32 nvbios_boostSe(struct nvkm_bios *, int, u32, u8 *, u8 *, u8, u8);
+u32 nvbios_boostSp(struct nvkm_bios *, int, u32, u8 *, u8 *, u8, u8,
struct nvbios_boostS *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
index 2f0e0c8e83be..76fe7d50a1ce 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
@@ -1,6 +1,6 @@
#ifndef __NVBIOS_CSTEP_H__
#define __NVBIOS_CSTEP_H__
-u16 nvbios_cstepTe(struct nvkm_bios *,
+u32 nvbios_cstepTe(struct nvkm_bios *,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz);
struct nvbios_cstepE {
@@ -8,10 +8,10 @@ struct nvbios_cstepE {
u8 index;
};
-u16 nvbios_cstepEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
-u16 nvbios_cstepEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
+u32 nvbios_cstepEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_cstepEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
struct nvbios_cstepE *);
-u16 nvbios_cstepEm(struct nvkm_bios *, u8 pstate, u8 *ver, u8 *hdr,
+u32 nvbios_cstepEm(struct nvkm_bios *, u8 pstate, u8 *ver, u8 *hdr,
struct nvbios_cstepE *);
struct nvbios_cstepX {
@@ -20,7 +20,7 @@ struct nvbios_cstepX {
u8 voltage;
};
-u16 nvbios_cstepXe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
-u16 nvbios_cstepXp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
+u32 nvbios_cstepXe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_cstepXp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
struct nvbios_cstepX *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
index 693ea7d9ec43..a7513e8406a3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
@@ -2,5 +2,5 @@
#define __NVBIOS_FAN_H__
#include <subdev/bios/therm.h>
-u16 nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan);
+u32 nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan);
#endif
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 a47d46dda704..b7a54e605469 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
@@ -6,6 +6,7 @@ enum dcb_gpio_func_name {
DCB_GPIO_TVDAC1 = 0x2d,
DCB_GPIO_FAN = 0x09,
DCB_GPIO_FAN_SENSE = 0x3d,
+ DCB_GPIO_LOGO_LED_PWM = 0x84,
DCB_GPIO_UNUSED = 0xff,
DCB_GPIO_VID0 = 0x04,
DCB_GPIO_VID1 = 0x05,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
index 9cb97477248b..e933d3eede70 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
@@ -1,10 +1,16 @@
#ifndef __NVBIOS_ICCSENSE_H__
#define __NVBIOS_ICCSENSE_H__
+struct pwr_rail_resistor_t {
+ u8 mohm;
+ bool enabled;
+};
+
struct pwr_rail_t {
u8 mode;
u8 extdev_id;
- u8 resistor_mohm;
- u8 rail;
+ u8 resistor_count;
+ struct pwr_rail_resistor_t resistors[3];
+ u16 config;
};
struct nvbios_iccsense {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
index d3bd250103d5..478b1c0d2089 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
@@ -1,6 +1,6 @@
#ifndef __NVBIOS_PERF_H__
#define __NVBIOS_PERF_H__
-u16 nvbios_perf_table(struct nvkm_bios *, u8 *ver, u8 *hdr,
+u32 nvbios_perf_table(struct nvkm_bios *, u8 *ver, u8 *hdr,
u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
struct nvbios_perfE {
@@ -17,9 +17,9 @@ struct nvbios_perfE {
u8 pcie_width;
};
-u16 nvbios_perf_entry(struct nvkm_bios *, int idx,
+u32 nvbios_perf_entry(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_perfEp(struct nvkm_bios *, int idx,
+u32 nvbios_perfEp(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *);
struct nvbios_perfS {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
index 339a826aa176..38188d4c9ab5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
@@ -2,10 +2,10 @@
#define __NVBIOS_TIMING_H__
#include <subdev/bios/ramcfg.h>
-u16 nvbios_timingTe(struct nvkm_bios *,
+u32 nvbios_timingTe(struct nvkm_bios *,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
-u16 nvbios_timingEe(struct nvkm_bios *, int idx,
+u32 nvbios_timingEe(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_timingEp(struct nvkm_bios *, int idx,
+u32 nvbios_timingEp(struct nvkm_bios *, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
index 6633c6db9281..bea31cdd1dd1 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
@@ -1,21 +1,24 @@
#ifndef __NVBIOS_VMAP_H__
#define __NVBIOS_VMAP_H__
struct nvbios_vmap {
+ u8 max0;
+ u8 max1;
+ u8 max2;
};
-u16 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_vmap_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+u32 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_vmap_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_vmap *);
struct nvbios_vmap_entry {
- u8 unk0;
+ u8 mode;
u8 link;
u32 min;
u32 max;
s32 arg[6];
};
-u16 nvbios_vmap_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
-u16 nvbios_vmap_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
+u32 nvbios_vmap_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
+u32 nvbios_vmap_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
struct nvbios_vmap_entry *);
#endif
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 b0df610cec2b..f0baa2c7de09 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
@@ -13,16 +13,17 @@ struct nvbios_volt {
u32 base;
/* GPIO mode */
- u8 vidmask;
- s16 step;
+ bool ranged;
+ 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);
-u16 nvbios_volt_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+u32 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_volt_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_volt *);
struct nvbios_volt_entry {
@@ -30,7 +31,7 @@ struct nvbios_volt_entry {
u8 vid;
};
-u16 nvbios_volt_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
-u16 nvbios_volt_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
+u32 nvbios_volt_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
+u32 nvbios_volt_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
struct nvbios_volt_entry *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
new file mode 100644
index 000000000000..87f804fc3a88
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
@@ -0,0 +1,24 @@
+#ifndef __NVBIOS_VPSTATE_H__
+#define __NVBIOS_VPSTATE_H__
+struct nvbios_vpstate_header {
+ u32 offset;
+
+ u8 version;
+ u8 hlen;
+ u8 ecount;
+ u8 elen;
+ u8 scount;
+ u8 slen;
+
+ u8 base_id;
+ u8 boost_id;
+ u8 tdp_id;
+};
+struct nvbios_vpstate_entry {
+ u8 pstate;
+ u16 clock_mhz;
+};
+int nvbios_vpstate_parse(struct nvkm_bios *, struct nvbios_vpstate_header *);
+int nvbios_vpstate_entry(struct nvkm_bios *, struct nvbios_vpstate_header *,
+ u8 idx, struct nvbios_vpstate_entry *);
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
index fb54417bc458..e5275f742977 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
@@ -6,6 +6,10 @@
struct nvbios_pll;
struct nvkm_pll_vals;
+#define NVKM_CLK_CSTATE_DEFAULT -1 /* POSTed default */
+#define NVKM_CLK_CSTATE_BASE -2 /* pstate base */
+#define NVKM_CLK_CSTATE_HIGHEST -3 /* highest possible */
+
enum nv_clk_src {
nv_clk_src_crystal,
nv_clk_src_href,
@@ -52,6 +56,7 @@ struct nvkm_cstate {
struct list_head head;
u8 voltage;
u32 domain[nv_clk_src_max];
+ u8 id;
};
struct nvkm_pstate {
@@ -67,7 +72,8 @@ struct nvkm_pstate {
struct nvkm_domain {
enum nv_clk_src name;
u8 bios; /* 0xff for none */
-#define NVKM_CLK_DOM_FLAG_CORE 0x01
+#define NVKM_CLK_DOM_FLAG_CORE 0x01
+#define NVKM_CLK_DOM_FLAG_VPSTATE 0x02
u8 flags;
const char *mname;
int mdiv;
@@ -93,10 +99,16 @@ struct nvkm_clk {
int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
int astate; /* perfmon adjustment (base) */
- int tstate; /* thermal adjustment (max-) */
int dstate; /* display adjustment (min+) */
+ u8 temp;
bool allow_reclock;
+#define NVKM_CLK_BOOST_NONE 0x0
+#define NVKM_CLK_BOOST_BIOS 0x1
+#define NVKM_CLK_BOOST_FULL 0x2
+ u8 boost_mode;
+ u32 base_khz;
+ u32 boost_khz;
/*XXX: die, these are here *only* to support the completely
* bat-shit insane what-was-nouveau_hw.c code
@@ -110,7 +122,7 @@ int nvkm_clk_read(struct nvkm_clk *, enum nv_clk_src);
int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr);
int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait);
int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel);
-int nvkm_clk_tstate(struct nvkm_clk *, int req, int rel);
+int nvkm_clk_tstate(struct nvkm_clk *, u8 temperature);
int nv04_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
int nv40_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
index 3a410275fa71..794e432578b2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
@@ -93,8 +93,9 @@ int gk104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int gm20b_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
-int gp104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int gp102_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
#include <subdev/bios.h>
#include <subdev/bios/ramcfg.h>
@@ -156,4 +157,6 @@ struct nvkm_ram_func {
int (*prog)(struct nvkm_ram *);
void (*tidy)(struct nvkm_ram *);
};
+
+extern const u8 gf100_pte_storage_type_map[256];
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
index e61923d5e49c..f37538eb1fe5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
@@ -35,6 +35,8 @@ int gk110_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
+int gp100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
+int gp102_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
/* interface to MEMX process running on PMU */
struct nvkm_memx;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
index b765f4ffcde6..08ef9983c643 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
@@ -15,12 +15,28 @@ struct nvkm_volt {
u32 max_uv;
u32 min_uv;
+
+ /*
+ * These are fully functional map entries creating a sw ceiling for
+ * the voltage. These all can describe different kind of curves, so
+ * that for any given temperature a different one can return the lowest
+ * value of all three.
+ */
+ u8 max0_id;
+ u8 max1_id;
+ u8 max2_id;
+
+ int speedo;
};
+int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temperature);
+int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id);
int nvkm_volt_get(struct nvkm_volt *);
-int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition);
+int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp,
+ int condition);
int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+int gf100_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 **);
int gm20b_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index f5101be806cb..8b1ca4add2ed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -30,12 +30,37 @@
* Register locations derived from NVClock by Roderick Colenbrander
*/
+#include <linux/apple-gmux.h>
#include <linux/backlight.h>
+#include <linux/idr.h>
#include "nouveau_drv.h"
#include "nouveau_reg.h"
#include "nouveau_encoder.h"
+static struct ida bl_ida;
+#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
+
+struct backlight_connector {
+ struct list_head head;
+ int id;
+};
+
+static bool
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
+ *connector)
+{
+ const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
+ if (nb < 0 || nb >= 100)
+ return false;
+ if (nb > 0)
+ snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
+ else
+ snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
+ connector->id = nb;
+ return true;
+}
+
static int
nv40_get_intensity(struct backlight_device *bd)
{
@@ -74,6 +99,8 @@ nv40_backlight_init(struct drm_connector *connector)
struct nvif_object *device = &drm->device.object;
struct backlight_properties props;
struct backlight_device *bd;
+ struct backlight_connector bl_connector;
+ char backlight_name[BL_NAME_SIZE];
if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
return 0;
@@ -81,10 +108,19 @@ nv40_backlight_init(struct drm_connector *connector)
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.max_brightness = 31;
- bd = backlight_device_register("nv_backlight", connector->kdev, drm,
+ if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+ NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+ return 0;
+ }
+ bd = backlight_device_register(backlight_name , connector->kdev, drm,
&nv40_bl_ops, &props);
- if (IS_ERR(bd))
+
+ if (IS_ERR(bd)) {
+ if (bl_connector.id > 0)
+ ida_simple_remove(&bl_ida, bl_connector.id);
return PTR_ERR(bd);
+ }
+ list_add(&bl_connector.head, &drm->bl_connectors);
drm->backlight = bd;
bd->props.brightness = nv40_get_intensity(bd);
backlight_update_status(bd);
@@ -182,6 +218,8 @@ nv50_backlight_init(struct drm_connector *connector)
struct backlight_properties props;
struct backlight_device *bd;
const struct backlight_ops *ops;
+ struct backlight_connector bl_connector;
+ char backlight_name[BL_NAME_SIZE];
nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
if (!nv_encoder) {
@@ -203,11 +241,20 @@ nv50_backlight_init(struct drm_connector *connector)
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.max_brightness = 100;
- bd = backlight_device_register("nv_backlight", connector->kdev,
+ if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+ NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+ return 0;
+ }
+ bd = backlight_device_register(backlight_name , connector->kdev,
nv_encoder, ops, &props);
- if (IS_ERR(bd))
+
+ if (IS_ERR(bd)) {
+ if (bl_connector.id > 0)
+ ida_simple_remove(&bl_ida, bl_connector.id);
return PTR_ERR(bd);
+ }
+ list_add(&bl_connector.head, &drm->bl_connectors);
drm->backlight = bd;
bd->props.brightness = bd->ops->get_brightness(bd);
backlight_update_status(bd);
@@ -221,6 +268,13 @@ nouveau_backlight_init(struct drm_device *dev)
struct nvif_device *device = &drm->device;
struct drm_connector *connector;
+ if (apple_gmux_present()) {
+ NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+ return 0;
+ }
+
+ INIT_LIST_HEAD(&drm->bl_connectors);
+
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
connector->connector_type != DRM_MODE_CONNECTOR_eDP)
@@ -232,6 +286,7 @@ nouveau_backlight_init(struct drm_device *dev)
case NV_DEVICE_INFO_V0_TESLA:
case NV_DEVICE_INFO_V0_FERMI:
case NV_DEVICE_INFO_V0_KEPLER:
+ case NV_DEVICE_INFO_V0_MAXWELL:
return nv50_backlight_init(connector);
default:
break;
@@ -246,9 +301,27 @@ void
nouveau_backlight_exit(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
+ struct backlight_connector *connector;
+
+ list_for_each_entry(connector, &drm->bl_connectors, head) {
+ if (connector->id >= 0)
+ ida_simple_remove(&bl_ida, connector->id);
+ }
if (drm->backlight) {
backlight_device_unregister(drm->backlight);
drm->backlight = NULL;
}
}
+
+void
+nouveau_backlight_ctor(void)
+{
+ ida_init(&bl_ida);
+}
+
+void
+nouveau_backlight_dtor(void)
+{
+ ida_destroy(&bl_ida);
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index a1570b109434..23ffe8571a99 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -333,6 +333,9 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios)
if (bios->major_version < 5 && bios->data[0x48] & 0x4)
return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
+ return nvif_rd32(device, 0x001800) & 0x0000000f;
+ else
if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
else
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 0067586eb015..18eb061ccafb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -31,10 +31,8 @@
#define DCB_LOC_ON_CHIP 0
-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
-#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); })
-#define ROM64(x) le64_to_cpu(*(u64 *)&(x))
+#define ROM16(x) get_unaligned_le16(&(x))
+#define ROM32(x) get_unaligned_le32(&(x))
#define ROMPTR(d,x) ({ \
struct nouveau_drm *drm = nouveau_drm((d)); \
ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 343b8659472c..dd07ca140d12 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -83,13 +83,13 @@ nv10_bo_get_tile_region(struct drm_device *dev, int i)
static void
nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
- struct fence *fence)
+ struct dma_fence *fence)
{
struct nouveau_drm *drm = nouveau_drm(dev);
if (tile) {
spin_lock(&drm->tile.lock);
- tile->fence = (struct nouveau_fence *)fence_get(fence);
+ tile->fence = (struct nouveau_fence *)dma_fence_get(fence);
tile->used = false;
spin_unlock(&drm->tile.lock);
}
@@ -1209,6 +1209,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
nvbo->page_shift != vma->vm->mmu->lpg_shift)) {
nvkm_vm_map(vma, new_mem->mm_node);
} else {
+ WARN_ON(ttm_bo_wait(bo, false, false));
nvkm_vm_unmap(vma);
}
}
@@ -1243,7 +1244,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
{
struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
struct drm_device *dev = drm->dev;
- struct fence *fence = reservation_object_get_excl(bo->resv);
+ struct dma_fence *fence = reservation_object_get_excl(bo->resv);
nv10_bo_put_tile_region(dev, *old_tile, fence);
*old_tile = new_tile;
@@ -1561,6 +1562,7 @@ struct ttm_bo_driver nouveau_bo_driver = {
.ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
.invalidate_caches = nouveau_bo_invalidate_caches,
.init_mem_type = nouveau_bo_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = nouveau_bo_evict_flags,
.move_notify = nouveau_bo_move_ntfy,
.move = nouveau_bo_move,
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index c1084088f9e4..947c200655b4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -30,6 +30,7 @@
#include <linux/vga_switcheroo.h>
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_crtc_helper.h>
@@ -47,6 +48,301 @@
#include <nvif/cl0046.h>
#include <nvif/event.h>
+struct drm_display_mode *
+nouveau_conn_native_mode(struct drm_connector *connector)
+{
+ const struct drm_connector_helper_funcs *helper = connector->helper_private;
+ struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode, *largest = NULL;
+ int high_w = 0, high_h = 0, high_v = 0;
+
+ list_for_each_entry(mode, &connector->probed_modes, head) {
+ mode->vrefresh = drm_mode_vrefresh(mode);
+ if (helper->mode_valid(connector, mode) != MODE_OK ||
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))
+ continue;
+
+ /* Use preferred mode if there is one.. */
+ if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+ NV_DEBUG(drm, "native mode from preferred\n");
+ return drm_mode_duplicate(dev, mode);
+ }
+
+ /* Otherwise, take the resolution with the largest width, then
+ * height, then vertical refresh
+ */
+ if (mode->hdisplay < high_w)
+ continue;
+
+ if (mode->hdisplay == high_w && mode->vdisplay < high_h)
+ continue;
+
+ if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
+ mode->vrefresh < high_v)
+ continue;
+
+ high_w = mode->hdisplay;
+ high_h = mode->vdisplay;
+ high_v = mode->vrefresh;
+ largest = mode;
+ }
+
+ NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
+ high_w, high_h, high_v);
+ return largest ? drm_mode_duplicate(dev, largest) : NULL;
+}
+
+int
+nouveau_conn_atomic_get_property(struct drm_connector *connector,
+ const struct drm_connector_state *state,
+ struct drm_property *property, u64 *val)
+{
+ struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+ struct nouveau_display *disp = nouveau_display(connector->dev);
+ struct drm_device *dev = connector->dev;
+
+ if (property == dev->mode_config.scaling_mode_property)
+ *val = asyc->scaler.mode;
+ else if (property == disp->underscan_property)
+ *val = asyc->scaler.underscan.mode;
+ else if (property == disp->underscan_hborder_property)
+ *val = asyc->scaler.underscan.hborder;
+ else if (property == disp->underscan_vborder_property)
+ *val = asyc->scaler.underscan.vborder;
+ else if (property == disp->dithering_mode)
+ *val = asyc->dither.mode;
+ else if (property == disp->dithering_depth)
+ *val = asyc->dither.depth;
+ else if (property == disp->vibrant_hue_property)
+ *val = asyc->procamp.vibrant_hue;
+ else if (property == disp->color_vibrance_property)
+ *val = asyc->procamp.color_vibrance;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+nouveau_conn_atomic_set_property(struct drm_connector *connector,
+ struct drm_connector_state *state,
+ struct drm_property *property, u64 val)
+{
+ struct drm_device *dev = connector->dev;
+ struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+ struct nouveau_display *disp = nouveau_display(dev);
+
+ if (property == dev->mode_config.scaling_mode_property) {
+ switch (val) {
+ case DRM_MODE_SCALE_NONE:
+ /* We allow 'None' for EDID modes, even on a fixed
+ * panel (some exist with support for lower refresh
+ * rates, which people might want to use for power-
+ * saving purposes).
+ *
+ * Non-EDID modes will force the use of GPU scaling
+ * to the native mode regardless of this setting.
+ */
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_LVDS:
+ case DRM_MODE_CONNECTOR_eDP:
+ /* ... except prior to G80, where the code
+ * doesn't support such things.
+ */
+ if (disp->disp.oclass < NV50_DISP)
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+ case DRM_MODE_SCALE_FULLSCREEN:
+ case DRM_MODE_SCALE_CENTER:
+ case DRM_MODE_SCALE_ASPECT:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (asyc->scaler.mode != val) {
+ asyc->scaler.mode = val;
+ asyc->set.scaler = true;
+ }
+ } else
+ if (property == disp->underscan_property) {
+ if (asyc->scaler.underscan.mode != val) {
+ asyc->scaler.underscan.mode = val;
+ asyc->set.scaler = true;
+ }
+ } else
+ if (property == disp->underscan_hborder_property) {
+ if (asyc->scaler.underscan.hborder != val) {
+ asyc->scaler.underscan.hborder = val;
+ asyc->set.scaler = true;
+ }
+ } else
+ if (property == disp->underscan_vborder_property) {
+ if (asyc->scaler.underscan.vborder != val) {
+ asyc->scaler.underscan.vborder = val;
+ asyc->set.scaler = true;
+ }
+ } else
+ if (property == disp->dithering_mode) {
+ if (asyc->dither.mode != val) {
+ asyc->dither.mode = val;
+ asyc->set.dither = true;
+ }
+ } else
+ if (property == disp->dithering_depth) {
+ if (asyc->dither.mode != val) {
+ asyc->dither.depth = val;
+ asyc->set.dither = true;
+ }
+ } else
+ if (property == disp->vibrant_hue_property) {
+ if (asyc->procamp.vibrant_hue != val) {
+ asyc->procamp.vibrant_hue = val;
+ asyc->set.procamp = true;
+ }
+ } else
+ if (property == disp->color_vibrance_property) {
+ if (asyc->procamp.color_vibrance != val) {
+ asyc->procamp.color_vibrance = val;
+ asyc->set.procamp = true;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void
+nouveau_conn_atomic_destroy_state(struct drm_connector *connector,
+ struct drm_connector_state *state)
+{
+ struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+ __drm_atomic_helper_connector_destroy_state(&asyc->state);
+ kfree(asyc);
+}
+
+struct drm_connector_state *
+nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
+{
+ struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
+ struct nouveau_conn_atom *asyc;
+ if (!(asyc = kmalloc(sizeof(*asyc), GFP_KERNEL)))
+ return NULL;
+ __drm_atomic_helper_connector_duplicate_state(connector, &asyc->state);
+ asyc->dither = armc->dither;
+ asyc->scaler = armc->scaler;
+ asyc->procamp = armc->procamp;
+ asyc->set.mask = 0;
+ return &asyc->state;
+}
+
+void
+nouveau_conn_reset(struct drm_connector *connector)
+{
+ struct nouveau_conn_atom *asyc;
+
+ if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
+ return;
+
+ if (connector->state)
+ __drm_atomic_helper_connector_destroy_state(connector->state);
+ __drm_atomic_helper_connector_reset(connector, &asyc->state);
+ asyc->dither.mode = DITHERING_MODE_AUTO;
+ asyc->dither.depth = DITHERING_DEPTH_AUTO;
+ asyc->scaler.mode = DRM_MODE_SCALE_NONE;
+ asyc->scaler.underscan.mode = UNDERSCAN_OFF;
+ asyc->procamp.color_vibrance = 150;
+ asyc->procamp.vibrant_hue = 90;
+
+ if (nouveau_display(connector->dev)->disp.oclass < NV50_DISP) {
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_LVDS:
+ /* See note in nouveau_conn_atomic_set_property(). */
+ asyc->scaler.mode = DRM_MODE_SCALE_FULLSCREEN;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+nouveau_conn_attach_properties(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
+ struct nouveau_display *disp = nouveau_display(dev);
+
+ /* Init DVI-I specific properties. */
+ if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
+ drm_object_attach_property(&connector->base, dev->mode_config.
+ dvi_i_subconnector_property, 0);
+
+ /* Add overscan compensation options to digital outputs. */
+ if (disp->underscan_property &&
+ (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+ connector->connector_type == DRM_MODE_CONNECTOR_DVII ||
+ connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+ connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)) {
+ drm_object_attach_property(&connector->base,
+ disp->underscan_property,
+ UNDERSCAN_OFF);
+ drm_object_attach_property(&connector->base,
+ disp->underscan_hborder_property, 0);
+ drm_object_attach_property(&connector->base,
+ disp->underscan_vborder_property, 0);
+ }
+
+ /* Add hue and saturation options. */
+ if (disp->vibrant_hue_property)
+ drm_object_attach_property(&connector->base,
+ disp->vibrant_hue_property,
+ armc->procamp.vibrant_hue);
+ if (disp->color_vibrance_property)
+ drm_object_attach_property(&connector->base,
+ disp->color_vibrance_property,
+ armc->procamp.color_vibrance);
+
+ /* Scaling mode property. */
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_TV:
+ break;
+ case DRM_MODE_CONNECTOR_VGA:
+ if (disp->disp.oclass < NV50_DISP)
+ break; /* Can only scale on DFPs. */
+ /* Fall-through. */
+ default:
+ drm_object_attach_property(&connector->base, dev->mode_config.
+ scaling_mode_property,
+ armc->scaler.mode);
+ break;
+ }
+
+ /* Dithering properties. */
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_TV:
+ case DRM_MODE_CONNECTOR_VGA:
+ break;
+ default:
+ if (disp->dithering_mode) {
+ drm_object_attach_property(&connector->base,
+ disp->dithering_mode,
+ armc->dither.mode);
+ }
+ if (disp->dithering_depth) {
+ drm_object_attach_property(&connector->base,
+ disp->dithering_depth,
+ armc->dither.depth);
+ }
+ break;
+ }
+}
+
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
int nouveau_tv_disable = 0;
module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
@@ -151,7 +447,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
int ret = nouveau_dp_detect(nv_encoder);
- if (ret == 0)
+ if (ret == NOUVEAU_DP_MST)
+ return NULL;
+ if (ret == NOUVEAU_DP_SST)
break;
} else
if ((vga_switcheroo_handler_flags() &
@@ -465,199 +763,39 @@ static int
nouveau_connector_set_property(struct drm_connector *connector,
struct drm_property *property, uint64_t value)
{
- struct nouveau_display *disp = nouveau_display(connector->dev);
+ struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
- struct drm_device *dev = connector->dev;
- struct nouveau_crtc *nv_crtc;
int ret;
- nv_crtc = NULL;
- if (connector->encoder && connector->encoder->crtc)
- nv_crtc = nouveau_crtc(connector->encoder->crtc);
-
- /* Scaling mode */
- if (property == dev->mode_config.scaling_mode_property) {
- bool modeset = false;
-
- switch (value) {
- case DRM_MODE_SCALE_NONE:
- /* We allow 'None' for EDID modes, even on a fixed
- * panel (some exist with support for lower refresh
- * rates, which people might want to use for power
- * saving purposes).
- *
- * Non-EDID modes will force the use of GPU scaling
- * to the native mode regardless of this setting.
- */
- switch (nv_connector->type) {
- case DCB_CONNECTOR_LVDS:
- case DCB_CONNECTOR_LVDS_SPWG:
- case DCB_CONNECTOR_eDP:
- /* ... except prior to G80, where the code
- * doesn't support such things.
- */
- if (disp->disp.oclass < NV50_DISP)
- return -EINVAL;
- break;
- default:
- break;
- }
- break;
- case DRM_MODE_SCALE_FULLSCREEN:
- case DRM_MODE_SCALE_CENTER:
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- return -EINVAL;
- }
-
- /* Changing between GPU and panel scaling requires a full
- * modeset
- */
- if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) ||
- (value == DRM_MODE_SCALE_NONE))
- modeset = true;
- nv_connector->scaling_mode = value;
-
- if (!nv_crtc)
- return 0;
-
- if (modeset || !nv_crtc->set_scale) {
- ret = drm_crtc_helper_set_mode(&nv_crtc->base,
- &nv_crtc->base.mode,
- nv_crtc->base.x,
- nv_crtc->base.y, NULL);
- if (!ret)
- return -EINVAL;
- } else {
- ret = nv_crtc->set_scale(nv_crtc, true);
- if (ret)
- return ret;
- }
-
- return 0;
- }
-
- /* Underscan */
- if (property == disp->underscan_property) {
- if (nv_connector->underscan != value) {
- nv_connector->underscan = value;
- if (!nv_crtc || !nv_crtc->set_scale)
- return 0;
-
- return nv_crtc->set_scale(nv_crtc, true);
- }
-
- return 0;
- }
-
- if (property == disp->underscan_hborder_property) {
- if (nv_connector->underscan_hborder != value) {
- nv_connector->underscan_hborder = value;
- if (!nv_crtc || !nv_crtc->set_scale)
- return 0;
-
- return nv_crtc->set_scale(nv_crtc, true);
- }
-
- return 0;
- }
-
- if (property == disp->underscan_vborder_property) {
- if (nv_connector->underscan_vborder != value) {
- nv_connector->underscan_vborder = value;
- if (!nv_crtc || !nv_crtc->set_scale)
- return 0;
-
- return nv_crtc->set_scale(nv_crtc, true);
- }
-
- return 0;
- }
+ if (connector->dev->mode_config.funcs->atomic_commit)
+ return drm_atomic_helper_connector_set_property(connector, property, value);
- /* Dithering */
- if (property == disp->dithering_mode) {
- nv_connector->dithering_mode = value;
- if (!nv_crtc || !nv_crtc->set_dither)
- return 0;
-
- return nv_crtc->set_dither(nv_crtc, true);
- }
-
- if (property == disp->dithering_depth) {
- nv_connector->dithering_depth = value;
- if (!nv_crtc || !nv_crtc->set_dither)
- return 0;
-
- return nv_crtc->set_dither(nv_crtc, true);
- }
-
- if (nv_crtc && nv_crtc->set_color_vibrance) {
- /* Hue */
- if (property == disp->vibrant_hue_property) {
- nv_crtc->vibrant_hue = value - 90;
- return nv_crtc->set_color_vibrance(nv_crtc, true);
- }
- /* Saturation */
- if (property == disp->color_vibrance_property) {
- nv_crtc->color_vibrance = value - 100;
- return nv_crtc->set_color_vibrance(nv_crtc, true);
- }
+ ret = connector->funcs->atomic_set_property(&nv_connector->base,
+ &asyc->state,
+ property, value);
+ if (ret) {
+ if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
+ return get_slave_funcs(encoder)->set_property(
+ encoder, connector, property, value);
+ return ret;
}
- if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
- return get_slave_funcs(encoder)->set_property(
- encoder, connector, property, value);
-
- return -EINVAL;
-}
-
-static struct drm_display_mode *
-nouveau_connector_native_mode(struct drm_connector *connector)
-{
- const struct drm_connector_helper_funcs *helper = connector->helper_private;
- struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_connector *nv_connector = nouveau_connector(connector);
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode, *largest = NULL;
- int high_w = 0, high_h = 0, high_v = 0;
+ nv_connector->scaling_mode = asyc->scaler.mode;
+ nv_connector->dithering_mode = asyc->dither.mode;
- list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
- mode->vrefresh = drm_mode_vrefresh(mode);
- if (helper->mode_valid(connector, mode) != MODE_OK ||
- (mode->flags & DRM_MODE_FLAG_INTERLACE))
- continue;
-
- /* Use preferred mode if there is one.. */
- if (mode->type & DRM_MODE_TYPE_PREFERRED) {
- NV_DEBUG(drm, "native mode from preferred\n");
- return drm_mode_duplicate(dev, mode);
- }
-
- /* Otherwise, take the resolution with the largest width, then
- * height, then vertical refresh
- */
- if (mode->hdisplay < high_w)
- continue;
-
- if (mode->hdisplay == high_w && mode->vdisplay < high_h)
- continue;
-
- if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
- mode->vrefresh < high_v)
- continue;
-
- high_w = mode->hdisplay;
- high_h = mode->vdisplay;
- high_v = mode->vrefresh;
- largest = mode;
+ if (connector->encoder && connector->encoder->crtc) {
+ ret = drm_crtc_helper_set_mode(connector->encoder->crtc,
+ &connector->encoder->crtc->mode,
+ connector->encoder->crtc->x,
+ connector->encoder->crtc->y,
+ NULL);
+ if (!ret)
+ return -EINVAL;
}
- NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
- high_w, high_h, high_v);
- return largest ? drm_mode_duplicate(dev, largest) : NULL;
+ return 0;
}
struct moderec {
@@ -805,8 +943,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
* the list of modes.
*/
if (!nv_connector->native_mode)
- nv_connector->native_mode =
- nouveau_connector_native_mode(connector);
+ nv_connector->native_mode = nouveau_conn_native_mode(connector);
if (ret == 0 && nv_connector->native_mode) {
struct drm_display_mode *mode;
@@ -934,56 +1071,42 @@ nouveau_connector_helper_funcs = {
.best_encoder = nouveau_connector_best_encoder,
};
+static int
+nouveau_connector_dpms(struct drm_connector *connector, int mode)
+{
+ if (connector->dev->mode_config.funcs->atomic_commit)
+ return drm_atomic_helper_connector_dpms(connector, mode);
+ return drm_helper_connector_dpms(connector, mode);
+}
+
static const struct drm_connector_funcs
nouveau_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
+ .dpms = nouveau_connector_dpms,
+ .reset = nouveau_conn_reset,
.detect = nouveau_connector_detect,
- .destroy = nouveau_connector_destroy,
+ .force = nouveau_connector_force,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = nouveau_connector_set_property,
- .force = nouveau_connector_force
+ .destroy = nouveau_connector_destroy,
+ .atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+ .atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+ .atomic_set_property = nouveau_conn_atomic_set_property,
+ .atomic_get_property = nouveau_conn_atomic_get_property,
};
static const struct drm_connector_funcs
nouveau_connector_funcs_lvds = {
- .dpms = drm_helper_connector_dpms,
+ .dpms = nouveau_connector_dpms,
+ .reset = nouveau_conn_reset,
.detect = nouveau_connector_detect_lvds,
- .destroy = nouveau_connector_destroy,
+ .force = nouveau_connector_force,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = nouveau_connector_set_property,
- .force = nouveau_connector_force
-};
-
-static int
-nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
-{
- struct nouveau_encoder *nv_encoder = NULL;
-
- if (connector->encoder)
- nv_encoder = nouveau_encoder(connector->encoder);
- if (nv_encoder && nv_encoder->dcb &&
- nv_encoder->dcb->type == DCB_OUTPUT_DP) {
- if (mode == DRM_MODE_DPMS_ON) {
- u8 data = DP_SET_POWER_D0;
- nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
- usleep_range(1000, 2000);
- } else {
- u8 data = DP_SET_POWER_D3;
- nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
- }
- }
-
- return drm_helper_connector_dpms(connector, mode);
-}
-
-static const struct drm_connector_funcs
-nouveau_connector_funcs_dp = {
- .dpms = nouveau_connector_dp_dpms,
- .detect = nouveau_connector_detect,
.destroy = nouveau_connector_destroy,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = nouveau_connector_set_property,
- .force = nouveau_connector_force
+ .atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+ .atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+ .atomic_set_property = nouveau_conn_atomic_set_property,
+ .atomic_get_property = nouveau_conn_atomic_get_property,
};
static int
@@ -995,19 +1118,20 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
struct nouveau_drm *drm = nouveau_drm(connector->dev);
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
const char *name = connector->name;
+ struct nouveau_encoder *nv_encoder;
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
+ NV_DEBUG(drm, "service %s\n", name);
+ if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP)))
+ nv50_mstm_service(nv_encoder->dp.mstm);
} else {
bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
-
- mutex_lock(&drm->dev->mode_config.mutex);
- if (plugged)
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
- else
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
- mutex_unlock(&drm->dev->mode_config.mutex);
+ if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) {
+ if (!plugged)
+ nv50_mstm_remove(nv_encoder->dp.mstm);
+ }
drm_helper_hpd_irq_event(connector->dev);
}
@@ -1188,7 +1312,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
return ERR_PTR(ret);
}
- funcs = &nouveau_connector_funcs_dp;
+ funcs = &nouveau_connector_funcs;
break;
default:
funcs = &nouveau_connector_funcs;
@@ -1202,38 +1326,10 @@ nouveau_connector_create(struct drm_device *dev, int index)
drm_connector_init(dev, connector, funcs, type);
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
- /* Init DVI-I specific properties */
- if (nv_connector->type == DCB_CONNECTOR_DVI_I)
- drm_object_attach_property(&connector->base, dev->mode_config.dvi_i_subconnector_property, 0);
+ connector->funcs->reset(connector);
+ nouveau_conn_attach_properties(connector);
- /* Add overscan compensation options to digital outputs */
- if (disp->underscan_property &&
- (type == DRM_MODE_CONNECTOR_DVID ||
- type == DRM_MODE_CONNECTOR_DVII ||
- type == DRM_MODE_CONNECTOR_HDMIA ||
- type == DRM_MODE_CONNECTOR_DisplayPort)) {
- drm_object_attach_property(&connector->base,
- disp->underscan_property,
- UNDERSCAN_OFF);
- drm_object_attach_property(&connector->base,
- disp->underscan_hborder_property,
- 0);
- drm_object_attach_property(&connector->base,
- disp->underscan_vborder_property,
- 0);
- }
-
- /* Add hue and saturation options */
- if (disp->vibrant_hue_property)
- drm_object_attach_property(&connector->base,
- disp->vibrant_hue_property,
- 90);
- if (disp->color_vibrance_property)
- drm_object_attach_property(&connector->base,
- disp->color_vibrance_property,
- 150);
-
- /* default scaling mode */
+ /* Default scaling mode */
switch (nv_connector->type) {
case DCB_CONNECTOR_LVDS:
case DCB_CONNECTOR_LVDS_SPWG:
@@ -1250,23 +1346,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
break;
}
- /* scaling mode property */
- switch (nv_connector->type) {
- case DCB_CONNECTOR_TV_0:
- case DCB_CONNECTOR_TV_1:
- case DCB_CONNECTOR_TV_3:
- break;
- case DCB_CONNECTOR_VGA:
- if (disp->disp.oclass < NV50_DISP)
- break; /* can only scale on DFPs */
- /* fall-through */
- default:
- drm_object_attach_property(&connector->base, dev->mode_config.
- scaling_mode_property,
- nv_connector->scaling_mode);
- break;
- }
-
/* dithering properties */
switch (nv_connector->type) {
case DCB_CONNECTOR_TV_0:
@@ -1275,20 +1354,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
case DCB_CONNECTOR_VGA:
break;
default:
- if (disp->dithering_mode) {
- nv_connector->dithering_mode = DITHERING_MODE_AUTO;
- drm_object_attach_property(&connector->base,
- disp->dithering_mode,
- nv_connector->
- dithering_mode);
- }
- if (disp->dithering_depth) {
- nv_connector->dithering_depth = DITHERING_DEPTH_AUTO;
- drm_object_attach_property(&connector->base,
- disp->dithering_depth,
- nv_connector->
- dithering_depth);
- }
+ nv_connector->dithering_mode = DITHERING_MODE_AUTO;
break;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 7446ee66ea04..096983c42a1f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -35,30 +35,6 @@
struct nvkm_i2c_port;
-enum nouveau_underscan_type {
- UNDERSCAN_OFF,
- UNDERSCAN_ON,
- UNDERSCAN_AUTO,
-};
-
-/* the enum values specifically defined here match nv50/nvd0 hw values, and
- * the code relies on this
- */
-enum nouveau_dithering_mode {
- DITHERING_MODE_OFF = 0x00,
- DITHERING_MODE_ON = 0x01,
- DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
- DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
- DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
- DITHERING_MODE_AUTO
-};
-
-enum nouveau_dithering_depth {
- DITHERING_DEPTH_6BPC = 0x00,
- DITHERING_DEPTH_8BPC = 0x02,
- DITHERING_DEPTH_AUTO
-};
-
struct nouveau_connector {
struct drm_connector base;
enum dcb_connector_type type;
@@ -70,12 +46,7 @@ struct nouveau_connector {
struct drm_dp_aux aux;
int dithering_mode;
- int dithering_depth;
int scaling_mode;
- bool scaling_full;
- enum nouveau_underscan_type underscan;
- u32 underscan_hborder;
- u32 underscan_vborder;
struct nouveau_encoder *detected_encoder;
struct edid *edid;
@@ -109,5 +80,74 @@ nouveau_connector_create(struct drm_device *, int index);
extern int nouveau_tv_disable;
extern int nouveau_ignorelid;
extern int nouveau_duallink;
+extern int nouveau_hdmimhz;
+
+#include <drm/drm_crtc.h>
+#define nouveau_conn_atom(p) \
+ container_of((p), struct nouveau_conn_atom, state)
+
+struct nouveau_conn_atom {
+ struct drm_connector_state state;
+
+ struct {
+ /* The enum values specifically defined here match nv50/gf119
+ * hw values, and the code relies on this.
+ */
+ enum {
+ DITHERING_MODE_OFF = 0x00,
+ DITHERING_MODE_ON = 0x01,
+ DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
+ DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
+ DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
+ DITHERING_MODE_AUTO
+ } mode;
+ enum {
+ DITHERING_DEPTH_6BPC = 0x00,
+ DITHERING_DEPTH_8BPC = 0x02,
+ DITHERING_DEPTH_AUTO
+ } depth;
+ } dither;
+
+ struct {
+ int mode; /* DRM_MODE_SCALE_* */
+ struct {
+ enum {
+ UNDERSCAN_OFF,
+ UNDERSCAN_ON,
+ UNDERSCAN_AUTO,
+ } mode;
+ u32 hborder;
+ u32 vborder;
+ } underscan;
+ bool full;
+ } scaler;
+
+ struct {
+ int color_vibrance;
+ int vibrant_hue;
+ } procamp;
+
+ union {
+ struct {
+ bool dither:1;
+ bool scaler:1;
+ bool procamp:1;
+ };
+ u8 mask;
+ } set;
+};
+void nouveau_conn_attach_properties(struct drm_connector *);
+void nouveau_conn_reset(struct drm_connector *);
+struct drm_connector_state *
+nouveau_conn_atomic_duplicate_state(struct drm_connector *);
+void nouveau_conn_atomic_destroy_state(struct drm_connector *,
+ struct drm_connector_state *);
+int nouveau_conn_atomic_set_property(struct drm_connector *,
+ struct drm_connector_state *,
+ struct drm_property *, u64);
+int nouveau_conn_atomic_get_property(struct drm_connector *,
+ const struct drm_connector_state *,
+ struct drm_property *, u64 *);
+struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
#endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index 863f10b8d818..050fcf30a0d2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -38,8 +38,6 @@ struct nouveau_crtc {
uint32_t dpms_saved_fp_control;
uint32_t fp_users;
int saturation;
- int color_vibrance;
- int vibrant_hue;
int sharpness;
int last_dpms;
@@ -54,7 +52,6 @@ struct nouveau_crtc {
struct {
struct nouveau_bo *nvbo;
- bool visible;
uint32_t offset;
void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
void (*set_pos)(struct nouveau_crtc *, int x, int y);
@@ -70,10 +67,6 @@ struct nouveau_crtc {
int depth;
} lut;
- int (*set_dither)(struct nouveau_crtc *crtc, bool update);
- int (*set_scale)(struct nouveau_crtc *crtc, bool update);
- int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update);
-
void (*save)(struct drm_crtc *crtc);
void (*restore)(struct drm_crtc *crtc);
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index afbf557b23d4..cef08da1da4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -24,7 +24,10 @@
*
*/
+#include <acpi/video.h>
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <nvif/class.h>
@@ -92,7 +95,7 @@ calc(int blanks, int blanke, int total, int line)
return line;
}
-int
+static int
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime)
{
@@ -158,9 +161,13 @@ nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (nouveau_crtc(crtc)->index == pipe) {
+ struct drm_display_mode *mode;
+ if (dev->mode_config.funcs->atomic_commit)
+ mode = &crtc->state->adjusted_mode;
+ else
+ mode = &crtc->hwmode;
return drm_calc_vbltimestamp_from_scanoutpos(dev,
- pipe, max_error, time, flags,
- &crtc->hwmode);
+ pipe, max_error, time, flags, mode);
}
}
@@ -217,10 +224,6 @@ static void
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
{
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
- struct nouveau_display *disp = nouveau_display(drm_fb->dev);
-
- if (disp->fb_dtor)
- disp->fb_dtor(drm_fb);
if (fb->nvbo)
drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
@@ -245,57 +248,45 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
};
int
-nouveau_framebuffer_init(struct drm_device *dev,
- struct nouveau_framebuffer *nv_fb,
- const struct drm_mode_fb_cmd2 *mode_cmd,
- struct nouveau_bo *nvbo)
+nouveau_framebuffer_new(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct nouveau_bo *nvbo,
+ struct nouveau_framebuffer **pfb)
{
- struct nouveau_display *disp = nouveau_display(dev);
- struct drm_framebuffer *fb = &nv_fb->base;
+ struct nouveau_framebuffer *fb;
int ret;
- drm_helper_mode_fill_fb_struct(fb, mode_cmd);
- nv_fb->nvbo = nvbo;
-
- ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
- if (ret)
- return ret;
+ if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
+ return -ENOMEM;
- if (disp->fb_ctor) {
- ret = disp->fb_ctor(fb);
- if (ret)
- disp->fb_dtor(fb);
- }
+ drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+ fb->nvbo = nvbo;
+ ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
+ if (ret)
+ kfree(fb);
return ret;
}
-static struct drm_framebuffer *
+struct drm_framebuffer *
nouveau_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
- struct nouveau_framebuffer *nouveau_fb;
+ struct nouveau_framebuffer *fb;
+ struct nouveau_bo *nvbo;
struct drm_gem_object *gem;
- int ret = -ENOMEM;
+ int ret;
gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
if (!gem)
return ERR_PTR(-ENOENT);
+ nvbo = nouveau_gem_object(gem);
- nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
- if (!nouveau_fb)
- goto err_unref;
-
- ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
- if (ret)
- goto err;
+ ret = nouveau_framebuffer_new(dev, mode_cmd, nvbo, &fb);
+ if (ret == 0)
+ return &fb->base;
- return &nouveau_fb->base;
-
-err:
- kfree(nouveau_fb);
-err_unref:
drm_gem_object_unreference_unlocked(gem);
return ERR_PTR(ret);
}
@@ -358,6 +349,55 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
} \
} while(0)
+static void
+nouveau_display_hpd_work(struct work_struct *work)
+{
+ struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work);
+
+ pm_runtime_get_sync(drm->dev->dev);
+
+ drm_helper_hpd_irq_event(drm->dev);
+
+ pm_runtime_mark_last_busy(drm->dev->dev);
+ pm_runtime_put_sync(drm->dev->dev);
+}
+
+#ifdef CONFIG_ACPI
+
+/*
+ * Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
+ * to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
+ * This should be dropped once that is merged.
+ */
+#ifndef ACPI_VIDEO_NOTIFY_PROBE
+#define ACPI_VIDEO_NOTIFY_PROBE 0x81
+#endif
+
+static int
+nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
+ struct acpi_bus_event *info = data;
+
+ if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
+ if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
+ /*
+ * This may be the only indication we receive of a
+ * connector hotplug on a runtime suspended GPU,
+ * schedule hpd_work to check.
+ */
+ schedule_work(&drm->hpd_work);
+
+ /* acpi-video should not generate keypresses for this */
+ return NOTIFY_BAD;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+#endif
+
int
nouveau_display_init(struct drm_device *dev)
{
@@ -385,16 +425,19 @@ nouveau_display_init(struct drm_device *dev)
}
void
-nouveau_display_fini(struct drm_device *dev)
+nouveau_display_fini(struct drm_device *dev, bool suspend)
{
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_connector *connector;
- int head;
+ struct drm_crtc *crtc;
+
+ if (!suspend)
+ drm_crtc_force_disable_all(dev);
/* Make sure that drm and hw vblank irqs get properly disabled. */
- for (head = 0; head < dev->mode_config.num_crtc; head++)
- drm_vblank_off(dev, head);
+ drm_for_each_crtc(crtc, dev)
+ drm_crtc_vblank_off(crtc);
/* disable flip completion events */
nvif_notify_put(&drm->flip);
@@ -495,7 +538,7 @@ nouveau_display_create(struct drm_device *dev)
if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
static const u16 oclass[] = {
- GP104_DISP,
+ GP102_DISP,
GP100_DISP,
GM200_DISP,
GM107_DISP,
@@ -530,6 +573,8 @@ nouveau_display_create(struct drm_device *dev)
if (ret)
goto disp_create_err;
+ drm_mode_config_reset(dev);
+
if (dev->mode_config.num_crtc) {
ret = nouveau_display_vblank_init(dev);
if (ret)
@@ -537,6 +582,12 @@ nouveau_display_create(struct drm_device *dev)
}
nouveau_backlight_init(dev);
+ INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
+#ifdef CONFIG_ACPI
+ drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
+ register_acpi_notifier(&drm->acpi_nb);
+#endif
+
return 0;
vblank_err:
@@ -552,11 +603,13 @@ nouveau_display_destroy(struct drm_device *dev)
{
struct nouveau_display *disp = nouveau_display(dev);
+#ifdef CONFIG_ACPI
+ unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
+#endif
nouveau_backlight_exit(dev);
nouveau_display_vblank_fini(dev);
drm_kms_helper_poll_fini(dev);
- drm_crtc_force_disable_all(dev);
drm_mode_config_cleanup(dev);
if (disp->dtor)
@@ -568,12 +621,138 @@ nouveau_display_destroy(struct drm_device *dev)
kfree(disp);
}
+static int
+nouveau_atomic_disable_connector(struct drm_atomic_state *state,
+ struct drm_connector *connector)
+{
+ struct drm_connector_state *connector_state;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane_state *plane_state;
+ struct drm_plane *plane;
+ int ret;
+
+ if (!(crtc = connector->state->crtc))
+ return 0;
+
+ connector_state = drm_atomic_get_connector_state(state, connector);
+ if (IS_ERR(connector_state))
+ return PTR_ERR(connector_state);
+
+ ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
+ if (ret)
+ return ret;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+ if (ret)
+ return ret;
+
+ crtc_state->active = false;
+
+ drm_for_each_plane_mask(plane, connector->dev, crtc_state->plane_mask) {
+ plane_state = drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state))
+ return PTR_ERR(plane_state);
+
+ ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+ if (ret)
+ return ret;
+
+ drm_atomic_set_fb_for_plane(plane_state, NULL);
+ }
+
+ return 0;
+}
+
+static int
+nouveau_atomic_disable(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_atomic_state *state;
+ struct drm_connector *connector;
+ int ret;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return -ENOMEM;
+
+ state->acquire_ctx = ctx;
+
+ drm_for_each_connector(connector, dev) {
+ ret = nouveau_atomic_disable_connector(state, connector);
+ if (ret)
+ break;
+ }
+
+ if (ret == 0)
+ ret = drm_atomic_commit(state);
+ drm_atomic_state_put(state);
+ return ret;
+}
+
+static struct drm_atomic_state *
+nouveau_atomic_suspend(struct drm_device *dev)
+{
+ struct drm_modeset_acquire_ctx ctx;
+ struct drm_atomic_state *state;
+ int ret;
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+ ret = drm_modeset_lock_all_ctx(dev, &ctx);
+ if (ret < 0) {
+ state = ERR_PTR(ret);
+ goto unlock;
+ }
+
+ state = drm_atomic_helper_duplicate_state(dev, &ctx);
+ if (IS_ERR(state))
+ goto unlock;
+
+ ret = nouveau_atomic_disable(dev, &ctx);
+ if (ret < 0) {
+ drm_atomic_state_put(state);
+ state = ERR_PTR(ret);
+ goto unlock;
+ }
+
+unlock:
+ if (PTR_ERR(state) == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+ return state;
+}
+
int
nouveau_display_suspend(struct drm_device *dev, bool runtime)
{
+ struct nouveau_display *disp = nouveau_display(dev);
struct drm_crtc *crtc;
- nouveau_display_fini(dev);
+ if (dev->mode_config.funcs->atomic_commit) {
+ if (!runtime) {
+ disp->suspend = nouveau_atomic_suspend(dev);
+ if (IS_ERR(disp->suspend)) {
+ int ret = PTR_ERR(disp->suspend);
+ disp->suspend = NULL;
+ return ret;
+ }
+ }
+
+ nouveau_display_fini(dev, true);
+ return 0;
+ }
+
+ nouveau_display_fini(dev, true);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
@@ -600,9 +779,19 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
void
nouveau_display_resume(struct drm_device *dev, bool runtime)
{
+ struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_crtc *crtc;
- int ret, head;
+ int ret;
+
+ if (dev->mode_config.funcs->atomic_commit) {
+ nouveau_display_init(dev);
+ if (disp->suspend) {
+ drm_atomic_helper_resume(dev, disp->suspend);
+ disp->suspend = NULL;
+ }
+ return;
+ }
/* re-pin fb/cursors */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -647,10 +836,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
drm_helper_resume_force_mode(dev);
- /* Make sure that drm and hw vblank irqs get resumed if needed. */
- for (head = 0; head < dev->mode_config.num_crtc; head++)
- drm_vblank_on(dev, head);
-
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -692,10 +877,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
if (ret)
goto fail;
- if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
- BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
- else
- BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
+ BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
OUT_RING (chan, 0x00000000);
FIRE_RING (chan);
@@ -724,6 +906,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_channel *chan;
struct nouveau_cli *cli;
struct nouveau_fence *fence;
+ struct nv04_display *dispnv04 = nv04_display(dev);
+ int head = nouveau_crtc(crtc)->index;
int ret;
chan = drm->channel;
@@ -770,32 +954,23 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
drm_crtc_vblank_get(crtc);
/* Emit a page flip */
- if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
- ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
+ if (swap_interval) {
+ ret = RING_SPACE(chan, 8);
if (ret)
goto fail_unreserve;
- } else {
- struct nv04_display *dispnv04 = nv04_display(dev);
- int head = nouveau_crtc(crtc)->index;
-
- if (swap_interval) {
- ret = RING_SPACE(chan, 8);
- if (ret)
- goto fail_unreserve;
-
- BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
- OUT_RING (chan, 0);
- BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
- OUT_RING (chan, head);
- BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
- OUT_RING (chan, 0);
- BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
- OUT_RING (chan, 0);
- }
- nouveau_bo_ref(new_bo, &dispnv04->image[head]);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
+ OUT_RING (chan, 0);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
+ OUT_RING (chan, head);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
+ OUT_RING (chan, 0);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
+ OUT_RING (chan, 0);
}
+ nouveau_bo_ref(new_bo, &dispnv04->image[head]);
+
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
if (ret)
goto fail_unreserve;
@@ -843,16 +1018,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
if (s->event) {
- if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
- drm_crtc_arm_vblank_event(s->crtc, s->event);
- } else {
- drm_crtc_send_vblank_event(s->crtc, s->event);
-
- /* Give up ownership of vblank for page-flipped crtc */
- drm_crtc_vblank_put(s->crtc);
- }
- }
- else {
+ drm_crtc_arm_vblank_event(s->crtc, s->event);
+ } else {
/* Give up ownership of vblank for page-flipped crtc */
drm_crtc_vblank_put(s->crtc);
}
@@ -874,12 +1041,10 @@ nouveau_flip_complete(struct nvif_notify *notify)
struct nouveau_page_flip_state state;
if (!nouveau_finish_page_flip(chan, &state)) {
- if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
- nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
- state.offset + state.crtc->y *
- state.pitch + state.crtc->x *
- state.bpp / 8);
- }
+ nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
+ state.offset + state.crtc->y *
+ state.pitch + state.crtc->x *
+ state.bpp / 8);
}
return NVIF_NOTIFY_KEEP;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 0420ee861ea4..4a75df06c139 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -22,8 +22,9 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
return container_of(fb, struct nouveau_framebuffer, base);
}
-int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
- const struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
+int nouveau_framebuffer_new(struct drm_device *,
+ const struct drm_mode_fb_cmd2 *,
+ struct nouveau_bo *, struct nouveau_framebuffer **);
struct nouveau_page_flip_state {
struct list_head head;
@@ -39,9 +40,6 @@ struct nouveau_display {
int (*init)(struct drm_device *);
void (*fini)(struct drm_device *);
- int (*fb_ctor)(struct drm_framebuffer *);
- void (*fb_dtor)(struct drm_framebuffer *);
-
struct nvif_object disp;
struct drm_property *dithering_mode;
@@ -52,6 +50,8 @@ struct nouveau_display {
/* not really hue and saturation: */
struct drm_property *vibrant_hue_property;
struct drm_property *color_vibrance_property;
+
+ struct drm_atomic_state *suspend;
};
static inline struct nouveau_display *
@@ -63,7 +63,7 @@ nouveau_display(struct drm_device *dev)
int nouveau_display_create(struct drm_device *dev);
void nouveau_display_destroy(struct drm_device *dev);
int nouveau_display_init(struct drm_device *dev);
-void nouveau_display_fini(struct drm_device *dev);
+void nouveau_display_fini(struct drm_device *dev, bool suspend);
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 *, unsigned int);
@@ -91,6 +91,8 @@ int nouveau_crtc_set_config(struct drm_mode_set *set);
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
extern int nouveau_backlight_init(struct drm_device *);
extern void nouveau_backlight_exit(struct drm_device *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
#else
static inline int
nouveau_backlight_init(struct drm_device *dev)
@@ -101,6 +103,17 @@ nouveau_backlight_init(struct drm_device *dev)
static inline void
nouveau_backlight_exit(struct drm_device *dev) {
}
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
#endif
+struct drm_framebuffer *
+nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
+ const struct drm_mode_fb_cmd2 *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 87d52d36f4fc..0d052e1660f8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -30,6 +30,13 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
+#include <nvif/class.h>
+#include <nvif/cl5070.h>
+
+MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
+static int nouveau_mst = 1;
+module_param_named(mst, nouveau_mst, int, 0400);
+
static void
nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd)
{
@@ -55,14 +62,14 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
struct drm_device *dev = nv_encoder->base.base.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nvkm_i2c_aux *aux;
- u8 *dpcd = nv_encoder->dp.dpcd;
+ u8 dpcd[8];
int ret;
aux = nv_encoder->aux;
if (!aux)
return -ENODEV;
- ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, 8);
+ ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
if (ret)
return ret;
@@ -84,5 +91,11 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
nouveau_dp_probe_oui(dev, aux, dpcd);
- return 0;
+
+ ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst);
+ if (ret == 1)
+ return NOUVEAU_DP_MST;
+ if (ret == 0)
+ return NOUVEAU_DP_SST;
+ return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 3100fd88a015..59348fc41c77 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -47,6 +47,7 @@
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
#include "nouveau_vga.h"
+#include "nouveau_led.h"
#include "nouveau_hwmon.h"
#include "nouveau_acpi.h"
#include "nouveau_bios.h"
@@ -475,6 +476,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
nouveau_hwmon_init(dev);
nouveau_accel_init(drm);
nouveau_fbcon_init(dev);
+ nouveau_led_init(dev);
if (nouveau_runtime_pm != 0) {
pm_runtime_use_autosuspend(dev->dev);
@@ -510,13 +512,14 @@ nouveau_drm_unload(struct drm_device *dev)
pm_runtime_forbid(dev->dev);
}
+ nouveau_led_fini(dev);
nouveau_fbcon_fini(dev);
nouveau_accel_fini(drm);
nouveau_hwmon_fini(dev);
nouveau_debugfs_fini(drm);
if (dev->mode_config.num_crtc)
- nouveau_display_fini(dev);
+ nouveau_display_fini(dev, false);
nouveau_display_destroy(dev);
nouveau_bios_takedown(dev);
@@ -561,6 +564,8 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
struct nouveau_cli *cli;
int ret;
+ nouveau_led_suspend(dev);
+
if (dev->mode_config.num_crtc) {
NV_INFO(drm, "suspending console...\n");
nouveau_fbcon_set_suspend(dev, 1);
@@ -649,6 +654,8 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
nouveau_fbcon_set_suspend(dev, 0);
}
+ nouveau_led_resume(dev);
+
return 0;
}
@@ -692,7 +699,12 @@ nouveau_pmops_resume(struct device *dev)
return ret;
pci_set_master(pdev);
- return nouveau_do_resume(drm_dev, false);
+ ret = nouveau_do_resume(drm_dev, false);
+
+ /* Monitors may have been connected / disconnected during suspend */
+ schedule_work(&nouveau_drm(drm_dev)->hpd_work);
+
+ return ret;
}
static int
@@ -766,6 +778,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
+
+ /* Monitors may have been connected / disconnected during suspend */
+ schedule_work(&nouveau_drm(drm_dev)->hpd_work);
+
return ret;
}
@@ -1030,6 +1046,7 @@ static void nouveau_display_options(void)
DRM_DEBUG_DRIVER("... modeset : %d\n", nouveau_modeset);
DRM_DEBUG_DRIVER("... runpm : %d\n", nouveau_runtime_pm);
DRM_DEBUG_DRIVER("... vram_pushbuf : %d\n", nouveau_vram_pushbuf);
+ DRM_DEBUG_DRIVER("... hdmimhz : %d\n", nouveau_hdmimhz);
}
static const struct dev_pm_ops nouveau_pm_ops = {
@@ -1105,6 +1122,7 @@ nouveau_drm_init(void)
#endif
nouveau_register_dsm_handler();
+ nouveau_backlight_ctor();
return drm_pci_init(&driver_pci, &nouveau_drm_pci_driver);
}
@@ -1115,6 +1133,7 @@ nouveau_drm_exit(void)
return;
drm_pci_exit(&driver_pci, &nouveau_drm_pci_driver);
+ nouveau_backlight_dtor();
nouveau_unregister_dsm_handler();
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 822a0212cd48..8d5ed5bfdacb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -37,6 +37,8 @@
* - implemented limited ABI16/NVIF interop
*/
+#include <linux/notifier.h>
+
#include <nvif/client.h>
#include <nvif/device.h>
#include <nvif/ioctl.h>
@@ -161,11 +163,19 @@ struct nouveau_drm {
struct nvbios vbios;
struct nouveau_display *display;
struct backlight_device *backlight;
+ struct list_head bl_connectors;
+ struct work_struct hpd_work;
+#ifdef CONFIG_ACPI
+ struct notifier_block acpi_nb;
+#endif
/* power management */
struct nouveau_hwmon *hwmon;
struct nouveau_debugfs *debugfs;
+ /* led management */
+ struct nouveau_led *led;
+
/* display power reference */
bool have_disp_power_ref;
@@ -201,6 +211,10 @@ void nouveau_drm_device_remove(struct drm_device *dev);
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
NV_PRINTK(info, &(drm)->client, f, ##a); \
} while(0)
+#define NV_ATOMIC(drm,f,a...) do { \
+ if (unlikely(drm_debug & DRM_UT_ATOMIC)) \
+ NV_PRINTK(info, &(drm)->client, f, ##a); \
+} while(0)
extern int nouveau_modeset;
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index ee6a6d3fc80f..198e5f27682f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -30,6 +30,7 @@
#include <subdev/bios/dcb.h>
#include <drm/drm_encoder_slave.h>
+#include <drm/drm_dp_mst_helper.h>
#include "dispnv04/disp.h"
#define NV_DPMS_CLEARED 0x80
@@ -57,15 +58,16 @@ struct nouveau_encoder {
union {
struct {
- u8 dpcd[8];
+ struct nv50_mstm *mstm;
int link_nr;
int link_bw;
- u32 datarate;
} dp;
};
void (*enc_save)(struct drm_encoder *encoder);
void (*enc_restore)(struct drm_encoder *encoder);
+ void (*update)(struct nouveau_encoder *, u8 head,
+ struct drm_display_mode *, u8 proto, u8 depth);
};
struct nouveau_encoder *
@@ -90,9 +92,17 @@ get_slave_funcs(struct drm_encoder *enc)
}
/* nouveau_dp.c */
+enum nouveau_dp_status {
+ NOUVEAU_DP_SST,
+ NOUVEAU_DP_MST,
+};
+
int nouveau_dp_detect(struct nouveau_encoder *);
struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
+int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow);
+void nv50_mstm_remove(struct nv50_mstm *);
+void nv50_mstm_service(struct nv50_mstm *);
#endif /* __NOUVEAU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 9f5692726c16..2f2a3dcd4ad7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -58,7 +58,7 @@ static void
nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *fbcon = info->par;
- struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
struct nvif_device *device = &drm->device;
int ret;
@@ -90,7 +90,7 @@ static void
nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
{
struct nouveau_fbdev *fbcon = info->par;
- struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
struct nvif_device *device = &drm->device;
int ret;
@@ -122,7 +122,7 @@ static void
nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *fbcon = info->par;
- struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
struct nvif_device *device = &drm->device;
int ret;
@@ -154,7 +154,7 @@ static int
nouveau_fbcon_sync(struct fb_info *info)
{
struct nouveau_fbdev *fbcon = info->par;
- struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -181,7 +181,7 @@ 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);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
int ret = pm_runtime_get_sync(drm->dev->dev);
if (ret < 0 && ret != -EACCES)
return ret;
@@ -192,42 +192,30 @@ 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);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
pm_runtime_put(drm->dev->dev);
return 0;
}
static struct fb_ops nouveau_fbcon_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.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,
.fb_copyarea = nouveau_fbcon_copyarea,
.fb_imageblit = nouveau_fbcon_imageblit,
.fb_sync = nouveau_fbcon_sync,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
static struct fb_ops nouveau_fbcon_sw_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.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,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
void
@@ -333,16 +321,15 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
{
struct nouveau_fbdev *fbcon =
container_of(helper, struct nouveau_fbdev, helper);
- struct drm_device *dev = fbcon->dev;
+ struct drm_device *dev = fbcon->helper.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nvif_device *device = &drm->device;
struct fb_info *info;
- struct drm_framebuffer *fb;
- struct nouveau_framebuffer *nouveau_fb;
+ struct nouveau_framebuffer *fb;
struct nouveau_channel *chan;
struct nouveau_bo *nvbo;
struct drm_mode_fb_cmd2 mode_cmd;
- int size, ret;
+ int ret;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
@@ -353,16 +340,17 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
- size = mode_cmd.pitches[0] * mode_cmd.height;
- size = roundup(size, PAGE_SIZE);
-
- ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
- 0, 0x0000, &nvbo);
+ ret = nouveau_gem_new(dev, mode_cmd.pitches[0] * mode_cmd.height,
+ 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
if (ret) {
NV_ERROR(drm, "failed to allocate framebuffer\n");
goto out;
}
+ ret = nouveau_framebuffer_new(dev, &mode_cmd, nvbo, &fb);
+ if (ret)
+ goto out_unref;
+
ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
if (ret) {
NV_ERROR(drm, "failed to pin fb: %d\n", ret);
@@ -377,8 +365,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
chan = nouveau_nofbaccel ? NULL : drm->channel;
if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
- ret = nouveau_bo_vma_add(nvbo, drm->client.vm,
- &fbcon->nouveau_fb.vma);
+ ret = nouveau_bo_vma_add(nvbo, drm->client.vm, &fb->vma);
if (ret) {
NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
chan = NULL;
@@ -394,13 +381,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
info->par = fbcon;
- nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo);
-
- nouveau_fb = &fbcon->nouveau_fb;
- fb = &nouveau_fb->base;
-
/* setup helper */
- fbcon->helper.fb = fb;
+ fbcon->helper.fb = &fb->base;
strcpy(info->fix.id, "nouveaufb");
if (!chan)
@@ -411,14 +393,14 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
FBINFO_HWACCEL_IMAGEBLIT;
info->flags |= FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &nouveau_fbcon_sw_ops;
- info->fix.smem_start = nvbo->bo.mem.bus.base +
- nvbo->bo.mem.bus.offset;
- info->fix.smem_len = size;
+ info->fix.smem_start = fb->nvbo->bo.mem.bus.base +
+ fb->nvbo->bo.mem.bus.offset;
+ info->fix.smem_len = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
- info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
- info->screen_size = size;
+ info->screen_base = nvbo_kmap_obj_iovirtual(fb->nvbo);
+ info->screen_size = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
- drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+ drm_fb_helper_fill_fix(info, fb->base.pitches[0], fb->base.depth);
drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@@ -429,20 +411,19 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
/* To allow resizeing without swapping buffers */
NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
- nouveau_fb->base.width, nouveau_fb->base.height,
- nvbo->bo.offset, nvbo);
+ fb->base.width, fb->base.height, fb->nvbo->bo.offset, nvbo);
vga_switcheroo_client_fb_set(dev->pdev, info);
return 0;
out_unlock:
if (chan)
- nouveau_bo_vma_del(nvbo, &fbcon->nouveau_fb.vma);
- nouveau_bo_unmap(nvbo);
+ nouveau_bo_vma_del(fb->nvbo, &fb->vma);
+ nouveau_bo_unmap(fb->nvbo);
out_unpin:
- nouveau_bo_unpin(nvbo);
+ nouveau_bo_unpin(fb->nvbo);
out_unref:
- nouveau_bo_ref(NULL, &nvbo);
+ nouveau_bo_ref(NULL, &fb->nvbo);
out:
return ret;
}
@@ -458,28 +439,26 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev)
static int
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
{
- struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb;
+ struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fbcon->helper.fb);
drm_fb_helper_unregister_fbi(&fbcon->helper);
drm_fb_helper_release_fbi(&fbcon->helper);
+ drm_fb_helper_fini(&fbcon->helper);
if (nouveau_fb->nvbo) {
- nouveau_bo_unmap(nouveau_fb->nvbo);
nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
+ nouveau_bo_unmap(nouveau_fb->nvbo);
nouveau_bo_unpin(nouveau_fb->nvbo);
- drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);
- nouveau_fb->nvbo = NULL;
+ drm_framebuffer_unreference(&nouveau_fb->base);
}
- drm_fb_helper_fini(&fbcon->helper);
- drm_framebuffer_unregister_private(&nouveau_fb->base);
- drm_framebuffer_cleanup(&nouveau_fb->base);
+
return 0;
}
void nouveau_fbcon_gpu_lockup(struct fb_info *info)
{
struct nouveau_fbdev *fbcon = info->par;
- struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
NV_ERROR(drm, "GPU lockup - switching to software fbcon\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
@@ -522,7 +501,6 @@ nouveau_fbcon_init(struct drm_device *dev)
if (!fbcon)
return -ENOMEM;
- fbcon->dev = dev;
drm->fbcon = fbcon;
drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
@@ -545,7 +523,8 @@ nouveau_fbcon_init(struct drm_device *dev)
preferred_bpp = 32;
/* disable all the possible outputs/crtcs before entering KMS mode */
- drm_helper_disable_unused_functions(dev);
+ if (!dev->mode_config.funcs->atomic_commit)
+ drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index ca77ad001978..e2bca729721e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -33,8 +33,6 @@
struct nouveau_fbdev {
struct drm_fb_helper helper;
- struct nouveau_framebuffer nouveau_fb;
- struct drm_device *dev;
unsigned int saved_flags;
struct nvif_object surf2d;
struct nvif_object clip;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 4bb9ab892ae1..f2f348f0160c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -28,7 +28,7 @@
#include <linux/ktime.h>
#include <linux/hrtimer.h>
-#include <trace/events/fence.h>
+#include <trace/events/dma_fence.h>
#include <nvif/cl826e.h>
#include <nvif/notify.h>
@@ -38,11 +38,11 @@
#include "nouveau_dma.h"
#include "nouveau_fence.h"
-static const struct fence_ops nouveau_fence_ops_uevent;
-static const struct fence_ops nouveau_fence_ops_legacy;
+static const struct dma_fence_ops nouveau_fence_ops_uevent;
+static const struct dma_fence_ops nouveau_fence_ops_legacy;
static inline struct nouveau_fence *
-from_fence(struct fence *fence)
+from_fence(struct dma_fence *fence)
{
return container_of(fence, struct nouveau_fence, base);
}
@@ -58,23 +58,23 @@ nouveau_fence_signal(struct nouveau_fence *fence)
{
int drop = 0;
- fence_signal_locked(&fence->base);
+ dma_fence_signal_locked(&fence->base);
list_del(&fence->head);
rcu_assign_pointer(fence->channel, NULL);
- if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) {
+ if (test_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags)) {
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
if (!--fctx->notify_ref)
drop = 1;
}
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
return drop;
}
static struct nouveau_fence *
-nouveau_local_fence(struct fence *fence, struct nouveau_drm *drm) {
+nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) {
struct nouveau_fence_priv *priv = (void*)drm->fence;
if (fence->ops != &nouveau_fence_ops_legacy &&
@@ -201,7 +201,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
struct nouveau_fence_work {
struct work_struct work;
- struct fence_cb cb;
+ struct dma_fence_cb cb;
void (*func)(void *);
void *data;
};
@@ -214,7 +214,7 @@ nouveau_fence_work_handler(struct work_struct *kwork)
kfree(work);
}
-static void nouveau_fence_work_cb(struct fence *fence, struct fence_cb *cb)
+static void nouveau_fence_work_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct nouveau_fence_work *work = container_of(cb, typeof(*work), cb);
@@ -222,12 +222,12 @@ static void nouveau_fence_work_cb(struct fence *fence, struct fence_cb *cb)
}
void
-nouveau_fence_work(struct fence *fence,
+nouveau_fence_work(struct dma_fence *fence,
void (*func)(void *), void *data)
{
struct nouveau_fence_work *work;
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
goto err;
work = kmalloc(sizeof(*work), GFP_KERNEL);
@@ -245,7 +245,7 @@ nouveau_fence_work(struct fence *fence,
work->func = func;
work->data = data;
- if (fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0)
+ if (dma_fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0)
goto err_free;
return;
@@ -266,17 +266,17 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
fence->timeout = jiffies + (15 * HZ);
if (priv->uevent)
- fence_init(&fence->base, &nouveau_fence_ops_uevent,
- &fctx->lock, fctx->context, ++fctx->sequence);
+ dma_fence_init(&fence->base, &nouveau_fence_ops_uevent,
+ &fctx->lock, fctx->context, ++fctx->sequence);
else
- fence_init(&fence->base, &nouveau_fence_ops_legacy,
- &fctx->lock, fctx->context, ++fctx->sequence);
+ dma_fence_init(&fence->base, &nouveau_fence_ops_legacy,
+ &fctx->lock, fctx->context, ++fctx->sequence);
kref_get(&fctx->fence_ref);
- trace_fence_emit(&fence->base);
+ trace_dma_fence_emit(&fence->base);
ret = fctx->emit(fence);
if (!ret) {
- fence_get(&fence->base);
+ dma_fence_get(&fence->base);
spin_lock_irq(&fctx->lock);
if (nouveau_fence_update(chan, fctx))
@@ -298,7 +298,7 @@ nouveau_fence_done(struct nouveau_fence *fence)
struct nouveau_channel *chan;
unsigned long flags;
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
return true;
spin_lock_irqsave(&fctx->lock, flags);
@@ -307,11 +307,11 @@ nouveau_fence_done(struct nouveau_fence *fence)
nvif_notify_put(&fctx->notify);
spin_unlock_irqrestore(&fctx->lock, flags);
}
- return fence_is_signaled(&fence->base);
+ return dma_fence_is_signaled(&fence->base);
}
static long
-nouveau_fence_wait_legacy(struct fence *f, bool intr, long wait)
+nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait)
{
struct nouveau_fence *fence = from_fence(f);
unsigned long sleep_time = NSEC_PER_MSEC / 1000;
@@ -378,7 +378,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
if (!lazy)
return nouveau_fence_wait_busy(fence, intr);
- ret = fence_wait_timeout(&fence->base, intr, 15 * HZ);
+ ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ);
if (ret < 0)
return ret;
else if (!ret)
@@ -391,7 +391,7 @@ int
nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr)
{
struct nouveau_fence_chan *fctx = chan->fence;
- struct fence *fence;
+ struct dma_fence *fence;
struct reservation_object *resv = nvbo->bo.resv;
struct reservation_object_list *fobj;
struct nouveau_fence *f;
@@ -421,7 +421,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
}
if (must_wait)
- ret = fence_wait(fence, intr);
+ ret = dma_fence_wait(fence, intr);
return ret;
}
@@ -446,7 +446,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
}
if (must_wait)
- ret = fence_wait(fence, intr);
+ ret = dma_fence_wait(fence, intr);
}
return ret;
@@ -456,7 +456,7 @@ void
nouveau_fence_unref(struct nouveau_fence **pfence)
{
if (*pfence)
- fence_put(&(*pfence)->base);
+ dma_fence_put(&(*pfence)->base);
*pfence = NULL;
}
@@ -484,12 +484,12 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
return ret;
}
-static const char *nouveau_fence_get_get_driver_name(struct fence *fence)
+static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence)
{
return "nouveau";
}
-static const char *nouveau_fence_get_timeline_name(struct fence *f)
+static const char *nouveau_fence_get_timeline_name(struct dma_fence *f)
{
struct nouveau_fence *fence = from_fence(f);
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -503,7 +503,7 @@ static const char *nouveau_fence_get_timeline_name(struct fence *f)
* result. The drm node should still be there, so we can derive the index from
* the fence context.
*/
-static bool nouveau_fence_is_signaled(struct fence *f)
+static bool nouveau_fence_is_signaled(struct dma_fence *f)
{
struct nouveau_fence *fence = from_fence(f);
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -519,7 +519,7 @@ static bool nouveau_fence_is_signaled(struct fence *f)
return ret;
}
-static bool nouveau_fence_no_signaling(struct fence *f)
+static bool nouveau_fence_no_signaling(struct dma_fence *f)
{
struct nouveau_fence *fence = from_fence(f);
@@ -530,30 +530,30 @@ static bool nouveau_fence_no_signaling(struct fence *f)
WARN_ON(atomic_read(&fence->base.refcount.refcount) <= 1);
/*
- * This needs uevents to work correctly, but fence_add_callback relies on
+ * This needs uevents to work correctly, but dma_fence_add_callback relies on
* being able to enable signaling. It will still get signaled eventually,
* just not right away.
*/
if (nouveau_fence_is_signaled(f)) {
list_del(&fence->head);
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
return false;
}
return true;
}
-static void nouveau_fence_release(struct fence *f)
+static void nouveau_fence_release(struct dma_fence *f)
{
struct nouveau_fence *fence = from_fence(f);
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
kref_put(&fctx->fence_ref, nouveau_fence_context_put);
- fence_free(&fence->base);
+ dma_fence_free(&fence->base);
}
-static const struct fence_ops nouveau_fence_ops_legacy = {
+static const struct dma_fence_ops nouveau_fence_ops_legacy = {
.get_driver_name = nouveau_fence_get_get_driver_name,
.get_timeline_name = nouveau_fence_get_timeline_name,
.enable_signaling = nouveau_fence_no_signaling,
@@ -562,7 +562,7 @@ static const struct fence_ops nouveau_fence_ops_legacy = {
.release = nouveau_fence_release
};
-static bool nouveau_fence_enable_signaling(struct fence *f)
+static bool nouveau_fence_enable_signaling(struct dma_fence *f)
{
struct nouveau_fence *fence = from_fence(f);
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -573,18 +573,18 @@ static bool nouveau_fence_enable_signaling(struct fence *f)
ret = nouveau_fence_no_signaling(f);
if (ret)
- set_bit(FENCE_FLAG_USER_BITS, &fence->base.flags);
+ set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags);
else if (!--fctx->notify_ref)
nvif_notify_put(&fctx->notify);
return ret;
}
-static const struct fence_ops nouveau_fence_ops_uevent = {
+static const struct dma_fence_ops nouveau_fence_ops_uevent = {
.get_driver_name = nouveau_fence_get_get_driver_name,
.get_timeline_name = nouveau_fence_get_timeline_name,
.enable_signaling = nouveau_fence_enable_signaling,
.signaled = nouveau_fence_is_signaled,
- .wait = fence_default_wait,
- .release = NULL
+ .wait = dma_fence_default_wait,
+ .release = nouveau_fence_release
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 64c4ce7115ad..ccdce1b4eec4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -1,14 +1,14 @@
#ifndef __NOUVEAU_FENCE_H__
#define __NOUVEAU_FENCE_H__
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <nvif/notify.h>
struct nouveau_drm;
struct nouveau_bo;
struct nouveau_fence {
- struct fence base;
+ struct dma_fence base;
struct list_head head;
@@ -24,7 +24,7 @@ void nouveau_fence_unref(struct nouveau_fence **);
int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
bool nouveau_fence_done(struct nouveau_fence *);
-void nouveau_fence_work(struct fence *, void (*)(void *), void *);
+void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *);
int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
@@ -92,7 +92,6 @@ struct nv84_fence_chan {
struct nouveau_fence_chan base;
struct nvkm_vma vma;
struct nvkm_vma vma_gart;
- struct nvkm_vma dispc_vma[4];
};
struct nv84_fence_priv {
@@ -102,7 +101,6 @@ struct nv84_fence_priv {
u32 *suspend;
};
-u64 nv84_fence_crtc(struct nouveau_channel *, int);
int nv84_fence_context_new(struct nouveau_channel *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 72e2399bce39..201b52b750dd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -119,7 +119,7 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma)
const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM;
struct reservation_object *resv = nvbo->bo.resv;
struct reservation_object_list *fobj;
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
fobj = reservation_object_get_list(resv);
@@ -369,7 +369,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
{
struct nouveau_cli *cli = nouveau_cli(file_priv);
int trycnt = 0;
- int ret, i;
+ int ret = -EINVAL, i;
struct nouveau_bo *res_bo = NULL;
LIST_HEAD(gart_list);
LIST_HEAD(vram_list);
@@ -861,6 +861,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
struct nouveau_bo *nvbo;
bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE);
+ long lret;
int ret;
gem = drm_gem_object_lookup(file_priv, req->handle);
@@ -868,19 +869,15 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
return -ENOENT;
nvbo = nouveau_gem_object(gem);
- if (no_wait)
- ret = reservation_object_test_signaled_rcu(nvbo->bo.resv, write) ? 0 : -EBUSY;
- else {
- long lret;
+ lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true,
+ no_wait ? 0 : 30 * HZ);
+ if (!lret)
+ ret = -EBUSY;
+ else if (lret > 0)
+ ret = 0;
+ else
+ ret = lret;
- lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, 30 * HZ);
- if (!lret)
- ret = -EBUSY;
- else if (lret > 0)
- ret = 0;
- else
- ret = lret;
- }
nouveau_bo_sync_for_cpu(nvbo);
drm_gem_object_unreference_unlocked(gem);
diff --git a/drivers/gpu/drm/nouveau/nouveau_led.c b/drivers/gpu/drm/nouveau/nouveau_led.c
new file mode 100644
index 000000000000..3e2f1b6cd4df
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_led.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 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 (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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 <martin.peres@free.fr>
+ */
+
+#include <linux/leds.h>
+
+#include "nouveau_led.h"
+#include <nvkm/subdev/gpio.h>
+
+static enum led_brightness
+nouveau_led_get_brightness(struct led_classdev *led)
+{
+ struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev;
+ struct nouveau_drm *drm = nouveau_drm(drm_dev);
+ struct nvif_object *device = &drm->device.object;
+ u32 div, duty;
+
+ div = nvif_rd32(device, 0x61c880) & 0x00ffffff;
+ duty = nvif_rd32(device, 0x61c884) & 0x00ffffff;
+
+ if (div > 0)
+ return duty * LED_FULL / div;
+ else
+ return 0;
+}
+
+static void
+nouveau_led_set_brightness(struct led_classdev *led, enum led_brightness value)
+{
+ struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev;
+ struct nouveau_drm *drm = nouveau_drm(drm_dev);
+ struct nvif_object *device = &drm->device.object;
+
+ u32 input_clk = 27e6; /* PDISPLAY.SOR[1].PWM is connected to the crystal */
+ u32 freq = 100; /* this is what nvidia uses and it should be good-enough */
+ u32 div, duty;
+
+ div = input_clk / freq;
+ duty = value * div / LED_FULL;
+
+ /* for now, this is safe to directly poke those registers because:
+ * - A: nvidia never puts the logo led to any other PWM controler
+ * than PDISPLAY.SOR[1].PWM.
+ * - B: nouveau does not touch these registers anywhere else
+ */
+ nvif_wr32(device, 0x61c880, div);
+ nvif_wr32(device, 0x61c884, 0xc0000000 | duty);
+}
+
+
+int
+nouveau_led_init(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nvkm_gpio *gpio = nvxx_gpio(&drm->device);
+ struct dcb_gpio_func logo_led;
+ int ret;
+
+ if (!gpio)
+ return 0;
+
+ /* check that there is a GPIO controlling the logo LED */
+ if (nvkm_gpio_find(gpio, 0, DCB_GPIO_LOGO_LED_PWM, 0xff, &logo_led))
+ return 0;
+
+ drm->led = kzalloc(sizeof(*drm->led), GFP_KERNEL);
+ if (!drm->led)
+ return -ENOMEM;
+ drm->led->dev = dev;
+
+ drm->led->led.name = "nvidia-logo";
+ drm->led->led.max_brightness = 255;
+ drm->led->led.brightness_get = nouveau_led_get_brightness;
+ drm->led->led.brightness_set = nouveau_led_set_brightness;
+
+ ret = led_classdev_register(dev->dev, &drm->led->led);
+ if (ret) {
+ kfree(drm->led);
+ return ret;
+ }
+
+ return 0;
+}
+
+void
+nouveau_led_suspend(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+
+ if (drm->led)
+ led_classdev_suspend(&drm->led->led);
+}
+
+void
+nouveau_led_resume(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+
+ if (drm->led)
+ led_classdev_resume(&drm->led->led);
+}
+
+void
+nouveau_led_fini(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+
+ if (drm->led) {
+ led_classdev_unregister(&drm->led->led);
+ kfree(drm->led);
+ drm->led = NULL;
+ }
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_led.h b/drivers/gpu/drm/nouveau/nouveau_led.h
new file mode 100644
index 000000000000..187ecdb82002
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_led.h
@@ -0,0 +1,57 @@
+/*
+ * 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 <martin.peres@free.fr>
+ */
+
+#ifndef __NOUVEAU_LED_H__
+#define __NOUVEAU_LED_H__
+
+#include "nouveau_drv.h"
+
+struct led_classdev;
+
+struct nouveau_led {
+ struct drm_device *dev;
+
+ struct led_classdev led;
+};
+
+static inline struct nouveau_led *
+nouveau_led(struct drm_device *dev)
+{
+ return nouveau_drm(dev)->led;
+}
+
+/* nouveau_led.c */
+#if IS_ENABLED(CONFIG_LEDS_CLASS)
+int nouveau_led_init(struct drm_device *dev);
+void nouveau_led_suspend(struct drm_device *dev);
+void nouveau_led_resume(struct drm_device *dev);
+void nouveau_led_fini(struct drm_device *dev);
+#else
+static inline int nouveau_led_init(struct drm_device *dev) { return 0; };
+static inline void nouveau_led_suspend(struct drm_device *dev) { };
+static inline void nouveau_led_resume(struct drm_device *dev) { };
+static inline void nouveau_led_fini(struct drm_device *dev) { };
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index da8fd5ff9d0f..6a2b187e3c3b 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -30,7 +30,7 @@ int
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -50,7 +50,7 @@ int
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -77,7 +77,7 @@ int
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
uint32_t fg;
uint32_t bg;
@@ -133,7 +133,7 @@ int
nv04_fbcon_accel_init(struct fb_info *info)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct drm_device *dev = nfbdev->dev;
+ struct drm_device *dev = nfbdev->helper.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
struct nvif_device *device = &drm->device;
diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c
index 1915b7b82a59..fa8f2375c398 100644
--- a/drivers/gpu/drm/nouveau/nv04_fence.c
+++ b/drivers/gpu/drm/nouveau/nv04_fence.c
@@ -110,6 +110,6 @@ nv04_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv04_fence_context_new;
priv->base.context_del = nv04_fence_context_del;
priv->base.contexts = 15;
- priv->base.context_base = fence_context_alloc(priv->base.contexts);
+ priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c
index 4e3de34ff6f4..2998bde29211 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.c
+++ b/drivers/gpu/drm/nouveau/nv10_fence.c
@@ -57,16 +57,13 @@ void
nv10_fence_context_del(struct nouveau_channel *chan)
{
struct nv10_fence_chan *fctx = chan->fence;
- int i;
nouveau_fence_context_del(&fctx->base);
- for (i = 0; i < ARRAY_SIZE(fctx->head); i++)
- nvif_object_fini(&fctx->head[i]);
nvif_object_fini(&fctx->sema);
chan->fence = NULL;
nouveau_fence_context_free(&fctx->base);
}
-int
+static int
nv10_fence_context_new(struct nouveau_channel *chan)
{
struct nv10_fence_chan *fctx;
@@ -107,7 +104,7 @@ nv10_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv10_fence_context_new;
priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 31;
- priv->base.context_base = fence_context_alloc(priv->base.contexts);
+ priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.h b/drivers/gpu/drm/nouveau/nv10_fence.h
index a87259f3983a..b7a508585304 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.h
+++ b/drivers/gpu/drm/nouveau/nv10_fence.h
@@ -7,7 +7,6 @@
struct nv10_fence_chan {
struct nouveau_fence_chan base;
struct nvif_object sema;
- struct nvif_object head[4];
};
struct nv10_fence_priv {
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c
index 7d5e562a55c5..79bc01111351 100644
--- a/drivers/gpu/drm/nouveau/nv17_fence.c
+++ b/drivers/gpu/drm/nouveau/nv17_fence.c
@@ -126,7 +126,7 @@ nv17_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv17_fence_context_new;
priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 31;
- priv->base.context_base = fence_context_alloc(priv->base.contexts);
+ priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock);
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7d0edcbcfca7..2c2c64507661 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -25,10 +25,12 @@
#include <linux/dma-mapping.h>
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_plane_helper.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
@@ -38,6 +40,7 @@
#include <nvif/cl507c.h>
#include <nvif/cl507d.h>
#include <nvif/cl507e.h>
+#include <nvif/event.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
@@ -46,6 +49,7 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include "nouveau_fence.h"
+#include "nouveau_fbcon.h"
#include "nv50_display.h"
#define EVO_DMA_NR 9
@@ -61,6 +65,227 @@
#define EVO_MAST_NTFY EVO_SYNC( 0, 0x00)
#define EVO_FLIP_SEM0(c) EVO_SYNC((c) + 1, 0x00)
#define EVO_FLIP_SEM1(c) EVO_SYNC((c) + 1, 0x10)
+#define EVO_FLIP_NTFY0(c) EVO_SYNC((c) + 1, 0x20)
+#define EVO_FLIP_NTFY1(c) EVO_SYNC((c) + 1, 0x30)
+
+/******************************************************************************
+ * Atomic state
+ *****************************************************************************/
+#define nv50_atom(p) container_of((p), struct nv50_atom, state)
+
+struct nv50_atom {
+ struct drm_atomic_state state;
+
+ struct list_head outp;
+ bool lock_core;
+ bool flush_disable;
+};
+
+struct nv50_outp_atom {
+ struct list_head head;
+
+ struct drm_encoder *encoder;
+ bool flush_disable;
+
+ union {
+ struct {
+ bool ctrl:1;
+ };
+ u8 mask;
+ } clr;
+
+ union {
+ struct {
+ bool ctrl:1;
+ };
+ u8 mask;
+ } set;
+};
+
+#define nv50_head_atom(p) container_of((p), struct nv50_head_atom, state)
+
+struct nv50_head_atom {
+ struct drm_crtc_state state;
+
+ struct {
+ u16 iW;
+ u16 iH;
+ u16 oW;
+ u16 oH;
+ } view;
+
+ struct nv50_head_mode {
+ bool interlace;
+ u32 clock;
+ struct {
+ u16 active;
+ u16 synce;
+ u16 blanke;
+ u16 blanks;
+ } h;
+ struct {
+ u32 active;
+ u16 synce;
+ u16 blanke;
+ u16 blanks;
+ u16 blank2s;
+ u16 blank2e;
+ u16 blankus;
+ } v;
+ } mode;
+
+ struct {
+ u32 handle;
+ u64 offset:40;
+ } lut;
+
+ struct {
+ bool visible;
+ u32 handle;
+ u64 offset:40;
+ u8 format;
+ u8 kind:7;
+ u8 layout:1;
+ u8 block:4;
+ u32 pitch:20;
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+ } core;
+
+ struct {
+ bool visible;
+ u32 handle;
+ u64 offset:40;
+ u8 layout:1;
+ u8 format:1;
+ } curs;
+
+ struct {
+ u8 depth;
+ u8 cpp;
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+ } base;
+
+ struct {
+ u8 cpp;
+ } ovly;
+
+ struct {
+ bool enable:1;
+ u8 bits:2;
+ u8 mode:4;
+ } dither;
+
+ struct {
+ struct {
+ u16 cos:12;
+ u16 sin:12;
+ } sat;
+ } procamp;
+
+ union {
+ struct {
+ bool core:1;
+ bool curs:1;
+ };
+ u8 mask;
+ } clr;
+
+ union {
+ struct {
+ bool core:1;
+ bool curs:1;
+ bool view:1;
+ bool mode:1;
+ bool base:1;
+ bool ovly:1;
+ bool dither:1;
+ bool procamp:1;
+ };
+ u16 mask;
+ } set;
+};
+
+static inline struct nv50_head_atom *
+nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+ struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(statec))
+ return (void *)statec;
+ return nv50_head_atom(statec);
+}
+
+#define nv50_wndw_atom(p) container_of((p), struct nv50_wndw_atom, state)
+
+struct nv50_wndw_atom {
+ struct drm_plane_state state;
+ u8 interval;
+
+ struct drm_rect clip;
+
+ struct {
+ u32 handle;
+ u16 offset:12;
+ bool awaken:1;
+ } ntfy;
+
+ struct {
+ u32 handle;
+ u16 offset:12;
+ u32 acquire;
+ u32 release;
+ } sema;
+
+ struct {
+ u8 enable:2;
+ } lut;
+
+ struct {
+ u8 mode:2;
+ u8 interval:4;
+
+ u8 format;
+ u8 kind:7;
+ u8 layout:1;
+ u8 block:4;
+ u32 pitch:20;
+ u16 w;
+ u16 h;
+
+ u32 handle;
+ u64 offset;
+ } image;
+
+ struct {
+ u16 x;
+ u16 y;
+ } point;
+
+ union {
+ struct {
+ bool ntfy:1;
+ bool sema:1;
+ bool image:1;
+ };
+ u8 mask;
+ } clr;
+
+ union {
+ struct {
+ bool ntfy:1;
+ bool sema:1;
+ bool image:1;
+ bool lut:1;
+ bool point:1;
+ };
+ u8 mask;
+ } set;
+};
/******************************************************************************
* EVO channel
@@ -133,34 +358,6 @@ nv50_pioc_create(struct nvif_device *device, struct nvif_object *disp,
}
/******************************************************************************
- * Cursor Immediate
- *****************************************************************************/
-
-struct nv50_curs {
- struct nv50_pioc base;
-};
-
-static int
-nv50_curs_create(struct nvif_device *device, struct nvif_object *disp,
- int head, struct nv50_curs *curs)
-{
- struct nv50_disp_cursor_v0 args = {
- .head = head,
- };
- static const s32 oclass[] = {
- GK104_DISP_CURSOR,
- GF110_DISP_CURSOR,
- GT214_DISP_CURSOR,
- G82_DISP_CURSOR,
- NV50_DISP_CURSOR,
- 0
- };
-
- return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args),
- &curs->base);
-}
-
-/******************************************************************************
* Overlay Immediate
*****************************************************************************/
@@ -192,6 +389,11 @@ nv50_oimm_create(struct nvif_device *device, struct nvif_object *disp,
* DMA EVO channel
*****************************************************************************/
+struct nv50_dmac_ctxdma {
+ struct list_head head;
+ struct nvif_object object;
+};
+
struct nv50_dmac {
struct nv50_chan base;
dma_addr_t handle;
@@ -199,6 +401,7 @@ struct nv50_dmac {
struct nvif_object sync;
struct nvif_object vram;
+ struct list_head ctxdma;
/* Protects against concurrent pushbuf access to this channel, lock is
* grabbed by evo_wait (if the pushbuf reservation is successful) and
@@ -207,9 +410,82 @@ struct nv50_dmac {
};
static void
+nv50_dmac_ctxdma_del(struct nv50_dmac_ctxdma *ctxdma)
+{
+ nvif_object_fini(&ctxdma->object);
+ list_del(&ctxdma->head);
+ kfree(ctxdma);
+}
+
+static struct nv50_dmac_ctxdma *
+nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb)
+{
+ struct nouveau_drm *drm = nouveau_drm(fb->base.dev);
+ struct nv50_dmac_ctxdma *ctxdma;
+ const u8 kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
+ const u32 handle = 0xfb000000 | kind;
+ struct {
+ struct nv_dma_v0 base;
+ union {
+ struct nv50_dma_v0 nv50;
+ struct gf100_dma_v0 gf100;
+ struct gf119_dma_v0 gf119;
+ };
+ } args = {};
+ u32 argc = sizeof(args.base);
+ int ret;
+
+ list_for_each_entry(ctxdma, &dmac->ctxdma, head) {
+ if (ctxdma->object.handle == handle)
+ return ctxdma;
+ }
+
+ if (!(ctxdma = kzalloc(sizeof(*ctxdma), GFP_KERNEL)))
+ return ERR_PTR(-ENOMEM);
+ list_add(&ctxdma->head, &dmac->ctxdma);
+
+ args.base.target = NV_DMA_V0_TARGET_VRAM;
+ args.base.access = NV_DMA_V0_ACCESS_RDWR;
+ args.base.start = 0;
+ args.base.limit = drm->device.info.ram_user - 1;
+
+ if (drm->device.info.chipset < 0x80) {
+ args.nv50.part = NV50_DMA_V0_PART_256;
+ argc += sizeof(args.nv50);
+ } else
+ if (drm->device.info.chipset < 0xc0) {
+ args.nv50.part = NV50_DMA_V0_PART_256;
+ args.nv50.kind = kind;
+ argc += sizeof(args.nv50);
+ } else
+ if (drm->device.info.chipset < 0xd0) {
+ args.gf100.kind = kind;
+ argc += sizeof(args.gf100);
+ } else {
+ args.gf119.page = GF119_DMA_V0_PAGE_LP;
+ args.gf119.kind = kind;
+ argc += sizeof(args.gf119);
+ }
+
+ ret = nvif_object_init(&dmac->base.user, handle, NV_DMA_IN_MEMORY,
+ &args, argc, &ctxdma->object);
+ if (ret) {
+ nv50_dmac_ctxdma_del(ctxdma);
+ return ERR_PTR(ret);
+ }
+
+ return ctxdma;
+}
+
+static void
nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp)
{
struct nvif_device *device = dmac->base.device;
+ struct nv50_dmac_ctxdma *ctxdma, *ctxtmp;
+
+ list_for_each_entry_safe(ctxdma, ctxtmp, &dmac->ctxdma, head) {
+ nv50_dmac_ctxdma_del(ctxdma);
+ }
nvif_object_fini(&dmac->vram);
nvif_object_fini(&dmac->sync);
@@ -278,6 +554,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
if (ret)
return ret;
+ INIT_LIST_HEAD(&dmac->ctxdma);
return ret;
}
@@ -297,7 +574,7 @@ nv50_core_create(struct nvif_device *device, struct nvif_object *disp,
.pushbuf = 0xb0007d00,
};
static const s32 oclass[] = {
- GP104_DISP_CORE_CHANNEL_DMA,
+ GP102_DISP_CORE_CHANNEL_DMA,
GP100_DISP_CORE_CHANNEL_DMA,
GM200_DISP_CORE_CHANNEL_DMA,
GM107_DISP_CORE_CHANNEL_DMA,
@@ -381,34 +658,23 @@ nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp,
struct nv50_head {
struct nouveau_crtc base;
- struct nouveau_bo *image;
- struct nv50_curs curs;
- struct nv50_sync sync;
struct nv50_ovly ovly;
struct nv50_oimm oimm;
};
#define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c))
-#define nv50_curs(c) (&nv50_head(c)->curs)
-#define nv50_sync(c) (&nv50_head(c)->sync)
#define nv50_ovly(c) (&nv50_head(c)->ovly)
#define nv50_oimm(c) (&nv50_head(c)->oimm)
#define nv50_chan(c) (&(c)->base.base)
#define nv50_vers(c) nv50_chan(c)->user.oclass
-struct nv50_fbdma {
- struct list_head head;
- struct nvif_object core;
- struct nvif_object base[4];
-};
-
struct nv50_disp {
struct nvif_object *disp;
struct nv50_mast mast;
- struct list_head fbdma;
-
struct nouveau_bo *sync;
+
+ struct mutex mutex;
};
static struct nv50_disp *
@@ -419,12 +685,6 @@ nv50_disp(struct drm_device *dev)
#define nv50_mast(d) (&nv50_disp(d)->mast)
-static struct drm_crtc *
-nv50_display_crtc_get(struct drm_encoder *encoder)
-{
- return nouveau_encoder(encoder)->crtc;
-}
-
/******************************************************************************
* EVO channel helpers
*****************************************************************************/
@@ -463,812 +723,1465 @@ evo_kick(u32 *push, void *evoc)
mutex_unlock(&dmac->lock);
}
-#if 1
-#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
-#define evo_data(p,d) *((p)++) = (d)
-#else
#define evo_mthd(p,m,s) do { \
const u32 _m = (m), _s = (s); \
- printk(KERN_ERR "%04x %d %s\n", _m, _s, __func__); \
+ if (drm_debug & DRM_UT_KMS) \
+ printk(KERN_ERR "%04x %d %s\n", _m, _s, __func__); \
*((p)++) = ((_s << 18) | _m); \
} while(0)
+
#define evo_data(p,d) do { \
const u32 _d = (d); \
- printk(KERN_ERR "\t%08x\n", _d); \
+ if (drm_debug & DRM_UT_KMS) \
+ printk(KERN_ERR "\t%08x\n", _d); \
*((p)++) = _d; \
} while(0)
-#endif
-static bool
-evo_sync_wait(void *data)
+/******************************************************************************
+ * Plane
+ *****************************************************************************/
+#define nv50_wndw(p) container_of((p), struct nv50_wndw, plane)
+
+struct nv50_wndw {
+ const struct nv50_wndw_func *func;
+ struct nv50_dmac *dmac;
+
+ struct drm_plane plane;
+
+ struct nvif_notify notify;
+ u16 ntfy;
+ u16 sema;
+ u32 data;
+};
+
+struct nv50_wndw_func {
+ void *(*dtor)(struct nv50_wndw *);
+ int (*acquire)(struct nv50_wndw *, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh);
+ void (*release)(struct nv50_wndw *, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh);
+ void (*prepare)(struct nv50_wndw *, struct nv50_head_atom *asyh,
+ struct nv50_wndw_atom *asyw);
+
+ void (*sema_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*sema_clr)(struct nv50_wndw *);
+ void (*ntfy_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*ntfy_clr)(struct nv50_wndw *);
+ int (*ntfy_wait_begun)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*image_clr)(struct nv50_wndw *);
+ void (*lut)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
+
+ u32 (*update)(struct nv50_wndw *, u32 interlock);
+};
+
+static int
+nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
- if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000)
- return true;
- usleep_range(1, 2);
- return false;
+ if (asyw->set.ntfy)
+ return wndw->func->ntfy_wait_begun(wndw, asyw);
+ return 0;
}
-static int
-evo_sync(struct drm_device *dev)
+static u32
+nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush,
+ struct nv50_wndw_atom *asyw)
{
- struct nvif_device *device = &nouveau_drm(dev)->device;
- struct nv50_disp *disp = nv50_disp(dev);
- struct nv50_mast *mast = nv50_mast(dev);
- u32 *push = evo_wait(mast, 8);
- if (push) {
- nouveau_bo_wr32(disp->sync, EVO_MAST_NTFY, 0x00000000);
- evo_mthd(push, 0x0084, 1);
- evo_data(push, 0x80000000 | EVO_MAST_NTFY);
- evo_mthd(push, 0x0080, 2);
- evo_data(push, 0x00000000);
- evo_data(push, 0x00000000);
- evo_kick(push, mast);
- if (nvif_msec(device, 2000,
- if (evo_sync_wait(disp->sync))
- break;
- ) >= 0)
- return 0;
+ if (asyw->clr.sema && (!asyw->set.sema || flush))
+ wndw->func->sema_clr(wndw);
+ if (asyw->clr.ntfy && (!asyw->set.ntfy || flush))
+ wndw->func->ntfy_clr(wndw);
+ if (asyw->clr.image && (!asyw->set.image || flush))
+ wndw->func->image_clr(wndw);
+
+ return flush ? wndw->func->update(wndw, interlock) : 0;
+}
+
+static u32
+nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock,
+ struct nv50_wndw_atom *asyw)
+{
+ if (interlock) {
+ asyw->image.mode = 0;
+ asyw->image.interval = 1;
}
- return -EBUSY;
+ if (asyw->set.sema ) wndw->func->sema_set (wndw, asyw);
+ if (asyw->set.ntfy ) wndw->func->ntfy_set (wndw, asyw);
+ if (asyw->set.image) wndw->func->image_set(wndw, asyw);
+ if (asyw->set.lut ) wndw->func->lut (wndw, asyw);
+ if (asyw->set.point) wndw->func->point (wndw, asyw);
+
+ return wndw->func->update(wndw, interlock);
}
-/******************************************************************************
- * Page flipping channel
- *****************************************************************************/
-struct nouveau_bo *
-nv50_display_crtc_sema(struct drm_device *dev, int crtc)
+static void
+nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
+ struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
{
- return nv50_disp(dev)->sync;
+ struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+ NV_ATOMIC(drm, "%s release\n", wndw->plane.name);
+ wndw->func->release(wndw, asyw, asyh);
+ asyw->ntfy.handle = 0;
+ asyw->sema.handle = 0;
}
-struct nv50_display_flip {
- struct nv50_disp *disp;
- struct nv50_sync *chan;
-};
-
-static bool
-nv50_display_flip_wait(void *data)
+static int
+nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
+ struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
{
- struct nv50_display_flip *flip = data;
- if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
- flip->chan->data)
- return true;
- usleep_range(1, 2);
- return false;
+ struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
+ struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+ int ret;
+
+ NV_ATOMIC(drm, "%s acquire\n", wndw->plane.name);
+ asyw->clip.x1 = 0;
+ asyw->clip.y1 = 0;
+ asyw->clip.x2 = asyh->state.mode.hdisplay;
+ asyw->clip.y2 = asyh->state.mode.vdisplay;
+
+ asyw->image.w = fb->base.width;
+ asyw->image.h = fb->base.height;
+ asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
+ if (asyw->image.kind) {
+ asyw->image.layout = 0;
+ if (drm->device.info.chipset >= 0xc0)
+ asyw->image.block = fb->nvbo->tile_mode >> 4;
+ else
+ asyw->image.block = fb->nvbo->tile_mode;
+ asyw->image.pitch = (fb->base.pitches[0] / 4) << 4;
+ } else {
+ asyw->image.layout = 1;
+ asyw->image.block = 0;
+ asyw->image.pitch = fb->base.pitches[0];
+ }
+
+ ret = wndw->func->acquire(wndw, asyw, asyh);
+ if (ret)
+ return ret;
+
+ if (asyw->set.image) {
+ if (!(asyw->image.mode = asyw->interval ? 0 : 1))
+ asyw->image.interval = asyw->interval;
+ else
+ asyw->image.interval = 0;
+ }
+
+ return 0;
}
-void
-nv50_display_flip_stop(struct drm_crtc *crtc)
+static int
+nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
{
- struct nvif_device *device = &nouveau_drm(crtc->dev)->device;
- struct nv50_display_flip flip = {
- .disp = nv50_disp(crtc->dev),
- .chan = nv50_sync(crtc),
- };
- u32 *push;
+ struct nouveau_drm *drm = nouveau_drm(plane->dev);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ struct nv50_wndw_atom *armw = nv50_wndw_atom(wndw->plane.state);
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+ struct nv50_head_atom *harm = NULL, *asyh = NULL;
+ bool varm = false, asyv = false, asym = false;
+ int ret;
- push = evo_wait(flip.chan, 8);
- if (push) {
- evo_mthd(push, 0x0084, 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0094, 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x00c0, 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
- evo_kick(push, flip.chan);
+ NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
+ if (asyw->state.crtc) {
+ asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+ if (IS_ERR(asyh))
+ return PTR_ERR(asyh);
+ asym = drm_atomic_crtc_needs_modeset(&asyh->state);
+ asyv = asyh->state.active;
}
- nvif_msec(device, 2000,
- if (nv50_display_flip_wait(&flip))
- break;
- );
+ if (armw->state.crtc) {
+ harm = nv50_head_atom_get(asyw->state.state, armw->state.crtc);
+ if (IS_ERR(harm))
+ return PTR_ERR(harm);
+ varm = harm->state.crtc->state->active;
+ }
+
+ if (asyv) {
+ asyw->point.x = asyw->state.crtc_x;
+ asyw->point.y = asyw->state.crtc_y;
+ if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point)))
+ asyw->set.point = true;
+
+ if (!varm || asym || armw->state.fb != asyw->state.fb) {
+ ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
+ if (ret)
+ return ret;
+ }
+ } else
+ if (varm) {
+ nv50_wndw_atomic_check_release(wndw, asyw, harm);
+ } else {
+ return 0;
+ }
+
+ if (!asyv || asym) {
+ asyw->clr.ntfy = armw->ntfy.handle != 0;
+ asyw->clr.sema = armw->sema.handle != 0;
+ if (wndw->func->image_clr)
+ asyw->clr.image = armw->image.handle != 0;
+ asyw->set.lut = wndw->func->lut && asyv;
+ }
+
+ return 0;
}
-int
-nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
- struct nouveau_channel *chan, u32 swap_interval)
+static void
+nv50_wndw_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state)
{
- struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct nv50_head *head = nv50_head(crtc);
- struct nv50_sync *sync = nv50_sync(crtc);
- u32 *push;
- int ret;
+ struct nouveau_framebuffer *fb = nouveau_framebuffer(old_state->fb);
+ struct nouveau_drm *drm = nouveau_drm(plane->dev);
- if (crtc->primary->fb->width != fb->width ||
- crtc->primary->fb->height != fb->height)
- return -EINVAL;
+ NV_ATOMIC(drm, "%s cleanup: %p\n", plane->name, old_state->fb);
+ if (!old_state->fb)
+ return;
+
+ nouveau_bo_unpin(fb->nvbo);
+}
- swap_interval <<= 4;
- if (swap_interval == 0)
- swap_interval |= 0x100;
- if (chan == NULL)
- evo_sync(crtc->dev);
+static int
+nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
+{
+ struct nouveau_framebuffer *fb = nouveau_framebuffer(state->fb);
+ struct nouveau_drm *drm = nouveau_drm(plane->dev);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+ struct nv50_head_atom *asyh;
+ struct nv50_dmac_ctxdma *ctxdma;
+ int ret;
- push = evo_wait(sync, 128);
- if (unlikely(push == NULL))
- return -EBUSY;
+ NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, state->fb);
+ if (!asyw->state.fb)
+ return 0;
- if (chan && chan->user.oclass < G82_CHANNEL_GPFIFO) {
- ret = RING_SPACE(chan, 8);
- if (ret)
- return ret;
+ ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM, true);
+ if (ret)
+ return ret;
- BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
- OUT_RING (chan, NvEvoSema0 + nv_crtc->index);
- OUT_RING (chan, sync->addr ^ 0x10);
- BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
- OUT_RING (chan, sync->data + 1);
- BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2);
- OUT_RING (chan, sync->addr);
- OUT_RING (chan, sync->data);
- } else
- if (chan && chan->user.oclass < FERMI_CHANNEL_GPFIFO) {
- u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
- ret = RING_SPACE(chan, 12);
- if (ret)
- return ret;
+ ctxdma = nv50_dmac_ctxdma_new(wndw->dmac, fb);
+ if (IS_ERR(ctxdma)) {
+ nouveau_bo_unpin(fb->nvbo);
+ return PTR_ERR(ctxdma);
+ }
- BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
- OUT_RING (chan, chan->vram.handle);
- BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
- OUT_RING (chan, upper_32_bits(addr ^ 0x10));
- OUT_RING (chan, lower_32_bits(addr ^ 0x10));
- OUT_RING (chan, sync->data + 1);
- OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
- BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
- OUT_RING (chan, upper_32_bits(addr));
- OUT_RING (chan, lower_32_bits(addr));
- OUT_RING (chan, sync->data);
- OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
- } else
- if (chan) {
- u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
- ret = RING_SPACE(chan, 10);
- if (ret)
- return ret;
+ asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv);
+ asyw->image.handle = ctxdma->object.handle;
+ asyw->image.offset = fb->nvbo->bo.offset;
- BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
- OUT_RING (chan, upper_32_bits(addr ^ 0x10));
- OUT_RING (chan, lower_32_bits(addr ^ 0x10));
- OUT_RING (chan, sync->data + 1);
- OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG |
- NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
- BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
- OUT_RING (chan, upper_32_bits(addr));
- OUT_RING (chan, lower_32_bits(addr));
- OUT_RING (chan, sync->data);
- OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL |
- NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
- }
-
- if (chan) {
- sync->addr ^= 0x10;
- sync->data++;
- FIRE_RING (chan);
- }
-
- /* queue the flip */
- evo_mthd(push, 0x0100, 1);
- evo_data(push, 0xfffe0000);
- evo_mthd(push, 0x0084, 1);
- evo_data(push, swap_interval);
- if (!(swap_interval & 0x00000100)) {
- evo_mthd(push, 0x00e0, 1);
- evo_data(push, 0x40000000);
- }
- evo_mthd(push, 0x0088, 4);
- evo_data(push, sync->addr);
- evo_data(push, sync->data++);
- evo_data(push, sync->data);
- evo_data(push, sync->base.sync.handle);
- evo_mthd(push, 0x00a0, 2);
- evo_data(push, 0x00000000);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x00c0, 1);
- evo_data(push, nv_fb->r_handle);
- evo_mthd(push, 0x0110, 2);
- evo_data(push, 0x00000000);
- evo_data(push, 0x00000000);
- if (nv50_vers(sync) < GF110_DISP_BASE_CHANNEL_DMA) {
- evo_mthd(push, 0x0800, 5);
- evo_data(push, nv_fb->nvbo->bo.offset >> 8);
- evo_data(push, 0);
- evo_data(push, (fb->height << 16) | fb->width);
- evo_data(push, nv_fb->r_pitch);
- evo_data(push, nv_fb->r_format);
- } else {
- evo_mthd(push, 0x0400, 5);
- evo_data(push, nv_fb->nvbo->bo.offset >> 8);
- evo_data(push, 0);
- evo_data(push, (fb->height << 16) | fb->width);
- evo_data(push, nv_fb->r_pitch);
- evo_data(push, nv_fb->r_format);
+ if (wndw->func->prepare) {
+ asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+ if (IS_ERR(asyh))
+ return PTR_ERR(asyh);
+
+ wndw->func->prepare(wndw, asyh, asyw);
}
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
- evo_kick(push, sync);
- nouveau_bo_ref(nv_fb->nvbo, &head->image);
+ return 0;
+}
+
+static const struct drm_plane_helper_funcs
+nv50_wndw_helper = {
+ .prepare_fb = nv50_wndw_prepare_fb,
+ .cleanup_fb = nv50_wndw_cleanup_fb,
+ .atomic_check = nv50_wndw_atomic_check,
+};
+
+static void
+nv50_wndw_atomic_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+ __drm_atomic_helper_plane_destroy_state(&asyw->state);
+ dma_fence_put(asyw->state.fence);
+ kfree(asyw);
+}
+
+static struct drm_plane_state *
+nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
+{
+ struct nv50_wndw_atom *armw = nv50_wndw_atom(plane->state);
+ struct nv50_wndw_atom *asyw;
+ if (!(asyw = kmalloc(sizeof(*asyw), GFP_KERNEL)))
+ return NULL;
+ __drm_atomic_helper_plane_duplicate_state(plane, &asyw->state);
+ asyw->state.fence = NULL;
+ asyw->interval = 1;
+ asyw->sema = armw->sema;
+ asyw->ntfy = armw->ntfy;
+ asyw->image = armw->image;
+ asyw->point = armw->point;
+ asyw->lut = armw->lut;
+ asyw->clr.mask = 0;
+ asyw->set.mask = 0;
+ return &asyw->state;
+}
+
+static void
+nv50_wndw_reset(struct drm_plane *plane)
+{
+ struct nv50_wndw_atom *asyw;
+
+ if (WARN_ON(!(asyw = kzalloc(sizeof(*asyw), GFP_KERNEL))))
+ return;
+
+ if (plane->state)
+ plane->funcs->atomic_destroy_state(plane, plane->state);
+ plane->state = &asyw->state;
+ plane->state->plane = plane;
+ plane->state->rotation = DRM_ROTATE_0;
+}
+
+static void
+nv50_wndw_destroy(struct drm_plane *plane)
+{
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ void *data;
+ nvif_notify_fini(&wndw->notify);
+ data = wndw->func->dtor(wndw);
+ drm_plane_cleanup(&wndw->plane);
+ kfree(data);
+}
+
+static const struct drm_plane_funcs
+nv50_wndw = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = nv50_wndw_destroy,
+ .reset = nv50_wndw_reset,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .atomic_duplicate_state = nv50_wndw_atomic_duplicate_state,
+ .atomic_destroy_state = nv50_wndw_atomic_destroy_state,
+};
+
+static void
+nv50_wndw_fini(struct nv50_wndw *wndw)
+{
+ nvif_notify_put(&wndw->notify);
+}
+
+static void
+nv50_wndw_init(struct nv50_wndw *wndw)
+{
+ nvif_notify_get(&wndw->notify);
+}
+
+static int
+nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
+ enum drm_plane_type type, const char *name, int index,
+ struct nv50_dmac *dmac, const u32 *format, int nformat,
+ struct nv50_wndw *wndw)
+{
+ int ret;
+
+ wndw->func = func;
+ wndw->dmac = dmac;
+
+ ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
+ nformat, type, "%s-%d", name, index);
+ if (ret)
+ return ret;
+
+ drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
return 0;
}
/******************************************************************************
- * CRTC
+ * Cursor plane
*****************************************************************************/
+#define nv50_curs(p) container_of((p), struct nv50_curs, wndw)
+
+struct nv50_curs {
+ struct nv50_wndw wndw;
+ struct nvif_object chan;
+};
+
+static u32
+nv50_curs_update(struct nv50_wndw *wndw, u32 interlock)
+{
+ struct nv50_curs *curs = nv50_curs(wndw);
+ nvif_wr32(&curs->chan, 0x0080, 0x00000000);
+ return 0;
+}
+
+static void
+nv50_curs_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ struct nv50_curs *curs = nv50_curs(wndw);
+ nvif_wr32(&curs->chan, 0x0084, (asyw->point.y << 16) | asyw->point.x);
+}
+
+static void
+nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
+ struct nv50_wndw_atom *asyw)
+{
+ asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
+ asyh->curs.offset = asyw->image.offset;
+ asyh->set.curs = asyh->curs.visible;
+}
+
+static void
+nv50_curs_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
+{
+ asyh->curs.visible = false;
+}
+
static int
-nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
+nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- struct nouveau_connector *nv_connector;
- struct drm_connector *connector;
- u32 *push, mode = 0x00;
+ int ret;
- nv_connector = nouveau_crtc_connector_get(nv_crtc);
- connector = &nv_connector->base;
- if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
- if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
- mode = DITHERING_MODE_DYNAMIC2X2;
- } else {
- mode = nv_connector->dithering_mode;
- }
+ ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+ asyh->curs.visible = asyw->state.visible;
+ if (ret || !asyh->curs.visible)
+ return ret;
- if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
- if (connector->display_info.bpc >= 8)
- mode |= DITHERING_DEPTH_8BPC;
- } else {
- mode |= nv_connector->dithering_depth;
+ switch (asyw->state.fb->width) {
+ case 32: asyh->curs.layout = 0; break;
+ case 64: asyh->curs.layout = 1; break;
+ default:
+ return -EINVAL;
}
- push = evo_wait(mast, 4);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x08a0 + (nv_crtc->index * 0x0400), 1);
- evo_data(push, mode);
- } else
- if (nv50_vers(mast) < GK104_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0490 + (nv_crtc->index * 0x0300), 1);
- evo_data(push, mode);
- } else {
- evo_mthd(push, 0x04a0 + (nv_crtc->index * 0x0300), 1);
- evo_data(push, mode);
- }
+ if (asyw->state.fb->width != asyw->state.fb->height)
+ return -EINVAL;
- if (update) {
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
- }
- evo_kick(push, mast);
+ switch (asyw->state.fb->pixel_format) {
+ case DRM_FORMAT_ARGB8888: asyh->curs.format = 1; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
}
return 0;
}
+static void *
+nv50_curs_dtor(struct nv50_wndw *wndw)
+{
+ struct nv50_curs *curs = nv50_curs(wndw);
+ nvif_object_fini(&curs->chan);
+ return curs;
+}
+
+static const u32
+nv50_curs_format[] = {
+ DRM_FORMAT_ARGB8888,
+};
+
+static const struct nv50_wndw_func
+nv50_curs = {
+ .dtor = nv50_curs_dtor,
+ .acquire = nv50_curs_acquire,
+ .release = nv50_curs_release,
+ .prepare = nv50_curs_prepare,
+ .point = nv50_curs_point,
+ .update = nv50_curs_update,
+};
+
static int
-nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
+nv50_curs_new(struct nouveau_drm *drm, struct nv50_head *head,
+ struct nv50_curs **pcurs)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- struct drm_display_mode *omode, *umode = &nv_crtc->base.mode;
- struct drm_crtc *crtc = &nv_crtc->base;
- struct nouveau_connector *nv_connector;
- int mode = DRM_MODE_SCALE_NONE;
- u32 oX, oY, *push;
+ static const struct nvif_mclass curses[] = {
+ { GK104_DISP_CURSOR, 0 },
+ { GF110_DISP_CURSOR, 0 },
+ { GT214_DISP_CURSOR, 0 },
+ { G82_DISP_CURSOR, 0 },
+ { NV50_DISP_CURSOR, 0 },
+ {}
+ };
+ struct nv50_disp_cursor_v0 args = {
+ .head = head->base.index,
+ };
+ struct nv50_disp *disp = nv50_disp(drm->dev);
+ struct nv50_curs *curs;
+ int cid, ret;
+
+ cid = nvif_mclass(disp->disp, curses);
+ if (cid < 0) {
+ NV_ERROR(drm, "No supported cursor immediate class\n");
+ return cid;
+ }
- /* start off at the resolution we programmed the crtc for, this
- * effectively handles NONE/FULL scaling
- */
- nv_connector = nouveau_crtc_connector_get(nv_crtc);
- if (nv_connector && nv_connector->native_mode) {
- mode = nv_connector->scaling_mode;
- if (nv_connector->scaling_full) /* non-EDID LVDS/eDP mode */
- mode = DRM_MODE_SCALE_FULLSCREEN;
+ if (!(curs = *pcurs = kzalloc(sizeof(*curs), GFP_KERNEL)))
+ return -ENOMEM;
+
+ ret = nv50_wndw_ctor(&nv50_curs, drm->dev, DRM_PLANE_TYPE_CURSOR,
+ "curs", head->base.index, &disp->mast.base,
+ nv50_curs_format, ARRAY_SIZE(nv50_curs_format),
+ &curs->wndw);
+ if (ret) {
+ kfree(curs);
+ return ret;
}
- if (mode != DRM_MODE_SCALE_NONE)
- omode = nv_connector->native_mode;
- else
- omode = umode;
+ ret = nvif_object_init(disp->disp, 0, curses[cid].oclass, &args,
+ sizeof(args), &curs->chan);
+ if (ret) {
+ NV_ERROR(drm, "curs%04x allocation failed: %d\n",
+ curses[cid].oclass, ret);
+ return ret;
+ }
- oX = omode->hdisplay;
- oY = omode->vdisplay;
- if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
- oY *= 2;
+ return 0;
+}
- /* add overscan compensation if necessary, will keep the aspect
- * ratio the same as the backend mode unless overridden by the
- * user setting both hborder and vborder properties.
- */
- if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
- (nv_connector->underscan == UNDERSCAN_AUTO &&
- drm_detect_hdmi_monitor(nv_connector->edid)))) {
- u32 bX = nv_connector->underscan_hborder;
- u32 bY = nv_connector->underscan_vborder;
- u32 aspect = (oY << 19) / oX;
+/******************************************************************************
+ * Primary plane
+ *****************************************************************************/
+#define nv50_base(p) container_of((p), struct nv50_base, wndw)
- if (bX) {
- oX -= (bX * 2);
- if (bY) oY -= (bY * 2);
- else oY = ((oX * aspect) + (aspect / 2)) >> 19;
- } else {
- oX -= (oX >> 4) + 32;
- if (bY) oY -= (bY * 2);
- else oY = ((oX * aspect) + (aspect / 2)) >> 19;
- }
+struct nv50_base {
+ struct nv50_wndw wndw;
+ struct nv50_sync chan;
+ int id;
+};
+
+static int
+nv50_base_notify(struct nvif_notify *notify)
+{
+ return NVIF_NOTIFY_KEEP;
+}
+
+static void
+nv50_base_lut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 2))) {
+ evo_mthd(push, 0x00e0, 1);
+ evo_data(push, asyw->lut.enable << 30);
+ evo_kick(push, &base->chan);
}
+}
- /* handle CENTER/ASPECT scaling, taking into account the areas
- * removed already for overscan compensation
- */
- switch (mode) {
- case DRM_MODE_SCALE_CENTER:
- oX = min((u32)umode->hdisplay, oX);
- oY = min((u32)umode->vdisplay, oY);
- /* fall-through */
- case DRM_MODE_SCALE_ASPECT:
- if (oY < oX) {
- u32 aspect = (umode->hdisplay << 19) / umode->vdisplay;
- oX = ((oY * aspect) + (aspect / 2)) >> 19;
- } else {
- u32 aspect = (umode->vdisplay << 19) / umode->hdisplay;
- oY = ((oX * aspect) + (aspect / 2)) >> 19;
- }
- break;
- default:
- break;
+static void
+nv50_base_image_clr(struct nv50_wndw *wndw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 4))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &base->chan);
}
+}
- push = evo_wait(mast, 8);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- /*XXX: SCALE_CTRL_ACTIVE??? */
- evo_mthd(push, 0x08d8 + (nv_crtc->index * 0x400), 2);
- evo_data(push, (oY << 16) | oX);
- evo_data(push, (oY << 16) | oX);
- evo_mthd(push, 0x08a4 + (nv_crtc->index * 0x400), 1);
+static void
+nv50_base_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ const s32 oclass = base->chan.base.base.user.oclass;
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 10))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, (asyw->image.mode << 8) |
+ (asyw->image.interval << 4));
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, asyw->image.handle);
+ if (oclass < G82_DISP_BASE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0800, 5);
+ evo_data(push, asyw->image.offset >> 8);
+ evo_data(push, 0x00000000);
+ evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+ evo_data(push, (asyw->image.layout << 20) |
+ asyw->image.pitch |
+ asyw->image.block);
+ evo_data(push, (asyw->image.kind << 16) |
+ (asyw->image.format << 8));
+ } else
+ if (oclass < GF110_DISP_BASE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0800, 5);
+ evo_data(push, asyw->image.offset >> 8);
evo_data(push, 0x00000000);
- evo_mthd(push, 0x08c8 + (nv_crtc->index * 0x400), 1);
- evo_data(push, umode->vdisplay << 16 | umode->hdisplay);
+ evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+ evo_data(push, (asyw->image.layout << 20) |
+ asyw->image.pitch |
+ asyw->image.block);
+ evo_data(push, asyw->image.format << 8);
} else {
- evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
- evo_data(push, (oY << 16) | oX);
- evo_data(push, (oY << 16) | oX);
- evo_data(push, (oY << 16) | oX);
- evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x0400, 5);
+ evo_data(push, asyw->image.offset >> 8);
evo_data(push, 0x00000000);
- evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
- evo_data(push, umode->vdisplay << 16 | umode->hdisplay);
+ evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+ evo_data(push, (asyw->image.layout << 24) |
+ asyw->image.pitch |
+ asyw->image.block);
+ evo_data(push, asyw->image.format << 8);
}
+ evo_kick(push, &base->chan);
+ }
+}
- evo_kick(push, mast);
+static void
+nv50_base_ntfy_clr(struct nv50_wndw *wndw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 2))) {
+ evo_mthd(push, 0x00a4, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &base->chan);
+ }
+}
- if (update) {
- nv50_display_flip_stop(crtc);
- nv50_display_flip_next(crtc, crtc->primary->fb,
- NULL, 1);
- }
+static void
+nv50_base_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 3))) {
+ evo_mthd(push, 0x00a0, 2);
+ evo_data(push, (asyw->ntfy.awaken << 30) | asyw->ntfy.offset);
+ evo_data(push, asyw->ntfy.handle);
+ evo_kick(push, &base->chan);
}
+}
- return 0;
+static void
+nv50_base_sema_clr(struct nv50_wndw *wndw)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
+ if ((push = evo_wait(&base->chan, 2))) {
+ evo_mthd(push, 0x0094, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &base->chan);
+ }
}
-static int
-nv50_crtc_set_raster_vblank_dmi(struct nouveau_crtc *nv_crtc, u32 usec)
+static void
+nv50_base_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
+ struct nv50_base *base = nv50_base(wndw);
u32 *push;
+ if ((push = evo_wait(&base->chan, 5))) {
+ evo_mthd(push, 0x0088, 4);
+ evo_data(push, asyw->sema.offset);
+ evo_data(push, asyw->sema.acquire);
+ evo_data(push, asyw->sema.release);
+ evo_data(push, asyw->sema.handle);
+ evo_kick(push, &base->chan);
+ }
+}
- push = evo_wait(mast, 8);
- if (!push)
- return -ENOMEM;
+static u32
+nv50_base_update(struct nv50_wndw *wndw, u32 interlock)
+{
+ struct nv50_base *base = nv50_base(wndw);
+ u32 *push;
- evo_mthd(push, 0x0828 + (nv_crtc->index * 0x400), 1);
- evo_data(push, usec);
- evo_kick(push, mast);
+ if (!(push = evo_wait(&base->chan, 2)))
+ return 0;
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, interlock);
+ evo_kick(push, &base->chan);
+
+ if (base->chan.base.base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA)
+ return interlock ? 2 << (base->id * 8) : 0;
+ return interlock ? 2 << (base->id * 4) : 0;
+}
+
+static int
+nv50_base_ntfy_wait_begun(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+ struct nv50_disp *disp = nv50_disp(wndw->plane.dev);
+ if (nvif_msec(&drm->device, 2000ULL,
+ u32 data = nouveau_bo_rd32(disp->sync, asyw->ntfy.offset / 4);
+ if ((data & 0xc0000000) == 0x40000000)
+ break;
+ usleep_range(1, 2);
+ ) < 0)
+ return -ETIMEDOUT;
return 0;
}
+static void
+nv50_base_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
+{
+ asyh->base.cpp = 0;
+}
+
static int
-nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
+nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- u32 *push, hue, vib;
- int adj;
+ const u32 format = asyw->state.fb->pixel_format;
+ const struct drm_format_info *info;
+ int ret;
- adj = (nv_crtc->color_vibrance > 0) ? 50 : 0;
- vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff;
- hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff;
+ info = drm_format_info(format);
+ if (!info || !info->depth)
+ return -EINVAL;
- push = evo_wait(mast, 16);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x08a8 + (nv_crtc->index * 0x400), 1);
- evo_data(push, (hue << 20) | (vib << 8));
- } else {
- evo_mthd(push, 0x0498 + (nv_crtc->index * 0x300), 1);
- evo_data(push, (hue << 20) | (vib << 8));
- }
+ ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ false, true);
+ if (ret)
+ return ret;
- if (update) {
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
- }
- evo_kick(push, mast);
+ asyh->base.depth = info->depth;
+ asyh->base.cpp = info->cpp[0];
+ asyh->base.x = asyw->state.src.x1 >> 16;
+ asyh->base.y = asyw->state.src.y1 >> 16;
+ asyh->base.w = asyw->state.fb->width;
+ asyh->base.h = asyw->state.fb->height;
+
+ switch (format) {
+ case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break;
+ case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break;
+ case DRM_FORMAT_XRGB1555 :
+ case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break;
+ case DRM_FORMAT_XRGB8888 :
+ case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break;
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break;
+ case DRM_FORMAT_XBGR8888 :
+ case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
}
+ asyw->lut.enable = 1;
+ asyw->set.image = true;
return 0;
}
+static void *
+nv50_base_dtor(struct nv50_wndw *wndw)
+{
+ struct nv50_disp *disp = nv50_disp(wndw->plane.dev);
+ struct nv50_base *base = nv50_base(wndw);
+ nv50_dmac_destroy(&base->chan.base, disp->disp);
+ return base;
+}
+
+static const u32
+nv50_base_format[] = {
+ DRM_FORMAT_C8,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_ABGR8888,
+};
+
+static const struct nv50_wndw_func
+nv50_base = {
+ .dtor = nv50_base_dtor,
+ .acquire = nv50_base_acquire,
+ .release = nv50_base_release,
+ .sema_set = nv50_base_sema_set,
+ .sema_clr = nv50_base_sema_clr,
+ .ntfy_set = nv50_base_ntfy_set,
+ .ntfy_clr = nv50_base_ntfy_clr,
+ .ntfy_wait_begun = nv50_base_ntfy_wait_begun,
+ .image_set = nv50_base_image_set,
+ .image_clr = nv50_base_image_clr,
+ .lut = nv50_base_lut,
+ .update = nv50_base_update,
+};
+
static int
-nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
- int x, int y, bool update)
+nv50_base_new(struct nouveau_drm *drm, struct nv50_head *head,
+ struct nv50_base **pbase)
+{
+ struct nv50_disp *disp = nv50_disp(drm->dev);
+ struct nv50_base *base;
+ int ret;
+
+ if (!(base = *pbase = kzalloc(sizeof(*base), GFP_KERNEL)))
+ return -ENOMEM;
+ base->id = head->base.index;
+ base->wndw.ntfy = EVO_FLIP_NTFY0(base->id);
+ base->wndw.sema = EVO_FLIP_SEM0(base->id);
+ base->wndw.data = 0x00000000;
+
+ ret = nv50_wndw_ctor(&nv50_base, drm->dev, DRM_PLANE_TYPE_PRIMARY,
+ "base", base->id, &base->chan.base,
+ nv50_base_format, ARRAY_SIZE(nv50_base_format),
+ &base->wndw);
+ if (ret) {
+ kfree(base);
+ return ret;
+ }
+
+ ret = nv50_base_create(&drm->device, disp->disp, base->id,
+ disp->sync->bo.offset, &base->chan);
+ if (ret)
+ return ret;
+
+ return nvif_notify_init(&base->chan.base.base.user, nv50_base_notify,
+ false,
+ NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT,
+ &(struct nvif_notify_uevent_req) {},
+ sizeof(struct nvif_notify_uevent_req),
+ sizeof(struct nvif_notify_uevent_rep),
+ &base->wndw.notify);
+}
+
+/******************************************************************************
+ * Head
+ *****************************************************************************/
+static void
+nv50_head_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
+ if ((push = evo_wait(core, 2))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
+ else
+ evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1);
+ evo_data(push, (asyh->procamp.sat.sin << 20) |
+ (asyh->procamp.sat.cos << 8));
+ evo_kick(push, core);
+ }
+}
- push = evo_wait(mast, 16);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0860 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nvfb->nvbo->bo.offset >> 8);
- evo_mthd(push, 0x0868 + (nv_crtc->index * 0x400), 3);
- evo_data(push, (fb->height << 16) | fb->width);
- evo_data(push, nvfb->r_pitch);
- evo_data(push, nvfb->r_format);
- evo_mthd(push, 0x08c0 + (nv_crtc->index * 0x400), 1);
- evo_data(push, (y << 16) | x);
- if (nv50_vers(mast) > NV50_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nvfb->r_handle);
- }
- } else {
- evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
- evo_data(push, nvfb->nvbo->bo.offset >> 8);
- evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
- evo_data(push, (fb->height << 16) | fb->width);
- evo_data(push, nvfb->r_pitch);
- evo_data(push, nvfb->r_format);
- evo_data(push, nvfb->r_handle);
- evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
- evo_data(push, (y << 16) | x);
- }
+static void
+nv50_head_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 2))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
+ else
+ if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
+ else
+ evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
+ evo_data(push, (asyh->dither.mode << 3) |
+ (asyh->dither.bits << 1) |
+ asyh->dither.enable);
+ evo_kick(push, core);
+ }
+}
- if (update) {
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
+static void
+nv50_head_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 bounds = 0;
+ u32 *push;
+
+ if (asyh->base.cpp) {
+ switch (asyh->base.cpp) {
+ case 8: bounds |= 0x00000500; break;
+ case 4: bounds |= 0x00000300; break;
+ case 2: bounds |= 0x00000100; break;
+ default:
+ WARN_ON(1);
+ break;
}
- evo_kick(push, mast);
+ bounds |= 0x00000001;
}
- nv_crtc->fb.handle = nvfb->r_handle;
- return 0;
+ if ((push = evo_wait(core, 2))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
+ else
+ evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
+ evo_data(push, bounds);
+ evo_kick(push, core);
+ }
}
static void
-nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
+nv50_head_base(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- u32 *push = evo_wait(mast, 16);
- if (push) {
- if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
- evo_data(push, 0x85000000);
- evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
- } else
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
- evo_data(push, 0x85000000);
- evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
- evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
- evo_data(push, mast->base.vram.handle);
- } else {
- evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
- evo_data(push, 0x85000000);
- evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
- evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
- evo_data(push, mast->base.vram.handle);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 bounds = 0;
+ u32 *push;
+
+ if (asyh->base.cpp) {
+ switch (asyh->base.cpp) {
+ case 8: bounds |= 0x00000500; break;
+ case 4: bounds |= 0x00000300; break;
+ case 2: bounds |= 0x00000100; break;
+ case 1: bounds |= 0x00000000; break;
+ default:
+ WARN_ON(1);
+ break;
}
- evo_kick(push, mast);
+ bounds |= 0x00000001;
+ }
+
+ if ((push = evo_wait(core, 2))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
+ else
+ evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
+ evo_data(push, bounds);
+ evo_kick(push, core);
}
- nv_crtc->cursor.visible = true;
}
static void
-nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
+nv50_head_curs_clr(struct nv50_head *head)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- u32 *push = evo_wait(mast, 16);
- if (push) {
- if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 4))) {
+ if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
} else
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
- evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
+ evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, 0x00000000);
} else {
- evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
evo_data(push, 0x05000000);
- evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, 0x00000000);
}
- evo_kick(push, mast);
+ evo_kick(push, core);
}
- nv_crtc->cursor.visible = false;
}
static void
-nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update)
+nv50_head_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-
- if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled)
- nv50_crtc_cursor_show(nv_crtc);
- else
- nv50_crtc_cursor_hide(nv_crtc);
-
- if (update) {
- u32 *push = evo_wait(mast, 2);
- if (push) {
- evo_mthd(push, 0x0080, 1);
- evo_data(push, 0x00000000);
- evo_kick(push, mast);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 5))) {
+ if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+ evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+ (asyh->curs.format << 24));
+ evo_data(push, asyh->curs.offset >> 8);
+ } else
+ if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+ evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+ (asyh->curs.format << 24));
+ evo_data(push, asyh->curs.offset >> 8);
+ evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
+ evo_data(push, asyh->curs.handle);
+ } else {
+ evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
+ evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+ (asyh->curs.format << 24));
+ evo_data(push, asyh->curs.offset >> 8);
+ evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
+ evo_data(push, asyh->curs.handle);
}
+ evo_kick(push, core);
}
}
static void
-nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
+nv50_head_core_clr(struct nv50_head *head)
{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 2))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+ evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
+ else
+ evo_mthd(push, 0x0474 + head->base.index * 0x300, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, core);
+ }
}
static void
-nv50_crtc_prepare(struct drm_crtc *crtc)
+nv50_head_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct nv50_mast *mast = nv50_mast(crtc->dev);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
+ if ((push = evo_wait(core, 9))) {
+ if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+ evo_data(push, asyh->core.offset >> 8);
+ evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+ evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+ evo_data(push, asyh->core.layout << 20 |
+ (asyh->core.pitch >> 8) << 8 |
+ asyh->core.block);
+ evo_data(push, asyh->core.kind << 16 |
+ asyh->core.format << 8);
+ evo_data(push, asyh->core.handle);
+ evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+ evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+ /* EVO will complain with INVALID_STATE if we have an
+ * active cursor and (re)specify HeadSetContextDmaIso
+ * without also updating HeadSetOffsetCursor.
+ */
+ asyh->set.curs = asyh->curs.visible;
+ } else
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+ evo_data(push, asyh->core.offset >> 8);
+ evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+ evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+ evo_data(push, asyh->core.layout << 20 |
+ (asyh->core.pitch >> 8) << 8 |
+ asyh->core.block);
+ evo_data(push, asyh->core.format << 8);
+ evo_data(push, asyh->core.handle);
+ evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+ evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+ } else {
+ evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
+ evo_data(push, asyh->core.offset >> 8);
+ evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
+ evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+ evo_data(push, asyh->core.layout << 24 |
+ (asyh->core.pitch >> 8) << 8 |
+ asyh->core.block);
+ evo_data(push, asyh->core.format << 8);
+ evo_data(push, asyh->core.handle);
+ evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
+ evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+ }
+ evo_kick(push, core);
+ }
+}
- nv50_display_flip_stop(crtc);
-
- push = evo_wait(mast, 6);
- if (push) {
- if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
+static void
+nv50_head_lut_clr(struct nv50_head *head)
+{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 4))) {
+ if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
evo_data(push, 0x40000000);
} else
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
evo_data(push, 0x40000000);
- evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
+ evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
evo_data(push, 0x00000000);
} else {
- evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
evo_data(push, 0x03000000);
- evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
evo_data(push, 0x00000000);
}
-
- evo_kick(push, mast);
+ evo_kick(push, core);
}
-
- nv50_crtc_cursor_show_hide(nv_crtc, false, false);
}
static void
-nv50_crtc_commit(struct drm_crtc *crtc)
+nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct nv50_mast *mast = nv50_mast(crtc->dev);
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
-
- push = evo_wait(mast, 32);
- if (push) {
- if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nv_crtc->fb.handle);
- evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
+ if ((push = evo_wait(core, 7))) {
+ if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
evo_data(push, 0xc0000000);
- evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+ evo_data(push, asyh->lut.offset >> 8);
} else
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nv_crtc->fb.handle);
- evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
evo_data(push, 0xc0000000);
- evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
- evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
- evo_data(push, mast->base.vram.handle);
+ evo_data(push, asyh->lut.offset >> 8);
+ evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
+ evo_data(push, asyh->lut.handle);
} else {
- evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
- evo_data(push, nv_crtc->fb.handle);
- evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
+ evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
evo_data(push, 0x83000000);
- evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+ evo_data(push, asyh->lut.offset >> 8);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
- evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
- evo_data(push, mast->base.vram.handle);
- evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
+ evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
+ evo_data(push, asyh->lut.handle);
+ }
+ evo_kick(push, core);
+ }
+}
+
+static void
+nv50_head_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ struct nv50_head_mode *m = &asyh->mode;
+ u32 *push;
+ if ((push = evo_wait(core, 14))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
+ evo_data(push, 0x00800000 | m->clock);
+ evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
+ evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
+ evo_data(push, 0x00000000);
+ evo_data(push, (m->v.active << 16) | m->h.active );
+ evo_data(push, (m->v.synce << 16) | m->h.synce );
+ evo_data(push, (m->v.blanke << 16) | m->h.blanke );
+ evo_data(push, (m->v.blanks << 16) | m->h.blanks );
+ evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
+ evo_data(push, asyh->mode.v.blankus);
+ evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
+ evo_data(push, 0x00000000);
+ } else {
+ evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
+ evo_data(push, 0x00000000);
+ evo_data(push, (m->v.active << 16) | m->h.active );
+ evo_data(push, (m->v.synce << 16) | m->h.synce );
+ evo_data(push, (m->v.blanke << 16) | m->h.blanke );
+ evo_data(push, (m->v.blanks << 16) | m->h.blanks );
+ evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
+ evo_mthd(push, 0x042c + (head->base.index * 0x300), 2);
+ evo_data(push, 0x00000000); /* ??? */
evo_data(push, 0xffffff00);
+ evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
+ evo_data(push, m->clock * 1000);
+ evo_data(push, 0x00200000); /* ??? */
+ evo_data(push, m->clock * 1000);
}
+ evo_kick(push, core);
+ }
+}
- evo_kick(push, mast);
+static void
+nv50_head_view(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+ struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+ u32 *push;
+ if ((push = evo_wait(core, 10))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
+ evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
+ evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
+ evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+ evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+ } else {
+ evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
+ evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
+ evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
+ evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+ evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+ evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+ }
+ evo_kick(push, core);
}
+}
- nv50_crtc_cursor_show_hide(nv_crtc, true, true);
- nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
+static void
+nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y)
+{
+ if (asyh->clr.core && (!asyh->set.core || y))
+ nv50_head_lut_clr(head);
+ if (asyh->clr.core && (!asyh->set.core || y))
+ nv50_head_core_clr(head);
+ if (asyh->clr.curs && (!asyh->set.curs || y))
+ nv50_head_curs_clr(head);
}
-static bool
-nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static void
+nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
- return true;
+ if (asyh->set.view ) nv50_head_view (head, asyh);
+ if (asyh->set.mode ) nv50_head_mode (head, asyh);
+ if (asyh->set.core ) nv50_head_lut_set (head, asyh);
+ if (asyh->set.core ) nv50_head_core_set(head, asyh);
+ if (asyh->set.curs ) nv50_head_curs_set(head, asyh);
+ if (asyh->set.base ) nv50_head_base (head, asyh);
+ if (asyh->set.ovly ) nv50_head_ovly (head, asyh);
+ if (asyh->set.dither ) nv50_head_dither (head, asyh);
+ if (asyh->set.procamp) nv50_head_procamp (head, asyh);
}
-static int
-nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+static void
+nv50_head_atomic_check_procamp(struct nv50_head_atom *armh,
+ struct nv50_head_atom *asyh,
+ struct nouveau_conn_atom *asyc)
{
- struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
- struct nv50_head *head = nv50_head(crtc);
- int ret;
+ const int vib = asyc->procamp.color_vibrance - 100;
+ const int hue = asyc->procamp.vibrant_hue - 90;
+ const int adj = (vib > 0) ? 50 : 0;
+ asyh->procamp.sat.cos = ((vib * 2047 + adj) / 100) & 0xfff;
+ asyh->procamp.sat.sin = ((hue * 2047) / 100) & 0xfff;
+ asyh->set.procamp = true;
+}
+
+static void
+nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
+ struct nv50_head_atom *asyh,
+ struct nouveau_conn_atom *asyc)
+{
+ struct drm_connector *connector = asyc->state.connector;
+ u32 mode = 0x00;
+
+ if (asyc->dither.mode == DITHERING_MODE_AUTO) {
+ if (asyh->base.depth > connector->display_info.bpc * 3)
+ mode = DITHERING_MODE_DYNAMIC2X2;
+ } else {
+ mode = asyc->dither.mode;
+ }
- ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM, true);
- if (ret == 0) {
- if (head->image)
- nouveau_bo_unpin(head->image);
- nouveau_bo_ref(nvfb->nvbo, &head->image);
+ if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
+ if (connector->display_info.bpc >= 8)
+ mode |= DITHERING_DEPTH_8BPC;
+ } else {
+ mode |= asyc->dither.depth;
}
- return ret;
+ asyh->dither.enable = mode;
+ asyh->dither.bits = mode >> 1;
+ asyh->dither.mode = mode >> 3;
+ asyh->set.dither = true;
}
-static int
-nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
- struct drm_display_mode *mode, int x, int y,
- struct drm_framebuffer *old_fb)
+static void
+nv50_head_atomic_check_view(struct nv50_head_atom *armh,
+ struct nv50_head_atom *asyh,
+ struct nouveau_conn_atom *asyc)
{
- struct nv50_mast *mast = nv50_mast(crtc->dev);
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct nouveau_connector *nv_connector;
- u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
- u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
- u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks;
- u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks;
- u32 vblan2e = 0, vblan2s = 1, vblankus = 0;
- u32 *push;
- int ret;
-
- hactive = mode->htotal;
- hsynce = mode->hsync_end - mode->hsync_start - 1;
- hbackp = mode->htotal - mode->hsync_end;
- hblanke = hsynce + hbackp;
- hfrontp = mode->hsync_start - mode->hdisplay;
- hblanks = mode->htotal - hfrontp - 1;
-
- vactive = mode->vtotal * vscan / ilace;
- vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
- vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace;
- vblanke = vsynce + vbackp;
- vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
- vblanks = vactive - vfrontp - 1;
- /* XXX: Safe underestimate, even "0" works */
- vblankus = (vactive - mode->vdisplay - 2) * hactive;
- vblankus *= 1000;
- vblankus /= mode->clock;
+ struct drm_connector *connector = asyc->state.connector;
+ struct drm_display_mode *omode = &asyh->state.adjusted_mode;
+ struct drm_display_mode *umode = &asyh->state.mode;
+ int mode = asyc->scaler.mode;
+ struct edid *edid;
+
+ if (connector->edid_blob_ptr)
+ edid = (struct edid *)connector->edid_blob_ptr->data;
+ else
+ edid = NULL;
- if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
- vblan2e = vactive + vsynce + vbackp;
- vblan2s = vblan2e + (mode->vdisplay * vscan / ilace);
- vactive = (vactive * 2) + 1;
+ if (!asyc->scaler.full) {
+ if (mode == DRM_MODE_SCALE_NONE)
+ omode = umode;
+ } else {
+ /* Non-EDID LVDS/eDP mode. */
+ mode = DRM_MODE_SCALE_FULLSCREEN;
}
- ret = nv50_crtc_swap_fbs(crtc, old_fb);
- if (ret)
- return ret;
+ asyh->view.iW = umode->hdisplay;
+ asyh->view.iH = umode->vdisplay;
+ asyh->view.oW = omode->hdisplay;
+ asyh->view.oH = omode->vdisplay;
+ if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
+ asyh->view.oH *= 2;
- push = evo_wait(mast, 64);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
- evo_data(push, 0x00800000 | mode->clock);
- evo_data(push, (ilace == 2) ? 2 : 0);
- evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6);
- evo_data(push, 0x00000000);
- evo_data(push, (vactive << 16) | hactive);
- evo_data(push, ( vsynce << 16) | hsynce);
- evo_data(push, (vblanke << 16) | hblanke);
- evo_data(push, (vblanks << 16) | hblanks);
- evo_data(push, (vblan2e << 16) | vblan2s);
- evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1);
- evo_data(push, 0x00000000);
- evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2);
- evo_data(push, 0x00000311);
- evo_data(push, 0x00000100);
+ /* Add overscan compensation if necessary, will keep the aspect
+ * ratio the same as the backend mode unless overridden by the
+ * user setting both hborder and vborder properties.
+ */
+ if ((asyc->scaler.underscan.mode == UNDERSCAN_ON ||
+ (asyc->scaler.underscan.mode == UNDERSCAN_AUTO &&
+ drm_detect_hdmi_monitor(edid)))) {
+ u32 bX = asyc->scaler.underscan.hborder;
+ u32 bY = asyc->scaler.underscan.vborder;
+ u32 r = (asyh->view.oH << 19) / asyh->view.oW;
+
+ if (bX) {
+ asyh->view.oW -= (bX * 2);
+ if (bY) asyh->view.oH -= (bY * 2);
+ else asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19;
} else {
- evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 6);
- evo_data(push, 0x00000000);
- evo_data(push, (vactive << 16) | hactive);
- evo_data(push, ( vsynce << 16) | hsynce);
- evo_data(push, (vblanke << 16) | hblanke);
- evo_data(push, (vblanks << 16) | hblanks);
- evo_data(push, (vblan2e << 16) | vblan2s);
- evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
- evo_data(push, 0x00000000); /* ??? */
- evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
- evo_data(push, mode->clock * 1000);
- evo_data(push, 0x00200000); /* ??? */
- evo_data(push, mode->clock * 1000);
- evo_mthd(push, 0x04d0 + (nv_crtc->index * 0x300), 2);
- evo_data(push, 0x00000311);
- evo_data(push, 0x00000100);
+ asyh->view.oW -= (asyh->view.oW >> 4) + 32;
+ if (bY) asyh->view.oH -= (bY * 2);
+ else asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19;
}
+ }
- evo_kick(push, mast);
+ /* Handle CENTER/ASPECT scaling, taking into account the areas
+ * removed already for overscan compensation.
+ */
+ switch (mode) {
+ case DRM_MODE_SCALE_CENTER:
+ asyh->view.oW = min((u16)umode->hdisplay, asyh->view.oW);
+ asyh->view.oH = min((u16)umode->vdisplay, asyh->view.oH);
+ /* fall-through */
+ case DRM_MODE_SCALE_ASPECT:
+ if (asyh->view.oH < asyh->view.oW) {
+ u32 r = (asyh->view.iW << 19) / asyh->view.iH;
+ asyh->view.oW = ((asyh->view.oH * r) + (r / 2)) >> 19;
+ } else {
+ u32 r = (asyh->view.iH << 19) / asyh->view.iW;
+ asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19;
+ }
+ break;
+ default:
+ break;
}
- nv_connector = nouveau_crtc_connector_get(nv_crtc);
- nv50_crtc_set_dither(nv_crtc, false);
- nv50_crtc_set_scale(nv_crtc, false);
+ asyh->set.view = true;
+}
- /* G94 only accepts this after setting scale */
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA)
- nv50_crtc_set_raster_vblank_dmi(nv_crtc, vblankus);
+static void
+nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+ struct drm_display_mode *mode = &asyh->state.adjusted_mode;
+ u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
+ u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
+ u32 hbackp = mode->htotal - mode->hsync_end;
+ u32 vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace;
+ u32 hfrontp = mode->hsync_start - mode->hdisplay;
+ u32 vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
+ struct nv50_head_mode *m = &asyh->mode;
+
+ m->h.active = mode->htotal;
+ m->h.synce = mode->hsync_end - mode->hsync_start - 1;
+ m->h.blanke = m->h.synce + hbackp;
+ m->h.blanks = mode->htotal - hfrontp - 1;
+
+ m->v.active = mode->vtotal * vscan / ilace;
+ m->v.synce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
+ m->v.blanke = m->v.synce + vbackp;
+ m->v.blanks = m->v.active - vfrontp - 1;
+
+ /*XXX: Safe underestimate, even "0" works */
+ m->v.blankus = (m->v.active - mode->vdisplay - 2) * m->h.active;
+ m->v.blankus *= 1000;
+ m->v.blankus /= mode->clock;
- nv50_crtc_set_color_vibrance(nv_crtc, false);
- nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
- return 0;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ m->v.blank2e = m->v.active + m->v.synce + vbackp;
+ m->v.blank2s = m->v.blank2e + (mode->vdisplay * vscan / ilace);
+ m->v.active = (m->v.active * 2) + 1;
+ m->interlace = true;
+ } else {
+ m->v.blank2e = 0;
+ m->v.blank2s = 1;
+ m->interlace = false;
+ }
+ m->clock = mode->clock;
+
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ asyh->set.mode = true;
}
static int
-nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
+nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
{
struct nouveau_drm *drm = nouveau_drm(crtc->dev);
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- int ret;
+ struct nv50_disp *disp = nv50_disp(crtc->dev);
+ struct nv50_head *head = nv50_head(crtc);
+ struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
+ struct nv50_head_atom *asyh = nv50_head_atom(state);
+ struct nouveau_conn_atom *asyc = NULL;
+ struct drm_connector_state *conns;
+ struct drm_connector *conn;
+ int i;
- if (!crtc->primary->fb) {
- NV_DEBUG(drm, "No FB bound\n");
- return 0;
+ NV_ATOMIC(drm, "%s atomic_check %d\n", crtc->name, asyh->state.active);
+ if (asyh->state.active) {
+ for_each_connector_in_state(asyh->state.state, conn, conns, i) {
+ if (conns->crtc == crtc) {
+ asyc = nouveau_conn_atom(conns);
+ break;
+ }
+ }
+
+ if (armh->state.active) {
+ if (asyc) {
+ if (asyh->state.mode_changed)
+ asyc->set.scaler = true;
+ if (armh->base.depth != asyh->base.depth)
+ asyc->set.dither = true;
+ }
+ } else {
+ asyc->set.mask = ~0;
+ asyh->set.mask = ~0;
+ }
+
+ if (asyh->state.mode_changed)
+ nv50_head_atomic_check_mode(head, asyh);
+
+ if (asyc) {
+ if (asyc->set.scaler)
+ nv50_head_atomic_check_view(armh, asyh, asyc);
+ if (asyc->set.dither)
+ nv50_head_atomic_check_dither(armh, asyh, asyc);
+ if (asyc->set.procamp)
+ nv50_head_atomic_check_procamp(armh, asyh, asyc);
+ }
+
+ if ((asyh->core.visible = (asyh->base.cpp != 0))) {
+ asyh->core.x = asyh->base.x;
+ asyh->core.y = asyh->base.y;
+ asyh->core.w = asyh->base.w;
+ asyh->core.h = asyh->base.h;
+ } else
+ if ((asyh->core.visible = asyh->curs.visible)) {
+ /*XXX: We need to either find some way of having the
+ * primary base layer appear black, while still
+ * being able to display the other layers, or we
+ * need to allocate a dummy black surface here.
+ */
+ asyh->core.x = 0;
+ asyh->core.y = 0;
+ asyh->core.w = asyh->state.mode.hdisplay;
+ asyh->core.h = asyh->state.mode.vdisplay;
+ }
+ asyh->core.handle = disp->mast.base.vram.handle;
+ asyh->core.offset = 0;
+ asyh->core.format = 0xcf;
+ asyh->core.kind = 0;
+ asyh->core.layout = 1;
+ asyh->core.block = 0;
+ asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
+ asyh->lut.handle = disp->mast.base.vram.handle;
+ asyh->lut.offset = head->base.lut.nvbo->bo.offset;
+ asyh->set.base = armh->base.cpp != asyh->base.cpp;
+ asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp;
+ } else {
+ asyh->core.visible = false;
+ asyh->curs.visible = false;
+ asyh->base.cpp = 0;
+ asyh->ovly.cpp = 0;
}
- ret = nv50_crtc_swap_fbs(crtc, old_fb);
- if (ret)
- return ret;
+ if (!drm_atomic_crtc_needs_modeset(&asyh->state)) {
+ if (asyh->core.visible) {
+ if (memcmp(&armh->core, &asyh->core, sizeof(asyh->core)))
+ asyh->set.core = true;
+ } else
+ if (armh->core.visible) {
+ asyh->clr.core = true;
+ }
- nv50_display_flip_stop(crtc);
- nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
- nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
- return 0;
-}
+ if (asyh->curs.visible) {
+ if (memcmp(&armh->curs, &asyh->curs, sizeof(asyh->curs)))
+ asyh->set.curs = true;
+ } else
+ if (armh->curs.visible) {
+ asyh->clr.curs = true;
+ }
+ } else {
+ asyh->clr.core = armh->core.visible;
+ asyh->clr.curs = armh->curs.visible;
+ asyh->set.core = asyh->core.visible;
+ asyh->set.curs = asyh->curs.visible;
+ }
-static int
-nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int x, int y,
- enum mode_set_atomic state)
-{
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- nv50_display_flip_stop(crtc);
- nv50_crtc_set_image(nv_crtc, fb, x, y, true);
+ if (asyh->clr.mask || asyh->set.mask)
+ nv50_atom(asyh->state.state)->lock_core = true;
return 0;
}
static void
-nv50_crtc_lut_load(struct drm_crtc *crtc)
+nv50_head_lut_load(struct drm_crtc *crtc)
{
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -1292,64 +2205,95 @@ nv50_crtc_lut_load(struct drm_crtc *crtc)
}
}
-static void
-nv50_crtc_disable(struct drm_crtc *crtc)
+static int
+nv50_head_mode_set_base_atomic(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int x, int y,
+ enum mode_set_atomic state)
{
- struct nv50_head *head = nv50_head(crtc);
- evo_sync(crtc->dev);
- if (head->image)
- nouveau_bo_unpin(head->image);
- nouveau_bo_ref(NULL, &head->image);
+ WARN_ON(1);
+ return 0;
}
+static const struct drm_crtc_helper_funcs
+nv50_head_help = {
+ .mode_set_base_atomic = nv50_head_mode_set_base_atomic,
+ .load_lut = nv50_head_lut_load,
+ .atomic_check = nv50_head_atomic_check,
+};
+
+/* This is identical to the version in the atomic helpers, except that
+ * it supports non-vblanked ("async") page flips.
+ */
static int
-nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
- uint32_t handle, uint32_t width, uint32_t height)
+nv50_head_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event, u32 flags)
{
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct drm_gem_object *gem = NULL;
- struct nouveau_bo *nvbo = NULL;
+ struct drm_plane *plane = crtc->primary;
+ struct drm_atomic_state *state;
+ struct drm_plane_state *plane_state;
+ struct drm_crtc_state *crtc_state;
int ret = 0;
- if (handle) {
- if (width != 64 || height != 64)
- return -EINVAL;
+ state = drm_atomic_state_alloc(plane->dev);
+ if (!state)
+ return -ENOMEM;
- gem = drm_gem_object_lookup(file_priv, handle);
- if (unlikely(!gem))
- return -ENOENT;
- nvbo = nouveau_gem_object(gem);
+ 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);
+ goto fail;
+ }
+ crtc_state->event = event;
- ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, true);
+ plane_state = drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state)) {
+ ret = PTR_ERR(plane_state);
+ goto fail;
}
- if (ret == 0) {
- if (nv_crtc->cursor.nvbo)
- nouveau_bo_unpin(nv_crtc->cursor.nvbo);
- nouveau_bo_ref(nvbo, &nv_crtc->cursor.nvbo);
+ ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+ if (ret != 0)
+ goto fail;
+ drm_atomic_set_fb_for_plane(plane_state, fb);
+
+ /* Make sure we don't accidentally do a full modeset. */
+ state->allow_modeset = false;
+ if (!crtc_state->active) {
+ DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
+ crtc->base.id);
+ ret = -EINVAL;
+ goto fail;
}
- drm_gem_object_unreference_unlocked(gem);
- nv50_crtc_cursor_show_hide(nv_crtc, true, true);
+ if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
+ nv50_wndw_atom(plane_state)->interval = 0;
+
+ ret = drm_atomic_nonblocking_commit(state);
+fail:
+ if (ret == -EDEADLK)
+ goto backoff;
+
+ drm_atomic_state_put(state);
return ret;
-}
-static int
-nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
- struct nv50_curs *curs = nv50_curs(crtc);
- struct nv50_chan *chan = nv50_chan(curs);
- nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
- nvif_wr32(&chan->user, 0x0080, 0x00000000);
+backoff:
+ drm_atomic_state_clear(state);
+ drm_atomic_legacy_backoff(state);
- nv_crtc->cursor_saved_x = x;
- nv_crtc->cursor_saved_y = y;
- return 0;
+ /*
+ * 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.
+ */
+ plane->old_fb = plane->fb;
+
+ goto retry;
}
static int
-nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
uint32_t size)
{
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -1361,47 +2305,71 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
nv_crtc->lut.b[i] = b[i];
}
- nv50_crtc_lut_load(crtc);
-
+ nv50_head_lut_load(crtc);
return 0;
}
static void
-nv50_crtc_cursor_restore(struct nouveau_crtc *nv_crtc, int x, int y)
+nv50_head_atomic_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
{
- nv50_crtc_cursor_move(&nv_crtc->base, x, y);
+ struct nv50_head_atom *asyh = nv50_head_atom(state);
+ __drm_atomic_helper_crtc_destroy_state(&asyh->state);
+ kfree(asyh);
+}
- nv50_crtc_cursor_show_hide(nv_crtc, true, true);
+static struct drm_crtc_state *
+nv50_head_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+ struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
+ struct nv50_head_atom *asyh;
+ if (!(asyh = kmalloc(sizeof(*asyh), GFP_KERNEL)))
+ return NULL;
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &asyh->state);
+ asyh->view = armh->view;
+ asyh->mode = armh->mode;
+ asyh->lut = armh->lut;
+ asyh->core = armh->core;
+ asyh->curs = armh->curs;
+ asyh->base = armh->base;
+ asyh->ovly = armh->ovly;
+ asyh->dither = armh->dither;
+ asyh->procamp = armh->procamp;
+ asyh->clr.mask = 0;
+ asyh->set.mask = 0;
+ return &asyh->state;
+}
+
+static void
+__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ if (crtc->state)
+ crtc->funcs->atomic_destroy_state(crtc, crtc->state);
+ crtc->state = state;
+ crtc->state->crtc = crtc;
}
static void
-nv50_crtc_destroy(struct drm_crtc *crtc)
+nv50_head_reset(struct drm_crtc *crtc)
+{
+ struct nv50_head_atom *asyh;
+
+ if (WARN_ON(!(asyh = kzalloc(sizeof(*asyh), GFP_KERNEL))))
+ return;
+
+ __drm_atomic_helper_crtc_reset(crtc, &asyh->state);
+}
+
+static void
+nv50_head_destroy(struct drm_crtc *crtc)
{
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nv50_head *head = nv50_head(crtc);
- struct nv50_fbdma *fbdma;
-
- list_for_each_entry(fbdma, &disp->fbdma, head) {
- nvif_object_fini(&fbdma->base[nv_crtc->index]);
- }
nv50_dmac_destroy(&head->ovly.base, disp->disp);
nv50_pioc_destroy(&head->oimm.base);
- nv50_dmac_destroy(&head->sync.base, disp->disp);
- nv50_pioc_destroy(&head->curs.base);
-
- /*XXX: this shouldn't be necessary, but the core doesn't call
- * disconnect() during the cleanup paths
- */
- if (head->image)
- nouveau_bo_unpin(head->image);
- nouveau_bo_ref(NULL, &head->image);
-
- /*XXX: ditto */
- if (nv_crtc->cursor.nvbo)
- nouveau_bo_unpin(nv_crtc->cursor.nvbo);
- nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
nouveau_bo_unmap(nv_crtc->lut.nvbo);
if (nv_crtc->lut.nvbo)
@@ -1412,34 +2380,27 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
kfree(crtc);
}
-static const struct drm_crtc_helper_funcs nv50_crtc_hfunc = {
- .dpms = nv50_crtc_dpms,
- .prepare = nv50_crtc_prepare,
- .commit = nv50_crtc_commit,
- .mode_fixup = nv50_crtc_mode_fixup,
- .mode_set = nv50_crtc_mode_set,
- .mode_set_base = nv50_crtc_mode_set_base,
- .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
- .load_lut = nv50_crtc_lut_load,
- .disable = nv50_crtc_disable,
-};
-
-static const struct drm_crtc_funcs nv50_crtc_func = {
- .cursor_set = nv50_crtc_cursor_set,
- .cursor_move = nv50_crtc_cursor_move,
- .gamma_set = nv50_crtc_gamma_set,
- .set_config = nouveau_crtc_set_config,
- .destroy = nv50_crtc_destroy,
- .page_flip = nouveau_crtc_page_flip,
+static const struct drm_crtc_funcs
+nv50_head_func = {
+ .reset = nv50_head_reset,
+ .gamma_set = nv50_head_gamma_set,
+ .destroy = nv50_head_destroy,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = nv50_head_page_flip,
+ .set_property = drm_atomic_helper_crtc_set_property,
+ .atomic_duplicate_state = nv50_head_atomic_duplicate_state,
+ .atomic_destroy_state = nv50_head_atomic_destroy_state,
};
static int
-nv50_crtc_create(struct drm_device *dev, int index)
+nv50_head_create(struct drm_device *dev, int index)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nvif_device *device = &drm->device;
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_head *head;
+ struct nv50_base *base;
+ struct nv50_curs *curs;
struct drm_crtc *crtc;
int ret, i;
@@ -1448,21 +2409,25 @@ nv50_crtc_create(struct drm_device *dev, int index)
return -ENOMEM;
head->base.index = index;
- head->base.set_dither = nv50_crtc_set_dither;
- head->base.set_scale = nv50_crtc_set_scale;
- head->base.set_color_vibrance = nv50_crtc_set_color_vibrance;
- head->base.color_vibrance = 50;
- head->base.vibrant_hue = 0;
- head->base.cursor.set_pos = nv50_crtc_cursor_restore;
for (i = 0; i < 256; i++) {
head->base.lut.r[i] = i << 8;
head->base.lut.g[i] = i << 8;
head->base.lut.b[i] = i << 8;
}
+ ret = nv50_base_new(drm, head, &base);
+ if (ret == 0)
+ ret = nv50_curs_new(drm, head, &curs);
+ if (ret) {
+ kfree(head);
+ return ret;
+ }
+
crtc = &head->base.base;
- drm_crtc_init(dev, crtc, &nv50_crtc_func);
- drm_crtc_helper_add(crtc, &nv50_crtc_hfunc);
+ drm_crtc_init_with_planes(dev, crtc, &base->wndw.plane,
+ &curs->wndw.plane, &nv50_head_func,
+ "head-%d", head->base.index);
+ drm_crtc_helper_add(crtc, &nv50_head_help);
drm_mode_crtc_set_gamma_size(crtc, 256);
ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
@@ -1481,20 +2446,6 @@ nv50_crtc_create(struct drm_device *dev, int index)
if (ret)
goto out;
- /* allocate cursor resources */
- ret = nv50_curs_create(device, disp->disp, index, &head->curs);
- if (ret)
- goto out;
-
- /* allocate page flip / sync resources */
- ret = nv50_base_create(device, disp->disp, index, disp->sync->bo.offset,
- &head->sync);
- if (ret)
- goto out;
-
- head->sync.addr = EVO_FLIP_SEM0(index);
- head->sync.data = 0x00000000;
-
/* allocate overlay resources */
ret = nv50_oimm_create(device, disp->disp, index, &head->oimm);
if (ret)
@@ -1507,43 +2458,64 @@ nv50_crtc_create(struct drm_device *dev, int index)
out:
if (ret)
- nv50_crtc_destroy(crtc);
+ nv50_head_destroy(crtc);
return ret;
}
/******************************************************************************
- * Encoder helpers
+ * Output path helpers
*****************************************************************************/
-static bool
-nv50_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int
+nv50_outp_atomic_check_view(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ struct drm_display_mode *native_mode)
{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nouveau_connector *nv_connector;
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+ struct drm_display_mode *mode = &crtc_state->mode;
+ struct drm_connector *connector = conn_state->connector;
+ struct nouveau_conn_atom *asyc = nouveau_conn_atom(conn_state);
+ struct nouveau_drm *drm = nouveau_drm(encoder->dev);
+
+ NV_ATOMIC(drm, "%s atomic_check\n", encoder->name);
+ asyc->scaler.full = false;
+ if (!native_mode)
+ return 0;
- nv_connector = nouveau_encoder_connector_get(nv_encoder);
- if (nv_connector && nv_connector->native_mode) {
- nv_connector->scaling_full = false;
- if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) {
- switch (nv_connector->type) {
- case DCB_CONNECTOR_LVDS:
- case DCB_CONNECTOR_LVDS_SPWG:
- case DCB_CONNECTOR_eDP:
- /* force use of scaler for non-edid modes */
- if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
- return true;
- nv_connector->scaling_full = true;
+ if (asyc->scaler.mode == DRM_MODE_SCALE_NONE) {
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_LVDS:
+ case DRM_MODE_CONNECTOR_eDP:
+ /* Force use of scaler for non-EDID modes. */
+ if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
break;
- default:
- return true;
- }
+ mode = native_mode;
+ asyc->scaler.full = true;
+ break;
+ default:
+ break;
}
+ } else {
+ mode = native_mode;
+ }
- drm_mode_copy(adjusted_mode, nv_connector->native_mode);
+ if (!drm_mode_equal(adjusted_mode, mode)) {
+ drm_mode_copy(adjusted_mode, mode);
+ crtc_state->mode_changed = true;
}
- return true;
+ return 0;
+}
+
+static int
+nv50_outp_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct nouveau_connector *nv_connector =
+ nouveau_connector(conn_state->connector);
+ return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+ nv_connector->native_mode);
}
/******************************************************************************
@@ -1574,21 +2546,39 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
}
static void
-nv50_dac_commit(struct drm_encoder *encoder)
+nv50_dac_disable(struct drm_encoder *encoder)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nv50_mast *mast = nv50_mast(encoder->dev);
+ const int or = nv_encoder->or;
+ u32 *push;
+
+ if (nv_encoder->crtc) {
+ push = evo_wait(mast, 4);
+ if (push) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0400 + (or * 0x080), 1);
+ evo_data(push, 0x00000000);
+ } else {
+ evo_mthd(push, 0x0180 + (or * 0x020), 1);
+ evo_data(push, 0x00000000);
+ }
+ evo_kick(push, mast);
+ }
+ }
+
+ nv_encoder->crtc = NULL;
}
static void
-nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+nv50_dac_enable(struct drm_encoder *encoder)
{
struct nv50_mast *mast = nv50_mast(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
u32 *push;
- nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
-
push = evo_wait(mast, 8);
if (push) {
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
@@ -1627,33 +2617,6 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
nv_encoder->crtc = encoder->crtc;
}
-static void
-nv50_dac_disconnect(struct drm_encoder *encoder)
-{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_mast *mast = nv50_mast(encoder->dev);
- const int or = nv_encoder->or;
- u32 *push;
-
- if (nv_encoder->crtc) {
- nv50_crtc_prepare(nv_encoder->crtc);
-
- push = evo_wait(mast, 4);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0400 + (or * 0x080), 1);
- evo_data(push, 0x00000000);
- } else {
- evo_mthd(push, 0x0180 + (or * 0x020), 1);
- evo_data(push, 0x00000000);
- }
- evo_kick(push, mast);
- }
- }
-
- nv_encoder->crtc = NULL;
-}
-
static enum drm_connector_status
nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
@@ -1681,6 +2644,15 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
return connector_status_connected;
}
+static const struct drm_encoder_helper_funcs
+nv50_dac_help = {
+ .dpms = nv50_dac_dpms,
+ .atomic_check = nv50_outp_atomic_check,
+ .enable = nv50_dac_enable,
+ .disable = nv50_dac_disable,
+ .detect = nv50_dac_detect
+};
+
static void
nv50_dac_destroy(struct drm_encoder *encoder)
{
@@ -1688,18 +2660,8 @@ nv50_dac_destroy(struct drm_encoder *encoder)
kfree(encoder);
}
-static const struct drm_encoder_helper_funcs nv50_dac_hfunc = {
- .dpms = nv50_dac_dpms,
- .mode_fixup = nv50_encoder_mode_fixup,
- .prepare = nv50_dac_disconnect,
- .commit = nv50_dac_commit,
- .mode_set = nv50_dac_mode_set,
- .disable = nv50_dac_disconnect,
- .get_crtc = nv50_display_crtc_get,
- .detect = nv50_dac_detect
-};
-
-static const struct drm_encoder_funcs nv50_dac_func = {
+static const struct drm_encoder_funcs
+nv50_dac_func = {
.destroy = nv50_dac_destroy,
};
@@ -1726,8 +2688,9 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
encoder = to_drm_encoder(nv_encoder);
encoder->possible_crtcs = dcbe->heads;
encoder->possible_clones = 0;
- drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type, NULL);
- drm_encoder_helper_add(encoder, &nv50_dac_hfunc);
+ drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type,
+ "dac-%04x-%04x", dcbe->hasht, dcbe->hashm);
+ drm_encoder_helper_add(encoder, &nv50_dac_help);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
@@ -1737,7 +2700,26 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
* Audio
*****************************************************************************/
static void
-nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
+nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_hda_eld_v0 eld;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
+ (0x0100 << nv_crtc->index),
+ };
+
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
+}
+
+static void
+nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1768,30 +2750,30 @@ nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
sizeof(args.base) + drm_eld_size(args.data));
}
+/******************************************************************************
+ * HDMI
+ *****************************************************************************/
static void
-nv50_audio_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
struct {
struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_hda_eld_v0 eld;
+ struct nv50_disp_sor_hdmi_pwr_v0 pwr;
} args = {
.base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
+ (0x0100 << nv_crtc->index),
};
nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
-/******************************************************************************
- * HDMI
- *****************************************************************************/
static void
-nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
+nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1821,26 +2803,635 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
args.pwr.max_ac_packet = max_ac_packet / 32;
nvif_mthd(disp->disp, 0, &args, sizeof(args));
- nv50_audio_mode_set(encoder, mode);
+ nv50_audio_enable(encoder, mode);
+}
+
+/******************************************************************************
+ * MST
+ *****************************************************************************/
+#define nv50_mstm(p) container_of((p), struct nv50_mstm, mgr)
+#define nv50_mstc(p) container_of((p), struct nv50_mstc, connector)
+#define nv50_msto(p) container_of((p), struct nv50_msto, encoder)
+
+struct nv50_mstm {
+ struct nouveau_encoder *outp;
+
+ struct drm_dp_mst_topology_mgr mgr;
+ struct nv50_msto *msto[4];
+
+ bool modified;
+};
+
+struct nv50_mstc {
+ struct nv50_mstm *mstm;
+ struct drm_dp_mst_port *port;
+ struct drm_connector connector;
+
+ struct drm_display_mode *native;
+ struct edid *edid;
+
+ int pbn;
+};
+
+struct nv50_msto {
+ struct drm_encoder encoder;
+
+ struct nv50_head *head;
+ struct nv50_mstc *mstc;
+ bool disabled;
+};
+
+static struct drm_dp_payload *
+nv50_msto_payload(struct nv50_msto *msto)
+{
+ struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+ struct nv50_mstc *mstc = msto->mstc;
+ struct nv50_mstm *mstm = mstc->mstm;
+ int vcpi = mstc->port->vcpi.vcpi, i;
+
+ NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi);
+ for (i = 0; i < mstm->mgr.max_payloads; i++) {
+ struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
+ NV_ATOMIC(drm, "%s: %d: vcpi %d start 0x%02x slots 0x%02x\n",
+ mstm->outp->base.base.name, i, payload->vcpi,
+ payload->start_slot, payload->num_slots);
+ }
+
+ for (i = 0; i < mstm->mgr.max_payloads; i++) {
+ struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
+ if (payload->vcpi == vcpi)
+ return payload;
+ }
+
+ return NULL;
}
static void
-nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+nv50_msto_cleanup(struct nv50_msto *msto)
{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+ struct nv50_mstc *mstc = msto->mstc;
+ struct nv50_mstm *mstm = mstc->mstm;
+
+ NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
+ if (mstc->port && mstc->port->vcpi.vcpi > 0 && !nv50_msto_payload(msto))
+ drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
+ if (msto->disabled) {
+ msto->mstc = NULL;
+ msto->head = NULL;
+ msto->disabled = false;
+ }
+}
+
+static void
+nv50_msto_prepare(struct nv50_msto *msto)
+{
+ struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+ struct nv50_mstc *mstc = msto->mstc;
+ struct nv50_mstm *mstm = mstc->mstm;
struct {
struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+ struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi;
} args = {
.base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
+ .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI,
+ .base.hasht = mstm->outp->dcb->hasht,
+ .base.hashm = (0xf0ff & mstm->outp->dcb->hashm) |
+ (0x0100 << msto->head->base.index),
};
- nvif_mthd(disp->disp, 0, &args, sizeof(args));
+ NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
+ if (mstc->port && mstc->port->vcpi.vcpi > 0) {
+ struct drm_dp_payload *payload = nv50_msto_payload(msto);
+ if (payload) {
+ args.vcpi.start_slot = payload->start_slot;
+ args.vcpi.num_slots = payload->num_slots;
+ args.vcpi.pbn = mstc->port->vcpi.pbn;
+ args.vcpi.aligned_pbn = mstc->port->vcpi.aligned_pbn;
+ }
+ }
+
+ NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
+ msto->encoder.name, msto->head->base.base.name,
+ args.vcpi.start_slot, args.vcpi.num_slots,
+ args.vcpi.pbn, args.vcpi.aligned_pbn);
+ nvif_mthd(&drm->display->disp, 0, &args, sizeof(args));
+}
+
+static int
+nv50_msto_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct nv50_mstc *mstc = nv50_mstc(conn_state->connector);
+ struct nv50_mstm *mstm = mstc->mstm;
+ int bpp = conn_state->connector->display_info.bpc * 3;
+ int slots;
+
+ mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, bpp);
+
+ slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
+ if (slots < 0)
+ return slots;
+
+ return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+ mstc->native);
+}
+
+static void
+nv50_msto_enable(struct drm_encoder *encoder)
+{
+ struct nv50_head *head = nv50_head(encoder->crtc);
+ struct nv50_msto *msto = nv50_msto(encoder);
+ struct nv50_mstc *mstc = NULL;
+ struct nv50_mstm *mstm = NULL;
+ struct drm_connector *connector;
+ u8 proto, depth;
+ int slots;
+ bool r;
+
+ drm_for_each_connector(connector, encoder->dev) {
+ if (connector->state->best_encoder == &msto->encoder) {
+ mstc = nv50_mstc(connector);
+ mstm = mstc->mstm;
+ break;
+ }
+ }
+
+ if (WARN_ON(!mstc))
+ return;
+
+ r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, &slots);
+ WARN_ON(!r);
+
+ if (mstm->outp->dcb->sorconf.link & 1)
+ proto = 0x8;
+ else
+ proto = 0x9;
+
+ switch (mstc->connector.display_info.bpc) {
+ case 6: depth = 0x2; break;
+ case 8: depth = 0x5; break;
+ case 10:
+ default: depth = 0x6; break;
+ }
+
+ mstm->outp->update(mstm->outp, head->base.index,
+ &head->base.base.state->adjusted_mode, proto, depth);
+
+ msto->head = head;
+ msto->mstc = mstc;
+ mstm->modified = true;
+}
+
+static void
+nv50_msto_disable(struct drm_encoder *encoder)
+{
+ struct nv50_msto *msto = nv50_msto(encoder);
+ struct nv50_mstc *mstc = msto->mstc;
+ struct nv50_mstm *mstm = mstc->mstm;
+
+ if (mstc->port)
+ drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
+
+ mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
+ mstm->modified = true;
+ msto->disabled = true;
+}
+
+static const struct drm_encoder_helper_funcs
+nv50_msto_help = {
+ .disable = nv50_msto_disable,
+ .enable = nv50_msto_enable,
+ .atomic_check = nv50_msto_atomic_check,
+};
+
+static void
+nv50_msto_destroy(struct drm_encoder *encoder)
+{
+ struct nv50_msto *msto = nv50_msto(encoder);
+ drm_encoder_cleanup(&msto->encoder);
+ kfree(msto);
+}
+
+static const struct drm_encoder_funcs
+nv50_msto = {
+ .destroy = nv50_msto_destroy,
+};
+
+static int
+nv50_msto_new(struct drm_device *dev, u32 heads, const char *name, int id,
+ struct nv50_msto **pmsto)
+{
+ struct nv50_msto *msto;
+ int ret;
+
+ if (!(msto = *pmsto = kzalloc(sizeof(*msto), GFP_KERNEL)))
+ return -ENOMEM;
+
+ ret = drm_encoder_init(dev, &msto->encoder, &nv50_msto,
+ DRM_MODE_ENCODER_DPMST, "%s-mst-%d", name, id);
+ if (ret) {
+ kfree(*pmsto);
+ *pmsto = NULL;
+ return ret;
+ }
+
+ drm_encoder_helper_add(&msto->encoder, &nv50_msto_help);
+ msto->encoder.possible_crtcs = heads;
+ return 0;
+}
+
+static struct drm_encoder *
+nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
+ struct drm_connector_state *connector_state)
+{
+ struct nv50_head *head = nv50_head(connector_state->crtc);
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+ if (mstc->port) {
+ struct nv50_mstm *mstm = mstc->mstm;
+ return &mstm->msto[head->base.index]->encoder;
+ }
+ return NULL;
+}
+
+static struct drm_encoder *
+nv50_mstc_best_encoder(struct drm_connector *connector)
+{
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+ if (mstc->port) {
+ struct nv50_mstm *mstm = mstc->mstm;
+ return &mstm->msto[0]->encoder;
+ }
+ return NULL;
+}
+
+static enum drm_mode_status
+nv50_mstc_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
+}
+
+static int
+nv50_mstc_get_modes(struct drm_connector *connector)
+{
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+ int ret = 0;
+
+ mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port);
+ drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid);
+ if (mstc->edid) {
+ ret = drm_add_edid_modes(&mstc->connector, mstc->edid);
+ drm_edid_to_eld(&mstc->connector, mstc->edid);
+ }
+
+ if (!mstc->connector.display_info.bpc)
+ mstc->connector.display_info.bpc = 8;
+
+ if (mstc->native)
+ drm_mode_destroy(mstc->connector.dev, mstc->native);
+ mstc->native = nouveau_conn_native_mode(&mstc->connector);
+ return ret;
+}
+
+static const struct drm_connector_helper_funcs
+nv50_mstc_help = {
+ .get_modes = nv50_mstc_get_modes,
+ .mode_valid = nv50_mstc_mode_valid,
+ .best_encoder = nv50_mstc_best_encoder,
+ .atomic_best_encoder = nv50_mstc_atomic_best_encoder,
+};
+
+static enum drm_connector_status
+nv50_mstc_detect(struct drm_connector *connector, bool force)
+{
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+ if (!mstc->port)
+ return connector_status_disconnected;
+ return drm_dp_mst_detect_port(connector, mstc->port->mgr, mstc->port);
+}
+
+static void
+nv50_mstc_destroy(struct drm_connector *connector)
+{
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+ drm_connector_cleanup(&mstc->connector);
+ kfree(mstc);
+}
+
+static const struct drm_connector_funcs
+nv50_mstc = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .reset = nouveau_conn_reset,
+ .detect = nv50_mstc_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = drm_atomic_helper_connector_set_property,
+ .destroy = nv50_mstc_destroy,
+ .atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+ .atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+ .atomic_set_property = nouveau_conn_atomic_set_property,
+ .atomic_get_property = nouveau_conn_atomic_get_property,
+};
+
+static int
+nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
+ const char *path, struct nv50_mstc **pmstc)
+{
+ struct drm_device *dev = mstm->outp->base.base.dev;
+ struct nv50_mstc *mstc;
+ int ret, i;
+
+ if (!(mstc = *pmstc = kzalloc(sizeof(*mstc), GFP_KERNEL)))
+ return -ENOMEM;
+ mstc->mstm = mstm;
+ mstc->port = port;
+
+ ret = drm_connector_init(dev, &mstc->connector, &nv50_mstc,
+ DRM_MODE_CONNECTOR_DisplayPort);
+ if (ret) {
+ kfree(*pmstc);
+ *pmstc = NULL;
+ return ret;
+ }
+
+ drm_connector_helper_add(&mstc->connector, &nv50_mstc_help);
+
+ mstc->connector.funcs->reset(&mstc->connector);
+ nouveau_conn_attach_properties(&mstc->connector);
+
+ for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto; i++)
+ drm_mode_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder);
+
+ drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0);
+ drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0);
+ drm_mode_connector_set_path_property(&mstc->connector, path);
+ return 0;
+}
+
+static void
+nv50_mstm_cleanup(struct nv50_mstm *mstm)
+{
+ struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
+ struct drm_encoder *encoder;
+ int ret;
+
+ NV_ATOMIC(drm, "%s: mstm cleanup\n", mstm->outp->base.base.name);
+ ret = drm_dp_check_act_status(&mstm->mgr);
+
+ ret = drm_dp_update_payload_part2(&mstm->mgr);
+
+ drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
+ if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+ struct nv50_msto *msto = nv50_msto(encoder);
+ struct nv50_mstc *mstc = msto->mstc;
+ if (mstc && mstc->mstm == mstm)
+ nv50_msto_cleanup(msto);
+ }
+ }
+
+ mstm->modified = false;
+}
+
+static void
+nv50_mstm_prepare(struct nv50_mstm *mstm)
+{
+ struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
+ struct drm_encoder *encoder;
+ int ret;
+
+ NV_ATOMIC(drm, "%s: mstm prepare\n", mstm->outp->base.base.name);
+ ret = drm_dp_update_payload_part1(&mstm->mgr);
+
+ drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
+ if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+ struct nv50_msto *msto = nv50_msto(encoder);
+ struct nv50_mstc *mstc = msto->mstc;
+ if (mstc && mstc->mstm == mstm)
+ nv50_msto_prepare(msto);
+ }
+ }
+}
+
+static void
+nv50_mstm_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct nv50_mstm *mstm = nv50_mstm(mgr);
+ drm_kms_helper_hotplug_event(mstm->outp->base.base.dev);
+}
+
+static void
+nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_connector *connector)
+{
+ struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct nv50_mstc *mstc = nv50_mstc(connector);
+
+ drm_connector_unregister(&mstc->connector);
+
+ drm_modeset_lock_all(drm->dev);
+ drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
+ mstc->port = NULL;
+ drm_modeset_unlock_all(drm->dev);
+
+ drm_connector_unreference(&mstc->connector);
+}
+
+static void
+nv50_mstm_register_connector(struct drm_connector *connector)
+{
+ struct nouveau_drm *drm = nouveau_drm(connector->dev);
+
+ drm_modeset_lock_all(drm->dev);
+ drm_fb_helper_add_one_connector(&drm->fbcon->helper, connector);
+ drm_modeset_unlock_all(drm->dev);
+
+ drm_connector_register(connector);
+}
+
+static struct drm_connector *
+nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port, const char *path)
+{
+ struct nv50_mstm *mstm = nv50_mstm(mgr);
+ struct nv50_mstc *mstc;
+ int ret;
+
+ ret = nv50_mstc_new(mstm, port, path, &mstc);
+ if (ret) {
+ if (mstc)
+ mstc->connector.funcs->destroy(&mstc->connector);
+ return NULL;
+ }
+
+ return &mstc->connector;
+}
+
+static const struct drm_dp_mst_topology_cbs
+nv50_mstm = {
+ .add_connector = nv50_mstm_add_connector,
+ .register_connector = nv50_mstm_register_connector,
+ .destroy_connector = nv50_mstm_destroy_connector,
+ .hotplug = nv50_mstm_hotplug,
+};
+
+void
+nv50_mstm_service(struct nv50_mstm *mstm)
+{
+ struct drm_dp_aux *aux = mstm->mgr.aux;
+ bool handled = true;
+ int ret;
+ u8 esi[8] = {};
+
+ while (handled) {
+ ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
+ if (ret != 8) {
+ drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
+ return;
+ }
+
+ drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled);
+ if (!handled)
+ break;
+
+ drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], 3);
+ }
+}
+
+void
+nv50_mstm_remove(struct nv50_mstm *mstm)
+{
+ if (mstm)
+ drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
+}
+
+static int
+nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
+{
+ struct nouveau_encoder *outp = mstm->outp;
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_dp_mst_link_v0 mst;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_LINK,
+ .base.hasht = outp->dcb->hasht,
+ .base.hashm = outp->dcb->hashm,
+ .mst.state = state,
+ };
+ struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
+ struct nvif_object *disp = &drm->display->disp;
+ int ret;
+
+ if (dpcd >= 0x12) {
+ ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CTRL, &dpcd);
+ if (ret < 0)
+ return ret;
+
+ dpcd &= ~DP_MST_EN;
+ if (state)
+ dpcd |= DP_MST_EN;
+
+ ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, dpcd);
+ if (ret < 0)
+ return ret;
+ }
+
+ return nvif_mthd(disp, 0, &args, sizeof(args));
+}
+
+int
+nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow)
+{
+ int ret, state = 0;
+
+ if (!mstm)
+ return 0;
+
+ if (dpcd[0] >= 0x12) {
+ ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]);
+ if (ret < 0)
+ return ret;
+
+ if (!(dpcd[1] & DP_MST_CAP))
+ dpcd[0] = 0x11;
+ else
+ state = allow;
+ }
+
+ ret = nv50_mstm_enable(mstm, dpcd[0], state);
+ if (ret)
+ return ret;
+
+ ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, state);
+ if (ret)
+ return nv50_mstm_enable(mstm, dpcd[0], 0);
+
+ return mstm->mgr.mst_state;
+}
+
+static void
+nv50_mstm_fini(struct nv50_mstm *mstm)
+{
+ if (mstm && mstm->mgr.mst_state)
+ drm_dp_mst_topology_mgr_suspend(&mstm->mgr);
+}
+
+static void
+nv50_mstm_init(struct nv50_mstm *mstm)
+{
+ if (mstm && mstm->mgr.mst_state)
+ drm_dp_mst_topology_mgr_resume(&mstm->mgr);
+}
+
+static void
+nv50_mstm_del(struct nv50_mstm **pmstm)
+{
+ struct nv50_mstm *mstm = *pmstm;
+ if (mstm) {
+ kfree(*pmstm);
+ *pmstm = NULL;
+ }
+}
+
+static int
+nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max,
+ int conn_base_id, struct nv50_mstm **pmstm)
+{
+ const int max_payloads = hweight8(outp->dcb->heads);
+ struct drm_device *dev = outp->base.base.dev;
+ struct nv50_mstm *mstm;
+ int ret, i;
+ u8 dpcd;
+
+ /* This is a workaround for some monitors not functioning
+ * correctly in MST mode on initial module load. I think
+ * some bad interaction with the VBIOS may be responsible.
+ *
+ * A good ol' off and on again seems to work here ;)
+ */
+ ret = drm_dp_dpcd_readb(aux, DP_DPCD_REV, &dpcd);
+ if (ret >= 0 && dpcd >= 0x12)
+ drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0);
+
+ if (!(mstm = *pmstm = kzalloc(sizeof(*mstm), GFP_KERNEL)))
+ return -ENOMEM;
+ mstm->outp = outp;
+ mstm->mgr.cbs = &nv50_mstm;
+
+ ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev->dev, aux, aux_max,
+ max_payloads, conn_base_id);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < max_payloads; i++) {
+ ret = nv50_msto_new(dev, outp->dcb->heads, outp->base.base.name,
+ i, &mstm->msto[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
/******************************************************************************
@@ -1861,89 +3452,91 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
.base.hashm = nv_encoder->dcb->hashm,
.pwr.state = mode == DRM_MODE_DPMS_ON,
};
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_dp_pwr_v0 pwr;
- } link = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_DP_PWR,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = nv_encoder->dcb->hashm,
- .pwr.state = mode == DRM_MODE_DPMS_ON,
- };
- struct drm_device *dev = encoder->dev;
- struct drm_encoder *partner;
- nv_encoder->last_dpms = mode;
-
- list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
- struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
-
- if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
- continue;
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
+}
- if (nv_partner != nv_encoder &&
- nv_partner->dcb->or == nv_encoder->dcb->or) {
- if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
- return;
- break;
- }
- }
+static void
+nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head,
+ struct drm_display_mode *mode, u8 proto, u8 depth)
+{
+ struct nv50_dmac *core = &nv50_mast(nv_encoder->base.base.dev)->base;
+ u32 *push;
- if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
- args.pwr.state = 1;
- nvif_mthd(disp->disp, 0, &args, sizeof(args));
- nvif_mthd(disp->disp, 0, &link, sizeof(link));
+ if (!mode) {
+ nv_encoder->ctrl &= ~BIT(head);
+ if (!(nv_encoder->ctrl & 0x0000000f))
+ nv_encoder->ctrl = 0;
} else {
- nvif_mthd(disp->disp, 0, &args, sizeof(args));
+ nv_encoder->ctrl |= proto << 8;
+ nv_encoder->ctrl |= BIT(head);
}
-}
-static void
-nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data)
-{
- struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev);
- u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push;
- if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+ if ((push = evo_wait(core, 6))) {
+ if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ if (mode) {
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ nv_encoder->ctrl |= 0x00001000;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ nv_encoder->ctrl |= 0x00002000;
+ nv_encoder->ctrl |= depth << 16;
+ }
evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1);
- evo_data(push, (nv_encoder->ctrl = temp));
} else {
+ if (mode) {
+ u32 magic = 0x31ec6000 | (head << 25);
+ u32 syncs = 0x00000001;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ syncs |= 0x00000008;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ syncs |= 0x00000010;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ magic |= 0x00000001;
+
+ evo_mthd(push, 0x0404 + (head * 0x300), 2);
+ evo_data(push, syncs | (depth << 6));
+ evo_data(push, magic);
+ }
evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
- evo_data(push, (nv_encoder->ctrl = temp));
}
- evo_kick(push, mast);
+ evo_data(push, nv_encoder->ctrl);
+ evo_kick(push, core);
}
}
static void
-nv50_sor_disconnect(struct drm_encoder *encoder)
+nv50_sor_disable(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
- nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
nv_encoder->crtc = NULL;
if (nv_crtc) {
- nv50_crtc_prepare(&nv_crtc->base);
- nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0);
- nv50_audio_disconnect(encoder, nv_crtc);
- nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc);
- }
-}
+ struct nvkm_i2c_aux *aux = nv_encoder->aux;
+ u8 pwr;
-static void
-nv50_sor_commit(struct drm_encoder *encoder)
-{
+ if (aux) {
+ int ret = nvkm_rdaux(aux, DP_SET_POWER, &pwr, 1);
+ if (ret == 0) {
+ pwr &= ~DP_SET_POWER_MASK;
+ pwr |= DP_SET_POWER_D3;
+ nvkm_wraux(aux, DP_SET_POWER, &pwr, 1);
+ }
+ }
+
+ nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
+ nv50_audio_disable(encoder, nv_crtc);
+ nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc);
+ }
}
static void
-nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
- struct drm_display_mode *mode)
+nv50_sor_enable(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
struct {
struct nv50_disp_mthd_v1 base;
struct nv50_disp_sor_lvds_script_v0 lvds;
@@ -1954,13 +3547,10 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
.base.hashm = nv_encoder->dcb->hashm,
};
struct nv50_disp *disp = nv50_disp(encoder->dev);
- struct nv50_mast *mast = nv50_mast(encoder->dev);
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector;
struct nvbios *bios = &drm->vbios;
- u32 mask, ctrl;
- u8 owner = 1 << nv_crtc->index;
u8 proto = 0xf;
u8 depth = 0x0;
@@ -1985,7 +3575,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
proto = 0x2;
}
- nv50_hdmi_mode_set(&nv_encoder->base.base, mode);
+ nv50_hdmi_enable(&nv_encoder->base.base, mode);
break;
case DCB_OUTPUT_LVDS:
proto = 0x0;
@@ -2019,94 +3609,60 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
break;
case DCB_OUTPUT_DP:
- if (nv_connector->base.display_info.bpc == 6) {
- nv_encoder->dp.datarate = mode->clock * 18 / 8;
+ if (nv_connector->base.display_info.bpc == 6)
depth = 0x2;
- } else
- if (nv_connector->base.display_info.bpc == 8) {
- nv_encoder->dp.datarate = mode->clock * 24 / 8;
+ else
+ if (nv_connector->base.display_info.bpc == 8)
depth = 0x5;
- } else {
- nv_encoder->dp.datarate = mode->clock * 30 / 8;
+ else
depth = 0x6;
- }
if (nv_encoder->dcb->sorconf.link & 1)
proto = 0x8;
else
proto = 0x9;
- nv50_audio_mode_set(encoder, mode);
+
+ nv50_audio_enable(encoder, mode);
break;
default:
BUG_ON(1);
break;
}
- nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON);
-
- if (nv50_vers(mast) >= GF110_DISP) {
- u32 *push = evo_wait(mast, 3);
- if (push) {
- u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
- u32 syncs = 0x00000001;
-
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- syncs |= 0x00000008;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- syncs |= 0x00000010;
-
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- magic |= 0x00000001;
-
- evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
- evo_data(push, syncs | (depth << 6));
- evo_data(push, magic);
- evo_kick(push, mast);
- }
-
- ctrl = proto << 8;
- mask = 0x00000f00;
- } else {
- ctrl = (depth << 16) | (proto << 8);
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- ctrl |= 0x00001000;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- ctrl |= 0x00002000;
- mask = 0x000f3f00;
- }
-
- nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner);
+ nv_encoder->update(nv_encoder, nv_crtc->index, mode, proto, depth);
}
+static const struct drm_encoder_helper_funcs
+nv50_sor_help = {
+ .dpms = nv50_sor_dpms,
+ .atomic_check = nv50_outp_atomic_check,
+ .enable = nv50_sor_enable,
+ .disable = nv50_sor_disable,
+};
+
static void
nv50_sor_destroy(struct drm_encoder *encoder)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ nv50_mstm_del(&nv_encoder->dp.mstm);
drm_encoder_cleanup(encoder);
kfree(encoder);
}
-static const struct drm_encoder_helper_funcs nv50_sor_hfunc = {
- .dpms = nv50_sor_dpms,
- .mode_fixup = nv50_encoder_mode_fixup,
- .prepare = nv50_sor_disconnect,
- .commit = nv50_sor_commit,
- .mode_set = nv50_sor_mode_set,
- .disable = nv50_sor_disconnect,
- .get_crtc = nv50_display_crtc_get,
-};
-
-static const struct drm_encoder_funcs nv50_sor_func = {
+static const struct drm_encoder_funcs
+nv50_sor_func = {
.destroy = nv50_sor_destroy,
};
static int
nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nvkm_i2c *i2c = nvxx_i2c(&drm->device);
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
- int type;
+ int type, ret;
switch (dcbe->type) {
case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break;
@@ -2122,7 +3678,16 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
return -ENOMEM;
nv_encoder->dcb = dcbe;
nv_encoder->or = ffs(dcbe->or) - 1;
- nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+ nv_encoder->update = nv50_sor_update;
+
+ encoder = to_drm_encoder(nv_encoder);
+ encoder->possible_crtcs = dcbe->heads;
+ encoder->possible_clones = 0;
+ drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type,
+ "sor-%04x-%04x", dcbe->hasht, dcbe->hashm);
+ drm_encoder_helper_add(encoder, &nv50_sor_help);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
if (dcbe->type == DCB_OUTPUT_DP) {
struct nvkm_i2c_aux *aux =
@@ -2131,6 +3696,15 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
nv_encoder->i2c = &aux->i2c;
nv_encoder->aux = aux;
}
+
+ /*TODO: Use DP Info Table to check for support. */
+ if (nv50_disp(encoder->dev)->disp->oclass >= GF110_DISP) {
+ ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
+ nv_connector->base.base.id,
+ &nv_encoder->dp.mstm);
+ if (ret)
+ return ret;
+ }
} else {
struct nvkm_i2c_bus *bus =
nvkm_i2c_bus_find(i2c, dcbe->i2c_index);
@@ -2138,20 +3712,12 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
nv_encoder->i2c = &bus->i2c;
}
- encoder = to_drm_encoder(nv_encoder);
- encoder->possible_crtcs = dcbe->heads;
- encoder->possible_clones = 0;
- drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type, NULL);
- drm_encoder_helper_add(encoder, &nv50_sor_hfunc);
-
- drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
/******************************************************************************
* PIOR
*****************************************************************************/
-
static void
nv50_pior_dpms(struct drm_encoder *encoder, int mode)
{
@@ -2172,30 +3738,48 @@ nv50_pior_dpms(struct drm_encoder *encoder, int mode)
nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
-static bool
-nv50_pior_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int
+nv50_pior_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
- if (!nv50_encoder_mode_fixup(encoder, mode, adjusted_mode))
- return false;
- adjusted_mode->clock *= 2;
- return true;
+ int ret = nv50_outp_atomic_check(encoder, crtc_state, conn_state);
+ if (ret)
+ return ret;
+ crtc_state->adjusted_mode.clock *= 2;
+ return 0;
}
static void
-nv50_pior_commit(struct drm_encoder *encoder)
+nv50_pior_disable(struct drm_encoder *encoder)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nv50_mast *mast = nv50_mast(encoder->dev);
+ const int or = nv_encoder->or;
+ u32 *push;
+
+ if (nv_encoder->crtc) {
+ push = evo_wait(mast, 4);
+ if (push) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+ evo_mthd(push, 0x0700 + (or * 0x040), 1);
+ evo_data(push, 0x00000000);
+ }
+ evo_kick(push, mast);
+ }
+ }
+
+ nv_encoder->crtc = NULL;
}
static void
-nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+nv50_pior_enable(struct drm_encoder *encoder)
{
struct nv50_mast *mast = nv50_mast(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nouveau_connector *nv_connector;
+ struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
u8 owner = 1 << nv_crtc->index;
u8 proto, depth;
u32 *push;
@@ -2218,8 +3802,6 @@ nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
break;
}
- nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON);
-
push = evo_wait(mast, 8);
if (push) {
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
@@ -2238,29 +3820,13 @@ nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
nv_encoder->crtc = encoder->crtc;
}
-static void
-nv50_pior_disconnect(struct drm_encoder *encoder)
-{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_mast *mast = nv50_mast(encoder->dev);
- const int or = nv_encoder->or;
- u32 *push;
-
- if (nv_encoder->crtc) {
- nv50_crtc_prepare(nv_encoder->crtc);
-
- push = evo_wait(mast, 4);
- if (push) {
- if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
- evo_mthd(push, 0x0700 + (or * 0x040), 1);
- evo_data(push, 0x00000000);
- }
- evo_kick(push, mast);
- }
- }
-
- nv_encoder->crtc = NULL;
-}
+static const struct drm_encoder_helper_funcs
+nv50_pior_help = {
+ .dpms = nv50_pior_dpms,
+ .atomic_check = nv50_pior_atomic_check,
+ .enable = nv50_pior_enable,
+ .disable = nv50_pior_disable,
+};
static void
nv50_pior_destroy(struct drm_encoder *encoder)
@@ -2269,17 +3835,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
kfree(encoder);
}
-static const struct drm_encoder_helper_funcs nv50_pior_hfunc = {
- .dpms = nv50_pior_dpms,
- .mode_fixup = nv50_pior_mode_fixup,
- .prepare = nv50_pior_disconnect,
- .commit = nv50_pior_commit,
- .mode_set = nv50_pior_mode_set,
- .disable = nv50_pior_disconnect,
- .get_crtc = nv50_display_crtc_get,
-};
-
-static const struct drm_encoder_funcs nv50_pior_func = {
+static const struct drm_encoder_funcs
+nv50_pior_func = {
.destroy = nv50_pior_destroy,
};
@@ -2321,149 +3878,464 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
encoder = to_drm_encoder(nv_encoder);
encoder->possible_crtcs = dcbe->heads;
encoder->possible_clones = 0;
- drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, NULL);
- drm_encoder_helper_add(encoder, &nv50_pior_hfunc);
+ drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type,
+ "pior-%04x-%04x", dcbe->hasht, dcbe->hashm);
+ drm_encoder_helper_add(encoder, &nv50_pior_help);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
/******************************************************************************
- * Framebuffer
+ * Atomic
*****************************************************************************/
static void
-nv50_fbdma_fini(struct nv50_fbdma *fbdma)
+nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(fbdma->base); i++)
- nvif_object_fini(&fbdma->base[i]);
- nvif_object_fini(&fbdma->core);
- list_del(&fbdma->head);
- kfree(fbdma);
+ struct nv50_disp *disp = nv50_disp(drm->dev);
+ struct nv50_dmac *core = &disp->mast.base;
+ struct nv50_mstm *mstm;
+ struct drm_encoder *encoder;
+ u32 *push;
+
+ NV_ATOMIC(drm, "commit core %08x\n", interlock);
+
+ drm_for_each_encoder(encoder, drm->dev) {
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+ mstm = nouveau_encoder(encoder)->dp.mstm;
+ if (mstm && mstm->modified)
+ nv50_mstm_prepare(mstm);
+ }
+ }
+
+ if ((push = evo_wait(core, 5))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, 0x80000000);
+ evo_mthd(push, 0x0080, 2);
+ evo_data(push, interlock);
+ evo_data(push, 0x00000000);
+ nouveau_bo_wr32(disp->sync, 0, 0x00000000);
+ evo_kick(push, core);
+ if (nvif_msec(&drm->device, 2000ULL,
+ if (nouveau_bo_rd32(disp->sync, 0))
+ break;
+ usleep_range(1, 2);
+ ) < 0)
+ NV_ERROR(drm, "EVO timeout\n");
+ }
+
+ drm_for_each_encoder(encoder, drm->dev) {
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+ mstm = nouveau_encoder(encoder)->dp.mstm;
+ if (mstm && mstm->modified)
+ nv50_mstm_cleanup(mstm);
+ }
+ }
}
-static int
-nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kind)
+static void
+nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
{
+ struct drm_device *dev = state->dev;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ struct drm_plane_state *plane_state;
+ struct drm_plane *plane;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nv50_disp *disp = nv50_disp(dev);
- struct nv50_mast *mast = nv50_mast(dev);
- struct __attribute__ ((packed)) {
- struct nv_dma_v0 base;
- union {
- struct nv50_dma_v0 nv50;
- struct gf100_dma_v0 gf100;
- struct gf119_dma_v0 gf119;
- };
- } args = {};
- struct nv50_fbdma *fbdma;
- struct drm_crtc *crtc;
- u32 size = sizeof(args.base);
- int ret;
+ struct nv50_atom *atom = nv50_atom(state);
+ struct nv50_outp_atom *outp, *outt;
+ u32 interlock_core = 0;
+ u32 interlock_chan = 0;
+ int i;
+
+ NV_ATOMIC(drm, "commit %d %d\n", atom->lock_core, atom->flush_disable);
+ drm_atomic_helper_wait_for_fences(dev, state, false);
+ drm_atomic_helper_wait_for_dependencies(state);
+ drm_atomic_helper_update_legacy_modeset_state(dev, state);
- list_for_each_entry(fbdma, &disp->fbdma, head) {
- if (fbdma->core.handle == name)
- return 0;
+ if (atom->lock_core)
+ mutex_lock(&disp->mutex);
+
+ /* Disable head(s). */
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ struct nv50_head_atom *asyh = nv50_head_atom(crtc->state);
+ struct nv50_head *head = nv50_head(crtc);
+
+ NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name,
+ asyh->clr.mask, asyh->set.mask);
+
+ if (asyh->clr.mask) {
+ nv50_head_flush_clr(head, asyh, atom->flush_disable);
+ interlock_core |= 1;
+ }
}
- fbdma = kzalloc(sizeof(*fbdma), GFP_KERNEL);
- if (!fbdma)
- return -ENOMEM;
- list_add(&fbdma->head, &disp->fbdma);
+ /* Disable plane(s). */
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
- args.base.target = NV_DMA_V0_TARGET_VRAM;
- args.base.access = NV_DMA_V0_ACCESS_RDWR;
- args.base.start = offset;
- args.base.limit = offset + length - 1;
+ NV_ATOMIC(drm, "%s: clr %02x (set %02x)\n", plane->name,
+ asyw->clr.mask, asyw->set.mask);
+ if (!asyw->clr.mask)
+ continue;
- if (drm->device.info.chipset < 0x80) {
- args.nv50.part = NV50_DMA_V0_PART_256;
- size += sizeof(args.nv50);
- } else
- if (drm->device.info.chipset < 0xc0) {
- args.nv50.part = NV50_DMA_V0_PART_256;
- args.nv50.kind = kind;
- size += sizeof(args.nv50);
- } else
- if (drm->device.info.chipset < 0xd0) {
- args.gf100.kind = kind;
- size += sizeof(args.gf100);
- } else {
- args.gf119.page = GF119_DMA_V0_PAGE_LP;
- args.gf119.kind = kind;
- size += sizeof(args.gf119);
+ interlock_chan |= nv50_wndw_flush_clr(wndw, interlock_core,
+ atom->flush_disable,
+ asyw);
+ }
+
+ /* Disable output path(s). */
+ list_for_each_entry(outp, &atom->outp, head) {
+ const struct drm_encoder_helper_funcs *help;
+ struct drm_encoder *encoder;
+
+ encoder = outp->encoder;
+ help = encoder->helper_private;
+
+ NV_ATOMIC(drm, "%s: clr %02x (set %02x)\n", encoder->name,
+ outp->clr.mask, outp->set.mask);
+
+ if (outp->clr.mask) {
+ help->disable(encoder);
+ interlock_core |= 1;
+ if (outp->flush_disable) {
+ nv50_disp_atomic_commit_core(drm, interlock_chan);
+ interlock_core = 0;
+ interlock_chan = 0;
+ }
+ }
+ }
+
+ /* Flush disable. */
+ if (interlock_core) {
+ if (atom->flush_disable) {
+ nv50_disp_atomic_commit_core(drm, interlock_chan);
+ interlock_core = 0;
+ interlock_chan = 0;
+ }
}
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ /* Update output path(s). */
+ list_for_each_entry_safe(outp, outt, &atom->outp, head) {
+ const struct drm_encoder_helper_funcs *help;
+ struct drm_encoder *encoder;
+
+ encoder = outp->encoder;
+ help = encoder->helper_private;
+
+ NV_ATOMIC(drm, "%s: set %02x (clr %02x)\n", encoder->name,
+ outp->set.mask, outp->clr.mask);
+
+ if (outp->set.mask) {
+ help->enable(encoder);
+ interlock_core = 1;
+ }
+
+ list_del(&outp->head);
+ kfree(outp);
+ }
+
+ /* Update head(s). */
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ struct nv50_head_atom *asyh = nv50_head_atom(crtc->state);
struct nv50_head *head = nv50_head(crtc);
- int ret = nvif_object_init(&head->sync.base.base.user, name,
- NV_DMA_IN_MEMORY, &args, size,
- &fbdma->base[head->base.index]);
- if (ret) {
- nv50_fbdma_fini(fbdma);
- return ret;
+
+ NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name,
+ asyh->set.mask, asyh->clr.mask);
+
+ if (asyh->set.mask) {
+ nv50_head_flush_set(head, asyh);
+ interlock_core = 1;
}
}
- ret = nvif_object_init(&mast->base.base.user, name, NV_DMA_IN_MEMORY,
- &args, size, &fbdma->core);
- if (ret) {
- nv50_fbdma_fini(fbdma);
+ /* Update plane(s). */
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+
+ NV_ATOMIC(drm, "%s: set %02x (clr %02x)\n", plane->name,
+ asyw->set.mask, asyw->clr.mask);
+ if ( !asyw->set.mask &&
+ (!asyw->clr.mask || atom->flush_disable))
+ continue;
+
+ interlock_chan |= nv50_wndw_flush_set(wndw, interlock_core, asyw);
+ }
+
+ /* Flush update. */
+ if (interlock_core) {
+ if (!interlock_chan && atom->state.legacy_cursor_update) {
+ u32 *push = evo_wait(&disp->mast, 2);
+ if (push) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &disp->mast);
+ }
+ } else {
+ nv50_disp_atomic_commit_core(drm, interlock_chan);
+ }
+ }
+
+ if (atom->lock_core)
+ mutex_unlock(&disp->mutex);
+
+ /* Wait for HW to signal completion. */
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ int ret = nv50_wndw_wait_armed(wndw, asyw);
+ if (ret)
+ NV_ERROR(drm, "%s: timeout\n", plane->name);
+ }
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc->state->event) {
+ unsigned long flags;
+ /* Get correct count/ts if racing with vblank irq */
+ drm_accurate_vblank_count(crtc);
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+ }
+
+ drm_atomic_helper_commit_hw_done(state);
+ drm_atomic_helper_cleanup_planes(dev, state);
+ drm_atomic_helper_commit_cleanup_done(state);
+ drm_atomic_state_put(state);
+}
+
+static void
+nv50_disp_atomic_commit_work(struct work_struct *work)
+{
+ struct drm_atomic_state *state =
+ container_of(work, typeof(*state), commit_work);
+ nv50_disp_atomic_commit_tail(state);
+}
+
+static int
+nv50_disp_atomic_commit(struct drm_device *dev,
+ struct drm_atomic_state *state, bool nonblock)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nv50_disp *disp = nv50_disp(dev);
+ struct drm_plane_state *plane_state;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ bool active = false;
+ int ret, i;
+
+ ret = pm_runtime_get_sync(dev->dev);
+ if (ret < 0 && ret != -EACCES)
return ret;
+
+ ret = drm_atomic_helper_setup_commit(state, nonblock);
+ if (ret)
+ goto done;
+
+ INIT_WORK(&state->commit_work, nv50_disp_atomic_commit_work);
+
+ ret = drm_atomic_helper_prepare_planes(dev, state);
+ if (ret)
+ goto done;
+
+ if (!nonblock) {
+ ret = drm_atomic_helper_wait_for_fences(dev, state, true);
+ if (ret)
+ goto done;
+ }
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ if (asyw->set.image) {
+ asyw->ntfy.handle = wndw->dmac->sync.handle;
+ asyw->ntfy.offset = wndw->ntfy;
+ asyw->ntfy.awaken = false;
+ asyw->set.ntfy = true;
+ nouveau_bo_wr32(disp->sync, wndw->ntfy / 4, 0x00000000);
+ wndw->ntfy ^= 0x10;
+ }
+ }
+
+ drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
+
+ if (nonblock)
+ queue_work(system_unbound_wq, &state->commit_work);
+ else
+ nv50_disp_atomic_commit_tail(state);
+
+ drm_for_each_crtc(crtc, dev) {
+ if (crtc->state->enable) {
+ if (!drm->have_disp_power_ref) {
+ drm->have_disp_power_ref = true;
+ return ret;
+ }
+ active = true;
+ break;
+ }
+ }
+
+ if (!active && drm->have_disp_power_ref) {
+ pm_runtime_put_autosuspend(dev->dev);
+ drm->have_disp_power_ref = false;
+ }
+
+done:
+ pm_runtime_put_autosuspend(dev->dev);
+ return ret;
+}
+
+static struct nv50_outp_atom *
+nv50_disp_outp_atomic_add(struct nv50_atom *atom, struct drm_encoder *encoder)
+{
+ struct nv50_outp_atom *outp;
+
+ list_for_each_entry(outp, &atom->outp, head) {
+ if (outp->encoder == encoder)
+ return outp;
+ }
+
+ outp = kzalloc(sizeof(*outp), GFP_KERNEL);
+ if (!outp)
+ return ERR_PTR(-ENOMEM);
+
+ list_add(&outp->head, &atom->outp);
+ outp->encoder = encoder;
+ return outp;
+}
+
+static int
+nv50_disp_outp_atomic_check_clr(struct nv50_atom *atom,
+ struct drm_connector *connector)
+{
+ struct drm_encoder *encoder = connector->state->best_encoder;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ struct nv50_outp_atom *outp;
+
+ if (!(crtc = connector->state->crtc))
+ return 0;
+
+ crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc);
+ if (crtc->state->active && drm_atomic_crtc_needs_modeset(crtc_state)) {
+ outp = nv50_disp_outp_atomic_add(atom, encoder);
+ if (IS_ERR(outp))
+ return PTR_ERR(outp);
+
+ if (outp->encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+ outp->flush_disable = true;
+ atom->flush_disable = true;
+ }
+ outp->clr.ctrl = true;
+ atom->lock_core = true;
}
return 0;
}
-static void
-nv50_fb_dtor(struct drm_framebuffer *fb)
+static int
+nv50_disp_outp_atomic_check_set(struct nv50_atom *atom,
+ struct drm_connector_state *connector_state)
{
+ struct drm_encoder *encoder = connector_state->best_encoder;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ struct nv50_outp_atom *outp;
+
+ if (!(crtc = connector_state->crtc))
+ return 0;
+
+ crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc);
+ if (crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state)) {
+ outp = nv50_disp_outp_atomic_add(atom, encoder);
+ if (IS_ERR(outp))
+ return PTR_ERR(outp);
+
+ outp->set.ctrl = true;
+ atom->lock_core = true;
+ }
+
+ return 0;
}
static int
-nv50_fb_ctor(struct drm_framebuffer *fb)
-{
- struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
- struct nouveau_drm *drm = nouveau_drm(fb->dev);
- struct nouveau_bo *nvbo = nv_fb->nvbo;
- struct nv50_disp *disp = nv50_disp(fb->dev);
- u8 kind = nouveau_bo_tile_layout(nvbo) >> 8;
- u8 tile = nvbo->tile_mode;
-
- if (drm->device.info.chipset >= 0xc0)
- tile >>= 4; /* yep.. */
-
- switch (fb->depth) {
- case 8: nv_fb->r_format = 0x1e00; break;
- case 15: nv_fb->r_format = 0xe900; break;
- case 16: nv_fb->r_format = 0xe800; break;
- case 24:
- case 32: nv_fb->r_format = 0xcf00; break;
- case 30: nv_fb->r_format = 0xd100; break;
- default:
- NV_ERROR(drm, "unknown depth %d\n", fb->depth);
- return -EINVAL;
+nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
+{
+ struct nv50_atom *atom = nv50_atom(state);
+ struct drm_connector_state *connector_state;
+ struct drm_connector *connector;
+ int ret, i;
+
+ ret = drm_atomic_helper_check(dev, state);
+ if (ret)
+ return ret;
+
+ for_each_connector_in_state(state, connector, connector_state, i) {
+ ret = nv50_disp_outp_atomic_check_clr(atom, connector);
+ if (ret)
+ return ret;
+
+ ret = nv50_disp_outp_atomic_check_set(atom, connector_state);
+ if (ret)
+ return ret;
}
- if (disp->disp->oclass < G82_DISP) {
- nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
- (fb->pitches[0] | 0x00100000);
- nv_fb->r_format |= kind << 16;
- } else
- if (disp->disp->oclass < GF110_DISP) {
- nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
- (fb->pitches[0] | 0x00100000);
- } else {
- nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
- (fb->pitches[0] | 0x01000000);
+ return 0;
+}
+
+static void
+nv50_disp_atomic_state_clear(struct drm_atomic_state *state)
+{
+ struct nv50_atom *atom = nv50_atom(state);
+ struct nv50_outp_atom *outp, *outt;
+
+ list_for_each_entry_safe(outp, outt, &atom->outp, head) {
+ list_del(&outp->head);
+ kfree(outp);
}
- nv_fb->r_handle = 0xffff0000 | kind;
- return nv50_fbdma_init(fb->dev, nv_fb->r_handle, 0,
- drm->device.info.ram_user, kind);
+ drm_atomic_state_default_clear(state);
+}
+
+static void
+nv50_disp_atomic_state_free(struct drm_atomic_state *state)
+{
+ struct nv50_atom *atom = nv50_atom(state);
+ drm_atomic_state_default_release(&atom->state);
+ kfree(atom);
}
+static struct drm_atomic_state *
+nv50_disp_atomic_state_alloc(struct drm_device *dev)
+{
+ struct nv50_atom *atom;
+ if (!(atom = kzalloc(sizeof(*atom), GFP_KERNEL)) ||
+ drm_atomic_state_init(dev, &atom->state) < 0) {
+ kfree(atom);
+ return NULL;
+ }
+ INIT_LIST_HEAD(&atom->outp);
+ return &atom->state;
+}
+
+static const struct drm_mode_config_funcs
+nv50_disp_func = {
+ .fb_create = nouveau_user_framebuffer_create,
+ .output_poll_changed = nouveau_fbcon_output_poll_changed,
+ .atomic_check = nv50_disp_atomic_check,
+ .atomic_commit = nv50_disp_atomic_commit,
+ .atomic_state_alloc = nv50_disp_atomic_state_alloc,
+ .atomic_state_clear = nv50_disp_atomic_state_clear,
+ .atomic_state_free = nv50_disp_atomic_state_free,
+};
+
/******************************************************************************
* Init
*****************************************************************************/
@@ -2471,12 +4343,30 @@ nv50_fb_ctor(struct drm_framebuffer *fb)
void
nv50_display_fini(struct drm_device *dev)
{
+ struct nouveau_encoder *nv_encoder;
+ struct drm_encoder *encoder;
+ struct drm_plane *plane;
+
+ drm_for_each_plane(plane, dev) {
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ if (plane->funcs != &nv50_wndw)
+ continue;
+ nv50_wndw_fini(wndw);
+ }
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+ nv_encoder = nouveau_encoder(encoder);
+ nv50_mstm_fini(nv_encoder->dp.mstm);
+ }
+ }
}
int
nv50_display_init(struct drm_device *dev)
{
- struct nv50_disp *disp = nv50_disp(dev);
+ struct drm_encoder *encoder;
+ struct drm_plane *plane;
struct drm_crtc *crtc;
u32 *push;
@@ -2484,16 +4374,35 @@ nv50_display_init(struct drm_device *dev)
if (!push)
return -EBUSY;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct nv50_sync *sync = nv50_sync(crtc);
-
- nv50_crtc_lut_load(crtc);
- nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data);
- }
-
evo_mthd(push, 0x0088, 1);
evo_data(push, nv50_mast(dev)->base.sync.handle);
evo_kick(push, nv50_mast(dev));
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+ const struct drm_encoder_helper_funcs *help;
+ struct nouveau_encoder *nv_encoder;
+
+ nv_encoder = nouveau_encoder(encoder);
+ help = encoder->helper_private;
+ if (help && help->dpms)
+ help->dpms(encoder, DRM_MODE_DPMS_ON);
+
+ nv50_mstm_init(nv_encoder->dp.mstm);
+ }
+ }
+
+ drm_for_each_crtc(crtc, dev) {
+ nv50_head_lut_load(crtc);
+ }
+
+ drm_for_each_plane(plane, dev) {
+ struct nv50_wndw *wndw = nv50_wndw(plane);
+ if (plane->funcs != &nv50_wndw)
+ continue;
+ nv50_wndw_init(wndw);
+ }
+
return 0;
}
@@ -2501,11 +4410,6 @@ void
nv50_display_destroy(struct drm_device *dev)
{
struct nv50_disp *disp = nv50_disp(dev);
- struct nv50_fbdma *fbdma, *fbtmp;
-
- list_for_each_entry_safe(fbdma, fbtmp, &disp->fbdma, head) {
- nv50_fbdma_fini(fbdma);
- }
nv50_dmac_destroy(&disp->mast.base, disp->disp);
@@ -2518,6 +4422,10 @@ nv50_display_destroy(struct drm_device *dev)
kfree(disp);
}
+MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
+static int nouveau_atomic = 0;
+module_param_named(atomic, nouveau_atomic, int, 0400);
+
int
nv50_display_create(struct drm_device *dev)
{
@@ -2532,15 +4440,17 @@ nv50_display_create(struct drm_device *dev)
disp = kzalloc(sizeof(*disp), GFP_KERNEL);
if (!disp)
return -ENOMEM;
- INIT_LIST_HEAD(&disp->fbdma);
+
+ mutex_init(&disp->mutex);
nouveau_display(dev)->priv = disp;
nouveau_display(dev)->dtor = nv50_display_destroy;
nouveau_display(dev)->init = nv50_display_init;
nouveau_display(dev)->fini = nv50_display_fini;
- nouveau_display(dev)->fb_ctor = nv50_fb_ctor;
- nouveau_display(dev)->fb_dtor = nv50_fb_dtor;
disp->disp = &nouveau_display(dev)->disp;
+ dev->mode_config.funcs = &nv50_disp_func;
+ if (nouveau_atomic)
+ dev->driver->driver_features |= DRIVER_ATOMIC;
/* small shared memory area we use for notifiers and semaphores */
ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2572,7 +4482,7 @@ nv50_display_create(struct drm_device *dev)
crtcs = 2;
for (i = 0; i < crtcs; i++) {
- ret = nv50_crtc_create(dev, i);
+ ret = nv50_head_create(dev, i);
if (ret)
goto out;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index 70da347aa8c5..918187cee84b 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -35,11 +35,4 @@ int nv50_display_create(struct drm_device *);
void nv50_display_destroy(struct drm_device *);
int nv50_display_init(struct drm_device *);
void nv50_display_fini(struct drm_device *);
-
-void nv50_display_flip_stop(struct drm_crtc *);
-int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
- struct nouveau_channel *, u32 swap_interval);
-
-struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head);
-
#endif /* __NV50_DISPLAY_H__ */
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index af3d3c49411a..327dcd7901ed 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -30,7 +30,7 @@ int
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -65,7 +65,7 @@ int
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -93,7 +93,7 @@ int
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
@@ -148,8 +148,8 @@ int
nv50_fbcon_accel_init(struct fb_info *info)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
- struct drm_device *dev = nfbdev->dev;
+ struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
+ struct drm_device *dev = nfbdev->helper.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
int ret, format;
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index 4d6f202b7770..f68c7054fd53 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -35,13 +35,12 @@
static int
nv50_fence_context_new(struct nouveau_channel *chan)
{
- struct drm_device *dev = chan->drm->dev;
struct nv10_fence_priv *priv = chan->drm->fence;
struct nv10_fence_chan *fctx;
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
u32 start = mem->start * PAGE_SIZE;
u32 limit = start + mem->size - 1;
- int ret, i;
+ int ret;
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
if (!fctx)
@@ -60,23 +59,6 @@ nv50_fence_context_new(struct nouveau_channel *chan)
.limit = limit,
}, sizeof(struct nv_dma_v0),
&fctx->sema);
-
- /* dma objects for display sync channel semaphore blocks */
- for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
- struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
- u32 start = bo->bo.mem.start * PAGE_SIZE;
- u32 limit = start + bo->bo.mem.size - 1;
-
- ret = nvif_object_init(&chan->user, NvEvoSema0 + i,
- NV_DMA_IN_MEMORY, &(struct nv_dma_v0) {
- .target = NV_DMA_V0_TARGET_VRAM,
- .access = NV_DMA_V0_ACCESS_RDWR,
- .start = start,
- .limit = limit,
- }, sizeof(struct nv_dma_v0),
- &fctx->head[i]);
- }
-
if (ret)
nv10_fence_context_del(chan);
return ret;
@@ -97,7 +79,7 @@ nv50_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv50_fence_context_new;
priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 127;
- priv->base.context_base = fence_context_alloc(priv->base.contexts);
+ priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock);
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 18bde9d8e6d6..52b87ae83e7b 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -28,13 +28,6 @@
#include "nv50_display.h"
-u64
-nv84_fence_crtc(struct nouveau_channel *chan, int crtc)
-{
- struct nv84_fence_chan *fctx = chan->fence;
- return fctx->dispc_vma[crtc].offset;
-}
-
static int
nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
{
@@ -110,15 +103,8 @@ nv84_fence_read(struct nouveau_channel *chan)
static void
nv84_fence_context_del(struct nouveau_channel *chan)
{
- struct drm_device *dev = chan->drm->dev;
struct nv84_fence_priv *priv = chan->drm->fence;
struct nv84_fence_chan *fctx = chan->fence;
- int i;
-
- for (i = 0; i < dev->mode_config.num_crtc; i++) {
- struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
- nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
- }
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
@@ -134,7 +120,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
struct nouveau_cli *cli = (void *)chan->user.client;
struct nv84_fence_priv *priv = chan->drm->fence;
struct nv84_fence_chan *fctx;
- int ret, i;
+ int ret;
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
if (!fctx)
@@ -154,12 +140,6 @@ nv84_fence_context_new(struct nouveau_channel *chan)
&fctx->vma_gart);
}
- /* map display semaphore buffers into channel's vm */
- for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
- struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
- ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
- }
-
if (ret)
nv84_fence_context_del(chan);
return ret;
@@ -229,7 +209,7 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_del = nv84_fence_context_del;
priv->base.contexts = fifo->nr;
- priv->base.context_base = fence_context_alloc(priv->base.contexts);
+ priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
priv->base.uevent = true;
/* Use VRAM if there is any ; otherwise fallback to system memory */
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index 054b6a056d99..90f27bfa381f 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -30,7 +30,7 @@ int
nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -65,7 +65,7 @@ int
nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
int ret;
@@ -93,7 +93,7 @@ int
nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
struct nouveau_channel *chan = drm->channel;
uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
@@ -148,8 +148,8 @@ int
nvc0_fbcon_accel_init(struct fb_info *info)
{
struct nouveau_fbdev *nfbdev = info->par;
- struct drm_device *dev = nfbdev->dev;
- struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
+ struct drm_device *dev = nfbdev->helper.dev;
+ struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
int ret, format;
diff --git a/drivers/gpu/drm/nouveau/nvif/client.c b/drivers/gpu/drm/nouveau/nvif/client.c
index 1ee9294eca2e..29c20dfd894d 100644
--- a/drivers/gpu/drm/nouveau/nvif/client.c
+++ b/drivers/gpu/drm/nouveau/nvif/client.c
@@ -55,7 +55,7 @@ nvif_client_fini(struct nvif_client *client)
}
}
-const struct nvif_driver *
+static const struct nvif_driver *
nvif_drivers[] = {
#ifdef __KERNEL__
&nvif_driver_nvkm,
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c
index b0787ff833ef..278b3933dc96 100644
--- a/drivers/gpu/drm/nouveau/nvif/notify.c
+++ b/drivers/gpu/drm/nouveau/nvif/notify.c
@@ -155,10 +155,8 @@ nvif_notify_fini(struct nvif_notify *notify)
int ret = nvif_notify_put(notify);
if (ret >= 0 && object) {
ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
- if (ret == 0) {
- notify->object = NULL;
- kfree((void *)notify->data);
- }
+ notify->object = NULL;
+ kfree((void *)notify->data);
}
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
index 34ecd4a7e0c1..058ff46b5f16 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
@@ -20,6 +20,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <core/device.h>
+#include <core/firmware.h>
/**
* nvkm_firmware_get - load firmware from the official nvidia/chip/ directory
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
index a4458a8eb30a..255d81ccf916 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
@@ -4,4 +4,4 @@ nvkm-y += nvkm/engine/ce/gk104.o
nvkm-y += nvkm/engine/ce/gm107.o
nvkm-y += nvkm/engine/ce/gm200.o
nvkm-y += nvkm/engine/ce/gp100.o
-nvkm-y += nvkm/engine/ce/gp104.o
+nvkm-y += nvkm/engine/ce/gp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
index 05bb65608dfe..d9ca9636a3e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf100_ce_data[] = {
+static uint32_t gf100_ce_data[] = {
/* 0x0000: ctx_object */
0x00000000,
/* 0x0004: ctx_query_address_high */
@@ -171,7 +171,7 @@ uint32_t gf100_ce_data[] = {
0x00000800,
};
-uint32_t gf100_ce_code[] = {
+static uint32_t gf100_ce_code[] = {
/* 0x0000: main */
0x04fe04bd,
0x3517f000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
index 972281d10f38..f0a1cf31c7ca 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gt215_ce_data[] = {
+static uint32_t gt215_ce_data[] = {
/* 0x0000: ctx_object */
0x00000000,
/* 0x0004: ctx_dma */
@@ -183,7 +183,7 @@ uint32_t gt215_ce_data[] = {
0x00000800,
};
-uint32_t gt215_ce_code[] = {
+static uint32_t gt215_ce_code[] = {
/* 0x0000: main */
0x04fe04bd,
0x3517f000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c
index 20e019788a53..985c8f653874 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c
@@ -27,7 +27,7 @@
#include <nvif/class.h>
static const struct nvkm_engine_func
-gp104_ce = {
+gp102_ce = {
.intr = gp100_ce_intr,
.sclass = {
{ -1, -1, PASCAL_DMA_COPY_B },
@@ -37,8 +37,8 @@ gp104_ce = {
};
int
-gp104_ce_new(struct nvkm_device *device, int index,
+gp102_ce_new(struct nvkm_device *device, int index,
struct nvkm_engine **pengine)
{
- return nvkm_engine_new_(&gp104_ce, device, index, true, pengine);
+ return nvkm_engine_new_(&gp102_ce, device, index, true, pengine);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 7218a067a6c5..cceda959b47c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -1357,7 +1357,7 @@ nvc0_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.ce[1] = gf100_ce_new,
.disp = gt215_disp_new,
@@ -1394,7 +1394,7 @@ nvc1_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.disp = gt215_disp_new,
.dma = gf100_dma_new,
@@ -1430,7 +1430,7 @@ nvc3_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.disp = gt215_disp_new,
.dma = gf100_dma_new,
@@ -1466,7 +1466,7 @@ nvc4_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.ce[1] = gf100_ce_new,
.disp = gt215_disp_new,
@@ -1503,7 +1503,7 @@ nvc8_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.ce[1] = gf100_ce_new,
.disp = gt215_disp_new,
@@ -1540,7 +1540,7 @@ nvce_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.ce[1] = gf100_ce_new,
.disp = gt215_disp_new,
@@ -1577,7 +1577,7 @@ nvcf_chipset = {
.pmu = gf100_pmu_new,
.therm = gt215_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.disp = gt215_disp_new,
.dma = gf100_dma_new,
@@ -1612,6 +1612,7 @@ nvd7_chipset = {
.pci = gf106_pci_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.disp = gf119_disp_new,
.dma = gf119_dma_new,
@@ -1647,7 +1648,7 @@ nvd9_chipset = {
.pmu = gf119_pmu_new,
.therm = gf119_therm_new,
.timer = nv41_timer_new,
- .volt = nv40_volt_new,
+ .volt = gf100_volt_new,
.ce[0] = gf100_ce_new,
.disp = gf119_disp_new,
.dma = gf119_dma_new,
@@ -1851,7 +1852,7 @@ nvf1_chipset = {
.fb = gk104_fb_new,
.fuse = gf100_fuse_new,
.gpio = gk104_gpio_new,
- .i2c = gf119_i2c_new,
+ .i2c = gk104_i2c_new,
.ibus = gk104_ibus_new,
.iccsense = gf100_iccsense_new,
.imem = nv50_instmem_new,
@@ -1965,7 +1966,7 @@ nv117_chipset = {
.fb = gm107_fb_new,
.fuse = gm107_fuse_new,
.gpio = gk104_gpio_new,
- .i2c = gf119_i2c_new,
+ .i2c = gk104_i2c_new,
.ibus = gk104_ibus_new,
.iccsense = gf100_iccsense_new,
.imem = nv50_instmem_new,
@@ -1999,7 +2000,7 @@ nv118_chipset = {
.fb = gm107_fb_new,
.fuse = gm107_fuse_new,
.gpio = gk104_gpio_new,
- .i2c = gf119_i2c_new,
+ .i2c = gk104_i2c_new,
.ibus = gk104_ibus_new,
.iccsense = gf100_iccsense_new,
.imem = nv50_instmem_new,
@@ -2130,7 +2131,7 @@ nv12b_chipset = {
.bar = gk20a_bar_new,
.bus = gf100_bus_new,
.clk = gm20b_clk_new,
- .fb = gk20a_fb_new,
+ .fb = gm20b_fb_new,
.fuse = gm107_fuse_new,
.ibus = gk20a_ibus_new,
.imem = gk20a_instmem_new,
@@ -2166,6 +2167,7 @@ nv130_chipset = {
.mmu = gf100_mmu_new,
.secboot = gm200_secboot_new,
.pci = gp100_pci_new,
+ .pmu = gp100_pmu_new,
.timer = gk20a_timer_new,
.top = gk104_top_new,
.ce[0] = gp100_ce_new,
@@ -2182,13 +2184,71 @@ nv130_chipset = {
};
static const struct nvkm_device_chip
+nv132_chipset = {
+ .name = "GP102",
+ .bar = gf100_bar_new,
+ .bios = nvkm_bios_new,
+ .bus = gf100_bus_new,
+ .devinit = gm200_devinit_new,
+ .fb = gp102_fb_new,
+ .fuse = gm107_fuse_new,
+ .gpio = gk104_gpio_new,
+ .i2c = gm200_i2c_new,
+ .ibus = gm200_ibus_new,
+ .imem = nv50_instmem_new,
+ .ltc = gp100_ltc_new,
+ .mc = gp100_mc_new,
+ .mmu = gf100_mmu_new,
+ .pci = gp100_pci_new,
+ .pmu = gp102_pmu_new,
+ .timer = gk20a_timer_new,
+ .top = gk104_top_new,
+ .ce[0] = gp102_ce_new,
+ .ce[1] = gp102_ce_new,
+ .ce[2] = gp102_ce_new,
+ .ce[3] = gp102_ce_new,
+ .disp = gp102_disp_new,
+ .dma = gf119_dma_new,
+ .fifo = gp100_fifo_new,
+};
+
+static const struct nvkm_device_chip
nv134_chipset = {
.name = "GP104",
.bar = gf100_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,
.devinit = gm200_devinit_new,
- .fb = gp104_fb_new,
+ .fb = gp102_fb_new,
+ .fuse = gm107_fuse_new,
+ .gpio = gk104_gpio_new,
+ .i2c = gm200_i2c_new,
+ .ibus = gm200_ibus_new,
+ .imem = nv50_instmem_new,
+ .ltc = gp100_ltc_new,
+ .mc = gp100_mc_new,
+ .mmu = gf100_mmu_new,
+ .pci = gp100_pci_new,
+ .pmu = gp102_pmu_new,
+ .timer = gk20a_timer_new,
+ .top = gk104_top_new,
+ .ce[0] = gp102_ce_new,
+ .ce[1] = gp102_ce_new,
+ .ce[2] = gp102_ce_new,
+ .ce[3] = gp102_ce_new,
+ .disp = gp102_disp_new,
+ .dma = gf119_dma_new,
+ .fifo = gp100_fifo_new,
+};
+
+static const struct nvkm_device_chip
+nv136_chipset = {
+ .name = "GP106",
+ .bar = gf100_bar_new,
+ .bios = nvkm_bios_new,
+ .bus = gf100_bus_new,
+ .devinit = gm200_devinit_new,
+ .fb = gp102_fb_new,
.fuse = gm107_fuse_new,
.gpio = gk104_gpio_new,
.i2c = gm200_i2c_new,
@@ -2198,13 +2258,14 @@ nv134_chipset = {
.mc = gp100_mc_new,
.mmu = gf100_mmu_new,
.pci = gp100_pci_new,
+ .pmu = gp102_pmu_new,
.timer = gk20a_timer_new,
.top = gk104_top_new,
- .ce[0] = gp104_ce_new,
- .ce[1] = gp104_ce_new,
- .ce[2] = gp104_ce_new,
- .ce[3] = gp104_ce_new,
- .disp = gp104_disp_new,
+ .ce[0] = gp102_ce_new,
+ .ce[1] = gp102_ce_new,
+ .ce[2] = gp102_ce_new,
+ .ce[3] = gp102_ce_new,
+ .disp = gp102_disp_new,
.dma = gf119_dma_new,
.fifo = gp100_fifo_new,
};
@@ -2643,7 +2704,9 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x126: device->chip = &nv126_chipset; break;
case 0x12b: device->chip = &nv12b_chipset; break;
case 0x130: device->chip = &nv130_chipset; break;
+ case 0x132: device->chip = &nv132_chipset; break;
case 0x134: device->chip = &nv134_chipset; break;
+ case 0x136: device->chip = &nv136_chipset; break;
default:
nvdev_error(device, "unknown chipset (%08x)\n", boot0);
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index 62ad0300cfa5..74a1ffa425f7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -1665,14 +1665,31 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
*pdevice = &pdev->device;
pdev->pdev = pci_dev;
- return nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
- pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
- pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
- NVKM_DEVICE_AGP : NVKM_DEVICE_PCI,
- (u64)pci_domain_nr(pci_dev->bus) << 32 |
- pci_dev->bus->number << 16 |
- PCI_SLOT(pci_dev->devfn) << 8 |
- PCI_FUNC(pci_dev->devfn), name,
- cfg, dbg, detect, mmio, subdev_mask,
- &pdev->device);
+ ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
+ pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
+ pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
+ NVKM_DEVICE_AGP : NVKM_DEVICE_PCI,
+ (u64)pci_domain_nr(pci_dev->bus) << 32 |
+ pci_dev->bus->number << 16 |
+ PCI_SLOT(pci_dev->devfn) << 8 |
+ PCI_FUNC(pci_dev->devfn), name,
+ cfg, dbg, detect, mmio, subdev_mask,
+ &pdev->device);
+
+ if (ret)
+ return ret;
+
+ /*
+ * Set a preliminary DMA mask based on the .dma_bits member of the
+ * MMU subdevice. This allows other subdevices to create DMA mappings
+ * in their init() or oneinit() methods, which may be called before the
+ * TTM layer sets the DMA mask definitively.
+ * This is necessary for platforms where the default DMA mask of 32
+ * does not cover any system memory, i.e., when all RAM is > 4 GB.
+ */
+ if (pdev->device.mmu)
+ dma_set_mask_and_coherent(&pci_dev->dev,
+ DMA_BIT_MASK(pdev->device.mmu->dma_bits));
+
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index 9b638bd905ff..f2bc0b7d9b93 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -102,7 +102,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
if (iommu_present(&platform_bus_type)) {
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
- if (IS_ERR(tdev->iommu.domain))
+ if (!tdev->iommu.domain)
goto error;
/*
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 79a8f71cf788..513ee6b79553 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -326,7 +326,7 @@ nvkm_udevice = {
.sclass = nvkm_udevice_child_get,
};
-int
+static int
nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index 77a52b54a31e..fa05d16ae948 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -11,7 +11,7 @@ nvkm-y += nvkm/engine/disp/gk110.o
nvkm-y += nvkm/engine/disp/gm107.o
nvkm-y += nvkm/engine/disp/gm200.o
nvkm-y += nvkm/engine/disp/gp100.o
-nvkm-y += nvkm/engine/disp/gp104.o
+nvkm-y += nvkm/engine/disp/gp102.o
nvkm-y += nvkm/engine/disp/outp.o
nvkm-y += nvkm/engine/disp/outpdp.o
@@ -48,14 +48,14 @@ nvkm-y += nvkm/engine/disp/rootgk110.o
nvkm-y += nvkm/engine/disp/rootgm107.o
nvkm-y += nvkm/engine/disp/rootgm200.o
nvkm-y += nvkm/engine/disp/rootgp100.o
-nvkm-y += nvkm/engine/disp/rootgp104.o
+nvkm-y += nvkm/engine/disp/rootgp102.o
nvkm-y += nvkm/engine/disp/channv50.o
nvkm-y += nvkm/engine/disp/changf119.o
nvkm-y += nvkm/engine/disp/dmacnv50.o
nvkm-y += nvkm/engine/disp/dmacgf119.o
-nvkm-y += nvkm/engine/disp/dmacgp104.o
+nvkm-y += nvkm/engine/disp/dmacgp102.o
nvkm-y += nvkm/engine/disp/basenv50.o
nvkm-y += nvkm/engine/disp/baseg84.o
@@ -64,7 +64,7 @@ nvkm-y += nvkm/engine/disp/basegt215.o
nvkm-y += nvkm/engine/disp/basegf119.o
nvkm-y += nvkm/engine/disp/basegk104.o
nvkm-y += nvkm/engine/disp/basegk110.o
-nvkm-y += nvkm/engine/disp/basegp104.o
+nvkm-y += nvkm/engine/disp/basegp102.o
nvkm-y += nvkm/engine/disp/corenv50.o
nvkm-y += nvkm/engine/disp/coreg84.o
@@ -77,7 +77,7 @@ nvkm-y += nvkm/engine/disp/coregk110.o
nvkm-y += nvkm/engine/disp/coregm107.o
nvkm-y += nvkm/engine/disp/coregm200.o
nvkm-y += nvkm/engine/disp/coregp100.o
-nvkm-y += nvkm/engine/disp/coregp104.o
+nvkm-y += nvkm/engine/disp/coregp102.o
nvkm-y += nvkm/engine/disp/ovlynv50.o
nvkm-y += nvkm/engine/disp/ovlyg84.o
@@ -85,7 +85,7 @@ nvkm-y += nvkm/engine/disp/ovlygt200.o
nvkm-y += nvkm/engine/disp/ovlygt215.o
nvkm-y += nvkm/engine/disp/ovlygf119.o
nvkm-y += nvkm/engine/disp/ovlygk104.o
-nvkm-y += nvkm/engine/disp/ovlygp104.o
+nvkm-y += nvkm/engine/disp/ovlygp102.o
nvkm-y += nvkm/engine/disp/piocnv50.o
nvkm-y += nvkm/engine/disp/piocgf119.o
@@ -95,9 +95,11 @@ nvkm-y += nvkm/engine/disp/cursg84.o
nvkm-y += nvkm/engine/disp/cursgt215.o
nvkm-y += nvkm/engine/disp/cursgf119.o
nvkm-y += nvkm/engine/disp/cursgk104.o
+nvkm-y += nvkm/engine/disp/cursgp102.o
nvkm-y += nvkm/engine/disp/oimmnv50.o
nvkm-y += nvkm/engine/disp/oimmg84.o
nvkm-y += nvkm/engine/disp/oimmgt215.o
nvkm-y += nvkm/engine/disp/oimmgf119.o
nvkm-y += nvkm/engine/disp/oimmgk104.o
+nvkm-y += nvkm/engine/disp/oimmgp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c
index 51688e37c54e..8a3cdeef8d2c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c
@@ -27,12 +27,12 @@
#include <nvif/class.h>
const struct nv50_disp_dmac_oclass
-gp104_disp_base_oclass = {
+gp102_disp_base_oclass = {
.base.oclass = GK110_DISP_BASE_CHANNEL_DMA,
.base.minver = 0,
.base.maxver = 0,
.ctor = nv50_disp_base_new,
- .func = &gp104_disp_dmac_func,
+ .func = &gp102_disp_dmac_func,
.mthd = &gf119_disp_base_chan_mthd,
.chid = 1,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
index dd2953bc9264..524a24eae1a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
@@ -82,7 +82,7 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug)
if (mthd->addr) {
snprintf(cname_, sizeof(cname_), "%s %d",
- mthd->name, chan->chid);
+ mthd->name, chan->chid.user);
cname = cname_;
}
@@ -139,7 +139,7 @@ nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
notify->size = sizeof(struct nvif_notify_uevent_rep);
notify->types = 1;
- notify->index = chan->chid;
+ notify->index = chan->chid.user;
return 0;
}
@@ -153,27 +153,27 @@ nv50_disp_chan_uevent = {
.fini = nv50_disp_chan_uevent_fini,
};
-int
+static int
nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
struct nv50_disp *disp = chan->root->disp;
struct nvkm_device *device = disp->base.engine.subdev.device;
- *data = nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr);
+ *data = nvkm_rd32(device, 0x640000 + (chan->chid.user * 0x1000) + addr);
return 0;
}
-int
+static int
nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
struct nv50_disp *disp = chan->root->disp;
struct nvkm_device *device = disp->base.engine.subdev.device;
- nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data);
+ nvkm_wr32(device, 0x640000 + (chan->chid.user * 0x1000) + addr, data);
return 0;
}
-int
+static int
nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
struct nvkm_event **pevent)
{
@@ -189,14 +189,14 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
return -EINVAL;
}
-int
+static int
nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
struct nv50_disp *disp = chan->root->disp;
struct nvkm_device *device = disp->base.engine.subdev.device;
*addr = device->func->resource_addr(device, 0) +
- 0x640000 + (chan->chid * 0x1000);
+ 0x640000 + (chan->chid.user * 0x1000);
*size = 0x001000;
return 0;
}
@@ -243,8 +243,8 @@ nv50_disp_chan_dtor(struct nvkm_object *object)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
struct nv50_disp *disp = chan->root->disp;
- if (chan->chid >= 0)
- disp->chan[chan->chid] = NULL;
+ if (chan->chid.user >= 0)
+ disp->chan[chan->chid.user] = NULL;
return chan->func->dtor ? chan->func->dtor(chan) : chan;
}
@@ -263,7 +263,7 @@ nv50_disp_chan = {
int
nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func,
const struct nv50_disp_chan_mthd *mthd,
- struct nv50_disp_root *root, int chid, int head,
+ struct nv50_disp_root *root, int ctrl, int user, int head,
const struct nvkm_oclass *oclass,
struct nv50_disp_chan *chan)
{
@@ -273,21 +273,22 @@ nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func,
chan->func = func;
chan->mthd = mthd;
chan->root = root;
- chan->chid = chid;
+ chan->chid.ctrl = ctrl;
+ chan->chid.user = user;
chan->head = head;
- if (disp->chan[chan->chid]) {
- chan->chid = -1;
+ if (disp->chan[chan->chid.user]) {
+ chan->chid.user = -1;
return -EBUSY;
}
- disp->chan[chan->chid] = chan;
+ disp->chan[chan->chid.user] = chan;
return 0;
}
int
nv50_disp_chan_new_(const struct nv50_disp_chan_func *func,
const struct nv50_disp_chan_mthd *mthd,
- struct nv50_disp_root *root, int chid, int head,
+ struct nv50_disp_root *root, int ctrl, int user, int head,
const struct nvkm_oclass *oclass,
struct nvkm_object **pobject)
{
@@ -297,5 +298,6 @@ nv50_disp_chan_new_(const struct nv50_disp_chan_func *func,
return -ENOMEM;
*pobject = &chan->object;
- return nv50_disp_chan_ctor(func, mthd, root, chid, head, oclass, chan);
+ return nv50_disp_chan_ctor(func, mthd, root, ctrl, user,
+ head, oclass, chan);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
index f5f683d9fd20..737b38f6fbd2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
@@ -7,7 +7,11 @@ struct nv50_disp_chan {
const struct nv50_disp_chan_func *func;
const struct nv50_disp_chan_mthd *mthd;
struct nv50_disp_root *root;
- int chid;
+
+ struct {
+ int ctrl;
+ int user;
+ } chid;
int head;
struct nvkm_object object;
@@ -25,11 +29,11 @@ struct nv50_disp_chan_func {
int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *,
const struct nv50_disp_chan_mthd *,
- struct nv50_disp_root *, int chid, int head,
+ struct nv50_disp_root *, int ctrl, int user, int head,
const struct nvkm_oclass *, struct nv50_disp_chan *);
int nv50_disp_chan_new_(const struct nv50_disp_chan_func *,
const struct nv50_disp_chan_mthd *,
- struct nv50_disp_root *, int chid, int head,
+ struct nv50_disp_root *, int ctrl, int user, int head,
const struct nvkm_oclass *, struct nvkm_object **);
extern const struct nv50_disp_chan_func nv50_disp_pioc_func;
@@ -90,13 +94,16 @@ extern const struct nv50_disp_chan_mthd gk104_disp_ovly_chan_mthd;
struct nv50_disp_pioc_oclass {
int (*ctor)(const struct nv50_disp_chan_func *,
const struct nv50_disp_chan_mthd *,
- struct nv50_disp_root *, int chid,
+ struct nv50_disp_root *, int ctrl, int user,
const struct nvkm_oclass *, void *data, u32 size,
struct nvkm_object **);
struct nvkm_sclass base;
const struct nv50_disp_chan_func *func;
const struct nv50_disp_chan_mthd *mthd;
- int chid;
+ struct {
+ int ctrl;
+ int user;
+ } chid;
};
extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass;
@@ -114,15 +121,17 @@ extern const struct nv50_disp_pioc_oclass gf119_disp_curs_oclass;
extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass;
extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass;
+extern const struct nv50_disp_pioc_oclass gp102_disp_oimm_oclass;
+extern const struct nv50_disp_pioc_oclass gp102_disp_curs_oclass;
int nv50_disp_curs_new(const struct nv50_disp_chan_func *,
const struct nv50_disp_chan_mthd *,
- struct nv50_disp_root *, int chid,
+ struct nv50_disp_root *, int ctrl, int user,
const struct nvkm_oclass *, void *data, u32 size,
struct nvkm_object **);
int nv50_disp_oimm_new(const struct nv50_disp_chan_func *,
const struct nv50_disp_chan_mthd *,
- struct nv50_disp_root *, int chid,
+ struct nv50_disp_root *, int ctrl, int user,
const struct nvkm_oclass *, void *data, u32 size,
struct nvkm_object **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c
index 019379a3a01c..c65c9f3ff69f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c
@@ -26,7 +26,7 @@
#include <nvif/class.h>
-const struct nv50_disp_mthd_list
+static const struct nv50_disp_mthd_list
g94_disp_core_mthd_sor = {
.mthd = 0x0040,
.addr = 0x000008,
@@ -43,8 +43,8 @@ g94_disp_core_chan_mthd = {
.prev = 0x000004,
.data = {
{ "Global", 1, &nv50_disp_core_mthd_base },
- { "DAC", 3, &g84_disp_core_mthd_dac },
- { "SOR", 4, &g94_disp_core_mthd_sor },
+ { "DAC", 3, &g84_disp_core_mthd_dac },
+ { "SOR", 4, &g94_disp_core_mthd_sor },
{ "PIOR", 3, &nv50_disp_core_mthd_pior },
{ "HEAD", 2, &g84_disp_core_mthd_head },
{}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c
index 6922f4007b61..b0df4b752b8c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c
@@ -29,7 +29,7 @@
#include <nvif/class.h>
static int
-gp104_disp_core_init(struct nv50_disp_dmac *chan)
+gp102_disp_core_init(struct nv50_disp_dmac *chan)
{
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
@@ -59,20 +59,20 @@ gp104_disp_core_init(struct nv50_disp_dmac *chan)
return 0;
}
-const struct nv50_disp_dmac_func
-gp104_disp_core_func = {
- .init = gp104_disp_core_init,
+static const struct nv50_disp_dmac_func
+gp102_disp_core_func = {
+ .init = gp102_disp_core_init,
.fini = gf119_disp_core_fini,
.bind = gf119_disp_dmac_bind,
};
const struct nv50_disp_dmac_oclass
-gp104_disp_core_oclass = {
- .base.oclass = GP104_DISP_CORE_CHANNEL_DMA,
+gp102_disp_core_oclass = {
+ .base.oclass = GP102_DISP_CORE_CHANNEL_DMA,
.base.minver = 0,
.base.maxver = 0,
.ctor = nv50_disp_core_new,
- .func = &gp104_disp_core_func,
+ .func = &gp102_disp_core_func,
.mthd = &gk104_disp_core_chan_mthd,
.chid = 0,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
index dd99fc7060b1..fa781b5a7e07 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
@@ -33,5 +33,5 @@ g84_disp_curs_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_curs_new,
.func = &nv50_disp_pioc_func,
- .chid = 7,
+ .chid = { 7, 7 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
index 2a1574e06ad6..2be6fb052c65 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
@@ -33,5 +33,5 @@ gf119_disp_curs_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_curs_new,
.func = &gf119_disp_pioc_func,
- .chid = 13,
+ .chid = { 13, 13 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
index 28e8f06c9472..2a99db4bf8f8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
@@ -33,5 +33,5 @@ gk104_disp_curs_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_curs_new,
.func = &gf119_disp_pioc_func,
- .chid = 13,
+ .chid = { 13, 13 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c
new file mode 100644
index 000000000000..e958210d8105
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 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 "channv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_pioc_oclass
+gp102_disp_curs_oclass = {
+ .base.oclass = GK104_DISP_CURSOR,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv50_disp_curs_new,
+ .func = &gf119_disp_pioc_func,
+ .chid = { 13, 17 },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
index d8a4b9ca139c..00a7f3564450 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
@@ -33,5 +33,5 @@ gt215_disp_curs_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_curs_new,
.func = &nv50_disp_pioc_func,
- .chid = 7,
+ .chid = { 7, 7 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
index 8b1320499a0f..82ff82d8c1ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
@@ -33,7 +33,7 @@
int
nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
const struct nv50_disp_chan_mthd *mthd,
- struct nv50_disp_root *root, int chid,
+ struct nv50_disp_root *root, int ctrl, int user,
const struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
@@ -54,7 +54,7 @@ nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
} else
return ret;
- return nv50_disp_chan_new_(func, mthd, root, chid + head,
+ return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
head, oclass, pobject);
}
@@ -65,5 +65,5 @@ nv50_disp_curs_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_curs_new,
.func = &nv50_disp_pioc_func,
- .chid = 7,
+ .chid = { 7, 7 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
index a57f7cef307a..ce7cd74fbd5d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
@@ -32,8 +32,8 @@ gf119_disp_dmac_bind(struct nv50_disp_dmac *chan,
struct nvkm_object *object, u32 handle)
{
return nvkm_ramht_insert(chan->base.root->ramht, object,
- chan->base.chid, -9, handle,
- chan->base.chid << 27 | 0x00000001);
+ chan->base.chid.user, -9, handle,
+ chan->base.chid.user << 27 | 0x00000001);
}
void
@@ -42,22 +42,23 @@ gf119_disp_dmac_fini(struct nv50_disp_dmac *chan)
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->base.chid;
+ int ctrl = chan->base.chid.ctrl;
+ int user = chan->base.chid.user;
/* deactivate channel */
- nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000);
- nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000);
+ nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000);
+ nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000);
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x001e0000))
+ if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d fini: %08x\n", chid,
- nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d fini: %08x\n", user,
+ nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
}
/* disable error reporting and completion notification */
- nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000);
- nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000);
+ nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
+ nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
}
static int
@@ -66,26 +67,27 @@ gf119_disp_dmac_init(struct nv50_disp_dmac *chan)
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->base.chid;
+ int ctrl = chan->base.chid.ctrl;
+ int user = chan->base.chid.user;
/* enable error reporting */
- nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
+ nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* initialise channel for dma command submission */
- nvkm_wr32(device, 0x610494 + (chid * 0x0010), chan->push);
- nvkm_wr32(device, 0x610498 + (chid * 0x0010), 0x00010000);
- nvkm_wr32(device, 0x61049c + (chid * 0x0010), 0x00000001);
- nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
- nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
- nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013);
+ nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push);
+ nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000);
+ nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001);
+ nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+ nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+ nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
/* wait for it to go inactive */
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000))
+ if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d init: %08x\n", chid,
- nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d init: %08x\n", user,
+ nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c
index ad24c2c57696..cdead9500343 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c
@@ -27,31 +27,32 @@
#include <subdev/timer.h>
static int
-gp104_disp_dmac_init(struct nv50_disp_dmac *chan)
+gp102_disp_dmac_init(struct nv50_disp_dmac *chan)
{
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->base.chid;
+ int ctrl = chan->base.chid.ctrl;
+ int user = chan->base.chid.user;
/* enable error reporting */
- nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
+ nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* initialise channel for dma command submission */
- nvkm_wr32(device, 0x611494 + (chid * 0x0010), chan->push);
- nvkm_wr32(device, 0x611498 + (chid * 0x0010), 0x00010000);
- nvkm_wr32(device, 0x61149c + (chid * 0x0010), 0x00000001);
- nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
- nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
- nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013);
+ nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push);
+ nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000);
+ nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001);
+ nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+ nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+ nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
/* wait for it to go inactive */
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000))
+ if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d init: %08x\n", chid,
- nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d init: %08x\n", user,
+ nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
return -EBUSY;
}
@@ -59,8 +60,8 @@ gp104_disp_dmac_init(struct nv50_disp_dmac *chan)
}
const struct nv50_disp_dmac_func
-gp104_disp_dmac_func = {
- .init = gp104_disp_dmac_init,
+gp102_disp_dmac_func = {
+ .init = gp102_disp_dmac_init,
.fini = gf119_disp_dmac_fini,
.bind = gf119_disp_dmac_bind,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
index 9c6645a357b9..0a1381a84552 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
@@ -149,7 +149,7 @@ nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *func,
chan->func = func;
ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root,
- chid, head, oclass, &chan->base);
+ chid, chid, head, oclass, &chan->base);
if (ret)
return ret;
@@ -179,9 +179,9 @@ nv50_disp_dmac_bind(struct nv50_disp_dmac *chan,
struct nvkm_object *object, u32 handle)
{
return nvkm_ramht_insert(chan->base.root->ramht, object,
- chan->base.chid, -10, handle,
- chan->base.chid << 28 |
- chan->base.chid);
+ chan->base.chid.user, -10, handle,
+ chan->base.chid.user << 28 |
+ chan->base.chid.user);
}
static void
@@ -190,21 +190,22 @@ nv50_disp_dmac_fini(struct nv50_disp_dmac *chan)
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->base.chid;
+ int ctrl = chan->base.chid.ctrl;
+ int user = chan->base.chid.user;
/* deactivate channel */
- nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000);
- nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000);
+ nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000);
+ nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000);
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x001e0000))
+ if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid,
- nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d fini timeout, %08x\n", user,
+ nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
}
/* disable error reporting and completion notifications */
- nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
+ nvkm_mask(device, 0x610028, 0x00010001 << user, 0x00000000 << user);
}
static int
@@ -213,26 +214,27 @@ nv50_disp_dmac_init(struct nv50_disp_dmac *chan)
struct nv50_disp *disp = chan->base.root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->base.chid;
+ int ctrl = chan->base.chid.ctrl;
+ int user = chan->base.chid.user;
/* enable error reporting */
- nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid);
+ nvkm_mask(device, 0x610028, 0x00010000 << user, 0x00010000 << user);
/* initialise channel for dma command submission */
- nvkm_wr32(device, 0x610204 + (chid * 0x0010), chan->push);
- nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000);
- nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid);
- nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
- nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
- nvkm_wr32(device, 0x610200 + (chid * 0x0010), 0x00000013);
+ nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push);
+ nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000);
+ nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl);
+ nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+ nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+ nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013);
/* wait for it to go inactive */
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x80000000))
+ if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d init timeout, %08x\n", chid,
- nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d init timeout, %08x\n", user,
+ nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
index 43ac05857853..ea4a0d062e31 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
@@ -30,7 +30,7 @@ int gf119_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32);
extern const struct nv50_disp_dmac_func gf119_disp_core_func;
void gf119_disp_core_fini(struct nv50_disp_dmac *);
-extern const struct nv50_disp_dmac_func gp104_disp_dmac_func;
+extern const struct nv50_disp_dmac_func gp102_disp_dmac_func;
struct nv50_disp_dmac_oclass {
int (*ctor)(const struct nv50_disp_dmac_func *,
@@ -95,7 +95,7 @@ extern const struct nv50_disp_dmac_oclass gm200_disp_core_oclass;
extern const struct nv50_disp_dmac_oclass gp100_disp_core_oclass;
-extern const struct nv50_disp_dmac_oclass gp104_disp_core_oclass;
-extern const struct nv50_disp_dmac_oclass gp104_disp_base_oclass;
-extern const struct nv50_disp_dmac_oclass gp104_disp_ovly_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_core_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_base_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_ovly_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
index 9688970eca47..4a93ceb850ac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
@@ -319,9 +319,8 @@ static const struct dp_rates {
};
void
-nvkm_dp_train(struct work_struct *w)
+nvkm_dp_train(struct nvkm_output_dp *outp)
{
- struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
struct nv50_disp *disp = nv50_disp(outp->base.disp);
const struct dp_rates *cfg = nvkm_dp_rates;
struct dp_state _dp = {
@@ -353,9 +352,6 @@ nvkm_dp_train(struct work_struct *w)
}
cfg--;
- /* disable link interrupt handling during link training */
- nvkm_notify_put(&outp->irq);
-
/* ensure sink is not in a low-power state */
if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
@@ -400,9 +396,6 @@ nvkm_dp_train(struct work_struct *w)
dp_link_train_fini(dp);
- /* signal completion and enable link interrupt handling */
OUTP_DBG(&outp->base, "training complete");
atomic_set(&outp->lt.done, 1);
- wake_up(&outp->lt.wait);
- nvkm_notify_get(&outp->irq);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
index 6e10c5e0ef11..baf1dd9ff975 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
@@ -1,6 +1,6 @@
#ifndef __NVKM_DISP_DPORT_H__
#define __NVKM_DISP_DPORT_H__
-#include <core/os.h>
+struct nvkm_output_dp;
/* DPCD Receiver Capabilities */
#define DPCD_RC00_DPCD_REV 0x00000
@@ -77,5 +77,5 @@
#define DPCD_SC00_SET_POWER_D0 0x01
#define DPCD_SC00_SET_POWER_D3 0x03
-void nvkm_dp_train(struct work_struct *);
+void nvkm_dp_train(struct nvkm_output_dp *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index 29e84b241cca..7b346ccc38b7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -203,17 +203,20 @@ gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
/* see note in nv50_disp_intr_unk20_0() */
if (outp && outp->info.type == DCB_OUTPUT_DP) {
struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
- struct nvbios_init init = {
- .subdev = subdev,
- .bios = subdev->device->bios,
- .outp = &outp->info,
- .crtc = head,
- .offset = outpdp->info.script[4],
- .execute = 1,
- };
+ if (!outpdp->lt.mst) {
+ struct nvbios_init init = {
+ .subdev = subdev,
+ .bios = subdev->device->bios,
+ .outp = &outp->info,
+ .crtc = head,
+ .offset = outpdp->info.script[4],
+ .execute = 1,
+ };
- nvbios_exec(&init);
- atomic_set(&outpdp->lt.done, 0);
+ nvkm_notify_put(&outpdp->irq);
+ nvbios_exec(&init);
+ atomic_set(&outpdp->lt.done, 0);
+ }
}
}
@@ -314,7 +317,7 @@ gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
break;
}
- if (nvkm_output_dp_train(outp, pclk, true))
+ if (nvkm_output_dp_train(outp, pclk))
OUTP_ERR(outp, "link not trained before attach");
} else {
if (disp->func->sor.magic)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
index 3bf3380336e4..f5d613f82709 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
@@ -25,7 +25,7 @@
#include "rootnv50.h"
static void
-gp104_disp_intr_error(struct nv50_disp *disp, int chid)
+gp102_disp_intr_error(struct nv50_disp *disp, int chid)
{
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
@@ -51,12 +51,12 @@ gp104_disp_intr_error(struct nv50_disp *disp, int chid)
}
static const struct nv50_disp_func
-gp104_disp = {
+gp102_disp = {
.intr = gf119_disp_intr,
- .intr_error = gp104_disp_intr_error,
+ .intr_error = gp102_disp_intr_error,
.uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor,
- .root = &gp104_disp_root_oclass,
+ .root = &gp102_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init,
.head.vblank_fini = gf119_disp_vblank_fini,
.head.scanoutpos = gf119_disp_root_scanoutpos,
@@ -75,7 +75,7 @@ gp104_disp = {
};
int
-gp104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
+gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{
- return gf119_disp_new_(&gp104_disp, device, index, pdisp);
+ return gf119_disp_new_(&gp102_disp, device, index, pdisp);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index fbb8c7dc18fd..567466f93cd5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -590,6 +590,7 @@ nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
.execute = 1,
};
+ nvkm_notify_put(&outpdp->irq);
nvbios_exec(&init);
atomic_set(&outpdp->lt.done, 0);
}
@@ -779,7 +780,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
break;
}
- if (nvkm_output_dp_train(outp, datarate / soff, true))
+ if (nvkm_output_dp_train(outp, datarate / soff))
OUTP_ERR(outp, "link not trained before attach");
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
index 54a4ae8d66c6..5ad5d0f5db05 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
@@ -33,5 +33,5 @@ g84_disp_oimm_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_oimm_new,
.func = &nv50_disp_pioc_func,
- .chid = 5,
+ .chid = { 5, 5 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
index c658db54afc5..1f9fd3403f07 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
@@ -33,5 +33,5 @@ gf119_disp_oimm_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_oimm_new,
.func = &gf119_disp_pioc_func,
- .chid = 9,
+ .chid = { 9, 9 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
index b1fde8c125d6..0c09fe85e952 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
@@ -33,5 +33,5 @@ gk104_disp_oimm_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_oimm_new,
.func = &gf119_disp_pioc_func,
- .chid = 9,
+ .chid = { 9, 9 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c
new file mode 100644
index 000000000000..abf82365c671
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 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 "channv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_pioc_oclass
+gp102_disp_oimm_oclass = {
+ .base.oclass = GK104_DISP_OVERLAY,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv50_disp_oimm_new,
+ .func = &gf119_disp_pioc_func,
+ .chid = { 9, 13 },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
index f4e7eb3d1177..1281db28aebd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
@@ -33,5 +33,5 @@ gt215_disp_oimm_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_oimm_new,
.func = &nv50_disp_pioc_func,
- .chid = 5,
+ .chid = { 5, 5 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
index 3940b9c966ec..07540f3d32dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
@@ -33,7 +33,7 @@
int
nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
const struct nv50_disp_chan_mthd *mthd,
- struct nv50_disp_root *root, int chid,
+ struct nv50_disp_root *root, int ctrl, int user,
const struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
@@ -54,7 +54,7 @@ nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
} else
return ret;
- return nv50_disp_chan_new_(func, mthd, root, chid + head,
+ return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
head, oclass, pobject);
}
@@ -65,5 +65,5 @@ nv50_disp_oimm_oclass = {
.base.maxver = 0,
.ctor = nv50_disp_oimm_new,
.func = &nv50_disp_pioc_func,
- .chid = 5,
+ .chid = { 5, 5 },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
index 3b7a9e7a1ea8..de36f73b14dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
@@ -31,7 +31,7 @@
#include <nvif/event.h>
int
-nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
+nvkm_output_dp_train(struct nvkm_output *base, u32 datarate)
{
struct nvkm_output_dp *outp = nvkm_output_dp(base);
bool retrain = true;
@@ -39,6 +39,8 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
u32 linkrate;
int ret, i;
+ mutex_lock(&outp->mutex);
+
/* check that the link is trained at a high enough rate */
ret = nvkm_rdaux(outp->aux, DPCD_LC00_LINK_BW_SET, link, 2);
if (ret) {
@@ -88,19 +90,10 @@ done:
outp->dpcd[DPCD_RC02] =
outp->base.info.dpconf.link_nr;
}
- atomic_set(&outp->lt.done, 0);
- schedule_work(&outp->lt.work);
- } else {
- nvkm_notify_get(&outp->irq);
- }
-
- if (wait) {
- if (!wait_event_timeout(outp->lt.wait,
- atomic_read(&outp->lt.done),
- msecs_to_jiffies(2000)))
- ret = -ETIMEDOUT;
+ nvkm_dp_train(outp);
}
+ mutex_unlock(&outp->mutex);
return ret;
}
@@ -118,7 +111,7 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dpcd,
sizeof(outp->dpcd))) {
- nvkm_output_dp_train(&outp->base, 0, true);
+ nvkm_output_dp_train(&outp->base, 0);
return;
}
}
@@ -165,10 +158,10 @@ nvkm_output_dp_irq(struct nvkm_notify *notify)
};
OUTP_DBG(&outp->base, "IRQ: %d", line->mask);
- nvkm_output_dp_train(&outp->base, 0, true);
+ nvkm_output_dp_train(&outp->base, 0);
nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
- return NVKM_NOTIFY_DROP;
+ return NVKM_NOTIFY_KEEP;
}
static void
@@ -177,7 +170,6 @@ nvkm_output_dp_fini(struct nvkm_output *base)
struct nvkm_output_dp *outp = nvkm_output_dp(base);
nvkm_notify_put(&outp->hpd);
nvkm_notify_put(&outp->irq);
- flush_work(&outp->lt.work);
nvkm_output_dp_enable(outp, false);
}
@@ -187,6 +179,7 @@ nvkm_output_dp_init(struct nvkm_output *base)
struct nvkm_output_dp *outp = nvkm_output_dp(base);
nvkm_notify_put(&outp->base.conn->hpd);
nvkm_output_dp_enable(outp, true);
+ nvkm_notify_get(&outp->irq);
nvkm_notify_get(&outp->hpd);
}
@@ -238,11 +231,6 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
OUTP_DBG(&outp->base, "bios dp %02x %02x %02x %02x",
outp->version, hdr, cnt, len);
- /* link training */
- INIT_WORK(&outp->lt.work, nvkm_dp_train);
- init_waitqueue_head(&outp->lt.wait);
- atomic_set(&outp->lt.done, 0);
-
/* link maintenance */
ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_irq, true,
&(struct nvkm_i2c_ntfy_req) {
@@ -257,6 +245,9 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
return ret;
}
+ mutex_init(&outp->mutex);
+ atomic_set(&outp->lt.done, 0);
+
/* hotplug detect, replaces gpio-based mechanism with aux events */
ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_hpd, true,
&(struct nvkm_i2c_ntfy_req) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
index 4e983f6d7032..3c83a561cd88 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
@@ -29,10 +29,10 @@ struct nvkm_output_dp {
bool present;
u8 dpcd[16];
+ struct mutex mutex;
struct {
- struct work_struct work;
- wait_queue_head_t wait;
atomic_t done;
+ bool mst;
} lt;
};
@@ -41,9 +41,11 @@ struct nvkm_output_dp_func {
int (*lnk_pwr)(struct nvkm_output_dp *, int nr);
int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef);
int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
+ void (*vcpi)(struct nvkm_output_dp *, int head, u8 start_slot,
+ u8 num_slots, u16 pbn, u16 aligned_pbn);
};
-int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait);
+int nvkm_output_dp_train(struct nvkm_output *, u32 rate);
int nvkm_output_dp_ctor(const struct nvkm_output_dp_func *, struct nvkm_disp *,
int index, struct dcb_output *, struct nvkm_i2c_aux *,
@@ -63,6 +65,7 @@ int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
struct nvkm_output **);
int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
+void gf119_sor_dp_vcpi(struct nvkm_output_dp *, int, u8, u8, u16, u16);
int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
struct nvkm_output **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c
index 97e2dd2d908e..589bd2f12b41 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c
@@ -27,12 +27,12 @@
#include <nvif/class.h>
const struct nv50_disp_dmac_oclass
-gp104_disp_ovly_oclass = {
+gp102_disp_ovly_oclass = {
.base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA,
.base.minver = 0,
.base.maxver = 0,
.ctor = nv50_disp_ovly_new,
- .func = &gp104_disp_dmac_func,
+ .func = &gp102_disp_dmac_func,
.mthd = &gk104_disp_ovly_chan_mthd,
.chid = 5,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
index a625a9876e34..0abaa6431943 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
@@ -32,20 +32,21 @@ gf119_disp_pioc_fini(struct nv50_disp_chan *chan)
struct nv50_disp *disp = chan->root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->chid;
+ int ctrl = chan->chid.ctrl;
+ int user = chan->chid.user;
- nvkm_mask(device, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000);
+ nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000);
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x00030000))
+ if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d fini: %08x\n", chid,
- nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d fini: %08x\n", user,
+ nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
}
/* disable error reporting and completion notification */
- nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000);
- nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000);
+ nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
+ nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
}
static int
@@ -54,20 +55,21 @@ gf119_disp_pioc_init(struct nv50_disp_chan *chan)
struct nv50_disp *disp = chan->root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->chid;
+ int ctrl = chan->chid.ctrl;
+ int user = chan->chid.user;
/* enable error reporting */
- nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
+ nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* activate channel */
- nvkm_wr32(device, 0x610490 + (chid * 0x10), 0x00000001);
+ nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001);
if (nvkm_msec(device, 2000,
- u32 tmp = nvkm_rd32(device, 0x610490 + (chid * 0x10));
+ u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10));
if ((tmp & 0x00030000) == 0x00010000)
break;
) < 0) {
- nvkm_error(subdev, "ch %d init: %08x\n", chid,
- nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d init: %08x\n", user,
+ nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
index 9d2618dacf20..0211e0e8a35f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
@@ -32,15 +32,16 @@ nv50_disp_pioc_fini(struct nv50_disp_chan *chan)
struct nv50_disp *disp = chan->root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->chid;
+ int ctrl = chan->chid.ctrl;
+ int user = chan->chid.user;
- nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000);
+ nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000);
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
+ if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d timeout: %08x\n", chid,
- nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d timeout: %08x\n", user,
+ nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
}
}
@@ -50,26 +51,27 @@ nv50_disp_pioc_init(struct nv50_disp_chan *chan)
struct nv50_disp *disp = chan->root->disp;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int chid = chan->chid;
+ int ctrl = chan->chid.ctrl;
+ int user = chan->chid.user;
- nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000);
+ nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000);
if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
+ if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
break;
) < 0) {
- nvkm_error(subdev, "ch %d timeout0: %08x\n", chid,
- nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d timeout0: %08x\n", user,
+ nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
return -EBUSY;
}
- nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00000001);
+ nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001);
if (nvkm_msec(device, 2000,
- u32 tmp = nvkm_rd32(device, 0x610200 + (chid * 0x10));
+ u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10));
if ((tmp & 0x00030000) == 0x00010000)
break;
) < 0) {
- nvkm_error(subdev, "ch %d timeout1: %08x\n", chid,
- nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+ nvkm_error(subdev, "ch %d timeout1: %08x\n", user,
+ nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c
index 8443e04dc626..37122ca579ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c
@@ -27,32 +27,32 @@
#include <nvif/class.h>
static const struct nv50_disp_root_func
-gp104_disp_root = {
+gp102_disp_root = {
.init = gf119_disp_root_init,
.fini = gf119_disp_root_fini,
.dmac = {
- &gp104_disp_core_oclass,
- &gp104_disp_base_oclass,
- &gp104_disp_ovly_oclass,
+ &gp102_disp_core_oclass,
+ &gp102_disp_base_oclass,
+ &gp102_disp_ovly_oclass,
},
.pioc = {
- &gk104_disp_oimm_oclass,
- &gk104_disp_curs_oclass,
+ &gp102_disp_oimm_oclass,
+ &gp102_disp_curs_oclass,
},
};
static int
-gp104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
+gp102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
- return nv50_disp_root_new_(&gp104_disp_root, disp, oclass,
+ return nv50_disp_root_new_(&gp102_disp_root, disp, oclass,
data, size, pobject);
}
const struct nvkm_disp_oclass
-gp104_disp_root_oclass = {
- .base.oclass = GP104_DISP,
+gp102_disp_root_oclass = {
+ .base.oclass = GP102_DISP,
.base.minver = -1,
.base.maxver = -1,
- .ctor = gp104_disp_root_new,
+ .ctor = gp102_disp_root_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 2f9cecd81d04..e70dc6a9ff7d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -66,7 +66,7 @@ nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0)
return 0;
}
-int
+static int
nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
union {
@@ -173,13 +173,56 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
return 0;
} else
if (args->v0.state != 0) {
- nvkm_output_dp_train(&outpdp->base, 0, true);
+ nvkm_output_dp_train(&outpdp->base, 0);
return 0;
}
} else
return ret;
}
break;
+ case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
+ struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
+ union {
+ struct nv50_disp_sor_dp_mst_link_v0 v0;
+ } *args = data;
+ int ret = -ENOSYS;
+ nvif_ioctl(object, "disp sor dp mst link size %d\n", size);
+ if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+ nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n",
+ args->v0.version, args->v0.state);
+ if (outpdp->lt.mst != !!args->v0.state) {
+ outpdp->lt.mst = !!args->v0.state;
+ atomic_set(&outpdp->lt.done, 0);
+ nvkm_output_dp_train(&outpdp->base, 0);
+ }
+ return 0;
+ } else
+ return ret;
+ }
+ break;
+ case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: {
+ struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
+ union {
+ struct nv50_disp_sor_dp_mst_vcpi_v0 v0;
+ } *args = data;
+ int ret = -ENOSYS;
+ nvif_ioctl(object, "disp sor dp mst vcpi size %d\n", size);
+ if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+ nvif_ioctl(object, "disp sor dp mst vcpi vers %d "
+ "slot %02x/%02x pbn %04x/%04x\n",
+ args->v0.version, args->v0.start_slot,
+ args->v0.num_slots, args->v0.pbn,
+ args->v0.aligned_pbn);
+ if (!outpdp->func->vcpi)
+ return -ENODEV;
+ outpdp->func->vcpi(outpdp, head, args->v0.start_slot,
+ args->v0.num_slots, args->v0.pbn,
+ args->v0.aligned_pbn);
+ return 0;
+ } else
+ return ret;
+ }
+ break;
case NV50_DISP_MTHD_V1_PIOR_PWR:
if (!func->pior.power)
return -ENODEV;
@@ -207,8 +250,8 @@ nv50_disp_root_pioc_new_(const struct nvkm_oclass *oclass,
{
const struct nv50_disp_pioc_oclass *sclass = oclass->priv;
struct nv50_disp_root *root = nv50_disp_root(oclass->parent);
- return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid,
- oclass, data, size, pobject);
+ return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid.ctrl,
+ sclass->chid.user, oclass, data, size, pobject);
}
static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
index ad00f1724b72..b147cf5b3518 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
@@ -41,5 +41,5 @@ extern const struct nvkm_disp_oclass gk110_disp_root_oclass;
extern const struct nvkm_disp_oclass gm107_disp_root_oclass;
extern const struct nvkm_disp_oclass gm200_disp_root_oclass;
extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
-extern const struct nvkm_disp_oclass gp104_disp_root_oclass;
+extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
index 1bb9d661e9b3..4510cb6e10a8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
@@ -45,14 +45,6 @@ static const struct nvkm_output_func
g94_sor_output_func = {
};
-int
-g94_sor_output_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_new_(&g94_sor_output_func, disp,
- index, dcbE, poutp);
-}
-
/*******************************************************************************
* DisplayPort
******************************************************************************/
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index 49bd5da194e1..6ffdaa65aa77 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -56,11 +56,13 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
clksor |= bw << 18;
dpctrl |= ((1 << nr) - 1) << 16;
+ if (outp->lt.mst)
+ dpctrl |= 0x40000000;
if (ef)
dpctrl |= 0x00004000;
nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
- nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl);
+ nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
return 0;
}
@@ -101,12 +103,24 @@ gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
return 0;
}
+void
+gf119_sor_dp_vcpi(struct nvkm_output_dp *outp, int head, u8 slot,
+ u8 slot_nr, u16 pbn, u16 aligned)
+{
+ struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+ const u32 hoff = head * 0x800;
+
+ nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
+ nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn);
+}
+
static const struct nvkm_output_dp_func
gf119_sor_dp_func = {
.pattern = gf119_sor_dp_pattern,
.lnk_pwr = g94_sor_dp_lnk_pwr,
.lnk_ctl = gf119_sor_dp_lnk_ctl,
.drv_ctl = gf119_sor_dp_drv_ctl,
+ .vcpi = gf119_sor_dp_vcpi,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
index 37790b2617c5..4cf8ad4d18ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
@@ -43,6 +43,7 @@ gm107_sor_dp_func = {
.lnk_pwr = g94_sor_dp_lnk_pwr,
.lnk_ctl = gf119_sor_dp_lnk_ctl,
.drv_ctl = gf119_sor_dp_drv_ctl,
+ .vcpi = gf119_sor_dp_vcpi,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
index c44fa7ea672a..81b788fa61be 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
@@ -120,6 +120,7 @@ gm200_sor_dp_func = {
.lnk_pwr = gm200_sor_dp_lnk_pwr,
.lnk_ctl = gf119_sor_dp_lnk_ctl,
.drv_ctl = gm200_sor_dp_drv_ctl,
+ .vcpi = gf119_sor_dp_vcpi,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
index aeb3387a3fb0..15a992b3580a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
@@ -129,7 +129,7 @@ g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
}
-int
+static int
g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine)
{
@@ -170,7 +170,7 @@ g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
}
-int
+static int
g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
struct nvkm_object *object)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index 352a0baec84d..ec68ea9747d5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -180,7 +180,8 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
list_del_init(&chan->head);
chan->killed = true;
- fifo->recover.mask |= 1ULL << engine->subdev.index;
+ if (engine != &fifo->base.engine)
+ fifo->recover.mask |= 1ULL << engine->subdev.index;
schedule_work(&fifo->recover.work);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 103c0afaaa6d..38c0910722c0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -743,14 +743,14 @@ gk104_fifo_fault_engine[] = {
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{ 0x06, "SCHED" },
- { 0x07, "HOST0" },
- { 0x08, "HOST1" },
- { 0x09, "HOST2" },
- { 0x0a, "HOST3" },
- { 0x0b, "HOST4" },
- { 0x0c, "HOST5" },
- { 0x0d, "HOST6" },
- { 0x0e, "HOST7" },
+ { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
+ { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
+ { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
+ { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
+ { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
+ { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
+ { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
+ { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
{ 0x0f, "HOSTSR" },
{ 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
{ 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
index bd1ff877aa06..29c080683b32 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
@@ -32,14 +32,14 @@ gm107_fifo_fault_engine[] = {
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{ 0x06, "SCHED" },
- { 0x07, "HOST0" },
- { 0x08, "HOST1" },
- { 0x09, "HOST2" },
- { 0x0a, "HOST3" },
- { 0x0b, "HOST4" },
- { 0x0c, "HOST5" },
- { 0x0d, "HOST6" },
- { 0x0e, "HOST7" },
+ { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
+ { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
+ { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
+ { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
+ { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
+ { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
+ { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
+ { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
{ 0x0f, "HOSTSR" },
{ 0x13, "PERF" },
{ 0x17, "PMU" },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
index eff83f7fb705..b2635aea9f6e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
@@ -30,17 +30,17 @@ gp100_fifo_fault_engine[] = {
{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
- { 0x06, "HOST0" },
- { 0x07, "HOST1" },
- { 0x08, "HOST2" },
- { 0x09, "HOST3" },
- { 0x0a, "HOST4" },
- { 0x0b, "HOST5" },
- { 0x0c, "HOST6" },
- { 0x0d, "HOST7" },
- { 0x0e, "HOST8" },
- { 0x0f, "HOST9" },
- { 0x10, "HOST10" },
+ { 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO },
+ { 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO },
+ { 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO },
+ { 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO },
+ { 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO },
+ { 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO },
+ { 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO },
+ { 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO },
+ { 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO },
+ { 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO },
+ { 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO },
{ 0x13, "PERF" },
{ 0x17, "PMU" },
{ 0x18, "PTP" },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index cbc67f262322..12d964260a29 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
struct nvkm_gpuobj *inst = chan->base.inst;
int ret = 0;
+ mutex_lock(&subdev->mutex);
nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000,
if (nvkm_rd32(device, 0x002634) == chan->base.chid)
@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
chan->base.chid, chan->base.object.client->name);
- ret = -EBUSY;
- if (suspend)
- return ret;
+ ret = -ETIMEDOUT;
}
+ mutex_unlock(&subdev->mutex);
+
+ if (ret && suspend)
+ return ret;
if (offset) {
nvkm_kmap(inst);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index ed4351032ed6..a2df4f3e7763 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_client *client = chan->base.object.client;
+ int ret = 0;
+ mutex_lock(&subdev->mutex);
nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
chan->base.chid, client->name);
- return -EBUSY;
+ ret = -ETIMEDOUT;
}
-
- return 0;
+ mutex_unlock(&subdev->mutex);
+ return ret;
}
static u32
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
index c925ade5880e..74a64e3fd59a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
@@ -218,7 +218,7 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info)
}
}
-void
+static void
gf117_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
index 6d3c5011e18c..4c4b5ab6e46d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
@@ -933,7 +933,7 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info)
}
}
-void
+static void
gm107_grctx_generate_tpcid(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c
index 1e13278cf306..c8bb9191f9a2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c
@@ -106,6 +106,7 @@
#define CP_SEEK_2 0x00c800ff
#include "ctxnv40.h"
+#include "nv50.h"
#include <subdev/fb.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
index 8cb240b65ec2..12a703fe355d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf100_grgpc_data[] = {
+static uint32_t gf100_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x00000064,
/* 0x0004: gpc_mmio_list_tail */
@@ -36,7 +36,7 @@ uint32_t gf100_grgpc_data[] = {
0x00000000,
};
-uint32_t gf100_grgpc_code[] = {
+static uint32_t gf100_grgpc_code[] = {
0x03a10ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
index 550d6ba0933b..ffbfc51200f1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf117_grgpc_data[] = {
+static uint32_t gf117_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x0000006c,
/* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gf117_grgpc_data[] = {
0x00000000,
};
-uint32_t gf117_grgpc_code[] = {
+static uint32_t gf117_grgpc_code[] = {
0x03a10ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
index 271b59d365e5..357f662de571 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gk104_grgpc_data[] = {
+static uint32_t gk104_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x0000006c,
/* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk104_grgpc_data[] = {
0x00000000,
};
-uint32_t gk104_grgpc_code[] = {
+static uint32_t gk104_grgpc_code[] = {
0x03a10ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
index 73b4a32c5d29..4ffc8212a85c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gk110_grgpc_data[] = {
+static uint32_t gk110_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x0000006c,
/* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk110_grgpc_data[] = {
0x00000000,
};
-uint32_t gk110_grgpc_code[] = {
+static uint32_t gk110_grgpc_code[] = {
0x03a10ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
index 018169818317..09196206c9bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
@@ -1,4 +1,4 @@
-uint32_t gk208_grgpc_data[] = {
+static uint32_t gk208_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x0000006c,
/* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk208_grgpc_data[] = {
0x00000000,
};
-uint32_t gk208_grgpc_code[] = {
+static uint32_t gk208_grgpc_code[] = {
0x03140ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
index eca007f03fa9..6d7d004363d9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
@@ -1,4 +1,4 @@
-uint32_t gm107_grgpc_data[] = {
+static uint32_t gm107_grgpc_data[] = {
/* 0x0000: gpc_mmio_list_head */
0x0000006c,
/* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gm107_grgpc_data[] = {
0x00000000,
};
-uint32_t gm107_grgpc_code[] = {
+static uint32_t gm107_grgpc_code[] = {
0x03410ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
index 8015b40a61d6..7538404b8b13 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf100_grhub_data[] = {
+static uint32_t gf100_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gf100_grhub_data[] = {
0x0417e91c,
};
-uint32_t gf100_grhub_code[] = {
+static uint32_t gf100_grhub_code[] = {
0x039b0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
index 2af90ec6852a..ce000a47ec6d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf117_grhub_data[] = {
+static uint32_t gf117_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gf117_grhub_data[] = {
0x0417e91c,
};
-uint32_t gf117_grhub_code[] = {
+static uint32_t gf117_grhub_code[] = {
0x039b0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
index e8b8c1c94700..1f26cb6a233c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gk104_grhub_data[] = {
+static uint32_t gk104_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk104_grhub_data[] = {
0x0417e91c,
};
-uint32_t gk104_grhub_code[] = {
+static uint32_t gk104_grhub_code[] = {
0x039b0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
index f4ed2fb6f714..70436d93efe3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gk110_grhub_data[] = {
+static uint32_t gk110_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk110_grhub_data[] = {
0x0417e91c,
};
-uint32_t gk110_grhub_code[] = {
+static uint32_t gk110_grhub_code[] = {
0x039b0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
index ed488973c117..e0933a07426a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
@@ -1,4 +1,4 @@
-uint32_t gk208_grhub_data[] = {
+static uint32_t gk208_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk208_grhub_data[] = {
0x0417e91c,
};
-uint32_t gk208_grhub_code[] = {
+static uint32_t gk208_grhub_code[] = {
0x030e0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
index 5c9051839557..9b432823bcbe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
@@ -1,4 +1,4 @@
-uint32_t gm107_grhub_data[] = {
+static uint32_t gm107_grhub_data[] = {
/* 0x0000: hub_mmio_list_head */
0x00000300,
/* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gm107_grhub_data[] = {
0x0417e91c,
};
-uint32_t gm107_grhub_code[] = {
+static uint32_t gm107_grhub_code[] = {
0x030e0ef5,
/* 0x0004: queue_put */
0x9800d898,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 157919c788e6..f65a5b0a1a4d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1041,6 +1041,13 @@ gf100_gr_trap_tpc(struct gf100_gr *gr, int gpc, int tpc)
stat &= ~0x00000008;
}
+ if (stat & 0x00000010) {
+ u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0430));
+ nvkm_error(subdev, "GPC%d/TPC%d/MPC: %08x\n", gpc, tpc, trap);
+ nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0430), 0xc0000000);
+ stat &= ~0x00000010;
+ }
+
if (stat) {
nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat);
}
@@ -1258,7 +1265,7 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr)
struct nvkm_device *device = subdev->device;
u32 stat = nvkm_rd32(device, 0x409c18);
- if (stat & 0x00000001) {
+ if (!gr->firmware && (stat & 0x00000001)) {
u32 code = nvkm_rd32(device, 0x409814);
if (code == E_BAD_FWMTHD) {
u32 class = nvkm_rd32(device, 0x409808);
@@ -1270,15 +1277,14 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr)
nvkm_error(subdev, "FECS MTHD subc %d class %04x "
"mthd %04x data %08x\n",
subc, class, mthd, data);
-
- nvkm_wr32(device, 0x409c20, 0x00000001);
- stat &= ~0x00000001;
} else {
nvkm_error(subdev, "FECS ucode error %d\n", code);
}
+ nvkm_wr32(device, 0x409c20, 0x00000001);
+ stat &= ~0x00000001;
}
- if (stat & 0x00080000) {
+ if (!gr->firmware && (stat & 0x00080000)) {
nvkm_error(subdev, "FECS watchdog timeout\n");
gf100_gr_ctxctl_debug(gr);
nvkm_wr32(device, 0x409c20, 0x00080000);
@@ -1384,7 +1390,7 @@ gf100_gr_intr(struct nvkm_gr *base)
nvkm_fifo_chan_put(device->fifo, flags, &chan);
}
-void
+static void
gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
{
@@ -1701,7 +1707,7 @@ gf100_gr_oneinit(struct nvkm_gr *base)
return 0;
}
-int
+static int
gf100_gr_init_(struct nvkm_gr *base)
{
struct gf100_gr *gr = gf100_gr(base);
@@ -1756,6 +1762,50 @@ gf100_gr_ = {
};
int
+gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname,
+ struct gf100_gr_fuc *fuc, int ret)
+{
+ struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ const struct firmware *fw;
+ char f[32];
+
+ /* see if this firmware has a legacy path */
+ if (!strcmp(fwname, "fecs_inst"))
+ fwname = "fuc409c";
+ else if (!strcmp(fwname, "fecs_data"))
+ fwname = "fuc409d";
+ else if (!strcmp(fwname, "gpccs_inst"))
+ fwname = "fuc41ac";
+ else if (!strcmp(fwname, "gpccs_data"))
+ fwname = "fuc41ad";
+ else {
+ /* nope, let's just return the error we got */
+ nvkm_error(subdev, "failed to load %s\n", fwname);
+ return ret;
+ }
+
+ /* yes, try to load from the legacy path */
+ nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname);
+
+ snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
+ ret = request_firmware(&fw, f, device->dev);
+ if (ret) {
+ snprintf(f, sizeof(f), "nouveau/%s", fwname);
+ ret = request_firmware(&fw, f, device->dev);
+ if (ret) {
+ nvkm_error(subdev, "failed to load %s\n", fwname);
+ return ret;
+ }
+ }
+
+ fuc->size = fw->size;
+ fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
+ release_firmware(fw);
+ return (fuc->data != NULL) ? 0 : -ENOMEM;
+}
+
+int
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
struct gf100_gr_fuc *fuc)
{
@@ -1765,10 +1815,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
int ret;
ret = nvkm_firmware_get(device, fwname, &fw);
- if (ret) {
- nvkm_error(subdev, "failed to load %s\n", fwname);
- return ret;
- }
+ if (ret)
+ return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
fuc->size = fw->size;
fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
index 70335f65c51e..0124e468086e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
@@ -102,7 +102,7 @@ gf117_gr_pack_mmio[] = {
#include "fuc/hubgf117.fuc3.h"
-struct gf100_gr_ucode
+static struct gf100_gr_ucode
gf117_gr_fecs_ucode = {
.code.data = gf117_grhub_code,
.code.size = sizeof(gf117_grhub_code),
@@ -112,7 +112,7 @@ gf117_gr_fecs_ucode = {
#include "fuc/gpcgf117.fuc3.h"
-struct gf100_gr_ucode
+static struct gf100_gr_ucode
gf117_gr_gpccs_ucode = {
.code.data = gf117_grgpc_code,
.code.size = sizeof(gf117_grgpc_code),
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
index 45f965f608a7..2c67fac576d1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
@@ -308,7 +308,7 @@ gm107_gr_init_bios(struct gf100_gr *gr)
}
}
-int
+static int
gm107_gr_init(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
index f1e15a4d4f64..b4e3c50badc7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
@@ -187,6 +187,7 @@ nv30_gr = {
{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
{ -1, -1, 0x0397, &nv04_gr_object }, /* rankine */
+ { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
{}
}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
index 300f5ed5de0b..e7ed04b935cd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
@@ -123,6 +123,7 @@ nv34_gr = {
{ -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */
{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
+ { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
{ -1, -1, 0x0697, &nv04_gr_object }, /* rankine */
{}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
index 740df0f52c38..5e8abacbacc6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
@@ -124,6 +124,7 @@ nv35_gr = {
{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
{ -1, -1, 0x0497, &nv04_gr_object }, /* rankine */
+ { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
{}
}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
index 8616636ad7b4..dde89a4a0f5b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
@@ -71,7 +71,7 @@ nvkm_perfdom_find(struct nvkm_pm *pm, int di)
return NULL;
}
-struct nvkm_perfsig *
+static struct nvkm_perfsig *
nvkm_perfsig_find(struct nvkm_pm *pm, u8 di, u8 si, struct nvkm_perfdom **pdom)
{
struct nvkm_perfdom *dom = *pdom;
@@ -699,7 +699,7 @@ nvkm_pm_oclass_get(struct nvkm_oclass *oclass, int index,
return 1;
}
-int
+static int
nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig,
const struct nvkm_specsrc *spec)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
index d2901e9a7808..fe2532ee4145 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
@@ -102,7 +102,7 @@ gf100_pm_gpc[] = {
{}
};
-const struct nvkm_specdom
+static const struct nvkm_specdom
gf100_pm_part[] = {
{ 0xe0, (const struct nvkm_specsig[]) {
{ 0x0f, "part00_pbfb_00", gf100_pbfb_sources },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
index eca62221f299..4b57f8814560 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
@@ -1,4 +1,4 @@
-uint32_t g98_sec_data[] = {
+static uint32_t g98_sec_data[] = {
/* 0x0000: ctx_dma */
/* 0x0000: ctx_dma_query */
0x00000000,
@@ -150,7 +150,7 @@ uint32_t g98_sec_data[] = {
0x00000000,
};
-uint32_t g98_sec_code[] = {
+static uint32_t g98_sec_code[] = {
0x17f004bd,
0x0010fe35,
0xf10004fe,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
index 370dcd8ff7b5..6eff637ac301 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
@@ -84,7 +84,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
start = 0x0100000000ULL;
limit = start + device->func->resource_size(device, 3);
- ret = nvkm_vm_new(device, start, limit, start, &bar3_lock, &vm);
+ ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm);
if (ret)
return ret;
@@ -117,7 +117,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
start = 0x0000000000ULL;
limit = start + device->func->resource_size(device, 1);
- ret = nvkm_vm_new(device, start, limit--, start, &bar1_lock, &vm);
+ ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild
index dbcb0ef21587..be57220a2e01 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild
@@ -31,6 +31,7 @@ nvkm-y += nvkm/subdev/bios/timing.o
nvkm-y += nvkm/subdev/bios/therm.o
nvkm-y += nvkm/subdev/bios/vmap.o
nvkm-y += nvkm/subdev/bios/volt.o
+nvkm-y += nvkm/subdev/bios/vpstate.o
nvkm-y += nvkm/subdev/bios/xpio.o
nvkm-y += nvkm/subdev/bios/M0203.o
nvkm-y += nvkm/subdev/bios/M0205.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c
index 3756ec91a88d..eaf74eb72983 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c
@@ -25,16 +25,16 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/boost.h>
-u16
+u32
nvbios_boostTe(struct nvkm_bios *bios,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
{
struct bit_entry bit_P;
- u16 boost = 0x0000;
+ u32 boost = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 2)
- boost = nvbios_rd16(bios, bit_P.offset + 0x30);
+ boost = nvbios_rd32(bios, bit_P.offset + 0x30);
if (boost) {
*ver = nvbios_rd08(bios, boost + 0);
@@ -52,15 +52,15 @@ nvbios_boostTe(struct nvkm_bios *bios,
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_boostEe(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
u8 snr, ssz;
- u16 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+ u32 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz);
if (data && idx < *cnt) {
data = data + *hdr + (idx * (*len + (snr * ssz)));
*hdr = *len;
@@ -68,14 +68,14 @@ nvbios_boostEe(struct nvkm_bios *bios, int idx,
*len = ssz;
return data;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_boostEp(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
{
- u16 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len);
+ u32 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len);
memset(info, 0x00, sizeof(*info));
if (data) {
info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5;
@@ -85,7 +85,7 @@ nvbios_boostEp(struct nvkm_bios *bios, int idx,
return data;
}
-u16
+u32
nvbios_boostEm(struct nvkm_bios *bios, u8 pstate,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
{
@@ -97,21 +97,21 @@ nvbios_boostEm(struct nvkm_bios *bios, u8 pstate,
return data;
}
-u16
+u32
nvbios_boostSe(struct nvkm_bios *bios, int idx,
- u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len)
+ u32 data, u8 *ver, u8 *hdr, u8 cnt, u8 len)
{
if (data && idx < cnt) {
data = data + *hdr + (idx * len);
*hdr = len;
return data;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_boostSp(struct nvkm_bios *bios, int idx,
- u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len,
+ u32 data, u8 *ver, u8 *hdr, u8 cnt, u8 len,
struct nvbios_boostS *info)
{
data = nvbios_boostSe(bios, idx, data, ver, hdr, cnt, len);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c
index 32e01624a162..5063382d8a6c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c
@@ -25,16 +25,16 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/cstep.h>
-u16
+u32
nvbios_cstepTe(struct nvkm_bios *bios,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
{
struct bit_entry bit_P;
- u16 cstep = 0x0000;
+ u32 cstep = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 2)
- cstep = nvbios_rd16(bios, bit_P.offset + 0x34);
+ cstep = nvbios_rd32(bios, bit_P.offset + 0x34);
if (cstep) {
*ver = nvbios_rd08(bios, cstep + 0);
@@ -52,27 +52,27 @@ nvbios_cstepTe(struct nvkm_bios *bios,
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_cstepEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
{
u8 cnt, len, xnr, xsz;
- u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
+ u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
if (data && idx < cnt) {
data = data + *hdr + (idx * len);
*hdr = len;
return data;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_cstepEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
struct nvbios_cstepE *info)
{
- u16 data = nvbios_cstepEe(bios, idx, ver, hdr);
+ u32 data = nvbios_cstepEe(bios, idx, ver, hdr);
memset(info, 0x00, sizeof(*info));
if (data) {
info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5;
@@ -81,7 +81,7 @@ nvbios_cstepEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
return data;
}
-u16
+u32
nvbios_cstepEm(struct nvkm_bios *bios, u8 pstate, u8 *ver, u8 *hdr,
struct nvbios_cstepE *info)
{
@@ -93,24 +93,24 @@ nvbios_cstepEm(struct nvkm_bios *bios, u8 pstate, u8 *ver, u8 *hdr,
return data;
}
-u16
+u32
nvbios_cstepXe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
{
u8 cnt, len, xnr, xsz;
- u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
+ u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
if (data && idx < xnr) {
data = data + *hdr + (cnt * len) + (idx * xsz);
*hdr = xsz;
return data;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_cstepXp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
struct nvbios_cstepX *info)
{
- u16 data = nvbios_cstepXe(bios, idx, ver, hdr);
+ u32 data = nvbios_cstepXe(bios, idx, ver, hdr);
memset(info, 0x00, sizeof(*info));
if (data) {
info->freq = nvbios_rd16(bios, data + 0x00) * 1000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
index d89e78c4e689..972370ed36f0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
@@ -207,8 +207,11 @@ nvbios_dpcfg_match(struct nvkm_bios *bios, u16 outp, u8 pc, u8 vs, u8 pe,
if (*ver >= 0x30) {
const u8 vsoff[] = { 0, 4, 7, 9 };
idx = (pc * 10) + vsoff[vs] + pe;
- if (*ver >= 0x40 && *hdr >= 0x12)
+ if (*ver >= 0x40 && *ver <= 0x41 && *hdr >= 0x12)
idx += nvbios_rd08(bios, outp + 0x11) * 40;
+ else
+ if (*ver >= 0x42)
+ idx += nvbios_rd08(bios, outp + 0x11) * 10;
} else {
while ((data = nvbios_dpcfg_entry(bios, outp, ++idx,
ver, hdr, cnt, len))) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
index 80fed7e78dcb..456f9ea920dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
@@ -25,15 +25,15 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/fan.h>
-u16
+static u32
nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
struct bit_entry bit_P;
- u16 fan = 0x0000;
+ u32 fan = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 2 && bit_P.length >= 0x5a)
- fan = nvbios_rd16(bios, bit_P.offset + 0x58);
+ fan = nvbios_rd32(bios, bit_P.offset + 0x58);
if (fan) {
*ver = nvbios_rd08(bios, fan + 0);
@@ -49,25 +49,25 @@ nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
}
}
- return 0x0000;
+ return 0;
}
-u16
+static u32
nvbios_fan_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
u8 *cnt, u8 *len)
{
- u16 data = nvbios_fan_table(bios, ver, hdr, cnt, len);
+ u32 data = nvbios_fan_table(bios, ver, hdr, cnt, len);
if (data && idx < *cnt)
return data + *hdr + (idx * (*len));
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan)
{
u8 ver, hdr, cnt, len;
- u16 data = nvbios_fan_entry(bios, 0, &ver, &hdr, &cnt, &len);
+ u32 data = nvbios_fan_entry(bios, 0, &ver, &hdr, &cnt, &len);
if (data) {
u8 type = nvbios_rd08(bios, data + 0x00);
switch (type) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
index 084328028af1..3953d11844ea 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
@@ -23,20 +23,21 @@
*/
#include <subdev/bios.h>
#include <subdev/bios/bit.h>
+#include <subdev/bios/extdev.h>
#include <subdev/bios/iccsense.h>
-static u16
+static u32
nvbios_iccsense_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt,
u8 *len)
{
struct bit_entry bit_P;
- u16 iccsense;
+ u32 iccsense;
if (bit_entry(bios, 'P', &bit_P) || bit_P.version != 2 ||
bit_P.length < 0x2c)
return 0;
- iccsense = nvbios_rd16(bios, bit_P.offset + 0x28);
+ iccsense = nvbios_rd32(bios, bit_P.offset + 0x28);
if (!iccsense)
return 0;
@@ -60,7 +61,7 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
{
struct nvkm_subdev *subdev = &bios->subdev;
u8 ver, hdr, cnt, len, i;
- u16 table, entry;
+ u32 table, entry;
table = nvbios_iccsense_table(bios, &ver, &hdr, &cnt, &len);
if (!table || !cnt)
@@ -77,23 +78,47 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
return -ENOMEM;
for (i = 0; i < cnt; ++i) {
+ struct nvbios_extdev_func extdev;
struct pwr_rail_t *rail = &iccsense->rail[i];
+ u8 res_start = 0;
+ int r;
+
entry = table + hdr + i * len;
switch(ver) {
case 0x10:
rail->mode = nvbios_rd08(bios, entry + 0x1);
rail->extdev_id = nvbios_rd08(bios, entry + 0x2);
- rail->resistor_mohm = nvbios_rd08(bios, entry + 0x3);
- rail->rail = nvbios_rd08(bios, entry + 0x4);
+ res_start = 0x3;
break;
case 0x20:
rail->mode = nvbios_rd08(bios, entry);
rail->extdev_id = nvbios_rd08(bios, entry + 0x1);
- rail->resistor_mohm = nvbios_rd08(bios, entry + 0x5);
- rail->rail = nvbios_rd08(bios, entry + 0x6);
+ res_start = 0x5;
+ break;
+ };
+
+ if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev))
+ continue;
+
+ switch (extdev.type) {
+ case NVBIOS_EXTDEV_INA209:
+ case NVBIOS_EXTDEV_INA219:
+ rail->resistor_count = 1;
+ break;
+ case NVBIOS_EXTDEV_INA3221:
+ rail->resistor_count = 3;
+ break;
+ default:
+ rail->resistor_count = 0;
break;
};
+
+ for (r = 0; r < rail->resistor_count; ++r) {
+ rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2);
+ rail->resistors[r].enabled = !(nvbios_rd08(bios, entry + res_start + r * 2 + 1) & 0x40);
+ }
+ rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2);
}
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c
index 3ddf0939ded3..994cc2d7759b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c
@@ -81,7 +81,7 @@ mxm_sor_map(struct nvkm_bios *bios, u8 conn)
u16 map = nvbios_rd16(bios, mxm + 4);
if (map) {
ver = nvbios_rd08(bios, map);
- if (ver == 0x10) {
+ if (ver == 0x10 || ver == 0x11) {
if (conn < nvbios_rd08(bios, map + 3)) {
map += nvbios_rd08(bios, map + 1);
map += conn;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
index 636bfb665bb9..c3068358f695 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
@@ -26,16 +26,16 @@
#include <subdev/bios/perf.h>
#include <subdev/pci.h>
-u16
+u32
nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
{
struct bit_entry bit_P;
- u16 perf = 0x0000;
+ u32 perf = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version <= 2) {
- perf = nvbios_rd16(bios, bit_P.offset + 0);
+ perf = nvbios_rd32(bios, bit_P.offset + 0);
if (perf) {
*ver = nvbios_rd08(bios, perf + 0);
*hdr = nvbios_rd08(bios, perf + 1);
@@ -72,15 +72,15 @@ nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_perf_entry(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
u8 snr, ssz;
- u16 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz);
+ u32 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz);
if (perf && idx < *cnt) {
perf = perf + *hdr + (idx * (*len + (snr * ssz)));
*hdr = *len;
@@ -88,14 +88,14 @@ nvbios_perf_entry(struct nvkm_bios *bios, int idx,
*len = ssz;
return perf;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_perfEp(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *info)
{
- u16 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
+ u32 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
memset(info, 0x00, sizeof(*info));
info->pstate = nvbios_rd08(bios, perf + 0x00);
switch (!!perf * *ver) {
@@ -163,7 +163,7 @@ nvbios_perfEp(struct nvkm_bios *bios, int idx,
info->pcie_width = 0xff;
break;
default:
- return 0x0000;
+ return 0;
}
return perf;
}
@@ -202,7 +202,7 @@ nvbios_perf_fan_parse(struct nvkm_bios *bios,
struct nvbios_perf_fan *fan)
{
u8 ver, hdr, cnt, len, snr, ssz;
- u16 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
+ u32 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
if (!perf)
return -ENODEV;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
index 212800ecdce9..7d1d3c6b4b72 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
@@ -12,6 +12,7 @@ struct nvbios_source {
bool rw;
bool ignore_checksum;
bool no_pcir;
+ bool require_checksum;
};
int nvbios_extend(struct nvkm_bios *, u32 length);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
index b2557e87afdd..7deb81b6dbac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -86,9 +86,12 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
nvbios_checksum(&bios->data[image.base], image.size)) {
nvkm_debug(subdev, "%08x: checksum failed\n",
image.base);
- if (mthd->func->rw)
+ if (!mthd->func->require_checksum) {
+ if (mthd->func->rw)
+ score += 1;
score += 1;
- score += 1;
+ } else
+ return 0;
} else {
score += 3;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
index 8fecb5ff22a0..06572f8ce914 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
@@ -99,6 +99,7 @@ nvbios_acpi_fast = {
.init = acpi_init,
.read = acpi_read_fast,
.rw = false,
+ .require_checksum = true,
};
const struct nvbios_source
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c
index a54cfec0550d..5babc5a7c7d5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c
@@ -25,17 +25,17 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/therm.h>
-static u16
+static u32
therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
{
struct bit_entry bit_P;
- u16 therm = 0;
+ u32 therm = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 1)
- therm = nvbios_rd16(bios, bit_P.offset + 12);
+ therm = nvbios_rd32(bios, bit_P.offset + 12);
else if (bit_P.version == 2)
- therm = nvbios_rd16(bios, bit_P.offset + 16);
+ therm = nvbios_rd32(bios, bit_P.offset + 16);
else
nvkm_error(&bios->subdev,
"unknown offset for thermal in BIT P %d\n",
@@ -44,7 +44,7 @@ therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
/* exit now if we haven't found the thermal table */
if (!therm)
- return 0x0000;
+ return 0;
*ver = nvbios_rd08(bios, therm + 0);
*hdr = nvbios_rd08(bios, therm + 1);
@@ -53,14 +53,14 @@ therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
return therm + nvbios_rd08(bios, therm + 1);
}
-static u16
+static u32
nvbios_therm_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
{
u8 hdr, cnt;
- u16 therm = therm_table(bios, ver, &hdr, len, &cnt);
+ u32 therm = therm_table(bios, ver, &hdr, len, &cnt);
if (therm && idx < cnt)
return therm + idx * *len;
- return 0x0000;
+ return 0;
}
int
@@ -70,7 +70,7 @@ nvbios_therm_sensor_parse(struct nvkm_bios *bios,
{
s8 thrs_section, sensor_section, offset;
u8 ver, len, i;
- u16 entry;
+ u32 entry;
/* we only support the core domain for now */
if (domain != NVBIOS_THERM_DOMAIN_CORE)
@@ -154,7 +154,7 @@ nvbios_therm_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan)
{
struct nvbios_therm_trip_point *cur_trip = NULL;
u8 ver, len, i;
- u16 entry;
+ u32 entry;
uint8_t duty_lut[] = { 0, 0, 25, 0, 40, 0, 50, 0,
75, 0, 85, 0, 100, 0, 100, 0 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
index 99f6432ac0af..7e83c3985020 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
@@ -25,19 +25,19 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/timing.h>
-u16
+u32
nvbios_timingTe(struct nvkm_bios *bios,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
{
struct bit_entry bit_P;
- u16 timing = 0x0000;
+ u32 timing = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 1)
- timing = nvbios_rd16(bios, bit_P.offset + 4);
+ timing = nvbios_rd32(bios, bit_P.offset + 4);
else
if (bit_P.version == 2)
- timing = nvbios_rd16(bios, bit_P.offset + 8);
+ timing = nvbios_rd32(bios, bit_P.offset + 8);
if (timing) {
*ver = nvbios_rd08(bios, timing + 0);
@@ -62,15 +62,15 @@ nvbios_timingTe(struct nvkm_bios *bios,
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_timingEe(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
u8 snr, ssz;
- u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+ u32 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
if (timing && idx < *cnt) {
timing += *hdr + idx * (*len + (snr * ssz));
*hdr = *len;
@@ -78,14 +78,14 @@ nvbios_timingEe(struct nvkm_bios *bios, int idx,
*len = ssz;
return timing;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_timingEp(struct nvkm_bios *bios, int idx,
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p)
{
- u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
+ u32 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
p->timing_ver = *ver;
p->timing_hdr = *hdr;
switch (!!data * *ver) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c
index 2f13db745948..c228ca15fa3b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c
@@ -25,15 +25,15 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/vmap.h>
-u16
+u32
nvbios_vmap_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
struct bit_entry bit_P;
- u16 vmap = 0x0000;
+ u32 vmap = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 2) {
- vmap = nvbios_rd16(bios, bit_P.offset + 0x20);
+ vmap = nvbios_rd32(bios, bit_P.offset + 0x20);
if (vmap) {
*ver = nvbios_rd08(bios, vmap + 0);
switch (*ver) {
@@ -50,40 +50,50 @@ nvbios_vmap_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_vmap *info)
{
- u16 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len);
+ u32 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len);
memset(info, 0x00, sizeof(*info));
switch (!!vmap * *ver) {
case 0x10:
+ info->max0 = 0xff;
+ info->max1 = 0xff;
+ info->max2 = 0xff;
+ break;
case 0x20:
+ info->max0 = nvbios_rd08(bios, vmap + 0x7);
+ info->max1 = nvbios_rd08(bios, vmap + 0x8);
+ if (*len >= 0xc)
+ info->max2 = nvbios_rd08(bios, vmap + 0xc);
+ else
+ info->max2 = 0xff;
break;
}
return vmap;
}
-u16
+u32
nvbios_vmap_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
{
u8 hdr, cnt;
- u16 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len);
+ u32 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len);
if (vmap && idx < cnt) {
vmap = vmap + hdr + (idx * *len);
return vmap;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
struct nvbios_vmap_entry *info)
{
- u16 vmap = nvbios_vmap_entry(bios, idx, ver, len);
+ u32 vmap = nvbios_vmap_entry(bios, idx, ver, len);
memset(info, 0x00, sizeof(*info));
switch (!!vmap * *ver) {
case 0x10:
@@ -95,7 +105,7 @@ nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
info->arg[2] = nvbios_rd32(bios, vmap + 0x10);
break;
case 0x20:
- info->unk0 = nvbios_rd08(bios, vmap + 0x00);
+ info->mode = nvbios_rd08(bios, vmap + 0x00);
info->link = nvbios_rd08(bios, vmap + 0x01);
info->min = nvbios_rd32(bios, vmap + 0x02);
info->max = nvbios_rd32(bios, vmap + 0x06);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
index 6e0a33648be9..a7797a9e9cbc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
@@ -25,18 +25,18 @@
#include <subdev/bios/bit.h>
#include <subdev/bios/volt.h>
-u16
+u32
nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
struct bit_entry bit_P;
- u16 volt = 0x0000;
+ u32 volt = 0;
if (!bit_entry(bios, 'P', &bit_P)) {
if (bit_P.version == 2)
- volt = nvbios_rd16(bios, bit_P.offset + 0x0c);
+ volt = nvbios_rd32(bios, bit_P.offset + 0x0c);
else
if (bit_P.version == 1)
- volt = nvbios_rd16(bios, bit_P.offset + 0x10);
+ volt = nvbios_rd32(bios, bit_P.offset + 0x10);
if (volt) {
*ver = nvbios_rd08(bios, volt + 0);
@@ -62,33 +62,37 @@ nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
}
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_volt *info)
{
- u16 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
+ u32 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
memset(info, 0x00, sizeof(*info));
switch (!!volt * *ver) {
case 0x12:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
+ info->ranged = false;
break;
case 0x20:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x05);
+ info->ranged = false;
break;
case 0x30:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
+ info->ranged = false;
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);
+ info->ranged = true; /* XXX: find the flag byte */
/*XXX*/
info->min = 0;
info->max = info->base;
@@ -104,32 +108,34 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
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);
+ info->type = NVBIOS_VOLT_GPIO;
+ info->vidmask = nvbios_rd08(bios, volt + 0x06);
+ info->step = nvbios_rd16(bios, volt + 0x16);
+ info->ranged =
+ !!(nvbios_rd08(bios, volt + 0x4) & 0x2);
}
break;
}
return volt;
}
-u16
+u32
nvbios_volt_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
{
u8 hdr, cnt;
- u16 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
+ u32 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
if (volt && idx < cnt) {
volt = volt + hdr + (idx * *len);
return volt;
}
- return 0x0000;
+ return 0;
}
-u16
+u32
nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
struct nvbios_volt_entry *info)
{
- u16 volt = nvbios_volt_entry(bios, idx, ver, len);
+ u32 volt = nvbios_volt_entry(bios, idx, ver, len);
memset(info, 0x00, sizeof(*info));
switch (!!volt * *ver) {
case 0x12:
@@ -142,7 +148,10 @@ nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
info->vid = nvbios_rd08(bios, volt + 0x01) >> 2;
break;
case 0x40:
+ break;
case 0x50:
+ info->voltage = nvbios_rd32(bios, volt) & 0x001fffff;
+ info->vid = (nvbios_rd32(bios, volt) >> 23) & 0xff;
break;
}
return volt;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c
new file mode 100644
index 000000000000..f199270163d2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Karol Herbst
+ *
+ * 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: Karol Herbst
+ */
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/vpstate.h>
+
+static u32
+nvbios_vpstate_offset(struct nvkm_bios *b)
+{
+ struct bit_entry bit_P;
+
+ if (!bit_entry(b, 'P', &bit_P)) {
+ if (bit_P.version == 2)
+ return nvbios_rd32(b, bit_P.offset + 0x38);
+ }
+
+ return 0x0000;
+}
+
+int
+nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h)
+{
+ if (!h)
+ return -EINVAL;
+
+ h->offset = nvbios_vpstate_offset(b);
+ if (!h->offset)
+ return -ENODEV;
+
+ h->version = nvbios_rd08(b, h->offset);
+ switch (h->version) {
+ case 0x10:
+ h->hlen = nvbios_rd08(b, h->offset + 0x1);
+ h->elen = nvbios_rd08(b, h->offset + 0x2);
+ h->slen = nvbios_rd08(b, h->offset + 0x3);
+ h->scount = nvbios_rd08(b, h->offset + 0x4);
+ h->ecount = nvbios_rd08(b, h->offset + 0x5);
+
+ h->base_id = nvbios_rd08(b, h->offset + 0x0f);
+ h->boost_id = nvbios_rd08(b, h->offset + 0x10);
+ h->tdp_id = nvbios_rd08(b, h->offset + 0x11);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int
+nvbios_vpstate_entry(struct nvkm_bios *b, struct nvbios_vpstate_header *h,
+ u8 idx, struct nvbios_vpstate_entry *e)
+{
+ u32 offset;
+
+ if (!e || !h || idx > h->ecount)
+ return -EINVAL;
+
+ offset = h->offset + h->hlen + idx * (h->elen + (h->slen * h->scount));
+ e->pstate = nvbios_rd08(b, offset);
+ e->clock_mhz = nvbios_rd16(b, offset + 0x5);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
index 7102c25320fc..e4c8d310d870 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -27,6 +27,7 @@
#include <subdev/bios/boost.h>
#include <subdev/bios/cstep.h>
#include <subdev/bios/perf.h>
+#include <subdev/bios/vpstate.h>
#include <subdev/fb.h>
#include <subdev/therm.h>
#include <subdev/volt.h>
@@ -43,13 +44,13 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust,
struct nvkm_bios *bios = clk->subdev.device->bios;
struct nvbios_boostE boostE;
u8 ver, hdr, cnt, len;
- u16 data;
+ u32 data;
data = nvbios_boostEm(bios, pstate, &ver, &hdr, &cnt, &len, &boostE);
if (data) {
struct nvbios_boostS boostS;
u8 idx = 0, sver, shdr;
- u16 subd;
+ u32 subd;
input = max(boostE.min, input);
input = min(boostE.max, input);
@@ -74,6 +75,88 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust,
/******************************************************************************
* C-States
*****************************************************************************/
+static bool
+nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate,
+ u32 max_volt, int temp)
+{
+ const struct nvkm_domain *domain = clk->domains;
+ struct nvkm_volt *volt = clk->subdev.device->volt;
+ int voltage;
+
+ while (domain && domain->name != nv_clk_src_max) {
+ if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) {
+ u32 freq = cstate->domain[domain->name];
+ switch (clk->boost_mode) {
+ case NVKM_CLK_BOOST_NONE:
+ if (clk->base_khz && freq > clk->base_khz)
+ return false;
+ case NVKM_CLK_BOOST_BIOS:
+ if (clk->boost_khz && freq > clk->boost_khz)
+ return false;
+ }
+ }
+ domain++;
+ }
+
+ if (!volt)
+ return true;
+
+ voltage = nvkm_volt_map(volt, cstate->voltage, temp);
+ if (voltage < 0)
+ return false;
+ return voltage <= min(max_volt, volt->max_uv);
+}
+
+static struct nvkm_cstate *
+nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate,
+ struct nvkm_cstate *start)
+{
+ struct nvkm_device *device = clk->subdev.device;
+ struct nvkm_volt *volt = device->volt;
+ struct nvkm_cstate *cstate;
+ int max_volt;
+
+ if (!pstate || !start)
+ return NULL;
+
+ if (!volt)
+ return start;
+
+ max_volt = volt->max_uv;
+ if (volt->max0_id != 0xff)
+ max_volt = min(max_volt,
+ nvkm_volt_map(volt, volt->max0_id, clk->temp));
+ if (volt->max1_id != 0xff)
+ max_volt = min(max_volt,
+ nvkm_volt_map(volt, volt->max1_id, clk->temp));
+ if (volt->max2_id != 0xff)
+ max_volt = min(max_volt,
+ nvkm_volt_map(volt, volt->max2_id, clk->temp));
+
+ for (cstate = start; &cstate->head != &pstate->list;
+ cstate = list_entry(cstate->head.prev, typeof(*cstate), head)) {
+ if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp))
+ break;
+ }
+
+ return cstate;
+}
+
+static struct nvkm_cstate *
+nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
+{
+ struct nvkm_cstate *cstate;
+ if (cstatei == NVKM_CLK_CSTATE_HIGHEST)
+ return list_last_entry(&pstate->list, typeof(*cstate), head);
+ else {
+ list_for_each_entry(cstate, &pstate->list, head) {
+ if (cstate->id == cstatei)
+ return cstate;
+ }
+ }
+ return NULL;
+}
+
static int
nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
{
@@ -85,7 +168,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
int ret;
if (!list_empty(&pstate->list)) {
- cstate = list_entry(pstate->list.prev, typeof(*cstate), head);
+ cstate = nvkm_cstate_get(clk, pstate, cstatei);
+ cstate = nvkm_cstate_find_best(clk, pstate, cstate);
} else {
cstate = &pstate->base;
}
@@ -99,7 +183,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
}
if (volt) {
- ret = nvkm_volt_set_id(volt, cstate->voltage, +1);
+ ret = nvkm_volt_set_id(volt, cstate->voltage,
+ pstate->base.voltage, clk->temp, +1);
if (ret && ret != -ENODEV) {
nvkm_error(subdev, "failed to raise voltage: %d\n", ret);
return ret;
@@ -113,7 +198,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
}
if (volt) {
- ret = nvkm_volt_set_id(volt, cstate->voltage, -1);
+ ret = nvkm_volt_set_id(volt, cstate->voltage,
+ pstate->base.voltage, clk->temp, -1);
if (ret && ret != -ENODEV)
nvkm_error(subdev, "failed to lower voltage: %d\n", ret);
}
@@ -138,22 +224,27 @@ static int
nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
{
struct nvkm_bios *bios = clk->subdev.device->bios;
+ struct nvkm_volt *volt = clk->subdev.device->volt;
const struct nvkm_domain *domain = clk->domains;
struct nvkm_cstate *cstate = NULL;
struct nvbios_cstepX cstepX;
u8 ver, hdr;
- u16 data;
+ u32 data;
data = nvbios_cstepXp(bios, idx, &ver, &hdr, &cstepX);
if (!data)
return -ENOENT;
+ if (volt && nvkm_volt_map_min(volt, cstepX.voltage) > volt->max_uv)
+ return -EINVAL;
+
cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
if (!cstate)
return -ENOMEM;
*cstate = pstate->base;
cstate->voltage = cstepX.voltage;
+ cstate->id = idx;
while (domain && domain->name != nv_clk_src_max) {
if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
@@ -175,7 +266,7 @@ static int
nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
{
struct nvkm_subdev *subdev = &clk->subdev;
- struct nvkm_ram *ram = subdev->device->fb->ram;
+ struct nvkm_fb *fb = subdev->device->fb;
struct nvkm_pci *pci = subdev->device->pci;
struct nvkm_pstate *pstate;
int ret, idx = 0;
@@ -190,7 +281,8 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width);
- if (ram && ram->func->calc) {
+ if (fb && fb->ram && fb->ram->func->calc) {
+ struct nvkm_ram *ram = fb->ram;
int khz = pstate->base.domain[nv_clk_src_mem];
do {
ret = ram->func->calc(ram, khz);
@@ -200,7 +292,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
ram->func->tidy(ram);
}
- return nvkm_cstate_prog(clk, pstate, 0);
+ return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST);
}
static void
@@ -214,14 +306,14 @@ nvkm_pstate_work(struct work_struct *work)
return;
clk->pwrsrc = power_supply_is_system_supplied();
- nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
+ nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d°C D %d\n",
clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
- clk->astate, clk->tstate, clk->dstate);
+ clk->astate, clk->temp, clk->dstate);
pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
if (clk->state_nr && pstate != -1) {
pstate = (pstate < 0) ? clk->astate : pstate;
- pstate = min(pstate, clk->state_nr - 1 + clk->tstate);
+ pstate = min(pstate, clk->state_nr - 1);
pstate = max(pstate, clk->dstate);
} else {
pstate = clk->pstate = -1;
@@ -316,7 +408,7 @@ nvkm_pstate_new(struct nvkm_clk *clk, int idx)
struct nvbios_cstepE cstepE;
struct nvbios_perfE perfE;
u8 ver, hdr, cnt, len;
- u16 data;
+ u32 data;
data = nvbios_perfEp(bios, idx, &ver, &hdr, &cnt, &len, &perfE);
if (!data)
@@ -448,13 +540,12 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait)
}
int
-nvkm_clk_tstate(struct nvkm_clk *clk, int req, int rel)
+nvkm_clk_tstate(struct nvkm_clk *clk, u8 temp)
{
- if (!rel) clk->tstate = req;
- if ( rel) clk->tstate += rel;
- clk->tstate = min(clk->tstate, 0);
- clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
- return nvkm_pstate_calc(clk, true);
+ if (clk->temp == temp)
+ return 0;
+ clk->temp = temp;
+ return nvkm_pstate_calc(clk, false);
}
int
@@ -524,9 +615,9 @@ nvkm_clk_init(struct nvkm_subdev *subdev)
return clk->func->init(clk);
clk->astate = clk->state_nr - 1;
- clk->tstate = 0;
clk->dstate = 0;
clk->pstate = -1;
+ clk->temp = 90; /* reasonable default value */
nvkm_pstate_calc(clk, true);
return 0;
}
@@ -561,10 +652,22 @@ int
nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
int index, bool allow_reclock, struct nvkm_clk *clk)
{
+ struct nvkm_subdev *subdev = &clk->subdev;
+ struct nvkm_bios *bios = device->bios;
int ret, idx, arglen;
const char *mode;
+ struct nvbios_vpstate_header h;
+
+ nvkm_subdev_ctor(&nvkm_clk, device, index, subdev);
+
+ if (bios && !nvbios_vpstate_parse(bios, &h)) {
+ struct nvbios_vpstate_entry base, boost;
+ if (!nvbios_vpstate_entry(bios, &h, h.boost_id, &boost))
+ clk->boost_khz = boost.clock_mhz * 1000;
+ if (!nvbios_vpstate_entry(bios, &h, h.base_id, &base))
+ clk->base_khz = base.clock_mhz * 1000;
+ }
- nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev);
clk->func = func;
INIT_LIST_HEAD(&clk->states);
clk->domains = func->domains;
@@ -607,6 +710,8 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
if (mode)
clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
+ clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
+ NVKM_CLK_BOOST_NONE);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
index 89d5543118cf..7f67f9f5a550 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
@@ -457,7 +457,7 @@ gf100_clk = {
{ nv_clk_src_hubk06 , 0x00 },
{ nv_clk_src_hubk01 , 0x01 },
{ nv_clk_src_copy , 0x02 },
- { nv_clk_src_gpc , 0x03, 0, "core", 2000 },
+ { nv_clk_src_gpc , 0x03, NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
{ nv_clk_src_rop , 0x04 },
{ nv_clk_src_mem , 0x05, 0, "memory", 1000 },
{ nv_clk_src_vdec , 0x06 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
index 06bc0d2d6ae1..0b37e3da7feb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
@@ -491,7 +491,7 @@ gk104_clk = {
.domains = {
{ nv_clk_src_crystal, 0xff },
{ nv_clk_src_href , 0xff },
- { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
+ { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE | NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
{ nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
{ nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE },
{ nv_clk_src_mem , 0x03, 0, "memory", 500 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
index 056702ef69aa..96e0941c8edd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
@@ -180,7 +180,7 @@ gt215_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
return 0;
}
-int
+static int
gt215_clk_info(struct nvkm_clk *base, int idx, u32 khz,
struct gt215_clk_info *info)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
index a410c0db8a08..1730371933df 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
@@ -26,6 +26,7 @@
#include <subdev/bios.h>
#include <subdev/bios/bit.h>
#include <subdev/bios/pmu.h>
+#include <subdev/timer.h>
static void
pmu_code(struct nv50_devinit *init, u32 pmu, u32 img, u32 len, bool sec)
@@ -123,21 +124,13 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
return -EINVAL;
}
- /* reset PMU and load init table parser ucode */
- if (post) {
- nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
- nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
- nvkm_rd32(device, 0x000200);
- while (nvkm_rd32(device, 0x10a10c) & 0x00000006) {
- }
- }
-
ret = pmu_load(init, 0x04, post, &exec, &args);
if (ret)
return ret;
/* upload first chunk of init data */
if (post) {
+ // devinit tables
u32 pmu = pmu_args(init, args + 0x08, 0x08);
u32 img = nvbios_rd16(bios, bit_I.offset + 0x14);
u32 len = nvbios_rd16(bios, bit_I.offset + 0x16);
@@ -146,6 +139,7 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
/* upload second chunk of init data */
if (post) {
+ // devinit boot scripts
u32 pmu = pmu_args(init, args + 0x08, 0x10);
u32 img = nvbios_rd16(bios, bit_I.offset + 0x18);
u32 len = nvbios_rd16(bios, bit_I.offset + 0x1a);
@@ -156,8 +150,11 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
if (post) {
nvkm_wr32(device, 0x10a040, 0x00005000);
pmu_exec(init, exec);
- while (!(nvkm_rd32(device, 0x10a040) & 0x00002000)) {
- }
+ if (nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x10a040) & 0x00002000)
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
}
/* load and execute some other ucode image (bios therm?) */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
index edcc157e6ac8..63566ba12fbb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
@@ -24,8 +24,9 @@ nvkm-y += nvkm/subdev/fb/gk104.o
nvkm-y += nvkm/subdev/fb/gk20a.o
nvkm-y += nvkm/subdev/fb/gm107.o
nvkm-y += nvkm/subdev/fb/gm200.o
+nvkm-y += nvkm/subdev/fb/gm20b.o
nvkm-y += nvkm/subdev/fb/gp100.o
-nvkm-y += nvkm/subdev/fb/gp104.o
+nvkm-y += nvkm/subdev/fb/gp102.o
nvkm-y += nvkm/subdev/fb/ram.o
nvkm-y += nvkm/subdev/fb/ramnv04.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
index 76433cc66fff..3841ad6be99e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
@@ -50,24 +50,33 @@ gf100_fb_intr(struct nvkm_fb *base)
}
int
-gf100_fb_oneinit(struct nvkm_fb *fb)
+gf100_fb_oneinit(struct nvkm_fb *base)
{
- struct nvkm_device *device = fb->subdev.device;
+ struct gf100_fb *fb = gf100_fb(base);
+ struct nvkm_device *device = fb->base.subdev.device;
int ret, size = 0x1000;
size = nvkm_longopt(device->cfgopt, "MmuDebugBufferSize", size);
size = min(size, 0x1000);
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
- false, &fb->mmu_rd);
+ false, &fb->base.mmu_rd);
if (ret)
return ret;
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
- false, &fb->mmu_wr);
+ false, &fb->base.mmu_wr);
if (ret)
return ret;
+ fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (fb->r100c10_page) {
+ fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(device->dev, fb->r100c10))
+ return -EFAULT;
+ }
+
return 0;
}
@@ -123,14 +132,6 @@ gf100_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
nvkm_fb_ctor(func, device, index, &fb->base);
*pfb = &fb->base;
- fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (fb->r100c10_page) {
- fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(device->dev, fb->r100c10))
- return -EFAULT;
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
index 449f431644b3..412eb89834e8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
@@ -16,4 +16,8 @@ void gf100_fb_init(struct nvkm_fb *);
void gf100_fb_intr(struct nvkm_fb *);
void gp100_fb_init(struct nvkm_fb *);
+
+void gm200_fb_init_page(struct nvkm_fb *fb);
+void gm200_fb_init(struct nvkm_fb *base);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
index f815fe2bbf08..5d34d6136616 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -20,27 +20,21 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
+#include "gf100.h"
-#include <core/memory.h>
-
-static void
-gk20a_fb_init(struct nvkm_fb *fb)
-{
- struct nvkm_device *device = fb->subdev.device;
- nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->mmu_wr) >> 8);
- nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->mmu_rd) >> 8);
-}
-
+/* GK20A's FB is similar to GF100's, but without the ability to allocate VRAM */
static const struct nvkm_fb_func
gk20a_fb = {
+ .dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gk20a_fb_init,
+ .init = gf100_fb_init,
.init_page = gf100_fb_init_page,
+ .intr = gf100_fb_intr,
.memtype_valid = gf100_fb_memtype_valid,
};
int
gk20a_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
{
- return nvkm_fb_new_(&gk20a_fb, device, index, pfb);
+ return gf100_fb_new_(&gk20a_fb, device, index, pfb);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
index 62f653240be3..fe5886013ac0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
@@ -44,7 +44,7 @@ gm200_fb_init_page(struct nvkm_fb *fb)
}
}
-static void
+void
gm200_fb_init(struct nvkm_fb *base)
{
struct gf100_fb *fb = gf100_fb(base);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
new file mode 100644
index 000000000000..b87c233bcd6d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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 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 "priv.h"
+#include "gf100.h"
+
+/* GM20B's FB is similar to GM200, but without the ability to allocate VRAM */
+static const struct nvkm_fb_func
+gm20b_fb = {
+ .dtor = gf100_fb_dtor,
+ .oneinit = gf100_fb_oneinit,
+ .init = gm200_fb_init,
+ .init_page = gm200_fb_init_page,
+ .intr = gf100_fb_intr,
+ .memtype_valid = gf100_fb_memtype_valid,
+};
+
+int
+gm20b_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+ return gf100_fb_new_(&gm20b_fb, device, index, pfb);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
index 92cb71861bec..73b4ae1c73dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
@@ -27,7 +27,7 @@
#include <core/memory.h>
static const struct nvkm_fb_func
-gp104_fb = {
+gp102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
.init = gp100_fb_init,
@@ -37,7 +37,7 @@ gp104_fb = {
};
int
-gp104_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+gp102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
{
- return gf100_fb_new_(&gp104_fb, device, index, pfb);
+ return gf100_fb_new_(&gp102_fb, device, index, pfb);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
index 1b5fb02eab2a..0595e0722bfc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
@@ -210,6 +210,23 @@ nv50_fb_intr(struct nvkm_fb *base)
nvkm_fifo_chan_put(fifo, flags, &chan);
}
+static int
+nv50_fb_oneinit(struct nvkm_fb *base)
+{
+ struct nv50_fb *fb = nv50_fb(base);
+ struct nvkm_device *device = fb->base.subdev.device;
+
+ fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (fb->r100c08_page) {
+ fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(device->dev, fb->r100c08))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
static void
nv50_fb_init(struct nvkm_fb *base)
{
@@ -245,6 +262,7 @@ nv50_fb_dtor(struct nvkm_fb *base)
static const struct nvkm_fb_func
nv50_fb_ = {
.dtor = nv50_fb_dtor,
+ .oneinit = nv50_fb_oneinit,
.init = nv50_fb_init,
.intr = nv50_fb_intr,
.ram_new = nv50_fb_ram_new,
@@ -263,16 +281,6 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device,
fb->func = func;
*pfb = &fb->base;
- fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (fb->r100c08_page) {
- fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(device->dev, fb->r100c08))
- return -EFAULT;
- } else {
- nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n");
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
index b9ec0ae6723a..b60068b7d8f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
@@ -24,6 +24,7 @@ int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **);
+int gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32);
int gk104_ram_init(struct nvkm_ram *ram);
/* RAM type-specific MR calculation routines */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
index 772425ca5a9e..093223d1df4f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
@@ -420,8 +420,6 @@ gf100_ram_tidy(struct nvkm_ram *base)
ram_exec(&ram->fuc, false);
}
-extern const u8 gf100_pte_storage_type_map[256];
-
void
gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
index 1fa3ade468ae..7904fa41acef 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
@@ -259,7 +259,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq)
ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
ram_block(fuc);
- ram_wr32(fuc, 0x62c000, 0x0f0f0000);
+
+ if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+ ram_wr32(fuc, 0x62c000, 0x0f0f0000);
/* MR1: turn termination on early, for some reason.. */
if ((ram->base.mr[1] & 0x03c) != 0x030) {
@@ -658,7 +660,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq)
gk104_ram_train(fuc, 0x80020000, 0x01000000);
ram_unblock(fuc);
- ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
+
+ if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+ ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (next->bios.rammap_11_08_01)
data = 0x00000800;
@@ -706,7 +710,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
ram_block(fuc);
- ram_wr32(fuc, 0x62c000, 0x0f0f0000);
+
+ if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+ ram_wr32(fuc, 0x62c000, 0x0f0f0000);
if (vc == 1 && ram_have(fuc, gpio2E)) {
u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
@@ -936,7 +942,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_nsec(fuc, 1000);
ram_unblock(fuc);
- ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
+
+ if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+ ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (next->bios.rammap_11_08_01)
data = 0x00000800;
@@ -1530,6 +1538,12 @@ gk104_ram_func = {
int
gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
{
+ return gk104_ram_ctor(fb, pram, 0x022554);
+}
+
+int
+gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr)
+{
struct nvkm_subdev *subdev = &fb->subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_bios *bios = device->bios;
@@ -1544,7 +1558,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
return -ENOMEM;
*pram = &ram->base;
- ret = gf100_ram_ctor(&gk104_ram_func, fb, 0x022554, &ram->base);
+ ret = gf100_ram_ctor(&gk104_ram_func, fb, maskaddr, &ram->base);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
index 43d807f6ca71..ac862d1d77bd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
@@ -23,18 +23,8 @@
*/
#include "ram.h"
-static const struct nvkm_ram_func
-gm107_ram_func = {
- .init = gk104_ram_init,
- .get = gf100_ram_get,
- .put = gf100_ram_put,
-};
-
int
gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
{
- if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL)))
- return -ENOMEM;
-
- return gf100_ram_ctor(&gm107_ram_func, fb, 0x021c14, *pram);
+ return gk104_ram_ctor(fb, pram, 0x021c14);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
index f3be408b5e5e..405faabe8dcd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
@@ -92,13 +92,13 @@ gp100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
enum nvkm_ram_type type = nvkm_fb_bios_memtype(device->bios);
const u32 rsvd_head = ( 256 * 1024); /* vga memory */
const u32 rsvd_tail = (1024 * 1024); /* vbios etc */
- u32 fbpa_num = nvkm_rd32(device, 0x022438), fbpa;
+ u32 fbpa_num = nvkm_rd32(device, 0x02243c), fbpa;
u32 fbio_opt = nvkm_rd32(device, 0x021c14);
u64 part, size = 0, comm = ~0ULL;
bool mixed = false;
int ret;
- nvkm_debug(subdev, "022438: %08x\n", fbpa_num);
+ nvkm_debug(subdev, "02243c: %08x\n", fbpa_num);
nvkm_debug(subdev, "021c14: %08x\n", fbio_opt);
for (fbpa = 0; fbpa < fbpa_num; fbpa++) {
if (!(fbio_opt & (1 << fbpa))) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index d15ea886df27..f10664372161 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -95,7 +95,7 @@ struct gt215_ram {
struct gt215_ltrain ltrain;
};
-void
+static void
gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train)
{
int i, lo, hi;
@@ -149,7 +149,7 @@ gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train)
/*
* Link training for (at least) DDR3
*/
-int
+static int
gt215_link_train(struct gt215_ram *ram)
{
struct gt215_ltrain *train = &ram->ltrain;
@@ -267,7 +267,7 @@ out:
return ret;
}
-int
+static int
gt215_link_train_init(struct gt215_ram *ram)
{
static const u32 pattern[16] = {
@@ -333,7 +333,7 @@ gt215_link_train_init(struct gt215_ram *ram)
return 0;
}
-void
+static void
gt215_link_train_fini(struct gt215_ram *ram)
{
if (ram->ltrain.mem)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
index b9f1ffdfc602..4dcd8742f2da 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
@@ -23,6 +23,7 @@
* Ben Skeggs
*/
#include "priv.h"
+#include "ram.h"
struct ramxlat {
int id;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
index 26900333b1d6..eca8a445eab3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
@@ -23,6 +23,7 @@
* Roy Spliet <rspliet@eclipso.eu>
*/
#include "priv.h"
+#include "ram.h"
struct ramxlat {
int id;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c
index 3f45afd17d5a..2ead515b8530 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c
@@ -37,7 +37,7 @@ gk104_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo)
nvkm_wr32(device, 0x00dc80, intr1);
}
-void
+static void
gk104_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
{
struct nvkm_device *device = gpio->subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
index f0851d57df2f..01d5c5a56e2e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
@@ -74,7 +74,7 @@ nvkm_i2c_aux_i2c_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
-const struct i2c_algorithm
+static const struct i2c_algorithm
nvkm_i2c_aux_i2c_algo = {
.master_xfer = nvkm_i2c_aux_i2c_xfer,
.functionality = nvkm_i2c_aux_i2c_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
index 954f5b76bfcf..b80236a4eeac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
@@ -79,7 +79,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
struct g94_i2c_aux *aux = g94_i2c_aux(obj);
struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
const u32 base = aux->ch * 0x50;
- u32 ctrl, stat, timeout, retries;
+ u32 ctrl, stat, timeout, retries = 0;
u32 xbuf[4] = {};
int ret, i;
@@ -111,7 +111,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
nvkm_wr32(device, 0x00e4e0 + base, addr);
/* (maybe) retry transaction a number of times on failure... */
- for (retries = 0; !ret && retries < 32; retries++) {
+ do {
/* reset, and delay a while if this is a retry */
nvkm_wr32(device, 0x00e4e4 + base, 0x80000000 | ctrl);
nvkm_wr32(device, 0x00e4e4 + base, 0x00000000 | ctrl);
@@ -131,20 +131,20 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
goto out;
}
} while (ctrl & 0x00010000);
- ret = 1;
+ ret = 0;
/* read status, and check if transaction completed ok */
stat = nvkm_mask(device, 0x00e4e8 + base, 0, 0);
if ((stat & 0x000f0000) == 0x00080000 ||
(stat & 0x000f0000) == 0x00020000)
- ret = retry ? 0 : 1;
+ ret = 1;
if ((stat & 0x00000100))
ret = -ETIMEDOUT;
if ((stat & 0x00000e00))
ret = -EIO;
AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
- }
+ } while (ret && retry && retries++ < 32);
if (type & 1) {
for (i = 0; i < 16; i += 4) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
index 61d729b82c69..ed458c7f056b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
@@ -79,7 +79,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
const u32 base = aux->ch * 0x50;
- u32 ctrl, stat, timeout, retries;
+ u32 ctrl, stat, timeout, retries = 0;
u32 xbuf[4] = {};
int ret, i;
@@ -111,7 +111,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
nvkm_wr32(device, 0x00d950 + base, addr);
/* (maybe) retry transaction a number of times on failure... */
- for (retries = 0; !ret && retries < 32; retries++) {
+ do {
/* reset, and delay a while if this is a retry */
nvkm_wr32(device, 0x00d954 + base, 0x80000000 | ctrl);
nvkm_wr32(device, 0x00d954 + base, 0x00000000 | ctrl);
@@ -131,20 +131,20 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
goto out;
}
} while (ctrl & 0x00010000);
- ret = 1;
+ ret = 0;
/* read status, and check if transaction completed ok */
stat = nvkm_mask(device, 0x00d958 + base, 0, 0);
if ((stat & 0x000f0000) == 0x00080000 ||
(stat & 0x000f0000) == 0x00020000)
- ret = retry ? 0 : 1;
+ ret = 1;
if ((stat & 0x00000100))
ret = -ETIMEDOUT;
if ((stat & 0x00000e00))
ret = -EIO;
AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
- }
+ } while (ret && retry && retries++ < 32);
if (type & 1) {
for (i = 0; i < 16; i += 4) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
index b7159b338fac..1a4ab825852c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
@@ -29,7 +29,7 @@ gk20a_ibus_init_ibus_ring(struct nvkm_subdev *ibus)
nvkm_mask(device, 0x137250, 0x3f, 0);
nvkm_mask(device, 0x000200, 0x20, 0);
- usleep_range(20, 30);
+ udelay(20);
nvkm_mask(device, 0x000200, 0x20, 0x20);
nvkm_wr32(device, 0x12004c, 0x4);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
index 41bd5d0f7692..f0af2a381eea 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
@@ -96,60 +96,12 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense,
}
static void
-nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense,
- struct nvkm_iccsense_sensor *sensor)
-{
- struct nvkm_subdev *subdev = &iccsense->subdev;
- /* configuration:
- * 0x0007: 0x0007 shunt and bus continous
- * 0x0078: 0x0078 128 samples shunt
- * 0x0780: 0x0780 128 samples bus
- * 0x1800: 0x0000 +-40 mV shunt range
- * 0x2000: 0x0000 16V FSR
- */
- u16 value = 0x07ff;
- nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
- nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
-}
-
-static void
-nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense,
- struct nvkm_iccsense_sensor *sensor)
-{
- struct nvkm_subdev *subdev = &iccsense->subdev;
- /* configuration:
- * 0x0007: 0x0007 shunt and bus continous
- * 0x0031: 0x0000 140 us conversion time shunt
- * 0x01c0: 0x0000 140 us conversion time bus
- * 0x0f00: 0x0f00 1024 samples
- * 0x7000: 0x?000 channels
- */
- u16 value = 0x0e07;
- if (sensor->rail_mask & 0x1)
- value |= 0x1 << 14;
- if (sensor->rail_mask & 0x2)
- value |= 0x1 << 13;
- if (sensor->rail_mask & 0x4)
- value |= 0x1 << 12;
- nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
- nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
-}
-
-static void
nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense,
struct nvkm_iccsense_sensor *sensor)
{
- switch (sensor->type) {
- case NVBIOS_EXTDEV_INA209:
- case NVBIOS_EXTDEV_INA219:
- nvkm_iccsense_ina209_config(iccsense, sensor);
- break;
- case NVBIOS_EXTDEV_INA3221:
- nvkm_iccsense_ina3221_config(iccsense, sensor);
- break;
- default:
- break;
- }
+ struct nvkm_subdev *subdev = &iccsense->subdev;
+ nvkm_trace(subdev, "write config of extdev %i: 0x%04x\n", sensor->id, sensor->config);
+ nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, sensor->config);
}
int
@@ -196,7 +148,6 @@ nvkm_iccsense_dtor(struct nvkm_subdev *subdev)
static struct nvkm_iccsense_sensor*
nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
{
-
struct nvkm_subdev *subdev = &iccsense->subdev;
struct nvkm_bios *bios = subdev->device->bios;
struct nvkm_i2c *i2c = subdev->device->i2c;
@@ -245,7 +196,7 @@ nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
sensor->type = extdev.type;
sensor->i2c = &i2c_bus->i2c;
sensor->addr = addr;
- sensor->rail_mask = 0x0;
+ sensor->config = 0x0;
return sensor;
}
@@ -273,48 +224,56 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
iccsense->data_valid = true;
for (i = 0; i < stbl.nr_entry; ++i) {
- struct pwr_rail_t *r = &stbl.rail[i];
- struct nvkm_iccsense_rail *rail;
+ struct pwr_rail_t *pwr_rail = &stbl.rail[i];
struct nvkm_iccsense_sensor *sensor;
- int (*read)(struct nvkm_iccsense *,
- struct nvkm_iccsense_rail *);
+ int r;
- if (!r->mode || r->resistor_mohm == 0)
+ if (pwr_rail->mode != 1 || !pwr_rail->resistor_count)
continue;
- sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id);
+ sensor = nvkm_iccsense_get_sensor(iccsense, pwr_rail->extdev_id);
if (!sensor)
continue;
- switch (sensor->type) {
- case NVBIOS_EXTDEV_INA209:
- if (r->rail != 0)
- continue;
- read = nvkm_iccsense_ina209_read;
- break;
- case NVBIOS_EXTDEV_INA219:
- if (r->rail != 0)
+ if (!sensor->config)
+ sensor->config = pwr_rail->config;
+ else if (sensor->config != pwr_rail->config)
+ nvkm_error(subdev, "config mismatch found for extdev %i\n", pwr_rail->extdev_id);
+
+ for (r = 0; r < pwr_rail->resistor_count; ++r) {
+ struct nvkm_iccsense_rail *rail;
+ struct pwr_rail_resistor_t *res = &pwr_rail->resistors[r];
+ int (*read)(struct nvkm_iccsense *,
+ struct nvkm_iccsense_rail *);
+
+ if (!res->mohm || !res->enabled)
continue;
- read = nvkm_iccsense_ina219_read;
- break;
- case NVBIOS_EXTDEV_INA3221:
- if (r->rail >= 3)
+
+ switch (sensor->type) {
+ case NVBIOS_EXTDEV_INA209:
+ read = nvkm_iccsense_ina209_read;
+ break;
+ case NVBIOS_EXTDEV_INA219:
+ read = nvkm_iccsense_ina219_read;
+ break;
+ case NVBIOS_EXTDEV_INA3221:
+ read = nvkm_iccsense_ina3221_read;
+ break;
+ default:
continue;
- read = nvkm_iccsense_ina3221_read;
- break;
- default:
- continue;
+ }
+
+ rail = kmalloc(sizeof(*rail), GFP_KERNEL);
+ if (!rail)
+ return -ENOMEM;
+
+ rail->read = read;
+ rail->sensor = sensor;
+ rail->idx = r;
+ rail->mohm = res->mohm;
+ nvkm_debug(subdev, "create rail for extdev %i: { idx: %i, mohm: %i }\n", pwr_rail->extdev_id, r, rail->mohm);
+ list_add_tail(&rail->head, &iccsense->rails);
}
-
- rail = kmalloc(sizeof(*rail), GFP_KERNEL);
- if (!rail)
- return -ENOMEM;
- sensor->rail_mask |= 1 << r->rail;
- rail->read = read;
- rail->sensor = sensor;
- rail->idx = r->rail;
- rail->mohm = r->resistor_mohm;
- list_add_tail(&rail->head, &iccsense->rails);
}
return 0;
}
@@ -329,7 +288,8 @@ nvkm_iccsense_init(struct nvkm_subdev *subdev)
return 0;
}
-struct nvkm_subdev_func iccsense_func = {
+static const struct nvkm_subdev_func
+iccsense_func = {
.oneinit = nvkm_iccsense_oneinit,
.init = nvkm_iccsense_init,
.dtor = nvkm_iccsense_dtor,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
index b72c31d2f908..e90e0f6ed008 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
@@ -10,7 +10,7 @@ struct nvkm_iccsense_sensor {
enum nvbios_extdev_type type;
struct i2c_adapter *i2c;
u8 addr;
- u8 rail_mask;
+ u16 config;
};
struct nvkm_iccsense_rail {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index 8ed8f65ff664..10c987a654ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -104,7 +104,7 @@ nvkm_instobj_dtor(struct nvkm_memory *memory)
return iobj;
}
-const struct nvkm_memory_func
+static const struct nvkm_memory_func
nvkm_instobj_func = {
.dtor = nvkm_instobj_dtor,
.target = nvkm_instobj_target,
@@ -156,7 +156,7 @@ nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data)
return nvkm_wo32(iobj->parent, offset, data);
}
-const struct nvkm_memory_func
+static const struct nvkm_memory_func
nvkm_instobj_func_slow = {
.dtor = nvkm_instobj_dtor,
.target = nvkm_instobj_target,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
index 39c2a38e54f7..0c7ef250dcaf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
@@ -47,8 +47,10 @@ nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count)
BUG_ON((first > limit) || (limit >= ltc->num_tags));
+ mutex_lock(&ltc->subdev.mutex);
ltc->func->cbc_clear(ltc, first, limit);
ltc->func->cbc_wait(ltc);
+ mutex_unlock(&ltc->subdev.mutex);
}
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
index c3d66ef5dc12..430a61c3df44 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
@@ -34,7 +34,7 @@ g84_mc_reset[] = {
{}
};
-const struct nvkm_mc_map
+static const struct nvkm_mc_map
g84_mc_intr[] = {
{ 0x04000000, NVKM_ENGINE_DISP },
{ 0x00020000, NVKM_ENGINE_VP },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
index 21b65ee254e4..e3e2f5e83815 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
@@ -250,6 +250,10 @@ nvkm_mxm_new_(struct nvkm_device *device, int index, struct nvkm_mxm **pmxm)
}
nvkm_info(&mxm->subdev, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f);
+ nvkm_debug(&mxm->subdev, "module flags: %02x\n",
+ nvbios_rd08(bios, data + 0x01));
+ nvkm_debug(&mxm->subdev, "config flags: %02x\n",
+ nvbios_rd08(bios, data + 0x02));
if (mxm_shadow(mxm, ver)) {
nvkm_warn(&mxm->subdev, "failed to locate valid SIS\n");
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
index 45a2f8e784f9..9abfa5e2fe9f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
@@ -23,8 +23,8 @@
*/
#include "mxms.h"
-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
+#define ROM16(x) get_unaligned_le16(&(x))
+#define ROM32(x) get_unaligned_le32(&(x))
static u8 *
mxms_data(struct nvkm_mxm *mxm)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c
index db14fad2ddfc..844971e5e874 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c
@@ -190,8 +190,8 @@ mxm_dcb_sanitise(struct nvkm_mxm *mxm)
struct nvkm_bios *bios = subdev->device->bios;
u8 ver, hdr, cnt, len;
u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len);
- if (dcb == 0x0000 || ver != 0x40) {
- nvkm_debug(subdev, "unsupported DCB version\n");
+ if (dcb == 0x0000 || (ver != 0x40 && ver != 0x41)) {
+ nvkm_warn(subdev, "unsupported DCB version\n");
return;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
index 88b643b8664e..51fb4bf94a44 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
@@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/pmu/gk110.o
nvkm-y += nvkm/subdev/pmu/gk208.o
nvkm-y += nvkm/subdev/pmu/gk20a.o
nvkm-y += nvkm/subdev/pmu/gm107.o
+nvkm-y += nvkm/subdev/pmu/gp100.o
+nvkm-y += nvkm/subdev/pmu/gp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 8dd164d13043..e611ce80f8ef 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -32,225 +32,85 @@ nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
pmu->func->pgob(pmu, enable);
}
-int
-nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
- u32 process, u32 message, u32 data0, u32 data1)
-{
- struct nvkm_subdev *subdev = &pmu->subdev;
- struct nvkm_device *device = subdev->device;
- u32 addr;
-
- mutex_lock(&subdev->mutex);
- /* wait for a free slot in the fifo */
- addr = nvkm_rd32(device, 0x10a4a0);
- if (nvkm_msec(device, 2000,
- u32 tmp = nvkm_rd32(device, 0x10a4b0);
- if (tmp != (addr ^ 8))
- break;
- ) < 0) {
- mutex_unlock(&subdev->mutex);
- return -EBUSY;
- }
-
- /* we currently only support a single process at a time waiting
- * on a synchronous reply, take the PMU mutex and tell the
- * receive handler what we're waiting for
- */
- if (reply) {
- pmu->recv.message = message;
- pmu->recv.process = process;
- }
-
- /* acquire data segment access */
- do {
- nvkm_wr32(device, 0x10a580, 0x00000001);
- } while (nvkm_rd32(device, 0x10a580) != 0x00000001);
-
- /* write the packet */
- nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
- pmu->send.base));
- nvkm_wr32(device, 0x10a1c4, process);
- nvkm_wr32(device, 0x10a1c4, message);
- nvkm_wr32(device, 0x10a1c4, data0);
- nvkm_wr32(device, 0x10a1c4, data1);
- nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
-
- /* release data segment access */
- nvkm_wr32(device, 0x10a580, 0x00000000);
-
- /* wait for reply, if requested */
- if (reply) {
- wait_event(pmu->recv.wait, (pmu->recv.process == 0));
- reply[0] = pmu->recv.data[0];
- reply[1] = pmu->recv.data[1];
- }
-
- mutex_unlock(&subdev->mutex);
- return 0;
-}
-
static void
nvkm_pmu_recv(struct work_struct *work)
{
- struct nvkm_pmu *pmu = container_of(work, struct nvkm_pmu, recv.work);
- struct nvkm_subdev *subdev = &pmu->subdev;
- struct nvkm_device *device = subdev->device;
- u32 process, message, data0, data1;
-
- /* nothing to do if GET == PUT */
- u32 addr = nvkm_rd32(device, 0x10a4cc);
- if (addr == nvkm_rd32(device, 0x10a4c8))
- return;
-
- /* acquire data segment access */
- do {
- nvkm_wr32(device, 0x10a580, 0x00000002);
- } while (nvkm_rd32(device, 0x10a580) != 0x00000002);
-
- /* read the packet */
- nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
- pmu->recv.base));
- process = nvkm_rd32(device, 0x10a1c4);
- message = nvkm_rd32(device, 0x10a1c4);
- data0 = nvkm_rd32(device, 0x10a1c4);
- data1 = nvkm_rd32(device, 0x10a1c4);
- nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
-
- /* release data segment access */
- nvkm_wr32(device, 0x10a580, 0x00000000);
-
- /* wake process if it's waiting on a synchronous reply */
- if (pmu->recv.process) {
- if (process == pmu->recv.process &&
- message == pmu->recv.message) {
- pmu->recv.data[0] = data0;
- pmu->recv.data[1] = data1;
- pmu->recv.process = 0;
- wake_up(&pmu->recv.wait);
- return;
- }
- }
+ struct nvkm_pmu *pmu = container_of(work, typeof(*pmu), recv.work);
+ return pmu->func->recv(pmu);
+}
- /* right now there's no other expected responses from the engine,
- * so assume that any unexpected message is an error.
- */
- nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n",
- (char)((process & 0x000000ff) >> 0),
- (char)((process & 0x0000ff00) >> 8),
- (char)((process & 0x00ff0000) >> 16),
- (char)((process & 0xff000000) >> 24),
- process, message, data0, data1);
+int
+nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
+ u32 process, u32 message, u32 data0, u32 data1)
+{
+ if (!pmu || !pmu->func->send)
+ return -ENODEV;
+ return pmu->func->send(pmu, reply, process, message, data0, data1);
}
static void
nvkm_pmu_intr(struct nvkm_subdev *subdev)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
- struct nvkm_device *device = pmu->subdev.device;
- u32 disp = nvkm_rd32(device, 0x10a01c);
- u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16);
-
- if (intr & 0x00000020) {
- u32 stat = nvkm_rd32(device, 0x10a16c);
- if (stat & 0x80000000) {
- nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
- stat & 0x00ffffff,
- nvkm_rd32(device, 0x10a168));
- nvkm_wr32(device, 0x10a16c, 0x00000000);
- intr &= ~0x00000020;
- }
- }
-
- if (intr & 0x00000040) {
- schedule_work(&pmu->recv.work);
- nvkm_wr32(device, 0x10a004, 0x00000040);
- intr &= ~0x00000040;
- }
-
- if (intr & 0x00000080) {
- nvkm_info(subdev, "wr32 %06x %08x\n",
- nvkm_rd32(device, 0x10a7a0),
- nvkm_rd32(device, 0x10a7a4));
- nvkm_wr32(device, 0x10a004, 0x00000080);
- intr &= ~0x00000080;
- }
-
- if (intr) {
- nvkm_error(subdev, "intr %08x\n", intr);
- nvkm_wr32(device, 0x10a004, intr);
- }
+ if (!pmu->func->intr)
+ return;
+ pmu->func->intr(pmu);
}
static int
nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
- struct nvkm_device *device = pmu->subdev.device;
- nvkm_wr32(device, 0x10a014, 0x00000060);
+ if (pmu->func->fini)
+ pmu->func->fini(pmu);
+
flush_work(&pmu->recv.work);
return 0;
}
static int
-nvkm_pmu_init(struct nvkm_subdev *subdev)
+nvkm_pmu_reset(struct nvkm_pmu *pmu)
{
- struct nvkm_pmu *pmu = nvkm_pmu(subdev);
struct nvkm_device *device = pmu->subdev.device;
- int i;
- /* prevent previous ucode from running, wait for idle, reset */
- nvkm_wr32(device, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */
+ if (!(nvkm_rd32(device, 0x000200) & 0x00002000))
+ return 0;
+
+ /* Inhibit interrupts, and wait for idle. */
+ nvkm_wr32(device, 0x10a014, 0x0000ffff);
nvkm_msec(device, 2000,
if (!nvkm_rd32(device, 0x10a04c))
break;
);
- nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
- nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
- nvkm_rd32(device, 0x000200);
+
+ /* Reset. */
+ pmu->func->reset(pmu);
+
+ /* Wait for IMEM/DMEM scrubbing to be complete. */
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
break;
);
- /* upload data segment */
- nvkm_wr32(device, 0x10a1c0, 0x01000000);
- for (i = 0; i < pmu->func->data.size / 4; i++)
- nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
-
- /* upload code segment */
- nvkm_wr32(device, 0x10a180, 0x01000000);
- for (i = 0; i < pmu->func->code.size / 4; i++) {
- if ((i & 0x3f) == 0)
- nvkm_wr32(device, 0x10a188, i >> 6);
- nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
- }
-
- /* start it running */
- nvkm_wr32(device, 0x10a10c, 0x00000000);
- nvkm_wr32(device, 0x10a104, 0x00000000);
- nvkm_wr32(device, 0x10a100, 0x00000002);
-
- /* wait for valid host->pmu ring configuration */
- if (nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x10a4d0))
- break;
- ) < 0)
- return -EBUSY;
- pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
- pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
+ return 0;
+}
- /* wait for valid pmu->host ring configuration */
- if (nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x10a4dc))
- break;
- ) < 0)
- return -EBUSY;
- pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
- pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
+static int
+nvkm_pmu_preinit(struct nvkm_subdev *subdev)
+{
+ struct nvkm_pmu *pmu = nvkm_pmu(subdev);
+ return nvkm_pmu_reset(pmu);
+}
- nvkm_wr32(device, 0x10a010, 0x000000e0);
- return 0;
+static int
+nvkm_pmu_init(struct nvkm_subdev *subdev)
+{
+ struct nvkm_pmu *pmu = nvkm_pmu(subdev);
+ int ret = nvkm_pmu_reset(pmu);
+ if (ret == 0 && pmu->func->init)
+ ret = pmu->func->init(pmu);
+ return ret;
}
static void *
@@ -262,6 +122,7 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev)
static const struct nvkm_subdev_func
nvkm_pmu = {
.dtor = nvkm_pmu_dtor,
+ .preinit = nvkm_pmu_preinit,
.init = nvkm_pmu_init,
.fini = nvkm_pmu_fini,
.intr = nvkm_pmu_intr,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
index e2faccffee6f..0bcf0b307a61 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gf100_pmu_data[] = {
+static uint32_t gf100_pmu_data[] = {
/* 0x0000: proc_kern */
0x52544e49,
0x00000000,
@@ -916,7 +916,7 @@ uint32_t gf100_pmu_data[] = {
0x00000000,
};
-uint32_t gf100_pmu_code[] = {
+static uint32_t gf100_pmu_code[] = {
0x03920ef5,
/* 0x0004: rd32 */
0x07a007f1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
index 2d5bdc539697..fe8905666c67 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
@@ -1,4 +1,4 @@
-uint32_t gf119_pmu_data[] = {
+static uint32_t gf119_pmu_data[] = {
/* 0x0000: proc_kern */
0x52544e49,
0x00000000,
@@ -915,7 +915,7 @@ uint32_t gf119_pmu_data[] = {
0x00000000,
};
-uint32_t gf119_pmu_code[] = {
+static uint32_t gf119_pmu_code[] = {
0x03410ef5,
/* 0x0004: rd32 */
0x07a007f1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
index 3c731ff12871..9cf4e6fc724e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
@@ -1,4 +1,4 @@
-uint32_t gk208_pmu_data[] = {
+static uint32_t gk208_pmu_data[] = {
/* 0x0000: proc_kern */
0x52544e49,
0x00000000,
@@ -915,7 +915,7 @@ uint32_t gk208_pmu_data[] = {
0x00000000,
};
-uint32_t gk208_pmu_code[] = {
+static uint32_t gk208_pmu_code[] = {
0x02f90ef5,
/* 0x0004: rd32 */
0xf607a040,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
index e83341815ec6..5d692425b190 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
@@ -1,4 +1,4 @@
-uint32_t gt215_pmu_data[] = {
+static uint32_t gt215_pmu_data[] = {
/* 0x0000: proc_kern */
0x52544e49,
0x00000000,
@@ -916,7 +916,7 @@ uint32_t gt215_pmu_data[] = {
0x00000000,
};
-uint32_t gt215_pmu_code[] = {
+static uint32_t gt215_pmu_code[] = {
0x03920ef5,
/* 0x0004: rd32 */
0x07a007f1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
index aeb8ccd891fc..0e36d4cb7201 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
@@ -30,6 +30,12 @@ gf100_pmu = {
.code.size = sizeof(gf100_pmu_code),
.data.data = gf100_pmu_data,
.data.size = sizeof(gf100_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
index fbc88d8ecd4d..0e4ba4248b15 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
@@ -30,6 +30,12 @@ gf119_pmu = {
.code.size = sizeof(gf119_pmu_code),
.data.data = gf119_pmu_data,
.data.size = sizeof(gf119_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
index 86f9f3b13f71..2ad858d825ac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
@@ -109,6 +109,12 @@ gk104_pmu = {
.code.size = sizeof(gk104_pmu_code),
.data.data = gk104_pmu_data,
.data.size = sizeof(gk104_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
.pgob = gk104_pmu_pgob,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
index ae255247c9d1..fc4b8ecfdaeb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
@@ -88,6 +88,12 @@ gk110_pmu = {
.code.size = sizeof(gk110_pmu_code),
.data.data = gk110_pmu_data,
.data.size = sizeof(gk110_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
.pgob = gk110_pmu_pgob,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
index 3b4917637902..e9a91277683a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
@@ -30,6 +30,12 @@ gk208_pmu = {
.code.size = sizeof(gk208_pmu_code),
.data.data = gk208_pmu_data,
.data.size = sizeof(gk208_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
.pgob = gk110_pmu_pgob,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
index 31b8692b4641..9a248ed75f09 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
@@ -32,6 +32,12 @@ gm107_pmu = {
.code.size = sizeof(gm107_pmu_code),
.data.data = gm107_pmu_data,
.data.size = sizeof(gm107_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c
new file mode 100644
index 000000000000..6c41c20c85a7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 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_pmu_func
+gp100_pmu = {
+ .reset = gt215_pmu_reset,
+};
+
+int
+gp100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
+{
+ return nvkm_pmu_new_(&gp100_pmu, device, index, ppmu);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
new file mode 100644
index 000000000000..f017352206c9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 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 void
+gp102_pmu_reset(struct nvkm_pmu *pmu)
+{
+ struct nvkm_device *device = pmu->subdev.device;
+ nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001);
+ nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000);
+}
+
+static const struct nvkm_pmu_func
+gp102_pmu = {
+ .reset = gp102_pmu_reset,
+};
+
+int
+gp102_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
+{
+ return nvkm_pmu_new_(&gp102_pmu, device, index, ppmu);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
index 8ba7fa4ca75b..90d428b3be97 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
@@ -24,21 +24,229 @@
#include "priv.h"
#include "fuc/gt215.fuc3.h"
-static void
+#include <subdev/timer.h>
+
+int
+gt215_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
+ u32 process, u32 message, u32 data0, u32 data1)
+{
+ struct nvkm_subdev *subdev = &pmu->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 addr;
+
+ mutex_lock(&subdev->mutex);
+ /* wait for a free slot in the fifo */
+ addr = nvkm_rd32(device, 0x10a4a0);
+ if (nvkm_msec(device, 2000,
+ u32 tmp = nvkm_rd32(device, 0x10a4b0);
+ if (tmp != (addr ^ 8))
+ break;
+ ) < 0) {
+ mutex_unlock(&subdev->mutex);
+ return -EBUSY;
+ }
+
+ /* we currently only support a single process at a time waiting
+ * on a synchronous reply, take the PMU mutex and tell the
+ * receive handler what we're waiting for
+ */
+ if (reply) {
+ pmu->recv.message = message;
+ pmu->recv.process = process;
+ }
+
+ /* acquire data segment access */
+ do {
+ nvkm_wr32(device, 0x10a580, 0x00000001);
+ } while (nvkm_rd32(device, 0x10a580) != 0x00000001);
+
+ /* write the packet */
+ nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
+ pmu->send.base));
+ nvkm_wr32(device, 0x10a1c4, process);
+ nvkm_wr32(device, 0x10a1c4, message);
+ nvkm_wr32(device, 0x10a1c4, data0);
+ nvkm_wr32(device, 0x10a1c4, data1);
+ nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
+
+ /* release data segment access */
+ nvkm_wr32(device, 0x10a580, 0x00000000);
+
+ /* wait for reply, if requested */
+ if (reply) {
+ wait_event(pmu->recv.wait, (pmu->recv.process == 0));
+ reply[0] = pmu->recv.data[0];
+ reply[1] = pmu->recv.data[1];
+ }
+
+ mutex_unlock(&subdev->mutex);
+ return 0;
+}
+
+void
+gt215_pmu_recv(struct nvkm_pmu *pmu)
+{
+ struct nvkm_subdev *subdev = &pmu->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 process, message, data0, data1;
+
+ /* nothing to do if GET == PUT */
+ u32 addr = nvkm_rd32(device, 0x10a4cc);
+ if (addr == nvkm_rd32(device, 0x10a4c8))
+ return;
+
+ /* acquire data segment access */
+ do {
+ nvkm_wr32(device, 0x10a580, 0x00000002);
+ } while (nvkm_rd32(device, 0x10a580) != 0x00000002);
+
+ /* read the packet */
+ nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
+ pmu->recv.base));
+ process = nvkm_rd32(device, 0x10a1c4);
+ message = nvkm_rd32(device, 0x10a1c4);
+ data0 = nvkm_rd32(device, 0x10a1c4);
+ data1 = nvkm_rd32(device, 0x10a1c4);
+ nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
+
+ /* release data segment access */
+ nvkm_wr32(device, 0x10a580, 0x00000000);
+
+ /* wake process if it's waiting on a synchronous reply */
+ if (pmu->recv.process) {
+ if (process == pmu->recv.process &&
+ message == pmu->recv.message) {
+ pmu->recv.data[0] = data0;
+ pmu->recv.data[1] = data1;
+ pmu->recv.process = 0;
+ wake_up(&pmu->recv.wait);
+ return;
+ }
+ }
+
+ /* right now there's no other expected responses from the engine,
+ * so assume that any unexpected message is an error.
+ */
+ nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n",
+ (char)((process & 0x000000ff) >> 0),
+ (char)((process & 0x0000ff00) >> 8),
+ (char)((process & 0x00ff0000) >> 16),
+ (char)((process & 0xff000000) >> 24),
+ process, message, data0, data1);
+}
+
+void
+gt215_pmu_intr(struct nvkm_pmu *pmu)
+{
+ struct nvkm_subdev *subdev = &pmu->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 disp = nvkm_rd32(device, 0x10a01c);
+ u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16);
+
+ if (intr & 0x00000020) {
+ u32 stat = nvkm_rd32(device, 0x10a16c);
+ if (stat & 0x80000000) {
+ nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
+ stat & 0x00ffffff,
+ nvkm_rd32(device, 0x10a168));
+ nvkm_wr32(device, 0x10a16c, 0x00000000);
+ intr &= ~0x00000020;
+ }
+ }
+
+ if (intr & 0x00000040) {
+ schedule_work(&pmu->recv.work);
+ nvkm_wr32(device, 0x10a004, 0x00000040);
+ intr &= ~0x00000040;
+ }
+
+ if (intr & 0x00000080) {
+ nvkm_info(subdev, "wr32 %06x %08x\n",
+ nvkm_rd32(device, 0x10a7a0),
+ nvkm_rd32(device, 0x10a7a4));
+ nvkm_wr32(device, 0x10a004, 0x00000080);
+ intr &= ~0x00000080;
+ }
+
+ if (intr) {
+ nvkm_error(subdev, "intr %08x\n", intr);
+ nvkm_wr32(device, 0x10a004, intr);
+ }
+}
+
+void
+gt215_pmu_fini(struct nvkm_pmu *pmu)
+{
+ nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
+}
+
+void
gt215_pmu_reset(struct nvkm_pmu *pmu)
{
struct nvkm_device *device = pmu->subdev.device;
- nvkm_mask(device, 0x022210, 0x00000001, 0x00000000);
- nvkm_mask(device, 0x022210, 0x00000001, 0x00000001);
+ nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
+ nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
+ nvkm_rd32(device, 0x000200);
+}
+
+int
+gt215_pmu_init(struct nvkm_pmu *pmu)
+{
+ struct nvkm_device *device = pmu->subdev.device;
+ int i;
+
+ /* upload data segment */
+ nvkm_wr32(device, 0x10a1c0, 0x01000000);
+ for (i = 0; i < pmu->func->data.size / 4; i++)
+ nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
+
+ /* upload code segment */
+ nvkm_wr32(device, 0x10a180, 0x01000000);
+ for (i = 0; i < pmu->func->code.size / 4; i++) {
+ if ((i & 0x3f) == 0)
+ nvkm_wr32(device, 0x10a188, i >> 6);
+ nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
+ }
+
+ /* start it running */
+ nvkm_wr32(device, 0x10a10c, 0x00000000);
+ nvkm_wr32(device, 0x10a104, 0x00000000);
+ nvkm_wr32(device, 0x10a100, 0x00000002);
+
+ /* wait for valid host->pmu ring configuration */
+ if (nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x10a4d0))
+ break;
+ ) < 0)
+ return -EBUSY;
+ pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
+ pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
+
+ /* wait for valid pmu->host ring configuration */
+ if (nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x10a4dc))
+ break;
+ ) < 0)
+ return -EBUSY;
+ pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
+ pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
+
+ nvkm_wr32(device, 0x10a010, 0x000000e0);
+ return 0;
}
static const struct nvkm_pmu_func
gt215_pmu = {
- .reset = gt215_pmu_reset,
.code.data = gt215_pmu_code,
.code.size = sizeof(gt215_pmu_code),
.data.data = gt215_pmu_data,
.data.size = sizeof(gt215_pmu_data),
+ .reset = gt215_pmu_reset,
+ .init = gt215_pmu_init,
+ .fini = gt215_pmu_fini,
+ .intr = gt215_pmu_intr,
+ .send = gt215_pmu_send,
+ .recv = gt215_pmu_recv,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index f38c88fae3d6..2e2179a4ad17 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -8,8 +8,6 @@ int nvkm_pmu_new_(const struct nvkm_pmu_func *, struct nvkm_device *,
int index, struct nvkm_pmu **);
struct nvkm_pmu_func {
- void (*reset)(struct nvkm_pmu *);
-
struct {
u32 *data;
u32 size;
@@ -20,8 +18,22 @@ struct nvkm_pmu_func {
u32 size;
} data;
+ void (*reset)(struct nvkm_pmu *);
+ int (*init)(struct nvkm_pmu *);
+ void (*fini)(struct nvkm_pmu *);
+ void (*intr)(struct nvkm_pmu *);
+ int (*send)(struct nvkm_pmu *, u32 reply[2], u32 process,
+ u32 message, u32 data0, u32 data1);
+ void (*recv)(struct nvkm_pmu *);
void (*pgob)(struct nvkm_pmu *, bool);
};
+void gt215_pmu_reset(struct nvkm_pmu *);
+int gt215_pmu_init(struct nvkm_pmu *);
+void gt215_pmu_fini(struct nvkm_pmu *);
+void gt215_pmu_intr(struct nvkm_pmu *);
+void gt215_pmu_recv(struct nvkm_pmu *);
+int gt215_pmu_send(struct nvkm_pmu *, u32[2], u32, u32, u32, u32);
+
void gk110_pmu_pgob(struct nvkm_pmu *, bool);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
index f1e2dc914366..ec48e4ace37a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
@@ -1364,7 +1364,7 @@ gm200_secboot_init(struct nvkm_secboot *sb)
return 0;
}
-int
+static int
gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend)
{
struct gm200_secboot *gsb = gm200_secboot(sb);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
index c34076223b7b..bcd179ba11d0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
@@ -1,6 +1,7 @@
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/gf100.o
nvkm-y += nvkm/subdev/volt/gk104.o
nvkm-y += nvkm/subdev/volt/gk20a.o
nvkm-y += nvkm/subdev/volt/gm20b.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
index 1c3d23b0e84a..e344901cfdc7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
@@ -26,6 +26,7 @@
#include <subdev/bios.h>
#include <subdev/bios/vmap.h>
#include <subdev/bios/volt.h>
+#include <subdev/therm.h>
int
nvkm_volt_get(struct nvkm_volt *volt)
@@ -50,33 +51,45 @@ static int
nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
{
struct nvkm_subdev *subdev = &volt->subdev;
- int i, ret = -EINVAL;
+ int i, ret = -EINVAL, best_err = volt->max_uv, best = -1;
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);
- nvkm_debug(subdev, "set %duv: %d\n", uv, ret);
+ int err = volt->vid[i].uv - uv;
+ if (err < 0 || err > best_err)
+ continue;
+
+ best_err = err;
+ best = i;
+ if (best_err == 0)
break;
- }
}
+
+ if (best == -1) {
+ nvkm_error(subdev, "couldn't set %iuv\n", uv);
+ return ret;
+ }
+
+ ret = volt->func->vid_set(volt, volt->vid[best].vid);
+ nvkm_debug(subdev, "set req %duv to %duv: %d\n", uv,
+ volt->vid[best].uv, ret);
return ret;
}
-static int
-nvkm_volt_map(struct nvkm_volt *volt, u8 id)
+int
+nvkm_volt_map_min(struct nvkm_volt *volt, u8 id)
{
struct nvkm_bios *bios = volt->subdev.device->bios;
struct nvbios_vmap_entry info;
u8 ver, len;
- u16 vmap;
+ u32 vmap;
vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
if (vmap) {
if (info.link != 0xff) {
- int ret = nvkm_volt_map(volt, info.link);
+ int ret = nvkm_volt_map_min(volt, info.link);
if (ret < 0)
return ret;
info.min += ret;
@@ -88,19 +101,79 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id)
}
int
-nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition)
+nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp)
+{
+ struct nvkm_bios *bios = volt->subdev.device->bios;
+ struct nvbios_vmap_entry info;
+ u8 ver, len;
+ u32 vmap;
+
+ vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
+ if (vmap) {
+ s64 result;
+
+ if (volt->speedo < 0)
+ return volt->speedo;
+
+ if (ver == 0x10 || (ver == 0x20 && info.mode == 0)) {
+ result = div64_s64((s64)info.arg[0], 10);
+ result += div64_s64((s64)info.arg[1] * volt->speedo, 10);
+ result += div64_s64((s64)info.arg[2] * volt->speedo * volt->speedo, 100000);
+ } else if (ver == 0x20) {
+ switch (info.mode) {
+ /* 0x0 handled above! */
+ case 0x1:
+ result = ((s64)info.arg[0] * 15625) >> 18;
+ result += ((s64)info.arg[1] * volt->speedo * 15625) >> 18;
+ result += ((s64)info.arg[2] * temp * 15625) >> 10;
+ result += ((s64)info.arg[3] * volt->speedo * temp * 15625) >> 18;
+ result += ((s64)info.arg[4] * volt->speedo * volt->speedo * 15625) >> 30;
+ result += ((s64)info.arg[5] * temp * temp * 15625) >> 18;
+ break;
+ case 0x3:
+ result = (info.min + info.max) / 2;
+ break;
+ case 0x2:
+ default:
+ result = info.min;
+ break;
+ }
+ } else {
+ return -ENODEV;
+ }
+
+ result = min(max(result, (s64)info.min), (s64)info.max);
+
+ if (info.link != 0xff) {
+ int ret = nvkm_volt_map(volt, info.link, temp);
+ if (ret < 0)
+ return ret;
+ result += ret;
+ }
+ return result;
+ }
+
+ return id ? id * 10000 : -ENODEV;
+}
+
+int
+nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, u8 min_id, u8 temp,
+ int condition)
{
int ret;
if (volt->func->set_id)
return volt->func->set_id(volt, id, condition);
- ret = nvkm_volt_map(volt, id);
+ ret = nvkm_volt_map(volt, id, temp);
if (ret >= 0) {
int prev = nvkm_volt_get(volt);
if (!condition || prev < 0 ||
(condition < 0 && ret < prev) ||
(condition > 0 && ret > prev)) {
+ int min = nvkm_volt_map(volt, min_id, temp);
+ if (min >= 0)
+ ret = max(min, ret);
ret = nvkm_volt_set(volt, ret);
} else {
ret = 0;
@@ -112,14 +185,16 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition)
static void
nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
{
+ struct nvkm_subdev *subdev = &bios->subdev;
struct nvbios_volt_entry ivid;
struct nvbios_volt info;
u8 ver, hdr, cnt, len;
- u16 data;
+ u32 data;
int i;
data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info);
- if (data && info.vidmask && info.base && info.step) {
+ if (data && info.vidmask && info.base && info.step && info.ranged) {
+ nvkm_debug(subdev, "found ranged based VIDs\n");
volt->min_uv = info.min;
volt->max_uv = info.max;
for (i = 0; i < info.vidmask + 1; i++) {
@@ -132,7 +207,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
info.base += info.step;
}
volt->vid_mask = info.vidmask;
- } else if (data && info.vidmask) {
+ } else if (data && info.vidmask && !info.ranged) {
+ nvkm_debug(subdev, "found entry based VIDs\n");
volt->min_uv = 0xffffffff;
volt->max_uv = 0;
for (i = 0; i < cnt; i++) {
@@ -154,6 +230,14 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
}
static int
+nvkm_volt_speedo_read(struct nvkm_volt *volt)
+{
+ if (volt->func->speedo_read)
+ return volt->func->speedo_read(volt);
+ return -EINVAL;
+}
+
+static int
nvkm_volt_init(struct nvkm_subdev *subdev)
{
struct nvkm_volt *volt = nvkm_volt(subdev);
@@ -167,6 +251,21 @@ nvkm_volt_init(struct nvkm_subdev *subdev)
return 0;
}
+static int
+nvkm_volt_oneinit(struct nvkm_subdev *subdev)
+{
+ struct nvkm_volt *volt = nvkm_volt(subdev);
+
+ volt->speedo = nvkm_volt_speedo_read(volt);
+ if (volt->speedo > 0)
+ nvkm_debug(&volt->subdev, "speedo %x\n", volt->speedo);
+
+ if (volt->func->oneinit)
+ return volt->func->oneinit(volt);
+
+ return 0;
+}
+
static void *
nvkm_volt_dtor(struct nvkm_subdev *subdev)
{
@@ -177,6 +276,7 @@ static const struct nvkm_subdev_func
nvkm_volt = {
.dtor = nvkm_volt_dtor,
.init = nvkm_volt_init,
+ .oneinit = nvkm_volt_oneinit,
};
void
@@ -191,9 +291,22 @@ nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device,
/* Assuming the non-bios device should build the voltage table later */
if (bios) {
+ u8 ver, hdr, cnt, len;
+ struct nvbios_vmap vmap;
+
nvkm_volt_parse_bios(bios, volt);
nvkm_debug(&volt->subdev, "min: %iuv max: %iuv\n",
volt->min_uv, volt->max_uv);
+
+ if (nvbios_vmap_parse(bios, &ver, &hdr, &cnt, &len, &vmap)) {
+ volt->max0_id = vmap.max0;
+ volt->max1_id = vmap.max1;
+ volt->max2_id = vmap.max2;
+ } else {
+ volt->max0_id = 0xff;
+ volt->max1_id = 0xff;
+ volt->max2_id = 0xff;
+ }
}
if (volt->vid_nr) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c
new file mode 100644
index 000000000000..d9ed6925ca64
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Karol Herbst
+ *
+ * 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: Karol Herbst
+ */
+#include "priv.h"
+
+#include <subdev/fuse.h>
+
+static int
+gf100_volt_speedo_read(struct nvkm_volt *volt)
+{
+ struct nvkm_device *device = volt->subdev.device;
+ struct nvkm_fuse *fuse = device->fuse;
+
+ if (!fuse)
+ return -EINVAL;
+
+ return nvkm_fuse_read(fuse, 0x1cc);
+}
+
+int
+gf100_volt_oneinit(struct nvkm_volt *volt)
+{
+ struct nvkm_subdev *subdev = &volt->subdev;
+ if (volt->speedo <= 0)
+ nvkm_error(subdev, "couldn't find speedo value, volting not "
+ "possible\n");
+ return 0;
+}
+
+static const struct nvkm_volt_func
+gf100_volt = {
+ .oneinit = gf100_volt_oneinit,
+ .vid_get = nvkm_voltgpio_get,
+ .vid_set = nvkm_voltgpio_set,
+ .speedo_read = gf100_volt_speedo_read,
+};
+
+int
+gf100_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
+{
+ struct nvkm_volt *volt;
+ int ret;
+
+ ret = nvkm_volt_new_(&gf100_volt, device, index, &volt);
+ *pvolt = volt;
+ if (ret)
+ return ret;
+
+ return nvkm_voltgpio_init(volt);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
index 420bd84d8483..1c744e029454 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
@@ -27,6 +27,7 @@
#include <subdev/gpio.h>
#include <subdev/bios.h>
#include <subdev/bios/volt.h>
+#include <subdev/fuse.h>
#define gk104_volt(p) container_of((p), struct gk104_volt, base)
struct gk104_volt {
@@ -34,7 +35,7 @@ struct gk104_volt {
struct nvbios_volt bios;
};
-int
+static int
gk104_volt_get(struct nvkm_volt *base)
{
struct nvbios_volt *bios = &gk104_volt(base)->bios;
@@ -47,7 +48,7 @@ gk104_volt_get(struct nvkm_volt *base)
return bios->base + bios->pwm_range * duty / div;
}
-int
+static int
gk104_volt_set(struct nvkm_volt *base, u32 uv)
{
struct nvbios_volt *bios = &gk104_volt(base)->bios;
@@ -64,13 +65,33 @@ gk104_volt_set(struct nvkm_volt *base, u32 uv)
return 0;
}
+static int
+gk104_volt_speedo_read(struct nvkm_volt *volt)
+{
+ struct nvkm_device *device = volt->subdev.device;
+ struct nvkm_fuse *fuse = device->fuse;
+ int ret;
+
+ if (!fuse)
+ return -EINVAL;
+
+ nvkm_wr32(device, 0x122634, 0x0);
+ ret = nvkm_fuse_read(fuse, 0x3a8);
+ nvkm_wr32(device, 0x122634, 0x41);
+ return ret;
+}
+
static const struct nvkm_volt_func
gk104_volt_pwm = {
+ .oneinit = gf100_volt_oneinit,
.volt_get = gk104_volt_get,
.volt_set = gk104_volt_set,
+ .speedo_read = gk104_volt_speedo_read,
}, gk104_volt_gpio = {
+ .oneinit = gf100_volt_oneinit,
.vid_get = nvkm_voltgpio_get,
.vid_set = nvkm_voltgpio_set,
+ .speedo_read = gk104_volt_speedo_read,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c
index 74db4d28930f..2925b9cae681 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c
@@ -25,7 +25,7 @@
#include <core/tegra.h>
-const struct cvb_coef gm20b_cvb_coef[] = {
+static const struct cvb_coef gm20b_cvb_coef[] = {
/* KHz, c0, c1, c2 */
/* 76800 */ { 1786666, -85625, 1632 },
/* 153600 */ { 1846729, -87525, 1632 },
@@ -58,7 +58,7 @@ static const struct cvb_coef gm20b_na_cvb_coef[] = {
/* 998400 */ { 1316991, 8144, -940, 808, -21583, 226 },
};
-const u32 speedo_to_vmin[] = {
+static const u32 speedo_to_vmin[] = {
/* 0, 1, 2, 3, 4, */
950000, 840000, 818750, 840000, 810000,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c
index d2bac1d77819..443c031b966b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c
@@ -25,6 +25,7 @@
#include <subdev/bios.h>
#include <subdev/bios/gpio.h>
#include <subdev/gpio.h>
+#include "priv.h"
static const u8 tags[] = {
DCB_GPIO_VID0, DCB_GPIO_VID1, DCB_GPIO_VID2, DCB_GPIO_VID3,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
index d5140d991161..354bafe4b4e2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
@@ -9,11 +9,13 @@ int nvkm_volt_new_(const struct nvkm_volt_func *, struct nvkm_device *,
int index, struct nvkm_volt **);
struct nvkm_volt_func {
+ int (*oneinit)(struct nvkm_volt *);
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);
+ int (*speedo_read)(struct nvkm_volt *);
};
int nvkm_voltgpio_init(struct nvkm_volt *);
@@ -23,4 +25,6 @@ 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);
+
+int gf100_volt_oneinit(struct nvkm_volt *);
#endif
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
index 3485d1ecd655..aaa8a58390f1 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
@@ -24,23 +24,24 @@ struct panel_drv_data {
struct device *dev;
- struct omap_video_timings timings;
+ struct videomode vm;
bool invert_polarity;
};
-static const struct omap_video_timings tvc_pal_timings = {
- .x_res = 720,
- .y_res = 574,
+static const struct videomode tvc_pal_vm = {
+ .hactive = 720,
+ .vactive = 574,
.pixelclock = 13500000,
- .hsw = 64,
- .hfp = 12,
- .hbp = 68,
- .vsw = 5,
- .vfp = 5,
- .vbp = 41,
-
- .interlace = true,
+ .hsync_len = 64,
+ .hfront_porch = 12,
+ .hback_porch = 68,
+ .vsync_len = 5,
+ .vfront_porch = 5,
+ .vback_porch = 41,
+
+ .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_VSYNC_LOW,
};
static const struct of_device_id tvc_of_match[];
@@ -92,7 +93,7 @@ static int tvc_enable(struct omap_dss_device *dssdev)
if (omapdss_device_is_enabled(dssdev))
return 0;
- in->ops.atv->set_timings(in, &ddata->timings);
+ in->ops.atv->set_timings(in, &ddata->vm);
if (!ddata->dev->of_node) {
in->ops.atv->set_type(in, OMAP_DSS_VENC_TYPE_COMPOSITE);
@@ -126,32 +127,32 @@ static void tvc_disable(struct omap_dss_device *dssdev)
}
static void tvc_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.atv->set_timings(in, timings);
+ in->ops.atv->set_timings(in, vm);
}
static void tvc_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int tvc_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.atv->check_timings(in, timings);
+ return in->ops.atv->check_timings(in, vm);
}
static u32 tvc_get_wss(struct omap_dss_device *dssdev)
@@ -253,14 +254,14 @@ static int tvc_probe(struct platform_device *pdev)
return -ENODEV;
}
- ddata->timings = tvc_pal_timings;
+ ddata->vm = tvc_pal_vm;
dssdev = &ddata->dssdev;
dssdev->driver = &tvc_driver;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = tvc_pal_timings;
+ dssdev->panel.vm = tvc_pal_vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
index 684b7aeda411..d6875d9fcefa 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
@@ -19,32 +19,30 @@
#include "../dss/omapdss.h"
-static const struct omap_video_timings dvic_default_timings = {
- .x_res = 640,
- .y_res = 480,
+static const struct videomode dvic_default_vm = {
+ .hactive = 640,
+ .vactive = 480,
.pixelclock = 23500000,
- .hfp = 48,
- .hsw = 32,
- .hbp = 80,
+ .hfront_porch = 48,
+ .hsync_len = 32,
+ .hback_porch = 80,
- .vfp = 3,
- .vsw = 4,
- .vbp = 7,
+ .vfront_porch = 3,
+ .vsync_len = 4,
+ .vback_porch = 7,
- .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH |
+ DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_DE_HIGH |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
};
struct panel_drv_data {
struct omap_dss_device dssdev;
struct omap_dss_device *in;
- struct omap_video_timings timings;
+ struct videomode vm;
struct i2c_adapter *i2c_adapter;
};
@@ -90,7 +88,7 @@ static int dvic_enable(struct omap_dss_device *dssdev)
if (omapdss_device_is_enabled(dssdev))
return 0;
- in->ops.dvi->set_timings(in, &ddata->timings);
+ in->ops.dvi->set_timings(in, &ddata->vm);
r = in->ops.dvi->enable(in);
if (r)
@@ -115,32 +113,32 @@ static void dvic_disable(struct omap_dss_device *dssdev)
}
static void dvic_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dvi->set_timings(in, timings);
+ in->ops.dvi->set_timings(in, vm);
}
static void dvic_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int dvic_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dvi->check_timings(in, timings);
+ return in->ops.dvi->check_timings(in, vm);
}
static int dvic_ddc_read(struct i2c_adapter *adapter,
@@ -287,14 +285,14 @@ static int dvic_probe(struct platform_device *pdev)
if (r)
return r;
- ddata->timings = dvic_default_timings;
+ ddata->vm = dvic_default_vm;
dssdev = &ddata->dssdev;
dssdev->driver = &dvic_driver;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_DVI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = dvic_default_timings;
+ dssdev->panel.vm = dvic_default_vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index 7bdf83af9797..1ef130641bae 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -21,21 +21,18 @@
#include "../dss/omapdss.h"
-static const struct omap_video_timings hdmic_default_timings = {
- .x_res = 640,
- .y_res = 480,
+static const struct videomode hdmic_default_vm = {
+ .hactive = 640,
+ .vactive = 480,
.pixelclock = 25175000,
- .hsw = 96,
- .hfp = 16,
- .hbp = 48,
- .vsw = 2,
- .vfp = 11,
- .vbp = 31,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-
- .interlace = false,
+ .hsync_len = 96,
+ .hfront_porch = 16,
+ .hback_porch = 48,
+ .vsync_len = 2,
+ .vfront_porch = 11,
+ .vback_porch = 31,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
};
struct panel_drv_data {
@@ -44,7 +41,7 @@ struct panel_drv_data {
struct device *dev;
- struct omap_video_timings timings;
+ struct videomode vm;
int hpd_gpio;
};
@@ -96,7 +93,7 @@ static int hdmic_enable(struct omap_dss_device *dssdev)
if (omapdss_device_is_enabled(dssdev))
return 0;
- in->ops.hdmi->set_timings(in, &ddata->timings);
+ in->ops.hdmi->set_timings(in, &ddata->vm);
r = in->ops.hdmi->enable(in);
if (r)
@@ -123,32 +120,32 @@ static void hdmic_disable(struct omap_dss_device *dssdev)
}
static void hdmic_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.hdmi->set_timings(in, timings);
+ in->ops.hdmi->set_timings(in, vm);
}
static void hdmic_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int hdmic_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.hdmi->check_timings(in, timings);
+ return in->ops.hdmi->check_timings(in, vm);
}
static int hdmic_read_edid(struct omap_dss_device *dssdev,
@@ -259,14 +256,14 @@ static int hdmic_probe(struct platform_device *pdev)
goto err_reg;
}
- ddata->timings = hdmic_default_timings;
+ ddata->vm = hdmic_default_vm;
dssdev = &ddata->dssdev;
dssdev->driver = &hdmic_driver;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = hdmic_default_timings;
+ dssdev->panel.vm = hdmic_default_vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index fe4e7ec3bab0..f7a5731492d0 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -27,7 +27,7 @@ struct panel_drv_data {
struct gpio_desc *enable_gpio;
- struct omap_video_timings timings;
+ struct videomode vm;
};
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -90,7 +90,7 @@ static int opa362_enable(struct omap_dss_device *dssdev)
if (omapdss_device_is_enabled(dssdev))
return 0;
- in->ops.atv->set_timings(in, &ddata->timings);
+ in->ops.atv->set_timings(in, &ddata->vm);
r = in->ops.atv->enable(in);
if (r)
@@ -123,38 +123,38 @@ static void opa362_disable(struct omap_dss_device *dssdev)
}
static void opa362_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
dev_dbg(dssdev->dev, "set_timings\n");
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.atv->set_timings(in, timings);
+ in->ops.atv->set_timings(in, vm);
}
static void opa362_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
dev_dbg(dssdev->dev, "get_timings\n");
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int opa362_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
dev_dbg(dssdev->dev, "check_timings\n");
- return in->ops.atv->check_timings(in, timings);
+ return in->ops.atv->check_timings(in, vm);
}
static void opa362_set_type(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
index d768217cefe0..13e32d02c884 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
@@ -24,7 +24,7 @@ struct panel_drv_data {
int pd_gpio;
int data_lines;
- struct omap_video_timings timings;
+ struct videomode vm;
};
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -81,7 +81,7 @@ static int tfp410_enable(struct omap_dss_device *dssdev)
if (omapdss_device_is_enabled(dssdev))
return 0;
- in->ops.dpi->set_timings(in, &ddata->timings);
+ in->ops.dpi->set_timings(in, &ddata->vm);
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
@@ -113,44 +113,43 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void tfp410_fix_timings(struct omap_video_timings *timings)
+static void tfp410_fix_timings(struct videomode *vm)
{
- timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+ vm->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_POSEDGE;
}
static void tfp410_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- tfp410_fix_timings(timings);
+ tfp410_fix_timings(vm);
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void tfp410_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int tfp410_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- tfp410_fix_timings(timings);
+ tfp410_fix_timings(vm);
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static const struct omapdss_dvi_ops tfp410_dvi_ops = {
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 46855c8f5cbf..58276a48112e 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -26,7 +26,7 @@ struct panel_drv_data {
struct gpio_desc *ls_oe_gpio;
struct gpio_desc *hpd_gpio;
- struct omap_video_timings timings;
+ struct videomode vm;
};
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -80,7 +80,7 @@ static int tpd_enable(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
- in->ops.hdmi->set_timings(in, &ddata->timings);
+ in->ops.hdmi->set_timings(in, &ddata->vm);
r = in->ops.hdmi->enable(in);
if (r)
@@ -105,33 +105,33 @@ static void tpd_disable(struct omap_dss_device *dssdev)
}
static void tpd_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->timings = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.hdmi->set_timings(in, timings);
+ in->ops.hdmi->set_timings(in, vm);
}
static void tpd_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->timings;
+ *vm = ddata->vm;
}
static int tpd_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
int r;
- r = in->ops.hdmi->check_timings(in, timings);
+ r = in->ops.hdmi->check_timings(in, vm);
return r;
}
@@ -234,25 +234,30 @@ static int tpd_probe(struct platform_device *pdev)
if (r)
return r;
-
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ct_cp_hpd_gpio = gpio;
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ls_oe_gpio = gpio;
gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
GPIOD_IN);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->hpd_gpio = gpio;
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
index 7f16f985ab22..38003208d9ca 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
@@ -28,7 +28,7 @@ struct panel_drv_data {
int data_lines;
- struct omap_video_timings videomode;
+ struct videomode vm;
/* used for non-DT boot, to be removed */
int backlight_gpio;
@@ -80,7 +80,7 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
r = in->ops.dpi->enable(in);
if (r)
@@ -122,32 +122,32 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev)
}
static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver panel_dpi_ops = {
@@ -169,7 +169,6 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev)
const struct panel_dpi_platform_data *pdata;
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
struct omap_dss_device *dssdev, *in;
- struct videomode vm;
int r;
pdata = dev_get_platdata(&pdev->dev);
@@ -185,8 +184,7 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev)
ddata->data_lines = pdata->data_lines;
- videomode_from_timing(pdata->display_timing, &vm);
- videomode_to_omap_video_timings(&vm, &ddata->videomode);
+ videomode_from_timing(pdata->display_timing, &ddata->vm);
dssdev = &ddata->dssdev;
dssdev->name = pdata->name;
@@ -214,7 +212,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
struct omap_dss_device *in;
int r;
struct display_timing timing;
- struct videomode vm;
struct gpio_desc *gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
@@ -245,8 +242,7 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
return r;
}
- videomode_from_timing(&timing, &vm);
- videomode_to_omap_video_timings(&vm, &ddata->videomode);
+ videomode_from_timing(&timing, &ddata->vm);
in = omapdss_of_find_source_for_first_ep(node);
if (IS_ERR(in)) {
@@ -295,7 +291,7 @@ static int panel_dpi_probe(struct platform_device *pdev)
dssdev->driver = &panel_dpi_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
dssdev->phy.dpi.data_lines = ddata->data_lines;
r = omapdss_register_display(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index b1f3b818edf4..dc026a843712 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -42,7 +42,7 @@ struct panel_drv_data {
struct omap_dss_device dssdev;
struct omap_dss_device *in;
- struct omap_video_timings timings;
+ struct videomode vm;
struct platform_device *pdev;
@@ -382,8 +382,8 @@ static const struct backlight_ops dsicm_bl_ops = {
static void dsicm_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
- *xres = dssdev->panel.timings.x_res;
- *yres = dssdev->panel.timings.y_res;
+ *xres = dssdev->panel.vm.hactive;
+ *yres = dssdev->panel.vm.vactive;
}
static ssize_t dsicm_num_errors_show(struct device *dev,
@@ -589,7 +589,7 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
struct omap_dss_dsi_config dsi_config = {
.mode = OMAP_DSS_DSI_CMD_MODE,
.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
- .timings = &ddata->timings,
+ .vm = &ddata->vm,
.hs_clk_min = 150000000,
.hs_clk_max = 300000000,
.lp_clk_min = 7000000,
@@ -892,8 +892,8 @@ static int dsicm_update(struct omap_dss_device *dssdev,
/* XXX no need to send this every frame, but dsi break if not done */
r = dsicm_set_update_window(ddata, 0, 0,
- dssdev->panel.timings.x_res,
- dssdev->panel.timings.y_res);
+ dssdev->panel.vm.hactive,
+ dssdev->panel.vm.vactive);
if (r)
goto err;
@@ -1023,9 +1023,8 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev,
goto err1;
}
- size = min(w * h * 3,
- dssdev->panel.timings.x_res *
- dssdev->panel.timings.y_res * 3);
+ size = min((u32)w * h * 3,
+ dssdev->panel.vm.hactive * dssdev->panel.vm.vactive * 3);
in->ops.dsi->bus_lock(in);
@@ -1186,14 +1185,14 @@ static int dsicm_probe(struct platform_device *pdev)
if (r)
return r;
- ddata->timings.x_res = 864;
- ddata->timings.y_res = 480;
- ddata->timings.pixelclock = 864 * 480 * 60;
+ ddata->vm.hactive = 864;
+ ddata->vm.vactive = 480;
+ ddata->vm.pixelclock = 864 * 480 * 60;
dssdev = &ddata->dssdev;
dssdev->dev = dev;
dssdev->driver = &dsicm_ops;
- dssdev->panel.timings = ddata->timings;
+ dssdev->panel.vm = ddata->vm;
dssdev->type = OMAP_DISPLAY_TYPE_DSI;
dssdev->owner = THIS_MODULE;
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
index 6dfb96cea293..43d21edb51f5 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
@@ -19,25 +19,28 @@
#include "../dss/omapdss.h"
-static struct omap_video_timings lb035q02_timings = {
- .x_res = 320,
- .y_res = 240,
+static struct videomode lb035q02_vm = {
+ .hactive = 320,
+ .vactive = 240,
.pixelclock = 6500000,
- .hsw = 2,
- .hfp = 20,
- .hbp = 68,
-
- .vsw = 2,
- .vfp = 4,
- .vbp = 18,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .hsync_len = 2,
+ .hfront_porch = 20,
+ .hback_porch = 68,
+
+ .vsync_len = 2,
+ .vfront_porch = 4,
+ .vback_porch = 18,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
+ /*
+ * Note: According to the panel documentation:
+ * DE is active LOW
+ * DATA needs to be driven on the FALLING edge
+ */
};
struct panel_drv_data {
@@ -48,7 +51,7 @@ struct panel_drv_data {
int data_lines;
- struct omap_video_timings videomode;
+ struct videomode vm;
struct gpio_desc *enable_gpio;
};
@@ -158,7 +161,7 @@ static int lb035q02_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
r = in->ops.dpi->enable(in);
if (r)
@@ -189,32 +192,32 @@ static void lb035q02_disable(struct omap_dss_device *dssdev)
}
static void lb035q02_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void lb035q02_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int lb035q02_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver lb035q02_ops = {
@@ -278,14 +281,14 @@ static int lb035q02_panel_spi_probe(struct spi_device *spi)
if (r)
return r;
- ddata->videomode = lb035q02_timings;
+ ddata->vm = lb035q02_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &spi->dev;
dssdev->driver = &lb035q02_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
dssdev->phy.dpi.data_lines = ddata->data_lines;
r = omapdss_register_display(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
index 9f3d6f48f3e1..2de27ba01552 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
@@ -23,7 +23,7 @@ struct panel_drv_data {
struct omap_dss_device dssdev;
struct omap_dss_device *in;
- struct omap_video_timings videomode;
+ struct videomode vm;
int data_lines;
@@ -65,22 +65,20 @@ static const struct {
{ 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
};
-static const struct omap_video_timings nec_8048_panel_timings = {
- .x_res = LCD_XRES,
- .y_res = LCD_YRES,
+static const struct videomode nec_8048_panel_vm = {
+ .hactive = LCD_XRES,
+ .vactive = LCD_YRES,
.pixelclock = LCD_PIXEL_CLOCK,
- .hfp = 6,
- .hsw = 1,
- .hbp = 4,
- .vfp = 3,
- .vsw = 1,
- .vbp = 4,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .hfront_porch = 6,
+ .hsync_len = 1,
+ .hback_porch = 4,
+ .vfront_porch = 3,
+ .vsync_len = 1,
+ .vback_porch = 4,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
};
#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -157,7 +155,7 @@ static int nec_8048_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
r = in->ops.dpi->enable(in);
if (r)
@@ -188,32 +186,32 @@ static void nec_8048_disable(struct omap_dss_device *dssdev)
}
static void nec_8048_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void nec_8048_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int nec_8048_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver nec_8048_ops = {
@@ -306,14 +304,14 @@ static int nec_8048_probe(struct spi_device *spi)
goto err_gpio;
}
- ddata->videomode = nec_8048_panel_timings;
+ ddata->vm = nec_8048_panel_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &spi->dev;
dssdev->driver = &nec_8048_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
index 3d3efc561ea9..04fe235b7cac 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
@@ -26,7 +26,7 @@ struct panel_drv_data {
int data_lines;
- struct omap_video_timings videomode;
+ struct videomode vm;
struct gpio_desc *resb_gpio; /* low = reset active min 20 us */
struct gpio_desc *ini_gpio; /* high = power on */
@@ -35,25 +35,27 @@ struct panel_drv_data {
struct gpio_desc *ud_gpio; /* high = conventional vertical scanning */
};
-static const struct omap_video_timings sharp_ls_timings = {
- .x_res = 480,
- .y_res = 640,
+static const struct videomode sharp_ls_vm = {
+ .hactive = 480,
+ .vactive = 640,
.pixelclock = 19200000,
- .hsw = 2,
- .hfp = 1,
- .hbp = 28,
-
- .vsw = 1,
- .vfp = 1,
- .vbp = 1,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .hsync_len = 2,
+ .hfront_porch = 1,
+ .hback_porch = 28,
+
+ .vsync_len = 1,
+ .vfront_porch = 1,
+ .vback_porch = 1,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
+ /*
+ * Note: According to the panel documentation:
+ * DATA needs to be driven on the FALLING edge
+ */
};
#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -99,7 +101,7 @@ static int sharp_ls_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
if (ddata->vcc) {
r = regulator_enable(ddata->vcc);
@@ -154,32 +156,32 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev)
}
static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver sharp_ls_ops = {
@@ -279,14 +281,14 @@ static int sharp_ls_probe(struct platform_device *pdev)
if (r)
return r;
- ddata->videomode = sharp_ls_timings;
+ ddata->vm = sharp_ls_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &pdev->dev;
dssdev->driver = &sharp_ls_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
dssdev->phy.dpi.data_lines = ddata->data_lines;
r = omapdss_register_display(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
index 3557a4c7dd7b..746cb8d9cba1 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
@@ -71,7 +71,7 @@ struct panel_drv_data {
int reset_gpio;
int datapairs;
- struct omap_video_timings videomode;
+ struct videomode vm;
char *name;
int enabled;
@@ -92,23 +92,20 @@ struct panel_drv_data {
struct backlight_device *bl_dev;
};
-static const struct omap_video_timings acx565akm_panel_timings = {
- .x_res = 800,
- .y_res = 480,
+static const struct videomode acx565akm_panel_vm = {
+ .hactive = 800,
+ .vactive = 480,
.pixelclock = 24000000,
- .hfp = 28,
- .hsw = 4,
- .hbp = 24,
- .vfp = 3,
- .vsw = 3,
- .vbp = 4,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .hfront_porch = 28,
+ .hsync_len = 4,
+ .hback_porch = 24,
+ .vfront_porch = 3,
+ .vsync_len = 3,
+ .vback_porch = 4,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
};
#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -548,7 +545,7 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
dev_dbg(&ddata->spi->dev, "%s\n", __func__);
- in->ops.sdi->set_timings(in, &ddata->videomode);
+ in->ops.sdi->set_timings(in, &ddata->vm);
if (ddata->datapairs > 0)
in->ops.sdi->set_datapairs(in, ddata->datapairs);
@@ -662,32 +659,32 @@ static void acx565akm_disable(struct omap_dss_device *dssdev)
}
static void acx565akm_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.sdi->set_timings(in, timings);
+ in->ops.sdi->set_timings(in, vm);
}
static void acx565akm_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int acx565akm_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.sdi->check_timings(in, timings);
+ return in->ops.sdi->check_timings(in, vm);
}
static struct omap_dss_driver acx565akm_ops = {
@@ -845,14 +842,14 @@ static int acx565akm_probe(struct spi_device *spi)
acx565akm_bl_update_status(bldev);
- ddata->videomode = acx565akm_panel_timings;
+ ddata->vm = acx565akm_panel_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &spi->dev;
dssdev->driver = &acx565akm_ops;
dssdev->type = OMAP_DISPLAY_TYPE_SDI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
index e859b3f893f7..f313dbfcbacb 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
@@ -37,28 +37,29 @@ struct panel_drv_data {
int data_lines;
- struct omap_video_timings videomode;
+ struct videomode vm;
struct spi_device *spi_dev;
};
-static struct omap_video_timings td028ttec1_panel_timings = {
- .x_res = 480,
- .y_res = 640,
+static struct videomode td028ttec1_panel_vm = {
+ .hactive = 480,
+ .vactive = 640,
.pixelclock = 22153000,
- .hfp = 24,
- .hsw = 8,
- .hbp = 8,
- .vfp = 4,
- .vsw = 2,
- .vbp = 2,
-
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .hfront_porch = 24,
+ .hsync_len = 8,
+ .hback_porch = 8,
+ .vfront_porch = 4,
+ .vsync_len = 2,
+ .vback_porch = 2,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+ /*
+ * Note: According to the panel documentation:
+ * SYNC needs to be driven on the FALLING edge
+ */
};
#define JBT_COMMAND 0x000
@@ -208,7 +209,7 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
r = in->ops.dpi->enable(in);
if (r)
@@ -325,32 +326,32 @@ static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
}
static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver td028ttec1_ops = {
@@ -414,14 +415,14 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
if (r)
return r;
- ddata->videomode = td028ttec1_panel_timings;
+ ddata->vm = td028ttec1_panel_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &spi->dev;
dssdev->driver = &td028ttec1_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
dssdev->phy.dpi.data_lines = ddata->data_lines;
r = omapdss_register_display(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
index 66c6bbe6472b..0787dba44faa 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
@@ -56,7 +56,7 @@ struct panel_drv_data {
struct omap_dss_device dssdev;
struct omap_dss_device *in;
- struct omap_video_timings videomode;
+ struct videomode vm;
int data_lines;
@@ -72,25 +72,27 @@ struct panel_drv_data {
u32 power_on_resume:1;
};
-static const struct omap_video_timings tpo_td043_timings = {
- .x_res = 800,
- .y_res = 480,
+static const struct videomode tpo_td043_vm = {
+ .hactive = 800,
+ .vactive = 480,
.pixelclock = 36000000,
- .hsw = 1,
- .hfp = 68,
- .hbp = 214,
+ .hsync_len = 1,
+ .hfront_porch = 68,
+ .hback_porch = 214,
- .vsw = 1,
- .vfp = 39,
- .vbp = 34,
+ .vsync_len = 1,
+ .vfront_porch = 39,
+ .vback_porch = 34,
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+ /*
+ * Note: According to the panel documentation:
+ * SYNC needs to be driven on the FALLING edge
+ */
};
#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -378,7 +380,7 @@ static int tpo_td043_enable(struct omap_dss_device *dssdev)
if (ddata->data_lines)
in->ops.dpi->set_data_lines(in, ddata->data_lines);
- in->ops.dpi->set_timings(in, &ddata->videomode);
+ in->ops.dpi->set_timings(in, &ddata->vm);
r = in->ops.dpi->enable(in);
if (r)
@@ -418,32 +420,32 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
}
static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- ddata->videomode = *timings;
- dssdev->panel.timings = *timings;
+ ddata->vm = *vm;
+ dssdev->panel.vm = *vm;
- in->ops.dpi->set_timings(in, timings);
+ in->ops.dpi->set_timings(in, vm);
}
static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *timings = ddata->videomode;
+ *vm = ddata->vm;
}
static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
- return in->ops.dpi->check_timings(in, timings);
+ return in->ops.dpi->check_timings(in, vm);
}
static struct omap_dss_driver tpo_td043_ops = {
@@ -546,14 +548,14 @@ static int tpo_td043_probe(struct spi_device *spi)
goto err_sysfs;
}
- ddata->videomode = tpo_td043_timings;
+ ddata->vm = tpo_td043_vm;
dssdev = &ddata->dssdev;
dssdev->dev = &spi->dev;
dssdev->driver = &tpo_td043_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
dssdev->owner = THIS_MODULE;
- dssdev->panel.timings = ddata->videomode;
+ dssdev->panel.vm = ddata->vm;
r = omapdss_register_display(dssdev);
if (r) {
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index 535240fba671..c839f6456db2 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -75,7 +75,7 @@ struct dispc_features {
unsigned long max_lcd_pclk;
unsigned long max_tv_pclk;
int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
- const struct omap_video_timings *mgr_timings,
+ const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -1679,7 +1679,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
{
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
- bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
+ bool chroma_upscale = plane != OMAP_DSS_WB;
if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
return;
@@ -2179,7 +2179,7 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
* undocumented horizontal position and timing related limitations.
*/
static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
- const struct omap_video_timings *t, u16 pos_x,
+ const struct videomode *vm, u16 pos_x,
u16 width, u16 height, u16 out_width, u16 out_height,
bool five_taps)
{
@@ -2189,14 +2189,16 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
u64 val, blank;
int i;
- nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
+ nonactive = vm->hactive + vm->hfront_porch + vm->hsync_len +
+ vm->hback_porch - out_width;
i = 0;
if (out_height < height)
i++;
if (out_width < width)
i++;
- blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
+ blank = div_u64((u64)(vm->hback_porch + vm->hsync_len + vm->hfront_porch) *
+ lclk, pclk);
DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
if (blank <= limits[i])
return -EINVAL;
@@ -2231,7 +2233,7 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
}
static unsigned long calc_core_clk_five_taps(unsigned long pclk,
- const struct omap_video_timings *mgr_timings, u16 width,
+ const struct videomode *vm, u16 width,
u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode)
{
@@ -2242,7 +2244,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
return (unsigned long) pclk;
if (height > out_height) {
- unsigned int ppl = mgr_timings->x_res;
+ unsigned int ppl = vm->hactive;
tmp = (u64)pclk * height * out_width;
do_div(tmp, 2 * out_height * ppl);
@@ -2324,7 +2326,7 @@ static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
}
static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
- const struct omap_video_timings *mgr_timings,
+ const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2370,7 +2372,7 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
}
static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
- const struct omap_video_timings *mgr_timings,
+ const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2392,7 +2394,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
*five_taps = false;
again:
if (*five_taps)
- *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
+ *core_clk = calc_core_clk_five_taps(pclk, vm,
in_width, in_height, out_width,
out_height, color_mode);
else
@@ -2400,7 +2402,7 @@ again:
in_height, out_width, out_height,
mem_to_mem);
- error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
+ error = check_horiz_timing_omap3(pclk, lclk, vm,
pos_x, in_width, in_height, out_width,
out_height, *five_taps);
if (error && *five_taps) {
@@ -2435,7 +2437,7 @@ again:
return -EINVAL;
}
- if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width,
+ if (check_horiz_timing_omap3(pclk, lclk, vm, pos_x, in_width,
in_height, out_width, out_height, *five_taps)) {
DSSERR("horizontal timing too tight\n");
return -EINVAL;
@@ -2455,7 +2457,7 @@ again:
}
static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
- const struct omap_video_timings *mgr_timings,
+ const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2501,7 +2503,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
enum omap_overlay_caps caps,
- const struct omap_video_timings *mgr_timings,
+ const struct videomode *vm,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, u16 pos_x,
@@ -2515,7 +2517,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
if (width == out_width && height == out_height)
return 0;
- if (!mem_to_mem && (pclk == 0 || mgr_timings->pixelclock == 0)) {
+ if (!mem_to_mem && (pclk == 0 || vm->pixelclock == 0)) {
DSSERR("cannot calculate scaling settings: pclk is zero\n");
return -EINVAL;
}
@@ -2551,7 +2553,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
if (decim_y > *y_predecim || out_height > height * 8)
return -EINVAL;
- ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
+ ret = dispc.feat->calc_scaling(pclk, lclk, vm, width, height,
out_width, out_height, color_mode, five_taps,
x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
mem_to_mem);
@@ -2591,7 +2593,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
u16 out_width, u16 out_height, enum omap_color_mode color_mode,
u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
u8 global_alpha, enum omap_dss_rotation_type rotation_type,
- bool replication, const struct omap_video_timings *mgr_timings,
+ bool replication, const struct videomode *vm,
bool mem_to_mem)
{
bool five_taps = true;
@@ -2605,7 +2607,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
u16 in_height = height;
u16 in_width = width;
int x_predecim = 1, y_predecim = 1;
- bool ilace = mgr_timings->interlace;
+ bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
unsigned long pclk = dispc_plane_pclk_rate(plane);
unsigned long lclk = dispc_plane_lclk_rate(plane);
@@ -2647,7 +2649,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
if (!dss_feat_color_mode_supported(plane, color_mode))
return -EINVAL;
- r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
+ r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width,
in_height, out_width, out_height, color_mode,
&five_taps, &x_predecim, &y_predecim, pos_x,
rotation_type, mem_to_mem);
@@ -2784,7 +2786,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
}
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
- bool replication, const struct omap_video_timings *mgr_timings,
+ bool replication, const struct videomode *vm,
bool mem_to_mem)
{
int r;
@@ -2803,14 +2805,14 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
- oi->rotation_type, replication, mgr_timings, mem_to_mem);
+ oi->rotation_type, replication, vm, mem_to_mem);
return r;
}
EXPORT_SYMBOL(dispc_ovl_setup);
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
- bool mem_to_mem, const struct omap_video_timings *mgr_timings)
+ bool mem_to_mem, const struct videomode *vm)
{
int r;
u32 l;
@@ -2819,8 +2821,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
const u8 zorder = 0, global_alpha = 0;
const bool replication = false;
bool truncation;
- int in_width = mgr_timings->x_res;
- int in_height = mgr_timings->y_res;
+ int in_width = vm->hactive;
+ int in_height = vm->vactive;
enum omap_overlay_caps caps =
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
@@ -2833,7 +2835,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
wi->pre_mult_alpha, global_alpha, wi->rotation_type,
- replication, mgr_timings, mem_to_mem);
+ replication, vm, mem_to_mem);
switch (wi->color_mode) {
case OMAP_DSS_COLOR_RGB16:
@@ -2867,8 +2869,8 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
} else {
int wbdelay;
- wbdelay = min(mgr_timings->vfp + mgr_timings->vsw +
- mgr_timings->vbp, 255);
+ wbdelay = min(vm->vfront_porch +
+ vm->vsync_len + vm->vback_porch, (u32)255);
/* WBDELAYCOUNT */
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
@@ -3093,10 +3095,10 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
height <= dispc.feat->mgr_height_max;
}
-static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
+static bool _dispc_lcd_timings_ok(int hsync_len, int hfp, int hbp,
int vsw, int vfp, int vbp)
{
- if (hsw < 1 || hsw > dispc.feat->sw_max ||
+ if (hsync_len < 1 || hsync_len > dispc.feat->sw_max ||
hfp < 1 || hfp > dispc.feat->hp_max ||
hbp < 1 || hbp > dispc.feat->hp_max ||
vsw < 1 || vsw > dispc.feat->sw_max ||
@@ -3110,113 +3112,77 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
unsigned long pclk)
{
if (dss_mgr_is_lcd(channel))
- return pclk <= dispc.feat->max_lcd_pclk ? true : false;
+ return pclk <= dispc.feat->max_lcd_pclk;
else
- return pclk <= dispc.feat->max_tv_pclk ? true : false;
+ return pclk <= dispc.feat->max_tv_pclk;
}
-bool dispc_mgr_timings_ok(enum omap_channel channel,
- const struct omap_video_timings *timings)
+bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm)
{
- if (!_dispc_mgr_size_ok(timings->x_res, timings->y_res))
+ if (!_dispc_mgr_size_ok(vm->hactive, vm->vactive))
return false;
- if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock))
+ if (!_dispc_mgr_pclk_ok(channel, vm->pixelclock))
return false;
if (dss_mgr_is_lcd(channel)) {
/* TODO: OMAP4+ supports interlace for LCD outputs */
- if (timings->interlace)
+ if (vm->flags & DISPLAY_FLAGS_INTERLACED)
return false;
- if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
- timings->hbp, timings->vsw, timings->vfp,
- timings->vbp))
+ if (!_dispc_lcd_timings_ok(vm->hsync_len,
+ vm->hfront_porch, vm->hback_porch,
+ vm->vsync_len, vm->vfront_porch,
+ vm->vback_porch))
return false;
}
return true;
}
-static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
- int hfp, int hbp, int vsw, int vfp, int vbp,
- enum omap_dss_signal_level vsync_level,
- enum omap_dss_signal_level hsync_level,
- enum omap_dss_signal_edge data_pclk_edge,
- enum omap_dss_signal_level de_level,
- enum omap_dss_signal_edge sync_pclk_edge)
-
+static void _dispc_mgr_set_lcd_timings(enum omap_channel channel,
+ const struct videomode *vm)
{
u32 timing_h, timing_v, l;
bool onoff, rf, ipc, vs, hs, de;
- timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
- FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
- FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
- timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
- FLD_VAL(vfp, dispc.feat->fp_start, 8) |
- FLD_VAL(vbp, dispc.feat->bp_start, 20);
+ timing_h = FLD_VAL(vm->hsync_len - 1, dispc.feat->sw_start, 0) |
+ FLD_VAL(vm->hfront_porch - 1, dispc.feat->fp_start, 8) |
+ FLD_VAL(vm->hback_porch - 1, dispc.feat->bp_start, 20);
+ timing_v = FLD_VAL(vm->vsync_len - 1, dispc.feat->sw_start, 0) |
+ FLD_VAL(vm->vfront_porch, dispc.feat->fp_start, 8) |
+ FLD_VAL(vm->vback_porch, dispc.feat->bp_start, 20);
dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
- switch (vsync_level) {
- case OMAPDSS_SIG_ACTIVE_LOW:
- vs = true;
- break;
- case OMAPDSS_SIG_ACTIVE_HIGH:
+ if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
vs = false;
- break;
- default:
- BUG();
- }
+ else
+ vs = true;
- switch (hsync_level) {
- case OMAPDSS_SIG_ACTIVE_LOW:
- hs = true;
- break;
- case OMAPDSS_SIG_ACTIVE_HIGH:
+ if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
hs = false;
- break;
- default:
- BUG();
- }
+ else
+ hs = true;
- switch (de_level) {
- case OMAPDSS_SIG_ACTIVE_LOW:
- de = true;
- break;
- case OMAPDSS_SIG_ACTIVE_HIGH:
+ if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
de = false;
- break;
- default:
- BUG();
- }
+ else
+ de = true;
- switch (data_pclk_edge) {
- case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+ if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
ipc = false;
- break;
- case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
+ else
ipc = true;
- break;
- default:
- BUG();
- }
/* always use the 'rf' setting */
onoff = true;
- switch (sync_pclk_edge) {
- case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
- rf = false;
- break;
- case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+ if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
rf = true;
- break;
- default:
- BUG();
- }
+ else
+ rf = false;
l = FLD_VAL(onoff, 17, 17) |
FLD_VAL(rf, 16, 16) |
@@ -3253,13 +3219,13 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
/* change name to mode? */
void dispc_mgr_set_timings(enum omap_channel channel,
- const struct omap_video_timings *timings)
+ const struct videomode *vm)
{
unsigned xtot, ytot;
unsigned long ht, vt;
- struct omap_video_timings t = *timings;
+ struct videomode t = *vm;
- DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
+ DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive);
if (!dispc_mgr_timings_ok(channel, &t)) {
BUG();
@@ -3267,34 +3233,37 @@ void dispc_mgr_set_timings(enum omap_channel channel,
}
if (dss_mgr_is_lcd(channel)) {
- _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
- t.vfp, t.vbp, t.vsync_level, t.hsync_level,
- t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
+ _dispc_mgr_set_lcd_timings(channel, &t);
- xtot = t.x_res + t.hfp + t.hsw + t.hbp;
- ytot = t.y_res + t.vfp + t.vsw + t.vbp;
+ xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch;
+ ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vback_porch;
- ht = timings->pixelclock / xtot;
- vt = timings->pixelclock / xtot / ytot;
+ ht = vm->pixelclock / xtot;
+ vt = vm->pixelclock / xtot / ytot;
- DSSDBG("pck %u\n", timings->pixelclock);
- DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
- t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
+ DSSDBG("pck %lu\n", vm->pixelclock);
+ DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
+ t.hsync_len, t.hfront_porch, t.hback_porch,
+ t.vsync_len, t.vfront_porch, t.vback_porch);
DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
- t.vsync_level, t.hsync_level, t.data_pclk_edge,
- t.de_level, t.sync_pclk_edge);
+ !!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH),
+ !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH),
+ !!(t.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE),
+ !!(t.flags & DISPLAY_FLAGS_DE_HIGH),
+ !!(t.flags & DISPLAY_FLAGS_SYNC_POSEDGE));
DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
} else {
- if (t.interlace)
- t.y_res /= 2;
+ if (t.flags & DISPLAY_FLAGS_INTERLACED)
+ t.vactive /= 2;
if (dispc.feat->supports_double_pixel)
- REG_FLD_MOD(DISPC_CONTROL, t.double_pixel ? 1 : 0,
- 19, 17);
+ REG_FLD_MOD(DISPC_CONTROL,
+ !!(t.flags & DISPLAY_FLAGS_DOUBLECLK),
+ 19, 17);
}
- dispc_mgr_set_size(channel, t.x_res, t.y_res);
+ dispc_mgr_set_size(channel, t.hactive, t.vactive);
}
EXPORT_SYMBOL(dispc_mgr_set_timings);
@@ -4214,23 +4183,20 @@ EXPORT_SYMBOL(dispc_free_irq);
*/
static const struct dispc_errata_i734_data {
- struct omap_video_timings timings;
+ struct videomode vm;
struct omap_overlay_info ovli;
struct omap_overlay_manager_info mgri;
struct dss_lcd_mgr_config lcd_conf;
} i734 = {
- .timings = {
- .x_res = 8, .y_res = 1,
+ .vm = {
+ .hactive = 8, .vactive = 1,
.pixelclock = 16000000,
- .hsw = 8, .hfp = 4, .hbp = 4,
- .vsw = 1, .vfp = 1, .vbp = 1,
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .interlace = false,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .double_pixel = false,
+ .hsync_len = 8, .hfront_porch = 4, .hback_porch = 4,
+ .vsync_len = 1, .vfront_porch = 1, .vback_porch = 1,
+
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE,
},
.ovli = {
.screen_width = 1,
@@ -4320,7 +4286,7 @@ static void dispc_errata_i734_wa(void)
/* Setup and enable GFX plane */
dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD);
- dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.timings, false);
+ dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.vm, false);
dispc_ovl_enable(OMAP_DSS_GFX, true);
/* Set up and enable display manager for LCD1 */
@@ -4328,7 +4294,7 @@ static void dispc_errata_i734_wa(void)
dispc_calc_clock_rates(dss_get_dispc_clk_rate(),
&lcd_conf.clock_info);
dispc_mgr_set_lcd_config(OMAP_DSS_CHANNEL_LCD, &lcd_conf);
- dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.timings);
+ dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.vm);
dispc_clear_irqstatus(framedone_irq);
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index 8dcdd7cf9937..425a5a8dff8b 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -35,8 +35,8 @@
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
- *xres = dssdev->panel.timings.x_res;
- *yres = dssdev->panel.timings.y_res;
+ *xres = dssdev->panel.vm.hactive;
+ *yres = dssdev->panel.vm.vactive;
}
EXPORT_SYMBOL(omapdss_default_get_resolution);
@@ -72,9 +72,9 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
void omapdss_default_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- *timings = dssdev->panel.timings;
+ *vm = dssdev->panel.vm;
}
EXPORT_SYMBOL(omapdss_default_get_timings);
@@ -217,73 +217,3 @@ struct omap_dss_device *omap_dss_find_device(void *data,
return NULL;
}
EXPORT_SYMBOL(omap_dss_find_device);
-
-void videomode_to_omap_video_timings(const struct videomode *vm,
- struct omap_video_timings *ovt)
-{
- memset(ovt, 0, sizeof(*ovt));
-
- ovt->pixelclock = vm->pixelclock;
- ovt->x_res = vm->hactive;
- ovt->hbp = vm->hback_porch;
- ovt->hfp = vm->hfront_porch;
- ovt->hsw = vm->hsync_len;
- ovt->y_res = vm->vactive;
- ovt->vbp = vm->vback_porch;
- ovt->vfp = vm->vfront_porch;
- ovt->vsw = vm->vsync_len;
-
- ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
- OMAPDSS_SIG_ACTIVE_HIGH :
- OMAPDSS_SIG_ACTIVE_LOW;
- ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
- OMAPDSS_SIG_ACTIVE_HIGH :
- OMAPDSS_SIG_ACTIVE_LOW;
- ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ?
- OMAPDSS_SIG_ACTIVE_HIGH :
- OMAPDSS_SIG_ACTIVE_LOW;
- ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
- OMAPDSS_DRIVE_SIG_RISING_EDGE :
- OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-
- ovt->sync_pclk_edge = ovt->data_pclk_edge;
-}
-EXPORT_SYMBOL(videomode_to_omap_video_timings);
-
-void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
- struct videomode *vm)
-{
- memset(vm, 0, sizeof(*vm));
-
- vm->pixelclock = ovt->pixelclock;
-
- vm->hactive = ovt->x_res;
- vm->hback_porch = ovt->hbp;
- vm->hfront_porch = ovt->hfp;
- vm->hsync_len = ovt->hsw;
- vm->vactive = ovt->y_res;
- vm->vback_porch = ovt->vbp;
- vm->vfront_porch = ovt->vfp;
- vm->vsync_len = ovt->vsw;
-
- if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
- else
- vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
-
- if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
- else
- vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
-
- if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
- vm->flags |= DISPLAY_FLAGS_DE_HIGH;
- else
- vm->flags |= DISPLAY_FLAGS_DE_LOW;
-
- if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
- vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
- else
- vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
-}
-EXPORT_SYMBOL(omap_video_timings_to_videomode);
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index b268295b76cf..e75162d26ac0 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -47,7 +47,7 @@ struct dpi_data {
struct mutex lock;
- struct omap_video_timings timings;
+ struct videomode vm;
struct dss_lcd_mgr_config mgr_config;
int data_lines;
@@ -333,31 +333,31 @@ static int dpi_set_mode(struct dpi_data *dpi)
{
struct omap_dss_device *out = &dpi->output;
enum omap_channel channel = out->dispc_channel;
- struct omap_video_timings *t = &dpi->timings;
+ struct videomode *vm = &dpi->vm;
int lck_div = 0, pck_div = 0;
unsigned long fck = 0;
unsigned long pck;
int r = 0;
if (dpi->pll)
- r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck,
+ r = dpi_set_pll_clk(dpi, channel, vm->pixelclock, &fck,
&lck_div, &pck_div);
else
- r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
+ r = dpi_set_dispc_clk(dpi, vm->pixelclock, &fck,
&lck_div, &pck_div);
if (r)
return r;
pck = fck / lck_div / pck_div;
- if (pck != t->pixelclock) {
- DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
- t->pixelclock, pck);
+ if (pck != vm->pixelclock) {
+ DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
+ vm->pixelclock, pck);
- t->pixelclock = pck;
+ vm->pixelclock = pck;
}
- dss_mgr_set_timings(channel, t);
+ dss_mgr_set_timings(channel, vm);
return 0;
}
@@ -476,7 +476,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
}
static void dpi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -484,25 +484,25 @@ static void dpi_set_timings(struct omap_dss_device *dssdev,
mutex_lock(&dpi->lock);
- dpi->timings = *timings;
+ dpi->vm = *vm;
mutex_unlock(&dpi->lock);
}
static void dpi_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
mutex_lock(&dpi->lock);
- *timings = dpi->timings;
+ *vm = dpi->vm;
mutex_unlock(&dpi->lock);
}
static int dpi_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
enum omap_channel channel = dpi->output.dispc_channel;
@@ -512,23 +512,23 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
struct dpi_clk_calc_ctx ctx;
bool ok;
- if (timings->x_res % 8 != 0)
+ if (vm->hactive % 8 != 0)
return -EINVAL;
- if (!dispc_mgr_timings_ok(channel, timings))
+ if (!dispc_mgr_timings_ok(channel, vm))
return -EINVAL;
- if (timings->pixelclock == 0)
+ if (vm->pixelclock == 0)
return -EINVAL;
if (dpi->pll) {
- ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx);
+ ok = dpi_pll_clk_calc(dpi, vm->pixelclock, &ctx);
if (!ok)
return -EINVAL;
fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
} else {
- ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
+ ok = dpi_dss_clk_calc(vm->pixelclock, &ctx);
if (!ok)
return -EINVAL;
@@ -540,7 +540,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
pck = fck / lck_div / pck_div;
- timings->pixelclock = pck;
+ vm->pixelclock = pck;
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index e1be5e795cd8..f060bda31235 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -289,7 +289,7 @@ struct dsi_clk_calc_ctx {
struct dss_pll_clock_info dsi_cinfo;
struct dispc_clock_info dispc_cinfo;
- struct omap_video_timings dispc_vm;
+ struct videomode vm;
struct omap_dss_dsi_videomode_timings dsi_vm;
};
@@ -383,7 +383,7 @@ struct dsi_data {
unsigned scp_clk_refcount;
struct dss_lcd_mgr_config mgr_config;
- struct omap_video_timings timings;
+ struct videomode vm;
enum omap_dss_dsi_pixel_format pix_fmt;
enum omap_dss_dsi_mode mode;
struct omap_dss_dsi_videomode_timings vm_timings;
@@ -3321,12 +3321,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
- struct omap_video_timings *timings = &dsi->timings;
+ struct videomode *vm = &dsi->vm;
/*
* Don't use line buffers if width is greater than the video
* port's line buffer size
*/
- if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
+ if (dsi->line_buffer_size <= vm->hactive * bpp / 8)
num_line_buffers = 0;
else
num_line_buffers = 2;
@@ -3453,7 +3453,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
int tclk_trail, ths_exit, exiths_clk;
bool ddr_alwon;
- struct omap_video_timings *timings = &dsi->timings;
+ struct videomode *vm = &dsi->vm;
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int ndl = dsi->num_lanes_used - 1;
int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1;
@@ -3494,7 +3494,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
exiths_clk = ths_exit + tclk_trail;
- width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+ width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8);
bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
if (!hsa_blanking_mode) {
@@ -3705,7 +3705,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
int vbp = dsi->vm_timings.vbp;
int window_sync = dsi->vm_timings.window_sync;
bool hsync_end;
- struct omap_video_timings *timings = &dsi->timings;
+ struct videomode *vm = &dsi->vm;
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int tl, t_he, width_bytes;
@@ -3713,7 +3713,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
t_he = hsync_end ?
((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
- width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+ width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8);
/* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
@@ -3722,7 +3722,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
hfp, hsync_end ? hsa : 0, tl);
DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
- vsa, timings->y_res);
+ vsa, vm->vactive);
r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
r = FLD_MOD(r, hbp, 11, 0); /* HBP */
@@ -3738,7 +3738,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
- r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */
+ r = FLD_MOD(r, vm->vactive, 14, 0); /* VACT */
r = FLD_MOD(r, tl, 31, 16); /* TL */
dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
}
@@ -3856,7 +3856,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
/* MODE, 1 = video mode */
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
- word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
+ word_count = DIV_ROUND_UP(dsi->vm.hactive * bpp, 8);
dsi_vc_write_long_header(dsidev, channel, data_type,
word_count, 0);
@@ -3918,8 +3918,8 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev)
int r;
const unsigned channel = dsi->update_channel;
const unsigned line_buf_size = dsi->line_buffer_size;
- u16 w = dsi->timings.x_res;
- u16 h = dsi->timings.y_res;
+ u16 w = dsi->vm.hactive;
+ u16 h = dsi->vm.vactive;
DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
@@ -3969,7 +3969,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev)
msecs_to_jiffies(250));
BUG_ON(r == 0);
- dss_mgr_set_timings(dispc_channel, &dsi->timings);
+ dss_mgr_set_timings(dispc_channel, &dsi->vm);
dss_mgr_start_update(dispc_channel);
@@ -4056,8 +4056,8 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel,
dsi->framedone_callback = callback;
dsi->framedone_data = data;
- dw = dsi->timings.x_res;
- dh = dsi->timings.y_res;
+ dw = dsi->vm.hactive;
+ dh = dsi->vm.vactive;
#ifdef DSI_PERF_MEASURE
dsi->update_bytes = dw * dh *
@@ -4120,16 +4120,21 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
/*
* override interlace, logic level and edge related parameters in
- * omap_video_timings with default values
+ * videomode with default values
*/
- dsi->timings.interlace = false;
- dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
- dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-
- dss_mgr_set_timings(channel, &dsi->timings);
+ dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+ dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
+
+ dss_mgr_set_timings(channel, &dsi->vm);
r = dsi_configure_dispc_clocks(dsidev);
if (r)
@@ -4331,7 +4336,7 @@ static void print_dsi_vm(const char *str,
wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
- bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+ bl = t->hss + t->hsa + t->hse + t->hbp + t->hfront_porch;
tot = bl + pps;
#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
@@ -4340,14 +4345,14 @@ static void print_dsi_vm(const char *str,
"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
str,
byteclk,
- t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+ t->hss, t->hsa, t->hse, t->hbp, pps, t->hfront_porch,
bl, pps, tot,
TO_DSI_T(t->hss),
TO_DSI_T(t->hsa),
TO_DSI_T(t->hse),
TO_DSI_T(t->hbp),
TO_DSI_T(pps),
- TO_DSI_T(t->hfp),
+ TO_DSI_T(t->hfront_porch),
TO_DSI_T(bl),
TO_DSI_T(pps),
@@ -4356,13 +4361,13 @@ static void print_dsi_vm(const char *str,
#undef TO_DSI_T
}
-static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+static void print_dispc_vm(const char *str, const struct videomode *vm)
{
- unsigned long pck = t->pixelclock;
+ unsigned long pck = vm->pixelclock;
int hact, bl, tot;
- hact = t->x_res;
- bl = t->hsw + t->hbp + t->hfp;
+ hact = vm->hactive;
+ bl = vm->hsync_len + vm->hbp + vm->hfront_porch;
tot = hact + bl;
#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
@@ -4371,12 +4376,12 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
"%u/%u/%u/%u = %u + %u = %u\n",
str,
pck,
- t->hsw, t->hbp, hact, t->hfp,
+ vm->hsync_len, vm->hbp, hact, vm->hfront_porch,
bl, hact, tot,
- TO_DISPC_T(t->hsw),
- TO_DISPC_T(t->hbp),
+ TO_DISPC_T(vm->hsync_len),
+ TO_DISPC_T(vm->hbp),
TO_DISPC_T(hact),
- TO_DISPC_T(t->hfp),
+ TO_DISPC_T(vm->hfront_porch),
TO_DISPC_T(bl),
TO_DISPC_T(hact),
TO_DISPC_T(tot));
@@ -4387,7 +4392,7 @@ static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
static void print_dsi_dispc_vm(const char *str,
const struct omap_dss_dsi_videomode_timings *t)
{
- struct omap_video_timings vm = { 0 };
+ struct videomode vm = { 0 };
unsigned long byteclk = t->hsclk / 4;
unsigned long pck;
u64 dsi_tput;
@@ -4396,13 +4401,13 @@ static void print_dsi_dispc_vm(const char *str,
dsi_tput = (u64)byteclk * t->ndl * 8;
pck = (u32)div64_u64(dsi_tput, t->bitspp);
dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
- dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+ dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfront_porch;
vm.pixelclock = pck;
- vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+ vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
- vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
- vm.x_res = t->hact;
+ vm.hfront_porch = div64_u64((u64)t->hfront_porch * pck, byteclk);
+ vm.hactive = t->hact;
print_dispc_vm(str, &vm);
}
@@ -4412,19 +4417,19 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
unsigned long pck, void *data)
{
struct dsi_clk_calc_ctx *ctx = data;
- struct omap_video_timings *t = &ctx->dispc_vm;
+ struct videomode *vm = &ctx->vm;
ctx->dispc_cinfo.lck_div = lckd;
ctx->dispc_cinfo.pck_div = pckd;
ctx->dispc_cinfo.lck = lck;
ctx->dispc_cinfo.pck = pck;
- *t = *ctx->config->timings;
- t->pixelclock = pck;
- t->x_res = ctx->config->timings->x_res;
- t->y_res = ctx->config->timings->y_res;
- t->hsw = t->hfp = t->hbp = t->vsw = 1;
- t->vfp = t->vbp = 0;
+ *vm = *ctx->config->vm;
+ vm->pixelclock = pck;
+ vm->hactive = ctx->config->vm->hactive;
+ vm->vactive = ctx->config->vm->vactive;
+ vm->hsync_len = vm->hfront_porch = vm->hback_porch = vm->vsync_len = 1;
+ vm->vfront_porch = vm->vback_porch = 0;
return true;
}
@@ -4475,7 +4480,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
* especially as we go to LP between each pixel packet due to HW
* "feature". So let's just estimate very roughly and multiply by 1.5.
*/
- pck = cfg->timings->pixelclock;
+ pck = cfg->vm->pixelclock;
pck = pck * 3 / 2;
txbyteclk = pck * bitspp / 8 / ndl;
@@ -4510,14 +4515,14 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
int dispc_htot, dispc_hbl; /* pixels */
int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
int hfp, hsa, hbp;
- const struct omap_video_timings *req_vm;
- struct omap_video_timings *dispc_vm;
+ const struct videomode *req_vm;
+ struct videomode *dispc_vm;
struct omap_dss_dsi_videomode_timings *dsi_vm;
u64 dsi_tput, dispc_tput;
dsi_tput = (u64)byteclk * ndl * 8;
- req_vm = cfg->timings;
+ req_vm = cfg->vm;
req_pck_min = ctx->req_pck_min;
req_pck_max = ctx->req_pck_max;
req_pck_nom = ctx->req_pck_nom;
@@ -4525,9 +4530,10 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
dispc_pck = ctx->dispc_cinfo.pck;
dispc_tput = (u64)dispc_pck * bitspp;
- xres = req_vm->x_res;
+ xres = req_vm->hactive;
- panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+ panel_hbl = req_vm->hfront_porch + req_vm->hback_porch +
+ req_vm->hsync_len;
panel_htot = xres + panel_hbl;
dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
@@ -4557,7 +4563,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
hss = DIV_ROUND_UP(4, ndl);
if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
- if (ndl == 3 && req_vm->hsw == 0)
+ if (ndl == 3 && req_vm->hsync_len == 0)
hse = 1;
else
hse = DIV_ROUND_UP(4, ndl);
@@ -4596,14 +4602,14 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
hsa = 0;
- } else if (ndl == 3 && req_vm->hsw == 0) {
+ } else if (ndl == 3 && req_vm->hsync_len == 0) {
hsa = 0;
} else {
- hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
+ hsa = div64_u64((u64)req_vm->hsync_len * byteclk, req_pck_nom);
hsa = max(hsa - hse, 1);
}
- hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+ hbp = div64_u64((u64)req_vm->hback_porch * byteclk, req_pck_nom);
hbp = max(hbp, 1);
hfp = dsi_hbl - (hss + hsa + hse + hbp);
@@ -4633,10 +4639,10 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
dsi_vm->hact = xres;
dsi_vm->hfp = hfp;
- dsi_vm->vsa = req_vm->vsw;
- dsi_vm->vbp = req_vm->vbp;
- dsi_vm->vact = req_vm->y_res;
- dsi_vm->vfp = req_vm->vfp;
+ dsi_vm->vsa = req_vm->vsync_len;
+ dsi_vm->vbp = req_vm->vback_porch;
+ dsi_vm->vact = req_vm->vactive;
+ dsi_vm->vfp = req_vm->vfront_porch;
dsi_vm->trans_mode = cfg->trans_mode;
@@ -4650,19 +4656,19 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
/* setup DISPC videomode */
- dispc_vm = &ctx->dispc_vm;
+ dispc_vm = &ctx->vm;
*dispc_vm = *req_vm;
dispc_vm->pixelclock = dispc_pck;
if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
- hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
+ hsa = div64_u64((u64)req_vm->hsync_len * dispc_pck,
req_pck_nom);
hsa = max(hsa, 1);
} else {
hsa = 1;
}
- hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+ hbp = div64_u64((u64)req_vm->hback_porch * dispc_pck, req_pck_nom);
hbp = max(hbp, 1);
hfp = dispc_hbl - hsa - hbp;
@@ -4685,9 +4691,9 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
if (hfp < 1)
return false;
- dispc_vm->hfp = hfp;
- dispc_vm->hsw = hsa;
- dispc_vm->hbp = hbp;
+ dispc_vm->hfront_porch = hfp;
+ dispc_vm->hsync_len = hsa;
+ dispc_vm->hback_porch = hbp;
return true;
}
@@ -4707,9 +4713,9 @@ static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
return false;
#ifdef PRINT_VERBOSE_VM_TIMINGS
- print_dispc_vm("dispc", &ctx->dispc_vm);
+ print_dispc_vm("dispc", &ctx->vm);
print_dsi_vm("dsi ", &ctx->dsi_vm);
- print_dispc_vm("req ", ctx->config->timings);
+ print_dispc_vm("req ", ctx->config->vm);
print_dsi_dispc_vm("act ", &ctx->dsi_vm);
#endif
@@ -4758,7 +4764,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
const struct omap_dss_dsi_config *cfg,
struct dsi_clk_calc_ctx *ctx)
{
- const struct omap_video_timings *t = cfg->timings;
+ const struct videomode *vm = cfg->vm;
unsigned long clkin;
unsigned long pll_min;
unsigned long pll_max;
@@ -4774,9 +4780,9 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
ctx->config = cfg;
/* these limits should come from the panel driver */
- ctx->req_pck_min = t->pixelclock - 1000;
- ctx->req_pck_nom = t->pixelclock;
- ctx->req_pck_max = t->pixelclock + 1000;
+ ctx->req_pck_min = vm->pixelclock - 1000;
+ ctx->req_pck_nom = vm->pixelclock;
+ ctx->req_pck_max = vm->pixelclock + 1000;
byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
@@ -4833,7 +4839,7 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
dsi->user_dsi_cinfo = ctx.dsi_cinfo;
dsi->user_dispc_cinfo = ctx.dispc_cinfo;
- dsi->timings = ctx.dispc_vm;
+ dsi->vm = ctx.vm;
dsi->vm_timings = ctx.dsi_vm;
mutex_unlock(&dsi->lock);
@@ -5342,7 +5348,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
resource_size(res));
- if (!dsi->proto_base) {
+ if (!dsi->phy_base) {
DSSERR("can't ioremap DSI PHY\n");
return -ENOMEM;
}
@@ -5362,7 +5368,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
resource_size(res));
- if (!dsi->proto_base) {
+ if (!dsi->pll_base) {
DSSERR("can't ioremap DSI PLL\n");
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 4fd06dc41cb3..56493b290731 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -366,8 +366,7 @@ bool dispc_div_calc(unsigned long dispc,
unsigned long pck_min, unsigned long pck_max,
dispc_div_calc_func func, void *data);
-bool dispc_mgr_timings_ok(enum omap_channel channel,
- const struct omap_video_timings *timings);
+bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm);
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo);
@@ -390,7 +389,7 @@ void dispc_wb_enable(bool enable);
bool dispc_wb_is_enabled(void);
void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
- bool mem_to_mem, const struct omap_video_timings *timings);
+ bool mem_to_mem, const struct videomode *vm);
/* VENC */
int venc_init_platform_driver(void) __init;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index 63e711545865..fb6cccd02374 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -181,7 +181,7 @@ struct hdmi_video_format {
};
struct hdmi_config {
- struct omap_video_timings timings;
+ struct videomode vm;
struct hdmi_avi_infoframe infoframe;
enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
};
@@ -298,11 +298,11 @@ int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val);
void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
struct hdmi_video_format *video_fmt);
void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
- struct omap_video_timings *timings, struct hdmi_config *param);
+ struct videomode *vm, struct hdmi_config *param);
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index cbd28dfdb86a..e7162c16de2e 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -155,7 +155,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
static int hdmi_power_on_full(struct omap_dss_device *dssdev)
{
int r;
- struct omap_video_timings *p;
+ struct videomode *vm;
enum omap_channel channel = dssdev->dispc_channel;
struct hdmi_wp_data *wp = &hdmi.wp;
struct dss_pll_clock_info hdmi_cinfo = { 0 };
@@ -169,12 +169,13 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi_wp_clear_irqenable(wp, 0xffffffff);
hdmi_wp_set_irqstatus(wp, 0xffffffff);
- p = &hdmi.cfg.timings;
+ vm = &hdmi.cfg.vm;
- DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+ DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive,
+ vm->vactive);
- pc = p->pixelclock;
- if (p->double_pixel)
+ pc = vm->pixelclock;
+ if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
pc *= 2;
/* DSS_HDMI_TCLK is bitclk / 10 */
@@ -209,7 +210,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
/* tv size */
- dss_mgr_set_timings(channel, p);
+ dss_mgr_set_timings(channel, vm);
r = dss_mgr_enable(channel);
if (r)
@@ -255,30 +256,30 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
}
static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings))
+ if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm))
return -EINVAL;
return 0;
}
static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
mutex_lock(&hdmi.lock);
- hdmi.cfg.timings = *timings;
+ hdmi.cfg.vm = *vm;
- dispc_set_tv_pclk(timings->pixelclock);
+ dispc_set_tv_pclk(vm->pixelclock);
mutex_unlock(&hdmi.lock);
}
static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- *timings = hdmi.cfg.timings;
+ *vm = hdmi.cfg.vm;
}
static void hdmi_dump_regs(struct seq_file *s)
@@ -352,7 +353,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
if (hdmi.audio_configured) {
r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
- hdmi.cfg.timings.pixelclock);
+ hdmi.cfg.vm.pixelclock);
if (r) {
DSSERR("Error restoring audio configuration: %d", r);
hdmi.audio_abort_cb(&hdmi.pdev->dev);
@@ -643,7 +644,7 @@ static int hdmi_audio_config(struct device *dev,
}
ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
- hd->cfg.timings.pixelclock);
+ hd->cfg.vm.pixelclock);
if (!ret) {
hd->audio_configured = true;
hd->audio_config = *dss_audio;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
index ef3afe99e487..e05b7ac4f7dd 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
@@ -310,7 +310,7 @@ void hdmi4_configure(struct hdmi_core_data *core,
struct hdmi_wp_data *wp, struct hdmi_config *cfg)
{
/* HDMI */
- struct omap_video_timings video_timing;
+ struct videomode vm;
struct hdmi_video_format video_format;
/* HDMI core */
struct hdmi_core_video_config v_core_cfg;
@@ -318,16 +318,16 @@ void hdmi4_configure(struct hdmi_core_data *core,
hdmi_core_init(&v_core_cfg);
- hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
+ hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg);
- hdmi_wp_video_config_timing(wp, &video_timing);
+ hdmi_wp_video_config_timing(wp, &vm);
/* video config */
video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
hdmi_wp_video_config_format(wp, &video_format);
- hdmi_wp_video_config_interface(wp, &video_timing);
+ hdmi_wp_video_config_interface(wp, &vm);
/*
* configure core video part
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 0c0a5139a301..678dfb02764a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -172,7 +172,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
static int hdmi_power_on_full(struct omap_dss_device *dssdev)
{
int r;
- struct omap_video_timings *p;
+ struct videomode *vm;
enum omap_channel channel = dssdev->dispc_channel;
struct dss_pll_clock_info hdmi_cinfo = { 0 };
unsigned pc;
@@ -181,12 +181,13 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (r)
return r;
- p = &hdmi.cfg.timings;
+ vm = &hdmi.cfg.vm;
- DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+ DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive,
+ vm->vactive);
- pc = p->pixelclock;
- if (p->double_pixel)
+ pc = vm->pixelclock;
+ if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
pc *= 2;
/* DSS_HDMI_TCLK is bitclk / 10 */
@@ -226,7 +227,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
/* tv size */
- dss_mgr_set_timings(channel, p);
+ dss_mgr_set_timings(channel, vm);
r = dss_mgr_enable(channel);
if (r)
@@ -272,30 +273,30 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
}
static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings))
+ if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm))
return -EINVAL;
return 0;
}
static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
mutex_lock(&hdmi.lock);
- hdmi.cfg.timings = *timings;
+ hdmi.cfg.vm = *vm;
- dispc_set_tv_pclk(timings->pixelclock);
+ dispc_set_tv_pclk(vm->pixelclock);
mutex_unlock(&hdmi.lock);
}
static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- *timings = hdmi.cfg.timings;
+ *vm = hdmi.cfg.vm;
}
static void hdmi_dump_regs(struct seq_file *s)
@@ -378,7 +379,7 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
if (hdmi.audio_configured) {
r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
- hdmi.cfg.timings.pixelclock);
+ hdmi.cfg.vm.pixelclock);
if (r) {
DSSERR("Error restoring audio configuration: %d", r);
hdmi.audio_abort_cb(&hdmi.pdev->dev);
@@ -669,7 +670,7 @@ static int hdmi_audio_config(struct device *dev,
}
ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
- hd->cfg.timings.pixelclock);
+ hd->cfg.vm.pixelclock);
if (!ret) {
hd->audio_configured = true;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index 8ab2093daa12..8de1d7b2ae55 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -292,35 +292,35 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
{
DSSDBG("hdmi_core_init\n");
- video_cfg->v_fc_config.timings = cfg->timings;
+ video_cfg->v_fc_config.vm = cfg->vm;
/* video core */
video_cfg->data_enable_pol = 1; /* It is always 1*/
- video_cfg->hblank = cfg->timings.hfp +
- cfg->timings.hbp + cfg->timings.hsw;
+ video_cfg->hblank = cfg->vm.hfront_porch +
+ cfg->vm.hback_porch + cfg->vm.hsync_len;
video_cfg->vblank_osc = 0;
- video_cfg->vblank = cfg->timings.vsw +
- cfg->timings.vfp + cfg->timings.vbp;
+ video_cfg->vblank = cfg->vm.vsync_len + cfg->vm.vfront_porch +
+ cfg->vm.vback_porch;
video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode;
- if (cfg->timings.interlace) {
+ if (cfg->vm.flags & DISPLAY_FLAGS_INTERLACED) {
/* set vblank_osc if vblank is fractional */
if (video_cfg->vblank % 2 != 0)
video_cfg->vblank_osc = 1;
- video_cfg->v_fc_config.timings.y_res /= 2;
+ video_cfg->v_fc_config.vm.vactive /= 2;
video_cfg->vblank /= 2;
- video_cfg->v_fc_config.timings.vfp /= 2;
- video_cfg->v_fc_config.timings.vsw /= 2;
- video_cfg->v_fc_config.timings.vbp /= 2;
+ video_cfg->v_fc_config.vm.vfront_porch /= 2;
+ video_cfg->v_fc_config.vm.vsync_len /= 2;
+ video_cfg->v_fc_config.vm.vback_porch /= 2;
}
- if (cfg->timings.double_pixel) {
- video_cfg->v_fc_config.timings.x_res *= 2;
+ if (cfg->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
+ video_cfg->v_fc_config.vm.hactive *= 2;
video_cfg->hblank *= 2;
- video_cfg->v_fc_config.timings.hfp *= 2;
- video_cfg->v_fc_config.timings.hsw *= 2;
- video_cfg->v_fc_config.timings.hbp *= 2;
+ video_cfg->v_fc_config.vm.hfront_porch *= 2;
+ video_cfg->v_fc_config.vm.hsync_len *= 2;
+ video_cfg->v_fc_config.vm.hback_porch *= 2;
}
}
@@ -329,13 +329,12 @@ static void hdmi_core_video_config(struct hdmi_core_data *core,
struct hdmi_core_vid_config *cfg)
{
void __iomem *base = core->base;
+ struct videomode *vm = &cfg->v_fc_config.vm;
unsigned char r = 0;
bool vsync_pol, hsync_pol;
- vsync_pol =
- cfg->v_fc_config.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
- hsync_pol =
- cfg->v_fc_config.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+ vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH);
+ hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH);
/* Set hsync, vsync and data-enable polarity */
r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF);
@@ -343,20 +342,16 @@ static void hdmi_core_video_config(struct hdmi_core_data *core,
r = FLD_MOD(r, hsync_pol, 5, 5);
r = FLD_MOD(r, cfg->data_enable_pol, 4, 4);
r = FLD_MOD(r, cfg->vblank_osc, 1, 1);
- r = FLD_MOD(r, cfg->v_fc_config.timings.interlace, 0, 0);
+ r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 0, 0);
hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r);
/* set x resolution */
- REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1,
- cfg->v_fc_config.timings.x_res >> 8, 4, 0);
- REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0,
- cfg->v_fc_config.timings.x_res & 0xFF, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, vm->hactive >> 8, 4, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, vm->hactive & 0xFF, 7, 0);
/* set y resolution */
- REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1,
- cfg->v_fc_config.timings.y_res >> 8, 4, 0);
- REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0,
- cfg->v_fc_config.timings.y_res & 0xFF, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, vm->vactive >> 8, 4, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, vm->vactive & 0xFF, 7, 0);
/* set horizontal blanking pixels */
REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0);
@@ -366,30 +361,28 @@ static void hdmi_core_video_config(struct hdmi_core_data *core,
REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0);
/* set horizontal sync offset */
- REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1,
- cfg->v_fc_config.timings.hfp >> 8, 4, 0);
- REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0,
- cfg->v_fc_config.timings.hfp & 0xFF, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, vm->hfront_porch >> 8,
+ 4, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, vm->hfront_porch & 0xFF,
+ 7, 0);
/* set vertical sync offset */
- REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY,
- cfg->v_fc_config.timings.vfp, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, vm->vfront_porch, 7, 0);
/* set horizontal sync pulse width */
- REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1,
- (cfg->v_fc_config.timings.hsw >> 8), 1, 0);
- REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0,
- cfg->v_fc_config.timings.hsw & 0xFF, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, (vm->hsync_len >> 8),
+ 1, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, vm->hsync_len & 0xFF,
+ 7, 0);
/* set vertical sync pulse width */
- REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH,
- cfg->v_fc_config.timings.vsw, 5, 0);
+ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, vm->vsync_len, 5, 0);
/* select DVI mode */
REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF,
- cfg->v_fc_config.hdmi_dvi_mode, 3, 3);
+ cfg->v_fc_config.hdmi_dvi_mode, 3, 3);
- if (cfg->v_fc_config.timings.double_pixel)
+ if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 2, 7, 4);
else
REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 1, 7, 4);
@@ -616,7 +609,7 @@ int hdmi5_core_handle_irqs(struct hdmi_core_data *core)
void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
struct hdmi_config *cfg)
{
- struct omap_video_timings video_timing;
+ struct videomode vm;
struct hdmi_video_format video_format;
struct hdmi_core_vid_config v_core_cfg;
@@ -624,16 +617,16 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
hdmi_core_init(&v_core_cfg, cfg);
- hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
+ hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg);
- hdmi_wp_video_config_timing(wp, &video_timing);
+ hdmi_wp_video_config_timing(wp, &vm);
/* video config */
video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
hdmi_wp_video_config_format(wp, &video_format);
- hdmi_wp_video_config_interface(wp, &video_timing);
+ hdmi_wp_video_config_interface(wp, &vm);
/* support limited range with 24 bit color depth for now */
hdmi_core_configure_range(core);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
index 203694a52d18..b783d5a0750e 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
@@ -144,87 +144,84 @@ void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
}
void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
u32 r;
bool vsync_pol, hsync_pol;
DSSDBG("Enter hdmi_wp_video_config_interface\n");
- vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
- hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+ vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH);
+ hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH);
r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
r = FLD_MOD(r, vsync_pol, 7, 7);
r = FLD_MOD(r, hsync_pol, 6, 6);
- r = FLD_MOD(r, timings->interlace, 3, 3);
+ r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3);
r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
}
void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
u32 timing_h = 0;
u32 timing_v = 0;
- unsigned hsw_offset = 1;
+ unsigned hsync_len_offset = 1;
DSSDBG("Enter hdmi_wp_video_config_timing\n");
/*
* On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5
- * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsw-1.
+ * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsync_len-1.
* However, we don't support OMAP5 ES1 at all, so we can just check for
* OMAP4 here.
*/
if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
omapdss_get_version() == OMAPDSS_VER_OMAP4)
- hsw_offset = 0;
+ hsync_len_offset = 0;
- timing_h |= FLD_VAL(timings->hbp, 31, 20);
- timing_h |= FLD_VAL(timings->hfp, 19, 8);
- timing_h |= FLD_VAL(timings->hsw - hsw_offset, 7, 0);
+ timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
+ timing_h |= FLD_VAL(vm->hfront_porch, 19, 8);
+ timing_h |= FLD_VAL(vm->hsync_len - hsync_len_offset, 7, 0);
hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
- timing_v |= FLD_VAL(timings->vbp, 31, 20);
- timing_v |= FLD_VAL(timings->vfp, 19, 8);
- timing_v |= FLD_VAL(timings->vsw, 7, 0);
+ timing_v |= FLD_VAL(vm->vback_porch, 31, 20);
+ timing_v |= FLD_VAL(vm->vfront_porch, 19, 8);
+ timing_v |= FLD_VAL(vm->vsync_len, 7, 0);
hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
}
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
- struct omap_video_timings *timings, struct hdmi_config *param)
+ struct videomode *vm, struct hdmi_config *param)
{
DSSDBG("Enter hdmi_wp_video_init_format\n");
video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
- video_fmt->y_res = param->timings.y_res;
- video_fmt->x_res = param->timings.x_res;
-
- timings->hbp = param->timings.hbp;
- timings->hfp = param->timings.hfp;
- timings->hsw = param->timings.hsw;
- timings->vbp = param->timings.vbp;
- timings->vfp = param->timings.vfp;
- timings->vsw = param->timings.vsw;
-
- timings->vsync_level = param->timings.vsync_level;
- timings->hsync_level = param->timings.hsync_level;
- timings->interlace = param->timings.interlace;
- timings->double_pixel = param->timings.double_pixel;
-
- if (param->timings.interlace) {
+ video_fmt->y_res = param->vm.vactive;
+ video_fmt->x_res = param->vm.hactive;
+
+ vm->hback_porch = param->vm.hback_porch;
+ vm->hfront_porch = param->vm.hfront_porch;
+ vm->hsync_len = param->vm.hsync_len;
+ vm->vback_porch = param->vm.vback_porch;
+ vm->vfront_porch = param->vm.vfront_porch;
+ vm->vsync_len = param->vm.vsync_len;
+
+ vm->flags = param->vm.flags;
+
+ if (param->vm.flags & DISPLAY_FLAGS_INTERLACED) {
video_fmt->y_res /= 2;
- timings->vbp /= 2;
- timings->vfp /= 2;
- timings->vsw /= 2;
+ vm->vback_porch /= 2;
+ vm->vfront_porch /= 2;
+ vm->vsync_len /= 2;
}
- if (param->timings.double_pixel) {
+ if (param->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
video_fmt->x_res *= 2;
- timings->hfp *= 2;
- timings->hsw *= 2;
- timings->hbp *= 2;
+ vm->hfront_porch *= 2;
+ vm->hsync_len *= 2;
+ vm->hback_porch *= 2;
}
}
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 6eaf1adbd606..b420dde8c0fb 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -290,7 +290,7 @@ struct omap_dss_dsi_videomode_timings {
struct omap_dss_dsi_config {
enum omap_dss_dsi_mode mode;
enum omap_dss_dsi_pixel_format pixel_format;
- const struct omap_video_timings *timings;
+ const struct videomode *vm;
unsigned long hs_clk_min, hs_clk_max;
unsigned long lp_clk_min, lp_clk_max;
@@ -299,48 +299,12 @@ struct omap_dss_dsi_config {
enum omap_dss_dsi_trans_mode trans_mode;
};
-struct omap_video_timings {
- /* Unit: pixels */
- u16 x_res;
- /* Unit: pixels */
- u16 y_res;
- /* Unit: Hz */
- u32 pixelclock;
- /* Unit: pixel clocks */
- u16 hsw; /* Horizontal synchronization pulse width */
- /* Unit: pixel clocks */
- u16 hfp; /* Horizontal front porch */
- /* Unit: pixel clocks */
- u16 hbp; /* Horizontal back porch */
- /* Unit: line clocks */
- u16 vsw; /* Vertical synchronization pulse width */
- /* Unit: line clocks */
- u16 vfp; /* Vertical front porch */
- /* Unit: line clocks */
- u16 vbp; /* Vertical back porch */
-
- /* Vsync logic level */
- enum omap_dss_signal_level vsync_level;
- /* Hsync logic level */
- enum omap_dss_signal_level hsync_level;
- /* Interlaced or Progressive timings */
- bool interlace;
- /* Pixel clock edge to drive LCD data */
- enum omap_dss_signal_edge data_pclk_edge;
- /* Data enable logic level */
- enum omap_dss_signal_level de_level;
- /* Pixel clock edges to drive HSYNC and VSYNC signals */
- enum omap_dss_signal_edge sync_pclk_edge;
-
- bool double_pixel;
-};
-
-/* Hardcoded timings for tv modes. Venc only uses these to
+/* Hardcoded videomodes for tv. Venc only uses these to
* identify the mode, and does not actually use the configs
* itself. However, the configs should be something that
* a normal monitor can also show */
-extern const struct omap_video_timings omap_dss_pal_timings;
-extern const struct omap_video_timings omap_dss_ntsc_timings;
+extern const struct videomode omap_dss_pal_vm;
+extern const struct videomode omap_dss_ntsc_vm;
struct omap_dss_cpr_coefs {
s16 rr, rg, rb;
@@ -502,11 +466,11 @@ struct omapdss_dpi_ops {
void (*disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines);
};
@@ -521,11 +485,11 @@ struct omapdss_sdi_ops {
void (*disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs);
};
@@ -540,11 +504,11 @@ struct omapdss_dvi_ops {
void (*disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
};
struct omapdss_atv_ops {
@@ -557,11 +521,11 @@ struct omapdss_atv_ops {
void (*disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_type)(struct omap_dss_device *dssdev,
enum omap_dss_venc_type type);
@@ -582,11 +546,11 @@ struct omapdss_hdmi_ops {
void (*disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev);
@@ -692,7 +656,7 @@ struct omap_dss_device {
} phy;
struct {
- struct omap_video_timings timings;
+ struct videomode vm;
enum omap_dss_dsi_pixel_format dsi_pix_fmt;
enum omap_dss_dsi_mode dsi_mode;
@@ -785,11 +749,11 @@ struct omap_dss_driver {
int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*set_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
void (*get_timings)(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
u32 (*get_wss)(struct omap_dss_device *dssdev);
@@ -819,11 +783,6 @@ struct omap_dss_device *omap_dss_find_device(void *data,
int (*match)(struct omap_dss_device *dssdev, void *data));
const char *omapdss_get_default_display_name(void);
-void videomode_to_omap_video_timings(const struct videomode *vm,
- struct omap_video_timings *ovt);
-void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
- struct videomode *vm);
-
int dss_feat_get_num_mgrs(void);
int dss_feat_get_num_ovls(void);
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
@@ -852,7 +811,7 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres);
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
void omapdss_default_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings);
+ struct videomode *vm);
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
@@ -906,7 +865,7 @@ void dispc_mgr_go(enum omap_channel channel);
void dispc_mgr_set_lcd_config(enum omap_channel channel,
const struct dss_lcd_mgr_config *config);
void dispc_mgr_set_timings(enum omap_channel channel,
- const struct omap_video_timings *timings);
+ const struct videomode *vm);
void dispc_mgr_setup(enum omap_channel channel,
const struct omap_overlay_manager_info *info);
u32 dispc_mgr_gamma_size(enum omap_channel channel);
@@ -919,8 +878,7 @@ bool dispc_ovl_enabled(enum omap_plane plane);
void dispc_ovl_set_channel_out(enum omap_plane plane,
enum omap_channel channel);
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
- bool replication, const struct omap_video_timings *mgr_timings,
- bool mem_to_mem);
+ bool replication, const struct videomode *vm, bool mem_to_mem);
enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel);
@@ -934,7 +892,7 @@ struct dss_mgr_ops {
int (*enable)(enum omap_channel channel);
void (*disable)(enum omap_channel channel);
void (*set_timings)(enum omap_channel channel,
- const struct omap_video_timings *timings);
+ const struct videomode *vm);
void (*set_lcd_config)(enum omap_channel channel,
const struct dss_lcd_mgr_config *config);
int (*register_framedone_handler)(enum omap_channel channel,
@@ -951,7 +909,7 @@ int dss_mgr_connect(enum omap_channel channel,
void dss_mgr_disconnect(enum omap_channel channel,
struct omap_dss_device *dst);
void dss_mgr_set_timings(enum omap_channel channel,
- const struct omap_video_timings *timings);
+ const struct videomode *vm);
void dss_mgr_set_lcd_config(enum omap_channel channel,
const struct dss_lcd_mgr_config *config);
int dss_mgr_enable(enum omap_channel channel);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 24f859488201..a901af5a9bc3 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -201,10 +201,9 @@ void dss_mgr_disconnect(enum omap_channel channel,
}
EXPORT_SYMBOL(dss_mgr_disconnect);
-void dss_mgr_set_timings(enum omap_channel channel,
- const struct omap_video_timings *timings)
+void dss_mgr_set_timings(enum omap_channel channel, const struct videomode *vm)
{
- dss_mgr_ops->set_timings(channel, timings);
+ dss_mgr_ops->set_timings(channel, vm);
}
EXPORT_SYMBOL(dss_mgr_set_timings);
diff --git a/drivers/gpu/drm/omapdrm/dss/rfbi.c b/drivers/gpu/drm/omapdrm/dss/rfbi.c
index cd53566d75eb..09724757366a 100644
--- a/drivers/gpu/drm/omapdrm/dss/rfbi.c
+++ b/drivers/gpu/drm/omapdrm/dss/rfbi.c
@@ -113,7 +113,7 @@ static struct {
struct semaphore bus_lock;
- struct omap_video_timings timings;
+ struct videomode vm;
int pixel_size;
int data_lines;
struct rfbi_timings intf_timings;
@@ -308,15 +308,15 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
u32 l;
int r;
struct omap_overlay_manager *mgr = rfbi.output.manager;
- u16 width = rfbi.timings.x_res;
- u16 height = rfbi.timings.y_res;
+ u16 width = rfbi.vm.hactive;
+ u16 height = rfbi.vm.vactive;
/*BUG_ON(callback == 0);*/
BUG_ON(rfbi.framedone_callback != NULL);
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
- dss_mgr_set_timings(mgr, &rfbi.timings);
+ dss_mgr_set_timings(mgr, &rfbi.vm);
r = dss_mgr_enable(mgr);
if (r)
@@ -777,8 +777,8 @@ static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
{
- rfbi.timings.x_res = w;
- rfbi.timings.y_res = h;
+ rfbi.vm.hactive = w;
+ rfbi.vm.vactive = h;
}
static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
@@ -854,25 +854,30 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
dss_mgr_set_lcd_config(mgr, &mgr_config);
/*
- * Set rfbi.timings with default values, the x_res and y_res fields
+ * Set rfbi.timings with default values, the hactive and vactive fields
* are expected to be already configured by the panel driver via
* omapdss_rfbi_set_size()
*/
- rfbi.timings.hsw = 1;
- rfbi.timings.hfp = 1;
- rfbi.timings.hbp = 1;
- rfbi.timings.vsw = 1;
- rfbi.timings.vfp = 0;
- rfbi.timings.vbp = 0;
-
- rfbi.timings.interlace = false;
- rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
- rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-
- dss_mgr_set_timings(mgr, &rfbi.timings);
+ rfbi.vm.hsync_len = 1;
+ rfbi.vm.hfront_porch = 1;
+ rfbi.vm.hback_porch = 1;
+ rfbi.vm.vsync_len = 1;
+ rfbi.vm.vfront_porch = 0;
+ rfbi.vm.vback_porch = 0;
+
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
+ rfbi.vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
+ rfbi.vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ rfbi.vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+ rfbi.vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+ rfbi.vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+ rfbi.vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
+
+ dss_mgr_set_timings(mgr, &rfbi.vm);
}
static int rfbi_display_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 0a96c321ce62..b3bda2d3c08d 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -39,7 +39,7 @@ static struct {
struct regulator *vdds_sdi_reg;
struct dss_lcd_mgr_config mgr_config;
- struct omap_video_timings timings;
+ struct videomode vm;
int datapairs;
struct omap_dss_device output;
@@ -131,7 +131,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &sdi.output;
enum omap_channel channel = dssdev->dispc_channel;
- struct omap_video_timings *t = &sdi.timings;
+ struct videomode *vm = &sdi.vm;
unsigned long fck;
struct dispc_clock_info dispc_cinfo;
unsigned long pck;
@@ -151,10 +151,9 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
goto err_get_dispc;
/* 15.5.9.1.2 */
- t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE;
- r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
+ r = sdi_calc_clock_div(vm->pixelclock, &fck, &dispc_cinfo);
if (r)
goto err_calc_clock_div;
@@ -162,15 +161,15 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
- if (pck != t->pixelclock) {
- DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
- t->pixelclock, pck);
+ if (pck != vm->pixelclock) {
+ DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
+ vm->pixelclock, pck);
- t->pixelclock = pck;
+ vm->pixelclock = pck;
}
- dss_mgr_set_timings(channel, t);
+ dss_mgr_set_timings(channel, vm);
r = dss_set_fck_rate(fck);
if (r)
@@ -229,26 +228,26 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
}
static void sdi_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- sdi.timings = *timings;
+ sdi.vm = *vm;
}
static void sdi_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
- *timings = sdi.timings;
+ *vm = sdi.vm;
}
static int sdi_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
enum omap_channel channel = dssdev->dispc_channel;
- if (!dispc_mgr_timings_ok(channel, timings))
+ if (!dispc_mgr_timings_ok(channel, vm))
return -EINVAL;
- if (timings->pixelclock == 0)
+ if (vm->pixelclock == 0)
return -EINVAL;
return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 6eedf2118708..d74f7fcc2e46 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -262,47 +262,41 @@ static const struct venc_config venc_config_pal_bdghi = {
.fid_ext_start_y__fid_ext_offset_y = 0x01380005,
};
-const struct omap_video_timings omap_dss_pal_timings = {
- .x_res = 720,
- .y_res = 574,
+const struct videomode omap_dss_pal_vm = {
+ .hactive = 720,
+ .vactive = 574,
.pixelclock = 13500000,
- .hsw = 64,
- .hfp = 12,
- .hbp = 68,
- .vsw = 5,
- .vfp = 5,
- .vbp = 41,
-
- .interlace = true,
-
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .hsync_len = 64,
+ .hfront_porch = 12,
+ .hback_porch = 68,
+ .vsync_len = 5,
+ .vfront_porch = 5,
+ .vback_porch = 41,
+
+ .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_NEGEDGE,
};
-EXPORT_SYMBOL(omap_dss_pal_timings);
+EXPORT_SYMBOL(omap_dss_pal_vm);
-const struct omap_video_timings omap_dss_ntsc_timings = {
- .x_res = 720,
- .y_res = 482,
+const struct videomode omap_dss_ntsc_vm = {
+ .hactive = 720,
+ .vactive = 482,
.pixelclock = 13500000,
- .hsw = 64,
- .hfp = 16,
- .hbp = 58,
- .vsw = 6,
- .vfp = 6,
- .vbp = 31,
-
- .interlace = true,
-
- .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
- .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
- .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
- .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+ .hsync_len = 64,
+ .hfront_porch = 16,
+ .hback_porch = 58,
+ .vsync_len = 6,
+ .vfront_porch = 6,
+ .vback_porch = 31,
+
+ .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_NEGEDGE,
};
-EXPORT_SYMBOL(omap_dss_ntsc_timings);
+EXPORT_SYMBOL(omap_dss_ntsc_vm);
static struct {
struct platform_device *pdev;
@@ -313,7 +307,7 @@ static struct {
struct clk *tv_dac_clk;
- struct omap_video_timings timings;
+ struct videomode vm;
enum omap_dss_venc_type type;
bool invert_polarity;
@@ -427,13 +421,12 @@ static void venc_runtime_put(void)
WARN_ON(r < 0 && r != -ENOSYS);
}
-static const struct venc_config *venc_timings_to_config(
- struct omap_video_timings *timings)
+static const struct venc_config *venc_timings_to_config(struct videomode *vm)
{
- if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+ if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
return &venc_config_pal_trm;
- if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+ if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
return &venc_config_ntsc_trm;
BUG();
@@ -451,7 +444,7 @@ static int venc_power_on(struct omap_dss_device *dssdev)
goto err0;
venc_reset();
- venc_write_config(venc_timings_to_config(&venc.timings));
+ venc_write_config(venc_timings_to_config(&venc.vm));
dss_set_venc_output(venc.type);
dss_set_dac_pwrdn_bgz(1);
@@ -468,7 +461,7 @@ static int venc_power_on(struct omap_dss_device *dssdev)
venc_write_reg(VENC_OUTPUT_CONTROL, l);
- dss_mgr_set_timings(channel, &venc.timings);
+ dss_mgr_set_timings(channel, &venc.vm);
r = regulator_enable(venc.vdda_dac_reg);
if (r)
@@ -546,17 +539,17 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
}
static void venc_set_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
DSSDBG("venc_set_timings\n");
mutex_lock(&venc.venc_lock);
/* Reset WSS data when the TV standard changes. */
- if (memcmp(&venc.timings, timings, sizeof(*timings)))
+ if (memcmp(&venc.vm, vm, sizeof(*vm)))
venc.wss_data = 0;
- venc.timings = *timings;
+ venc.vm = *vm;
dispc_set_tv_pclk(13500000);
@@ -564,25 +557,25 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
}
static int venc_check_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
DSSDBG("venc_check_timings\n");
- if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+ if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
return 0;
- if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+ if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
return 0;
return -EINVAL;
}
static void venc_get_timings(struct omap_dss_device *dssdev,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
mutex_lock(&venc.venc_lock);
- *timings = venc.timings;
+ *vm = venc.vm;
mutex_unlock(&venc.venc_lock);
}
@@ -602,7 +595,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
mutex_lock(&venc.venc_lock);
- config = venc_timings_to_config(&venc.timings);
+ config = venc_timings_to_config(&venc.vm);
/* Invert due to VENC_L21_WC_CTL:INV=1 */
venc.wss_data = (wss ^ 0xfffff) << 8;
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 137fe690a0da..2580e8673908 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -42,73 +42,6 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
return omap_connector->hdmi_mode;
}
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
- struct omap_video_timings *timings)
-{
- mode->clock = timings->pixelclock / 1000;
-
- mode->hdisplay = timings->x_res;
- mode->hsync_start = mode->hdisplay + timings->hfp;
- mode->hsync_end = mode->hsync_start + timings->hsw;
- mode->htotal = mode->hsync_end + timings->hbp;
-
- mode->vdisplay = timings->y_res;
- mode->vsync_start = mode->vdisplay + timings->vfp;
- mode->vsync_end = mode->vsync_start + timings->vsw;
- mode->vtotal = mode->vsync_end + timings->vbp;
-
- mode->flags = 0;
-
- if (timings->interlace)
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
- if (timings->double_pixel)
- mode->flags |= DRM_MODE_FLAG_DBLCLK;
-
- if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- mode->flags |= DRM_MODE_FLAG_PHSYNC;
- else
- mode->flags |= DRM_MODE_FLAG_NHSYNC;
-
- if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- mode->flags |= DRM_MODE_FLAG_PVSYNC;
- else
- mode->flags |= DRM_MODE_FLAG_NVSYNC;
-}
-
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
- struct drm_display_mode *mode)
-{
- timings->pixelclock = mode->clock * 1000;
-
- timings->x_res = mode->hdisplay;
- timings->hfp = mode->hsync_start - mode->hdisplay;
- timings->hsw = mode->hsync_end - mode->hsync_start;
- timings->hbp = mode->htotal - mode->hsync_end;
-
- timings->y_res = mode->vdisplay;
- timings->vfp = mode->vsync_start - mode->vdisplay;
- timings->vsw = mode->vsync_end - mode->vsync_start;
- timings->vbp = mode->vtotal - mode->vsync_end;
-
- timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
- timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK);
-
- if (mode->flags & DRM_MODE_FLAG_PHSYNC)
- timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- else
- timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
- if (mode->flags & DRM_MODE_FLAG_PVSYNC)
- timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- else
- timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
- timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
- timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-}
-
static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
{
@@ -185,11 +118,11 @@ static int omap_connector_get_modes(struct drm_connector *connector)
kfree(edid);
} else {
struct drm_display_mode *mode = drm_mode_create(dev);
- struct omap_video_timings timings = {0};
+ struct videomode vm = {0};
- dssdrv->get_timings(dssdev, &timings);
+ dssdrv->get_timings(dssdev, &vm);
- copy_timings_omap_to_drm(mode, &timings);
+ drm_display_mode_from_videomode(&vm, mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_set_name(mode);
@@ -207,12 +140,14 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
struct omap_dss_driver *dssdrv = dssdev->driver;
- struct omap_video_timings timings = {0};
+ struct videomode vm = {0};
struct drm_device *dev = connector->dev;
struct drm_display_mode *new_mode;
int r, ret = MODE_BAD;
- copy_timings_drm_to_omap(&timings, mode);
+ drm_display_mode_to_videomode(mode, &vm);
+ vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_NEGEDGE;
mode->vrefresh = drm_mode_vrefresh(mode);
/*
@@ -221,13 +156,13 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
* panel's timings
*/
if (dssdrv->check_timings) {
- r = dssdrv->check_timings(dssdev, &timings);
+ r = dssdrv->check_timings(dssdev, &vm);
} else {
- struct omap_video_timings t = {0};
+ struct videomode t = {0};
dssdrv->get_timings(dssdev, &t);
- if (memcmp(&timings, &t, sizeof(struct omap_video_timings)))
+ if (memcmp(&vm, &t, sizeof(struct videomode)))
r = -EINVAL;
else
r = 0;
@@ -236,7 +171,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
if (!r) {
/* check if vrefresh is still valid */
new_mode = drm_mode_duplicate(dev, mode);
- new_mode->clock = timings.pixelclock / 1000;
+ new_mode->clock = vm.pixelclock / 1000;
new_mode->vrefresh = 0;
if (mode->vrefresh == drm_mode_vrefresh(new_mode))
ret = MODE_OK;
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 180f644e861e..8dea89030e66 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -34,7 +34,7 @@ struct omap_crtc {
const char *name;
enum omap_channel channel;
- struct omap_video_timings timings;
+ struct videomode vm;
struct omap_drm_irq vblank_irq;
struct omap_drm_irq error_irq;
@@ -56,10 +56,10 @@ uint32_t pipe2vbl(struct drm_crtc *crtc)
return dispc_mgr_get_vsync_irq(omap_crtc->channel);
}
-struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
+struct videomode *omap_crtc_timings(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- return &omap_crtc->timings;
+ return &omap_crtc->vm;
}
enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
@@ -201,7 +201,7 @@ static int omap_crtc_dss_enable(enum omap_channel channel)
dispc_mgr_setup(omap_crtc->channel, &info);
dispc_mgr_set_timings(omap_crtc->channel,
- &omap_crtc->timings);
+ &omap_crtc->vm);
omap_crtc_set_enabled(&omap_crtc->base, true);
return 0;
@@ -215,11 +215,11 @@ static void omap_crtc_dss_disable(enum omap_channel channel)
}
static void omap_crtc_dss_set_timings(enum omap_channel channel,
- const struct omap_video_timings *timings)
+ const struct videomode *vm)
{
struct omap_crtc *omap_crtc = omap_crtcs[channel];
DBG("%s", omap_crtc->name);
- omap_crtc->timings = *timings;
+ omap_crtc->vm = *vm;
}
static void omap_crtc_dss_set_lcd_config(enum omap_channel channel,
@@ -369,7 +369,10 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal,
mode->type, mode->flags);
- copy_timings_drm_to_omap(&omap_crtc->timings, mode);
+ drm_display_mode_to_videomode(mode, &omap_crtc->vm);
+ omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH |
+ DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_NEGEDGE;
}
static int omap_crtc_atomic_check(struct drm_crtc *crtc,
@@ -411,19 +414,6 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
}
- if (crtc->state->color_mgmt_changed) {
- struct drm_color_lut *lut = NULL;
- uint length = 0;
-
- if (crtc->state->gamma_lut) {
- lut = (struct drm_color_lut *)
- crtc->state->gamma_lut->data;
- length = crtc->state->gamma_lut->length /
- sizeof(*lut);
- }
- dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
- }
-
if (dispc_mgr_is_enabled(omap_crtc->channel)) {
DBG("%s: GO", omap_crtc->name);
@@ -438,13 +428,14 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
}
}
-static bool omap_crtc_is_plane_prop(struct drm_device *dev,
+static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc,
struct drm_property *property)
{
+ struct drm_device *dev = crtc->dev;
struct omap_drm_private *priv = dev->dev_private;
return property == priv->zorder_prop ||
- property == dev->mode_config.rotation_property;
+ property == crtc->primary->rotation_property;
}
static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
@@ -452,9 +443,7 @@ static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
struct drm_property *property,
uint64_t val)
{
- struct drm_device *dev = crtc->dev;
-
- if (omap_crtc_is_plane_prop(dev, property)) {
+ if (omap_crtc_is_plane_prop(crtc, property)) {
struct drm_plane_state *plane_state;
struct drm_plane *plane = crtc->primary;
@@ -479,9 +468,7 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc,
struct drm_property *property,
uint64_t *val)
{
- struct drm_device *dev = crtc->dev;
-
- if (omap_crtc_is_plane_prop(dev, property)) {
+ if (omap_crtc_is_plane_prop(crtc, property)) {
/*
* Delegate property get to the primary plane. The
* drm_atomic_plane_get_property() function isn't exported, but
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index e1cfba51cff6..fdc83cbcde61 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -105,7 +105,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
dispc_runtime_put();
- drm_atomic_state_free(old_state);
+ drm_atomic_state_put(old_state);
/* Complete the commit, wake up any waiter. */
spin_lock(&priv->commit.lock);
@@ -176,6 +176,7 @@ static int omap_atomic_commit(struct drm_device *dev,
/* Swap the state, this is the point of no return. */
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (nonblock)
schedule_work(&commit->work);
else
@@ -266,13 +267,15 @@ cleanup:
}
static int omap_modeset_create_crtc(struct drm_device *dev, int id,
- enum omap_channel channel)
+ enum omap_channel channel,
+ u32 possible_crtcs)
{
struct omap_drm_private *priv = dev->dev_private;
struct drm_plane *plane;
struct drm_crtc *crtc;
- plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY);
+ plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY,
+ possible_crtcs);
if (IS_ERR(plane))
return PTR_ERR(plane);
@@ -292,16 +295,6 @@ static int omap_modeset_init_properties(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
- if (priv->has_dmm) {
- dev->mode_config.rotation_property =
- drm_mode_create_rotation_property(dev,
- DRM_ROTATE_0 | DRM_ROTATE_90 |
- DRM_ROTATE_180 | DRM_ROTATE_270 |
- DRM_REFLECT_X | DRM_REFLECT_Y);
- if (!dev->mode_config.rotation_property)
- return -ENOMEM;
- }
-
priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
if (!priv->zorder_prop)
return -ENOMEM;
@@ -318,6 +311,7 @@ static int omap_modeset_init(struct drm_device *dev)
int num_crtcs;
int i, id = 0;
int ret;
+ u32 possible_crtcs;
drm_mode_config_init(dev);
@@ -334,6 +328,7 @@ static int omap_modeset_init(struct drm_device *dev)
* We use the num_crtc argument to limit the number of crtcs we create.
*/
num_crtcs = min3(num_crtc, num_mgrs, num_ovls);
+ possible_crtcs = (1 << num_crtcs) - 1;
dssdev = NULL;
@@ -397,7 +392,8 @@ static int omap_modeset_init(struct drm_device *dev)
* allocated crtc, we create a new crtc for it
*/
if (!channel_used(dev, channel)) {
- ret = omap_modeset_create_crtc(dev, id, channel);
+ ret = omap_modeset_create_crtc(dev, id, channel,
+ possible_crtcs);
if (ret < 0) {
dev_err(dev->dev,
"could not create CRTC (channel %u)\n",
@@ -427,7 +423,8 @@ static int omap_modeset_init(struct drm_device *dev)
return -ENOMEM;
}
- ret = omap_modeset_create_crtc(dev, id, i);
+ ret = omap_modeset_create_crtc(dev, id, i,
+ possible_crtcs);
if (ret < 0) {
dev_err(dev->dev,
"could not create CRTC (channel %u)\n", i);
@@ -441,7 +438,8 @@ static int omap_modeset_init(struct drm_device *dev)
for (; id < num_ovls; id++) {
struct drm_plane *plane;
- plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY);
+ plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY,
+ possible_crtcs);
if (IS_ERR(plane))
return PTR_ERR(plane);
@@ -752,22 +750,32 @@ static void dev_lastclose(struct drm_device *dev)
DBG("lastclose: dev=%p", dev);
- if (dev->mode_config.rotation_property) {
- /* need to restore default rotation state.. not sure
- * if there is a cleaner way to restore properties to
- * default state? Maybe a flag that properties should
- * automatically be restored to default state on
- * lastclose?
- */
- for (i = 0; i < priv->num_crtcs; i++) {
- drm_object_property_set_value(&priv->crtcs[i]->base,
- dev->mode_config.rotation_property, 0);
- }
+ /* need to restore default rotation state.. not sure
+ * if there is a cleaner way to restore properties to
+ * default state? Maybe a flag that properties should
+ * automatically be restored to default state on
+ * lastclose?
+ */
+ for (i = 0; i < priv->num_crtcs; i++) {
+ struct drm_crtc *crtc = priv->crtcs[i];
- for (i = 0; i < priv->num_planes; i++) {
- drm_object_property_set_value(&priv->planes[i]->base,
- dev->mode_config.rotation_property, 0);
- }
+ if (!crtc->primary->rotation_property)
+ continue;
+
+ drm_object_property_set_value(&crtc->base,
+ crtc->primary->rotation_property,
+ DRM_ROTATE_0);
+ }
+
+ for (i = 0; i < priv->num_planes; i++) {
+ struct drm_plane *plane = priv->planes[i];
+
+ if (!plane->rotation_property)
+ continue;
+
+ drm_object_property_set_value(&plane->base,
+ plane->rotation_property,
+ DRM_ROTATE_0);
}
if (priv->fbdev) {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index dcc30a98b9d4..7d9dd5400cef 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -148,7 +148,7 @@ static inline void omap_fbdev_free(struct drm_device *dev)
}
#endif
-struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
+struct videomode *omap_crtc_timings(struct drm_crtc *crtc);
enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
void omap_crtc_pre_init(void);
void omap_crtc_pre_uninit(void);
@@ -157,7 +157,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
int omap_crtc_wait_pending(struct drm_crtc *crtc);
struct drm_plane *omap_plane_init(struct drm_device *dev,
- int id, enum drm_plane_type type);
+ int id, enum drm_plane_type type,
+ u32 possible_crtcs);
void omap_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj);
@@ -171,11 +172,6 @@ struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
- struct omap_video_timings *timings);
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
- struct drm_display_mode *mode);
-
uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
uint32_t max_formats, enum omap_color_mode supported_modes);
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 0bbb9c59622e..a20f30039aee 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -102,7 +102,7 @@ static void omap_encoder_disable(struct drm_encoder *encoder)
static int omap_encoder_update(struct drm_encoder *encoder,
enum omap_channel channel,
- struct omap_video_timings *timings)
+ struct videomode *vm)
{
struct drm_device *dev = encoder->dev;
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
@@ -111,13 +111,13 @@ static int omap_encoder_update(struct drm_encoder *encoder,
int ret;
if (dssdrv->check_timings) {
- ret = dssdrv->check_timings(dssdev, timings);
+ ret = dssdrv->check_timings(dssdev, vm);
} else {
- struct omap_video_timings t = {0};
+ struct videomode t = {0};
dssdrv->get_timings(dssdev, &t);
- if (memcmp(timings, &t, sizeof(struct omap_video_timings)))
+ if (memcmp(vm, &t, sizeof(struct videomode)))
ret = -EINVAL;
else
ret = 0;
@@ -129,7 +129,7 @@ static int omap_encoder_update(struct drm_encoder *encoder,
}
if (dssdrv->set_timings)
- dssdrv->set_timings(dssdev, timings);
+ dssdrv->set_timings(dssdev, vm);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index adb10fbe918d..8d8ac173f55d 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -82,6 +82,7 @@ fallback:
static struct fb_ops omap_fb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
/* Note: to properly handle manual update displays, we wrap the
* basic fbdev ops which write to the framebuffer
@@ -92,11 +93,7 @@ static struct fb_ops omap_fb_ops = {
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
.fb_pan_display = omap_fbdev_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
};
static int omap_fbdev_create(struct drm_fb_helper *helper,
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 505dee0db973..d4e1e11466f8 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -336,8 +336,10 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
int i, npages = obj->size >> PAGE_SHIFT;
for (i = 0; i < npages; i++) {
- dma_unmap_page(obj->dev->dev, omap_obj->addrs[i],
- PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (omap_obj->addrs[i])
+ dma_unmap_page(obj->dev->dev,
+ omap_obj->addrs[i],
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
}
}
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 66ac8c40db26..82b2c23d6769 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -108,16 +108,12 @@ 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 & DRM_ROTATE_MASK) {
- case DRM_ROTATE_90:
- case DRM_ROTATE_270:
+ if (drm_rotation_90_or_270(state->rotation)) {
win.src_w = state->src_h >> 16;
win.src_h = state->src_w >> 16;
- break;
- default:
+ } else {
win.src_w = state->src_w >> 16;
win.src_h = state->src_h >> 16;
- break;
}
/* update scanout: */
@@ -135,7 +131,9 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
/* and finally, update omapdss: */
ret = dispc_ovl_setup(omap_plane->id, &info, false,
omap_crtc_timings(state->crtc), false);
- if (WARN_ON(ret)) {
+ if (ret) {
+ dev_err(plane->dev->dev, "Failed to setup plane %s\n",
+ omap_plane->name);
dispc_ovl_enable(omap_plane->id, false);
return;
}
@@ -161,12 +159,20 @@ static int omap_plane_atomic_check(struct drm_plane *plane,
{
struct drm_crtc_state *crtc_state;
- if (!state->crtc)
+ if (!state->fb)
return 0;
- crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
- if (IS_ERR(crtc_state))
- return PTR_ERR(crtc_state);
+ /* crtc should only be NULL when disabling (i.e., !state->fb) */
+ if (WARN_ON(!state->crtc))
+ return 0;
+
+ crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
+ /* we should have a crtc state if the plane is attached to a crtc */
+ if (WARN_ON(!crtc_state))
+ return 0;
+
+ if (!crtc_state->enable)
+ return 0;
if (state->crtc_x < 0 || state->crtc_y < 0)
return -EINVAL;
@@ -177,11 +183,9 @@ static int omap_plane_atomic_check(struct drm_plane *plane,
if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay)
return -EINVAL;
- if (state->fb) {
- if (state->rotation != DRM_ROTATE_0 &&
- !omap_framebuffer_supports_rotation(state->fb))
- return -EINVAL;
- }
+ if (state->rotation != DRM_ROTATE_0 &&
+ !omap_framebuffer_supports_rotation(state->fb))
+ return -EINVAL;
return 0;
}
@@ -215,9 +219,17 @@ void omap_plane_install_properties(struct drm_plane *plane,
struct omap_drm_private *priv = dev->dev_private;
if (priv->has_dmm) {
- struct drm_property *prop = dev->mode_config.rotation_property;
-
- drm_object_attach_property(obj, prop, 0);
+ if (!plane->rotation_property)
+ drm_plane_create_rotation_property(plane,
+ DRM_ROTATE_0,
+ DRM_ROTATE_0 | DRM_ROTATE_90 |
+ DRM_ROTATE_180 | DRM_ROTATE_270 |
+ DRM_REFLECT_X | DRM_REFLECT_Y);
+
+ /* Attach the rotation property also to the crtc object */
+ if (plane->rotation_property && obj != &plane->base)
+ drm_object_attach_property(obj, plane->rotation_property,
+ DRM_ROTATE_0);
}
drm_object_attach_property(obj, priv->zorder_prop, 0);
@@ -344,9 +356,9 @@ static const uint32_t error_irqs[] = {
/* initialize plane */
struct drm_plane *omap_plane_init(struct drm_device *dev,
- int id, enum drm_plane_type type)
+ int id, enum drm_plane_type type,
+ u32 possible_crtcs)
{
- struct omap_drm_private *priv = dev->dev_private;
struct drm_plane *plane;
struct omap_plane *omap_plane;
int ret;
@@ -369,7 +381,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
omap_plane->error_irq.irq = omap_plane_error_irq;
omap_irq_register(dev, &omap_plane->error_irq);
- ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1,
+ ret = drm_universal_plane_init(dev, plane, possible_crtcs,
&omap_plane_funcs, omap_plane->formats,
omap_plane->nformats, type, NULL);
if (ret < 0)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 113db3c4a633..06aaf79de8c8 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -120,7 +120,7 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
mode->type |= DRM_MODE_TYPE_DRIVER;
- if (panel->desc->num_modes == 1)
+ if (panel->desc->num_timings == 1)
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
@@ -555,6 +555,91 @@ static const struct panel_desc auo_b133htn01 = {
},
};
+static const struct display_timing auo_g133han01_timings = {
+ .pixelclock = { 134000000, 141200000, 149000000 },
+ .hactive = { 1920, 1920, 1920 },
+ .hfront_porch = { 39, 58, 77 },
+ .hback_porch = { 59, 88, 117 },
+ .hsync_len = { 28, 42, 56 },
+ .vactive = { 1080, 1080, 1080 },
+ .vfront_porch = { 3, 8, 11 },
+ .vback_porch = { 5, 14, 19 },
+ .vsync_len = { 4, 14, 19 },
+};
+
+static const struct panel_desc auo_g133han01 = {
+ .timings = &auo_g133han01_timings,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 293,
+ .height = 165,
+ },
+ .delay = {
+ .prepare = 200,
+ .enable = 50,
+ .disable = 50,
+ .unprepare = 1000,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+};
+
+static const struct display_timing auo_g185han01_timings = {
+ .pixelclock = { 120000000, 144000000, 175000000 },
+ .hactive = { 1920, 1920, 1920 },
+ .hfront_porch = { 18, 60, 74 },
+ .hback_porch = { 12, 44, 54 },
+ .hsync_len = { 10, 24, 32 },
+ .vactive = { 1080, 1080, 1080 },
+ .vfront_porch = { 6, 10, 40 },
+ .vback_porch = { 2, 5, 20 },
+ .vsync_len = { 2, 5, 20 },
+};
+
+static const struct panel_desc auo_g185han01 = {
+ .timings = &auo_g185han01_timings,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 409,
+ .height = 230,
+ },
+ .delay = {
+ .prepare = 50,
+ .enable = 200,
+ .disable = 110,
+ .unprepare = 1000,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
+static const struct drm_display_mode auo_t215hvn01_mode = {
+ .clock = 148800,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 88,
+ .hsync_end = 1920 + 88 + 44,
+ .htotal = 1920 + 88 + 44 + 148,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 4,
+ .vsync_end = 1080 + 4 + 5,
+ .vtotal = 1080 + 4 + 5 + 36,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc auo_t215hvn01 = {
+ .modes = &auo_t215hvn01_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 430,
+ .height = 270,
+ },
+ .delay = {
+ .disable = 5,
+ .unprepare = 1000,
+ }
+};
+
static const struct drm_display_mode avic_tm070ddh03_mode = {
.clock = 51200,
.hdisplay = 1024,
@@ -583,6 +668,30 @@ static const struct panel_desc avic_tm070ddh03 = {
},
};
+static const struct drm_display_mode chunghwa_claa070wp03xg_mode = {
+ .clock = 66770,
+ .hdisplay = 800,
+ .hsync_start = 800 + 49,
+ .hsync_end = 800 + 49 + 33,
+ .htotal = 800 + 49 + 33 + 17,
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 1,
+ .vsync_end = 1280 + 1 + 7,
+ .vtotal = 1280 + 1 + 7 + 15,
+ .vrefresh = 60,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc chunghwa_claa070wp03xg = {
+ .modes = &chunghwa_claa070wp03xg_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 94,
+ .height = 150,
+ },
+};
+
static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
.clock = 72070,
.hdisplay = 1366,
@@ -877,27 +986,31 @@ static const struct panel_desc innolux_g101ice_l01 = {
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
};
-static const struct drm_display_mode innolux_g121i1_l01_mode = {
- .clock = 71000,
- .hdisplay = 1280,
- .hsync_start = 1280 + 64,
- .hsync_end = 1280 + 64 + 32,
- .htotal = 1280 + 64 + 32 + 64,
- .vdisplay = 800,
- .vsync_start = 800 + 9,
- .vsync_end = 800 + 9 + 6,
- .vtotal = 800 + 9 + 6 + 9,
- .vrefresh = 60,
+static const struct display_timing innolux_g121i1_l01_timing = {
+ .pixelclock = { 67450000, 71000000, 74550000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 40, 80, 160 },
+ .hback_porch = { 39, 79, 159 },
+ .hsync_len = { 1, 1, 1 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 5, 11, 100 },
+ .vback_porch = { 4, 11, 99 },
+ .vsync_len = { 1, 1, 1 },
};
static const struct panel_desc innolux_g121i1_l01 = {
- .modes = &innolux_g121i1_l01_mode,
- .num_modes = 1,
+ .timings = &innolux_g121i1_l01_timing,
+ .num_timings = 1,
.bpc = 6,
.size = {
.width = 261,
.height = 163,
},
+ .delay = {
+ .enable = 200,
+ .disable = 20,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
};
static const struct drm_display_mode innolux_g121x1_l03_mode = {
@@ -1164,6 +1277,29 @@ static const struct panel_desc nec_nl4827hc19_05b = {
.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
};
+static const struct drm_display_mode nvd_9128_mode = {
+ .clock = 29500,
+ .hdisplay = 800,
+ .hsync_start = 800 + 130,
+ .hsync_end = 800 + 130 + 98,
+ .htotal = 800 + 0 + 130 + 98,
+ .vdisplay = 480,
+ .vsync_start = 480 + 10,
+ .vsync_end = 480 + 10 + 50,
+ .vtotal = 480 + 0 + 10 + 50,
+};
+
+static const struct panel_desc nvd_9128 = {
+ .modes = &nvd_9128_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 156,
+ .height = 88,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
static const struct display_timing okaya_rs800480t_7x0gp_timing = {
.pixelclock = { 30000000, 30000000, 40000000 },
.hactive = { 800, 800, 800 },
@@ -1409,6 +1545,7 @@ static const struct drm_display_mode sharp_lq123p1jx31_mode = {
static const struct panel_desc sharp_lq123p1jx31 = {
.modes = &sharp_lq123p1jx31_mode,
.num_modes = 1,
+ .bpc = 8,
.size = {
.width = 259,
.height = 173,
@@ -1420,6 +1557,30 @@ static const struct panel_desc sharp_lq123p1jx31 = {
},
};
+static const struct drm_display_mode sharp_lq150x1lg11_mode = {
+ .clock = 71100,
+ .hdisplay = 1024,
+ .hsync_start = 1024 + 168,
+ .hsync_end = 1024 + 168 + 64,
+ .htotal = 1024 + 168 + 64 + 88,
+ .vdisplay = 768,
+ .vsync_start = 768 + 37,
+ .vsync_end = 768 + 37 + 2,
+ .vtotal = 768 + 37 + 2 + 8,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc sharp_lq150x1lg11 = {
+ .modes = &sharp_lq150x1lg11_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 304,
+ .height = 228,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB565_1X16,
+};
+
static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
.clock = 33300,
.hdisplay = 800,
@@ -1575,9 +1736,21 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "auo,b133xtn01",
.data = &auo_b133xtn01,
}, {
+ .compatible = "auo,g133han01",
+ .data = &auo_g133han01,
+ }, {
+ .compatible = "auo,g185han01",
+ .data = &auo_g185han01,
+ }, {
+ .compatible = "auo,t215hvn01",
+ .data = &auo_t215hvn01,
+ }, {
.compatible = "avic,tm070ddh03",
.data = &avic_tm070ddh03,
}, {
+ .compatible = "chunghwa,claa070wp03xg",
+ .data = &chunghwa_claa070wp03xg,
+ }, {
.compatible = "chunghwa,claa101wa01a",
.data = &chunghwa_claa101wa01a
}, {
@@ -1653,6 +1826,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "nec,nl4827hc19-05b",
.data = &nec_nl4827hc19_05b,
}, {
+ .compatible = "nvd,9128",
+ .data = &nvd_9128,
+ }, {
.compatible = "okaya,rs800480t-7x0gp",
.data = &okaya_rs800480t_7x0gp,
}, {
@@ -1683,6 +1859,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "sharp,lq123p1jx31",
.data = &sharp_lq123p1jx31,
}, {
+ .compatible = "sharp,lq150x1lg11",
+ .data = &sharp_lq150x1lg11,
+ }, {
.compatible = "shelly,sca07010-bfn-lnn",
.data = &shelly_sca07010_bfn_lnn,
}, {
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 04270f5d110c..74fc9362ecf9 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -578,7 +578,7 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
return 0;
}
-int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf)
+static int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf)
{
struct qxl_rect rect;
int ret;
diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c
index 6911b8c44492..241af9131dc8 100644
--- a/drivers/gpu/drm/qxl/qxl_debugfs.c
+++ b/drivers/gpu/drm/qxl/qxl_debugfs.c
@@ -123,9 +123,6 @@ int qxl_debugfs_add_files(struct qxl_device *qdev,
qdev->debugfs_count = i;
#if defined(CONFIG_DEBUG_FS)
drm_debugfs_create_files(files, nfiles,
- qdev->ddev->control->debugfs_root,
- qdev->ddev->control);
- drm_debugfs_create_files(files, nfiles,
qdev->ddev->primary->debugfs_root,
qdev->ddev->primary);
#endif
@@ -140,9 +137,6 @@ void qxl_debugfs_remove_files(struct qxl_device *qdev)
for (i = 0; i < qdev->debugfs_count; i++) {
drm_debugfs_remove_files(qdev->debugfs[i].files,
qdev->debugfs[i].num_files,
- qdev->ddev->control);
- drm_debugfs_remove_files(qdev->debugfs[i].files,
- qdev->debugfs[i].num_files,
qdev->ddev->primary);
}
#endif
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a61c0d460ec2..4b5eab8a47b3 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -36,7 +36,7 @@ static bool qxl_head_enabled(struct qxl_head *head)
return head->width && head->height;
}
-void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
+static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
{
if (qdev->client_monitors_config &&
count > qdev->client_monitors_config->count) {
@@ -57,11 +57,18 @@ void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
qdev->client_monitors_config->count = count;
}
+enum {
+ MONITORS_CONFIG_MODIFIED,
+ MONITORS_CONFIG_UNCHANGED,
+ MONITORS_CONFIG_BAD_CRC,
+};
+
static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
{
int i;
int num_monitors;
uint32_t crc;
+ int status = MONITORS_CONFIG_UNCHANGED;
num_monitors = qdev->rom->client_monitors_config.count;
crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config,
@@ -70,7 +77,7 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
qxl_io_log(qdev, "crc mismatch: have %X (%zd) != %X\n", crc,
sizeof(qdev->rom->client_monitors_config),
qdev->rom->client_monitors_config_crc);
- return 1;
+ return MONITORS_CONFIG_BAD_CRC;
}
if (num_monitors > qdev->monitors_config->max_allowed) {
DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
@@ -79,6 +86,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
} else {
num_monitors = qdev->rom->client_monitors_config.count;
}
+ if (qdev->client_monitors_config
+ && (num_monitors != qdev->client_monitors_config->count)) {
+ status = MONITORS_CONFIG_MODIFIED;
+ }
qxl_alloc_client_monitors_config(qdev, num_monitors);
/* we copy max from the client but it isn't used */
qdev->client_monitors_config->max_allowed =
@@ -88,17 +99,39 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
&qdev->rom->client_monitors_config.heads[i];
struct qxl_head *client_head =
&qdev->client_monitors_config->heads[i];
- client_head->x = c_rect->left;
- client_head->y = c_rect->top;
- client_head->width = c_rect->right - c_rect->left;
- client_head->height = c_rect->bottom - c_rect->top;
- client_head->surface_id = 0;
- client_head->id = i;
- client_head->flags = 0;
+ if (client_head->x != c_rect->left) {
+ client_head->x = c_rect->left;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->y != c_rect->top) {
+ client_head->y = c_rect->top;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->width != c_rect->right - c_rect->left) {
+ client_head->width = c_rect->right - c_rect->left;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->height != c_rect->bottom - c_rect->top) {
+ client_head->height = c_rect->bottom - c_rect->top;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->surface_id != 0) {
+ client_head->surface_id = 0;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->id != i) {
+ client_head->id = i;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
+ if (client_head->flags != 0) {
+ client_head->flags = 0;
+ status = MONITORS_CONFIG_MODIFIED;
+ }
DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head->width, client_head->height,
client_head->x, client_head->y);
}
- return 0;
+
+ return status;
}
static void qxl_update_offset_props(struct qxl_device *qdev)
@@ -124,9 +157,18 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
{
struct drm_device *dev = qdev->ddev;
- while (qxl_display_copy_rom_client_monitors_config(qdev)) {
+ int status;
+
+ status = qxl_display_copy_rom_client_monitors_config(qdev);
+ while (status == MONITORS_CONFIG_BAD_CRC) {
qxl_io_log(qdev, "failed crc check for client_monitors_config,"
" retrying\n");
+ status = qxl_display_copy_rom_client_monitors_config(qdev);
+ }
+ if (status == MONITORS_CONFIG_UNCHANGED) {
+ qxl_io_log(qdev, "config unchanged\n");
+ DRM_DEBUG("ignoring unchanged client monitors config");
+ return;
}
drm_modeset_lock_all(dev);
@@ -157,6 +199,9 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
false);
mode->type |= DRM_MODE_TYPE_PREFERRED;
+ mode->hdisplay = head->width;
+ mode->vdisplay = head->height;
+ drm_mode_set_name(mode);
*pwidth = head->width;
*pheight = head->height;
drm_mode_probed_add(connector, mode);
@@ -607,7 +652,7 @@ static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}
-void
+static void
qxl_send_monitors_config(struct qxl_device *qdev)
{
int i;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 5f3e5ad99de7..785aad42e9bb 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -31,7 +31,7 @@
* Definitions taken from spice-protocol, plus kernel driver specific bits.
*/
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
@@ -190,7 +190,7 @@ enum {
* spice-protocol/qxl_dev.h */
#define QXL_MAX_RES 96
struct qxl_release {
- struct fence base;
+ struct dma_fence base;
int id;
int type;
@@ -395,16 +395,11 @@ qxl_framebuffer_init(struct drm_device *dev,
struct drm_gem_object *obj,
const struct drm_framebuffer_funcs *funcs);
void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
-void qxl_send_monitors_config(struct qxl_device *qdev);
int qxl_create_monitors_object(struct qxl_device *qdev);
int qxl_destroy_monitors_object(struct qxl_device *qdev);
-/* used by qxl_debugfs only */
-void qxl_crtc_set_from_monitors_config(struct qxl_device *qdev);
-void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count);
-
/* qxl_gem.c */
-int qxl_gem_init(struct qxl_device *qdev);
+void qxl_gem_init(struct qxl_device *qdev);
void qxl_gem_fini(struct qxl_device *qdev);
int qxl_gem_object_create(struct qxl_device *qdev, int size,
int alignment, int initial_domain,
@@ -574,6 +569,5 @@ int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo);
struct qxl_drv_surface *
qxl_surface_lookup(struct drm_device *dev, int surface_id);
void qxl_surface_evict(struct qxl_device *qdev, struct qxl_bo *surf, bool freeing);
-int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf);
#endif
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 2cd879a4ae15..fd7e5e94be5b 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -81,16 +81,10 @@ static struct fb_deferred_io qxl_defio = {
static struct fb_ops qxlfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -197,7 +191,7 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
/*
* we are using a shadow draw buffer, at qdev->surface0_shadow
*/
- qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2,
+ qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]\n", clips->x1, clips->x2,
clips->y1, clips->y2);
image->dx = clips->x1;
image->dy = clips->y1;
diff --git a/drivers/gpu/drm/qxl/qxl_gem.c b/drivers/gpu/drm/qxl/qxl_gem.c
index d9746e904ef1..3f185c4da5b7 100644
--- a/drivers/gpu/drm/qxl/qxl_gem.c
+++ b/drivers/gpu/drm/qxl/qxl_gem.c
@@ -111,10 +111,9 @@ void qxl_gem_object_close(struct drm_gem_object *obj,
{
}
-int qxl_gem_init(struct qxl_device *qdev)
+void qxl_gem_init(struct qxl_device *qdev)
{
INIT_LIST_HEAD(&qdev->gem.objects);
- return 0;
}
void qxl_gem_fini(struct qxl_device *qdev)
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index e642242728c0..af685f1d91f8 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -131,7 +131,7 @@ static int qxl_device_init(struct qxl_device *qdev,
mutex_init(&qdev->update_area_mutex);
mutex_init(&qdev->release_mutex);
mutex_init(&qdev->surf_evict_mutex);
- INIT_LIST_HEAD(&qdev->gem.objects);
+ qxl_gem_init(qdev);
qdev->rom_base = pci_resource_start(pdev, 2);
qdev->rom_size = pci_resource_len(pdev, 2);
@@ -273,6 +273,7 @@ static void qxl_device_fini(struct qxl_device *qdev)
qxl_ring_free(qdev->command_ring);
qxl_ring_free(qdev->cursor_ring);
qxl_ring_free(qdev->release_ring);
+ qxl_gem_fini(qdev);
qxl_bo_fini(qdev);
io_mapping_free(qdev->surface_mapping);
io_mapping_free(qdev->vram_mapping);
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index cd83f050cf3e..e6ec845b5be0 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -21,7 +21,7 @@
*/
#include "qxl_drv.h"
#include "qxl_object.h"
-#include <trace/events/fence.h>
+#include <trace/events/dma_fence.h>
/*
* drawable cmd cache - allocate a bunch of VRAM pages, suballocate
@@ -40,23 +40,24 @@
static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE };
static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO };
-static const char *qxl_get_driver_name(struct fence *fence)
+static const char *qxl_get_driver_name(struct dma_fence *fence)
{
return "qxl";
}
-static const char *qxl_get_timeline_name(struct fence *fence)
+static const char *qxl_get_timeline_name(struct dma_fence *fence)
{
return "release";
}
-static bool qxl_nop_signaling(struct fence *fence)
+static bool qxl_nop_signaling(struct dma_fence *fence)
{
/* fences are always automatically signaled, so just pretend we did this.. */
return true;
}
-static long qxl_fence_wait(struct fence *fence, bool intr, signed long timeout)
+static long qxl_fence_wait(struct dma_fence *fence, bool intr,
+ signed long timeout)
{
struct qxl_device *qdev;
struct qxl_release *release;
@@ -71,7 +72,7 @@ static long qxl_fence_wait(struct fence *fence, bool intr, signed long timeout)
retry:
sc++;
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
goto signaled;
qxl_io_notify_oom(qdev);
@@ -80,11 +81,11 @@ retry:
if (!qxl_queue_garbage_collect(qdev, true))
break;
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
goto signaled;
}
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
goto signaled;
if (have_drawable_releases || sc < 4) {
@@ -96,9 +97,9 @@ retry:
return 0;
if (have_drawable_releases && sc > 300) {
- FENCE_WARN(fence, "failed to wait on release %llu "
- "after spincount %d\n",
- fence->context & ~0xf0000000, sc);
+ DMA_FENCE_WARN(fence, "failed to wait on release %llu "
+ "after spincount %d\n",
+ fence->context & ~0xf0000000, sc);
goto signaled;
}
goto retry;
@@ -115,7 +116,7 @@ signaled:
return end - cur;
}
-static const struct fence_ops qxl_fence_ops = {
+static const struct dma_fence_ops qxl_fence_ops = {
.get_driver_name = qxl_get_driver_name,
.get_timeline_name = qxl_get_timeline_name,
.enable_signaling = qxl_nop_signaling,
@@ -133,7 +134,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
release = kmalloc(size, GFP_KERNEL);
if (!release) {
DRM_ERROR("Out of memory\n");
- return 0;
+ return -ENOMEM;
}
release->base.ops = NULL;
release->type = type;
@@ -192,8 +193,8 @@ qxl_release_free(struct qxl_device *qdev,
WARN_ON(list_empty(&release->bos));
qxl_release_free_list(release);
- fence_signal(&release->base);
- fence_put(&release->base);
+ dma_fence_signal(&release->base);
+ dma_fence_put(&release->base);
} else {
qxl_release_free_list(release);
kfree(release);
@@ -453,9 +454,9 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release)
* Since we never really allocated a context and we don't want to conflict,
* set the highest bits. This will break if we really allow exporting of dma-bufs.
*/
- fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock,
- release->id | 0xf0000000, release->base.seqno);
- trace_fence_emit(&release->base);
+ dma_fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock,
+ release->id | 0xf0000000, release->base.seqno);
+ trace_dma_fence_emit(&release->base);
driver = bdev->driver;
glob = bo->glob;
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index e26c82db948b..11761330a6b8 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -387,6 +387,7 @@ static struct ttm_bo_driver qxl_bo_driver = {
.ttm_tt_unpopulate = &qxl_ttm_tt_unpopulate,
.invalidate_caches = &qxl_invalidate_caches,
.init_mem_type = &qxl_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = &qxl_evict_flags,
.move = &qxl_bo_move,
.verify_access = &qxl_verify_access,
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 74f99bac08b1..05f4ebe31ce2 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1156,7 +1156,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
u32 tmp, viewport_w, viewport_h;
int r;
bool bypass_lut = false;
- char *format_name;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -1260,9 +1260,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
bypass_lut = true;
break;
default:
- format_name = drm_get_format_name(target_fb->pixel_format);
- DRM_ERROR("Unsupported screen format %s\n", format_name);
- kfree(format_name);
+ DRM_ERROR("Unsupported screen format %s\n",
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
@@ -1473,7 +1472,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
u32 viewport_w, viewport_h;
int r;
bool bypass_lut = false;
- char *format_name;
+ struct drm_format_name_buf format_name;
/* no fb bound */
if (!atomic && !crtc->primary->fb) {
@@ -1563,9 +1562,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
bypass_lut = true;
break;
default:
- format_name = drm_get_format_name(target_fb->pixel_format);
- DRM_ERROR("Unsupported screen format %s\n", format_name);
- kfree(format_name);
+ DRM_ERROR("Unsupported screen format %s\n",
+ drm_get_format_name(target_fb->pixel_format, &format_name));
return -EINVAL;
}
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 56bb758f4e33..fa4f8f008e4d 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -28,6 +28,7 @@
#include <drm/radeon_drm.h>
#include "radeon.h"
#include "radeon_audio.h"
+#include "radeon_asic.h"
#include "atom.h"
#include <linux/backlight.h>
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index d960d3915408..f8b05090232a 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -27,6 +27,7 @@
*/
#include <drm/drmP.h>
#include "radeon.h"
+#include "radeon_asic.h"
#include "evergreend.h"
#include "evergreen_reg_safe.h"
#include "cayman_reg_safe.h"
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index b69c8de35bd3..595a19736458 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <drm/drmP.h>
#include "radeon.h"
+#include "radeon_asic.h"
#include "r600d.h"
#include "r600_reg_safe.h"
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 1b0dcad916b0..44e0c5ed6418 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -66,7 +66,7 @@
#include <linux/kref.h>
#include <linux/interval_tree.h>
#include <linux/hashtable.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <ttm/ttm_bo_api.h>
#include <ttm/ttm_bo_driver.h>
@@ -367,7 +367,7 @@ struct radeon_fence_driver {
};
struct radeon_fence {
- struct fence base;
+ struct dma_fence base;
struct radeon_device *rdev;
uint64_t seq;
@@ -746,7 +746,7 @@ struct radeon_flip_work {
uint64_t base;
struct drm_pending_vblank_event *event;
struct radeon_bo *old_rbo;
- struct fence *fence;
+ struct dma_fence *fence;
bool async;
};
@@ -2514,9 +2514,9 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v);
/*
* Cast helper
*/
-extern const struct fence_ops radeon_fence_ops;
+extern const struct dma_fence_ops radeon_fence_ops;
-static inline struct radeon_fence *to_radeon_fence(struct fence *f)
+static inline struct radeon_fence *to_radeon_fence(struct dma_fence *f)
{
struct radeon_fence *__f = container_of(f, struct radeon_fence, base);
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 5df3ec73021b..4134759a6823 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -29,6 +29,7 @@
#include "atom.h"
#include "atom-bits.h"
+#include "radeon_asic.h"
extern void
radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 38e396dae0a9..c1135feb93c1 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -29,6 +29,7 @@
#include <drm/radeon_drm.h>
#include "radeon_reg.h"
#include "radeon.h"
+#include "radeon_asic.h"
#include "atom.h"
/* 10 khz */
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index 2a10e24b34b1..fb16070b266e 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -90,6 +90,9 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
+ if (radeon_crtc->cursor_out_of_bounds)
+ return;
+
if (ASIC_IS_DCE4(rdev)) {
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(radeon_crtc->cursor_addr));
@@ -143,21 +146,25 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
int xorigin = 0, yorigin = 0;
int w = radeon_crtc->cursor_width;
+ radeon_crtc->cursor_x = x;
+ radeon_crtc->cursor_y = y;
+
if (ASIC_IS_AVIVO(rdev)) {
/* avivo cursor are offset into the total surface */
x += crtc->x;
y += crtc->y;
}
- DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
- if (x < 0) {
+ if (x < 0)
xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
- x = 0;
- }
- if (y < 0) {
+ if (y < 0)
yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
- y = 0;
+
+ if (!ASIC_IS_AVIVO(rdev)) {
+ x += crtc->x;
+ y += crtc->y;
}
+ DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
/* fixed on DCE6 and newer */
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
@@ -180,27 +187,31 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
if (i > 1) {
int cursor_end, frame_end;
- cursor_end = x - xorigin + w;
+ cursor_end = x + w;
frame_end = crtc->x + crtc->mode.crtc_hdisplay;
if (cursor_end >= frame_end) {
w = w - (cursor_end - frame_end);
if (!(frame_end & 0x7f))
w--;
- } else {
- if (!(cursor_end & 0x7f))
- w--;
+ } else if (cursor_end <= 0) {
+ goto out_of_bounds;
+ } else if (!(cursor_end & 0x7f)) {
+ w--;
}
if (w <= 0) {
- w = 1;
- cursor_end = x - xorigin + w;
- if (!(cursor_end & 0x7f)) {
- x--;
- WARN_ON_ONCE(x < 0);
- }
+ goto out_of_bounds;
}
}
}
+ if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
+ x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
+ y >= (crtc->y + crtc->mode.crtc_vdisplay))
+ goto out_of_bounds;
+
+ x += xorigin;
+ y += yorigin;
+
if (ASIC_IS_DCE4(rdev)) {
WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
@@ -212,6 +223,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
} else {
+ x -= crtc->x;
+ y -= crtc->y;
+
if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
y *= 2;
@@ -229,10 +243,20 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
yorigin * 256);
}
- radeon_crtc->cursor_x = x;
- radeon_crtc->cursor_y = y;
+ if (radeon_crtc->cursor_out_of_bounds) {
+ radeon_crtc->cursor_out_of_bounds = false;
+ if (radeon_crtc->cursor_bo)
+ radeon_show_cursor(crtc);
+ }
return 0;
+
+ out_of_bounds:
+ if (!radeon_crtc->cursor_out_of_bounds) {
+ radeon_hide_cursor(crtc);
+ radeon_crtc->cursor_out_of_bounds = true;
+ }
+ return 0;
}
int radeon_crtc_cursor_move(struct drm_crtc *crtc,
@@ -297,22 +321,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
return ret;
}
- radeon_crtc->cursor_width = width;
- radeon_crtc->cursor_height = height;
-
radeon_lock_cursor(crtc, true);
- if (hot_x != radeon_crtc->cursor_hot_x ||
+ if (width != radeon_crtc->cursor_width ||
+ height != radeon_crtc->cursor_height ||
+ hot_x != radeon_crtc->cursor_hot_x ||
hot_y != radeon_crtc->cursor_hot_y) {
int x, y;
x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
- radeon_cursor_move_locked(crtc, x, y);
-
+ radeon_crtc->cursor_width = width;
+ radeon_crtc->cursor_height = height;
radeon_crtc->cursor_hot_x = hot_x;
radeon_crtc->cursor_hot_y = hot_y;
+
+ radeon_cursor_move_locked(crtc, x, y);
}
radeon_show_cursor(crtc);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 621af069a3d2..8a1df2a1afbd 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1333,7 +1333,7 @@ int radeon_device_init(struct radeon_device *rdev,
for (i = 0; i < RADEON_NUM_RINGS; i++) {
rdev->ring[i].idx = i;
}
- rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS);
+ rdev->fence_context = dma_fence_context_alloc(RADEON_NUM_RINGS);
DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n",
radeon_family_name[rdev->family], pdev->vendor, pdev->device,
@@ -1664,7 +1664,10 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend,
radeon_suspend(rdev);
radeon_hpd_fini(rdev);
- /* evict remaining vram memory */
+ /* evict remaining vram memory
+ * This second call to evict vram is to evict the gart page table
+ * using the CPU.
+ */
radeon_bo_evict_vram(rdev);
radeon_agp_suspend(rdev);
@@ -1946,9 +1949,6 @@ int radeon_debugfs_add_files(struct radeon_device *rdev,
rdev->debugfs_count = i;
#if defined(CONFIG_DEBUG_FS)
drm_debugfs_create_files(files, nfiles,
- rdev->ddev->control->debugfs_root,
- rdev->ddev->control);
- drm_debugfs_create_files(files, nfiles,
rdev->ddev->primary->debugfs_root,
rdev->ddev->primary);
#endif
@@ -1963,9 +1963,6 @@ static void radeon_debugfs_remove_files(struct radeon_device *rdev)
for (i = 0; i < rdev->debugfs_count; i++) {
drm_debugfs_remove_files(rdev->debugfs[i].files,
rdev->debugfs[i].num_files,
- rdev->ddev->control);
- drm_debugfs_remove_files(rdev->debugfs[i].files,
- rdev->debugfs[i].num_files,
rdev->ddev->primary);
}
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index cdb8cb568c15..e7409e8a9f87 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -437,7 +437,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
down_read(&rdev->exclusive_lock);
}
} else
- r = fence_wait(work->fence, false);
+ r = dma_fence_wait(work->fence, false);
if (r)
DRM_ERROR("failed to wait on page flip fence (%d)!\n", r);
@@ -447,7 +447,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
* confused about which BO the CRTC is scanning out
*/
- fence_put(work->fence);
+ dma_fence_put(work->fence);
work->fence = NULL;
}
@@ -542,7 +542,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
DRM_ERROR("failed to pin new rbo buffer before flip\n");
goto cleanup;
}
- work->fence = fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
+ work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
radeon_bo_unreserve(new_rbo);
@@ -617,7 +617,7 @@ pflip_cleanup:
cleanup:
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
- fence_put(work->fence);
+ dma_fence_put(work->fence);
kfree(work);
return r;
}
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index de504ea29c06..6d1237d6e1b8 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -223,7 +223,8 @@ radeon_dp_mst_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
-struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
+static struct
+drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -341,7 +342,8 @@ const struct drm_dp_mst_topology_cbs mst_cbs = {
.hotplug = radeon_dp_mst_hotplug,
};
-struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
+static struct
+radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_connector *connector;
@@ -597,7 +599,7 @@ static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = {
.commit = radeon_mst_encoder_commit,
};
-void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
+static void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
kfree(encoder);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 0daad446d2c7..899b6a1644bd 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -74,28 +74,22 @@ radeonfb_release(struct fb_info *info, int user)
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_open = radeonfb_open,
.fb_release = radeonfb_release,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
-int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tiled)
{
int aligned = width;
int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
int pitch_mask = 0;
- switch (bpp / 8) {
+ switch (cpp) {
case 1:
pitch_mask = align_large ? 255 : 127;
break;
@@ -110,7 +104,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tile
aligned += pitch_mask;
aligned &= ~pitch_mask;
- return aligned;
+ return aligned * cpp;
}
static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -139,13 +133,13 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
int ret;
int aligned_size, size;
int height = mode_cmd->height;
- u32 bpp, depth;
+ u32 cpp;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+ cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
/* need to align pitch with crtc limits */
- mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp,
- fb_tiled) * ((bpp + 1) / 8);
+ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
+ fb_tiled);
if (rdev->family >= CHIP_R600)
height = ALIGN(mode_cmd->height, 8);
@@ -165,11 +159,11 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
tiling_flags = RADEON_TILING_MACRO;
#ifdef __BIG_ENDIAN
- switch (bpp) {
- case 32:
+ switch (cpp) {
+ case 4:
tiling_flags |= RADEON_TILING_SWAP_32BIT;
break;
- case 16:
+ case 2:
tiling_flags |= RADEON_TILING_SWAP_16BIT;
default:
break;
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 7ef075acde9c..ef09f0a63754 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -141,8 +141,10 @@ int radeon_fence_emit(struct radeon_device *rdev,
(*fence)->seq = seq = ++rdev->fence_drv[ring].sync_seq[ring];
(*fence)->ring = ring;
(*fence)->is_vm_update = false;
- fence_init(&(*fence)->base, &radeon_fence_ops,
- &rdev->fence_queue.lock, rdev->fence_context + ring, seq);
+ dma_fence_init(&(*fence)->base, &radeon_fence_ops,
+ &rdev->fence_queue.lock,
+ rdev->fence_context + ring,
+ seq);
radeon_fence_ring_emit(rdev, ring, *fence);
trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq);
radeon_fence_schedule_check(rdev, ring);
@@ -169,18 +171,18 @@ static int radeon_fence_check_signaled(wait_queue_t *wait, unsigned mode, int fl
*/
seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq);
if (seq >= fence->seq) {
- int ret = fence_signal_locked(&fence->base);
+ int ret = dma_fence_signal_locked(&fence->base);
if (!ret)
- FENCE_TRACE(&fence->base, "signaled from irq context\n");
+ DMA_FENCE_TRACE(&fence->base, "signaled from irq context\n");
else
- FENCE_TRACE(&fence->base, "was already signaled\n");
+ DMA_FENCE_TRACE(&fence->base, "was already signaled\n");
radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring);
__remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake);
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
} else
- FENCE_TRACE(&fence->base, "pending\n");
+ DMA_FENCE_TRACE(&fence->base, "pending\n");
return 0;
}
@@ -351,7 +353,7 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev,
return false;
}
-static bool radeon_fence_is_signaled(struct fence *f)
+static bool radeon_fence_is_signaled(struct dma_fence *f)
{
struct radeon_fence *fence = to_radeon_fence(f);
struct radeon_device *rdev = fence->rdev;
@@ -381,7 +383,7 @@ static bool radeon_fence_is_signaled(struct fence *f)
* to fence_queue that checks if this fence is signaled, and if so it
* signals the fence and removes itself.
*/
-static bool radeon_fence_enable_signaling(struct fence *f)
+static bool radeon_fence_enable_signaling(struct dma_fence *f)
{
struct radeon_fence *fence = to_radeon_fence(f);
struct radeon_device *rdev = fence->rdev;
@@ -414,9 +416,9 @@ static bool radeon_fence_enable_signaling(struct fence *f)
fence->fence_wake.private = NULL;
fence->fence_wake.func = radeon_fence_check_signaled;
__add_wait_queue(&rdev->fence_queue, &fence->fence_wake);
- fence_get(f);
+ dma_fence_get(f);
- FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring);
+ DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring);
return true;
}
@@ -436,9 +438,9 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {
int ret;
- ret = fence_signal(&fence->base);
+ ret = dma_fence_signal(&fence->base);
if (!ret)
- FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n");
+ DMA_FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n");
return true;
}
return false;
@@ -552,7 +554,7 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo
* exclusive_lock is not held in that case.
*/
if (WARN_ON_ONCE(!to_radeon_fence(&fence->base)))
- return fence_wait(&fence->base, intr);
+ return dma_fence_wait(&fence->base, intr);
seq[fence->ring] = fence->seq;
r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, timeout);
@@ -560,9 +562,9 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo
return r;
}
- r_sig = fence_signal(&fence->base);
+ r_sig = dma_fence_signal(&fence->base);
if (!r_sig)
- FENCE_TRACE(&fence->base, "signaled from fence_wait\n");
+ DMA_FENCE_TRACE(&fence->base, "signaled from fence_wait\n");
return r;
}
@@ -697,7 +699,7 @@ int radeon_fence_wait_empty(struct radeon_device *rdev, int ring)
*/
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
{
- fence_get(&fence->base);
+ dma_fence_get(&fence->base);
return fence;
}
@@ -714,7 +716,7 @@ void radeon_fence_unref(struct radeon_fence **fence)
*fence = NULL;
if (tmp) {
- fence_put(&tmp->base);
+ dma_fence_put(&tmp->base);
}
}
@@ -1028,12 +1030,12 @@ int radeon_debugfs_fence_init(struct radeon_device *rdev)
#endif
}
-static const char *radeon_fence_get_driver_name(struct fence *fence)
+static const char *radeon_fence_get_driver_name(struct dma_fence *fence)
{
return "radeon";
}
-static const char *radeon_fence_get_timeline_name(struct fence *f)
+static const char *radeon_fence_get_timeline_name(struct dma_fence *f)
{
struct radeon_fence *fence = to_radeon_fence(f);
switch (fence->ring) {
@@ -1051,16 +1053,16 @@ static const char *radeon_fence_get_timeline_name(struct fence *f)
static inline bool radeon_test_signaled(struct radeon_fence *fence)
{
- return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
+ return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
}
struct radeon_wait_cb {
- struct fence_cb base;
+ struct dma_fence_cb base;
struct task_struct *task;
};
static void
-radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
+radeon_fence_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct radeon_wait_cb *wait =
container_of(cb, struct radeon_wait_cb, base);
@@ -1068,7 +1070,7 @@ radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
wake_up_process(wait->task);
}
-static signed long radeon_fence_default_wait(struct fence *f, bool intr,
+static signed long radeon_fence_default_wait(struct dma_fence *f, bool intr,
signed long t)
{
struct radeon_fence *fence = to_radeon_fence(f);
@@ -1077,7 +1079,7 @@ static signed long radeon_fence_default_wait(struct fence *f, bool intr,
cb.task = current;
- if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb))
+ if (dma_fence_add_callback(f, &cb.base, radeon_fence_wait_cb))
return t;
while (t > 0) {
@@ -1105,12 +1107,12 @@ static signed long radeon_fence_default_wait(struct fence *f, bool intr,
}
__set_current_state(TASK_RUNNING);
- fence_remove_callback(f, &cb.base);
+ dma_fence_remove_callback(f, &cb.base);
return t;
}
-const struct fence_ops radeon_fence_ops = {
+const struct dma_fence_ops radeon_fence_ops = {
.get_driver_name = radeon_fence_get_driver_name,
.get_timeline_name = radeon_fence_get_timeline_name,
.enable_signaling = radeon_fence_enable_signaling,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index deb9511725c9..0bcffd8a7bd3 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -745,7 +745,8 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
uint32_t handle;
int r;
- args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+ args->pitch = radeon_align_pitch(rdev, args->width,
+ DIV_ROUND_UP(args->bpp, 8), 0);
args->size = args->pitch * args->height;
args->size = ALIGN(args->size, PAGE_SIZE);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 868c3ba2efaa..222a1fa41d7c 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -27,6 +27,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
+#include "radeon_asic.h"
#include "atom.h"
#include <linux/backlight.h>
#ifdef CONFIG_PMAC_BACKLIGHT
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index bb75201a24ba..f1da484864a9 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -330,6 +330,7 @@ struct radeon_crtc {
u16 lut_r[256], lut_g[256], lut_b[256];
bool enabled;
bool can_tile;
+ bool cursor_out_of_bounds;
uint32_t crtc_offset;
struct drm_gem_object *cursor_bo;
uint64_t cursor_addr;
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 4b6542538ff9..326ad068c15a 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -47,6 +47,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev);
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
static void radeon_pm_update_profile(struct radeon_device *rdev);
static void radeon_pm_set_clocks(struct radeon_device *rdev);
+static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev);
int radeon_pm_get_type_index(struct radeon_device *rdev,
enum radeon_pm_state_type ps_type,
@@ -79,6 +80,8 @@ void radeon_pm_acpi_event_handler(struct radeon_device *rdev)
radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power);
}
mutex_unlock(&rdev->pm.mutex);
+ /* allow new DPM state to be picked */
+ radeon_pm_compute_clocks_dpm(rdev);
} else if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
if (rdev->pm.profile == PM_PROFILE_AUTO) {
mutex_lock(&rdev->pm.mutex);
@@ -882,7 +885,8 @@ static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev,
dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
/* balanced states don't exist at the moment */
if (dpm_state == POWER_STATE_TYPE_BALANCED)
- dpm_state = POWER_STATE_TYPE_PERFORMANCE;
+ dpm_state = rdev->pm.dpm.ac_power ?
+ POWER_STATE_TYPE_PERFORMANCE : POWER_STATE_TYPE_BATTERY;
restart_search:
/* Pick the best power state based on current conditions */
diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c
index 02ac8a1de4ff..be5d7a38d3aa 100644
--- a/drivers/gpu/drm/radeon/radeon_sync.c
+++ b/drivers/gpu/drm/radeon/radeon_sync.c
@@ -92,7 +92,7 @@ int radeon_sync_resv(struct radeon_device *rdev,
bool shared)
{
struct reservation_object_list *flist;
- struct fence *f;
+ struct dma_fence *f;
struct radeon_fence *fence;
unsigned i;
int r = 0;
@@ -103,7 +103,7 @@ int radeon_sync_resv(struct radeon_device *rdev,
if (fence && fence->rdev == rdev)
radeon_sync_fence(sync, fence);
else if (f)
- r = fence_wait(f, true);
+ r = dma_fence_wait(f, true);
flist = reservation_object_get_list(resv);
if (shared || !flist || r)
@@ -116,7 +116,7 @@ int radeon_sync_resv(struct radeon_device *rdev,
if (fence && fence->rdev == rdev)
radeon_sync_fence(sync, fence);
else
- r = fence_wait(f, true);
+ r = dma_fence_wait(f, true);
if (r)
break;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 3de5e6e21662..0cf03ccbf0a7 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -863,6 +863,7 @@ static struct ttm_bo_driver radeon_bo_driver = {
.ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate,
.invalidate_caches = &radeon_invalidate_caches,
.init_mem_type = &radeon_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = &radeon_evict_flags,
.move = &radeon_bo_move,
.verify_access = &radeon_verify_access,
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 0cd0e7bdee55..d34d1cf33895 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -467,7 +467,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
{
int32_t *msg, msg_type, handle;
unsigned img_size = 0;
- struct fence *f;
+ struct dma_fence *f;
void *ptr;
int i, r;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index e402be8821c4..ad4d7b8b8322 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -1714,6 +1714,7 @@ static int si_init_microcode(struct radeon_device *rdev)
(rdev->pdev->revision == 0x80) ||
(rdev->pdev->revision == 0x81) ||
(rdev->pdev->revision == 0x83) ||
+ (rdev->pdev->revision == 0x87) ||
(rdev->pdev->device == 0x6604) ||
(rdev->pdev->device == 0x6605))
new_smc = true;
@@ -7858,7 +7859,7 @@ static void si_program_aspm(struct radeon_device *rdev)
}
}
-int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
+static int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
{
unsigned i;
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index c49934527a87..8b5e697f2549 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -3026,6 +3026,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
(rdev->pdev->revision == 0x80) ||
(rdev->pdev->revision == 0x81) ||
(rdev->pdev->revision == 0x83) ||
+ (rdev->pdev->revision == 0x87) ||
(rdev->pdev->device == 0x6604) ||
(rdev->pdev->device == 0x6605)) {
max_sclk = 75000;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7316fc7fa0bd..a2ec6d8796a0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -149,8 +149,8 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
/* Signal polarities */
- value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
- | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
+ value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
+ | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
| DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, value);
@@ -172,7 +172,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
mode->crtc_vsync_start - 1);
rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1);
- rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start);
+ rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start - 1);
rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 73c971e39b1c..c05e00872778 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -110,6 +110,27 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.num_lvds = 1,
};
+static const struct rcar_du_device_info rcar_du_r8a7792_info = {
+ .gen = 2,
+ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+ .num_crtcs = 2,
+ .routes = {
+ /* R8A7792 has two RGB outputs. */
+ [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,
+};
+
static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
@@ -157,13 +178,39 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.num_lvds = 1,
};
+static const struct rcar_du_device_info rcar_du_r8a7796_info = {
+ .gen = 3,
+ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS
+ | RCAR_DU_FEATURE_VSP1_SOURCE,
+ .num_crtcs = 3,
+ .routes = {
+ /* R8A7796 has one RGB output, one LVDS output and one
+ * (currently unsupported) HDMI output.
+ */
+ [RCAR_DU_OUTPUT_DPAD0] = {
+ .possible_crtcs = BIT(2),
+ .encoder_type = DRM_MODE_ENCODER_NONE,
+ .port = 0,
+ },
+ [RCAR_DU_OUTPUT_LVDS0] = {
+ .possible_crtcs = BIT(0),
+ .encoder_type = DRM_MODE_ENCODER_LVDS,
+ .port = 2,
+ },
+ },
+ .num_lvds = 1,
+};
+
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-r8a7792", .data = &rcar_du_r8a7792_info },
{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
+ { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
{ }
};
@@ -201,9 +248,7 @@ static const struct file_operations rcar_du_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -285,7 +330,6 @@ static int rcar_du_remove(struct platform_device *pdev)
drm_kms_helper_poll_fini(ddev);
drm_mode_config_cleanup(ddev);
- drm_vblank_cleanup(ddev);
drm_dev_unref(ddev);
@@ -294,18 +338,12 @@ static int rcar_du_remove(struct platform_device *pdev)
static int rcar_du_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
struct rcar_du_device *rcdu;
struct drm_device *ddev;
struct resource *mem;
int ret;
- if (np == NULL) {
- dev_err(&pdev->dev, "no device tree node\n");
- return -ENODEV;
- }
-
- /* Allocate and initialize the DRM and R-Car device structures. */
+ /* Allocate and initialize the R-Car device structure. */
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
if (rcdu == NULL)
return -ENOMEM;
@@ -315,31 +353,22 @@ static int rcar_du_probe(struct platform_device *pdev)
rcdu->dev = &pdev->dev;
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
- ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
- if (IS_ERR(ddev))
- return PTR_ERR(ddev);
-
- rcdu->ddev = ddev;
- ddev->dev_private = rcdu;
-
platform_set_drvdata(pdev, rcdu);
/* I/O resources */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
- if (IS_ERR(rcdu->mmio)) {
- ret = PTR_ERR(rcdu->mmio);
- goto error;
- }
-
- /* Initialize vertical blanking interrupts handling. Start with vblank
- * disabled for all CRTCs.
- */
- ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
- if (ret < 0)
- goto error;
+ if (IS_ERR(rcdu->mmio))
+ return PTR_ERR(rcdu->mmio);
/* DRM/KMS objects */
+ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
+ if (IS_ERR(ddev))
+ return PTR_ERR(ddev);
+
+ rcdu->ddev = ddev;
+ ddev->dev_private = rcdu;
+
ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 33b2fc53da3e..64738fca96d0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -105,16 +105,20 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
rcar_du_group_setup_defr8(rgrp);
- /* Configure input dot clock routing. We currently hardcode the
- * configuration to routing DOTCLKINn to DUn.
+ /*
+ * Configure input dot clock routing. We currently hardcode the
+ * configuration to routing DOTCLKINn to DUn. Register fields
+ * depend on the DU generation, but the resulting value is 0 in
+ * all cases.
+ *
+ * On Gen2 a single register in the first group controls dot
+ * clock selection for all channels, while on Gen3 dot clocks
+ * are setup through per-group registers, only available when
+ * the group has two channels.
*/
- rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE |
- DIDSR_LCDS_DCLKIN(2) |
- DIDSR_LCDS_DCLKIN(1) |
- DIDSR_LCDS_DCLKIN(0) |
- DIDSR_PDCS_CLK(2, 0) |
- DIDSR_PDCS_CLK(1, 0) |
- DIDSR_PDCS_CLK(0, 0));
+ if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
+ (rcdu->info->gen == 3 && rgrp->num_crtcs > 1))
+ rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
}
if (rcdu->info->gen >= 3)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index e03004f4588d..f9515f53cc5b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -108,7 +108,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
if (hdmienc == NULL)
return -ENOMEM;
- /* Locate drm bridge from the hdmi encoder DT node */
+ /* Locate the DRM bridge from the HDMI encoder DT node. */
bridge = of_drm_find_bridge(np);
if (!bridge)
return -EPROBE_DEFER;
@@ -123,7 +123,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
renc->hdmi = hdmienc;
hdmienc->renc = renc;
- /* Link drm_bridge to encoder */
+ /* Link the bridge to the encoder. */
bridge->encoder = encoder;
encoder->bridge = bridge;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 392c7e6de042..b5d3f16cfa12 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -272,7 +272,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
drm_atomic_helper_cleanup_planes(dev, old_state);
- drm_atomic_state_free(old_state);
+ drm_atomic_state_put(old_state);
/* Complete the commit, wake up any waiter. */
spin_lock(&rcdu->commit.wait.lock);
@@ -338,6 +338,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
/* Swap the state, this is the point of no return. */
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (nonblock)
schedule_work(&commit->work);
else
@@ -453,13 +454,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
}
ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
- of_node_put(encoder);
- of_node_put(connector);
-
if (ret && ret != -EPROBE_DEFER)
dev_warn(rcdu->dev,
- "failed to initialize encoder %s (%d), skipping\n",
- encoder->full_name, ret);
+ "failed to initialize encoder %s on output %u (%d), skipping\n",
+ of_node_full_name(encoder), output, ret);
+
+ of_node_put(encoder);
+ of_node_put(connector);
return ret;
}
@@ -567,6 +568,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
if (ret < 0)
return ret;
+ /* Initialize vertical blanking interrupts handling. Start with vblank
+ * disabled for all CRTCs.
+ */
+ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
+ if (ret < 0)
+ return ret;
+
/* Initialize the groups. */
num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 6afd0af312ba..3bcfd161c53f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -61,16 +61,9 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.get_modes = rcar_du_lvds_connector_get_modes,
};
-static enum drm_connector_status
-rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
- .detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -79,7 +72,7 @@ static const struct drm_connector_funcs connector_funcs = {
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
struct rcar_du_encoder *renc,
- /* TODO const */ struct device_node *np)
+ const struct device_node *np)
{
struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
struct rcar_du_lvds_connector *lvdscon;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
index d4881ee0be7e..639071dd235c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
@@ -19,6 +19,6 @@ struct rcar_du_encoder;
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
struct rcar_du_encoder *renc,
- struct device_node *np);
+ const struct device_node *np);
#endif /* __RCAR_DU_LVDSCON_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index ef3a50321ecc..e3a4985f6f3f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -104,7 +104,14 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
- /* Turn the PLL on, set it to LVDS normal mode, wait for the startup
+ /* Turn all the channels on. */
+ rcar_lvds_write(lvds, LVDCR1,
+ LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
+ LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
+ LVDCR1_CLKSTBY_GEN3);
+
+ /*
+ * Turn the PLL on, set it to LVDS normal mode, wait for the startup
* delay and turn the output on.
*/
lvdcr0 = LVDCR0_PLLON;
@@ -117,12 +124,6 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
-
- /* Turn all the channels on. */
- rcar_lvds_write(lvds, LVDCR1,
- LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
- LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
- LVDCR1_CLKSTBY_GEN3);
}
static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
@@ -241,10 +242,8 @@ int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
for (i = 0; i < rcdu->info->num_lvds; ++i) {
lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
- if (lvds == NULL) {
- dev_err(&pdev->dev, "failed to allocate private data\n");
+ if (lvds == NULL)
return -ENOMEM;
- }
lvds->dev = rcdu;
lvds->index = i;
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 3c58669a06ce..6f7f9c59f05b 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -1,7 +1,6 @@
config DRM_ROCKCHIP
tristate "DRM Support for Rockchip"
depends on DRM && ROCKCHIP_IOMMU
- depends on RESET_CONTROLLER
select DRM_GEM_CMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index ca22e5ee89ca..d9aa382bb629 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -969,12 +969,6 @@ static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = {
.mode_valid = dw_mipi_dsi_mode_valid,
};
-static enum drm_connector_status
-dw_mipi_dsi_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
@@ -984,7 +978,6 @@ static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
- .detect = dw_mipi_dsi_detect,
.destroy = dw_mipi_dsi_drm_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 8c8cbe837e61..2390c8577617 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -20,6 +20,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -274,9 +275,7 @@ static const struct file_operations rockchip_drm_driver_fops = {
.poll = drm_poll,
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.release = drm_release,
};
@@ -388,7 +387,7 @@ static void rockchip_add_endpoints(struct device *dev,
continue;
}
- component_match_add(dev, match, compare_of, remote);
+ drm_of_component_match_add(dev, match, compare_of, remote);
of_node_put(remote);
}
}
@@ -437,7 +436,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
}
of_node_put(iommu);
- component_match_add(dev, &match, compare_of, port->parent);
+ drm_of_component_match_add(dev, &match, compare_of,
+ port->parent);
of_node_put(port);
}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
index a16c69f96ed5..8f639c8597a5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
@@ -37,15 +37,11 @@ static int rockchip_fbdev_mmap(struct fb_info *info,
static struct fb_ops rockchip_drm_fbdev_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_mmap = rockchip_fbdev_mmap,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
};
static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
index 3b807135a5cd..78c6d8e9b42c 100644
--- a/drivers/gpu/drm/savage/savage_drv.c
+++ b/drivers/gpu/drm/savage/savage_drv.c
@@ -42,9 +42,7 @@ static const struct file_operations savage_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = drm_legacy_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c
index 3dc0d8ff95ec..2db89bed52e8 100644
--- a/drivers/gpu/drm/savage/savage_state.c
+++ b/drivers/gpu/drm/savage/savage_state.c
@@ -1004,6 +1004,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size);
if (IS_ERR(kvb_addr)) {
ret = PTR_ERR(kvb_addr);
+ kvb_addr = NULL;
goto done;
}
cmdbuf->vb_addr = kvb_addr;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 6547b1db460a..dddbdd62bed0 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -669,15 +669,8 @@ static void shmob_drm_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
-static enum drm_connector_status
-shmob_drm_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .detect = shmob_drm_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = shmob_drm_connector_destroy,
};
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index f0492603ea88..38dd55f4af81 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -245,9 +245,7 @@ static const struct file_operations shmob_drm_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index ae9839886c4d..a836451920f0 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -72,9 +72,7 @@ static const struct file_operations sis_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = drm_legacy_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 9df308565f6c..ff71e25ab5bf 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -17,6 +17,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_of.h>
#include "sti_crtc.h"
#include "sti_drv.h"
@@ -184,7 +185,7 @@ static void sti_atomic_complete(struct sti_private *private,
drm_atomic_helper_wait_for_vblanks(drm, state);
drm_atomic_helper_cleanup_planes(drm, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
}
static void sti_atomic_work(struct work_struct *work)
@@ -237,6 +238,7 @@ static int sti_atomic_commit(struct drm_device *drm,
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (nonblock)
sti_atomic_schedule(private, state);
else
@@ -295,9 +297,7 @@ static const struct file_operations sti_driver_fops = {
.poll = drm_poll,
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.release = drm_release,
};
@@ -443,8 +443,8 @@ static int sti_platform_probe(struct platform_device *pdev)
child_np = of_get_next_available_child(node, NULL);
while (child_np) {
- component_match_add(dev, &match, compare_of, child_np);
- of_node_put(child_np);
+ drm_of_component_match_add(dev, &match, compare_of,
+ child_np);
child_np = of_get_next_available_child(node, child_np);
}
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index e7c243f70870..96f336dd0e29 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -642,12 +642,6 @@ struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
.mode_valid = sti_hda_connector_mode_valid,
};
-static enum drm_connector_status
-sti_hda_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static int sti_hda_late_register(struct drm_connector *connector)
{
struct sti_hda_connector *hda_connector
@@ -665,7 +659,6 @@ static int sti_hda_late_register(struct drm_connector *connector)
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,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 32c0584e3c35..2e08f969bb64 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -95,6 +95,22 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
break;
+ case DRM_FORMAT_ARGB4444:
+ *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444;
+ break;
+
+ case DRM_FORMAT_ARGB1555:
+ *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555;
+ break;
+
+ case DRM_FORMAT_RGBA5551:
+ *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551;
+ break;
+
+ case DRM_FORMAT_RGBA4444:
+ *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444;
+ break;
+
case DRM_FORMAT_XRGB8888:
*mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888;
break;
@@ -103,6 +119,10 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
*mode = SUN4I_BACKEND_LAY_FBFMT_RGB888;
break;
+ case DRM_FORMAT_RGB565:
+ *mode = SUN4I_BACKEND_LAY_FBFMT_RGB565;
+ break;
+
default:
return -EINVAL;
}
@@ -389,7 +409,7 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
reset_control_assert(backend->reset);
}
-static struct component_ops sun4i_backend_ops = {
+static const struct component_ops sun4i_backend_ops = {
.bind = sun4i_backend_bind,
.unbind = sun4i_backend_unbind,
};
@@ -408,6 +428,7 @@ static int sun4i_backend_remove(struct platform_device *pdev)
static const struct of_device_id sun4i_backend_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-display-backend" },
+ { .compatible = "allwinner,sun6i-a31-display-backend" },
{ .compatible = "allwinner,sun8i-a33-display-backend" },
{ }
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 70e9fd59c5a2..4ce665349f6b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -18,6 +18,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_of.h>
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
@@ -52,9 +53,7 @@ static const struct file_operations sun4i_drv_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -201,12 +200,15 @@ static const struct component_master_ops sun4i_drv_master_ops = {
static bool sun4i_drv_node_is_frontend(struct device_node *node)
{
return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") ||
of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
}
static bool sun4i_drv_node_is_tcon(struct device_node *node)
{
return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
}
@@ -239,7 +241,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
/* Add current component */
DRM_DEBUG_DRIVER("Adding component %s\n",
of_node_full_name(node));
- component_match_add(dev, match, compare_of, node);
+ drm_of_component_match_add(dev, match, compare_of, node);
count++;
}
@@ -322,6 +324,8 @@ static int sun4i_drv_remove(struct platform_device *pdev)
static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-display-engine" },
+ { .compatible = "allwinner,sun6i-a31-display-engine" },
+ { .compatible = "allwinner,sun6i-a31s-display-engine" },
{ .compatible = "allwinner,sun8i-a33-display-engine" },
{ }
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f0035bf5efea..5d53c977bca5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -73,12 +73,18 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
static const uint32_t sun4i_backend_layer_formats_primary[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
};
static const uint32_t sun4i_backend_layer_formats_overlay[] = {
DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB4444,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_RGBA5551,
+ DRM_FORMAT_RGBA4444,
DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index d198ad7e5323..f5e86fe7750e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -110,12 +110,6 @@ static struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = {
.mode_valid = sun4i_rgb_mode_valid,
};
-static enum drm_connector_status
-sun4i_rgb_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void
sun4i_rgb_connector_destroy(struct drm_connector *connector)
{
@@ -129,7 +123,6 @@ sun4i_rgb_connector_destroy(struct drm_connector *connector)
static struct drm_connector_funcs sun4i_rgb_con_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
- .detect = sun4i_rgb_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = sun4i_rgb_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index cadacb517f95..ea2906f87cb9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -20,6 +20,7 @@
#include <linux/component.h>
#include <linux/ioport.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
@@ -62,7 +63,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
return;
}
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
SUN4I_TCON1_CTL_TCON_ENABLE, 0);
clk_disable_unprepare(tcon->sclk1);
@@ -80,7 +81,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
return;
}
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
SUN4I_TCON1_CTL_TCON_ENABLE,
SUN4I_TCON1_CTL_TCON_ENABLE);
@@ -202,7 +203,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
u8 clk_delay;
u32 val;
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
/* Adjust clock delay */
clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
@@ -266,7 +267,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
/*
* FIXME: Undocumented bits
*/
- if (tcon->has_mux)
+ if (tcon->quirks->has_unknown_mux)
regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1);
}
EXPORT_SYMBOL(sun4i_tcon1_mode_set);
@@ -327,7 +328,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
return PTR_ERR(tcon->sclk0);
}
- if (tcon->has_channel_1) {
+ if (tcon->quirks->has_channel_1) {
tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
if (IS_ERR(tcon->sclk1)) {
dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
@@ -487,14 +488,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
drv->tcon = tcon;
tcon->drm = drm;
tcon->dev = dev;
-
- if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) {
- tcon->has_mux = true;
- tcon->has_channel_1 = true;
- } else {
- tcon->has_mux = false;
- tcon->has_channel_1 = false;
- }
+ tcon->quirks = of_device_get_match_data(dev);
tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
if (IS_ERR(tcon->lcd_rst)) {
@@ -551,7 +545,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
sun4i_tcon_free_clocks(tcon);
}
-static struct component_ops sun4i_tcon_ops = {
+static const struct component_ops sun4i_tcon_ops = {
.bind = sun4i_tcon_bind,
.unbind = sun4i_tcon_unbind,
};
@@ -588,9 +582,28 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
return 0;
}
+static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
+ .has_unknown_mux = true,
+ .has_channel_1 = true,
+};
+
+static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
+ .has_channel_1 = true,
+};
+
+static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
+ .has_channel_1 = true,
+};
+
+static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
+ /* nothing is supported */
+};
+
static const struct of_device_id sun4i_tcon_of_table[] = {
- { .compatible = "allwinner,sun5i-a13-tcon" },
- { .compatible = "allwinner,sun8i-a33-tcon" },
+ { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
+ { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
+ { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
+ { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 12bd48925f4d..166064bafe2e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -142,6 +142,11 @@
#define SUN4I_TCON_MAX_CHANNELS 2
+struct sun4i_tcon_quirks {
+ bool has_unknown_mux; /* sun5i has undocumented mux */
+ bool has_channel_1; /* a33 does not have channel 1 */
+};
+
struct sun4i_tcon {
struct device *dev;
struct drm_device *drm;
@@ -160,12 +165,10 @@ struct sun4i_tcon {
/* Reset control */
struct reset_control *lcd_rst;
- /* Platform adjustments */
- bool has_mux;
-
struct drm_panel *panel;
- bool has_channel_1;
+ /* Platform adjustments */
+ const struct sun4i_tcon_quirks *quirks;
};
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 1dd3d9eabf2e..c6f47222e8fc 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -537,12 +537,6 @@ static struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs =
.mode_valid = sun4i_tv_comp_mode_valid,
};
-static enum drm_connector_status
-sun4i_tv_comp_connector_detect(struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
static void
sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
{
@@ -551,7 +545,6 @@ sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
static struct drm_connector_funcs sun4i_tv_comp_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
- .detect = sun4i_tv_comp_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = sun4i_tv_comp_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
@@ -667,7 +660,7 @@ static void sun4i_tv_unbind(struct device *dev, struct device *master,
clk_disable_unprepare(tv->clk);
}
-static struct component_ops sun4i_tv_ops = {
+static const struct component_ops sun4i_tv_ops = {
.bind = sun4i_tv_bind,
.unbind = sun4i_tv_unbind,
};
diff --git a/drivers/gpu/drm/sun4i/sun6i_drc.c b/drivers/gpu/drm/sun4i/sun6i_drc.c
index bf6d846d8132..09bba853e2a4 100644
--- a/drivers/gpu/drm/sun4i/sun6i_drc.c
+++ b/drivers/gpu/drm/sun4i/sun6i_drc.c
@@ -80,7 +80,7 @@ static void sun6i_drc_unbind(struct device *dev, struct device *master,
reset_control_assert(drc->reset);
}
-static struct component_ops sun6i_drc_ops = {
+static const struct component_ops sun6i_drc_ops = {
.bind = sun6i_drc_bind,
.unbind = sun6i_drc_unbind,
};
@@ -98,6 +98,8 @@ static int sun6i_drc_remove(struct platform_device *pdev)
}
static const struct of_device_id sun6i_drc_of_table[] = {
+ { .compatible = "allwinner,sun6i-a31-drc" },
+ { .compatible = "allwinner,sun6i-a31s-drc" },
{ .compatible = "allwinner,sun8i-a33-drc" },
{ }
};
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
index f418892b0c71..c54138c3a376 100644
--- a/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ b/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -49,9 +49,7 @@ static const struct file_operations tdfx_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = drm_legacy_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 63ebb154b9b5..bbf5a4b7e0b6 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -3,7 +3,6 @@ config DRM_TEGRA
depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
depends on COMMON_CLK
depends on DRM
- depends on RESET_CONTROLLER
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 059f409556d5..2fde44c3a1b3 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -539,9 +539,9 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
dpaux->desc.owner = THIS_MODULE;
dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
- if (!dpaux->pinctrl) {
+ if (IS_ERR(dpaux->pinctrl)) {
dev_err(&pdev->dev, "failed to register pincontrol\n");
- return -ENODEV;
+ return PTR_ERR(dpaux->pinctrl);
}
#endif
/* enable and clear all interrupts */
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 8ab47b502d83..b8be3ee4d3b8 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -63,7 +63,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra,
drm_atomic_helper_wait_for_vblanks(drm, state);
drm_atomic_helper_cleanup_planes(drm, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
}
static void tegra_atomic_work(struct work_struct *work)
@@ -96,6 +96,7 @@ static int tegra_atomic_commit(struct drm_device *drm,
drm_atomic_helper_swap_state(state, true);
+ drm_atomic_state_get(state);
if (nonblock)
tegra_atomic_schedule(tegra, state);
else
@@ -801,9 +802,7 @@ static const struct file_operations tegra_drm_fops = {
.mmap = tegra_drm_mmap,
.poll = drm_poll,
.read = drm_read,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index e6d71fa4028e..e4a5ab0a9677 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -186,14 +186,10 @@ unreference:
#ifdef CONFIG_DRM_FBDEV_EMULATION
static struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
};
static int tegra_fbdev_probe(struct drm_fb_helper *helper,
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 95e622e31931..c08e5279eeac 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -2,7 +2,7 @@
* NVIDIA Tegra DRM GEM helper functions
*
* Copyright (C) 2012 Sascha Hauer, Pengutronix
- * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
+ * Copyright (C) 2013-2015 NVIDIA CORPORATION, All rights reserved.
*
* Based on the GEM/CMA helpers
*
@@ -36,6 +36,8 @@ static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+ *sgt = obj->sgt;
+
return obj->paddr;
}
@@ -47,23 +49,51 @@ static void *tegra_bo_mmap(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- return obj->vaddr;
+ if (obj->vaddr)
+ return obj->vaddr;
+ else if (obj->gem.import_attach)
+ return dma_buf_vmap(obj->gem.import_attach->dmabuf);
+ else
+ return vmap(obj->pages, obj->num_pages, VM_MAP,
+ pgprot_writecombine(PAGE_KERNEL));
}
static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
{
+ struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+ if (obj->vaddr)
+ return;
+ else if (obj->gem.import_attach)
+ dma_buf_vunmap(obj->gem.import_attach->dmabuf, addr);
+ else
+ vunmap(addr);
}
static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- return obj->vaddr + page * PAGE_SIZE;
+ if (obj->vaddr)
+ return obj->vaddr + page * PAGE_SIZE;
+ else if (obj->gem.import_attach)
+ return dma_buf_kmap(obj->gem.import_attach->dmabuf, page);
+ else
+ return vmap(obj->pages + page, 1, VM_MAP,
+ pgprot_writecombine(PAGE_KERNEL));
}
static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
void *addr)
{
+ struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+ if (obj->vaddr)
+ return;
+ else if (obj->gem.import_attach)
+ dma_buf_kunmap(obj->gem.import_attach->dmabuf, page, addr);
+ else
+ vunmap(addr);
}
static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
@@ -318,11 +348,6 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
get_dma_buf(buf);
bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
- if (!bo->sgt) {
- err = -ENOMEM;
- goto detach;
- }
-
if (IS_ERR(bo->sgt)) {
err = PTR_ERR(bo->sgt);
goto detach;
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 0b3f2b977ba0..13f0d1b7cd98 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -268,9 +268,9 @@ static int gr3d_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) {
gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2");
- if (IS_ERR(gr3d->clk)) {
+ if (IS_ERR(gr3d->clk_secondary)) {
dev_err(&pdev->dev, "cannot get secondary clock\n");
- return PTR_ERR(gr3d->clk);
+ return PTR_ERR(gr3d->clk_secondary);
}
gr3d->rst_secondary = devm_reset_control_get(&pdev->dev,
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 74d0540b8d4c..a8f528925009 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -349,8 +349,6 @@ static struct clk *tegra_clk_sor_brick_register(struct tegra_sor *sor,
brick->hw.init = &init;
clk = devm_clk_register(sor->dev, &brick->hw);
- if (IS_ERR(clk))
- kfree(brick);
return clk;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 52ebe8fc1784..9942b0577d6e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -21,11 +21,15 @@
#include <drm/drm_flip_work.h>
#include <drm/drm_plane_helper.h>
#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
#include "tilcdc_drv.h"
#include "tilcdc_regs.h"
-#define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000
+#define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000
+#define TILCDC_PALETTE_SIZE 32
+#define TILCDC_PALETTE_FIRST_ENTRY 0x4000
struct tilcdc_crtc {
struct drm_crtc base;
@@ -33,7 +37,9 @@ struct tilcdc_crtc {
struct drm_plane primary;
const struct tilcdc_panel_info *info;
struct drm_pending_vblank_event *event;
+ struct mutex enable_lock;
bool enabled;
+ bool shutdown;
wait_queue_head_t frame_done_wq;
bool frame_done;
spinlock_t irq_lock;
@@ -53,6 +59,11 @@ struct tilcdc_crtc {
int sync_lost_count;
bool frame_intact;
+ struct work_struct recover_work;
+
+ dma_addr_t palette_dma_handle;
+ u16 *palette_base;
+ struct completion palette_loaded;
};
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
@@ -71,17 +82,16 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
+ struct tilcdc_drm_private *priv = dev->dev_private;
struct drm_gem_cma_object *gem;
- unsigned int depth, bpp;
dma_addr_t start, end;
u64 dma_base_and_ceiling;
- drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
gem = drm_fb_cma_get_gem_obj(fb, 0);
start = gem->paddr + fb->offsets[0] +
crtc->y * fb->pitches[0] +
- crtc->x * bpp / 8;
+ crtc->x * drm_format_plane_cpp(fb->pixel_format, 0);
end = start + (crtc->mode.vdisplay * fb->pitches[0]);
@@ -90,7 +100,10 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
* unlikely that LCDC would fetch the DMA addresses in the middle of
* an update.
*/
- dma_base_and_ceiling = (u64)(end - 1) << 32 | start;
+ if (priv->rev == 1)
+ end -= 1;
+
+ dma_base_and_ceiling = (u64)end << 32 | start;
tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_base_and_ceiling);
if (tilcdc_crtc->curr_fb)
@@ -100,6 +113,56 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
tilcdc_crtc->curr_fb = fb;
}
+/*
+ * The driver currently only supports only true color formats. For
+ * true color the palette block is bypassed, but a 32 byte palette
+ * should still be loaded. The first 16-bit entry must be 0x4000 while
+ * all other entries must be zeroed.
+ */
+static void tilcdc_crtc_load_palette(struct drm_crtc *crtc)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct tilcdc_drm_private *priv = dev->dev_private;
+ int ret;
+
+ reinit_completion(&tilcdc_crtc->palette_loaded);
+
+ /* Tell the LCDC where the palette is located. */
+ tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG,
+ tilcdc_crtc->palette_dma_handle);
+ tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG,
+ (u32) tilcdc_crtc->palette_dma_handle +
+ TILCDC_PALETTE_SIZE - 1);
+
+ /* Set dma load mode for palette loading only. */
+ tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_PALETTE_LOAD_MODE(PALETTE_ONLY),
+ LCDC_PALETTE_LOAD_MODE_MASK);
+
+ /* Enable DMA Palette Loaded Interrupt */
+ if (priv->rev == 1)
+ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA);
+ else
+ tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_PL_INT_ENA);
+
+ /* Enable LCDC DMA and wait for palette to be loaded. */
+ tilcdc_clear_irqstatus(dev, 0xffffffff);
+ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+ ret = wait_for_completion_timeout(&tilcdc_crtc->palette_loaded,
+ msecs_to_jiffies(50));
+ if (ret == 0)
+ dev_err(dev->dev, "%s: Palette loading timeout", __func__);
+
+ /* Disable LCDC DMA and DMA Palette Loaded Interrupt. */
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+ if (priv->rev == 1)
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA);
+ else
+ tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, LCDC_V2_PL_INT_ENA);
+}
+
static void tilcdc_crtc_enable_irqs(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
@@ -108,6 +171,7 @@ static void tilcdc_crtc_enable_irqs(struct drm_device *dev)
if (priv->rev == 1) {
tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA |
LCDC_V1_UNDERFLOW_INT_ENA);
tilcdc_set(dev, LCDC_DMA_CTRL_REG,
LCDC_V1_END_OF_FRAME_INT_ENA);
@@ -126,6 +190,7 @@ static void tilcdc_crtc_disable_irqs(struct drm_device *dev)
/* disable irqs that we might have enabled: */
if (priv->rev == 1) {
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA |
LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
tilcdc_clear(dev, LCDC_DMA_CTRL_REG,
LCDC_V1_END_OF_FRAME_INT_ENA);
@@ -150,193 +215,68 @@ static void reset(struct drm_crtc *crtc)
tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
}
-static void tilcdc_crtc_enable(struct drm_crtc *crtc)
+/*
+ * Calculate the percentage difference between the requested pixel clock rate
+ * and the effective rate resulting from calculating the clock divider value.
+ */
+static unsigned int tilcdc_pclk_diff(unsigned long rate,
+ unsigned long real_rate)
{
- struct drm_device *dev = crtc->dev;
- struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-
- WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
- if (tilcdc_crtc->enabled)
- return;
-
- pm_runtime_get_sync(dev->dev);
-
- reset(crtc);
-
- tilcdc_crtc_enable_irqs(dev);
-
- tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
- tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
- tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
-
- drm_crtc_vblank_on(crtc);
+ int r = rate / 100, rr = real_rate / 100;
- tilcdc_crtc->enabled = true;
+ return (unsigned int)(abs(((rr - r) * 100) / r));
}
-void tilcdc_crtc_disable(struct drm_crtc *crtc)
+static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)
{
- struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct tilcdc_drm_private *priv = dev->dev_private;
-
- WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
- if (!tilcdc_crtc->enabled)
- return;
-
- tilcdc_crtc->frame_done = false;
- tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
-
- /*
- * if necessary wait for framedone irq which will still come
- * before putting things to sleep..
- */
- if (priv->rev == 2) {
- int ret = wait_event_timeout(tilcdc_crtc->frame_done_wq,
- tilcdc_crtc->frame_done,
- msecs_to_jiffies(500));
- if (ret == 0)
- dev_err(dev->dev, "%s: timeout waiting for framedone\n",
- __func__);
- }
-
- drm_crtc_vblank_off(crtc);
-
- tilcdc_crtc_disable_irqs(dev);
-
- pm_runtime_put_sync(dev->dev);
-
- if (tilcdc_crtc->next_fb) {
- drm_flip_work_queue(&tilcdc_crtc->unref_work,
- tilcdc_crtc->next_fb);
- tilcdc_crtc->next_fb = NULL;
- }
-
- if (tilcdc_crtc->curr_fb) {
- drm_flip_work_queue(&tilcdc_crtc->unref_work,
- tilcdc_crtc->curr_fb);
- tilcdc_crtc->curr_fb = NULL;
- }
-
- drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
- tilcdc_crtc->last_vblank = ktime_set(0, 0);
-
- tilcdc_crtc->enabled = false;
-}
-
-static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
-{
- return crtc->state && crtc->state->enable && crtc->state->active;
-}
-
-static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
-{
- struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
- struct tilcdc_drm_private *priv = crtc->dev->dev_private;
-
- drm_modeset_lock_crtc(crtc, NULL);
- tilcdc_crtc_disable(crtc);
- drm_modeset_unlock_crtc(crtc);
-
- flush_workqueue(priv->wq);
-
- of_node_put(crtc->port);
- drm_crtc_cleanup(crtc);
- drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
-}
-
-int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event)
-{
- struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- unsigned long flags;
-
- WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
- if (tilcdc_crtc->event) {
- dev_err(dev->dev, "already pending page flip!\n");
- return -EBUSY;
- }
-
- drm_framebuffer_reference(fb);
-
- crtc->primary->fb = fb;
-
- spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
-
- if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
- ktime_t next_vblank;
- s64 tdiff;
-
- next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
- 1000000 / crtc->hwmode.vrefresh);
-
- tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
-
- if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
- tilcdc_crtc->next_fb = fb;
- }
-
- if (tilcdc_crtc->next_fb != fb)
- set_scanout(crtc, fb);
-
- tilcdc_crtc->event = event;
-
- spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
-
- return 0;
-}
-
-static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ unsigned long clk_rate, real_rate, req_rate;
+ unsigned int clkdiv;
+ int ret;
- if (!tilcdc_crtc->simulate_vesa_sync)
- return true;
+ clkdiv = 2; /* first try using a standard divider of 2 */
- /*
- * tilcdc does not generate VESA-compliant sync but aligns
- * VS on the second edge of HS instead of first edge.
- * We use adjusted_mode, to fixup sync by aligning both rising
- * edges and add HSKEW offset to fix the sync.
- */
- adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
- adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
+ /* mode.clock is in KHz, set_rate wants parameter in Hz */
+ req_rate = crtc->mode.clock * 1000;
- if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
- adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
- adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
- } else {
- adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
- adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
- }
+ ret = clk_set_rate(priv->clk, req_rate * clkdiv);
+ clk_rate = clk_get_rate(priv->clk);
+ if (ret < 0) {
+ /*
+ * If we fail to set the clock rate (some architectures don't
+ * use the common clock framework yet and may not implement
+ * all the clk API calls for every clock), try the next best
+ * thing: adjusting the clock divider, unless clk_get_rate()
+ * failed as well.
+ */
+ if (!clk_rate) {
+ /* Nothing more we can do. Just bail out. */
+ dev_err(dev->dev,
+ "failed to set the pixel clock - unable to read current lcdc clock rate\n");
+ return;
+ }
- return true;
-}
+ clkdiv = DIV_ROUND_CLOSEST(clk_rate, req_rate);
-static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct tilcdc_drm_private *priv = dev->dev_private;
- struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
- const unsigned clkdiv = 2; /* using a fixed divider of 2 */
- int ret;
+ /*
+ * Emit a warning if the real clock rate resulting from the
+ * calculated divider differs much from the requested rate.
+ *
+ * 5% is an arbitrary value - LCDs are usually quite tolerant
+ * about pixel clock rates.
+ */
+ real_rate = clkdiv * req_rate;
- /* mode.clock is in KHz, set_rate wants parameter in Hz */
- ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv);
- if (ret < 0) {
- dev_err(dev->dev, "failed to set display clock rate to: %d\n",
- crtc->mode.clock);
- return;
+ if (tilcdc_pclk_diff(clk_rate, real_rate) > 5) {
+ dev_warn(dev->dev,
+ "effective pixel clock rate (%luHz) differs from the calculated rate (%luHz)\n",
+ clk_rate, real_rate);
+ }
}
- tilcdc_crtc->lcd_fck_rate = clk_get_rate(priv->clk);
+ tilcdc_crtc->lcd_fck_rate = clk_rate;
DBG("lcd_clk=%u, mode clock=%d, div=%u",
tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv);
@@ -351,7 +291,7 @@ static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)
LCDC_V2_CORE_CLK_EN);
}
-static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+static void tilcdc_crtc_set_mode(struct drm_crtc *crtc)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
@@ -361,8 +301,6 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct drm_framebuffer *fb = crtc->primary->state->fb;
- WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
if (WARN_ON(!info))
return;
@@ -461,16 +399,16 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
if (info->tft_alt_mode)
reg |= LCDC_TFT_ALT_ENABLE;
if (priv->rev == 2) {
- unsigned int depth, bpp;
-
- drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
- switch (bpp) {
- case 16:
+ switch (fb->pixel_format) {
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_RGB565:
break;
- case 32:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_XRGB8888:
reg |= LCDC_V2_TFT_24BPP_UNPACK;
/* fallthrough */
- case 24:
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
reg |= LCDC_V2_TFT_24BPP_MODE;
break;
default:
@@ -511,15 +449,226 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
else
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
- drm_framebuffer_reference(fb);
+ tilcdc_crtc_set_clk(crtc);
+
+ tilcdc_crtc_load_palette(crtc);
set_scanout(crtc, fb);
- tilcdc_crtc_set_clk(crtc);
+ drm_framebuffer_reference(fb);
crtc->hwmode = crtc->state->adjusted_mode;
}
+static void tilcdc_crtc_enable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+ mutex_lock(&tilcdc_crtc->enable_lock);
+ if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) {
+ mutex_unlock(&tilcdc_crtc->enable_lock);
+ return;
+ }
+
+ pm_runtime_get_sync(dev->dev);
+
+ reset(crtc);
+
+ tilcdc_crtc_set_mode(crtc);
+
+ tilcdc_crtc_enable_irqs(dev);
+
+ tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
+ tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_PALETTE_LOAD_MODE(DATA_ONLY),
+ LCDC_PALETTE_LOAD_MODE_MASK);
+ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+ drm_crtc_vblank_on(crtc);
+
+ tilcdc_crtc->enabled = true;
+ mutex_unlock(&tilcdc_crtc->enable_lock);
+}
+
+static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct tilcdc_drm_private *priv = dev->dev_private;
+ int ret;
+
+ mutex_lock(&tilcdc_crtc->enable_lock);
+ if (shutdown)
+ tilcdc_crtc->shutdown = true;
+ if (!tilcdc_crtc->enabled) {
+ mutex_unlock(&tilcdc_crtc->enable_lock);
+ return;
+ }
+ tilcdc_crtc->frame_done = false;
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+ /*
+ * Wait for framedone irq which will still come before putting
+ * things to sleep..
+ */
+ ret = wait_event_timeout(tilcdc_crtc->frame_done_wq,
+ tilcdc_crtc->frame_done,
+ msecs_to_jiffies(500));
+ if (ret == 0)
+ dev_err(dev->dev, "%s: timeout waiting for framedone\n",
+ __func__);
+
+ drm_crtc_vblank_off(crtc);
+
+ tilcdc_crtc_disable_irqs(dev);
+
+ pm_runtime_put_sync(dev->dev);
+
+ if (tilcdc_crtc->next_fb) {
+ drm_flip_work_queue(&tilcdc_crtc->unref_work,
+ tilcdc_crtc->next_fb);
+ tilcdc_crtc->next_fb = NULL;
+ }
+
+ if (tilcdc_crtc->curr_fb) {
+ drm_flip_work_queue(&tilcdc_crtc->unref_work,
+ tilcdc_crtc->curr_fb);
+ tilcdc_crtc->curr_fb = NULL;
+ }
+
+ drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
+ tilcdc_crtc->last_vblank = ktime_set(0, 0);
+
+ tilcdc_crtc->enabled = false;
+ mutex_unlock(&tilcdc_crtc->enable_lock);
+}
+
+static void tilcdc_crtc_disable(struct drm_crtc *crtc)
+{
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+ tilcdc_crtc_off(crtc, false);
+}
+
+void tilcdc_crtc_shutdown(struct drm_crtc *crtc)
+{
+ tilcdc_crtc_off(crtc, true);
+}
+
+static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
+{
+ return crtc->state && crtc->state->enable && crtc->state->active;
+}
+
+static void tilcdc_crtc_recover_work(struct work_struct *work)
+{
+ struct tilcdc_crtc *tilcdc_crtc =
+ container_of(work, struct tilcdc_crtc, recover_work);
+ struct drm_crtc *crtc = &tilcdc_crtc->base;
+
+ dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);
+
+ drm_modeset_lock_crtc(crtc, NULL);
+
+ if (!tilcdc_crtc_is_on(crtc))
+ goto out;
+
+ tilcdc_crtc_disable(crtc);
+ tilcdc_crtc_enable(crtc);
+out:
+ drm_modeset_unlock_crtc(crtc);
+}
+
+static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+
+ drm_modeset_lock_crtc(crtc, NULL);
+ tilcdc_crtc_disable(crtc);
+ drm_modeset_unlock_crtc(crtc);
+
+ flush_workqueue(priv->wq);
+
+ of_node_put(crtc->port);
+ drm_crtc_cleanup(crtc);
+ drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
+}
+
+int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+
+ if (tilcdc_crtc->event) {
+ dev_err(dev->dev, "already pending page flip!\n");
+ return -EBUSY;
+ }
+
+ drm_framebuffer_reference(fb);
+
+ crtc->primary->fb = fb;
+
+ spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
+
+ if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
+ ktime_t next_vblank;
+ s64 tdiff;
+
+ next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
+ 1000000 / crtc->hwmode.vrefresh);
+
+ tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
+
+ if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
+ tilcdc_crtc->next_fb = fb;
+ }
+
+ if (tilcdc_crtc->next_fb != fb)
+ set_scanout(crtc, fb);
+
+ tilcdc_crtc->event = event;
+
+ spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
+
+ return 0;
+}
+
+static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+ if (!tilcdc_crtc->simulate_vesa_sync)
+ return true;
+
+ /*
+ * tilcdc does not generate VESA-compliant sync but aligns
+ * VS on the second edge of HS instead of first edge.
+ * We use adjusted_mode, to fixup sync by aligning both rising
+ * edges and add HSKEW offset to fix the sync.
+ */
+ adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
+ adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
+
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
+ adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
+ } else {
+ adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+ adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
+ }
+
+ return true;
+}
+
static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
@@ -560,7 +709,6 @@ static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
.enable = tilcdc_crtc_enable,
.disable = tilcdc_crtc_disable,
.atomic_check = tilcdc_crtc_atomic_check,
- .mode_set_nofb = tilcdc_crtc_mode_set_nofb,
};
int tilcdc_crtc_max_width(struct drm_crtc *crtc)
@@ -756,28 +904,48 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
}
if (stat & LCDC_FIFO_UNDERFLOW)
- dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underfow",
+ dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underflow",
__func__, stat);
- /* For revision 2 only */
- if (priv->rev == 2) {
- if (stat & LCDC_FRAME_DONE) {
- tilcdc_crtc->frame_done = true;
- wake_up(&tilcdc_crtc->frame_done_wq);
- }
+ if (stat & LCDC_PL_LOAD_DONE) {
+ complete(&tilcdc_crtc->palette_loaded);
+ if (priv->rev == 1)
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_V1_PL_INT_ENA);
+ else
+ tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
+ LCDC_V2_PL_INT_ENA);
+ }
- if (stat & LCDC_SYNC_LOST) {
- dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
- __func__, stat);
- tilcdc_crtc->frame_intact = false;
- if (tilcdc_crtc->sync_lost_count++ >
- SYNC_LOST_COUNT_LIMIT) {
- dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, disabling the interrupt", __func__, stat);
+ if (stat & LCDC_SYNC_LOST) {
+ dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
+ __func__, stat);
+ tilcdc_crtc->frame_intact = false;
+ if (tilcdc_crtc->sync_lost_count++ >
+ SYNC_LOST_COUNT_LIMIT) {
+ dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat);
+ queue_work(system_wq, &tilcdc_crtc->recover_work);
+ if (priv->rev == 1)
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_V1_SYNC_LOST_INT_ENA);
+ else
tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
LCDC_SYNC_LOST);
- }
+ tilcdc_crtc->sync_lost_count = 0;
}
+ }
+
+ if (stat & LCDC_FRAME_DONE) {
+ tilcdc_crtc->frame_done = true;
+ wake_up(&tilcdc_crtc->frame_done_wq);
+ /* rev 1 lcdc appears to hang if irq is not disbaled here */
+ if (priv->rev == 1)
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+ LCDC_V1_FRAME_DONE_INT_ENA);
+ }
+ /* For revision 2 only */
+ if (priv->rev == 2) {
/* Indicate to LCDC that the interrupt service routine has
* completed, see 13.3.6.1.6 in AM335x TRM.
*/
@@ -787,7 +955,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
return IRQ_HANDLED;
}
-struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
+int tilcdc_crtc_create(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
struct tilcdc_crtc *tilcdc_crtc;
@@ -797,21 +965,33 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
tilcdc_crtc = devm_kzalloc(dev->dev, sizeof(*tilcdc_crtc), GFP_KERNEL);
if (!tilcdc_crtc) {
dev_err(dev->dev, "allocation failed\n");
- return NULL;
+ return -ENOMEM;
}
+ init_completion(&tilcdc_crtc->palette_loaded);
+ tilcdc_crtc->palette_base = dmam_alloc_coherent(dev->dev,
+ TILCDC_PALETTE_SIZE,
+ &tilcdc_crtc->palette_dma_handle,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!tilcdc_crtc->palette_base)
+ return -ENOMEM;
+ *tilcdc_crtc->palette_base = TILCDC_PALETTE_FIRST_ENTRY;
+
crtc = &tilcdc_crtc->base;
ret = tilcdc_plane_init(dev, &tilcdc_crtc->primary);
if (ret < 0)
goto fail;
+ mutex_init(&tilcdc_crtc->enable_lock);
+
init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
drm_flip_work_init(&tilcdc_crtc->unref_work,
"unref", unref_worker);
spin_lock_init(&tilcdc_crtc->irq_lock);
+ INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);
ret = drm_crtc_init_with_planes(dev, crtc,
&tilcdc_crtc->primary,
@@ -837,13 +1017,15 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
if (!crtc->port) { /* This should never happen */
dev_err(dev->dev, "Port node not found in %s\n",
dev->dev->of_node->full_name);
+ ret = -EINVAL;
goto fail;
}
}
- return crtc;
+ priv->crtc = crtc;
+ return 0;
fail:
tilcdc_crtc_destroy(crtc);
- return NULL;
+ return -ENOMEM;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index a694977c32f4..bd0a3bd07167 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -127,24 +127,16 @@ static int tilcdc_commit(struct drm_device *dev,
* current layout.
*/
- /* Keep HW on while we commit the state. */
- pm_runtime_get_sync(dev->dev);
-
drm_atomic_helper_commit_modeset_disables(dev, state);
drm_atomic_helper_commit_planes(dev, state, 0);
drm_atomic_helper_commit_modeset_enables(dev, state);
- /* Now HW should remain on if need becase the crtc is enabled */
- pm_runtime_put_sync(dev->dev);
-
drm_atomic_helper_wait_for_vblanks(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
- drm_atomic_state_free(state);
-
return 0;
}
@@ -155,15 +147,11 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
.atomic_commit = tilcdc_commit,
};
-static int modeset_init(struct drm_device *dev)
+static void modeset_init(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
struct tilcdc_module *mod;
- drm_mode_config_init(dev);
-
- priv->crtc = tilcdc_crtc_create(dev);
-
list_for_each_entry(mod, &module_list, list) {
DBG("loading module: %s", mod->name);
mod->funcs->modeset_init(mod, dev);
@@ -174,8 +162,6 @@ static int modeset_init(struct drm_device *dev)
dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
dev->mode_config.max_height = 2048;
dev->mode_config.funcs = &mode_config_funcs;
-
- return 0;
}
#ifdef CONFIG_CPU_FREQ
@@ -196,22 +182,29 @@ static int cpufreq_transition(struct notifier_block *nb,
* DRM operations:
*/
-static int tilcdc_unload(struct drm_device *dev)
+static void tilcdc_fini(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
- tilcdc_remove_external_encoders(dev);
+ if (priv->crtc)
+ tilcdc_crtc_shutdown(priv->crtc);
+
+ if (priv->is_registered)
+ drm_dev_unregister(dev);
- drm_fbdev_cma_fini(priv->fbdev);
drm_kms_helper_poll_fini(dev);
- drm_mode_config_cleanup(dev);
- drm_vblank_cleanup(dev);
+
+ if (priv->fbdev)
+ drm_fbdev_cma_fini(priv->fbdev);
drm_irq_uninstall(dev);
+ drm_mode_config_cleanup(dev);
+ tilcdc_remove_external_device(dev);
#ifdef CONFIG_CPU_FREQ
- cpufreq_unregister_notifier(&priv->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
+ if (priv->freq_transition.notifier_call)
+ cpufreq_unregister_notifier(&priv->freq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
#endif
if (priv->clk)
@@ -220,61 +213,71 @@ static int tilcdc_unload(struct drm_device *dev)
if (priv->mmio)
iounmap(priv->mmio);
- flush_workqueue(priv->wq);
- destroy_workqueue(priv->wq);
+ if (priv->wq) {
+ flush_workqueue(priv->wq);
+ destroy_workqueue(priv->wq);
+ }
dev->dev_private = NULL;
pm_runtime_disable(dev->dev);
- return 0;
+ drm_dev_unref(dev);
}
-static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
{
- struct platform_device *pdev = dev->platformdev;
- struct device_node *node = pdev->dev.of_node;
+ struct drm_device *ddev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct device_node *node = dev->of_node;
struct tilcdc_drm_private *priv;
struct resource *res;
u32 bpp = 0;
int ret;
- priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
- dev_err(dev->dev, "failed to allocate private data\n");
+ dev_err(dev, "failed to allocate private data\n");
return -ENOMEM;
}
- dev->dev_private = priv;
+ ddev = drm_dev_alloc(ddrv, dev);
+ if (IS_ERR(ddev))
+ return PTR_ERR(ddev);
+
+ ddev->platformdev = pdev;
+ ddev->dev_private = priv;
+ platform_set_drvdata(pdev, ddev);
+ drm_mode_config_init(ddev);
priv->is_componentized =
- tilcdc_get_external_components(dev->dev, NULL) > 0;
+ tilcdc_get_external_components(dev, NULL) > 0;
priv->wq = alloc_ordered_workqueue("tilcdc", 0);
if (!priv->wq) {
ret = -ENOMEM;
- goto fail_unset_priv;
+ goto init_failed;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- dev_err(dev->dev, "failed to get memory resource\n");
+ dev_err(dev, "failed to get memory resource\n");
ret = -EINVAL;
- goto fail_free_wq;
+ goto init_failed;
}
priv->mmio = ioremap_nocache(res->start, resource_size(res));
if (!priv->mmio) {
- dev_err(dev->dev, "failed to ioremap\n");
+ dev_err(dev, "failed to ioremap\n");
ret = -ENOMEM;
- goto fail_free_wq;
+ goto init_failed;
}
- priv->clk = clk_get(dev->dev, "fck");
+ priv->clk = clk_get(dev, "fck");
if (IS_ERR(priv->clk)) {
- dev_err(dev->dev, "failed to get functional clock\n");
+ dev_err(dev, "failed to get functional clock\n");
ret = -ENODEV;
- goto fail_iounmap;
+ goto init_failed;
}
#ifdef CONFIG_CPU_FREQ
@@ -282,8 +285,9 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
ret = cpufreq_register_notifier(&priv->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
- dev_err(dev->dev, "failed to register cpufreq notifier\n");
- goto fail_put_clk;
+ dev_err(dev, "failed to register cpufreq notifier\n");
+ priv->freq_transition.notifier_call = NULL;
+ goto init_failed;
}
#endif
@@ -292,22 +296,22 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
- if (of_property_read_u32(node, "ti,max-width", &priv->max_width))
+ if (of_property_read_u32(node, "max-width", &priv->max_width))
priv->max_width = TILCDC_DEFAULT_MAX_WIDTH;
DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
- if (of_property_read_u32(node, "ti,max-pixelclock",
+ if (of_property_read_u32(node, "max-pixelclock",
&priv->max_pixelclock))
priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
- pm_runtime_enable(dev->dev);
+ pm_runtime_enable(dev);
/* Determine LCD IP Version */
- pm_runtime_get_sync(dev->dev);
- switch (tilcdc_read(dev, LCDC_PID_REG)) {
+ pm_runtime_get_sync(dev);
+ switch (tilcdc_read(ddev, LCDC_PID_REG)) {
case 0x4c100102:
priv->rev = 1;
break;
@@ -316,14 +320,14 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
priv->rev = 2;
break;
default:
- dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
- "defaulting to LCD revision 1\n",
- tilcdc_read(dev, LCDC_PID_REG));
+ dev_warn(dev, "Unknown PID Reg value 0x%08x, "
+ "defaulting to LCD revision 1\n",
+ tilcdc_read(ddev, LCDC_PID_REG));
priv->rev = 1;
break;
}
- pm_runtime_put_sync(dev->dev);
+ pm_runtime_put_sync(dev);
if (priv->rev == 1) {
DBG("Revision 1 LCDC supports only RGB565 format");
@@ -356,91 +360,67 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
}
}
- ret = modeset_init(dev);
+ ret = tilcdc_crtc_create(ddev);
if (ret < 0) {
- dev_err(dev->dev, "failed to initialize mode setting\n");
- goto fail_cpufreq_unregister;
+ dev_err(dev, "failed to create crtc\n");
+ goto init_failed;
}
-
- platform_set_drvdata(pdev, dev);
+ modeset_init(ddev);
if (priv->is_componentized) {
- ret = component_bind_all(dev->dev, dev);
+ ret = component_bind_all(dev, ddev);
if (ret < 0)
- goto fail_mode_config_cleanup;
+ goto init_failed;
- ret = tilcdc_add_external_encoders(dev);
+ ret = tilcdc_add_component_encoder(ddev);
if (ret < 0)
- goto fail_component_cleanup;
+ goto init_failed;
+ } else {
+ ret = tilcdc_attach_external_device(ddev);
+ if (ret)
+ goto init_failed;
}
- if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
- dev_err(dev->dev, "no encoders/connectors found\n");
+ if (!priv->external_connector &&
+ ((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
+ dev_err(dev, "no encoders/connectors found\n");
ret = -ENXIO;
- goto fail_external_cleanup;
+ goto init_failed;
}
- ret = drm_vblank_init(dev, 1);
+ ret = drm_vblank_init(ddev, 1);
if (ret < 0) {
- dev_err(dev->dev, "failed to initialize vblank\n");
- goto fail_external_cleanup;
+ dev_err(dev, "failed to initialize vblank\n");
+ goto init_failed;
}
- ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+ ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
if (ret < 0) {
- dev_err(dev->dev, "failed to install IRQ handler\n");
- goto fail_vblank_cleanup;
+ dev_err(dev, "failed to install IRQ handler\n");
+ goto init_failed;
}
- drm_mode_config_reset(dev);
+ drm_mode_config_reset(ddev);
- priv->fbdev = drm_fbdev_cma_init(dev, bpp,
- dev->mode_config.num_crtc,
- dev->mode_config.num_connector);
+ priv->fbdev = drm_fbdev_cma_init(ddev, bpp,
+ ddev->mode_config.num_crtc,
+ ddev->mode_config.num_connector);
if (IS_ERR(priv->fbdev)) {
ret = PTR_ERR(priv->fbdev);
- goto fail_irq_uninstall;
+ goto init_failed;
}
- drm_kms_helper_poll_init(dev);
+ drm_kms_helper_poll_init(ddev);
- return 0;
-
-fail_irq_uninstall:
- drm_irq_uninstall(dev);
-
-fail_vblank_cleanup:
- drm_vblank_cleanup(dev);
-
-fail_component_cleanup:
- if (priv->is_componentized)
- component_unbind_all(dev->dev, dev);
-
-fail_mode_config_cleanup:
- drm_mode_config_cleanup(dev);
-
-fail_external_cleanup:
- tilcdc_remove_external_encoders(dev);
-
-fail_cpufreq_unregister:
- pm_runtime_disable(dev->dev);
-#ifdef CONFIG_CPU_FREQ
- cpufreq_unregister_notifier(&priv->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-
-fail_put_clk:
-#endif
- clk_put(priv->clk);
-
-fail_iounmap:
- iounmap(priv->mmio);
+ ret = drm_dev_register(ddev, 0);
+ if (ret)
+ goto init_failed;
-fail_free_wq:
- flush_workqueue(priv->wq);
- destroy_workqueue(priv->wq);
+ priv->is_registered = true;
+ return 0;
-fail_unset_priv:
- dev->dev_private = NULL;
+init_failed:
+ tilcdc_fini(ddev);
return ret;
}
@@ -575,9 +555,7 @@ static const struct file_operations fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -587,8 +565,6 @@ static const struct file_operations fops = {
static struct drm_driver tilcdc_driver = {
.driver_features = (DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET |
DRIVER_PRIME | DRIVER_ATOMIC),
- .load = tilcdc_load,
- .unload = tilcdc_unload,
.lastclose = tilcdc_lastclose,
.irq_handler = tilcdc_irq,
.get_vblank_counter = drm_vblank_no_hw_counter,
@@ -662,10 +638,9 @@ static const struct dev_pm_ops tilcdc_pm_ops = {
/*
* Platform driver:
*/
-
static int tilcdc_bind(struct device *dev)
{
- return drm_platform_init(&tilcdc_driver, to_platform_device(dev));
+ return tilcdc_init(&tilcdc_driver, dev);
}
static void tilcdc_unbind(struct device *dev)
@@ -676,7 +651,7 @@ static void tilcdc_unbind(struct device *dev)
if (!ddev->dev_private)
return;
- drm_put_dev(dev_get_drvdata(dev));
+ tilcdc_fini(dev_get_drvdata(dev));
}
static const struct component_master_ops tilcdc_comp_ops = {
@@ -699,7 +674,7 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
else if (ret == 0)
- return drm_platform_init(&tilcdc_driver, pdev);
+ return tilcdc_init(&tilcdc_driver, &pdev->dev);
else
return component_master_add_with_match(&pdev->dev,
&tilcdc_comp_ops,
@@ -714,7 +689,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
if (ret < 0)
return ret;
else if (ret == 0)
- drm_put_dev(platform_get_drvdata(pdev));
+ tilcdc_fini(platform_get_drvdata(pdev));
else
component_master_del(&pdev->dev, &tilcdc_comp_ops);
@@ -723,6 +698,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
static struct of_device_id tilcdc_of_match[] = {
{ .compatible = "ti,am33xx-tilcdc", },
+ { .compatible = "ti,da850-tilcdc", },
{ },
};
MODULE_DEVICE_TABLE(of, tilcdc_of_match);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index 9780c37ec4cd..0e71daf5b5cb 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -33,6 +33,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_bridge.h>
/* Defaulting to pixel clock defined on AM335x */
#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000
@@ -87,8 +88,12 @@ struct tilcdc_drm_private {
unsigned int num_connectors;
struct drm_connector *connectors[8];
- const struct drm_connector_helper_funcs *connector_funcs[8];
+ struct drm_encoder *external_encoder;
+ struct drm_connector *external_connector;
+ const struct drm_connector_helper_funcs *connector_funcs;
+
+ bool is_registered;
bool is_componentized;
};
@@ -163,7 +168,7 @@ struct tilcdc_panel_info {
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
+int tilcdc_crtc_create(struct drm_device *dev);
irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
@@ -172,7 +177,7 @@ void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
bool simulate_vesa_sync);
int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
int tilcdc_crtc_max_width(struct drm_crtc *crtc);
-void tilcdc_crtc_disable(struct drm_crtc *crtc);
+void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index 68e895021005..c67d7cd7d57e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -10,6 +10,7 @@
#include <linux/component.h>
#include <linux/of_graph.h>
+#include <drm/drm_of.h>
#include "tilcdc_drv.h"
#include "tilcdc_external.h"
@@ -27,44 +28,50 @@ static const struct tilcdc_panel_info panel_info_tda998x = {
.raster_order = 0,
};
+static const struct tilcdc_panel_info panel_info_default = {
+ .ac_bias = 255,
+ .ac_bias_intrpt = 0,
+ .dma_burst_sz = 16,
+ .bpp = 16,
+ .fdd = 0x80,
+ .tft_alt_mode = 0,
+ .sync_edge = 0,
+ .sync_ctrl = 1,
+ .raster_order = 0,
+};
+
static int tilcdc_external_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct tilcdc_drm_private *priv = connector->dev->dev_private;
- int ret, i;
+ int ret;
ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
if (ret != MODE_OK)
return ret;
- for (i = 0; i < priv->num_connectors &&
- priv->connectors[i] != connector; i++)
- ;
-
- BUG_ON(priv->connectors[i] != connector);
- BUG_ON(!priv->connector_funcs[i]);
+ BUG_ON(priv->external_connector != connector);
+ BUG_ON(!priv->connector_funcs);
/* If the connector has its own mode_valid call it. */
- if (!IS_ERR(priv->connector_funcs[i]) &&
- priv->connector_funcs[i]->mode_valid)
- return priv->connector_funcs[i]->mode_valid(connector, mode);
+ if (!IS_ERR(priv->connector_funcs) &&
+ priv->connector_funcs->mode_valid)
+ return priv->connector_funcs->mode_valid(connector, mode);
return MODE_OK;
}
-static int tilcdc_add_external_encoder(struct drm_device *dev,
- struct drm_connector *connector)
+static int tilcdc_add_external_connector(struct drm_device *dev,
+ struct drm_connector *connector)
{
struct tilcdc_drm_private *priv = dev->dev_private;
struct drm_connector_helper_funcs *connector_funcs;
- priv->connectors[priv->num_connectors] = connector;
- priv->encoders[priv->num_encoders++] = connector->encoder;
-
- /* Only tda998x is supported at the moment. */
- tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
- tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
+ /* There should never be more than one connector */
+ if (WARN_ON(priv->external_connector))
+ return -EINVAL;
+ priv->external_connector = connector;
connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs),
GFP_KERNEL);
if (!connector_funcs)
@@ -77,56 +84,177 @@ static int tilcdc_add_external_encoder(struct drm_device *dev,
* everything else but use our own mode_valid() (above).
*/
if (connector->helper_private) {
- priv->connector_funcs[priv->num_connectors] =
- connector->helper_private;
- *connector_funcs = *priv->connector_funcs[priv->num_connectors];
+ priv->connector_funcs = connector->helper_private;
+ *connector_funcs = *priv->connector_funcs;
} else {
- priv->connector_funcs[priv->num_connectors] = ERR_PTR(-ENOENT);
+ priv->connector_funcs = ERR_PTR(-ENOENT);
}
connector_funcs->mode_valid = tilcdc_external_mode_valid;
drm_connector_helper_add(connector, connector_funcs);
- priv->num_connectors++;
- dev_dbg(dev->dev, "External encoder '%s' connected\n",
- connector->encoder->name);
+ dev_dbg(dev->dev, "External connector '%s' connected\n",
+ connector->name);
return 0;
}
-int tilcdc_add_external_encoders(struct drm_device *dev)
+static
+struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
+ struct drm_encoder *encoder)
{
- struct tilcdc_drm_private *priv = dev->dev_private;
struct drm_connector *connector;
- int num_internal_connectors = priv->num_connectors;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- bool found = false;
- int i, ret;
-
- for (i = 0; i < num_internal_connectors; i++)
- if (connector == priv->connectors[i])
- found = true;
- if (!found) {
- ret = tilcdc_add_external_encoder(dev, connector);
- if (ret)
- return ret;
- }
+ int i;
+
+ list_for_each_entry(connector, &ddev->mode_config.connector_list, head)
+ for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
+ if (connector->encoder_ids[i] == encoder->base.id)
+ return connector;
+
+ dev_err(ddev->dev, "No connector found for %s encoder (id %d)\n",
+ encoder->name, encoder->base.id);
+
+ return NULL;
+}
+
+int tilcdc_add_component_encoder(struct drm_device *ddev)
+{
+ struct tilcdc_drm_private *priv = ddev->dev_private;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+
+ list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head)
+ if (encoder->possible_crtcs & (1 << priv->crtc->index))
+ break;
+
+ if (!encoder) {
+ dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__);
+ return -ENODEV;
}
- return 0;
+
+ connector = tilcdc_encoder_find_connector(ddev, encoder);
+
+ if (!connector)
+ return -ENODEV;
+
+ /* Only tda998x is supported at the moment. */
+ tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
+ tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
+
+ return tilcdc_add_external_connector(ddev, connector);
}
-void tilcdc_remove_external_encoders(struct drm_device *dev)
+void tilcdc_remove_external_device(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
- int i;
/* Restore the original helper functions, if any. */
- for (i = 0; i < priv->num_connectors; i++)
- if (IS_ERR(priv->connector_funcs[i]))
- drm_connector_helper_add(priv->connectors[i], NULL);
- else if (priv->connector_funcs[i])
- drm_connector_helper_add(priv->connectors[i],
- priv->connector_funcs[i]);
+ if (IS_ERR(priv->connector_funcs))
+ drm_connector_helper_add(priv->external_connector, NULL);
+ else if (priv->connector_funcs)
+ drm_connector_helper_add(priv->external_connector,
+ priv->connector_funcs);
+}
+
+static const struct drm_encoder_funcs tilcdc_external_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static
+int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
+{
+ struct tilcdc_drm_private *priv = ddev->dev_private;
+ struct drm_connector *connector;
+ int ret;
+
+ priv->external_encoder->possible_crtcs = BIT(0);
+ priv->external_encoder->bridge = bridge;
+ bridge->encoder = priv->external_encoder;
+
+ ret = drm_bridge_attach(ddev, bridge);
+ if (ret) {
+ dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
+ return ret;
+ }
+
+ tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
+
+ connector = tilcdc_encoder_find_connector(ddev, priv->external_encoder);
+ if (!connector)
+ return -ENODEV;
+
+ ret = tilcdc_add_external_connector(ddev, connector);
+
+ return ret;
+}
+
+static int tilcdc_node_has_port(struct device_node *dev_node)
+{
+ struct device_node *node;
+
+ node = of_get_child_by_name(dev_node, "ports");
+ if (!node)
+ node = of_get_child_by_name(dev_node, "port");
+ if (!node)
+ return 0;
+ of_node_put(node);
+
+ return 1;
+}
+
+static
+struct device_node *tilcdc_get_remote_node(struct device_node *node)
+{
+ struct device_node *ep;
+ struct device_node *parent;
+
+ if (!tilcdc_node_has_port(node))
+ return NULL;
+
+ ep = of_graph_get_next_endpoint(node, NULL);
+ if (!ep)
+ return NULL;
+
+ parent = of_graph_get_remote_port_parent(ep);
+ of_node_put(ep);
+
+ return parent;
+}
+
+int tilcdc_attach_external_device(struct drm_device *ddev)
+{
+ struct tilcdc_drm_private *priv = ddev->dev_private;
+ struct device_node *remote_node;
+ struct drm_bridge *bridge;
+ int ret;
+
+ remote_node = tilcdc_get_remote_node(ddev->dev->of_node);
+ if (!remote_node)
+ return 0;
+
+ bridge = of_drm_find_bridge(remote_node);
+ of_node_put(remote_node);
+ if (!bridge)
+ return -EPROBE_DEFER;
+
+ priv->external_encoder = devm_kzalloc(ddev->dev,
+ sizeof(*priv->external_encoder),
+ GFP_KERNEL);
+ if (!priv->external_encoder)
+ return -ENOMEM;
+
+ ret = drm_encoder_init(ddev, priv->external_encoder,
+ &tilcdc_external_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
+ if (ret) {
+ dev_err(ddev->dev, "drm_encoder_init() failed %d\n", ret);
+ return ret;
+ }
+
+ ret = tilcdc_attach_bridge(ddev, bridge);
+ if (ret)
+ drm_encoder_cleanup(priv->external_encoder);
+
+ return ret;
}
static int dev_match_of(struct device *dev, void *data)
@@ -140,16 +268,10 @@ int tilcdc_get_external_components(struct device *dev,
struct device_node *node;
struct device_node *ep = NULL;
int count = 0;
+ int ret = 0;
- /* Avoid error print by of_graph_get_next_endpoint() if there
- * is no ports present.
- */
- node = of_get_child_by_name(dev->of_node, "ports");
- if (!node)
- node = of_get_child_by_name(dev->of_node, "port");
- if (!node)
+ if (!tilcdc_node_has_port(dev->of_node))
return 0;
- of_node_put(node);
while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) {
node = of_graph_get_remote_port_parent(ep);
@@ -159,16 +281,20 @@ int tilcdc_get_external_components(struct device *dev,
}
dev_dbg(dev, "Subdevice node '%s' found\n", node->name);
- if (match)
- component_match_add(dev, match, dev_match_of, node);
- of_node_put(node);
- count++;
- }
- if (count > 1) {
- dev_err(dev, "Only one external encoder is supported\n");
- return -EINVAL;
+ if (of_device_is_compatible(node, "nxp,tda998x")) {
+ if (match)
+ drm_of_component_match_add(dev, match,
+ dev_match_of, node);
+ ret = 1;
+ }
+
+ of_node_put(node);
+ if (count++ > 1) {
+ dev_err(dev, "Only one port is supported\n");
+ return -EINVAL;
+ }
}
- return count;
+ return ret;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.h b/drivers/gpu/drm/tilcdc/tilcdc_external.h
index c700e0c1623e..763d18f006c7 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.h
@@ -18,8 +18,9 @@
#ifndef __TILCDC_EXTERNAL_H__
#define __TILCDC_EXTERNAL_H__
-int tilcdc_add_external_encoders(struct drm_device *dev);
-void tilcdc_remove_external_encoders(struct drm_device *dev);
+int tilcdc_add_component_encoder(struct drm_device *dev);
+void tilcdc_remove_external_device(struct drm_device *dev);
int tilcdc_get_external_components(struct device *dev,
struct component_match **match);
+int tilcdc_attach_external_device(struct drm_device *ddev);
#endif /* __TILCDC_SLAVE_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 2134bb20fbe9..28c3e2f44f64 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -144,13 +144,6 @@ static void panel_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
-static enum drm_connector_status panel_connector_detect(
- struct drm_connector *connector,
- bool force)
-{
- return connector_status_connected;
-}
-
static int panel_connector_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -197,7 +190,6 @@ static struct drm_encoder *panel_connector_best_encoder(
static const struct drm_connector_funcs panel_connector_funcs = {
.destroy = panel_connector_destroy,
.dpms = drm_atomic_helper_connector_dpms,
- .detect = panel_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -240,8 +232,6 @@ static struct drm_connector *panel_connector_create(struct drm_device *dev,
if (ret)
goto fail;
- drm_connector_register(connector);
-
return connector;
fail:
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c
index 74c65fa859b2..8a6a50d74aff 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c
@@ -39,7 +39,7 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane,
{
struct drm_crtc_state *crtc_state;
struct drm_plane_state *old_state = plane->state;
- unsigned int depth, bpp;
+ unsigned int pitch;
if (!state->crtc)
return 0;
@@ -68,8 +68,9 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- drm_fb_get_bpp_depth(state->fb->pixel_format, &depth, &bpp);
- if (state->fb->pitches[0] != crtc_state->mode.hdisplay * bpp / 8) {
+ pitch = crtc_state->mode.hdisplay *
+ drm_format_plane_cpp(state->fb->pixel_format, 0);
+ if (state->fb->pitches[0] != pitch) {
dev_err(plane->dev->dev,
"Invalid pitch: fb and crtc widths must be the same");
return -EINVAL;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
index f57c0d62c76a..9d528c0a67a4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
@@ -34,11 +34,14 @@
/* LCDC DMA Control Register */
#define LCDC_DMA_BURST_SIZE(x) ((x) << 4)
+#define LCDC_DMA_BURST_SIZE_MASK ((0x7) << 4)
#define LCDC_DMA_BURST_1 0x0
#define LCDC_DMA_BURST_2 0x1
#define LCDC_DMA_BURST_4 0x2
#define LCDC_DMA_BURST_8 0x3
#define LCDC_DMA_BURST_16 0x4
+#define LCDC_DMA_FIFO_THRESHOLD(x) ((x) << 8)
+#define LCDC_DMA_FIFO_THRESHOLD_MASK ((0x3) << 8)
#define LCDC_V1_END_OF_FRAME_INT_ENA BIT(2)
#define LCDC_V2_END_OF_FRAME0_INT_ENA BIT(8)
#define LCDC_V2_END_OF_FRAME1_INT_ENA BIT(9)
@@ -46,10 +49,12 @@
/* LCDC Control Register */
#define LCDC_CLK_DIVISOR(x) ((x) << 8)
+#define LCDC_CLK_DIVISOR_MASK ((0xFF) << 8)
#define LCDC_RASTER_MODE 0x01
/* LCDC Raster Control Register */
#define LCDC_PALETTE_LOAD_MODE(x) ((x) << 20)
+#define LCDC_PALETTE_LOAD_MODE_MASK ((0x3) << 20)
#define PALETTE_AND_DATA 0x00
#define PALETTE_ONLY 0x01
#define DATA_ONLY 0x02
@@ -61,6 +66,8 @@
#define LCDC_V2_UNDERFLOW_INT_ENA BIT(5)
#define LCDC_V1_PL_INT_ENA BIT(4)
#define LCDC_V2_PL_INT_ENA BIT(6)
+#define LCDC_V1_SYNC_LOST_INT_ENA BIT(5)
+#define LCDC_V1_FRAME_DONE_INT_ENA BIT(3)
#define LCDC_MONOCHROME_MODE BIT(1)
#define LCDC_RASTER_ENABLE BIT(0)
#define LCDC_TFT_ALT_ENABLE BIT(23)
@@ -74,7 +81,9 @@
/* LCDC Raster Timing 2 Register */
#define LCDC_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
+#define LCDC_AC_BIAS_TRANSITIONS_PER_INT_MASK ((0xF) << 16)
#define LCDC_AC_BIAS_FREQUENCY(x) ((x) << 8)
+#define LCDC_AC_BIAS_FREQUENCY_MASK ((0xFF) << 8)
#define LCDC_SYNC_CTRL BIT(25)
#define LCDC_SYNC_EDGE BIT(24)
#define LCDC_INVERT_PIXEL_CLOCK BIT(22)
@@ -139,6 +148,12 @@ static inline u32 tilcdc_read(struct drm_device *dev, u32 reg)
return ioread32(priv->mmio + reg);
}
+static inline void tilcdc_write_mask(struct drm_device *dev, u32 reg,
+ u32 val, u32 mask)
+{
+ tilcdc_write(dev, reg, (tilcdc_read(dev, reg) & ~mask) | (val & mask));
+}
+
static inline void tilcdc_set(struct drm_device *dev, u32 reg, u32 mask)
{
tilcdc_write(dev, reg, tilcdc_read(dev, reg) | mask);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
index 458043a53995..aabfad882e23 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -249,8 +249,6 @@ static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
if (ret)
goto fail;
- drm_connector_register(connector);
-
return connector;
fail:
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index fc6217dfe401..d5063618efa7 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -148,7 +148,7 @@ static void ttm_bo_release_list(struct kref *list_kref)
BUG_ON(!list_empty(&bo->ddestroy));
ttm_tt_destroy(bo->ttm);
atomic_dec(&bo->glob->bo_count);
- fence_put(bo->moving);
+ dma_fence_put(bo->moving);
if (bo->resv == &bo->ttm_resv)
reservation_object_fini(&bo->ttm_resv);
mutex_destroy(&bo->wu_mutex);
@@ -426,20 +426,20 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
{
struct reservation_object_list *fobj;
- struct fence *fence;
+ struct dma_fence *fence;
int i;
fobj = reservation_object_get_list(bo->resv);
fence = reservation_object_get_excl(bo->resv);
if (fence && !fence->ops->signaled)
- fence_enable_sw_signaling(fence);
+ dma_fence_enable_sw_signaling(fence);
for (i = 0; fobj && i < fobj->shared_count; ++i) {
fence = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(bo->resv));
if (!fence->ops->signaled)
- fence_enable_sw_signaling(fence);
+ dma_fence_enable_sw_signaling(fence);
}
}
@@ -717,6 +717,20 @@ out:
return ret;
}
+bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
+ const struct ttm_place *place)
+{
+ /* Don't evict this BO if it's outside of the
+ * requested placement range
+ */
+ if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
+ (place->lpfn && place->lpfn <= bo->mem.start))
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL(ttm_bo_eviction_valuable);
+
static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
uint32_t mem_type,
const struct ttm_place *place,
@@ -731,21 +745,16 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
spin_lock(&glob->lru_lock);
list_for_each_entry(bo, &man->lru, lru) {
ret = __ttm_bo_reserve(bo, false, true, NULL);
- if (!ret) {
- if (place && (place->fpfn || place->lpfn)) {
- /* Don't evict this BO if it's outside of the
- * requested placement range
- */
- if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
- (place->lpfn && place->lpfn <= bo->mem.start)) {
- __ttm_bo_unreserve(bo);
- ret = -EBUSY;
- continue;
- }
- }
+ if (ret)
+ continue;
- break;
+ if (place && !bdev->driver->eviction_valuable(bo, place)) {
+ __ttm_bo_unreserve(bo);
+ ret = -EBUSY;
+ continue;
}
+
+ break;
}
if (ret) {
@@ -792,11 +801,11 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
- struct fence *fence;
+ struct dma_fence *fence;
int ret;
spin_lock(&man->move_lock);
- fence = fence_get(man->move);
+ fence = dma_fence_get(man->move);
spin_unlock(&man->move_lock);
if (fence) {
@@ -806,7 +815,7 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
if (unlikely(ret))
return ret;
- fence_put(bo->moving);
+ dma_fence_put(bo->moving);
bo->moving = fence;
}
@@ -1286,7 +1295,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
{
struct ttm_mem_type_manager *man = &bdev->man[mem_type];
struct ttm_bo_global *glob = bdev->glob;
- struct fence *fence;
+ struct dma_fence *fence;
int ret;
/*
@@ -1309,12 +1318,12 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
spin_unlock(&glob->lru_lock);
spin_lock(&man->move_lock);
- fence = fence_get(man->move);
+ fence = dma_fence_get(man->move);
spin_unlock(&man->move_lock);
if (fence) {
- ret = fence_wait(fence, false);
- fence_put(fence);
+ ret = dma_fence_wait(fence, false);
+ dma_fence_put(fence);
if (ret) {
if (allow_errors) {
return ret;
@@ -1343,7 +1352,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
mem_type);
return ret;
}
- fence_put(man->move);
+ dma_fence_put(man->move);
man->use_type = false;
man->has_type = false;
@@ -1602,7 +1611,14 @@ EXPORT_SYMBOL(ttm_bo_unmap_virtual);
int ttm_bo_wait(struct ttm_buffer_object *bo,
bool interruptible, bool no_wait)
{
- long timeout = no_wait ? 0 : 15 * HZ;
+ long timeout = 15 * HZ;
+
+ if (no_wait) {
+ if (reservation_object_test_signaled_rcu(bo->resv, true))
+ return 0;
+ else
+ return -EBUSY;
+ }
timeout = reservation_object_wait_timeout_rcu(bo->resv, true,
interruptible, timeout);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index bf6e21655c57..d0459b392e5e 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -644,7 +644,7 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map)
EXPORT_SYMBOL(ttm_bo_kunmap);
int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
- struct fence *fence,
+ struct dma_fence *fence,
bool evict,
struct ttm_mem_reg *new_mem)
{
@@ -674,8 +674,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
* operation has completed.
*/
- fence_put(bo->moving);
- bo->moving = fence_get(fence);
+ dma_fence_put(bo->moving);
+ bo->moving = dma_fence_get(fence);
ret = ttm_buffer_object_transfer(bo, &ghost_obj);
if (ret)
@@ -706,7 +706,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
- struct fence *fence, bool evict,
+ struct dma_fence *fence, bool evict,
struct ttm_mem_reg *new_mem)
{
struct ttm_bo_device *bdev = bo->bdev;
@@ -730,8 +730,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
* operation has completed.
*/
- fence_put(bo->moving);
- bo->moving = fence_get(fence);
+ dma_fence_put(bo->moving);
+ bo->moving = dma_fence_get(fence);
ret = ttm_buffer_object_transfer(bo, &ghost_obj);
if (ret)
@@ -761,16 +761,16 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
*/
spin_lock(&from->move_lock);
- if (!from->move || fence_is_later(fence, from->move)) {
- fence_put(from->move);
- from->move = fence_get(fence);
+ if (!from->move || dma_fence_is_later(fence, from->move)) {
+ dma_fence_put(from->move);
+ from->move = dma_fence_get(fence);
}
spin_unlock(&from->move_lock);
ttm_bo_free_old_node(bo);
- fence_put(bo->moving);
- bo->moving = fence_get(fence);
+ dma_fence_put(bo->moving);
+ bo->moving = dma_fence_get(fence);
} else {
/**
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index a6ed9d5e5167..4748aedc933a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -54,7 +54,7 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
/*
* Quick non-stalling check for idle.
*/
- if (fence_is_signaled(bo->moving))
+ if (dma_fence_is_signaled(bo->moving))
goto out_clear;
/*
@@ -67,14 +67,14 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
goto out_unlock;
up_read(&vma->vm_mm->mmap_sem);
- (void) fence_wait(bo->moving, true);
+ (void) dma_fence_wait(bo->moving, true);
goto out_unlock;
}
/*
* Ordinary wait.
*/
- ret = fence_wait(bo->moving, true);
+ ret = dma_fence_wait(bo->moving, true);
if (unlikely(ret != 0)) {
ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS :
VM_FAULT_NOPAGE;
@@ -82,7 +82,7 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
}
out_clear:
- fence_put(bo->moving);
+ dma_fence_put(bo->moving);
bo->moving = NULL;
out_unlock:
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index a80717b35dc6..d35bc491e8de 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -179,7 +179,8 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
EXPORT_SYMBOL(ttm_eu_reserve_buffers);
void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
- struct list_head *list, struct fence *fence)
+ struct list_head *list,
+ struct dma_fence *fence)
{
struct ttm_validate_buffer *entry;
struct ttm_buffer_object *bo;
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cc45d98f9bb5..cd8b01727734 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -44,9 +44,7 @@ static const struct file_operations udl_driver_fops = {
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
.release = drm_release,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 611b6b9bb3cb..167f42c67c7c 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -254,16 +254,10 @@ static int udl_fb_release(struct fb_info *info, int user)
static struct fb_ops udlfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
.fb_mmap = udl_fb_mmap,
.fb_open = udl_fb_open,
.fb_release = udl_fb_release,
diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index fb77db755e0a..7757f69a8a77 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -11,6 +11,7 @@ vc4-y := \
vc4_kms.o \
vc4_gem.o \
vc4_hdmi.o \
+ vc4_vec.o \
vc4_hvs.o \
vc4_irq.o \
vc4_plane.o \
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7f08d681a74b..a0fd3e66bc4b 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -83,8 +83,7 @@ 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;
+ enum vc4_encoder_type encoder_types[4];
};
#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
@@ -669,6 +668,14 @@ void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
CRTC_WRITE(PV_INTEN, 0);
}
+/* Must be called with the event lock held */
+bool vc4_event_pending(struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+ return !!vc4_crtc->event;
+}
+
static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
{
struct drm_crtc *crtc = &vc4_crtc->base;
@@ -859,20 +866,26 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
static const struct vc4_crtc_data pv0_data = {
.hvs_channel = 0,
- .encoder0_type = VC4_ENCODER_TYPE_DSI0,
- .encoder1_type = VC4_ENCODER_TYPE_DPI,
+ .encoder_types = {
+ [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
+ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = 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,
+ .encoder_types = {
+ [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
+ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = 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,
+ .encoder_types = {
+ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
+ [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
+ },
};
static const struct of_device_id vc4_crtc_dt_match[] = {
@@ -886,17 +899,20 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
struct drm_crtc *crtc)
{
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ const struct vc4_crtc_data *crtc_data = vc4_crtc->data;
+ const enum vc4_encoder_type *encoder_types = crtc_data->encoder_types;
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);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(crtc_data->encoder_types); i++) {
+ if (vc4_encoder->type == encoder_types[i]) {
+ vc4_encoder->clock_select = i;
+ encoder->possible_crtcs |= drm_crtc_mask(crtc);
+ break;
+ }
}
}
}
diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c
index 245115d49c46..caf817bac885 100644
--- a/drivers/gpu/drm/vc4/vc4_debugfs.c
+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c
@@ -19,6 +19,7 @@ static const struct drm_info_list vc4_debugfs_list[] = {
{"bo_stats", vc4_bo_stats_debugfs, 0},
{"dpi_regs", vc4_dpi_debugfs_regs, 0},
{"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
+ {"vec_regs", vc4_vec_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},
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 8703f56b7947..ac09ca7ff430 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -61,23 +61,28 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
if (ret < 0)
return ret;
args->value = V3D_READ(V3D_IDENT0);
- pm_runtime_put(&vc4->v3d->pdev->dev);
+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
break;
case DRM_VC4_PARAM_V3D_IDENT1:
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
if (ret < 0)
return ret;
args->value = V3D_READ(V3D_IDENT1);
- pm_runtime_put(&vc4->v3d->pdev->dev);
+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
break;
case DRM_VC4_PARAM_V3D_IDENT2:
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
if (ret < 0)
return ret;
args->value = V3D_READ(V3D_IDENT2);
- pm_runtime_put(&vc4->v3d->pdev->dev);
+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
break;
case DRM_VC4_PARAM_SUPPORTS_BRANCHES:
+ case DRM_VC4_PARAM_SUPPORTS_ETC1:
+ case DRM_VC4_PARAM_SUPPORTS_THREADED_FS:
args->value = true;
break;
default:
@@ -103,9 +108,7 @@ static const struct file_operations vc4_drm_fops = {
.mmap = vc4_mmap,
.poll = drm_poll,
.read = drm_read,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
@@ -274,12 +277,14 @@ static void vc4_drm_unbind(struct device *dev)
struct drm_device *drm = platform_get_drvdata(pdev);
struct vc4_dev *vc4 = to_vc4_dev(drm);
+ drm_dev_unregister(drm);
+
if (vc4->fbdev)
drm_fbdev_cma_fini(vc4->fbdev);
drm_mode_config_cleanup(drm);
- drm_put_dev(drm);
+ drm_dev_unref(drm);
}
static const struct component_master_ops vc4_drm_ops = {
@@ -289,6 +294,7 @@ static const struct component_master_ops vc4_drm_ops = {
static struct platform_driver *const component_drivers[] = {
&vc4_hdmi_driver,
+ &vc4_vec_driver,
&vc4_dpi_driver,
&vc4_hvs_driver,
&vc4_crtc_driver,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 7c1e4d97486f..b5c4bb14d0d1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -17,6 +17,7 @@ struct vc4_dev {
struct vc4_crtc *crtc[3];
struct vc4_v3d *v3d;
struct vc4_dpi *dpi;
+ struct vc4_vec *vec;
struct drm_fbdev_cma *fbdev;
@@ -194,6 +195,7 @@ to_vc4_plane(struct drm_plane *plane)
}
enum vc4_encoder_type {
+ VC4_ENCODER_TYPE_NONE,
VC4_ENCODER_TYPE_HDMI,
VC4_ENCODER_TYPE_VEC,
VC4_ENCODER_TYPE_DSI0,
@@ -381,6 +383,8 @@ struct vc4_validated_shader_info {
uint32_t num_uniform_addr_offsets;
uint32_t *uniform_addr_offsets;
+
+ bool is_threaded;
};
/**
@@ -440,6 +444,7 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
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);
+bool vc4_event_pending(struct drm_crtc *crtc);
int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
unsigned int flags, int *vpos, int *hpos,
@@ -483,6 +488,10 @@ int vc4_queue_seqno_cb(struct drm_device *dev,
extern struct platform_driver vc4_hdmi_driver;
int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused);
+/* vc4_hdmi.c */
+extern struct platform_driver vc4_vec_driver;
+int vc4_vec_debugfs_regs(struct seq_file *m, void *unused);
+
/* vc4_irq.c */
irqreturn_t vc4_irq(int irq, void *arg);
void vc4_irq_preinstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 47a095f392f8..db920771bfb5 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -544,14 +544,15 @@ vc4_cl_lookup_bos(struct drm_device *dev,
handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t));
if (!handles) {
+ ret = -ENOMEM;
DRM_ERROR("Failed to allocate incoming GEM handles\n");
goto fail;
}
- ret = copy_from_user(handles,
- (void __user *)(uintptr_t)args->bo_handles,
- exec->bo_count * sizeof(uint32_t));
- if (ret) {
+ if (copy_from_user(handles,
+ (void __user *)(uintptr_t)args->bo_handles,
+ exec->bo_count * sizeof(uint32_t))) {
+ ret = -EFAULT;
DRM_ERROR("Failed to copy in GEM handles\n");
goto fail;
}
@@ -708,8 +709,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
}
mutex_lock(&vc4->power_lock);
- if (--vc4->power_refcount == 0)
- pm_runtime_put(&vc4->v3d->pdev->dev);
+ if (--vc4->power_refcount == 0) {
+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
+ }
mutex_unlock(&vc4->power_lock);
kfree(exec);
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index c1f65c6c8e60..be8dd8262f27 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -61,7 +61,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c)
drm_atomic_helper_cleanup_planes(dev, state);
- drm_atomic_state_free(state);
+ drm_atomic_state_put(state);
up(&vc4->async_modeset);
@@ -119,17 +119,34 @@ static int vc4_atomic_commit(struct drm_device *dev,
/* Make sure that any outstanding modesets have finished. */
if (nonblock) {
- ret = down_trylock(&vc4->async_modeset);
- if (ret) {
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ unsigned long flags;
+ bool busy = false;
+
+ /*
+ * If there's an undispatched event to send then we're
+ * obviously still busy. If there isn't, then we can
+ * unconditionally wait for the semaphore because it
+ * shouldn't be contended (for long).
+ *
+ * This is to prevent a race where queuing a new flip
+ * from userspace immediately on receipt of an event
+ * beats our clean-up and returns EBUSY.
+ */
+ spin_lock_irqsave(&dev->event_lock, flags);
+ for_each_crtc_in_state(state, crtc, crtc_state, i)
+ busy |= vc4_event_pending(crtc);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ if (busy) {
kfree(c);
return -EBUSY;
}
- } else {
- ret = down_interruptible(&vc4->async_modeset);
- if (ret) {
- kfree(c);
- return ret;
- }
+ }
+ ret = down_interruptible(&vc4->async_modeset);
+ if (ret) {
+ kfree(c);
+ return ret;
}
ret = drm_atomic_helper_prepare_planes(dev, state);
@@ -173,6 +190,7 @@ static int vc4_atomic_commit(struct drm_device *dev,
* current layout.
*/
+ drm_atomic_state_get(state);
if (nonblock) {
vc4_queue_seqno_cb(dev, &c->cb, wait_seqno,
vc4_atomic_complete_commit_seqno_cb);
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 1aa44c2db556..39f6886b2410 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -177,8 +177,9 @@
# define PV_CONTROL_WAIT_HSTART BIT(12)
# define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4)
# define PV_CONTROL_PIXEL_REP_SHIFT 4
-# define PV_CONTROL_CLK_SELECT_DSI_VEC 0
+# define PV_CONTROL_CLK_SELECT_DSI 0
# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1
+# define PV_CONTROL_CLK_SELECT_VEC 2
# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2)
# define PV_CONTROL_CLK_SELECT_SHIFT 2
# define PV_CONTROL_FIFO_CLR BIT(1)
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index e6d3c6028341..7cc346ad9b0b 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
return ret;
}
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
pm_runtime_enable(dev);
return 0;
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
index 26503e307438..9fd171c361c2 100644
--- a/drivers/gpu/drm/vc4/vc4_validate.c
+++ b/drivers/gpu/drm/vc4/vc4_validate.c
@@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec,
cpp = 1;
break;
case VC4_TEXTURE_TYPE_ETC1:
+ /* ETC1 is arranged as 64-bit blocks, where each block is 4x4
+ * pixels.
+ */
+ cpp = 8;
+ width = (width + 3) >> 2;
+ height = (height + 3) >> 2;
+ break;
case VC4_TEXTURE_TYPE_BW1:
case VC4_TEXTURE_TYPE_A4:
case VC4_TEXTURE_TYPE_A1:
@@ -782,11 +789,6 @@ validate_gl_shader_rec(struct drm_device *dev,
exec->shader_rec_v += roundup(packet_size, 16);
exec->shader_rec_size -= packet_size;
- if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) {
- DRM_ERROR("Multi-threaded fragment shaders not supported.\n");
- return -EINVAL;
- }
-
for (i = 0; i < shader_reloc_count; i++) {
if (src_handles[i] > exec->bo_count) {
DRM_ERROR("Shader handle %d too big\n", src_handles[i]);
@@ -803,6 +805,18 @@ validate_gl_shader_rec(struct drm_device *dev,
return -EINVAL;
}
+ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) !=
+ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) {
+ DRM_ERROR("Thread mode of CL and FS do not match\n");
+ return -EINVAL;
+ }
+
+ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded ||
+ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) {
+ DRM_ERROR("cs and vs cannot be threaded\n");
+ return -EINVAL;
+ }
+
for (i = 0; i < shader_reloc_count; i++) {
struct vc4_validated_shader_info *validated_shader;
uint32_t o = shader_reloc_offsets[i];
diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
index 2543cf5b8b51..5dba13dd1e9b 100644
--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c
+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
@@ -83,6 +83,13 @@ struct vc4_shader_validation_state {
* basic blocks.
*/
bool needs_uniform_address_for_loop;
+
+ /* Set when we find an instruction writing the top half of the
+ * register files. If we allowed writing the unusable regs in
+ * a threaded shader, then the other shader running on our
+ * QPU's clamp validation would be invalid.
+ */
+ bool all_registers_used;
};
static uint32_t
@@ -119,6 +126,13 @@ raddr_add_a_to_live_reg_index(uint64_t inst)
}
static bool
+live_reg_is_upper_half(uint32_t lri)
+{
+ return (lri >= 16 && lri < 32) ||
+ (lri >= 32 + 16 && lri < 32 + 32);
+}
+
+static bool
is_tmu_submit(uint32_t waddr)
{
return (waddr == QPU_W_TMU0_S ||
@@ -390,6 +404,9 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader,
} else {
validation_state->live_immediates[lri] = ~0;
}
+
+ if (live_reg_is_upper_half(lri))
+ validation_state->all_registers_used = true;
}
switch (waddr) {
@@ -598,6 +615,11 @@ check_instruction_reads(struct vc4_validated_shader_info *validated_shader,
}
}
+ if ((raddr_a >= 16 && raddr_a < 32) ||
+ (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) {
+ validation_state->all_registers_used = true;
+ }
+
return true;
}
@@ -608,9 +630,7 @@ static bool
vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
{
uint32_t max_branch_target = 0;
- bool found_shader_end = false;
int ip;
- int shader_end_ip = 0;
int last_branch = -2;
for (ip = 0; ip < validation_state->max_ip; ip++) {
@@ -621,8 +641,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
uint32_t branch_target_ip;
if (sig == QPU_SIG_PROG_END) {
- shader_end_ip = ip;
- found_shader_end = true;
+ /* There are two delay slots after program end is
+ * signaled that are still executed, then we're
+ * finished. validation_state->max_ip is the
+ * instruction after the last valid instruction in the
+ * program.
+ */
+ validation_state->max_ip = ip + 3;
continue;
}
@@ -676,15 +701,9 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
}
set_bit(after_delay_ip, validation_state->branch_targets);
max_branch_target = max(max_branch_target, after_delay_ip);
-
- /* There are two delay slots after program end is signaled
- * that are still executed, then we're finished.
- */
- if (found_shader_end && ip == shader_end_ip + 2)
- break;
}
- if (max_branch_target > shader_end_ip) {
+ if (max_branch_target > validation_state->max_ip - 3) {
DRM_ERROR("Branch landed after QPU_SIG_PROG_END");
return false;
}
@@ -756,6 +775,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
{
bool found_shader_end = false;
int shader_end_ip = 0;
+ uint32_t last_thread_switch_ip = -3;
uint32_t ip;
struct vc4_validated_shader_info *validated_shader = NULL;
struct vc4_shader_validation_state validation_state;
@@ -788,6 +808,17 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
if (!vc4_handle_branch_target(&validation_state))
goto fail;
+ if (ip == last_thread_switch_ip + 3) {
+ /* Reset r0-r3 live clamp data */
+ int i;
+
+ for (i = 64; i < LIVE_REG_COUNT; i++) {
+ validation_state.live_min_clamp_offsets[i] = ~0;
+ validation_state.live_max_clamp_regs[i] = false;
+ validation_state.live_immediates[i] = ~0;
+ }
+ }
+
switch (sig) {
case QPU_SIG_NONE:
case QPU_SIG_WAIT_FOR_SCOREBOARD:
@@ -797,6 +828,8 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
case QPU_SIG_LOAD_TMU1:
case QPU_SIG_PROG_END:
case QPU_SIG_SMALL_IMM:
+ case QPU_SIG_THREAD_SWITCH:
+ case QPU_SIG_LAST_THREAD_SWITCH:
if (!check_instruction_writes(validated_shader,
&validation_state)) {
DRM_ERROR("Bad write at ip %d\n", ip);
@@ -812,6 +845,18 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
shader_end_ip = ip;
}
+ if (sig == QPU_SIG_THREAD_SWITCH ||
+ sig == QPU_SIG_LAST_THREAD_SWITCH) {
+ validated_shader->is_threaded = true;
+
+ if (ip < last_thread_switch_ip + 3) {
+ DRM_ERROR("Thread switch too soon after "
+ "last switch at ip %d\n", ip);
+ goto fail;
+ }
+ last_thread_switch_ip = ip;
+ }
+
break;
case QPU_SIG_LOAD_IMM:
@@ -826,6 +871,13 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
if (!check_branch(inst, validated_shader,
&validation_state, ip))
goto fail;
+
+ if (ip < last_thread_switch_ip + 3) {
+ DRM_ERROR("Branch in thread switch at ip %d",
+ ip);
+ goto fail;
+ }
+
break;
default:
DRM_ERROR("Unsupported QPU signal %d at "
@@ -847,6 +899,14 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
goto fail;
}
+ /* Might corrupt other thread */
+ if (validated_shader->is_threaded &&
+ validation_state.all_registers_used) {
+ DRM_ERROR("Shader uses threading, but uses the upper "
+ "half of the registers, too\n");
+ goto fail;
+ }
+
/* If we did a backwards branch and we haven't emitted a uniforms
* reset since then, we still need the uniforms stream to have the
* uniforms address available so that the backwards branch can do its
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
new file mode 100644
index 000000000000..32bb8ef985fb
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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 SDTV module
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_panel.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+/* WSE Registers */
+#define VEC_WSE_RESET 0xc0
+
+#define VEC_WSE_CONTROL 0xc4
+#define VEC_WSE_WSS_ENABLE BIT(7)
+
+#define VEC_WSE_WSS_DATA 0xc8
+#define VEC_WSE_VPS_DATA1 0xcc
+#define VEC_WSE_VPS_CONTROL 0xd0
+
+/* VEC Registers */
+#define VEC_REVID 0x100
+
+#define VEC_CONFIG0 0x104
+#define VEC_CONFIG0_YDEL_MASK GENMASK(28, 26)
+#define VEC_CONFIG0_YDEL(x) ((x) << 26)
+#define VEC_CONFIG0_CDEL_MASK GENMASK(25, 24)
+#define VEC_CONFIG0_CDEL(x) ((x) << 24)
+#define VEC_CONFIG0_PBPR_FIL BIT(18)
+#define VEC_CONFIG0_CHROMA_GAIN_MASK GENMASK(17, 16)
+#define VEC_CONFIG0_CHROMA_GAIN_UNITY (0 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_32 (1 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_16 (2 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_8 (3 << 16)
+#define VEC_CONFIG0_CBURST_GAIN_MASK GENMASK(14, 13)
+#define VEC_CONFIG0_CBURST_GAIN_UNITY (0 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_128 (1 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_64 (2 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_32 (3 << 13)
+#define VEC_CONFIG0_CHRBW1 BIT(11)
+#define VEC_CONFIG0_CHRBW0 BIT(10)
+#define VEC_CONFIG0_SYNCDIS BIT(9)
+#define VEC_CONFIG0_BURDIS BIT(8)
+#define VEC_CONFIG0_CHRDIS BIT(7)
+#define VEC_CONFIG0_PDEN BIT(6)
+#define VEC_CONFIG0_YCDELAY BIT(4)
+#define VEC_CONFIG0_RAMPEN BIT(2)
+#define VEC_CONFIG0_YCDIS BIT(2)
+#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
+#define VEC_CONFIG0_NTSC_STD 0
+#define VEC_CONFIG0_PAL_BDGHI_STD 1
+#define VEC_CONFIG0_PAL_N_STD 3
+
+#define VEC_SCHPH 0x108
+#define VEC_SOFT_RESET 0x10c
+#define VEC_CLMP0_START 0x144
+#define VEC_CLMP0_END 0x148
+#define VEC_FREQ3_2 0x180
+#define VEC_FREQ1_0 0x184
+
+#define VEC_CONFIG1 0x188
+#define VEC_CONFIG_VEC_RESYNC_OFF BIT(18)
+#define VEC_CONFIG_RGB219 BIT(17)
+#define VEC_CONFIG_CBAR_EN BIT(16)
+#define VEC_CONFIG_TC_OBB BIT(15)
+#define VEC_CONFIG1_OUTPUT_MODE_MASK GENMASK(12, 10)
+#define VEC_CONFIG1_C_Y_CVBS (0 << 10)
+#define VEC_CONFIG1_CVBS_Y_C (1 << 10)
+#define VEC_CONFIG1_PR_Y_PB (2 << 10)
+#define VEC_CONFIG1_RGB (4 << 10)
+#define VEC_CONFIG1_Y_C_CVBS (5 << 10)
+#define VEC_CONFIG1_C_CVBS_Y (6 << 10)
+#define VEC_CONFIG1_C_CVBS_CVBS (7 << 10)
+#define VEC_CONFIG1_DIS_CHR BIT(9)
+#define VEC_CONFIG1_DIS_LUMA BIT(8)
+#define VEC_CONFIG1_YCBCR_IN BIT(6)
+#define VEC_CONFIG1_DITHER_TYPE_LFSR 0
+#define VEC_CONFIG1_DITHER_TYPE_COUNTER BIT(5)
+#define VEC_CONFIG1_DITHER_EN BIT(4)
+#define VEC_CONFIG1_CYDELAY BIT(3)
+#define VEC_CONFIG1_LUMADIS BIT(2)
+#define VEC_CONFIG1_COMPDIS BIT(1)
+#define VEC_CONFIG1_CUSTOM_FREQ BIT(0)
+
+#define VEC_CONFIG2 0x18c
+#define VEC_CONFIG2_PROG_SCAN BIT(15)
+#define VEC_CONFIG2_SYNC_ADJ_MASK GENMASK(14, 12)
+#define VEC_CONFIG2_SYNC_ADJ(x) (((x) / 2) << 12)
+#define VEC_CONFIG2_PBPR_EN BIT(10)
+#define VEC_CONFIG2_UV_DIG_DIS BIT(6)
+#define VEC_CONFIG2_RGB_DIG_DIS BIT(5)
+#define VEC_CONFIG2_TMUX_MASK GENMASK(3, 2)
+#define VEC_CONFIG2_TMUX_DRIVE0 (0 << 2)
+#define VEC_CONFIG2_TMUX_RG_COMP (1 << 2)
+#define VEC_CONFIG2_TMUX_UV_YC (2 << 2)
+#define VEC_CONFIG2_TMUX_SYNC_YC (3 << 2)
+
+#define VEC_INTERRUPT_CONTROL 0x190
+#define VEC_INTERRUPT_STATUS 0x194
+#define VEC_FCW_SECAM_B 0x198
+#define VEC_SECAM_GAIN_VAL 0x19c
+
+#define VEC_CONFIG3 0x1a0
+#define VEC_CONFIG3_HORIZ_LEN_STD (0 << 0)
+#define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF (1 << 0)
+#define VEC_CONFIG3_SHAPE_NON_LINEAR BIT(1)
+
+#define VEC_STATUS0 0x200
+#define VEC_MASK0 0x204
+
+#define VEC_CFG 0x208
+#define VEC_CFG_SG_MODE_MASK GENMASK(6, 5)
+#define VEC_CFG_SG_MODE(x) ((x) << 5)
+#define VEC_CFG_SG_EN BIT(4)
+#define VEC_CFG_VEC_EN BIT(3)
+#define VEC_CFG_MB_EN BIT(2)
+#define VEC_CFG_ENABLE BIT(1)
+#define VEC_CFG_TB_EN BIT(0)
+
+#define VEC_DAC_TEST 0x20c
+
+#define VEC_DAC_CONFIG 0x210
+#define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24)
+#define VEC_DAC_CONFIG_DRIVER_CTRL(x) ((x) << 16)
+#define VEC_DAC_CONFIG_DAC_CTRL(x) (x)
+
+#define VEC_DAC_MISC 0x214
+#define VEC_DAC_MISC_VCD_CTRL_MASK GENMASK(31, 16)
+#define VEC_DAC_MISC_VCD_CTRL(x) ((x) << 16)
+#define VEC_DAC_MISC_VID_ACT BIT(8)
+#define VEC_DAC_MISC_VCD_PWRDN BIT(6)
+#define VEC_DAC_MISC_BIAS_PWRDN BIT(5)
+#define VEC_DAC_MISC_DAC_PWRDN BIT(2)
+#define VEC_DAC_MISC_LDO_PWRDN BIT(1)
+#define VEC_DAC_MISC_DAC_RST_N BIT(0)
+
+
+/* General VEC hardware state. */
+struct vc4_vec {
+ struct platform_device *pdev;
+
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
+ void __iomem *regs;
+
+ struct clk *clock;
+
+ const struct vc4_vec_tv_mode *tv_mode;
+};
+
+#define VEC_READ(offset) readl(vec->regs + (offset))
+#define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
+
+/* VC4 VEC encoder KMS struct */
+struct vc4_vec_encoder {
+ struct vc4_encoder base;
+ struct vc4_vec *vec;
+};
+
+static inline struct vc4_vec_encoder *
+to_vc4_vec_encoder(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct vc4_vec_encoder, base.base);
+}
+
+/* VC4 VEC connector KMS struct */
+struct vc4_vec_connector {
+ struct drm_connector base;
+ struct vc4_vec *vec;
+
+ /* 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_vec_connector *
+to_vc4_vec_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct vc4_vec_connector, base);
+}
+
+enum vc4_vec_tv_mode_id {
+ VC4_VEC_TV_MODE_NTSC,
+ VC4_VEC_TV_MODE_NTSC_J,
+ VC4_VEC_TV_MODE_PAL,
+ VC4_VEC_TV_MODE_PAL_M,
+};
+
+struct vc4_vec_tv_mode {
+ const struct drm_display_mode *mode;
+ void (*mode_set)(struct vc4_vec *vec);
+};
+
+#define VEC_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} vec_regs[] = {
+ VEC_REG(VEC_WSE_CONTROL),
+ VEC_REG(VEC_WSE_WSS_DATA),
+ VEC_REG(VEC_WSE_VPS_DATA1),
+ VEC_REG(VEC_WSE_VPS_CONTROL),
+ VEC_REG(VEC_REVID),
+ VEC_REG(VEC_CONFIG0),
+ VEC_REG(VEC_SCHPH),
+ VEC_REG(VEC_CLMP0_START),
+ VEC_REG(VEC_CLMP0_END),
+ VEC_REG(VEC_FREQ3_2),
+ VEC_REG(VEC_FREQ1_0),
+ VEC_REG(VEC_CONFIG1),
+ VEC_REG(VEC_CONFIG2),
+ VEC_REG(VEC_INTERRUPT_CONTROL),
+ VEC_REG(VEC_INTERRUPT_STATUS),
+ VEC_REG(VEC_FCW_SECAM_B),
+ VEC_REG(VEC_SECAM_GAIN_VAL),
+ VEC_REG(VEC_CONFIG3),
+ VEC_REG(VEC_STATUS0),
+ VEC_REG(VEC_MASK0),
+ VEC_REG(VEC_CFG),
+ VEC_REG(VEC_DAC_TEST),
+ VEC_REG(VEC_DAC_CONFIG),
+ VEC_REG(VEC_DAC_MISC),
+};
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_vec_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);
+ struct vc4_vec *vec = vc4->vec;
+ int i;
+
+ if (!vec)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(vec_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ vec_regs[i].name, vec_regs[i].reg,
+ VEC_READ(vec_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif
+
+static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
+{
+ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
+ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
+{
+ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
+ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static const struct drm_display_mode ntsc_mode = {
+ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
+ 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
+ DRM_MODE_FLAG_INTERLACE)
+};
+
+static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
+{
+ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
+ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
+{
+ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
+ VEC_WRITE(VEC_CONFIG1,
+ VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
+ VEC_WRITE(VEC_FREQ3_2, 0x223b);
+ VEC_WRITE(VEC_FREQ1_0, 0x61d1);
+}
+
+static const struct drm_display_mode pal_mode = {
+ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
+ 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
+ 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
+ DRM_MODE_FLAG_INTERLACE)
+};
+
+static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
+ [VC4_VEC_TV_MODE_NTSC] = {
+ .mode = &ntsc_mode,
+ .mode_set = vc4_vec_ntsc_mode_set,
+ },
+ [VC4_VEC_TV_MODE_NTSC_J] = {
+ .mode = &ntsc_mode,
+ .mode_set = vc4_vec_ntsc_j_mode_set,
+ },
+ [VC4_VEC_TV_MODE_PAL] = {
+ .mode = &pal_mode,
+ .mode_set = vc4_vec_pal_mode_set,
+ },
+ [VC4_VEC_TV_MODE_PAL_M] = {
+ .mode = &pal_mode,
+ .mode_set = vc4_vec_pal_m_mode_set,
+ },
+};
+
+static enum drm_connector_status
+vc4_vec_connector_detect(struct drm_connector *connector, bool force)
+{
+ return connector_status_unknown;
+}
+
+static void vc4_vec_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static int vc4_vec_connector_get_modes(struct drm_connector *connector)
+{
+ struct drm_connector_state *state = connector->state;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev,
+ vc4_vec_tv_modes[state->tv.mode].mode);
+ if (!mode) {
+ DRM_ERROR("Failed to create a new display mode\n");
+ return -ENOMEM;
+ }
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_connector_funcs vc4_vec_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = vc4_vec_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = drm_atomic_helper_connector_set_property,
+ .destroy = vc4_vec_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_vec_connector_helper_funcs = {
+ .get_modes = vc4_vec_connector_get_modes,
+};
+
+static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
+ struct vc4_vec *vec)
+{
+ struct drm_connector *connector = NULL;
+ struct vc4_vec_connector *vec_connector;
+
+ vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector),
+ GFP_KERNEL);
+ if (!vec_connector)
+ return ERR_PTR(-ENOMEM);
+
+ connector = &vec_connector->base;
+ connector->interlace_allowed = true;
+
+ vec_connector->encoder = vec->encoder;
+ vec_connector->vec = vec;
+
+ drm_connector_init(dev, connector, &vc4_vec_connector_funcs,
+ DRM_MODE_CONNECTOR_Composite);
+ drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
+
+ drm_object_attach_property(&connector->base,
+ dev->mode_config.tv_mode_property,
+ VC4_VEC_TV_MODE_NTSC);
+ vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
+
+ drm_mode_connector_attach_encoder(connector, vec->encoder);
+
+ return connector;
+}
+
+static const struct drm_encoder_funcs vc4_vec_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
+{
+ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+ struct vc4_vec *vec = vc4_vec_encoder->vec;
+ int ret;
+
+ VEC_WRITE(VEC_CFG, 0);
+ VEC_WRITE(VEC_DAC_MISC,
+ VEC_DAC_MISC_VCD_PWRDN |
+ VEC_DAC_MISC_BIAS_PWRDN |
+ VEC_DAC_MISC_DAC_PWRDN |
+ VEC_DAC_MISC_LDO_PWRDN);
+
+ clk_disable_unprepare(vec->clock);
+
+ ret = pm_runtime_put(&vec->pdev->dev);
+ if (ret < 0) {
+ DRM_ERROR("Failed to release power domain: %d\n", ret);
+ return;
+ }
+}
+
+static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
+{
+ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+ struct vc4_vec *vec = vc4_vec_encoder->vec;
+ int ret;
+
+ ret = pm_runtime_get_sync(&vec->pdev->dev);
+ if (ret < 0) {
+ DRM_ERROR("Failed to retain power domain: %d\n", ret);
+ return;
+ }
+
+ /*
+ * We need to set the clock rate each time we enable the encoder
+ * because there's a chance we share the same parent with the HDMI
+ * clock, and both drivers are requesting different rates.
+ * The good news is, these 2 encoders cannot be enabled at the same
+ * time, thus preventing incompatible rate requests.
+ */
+ ret = clk_set_rate(vec->clock, 108000000);
+ if (ret) {
+ DRM_ERROR("Failed to set clock rate: %d\n", ret);
+ return;
+ }
+
+ ret = clk_prepare_enable(vec->clock);
+ if (ret) {
+ DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+ return;
+ }
+
+ /* Reset the different blocks */
+ VEC_WRITE(VEC_WSE_RESET, 1);
+ VEC_WRITE(VEC_SOFT_RESET, 1);
+
+ /* Disable the CGSM-A and WSE blocks */
+ VEC_WRITE(VEC_WSE_CONTROL, 0);
+
+ /* Write config common to all modes. */
+
+ /*
+ * Color subcarrier phase: phase = 360 * SCHPH / 256.
+ * 0x28 <=> 39.375 deg.
+ */
+ VEC_WRITE(VEC_SCHPH, 0x28);
+
+ /*
+ * Reset to default values.
+ */
+ VEC_WRITE(VEC_CLMP0_START, 0xac);
+ VEC_WRITE(VEC_CLMP0_END, 0xec);
+ VEC_WRITE(VEC_CONFIG2,
+ VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
+ VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
+ VEC_WRITE(VEC_DAC_CONFIG,
+ VEC_DAC_CONFIG_DAC_CTRL(0xc) |
+ VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
+ VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46));
+
+ /* Mask all interrupts. */
+ VEC_WRITE(VEC_MASK0, 0);
+
+ vec->tv_mode->mode_set(vec);
+
+ VEC_WRITE(VEC_DAC_MISC,
+ VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
+ VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
+}
+
+
+static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+ struct vc4_vec *vec = vc4_vec_encoder->vec;
+
+ vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
+}
+
+static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ const struct vc4_vec_tv_mode *vec_mode;
+
+ vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
+
+ if (conn_state->crtc &&
+ !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
+ .disable = vc4_vec_encoder_disable,
+ .enable = vc4_vec_encoder_enable,
+ .mode_fixup = vc4_vec_encoder_mode_fixup,
+ .atomic_check = vc4_vec_encoder_atomic_check,
+ .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
+};
+
+static const struct of_device_id vc4_vec_dt_match[] = {
+ { .compatible = "brcm,bcm2835-vec", .data = NULL },
+ { /* sentinel */ },
+};
+
+static const char * const tv_mode_names[] = {
+ [VC4_VEC_TV_MODE_NTSC] = "NTSC",
+ [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
+ [VC4_VEC_TV_MODE_PAL] = "PAL",
+ [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
+};
+
+static int vc4_vec_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_vec *vec;
+ struct vc4_vec_encoder *vc4_vec_encoder;
+ int ret;
+
+ ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
+ tv_mode_names);
+ if (ret)
+ return ret;
+
+ vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
+ if (!vec)
+ return -ENOMEM;
+
+ vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
+ GFP_KERNEL);
+ if (!vc4_vec_encoder)
+ return -ENOMEM;
+ vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
+ vc4_vec_encoder->vec = vec;
+ vec->encoder = &vc4_vec_encoder->base.base;
+
+ vec->pdev = pdev;
+ vec->regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(vec->regs))
+ return PTR_ERR(vec->regs);
+
+ vec->clock = devm_clk_get(dev, NULL);
+ if (IS_ERR(vec->clock)) {
+ ret = PTR_ERR(vec->clock);
+ if (ret != -EPROBE_DEFER)
+ DRM_ERROR("Failed to get clock: %d\n", ret);
+ return ret;
+ }
+
+ pm_runtime_enable(dev);
+
+ drm_encoder_init(drm, vec->encoder, &vc4_vec_encoder_funcs,
+ DRM_MODE_ENCODER_TVDAC, NULL);
+ drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
+
+ vec->connector = vc4_vec_connector_init(drm, vec);
+ if (IS_ERR(vec->connector)) {
+ ret = PTR_ERR(vec->connector);
+ goto err_destroy_encoder;
+ }
+
+ dev_set_drvdata(dev, vec);
+
+ vc4->vec = vec;
+
+ return 0;
+
+err_destroy_encoder:
+ drm_encoder_cleanup(vec->encoder);
+ pm_runtime_disable(dev);
+
+ return ret;
+}
+
+static void vc4_vec_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+ struct vc4_vec *vec = dev_get_drvdata(dev);
+
+ vc4_vec_connector_destroy(vec->connector);
+ drm_encoder_cleanup(vec->encoder);
+ pm_runtime_disable(dev);
+
+ vc4->vec = NULL;
+}
+
+static const struct component_ops vc4_vec_ops = {
+ .bind = vc4_vec_bind,
+ .unbind = vc4_vec_unbind,
+};
+
+static int vc4_vec_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_vec_ops);
+}
+
+static int vc4_vec_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_vec_ops);
+ return 0;
+}
+
+struct platform_driver vc4_vec_driver = {
+ .probe = vc4_vec_dev_probe,
+ .remove = vc4_vec_dev_remove,
+ .driver = {
+ .name = "vc4_vec",
+ .of_match_table = vc4_vec_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c
index 5c57c1ffa1f9..da25dfe7b80e 100644
--- a/drivers/gpu/drm/vgem/vgem_fence.c
+++ b/drivers/gpu/drm/vgem/vgem_fence.c
@@ -28,56 +28,57 @@
#define VGEM_FENCE_TIMEOUT (10*HZ)
struct vgem_fence {
- struct fence base;
+ struct dma_fence base;
struct spinlock lock;
struct timer_list timer;
};
-static const char *vgem_fence_get_driver_name(struct fence *fence)
+static const char *vgem_fence_get_driver_name(struct dma_fence *fence)
{
return "vgem";
}
-static const char *vgem_fence_get_timeline_name(struct fence *fence)
+static const char *vgem_fence_get_timeline_name(struct dma_fence *fence)
{
return "unbound";
}
-static bool vgem_fence_signaled(struct fence *fence)
+static bool vgem_fence_signaled(struct dma_fence *fence)
{
return false;
}
-static bool vgem_fence_enable_signaling(struct fence *fence)
+static bool vgem_fence_enable_signaling(struct dma_fence *fence)
{
return true;
}
-static void vgem_fence_release(struct fence *base)
+static void vgem_fence_release(struct dma_fence *base)
{
struct vgem_fence *fence = container_of(base, typeof(*fence), base);
del_timer_sync(&fence->timer);
- fence_free(&fence->base);
+ dma_fence_free(&fence->base);
}
-static void vgem_fence_value_str(struct fence *fence, char *str, int size)
+static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size)
{
snprintf(str, size, "%u", fence->seqno);
}
-static void vgem_fence_timeline_value_str(struct fence *fence, char *str,
+static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str,
int size)
{
- snprintf(str, size, "%u", fence_is_signaled(fence) ? fence->seqno : 0);
+ snprintf(str, size, "%u",
+ dma_fence_is_signaled(fence) ? fence->seqno : 0);
}
-static const struct fence_ops vgem_fence_ops = {
+static const struct dma_fence_ops vgem_fence_ops = {
.get_driver_name = vgem_fence_get_driver_name,
.get_timeline_name = vgem_fence_get_timeline_name,
.enable_signaling = vgem_fence_enable_signaling,
.signaled = vgem_fence_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = vgem_fence_release,
.fence_value_str = vgem_fence_value_str,
@@ -88,11 +89,11 @@ static void vgem_fence_timeout(unsigned long data)
{
struct vgem_fence *fence = (struct vgem_fence *)data;
- fence_signal(&fence->base);
+ dma_fence_signal(&fence->base);
}
-static struct fence *vgem_fence_create(struct vgem_file *vfile,
- unsigned int flags)
+static struct dma_fence *vgem_fence_create(struct vgem_file *vfile,
+ unsigned int flags)
{
struct vgem_fence *fence;
@@ -101,8 +102,8 @@ static struct fence *vgem_fence_create(struct vgem_file *vfile,
return NULL;
spin_lock_init(&fence->lock);
- fence_init(&fence->base, &vgem_fence_ops, &fence->lock,
- fence_context_alloc(1), 1);
+ dma_fence_init(&fence->base, &vgem_fence_ops, &fence->lock,
+ dma_fence_context_alloc(1), 1);
setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence);
@@ -125,7 +126,6 @@ static int attach_dmabuf(struct drm_device *dev,
return PTR_ERR(dmabuf);
obj->dma_buf = dmabuf;
- drm_gem_object_reference(obj);
return 0;
}
@@ -157,7 +157,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
struct vgem_file *vfile = file->driver_priv;
struct reservation_object *resv;
struct drm_gem_object *obj;
- struct fence *fence;
+ struct dma_fence *fence;
int ret;
if (arg->flags & ~VGEM_FENCE_WRITE)
@@ -190,12 +190,12 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
/* Expose the fence via the dma-buf */
ret = 0;
- mutex_lock(&resv->lock.base);
+ ww_mutex_lock(&resv->lock, NULL);
if (arg->flags & VGEM_FENCE_WRITE)
reservation_object_add_excl_fence(resv, fence);
else if ((ret = reservation_object_reserve_shared(resv)) == 0)
reservation_object_add_shared_fence(resv, fence);
- mutex_unlock(&resv->lock.base);
+ ww_mutex_unlock(&resv->lock);
/* Record the fence in our idr for later signaling */
if (ret == 0) {
@@ -209,8 +209,8 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
}
err_fence:
if (ret) {
- fence_signal(fence);
- fence_put(fence);
+ dma_fence_signal(fence);
+ dma_fence_put(fence);
}
err:
drm_gem_object_unreference_unlocked(obj);
@@ -239,7 +239,7 @@ int vgem_fence_signal_ioctl(struct drm_device *dev,
{
struct vgem_file *vfile = file->driver_priv;
struct drm_vgem_fence_signal *arg = data;
- struct fence *fence;
+ struct dma_fence *fence;
int ret = 0;
if (arg->flags)
@@ -253,11 +253,11 @@ int vgem_fence_signal_ioctl(struct drm_device *dev,
if (IS_ERR(fence))
return PTR_ERR(fence);
- if (fence_is_signaled(fence))
+ if (dma_fence_is_signaled(fence))
ret = -ETIMEDOUT;
- fence_signal(fence);
- fence_put(fence);
+ dma_fence_signal(fence);
+ dma_fence_put(fence);
return ret;
}
@@ -271,8 +271,8 @@ int vgem_fence_open(struct vgem_file *vfile)
static int __vgem_fence_idr_fini(int id, void *p, void *data)
{
- fence_signal(p);
- fence_put(p);
+ dma_fence_signal(p);
+ dma_fence_put(p);
return 0;
}
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index e5582bab7e3c..9e0e5392b6ec 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -64,9 +64,7 @@ static const struct file_operations via_driver_fops = {
.unlocked_ioctl = drm_ioctl,
.mmap = drm_legacy_mmap,
.poll = drm_poll,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig
index e1afc3d3f8d9..81d1807ac228 100644
--- a/drivers/gpu/drm/virtio/Kconfig
+++ b/drivers/gpu/drm/virtio/Kconfig
@@ -1,10 +1,10 @@
config DRM_VIRTIO_GPU
tristate "Virtio GPU driver"
depends on DRM && VIRTIO
- select DRM_KMS_HELPER
- select DRM_TTM
+ select DRM_KMS_HELPER
+ select DRM_TTM
help
This is the virtual GPU driver for virtio. It can be used with
- QEMU based VMMs (like KVM or Xen).
+ QEMU based VMMs (like KVM or Xen).
If unsure say M.
diff --git a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
index 49e5996cb9f2..3b97d50fd392 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
@@ -28,16 +28,6 @@
#include "virtgpu_drv.h"
-int drm_virtio_set_busid(struct drm_device *dev, struct drm_master *master)
-{
- struct pci_dev *pdev = dev->pdev;
-
- if (pdev) {
- return drm_pci_set_busid(dev, master);
- }
- return 0;
-}
-
static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev)
{
struct apertures_struct *ap;
@@ -71,13 +61,22 @@ int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
if (strcmp(vdev->dev.parent->bus->name, "pci") == 0) {
struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
+ const char *pname = dev_name(&pdev->dev);
bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+ char unique[20];
- DRM_INFO("pci: %s detected\n",
- vga ? "virtio-vga" : "virtio-gpu-pci");
+ DRM_INFO("pci: %s detected at %s\n",
+ vga ? "virtio-vga" : "virtio-gpu-pci",
+ pname);
dev->pdev = pdev;
if (vga)
virtio_pci_kick_out_firmware_fb(pdev);
+
+ snprintf(unique, sizeof(unique), "pci:%s", pname);
+ ret = drm_dev_set_unique(dev, unique);
+ if (ret)
+ goto err_free;
+
}
ret = drm_dev_register(dev, 0);
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 5820b7020ae5..d82489815096 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -108,16 +108,13 @@ static const struct file_operations virtio_gpu_driver_fops = {
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
.release = drm_release,
-#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
-#endif
.llseek = noop_llseek,
};
static struct drm_driver driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
- .set_busid = drm_virtio_set_busid,
.load = virtio_gpu_driver_load,
.unload = virtio_gpu_driver_unload,
.open = virtio_gpu_driver_open,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index ae59080d63d1..08906c8ce3fa 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -49,7 +49,6 @@
#define DRIVER_PATCHLEVEL 1
/* virtgpu_drm_bus.c */
-int drm_virtio_set_busid(struct drm_device *dev, struct drm_master *master);
int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev);
struct virtio_gpu_object {
@@ -82,7 +81,7 @@ struct virtio_gpu_fence_driver {
};
struct virtio_gpu_fence {
- struct fence f;
+ struct dma_fence f;
struct virtio_gpu_fence_driver *drv;
struct list_head node;
uint64_t seq;
diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c
index 2242a80866a9..dd21f950e129 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fb.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fb.c
@@ -200,16 +200,10 @@ static void virtio_gpu_3d_imageblit(struct fb_info *info,
static struct fb_ops virtio_gpufb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = virtio_gpu_3d_fillrect,
.fb_copyarea = virtio_gpu_3d_copyarea,
.fb_imageblit = virtio_gpu_3d_imageblit,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
};
static int virtio_gpu_vmap_fb(struct virtio_gpu_device *vgdev,
diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index f3f70fa8a4c7..23353521f903 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -26,22 +26,22 @@
#include <drm/drmP.h>
#include "virtgpu_drv.h"
-static const char *virtio_get_driver_name(struct fence *f)
+static const char *virtio_get_driver_name(struct dma_fence *f)
{
return "virtio_gpu";
}
-static const char *virtio_get_timeline_name(struct fence *f)
+static const char *virtio_get_timeline_name(struct dma_fence *f)
{
return "controlq";
}
-static bool virtio_enable_signaling(struct fence *f)
+static bool virtio_enable_signaling(struct dma_fence *f)
{
return true;
}
-static bool virtio_signaled(struct fence *f)
+static bool virtio_signaled(struct dma_fence *f)
{
struct virtio_gpu_fence *fence = to_virtio_fence(f);
@@ -50,26 +50,26 @@ static bool virtio_signaled(struct fence *f)
return false;
}
-static void virtio_fence_value_str(struct fence *f, char *str, int size)
+static void virtio_fence_value_str(struct dma_fence *f, char *str, int size)
{
struct virtio_gpu_fence *fence = to_virtio_fence(f);
snprintf(str, size, "%llu", fence->seq);
}
-static void virtio_timeline_value_str(struct fence *f, char *str, int size)
+static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size)
{
struct virtio_gpu_fence *fence = to_virtio_fence(f);
snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
}
-static const struct fence_ops virtio_fence_ops = {
+static const struct dma_fence_ops virtio_fence_ops = {
.get_driver_name = virtio_get_driver_name,
.get_timeline_name = virtio_get_timeline_name,
.enable_signaling = virtio_enable_signaling,
.signaled = virtio_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.fence_value_str = virtio_fence_value_str,
.timeline_value_str = virtio_timeline_value_str,
};
@@ -88,9 +88,9 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
spin_lock_irqsave(&drv->lock, irq_flags);
(*fence)->drv = drv;
(*fence)->seq = ++drv->sync_seq;
- fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
- drv->context, (*fence)->seq);
- fence_get(&(*fence)->f);
+ dma_fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
+ drv->context, (*fence)->seq);
+ dma_fence_get(&(*fence)->f);
list_add_tail(&(*fence)->node, &drv->fences);
spin_unlock_irqrestore(&drv->lock, irq_flags);
@@ -111,9 +111,9 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,
list_for_each_entry_safe(fence, tmp, &drv->fences, node) {
if (last_seq < fence->seq)
continue;
- fence_signal_locked(&fence->f);
+ dma_fence_signal_locked(&fence->f);
list_del(&fence->node);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
}
spin_unlock_irqrestore(&drv->lock, irq_flags);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 818478b4c4f0..61f3a963af95 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -172,7 +172,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
/* fence the command bo */
virtio_gpu_unref_list(&validate_list);
drm_free_large(buflist);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
return 0;
out_unresv:
@@ -298,7 +298,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
drm_gem_object_release(obj);
if (vgdev->has_virgl_3d) {
virtio_gpu_unref_list(&validate_list);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
}
return ret;
}
@@ -309,13 +309,13 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
if (vgdev->has_virgl_3d) {
virtio_gpu_unref_list(&validate_list);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
}
return 0;
fail_unref:
if (vgdev->has_virgl_3d) {
virtio_gpu_unref_list(&validate_list);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
}
//fail_obj:
// drm_gem_object_handle_unreference_unlocked(obj);
@@ -383,7 +383,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
reservation_object_add_excl_fence(qobj->tbo.resv,
&fence->f);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
out_unres:
virtio_gpu_object_unreserve(qobj);
out:
@@ -431,7 +431,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
args->level, &box, &fence);
reservation_object_add_excl_fence(qobj->tbo.resv,
&fence->f);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
}
out_unres:
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 036b0fbae0fb..1235519853f4 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -159,7 +159,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func);
virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func);
- vgdev->fence_drv.context = fence_context_alloc(1);
+ vgdev->fence_drv.context = dma_fence_context_alloc(1);
spin_lock_init(&vgdev->fence_drv.lock);
INIT_LIST_HEAD(&vgdev->fence_drv.fences);
INIT_LIST_HEAD(&vgdev->cap_cache);
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index ba28c0f6f28a..cb75f0663ba0 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -152,7 +152,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
if (!ret) {
reservation_object_add_excl_fence(bo->tbo.resv,
&fence->f);
- fence_put(&fence->f);
+ dma_fence_put(&fence->f);
fence = NULL;
virtio_gpu_object_unreserve(bo);
virtio_gpu_object_wait(bo, false);
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c
index 80482ac5f95d..4a1de9f81193 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ttm.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c
@@ -425,6 +425,7 @@ static struct ttm_bo_driver virtio_gpu_bo_driver = {
.ttm_tt_unpopulate = &virtio_gpu_ttm_tt_unpopulate,
.invalidate_caches = &virtio_gpu_invalidate_caches,
.init_mem_type = &virtio_gpu_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = &virtio_gpu_evict_flags,
.move = &virtio_gpu_bo_move,
.verify_access = &virtio_gpu_verify_access,
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 5a0f8a745b9d..974f9410474b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -75,7 +75,7 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq)
int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
{
struct virtio_gpu_vbuffer *vbuf;
- int i, size, count = 0;
+ int i, size, count = 16;
void *ptr;
INIT_LIST_HEAD(&vgdev->free_vbufs);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 78b75ee3c931..c894a48a74a6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -849,6 +849,7 @@ struct ttm_bo_driver vmw_bo_driver = {
.ttm_tt_unpopulate = &vmw_ttm_unpopulate,
.invalidate_caches = vmw_invalidate_caches,
.init_mem_type = vmw_init_mem_type,
+ .eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = vmw_evict_flags,
.move = NULL,
.verify_access = vmw_verify_access,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index d2d93959b119..723fd763da8e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -465,33 +465,34 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,
static int vmw_fb_kms_framebuffer(struct fb_info *info)
{
- struct drm_mode_fb_cmd mode_cmd;
+ struct drm_mode_fb_cmd2 mode_cmd;
struct vmw_fb_par *par = info->par;
struct fb_var_screeninfo *var = &info->var;
struct drm_framebuffer *cur_fb;
struct vmw_framebuffer *vfb;
- int ret = 0;
+ int ret = 0, depth;
size_t new_bo_size;
- ret = vmw_fb_compute_depth(var, &mode_cmd.depth);
+ ret = vmw_fb_compute_depth(var, &depth);
if (ret)
return ret;
mode_cmd.width = var->xres;
mode_cmd.height = var->yres;
- mode_cmd.bpp = var->bits_per_pixel;
- mode_cmd.pitch = ((mode_cmd.bpp + 7) / 8) * mode_cmd.width;
+ mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
+ mode_cmd.pixel_format =
+ drm_mode_legacy_fb_format(var->bits_per_pixel,
+ ((var->bits_per_pixel + 7) / 8) * mode_cmd.width);
cur_fb = par->set_fb;
if (cur_fb && cur_fb->width == mode_cmd.width &&
cur_fb->height == mode_cmd.height &&
- cur_fb->bits_per_pixel == mode_cmd.bpp &&
- cur_fb->depth == mode_cmd.depth &&
- cur_fb->pitches[0] == mode_cmd.pitch)
+ cur_fb->pixel_format == mode_cmd.pixel_format &&
+ cur_fb->pitches[0] == mode_cmd.pitches[0])
return 0;
/* Need new buffer object ? */
- new_bo_size = (size_t) mode_cmd.pitch * (size_t) mode_cmd.height;
+ new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height;
ret = vmw_fb_kms_detach(par,
par->bo_size < new_bo_size ||
par->bo_size > 2*new_bo_size,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 26ac8e80a478..6541dd8b82dc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -108,7 +108,7 @@ fman_from_fence(struct vmw_fence_obj *fence)
* objects with actions attached to them.
*/
-static void vmw_fence_obj_destroy(struct fence *f)
+static void vmw_fence_obj_destroy(struct dma_fence *f)
{
struct vmw_fence_obj *fence =
container_of(f, struct vmw_fence_obj, base);
@@ -123,17 +123,17 @@ static void vmw_fence_obj_destroy(struct fence *f)
fence->destroy(fence);
}
-static const char *vmw_fence_get_driver_name(struct fence *f)
+static const char *vmw_fence_get_driver_name(struct dma_fence *f)
{
return "vmwgfx";
}
-static const char *vmw_fence_get_timeline_name(struct fence *f)
+static const char *vmw_fence_get_timeline_name(struct dma_fence *f)
{
return "svga";
}
-static bool vmw_fence_enable_signaling(struct fence *f)
+static bool vmw_fence_enable_signaling(struct dma_fence *f)
{
struct vmw_fence_obj *fence =
container_of(f, struct vmw_fence_obj, base);
@@ -152,12 +152,12 @@ static bool vmw_fence_enable_signaling(struct fence *f)
}
struct vmwgfx_wait_cb {
- struct fence_cb base;
+ struct dma_fence_cb base;
struct task_struct *task;
};
static void
-vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb)
+vmwgfx_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct vmwgfx_wait_cb *wait =
container_of(cb, struct vmwgfx_wait_cb, base);
@@ -167,7 +167,7 @@ vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb)
static void __vmw_fences_update(struct vmw_fence_manager *fman);
-static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout)
+static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
{
struct vmw_fence_obj *fence =
container_of(f, struct vmw_fence_obj, base);
@@ -197,7 +197,7 @@ static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout)
while (ret > 0) {
__vmw_fences_update(fman);
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &f->flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags))
break;
if (intr)
@@ -225,7 +225,7 @@ out:
return ret;
}
-static struct fence_ops vmw_fence_ops = {
+static struct dma_fence_ops vmw_fence_ops = {
.get_driver_name = vmw_fence_get_driver_name,
.get_timeline_name = vmw_fence_get_timeline_name,
.enable_signaling = vmw_fence_enable_signaling,
@@ -298,7 +298,7 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
fman->event_fence_action_size =
ttm_round_pot(sizeof(struct vmw_event_fence_action));
mutex_init(&fman->goal_irq_mutex);
- fman->ctx = fence_context_alloc(1);
+ fman->ctx = dma_fence_context_alloc(1);
return fman;
}
@@ -326,8 +326,8 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman,
unsigned long irq_flags;
int ret = 0;
- fence_init(&fence->base, &vmw_fence_ops, &fman->lock,
- fman->ctx, seqno);
+ dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock,
+ fman->ctx, seqno);
INIT_LIST_HEAD(&fence->seq_passed_actions);
fence->destroy = destroy;
@@ -431,7 +431,7 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
u32 goal_seqno;
u32 *fifo_mem;
- if (fence_is_signaled_locked(&fence->base))
+ if (dma_fence_is_signaled_locked(&fence->base))
return false;
fifo_mem = fman->dev_priv->mmio_virt;
@@ -459,7 +459,7 @@ rerun:
list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
if (seqno - fence->base.seqno < VMW_FENCE_WRAP) {
list_del_init(&fence->head);
- fence_signal_locked(&fence->base);
+ dma_fence_signal_locked(&fence->base);
INIT_LIST_HEAD(&action_list);
list_splice_init(&fence->seq_passed_actions,
&action_list);
@@ -500,18 +500,18 @@ bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence)
{
struct vmw_fence_manager *fman = fman_from_fence(fence);
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
return 1;
vmw_fences_update(fman);
- return fence_is_signaled(&fence->base);
+ return dma_fence_is_signaled(&fence->base);
}
int vmw_fence_obj_wait(struct vmw_fence_obj *fence, bool lazy,
bool interruptible, unsigned long timeout)
{
- long ret = fence_wait_timeout(&fence->base, interruptible, timeout);
+ long ret = dma_fence_wait_timeout(&fence->base, interruptible, timeout);
if (likely(ret > 0))
return 0;
@@ -530,7 +530,7 @@ void vmw_fence_obj_flush(struct vmw_fence_obj *fence)
static void vmw_fence_destroy(struct vmw_fence_obj *fence)
{
- fence_free(&fence->base);
+ dma_fence_free(&fence->base);
}
int vmw_fence_create(struct vmw_fence_manager *fman,
@@ -669,7 +669,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
struct vmw_fence_obj *fence =
list_entry(fman->fence_list.prev, struct vmw_fence_obj,
head);
- fence_get(&fence->base);
+ dma_fence_get(&fence->base);
spin_unlock_irq(&fman->lock);
ret = vmw_fence_obj_wait(fence, false, false,
@@ -677,7 +677,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
if (unlikely(ret != 0)) {
list_del_init(&fence->head);
- fence_signal(&fence->base);
+ dma_fence_signal(&fence->base);
INIT_LIST_HEAD(&action_list);
list_splice_init(&fence->seq_passed_actions,
&action_list);
@@ -685,7 +685,7 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
}
BUG_ON(!list_empty(&fence->head));
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
spin_lock_irq(&fman->lock);
}
spin_unlock_irq(&fman->lock);
@@ -884,7 +884,7 @@ static void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
spin_lock_irqsave(&fman->lock, irq_flags);
fman->pending_actions[action->type]++;
- if (fence_is_signaled_locked(&fence->base)) {
+ if (dma_fence_is_signaled_locked(&fence->base)) {
struct list_head action_list;
INIT_LIST_HEAD(&action_list);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
index 83ae301ee141..d9d85aa6ed20 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
@@ -27,7 +27,7 @@
#ifndef _VMWGFX_FENCE_H_
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
@@ -52,7 +52,7 @@ struct vmw_fence_action {
};
struct vmw_fence_obj {
- struct fence base;
+ struct dma_fence base;
struct list_head head;
struct list_head seq_passed_actions;
@@ -71,14 +71,14 @@ vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
*fence_p = NULL;
if (fence)
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
}
static inline struct vmw_fence_obj *
vmw_fence_obj_reference(struct vmw_fence_obj *fence)
{
if (fence)
- fence_get(&fence->base);
+ dma_fence_get(&fence->base);
return fence;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index bf28ccc150df..e7daf59bac80 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -516,7 +516,7 @@ static const struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = {
static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
struct vmw_surface *surface,
struct vmw_framebuffer **out,
- const struct drm_mode_fb_cmd
+ const struct drm_mode_fb_cmd2
*mode_cmd,
bool is_dmabuf_proxy)
@@ -525,6 +525,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs;
enum SVGA3dSurfaceFormat format;
int ret;
+ struct drm_format_name_buf format_name;
/* 3D is only supported on HWv8 and newer hosts */
if (dev_priv->active_display_unit == vmw_du_legacy)
@@ -548,21 +549,22 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
return -EINVAL;
}
- switch (mode_cmd->depth) {
- case 32:
+ switch (mode_cmd->pixel_format) {
+ case DRM_FORMAT_ARGB8888:
format = SVGA3D_A8R8G8B8;
break;
- case 24:
+ case DRM_FORMAT_XRGB8888:
format = SVGA3D_X8R8G8B8;
break;
- case 16:
+ case DRM_FORMAT_RGB565:
format = SVGA3D_R5G6B5;
break;
- case 15:
+ case DRM_FORMAT_XRGB1555:
format = SVGA3D_A1R5G5B5;
break;
default:
- DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+ DRM_ERROR("Invalid pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
@@ -581,14 +583,9 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
goto out_err1;
}
- /* XXX get the first 3 from the surface info */
- vfbs->base.base.bits_per_pixel = mode_cmd->bpp;
- vfbs->base.base.pitches[0] = mode_cmd->pitch;
- vfbs->base.base.depth = mode_cmd->depth;
- vfbs->base.base.width = mode_cmd->width;
- vfbs->base.base.height = mode_cmd->height;
+ drm_helper_mode_fill_fb_struct(&vfbs->base.base, mode_cmd);
vfbs->surface = vmw_surface_reference(surface);
- vfbs->base.user_handle = mode_cmd->handle;
+ vfbs->base.user_handle = mode_cmd->handles[0];
vfbs->is_dmabuf_proxy = is_dmabuf_proxy;
*out = &vfbs->base;
@@ -755,7 +752,7 @@ static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb)
* 0 on success, error code otherwise
*/
static int vmw_create_dmabuf_proxy(struct drm_device *dev,
- const struct drm_mode_fb_cmd *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct vmw_dma_buffer *dmabuf_mob,
struct vmw_surface **srf_out)
{
@@ -763,17 +760,18 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
struct drm_vmw_size content_base_size;
struct vmw_resource *res;
unsigned int bytes_pp;
+ struct drm_format_name_buf format_name;
int ret;
- switch (mode_cmd->depth) {
- case 32:
- case 24:
+ switch (mode_cmd->pixel_format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
format = SVGA3D_X8R8G8B8;
bytes_pp = 4;
break;
- case 16:
- case 15:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_XRGB1555:
format = SVGA3D_R5G6B5;
bytes_pp = 2;
break;
@@ -784,11 +782,12 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
break;
default:
- DRM_ERROR("Invalid framebuffer format %d\n", mode_cmd->depth);
+ DRM_ERROR("Invalid framebuffer format %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
- content_base_size.width = mode_cmd->pitch / bytes_pp;
+ content_base_size.width = mode_cmd->pitches[0] / bytes_pp;
content_base_size.height = mode_cmd->height;
content_base_size.depth = 1;
@@ -826,16 +825,17 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
struct vmw_dma_buffer *dmabuf,
struct vmw_framebuffer **out,
- const struct drm_mode_fb_cmd
+ const struct drm_mode_fb_cmd2
*mode_cmd)
{
struct drm_device *dev = dev_priv->dev;
struct vmw_framebuffer_dmabuf *vfbd;
unsigned int requested_size;
+ struct drm_format_name_buf format_name;
int ret;
- requested_size = mode_cmd->height * mode_cmd->pitch;
+ requested_size = mode_cmd->height * mode_cmd->pitches[0];
if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) {
DRM_ERROR("Screen buffer object size is too small "
"for requested mode.\n");
@@ -844,27 +844,16 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
/* Limited framebuffer color depth support for screen objects */
if (dev_priv->active_display_unit == vmw_du_screen_object) {
- switch (mode_cmd->depth) {
- case 32:
- case 24:
- /* Only support 32 bpp for 32 and 24 depth fbs */
- if (mode_cmd->bpp == 32)
- break;
-
- DRM_ERROR("Invalid color depth/bbp: %d %d\n",
- mode_cmd->depth, mode_cmd->bpp);
- return -EINVAL;
- case 16:
- case 15:
- /* Only support 16 bpp for 16 and 15 depth fbs */
- if (mode_cmd->bpp == 16)
- break;
-
- DRM_ERROR("Invalid color depth/bbp: %d %d\n",
- mode_cmd->depth, mode_cmd->bpp);
- return -EINVAL;
+ switch (mode_cmd->pixel_format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ break;
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_RGB565:
+ break;
default:
- DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+ DRM_ERROR("Invalid pixel format: %s\n",
+ drm_get_format_name(mode_cmd->pixel_format, &format_name));
return -EINVAL;
}
}
@@ -875,14 +864,10 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
goto out_err1;
}
- vfbd->base.base.bits_per_pixel = mode_cmd->bpp;
- vfbd->base.base.pitches[0] = mode_cmd->pitch;
- vfbd->base.base.depth = mode_cmd->depth;
- vfbd->base.base.width = mode_cmd->width;
- vfbd->base.base.height = mode_cmd->height;
+ drm_helper_mode_fill_fb_struct(&vfbd->base.base, mode_cmd);
vfbd->base.dmabuf = true;
vfbd->buffer = vmw_dmabuf_reference(dmabuf);
- vfbd->base.user_handle = mode_cmd->handle;
+ vfbd->base.user_handle = mode_cmd->handles[0];
*out = &vfbd->base;
ret = drm_framebuffer_init(dev, &vfbd->base.base,
@@ -916,7 +901,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
struct vmw_dma_buffer *dmabuf,
struct vmw_surface *surface,
bool only_2d,
- const struct drm_mode_fb_cmd *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct vmw_framebuffer *vfb = NULL;
bool is_dmabuf_proxy = false;
@@ -971,7 +956,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
struct drm_file *file_priv,
- const struct drm_mode_fb_cmd2 *mode_cmd2)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct vmw_private *dev_priv = vmw_priv(dev);
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
@@ -979,16 +964,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
struct vmw_surface *surface = NULL;
struct vmw_dma_buffer *bo = NULL;
struct ttm_base_object *user_obj;
- struct drm_mode_fb_cmd mode_cmd;
int ret;
- mode_cmd.width = mode_cmd2->width;
- mode_cmd.height = mode_cmd2->height;
- mode_cmd.pitch = mode_cmd2->pitches[0];
- mode_cmd.handle = mode_cmd2->handles[0];
- drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
- &mode_cmd.bpp);
-
/**
* This code should be conditioned on Screen Objects not being used.
* If screen objects are used, we can allocate a GMR to hold the
@@ -996,8 +973,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
*/
if (!vmw_kms_validate_mode_vram(dev_priv,
- mode_cmd.pitch,
- mode_cmd.height)) {
+ mode_cmd->pitches[0],
+ mode_cmd->height)) {
DRM_ERROR("Requested mode exceed bounding box limit.\n");
return ERR_PTR(-ENOMEM);
}
@@ -1011,7 +988,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
* command stream using user-space handles.
*/
- user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
+ user_obj = ttm_base_object_lookup(tfile, mode_cmd->handles[0]);
if (unlikely(user_obj == NULL)) {
DRM_ERROR("Could not locate requested kms frame buffer.\n");
return ERR_PTR(-ENOENT);
@@ -1023,14 +1000,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
/* returns either a dmabuf or surface */
ret = vmw_user_lookup_handle(dev_priv, tfile,
- mode_cmd.handle,
+ mode_cmd->handles[0],
&surface, &bo);
if (ret)
goto err_out;
vfb = vmw_kms_new_framebuffer(dev_priv, bo, surface,
!(dev_priv->capabilities & SVGA_CAP_3D),
- &mode_cmd);
+ mode_cmd);
if (IS_ERR(vfb)) {
ret = PTR_ERR(vfb);
goto err_out;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index ff4803c107bc..f42ce9a1c3ac 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -248,7 +248,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
struct vmw_dma_buffer *dmabuf,
struct vmw_surface *surface,
bool only_2d,
- const struct drm_mode_fb_cmd *mode_cmd);
+ const struct drm_mode_fb_cmd2 *mode_cmd);
int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
unsigned unit,
u32 max_width,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 52ca1c9d070e..8e86d6d4141b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -575,7 +575,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
long lret;
lret = reservation_object_wait_timeout_rcu(bo->resv, true, true,
- nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
+ nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
if (!lret)
return -EBUSY;
else if (lret < 0)
@@ -1454,7 +1454,7 @@ void vmw_fence_single_bo(struct ttm_buffer_object *bo,
if (fence == NULL) {
vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
reservation_object_add_excl_fence(bo->resv, &fence->base);
- fence_put(&fence->base);
+ dma_fence_put(&fence->base);
} else
reservation_object_add_excl_fence(bo->resv, &fence->base);
}
diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig
new file mode 100644
index 000000000000..4065b2840f1c
--- /dev/null
+++ b/drivers/gpu/drm/zte/Kconfig
@@ -0,0 +1,8 @@
+config DRM_ZTE
+ tristate "DRM Support for ZTE SoCs"
+ depends on DRM && ARCH_ZX
+ select DRM_KMS_CMA_HELPER
+ select DRM_KMS_FB_HELPER
+ select DRM_KMS_HELPER
+ help
+ Choose this option to enable DRM on ZTE ZX SoCs.
diff --git a/drivers/gpu/drm/zte/Makefile b/drivers/gpu/drm/zte/Makefile
new file mode 100644
index 000000000000..699180bfd57c
--- /dev/null
+++ b/drivers/gpu/drm/zte/Makefile
@@ -0,0 +1,7 @@
+zxdrm-y := \
+ zx_drm_drv.o \
+ zx_hdmi.o \
+ zx_plane.o \
+ zx_vou.o
+
+obj-$(CONFIG_DRM_ZTE) += zxdrm.o
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
new file mode 100644
index 000000000000..3e76f72c92ff
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_drm_drv.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_vou.h"
+
+struct zx_drm_private {
+ struct drm_fbdev_cma *fbdev;
+};
+
+static void zx_drm_fb_output_poll_changed(struct drm_device *drm)
+{
+ struct zx_drm_private *priv = drm->dev_private;
+
+ drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
+ .fb_create = drm_fb_cma_create,
+ .output_poll_changed = zx_drm_fb_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static void zx_drm_lastclose(struct drm_device *drm)
+{
+ struct zx_drm_private *priv = drm->dev_private;
+
+ drm_fbdev_cma_restore_mode(priv->fbdev);
+}
+
+static const struct file_operations zx_drm_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = noop_llseek,
+ .mmap = drm_gem_cma_mmap,
+};
+
+static struct drm_driver zx_drm_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
+ DRIVER_ATOMIC,
+ .lastclose = zx_drm_lastclose,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+ .enable_vblank = zx_vou_enable_vblank,
+ .disable_vblank = zx_vou_disable_vblank,
+ .gem_free_object = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .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_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,
+ .fops = &zx_drm_fops,
+ .name = "zx-vou",
+ .desc = "ZTE VOU Controller DRM",
+ .date = "20160811",
+ .major = 1,
+ .minor = 0,
+};
+
+static int zx_drm_bind(struct device *dev)
+{
+ struct drm_device *drm;
+ struct zx_drm_private *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ drm = drm_dev_alloc(&zx_drm_driver, dev);
+ if (IS_ERR(drm))
+ return PTR_ERR(drm);
+
+ drm->dev_private = priv;
+ dev_set_drvdata(dev, drm);
+
+ drm_mode_config_init(drm);
+ drm->mode_config.min_width = 16;
+ drm->mode_config.min_height = 16;
+ drm->mode_config.max_width = 4096;
+ drm->mode_config.max_height = 4096;
+ drm->mode_config.funcs = &zx_drm_mode_config_funcs;
+
+ ret = component_bind_all(dev, drm);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to bind all components: %d\n", ret);
+ goto out_unregister;
+ }
+
+ ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "failed to init vblank: %d\n", ret);
+ goto out_unbind;
+ }
+
+ /*
+ * We will manage irq handler on our own. In this case, irq_enabled
+ * need to be true for using vblank core support.
+ */
+ drm->irq_enabled = true;
+
+ drm_mode_config_reset(drm);
+ drm_kms_helper_poll_init(drm);
+
+ priv->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
+ drm->mode_config.num_connector);
+ if (IS_ERR(priv->fbdev)) {
+ ret = PTR_ERR(priv->fbdev);
+ DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret);
+ priv->fbdev = NULL;
+ goto out_poll_fini;
+ }
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto out_fbdev_fini;
+
+ return 0;
+
+out_fbdev_fini:
+ if (priv->fbdev) {
+ drm_fbdev_cma_fini(priv->fbdev);
+ priv->fbdev = NULL;
+ }
+out_poll_fini:
+ drm_kms_helper_poll_fini(drm);
+ drm_mode_config_cleanup(drm);
+ drm_vblank_cleanup(drm);
+out_unbind:
+ component_unbind_all(dev, drm);
+out_unregister:
+ dev_set_drvdata(dev, NULL);
+ drm->dev_private = NULL;
+ drm_dev_unref(drm);
+ return ret;
+}
+
+static void zx_drm_unbind(struct device *dev)
+{
+ struct drm_device *drm = dev_get_drvdata(dev);
+ struct zx_drm_private *priv = drm->dev_private;
+
+ drm_dev_unregister(drm);
+ if (priv->fbdev) {
+ drm_fbdev_cma_fini(priv->fbdev);
+ priv->fbdev = NULL;
+ }
+ drm_kms_helper_poll_fini(drm);
+ drm_mode_config_cleanup(drm);
+ drm_vblank_cleanup(drm);
+ component_unbind_all(dev, drm);
+ dev_set_drvdata(dev, NULL);
+ drm->dev_private = NULL;
+ drm_dev_unref(drm);
+}
+
+static const struct component_master_ops zx_drm_master_ops = {
+ .bind = zx_drm_bind,
+ .unbind = zx_drm_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int zx_drm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *parent = dev->of_node;
+ struct device_node *child;
+ struct component_match *match = NULL;
+ int ret;
+
+ ret = of_platform_populate(parent, NULL, NULL, dev);
+ if (ret)
+ return ret;
+
+ for_each_available_child_of_node(parent, child) {
+ component_match_add(dev, &match, compare_of, child);
+ of_node_put(child);
+ }
+
+ return component_master_add_with_match(dev, &zx_drm_master_ops, match);
+}
+
+static int zx_drm_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &zx_drm_master_ops);
+ return 0;
+}
+
+static const struct of_device_id zx_drm_of_match[] = {
+ { .compatible = "zte,zx296718-vou", },
+ { /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_drm_of_match);
+
+static struct platform_driver zx_drm_platform_driver = {
+ .probe = zx_drm_probe,
+ .remove = zx_drm_remove,
+ .driver = {
+ .name = "zx-drm",
+ .of_match_table = zx_drm_of_match,
+ },
+};
+
+static struct platform_driver *drivers[] = {
+ &zx_crtc_driver,
+ &zx_hdmi_driver,
+ &zx_drm_platform_driver,
+};
+
+static int zx_drm_init(void)
+{
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_init(zx_drm_init);
+
+static void zx_drm_exit(void)
+{
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(zx_drm_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("ZTE ZX VOU DRM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.h b/drivers/gpu/drm/zte/zx_drm_drv.h
new file mode 100644
index 000000000000..e65cd18a6cba
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_drm_drv.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_DRM_DRV_H__
+#define __ZX_DRM_DRV_H__
+
+extern struct platform_driver zx_crtc_driver;
+extern struct platform_driver zx_hdmi_driver;
+
+static inline u32 zx_readl(void __iomem *reg)
+{
+ return readl_relaxed(reg);
+}
+
+static inline void zx_writel(void __iomem *reg, u32 val)
+{
+ writel_relaxed(val, reg);
+}
+
+static inline void zx_writel_mask(void __iomem *reg, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = zx_readl(reg);
+ tmp = (tmp & ~mask) | (val & mask);
+ zx_writel(reg, tmp);
+}
+
+#endif /* __ZX_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
new file mode 100644
index 000000000000..6bf6c364811e
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_hdmi.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hdmi.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+
+#include "zx_hdmi_regs.h"
+#include "zx_vou.h"
+
+#define ZX_HDMI_INFOFRAME_SIZE 31
+#define DDC_SEGMENT_ADDR 0x30
+
+struct zx_hdmi_i2c {
+ struct i2c_adapter adap;
+ struct mutex lock;
+};
+
+struct zx_hdmi {
+ struct drm_connector connector;
+ struct drm_encoder encoder;
+ struct zx_hdmi_i2c *ddc;
+ struct device *dev;
+ struct drm_device *drm;
+ void __iomem *mmio;
+ struct clk *cec_clk;
+ struct clk *osc_clk;
+ struct clk *xclk;
+ bool sink_is_hdmi;
+ bool sink_has_audio;
+ const struct vou_inf *inf;
+};
+
+#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x)
+
+static const struct vou_inf vou_inf_hdmi = {
+ .id = VOU_HDMI,
+ .data_sel = VOU_YUV444,
+ .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
+ .clocks_sel_bits = BIT(13) | BIT(2),
+};
+
+static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset)
+{
+ return readl_relaxed(hdmi->mmio + offset * 4);
+}
+
+static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val)
+{
+ writel_relaxed(val, hdmi->mmio + offset * 4);
+}
+
+static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset,
+ u8 mask, u8 val)
+{
+ u8 tmp;
+
+ tmp = hdmi_readb(hdmi, offset);
+ tmp = (tmp & ~mask) | (val & mask);
+ hdmi_writeb(hdmi, offset, tmp);
+}
+
+static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi,
+ union hdmi_infoframe *frame, u8 fsel)
+{
+ u8 buffer[ZX_HDMI_INFOFRAME_SIZE];
+ int num;
+ int i;
+
+ hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel);
+
+ num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE);
+ if (num < 0) {
+ DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num);
+ return num;
+ }
+
+ for (i = 0; i < num; i++)
+ hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]);
+
+ hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT,
+ TPI_INFO_TRANS_RPT);
+ hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN,
+ TPI_INFO_TRANS_EN);
+
+ return num;
+}
+
+static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
+ struct drm_display_mode *mode)
+{
+ union hdmi_infoframe frame;
+ int ret;
+
+ ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
+ mode);
+ if (ret) {
+ DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",
+ ret);
+ return ret;
+ }
+
+ return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF);
+}
+
+static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
+ struct drm_display_mode *mode)
+{
+ union hdmi_infoframe frame;
+ int ret;
+
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+ if (ret) {
+ DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* We always use YUV444 for HDMI output. */
+ frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
+
+ return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI);
+}
+
+static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+ if (hdmi->sink_is_hdmi) {
+ zx_hdmi_config_video_avi(hdmi, mode);
+ zx_hdmi_config_video_vsi(hdmi, mode);
+ }
+}
+
+static void zx_hdmi_phy_start(struct zx_hdmi *hdmi)
+{
+ /* Copy from ZTE BSP code */
+ hdmi_writeb(hdmi, 0x222, 0x0);
+ hdmi_writeb(hdmi, 0x224, 0x4);
+ hdmi_writeb(hdmi, 0x909, 0x0);
+ hdmi_writeb(hdmi, 0x7b0, 0x90);
+ hdmi_writeb(hdmi, 0x7b1, 0x00);
+ hdmi_writeb(hdmi, 0x7b2, 0xa7);
+ hdmi_writeb(hdmi, 0x7b8, 0xaa);
+ hdmi_writeb(hdmi, 0x7b2, 0xa7);
+ hdmi_writeb(hdmi, 0x7b3, 0x0f);
+ hdmi_writeb(hdmi, 0x7b4, 0x0f);
+ hdmi_writeb(hdmi, 0x7b5, 0x55);
+ hdmi_writeb(hdmi, 0x7b7, 0x03);
+ hdmi_writeb(hdmi, 0x7b9, 0x12);
+ hdmi_writeb(hdmi, 0x7ba, 0x32);
+ hdmi_writeb(hdmi, 0x7bc, 0x68);
+ hdmi_writeb(hdmi, 0x7be, 0x40);
+ hdmi_writeb(hdmi, 0x7bf, 0x84);
+ hdmi_writeb(hdmi, 0x7c1, 0x0f);
+ hdmi_writeb(hdmi, 0x7c8, 0x02);
+ hdmi_writeb(hdmi, 0x7c9, 0x03);
+ hdmi_writeb(hdmi, 0x7ca, 0x40);
+ hdmi_writeb(hdmi, 0x7dc, 0x31);
+ hdmi_writeb(hdmi, 0x7e2, 0x04);
+ hdmi_writeb(hdmi, 0x7e0, 0x06);
+ hdmi_writeb(hdmi, 0x7cb, 0x68);
+ hdmi_writeb(hdmi, 0x7f9, 0x02);
+ hdmi_writeb(hdmi, 0x7b6, 0x02);
+ hdmi_writeb(hdmi, 0x7f3, 0x0);
+}
+
+static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi)
+{
+ /* Enable pclk */
+ hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK);
+
+ /* Enable HDMI for TX */
+ hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN);
+
+ /* Enable deep color packet */
+ hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
+
+ /* Enable HDMI/MHL mode for output */
+ hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE,
+ TEST_TXCTRL_HDMI_MODE);
+
+ /* Configure reg_qc_sel */
+ hdmi_writeb(hdmi, HDMICTL4, 0x3);
+
+ /* Enable interrupt */
+ hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT,
+ INTR1_MONITOR_DETECT);
+
+ /* Start up phy */
+ zx_hdmi_phy_start(hdmi);
+}
+
+static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi)
+{
+ /* Disable interrupt */
+ hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0);
+
+ /* Disable deep color packet */
+ hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
+
+ /* Disable HDMI for TX */
+ hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0);
+
+ /* Disable pclk */
+ hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0);
+}
+
+static void zx_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+ clk_prepare_enable(hdmi->cec_clk);
+ clk_prepare_enable(hdmi->osc_clk);
+ clk_prepare_enable(hdmi->xclk);
+
+ zx_hdmi_hw_enable(hdmi);
+
+ vou_inf_enable(hdmi->inf, encoder->crtc);
+}
+
+static void zx_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+ vou_inf_disable(hdmi->inf, encoder->crtc);
+
+ zx_hdmi_hw_disable(hdmi);
+
+ clk_disable_unprepare(hdmi->xclk);
+ clk_disable_unprepare(hdmi->osc_clk);
+ clk_disable_unprepare(hdmi->cec_clk);
+}
+
+static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = {
+ .enable = zx_hdmi_encoder_enable,
+ .disable = zx_hdmi_encoder_disable,
+ .mode_set = zx_hdmi_encoder_mode_set,
+};
+
+static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int zx_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+ struct zx_hdmi *hdmi = to_zx_hdmi(connector);
+ struct edid *edid;
+ int ret;
+
+ edid = drm_get_edid(connector, &hdmi->ddc->adap);
+ if (!edid)
+ return 0;
+
+ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
+ hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+ kfree(edid);
+
+ return ret;
+}
+
+static enum drm_mode_status
+zx_hdmi_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = {
+ .get_modes = zx_hdmi_connector_get_modes,
+ .mode_valid = zx_hdmi_connector_mode_valid,
+};
+
+static enum drm_connector_status
+zx_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct zx_hdmi *hdmi = to_zx_hdmi(connector);
+
+ return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ?
+ connector_status_connected : connector_status_disconnected;
+}
+
+static const struct drm_connector_funcs zx_hdmi_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = zx_hdmi_connector_detect,
+ .destroy = drm_connector_cleanup,
+ .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 int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
+{
+ struct drm_encoder *encoder = &hdmi->encoder;
+
+ encoder->possible_crtcs = VOU_CRTC_MASK;
+
+ drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs);
+
+ hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
+
+ drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(&hdmi->connector,
+ &zx_hdmi_connector_helper_funcs);
+
+ drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
+
+ return 0;
+}
+
+static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id)
+{
+ struct zx_hdmi *hdmi = dev_id;
+
+ drm_helper_hpd_irq_event(hdmi->connector.dev);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id)
+{
+ struct zx_hdmi *hdmi = dev_id;
+ u8 lstat;
+
+ lstat = hdmi_readb(hdmi, L1_INTR_STAT);
+
+ /* Monitor detect/HPD interrupt */
+ if (lstat & L1_INTR_STAT_INTR1) {
+ u8 stat;
+
+ stat = hdmi_readb(hdmi, INTR1_STAT);
+ hdmi_writeb(hdmi, INTR1_STAT, stat);
+
+ if (stat & INTR1_MONITOR_DETECT)
+ return IRQ_WAKE_THREAD;
+ }
+
+ return IRQ_NONE;
+}
+
+static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg)
+{
+ int len = msg->len;
+ u8 *buf = msg->buf;
+ int retry = 0;
+ int ret = 0;
+
+ /* Bits [9:8] of bytes */
+ hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff);
+ /* Bits [7:0] of bytes */
+ hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff);
+
+ /* Clear FIFO */
+ hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO);
+
+ /* Kick off the read */
+ hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK,
+ DDC_CMD_SEQUENTIAL_READ);
+
+ while (len > 0) {
+ int cnt, i;
+
+ /* FIFO needs some time to get ready */
+ usleep_range(500, 1000);
+
+ cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK;
+ if (cnt == 0) {
+ if (++retry > 5) {
+ DRM_DEV_ERROR(hdmi->dev,
+ "DDC FIFO read timed out!");
+ return -ETIMEDOUT;
+ }
+ continue;
+ }
+
+ for (i = 0; i < cnt; i++)
+ *buf++ = hdmi_readb(hdmi, ZX_DDC_DATA);
+ len -= cnt;
+ }
+
+ return ret;
+}
+
+static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg)
+{
+ /*
+ * The DDC I2C adapter is only for reading EDID data, so we assume
+ * that the write to this adapter must be the EDID data offset.
+ */
+ if ((msg->len != 1) ||
+ ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR)))
+ return -EINVAL;
+
+ if (msg->addr == DDC_SEGMENT_ADDR)
+ hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1);
+ else if (msg->addr == DDC_ADDR)
+ hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1);
+
+ hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]);
+
+ return 0;
+}
+
+static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct zx_hdmi *hdmi = i2c_get_adapdata(adap);
+ struct zx_hdmi_i2c *ddc = hdmi->ddc;
+ int i, ret = 0;
+
+ mutex_lock(&ddc->lock);
+
+ /* Enable DDC master access */
+ hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER);
+
+ for (i = 0; i < num; i++) {
+ DRM_DEV_DEBUG(hdmi->dev,
+ "xfer: num: %d/%d, len: %d, flags: %#x\n",
+ i + 1, num, msgs[i].len, msgs[i].flags);
+
+ if (msgs[i].flags & I2C_M_RD)
+ ret = zx_hdmi_i2c_read(hdmi, &msgs[i]);
+ else
+ ret = zx_hdmi_i2c_write(hdmi, &msgs[i]);
+
+ if (ret < 0)
+ break;
+ }
+
+ if (!ret)
+ ret = num;
+
+ /* Disable DDC master access */
+ hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0);
+
+ mutex_unlock(&ddc->lock);
+
+ return ret;
+}
+
+static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm zx_hdmi_algorithm = {
+ .master_xfer = zx_hdmi_i2c_xfer,
+ .functionality = zx_hdmi_i2c_func,
+};
+
+static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi)
+{
+ struct i2c_adapter *adap;
+ struct zx_hdmi_i2c *ddc;
+ int ret;
+
+ ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
+ if (!ddc)
+ return -ENOMEM;
+
+ hdmi->ddc = ddc;
+ mutex_init(&ddc->lock);
+
+ adap = &ddc->adap;
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_DDC;
+ adap->dev.parent = hdmi->dev;
+ adap->algo = &zx_hdmi_algorithm;
+ snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c");
+
+ ret = i2c_add_adapter(adap);
+ if (ret) {
+ DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n",
+ ret);
+ return ret;
+ }
+
+ i2c_set_adapdata(adap, hdmi);
+
+ return 0;
+}
+
+static int zx_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = data;
+ struct resource *res;
+ struct zx_hdmi *hdmi;
+ int irq;
+ int ret;
+
+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ hdmi->dev = dev;
+ hdmi->drm = drm;
+ hdmi->inf = &vou_inf_hdmi;
+
+ dev_set_drvdata(dev, hdmi);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hdmi->mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(hdmi->mmio)) {
+ ret = PTR_ERR(hdmi->mmio);
+ DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret);
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec");
+ if (IS_ERR(hdmi->cec_clk)) {
+ ret = PTR_ERR(hdmi->cec_clk);
+ DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret);
+ return ret;
+ }
+
+ hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk");
+ if (IS_ERR(hdmi->osc_clk)) {
+ ret = PTR_ERR(hdmi->osc_clk);
+ DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret);
+ return ret;
+ }
+
+ hdmi->xclk = devm_clk_get(hdmi->dev, "xclk");
+ if (IS_ERR(hdmi->xclk)) {
+ ret = PTR_ERR(hdmi->xclk);
+ DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = zx_hdmi_ddc_register(hdmi);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
+ return ret;
+ }
+
+ ret = zx_hdmi_register(drm, hdmi);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler,
+ zx_hdmi_irq_thread, IRQF_SHARED,
+ dev_name(dev), hdmi);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void zx_hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct zx_hdmi *hdmi = dev_get_drvdata(dev);
+
+ hdmi->connector.funcs->destroy(&hdmi->connector);
+ hdmi->encoder.funcs->destroy(&hdmi->encoder);
+}
+
+static const struct component_ops zx_hdmi_component_ops = {
+ .bind = zx_hdmi_bind,
+ .unbind = zx_hdmi_unbind,
+};
+
+static int zx_hdmi_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &zx_hdmi_component_ops);
+}
+
+static int zx_hdmi_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &zx_hdmi_component_ops);
+ return 0;
+}
+
+static const struct of_device_id zx_hdmi_of_match[] = {
+ { .compatible = "zte,zx296718-hdmi", },
+ { /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_hdmi_of_match);
+
+struct platform_driver zx_hdmi_driver = {
+ .probe = zx_hdmi_probe,
+ .remove = zx_hdmi_remove,
+ .driver = {
+ .name = "zx-hdmi",
+ .of_match_table = zx_hdmi_of_match,
+ },
+};
diff --git a/drivers/gpu/drm/zte/zx_hdmi_regs.h b/drivers/gpu/drm/zte/zx_hdmi_regs.h
new file mode 100644
index 000000000000..de911f66b658
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_hdmi_regs.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_HDMI_REGS_H__
+#define __ZX_HDMI_REGS_H__
+
+#define FUNC_SEL 0x000b
+#define FUNC_HDMI_EN BIT(0)
+#define CLKPWD 0x000d
+#define CLKPWD_PDIDCK BIT(2)
+#define P2T_CTRL 0x0066
+#define P2T_DC_PKT_EN BIT(7)
+#define L1_INTR_STAT 0x007e
+#define L1_INTR_STAT_INTR1 BIT(0)
+#define INTR1_STAT 0x008f
+#define INTR1_MASK 0x0095
+#define INTR1_MONITOR_DETECT (BIT(5) | BIT(6))
+#define ZX_DDC_ADDR 0x00ed
+#define ZX_DDC_SEGM 0x00ee
+#define ZX_DDC_OFFSET 0x00ef
+#define ZX_DDC_DIN_CNT1 0x00f0
+#define ZX_DDC_DIN_CNT2 0x00f1
+#define ZX_DDC_CMD 0x00f3
+#define DDC_CMD_MASK 0xf
+#define DDC_CMD_CLEAR_FIFO 0x9
+#define DDC_CMD_SEQUENTIAL_READ 0x2
+#define ZX_DDC_DATA 0x00f4
+#define ZX_DDC_DOUT_CNT 0x00f5
+#define DDC_DOUT_CNT_MASK 0x1f
+#define TEST_TXCTRL 0x00f7
+#define TEST_TXCTRL_HDMI_MODE BIT(1)
+#define HDMICTL4 0x0235
+#define TPI_HPD_RSEN 0x063b
+#define TPI_HPD_CONNECTION (BIT(1) | BIT(2))
+#define TPI_INFO_FSEL 0x06bf
+#define FSEL_AVI 0
+#define FSEL_GBD 1
+#define FSEL_AUDIO 2
+#define FSEL_SPD 3
+#define FSEL_MPEG 4
+#define FSEL_VSIF 5
+#define TPI_INFO_B0 0x06c0
+#define TPI_INFO_EN 0x06df
+#define TPI_INFO_TRANS_EN BIT(7)
+#define TPI_INFO_TRANS_RPT BIT(6)
+#define TPI_DDC_MASTER_EN 0x06f8
+#define HW_DDC_MASTER BIT(7)
+
+#endif /* __ZX_HDMI_REGS_H__ */
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
new file mode 100644
index 000000000000..546eb92a94e8
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_plane.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_plane.h"
+#include "zx_plane_regs.h"
+#include "zx_vou.h"
+
+struct zx_plane {
+ struct drm_plane plane;
+ void __iomem *layer;
+ void __iomem *csc;
+ void __iomem *hbsc;
+ void __iomem *rsz;
+};
+
+#define to_zx_plane(plane) container_of(plane, struct zx_plane, plane)
+
+static const uint32_t gl_formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_ARGB4444,
+};
+
+static int zx_gl_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_crtc *crtc = plane_state->crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_rect clip;
+
+ if (!crtc || !fb)
+ return 0;
+
+ crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
+ crtc);
+ if (WARN_ON(!crtc_state))
+ return -EINVAL;
+
+ /* nothing to check when disabling or disabled */
+ if (!crtc_state->enable)
+ return 0;
+
+ /* plane must be enabled */
+ if (!plane_state->crtc)
+ return -EINVAL;
+
+ clip.x1 = 0;
+ clip.y1 = 0;
+ clip.x2 = crtc_state->adjusted_mode.hdisplay;
+ clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+ return drm_plane_helper_check_state(plane_state, &clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ false, true);
+}
+
+static int zx_gl_get_fmt(uint32_t format)
+{
+ switch (format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ return GL_FMT_ARGB8888;
+ case DRM_FORMAT_RGB888:
+ return GL_FMT_RGB888;
+ case DRM_FORMAT_RGB565:
+ return GL_FMT_RGB565;
+ case DRM_FORMAT_ARGB1555:
+ return GL_FMT_ARGB1555;
+ case DRM_FORMAT_ARGB4444:
+ return GL_FMT_ARGB4444;
+ default:
+ WARN_ONCE(1, "invalid pixel format %d\n", format);
+ return -EINVAL;
+ }
+}
+
+static inline void zx_gl_set_update(struct zx_plane *zplane)
+{
+ void __iomem *layer = zplane->layer;
+
+ zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
+}
+
+static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
+{
+ zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
+}
+
+void zx_plane_set_update(struct drm_plane *plane)
+{
+ struct zx_plane *zplane = to_zx_plane(plane);
+
+ zx_gl_rsz_set_update(zplane);
+ zx_gl_set_update(zplane);
+}
+
+static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
+ u32 dst_w, u32 dst_h)
+{
+ void __iomem *rsz = zplane->rsz;
+
+ zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
+ zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
+
+ zx_gl_rsz_set_update(zplane);
+}
+
+static void zx_gl_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct zx_plane *zplane = to_zx_plane(plane);
+ struct drm_framebuffer *fb = plane->state->fb;
+ struct drm_gem_cma_object *cma_obj;
+ void __iomem *layer = zplane->layer;
+ void __iomem *csc = zplane->csc;
+ void __iomem *hbsc = zplane->hbsc;
+ u32 src_x, src_y, src_w, src_h;
+ u32 dst_x, dst_y, dst_w, dst_h;
+ unsigned int bpp;
+ uint32_t format;
+ dma_addr_t paddr;
+ u32 stride;
+ int fmt;
+
+ if (!fb)
+ return;
+
+ format = fb->pixel_format;
+ stride = fb->pitches[0];
+
+ src_x = plane->state->src_x >> 16;
+ src_y = plane->state->src_y >> 16;
+ src_w = plane->state->src_w >> 16;
+ src_h = plane->state->src_h >> 16;
+
+ dst_x = plane->state->crtc_x;
+ dst_y = plane->state->crtc_y;
+ dst_w = plane->state->crtc_w;
+ dst_h = plane->state->crtc_h;
+
+ bpp = drm_format_plane_cpp(format, 0);
+
+ cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+ paddr = cma_obj->paddr + fb->offsets[0];
+ paddr += src_y * stride + src_x * bpp / 8;
+ zx_writel(layer + GL_ADDR, paddr);
+
+ /* Set up source height/width register */
+ zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
+
+ /* Set up start position register */
+ zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
+
+ /* Set up end position register */
+ zx_writel(layer + GL_POS_END,
+ GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
+
+ /* Set up stride register */
+ zx_writel(layer + GL_STRIDE, stride & 0xffff);
+
+ /* Set up graphic layer data format */
+ fmt = zx_gl_get_fmt(format);
+ if (fmt >= 0)
+ zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
+ fmt << GL_DATA_FMT_SHIFT);
+
+ /* Initialize global alpha with a sane value */
+ zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
+ 0xff << GL_GLOBAL_ALPHA_SHIFT);
+
+ /* Setup CSC for the GL */
+ if (dst_h > 720)
+ zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
+ CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
+ else
+ zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
+ CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
+ zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
+
+ /* Always use scaler since it exists (set for not bypass) */
+ zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
+ GL_SCALER_BYPASS_MODE);
+
+ zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
+
+ /* Enable HBSC block */
+ zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
+
+ zx_gl_set_update(zplane);
+}
+
+static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
+ .atomic_check = zx_gl_plane_atomic_check,
+ .atomic_update = zx_gl_plane_atomic_update,
+};
+
+static void zx_plane_destroy(struct drm_plane *plane)
+{
+ drm_plane_helper_disable(plane);
+ drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs zx_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = zx_plane_destroy,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static void zx_plane_hbsc_init(struct zx_plane *zplane)
+{
+ void __iomem *hbsc = zplane->hbsc;
+
+ /*
+ * Initialize HBSC block with a sane configuration per recommedation
+ * from ZTE BSP code.
+ */
+ zx_writel(hbsc + HBSC_SATURATION, 0x200);
+ zx_writel(hbsc + HBSC_HUE, 0x0);
+ zx_writel(hbsc + HBSC_BRIGHT, 0x0);
+ zx_writel(hbsc + HBSC_CONTRAST, 0x200);
+
+ zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
+ zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
+ zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
+}
+
+struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
+ struct zx_layer_data *data,
+ enum drm_plane_type type)
+{
+ const struct drm_plane_helper_funcs *helper;
+ struct zx_plane *zplane;
+ struct drm_plane *plane;
+ const uint32_t *formats;
+ unsigned int format_count;
+ int ret;
+
+ zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
+ if (!zplane)
+ return ERR_PTR(-ENOMEM);
+
+ plane = &zplane->plane;
+
+ zplane->layer = data->layer;
+ zplane->hbsc = data->hbsc;
+ zplane->csc = data->csc;
+ zplane->rsz = data->rsz;
+
+ zx_plane_hbsc_init(zplane);
+
+ switch (type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ helper = &zx_gl_plane_helper_funcs;
+ formats = gl_formats;
+ format_count = ARRAY_SIZE(gl_formats);
+ break;
+ case DRM_PLANE_TYPE_OVERLAY:
+ /* TODO: add video layer (vl) support */
+ break;
+ default:
+ return ERR_PTR(-ENODEV);
+ }
+
+ ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
+ &zx_plane_funcs, formats, format_count,
+ type, NULL);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ drm_plane_helper_add(plane, helper);
+
+ return plane;
+}
diff --git a/drivers/gpu/drm/zte/zx_plane.h b/drivers/gpu/drm/zte/zx_plane.h
new file mode 100644
index 000000000000..2b82cd558d9d
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_plane.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_PLANE_H__
+#define __ZX_PLANE_H__
+
+struct zx_layer_data {
+ void __iomem *layer;
+ void __iomem *csc;
+ void __iomem *hbsc;
+ void __iomem *rsz;
+};
+
+struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
+ struct zx_layer_data *data,
+ enum drm_plane_type type);
+void zx_plane_set_update(struct drm_plane *plane);
+
+#endif /* __ZX_PLANE_H__ */
diff --git a/drivers/gpu/drm/zte/zx_plane_regs.h b/drivers/gpu/drm/zte/zx_plane_regs.h
new file mode 100644
index 000000000000..3dde6716a558
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_plane_regs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_PLANE_REGS_H__
+#define __ZX_PLANE_REGS_H__
+
+/* GL registers */
+#define GL_CTRL0 0x00
+#define GL_UPDATE BIT(5)
+#define GL_CTRL1 0x04
+#define GL_DATA_FMT_SHIFT 0
+#define GL_DATA_FMT_MASK (0xf << GL_DATA_FMT_SHIFT)
+#define GL_FMT_ARGB8888 0
+#define GL_FMT_RGB888 1
+#define GL_FMT_RGB565 2
+#define GL_FMT_ARGB1555 3
+#define GL_FMT_ARGB4444 4
+#define GL_CTRL2 0x08
+#define GL_GLOBAL_ALPHA_SHIFT 8
+#define GL_GLOBAL_ALPHA_MASK (0xff << GL_GLOBAL_ALPHA_SHIFT)
+#define GL_CTRL3 0x0c
+#define GL_SCALER_BYPASS_MODE BIT(0)
+#define GL_STRIDE 0x18
+#define GL_ADDR 0x1c
+#define GL_SRC_SIZE 0x38
+#define GL_SRC_W_SHIFT 16
+#define GL_SRC_W_MASK (0x3fff << GL_SRC_W_SHIFT)
+#define GL_SRC_H_SHIFT 0
+#define GL_SRC_H_MASK (0x3fff << GL_SRC_H_SHIFT)
+#define GL_POS_START 0x9c
+#define GL_POS_END 0xa0
+#define GL_POS_X_SHIFT 16
+#define GL_POS_X_MASK (0x1fff << GL_POS_X_SHIFT)
+#define GL_POS_Y_SHIFT 0
+#define GL_POS_Y_MASK (0x1fff << GL_POS_Y_SHIFT)
+
+#define GL_SRC_W(x) (((x) << GL_SRC_W_SHIFT) & GL_SRC_W_MASK)
+#define GL_SRC_H(x) (((x) << GL_SRC_H_SHIFT) & GL_SRC_H_MASK)
+#define GL_POS_X(x) (((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
+#define GL_POS_Y(x) (((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
+
+/* CSC registers */
+#define CSC_CTRL0 0x30
+#define CSC_COV_MODE_SHIFT 16
+#define CSC_COV_MODE_MASK (0xffff << CSC_COV_MODE_SHIFT)
+#define CSC_BT601_IMAGE_RGB2YCBCR 0
+#define CSC_BT601_IMAGE_YCBCR2RGB 1
+#define CSC_BT601_VIDEO_RGB2YCBCR 2
+#define CSC_BT601_VIDEO_YCBCR2RGB 3
+#define CSC_BT709_IMAGE_RGB2YCBCR 4
+#define CSC_BT709_IMAGE_YCBCR2RGB 5
+#define CSC_BT709_VIDEO_RGB2YCBCR 6
+#define CSC_BT709_VIDEO_YCBCR2RGB 7
+#define CSC_BT2020_IMAGE_RGB2YCBCR 8
+#define CSC_BT2020_IMAGE_YCBCR2RGB 9
+#define CSC_BT2020_VIDEO_RGB2YCBCR 10
+#define CSC_BT2020_VIDEO_YCBCR2RGB 11
+#define CSC_WORK_ENABLE BIT(0)
+
+/* RSZ registers */
+#define RSZ_SRC_CFG 0x00
+#define RSZ_DEST_CFG 0x04
+#define RSZ_ENABLE_CFG 0x14
+
+#define RSZ_VER_SHIFT 16
+#define RSZ_VER_MASK (0xffff << RSZ_VER_SHIFT)
+#define RSZ_HOR_SHIFT 0
+#define RSZ_HOR_MASK (0xffff << RSZ_HOR_SHIFT)
+
+#define RSZ_VER(x) (((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
+#define RSZ_HOR(x) (((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
+
+/* HBSC registers */
+#define HBSC_SATURATION 0x00
+#define HBSC_HUE 0x04
+#define HBSC_BRIGHT 0x08
+#define HBSC_CONTRAST 0x0c
+#define HBSC_THRESHOLD_COL1 0x10
+#define HBSC_THRESHOLD_COL2 0x14
+#define HBSC_THRESHOLD_COL3 0x18
+#define HBSC_CTRL0 0x28
+#define HBSC_CTRL_EN BIT(2)
+
+#endif /* __ZX_PLANE_REGS_H__ */
diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
new file mode 100644
index 000000000000..73fe15c17c32
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_vou.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_address.h>
+#include <video/videomode.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_plane.h"
+#include "zx_vou.h"
+#include "zx_vou_regs.h"
+
+#define GL_NUM 2
+#define VL_NUM 3
+
+enum vou_chn_type {
+ VOU_CHN_MAIN,
+ VOU_CHN_AUX,
+};
+
+struct zx_crtc_regs {
+ u32 fir_active;
+ u32 fir_htiming;
+ u32 fir_vtiming;
+ u32 timing_shift;
+ u32 timing_pi_shift;
+};
+
+static const struct zx_crtc_regs main_crtc_regs = {
+ .fir_active = FIR_MAIN_ACTIVE,
+ .fir_htiming = FIR_MAIN_H_TIMING,
+ .fir_vtiming = FIR_MAIN_V_TIMING,
+ .timing_shift = TIMING_MAIN_SHIFT,
+ .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
+};
+
+static const struct zx_crtc_regs aux_crtc_regs = {
+ .fir_active = FIR_AUX_ACTIVE,
+ .fir_htiming = FIR_AUX_H_TIMING,
+ .fir_vtiming = FIR_AUX_V_TIMING,
+ .timing_shift = TIMING_AUX_SHIFT,
+ .timing_pi_shift = TIMING_AUX_PI_SHIFT,
+};
+
+struct zx_crtc_bits {
+ u32 polarity_mask;
+ u32 polarity_shift;
+ u32 int_frame_mask;
+ u32 tc_enable;
+ u32 gl_enable;
+};
+
+static const struct zx_crtc_bits main_crtc_bits = {
+ .polarity_mask = MAIN_POL_MASK,
+ .polarity_shift = MAIN_POL_SHIFT,
+ .int_frame_mask = TIMING_INT_MAIN_FRAME,
+ .tc_enable = MAIN_TC_EN,
+ .gl_enable = OSD_CTRL0_GL0_EN,
+};
+
+static const struct zx_crtc_bits aux_crtc_bits = {
+ .polarity_mask = AUX_POL_MASK,
+ .polarity_shift = AUX_POL_SHIFT,
+ .int_frame_mask = TIMING_INT_AUX_FRAME,
+ .tc_enable = AUX_TC_EN,
+ .gl_enable = OSD_CTRL0_GL1_EN,
+};
+
+struct zx_crtc {
+ struct drm_crtc crtc;
+ struct drm_plane *primary;
+ struct zx_vou_hw *vou;
+ void __iomem *chnreg;
+ const struct zx_crtc_regs *regs;
+ const struct zx_crtc_bits *bits;
+ enum vou_chn_type chn_type;
+ struct clk *pixclk;
+};
+
+#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
+
+struct zx_vou_hw {
+ struct device *dev;
+ void __iomem *osd;
+ void __iomem *timing;
+ void __iomem *vouctl;
+ void __iomem *otfppu;
+ void __iomem *dtrc;
+ struct clk *axi_clk;
+ struct clk *ppu_clk;
+ struct clk *main_clk;
+ struct clk *aux_clk;
+ struct zx_crtc *main_crtc;
+ struct zx_crtc *aux_crtc;
+};
+
+static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
+{
+ struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+
+ return zcrtc->vou;
+}
+
+void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc)
+{
+ struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+ struct zx_vou_hw *vou = zcrtc->vou;
+ bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
+ u32 data_sel_shift = inf->id << 1;
+
+ /* Select data format */
+ zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
+ inf->data_sel << data_sel_shift);
+
+ /* Select channel */
+ zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << inf->id,
+ zcrtc->chn_type << inf->id);
+
+ /* Select interface clocks */
+ zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
+ is_main ? 0 : inf->clocks_sel_bits);
+
+ /* Enable interface clocks */
+ zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
+ inf->clocks_en_bits);
+
+ /* Enable the device */
+ zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 1 << inf->id);
+}
+
+void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc)
+{
+ struct zx_vou_hw *vou = crtc_to_vou(crtc);
+
+ /* Disable the device */
+ zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 0);
+
+ /* Disable interface clocks */
+ zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
+}
+
+static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
+{
+ zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
+}
+
+static void zx_crtc_enable(struct drm_crtc *crtc)
+{
+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+ struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+ struct zx_vou_hw *vou = zcrtc->vou;
+ const struct zx_crtc_regs *regs = zcrtc->regs;
+ const struct zx_crtc_bits *bits = zcrtc->bits;
+ struct videomode vm;
+ u32 pol = 0;
+ u32 val;
+ int ret;
+
+ drm_display_mode_to_videomode(mode, &vm);
+
+ /* Set up timing parameters */
+ val = V_ACTIVE(vm.vactive - 1);
+ val |= H_ACTIVE(vm.hactive - 1);
+ zx_writel(vou->timing + regs->fir_active, val);
+
+ val = SYNC_WIDE(vm.hsync_len - 1);
+ val |= BACK_PORCH(vm.hback_porch - 1);
+ val |= FRONT_PORCH(vm.hfront_porch - 1);
+ zx_writel(vou->timing + regs->fir_htiming, val);
+
+ val = SYNC_WIDE(vm.vsync_len - 1);
+ val |= BACK_PORCH(vm.vback_porch - 1);
+ val |= FRONT_PORCH(vm.vfront_porch - 1);
+ zx_writel(vou->timing + regs->fir_vtiming, val);
+
+ /* Set up polarities */
+ if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
+ pol |= 1 << POL_VSYNC_SHIFT;
+ if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
+ pol |= 1 << POL_HSYNC_SHIFT;
+
+ zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
+ pol << bits->polarity_shift);
+
+ /* Setup SHIFT register by following what ZTE BSP does */
+ zx_writel(vou->timing + regs->timing_shift, H_SHIFT_VAL);
+ zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
+
+ /* Enable TIMING_CTRL */
+ zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
+ bits->tc_enable);
+
+ /* Configure channel screen size */
+ zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
+ vm.hactive << CHN_SCREEN_W_SHIFT);
+ zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
+ vm.vactive << CHN_SCREEN_H_SHIFT);
+
+ /* Update channel */
+ vou_chn_set_update(zcrtc);
+
+ /* Enable channel */
+ zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
+
+ /* Enable Graphic Layer */
+ zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable,
+ bits->gl_enable);
+
+ drm_crtc_vblank_on(crtc);
+
+ ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
+ if (ret) {
+ DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
+ return;
+ }
+
+ ret = clk_prepare_enable(zcrtc->pixclk);
+ if (ret)
+ DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
+}
+
+static void zx_crtc_disable(struct drm_crtc *crtc)
+{
+ struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+ const struct zx_crtc_bits *bits = zcrtc->bits;
+ struct zx_vou_hw *vou = zcrtc->vou;
+
+ clk_disable_unprepare(zcrtc->pixclk);
+
+ drm_crtc_vblank_off(crtc);
+
+ /* Disable Graphic Layer */
+ zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0);
+
+ /* Disable channel */
+ zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
+
+ /* Disable TIMING_CTRL */
+ zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
+}
+
+static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct drm_pending_vblank_event *event = crtc->state->event;
+
+ if (!event)
+ return;
+
+ crtc->state->event = NULL;
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (drm_crtc_vblank_get(crtc) == 0)
+ drm_crtc_arm_vblank_event(crtc, event);
+ else
+ drm_crtc_send_vblank_event(crtc, event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+}
+
+static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
+ .enable = zx_crtc_enable,
+ .disable = zx_crtc_disable,
+ .atomic_flush = zx_crtc_atomic_flush,
+};
+
+static const struct drm_crtc_funcs zx_crtc_funcs = {
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_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,
+};
+
+static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
+ enum vou_chn_type chn_type)
+{
+ struct device *dev = vou->dev;
+ struct zx_layer_data data;
+ struct zx_crtc *zcrtc;
+ int ret;
+
+ zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
+ if (!zcrtc)
+ return -ENOMEM;
+
+ zcrtc->vou = vou;
+ zcrtc->chn_type = chn_type;
+
+ if (chn_type == VOU_CHN_MAIN) {
+ data.layer = vou->osd + MAIN_GL_OFFSET;
+ data.csc = vou->osd + MAIN_CSC_OFFSET;
+ data.hbsc = vou->osd + MAIN_HBSC_OFFSET;
+ data.rsz = vou->otfppu + MAIN_RSZ_OFFSET;
+ zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
+ zcrtc->regs = &main_crtc_regs;
+ zcrtc->bits = &main_crtc_bits;
+ } else {
+ data.layer = vou->osd + AUX_GL_OFFSET;
+ data.csc = vou->osd + AUX_CSC_OFFSET;
+ data.hbsc = vou->osd + AUX_HBSC_OFFSET;
+ data.rsz = vou->otfppu + AUX_RSZ_OFFSET;
+ zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
+ zcrtc->regs = &aux_crtc_regs;
+ zcrtc->bits = &aux_crtc_bits;
+ }
+
+ zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
+ "main_wclk" : "aux_wclk");
+ if (IS_ERR(zcrtc->pixclk)) {
+ ret = PTR_ERR(zcrtc->pixclk);
+ DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
+ return ret;
+ }
+
+ zcrtc->primary = zx_plane_init(drm, dev, &data, DRM_PLANE_TYPE_PRIMARY);
+ if (IS_ERR(zcrtc->primary)) {
+ ret = PTR_ERR(zcrtc->primary);
+ DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
+ return ret;
+ }
+
+ ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
+ &zx_crtc_funcs, NULL);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
+ return ret;
+ }
+
+ drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
+
+ if (chn_type == VOU_CHN_MAIN)
+ vou->main_crtc = zcrtc;
+ else
+ vou->aux_crtc = zcrtc;
+
+ return 0;
+}
+
+static inline struct drm_crtc *zx_find_crtc(struct drm_device *drm, int pipe)
+{
+ struct drm_crtc *crtc;
+
+ list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
+ if (crtc->index == pipe)
+ return crtc;
+
+ return NULL;
+}
+
+int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+ struct drm_crtc *crtc;
+ struct zx_crtc *zcrtc;
+ struct zx_vou_hw *vou;
+ u32 int_frame_mask;
+
+ crtc = zx_find_crtc(drm, pipe);
+ if (!crtc)
+ return 0;
+
+ vou = crtc_to_vou(crtc);
+ zcrtc = to_zx_crtc(crtc);
+ int_frame_mask = zcrtc->bits->int_frame_mask;
+
+ zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
+ int_frame_mask);
+
+ return 0;
+}
+
+void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+ struct drm_crtc *crtc;
+ struct zx_crtc *zcrtc;
+ struct zx_vou_hw *vou;
+
+ crtc = zx_find_crtc(drm, pipe);
+ if (!crtc)
+ return;
+
+ vou = crtc_to_vou(crtc);
+ zcrtc = to_zx_crtc(crtc);
+
+ zx_writel_mask(vou->timing + TIMING_INT_CTRL,
+ zcrtc->bits->int_frame_mask, 0);
+}
+
+static irqreturn_t vou_irq_handler(int irq, void *dev_id)
+{
+ struct zx_vou_hw *vou = dev_id;
+ u32 state;
+
+ /* Handle TIMING_CTRL frame interrupts */
+ state = zx_readl(vou->timing + TIMING_INT_STATE);
+ zx_writel(vou->timing + TIMING_INT_STATE, state);
+
+ if (state & TIMING_INT_MAIN_FRAME)
+ drm_crtc_handle_vblank(&vou->main_crtc->crtc);
+
+ if (state & TIMING_INT_AUX_FRAME)
+ drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
+
+ /* Handle OSD interrupts */
+ state = zx_readl(vou->osd + OSD_INT_STA);
+ zx_writel(vou->osd + OSD_INT_CLRSTA, state);
+
+ if (state & OSD_INT_MAIN_UPT) {
+ vou_chn_set_update(vou->main_crtc);
+ zx_plane_set_update(vou->main_crtc->primary);
+ }
+
+ if (state & OSD_INT_AUX_UPT) {
+ vou_chn_set_update(vou->aux_crtc);
+ zx_plane_set_update(vou->aux_crtc->primary);
+ }
+
+ if (state & OSD_INT_ERROR)
+ DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
+
+ return IRQ_HANDLED;
+}
+
+static void vou_dtrc_init(struct zx_vou_hw *vou)
+{
+ /* Clear bit for bypass by ID */
+ zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
+ TILE2RASTESCAN_BYPASS_MODE, 0);
+
+ /* Select ARIDR mode */
+ zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
+ DETILE_ARID_IN_ARIDR);
+
+ /* Bypass decompression for both frames */
+ zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
+ DTRC_DECOMPRESS_BYPASS);
+ zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
+ DTRC_DECOMPRESS_BYPASS);
+
+ /* Set up ARID register */
+ zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
+ DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
+}
+
+static void vou_hw_init(struct zx_vou_hw *vou)
+{
+ /* Set GL0 to main channel and GL1 to aux channel */
+ zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL0_SEL, 0);
+ zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL1_SEL,
+ OSD_CTRL0_GL1_SEL);
+
+ /* Release reset for all VOU modules */
+ zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
+
+ /* Select main clock for GL0 and aux clock for GL1 module */
+ zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL0_SEL, 0);
+ zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL1_SEL,
+ VOU_CLK_GL1_SEL);
+
+ /* Enable clock auto-gating for all VOU modules */
+ zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0);
+
+ /* Enable all VOU module clocks */
+ zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
+
+ /* Clear both OSD and TIMING_CTRL interrupt state */
+ zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
+ zx_writel(vou->timing + TIMING_INT_STATE, ~0);
+
+ /* Enable OSD and TIMING_CTRL interrrupts */
+ zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
+ zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
+
+ /* Select GPC as input to gl/vl scaler as a sane default setting */
+ zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
+
+ /*
+ * Needs to reset channel and layer logic per frame when frame starts
+ * to get VOU work properly.
+ */
+ zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
+
+ vou_dtrc_init(vou);
+}
+
+static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = data;
+ struct zx_vou_hw *vou;
+ struct resource *res;
+ int irq;
+ int ret;
+
+ vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
+ if (!vou)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
+ vou->osd = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vou->osd)) {
+ ret = PTR_ERR(vou->osd);
+ DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
+ return ret;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
+ vou->timing = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vou->timing)) {
+ ret = PTR_ERR(vou->timing);
+ DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
+ ret);
+ return ret;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
+ vou->dtrc = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vou->dtrc)) {
+ ret = PTR_ERR(vou->dtrc);
+ DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
+ return ret;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
+ vou->vouctl = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vou->vouctl)) {
+ ret = PTR_ERR(vou->vouctl);
+ DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
+ ret);
+ return ret;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
+ vou->otfppu = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vou->otfppu)) {
+ ret = PTR_ERR(vou->otfppu);
+ DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ vou->axi_clk = devm_clk_get(dev, "aclk");
+ if (IS_ERR(vou->axi_clk)) {
+ ret = PTR_ERR(vou->axi_clk);
+ DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
+ return ret;
+ }
+
+ vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
+ if (IS_ERR(vou->ppu_clk)) {
+ ret = PTR_ERR(vou->ppu_clk);
+ DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(vou->axi_clk);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
+ return ret;
+ }
+
+ clk_prepare_enable(vou->ppu_clk);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
+ goto disable_axi_clk;
+ }
+
+ vou->dev = dev;
+ dev_set_drvdata(dev, vou);
+
+ vou_hw_init(vou);
+
+ ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
+ goto disable_ppu_clk;
+ }
+
+ ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
+ ret);
+ goto disable_ppu_clk;
+ }
+
+ ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
+ ret);
+ goto disable_ppu_clk;
+ }
+
+ return 0;
+
+disable_ppu_clk:
+ clk_disable_unprepare(vou->ppu_clk);
+disable_axi_clk:
+ clk_disable_unprepare(vou->axi_clk);
+ return ret;
+}
+
+static void zx_crtc_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct zx_vou_hw *vou = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(vou->axi_clk);
+ clk_disable_unprepare(vou->ppu_clk);
+}
+
+static const struct component_ops zx_crtc_component_ops = {
+ .bind = zx_crtc_bind,
+ .unbind = zx_crtc_unbind,
+};
+
+static int zx_crtc_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &zx_crtc_component_ops);
+}
+
+static int zx_crtc_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &zx_crtc_component_ops);
+ return 0;
+}
+
+static const struct of_device_id zx_crtc_of_match[] = {
+ { .compatible = "zte,zx296718-dpc", },
+ { /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
+
+struct platform_driver zx_crtc_driver = {
+ .probe = zx_crtc_probe,
+ .remove = zx_crtc_remove,
+ .driver = {
+ .name = "zx-crtc",
+ .of_match_table = zx_crtc_of_match,
+ },
+};
diff --git a/drivers/gpu/drm/zte/zx_vou.h b/drivers/gpu/drm/zte/zx_vou.h
new file mode 100644
index 000000000000..349e06cd86f4
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_vou.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_VOU_H__
+#define __ZX_VOU_H__
+
+#define VOU_CRTC_MASK 0x3
+
+/* VOU output interfaces */
+enum vou_inf_id {
+ VOU_HDMI = 0,
+ VOU_RGB_LCD = 1,
+ VOU_TV_ENC = 2,
+ VOU_MIPI_DSI = 3,
+ VOU_LVDS = 4,
+ VOU_VGA = 5,
+};
+
+enum vou_inf_data_sel {
+ VOU_YUV444 = 0,
+ VOU_RGB_101010 = 1,
+ VOU_RGB_888 = 2,
+ VOU_RGB_666 = 3,
+};
+
+struct vou_inf {
+ enum vou_inf_id id;
+ enum vou_inf_data_sel data_sel;
+ u32 clocks_en_bits;
+ u32 clocks_sel_bits;
+};
+
+void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc);
+void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc);
+
+int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe);
+void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe);
+
+#endif /* __ZX_VOU_H__ */
diff --git a/drivers/gpu/drm/zte/zx_vou_regs.h b/drivers/gpu/drm/zte/zx_vou_regs.h
new file mode 100644
index 000000000000..f44e7a4ae441
--- /dev/null
+++ b/drivers/gpu/drm/zte/zx_vou_regs.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE 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.
+ *
+ */
+
+#ifndef __ZX_VOU_REGS_H__
+#define __ZX_VOU_REGS_H__
+
+/* Sub-module offset */
+#define MAIN_GL_OFFSET 0x130
+#define MAIN_CSC_OFFSET 0x580
+#define MAIN_HBSC_OFFSET 0x820
+#define MAIN_RSZ_OFFSET 0x600 /* OTFPPU sub-module */
+
+#define AUX_GL_OFFSET 0x200
+#define AUX_CSC_OFFSET 0x5d0
+#define AUX_HBSC_OFFSET 0x860
+#define AUX_RSZ_OFFSET 0x800
+
+/* OSD (GPC_GLOBAL) registers */
+#define OSD_INT_STA 0x04
+#define OSD_INT_CLRSTA 0x08
+#define OSD_INT_MSK 0x0c
+#define OSD_INT_AUX_UPT BIT(14)
+#define OSD_INT_MAIN_UPT BIT(13)
+#define OSD_INT_GL1_LBW BIT(10)
+#define OSD_INT_GL0_LBW BIT(9)
+#define OSD_INT_VL2_LBW BIT(8)
+#define OSD_INT_VL1_LBW BIT(7)
+#define OSD_INT_VL0_LBW BIT(6)
+#define OSD_INT_BUS_ERR BIT(3)
+#define OSD_INT_CFG_ERR BIT(2)
+#define OSD_INT_ERROR (\
+ OSD_INT_GL1_LBW | OSD_INT_GL0_LBW | \
+ OSD_INT_VL2_LBW | OSD_INT_VL1_LBW | OSD_INT_VL0_LBW | \
+ OSD_INT_BUS_ERR | OSD_INT_CFG_ERR \
+)
+#define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
+#define OSD_CTRL0 0x10
+#define OSD_CTRL0_GL0_EN BIT(7)
+#define OSD_CTRL0_GL0_SEL BIT(6)
+#define OSD_CTRL0_GL1_EN BIT(5)
+#define OSD_CTRL0_GL1_SEL BIT(4)
+#define OSD_RST_CLR 0x1c
+#define RST_PER_FRAME BIT(19)
+
+/* Main/Aux channel registers */
+#define OSD_MAIN_CHN 0x470
+#define OSD_AUX_CHN 0x4d0
+#define CHN_CTRL0 0x00
+#define CHN_ENABLE BIT(0)
+#define CHN_CTRL1 0x04
+#define CHN_SCREEN_W_SHIFT 18
+#define CHN_SCREEN_W_MASK (0x1fff << CHN_SCREEN_W_SHIFT)
+#define CHN_SCREEN_H_SHIFT 5
+#define CHN_SCREEN_H_MASK (0x1fff << CHN_SCREEN_H_SHIFT)
+#define CHN_UPDATE 0x08
+
+/* TIMING_CTRL registers */
+#define TIMING_TC_ENABLE 0x04
+#define AUX_TC_EN BIT(1)
+#define MAIN_TC_EN BIT(0)
+#define FIR_MAIN_ACTIVE 0x08
+#define FIR_AUX_ACTIVE 0x0c
+#define V_ACTIVE_SHIFT 16
+#define V_ACTIVE_MASK (0xffff << V_ACTIVE_SHIFT)
+#define H_ACTIVE_SHIFT 0
+#define H_ACTIVE_MASK (0xffff << H_ACTIVE_SHIFT)
+#define FIR_MAIN_H_TIMING 0x10
+#define FIR_MAIN_V_TIMING 0x14
+#define FIR_AUX_H_TIMING 0x18
+#define FIR_AUX_V_TIMING 0x1c
+#define SYNC_WIDE_SHIFT 22
+#define SYNC_WIDE_MASK (0x3ff << SYNC_WIDE_SHIFT)
+#define BACK_PORCH_SHIFT 11
+#define BACK_PORCH_MASK (0x7ff << BACK_PORCH_SHIFT)
+#define FRONT_PORCH_SHIFT 0
+#define FRONT_PORCH_MASK (0x7ff << FRONT_PORCH_SHIFT)
+#define TIMING_CTRL 0x20
+#define AUX_POL_SHIFT 3
+#define AUX_POL_MASK (0x7 << AUX_POL_SHIFT)
+#define MAIN_POL_SHIFT 0
+#define MAIN_POL_MASK (0x7 << MAIN_POL_SHIFT)
+#define POL_DE_SHIFT 2
+#define POL_VSYNC_SHIFT 1
+#define POL_HSYNC_SHIFT 0
+#define TIMING_INT_CTRL 0x24
+#define TIMING_INT_STATE 0x28
+#define TIMING_INT_AUX_FRAME BIT(3)
+#define TIMING_INT_MAIN_FRAME BIT(1)
+#define TIMING_INT_AUX_FRAME_SEL_VSW (0x2 << 10)
+#define TIMING_INT_MAIN_FRAME_SEL_VSW (0x2 << 6)
+#define TIMING_INT_ENABLE (\
+ TIMING_INT_MAIN_FRAME_SEL_VSW | TIMING_INT_AUX_FRAME_SEL_VSW | \
+ TIMING_INT_MAIN_FRAME | TIMING_INT_AUX_FRAME \
+)
+#define TIMING_MAIN_SHIFT 0x2c
+#define TIMING_AUX_SHIFT 0x30
+#define H_SHIFT_VAL 0x0048
+#define TIMING_MAIN_PI_SHIFT 0x68
+#define TIMING_AUX_PI_SHIFT 0x6c
+#define H_PI_SHIFT_VAL 0x000f
+
+#define V_ACTIVE(x) (((x) << V_ACTIVE_SHIFT) & V_ACTIVE_MASK)
+#define H_ACTIVE(x) (((x) << H_ACTIVE_SHIFT) & H_ACTIVE_MASK)
+
+#define SYNC_WIDE(x) (((x) << SYNC_WIDE_SHIFT) & SYNC_WIDE_MASK)
+#define BACK_PORCH(x) (((x) << BACK_PORCH_SHIFT) & BACK_PORCH_MASK)
+#define FRONT_PORCH(x) (((x) << FRONT_PORCH_SHIFT) & FRONT_PORCH_MASK)
+
+/* DTRC registers */
+#define DTRC_F0_CTRL 0x2c
+#define DTRC_F1_CTRL 0x5c
+#define DTRC_DECOMPRESS_BYPASS BIT(17)
+#define DTRC_DETILE_CTRL 0x68
+#define TILE2RASTESCAN_BYPASS_MODE BIT(30)
+#define DETILE_ARIDR_MODE_MASK (0x3 << 0)
+#define DETILE_ARID_ALL 0
+#define DETILE_ARID_IN_ARIDR 1
+#define DETILE_ARID_BYP_BUT_ARIDR 2
+#define DETILE_ARID_IN_ARIDR2 3
+#define DTRC_ARID 0x6c
+#define DTRC_ARID3_SHIFT 24
+#define DTRC_ARID3_MASK (0xff << DTRC_ARID3_SHIFT)
+#define DTRC_ARID2_SHIFT 16
+#define DTRC_ARID2_MASK (0xff << DTRC_ARID2_SHIFT)
+#define DTRC_ARID1_SHIFT 8
+#define DTRC_ARID1_MASK (0xff << DTRC_ARID1_SHIFT)
+#define DTRC_ARID0_SHIFT 0
+#define DTRC_ARID0_MASK (0xff << DTRC_ARID0_SHIFT)
+#define DTRC_DEC2DDR_ARID 0x70
+
+#define DTRC_ARID3(x) (((x) << DTRC_ARID3_SHIFT) & DTRC_ARID3_MASK)
+#define DTRC_ARID2(x) (((x) << DTRC_ARID2_SHIFT) & DTRC_ARID2_MASK)
+#define DTRC_ARID1(x) (((x) << DTRC_ARID1_SHIFT) & DTRC_ARID1_MASK)
+#define DTRC_ARID0(x) (((x) << DTRC_ARID0_SHIFT) & DTRC_ARID0_MASK)
+
+/* VOU_CTRL registers */
+#define VOU_INF_EN 0x00
+#define VOU_INF_CH_SEL 0x04
+#define VOU_INF_DATA_SEL 0x08
+#define VOU_SOFT_RST 0x14
+#define VOU_CLK_SEL 0x18
+#define VOU_CLK_GL1_SEL BIT(5)
+#define VOU_CLK_GL0_SEL BIT(4)
+#define VOU_CLK_REQEN 0x20
+#define VOU_CLK_EN 0x24
+
+/* OTFPPU_CTRL registers */
+#define OTFPPU_RSZ_DATA_SOURCE 0x04
+
+#endif /* __ZX_VOU_REGS_H__ */
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 5220510f39da..06dd4f85125f 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, NVIDIA Corporation.
+ * Copyright (c) 2012-2015, NVIDIA 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,
@@ -120,6 +120,7 @@ struct host1x {
struct host1x_syncpt *nop_sp;
+ struct mutex syncpt_mutex;
struct mutex chlist_mutex;
struct host1x_channel chlist;
unsigned long allocated_channels;
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index a91b7c4a6110..92c3df933303 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -1,7 +1,7 @@
/*
* Tegra host1x Job
*
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2015, NVIDIA 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,
@@ -539,9 +539,12 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
g->base = job->gather_addr_phys[i];
- for (j = i + 1; j < job->num_gathers; j++)
- if (job->gathers[j].bo == g->bo)
+ for (j = i + 1; j < job->num_gathers; j++) {
+ if (job->gathers[j].bo == g->bo) {
job->gathers[j].handled = true;
+ job->gathers[j].base = g->base;
+ }
+ }
err = do_relocs(job, g->bo);
if (err)
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 95589328ad52..25c11a85050b 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -1,7 +1,7 @@
/*
* Tegra host1x Syncpoints
*
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2015, NVIDIA 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,
@@ -61,22 +61,24 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
struct host1x_syncpt *sp = host->syncpt;
char *name;
+ mutex_lock(&host->syncpt_mutex);
+
for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++)
;
if (i >= host->info->nb_pts)
- return NULL;
+ goto unlock;
if (flags & HOST1X_SYNCPT_HAS_BASE) {
sp->base = host1x_syncpt_base_request(host);
if (!sp->base)
- return NULL;
+ goto unlock;
}
name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id,
dev ? dev_name(dev) : NULL);
if (!name)
- return NULL;
+ goto free_base;
sp->dev = dev;
sp->name = name;
@@ -86,7 +88,15 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
else
sp->client_managed = false;
+ mutex_unlock(&host->syncpt_mutex);
return sp;
+
+free_base:
+ host1x_syncpt_base_free(sp->base);
+ sp->base = NULL;
+unlock:
+ mutex_unlock(&host->syncpt_mutex);
+ return NULL;
}
u32 host1x_syncpt_id(struct host1x_syncpt *sp)
@@ -378,6 +388,7 @@ int host1x_syncpt_init(struct host1x *host)
for (i = 0; i < host->info->nb_bases; i++)
bases[i].id = i;
+ mutex_init(&host->syncpt_mutex);
host->syncpt = syncpt;
host->bases = bases;
@@ -405,12 +416,16 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
if (!sp)
return;
+ mutex_lock(&sp->host->syncpt_mutex);
+
host1x_syncpt_base_free(sp->base);
kfree(sp->name);
sp->base = NULL;
sp->dev = NULL;
sp->name = NULL;
sp->client_managed = false;
+
+ mutex_unlock(&sp->host->syncpt_mutex);
}
EXPORT_SYMBOL(host1x_syncpt_free);
diff --git a/drivers/gpu/ipu-v3/Kconfig b/drivers/gpu/ipu-v3/Kconfig
index aefdff95356d..08766c6e7856 100644
--- a/drivers/gpu/ipu-v3/Kconfig
+++ b/drivers/gpu/ipu-v3/Kconfig
@@ -1,7 +1,6 @@
config IMX_IPUV3_CORE
tristate "IPUv3 core support"
depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM
- depends on RESET_CONTROLLER
select GENERIC_IRQ_CHIP
help
Choose this if you have a i.MX5/6 system and want to use the Image
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index b9539f7c5e9a..97218af4fe75 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -88,6 +88,8 @@ enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
case DRM_FORMAT_YVU420:
case DRM_FORMAT_YUV422:
case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
@@ -1284,8 +1286,11 @@ static int ipu_irq_init(struct ipu_soc *ipu)
return ret;
}
- for (i = 0; i < IPU_NUM_IRQS; i += 32)
+ /* Mask and clear all interrupts */
+ for (i = 0; i < IPU_NUM_IRQS; i += 32) {
ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
+ ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
+ }
for (i = 0; i < IPU_NUM_IRQS; i += 32) {
gc = irq_get_domain_generic_chip(ipu->domain, i);
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index fcb7dc86167b..4b2b67113d92 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -417,42 +417,6 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
}
EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
-void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
- u32 pixel_format, int stride, int height)
-{
- int fourcc, u_offset, v_offset;
- int uv_stride = 0;
-
- fourcc = v4l2_pix_fmt_to_drm_fourcc(pixel_format);
- switch (fourcc) {
- case DRM_FORMAT_YUV420:
- uv_stride = stride / 2;
- u_offset = stride * height;
- v_offset = u_offset + (uv_stride * height / 2);
- break;
- case DRM_FORMAT_YVU420:
- uv_stride = stride / 2;
- v_offset = stride * height;
- u_offset = v_offset + (uv_stride * height / 2);
- break;
- case DRM_FORMAT_YUV422:
- uv_stride = stride / 2;
- u_offset = stride * height;
- v_offset = u_offset + (uv_stride * height);
- break;
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV16:
- uv_stride = stride;
- u_offset = stride * height;
- v_offset = 0;
- break;
- default:
- return;
- }
- ipu_cpmem_set_yuv_planar_full(ch, uv_stride, u_offset, v_offset);
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
-
static const struct ipu_rgb def_xrgb_32 = {
.red = { .offset = 16, .length = 8, },
.green = { .offset = 8, .length = 8, },
@@ -590,6 +554,13 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
/* burst size */
ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
break;
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
+ /* pix format */
+ ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
+ /* burst size */
+ ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
+ break;
case DRM_FORMAT_NV12:
/* pix format */
ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c
index d6e5ded24418..63c7292f427a 100644
--- a/drivers/gpu/ipu-v3/ipu-csi.c
+++ b/drivers/gpu/ipu-v3/ipu-csi.c
@@ -529,6 +529,22 @@ void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
}
EXPORT_SYMBOL_GPL(ipu_csi_set_window);
+void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&csi->lock, flags);
+
+ reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
+ reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
+ reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
+ (vert ? CSI_VERT_DOWNSIZE_EN : 0);
+ ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
+
+ spin_unlock_irqrestore(&csi->lock, flags);
+}
+
void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
u32 r_value, u32 g_value, u32 b_value,
u32 pix_clk)
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index a8d87ddd8a17..d2f1bd9d3deb 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -535,7 +535,7 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
return -EINVAL;
}
- dev_warn(di->ipu->dev, "videomode adapted for IPU restrictions\n");
+ dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
return 0;
}
EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 1887f199ccb7..0f5b2dd24507 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -31,6 +31,10 @@
#define pr_fmt(fmt) "vgaarb: " fmt
+#define vgaarb_dbg(dev, fmt, arg...) dev_dbg(dev, "vgaarb: " fmt, ##arg)
+#define vgaarb_info(dev, fmt, arg...) dev_info(dev, "vgaarb: " fmt, ##arg)
+#define vgaarb_err(dev, fmt, arg...) dev_err(dev, "vgaarb: " fmt, ##arg)
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -188,6 +192,7 @@ static void vga_check_first_use(void)
static struct vga_device *__vga_tryget(struct vga_device *vgadev,
unsigned int rsrc)
{
+ struct device *dev = &vgadev->pdev->dev;
unsigned int wants, legacy_wants, match;
struct vga_device *conflict;
unsigned int pci_bits;
@@ -203,8 +208,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
(vgadev->decodes & VGA_RSRC_LEGACY_MEM))
rsrc |= VGA_RSRC_LEGACY_MEM;
- pr_debug("%s: %d\n", __func__, rsrc);
- pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
+ vgaarb_dbg(dev, "%s: %d\n", __func__, rsrc);
+ vgaarb_dbg(dev, "%s: owns: %d\n", __func__, vgadev->owns);
/* Check what resources we need to acquire */
wants = rsrc & ~vgadev->owns;
@@ -336,9 +341,10 @@ lock_them:
static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
{
+ struct device *dev = &vgadev->pdev->dev;
unsigned int old_locks = vgadev->locks;
- pr_debug("%s\n", __func__);
+ vgaarb_dbg(dev, "%s\n", __func__);
/* Update our counters, and account for equivalent legacy resources
* if we decode them
@@ -611,7 +617,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
/* Allocate structure */
vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
if (vgadev == NULL) {
- pr_err("failed to allocate pci device\n");
+ vgaarb_err(&pdev->dev, "failed to allocate VGA arbiter data\n");
/*
* What to do on allocation failure ? For now, let's just do
* nothing, I'm not sure there is anything saner to be done.
@@ -663,7 +669,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
*/
if (vga_default == NULL &&
((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
- pr_info("setting as boot device: PCI:%s\n", pci_name(pdev));
+ vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
vga_set_default_device(pdev);
}
@@ -672,8 +678,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
/* Add to the list */
list_add(&vgadev->list, &vga_list);
vga_count++;
- pr_info("device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
- pci_name(pdev),
+ vgaarb_info(&pdev->dev, "VGA device added: decodes=%s,owns=%s,locks=%s\n",
vga_iostate_to_str(vgadev->decodes),
vga_iostate_to_str(vgadev->owns),
vga_iostate_to_str(vgadev->locks));
@@ -725,6 +730,7 @@ bail:
static inline void vga_update_device_decodes(struct vga_device *vgadev,
int new_decodes)
{
+ struct device *dev = &vgadev->pdev->dev;
int old_decodes, decodes_removed, decodes_unlocked;
old_decodes = vgadev->decodes;
@@ -732,8 +738,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
decodes_unlocked = vgadev->locks & decodes_removed;
vgadev->decodes = new_decodes;
- pr_info("device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
- pci_name(vgadev->pdev),
+ vgaarb_info(dev, "changed VGA decodes: olddecodes=%s,decodes=%s:owns=%s\n",
vga_iostate_to_str(old_decodes),
vga_iostate_to_str(vgadev->decodes),
vga_iostate_to_str(vgadev->owns));
@@ -754,7 +759,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
new_decodes & VGA_RSRC_LEGACY_MASK)
vga_decode_count++;
- pr_debug("decoding count now is: %d\n", vga_decode_count);
+ vgaarb_dbg(dev, "decoding count now is: %d\n", vga_decode_count);
}
static void __vga_set_legacy_decoding(struct pci_dev *pdev,
@@ -1022,21 +1027,16 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
unsigned int io_state;
- char *kbuf, *curr_pos;
+ char kbuf[64], *curr_pos;
size_t remaining = count;
int ret_val;
int i;
-
- kbuf = kmalloc(count + 1, GFP_KERNEL);
- if (!kbuf)
- return -ENOMEM;
-
- if (copy_from_user(kbuf, buf, count)) {
- kfree(kbuf);
+ if (count >= sizeof(kbuf))
+ return -EINVAL;
+ if (copy_from_user(kbuf, buf, count))
return -EFAULT;
- }
curr_pos = kbuf;
kbuf[count] = '\0'; /* Just to make sure... */
@@ -1189,24 +1189,25 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
ret_val = -EPROTO;
goto done;
}
- pr_debug("%s ==> %x:%x:%x.%x\n", curr_pos,
- domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
- pr_debug("pdev %p\n", pdev);
if (!pdev) {
- pr_err("invalid PCI address %x:%x:%x\n",
- domain, bus, devfn);
+ pr_debug("invalid PCI address %04x:%02x:%02x.%x\n",
+ domain, bus, PCI_SLOT(devfn),
+ PCI_FUNC(devfn));
ret_val = -ENODEV;
goto done;
}
+
+ pr_debug("%s ==> %04x:%02x:%02x.%x pdev %p\n", curr_pos,
+ domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ pdev);
}
vgadev = vgadev_find(pdev);
pr_debug("vgadev %p\n", vgadev);
if (vgadev == NULL) {
if (pdev) {
- pr_err("this pci device is not a vga device\n");
+ vgaarb_dbg(&pdev->dev, "not a VGA device\n");
pci_dev_put(pdev);
}
@@ -1226,7 +1227,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
}
}
if (i == MAX_USER_CARDS) {
- pr_err("maximum user cards (%d) number reached!\n",
+ vgaarb_dbg(&pdev->dev, "maximum user cards (%d) number reached, ignoring this one!\n",
MAX_USER_CARDS);
pci_dev_put(pdev);
/* XXX: which value to return? */
@@ -1259,11 +1260,9 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
goto done;
}
/* If we got here, the message written is not part of the protocol! */
- kfree(kbuf);
return -EPROTO;
done:
- kfree(kbuf);
return ret_val;
}
@@ -1317,8 +1316,8 @@ static int vga_arb_release(struct inode *inode, struct file *file)
uc = &priv->cards[i];
if (uc->pdev == NULL)
continue;
- pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
- uc->io_cnt, uc->mem_cnt);
+ vgaarb_dbg(&uc->pdev->dev, "uc->io_cnt == %d, uc->mem_cnt == %d\n",
+ uc->io_cnt, uc->mem_cnt);
while (uc->io_cnt--)
vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
while (uc->mem_cnt--)
@@ -1371,7 +1370,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
struct pci_dev *pdev = to_pci_dev(dev);
bool notify = false;
- pr_debug("%s\n", __func__);
+ vgaarb_dbg(dev, "%s\n", __func__);
/* For now we're only intereted in devices added and removed. I didn't
* test this thing here, so someone needs to double check for the
@@ -1423,9 +1422,8 @@ static int __init vga_arb_device_init(void)
PCI_ANY_ID, pdev)) != NULL)
vga_arbiter_add_pci_device(pdev);
- pr_info("loaded\n");
-
list_for_each_entry(vgadev, &vga_list, list) {
+ struct device *dev = &vgadev->pdev->dev;
#if defined(CONFIG_X86) || defined(CONFIG_IA64)
/*
* Override vga_arbiter_add_pci_device()'s I/O based detection
@@ -1458,21 +1456,19 @@ static int __init vga_arb_device_init(void)
continue;
if (!vga_default_device())
- pr_info("setting as boot device: PCI:%s\n",
- pci_name(vgadev->pdev));
+ vgaarb_info(dev, "setting as boot device\n");
else if (vgadev->pdev != vga_default_device())
- pr_info("overriding boot device: PCI:%s\n",
- pci_name(vgadev->pdev));
+ vgaarb_info(dev, "overriding boot device\n");
vga_set_default_device(vgadev->pdev);
}
#endif
if (vgadev->bridge_has_one_vga)
- pr_info("bridge control possible %s\n",
- pci_name(vgadev->pdev));
+ vgaarb_info(dev, "bridge control possible\n");
else
- pr_info("no bridge control possible %s\n",
- pci_name(vgadev->pdev));
+ vgaarb_info(dev, "no bridge control possible\n");
}
+
+ pr_info("loaded\n");
return rc;
}
subsys_initcall(vga_arb_device_init);
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index 6031cd146556..7ef819680acd 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -960,15 +960,6 @@ static int ssip_pn_stop(struct net_device *dev)
return 0;
}
-static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu > SSIP_MAX_MTU || new_mtu < PHONET_MIN_MTU)
- return -EINVAL;
- dev->mtu = new_mtu;
-
- return 0;
-}
-
static void ssip_xmit_work(struct work_struct *work)
{
struct ssi_protocol *ssi =
@@ -1060,7 +1051,6 @@ static const struct net_device_ops ssip_pn_ops = {
.ndo_open = ssip_pn_open,
.ndo_stop = ssip_pn_stop,
.ndo_start_xmit = ssip_pn_xmit,
- .ndo_change_mtu = ssip_pn_set_mtu,
};
static void ssip_pn_setup(struct net_device *dev)
@@ -1136,6 +1126,10 @@ static int ssi_protocol_probe(struct device *dev)
goto out1;
}
+ /* MTU range: 6 - 65535 */
+ ssi->netdev->min_mtu = PHONET_MIN_MTU;
+ ssi->netdev->max_mtu = SSIP_MAX_MTU;
+
SET_NETDEV_DEV(ssi->netdev, dev);
netif_carrier_off(ssi->netdev);
err = register_netdev(ssi->netdev);
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 05352f490d60..f90ea221f7f2 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -211,7 +211,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
sense_rq->cmd[4] = cmd_len;
sense_rq->cmd_type = REQ_TYPE_ATA_SENSE;
- sense_rq->cmd_flags |= REQ_PREEMPT;
+ sense_rq->rq_flags |= RQF_PREEMPT;
if (drive->media == ide_tape)
sense_rq->cmd[13] = REQ_IDETAPE_PC1;
@@ -295,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive)
wait = ATAPI_WAIT_PC;
break;
default:
- if (!(rq->cmd_flags & REQ_QUIET))
+ if (!(rq->rq_flags & RQF_QUIET))
printk(KERN_INFO PFX "cmd 0x%x timed out\n",
rq->cmd[0]);
wait = 0;
@@ -375,7 +375,7 @@ int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len,
}
if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC)
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
return 1;
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index bf9a2ad296ed..9cbd217bc0c9 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -98,7 +98,7 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq)
struct request_sense *sense = &drive->sense_data;
int log = 0;
- if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
+ if (!sense || !rq || (rq->rq_flags & RQF_QUIET))
return 0;
ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
@@ -291,7 +291,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
* (probably while trying to recover from a former error).
* Just give up.
*/
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
return 2;
}
@@ -311,7 +311,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
cdrom_saw_media_change(drive);
if (rq->cmd_type == REQ_TYPE_FS &&
- !(rq->cmd_flags & REQ_QUIET))
+ !(rq->rq_flags & RQF_QUIET))
printk(KERN_ERR PFX "%s: tray open\n",
drive->name);
}
@@ -346,7 +346,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
* No point in retrying after an illegal request or data
* protect error.
*/
- if (!(rq->cmd_flags & REQ_QUIET))
+ if (!(rq->rq_flags & RQF_QUIET))
ide_dump_status(drive, "command error", stat);
do_end_request = 1;
break;
@@ -355,14 +355,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
* No point in re-trying a zillion times on a bad sector.
* If we got here the error is not correctable.
*/
- if (!(rq->cmd_flags & REQ_QUIET))
+ if (!(rq->rq_flags & RQF_QUIET))
ide_dump_status(drive, "media error "
"(bad sector)", stat);
do_end_request = 1;
break;
case BLANK_CHECK:
/* disk appears blank? */
- if (!(rq->cmd_flags & REQ_QUIET))
+ if (!(rq->rq_flags & RQF_QUIET))
ide_dump_status(drive, "media error (blank)",
stat);
do_end_request = 1;
@@ -380,7 +380,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
}
if (rq->cmd_type != REQ_TYPE_FS) {
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
do_end_request = 1;
}
@@ -422,19 +422,19 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
int write, void *buffer, unsigned *bufflen,
struct request_sense *sense, int timeout,
- unsigned int cmd_flags)
+ req_flags_t rq_flags)
{
struct cdrom_info *info = drive->driver_data;
struct request_sense local_sense;
int retries = 10;
- unsigned int flags = 0;
+ req_flags_t flags = 0;
if (!sense)
sense = &local_sense;
ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, "
- "cmd_flags: 0x%x",
- cmd[0], write, timeout, cmd_flags);
+ "rq_flags: 0x%x",
+ cmd[0], write, timeout, rq_flags);
/* start of retry loop */
do {
@@ -446,7 +446,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
memcpy(rq->cmd, cmd, BLK_MAX_CDB);
rq->cmd_type = REQ_TYPE_ATA_PC;
rq->sense = sense;
- rq->cmd_flags |= cmd_flags;
+ rq->rq_flags |= rq_flags;
rq->timeout = timeout;
if (buffer) {
error = blk_rq_map_kern(drive->queue, rq, buffer,
@@ -462,14 +462,14 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
if (buffer)
*bufflen = rq->resid_len;
- flags = rq->cmd_flags;
+ flags = rq->rq_flags;
blk_put_request(rq);
/*
* FIXME: we should probably abort/retry or something in case of
* failure.
*/
- if (flags & REQ_FAILED) {
+ if (flags & RQF_FAILED) {
/*
* The request failed. Retry if it was due to a unit
* attention status (usually means media was changed).
@@ -494,10 +494,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
}
/* end of retry loop */
- } while ((flags & REQ_FAILED) && retries >= 0);
+ } while ((flags & RQF_FAILED) && retries >= 0);
/* return an error if the command failed */
- return (flags & REQ_FAILED) ? -EIO : 0;
+ return (flags & RQF_FAILED) ? -EIO : 0;
}
/*
@@ -589,7 +589,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
"(%u bytes)\n", drive->name, __func__,
cmd->nleft);
if (!write)
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
uptodate = 0;
}
} else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
@@ -607,7 +607,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
}
if (!uptodate)
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
}
goto out_end;
}
@@ -745,9 +745,9 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
rq->cmd[0], rq->cmd_type);
if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
- rq->cmd_flags |= REQ_QUIET;
+ rq->rq_flags |= RQF_QUIET;
else
- rq->cmd_flags &= ~REQ_FAILED;
+ rq->rq_flags &= ~RQF_FAILED;
drive->dma = 0;
@@ -867,7 +867,7 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
*/
cmd[7] = cdi->sanyo_slot % 3;
- return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, RQF_QUIET);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -890,7 +890,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
cmd[0] = GPCMD_READ_CDVD_CAPACITY;
stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
- REQ_QUIET);
+ RQF_QUIET);
if (stat)
return stat;
@@ -943,7 +943,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
if (msf_flag)
cmd[1] = 2;
- return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
+ return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, RQF_QUIET);
}
/* Try to read the entire TOC for the disk into our internal buffer. */
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 1efc936f5b66..eea60c986c4f 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -101,7 +101,7 @@ void ide_cd_log_error(const char *, struct request *, struct request_sense *);
/* ide-cd.c functions used by ide-cd_ioctl.c */
int ide_cd_queue_pc(ide_drive_t *, const unsigned char *, int, void *,
- unsigned *, struct request_sense *, int, unsigned int);
+ unsigned *, struct request_sense *, int, req_flags_t);
int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
void ide_cdrom_update_speed(ide_drive_t *, u8 *);
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 5887a7a09e37..f085e3a2e1d6 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -305,7 +305,7 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi)
rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_DRV_PRIV;
- rq->cmd_flags = REQ_QUIET;
+ rq->rq_flags = RQF_QUIET;
ret = blk_execute_rq(drive->queue, cd->disk, rq, 0);
blk_put_request(rq);
/*
@@ -449,7 +449,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi,
struct packet_command *cgc)
{
ide_drive_t *drive = cdi->handle;
- unsigned int flags = 0;
+ req_flags_t flags = 0;
unsigned len = cgc->buflen;
if (cgc->timeout <= 0)
@@ -463,7 +463,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi,
memset(cgc->sense, 0, sizeof(struct request_sense));
if (cgc->quiet)
- flags |= REQ_QUIET;
+ flags |= RQF_QUIET;
cgc->stat = ide_cd_queue_pc(drive, cgc->cmd,
cgc->data_direction == CGC_DATA_WRITE,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 669ea1e45795..6360bbd37efe 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -307,7 +307,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
- BUG_ON(!(rq->cmd_flags & REQ_STARTED));
+ BUG_ON(!(rq->rq_flags & RQF_STARTED));
#ifdef DEBUG
printk("%s: start_request: current=0x%08lx\n",
@@ -316,7 +316,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
goto kill_rq;
}
@@ -539,7 +539,7 @@ repeat:
*/
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
ata_pm_request(rq) == 0 &&
- (rq->cmd_flags & REQ_PREEMPT) == 0) {
+ (rq->rq_flags & RQF_PREEMPT) == 0) {
/* there should be no pending command at this point */
ide_unlock_port(hwif);
goto plug_device;
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index e34af488693a..a015acdffb39 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -53,7 +53,7 @@ static int ide_pm_execute_rq(struct request *rq)
spin_lock_irq(q->queue_lock);
if (unlikely(blk_queue_dying(q))) {
- rq->cmd_flags |= REQ_QUIET;
+ rq->rq_flags |= RQF_QUIET;
rq->errors = -ENXIO;
__blk_end_request_all(rq, rq->errors);
spin_unlock_irq(q->queue_lock);
@@ -90,7 +90,7 @@ int generic_ide_resume(struct device *dev)
memset(&rqpm, 0, sizeof(rqpm));
rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
rq->cmd_type = REQ_TYPE_ATA_PM_RESUME;
- rq->cmd_flags |= REQ_PREEMPT;
+ rq->rq_flags |= RQF_PREEMPT;
rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_RESUME;
rqpm.pm_state = PM_EVENT_ON;
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig
index 4732dfc15447..55bcf803841e 100644
--- a/drivers/idle/Kconfig
+++ b/drivers/idle/Kconfig
@@ -8,20 +8,3 @@ config INTEL_IDLE
native Intel hardware idle features. The acpi_idle driver
can be configured at the same time, in order to handle
processors intel_idle does not support.
-
-menu "Memory power savings"
-depends on X86_64
-
-config I7300_IDLE_IOAT_CHANNEL
- bool
-
-config I7300_IDLE
- tristate "Intel chipset idle memory power saving driver"
- select I7300_IDLE_IOAT_CHANNEL
- help
- Enable memory power savings when idle with certain Intel server
- chipsets. The chipset must have I/O AT support, such as the
- Intel 7300. The power savings depends on the type and quantity of
- DRAM devices.
-
-endmenu
diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile
index 23d295cf10f2..0007111d73e9 100644
--- a/drivers/idle/Makefile
+++ b/drivers/idle/Makefile
@@ -1,3 +1,2 @@
-obj-$(CONFIG_I7300_IDLE) += i7300_idle.o
obj-$(CONFIG_INTEL_IDLE) += intel_idle.o
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
deleted file mode 100644
index ffeebc7e9f1c..000000000000
--- a/drivers/idle/i7300_idle.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * (C) Copyright 2008 Intel Corporation
- * Authors:
- * Andy Henroid <andrew.d.henroid@intel.com>
- * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- */
-
-/*
- * Save DIMM power on Intel 7300-based platforms when all CPUs/cores
- * are idle, using the DIMM thermal throttling capability.
- *
- * This driver depends on the Intel integrated DMA controller (I/O AT).
- * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled,
- * this driver should work cooperatively.
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/gfp.h>
-#include <linux/sched.h>
-#include <linux/notifier.h>
-#include <linux/cpumask.h>
-#include <linux/ktime.h>
-#include <linux/delay.h>
-#include <linux/debugfs.h>
-#include <linux/stop_machine.h>
-#include <linux/i7300_idle.h>
-
-#include <asm/idle.h>
-
-#include "../dma/ioat/hw.h"
-#include "../dma/ioat/registers.h"
-
-#define I7300_IDLE_DRIVER_VERSION "1.55"
-#define I7300_PRINT "i7300_idle:"
-
-#define MAX_STOP_RETRIES 10
-
-static int debug;
-module_param_named(debug, debug, uint, 0644);
-MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
-
-static int forceload;
-module_param_named(forceload, forceload, uint, 0644);
-MODULE_PARM_DESC(debug, "Enable driver testing on unvalidated i5000");
-
-#define dprintk(fmt, arg...) \
- do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0)
-
-/*
- * Value to set THRTLOW to when initiating throttling
- * 0 = No throttling
- * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
- * 2 = Throttle when > 8 activations
- * 168 = Throttle when > 672 activations (Minimum throttling)
- */
-#define MAX_THROTTLE_LOW_LIMIT 168
-static uint throttle_low_limit = 1;
-module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
-MODULE_PARM_DESC(throttle_low_limit,
- "Value for THRTLOWLM activation field "
- "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
-
-/*
- * simple invocation and duration statistics
- */
-static unsigned long total_starts;
-static unsigned long total_us;
-
-#ifdef DEBUG
-static unsigned long past_skip;
-#endif
-
-static struct pci_dev *fbd_dev;
-
-static raw_spinlock_t i7300_idle_lock;
-static int i7300_idle_active;
-
-static u8 i7300_idle_thrtctl_saved;
-static u8 i7300_idle_thrtlow_saved;
-static u32 i7300_idle_mc_saved;
-
-static cpumask_var_t idle_cpumask;
-static ktime_t start_ktime;
-static unsigned long avg_idle_us;
-
-static struct dentry *debugfs_dir;
-
-/* Begin: I/O AT Helper routines */
-
-#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan)
-/* Snoop control (disable snoops when coherency is not important) */
-#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1)
-#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2)
-
-static struct pci_dev *ioat_dev;
-static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */
-static unsigned long ioat_desc_phys;
-static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */
-static u8 *ioat_chanbase;
-
-/* Start I/O AT memory copy */
-static int i7300_idle_ioat_start(void)
-{
- u32 err;
- /* Clear error (due to circular descriptor pointer) */
- err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET);
- if (err)
- writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET);
-
- writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
- return 0;
-}
-
-/* Stop I/O AT memory copy */
-static void i7300_idle_ioat_stop(void)
-{
- int i;
- u64 sts;
-
- for (i = 0; i < MAX_STOP_RETRIES; i++) {
- writeb(IOAT_CHANCMD_RESET,
- ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
- udelay(10);
-
- sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
- IOAT_CHANSTS_STATUS;
-
- if (sts != IOAT_CHANSTS_ACTIVE)
- break;
-
- }
-
- if (i == MAX_STOP_RETRIES) {
- dprintk("failed to stop I/O AT after %d retries\n",
- MAX_STOP_RETRIES);
- }
-}
-
-/* Test I/O AT by copying 1024 byte from 2k to 1k */
-static int __init i7300_idle_ioat_selftest(u8 *ctl,
- struct ioat_dma_descriptor *desc, unsigned long desc_phys)
-{
- u64 chan_sts;
-
- memset(desc, 0, 2048);
- memset((u8 *) desc + 2048, 0xab, 1024);
-
- desc[0].size = 1024;
- desc[0].ctl = 0;
- desc[0].src_addr = desc_phys + 2048;
- desc[0].dst_addr = desc_phys + 1024;
- desc[0].next = 0;
-
- writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
- writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
- udelay(1000);
-
- chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
- IOAT_CHANSTS_STATUS;
-
- if (chan_sts != IOAT_CHANSTS_DONE) {
- /* Not complete, reset the channel */
- writeb(IOAT_CHANCMD_RESET,
- ioat_chanbase + IOAT1_CHANCMD_OFFSET);
- return -1;
- }
-
- if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab ||
- *(u32 *) ((u8 *) desc + 2044) != 0xabababab) {
- dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n",
- *(u32 *) ((u8 *) desc + 2048),
- *(u32 *) ((u8 *) desc + 1024),
- *(u32 *) ((u8 *) desc + 3072));
- return -1;
- }
- return 0;
-}
-
-static struct device dummy_dma_dev = {
- .init_name = "fallback device",
- .coherent_dma_mask = DMA_BIT_MASK(64),
- .dma_mask = &dummy_dma_dev.coherent_dma_mask,
-};
-
-/* Setup and initialize I/O AT */
-/* This driver needs I/O AT as the throttling takes effect only when there is
- * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs
- * go idle and memory is throttled.
- */
-static int __init i7300_idle_ioat_init(void)
-{
- u8 ver, chan_count, ioat_chan;
- u16 chan_ctl;
-
- ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0),
- pci_resource_len(ioat_dev, 0));
-
- if (!ioat_iomap) {
- printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n");
- goto err_ret;
- }
-
- ver = readb(ioat_iomap + IOAT_VER_OFFSET);
- if (ver != IOAT_VER_1_2) {
- printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n",
- ver >> 4, ver & 0xf);
- goto err_unmap;
- }
-
- chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET);
- if (!chan_count) {
- printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels "
- "(%u)\n",
- chan_count);
- goto err_unmap;
- }
-
- ioat_chan = chan_count - 1;
- ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan);
-
- chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET);
- if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) {
- printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan);
- goto err_unmap;
- }
-
- writew(IOAT_CHANCTRL_CHANNEL_IN_USE,
- ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-
- ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent(
- &dummy_dma_dev, 4096,
- (dma_addr_t *)&ioat_desc_phys, GFP_KERNEL);
- if (!ioat_desc) {
- printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n");
- goto err_mark_unused;
- }
-
- writel(ioat_desc_phys & 0xffffffffUL,
- ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW);
- writel(ioat_desc_phys >> 32,
- ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH);
-
- if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) {
- printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n");
- goto err_free;
- }
-
- /* Setup circular I/O AT descriptor chain */
- ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL;
- ioat_desc[0].src_addr = ioat_desc_phys + 2048;
- ioat_desc[0].dst_addr = ioat_desc_phys + 3072;
- ioat_desc[0].size = 128;
- ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor);
-
- ioat_desc[1].ctl = ioat_desc[0].ctl;
- ioat_desc[1].src_addr = ioat_desc[0].src_addr;
- ioat_desc[1].dst_addr = ioat_desc[0].dst_addr;
- ioat_desc[1].size = ioat_desc[0].size;
- ioat_desc[1].next = ioat_desc_phys;
-
- return 0;
-
-err_free:
- dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
-err_mark_unused:
- writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-err_unmap:
- iounmap(ioat_iomap);
-err_ret:
- return -ENODEV;
-}
-
-/* Cleanup I/O AT */
-static void __exit i7300_idle_ioat_exit(void)
-{
- int i;
- u64 chan_sts;
-
- i7300_idle_ioat_stop();
-
- /* Wait for a while for the channel to halt before releasing */
- for (i = 0; i < MAX_STOP_RETRIES; i++) {
- writeb(IOAT_CHANCMD_RESET,
- ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
- chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
- IOAT_CHANSTS_STATUS;
-
- if (chan_sts != IOAT_CHANSTS_ACTIVE) {
- writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
- break;
- }
- udelay(1000);
- }
-
- chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
- IOAT_CHANSTS_STATUS;
-
- /*
- * We tried to reset multiple times. If IO A/T channel is still active
- * flag an error and return without cleanup. Memory leak is better
- * than random corruption in that extreme error situation.
- */
- if (chan_sts == IOAT_CHANSTS_ACTIVE) {
- printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels."
- " Not freeing resources\n");
- return;
- }
-
- dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
- iounmap(ioat_iomap);
-}
-
-/* End: I/O AT Helper routines */
-
-#define DIMM_THRTLOW 0x64
-#define DIMM_THRTCTL 0x67
-#define DIMM_THRTCTL_THRMHUNT (1UL << 0)
-#define DIMM_MC 0x40
-#define DIMM_GTW_MODE (1UL << 17)
-#define DIMM_GBLACT 0x60
-
-/*
- * Keep track of an exponential-decaying average of recent idle durations.
- * The latest duration gets DURATION_WEIGHT_PCT percentage weight
- * in this average, with the old average getting the remaining weight.
- *
- * High weights emphasize recent history, low weights include long history.
- */
-#define DURATION_WEIGHT_PCT 55
-
-/*
- * When the decaying average of recent durations or the predicted duration
- * of the next timer interrupt is shorter than duration_threshold, the
- * driver will decline to throttle.
- */
-#define DURATION_THRESHOLD_US 100
-
-
-/* Store DIMM thermal throttle configuration */
-static int i7300_idle_thrt_save(void)
-{
- u32 new_mc_val;
- u8 gblactlm;
-
- pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved);
- pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved);
- pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved);
- /*
- * Make sure we have Global Throttling Window Mode set to have a
- * "short" window. This (mostly) works around an issue where
- * throttling persists until the end of the global throttling window
- * size. On the tested system, this was resulting in a maximum of
- * 64 ms to exit throttling (average 32 ms). The actual numbers
- * depends on system frequencies. Setting the short window reduces
- * this by a factor of 4096.
- *
- * We will only do this only if the system is set for
- * unlimited-activations while in open-loop throttling (i.e., when
- * Global Activation Throttle Limit is zero).
- */
- pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm);
- dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n",
- i7300_idle_thrtctl_saved,
- i7300_idle_thrtlow_saved);
- dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n",
- i7300_idle_mc_saved,
- gblactlm);
- if (gblactlm == 0) {
- new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE;
- pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val);
- return 0;
- } else {
- dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n");
- return -ENODEV;
- }
-}
-
-/* Restore DIMM thermal throttle configuration */
-static void i7300_idle_thrt_restore(void)
-{
- pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved);
- pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
- pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
-}
-
-/* Enable DIMM thermal throttling */
-static void i7300_idle_start(void)
-{
- u8 new_ctl;
- u8 limit;
-
- new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
- pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-
- limit = throttle_low_limit;
- if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
- limit = MAX_THROTTLE_LOW_LIMIT;
-
- pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
-
- new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT;
- pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-}
-
-/* Disable DIMM thermal throttling */
-static void i7300_idle_stop(void)
-{
- u8 new_ctl;
- u8 got_ctl;
-
- new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
- pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-
- pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
- pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
- pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl);
- WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved);
-}
-
-
-/*
- * i7300_avg_duration_check()
- * return 0 if the decaying average of recent idle durations is
- * more than DURATION_THRESHOLD_US
- */
-static int i7300_avg_duration_check(void)
-{
- if (avg_idle_us >= DURATION_THRESHOLD_US)
- return 0;
-
-#ifdef DEBUG
- past_skip++;
-#endif
- return 1;
-}
-
-/* Idle notifier to look at idle CPUs */
-static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
- void *data)
-{
- unsigned long flags;
- ktime_t now_ktime;
- static ktime_t idle_begin_time;
- static int time_init = 1;
-
- if (!throttle_low_limit)
- return 0;
-
- if (unlikely(time_init)) {
- time_init = 0;
- idle_begin_time = ktime_get();
- }
-
- raw_spin_lock_irqsave(&i7300_idle_lock, flags);
- if (val == IDLE_START) {
-
- cpumask_set_cpu(smp_processor_id(), idle_cpumask);
-
- if (cpumask_weight(idle_cpumask) != num_online_cpus())
- goto end;
-
- now_ktime = ktime_get();
- idle_begin_time = now_ktime;
-
- if (i7300_avg_duration_check())
- goto end;
-
- i7300_idle_active = 1;
- total_starts++;
- start_ktime = now_ktime;
-
- i7300_idle_start();
- i7300_idle_ioat_start();
-
- } else if (val == IDLE_END) {
- cpumask_clear_cpu(smp_processor_id(), idle_cpumask);
- if (cpumask_weight(idle_cpumask) == (num_online_cpus() - 1)) {
- /* First CPU coming out of idle */
- u64 idle_duration_us;
-
- now_ktime = ktime_get();
-
- idle_duration_us = ktime_to_us(ktime_sub
- (now_ktime, idle_begin_time));
-
- avg_idle_us =
- ((100 - DURATION_WEIGHT_PCT) * avg_idle_us +
- DURATION_WEIGHT_PCT * idle_duration_us) / 100;
-
- if (i7300_idle_active) {
- ktime_t idle_ktime;
-
- idle_ktime = ktime_sub(now_ktime, start_ktime);
- total_us += ktime_to_us(idle_ktime);
-
- i7300_idle_ioat_stop();
- i7300_idle_stop();
- i7300_idle_active = 0;
- }
- }
- }
-end:
- raw_spin_unlock_irqrestore(&i7300_idle_lock, flags);
- return 0;
-}
-
-static struct notifier_block i7300_idle_nb = {
- .notifier_call = i7300_idle_notifier,
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
- loff_t *off)
-{
- unsigned long *p = fp->private_data;
- char buf[32];
- int len;
-
- len = snprintf(buf, 32, "%lu\n", *p);
- return simple_read_from_buffer(ubuf, count, off, buf, len);
-}
-
-static const struct file_operations idle_fops = {
- .open = simple_open,
- .read = stats_read_ul,
- .llseek = default_llseek,
-};
-
-struct debugfs_file_info {
- void *ptr;
- char name[32];
- struct dentry *file;
-} debugfs_file_list[] = {
- {&total_starts, "total_starts", NULL},
- {&total_us, "total_us", NULL},
-#ifdef DEBUG
- {&past_skip, "past_skip", NULL},
-#endif
- {NULL, "", NULL}
- };
-
-static int __init i7300_idle_init(void)
-{
- raw_spin_lock_init(&i7300_idle_lock);
- total_us = 0;
-
- if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev, forceload))
- return -ENODEV;
-
- if (i7300_idle_thrt_save())
- return -ENODEV;
-
- if (i7300_idle_ioat_init())
- return -ENODEV;
-
- if (!zalloc_cpumask_var(&idle_cpumask, GFP_KERNEL))
- return -ENOMEM;
-
- debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
- if (debugfs_dir) {
- int i = 0;
-
- while (debugfs_file_list[i].ptr != NULL) {
- debugfs_file_list[i].file = debugfs_create_file(
- debugfs_file_list[i].name,
- S_IRUSR,
- debugfs_dir,
- debugfs_file_list[i].ptr,
- &idle_fops);
- i++;
- }
- }
-
- idle_notifier_register(&i7300_idle_nb);
-
- printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION);
- return 0;
-}
-
-static void __exit i7300_idle_exit(void)
-{
- idle_notifier_unregister(&i7300_idle_nb);
- free_cpumask_var(idle_cpumask);
-
- if (debugfs_dir) {
- int i = 0;
-
- while (debugfs_file_list[i].file != NULL) {
- debugfs_remove(debugfs_file_list[i].file);
- i++;
- }
-
- debugfs_remove(debugfs_dir);
- }
- i7300_idle_thrt_restore();
- i7300_idle_ioat_exit();
-}
-
-module_init(i7300_idle_init);
-module_exit(i7300_idle_exit);
-
-MODULE_AUTHOR("Andy Henroid <andrew.d.henroid@intel.com>");
-MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v"
- I7300_IDLE_DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 4466a2f969d7..7d8ea3d5fda6 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -98,8 +98,6 @@ static int intel_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
static void intel_idle_freeze(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
-static int intel_idle_cpu_init(int cpu);
-
static struct cpuidle_state *cpuidle_state_table;
/*
@@ -724,6 +722,50 @@ static struct cpuidle_state atom_cstates[] = {
{
.enter = NULL }
};
+static struct cpuidle_state tangier_cstates[] = {
+ {
+ .name = "C1-TNG",
+ .desc = "MWAIT 0x00",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 4,
+ .enter = &intel_idle,
+ .enter_freeze = intel_idle_freeze, },
+ {
+ .name = "C4-TNG",
+ .desc = "MWAIT 0x30",
+ .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 100,
+ .target_residency = 400,
+ .enter = &intel_idle,
+ .enter_freeze = intel_idle_freeze, },
+ {
+ .name = "C6-TNG",
+ .desc = "MWAIT 0x52",
+ .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 140,
+ .target_residency = 560,
+ .enter = &intel_idle,
+ .enter_freeze = intel_idle_freeze, },
+ {
+ .name = "C7-TNG",
+ .desc = "MWAIT 0x60",
+ .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 1200,
+ .target_residency = 4000,
+ .enter = &intel_idle,
+ .enter_freeze = intel_idle_freeze, },
+ {
+ .name = "C9-TNG",
+ .desc = "MWAIT 0x64",
+ .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 10000,
+ .target_residency = 20000,
+ .enter = &intel_idle,
+ .enter_freeze = intel_idle_freeze, },
+ {
+ .enter = NULL }
+};
static struct cpuidle_state avn_cstates[] = {
{
.name = "C1-AVN",
@@ -907,51 +949,15 @@ static void intel_idle_freeze(struct cpuidle_device *dev,
mwait_idle_with_hints(eax, ecx);
}
-static void __setup_broadcast_timer(void *arg)
+static void __setup_broadcast_timer(bool on)
{
- unsigned long on = (unsigned long)arg;
-
if (on)
tick_broadcast_enable();
else
tick_broadcast_disable();
}
-static int cpu_hotplug_notify(struct notifier_block *n,
- unsigned long action, void *hcpu)
-{
- int hotcpu = (unsigned long)hcpu;
- struct cpuidle_device *dev;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
-
- if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
- smp_call_function_single(hotcpu, __setup_broadcast_timer,
- (void *)true, 1);
-
- /*
- * Some systems can hotplug a cpu at runtime after
- * the kernel has booted, we have to initialize the
- * driver in this case
- */
- dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
- if (dev->registered)
- break;
-
- if (intel_idle_cpu_init(hotcpu))
- return NOTIFY_BAD;
-
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block cpu_hotplug_notifier = {
- .notifier_call = cpu_hotplug_notify,
-};
-
-static void auto_demotion_disable(void *dummy)
+static void auto_demotion_disable(void)
{
unsigned long long msr_bits;
@@ -959,7 +965,7 @@ static void auto_demotion_disable(void *dummy)
msr_bits &= ~(icpu->auto_demotion_disable_flags);
wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
}
-static void c1e_promotion_disable(void *dummy)
+static void c1e_promotion_disable(void)
{
unsigned long long msr_bits;
@@ -978,6 +984,10 @@ static const struct idle_cpu idle_cpu_atom = {
.state_table = atom_cstates,
};
+static const struct idle_cpu idle_cpu_tangier = {
+ .state_table = tangier_cstates,
+};
+
static const struct idle_cpu idle_cpu_lincroft = {
.state_table = atom_cstates,
.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
@@ -1066,6 +1076,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
ICPU(INTEL_FAM6_SANDYBRIDGE_X, idle_cpu_snb),
ICPU(INTEL_FAM6_ATOM_CEDARVIEW, idle_cpu_atom),
ICPU(INTEL_FAM6_ATOM_SILVERMONT1, idle_cpu_byt),
+ ICPU(INTEL_FAM6_ATOM_MERRIFIELD, idle_cpu_tangier),
ICPU(INTEL_FAM6_ATOM_AIRMONT, idle_cpu_cht),
ICPU(INTEL_FAM6_IVYBRIDGE, idle_cpu_ivb),
ICPU(INTEL_FAM6_IVYBRIDGE_X, idle_cpu_ivt),
@@ -1084,6 +1095,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, idle_cpu_skl),
ICPU(INTEL_FAM6_SKYLAKE_X, idle_cpu_skx),
ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl),
+ ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl),
ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt),
ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv),
{}
@@ -1373,12 +1385,11 @@ static void __init intel_idle_cpuidle_driver_init(void)
* allocate, initialize, register cpuidle_devices
* @cpu: cpu/core to initialize
*/
-static int intel_idle_cpu_init(int cpu)
+static int intel_idle_cpu_init(unsigned int cpu)
{
struct cpuidle_device *dev;
dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
-
dev->cpu = cpu;
if (cpuidle_register_device(dev)) {
@@ -1387,17 +1398,36 @@ static int intel_idle_cpu_init(int cpu)
}
if (icpu->auto_demotion_disable_flags)
- smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
+ auto_demotion_disable();
if (icpu->disable_promotion_to_c1e)
- smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
+ c1e_promotion_disable();
+
+ return 0;
+}
+
+static int intel_idle_cpu_online(unsigned int cpu)
+{
+ struct cpuidle_device *dev;
+
+ if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+ __setup_broadcast_timer(true);
+
+ /*
+ * Some systems can hotplug a cpu at runtime after
+ * the kernel has booted, we have to initialize the
+ * driver in this case
+ */
+ dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
+ if (!dev->registered)
+ return intel_idle_cpu_init(cpu);
return 0;
}
static int __init intel_idle_init(void)
{
- int retval, i;
+ int retval;
/* Do not load intel_idle at all for now if idle= is passed */
if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -1417,35 +1447,29 @@ static int __init intel_idle_init(void)
struct cpuidle_driver *drv = cpuidle_get_driver();
printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
drv ? drv->name : "none");
- free_percpu(intel_idle_cpuidle_devices);
- return retval;
+ goto init_driver_fail;
}
- cpu_notifier_register_begin();
-
- for_each_online_cpu(i) {
- retval = intel_idle_cpu_init(i);
- if (retval) {
- intel_idle_cpuidle_devices_uninit();
- cpu_notifier_register_done();
- cpuidle_unregister_driver(&intel_idle_driver);
- free_percpu(intel_idle_cpuidle_devices);
- return retval;
- }
- }
- __register_cpu_notifier(&cpu_hotplug_notifier);
-
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
- else
- on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
- cpu_notifier_register_done();
+ retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
+ intel_idle_cpu_online, NULL);
+ if (retval < 0)
+ goto hp_setup_fail;
pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
lapic_timer_reliable_states);
return 0;
+
+hp_setup_fail:
+ intel_idle_cpuidle_devices_uninit();
+ cpuidle_unregister_driver(&intel_idle_driver);
+init_driver_fail:
+ free_percpu(intel_idle_cpuidle_devices);
+ return retval;
+
}
device_initcall(intel_idle_init);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2a6fc47a1dfb..22fcf284dd8b 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -116,7 +116,7 @@ static LIST_HEAD(dev_list);
static LIST_HEAD(listen_any_list);
static DEFINE_MUTEX(lock);
static struct workqueue_struct *cma_wq;
-static int cma_pernet_id;
+static unsigned int cma_pernet_id;
struct cma_pernet {
struct idr tcp_ps;
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 19d499dcab76..0c0bea091de8 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -127,14 +127,7 @@ void ib_cache_release_one(struct ib_device *device);
static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
struct net_device *upper)
{
- struct net_device *_upper = NULL;
- struct list_head *iter;
-
- netdev_for_each_all_upper_dev_rcu(dev, _upper, iter)
- if (_upper == upper)
- break;
-
- return _upper == upper;
+ return netdev_has_upper_dev_all_rcu(dev, upper);
}
int addr_init(void);
diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c
index 06556c34606d..3a64a0881882 100644
--- a/drivers/infiniband/core/roce_gid_mgmt.c
+++ b/drivers/infiniband/core/roce_gid_mgmt.c
@@ -437,6 +437,28 @@ static void callback_for_addr_gid_device_scan(struct ib_device *device,
&parsed->gid_attr);
}
+struct upper_list {
+ struct list_head list;
+ struct net_device *upper;
+};
+
+static int netdev_upper_walk(struct net_device *upper, void *data)
+{
+ struct upper_list *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ struct list_head *upper_list = data;
+
+ if (!entry) {
+ pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
+ return 0;
+ }
+
+ list_add_tail(&entry->list, upper_list);
+ dev_hold(upper);
+ entry->upper = upper;
+
+ return 0;
+}
+
static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
void *cookie,
void (*handle_netdev)(struct ib_device *ib_dev,
@@ -444,30 +466,12 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
struct net_device *ndev))
{
struct net_device *ndev = (struct net_device *)cookie;
- struct upper_list {
- struct list_head list;
- struct net_device *upper;
- };
- struct net_device *upper;
- struct list_head *iter;
struct upper_list *upper_iter;
struct upper_list *upper_temp;
LIST_HEAD(upper_list);
rcu_read_lock();
- netdev_for_each_all_upper_dev_rcu(ndev, upper, iter) {
- struct upper_list *entry = kmalloc(sizeof(*entry),
- GFP_ATOMIC);
-
- if (!entry) {
- pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
- continue;
- }
-
- list_add_tail(&entry->list, &upper_list);
- dev_hold(upper);
- entry->upper = upper;
- }
+ netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list);
rcu_read_unlock();
handle_netdev(ib_dev, port, ndev);
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 93e3d270a98a..4e5baf4fe15e 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -1481,6 +1481,7 @@ static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
static struct cxgb4_uld_info c4iw_uld_info = {
.name = DRV_NAME,
.nrxq = MAX_ULD_QSETS,
+ .ntxq = MAX_ULD_QSETS,
.rxq_size = 511,
.ciq = true,
.lro = false,
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 32b09f059c84..2be65ddf56ba 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1771,13 +1771,13 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
mutex_lock(&dev->flow_db.lock);
list_for_each_entry_safe(iter, tmp, &handler->list, list) {
- mlx5_del_flow_rule(iter->rule);
+ mlx5_del_flow_rules(iter->rule);
put_flow_table(dev, iter->prio, true);
list_del(&iter->list);
kfree(iter);
}
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
put_flow_table(dev, handler->prio, true);
mutex_unlock(&dev->flow_db.lock);
@@ -1857,7 +1857,7 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
ft = mlx5_create_auto_grouped_flow_table(ns, priority,
num_entries,
num_groups,
- 0);
+ 0, 0);
if (!IS_ERR(ft)) {
prio->refcount = 0;
@@ -1877,10 +1877,10 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
{
struct mlx5_flow_table *ft = ft_prio->flow_table;
struct mlx5_ib_flow_handler *handler;
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_spec *spec;
const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
unsigned int spec_index;
- u32 action;
int err = 0;
if (!is_valid_attr(flow_attr))
@@ -1905,12 +1905,12 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
}
spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
- action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
+ flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
- handler->rule = mlx5_add_flow_rule(ft, spec,
- action,
- MLX5_FS_DEFAULT_FLOW_TAG,
- dst);
+ flow_act.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
+ handler->rule = mlx5_add_flow_rules(ft, spec,
+ &flow_act,
+ dst, 1);
if (IS_ERR(handler->rule)) {
err = PTR_ERR(handler->rule);
@@ -1941,7 +1941,7 @@ static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *de
handler_dst = create_flow_rule(dev, ft_prio,
flow_attr, dst);
if (IS_ERR(handler_dst)) {
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
ft_prio->refcount--;
kfree(handler);
handler = handler_dst;
@@ -2004,7 +2004,7 @@ static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *de
&leftovers_specs[LEFTOVERS_UC].flow_attr,
dst);
if (IS_ERR(handler_ucast)) {
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
ft_prio->refcount--;
kfree(handler);
handler = handler_ucast;
@@ -2046,7 +2046,7 @@ static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev,
return handler_rx;
err_tx:
- mlx5_del_flow_rule(handler_rx->rule);
+ mlx5_del_flow_rules(handler_rx->rule);
ft_rx->refcount--;
kfree(handler_rx);
err:
@@ -2358,6 +2358,8 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
ibev.event = IB_EVENT_CLIENT_REREGISTER;
port = (u8)param;
break;
+ default:
+ return;
}
ibev.device = &ibdev->ib_dev;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 7d689903c87c..854748b61212 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -153,7 +153,7 @@ struct mlx5_ib_flow_handler {
struct list_head list;
struct ib_flow ibflow;
struct mlx5_ib_flow_prio *prio;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
};
struct mlx5_ib_flow_db {
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 35cbb17bec12..2baa45a8e401 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -65,7 +65,6 @@ MODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
-int max_mtu = 9000;
int interrupt_mod_interval = 0;
/* Interoperability */
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index e7430c9254d3..85acd0843b50 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -83,6 +83,8 @@
#define NES_FIRST_QPN 64
#define NES_SW_CONTEXT_ALIGN 1024
+#define NES_MAX_MTU 9000
+
#define NES_NIC_MAX_NICS 16
#define NES_MAX_ARP_TABLE_SIZE 4096
@@ -169,8 +171,6 @@ do { \
#include "nes_cm.h"
#include "nes_mgt.h"
-extern int max_mtu;
-#define max_frame_len (max_mtu+ETH_HLEN)
extern int interrupt_mod_interval;
extern int nes_if_count;
extern int mpa_version;
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 2b27d1351cf7..7f8597d6738b 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -981,20 +981,16 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
{
struct nes_vnic *nesvnic = netdev_priv(netdev);
struct nes_device *nesdev = nesvnic->nesdev;
- int ret = 0;
u8 jumbomode = 0;
u32 nic_active;
u32 nic_active_bit;
u32 uc_all_active;
u32 mc_all_active;
- if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
- return -EINVAL;
-
netdev->mtu = new_mtu;
nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;
- if (netdev->mtu > 1500) {
+ if (netdev->mtu > ETH_DATA_LEN) {
jumbomode=1;
}
nes_nic_init_timer_defaults(nesdev, jumbomode);
@@ -1020,7 +1016,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
}
- return ret;
+ return 0;
}
@@ -1658,7 +1654,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->watchdog_timeo = NES_TX_TIMEOUT;
netdev->irq = nesdev->pcidev->irq;
- netdev->mtu = ETH_DATA_LEN;
+ netdev->max_mtu = NES_MAX_MTU;
netdev->hard_header_len = ETH_HLEN;
netdev->addr_len = ETH_ALEN;
netdev->type = ARPHRD_ETHER;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b58d9dca5c93..c50794fb92db 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -292,6 +292,25 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev)
return dev;
}
+struct ipoib_walk_data {
+ const struct sockaddr *addr;
+ struct net_device *result;
+};
+
+static int ipoib_upper_walk(struct net_device *upper, void *_data)
+{
+ struct ipoib_walk_data *data = _data;
+ int ret = 0;
+
+ if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) {
+ dev_hold(upper);
+ data->result = upper;
+ ret = 1;
+ }
+
+ return ret;
+}
+
/**
* Find a net_device matching the given address, which is an upper device of
* the given net_device.
@@ -304,27 +323,21 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev)
static struct net_device *ipoib_get_net_dev_match_addr(
const struct sockaddr *addr, struct net_device *dev)
{
- struct net_device *upper,
- *result = NULL;
- struct list_head *iter;
+ struct ipoib_walk_data data = {
+ .addr = addr,
+ };
rcu_read_lock();
if (ipoib_is_dev_match_addr_rcu(addr, dev)) {
dev_hold(dev);
- result = dev;
+ data.result = dev;
goto out;
}
- netdev_for_each_all_upper_dev_rcu(dev, upper, iter) {
- if (ipoib_is_dev_match_addr_rcu(addr, upper)) {
- dev_hold(upper);
- result = upper;
- break;
- }
- }
+ netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data);
out:
rcu_read_unlock();
- return result;
+ return data.result;
}
/* returns the number of IPoIB netdevs on top a given ipoib device matching a
@@ -2016,6 +2029,7 @@ static struct net_device *ipoib_add_port(const char *format,
/* MTU will be reset when mcast join happens */
priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
+ priv->dev->max_mtu = IPOIB_CM_MTU;
priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index d8376c2d18b3..c66c273dfd8a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4688,25 +4688,13 @@ static void free_all_cpu_cached_iovas(unsigned int cpu)
}
}
-static int intel_iommu_cpu_notifier(struct notifier_block *nfb,
- unsigned long action, void *v)
+static int intel_iommu_cpu_dead(unsigned int cpu)
{
- unsigned int cpu = (unsigned long)v;
-
- switch (action) {
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- free_all_cpu_cached_iovas(cpu);
- flush_unmaps_timeout(cpu);
- break;
- }
- return NOTIFY_OK;
+ free_all_cpu_cached_iovas(cpu);
+ flush_unmaps_timeout(cpu);
+ return 0;
}
-static struct notifier_block intel_iommu_cpu_nb = {
- .notifier_call = intel_iommu_cpu_notifier,
-};
-
static ssize_t intel_iommu_show_version(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -4855,8 +4843,8 @@ int __init intel_iommu_init(void)
bus_register_notifier(&pci_bus_type, &device_nb);
if (si_domain && !hw_pass_through)
register_memory_notifier(&intel_iommu_memory_nb);
- register_hotcpu_notifier(&intel_iommu_cpu_nb);
-
+ cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
+ intel_iommu_cpu_dead);
intel_iommu_enabled = 1;
return 0;
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index bc0af3307bbf..ae96731cd2fb 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -211,6 +211,10 @@ config XTENSA_MX
bool
select IRQ_DOMAIN
+config XILINX_INTC
+ bool
+ select IRQ_DOMAIN
+
config IRQ_CROSSBAR
bool
help
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e4dbfc85abdb..0e55d94065bf 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o
obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
+obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o
obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o
obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index 353c54986211..c2662a1bfdd3 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -215,6 +215,31 @@ static int bcm7038_l1_set_affinity(struct irq_data *d,
return 0;
}
+static void bcm7038_l1_cpu_offline(struct irq_data *d)
+{
+ struct cpumask *mask = irq_data_get_affinity_mask(d);
+ int cpu = smp_processor_id();
+ cpumask_t new_affinity;
+
+ /* This CPU was not on the affinity mask */
+ if (!cpumask_test_cpu(cpu, mask))
+ return;
+
+ if (cpumask_weight(mask) > 1) {
+ /*
+ * Multiple CPU affinity, remove this CPU from the affinity
+ * mask
+ */
+ cpumask_copy(&new_affinity, mask);
+ cpumask_clear_cpu(cpu, &new_affinity);
+ } else {
+ /* Only CPU, put on the lowest online CPU */
+ cpumask_clear(&new_affinity);
+ cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
+ }
+ irq_set_affinity_locked(d, &new_affinity, false);
+}
+
static int __init bcm7038_l1_init_one(struct device_node *dn,
unsigned int idx,
struct bcm7038_l1_chip *intc)
@@ -266,6 +291,7 @@ static struct irq_chip bcm7038_l1_irq_chip = {
.irq_mask = bcm7038_l1_mask,
.irq_unmask = bcm7038_l1_unmask,
.irq_set_affinity = bcm7038_l1_set_affinity,
+ .irq_cpu_offline = bcm7038_l1_cpu_offline,
};
static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index c5dee300e8a3..69b040f47d56 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -37,7 +37,6 @@
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-v3.h>
-#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/exception.h>
@@ -196,7 +195,7 @@ typedef struct its_collection *(*its_cmd_builder_t)(struct its_cmd_block *,
static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
{
- cmd->raw_cmd[0] &= ~0xffUL;
+ cmd->raw_cmd[0] &= ~0xffULL;
cmd->raw_cmd[0] |= cmd_nr;
}
@@ -208,43 +207,43 @@ static void its_encode_devid(struct its_cmd_block *cmd, u32 devid)
static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
{
- cmd->raw_cmd[1] &= ~0xffffffffUL;
+ cmd->raw_cmd[1] &= ~0xffffffffULL;
cmd->raw_cmd[1] |= id;
}
static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
{
- cmd->raw_cmd[1] &= 0xffffffffUL;
+ cmd->raw_cmd[1] &= 0xffffffffULL;
cmd->raw_cmd[1] |= ((u64)phys_id) << 32;
}
static void its_encode_size(struct its_cmd_block *cmd, u8 size)
{
- cmd->raw_cmd[1] &= ~0x1fUL;
+ cmd->raw_cmd[1] &= ~0x1fULL;
cmd->raw_cmd[1] |= size & 0x1f;
}
static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
{
- cmd->raw_cmd[2] &= ~0xffffffffffffUL;
- cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00UL;
+ cmd->raw_cmd[2] &= ~0xffffffffffffULL;
+ cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00ULL;
}
static void its_encode_valid(struct its_cmd_block *cmd, int valid)
{
- cmd->raw_cmd[2] &= ~(1UL << 63);
+ cmd->raw_cmd[2] &= ~(1ULL << 63);
cmd->raw_cmd[2] |= ((u64)!!valid) << 63;
}
static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
{
- cmd->raw_cmd[2] &= ~(0xffffffffUL << 16);
- cmd->raw_cmd[2] |= (target_addr & (0xffffffffUL << 16));
+ cmd->raw_cmd[2] &= ~(0xffffffffULL << 16);
+ cmd->raw_cmd[2] |= (target_addr & (0xffffffffULL << 16));
}
static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
{
- cmd->raw_cmd[2] &= ~0xffffUL;
+ cmd->raw_cmd[2] &= ~0xffffULL;
cmd->raw_cmd[2] |= col;
}
@@ -433,7 +432,7 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
* the ITS.
*/
if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
- __flush_dcache_area(cmd, sizeof(*cmd));
+ gic_flush_dcache_to_poc(cmd, sizeof(*cmd));
else
dsb(ishst);
}
@@ -602,7 +601,7 @@ static void lpi_set_config(struct irq_data *d, bool enable)
* Humpf...
*/
if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)
- __flush_dcache_area(cfg, sizeof(*cfg));
+ gic_flush_dcache_to_poc(cfg, sizeof(*cfg));
else
dsb(ishst);
its_send_inv(its_dev, id);
@@ -657,8 +656,8 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
its = its_dev->its;
addr = its->phys_base + GITS_TRANSLATER;
- msg->address_lo = addr & ((1UL << 32) - 1);
- msg->address_hi = addr >> 32;
+ msg->address_lo = lower_32_bits(addr);
+ msg->address_hi = upper_32_bits(addr);
msg->data = its_get_event_id(d);
iommu_dma_map_msi_msg(d->irq, msg);
@@ -817,7 +816,7 @@ static int __init its_alloc_lpi_tables(void)
LPI_PROPBASE_SZ);
/* Make sure the GIC will observe the written configuration */
- __flush_dcache_area(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
+ gic_flush_dcache_to_poc(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
return 0;
}
@@ -836,7 +835,7 @@ static u64 its_read_baser(struct its_node *its, struct its_baser *baser)
{
u32 idx = baser - its->tables;
- return readq_relaxed(its->base + GITS_BASER + (idx << 3));
+ return gits_read_baser(its->base + GITS_BASER + (idx << 3));
}
static void its_write_baser(struct its_node *its, struct its_baser *baser,
@@ -844,7 +843,7 @@ static void its_write_baser(struct its_node *its, struct its_baser *baser,
{
u32 idx = baser - its->tables;
- writeq_relaxed(val, its->base + GITS_BASER + (idx << 3));
+ gits_write_baser(val, its->base + GITS_BASER + (idx << 3));
baser->val = its_read_baser(its, baser);
}
@@ -910,7 +909,7 @@ retry_baser:
shr = tmp & GITS_BASER_SHAREABILITY_MASK;
if (!shr) {
cache = GITS_BASER_nC;
- __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+ gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
}
goto retry_baser;
}
@@ -935,9 +934,9 @@ retry_baser:
}
if (val != tmp) {
- pr_err("ITS@%pa: %s doesn't stick: %lx %lx\n",
+ pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
&its->phys_base, its_base_type_string[type],
- (unsigned long) val, (unsigned long) tmp);
+ val, tmp);
free_pages((unsigned long)base, order);
return -ENXIO;
}
@@ -948,7 +947,7 @@ retry_baser:
tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
- &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),
+ &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
its_base_type_string[type],
(unsigned long)virt_to_phys(base),
indirect ? "indirect" : "flat", (int)esz,
@@ -983,7 +982,7 @@ static bool its_parse_baser_device(struct its_node *its, struct its_baser *baser
* which is reported by ITS hardware times lvl1 table
* entry size.
*/
- ids -= ilog2(psz / esz);
+ ids -= ilog2(psz / (int)esz);
esz = GITS_LVL1_ENTRY_SIZE;
}
}
@@ -998,7 +997,7 @@ static bool its_parse_baser_device(struct its_node *its, struct its_baser *baser
new_order = max_t(u32, get_order(esz << ids), new_order);
if (new_order >= MAX_ORDER) {
new_order = MAX_ORDER - 1;
- ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / esz);
+ ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
pr_warn("ITS@%pa: Device Table too large, reduce ids %u->%u\n",
&its->phys_base, its->device_ids, ids);
}
@@ -1102,7 +1101,7 @@ static void its_cpu_init_lpis(void)
}
/* Make sure the GIC will observe the zero-ed page */
- __flush_dcache_area(page_address(pend_page), LPI_PENDBASE_SZ);
+ gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
paddr = page_to_phys(pend_page);
pr_info("CPU%d: using LPI pending table @%pa\n",
@@ -1126,8 +1125,8 @@ static void its_cpu_init_lpis(void)
GICR_PROPBASER_WaWb |
((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
- writeq_relaxed(val, rbase + GICR_PROPBASER);
- tmp = readq_relaxed(rbase + GICR_PROPBASER);
+ gicr_write_propbaser(val, rbase + GICR_PROPBASER);
+ tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
@@ -1139,7 +1138,7 @@ static void its_cpu_init_lpis(void)
val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
GICR_PROPBASER_CACHEABILITY_MASK);
val |= GICR_PROPBASER_nC;
- writeq_relaxed(val, rbase + GICR_PROPBASER);
+ gicr_write_propbaser(val, rbase + GICR_PROPBASER);
}
pr_info_once("GIC: using cache flushing for LPI property table\n");
gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;
@@ -1150,8 +1149,8 @@ static void its_cpu_init_lpis(void)
GICR_PENDBASER_InnerShareable |
GICR_PENDBASER_WaWb);
- writeq_relaxed(val, rbase + GICR_PENDBASER);
- tmp = readq_relaxed(rbase + GICR_PENDBASER);
+ gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
+ tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
/*
@@ -1161,7 +1160,7 @@ static void its_cpu_init_lpis(void)
val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
GICR_PENDBASER_CACHEABILITY_MASK);
val |= GICR_PENDBASER_nC;
- writeq_relaxed(val, rbase + GICR_PENDBASER);
+ gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
}
/* Enable LPIs */
@@ -1287,13 +1286,13 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
/* Flush Lvl2 table to PoC if hw doesn't support coherency */
if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
- __flush_dcache_area(page_address(page), baser->psz);
+ gic_flush_dcache_to_poc(page_address(page), baser->psz);
table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
/* Flush Lvl1 entry to PoC if hw doesn't support coherency */
if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
- __flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
+ gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
/* Ensure updated table contents are visible to ITS hardware */
dsb(sy);
@@ -1340,7 +1339,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
return NULL;
}
- __flush_dcache_area(itt, sz);
+ gic_flush_dcache_to_poc(itt, sz);
dev->its = its;
dev->itt = itt;
@@ -1717,8 +1716,8 @@ static int __init its_probe_one(struct resource *res,
(ITS_CMD_QUEUE_SZ / SZ_4K - 1) |
GITS_CBASER_VALID);
- writeq_relaxed(baser, its->base + GITS_CBASER);
- tmp = readq_relaxed(its->base + GITS_CBASER);
+ gits_write_cbaser(baser, its->base + GITS_CBASER);
+ tmp = gits_read_cbaser(its->base + GITS_CBASER);
if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
@@ -1730,13 +1729,13 @@ static int __init its_probe_one(struct resource *res,
baser &= ~(GITS_CBASER_SHAREABILITY_MASK |
GITS_CBASER_CACHEABILITY_MASK);
baser |= GITS_CBASER_nC;
- writeq_relaxed(baser, its->base + GITS_CBASER);
+ gits_write_cbaser(baser, its->base + GITS_CBASER);
}
pr_info("ITS: using cache flushing for cmd queue\n");
its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;
}
- writeq_relaxed(0, its->base + GITS_CWRITER);
+ gits_write_cwriter(0, its->base + GITS_CWRITER);
writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
err = its_init_domain(handle, its);
diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c
new file mode 100644
index 000000000000..3db7ab1c9741
--- /dev/null
+++ b/drivers/irqchip/irq-xilinx-intc.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012-2013 Xilinx, Inc.
+ * Copyright (C) 2007-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/jump_label.h>
+#include <linux/bug.h>
+#include <linux/of_irq.h>
+
+/* No one else should require these constants, so define them locally here. */
+#define ISR 0x00 /* Interrupt Status Register */
+#define IPR 0x04 /* Interrupt Pending Register */
+#define IER 0x08 /* Interrupt Enable Register */
+#define IAR 0x0c /* Interrupt Acknowledge Register */
+#define SIE 0x10 /* Set Interrupt Enable bits */
+#define CIE 0x14 /* Clear Interrupt Enable bits */
+#define IVR 0x18 /* Interrupt Vector Register */
+#define MER 0x1c /* Master Enable Register */
+
+#define MER_ME (1<<0)
+#define MER_HIE (1<<1)
+
+static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
+
+struct xintc_irq_chip {
+ void __iomem *base;
+ struct irq_domain *root_domain;
+ u32 intr_mask;
+};
+
+static struct xintc_irq_chip *xintc_irqc;
+
+static void xintc_write(int reg, u32 data)
+{
+ if (static_branch_unlikely(&xintc_is_be))
+ iowrite32be(data, xintc_irqc->base + reg);
+ else
+ iowrite32(data, xintc_irqc->base + reg);
+}
+
+static unsigned int xintc_read(int reg)
+{
+ if (static_branch_unlikely(&xintc_is_be))
+ return ioread32be(xintc_irqc->base + reg);
+ else
+ return ioread32(xintc_irqc->base + reg);
+}
+
+static void intc_enable_or_unmask(struct irq_data *d)
+{
+ unsigned long mask = 1 << d->hwirq;
+
+ pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);
+
+ /* ack level irqs because they can't be acked during
+ * ack function since the handle_level_irq function
+ * acks the irq before calling the interrupt handler
+ */
+ if (irqd_is_level_type(d))
+ xintc_write(IAR, mask);
+
+ xintc_write(SIE, mask);
+}
+
+static void intc_disable_or_mask(struct irq_data *d)
+{
+ pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
+ xintc_write(CIE, 1 << d->hwirq);
+}
+
+static void intc_ack(struct irq_data *d)
+{
+ pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
+ xintc_write(IAR, 1 << d->hwirq);
+}
+
+static void intc_mask_ack(struct irq_data *d)
+{
+ unsigned long mask = 1 << d->hwirq;
+
+ pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
+ xintc_write(CIE, mask);
+ xintc_write(IAR, mask);
+}
+
+static struct irq_chip intc_dev = {
+ .name = "Xilinx INTC",
+ .irq_unmask = intc_enable_or_unmask,
+ .irq_mask = intc_disable_or_mask,
+ .irq_ack = intc_ack,
+ .irq_mask_ack = intc_mask_ack,
+};
+
+unsigned int xintc_get_irq(void)
+{
+ unsigned int hwirq, irq = -1;
+
+ hwirq = xintc_read(IVR);
+ if (hwirq != -1U)
+ irq = irq_find_mapping(xintc_irqc->root_domain, hwirq);
+
+ pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
+
+ return irq;
+}
+
+static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ if (xintc_irqc->intr_mask & (1 << hw)) {
+ irq_set_chip_and_handler_name(irq, &intc_dev,
+ handle_edge_irq, "edge");
+ irq_clear_status_flags(irq, IRQ_LEVEL);
+ } else {
+ irq_set_chip_and_handler_name(irq, &intc_dev,
+ handle_level_irq, "level");
+ irq_set_status_flags(irq, IRQ_LEVEL);
+ }
+ return 0;
+}
+
+static const struct irq_domain_ops xintc_irq_domain_ops = {
+ .xlate = irq_domain_xlate_onetwocell,
+ .map = xintc_map,
+};
+
+static void xil_intc_irq_handler(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u32 pending;
+
+ chained_irq_enter(chip, desc);
+ do {
+ pending = xintc_get_irq();
+ if (pending == -1U)
+ break;
+ generic_handle_irq(pending);
+ } while (true);
+ chained_irq_exit(chip, desc);
+}
+
+static int __init xilinx_intc_of_init(struct device_node *intc,
+ struct device_node *parent)
+{
+ u32 nr_irq;
+ int ret, irq;
+ struct xintc_irq_chip *irqc;
+
+ if (xintc_irqc) {
+ pr_err("irq-xilinx: Multiple instances aren't supported\n");
+ return -EINVAL;
+ }
+
+ irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
+ if (!irqc)
+ return -ENOMEM;
+
+ xintc_irqc = irqc;
+
+ irqc->base = of_iomap(intc, 0);
+ BUG_ON(!irqc->base);
+
+ ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
+ if (ret < 0) {
+ pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n");
+ goto err_alloc;
+ }
+
+ ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask);
+ if (ret < 0) {
+ pr_warn("irq-xilinx: unable to read xlnx,kind-of-intr\n");
+ irqc->intr_mask = 0;
+ }
+
+ if (irqc->intr_mask >> nr_irq)
+ pr_warn("irq-xilinx: mismatch in kind-of-intr param\n");
+
+ pr_info("irq-xilinx: %s: num_irq=%d, edge=0x%x\n",
+ intc->full_name, nr_irq, irqc->intr_mask);
+
+
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ xintc_write(IER, 0);
+
+ /* Acknowledge any pending interrupts just in case. */
+ xintc_write(IAR, 0xffffffff);
+
+ /* Turn on the Master Enable. */
+ xintc_write(MER, MER_HIE | MER_ME);
+ if (!(xintc_read(MER) & (MER_HIE | MER_ME))) {
+ static_branch_enable(&xintc_is_be);
+ xintc_write(MER, MER_HIE | MER_ME);
+ }
+
+ irqc->root_domain = irq_domain_add_linear(intc, nr_irq,
+ &xintc_irq_domain_ops, irqc);
+ if (!irqc->root_domain) {
+ pr_err("irq-xilinx: Unable to create IRQ domain\n");
+ goto err_alloc;
+ }
+
+ if (parent) {
+ irq = irq_of_parse_and_map(intc, 0);
+ if (irq) {
+ irq_set_chained_handler_and_data(irq,
+ xil_intc_irq_handler,
+ irqc);
+ } else {
+ pr_err("irq-xilinx: interrupts property not in DT\n");
+ ret = -EINVAL;
+ goto err_alloc;
+ }
+ } else {
+ irq_set_default_host(irqc->root_domain);
+ }
+
+ return 0;
+
+err_alloc:
+ xintc_irqc = NULL;
+ kfree(irqc);
+ return ret;
+
+}
+
+IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
+IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init);
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 5609deee7cd3..b93a4e9a8d34 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -232,7 +232,6 @@ static const struct net_device_ops hysdn_netdev_ops = {
.ndo_open = net_open,
.ndo_stop = net_close,
.ndo_start_xmit = net_send_packet,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 7a628c6516f6..c621cbbb5768 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -645,7 +645,7 @@ config LEDS_VERSATILE
config LEDS_PM8058
tristate "LED Support for the Qualcomm PM8058 PMIC"
- depends on MFD_PM8921_CORE
+ depends on MFD_PM8XXX
depends on LEDS_CLASS
help
Choose this option if you want to use the LED drivers in
@@ -659,6 +659,25 @@ config LEDS_MLXCPLD
This option enabled support for the LEDs on the Mellanox
boards. Say Y to enabled these.
+config LEDS_USER
+ tristate "Userspace LED support"
+ depends on LEDS_CLASS
+ help
+ This option enables support for userspace LEDs. Say 'y' to enable this
+ support in kernel. To compile this driver as a module, choose 'm' here:
+ the module will be called uleds.
+
+config LEDS_NIC78BX
+ tristate "LED support for NI PXI NIC78bx devices"
+ depends on LEDS_CLASS
+ depends on X86 && ACPI
+ help
+ This option enables support for the User1 and User2 LEDs on NI
+ PXI NIC78bx devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called leds-nic78bx.
+
comment "LED Triggers"
source "drivers/leds/trigger/Kconfig"
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 3965070190f5..6b8273736478 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -71,9 +71,13 @@ obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o
obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o
obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
+obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
+# LED Userspace Drivers
+obj-$(CONFIG_LEDS_USER) += uleds.o
+
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index aa84e5b37593..326ee6e925a2 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
+#include <uapi/linux/uleds.h>
#include "leds.h"
static struct class *leds_class;
@@ -187,7 +188,7 @@ static int led_classdev_next_name(const char *init_name, char *name,
*/
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
- char name[64];
+ char name[LED_MAX_NAME_SIZE];
int ret;
ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
@@ -203,6 +204,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
dev_warn(parent, "Led %s renamed to %s due to name collision",
led_cdev->name, dev_name(led_cdev->dev));
+ led_cdev->work_flags = 0;
#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
#endif
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 3bce44893021..ef1360445413 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -53,30 +53,30 @@ static void led_timer_function(unsigned long data)
if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
led_set_brightness_nosleep(led_cdev, LED_OFF);
- led_cdev->flags &= ~LED_BLINK_SW;
+ clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
return;
}
- if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
- led_cdev->flags &= ~(LED_BLINK_ONESHOT_STOP | LED_BLINK_SW);
+ if (test_and_clear_bit(LED_BLINK_ONESHOT_STOP,
+ &led_cdev->work_flags)) {
+ clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
return;
}
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
- brightness = led_cdev->blink_brightness;
+ if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE,
+ &led_cdev->work_flags))
+ brightness = led_cdev->new_blink_brightness;
+ else
+ 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.
- * Do it only if there is no pending blink brightness
- * change, to avoid overwriting the new value.
*/
- if (!(led_cdev->flags & LED_BLINK_BRIGHTNESS_CHANGE))
- led_cdev->blink_brightness = brightness;
- else
- led_cdev->flags &= ~LED_BLINK_BRIGHTNESS_CHANGE;
+ led_cdev->blink_brightness = brightness;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
@@ -87,13 +87,15 @@ static void led_timer_function(unsigned long data)
* 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 (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags)) {
+ if (test_bit(LED_BLINK_INVERT, &led_cdev->work_flags)) {
if (brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ set_bit(LED_BLINK_ONESHOT_STOP,
+ &led_cdev->work_flags);
} else {
if (!brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ set_bit(LED_BLINK_ONESHOT_STOP,
+ &led_cdev->work_flags);
}
}
@@ -106,10 +108,9 @@ static void set_brightness_delayed(struct work_struct *ws)
container_of(ws, struct led_classdev, set_brightness_work);
int ret = 0;
- if (led_cdev->flags & LED_BLINK_DISABLE) {
+ if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) {
led_cdev->delayed_set_value = LED_OFF;
led_stop_software_blink(led_cdev);
- led_cdev->flags &= ~LED_BLINK_DISABLE;
}
ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
@@ -152,7 +153,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
return;
}
- led_cdev->flags |= LED_BLINK_SW;
+ set_bit(LED_BLINK_SW, &led_cdev->work_flags);
mod_timer(&led_cdev->blink_timer, jiffies + 1);
}
@@ -161,7 +162,7 @@ static void led_blink_setup(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
- if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
+ if (!test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
led_cdev->blink_set &&
!led_cdev->blink_set(led_cdev, delay_on, delay_off))
return;
@@ -188,8 +189,8 @@ void led_blink_set(struct led_classdev *led_cdev,
{
del_timer_sync(&led_cdev->blink_timer);
- led_cdev->flags &= ~LED_BLINK_ONESHOT;
- led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+ clear_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
+ clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
led_blink_setup(led_cdev, delay_on, delay_off);
}
@@ -200,17 +201,17 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
unsigned long *delay_off,
int invert)
{
- if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
+ if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
timer_pending(&led_cdev->blink_timer))
return;
- led_cdev->flags |= LED_BLINK_ONESHOT;
- led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+ set_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
+ clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
if (invert)
- led_cdev->flags |= LED_BLINK_INVERT;
+ set_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
else
- led_cdev->flags &= ~LED_BLINK_INVERT;
+ clear_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
led_blink_setup(led_cdev, delay_on, delay_off);
}
@@ -221,7 +222,7 @@ void led_stop_software_blink(struct led_classdev *led_cdev)
del_timer_sync(&led_cdev->blink_timer);
led_cdev->blink_delay_on = 0;
led_cdev->blink_delay_off = 0;
- led_cdev->flags &= ~LED_BLINK_SW;
+ clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
}
EXPORT_SYMBOL_GPL(led_stop_software_blink);
@@ -232,18 +233,19 @@ void led_set_brightness(struct led_classdev *led_cdev,
* If software blink is active, delay brightness setting
* until the next timer tick.
*/
- if (led_cdev->flags & LED_BLINK_SW) {
+ if (test_bit(LED_BLINK_SW, &led_cdev->work_flags)) {
/*
* If we need to disable soft blinking delegate this to the
* work queue task to avoid problems in case we are called
* from hard irq context.
*/
if (brightness == LED_OFF) {
- led_cdev->flags |= LED_BLINK_DISABLE;
+ set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags);
schedule_work(&led_cdev->set_brightness_work);
} else {
- led_cdev->flags |= LED_BLINK_BRIGHTNESS_CHANGE;
- led_cdev->blink_brightness = brightness;
+ set_bit(LED_BLINK_BRIGHTNESS_CHANGE,
+ &led_cdev->work_flags);
+ led_cdev->new_blink_brightness = brightness;
}
return;
}
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index b316df4a8c1e..8d066facdc73 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -115,8 +115,4 @@ static struct platform_driver cobalt_raq_led_driver = {
},
};
-static int __init cobalt_raq_led_init(void)
-{
- return platform_driver_register(&cobalt_raq_led_driver);
-}
-device_initcall(cobalt_raq_led_init);
+builtin_platform_driver(cobalt_raq_led_driver);
diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c
index a73c8ff08530..4847e89883a7 100644
--- a/drivers/leds/leds-lp3952.c
+++ b/drivers/leds/leds-lp3952.c
@@ -274,6 +274,7 @@ static const struct i2c_device_id lp3952_id[] = {
{LP3952_NAME, 0},
{}
};
+MODULE_DEVICE_TABLE(i2c, lp3952_id);
#ifdef CONFIG_ACPI
static const struct acpi_device_id lp3952_acpi_match[] = {
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index a2e4c1792e17..2421cf104991 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -84,8 +84,9 @@ static int mc13xxx_led_set(struct led_classdev *led_cdev,
case MC13892_LED_MD:
case MC13892_LED_AD:
case MC13892_LED_KP:
- reg = (led->id - MC13892_LED_MD) / 2;
- shift = 3 + (led->id - MC13892_LED_MD) * 12;
+ off = led->id - MC13892_LED_MD;
+ reg = off / 2;
+ shift = 3 + (off - reg * 2) * 12;
break;
case MC13892_LED_R:
case MC13892_LED_G:
diff --git a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c
index 197ab9b29a9c..281482e1d50f 100644
--- a/drivers/leds/leds-mlxcpld.c
+++ b/drivers/leds/leds-mlxcpld.c
@@ -400,6 +400,9 @@ static int __init mlxcpld_led_init(void)
struct platform_device *pdev;
int err;
+ if (!dmi_match(DMI_CHASSIS_VENDOR, "Mellanox Technologies Ltd."))
+ return -ENODEV;
+
pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
if (IS_ERR(pdev)) {
pr_err("Device allocation failed\n");
@@ -426,5 +429,5 @@ module_exit(mlxcpld_led_exit);
MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
MODULE_DESCRIPTION("Mellanox board LED driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:leds_mlxcpld");
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index 4b88b93244be..f48b1aed9b4e 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -534,6 +534,7 @@ static const struct of_device_id of_netxbig_leds_match[] = {
{ .compatible = "lacie,netxbig-leds", },
{},
};
+MODULE_DEVICE_TABLE(of, of_netxbig_leds_match);
#else
static inline int
netxbig_leds_get_of_pdata(struct device *dev,
diff --git a/drivers/leds/leds-nic78bx.c b/drivers/leds/leds-nic78bx.c
new file mode 100644
index 000000000000..8d69e2b74a27
--- /dev/null
+++ b/drivers/leds/leds-nic78bx.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2016 National Instruments Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/acpi.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#define NIC78BX_USER1_LED_MASK 0x3
+#define NIC78BX_USER1_GREEN_LED BIT(0)
+#define NIC78BX_USER1_YELLOW_LED BIT(1)
+
+#define NIC78BX_USER2_LED_MASK 0xC
+#define NIC78BX_USER2_GREEN_LED BIT(2)
+#define NIC78BX_USER2_YELLOW_LED BIT(3)
+
+#define NIC78BX_LOCK_REG_OFFSET 1
+#define NIC78BX_LOCK_VALUE 0xA5
+#define NIC78BX_UNLOCK_VALUE 0x5A
+
+#define NIC78BX_USER_LED_IO_SIZE 2
+
+struct nic78bx_led_data {
+ u16 io_base;
+ spinlock_t lock;
+ struct platform_device *pdev;
+};
+
+struct nic78bx_led {
+ u8 bit;
+ u8 mask;
+ struct nic78bx_led_data *data;
+ struct led_classdev cdev;
+};
+
+static inline struct nic78bx_led *to_nic78bx_led(struct led_classdev *cdev)
+{
+ return container_of(cdev, struct nic78bx_led, cdev);
+}
+
+static void nic78bx_brightness_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct nic78bx_led *nled = to_nic78bx_led(cdev);
+ unsigned long flags;
+ u8 value;
+
+ spin_lock_irqsave(&nled->data->lock, flags);
+ value = inb(nled->data->io_base);
+
+ if (brightness) {
+ value &= ~nled->mask;
+ value |= nled->bit;
+ } else {
+ value &= ~nled->bit;
+ }
+
+ outb(value, nled->data->io_base);
+ spin_unlock_irqrestore(&nled->data->lock, flags);
+}
+
+static enum led_brightness nic78bx_brightness_get(struct led_classdev *cdev)
+{
+ struct nic78bx_led *nled = to_nic78bx_led(cdev);
+ unsigned long flags;
+ u8 value;
+
+ spin_lock_irqsave(&nled->data->lock, flags);
+ value = inb(nled->data->io_base);
+ spin_unlock_irqrestore(&nled->data->lock, flags);
+
+ return (value & nled->bit) ? 1 : LED_OFF;
+}
+
+static struct nic78bx_led nic78bx_leds[] = {
+ {
+ .bit = NIC78BX_USER1_GREEN_LED,
+ .mask = NIC78BX_USER1_LED_MASK,
+ .cdev = {
+ .name = "nilrt:green:user1",
+ .max_brightness = 1,
+ .brightness_set = nic78bx_brightness_set,
+ .brightness_get = nic78bx_brightness_get,
+ }
+ },
+ {
+ .bit = NIC78BX_USER1_YELLOW_LED,
+ .mask = NIC78BX_USER1_LED_MASK,
+ .cdev = {
+ .name = "nilrt:yellow:user1",
+ .max_brightness = 1,
+ .brightness_set = nic78bx_brightness_set,
+ .brightness_get = nic78bx_brightness_get,
+ }
+ },
+ {
+ .bit = NIC78BX_USER2_GREEN_LED,
+ .mask = NIC78BX_USER2_LED_MASK,
+ .cdev = {
+ .name = "nilrt:green:user2",
+ .max_brightness = 1,
+ .brightness_set = nic78bx_brightness_set,
+ .brightness_get = nic78bx_brightness_get,
+ }
+ },
+ {
+ .bit = NIC78BX_USER2_YELLOW_LED,
+ .mask = NIC78BX_USER2_LED_MASK,
+ .cdev = {
+ .name = "nilrt:yellow:user2",
+ .max_brightness = 1,
+ .brightness_set = nic78bx_brightness_set,
+ .brightness_get = nic78bx_brightness_get,
+ }
+ }
+};
+
+static int nic78bx_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct nic78bx_led_data *led_data;
+ struct resource *io_rc;
+ int ret, i;
+
+ led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL);
+ if (!led_data)
+ return -ENOMEM;
+
+ led_data->pdev = pdev;
+ platform_set_drvdata(pdev, led_data);
+
+ io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!io_rc) {
+ dev_err(dev, "missing IO resources\n");
+ return -EINVAL;
+ }
+
+ if (resource_size(io_rc) < NIC78BX_USER_LED_IO_SIZE) {
+ dev_err(dev, "IO region too small\n");
+ return -EINVAL;
+ }
+
+ if (!devm_request_region(dev, io_rc->start, resource_size(io_rc),
+ KBUILD_MODNAME)) {
+ dev_err(dev, "failed to get IO region\n");
+ return -EBUSY;
+ }
+
+ led_data->io_base = io_rc->start;
+ spin_lock_init(&led_data->lock);
+
+ for (i = 0; i < ARRAY_SIZE(nic78bx_leds); i++) {
+ nic78bx_leds[i].data = led_data;
+
+ ret = devm_led_classdev_register(dev, &nic78bx_leds[i].cdev);
+ if (ret)
+ return ret;
+ }
+
+ /* Unlock LED register */
+ outb(NIC78BX_UNLOCK_VALUE,
+ led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
+
+ return ret;
+}
+
+static int nic78bx_remove(struct platform_device *pdev)
+{
+ struct nic78bx_led_data *led_data = platform_get_drvdata(pdev);
+
+ /* Lock LED register */
+ outb(NIC78BX_LOCK_VALUE,
+ led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
+
+ return 0;
+}
+
+static const struct acpi_device_id led_device_ids[] = {
+ {"NIC78B3", 0},
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, led_device_ids);
+
+static struct platform_driver led_driver = {
+ .probe = nic78bx_probe,
+ .remove = nic78bx_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .acpi_match_table = ACPI_PTR(led_device_ids),
+ },
+};
+
+module_platform_driver(led_driver);
+
+MODULE_DESCRIPTION("National Instruments PXI User LEDs driver");
+MODULE_AUTHOR("Hui Chun Ong <hui.chun.ong@ni.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 09a7cffbc46f..06e63106ae1e 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -369,7 +369,7 @@ static int pca9532_configure(struct i2c_client *client,
led->state = pled->state;
led->name = pled->name;
led->ldev.name = led->name;
- led->ldev.default_trigger = led->default_trigger;
+ led->ldev.default_trigger = pled->default_trigger;
led->ldev.brightness = LED_OFF;
led->ldev.brightness_set_blocking =
pca9532_set_brightness;
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 840401ae9a4e..78a7ce816a47 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -40,6 +40,7 @@
* bits the chip supports.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/string.h>
@@ -100,6 +101,15 @@ static const struct i2c_device_id pca955x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca955x_id);
+static const struct acpi_device_id pca955x_acpi_ids[] = {
+ { "PCA9550", pca9550 },
+ { "PCA9551", pca9551 },
+ { "PCA9552", pca9552 },
+ { "PCA9553", pca9553 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, pca955x_acpi_ids);
+
struct pca955x {
struct mutex lock;
struct pca955x_led *leds;
@@ -250,7 +260,16 @@ static int pca955x_probe(struct i2c_client *client,
struct led_platform_data *pdata;
int i, err;
- chip = &pca955x_chipdefs[id->driver_data];
+ if (id) {
+ chip = &pca955x_chipdefs[id->driver_data];
+ } else {
+ const struct acpi_device_id *acpi_id;
+
+ acpi_id = acpi_match_device(pca955x_acpi_ids, &client->dev);
+ if (!acpi_id)
+ return -ENODEV;
+ chip = &pca955x_chipdefs[acpi_id->driver_data];
+ }
adapter = to_i2c_adapter(client->dev.parent);
pdata = dev_get_platdata(&client->dev);
@@ -264,7 +283,7 @@ static int pca955x_probe(struct i2c_client *client,
dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at "
"slave address 0x%02x\n",
- id->name, chip->bits, client->addr);
+ client->name, chip->bits, client->addr);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return -EIO;
@@ -358,6 +377,7 @@ static int pca955x_remove(struct i2c_client *client)
static struct i2c_driver pca955x_driver = {
.driver = {
.name = "leds-pca955x",
+ .acpi_match_table = ACPI_PTR(pca955x_acpi_ids),
},
.probe = pca955x_probe,
.remove = pca955x_remove,
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 407eba11e187..ded1e4dac36a 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -25,6 +25,7 @@
* or by adding the 'nxp,hw-blink' property to the DTS.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/string.h>
@@ -59,6 +60,7 @@ struct pca963x_chipdef {
u8 grpfreq;
u8 ledout_base;
int n_leds;
+ unsigned int scaling;
};
static struct pca963x_chipdef pca963x_chipdefs[] = {
@@ -95,6 +97,15 @@ static const struct i2c_device_id pca963x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca963x_id);
+static const struct acpi_device_id pca963x_acpi_ids[] = {
+ { "PCA9632", pca9633 },
+ { "PCA9633", pca9633 },
+ { "PCA9634", pca9634 },
+ { "PCA9635", pca9635 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, pca963x_acpi_ids);
+
struct pca963x_led;
struct pca963x {
@@ -102,6 +113,7 @@ struct pca963x {
struct mutex mutex;
struct i2c_client *client;
struct pca963x_led *leds;
+ unsigned long leds_on;
};
struct pca963x_led {
@@ -123,7 +135,6 @@ static int pca963x_brightness(struct pca963x_led *pca963x,
u8 mask = 0x3 << shift;
int ret;
- mutex_lock(&pca963x->chip->mutex);
ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr);
switch (brightness) {
case LED_FULL:
@@ -140,14 +151,13 @@ static int pca963x_brightness(struct pca963x_led *pca963x,
PCA963X_PWM_BASE + pca963x->led_num,
brightness);
if (ret < 0)
- goto unlock;
+ return ret;
ret = i2c_smbus_write_byte_data(pca963x->chip->client,
ledout_addr,
(ledout & ~mask) | (PCA963X_LED_PWM << shift));
break;
}
-unlock:
- mutex_unlock(&pca963x->chip->mutex);
+
return ret;
}
@@ -179,14 +189,49 @@ static void pca963x_blink(struct pca963x_led *pca963x)
mutex_unlock(&pca963x->chip->mutex);
}
+static int pca963x_power_state(struct pca963x_led *pca963x)
+{
+ unsigned long *leds_on = &pca963x->chip->leds_on;
+ unsigned long cached_leds = pca963x->chip->leds_on;
+
+ if (pca963x->led_cdev.brightness)
+ set_bit(pca963x->led_num, leds_on);
+ else
+ clear_bit(pca963x->led_num, leds_on);
+
+ if (!(*leds_on) != !cached_leds)
+ return i2c_smbus_write_byte_data(pca963x->chip->client,
+ PCA963X_MODE1, *leds_on ? 0 : BIT(4));
+
+ return 0;
+}
+
static int pca963x_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct pca963x_led *pca963x;
+ int ret;
pca963x = container_of(led_cdev, struct pca963x_led, led_cdev);
- return pca963x_brightness(pca963x, value);
+ mutex_lock(&pca963x->chip->mutex);
+
+ ret = pca963x_brightness(pca963x, value);
+ if (ret < 0)
+ goto unlock;
+ ret = pca963x_power_state(pca963x);
+
+unlock:
+ mutex_unlock(&pca963x->chip->mutex);
+ return ret;
+}
+
+static unsigned int pca963x_period_scale(struct pca963x_led *pca963x,
+ unsigned int val)
+{
+ unsigned int scaling = pca963x->chip->chipdef->scaling;
+
+ return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val;
}
static int pca963x_blink_set(struct led_classdev *led_cdev,
@@ -207,14 +252,14 @@ static int pca963x_blink_set(struct led_classdev *led_cdev,
time_off = 500;
}
- period = time_on + time_off;
+ period = pca963x_period_scale(pca963x, time_on + time_off);
/* If period not supported by hardware, default to someting sane. */
if ((period < PCA963X_BLINK_PERIOD_MIN) ||
(period > PCA963X_BLINK_PERIOD_MAX)) {
time_on = 500;
time_off = 500;
- period = time_on + time_off;
+ period = pca963x_period_scale(pca963x, 1000);
}
/*
@@ -222,7 +267,7 @@ static int pca963x_blink_set(struct led_classdev *led_cdev,
* (time_on / period) = (GDC / 256) ->
* GDC = ((time_on * 256) / period)
*/
- gdc = (time_on * 256) / period;
+ gdc = (pca963x_period_scale(pca963x, time_on) * 256) / period;
/*
* From manual: period = ((GFRQ + 1) / 24) in seconds.
@@ -294,6 +339,9 @@ pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
else
pdata->blink_type = PCA963X_SW_BLINK;
+ if (of_property_read_u32(np, "nxp,period-scale", &chip->scaling))
+ chip->scaling = 1000;
+
return pdata;
}
@@ -322,7 +370,16 @@ static int pca963x_probe(struct i2c_client *client,
struct pca963x_chipdef *chip;
int i, err;
- chip = &pca963x_chipdefs[id->driver_data];
+ if (id) {
+ chip = &pca963x_chipdefs[id->driver_data];
+ } else {
+ const struct acpi_device_id *acpi_id;
+
+ acpi_id = acpi_match_device(pca963x_acpi_ids, &client->dev);
+ if (!acpi_id)
+ return -ENODEV;
+ chip = &pca963x_chipdefs[acpi_id->driver_data];
+ }
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
@@ -391,8 +448,8 @@ static int pca963x_probe(struct i2c_client *client,
goto exit;
}
- /* Disable LED all-call address and set normal mode */
- i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
+ /* Disable LED all-call address, and power down initially */
+ i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4));
if (pdata) {
/* Configure output: open-drain or totem pole (push-pull) */
@@ -426,6 +483,7 @@ static struct i2c_driver pca963x_driver = {
.driver = {
.name = "leds-pca963x",
.of_match_table = of_match_ptr(of_pca963x_match),
+ .acpi_match_table = ACPI_PTR(pca963x_acpi_ids),
},
.probe = pca963x_probe,
.remove = pca963x_remove,
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
index 22f0634dd3fa..9719caf7437c 100644
--- a/drivers/leds/trigger/ledtrig-cpu.c
+++ b/drivers/leds/trigger/ledtrig-cpu.c
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
* @evt: CPU event to be emitted
*
* Emit a CPU event on a CPU core, which will trigger a
- * binded LED to turn on or turn off.
+ * bound LED to turn on or turn off.
*/
void ledtrig_cpu(enum cpu_led_event ledevt)
{
diff --git a/drivers/leds/uleds.c b/drivers/leds/uleds.c
new file mode 100644
index 000000000000..5e9e8a1fdefb
--- /dev/null
+++ b/drivers/leds/uleds.c
@@ -0,0 +1,235 @@
+/*
+ * Userspace driver for the LED subsystem
+ *
+ * Copyright (C) 2016 David Lechner <david@lechnology.com>
+ *
+ * Based on uinput.c: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <uapi/linux/uleds.h>
+
+#define ULEDS_NAME "uleds"
+
+enum uleds_state {
+ ULEDS_STATE_UNKNOWN,
+ ULEDS_STATE_REGISTERED,
+};
+
+struct uleds_device {
+ struct uleds_user_dev user_dev;
+ struct led_classdev led_cdev;
+ struct mutex mutex;
+ enum uleds_state state;
+ wait_queue_head_t waitq;
+ int brightness;
+ bool new_data;
+};
+
+static struct miscdevice uleds_misc;
+
+static void uleds_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct uleds_device *udev = container_of(led_cdev, struct uleds_device,
+ led_cdev);
+
+ if (udev->brightness != brightness) {
+ udev->brightness = brightness;
+ udev->new_data = true;
+ wake_up_interruptible(&udev->waitq);
+ }
+}
+
+static int uleds_open(struct inode *inode, struct file *file)
+{
+ struct uleds_device *udev;
+
+ udev = kzalloc(sizeof(*udev), GFP_KERNEL);
+ if (!udev)
+ return -ENOMEM;
+
+ udev->led_cdev.name = udev->user_dev.name;
+ udev->led_cdev.brightness_set = uleds_brightness_set;
+
+ mutex_init(&udev->mutex);
+ init_waitqueue_head(&udev->waitq);
+ udev->state = ULEDS_STATE_UNKNOWN;
+
+ file->private_data = udev;
+ nonseekable_open(inode, file);
+
+ return 0;
+}
+
+static ssize_t uleds_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct uleds_device *udev = file->private_data;
+ const char *name;
+ int ret;
+
+ if (count == 0)
+ return 0;
+
+ ret = mutex_lock_interruptible(&udev->mutex);
+ if (ret)
+ return ret;
+
+ if (udev->state == ULEDS_STATE_REGISTERED) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (count != sizeof(struct uleds_user_dev)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (copy_from_user(&udev->user_dev, buffer,
+ sizeof(struct uleds_user_dev))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ name = udev->user_dev.name;
+ if (!name[0] || !strcmp(name, ".") || !strcmp(name, "..") ||
+ strchr(name, '/')) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (udev->user_dev.max_brightness <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ udev->led_cdev.max_brightness = udev->user_dev.max_brightness;
+
+ ret = devm_led_classdev_register(uleds_misc.this_device,
+ &udev->led_cdev);
+ if (ret < 0)
+ goto out;
+
+ udev->new_data = true;
+ udev->state = ULEDS_STATE_REGISTERED;
+ ret = count;
+
+out:
+ mutex_unlock(&udev->mutex);
+
+ return ret;
+}
+
+static ssize_t uleds_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct uleds_device *udev = file->private_data;
+ ssize_t retval;
+
+ if (count < sizeof(udev->brightness))
+ return 0;
+
+ do {
+ retval = mutex_lock_interruptible(&udev->mutex);
+ if (retval)
+ return retval;
+
+ if (udev->state != ULEDS_STATE_REGISTERED) {
+ retval = -ENODEV;
+ } else if (!udev->new_data && (file->f_flags & O_NONBLOCK)) {
+ retval = -EAGAIN;
+ } else if (udev->new_data) {
+ retval = copy_to_user(buffer, &udev->brightness,
+ sizeof(udev->brightness));
+ udev->new_data = false;
+ retval = sizeof(udev->brightness);
+ }
+
+ mutex_unlock(&udev->mutex);
+
+ if (retval)
+ break;
+
+ if (!(file->f_flags & O_NONBLOCK))
+ retval = wait_event_interruptible(udev->waitq,
+ udev->new_data ||
+ udev->state != ULEDS_STATE_REGISTERED);
+ } while (retval == 0);
+
+ return retval;
+}
+
+static unsigned int uleds_poll(struct file *file, poll_table *wait)
+{
+ struct uleds_device *udev = file->private_data;
+
+ poll_wait(file, &udev->waitq, wait);
+
+ if (udev->new_data)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static int uleds_release(struct inode *inode, struct file *file)
+{
+ struct uleds_device *udev = file->private_data;
+
+ if (udev->state == ULEDS_STATE_REGISTERED) {
+ udev->state = ULEDS_STATE_UNKNOWN;
+ devm_led_classdev_unregister(uleds_misc.this_device,
+ &udev->led_cdev);
+ }
+ kfree(udev);
+
+ return 0;
+}
+
+static const struct file_operations uleds_fops = {
+ .owner = THIS_MODULE,
+ .open = uleds_open,
+ .release = uleds_release,
+ .read = uleds_read,
+ .write = uleds_write,
+ .poll = uleds_poll,
+ .llseek = no_llseek,
+};
+
+static struct miscdevice uleds_misc = {
+ .fops = &uleds_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = ULEDS_NAME,
+};
+
+static int __init uleds_init(void)
+{
+ return misc_register(&uleds_misc);
+}
+module_init(uleds_init);
+
+static void __exit uleds_exit(void)
+{
+ misc_deregister(&uleds_misc);
+}
+module_exit(uleds_exit);
+
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_DESCRIPTION("Userspace driver for the LED subsystem");
+MODULE_LICENSE("GPL");
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 19a32280731d..601f81c04873 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -109,10 +109,6 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
case LHCALL_SET_CLOCKEVENT:
guest_set_clockevent(cpu, args->arg1);
break;
- case LHCALL_TS:
- /* This sets the TS flag, as we saw used in run_guest(). */
- cpu->ts = args->arg1;
- break;
case LHCALL_HALT:
/* Similarly, this sets the halted flag for run_guest(). */
cpu->halted = 1;
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 69b3814afd2f..2356a2318034 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -43,7 +43,6 @@ struct lg_cpu {
struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
u32 cr2;
- int ts;
u32 esp1;
u16 ss1;
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 6e9042e3d2a9..743253fc638f 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -247,14 +247,6 @@ unsigned long *lguest_arch_regptr(struct lg_cpu *cpu, size_t reg_off, bool any)
void lguest_arch_run_guest(struct lg_cpu *cpu)
{
/*
- * Remember the awfully-named TS bit? If the Guest has asked to set it
- * we set it now, so we can trap and pass that trap to the Guest if it
- * uses the FPU.
- */
- if (cpu->ts && fpregs_active())
- stts();
-
- /*
* SYSENTER is an optimized way of doing system calls. We can't allow
* it because it always jumps to privilege level 0. A normal Guest
* won't try it because we don't advertise it in CPUID, but a malicious
@@ -282,10 +274,6 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
if (boot_cpu_has(X86_FEATURE_SEP))
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
- /* Clear the host TS bit if it was set above. */
- if (cpu->ts && fpregs_active())
- clts();
-
/*
* If the Guest page faulted, then the cr2 register will tell us the
* bad virtual address. We have to grab this now, because once we
@@ -421,12 +409,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
kill_guest(cpu, "Writing cr2");
break;
case 7: /* We've intercepted a Device Not Available fault. */
- /*
- * If the Guest doesn't want to know, we already restored the
- * Floating Point Unit, so we just continue without telling it.
- */
- if (!cpu->ts)
- return;
+ /* No special handling is needed here. */
break;
case 32 ... 255:
/* This might be a syscall. */
diff --git a/drivers/lightnvm/Makefile b/drivers/lightnvm/Makefile
index 1f6b6521016a..a7a0a22cf1a5 100644
--- a/drivers/lightnvm/Makefile
+++ b/drivers/lightnvm/Makefile
@@ -2,6 +2,6 @@
# Makefile for Open-Channel SSDs.
#
-obj-$(CONFIG_NVM) := core.o sysblk.o sysfs.o
+obj-$(CONFIG_NVM) := core.o sysblk.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
index 1cac0f8bc0dc..7622e3dc5d82 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -27,8 +27,6 @@
#include <linux/lightnvm.h>
#include <linux/sched/sysctl.h>
-#include "lightnvm.h"
-
static LIST_HEAD(nvm_tgt_types);
static DECLARE_RWSEM(nvm_tgtt_lock);
static LIST_HEAD(nvm_mgrs);
@@ -88,8 +86,7 @@ void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags,
}
EXPORT_SYMBOL(nvm_dev_dma_alloc);
-void nvm_dev_dma_free(struct nvm_dev *dev, void *addr,
- dma_addr_t dma_handler)
+void nvm_dev_dma_free(struct nvm_dev *dev, void *addr, dma_addr_t dma_handler)
{
dev->ops->dev_dma_free(dev->dma_pool, addr, dma_handler);
}
@@ -178,38 +175,133 @@ static struct nvm_dev *nvm_find_nvm_dev(const char *name)
return NULL;
}
-struct nvm_block *nvm_get_blk(struct nvm_dev *dev, struct nvm_lun *lun,
- unsigned long flags)
+static void nvm_tgt_generic_to_addr_mode(struct nvm_tgt_dev *tgt_dev,
+ struct nvm_rq *rqd)
{
- return dev->mt->get_blk(dev, lun, flags);
+ struct nvm_dev *dev = tgt_dev->parent;
+ int i;
+
+ if (rqd->nr_ppas > 1) {
+ for (i = 0; i < rqd->nr_ppas; i++) {
+ rqd->ppa_list[i] = dev->mt->trans_ppa(tgt_dev,
+ rqd->ppa_list[i], TRANS_TGT_TO_DEV);
+ rqd->ppa_list[i] = generic_to_dev_addr(dev,
+ rqd->ppa_list[i]);
+ }
+ } else {
+ rqd->ppa_addr = dev->mt->trans_ppa(tgt_dev, rqd->ppa_addr,
+ TRANS_TGT_TO_DEV);
+ rqd->ppa_addr = generic_to_dev_addr(dev, rqd->ppa_addr);
+ }
}
-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)
+int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
+ int type)
{
- return dev->mt->put_blk(dev, blk);
+ struct nvm_rq rqd;
+ int ret;
+
+ if (nr_ppas > dev->ops->max_phys_sect) {
+ pr_err("nvm: unable to update all sysblocks atomically\n");
+ return -EINVAL;
+ }
+
+ memset(&rqd, 0, sizeof(struct nvm_rq));
+
+ nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
+ nvm_generic_to_addr_mode(dev, &rqd);
+
+ ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
+ nvm_free_rqd_ppalist(dev, &rqd);
+ if (ret) {
+ pr_err("nvm: sysblk failed bb mark\n");
+ return -EINVAL;
+ }
+
+ return 0;
}
-EXPORT_SYMBOL(nvm_put_blk);
+EXPORT_SYMBOL(nvm_set_bb_tbl);
-void nvm_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type)
+int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
+ int nr_ppas, int type)
{
- return dev->mt->mark_blk(dev, ppa, type);
+ struct nvm_dev *dev = tgt_dev->parent;
+ struct nvm_rq rqd;
+ int ret;
+
+ if (nr_ppas > dev->ops->max_phys_sect) {
+ pr_err("nvm: unable to update all blocks atomically\n");
+ return -EINVAL;
+ }
+
+ memset(&rqd, 0, sizeof(struct nvm_rq));
+
+ nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
+ nvm_tgt_generic_to_addr_mode(tgt_dev, &rqd);
+
+ ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
+ nvm_free_rqd_ppalist(dev, &rqd);
+ if (ret) {
+ pr_err("nvm: sysblk failed bb mark\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(nvm_set_tgt_bb_tbl);
+
+int nvm_max_phys_sects(struct nvm_tgt_dev *tgt_dev)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ return dev->ops->max_phys_sect;
}
-EXPORT_SYMBOL(nvm_mark_blk);
+EXPORT_SYMBOL(nvm_max_phys_sects);
-int nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
{
- return dev->mt->submit_io(dev, rqd);
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ return dev->mt->submit_io(tgt_dev, rqd);
}
EXPORT_SYMBOL(nvm_submit_io);
-int nvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk)
+int nvm_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p, int flags)
{
- return dev->mt->erase_blk(dev, blk, 0);
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ return dev->mt->erase_blk(tgt_dev, p, flags);
}
EXPORT_SYMBOL(nvm_erase_blk);
+int nvm_get_l2p_tbl(struct nvm_tgt_dev *tgt_dev, u64 slba, u32 nlb,
+ nvm_l2p_update_fn *update_l2p, void *priv)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ if (!dev->ops->get_l2p_tbl)
+ return 0;
+
+ return dev->ops->get_l2p_tbl(dev, slba, nlb, update_l2p, priv);
+}
+EXPORT_SYMBOL(nvm_get_l2p_tbl);
+
+int nvm_get_area(struct nvm_tgt_dev *tgt_dev, sector_t *lba, sector_t len)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ return dev->mt->get_area(dev, lba, len);
+}
+EXPORT_SYMBOL(nvm_get_area);
+
+void nvm_put_area(struct nvm_tgt_dev *tgt_dev, sector_t lba)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ dev->mt->put_area(dev, lba);
+}
+EXPORT_SYMBOL(nvm_put_area);
+
void nvm_addr_to_generic_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
{
int i;
@@ -241,10 +333,11 @@ EXPORT_SYMBOL(nvm_generic_to_addr_mode);
int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd,
const struct ppa_addr *ppas, int nr_ppas, int vblk)
{
+ struct nvm_geo *geo = &dev->geo;
int i, plane_cnt, pl_idx;
struct ppa_addr ppa;
- if ((!vblk || dev->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) {
+ if ((!vblk || geo->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) {
rqd->nr_ppas = nr_ppas;
rqd->ppa_addr = ppas[0];
@@ -262,7 +355,7 @@ int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd,
for (i = 0; i < nr_ppas; i++)
rqd->ppa_list[i] = ppas[i];
} else {
- plane_cnt = dev->plane_mode;
+ plane_cnt = geo->plane_mode;
rqd->nr_ppas *= plane_cnt;
for (i = 0; i < nr_ppas; i++) {
@@ -287,7 +380,8 @@ void nvm_free_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd)
}
EXPORT_SYMBOL(nvm_free_rqd_ppalist);
-int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas)
+int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
+ int flags)
{
struct nvm_rq rqd;
int ret;
@@ -303,6 +397,8 @@ int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas)
nvm_generic_to_addr_mode(dev, &rqd);
+ rqd.flags = flags;
+
ret = dev->ops->erase_block(dev, &rqd);
nvm_free_rqd_ppalist(dev, &rqd);
@@ -341,7 +437,7 @@ static int __nvm_submit_ppa(struct nvm_dev *dev, struct nvm_rq *rqd, int opcode,
nvm_generic_to_addr_mode(dev, rqd);
- rqd->dev = dev;
+ rqd->dev = NULL;
rqd->opcode = opcode;
rqd->flags = flags;
rqd->bio = bio;
@@ -437,17 +533,18 @@ EXPORT_SYMBOL(nvm_submit_ppa);
*/
int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
{
+ struct nvm_geo *geo = &dev->geo;
int blk, offset, pl, blktype;
- if (nr_blks != dev->blks_per_lun * dev->plane_mode)
+ if (nr_blks != geo->blks_per_lun * geo->plane_mode)
return -EINVAL;
- for (blk = 0; blk < dev->blks_per_lun; blk++) {
- offset = blk * dev->plane_mode;
+ for (blk = 0; blk < geo->blks_per_lun; blk++) {
+ offset = blk * geo->plane_mode;
blktype = blks[offset];
/* Bad blocks on any planes take precedence over other types */
- for (pl = 0; pl < dev->plane_mode; pl++) {
+ for (pl = 0; pl < geo->plane_mode; pl++) {
if (blks[offset + pl] &
(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
blktype = blks[offset + pl];
@@ -458,7 +555,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
blks[blk] = blktype;
}
- return dev->blks_per_lun;
+ return geo->blks_per_lun;
}
EXPORT_SYMBOL(nvm_bb_tbl_fold);
@@ -470,11 +567,22 @@ int nvm_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, u8 *blks)
}
EXPORT_SYMBOL(nvm_get_bb_tbl);
+int nvm_get_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr ppa,
+ u8 *blks)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+
+ ppa = dev->mt->trans_ppa(tgt_dev, ppa, TRANS_TGT_TO_DEV);
+ return nvm_get_bb_tbl(dev, ppa, blks);
+}
+EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
+
static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp)
{
+ struct nvm_geo *geo = &dev->geo;
int i;
- dev->lps_per_blk = dev->pgs_per_blk;
+ dev->lps_per_blk = geo->pgs_per_blk;
dev->lptbl = kcalloc(dev->lps_per_blk, sizeof(int), GFP_KERNEL);
if (!dev->lptbl)
return -ENOMEM;
@@ -520,29 +628,32 @@ static int nvm_core_init(struct nvm_dev *dev)
{
struct nvm_id *id = &dev->identity;
struct nvm_id_group *grp = &id->groups[0];
+ struct nvm_geo *geo = &dev->geo;
int ret;
- /* 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->fpg_size = grp->fpg_sz;
- dev->pfpg_size = grp->fpg_sz * grp->num_pln;
- dev->sec_size = grp->csecs;
- dev->oob_size = grp->sos;
- dev->sec_per_pg = grp->fpg_sz / grp->csecs;
- dev->mccap = grp->mccap;
- memcpy(&dev->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
-
- dev->plane_mode = NVM_PLANE_SINGLE;
- dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size;
+ /* Whole device values */
+ geo->nr_chnls = grp->num_ch;
+ geo->luns_per_chnl = grp->num_lun;
+
+ /* Generic device values */
+ geo->pgs_per_blk = grp->num_pg;
+ geo->blks_per_lun = grp->num_blk;
+ geo->nr_planes = grp->num_pln;
+ geo->fpg_size = grp->fpg_sz;
+ geo->pfpg_size = grp->fpg_sz * grp->num_pln;
+ geo->sec_size = grp->csecs;
+ geo->oob_size = grp->sos;
+ geo->sec_per_pg = grp->fpg_sz / grp->csecs;
+ geo->mccap = grp->mccap;
+ memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
+
+ geo->plane_mode = NVM_PLANE_SINGLE;
+ geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size;
if (grp->mpos & 0x020202)
- dev->plane_mode = NVM_PLANE_DOUBLE;
+ geo->plane_mode = NVM_PLANE_DOUBLE;
if (grp->mpos & 0x040404)
- dev->plane_mode = NVM_PLANE_QUAD;
+ geo->plane_mode = NVM_PLANE_QUAD;
if (grp->mtype != 0) {
pr_err("nvm: memory type not supported\n");
@@ -550,13 +661,13 @@ static int nvm_core_init(struct nvm_dev *dev)
}
/* 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;
+ geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
+ geo->sec_per_blk = geo->sec_per_pl * geo->pgs_per_blk;
+ geo->sec_per_lun = geo->sec_per_blk * geo->blks_per_lun;
+ geo->nr_luns = geo->luns_per_chnl * geo->nr_chnls;
- dev->total_secs = dev->nr_luns * dev->sec_per_lun;
- dev->lun_map = kcalloc(BITS_TO_LONGS(dev->nr_luns),
+ dev->total_secs = geo->nr_luns * geo->sec_per_lun;
+ dev->lun_map = kcalloc(BITS_TO_LONGS(geo->nr_luns),
sizeof(unsigned long), GFP_KERNEL);
if (!dev->lun_map)
return -ENOMEM;
@@ -583,7 +694,7 @@ static int nvm_core_init(struct nvm_dev *dev)
mutex_init(&dev->mlock);
spin_lock_init(&dev->lock);
- blk_queue_logical_block_size(dev->q, dev->sec_size);
+ blk_queue_logical_block_size(dev->q, geo->sec_size);
return 0;
err_fmtype:
@@ -617,6 +728,7 @@ void nvm_free(struct nvm_dev *dev)
static int nvm_init(struct nvm_dev *dev)
{
+ struct nvm_geo *geo = &dev->geo;
int ret = -EINVAL;
if (!dev->q || !dev->ops)
@@ -648,20 +760,15 @@ static int nvm_init(struct nvm_dev *dev)
}
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);
+ dev->name, geo->sec_per_pg, geo->nr_planes,
+ geo->pgs_per_blk, geo->blks_per_lun,
+ geo->nr_luns, geo->nr_chnls);
return 0;
err:
pr_err("nvm: failed to initialize nvm\n");
return ret;
}
-static void nvm_exit(struct nvm_dev *dev)
-{
- nvm_sysfs_unregister_dev(dev);
-}
-
struct nvm_dev *nvm_alloc_dev(int node)
{
return kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node);
@@ -691,10 +798,6 @@ int nvm_register(struct nvm_dev *dev)
}
}
- ret = nvm_sysfs_register_dev(dev);
- if (ret)
- goto err_ppalist;
-
if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) {
ret = nvm_get_sysblock(dev, &dev->sb);
if (!ret)
@@ -711,8 +814,6 @@ int nvm_register(struct nvm_dev *dev)
up_write(&nvm_lock);
return 0;
-err_ppalist:
- dev->ops->destroy_dma_pool(dev->dma_pool);
err_init:
kfree(dev->lun_map);
return ret;
@@ -725,7 +826,7 @@ void nvm_unregister(struct nvm_dev *dev)
list_del(&dev->devices);
up_write(&nvm_lock);
- nvm_exit(dev);
+ nvm_free(dev);
}
EXPORT_SYMBOL(nvm_unregister);
@@ -754,149 +855,15 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create)
}
s = &create->conf.s;
- if (s->lun_begin > s->lun_end || s->lun_end > dev->nr_luns) {
+ if (s->lun_begin > s->lun_end || s->lun_end > dev->geo.nr_luns) {
pr_err("nvm: lun out of bound (%u:%u > %u)\n",
- s->lun_begin, s->lun_end, dev->nr_luns);
+ s->lun_begin, s->lun_end, dev->geo.nr_luns);
return -EINVAL;
}
return dev->mt->create_tgt(dev, create);
}
-#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;
- }
-
- down_write(&nvm_lock);
- dev = nvm_find_nvm_dev(devname);
- up_write(&nvm_lock);
- if (!dev) {
- pr_err("nvm: device not found\n");
- return -EINVAL;
- }
-
- if (!dev->mt)
- return 0;
-
- dev->mt->lun_info_print(dev);
-
- return 0;
-}
-
-static int nvm_configure_remove(const char *val)
-{
- struct nvm_ioctl_remove remove;
- struct nvm_dev *dev;
- char opcode;
- int ret = 0;
-
- 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;
-
- list_for_each_entry(dev, &nvm_devices, devices) {
- ret = dev->mt->remove_tgt(dev, &remove);
- if (!ret)
- break;
- }
-
- return ret;
-}
-
-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;
- struct nvm_dev *dev;
-
- sz = sprintf(buf, "available devices:\n");
- down_write(&nvm_lock);
- list_for_each_entry(dev, &nvm_devices, devices) {
- if (sz > 4095 - DISK_NAME_LEN - 2)
- break;
- sz += sprintf(buf + sz, " %32s\n", dev->name);
- }
- up_write(&nvm_lock);
-
- return sz;
-}
-
-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;
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c6d021..ca7880082d80 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -35,6 +35,165 @@ static const struct block_device_operations gen_fops = {
.owner = THIS_MODULE,
};
+static int gen_reserve_luns(struct nvm_dev *dev, struct nvm_target *t,
+ int lun_begin, int lun_end)
+{
+ int i;
+
+ for (i = lun_begin; i <= lun_end; i++) {
+ if (test_and_set_bit(i, dev->lun_map)) {
+ pr_err("nvm: lun %d already allocated\n", i);
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ while (--i > lun_begin)
+ clear_bit(i, dev->lun_map);
+
+ return -EBUSY;
+}
+
+static void gen_release_luns_err(struct nvm_dev *dev, int lun_begin,
+ int lun_end)
+{
+ int i;
+
+ for (i = lun_begin; i <= lun_end; i++)
+ WARN_ON(!test_and_clear_bit(i, dev->lun_map));
+}
+
+static void gen_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev)
+{
+ struct nvm_dev *dev = tgt_dev->parent;
+ struct gen_dev_map *dev_map = tgt_dev->map;
+ int i, j;
+
+ for (i = 0; i < dev_map->nr_chnls; i++) {
+ struct gen_ch_map *ch_map = &dev_map->chnls[i];
+ int *lun_offs = ch_map->lun_offs;
+ int ch = i + ch_map->ch_off;
+
+ for (j = 0; j < ch_map->nr_luns; j++) {
+ int lun = j + lun_offs[j];
+ int lunid = (ch * dev->geo.luns_per_chnl) + lun;
+
+ WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
+ }
+
+ kfree(ch_map->lun_offs);
+ }
+
+ kfree(dev_map->chnls);
+ kfree(dev_map);
+ kfree(tgt_dev->luns);
+ kfree(tgt_dev);
+}
+
+static struct nvm_tgt_dev *gen_create_tgt_dev(struct nvm_dev *dev,
+ int lun_begin, int lun_end)
+{
+ struct nvm_tgt_dev *tgt_dev = NULL;
+ struct gen_dev_map *dev_rmap = dev->rmap;
+ struct gen_dev_map *dev_map;
+ struct ppa_addr *luns;
+ int nr_luns = lun_end - lun_begin + 1;
+ int luns_left = nr_luns;
+ int nr_chnls = nr_luns / dev->geo.luns_per_chnl;
+ int nr_chnls_mod = nr_luns % dev->geo.luns_per_chnl;
+ int bch = lun_begin / dev->geo.luns_per_chnl;
+ int blun = lun_begin % dev->geo.luns_per_chnl;
+ int lunid = 0;
+ int lun_balanced = 1;
+ int prev_nr_luns;
+ int i, j;
+
+ nr_chnls = nr_luns / dev->geo.luns_per_chnl;
+ nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
+
+ dev_map = kmalloc(sizeof(struct gen_dev_map), GFP_KERNEL);
+ if (!dev_map)
+ goto err_dev;
+
+ dev_map->chnls = kcalloc(nr_chnls, sizeof(struct gen_ch_map),
+ GFP_KERNEL);
+ if (!dev_map->chnls)
+ goto err_chnls;
+
+ luns = kcalloc(nr_luns, sizeof(struct ppa_addr), GFP_KERNEL);
+ if (!luns)
+ goto err_luns;
+
+ prev_nr_luns = (luns_left > dev->geo.luns_per_chnl) ?
+ dev->geo.luns_per_chnl : luns_left;
+ for (i = 0; i < nr_chnls; i++) {
+ struct gen_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
+ int *lun_roffs = ch_rmap->lun_offs;
+ struct gen_ch_map *ch_map = &dev_map->chnls[i];
+ int *lun_offs;
+ int luns_in_chnl = (luns_left > dev->geo.luns_per_chnl) ?
+ dev->geo.luns_per_chnl : luns_left;
+
+ if (lun_balanced && prev_nr_luns != luns_in_chnl)
+ lun_balanced = 0;
+
+ ch_map->ch_off = ch_rmap->ch_off = bch;
+ ch_map->nr_luns = luns_in_chnl;
+
+ lun_offs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
+ if (!lun_offs)
+ goto err_ch;
+
+ for (j = 0; j < luns_in_chnl; j++) {
+ luns[lunid].ppa = 0;
+ luns[lunid].g.ch = i;
+ luns[lunid++].g.lun = j;
+
+ lun_offs[j] = blun;
+ lun_roffs[j + blun] = blun;
+ }
+
+ ch_map->lun_offs = lun_offs;
+
+ /* when starting a new channel, lun offset is reset */
+ blun = 0;
+ luns_left -= luns_in_chnl;
+ }
+
+ dev_map->nr_chnls = nr_chnls;
+
+ tgt_dev = kmalloc(sizeof(struct nvm_tgt_dev), GFP_KERNEL);
+ if (!tgt_dev)
+ goto err_ch;
+
+ memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
+ /* Target device only owns a portion of the physical device */
+ tgt_dev->geo.nr_chnls = nr_chnls;
+ tgt_dev->geo.nr_luns = nr_luns;
+ tgt_dev->geo.luns_per_chnl = (lun_balanced) ? prev_nr_luns : -1;
+ tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
+ tgt_dev->q = dev->q;
+ tgt_dev->map = dev_map;
+ tgt_dev->luns = luns;
+ memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
+
+ tgt_dev->parent = dev;
+
+ return tgt_dev;
+err_ch:
+ while (--i > 0)
+ kfree(dev_map->chnls[i].lun_offs);
+ kfree(luns);
+err_luns:
+ kfree(dev_map->chnls);
+err_chnls:
+ kfree(dev_map);
+err_dev:
+ return tgt_dev;
+}
+
static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
{
struct gen_dev *gn = dev->mp;
@@ -43,6 +202,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
struct gendisk *tdisk;
struct nvm_tgt_type *tt;
struct nvm_target *t;
+ struct nvm_tgt_dev *tgt_dev;
void *targetdata;
tt = nvm_find_target_type(create->tgttype, 1);
@@ -64,9 +224,18 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
if (!t)
return -ENOMEM;
+ if (gen_reserve_luns(dev, t, s->lun_begin, s->lun_end))
+ goto err_t;
+
+ tgt_dev = gen_create_tgt_dev(dev, s->lun_begin, s->lun_end);
+ if (!tgt_dev) {
+ pr_err("nvm: could not create target device\n");
+ goto err_reserve;
+ }
+
tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node);
if (!tqueue)
- goto err_t;
+ goto err_dev;
blk_queue_make_request(tqueue, tt->make_rq);
tdisk = alloc_disk(0);
@@ -80,7 +249,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
tdisk->fops = &gen_fops;
tdisk->queue = tqueue;
- targetdata = tt->init(dev, tdisk, s->lun_begin, s->lun_end);
+ targetdata = tt->init(tgt_dev, tdisk);
if (IS_ERR(targetdata))
goto err_init;
@@ -94,7 +263,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
t->type = tt;
t->disk = tdisk;
- t->dev = dev;
+ t->dev = tgt_dev;
mutex_lock(&gn->lock);
list_add_tail(&t->list, &gn->targets);
@@ -105,6 +274,10 @@ err_init:
put_disk(tdisk);
err_queue:
blk_cleanup_queue(tqueue);
+err_dev:
+ kfree(tgt_dev);
+err_reserve:
+ gen_release_luns_err(dev, s->lun_begin, s->lun_end);
err_t:
kfree(t);
return -ENOMEM;
@@ -122,6 +295,7 @@ static void __gen_remove_target(struct nvm_target *t)
if (tt->exit)
tt->exit(tdisk->private_data);
+ gen_remove_tgt_dev(t->dev);
put_disk(tdisk);
list_del(&t->list);
@@ -160,10 +334,11 @@ static int gen_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
static int gen_get_area(struct nvm_dev *dev, sector_t *lba, sector_t len)
{
+ struct nvm_geo *geo = &dev->geo;
struct gen_dev *gn = dev->mp;
struct gen_area *area, *prev, *next;
sector_t begin = 0;
- sector_t max_sectors = (dev->sec_size * dev->total_secs) >> 9;
+ sector_t max_sectors = (geo->sec_size * dev->total_secs) >> 9;
if (len > max_sectors)
return -EINVAL;
@@ -220,240 +395,74 @@ static void gen_put_area(struct nvm_dev *dev, sector_t begin)
spin_unlock(&dev->lock);
}
-static void gen_blocks_free(struct nvm_dev *dev)
-{
- struct gen_dev *gn = dev->mp;
- struct gen_lun *lun;
- int i;
-
- gen_for_each_lun(gn, lun, i) {
- if (!lun->vlun.blocks)
- break;
- vfree(lun->vlun.blocks);
- }
-}
-
-static void gen_luns_free(struct nvm_dev *dev)
-{
- struct gen_dev *gn = dev->mp;
-
- kfree(gn->luns);
-}
-
-static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn)
-{
- struct gen_lun *lun;
- int i;
-
- gn->luns = kcalloc(dev->nr_luns, sizeof(struct gen_lun), GFP_KERNEL);
- if (!gn->luns)
- return -ENOMEM;
-
- gen_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 gen_block_bb(struct gen_dev *gn, struct ppa_addr ppa,
- u8 *blks, int nr_blks)
-{
- struct nvm_dev *dev = gn->dev;
- struct gen_lun *lun;
- struct nvm_block *blk;
- int i;
-
- nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks);
- if (nr_blks < 0)
- return nr_blks;
-
- lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun];
-
- for (i = 0; i < nr_blks; i++) {
- if (blks[i] == 0)
- continue;
-
- blk = &lun->vlun.blocks[i];
- list_move_tail(&blk->list, &lun->bb_list);
- lun->vlun.nr_free_blocks--;
- }
-
- return 0;
-}
-
-static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private)
-{
- struct nvm_dev *dev = private;
- struct gen_dev *gn = dev->mp;
- u64 elba = slba + nlb;
- struct gen_lun *lun;
- struct nvm_block *blk;
- u64 i;
- int lun_id;
-
- if (unlikely(elba > dev->total_secs)) {
- pr_err("gen: 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 >= dev->total_secs && pba != U64_MAX)) {
- pr_err("gen: 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->state) {
- /* 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. The block is assumed to be open.
- */
- list_move_tail(&blk->list, &lun->used_list);
- blk->state = NVM_BLK_ST_TGT;
- lun->vlun.nr_free_blocks--;
- }
- }
-
- return 0;
-}
-
-static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn)
-{
- struct gen_lun *lun;
- struct nvm_block *block;
- sector_t lun_iter, blk_iter, cur_block_id = 0;
- int ret, nr_blks;
- u8 *blks;
-
- nr_blks = dev->blks_per_lun * dev->plane_mode;
- blks = kmalloc(nr_blks, GFP_KERNEL);
- if (!blks)
- return -ENOMEM;
-
- gen_for_each_lun(gn, lun, lun_iter) {
- lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) *
- dev->blks_per_lun);
- if (!lun->vlun.blocks) {
- kfree(blks);
- 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)) {
- lun->vlun.nr_free_blocks--;
- continue;
- }
-
- list_add_tail(&block->list, &lun->free_list);
- }
-
- if (dev->ops->get_bb_tbl) {
- struct ppa_addr ppa;
-
- ppa.ppa = 0;
- ppa.g.ch = lun->vlun.chnl_id;
- ppa.g.lun = lun->vlun.lun_id;
-
- ret = nvm_get_bb_tbl(dev, ppa, blks);
- if (ret)
- pr_err("gen: could not get BB table\n");
-
- ret = gen_block_bb(gn, ppa, blks, nr_blks);
- if (ret)
- pr_err("gen: BB table map failed\n");
- }
- }
-
- if ((dev->identity.dom & NVM_RSP_L2P) && dev->ops->get_l2p_tbl) {
- ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_secs,
- gen_block_map, dev);
- if (ret) {
- pr_err("gen: could not read L2P table.\n");
- pr_warn("gen: default block initialization");
- }
- }
-
- kfree(blks);
- return 0;
-}
-
static void gen_free(struct nvm_dev *dev)
{
- gen_blocks_free(dev);
- gen_luns_free(dev);
kfree(dev->mp);
+ kfree(dev->rmap);
dev->mp = NULL;
}
static int gen_register(struct nvm_dev *dev)
{
struct gen_dev *gn;
- int ret;
+ struct gen_dev_map *dev_rmap;
+ int i, j;
if (!try_module_get(THIS_MODULE))
return -ENODEV;
gn = kzalloc(sizeof(struct gen_dev), GFP_KERNEL);
if (!gn)
- return -ENOMEM;
+ goto err_gn;
+
+ dev_rmap = kmalloc(sizeof(struct gen_dev_map), GFP_KERNEL);
+ if (!dev_rmap)
+ goto err_rmap;
+
+ dev_rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct gen_ch_map),
+ GFP_KERNEL);
+ if (!dev_rmap->chnls)
+ goto err_chnls;
+
+ for (i = 0; i < dev->geo.nr_chnls; i++) {
+ struct gen_ch_map *ch_rmap;
+ int *lun_roffs;
+ int luns_in_chnl = dev->geo.luns_per_chnl;
+
+ ch_rmap = &dev_rmap->chnls[i];
+
+ ch_rmap->ch_off = -1;
+ ch_rmap->nr_luns = luns_in_chnl;
+
+ lun_roffs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
+ if (!lun_roffs)
+ goto err_ch;
+
+ for (j = 0; j < luns_in_chnl; j++)
+ lun_roffs[j] = -1;
+
+ ch_rmap->lun_offs = lun_roffs;
+ }
gn->dev = dev;
- gn->nr_luns = dev->nr_luns;
+ gn->nr_luns = dev->geo.nr_luns;
INIT_LIST_HEAD(&gn->area_list);
mutex_init(&gn->lock);
INIT_LIST_HEAD(&gn->targets);
dev->mp = gn;
-
- ret = gen_luns_init(dev, gn);
- if (ret) {
- pr_err("gen: could not initialize luns\n");
- goto err;
- }
-
- ret = gen_blocks_init(dev, gn);
- if (ret) {
- pr_err("gen: could not initialize blocks\n");
- goto err;
- }
+ dev->rmap = dev_rmap;
return 1;
-err:
+err_ch:
+ while (--i >= 0)
+ kfree(dev_rmap->chnls[i].lun_offs);
+err_chnls:
+ kfree(dev_rmap);
+err_rmap:
gen_free(dev);
+err_gn:
module_put(THIS_MODULE);
- return ret;
+ return -ENOMEM;
}
static void gen_unregister(struct nvm_dev *dev)
@@ -463,7 +472,7 @@ static void gen_unregister(struct nvm_dev *dev)
mutex_lock(&gn->lock);
list_for_each_entry_safe(t, tmp, &gn->targets, list) {
- if (t->dev != dev)
+ if (t->dev->parent != dev)
continue;
__gen_remove_target(t);
}
@@ -473,168 +482,142 @@ static void gen_unregister(struct nvm_dev *dev)
module_put(THIS_MODULE);
}
-static struct nvm_block *gen_get_blk(struct nvm_dev *dev,
- struct nvm_lun *vlun, unsigned long flags)
+static int gen_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
{
- 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("gen: lun %u have no free pages available",
- lun->vlun.id);
- goto out;
+ struct gen_dev_map *dev_map = tgt_dev->map;
+ struct gen_ch_map *ch_map = &dev_map->chnls[p->g.ch];
+ int lun_off = ch_map->lun_offs[p->g.lun];
+ struct nvm_dev *dev = tgt_dev->parent;
+ struct gen_dev_map *dev_rmap = dev->rmap;
+ struct gen_ch_map *ch_rmap;
+ int lun_roff;
+
+ p->g.ch += ch_map->ch_off;
+ p->g.lun += lun_off;
+
+ ch_rmap = &dev_rmap->chnls[p->g.ch];
+ lun_roff = ch_rmap->lun_offs[p->g.lun];
+
+ if (unlikely(ch_rmap->ch_off < 0 || lun_roff < 0)) {
+ pr_err("nvm: corrupted device partition table\n");
+ return -EINVAL;
}
- if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks)
- goto out;
-
- blk = list_first_entry(&lun->free_list, struct nvm_block, list);
-
- list_move_tail(&blk->list, &lun->used_list);
- blk->state = NVM_BLK_ST_TGT;
- lun->vlun.nr_free_blocks--;
-out:
- spin_unlock(&vlun->lock);
- return blk;
-}
-
-static void gen_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);
- if (blk->state & NVM_BLK_ST_TGT) {
- list_move_tail(&blk->list, &lun->free_list);
- lun->vlun.nr_free_blocks++;
- blk->state = NVM_BLK_ST_FREE;
- } else if (blk->state & NVM_BLK_ST_BAD) {
- list_move_tail(&blk->list, &lun->bb_list);
- blk->state = NVM_BLK_ST_BAD;
- } else {
- WARN_ON_ONCE(1);
- pr_err("gen: erroneous block type (%lu -> %u)\n",
- blk->id, blk->state);
- list_move_tail(&blk->list, &lun->bb_list);
- }
- spin_unlock(&vlun->lock);
+ return 0;
}
-static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type)
+static int gen_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
{
- struct gen_dev *gn = dev->mp;
- struct gen_lun *lun;
- struct nvm_block *blk;
-
- pr_debug("gen: ppa (ch: %u lun: %u blk: %u pg: %u) -> %u\n",
- ppa.g.ch, ppa.g.lun, ppa.g.blk, ppa.g.pg, type);
-
- 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("gen: 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;
- }
+ struct nvm_dev *dev = tgt_dev->parent;
+ struct gen_dev_map *dev_rmap = dev->rmap;
+ struct gen_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
+ int lun_roff = ch_rmap->lun_offs[p->g.lun];
- lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun];
- blk = &lun->vlun.blocks[ppa.g.blk];
+ p->g.ch -= ch_rmap->ch_off;
+ p->g.lun -= lun_roff;
- /* will be moved to bb list on put_blk from target */
- blk->state = type;
+ return 0;
}
-/*
- * mark block bad in gen. It is expected that the target recovers separately
- */
-static void gen_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
+static int gen_trans_rq(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
+ int flag)
{
- int bit = -1;
- int max_secs = dev->ops->max_phys_sect;
- void *comp_bits = &rqd->ppa_status;
+ gen_trans_fn *f;
+ int i;
+ int ret = 0;
- nvm_addr_to_generic_mode(dev, rqd);
+ f = (flag == TRANS_TGT_TO_DEV) ? gen_map_to_dev : gen_map_to_tgt;
- /* look up blocks and mark them as bad */
- if (rqd->nr_ppas == 1) {
- gen_mark_blk(dev, rqd->ppa_addr, NVM_BLK_ST_BAD);
- return;
+ if (rqd->nr_ppas == 1)
+ return f(tgt_dev, &rqd->ppa_addr);
+
+ for (i = 0; i < rqd->nr_ppas; i++) {
+ ret = f(tgt_dev, &rqd->ppa_list[i]);
+ if (ret)
+ goto out;
}
- while ((bit = find_next_bit(comp_bits, max_secs, bit + 1)) < max_secs)
- gen_mark_blk(dev, rqd->ppa_list[bit], NVM_BLK_ST_BAD);
+out:
+ return ret;
}
static void gen_end_io(struct nvm_rq *rqd)
{
+ struct nvm_tgt_dev *tgt_dev = rqd->dev;
struct nvm_tgt_instance *ins = rqd->ins;
- if (rqd->error == NVM_RSP_ERR_FAILWRITE)
- gen_mark_blk_bad(rqd->dev, rqd);
+ /* Convert address space */
+ if (tgt_dev)
+ gen_trans_rq(tgt_dev, rqd, TRANS_DEV_TO_TGT);
ins->tt->end_io(rqd);
}
-static int gen_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+static int gen_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
{
+ struct nvm_dev *dev = tgt_dev->parent;
+
if (!dev->ops->submit_io)
return -ENODEV;
/* Convert address space */
+ gen_trans_rq(tgt_dev, rqd, TRANS_TGT_TO_DEV);
nvm_generic_to_addr_mode(dev, rqd);
- rqd->dev = dev;
+ rqd->dev = tgt_dev;
rqd->end_io = gen_end_io;
return dev->ops->submit_io(dev, rqd);
}
-static int gen_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,
- unsigned long flags)
+static int gen_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p,
+ int flags)
{
- struct ppa_addr addr = block_to_ppa(dev, blk);
+ /* Convert address space */
+ gen_map_to_dev(tgt_dev, p);
- return nvm_erase_ppa(dev, &addr, 1);
+ return nvm_erase_ppa(tgt_dev->parent, p, 1, flags);
}
-static int gen_reserve_lun(struct nvm_dev *dev, int lunid)
+static struct ppa_addr gen_trans_ppa(struct nvm_tgt_dev *tgt_dev,
+ struct ppa_addr p, int direction)
{
- return test_and_set_bit(lunid, dev->lun_map);
-}
+ gen_trans_fn *f;
+ struct ppa_addr ppa = p;
-static void gen_release_lun(struct nvm_dev *dev, int lunid)
-{
- WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
+ f = (direction == TRANS_TGT_TO_DEV) ? gen_map_to_dev : gen_map_to_tgt;
+ f(tgt_dev, &ppa);
+
+ return ppa;
}
-static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid)
+static void gen_part_to_tgt(struct nvm_dev *dev, sector_t *entries,
+ int len)
{
- struct gen_dev *gn = dev->mp;
-
- if (unlikely(lunid >= dev->nr_luns))
- return NULL;
+ struct nvm_geo *geo = &dev->geo;
+ struct gen_dev_map *dev_rmap = dev->rmap;
+ u64 i;
- return &gn->luns[lunid].vlun;
-}
+ for (i = 0; i < len; i++) {
+ struct gen_ch_map *ch_rmap;
+ int *lun_roffs;
+ struct ppa_addr gaddr;
+ u64 pba = le64_to_cpu(entries[i]);
+ int off;
+ u64 diff;
-static void gen_lun_info_print(struct nvm_dev *dev)
-{
- struct gen_dev *gn = dev->mp;
- struct gen_lun *lun;
- unsigned int i;
+ if (!pba)
+ continue;
+ gaddr = linear_to_generic_addr(geo, pba);
+ ch_rmap = &dev_rmap->chnls[gaddr.g.ch];
+ lun_roffs = ch_rmap->lun_offs;
- gen_for_each_lun(gn, lun, i) {
- spin_lock(&lun->vlun.lock);
+ off = gaddr.g.ch * geo->luns_per_chnl + gaddr.g.lun;
- pr_info("%s: lun%8u\t%u\n", dev->name, i,
- lun->vlun.nr_free_blocks);
+ diff = ((ch_rmap->ch_off * geo->luns_per_chnl) +
+ (lun_roffs[gaddr.g.lun])) * geo->sec_per_lun;
- spin_unlock(&lun->vlun.lock);
+ entries[i] -= cpu_to_le64(diff);
}
}
@@ -648,22 +631,14 @@ static struct nvmm_type gen = {
.create_tgt = gen_create_tgt,
.remove_tgt = gen_remove_tgt,
- .get_blk = gen_get_blk,
- .put_blk = gen_put_blk,
-
.submit_io = gen_submit_io,
.erase_blk = gen_erase_blk,
- .mark_blk = gen_mark_blk,
-
- .get_lun = gen_get_lun,
- .reserve_lun = gen_reserve_lun,
- .release_lun = gen_release_lun,
- .lun_info_print = gen_lun_info_print,
-
.get_area = gen_get_area,
.put_area = gen_put_area,
+ .trans_ppa = gen_trans_ppa,
+ .part_to_tgt = gen_part_to_tgt,
};
static int __init gen_module_init(void)
diff --git a/drivers/lightnvm/gennvm.h b/drivers/lightnvm/gennvm.h
index 8ecfa817d21d..6a4b3f368848 100644
--- a/drivers/lightnvm/gennvm.h
+++ b/drivers/lightnvm/gennvm.h
@@ -20,37 +20,41 @@
#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_dev {
struct nvm_dev *dev;
int nr_luns;
- struct gen_lun *luns;
struct list_head area_list;
struct mutex lock;
struct list_head targets;
};
+/* Map between virtual and physical channel and lun */
+struct gen_ch_map {
+ int ch_off;
+ int nr_luns;
+ int *lun_offs;
+};
+
+struct gen_dev_map {
+ struct gen_ch_map *chnls;
+ int nr_chnls;
+};
+
struct gen_area {
struct list_head list;
sector_t begin;
sector_t end; /* end is excluded */
};
+static inline void *ch_map_to_lun_offs(struct gen_ch_map *ch_map)
+{
+ return ch_map + 1;
+}
+
+typedef int (gen_trans_fn)(struct nvm_tgt_dev *, struct ppa_addr *);
+
#define gen_for_each_lun(bm, lun, i) \
for ((i) = 0, lun = &(bm)->luns[0]; \
(i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)])
diff --git a/drivers/lightnvm/lightnvm.h b/drivers/lightnvm/lightnvm.h
deleted file mode 100644
index 305c181509a6..000000000000
--- a/drivers/lightnvm/lightnvm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 CNEX Labs. All rights reserved.
- * Initial release: Matias Bjorling <matias@cnexlabs.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; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- */
-
-#ifndef LIGHTNVM_H
-#define LIGHTNVM_H
-
-#include <linux/lightnvm.h>
-
-/* core -> sysfs.c */
-int __must_check nvm_sysfs_register_dev(struct nvm_dev *);
-void nvm_sysfs_unregister_dev(struct nvm_dev *);
-int nvm_sysfs_register(void);
-void nvm_sysfs_unregister(void);
-
-/* sysfs > core */
-void nvm_free(struct nvm_dev *);
-
-#endif
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 37fcaadbf80c..9fb7de395915 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -28,6 +28,7 @@ static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
static void rrpc_page_invalidate(struct rrpc *rrpc, struct rrpc_addr *a)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_block *rblk = a->rblk;
unsigned int pg_offset;
@@ -38,13 +39,13 @@ static void rrpc_page_invalidate(struct rrpc *rrpc, struct rrpc_addr *a)
spin_lock(&rblk->lock);
- div_u64_rem(a->addr, rrpc->dev->sec_per_blk, &pg_offset);
+ div_u64_rem(a->addr, dev->geo.sec_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;
+ rrpc->rev_trans_map[a->addr].addr = ADDR_EMPTY;
}
static void rrpc_invalidate_range(struct rrpc *rrpc, sector_t slba,
@@ -116,62 +117,35 @@ static void rrpc_discard(struct rrpc *rrpc, struct bio *bio)
static int block_is_full(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- return (rblk->next_page == rrpc->dev->sec_per_blk);
+ struct nvm_tgt_dev *dev = rrpc->dev;
+
+ return (rblk->next_page == dev->geo.sec_per_blk);
}
/* Calculate relative addr for the given block, considering instantiated LUNs */
static u64 block_to_rel_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- struct nvm_block *blk = rblk->parent;
- int lun_blk = blk->id % (rrpc->dev->blks_per_lun * rrpc->nr_luns);
-
- return lun_blk * rrpc->dev->sec_per_blk;
-}
-
-/* Calculate global addr for the given block */
-static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
-{
- struct nvm_block *blk = rblk->parent;
-
- return blk->id * rrpc->dev->sec_per_blk;
-}
-
-static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev,
- struct ppa_addr r)
-{
- struct ppa_addr l;
- int secs, pgs, blks, luns;
- sector_t ppa = r.ppa;
-
- l.ppa = 0;
-
- div_u64_rem(ppa, dev->sec_per_pg, &secs);
- l.g.sec = secs;
-
- sector_div(ppa, dev->sec_per_pg);
- div_u64_rem(ppa, dev->pgs_per_blk, &pgs);
- l.g.pg = pgs;
-
- sector_div(ppa, dev->pgs_per_blk);
- div_u64_rem(ppa, dev->blks_per_lun, &blks);
- l.g.blk = blks;
-
- sector_div(ppa, dev->blks_per_lun);
- div_u64_rem(ppa, dev->luns_per_chnl, &luns);
- l.g.lun = luns;
-
- sector_div(ppa, dev->luns_per_chnl);
- l.g.ch = ppa;
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct rrpc_lun *rlun = rblk->rlun;
- return l;
+ return rlun->id * dev->geo.sec_per_blk;
}
-static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr)
+static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_tgt_dev *dev,
+ struct rrpc_addr *gp)
{
+ struct rrpc_block *rblk = gp->rblk;
+ struct rrpc_lun *rlun = rblk->rlun;
+ u64 addr = gp->addr;
struct ppa_addr paddr;
paddr.ppa = addr;
- return linear_to_generic_addr(dev, paddr);
+ paddr = rrpc_linear_to_generic_addr(&dev->geo, paddr);
+ paddr.g.ch = rlun->bppa.g.ch;
+ paddr.g.lun = rlun->bppa.g.lun;
+ paddr.g.blk = rblk->id;
+
+ return paddr;
}
/* requires lun->lock taken */
@@ -188,21 +162,47 @@ static void rrpc_set_lun_cur(struct rrpc_lun *rlun, struct rrpc_block *new_rblk,
*cur_rblk = new_rblk;
}
+static struct rrpc_block *__rrpc_get_blk(struct rrpc *rrpc,
+ struct rrpc_lun *rlun)
+{
+ struct rrpc_block *rblk = NULL;
+
+ if (list_empty(&rlun->free_list))
+ goto out;
+
+ rblk = list_first_entry(&rlun->free_list, struct rrpc_block, list);
+
+ list_move_tail(&rblk->list, &rlun->used_list);
+ rblk->state = NVM_BLK_ST_TGT;
+ rlun->nr_free_blocks--;
+
+out:
+ return rblk;
+}
+
static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun,
unsigned long flags)
{
- struct nvm_block *blk;
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_block *rblk;
+ int is_gc = flags & NVM_IOTYPE_GC;
+
+ spin_lock(&rlun->lock);
+ if (!is_gc && rlun->nr_free_blocks < rlun->reserved_blocks) {
+ pr_err("nvm: rrpc: cannot give block to non GC request\n");
+ spin_unlock(&rlun->lock);
+ return NULL;
+ }
- blk = nvm_get_blk(rrpc->dev, rlun->parent, flags);
- if (!blk) {
- pr_err("nvm: rrpc: cannot get new block from media manager\n");
+ rblk = __rrpc_get_blk(rrpc, rlun);
+ if (!rblk) {
+ pr_err("nvm: rrpc: cannot get new block\n");
+ spin_unlock(&rlun->lock);
return NULL;
}
+ spin_unlock(&rlun->lock);
- rblk = rrpc_get_rblk(rlun, blk->id);
- blk->priv = rblk;
- bitmap_zero(rblk->invalid_pages, rrpc->dev->sec_per_blk);
+ bitmap_zero(rblk->invalid_pages, dev->geo.sec_per_blk);
rblk->next_page = 0;
rblk->nr_invalid_pages = 0;
atomic_set(&rblk->data_cmnt_size, 0);
@@ -212,7 +212,24 @@ static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun,
static void rrpc_put_blk(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- nvm_put_blk(rrpc->dev, rblk->parent);
+ struct rrpc_lun *rlun = rblk->rlun;
+
+ spin_lock(&rlun->lock);
+ if (rblk->state & NVM_BLK_ST_TGT) {
+ list_move_tail(&rblk->list, &rlun->free_list);
+ rlun->nr_free_blocks++;
+ rblk->state = NVM_BLK_ST_FREE;
+ } else if (rblk->state & NVM_BLK_ST_BAD) {
+ list_move_tail(&rblk->list, &rlun->bb_list);
+ rblk->state = NVM_BLK_ST_BAD;
+ } else {
+ WARN_ON_ONCE(1);
+ pr_err("rrpc: erroneous type (ch:%d,lun:%d,blk%d-> %u)\n",
+ rlun->bppa.g.ch, rlun->bppa.g.lun,
+ rblk->id, rblk->state);
+ list_move_tail(&rblk->list, &rlun->bb_list);
+ }
+ spin_unlock(&rlun->lock);
}
static void rrpc_put_blks(struct rrpc *rrpc)
@@ -280,13 +297,14 @@ static void rrpc_end_sync_bio(struct bio *bio)
*/
static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- struct request_queue *q = rrpc->dev->q;
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct request_queue *q = dev->q;
struct rrpc_rev_addr *rev;
struct nvm_rq *rqd;
struct bio *bio;
struct page *page;
int slot;
- int nr_sec_per_blk = rrpc->dev->sec_per_blk;
+ int nr_sec_per_blk = dev->geo.sec_per_blk;
u64 phys_addr;
DECLARE_COMPLETION_ONSTACK(wait);
@@ -309,12 +327,12 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk)
nr_sec_per_blk)) < nr_sec_per_blk) {
/* Lock laddr */
- phys_addr = rblk->parent->id * nr_sec_per_blk + slot;
+ phys_addr = rrpc_blk_to_ppa(rrpc, rblk) + slot;
try:
spin_lock(&rrpc->rev_lock);
/* Get logical address from physical to logical table */
- rev = &rrpc->rev_trans_map[phys_addr - rrpc->poffset];
+ rev = &rrpc->rev_trans_map[phys_addr];
/* already updated by previous regular write */
if (rev->addr == ADDR_EMPTY) {
spin_unlock(&rrpc->rev_lock);
@@ -396,15 +414,23 @@ static void rrpc_block_gc(struct work_struct *work)
struct rrpc *rrpc = gcb->rrpc;
struct rrpc_block *rblk = gcb->rblk;
struct rrpc_lun *rlun = rblk->rlun;
- struct nvm_dev *dev = rrpc->dev;
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct ppa_addr ppa;
mempool_free(gcb, rrpc->gcb_pool);
- pr_debug("nvm: block '%lu' being reclaimed\n", rblk->parent->id);
+ pr_debug("nvm: block 'ch:%d,lun:%d,blk:%d' being reclaimed\n",
+ rlun->bppa.g.ch, rlun->bppa.g.lun,
+ rblk->id);
if (rrpc_move_valid_pages(rrpc, rblk))
goto put_back;
- if (nvm_erase_blk(dev, rblk->parent))
+ ppa.ppa = 0;
+ ppa.g.ch = rlun->bppa.g.ch;
+ ppa.g.lun = rlun->bppa.g.lun;
+ ppa.g.blk = rblk->id;
+
+ if (nvm_erase_blk(dev, &ppa, 0))
goto put_back;
rrpc_put_blk(rrpc, rblk);
@@ -420,7 +446,7 @@ put_back:
/* 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,
+static struct rrpc_block *rblk_max_invalid(struct rrpc_block *ra,
struct rrpc_block *rb)
{
if (ra->nr_invalid_pages == rb->nr_invalid_pages)
@@ -435,13 +461,13 @@ static struct rrpc_block *rblock_max_invalid(struct rrpc_block *ra,
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;
+ struct rrpc_block *rblk, *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);
+ list_for_each_entry(rblk, prio_list, prio)
+ max = rblk_max_invalid(max, rblk);
return max;
}
@@ -450,36 +476,37 @@ 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 nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_block_gc *gcb;
unsigned int nr_blocks_need;
- nr_blocks_need = rrpc->dev->blks_per_lun / GC_LIMIT_INVERSE;
+ nr_blocks_need = dev->geo.blks_per_lun / GC_LIMIT_INVERSE;
if (nr_blocks_need < rrpc->nr_luns)
nr_blocks_need = rrpc->nr_luns;
spin_lock(&rlun->lock);
- while (nr_blocks_need > lun->nr_free_blocks &&
+ while (nr_blocks_need > rlun->nr_free_blocks &&
!list_empty(&rlun->prio_list)) {
- struct rrpc_block *rblock = block_prio_find_max(rlun);
- struct nvm_block *block = rblock->parent;
+ struct rrpc_block *rblk = block_prio_find_max(rlun);
- if (!rblock->nr_invalid_pages)
+ if (!rblk->nr_invalid_pages)
break;
gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
if (!gcb)
break;
- list_del_init(&rblock->prio);
+ list_del_init(&rblk->prio);
- BUG_ON(!block_is_full(rrpc, rblock));
+ WARN_ON(!block_is_full(rrpc, rblk));
- pr_debug("rrpc: selected block '%lu' for GC\n", block->id);
+ pr_debug("rrpc: selected block 'ch:%d,lun:%d,blk:%d' for GC\n",
+ rlun->bppa.g.ch, rlun->bppa.g.lun,
+ rblk->id);
gcb->rrpc = rrpc;
- gcb->rblk = rblock;
+ gcb->rblk = rblk;
INIT_WORK(&gcb->ws_gc, rrpc_block_gc);
queue_work(rrpc->kgc_wq, &gcb->ws_gc);
@@ -504,8 +531,9 @@ static void rrpc_gc_queue(struct work_struct *work)
spin_unlock(&rlun->lock);
mempool_free(gcb, rrpc->gcb_pool);
- pr_debug("nvm: block '%lu' is full, allow GC (sched)\n",
- rblk->parent->id);
+ pr_debug("nvm: block 'ch:%d,lun:%d,blk:%d' full, allow GC (sched)\n",
+ rlun->bppa.g.ch, rlun->bppa.g.lun,
+ rblk->id);
}
static const struct block_device_operations rrpc_fops = {
@@ -529,8 +557,7 @@ static struct rrpc_lun *rrpc_get_lun_rr(struct rrpc *rrpc, int is_gc)
* estimate.
*/
rrpc_for_each_lun(rrpc, rlun, i) {
- if (rlun->parent->nr_free_blocks >
- max_free->parent->nr_free_blocks)
+ if (rlun->nr_free_blocks > max_free->nr_free_blocks)
max_free = rlun;
}
@@ -553,7 +580,7 @@ static struct rrpc_addr *rrpc_update_map(struct rrpc *rrpc, sector_t laddr,
gp->addr = paddr;
gp->rblk = rblk;
- rev = &rrpc->rev_trans_map[gp->addr - rrpc->poffset];
+ rev = &rrpc->rev_trans_map[gp->addr];
rev->addr = laddr;
spin_unlock(&rrpc->rev_lock);
@@ -568,7 +595,7 @@ static u64 rrpc_alloc_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
if (block_is_full(rrpc, rblk))
goto out;
- addr = block_to_addr(rrpc, rblk) + rblk->next_page;
+ addr = rblk->next_page;
rblk->next_page++;
out:
@@ -582,20 +609,22 @@ out:
* Returns rrpc_addr with the physical address and block. Returns NULL if no
* blocks in the next rlun are available.
*/
-static struct rrpc_addr *rrpc_map_page(struct rrpc *rrpc, sector_t laddr,
+static struct ppa_addr rrpc_map_page(struct rrpc *rrpc, sector_t laddr,
int is_gc)
{
+ struct nvm_tgt_dev *tgt_dev = rrpc->dev;
struct rrpc_lun *rlun;
struct rrpc_block *rblk, **cur_rblk;
- struct nvm_lun *lun;
+ struct rrpc_addr *p;
+ struct ppa_addr ppa;
u64 paddr;
int gc_force = 0;
+ ppa.ppa = ADDR_EMPTY;
rlun = rrpc_get_lun_rr(rrpc, is_gc);
- lun = rlun->parent;
- if (!is_gc && lun->nr_free_blocks < rrpc->nr_luns * 4)
- return NULL;
+ if (!is_gc && rlun->nr_free_blocks < rrpc->nr_luns * 4)
+ return ppa;
/*
* page allocation steps:
@@ -652,10 +681,15 @@ new_blk:
}
pr_err("rrpc: failed to allocate new block\n");
- return NULL;
+ return ppa;
done:
spin_unlock(&rlun->lock);
- return rrpc_update_map(rrpc, laddr, rblk, paddr);
+ p = rrpc_update_map(rrpc, laddr, rblk, paddr);
+ if (!p)
+ return ppa;
+
+ /* return global address */
+ return rrpc_ppa_to_gaddr(tgt_dev, p);
}
static void rrpc_run_gc(struct rrpc *rrpc, struct rrpc_block *rblk)
@@ -675,21 +709,70 @@ static void rrpc_run_gc(struct rrpc *rrpc, struct rrpc_block *rblk)
queue_work(rrpc->kgc_wq, &gcb->ws_gc);
}
+static struct rrpc_lun *rrpc_ppa_to_lun(struct rrpc *rrpc, struct ppa_addr p)
+{
+ struct rrpc_lun *rlun = NULL;
+ int i;
+
+ for (i = 0; i < rrpc->nr_luns; i++) {
+ if (rrpc->luns[i].bppa.g.ch == p.g.ch &&
+ rrpc->luns[i].bppa.g.lun == p.g.lun) {
+ rlun = &rrpc->luns[i];
+ break;
+ }
+ }
+
+ return rlun;
+}
+
+static void __rrpc_mark_bad_block(struct rrpc *rrpc, struct ppa_addr ppa)
+{
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct rrpc_lun *rlun;
+ struct rrpc_block *rblk;
+
+ rlun = rrpc_ppa_to_lun(rrpc, ppa);
+ rblk = &rlun->blocks[ppa.g.blk];
+ rblk->state = NVM_BLK_ST_BAD;
+
+ nvm_set_tgt_bb_tbl(dev, &ppa, 1, NVM_BLK_T_GRWN_BAD);
+}
+
+static void rrpc_mark_bad_block(struct rrpc *rrpc, struct nvm_rq *rqd)
+{
+ void *comp_bits = &rqd->ppa_status;
+ struct ppa_addr ppa, prev_ppa;
+ int nr_ppas = rqd->nr_ppas;
+ int bit;
+
+ if (rqd->nr_ppas == 1)
+ __rrpc_mark_bad_block(rrpc, rqd->ppa_addr);
+
+ ppa_set_empty(&prev_ppa);
+ bit = -1;
+ while ((bit = find_next_bit(comp_bits, nr_ppas, bit + 1)) < nr_ppas) {
+ ppa = rqd->ppa_list[bit];
+ if (ppa_cmp_blk(ppa, prev_ppa))
+ continue;
+
+ __rrpc_mark_bad_block(rrpc, ppa);
+ }
+}
+
static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd,
sector_t laddr, uint8_t npages)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
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->sec_per_blk))
+ if (unlikely(cmnt_size == dev->geo.sec_per_blk))
rrpc_run_gc(rrpc, rblk);
}
}
@@ -697,12 +780,17 @@ static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd,
static void rrpc_end_io(struct nvm_rq *rqd)
{
struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance);
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
uint8_t npages = rqd->nr_ppas;
sector_t laddr = rrpc_get_laddr(rqd->bio) - npages;
- if (bio_data_dir(rqd->bio) == WRITE)
+ if (bio_data_dir(rqd->bio) == WRITE) {
+ if (rqd->error == NVM_RSP_ERR_FAILWRITE)
+ rrpc_mark_bad_block(rrpc, rqd);
+
rrpc_end_io_write(rrpc, rrqd, laddr, npages);
+ }
bio_put(rqd->bio);
@@ -712,7 +800,7 @@ static void rrpc_end_io(struct nvm_rq *rqd)
rrpc_unlock_rq(rrpc, rqd);
if (npages > 1)
- nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
mempool_free(rqd, rrpc->rq_pool);
}
@@ -720,6 +808,7 @@ static void rrpc_end_io(struct nvm_rq *rqd)
static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
struct nvm_rq *rqd, unsigned long flags, int npages)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
struct rrpc_addr *gp;
sector_t laddr = rrpc_get_laddr(bio);
@@ -727,7 +816,7 @@ static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
int i;
if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd)) {
- nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
return NVM_IO_REQUEUE;
}
@@ -737,12 +826,11 @@ static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
gp = &rrpc->trans_map[laddr + i];
if (gp->rblk) {
- rqd->ppa_list[i] = rrpc_ppa_to_gaddr(rrpc->dev,
- gp->addr);
+ rqd->ppa_list[i] = rrpc_ppa_to_gaddr(dev, gp);
} else {
BUG_ON(is_gc);
rrpc_unlock_laddr(rrpc, r);
- nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+ nvm_dev_dma_free(dev->parent, rqd->ppa_list,
rqd->dma_ppa_list);
return NVM_IO_DONE;
}
@@ -756,7 +844,6 @@ static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
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;
@@ -768,7 +855,7 @@ static int rrpc_read_rq(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd,
gp = &rrpc->trans_map[laddr];
if (gp->rblk) {
- rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, gp->addr);
+ rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, gp);
} else {
BUG_ON(is_gc);
rrpc_unlock_rq(rrpc, rqd);
@@ -776,7 +863,6 @@ static int rrpc_read_rq(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd,
}
rqd->opcode = NVM_OP_HBREAD;
- rrqd->addr = gp;
return NVM_IO_OK;
}
@@ -784,31 +870,31 @@ static int rrpc_read_rq(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd,
static int rrpc_write_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
struct nvm_rq *rqd, unsigned long flags, int npages)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
- struct rrpc_addr *p;
+ struct ppa_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);
+ nvm_dev_dma_free(dev->parent, 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) {
+ if (p.ppa == ADDR_EMPTY) {
BUG_ON(is_gc);
rrpc_unlock_laddr(rrpc, r);
- nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+ nvm_dev_dma_free(dev->parent, 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->ppa_list[i] = p;
}
rqd->opcode = NVM_OP_HBWRITE;
@@ -819,8 +905,7 @@ static int rrpc_write_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
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;
+ struct ppa_addr p;
int is_gc = flags & NVM_IOTYPE_GC;
sector_t laddr = rrpc_get_laddr(bio);
@@ -828,16 +913,15 @@ static int rrpc_write_rq(struct rrpc *rrpc, struct bio *bio,
return NVM_IO_REQUEUE;
p = rrpc_map_page(rrpc, laddr, is_gc);
- if (!p) {
+ if (p.ppa == ADDR_EMPTY) {
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->ppa_addr = p;
rqd->opcode = NVM_OP_HBWRITE;
- rrqd->addr = p;
return NVM_IO_OK;
}
@@ -845,8 +929,10 @@ static int rrpc_write_rq(struct rrpc *rrpc, struct bio *bio,
static int rrpc_setup_rq(struct rrpc *rrpc, struct bio *bio,
struct nvm_rq *rqd, unsigned long flags, uint8_t npages)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
+
if (npages > 1) {
- rqd->ppa_list = nvm_dev_dma_alloc(rrpc->dev, GFP_KERNEL,
+ rqd->ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
&rqd->dma_ppa_list);
if (!rqd->ppa_list) {
pr_err("rrpc: not able to allocate ppa list\n");
@@ -869,14 +955,15 @@ static int rrpc_setup_rq(struct rrpc *rrpc, struct bio *bio,
static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
struct nvm_rq *rqd, unsigned long flags)
{
- int err;
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_rq *rrq = nvm_rq_to_pdu(rqd);
uint8_t nr_pages = rrpc_get_pages(bio);
int bio_size = bio_sectors(bio) << 9;
+ int err;
- if (bio_size < rrpc->dev->sec_size)
+ if (bio_size < dev->geo.sec_size)
return NVM_IO_ERR;
- else if (bio_size > rrpc->dev->max_rq_size)
+ else if (bio_size > dev->geo.max_rq_size)
return NVM_IO_ERR;
err = rrpc_setup_rq(rrpc, bio, rqd, flags, nr_pages);
@@ -889,15 +976,15 @@ static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
rqd->nr_ppas = nr_pages;
rrq->flags = flags;
- err = nvm_submit_io(rrpc->dev, rqd);
+ err = nvm_submit_io(dev, rqd);
if (err) {
pr_err("rrpc: I/O submission failed: %d\n", err);
bio_put(bio);
if (!(flags & NVM_IOTYPE_GC)) {
rrpc_unlock_rq(rrpc, rqd);
if (rqd->nr_ppas > 1)
- nvm_dev_dma_free(rrpc->dev,
- rqd->ppa_list, rqd->dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd->ppa_list,
+ rqd->dma_ppa_list);
}
return NVM_IO_ERR;
}
@@ -911,6 +998,8 @@ static blk_qc_t rrpc_make_rq(struct request_queue *q, struct bio *bio)
struct nvm_rq *rqd;
int err;
+ blk_queue_split(q, &bio, q->bio_split);
+
if (bio_op(bio) == REQ_OP_DISCARD) {
rrpc_discard(rrpc, bio);
return BLK_QC_T_NONE;
@@ -997,25 +1086,24 @@ static void rrpc_map_free(struct rrpc *rrpc)
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 nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_addr *addr = rrpc->trans_map + slba;
struct rrpc_rev_addr *raddr = rrpc->rev_trans_map;
- u64 elba = slba + nlb;
+ struct rrpc_lun *rlun;
+ struct rrpc_block *rblk;
u64 i;
- if (unlikely(elba > dev->total_secs)) {
- pr_err("nvm: L2P data from device is out of bounds!\n");
- return -EINVAL;
- }
-
for (i = 0; i < nlb; i++) {
+ struct ppa_addr gaddr;
u64 pba = le64_to_cpu(entries[i]);
unsigned int mod;
+
/* LNVM treats address-spaces as silos, LBA and PBA are
* equally large and zero-indexed.
*/
if (unlikely(pba >= dev->total_secs && pba != U64_MAX)) {
pr_err("nvm: L2P data entry is out of bounds!\n");
+ pr_err("nvm: Maybe loaded an old target L2P\n");
return -EINVAL;
}
@@ -1028,7 +1116,27 @@ static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private)
div_u64_rem(pba, rrpc->nr_sects, &mod);
+ gaddr = rrpc_recov_addr(dev, pba);
+ rlun = rrpc_ppa_to_lun(rrpc, gaddr);
+ if (!rlun) {
+ pr_err("rrpc: l2p corruption on lba %llu\n",
+ slba + i);
+ return -EINVAL;
+ }
+
+ rblk = &rlun->blocks[gaddr.g.blk];
+ if (!rblk->state) {
+ /* 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. The block is assumed to be open.
+ */
+ list_move_tail(&rblk->list, &rlun->used_list);
+ rblk->state = NVM_BLK_ST_TGT;
+ rlun->nr_free_blocks--;
+ }
+
addr[i].addr = pba;
+ addr[i].rblk = rblk;
raddr[mod].addr = slba + i;
}
@@ -1037,7 +1145,7 @@ static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private)
static int rrpc_map_init(struct rrpc *rrpc)
{
- struct nvm_dev *dev = rrpc->dev;
+ struct nvm_tgt_dev *dev = rrpc->dev;
sector_t i;
int ret;
@@ -1058,12 +1166,9 @@ static int rrpc_map_init(struct rrpc *rrpc)
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, rrpc->soffset, rrpc->nr_sects,
- rrpc_l2p_update, rrpc);
+ ret = nvm_get_l2p_tbl(dev, rrpc->soffset, rrpc->nr_sects,
+ rrpc_l2p_update, rrpc);
if (ret) {
pr_err("nvm: rrpc: could not read L2P table.\n");
return -EINVAL;
@@ -1102,7 +1207,7 @@ static int rrpc_core_init(struct rrpc *rrpc)
if (!rrpc->page_pool)
return -ENOMEM;
- rrpc->gcb_pool = mempool_create_slab_pool(rrpc->dev->nr_luns,
+ rrpc->gcb_pool = mempool_create_slab_pool(rrpc->dev->geo.nr_luns,
rrpc_gcb_cache);
if (!rrpc->gcb_pool)
return -ENOMEM;
@@ -1126,8 +1231,6 @@ static void rrpc_core_free(struct rrpc *rrpc)
static void rrpc_luns_free(struct rrpc *rrpc)
{
- struct nvm_dev *dev = rrpc->dev;
- struct nvm_lun *lun;
struct rrpc_lun *rlun;
int i;
@@ -1136,23 +1239,74 @@ static void rrpc_luns_free(struct rrpc *rrpc)
for (i = 0; i < rrpc->nr_luns; i++) {
rlun = &rrpc->luns[i];
- lun = rlun->parent;
- if (!lun)
- break;
- dev->mt->release_lun(dev, lun->id);
vfree(rlun->blocks);
}
kfree(rrpc->luns);
}
-static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
+static int rrpc_bb_discovery(struct nvm_tgt_dev *dev, struct rrpc_lun *rlun)
{
- struct nvm_dev *dev = rrpc->dev;
+ struct nvm_geo *geo = &dev->geo;
+ struct rrpc_block *rblk;
+ struct ppa_addr ppa;
+ u8 *blks;
+ int nr_blks;
+ int i;
+ int ret;
+
+ if (!dev->parent->ops->get_bb_tbl)
+ return 0;
+
+ nr_blks = geo->blks_per_lun * geo->plane_mode;
+ blks = kmalloc(nr_blks, GFP_KERNEL);
+ if (!blks)
+ return -ENOMEM;
+
+ ppa.ppa = 0;
+ ppa.g.ch = rlun->bppa.g.ch;
+ ppa.g.lun = rlun->bppa.g.lun;
+
+ ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
+ if (ret) {
+ pr_err("rrpc: could not get BB table\n");
+ goto out;
+ }
+
+ nr_blks = nvm_bb_tbl_fold(dev->parent, blks, nr_blks);
+ if (nr_blks < 0)
+ return nr_blks;
+
+ for (i = 0; i < nr_blks; i++) {
+ if (blks[i] == NVM_BLK_T_FREE)
+ continue;
+
+ rblk = &rlun->blocks[i];
+ list_move_tail(&rblk->list, &rlun->bb_list);
+ rblk->state = NVM_BLK_ST_BAD;
+ rlun->nr_free_blocks--;
+ }
+
+out:
+ kfree(blks);
+ return ret;
+}
+
+static void rrpc_set_lun_ppa(struct rrpc_lun *rlun, struct ppa_addr ppa)
+{
+ rlun->bppa.ppa = 0;
+ rlun->bppa.g.ch = ppa.g.ch;
+ rlun->bppa.g.lun = ppa.g.lun;
+}
+
+static int rrpc_luns_init(struct rrpc *rrpc, struct ppa_addr *luns)
+{
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct nvm_geo *geo = &dev->geo;
struct rrpc_lun *rlun;
int i, j, ret = -EINVAL;
- if (dev->sec_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
+ if (geo->sec_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
pr_err("rrpc: number of pages per block too high.");
return -EINVAL;
}
@@ -1166,43 +1320,46 @@ static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
/* 1:1 mapping */
for (i = 0; i < rrpc->nr_luns; i++) {
- int lunid = lun_begin + i;
- struct nvm_lun *lun;
-
- if (dev->mt->reserve_lun(dev, lunid)) {
- pr_err("rrpc: lun %u is already allocated\n", lunid);
- goto err;
- }
-
- lun = dev->mt->get_lun(dev, lunid);
- if (!lun)
- goto err;
-
rlun = &rrpc->luns[i];
- rlun->parent = lun;
+ rlun->id = i;
+ rrpc_set_lun_ppa(rlun, luns[i]);
rlun->blocks = vzalloc(sizeof(struct rrpc_block) *
- rrpc->dev->blks_per_lun);
+ geo->blks_per_lun);
if (!rlun->blocks) {
ret = -ENOMEM;
goto err;
}
- for (j = 0; j < rrpc->dev->blks_per_lun; j++) {
+ INIT_LIST_HEAD(&rlun->free_list);
+ INIT_LIST_HEAD(&rlun->used_list);
+ INIT_LIST_HEAD(&rlun->bb_list);
+
+ for (j = 0; j < geo->blks_per_lun; j++) {
struct rrpc_block *rblk = &rlun->blocks[j];
- struct nvm_block *blk = &lun->blocks[j];
- rblk->parent = blk;
+ rblk->id = j;
rblk->rlun = rlun;
+ rblk->state = NVM_BLK_T_FREE;
INIT_LIST_HEAD(&rblk->prio);
+ INIT_LIST_HEAD(&rblk->list);
spin_lock_init(&rblk->lock);
+
+ list_add_tail(&rblk->list, &rlun->free_list);
}
rlun->rrpc = rrpc;
+ rlun->nr_free_blocks = geo->blks_per_lun;
+ rlun->reserved_blocks = 2; /* for GC only */
+
INIT_LIST_HEAD(&rlun->prio_list);
INIT_LIST_HEAD(&rlun->wblk_list);
INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
spin_lock_init(&rlun->lock);
+
+ if (rrpc_bb_discovery(dev, rlun))
+ goto err;
+
}
return 0;
@@ -1213,27 +1370,25 @@ err:
/* returns 0 on success and stores the beginning address in *begin */
static int rrpc_area_init(struct rrpc *rrpc, sector_t *begin)
{
- struct nvm_dev *dev = rrpc->dev;
- struct nvmm_type *mt = dev->mt;
- sector_t size = rrpc->nr_sects * dev->sec_size;
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ sector_t size = rrpc->nr_sects * dev->geo.sec_size;
int ret;
size >>= 9;
- ret = mt->get_area(dev, begin, size);
+ ret = nvm_get_area(dev, begin, size);
if (!ret)
- *begin >>= (ilog2(dev->sec_size) - 9);
+ *begin >>= (ilog2(dev->geo.sec_size) - 9);
return ret;
}
static void rrpc_area_free(struct rrpc *rrpc)
{
- struct nvm_dev *dev = rrpc->dev;
- struct nvmm_type *mt = dev->mt;
- sector_t begin = rrpc->soffset << (ilog2(dev->sec_size) - 9);
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ sector_t begin = rrpc->soffset << (ilog2(dev->geo.sec_size) - 9);
- mt->put_area(dev, begin);
+ nvm_put_area(dev, begin);
}
static void rrpc_free(struct rrpc *rrpc)
@@ -1262,11 +1417,11 @@ static void rrpc_exit(void *private)
static sector_t rrpc_capacity(void *private)
{
struct rrpc *rrpc = private;
- struct nvm_dev *dev = rrpc->dev;
+ struct nvm_tgt_dev *dev = rrpc->dev;
sector_t reserved, provisioned;
/* cur, gc, and two emergency blocks for each lun */
- reserved = rrpc->nr_luns * dev->sec_per_blk * 4;
+ reserved = rrpc->nr_luns * dev->geo.sec_per_blk * 4;
provisioned = rrpc->nr_sects - reserved;
if (reserved > rrpc->nr_sects) {
@@ -1285,13 +1440,13 @@ static sector_t rrpc_capacity(void *private)
*/
static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- struct nvm_dev *dev = rrpc->dev;
+ struct nvm_tgt_dev *dev = rrpc->dev;
int offset;
struct rrpc_addr *laddr;
u64 bpaddr, paddr, pladdr;
bpaddr = block_to_rel_addr(rrpc, rblk);
- for (offset = 0; offset < dev->sec_per_blk; offset++) {
+ for (offset = 0; offset < dev->geo.sec_per_blk; offset++) {
paddr = bpaddr + offset;
pladdr = rrpc->rev_trans_map[paddr].addr;
@@ -1311,6 +1466,7 @@ static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk)
static int rrpc_blocks_init(struct rrpc *rrpc)
{
+ struct nvm_tgt_dev *dev = rrpc->dev;
struct rrpc_lun *rlun;
struct rrpc_block *rblk;
int lun_iter, blk_iter;
@@ -1318,7 +1474,7 @@ static int rrpc_blocks_init(struct rrpc *rrpc)
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;
+ for (blk_iter = 0; blk_iter < dev->geo.blks_per_lun;
blk_iter++) {
rblk = &rlun->blocks[blk_iter];
rrpc_block_map_update(rrpc, rblk);
@@ -1357,11 +1513,11 @@ err:
static struct nvm_tgt_type tt_rrpc;
-static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
- int lun_begin, int lun_end)
+static void *rrpc_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk)
{
struct request_queue *bqueue = dev->q;
struct request_queue *tqueue = tdisk->queue;
+ struct nvm_geo *geo = &dev->geo;
struct rrpc *rrpc;
sector_t soffset;
int ret;
@@ -1384,9 +1540,8 @@ static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
spin_lock_init(&rrpc->bio_lock);
INIT_WORK(&rrpc->ws_requeue, rrpc_requeue);
- rrpc->nr_luns = lun_end - lun_begin + 1;
- rrpc->total_blocks = (unsigned long)dev->blks_per_lun * rrpc->nr_luns;
- rrpc->nr_sects = (unsigned long long)dev->sec_per_lun * rrpc->nr_luns;
+ rrpc->nr_luns = geo->nr_luns;
+ rrpc->nr_sects = (unsigned long long)geo->sec_per_lun * rrpc->nr_luns;
/* simple round-robin strategy */
atomic_set(&rrpc->next_lun, -1);
@@ -1398,15 +1553,12 @@ static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
}
rrpc->soffset = soffset;
- ret = rrpc_luns_init(rrpc, lun_begin, lun_end);
+ ret = rrpc_luns_init(rrpc, dev->luns);
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");
diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h
index 5e87d52cb983..94e4d73116b2 100644
--- a/drivers/lightnvm/rrpc.h
+++ b/drivers/lightnvm/rrpc.h
@@ -48,14 +48,15 @@ struct rrpc_inflight_rq {
struct rrpc_rq {
struct rrpc_inflight_rq inflight_rq;
- struct rrpc_addr *addr;
unsigned long flags;
};
struct rrpc_block {
- struct nvm_block *parent;
+ int id; /* id inside of LUN */
struct rrpc_lun *rlun;
- struct list_head prio;
+
+ struct list_head prio; /* LUN CG list */
+ struct list_head list; /* LUN free, used, bb list */
#define MAX_INVALID_PAGES_STORAGE 8
/* Bitmap for invalid page intries */
@@ -65,21 +66,38 @@ struct rrpc_block {
/* number of pages that are invalid, wrt host page size */
unsigned int nr_invalid_pages;
+ int state;
+
spinlock_t lock;
atomic_t data_cmnt_size; /* data pages committed to stable storage */
};
struct rrpc_lun {
struct rrpc *rrpc;
- struct nvm_lun *parent;
+
+ int id;
+ struct ppa_addr bppa;
+
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 list_head wblk_list; /* Queued blocks to be written to */
+ /* 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
+ */
+ unsigned int nr_free_blocks; /* Number of unused blocks */
+
struct work_struct ws_gc;
+ int reserved_blocks;
+
spinlock_t lock;
};
@@ -87,19 +105,16 @@ struct rrpc {
/* instance must be kept in top to resolve rrpc in unprep */
struct nvm_tgt_instance instance;
- struct nvm_dev *dev;
+ struct nvm_tgt_dev *dev;
struct gendisk *disk;
sector_t soffset; /* logical sector offset */
- u64 poffset; /* physical page offset */
- int lun_offset;
int nr_luns;
struct rrpc_lun *luns;
/* calculated values */
unsigned long long nr_sects;
- unsigned long total_blocks;
/* Write strategy variables. Move these into each for structure for each
* strategy
@@ -150,13 +165,37 @@ struct rrpc_rev_addr {
u64 addr;
};
-static inline struct rrpc_block *rrpc_get_rblk(struct rrpc_lun *rlun,
- int blk_id)
+static inline struct ppa_addr rrpc_linear_to_generic_addr(struct nvm_geo *geo,
+ struct ppa_addr r)
+{
+ struct ppa_addr l;
+ int secs, pgs;
+ sector_t ppa = r.ppa;
+
+ l.ppa = 0;
+
+ div_u64_rem(ppa, geo->sec_per_pg, &secs);
+ l.g.sec = secs;
+
+ sector_div(ppa, geo->sec_per_pg);
+ div_u64_rem(ppa, geo->pgs_per_blk, &pgs);
+ l.g.pg = pgs;
+
+ return l;
+}
+
+static inline struct ppa_addr rrpc_recov_addr(struct nvm_tgt_dev *dev, u64 pba)
+{
+ return linear_to_generic_addr(&dev->geo, pba);
+}
+
+static inline u64 rrpc_blk_to_ppa(struct rrpc *rrpc, struct rrpc_block *rblk)
{
- struct rrpc *rrpc = rlun->rrpc;
- int lun_blk = blk_id % rrpc->dev->blks_per_lun;
+ struct nvm_tgt_dev *dev = rrpc->dev;
+ struct nvm_geo *geo = &dev->geo;
+ struct rrpc_lun *rlun = rblk->rlun;
- return &rlun->blocks[lun_blk];
+ return (rlun->id * geo->sec_per_lun) + (rblk->id * geo->sec_per_blk);
}
static inline sector_t rrpc_get_laddr(struct bio *bio)
diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c
index a75bd28aaca3..12002bf4efc2 100644
--- a/drivers/lightnvm/sysblk.c
+++ b/drivers/lightnvm/sysblk.c
@@ -62,7 +62,8 @@ static void nvm_cpu_to_sysblk(struct nvm_system_block *sb,
static int nvm_setup_sysblks(struct nvm_dev *dev, struct ppa_addr *sysblk_ppas)
{
- int nr_rows = min_t(int, MAX_SYSBLKS, dev->nr_chnls);
+ struct nvm_geo *geo = &dev->geo;
+ int nr_rows = min_t(int, MAX_SYSBLKS, geo->nr_chnls);
int i;
for (i = 0; i < nr_rows; i++)
@@ -71,7 +72,7 @@ static int nvm_setup_sysblks(struct nvm_dev *dev, struct ppa_addr *sysblk_ppas)
/* if possible, place sysblk at first channel, middle channel and last
* channel of the device. If not, create only one or two sys blocks
*/
- switch (dev->nr_chnls) {
+ switch (geo->nr_chnls) {
case 2:
sysblk_ppas[1].g.ch = 1;
/* fall-through */
@@ -80,8 +81,8 @@ static int nvm_setup_sysblks(struct nvm_dev *dev, struct ppa_addr *sysblk_ppas)
break;
default:
sysblk_ppas[0].g.ch = 0;
- sysblk_ppas[1].g.ch = dev->nr_chnls / 2;
- sysblk_ppas[2].g.ch = dev->nr_chnls - 1;
+ sysblk_ppas[1].g.ch = geo->nr_chnls / 2;
+ sysblk_ppas[2].g.ch = geo->nr_chnls - 1;
break;
}
@@ -162,11 +163,12 @@ static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa,
static int nvm_get_all_sysblks(struct nvm_dev *dev, struct sysblk_scan *s,
struct ppa_addr *ppas, int get_free)
{
+ struct nvm_geo *geo = &dev->geo;
int i, nr_blks, ret = 0;
u8 *blks;
s->nr_ppas = 0;
- nr_blks = dev->blks_per_lun * dev->plane_mode;
+ nr_blks = geo->blks_per_lun * geo->plane_mode;
blks = kmalloc(nr_blks, GFP_KERNEL);
if (!blks)
@@ -210,13 +212,14 @@ err_get:
static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa,
struct nvm_system_block *sblk)
{
+ struct nvm_geo *geo = &dev->geo;
struct nvm_system_block *cur;
int pg, ret, found = 0;
/* the full buffer for a flash page is allocated. Only the first of it
* contains the system block information
*/
- cur = kmalloc(dev->pfpg_size, GFP_KERNEL);
+ cur = kmalloc(geo->pfpg_size, GFP_KERNEL);
if (!cur)
return -ENOMEM;
@@ -225,7 +228,7 @@ static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa,
ppa->g.pg = ppa_to_slc(dev, pg);
ret = nvm_submit_ppa(dev, ppa, 1, NVM_OP_PREAD, NVM_IO_SLC_MODE,
- cur, dev->pfpg_size);
+ cur, geo->pfpg_size);
if (ret) {
if (ret == NVM_RSP_ERR_EMPTYPAGE) {
pr_debug("nvm: sysblk scan empty ppa (%u %u %u %u)\n",
@@ -267,34 +270,16 @@ static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa,
return found;
}
-static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type)
+static int nvm_sysblk_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s,
+ int type)
{
- struct nvm_rq rqd;
- int ret;
-
- if (s->nr_ppas > dev->ops->max_phys_sect) {
- pr_err("nvm: unable to update all sysblocks atomically\n");
- return -EINVAL;
- }
-
- memset(&rqd, 0, sizeof(struct nvm_rq));
-
- nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1);
- nvm_generic_to_addr_mode(dev, &rqd);
-
- ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
- nvm_free_rqd_ppalist(dev, &rqd);
- if (ret) {
- pr_err("nvm: sysblk failed bb mark\n");
- return -EINVAL;
- }
-
- return 0;
+ return nvm_set_bb_tbl(dev, s->ppas, s->nr_ppas, type);
}
static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info,
struct sysblk_scan *s)
{
+ struct nvm_geo *geo = &dev->geo;
struct nvm_system_block nvmsb;
void *buf;
int i, sect, ret = 0;
@@ -302,12 +287,12 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info,
nvm_cpu_to_sysblk(&nvmsb, info);
- buf = kzalloc(dev->pfpg_size, GFP_KERNEL);
+ buf = kzalloc(geo->pfpg_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, &nvmsb, sizeof(struct nvm_system_block));
- ppas = kcalloc(dev->sec_per_pg, sizeof(struct ppa_addr), GFP_KERNEL);
+ ppas = kcalloc(geo->sec_per_pg, sizeof(struct ppa_addr), GFP_KERNEL);
if (!ppas) {
ret = -ENOMEM;
goto err;
@@ -324,15 +309,15 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info,
ppas[0].g.pg);
/* Expand to all sectors within a flash page */
- if (dev->sec_per_pg > 1) {
- for (sect = 1; sect < dev->sec_per_pg; sect++) {
+ if (geo->sec_per_pg > 1) {
+ for (sect = 1; sect < geo->sec_per_pg; sect++) {
ppas[sect].ppa = ppas[0].ppa;
ppas[sect].g.sec = sect;
}
}
- ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PWRITE,
- NVM_IO_SLC_MODE, buf, dev->pfpg_size);
+ ret = nvm_submit_ppa(dev, ppas, geo->sec_per_pg, NVM_OP_PWRITE,
+ NVM_IO_SLC_MODE, buf, geo->pfpg_size);
if (ret) {
pr_err("nvm: sysblk failed program (%u %u %u)\n",
ppas[0].g.ch,
@@ -341,8 +326,8 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info,
break;
}
- ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PREAD,
- NVM_IO_SLC_MODE, buf, dev->pfpg_size);
+ ret = nvm_submit_ppa(dev, ppas, geo->sec_per_pg, NVM_OP_PREAD,
+ NVM_IO_SLC_MODE, buf, geo->pfpg_size);
if (ret) {
pr_err("nvm: sysblk failed read (%u %u %u)\n",
ppas[0].g.ch,
@@ -379,7 +364,7 @@ static int nvm_prepare_new_sysblks(struct nvm_dev *dev, struct sysblk_scan *s)
ppa = &s->ppas[scan_ppa_idx(i, nxt_blk)];
ppa->g.pg = ppa_to_slc(dev, 0);
- ret = nvm_erase_ppa(dev, ppa, 1);
+ ret = nvm_erase_ppa(dev, ppa, 1, 0);
if (ret)
return ret;
@@ -546,6 +531,7 @@ err_sysblk:
int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr sysblk_ppas[MAX_SYSBLKS];
struct sysblk_scan s;
int ret;
@@ -560,7 +546,7 @@ int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)
if (!dev->ops->get_bb_tbl || !dev->ops->set_bb_tbl)
return -EINVAL;
- if (!(dev->mccap & NVM_ID_CAP_SLC) || !dev->lps_per_blk) {
+ if (!(geo->mccap & NVM_ID_CAP_SLC) || !dev->lps_per_blk) {
pr_err("nvm: memory does not support SLC access\n");
return -EINVAL;
}
@@ -573,7 +559,7 @@ int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)
if (ret)
goto err_mark;
- ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_HOST);
+ ret = nvm_sysblk_set_bb_tbl(dev, &s, NVM_BLK_T_HOST);
if (ret)
goto err_mark;
@@ -590,11 +576,11 @@ static int factory_nblks(int nblks)
return (nblks + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
}
-static unsigned int factory_blk_offset(struct nvm_dev *dev, struct ppa_addr ppa)
+static unsigned int factory_blk_offset(struct nvm_geo *geo, struct ppa_addr ppa)
{
- int nblks = factory_nblks(dev->blks_per_lun);
+ int nblks = factory_nblks(geo->blks_per_lun);
- return ((ppa.g.ch * dev->luns_per_chnl * nblks) + (ppa.g.lun * nblks)) /
+ return ((ppa.g.ch * geo->luns_per_chnl * nblks) + (ppa.g.lun * nblks)) /
BITS_PER_LONG;
}
@@ -608,7 +594,7 @@ static int nvm_factory_blks(struct nvm_dev *dev, struct ppa_addr ppa,
if (nr_blks < 0)
return nr_blks;
- lunoff = factory_blk_offset(dev, ppa);
+ lunoff = factory_blk_offset(&dev->geo, ppa);
/* non-set bits correspond to the block must be erased */
for (i = 0; i < nr_blks; i++) {
@@ -637,19 +623,19 @@ static int nvm_factory_blks(struct nvm_dev *dev, struct ppa_addr ppa,
static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list,
int max_ppas, unsigned long *blk_bitmap)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr ppa;
int ch, lun, blkid, idx, done = 0, ppa_cnt = 0;
unsigned long *offset;
while (!done) {
done = 1;
- nvm_for_each_lun_ppa(dev, ppa, ch, lun) {
- idx = factory_blk_offset(dev, ppa);
+ nvm_for_each_lun_ppa(geo, ppa, ch, lun) {
+ idx = factory_blk_offset(geo, ppa);
offset = &blk_bitmap[idx];
- blkid = find_first_zero_bit(offset,
- dev->blks_per_lun);
- if (blkid >= dev->blks_per_lun)
+ blkid = find_first_zero_bit(offset, geo->blks_per_lun);
+ if (blkid >= geo->blks_per_lun)
continue;
set_bit(blkid, offset);
@@ -674,16 +660,17 @@ static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list,
static int nvm_fact_select_blks(struct nvm_dev *dev, unsigned long *blk_bitmap,
int flags)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr ppa;
int ch, lun, nr_blks, ret = 0;
u8 *blks;
- nr_blks = dev->blks_per_lun * dev->plane_mode;
+ nr_blks = geo->blks_per_lun * geo->plane_mode;
blks = kmalloc(nr_blks, GFP_KERNEL);
if (!blks)
return -ENOMEM;
- nvm_for_each_lun_ppa(dev, ppa, ch, lun) {
+ nvm_for_each_lun_ppa(geo, ppa, ch, lun) {
ret = nvm_get_bb_tbl(dev, ppa, blks);
if (ret)
pr_err("nvm: failed bb tbl for ch%u lun%u\n",
@@ -701,14 +688,15 @@ static int nvm_fact_select_blks(struct nvm_dev *dev, unsigned long *blk_bitmap,
int nvm_dev_factory(struct nvm_dev *dev, int flags)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr *ppas;
int ppa_cnt, ret = -ENOMEM;
- int max_ppas = dev->ops->max_phys_sect / dev->nr_planes;
+ int max_ppas = dev->ops->max_phys_sect / geo->nr_planes;
struct ppa_addr sysblk_ppas[MAX_SYSBLKS];
struct sysblk_scan s;
unsigned long *blk_bitmap;
- blk_bitmap = kzalloc(factory_nblks(dev->blks_per_lun) * dev->nr_luns,
+ blk_bitmap = kzalloc(factory_nblks(geo->blks_per_lun) * geo->nr_luns,
GFP_KERNEL);
if (!blk_bitmap)
return ret;
@@ -725,7 +713,7 @@ int nvm_dev_factory(struct nvm_dev *dev, int flags)
/* continue to erase until list of blks until empty */
while ((ppa_cnt =
nvm_fact_get_blks(dev, ppas, max_ppas, blk_bitmap)) > 0)
- nvm_erase_ppa(dev, ppas, ppa_cnt);
+ nvm_erase_ppa(dev, ppas, ppa_cnt, 0);
/* mark host reserved blocks free */
if (flags & NVM_FACTORY_RESET_HOST_BLKS) {
@@ -733,7 +721,7 @@ int nvm_dev_factory(struct nvm_dev *dev, int flags)
mutex_lock(&dev->mlock);
ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0);
if (!ret)
- ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_FREE);
+ ret = nvm_sysblk_set_bb_tbl(dev, &s, NVM_BLK_T_FREE);
mutex_unlock(&dev->mlock);
}
err_ppas:
diff --git a/drivers/lightnvm/sysfs.c b/drivers/lightnvm/sysfs.c
deleted file mode 100644
index 0338c27ab95a..000000000000
--- a/drivers/lightnvm/sysfs.c
+++ /dev/null
@@ -1,198 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/lightnvm.h>
-#include <linux/miscdevice.h>
-#include <linux/kobject.h>
-#include <linux/blk-mq.h>
-
-#include "lightnvm.h"
-
-static ssize_t nvm_dev_attr_show(struct device *dev,
- struct device_attribute *dattr, char *page)
-{
- struct nvm_dev *ndev = container_of(dev, struct nvm_dev, dev);
- struct nvm_id *id = &ndev->identity;
- struct nvm_id_group *grp = &id->groups[0];
- struct attribute *attr = &dattr->attr;
-
- if (strcmp(attr->name, "version") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
- } else if (strcmp(attr->name, "vendor_opcode") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
- } else if (strcmp(attr->name, "capabilities") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
- } else if (strcmp(attr->name, "device_mode") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
- } else if (strcmp(attr->name, "media_manager") == 0) {
- if (!ndev->mt)
- return scnprintf(page, PAGE_SIZE, "%s\n", "none");
- return scnprintf(page, PAGE_SIZE, "%s\n", ndev->mt->name);
- } else if (strcmp(attr->name, "ppa_format") == 0) {
- return scnprintf(page, PAGE_SIZE,
- "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- id->ppaf.ch_offset, id->ppaf.ch_len,
- id->ppaf.lun_offset, id->ppaf.lun_len,
- id->ppaf.pln_offset, id->ppaf.pln_len,
- id->ppaf.blk_offset, id->ppaf.blk_len,
- id->ppaf.pg_offset, id->ppaf.pg_len,
- id->ppaf.sect_offset, id->ppaf.sect_len);
- } else if (strcmp(attr->name, "media_type") == 0) { /* u8 */
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->mtype);
- } else if (strcmp(attr->name, "flash_media_type") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->fmtype);
- } else if (strcmp(attr->name, "num_channels") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_ch);
- } else if (strcmp(attr->name, "num_luns") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_lun);
- } else if (strcmp(attr->name, "num_planes") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pln);
- } else if (strcmp(attr->name, "num_blocks") == 0) { /* u16 */
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_blk);
- } else if (strcmp(attr->name, "num_pages") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pg);
- } else if (strcmp(attr->name, "page_size") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->fpg_sz);
- } else if (strcmp(attr->name, "hw_sector_size") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->csecs);
- } else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->sos);
- } else if (strcmp(attr->name, "read_typ") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdt);
- } else if (strcmp(attr->name, "read_max") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdm);
- } else if (strcmp(attr->name, "prog_typ") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprt);
- } else if (strcmp(attr->name, "prog_max") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprm);
- } else if (strcmp(attr->name, "erase_typ") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbet);
- } else if (strcmp(attr->name, "erase_max") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbem);
- } else if (strcmp(attr->name, "multiplane_modes") == 0) {
- return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mpos);
- } else if (strcmp(attr->name, "media_capabilities") == 0) {
- return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mccap);
- } else if (strcmp(attr->name, "max_phys_secs") == 0) {
- return scnprintf(page, PAGE_SIZE, "%u\n",
- ndev->ops->max_phys_sect);
- } else {
- return scnprintf(page,
- PAGE_SIZE,
- "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
- attr->name);
- }
-}
-
-#define NVM_DEV_ATTR_RO(_name) \
- DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
-
-static NVM_DEV_ATTR_RO(version);
-static NVM_DEV_ATTR_RO(vendor_opcode);
-static NVM_DEV_ATTR_RO(capabilities);
-static NVM_DEV_ATTR_RO(device_mode);
-static NVM_DEV_ATTR_RO(ppa_format);
-static NVM_DEV_ATTR_RO(media_manager);
-
-static NVM_DEV_ATTR_RO(media_type);
-static NVM_DEV_ATTR_RO(flash_media_type);
-static NVM_DEV_ATTR_RO(num_channels);
-static NVM_DEV_ATTR_RO(num_luns);
-static NVM_DEV_ATTR_RO(num_planes);
-static NVM_DEV_ATTR_RO(num_blocks);
-static NVM_DEV_ATTR_RO(num_pages);
-static NVM_DEV_ATTR_RO(page_size);
-static NVM_DEV_ATTR_RO(hw_sector_size);
-static NVM_DEV_ATTR_RO(oob_sector_size);
-static NVM_DEV_ATTR_RO(read_typ);
-static NVM_DEV_ATTR_RO(read_max);
-static NVM_DEV_ATTR_RO(prog_typ);
-static NVM_DEV_ATTR_RO(prog_max);
-static NVM_DEV_ATTR_RO(erase_typ);
-static NVM_DEV_ATTR_RO(erase_max);
-static NVM_DEV_ATTR_RO(multiplane_modes);
-static NVM_DEV_ATTR_RO(media_capabilities);
-static NVM_DEV_ATTR_RO(max_phys_secs);
-
-#define NVM_DEV_ATTR(_name) (dev_attr_##_name##)
-
-static struct attribute *nvm_dev_attrs[] = {
- &dev_attr_version.attr,
- &dev_attr_vendor_opcode.attr,
- &dev_attr_capabilities.attr,
- &dev_attr_device_mode.attr,
- &dev_attr_media_manager.attr,
-
- &dev_attr_ppa_format.attr,
- &dev_attr_media_type.attr,
- &dev_attr_flash_media_type.attr,
- &dev_attr_num_channels.attr,
- &dev_attr_num_luns.attr,
- &dev_attr_num_planes.attr,
- &dev_attr_num_blocks.attr,
- &dev_attr_num_pages.attr,
- &dev_attr_page_size.attr,
- &dev_attr_hw_sector_size.attr,
- &dev_attr_oob_sector_size.attr,
- &dev_attr_read_typ.attr,
- &dev_attr_read_max.attr,
- &dev_attr_prog_typ.attr,
- &dev_attr_prog_max.attr,
- &dev_attr_erase_typ.attr,
- &dev_attr_erase_max.attr,
- &dev_attr_multiplane_modes.attr,
- &dev_attr_media_capabilities.attr,
- &dev_attr_max_phys_secs.attr,
- NULL,
-};
-
-static struct attribute_group nvm_dev_attr_group = {
- .name = "lightnvm",
- .attrs = nvm_dev_attrs,
-};
-
-static const struct attribute_group *nvm_dev_attr_groups[] = {
- &nvm_dev_attr_group,
- NULL,
-};
-
-static void nvm_dev_release(struct device *device)
-{
- struct nvm_dev *dev = container_of(device, struct nvm_dev, dev);
- struct request_queue *q = dev->q;
-
- pr_debug("nvm/sysfs: `nvm_dev_release`\n");
-
- blk_mq_unregister_dev(device, q);
-
- nvm_free(dev);
-}
-
-static struct device_type nvm_type = {
- .name = "lightnvm",
- .groups = nvm_dev_attr_groups,
- .release = nvm_dev_release,
-};
-
-int nvm_sysfs_register_dev(struct nvm_dev *dev)
-{
- int ret;
-
- if (!dev->parent_dev)
- return 0;
-
- dev->dev.parent = dev->parent_dev;
- dev_set_name(&dev->dev, "%s", dev->name);
- dev->dev.type = &nvm_type;
- device_initialize(&dev->dev);
- ret = device_add(&dev->dev);
-
- if (!ret)
- blk_mq_register_dev(&dev->dev, dev->q);
-
- return ret;
-}
-
-void nvm_sysfs_unregister_dev(struct nvm_dev *dev)
-{
- if (dev && dev->parent_dev)
- kobject_put(&dev->dev.kobj);
-}
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 81d3db40cd7b..6fdd8e252760 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -297,7 +297,7 @@ static void bch_btree_node_read(struct btree *b)
bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9;
bio->bi_end_io = btree_node_read_endio;
bio->bi_private = &cl;
- bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC);
+ bio->bi_opf = REQ_OP_READ | REQ_META;
bch_bio_map(bio, b->keys.set[0].data);
@@ -393,7 +393,7 @@ static void do_btree_node_write(struct btree *b)
b->bio->bi_end_io = btree_node_write_endio;
b->bio->bi_private = cl;
b->bio->bi_iter.bi_size = roundup(set_bytes(i), block_bytes(b->c));
- bio_set_op_attrs(b->bio, REQ_OP_WRITE, REQ_META|WRITE_SYNC|REQ_FUA);
+ b->bio->bi_opf = REQ_OP_WRITE | REQ_META | REQ_FUA;
bch_bio_map(b->bio, i);
/*
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 333a1e5f6ae6..06f55056aaae 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -52,7 +52,7 @@ void bch_btree_verify(struct btree *b)
bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev;
bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0);
bio->bi_iter.bi_size = KEY_SIZE(&v->key) << 9;
- bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC);
+ bio->bi_opf = REQ_OP_READ | REQ_META;
bch_bio_map(bio, sorted);
submit_bio_wait(bio);
@@ -107,22 +107,26 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
{
char name[BDEVNAME_SIZE];
struct bio *check;
- struct bio_vec bv;
- struct bvec_iter iter;
+ struct bio_vec bv, cbv;
+ struct bvec_iter iter, citer = { 0 };
check = bio_clone(bio, GFP_NOIO);
if (!check)
return;
- bio_set_op_attrs(check, REQ_OP_READ, READ_SYNC);
+ check->bi_opf = REQ_OP_READ;
if (bio_alloc_pages(check, GFP_NOIO))
goto out_put;
submit_bio_wait(check);
+ citer.bi_size = UINT_MAX;
bio_for_each_segment(bv, bio, iter) {
void *p1 = kmap_atomic(bv.bv_page);
- void *p2 = page_address(check->bi_io_vec[iter.bi_idx].bv_page);
+ void *p2;
+
+ cbv = bio_iter_iovec(check, citer);
+ p2 = page_address(cbv.bv_page);
cache_set_err_on(memcmp(p1 + bv.bv_offset,
p2 + bv.bv_offset,
@@ -133,6 +137,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
(uint64_t) bio->bi_iter.bi_sector);
kunmap_atomic(p1);
+ bio_advance_iter(check, &citer, bv.bv_len);
}
bio_free_pages(check);
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index e97b0acf7b8d..db45a88c0ce9 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -24,9 +24,7 @@ struct bio *bch_bbio_alloc(struct cache_set *c)
struct bbio *b = mempool_alloc(c->bio_meta, GFP_NOIO);
struct bio *bio = &b->bio;
- bio_init(bio);
- bio->bi_max_vecs = bucket_pages(c);
- bio->bi_io_vec = bio->bi_inline_vecs;
+ bio_init(bio, bio->bi_inline_vecs, bucket_pages(c));
return bio;
}
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 6925023e12d4..1198e53d5670 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -448,13 +448,11 @@ static void do_journal_discard(struct cache *ca)
atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT);
- bio_init(bio);
+ bio_init(bio, bio->bi_inline_vecs, 1);
bio_set_op_attrs(bio, REQ_OP_DISCARD, 0);
bio->bi_iter.bi_sector = bucket_to_sector(ca->set,
ca->sb.d[ja->discard_idx]);
bio->bi_bdev = ca->bdev;
- bio->bi_max_vecs = 1;
- bio->bi_io_vec = bio->bi_inline_vecs;
bio->bi_iter.bi_size = bucket_bytes(ca);
bio->bi_end_io = journal_discard_endio;
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 5c4bddecfaf0..13b8a907006d 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -77,15 +77,13 @@ static void moving_init(struct moving_io *io)
{
struct bio *bio = &io->bio.bio;
- bio_init(bio);
+ bio_init(bio, bio->bi_inline_vecs,
+ DIV_ROUND_UP(KEY_SIZE(&io->w->key), PAGE_SECTORS));
bio_get(bio);
bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
bio->bi_iter.bi_size = KEY_SIZE(&io->w->key) << 9;
- bio->bi_max_vecs = DIV_ROUND_UP(KEY_SIZE(&io->w->key),
- PAGE_SECTORS);
bio->bi_private = &io->cl;
- bio->bi_io_vec = bio->bi_inline_vecs;
bch_bio_map(bio, NULL);
}
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 40ffe5e424b3..f49c5417527d 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -404,8 +404,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
if (!congested &&
mode == CACHE_MODE_WRITEBACK &&
- op_is_write(bio_op(bio)) &&
- (bio->bi_opf & REQ_SYNC))
+ op_is_write(bio->bi_opf) &&
+ op_is_sync(bio->bi_opf))
goto rescale;
spin_lock(&dc->io_lock);
@@ -623,7 +623,7 @@ static void do_bio_hook(struct search *s, struct bio *orig_bio)
{
struct bio *bio = &s->bio.bio;
- bio_init(bio);
+ bio_init(bio, NULL, 0);
__bio_clone_fast(bio, orig_bio);
bio->bi_end_io = request_endio;
bio->bi_private = &s->cl;
@@ -923,7 +923,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)
flush->bi_bdev = bio->bi_bdev;
flush->bi_end_io = request_endio;
flush->bi_private = cl;
- bio_set_op_attrs(flush, REQ_OP_WRITE, WRITE_FLUSH);
+ flush->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
closure_bio_submit(flush, cl);
}
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 849ad441cd76..2fb5bfeb43e2 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -381,7 +381,7 @@ static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl)
return "bad uuid pointer";
bkey_copy(&c->uuid_bucket, k);
- uuid_io(c, REQ_OP_READ, READ_SYNC, k, cl);
+ uuid_io(c, REQ_OP_READ, 0, k, cl);
if (j->version < BCACHE_JSET_VERSION_UUIDv1) {
struct uuid_entry_v0 *u0 = (void *) c->uuids;
@@ -600,7 +600,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
ca->prio_last_buckets[bucket_nr] = bucket;
bucket_nr++;
- prio_io(ca, bucket, REQ_OP_READ, READ_SYNC);
+ prio_io(ca, bucket, REQ_OP_READ, 0);
if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
pr_warn("bad csum reading priorities");
@@ -1152,9 +1152,7 @@ static void register_bdev(struct cache_sb *sb, struct page *sb_page,
dc->bdev = bdev;
dc->bdev->bd_holder = dc;
- bio_init(&dc->sb_bio);
- dc->sb_bio.bi_max_vecs = 1;
- dc->sb_bio.bi_io_vec = dc->sb_bio.bi_inline_vecs;
+ bio_init(&dc->sb_bio, dc->sb_bio.bi_inline_vecs, 1);
dc->sb_bio.bi_io_vec[0].bv_page = sb_page;
get_page(sb_page);
@@ -1814,9 +1812,7 @@ static int cache_alloc(struct cache *ca)
__module_get(THIS_MODULE);
kobject_init(&ca->kobj, &bch_cache_ktype);
- bio_init(&ca->journal.bio);
- ca->journal.bio.bi_max_vecs = 8;
- ca->journal.bio.bi_io_vec = ca->journal.bio.bi_inline_vecs;
+ bio_init(&ca->journal.bio, ca->journal.bio.bi_inline_vecs, 8);
free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
@@ -1852,9 +1848,7 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
ca->bdev = bdev;
ca->bdev->bd_holder = ca;
- bio_init(&ca->sb_bio);
- ca->sb_bio.bi_max_vecs = 1;
- ca->sb_bio.bi_io_vec = ca->sb_bio.bi_inline_vecs;
+ bio_init(&ca->sb_bio, ca->sb_bio.bi_inline_vecs, 1);
ca->sb_bio.bi_io_vec[0].bv_page = sb_page;
get_page(sb_page);
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index e51644e503a5..69e1ae59cab8 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -106,14 +106,13 @@ static void dirty_init(struct keybuf_key *w)
struct dirty_io *io = w->private;
struct bio *bio = &io->bio;
- bio_init(bio);
+ bio_init(bio, bio->bi_inline_vecs,
+ DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS));
if (!io->dc->writeback_percent)
bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
bio->bi_iter.bi_size = KEY_SIZE(&w->key) << 9;
- bio->bi_max_vecs = DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS);
bio->bi_private = w;
- bio->bi_io_vec = bio->bi_inline_vecs;
bch_bio_map(bio, NULL);
}
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index 301eaf565167..629bd1a502fd 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -57,8 +57,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
if (would_skip)
return false;
- return bio->bi_opf & REQ_SYNC ||
- in_use <= CUTOFF_WRITEBACK;
+ return op_is_sync(bio->bi_opf) || in_use <= CUTOFF_WRITEBACK;
}
static inline void bch_writeback_queue(struct cached_dev *dc)
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 125aedc3875f..262e75365cc0 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -611,9 +611,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
char *ptr;
int len;
- bio_init(&b->bio);
- b->bio.bi_io_vec = b->bio_vec;
- b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
+ bio_init(&b->bio, b->bio_vec, DM_BUFIO_INLINE_VECS);
b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits;
b->bio.bi_bdev = b->c->bdev;
b->bio.bi_end_io = inline_endio;
@@ -1316,7 +1314,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c)
{
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = WRITE_FLUSH,
+ .bi_op_flags = REQ_PREFLUSH,
.mem.type = DM_IO_KMEM,
.mem.ptr.addr = NULL,
.client = c->dm_io,
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a2768835d394..68a9eb4f3f36 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1135,7 +1135,7 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone)
clone->bi_private = io;
clone->bi_end_io = crypt_endio;
clone->bi_bdev = cc->dev->bdev;
- bio_set_op_attrs(clone, bio_op(io->base_bio), bio_flags(io->base_bio));
+ clone->bi_opf = io->base_bio->bi_opf;
}
static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 07fc1ad42ec5..33e71ea6cc14 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -308,7 +308,7 @@ static int flush_header(struct log_c *lc)
};
lc->io_req.bi_op = REQ_OP_WRITE;
- lc->io_req.bi_op_flags = WRITE_FLUSH;
+ lc->io_req.bi_op_flags = REQ_PREFLUSH;
return dm_io(&lc->io_req, 1, &null_location, NULL);
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 9a8b71067c6e..2ddc2d20e62d 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -260,7 +260,7 @@ static int mirror_flush(struct dm_target *ti)
struct mirror *m;
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = WRITE_FLUSH,
+ .bi_op_flags = REQ_PREFLUSH,
.mem.type = DM_IO_KMEM,
.mem.ptr.addr = NULL,
.client = ms->io_client,
@@ -656,7 +656,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
struct mirror *m;
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = bio->bi_opf & WRITE_FLUSH_FUA,
+ .bi_op_flags = bio->bi_opf & (REQ_FUA | REQ_PREFLUSH),
.mem.type = DM_IO_BIO,
.mem.ptr.bio = bio,
.notify.fn = write_callback,
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 1d0d2adc050a..b2a9e2d161e4 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -75,12 +75,6 @@ static void dm_old_start_queue(struct request_queue *q)
static void dm_mq_start_queue(struct request_queue *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- queue_flag_clear(QUEUE_FLAG_STOPPED, q);
- spin_unlock_irqrestore(q->queue_lock, flags);
-
blk_mq_start_stopped_hw_queues(q, true);
blk_mq_kick_requeue_list(q);
}
@@ -105,20 +99,10 @@ static void dm_old_stop_queue(struct request_queue *q)
static void dm_mq_stop_queue(struct request_queue *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- if (blk_queue_stopped(q)) {
- spin_unlock_irqrestore(q->queue_lock, flags);
+ if (blk_mq_queue_stopped(q))
return;
- }
-
- queue_flag_set(QUEUE_FLAG_STOPPED, q);
- spin_unlock_irqrestore(q->queue_lock, flags);
- /* Avoid that requeuing could restart the queue. */
- blk_mq_cancel_requeue_work(q);
- blk_mq_stop_hw_queues(q);
+ blk_mq_quiesce_queue(q);
}
void dm_stop_queue(struct request_queue *q)
@@ -313,7 +297,7 @@ static void dm_unprep_request(struct request *rq)
if (!rq->q->mq_ops) {
rq->special = NULL;
- rq->cmd_flags &= ~REQ_DONTPREP;
+ rq->rq_flags &= ~RQF_DONTPREP;
}
if (clone)
@@ -338,12 +322,7 @@ static void dm_old_requeue_request(struct request *rq)
static void __dm_mq_kick_requeue_list(struct request_queue *q, unsigned long msecs)
{
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- if (!blk_queue_stopped(q))
- blk_mq_delay_kick_requeue_list(q, msecs);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_mq_delay_kick_requeue_list(q, msecs);
}
void dm_mq_kick_requeue_list(struct mapped_device *md)
@@ -354,7 +333,7 @@ EXPORT_SYMBOL(dm_mq_kick_requeue_list);
static void dm_mq_delay_requeue_request(struct request *rq, unsigned long msecs)
{
- blk_mq_requeue_request(rq);
+ blk_mq_requeue_request(rq, false);
__dm_mq_kick_requeue_list(rq->q, msecs);
}
@@ -431,7 +410,7 @@ static void dm_softirq_done(struct request *rq)
return;
}
- if (rq->cmd_flags & REQ_FAILED)
+ if (rq->rq_flags & RQF_FAILED)
mapped = false;
dm_done(clone, tio->error, mapped);
@@ -460,7 +439,7 @@ static void dm_complete_request(struct request *rq, int error)
*/
static void dm_kill_unmapped_request(struct request *rq, int error)
{
- rq->cmd_flags |= REQ_FAILED;
+ rq->rq_flags |= RQF_FAILED;
dm_complete_request(rq, error);
}
@@ -476,7 +455,7 @@ static void end_clone_request(struct request *clone, int error)
* For just cleaning up the information of the queue in which
* the clone was dispatched.
* The clone is *NOT* freed actually here because it is alloced
- * from dm own mempool (REQ_ALLOCED isn't set).
+ * from dm own mempool (RQF_ALLOCED isn't set).
*/
__blk_put_request(clone->q, clone);
}
@@ -497,7 +476,7 @@ static void dm_dispatch_clone_request(struct request *clone, struct request *rq)
int r;
if (blk_queue_io_stat(clone->q))
- clone->cmd_flags |= REQ_IO_STAT;
+ clone->rq_flags |= RQF_IO_STAT;
clone->start_time = jiffies;
r = blk_insert_cloned_request(clone->q, clone);
@@ -633,7 +612,7 @@ static int dm_old_prep_fn(struct request_queue *q, struct request *rq)
return BLKPREP_DEFER;
rq->special = tio;
- rq->cmd_flags |= REQ_DONTPREP;
+ rq->rq_flags |= RQF_DONTPREP;
return BLKPREP_OK;
}
@@ -904,17 +883,6 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
dm_put_live_table(md, srcu_idx);
}
- /*
- * On suspend dm_stop_queue() handles stopping the blk-mq
- * request_queue BUT: even though the hw_queues are marked
- * BLK_MQ_S_STOPPED at that point there is still a race that
- * is allowing block/blk-mq.c to call ->queue_rq against a
- * hctx that it really shouldn't. The following check guards
- * against this rarity (albeit _not_ race-free).
- */
- if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
- return BLK_MQ_RQ_QUEUE_BUSY;
-
if (ti->type->busy && ti->type->busy(ti))
return BLK_MQ_RQ_QUEUE_BUSY;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index b8cf956b577b..b93476c3ba3f 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -741,7 +741,7 @@ static void persistent_commit_exception(struct dm_exception_store *store,
/*
* Commit exceptions to disk.
*/
- if (ps->valid && area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA))
+ if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA))
ps->valid = 0;
/*
@@ -818,7 +818,7 @@ static int persistent_commit_merge(struct dm_exception_store *store,
for (i = 0; i < nr_merged; i++)
clear_exception(ps, ps->current_committed - 1 - i);
- r = area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA);
+ r = area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA);
if (r < 0)
return r;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ef7bf1dd6900..ffa97b742a68 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1525,9 +1525,9 @@ static struct mapped_device *alloc_dev(int minor)
if (!md->bdev)
goto bad;
- bio_init(&md->flush_bio);
+ bio_init(&md->flush_bio, NULL, 0);
md->flush_bio.bi_bdev = md->bdev;
- bio_set_op_attrs(&md->flush_bio, REQ_OP_WRITE, WRITE_FLUSH);
+ md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
dm_stats_init(&md->stats);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2089d46b0eb8..f975cd08923d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -394,7 +394,7 @@ static void submit_flushes(struct work_struct *ws)
bi->bi_end_io = md_end_flush;
bi->bi_private = rdev;
bi->bi_bdev = rdev->bdev;
- bio_set_op_attrs(bi, REQ_OP_WRITE, WRITE_FLUSH);
+ bi->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
atomic_inc(&mddev->flush_pending);
submit_bio(bi);
rcu_read_lock();
@@ -743,7 +743,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
bio_add_page(bio, page, size, 0);
bio->bi_private = rdev;
bio->bi_end_io = super_written;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH_FUA);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA;
atomic_inc(&mddev->pending_writes);
submit_bio(bio);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 673efbd6fc47..4da06d813b8f 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -130,7 +130,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
}
multipath = conf->multipaths + mp_bh->path;
- bio_init(&mp_bh->bio);
+ bio_init(&mp_bh->bio, NULL, 0);
__bio_clone_fast(&mp_bh->bio, bio);
mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index a227a9f3ee65..8491edcfb5a6 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -685,7 +685,7 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log)
bio_reset(&log->flush_bio);
log->flush_bio.bi_bdev = log->rdev->bdev;
log->flush_bio.bi_end_io = r5l_log_flush_endio;
- bio_set_op_attrs(&log->flush_bio, REQ_OP_WRITE, WRITE_FLUSH);
+ log->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
submit_bio(&log->flush_bio);
}
@@ -1053,7 +1053,7 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
mb->checksum = cpu_to_le32(crc);
if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE,
- WRITE_FUA, false)) {
+ REQ_FUA, false)) {
__free_page(page);
return -EIO;
}
@@ -1205,7 +1205,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
INIT_LIST_HEAD(&log->io_end_ios);
INIT_LIST_HEAD(&log->flushing_ios);
INIT_LIST_HEAD(&log->finished_ios);
- bio_init(&log->flush_bio);
+ bio_init(&log->flush_bio, NULL, 0);
log->io_kc = KMEM_CACHE(r5l_io_unit, 0);
if (!log->io_kc)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 92ac251e91e6..5f9e28443c8a 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -913,7 +913,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
op = REQ_OP_WRITE;
if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
- op_flags = WRITE_FUA;
+ op_flags = REQ_FUA;
if (test_bit(R5_Discard, &sh->dev[i].flags))
op = REQ_OP_DISCARD;
} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
@@ -2004,13 +2004,8 @@ static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp,
for (i = 0; i < disks; i++) {
struct r5dev *dev = &sh->dev[i];
- bio_init(&dev->req);
- dev->req.bi_io_vec = &dev->vec;
- dev->req.bi_max_vecs = 1;
-
- bio_init(&dev->rreq);
- dev->rreq.bi_io_vec = &dev->rvec;
- dev->rreq.bi_max_vecs = 1;
+ bio_init(&dev->req, &dev->vec, 1);
+ bio_init(&dev->rreq, &dev->rvec, 1);
}
}
return sh;
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index 9914f69a4a02..0da622f5fe69 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -1198,7 +1198,6 @@ static const struct net_device_ops dvb_netdev_ops = {
.ndo_start_xmit = dvb_net_tx,
.ndo_set_rx_mode = dvb_net_set_multicast_list,
.ndo_set_mac_address = dvb_net_set_mac,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -1209,6 +1208,7 @@ static void dvb_net_setup(struct net_device *dev)
dev->header_ops = &dvb_header_ops;
dev->netdev_ops = &dvb_netdev_ops;
dev->mtu = 4096;
+ dev->max_mtu = 4096;
dev->flags |= IFF_NOARP;
}
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index aacf584f2a42..f3512404bc52 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -2006,7 +2006,7 @@ static int msb_prepare_req(struct request_queue *q, struct request *req)
blk_dump_rq_flags(req, "MS unsupported request");
return BLKPREP_KILL;
}
- req->cmd_flags |= REQ_DONTPREP;
+ req->rq_flags |= RQF_DONTPREP;
return BLKPREP_OK;
}
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index c1472275fe57..fa0746d182ff 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -834,7 +834,7 @@ static int mspro_block_prepare_req(struct request_queue *q, struct request *req)
return BLKPREP_KILL;
}
- req->cmd_flags |= REQ_DONTPREP;
+ req->rq_flags |= RQF_DONTPREP;
return BLKPREP_OK;
}
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 6955c9e22d57..55dd71bbdc2a 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -549,16 +549,6 @@ mpt_lan_close(struct net_device *dev)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
-mpt_lan_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Tx timeout handler. */
static void
mpt_lan_tx_timeout(struct net_device *dev)
@@ -1304,7 +1294,6 @@ static const struct net_device_ops mpt_netdev_ops = {
.ndo_open = mpt_lan_open,
.ndo_stop = mpt_lan_close,
.ndo_start_xmit = mpt_lan_sdu_send,
- .ndo_change_mtu = mpt_lan_change_mtu,
.ndo_tx_timeout = mpt_lan_tx_timeout,
};
@@ -1375,6 +1364,10 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
dev->netdev_ops = &mpt_netdev_ops;
dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
+ /* MTU range: 96 - 65280 */
+ dev->min_mtu = MPT_LAN_MIN_MTU;
+ dev->max_mtu = MPT_LAN_MAX_MTU;
+
dlprintk((KERN_INFO MYNAM ": Finished registering dev "
"and setting initial values\n"));
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df6442ba2b..1ed0584f494e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -756,24 +756,20 @@ config UCB1400_CORE
module will be called ucb1400_core.
config MFD_PM8XXX
- tristate
-
-config MFD_PM8921_CORE
- tristate "Qualcomm PM8921 PMIC chip"
+ tristate "Qualcomm PM8xxx PMIC chips driver"
depends on (ARM || HEXAGON)
select IRQ_DOMAIN
select MFD_CORE
- select MFD_PM8XXX
select REGMAP
help
If you say yes to this option, support will be included for the
- built-in PM8921 PMIC chip.
+ built-in PM8xxx PMIC chips.
- This is required if your board has a PM8921 and uses its features,
+ This is required if your board has a PM8xxx and uses its features,
such as: MPPs, GPIOs, regulators, interrupts, and PWM.
- Say M here if you want to include support for PM8921 chip as a module.
- This will build a module called "pm8921-core".
+ Say M here if you want to include support for PM8xxx chips as a
+ module. This will build a module called "pm8xxx-core".
config MFD_QCOM_RPM
tristate "Qualcomm Resource Power Manager (RPM)"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9834e669d985..7bb5a50127cb 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -172,7 +172,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
-obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o
+obj-$(CONFIG_MFD_PM8XXX) += qcom-pm8xxx.o ssbi.o
obj-$(CONFIG_MFD_QCOM_RPM) += qcom_rpm.o
obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/qcom-pm8xxx.c
index 0e3a2ea25942..7f9620ec61e8 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -53,7 +53,7 @@
#define REG_HWREV 0x002 /* PMIC4 revision */
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
-#define PM8921_NR_IRQS 256
+#define PM8XXX_NR_IRQS 256
struct pm_irq_chip {
struct regmap *regmap;
@@ -308,22 +308,22 @@ static const struct regmap_config ssbi_regmap_config = {
.reg_write = ssbi_reg_write
};
-static const struct of_device_id pm8921_id_table[] = {
+static const struct of_device_id pm8xxx_id_table[] = {
{ .compatible = "qcom,pm8018", },
{ .compatible = "qcom,pm8058", },
{ .compatible = "qcom,pm8921", },
{ }
};
-MODULE_DEVICE_TABLE(of, pm8921_id_table);
+MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
-static int pm8921_probe(struct platform_device *pdev)
+static int pm8xxx_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int irq, rc;
unsigned int val;
u32 rev;
struct pm_irq_chip *chip;
- unsigned int nirqs = PM8921_NR_IRQS;
+ unsigned int nirqs = PM8XXX_NR_IRQS;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -384,46 +384,46 @@ static int pm8921_probe(struct platform_device *pdev)
return rc;
}
-static int pm8921_remove_child(struct device *dev, void *unused)
+static int pm8xxx_remove_child(struct device *dev, void *unused)
{
platform_device_unregister(to_platform_device(dev));
return 0;
}
-static int pm8921_remove(struct platform_device *pdev)
+static int pm8xxx_remove(struct platform_device *pdev)
{
int irq = platform_get_irq(pdev, 0);
struct pm_irq_chip *chip = platform_get_drvdata(pdev);
- device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
+ device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
irq_set_chained_handler_and_data(irq, NULL, NULL);
irq_domain_remove(chip->irqdomain);
return 0;
}
-static struct platform_driver pm8921_driver = {
- .probe = pm8921_probe,
- .remove = pm8921_remove,
+static struct platform_driver pm8xxx_driver = {
+ .probe = pm8xxx_probe,
+ .remove = pm8xxx_remove,
.driver = {
- .name = "pm8921-core",
- .of_match_table = pm8921_id_table,
+ .name = "pm8xxx-core",
+ .of_match_table = pm8xxx_id_table,
},
};
-static int __init pm8921_init(void)
+static int __init pm8xxx_init(void)
{
- return platform_driver_register(&pm8921_driver);
+ return platform_driver_register(&pm8xxx_driver);
}
-subsys_initcall(pm8921_init);
+subsys_initcall(pm8xxx_init);
-static void __exit pm8921_exit(void)
+static void __exit pm8xxx_exit(void)
{
- platform_driver_unregister(&pm8921_driver);
+ platform_driver_unregister(&pm8xxx_driver);
}
-module_exit(pm8921_exit);
+module_exit(pm8xxx_exit);
MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC 8921 core driver");
+MODULE_DESCRIPTION("PMIC 8xxx core driver");
MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pm8921-core");
+MODULE_ALIAS("platform:pm8xxx-core");
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c2107f..cfa1039c62e7 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
void lkdtm_HUNG_TASK(void);
void lkdtm_ATOMIC_UNDERFLOW(void);
void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
/* lkdtm_heap.c */
void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae1894b32..f336206d4b1f 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -5,8 +5,13 @@
* test source files.
*/
#include "lkdtm.h"
+#include <linux/list.h>
#include <linux/sched.h>
+struct lkdtm_list {
+ struct list_head node;
+};
+
/*
* Make sure our attempts to over run the kernel stack doesn't trigger
* a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
pr_info("attempting bad atomic overflow\n");
atomic_inc(&over);
}
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+ /*
+ * Initially, an empty list via LIST_HEAD:
+ * test_head.next = &test_head
+ * test_head.prev = &test_head
+ */
+ LIST_HEAD(test_head);
+ struct lkdtm_list good, bad;
+ void *target[2] = { };
+ void *redirection = &target;
+
+ pr_info("attempting good list addition\n");
+
+ /*
+ * Adding to the list performs these actions:
+ * test_head.next->prev = &good.node
+ * good.node.next = test_head.next
+ * good.node.prev = test_head
+ * test_head.next = good.node
+ */
+ list_add(&good.node, &test_head);
+
+ pr_info("attempting corrupted list addition\n");
+ /*
+ * In simulating this "write what where" primitive, the "what" is
+ * the address of &bad.node, and the "where" is the address held
+ * by "redirection".
+ */
+ test_head.next = redirection;
+ list_add(&bad.node, &test_head);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+ LIST_HEAD(test_head);
+ struct lkdtm_list item;
+ void *target[2] = { };
+ void *redirection = &target;
+
+ list_add(&item.node, &test_head);
+
+ pr_info("attempting good list removal\n");
+ list_del(&item.node);
+
+ pr_info("attempting corrupted list removal\n");
+ list_add(&item.node, &test_head);
+
+ /* As with the list_add() test above, this corrupts "next". */
+ item.node.next = redirection;
+ list_del(&item.node);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_del() corruption not detected!\n");
+}
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8d67f6..7eeb71a75549 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
CRASHTYPE(EXCEPTION),
CRASHTYPE(LOOP),
CRASHTYPE(OVERFLOW),
+ CRASHTYPE(CORRUPT_LIST_ADD),
+ CRASHTYPE(CORRUPT_LIST_DEL),
CRASHTYPE(CORRUPT_STACK),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
CRASHTYPE(OVERWRITE_ALLOCATION),
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 557f9782c53c..0c26eaf5f62b 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -118,6 +118,8 @@ static DEFINE_SPINLOCK(xpnet_broadcast_lock);
* now, the default is 64KB.
*/
#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+/* 68 comes from min TCP+IP+MAC header */
+#define XPNET_MIN_MTU 68
/* 32KB has been determined to be the ideal */
#define XPNET_DEF_MTU (0x8000UL)
@@ -330,22 +332,6 @@ xpnet_dev_stop(struct net_device *dev)
return 0;
}
-static int
-xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
-{
- /* 68 comes from min TCP+IP+MAC header */
- if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
- dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
- "between 68 and %ld\n", dev->name, new_mtu,
- XPNET_MAX_MTU);
- return -EINVAL;
- }
-
- dev->mtu = new_mtu;
- dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
- return 0;
-}
-
/*
* Notification that the other end has received the message and
* DMA'd the skb information. At this point, they are done with
@@ -519,7 +505,6 @@ static const struct net_device_ops xpnet_netdev_ops = {
.ndo_open = xpnet_dev_open,
.ndo_stop = xpnet_dev_stop,
.ndo_start_xmit = xpnet_dev_hard_start_xmit,
- .ndo_change_mtu = xpnet_dev_change_mtu,
.ndo_tx_timeout = xpnet_dev_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -555,6 +540,8 @@ xpnet_init(void)
xpnet_device->netdev_ops = &xpnet_netdev_ops;
xpnet_device->mtu = XPNET_DEF_MTU;
+ xpnet_device->min_mtu = XPNET_MIN_MTU;
+ xpnet_device->max_mtu = XPNET_MAX_MTU;
/*
* Multicast assumes the LSB of the first octet is set for multicast
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 709a872ed484..bab3f07b1117 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -66,9 +66,6 @@ MODULE_ALIAS("mmc:block");
#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
-
static DEFINE_MUTEX(block_mutex);
/*
@@ -102,7 +99,6 @@ struct mmc_blk_data {
unsigned int flags;
#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */
-#define MMC_BLK_PACKED_CMD (1 << 2) /* MMC packed command support */
unsigned int usage;
unsigned int read_only;
@@ -126,12 +122,6 @@ struct mmc_blk_data {
static DEFINE_MUTEX(open_lock);
-enum {
- MMC_PACKED_NR_IDX = -1,
- MMC_PACKED_NR_ZERO,
- MMC_PACKED_NR_SINGLE,
-};
-
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
@@ -139,17 +129,6 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
struct mmc_blk_data *md);
static int get_card_status(struct mmc_card *card, u32 *status, int retries);
-static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)
-{
- struct mmc_packed *packed = mqrq->packed;
-
- mqrq->cmd_type = MMC_PACKED_NONE;
- packed->nr_entries = MMC_PACKED_NR_ZERO;
- packed->idx_failure = MMC_PACKED_NR_IDX;
- packed->retries = 0;
- packed->blocks = 0;
-}
-
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
struct mmc_blk_data *md;
@@ -854,7 +833,7 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
}
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
- bool hw_busy_detect, struct request *req, int *gen_err)
+ bool hw_busy_detect, struct request *req, bool *gen_err)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
int err = 0;
@@ -871,7 +850,7 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
if (status & R1_ERROR) {
pr_err("%s: %s: error sending status cmd, status %#x\n",
req->rq_disk->disk_name, __func__, status);
- *gen_err = 1;
+ *gen_err = true;
}
/* We may rely on the host hw to handle busy detection.*/
@@ -902,7 +881,7 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
}
static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
- struct request *req, int *gen_err, u32 *stop_status)
+ struct request *req, bool *gen_err, u32 *stop_status)
{
struct mmc_host *host = card->host;
struct mmc_command cmd = {0};
@@ -940,7 +919,7 @@ static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
(*stop_status & R1_ERROR)) {
pr_err("%s: %s: general error sending stop command, resp %#x\n",
req->rq_disk->disk_name, __func__, *stop_status);
- *gen_err = 1;
+ *gen_err = true;
}
return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
@@ -1014,7 +993,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
* Otherwise we don't understand what happened, so abort.
*/
static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
- struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
+ struct mmc_blk_request *brq, bool *ecc_err, bool *gen_err)
{
bool prev_cmd_status_valid = true;
u32 status, stop_status = 0;
@@ -1053,7 +1032,7 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
if ((status & R1_CARD_ECC_FAILED) ||
(brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
(brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
- *ecc_err = 1;
+ *ecc_err = true;
/* Flag General errors */
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
@@ -1062,7 +1041,7 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
req->rq_disk->disk_name, __func__,
brq->stop.resp[0], status);
- *gen_err = 1;
+ *gen_err = true;
}
/*
@@ -1085,7 +1064,7 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
}
if (stop_status & R1_CARD_ECC_FAILED)
- *ecc_err = 1;
+ *ecc_err = true;
}
/* Check for set block count errors */
@@ -1154,7 +1133,7 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
int mmc_access_rpmb(struct mmc_queue *mq)
{
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
/*
* If this is a RPMB partition access, return ture
*/
@@ -1166,7 +1145,7 @@ int mmc_access_rpmb(struct mmc_queue *mq)
static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_DISCARD;
@@ -1210,7 +1189,7 @@ out:
static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
struct request *req)
{
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_SECDISCARD;
@@ -1276,7 +1255,7 @@ out:
static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
{
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
int ret = 0;
@@ -1320,15 +1299,16 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
R1_CC_ERROR | /* Card controller error */ \
R1_ERROR) /* General/unknown error */
-static int mmc_blk_err_check(struct mmc_card *card,
- struct mmc_async_req *areq)
+static enum mmc_blk_status mmc_blk_err_check(struct mmc_card *card,
+ struct mmc_async_req *areq)
{
struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
mmc_active);
struct mmc_blk_request *brq = &mq_mrq->brq;
struct request *req = mq_mrq->req;
int need_retune = card->host->need_retune;
- int ecc_err = 0, gen_err = 0;
+ bool ecc_err = false;
+ bool gen_err = false;
/*
* sbc.error indicates a problem with the set block count
@@ -1378,7 +1358,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
req->rq_disk->disk_name, __func__,
brq->stop.resp[0]);
- gen_err = 1;
+ gen_err = true;
}
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
@@ -1419,67 +1399,12 @@ static int mmc_blk_err_check(struct mmc_card *card,
if (!brq->data.bytes_xfered)
return MMC_BLK_RETRY;
- if (mmc_packed_cmd(mq_mrq->cmd_type)) {
- if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered))
- return MMC_BLK_PARTIAL;
- else
- return MMC_BLK_SUCCESS;
- }
-
if (blk_rq_bytes(req) != brq->data.bytes_xfered)
return MMC_BLK_PARTIAL;
return MMC_BLK_SUCCESS;
}
-static int mmc_blk_packed_err_check(struct mmc_card *card,
- struct mmc_async_req *areq)
-{
- struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req,
- mmc_active);
- struct request *req = mq_rq->req;
- struct mmc_packed *packed = mq_rq->packed;
- int err, check, status;
- u8 *ext_csd;
-
- packed->retries--;
- check = mmc_blk_err_check(card, areq);
- err = get_card_status(card, &status, 0);
- if (err) {
- pr_err("%s: error %d sending status command\n",
- req->rq_disk->disk_name, err);
- return MMC_BLK_ABORT;
- }
-
- if (status & R1_EXCEPTION_EVENT) {
- err = mmc_get_ext_csd(card, &ext_csd);
- if (err) {
- pr_err("%s: error %d sending ext_csd\n",
- req->rq_disk->disk_name, err);
- return MMC_BLK_ABORT;
- }
-
- if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] &
- EXT_CSD_PACKED_FAILURE) &&
- (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
- EXT_CSD_PACKED_GENERIC_ERROR)) {
- if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
- EXT_CSD_PACKED_INDEXED_ERROR) {
- packed->idx_failure =
- ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1;
- check = MMC_BLK_PARTIAL;
- }
- pr_err("%s: packed cmd failed, nr %u, sectors %u, "
- "failure index: %d\n",
- req->rq_disk->disk_name, packed->nr_entries,
- packed->blocks, packed->idx_failure);
- }
- kfree(ext_csd);
- }
-
- return check;
-}
-
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
struct mmc_card *card,
int disable_multi,
@@ -1488,7 +1413,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
u32 readcmd, writecmd;
struct mmc_blk_request *brq = &mqrq->brq;
struct request *req = mqrq->req;
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
bool do_data_tag;
/*
@@ -1640,224 +1565,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
mmc_queue_bounce_pre(mqrq);
}
-static inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q,
- struct mmc_card *card)
-{
- unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512;
- unsigned int max_seg_sz = queue_max_segment_size(q);
- unsigned int len, nr_segs = 0;
-
- do {
- len = min(hdr_sz, max_seg_sz);
- hdr_sz -= len;
- nr_segs++;
- } while (hdr_sz);
-
- return nr_segs;
-}
-
-static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
-{
- struct request_queue *q = mq->queue;
- struct mmc_card *card = mq->card;
- struct request *cur = req, *next = NULL;
- struct mmc_blk_data *md = mq->data;
- struct mmc_queue_req *mqrq = mq->mqrq_cur;
- bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN;
- unsigned int req_sectors = 0, phys_segments = 0;
- unsigned int max_blk_count, max_phys_segs;
- bool put_back = true;
- u8 max_packed_rw = 0;
- u8 reqs = 0;
-
- /*
- * We don't need to check packed for any further
- * operation of packed stuff as we set MMC_PACKED_NONE
- * and return zero for reqs if geting null packed. Also
- * we clean the flag of MMC_BLK_PACKED_CMD to avoid doing
- * it again when removing blk req.
- */
- if (!mqrq->packed) {
- md->flags &= (~MMC_BLK_PACKED_CMD);
- goto no_packed;
- }
-
- if (!(md->flags & MMC_BLK_PACKED_CMD))
- goto no_packed;
-
- if ((rq_data_dir(cur) == WRITE) &&
- mmc_host_packed_wr(card->host))
- max_packed_rw = card->ext_csd.max_packed_writes;
-
- if (max_packed_rw == 0)
- goto no_packed;
-
- if (mmc_req_rel_wr(cur) &&
- (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
- goto no_packed;
-
- if (mmc_large_sector(card) &&
- !IS_ALIGNED(blk_rq_sectors(cur), 8))
- goto no_packed;
-
- mmc_blk_clear_packed(mqrq);
-
- max_blk_count = min(card->host->max_blk_count,
- card->host->max_req_size >> 9);
- if (unlikely(max_blk_count > 0xffff))
- max_blk_count = 0xffff;
-
- max_phys_segs = queue_max_segments(q);
- req_sectors += blk_rq_sectors(cur);
- phys_segments += cur->nr_phys_segments;
-
- if (rq_data_dir(cur) == WRITE) {
- req_sectors += mmc_large_sector(card) ? 8 : 1;
- phys_segments += mmc_calc_packed_hdr_segs(q, card);
- }
-
- do {
- if (reqs >= max_packed_rw - 1) {
- put_back = false;
- break;
- }
-
- spin_lock_irq(q->queue_lock);
- next = blk_fetch_request(q);
- spin_unlock_irq(q->queue_lock);
- if (!next) {
- put_back = false;
- break;
- }
-
- if (mmc_large_sector(card) &&
- !IS_ALIGNED(blk_rq_sectors(next), 8))
- break;
-
- if (req_op(next) == REQ_OP_DISCARD ||
- req_op(next) == REQ_OP_SECURE_ERASE ||
- req_op(next) == REQ_OP_FLUSH)
- break;
-
- if (rq_data_dir(cur) != rq_data_dir(next))
- break;
-
- if (mmc_req_rel_wr(next) &&
- (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
- break;
-
- req_sectors += blk_rq_sectors(next);
- if (req_sectors > max_blk_count)
- break;
-
- phys_segments += next->nr_phys_segments;
- if (phys_segments > max_phys_segs)
- break;
-
- list_add_tail(&next->queuelist, &mqrq->packed->list);
- cur = next;
- reqs++;
- } while (1);
-
- if (put_back) {
- spin_lock_irq(q->queue_lock);
- blk_requeue_request(q, next);
- spin_unlock_irq(q->queue_lock);
- }
-
- if (reqs > 0) {
- list_add(&req->queuelist, &mqrq->packed->list);
- mqrq->packed->nr_entries = ++reqs;
- mqrq->packed->retries = reqs;
- return reqs;
- }
-
-no_packed:
- mqrq->cmd_type = MMC_PACKED_NONE;
- return 0;
-}
-
-static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
- struct mmc_card *card,
- struct mmc_queue *mq)
-{
- struct mmc_blk_request *brq = &mqrq->brq;
- struct request *req = mqrq->req;
- struct request *prq;
- struct mmc_blk_data *md = mq->data;
- struct mmc_packed *packed = mqrq->packed;
- bool do_rel_wr, do_data_tag;
- __le32 *packed_cmd_hdr;
- u8 hdr_blocks;
- u8 i = 1;
-
- mqrq->cmd_type = MMC_PACKED_WRITE;
- packed->blocks = 0;
- packed->idx_failure = MMC_PACKED_NR_IDX;
-
- packed_cmd_hdr = packed->cmd_hdr;
- memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr));
- packed_cmd_hdr[0] = cpu_to_le32((packed->nr_entries << 16) |
- (PACKED_CMD_WR << 8) | PACKED_CMD_VER);
- hdr_blocks = mmc_large_sector(card) ? 8 : 1;
-
- /*
- * Argument for each entry of packed group
- */
- list_for_each_entry(prq, &packed->list, queuelist) {
- do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR);
- do_data_tag = (card->ext_csd.data_tag_unit_size) &&
- (prq->cmd_flags & REQ_META) &&
- (rq_data_dir(prq) == WRITE) &&
- blk_rq_bytes(prq) >= card->ext_csd.data_tag_unit_size;
- /* Argument of CMD23 */
- packed_cmd_hdr[(i * 2)] = cpu_to_le32(
- (do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) |
- (do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) |
- blk_rq_sectors(prq));
- /* Argument of CMD18 or CMD25 */
- packed_cmd_hdr[((i * 2)) + 1] = cpu_to_le32(
- mmc_card_blockaddr(card) ?
- blk_rq_pos(prq) : blk_rq_pos(prq) << 9);
- packed->blocks += blk_rq_sectors(prq);
- i++;
- }
-
- memset(brq, 0, sizeof(struct mmc_blk_request));
- brq->mrq.cmd = &brq->cmd;
- brq->mrq.data = &brq->data;
- brq->mrq.sbc = &brq->sbc;
- brq->mrq.stop = &brq->stop;
-
- brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
- brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks);
- brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
- brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
- brq->cmd.arg = blk_rq_pos(req);
- if (!mmc_card_blockaddr(card))
- brq->cmd.arg <<= 9;
- brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-
- brq->data.blksz = 512;
- brq->data.blocks = packed->blocks + hdr_blocks;
- brq->data.flags = MMC_DATA_WRITE;
-
- brq->stop.opcode = MMC_STOP_TRANSMISSION;
- brq->stop.arg = 0;
- brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-
- mmc_set_data_timeout(&brq->data, card);
-
- brq->data.sg = mqrq->sg;
- brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
-
- mqrq->mmc_active.mrq = &brq->mrq;
- mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
-
- mmc_queue_bounce_pre(mqrq);
-}
-
static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
struct mmc_blk_request *brq, struct request *req,
int ret)
@@ -1881,97 +1588,25 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
ret = blk_end_request(req, 0, blocks << 9);
}
} else {
- if (!mmc_packed_cmd(mq_rq->cmd_type))
- ret = blk_end_request(req, 0, brq->data.bytes_xfered);
+ ret = blk_end_request(req, 0, brq->data.bytes_xfered);
}
return ret;
}
-static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
-{
- struct request *prq;
- struct mmc_packed *packed = mq_rq->packed;
- int idx = packed->idx_failure, i = 0;
- int ret = 0;
-
- while (!list_empty(&packed->list)) {
- prq = list_entry_rq(packed->list.next);
- if (idx == i) {
- /* retry from error index */
- packed->nr_entries -= idx;
- mq_rq->req = prq;
- ret = 1;
-
- if (packed->nr_entries == MMC_PACKED_NR_SINGLE) {
- list_del_init(&prq->queuelist);
- mmc_blk_clear_packed(mq_rq);
- }
- return ret;
- }
- list_del_init(&prq->queuelist);
- blk_end_request(prq, 0, blk_rq_bytes(prq));
- i++;
- }
-
- mmc_blk_clear_packed(mq_rq);
- return ret;
-}
-
-static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)
-{
- struct request *prq;
- struct mmc_packed *packed = mq_rq->packed;
-
- while (!list_empty(&packed->list)) {
- prq = list_entry_rq(packed->list.next);
- list_del_init(&prq->queuelist);
- blk_end_request(prq, -EIO, blk_rq_bytes(prq));
- }
-
- mmc_blk_clear_packed(mq_rq);
-}
-
-static void mmc_blk_revert_packed_req(struct mmc_queue *mq,
- struct mmc_queue_req *mq_rq)
-{
- struct request *prq;
- struct request_queue *q = mq->queue;
- struct mmc_packed *packed = mq_rq->packed;
-
- while (!list_empty(&packed->list)) {
- prq = list_entry_rq(packed->list.prev);
- if (prq->queuelist.prev != &packed->list) {
- list_del_init(&prq->queuelist);
- spin_lock_irq(q->queue_lock);
- blk_requeue_request(mq->queue, prq);
- spin_unlock_irq(q->queue_lock);
- } else {
- list_del_init(&prq->queuelist);
- }
- }
-
- mmc_blk_clear_packed(mq_rq);
-}
-
static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
{
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
- struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
+ struct mmc_blk_request *brq;
int ret = 1, disable_multi = 0, retry = 0, type, retune_retry_done = 0;
enum mmc_blk_status status;
struct mmc_queue_req *mq_rq;
- struct request *req = rqc;
+ struct request *req;
struct mmc_async_req *areq;
- const u8 packed_nr = 2;
- u8 reqs = 0;
if (!rqc && !mq->mqrq_prev->req)
return 0;
- if (rqc)
- reqs = mmc_blk_prep_packed_list(mq, rqc);
-
do {
if (rqc) {
/*
@@ -1981,20 +1616,18 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
if (mmc_large_sector(card) &&
!IS_ALIGNED(blk_rq_sectors(rqc), 8)) {
pr_err("%s: Transfer size is not 4KB sector size aligned\n",
- req->rq_disk->disk_name);
+ rqc->rq_disk->disk_name);
mq_rq = mq->mqrq_cur;
+ req = rqc;
+ rqc = NULL;
goto cmd_abort;
}
- if (reqs >= packed_nr)
- mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur,
- card, mq);
- else
- mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+ mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
areq = &mq->mqrq_cur->mmc_active;
} else
areq = NULL;
- areq = mmc_start_req(card->host, areq, (int *) &status);
+ areq = mmc_start_req(card->host, areq, &status);
if (!areq) {
if (status == MMC_BLK_NEW_REQUEST)
mq->flags |= MMC_QUEUE_NEW_REQUEST;
@@ -2015,13 +1648,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
*/
mmc_blk_reset_success(md, type);
- if (mmc_packed_cmd(mq_rq->cmd_type)) {
- ret = mmc_blk_end_packed_req(mq_rq);
- break;
- } else {
- ret = blk_end_request(req, 0,
- brq->data.bytes_xfered);
- }
+ ret = blk_end_request(req, 0,
+ brq->data.bytes_xfered);
/*
* If the blk_end_request function returns non-zero even
@@ -2058,8 +1686,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
err = mmc_blk_reset(md, card->host, type);
if (!err)
break;
- if (err == -ENODEV ||
- mmc_packed_cmd(mq_rq->cmd_type))
+ if (err == -ENODEV)
goto cmd_abort;
/* Fall through */
}
@@ -2090,23 +1717,14 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
}
if (ret) {
- if (mmc_packed_cmd(mq_rq->cmd_type)) {
- if (!mq_rq->packed->retries)
- goto cmd_abort;
- mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
- mmc_start_req(card->host,
- &mq_rq->mmc_active, NULL);
- } else {
-
- /*
- * In case of a incomplete request
- * prepare it again and resend.
- */
- mmc_blk_rw_rq_prep(mq_rq, card,
- disable_multi, mq);
- mmc_start_req(card->host,
- &mq_rq->mmc_active, NULL);
- }
+ /*
+ * In case of a incomplete request
+ * prepare it again and resend.
+ */
+ mmc_blk_rw_rq_prep(mq_rq, card,
+ disable_multi, mq);
+ mmc_start_req(card->host,
+ &mq_rq->mmc_active, NULL);
mq_rq->brq.retune_retry_done = retune_retry_done;
}
} while (ret);
@@ -2114,28 +1732,18 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
return 1;
cmd_abort:
- if (mmc_packed_cmd(mq_rq->cmd_type)) {
- mmc_blk_abort_packed_req(mq_rq);
- } else {
- if (mmc_card_removed(card))
- req->cmd_flags |= REQ_QUIET;
- while (ret)
- ret = blk_end_request(req, -EIO,
- blk_rq_cur_bytes(req));
- }
+ if (mmc_card_removed(card))
+ req->rq_flags |= RQF_QUIET;
+ while (ret)
+ ret = blk_end_request(req, -EIO,
+ blk_rq_cur_bytes(req));
start_new_req:
if (rqc) {
if (mmc_card_removed(card)) {
- rqc->cmd_flags |= REQ_QUIET;
+ rqc->rq_flags |= RQF_QUIET;
blk_end_request_all(rqc, -EIO);
} else {
- /*
- * If current request is packed, it needs to put back.
- */
- if (mmc_packed_cmd(mq->mqrq_cur->cmd_type))
- mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
-
mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
mmc_start_req(card->host,
&mq->mqrq_cur->mmc_active, NULL);
@@ -2148,10 +1756,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
{
int ret;
- struct mmc_blk_data *md = mq->data;
+ struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
- struct mmc_host *host = card->host;
- unsigned long flags;
bool req_is_special = mmc_req_is_special(req);
if (req && !mq->mqrq_prev->req)
@@ -2184,11 +1790,6 @@ int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
mmc_blk_issue_rw_rq(mq, NULL);
ret = mmc_blk_issue_flush(mq, req);
} else {
- if (!req && host->areq) {
- spin_lock_irqsave(&host->context_info.lock, flags);
- host->context_info.is_waiting_last_req = true;
- spin_unlock_irqrestore(&host->context_info.lock, flags);
- }
ret = mmc_blk_issue_rw_rq(mq, req);
}
@@ -2266,7 +1867,7 @@ again:
if (ret)
goto err_putdisk;
- md->queue.data = md;
+ md->queue.blkdata = md;
md->disk->major = MMC_BLOCK_MAJOR;
md->disk->first_minor = devidx * perdev_minors;
@@ -2318,14 +1919,6 @@ again:
blk_queue_write_cache(md->queue.queue, true, true);
}
- if (mmc_card_mmc(card) &&
- (area_type == MMC_BLK_DATA_AREA_MAIN) &&
- (md->flags & MMC_BLK_CMD23) &&
- card->ext_csd.packed_event_en) {
- if (!mmc_packed_init(&md->queue, card))
- md->flags |= MMC_BLK_PACKED_CMD;
- }
-
return md;
err_putdisk:
@@ -2429,8 +2022,6 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
*/
card = md->queue.card;
mmc_cleanup_queue(&md->queue);
- if (md->flags & MMC_BLK_PACKED_CMD)
- mmc_packed_clean(&md->queue);
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 3678220964fe..ec1d1c46eb90 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -214,7 +214,8 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test,
struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len,
unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
{
- BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
+ if (WARN_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop))
+ return;
if (blocks > 1) {
mrq->cmd->opcode = write ?
@@ -694,7 +695,8 @@ static int mmc_test_cleanup(struct mmc_test_card *test)
static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
struct mmc_request *mrq, int write)
{
- BUG_ON(!mrq || !mrq->cmd || !mrq->data);
+ if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+ return;
if (mrq->data->blocks > 1) {
mrq->cmd->opcode = write ?
@@ -714,7 +716,8 @@ static int mmc_test_check_result(struct mmc_test_card *test,
{
int ret;
- BUG_ON(!mrq || !mrq->cmd || !mrq->data);
+ if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+ return -EINVAL;
ret = 0;
@@ -736,15 +739,28 @@ static int mmc_test_check_result(struct mmc_test_card *test,
return ret;
}
-static int mmc_test_check_result_async(struct mmc_card *card,
+static enum mmc_blk_status mmc_test_check_result_async(struct mmc_card *card,
struct mmc_async_req *areq)
{
struct mmc_test_async_req *test_async =
container_of(areq, struct mmc_test_async_req, areq);
+ int ret;
mmc_test_wait_busy(test_async->test);
- return mmc_test_check_result(test_async->test, areq->mrq);
+ /*
+ * FIXME: this would earlier just casts a regular error code,
+ * either of the kernel type -ERRORCODE or the local test framework
+ * RESULT_* errorcode, into an enum mmc_blk_status and return as
+ * result check. Instead, convert it to some reasonable type by just
+ * returning either MMC_BLK_SUCCESS or MMC_BLK_CMD_ERR.
+ * If possible, a reasonable error code should be returned.
+ */
+ ret = mmc_test_check_result(test_async->test, areq->mrq);
+ if (ret)
+ return MMC_BLK_CMD_ERR;
+
+ return MMC_BLK_SUCCESS;
}
/*
@@ -755,7 +771,8 @@ static int mmc_test_check_broken_result(struct mmc_test_card *test,
{
int ret;
- BUG_ON(!mrq || !mrq->cmd || !mrq->data);
+ if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+ return -EINVAL;
ret = 0;
@@ -817,8 +834,9 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
struct mmc_async_req *done_areq;
struct mmc_async_req *cur_areq = &test_areq[0].areq;
struct mmc_async_req *other_areq = &test_areq[1].areq;
+ enum mmc_blk_status status;
int i;
- int ret;
+ int ret = RESULT_OK;
test_areq[0].test = test;
test_areq[1].test = test;
@@ -834,10 +852,12 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
for (i = 0; i < count; i++) {
mmc_test_prepare_mrq(test, cur_areq->mrq, sg, sg_len, dev_addr,
blocks, blksz, write);
- done_areq = mmc_start_req(test->card->host, cur_areq, &ret);
+ done_areq = mmc_start_req(test->card->host, cur_areq, &status);
- if (ret || (!done_areq && i > 0))
+ if (status != MMC_BLK_SUCCESS || (!done_areq && i > 0)) {
+ ret = RESULT_FAIL;
goto err;
+ }
if (done_areq) {
if (done_areq->mrq == &mrq2)
@@ -851,7 +871,9 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
dev_addr += blocks;
}
- done_areq = mmc_start_req(test->card->host, NULL, &ret);
+ done_areq = mmc_start_req(test->card->host, NULL, &status);
+ if (status != MMC_BLK_SUCCESS)
+ ret = RESULT_FAIL;
return ret;
err:
@@ -2351,6 +2373,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
struct mmc_request *mrq;
unsigned long timeout;
bool expired = false;
+ enum mmc_blk_status blkstat = MMC_BLK_SUCCESS;
int ret = 0, cmd_ret;
u32 status = 0;
int count = 0;
@@ -2378,9 +2401,11 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
/* Start ongoing data request */
if (use_areq) {
- mmc_start_req(host, &test_areq.areq, &ret);
- if (ret)
+ mmc_start_req(host, &test_areq.areq, &blkstat);
+ if (blkstat != MMC_BLK_SUCCESS) {
+ ret = RESULT_FAIL;
goto out_free;
+ }
} else {
mmc_wait_for_req(host, mrq);
}
@@ -2413,10 +2438,13 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
} while (repeat_cmd && R1_CURRENT_STATE(status) != R1_STATE_TRAN);
/* Wait for data request to complete */
- if (use_areq)
- mmc_start_req(host, NULL, &ret);
- else
+ if (use_areq) {
+ mmc_start_req(host, NULL, &blkstat);
+ if (blkstat != MMC_BLK_SUCCESS)
+ ret = RESULT_FAIL;
+ } else {
mmc_wait_for_req_done(test->card->host, mrq);
+ }
/*
* For cap_cmd_during_tfr request, upper layer must send stop if
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 8037f73a109a..6ae6bfb8b221 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -44,7 +44,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
return BLKPREP_KILL;
- req->cmd_flags |= REQ_DONTPREP;
+ req->rq_flags |= RQF_DONTPREP;
return BLKPREP_OK;
}
@@ -53,6 +53,7 @@ static int mmc_queue_thread(void *d)
{
struct mmc_queue *mq = d;
struct request_queue *q = mq->queue;
+ struct mmc_context_info *cntx = &mq->card->host->context_info;
current->flags |= PF_MEMALLOC;
@@ -63,6 +64,19 @@ static int mmc_queue_thread(void *d)
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
req = blk_fetch_request(q);
+ mq->asleep = false;
+ cntx->is_waiting_last_req = false;
+ cntx->is_new_req = false;
+ if (!req) {
+ /*
+ * Dispatch queue is empty so set flags for
+ * mmc_request_fn() to wake us up.
+ */
+ if (mq->mqrq_prev->req)
+ cntx->is_waiting_last_req = true;
+ else
+ mq->asleep = true;
+ }
mq->mqrq_cur->req = req;
spin_unlock_irq(q->queue_lock);
@@ -115,31 +129,24 @@ static void mmc_request_fn(struct request_queue *q)
{
struct mmc_queue *mq = q->queuedata;
struct request *req;
- unsigned long flags;
struct mmc_context_info *cntx;
if (!mq) {
while ((req = blk_fetch_request(q)) != NULL) {
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
__blk_end_request_all(req, -EIO);
}
return;
}
cntx = &mq->card->host->context_info;
- if (!mq->mqrq_cur->req && mq->mqrq_prev->req) {
- /*
- * New MMC request arrived when MMC thread may be
- * blocked on the previous request to be complete
- * with no current request fetched
- */
- spin_lock_irqsave(&cntx->lock, flags);
- if (cntx->is_waiting_last_req) {
- cntx->is_new_req = true;
- wake_up_interruptible(&cntx->wait);
- }
- spin_unlock_irqrestore(&cntx->lock, flags);
- } else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
+
+ if (cntx->is_waiting_last_req) {
+ cntx->is_new_req = true;
+ wake_up_interruptible(&cntx->wait);
+ }
+
+ if (mq->asleep)
wake_up_process(mq->thread);
}
@@ -179,6 +186,82 @@ static void mmc_queue_setup_discard(struct request_queue *q,
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
}
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+static bool mmc_queue_alloc_bounce_bufs(struct mmc_queue *mq,
+ unsigned int bouncesz)
+{
+ int i;
+
+ for (i = 0; i < mq->qdepth; i++) {
+ mq->mqrq[i].bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mq->mqrq[i].bounce_buf)
+ goto out_err;
+ }
+
+ return true;
+
+out_err:
+ while (--i >= 0) {
+ kfree(mq->mqrq[i].bounce_buf);
+ mq->mqrq[i].bounce_buf = NULL;
+ }
+ pr_warn("%s: unable to allocate bounce buffers\n",
+ mmc_card_name(mq->card));
+ return false;
+}
+
+static int mmc_queue_alloc_bounce_sgs(struct mmc_queue *mq,
+ unsigned int bouncesz)
+{
+ int i, ret;
+
+ for (i = 0; i < mq->qdepth; i++) {
+ mq->mqrq[i].sg = mmc_alloc_sg(1, &ret);
+ if (ret)
+ return ret;
+
+ mq->mqrq[i].bounce_sg = mmc_alloc_sg(bouncesz / 512, &ret);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+static int mmc_queue_alloc_sgs(struct mmc_queue *mq, int max_segs)
+{
+ int i, ret;
+
+ for (i = 0; i < mq->qdepth; i++) {
+ mq->mqrq[i].sg = mmc_alloc_sg(max_segs, &ret);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void mmc_queue_req_free_bufs(struct mmc_queue_req *mqrq)
+{
+ kfree(mqrq->bounce_sg);
+ mqrq->bounce_sg = NULL;
+
+ kfree(mqrq->sg);
+ mqrq->sg = NULL;
+
+ kfree(mqrq->bounce_buf);
+ mqrq->bounce_buf = NULL;
+}
+
+static void mmc_queue_reqs_free_bufs(struct mmc_queue *mq)
+{
+ int i;
+
+ for (i = 0; i < mq->qdepth; i++)
+ mmc_queue_req_free_bufs(&mq->mqrq[i]);
+}
+
/**
* mmc_init_queue - initialise a queue structure.
* @mq: mmc queue
@@ -193,9 +276,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
{
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
- int ret;
- struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
- struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
+ bool bounce = false;
+ int ret = -ENOMEM;
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
@@ -205,8 +287,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (!mq->queue)
return -ENOMEM;
- mq->mqrq_cur = mqrq_cur;
- mq->mqrq_prev = mqrq_prev;
+ mq->qdepth = 2;
+ mq->mqrq = kcalloc(mq->qdepth, sizeof(struct mmc_queue_req),
+ GFP_KERNEL);
+ if (!mq->mqrq)
+ goto blk_cleanup;
+ mq->mqrq_cur = &mq->mqrq[0];
+ mq->mqrq_prev = &mq->mqrq[1];
mq->queue->queuedata = mq;
blk_queue_prep_rq(mq->queue, mmc_prep_request);
@@ -228,63 +315,29 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (bouncesz > (host->max_blk_count * 512))
bouncesz = host->max_blk_count * 512;
- if (bouncesz > 512) {
- mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
- if (!mqrq_cur->bounce_buf) {
- pr_warn("%s: unable to allocate bounce cur buffer\n",
- mmc_card_name(card));
- } else {
- mqrq_prev->bounce_buf =
- kmalloc(bouncesz, GFP_KERNEL);
- if (!mqrq_prev->bounce_buf) {
- pr_warn("%s: unable to allocate bounce prev buffer\n",
- mmc_card_name(card));
- kfree(mqrq_cur->bounce_buf);
- mqrq_cur->bounce_buf = NULL;
- }
- }
- }
-
- if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
+ if (bouncesz > 512 &&
+ mmc_queue_alloc_bounce_bufs(mq, bouncesz)) {
blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
blk_queue_max_segments(mq->queue, bouncesz / 512);
blk_queue_max_segment_size(mq->queue, bouncesz);
- mqrq_cur->sg = mmc_alloc_sg(1, &ret);
- if (ret)
- goto cleanup_queue;
-
- mqrq_cur->bounce_sg =
- mmc_alloc_sg(bouncesz / 512, &ret);
- if (ret)
- goto cleanup_queue;
-
- mqrq_prev->sg = mmc_alloc_sg(1, &ret);
- if (ret)
- goto cleanup_queue;
-
- mqrq_prev->bounce_sg =
- mmc_alloc_sg(bouncesz / 512, &ret);
+ ret = mmc_queue_alloc_bounce_sgs(mq, bouncesz);
if (ret)
goto cleanup_queue;
+ bounce = true;
}
}
#endif
- if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
+ if (!bounce) {
blk_queue_bounce_limit(mq->queue, limit);
blk_queue_max_hw_sectors(mq->queue,
min(host->max_blk_count, host->max_req_size / 512));
blk_queue_max_segments(mq->queue, host->max_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
- mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
- if (ret)
- goto cleanup_queue;
-
-
- mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
+ ret = mmc_queue_alloc_sgs(mq, host->max_segs);
if (ret)
goto cleanup_queue;
}
@@ -296,27 +349,16 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (IS_ERR(mq->thread)) {
ret = PTR_ERR(mq->thread);
- goto free_bounce_sg;
+ goto cleanup_queue;
}
return 0;
- free_bounce_sg:
- kfree(mqrq_cur->bounce_sg);
- mqrq_cur->bounce_sg = NULL;
- kfree(mqrq_prev->bounce_sg);
- mqrq_prev->bounce_sg = NULL;
cleanup_queue:
- kfree(mqrq_cur->sg);
- mqrq_cur->sg = NULL;
- kfree(mqrq_cur->bounce_buf);
- mqrq_cur->bounce_buf = NULL;
-
- kfree(mqrq_prev->sg);
- mqrq_prev->sg = NULL;
- kfree(mqrq_prev->bounce_buf);
- mqrq_prev->bounce_buf = NULL;
-
+ mmc_queue_reqs_free_bufs(mq);
+ kfree(mq->mqrq);
+ mq->mqrq = NULL;
+blk_cleanup:
blk_cleanup_queue(mq->queue);
return ret;
}
@@ -325,8 +367,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
{
struct request_queue *q = mq->queue;
unsigned long flags;
- struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
- struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
/* Make sure the queue isn't suspended, as that will deadlock */
mmc_queue_resume(mq);
@@ -340,71 +380,14 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
blk_start_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
- kfree(mqrq_cur->bounce_sg);
- mqrq_cur->bounce_sg = NULL;
-
- kfree(mqrq_cur->sg);
- mqrq_cur->sg = NULL;
-
- kfree(mqrq_cur->bounce_buf);
- mqrq_cur->bounce_buf = NULL;
-
- kfree(mqrq_prev->bounce_sg);
- mqrq_prev->bounce_sg = NULL;
-
- kfree(mqrq_prev->sg);
- mqrq_prev->sg = NULL;
-
- kfree(mqrq_prev->bounce_buf);
- mqrq_prev->bounce_buf = NULL;
+ mmc_queue_reqs_free_bufs(mq);
+ kfree(mq->mqrq);
+ mq->mqrq = NULL;
mq->card = NULL;
}
EXPORT_SYMBOL(mmc_cleanup_queue);
-int mmc_packed_init(struct mmc_queue *mq, struct mmc_card *card)
-{
- struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
- struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
- int ret = 0;
-
-
- mqrq_cur->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
- if (!mqrq_cur->packed) {
- pr_warn("%s: unable to allocate packed cmd for mqrq_cur\n",
- mmc_card_name(card));
- ret = -ENOMEM;
- goto out;
- }
-
- mqrq_prev->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
- if (!mqrq_prev->packed) {
- pr_warn("%s: unable to allocate packed cmd for mqrq_prev\n",
- mmc_card_name(card));
- kfree(mqrq_cur->packed);
- mqrq_cur->packed = NULL;
- ret = -ENOMEM;
- goto out;
- }
-
- INIT_LIST_HEAD(&mqrq_cur->packed->list);
- INIT_LIST_HEAD(&mqrq_prev->packed->list);
-
-out:
- return ret;
-}
-
-void mmc_packed_clean(struct mmc_queue *mq)
-{
- struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
- struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
-
- kfree(mqrq_cur->packed);
- mqrq_cur->packed = NULL;
- kfree(mqrq_prev->packed);
- mqrq_prev->packed = NULL;
-}
-
/**
* mmc_queue_suspend - suspend a MMC request queue
* @mq: MMC queue to suspend
@@ -449,41 +432,6 @@ void mmc_queue_resume(struct mmc_queue *mq)
}
}
-static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq,
- struct mmc_packed *packed,
- struct scatterlist *sg,
- enum mmc_packed_type cmd_type)
-{
- struct scatterlist *__sg = sg;
- unsigned int sg_len = 0;
- struct request *req;
-
- if (mmc_packed_wr(cmd_type)) {
- unsigned int hdr_sz = mmc_large_sector(mq->card) ? 4096 : 512;
- unsigned int max_seg_sz = queue_max_segment_size(mq->queue);
- unsigned int len, remain, offset = 0;
- u8 *buf = (u8 *)packed->cmd_hdr;
-
- remain = hdr_sz;
- do {
- len = min(remain, max_seg_sz);
- sg_set_buf(__sg, buf + offset, len);
- offset += len;
- remain -= len;
- sg_unmark_end(__sg++);
- sg_len++;
- } while (remain);
- }
-
- list_for_each_entry(req, &packed->list, queuelist) {
- sg_len += blk_rq_map_sg(mq->queue, req, __sg);
- __sg = sg + (sg_len - 1);
- sg_unmark_end(__sg++);
- }
- sg_mark_end(sg + (sg_len - 1));
- return sg_len;
-}
-
/*
* Prepare the sg list(s) to be handed of to the host driver
*/
@@ -492,26 +440,12 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
unsigned int sg_len;
size_t buflen;
struct scatterlist *sg;
- enum mmc_packed_type cmd_type;
int i;
- cmd_type = mqrq->cmd_type;
-
- if (!mqrq->bounce_buf) {
- if (mmc_packed_cmd(cmd_type))
- return mmc_queue_packed_map_sg(mq, mqrq->packed,
- mqrq->sg, cmd_type);
- else
- return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
- }
-
- BUG_ON(!mqrq->bounce_sg);
+ if (!mqrq->bounce_buf)
+ return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
- if (mmc_packed_cmd(cmd_type))
- sg_len = mmc_queue_packed_map_sg(mq, mqrq->packed,
- mqrq->bounce_sg, cmd_type);
- else
- sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
+ sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
mqrq->bounce_sg_len = sg_len;
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 342f1e3f301e..dac8c3d010dd 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -11,6 +11,7 @@ static inline bool mmc_req_is_special(struct request *req)
struct request;
struct task_struct;
+struct mmc_blk_data;
struct mmc_blk_request {
struct mmc_request mrq;
@@ -21,23 +22,6 @@ struct mmc_blk_request {
int retune_retry_done;
};
-enum mmc_packed_type {
- MMC_PACKED_NONE = 0,
- MMC_PACKED_WRITE,
-};
-
-#define mmc_packed_cmd(type) ((type) != MMC_PACKED_NONE)
-#define mmc_packed_wr(type) ((type) == MMC_PACKED_WRITE)
-
-struct mmc_packed {
- struct list_head list;
- __le32 cmd_hdr[1024];
- unsigned int blocks;
- u8 nr_entries;
- u8 retries;
- s16 idx_failure;
-};
-
struct mmc_queue_req {
struct request *req;
struct mmc_blk_request brq;
@@ -46,8 +30,6 @@ struct mmc_queue_req {
struct scatterlist *bounce_sg;
unsigned int bounce_sg_len;
struct mmc_async_req mmc_active;
- enum mmc_packed_type cmd_type;
- struct mmc_packed *packed;
};
struct mmc_queue {
@@ -57,11 +39,13 @@ struct mmc_queue {
unsigned int flags;
#define MMC_QUEUE_SUSPENDED (1 << 0)
#define MMC_QUEUE_NEW_REQUEST (1 << 1)
- void *data;
+ bool asleep;
+ struct mmc_blk_data *blkdata;
struct request_queue *queue;
- struct mmc_queue_req mqrq[2];
+ struct mmc_queue_req *mqrq;
struct mmc_queue_req *mqrq_cur;
struct mmc_queue_req *mqrq_prev;
+ int qdepth;
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
@@ -75,9 +59,6 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
extern void mmc_queue_bounce_post(struct mmc_queue_req *);
-extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *);
-extern void mmc_packed_clean(struct mmc_queue *);
-
extern int mmc_access_rpmb(struct mmc_queue *);
#endif
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 5af6fb9a9ce2..491c187744f5 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -135,8 +135,6 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
{
struct sdio_func *func;
- BUG_ON(sdio_uart_table[port->index] != port);
-
spin_lock(&sdio_uart_table_lock);
sdio_uart_table[port->index] = NULL;
spin_unlock(&sdio_uart_table_lock);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 2553d903a82b..543eadd230e5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -306,16 +306,16 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
mrq->sbc->mrq = mrq;
}
if (mrq->data) {
- BUG_ON(mrq->data->blksz > host->max_blk_size);
- BUG_ON(mrq->data->blocks > host->max_blk_count);
- BUG_ON(mrq->data->blocks * mrq->data->blksz >
- host->max_req_size);
-
+ if (mrq->data->blksz > host->max_blk_size ||
+ mrq->data->blocks > host->max_blk_count ||
+ mrq->data->blocks * mrq->data->blksz > host->max_req_size)
+ return -EINVAL;
#ifdef CONFIG_MMC_DEBUG
sz = 0;
for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
sz += sg->length;
- BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
+ if (sz != mrq->data->blocks * mrq->data->blksz)
+ return -EINVAL;
#endif
mrq->cmd->data = mrq->data;
@@ -349,8 +349,6 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
int timeout;
bool use_busy_signal;
- BUG_ON(!card);
-
if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
return;
@@ -380,7 +378,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
mmc_retune_hold(card->host);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BKOPS_START, 1, timeout,
+ EXT_CSD_BKOPS_START, 1, timeout, 0,
use_busy_signal, true, false);
if (err) {
pr_warn("%s: Error %d starting bkops\n",
@@ -497,32 +495,28 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
*
* Returns enum mmc_blk_status after checking errors.
*/
-static int mmc_wait_for_data_req_done(struct mmc_host *host,
+static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host,
struct mmc_request *mrq,
struct mmc_async_req *next_req)
{
struct mmc_command *cmd;
struct mmc_context_info *context_info = &host->context_info;
- int err;
- unsigned long flags;
+ enum mmc_blk_status status;
while (1) {
wait_event_interruptible(context_info->wait,
(context_info->is_done_rcv ||
context_info->is_new_req));
- spin_lock_irqsave(&context_info->lock, flags);
context_info->is_waiting_last_req = false;
- spin_unlock_irqrestore(&context_info->lock, flags);
if (context_info->is_done_rcv) {
context_info->is_done_rcv = false;
- context_info->is_new_req = false;
cmd = mrq->cmd;
if (!cmd->error || !cmd->retries ||
mmc_card_removed(host->card)) {
- err = host->areq->err_check(host->card,
- host->areq);
- break; /* return err */
+ status = host->areq->err_check(host->card,
+ host->areq);
+ break; /* return status */
} else {
mmc_retune_recheck(host);
pr_info("%s: req failed (CMD%u): %d, retrying...\n",
@@ -534,13 +528,12 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
continue; /* wait for done/new event again */
}
} else if (context_info->is_new_req) {
- context_info->is_new_req = false;
if (!next_req)
return MMC_BLK_NEW_REQUEST;
}
}
mmc_retune_release(host);
- return err;
+ return status;
}
void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
@@ -611,18 +604,15 @@ EXPORT_SYMBOL(mmc_is_req_done);
* mmc_pre_req - Prepare for a new request
* @host: MMC host to prepare command
* @mrq: MMC request to prepare for
- * @is_first_req: true if there is no previous started request
- * that may run in parellel to this call, otherwise false
*
* mmc_pre_req() is called in prior to mmc_start_req() to let
* host prepare for the new request. Preparation of a request may be
* performed while another request is running on the host.
*/
-static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
- bool is_first_req)
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq)
{
if (host->ops->pre_req)
- host->ops->pre_req(host, mrq, is_first_req);
+ host->ops->pre_req(host, mrq);
}
/**
@@ -658,21 +648,22 @@ static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
* is returned without waiting. NULL is not an error condition.
*/
struct mmc_async_req *mmc_start_req(struct mmc_host *host,
- struct mmc_async_req *areq, int *error)
+ struct mmc_async_req *areq,
+ enum mmc_blk_status *ret_stat)
{
- int err = 0;
+ enum mmc_blk_status status = MMC_BLK_SUCCESS;
int start_err = 0;
struct mmc_async_req *data = host->areq;
/* Prepare a new request */
if (areq)
- mmc_pre_req(host, areq->mrq, !host->areq);
+ mmc_pre_req(host, areq->mrq);
if (host->areq) {
- err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq);
- if (err == MMC_BLK_NEW_REQUEST) {
- if (error)
- *error = err;
+ status = mmc_wait_for_data_req_done(host, host->areq->mrq, areq);
+ if (status == MMC_BLK_NEW_REQUEST) {
+ if (ret_stat)
+ *ret_stat = status;
/*
* The previous request was not completed,
* nothing to return
@@ -695,27 +686,27 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
/* prepare the request again */
if (areq)
- mmc_pre_req(host, areq->mrq, !host->areq);
+ mmc_pre_req(host, areq->mrq);
}
}
- if (!err && areq)
+ if (status == MMC_BLK_SUCCESS && areq)
start_err = __mmc_start_data_req(host, areq->mrq);
if (host->areq)
mmc_post_req(host, host->areq->mrq, 0);
/* Cancel a prepared request if it was not started. */
- if ((err || start_err) && areq)
+ if ((status != MMC_BLK_SUCCESS || start_err) && areq)
mmc_post_req(host, areq->mrq, -EINVAL);
- if (err)
+ if (status != MMC_BLK_SUCCESS)
host->areq = NULL;
else
host->areq = areq;
- if (error)
- *error = err;
+ if (ret_stat)
+ *ret_stat = status;
return data;
}
EXPORT_SYMBOL(mmc_start_req);
@@ -754,8 +745,6 @@ int mmc_interrupt_hpi(struct mmc_card *card)
u32 status;
unsigned long prg_wait;
- BUG_ON(!card);
-
if (!card->ext_csd.hpi_en) {
pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
return 1;
@@ -850,7 +839,6 @@ int mmc_stop_bkops(struct mmc_card *card)
{
int err = 0;
- BUG_ON(!card);
err = mmc_interrupt_hpi(card);
/*
@@ -1666,8 +1654,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
int err = 0;
u32 clock;
- BUG_ON(!host);
-
/*
* Send CMD11 only if the request is to switch the card to
* 1.8V signalling.
@@ -1884,9 +1870,7 @@ void mmc_power_cycle(struct mmc_host *host, u32 ocr)
*/
static void __mmc_release_bus(struct mmc_host *host)
{
- BUG_ON(!host);
- BUG_ON(host->bus_refs);
- BUG_ON(!host->bus_dead);
+ WARN_ON(!host->bus_dead);
host->bus_ops = NULL;
}
@@ -1926,15 +1910,12 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
{
unsigned long flags;
- BUG_ON(!host);
- BUG_ON(!ops);
-
WARN_ON(!host->claimed);
spin_lock_irqsave(&host->lock, flags);
- BUG_ON(host->bus_ops);
- BUG_ON(host->bus_refs);
+ WARN_ON(host->bus_ops);
+ WARN_ON(host->bus_refs);
host->bus_ops = ops;
host->bus_refs = 1;
@@ -1950,8 +1931,6 @@ void mmc_detach_bus(struct mmc_host *host)
{
unsigned long flags;
- BUG_ON(!host);
-
WARN_ON(!host->claimed);
WARN_ON(!host->bus_ops);
@@ -2824,12 +2803,11 @@ void mmc_start_host(struct mmc_host *host)
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
+ if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) {
+ mmc_claim_host(host);
mmc_power_up(host, host->ocr_avail);
- mmc_release_host(host);
+ mmc_release_host(host);
+ }
mmc_gpiod_request_cd_irq(host);
_mmc_detect_change(host, 0, false);
@@ -2865,8 +2843,6 @@ void mmc_stop_host(struct mmc_host *host)
}
mmc_bus_put(host);
- BUG_ON(host->card);
-
mmc_claim_host(host);
mmc_power_off(host);
mmc_release_host(host);
@@ -3019,7 +2995,6 @@ void mmc_unregister_pm_notifier(struct mmc_host *host)
*/
void mmc_init_context_info(struct mmc_host *host)
{
- spin_lock_init(&host->context_info.lock);
host->context_info.is_new_req = false;
host->context_info.is_done_rcv = false;
host->context_info.is_waiting_last_req = false;
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index c8451ce557ae..30623b8b86a4 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -321,7 +321,11 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
for (i = 0; i < 512; i++)
n += sprintf(buf + n, "%02x", ext_csd[i]);
n += sprintf(buf + n, "\n");
- BUG_ON(n != EXT_CSD_STR_LEN);
+
+ if (n != EXT_CSD_STR_LEN) {
+ err = -EINVAL;
+ goto out_free;
+ }
filp->private_data = buf;
kfree(ext_csd);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index df19777068a6..b61b52f9da3d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -618,6 +618,24 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
(ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
!(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
}
+
+ /* eMMC v5.1 or later */
+ if (card->ext_csd.rev >= 8) {
+ card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT] &
+ EXT_CSD_CMDQ_SUPPORTED;
+ card->ext_csd.cmdq_depth = (ext_csd[EXT_CSD_CMDQ_DEPTH] &
+ EXT_CSD_CMDQ_DEPTH_MASK) + 1;
+ /* Exclude inefficiently small queue depths */
+ if (card->ext_csd.cmdq_depth <= 2) {
+ card->ext_csd.cmdq_support = false;
+ card->ext_csd.cmdq_depth = 0;
+ }
+ if (card->ext_csd.cmdq_support) {
+ pr_debug("%s: Command Queue supported depth %u\n",
+ mmc_hostname(card->host),
+ card->ext_csd.cmdq_depth);
+ }
+ }
out:
return err;
}
@@ -1003,19 +1021,6 @@ static int mmc_select_bus_width(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);
-}
-
/*
* Switch to the high-speed mode
*/
@@ -1025,13 +1030,8 @@ static int mmc_select_hs(struct mmc_card *card)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
- card->ext_csd.generic_cmd6_time,
- true, false, true);
- if (!err) {
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- err = mmc_switch_status(card);
- }
-
+ card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS,
+ true, true, true);
if (err)
pr_warn("%s: switch to high-speed failed, err:%d\n",
mmc_hostname(card->host), err);
@@ -1058,10 +1058,12 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits,
- card->ext_csd.generic_cmd6_time);
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ ext_csd_bits,
+ card->ext_csd.generic_cmd6_time,
+ MMC_TIMING_MMC_DDR52,
+ true, true, true);
if (err) {
pr_err("%s: switch to bus width %d ddr failed\n",
mmc_hostname(host), 1 << bus_width);
@@ -1104,9 +1106,6 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
if (err)
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330);
- if (!err)
- mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
-
return err;
}
@@ -1128,7 +1127,7 @@ static int mmc_select_hs400(struct mmc_card *card)
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
- card->ext_csd.generic_cmd6_time,
+ card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err) {
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
@@ -1163,7 +1162,7 @@ static int mmc_select_hs400(struct mmc_card *card)
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,
+ card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err) {
pr_err("%s: switch to hs400 failed, err:%d\n",
@@ -1206,7 +1205,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
/* Switch HS400 to HS DDR */
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
- val, card->ext_csd.generic_cmd6_time,
+ val, card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err)
goto out_err;
@@ -1220,7 +1219,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
/* Switch HS DDR to HS */
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
- true, false, true);
+ 0, true, false, true);
if (err)
goto out_err;
@@ -1234,14 +1233,19 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
val = EXT_CSD_TIMING_HS200 |
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,
+ val, card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err)
goto out_err;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
- err = mmc_switch_status(card);
+ /*
+ * For HS200, CRC errors are not a reliable way to know the switch
+ * failed. If there really is a problem, we would expect tuning will
+ * fail and the result ends up the same.
+ */
+ err = __mmc_switch_status(card, false);
if (err)
goto out_err;
@@ -1281,16 +1285,23 @@ static int mmc_select_hs400es(struct mmc_card *card)
goto out_err;
/* Switch card to HS mode */
- err = mmc_select_hs(card);
- if (err)
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+ card->ext_csd.generic_cmd6_time, 0,
+ true, false, true);
+ if (err) {
+ pr_err("%s: switch to hs for hs400es failed, err:%d\n",
+ mmc_hostname(host), err);
goto out_err;
+ }
- mmc_set_clock(host, card->ext_csd.hs_max_dtr);
-
+ mmc_set_timing(host, MMC_TIMING_MMC_HS);
err = mmc_switch_status(card);
if (err)
goto out_err;
+ mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+
/* Switch card to DDR with strobe bit */
val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1308,7 +1319,7 @@ static int mmc_select_hs400es(struct mmc_card *card)
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,
+ card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err) {
pr_err("%s: switch to hs400es failed, err:%d\n",
@@ -1390,14 +1401,20 @@ static int mmc_select_hs200(struct mmc_card *card)
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,
+ card->ext_csd.generic_cmd6_time, 0,
true, false, true);
if (err)
goto err;
old_timing = host->ios.timing;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
- err = mmc_switch_status(card);
+ /*
+ * For HS200, CRC errors are not a reliable way to know the
+ * switch failed. If there really is a problem, we would expect
+ * tuning will fail and the result ends up the same.
+ */
+ err = __mmc_switch_status(card, false);
+
/*
* mmc_select_timing() assumes timing has not changed if
* it is a switch error.
@@ -1480,7 +1497,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
u32 cid[4];
u32 rocr;
- BUG_ON(!host);
WARN_ON(!host->claimed);
/* Set correct bus mode for MMC before attempting init */
@@ -1854,7 +1870,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_OFF_NOTIFICATION,
- notify_type, timeout, true, false, false);
+ notify_type, timeout, 0, true, false, false);
if (err)
pr_err("%s: Power Off Notification timed out, %u\n",
mmc_hostname(card->host), timeout);
@@ -1870,9 +1886,6 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
*/
static void mmc_remove(struct mmc_host *host)
{
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_remove_card(host->card);
host->card = NULL;
}
@@ -1892,9 +1905,6 @@ static void mmc_detect(struct mmc_host *host)
{
int err;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_get_card(host->card);
/*
@@ -1920,9 +1930,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT :
EXT_CSD_POWER_OFF_LONG;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_claim_host(host);
if (mmc_card_suspended(host->card))
@@ -1979,9 +1986,6 @@ static int _mmc_resume(struct mmc_host *host)
{
int err = 0;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_claim_host(host);
if (!mmc_card_suspended(host->card))
@@ -2114,7 +2118,6 @@ int mmc_attach_mmc(struct mmc_host *host)
int err;
u32 ocr, rocr;
- BUG_ON(!host);
WARN_ON(!host->claimed);
/* Set correct bus mode for MMC before attempting attach */
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index ad6e9798e949..b11c3455b040 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -54,21 +54,15 @@ static const u8 tuning_blk_pattern_8bit[] = {
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};
-static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
- bool ignore_crc)
+int mmc_send_status(struct mmc_card *card, u32 *status)
{
int err;
struct mmc_command cmd = {0};
- BUG_ON(!card);
- BUG_ON(!card->host);
-
cmd.opcode = MMC_SEND_STATUS;
if (!mmc_host_is_spi(card->host))
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
- if (ignore_crc)
- cmd.flags &= ~MMC_RSP_CRC;
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
if (err)
@@ -83,17 +77,10 @@ static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
return 0;
}
-int mmc_send_status(struct mmc_card *card, u32 *status)
-{
- return __mmc_send_status(card, status, false);
-}
-
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
struct mmc_command cmd = {0};
- BUG_ON(!host);
-
cmd.opcode = MMC_SELECT_CARD;
if (card) {
@@ -109,7 +96,6 @@ static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
int mmc_select_card(struct mmc_card *card)
{
- BUG_ON(!card);
return _mmc_select_card(card->host, card);
}
@@ -181,8 +167,6 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
struct mmc_command cmd = {0};
int i, err = 0;
- BUG_ON(!host);
-
cmd.opcode = MMC_SEND_OP_COND;
cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
@@ -221,9 +205,6 @@ int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
int err;
struct mmc_command cmd = {0};
- BUG_ON(!host);
- BUG_ON(!cid);
-
cmd.opcode = MMC_ALL_SEND_CID;
cmd.arg = 0;
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
@@ -241,9 +222,6 @@ int mmc_set_relative_addr(struct mmc_card *card)
{
struct mmc_command cmd = {0};
- BUG_ON(!card);
- BUG_ON(!card->host);
-
cmd.opcode = MMC_SET_RELATIVE_ADDR;
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
@@ -257,9 +235,6 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
int err;
struct mmc_command cmd = {0};
- BUG_ON(!host);
- BUG_ON(!cxd);
-
cmd.opcode = opcode;
cmd.arg = arg;
cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
@@ -440,7 +415,7 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
return err;
}
-int mmc_switch_status_error(struct mmc_host *host, u32 status)
+static int mmc_switch_status_error(struct mmc_host *host, u32 status)
{
if (mmc_host_is_spi(host)) {
if (status & R1_SPI_ILLEGAL_COMMAND)
@@ -455,6 +430,88 @@ int mmc_switch_status_error(struct mmc_host *host, u32 status)
return 0;
}
+/* Caller must hold re-tuning */
+int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal)
+{
+ u32 status;
+ int err;
+
+ err = mmc_send_status(card, &status);
+ if (!crc_err_fatal && err == -EILSEQ)
+ return 0;
+ if (err)
+ return err;
+
+ return mmc_switch_status_error(card->host, status);
+}
+
+int mmc_switch_status(struct mmc_card *card)
+{
+ return __mmc_switch_status(card, true);
+}
+
+static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+ bool send_status, bool retry_crc_err)
+{
+ struct mmc_host *host = card->host;
+ int err;
+ unsigned long timeout;
+ u32 status = 0;
+ bool expired = false;
+ bool busy = false;
+
+ /* We have an unspecified cmd timeout, use the fallback value. */
+ if (!timeout_ms)
+ timeout_ms = MMC_OPS_TIMEOUT_MS;
+
+ /*
+ * In cases when not allowed to poll by using CMD13 or because we aren't
+ * capable of polling by using ->card_busy(), then rely on waiting the
+ * stated timeout to be sufficient.
+ */
+ if (!send_status && !host->ops->card_busy) {
+ mmc_delay(timeout_ms);
+ return 0;
+ }
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
+ do {
+ /*
+ * Due to the possibility of being preempted while polling,
+ * check the expiration time first.
+ */
+ expired = time_after(jiffies, timeout);
+
+ if (host->ops->card_busy) {
+ busy = host->ops->card_busy(host);
+ } else {
+ err = mmc_send_status(card, &status);
+ if (retry_crc_err && err == -EILSEQ) {
+ busy = true;
+ } else if (err) {
+ return err;
+ } else {
+ err = mmc_switch_status_error(host, status);
+ if (err)
+ return err;
+ busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
+ }
+ }
+
+ /* Timeout if the device still remains busy. */
+ if (expired && busy) {
+ pr_err("%s: Card stuck being busy! %s\n",
+ mmc_hostname(host), __func__);
+ return -ETIMEDOUT;
+ }
+ } while (busy);
+
+ if (host->ops->card_busy && send_status)
+ return mmc_switch_status(card);
+
+ return 0;
+}
+
/**
* __mmc_switch - modify EXT_CSD register
* @card: the MMC card associated with the data transfer
@@ -463,24 +520,22 @@ int mmc_switch_status_error(struct mmc_host *host, u32 status)
* @value: value to program into EXT_CSD register
* @timeout_ms: timeout (ms) for operation performed by register write,
* timeout of zero implies maximum possible timeout
+ * @timing: new timing to change to
* @use_busy_signal: use the busy signal as response type
* @send_status: send status cmd to poll for busy
- * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy
+ * @retry_crc_err: retry when CRC errors when polling with CMD13 for busy
*
* Modifies the EXT_CSD register for selected card.
*/
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)
+ unsigned int timeout_ms, unsigned char timing,
+ bool use_busy_signal, bool send_status, bool retry_crc_err)
{
struct mmc_host *host = card->host;
int err;
struct mmc_command cmd = {0};
- unsigned long timeout;
- u32 status = 0;
bool use_r1b_resp = use_busy_signal;
- bool expired = false;
- bool busy = false;
+ unsigned char old_timing = host->ios.timing;
mmc_retune_hold(host);
@@ -522,62 +577,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (!use_busy_signal)
goto out;
- /*
- * CRC errors shall only be ignored in cases were CMD13 is used to poll
- * to detect busy completion.
- */
- if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
- ignore_crc = false;
-
- /* We have an unspecified cmd timeout, use the fallback value. */
- if (!timeout_ms)
- timeout_ms = MMC_OPS_TIMEOUT_MS;
-
- /* Must check status to be sure of no errors. */
- timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
- do {
- /*
- * Due to the possibility of being preempted after
- * sending the status command, check the expiration
- * time first.
- */
- expired = time_after(jiffies, timeout);
- if (send_status) {
- err = __mmc_send_status(card, &status, ignore_crc);
- if (err)
- goto out;
- }
- if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
- break;
- if (host->ops->card_busy) {
- if (!host->ops->card_busy(host))
- break;
- busy = true;
- }
- if (mmc_host_is_spi(host))
- break;
+ /* Switch to new timing before poll and check switch status. */
+ if (timing)
+ mmc_set_timing(host, timing);
- /*
- * We are not allowed to issue a status command and the host
- * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
- * rely on waiting for the stated timeout to be sufficient.
- */
- if (!send_status && !host->ops->card_busy) {
- mmc_delay(timeout_ms);
- goto out;
- }
+ /*If SPI or used HW busy detection above, then we don't need to poll. */
+ if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ||
+ mmc_host_is_spi(host)) {
+ if (send_status)
+ err = mmc_switch_status(card);
+ goto out_tim;
+ }
- /* Timeout if the device never leaves the program state. */
- if (expired &&
- (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
- pr_err("%s: Card stuck in programming state! %s\n",
- mmc_hostname(host), __func__);
- err = -ETIMEDOUT;
- goto out;
- }
- } while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
+ /* Let's try to poll to find out when the command is completed. */
+ err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err);
- err = mmc_switch_status_error(host, status);
+out_tim:
+ if (err && timing)
+ mmc_set_timing(host, old_timing);
out:
mmc_retune_release(host);
@@ -587,8 +604,8 @@ out:
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms)
{
- return __mmc_switch(card, set, index, value, timeout_ms, true, true,
- false);
+ return __mmc_switch(card, set, index, value, timeout_ms, 0,
+ true, true, false);
}
EXPORT_SYMBOL_GPL(mmc_switch);
@@ -661,6 +678,31 @@ out:
}
EXPORT_SYMBOL_GPL(mmc_send_tuning);
+int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
+{
+ struct mmc_command cmd = {0};
+
+ /*
+ * eMMC specification specifies that CMD12 can be used to stop a tuning
+ * command, but SD specification does not, so do nothing unless it is
+ * eMMC.
+ */
+ if (opcode != MMC_SEND_TUNING_BLOCK_HS200)
+ return 0;
+
+ cmd.opcode = MMC_STOP_TRANSMISSION;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+
+ /*
+ * For drivers that override R1 to R1b, set an arbitrary timeout based
+ * on the tuning timeout i.e. 150ms.
+ */
+ cmd.busy_timeout = 150;
+
+ return mmc_wait_for_cmd(host, &cmd, 0);
+}
+EXPORT_SYMBOL_GPL(mmc_abort_tuning);
+
static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
u8 len)
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index f1b8e81aaa28..abd525ed74be 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -27,10 +27,11 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
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_status(struct mmc_card *card);
+int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
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);
+ unsigned int timeout_ms, unsigned char timing,
+ bool use_busy_signal, bool send_status, bool retry_crc_err);
#endif
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 73c762a28dfe..deb90c2ff6b4 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -927,7 +927,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
u32 cid[4];
u32 rocr = 0;
- BUG_ON(!host);
WARN_ON(!host->claimed);
err = mmc_sd_get_cid(host, ocr, cid, &rocr);
@@ -1043,9 +1042,6 @@ free_card:
*/
static void mmc_sd_remove(struct mmc_host *host)
{
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_remove_card(host->card);
host->card = NULL;
}
@@ -1065,9 +1061,6 @@ static void mmc_sd_detect(struct mmc_host *host)
{
int err;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_get_card(host->card);
/*
@@ -1091,9 +1084,6 @@ static int _mmc_sd_suspend(struct mmc_host *host)
{
int err = 0;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_claim_host(host);
if (mmc_card_suspended(host->card))
@@ -1136,9 +1126,6 @@ static int _mmc_sd_resume(struct mmc_host *host)
{
int err = 0;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_claim_host(host);
if (!mmc_card_suspended(host->card))
@@ -1221,7 +1208,6 @@ int mmc_attach_sd(struct mmc_host *host)
int err;
u32 ocr, rocr;
- BUG_ON(!host);
WARN_ON(!host->claimed);
err = mmc_send_app_op_cond(host, 0, &ocr);
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 16b774c18e75..de125a41aa7a 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -27,8 +27,8 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
int err;
struct mmc_command cmd = {0};
- BUG_ON(!host);
- BUG_ON(card && (card->host != host));
+ if (WARN_ON(card && card->host != host))
+ return -EINVAL;
cmd.opcode = MMC_APP_CMD;
@@ -72,8 +72,8 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
int i, err;
- BUG_ON(!cmd);
- BUG_ON(retries < 0);
+ if (retries < 0)
+ retries = MMC_CMD_RETRIES;
err = -EIO;
@@ -122,9 +122,6 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width)
{
struct mmc_command cmd = {0};
- BUG_ON(!card);
- BUG_ON(!card->host);
-
cmd.opcode = SD_APP_SET_BUS_WIDTH;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
@@ -147,8 +144,6 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
struct mmc_command cmd = {0};
int i, err = 0;
- BUG_ON(!host);
-
cmd.opcode = SD_APP_OP_COND;
if (mmc_host_is_spi(host))
cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
@@ -224,9 +219,6 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
int err;
struct mmc_command cmd = {0};
- BUG_ON(!host);
- BUG_ON(!rca);
-
cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0;
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
@@ -249,10 +241,6 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
struct scatterlist sg;
void *data_buf;
- BUG_ON(!card);
- BUG_ON(!card->host);
- BUG_ON(!scr);
-
/* NOTE: caller guarantees scr is heap-allocated */
err = mmc_app_cmd(card->host, card);
@@ -307,9 +295,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
struct mmc_data data = {0};
struct scatterlist sg;
- BUG_ON(!card);
- BUG_ON(!card->host);
-
/* NOTE: caller guarantees resp is heap-allocated */
mode = !!mode;
@@ -352,10 +337,6 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr)
struct mmc_data data = {0};
struct scatterlist sg;
- BUG_ON(!card);
- BUG_ON(!card->host);
- BUG_ON(!ssr);
-
/* NOTE: caller guarantees ssr is heap-allocated */
err = mmc_app_cmd(card->host, card);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index bd44ba8116d1..ecbc52981ba5 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -63,7 +63,8 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
int ret;
struct sdio_func *func;
- BUG_ON(fn > SDIO_MAX_FUNCS);
+ if (WARN_ON(fn > SDIO_MAX_FUNCS))
+ return -EINVAL;
func = sdio_alloc_func(card);
if (IS_ERR(func))
@@ -555,7 +556,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
u32 rocr = 0;
u32 ocr_card = ocr;
- BUG_ON(!host);
WARN_ON(!host->claimed);
/* to query card if 1.8V signalling is supported */
@@ -791,9 +791,6 @@ static void mmc_sdio_remove(struct mmc_host *host)
{
int i;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
for (i = 0;i < host->card->sdio_funcs;i++) {
if (host->card->sdio_func[i]) {
sdio_remove_func(host->card->sdio_func[i]);
@@ -820,9 +817,6 @@ static void mmc_sdio_detect(struct mmc_host *host)
{
int err;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
/* Make sure card is powered before detecting it */
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
err = pm_runtime_get_sync(&host->card->dev);
@@ -916,9 +910,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
{
int err = 0;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
/* Basic card reinitialization. */
mmc_claim_host(host);
@@ -970,9 +961,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
{
int ret;
- BUG_ON(!host);
- BUG_ON(!host->card);
-
mmc_claim_host(host);
/*
@@ -1063,7 +1051,6 @@ int mmc_attach_sdio(struct mmc_host *host)
u32 ocr, rocr;
struct mmc_card *card;
- BUG_ON(!host);
WARN_ON(!host->claimed);
err = mmc_send_io_op_cond(host, 0, &ocr);
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index dcb3dee59fa5..f8c372839d24 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -262,7 +262,8 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
else
prev = &card->tuples;
- BUG_ON(*prev);
+ if (*prev)
+ return -EINVAL;
do {
unsigned char tpl_code, tpl_link;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 91bbbfb29f3f..f1faf9acc007 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -214,7 +214,9 @@ static int sdio_card_irq_put(struct mmc_card *card)
struct mmc_host *host = card->host;
WARN_ON(!host->claimed);
- BUG_ON(host->sdio_irqs < 1);
+
+ if (host->sdio_irqs < 1)
+ return -EINVAL;
if (!--host->sdio_irqs) {
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
@@ -261,8 +263,8 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
int ret;
unsigned char reg;
- BUG_ON(!func);
- BUG_ON(!func->card);
+ if (!func)
+ return -EINVAL;
pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));
@@ -304,8 +306,8 @@ int sdio_release_irq(struct sdio_func *func)
int ret;
unsigned char reg;
- BUG_ON(!func);
- BUG_ON(!func->card);
+ if (!func)
+ return -EINVAL;
pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 27117ba47073..babe591aea96 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -258,6 +258,14 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
}
EXPORT_SYMBOL(mmc_gpiod_request_cd);
+bool mmc_can_gpio_cd(struct mmc_host *host)
+{
+ struct mmc_gpio *ctx = host->slot.handler_priv;
+
+ return ctx->cd_gpio ? true : false;
+}
+EXPORT_SYMBOL(mmc_can_gpio_cd);
+
/**
* mmc_gpiod_request_ro - request a gpio descriptor for write protection
* @host: mmc host
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5274f503a39a..2eb97014dc3f 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -135,7 +135,6 @@ config MMC_SDHCI_OF_AT91
tristate "SDHCI OF support for the Atmel SDMMC controller"
depends on MMC_SDHCI_PLTFM
depends on OF
- select MMC_SDHCI_IO_ACCESSORS
help
This selects the Atmel SDMMC driver
@@ -144,6 +143,7 @@ config MMC_SDHCI_OF_ESDHC
depends on MMC_SDHCI_PLTFM
depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
select MMC_SDHCI_IO_ACCESSORS
+ select FSL_GUTS
help
This selects the Freescale eSDHC controller support.
@@ -165,6 +165,17 @@ config MMC_SDHCI_OF_HLWD
If unsure, say N.
+config MMC_SDHCI_CADENCE
+ tristate "SDHCI support for the Cadence SD/SDIO/eMMC controller"
+ depends on MMC_SDHCI_PLTFM
+ depends on OF
+ help
+ This selects the Cadence SD/SDIO/eMMC driver.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_CNS3XXX
tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
depends on ARCH_CNS3XXX
@@ -322,6 +333,16 @@ config MMC_SDHCI_IPROC
If unsure, say N.
+config MMC_MESON_GX
+ tristate "Amlogic S905/GX* SD/MMC Host Controller support"
+ depends on ARCH_MESON && MMC
+ help
+ This selects support for the Amlogic SD/MMC Host Controller
+ found on the S905/GX* family of SoCs. This controller is
+ MMC 5.1 compliant and supports SD, eMMC and SDIO interfaces.
+
+ If you have a controller with this interface, say Y here.
+
config MMC_MOXART
tristate "MOXART SD/MMC Host Controller support"
depends on ARCH_MOXART && MMC
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e2bdaaf43184..ccc9c4cba154 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
obj-$(CONFIG_MMC_VUB300) += vub300.o
obj-$(CONFIG_MMC_USHC) += ushc.o
obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
+obj-$(CONFIG_MMC_MESON_GX) += meson-gx-mmc.o
obj-$(CONFIG_MMC_MOXART) += moxart-mmc.o
obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o
obj-$(CONFIG_MMC_USDHI6ROL0) += usdhi6rol0.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 8fa478c3b0db..36b5af8eadb8 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -35,6 +35,7 @@
#include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/mmc/slot-gpio.h>
#include <linux/platform_data/mmc-davinci.h>
@@ -1029,9 +1030,10 @@ static int mmc_davinci_get_cd(struct mmc_host *mmc)
struct platform_device *pdev = to_platform_device(mmc->parent);
struct davinci_mmc_config *config = pdev->dev.platform_data;
- if (!config || !config->get_cd)
- return -ENOSYS;
- return config->get_cd(pdev->id);
+ if (config && config->get_cd)
+ return config->get_cd(pdev->id);
+
+ return mmc_gpio_get_cd(mmc);
}
static int mmc_davinci_get_ro(struct mmc_host *mmc)
@@ -1039,9 +1041,10 @@ static int mmc_davinci_get_ro(struct mmc_host *mmc)
struct platform_device *pdev = to_platform_device(mmc->parent);
struct davinci_mmc_config *config = pdev->dev.platform_data;
- if (!config || !config->get_ro)
- return -ENOSYS;
- return config->get_ro(pdev->id);
+ if (config && config->get_ro)
+ return config->get_ro(pdev->id);
+
+ return mmc_gpio_get_ro(mmc);
}
static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1159,49 +1162,53 @@ static const struct of_device_id davinci_mmc_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, davinci_mmc_dt_ids);
-static struct davinci_mmc_config
- *mmc_parse_pdata(struct platform_device *pdev)
+static int mmc_davinci_parse_pdata(struct mmc_host *mmc)
{
- struct device_node *np;
+ struct platform_device *pdev = to_platform_device(mmc->parent);
struct davinci_mmc_config *pdata = pdev->dev.platform_data;
- const struct of_device_id *match =
- of_match_device(davinci_mmc_dt_ids, &pdev->dev);
- u32 data;
-
- np = pdev->dev.of_node;
- if (!np)
- return pdata;
-
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(&pdev->dev, "Failed to allocate memory for struct davinci_mmc_config\n");
- goto nodata;
- }
+ struct mmc_davinci_host *host;
+ int ret;
- if (match)
- pdev->id_entry = match->data;
+ if (!pdata)
+ return -EINVAL;
- if (of_property_read_u32(np, "max-frequency", &pdata->max_freq))
- dev_info(&pdev->dev, "'max-frequency' property not specified, defaulting to 25MHz\n");
+ host = mmc_priv(mmc);
+ if (!host)
+ return -EINVAL;
- of_property_read_u32(np, "bus-width", &data);
- switch (data) {
- case 1:
- case 4:
- case 8:
- pdata->wires = data;
- break;
- default:
- pdata->wires = 1;
- dev_info(&pdev->dev, "Unsupported buswidth, defaulting to 1 bit\n");
- }
-nodata:
- return pdata;
+ if (pdata && pdata->nr_sg)
+ host->nr_sg = pdata->nr_sg - 1;
+
+ if (pdata && (pdata->wires == 4 || pdata->wires == 0))
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ if (pdata && (pdata->wires == 8))
+ mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+
+ mmc->f_min = 312500;
+ mmc->f_max = 25000000;
+ if (pdata && pdata->max_freq)
+ mmc->f_max = pdata->max_freq;
+ if (pdata && pdata->caps)
+ mmc->caps |= pdata->caps;
+
+ /* Register a cd gpio, if there is not one, enable polling */
+ ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ else if (ret)
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+ ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ return 0;
}
static int __init davinci_mmcsd_probe(struct platform_device *pdev)
{
- struct davinci_mmc_config *pdata = NULL;
+ const struct of_device_id *match;
struct mmc_davinci_host *host = NULL;
struct mmc_host *mmc = NULL;
struct resource *r, *mem = NULL;
@@ -1209,12 +1216,6 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
size_t mem_size;
const struct platform_device_id *id_entry;
- pdata = mmc_parse_pdata(pdev);
- if (pdata == NULL) {
- dev_err(&pdev->dev, "Couldn't get platform data\n");
- return -ENOENT;
- }
-
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r)
return -ENODEV;
@@ -1253,14 +1254,28 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
host->mmc_input_clk = clk_get_rate(host->clk);
- init_mmcsd_host(host);
-
- if (pdata->nr_sg)
- host->nr_sg = pdata->nr_sg - 1;
+ match = of_match_device(davinci_mmc_dt_ids, &pdev->dev);
+ if (match) {
+ pdev->id_entry = match->data;
+ ret = mmc_of_parse(mmc);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "could not parse of data: %d\n", ret);
+ goto parse_fail;
+ }
+ } else {
+ ret = mmc_davinci_parse_pdata(mmc);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "could not parse platform data: %d\n", ret);
+ goto parse_fail;
+ } }
if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
host->nr_sg = MAX_NR_SG;
+ init_mmcsd_host(host);
+
host->use_dma = use_dma;
host->mmc_irq = irq;
host->sdio_irq = platform_get_irq(pdev, 1);
@@ -1273,27 +1288,13 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
host->use_dma = 0;
}
- /* REVISIT: someday, support IRQ-driven card detection. */
- mmc->caps |= MMC_CAP_NEEDS_POLL;
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
- if (pdata && (pdata->wires == 4 || pdata->wires == 0))
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-
- if (pdata && (pdata->wires == 8))
- mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
-
id_entry = platform_get_device_id(pdev);
if (id_entry)
host->version = id_entry->driver_data;
mmc->ops = &mmc_davinci_ops;
- mmc->f_min = 312500;
- mmc->f_max = 25000000;
- if (pdata && pdata->max_freq)
- mmc->f_max = pdata->max_freq;
- if (pdata && pdata->caps)
- mmc->caps |= pdata->caps;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
/* With no iommu coalescing pages, each phys_seg is a hw_seg.
@@ -1354,6 +1355,7 @@ mmc_add_host_fail:
mmc_davinci_cpufreq_deregister(host);
cpu_freq_fail:
davinci_release_dma_channels(host);
+parse_fail:
dma_probe_defer:
clk_disable_unprepare(host->clk);
clk_prepare_enable_fail:
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 7ab3d749b5ae..e1335289316c 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -17,6 +17,7 @@
#include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "dw_mmc.h"
@@ -161,20 +162,13 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags);
}
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_exynos_suspend(struct device *dev)
-{
- struct dw_mci *host = dev_get_drvdata(dev);
-
- return dw_mci_suspend(host);
-}
-
-static int dw_mci_exynos_resume(struct device *dev)
+#ifdef CONFIG_PM
+static int dw_mci_exynos_runtime_resume(struct device *dev)
{
struct dw_mci *host = dev_get_drvdata(dev);
dw_mci_exynos_config_smu(host);
- return dw_mci_resume(host);
+ return dw_mci_runtime_resume(dev);
}
/**
@@ -211,10 +205,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
return 0;
}
#else
-#define dw_mci_exynos_suspend NULL
-#define dw_mci_exynos_resume NULL
#define dw_mci_exynos_resume_noirq NULL
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
{
@@ -524,14 +516,42 @@ static int dw_mci_exynos_probe(struct platform_device *pdev)
{
const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match;
+ int ret;
match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
drv_data = match->data;
- return dw_mci_pltfm_register(pdev, drv_data);
+
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ ret = dw_mci_pltfm_register(pdev, drv_data);
+ if (ret) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dw_mci_exynos_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return dw_mci_pltfm_remove(pdev);
}
static const struct dev_pm_ops dw_mci_exynos_pmops = {
- SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+ dw_mci_exynos_runtime_resume,
+ NULL)
.resume_noirq = dw_mci_exynos_resume_noirq,
.thaw_noirq = dw_mci_exynos_resume_noirq,
.restore_noirq = dw_mci_exynos_resume_noirq,
@@ -539,7 +559,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = {
static struct platform_driver dw_mci_exynos_pltfm_driver = {
.probe = dw_mci_exynos_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove = dw_mci_exynos_remove,
.driver = {
.name = "dwmmc_exynos",
.of_match_table = dw_mci_exynos_match,
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index 624789496dce..9821e6bd5d5e 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -162,35 +163,13 @@ static int dw_mci_k3_probe(struct platform_device *pdev)
return dw_mci_pltfm_register(pdev, drv_data);
}
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_k3_suspend(struct device *dev)
-{
- struct dw_mci *host = dev_get_drvdata(dev);
- int ret;
-
- ret = dw_mci_suspend(host);
- if (!ret)
- clk_disable_unprepare(host->ciu_clk);
-
- return ret;
-}
-
-static int dw_mci_k3_resume(struct device *dev)
-{
- struct dw_mci *host = dev_get_drvdata(dev);
- int ret;
-
- ret = clk_prepare_enable(host->ciu_clk);
- if (ret) {
- dev_err(host->dev, "failed to enable ciu clock\n");
- return ret;
- }
-
- return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+ dw_mci_runtime_resume,
+ NULL)
+};
static struct platform_driver dw_mci_k3_pltfm_driver = {
.probe = dw_mci_k3_probe,
@@ -198,7 +177,7 @@ static struct platform_driver dw_mci_k3_pltfm_driver = {
.driver = {
.name = "dwmmc_k3",
.of_match_table = dw_mci_k3_match,
- .pm = &dw_mci_k3_pmops,
+ .pm = &dw_mci_k3_dev_pm_ops,
},
};
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
index 4c69fbd29811..ab82796b01e2 100644
--- a/drivers/mmc/host/dw_mmc-pci.c
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/pci.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
@@ -79,25 +80,13 @@ static void dw_mci_pci_remove(struct pci_dev *pdev)
dw_mci_remove(host);
}
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_pci_suspend(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_mci *host = pci_get_drvdata(pdev);
-
- return dw_mci_suspend(host);
-}
-
-static int dw_mci_pci_resume(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct dw_mci *host = pci_get_drvdata(pdev);
-
- return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
+static const struct dev_pm_ops dw_mci_pci_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+ dw_mci_runtime_resume,
+ NULL)
+};
static const struct pci_device_id dw_mci_pci_id[] = {
{ PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
@@ -111,7 +100,7 @@ static struct pci_driver dw_mci_pci_driver = {
.probe = dw_mci_pci_probe,
.remove = dw_mci_pci_remove,
.driver = {
- .pm = &dw_mci_pci_pmops
+ .pm = &dw_mci_pci_dev_pm_ops,
},
};
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index dbbc4303bdd0..1236d49ba36e 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
@@ -58,26 +59,13 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
-#ifdef CONFIG_PM_SLEEP
-/*
- * TODO: we should probably disable the clock to the card in the suspend path.
- */
-static int dw_mci_pltfm_suspend(struct device *dev)
-{
- struct dw_mci *host = dev_get_drvdata(dev);
-
- return dw_mci_suspend(host);
-}
-
-static int dw_mci_pltfm_resume(struct device *dev)
-{
- struct dw_mci *host = dev_get_drvdata(dev);
-
- return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
+const struct dev_pm_ops dw_mci_pltfm_pmops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+ dw_mci_runtime_resume,
+ NULL)
+};
EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
static const struct of_device_id dw_mci_pltfm_match[] = {
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 25eae359a5ea..9a46e4694227 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -13,6 +13,8 @@
#include <linux/mmc/host.h>
#include <linux/mmc/dw_mmc.h>
#include <linux/of_address.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "dw_mmc.h"
@@ -325,6 +327,7 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
{
const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match;
+ int ret;
if (!pdev->dev.of_node)
return -ENODEV;
@@ -332,16 +335,49 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node);
drv_data = match->data;
- return dw_mci_pltfm_register(pdev, drv_data);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
+ ret = dw_mci_pltfm_register(pdev, drv_data);
+ if (ret) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
+
+ pm_runtime_put_autosuspend(&pdev->dev);
+
+ return 0;
}
+static int dw_mci_rockchip_remove(struct platform_device *pdev)
+{
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return dw_mci_pltfm_remove(pdev);
+}
+
+static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+ dw_mci_runtime_resume,
+ NULL)
+};
+
static struct platform_driver dw_mci_rockchip_pltfm_driver = {
.probe = dw_mci_rockchip_probe,
- .remove = dw_mci_pltfm_remove,
+ .remove = dw_mci_rockchip_remove,
.driver = {
.name = "dwmmc_rockchip",
.of_match_table = dw_mci_rockchip_match,
- .pm = &dw_mci_pltfm_pmops,
+ .pm = &dw_mci_rockchip_dev_pm_ops,
},
};
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index df478ae72e23..b44306b886cb 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -54,7 +54,7 @@
#define DW_MCI_DMA_THRESHOLD 16
#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */
-#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */
+#define DW_MCI_FREQ_MIN 100000 /* unit: HZ */
#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
@@ -165,12 +165,14 @@ static const struct file_operations dw_mci_req_fops = {
static int dw_mci_regs_show(struct seq_file *s, void *v)
{
- seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
- seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
- seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
- seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
- seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
- seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
+ struct dw_mci *host = s->private;
+
+ seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
+ seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
+ seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
+ seq_printf(s, "CTRL:\t0x%08x\n", mci_readl(host, CTRL));
+ seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
+ seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
return 0;
}
@@ -234,7 +236,6 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg);
static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{
- struct mmc_data *data;
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
u32 cmdr;
@@ -289,10 +290,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
if (cmd->flags & MMC_RSP_CRC)
cmdr |= SDMMC_CMD_RESP_CRC;
- data = cmd->data;
- if (data) {
+ if (cmd->data) {
cmdr |= SDMMC_CMD_DAT_EXP;
- if (data->flags & MMC_DATA_WRITE)
+ if (cmd->data->flags & MMC_DATA_WRITE)
cmdr |= SDMMC_CMD_DAT_WR;
}
@@ -335,6 +335,9 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
cmdr = stop->opcode | SDMMC_CMD_STOP |
SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
+ if (!test_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags))
+ cmdr |= SDMMC_CMD_USE_HOLD_REG;
+
return cmdr;
}
@@ -380,7 +383,7 @@ static void dw_mci_start_command(struct dw_mci *host,
static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
{
- struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
+ struct mmc_command *stop = &host->stop_abort;
dw_mci_start_command(host, stop, host->stop_cmdr);
}
@@ -409,12 +412,13 @@ static void dw_mci_dma_cleanup(struct dw_mci *host)
{
struct mmc_data *data = host->data;
- if (data)
- if (!data->host_cookie)
- dma_unmap_sg(host->dev,
- data->sg,
- data->sg_len,
- dw_mci_get_dma_dir(data));
+ if (data && data->host_cookie == COOKIE_MAPPED) {
+ dma_unmap_sg(host->dev,
+ data->sg,
+ data->sg_len,
+ dw_mci_get_dma_dir(data));
+ data->host_cookie = COOKIE_UNMAPPED;
+ }
}
static void dw_mci_idmac_reset(struct dw_mci *host)
@@ -612,7 +616,7 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host,
return 0;
err_own_bit:
/* restore the descriptor chain as it's polluted */
- dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+ dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
dw_mci_idmac_init(host);
return -EINVAL;
@@ -688,7 +692,7 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host,
return 0;
err_own_bit:
/* restore the descriptor chain as it's polluted */
- dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+ dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
dw_mci_idmac_init(host);
return -EINVAL;
@@ -845,13 +849,13 @@ static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
static int dw_mci_pre_dma_transfer(struct dw_mci *host,
struct mmc_data *data,
- bool next)
+ int cookie)
{
struct scatterlist *sg;
unsigned int i, sg_len;
- if (!next && data->host_cookie)
- return data->host_cookie;
+ if (data->host_cookie == COOKIE_PRE_MAPPED)
+ return data->sg_len;
/*
* We don't do DMA on "complex" transfers, i.e. with
@@ -876,15 +880,13 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
if (sg_len == 0)
return -EINVAL;
- if (next)
- data->host_cookie = sg_len;
+ data->host_cookie = cookie;
return sg_len;
}
static void dw_mci_pre_req(struct mmc_host *mmc,
- struct mmc_request *mrq,
- bool is_first_req)
+ struct mmc_request *mrq)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
@@ -892,13 +894,12 @@ static void dw_mci_pre_req(struct mmc_host *mmc,
if (!slot->host->use_dma || !data)
return;
- if (data->host_cookie) {
- data->host_cookie = 0;
- return;
- }
+ /* This data might be unmapped at this time */
+ data->host_cookie = COOKIE_UNMAPPED;
- if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0)
- data->host_cookie = 0;
+ if (dw_mci_pre_dma_transfer(slot->host, mrq->data,
+ COOKIE_PRE_MAPPED) < 0)
+ data->host_cookie = COOKIE_UNMAPPED;
}
static void dw_mci_post_req(struct mmc_host *mmc,
@@ -911,12 +912,12 @@ static void dw_mci_post_req(struct mmc_host *mmc,
if (!slot->host->use_dma || !data)
return;
- if (data->host_cookie)
+ if (data->host_cookie != COOKIE_UNMAPPED)
dma_unmap_sg(slot->host->dev,
data->sg,
data->sg_len,
dw_mci_get_dma_dir(data));
- data->host_cookie = 0;
+ data->host_cookie = COOKIE_UNMAPPED;
}
static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
@@ -1022,7 +1023,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
if (!host->use_dma)
return -ENODEV;
- sg_len = dw_mci_pre_dma_transfer(host, data, 0);
+ sg_len = dw_mci_pre_dma_transfer(host, data, COOKIE_MAPPED);
if (sg_len < 0) {
host->dma_ops->stop(host);
return sg_len;
@@ -1175,13 +1176,24 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0;
- if (clock != slot->__clk_old || force_clkinit)
+ if ((clock != slot->__clk_old &&
+ !test_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags)) ||
+ force_clkinit) {
dev_info(&slot->mmc->class_dev,
"Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n",
slot->id, host->bus_hz, clock,
div ? ((host->bus_hz / div) >> 1) :
host->bus_hz, div);
+ /*
+ * If card is polling, display the message only
+ * one time at boot time.
+ */
+ if (slot->mmc->caps & MMC_CAP_NEEDS_POLL &&
+ slot->mmc->f_min == clock)
+ set_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags);
+ }
+
/* disable clock */
mci_writel(host, CLKENA, 0);
mci_writel(host, CLKSRC, 0);
@@ -1273,10 +1285,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
spin_unlock_irqrestore(&host->irq_lock, irqflags);
}
- if (mrq->stop)
- host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
- else
- host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
+ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
}
static void dw_mci_start_request(struct dw_mci *host,
@@ -1527,22 +1536,34 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
int gpio_cd = mmc_gpio_get_cd(mmc);
/* Use platform get_cd function, else try onboard card detect */
- if ((mmc->caps & MMC_CAP_NEEDS_POLL) || !mmc_card_is_removable(mmc))
+ if (((mmc->caps & MMC_CAP_NEEDS_POLL)
+ || !mmc_card_is_removable(mmc))) {
present = 1;
- else if (gpio_cd >= 0)
+
+ if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
+ if (mmc->caps & MMC_CAP_NEEDS_POLL) {
+ dev_info(&mmc->class_dev,
+ "card is polling.\n");
+ } else {
+ dev_info(&mmc->class_dev,
+ "card is non-removable.\n");
+ }
+ set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+ }
+
+ return present;
+ } else if (gpio_cd >= 0)
present = gpio_cd;
else
present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
== 0 ? 1 : 0;
spin_lock_bh(&host->lock);
- if (present) {
- set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+ if (present && !test_and_set_bit(DW_MMC_CARD_PRESENT, &slot->flags))
dev_dbg(&mmc->class_dev, "card is present\n");
- } else {
- clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+ else if (!present &&
+ !test_and_clear_bit(DW_MMC_CARD_PRESENT, &slot->flags))
dev_dbg(&mmc->class_dev, "card is not present\n");
- }
spin_unlock_bh(&host->lock);
return present;
@@ -1889,8 +1910,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
dw_mci_stop_dma(host);
- if (data->stop ||
- !(host->data_status & (SDMMC_INT_DRTO |
+ if (!(host->data_status & (SDMMC_INT_DRTO |
SDMMC_INT_EBE)))
send_stop_abort(host, data);
state = STATE_DATA_ERROR;
@@ -1926,8 +1946,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
dw_mci_stop_dma(host);
- if (data->stop ||
- !(host->data_status & (SDMMC_INT_DRTO |
+ if (!(host->data_status & (SDMMC_INT_DRTO |
SDMMC_INT_EBE)))
send_stop_abort(host, data);
state = STATE_DATA_ERROR;
@@ -2003,7 +2022,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
host->cmd = NULL;
host->data = NULL;
- if (mrq->stop)
+ if (!mrq->sbc && mrq->stop)
dw_mci_command_complete(host, mrq->stop);
else
host->cmd_status = 0;
@@ -2615,6 +2634,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
mmc->f_min = DW_MCI_FREQ_MIN;
mmc->f_max = DW_MCI_FREQ_MAX;
} else {
+ dev_info(host->dev,
+ "'clock-freq-min-max' property was deprecated.\n");
mmc->f_min = freq[0];
mmc->f_max = freq[1];
}
@@ -3267,26 +3288,46 @@ EXPORT_SYMBOL(dw_mci_remove);
-#ifdef CONFIG_PM_SLEEP
-/*
- * TODO: we should probably disable the clock to the card in the suspend path.
- */
-int dw_mci_suspend(struct dw_mci *host)
+#ifdef CONFIG_PM
+int dw_mci_runtime_suspend(struct device *dev)
{
+ struct dw_mci *host = dev_get_drvdata(dev);
+
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
+ clk_disable_unprepare(host->ciu_clk);
+
+ if (host->cur_slot &&
+ (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+ !mmc_card_is_removable(host->cur_slot->mmc)))
+ clk_disable_unprepare(host->biu_clk);
+
return 0;
}
-EXPORT_SYMBOL(dw_mci_suspend);
+EXPORT_SYMBOL(dw_mci_runtime_suspend);
-int dw_mci_resume(struct dw_mci *host)
+int dw_mci_runtime_resume(struct device *dev)
{
- int i, ret;
+ int i, ret = 0;
+ struct dw_mci *host = dev_get_drvdata(dev);
+
+ if (host->cur_slot &&
+ (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+ !mmc_card_is_removable(host->cur_slot->mmc))) {
+ ret = clk_prepare_enable(host->biu_clk);
+ if (ret)
+ return ret;
+ }
+
+ ret = clk_prepare_enable(host->ciu_clk);
+ if (ret)
+ goto err;
if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
+ clk_disable_unprepare(host->ciu_clk);
ret = -ENODEV;
- return ret;
+ goto err;
}
if (host->use_dma && host->dma_ops->init)
@@ -3296,8 +3337,8 @@ int dw_mci_resume(struct dw_mci *host)
* Restore the initial value at FIFOTH register
* And Invalidate the prev_blksz with zero
*/
- mci_writel(host, FIFOTH, host->fifoth_val);
- host->prev_blksz = 0;
+ mci_writel(host, FIFOTH, host->fifoth_val);
+ host->prev_blksz = 0;
/* Put in max timeout */
mci_writel(host, TMOUT, 0xFFFFFFFF);
@@ -3323,9 +3364,17 @@ int dw_mci_resume(struct dw_mci *host)
dw_mci_enable_cd(host);
return 0;
+
+err:
+ if (host->cur_slot &&
+ (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+ !mmc_card_is_removable(host->cur_slot->mmc)))
+ clk_disable_unprepare(host->biu_clk);
+
+ return ret;
}
-EXPORT_SYMBOL(dw_mci_resume);
-#endif /* CONFIG_PM_SLEEP */
+EXPORT_SYMBOL(dw_mci_runtime_resume);
+#endif /* CONFIG_PM */
static int __init dw_mci_init(void)
{
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index e8cd2dec3263..c59465829387 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -234,9 +234,9 @@
extern int dw_mci_probe(struct dw_mci *host);
extern void dw_mci_remove(struct dw_mci *host);
-#ifdef CONFIG_PM_SLEEP
-extern int dw_mci_suspend(struct dw_mci *host);
-extern int dw_mci_resume(struct dw_mci *host);
+#ifdef CONFIG_PM
+extern int dw_mci_runtime_suspend(struct device *device);
+extern int dw_mci_runtime_resume(struct device *device);
#endif
/**
@@ -272,6 +272,7 @@ struct dw_mci_slot {
#define DW_MMC_CARD_NEED_INIT 1
#define DW_MMC_CARD_NO_LOW_PWR 2
#define DW_MMC_CARD_NO_USE_HOLD 3
+#define DW_MMC_CARD_NEEDS_POLL 4
int id;
int sdio_id;
};
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 684087db170b..819ad32964fc 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -320,8 +320,7 @@ dma_unmap:
}
static void jz4740_mmc_pre_request(struct mmc_host *mmc,
- struct mmc_request *mrq,
- bool is_first_req)
+ struct mmc_request *mrq)
{
struct jz4740_mmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
new file mode 100644
index 000000000000..b352760c041e
--- /dev/null
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -0,0 +1,851 @@
+/*
+ * Amlogic SD/eMMC driver for the GX/S905 family SoCs
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman@baylibre.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.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regulator/consumer.h>
+
+#define DRIVER_NAME "meson-gx-mmc"
+
+#define SD_EMMC_CLOCK 0x0
+#define CLK_DIV_SHIFT 0
+#define CLK_DIV_WIDTH 6
+#define CLK_DIV_MASK 0x3f
+#define CLK_DIV_MAX 63
+#define CLK_SRC_SHIFT 6
+#define CLK_SRC_WIDTH 2
+#define CLK_SRC_MASK 0x3
+#define CLK_SRC_XTAL 0 /* external crystal */
+#define CLK_SRC_XTAL_RATE 24000000
+#define CLK_SRC_PLL 1 /* FCLK_DIV2 */
+#define CLK_SRC_PLL_RATE 1000000000
+#define CLK_PHASE_SHIFT 8
+#define CLK_PHASE_MASK 0x3
+#define CLK_PHASE_0 0
+#define CLK_PHASE_90 1
+#define CLK_PHASE_180 2
+#define CLK_PHASE_270 3
+#define CLK_ALWAYS_ON BIT(24)
+
+#define SD_EMMC_DElAY 0x4
+#define SD_EMMC_ADJUST 0x8
+#define SD_EMMC_CALOUT 0x10
+#define SD_EMMC_START 0x40
+#define START_DESC_INIT BIT(0)
+#define START_DESC_BUSY BIT(1)
+#define START_DESC_ADDR_SHIFT 2
+#define START_DESC_ADDR_MASK (~0x3)
+
+#define SD_EMMC_CFG 0x44
+#define CFG_BUS_WIDTH_SHIFT 0
+#define CFG_BUS_WIDTH_MASK 0x3
+#define CFG_BUS_WIDTH_1 0x0
+#define CFG_BUS_WIDTH_4 0x1
+#define CFG_BUS_WIDTH_8 0x2
+#define CFG_DDR BIT(2)
+#define CFG_BLK_LEN_SHIFT 4
+#define CFG_BLK_LEN_MASK 0xf
+#define CFG_RESP_TIMEOUT_SHIFT 8
+#define CFG_RESP_TIMEOUT_MASK 0xf
+#define CFG_RC_CC_SHIFT 12
+#define CFG_RC_CC_MASK 0xf
+#define CFG_STOP_CLOCK BIT(22)
+#define CFG_CLK_ALWAYS_ON BIT(18)
+#define CFG_AUTO_CLK BIT(23)
+
+#define SD_EMMC_STATUS 0x48
+#define STATUS_BUSY BIT(31)
+
+#define SD_EMMC_IRQ_EN 0x4c
+#define IRQ_EN_MASK 0x3fff
+#define IRQ_RXD_ERR_SHIFT 0
+#define IRQ_RXD_ERR_MASK 0xff
+#define IRQ_TXD_ERR BIT(8)
+#define IRQ_DESC_ERR BIT(9)
+#define IRQ_RESP_ERR BIT(10)
+#define IRQ_RESP_TIMEOUT BIT(11)
+#define IRQ_DESC_TIMEOUT BIT(12)
+#define IRQ_END_OF_CHAIN BIT(13)
+#define IRQ_RESP_STATUS BIT(14)
+#define IRQ_SDIO BIT(15)
+
+#define SD_EMMC_CMD_CFG 0x50
+#define SD_EMMC_CMD_ARG 0x54
+#define SD_EMMC_CMD_DAT 0x58
+#define SD_EMMC_CMD_RSP 0x5c
+#define SD_EMMC_CMD_RSP1 0x60
+#define SD_EMMC_CMD_RSP2 0x64
+#define SD_EMMC_CMD_RSP3 0x68
+
+#define SD_EMMC_RXD 0x94
+#define SD_EMMC_TXD 0x94
+#define SD_EMMC_LAST_REG SD_EMMC_TXD
+
+#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
+#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
+#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
+#define MUX_CLK_NUM_PARENTS 2
+
+struct meson_host {
+ struct device *dev;
+ struct mmc_host *mmc;
+ struct mmc_request *mrq;
+ struct mmc_command *cmd;
+
+ spinlock_t lock;
+ void __iomem *regs;
+ int irq;
+ u32 ocr_mask;
+ struct clk *core_clk;
+ struct clk_mux mux;
+ struct clk *mux_clk;
+ struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
+ unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
+
+ struct clk_divider cfg_div;
+ struct clk *cfg_div_clk;
+
+ unsigned int bounce_buf_size;
+ void *bounce_buf;
+ dma_addr_t bounce_dma_addr;
+
+ bool vqmmc_enabled;
+};
+
+struct sd_emmc_desc {
+ u32 cmd_cfg;
+ u32 cmd_arg;
+ u32 cmd_data;
+ u32 cmd_resp;
+};
+#define CMD_CFG_LENGTH_SHIFT 0
+#define CMD_CFG_LENGTH_MASK 0x1ff
+#define CMD_CFG_BLOCK_MODE BIT(9)
+#define CMD_CFG_R1B BIT(10)
+#define CMD_CFG_END_OF_CHAIN BIT(11)
+#define CMD_CFG_TIMEOUT_SHIFT 12
+#define CMD_CFG_TIMEOUT_MASK 0xf
+#define CMD_CFG_NO_RESP BIT(16)
+#define CMD_CFG_NO_CMD BIT(17)
+#define CMD_CFG_DATA_IO BIT(18)
+#define CMD_CFG_DATA_WR BIT(19)
+#define CMD_CFG_RESP_NOCRC BIT(20)
+#define CMD_CFG_RESP_128 BIT(21)
+#define CMD_CFG_RESP_NUM BIT(22)
+#define CMD_CFG_DATA_NUM BIT(23)
+#define CMD_CFG_CMD_INDEX_SHIFT 24
+#define CMD_CFG_CMD_INDEX_MASK 0x3f
+#define CMD_CFG_ERROR BIT(30)
+#define CMD_CFG_OWNER BIT(31)
+
+#define CMD_DATA_MASK (~0x3)
+#define CMD_DATA_BIG_ENDIAN BIT(1)
+#define CMD_DATA_SRAM BIT(0)
+#define CMD_RESP_MASK (~0x1)
+#define CMD_RESP_SRAM BIT(0)
+
+static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
+{
+ struct mmc_host *mmc = host->mmc;
+ int ret = 0;
+ u32 cfg;
+
+ if (clk_rate) {
+ if (WARN_ON(clk_rate > mmc->f_max))
+ clk_rate = mmc->f_max;
+ else if (WARN_ON(clk_rate < mmc->f_min))
+ clk_rate = mmc->f_min;
+ }
+
+ if (clk_rate == mmc->actual_clock)
+ return 0;
+
+ /* stop clock */
+ cfg = readl(host->regs + SD_EMMC_CFG);
+ if (!(cfg & CFG_STOP_CLOCK)) {
+ cfg |= CFG_STOP_CLOCK;
+ writel(cfg, host->regs + SD_EMMC_CFG);
+ }
+
+ dev_dbg(host->dev, "change clock rate %u -> %lu\n",
+ mmc->actual_clock, clk_rate);
+
+ if (clk_rate == 0) {
+ mmc->actual_clock = 0;
+ return 0;
+ }
+
+ ret = clk_set_rate(host->cfg_div_clk, clk_rate);
+ if (ret)
+ dev_warn(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n",
+ clk_rate, ret);
+ else if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
+ dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
+ clk_rate, clk_get_rate(host->cfg_div_clk), ret);
+ else
+ mmc->actual_clock = clk_rate;
+
+ /* (re)start clock, if non-zero */
+ if (!ret && clk_rate) {
+ cfg = readl(host->regs + SD_EMMC_CFG);
+ cfg &= ~CFG_STOP_CLOCK;
+ writel(cfg, host->regs + SD_EMMC_CFG);
+ }
+
+ return ret;
+}
+
+/*
+ * The SD/eMMC IP block has an internal mux and divider used for
+ * generating the MMC clock. Use the clock framework to create and
+ * manage these clocks.
+ */
+static int meson_mmc_clk_init(struct meson_host *host)
+{
+ struct clk_init_data init;
+ char clk_name[32];
+ int i, ret = 0;
+ const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+ unsigned int mux_parent_count = 0;
+ const char *clk_div_parents[1];
+ unsigned int f_min = UINT_MAX;
+ u32 clk_reg, cfg;
+
+ /* get the mux parents */
+ for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+ char name[16];
+
+ snprintf(name, sizeof(name), "clkin%d", i);
+ host->mux_parent[i] = devm_clk_get(host->dev, name);
+ if (IS_ERR(host->mux_parent[i])) {
+ ret = PTR_ERR(host->mux_parent[i]);
+ if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
+ dev_err(host->dev, "Missing clock %s\n", name);
+ host->mux_parent[i] = NULL;
+ return ret;
+ }
+
+ host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
+ mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
+ mux_parent_count++;
+ if (host->mux_parent_rate[i] < f_min)
+ f_min = host->mux_parent_rate[i];
+ }
+
+ /* cacluate f_min based on input clocks, and max divider value */
+ if (f_min != UINT_MAX)
+ f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
+ else
+ f_min = 4000000; /* default min: 400 MHz */
+ host->mmc->f_min = f_min;
+
+ /* create the mux */
+ snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
+ init.name = clk_name;
+ init.ops = &clk_mux_ops;
+ init.flags = 0;
+ init.parent_names = mux_parent_names;
+ init.num_parents = mux_parent_count;
+
+ host->mux.reg = host->regs + SD_EMMC_CLOCK;
+ host->mux.shift = CLK_SRC_SHIFT;
+ host->mux.mask = CLK_SRC_MASK;
+ host->mux.flags = 0;
+ host->mux.table = NULL;
+ host->mux.hw.init = &init;
+
+ host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
+ if (WARN_ON(IS_ERR(host->mux_clk)))
+ return PTR_ERR(host->mux_clk);
+
+ /* create the divider */
+ snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
+ init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
+ init.ops = &clk_divider_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ clk_div_parents[0] = __clk_get_name(host->mux_clk);
+ init.parent_names = clk_div_parents;
+ init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+ host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
+ host->cfg_div.shift = CLK_DIV_SHIFT;
+ host->cfg_div.width = CLK_DIV_WIDTH;
+ host->cfg_div.hw.init = &init;
+ host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
+ CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
+
+ host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
+ if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
+ return PTR_ERR(host->cfg_div_clk);
+
+ /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+ clk_reg = 0;
+ clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
+ clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
+ clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
+ clk_reg &= ~CLK_ALWAYS_ON;
+ writel(clk_reg, host->regs + SD_EMMC_CLOCK);
+
+ /* Ensure clock starts in "auto" mode, not "always on" */
+ cfg = readl(host->regs + SD_EMMC_CFG);
+ cfg &= ~CFG_CLK_ALWAYS_ON;
+ cfg |= CFG_AUTO_CLK;
+ writel(cfg, host->regs + SD_EMMC_CFG);
+
+ ret = clk_prepare_enable(host->cfg_div_clk);
+ if (!ret)
+ ret = meson_mmc_clk_set(host, f_min);
+
+ if (!ret)
+ clk_disable_unprepare(host->cfg_div_clk);
+
+ return ret;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct meson_host *host = mmc_priv(mmc);
+ u32 bus_width;
+ u32 val, orig;
+
+ /*
+ * GPIO regulator, only controls switching between 1v8 and
+ * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
+ */
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ if (!IS_ERR(mmc->supply.vmmc))
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
+ if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
+ regulator_disable(mmc->supply.vqmmc);
+ host->vqmmc_enabled = false;
+ }
+
+ break;
+
+ case MMC_POWER_UP:
+ if (!IS_ERR(mmc->supply.vmmc))
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+ break;
+
+ case MMC_POWER_ON:
+ if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
+ int ret = regulator_enable(mmc->supply.vqmmc);
+
+ if (ret < 0)
+ dev_err(mmc_dev(mmc),
+ "failed to enable vqmmc regulator\n");
+ else
+ host->vqmmc_enabled = true;
+ }
+
+ break;
+ }
+
+
+ meson_mmc_clk_set(host, ios->clock);
+
+ /* Bus width */
+ val = readl(host->regs + SD_EMMC_CFG);
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_1:
+ bus_width = CFG_BUS_WIDTH_1;
+ break;
+ case MMC_BUS_WIDTH_4:
+ bus_width = CFG_BUS_WIDTH_4;
+ break;
+ case MMC_BUS_WIDTH_8:
+ bus_width = CFG_BUS_WIDTH_8;
+ break;
+ default:
+ dev_err(host->dev, "Invalid ios->bus_width: %u. Setting to 4.\n",
+ ios->bus_width);
+ bus_width = CFG_BUS_WIDTH_4;
+ return;
+ }
+
+ val = readl(host->regs + SD_EMMC_CFG);
+ orig = val;
+
+ val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
+ val |= bus_width << CFG_BUS_WIDTH_SHIFT;
+
+ val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+ val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
+
+ val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
+ val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
+
+ val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
+ val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
+
+ writel(val, host->regs + SD_EMMC_CFG);
+
+ if (val != orig)
+ dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
+ __func__, orig, val);
+}
+
+static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct meson_host *host = mmc_priv(mmc);
+
+ WARN_ON(host->mrq != mrq);
+
+ host->mrq = NULL;
+ host->cmd = NULL;
+ mmc_request_done(host->mmc, mrq);
+
+ return 0;
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+ struct meson_host *host = mmc_priv(mmc);
+ struct sd_emmc_desc *desc, desc_tmp;
+ u32 cfg;
+ u8 blk_len, cmd_cfg_timeout;
+ unsigned int xfer_bytes = 0;
+
+ /* Setup descriptors */
+ dma_rmb();
+ desc = &desc_tmp;
+ memset(desc, 0, sizeof(struct sd_emmc_desc));
+
+ desc->cmd_cfg |= (cmd->opcode & CMD_CFG_CMD_INDEX_MASK) <<
+ CMD_CFG_CMD_INDEX_SHIFT;
+ desc->cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */
+ desc->cmd_arg = cmd->arg;
+
+ /* Response */
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ desc->cmd_cfg &= ~CMD_CFG_NO_RESP;
+ if (cmd->flags & MMC_RSP_136)
+ desc->cmd_cfg |= CMD_CFG_RESP_128;
+ desc->cmd_cfg |= CMD_CFG_RESP_NUM;
+ desc->cmd_resp = 0;
+
+ if (!(cmd->flags & MMC_RSP_CRC))
+ desc->cmd_cfg |= CMD_CFG_RESP_NOCRC;
+
+ if (cmd->flags & MMC_RSP_BUSY)
+ desc->cmd_cfg |= CMD_CFG_R1B;
+ } else {
+ desc->cmd_cfg |= CMD_CFG_NO_RESP;
+ }
+
+ /* data? */
+ if (cmd->data) {
+ desc->cmd_cfg |= CMD_CFG_DATA_IO;
+ if (cmd->data->blocks > 1) {
+ desc->cmd_cfg |= CMD_CFG_BLOCK_MODE;
+ desc->cmd_cfg |=
+ (cmd->data->blocks & CMD_CFG_LENGTH_MASK) <<
+ CMD_CFG_LENGTH_SHIFT;
+
+ /* check if block-size matches, if not update */
+ cfg = readl(host->regs + SD_EMMC_CFG);
+ blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+ blk_len >>= CFG_BLK_LEN_SHIFT;
+ if (blk_len != ilog2(cmd->data->blksz)) {
+ dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
+ __func__, blk_len,
+ ilog2(cmd->data->blksz));
+ blk_len = ilog2(cmd->data->blksz);
+ cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+ cfg |= blk_len << CFG_BLK_LEN_SHIFT;
+ writel(cfg, host->regs + SD_EMMC_CFG);
+ }
+ } else {
+ desc->cmd_cfg &= ~CMD_CFG_BLOCK_MODE;
+ desc->cmd_cfg |=
+ (cmd->data->blksz & CMD_CFG_LENGTH_MASK) <<
+ CMD_CFG_LENGTH_SHIFT;
+ }
+
+ cmd->data->bytes_xfered = 0;
+ xfer_bytes = cmd->data->blksz * cmd->data->blocks;
+ if (cmd->data->flags & MMC_DATA_WRITE) {
+ desc->cmd_cfg |= CMD_CFG_DATA_WR;
+ WARN_ON(xfer_bytes > host->bounce_buf_size);
+ sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len,
+ host->bounce_buf, xfer_bytes);
+ cmd->data->bytes_xfered = xfer_bytes;
+ dma_wmb();
+ } else {
+ desc->cmd_cfg &= ~CMD_CFG_DATA_WR;
+ }
+
+ if (xfer_bytes > 0) {
+ desc->cmd_cfg &= ~CMD_CFG_DATA_NUM;
+ desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
+ } else {
+ /* write data to data_addr */
+ desc->cmd_cfg |= CMD_CFG_DATA_NUM;
+ desc->cmd_data = 0;
+ }
+
+ cmd_cfg_timeout = 12;
+ } else {
+ desc->cmd_cfg &= ~CMD_CFG_DATA_IO;
+ cmd_cfg_timeout = 10;
+ }
+ desc->cmd_cfg |= (cmd_cfg_timeout & CMD_CFG_TIMEOUT_MASK) <<
+ CMD_CFG_TIMEOUT_SHIFT;
+
+ host->cmd = cmd;
+
+ /* Last descriptor */
+ desc->cmd_cfg |= CMD_CFG_END_OF_CHAIN;
+ writel(desc->cmd_cfg, host->regs + SD_EMMC_CMD_CFG);
+ writel(desc->cmd_data, host->regs + SD_EMMC_CMD_DAT);
+ writel(desc->cmd_resp, host->regs + SD_EMMC_CMD_RSP);
+ wmb(); /* ensure descriptor is written before kicked */
+ writel(desc->cmd_arg, host->regs + SD_EMMC_CMD_ARG);
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct meson_host *host = mmc_priv(mmc);
+
+ WARN_ON(host->mrq != NULL);
+
+ /* Stop execution */
+ writel(0, host->regs + SD_EMMC_START);
+
+ /* clear, ack, enable all interrupts */
+ writel(0, host->regs + SD_EMMC_IRQ_EN);
+ writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
+ writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN);
+
+ host->mrq = mrq;
+
+ if (mrq->sbc)
+ meson_mmc_start_cmd(mmc, mrq->sbc);
+ else
+ meson_mmc_start_cmd(mmc, mrq->cmd);
+}
+
+static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+ struct meson_host *host = mmc_priv(mmc);
+
+ if (cmd->flags & MMC_RSP_136) {
+ cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP3);
+ cmd->resp[1] = readl(host->regs + SD_EMMC_CMD_RSP2);
+ cmd->resp[2] = readl(host->regs + SD_EMMC_CMD_RSP1);
+ cmd->resp[3] = readl(host->regs + SD_EMMC_CMD_RSP);
+ } else if (cmd->flags & MMC_RSP_PRESENT) {
+ cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP);
+ }
+
+ return 0;
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+{
+ struct meson_host *host = dev_id;
+ struct mmc_request *mrq;
+ struct mmc_command *cmd = host->cmd;
+ u32 irq_en, status, raw_status;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ if (WARN_ON(!host))
+ return IRQ_NONE;
+
+ mrq = host->mrq;
+
+ if (WARN_ON(!mrq))
+ return IRQ_NONE;
+
+ if (WARN_ON(!cmd))
+ return IRQ_NONE;
+
+ spin_lock(&host->lock);
+ irq_en = readl(host->regs + SD_EMMC_IRQ_EN);
+ raw_status = readl(host->regs + SD_EMMC_STATUS);
+ status = raw_status & irq_en;
+
+ if (!status) {
+ dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
+ raw_status, irq_en);
+ ret = IRQ_NONE;
+ goto out;
+ }
+
+ cmd->error = 0;
+ if (status & IRQ_RXD_ERR_MASK) {
+ dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
+ cmd->error = -EILSEQ;
+ }
+ if (status & IRQ_TXD_ERR) {
+ dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
+ cmd->error = -EILSEQ;
+ }
+ if (status & IRQ_DESC_ERR)
+ dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
+ if (status & IRQ_RESP_ERR) {
+ dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
+ cmd->error = -EILSEQ;
+ }
+ if (status & IRQ_RESP_TIMEOUT) {
+ dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
+ cmd->error = -ETIMEDOUT;
+ }
+ if (status & IRQ_DESC_TIMEOUT) {
+ dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
+ cmd->error = -ETIMEDOUT;
+ }
+ if (status & IRQ_SDIO)
+ dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
+
+ if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
+ ret = IRQ_WAKE_THREAD;
+ else {
+ dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
+ status, cmd->opcode, cmd->arg,
+ cmd->flags, mrq->stop ? 1 : 0);
+ if (cmd->data) {
+ struct mmc_data *data = cmd->data;
+
+ dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
+ data->blksz, data->blocks, data->flags,
+ data->flags & MMC_DATA_WRITE ? "write" : "",
+ data->flags & MMC_DATA_READ ? "read" : "");
+ }
+ }
+
+out:
+ /* ack all (enabled) interrupts */
+ writel(status, host->regs + SD_EMMC_STATUS);
+
+ if (ret == IRQ_HANDLED) {
+ meson_mmc_read_resp(host->mmc, cmd);
+ meson_mmc_request_done(host->mmc, cmd->mrq);
+ }
+
+ spin_unlock(&host->lock);
+ return ret;
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
+{
+ struct meson_host *host = dev_id;
+ struct mmc_request *mrq = host->mrq;
+ struct mmc_command *cmd = host->cmd;
+ struct mmc_data *data;
+ unsigned int xfer_bytes;
+ int ret = IRQ_HANDLED;
+
+ if (WARN_ON(!mrq))
+ ret = IRQ_NONE;
+
+ if (WARN_ON(!cmd))
+ ret = IRQ_NONE;
+
+ data = cmd->data;
+ if (data) {
+ xfer_bytes = data->blksz * data->blocks;
+ if (data->flags & MMC_DATA_READ) {
+ WARN_ON(xfer_bytes > host->bounce_buf_size);
+ sg_copy_from_buffer(data->sg, data->sg_len,
+ host->bounce_buf, xfer_bytes);
+ data->bytes_xfered = xfer_bytes;
+ }
+ }
+
+ meson_mmc_read_resp(host->mmc, cmd);
+ if (!data || !data->stop || mrq->sbc)
+ meson_mmc_request_done(host->mmc, mrq);
+ else
+ meson_mmc_start_cmd(host->mmc, data->stop);
+
+ return ret;
+}
+
+/*
+ * NOTE: we only need this until the GPIO/pinctrl driver can handle
+ * interrupts. For now, the MMC core will use this for polling.
+ */
+static int meson_mmc_get_cd(struct mmc_host *mmc)
+{
+ int status = mmc_gpio_get_cd(mmc);
+
+ if (status == -ENOSYS)
+ return 1; /* assume present */
+
+ return status;
+}
+
+static const struct mmc_host_ops meson_mmc_ops = {
+ .request = meson_mmc_request,
+ .set_ios = meson_mmc_set_ios,
+ .get_cd = meson_mmc_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct meson_host *host;
+ struct mmc_host *mmc;
+ int ret;
+
+ mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
+ if (!mmc)
+ return -ENOMEM;
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, host);
+
+ spin_lock_init(&host->lock);
+
+ /* Get regulators and the supported OCR mask */
+ host->vqmmc_enabled = false;
+ ret = mmc_regulator_get_supply(mmc);
+ if (ret == -EPROBE_DEFER)
+ goto free_host;
+
+ ret = mmc_of_parse(mmc);
+ if (ret) {
+ dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
+ goto free_host;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ host->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(host->regs)) {
+ ret = PTR_ERR(host->regs);
+ goto free_host;
+ }
+
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq == 0) {
+ dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+ ret = -EINVAL;
+ goto free_host;
+ }
+
+ host->core_clk = devm_clk_get(&pdev->dev, "core");
+ if (IS_ERR(host->core_clk)) {
+ ret = PTR_ERR(host->core_clk);
+ goto free_host;
+ }
+
+ ret = clk_prepare_enable(host->core_clk);
+ if (ret)
+ goto free_host;
+
+ ret = meson_mmc_clk_init(host);
+ if (ret)
+ goto free_host;
+
+ /* Stop execution */
+ writel(0, host->regs + SD_EMMC_START);
+
+ /* clear, ack, enable all interrupts */
+ writel(0, host->regs + SD_EMMC_IRQ_EN);
+ writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
+
+ ret = devm_request_threaded_irq(&pdev->dev, host->irq,
+ meson_mmc_irq, meson_mmc_irq_thread,
+ IRQF_SHARED, DRIVER_NAME, host);
+ if (ret)
+ goto free_host;
+
+ /* data bounce buffer */
+ host->bounce_buf_size = SZ_512K;
+ host->bounce_buf =
+ dma_alloc_coherent(host->dev, host->bounce_buf_size,
+ &host->bounce_dma_addr, GFP_KERNEL);
+ if (host->bounce_buf == NULL) {
+ dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
+ ret = -ENOMEM;
+ goto free_host;
+ }
+
+ mmc->ops = &meson_mmc_ops;
+ mmc_add_host(mmc);
+
+ return 0;
+
+free_host:
+ clk_disable_unprepare(host->cfg_div_clk);
+ clk_disable_unprepare(host->core_clk);
+ mmc_free_host(mmc);
+ return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+ struct meson_host *host = dev_get_drvdata(&pdev->dev);
+
+ if (WARN_ON(!host))
+ return 0;
+
+ if (host->bounce_buf)
+ dma_free_coherent(host->dev, host->bounce_buf_size,
+ host->bounce_buf, host->bounce_dma_addr);
+
+ clk_disable_unprepare(host->cfg_div_clk);
+ clk_disable_unprepare(host->core_clk);
+
+ mmc_free_host(host->mmc);
+ return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+ { .compatible = "amlogic,meson-gx-mmc", },
+ { .compatible = "amlogic,meson-gxbb-mmc", },
+ { .compatible = "amlogic,meson-gxl-mmc", },
+ { .compatible = "amlogic,meson-gxm-mmc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {
+ .probe = meson_mmc_probe,
+ .remove = meson_mmc_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = of_match_ptr(meson_mmc_of_match),
+ },
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_DESCRIPTION("Amlogic S905*/GX* SD/eMMC driver");
+MODULE_AUTHOR("Kevin Hilman <khilman@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index df990bb8c873..01a804792f30 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -71,7 +71,12 @@ static unsigned int fmax = 515633;
* @f_max: maximum clk frequency supported by the controller.
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
- * @busy_detect: true if busy detection on dat0 is supported
+ * @busy_detect: true if the variant supports busy detection on DAT0.
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
+ * indicating that the card is busy
+ * @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
+ * getting busy end detection interrupts
* @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
* @explicit_mclk_control: enable explicit mclk control in driver.
* @qcom_fifo: enables qcom specific fifo pio read logic.
@@ -98,6 +103,9 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ u32 busy_dpsm_flag;
+ u32 busy_detect_flag;
+ u32 busy_detect_mask;
bool pwrreg_nopower;
bool explicit_mclk_control;
bool qcom_fifo;
@@ -137,7 +145,7 @@ static struct variant_data variant_u300 = {
.clkreg_enable = MCI_ST_U300_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 16,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.pwrreg_powerup = MCI_PWR_ON,
.f_max = 100000000,
@@ -152,7 +160,7 @@ static struct variant_data variant_nomadik = {
.clkreg = MCI_CLK_ENABLE,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -170,7 +178,7 @@ static struct variant_data variant_ux500 = {
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -178,6 +186,9 @@ static struct variant_data variant_ux500 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -188,9 +199,9 @@ static struct variant_data variant_ux500v2 = {
.clkreg_enable = MCI_ST_UX500_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
- .datactrl_mask_ddrmode = MCI_ST_DPSM_DDRMODE,
+ .datactrl_mask_ddrmode = MCI_DPSM_ST_DDRMODE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.blksz_datactrl16 = true,
@@ -199,6 +210,9 @@ static struct variant_data variant_ux500v2 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -210,7 +224,7 @@ static struct variant_data variant_qcom = {
MCI_QCOM_CLK_SELECT_IN_FBCLK,
.clkreg_8bit_bus_enable = MCI_QCOM_CLK_WIDEBUS_8,
.datactrl_mask_ddrmode = MCI_QCOM_CLK_SELECT_IN_DDR_MODE,
- .data_cmd_enable = MCI_QCOM_CSPM_DATCMD,
+ .data_cmd_enable = MCI_CPSM_QCOM_DATCMD,
.blksz_datactrl4 = true,
.datalength_bits = 24,
.pwrreg_powerup = MCI_PWR_UP,
@@ -220,6 +234,7 @@ static struct variant_data variant_qcom = {
.qcom_dml = true,
};
+/* Busy detection for the ST Micro variant */
static int mmci_card_busy(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
@@ -227,7 +242,7 @@ static int mmci_card_busy(struct mmc_host *mmc)
int busy = 0;
spin_lock_irqsave(&host->lock, flags);
- if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY)
+ if (readl(host->base + MMCISTATUS) & host->variant->busy_detect_flag)
busy = 1;
spin_unlock_irqrestore(&host->lock, flags);
@@ -294,8 +309,8 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
*/
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
- /* Keep ST Micro busy mode if enabled */
- datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE;
+ /* Keep busy mode in DPSM if enabled */
+ datactrl |= host->datactrl_reg & host->variant->busy_dpsm_flag;
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
@@ -684,8 +699,7 @@ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
next->dma_chan = NULL;
}
-static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
- bool is_first_req)
+static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct mmci_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
@@ -973,37 +987,66 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
unsigned int status)
{
void __iomem *base = host->base;
- bool sbc, busy_resp;
+ bool sbc;
if (!cmd)
return;
sbc = (cmd == host->mrq->sbc);
- busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
- if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
- MCI_CMDSENT|MCI_CMDRESPEND)))
+ /*
+ * We need to be one of these interrupts to be considered worth
+ * handling. Note that we tag on any latent IRQs postponed
+ * due to waiting for busy status.
+ */
+ if (!((status|host->busy_status) &
+ (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND)))
return;
- /* Check if we need to wait for busy completion. */
- if (host->busy_status && (status & MCI_ST_CARDBUSY))
- return;
+ /*
+ * ST Micro variant: handle busy detection.
+ */
+ if (host->variant->busy_detect) {
+ bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
- /* Enable busy completion if needed and supported. */
- if (!host->busy_status && busy_resp &&
- !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
- (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
- writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
- return;
- }
+ /* We are busy with a command, return */
+ if (host->busy_status &&
+ (status & host->variant->busy_detect_flag))
+ return;
+
+ /*
+ * We were not busy, but we now got a busy response on
+ * something that was not an error, and we double-check
+ * that the special busy status bit is still set before
+ * proceeding.
+ */
+ if (!host->busy_status && busy_resp &&
+ !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+ (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
+ /* Unmask the busy IRQ */
+ writel(readl(base + MMCIMASK0) |
+ host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ /*
+ * Now cache the last response status code (until
+ * the busy bit goes low), and return.
+ */
+ host->busy_status =
+ status & (MCI_CMDSENT|MCI_CMDRESPEND);
+ return;
+ }
- /* At busy completion, mask the IRQ and complete the request. */
- if (host->busy_status) {
- writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = 0;
+ /*
+ * At this point we are not busy with a command, we have
+ * not received a new busy request, mask the busy IRQ and
+ * fall through to process the IRQ.
+ */
+ if (host->busy_status) {
+ writel(readl(base + MMCIMASK0) &
+ ~host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ host->busy_status = 0;
+ }
}
host->cmd = NULL;
@@ -1257,9 +1300,11 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
mmci_data_irq(host, host->data, status);
}
- /* Don't poll for busy completion in irq context. */
- if (host->busy_status)
- status &= ~MCI_ST_CARDBUSY;
+ /*
+ * Don't poll for busy completion in irq context.
+ */
+ if (host->variant->busy_detect && host->busy_status)
+ status &= ~host->variant->busy_detect_flag;
ret = 1;
} while (status);
@@ -1612,9 +1657,18 @@ static int mmci_probe(struct amba_device *dev,
/* We support these capabilities. */
mmc->caps |= MMC_CAP_CMD23;
+ /*
+ * Enable busy detection.
+ */
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+ /*
+ * Not all variants have a flag to enable busy detection
+ * in the DPSM, but if they do, set it here.
+ */
+ if (variant->busy_dpsm_flag)
+ mmci_write_datactrlreg(host,
+ host->variant->busy_dpsm_flag);
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
mmc->max_busy_timeout = 0;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a1f5e4f49e2a..56322c6afba4 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -51,25 +51,27 @@
#define MCI_QCOM_CLK_SELECT_IN_DDR_MODE (BIT(14) | BIT(15))
#define MMCIARGUMENT 0x008
-#define MMCICOMMAND 0x00c
-#define MCI_CPSM_RESPONSE (1 << 6)
-#define MCI_CPSM_LONGRSP (1 << 7)
-#define MCI_CPSM_INTERRUPT (1 << 8)
-#define MCI_CPSM_PENDING (1 << 9)
-#define MCI_CPSM_ENABLE (1 << 10)
-/* Argument flag extenstions in the ST Micro versions */
-#define MCI_ST_SDIO_SUSP (1 << 11)
-#define MCI_ST_ENCMD_COMPL (1 << 12)
-#define MCI_ST_NIEN (1 << 13)
-#define MCI_ST_CE_ATACMD (1 << 14)
-/* Modified on Qualcomm Integrations */
-#define MCI_QCOM_CSPM_DATCMD BIT(12)
-#define MCI_QCOM_CSPM_MCIABORT BIT(13)
-#define MCI_QCOM_CSPM_CCSENABLE BIT(14)
-#define MCI_QCOM_CSPM_CCSDISABLE BIT(15)
-#define MCI_QCOM_CSPM_AUTO_CMD19 BIT(16)
-#define MCI_QCOM_CSPM_AUTO_CMD21 BIT(21)
+/* The command register controls the Command Path State Machine (CPSM) */
+#define MMCICOMMAND 0x00c
+#define MCI_CPSM_RESPONSE BIT(6)
+#define MCI_CPSM_LONGRSP BIT(7)
+#define MCI_CPSM_INTERRUPT BIT(8)
+#define MCI_CPSM_PENDING BIT(9)
+#define MCI_CPSM_ENABLE BIT(10)
+/* Command register flag extenstions in the ST Micro versions */
+#define MCI_CPSM_ST_SDIO_SUSP BIT(11)
+#define MCI_CPSM_ST_ENCMD_COMPL BIT(12)
+#define MCI_CPSM_ST_NIEN BIT(13)
+#define MCI_CPSM_ST_CE_ATACMD BIT(14)
+/* Command register flag extensions in the Qualcomm versions */
+#define MCI_CPSM_QCOM_PROGENA BIT(11)
+#define MCI_CPSM_QCOM_DATCMD BIT(12)
+#define MCI_CPSM_QCOM_MCIABORT BIT(13)
+#define MCI_CPSM_QCOM_CCSENABLE BIT(14)
+#define MCI_CPSM_QCOM_CCSDISABLE BIT(15)
+#define MCI_CPSM_QCOM_AUTO_CMD19 BIT(16)
+#define MCI_CPSM_QCOM_AUTO_CMD21 BIT(21)
#define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014
@@ -78,22 +80,27 @@
#define MMCIRESPONSE3 0x020
#define MMCIDATATIMER 0x024
#define MMCIDATALENGTH 0x028
+
+/* The data control register controls the Data Path State Machine (DPSM) */
#define MMCIDATACTRL 0x02c
-#define MCI_DPSM_ENABLE (1 << 0)
-#define MCI_DPSM_DIRECTION (1 << 1)
-#define MCI_DPSM_MODE (1 << 2)
-#define MCI_DPSM_DMAENABLE (1 << 3)
-#define MCI_DPSM_BLOCKSIZE (1 << 4)
+#define MCI_DPSM_ENABLE BIT(0)
+#define MCI_DPSM_DIRECTION BIT(1)
+#define MCI_DPSM_MODE BIT(2)
+#define MCI_DPSM_DMAENABLE BIT(3)
+#define MCI_DPSM_BLOCKSIZE BIT(4)
/* Control register extensions in the ST Micro U300 and Ux500 versions */
-#define MCI_ST_DPSM_RWSTART (1 << 8)
-#define MCI_ST_DPSM_RWSTOP (1 << 9)
-#define MCI_ST_DPSM_RWMOD (1 << 10)
-#define MCI_ST_DPSM_SDIOEN (1 << 11)
+#define MCI_DPSM_ST_RWSTART BIT(8)
+#define MCI_DPSM_ST_RWSTOP BIT(9)
+#define MCI_DPSM_ST_RWMOD BIT(10)
+#define MCI_DPSM_ST_SDIOEN BIT(11)
/* Control register extensions in the ST Micro Ux500 versions */
-#define MCI_ST_DPSM_DMAREQCTL (1 << 12)
-#define MCI_ST_DPSM_DBOOTMODEEN (1 << 13)
-#define MCI_ST_DPSM_BUSYMODE (1 << 14)
-#define MCI_ST_DPSM_DDRMODE (1 << 15)
+#define MCI_DPSM_ST_DMAREQCTL BIT(12)
+#define MCI_DPSM_ST_DBOOTMODEEN BIT(13)
+#define MCI_DPSM_ST_BUSYMODE BIT(14)
+#define MCI_DPSM_ST_DDRMODE BIT(15)
+/* Control register extensions in the Qualcomm versions */
+#define MCI_DPSM_QCOM_DATA_PEND BIT(17)
+#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
@@ -167,7 +174,7 @@
/* Extended status bits for the ST Micro variants */
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
-#define MCI_ST_BUSYEND (1 << 24)
+#define MCI_ST_BUSYENDMASK (1 << 24)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 84e9afcb5c09..10ef2ae1d2f6 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -927,8 +927,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
msdc_start_command(host, mrq, mrq->cmd);
}
-static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
- bool is_first_req)
+static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct msdc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
@@ -1713,6 +1712,7 @@ static const struct of_device_id msdc_of_ids[] = {
{ .compatible = "mediatek,mt8135-mmc", },
{}
};
+MODULE_DEVICE_TABLE(of, msdc_of_ids);
static struct platform_driver mt_msdc_driver = {
.probe = msdc_drv_probe,
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 5f2f24a7360d..ad11c4cc12ed 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1565,8 +1565,7 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
}
}
-static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
- bool is_first_req)
+static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 3ccaa1415f33..ecb99a8d2fa2 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -190,8 +190,7 @@ static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
return using_cookie;
}
-static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
- bool is_first_req)
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct realtek_pci_sdmmc *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
index 6e9c0f8fddb1..dc1abd14acbc 100644
--- a/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -1374,6 +1374,8 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
mutex_init(&host->host_mutex);
rtsx_usb_init_host(host);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_enable(&pdev->dev);
#ifdef RTSX_USB_USE_LEDS_CLASS
@@ -1428,6 +1430,7 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
mmc_free_host(mmc);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
platform_set_drvdata(pdev, NULL);
dev_dbg(&(pdev->dev),
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index c531deef3258..932a4b1fed33 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -28,7 +28,6 @@
#include <mach/dma.h>
#include <mach/gpio-samsung.h>
-#include <linux/platform_data/dma-s3c24xx.h>
#include <linux/platform_data/mmc-s3cmci.h>
#include "s3cmci.h"
@@ -1682,19 +1681,13 @@ static int s3cmci_probe(struct platform_device *pdev)
gpio_direction_input(host->pdata->gpio_wprotect);
}
- /* depending on the dma state, get a dma channel to use. */
+ /* Depending on the dma state, get a DMA channel to use. */
if (s3cmci_host_usedma(host)) {
- dma_cap_mask_t mask;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- host->dma = dma_request_slave_channel_compat(mask,
- s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx");
- if (!host->dma) {
+ host->dma = dma_request_chan(&pdev->dev, "rx-tx");
+ ret = PTR_ERR_OR_ZERO(host->dma);
+ if (ret) {
dev_err(&pdev->dev, "cannot get DMA channel.\n");
- ret = -EBUSY;
goto probe_free_gpio_wp;
}
}
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 81d4dc034793..160f695cc09c 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -328,6 +328,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
{ "80865ACC", NULL, &sdhci_acpi_slot_int_emmc },
{ "80865AD0", NULL, &sdhci_acpi_slot_int_sdio },
{ "80860F14" , "1" , &sdhci_acpi_slot_int_emmc },
+ { "80860F14" , "2" , &sdhci_acpi_slot_int_sdio },
{ "80860F14" , "3" , &sdhci_acpi_slot_int_sd },
{ "80860F16" , NULL, &sdhci_acpi_slot_int_sd },
{ "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio },
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
new file mode 100644
index 000000000000..1501cfdac473
--- /dev/null
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ * Author: 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/bitops.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci-pltfm.h"
+
+/* HRS - Host Register Set (specific to Cadence) */
+#define SDHCI_CDNS_HRS04 0x10 /* PHY access port */
+#define SDHCI_CDNS_HRS04_ACK BIT(26)
+#define SDHCI_CDNS_HRS04_RD BIT(25)
+#define SDHCI_CDNS_HRS04_WR BIT(24)
+#define SDHCI_CDNS_HRS04_RDATA_SHIFT 12
+#define SDHCI_CDNS_HRS04_WDATA_SHIFT 8
+#define SDHCI_CDNS_HRS04_ADDR_SHIFT 0
+
+#define SDHCI_CDNS_HRS06 0x18 /* eMMC control */
+#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15)
+#define SDHCI_CDNS_HRS06_TUNE_SHIFT 8
+#define SDHCI_CDNS_HRS06_TUNE_MASK 0x3f
+#define SDHCI_CDNS_HRS06_MODE_MASK 0x7
+#define SDHCI_CDNS_HRS06_MODE_SD 0x0
+#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2
+#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3
+#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4
+#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5
+
+/* SRS - Slot Register Set (SDHCI-compatible) */
+#define SDHCI_CDNS_SRS_BASE 0x200
+
+/* PHY */
+#define SDHCI_CDNS_PHY_DLY_SD_HS 0x00
+#define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04
+#define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05
+#define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
+#define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07
+#define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08
+
+/*
+ * The tuned val register is 6 bit-wide, but not the whole of the range is
+ * available. The range 0-42 seems to be available (then 43 wraps around to 0)
+ * but I am not quite sure if it is official. Use only 0 to 39 for safety.
+ */
+#define SDHCI_CDNS_MAX_TUNING_LOOP 40
+
+struct sdhci_cdns_priv {
+ void __iomem *hrs_addr;
+};
+
+static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+ u8 addr, u8 data)
+{
+ void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
+ u32 tmp;
+
+ tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
+ (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
+ writel(tmp, reg);
+
+ tmp |= SDHCI_CDNS_HRS04_WR;
+ writel(tmp, reg);
+
+ tmp &= ~SDHCI_CDNS_HRS04_WR;
+ writel(tmp, reg);
+}
+
+static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+{
+ sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
+ sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
+ sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
+ sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
+ sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+}
+
+static inline void *sdhci_cdns_priv(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return sdhci_pltfm_priv(pltfm_host);
+}
+
+static unsigned int sdhci_cdns_get_timeout_clock(struct sdhci_host *host)
+{
+ /*
+ * Cadence's spec says the Timeout Clock Frequency is the same as the
+ * Base Clock Frequency. Divide it by 1000 to return a value in kHz.
+ */
+ return host->max_clk / 1000;
+}
+
+static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
+ unsigned int timing)
+{
+ struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+ u32 mode, tmp;
+
+ switch (timing) {
+ case MMC_TIMING_MMC_HS:
+ mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
+ break;
+ case MMC_TIMING_MMC_DDR52:
+ mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
+ break;
+ case MMC_TIMING_MMC_HS200:
+ mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
+ break;
+ case MMC_TIMING_MMC_HS400:
+ mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+ break;
+ default:
+ mode = SDHCI_CDNS_HRS06_MODE_SD;
+ break;
+ }
+
+ /* The speed mode for eMMC is selected by HRS06 register */
+ tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+ tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+ tmp |= mode;
+ writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+
+ /* For SD, fall back to the default handler */
+ if (mode == SDHCI_CDNS_HRS06_MODE_SD)
+ sdhci_set_uhs_signaling(host, timing);
+}
+
+static const struct sdhci_ops sdhci_cdns_ops = {
+ .set_clock = sdhci_set_clock,
+ .get_timeout_clock = sdhci_cdns_get_timeout_clock,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
+ .ops = &sdhci_cdns_ops,
+};
+
+static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
+{
+ struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+ void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS06;
+ u32 tmp;
+
+ if (WARN_ON(val > SDHCI_CDNS_HRS06_TUNE_MASK))
+ return -EINVAL;
+
+ tmp = readl(reg);
+ tmp &= ~(SDHCI_CDNS_HRS06_TUNE_MASK << SDHCI_CDNS_HRS06_TUNE_SHIFT);
+ tmp |= val << SDHCI_CDNS_HRS06_TUNE_SHIFT;
+ tmp |= SDHCI_CDNS_HRS06_TUNE_UP;
+ writel(tmp, reg);
+
+ return readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS06_TUNE_UP),
+ 0, 1);
+}
+
+static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ int cur_streak = 0;
+ int max_streak = 0;
+ int end_of_streak = 0;
+ int i;
+
+ /*
+ * This handler only implements the eMMC tuning that is specific to
+ * this controller. Fall back to the standard method for SD timing.
+ */
+ if (host->timing != MMC_TIMING_MMC_HS200)
+ return sdhci_execute_tuning(mmc, opcode);
+
+ if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
+ return -EINVAL;
+
+ for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
+ if (sdhci_cdns_set_tune_val(host, i) ||
+ mmc_send_tuning(host->mmc, opcode, NULL)) { /* bad */
+ cur_streak = 0;
+ } else { /* good */
+ cur_streak++;
+ if (cur_streak > max_streak) {
+ max_streak = cur_streak;
+ end_of_streak = i;
+ }
+ }
+ }
+
+ if (!max_streak) {
+ dev_err(mmc_dev(host->mmc), "no tuning point found\n");
+ return -EIO;
+ }
+
+ return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
+}
+
+static int sdhci_cdns_probe(struct platform_device *pdev)
+{
+ struct sdhci_host *host;
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_cdns_priv *priv;
+ struct clk *clk;
+ int ret;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+
+ host = sdhci_pltfm_init(pdev, &sdhci_cdns_pltfm_data, sizeof(*priv));
+ if (IS_ERR(host)) {
+ ret = PTR_ERR(host);
+ goto disable_clk;
+ }
+
+ pltfm_host = sdhci_priv(host);
+ pltfm_host->clk = clk;
+
+ priv = sdhci_cdns_priv(host);
+ priv->hrs_addr = host->ioaddr;
+ host->ioaddr += SDHCI_CDNS_SRS_BASE;
+ host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ goto free;
+
+ sdhci_cdns_phy_init(priv);
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ goto free;
+
+ return 0;
+free:
+ sdhci_pltfm_free(pdev);
+disable_clk:
+ clk_disable_unprepare(clk);
+
+ return ret;
+}
+
+static const struct of_device_id sdhci_cdns_match[] = {
+ { .compatible = "cdns,sd4hc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_cdns_match);
+
+static struct platform_driver sdhci_cdns_driver = {
+ .driver = {
+ .name = "sdhci-cdns",
+ .pm = &sdhci_pltfm_pmops,
+ .of_match_table = sdhci_cdns_match,
+ },
+ .probe = sdhci_cdns_probe,
+ .remove = sdhci_pltfm_unregister,
+};
+module_platform_driver(sdhci_cdns_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("Cadence SD/SDIO/eMMC Host Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 726246665850..d7046d67415a 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -143,6 +143,14 @@ static void sdhci_iproc_writeb(struct sdhci_host *host, u8 val, int reg)
}
static const struct sdhci_ops sdhci_iproc_ops = {
+ .set_clock = sdhci_set_clock,
+ .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_ops sdhci_iproc_32only_ops = {
.read_l = sdhci_iproc_readl,
.read_w = sdhci_iproc_readw,
.read_b = sdhci_iproc_readb,
@@ -156,6 +164,28 @@ static const struct sdhci_ops sdhci_iproc_ops = {
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
+static const struct sdhci_pltfm_data sdhci_iproc_cygnus_pltfm_data = {
+ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+ .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
+ .ops = &sdhci_iproc_32only_ops,
+};
+
+static const struct sdhci_iproc_data iproc_cygnus_data = {
+ .pdata = &sdhci_iproc_cygnus_pltfm_data,
+ .caps = ((0x1 << SDHCI_MAX_BLOCK_SHIFT)
+ & SDHCI_MAX_BLOCK_MASK) |
+ SDHCI_CAN_VDD_330 |
+ SDHCI_CAN_VDD_180 |
+ SDHCI_CAN_DO_SUSPEND |
+ SDHCI_CAN_DO_HISPD |
+ SDHCI_CAN_DO_ADMA2 |
+ SDHCI_CAN_DO_SDMA,
+ .caps1 = SDHCI_DRIVER_TYPE_C |
+ SDHCI_DRIVER_TYPE_D |
+ SDHCI_SUPPORT_DDR50,
+ .mmc_caps = MMC_CAP_1_8V_DDR,
+};
+
static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
@@ -182,7 +212,7 @@ static const struct sdhci_pltfm_data sdhci_bcm2835_pltfm_data = {
.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
SDHCI_QUIRK_MISSING_CAPS,
- .ops = &sdhci_iproc_ops,
+ .ops = &sdhci_iproc_32only_ops,
};
static const struct sdhci_iproc_data bcm2835_data = {
@@ -194,7 +224,8 @@ static const struct sdhci_iproc_data bcm2835_data = {
static const struct of_device_id sdhci_iproc_of_match[] = {
{ .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
- { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_data },
+ { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
+ { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
{ }
};
MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 90ed2e12d345..32879b845b75 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -18,7 +18,9 @@
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/iopoll.h>
#include "sdhci-pltfm.h"
@@ -31,6 +33,7 @@
#define HC_MODE_EN 0x1
#define CORE_POWER 0x0
#define CORE_SW_RST BIT(7)
+#define FF_CLK_SW_RST_DIS BIT(13)
#define CORE_PWRCTL_STATUS 0xdc
#define CORE_PWRCTL_MASK 0xe0
@@ -49,6 +52,7 @@
#define INT_MASK 0xf
#define MAX_PHASES 16
#define CORE_DLL_LOCK BIT(7)
+#define CORE_DDR_DLL_LOCK BIT(11)
#define CORE_DLL_EN BIT(16)
#define CORE_CDR_EN BIT(17)
#define CORE_CK_OUT_EN BIT(18)
@@ -56,18 +60,67 @@
#define CORE_DLL_PDN BIT(29)
#define CORE_DLL_RST BIT(30)
#define CORE_DLL_CONFIG 0x100
+#define CORE_CMD_DAT_TRACK_SEL BIT(0)
#define CORE_DLL_STATUS 0x108
+#define CORE_DLL_CONFIG_2 0x1b4
+#define CORE_DDR_CAL_EN BIT(0)
+#define CORE_FLL_CYCLE_CNT BIT(18)
+#define CORE_DLL_CLOCK_DISABLE BIT(21)
+
#define CORE_VENDOR_SPEC 0x10c
#define CORE_CLK_PWRSAVE BIT(1)
+#define CORE_HC_MCLK_SEL_DFLT (2 << 8)
+#define CORE_HC_MCLK_SEL_HS400 (3 << 8)
+#define CORE_HC_MCLK_SEL_MASK (3 << 8)
+#define CORE_HC_SELECT_IN_EN BIT(18)
+#define CORE_HC_SELECT_IN_HS400 (6 << 19)
+#define CORE_HC_SELECT_IN_MASK (7 << 19)
+
+#define CORE_CSR_CDC_CTLR_CFG0 0x130
+#define CORE_SW_TRIG_FULL_CALIB BIT(16)
+#define CORE_HW_AUTOCAL_ENA BIT(17)
+
+#define CORE_CSR_CDC_CTLR_CFG1 0x134
+#define CORE_CSR_CDC_CAL_TIMER_CFG0 0x138
+#define CORE_TIMER_ENA BIT(16)
+
+#define CORE_CSR_CDC_CAL_TIMER_CFG1 0x13C
+#define CORE_CSR_CDC_REFCOUNT_CFG 0x140
+#define CORE_CSR_CDC_COARSE_CAL_CFG 0x144
+#define CORE_CDC_OFFSET_CFG 0x14C
+#define CORE_CSR_CDC_DELAY_CFG 0x150
+#define CORE_CDC_SLAVE_DDA_CFG 0x160
+#define CORE_CSR_CDC_STATUS0 0x164
+#define CORE_CALIBRATION_DONE BIT(0)
+
+#define CORE_CDC_ERROR_CODE_MASK 0x7000000
+
+#define CORE_CSR_CDC_GEN_CFG 0x178
+#define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
+#define CORE_CDC_SWITCH_RC_EN BIT(1)
+
+#define CORE_DDR_200_CFG 0x184
+#define CORE_CDC_T4_DLY_SEL BIT(0)
+#define CORE_START_CDC_TRAFFIC BIT(6)
+#define CORE_VENDOR_SPEC3 0x1b0
+#define CORE_PWRSAVE_DLL BIT(3)
+
+#define CORE_DDR_CONFIG 0x1b8
+#define DDR_CONFIG_POR_VAL 0x80040853
#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
+#define INVALID_TUNING_PHASE -1
+#define SDHCI_MSM_MIN_CLOCK 400000
+#define CORE_FREQ_100MHZ (100 * 1000 * 1000)
+
#define CDR_SELEXT_SHIFT 20
#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
#define CMUX_SHIFT_PHASE_SHIFT 24
#define CMUX_SHIFT_PHASE_MASK (7 << CMUX_SHIFT_PHASE_SHIFT)
+#define MSM_MMC_AUTOSUSPEND_DELAY_MS 50
struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -75,7 +128,14 @@ struct sdhci_msm_host {
struct clk *clk; /* main SD/MMC bus clock */
struct clk *pclk; /* SDHC peripheral bus clock */
struct clk *bus_clk; /* SDHC bus voter clock */
+ struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/
+ unsigned long clk_rate;
struct mmc_host *mmc;
+ bool use_14lpp_dll_reset;
+ bool tuning_done;
+ bool calibration_done;
+ u8 saved_tuning_phase;
+ bool use_cdclp533;
};
/* Platform specific tuning */
@@ -115,6 +175,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
u32 config;
struct mmc_host *mmc = host->mmc;
+ if (phase > 0xf)
+ return -EINVAL;
+
spin_lock_irqsave(&host->lock, flags);
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
@@ -136,9 +199,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
- /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
rc = msm_dll_poll_ck_out_en(host, 1);
@@ -163,8 +226,8 @@ out:
* Find out the greatest range of consecuitive selected
* DLL clock output phases that can be used as sampling
* setting for SD3.0 UHS-I card read operation (in SDR104
- * timing mode) or for eMMC4.5 card read operation (in HS200
- * timing mode).
+ * timing mode) or for eMMC4.5 card read operation (in
+ * HS400/HS200 timing mode).
* Select the 3/4 of the range and configure the DLL with the
* selected DLL clock output phase.
*/
@@ -303,8 +366,11 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
static int msm_init_cm_dll(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
int wait_cnt = 50;
unsigned long flags;
+ u32 config;
spin_lock_irqsave(&host->lock, flags);
@@ -313,33 +379,73 @@ static int msm_init_cm_dll(struct sdhci_host *host)
* tuning is in progress. Keeping PWRSAVE ON may
* turn off the clock.
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_CLK_PWRSAVE;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+ if (msm_host->use_14lpp_dll_reset) {
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config |= CORE_DLL_CLOCK_DISABLE;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ }
- /* Write 1 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
- /* Write 1 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
msm_cm_dll_set_freq(host);
- /* Write 0 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ if (msm_host->use_14lpp_dll_reset &&
+ !IS_ERR_OR_NULL(msm_host->xo_clk)) {
+ u32 mclk_freq = 0;
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config &= CORE_FLL_CYCLE_CNT;
+ if (config)
+ mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8),
+ clk_get_rate(msm_host->xo_clk));
+ else
+ mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4),
+ clk_get_rate(msm_host->xo_clk));
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config &= ~(0xFF << 10);
+ config |= mclk_freq << 10;
- /* Write 0 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ /* wait for 5us before enabling DLL clock */
+ udelay(5);
+ }
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config &= ~CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ if (msm_host->use_14lpp_dll_reset) {
+ msm_cm_dll_set_freq(host);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config &= ~CORE_DLL_CLOCK_DISABLE;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+ }
- /* Set DLL_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
- /* Set CK_OUT_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CK_OUT_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
@@ -358,6 +464,200 @@ static int msm_init_cm_dll(struct sdhci_host *host)
return 0;
}
+static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ u32 config, calib_done;
+ int ret;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Retuning in HS400 (DDR mode) will fail, just reset the
+ * tuning block and restore the saved tuning phase.
+ */
+ ret = msm_init_cm_dll(host);
+ if (ret)
+ goto out;
+
+ /* Set the selected phase in delay line hw block */
+ ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+ if (ret)
+ goto out;
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CMD_DAT_TRACK_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config &= ~CORE_CDC_T4_DLY_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+ config &= ~CORE_CDC_SWITCH_BYPASS_OFF;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+ config |= CORE_CDC_SWITCH_RC_EN;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config &= ~CORE_START_CDC_TRAFFIC;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+ /*
+ * Perform CDC Register Initialization Sequence
+ *
+ * CORE_CSR_CDC_CTLR_CFG0 0x11800EC
+ * CORE_CSR_CDC_CTLR_CFG1 0x3011111
+ * CORE_CSR_CDC_CAL_TIMER_CFG0 0x1201000
+ * CORE_CSR_CDC_CAL_TIMER_CFG1 0x4
+ * CORE_CSR_CDC_REFCOUNT_CFG 0xCB732020
+ * CORE_CSR_CDC_COARSE_CAL_CFG 0xB19
+ * CORE_CSR_CDC_DELAY_CFG 0x3AC
+ * CORE_CDC_OFFSET_CFG 0x0
+ * CORE_CDC_SLAVE_DDA_CFG 0x16334
+ */
+
+ writel_relaxed(0x11800EC, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ writel_relaxed(0x3011111, host->ioaddr + CORE_CSR_CDC_CTLR_CFG1);
+ writel_relaxed(0x1201000, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+ writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
+ writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
+ writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
+ writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+ writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
+ writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
+
+ /* CDC HW Calibration */
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config |= CORE_SW_TRIG_FULL_CALIB;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config &= ~CORE_SW_TRIG_FULL_CALIB;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ config |= CORE_HW_AUTOCAL_ENA;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+ config |= CORE_TIMER_ENA;
+ writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+
+ ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_CSR_CDC_STATUS0,
+ calib_done,
+ (calib_done & CORE_CALIBRATION_DONE),
+ 1, 50);
+
+ if (ret == -ETIMEDOUT) {
+ pr_err("%s: %s: CDC calibration was not completed\n",
+ mmc_hostname(host->mmc), __func__);
+ goto out;
+ }
+
+ ret = readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
+ & CORE_CDC_ERROR_CODE_MASK;
+ if (ret) {
+ pr_err("%s: %s: CDC error code %d\n",
+ mmc_hostname(host->mmc), __func__, ret);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+ config |= CORE_START_CDC_TRAFFIC;
+ writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
+static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
+{
+ u32 dll_status, config;
+ int ret;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Currently the CORE_DDR_CONFIG register defaults to desired
+ * configuration on reset. Currently reprogramming the power on
+ * reset (POR) value in case it might have been modified by
+ * bootloaders. In the future, if this changes, then the desired
+ * values will need to be programmed appropriately.
+ */
+ writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+ config |= CORE_DDR_CAL_EN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+
+ ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
+ dll_status,
+ (dll_status & CORE_DDR_DLL_LOCK),
+ 10, 1000);
+
+ if (ret == -ETIMEDOUT) {
+ pr_err("%s: %s: CM_DLL_SDC4 calibration was not completed\n",
+ mmc_hostname(host->mmc), __func__);
+ goto out;
+ }
+
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3);
+ config |= CORE_PWRSAVE_DLL;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC3);
+
+ /*
+ * Drain writebuffer to ensure above DLL calibration
+ * and PWRSAVE DLL is enabled.
+ */
+ wmb();
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
+static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+ u32 config;
+
+ pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Retuning in HS400 (DDR mode) will fail, just reset the
+ * tuning block and restore the saved tuning phase.
+ */
+ ret = msm_init_cm_dll(host);
+ if (ret)
+ goto out;
+
+ /* Set the selected phase in delay line hw block */
+ ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+ if (ret)
+ goto out;
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_CMD_DAT_TRACK_SEL;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ if (msm_host->use_cdclp533)
+ ret = sdhci_msm_cdclp533_calibration(host);
+ else
+ ret = sdhci_msm_cm_dll_sdc4_calibration(host);
+out:
+ pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
int tuning_seq_cnt = 3;
@@ -365,14 +665,17 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
int rc;
struct mmc_host *mmc = host->mmc;
struct mmc_ios ios = host->mmc->ios;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
/*
* Tuning is required for SDR104, HS200 and HS400 cards and
* if clock frequency is greater than 100MHz in these modes.
*/
- if (host->clock <= 100 * 1000 * 1000 ||
- !((ios.timing == MMC_TIMING_MMC_HS200) ||
- (ios.timing == MMC_TIMING_UHS_SDR104)))
+ if (host->clock <= CORE_FREQ_100MHZ ||
+ !(ios.timing == MMC_TIMING_MMC_HS400 ||
+ ios.timing == MMC_TIMING_MMC_HS200 ||
+ ios.timing == MMC_TIMING_UHS_SDR104))
return 0;
retry:
@@ -388,6 +691,7 @@ retry:
if (rc)
return rc;
+ msm_host->saved_tuning_phase = phase;
rc = mmc_send_tuning(mmc, opcode, NULL);
if (!rc) {
/* Tuning is successful at this tuning point */
@@ -423,6 +727,8 @@ retry:
rc = -EIO;
}
+ if (!rc)
+ msm_host->tuning_done = true;
return rc;
}
@@ -430,7 +736,10 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
unsigned int uhs)
{
struct mmc_host *mmc = host->mmc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u16 ctrl_2;
+ u32 config;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
@@ -445,6 +754,7 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
case MMC_TIMING_UHS_SDR50:
ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
break;
+ case MMC_TIMING_MMC_HS400:
case MMC_TIMING_MMC_HS200:
case MMC_TIMING_UHS_SDR104:
ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
@@ -461,15 +771,42 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
* provide feedback clock, the mode selection can be any value less
* than 3'b011 in bits [2:0] of HOST CONTROL2 register.
*/
- if (host->clock <= 100000000 &&
- (uhs == MMC_TIMING_MMC_HS400 ||
- uhs == MMC_TIMING_MMC_HS200 ||
- uhs == MMC_TIMING_UHS_SDR104))
- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ if (host->clock <= CORE_FREQ_100MHZ) {
+ if (uhs == MMC_TIMING_MMC_HS400 ||
+ uhs == MMC_TIMING_MMC_HS200 ||
+ uhs == MMC_TIMING_UHS_SDR104)
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ /*
+ * DLL is not required for clock <= 100MHz
+ * Thus, make sure DLL it is disabled when not required
+ */
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_RST;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config |= CORE_DLL_PDN;
+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+ /*
+ * The DLL needs to be restored and CDCLP533 recalibrated
+ * when the clock frequency is set back to 400MHz.
+ */
+ msm_host->calibration_done = false;
+ }
dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+ spin_unlock_irq(&host->lock);
+ /* CDCLP533 HW calibration is only required for HS400 mode*/
+ if (host->clock > CORE_FREQ_100MHZ &&
+ msm_host->tuning_done && !msm_host->calibration_done &&
+ mmc->ios.timing == MMC_TIMING_MMC_HS400)
+ if (!sdhci_msm_hs400_dll_calibration(host))
+ msm_host->calibration_done = true;
+ spin_lock_irq(&host->lock);
}
static void sdhci_msm_voltage_switch(struct sdhci_host *host)
@@ -505,6 +842,183 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+ return clk_round_rate(msm_host->clk, ULONG_MAX);
+}
+
+static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
+{
+ return SDHCI_MSM_MIN_CLOCK;
+}
+
+/**
+ * __sdhci_msm_set_clock - sdhci_msm clock control.
+ *
+ * Description:
+ * MSM controller does not use internal divider and
+ * instead directly control the GCC clock as per
+ * HW recommendation.
+ **/
+void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ u16 clk;
+ /*
+ * Keep actual_clock as zero -
+ * - since there is no divider used so no need of having actual_clock.
+ * - MSM controller uses SDCLK for data timeout calculation. If
+ * actual_clock is zero, host->clock is taken for calculation.
+ */
+ host->mmc->actual_clock = 0;
+
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ return;
+
+ /*
+ * MSM controller do not use clock divider.
+ * Thus read SDHCI_CLOCK_CONTROL and only enable
+ * clock with no divider value programmed.
+ */
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ sdhci_enable_clk(host, clk);
+}
+
+/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
+static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ struct mmc_ios curr_ios = host->mmc->ios;
+ u32 config, dll_lock;
+ int rc;
+
+ if (!clock) {
+ msm_host->clk_rate = clock;
+ goto out;
+ }
+
+ spin_unlock_irq(&host->lock);
+ /*
+ * The SDHC requires internal clock frequency to be double the
+ * actual clock that will be set for DDR mode. The controller
+ * uses the faster clock(100/400MHz) for some of its parts and
+ * send the actual required clock (50/200MHz) to the card.
+ */
+ if (curr_ios.timing == MMC_TIMING_UHS_DDR50 ||
+ curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
+ curr_ios.timing == MMC_TIMING_MMC_HS400)
+ clock *= 2;
+ /*
+ * In general all timing modes are controlled via UHS mode select in
+ * Host Control2 register. eMMC specific HS200/HS400 doesn't have
+ * their respective modes defined here, hence we use these values.
+ *
+ * HS200 - SDR104 (Since they both are equivalent in functionality)
+ * HS400 - This involves multiple configurations
+ * Initially SDR104 - when tuning is required as HS200
+ * Then when switching to DDR @ 400MHz (HS400) we use
+ * the vendor specific HC_SELECT_IN to control the mode.
+ *
+ * In addition to controlling the modes we also need to select the
+ * correct input clock for DLL depending on the mode.
+ *
+ * HS400 - divided clock (free running MCLK/2)
+ * All other modes - default (free running MCLK)
+ */
+ if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
+ /* Select the divided clock (free running MCLK/2) */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_MCLK_SEL_MASK;
+ config |= CORE_HC_MCLK_SEL_HS400;
+
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ /*
+ * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+ * register
+ */
+ if (msm_host->tuning_done && !msm_host->calibration_done) {
+ /*
+ * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
+ * field in VENDOR_SPEC_FUNC
+ */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config |= CORE_HC_SELECT_IN_HS400;
+ config |= CORE_HC_SELECT_IN_EN;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+ if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
+ /*
+ * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
+ * CORE_DLL_STATUS to be set. This should get set
+ * within 15 us at 200 MHz.
+ */
+ rc = readl_relaxed_poll_timeout(host->ioaddr +
+ CORE_DLL_STATUS,
+ dll_lock,
+ (dll_lock &
+ (CORE_DLL_LOCK |
+ CORE_DDR_DLL_LOCK)), 10,
+ 1000);
+ if (rc == -ETIMEDOUT)
+ pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
+ mmc_hostname(host->mmc), dll_lock);
+ }
+ } else {
+ if (!msm_host->use_cdclp533) {
+ config = readl_relaxed(host->ioaddr +
+ CORE_VENDOR_SPEC3);
+ config &= ~CORE_PWRSAVE_DLL;
+ writel_relaxed(config, host->ioaddr +
+ CORE_VENDOR_SPEC3);
+ }
+
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_MCLK_SEL_MASK;
+ config |= CORE_HC_MCLK_SEL_DFLT;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+ /*
+ * Disable HC_SELECT_IN to be able to use the UHS mode select
+ * configuration from Host Control2 register for all other
+ * modes.
+ * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+ * in VENDOR_SPEC_FUNC
+ */
+ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ config &= ~CORE_HC_SELECT_IN_EN;
+ config &= ~CORE_HC_SELECT_IN_MASK;
+ writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+
+ /*
+ * Make sure above writes impacting free running MCLK are completed
+ * before changing the clk_rate at GCC.
+ */
+ wmb();
+
+ rc = clk_set_rate(msm_host->clk, clock);
+ if (rc) {
+ pr_err("%s: Failed to set clock at rate %u at timing %d\n",
+ mmc_hostname(host->mmc), clock,
+ curr_ios.timing);
+ goto out_lock;
+ }
+ msm_host->clk_rate = clock;
+ pr_debug("%s: Setting clock at rate %lu at timing %d\n",
+ mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
+ curr_ios.timing);
+
+out_lock:
+ spin_lock_irq(&host->lock);
+out:
+ __sdhci_msm_set_clock(host, clock);
+}
+
static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -515,7 +1029,9 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
static const struct sdhci_ops sdhci_msm_ops = {
.platform_execute_tuning = sdhci_msm_execute_tuning,
.reset = sdhci_reset,
- .set_clock = sdhci_set_clock,
+ .set_clock = sdhci_msm_set_clock,
+ .get_min_clock = sdhci_msm_get_min_clock,
+ .get_max_clock = sdhci_msm_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.voltage_switch = sdhci_msm_voltage_switch,
@@ -524,7 +1040,9 @@ static const struct sdhci_ops sdhci_msm_ops = {
static const struct sdhci_pltfm_data sdhci_msm_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
SDHCI_QUIRK_NO_CARD_NO_RESET |
- SDHCI_QUIRK_SINGLE_POWER_WRITE,
+ SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.ops = &sdhci_msm_ops,
};
@@ -536,7 +1054,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
struct resource *core_memres;
int ret;
u16 host_version, core_minor;
- u32 core_version, caps;
+ u32 core_version, config;
u8 core_major;
host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
@@ -554,6 +1072,8 @@ static int sdhci_msm_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
+ msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+
/* Setup SDCC bus voter clock. */
msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (!IS_ERR(msm_host->bus_clk)) {
@@ -586,6 +1106,16 @@ static int sdhci_msm_probe(struct platform_device *pdev)
goto pclk_disable;
}
+ /*
+ * xo clock is needed for FLL feature of cm_dll.
+ * In case if xo clock is not mentioned in DT, warn and proceed.
+ */
+ msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo");
+ if (IS_ERR(msm_host->xo_clk)) {
+ ret = PTR_ERR(msm_host->xo_clk);
+ dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret);
+ }
+
/* Vote for maximum clock rate for maximum performance */
ret = clk_set_rate(msm_host->clk, INT_MAX);
if (ret)
@@ -604,9 +1134,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
goto clk_disable;
}
- /* Reset the core and Enable SDHC mode */
- writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
- CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+ config = readl_relaxed(msm_host->core_mem + CORE_POWER);
+ config |= CORE_SW_RST;
+ writel_relaxed(config, msm_host->core_mem + CORE_POWER);
/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
usleep_range(1000, 5000);
@@ -619,6 +1149,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
/* Set HC_MODE_EN bit in HC_MODE register */
writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+ config = readl_relaxed(msm_host->core_mem + CORE_HC_MODE);
+ config |= FF_CLK_SW_RST_DIS;
+ writel_relaxed(config, msm_host->core_mem + CORE_HC_MODE);
+
host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
@@ -631,14 +1165,24 @@ static int sdhci_msm_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
core_version, core_major, core_minor);
+ if (core_major == 1 && core_minor >= 0x42)
+ msm_host->use_14lpp_dll_reset = true;
+
+ /*
+ * SDCC 5 controller with major version 1, minor version 0x34 and later
+ * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL.
+ */
+ if (core_major == 1 && core_minor < 0x34)
+ msm_host->use_cdclp533 = true;
+
/*
* Support for some capabilities is not advertised by newer
* controller versions and must be explicitly enabled.
*/
if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
- caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
- caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
- writel_relaxed(caps, host->ioaddr +
+ config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
+ config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
+ writel_relaxed(config, host->ioaddr +
CORE_VENDOR_SPEC_CAPABILITIES0);
}
@@ -659,12 +1203,26 @@ static int sdhci_msm_probe(struct platform_device *pdev)
goto clk_disable;
}
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ MSM_MMC_AUTOSUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
ret = sdhci_add_host(host);
if (ret)
- goto clk_disable;
+ goto pm_runtime_disable;
+
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
return 0;
+pm_runtime_disable:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
clk_disable:
clk_disable_unprepare(msm_host->clk);
pclk_disable:
@@ -686,6 +1244,11 @@ static int sdhci_msm_remove(struct platform_device *pdev)
0xffffffff);
sdhci_remove_host(host, dead);
+
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
clk_disable_unprepare(msm_host->clk);
clk_disable_unprepare(msm_host->pclk);
if (!IS_ERR(msm_host->bus_clk))
@@ -694,12 +1257,57 @@ static int sdhci_msm_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int sdhci_msm_runtime_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+ clk_disable_unprepare(msm_host->clk);
+ clk_disable_unprepare(msm_host->pclk);
+
+ return 0;
+}
+
+static int sdhci_msm_runtime_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+
+ ret = clk_prepare_enable(msm_host->clk);
+ if (ret) {
+ dev_err(dev, "clk_enable failed for core_clk: %d\n", ret);
+ return ret;
+ }
+ ret = clk_prepare_enable(msm_host->pclk);
+ if (ret) {
+ dev_err(dev, "clk_enable failed for iface_clk: %d\n", ret);
+ clk_disable_unprepare(msm_host->clk);
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops sdhci_msm_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend,
+ sdhci_msm_runtime_resume,
+ NULL)
+};
+
static struct platform_driver sdhci_msm_driver = {
.probe = sdhci_msm_probe,
.remove = sdhci_msm_remove,
.driver = {
.name = "sdhci_msm",
.of_match_table = sdhci_msm_dt_match,
+ .pm = &sdhci_msm_pm_ops,
},
};
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index a9b7fc06c434..2f9ad213377a 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -100,6 +100,7 @@ static const struct of_device_id sdhci_at91_dt_match[] = {
{ .compatible = "atmel,sama5d2-sdhci", .data = &soc_data_sama5d2 },
{}
};
+MODULE_DEVICE_TABLE(of, sdhci_at91_dt_match);
#ifdef CONFIG_PM
static int sdhci_at91_runtime_suspend(struct device *dev)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 1bb11e4a9fe5..9a6eb4492172 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/sys_soc.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -28,6 +29,7 @@
struct sdhci_esdhc {
u8 vendor_ver;
u8 spec_ver;
+ bool quirk_incorrect_hostver;
};
/**
@@ -87,6 +89,8 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host,
static u16 esdhc_readw_fixup(struct sdhci_host *host,
int spec_reg, u32 value)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
u16 ret;
int shift = (spec_reg & 0x2) * 8;
@@ -94,6 +98,12 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,
ret = value & 0xffff;
else
ret = (value >> shift) & 0xffff;
+ /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
+ * vendor version and spec version information.
+ */
+ if ((spec_reg == SDHCI_HOST_VERSION) &&
+ (esdhc->quirk_incorrect_hostver))
+ ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
return ret;
}
@@ -572,6 +582,12 @@ static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
.ops = &sdhci_esdhc_le_ops,
};
+static struct soc_device_attribute soc_incorrect_hostver[] = {
+ { .family = "QorIQ T4240", .revision = "1.0", },
+ { .family = "QorIQ T4240", .revision = "2.0", },
+ { },
+};
+
static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host;
@@ -585,6 +601,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
SDHCI_VENDOR_VER_SHIFT;
esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
+ if (soc_device_match(soc_incorrect_hostver))
+ esdhc->quirk_incorrect_hostver = true;
+ else
+ esdhc->quirk_incorrect_hostver = false;
}
static int sdhci_esdhc_probe(struct platform_device *pdev)
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 1d9e00a00e9f..1a72d32af07f 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -27,6 +27,7 @@
#include <linux/pm_runtime.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdhci-pci-data.h>
+#include <linux/acpi.h>
#include "sdhci.h"
#include "sdhci-pci.h"
@@ -375,6 +376,44 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
return 0;
}
+#ifdef CONFIG_ACPI
+static int ni_set_max_freq(struct sdhci_pci_slot *slot)
+{
+ acpi_status status;
+ unsigned long long max_freq;
+
+ status = acpi_evaluate_integer(ACPI_HANDLE(&slot->chip->pdev->dev),
+ "MXFQ", NULL, &max_freq);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&slot->chip->pdev->dev,
+ "MXFQ not found in acpi table\n");
+ return -EINVAL;
+ }
+
+ slot->host->mmc->f_max = max_freq * 1000000;
+
+ return 0;
+}
+#else
+static inline int ni_set_max_freq(struct sdhci_pci_slot *slot)
+{
+ return 0;
+}
+#endif
+
+static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+ int err;
+
+ err = ni_set_max_freq(slot);
+ if (err)
+ return err;
+
+ slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+ MMC_CAP_WAIT_WHILE_BUSY;
+ return 0;
+}
+
static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
@@ -390,7 +429,8 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
slot->cd_override_level = true;
if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD ||
slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXTM_SD ||
- slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD) {
+ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD ||
+ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) {
slot->host->mmc_host_ops.get_cd = bxt_get_cd;
slot->host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM;
}
@@ -447,6 +487,15 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.ops = &sdhci_intel_byt_ops,
};
+static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
+ SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .allow_runtime_pm = true,
+ .probe_slot = ni_byt_sdio_probe_slot,
+ .ops = &sdhci_intel_byt_ops,
+};
+
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
@@ -1079,6 +1128,14 @@ static const struct pci_device_id pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BYT_SDIO,
+ .subvendor = PCI_VENDOR_ID_NI,
+ .subdevice = 0x7884,
+ .driver_data = (kernel_ulong_t)&sdhci_ni_byt_sdio,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BYT_SDIO,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio,
@@ -1277,6 +1334,30 @@ static const struct pci_device_id pci_ids[] = {
},
{
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_GLK_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_GLK_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_GLK_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,
@@ -1735,11 +1816,16 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
host->mmc->slotno = slotno;
host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
- if (slot->cd_idx >= 0 &&
- mmc_gpiod_request_cd(host->mmc, slot->cd_con_id, slot->cd_idx,
- slot->cd_override_level, 0, NULL)) {
- dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
- slot->cd_idx = -1;
+ if (slot->cd_idx >= 0) {
+ ret = mmc_gpiod_request_cd(host->mmc, slot->cd_con_id, slot->cd_idx,
+ slot->cd_override_level, 0, NULL);
+ if (ret == -EPROBE_DEFER)
+ goto remove;
+
+ if (ret) {
+ dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
+ slot->cd_idx = -1;
+ }
}
ret = sdhci_add_host(host);
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 6bccf56bc5ff..4abdaed72bd4 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -34,6 +34,9 @@
#define PCI_DEVICE_ID_INTEL_APL_SD 0x5aca
#define PCI_DEVICE_ID_INTEL_APL_EMMC 0x5acc
#define PCI_DEVICE_ID_INTEL_APL_SDIO 0x5ad0
+#define PCI_DEVICE_ID_INTEL_GLK_SD 0x31ca
+#define PCI_DEVICE_ID_INTEL_GLK_EMMC 0x31cc
+#define PCI_DEVICE_ID_INTEL_GLK_SDIO 0x31d0
/*
* PCI registers
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 3280f2077959..957839d0fe37 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -106,7 +106,7 @@ extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
{
- return (void *)host->private;
+ return host->private;
}
extern const struct dev_pm_ops sdhci_pltfm_pmops;
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 784c5a848fb4..de219ca7ea7c 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -121,7 +121,9 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
* speed possible with selected clock source and skip the division.
*/
if (ourhost->no_divider) {
+ spin_unlock_irq(&ourhost->host->lock);
rate = clk_round_rate(clksrc, wanted);
+ spin_lock_irq(&ourhost->host->lock);
return wanted - rate;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 42ef3ebb1d8c..111991e5b9a0 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -22,6 +22,7 @@
#include <linux/scatterlist.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
#include <linux/leds.h>
@@ -1343,20 +1344,10 @@ clock_set:
}
EXPORT_SYMBOL_GPL(sdhci_calc_clk);
-void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
{
- u16 clk;
unsigned long timeout;
- host->mmc->actual_clock = 0;
-
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-
- if (clock == 0)
- return;
-
- clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
-
clk |= SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
@@ -1377,6 +1368,22 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
+EXPORT_SYMBOL_GPL(sdhci_enable_clk);
+
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ u16 clk;
+
+ host->mmc->actual_clock = 0;
+
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ return;
+
+ clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+ sdhci_enable_clk(host, clk);
+}
EXPORT_SYMBOL_GPL(sdhci_set_clock);
static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
@@ -1623,7 +1630,14 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if ((ios->timing == MMC_TIMING_SD_HS ||
- ios->timing == MMC_TIMING_MMC_HS)
+ ios->timing == MMC_TIMING_MMC_HS ||
+ ios->timing == MMC_TIMING_MMC_HS400 ||
+ ios->timing == MMC_TIMING_MMC_HS200 ||
+ ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_UHS_SDR50 ||
+ ios->timing == MMC_TIMING_UHS_SDR104 ||
+ ios->timing == MMC_TIMING_UHS_DDR50 ||
+ ios->timing == MMC_TIMING_UHS_SDR25)
&& !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
ctrl |= SDHCI_CTRL_HISPD;
else
@@ -1632,16 +1646,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->version >= SDHCI_SPEC_300) {
u16 clk, ctrl_2;
- /* In case of UHS-I modes, set High Speed Enable */
- if ((ios->timing == MMC_TIMING_MMC_HS400) ||
- (ios->timing == MMC_TIMING_MMC_HS200) ||
- (ios->timing == MMC_TIMING_MMC_DDR52) ||
- (ios->timing == MMC_TIMING_UHS_SDR50) ||
- (ios->timing == MMC_TIMING_UHS_SDR104) ||
- (ios->timing == MMC_TIMING_UHS_DDR50) ||
- (ios->timing == MMC_TIMING_UHS_SDR25))
- ctrl |= SDHCI_CTRL_HISPD;
-
if (!host->preset_enabled) {
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
/*
@@ -1948,11 +1952,157 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
return 0;
}
-static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+static void sdhci_start_tuning(struct sdhci_host *host)
{
- struct sdhci_host *host = mmc_priv(mmc);
u16 ctrl;
- int tuning_loop_counter = MAX_TUNING_LOOP;
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl |= SDHCI_CTRL_EXEC_TUNING;
+ if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
+ ctrl |= SDHCI_CTRL_TUNED_CLK;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+ /*
+ * As per the Host Controller spec v3.00, tuning command
+ * generates Buffer Read Ready interrupt, so enable that.
+ *
+ * Note: The spec clearly says that when tuning sequence
+ * is being performed, the controller does not generate
+ * interrupts other than Buffer Read Ready interrupt. But
+ * to make sure we don't hit a controller bug, we _only_
+ * enable Buffer Read Ready interrupt here.
+ */
+ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_end_tuning(struct sdhci_host *host)
+{
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_reset_tuning(struct sdhci_host *host)
+{
+ u16 ctrl;
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+ ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+}
+
+static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode,
+ unsigned long flags)
+{
+ sdhci_reset_tuning(host);
+
+ sdhci_do_reset(host, SDHCI_RESET_CMD);
+ sdhci_do_reset(host, SDHCI_RESET_DATA);
+
+ sdhci_end_tuning(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ mmc_abort_tuning(host->mmc, opcode);
+ spin_lock_irqsave(&host->lock, flags);
+}
+
+/*
+ * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI
+ * tuning command does not have a data payload (or rather the hardware does it
+ * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command
+ * interrupt setup is different to other commands and there is no timeout
+ * interrupt so special handling is needed.
+ */
+static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode,
+ unsigned long flags)
+{
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_command cmd = {0};
+ struct mmc_request mrq = {NULL};
+
+ cmd.opcode = opcode;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+ cmd.mrq = &mrq;
+
+ mrq.cmd = &cmd;
+ /*
+ * In response to CMD19, the card sends 64 bytes of tuning
+ * block to the Host Controller. So we set the block size
+ * to 64 here.
+ */
+ if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 &&
+ mmc->ios.bus_width == MMC_BUS_WIDTH_8)
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), SDHCI_BLOCK_SIZE);
+ else
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
+
+ /*
+ * The tuning block is sent by the card to the host controller.
+ * So we set the TRNS_READ bit in the Transfer Mode register.
+ * This also takes care of setting DMA Enable and Multi Block
+ * Select in the same register to 0.
+ */
+ sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+ sdhci_send_command(host, &cmd);
+
+ host->cmd = NULL;
+
+ sdhci_del_timer(host, &mrq);
+
+ host->tuning_done = 0;
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ /* Wait for Buffer Read Ready interrupt */
+ wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1),
+ msecs_to_jiffies(50));
+
+ spin_lock_irqsave(&host->lock, flags);
+}
+
+static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode,
+ unsigned long flags)
+{
+ int i;
+
+ /*
+ * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
+ * of loops reaches 40 times.
+ */
+ for (i = 0; i < MAX_TUNING_LOOP; i++) {
+ u16 ctrl;
+
+ sdhci_send_tuning(host, opcode, flags);
+
+ if (!host->tuning_done) {
+ pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
+ mmc_hostname(host->mmc));
+ sdhci_abort_tuning(host, opcode, flags);
+ return;
+ }
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
+ if (ctrl & SDHCI_CTRL_TUNED_CLK)
+ return; /* Success! */
+ break;
+ }
+
+ /* eMMC spec does not require a delay between tuning cycles */
+ if (opcode == MMC_SEND_TUNING_BLOCK)
+ mdelay(1);
+ }
+
+ pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
+ mmc_hostname(host->mmc));
+ sdhci_reset_tuning(host);
+}
+
+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
int err = 0;
unsigned long flags;
unsigned int tuning_count = 0;
@@ -2003,144 +2153,22 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
if (host->ops->platform_execute_tuning) {
spin_unlock_irqrestore(&host->lock, flags);
- err = host->ops->platform_execute_tuning(host, opcode);
- return err;
+ return host->ops->platform_execute_tuning(host, opcode);
}
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl |= SDHCI_CTRL_EXEC_TUNING;
- if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
- ctrl |= SDHCI_CTRL_TUNED_CLK;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- /*
- * As per the Host Controller spec v3.00, tuning command
- * generates Buffer Read Ready interrupt, so enable that.
- *
- * Note: The spec clearly says that when tuning sequence
- * is being performed, the controller does not generate
- * interrupts other than Buffer Read Ready interrupt. But
- * to make sure we don't hit a controller bug, we _only_
- * enable Buffer Read Ready interrupt here.
- */
- sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
- sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
-
- /*
- * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
- * of loops reaches 40 times.
- */
- do {
- struct mmc_command cmd = {0};
- struct mmc_request mrq = {NULL};
-
- cmd.opcode = opcode;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
- cmd.retries = 0;
- cmd.data = NULL;
- cmd.mrq = &mrq;
- cmd.error = 0;
-
- if (tuning_loop_counter-- == 0)
- break;
-
- mrq.cmd = &cmd;
-
- /*
- * In response to CMD19, the card sends 64 bytes of tuning
- * block to the Host Controller. So we set the block size
- * to 64 here.
- */
- if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
- if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
- SDHCI_BLOCK_SIZE);
- else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
- SDHCI_BLOCK_SIZE);
- } else {
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
- SDHCI_BLOCK_SIZE);
- }
-
- /*
- * The tuning block is sent by the card to the host controller.
- * So we set the TRNS_READ bit in the Transfer Mode register.
- * This also takes care of setting DMA Enable and Multi Block
- * Select in the same register to 0.
- */
- sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
-
- sdhci_send_command(host, &cmd);
-
- host->cmd = NULL;
- sdhci_del_timer(host, &mrq);
-
- spin_unlock_irqrestore(&host->lock, flags);
- /* Wait for Buffer Read Ready interrupt */
- wait_event_timeout(host->buf_ready_int,
- (host->tuning_done == 1),
- msecs_to_jiffies(50));
- spin_lock_irqsave(&host->lock, flags);
-
- if (!host->tuning_done) {
- pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
-
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl &= ~SDHCI_CTRL_TUNED_CLK;
- ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- err = -EIO;
- goto out;
- }
+ host->mmc->retune_period = tuning_count;
- host->tuning_done = 0;
+ sdhci_start_tuning(host);
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ __sdhci_execute_tuning(host, opcode, flags);
- /* eMMC spec does not require a delay between tuning cycles */
- if (opcode == MMC_SEND_TUNING_BLOCK)
- mdelay(1);
- } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
-
- /*
- * The Host Driver has exhausted the maximum number of loops allowed,
- * so use fixed sampling frequency.
- */
- if (tuning_loop_counter < 0) {
- ctrl &= ~SDHCI_CTRL_TUNED_CLK;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- }
- if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
- pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n");
- err = -EIO;
- }
-
-out:
- if (tuning_count) {
- /*
- * In case tuning fails, host controllers which support
- * re-tuning can try tuning again at a later time, when the
- * re-tuning timer expires. So for these controllers, we
- * return 0. Since there might be other controllers who do not
- * have this capability, we return error for them.
- */
- err = 0;
- }
-
- host->mmc->retune_period = err ? 0 : tuning_count;
-
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ sdhci_end_tuning(host);
out_unlock:
spin_unlock_irqrestore(&host->lock, flags);
+
return err;
}
+EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
static int sdhci_select_drive_strength(struct mmc_card *card,
unsigned int max_dtr, int host_drv,
@@ -2198,8 +2226,7 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
data->host_cookie = COOKIE_UNMAPPED;
}
-static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
- bool is_first_req)
+static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -3010,6 +3037,8 @@ static int sdhci_set_dma_mask(struct sdhci_host *host)
void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1)
{
u16 v;
+ u64 dt_caps_mask = 0;
+ u64 dt_caps = 0;
if (host->read_caps)
return;
@@ -3024,18 +3053,35 @@ void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1)
sdhci_do_reset(host, SDHCI_RESET_ALL);
+ of_property_read_u64(mmc_dev(host->mmc)->of_node,
+ "sdhci-caps-mask", &dt_caps_mask);
+ of_property_read_u64(mmc_dev(host->mmc)->of_node,
+ "sdhci-caps", &dt_caps);
+
v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
if (host->quirks & SDHCI_QUIRK_MISSING_CAPS)
return;
- host->caps = caps ? *caps : sdhci_readl(host, SDHCI_CAPABILITIES);
+ if (caps) {
+ host->caps = *caps;
+ } else {
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps &= ~lower_32_bits(dt_caps_mask);
+ host->caps |= lower_32_bits(dt_caps);
+ }
if (host->version < SDHCI_SPEC_300)
return;
- host->caps1 = caps1 ? *caps1 : sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ if (caps1) {
+ host->caps1 = *caps1;
+ } else {
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~upper_32_bits(dt_caps_mask);
+ host->caps1 |= upper_32_bits(dt_caps);
+ }
}
EXPORT_SYMBOL_GPL(__sdhci_read_caps);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 2570455b219a..0b66f210ae82 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -656,7 +656,7 @@ extern void sdhci_free_host(struct sdhci_host *host);
static inline void *sdhci_priv(struct sdhci_host *host)
{
- return (void *)host->private;
+ return host->private;
}
extern void sdhci_card_detect(struct sdhci_host *host);
@@ -682,6 +682,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
unsigned int *actual_clock);
void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
+void sdhci_enable_clk(struct sdhci_host *host, u16 clk);
void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
unsigned short vdd);
void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
@@ -689,6 +690,7 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
#ifdef CONFIG_PM
extern int sdhci_suspend_host(struct sdhci_host *host);
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 49edff7fee49..d46c2d00c182 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -47,31 +47,69 @@
#define host_to_priv(host) container_of((host)->pdata, struct sh_mobile_sdhi, mmc_data)
+struct sh_mobile_sdhi_scc {
+ unsigned long clk_rate; /* clock rate for SDR104 */
+ u32 tap; /* sampling clock position for SDR104 */
+};
+
struct sh_mobile_sdhi_of_data {
unsigned long tmio_flags;
+ u32 tmio_ocr_mask;
unsigned long capabilities;
unsigned long capabilities2;
enum dma_slave_buswidth dma_buswidth;
dma_addr_t dma_rx_offset;
unsigned bus_shift;
+ int scc_offset;
+ struct sh_mobile_sdhi_scc *taps;
+ int taps_num;
};
static const struct sh_mobile_sdhi_of_data of_default_cfg = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
};
+static const struct sh_mobile_sdhi_of_data of_rz_compatible = {
+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_32BIT_DATA_PORT,
+ .tmio_ocr_mask = MMC_VDD_32_33,
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+};
+
static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE |
TMIO_MMC_CLK_ACTUAL,
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
};
+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen2_scc_taps[] = {
+ {
+ .clk_rate = 156000000,
+ .tap = 0x00000703,
+ },
+ {
+ .clk_rate = 0,
+ .tap = 0x00000300,
+ },
+};
+
static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE |
TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
.dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES,
.dma_rx_offset = 0x2000,
+ .scc_offset = 0x0300,
+ .taps = rcar_gen2_scc_taps,
+ .taps_num = ARRAY_SIZE(rcar_gen2_scc_taps),
+};
+
+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen3_scc_taps[] = {
+ {
+ .clk_rate = 0,
+ .tap = 0x00000300,
+ },
};
static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = {
@@ -79,6 +117,9 @@ static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = {
TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
.bus_shift = 2,
+ .scc_offset = 0x1000,
+ .taps = rcar_gen3_scc_taps,
+ .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps),
};
static const struct of_device_id sh_mobile_sdhi_of_match[] = {
@@ -86,6 +127,7 @@ static const struct of_device_id sh_mobile_sdhi_of_match[] = {
{ .compatible = "renesas,sdhi-sh73a0", .data = &of_default_cfg, },
{ .compatible = "renesas,sdhi-r8a73a4", .data = &of_default_cfg, },
{ .compatible = "renesas,sdhi-r8a7740", .data = &of_default_cfg, },
+ { .compatible = "renesas,sdhi-r7s72100", .data = &of_rz_compatible, },
{ .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, },
{ .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, },
{ .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, },
@@ -105,6 +147,7 @@ struct sh_mobile_sdhi {
struct tmio_mmc_dma dma_priv;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default, *pins_uhs;
+ void __iomem *scc_ctl;
};
static void sh_mobile_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
@@ -255,6 +298,201 @@ static int sh_mobile_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
return pinctrl_select_state(priv->pinctrl, pin_state);
}
+/* SCC registers */
+#define SH_MOBILE_SDHI_SCC_DTCNTL 0x000
+#define SH_MOBILE_SDHI_SCC_TAPSET 0x002
+#define SH_MOBILE_SDHI_SCC_DT2FF 0x004
+#define SH_MOBILE_SDHI_SCC_CKSEL 0x006
+#define SH_MOBILE_SDHI_SCC_RVSCNTL 0x008
+#define SH_MOBILE_SDHI_SCC_RVSREQ 0x00A
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_DTCNTL register */
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN BIT(0)
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK 0xff
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_CKSEL register */
+#define SH_MOBILE_SDHI_SCC_CKSEL_DTSEL BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSCNTL register */
+#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSREQ register */
+#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR BIT(2)
+
+static inline u32 sd_scc_read32(struct tmio_mmc_host *host,
+ struct sh_mobile_sdhi *priv, int addr)
+{
+ return readl(priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_scc_write32(struct tmio_mmc_host *host,
+ struct sh_mobile_sdhi *priv,
+ int addr, u32 val)
+{
+ writel(val, priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static unsigned int sh_mobile_sdhi_init_tuning(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return 0;
+
+ priv = host_to_priv(host);
+
+ /* set sampling clock selection range */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+ 0x8 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
+
+ /* Initialize SCC */
+ sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, 0x0);
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+ SH_MOBILE_SDHI_SCC_CKSEL_DTSEL |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, host->scc_tappos);
+
+ /* Read TAPNUM */
+ return (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL) >>
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) &
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK;
+}
+
+static void sh_mobile_sdhi_prepare_tuning(struct tmio_mmc_host *host,
+ unsigned long tap)
+{
+ struct sh_mobile_sdhi *priv = host_to_priv(host);
+
+ /* Set sampling clock position */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap);
+}
+
+#define SH_MOBILE_SDHI_MAX_TAP 3
+
+static int sh_mobile_sdhi_select_tuning(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv = host_to_priv(host);
+ unsigned long tap_cnt; /* counter of tuning success */
+ unsigned long tap_set; /* tap position */
+ unsigned long tap_start;/* start position of tuning success */
+ unsigned long tap_end; /* end position of tuning success */
+ unsigned long ntap; /* temporary counter of tuning success */
+ unsigned long i;
+
+ /* Clear SCC_RVSREQ */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+
+ /*
+ * Find the longest consecutive run of successful probes. If that
+ * is more than SH_MOBILE_SDHI_MAX_TAP probes long then use the
+ * center index as the tap.
+ */
+ tap_cnt = 0;
+ ntap = 0;
+ tap_start = 0;
+ tap_end = 0;
+ for (i = 0; i < host->tap_num * 2; i++) {
+ if (test_bit(i, host->taps))
+ ntap++;
+ else {
+ if (ntap > tap_cnt) {
+ tap_start = i - ntap;
+ tap_end = i - 1;
+ tap_cnt = ntap;
+ }
+ ntap = 0;
+ }
+ }
+
+ if (ntap > tap_cnt) {
+ tap_start = i - ntap;
+ tap_end = i - 1;
+ tap_cnt = ntap;
+ }
+
+ if (tap_cnt >= SH_MOBILE_SDHI_MAX_TAP)
+ tap_set = (tap_start + tap_end) / 2 % host->tap_num;
+ else
+ return -EIO;
+
+ /* Set SCC */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap_set);
+
+ /* Enable auto re-tuning */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ return 0;
+}
+
+
+static bool sh_mobile_sdhi_check_scc_error(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return 0;
+
+ priv = host_to_priv(host);
+
+ /* Check SCC error */
+ if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) &
+ SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &&
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ) &
+ SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR) {
+ /* Clear SCC error */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+ return true;
+ }
+
+ return false;
+}
+
+static void sh_mobile_sdhi_hw_reset(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return;
+
+ priv = host_to_priv(host);
+
+ /* Reset SCC */
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+ ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+}
+
static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
{
int timeout = 1000;
@@ -325,7 +563,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
struct tmio_mmc_data *mmd = pdev->dev.platform_data;
struct tmio_mmc_host *host;
struct resource *res;
- int irq, ret, i = 0;
+ int irq, ret, i;
struct tmio_mmc_dma *dma_priv;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -364,6 +602,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
const struct sh_mobile_sdhi_of_data *of_data = of_id->data;
mmc_data->flags |= of_data->tmio_flags;
+ mmc_data->ocr_mask = of_data->tmio_ocr_mask;
mmc_data->capabilities |= of_data->capabilities;
mmc_data->capabilities2 |= of_data->capabilities2;
mmc_data->dma_rx_offset = of_data->dma_rx_offset;
@@ -384,6 +623,11 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
host->card_busy = sh_mobile_sdhi_card_busy;
host->start_signal_voltage_switch =
sh_mobile_sdhi_start_signal_voltage_switch;
+ host->init_tuning = sh_mobile_sdhi_init_tuning;
+ host->prepare_tuning = sh_mobile_sdhi_prepare_tuning;
+ host->select_tuning = sh_mobile_sdhi_select_tuning;
+ host->check_scc_error = sh_mobile_sdhi_check_scc_error;
+ host->hw_reset = sh_mobile_sdhi_hw_reset;
}
/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@@ -424,6 +668,34 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
if (ret < 0)
goto efree;
+ if (host->mmc->caps & MMC_CAP_UHS_SDR104) {
+ host->mmc->caps |= MMC_CAP_HW_RESET;
+
+ if (of_id && of_id->data) {
+ const struct sh_mobile_sdhi_of_data *of_data;
+ const struct sh_mobile_sdhi_scc *taps;
+ bool hit = false;
+
+ of_data = of_id->data;
+ taps = of_data->taps;
+
+ for (i = 0; i < of_data->taps_num; i++) {
+ if (taps[i].clk_rate == 0 ||
+ taps[i].clk_rate == host->mmc->f_max) {
+ host->scc_tappos = taps->tap;
+ hit = true;
+ break;
+ }
+ }
+
+ if (!hit)
+ dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
+
+ priv->scc_ctl = host->ctl + of_data->scc_offset;
+ }
+ }
+
+ i = 0;
while (1) {
irq = platform_get_irq(pdev, i);
if (irq < 0)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index c0a5c676d0e8..b1d1303389a7 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -822,10 +822,13 @@ static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
case MMC_POWER_UP:
- host->ferror = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
- ios->vdd);
- if (host->ferror)
- return;
+ if (!IS_ERR(mmc->supply.vmmc)) {
+ host->ferror = mmc_regulator_set_ocr(mmc,
+ mmc->supply.vmmc,
+ ios->vdd);
+ if (host->ferror)
+ return;
+ }
if (!IS_ERR(mmc->supply.vqmmc)) {
host->ferror = regulator_enable(mmc->supply.vqmmc);
@@ -847,7 +850,9 @@ static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF:
dev_dbg(mmc_dev(mmc), "power off!\n");
sunxi_mmc_reset_host(host);
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+ if (!IS_ERR(mmc->supply.vmmc))
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled)
regulator_disable(mmc->supply.vqmmc);
host->vqmmc_enabled = false;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 8e126afd988c..9e20bcf3aa8d 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -153,9 +153,12 @@ struct tmio_mmc_host {
struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug;
bool sdio_irq_enabled;
+ u32 scc_tappos;
- int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+ /* Mandatory callback */
int (*clk_enable)(struct tmio_mmc_host *host);
+
+ /* Optional callbacks */
unsigned int (*clk_update)(struct tmio_mmc_host *host,
unsigned int new_clock);
void (*clk_disable)(struct tmio_mmc_host *host);
@@ -164,6 +167,21 @@ struct tmio_mmc_host {
int (*card_busy)(struct mmc_host *mmc);
int (*start_signal_voltage_switch)(struct mmc_host *mmc,
struct mmc_ios *ios);
+ int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+ void (*hw_reset)(struct tmio_mmc_host *host);
+ void (*prepare_tuning)(struct tmio_mmc_host *host, unsigned long tap);
+ bool (*check_scc_error)(struct tmio_mmc_host *host);
+
+ /*
+ * Mandatory callback for tuning to occur which is optional for SDR50
+ * and mandatory for SDR104.
+ */
+ unsigned int (*init_tuning)(struct tmio_mmc_host *host);
+ int (*select_tuning)(struct tmio_mmc_host *host);
+
+ /* Tuning values: 1 for success, 0 for failure */
+ DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long));
+ unsigned int tap_num;
};
struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
@@ -245,6 +263,12 @@ static inline u32 sd_ctrl_read16_and_16_as_32(struct tmio_mmc_host *host, int ad
readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
}
+static inline void sd_ctrl_read32_rep(struct tmio_mmc_host *host, int addr,
+ u32 *buf, int count)
+{
+ readsl(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
{
/* If there is a hook and it returns non-zero then there
@@ -267,4 +291,10 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, int
writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
}
+static inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr,
+ const u32 *buf, int count)
+{
+ writesl(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
#endif
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 700567603107..2064fa1a5bf1 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -22,7 +22,6 @@
* TODO:
* Investigate using a workqueue for PIO transfers
* Eliminate FIXMEs
- * SDIO support
* Better Power management
* Handle MMC errors better
* double buffer support
@@ -36,6 +35,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mfd/tmio.h>
+#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
@@ -298,6 +298,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
if (mrq->cmd->error || (mrq->data && mrq->data->error))
tmio_mmc_abort_dma(host);
+ if (host->check_scc_error)
+ host->check_scc_error(host);
+
mmc_request_done(host->mmc, mrq);
}
@@ -393,6 +396,36 @@ static void tmio_mmc_transfer_data(struct tmio_mmc_host *host,
/*
* Transfer the data
*/
+ if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) {
+ u8 data[4] = { };
+
+ if (is_read)
+ sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+ count >> 2);
+ else
+ sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+ count >> 2);
+
+ /* if count was multiple of 4 */
+ if (!(count & 0x3))
+ return;
+
+ buf8 = (u8 *)(buf + (count >> 2));
+ count %= 4;
+
+ if (is_read) {
+ sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT,
+ (u32 *)data, 1);
+ memcpy(buf8, data, count);
+ } else {
+ memcpy(data, buf8, count);
+ sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT,
+ (u32 *)data, 1);
+ }
+
+ return;
+ }
+
if (is_read)
sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
else
@@ -522,7 +555,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
schedule_work(&host->done);
}
-static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
+static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat)
{
struct mmc_data *data;
spin_lock(&host->lock);
@@ -531,6 +564,9 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
if (!data)
goto out;
+ if (stat & TMIO_STAT_CRCFAIL || stat & TMIO_STAT_STOPBIT_ERR ||
+ stat & TMIO_STAT_TXUNDERRUN)
+ data->error = -EILSEQ;
if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS);
bool done = false;
@@ -579,8 +615,6 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
goto out;
}
- host->cmd = NULL;
-
/* This controller is sicker than the PXA one. Not only do we need to
* drop the top 8 bits of the first response word, we also need to
* modify the order of the response for short response command types.
@@ -600,14 +634,16 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
if (stat & TMIO_STAT_CMDTIMEOUT)
cmd->error = -ETIMEDOUT;
- else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
+ else if ((stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC) ||
+ stat & TMIO_STAT_STOPBIT_ERR ||
+ stat & TMIO_STAT_CMD_IDX_ERR)
cmd->error = -EILSEQ;
/* If there is data to handle we enable data IRQs here, and
* we will ultimatley finish the request in the data_end handler.
* If theres no data or we encountered an error, finish now.
*/
- if (host->data && !cmd->error) {
+ if (host->data && (!cmd->error || cmd->error == -EILSEQ)) {
if (host->data->flags & MMC_DATA_READ) {
if (host->force_pio || !host->chan_rx)
tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP);
@@ -668,7 +704,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
/* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
- tmio_mmc_data_irq(host);
+ tmio_mmc_data_irq(host, status);
return true;
}
@@ -687,7 +723,7 @@ static void tmio_mmc_sdio_irq(int irq, void *devid)
return;
status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
- ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
+ ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask;
sdio_status = status & ~TMIO_SDIO_MASK_ALL;
if (pdata->flags & TMIO_MMC_SDIO_STATUS_QUIRK)
@@ -756,6 +792,63 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
return 0;
}
+static void tmio_mmc_hw_reset(struct mmc_host *mmc)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+
+ if (host->hw_reset)
+ host->hw_reset(host);
+}
+
+static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ int i, ret = 0;
+
+ if (!host->tap_num) {
+ if (!host->init_tuning || !host->select_tuning)
+ /* Tuning is not supported */
+ goto out;
+
+ host->tap_num = host->init_tuning(host);
+ if (!host->tap_num)
+ /* Tuning is not supported */
+ goto out;
+ }
+
+ if (host->tap_num * 2 >= sizeof(host->taps) * BITS_PER_BYTE) {
+ dev_warn_once(&host->pdev->dev,
+ "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n");
+ goto out;
+ }
+
+ bitmap_zero(host->taps, host->tap_num * 2);
+
+ /* Issue CMD19 twice for each tap */
+ for (i = 0; i < 2 * host->tap_num; i++) {
+ if (host->prepare_tuning)
+ host->prepare_tuning(host, i % host->tap_num);
+
+ ret = mmc_send_tuning(mmc, opcode, NULL);
+ if (ret && ret != -EILSEQ)
+ goto out;
+ if (ret == 0)
+ set_bit(i, host->taps);
+
+ mdelay(1);
+ }
+
+ ret = host->select_tuning(host);
+
+out:
+ if (ret < 0) {
+ dev_warn(&host->pdev->dev, "Tuning procedure failed\n");
+ tmio_mmc_hw_reset(mmc);
+ }
+
+ return ret;
+}
+
/* Process requests from the MMC layer */
static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
@@ -972,6 +1065,8 @@ static struct mmc_host_ops tmio_mmc_ops = {
.get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
.multi_io_quirk = tmio_multi_io_quirk,
+ .hw_reset = tmio_mmc_hw_reset,
+ .execute_tuning = tmio_mmc_execute_tuning,
};
static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
@@ -1218,6 +1313,11 @@ int tmio_mmc_host_runtime_suspend(struct device *dev)
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend);
+static bool tmio_mmc_can_retune(struct tmio_mmc_host *host)
+{
+ return host->tap_num && mmc_can_retune(host->mmc);
+}
+
int tmio_mmc_host_runtime_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -1231,6 +1331,9 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
tmio_mmc_enable_dma(host, true);
+ if (tmio_mmc_can_retune(host) && host->select_tuning(host))
+ dev_warn(&host->pdev->dev, "Tuning selection failed\n");
+
return 0;
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index c3fd16d997ca..80a3b11f3217 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1395,23 +1395,25 @@ static void wbsd_request_dma(struct wbsd_host *host, int dma)
*/
host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(mmc_dev(host->mmc), host->dma_addr))
+ goto kfree;
/*
* ISA DMA must be aligned on a 64k basis.
*/
if ((host->dma_addr & 0xffff) != 0)
- goto kfree;
+ goto unmap;
/*
* ISA cannot access memory above 16 MB.
*/
else if (host->dma_addr >= 0x1000000)
- goto kfree;
+ goto unmap;
host->dma = dma;
return;
-kfree:
+unmap:
/*
* If we've gotten here then there is some kind of alignment bug
*/
@@ -1421,6 +1423,7 @@ kfree:
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
host->dma_addr = 0;
+kfree:
kfree(host->dma_buffer);
host->dma_buffer = NULL;
@@ -1434,7 +1437,7 @@ err:
static void wbsd_release_dma(struct wbsd_host *host)
{
- if (host->dma_addr) {
+ if (!dma_mapping_error(mmc_dev(host->mmc), host->dma_addr)) {
dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
}
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index e90c6a7333d7..31f89f1c6123 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -59,7 +59,6 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static const struct net_device_ops ipddp_netdev_ops = {
.ndo_start_xmit = ipddp_xmit,
.ndo_do_ioctl = ipddp_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 551f0f8dead3..c80b023092dd 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -950,13 +950,61 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
dev_queue_xmit(skb);
}
+struct alb_walk_data {
+ struct bonding *bond;
+ struct slave *slave;
+ u8 *mac_addr;
+ bool strict_match;
+};
+
+static int alb_upper_dev_walk(struct net_device *upper, void *_data)
+{
+ struct alb_walk_data *data = _data;
+ bool strict_match = data->strict_match;
+ struct bonding *bond = data->bond;
+ struct slave *slave = data->slave;
+ u8 *mac_addr = data->mac_addr;
+ struct bond_vlan_tag *tags;
+
+ if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
+ if (strict_match &&
+ ether_addr_equal_64bits(mac_addr,
+ upper->dev_addr)) {
+ alb_send_lp_vid(slave, mac_addr,
+ vlan_dev_vlan_proto(upper),
+ vlan_dev_vlan_id(upper));
+ } else if (!strict_match) {
+ alb_send_lp_vid(slave, upper->dev_addr,
+ vlan_dev_vlan_proto(upper),
+ vlan_dev_vlan_id(upper));
+ }
+ }
+
+ /* If this is a macvlan device, then only send updates
+ * when strict_match is turned off.
+ */
+ if (netif_is_macvlan(upper) && !strict_match) {
+ tags = bond_verify_device_path(bond->dev, upper, 0);
+ if (IS_ERR_OR_NULL(tags))
+ BUG();
+ alb_send_lp_vid(slave, upper->dev_addr,
+ tags[0].vlan_proto, tags[0].vlan_id);
+ kfree(tags);
+ }
+
+ return 0;
+}
+
static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
bool strict_match)
{
struct bonding *bond = bond_get_bond_by_slave(slave);
- struct net_device *upper;
- struct list_head *iter;
- struct bond_vlan_tag *tags;
+ struct alb_walk_data data = {
+ .strict_match = strict_match,
+ .mac_addr = mac_addr,
+ .slave = slave,
+ .bond = bond,
+ };
/* send untagged */
alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -965,33 +1013,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
* for that device.
*/
rcu_read_lock();
- netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
- if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
- if (strict_match &&
- ether_addr_equal_64bits(mac_addr,
- upper->dev_addr)) {
- alb_send_lp_vid(slave, mac_addr,
- vlan_dev_vlan_proto(upper),
- vlan_dev_vlan_id(upper));
- } else if (!strict_match) {
- alb_send_lp_vid(slave, upper->dev_addr,
- vlan_dev_vlan_proto(upper),
- vlan_dev_vlan_id(upper));
- }
- }
-
- /* If this is a macvlan device, then only send updates
- * when strict_match is turned off.
- */
- if (netif_is_macvlan(upper) && !strict_match) {
- tags = bond_verify_device_path(bond->dev, upper, 0);
- if (IS_ERR_OR_NULL(tags))
- BUG();
- alb_send_lp_vid(slave, upper->dev_addr,
- tags[0].vlan_proto, tags[0].vlan_id);
- kfree(tags);
- }
- }
+ netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data);
rcu_read_unlock();
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5fa36ebc0640..8029dd4912b6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -199,7 +199,7 @@ MODULE_PARM_DESC(lp_interval, "The number of seconds between instances where "
atomic_t netpoll_block_tx = ATOMIC_INIT(0);
#endif
-int bond_net_id __read_mostly;
+unsigned int bond_net_id __read_mostly;
static __be32 arp_target[BOND_MAX_ARP_TARGETS];
static int arp_ip_count;
@@ -2270,22 +2270,23 @@ re_arm:
}
}
+static int bond_upper_dev_walk(struct net_device *upper, void *data)
+{
+ __be32 ip = *((__be32 *)data);
+
+ return ip == bond_confirm_addr(upper, 0, ip);
+}
+
static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
{
- struct net_device *upper;
- struct list_head *iter;
bool ret = false;
if (ip == bond_confirm_addr(bond->dev, 0, ip))
return true;
rcu_read_lock();
- netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
- if (ip == bond_confirm_addr(upper, 0, ip)) {
- ret = true;
- break;
- }
- }
+ if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &ip))
+ ret = true;
rcu_read_unlock();
return ret;
@@ -4079,16 +4080,16 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
return ret;
}
-static int bond_ethtool_get_settings(struct net_device *bond_dev,
- struct ethtool_cmd *ecmd)
+static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
+ struct ethtool_link_ksettings *cmd)
{
struct bonding *bond = netdev_priv(bond_dev);
unsigned long speed = 0;
struct list_head *iter;
struct slave *slave;
- ecmd->duplex = DUPLEX_UNKNOWN;
- ecmd->port = PORT_OTHER;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ cmd->base.port = PORT_OTHER;
/* Since bond_slave_can_tx returns false for all inactive or down slaves, we
* do not need to check mode. Though link speed might not represent
@@ -4099,12 +4100,12 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
if (bond_slave_can_tx(slave)) {
if (slave->speed != SPEED_UNKNOWN)
speed += slave->speed;
- if (ecmd->duplex == DUPLEX_UNKNOWN &&
+ if (cmd->base.duplex == DUPLEX_UNKNOWN &&
slave->duplex != DUPLEX_UNKNOWN)
- ecmd->duplex = slave->duplex;
+ cmd->base.duplex = slave->duplex;
}
}
- ethtool_cmd_speed_set(ecmd, speed ? : SPEED_UNKNOWN);
+ cmd->base.speed = speed ? : SPEED_UNKNOWN;
return 0;
}
@@ -4120,8 +4121,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
static const struct ethtool_ops bond_ethtool_ops = {
.get_drvinfo = bond_ethtool_get_drvinfo,
- .get_settings = bond_ethtool_get_settings,
.get_link = ethtool_op_get_link,
+ .get_link_ksettings = bond_ethtool_get_link_ksettings,
};
static const struct net_device_ops bond_netdev_ops = {
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index db9538d4b358..a7be12d9a139 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -15,7 +15,7 @@
* See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
* sysfs interface.
*
- * See "Documentation/kernel-parameters.txt" for information on the module
+ * See "Documentation/admin-guide/kernel-parameters.rst" for information on the module
* parameters.
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index d51e0c401b48..18cc529fb807 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -459,7 +459,7 @@ struct kvaser_usb {
struct usb_endpoint_descriptor *bulk_in, *bulk_out;
struct usb_anchor rx_submitted;
- /* @max_tx_urbs: Firmware-reported maximum number of oustanding,
+ /* @max_tx_urbs: Firmware-reported maximum number of outstanding,
* not yet ACKed, transmissions on this device. This value is
* also used as a sentinel for marking free tx contexts.
*/
@@ -2027,7 +2027,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
((dev->fw_version >> 16) & 0xff),
(dev->fw_version & 0xffff));
- dev_dbg(&intf->dev, "Max oustanding tx = %d URBs\n", dev->max_tx_urbs);
+ dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs);
err = kvaser_usb_get_card_info(dev);
if (err) {
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 221f5f011ff9..91c876a0a647 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -7,9 +7,6 @@
*
*/
-
-#include <linux/module.h>
-
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
@@ -264,7 +261,6 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_do_ioctl = e100_ioctl,
.ndo_set_mac_address = e100_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_config = e100_set_config,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = e100_netpoll,
@@ -412,6 +408,7 @@ etrax_ethernet_init(void)
led_next_time = jiffies;
return 0;
}
+device_initcall(etrax_ethernet_init)
/* set MAC address of the interface. called from the core after a
* SIOCSIFADDR ioctl, and from the bootup above.
@@ -1715,11 +1712,6 @@ e100_netpoll(struct net_device* netdev)
}
#endif
-static int
-etrax_init_module(void)
-{
- return etrax_ethernet_init();
-}
static int __init
e100_boot_setup(char* str)
@@ -1742,5 +1734,3 @@ e100_boot_setup(char* str)
}
__setup("etrax100_eth=", e100_boot_setup);
-
-module_init(etrax_init_module);
diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig
index 486668813e15..1aaa7a95ebc4 100644
--- a/drivers/net/dsa/mv88e6xxx/Kconfig
+++ b/drivers/net/dsa/mv88e6xxx/Kconfig
@@ -1,6 +1,7 @@
config NET_DSA_MV88E6XXX
tristate "Marvell 88E6xxx Ethernet switch fabric support"
depends on NET_DSA
+ select IRQ_DOMAIN
select NET_DSA_TAG_EDSA
select NET_DSA_TAG_DSA
help
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index 10ce820daa48..c36be318de1a 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
mv88e6xxx-objs := chip.o
mv88e6xxx-objs += global1.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
+mv88e6xxx-objs += port.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 883fd9809dd2..4da379f28d5d 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -18,11 +18,15 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_bridge.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/jiffies.h>
#include <linux/list.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/netdevice.h>
#include <linux/gpio/consumer.h>
@@ -33,6 +37,7 @@
#include "mv88e6xxx.h"
#include "global1.h"
#include "global2.h"
+#include "port.h"
static void assert_reg_lock(struct mv88e6xxx_chip *chip)
{
@@ -217,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
return 0;
}
-static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
- u16 *val)
-{
- int addr = chip->info->port_base_addr + port;
-
- return mv88e6xxx_read(chip, addr, reg, val);
-}
-
-static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
- u16 val)
-{
- int addr = chip->info->port_base_addr + port;
-
- return mv88e6xxx_write(chip, addr, reg, val);
-}
-
static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
int reg, u16 *val)
{
@@ -323,6 +312,180 @@ static int mv88e6xxx_serdes_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
reg, val);
}
+static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int n = d->hwirq;
+
+ chip->g1_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int n = d->hwirq;
+
+ chip->g1_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
+{
+ struct mv88e6xxx_chip *chip = dev_id;
+ unsigned int nhandled = 0;
+ unsigned int sub_irq;
+ unsigned int n;
+ u16 reg;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err)
+ goto out;
+
+ for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+ if (reg & (1 << n)) {
+ sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
+ handle_nested_irq(sub_irq);
+ ++nhandled;
+ }
+ }
+out:
+ return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+ mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
+ if (err)
+ goto out;
+
+ reg &= ~mask;
+ reg |= (~chip->g1_irq.masked & mask);
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+ if (err)
+ goto out;
+
+out:
+ mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g1_irq_chip = {
+ .name = "mv88e6xxx-g1",
+ .irq_mask = mv88e6xxx_g1_irq_mask,
+ .irq_unmask = mv88e6xxx_g1_irq_unmask,
+ .irq_bus_lock = mv88e6xxx_g1_irq_bus_lock,
+ .irq_bus_sync_unlock = mv88e6xxx_g1_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
+ unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct mv88e6xxx_chip *chip = d->host_data;
+
+ irq_set_chip_data(irq, d->host_data);
+ irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
+ .map = mv88e6xxx_g1_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
+{
+ int irq, virq;
+ u16 mask;
+
+ mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
+ mask |= GENMASK(chip->g1_irq.nirqs, 0);
+ mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+
+ free_irq(chip->irq, chip);
+
+ for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
+ virq = irq_find_mapping(chip->g1_irq.domain, irq);
+ irq_dispose_mapping(virq);
+ }
+
+ irq_domain_remove(chip->g1_irq.domain);
+}
+
+static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
+{
+ int err, irq, virq;
+ u16 reg, mask;
+
+ chip->g1_irq.nirqs = chip->info->g1_irqs;
+ chip->g1_irq.domain = irq_domain_add_simple(
+ NULL, chip->g1_irq.nirqs, 0,
+ &mv88e6xxx_g1_irq_domain_ops, chip);
+ if (!chip->g1_irq.domain)
+ return -ENOMEM;
+
+ for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
+ irq_create_mapping(chip->g1_irq.domain, irq);
+
+ chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
+ chip->g1_irq.masked = ~0;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
+ if (err)
+ goto out_mapping;
+
+ mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+ if (err)
+ goto out_disable;
+
+ /* Reading the interrupt status clears (most of) them */
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+ if (err)
+ goto out_disable;
+
+ err = request_threaded_irq(chip->irq, NULL,
+ mv88e6xxx_g1_irq_thread_fn,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ dev_name(chip->dev), chip);
+ if (err)
+ goto out_disable;
+
+ return 0;
+
+out_disable:
+ mask |= GENMASK(chip->g1_irq.nirqs, 0);
+ mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+
+out_mapping:
+ for (irq = 0; irq < 16; irq++) {
+ virq = irq_find_mapping(chip->g1_irq.domain, irq);
+ irq_dispose_mapping(virq);
+ }
+
+ irq_domain_remove(chip->g1_irq.domain);
+
+ return err;
+}
+
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
{
int i;
@@ -364,56 +527,18 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
static int mv88e6xxx_ppu_disable(struct mv88e6xxx_chip *chip)
{
- u16 val;
- int i, err;
-
- err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
- if (err)
- return err;
-
- err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
- val & ~GLOBAL_CONTROL_PPU_ENABLE);
- if (err)
- return err;
-
- for (i = 0; i < 16; i++) {
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
- if (err)
- return err;
+ if (!chip->info->ops->ppu_disable)
+ return 0;
- usleep_range(1000, 2000);
- if ((val & GLOBAL_STATUS_PPU_MASK) != GLOBAL_STATUS_PPU_POLLING)
- return 0;
- }
-
- return -ETIMEDOUT;
+ return chip->info->ops->ppu_disable(chip);
}
static int mv88e6xxx_ppu_enable(struct mv88e6xxx_chip *chip)
{
- u16 val;
- int i, err;
-
- err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
- if (err)
- return err;
-
- err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
- val | GLOBAL_CONTROL_PPU_ENABLE);
- if (err)
- return err;
-
- for (i = 0; i < 16; i++) {
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
- if (err)
- return err;
-
- usleep_range(1000, 2000);
- if ((val & GLOBAL_STATUS_PPU_MASK) == GLOBAL_STATUS_PPU_POLLING)
- return 0;
- }
+ if (!chip->info->ops->ppu_enable)
+ return 0;
- return -ETIMEDOUT;
+ return chip->info->ops->ppu_enable(chip);
}
static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
@@ -477,9 +602,8 @@ static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_chip *chip)
{
mutex_init(&chip->ppu_mutex);
INIT_WORK(&chip->ppu_work, mv88e6xxx_ppu_reenable_work);
- init_timer(&chip->ppu_timer);
- chip->ppu_timer.data = (unsigned long)chip;
- chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
+ setup_timer(&chip->ppu_timer, mv88e6xxx_ppu_reenable_timer,
+ (unsigned long)chip);
}
static void mv88e6xxx_ppu_state_destroy(struct mv88e6xxx_chip *chip)
@@ -515,11 +639,6 @@ static int mv88e6xxx_phy_ppu_write(struct mv88e6xxx_chip *chip, int addr,
return err;
}
-static bool mv88e6xxx_6065_family(struct mv88e6xxx_chip *chip)
-{
- return chip->info->family == MV88E6XXX_FAMILY_6065;
-}
-
static bool mv88e6xxx_6095_family(struct mv88e6xxx_chip *chip)
{
return chip->info->family == MV88E6XXX_FAMILY_6095;
@@ -555,231 +674,152 @@ static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip)
return chip->info->family == MV88E6XXX_FAMILY_6352;
}
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
- struct phy_device *phydev)
+static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
+ int link, int speed, int duplex,
+ phy_interface_t mode)
{
- struct mv88e6xxx_chip *chip = ds->priv;
- u16 reg;
int err;
- if (!phy_is_pseudo_fixed_link(phydev))
- return;
-
- mutex_lock(&chip->reg_lock);
+ if (!chip->info->ops->port_set_link)
+ return 0;
- err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+ /* Port's MAC control must not be changed unless the link is down */
+ err = chip->info->ops->port_set_link(chip, port, 0);
if (err)
- goto out;
-
- reg &= ~(PORT_PCS_CTRL_LINK_UP |
- PORT_PCS_CTRL_FORCE_LINK |
- PORT_PCS_CTRL_DUPLEX_FULL |
- PORT_PCS_CTRL_FORCE_DUPLEX |
- PORT_PCS_CTRL_UNFORCED);
-
- reg |= PORT_PCS_CTRL_FORCE_LINK;
- if (phydev->link)
- reg |= PORT_PCS_CTRL_LINK_UP;
-
- if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100)
- goto out;
+ return err;
- switch (phydev->speed) {
- case SPEED_1000:
- reg |= PORT_PCS_CTRL_1000;
- break;
- case SPEED_100:
- reg |= PORT_PCS_CTRL_100;
- break;
- case SPEED_10:
- reg |= PORT_PCS_CTRL_10;
- break;
- default:
- pr_info("Unknown speed");
- goto out;
+ if (chip->info->ops->port_set_speed) {
+ err = chip->info->ops->port_set_speed(chip, port, speed);
+ if (err && err != -EOPNOTSUPP)
+ goto restore_link;
}
- reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
- if (phydev->duplex == DUPLEX_FULL)
- reg |= PORT_PCS_CTRL_DUPLEX_FULL;
-
- if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) &&
- (port >= mv88e6xxx_num_ports(chip) - 2)) {
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
- reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
- reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
- PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
+ if (chip->info->ops->port_set_duplex) {
+ err = chip->info->ops->port_set_duplex(chip, port, duplex);
+ if (err && err != -EOPNOTSUPP)
+ goto restore_link;
}
- mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
-out:
- mutex_unlock(&chip->reg_lock);
-}
-
-static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip)
-{
- u16 val;
- int i, err;
-
- for (i = 0; i < 10; i++) {
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_OP, &val);
- if ((val & GLOBAL_STATS_OP_BUSY) == 0)
- return 0;
+ if (chip->info->ops->port_set_rgmii_delay) {
+ err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
+ if (err && err != -EOPNOTSUPP)
+ goto restore_link;
}
- return -ETIMEDOUT;
-}
-
-static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
-{
- int err;
-
- if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
- port = (port + 1) << 5;
-
- /* Snapshot the hardware statistics counters for this port. */
- err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_CAPTURE_PORT |
- GLOBAL_STATS_OP_HIST_RX_TX | port);
- if (err)
- return err;
+ err = 0;
+restore_link:
+ if (chip->info->ops->port_set_link(chip, port, link))
+ netdev_err(chip->ds->ports[port].netdev,
+ "failed to restore MAC's link\n");
- /* Wait for the snapshotting to complete. */
- return _mv88e6xxx_stats_wait(chip);
+ return err;
}
-static void _mv88e6xxx_stats_read(struct mv88e6xxx_chip *chip,
- int stat, u32 *val)
+/* We expect the switch to perform auto negotiation if there is a real
+ * phy. However, in the case of a fixed link phy, we force the port
+ * settings from the fixed link settings.
+ */
+static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
{
- u32 value;
- u16 reg;
+ struct mv88e6xxx_chip *chip = ds->priv;
int err;
- *val = 0;
-
- err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_READ_CAPTURED |
- GLOBAL_STATS_OP_HIST_RX_TX | stat);
- if (err)
- return;
-
- err = _mv88e6xxx_stats_wait(chip);
- if (err)
+ if (!phy_is_pseudo_fixed_link(phydev))
return;
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
- if (err)
- return;
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
+ phydev->duplex, phydev->interface);
+ mutex_unlock(&chip->reg_lock);
- value = reg << 16;
+ if (err && err != -EOPNOTSUPP)
+ netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
+}
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
- if (err)
- return;
+static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ if (!chip->info->ops->stats_snapshot)
+ return -EOPNOTSUPP;
- *val = value | reg;
+ return chip->info->ops->stats_snapshot(chip, port);
}
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
- { "in_good_octets", 8, 0x00, BANK0, },
- { "in_bad_octets", 4, 0x02, BANK0, },
- { "in_unicast", 4, 0x04, BANK0, },
- { "in_broadcasts", 4, 0x06, BANK0, },
- { "in_multicasts", 4, 0x07, BANK0, },
- { "in_pause", 4, 0x16, BANK0, },
- { "in_undersize", 4, 0x18, BANK0, },
- { "in_fragments", 4, 0x19, BANK0, },
- { "in_oversize", 4, 0x1a, BANK0, },
- { "in_jabber", 4, 0x1b, BANK0, },
- { "in_rx_error", 4, 0x1c, BANK0, },
- { "in_fcs_error", 4, 0x1d, BANK0, },
- { "out_octets", 8, 0x0e, BANK0, },
- { "out_unicast", 4, 0x10, BANK0, },
- { "out_broadcasts", 4, 0x13, BANK0, },
- { "out_multicasts", 4, 0x12, BANK0, },
- { "out_pause", 4, 0x15, BANK0, },
- { "excessive", 4, 0x11, BANK0, },
- { "collisions", 4, 0x1e, BANK0, },
- { "deferred", 4, 0x05, BANK0, },
- { "single", 4, 0x14, BANK0, },
- { "multiple", 4, 0x17, BANK0, },
- { "out_fcs_error", 4, 0x03, BANK0, },
- { "late", 4, 0x1f, BANK0, },
- { "hist_64bytes", 4, 0x08, BANK0, },
- { "hist_65_127bytes", 4, 0x09, BANK0, },
- { "hist_128_255bytes", 4, 0x0a, BANK0, },
- { "hist_256_511bytes", 4, 0x0b, BANK0, },
- { "hist_512_1023bytes", 4, 0x0c, BANK0, },
- { "hist_1024_max_bytes", 4, 0x0d, BANK0, },
- { "sw_in_discards", 4, 0x10, PORT, },
- { "sw_in_filtered", 2, 0x12, PORT, },
- { "sw_out_filtered", 2, 0x13, PORT, },
- { "in_discards", 4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_filtered", 4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_accepted", 4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_accepted", 4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_0", 4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_1", 4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_2", 4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_3", 4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_da_unknown", 4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_management", 4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_0", 4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_1", 4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_2", 4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_3", 4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_4", 4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_5", 4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_6", 4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_7", 4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_cut_through", 4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_a", 4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_b", 4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
+ { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
+ { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
+ { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
+ { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
+ { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
+ { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
+ { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
+ { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
+ { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
+ { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
+ { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
+ { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
+ { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
+ { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
+ { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
+ { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
+ { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
+ { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
+ { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
+ { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
+ { "single", 4, 0x14, STATS_TYPE_BANK0, },
+ { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
+ { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
+ { "late", 4, 0x1f, STATS_TYPE_BANK0, },
+ { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
+ { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
+ { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
+ { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
+ { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
+ { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
+ { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
+ { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
+ { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
+ { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
+ { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
+ { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
+ { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
+ { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
+ { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
+ { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
+ { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
+ { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
+ { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
+ { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
+ { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
+ { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
+ { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
+ { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
+ { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
+ { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
+ { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
+ { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
+ { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
+ { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
+ { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
+ { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
+ { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
+ { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
+ { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
};
-static bool mv88e6xxx_has_stat(struct mv88e6xxx_chip *chip,
- struct mv88e6xxx_hw_stat *stat)
-{
- switch (stat->type) {
- case BANK0:
- return true;
- case BANK1:
- return mv88e6xxx_6320_family(chip);
- case PORT:
- return mv88e6xxx_6095_family(chip) ||
- mv88e6xxx_6185_family(chip) ||
- mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6165_family(chip) ||
- mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6352_family(chip);
- }
- return false;
-}
-
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_hw_stat *s,
- int port)
+ int port, u16 bank1_select,
+ u16 histogram)
{
u32 low;
u32 high = 0;
+ u16 reg = 0;
int err;
- u16 reg;
u64 value;
switch (s->type) {
- case PORT:
+ case STATS_TYPE_PORT:
err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
if (err)
return UINT64_MAX;
@@ -792,26 +832,28 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
high = reg;
}
break;
- case BANK0:
- case BANK1:
- _mv88e6xxx_stats_read(chip, s->reg, &low);
+ case STATS_TYPE_BANK1:
+ reg = bank1_select;
+ /* fall through */
+ case STATS_TYPE_BANK0:
+ reg |= s->reg | histogram;
+ mv88e6xxx_g1_stats_read(chip, reg, &low);
if (s->sizeof_stat == 8)
- _mv88e6xxx_stats_read(chip, s->reg + 1, &high);
+ mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
}
value = (((u64)high) << 16) | low;
return value;
}
-static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
- uint8_t *data)
+static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data, int types)
{
- struct mv88e6xxx_chip *chip = ds->priv;
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat)) {
+ if (stat->type & types) {
memcpy(data + j * ETH_GSTRING_LEN, stat->string,
ETH_GSTRING_LEN);
j++;
@@ -819,46 +861,142 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
}
}
-static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
+{
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT);
+}
+
+static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
+{
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
+}
+
+static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
+ uint8_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (chip->info->ops->stats_get_strings)
+ chip->info->ops->stats_get_strings(chip, data);
+}
+
+static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
+ int types)
+{
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat))
+ if (stat->type & types)
j++;
}
return j;
}
+static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+ STATS_TYPE_PORT);
+}
+
+static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+ STATS_TYPE_BANK1);
+}
+
+static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (chip->info->ops->stats_get_sset_count)
+ return chip->info->ops->stats_get_sset_count(chip);
+
+ return 0;
+}
+
+static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data, int types,
+ u16 bank1_select, u16 histogram)
+{
+ struct mv88e6xxx_hw_stat *stat;
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
+ stat = &mv88e6xxx_hw_stats[i];
+ if (stat->type & types) {
+ data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
+ bank1_select,
+ histogram);
+ j++;
+ }
+ }
+}
+
+static void mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT,
+ 0, GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+ GLOBAL_STATS_OP_BANK_1_BIT_9,
+ GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+ GLOBAL_STATS_OP_BANK_1_BIT_10, 0);
+}
+
+static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ if (chip->info->ops->stats_get_stats)
+ chip->info->ops->stats_get_stats(chip, port, data);
+}
+
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
- struct mv88e6xxx_hw_stat *stat;
int ret;
- int i, j;
mutex_lock(&chip->reg_lock);
- ret = _mv88e6xxx_stats_snapshot(chip, port);
+ ret = mv88e6xxx_stats_snapshot(chip, port);
if (ret < 0) {
mutex_unlock(&chip->reg_lock);
return;
}
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
- stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat)) {
- data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port);
- j++;
- }
- }
+
+ mv88e6xxx_get_stats(chip, port, data);
mutex_unlock(&chip->reg_lock);
}
+static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+ if (chip->info->ops->stats_set_histogram)
+ return chip->info->ops->stats_set_histogram(chip);
+
+ return 0;
+}
+
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
return 32 * sizeof(u16);
@@ -1069,54 +1207,16 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid,
return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too);
}
-static const char * const mv88e6xxx_port_state_names[] = {
- [PORT_CONTROL_STATE_DISABLED] = "Disabled",
- [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
- [PORT_CONTROL_STATE_LEARNING] = "Learning",
- [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
-};
-
-static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port,
- u8 state)
-{
- struct dsa_switch *ds = chip->ds;
- u16 reg;
- int err;
- u8 oldstate;
-
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
- if (err)
- return err;
-
- oldstate = reg & PORT_CONTROL_STATE_MASK;
-
- reg &= ~PORT_CONTROL_STATE_MASK;
- reg |= state;
-
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
- if (err)
- return err;
-
- netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n",
- mv88e6xxx_port_state_names[state],
- mv88e6xxx_port_state_names[oldstate]);
-
- return 0;
-}
-
static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
{
struct net_device *bridge = chip->ports[port].bridge_dev;
- const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1;
struct dsa_switch *ds = chip->ds;
u16 output_ports = 0;
- u16 reg;
- int err;
int i;
/* allow CPU port or DSA link(s) to send frames to every port */
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
- output_ports = mask;
+ output_ports = ~0;
} else {
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
/* allow sending frames to every group member */
@@ -1132,14 +1232,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
/* prevent frames from going back out of the port they came in on */
output_ports &= ~BIT(port);
- err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
- if (err)
- return err;
-
- reg &= ~mask;
- reg |= output_ports & mask;
-
- return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+ return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
}
static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
@@ -1167,13 +1260,11 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
}
mutex_lock(&chip->reg_lock);
- err = _mv88e6xxx_port_state(chip, port, stp_state);
+ err = mv88e6xxx_port_set_state(chip, port, stp_state);
mutex_unlock(&chip->reg_lock);
if (err)
- netdev_err(ds->ports[port].netdev,
- "failed to update state to %s\n",
- mv88e6xxx_port_state_names[stp_state]);
+ netdev_err(ds->ports[port].netdev, "failed to update state\n");
}
static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
@@ -1189,49 +1280,6 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
}
-static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port,
- u16 *new, u16 *old)
-{
- struct dsa_switch *ds = chip->ds;
- u16 pvid, reg;
- int err;
-
- err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
- if (err)
- return err;
-
- pvid = reg & PORT_DEFAULT_VLAN_MASK;
-
- if (new) {
- reg &= ~PORT_DEFAULT_VLAN_MASK;
- reg |= *new & PORT_DEFAULT_VLAN_MASK;
-
- err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
- if (err)
- return err;
-
- netdev_dbg(ds->ports[port].netdev,
- "DefaultVID %d (was %d)\n", *new, pvid);
- }
-
- if (old)
- *old = pvid;
-
- return 0;
-}
-
-static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip,
- int port, u16 *pvid)
-{
- return _mv88e6xxx_port_pvid(chip, port, NULL, pvid);
-}
-
-static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip,
- int port, u16 pvid)
-{
- return _mv88e6xxx_port_pvid(chip, port, &pvid, NULL);
-}
-
static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY);
@@ -1411,7 +1459,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
mutex_lock(&chip->reg_lock);
- err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
+ err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
if (err)
goto unlock;
@@ -1575,75 +1623,6 @@ loadpurge:
return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
}
-static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port,
- u16 *new, u16 *old)
-{
- struct dsa_switch *ds = chip->ds;
- u16 upper_mask;
- u16 fid;
- u16 reg;
- int err;
-
- if (mv88e6xxx_num_databases(chip) == 4096)
- upper_mask = 0xff;
- else if (mv88e6xxx_num_databases(chip) == 256)
- upper_mask = 0xf;
- else
- return -EOPNOTSUPP;
-
- /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
- err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
- if (err)
- return err;
-
- fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
-
- if (new) {
- reg &= ~PORT_BASE_VLAN_FID_3_0_MASK;
- reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
-
- err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
- if (err)
- return err;
- }
-
- /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
- if (err)
- return err;
-
- fid |= (reg & upper_mask) << 4;
-
- if (new) {
- reg &= ~upper_mask;
- reg |= (*new >> 4) & upper_mask;
-
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
- if (err)
- return err;
-
- netdev_dbg(ds->ports[port].netdev,
- "FID %d (was %d)\n", *new, fid);
- }
-
- if (old)
- *old = fid;
-
- return 0;
-}
-
-static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip,
- int port, u16 *fid)
-{
- return _mv88e6xxx_port_fid(chip, port, NULL, fid);
-}
-
-static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip,
- int port, u16 fid)
-{
- return _mv88e6xxx_port_fid(chip, port, &fid, NULL);
-}
-
static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
{
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
@@ -1654,7 +1633,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
/* Set every FID bit used by the (un)bridged ports */
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
- err = _mv88e6xxx_port_fid_get(chip, i, fid);
+ err = mv88e6xxx_port_get_fid(chip, i, fid);
if (err)
return err;
@@ -1819,48 +1798,19 @@ unlock:
return err;
}
-static const char * const mv88e6xxx_port_8021q_mode_names[] = {
- [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
- [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
- [PORT_CONTROL_2_8021Q_CHECK] = "Check",
- [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
-};
-
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering)
{
struct mv88e6xxx_chip *chip = ds->priv;
- u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
+ u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
PORT_CONTROL_2_8021Q_DISABLED;
- u16 reg;
int err;
if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
return -EOPNOTSUPP;
mutex_lock(&chip->reg_lock);
-
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
- if (err)
- goto unlock;
-
- old = reg & PORT_CONTROL_2_8021Q_MASK;
-
- if (new != old) {
- reg &= ~PORT_CONTROL_2_8021Q_MASK;
- reg |= new & PORT_CONTROL_2_8021Q_MASK;
-
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
- if (err)
- goto unlock;
-
- netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n",
- mv88e6xxx_port_8021q_mode_names[new],
- mv88e6xxx_port_8021q_mode_names[old]);
- }
-
- err = 0;
-unlock:
+ err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
mutex_unlock(&chip->reg_lock);
return err;
@@ -1928,7 +1878,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
"failed to add VLAN %d%c\n",
vid, untagged ? 'u' : 't');
- if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end))
+ if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n",
vlan->vid_end);
@@ -1983,7 +1933,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
mutex_lock(&chip->reg_lock);
- err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
+ err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
if (err)
goto unlock;
@@ -1993,7 +1943,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
goto unlock;
if (vid == pvid) {
- err = _mv88e6xxx_port_pvid_set(chip, port, 0);
+ err = mv88e6xxx_port_set_pvid(chip, port, 0);
if (err)
goto unlock;
}
@@ -2104,7 +2054,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
/* Null VLAN ID corresponds to the port private database */
if (vid == 0)
- err = _mv88e6xxx_port_fid_get(chip, port, &vlan.fid);
+ err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
else
err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false);
if (err)
@@ -2280,7 +2230,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
int err;
/* Dump port's default Filtering Information Database (VLAN ID 0) */
- err = _mv88e6xxx_port_fid_get(chip, port, &fid);
+ err = mv88e6xxx_port_get_fid(chip, port, &fid);
if (err)
return err;
@@ -2368,67 +2318,58 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
mutex_unlock(&chip->reg_lock);
}
-static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
+static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
{
- bool ppu_active = mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE);
- u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
- struct gpio_desc *gpiod = chip->reset;
- unsigned long timeout;
- u16 reg;
- int err;
- int i;
+ if (chip->info->ops->reset)
+ return chip->info->ops->reset(chip);
- /* Set all ports to the disabled state. */
- for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
- err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, &reg);
- if (err)
- return err;
-
- err = mv88e6xxx_port_write(chip, i, PORT_CONTROL,
- reg & 0xfffc);
- if (err)
- return err;
- }
+ return 0;
+}
- /* Wait for transmit queues to drain. */
- usleep_range(2000, 4000);
+static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
+{
+ struct gpio_desc *gpiod = chip->reset;
- /* If there is a gpio connected to the reset pin, toggle it */
+ /* If there is a GPIO connected to the reset pin, toggle it */
if (gpiod) {
gpiod_set_value_cansleep(gpiod, 1);
usleep_range(10000, 20000);
gpiod_set_value_cansleep(gpiod, 0);
usleep_range(10000, 20000);
}
+}
- /* Reset the switch. Keep the PPU active if requested. The PPU
- * needs to be active to support indirect phy register access
- * through global registers 0x18 and 0x19.
- */
- if (ppu_active)
- err = mv88e6xxx_g1_write(chip, 0x04, 0xc000);
- else
- err = mv88e6xxx_g1_write(chip, 0x04, 0xc400);
- if (err)
- return err;
+static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
+{
+ int i, err;
- /* Wait up to one second for reset to complete. */
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- err = mv88e6xxx_g1_read(chip, 0x00, &reg);
+ /* Set all ports to the Disabled state */
+ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
+ err = mv88e6xxx_port_set_state(chip, i,
+ PORT_CONTROL_STATE_DISABLED);
if (err)
return err;
-
- if ((reg & is_reset) == is_reset)
- break;
- usleep_range(1000, 2000);
}
- if (time_after(jiffies, timeout))
- err = -ETIMEDOUT;
- else
- err = 0;
- return err;
+ /* Wait for transmit queues to drain,
+ * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
+ */
+ usleep_range(2000, 4000);
+
+ return 0;
+}
+
+static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
+{
+ int err;
+
+ err = mv88e6xxx_disable_ports(chip);
+ if (err)
+ return err;
+
+ mv88e6xxx_hardware_reset(chip);
+
+ return mv88e6xxx_software_reset(chip);
}
static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip)
@@ -2449,42 +2390,93 @@ static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip)
return err;
}
-static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
+static int mv88e6xxx_setup_port_dsa(struct mv88e6xxx_chip *chip, int port,
+ int upstream_port)
{
- struct dsa_switch *ds = chip->ds;
int err;
- u16 reg;
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip) ||
- mv88e6xxx_6065_family(chip) || mv88e6xxx_6320_family(chip)) {
- /* MAC Forcing register: don't force link, speed,
- * duplex or flow control state to any particular
- * values on physical ports, but force the CPU port
- * and all DSA ports to their maximum bandwidth and
- * full duplex.
- */
- err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
- if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
- reg &= ~PORT_PCS_CTRL_UNFORCED;
- reg |= PORT_PCS_CTRL_FORCE_LINK |
- PORT_PCS_CTRL_LINK_UP |
- PORT_PCS_CTRL_DUPLEX_FULL |
- PORT_PCS_CTRL_FORCE_DUPLEX;
- if (mv88e6xxx_6065_family(chip))
- reg |= PORT_PCS_CTRL_100;
- else
- reg |= PORT_PCS_CTRL_1000;
- } else {
- reg |= PORT_PCS_CTRL_UNFORCED;
- }
+ err = chip->info->ops->port_set_frame_mode(
+ chip, port, MV88E6XXX_FRAME_MODE_DSA);
+ if (err)
+ return err;
+
+ return chip->info->ops->port_set_egress_unknowns(
+ chip, port, port == upstream_port);
+}
+
+static int mv88e6xxx_setup_port_cpu(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ switch (chip->info->tag_protocol) {
+ case DSA_TAG_PROTO_EDSA:
+ err = chip->info->ops->port_set_frame_mode(
+ chip, port, MV88E6XXX_FRAME_MODE_ETHERTYPE);
+ if (err)
+ return err;
- err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+ err = mv88e6xxx_port_set_egress_mode(
+ chip, port, PORT_CONTROL_EGRESS_ADD_TAG);
if (err)
return err;
+
+ if (chip->info->ops->port_set_ether_type)
+ err = chip->info->ops->port_set_ether_type(
+ chip, port, ETH_P_EDSA);
+ break;
+
+ case DSA_TAG_PROTO_DSA:
+ err = chip->info->ops->port_set_frame_mode(
+ chip, port, MV88E6XXX_FRAME_MODE_DSA);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_set_egress_mode(
+ chip, port, PORT_CONTROL_EGRESS_UNMODIFIED);
+ break;
+ default:
+ err = -EINVAL;
}
+ if (err)
+ return err;
+
+ return chip->info->ops->port_set_egress_unknowns(chip, port, true);
+}
+
+static int mv88e6xxx_setup_port_normal(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ err = chip->info->ops->port_set_frame_mode(
+ chip, port, MV88E6XXX_FRAME_MODE_NORMAL);
+ if (err)
+ return err;
+
+ return chip->info->ops->port_set_egress_unknowns(chip, port, false);
+}
+
+static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
+{
+ struct dsa_switch *ds = chip->ds;
+ int err;
+ u16 reg;
+
+ /* MAC Forcing register: don't force link, speed, duplex or flow control
+ * state to any particular values on physical ports, but force the CPU
+ * port and all DSA ports to their maximum bandwidth and full duplex.
+ */
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+ err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
+ SPEED_MAX, DUPLEX_FULL,
+ PHY_INTERFACE_MODE_NA);
+ else
+ err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
+ SPEED_UNFORCED, DUPLEX_UNFORCED,
+ PHY_INTERFACE_MODE_NA);
+ if (err)
+ return err;
+
/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
* disable Header mode, enable IGMP/MLD snooping, disable VLAN
* tunneling, determine priority by looking at 802.1p and IP
@@ -2499,44 +2491,23 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
* If this is the upstream port for this switch, enable
* forwarding of unknown unicasts and multicasts.
*/
- reg = 0;
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6095_family(chip) || mv88e6xxx_6065_family(chip) ||
- mv88e6xxx_6185_family(chip) || mv88e6xxx_6320_family(chip))
- reg = PORT_CONTROL_IGMP_MLD_SNOOP |
+ reg = PORT_CONTROL_IGMP_MLD_SNOOP |
PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
PORT_CONTROL_STATE_FORWARDING;
- if (dsa_is_cpu_port(ds, port)) {
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA))
- reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA |
- PORT_CONTROL_FORWARD_UNKNOWN_MC;
- else
- reg |= PORT_CONTROL_DSA_TAG;
- reg |= PORT_CONTROL_EGRESS_ADD_TAG |
- PORT_CONTROL_FORWARD_UNKNOWN;
- }
- if (dsa_is_dsa_port(ds, port)) {
- if (mv88e6xxx_6095_family(chip) ||
- mv88e6xxx_6185_family(chip))
- reg |= PORT_CONTROL_DSA_TAG;
- if (mv88e6xxx_6352_family(chip) ||
- mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) ||
- mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6320_family(chip)) {
- reg |= PORT_CONTROL_FRAME_MODE_DSA;
- }
+ err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+ if (err)
+ return err;
- if (port == dsa_upstream_port(ds))
- reg |= PORT_CONTROL_FORWARD_UNKNOWN |
- PORT_CONTROL_FORWARD_UNKNOWN_MC;
- }
- if (reg) {
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
- if (err)
- return err;
+ if (dsa_is_cpu_port(ds, port)) {
+ err = mv88e6xxx_setup_port_cpu(chip, port);
+ } else if (dsa_is_dsa_port(ds, port)) {
+ err = mv88e6xxx_setup_port_dsa(chip, port,
+ dsa_upstream_port(ds));
+ } else {
+ err = mv88e6xxx_setup_port_normal(chip, port);
}
+ if (err)
+ return err;
/* If this port is connected to a SerDes, make sure the SerDes is not
* powered down.
@@ -2568,10 +2539,6 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
mv88e6xxx_6185_family(chip))
reg = PORT_CONTROL_2_MAP_DA;
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6320_family(chip))
- reg |= PORT_CONTROL_2_JUMBO_10240;
-
if (mv88e6xxx_6095_family(chip) || mv88e6xxx_6185_family(chip)) {
/* Set the upstream port this port should use */
reg |= dsa_upstream_port(ds);
@@ -2590,6 +2557,12 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return err;
}
+ if (chip->info->ops->port_jumbo_config) {
+ err = chip->info->ops->port_jumbo_config(chip, port);
+ if (err)
+ return err;
+ }
+
/* 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
@@ -2609,17 +2582,15 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
if (err)
return err;
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6320_family(chip)) {
- /* Do not limit the period of time that this port can
- * be paused for by the remote end or the period of
- * time that this port can pause the remote end.
- */
- err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
+ if (chip->info->ops->port_pause_config) {
+ err = chip->info->ops->port_pause_config(chip, port);
if (err)
return err;
+ }
+ if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
+ mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
+ mv88e6xxx_6320_family(chip)) {
/* Port ATU control: disable limiting the number of
* address database entries that this port is allowed
* to use.
@@ -2633,45 +2604,16 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
0x0000);
if (err)
return err;
+ }
- /* Port Ethertype: use the Ethertype DSA Ethertype
- * value.
- */
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA)) {
- err = mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE,
- ETH_P_EDSA);
- if (err)
- return err;
- }
-
- /* Tag Remap: use an identity 802.1p prio -> switch
- * prio mapping.
- */
- err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123,
- 0x3210);
- if (err)
- return err;
-
- /* Tag Remap 2: use an identity 802.1p prio -> switch
- * prio mapping.
- */
- err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567,
- 0x7654);
+ if (chip->info->ops->port_tag_remap) {
+ err = chip->info->ops->port_tag_remap(chip, port);
if (err)
return err;
}
- /* Rate Control: disable ingress rate limiting. */
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6320_family(chip)) {
- err = mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL,
- 0x0001);
- if (err)
- return err;
- } else if (mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip)) {
- err = mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL,
- 0x0000);
+ if (chip->info->ops->port_egress_rate_limiting) {
+ err = chip->info->ops->port_egress_rate_limiting(chip, port);
if (err)
return err;
}
@@ -2687,7 +2629,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
* database, and allow bidirectional communication between the
* CPU and DSA port(s), and the other ports.
*/
- err = _mv88e6xxx_port_fid_set(chip, port, 0);
+ err = mv88e6xxx_port_set_fid(chip, port, 0);
if (err)
return err;
@@ -2701,7 +2643,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000);
}
-int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
+static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
{
int err;
@@ -2764,30 +2706,26 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
{
struct dsa_switch *ds = chip->ds;
u32 upstream_port = dsa_upstream_port(ds);
- u16 reg;
int err;
/* Enable the PHY Polling Unit if present, don't discard any packets,
* and mask all interrupt sources.
*/
- reg = 0;
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU) ||
- mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE))
- reg |= GLOBAL_CONTROL_PPU_ENABLE;
-
- err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+ err = mv88e6xxx_ppu_enable(chip);
if (err)
return err;
- /* Configure the upstream port, and configure it as the port to which
- * ingress and egress and ARP monitor frames are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- err = mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
- if (err)
- return err;
+ if (chip->info->ops->g1_set_cpu_port) {
+ err = chip->info->ops->g1_set_cpu_port(chip, upstream_port);
+ if (err)
+ return err;
+ }
+
+ if (chip->info->ops->g1_set_egress_port) {
+ err = chip->info->ops->g1_set_egress_port(chip, upstream_port);
+ if (err)
+ return err;
+ }
/* Disable remote management, and set the switch's DSA device number. */
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2,
@@ -2850,6 +2788,11 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
if (err)
return err;
+ /* Initialize the statistics unit */
+ err = mv88e6xxx_stats_set_histogram(chip);
+ if (err)
+ return err;
+
/* Clear the statistics counters for all ports */
err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_FLUSH_ALL);
@@ -2857,7 +2800,7 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
return err;
/* Wait for the flush to complete. */
- err = _mv88e6xxx_stats_wait(chip);
+ err = mv88e6xxx_g1_stats_wait(chip);
if (err)
return err;
@@ -2875,10 +2818,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
mutex_lock(&chip->reg_lock);
- err = mv88e6xxx_switch_reset(chip);
- if (err)
- goto unlock;
-
/* Setup Switch Port Registers */
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
err = mv88e6xxx_setup_port(chip, i);
@@ -2898,6 +2837,17 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
goto unlock;
}
+ /* Some generations have the configuration of sending reserved
+ * management frames to the CPU in global2, others in
+ * global1. Hence it does not fit the two setup functions
+ * above.
+ */
+ if (chip->info->ops->mgmt_rsvd2cpu) {
+ err = chip->info->ops->mgmt_rsvd2cpu(chip);
+ if (err)
+ goto unlock;
+ }
+
unlock:
mutex_unlock(&chip->reg_lock);
@@ -3203,119 +3153,653 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
}
static const struct mv88e6xxx_ops mv88e6085_ops = {
+ /* MV88E6XXX_FAMILY_6097 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .ppu_enable = mv88e6185_g1_ppu_enable,
+ .ppu_disable = mv88e6185_g1_ppu_disable,
+ .reset = mv88e6185_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6095_ops = {
+ /* MV88E6XXX_FAMILY_6095 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_set_frame_mode = mv88e6085_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .ppu_enable = mv88e6185_g1_ppu_enable,
+ .ppu_disable = mv88e6185_g1_ppu_disable,
+ .reset = mv88e6185_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6097_ops = {
+ /* MV88E6XXX_FAMILY_6097 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6123_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_set_frame_mode = mv88e6085_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6131_ops = {
+ /* MV88E6XXX_FAMILY_6185 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .ppu_enable = mv88e6185_g1_ppu_enable,
+ .ppu_disable = mv88e6185_g1_ppu_disable,
+ .reset = mv88e6185_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6161_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6165_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6171_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6172_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6352_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6175_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6176_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6352_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6185_ops = {
+ /* MV88E6XXX_FAMILY_6185 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_set_frame_mode = mv88e6085_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+ .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .ppu_enable = mv88e6185_g1_ppu_enable,
+ .ppu_disable = mv88e6185_g1_ppu_disable,
+ .reset = mv88e6185_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6190_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6190x_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390x_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6191_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6240_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6352_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6290_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6320_ops = {
+ /* MV88E6XXX_FAMILY_6320 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6320_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6321_ops = {
+ /* MV88E6XXX_FAMILY_6321 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6320_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6350_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6351_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6185_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
static const struct mv88e6xxx_ops mv88e6352_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+ .port_set_speed = mv88e6352_port_set_speed,
+ .port_tag_remap = mv88e6095_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6097_port_pause_config,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+ .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6390_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
};
+static const struct mv88e6xxx_ops mv88e6390x_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390x_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_jumbo_config = mv88e6165_port_jumbo_config,
+ .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6391_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .port_tag_remap = mv88e6390_port_tag_remap,
+ .port_set_frame_mode = mv88e6351_port_set_frame_mode,
+ .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+ .port_set_ether_type = mv88e6351_port_set_ether_type,
+ .port_pause_config = mv88e6390_port_pause_config,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+ .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+ .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .reset = mv88e6352_g1_reset,
+};
+
+static int mv88e6xxx_verify_madatory_ops(struct mv88e6xxx_chip *chip,
+ const struct mv88e6xxx_ops *ops)
+{
+ if (!ops->port_set_frame_mode) {
+ dev_err(chip->dev, "Missing port_set_frame_mode");
+ return -EINVAL;
+ }
+
+ if (!ops->port_set_egress_unknowns) {
+ dev_err(chip->dev, "Missing port_set_egress_mode");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
[MV88E6085] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
@@ -3326,6 +3810,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6097,
.ops = &mv88e6085_ops,
},
@@ -3339,10 +3825,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6095,
.ops = &mv88e6095_ops,
},
+ [MV88E6097] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6097,
+ .family = MV88E6XXX_FAMILY_6097,
+ .name = "Marvell 88E6097/88E6097F",
+ .num_databases = 4096,
+ .num_ports = 11,
+ .port_base_addr = 0x10,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6097,
+ .ops = &mv88e6097_ops,
+ },
+
[MV88E6123] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
.family = MV88E6XXX_FAMILY_6165,
@@ -3352,6 +3855,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6123_ops,
},
@@ -3365,6 +3870,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6185,
.ops = &mv88e6131_ops,
},
@@ -3378,6 +3885,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6161_ops,
},
@@ -3391,6 +3900,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6165,
.ops = &mv88e6165_ops,
},
@@ -3404,6 +3915,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6171_ops,
},
@@ -3417,6 +3930,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6172_ops,
},
@@ -3430,6 +3945,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6175_ops,
},
@@ -3443,6 +3960,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6176_ops,
},
@@ -3456,10 +3975,57 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6185,
.ops = &mv88e6185_ops,
},
+ [MV88E6190] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6190,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6190",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6190_ops,
+ },
+
+ [MV88E6190X] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6190X,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6190X",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6190x_ops,
+ },
+
+ [MV88E6191] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6191,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6191",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6391_ops,
+ },
+
[MV88E6240] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
.family = MV88E6XXX_FAMILY_6352,
@@ -3469,10 +4035,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6240_ops,
},
+ [MV88E6290] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6290,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6290",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6290_ops,
+ },
+
[MV88E6320] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
.family = MV88E6XXX_FAMILY_6320,
@@ -3482,6 +4065,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6320,
.ops = &mv88e6320_ops,
},
@@ -3495,6 +4080,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 8,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6320,
.ops = &mv88e6321_ops,
},
@@ -3508,6 +4095,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6350_ops,
},
@@ -3521,6 +4110,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6351,
.ops = &mv88e6351_ops,
},
@@ -3534,9 +4125,39 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.port_base_addr = 0x10,
.global1_addr = 0x1b,
.age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6352_ops,
},
+ [MV88E6390] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6390,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6390",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6390_ops,
+ },
+ [MV88E6390X] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6390X,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6390X",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6390x_ops,
+ },
};
static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
@@ -3600,13 +4221,13 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
static void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip)
{
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
+ if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
mv88e6xxx_ppu_state_init(chip);
}
static void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip)
{
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
+ if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
mv88e6xxx_ppu_state_destroy(chip);
}
@@ -3634,10 +4255,7 @@ static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds)
{
struct mv88e6xxx_chip *chip = ds->priv;
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA))
- return DSA_TAG_PROTO_EDSA;
-
- return DSA_TAG_PROTO_DSA;
+ return chip->info->tag_protocol;
}
static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
@@ -3667,6 +4285,12 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
if (err)
goto free;
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_switch_reset(chip);
+ mutex_unlock(&chip->reg_lock);
+ if (err)
+ goto free;
+
mv88e6xxx_phy_init(chip);
err = mv88e6xxx_mdio_register(chip, NULL);
@@ -3819,35 +4443,82 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
chip->info = compat_info;
+ err = mv88e6xxx_verify_madatory_ops(chip, chip->info->ops);
+ if (err)
+ return err;
+
err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
if (err)
return err;
+ chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(chip->reset))
+ return PTR_ERR(chip->reset);
+
err = mv88e6xxx_detect(chip);
if (err)
return err;
mv88e6xxx_phy_init(chip);
- chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
- if (IS_ERR(chip->reset))
- return PTR_ERR(chip->reset);
-
if (chip->info->ops->get_eeprom &&
!of_property_read_u32(np, "eeprom-length", &eeprom_len))
chip->eeprom_len = eeprom_len;
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_switch_reset(chip);
+ mutex_unlock(&chip->reg_lock);
+ if (err)
+ goto out;
+
+ chip->irq = of_irq_get(np, 0);
+ if (chip->irq == -EPROBE_DEFER) {
+ err = chip->irq;
+ goto out;
+ }
+
+ if (chip->irq > 0) {
+ /* Has to be performed before the MDIO bus is created,
+ * because the PHYs will link there interrupts to these
+ * interrupt controllers
+ */
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_irq_setup(chip);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err)
+ goto out;
+
+ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) {
+ err = mv88e6xxx_g2_irq_setup(chip);
+ if (err)
+ goto out_g1_irq;
+ }
+ }
+
err = mv88e6xxx_mdio_register(chip, np);
if (err)
- return err;
+ goto out_g2_irq;
err = mv88e6xxx_register_switch(chip, np);
- if (err) {
- mv88e6xxx_mdio_unregister(chip);
- return err;
- }
+ if (err)
+ goto out_mdio;
return 0;
+
+out_mdio:
+ mv88e6xxx_mdio_unregister(chip);
+out_g2_irq:
+ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
+ mv88e6xxx_g2_irq_free(chip);
+out_g1_irq:
+ if (chip->irq > 0) {
+ mutex_lock(&chip->reg_lock);
+ mv88e6xxx_g1_irq_free(chip);
+ mutex_unlock(&chip->reg_lock);
+ }
+out:
+ return err;
}
static void mv88e6xxx_remove(struct mdio_device *mdiodev)
@@ -3858,6 +4529,12 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
mv88e6xxx_phy_destroy(chip);
mv88e6xxx_unregister_switch(chip);
mv88e6xxx_mdio_unregister(chip);
+
+ if (chip->irq > 0) {
+ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
+ mv88e6xxx_g2_irq_free(chip);
+ mv88e6xxx_g1_irq_free(chip);
+ }
}
static const struct of_device_id mv88e6xxx_of_match[] = {
@@ -3865,6 +4542,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
.compatible = "marvell,mv88e6085",
.data = &mv88e6xxx_table[MV88E6085],
},
+ {
+ .compatible = "marvell,mv88e6190",
+ .data = &mv88e6xxx_table[MV88E6190],
+ },
{ /* sentinel */ },
};
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index d358720b6c2d..75af86a7fad8 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -32,3 +32,370 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
{
return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}
+
+/* Offset 0x00: Switch Global Status Register */
+
+static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
+{
+ u16 state;
+ int i, err;
+
+ for (i = 0; i < 16; i++) {
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+ if (err)
+ return err;
+
+ /* Check the value of the PPUState bits 15:14 */
+ state &= GLOBAL_STATUS_PPU_STATE_MASK;
+ if (state != GLOBAL_STATUS_PPU_STATE_POLLING)
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
+{
+ u16 state;
+ int i, err;
+
+ for (i = 0; i < 16; ++i) {
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+ if (err)
+ return err;
+
+ /* Check the value of the PPUState bits 15:14 */
+ state &= GLOBAL_STATUS_PPU_STATE_MASK;
+ if (state == GLOBAL_STATUS_PPU_STATE_POLLING)
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
+{
+ u16 state;
+ int i, err;
+
+ for (i = 0; i < 16; ++i) {
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+ if (err)
+ return err;
+
+ /* Check the value of the PPUState (or InitState) bit 15 */
+ if (state & GLOBAL_STATUS_PPU_STATE)
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
+{
+ const unsigned long timeout = jiffies + 1 * HZ;
+ u16 val;
+ int err;
+
+ /* Wait up to 1 second for the switch to be ready. The InitReady bit 11
+ * is set to a one when all units inside the device (ATU, VTU, etc.)
+ * have finished their initialization and are ready to accept frames.
+ */
+ while (time_before(jiffies, timeout)) {
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
+ if (err)
+ return err;
+
+ if (val & GLOBAL_STATUS_INIT_READY)
+ break;
+
+ usleep_range(1000, 2000);
+ }
+
+ if (time_after(jiffies, timeout))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/* Offset 0x04: Switch Global Control Register */
+
+int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
+ * the PPU, including re-doing PHY detection and initialization
+ */
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+ if (err)
+ return err;
+
+ val |= GLOBAL_CONTROL_SW_RESET;
+ val |= GLOBAL_CONTROL_PPU_ENABLE;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_g1_wait_init_ready(chip);
+ if (err)
+ return err;
+
+ return mv88e6185_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ /* Set the SWReset bit 15 */
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+ if (err)
+ return err;
+
+ val |= GLOBAL_CONTROL_SW_RESET;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_g1_wait_init_ready(chip);
+ if (err)
+ return err;
+
+ return mv88e6352_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+ if (err)
+ return err;
+
+ val |= GLOBAL_CONTROL_PPU_ENABLE;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+ if (err)
+ return err;
+
+ return mv88e6185_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+ if (err)
+ return err;
+
+ val &= ~GLOBAL_CONTROL_PPU_ENABLE;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+ if (err)
+ return err;
+
+ return mv88e6185_g1_wait_ppu_disabled(chip);
+}
+
+/* Offset 0x1a: Monitor Control */
+/* Offset 0x1a: Monitor & MGMT Control on some devices */
+
+int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
+ GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
+
+ reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+ port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
+
+ return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+/* Older generations also call this the ARP destination. It has been
+ * generalized in more modern devices such that more than ARP can
+ * egress it
+ */
+int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
+ reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+
+ return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
+ u16 pointer, u8 data)
+{
+ u16 reg;
+
+ reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
+
+ return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
+ port);
+ if (err)
+ return err;
+
+ return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
+ port);
+}
+
+int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
+{
+ return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
+ port);
+}
+
+int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ int err;
+
+ /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
+ err = mv88e6390_g1_monitor_write(
+ chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff);
+ if (err)
+ return err;
+
+ /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
+ err = mv88e6390_g1_monitor_write(
+ chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff);
+ if (err)
+ return err;
+
+ /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
+ err = mv88e6390_g1_monitor_write(
+ chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff);
+ if (err)
+ return err;
+
+ /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
+ return mv88e6390_g1_monitor_write(
+ chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff);
+}
+
+/* Offset 0x1c: Global Control 2 */
+
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
+ if (err)
+ return err;
+
+ val |= GLOBAL_CONTROL_2_HIST_RX_TX;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
+
+ return err;
+}
+
+/* Offset 0x1d: Statistics Operation 2 */
+
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
+}
+
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ /* Snapshot the hardware statistics counters for this port. */
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_CAPTURE_PORT |
+ GLOBAL_STATS_OP_HIST_RX_TX | port);
+ if (err)
+ return err;
+
+ /* Wait for the snapshotting to complete. */
+ return mv88e6xxx_g1_stats_wait(chip);
+}
+
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ port = (port + 1) << 5;
+
+ return mv88e6xxx_g1_stats_snapshot(chip, port);
+}
+
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ port = (port + 1) << 5;
+
+ /* Snapshot the hardware statistics counters for this port. */
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_CAPTURE_PORT | port);
+ if (err)
+ return err;
+
+ /* Wait for the snapshotting to complete. */
+ return mv88e6xxx_g1_stats_wait(chip);
+}
+
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
+{
+ u32 value;
+ u16 reg;
+ int err;
+
+ *val = 0;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_READ_CAPTURED | stat);
+ if (err)
+ return;
+
+ err = mv88e6xxx_g1_stats_wait(chip);
+ if (err)
+ return;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
+ if (err)
+ return;
+
+ value = reg << 16;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
+ if (err)
+ return;
+
+ *val = value | reg;
+}
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index 62291e6fe3a3..1aec7382c02d 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -20,4 +20,22 @@ int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
+int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
+int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
+
+int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
+int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
+
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val);
+int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
+
#endif /* _MV88E6XXX_GLOBAL1_H */
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index cf686e7506a9..3e77071949ab 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1,5 +1,6 @@
/*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support (device address
+ * 0x1C)
*
* Copyright (c) 2008 Marvell Semiconductor
*
@@ -11,6 +12,7 @@
* (at your option) any later version.
*/
+#include <linux/irqdomain.h>
#include "mv88e6xxx.h"
#include "global2.h"
@@ -36,6 +38,31 @@ static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
}
+/* Offset 0x02: Management Enable 2x */
+/* Offset 0x03: Management Enable 0x */
+
+int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ int err;
+
+ /* Consider the frames with reserved multicast destination
+ * addresses matching 01:80:c2:00:00:2x as MGMT.
+ */
+ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
+ err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
+ if (err)
+ return err;
+ }
+
+ /* Consider the frames with reserved multicast destination
+ * addresses matching 01:80:c2:00:00:0x as MGMT.
+ */
+ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
+ return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
+
+ return 0;
+}
+
/* Offset 0x06: Device Mapping Table register */
static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
@@ -417,29 +444,154 @@ int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
}
-int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
+static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
{
- u16 reg;
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int n = d->hwirq;
+
+ chip->g2_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int n = d->hwirq;
+
+ chip->g2_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
+{
+ struct mv88e6xxx_chip *chip = dev_id;
+ unsigned int nhandled = 0;
+ unsigned int sub_irq;
+ unsigned int n;
int err;
+ u16 reg;
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
- /* Consider the frames with reserved multicast destination
- * addresses matching 01:80:c2:00:00:2x as MGMT.
- */
- err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
- if (err)
- return err;
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
+ mutex_unlock(&chip->reg_lock);
+ if (err)
+ goto out;
+
+ for (n = 0; n < 16; ++n) {
+ if (reg & (1 << n)) {
+ sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
+ handle_nested_irq(sub_irq);
+ ++nhandled;
+ }
}
+out:
+ return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
- if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
- /* Consider the frames with reserved multicast destination
- * addresses matching 01:80:c2:00:00:0x as MGMT.
- */
- err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
- if (err)
- return err;
+static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+ mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+ mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
+
+ mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g2_irq_chip = {
+ .name = "mv88e6xxx-g2",
+ .irq_mask = mv88e6xxx_g2_irq_mask,
+ .irq_unmask = mv88e6xxx_g2_irq_unmask,
+ .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock,
+ .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
+ unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct mv88e6xxx_chip *chip = d->host_data;
+
+ irq_set_chip_data(irq, d->host_data);
+ irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
+ .map = mv88e6xxx_g2_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+ int irq, virq;
+
+ free_irq(chip->device_irq, chip);
+ irq_dispose_mapping(chip->device_irq);
+
+ for (irq = 0; irq < 16; irq++) {
+ virq = irq_find_mapping(chip->g2_irq.domain, irq);
+ irq_dispose_mapping(virq);
}
+ irq_domain_remove(chip->g2_irq.domain);
+}
+
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+ int err, irq, virq;
+
+ if (!chip->dev->of_node)
+ return -EINVAL;
+
+ chip->g2_irq.domain = irq_domain_add_simple(
+ chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
+ if (!chip->g2_irq.domain)
+ return -ENOMEM;
+
+ for (irq = 0; irq < 16; irq++)
+ irq_create_mapping(chip->g2_irq.domain, irq);
+
+ chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
+ chip->g2_irq.masked = ~0;
+
+ chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
+ GLOBAL_STATUS_IRQ_DEVICE);
+ if (chip->device_irq < 0) {
+ err = chip->device_irq;
+ goto out;
+ }
+
+ err = request_threaded_irq(chip->device_irq, NULL,
+ mv88e6xxx_g2_irq_thread_fn,
+ IRQF_ONESHOT, "mv88e6xxx-g1", chip);
+ if (err)
+ goto out;
+
+ return 0;
+
+out:
+ for (irq = 0; irq < 16; irq++) {
+ virq = irq_find_mapping(chip->g2_irq.domain, irq);
+ irq_dispose_mapping(virq);
+ }
+
+ irq_domain_remove(chip->g2_irq.domain);
+
+ return err;
+}
+
+int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
+{
+ u16 reg;
+ int err;
+
/* Ignore removed tag data on doubly tagged packets, disable
* flow control messages, force flow control priority to the
* highest, and send all special multicast frames to the CPU
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index c4bb9035ee3a..9aefb7d8b0ad 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -33,6 +33,9 @@ int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
struct ethtool_eeprom *eeprom, u8 *data);
int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip);
+int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
#else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
@@ -83,6 +86,20 @@ static inline int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
return -EOPNOTSUPP;
}
+static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+}
+
+static inline int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
#endif /* _MV88E6XXX_GLOBAL2_H */
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index e572121c196e..af54baea47cf 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -13,6 +13,7 @@
#define __MV88E6XXX_H
#include <linux/if_vlan.h>
+#include <linux/irq.h>
#include <linux/gpio/consumer.h>
#ifndef UINT64_MAX
@@ -60,20 +61,29 @@
#define PORT_PCS_CTRL 0x01
#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15)
#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14)
+#define PORT_PCS_CTRL_FORCE_SPEED BIT(13) /* 6390 */
+#define PORT_PCS_CTRL_ALTSPEED BIT(12) /* 6390 */
+#define PORT_PCS_CTRL_200BASE BIT(12) /* 6352 */
#define PORT_PCS_CTRL_FC BIT(7)
#define PORT_PCS_CTRL_FORCE_FC BIT(6)
#define PORT_PCS_CTRL_LINK_UP BIT(5)
#define PORT_PCS_CTRL_FORCE_LINK BIT(4)
#define PORT_PCS_CTRL_DUPLEX_FULL BIT(3)
#define PORT_PCS_CTRL_FORCE_DUPLEX BIT(2)
-#define PORT_PCS_CTRL_10 0x00
-#define PORT_PCS_CTRL_100 0x01
-#define PORT_PCS_CTRL_1000 0x02
-#define PORT_PCS_CTRL_UNFORCED 0x03
+#define PORT_PCS_CTRL_SPEED_MASK (0x03)
+#define PORT_PCS_CTRL_SPEED_10 (0x00)
+#define PORT_PCS_CTRL_SPEED_100 (0x01)
+#define PORT_PCS_CTRL_SPEED_200 (0x02) /* 6065 and non Gb chips */
+#define PORT_PCS_CTRL_SPEED_1000 (0x02)
+#define PORT_PCS_CTRL_SPEED_10000 (0x03) /* 6390X */
+#define PORT_PCS_CTRL_SPEED_UNFORCED (0x03)
#define PORT_PAUSE_CTRL 0x02
+#define PORT_FLOW_CTRL_LIMIT_IN ((0x00 << 8) | BIT(15))
+#define PORT_FLOW_CTRL_LIMIT_OUT ((0x01 << 8) | BIT(15))
#define PORT_SWITCH_ID 0x03
#define PORT_SWITCH_ID_PROD_NUM_6085 0x04a
#define PORT_SWITCH_ID_PROD_NUM_6095 0x095
+#define PORT_SWITCH_ID_PROD_NUM_6097 0x099
#define PORT_SWITCH_ID_PROD_NUM_6131 0x106
#define PORT_SWITCH_ID_PROD_NUM_6320 0x115
#define PORT_SWITCH_ID_PROD_NUM_6123 0x121
@@ -84,11 +94,17 @@
#define PORT_SWITCH_ID_PROD_NUM_6175 0x175
#define PORT_SWITCH_ID_PROD_NUM_6176 0x176
#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7
+#define PORT_SWITCH_ID_PROD_NUM_6190 0x190
+#define PORT_SWITCH_ID_PROD_NUM_6190X 0x0a0
+#define PORT_SWITCH_ID_PROD_NUM_6191 0x191
#define PORT_SWITCH_ID_PROD_NUM_6240 0x240
+#define PORT_SWITCH_ID_PROD_NUM_6290 0x290
#define PORT_SWITCH_ID_PROD_NUM_6321 0x310
#define PORT_SWITCH_ID_PROD_NUM_6352 0x352
#define PORT_SWITCH_ID_PROD_NUM_6350 0x371
#define PORT_SWITCH_ID_PROD_NUM_6351 0x375
+#define PORT_SWITCH_ID_PROD_NUM_6390 0x390
+#define PORT_SWITCH_ID_PROD_NUM_6390X 0x0a1
#define PORT_CONTROL 0x04
#define PORT_CONTROL_USE_CORE_TAG BIT(15)
#define PORT_CONTROL_DROP_ON_LOCK BIT(14)
@@ -96,6 +112,7 @@
#define PORT_CONTROL_EGRESS_UNTAGGED (0x1 << 12)
#define PORT_CONTROL_EGRESS_TAGGED (0x2 << 12)
#define PORT_CONTROL_EGRESS_ADD_TAG (0x3 << 12)
+#define PORT_CONTROL_EGRESS_MASK (0x3 << 12)
#define PORT_CONTROL_HEADER BIT(11)
#define PORT_CONTROL_IGMP_MLD_SNOOP BIT(10)
#define PORT_CONTROL_DOUBLE_TAG BIT(9)
@@ -103,6 +120,7 @@
#define PORT_CONTROL_FRAME_MODE_DSA (0x1 << 8)
#define PORT_CONTROL_FRAME_MODE_PROVIDER (0x2 << 8)
#define PORT_CONTROL_FRAME_ETHER_TYPE_DSA (0x3 << 8)
+#define PORT_CONTROL_FRAME_MASK (0x3 << 8)
#define PORT_CONTROL_DSA_TAG BIT(8)
#define PORT_CONTROL_VLAN_TUNNEL BIT(7)
#define PORT_CONTROL_TAG_IF_BOTH BIT(6)
@@ -110,6 +128,10 @@
#define PORT_CONTROL_USE_TAG BIT(4)
#define PORT_CONTROL_FORWARD_UNKNOWN_MC BIT(3)
#define PORT_CONTROL_FORWARD_UNKNOWN BIT(2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_DA (0x0 << 2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_MULTICAST_DA (0x1 << 2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_UNITCAST_DA (0x2 << 2)
+#define PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA (0x3 << 2)
#define PORT_CONTROL_STATE_MASK 0x03
#define PORT_CONTROL_STATE_DISABLED 0x00
#define PORT_CONTROL_STATE_BLOCKING 0x01
@@ -158,15 +180,34 @@
#define PORT_OUT_FILTERED 0x13
#define PORT_TAG_REGMAP_0123 0x18
#define PORT_TAG_REGMAP_4567 0x19
+#define PORT_IEEE_PRIO_MAP_TABLE 0x18 /* 6390 */
+#define PORT_IEEE_PRIO_MAP_TABLE_UPDATE BIT(15)
+#define PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP (0x0 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP (0x1 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP (0x2 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP (0x3 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP (0x5 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP (0x6 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP (0x7 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT 9
#define GLOBAL_STATUS 0x00
#define GLOBAL_STATUS_PPU_STATE BIT(15) /* 6351 and 6171 */
-/* Two bits for 6165, 6185 etc */
-#define GLOBAL_STATUS_PPU_MASK (0x3 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED_RST (0x0 << 14)
-#define GLOBAL_STATUS_PPU_INITIALIZING (0x1 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED (0x2 << 14)
-#define GLOBAL_STATUS_PPU_POLLING (0x3 << 14)
+#define GLOBAL_STATUS_PPU_STATE_MASK (0x3 << 14) /* 6165 6185 */
+#define GLOBAL_STATUS_PPU_STATE_DISABLED_RST (0x0 << 14)
+#define GLOBAL_STATUS_PPU_STATE_INITIALIZING (0x1 << 14)
+#define GLOBAL_STATUS_PPU_STATE_DISABLED (0x2 << 14)
+#define GLOBAL_STATUS_PPU_STATE_POLLING (0x3 << 14)
+#define GLOBAL_STATUS_INIT_READY BIT(11)
+#define GLOBAL_STATUS_IRQ_AVB 8
+#define GLOBAL_STATUS_IRQ_DEVICE 7
+#define GLOBAL_STATUS_IRQ_STATS 6
+#define GLOBAL_STATUS_IRQ_VTU_PROBLEM 5
+#define GLOBAL_STATUS_IRQ_VTU_DONE 4
+#define GLOBAL_STATUS_IRQ_ATU_PROBLEM 3
+#define GLOBAL_STATUS_IRQ_ATU_DONE 2
+#define GLOBAL_STATUS_IRQ_TCAM_DONE 1
+#define GLOBAL_STATUS_IRQ_EEPROM_DONE 0
#define GLOBAL_MAC_01 0x01
#define GLOBAL_MAC_23 0x02
#define GLOBAL_MAC_45 0x03
@@ -254,14 +295,27 @@
#define GLOBAL_CORE_TAG_TYPE 0x19
#define GLOBAL_MONITOR_CONTROL 0x1a
#define GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT 12
+#define GLOBAL_MONITOR_CONTROL_INGRESS_MASK (0xf << 12)
#define GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT 8
+#define GLOBAL_MONITOR_CONTROL_EGRESS_MASK (0xf << 8)
#define GLOBAL_MONITOR_CONTROL_ARP_SHIFT 4
+#define GLOBAL_MONITOR_CONTROL_ARP_MASK (0xf << 4)
#define GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT 0
#define GLOBAL_MONITOR_CONTROL_ARP_DISABLED (0xf0)
+#define GLOBAL_MONITOR_CONTROL_UPDATE BIT(15)
+#define GLOBAL_MONITOR_CONTROL_0180C280000000XLO (0x00 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000000XHI (0x01 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000002XLO (0x02 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000002XHI (0x03 << 8)
+#define GLOBAL_MONITOR_CONTROL_INGRESS (0x20 << 8)
+#define GLOBAL_MONITOR_CONTROL_EGRESS (0x21 << 8)
+#define GLOBAL_MONITOR_CONTROL_CPU_DEST (0x30 << 8)
#define GLOBAL_CONTROL_2 0x1c
#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000
#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000
-
+#define GLOBAL_CONTROL_2_HIST_RX (0x1 << 6)
+#define GLOBAL_CONTROL_2_HIST_TX (0x2 << 6)
+#define GLOBAL_CONTROL_2_HIST_RX_TX (0x3 << 6)
#define GLOBAL_STATS_OP 0x1d
#define GLOBAL_STATS_OP_BUSY BIT(15)
#define GLOBAL_STATS_OP_NOP (0 << 12)
@@ -272,7 +326,8 @@
#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_BANK_1 BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_9 BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_10 BIT(10)
#define GLOBAL_STATS_COUNTER_32 0x1e
#define GLOBAL_STATS_COUNTER_01 0x1f
@@ -349,10 +404,18 @@
#define MV88E6XXX_N_FID 4096
+enum mv88e6xxx_frame_mode {
+ MV88E6XXX_FRAME_MODE_NORMAL,
+ MV88E6XXX_FRAME_MODE_DSA,
+ MV88E6XXX_FRAME_MODE_PROVIDER,
+ MV88E6XXX_FRAME_MODE_ETHERTYPE,
+};
+
/* List of supported models */
enum mv88e6xxx_model {
MV88E6085,
MV88E6095,
+ MV88E6097,
MV88E6123,
MV88E6131,
MV88E6161,
@@ -362,12 +425,18 @@ enum mv88e6xxx_model {
MV88E6175,
MV88E6176,
MV88E6185,
+ MV88E6190,
+ MV88E6190X,
+ MV88E6191,
MV88E6240,
+ MV88E6290,
MV88E6320,
MV88E6321,
MV88E6350,
MV88E6351,
MV88E6352,
+ MV88E6390,
+ MV88E6390X,
};
enum mv88e6xxx_family {
@@ -380,15 +449,10 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
+ MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
};
enum mv88e6xxx_cap {
- /* Two different tag protocols can be used by the driver. All
- * switches support DSA, but only later generations support
- * EDSA.
- */
- MV88E6XXX_CAP_EDSA,
-
/* Energy Efficient Ethernet.
*/
MV88E6XXX_CAP_EEE,
@@ -417,6 +481,7 @@ enum mv88e6xxx_cap {
* The device contains a second set of global 16-bit registers.
*/
MV88E6XXX_CAP_GLOBAL2,
+ MV88E6XXX_CAP_G2_INT, /* (0x00) Interrupt Status */
MV88E6XXX_CAP_G2_MGMT_EN_2X, /* (0x02) MGMT Enable Register 2x */
MV88E6XXX_CAP_G2_MGMT_EN_0X, /* (0x03) MGMT Enable Register 0x */
MV88E6XXX_CAP_G2_IRL_CMD, /* (0x09) Ingress Rate Command */
@@ -425,12 +490,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_CAP_G2_PVT_DATA, /* (0x0c) Cross Chip Port VLAN Data */
MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */
- /* PHY Polling Unit.
- * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
- */
- MV88E6XXX_CAP_PPU,
- MV88E6XXX_CAP_PPU_ACTIVE,
-
/* Per VLAN Spanning Tree Unit (STU).
* The Port State database, if present, is accessed through VTU
* operations and dedicated SID registers. See GLOBAL_VTU_SID.
@@ -450,7 +509,6 @@ enum mv88e6xxx_cap {
};
/* Bitmask of capabilities */
-#define MV88E6XXX_FLAG_EDSA BIT_ULL(MV88E6XXX_CAP_EDSA)
#define MV88E6XXX_FLAG_EEE BIT_ULL(MV88E6XXX_CAP_EEE)
#define MV88E6XXX_FLAG_SMI_CMD BIT_ULL(MV88E6XXX_CAP_SMI_CMD)
@@ -464,6 +522,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_G1_VTU_FID BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID)
#define MV88E6XXX_FLAG_GLOBAL2 BIT_ULL(MV88E6XXX_CAP_GLOBAL2)
+#define MV88E6XXX_FLAG_G2_INT BIT_ULL(MV88E6XXX_CAP_G2_INT)
#define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X)
#define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X)
#define MV88E6XXX_FLAG_G2_IRL_CMD BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD)
@@ -472,8 +531,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_G2_PVT_DATA BIT_ULL(MV88E6XXX_CAP_G2_PVT_DATA)
#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
-#define MV88E6XXX_FLAG_PPU BIT_ULL(MV88E6XXX_CAP_PPU)
-#define MV88E6XXX_FLAG_PPU_ACTIVE BIT_ULL(MV88E6XXX_CAP_PPU_ACTIVE)
#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU)
#define MV88E6XXX_FLAG_TEMP BIT_ULL(MV88E6XXX_CAP_TEMP)
#define MV88E6XXX_FLAG_TEMP_LIMIT BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT)
@@ -502,7 +559,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6095 \
(MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
- MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_MULTI_CHIP)
@@ -513,7 +569,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
@@ -524,6 +579,7 @@ enum mv88e6xxx_cap {
(MV88E6XXX_FLAG_G1_ATU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
@@ -536,19 +592,17 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6185 \
(MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
- MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6320 \
- (MV88E6XXX_FLAG_EDSA | \
- MV88E6XXX_FLAG_EEE | \
+ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \
MV88E6XXX_FLAG_VTU | \
@@ -557,14 +611,13 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAGS_PVT)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
- (MV88E6XXX_FLAG_EDSA | \
- MV88E6XXX_FLAG_G1_ATU_FID | \
+ (MV88E6XXX_FLAG_G1_ATU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_VTU | \
@@ -573,15 +626,14 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAGS_PVT)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
- (MV88E6XXX_FLAG_EDSA | \
- MV88E6XXX_FLAG_EEE | \
+ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_G1_ATU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \
@@ -593,6 +645,17 @@ enum mv88e6xxx_cap {
struct mv88e6xxx_ops;
+#define MV88E6XXX_FLAGS_FAMILY_6390 \
+ (MV88E6XXX_FLAG_EEE | \
+ MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_STU | \
+ MV88E6XXX_FLAG_TEMP | \
+ MV88E6XXX_FLAG_TEMP_LIMIT | \
+ MV88E6XXX_FLAG_VTU | \
+ MV88E6XXX_FLAGS_IRL | \
+ MV88E6XXX_FLAGS_MULTI_CHIP | \
+ MV88E6XXX_FLAGS_PVT)
+
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
u16 prod_num;
@@ -602,6 +665,8 @@ struct mv88e6xxx_info {
unsigned int port_base_addr;
unsigned int global1_addr;
unsigned int age_time_coeff;
+ unsigned int g1_irqs;
+ enum dsa_tag_protocol tag_protocol;
unsigned long long flags;
const struct mv88e6xxx_ops *ops;
};
@@ -628,6 +693,13 @@ struct mv88e6xxx_priv_port {
struct net_device *bridge_dev;
};
+struct mv88e6xxx_irq {
+ u16 masked;
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ unsigned int nirqs;
+};
+
struct mv88e6xxx_chip {
const struct mv88e6xxx_info *info;
@@ -677,6 +749,14 @@ struct mv88e6xxx_chip {
/* And the MDIO bus itself */
struct mii_bus *mdio_bus;
+
+ /* There can be two interrupt controllers, which are chained
+ * off a GPIO as interrupt source
+ */
+ struct mv88e6xxx_irq g1_irq;
+ struct mv88e6xxx_irq g2_irq;
+ int irq;
+ int device_irq;
};
struct mv88e6xxx_bus_ops {
@@ -696,19 +776,93 @@ struct mv88e6xxx_ops {
u16 *val);
int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 val);
-};
-enum stat_type {
- BANK0,
- BANK1,
- PORT,
+ /* PHY Polling Unit (PPU) operations */
+ int (*ppu_enable)(struct mv88e6xxx_chip *chip);
+ int (*ppu_disable)(struct mv88e6xxx_chip *chip);
+
+ /* Switch Software Reset */
+ int (*reset)(struct mv88e6xxx_chip *chip);
+
+ /* RGMII Receive/Transmit Timing Control
+ * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise.
+ */
+ int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
+
+#define LINK_FORCED_DOWN 0
+#define LINK_FORCED_UP 1
+#define LINK_UNFORCED -2
+
+ /* Port's MAC link state
+ * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down,
+ * or LINK_UNFORCED for normal link detection.
+ */
+ int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
+
+#define DUPLEX_UNFORCED -2
+
+ /* Port's MAC duplex mode
+ *
+ * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
+ * or DUPLEX_UNFORCED for normal duplex detection.
+ */
+ int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
+
+#define SPEED_MAX INT_MAX
+#define SPEED_UNFORCED -2
+
+ /* Port's MAC speed (in Mbps)
+ *
+ * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
+ * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
+ */
+ int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
+
+ int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
+
+ int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
+ enum mv88e6xxx_frame_mode mode);
+ int (*port_set_egress_unknowns)(struct mv88e6xxx_chip *chip, int port,
+ bool on);
+ int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
+ u16 etype);
+ int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port);
+
+ int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
+ int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
+
+ /* Snapshot the statistics for a port. The statistics can then
+ * be read back a leisure but still with a consistent view.
+ */
+ int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
+
+ /* Set the histogram mode for statistics, when the control registers
+ * are separated out of the STATS_OP register.
+ */
+ int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
+
+ /* Return the number of strings describing statistics */
+ int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
+ void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
+ void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data);
+ int (*g1_set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
+ int (*g1_set_egress_port)(struct mv88e6xxx_chip *chip, int port);
+
+ /* Can be either in g1 or g2, so don't use a prefix */
+ int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
};
+#define STATS_TYPE_PORT BIT(0)
+#define STATS_TYPE_BANK0 BIT(1)
+#define STATS_TYPE_BANK1 BIT(2)
+
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
int sizeof_stat;
int reg;
- enum stat_type type;
+ int type;
};
static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
new file mode 100644
index 000000000000..0db7fa0373ae
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -0,0 +1,729 @@
+/*
+ * Marvell 88E6xxx Switch Port Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.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 "mv88e6xxx.h"
+#include "port.h"
+
+int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
+ u16 *val)
+{
+ int addr = chip->info->port_base_addr + port;
+
+ return mv88e6xxx_read(chip, addr, reg, val);
+}
+
+int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
+ u16 val)
+{
+ int addr = chip->info->port_base_addr + port;
+
+ return mv88e6xxx_write(chip, addr, reg, val);
+}
+
+/* Offset 0x01: MAC (or PCS or Physical) Control Register
+ *
+ * Link, Duplex and Flow Control have one force bit, one value bit.
+ *
+ * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
+ * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
+ * Newer chips need a ForcedSpd bit 13 set to consider the value.
+ */
+
+static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
+ PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
+
+ switch (mode) {
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
+ PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ break;
+ default:
+ return 0;
+ }
+
+ err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n",
+ reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no",
+ reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no");
+
+ return 0;
+}
+
+int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port < 5)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
+}
+
+int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port != 0)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
+}
+
+int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP);
+
+ switch (link) {
+ case LINK_FORCED_DOWN:
+ reg |= PORT_PCS_CTRL_FORCE_LINK;
+ break;
+ case LINK_FORCED_UP:
+ reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP;
+ break;
+ case LINK_UNFORCED:
+ /* normal link detection */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n",
+ reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce",
+ reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down");
+
+ return 0;
+}
+
+int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL);
+
+ switch (dup) {
+ case DUPLEX_HALF:
+ reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
+ break;
+ case DUPLEX_FULL:
+ reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL;
+ break;
+ case DUPLEX_UNFORCED:
+ /* normal duplex detection */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n",
+ reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce",
+ reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half");
+
+ return 0;
+}
+
+static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
+ int speed, bool alt_bit, bool force_bit)
+{
+ u16 reg, ctrl;
+ int err;
+
+ switch (speed) {
+ case 10:
+ ctrl = PORT_PCS_CTRL_SPEED_10;
+ break;
+ case 100:
+ ctrl = PORT_PCS_CTRL_SPEED_100;
+ break;
+ case 200:
+ if (alt_bit)
+ ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
+ else
+ ctrl = PORT_PCS_CTRL_SPEED_200;
+ break;
+ case 1000:
+ ctrl = PORT_PCS_CTRL_SPEED_1000;
+ break;
+ case 2500:
+ ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED;
+ break;
+ case 10000:
+ /* all bits set, fall through... */
+ case SPEED_UNFORCED:
+ ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_PCS_CTRL_SPEED_MASK;
+ if (alt_bit)
+ reg &= ~PORT_PCS_CTRL_ALTSPEED;
+ if (force_bit) {
+ reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
+ if (speed != SPEED_UNFORCED)
+ ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
+ }
+ reg |= ctrl;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+ if (err)
+ return err;
+
+ if (speed)
+ netdev_dbg(chip->ds->ports[port].netdev,
+ "Speed set to %d Mbps\n", speed);
+ else
+ netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
+
+ return 0;
+}
+
+/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
+int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = 200;
+
+ if (speed > 200)
+ return -EOPNOTSUPP;
+
+ /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
+ return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
+int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = 1000;
+
+ if (speed == 200 || speed > 1000)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
+int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = 1000;
+
+ if (speed > 1000)
+ return -EOPNOTSUPP;
+
+ if (speed == 200 && port < 5)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
+}
+
+/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
+int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = port < 9 ? 1000 : 2500;
+
+ if (speed > 2500)
+ return -EOPNOTSUPP;
+
+ if (speed == 200 && port != 0)
+ return -EOPNOTSUPP;
+
+ if (speed == 2500 && port < 9)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
+/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
+int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+ if (speed == SPEED_MAX)
+ speed = port < 9 ? 1000 : 10000;
+
+ if (speed == 200 && port != 0)
+ return -EOPNOTSUPP;
+
+ if (speed >= 2500 && port < 9)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
+/* Offset 0x02: Pause Control
+ *
+ * Do not limit the period of time that this port can be paused for by
+ * the remote end or the period of time that this port can pause the
+ * remote end.
+ */
+int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+{
+ return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
+}
+
+int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
+ PORT_FLOW_CTRL_LIMIT_IN | 0);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
+ PORT_FLOW_CTRL_LIMIT_OUT | 0);
+}
+
+/* Offset 0x04: Port Control Register */
+
+static const char * const mv88e6xxx_port_state_names[] = {
+ [PORT_CONTROL_STATE_DISABLED] = "Disabled",
+ [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
+ [PORT_CONTROL_STATE_LEARNING] = "Learning",
+ [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
+};
+
+int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_CONTROL_STATE_MASK;
+ reg |= state;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n",
+ mv88e6xxx_port_state_names[state]);
+
+ return 0;
+}
+
+int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
+ u16 mode)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_CONTROL_EGRESS_MASK;
+ reg |= mode;
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+ enum mv88e6xxx_frame_mode mode)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_CONTROL_FRAME_MODE_DSA;
+
+ switch (mode) {
+ case MV88E6XXX_FRAME_MODE_NORMAL:
+ reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+ break;
+ case MV88E6XXX_FRAME_MODE_DSA:
+ reg |= PORT_CONTROL_FRAME_MODE_DSA;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+ enum mv88e6xxx_frame_mode mode)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_CONTROL_FRAME_MASK;
+
+ switch (mode) {
+ case MV88E6XXX_FRAME_MODE_NORMAL:
+ reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+ break;
+ case MV88E6XXX_FRAME_MODE_DSA:
+ reg |= PORT_CONTROL_FRAME_MODE_DSA;
+ break;
+ case MV88E6XXX_FRAME_MODE_PROVIDER:
+ reg |= PORT_CONTROL_FRAME_MODE_PROVIDER;
+ break;
+ case MV88E6XXX_FRAME_MODE_ETHERTYPE:
+ reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+ bool on)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ if (on)
+ reg |= PORT_CONTROL_FORWARD_UNKNOWN;
+ else
+ reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+ bool on)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+ if (err)
+ return err;
+
+ if (on)
+ reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+ else
+ reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+/* Offset 0x05: Port Control 1 */
+
+/* Offset 0x06: Port Based VLAN Map */
+
+int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
+{
+ const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+ if (err)
+ return err;
+
+ reg &= ~mask;
+ reg |= map & mask;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n",
+ map);
+
+ return 0;
+}
+
+int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
+{
+ const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
+ u16 reg;
+ int err;
+
+ /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
+ err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+ if (err)
+ return err;
+
+ *fid = (reg & 0xf000) >> 12;
+
+ /* Port's default FID upper bits are located in reg 0x05, offset 0 */
+ if (upper_mask) {
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+ if (err)
+ return err;
+
+ *fid |= (reg & upper_mask) << 4;
+ }
+
+ return 0;
+}
+
+int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
+{
+ const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
+ u16 reg;
+ int err;
+
+ if (fid >= mv88e6xxx_num_databases(chip))
+ return -EINVAL;
+
+ /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
+ err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+ if (err)
+ return err;
+
+ reg &= 0x0fff;
+ reg |= (fid & 0x000f) << 12;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+ if (err)
+ return err;
+
+ /* Port's default FID upper bits are located in reg 0x05, offset 0 */
+ if (upper_mask) {
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+ if (err)
+ return err;
+
+ reg &= ~upper_mask;
+ reg |= (fid >> 4) & upper_mask;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
+ if (err)
+ return err;
+ }
+
+ netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid);
+
+ return 0;
+}
+
+/* Offset 0x07: Default Port VLAN ID & Priority */
+
+int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+ if (err)
+ return err;
+
+ *pvid = reg & PORT_DEFAULT_VLAN_MASK;
+
+ return 0;
+}
+
+int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_DEFAULT_VLAN_MASK;
+ reg |= pvid & PORT_DEFAULT_VLAN_MASK;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n",
+ pvid);
+
+ return 0;
+}
+
+/* Offset 0x08: Port Control 2 Register */
+
+static const char * const mv88e6xxx_port_8021q_mode_names[] = {
+ [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
+ [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
+ [PORT_CONTROL_2_8021Q_CHECK] = "Check",
+ [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
+};
+
+int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
+ u16 mode)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+ if (err)
+ return err;
+
+ reg &= ~PORT_CONTROL_2_8021Q_MASK;
+ reg |= mode & PORT_CONTROL_2_8021Q_MASK;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+ if (err)
+ return err;
+
+ netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
+ mv88e6xxx_port_8021q_mode_names[mode]);
+
+ return 0;
+}
+
+int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+ if (err)
+ return err;
+
+ reg |= PORT_CONTROL_2_JUMBO_10240;
+
+ return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+}
+
+/* Offset 0x09: Port Rate Control */
+
+int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
+{
+ return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0000);
+}
+
+int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
+{
+ return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
+}
+
+/* Offset 0x0f: Port Ether type */
+
+int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
+ u16 etype)
+{
+ return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype);
+}
+
+/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
+ * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
+ */
+
+int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ /* Use a direct priority mapping for all IEEE tagged frames */
+ err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654);
+}
+
+static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
+ int port, u16 table,
+ u8 pointer, u16 data)
+{
+ u16 reg;
+
+ reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
+ table |
+ (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
+ data;
+
+ return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg);
+}
+
+int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
+{
+ int err, i;
+
+ for (i = 0; i <= 7; i++) {
+ err = mv88e6xxx_port_ieeepmt_write(
+ chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP,
+ i, (i | i << 4));
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ieeepmt_write(
+ chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP,
+ i, i);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ieeepmt_write(
+ chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP,
+ i, i);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ieeepmt_write(
+ chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP,
+ i, i);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
new file mode 100644
index 000000000000..7b3bacaacbfe
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -0,0 +1,71 @@
+/*
+ * Marvell 88E6xxx Switch Port Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.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.
+ */
+
+#ifndef _MV88E6XXX_PORT_H
+#define _MV88E6XXX_PORT_H
+
+#include "mv88e6xxx.h"
+
+int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
+ u16 *val);
+int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
+ u16 val);
+
+int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
+int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
+
+int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
+
+int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup);
+
+int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+
+int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state);
+
+int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map);
+
+int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid);
+int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid);
+
+int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid);
+int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid);
+
+int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
+ u16 mode);
+int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
+int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
+ u16 mode);
+int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+ enum mv88e6xxx_frame_mode mode);
+int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+ enum mv88e6xxx_frame_mode mode);
+int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+ bool on);
+int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+ bool on);
+int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
+ u16 etype);
+int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
+int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
+int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+
+#endif /* _MV88E6XXX_PORT_H */
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 69fc8409a973..6421835f11b7 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -154,6 +154,9 @@ static void dummy_setup(struct net_device *dev)
dev->hw_features |= dev->features;
dev->hw_enc_features |= dev->features;
eth_hw_addr_random(dev);
+
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
}
static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 91ada52f776b..a7533780dddc 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -508,7 +508,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_get_stats = el3_get_stats,
.ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = el3_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1041,67 +1040,68 @@ el3_link_ok(struct net_device *dev)
}
static int
-el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_link_ksettings *cmd)
{
u16 tmp;
int ioaddr = dev->base_addr;
+ u32 supported;
EL3WINDOW(0);
/* obtain current transceiver via WN4_MEDIA? */
tmp = inw(ioaddr + WN0_ADDR_CONF);
- ecmd->transceiver = XCVR_INTERNAL;
switch (tmp >> 14) {
case 0:
- ecmd->port = PORT_TP;
+ cmd->base.port = PORT_TP;
break;
case 1:
- ecmd->port = PORT_AUI;
- ecmd->transceiver = XCVR_EXTERNAL;
+ cmd->base.port = PORT_AUI;
break;
case 3:
- ecmd->port = PORT_BNC;
+ cmd->base.port = PORT_BNC;
default:
break;
}
- ecmd->duplex = DUPLEX_HALF;
- ecmd->supported = 0;
+ cmd->base.duplex = DUPLEX_HALF;
+ supported = 0;
tmp = inw(ioaddr + WN0_CONF_CTRL);
if (tmp & (1<<13))
- ecmd->supported |= SUPPORTED_AUI;
+ supported |= SUPPORTED_AUI;
if (tmp & (1<<12))
- ecmd->supported |= SUPPORTED_BNC;
+ supported |= SUPPORTED_BNC;
if (tmp & (1<<9)) {
- ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
+ supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full; /* hmm... */
EL3WINDOW(4);
tmp = inw(ioaddr + WN4_NETDIAG);
if (tmp & FD_ENABLE)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
}
- ethtool_cmd_speed_set(ecmd, SPEED_10);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ cmd->base.speed = SPEED_10;
EL3WINDOW(1);
return 0;
}
static int
-el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+el3_netdev_set_ecmd(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
u16 tmp;
int ioaddr = dev->base_addr;
- if (ecmd->speed != SPEED_10)
+ if (cmd->base.speed != SPEED_10)
return -EINVAL;
- if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
- return -EINVAL;
- if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
+ if ((cmd->base.duplex != DUPLEX_HALF) &&
+ (cmd->base.duplex != DUPLEX_FULL))
return -EINVAL;
/* change XCVR type */
EL3WINDOW(0);
tmp = inw(ioaddr + WN0_ADDR_CONF);
- switch (ecmd->port) {
+ switch (cmd->base.port) {
case PORT_TP:
tmp &= ~(3<<14);
dev->if_port = 0;
@@ -1131,7 +1131,7 @@ el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
EL3WINDOW(4);
tmp = inw(ioaddr + WN4_NETDIAG);
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
tmp |= FD_ENABLE;
else
tmp &= ~FD_ENABLE;
@@ -1147,24 +1147,26 @@ static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
}
-static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int el3_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct el3_private *lp = netdev_priv(dev);
int ret;
spin_lock_irq(&lp->lock);
- ret = el3_netdev_get_ecmd(dev, ecmd);
+ ret = el3_netdev_get_ecmd(dev, cmd);
spin_unlock_irq(&lp->lock);
return ret;
}
-static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int el3_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct el3_private *lp = netdev_priv(dev);
int ret;
spin_lock_irq(&lp->lock);
- ret = el3_netdev_set_ecmd(dev, ecmd);
+ ret = el3_netdev_set_ecmd(dev, cmd);
spin_unlock_irq(&lp->lock);
return ret;
}
@@ -1192,11 +1194,11 @@ static void el3_set_msglevel(struct net_device *dev, u32 v)
static const struct ethtool_ops ethtool_ops = {
.get_drvinfo = el3_get_drvinfo,
- .get_settings = el3_get_settings,
- .set_settings = el3_set_settings,
.get_link = el3_get_link,
.get_msglevel = el3_get_msglevel,
.set_msglevel = el3_set_msglevel,
+ .get_link_ksettings = el3_get_link_ksettings,
+ .set_link_ksettings = el3_set_link_ksettings,
};
static void
diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c
index b26e038b4a0e..b9f4c463e516 100644
--- a/drivers/net/ethernet/3com/3c515.c
+++ b/drivers/net/ethernet/3com/3c515.c
@@ -570,7 +570,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_tx_timeout = corkscrew_timeout,
.ndo_get_stats = corkscrew_get_stats,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
index b88afd759307..9359a37fedc0 100644
--- a/drivers/net/ethernet/3com/3c574_cs.c
+++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -254,7 +254,6 @@ static const struct net_device_ops el3_netdev_ops = {
.ndo_get_stats = el3_get_stats,
.ndo_do_ioctl = el3_ioctl,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index 71396e4b87e3..e28254a00599 100644
--- a/drivers/net/ethernet/3com/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -188,7 +188,6 @@ static const struct net_device_ops el3_netdev_ops = {
.ndo_set_config = el3_config,
.ndo_get_stats = el3_get_stats,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 9133e7926da5..b3560a364e53 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1062,7 +1062,6 @@ static const struct net_device_ops boomrang_netdev_ops = {
.ndo_do_ioctl = vortex_ioctl,
#endif
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1080,7 +1079,6 @@ static const struct net_device_ops vortex_netdev_ops = {
.ndo_do_ioctl = vortex_ioctl,
#endif
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2909,18 +2907,20 @@ static int vortex_nway_reset(struct net_device *dev)
return mii_nway_restart(&vp->mii);
}
-static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int vortex_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- return mii_ethtool_gset(&vp->mii, cmd);
+ return mii_ethtool_get_link_ksettings(&vp->mii, cmd);
}
-static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int vortex_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- return mii_ethtool_sset(&vp->mii, cmd);
+ return mii_ethtool_set_link_ksettings(&vp->mii, cmd);
}
static u32 vortex_get_msglevel(struct net_device *dev)
@@ -3033,13 +3033,13 @@ static const struct ethtool_ops vortex_ethtool_ops = {
.set_msglevel = vortex_set_msglevel,
.get_ethtool_stats = vortex_get_ethtool_stats,
.get_sset_count = vortex_get_sset_count,
- .get_settings = vortex_get_settings,
- .set_settings = vortex_set_settings,
.get_link = ethtool_op_get_link,
.nway_reset = vortex_nway_reset,
.get_wol = vortex_get_wol,
.set_wol = vortex_set_wol,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_link_ksettings = vortex_get_link_ksettings,
+ .set_link_ksettings = vortex_set_link_ksettings,
};
#ifdef CONFIG_PCI
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 8f8418d2ac4a..a0cacbe846ba 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -996,28 +996,30 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
}
static int
-typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+typhoon_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct typhoon *tp = netdev_priv(dev);
+ u32 supported, advertising = 0;
- cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg;
switch (tp->xcvr_select) {
case TYPHOON_XCVR_10HALF:
- cmd->advertising = ADVERTISED_10baseT_Half;
+ advertising = ADVERTISED_10baseT_Half;
break;
case TYPHOON_XCVR_10FULL:
- cmd->advertising = ADVERTISED_10baseT_Full;
+ advertising = ADVERTISED_10baseT_Full;
break;
case TYPHOON_XCVR_100HALF:
- cmd->advertising = ADVERTISED_100baseT_Half;
+ advertising = ADVERTISED_100baseT_Half;
break;
case TYPHOON_XCVR_100FULL:
- cmd->advertising = ADVERTISED_100baseT_Full;
+ advertising = ADVERTISED_100baseT_Full;
break;
case TYPHOON_XCVR_AUTONEG:
- cmd->advertising = ADVERTISED_10baseT_Half |
+ advertising = ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
@@ -1026,54 +1028,57 @@ typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
if(tp->capabilities & TYPHOON_FIBER) {
- cmd->supported |= SUPPORTED_FIBRE;
- cmd->advertising |= ADVERTISED_FIBRE;
- cmd->port = PORT_FIBRE;
+ supported |= SUPPORTED_FIBRE;
+ advertising |= ADVERTISED_FIBRE;
+ cmd->base.port = PORT_FIBRE;
} else {
- cmd->supported |= SUPPORTED_10baseT_Half |
+ supported |= SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_TP;
- cmd->advertising |= ADVERTISED_TP;
- cmd->port = PORT_TP;
+ advertising |= ADVERTISED_TP;
+ cmd->base.port = PORT_TP;
}
/* need to get stats to make these link speed/duplex valid */
typhoon_do_get_stats(tp);
- ethtool_cmd_speed_set(cmd, tp->speed);
- cmd->duplex = tp->duplex;
- cmd->phy_address = 0;
- cmd->transceiver = XCVR_INTERNAL;
+ cmd->base.speed = tp->speed;
+ cmd->base.duplex = tp->duplex;
+ cmd->base.phy_address = 0;
if(tp->xcvr_select == TYPHOON_XCVR_AUTONEG)
- cmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
else
- cmd->autoneg = AUTONEG_DISABLE;
- cmd->maxtxpkt = 1;
- cmd->maxrxpkt = 1;
+ cmd->base.autoneg = AUTONEG_DISABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
static int
-typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+typhoon_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct typhoon *tp = netdev_priv(dev);
- u32 speed = ethtool_cmd_speed(cmd);
+ u32 speed = cmd->base.speed;
struct cmd_desc xp_cmd;
__le16 xcvr;
int err;
err = -EINVAL;
- if (cmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
xcvr = TYPHOON_XCVR_AUTONEG;
} else {
- if (cmd->duplex == DUPLEX_HALF) {
+ if (cmd->base.duplex == DUPLEX_HALF) {
if (speed == SPEED_10)
xcvr = TYPHOON_XCVR_10HALF;
else if (speed == SPEED_100)
xcvr = TYPHOON_XCVR_100HALF;
else
goto out;
- } else if (cmd->duplex == DUPLEX_FULL) {
+ } else if (cmd->base.duplex == DUPLEX_FULL) {
if (speed == SPEED_10)
xcvr = TYPHOON_XCVR_10FULL;
else if (speed == SPEED_100)
@@ -1091,12 +1096,12 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
goto out;
tp->xcvr_select = xcvr;
- if(cmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
tp->speed = 0xff; /* invalid */
tp->duplex = 0xff; /* invalid */
} else {
tp->speed = speed;
- tp->duplex = cmd->duplex;
+ tp->duplex = cmd->base.duplex;
}
out:
@@ -1145,13 +1150,13 @@ typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
}
static const struct ethtool_ops typhoon_ethtool_ops = {
- .get_settings = typhoon_get_settings,
- .set_settings = typhoon_set_settings,
.get_drvinfo = typhoon_get_drvinfo,
.get_wol = typhoon_get_wol,
.set_wol = typhoon_set_wol,
.get_link = ethtool_op_get_link,
.get_ringparam = typhoon_get_ringparam,
+ .get_link_ksettings = typhoon_get_link_ksettings,
+ .set_link_ksettings = typhoon_set_link_ksettings,
};
static int
@@ -2255,7 +2260,6 @@ static const struct net_device_ops typhoon_netdev_ops = {
.ndo_get_stats = typhoon_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int
diff --git a/drivers/net/ethernet/8390/8390.c b/drivers/net/ethernet/8390/8390.c
index 5db1f55abef4..a43544af257b 100644
--- a/drivers/net/ethernet/8390/8390.c
+++ b/drivers/net/ethernet/8390/8390.c
@@ -64,7 +64,6 @@ const struct net_device_ops ei_netdev_ops = {
.ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/8390p.c b/drivers/net/ethernet/8390/8390p.c
index e8fc2e87e840..46d2257c4430 100644
--- a/drivers/net/ethernet/8390/8390p.c
+++ b/drivers/net/ethernet/8390/8390p.c
@@ -69,7 +69,6 @@ const struct net_device_ops eip_netdev_ops = {
.ndo_set_rx_mode = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
#endif
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 39ca9350d1b2..b0a3b85fc6f8 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -536,7 +536,6 @@ static const struct net_device_ops ax_netdev_ops = {
.ndo_set_rx_mode = ax_ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ax_ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 4ea717d68c95..1d84a0544ace 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -134,7 +134,6 @@ static const struct net_device_ops axnet_netdev_ops = {
.ndo_tx_timeout = axnet_tx_timeout,
.ndo_get_stats = get_stats,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
index d686b9cac29f..11cbf22ad201 100644
--- a/drivers/net/ethernet/8390/etherh.c
+++ b/drivers/net/ethernet/8390/etherh.c
@@ -654,7 +654,6 @@ static const struct net_device_ops etherh_netdev_ops = {
.ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
index 0fe19d609c2e..8ae249195301 100644
--- a/drivers/net/ethernet/8390/hydra.c
+++ b/drivers/net/ethernet/8390/hydra.c
@@ -105,7 +105,6 @@ static const struct net_device_ops hydra_netdev_ops = {
.ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index b9283901136e..9497f18eaba0 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -483,7 +483,6 @@ static const struct net_device_ops mac8390_netdev_ops = {
.ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
index e1c055574a11..4bb967bc879e 100644
--- a/drivers/net/ethernet/8390/mcf8390.c
+++ b/drivers/net/ethernet/8390/mcf8390.c
@@ -308,7 +308,6 @@ static const struct net_device_ops mcf8390_netdev_ops = {
.ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index 57e97910c728..07355302443d 100644
--- a/drivers/net/ethernet/8390/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -209,7 +209,6 @@ static const struct net_device_ops ne2k_netdev_ops = {
.ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index 2f79d29f17f2..63079a6e20d9 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -227,7 +227,6 @@ static const struct net_device_ops pcnet_netdev_ops = {
.ndo_do_ioctl = ei_ioctl,
.ndo_set_rx_mode = ei_set_multicast_list,
.ndo_tx_timeout = ei_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c
index 139385dcdaa7..364b6514f65f 100644
--- a/drivers/net/ethernet/8390/smc-ultra.c
+++ b/drivers/net/ethernet/8390/smc-ultra.c
@@ -195,7 +195,6 @@ static const struct net_device_ops ultra_netdev_ops = {
.ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ultra_poll,
#endif
diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c
index dd7d816bde52..ad019cbc698f 100644
--- a/drivers/net/ethernet/8390/wd.c
+++ b/drivers/net/ethernet/8390/wd.c
@@ -156,7 +156,6 @@ static const struct net_device_ops wd_netdev_ops = {
.ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
#endif
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
index 8308728fad05..6d93956b293b 100644
--- a/drivers/net/ethernet/8390/zorro8390.c
+++ b/drivers/net/ethernet/8390/zorro8390.c
@@ -284,7 +284,6 @@ static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = __ei_poll,
#endif
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 8cc7467b6c1f..6e16e441f85e 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -21,6 +21,7 @@ source "drivers/net/ethernet/3com/Kconfig"
source "drivers/net/ethernet/adaptec/Kconfig"
source "drivers/net/ethernet/aeroflex/Kconfig"
source "drivers/net/ethernet/agere/Kconfig"
+source "drivers/net/ethernet/alacritech/Kconfig"
source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
source "drivers/net/ethernet/altera/Kconfig"
@@ -165,6 +166,7 @@ source "drivers/net/ethernet/seeq/Kconfig"
source "drivers/net/ethernet/silan/Kconfig"
source "drivers/net/ethernet/sis/Kconfig"
source "drivers/net/ethernet/sfc/Kconfig"
+source "drivers/net/ethernet/sfc/falcon/Kconfig"
source "drivers/net/ethernet/sgi/Kconfig"
source "drivers/net/ethernet/smsc/Kconfig"
source "drivers/net/ethernet/stmicro/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index a09423df83f2..24330f4885a9 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_NET_VENDOR_8390) += 8390/
obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
obj-$(CONFIG_GRETH) += aeroflex/
obj-$(CONFIG_NET_VENDOR_AGERE) += agere/
+obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/
obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
obj-$(CONFIG_ALTERA_TSE) += altera/
@@ -75,6 +76,7 @@ obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
obj-$(CONFIG_NET_VENDOR_SILAN) += silan/
obj-$(CONFIG_NET_VENDOR_SIS) += sis/
obj-$(CONFIG_SFC) += sfc/
+obj-$(CONFIG_SFC_FALCON) += sfc/falcon/
obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/
obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 8af2c88d5b33..3aaad33cdbc6 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -634,7 +634,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_get_stats = get_stats,
.ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef VLAN_SUPPORT
@@ -1817,21 +1816,23 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
}
-static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct netdev_private *np = netdev_priv(dev);
spin_lock_irq(&np->lock);
- mii_ethtool_gset(&np->mii_if, ecmd);
+ mii_ethtool_get_link_ksettings(&np->mii_if, cmd);
spin_unlock_irq(&np->lock);
return 0;
}
-static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct netdev_private *np = netdev_priv(dev);
int res;
spin_lock_irq(&np->lock);
- res = mii_ethtool_sset(&np->mii_if, ecmd);
+ res = mii_ethtool_set_link_ksettings(&np->mii_if, cmd);
spin_unlock_irq(&np->lock);
check_duplex(dev);
return res;
@@ -1862,12 +1863,12 @@ static void set_msglevel(struct net_device *dev, u32 val)
static const struct ethtool_ops ethtool_ops = {
.begin = check_if_running,
.get_drvinfo = get_drvinfo,
- .get_settings = get_settings,
- .set_settings = set_settings,
.nway_reset = nway_reset,
.get_link = get_link,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
+ .get_link_ksettings = get_link_ksettings,
+ .set_link_ksettings = set_link_ksettings,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index 6b94ba610399..98cc8f535021 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -58,7 +58,7 @@ config BFIN_RX_DESC_NUM
config BFIN_MAC_USE_HWSTAMP
bool "Use IEEE 1588 hwstamp"
depends on BFIN_MAC && BF518
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
default y
---help---
To support the IEEE 1588 Precision Time Protocol (PTP), select y here
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index 00f9ee3fc3e5..88164529b52a 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -1571,7 +1571,6 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
.ndo_set_rx_mode = bfin_mac_set_multicast_list,
.ndo_do_ioctl = bfin_mac_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = bfin_mac_poll_controller,
#endif
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index f8df8248035e..93def92f9997 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1290,15 +1290,6 @@ static int greth_mdio_probe(struct net_device *dev)
return 0;
}
-static inline int phy_aneg_done(struct phy_device *phydev)
-{
- int retval;
-
- retval = phy_read(phydev, MII_BMSR);
-
- return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
-}
-
static int greth_mdio_init(struct greth_private *greth)
{
int ret;
diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c
index 906683851c7d..831bab352f8e 100644
--- a/drivers/net/ethernet/agere/et131x.c
+++ b/drivers/net/ethernet/agere/et131x.c
@@ -176,6 +176,8 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
#define NUM_FBRS 2
#define MAX_PACKETS_HANDLED 256
+#define ET131X_MIN_MTU 64
+#define ET131X_MAX_MTU 9216
#define ALCATEL_MULTICAST_PKT 0x01000000
#define ALCATEL_BROADCAST_PKT 0x02000000
@@ -3869,9 +3871,6 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu)
int result = 0;
struct et131x_adapter *adapter = netdev_priv(netdev);
- if (new_mtu < 64 || new_mtu > 9216)
- return -EINVAL;
-
et131x_disable_txrx(netdev);
netdev->mtu = new_mtu;
@@ -3958,6 +3957,8 @@ static int et131x_pci_setup(struct pci_dev *pdev,
netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
netdev->netdev_ops = &et131x_netdev_ops;
+ netdev->min_mtu = ET131X_MIN_MTU;
+ netdev->max_mtu = ET131X_MAX_MTU;
SET_NETDEV_DEV(netdev, &pdev->dev);
netdev->ethtool_ops = &et131x_ethtool_ops;
diff --git a/drivers/net/ethernet/alacritech/Kconfig b/drivers/net/ethernet/alacritech/Kconfig
new file mode 100644
index 000000000000..09496e18cdc5
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/Kconfig
@@ -0,0 +1,28 @@
+config NET_VENDOR_ALACRITECH
+ bool "Alacritech devices"
+ default y
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all the
+ questions about Alacritech devices. If you say Y, you will be asked
+ for your specific device in the following questions.
+
+if NET_VENDOR_ALACRITECH
+
+config SLICOSS
+ tristate "Alacritech Slicoss support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver supports Gigabit Ethernet adapters based on the
+ Session Layer Interface (SLIC) technology by Alacritech.
+
+ Supported are Mojave (1 port) and Oasis (1, 2 and 4 port) cards,
+ both copper and fiber.
+
+ To compile this driver as a module, choose M here: the module
+ will be called slicoss. This is recommended.
+
+endif # NET_VENDOR_ALACRITECH
diff --git a/drivers/net/ethernet/alacritech/Makefile b/drivers/net/ethernet/alacritech/Makefile
new file mode 100644
index 000000000000..8790e9ed8496
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the Alacritech Slicoss driver
+#
+obj-$(CONFIG_SLICOSS) += slicoss.o
diff --git a/drivers/net/ethernet/alacritech/slic.h b/drivers/net/ethernet/alacritech/slic.h
new file mode 100644
index 000000000000..08931b4afc96
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/slic.h
@@ -0,0 +1,575 @@
+
+#ifndef _SLIC_H
+#define _SLIC_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock_types.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#define SLIC_VGBSTAT_XPERR 0x40000000
+#define SLIC_VGBSTAT_XERRSHFT 25
+#define SLIC_VGBSTAT_XCSERR 0x23
+#define SLIC_VGBSTAT_XUFLOW 0x22
+#define SLIC_VGBSTAT_XHLEN 0x20
+#define SLIC_VGBSTAT_NETERR 0x01000000
+#define SLIC_VGBSTAT_NERRSHFT 16
+#define SLIC_VGBSTAT_NERRMSK 0x1ff
+#define SLIC_VGBSTAT_NCSERR 0x103
+#define SLIC_VGBSTAT_NUFLOW 0x102
+#define SLIC_VGBSTAT_NHLEN 0x100
+#define SLIC_VGBSTAT_LNKERR 0x00000080
+#define SLIC_VGBSTAT_LERRMSK 0xff
+#define SLIC_VGBSTAT_LDEARLY 0x86
+#define SLIC_VGBSTAT_LBOFLO 0x85
+#define SLIC_VGBSTAT_LCODERR 0x84
+#define SLIC_VGBSTAT_LDBLNBL 0x83
+#define SLIC_VGBSTAT_LCRCERR 0x82
+#define SLIC_VGBSTAT_LOFLO 0x81
+#define SLIC_VGBSTAT_LUFLO 0x80
+
+#define SLIC_IRHDDR_FLEN_MSK 0x0000ffff
+#define SLIC_IRHDDR_SVALID 0x80000000
+#define SLIC_IRHDDR_ERR 0x10000000
+
+#define SLIC_VRHSTAT_802OE 0x80000000
+#define SLIC_VRHSTAT_TPOFLO 0x10000000
+#define SLIC_VRHSTATB_802UE 0x80000000
+#define SLIC_VRHSTATB_RCVE 0x40000000
+#define SLIC_VRHSTATB_BUFF 0x20000000
+#define SLIC_VRHSTATB_CARRE 0x08000000
+#define SLIC_VRHSTATB_LONGE 0x02000000
+#define SLIC_VRHSTATB_PREA 0x01000000
+#define SLIC_VRHSTATB_CRC 0x00800000
+#define SLIC_VRHSTATB_DRBL 0x00400000
+#define SLIC_VRHSTATB_CODE 0x00200000
+#define SLIC_VRHSTATB_TPCSUM 0x00100000
+#define SLIC_VRHSTATB_TPHLEN 0x00080000
+#define SLIC_VRHSTATB_IPCSUM 0x00040000
+#define SLIC_VRHSTATB_IPLERR 0x00020000
+#define SLIC_VRHSTATB_IPHERR 0x00010000
+
+#define SLIC_CMD_XMT_REQ 0x01
+#define SLIC_CMD_TYPE_DUMB 3
+
+#define SLIC_RESET_MAGIC 0xDEAD
+#define SLIC_ICR_INT_OFF 0
+#define SLIC_ICR_INT_ON 1
+#define SLIC_ICR_INT_MASK 2
+
+#define SLIC_ISR_ERR 0x80000000
+#define SLIC_ISR_RCV 0x40000000
+#define SLIC_ISR_CMD 0x20000000
+#define SLIC_ISR_IO 0x60000000
+#define SLIC_ISR_UPC 0x10000000
+#define SLIC_ISR_LEVENT 0x08000000
+#define SLIC_ISR_RMISS 0x02000000
+#define SLIC_ISR_UPCERR 0x01000000
+#define SLIC_ISR_XDROP 0x00800000
+#define SLIC_ISR_UPCBSY 0x00020000
+
+#define SLIC_ISR_PING_MASK 0x00700000
+#define SLIC_ISR_UPCERR_MASK (SLIC_ISR_UPCERR | SLIC_ISR_UPCBSY)
+#define SLIC_ISR_UPC_MASK (SLIC_ISR_UPC | SLIC_ISR_UPCERR_MASK)
+#define SLIC_WCS_START 0x80000000
+#define SLIC_WCS_COMPARE 0x40000000
+#define SLIC_RCVWCS_BEGIN 0x40000000
+#define SLIC_RCVWCS_FINISH 0x80000000
+
+#define SLIC_MIICR_REG_16 0x00100000
+#define SLIC_MRV_REG16_XOVERON 0x0068
+
+#define SLIC_GIG_LINKUP 0x0001
+#define SLIC_GIG_FULLDUPLEX 0x0002
+#define SLIC_GIG_SPEED_MASK 0x000C
+#define SLIC_GIG_SPEED_1000 0x0008
+#define SLIC_GIG_SPEED_100 0x0004
+#define SLIC_GIG_SPEED_10 0x0000
+
+#define SLIC_GMCR_RESET 0x80000000
+#define SLIC_GMCR_GBIT 0x20000000
+#define SLIC_GMCR_FULLD 0x10000000
+#define SLIC_GMCR_GAPBB_SHIFT 14
+#define SLIC_GMCR_GAPR1_SHIFT 7
+#define SLIC_GMCR_GAPR2_SHIFT 0
+#define SLIC_GMCR_GAPBB_1000 0x60
+#define SLIC_GMCR_GAPR1_1000 0x2C
+#define SLIC_GMCR_GAPR2_1000 0x40
+#define SLIC_GMCR_GAPBB_100 0x70
+#define SLIC_GMCR_GAPR1_100 0x2C
+#define SLIC_GMCR_GAPR2_100 0x40
+
+#define SLIC_XCR_RESET 0x80000000
+#define SLIC_XCR_XMTEN 0x40000000
+#define SLIC_XCR_PAUSEEN 0x20000000
+#define SLIC_XCR_LOADRNG 0x10000000
+
+#define SLIC_GXCR_RESET 0x80000000
+#define SLIC_GXCR_XMTEN 0x40000000
+#define SLIC_GXCR_PAUSEEN 0x20000000
+
+#define SLIC_GRCR_RESET 0x80000000
+#define SLIC_GRCR_RCVEN 0x40000000
+#define SLIC_GRCR_RCVALL 0x20000000
+#define SLIC_GRCR_RCVBAD 0x10000000
+#define SLIC_GRCR_CTLEN 0x08000000
+#define SLIC_GRCR_ADDRAEN 0x02000000
+#define SLIC_GRCR_HASHSIZE_SHIFT 17
+#define SLIC_GRCR_HASHSIZE 14
+
+/* Reset Register */
+#define SLIC_REG_RESET 0x0000
+/* Interrupt Control Register */
+#define SLIC_REG_ICR 0x0008
+/* Interrupt status pointer */
+#define SLIC_REG_ISP 0x0010
+/* Interrupt status */
+#define SLIC_REG_ISR 0x0018
+/* Header buffer address reg
+ * 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_REG_HBAR 0x0020
+/* Data buffer handle & address reg
+ * 4 sets of registers; Buffers are 2K bytes long 2 per 4K page.
+ */
+#define SLIC_REG_DBAR 0x0028
+/* 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
+ */
+#define SLIC_REG_CBAR 0x0030
+/* Write control store */
+#define SLIC_REG_WCS 0x0034
+/*Response buffer address reg.
+ * 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_REG_RBAR 0x0038
+/* Read statistics (UPR) */
+#define SLIC_REG_RSTAT 0x0040
+/* Read link status */
+#define SLIC_REG_LSTAT 0x0048
+/* Write Mac Config */
+#define SLIC_REG_WMCFG 0x0050
+/* Write phy register */
+#define SLIC_REG_WPHY 0x0058
+/* Rcv Cmd buf addr reg */
+#define SLIC_REG_RCBAR 0x0060
+/* Read SLIC Config*/
+#define SLIC_REG_RCONFIG 0x0068
+/* Interrupt aggregation time */
+#define SLIC_REG_INTAGG 0x0070
+/* Write XMIT config reg */
+#define SLIC_REG_WXCFG 0x0078
+/* Write RCV config reg */
+#define SLIC_REG_WRCFG 0x0080
+/* Write rcv addr a low */
+#define SLIC_REG_WRADDRAL 0x0088
+/* Write rcv addr a high */
+#define SLIC_REG_WRADDRAH 0x0090
+/* Write rcv addr b low */
+#define SLIC_REG_WRADDRBL 0x0098
+/* Write rcv addr b high */
+#define SLIC_REG_WRADDRBH 0x00a0
+/* Low bits of mcast mask */
+#define SLIC_REG_MCASTLOW 0x00a8
+/* High bits of mcast mask */
+#define SLIC_REG_MCASTHIGH 0x00b0
+/* Ping the card */
+#define SLIC_REG_PING 0x00b8
+/* Dump command */
+#define SLIC_REG_DUMP_CMD 0x00c0
+/* Dump data pointer */
+#define SLIC_REG_DUMP_DATA 0x00c8
+/* Read card's pci_status register */
+#define SLIC_REG_PCISTATUS 0x00d0
+/* Write hostid field */
+#define SLIC_REG_WRHOSTID 0x00d8
+/* Put card in a low power state */
+#define SLIC_REG_LOW_POWER 0x00e0
+/* Force slic into quiescent state before soft reset */
+#define SLIC_REG_QUIESCE 0x00e8
+/* Reset interface queues */
+#define SLIC_REG_RESET_IFACE 0x00f0
+/* Register is only written when it has changed.
+ * Bits 63-32 for host i/f addrs.
+ */
+#define SLIC_REG_ADDR_UPPER 0x00f8
+/* 64 bit Header buffer address reg */
+#define SLIC_REG_HBAR64 0x0100
+/* 64 bit Data buffer handle & address reg */
+#define SLIC_REG_DBAR64 0x0108
+/* 64 bit Xmt Cmd buf addr regs. */
+#define SLIC_REG_CBAR64 0x0110
+/* 64 bit Response buffer address reg.*/
+#define SLIC_REG_RBAR64 0x0118
+/* 64 bit Rcv Cmd buf addr reg*/
+#define SLIC_REG_RCBAR64 0x0120
+/* Read statistics (64 bit UPR) */
+#define SLIC_REG_RSTAT64 0x0128
+/* Download Gigabit RCV sequencer ucode */
+#define SLIC_REG_RCV_WCS 0x0130
+/* Write VlanId field */
+#define SLIC_REG_WRVLANID 0x0138
+/* Read Transformer info */
+#define SLIC_REG_READ_XF_INFO 0x0140
+/* Write Transformer info */
+#define SLIC_REG_WRITE_XF_INFO 0x0148
+/* Write card ticks per second */
+#define SLIC_REG_TICKS_PER_SEC 0x0170
+#define SLIC_REG_HOSTID 0x1554
+
+#define PCI_VENDOR_ID_ALACRITECH 0x139A
+#define PCI_DEVICE_ID_ALACRITECH_MOJAVE 0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1 0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1_2 0x0006
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1F 0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_CICADA 0x0008
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001T 0x2006
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001F 0x2007
+#define PCI_DEVICE_ID_ALACRITECH_OASIS 0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XT 0x000B
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF 0x000C
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XT 0x000D
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF 0x000E
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF 0x000F
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104ET 0x0010
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF 0x0011
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102ET 0x0012
+
+/* Note: power of two required for number descriptors */
+#define SLIC_NUM_RX_LES 256
+#define SLIC_RX_BUFF_SIZE 2048
+#define SLIC_RX_BUFF_ALIGN 256
+#define SLIC_RX_BUFF_HDR_SIZE 34
+#define SLIC_MAX_REQ_RX_DESCS 1
+
+#define SLIC_NUM_TX_DESCS 256
+#define SLIC_TX_DESC_ALIGN 32
+#define SLIC_MIN_TX_WAKEUP_DESCS 10
+#define SLIC_MAX_REQ_TX_DESCS 1
+#define SLIC_MAX_TX_COMPLETIONS 100
+
+#define SLIC_NUM_STAT_DESCS 128
+#define SLIC_STATS_DESC_ALIGN 256
+
+#define SLIC_NUM_STAT_DESC_ARRAYS 4
+#define SLIC_INVALID_STAT_DESC_IDX 0xffffffff
+
+#define SLIC_NAPI_WEIGHT 64
+
+#define SLIC_UPR_LSTAT 0
+#define SLIC_UPR_CONFIG 1
+
+#define SLIC_EEPROM_SIZE 128
+#define SLIC_EEPROM_MAGIC 0xa5a5
+
+#define SLIC_FIRMWARE_MOJAVE "slicoss/gbdownload.sys"
+#define SLIC_FIRMWARE_OASIS "slicoss/oasisdownload.sys"
+#define SLIC_RCV_FIRMWARE_MOJAVE "slicoss/gbrcvucode.sys"
+#define SLIC_RCV_FIRMWARE_OASIS "slicoss/oasisrcvucode.sys"
+#define SLIC_FIRMWARE_MIN_SIZE 64
+#define SLIC_FIRMWARE_MAX_SECTIONS 3
+
+#define SLIC_MODEL_MOJAVE 0
+#define SLIC_MODEL_OASIS 1
+
+#define SLIC_INC_STATS_COUNTER(st, counter) \
+do { \
+ u64_stats_update_begin(&(st)->syncp); \
+ (st)->counter++; \
+ u64_stats_update_end(&(st)->syncp); \
+} while (0)
+
+#define SLIC_GET_STATS_COUNTER(newst, st, counter) \
+{ \
+ unsigned int start; \
+ do { \
+ start = u64_stats_fetch_begin_irq(&(st)->syncp); \
+ newst = (st)->counter; \
+ } while (u64_stats_fetch_retry_irq(&(st)->syncp, start)); \
+}
+
+struct slic_upr {
+ dma_addr_t paddr;
+ unsigned int type;
+ struct list_head list;
+};
+
+struct slic_upr_list {
+ bool pending;
+ struct list_head list;
+ /* upr list lock */
+ spinlock_t lock;
+};
+
+/* SLIC EEPROM structure for Mojave */
+struct slic_mojave_eeprom {
+ __le16 id; /* 00 EEPROM/FLASH Magic code 'A5A5'*/
+ __le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+ __le16 flash_size; /* 02 Flash size */
+ __le16 eeprom_size; /* 03 EEPROM Size */
+ __le16 vendor_id; /* 04 Vendor ID */
+ __le16 dev_id; /* 05 Device ID */
+ u8 rev_id; /* 06 Revision ID */
+ u8 class_code[3]; /* 07 Class Code */
+ u8 irqpin_dbg; /* 08 Debug Interrupt pin */
+ u8 irqpin; /* Network Interrupt Pin */
+ u8 min_grant; /* 09 Minimum grant */
+ u8 max_lat; /* Maximum Latency */
+ __le16 pci_stat; /* 10 PCI Status */
+ __le16 sub_vendor_id; /* 11 Subsystem Vendor Id */
+ __le16 sub_id; /* 12 Subsystem ID */
+ __le16 dev_id_dbg; /* 13 Debug Device Id */
+ __le16 ramrom; /* 14 Dram/Rom function */
+ __le16 dram_size2pci; /* 15 DRAM size to PCI (bytes * 64K) */
+ __le16 rom_size2pci; /* 16 ROM extension size to PCI (bytes * 4k) */
+ u8 pad[2]; /* 17 Padding */
+ u8 freetime; /* 18 FreeTime setting */
+ u8 ifctrl; /* 10-bit interface control (Mojave only) */
+ __le16 dram_size; /* 19 DRAM size (bytes * 64k) */
+ u8 mac[ETH_ALEN]; /* 20 MAC addresses */
+ u8 mac2[ETH_ALEN];
+ u8 pad2[6];
+ u16 dev_id2; /* Device ID for 2nd PCI function */
+ u8 irqpin2; /* Interrupt pin for 2nd PCI function */
+ u8 class_code2[3]; /* Class Code for 2nd PCI function */
+ u16 cfg_byte6; /* Config Byte 6 */
+ u16 pme_cap; /* Power Mgment capabilities */
+ u16 nwclk_ctrl; /* NetworkClockControls */
+ u8 fru_format; /* Alacritech FRU format type */
+ u8 fru_assembly[6]; /* Alacritech FRU information */
+ u8 fru_rev[2];
+ u8 fru_serial[14];
+ u8 fru_pad[3];
+ u8 oem_fru[28]; /* optional OEM FRU format type */
+ u8 pad3[4]; /* Pad to 128 bytes - includes 2 cksum bytes
+ * (if OEM FRU info exists) and two unusable
+ * bytes at the end
+ */
+};
+
+/* SLIC EEPROM structure for Oasis */
+struct slic_oasis_eeprom {
+ __le16 id; /* 00 EEPROM/FLASH Magic code 'A5A5' */
+ __le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+ __le16 spidev0_cfg; /* 02 Flash Config for SPI device 0 */
+ __le16 spidev1_cfg; /* 03 Flash Config for SPI device 1 */
+ __le16 vendor_id; /* 04 Vendor ID */
+ __le16 dev_id; /* 05 Device ID (function 0) */
+ u8 rev_id; /* 06 Revision ID */
+ u8 class_code0[3]; /* 07 Class Code for PCI function 0 */
+ u8 irqpin1; /* 08 Interrupt pin for PCI function 1*/
+ u8 class_code1[3]; /* 09 Class Code for PCI function 1 */
+ u8 irqpin2; /* 10 Interrupt pin for PCI function 2*/
+ u8 irqpin0; /* Interrupt pin for PCI function 0*/
+ u8 min_grant; /* 11 Minimum grant */
+ u8 max_lat; /* Maximum Latency */
+ __le16 sub_vendor_id; /* 12 Subsystem Vendor Id */
+ __le16 sub_id; /* 13 Subsystem ID */
+ __le16 flash_size; /* 14 Flash size (bytes / 4K) */
+ __le16 dram_size2pci; /* 15 DRAM size to PCI (bytes / 64K) */
+ __le16 rom_size2pci; /* 16 Flash (ROM extension) size to PCI
+ * (bytes / 4K)
+ */
+ __le16 dev_id1; /* 17 Device Id (function 1) */
+ __le16 dev_id2; /* 18 Device Id (function 2) */
+ __le16 dev_stat_cfg; /* 19 Device Status Config Bytes 6-7 */
+ __le16 pme_cap; /* 20 Power Mgment capabilities */
+ u8 msi_cap; /* 21 MSI capabilities */
+ u8 clock_div; /* Clock divider */
+ __le16 pci_stat_lo; /* 22 PCI Status bits 15:0 */
+ __le16 pci_stat_hi; /* 23 PCI Status bits 31:16 */
+ __le16 dram_cfg_lo; /* 24 DRAM Configuration bits 15:0 */
+ __le16 dram_cfg_hi; /* 25 DRAM Configuration bits 31:16 */
+ __le16 dram_size; /* 26 DRAM size (bytes / 64K) */
+ __le16 gpio_tbi_ctrl; /* 27 GPIO/TBI controls for functions 1/0 */
+ __le16 eeprom_size; /* 28 EEPROM Size */
+ u8 mac[ETH_ALEN]; /* 29 MAC addresses (2 ports) */
+ u8 mac2[ETH_ALEN];
+ u8 fru_format; /* 35 Alacritech FRU format type */
+ u8 fru_assembly[6]; /* Alacritech FRU information */
+ u8 fru_rev[2];
+ u8 fru_serial[14];
+ u8 fru_pad[3];
+ u8 oem_fru[28]; /* optional OEM FRU information */
+ u8 pad[4]; /* Pad to 128 bytes - includes 2 checksum bytes
+ * (if OEM FRU info exists) and two unusable
+ * bytes at the end
+ */
+};
+
+struct slic_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 rx_mcasts;
+ u64 rx_errors;
+ u64 tx_packets;
+ u64 tx_bytes;
+ /* HW STATS */
+ u64 rx_buff_miss;
+ u64 tx_dropped;
+ u64 irq_errs;
+ /* transport layer */
+ u64 rx_tpcsum;
+ u64 rx_tpoflow;
+ u64 rx_tphlen;
+ /* ip layer */
+ u64 rx_ipcsum;
+ u64 rx_iplen;
+ u64 rx_iphlen;
+ /* link layer */
+ u64 rx_early;
+ u64 rx_buffoflow;
+ u64 rx_lcode;
+ u64 rx_drbl;
+ u64 rx_crc;
+ u64 rx_oflow802;
+ u64 rx_uflow802;
+ /* oasis only */
+ u64 tx_carrier;
+ struct u64_stats_sync syncp;
+};
+
+struct slic_shmem_data {
+ __le32 isr;
+ __le32 link;
+};
+
+struct slic_shmem {
+ dma_addr_t isr_paddr;
+ dma_addr_t link_paddr;
+ struct slic_shmem_data *shmem_data;
+};
+
+struct slic_rx_info_oasis {
+ __le32 frame_status;
+ __le32 frame_status_b;
+ __le32 time_stamp;
+ __le32 checksum;
+};
+
+struct slic_rx_info_mojave {
+ __le32 frame_status;
+ __le16 byte_cnt;
+ __le16 tp_chksum;
+ __le16 ctx_hash;
+ __le16 mac_hash;
+ __le16 buff_lnk;
+};
+
+struct slic_stat_desc {
+ __le32 hnd;
+ __u8 pad[8];
+ __le32 status;
+ __u8 pad2[16];
+};
+
+struct slic_stat_queue {
+ struct slic_stat_desc *descs[SLIC_NUM_STAT_DESC_ARRAYS];
+ dma_addr_t paddr[SLIC_NUM_STAT_DESC_ARRAYS];
+ unsigned int addr_offset[SLIC_NUM_STAT_DESC_ARRAYS];
+ unsigned int active_array;
+ unsigned int len;
+ unsigned int done_idx;
+ size_t mem_size;
+};
+
+struct slic_tx_desc {
+ __le32 hnd;
+ __le32 rsvd;
+ u8 cmd;
+ u8 flags;
+ __le16 rsvd2;
+ __le32 totlen;
+ __le32 paddrl;
+ __le32 paddrh;
+ __le32 len;
+ __le32 type;
+};
+
+struct slic_tx_buffer {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(map_addr);
+ DEFINE_DMA_UNMAP_LEN(map_len);
+ struct slic_tx_desc *desc;
+ dma_addr_t desc_paddr;
+};
+
+struct slic_tx_queue {
+ struct dma_pool *dma_pool;
+ struct slic_tx_buffer *txbuffs;
+ unsigned int len;
+ unsigned int put_idx;
+ unsigned int done_idx;
+};
+
+struct slic_rx_desc {
+ u8 pad[16];
+ __le32 buffer;
+ __le32 length;
+ __le32 status;
+};
+
+struct slic_rx_buffer {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(map_addr);
+ DEFINE_DMA_UNMAP_LEN(map_len);
+ unsigned int addr_offset;
+};
+
+struct slic_rx_queue {
+ struct slic_rx_buffer *rxbuffs;
+ unsigned int len;
+ unsigned int done_idx;
+ unsigned int put_idx;
+};
+
+struct slic_device {
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ void __iomem *regs;
+ /* upper address setting lock */
+ spinlock_t upper_lock;
+ struct slic_shmem shmem;
+ struct napi_struct napi;
+ struct slic_rx_queue rxq;
+ struct slic_tx_queue txq;
+ struct slic_stat_queue stq;
+ struct slic_stats stats;
+ struct slic_upr_list upr_list;
+ /* link configuration lock */
+ spinlock_t link_lock;
+ bool promisc;
+ int speed;
+ unsigned int duplex;
+ bool is_fiber;
+ unsigned char model;
+};
+
+static inline u32 slic_read(struct slic_device *sdev, unsigned int reg)
+{
+ return ioread32(sdev->regs + reg);
+}
+
+static inline void slic_write(struct slic_device *sdev, unsigned int reg,
+ u32 val)
+{
+ iowrite32(val, sdev->regs + reg);
+}
+
+static inline void slic_flush_write(struct slic_device *sdev)
+{
+ (void)ioread32(sdev->regs + SLIC_REG_HOSTID);
+}
+
+#endif /* _SLIC_H */
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
new file mode 100644
index 000000000000..b9fbd0107008
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -0,0 +1,1871 @@
+/*
+ * Driver for Gigabit Ethernet adapters based on the Session Layer
+ * Interface (SLIC) technology by Alacritech. The driver does not
+ * support the hardware acceleration features provided by these cards.
+ *
+ * Copyright (C) 2016 Lino Sanfilippo <LinoSanfilippo@gmx.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#include "slic.h"
+
+#define DRV_NAME "slicoss"
+#define DRV_VERSION "1.0"
+
+static const struct pci_device_id slic_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+ PCI_DEVICE_ID_ALACRITECH_MOJAVE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+ PCI_DEVICE_ID_ALACRITECH_OASIS) },
+ { 0 }
+};
+
+static const char slic_stats_strings[][ETH_GSTRING_LEN] = {
+ "rx_packets",
+ "rx_bytes",
+ "rx_multicasts",
+ "rx_errors",
+ "rx_buff_miss",
+ "rx_tp_csum",
+ "rx_tp_oflow",
+ "rx_tp_hlen",
+ "rx_ip_csum",
+ "rx_ip_len",
+ "rx_ip_hdr_len",
+ "rx_early",
+ "rx_buff_oflow",
+ "rx_lcode",
+ "rx_drbl",
+ "rx_crc",
+ "rx_oflow_802",
+ "rx_uflow_802",
+ "tx_packets",
+ "tx_bytes",
+ "tx_carrier",
+ "tx_dropped",
+ "irq_errs",
+};
+
+static inline int slic_next_queue_idx(unsigned int idx, unsigned int qlen)
+{
+ return (idx + 1) & (qlen - 1);
+}
+
+static inline int slic_get_free_queue_descs(unsigned int put_idx,
+ unsigned int done_idx,
+ unsigned int qlen)
+{
+ if (put_idx >= done_idx)
+ return (qlen - (put_idx - done_idx) - 1);
+ return (done_idx - put_idx - 1);
+}
+
+static unsigned int slic_next_compl_idx(struct slic_device *sdev)
+{
+ struct slic_stat_queue *stq = &sdev->stq;
+ unsigned int active = stq->active_array;
+ struct slic_stat_desc *descs;
+ struct slic_stat_desc *stat;
+ unsigned int idx;
+
+ descs = stq->descs[active];
+ stat = &descs[stq->done_idx];
+
+ if (!stat->status)
+ return SLIC_INVALID_STAT_DESC_IDX;
+
+ idx = (le32_to_cpu(stat->hnd) & 0xffff) - 1;
+ /* reset desc */
+ stat->hnd = 0;
+ stat->status = 0;
+
+ stq->done_idx = slic_next_queue_idx(stq->done_idx, stq->len);
+ /* check for wraparound */
+ if (!stq->done_idx) {
+ dma_addr_t paddr = stq->paddr[active];
+
+ slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+ stq->len);
+ /* make sure new status descriptors are immediately available */
+ slic_flush_write(sdev);
+ active++;
+ active &= (SLIC_NUM_STAT_DESC_ARRAYS - 1);
+ stq->active_array = active;
+ }
+ return idx;
+}
+
+static unsigned int slic_get_free_tx_descs(struct slic_tx_queue *txq)
+{
+ /* ensure tail idx is updated */
+ smp_mb();
+ return slic_get_free_queue_descs(txq->put_idx, txq->done_idx, txq->len);
+}
+
+static unsigned int slic_get_free_rx_descs(struct slic_rx_queue *rxq)
+{
+ return slic_get_free_queue_descs(rxq->put_idx, rxq->done_idx, rxq->len);
+}
+
+static void slic_clear_upr_list(struct slic_upr_list *upr_list)
+{
+ struct slic_upr *upr;
+ struct slic_upr *tmp;
+
+ spin_lock_bh(&upr_list->lock);
+ list_for_each_entry_safe(upr, tmp, &upr_list->list, list) {
+ list_del(&upr->list);
+ kfree(upr);
+ }
+ upr_list->pending = false;
+ spin_unlock_bh(&upr_list->lock);
+}
+
+static void slic_start_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+ u32 reg;
+
+ reg = (upr->type == SLIC_UPR_CONFIG) ? SLIC_REG_RCONFIG :
+ SLIC_REG_LSTAT;
+ slic_write(sdev, reg, lower_32_bits(upr->paddr));
+ slic_flush_write(sdev);
+}
+
+static void slic_queue_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+ struct slic_upr_list *upr_list = &sdev->upr_list;
+ bool pending;
+
+ spin_lock_bh(&upr_list->lock);
+ pending = upr_list->pending;
+ INIT_LIST_HEAD(&upr->list);
+ list_add_tail(&upr->list, &upr_list->list);
+ upr_list->pending = true;
+ spin_unlock_bh(&upr_list->lock);
+
+ if (!pending)
+ slic_start_upr(sdev, upr);
+}
+
+static struct slic_upr *slic_dequeue_upr(struct slic_device *sdev)
+{
+ struct slic_upr_list *upr_list = &sdev->upr_list;
+ struct slic_upr *next_upr = NULL;
+ struct slic_upr *upr = NULL;
+
+ spin_lock_bh(&upr_list->lock);
+ if (!list_empty(&upr_list->list)) {
+ upr = list_first_entry(&upr_list->list, struct slic_upr, list);
+ list_del(&upr->list);
+
+ if (list_empty(&upr_list->list))
+ upr_list->pending = false;
+ else
+ next_upr = list_first_entry(&upr_list->list,
+ struct slic_upr, list);
+ }
+ spin_unlock_bh(&upr_list->lock);
+ /* trigger processing of the next upr in list */
+ if (next_upr)
+ slic_start_upr(sdev, next_upr);
+
+ return upr;
+}
+
+static int slic_new_upr(struct slic_device *sdev, unsigned int type,
+ dma_addr_t paddr)
+{
+ struct slic_upr *upr;
+
+ upr = kmalloc(sizeof(*upr), GFP_ATOMIC);
+ if (!upr)
+ return -ENOMEM;
+ upr->type = type;
+ upr->paddr = paddr;
+
+ slic_queue_upr(sdev, upr);
+
+ return 0;
+}
+
+static void slic_set_mcast_bit(u64 *mcmask, unsigned char const *addr)
+{
+ u64 mask = *mcmask;
+ u8 crc;
+ /* 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.
+ */
+ crc = ether_crc(ETH_ALEN, addr) >> 23;
+ /* we only have space on the SLIC for 64 entries */
+ crc &= 0x3F;
+ mask |= (u64)1 << crc;
+ *mcmask = mask;
+}
+
+/* must be called with link_lock held */
+static void slic_configure_rcv(struct slic_device *sdev)
+{
+ u32 val;
+
+ val = SLIC_GRCR_RESET | SLIC_GRCR_ADDRAEN | SLIC_GRCR_RCVEN |
+ SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT | SLIC_GRCR_RCVBAD;
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GRCR_CTLEN;
+
+ if (sdev->promisc)
+ val |= SLIC_GRCR_RCVALL;
+
+ slic_write(sdev, SLIC_REG_WRCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_xmt(struct slic_device *sdev)
+{
+ u32 val;
+
+ val = SLIC_GXCR_RESET | SLIC_GXCR_XMTEN;
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GXCR_PAUSEEN;
+
+ slic_write(sdev, SLIC_REG_WXCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_mac(struct slic_device *sdev)
+{
+ u32 val;
+
+ if (sdev->speed == SPEED_1000) {
+ val = SLIC_GMCR_GAPBB_1000 << SLIC_GMCR_GAPBB_SHIFT |
+ SLIC_GMCR_GAPR1_1000 << SLIC_GMCR_GAPR1_SHIFT |
+ SLIC_GMCR_GAPR2_1000 << SLIC_GMCR_GAPR2_SHIFT |
+ SLIC_GMCR_GBIT; /* enable GMII */
+ } else {
+ val = SLIC_GMCR_GAPBB_100 << SLIC_GMCR_GAPBB_SHIFT |
+ SLIC_GMCR_GAPR1_100 << SLIC_GMCR_GAPR1_SHIFT |
+ SLIC_GMCR_GAPR2_100 << SLIC_GMCR_GAPR2_SHIFT;
+ }
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GMCR_FULLD;
+
+ slic_write(sdev, SLIC_REG_WMCFG, val);
+}
+
+static void slic_configure_link_locked(struct slic_device *sdev, int speed,
+ unsigned int duplex)
+{
+ struct net_device *dev = sdev->netdev;
+
+ if (sdev->speed == speed && sdev->duplex == duplex)
+ return;
+
+ sdev->speed = speed;
+ sdev->duplex = duplex;
+
+ if (sdev->speed == SPEED_UNKNOWN) {
+ if (netif_carrier_ok(dev))
+ netif_carrier_off(dev);
+ } else {
+ /* (re)configure link settings */
+ slic_configure_mac(sdev);
+ slic_configure_xmt(sdev);
+ slic_configure_rcv(sdev);
+ slic_flush_write(sdev);
+
+ if (!netif_carrier_ok(dev))
+ netif_carrier_on(dev);
+ }
+}
+
+static void slic_configure_link(struct slic_device *sdev, int speed,
+ unsigned int duplex)
+{
+ spin_lock_bh(&sdev->link_lock);
+ slic_configure_link_locked(sdev, speed, duplex);
+ spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_set_rx_mode(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct netdev_hw_addr *hwaddr;
+ bool set_promisc;
+ u64 mcmask;
+
+ if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+ /* 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).
+ */
+ mcmask = ~(u64)0;
+ } else {
+ mcmask = 0;
+
+ netdev_for_each_mc_addr(hwaddr, dev) {
+ slic_set_mcast_bit(&mcmask, hwaddr->addr);
+ }
+ }
+
+ slic_write(sdev, SLIC_REG_MCASTLOW, lower_32_bits(mcmask));
+ slic_write(sdev, SLIC_REG_MCASTHIGH, upper_32_bits(mcmask));
+
+ set_promisc = !!(dev->flags & IFF_PROMISC);
+
+ spin_lock_bh(&sdev->link_lock);
+ if (sdev->promisc != set_promisc) {
+ sdev->promisc = set_promisc;
+ slic_configure_rcv(sdev);
+ /* make sure writes to receiver cant leak out of the lock */
+ mmiowb();
+ }
+ spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_xmit_complete(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct net_device *dev = sdev->netdev;
+ unsigned int idx = txq->done_idx;
+ struct slic_tx_buffer *buff;
+ unsigned int frames = 0;
+ unsigned int bytes = 0;
+
+ /* Limit processing to SLIC_MAX_TX_COMPLETIONS frames to avoid that new
+ * completions during processing keeps the loop running endlessly.
+ */
+ do {
+ idx = slic_next_compl_idx(sdev);
+ if (idx == SLIC_INVALID_STAT_DESC_IDX)
+ break;
+
+ txq->done_idx = idx;
+ buff = &txq->txbuffs[idx];
+
+ if (unlikely(!buff->skb)) {
+ netdev_warn(dev,
+ "no skb found for desc idx %i\n", idx);
+ continue;
+ }
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+
+ bytes += buff->skb->len;
+ frames++;
+
+ dev_kfree_skb_any(buff->skb);
+ buff->skb = NULL;
+ } while (frames < SLIC_MAX_TX_COMPLETIONS);
+ /* make sure xmit sees the new value for done_idx */
+ smp_wmb();
+
+ u64_stats_update_begin(&sdev->stats.syncp);
+ sdev->stats.tx_bytes += bytes;
+ sdev->stats.tx_packets += frames;
+ u64_stats_update_end(&sdev->stats.syncp);
+
+ netif_tx_lock(dev);
+ if (netif_queue_stopped(dev) &&
+ (slic_get_free_tx_descs(txq) >= SLIC_MIN_TX_WAKEUP_DESCS))
+ netif_wake_queue(dev);
+ netif_tx_unlock(dev);
+}
+
+static void slic_refill_rx_queue(struct slic_device *sdev, gfp_t gfp)
+{
+ const unsigned int ALIGN_MASK = SLIC_RX_BUFF_ALIGN - 1;
+ unsigned int maplen = SLIC_RX_BUFF_SIZE;
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct net_device *dev = sdev->netdev;
+ struct slic_rx_buffer *buff;
+ struct slic_rx_desc *desc;
+ unsigned int misalign;
+ unsigned int offset;
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+
+ while (slic_get_free_rx_descs(rxq) > SLIC_MAX_REQ_RX_DESCS) {
+ skb = alloc_skb(maplen + ALIGN_MASK, gfp);
+ if (!skb)
+ break;
+
+ paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+ netdev_err(dev, "mapping rx packet failed\n");
+ /* drop skb */
+ dev_kfree_skb_any(skb);
+ break;
+ }
+ /* ensure head buffer descriptors are 256 byte aligned */
+ offset = 0;
+ misalign = paddr & ALIGN_MASK;
+ if (misalign) {
+ offset = SLIC_RX_BUFF_ALIGN - misalign;
+ skb_reserve(skb, offset);
+ }
+ /* the HW expects dma chunks for descriptor + frame data */
+ desc = (struct slic_rx_desc *)skb->data;
+ /* temporarily sync descriptor for CPU to clear status */
+ dma_sync_single_for_cpu(&sdev->pdev->dev, paddr,
+ offset + sizeof(*desc),
+ DMA_FROM_DEVICE);
+ desc->status = 0;
+ /* return it to HW again */
+ dma_sync_single_for_device(&sdev->pdev->dev, paddr,
+ offset + sizeof(*desc),
+ DMA_FROM_DEVICE);
+
+ buff = &rxq->rxbuffs[rxq->put_idx];
+ buff->skb = skb;
+ dma_unmap_addr_set(buff, map_addr, paddr);
+ dma_unmap_len_set(buff, map_len, maplen);
+ buff->addr_offset = offset;
+ /* complete write to descriptor before it is handed to HW */
+ wmb();
+ /* head buffer descriptors are placed immediately before skb */
+ slic_write(sdev, SLIC_REG_HBAR, lower_32_bits(paddr) + offset);
+ rxq->put_idx = slic_next_queue_idx(rxq->put_idx, rxq->len);
+ }
+}
+
+static void slic_handle_frame_error(struct slic_device *sdev,
+ struct sk_buff *skb)
+{
+ struct slic_stats *stats = &sdev->stats;
+
+ if (sdev->model == SLIC_MODEL_OASIS) {
+ struct slic_rx_info_oasis *info;
+ u32 status_b;
+ u32 status;
+
+ info = (struct slic_rx_info_oasis *)skb->data;
+ status = le32_to_cpu(info->frame_status);
+ status_b = le32_to_cpu(info->frame_status_b);
+ /* transport layer */
+ if (status_b & SLIC_VRHSTATB_TPCSUM)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+ if (status & SLIC_VRHSTAT_TPOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+ if (status_b & SLIC_VRHSTATB_TPHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+ /* ip layer */
+ if (status_b & SLIC_VRHSTATB_IPCSUM)
+ SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+ if (status_b & SLIC_VRHSTATB_IPLERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+ if (status_b & SLIC_VRHSTATB_IPHERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+ /* link layer */
+ if (status_b & SLIC_VRHSTATB_RCVE)
+ SLIC_INC_STATS_COUNTER(stats, rx_early);
+ if (status_b & SLIC_VRHSTATB_BUFF)
+ SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+ if (status_b & SLIC_VRHSTATB_CODE)
+ SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+ if (status_b & SLIC_VRHSTATB_DRBL)
+ SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+ if (status_b & SLIC_VRHSTATB_CRC)
+ SLIC_INC_STATS_COUNTER(stats, rx_crc);
+ if (status & SLIC_VRHSTAT_802OE)
+ SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+ if (status_b & SLIC_VRHSTATB_802UE)
+ SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+ if (status_b & SLIC_VRHSTATB_CARRE)
+ SLIC_INC_STATS_COUNTER(stats, tx_carrier);
+ } else { /* mojave */
+ struct slic_rx_info_mojave *info;
+ u32 status;
+
+ info = (struct slic_rx_info_mojave *)skb->data;
+ status = le32_to_cpu(info->frame_status);
+ /* transport layer */
+ if (status & SLIC_VGBSTAT_XPERR) {
+ u32 xerr = status >> SLIC_VGBSTAT_XERRSHFT;
+
+ if (xerr == SLIC_VGBSTAT_XCSERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+ if (xerr == SLIC_VGBSTAT_XUFLOW)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+ if (xerr == SLIC_VGBSTAT_XHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+ }
+ /* ip layer */
+ if (status & SLIC_VGBSTAT_NETERR) {
+ u32 nerr = status >> SLIC_VGBSTAT_NERRSHFT &
+ SLIC_VGBSTAT_NERRMSK;
+
+ if (nerr == SLIC_VGBSTAT_NCSERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+ if (nerr == SLIC_VGBSTAT_NUFLOW)
+ SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+ if (nerr == SLIC_VGBSTAT_NHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+ }
+ /* link layer */
+ if (status & SLIC_VGBSTAT_LNKERR) {
+ u32 lerr = status & SLIC_VGBSTAT_LERRMSK;
+
+ if (lerr == SLIC_VGBSTAT_LDEARLY)
+ SLIC_INC_STATS_COUNTER(stats, rx_early);
+ if (lerr == SLIC_VGBSTAT_LBOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+ if (lerr == SLIC_VGBSTAT_LCODERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+ if (lerr == SLIC_VGBSTAT_LDBLNBL)
+ SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+ if (lerr == SLIC_VGBSTAT_LCRCERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_crc);
+ if (lerr == SLIC_VGBSTAT_LOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+ if (lerr == SLIC_VGBSTAT_LUFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+ }
+ }
+ SLIC_INC_STATS_COUNTER(stats, rx_errors);
+}
+
+static void slic_handle_receive(struct slic_device *sdev, unsigned int todo,
+ unsigned int *done)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct net_device *dev = sdev->netdev;
+ struct slic_rx_buffer *buff;
+ struct slic_rx_desc *desc;
+ unsigned int frames = 0;
+ unsigned int bytes = 0;
+ struct sk_buff *skb;
+ u32 status;
+ u32 len;
+
+ while (todo && (rxq->done_idx != rxq->put_idx)) {
+ buff = &rxq->rxbuffs[rxq->done_idx];
+
+ skb = buff->skb;
+ if (!skb)
+ break;
+
+ desc = (struct slic_rx_desc *)skb->data;
+
+ dma_sync_single_for_cpu(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ buff->addr_offset + sizeof(*desc),
+ DMA_FROM_DEVICE);
+
+ status = le32_to_cpu(desc->status);
+ if (!(status & SLIC_IRHDDR_SVALID)) {
+ dma_sync_single_for_device(&sdev->pdev->dev,
+ dma_unmap_addr(buff,
+ map_addr),
+ buff->addr_offset +
+ sizeof(*desc),
+ DMA_FROM_DEVICE);
+ break;
+ }
+
+ buff->skb = NULL;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len),
+ DMA_FROM_DEVICE);
+
+ /* skip rx descriptor that is placed before the frame data */
+ skb_reserve(skb, SLIC_RX_BUFF_HDR_SIZE);
+
+ if (unlikely(status & SLIC_IRHDDR_ERR)) {
+ slic_handle_frame_error(sdev, skb);
+ dev_kfree_skb_any(skb);
+ } else {
+ struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+ if (is_multicast_ether_addr(eh->h_dest))
+ SLIC_INC_STATS_COUNTER(&sdev->stats, rx_mcasts);
+
+ len = le32_to_cpu(desc->length) & SLIC_IRHDDR_FLEN_MSK;
+ skb_put(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ napi_gro_receive(&sdev->napi, skb);
+
+ bytes += len;
+ frames++;
+ }
+ rxq->done_idx = slic_next_queue_idx(rxq->done_idx, rxq->len);
+ todo--;
+ }
+
+ u64_stats_update_begin(&sdev->stats.syncp);
+ sdev->stats.rx_bytes += bytes;
+ sdev->stats.rx_packets += frames;
+ u64_stats_update_end(&sdev->stats.syncp);
+
+ slic_refill_rx_queue(sdev, GFP_ATOMIC);
+}
+
+static void slic_handle_link_irq(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ unsigned int duplex;
+ int speed;
+ u32 link;
+
+ link = le32_to_cpu(sm_data->link);
+
+ if (link & SLIC_GIG_LINKUP) {
+ if (link & SLIC_GIG_SPEED_1000)
+ speed = SPEED_1000;
+ else if (link & SLIC_GIG_SPEED_100)
+ speed = SPEED_100;
+ else
+ speed = SPEED_10;
+
+ duplex = (link & SLIC_GIG_FULLDUPLEX) ? DUPLEX_FULL :
+ DUPLEX_HALF;
+ } else {
+ duplex = DUPLEX_UNKNOWN;
+ speed = SPEED_UNKNOWN;
+ }
+ slic_configure_link(sdev, speed, duplex);
+}
+
+static void slic_handle_upr_irq(struct slic_device *sdev, u32 irqs)
+{
+ struct slic_upr *upr;
+
+ /* remove upr that caused this irq (always the first entry in list) */
+ upr = slic_dequeue_upr(sdev);
+ if (!upr) {
+ netdev_warn(sdev->netdev, "no upr found on list\n");
+ return;
+ }
+
+ if (upr->type == SLIC_UPR_LSTAT) {
+ if (unlikely(irqs & SLIC_ISR_UPCERR_MASK)) {
+ /* try again */
+ slic_queue_upr(sdev, upr);
+ return;
+ }
+ slic_handle_link_irq(sdev);
+ }
+ kfree(upr);
+}
+
+static int slic_handle_link_change(struct slic_device *sdev)
+{
+ return slic_new_upr(sdev, SLIC_UPR_LSTAT, sdev->shmem.link_paddr);
+}
+
+static void slic_handle_err_irq(struct slic_device *sdev, u32 isr)
+{
+ struct slic_stats *stats = &sdev->stats;
+
+ if (isr & SLIC_ISR_RMISS)
+ SLIC_INC_STATS_COUNTER(stats, rx_buff_miss);
+ if (isr & SLIC_ISR_XDROP)
+ SLIC_INC_STATS_COUNTER(stats, tx_dropped);
+ if (!(isr & (SLIC_ISR_RMISS | SLIC_ISR_XDROP)))
+ SLIC_INC_STATS_COUNTER(stats, irq_errs);
+}
+
+static void slic_handle_irq(struct slic_device *sdev, u32 isr,
+ unsigned int todo, unsigned int *done)
+{
+ if (isr & SLIC_ISR_ERR)
+ slic_handle_err_irq(sdev, isr);
+
+ if (isr & SLIC_ISR_LEVENT)
+ slic_handle_link_change(sdev);
+
+ if (isr & SLIC_ISR_UPC_MASK)
+ slic_handle_upr_irq(sdev, isr);
+
+ if (isr & SLIC_ISR_RCV)
+ slic_handle_receive(sdev, todo, done);
+
+ if (isr & SLIC_ISR_CMD)
+ slic_xmit_complete(sdev);
+}
+
+static int slic_poll(struct napi_struct *napi, int todo)
+{
+ struct slic_device *sdev = container_of(napi, struct slic_device, napi);
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ u32 isr = le32_to_cpu(sm_data->isr);
+ int done = 0;
+
+ slic_handle_irq(sdev, isr, todo, &done);
+
+ if (done < todo) {
+ napi_complete_done(napi, done);
+ /* reenable irqs */
+ sm_data->isr = 0;
+ /* make sure sm_data->isr is cleard before irqs are reenabled */
+ wmb();
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+ }
+
+ return done;
+}
+
+static irqreturn_t slic_irq(int irq, void *dev_id)
+{
+ struct slic_device *sdev = dev_id;
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_MASK);
+ slic_flush_write(sdev);
+ /* make sure sm_data->isr is read after ICR_INT_MASK is set */
+ wmb();
+
+ if (!sm_data->isr) {
+ dma_rmb();
+ /* spurious interrupt */
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+ return IRQ_NONE;
+ }
+
+ napi_schedule_irqoff(&sdev->napi);
+
+ return IRQ_HANDLED;
+}
+
+static void slic_card_reset(struct slic_device *sdev)
+{
+ u16 cmd;
+
+ slic_write(sdev, SLIC_REG_RESET, SLIC_RESET_MAGIC);
+ /* flush write by means of config space */
+ pci_read_config_word(sdev->pdev, PCI_COMMAND, &cmd);
+ mdelay(1);
+}
+
+static int slic_init_stat_queue(struct slic_device *sdev)
+{
+ const unsigned int DESC_ALIGN_MASK = SLIC_STATS_DESC_ALIGN - 1;
+ struct slic_stat_queue *stq = &sdev->stq;
+ struct slic_stat_desc *descs;
+ unsigned int misalign;
+ unsigned int offset;
+ dma_addr_t paddr;
+ size_t size;
+ int err;
+ int i;
+
+ stq->len = SLIC_NUM_STAT_DESCS;
+ stq->active_array = 0;
+ stq->done_idx = 0;
+
+ size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
+
+ for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+ descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
+ GFP_KERNEL);
+ if (!descs) {
+ netdev_err(sdev->netdev,
+ "failed to allocate status descriptors\n");
+ err = -ENOMEM;
+ goto free_descs;
+ }
+ /* ensure correct alignment */
+ offset = 0;
+ misalign = paddr & DESC_ALIGN_MASK;
+ if (misalign) {
+ offset = SLIC_STATS_DESC_ALIGN - misalign;
+ descs += offset;
+ paddr += offset;
+ }
+
+ slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+ stq->len);
+ stq->descs[i] = descs;
+ stq->paddr[i] = paddr;
+ stq->addr_offset[i] = offset;
+ }
+
+ stq->mem_size = size;
+
+ return 0;
+
+free_descs:
+ while (i--) {
+ dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+ stq->descs[i] - stq->addr_offset[i],
+ stq->paddr[i] - stq->addr_offset[i]);
+ }
+
+ return err;
+}
+
+static void slic_free_stat_queue(struct slic_device *sdev)
+{
+ struct slic_stat_queue *stq = &sdev->stq;
+ int i;
+
+ for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+ dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+ stq->descs[i] - stq->addr_offset[i],
+ stq->paddr[i] - stq->addr_offset[i]);
+ }
+}
+
+static int slic_init_tx_queue(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ struct slic_tx_desc *desc;
+ unsigned int i;
+ int err;
+
+ txq->len = SLIC_NUM_TX_DESCS;
+ txq->put_idx = 0;
+ txq->done_idx = 0;
+
+ txq->txbuffs = kcalloc(txq->len, sizeof(*buff), GFP_KERNEL);
+ if (!txq->txbuffs)
+ return -ENOMEM;
+
+ txq->dma_pool = dma_pool_create("slic_pool", &sdev->pdev->dev,
+ sizeof(*desc), SLIC_TX_DESC_ALIGN,
+ 4096);
+ if (!txq->dma_pool) {
+ err = -ENOMEM;
+ netdev_err(sdev->netdev, "failed to create dma pool\n");
+ goto free_buffs;
+ }
+
+ for (i = 0; i < txq->len; i++) {
+ buff = &txq->txbuffs[i];
+ desc = dma_pool_zalloc(txq->dma_pool, GFP_KERNEL,
+ &buff->desc_paddr);
+ if (!desc) {
+ netdev_err(sdev->netdev,
+ "failed to alloc pool chunk (%i)\n", i);
+ err = -ENOMEM;
+ goto free_descs;
+ }
+
+ desc->hnd = cpu_to_le32((u32)(i + 1));
+ desc->cmd = SLIC_CMD_XMT_REQ;
+ desc->flags = 0;
+ desc->type = cpu_to_le32(SLIC_CMD_TYPE_DUMB);
+ buff->desc = desc;
+ }
+
+ return 0;
+
+free_descs:
+ while (i--) {
+ buff = &txq->txbuffs[i];
+ dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+ }
+ dma_pool_destroy(txq->dma_pool);
+
+free_buffs:
+ kfree(txq->txbuffs);
+
+ return err;
+}
+
+static void slic_free_tx_queue(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ unsigned int i;
+
+ for (i = 0; i < txq->len; i++) {
+ buff = &txq->txbuffs[i];
+ dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+ if (!buff->skb)
+ continue;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+ consume_skb(buff->skb);
+ }
+ dma_pool_destroy(txq->dma_pool);
+
+ kfree(txq->txbuffs);
+}
+
+static int slic_init_rx_queue(struct slic_device *sdev)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct slic_rx_buffer *buff;
+
+ rxq->len = SLIC_NUM_RX_LES;
+ rxq->done_idx = 0;
+ rxq->put_idx = 0;
+
+ buff = kcalloc(rxq->len, sizeof(*buff), GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ rxq->rxbuffs = buff;
+ slic_refill_rx_queue(sdev, GFP_KERNEL);
+
+ return 0;
+}
+
+static void slic_free_rx_queue(struct slic_device *sdev)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct slic_rx_buffer *buff;
+ unsigned int i;
+
+ /* free rx buffers */
+ for (i = 0; i < rxq->len; i++) {
+ buff = &rxq->rxbuffs[i];
+
+ if (!buff->skb)
+ continue;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len),
+ DMA_FROM_DEVICE);
+ consume_skb(buff->skb);
+ }
+ kfree(rxq->rxbuffs);
+}
+
+static void slic_set_link_autoneg(struct slic_device *sdev)
+{
+ unsigned int subid = sdev->pdev->subsystem_device;
+ u32 val;
+
+ if (sdev->is_fiber) {
+ /* We've got a fiber gigabit interface, and register 4 is
+ * different in fiber mode than in copper mode.
+ */
+ /* advertise FD only @1000 Mb */
+ val = MII_ADVERTISE << 16 | ADVERTISE_1000XFULL |
+ ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ /* enable PAUSE frames */
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ /* reset phy, enable auto-neg */
+ val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+ BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ } else { /* copper gigabit */
+ /* We've got a copper gigabit interface, and register 4 is
+ * different in copper mode than in fiber mode.
+ */
+ /* advertise 10/100 Mb modes */
+ val = MII_ADVERTISE << 16 | ADVERTISE_100FULL |
+ ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF;
+ /* enable PAUSE frames */
+ val |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ /* required by the Cicada PHY */
+ val |= ADVERTISE_CSMA;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ /* advertise FD only @1000 Mb */
+ val = MII_CTRL1000 << 16 | ADVERTISE_1000FULL;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ if (subid != PCI_SUBDEVICE_ID_ALACRITECH_CICADA) {
+ /* if a Marvell PHY enable auto crossover */
+ val = SLIC_MIICR_REG_16 | SLIC_MRV_REG16_XOVERON;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ /* reset phy, enable auto-neg */
+ val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+ BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ } else {
+ /* enable and restart auto-neg (don't reset) */
+ val = MII_BMCR << 16 | BMCR_ANENABLE | BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ }
+ }
+}
+
+static void slic_set_mac_address(struct slic_device *sdev)
+{
+ u8 *addr = sdev->netdev->dev_addr;
+ u32 val;
+
+ val = addr[5] | addr[4] << 8 | addr[3] << 16 | addr[2] << 24;
+
+ slic_write(sdev, SLIC_REG_WRADDRAL, val);
+ slic_write(sdev, SLIC_REG_WRADDRBL, val);
+
+ val = addr[0] << 8 | addr[1];
+
+ slic_write(sdev, SLIC_REG_WRADDRAH, val);
+ slic_write(sdev, SLIC_REG_WRADDRBH, val);
+ slic_flush_write(sdev);
+}
+
+static u32 slic_read_dword_from_firmware(const struct firmware *fw, int *offset)
+{
+ int idx = *offset;
+ __le32 val;
+
+ memcpy(&val, fw->data + *offset, sizeof(val));
+ idx += 4;
+ *offset = idx;
+
+ return le32_to_cpu(val);
+}
+
+MODULE_FIRMWARE(SLIC_RCV_FIRMWARE_MOJAVE);
+MODULE_FIRMWARE(SLIC_RCV_FIRMWARE_OASIS);
+
+static int slic_load_rcvseq_firmware(struct slic_device *sdev)
+{
+ const struct firmware *fw;
+ const char *file;
+ u32 codelen;
+ int idx = 0;
+ u32 instr;
+ u32 addr;
+ int err;
+
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_RCV_FIRMWARE_OASIS :
+ SLIC_RCV_FIRMWARE_MOJAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+ if (err) {
+ dev_err(&sdev->pdev->dev,
+ "failed to load receive sequencer firmware %s\n", file);
+ return err;
+ }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+ if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (min %u expected)\n",
+ fw->size, SLIC_FIRMWARE_MIN_SIZE);
+ err = -EINVAL;
+ goto release;
+ }
+
+ codelen = slic_read_dword_from_firmware(fw, &idx);
+
+ /* do another sanity check against firmware size */
+ if ((codelen + 4) > fw->size) {
+ dev_err(&sdev->pdev->dev,
+ "invalid rcv-sequencer firmware size %zu\n", fw->size);
+ err = -EINVAL;
+ goto release;
+ }
+
+ /* download sequencer code to card */
+ slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN);
+ for (addr = 0; addr < codelen; addr++) {
+ __le32 val;
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_RCV_WCS, addr);
+
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out the instruction data low addr */
+ slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+
+ val = (__le32)fw->data[idx];
+ instr = le32_to_cpu(val);
+ idx++;
+ /* write out the instruction data high addr */
+ slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+ }
+ /* finish download */
+ slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH);
+ slic_flush_write(sdev);
+release:
+ release_firmware(fw);
+
+ return err;
+}
+
+MODULE_FIRMWARE(SLIC_FIRMWARE_MOJAVE);
+MODULE_FIRMWARE(SLIC_FIRMWARE_OASIS);
+
+static int slic_load_firmware(struct slic_device *sdev)
+{
+ u32 sectstart[SLIC_FIRMWARE_MAX_SECTIONS];
+ u32 sectsize[SLIC_FIRMWARE_MAX_SECTIONS];
+ const struct firmware *fw;
+ unsigned int datalen;
+ const char *file;
+ int code_start;
+ unsigned int i;
+ u32 numsects;
+ int idx = 0;
+ u32 sect;
+ u32 instr;
+ u32 addr;
+ u32 base;
+ int err;
+
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_FIRMWARE_OASIS :
+ SLIC_FIRMWARE_MOJAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to load firmware %s\n", file);
+ return err;
+ }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+ if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (min is %u)\n", fw->size,
+ SLIC_FIRMWARE_MIN_SIZE);
+ err = -EINVAL;
+ goto release;
+ }
+
+ numsects = slic_read_dword_from_firmware(fw, &idx);
+ if (numsects == 0 || numsects > SLIC_FIRMWARE_MAX_SECTIONS) {
+ dev_err(&sdev->pdev->dev,
+ "invalid number of sections in firmware: %u", numsects);
+ err = -EINVAL;
+ goto release;
+ }
+
+ datalen = numsects * 8 + 4;
+ for (i = 0; i < numsects; i++) {
+ sectsize[i] = slic_read_dword_from_firmware(fw, &idx);
+ datalen += sectsize[i];
+ }
+
+ /* do another sanity check against firmware size */
+ if (datalen > fw->size) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (expected >= %u)\n",
+ fw->size, datalen);
+ err = -EINVAL;
+ goto release;
+ }
+ /* get sections */
+ for (i = 0; i < numsects; i++)
+ sectstart[i] = slic_read_dword_from_firmware(fw, &idx);
+
+ code_start = idx;
+ instr = slic_read_dword_from_firmware(fw, &idx);
+
+ for (sect = 0; sect < numsects; sect++) {
+ unsigned int ssize = sectsize[sect] >> 3;
+
+ base = sectstart[sect];
+
+ for (addr = 0; addr < ssize; addr++) {
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_WCS, base + addr);
+ /* write out instruction to low addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out instruction to high addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ }
+ }
+
+ idx = code_start;
+
+ for (sect = 0; sect < numsects; sect++) {
+ unsigned int ssize = sectsize[sect] >> 3;
+
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ base = sectstart[sect];
+ if (base < 0x8000)
+ continue;
+
+ for (addr = 0; addr < ssize; addr++) {
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_WCS,
+ SLIC_WCS_COMPARE | (base + addr));
+ /* write out instruction to low addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out instruction to high addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ }
+ }
+ slic_flush_write(sdev);
+ mdelay(10);
+ /* everything OK, kick off the card */
+ slic_write(sdev, SLIC_REG_WCS, SLIC_WCS_START);
+ slic_flush_write(sdev);
+ /* wait long enough for ucode to init card and reach the mainloop */
+ mdelay(20);
+release:
+ release_firmware(fw);
+
+ return err;
+}
+
+static int slic_init_shmem(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data;
+ dma_addr_t paddr;
+
+ sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+ &paddr, GFP_KERNEL);
+ if (!sm_data) {
+ dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
+ return -ENOMEM;
+ }
+
+ sm->shmem_data = sm_data;
+ sm->isr_paddr = paddr;
+ sm->link_paddr = paddr + offsetof(struct slic_shmem_data, link);
+
+ return 0;
+}
+
+static void slic_free_shmem(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+
+ dma_free_coherent(&sdev->pdev->dev, sizeof(*sm_data), sm_data,
+ sm->isr_paddr);
+}
+
+static int slic_init_iface(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ int err;
+
+ sdev->upr_list.pending = false;
+
+ err = slic_init_shmem(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init shared memory\n");
+ return err;
+ }
+
+ err = slic_load_firmware(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to load firmware\n");
+ goto free_sm;
+ }
+
+ err = slic_load_rcvseq_firmware(sdev);
+ if (err) {
+ netdev_err(sdev->netdev,
+ "failed to load firmware for receive sequencer\n");
+ goto free_sm;
+ }
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ slic_flush_write(sdev);
+ mdelay(1);
+
+ err = slic_init_rx_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init rx queue: %u\n", err);
+ goto free_sm;
+ }
+
+ err = slic_init_tx_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init tx queue: %u\n", err);
+ goto free_rxq;
+ }
+
+ err = slic_init_stat_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init status queue: %u\n",
+ err);
+ goto free_txq;
+ }
+
+ slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+ napi_enable(&sdev->napi);
+ /* disable irq mitigation */
+ slic_write(sdev, SLIC_REG_INTAGG, 0);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ slic_set_mac_address(sdev);
+
+ spin_lock_bh(&sdev->link_lock);
+ sdev->duplex = DUPLEX_UNKNOWN;
+ sdev->speed = SPEED_UNKNOWN;
+ spin_unlock_bh(&sdev->link_lock);
+
+ slic_set_link_autoneg(sdev);
+
+ err = request_irq(sdev->pdev->irq, slic_irq, IRQF_SHARED, DRV_NAME,
+ sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to request irq: %u\n", err);
+ goto disable_napi;
+ }
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_ON);
+ slic_flush_write(sdev);
+ /* request initial link status */
+ err = slic_handle_link_change(sdev);
+ if (err)
+ netdev_warn(sdev->netdev,
+ "failed to set initial link state: %u\n", err);
+ return 0;
+
+disable_napi:
+ napi_disable(&sdev->napi);
+ slic_free_stat_queue(sdev);
+free_txq:
+ slic_free_tx_queue(sdev);
+free_rxq:
+ slic_free_rx_queue(sdev);
+free_sm:
+ slic_free_shmem(sdev);
+ slic_card_reset(sdev);
+
+ return err;
+}
+
+static int slic_open(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ int err;
+
+ netif_carrier_off(dev);
+
+ err = slic_init_iface(sdev);
+ if (err) {
+ netdev_err(dev, "failed to initialize interface: %i\n", err);
+ return err;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int slic_close(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ u32 val;
+
+ netif_stop_queue(dev);
+
+ /* stop irq handling */
+ napi_disable(&sdev->napi);
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ free_irq(sdev->pdev->irq, sdev);
+ /* turn off RCV and XMT and power down PHY */
+ val = SLIC_GXCR_RESET | SLIC_GXCR_PAUSEEN;
+ slic_write(sdev, SLIC_REG_WXCFG, val);
+
+ val = SLIC_GRCR_RESET | SLIC_GRCR_CTLEN | SLIC_GRCR_ADDRAEN |
+ SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT;
+ slic_write(sdev, SLIC_REG_WRCFG, val);
+
+ val = MII_BMCR << 16 | BMCR_PDOWN;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ slic_flush_write(sdev);
+
+ slic_clear_upr_list(&sdev->upr_list);
+ slic_write(sdev, SLIC_REG_QUIESCE, 0);
+
+ slic_free_stat_queue(sdev);
+ slic_free_tx_queue(sdev);
+ slic_free_rx_queue(sdev);
+ slic_free_shmem(sdev);
+
+ slic_card_reset(sdev);
+ netif_carrier_off(dev);
+
+ return 0;
+}
+
+static netdev_tx_t slic_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ struct slic_tx_desc *desc;
+ dma_addr_t paddr;
+ u32 cbar_val;
+ u32 maplen;
+
+ if (unlikely(slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)) {
+ netdev_err(dev, "BUG! not enough tx LEs left: %u\n",
+ slic_get_free_tx_descs(txq));
+ return NETDEV_TX_BUSY;
+ }
+
+ maplen = skb_headlen(skb);
+ paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+ netdev_err(dev, "failed to map tx buffer\n");
+ goto drop_skb;
+ }
+
+ buff = &txq->txbuffs[txq->put_idx];
+ buff->skb = skb;
+ dma_unmap_addr_set(buff, map_addr, paddr);
+ dma_unmap_len_set(buff, map_len, maplen);
+
+ desc = buff->desc;
+ desc->totlen = cpu_to_le32(maplen);
+ desc->paddrl = cpu_to_le32(lower_32_bits(paddr));
+ desc->paddrh = cpu_to_le32(upper_32_bits(paddr));
+ desc->len = cpu_to_le32(maplen);
+
+ txq->put_idx = slic_next_queue_idx(txq->put_idx, txq->len);
+
+ cbar_val = lower_32_bits(buff->desc_paddr) | 1;
+ /* complete writes to RAM and DMA before hardware is informed */
+ wmb();
+
+ slic_write(sdev, SLIC_REG_CBAR, cbar_val);
+
+ if (slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)
+ netif_stop_queue(dev);
+ /* make sure writes to io-memory cant leak out of tx queue lock */
+ mmiowb();
+
+ return NETDEV_TX_OK;
+drop_skb:
+ dev_kfree_skb_any(skb);
+
+ return NETDEV_TX_OK;
+}
+
+static struct rtnl_link_stats64 *slic_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *lst)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_stats *stats = &sdev->stats;
+
+ SLIC_GET_STATS_COUNTER(lst->rx_packets, stats, rx_packets);
+ SLIC_GET_STATS_COUNTER(lst->tx_packets, stats, tx_packets);
+ SLIC_GET_STATS_COUNTER(lst->rx_bytes, stats, rx_bytes);
+ SLIC_GET_STATS_COUNTER(lst->tx_bytes, stats, tx_bytes);
+ SLIC_GET_STATS_COUNTER(lst->rx_errors, stats, rx_errors);
+ SLIC_GET_STATS_COUNTER(lst->rx_dropped, stats, rx_buff_miss);
+ SLIC_GET_STATS_COUNTER(lst->tx_dropped, stats, tx_dropped);
+ SLIC_GET_STATS_COUNTER(lst->multicast, stats, rx_mcasts);
+ SLIC_GET_STATS_COUNTER(lst->rx_over_errors, stats, rx_buffoflow);
+ SLIC_GET_STATS_COUNTER(lst->rx_crc_errors, stats, rx_crc);
+ SLIC_GET_STATS_COUNTER(lst->rx_fifo_errors, stats, rx_oflow802);
+ SLIC_GET_STATS_COUNTER(lst->tx_carrier_errors, stats, tx_carrier);
+
+ return lst;
+}
+
+static int slic_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(slic_stats_strings);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void slic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *eth_stats, u64 *data)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_stats *stats = &sdev->stats;
+
+ SLIC_GET_STATS_COUNTER(data[0], stats, rx_packets);
+ SLIC_GET_STATS_COUNTER(data[1], stats, rx_bytes);
+ SLIC_GET_STATS_COUNTER(data[2], stats, rx_mcasts);
+ SLIC_GET_STATS_COUNTER(data[3], stats, rx_errors);
+ SLIC_GET_STATS_COUNTER(data[4], stats, rx_buff_miss);
+ SLIC_GET_STATS_COUNTER(data[5], stats, rx_tpcsum);
+ SLIC_GET_STATS_COUNTER(data[6], stats, rx_tpoflow);
+ SLIC_GET_STATS_COUNTER(data[7], stats, rx_tphlen);
+ SLIC_GET_STATS_COUNTER(data[8], stats, rx_ipcsum);
+ SLIC_GET_STATS_COUNTER(data[9], stats, rx_iplen);
+ SLIC_GET_STATS_COUNTER(data[10], stats, rx_iphlen);
+ SLIC_GET_STATS_COUNTER(data[11], stats, rx_early);
+ SLIC_GET_STATS_COUNTER(data[12], stats, rx_buffoflow);
+ SLIC_GET_STATS_COUNTER(data[13], stats, rx_lcode);
+ SLIC_GET_STATS_COUNTER(data[14], stats, rx_drbl);
+ SLIC_GET_STATS_COUNTER(data[15], stats, rx_crc);
+ SLIC_GET_STATS_COUNTER(data[16], stats, rx_oflow802);
+ SLIC_GET_STATS_COUNTER(data[17], stats, rx_uflow802);
+ SLIC_GET_STATS_COUNTER(data[18], stats, tx_packets);
+ SLIC_GET_STATS_COUNTER(data[19], stats, tx_bytes);
+ SLIC_GET_STATS_COUNTER(data[20], stats, tx_carrier);
+ SLIC_GET_STATS_COUNTER(data[21], stats, tx_dropped);
+ SLIC_GET_STATS_COUNTER(data[22], stats, irq_errs);
+}
+
+static void slic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ if (stringset == ETH_SS_STATS) {
+ memcpy(data, slic_stats_strings, sizeof(slic_stats_strings));
+ data += sizeof(slic_stats_strings);
+ }
+}
+
+static void slic_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, pci_name(sdev->pdev), sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops slic_ethtool_ops = {
+ .get_drvinfo = slic_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_strings = slic_get_strings,
+ .get_ethtool_stats = slic_get_ethtool_stats,
+ .get_sset_count = slic_get_sset_count,
+};
+
+static const struct net_device_ops slic_netdev_ops = {
+ .ndo_open = slic_open,
+ .ndo_stop = slic_close,
+ .ndo_start_xmit = slic_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_get_stats64 = slic_get_stats,
+ .ndo_set_rx_mode = slic_set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static u16 slic_eeprom_csum(unsigned char *eeprom, unsigned int len)
+{
+ unsigned char *ptr = eeprom;
+ u32 csum = 0;
+ __le16 data;
+
+ while (len > 1) {
+ memcpy(&data, ptr, sizeof(data));
+ csum += le16_to_cpu(data);
+ ptr += 2;
+ len -= 2;
+ }
+ if (len > 0)
+ csum += *(u8 *)ptr;
+ while (csum >> 16)
+ csum = (csum & 0xFFFF) + ((csum >> 16) & 0xFFFF);
+ return ~csum;
+}
+
+/* check eeprom size, magic and checksum */
+static bool slic_eeprom_valid(unsigned char *eeprom, unsigned int size)
+{
+ const unsigned int MAX_SIZE = 128;
+ const unsigned int MIN_SIZE = 98;
+ __le16 magic;
+ __le16 csum;
+
+ if (size < MIN_SIZE || size > MAX_SIZE)
+ return false;
+ memcpy(&magic, eeprom, sizeof(magic));
+ if (le16_to_cpu(magic) != SLIC_EEPROM_MAGIC)
+ return false;
+ /* cut checksum bytes */
+ size -= 2;
+ memcpy(&csum, eeprom + size, sizeof(csum));
+
+ return (le16_to_cpu(csum) == slic_eeprom_csum(eeprom, size));
+}
+
+static int slic_read_eeprom(struct slic_device *sdev)
+{
+ unsigned int devfn = PCI_FUNC(sdev->pdev->devfn);
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ const unsigned int MAX_LOOPS = 5000;
+ unsigned int codesize;
+ unsigned char *eeprom;
+ struct slic_upr *upr;
+ unsigned int i = 0;
+ dma_addr_t paddr;
+ int err = 0;
+ u8 *mac[2];
+
+ eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+ &paddr, GFP_KERNEL);
+ if (!eeprom)
+ return -ENOMEM;
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ /* setup ISP temporarily */
+ slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+
+ err = slic_new_upr(sdev, SLIC_UPR_CONFIG, paddr);
+ if (!err) {
+ for (i = 0; i < MAX_LOOPS; i++) {
+ if (le32_to_cpu(sm_data->isr) & SLIC_ISR_UPC)
+ break;
+ mdelay(1);
+ }
+ if (i == MAX_LOOPS) {
+ dev_err(&sdev->pdev->dev,
+ "timed out while waiting for eeprom data\n");
+ err = -ETIMEDOUT;
+ }
+ upr = slic_dequeue_upr(sdev);
+ kfree(upr);
+ }
+
+ slic_write(sdev, SLIC_REG_ISP, 0);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ if (err)
+ goto free_eeprom;
+
+ if (sdev->model == SLIC_MODEL_OASIS) {
+ struct slic_oasis_eeprom *oee;
+
+ oee = (struct slic_oasis_eeprom *)eeprom;
+ mac[0] = oee->mac;
+ mac[1] = oee->mac2;
+ codesize = le16_to_cpu(oee->eeprom_code_size);
+ } else {
+ struct slic_mojave_eeprom *mee;
+
+ mee = (struct slic_mojave_eeprom *)eeprom;
+ mac[0] = mee->mac;
+ mac[1] = mee->mac2;
+ codesize = le16_to_cpu(mee->eeprom_code_size);
+ }
+
+ if (!slic_eeprom_valid(eeprom, codesize)) {
+ dev_err(&sdev->pdev->dev, "invalid checksum in eeprom\n");
+ err = -EINVAL;
+ goto free_eeprom;
+ }
+ /* set mac address */
+ ether_addr_copy(sdev->netdev->dev_addr, mac[devfn]);
+free_eeprom:
+ dma_free_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, eeprom, paddr);
+
+ return err;
+}
+
+static int slic_init(struct slic_device *sdev)
+{
+ int err;
+
+ spin_lock_init(&sdev->upper_lock);
+ spin_lock_init(&sdev->link_lock);
+ INIT_LIST_HEAD(&sdev->upr_list.list);
+ spin_lock_init(&sdev->upr_list.lock);
+ u64_stats_init(&sdev->stats.syncp);
+
+ slic_card_reset(sdev);
+
+ err = slic_load_firmware(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to load firmware\n");
+ return err;
+ }
+
+ /* we need the shared memory to read EEPROM so set it up temporarily */
+ err = slic_init_shmem(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to init shared memory\n");
+ return err;
+ }
+
+ err = slic_read_eeprom(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to read eeprom\n");
+ goto free_sm;
+ }
+
+ slic_card_reset(sdev);
+ slic_free_shmem(sdev);
+
+ return 0;
+free_sm:
+ slic_free_shmem(sdev);
+
+ return err;
+}
+
+static bool slic_is_fiber(unsigned short subdev)
+{
+ switch (subdev) {
+ /* Mojave */
+ case PCI_SUBDEVICE_ID_ALACRITECH_1000X1F: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SES1001F: /* fallthrough */
+ /* Oasis */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF: /* fallthrough */
+ return true;
+ }
+ return false;
+}
+
+static void slic_configure_pci(struct pci_dev *pdev)
+{
+ u16 old;
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &old);
+
+ cmd = old | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ if (old != cmd)
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+}
+
+static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct slic_device *sdev;
+ struct net_device *dev;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable PCI device\n");
+ return err;
+ }
+
+ pci_set_master(pdev);
+ pci_try_set_mwi(pdev);
+
+ slic_configure_pci(pdev);
+
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev, "failed to setup DMA\n");
+ goto disable;
+ }
+
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(&pdev->dev, "failed to obtain PCI regions\n");
+ goto disable;
+ }
+
+ dev = alloc_etherdev(sizeof(*sdev));
+ if (!dev) {
+ dev_err(&pdev->dev, "failed to alloc ethernet device\n");
+ err = -ENOMEM;
+ goto free_regions;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ pci_set_drvdata(pdev, dev);
+ dev->irq = pdev->irq;
+ dev->netdev_ops = &slic_netdev_ops;
+ dev->hw_features = NETIF_F_RXCSUM;
+ dev->features |= dev->hw_features;
+
+ dev->ethtool_ops = &slic_ethtool_ops;
+
+ sdev = netdev_priv(dev);
+ sdev->model = (pdev->device == PCI_DEVICE_ID_ALACRITECH_OASIS) ?
+ SLIC_MODEL_OASIS : SLIC_MODEL_MOJAVE;
+ sdev->is_fiber = slic_is_fiber(pdev->subsystem_device);
+ sdev->pdev = pdev;
+ sdev->netdev = dev;
+ sdev->regs = ioremap_nocache(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!sdev->regs) {
+ dev_err(&pdev->dev, "failed to map registers\n");
+ err = -ENOMEM;
+ goto free_netdev;
+ }
+
+ err = slic_init(sdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to initialize driver\n");
+ goto unmap;
+ }
+
+ netif_napi_add(dev, &sdev->napi, slic_poll, SLIC_NAPI_WEIGHT);
+ netif_carrier_off(dev);
+
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register net device: %i\n", err);
+ goto unmap;
+ }
+
+ return 0;
+
+unmap:
+ iounmap(sdev->regs);
+free_netdev:
+ free_netdev(dev);
+free_regions:
+ pci_release_regions(pdev);
+disable:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void slic_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct slic_device *sdev = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ iounmap(sdev->regs);
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver slic_driver = {
+ .name = DRV_NAME,
+ .id_table = slic_id_tbl,
+ .probe = slic_probe,
+ .remove = slic_remove,
+};
+
+module_pci_driver(slic_driver);
+
+MODULE_DESCRIPTION("Alacritech non-accelerated SLIC driver");
+MODULE_AUTHOR("Lino Sanfilippo <LinoSanfilippo@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index 6ffdff68bfc4..c8f4d26fc9d4 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -37,6 +37,11 @@
#define EMAC_MAX_FRAME_LEN 0x0600
+#define EMAC_DEFAULT_MSG_ENABLE 0x0000
+static int debug = -1; /* defaults above */;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "debug message flags");
+
/* Transmit timeout, default 5 seconds. */
static int watchdog = 5000;
module_param(watchdog, int, 0400);
@@ -225,11 +230,27 @@ static void emac_get_drvinfo(struct net_device *dev,
strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
}
+static u32 emac_get_msglevel(struct net_device *dev)
+{
+ struct emac_board_info *db = netdev_priv(dev);
+
+ return db->msg_enable;
+}
+
+static void emac_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct emac_board_info *db = netdev_priv(dev);
+
+ db->msg_enable = value;
+}
+
static const struct ethtool_ops emac_ethtool_ops = {
.get_drvinfo = emac_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_msglevel = emac_get_msglevel,
+ .set_msglevel = emac_set_msglevel,
};
static unsigned int emac_setup(struct net_device *ndev)
@@ -571,8 +592,7 @@ static void emac_rx(struct net_device *dev)
/* A packet ready now & Get status/length */
good_packet = true;
- emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
- &rxhdr, sizeof(rxhdr));
+ rxhdr = readl(db->membase + EMAC_RX_IO_DATA_REG);
if (netif_msg_rx_status(db))
dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr)));
@@ -773,7 +793,6 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_tx_timeout = emac_timeout,
.ndo_set_rx_mode = emac_set_rx_mode,
.ndo_do_ioctl = emac_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = emac_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -805,6 +824,7 @@ static int emac_probe(struct platform_device *pdev)
db->dev = &pdev->dev;
db->ndev = ndev;
db->pdev = pdev;
+ db->msg_enable = netif_msg_init(debug, EMAC_DEFAULT_MSG_ENABLE);
spin_lock_init(&db->lock);
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index b90a26b13fdf..16f0c70266bc 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -429,14 +429,16 @@ static const char version[] =
"acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
" http://home.cern.ch/~jes/gige/acenic.html\n";
-static int ace_get_settings(struct net_device *, struct ethtool_cmd *);
-static int ace_set_settings(struct net_device *, struct ethtool_cmd *);
+static int ace_get_link_ksettings(struct net_device *,
+ struct ethtool_link_ksettings *);
+static int ace_set_link_ksettings(struct net_device *,
+ const struct ethtool_link_ksettings *);
static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
static const struct ethtool_ops ace_ethtool_ops = {
- .get_settings = ace_get_settings,
- .set_settings = ace_set_settings,
.get_drvinfo = ace_get_drvinfo,
+ .get_link_ksettings = ace_get_link_ksettings,
+ .set_link_ksettings = ace_set_link_ksettings,
};
static void ace_watchdog(struct net_device *dev);
@@ -474,6 +476,8 @@ static int acenic_probe_one(struct pci_dev *pdev,
dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
dev->watchdog_timeo = 5*HZ;
+ dev->min_mtu = 0;
+ dev->max_mtu = ACE_JUMBO_MTU;
dev->netdev_ops = &ace_netdev_ops;
dev->ethtool_ops = &ace_ethtool_ops;
@@ -2548,9 +2552,6 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
struct ace_private *ap = netdev_priv(dev);
struct ace_regs __iomem *regs = ap->regs;
- if (new_mtu > ACE_JUMBO_MTU)
- return -EINVAL;
-
writel(new_mtu + ETH_HLEN + 4, &regs->IfMtu);
dev->mtu = new_mtu;
@@ -2580,43 +2581,44 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int ace_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct ace_private *ap = netdev_priv(dev);
struct ace_regs __iomem *regs = ap->regs;
u32 link;
+ u32 supported;
+
+ memset(cmd, 0, sizeof(struct ethtool_link_ksettings));
- memset(ecmd, 0, sizeof(struct ethtool_cmd));
- ecmd->supported =
- (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+ supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_FIBRE);
- ecmd->port = PORT_FIBRE;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_FIBRE;
link = readl(&regs->GigLnkState);
- if (link & LNK_1000MB)
- ethtool_cmd_speed_set(ecmd, SPEED_1000);
- else {
+ if (link & LNK_1000MB) {
+ cmd->base.speed = SPEED_1000;
+ } else {
link = readl(&regs->FastLnkState);
if (link & LNK_100MB)
- ethtool_cmd_speed_set(ecmd, SPEED_100);
+ cmd->base.speed = SPEED_100;
else if (link & LNK_10MB)
- ethtool_cmd_speed_set(ecmd, SPEED_10);
+ cmd->base.speed = SPEED_10;
else
- ethtool_cmd_speed_set(ecmd, 0);
+ cmd->base.speed = 0;
}
if (link & LNK_FULL_DUPLEX)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
else
- ecmd->duplex = DUPLEX_HALF;
+ cmd->base.duplex = DUPLEX_HALF;
if (link & LNK_NEGOTIATE)
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
else
- ecmd->autoneg = AUTONEG_DISABLE;
+ cmd->base.autoneg = AUTONEG_DISABLE;
#if 0
/*
@@ -2627,13 +2629,15 @@ static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->txcoal = readl(&regs->TuneTxCoalTicks);
ecmd->rxcoal = readl(&regs->TuneRxCoalTicks);
#endif
- ecmd->maxtxpkt = readl(&regs->TuneMaxTxDesc);
- ecmd->maxrxpkt = readl(&regs->TuneMaxRxDesc);
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
return 0;
}
-static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int ace_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct ace_private *ap = netdev_priv(dev);
struct ace_regs __iomem *regs = ap->regs;
@@ -2656,11 +2660,11 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
if (!ACE_IS_TIGON_I(ap))
link |= LNK_TX_FLOW_CTL_Y;
- if (ecmd->autoneg == AUTONEG_ENABLE)
+ if (cmd->base.autoneg == AUTONEG_ENABLE)
link |= LNK_NEGOTIATE;
- if (ethtool_cmd_speed(ecmd) != speed) {
+ if (cmd->base.speed != speed) {
link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
- switch (ethtool_cmd_speed(ecmd)) {
+ switch (cmd->base.speed) {
case SPEED_1000:
link |= LNK_1000MB;
break;
@@ -2673,7 +2677,7 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
}
}
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
link |= LNK_FULL_DUPLEX;
if (link != ap->link) {
diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h
index e0052003d16f..e2feee87180a 100644
--- a/drivers/net/ethernet/altera/altera_tse.h
+++ b/drivers/net/ethernet/altera/altera_tse.h
@@ -120,6 +120,17 @@
#define MAC_CMDCFG_DISABLE_READ_TIMEOUT_GET(v) GET_BIT_VALUE(v, 27)
#define MAC_CMDCFG_CNT_RESET_GET(v) GET_BIT_VALUE(v, 31)
+/* SGMII PCS register addresses
+ */
+#define SGMII_PCS_SCRATCH 0x10
+#define SGMII_PCS_REV 0x11
+#define SGMII_PCS_LINK_TIMER_0 0x12
+#define SGMII_PCS_LINK_TIMER_1 0x13
+#define SGMII_PCS_IF_MODE 0x14
+#define SGMII_PCS_DIS_READ_TO 0x15
+#define SGMII_PCS_READ_TO 0x16
+#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */
+
/* MDIO registers within MAC register Space
*/
struct altera_tse_mdio {
@@ -443,7 +454,6 @@ struct altera_tse_private {
/* RX/TX MAC FIFO configs */
u32 tx_fifo_depth;
u32 rx_fifo_depth;
- u32 max_mtu;
/* Hash filter settings */
u32 hash_filter;
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index a0eee7218695..25864bff25ee 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -37,6 +37,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
@@ -96,6 +97,27 @@ static inline u32 tse_tx_avail(struct altera_tse_private *priv)
return priv->tx_cons + priv->tx_ring_size - priv->tx_prod - 1;
}
+/* PCS Register read/write functions
+ */
+static u16 sgmii_pcs_read(struct altera_tse_private *priv, int regnum)
+{
+ return csrrd32(priv->mac_dev,
+ tse_csroffs(mdio_phy0) + regnum * 4) & 0xffff;
+}
+
+static void sgmii_pcs_write(struct altera_tse_private *priv, int regnum,
+ u16 value)
+{
+ csrwr32(value, priv->mac_dev, tse_csroffs(mdio_phy0) + regnum * 4);
+}
+
+/* Check PCS scratch memory */
+static int sgmii_pcs_scratch_test(struct altera_tse_private *priv, u16 value)
+{
+ sgmii_pcs_write(priv, SGMII_PCS_SCRATCH, value);
+ return (sgmii_pcs_read(priv, SGMII_PCS_SCRATCH) == value);
+}
+
/* MDIO specific functions
*/
static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
@@ -984,20 +1006,11 @@ static void tse_set_mac(struct altera_tse_private *priv, bool enable)
*/
static int tse_change_mtu(struct net_device *dev, int new_mtu)
{
- struct altera_tse_private *priv = netdev_priv(dev);
- unsigned int max_mtu = priv->max_mtu;
- unsigned int min_mtu = ETH_ZLEN + ETH_FCS_LEN;
-
if (netif_running(dev)) {
netdev_err(dev, "must be stopped to change its MTU\n");
return -EBUSY;
}
- if ((new_mtu < min_mtu) || (new_mtu > max_mtu)) {
- netdev_err(dev, "invalid MTU, max MTU is: %u\n", max_mtu);
- return -EINVAL;
- }
-
dev->mtu = new_mtu;
netdev_update_features(dev);
@@ -1082,6 +1095,66 @@ static void tse_set_rx_mode(struct net_device *dev)
spin_unlock(&priv->mac_cfg_lock);
}
+/* Initialise (if necessary) the SGMII PCS component
+ */
+static int init_sgmii_pcs(struct net_device *dev)
+{
+ struct altera_tse_private *priv = netdev_priv(dev);
+ int n;
+ unsigned int tmp_reg = 0;
+
+ if (priv->phy_iface != PHY_INTERFACE_MODE_SGMII)
+ return 0; /* Nothing to do, not in SGMII mode */
+
+ /* The TSE SGMII PCS block looks a little like a PHY, it is
+ * mapped into the zeroth MDIO space of the MAC and it has
+ * ID registers like a PHY would. Sadly this is often
+ * configured to zeroes, so don't be surprised if it does
+ * show 0x00000000.
+ */
+
+ if (sgmii_pcs_scratch_test(priv, 0x0000) &&
+ sgmii_pcs_scratch_test(priv, 0xffff) &&
+ sgmii_pcs_scratch_test(priv, 0xa5a5) &&
+ sgmii_pcs_scratch_test(priv, 0x5a5a)) {
+ netdev_info(dev, "PCS PHY ID: 0x%04x%04x\n",
+ sgmii_pcs_read(priv, MII_PHYSID1),
+ sgmii_pcs_read(priv, MII_PHYSID2));
+ } else {
+ netdev_err(dev, "SGMII PCS Scratch memory test failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Starting on page 5-29 of the MegaCore Function User Guide
+ * Set SGMII Link timer to 1.6ms
+ */
+ sgmii_pcs_write(priv, SGMII_PCS_LINK_TIMER_0, 0x0D40);
+ sgmii_pcs_write(priv, SGMII_PCS_LINK_TIMER_1, 0x03);
+
+ /* Enable SGMII Interface and Enable SGMII Auto Negotiation */
+ sgmii_pcs_write(priv, SGMII_PCS_IF_MODE, 0x3);
+
+ /* Enable Autonegotiation */
+ tmp_reg = sgmii_pcs_read(priv, MII_BMCR);
+ tmp_reg |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE);
+ sgmii_pcs_write(priv, MII_BMCR, tmp_reg);
+
+ /* Reset PCS block */
+ tmp_reg |= BMCR_RESET;
+ sgmii_pcs_write(priv, MII_BMCR, tmp_reg);
+ for (n = 0; n < SGMII_PCS_SW_RESET_TIMEOUT; n++) {
+ if (!(sgmii_pcs_read(priv, MII_BMCR) & BMCR_RESET)) {
+ netdev_info(dev, "SGMII PCS block initialised OK\n");
+ return 0;
+ }
+ udelay(1);
+ }
+
+ /* We failed to reset the block, return a timeout */
+ netdev_err(dev, "SGMII PCS block reset failed.\n");
+ return -ETIMEDOUT;
+}
+
/* Open and initialize the interface
*/
static int tse_open(struct net_device *dev)
@@ -1106,6 +1179,15 @@ static int tse_open(struct net_device *dev)
netdev_warn(dev, "TSE revision %x\n", priv->revision);
spin_lock(&priv->mac_cfg_lock);
+ /* no-op if MAC not operating in SGMII mode*/
+ ret = init_sgmii_pcs(dev);
+ if (ret) {
+ netdev_err(dev,
+ "Cannot init the SGMII PCS (error: %d)\n", ret);
+ spin_unlock(&priv->mac_cfg_lock);
+ goto phy_error;
+ }
+
ret = reset_mac(priv);
/* Note that reset_mac will fail if the clocks are gated by the PHY
* due to the PHY being put into isolation or power down mode.
@@ -1328,11 +1410,13 @@ static int altera_tse_probe(struct platform_device *pdev)
if (upper_32_bits(priv->rxdescmem_busaddr)) {
dev_dbg(priv->device,
"SGDMA bus addresses greater than 32-bits\n");
+ ret = -EINVAL;
goto err_free_netdev;
}
if (upper_32_bits(priv->txdescmem_busaddr)) {
dev_dbg(priv->device,
"SGDMA bus addresses greater than 32-bits\n");
+ ret = -EINVAL;
goto err_free_netdev;
}
} else if (priv->dmaops &&
@@ -1436,15 +1520,16 @@ static int altera_tse_probe(struct platform_device *pdev)
of_property_read_bool(pdev->dev.of_node,
"altr,has-supplementary-unicast");
+ priv->dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
/* Max MTU is 1500, ETH_DATA_LEN */
- priv->max_mtu = ETH_DATA_LEN;
+ priv->dev->max_mtu = ETH_DATA_LEN;
/* Get the max mtu from the device tree. Note that the
* "max-frame-size" parameter is actually max mtu. Definition
* in the ePAPR v1.1 spec and usage differ, so go with usage.
*/
of_property_read_u32(pdev->dev.of_node, "max-frame-size",
- &priv->max_mtu);
+ &priv->dev->max_mtu);
/* The DMA buffer size already accounts for an alignment bias
* to avoid unaligned access exceptions for the NIOS processor,
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index bfeaec5bd7b9..cc8b13ebfa75 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -103,13 +103,6 @@ static int ena_change_mtu(struct net_device *dev, int new_mtu)
struct ena_adapter *adapter = netdev_priv(dev);
int ret;
- if ((new_mtu > adapter->max_mtu) || (new_mtu < ENA_MIN_MTU)) {
- netif_err(adapter, drv, dev,
- "Invalid MTU setting. new_mtu: %d\n", new_mtu);
-
- return -EINVAL;
- }
-
ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
if (!ret) {
netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
@@ -2755,6 +2748,8 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter,
ena_set_dev_offloads(feat, netdev);
adapter->max_mtu = feat->dev_attr.max_mtu;
+ netdev->max_mtu = adapter->max_mtu;
+ netdev->min_mtu = ENA_MIN_MTU;
}
static int ena_rss_init_default(struct ena_adapter *adapter)
@@ -3018,12 +3013,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->last_keep_alive_jiffies = jiffies;
- init_timer(&adapter->timer_service);
- adapter->timer_service.expires = round_jiffies(jiffies + HZ);
- adapter->timer_service.function = ena_timer_service;
- adapter->timer_service.data = (unsigned long)adapter;
-
- add_timer(&adapter->timer_service);
+ setup_timer(&adapter->timer_service, ena_timer_service,
+ (unsigned long)adapter);
+ mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
dev_info(&pdev->dev, "%s found at mem %lx, mac addr %pM Queues %d\n",
DEVICE_NAME, (long)pci_resource_start(pdev, 0),
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index 0038709fd317..d5c15e8bb3de 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -173,11 +173,13 @@ config SUNLANCE
config AMD_XGBE
tristate "AMD 10GbE Ethernet driver"
- depends on ((OF_NET && OF_ADDRESS) || ACPI) && HAS_IOMEM && HAS_DMA
- depends on ARM64 || COMPILE_TEST
+ depends on ((OF_NET && OF_ADDRESS) || ACPI || PCI) && HAS_IOMEM && HAS_DMA
+ depends on X86 || ARM64 || COMPILE_TEST
select BITREVERSE
select CRC32
- select PTP_1588_CLOCK
+ select PHYLIB
+ select AMD_XGBE_HAVE_ECC if X86
+ imply PTP_1588_CLOCK
---help---
This driver supports the AMD 10GbE Ethernet device found on an
AMD SoC.
@@ -195,4 +197,8 @@ config AMD_XGBE_DCB
If unsure, say N.
+config AMD_XGBE_HAVE_ECC
+ bool
+ default n
+
endif # NET_VENDOR_AMD
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
index a83cd1c4ce1d..ee4b94e3cda9 100644
--- a/drivers/net/ethernet/amd/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -665,7 +665,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_tx_timeout = lance_tx_timeout,
.ndo_set_rx_mode = lance_set_multicast,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index fcdf5dda448f..b11e910850f7 100644
--- a/drivers/net/ethernet/amd/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -663,7 +663,6 @@ static const struct net_device_ops am79c961_netdev_ops = {
.ndo_set_rx_mode = am79c961_setmulticastlist,
.ndo_tx_timeout = am79c961_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = am79c961_poll_controller,
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index f92cc97151ec..11cf1e3e0295 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1421,21 +1421,23 @@ static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs,
amd8111e_read_regs(lp, buf);
}
-static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int amd8111e_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct amd8111e_priv *lp = netdev_priv(dev);
spin_lock_irq(&lp->lock);
- mii_ethtool_gset(&lp->mii_if, ecmd);
+ mii_ethtool_get_link_ksettings(&lp->mii_if, cmd);
spin_unlock_irq(&lp->lock);
return 0;
}
-static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int amd8111e_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct amd8111e_priv *lp = netdev_priv(dev);
int res;
spin_lock_irq(&lp->lock);
- res = mii_ethtool_sset(&lp->mii_if, ecmd);
+ res = mii_ethtool_set_link_ksettings(&lp->mii_if, cmd);
spin_unlock_irq(&lp->lock);
return res;
}
@@ -1482,12 +1484,12 @@ static const struct ethtool_ops ops = {
.get_drvinfo = amd8111e_get_drvinfo,
.get_regs_len = amd8111e_get_regs_len,
.get_regs = amd8111e_get_regs,
- .get_settings = amd8111e_get_settings,
- .set_settings = amd8111e_set_settings,
.nway_reset = amd8111e_nway_reset,
.get_link = amd8111e_get_link,
.get_wol = amd8111e_get_wol,
.set_wol = amd8111e_set_wol,
+ .get_link_ksettings = amd8111e_get_link_ksettings,
+ .set_link_ksettings = amd8111e_set_link_ksettings,
};
/* This function handles all the ethtool ioctls. It gives driver info,
@@ -1556,9 +1558,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
struct amd8111e_priv *lp = netdev_priv(dev);
int err;
- if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU))
- return -EINVAL;
-
if (!netif_running(dev)) {
/* new_mtu will be used
* when device starts netxt time
@@ -1874,6 +1873,8 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
dev->ethtool_ops = &ops;
dev->irq =pdev->irq;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
+ dev->min_mtu = AMD8111E_MIN_MTU;
+ dev->max_mtu = AMD8111E_MAX_MTU;
netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
#if AMD8111E_VLAN_TAG_USED
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index 968b7bfac8fc..5fd7b15b0574 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -706,7 +706,6 @@ static const struct net_device_ops ariadne_netdev_ops = {
.ndo_get_stats = ariadne_get_stats,
.ndo_set_rx_mode = set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index d2bc8e5dcd23..796c37a5bbde 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -460,7 +460,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_set_mac_address = lance_set_mac_address,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static unsigned long __init lance_probe1( struct net_device *dev,
@@ -1013,13 +1012,9 @@ static int lance_rx( struct net_device *dev )
u_char *data = PKTBUF_ADDR(head);
printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
- "data %02x %02x %02x %02x %02x %02x %02x %02x "
- "len %d\n",
+ "data %8ph len %d\n",
dev->name, ((u_short *)data)[6],
- &data[6], data,
- data[15], data[16], data[17], data[18],
- data[19], data[20], data[21], data[22],
- pkt_len);
+ &data[6], data, &data[15], pkt_len);
}
skb_reserve( skb, 2 ); /* 16 byte align */
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index df664187cd82..a3c90fe5de00 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1103,7 +1103,6 @@ static const struct net_device_ops au1000_netdev_ops = {
.ndo_tx_timeout = au1000_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int au1000_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index b799c7ac899b..76e5fc7adff5 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -1013,7 +1013,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_start_xmit = lance_start_xmit,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_set_rx_mode = lance_set_multicast,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
index 6c9de117ffc6..c3dbf1c8a269 100644
--- a/drivers/net/ethernet/amd/hplance.c
+++ b/drivers/net/ethernet/amd/hplance.c
@@ -72,7 +72,6 @@ static const struct net_device_ops hplance_netdev_ops = {
.ndo_stop = hplance_close,
.ndo_start_xmit = lance_start_xmit,
.ndo_set_rx_mode = lance_set_multicast,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c
index abb1ba228b26..61a641f23149 100644
--- a/drivers/net/ethernet/amd/lance.c
+++ b/drivers/net/ethernet/amd/lance.c
@@ -461,7 +461,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_get_stats = lance_get_stats,
.ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = lance_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
index 0660ac5846bb..0a920448522f 100644
--- a/drivers/net/ethernet/amd/mvme147.c
+++ b/drivers/net/ethernet/amd/mvme147.c
@@ -62,7 +62,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_start_xmit = lance_start_xmit,
.ndo_set_rx_mode = lance_set_multicast,
.ndo_tx_timeout = lance_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index cda53db75f17..5985bf220a8d 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -407,7 +407,6 @@ static const struct net_device_ops ni65_netdev_ops = {
.ndo_start_xmit = ni65_send_packet,
.ndo_tx_timeout = ni65_timeout,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 2807e181647b..113a3b3cc50c 100644
--- a/drivers/net/ethernet/amd/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -427,7 +427,6 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_set_config = mace_config,
.ndo_get_stats = mace_get_stats,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index c22bf52d3320..41e58cca8fee 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -677,7 +677,8 @@ static void pcnet32_poll_controller(struct net_device *dev)
}
#endif
-static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int pcnet32_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
@@ -685,14 +686,15 @@ static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (lp->mii) {
spin_lock_irqsave(&lp->lock, flags);
- mii_ethtool_gset(&lp->mii_if, cmd);
+ mii_ethtool_get_link_ksettings(&lp->mii_if, cmd);
spin_unlock_irqrestore(&lp->lock, flags);
r = 0;
}
return r;
}
-static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int pcnet32_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct pcnet32_private *lp = netdev_priv(dev);
unsigned long flags;
@@ -700,7 +702,7 @@ static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (lp->mii) {
spin_lock_irqsave(&lp->lock, flags);
- r = mii_ethtool_sset(&lp->mii_if, cmd);
+ r = mii_ethtool_set_link_ksettings(&lp->mii_if, cmd);
spin_unlock_irqrestore(&lp->lock, flags);
}
return r;
@@ -1440,8 +1442,6 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
}
static const struct ethtool_ops pcnet32_ethtool_ops = {
- .get_settings = pcnet32_get_settings,
- .set_settings = pcnet32_set_settings,
.get_drvinfo = pcnet32_get_drvinfo,
.get_msglevel = pcnet32_get_msglevel,
.set_msglevel = pcnet32_set_msglevel,
@@ -1455,6 +1455,8 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
.get_sset_count = pcnet32_get_sset_count,
+ .get_link_ksettings = pcnet32_get_link_ksettings,
+ .set_link_ksettings = pcnet32_set_link_ksettings,
};
/* only probes for non-PCI devices, the rest are handled by
@@ -1527,7 +1529,6 @@ static const struct net_device_ops pcnet32_netdev_ops = {
.ndo_get_stats = pcnet32_get_stats,
.ndo_set_rx_mode = pcnet32_set_multicast_list,
.ndo_do_ioctl = pcnet32_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
index 3d8c6b2cdea4..12bb4f1489fc 100644
--- a/drivers/net/ethernet/amd/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -299,7 +299,6 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_start_xmit = lance_start_xmit,
.ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = NULL,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index 9b56b40259dc..291ca5187f12 100644
--- a/drivers/net/ethernet/amd/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -1294,7 +1294,6 @@ static const struct net_device_ops sparc_lance_ops = {
.ndo_start_xmit = lance_start_xmit,
.ndo_set_rx_mode = lance_set_multicast,
.ndo_tx_timeout = lance_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile
index 171a7e68048d..0dea8f5da899 100644
--- a/drivers/net/ethernet/amd/xgbe/Makefile
+++ b/drivers/net/ethernet/amd/xgbe/Makefile
@@ -2,7 +2,10 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
- xgbe-ptp.o
+ xgbe-ptp.o \
+ xgbe-i2c.o xgbe-phy-v1.o xgbe-phy-v2.o \
+ xgbe-platform.o
+amd-xgbe-$(CONFIG_PCI) += xgbe-pci.o
amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index bbef95973c27..5b7ba25e0065 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -159,6 +159,8 @@
#define DMA_ISR_MACIS_WIDTH 1
#define DMA_ISR_MTLIS_INDEX 16
#define DMA_ISR_MTLIS_WIDTH 1
+#define DMA_MR_INTM_INDEX 12
+#define DMA_MR_INTM_WIDTH 2
#define DMA_MR_SWR_INDEX 0
#define DMA_MR_SWR_WIDTH 1
#define DMA_SBMR_EAME_INDEX 11
@@ -309,6 +311,11 @@
#define MAC_HWF0R 0x011c
#define MAC_HWF1R 0x0120
#define MAC_HWF2R 0x0124
+#define MAC_MDIOSCAR 0x0200
+#define MAC_MDIOSCCDR 0x0204
+#define MAC_MDIOISR 0x0214
+#define MAC_MDIOIER 0x0218
+#define MAC_MDIOCL22R 0x0220
#define MAC_GPIOCR 0x0278
#define MAC_GPIOSR 0x027c
#define MAC_MACA0HR 0x0300
@@ -409,10 +416,34 @@
#define MAC_ISR_MMCTXIS_WIDTH 1
#define MAC_ISR_PMTIS_INDEX 4
#define MAC_ISR_PMTIS_WIDTH 1
+#define MAC_ISR_SMI_INDEX 1
+#define MAC_ISR_SMI_WIDTH 1
#define MAC_ISR_TSIS_INDEX 12
#define MAC_ISR_TSIS_WIDTH 1
#define MAC_MACA1HR_AE_INDEX 31
#define MAC_MACA1HR_AE_WIDTH 1
+#define MAC_MDIOIER_SNGLCOMPIE_INDEX 12
+#define MAC_MDIOIER_SNGLCOMPIE_WIDTH 1
+#define MAC_MDIOISR_SNGLCOMPINT_INDEX 12
+#define MAC_MDIOISR_SNGLCOMPINT_WIDTH 1
+#define MAC_MDIOSCAR_DA_INDEX 21
+#define MAC_MDIOSCAR_DA_WIDTH 5
+#define MAC_MDIOSCAR_PA_INDEX 16
+#define MAC_MDIOSCAR_PA_WIDTH 5
+#define MAC_MDIOSCAR_RA_INDEX 0
+#define MAC_MDIOSCAR_RA_WIDTH 16
+#define MAC_MDIOSCAR_REG_INDEX 0
+#define MAC_MDIOSCAR_REG_WIDTH 21
+#define MAC_MDIOSCCDR_BUSY_INDEX 22
+#define MAC_MDIOSCCDR_BUSY_WIDTH 1
+#define MAC_MDIOSCCDR_CMD_INDEX 16
+#define MAC_MDIOSCCDR_CMD_WIDTH 2
+#define MAC_MDIOSCCDR_CR_INDEX 19
+#define MAC_MDIOSCCDR_CR_WIDTH 3
+#define MAC_MDIOSCCDR_DATA_INDEX 0
+#define MAC_MDIOSCCDR_DATA_WIDTH 16
+#define MAC_MDIOSCCDR_SADDR_INDEX 18
+#define MAC_MDIOSCCDR_SADDR_WIDTH 1
#define MAC_PFR_HMC_INDEX 2
#define MAC_PFR_HMC_WIDTH 1
#define MAC_PFR_HPF_INDEX 10
@@ -790,6 +821,10 @@
#define MTL_Q_RQOMR_RSF_WIDTH 1
#define MTL_Q_RQOMR_RTC_INDEX 0
#define MTL_Q_RQOMR_RTC_WIDTH 2
+#define MTL_Q_TQDR_TRCSTS_INDEX 1
+#define MTL_Q_TQDR_TRCSTS_WIDTH 2
+#define MTL_Q_TQDR_TXQSTS_INDEX 4
+#define MTL_Q_TQDR_TXQSTS_WIDTH 1
#define MTL_Q_TQOMR_FTQ_INDEX 0
#define MTL_Q_TQOMR_FTQ_WIDTH 1
#define MTL_Q_TQOMR_Q2TCMAP_INDEX 8
@@ -852,14 +887,16 @@
#define MTL_TSA_SP 0x00
#define MTL_TSA_ETS 0x02
-/* PCS MMD select register offset
- * The MMD select register is used for accessing PCS registers
- * when the underlying APB3 interface is using indirect addressing.
- * Indirect addressing requires accessing registers in two phases,
- * an address phase and a data phase. The address phases requires
- * writing an address selection value to the MMD select regiesters.
- */
-#define PCS_MMD_SELECT 0xff
+/* PCS register offsets */
+#define PCS_V1_WINDOW_SELECT 0x03fc
+#define PCS_V2_WINDOW_DEF 0x9060
+#define PCS_V2_WINDOW_SELECT 0x9064
+
+/* PCS register entry bit positions and sizes */
+#define PCS_V2_WINDOW_DEF_OFFSET_INDEX 6
+#define PCS_V2_WINDOW_DEF_OFFSET_WIDTH 14
+#define PCS_V2_WINDOW_DEF_SIZE_INDEX 2
+#define PCS_V2_WINDOW_DEF_SIZE_WIDTH 4
/* SerDes integration register offsets */
#define SIR0_KR_RT_1 0x002c
@@ -903,6 +940,198 @@
#define RXTX_REG129_RXDFE_CONFIG_INDEX 14
#define RXTX_REG129_RXDFE_CONFIG_WIDTH 2
+/* MAC Control register offsets */
+#define XP_PROP_0 0x0000
+#define XP_PROP_1 0x0004
+#define XP_PROP_2 0x0008
+#define XP_PROP_3 0x000c
+#define XP_PROP_4 0x0010
+#define XP_PROP_5 0x0014
+#define XP_MAC_ADDR_LO 0x0020
+#define XP_MAC_ADDR_HI 0x0024
+#define XP_ECC_ISR 0x0030
+#define XP_ECC_IER 0x0034
+#define XP_ECC_CNT0 0x003c
+#define XP_ECC_CNT1 0x0040
+#define XP_DRIVER_INT_REQ 0x0060
+#define XP_DRIVER_INT_RO 0x0064
+#define XP_DRIVER_SCRATCH_0 0x0068
+#define XP_DRIVER_SCRATCH_1 0x006c
+#define XP_INT_EN 0x0078
+#define XP_I2C_MUTEX 0x0080
+#define XP_MDIO_MUTEX 0x0084
+
+/* MAC Control register entry bit positions and sizes */
+#define XP_DRIVER_INT_REQ_REQUEST_INDEX 0
+#define XP_DRIVER_INT_REQ_REQUEST_WIDTH 1
+#define XP_DRIVER_INT_RO_STATUS_INDEX 0
+#define XP_DRIVER_INT_RO_STATUS_WIDTH 1
+#define XP_DRIVER_SCRATCH_0_COMMAND_INDEX 0
+#define XP_DRIVER_SCRATCH_0_COMMAND_WIDTH 8
+#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_INDEX 8
+#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_WIDTH 8
+#define XP_ECC_CNT0_RX_DED_INDEX 24
+#define XP_ECC_CNT0_RX_DED_WIDTH 8
+#define XP_ECC_CNT0_RX_SEC_INDEX 16
+#define XP_ECC_CNT0_RX_SEC_WIDTH 8
+#define XP_ECC_CNT0_TX_DED_INDEX 8
+#define XP_ECC_CNT0_TX_DED_WIDTH 8
+#define XP_ECC_CNT0_TX_SEC_INDEX 0
+#define XP_ECC_CNT0_TX_SEC_WIDTH 8
+#define XP_ECC_CNT1_DESC_DED_INDEX 8
+#define XP_ECC_CNT1_DESC_DED_WIDTH 8
+#define XP_ECC_CNT1_DESC_SEC_INDEX 0
+#define XP_ECC_CNT1_DESC_SEC_WIDTH 8
+#define XP_ECC_IER_DESC_DED_INDEX 0
+#define XP_ECC_IER_DESC_DED_WIDTH 1
+#define XP_ECC_IER_DESC_SEC_INDEX 1
+#define XP_ECC_IER_DESC_SEC_WIDTH 1
+#define XP_ECC_IER_RX_DED_INDEX 2
+#define XP_ECC_IER_RX_DED_WIDTH 1
+#define XP_ECC_IER_RX_SEC_INDEX 3
+#define XP_ECC_IER_RX_SEC_WIDTH 1
+#define XP_ECC_IER_TX_DED_INDEX 4
+#define XP_ECC_IER_TX_DED_WIDTH 1
+#define XP_ECC_IER_TX_SEC_INDEX 5
+#define XP_ECC_IER_TX_SEC_WIDTH 1
+#define XP_ECC_ISR_DESC_DED_INDEX 0
+#define XP_ECC_ISR_DESC_DED_WIDTH 1
+#define XP_ECC_ISR_DESC_SEC_INDEX 1
+#define XP_ECC_ISR_DESC_SEC_WIDTH 1
+#define XP_ECC_ISR_RX_DED_INDEX 2
+#define XP_ECC_ISR_RX_DED_WIDTH 1
+#define XP_ECC_ISR_RX_SEC_INDEX 3
+#define XP_ECC_ISR_RX_SEC_WIDTH 1
+#define XP_ECC_ISR_TX_DED_INDEX 4
+#define XP_ECC_ISR_TX_DED_WIDTH 1
+#define XP_ECC_ISR_TX_SEC_INDEX 5
+#define XP_ECC_ISR_TX_SEC_WIDTH 1
+#define XP_I2C_MUTEX_BUSY_INDEX 31
+#define XP_I2C_MUTEX_BUSY_WIDTH 1
+#define XP_I2C_MUTEX_ID_INDEX 29
+#define XP_I2C_MUTEX_ID_WIDTH 2
+#define XP_I2C_MUTEX_ACTIVE_INDEX 0
+#define XP_I2C_MUTEX_ACTIVE_WIDTH 1
+#define XP_MAC_ADDR_HI_VALID_INDEX 31
+#define XP_MAC_ADDR_HI_VALID_WIDTH 1
+#define XP_PROP_0_CONN_TYPE_INDEX 28
+#define XP_PROP_0_CONN_TYPE_WIDTH 3
+#define XP_PROP_0_MDIO_ADDR_INDEX 16
+#define XP_PROP_0_MDIO_ADDR_WIDTH 5
+#define XP_PROP_0_PORT_ID_INDEX 0
+#define XP_PROP_0_PORT_ID_WIDTH 8
+#define XP_PROP_0_PORT_MODE_INDEX 8
+#define XP_PROP_0_PORT_MODE_WIDTH 4
+#define XP_PROP_0_PORT_SPEEDS_INDEX 23
+#define XP_PROP_0_PORT_SPEEDS_WIDTH 4
+#define XP_PROP_1_MAX_RX_DMA_INDEX 24
+#define XP_PROP_1_MAX_RX_DMA_WIDTH 5
+#define XP_PROP_1_MAX_RX_QUEUES_INDEX 8
+#define XP_PROP_1_MAX_RX_QUEUES_WIDTH 5
+#define XP_PROP_1_MAX_TX_DMA_INDEX 16
+#define XP_PROP_1_MAX_TX_DMA_WIDTH 5
+#define XP_PROP_1_MAX_TX_QUEUES_INDEX 0
+#define XP_PROP_1_MAX_TX_QUEUES_WIDTH 5
+#define XP_PROP_2_RX_FIFO_SIZE_INDEX 16
+#define XP_PROP_2_RX_FIFO_SIZE_WIDTH 16
+#define XP_PROP_2_TX_FIFO_SIZE_INDEX 0
+#define XP_PROP_2_TX_FIFO_SIZE_WIDTH 16
+#define XP_PROP_3_GPIO_MASK_INDEX 28
+#define XP_PROP_3_GPIO_MASK_WIDTH 4
+#define XP_PROP_3_GPIO_MOD_ABS_INDEX 20
+#define XP_PROP_3_GPIO_MOD_ABS_WIDTH 4
+#define XP_PROP_3_GPIO_RATE_SELECT_INDEX 16
+#define XP_PROP_3_GPIO_RATE_SELECT_WIDTH 4
+#define XP_PROP_3_GPIO_RX_LOS_INDEX 24
+#define XP_PROP_3_GPIO_RX_LOS_WIDTH 4
+#define XP_PROP_3_GPIO_TX_FAULT_INDEX 12
+#define XP_PROP_3_GPIO_TX_FAULT_WIDTH 4
+#define XP_PROP_3_GPIO_ADDR_INDEX 8
+#define XP_PROP_3_GPIO_ADDR_WIDTH 3
+#define XP_PROP_3_MDIO_RESET_INDEX 0
+#define XP_PROP_3_MDIO_RESET_WIDTH 2
+#define XP_PROP_3_MDIO_RESET_I2C_ADDR_INDEX 8
+#define XP_PROP_3_MDIO_RESET_I2C_ADDR_WIDTH 3
+#define XP_PROP_3_MDIO_RESET_I2C_GPIO_INDEX 12
+#define XP_PROP_3_MDIO_RESET_I2C_GPIO_WIDTH 4
+#define XP_PROP_3_MDIO_RESET_INT_GPIO_INDEX 4
+#define XP_PROP_3_MDIO_RESET_INT_GPIO_WIDTH 2
+#define XP_PROP_4_MUX_ADDR_HI_INDEX 8
+#define XP_PROP_4_MUX_ADDR_HI_WIDTH 5
+#define XP_PROP_4_MUX_ADDR_LO_INDEX 0
+#define XP_PROP_4_MUX_ADDR_LO_WIDTH 3
+#define XP_PROP_4_MUX_CHAN_INDEX 4
+#define XP_PROP_4_MUX_CHAN_WIDTH 3
+#define XP_PROP_4_REDRV_ADDR_INDEX 16
+#define XP_PROP_4_REDRV_ADDR_WIDTH 7
+#define XP_PROP_4_REDRV_IF_INDEX 23
+#define XP_PROP_4_REDRV_IF_WIDTH 1
+#define XP_PROP_4_REDRV_LANE_INDEX 24
+#define XP_PROP_4_REDRV_LANE_WIDTH 3
+#define XP_PROP_4_REDRV_MODEL_INDEX 28
+#define XP_PROP_4_REDRV_MODEL_WIDTH 3
+#define XP_PROP_4_REDRV_PRESENT_INDEX 31
+#define XP_PROP_4_REDRV_PRESENT_WIDTH 1
+
+/* I2C Control register offsets */
+#define IC_CON 0x0000
+#define IC_TAR 0x0004
+#define IC_DATA_CMD 0x0010
+#define IC_INTR_STAT 0x002c
+#define IC_INTR_MASK 0x0030
+#define IC_RAW_INTR_STAT 0x0034
+#define IC_CLR_INTR 0x0040
+#define IC_CLR_TX_ABRT 0x0054
+#define IC_CLR_STOP_DET 0x0060
+#define IC_ENABLE 0x006c
+#define IC_TXFLR 0x0074
+#define IC_RXFLR 0x0078
+#define IC_TX_ABRT_SOURCE 0x0080
+#define IC_ENABLE_STATUS 0x009c
+#define IC_COMP_PARAM_1 0x00f4
+
+/* I2C Control register entry bit positions and sizes */
+#define IC_COMP_PARAM_1_MAX_SPEED_MODE_INDEX 2
+#define IC_COMP_PARAM_1_MAX_SPEED_MODE_WIDTH 2
+#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_INDEX 8
+#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_WIDTH 8
+#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_INDEX 16
+#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_WIDTH 8
+#define IC_CON_MASTER_MODE_INDEX 0
+#define IC_CON_MASTER_MODE_WIDTH 1
+#define IC_CON_RESTART_EN_INDEX 5
+#define IC_CON_RESTART_EN_WIDTH 1
+#define IC_CON_RX_FIFO_FULL_HOLD_INDEX 9
+#define IC_CON_RX_FIFO_FULL_HOLD_WIDTH 1
+#define IC_CON_SLAVE_DISABLE_INDEX 6
+#define IC_CON_SLAVE_DISABLE_WIDTH 1
+#define IC_CON_SPEED_INDEX 1
+#define IC_CON_SPEED_WIDTH 2
+#define IC_DATA_CMD_CMD_INDEX 8
+#define IC_DATA_CMD_CMD_WIDTH 1
+#define IC_DATA_CMD_STOP_INDEX 9
+#define IC_DATA_CMD_STOP_WIDTH 1
+#define IC_ENABLE_ABORT_INDEX 1
+#define IC_ENABLE_ABORT_WIDTH 1
+#define IC_ENABLE_EN_INDEX 0
+#define IC_ENABLE_EN_WIDTH 1
+#define IC_ENABLE_STATUS_EN_INDEX 0
+#define IC_ENABLE_STATUS_EN_WIDTH 1
+#define IC_INTR_MASK_TX_EMPTY_INDEX 4
+#define IC_INTR_MASK_TX_EMPTY_WIDTH 1
+#define IC_RAW_INTR_STAT_RX_FULL_INDEX 2
+#define IC_RAW_INTR_STAT_RX_FULL_WIDTH 1
+#define IC_RAW_INTR_STAT_STOP_DET_INDEX 9
+#define IC_RAW_INTR_STAT_STOP_DET_WIDTH 1
+#define IC_RAW_INTR_STAT_TX_ABRT_INDEX 6
+#define IC_RAW_INTR_STAT_TX_ABRT_WIDTH 1
+#define IC_RAW_INTR_STAT_TX_EMPTY_INDEX 4
+#define IC_RAW_INTR_STAT_TX_EMPTY_WIDTH 1
+
+/* I2C Control register value */
+#define IC_TX_ABRT_7B_ADDR_NOACK 0x0001
+#define IC_TX_ABRT_ARB_LOST 0x1000
+
/* Descriptor/Packet entry bit positions and sizes */
#define RX_PACKET_ERRORS_CRC_INDEX 2
#define RX_PACKET_ERRORS_CRC_WIDTH 1
@@ -1027,6 +1256,10 @@
#define MDIO_PMA_10GBR_FECCTRL 0x00ab
#endif
+#ifndef MDIO_PCS_DIG_CTRL
+#define MDIO_PCS_DIG_CTRL 0x8000
+#endif
+
#ifndef MDIO_AN_XNP
#define MDIO_AN_XNP 0x0016
#endif
@@ -1047,11 +1280,48 @@
#define MDIO_AN_INT 0x8002
#endif
+#ifndef MDIO_VEND2_AN_ADVERTISE
+#define MDIO_VEND2_AN_ADVERTISE 0x0004
+#endif
+
+#ifndef MDIO_VEND2_AN_LP_ABILITY
+#define MDIO_VEND2_AN_LP_ABILITY 0x0005
+#endif
+
+#ifndef MDIO_VEND2_AN_CTRL
+#define MDIO_VEND2_AN_CTRL 0x8001
+#endif
+
+#ifndef MDIO_VEND2_AN_STAT
+#define MDIO_VEND2_AN_STAT 0x8002
+#endif
+
#ifndef MDIO_CTRL1_SPEED1G
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
#endif
+#ifndef MDIO_VEND2_CTRL1_AN_ENABLE
+#define MDIO_VEND2_CTRL1_AN_ENABLE BIT(12)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_AN_RESTART
+#define MDIO_VEND2_CTRL1_AN_RESTART BIT(9)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_SS6
+#define MDIO_VEND2_CTRL1_SS6 BIT(6)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_SS13
+#define MDIO_VEND2_CTRL1_SS13 BIT(13)
+#endif
+
/* MDIO mask values */
+#define XGBE_AN_CL73_INT_CMPLT BIT(0)
+#define XGBE_AN_CL73_INC_LINK BIT(1)
+#define XGBE_AN_CL73_PG_RCV BIT(2)
+#define XGBE_AN_CL73_INT_MASK 0x07
+
#define XGBE_XNP_MCF_NULL_MESSAGE 0x001
#define XGBE_XNP_ACK_PROCESSED BIT(12)
#define XGBE_XNP_MP_FORMATTED BIT(13)
@@ -1060,6 +1330,19 @@
#define XGBE_KR_TRAINING_START BIT(0)
#define XGBE_KR_TRAINING_ENABLE BIT(1)
+#define XGBE_PCS_CL37_BP BIT(12)
+
+#define XGBE_AN_CL37_INT_CMPLT BIT(0)
+#define XGBE_AN_CL37_INT_MASK 0x01
+
+#define XGBE_AN_CL37_HD_MASK 0x40
+#define XGBE_AN_CL37_FD_MASK 0x20
+
+#define XGBE_AN_CL37_PCS_MODE_MASK 0x06
+#define XGBE_AN_CL37_PCS_MODE_BASEX 0x00
+#define XGBE_AN_CL37_PCS_MODE_SGMII 0x04
+#define XGBE_AN_CL37_TX_CONFIG_MASK 0x08
+
/* Bit setting and getting macros
* The get macro will extract the current bit field value from within
* the variable
@@ -1195,12 +1478,28 @@ do { \
/* Macros for building, reading or writing register values or bits
* within the register values of XPCS registers.
*/
-#define XPCS_IOWRITE(_pdata, _off, _val) \
+#define XPCS_GET_BITS(_var, _prefix, _field) \
+ GET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH)
+
+#define XPCS_SET_BITS(_var, _prefix, _field, _val) \
+ SET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH, (_val))
+
+#define XPCS32_IOWRITE(_pdata, _off, _val) \
iowrite32(_val, (_pdata)->xpcs_regs + (_off))
-#define XPCS_IOREAD(_pdata, _off) \
+#define XPCS32_IOREAD(_pdata, _off) \
ioread32((_pdata)->xpcs_regs + (_off))
+#define XPCS16_IOWRITE(_pdata, _off, _val) \
+ iowrite16(_val, (_pdata)->xpcs_regs + (_off))
+
+#define XPCS16_IOREAD(_pdata, _off) \
+ ioread16((_pdata)->xpcs_regs + (_off))
+
/* Macros for building, reading or writing register values or bits
* within the register values of SerDes integration registers.
*/
@@ -1278,6 +1577,72 @@ do { \
} while (0)
/* Macros for building, reading or writing register values or bits
+ * within the register values of MAC Control registers.
+ */
+#define XP_GET_BITS(_var, _prefix, _field) \
+ GET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH)
+
+#define XP_SET_BITS(_var, _prefix, _field, _val) \
+ SET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH, (_val))
+
+#define XP_IOREAD(_pdata, _reg) \
+ ioread32((_pdata)->xprop_regs + (_reg))
+
+#define XP_IOREAD_BITS(_pdata, _reg, _field) \
+ GET_BITS(XP_IOREAD((_pdata), (_reg)), \
+ _reg##_##_field##_INDEX, \
+ _reg##_##_field##_WIDTH)
+
+#define XP_IOWRITE(_pdata, _reg, _val) \
+ iowrite32((_val), (_pdata)->xprop_regs + (_reg))
+
+#define XP_IOWRITE_BITS(_pdata, _reg, _field, _val) \
+do { \
+ u32 reg_val = XP_IOREAD((_pdata), (_reg)); \
+ SET_BITS(reg_val, \
+ _reg##_##_field##_INDEX, \
+ _reg##_##_field##_WIDTH, (_val)); \
+ XP_IOWRITE((_pdata), (_reg), reg_val); \
+} while (0)
+
+/* Macros for building, reading or writing register values or bits
+ * within the register values of I2C Control registers.
+ */
+#define XI2C_GET_BITS(_var, _prefix, _field) \
+ GET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH)
+
+#define XI2C_SET_BITS(_var, _prefix, _field, _val) \
+ SET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH, (_val))
+
+#define XI2C_IOREAD(_pdata, _reg) \
+ ioread32((_pdata)->xi2c_regs + (_reg))
+
+#define XI2C_IOREAD_BITS(_pdata, _reg, _field) \
+ GET_BITS(XI2C_IOREAD((_pdata), (_reg)), \
+ _reg##_##_field##_INDEX, \
+ _reg##_##_field##_WIDTH)
+
+#define XI2C_IOWRITE(_pdata, _reg, _val) \
+ iowrite32((_val), (_pdata)->xi2c_regs + (_reg))
+
+#define XI2C_IOWRITE_BITS(_pdata, _reg, _field, _val) \
+do { \
+ u32 reg_val = XI2C_IOREAD((_pdata), (_reg)); \
+ SET_BITS(reg_val, \
+ _reg##_##_field##_INDEX, \
+ _reg##_##_field##_WIDTH, (_val)); \
+ XI2C_IOWRITE((_pdata), (_reg), reg_val); \
+} while (0)
+
+/* Macros for building, reading or writing register values or bits
* using MDIO. Different from above because of the use of standardized
* Linux include values. No shifting is performed with the bit
* operations, everything works on mask values.
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 96f485ab612e..7546b660d6b5 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -153,7 +153,7 @@ static ssize_t xgbe_common_write(const char __user *buffer, size_t count,
int ret;
if (*ppos != 0)
- return 0;
+ return -EINVAL;
if (count >= sizeof(workarea))
return -ENOSPC;
@@ -316,6 +316,126 @@ static const struct file_operations xpcs_reg_value_fops = {
.write = xpcs_reg_value_write,
};
+static ssize_t xprop_reg_addr_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+
+ return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xprop_reg);
+}
+
+static ssize_t xprop_reg_addr_write(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+
+ return xgbe_common_write(buffer, count, ppos,
+ &pdata->debugfs_xprop_reg);
+}
+
+static ssize_t xprop_reg_value_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+ unsigned int value;
+
+ value = XP_IOREAD(pdata, pdata->debugfs_xprop_reg);
+
+ return xgbe_common_read(buffer, count, ppos, value);
+}
+
+static ssize_t xprop_reg_value_write(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+ unsigned int value;
+ ssize_t len;
+
+ len = xgbe_common_write(buffer, count, ppos, &value);
+ if (len < 0)
+ return len;
+
+ XP_IOWRITE(pdata, pdata->debugfs_xprop_reg, value);
+
+ return len;
+}
+
+static const struct file_operations xprop_reg_addr_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = xprop_reg_addr_read,
+ .write = xprop_reg_addr_write,
+};
+
+static const struct file_operations xprop_reg_value_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = xprop_reg_value_read,
+ .write = xprop_reg_value_write,
+};
+
+static ssize_t xi2c_reg_addr_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+
+ return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xi2c_reg);
+}
+
+static ssize_t xi2c_reg_addr_write(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+
+ return xgbe_common_write(buffer, count, ppos,
+ &pdata->debugfs_xi2c_reg);
+}
+
+static ssize_t xi2c_reg_value_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+ unsigned int value;
+
+ value = XI2C_IOREAD(pdata, pdata->debugfs_xi2c_reg);
+
+ return xgbe_common_read(buffer, count, ppos, value);
+}
+
+static ssize_t xi2c_reg_value_write(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct xgbe_prv_data *pdata = filp->private_data;
+ unsigned int value;
+ ssize_t len;
+
+ len = xgbe_common_write(buffer, count, ppos, &value);
+ if (len < 0)
+ return len;
+
+ XI2C_IOWRITE(pdata, pdata->debugfs_xi2c_reg, value);
+
+ return len;
+}
+
+static const struct file_operations xi2c_reg_addr_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = xi2c_reg_addr_read,
+ .write = xi2c_reg_addr_write,
+};
+
+static const struct file_operations xi2c_reg_value_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = xi2c_reg_value_read,
+ .write = xi2c_reg_value_write,
+};
+
void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
{
struct dentry *pfile;
@@ -367,6 +487,38 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
if (!pfile)
netdev_err(pdata->netdev, "debugfs_create_file failed\n");
+ if (pdata->xprop_regs) {
+ pfile = debugfs_create_file("xprop_register", 0600,
+ pdata->xgbe_debugfs, pdata,
+ &xprop_reg_addr_fops);
+ if (!pfile)
+ netdev_err(pdata->netdev,
+ "debugfs_create_file failed\n");
+
+ pfile = debugfs_create_file("xprop_register_value", 0600,
+ pdata->xgbe_debugfs, pdata,
+ &xprop_reg_value_fops);
+ if (!pfile)
+ netdev_err(pdata->netdev,
+ "debugfs_create_file failed\n");
+ }
+
+ if (pdata->xi2c_regs) {
+ pfile = debugfs_create_file("xi2c_register", 0600,
+ pdata->xgbe_debugfs, pdata,
+ &xi2c_reg_addr_fops);
+ if (!pfile)
+ netdev_err(pdata->netdev,
+ "debugfs_create_file failed\n");
+
+ pfile = debugfs_create_file("xi2c_register_value", 0600,
+ pdata->xgbe_debugfs, pdata,
+ &xi2c_reg_value_fops);
+ if (!pfile)
+ netdev_err(pdata->netdev,
+ "debugfs_create_file failed\n");
+ }
+
kfree(buf);
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 1babcc11a248..aaf0350076a9 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -123,6 +123,11 @@
#include "xgbe.h"
#include "xgbe-common.h"
+static inline unsigned int xgbe_get_max_frame(struct xgbe_prv_data *pdata)
+{
+ return pdata->netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+}
+
static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata,
unsigned int usec)
{
@@ -491,6 +496,27 @@ static void xgbe_config_rss(struct xgbe_prv_data *pdata)
"error configuring RSS, RSS disabled\n");
}
+static bool xgbe_is_pfc_queue(struct xgbe_prv_data *pdata,
+ unsigned int queue)
+{
+ unsigned int prio, tc;
+
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+ /* Does this queue handle the priority? */
+ if (pdata->prio2q_map[prio] != queue)
+ continue;
+
+ /* Get the Traffic Class for this priority */
+ tc = pdata->ets->prio_tc[prio];
+
+ /* Check if PFC is enabled for this traffic class */
+ if (pdata->pfc->pfc_en & (1 << tc))
+ return true;
+ }
+
+ return false;
+}
+
static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
{
unsigned int max_q_count, q_count;
@@ -528,27 +554,14 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
for (i = 0; i < pdata->rx_q_count; i++) {
unsigned int ehfc = 0;
- if (pfc && ets) {
- unsigned int prio;
-
- for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
- unsigned int tc;
-
- /* Does this queue handle the priority? */
- if (pdata->prio2q_map[prio] != i)
- continue;
-
- /* Get the Traffic Class for this priority */
- tc = ets->prio_tc[prio];
-
- /* Check if flow control should be enabled */
- if (pfc->pfc_en & (1 << tc)) {
+ if (pdata->rx_rfd[i]) {
+ /* Flow control thresholds are established */
+ if (pfc && ets) {
+ if (xgbe_is_pfc_queue(pdata, i))
ehfc = 1;
- break;
- }
+ } else {
+ ehfc = 1;
}
- } else {
- ehfc = 1;
}
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc);
@@ -633,6 +646,11 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
unsigned int dma_ch_isr, dma_ch_ier;
unsigned int i;
+ /* Set the interrupt mode if supported */
+ if (pdata->channel_irq_mode)
+ XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM,
+ pdata->channel_irq_mode);
+
channel = pdata->channel;
for (i = 0; i < pdata->channel_count; i++, channel++) {
/* Clear all the interrupts which are set */
@@ -654,19 +672,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
if (channel->tx_ring) {
/* Enable the following Tx interrupts
* TIE - Transmit Interrupt Enable (unless using
- * per channel interrupts)
+ * per channel interrupts in edge triggered
+ * mode)
*/
- if (!pdata->per_channel_irq)
+ if (!pdata->per_channel_irq || pdata->channel_irq_mode)
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
}
if (channel->rx_ring) {
/* Enable following Rx interrupts
* RBUE - Receive Buffer Unavailable Enable
* RIE - Receive Interrupt Enable (unless using
- * per channel interrupts)
+ * per channel interrupts in edge triggered
+ * mode)
*/
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
- if (!pdata->per_channel_irq)
+ if (!pdata->per_channel_irq || pdata->channel_irq_mode)
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
}
@@ -702,34 +722,90 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
/* Enable all counter interrupts */
XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff);
XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
+
+ /* Enable MDIO single command completion interrupt */
+ XGMAC_IOWRITE_BITS(pdata, MAC_MDIOIER, SNGLCOMPIE, 1);
}
-static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
+static void xgbe_enable_ecc_interrupts(struct xgbe_prv_data *pdata)
{
- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3)
- return 0;
+ unsigned int ecc_isr, ecc_ier = 0;
- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3);
+ if (!pdata->vdata->ecc_support)
+ return;
- return 0;
+ /* Clear all the interrupts which are set */
+ ecc_isr = XP_IOREAD(pdata, XP_ECC_ISR);
+ XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
+
+ /* Enable ECC interrupts */
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_DED, 1);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_SEC, 1);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_DED, 1);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_SEC, 1);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_DED, 1);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_SEC, 1);
+
+ XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
}
-static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
+static void xgbe_disable_ecc_ded(struct xgbe_prv_data *pdata)
{
- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2)
- return 0;
+ unsigned int ecc_ier;
- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2);
+ ecc_ier = XP_IOREAD(pdata, XP_ECC_IER);
- return 0;
+ /* Disable ECC DED interrupts */
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_DED, 0);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_DED, 0);
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_DED, 0);
+
+ XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
}
-static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
+static void xgbe_disable_ecc_sec(struct xgbe_prv_data *pdata,
+ enum xgbe_ecc_sec sec)
{
- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0)
- return 0;
+ unsigned int ecc_ier;
+
+ ecc_ier = XP_IOREAD(pdata, XP_ECC_IER);
+
+ /* Disable ECC SEC interrupt */
+ switch (sec) {
+ case XGBE_ECC_SEC_TX:
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_SEC, 0);
+ break;
+ case XGBE_ECC_SEC_RX:
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_SEC, 0);
+ break;
+ case XGBE_ECC_SEC_DESC:
+ XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_SEC, 0);
+ break;
+ }
- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0);
+ XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
+}
+
+static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed)
+{
+ unsigned int ss;
+
+ switch (speed) {
+ case SPEED_1000:
+ ss = 0x03;
+ break;
+ case SPEED_2500:
+ ss = 0x02;
+ break;
+ case SPEED_10000:
+ ss = 0x00;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
return 0;
}
@@ -1019,8 +1095,101 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata)
return 0;
}
-static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
- int mmd_reg)
+static int xgbe_clr_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
+{
+ unsigned int reg;
+
+ if (gpio > 15)
+ return -EINVAL;
+
+ reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
+
+ reg &= ~(1 << (gpio + 16));
+ XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
+
+ return 0;
+}
+
+static int xgbe_set_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
+{
+ unsigned int reg;
+
+ if (gpio > 15)
+ return -EINVAL;
+
+ reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
+
+ reg |= (1 << (gpio + 16));
+ XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
+
+ return 0;
+}
+
+static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg)
+{
+ unsigned long flags;
+ unsigned int mmd_address, index, offset;
+ int mmd_data;
+
+ if (mmd_reg & MII_ADDR_C45)
+ mmd_address = mmd_reg & ~MII_ADDR_C45;
+ else
+ mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
+
+ /* The PCS registers are accessed using mmio. The underlying
+ * management interface uses indirect addressing to access the MMD
+ * register sets. This requires accessing of the PCS register in two
+ * phases, an address phase and a data phase.
+ *
+ * The mmio interface is based on 16-bit offsets and values. All
+ * register offsets must therefore be adjusted by left shifting the
+ * offset 1 bit and reading 16 bits of data.
+ */
+ mmd_address <<= 1;
+ index = mmd_address & ~pdata->xpcs_window_mask;
+ offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
+
+ spin_lock_irqsave(&pdata->xpcs_lock, flags);
+ XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+ mmd_data = XPCS16_IOREAD(pdata, offset);
+ spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+
+ return mmd_data;
+}
+
+static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg, int mmd_data)
+{
+ unsigned long flags;
+ unsigned int mmd_address, index, offset;
+
+ if (mmd_reg & MII_ADDR_C45)
+ mmd_address = mmd_reg & ~MII_ADDR_C45;
+ else
+ mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
+
+ /* The PCS registers are accessed using mmio. The underlying
+ * management interface uses indirect addressing to access the MMD
+ * register sets. This requires accessing of the PCS register in two
+ * phases, an address phase and a data phase.
+ *
+ * The mmio interface is based on 16-bit offsets and values. All
+ * register offsets must therefore be adjusted by left shifting the
+ * offset 1 bit and writing 16 bits of data.
+ */
+ mmd_address <<= 1;
+ index = mmd_address & ~pdata->xpcs_window_mask;
+ offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
+
+ spin_lock_irqsave(&pdata->xpcs_lock, flags);
+ XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+ XPCS16_IOWRITE(pdata, offset, mmd_data);
+ spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+}
+
+static int xgbe_read_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg)
{
unsigned long flags;
unsigned int mmd_address;
@@ -1041,15 +1210,15 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
* offset 2 bits and reading 32 bits of data.
*/
spin_lock_irqsave(&pdata->xpcs_lock, flags);
- XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
- mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2);
+ XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
+ mmd_data = XPCS32_IOREAD(pdata, (mmd_address & 0xff) << 2);
spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
return mmd_data;
}
-static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
- int mmd_reg, int mmd_data)
+static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg, int mmd_data)
{
unsigned int mmd_address;
unsigned long flags;
@@ -1066,14 +1235,113 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
*
* The mmio interface is based on 32-bit offsets and values. All
* register offsets must therefore be adjusted by left shifting the
- * offset 2 bits and reading 32 bits of data.
+ * offset 2 bits and writing 32 bits of data.
*/
spin_lock_irqsave(&pdata->xpcs_lock, flags);
- XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
- XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
+ XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
+ XPCS32_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
}
+static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg)
+{
+ switch (pdata->vdata->xpcs_access) {
+ case XGBE_XPCS_ACCESS_V1:
+ return xgbe_read_mmd_regs_v1(pdata, prtad, mmd_reg);
+
+ case XGBE_XPCS_ACCESS_V2:
+ default:
+ return xgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg);
+ }
+}
+
+static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg, int mmd_data)
+{
+ switch (pdata->vdata->xpcs_access) {
+ case XGBE_XPCS_ACCESS_V1:
+ return xgbe_write_mmd_regs_v1(pdata, prtad, mmd_reg, mmd_data);
+
+ case XGBE_XPCS_ACCESS_V2:
+ default:
+ return xgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data);
+ }
+}
+
+static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
+ int reg, u16 val)
+{
+ unsigned int mdio_sca, mdio_sccd;
+
+ reinit_completion(&pdata->mdio_complete);
+
+ mdio_sca = 0;
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+ XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
+
+ mdio_sccd = 0;
+ XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
+ XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
+ XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
+ XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
+
+ if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
+ netdev_err(pdata->netdev, "mdio write operation timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
+ int reg)
+{
+ unsigned int mdio_sca, mdio_sccd;
+
+ reinit_completion(&pdata->mdio_complete);
+
+ mdio_sca = 0;
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+ XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
+
+ mdio_sccd = 0;
+ XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3);
+ XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
+ XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
+
+ if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
+ netdev_err(pdata->netdev, "mdio read operation timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ return XGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
+}
+
+static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port,
+ enum xgbe_mdio_mode mode)
+{
+ unsigned int reg_val = 0;
+
+ switch (mode) {
+ case XGBE_MDIO_MODE_CL22:
+ if (port > XGMAC_MAX_C22_PORT)
+ return -EINVAL;
+ reg_val |= (1 << port);
+ break;
+ case XGBE_MDIO_MODE_CL45:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ XGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val);
+
+ return 0;
+}
+
static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
{
return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
@@ -1264,14 +1532,21 @@ static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)
static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
{
- unsigned int tx_snr;
+ unsigned int tx_snr, tx_ssr;
u64 nsec;
- tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+ if (pdata->vdata->tx_tstamp_workaround) {
+ tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+ tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
+ } else {
+ tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
+ tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+ }
+
if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS))
return 0;
- nsec = XGMAC_IOREAD(pdata, MAC_TXSSR);
+ nsec = tx_ssr;
nsec *= NSEC_PER_SEC;
nsec += tx_snr;
@@ -1327,106 +1602,6 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
return 0;
}
-static void xgbe_config_tc(struct xgbe_prv_data *pdata)
-{
- unsigned int offset, queue, prio;
- u8 i;
-
- netdev_reset_tc(pdata->netdev);
- if (!pdata->num_tcs)
- return;
-
- netdev_set_num_tc(pdata->netdev, pdata->num_tcs);
-
- for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) {
- while ((queue < pdata->tx_q_count) &&
- (pdata->q2tc_map[queue] == i))
- queue++;
-
- netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n",
- i, offset, queue - 1);
- netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset);
- offset = queue;
- }
-
- if (!pdata->ets)
- return;
-
- for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
- netdev_set_prio_tc_map(pdata->netdev, prio,
- pdata->ets->prio_tc[prio]);
-}
-
-static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
-{
- struct ieee_ets *ets = pdata->ets;
- unsigned int total_weight, min_weight, weight;
- unsigned int mask, reg, reg_val;
- unsigned int i, prio;
-
- if (!ets)
- return;
-
- /* Set Tx to deficit weighted round robin scheduling algorithm (when
- * traffic class is using ETS algorithm)
- */
- XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR);
-
- /* Set Traffic Class algorithms */
- total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt;
- min_weight = total_weight / 100;
- if (!min_weight)
- min_weight = 1;
-
- for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
- /* Map the priorities to the traffic class */
- mask = 0;
- for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
- if (ets->prio_tc[prio] == i)
- mask |= (1 << prio);
- }
- mask &= 0xff;
-
- netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n",
- i, mask);
- reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG));
- reg_val = XGMAC_IOREAD(pdata, reg);
-
- reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3));
- reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3));
-
- XGMAC_IOWRITE(pdata, reg, reg_val);
-
- /* Set the traffic class algorithm */
- switch (ets->tc_tsa[i]) {
- case IEEE_8021QAZ_TSA_STRICT:
- netif_dbg(pdata, drv, pdata->netdev,
- "TC%u using SP\n", i);
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
- MTL_TSA_SP);
- break;
- case IEEE_8021QAZ_TSA_ETS:
- weight = total_weight * ets->tc_tx_bw[i] / 100;
- weight = clamp(weight, min_weight, total_weight);
-
- netif_dbg(pdata, drv, pdata->netdev,
- "TC%u using DWRR (weight %u)\n", i, weight);
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
- MTL_TSA_ETS);
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW,
- weight);
- break;
- }
- }
-
- xgbe_config_tc(pdata);
-}
-
-static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
-{
- xgbe_config_flow_control(pdata);
-}
-
static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
struct xgbe_ring *ring)
{
@@ -1901,7 +2076,7 @@ static int xgbe_disable_int(struct xgbe_channel *channel,
return 0;
}
-static int xgbe_exit(struct xgbe_prv_data *pdata)
+static int __xgbe_exit(struct xgbe_prv_data *pdata)
{
unsigned int count = 2000;
@@ -1923,6 +2098,20 @@ static int xgbe_exit(struct xgbe_prv_data *pdata)
return 0;
}
+static int xgbe_exit(struct xgbe_prv_data *pdata)
+{
+ int ret;
+
+ /* To guard against possible incorrectly generated interrupts,
+ * issue the software reset twice.
+ */
+ ret = __xgbe_exit(pdata);
+ if (ret)
+ return ret;
+
+ return __xgbe_exit(pdata);
+}
+
static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata)
{
unsigned int i, count;
@@ -2000,61 +2189,331 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
}
-static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
- unsigned int queue_count)
+static void xgbe_queue_flow_control_threshold(struct xgbe_prv_data *pdata,
+ unsigned int queue,
+ unsigned int q_fifo_size)
+{
+ unsigned int frame_fifo_size;
+ unsigned int rfa, rfd;
+
+ frame_fifo_size = XGMAC_FLOW_CONTROL_ALIGN(xgbe_get_max_frame(pdata));
+
+ if (pdata->pfcq[queue] && (q_fifo_size > pdata->pfc_rfa)) {
+ /* PFC is active for this queue */
+ rfa = pdata->pfc_rfa;
+ rfd = rfa + frame_fifo_size;
+ if (rfd > XGMAC_FLOW_CONTROL_MAX)
+ rfd = XGMAC_FLOW_CONTROL_MAX;
+ if (rfa >= XGMAC_FLOW_CONTROL_MAX)
+ rfa = XGMAC_FLOW_CONTROL_MAX - XGMAC_FLOW_CONTROL_UNIT;
+ } else {
+ /* This path deals with just maximum frame sizes which are
+ * limited to a jumbo frame of 9,000 (plus headers, etc.)
+ * so we can never exceed the maximum allowable RFA/RFD
+ * values.
+ */
+ if (q_fifo_size <= 2048) {
+ /* rx_rfd to zero to signal no flow control */
+ pdata->rx_rfa[queue] = 0;
+ pdata->rx_rfd[queue] = 0;
+ return;
+ }
+
+ if (q_fifo_size <= 4096) {
+ /* Between 2048 and 4096 */
+ pdata->rx_rfa[queue] = 0; /* Full - 1024 bytes */
+ pdata->rx_rfd[queue] = 1; /* Full - 1536 bytes */
+ return;
+ }
+
+ if (q_fifo_size <= frame_fifo_size) {
+ /* Between 4096 and max-frame */
+ pdata->rx_rfa[queue] = 2; /* Full - 2048 bytes */
+ pdata->rx_rfd[queue] = 5; /* Full - 3584 bytes */
+ return;
+ }
+
+ if (q_fifo_size <= (frame_fifo_size * 3)) {
+ /* Between max-frame and 3 max-frames,
+ * trigger if we get just over a frame of data and
+ * resume when we have just under half a frame left.
+ */
+ rfa = q_fifo_size - frame_fifo_size;
+ rfd = rfa + (frame_fifo_size / 2);
+ } else {
+ /* Above 3 max-frames - trigger when just over
+ * 2 frames of space available
+ */
+ rfa = frame_fifo_size * 2;
+ rfa += XGMAC_FLOW_CONTROL_UNIT;
+ rfd = rfa + frame_fifo_size;
+ }
+ }
+
+ pdata->rx_rfa[queue] = XGMAC_FLOW_CONTROL_VALUE(rfa);
+ pdata->rx_rfd[queue] = XGMAC_FLOW_CONTROL_VALUE(rfd);
+}
+
+static void xgbe_calculate_flow_control_threshold(struct xgbe_prv_data *pdata,
+ unsigned int *fifo)
{
unsigned int q_fifo_size;
- unsigned int p_fifo;
+ unsigned int i;
- /* Calculate the configured fifo size */
- q_fifo_size = 1 << (fifo_size + 7);
+ for (i = 0; i < pdata->rx_q_count; i++) {
+ q_fifo_size = (fifo[i] + 1) * XGMAC_FIFO_UNIT;
+ xgbe_queue_flow_control_threshold(pdata, i, q_fifo_size);
+ }
+}
+
+static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
+{
+ unsigned int i;
+
+ for (i = 0; i < pdata->rx_q_count; i++) {
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA,
+ pdata->rx_rfa[i]);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD,
+ pdata->rx_rfd[i]);
+ }
+}
+
+static unsigned int xgbe_get_tx_fifo_size(struct xgbe_prv_data *pdata)
+{
/* 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);
+ return min_t(unsigned int, pdata->tx_max_fifo_size,
+ pdata->hw_feat.tx_fifo_size);
+}
- q_fifo_size = q_fifo_size / queue_count;
+static unsigned int xgbe_get_rx_fifo_size(struct xgbe_prv_data *pdata)
+{
+ /* The configured value may not be the actual amount of fifo RAM */
+ return min_t(unsigned int, pdata->rx_max_fifo_size,
+ pdata->hw_feat.rx_fifo_size);
+}
- /* Each increment in the queue fifo size represents 256 bytes of
- * fifo, with 0 representing 256 bytes. Distribute the fifo equally
- * between the queues.
+static void xgbe_calculate_equal_fifo(unsigned int fifo_size,
+ unsigned int queue_count,
+ unsigned int *fifo)
+{
+ unsigned int q_fifo_size;
+ unsigned int p_fifo;
+ unsigned int i;
+
+ q_fifo_size = fifo_size / queue_count;
+
+ /* Calculate the fifo setting by dividing the queue's fifo size
+ * by the fifo allocation increment (with 0 representing the
+ * base allocation increment so decrement the result by 1).
*/
- p_fifo = q_fifo_size / 256;
+ p_fifo = q_fifo_size / XGMAC_FIFO_UNIT;
if (p_fifo)
p_fifo--;
- return p_fifo;
+ /* Distribute the fifo equally amongst the queues */
+ for (i = 0; i < queue_count; i++)
+ fifo[i] = p_fifo;
+}
+
+static unsigned int xgbe_set_nonprio_fifos(unsigned int fifo_size,
+ unsigned int queue_count,
+ unsigned int *fifo)
+{
+ unsigned int i;
+
+ BUILD_BUG_ON_NOT_POWER_OF_2(XGMAC_FIFO_MIN_ALLOC);
+
+ if (queue_count <= IEEE_8021QAZ_MAX_TCS)
+ return fifo_size;
+
+ /* Rx queues 9 and up are for specialized packets,
+ * such as PTP or DCB control packets, etc. and
+ * don't require a large fifo
+ */
+ for (i = IEEE_8021QAZ_MAX_TCS; i < queue_count; i++) {
+ fifo[i] = (XGMAC_FIFO_MIN_ALLOC / XGMAC_FIFO_UNIT) - 1;
+ fifo_size -= XGMAC_FIFO_MIN_ALLOC;
+ }
+
+ return fifo_size;
+}
+
+static unsigned int xgbe_get_pfc_delay(struct xgbe_prv_data *pdata)
+{
+ unsigned int delay;
+
+ /* If a delay has been provided, use that */
+ if (pdata->pfc->delay)
+ return pdata->pfc->delay / 8;
+
+ /* Allow for two maximum size frames */
+ delay = xgbe_get_max_frame(pdata);
+ delay += XGMAC_ETH_PREAMBLE;
+ delay *= 2;
+
+ /* Allow for PFC frame */
+ delay += XGMAC_PFC_DATA_LEN;
+ delay += ETH_HLEN + ETH_FCS_LEN;
+ delay += XGMAC_ETH_PREAMBLE;
+
+ /* Allow for miscellaneous delays (LPI exit, cable, etc.) */
+ delay += XGMAC_PFC_DELAYS;
+
+ return delay;
+}
+
+static unsigned int xgbe_get_pfc_queues(struct xgbe_prv_data *pdata)
+{
+ unsigned int count, prio_queues;
+ unsigned int i;
+
+ if (!pdata->pfc->pfc_en)
+ return 0;
+
+ count = 0;
+ prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+ for (i = 0; i < prio_queues; i++) {
+ if (!xgbe_is_pfc_queue(pdata, i))
+ continue;
+
+ pdata->pfcq[i] = 1;
+ count++;
+ }
+
+ return count;
+}
+
+static void xgbe_calculate_dcb_fifo(struct xgbe_prv_data *pdata,
+ unsigned int fifo_size,
+ unsigned int *fifo)
+{
+ unsigned int q_fifo_size, rem_fifo, addn_fifo;
+ unsigned int prio_queues;
+ unsigned int pfc_count;
+ unsigned int i;
+
+ q_fifo_size = XGMAC_FIFO_ALIGN(xgbe_get_max_frame(pdata));
+ prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+ pfc_count = xgbe_get_pfc_queues(pdata);
+
+ if (!pfc_count || ((q_fifo_size * prio_queues) > fifo_size)) {
+ /* No traffic classes with PFC enabled or can't do lossless */
+ xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo);
+ return;
+ }
+
+ /* Calculate how much fifo we have to play with */
+ rem_fifo = fifo_size - (q_fifo_size * prio_queues);
+
+ /* Calculate how much more than base fifo PFC needs, which also
+ * becomes the threshold activation point (RFA)
+ */
+ pdata->pfc_rfa = xgbe_get_pfc_delay(pdata);
+ pdata->pfc_rfa = XGMAC_FLOW_CONTROL_ALIGN(pdata->pfc_rfa);
+
+ if (pdata->pfc_rfa > q_fifo_size) {
+ addn_fifo = pdata->pfc_rfa - q_fifo_size;
+ addn_fifo = XGMAC_FIFO_ALIGN(addn_fifo);
+ } else {
+ addn_fifo = 0;
+ }
+
+ /* Calculate DCB fifo settings:
+ * - distribute remaining fifo between the VLAN priority
+ * queues based on traffic class PFC enablement and overall
+ * priority (0 is lowest priority, so start at highest)
+ */
+ i = prio_queues;
+ while (i > 0) {
+ i--;
+
+ fifo[i] = (q_fifo_size / XGMAC_FIFO_UNIT) - 1;
+
+ if (!pdata->pfcq[i] || !addn_fifo)
+ continue;
+
+ if (addn_fifo > rem_fifo) {
+ netdev_warn(pdata->netdev,
+ "RXq%u cannot set needed fifo size\n", i);
+ if (!rem_fifo)
+ continue;
+
+ addn_fifo = rem_fifo;
+ }
+
+ fifo[i] += (addn_fifo / XGMAC_FIFO_UNIT);
+ rem_fifo -= addn_fifo;
+ }
+
+ if (rem_fifo) {
+ unsigned int inc_fifo = rem_fifo / prio_queues;
+
+ /* Distribute remaining fifo across queues */
+ for (i = 0; i < prio_queues; i++)
+ fifo[i] += (inc_fifo / XGMAC_FIFO_UNIT);
+ }
}
static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
{
unsigned int fifo_size;
+ unsigned int fifo[XGBE_MAX_QUEUES];
unsigned int i;
- fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
- pdata->tx_q_count);
+ fifo_size = xgbe_get_tx_fifo_size(pdata);
+
+ xgbe_calculate_equal_fifo(fifo_size, pdata->tx_q_count, fifo);
for (i = 0; i < pdata->tx_q_count; i++)
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo[i]);
netif_info(pdata, drv, pdata->netdev,
"%d Tx hardware queues, %d byte fifo per queue\n",
- pdata->tx_q_count, ((fifo_size + 1) * 256));
+ pdata->tx_q_count, ((fifo[0] + 1) * XGMAC_FIFO_UNIT));
}
static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
{
unsigned int fifo_size;
+ unsigned int fifo[XGBE_MAX_QUEUES];
+ unsigned int prio_queues;
unsigned int i;
- fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
- pdata->rx_q_count);
+ /* Clear any DCB related fifo/queue information */
+ memset(pdata->pfcq, 0, sizeof(pdata->pfcq));
+ pdata->pfc_rfa = 0;
+
+ fifo_size = xgbe_get_rx_fifo_size(pdata);
+ prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+
+ /* Assign a minimum fifo to the non-VLAN priority queues */
+ fifo_size = xgbe_set_nonprio_fifos(fifo_size, pdata->rx_q_count, fifo);
+
+ if (pdata->pfc && pdata->ets)
+ xgbe_calculate_dcb_fifo(pdata, fifo_size, fifo);
+ else
+ xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo);
for (i = 0; i < pdata->rx_q_count; i++)
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo[i]);
- netif_info(pdata, drv, pdata->netdev,
- "%d Rx hardware queues, %d byte fifo per queue\n",
- pdata->rx_q_count, ((fifo_size + 1) * 256));
+ xgbe_calculate_flow_control_threshold(pdata, fifo);
+ xgbe_config_flow_control_threshold(pdata);
+
+ if (pdata->pfc && pdata->ets && pdata->pfc->pfc_en) {
+ netif_info(pdata, drv, pdata->netdev,
+ "%u Rx hardware queues\n", pdata->rx_q_count);
+ for (i = 0; i < pdata->rx_q_count; i++)
+ netif_info(pdata, drv, pdata->netdev,
+ "RxQ%u, %u byte fifo queue\n", i,
+ ((fifo[i] + 1) * XGMAC_FIFO_UNIT));
+ } else {
+ netif_info(pdata, drv, pdata->netdev,
+ "%u Rx hardware queues, %u byte fifo per queue\n",
+ pdata->rx_q_count,
+ ((fifo[0] + 1) * XGMAC_FIFO_UNIT));
+ }
}
static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
@@ -2090,8 +2549,7 @@ static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
}
/* Map the 8 VLAN priority values to available MTL Rx queues */
- prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
- pdata->rx_q_count);
+ prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;
@@ -2139,16 +2597,120 @@ static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
}
}
-static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
+static void xgbe_config_tc(struct xgbe_prv_data *pdata)
{
- unsigned int i;
+ unsigned int offset, queue, prio;
+ u8 i;
- for (i = 0; i < pdata->rx_q_count; i++) {
- /* Activate flow control when less than 4k left in fifo */
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA, 2);
+ netdev_reset_tc(pdata->netdev);
+ if (!pdata->num_tcs)
+ return;
+
+ netdev_set_num_tc(pdata->netdev, pdata->num_tcs);
+
+ for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) {
+ while ((queue < pdata->tx_q_count) &&
+ (pdata->q2tc_map[queue] == i))
+ queue++;
- /* De-activate flow control when more than 6k left in fifo */
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD, 4);
+ netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n",
+ i, offset, queue - 1);
+ netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset);
+ offset = queue;
+ }
+
+ if (!pdata->ets)
+ return;
+
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
+ netdev_set_prio_tc_map(pdata->netdev, prio,
+ pdata->ets->prio_tc[prio]);
+}
+
+static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+{
+ struct ieee_ets *ets = pdata->ets;
+ unsigned int total_weight, min_weight, weight;
+ unsigned int mask, reg, reg_val;
+ unsigned int i, prio;
+
+ if (!ets)
+ return;
+
+ /* Set Tx to deficit weighted round robin scheduling algorithm (when
+ * traffic class is using ETS algorithm)
+ */
+ XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR);
+
+ /* Set Traffic Class algorithms */
+ total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt;
+ min_weight = total_weight / 100;
+ if (!min_weight)
+ min_weight = 1;
+
+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
+ /* Map the priorities to the traffic class */
+ mask = 0;
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+ if (ets->prio_tc[prio] == i)
+ mask |= (1 << prio);
+ }
+ mask &= 0xff;
+
+ netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n",
+ i, mask);
+ reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG));
+ reg_val = XGMAC_IOREAD(pdata, reg);
+
+ reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3));
+ reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3));
+
+ XGMAC_IOWRITE(pdata, reg, reg_val);
+
+ /* Set the traffic class algorithm */
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ netif_dbg(pdata, drv, pdata->netdev,
+ "TC%u using SP\n", i);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+ MTL_TSA_SP);
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ weight = total_weight * ets->tc_tx_bw[i] / 100;
+ weight = clamp(weight, min_weight, total_weight);
+
+ netif_dbg(pdata, drv, pdata->netdev,
+ "TC%u using DWRR (weight %u)\n", i, weight);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+ MTL_TSA_ETS);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW,
+ weight);
+ break;
+ }
+ }
+
+ xgbe_config_tc(pdata);
+}
+
+static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
+{
+ if (!test_bit(XGBE_DOWN, &pdata->dev_state)) {
+ /* Just stop the Tx queues while Rx fifo is changed */
+ netif_tx_stop_all_queues(pdata->netdev);
+
+ /* Suspend Rx so that fifo's can be adjusted */
+ pdata->hw_if.disable_rx(pdata);
+ }
+
+ xgbe_config_rx_fifo_size(pdata);
+ xgbe_config_flow_control(pdata);
+
+ if (!test_bit(XGBE_DOWN, &pdata->dev_state)) {
+ /* Resume Rx */
+ pdata->hw_if.enable_rx(pdata);
+
+ /* Resume Tx queues */
+ netif_tx_start_all_queues(pdata->netdev);
}
}
@@ -2175,19 +2737,7 @@ static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata)
static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata)
{
- switch (pdata->phy_speed) {
- case SPEED_10000:
- xgbe_set_xgmii_speed(pdata);
- break;
-
- case SPEED_2500:
- xgbe_set_gmii_2500_speed(pdata);
- break;
-
- case SPEED_1000:
- xgbe_set_gmii_speed(pdata);
- break;
- }
+ xgbe_set_speed(pdata, pdata->phy_speed);
}
static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
@@ -2223,17 +2773,33 @@ static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo)
bool read_hi;
u64 val;
- switch (reg_lo) {
- /* These registers are always 64 bit */
- case MMC_TXOCTETCOUNT_GB_LO:
- case MMC_TXOCTETCOUNT_G_LO:
- case MMC_RXOCTETCOUNT_GB_LO:
- case MMC_RXOCTETCOUNT_G_LO:
- read_hi = true;
- break;
+ if (pdata->vdata->mmc_64bit) {
+ switch (reg_lo) {
+ /* These registers are always 32 bit */
+ case MMC_RXRUNTERROR:
+ case MMC_RXJABBERERROR:
+ case MMC_RXUNDERSIZE_G:
+ case MMC_RXOVERSIZE_G:
+ case MMC_RXWATCHDOGERROR:
+ read_hi = false;
+ break;
- default:
- read_hi = false;
+ default:
+ read_hi = true;
+ }
+ } else {
+ switch (reg_lo) {
+ /* These registers are always 64 bit */
+ case MMC_TXOCTETCOUNT_GB_LO:
+ case MMC_TXOCTETCOUNT_G_LO:
+ case MMC_RXOCTETCOUNT_GB_LO:
+ case MMC_RXOCTETCOUNT_G_LO:
+ read_hi = true;
+ break;
+
+ default:
+ read_hi = false;
+ }
}
val = XGMAC_IOREAD(pdata, reg_lo);
@@ -2563,20 +3129,48 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
}
+static void xgbe_txq_prepare_tx_stop(struct xgbe_prv_data *pdata,
+ unsigned int queue)
+{
+ unsigned int tx_status;
+ unsigned long tx_timeout;
+
+ /* The Tx engine cannot be stopped if it is actively processing
+ * packets. Wait for the Tx queue to empty the Tx fifo. Don't
+ * wait forever though...
+ */
+ tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
+ while (time_before(jiffies, tx_timeout)) {
+ tx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR);
+ if ((XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) &&
+ (XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0))
+ break;
+
+ usleep_range(500, 1000);
+ }
+
+ if (!time_before(jiffies, tx_timeout))
+ netdev_info(pdata->netdev,
+ "timed out waiting for Tx queue %u to empty\n",
+ queue);
+}
+
static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
- struct xgbe_channel *channel)
+ unsigned int queue)
{
unsigned int tx_dsr, tx_pos, tx_qidx;
unsigned int tx_status;
unsigned long tx_timeout;
+ if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20)
+ return xgbe_txq_prepare_tx_stop(pdata, queue);
+
/* Calculate the status register to read and the position within */
- if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
+ if (queue < DMA_DSRX_FIRST_QUEUE) {
tx_dsr = DMA_DSR0;
- tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) +
- DMA_DSR0_TPS_START;
+ tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START;
} else {
- tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
+ tx_qidx = queue - DMA_DSRX_FIRST_QUEUE;
tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
@@ -2601,7 +3195,7 @@ static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
if (!time_before(jiffies, tx_timeout))
netdev_info(pdata->netdev,
"timed out waiting for Tx DMA channel %u to stop\n",
- channel->queue_index);
+ queue);
}
static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
@@ -2633,13 +3227,8 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
unsigned int i;
/* Prepare for Tx DMA channel stop */
- channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (!channel->tx_ring)
- break;
-
- xgbe_prepare_tx_stop(pdata, channel);
- }
+ for (i = 0; i < pdata->tx_q_count; i++)
+ xgbe_prepare_tx_stop(pdata, i);
/* Disable MAC Tx */
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -2763,13 +3352,8 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata)
unsigned int i;
/* Prepare for Tx DMA channel stop */
- channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (!channel->tx_ring)
- break;
-
- xgbe_prepare_tx_stop(pdata, channel);
- }
+ for (i = 0; i < pdata->tx_q_count; i++)
+ xgbe_prepare_tx_stop(pdata, i);
/* Disable MAC Tx */
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -2856,12 +3440,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
xgbe_config_rx_threshold(pdata, pdata->rx_threshold);
xgbe_config_tx_fifo_size(pdata);
xgbe_config_rx_fifo_size(pdata);
- xgbe_config_flow_control_threshold(pdata);
/*TODO: Error Packet and undersized good Packet forwarding enable
(FEP and FUP)
*/
xgbe_config_dcb_tc(pdata);
- xgbe_config_dcb_pfc(pdata);
xgbe_enable_mtl_interrupts(pdata);
/*
@@ -2877,6 +3459,11 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
xgbe_config_mmc(pdata);
xgbe_enable_mac_interrupts(pdata);
+ /*
+ * Initialize ECC related features
+ */
+ xgbe_enable_ecc_interrupts(pdata);
+
DBGPR("<--xgbe_init\n");
return 0;
@@ -2903,9 +3490,14 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->read_mmd_regs = xgbe_read_mmd_regs;
hw_if->write_mmd_regs = xgbe_write_mmd_regs;
- hw_if->set_gmii_speed = xgbe_set_gmii_speed;
- hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed;
- hw_if->set_xgmii_speed = xgbe_set_xgmii_speed;
+ hw_if->set_speed = xgbe_set_speed;
+
+ hw_if->set_ext_mii_mode = xgbe_set_ext_mii_mode;
+ hw_if->read_ext_mii_regs = xgbe_read_ext_mii_regs;
+ hw_if->write_ext_mii_regs = xgbe_write_ext_mii_regs;
+
+ hw_if->set_gpio = xgbe_set_gpio;
+ hw_if->clr_gpio = xgbe_clr_gpio;
hw_if->enable_tx = xgbe_enable_tx;
hw_if->disable_tx = xgbe_disable_tx;
@@ -2984,5 +3576,9 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->set_rss_hash_key = xgbe_set_rss_hash_key;
hw_if->set_rss_lookup_table = xgbe_set_rss_lookup_table;
+ /* For ECC */
+ hw_if->disable_ecc_ded = xgbe_disable_ecc_ded;
+ hw_if->disable_ecc_sec = xgbe_disable_ecc_sec;
+
DBGPR("<--xgbe_init_function_ptrs\n");
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 7f9216db026f..155190db682d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -114,7 +114,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/platform_device.h>
+#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/tcp.h>
#include <linux/if_vlan.h>
@@ -127,8 +127,35 @@
#include "xgbe.h"
#include "xgbe-common.h"
+static unsigned int ecc_sec_info_threshold = 10;
+static unsigned int ecc_sec_warn_threshold = 10000;
+static unsigned int ecc_sec_period = 600;
+static unsigned int ecc_ded_threshold = 2;
+static unsigned int ecc_ded_period = 600;
+
+#ifdef CONFIG_AMD_XGBE_HAVE_ECC
+/* Only expose the ECC parameters if supported */
+module_param(ecc_sec_info_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_info_threshold,
+ " ECC corrected error informational threshold setting");
+
+module_param(ecc_sec_warn_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_warn_threshold,
+ " ECC corrected error warning threshold setting");
+
+module_param(ecc_sec_period, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_period, " ECC corrected error period (in seconds)");
+
+module_param(ecc_ded_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_ded_threshold, " ECC detected error threshold setting");
+
+module_param(ecc_ded_period, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_ded_period, " ECC detected error period (in seconds)");
+#endif
+
static int xgbe_one_poll(struct napi_struct *, int);
static int xgbe_all_poll(struct napi_struct *, int);
+static void xgbe_stop(struct xgbe_prv_data *);
static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
{
@@ -160,18 +187,8 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE +
(DMA_CH_INC * i);
- if (pdata->per_channel_irq) {
- /* Get the DMA interrupt (offset 1) */
- ret = platform_get_irq(pdata->pdev, i + 1);
- if (ret < 0) {
- netdev_err(pdata->netdev,
- "platform_get_irq %u failed\n",
- i + 1);
- goto err_irq;
- }
-
- channel->dma_irq = ret;
- }
+ if (pdata->per_channel_irq)
+ channel->dma_irq = pdata->channel_irq[i];
if (i < pdata->tx_ring_count) {
spin_lock_init(&tx_ring->lock);
@@ -194,9 +211,6 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
return 0;
-err_irq:
- kfree(rx_ring);
-
err_rx_ring:
kfree(tx_ring);
@@ -257,11 +271,6 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
{
unsigned int rx_buf_size;
- if (mtu > XGMAC_JUMBO_PACKET_MTU) {
- netdev_alert(netdev, "MTU exceeds maximum supported value\n");
- return -EINVAL;
- }
-
rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE);
@@ -271,48 +280,161 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
return rx_buf_size;
}
-static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
+static void xgbe_enable_rx_tx_int(struct xgbe_prv_data *pdata,
+ struct xgbe_channel *channel)
{
struct xgbe_hw_if *hw_if = &pdata->hw_if;
- struct xgbe_channel *channel;
enum xgbe_int int_id;
+
+ if (channel->tx_ring && channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+ else if (channel->tx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI;
+ else if (channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_RI;
+ else
+ return;
+
+ hw_if->enable_int(channel, int_id);
+}
+
+static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_channel *channel;
unsigned int i;
channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (channel->tx_ring && channel->rx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
- else if (channel->tx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_TI;
- else if (channel->rx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_RI;
- else
- continue;
+ for (i = 0; i < pdata->channel_count; i++, channel++)
+ xgbe_enable_rx_tx_int(pdata, channel);
+}
- hw_if->enable_int(channel, int_id);
- }
+static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata,
+ struct xgbe_channel *channel)
+{
+ struct xgbe_hw_if *hw_if = &pdata->hw_if;
+ enum xgbe_int int_id;
+
+ if (channel->tx_ring && channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+ else if (channel->tx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI;
+ else if (channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_RI;
+ else
+ return;
+
+ hw_if->disable_int(channel, int_id);
}
static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata)
{
- struct xgbe_hw_if *hw_if = &pdata->hw_if;
struct xgbe_channel *channel;
- enum xgbe_int int_id;
unsigned int i;
channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (channel->tx_ring && channel->rx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
- else if (channel->tx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_TI;
- else if (channel->rx_ring)
- int_id = XGMAC_INT_DMA_CH_SR_RI;
- else
- continue;
+ for (i = 0; i < pdata->channel_count; i++, channel++)
+ xgbe_disable_rx_tx_int(pdata, channel);
+}
+
+static bool xgbe_ecc_sec(struct xgbe_prv_data *pdata, unsigned long *period,
+ unsigned int *count, const char *area)
+{
+ if (time_before(jiffies, *period)) {
+ (*count)++;
+ } else {
+ *period = jiffies + (ecc_sec_period * HZ);
+ *count = 1;
+ }
- hw_if->disable_int(channel, int_id);
+ if (*count > ecc_sec_info_threshold)
+ dev_warn_once(pdata->dev,
+ "%s ECC corrected errors exceed informational threshold\n",
+ area);
+
+ if (*count > ecc_sec_warn_threshold) {
+ dev_warn_once(pdata->dev,
+ "%s ECC corrected errors exceed warning threshold\n",
+ area);
+ return true;
}
+
+ return false;
+}
+
+static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period,
+ unsigned int *count, const char *area)
+{
+ if (time_before(jiffies, *period)) {
+ (*count)++;
+ } else {
+ *period = jiffies + (ecc_ded_period * HZ);
+ *count = 1;
+ }
+
+ if (*count > ecc_ded_threshold) {
+ netdev_alert(pdata->netdev,
+ "%s ECC detected errors exceed threshold\n",
+ area);
+ return true;
+ }
+
+ return false;
+}
+
+static irqreturn_t xgbe_ecc_isr(int irq, void *data)
+{
+ struct xgbe_prv_data *pdata = data;
+ unsigned int ecc_isr;
+ bool stop = false;
+
+ /* Mask status with only the interrupts we care about */
+ ecc_isr = XP_IOREAD(pdata, XP_ECC_ISR);
+ ecc_isr &= XP_IOREAD(pdata, XP_ECC_IER);
+ netif_dbg(pdata, intr, pdata->netdev, "ECC_ISR=%#010x\n", ecc_isr);
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, TX_DED)) {
+ stop |= xgbe_ecc_ded(pdata, &pdata->tx_ded_period,
+ &pdata->tx_ded_count, "TX fifo");
+ }
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, RX_DED)) {
+ stop |= xgbe_ecc_ded(pdata, &pdata->rx_ded_period,
+ &pdata->rx_ded_count, "RX fifo");
+ }
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, DESC_DED)) {
+ stop |= xgbe_ecc_ded(pdata, &pdata->desc_ded_period,
+ &pdata->desc_ded_count,
+ "descriptor cache");
+ }
+
+ if (stop) {
+ pdata->hw_if.disable_ecc_ded(pdata);
+ schedule_work(&pdata->stopdev_work);
+ goto out;
+ }
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, TX_SEC)) {
+ if (xgbe_ecc_sec(pdata, &pdata->tx_sec_period,
+ &pdata->tx_sec_count, "TX fifo"))
+ pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_TX);
+ }
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, RX_SEC))
+ if (xgbe_ecc_sec(pdata, &pdata->rx_sec_period,
+ &pdata->rx_sec_count, "RX fifo"))
+ pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_RX);
+
+ if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, DESC_SEC))
+ if (xgbe_ecc_sec(pdata, &pdata->desc_sec_period,
+ &pdata->desc_sec_count, "descriptor cache"))
+ pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_DESC);
+
+out:
+ /* Clear all ECC interrupts */
+ XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
+
+ return IRQ_HANDLED;
}
static irqreturn_t xgbe_isr(int irq, void *data)
@@ -321,7 +443,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
struct xgbe_hw_if *hw_if = &pdata->hw_if;
struct xgbe_channel *channel;
unsigned int dma_isr, dma_ch_isr;
- unsigned int mac_isr, mac_tssr;
+ unsigned int mac_isr, mac_tssr, mac_mdioisr;
unsigned int i;
/* The DMA interrupt status register also reports MAC and MTL
@@ -358,6 +480,13 @@ static irqreturn_t xgbe_isr(int irq, void *data)
/* Turn on polling */
__napi_schedule_irqoff(&pdata->napi);
}
+ } else {
+ /* Don't clear Rx/Tx status if doing per channel DMA
+ * interrupts, these will be cleared by the ISR for
+ * per channel DMA interrupts.
+ */
+ XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, TI, 0);
+ XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, RI, 0);
}
if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU))
@@ -367,13 +496,16 @@ static irqreturn_t xgbe_isr(int irq, void *data)
if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE))
schedule_work(&pdata->restart_work);
- /* Clear all interrupt signals */
+ /* Clear interrupt signals */
XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr);
}
if (XGMAC_GET_BITS(dma_isr, DMA_ISR, MACIS)) {
mac_isr = XGMAC_IOREAD(pdata, MAC_ISR);
+ netif_dbg(pdata, intr, pdata->netdev, "MAC_ISR=%#010x\n",
+ mac_isr);
+
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCTXIS))
hw_if->tx_mmc_int(pdata);
@@ -383,6 +515,9 @@ static irqreturn_t xgbe_isr(int irq, void *data)
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) {
mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR);
+ netif_dbg(pdata, intr, pdata->netdev,
+ "MAC_TSSR=%#010x\n", mac_tssr);
+
if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
/* Read Tx Timestamp to clear interrupt */
pdata->tx_tstamp =
@@ -391,8 +526,31 @@ static irqreturn_t xgbe_isr(int irq, void *data)
&pdata->tx_tstamp_work);
}
}
+
+ if (XGMAC_GET_BITS(mac_isr, MAC_ISR, SMI)) {
+ mac_mdioisr = XGMAC_IOREAD(pdata, MAC_MDIOISR);
+
+ netif_dbg(pdata, intr, pdata->netdev,
+ "MAC_MDIOISR=%#010x\n", mac_mdioisr);
+
+ if (XGMAC_GET_BITS(mac_mdioisr, MAC_MDIOISR,
+ SNGLCOMPINT))
+ complete(&pdata->mdio_complete);
+ }
}
+ /* If there is not a separate AN irq, handle it here */
+ if (pdata->dev_irq == pdata->an_irq)
+ pdata->phy_if.an_isr(irq, pdata);
+
+ /* If there is not a separate ECC irq, handle it here */
+ if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq))
+ xgbe_ecc_isr(irq, pdata);
+
+ /* If there is not a separate I2C irq, handle it here */
+ if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
+ pdata->i2c_if.i2c_isr(irq, pdata);
+
isr_done:
return IRQ_HANDLED;
}
@@ -400,18 +558,29 @@ isr_done:
static irqreturn_t xgbe_dma_isr(int irq, void *data)
{
struct xgbe_channel *channel = data;
+ struct xgbe_prv_data *pdata = channel->pdata;
+ unsigned int dma_status;
/* Per channel DMA interrupts are enabled, so we use the per
* channel napi structure and not the private data napi structure
*/
if (napi_schedule_prep(&channel->napi)) {
/* Disable Tx and Rx interrupts */
- disable_irq_nosync(channel->dma_irq);
+ if (pdata->channel_irq_mode)
+ xgbe_disable_rx_tx_int(pdata, channel);
+ else
+ disable_irq_nosync(channel->dma_irq);
/* Turn on polling */
__napi_schedule_irqoff(&channel->napi);
}
+ /* Clear Tx/Rx signals */
+ dma_status = 0;
+ XGMAC_SET_BITS(dma_status, DMA_CH_SR, TI, 1);
+ XGMAC_SET_BITS(dma_status, DMA_CH_SR, RI, 1);
+ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_status);
+
return IRQ_HANDLED;
}
@@ -428,7 +597,10 @@ static void xgbe_tx_timer(unsigned long data)
if (napi_schedule_prep(napi)) {
/* Disable Tx and Rx interrupts */
if (pdata->per_channel_irq)
- disable_irq_nosync(channel->dma_irq);
+ if (pdata->channel_irq_mode)
+ xgbe_disable_rx_tx_int(pdata, channel);
+ else
+ disable_irq_nosync(channel->dma_irq);
else
xgbe_disable_rx_tx_ints(pdata);
@@ -595,6 +767,10 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
hw_feat->tx_ch_cnt++;
hw_feat->tc_cnt++;
+ /* Translate the fifo sizes into actual numbers */
+ hw_feat->rx_fifo_size = 1 << (hw_feat->rx_fifo_size + 7);
+ hw_feat->tx_fifo_size = 1 << (hw_feat->tx_fifo_size + 7);
+
DBGPR("<--xgbe_get_all_hw_features\n");
}
@@ -657,6 +833,16 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
return ret;
}
+ if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) {
+ ret = devm_request_irq(pdata->dev, pdata->ecc_irq, xgbe_ecc_isr,
+ 0, pdata->ecc_name, pdata);
+ if (ret) {
+ netdev_alert(netdev, "error requesting ecc irq %d\n",
+ pdata->ecc_irq);
+ goto err_dev_irq;
+ }
+ }
+
if (!pdata->per_channel_irq)
return 0;
@@ -673,17 +859,21 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
if (ret) {
netdev_alert(netdev, "error requesting irq %d\n",
channel->dma_irq);
- goto err_irq;
+ goto err_dma_irq;
}
}
return 0;
-err_irq:
+err_dma_irq:
/* Using an unsigned int, 'i' will go to UINT_MAX and exit */
for (i--, channel--; i < pdata->channel_count; i--, channel--)
devm_free_irq(pdata->dev, channel->dma_irq, channel);
+ if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq))
+ devm_free_irq(pdata->dev, pdata->ecc_irq, pdata);
+
+err_dev_irq:
devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
return ret;
@@ -696,6 +886,9 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata)
devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
+ if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq))
+ devm_free_irq(pdata->dev, pdata->ecc_irq, pdata);
+
if (!pdata->per_channel_irq)
return;
@@ -783,7 +976,7 @@ static void xgbe_free_rx_data(struct xgbe_prv_data *pdata)
DBGPR("<--xgbe_free_rx_data\n");
}
-static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
{
pdata->phy_link = -1;
pdata->phy_speed = SPEED_UNKNOWN;
@@ -879,16 +1072,16 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
hw_if->init(pdata);
- ret = phy_if->phy_start(pdata);
- if (ret)
- goto err_phy;
-
xgbe_napi_enable(pdata, 1);
ret = xgbe_request_irqs(pdata);
if (ret)
goto err_napi;
+ ret = phy_if->phy_start(pdata);
+ if (ret)
+ goto err_irqs;
+
hw_if->enable_tx(pdata);
hw_if->enable_rx(pdata);
@@ -897,16 +1090,18 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
xgbe_start_timers(pdata);
queue_work(pdata->dev_workqueue, &pdata->service_work);
+ clear_bit(XGBE_STOPPED, &pdata->dev_state);
+
DBGPR("<--xgbe_start\n");
return 0;
+err_irqs:
+ xgbe_free_irqs(pdata);
+
err_napi:
xgbe_napi_disable(pdata, 1);
- phy_if->phy_stop(pdata);
-
-err_phy:
hw_if->exit(pdata);
return ret;
@@ -923,6 +1118,9 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
DBGPR("-->xgbe_stop\n");
+ if (test_bit(XGBE_STOPPED, &pdata->dev_state))
+ return;
+
netif_tx_stop_all_queues(netdev);
xgbe_stop_timers(pdata);
@@ -948,9 +1146,29 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
netdev_tx_reset_queue(txq);
}
+ set_bit(XGBE_STOPPED, &pdata->dev_state);
+
DBGPR("<--xgbe_stop\n");
}
+static void xgbe_stopdev(struct work_struct *work)
+{
+ struct xgbe_prv_data *pdata = container_of(work,
+ struct xgbe_prv_data,
+ stopdev_work);
+
+ rtnl_lock();
+
+ xgbe_stop(pdata);
+
+ xgbe_free_tx_data(pdata);
+ xgbe_free_rx_data(pdata);
+
+ rtnl_unlock();
+
+ netdev_alert(pdata->netdev, "device stopped\n");
+}
+
static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
{
DBGPR("-->xgbe_restart_dev\n");
@@ -1297,8 +1515,8 @@ static int xgbe_open(struct net_device *netdev)
DBGPR("-->xgbe_open\n");
- /* Initialize the phy */
- ret = xgbe_phy_init(pdata);
+ /* Reset the phy settings */
+ ret = xgbe_phy_reset(pdata);
if (ret)
return ret;
@@ -1333,6 +1551,7 @@ static int xgbe_open(struct net_device *netdev)
INIT_WORK(&pdata->service_work, xgbe_service);
INIT_WORK(&pdata->restart_work, xgbe_restart);
+ INIT_WORK(&pdata->stopdev_work, xgbe_stopdev);
INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
xgbe_init_timers(pdata);
@@ -2041,6 +2260,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget)
{
struct xgbe_channel *channel = container_of(napi, struct xgbe_channel,
napi);
+ struct xgbe_prv_data *pdata = channel->pdata;
int processed = 0;
DBGPR("-->xgbe_one_poll: budget=%d\n", budget);
@@ -2057,7 +2277,10 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget)
napi_complete_done(napi, processed);
/* Enable Tx and Rx interrupts */
- enable_irq(channel->dma_irq);
+ if (pdata->channel_irq_mode)
+ xgbe_enable_rx_tx_int(pdata, channel);
+ else
+ enable_irq(channel->dma_irq);
}
DBGPR("<--xgbe_one_poll: received = %d\n", processed);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 4007b429c80c..920566a3a599 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -272,97 +272,86 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
return ret;
}
-static int xgbe_get_settings(struct net_device *netdev,
- struct ethtool_cmd *cmd)
+static int xgbe_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
- cmd->phy_address = pdata->phy.address;
+ cmd->base.phy_address = pdata->phy.address;
- cmd->supported = pdata->phy.supported;
- cmd->advertising = pdata->phy.advertising;
- cmd->lp_advertising = pdata->phy.lp_advertising;
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ pdata->phy.supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ pdata->phy.advertising);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
+ pdata->phy.lp_advertising);
- cmd->autoneg = pdata->phy.autoneg;
- ethtool_cmd_speed_set(cmd, pdata->phy.speed);
- cmd->duplex = pdata->phy.duplex;
+ cmd->base.autoneg = pdata->phy.autoneg;
+ cmd->base.speed = pdata->phy.speed;
+ cmd->base.duplex = pdata->phy.duplex;
- cmd->port = PORT_NONE;
- cmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_NONE;
return 0;
}
-static int xgbe_set_settings(struct net_device *netdev,
- struct ethtool_cmd *cmd)
+static int xgbe_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ u32 advertising;
u32 speed;
int ret;
- speed = ethtool_cmd_speed(cmd);
+ speed = cmd->base.speed;
- if (cmd->phy_address != pdata->phy.address) {
+ if (cmd->base.phy_address != pdata->phy.address) {
netdev_err(netdev, "invalid phy address %hhu\n",
- cmd->phy_address);
+ cmd->base.phy_address);
return -EINVAL;
}
- if ((cmd->autoneg != AUTONEG_ENABLE) &&
- (cmd->autoneg != AUTONEG_DISABLE)) {
+ if ((cmd->base.autoneg != AUTONEG_ENABLE) &&
+ (cmd->base.autoneg != AUTONEG_DISABLE)) {
netdev_err(netdev, "unsupported autoneg %hhu\n",
- cmd->autoneg);
+ cmd->base.autoneg);
return -EINVAL;
}
- if (cmd->autoneg == AUTONEG_DISABLE) {
- switch (speed) {
- case SPEED_10000:
- break;
- case SPEED_2500:
- if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) {
- netdev_err(netdev, "unsupported speed %u\n",
- speed);
- return -EINVAL;
- }
- break;
- case SPEED_1000:
- if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) {
- netdev_err(netdev, "unsupported speed %u\n",
- speed);
- return -EINVAL;
- }
- break;
- default:
+ if (cmd->base.autoneg == AUTONEG_DISABLE) {
+ if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
netdev_err(netdev, "unsupported speed %u\n", speed);
return -EINVAL;
}
- if (cmd->duplex != DUPLEX_FULL) {
+ if (cmd->base.duplex != DUPLEX_FULL) {
netdev_err(netdev, "unsupported duplex %hhu\n",
- cmd->duplex);
+ cmd->base.duplex);
return -EINVAL;
}
}
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
+
netif_dbg(pdata, link, netdev,
"requested advertisement %#x, phy supported %#x\n",
- cmd->advertising, pdata->phy.supported);
+ advertising, pdata->phy.supported);
- cmd->advertising &= pdata->phy.supported;
- if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) {
+ advertising &= pdata->phy.supported;
+ if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) {
netdev_err(netdev,
"unsupported requested advertisement\n");
return -EINVAL;
}
ret = 0;
- pdata->phy.autoneg = cmd->autoneg;
+ pdata->phy.autoneg = cmd->base.autoneg;
pdata->phy.speed = speed;
- pdata->phy.duplex = cmd->duplex;
- pdata->phy.advertising = cmd->advertising;
+ pdata->phy.duplex = cmd->base.duplex;
+ pdata->phy.advertising = advertising;
- if (cmd->autoneg == AUTONEG_ENABLE)
+ if (cmd->base.autoneg == AUTONEG_ENABLE)
pdata->phy.advertising |= ADVERTISED_Autoneg;
else
pdata->phy.advertising &= ~ADVERTISED_Autoneg;
@@ -602,8 +591,6 @@ static int xgbe_get_ts_info(struct net_device *netdev,
}
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,
@@ -621,6 +608,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
.get_rxfh = xgbe_get_rxfh,
.set_rxfh = xgbe_set_rxfh,
.get_ts_info = xgbe_get_ts_info,
+ .get_link_ksettings = xgbe_get_link_ksettings,
+ .set_link_ksettings = xgbe_set_link_ksettings,
};
const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
new file mode 100644
index 000000000000..0c7088a426e9
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
@@ -0,0 +1,492 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * 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 of Advanced Micro Devices, Inc. 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 <COPYRIGHT HOLDER> 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.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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/module.h>
+#include <linux/kmod.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_ABORT_COUNT 500
+#define XGBE_DISABLE_COUNT 1000
+
+#define XGBE_STD_SPEED 1
+
+#define XGBE_INTR_RX_FULL BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX)
+#define XGBE_INTR_TX_EMPTY BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX)
+#define XGBE_INTR_TX_ABRT BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX)
+#define XGBE_INTR_STOP_DET BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX)
+#define XGBE_DEFAULT_INT_MASK (XGBE_INTR_RX_FULL | \
+ XGBE_INTR_TX_EMPTY | \
+ XGBE_INTR_TX_ABRT | \
+ XGBE_INTR_STOP_DET)
+
+#define XGBE_I2C_READ BIT(8)
+#define XGBE_I2C_STOP BIT(9)
+
+static int xgbe_i2c_abort(struct xgbe_prv_data *pdata)
+{
+ unsigned int wait = XGBE_ABORT_COUNT;
+
+ /* Must be enabled to recognize the abort request */
+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1);
+
+ /* Issue the abort */
+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1);
+
+ while (wait--) {
+ if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT))
+ return 0;
+
+ usleep_range(500, 600);
+ }
+
+ return -EBUSY;
+}
+
+static int xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable)
+{
+ unsigned int wait = XGBE_DISABLE_COUNT;
+ unsigned int mode = enable ? 1 : 0;
+
+ while (wait--) {
+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode);
+ if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode)
+ return 0;
+
+ usleep_range(100, 110);
+ }
+
+ return -EBUSY;
+}
+
+static int xgbe_i2c_disable(struct xgbe_prv_data *pdata)
+{
+ unsigned int ret;
+
+ ret = xgbe_i2c_set_enable(pdata, false);
+ if (ret) {
+ /* Disable failed, try an abort */
+ ret = xgbe_i2c_abort(pdata);
+ if (ret)
+ return ret;
+
+ /* Abort succeeded, try to disable again */
+ ret = xgbe_i2c_set_enable(pdata, false);
+ }
+
+ return ret;
+}
+
+static int xgbe_i2c_enable(struct xgbe_prv_data *pdata)
+{
+ return xgbe_i2c_set_enable(pdata, true);
+}
+
+static void xgbe_i2c_clear_all_interrupts(struct xgbe_prv_data *pdata)
+{
+ XI2C_IOREAD(pdata, IC_CLR_INTR);
+}
+
+static void xgbe_i2c_disable_interrupts(struct xgbe_prv_data *pdata)
+{
+ XI2C_IOWRITE(pdata, IC_INTR_MASK, 0);
+}
+
+static void xgbe_i2c_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+ XI2C_IOWRITE(pdata, IC_INTR_MASK, XGBE_DEFAULT_INT_MASK);
+}
+
+static void xgbe_i2c_write(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+ unsigned int tx_slots;
+ unsigned int cmd;
+
+ /* Configured to never receive Rx overflows, so fill up Tx fifo */
+ tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR);
+ while (tx_slots && state->tx_len) {
+ if (state->op->cmd == XGBE_I2C_CMD_READ)
+ cmd = XGBE_I2C_READ;
+ else
+ cmd = *state->tx_buf++;
+
+ if (state->tx_len == 1)
+ XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1);
+
+ XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd);
+
+ tx_slots--;
+ state->tx_len--;
+ }
+
+ /* No more Tx operations, so ignore TX_EMPTY and return */
+ if (!state->tx_len)
+ XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0);
+}
+
+static void xgbe_i2c_read(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+ unsigned int rx_slots;
+
+ /* Anything to be read? */
+ if (state->op->cmd != XGBE_I2C_CMD_READ)
+ return;
+
+ rx_slots = XI2C_IOREAD(pdata, IC_RXFLR);
+ while (rx_slots && state->rx_len) {
+ *state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD);
+ state->rx_len--;
+ rx_slots--;
+ }
+}
+
+static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata,
+ unsigned int isr)
+{
+ struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+
+ if (isr & XGBE_INTR_TX_ABRT) {
+ state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE);
+ XI2C_IOREAD(pdata, IC_CLR_TX_ABRT);
+ }
+
+ if (isr & XGBE_INTR_STOP_DET)
+ XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
+}
+
+static irqreturn_t xgbe_i2c_isr(int irq, void *data)
+{
+ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+ struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+ unsigned int isr;
+
+ isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
+ netif_dbg(pdata, intr, pdata->netdev,
+ "I2C interrupt received: status=%#010x\n", isr);
+
+ xgbe_i2c_clear_isr_interrupts(pdata, isr);
+
+ if (isr & XGBE_INTR_TX_ABRT) {
+ netif_dbg(pdata, link, pdata->netdev,
+ "I2C TX_ABRT received (%#010x) for target %#04x\n",
+ state->tx_abort_source, state->op->target);
+
+ xgbe_i2c_disable_interrupts(pdata);
+
+ state->ret = -EIO;
+ goto out;
+ }
+
+ /* Check for data in the Rx fifo */
+ xgbe_i2c_read(pdata);
+
+ /* Fill up the Tx fifo next */
+ xgbe_i2c_write(pdata);
+
+out:
+ /* Complete on an error or STOP condition */
+ if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
+ complete(&pdata->i2c_complete);
+
+ return IRQ_HANDLED;
+}
+
+static void xgbe_i2c_set_mode(struct xgbe_prv_data *pdata)
+{
+ unsigned int reg;
+
+ reg = XI2C_IOREAD(pdata, IC_CON);
+ XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1);
+ XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1);
+ XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1);
+ XI2C_SET_BITS(reg, IC_CON, SPEED, XGBE_STD_SPEED);
+ XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1);
+ XI2C_IOWRITE(pdata, IC_CON, reg);
+}
+
+static void xgbe_i2c_get_features(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_i2c *i2c = &pdata->i2c;
+ unsigned int reg;
+
+ reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1);
+ i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+ MAX_SPEED_MODE);
+ i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+ RX_BUFFER_DEPTH);
+ i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+ TX_BUFFER_DEPTH);
+
+ if (netif_msg_probe(pdata))
+ dev_dbg(pdata->dev, "I2C features: %s=%u, %s=%u, %s=%u\n",
+ "MAX_SPEED_MODE", i2c->max_speed_mode,
+ "RX_BUFFER_DEPTH", i2c->rx_fifo_size,
+ "TX_BUFFER_DEPTH", i2c->tx_fifo_size);
+}
+
+static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr)
+{
+ XI2C_IOWRITE(pdata, IC_TAR, addr);
+}
+
+static irqreturn_t xgbe_i2c_combined_isr(int irq, struct xgbe_prv_data *pdata)
+{
+ if (!XI2C_IOREAD(pdata, IC_RAW_INTR_STAT))
+ return IRQ_HANDLED;
+
+ return xgbe_i2c_isr(irq, pdata);
+}
+
+static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op)
+{
+ struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+ int ret;
+
+ mutex_lock(&pdata->i2c_mutex);
+
+ reinit_completion(&pdata->i2c_complete);
+
+ ret = xgbe_i2c_disable(pdata);
+ if (ret) {
+ netdev_err(pdata->netdev, "failed to disable i2c master\n");
+ goto unlock;
+ }
+
+ xgbe_i2c_set_target(pdata, op->target);
+
+ memset(state, 0, sizeof(*state));
+ state->op = op;
+ state->tx_len = op->len;
+ state->tx_buf = op->buf;
+ state->rx_len = op->len;
+ state->rx_buf = op->buf;
+
+ xgbe_i2c_clear_all_interrupts(pdata);
+ ret = xgbe_i2c_enable(pdata);
+ if (ret) {
+ netdev_err(pdata->netdev, "failed to enable i2c master\n");
+ goto unlock;
+ }
+
+ /* Enabling the interrupts will cause the TX FIFO empty interrupt to
+ * fire and begin to process the command via the ISR.
+ */
+ xgbe_i2c_enable_interrupts(pdata);
+
+ if (!wait_for_completion_timeout(&pdata->i2c_complete, HZ)) {
+ netdev_err(pdata->netdev, "i2c operation timed out\n");
+ ret = -ETIMEDOUT;
+ goto disable;
+ }
+
+ ret = state->ret;
+ if (ret) {
+ if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK)
+ ret = -ENOTCONN;
+ else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST)
+ ret = -EAGAIN;
+ }
+
+disable:
+ xgbe_i2c_disable_interrupts(pdata);
+ xgbe_i2c_disable(pdata);
+
+unlock:
+ mutex_unlock(&pdata->i2c_mutex);
+
+ return ret;
+}
+
+static void xgbe_i2c_stop(struct xgbe_prv_data *pdata)
+{
+ if (!pdata->i2c.started)
+ return;
+
+ netif_dbg(pdata, link, pdata->netdev, "stopping I2C\n");
+
+ pdata->i2c.started = 0;
+
+ xgbe_i2c_disable_interrupts(pdata);
+ xgbe_i2c_disable(pdata);
+ xgbe_i2c_clear_all_interrupts(pdata);
+
+ if (pdata->dev_irq != pdata->i2c_irq)
+ devm_free_irq(pdata->dev, pdata->i2c_irq, pdata);
+}
+
+static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
+{
+ int ret;
+
+ if (pdata->i2c.started)
+ return 0;
+
+ netif_dbg(pdata, link, pdata->netdev, "starting I2C\n");
+
+ /* If we have a separate I2C irq, enable it */
+ if (pdata->dev_irq != pdata->i2c_irq) {
+ ret = devm_request_irq(pdata->dev, pdata->i2c_irq,
+ xgbe_i2c_isr, 0, pdata->i2c_name,
+ pdata);
+ if (ret) {
+ netdev_err(pdata->netdev, "i2c irq request failed\n");
+ return ret;
+ }
+ }
+
+ pdata->i2c.started = 1;
+
+ return 0;
+}
+
+static int xgbe_i2c_init(struct xgbe_prv_data *pdata)
+{
+ int ret;
+
+ xgbe_i2c_disable_interrupts(pdata);
+
+ ret = xgbe_i2c_disable(pdata);
+ if (ret) {
+ dev_err(pdata->dev, "failed to disable i2c master\n");
+ return ret;
+ }
+
+ xgbe_i2c_get_features(pdata);
+
+ xgbe_i2c_set_mode(pdata);
+
+ xgbe_i2c_clear_all_interrupts(pdata);
+
+ return 0;
+}
+
+void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *i2c_if)
+{
+ i2c_if->i2c_init = xgbe_i2c_init;
+
+ i2c_if->i2c_start = xgbe_i2c_start;
+ i2c_if->i2c_stop = xgbe_i2c_stop;
+
+ i2c_if->i2c_xfer = xgbe_i2c_xfer;
+
+ i2c_if->i2c_isr = xgbe_i2c_combined_isr;
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 4f7635178200..17ac8f9a51a0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -116,19 +116,10 @@
#include <linux/module.h>
#include <linux/device.h>
-#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_net.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/property.h>
-#include <linux/acpi.h>
-#include <linux/mdio.h>
#include "xgbe.h"
#include "xgbe-common.h"
@@ -145,42 +136,6 @@ MODULE_PARM_DESC(debug, " Network interface message level setting");
static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
NETIF_MSG_IFUP);
-static const u32 xgbe_serdes_blwc[] = {
- XGBE_SPEED_1000_BLWC,
- XGBE_SPEED_2500_BLWC,
- XGBE_SPEED_10000_BLWC,
-};
-
-static const u32 xgbe_serdes_cdr_rate[] = {
- XGBE_SPEED_1000_CDR,
- XGBE_SPEED_2500_CDR,
- XGBE_SPEED_10000_CDR,
-};
-
-static const u32 xgbe_serdes_pq_skew[] = {
- XGBE_SPEED_1000_PQ,
- XGBE_SPEED_2500_PQ,
- XGBE_SPEED_10000_PQ,
-};
-
-static const u32 xgbe_serdes_tx_amp[] = {
- XGBE_SPEED_1000_TXAMP,
- XGBE_SPEED_2500_TXAMP,
- XGBE_SPEED_10000_TXAMP,
-};
-
-static const u32 xgbe_serdes_dfe_tap_cfg[] = {
- XGBE_SPEED_1000_DFE_TAP_CONFIG,
- XGBE_SPEED_2500_DFE_TAP_CONFIG,
- XGBE_SPEED_10000_DFE_TAP_CONFIG,
-};
-
-static const u32 xgbe_serdes_dfe_tap_ena[] = {
- XGBE_SPEED_1000_DFE_TAP_ENABLE,
- XGBE_SPEED_2500_DFE_TAP_ENABLE,
- XGBE_SPEED_10000_DFE_TAP_ENABLE,
-};
-
static void xgbe_default_config(struct xgbe_prv_data *pdata)
{
DBGPR("-->xgbe_default_config\n");
@@ -206,455 +161,124 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata)
{
xgbe_init_function_ptrs_dev(&pdata->hw_if);
xgbe_init_function_ptrs_phy(&pdata->phy_if);
+ xgbe_init_function_ptrs_i2c(&pdata->i2c_if);
xgbe_init_function_ptrs_desc(&pdata->desc_if);
-}
-
-#ifdef CONFIG_ACPI
-static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
-{
- struct device *dev = pdata->dev;
- u32 property;
- int ret;
-
- /* Obtain the system clock setting */
- ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property);
- if (ret) {
- dev_err(dev, "unable to obtain %s property\n",
- XGBE_ACPI_DMA_FREQ);
- return ret;
- }
- pdata->sysclk_rate = property;
-
- /* Obtain the PTP clock setting */
- ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property);
- if (ret) {
- dev_err(dev, "unable to obtain %s property\n",
- XGBE_ACPI_PTP_FREQ);
- return ret;
- }
- pdata->ptpclk_rate = property;
- return 0;
+ pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if);
}
-#else /* CONFIG_ACPI */
-static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
-{
- return -EINVAL;
-}
-#endif /* CONFIG_ACPI */
-#ifdef CONFIG_OF
-static int xgbe_of_support(struct xgbe_prv_data *pdata)
-{
- struct device *dev = pdata->dev;
-
- /* Obtain the system clock setting */
- pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
- if (IS_ERR(pdata->sysclk)) {
- dev_err(dev, "dma devm_clk_get failed\n");
- return PTR_ERR(pdata->sysclk);
- }
- pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
-
- /* Obtain the PTP clock setting */
- pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
- if (IS_ERR(pdata->ptpclk)) {
- dev_err(dev, "ptp devm_clk_get failed\n");
- return PTR_ERR(pdata->ptpclk);
- }
- pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
-
- return 0;
-}
-
-static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
- struct device *dev = pdata->dev;
- struct device_node *phy_node;
- struct platform_device *phy_pdev;
-
- phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
- if (phy_node) {
- /* Old style device tree:
- * The XGBE and PHY resources are separate
- */
- phy_pdev = of_find_device_by_node(phy_node);
- of_node_put(phy_node);
- } else {
- /* New style device tree:
- * The XGBE and PHY resources are grouped together with
- * the PHY resources listed last
- */
- get_device(dev);
- phy_pdev = pdata->pdev;
- }
-
- return phy_pdev;
-}
-#else /* CONFIG_OF */
-static int xgbe_of_support(struct xgbe_prv_data *pdata)
-{
- return -EINVAL;
-}
-
-static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
- return NULL;
-}
-#endif /* CONFIG_OF */
-
-static unsigned int xgbe_resource_count(struct platform_device *pdev,
- unsigned int type)
-{
- unsigned int count;
- int i;
-
- for (i = 0, count = 0; i < pdev->num_resources; i++) {
- struct resource *res = &pdev->resource[i];
-
- if (type == resource_type(res))
- count++;
- }
-
- return count;
-}
-
-static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
- struct platform_device *phy_pdev;
-
- if (pdata->use_acpi) {
- get_device(pdata->dev);
- phy_pdev = pdata->pdev;
- } else {
- phy_pdev = xgbe_of_get_phy_pdev(pdata);
- }
-
- return phy_pdev;
-}
-
-static int xgbe_probe(struct platform_device *pdev)
+struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
{
struct xgbe_prv_data *pdata;
struct net_device *netdev;
- struct device *dev = &pdev->dev, *phy_dev;
- struct platform_device *phy_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");
netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data),
XGBE_MAX_DMA_CHANNELS);
if (!netdev) {
- dev_err(dev, "alloc_etherdev failed\n");
- ret = -ENOMEM;
- goto err_alloc;
+ dev_err(dev, "alloc_etherdev_mq failed\n");
+ return ERR_PTR(-ENOMEM);
}
SET_NETDEV_DEV(netdev, dev);
pdata = netdev_priv(netdev);
pdata->netdev = netdev;
- pdata->pdev = pdev;
- pdata->adev = ACPI_COMPANION(dev);
pdata->dev = dev;
- platform_set_drvdata(pdev, netdev);
spin_lock_init(&pdata->lock);
spin_lock_init(&pdata->xpcs_lock);
mutex_init(&pdata->rss_mutex);
spin_lock_init(&pdata->tstamp_lock);
+ mutex_init(&pdata->i2c_mutex);
+ init_completion(&pdata->i2c_complete);
+ init_completion(&pdata->mdio_complete);
pdata->msg_enable = netif_msg_init(debug, default_msg_level);
set_bit(XGBE_DOWN, &pdata->dev_state);
+ set_bit(XGBE_STOPPED, &pdata->dev_state);
- /* Check if we should use ACPI or DT */
- pdata->use_acpi = dev->of_node ? 0 : 1;
-
- phy_pdev = xgbe_get_phy_pdev(pdata);
- if (!phy_pdev) {
- dev_err(dev, "unable to obtain phy device\n");
- ret = -EINVAL;
- goto err_phydev;
- }
- phy_dev = &phy_pdev->dev;
-
- if (pdev == phy_pdev) {
- /* New style device tree or ACPI:
- * The XGBE and PHY resources are grouped together with
- * the PHY resources listed last
- */
- phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
- phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
- } else {
- /* Old style device tree:
- * The XGBE and PHY resources are separate
- */
- phy_memnum = 0;
- phy_irqnum = 0;
- }
-
- /* Set and validate the number of descriptors for a ring */
- BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
- pdata->tx_desc_count = XGBE_TX_DESC_CNT;
- if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) {
- dev_err(dev, "tx descriptor count (%d) is not valid\n",
- pdata->tx_desc_count);
- ret = -EINVAL;
- goto err_io;
- }
- BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
- pdata->rx_desc_count = XGBE_RX_DESC_CNT;
- if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) {
- dev_err(dev, "rx descriptor count (%d) is not valid\n",
- pdata->rx_desc_count);
- ret = -EINVAL;
- goto err_io;
- }
-
- /* Obtain the mmio areas for the device */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pdata->xgmac_regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(pdata->xgmac_regs)) {
- dev_err(dev, "xgmac ioremap failed\n");
- ret = PTR_ERR(pdata->xgmac_regs);
- goto err_io;
- }
- if (netif_msg_probe(pdata))
- dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- pdata->xpcs_regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(pdata->xpcs_regs)) {
- dev_err(dev, "xpcs ioremap failed\n");
- ret = PTR_ERR(pdata->xpcs_regs);
- goto err_io;
- }
- if (netif_msg_probe(pdata))
- dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs);
-
- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
- pdata->rxtx_regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(pdata->rxtx_regs)) {
- dev_err(dev, "rxtx ioremap failed\n");
- ret = PTR_ERR(pdata->rxtx_regs);
- goto err_io;
- }
- if (netif_msg_probe(pdata))
- dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs);
-
- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
- pdata->sir0_regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(pdata->sir0_regs)) {
- dev_err(dev, "sir0 ioremap failed\n");
- ret = PTR_ERR(pdata->sir0_regs);
- goto err_io;
- }
- if (netif_msg_probe(pdata))
- dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs);
-
- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
- pdata->sir1_regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(pdata->sir1_regs)) {
- dev_err(dev, "sir1 ioremap failed\n");
- ret = PTR_ERR(pdata->sir1_regs);
- goto err_io;
- }
- if (netif_msg_probe(pdata))
- dev_dbg(dev, "sir1_regs = %p\n", pdata->sir1_regs);
-
- /* Retrieve the MAC address */
- ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
- pdata->mac_addr,
- sizeof(pdata->mac_addr));
- if (ret || !is_valid_ether_addr(pdata->mac_addr)) {
- dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY);
- if (!ret)
- ret = -EINVAL;
- goto err_io;
- }
-
- /* Retrieve the PHY mode - it must be "xgmii" */
- ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY,
- &phy_mode);
- if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) {
- dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY);
- if (!ret)
- ret = -EINVAL;
- goto err_io;
- }
- pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
-
- /* Check for per channel interrupt support */
- if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY))
- pdata->per_channel_irq = 1;
+ return pdata;
+}
- /* Retrieve the PHY speedset */
- ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY,
- &pdata->speed_set);
- if (ret) {
- dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
- goto err_io;
- }
+void xgbe_free_pdata(struct xgbe_prv_data *pdata)
+{
+ struct net_device *netdev = pdata->netdev;
- switch (pdata->speed_set) {
- case XGBE_SPEEDSET_1000_10000:
- case XGBE_SPEEDSET_2500_10000:
- break;
- default:
- dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
- ret = -EINVAL;
- goto err_io;
- }
+ free_netdev(netdev);
+}
- /* Retrieve the PHY configuration properties */
- if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_BLWC_PROPERTY,
- pdata->serdes_blwc,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_BLWC_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_blwc, xgbe_serdes_blwc,
- sizeof(pdata->serdes_blwc));
- }
+void xgbe_set_counts(struct xgbe_prv_data *pdata)
+{
+ /* Set all the function pointers */
+ xgbe_init_all_fptrs(pdata);
- if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_CDR_RATE_PROPERTY,
- pdata->serdes_cdr_rate,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_CDR_RATE_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate,
- sizeof(pdata->serdes_cdr_rate));
- }
+ /* Populate the hardware features */
+ xgbe_get_all_hw_features(pdata);
- if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_PQ_SKEW_PROPERTY,
- pdata->serdes_pq_skew,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_PQ_SKEW_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew,
- sizeof(pdata->serdes_pq_skew));
- }
+ /* Set default max values if not provided */
+ if (!pdata->tx_max_channel_count)
+ pdata->tx_max_channel_count = pdata->hw_feat.tx_ch_cnt;
+ if (!pdata->rx_max_channel_count)
+ pdata->rx_max_channel_count = pdata->hw_feat.rx_ch_cnt;
- if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_TX_AMP_PROPERTY,
- pdata->serdes_tx_amp,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_TX_AMP_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp,
- sizeof(pdata->serdes_tx_amp));
- }
+ if (!pdata->tx_max_q_count)
+ pdata->tx_max_q_count = pdata->hw_feat.tx_q_cnt;
+ if (!pdata->rx_max_q_count)
+ pdata->rx_max_q_count = pdata->hw_feat.rx_q_cnt;
- if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_DFE_CFG_PROPERTY,
- pdata->serdes_dfe_tap_cfg,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_DFE_CFG_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg,
- sizeof(pdata->serdes_dfe_tap_cfg));
- }
+ /* Calculate the number of Tx and Rx rings to be created
+ * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
+ * the number of Tx queues to the number of Tx channels
+ * enabled
+ * -Rx (DMA) Channels do not map 1-to-1 so use the actual
+ * number of Rx queues or maximum allowed
+ */
+ pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
+ pdata->hw_feat.tx_ch_cnt);
+ pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+ pdata->tx_max_channel_count);
+ pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+ pdata->tx_max_q_count);
- if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) {
- ret = device_property_read_u32_array(phy_dev,
- XGBE_DFE_ENA_PROPERTY,
- pdata->serdes_dfe_tap_ena,
- XGBE_SPEEDS);
- if (ret) {
- dev_err(dev, "invalid %s property\n",
- XGBE_DFE_ENA_PROPERTY);
- goto err_io;
- }
- } else {
- memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena,
- sizeof(pdata->serdes_dfe_tap_ena));
- }
+ pdata->tx_q_count = pdata->tx_ring_count;
- /* Obtain device settings unique to ACPI/OF */
- if (pdata->use_acpi)
- ret = xgbe_acpi_support(pdata);
- else
- ret = xgbe_of_support(pdata);
- if (ret)
- goto err_io;
+ pdata->rx_ring_count = min_t(unsigned int, num_online_cpus(),
+ pdata->hw_feat.rx_ch_cnt);
+ pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
+ pdata->rx_max_channel_count);
- /* Set the DMA coherency values */
- 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;
- pdata->awcache = XGBE_DMA_OS_AWCACHE;
- } else {
- pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
- pdata->arcache = XGBE_DMA_SYS_ARCACHE;
- pdata->awcache = XGBE_DMA_SYS_AWCACHE;
- }
+ pdata->rx_q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt,
+ pdata->rx_max_q_count);
- /* Get the device interrupt */
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "platform_get_irq 0 failed\n");
- goto err_io;
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(pdata->dev, "TX/RX DMA channel count = %u/%u\n",
+ pdata->tx_ring_count, pdata->rx_ring_count);
+ dev_dbg(pdata->dev, "TX/RX hardware queue count = %u/%u\n",
+ pdata->tx_q_count, pdata->rx_q_count);
}
- pdata->dev_irq = ret;
+}
- /* Get the auto-negotiation interrupt */
- ret = platform_get_irq(phy_pdev, phy_irqnum++);
- if (ret < 0) {
- dev_err(dev, "platform_get_irq phy 0 failed\n");
- goto err_io;
- }
- pdata->an_irq = ret;
+int xgbe_config_netdev(struct xgbe_prv_data *pdata)
+{
+ struct net_device *netdev = pdata->netdev;
+ struct device *dev = pdata->dev;
+ unsigned int i;
+ int ret;
netdev->irq = pdata->dev_irq;
netdev->base_addr = (unsigned long)pdata->xgmac_regs;
memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
- /* Set all the function pointers */
- xgbe_init_all_fptrs(pdata);
+ /* Initialize ECC timestamps */
+ pdata->tx_sec_period = jiffies;
+ pdata->tx_ded_period = jiffies;
+ pdata->rx_sec_period = jiffies;
+ pdata->rx_ded_period = jiffies;
+ pdata->desc_sec_period = jiffies;
+ pdata->desc_ded_period = jiffies;
/* Issue software reset to device */
pdata->hw_if.exit(pdata);
- /* Populate the hardware features */
- xgbe_get_all_hw_features(pdata);
-
/* Set default configuration data */
xgbe_default_config(pdata);
@@ -663,33 +287,46 @@ static int xgbe_probe(struct platform_device *pdev)
DMA_BIT_MASK(pdata->hw_feat.dma_width));
if (ret) {
dev_err(dev, "dma_set_mask_and_coherent failed\n");
- goto err_io;
+ return ret;
}
- /* Calculate the number of Tx and Rx rings to be created
- * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
- * the number of Tx queues to the number of Tx channels
- * enabled
- * -Rx (DMA) Channels do not map 1-to-1 so use the actual
- * number of Rx queues
- */
- pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
- pdata->hw_feat.tx_ch_cnt);
- pdata->tx_q_count = pdata->tx_ring_count;
+ /* Set default max values if not provided */
+ if (!pdata->tx_max_fifo_size)
+ pdata->tx_max_fifo_size = pdata->hw_feat.tx_fifo_size;
+ if (!pdata->rx_max_fifo_size)
+ pdata->rx_max_fifo_size = pdata->hw_feat.rx_fifo_size;
+
+ /* Set and validate the number of descriptors for a ring */
+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
+ pdata->tx_desc_count = XGBE_TX_DESC_CNT;
+
+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
+ pdata->rx_desc_count = XGBE_RX_DESC_CNT;
+
+ /* Adjust the number of queues based on interrupts assigned */
+ if (pdata->channel_irq_count) {
+ pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+ pdata->channel_irq_count);
+ pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
+ pdata->channel_irq_count);
+
+ if (netif_msg_probe(pdata))
+ dev_dbg(pdata->dev,
+ "adjusted TX/RX DMA channel count = %u/%u\n",
+ pdata->tx_ring_count, pdata->rx_ring_count);
+ }
+
+ /* Set the number of queues */
ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
if (ret) {
dev_err(dev, "error setting real tx queue count\n");
- goto err_io;
+ return ret;
}
- pdata->rx_ring_count = min_t(unsigned int,
- netif_get_num_default_rss_queues(),
- pdata->hw_feat.rx_ch_cnt);
- pdata->rx_q_count = pdata->hw_feat.rx_q_cnt;
ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
if (ret) {
dev_err(dev, "error setting real rx queue count\n");
- goto err_io;
+ return ret;
}
/* Initialize RSS hash key and lookup table */
@@ -704,7 +341,9 @@ static int xgbe_probe(struct platform_device *pdev)
XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
/* Call MDIO/PHY initialization routine */
- pdata->phy_if.phy_init(pdata);
+ ret = pdata->phy_if.phy_init(pdata);
+ if (ret)
+ return ret;
/* Set device operations */
netdev->netdev_ops = xgbe_get_netdev_ops();
@@ -738,6 +377,8 @@ static int xgbe_probe(struct platform_device *pdev)
pdata->netdev_features = netdev->features;
netdev->priv_flags |= IFF_UNICAST_FLT;
+ netdev->min_mtu = 0;
+ netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU;
/* Use default watchdog timeout */
netdev->watchdog_timeo = 0;
@@ -749,13 +390,21 @@ static int xgbe_probe(struct platform_device *pdev)
ret = register_netdev(netdev);
if (ret) {
dev_err(dev, "net device registration failed\n");
- goto err_io;
+ return ret;
}
/* Create the PHY/ANEG name based on netdev name */
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
netdev_name(netdev));
+ /* Create the ECC name based on netdev name */
+ snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
+ netdev_name(netdev));
+
+ /* Create the I2C name based on netdev name */
+ snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
+ netdev_name(netdev));
+
/* Create workqueues */
pdata->dev_workqueue =
create_singlethread_workqueue(netdev_name(netdev));
@@ -773,15 +422,15 @@ static int xgbe_probe(struct platform_device *pdev)
goto err_wq;
}
- xgbe_ptp_register(pdata);
+ if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+ xgbe_ptp_register(pdata);
xgbe_debugfs_init(pdata);
- platform_device_put(phy_pdev);
-
- netdev_notice(netdev, "net device enabled\n");
-
- DBGPR("<-- xgbe_probe\n");
+ netif_dbg(pdata, drv, pdata->netdev, "%u Tx software queues\n",
+ pdata->tx_ring_count);
+ netif_dbg(pdata, drv, pdata->netdev, "%u Rx software queues\n",
+ pdata->rx_ring_count);
return 0;
@@ -791,28 +440,19 @@ err_wq:
err_netdev:
unregister_netdev(netdev);
-err_io:
- platform_device_put(phy_pdev);
-
-err_phydev:
- free_netdev(netdev);
-
-err_alloc:
- dev_notice(dev, "net device not enabled\n");
-
return ret;
}
-static int xgbe_remove(struct platform_device *pdev)
+void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
{
- struct net_device *netdev = platform_get_drvdata(pdev);
- struct xgbe_prv_data *pdata = netdev_priv(netdev);
-
- DBGPR("-->xgbe_remove\n");
+ struct net_device *netdev = pdata->netdev;
xgbe_debugfs_exit(pdata);
- xgbe_ptp_unregister(pdata);
+ if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+ xgbe_ptp_unregister(pdata);
+
+ pdata->phy_if.phy_exit(pdata);
flush_workqueue(pdata->an_workqueue);
destroy_workqueue(pdata->an_workqueue);
@@ -821,94 +461,29 @@ static int xgbe_remove(struct platform_device *pdev)
destroy_workqueue(pdata->dev_workqueue);
unregister_netdev(netdev);
-
- free_netdev(netdev);
-
- DBGPR("<--xgbe_remove\n");
-
- return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int xgbe_suspend(struct device *dev)
+static int __init xgbe_mod_init(void)
{
- struct net_device *netdev = dev_get_drvdata(dev);
- struct xgbe_prv_data *pdata = netdev_priv(netdev);
- int ret = 0;
-
- DBGPR("-->xgbe_suspend\n");
-
- if (netif_running(netdev))
- ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+ int ret;
- pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+ ret = xgbe_platform_init();
+ if (ret)
+ return ret;
- DBGPR("<--xgbe_suspend\n");
+ ret = xgbe_pci_init();
+ if (ret)
+ return ret;
- return ret;
+ return 0;
}
-static int xgbe_resume(struct device *dev)
+static void __exit xgbe_mod_exit(void)
{
- struct net_device *netdev = dev_get_drvdata(dev);
- struct xgbe_prv_data *pdata = netdev_priv(netdev);
- int ret = 0;
-
- DBGPR("-->xgbe_resume\n");
-
- pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
-
- if (netif_running(netdev)) {
- ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
-
- /* Schedule a restart in case the link or phy state changed
- * while we were powered down.
- */
- schedule_work(&pdata->restart_work);
- }
-
- DBGPR("<--xgbe_resume\n");
+ xgbe_pci_exit();
- return ret;
+ xgbe_platform_exit();
}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id xgbe_acpi_match[] = {
- { "AMDI8001", 0 },
- {},
-};
-
-MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id xgbe_of_match[] = {
- { .compatible = "amd,xgbe-seattle-v1a", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, xgbe_of_match);
-#endif
-
-static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume);
-
-static struct platform_driver xgbe_driver = {
- .driver = {
- .name = "amd-xgbe",
-#ifdef CONFIG_ACPI
- .acpi_match_table = xgbe_acpi_match,
-#endif
-#ifdef CONFIG_OF
- .of_match_table = xgbe_of_match,
-#endif
- .pm = &xgbe_pm_ops,
- },
- .probe = xgbe_probe,
- .remove = xgbe_remove,
-};
-module_platform_driver(xgbe_driver);
+module_init(xgbe_mod_init);
+module_exit(xgbe_mod_exit);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 84c5d296d13e..4c5b90eea4af 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -125,303 +125,284 @@
#include "xgbe.h"
#include "xgbe-common.h"
-static void xgbe_an_enable_kr_training(struct xgbe_prv_data *pdata)
+static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
-
- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+ int reg;
- reg |= XGBE_KR_TRAINING_ENABLE;
- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+ reg &= ~XGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
}
-static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata)
+static void xgbe_an37_disable_interrupts(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
+ int reg;
- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+ reg &= ~XGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
- reg &= ~XGBE_KR_TRAINING_ENABLE;
- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+ reg &= ~XGBE_PCS_CL37_BP;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
}
-static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata)
+static void xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
-
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ int reg;
- reg |= MDIO_CTRL1_LPOWER;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+ reg |= XGBE_PCS_CL37_BP;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
- usleep_range(75, 100);
-
- reg &= ~MDIO_CTRL1_LPOWER;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+ reg |= XGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
}
-static void xgbe_serdes_start_ratechange(struct xgbe_prv_data *pdata)
+static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata)
{
- /* Assert Rx and Tx ratechange */
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
}
-static void xgbe_serdes_complete_ratechange(struct xgbe_prv_data *pdata)
+static void xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata)
{
- unsigned int wait;
- u16 status;
-
- /* Release Rx and Tx ratechange */
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+}
- /* Wait for Rx and Tx ready */
- wait = XGBE_RATECHANGE_COUNT;
- while (wait--) {
- usleep_range(50, 75);
+static void xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK);
+}
- status = XSIR0_IOREAD(pdata, SIR0_STATUS);
- if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
- XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
- goto rx_reset;
+static void xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_enable_interrupts(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_enable_interrupts(pdata);
+ break;
+ default:
+ break;
}
+}
- netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
- status);
-
-rx_reset:
- /* Perform Rx reset for the DFE changes */
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
+static void xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata)
+{
+ xgbe_an73_clear_interrupts(pdata);
+ xgbe_an37_clear_interrupts(pdata);
}
-static void xgbe_xgmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata)
{
unsigned int reg;
- /* Enable KR training */
- xgbe_an_enable_kr_training(pdata);
-
- /* Set MAC to 10G speed */
- pdata->hw_if.set_xgmii_speed(pdata);
-
- /* Set PCS to KR/10G speed */
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
- reg &= ~MDIO_PCS_CTRL2_TYPE;
- reg |= MDIO_PCS_CTRL2_10GBR;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- reg &= ~MDIO_CTRL1_SPEEDSEL;
- reg |= MDIO_CTRL1_SPEED10G;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ reg |= XGBE_KR_TRAINING_ENABLE;
+ XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+}
- xgbe_pcs_power_cycle(pdata);
+static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata)
+{
+ unsigned int reg;
- /* Set SerDes to 10G speed */
- xgbe_serdes_start_ratechange(pdata);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
+ reg &= ~XGBE_KR_TRAINING_ENABLE;
+ XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+}
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
- pdata->serdes_cdr_rate[XGBE_SPEED_10000]);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
- pdata->serdes_tx_amp[XGBE_SPEED_10000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
- pdata->serdes_blwc[XGBE_SPEED_10000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
- pdata->serdes_pq_skew[XGBE_SPEED_10000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_10000]);
- XRXTX_IOWRITE(pdata, RXTX_REG22,
- pdata->serdes_dfe_tap_ena[XGBE_SPEED_10000]);
+static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
+{
+ /* Enable KR training */
+ xgbe_an73_enable_kr_training(pdata);
- xgbe_serdes_complete_ratechange(pdata);
+ /* Set MAC to 10G speed */
+ pdata->hw_if.set_speed(pdata, SPEED_10000);
- netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
}
-static void xgbe_gmii_2500_mode(struct xgbe_prv_data *pdata)
+static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
-
/* Disable KR training */
- xgbe_an_disable_kr_training(pdata);
+ xgbe_an73_disable_kr_training(pdata);
/* Set MAC to 2.5G speed */
- pdata->hw_if.set_gmii_2500_speed(pdata);
+ pdata->hw_if.set_speed(pdata, SPEED_2500);
- /* Set PCS to KX/1G speed */
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
- reg &= ~MDIO_PCS_CTRL2_TYPE;
- reg |= MDIO_PCS_CTRL2_10GBX;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
+}
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- reg &= ~MDIO_CTRL1_SPEEDSEL;
- reg |= MDIO_CTRL1_SPEED1G;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+ /* Disable KR training */
+ xgbe_an73_disable_kr_training(pdata);
- xgbe_pcs_power_cycle(pdata);
+ /* Set MAC to 1G speed */
+ pdata->hw_if.set_speed(pdata, SPEED_1000);
- /* Set SerDes to 2.5G speed */
- xgbe_serdes_start_ratechange(pdata);
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
+}
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
+static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
+{
+ /* If a KR re-driver is present, change to KR mode instead */
+ if (pdata->kr_redrv)
+ return xgbe_kr_mode(pdata);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
- pdata->serdes_cdr_rate[XGBE_SPEED_2500]);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
- pdata->serdes_tx_amp[XGBE_SPEED_2500]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
- pdata->serdes_blwc[XGBE_SPEED_2500]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
- pdata->serdes_pq_skew[XGBE_SPEED_2500]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_2500]);
- XRXTX_IOWRITE(pdata, RXTX_REG22,
- pdata->serdes_dfe_tap_ena[XGBE_SPEED_2500]);
+ /* Disable KR training */
+ xgbe_an73_disable_kr_training(pdata);
- xgbe_serdes_complete_ratechange(pdata);
+ /* Set MAC to 10G speed */
+ pdata->hw_if.set_speed(pdata, SPEED_10000);
- netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SFI);
}
-static void xgbe_gmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_x_mode(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
-
/* Disable KR training */
- xgbe_an_disable_kr_training(pdata);
+ xgbe_an73_disable_kr_training(pdata);
/* Set MAC to 1G speed */
- pdata->hw_if.set_gmii_speed(pdata);
+ pdata->hw_if.set_speed(pdata, SPEED_1000);
- /* Set PCS to KX/1G speed */
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
- reg &= ~MDIO_PCS_CTRL2_TYPE;
- reg |= MDIO_PCS_CTRL2_10GBX;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
-
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- reg &= ~MDIO_CTRL1_SPEEDSEL;
- reg |= MDIO_CTRL1_SPEED1G;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_X);
+}
- xgbe_pcs_power_cycle(pdata);
+static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
+{
+ /* Disable KR training */
+ xgbe_an73_disable_kr_training(pdata);
- /* Set SerDes to 1G speed */
- xgbe_serdes_start_ratechange(pdata);
+ /* Set MAC to 1G speed */
+ pdata->hw_if.set_speed(pdata, SPEED_1000);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_1000);
+}
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
- pdata->serdes_cdr_rate[XGBE_SPEED_1000]);
- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
- pdata->serdes_tx_amp[XGBE_SPEED_1000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
- pdata->serdes_blwc[XGBE_SPEED_1000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
- pdata->serdes_pq_skew[XGBE_SPEED_1000]);
- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]);
- XRXTX_IOWRITE(pdata, RXTX_REG22,
- pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]);
+static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
+{
+ /* Disable KR training */
+ xgbe_an73_disable_kr_training(pdata);
- xgbe_serdes_complete_ratechange(pdata);
+ /* Set MAC to 1G speed */
+ pdata->hw_if.set_speed(pdata, SPEED_1000);
- netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+ /* Call PHY implementation support to complete rate change */
+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_100);
}
-static void xgbe_cur_mode(struct xgbe_prv_data *pdata,
- enum xgbe_mode *mode)
+static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
-
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
- if ((reg & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
- *mode = XGBE_MODE_KR;
- else
- *mode = XGBE_MODE_KX;
+ return pdata->phy_if.phy_impl.cur_mode(pdata);
}
static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
{
- enum xgbe_mode mode;
-
- xgbe_cur_mode(pdata, &mode);
+ return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
+}
- return (mode == XGBE_MODE_KR);
+static void xgbe_change_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ xgbe_kx_1000_mode(pdata);
+ break;
+ case XGBE_MODE_KX_2500:
+ xgbe_kx_2500_mode(pdata);
+ break;
+ case XGBE_MODE_KR:
+ xgbe_kr_mode(pdata);
+ break;
+ case XGBE_MODE_SGMII_100:
+ xgbe_sgmii_100_mode(pdata);
+ break;
+ case XGBE_MODE_SGMII_1000:
+ xgbe_sgmii_1000_mode(pdata);
+ break;
+ case XGBE_MODE_X:
+ xgbe_x_mode(pdata);
+ break;
+ case XGBE_MODE_SFI:
+ xgbe_sfi_mode(pdata);
+ break;
+ case XGBE_MODE_UNKNOWN:
+ break;
+ default:
+ netif_dbg(pdata, link, pdata->netdev,
+ "invalid operation mode requested (%u)\n", mode);
+ }
}
static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
{
- /* If we are in KR switch to KX, and vice-versa */
- if (xgbe_in_kr_mode(pdata)) {
- if (pdata->speed_set == XGBE_SPEEDSET_1000_10000)
- xgbe_gmii_mode(pdata);
- else
- xgbe_gmii_2500_mode(pdata);
- } else {
- xgbe_xgmii_mode(pdata);
- }
+ xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
}
static void xgbe_set_mode(struct xgbe_prv_data *pdata,
enum xgbe_mode mode)
{
- enum xgbe_mode cur_mode;
+ if (mode == xgbe_cur_mode(pdata))
+ return;
- xgbe_cur_mode(pdata, &cur_mode);
- if (mode != cur_mode)
- xgbe_switch_mode(pdata);
+ xgbe_change_mode(pdata, mode);
}
-static bool xgbe_use_xgmii_mode(struct xgbe_prv_data *pdata)
+static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
{
- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
- return true;
- } else {
- if (pdata->phy.speed == SPEED_10000)
- return true;
- }
+ return pdata->phy_if.phy_impl.use_mode(pdata, mode);
+}
+
+static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,
+ bool restart)
+{
+ unsigned int reg;
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1);
+ reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE;
- return false;
+ if (enable)
+ reg |= MDIO_VEND2_CTRL1_AN_ENABLE;
+
+ if (restart)
+ reg |= MDIO_VEND2_CTRL1_AN_RESTART;
+
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
}
-static bool xgbe_use_gmii_2500_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an37_restart(struct xgbe_prv_data *pdata)
{
- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
- if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
- return true;
- } else {
- if (pdata->phy.speed == SPEED_2500)
- return true;
- }
+ xgbe_an37_enable_interrupts(pdata);
+ xgbe_an37_set(pdata, true, true);
- return false;
+ netif_dbg(pdata, link, pdata->netdev, "CL37 AN enabled/restarted\n");
}
-static bool xgbe_use_gmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an37_disable(struct xgbe_prv_data *pdata)
{
- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
- if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
- return true;
- } else {
- if (pdata->phy.speed == SPEED_1000)
- return true;
- }
+ xgbe_an37_set(pdata, false, false);
+ xgbe_an37_disable_interrupts(pdata);
- return false;
+ netif_dbg(pdata, link, pdata->netdev, "CL37 AN disabled\n");
}
-static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
+static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable,
+ bool restart)
{
unsigned int reg;
@@ -437,22 +418,62 @@ static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
}
-static void xgbe_restart_an(struct xgbe_prv_data *pdata)
+static void xgbe_an73_restart(struct xgbe_prv_data *pdata)
+{
+ xgbe_an73_enable_interrupts(pdata);
+ xgbe_an73_set(pdata, true, true);
+
+ netif_dbg(pdata, link, pdata->netdev, "CL73 AN enabled/restarted\n");
+}
+
+static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
{
- xgbe_set_an(pdata, true, true);
+ xgbe_an73_set(pdata, false, false);
+ xgbe_an73_disable_interrupts(pdata);
- netif_dbg(pdata, link, pdata->netdev, "AN enabled/restarted\n");
+ netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n");
+}
+
+static void xgbe_an_restart(struct xgbe_prv_data *pdata)
+{
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_restart(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_restart(pdata);
+ break;
+ default:
+ break;
+ }
}
-static void xgbe_disable_an(struct xgbe_prv_data *pdata)
+static void xgbe_an_disable(struct xgbe_prv_data *pdata)
{
- xgbe_set_an(pdata, false, false);
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_disable(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_disable(pdata);
+ break;
+ default:
+ break;
+ }
+}
- netif_dbg(pdata, link, pdata->netdev, "AN disabled\n");
+static void xgbe_an_disable_all(struct xgbe_prv_data *pdata)
+{
+ xgbe_an73_disable(pdata);
+ xgbe_an37_disable(pdata);
}
-static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata,
- enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
+ enum xgbe_rx *state)
{
unsigned int ad_reg, lp_reg, reg;
@@ -476,13 +497,15 @@ static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata,
/* Start KR training */
reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
if (reg & XGBE_KR_TRAINING_ENABLE) {
- XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
+ if (pdata->phy_if.phy_impl.kr_training_pre)
+ pdata->phy_if.phy_impl.kr_training_pre(pdata);
reg |= XGBE_KR_TRAINING_START;
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
reg);
- XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
+ if (pdata->phy_if.phy_impl.kr_training_post)
+ pdata->phy_if.phy_impl.kr_training_post(pdata);
netif_dbg(pdata, link, pdata->netdev,
"KR training initiated\n");
@@ -491,8 +514,8 @@ static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata,
return XGBE_AN_PAGE_RECEIVED;
}
-static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata,
- enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata,
+ enum xgbe_rx *state)
{
u16 msg;
@@ -508,8 +531,8 @@ static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata,
return XGBE_AN_PAGE_RECEIVED;
}
-static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata,
- enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata,
+ enum xgbe_rx *state)
{
unsigned int link_support;
unsigned int reg, ad_reg, lp_reg;
@@ -528,12 +551,12 @@ static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata,
return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
(lp_reg & XGBE_XNP_NP_EXCHANGE))
- ? xgbe_an_tx_xnp(pdata, state)
- : xgbe_an_tx_training(pdata, state);
+ ? xgbe_an73_tx_xnp(pdata, state)
+ : xgbe_an73_tx_training(pdata, state);
}
-static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata,
- enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata,
+ enum xgbe_rx *state)
{
unsigned int ad_reg, lp_reg;
@@ -543,11 +566,11 @@ static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata,
return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
(lp_reg & XGBE_XNP_NP_EXCHANGE))
- ? xgbe_an_tx_xnp(pdata, state)
- : xgbe_an_tx_training(pdata, state);
+ ? xgbe_an73_tx_xnp(pdata, state)
+ : xgbe_an73_tx_training(pdata, state);
}
-static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata)
+static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata)
{
enum xgbe_rx *state;
unsigned long an_timeout;
@@ -566,20 +589,20 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata)
pdata->an_start = jiffies;
netif_dbg(pdata, link, pdata->netdev,
- "AN timed out, resetting state\n");
+ "CL73 AN timed out, resetting state\n");
}
}
state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
- : &pdata->kx_state;
+ : &pdata->kx_state;
switch (*state) {
case XGBE_RX_BPA:
- ret = xgbe_an_rx_bpa(pdata, state);
+ ret = xgbe_an73_rx_bpa(pdata, state);
break;
case XGBE_RX_XNP:
- ret = xgbe_an_rx_xnp(pdata, state);
+ ret = xgbe_an73_rx_xnp(pdata, state);
break;
default:
@@ -589,7 +612,7 @@ static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata)
return ret;
}
-static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata)
+static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
{
/* Be sure we aren't looping trying to negotiate */
if (xgbe_in_kr_mode(pdata)) {
@@ -611,23 +634,43 @@ static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata)
return XGBE_AN_NO_LINK;
}
- xgbe_disable_an(pdata);
+ xgbe_an73_disable(pdata);
xgbe_switch_mode(pdata);
- xgbe_restart_an(pdata);
+ xgbe_an73_restart(pdata);
return XGBE_AN_INCOMPAT_LINK;
}
-static irqreturn_t xgbe_an_isr(int irq, void *data)
+static void xgbe_an37_isr(struct xgbe_prv_data *pdata)
{
- struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+ unsigned int reg;
- netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
+ /* Disable AN interrupts */
+ xgbe_an37_disable_interrupts(pdata);
+
+ /* Save the interrupt(s) that fired */
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+ pdata->an_int = reg & XGBE_AN_CL37_INT_MASK;
+ pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK;
+ if (pdata->an_int) {
+ /* Clear the interrupt(s) that fired and process them */
+ reg &= ~XGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
+
+ queue_work(pdata->an_workqueue, &pdata->an_irq_work);
+ } else {
+ /* Enable AN interrupts */
+ xgbe_an37_enable_interrupts(pdata);
+ }
+}
+
+static void xgbe_an73_isr(struct xgbe_prv_data *pdata)
+{
/* Disable AN interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+ xgbe_an73_disable_interrupts(pdata);
/* Save the interrupt(s) that fired */
pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
@@ -639,13 +682,37 @@ static irqreturn_t xgbe_an_isr(int irq, void *data)
queue_work(pdata->an_workqueue, &pdata->an_irq_work);
} else {
/* Enable AN interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK,
- XGBE_AN_INT_MASK);
+ xgbe_an73_enable_interrupts(pdata);
+ }
+}
+
+static irqreturn_t xgbe_an_isr(int irq, void *data)
+{
+ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+
+ netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
+
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_isr(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_isr(pdata);
+ break;
+ default:
+ break;
}
return IRQ_HANDLED;
}
+static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata)
+{
+ return xgbe_an_isr(irq, pdata);
+}
+
static void xgbe_an_irq_work(struct work_struct *work)
{
struct xgbe_prv_data *pdata = container_of(work,
@@ -679,36 +746,87 @@ static const char *xgbe_state_as_string(enum xgbe_an state)
}
}
-static void xgbe_an_state_machine(struct work_struct *work)
+static void xgbe_an37_state_machine(struct xgbe_prv_data *pdata)
{
- struct xgbe_prv_data *pdata = container_of(work,
- struct xgbe_prv_data,
- an_work);
enum xgbe_an cur_state = pdata->an_state;
- mutex_lock(&pdata->an_mutex);
+ if (!pdata->an_int)
+ return;
+
+ if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) {
+ pdata->an_state = XGBE_AN_COMPLETE;
+ pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT;
+
+ /* If SGMII is enabled, check the link status */
+ if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) &&
+ !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS))
+ pdata->an_state = XGBE_AN_NO_LINK;
+ }
+
+ netif_dbg(pdata, link, pdata->netdev, "CL37 AN %s\n",
+ xgbe_state_as_string(pdata->an_state));
+
+ cur_state = pdata->an_state;
+
+ switch (pdata->an_state) {
+ case XGBE_AN_READY:
+ break;
+
+ case XGBE_AN_COMPLETE:
+ netif_dbg(pdata, link, pdata->netdev,
+ "Auto negotiation successful\n");
+ break;
+
+ case XGBE_AN_NO_LINK:
+ break;
+
+ default:
+ pdata->an_state = XGBE_AN_ERROR;
+ }
+
+ if (pdata->an_state == XGBE_AN_ERROR) {
+ netdev_err(pdata->netdev,
+ "error during auto-negotiation, state=%u\n",
+ cur_state);
+
+ pdata->an_int = 0;
+ xgbe_an37_clear_interrupts(pdata);
+ }
+
+ if (pdata->an_state >= XGBE_AN_COMPLETE) {
+ pdata->an_result = pdata->an_state;
+ pdata->an_state = XGBE_AN_READY;
+
+ netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n",
+ xgbe_state_as_string(pdata->an_result));
+ }
+
+ xgbe_an37_enable_interrupts(pdata);
+}
+
+static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
+{
+ enum xgbe_an cur_state = pdata->an_state;
if (!pdata->an_int)
- goto out;
+ return;
next_int:
- if (pdata->an_int & XGBE_AN_PG_RCV) {
+ if (pdata->an_int & XGBE_AN_CL73_PG_RCV) {
pdata->an_state = XGBE_AN_PAGE_RECEIVED;
- pdata->an_int &= ~XGBE_AN_PG_RCV;
- } else if (pdata->an_int & XGBE_AN_INC_LINK) {
+ pdata->an_int &= ~XGBE_AN_CL73_PG_RCV;
+ } else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) {
pdata->an_state = XGBE_AN_INCOMPAT_LINK;
- pdata->an_int &= ~XGBE_AN_INC_LINK;
- } else if (pdata->an_int & XGBE_AN_INT_CMPLT) {
+ pdata->an_int &= ~XGBE_AN_CL73_INC_LINK;
+ } else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) {
pdata->an_state = XGBE_AN_COMPLETE;
- pdata->an_int &= ~XGBE_AN_INT_CMPLT;
+ pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT;
} else {
pdata->an_state = XGBE_AN_ERROR;
}
- pdata->an_result = pdata->an_state;
-
again:
- netif_dbg(pdata, link, pdata->netdev, "AN %s\n",
+ netif_dbg(pdata, link, pdata->netdev, "CL73 AN %s\n",
xgbe_state_as_string(pdata->an_state));
cur_state = pdata->an_state;
@@ -719,14 +837,14 @@ again:
break;
case XGBE_AN_PAGE_RECEIVED:
- pdata->an_state = xgbe_an_page_received(pdata);
+ pdata->an_state = xgbe_an73_page_received(pdata);
pdata->an_supported++;
break;
case XGBE_AN_INCOMPAT_LINK:
pdata->an_supported = 0;
pdata->parallel_detect = 0;
- pdata->an_state = xgbe_an_incompat_link(pdata);
+ pdata->an_state = xgbe_an73_incompat_link(pdata);
break;
case XGBE_AN_COMPLETE:
@@ -745,14 +863,14 @@ again:
if (pdata->an_state == XGBE_AN_NO_LINK) {
pdata->an_int = 0;
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ xgbe_an73_clear_interrupts(pdata);
} else if (pdata->an_state == XGBE_AN_ERROR) {
netdev_err(pdata->netdev,
"error during auto-negotiation, state=%u\n",
cur_state);
pdata->an_int = 0;
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ xgbe_an73_clear_interrupts(pdata);
}
if (pdata->an_state >= XGBE_AN_COMPLETE) {
@@ -762,7 +880,7 @@ again:
pdata->kx_state = XGBE_RX_BPA;
pdata->an_start = 0;
- netif_dbg(pdata, link, pdata->netdev, "AN result: %s\n",
+ netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n",
xgbe_state_as_string(pdata->an_result));
}
@@ -772,20 +890,88 @@ again:
if (pdata->an_int)
goto next_int;
-out:
- /* Enable AN interrupts on the way out */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK);
+ xgbe_an73_enable_interrupts(pdata);
+}
+
+static void xgbe_an_state_machine(struct work_struct *work)
+{
+ struct xgbe_prv_data *pdata = container_of(work,
+ struct xgbe_prv_data,
+ an_work);
+
+ mutex_lock(&pdata->an_mutex);
+
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_state_machine(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_state_machine(pdata);
+ break;
+ default:
+ break;
+ }
mutex_unlock(&pdata->an_mutex);
}
-static void xgbe_an_init(struct xgbe_prv_data *pdata)
+static void xgbe_an37_init(struct xgbe_prv_data *pdata)
{
- unsigned int reg;
+ unsigned int advertising, reg;
+
+ advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
+
+ /* Set up Advertisement register */
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+ if (advertising & ADVERTISED_Pause)
+ reg |= 0x100;
+ else
+ reg &= ~0x100;
+
+ if (advertising & ADVERTISED_Asym_Pause)
+ reg |= 0x80;
+ else
+ reg &= ~0x80;
+
+ /* Full duplex, but not half */
+ reg |= XGBE_AN_CL37_FD_MASK;
+ reg &= ~XGBE_AN_CL37_HD_MASK;
+
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
+
+ /* Set up the Control register */
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+ reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK;
+ reg &= ~XGBE_AN_CL37_PCS_MODE_MASK;
+
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL37:
+ reg |= XGBE_AN_CL37_PCS_MODE_BASEX;
+ break;
+ case XGBE_AN_MODE_CL37_SGMII:
+ reg |= XGBE_AN_CL37_PCS_MODE_SGMII;
+ break;
+ default:
+ break;
+ }
+
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+
+ netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n",
+ (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII");
+}
+
+static void xgbe_an73_init(struct xgbe_prv_data *pdata)
+{
+ unsigned int advertising, reg;
+
+ advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
/* Set up Advertisement register 3 first */
reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
- if (pdata->phy.advertising & ADVERTISED_10000baseR_FEC)
+ if (advertising & ADVERTISED_10000baseR_FEC)
reg |= 0xc000;
else
reg &= ~0xc000;
@@ -794,13 +980,13 @@ static void xgbe_an_init(struct xgbe_prv_data *pdata)
/* Set up Advertisement register 2 next */
reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
+ if (advertising & ADVERTISED_10000baseKR_Full)
reg |= 0x80;
else
reg &= ~0x80;
- if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
- (pdata->phy.advertising & ADVERTISED_2500baseX_Full))
+ if ((advertising & ADVERTISED_1000baseKX_Full) ||
+ (advertising & ADVERTISED_2500baseX_Full))
reg |= 0x20;
else
reg &= ~0x20;
@@ -809,12 +995,12 @@ static void xgbe_an_init(struct xgbe_prv_data *pdata)
/* Set up Advertisement register 1 last */
reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
- if (pdata->phy.advertising & ADVERTISED_Pause)
+ if (advertising & ADVERTISED_Pause)
reg |= 0x400;
else
reg &= ~0x400;
- if (pdata->phy.advertising & ADVERTISED_Asym_Pause)
+ if (advertising & ADVERTISED_Asym_Pause)
reg |= 0x800;
else
reg &= ~0x800;
@@ -824,7 +1010,25 @@ static void xgbe_an_init(struct xgbe_prv_data *pdata)
XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
- netif_dbg(pdata, link, pdata->netdev, "AN initialized\n");
+ netif_dbg(pdata, link, pdata->netdev, "CL73 AN initialized\n");
+}
+
+static void xgbe_an_init(struct xgbe_prv_data *pdata)
+{
+ /* Set up advertisement registers based on current settings */
+ pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata);
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ case XGBE_AN_MODE_CL73_REDRV:
+ xgbe_an73_init(pdata);
+ break;
+ case XGBE_AN_MODE_CL37:
+ case XGBE_AN_MODE_CL37_SGMII:
+ xgbe_an37_init(pdata);
+ break;
+ default:
+ break;
+ }
}
static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
@@ -842,6 +1046,8 @@ static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
static const char *xgbe_phy_speed_string(int speed)
{
switch (speed) {
+ case SPEED_100:
+ return "100Mbps";
case SPEED_1000:
return "1Gbps";
case SPEED_2500:
@@ -907,24 +1113,32 @@ static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
xgbe_phy_print_status(pdata);
}
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+ return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
+}
+
static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
{
+ enum xgbe_mode mode;
+
netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
/* Disable auto-negotiation */
- xgbe_disable_an(pdata);
-
- /* Validate/Set specified speed */
- switch (pdata->phy.speed) {
- case SPEED_10000:
- xgbe_set_mode(pdata, XGBE_MODE_KR);
+ xgbe_an_disable(pdata);
+
+ /* Set specified mode for specified speed */
+ mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ case XGBE_MODE_KX_2500:
+ case XGBE_MODE_KR:
+ case XGBE_MODE_SGMII_100:
+ case XGBE_MODE_SGMII_1000:
+ case XGBE_MODE_X:
+ case XGBE_MODE_SFI:
break;
-
- case SPEED_2500:
- case SPEED_1000:
- xgbe_set_mode(pdata, XGBE_MODE_KX);
- break;
-
+ case XGBE_MODE_UNKNOWN:
default:
return -EINVAL;
}
@@ -933,38 +1147,60 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
if (pdata->phy.duplex != DUPLEX_FULL)
return -EINVAL;
+ xgbe_set_mode(pdata, mode);
+
return 0;
}
static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
{
+ int ret;
+
set_bit(XGBE_LINK_INIT, &pdata->dev_state);
pdata->link_check = jiffies;
- if (pdata->phy.autoneg != AUTONEG_ENABLE)
- return xgbe_phy_config_fixed(pdata);
+ ret = pdata->phy_if.phy_impl.an_config(pdata);
+ if (ret)
+ return ret;
+
+ if (pdata->phy.autoneg != AUTONEG_ENABLE) {
+ ret = xgbe_phy_config_fixed(pdata);
+ if (ret || !pdata->kr_redrv)
+ return ret;
- netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
+ netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n");
+ } else {
+ netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
+ }
/* Disable auto-negotiation interrupt */
disable_irq(pdata->an_irq);
/* Start auto-negotiation in a supported mode */
- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) {
+ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
xgbe_set_mode(pdata, XGBE_MODE_KR);
- } else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
- (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) {
- xgbe_set_mode(pdata, XGBE_MODE_KX);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+ xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+ xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+ xgbe_set_mode(pdata, XGBE_MODE_SFI);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+ xgbe_set_mode(pdata, XGBE_MODE_X);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+ xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+ xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
} else {
enable_irq(pdata->an_irq);
return -EINVAL;
}
/* Disable and stop any in progress auto-negotiation */
- xgbe_disable_an(pdata);
+ xgbe_an_disable_all(pdata);
/* Clear any auto-negotitation interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ xgbe_an_clear_interrupts_all(pdata);
pdata->an_result = XGBE_AN_READY;
pdata->an_state = XGBE_AN_READY;
@@ -974,11 +1210,8 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
/* Re-enable auto-negotiation interrupt */
enable_irq(pdata->an_irq);
- /* Set up advertisement registers based on current settings */
xgbe_an_init(pdata);
-
- /* Enable and start auto-negotiation */
- xgbe_restart_an(pdata);
+ xgbe_an_restart(pdata);
return 0;
}
@@ -1016,108 +1249,52 @@ static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
}
}
-static void xgbe_phy_status_force(struct xgbe_prv_data *pdata)
+static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
{
- if (xgbe_in_kr_mode(pdata)) {
- pdata->phy.speed = SPEED_10000;
- } else {
- switch (pdata->speed_set) {
- case XGBE_SPEEDSET_1000_10000:
- pdata->phy.speed = SPEED_1000;
- break;
-
- case XGBE_SPEEDSET_2500_10000:
- pdata->phy.speed = SPEED_2500;
- break;
- }
- }
- pdata->phy.duplex = DUPLEX_FULL;
+ return pdata->phy_if.phy_impl.an_outcome(pdata);
}
-static void xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
+static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
{
- unsigned int ad_reg, lp_reg;
+ enum xgbe_mode mode;
pdata->phy.lp_advertising = 0;
if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
- return xgbe_phy_status_force(pdata);
-
- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
- pdata->phy.lp_advertising |= ADVERTISED_Backplane;
-
- /* Compare Advertisement and Link Partner register 1 */
- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
- if (lp_reg & 0x400)
- pdata->phy.lp_advertising |= ADVERTISED_Pause;
- if (lp_reg & 0x800)
- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
-
- if (pdata->phy.pause_autoneg) {
- /* Set flow control based on auto-negotiation result */
- pdata->phy.tx_pause = 0;
- pdata->phy.rx_pause = 0;
-
- if (ad_reg & lp_reg & 0x400) {
- pdata->phy.tx_pause = 1;
- pdata->phy.rx_pause = 1;
- } else if (ad_reg & lp_reg & 0x800) {
- if (ad_reg & 0x400)
- pdata->phy.rx_pause = 1;
- else if (lp_reg & 0x400)
- pdata->phy.tx_pause = 1;
- }
- }
-
- /* Compare Advertisement and Link Partner register 2 */
- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
- if (lp_reg & 0x80)
- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
- if (lp_reg & 0x20) {
- switch (pdata->speed_set) {
- case XGBE_SPEEDSET_1000_10000:
- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
- break;
- case XGBE_SPEEDSET_2500_10000:
- pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
- break;
- }
- }
+ mode = xgbe_cur_mode(pdata);
+ else
+ mode = xgbe_phy_status_aneg(pdata);
- ad_reg &= lp_reg;
- if (ad_reg & 0x80) {
+ switch (mode) {
+ case XGBE_MODE_SGMII_100:
+ pdata->phy.speed = SPEED_100;
+ break;
+ case XGBE_MODE_X:
+ case XGBE_MODE_KX_1000:
+ case XGBE_MODE_SGMII_1000:
+ pdata->phy.speed = SPEED_1000;
+ break;
+ case XGBE_MODE_KX_2500:
+ pdata->phy.speed = SPEED_2500;
+ break;
+ case XGBE_MODE_KR:
+ case XGBE_MODE_SFI:
pdata->phy.speed = SPEED_10000;
- xgbe_set_mode(pdata, XGBE_MODE_KR);
- } else if (ad_reg & 0x20) {
- switch (pdata->speed_set) {
- case XGBE_SPEEDSET_1000_10000:
- pdata->phy.speed = SPEED_1000;
- break;
-
- case XGBE_SPEEDSET_2500_10000:
- pdata->phy.speed = SPEED_2500;
- break;
- }
-
- xgbe_set_mode(pdata, XGBE_MODE_KX);
- } else {
+ break;
+ case XGBE_MODE_UNKNOWN:
+ default:
pdata->phy.speed = SPEED_UNKNOWN;
}
- /* Compare Advertisement and Link Partner register 3 */
- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
- if (lp_reg & 0xc000)
- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
-
pdata->phy.duplex = DUPLEX_FULL;
+
+ xgbe_set_mode(pdata, mode);
}
static void xgbe_phy_status(struct xgbe_prv_data *pdata)
{
- unsigned int reg, link_aneg;
+ unsigned int link_aneg;
+ int an_restart;
if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
netif_carrier_off(pdata->netdev);
@@ -1128,12 +1305,12 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
- /* Get the link status. Link status is latched low, so read
- * once to clear and then read again to get current state
- */
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
- pdata->phy.link = (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
+ pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata,
+ &an_restart);
+ if (an_restart) {
+ xgbe_phy_config_aneg(pdata);
+ return;
+ }
if (pdata->phy.link) {
if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
@@ -1141,7 +1318,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
return;
}
- xgbe_phy_status_aneg(pdata);
+ xgbe_phy_status_result(pdata);
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
@@ -1155,7 +1332,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
return;
}
- xgbe_phy_status_aneg(pdata);
+ xgbe_phy_status_result(pdata);
netif_carrier_off(pdata->netdev);
}
@@ -1168,13 +1345,19 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
{
netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
+ if (!pdata->phy_started)
+ return;
+
+ /* Indicate the PHY is down */
+ pdata->phy_started = 0;
+
/* Disable auto-negotiation */
- xgbe_disable_an(pdata);
+ xgbe_an_disable_all(pdata);
- /* Disable auto-negotiation interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+ if (pdata->dev_irq != pdata->an_irq)
+ devm_free_irq(pdata->dev, pdata->an_irq, pdata);
- devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+ pdata->phy_if.phy_impl.stop(pdata);
pdata->phy.link = 0;
netif_carrier_off(pdata->netdev);
@@ -1189,64 +1372,74 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
- ret = devm_request_irq(pdata->dev, pdata->an_irq,
- xgbe_an_isr, 0, pdata->an_name,
- pdata);
- if (ret) {
- netdev_err(netdev, "phy irq request failed\n");
+ ret = pdata->phy_if.phy_impl.start(pdata);
+ if (ret)
return ret;
+
+ /* If we have a separate AN irq, enable it */
+ if (pdata->dev_irq != pdata->an_irq) {
+ ret = devm_request_irq(pdata->dev, pdata->an_irq,
+ xgbe_an_isr, 0, pdata->an_name,
+ pdata);
+ if (ret) {
+ netdev_err(netdev, "phy irq request failed\n");
+ goto err_stop;
+ }
}
/* Set initial mode - call the mode setting routines
* directly to insure we are properly configured
*/
- if (xgbe_use_xgmii_mode(pdata)) {
- xgbe_xgmii_mode(pdata);
- } else if (xgbe_use_gmii_mode(pdata)) {
- xgbe_gmii_mode(pdata);
- } else if (xgbe_use_gmii_2500_mode(pdata)) {
- xgbe_gmii_2500_mode(pdata);
+ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
+ xgbe_kr_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+ xgbe_kx_2500_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+ xgbe_kx_1000_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+ xgbe_sfi_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+ xgbe_x_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+ xgbe_sgmii_1000_mode(pdata);
+ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+ xgbe_sgmii_100_mode(pdata);
} else {
ret = -EINVAL;
goto err_irq;
}
- /* Set up advertisement registers based on current settings */
- xgbe_an_init(pdata);
+ /* Indicate the PHY is up and running */
+ pdata->phy_started = 1;
- /* Enable auto-negotiation interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
+ xgbe_an_init(pdata);
+ xgbe_an_enable_interrupts(pdata);
return xgbe_phy_config_aneg(pdata);
err_irq:
- devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+ if (pdata->dev_irq != pdata->an_irq)
+ devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+
+err_stop:
+ pdata->phy_if.phy_impl.stop(pdata);
return ret;
}
static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
{
- unsigned int count, reg;
-
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- reg |= MDIO_CTRL1_RESET;
- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-
- count = 50;
- do {
- msleep(20);
- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
- } while ((reg & MDIO_CTRL1_RESET) && --count);
+ int ret;
- if (reg & MDIO_CTRL1_RESET)
- return -ETIMEDOUT;
+ ret = pdata->phy_if.phy_impl.reset(pdata);
+ if (ret)
+ return ret;
/* Disable auto-negotiation for now */
- xgbe_disable_an(pdata);
+ xgbe_an_disable_all(pdata);
/* Clear auto-negotiation interrupts */
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ xgbe_an_clear_interrupts_all(pdata);
return 0;
}
@@ -1257,74 +1450,96 @@ static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
dev_dbg(dev, "\n************* PHY Reg dump **********************\n");
- dev_dbg(dev, "PCS Control Reg (%#04x) = %#04x\n", MDIO_CTRL1,
+ dev_dbg(dev, "PCS Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1));
- dev_dbg(dev, "PCS Status Reg (%#04x) = %#04x\n", MDIO_STAT1,
+ dev_dbg(dev, "PCS Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1));
- dev_dbg(dev, "Phy Id (PHYS ID 1 %#04x)= %#04x\n", MDIO_DEVID1,
+ dev_dbg(dev, "Phy Id (PHYS ID 1 %#06x)= %#06x\n", MDIO_DEVID1,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1));
- dev_dbg(dev, "Phy Id (PHYS ID 2 %#04x)= %#04x\n", MDIO_DEVID2,
+ dev_dbg(dev, "Phy Id (PHYS ID 2 %#06x)= %#06x\n", MDIO_DEVID2,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2));
- dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS1,
+ dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS1,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1));
- dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS2,
+ dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS2,
XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2));
- dev_dbg(dev, "Auto-Neg Control Reg (%#04x) = %#04x\n", MDIO_CTRL1,
+ dev_dbg(dev, "Auto-Neg Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1));
- dev_dbg(dev, "Auto-Neg Status Reg (%#04x) = %#04x\n", MDIO_STAT1,
+ dev_dbg(dev, "Auto-Neg Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1));
- dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#04x) = %#04x\n",
+ dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#06x) = %#06x\n",
MDIO_AN_ADVERTISE,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE));
- dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#04x) = %#04x\n",
+ dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#06x) = %#06x\n",
MDIO_AN_ADVERTISE + 1,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1));
- dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#04x) = %#04x\n",
+ dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#06x) = %#06x\n",
MDIO_AN_ADVERTISE + 2,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2));
- dev_dbg(dev, "Auto-Neg Completion Reg (%#04x) = %#04x\n",
+ dev_dbg(dev, "Auto-Neg Completion Reg (%#06x) = %#06x\n",
MDIO_AN_COMP_STAT,
XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT));
dev_dbg(dev, "\n*************************************************\n");
}
-static void xgbe_phy_init(struct xgbe_prv_data *pdata)
+static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
{
+ if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
+ return SPEED_10000;
+ else if (pdata->phy.advertising & ADVERTISED_10000baseT_Full)
+ return SPEED_10000;
+ else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
+ return SPEED_2500;
+ else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
+ return SPEED_1000;
+ else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full)
+ return SPEED_1000;
+ else if (pdata->phy.advertising & ADVERTISED_100baseT_Full)
+ return SPEED_100;
+
+ return SPEED_UNKNOWN;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+ xgbe_phy_stop(pdata);
+
+ pdata->phy_if.phy_impl.exit(pdata);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+ int ret;
+
mutex_init(&pdata->an_mutex);
INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
pdata->mdio_mmd = MDIO_MMD_PCS;
- /* Initialize supported features */
- pdata->phy.supported = SUPPORTED_Autoneg;
- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
- pdata->phy.supported |= SUPPORTED_Backplane;
- pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
- switch (pdata->speed_set) {
- case XGBE_SPEEDSET_1000_10000:
- pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
- break;
- case XGBE_SPEEDSET_2500_10000:
- pdata->phy.supported |= SUPPORTED_2500baseX_Full;
- break;
- }
-
+ /* Check for FEC support */
pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
MDIO_PMA_10GBR_FECABLE);
pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
MDIO_PMA_10GBR_FECABLE_ERRABLE);
- if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
- pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
+ /* Setup the phy (including supported features) */
+ ret = pdata->phy_if.phy_impl.init(pdata);
+ if (ret)
+ return ret;
pdata->phy.advertising = pdata->phy.supported;
pdata->phy.address = 0;
- pdata->phy.autoneg = AUTONEG_ENABLE;
- pdata->phy.speed = SPEED_UNKNOWN;
- pdata->phy.duplex = DUPLEX_UNKNOWN;
+ if (pdata->phy.advertising & ADVERTISED_Autoneg) {
+ pdata->phy.autoneg = AUTONEG_ENABLE;
+ pdata->phy.speed = SPEED_UNKNOWN;
+ pdata->phy.duplex = DUPLEX_UNKNOWN;
+ } else {
+ pdata->phy.autoneg = AUTONEG_DISABLE;
+ pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
+ pdata->phy.duplex = DUPLEX_FULL;
+ }
pdata->phy.link = 0;
@@ -1346,11 +1561,14 @@ static void xgbe_phy_init(struct xgbe_prv_data *pdata)
if (netif_msg_drv(pdata))
xgbe_dump_phy_registers(pdata);
+
+ return 0;
}
void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
{
phy_if->phy_init = xgbe_phy_init;
+ phy_if->phy_exit = xgbe_phy_exit;
phy_if->phy_reset = xgbe_phy_reset;
phy_if->phy_start = xgbe_phy_start;
@@ -1358,4 +1576,8 @@ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
phy_if->phy_status = xgbe_phy_status;
phy_if->phy_config_aneg = xgbe_phy_config_aneg;
+
+ phy_if->phy_valid_speed = xgbe_phy_valid_speed;
+
+ phy_if->an_isr = xgbe_an_combined_isr;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
new file mode 100644
index 000000000000..e76b7f65b805
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -0,0 +1,529 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * 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 of Advanced Micro Devices, Inc. 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 <COPYRIGHT HOLDER> 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.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/log2.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+static int xgbe_config_msi(struct xgbe_prv_data *pdata)
+{
+ unsigned int msi_count;
+ unsigned int i, j;
+ int ret;
+
+ msi_count = XGBE_MSIX_BASE_COUNT;
+ msi_count += max(pdata->rx_ring_count,
+ pdata->tx_ring_count);
+ msi_count = roundup_pow_of_two(msi_count);
+
+ ret = pci_enable_msi_exact(pdata->pcidev, msi_count);
+ if (ret < 0) {
+ dev_info(pdata->dev, "MSI request for %u interrupts failed\n",
+ msi_count);
+
+ ret = pci_enable_msi(pdata->pcidev);
+ if (ret < 0) {
+ dev_info(pdata->dev, "MSI enablement failed\n");
+ return ret;
+ }
+
+ msi_count = 1;
+ }
+
+ pdata->irq_count = msi_count;
+
+ pdata->dev_irq = pdata->pcidev->irq;
+
+ if (msi_count > 1) {
+ pdata->ecc_irq = pdata->pcidev->irq + 1;
+ pdata->i2c_irq = pdata->pcidev->irq + 2;
+ pdata->an_irq = pdata->pcidev->irq + 3;
+
+ for (i = XGBE_MSIX_BASE_COUNT, j = 0;
+ (i < msi_count) && (j < XGBE_MAX_DMA_CHANNELS);
+ i++, j++)
+ pdata->channel_irq[j] = pdata->pcidev->irq + i;
+ pdata->channel_irq_count = j;
+
+ pdata->per_channel_irq = 1;
+ pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL;
+ } else {
+ pdata->ecc_irq = pdata->pcidev->irq;
+ pdata->i2c_irq = pdata->pcidev->irq;
+ pdata->an_irq = pdata->pcidev->irq;
+ }
+
+ if (netif_msg_probe(pdata))
+ dev_dbg(pdata->dev, "MSI interrupts enabled\n");
+
+ return 0;
+}
+
+static int xgbe_config_msix(struct xgbe_prv_data *pdata)
+{
+ unsigned int msix_count;
+ unsigned int i, j;
+ int ret;
+
+ msix_count = XGBE_MSIX_BASE_COUNT;
+ msix_count += max(pdata->rx_ring_count,
+ pdata->tx_ring_count);
+
+ pdata->msix_entries = devm_kcalloc(pdata->dev, msix_count,
+ sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!pdata->msix_entries)
+ return -ENOMEM;
+
+ for (i = 0; i < msix_count; i++)
+ pdata->msix_entries[i].entry = i;
+
+ ret = pci_enable_msix_range(pdata->pcidev, pdata->msix_entries,
+ XGBE_MSIX_MIN_COUNT, msix_count);
+ if (ret < 0) {
+ dev_info(pdata->dev, "MSI-X enablement failed\n");
+ devm_kfree(pdata->dev, pdata->msix_entries);
+ pdata->msix_entries = NULL;
+ return ret;
+ }
+
+ pdata->irq_count = ret;
+
+ pdata->dev_irq = pdata->msix_entries[0].vector;
+ pdata->ecc_irq = pdata->msix_entries[1].vector;
+ pdata->i2c_irq = pdata->msix_entries[2].vector;
+ pdata->an_irq = pdata->msix_entries[3].vector;
+
+ for (i = XGBE_MSIX_BASE_COUNT, j = 0; i < ret; i++, j++)
+ pdata->channel_irq[j] = pdata->msix_entries[i].vector;
+ pdata->channel_irq_count = j;
+
+ pdata->per_channel_irq = 1;
+ pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL;
+
+ if (netif_msg_probe(pdata))
+ dev_dbg(pdata->dev, "MSI-X interrupts enabled\n");
+
+ return 0;
+}
+
+static int xgbe_config_irqs(struct xgbe_prv_data *pdata)
+{
+ int ret;
+
+ ret = xgbe_config_msix(pdata);
+ if (!ret)
+ goto out;
+
+ ret = xgbe_config_msi(pdata);
+ if (!ret)
+ goto out;
+
+ pdata->irq_count = 1;
+ pdata->irq_shared = 1;
+
+ pdata->dev_irq = pdata->pcidev->irq;
+ pdata->ecc_irq = pdata->pcidev->irq;
+ pdata->i2c_irq = pdata->pcidev->irq;
+ pdata->an_irq = pdata->pcidev->irq;
+
+out:
+ if (netif_msg_probe(pdata)) {
+ unsigned int i;
+
+ dev_dbg(pdata->dev, " dev irq=%d\n", pdata->dev_irq);
+ dev_dbg(pdata->dev, " ecc irq=%d\n", pdata->ecc_irq);
+ dev_dbg(pdata->dev, " i2c irq=%d\n", pdata->i2c_irq);
+ dev_dbg(pdata->dev, " an irq=%d\n", pdata->an_irq);
+ for (i = 0; i < pdata->channel_irq_count; i++)
+ dev_dbg(pdata->dev, " dma%u irq=%d\n",
+ i, pdata->channel_irq[i]);
+ }
+
+ return 0;
+}
+
+static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct xgbe_prv_data *pdata;
+ struct device *dev = &pdev->dev;
+ void __iomem * const *iomap_table;
+ unsigned int ma_lo, ma_hi;
+ unsigned int reg;
+ int bar_mask;
+ int ret;
+
+ pdata = xgbe_alloc_pdata(dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto err_alloc;
+ }
+
+ pdata->pcidev = pdev;
+ pci_set_drvdata(pdev, pdata);
+
+ /* Get the version data */
+ pdata->vdata = (struct xgbe_version_data *)id->driver_data;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "pcim_enable_device failed\n");
+ goto err_pci_enable;
+ }
+
+ /* Obtain the mmio areas for the device */
+ bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+ ret = pcim_iomap_regions(pdev, bar_mask, XGBE_DRV_NAME);
+ if (ret) {
+ dev_err(dev, "pcim_iomap_regions failed\n");
+ goto err_pci_enable;
+ }
+
+ iomap_table = pcim_iomap_table(pdev);
+ if (!iomap_table) {
+ dev_err(dev, "pcim_iomap_table failed\n");
+ ret = -ENOMEM;
+ goto err_pci_enable;
+ }
+
+ pdata->xgmac_regs = iomap_table[XGBE_XGMAC_BAR];
+ if (!pdata->xgmac_regs) {
+ dev_err(dev, "xgmac ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_pci_enable;
+ }
+ pdata->xprop_regs = pdata->xgmac_regs + XGBE_MAC_PROP_OFFSET;
+ pdata->xi2c_regs = pdata->xgmac_regs + XGBE_I2C_CTRL_OFFSET;
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
+ dev_dbg(dev, "xprop_regs = %p\n", pdata->xprop_regs);
+ dev_dbg(dev, "xi2c_regs = %p\n", pdata->xi2c_regs);
+ }
+
+ pdata->xpcs_regs = iomap_table[XGBE_XPCS_BAR];
+ if (!pdata->xpcs_regs) {
+ dev_err(dev, "xpcs ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_pci_enable;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs);
+
+ /* Configure the PCS indirect addressing support */
+ reg = XPCS32_IOREAD(pdata, PCS_V2_WINDOW_DEF);
+ pdata->xpcs_window = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, OFFSET);
+ pdata->xpcs_window <<= 6;
+ pdata->xpcs_window_size = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, SIZE);
+ pdata->xpcs_window_size = 1 << (pdata->xpcs_window_size + 7);
+ pdata->xpcs_window_mask = pdata->xpcs_window_size - 1;
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(dev, "xpcs window = %#010x\n",
+ pdata->xpcs_window);
+ dev_dbg(dev, "xpcs window size = %#010x\n",
+ pdata->xpcs_window_size);
+ dev_dbg(dev, "xpcs window mask = %#010x\n",
+ pdata->xpcs_window_mask);
+ }
+
+ pci_set_master(pdev);
+
+ /* Enable all interrupts in the hardware */
+ XP_IOWRITE(pdata, XP_INT_EN, 0x1fffff);
+
+ /* Retrieve the MAC address */
+ ma_lo = XP_IOREAD(pdata, XP_MAC_ADDR_LO);
+ ma_hi = XP_IOREAD(pdata, XP_MAC_ADDR_HI);
+ pdata->mac_addr[0] = ma_lo & 0xff;
+ pdata->mac_addr[1] = (ma_lo >> 8) & 0xff;
+ pdata->mac_addr[2] = (ma_lo >> 16) & 0xff;
+ pdata->mac_addr[3] = (ma_lo >> 24) & 0xff;
+ pdata->mac_addr[4] = ma_hi & 0xff;
+ pdata->mac_addr[5] = (ma_hi >> 8) & 0xff;
+ if (!XP_GET_BITS(ma_hi, XP_MAC_ADDR_HI, VALID) ||
+ !is_valid_ether_addr(pdata->mac_addr)) {
+ dev_err(dev, "invalid mac address\n");
+ ret = -EINVAL;
+ goto err_pci_enable;
+ }
+
+ /* Clock settings */
+ pdata->sysclk_rate = XGBE_V2_DMA_CLOCK_FREQ;
+ pdata->ptpclk_rate = XGBE_V2_PTP_CLOCK_FREQ;
+
+ /* Set the DMA coherency values */
+ pdata->coherent = 1;
+ pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+ pdata->arcache = XGBE_DMA_OS_ARCACHE;
+ pdata->awcache = XGBE_DMA_OS_AWCACHE;
+
+ /* Set the maximum channels and queues */
+ reg = XP_IOREAD(pdata, XP_PROP_1);
+ pdata->tx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_DMA);
+ pdata->rx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_DMA);
+ pdata->tx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_QUEUES);
+ pdata->rx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_QUEUES);
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
+ pdata->tx_max_channel_count,
+ pdata->tx_max_channel_count);
+ dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n",
+ pdata->tx_max_q_count, pdata->rx_max_q_count);
+ }
+
+ /* Set the hardware channel and queue counts */
+ xgbe_set_counts(pdata);
+
+ /* Set the maximum fifo amounts */
+ reg = XP_IOREAD(pdata, XP_PROP_2);
+ pdata->tx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, TX_FIFO_SIZE);
+ pdata->tx_max_fifo_size *= 16384;
+ pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size,
+ pdata->vdata->tx_max_fifo_size);
+ pdata->rx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, RX_FIFO_SIZE);
+ pdata->rx_max_fifo_size *= 16384;
+ pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size,
+ pdata->vdata->rx_max_fifo_size);
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "max tx/rx max fifo size = %u/%u\n",
+ pdata->tx_max_fifo_size, pdata->rx_max_fifo_size);
+
+ /* Configure interrupt support */
+ ret = xgbe_config_irqs(pdata);
+ if (ret)
+ goto err_pci_enable;
+
+ /* Configure the netdev resource */
+ ret = xgbe_config_netdev(pdata);
+ if (ret)
+ goto err_pci_enable;
+
+ netdev_notice(pdata->netdev, "net device enabled\n");
+
+ return 0;
+
+err_pci_enable:
+ xgbe_free_pdata(pdata);
+
+err_alloc:
+ dev_notice(dev, "net device not enabled\n");
+
+ return ret;
+}
+
+static void xgbe_pci_remove(struct pci_dev *pdev)
+{
+ struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+
+ xgbe_deconfig_netdev(pdata);
+
+ xgbe_free_pdata(pdata);
+}
+
+#ifdef CONFIG_PM
+static int xgbe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+ struct net_device *netdev = pdata->netdev;
+ int ret = 0;
+
+ if (netif_running(netdev))
+ ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+
+ pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+ return ret;
+}
+
+static int xgbe_pci_resume(struct pci_dev *pdev)
+{
+ struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+ struct net_device *netdev = pdata->netdev;
+ int ret = 0;
+
+ pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+ if (netif_running(netdev)) {
+ ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
+
+ /* Schedule a restart in case the link or phy state changed
+ * while we were powered down.
+ */
+ schedule_work(&pdata->restart_work);
+ }
+
+ return ret;
+}
+#endif /* CONFIG_PM */
+
+static const struct xgbe_version_data xgbe_v2a = {
+ .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v2,
+ .xpcs_access = XGBE_XPCS_ACCESS_V2,
+ .mmc_64bit = 1,
+ .tx_max_fifo_size = 229376,
+ .rx_max_fifo_size = 229376,
+ .tx_tstamp_workaround = 1,
+ .ecc_support = 1,
+ .i2c_support = 1,
+};
+
+static const struct xgbe_version_data xgbe_v2b = {
+ .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v2,
+ .xpcs_access = XGBE_XPCS_ACCESS_V2,
+ .mmc_64bit = 1,
+ .tx_max_fifo_size = 65536,
+ .rx_max_fifo_size = 65536,
+ .tx_tstamp_workaround = 1,
+ .ecc_support = 1,
+ .i2c_support = 1,
+};
+
+static const struct pci_device_id xgbe_pci_table[] = {
+ { PCI_VDEVICE(AMD, 0x1458),
+ .driver_data = (kernel_ulong_t)&xgbe_v2a },
+ { PCI_VDEVICE(AMD, 0x1459),
+ .driver_data = (kernel_ulong_t)&xgbe_v2b },
+ /* Last entry must be zero */
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, xgbe_pci_table);
+
+static struct pci_driver xgbe_driver = {
+ .name = XGBE_DRV_NAME,
+ .id_table = xgbe_pci_table,
+ .probe = xgbe_pci_probe,
+ .remove = xgbe_pci_remove,
+#ifdef CONFIG_PM
+ .suspend = xgbe_pci_suspend,
+ .resume = xgbe_pci_resume,
+#endif
+};
+
+int xgbe_pci_init(void)
+{
+ return pci_register_driver(&xgbe_driver);
+}
+
+void xgbe_pci_exit(void)
+{
+ pci_unregister_driver(&xgbe_driver);
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
new file mode 100644
index 000000000000..c75edcac5e0a
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
@@ -0,0 +1,845 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * 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 of Advanced Micro Devices, Inc. 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 <COPYRIGHT HOLDER> 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.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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/module.h>
+#include <linux/kmod.h>
+#include <linux/device.h>
+#include <linux/property.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_BLWC_PROPERTY "amd,serdes-blwc"
+#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate"
+#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
+#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp"
+#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
+#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
+
+/* Default SerDes settings */
+#define XGBE_SPEED_1000_BLWC 1
+#define XGBE_SPEED_1000_CDR 0x2
+#define XGBE_SPEED_1000_PLL 0x0
+#define XGBE_SPEED_1000_PQ 0xa
+#define XGBE_SPEED_1000_RATE 0x3
+#define XGBE_SPEED_1000_TXAMP 0xf
+#define XGBE_SPEED_1000_WORD 0x1
+#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3
+#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0
+
+#define XGBE_SPEED_2500_BLWC 1
+#define XGBE_SPEED_2500_CDR 0x2
+#define XGBE_SPEED_2500_PLL 0x0
+#define XGBE_SPEED_2500_PQ 0xa
+#define XGBE_SPEED_2500_RATE 0x1
+#define XGBE_SPEED_2500_TXAMP 0xf
+#define XGBE_SPEED_2500_WORD 0x1
+#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3
+#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0
+
+#define XGBE_SPEED_10000_BLWC 0
+#define XGBE_SPEED_10000_CDR 0x7
+#define XGBE_SPEED_10000_PLL 0x1
+#define XGBE_SPEED_10000_PQ 0x12
+#define XGBE_SPEED_10000_RATE 0x0
+#define XGBE_SPEED_10000_TXAMP 0xa
+#define XGBE_SPEED_10000_WORD 0x7
+#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1
+#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f
+
+/* Rate-change complete wait/retry count */
+#define XGBE_RATECHANGE_COUNT 500
+
+static const u32 xgbe_phy_blwc[] = {
+ XGBE_SPEED_1000_BLWC,
+ XGBE_SPEED_2500_BLWC,
+ XGBE_SPEED_10000_BLWC,
+};
+
+static const u32 xgbe_phy_cdr_rate[] = {
+ XGBE_SPEED_1000_CDR,
+ XGBE_SPEED_2500_CDR,
+ XGBE_SPEED_10000_CDR,
+};
+
+static const u32 xgbe_phy_pq_skew[] = {
+ XGBE_SPEED_1000_PQ,
+ XGBE_SPEED_2500_PQ,
+ XGBE_SPEED_10000_PQ,
+};
+
+static const u32 xgbe_phy_tx_amp[] = {
+ XGBE_SPEED_1000_TXAMP,
+ XGBE_SPEED_2500_TXAMP,
+ XGBE_SPEED_10000_TXAMP,
+};
+
+static const u32 xgbe_phy_dfe_tap_cfg[] = {
+ XGBE_SPEED_1000_DFE_TAP_CONFIG,
+ XGBE_SPEED_2500_DFE_TAP_CONFIG,
+ XGBE_SPEED_10000_DFE_TAP_CONFIG,
+};
+
+static const u32 xgbe_phy_dfe_tap_ena[] = {
+ XGBE_SPEED_1000_DFE_TAP_ENABLE,
+ XGBE_SPEED_2500_DFE_TAP_ENABLE,
+ XGBE_SPEED_10000_DFE_TAP_ENABLE,
+};
+
+struct xgbe_phy_data {
+ /* 1000/10000 vs 2500/10000 indicator */
+ unsigned int speed_set;
+
+ /* SerDes UEFI configurable settings.
+ * Switching between modes/speeds requires new values for some
+ * SerDes settings. The values can be supplied as device
+ * properties in array format. The first array entry is for
+ * 1GbE, second for 2.5GbE and third for 10GbE
+ */
+ u32 blwc[XGBE_SPEEDS];
+ u32 cdr_rate[XGBE_SPEEDS];
+ u32 pq_skew[XGBE_SPEEDS];
+ u32 tx_amp[XGBE_SPEEDS];
+ u32 dfe_tap_cfg[XGBE_SPEEDS];
+ u32 dfe_tap_ena[XGBE_SPEEDS];
+};
+
+static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
+{
+ XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
+}
+
+static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
+{
+ XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
+}
+
+static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_mode mode;
+ unsigned int ad_reg, lp_reg;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+ /* Compare Advertisement and Link Partner register 1 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
+ if (lp_reg & 0x400)
+ pdata->phy.lp_advertising |= ADVERTISED_Pause;
+ if (lp_reg & 0x800)
+ pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+ if (pdata->phy.pause_autoneg) {
+ /* Set flow control based on auto-negotiation result */
+ pdata->phy.tx_pause = 0;
+ pdata->phy.rx_pause = 0;
+
+ if (ad_reg & lp_reg & 0x400) {
+ pdata->phy.tx_pause = 1;
+ pdata->phy.rx_pause = 1;
+ } else if (ad_reg & lp_reg & 0x800) {
+ if (ad_reg & 0x400)
+ pdata->phy.rx_pause = 1;
+ else if (lp_reg & 0x400)
+ pdata->phy.tx_pause = 1;
+ }
+ }
+
+ /* Compare Advertisement and Link Partner register 2 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+ if (lp_reg & 0x80)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+ if (lp_reg & 0x20) {
+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+ pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
+ else
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+ }
+
+ ad_reg &= lp_reg;
+ if (ad_reg & 0x80) {
+ mode = XGBE_MODE_KR;
+ } else if (ad_reg & 0x20) {
+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+ mode = XGBE_MODE_KX_2500;
+ else
+ mode = XGBE_MODE_KX_1000;
+ } else {
+ mode = XGBE_MODE_UNKNOWN;
+ }
+
+ /* Compare Advertisement and Link Partner register 3 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+ if (lp_reg & 0xc000)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+ return mode;
+}
+
+static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
+{
+ return pdata->phy.advertising;
+}
+
+static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
+{
+ /* Nothing uniquely required for an configuration */
+ return 0;
+}
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
+{
+ return XGBE_AN_MODE_CL73;
+}
+
+static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
+{
+ unsigned int reg;
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+
+ reg |= MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+ usleep_range(75, 100);
+
+ reg &= ~MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+}
+
+static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
+{
+ /* Assert Rx and Tx ratechange */
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
+}
+
+static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
+{
+ unsigned int wait;
+ u16 status;
+
+ /* Release Rx and Tx ratechange */
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
+
+ /* Wait for Rx and Tx ready */
+ wait = XGBE_RATECHANGE_COUNT;
+ while (wait--) {
+ usleep_range(50, 75);
+
+ status = XSIR0_IOREAD(pdata, SIR0_STATUS);
+ if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+ XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
+ goto rx_reset;
+ }
+
+ netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
+ status);
+
+rx_reset:
+ /* Perform Rx reset for the DFE changes */
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
+}
+
+static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+
+ /* Set PCS to KR/10G speed */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+ reg &= ~MDIO_PCS_CTRL2_TYPE;
+ reg |= MDIO_PCS_CTRL2_10GBR;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_CTRL1_SPEEDSEL;
+ reg |= MDIO_CTRL1_SPEED10G;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+ xgbe_phy_pcs_power_cycle(pdata);
+
+ /* Set SerDes to 10G speed */
+ xgbe_phy_start_ratechange(pdata);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+ phy_data->cdr_rate[XGBE_SPEED_10000]);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+ phy_data->tx_amp[XGBE_SPEED_10000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+ phy_data->blwc[XGBE_SPEED_10000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+ phy_data->pq_skew[XGBE_SPEED_10000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+ phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
+ XRXTX_IOWRITE(pdata, RXTX_REG22,
+ phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+}
+
+static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+
+ /* Set PCS to KX/1G speed */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+ reg &= ~MDIO_PCS_CTRL2_TYPE;
+ reg |= MDIO_PCS_CTRL2_10GBX;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_CTRL1_SPEEDSEL;
+ reg |= MDIO_CTRL1_SPEED1G;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+ xgbe_phy_pcs_power_cycle(pdata);
+
+ /* Set SerDes to 2.5G speed */
+ xgbe_phy_start_ratechange(pdata);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+ phy_data->cdr_rate[XGBE_SPEED_2500]);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+ phy_data->tx_amp[XGBE_SPEED_2500]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+ phy_data->blwc[XGBE_SPEED_2500]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+ phy_data->pq_skew[XGBE_SPEED_2500]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+ phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
+ XRXTX_IOWRITE(pdata, RXTX_REG22,
+ phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+}
+
+static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+
+ /* Set PCS to KX/1G speed */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+ reg &= ~MDIO_PCS_CTRL2_TYPE;
+ reg |= MDIO_PCS_CTRL2_10GBX;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_CTRL1_SPEEDSEL;
+ reg |= MDIO_CTRL1_SPEED1G;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+ xgbe_phy_pcs_power_cycle(pdata);
+
+ /* Set SerDes to 1G speed */
+ xgbe_phy_start_ratechange(pdata);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
+
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+ phy_data->cdr_rate[XGBE_SPEED_1000]);
+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+ phy_data->tx_amp[XGBE_SPEED_1000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+ phy_data->blwc[XGBE_SPEED_1000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+ phy_data->pq_skew[XGBE_SPEED_1000]);
+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+ phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
+ XRXTX_IOWRITE(pdata, RXTX_REG22,
+ phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+}
+
+static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_mode mode;
+ unsigned int reg;
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+ reg &= MDIO_PCS_CTRL2_TYPE;
+
+ if (reg == MDIO_PCS_CTRL2_10GBR) {
+ mode = XGBE_MODE_KR;
+ } else {
+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+ mode = XGBE_MODE_KX_2500;
+ else
+ mode = XGBE_MODE_KX_1000;
+ }
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_mode mode;
+
+ /* If we are in KR switch to KX, and vice-versa */
+ if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+ mode = XGBE_MODE_KX_2500;
+ else
+ mode = XGBE_MODE_KX_1000;
+ } else {
+ mode = XGBE_MODE_KR;
+ }
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
+ int speed)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (speed) {
+ case SPEED_1000:
+ return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
+ ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
+ case SPEED_2500:
+ return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+ ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
+ case SPEED_10000:
+ return XGBE_MODE_KR;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ xgbe_phy_kx_1000_mode(pdata);
+ break;
+ case XGBE_MODE_KX_2500:
+ xgbe_phy_kx_2500_mode(pdata);
+ break;
+ case XGBE_MODE_KR:
+ xgbe_phy_kr_mode(pdata);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode, u32 advert)
+{
+ if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+ if (pdata->phy.advertising & advert)
+ return true;
+ } else {
+ enum xgbe_mode cur_mode;
+
+ cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
+ if (cur_mode == mode)
+ return true;
+ }
+
+ return false;
+}
+
+static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseKX_Full);
+ case XGBE_MODE_KX_2500:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_2500baseX_Full);
+ case XGBE_MODE_KR:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_10000baseKR_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (speed) {
+ case SPEED_1000:
+ if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
+ return false;
+ return true;
+ case SPEED_2500:
+ if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
+ return false;
+ return true;
+ case SPEED_10000:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
+{
+ unsigned int reg;
+
+ *an_restart = 0;
+
+ /* Link status is latched low, so read once to clear
+ * and then read again to get current state
+ */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+
+ return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
+}
+
+static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
+{
+ /* Nothing uniquely required for stop */
+}
+
+static int xgbe_phy_start(struct xgbe_prv_data *pdata)
+{
+ /* Nothing uniquely required for start */
+ return 0;
+}
+
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+{
+ unsigned int reg, count;
+
+ /* Perform a software reset of the PCS */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg |= MDIO_CTRL1_RESET;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+ count = 50;
+ do {
+ msleep(20);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ } while ((reg & MDIO_CTRL1_RESET) && --count);
+
+ if (reg & MDIO_CTRL1_RESET)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+ /* Nothing uniquely required for exit */
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data;
+ int ret;
+
+ phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
+ if (!phy_data)
+ return -ENOMEM;
+
+ /* Retrieve the PHY speedset */
+ ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
+ &phy_data->speed_set);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_SPEEDSET_PROPERTY);
+ return ret;
+ }
+
+ switch (phy_data->speed_set) {
+ case XGBE_SPEEDSET_1000_10000:
+ case XGBE_SPEEDSET_2500_10000:
+ break;
+ default:
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_SPEEDSET_PROPERTY);
+ return -EINVAL;
+ }
+
+ /* Retrieve the PHY configuration properties */
+ if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_BLWC_PROPERTY,
+ phy_data->blwc,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_BLWC_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->blwc, xgbe_phy_blwc,
+ sizeof(phy_data->blwc));
+ }
+
+ if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_CDR_RATE_PROPERTY,
+ phy_data->cdr_rate,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_CDR_RATE_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
+ sizeof(phy_data->cdr_rate));
+ }
+
+ if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_PQ_SKEW_PROPERTY,
+ phy_data->pq_skew,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_PQ_SKEW_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
+ sizeof(phy_data->pq_skew));
+ }
+
+ if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_TX_AMP_PROPERTY,
+ phy_data->tx_amp,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_TX_AMP_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
+ sizeof(phy_data->tx_amp));
+ }
+
+ if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_DFE_CFG_PROPERTY,
+ phy_data->dfe_tap_cfg,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_DFE_CFG_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
+ sizeof(phy_data->dfe_tap_cfg));
+ }
+
+ if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
+ ret = device_property_read_u32_array(pdata->phy_dev,
+ XGBE_DFE_ENA_PROPERTY,
+ phy_data->dfe_tap_ena,
+ XGBE_SPEEDS);
+ if (ret) {
+ dev_err(pdata->dev, "invalid %s property\n",
+ XGBE_DFE_ENA_PROPERTY);
+ return ret;
+ }
+ } else {
+ memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
+ sizeof(phy_data->dfe_tap_ena));
+ }
+
+ /* Initialize supported features */
+ pdata->phy.supported = SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_Backplane;
+ pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
+ switch (phy_data->speed_set) {
+ case XGBE_SPEEDSET_1000_10000:
+ pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
+ break;
+ case XGBE_SPEEDSET_2500_10000:
+ pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+ break;
+ }
+
+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+ pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
+
+ pdata->phy_data = phy_data;
+
+ return 0;
+}
+
+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
+{
+ struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
+
+ phy_impl->init = xgbe_phy_init;
+ phy_impl->exit = xgbe_phy_exit;
+
+ phy_impl->reset = xgbe_phy_reset;
+ phy_impl->start = xgbe_phy_start;
+ phy_impl->stop = xgbe_phy_stop;
+
+ phy_impl->link_status = xgbe_phy_link_status;
+
+ phy_impl->valid_speed = xgbe_phy_valid_speed;
+
+ phy_impl->use_mode = xgbe_phy_use_mode;
+ phy_impl->set_mode = xgbe_phy_set_mode;
+ phy_impl->get_mode = xgbe_phy_get_mode;
+ phy_impl->switch_mode = xgbe_phy_switch_mode;
+ phy_impl->cur_mode = xgbe_phy_cur_mode;
+
+ phy_impl->an_mode = xgbe_phy_an_mode;
+
+ phy_impl->an_config = xgbe_phy_an_config;
+
+ phy_impl->an_advertising = xgbe_phy_an_advertising;
+
+ phy_impl->an_outcome = xgbe_phy_an_outcome;
+
+ phy_impl->kr_training_pre = xgbe_phy_kr_training_pre;
+ phy_impl->kr_training_post = xgbe_phy_kr_training_post;
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
new file mode 100644
index 000000000000..9d8c953083b4
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -0,0 +1,3084 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * 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 of Advanced Micro Devices, Inc. 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 <COPYRIGHT HOLDER> 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.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/kmod.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_PHY_PORT_SPEED_100 BIT(0)
+#define XGBE_PHY_PORT_SPEED_1000 BIT(1)
+#define XGBE_PHY_PORT_SPEED_2500 BIT(2)
+#define XGBE_PHY_PORT_SPEED_10000 BIT(3)
+
+#define XGBE_MUTEX_RELEASE 0x80000000
+
+#define XGBE_SFP_DIRECT 7
+
+/* I2C target addresses */
+#define XGBE_SFP_SERIAL_ID_ADDRESS 0x50
+#define XGBE_SFP_DIAG_INFO_ADDRESS 0x51
+#define XGBE_SFP_PHY_ADDRESS 0x56
+#define XGBE_GPIO_ADDRESS_PCA9555 0x20
+
+/* SFP sideband signal indicators */
+#define XGBE_GPIO_NO_TX_FAULT BIT(0)
+#define XGBE_GPIO_NO_RATE_SELECT BIT(1)
+#define XGBE_GPIO_NO_MOD_ABSENT BIT(2)
+#define XGBE_GPIO_NO_RX_LOS BIT(3)
+
+/* Rate-change complete wait/retry count */
+#define XGBE_RATECHANGE_COUNT 500
+
+enum xgbe_port_mode {
+ XGBE_PORT_MODE_RSVD = 0,
+ XGBE_PORT_MODE_BACKPLANE,
+ XGBE_PORT_MODE_BACKPLANE_2500,
+ XGBE_PORT_MODE_1000BASE_T,
+ XGBE_PORT_MODE_1000BASE_X,
+ XGBE_PORT_MODE_NBASE_T,
+ XGBE_PORT_MODE_10GBASE_T,
+ XGBE_PORT_MODE_10GBASE_R,
+ XGBE_PORT_MODE_SFP,
+ XGBE_PORT_MODE_MAX,
+};
+
+enum xgbe_conn_type {
+ XGBE_CONN_TYPE_NONE = 0,
+ XGBE_CONN_TYPE_SFP,
+ XGBE_CONN_TYPE_MDIO,
+ XGBE_CONN_TYPE_RSVD1,
+ XGBE_CONN_TYPE_BACKPLANE,
+ XGBE_CONN_TYPE_MAX,
+};
+
+/* SFP/SFP+ related definitions */
+enum xgbe_sfp_comm {
+ XGBE_SFP_COMM_DIRECT = 0,
+ XGBE_SFP_COMM_PCA9545,
+};
+
+enum xgbe_sfp_cable {
+ XGBE_SFP_CABLE_UNKNOWN = 0,
+ XGBE_SFP_CABLE_ACTIVE,
+ XGBE_SFP_CABLE_PASSIVE,
+};
+
+enum xgbe_sfp_base {
+ XGBE_SFP_BASE_UNKNOWN = 0,
+ XGBE_SFP_BASE_1000_T,
+ XGBE_SFP_BASE_1000_SX,
+ XGBE_SFP_BASE_1000_LX,
+ XGBE_SFP_BASE_1000_CX,
+ XGBE_SFP_BASE_10000_SR,
+ XGBE_SFP_BASE_10000_LR,
+ XGBE_SFP_BASE_10000_LRM,
+ XGBE_SFP_BASE_10000_ER,
+ XGBE_SFP_BASE_10000_CR,
+};
+
+enum xgbe_sfp_speed {
+ XGBE_SFP_SPEED_UNKNOWN = 0,
+ XGBE_SFP_SPEED_100_1000,
+ XGBE_SFP_SPEED_1000,
+ XGBE_SFP_SPEED_10000,
+};
+
+/* SFP Serial ID Base ID values relative to an offset of 0 */
+#define XGBE_SFP_BASE_ID 0
+#define XGBE_SFP_ID_SFP 0x03
+
+#define XGBE_SFP_BASE_EXT_ID 1
+#define XGBE_SFP_EXT_ID_SFP 0x04
+
+#define XGBE_SFP_BASE_10GBE_CC 3
+#define XGBE_SFP_BASE_10GBE_CC_SR BIT(4)
+#define XGBE_SFP_BASE_10GBE_CC_LR BIT(5)
+#define XGBE_SFP_BASE_10GBE_CC_LRM BIT(6)
+#define XGBE_SFP_BASE_10GBE_CC_ER BIT(7)
+
+#define XGBE_SFP_BASE_1GBE_CC 6
+#define XGBE_SFP_BASE_1GBE_CC_SX BIT(0)
+#define XGBE_SFP_BASE_1GBE_CC_LX BIT(1)
+#define XGBE_SFP_BASE_1GBE_CC_CX BIT(2)
+#define XGBE_SFP_BASE_1GBE_CC_T BIT(3)
+
+#define XGBE_SFP_BASE_CABLE 8
+#define XGBE_SFP_BASE_CABLE_PASSIVE BIT(2)
+#define XGBE_SFP_BASE_CABLE_ACTIVE BIT(3)
+
+#define XGBE_SFP_BASE_BR 12
+#define XGBE_SFP_BASE_BR_1GBE_MIN 0x0a
+#define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d
+#define XGBE_SFP_BASE_BR_10GBE_MIN 0x64
+#define XGBE_SFP_BASE_BR_10GBE_MAX 0x68
+
+#define XGBE_SFP_BASE_CU_CABLE_LEN 18
+
+#define XGBE_SFP_BASE_VENDOR_NAME 20
+#define XGBE_SFP_BASE_VENDOR_NAME_LEN 16
+#define XGBE_SFP_BASE_VENDOR_PN 40
+#define XGBE_SFP_BASE_VENDOR_PN_LEN 16
+#define XGBE_SFP_BASE_VENDOR_REV 56
+#define XGBE_SFP_BASE_VENDOR_REV_LEN 4
+
+#define XGBE_SFP_BASE_CC 63
+
+/* SFP Serial ID Extended ID values relative to an offset of 64 */
+#define XGBE_SFP_BASE_VENDOR_SN 4
+#define XGBE_SFP_BASE_VENDOR_SN_LEN 16
+
+#define XGBE_SFP_EXTD_DIAG 28
+#define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2)
+
+#define XGBE_SFP_EXTD_SFF_8472 30
+
+#define XGBE_SFP_EXTD_CC 31
+
+struct xgbe_sfp_eeprom {
+ u8 base[64];
+ u8 extd[32];
+ u8 vendor[32];
+};
+
+#define XGBE_BEL_FUSE_VENDOR "BEL-FUSE "
+#define XGBE_BEL_FUSE_PARTNO "1GBT-SFP06 "
+
+struct xgbe_sfp_ascii {
+ union {
+ char vendor[XGBE_SFP_BASE_VENDOR_NAME_LEN + 1];
+ char partno[XGBE_SFP_BASE_VENDOR_PN_LEN + 1];
+ char rev[XGBE_SFP_BASE_VENDOR_REV_LEN + 1];
+ char serno[XGBE_SFP_BASE_VENDOR_SN_LEN + 1];
+ } u;
+};
+
+/* MDIO PHY reset types */
+enum xgbe_mdio_reset {
+ XGBE_MDIO_RESET_NONE = 0,
+ XGBE_MDIO_RESET_I2C_GPIO,
+ XGBE_MDIO_RESET_INT_GPIO,
+ XGBE_MDIO_RESET_MAX,
+};
+
+/* Re-driver related definitions */
+enum xgbe_phy_redrv_if {
+ XGBE_PHY_REDRV_IF_MDIO = 0,
+ XGBE_PHY_REDRV_IF_I2C,
+ XGBE_PHY_REDRV_IF_MAX,
+};
+
+enum xgbe_phy_redrv_model {
+ XGBE_PHY_REDRV_MODEL_4223 = 0,
+ XGBE_PHY_REDRV_MODEL_4227,
+ XGBE_PHY_REDRV_MODEL_MAX,
+};
+
+enum xgbe_phy_redrv_mode {
+ XGBE_PHY_REDRV_MODE_CX = 5,
+ XGBE_PHY_REDRV_MODE_SR = 9,
+};
+
+#define XGBE_PHY_REDRV_MODE_REG 0x12b0
+
+/* PHY related configuration information */
+struct xgbe_phy_data {
+ enum xgbe_port_mode port_mode;
+
+ unsigned int port_id;
+
+ unsigned int port_speeds;
+
+ enum xgbe_conn_type conn_type;
+
+ enum xgbe_mode cur_mode;
+ enum xgbe_mode start_mode;
+
+ unsigned int rrc_count;
+
+ unsigned int mdio_addr;
+
+ unsigned int comm_owned;
+
+ /* SFP Support */
+ enum xgbe_sfp_comm sfp_comm;
+ unsigned int sfp_mux_address;
+ unsigned int sfp_mux_channel;
+
+ unsigned int sfp_gpio_address;
+ unsigned int sfp_gpio_mask;
+ unsigned int sfp_gpio_rx_los;
+ unsigned int sfp_gpio_tx_fault;
+ unsigned int sfp_gpio_mod_absent;
+ unsigned int sfp_gpio_rate_select;
+
+ unsigned int sfp_rx_los;
+ unsigned int sfp_tx_fault;
+ unsigned int sfp_mod_absent;
+ unsigned int sfp_diags;
+ unsigned int sfp_changed;
+ unsigned int sfp_phy_avail;
+ unsigned int sfp_cable_len;
+ enum xgbe_sfp_base sfp_base;
+ enum xgbe_sfp_cable sfp_cable;
+ enum xgbe_sfp_speed sfp_speed;
+ struct xgbe_sfp_eeprom sfp_eeprom;
+
+ /* External PHY support */
+ enum xgbe_mdio_mode phydev_mode;
+ struct mii_bus *mii;
+ struct phy_device *phydev;
+ enum xgbe_mdio_reset mdio_reset;
+ unsigned int mdio_reset_addr;
+ unsigned int mdio_reset_gpio;
+
+ /* Re-driver support */
+ unsigned int redrv;
+ unsigned int redrv_if;
+ unsigned int redrv_addr;
+ unsigned int redrv_lane;
+ unsigned int redrv_model;
+};
+
+/* I2C, MDIO and GPIO lines are muxed, so only one device at a time */
+static DEFINE_MUTEX(xgbe_phy_comm_lock);
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata);
+
+static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata,
+ struct xgbe_i2c_op *i2c_op)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ /* Be sure we own the bus */
+ if (WARN_ON(!phy_data->comm_owned))
+ return -EIO;
+
+ return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
+}
+
+static int xgbe_phy_redrv_write(struct xgbe_prv_data *pdata, unsigned int reg,
+ unsigned int val)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_i2c_op i2c_op;
+ __be16 *redrv_val;
+ u8 redrv_data[5], csum;
+ unsigned int i, retry;
+ int ret;
+
+ /* High byte of register contains read/write indicator */
+ redrv_data[0] = ((reg >> 8) & 0xff) << 1;
+ redrv_data[1] = reg & 0xff;
+ redrv_val = (__be16 *)&redrv_data[2];
+ *redrv_val = cpu_to_be16(val);
+
+ /* Calculate 1 byte checksum */
+ csum = 0;
+ for (i = 0; i < 4; i++) {
+ csum += redrv_data[i];
+ if (redrv_data[i] > csum)
+ csum++;
+ }
+ redrv_data[4] = ~csum;
+
+ retry = 1;
+again1:
+ i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+ i2c_op.target = phy_data->redrv_addr;
+ i2c_op.len = sizeof(redrv_data);
+ i2c_op.buf = redrv_data;
+ ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+ if (ret) {
+ if ((ret == -EAGAIN) && retry--)
+ goto again1;
+
+ return ret;
+ }
+
+ retry = 1;
+again2:
+ i2c_op.cmd = XGBE_I2C_CMD_READ;
+ i2c_op.target = phy_data->redrv_addr;
+ i2c_op.len = 1;
+ i2c_op.buf = redrv_data;
+ ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+ if (ret) {
+ if ((ret == -EAGAIN) && retry--)
+ goto again2;
+
+ return ret;
+ }
+
+ if (redrv_data[0] != 0xff) {
+ netif_dbg(pdata, drv, pdata->netdev,
+ "Redriver write checksum error\n");
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int xgbe_phy_i2c_write(struct xgbe_prv_data *pdata, unsigned int target,
+ void *val, unsigned int val_len)
+{
+ struct xgbe_i2c_op i2c_op;
+ int retry, ret;
+
+ retry = 1;
+again:
+ /* Write the specfied register */
+ i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+ i2c_op.target = target;
+ i2c_op.len = val_len;
+ i2c_op.buf = val;
+ ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+ if ((ret == -EAGAIN) && retry--)
+ goto again;
+
+ return ret;
+}
+
+static int xgbe_phy_i2c_read(struct xgbe_prv_data *pdata, unsigned int target,
+ void *reg, unsigned int reg_len,
+ void *val, unsigned int val_len)
+{
+ struct xgbe_i2c_op i2c_op;
+ int retry, ret;
+
+ retry = 1;
+again1:
+ /* Set the specified register to read */
+ i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+ i2c_op.target = target;
+ i2c_op.len = reg_len;
+ i2c_op.buf = reg;
+ ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+ if (ret) {
+ if ((ret == -EAGAIN) && retry--)
+ goto again1;
+
+ return ret;
+ }
+
+ retry = 1;
+again2:
+ /* Read the specfied register */
+ i2c_op.cmd = XGBE_I2C_CMD_READ;
+ i2c_op.target = target;
+ i2c_op.len = val_len;
+ i2c_op.buf = val;
+ ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+ if ((ret == -EAGAIN) && retry--)
+ goto again2;
+
+ return ret;
+}
+
+static int xgbe_phy_sfp_put_mux(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_i2c_op i2c_op;
+ u8 mux_channel;
+
+ if (phy_data->sfp_comm == XGBE_SFP_COMM_DIRECT)
+ return 0;
+
+ /* Select no mux channels */
+ mux_channel = 0;
+ i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+ i2c_op.target = phy_data->sfp_mux_address;
+ i2c_op.len = sizeof(mux_channel);
+ i2c_op.buf = &mux_channel;
+
+ return xgbe_phy_i2c_xfer(pdata, &i2c_op);
+}
+
+static int xgbe_phy_sfp_get_mux(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_i2c_op i2c_op;
+ u8 mux_channel;
+
+ if (phy_data->sfp_comm == XGBE_SFP_COMM_DIRECT)
+ return 0;
+
+ /* Select desired mux channel */
+ mux_channel = 1 << phy_data->sfp_mux_channel;
+ i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+ i2c_op.target = phy_data->sfp_mux_address;
+ i2c_op.len = sizeof(mux_channel);
+ i2c_op.buf = &mux_channel;
+
+ return xgbe_phy_i2c_xfer(pdata, &i2c_op);
+}
+
+static void xgbe_phy_put_comm_ownership(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ phy_data->comm_owned = 0;
+
+ mutex_unlock(&xgbe_phy_comm_lock);
+}
+
+static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned long timeout;
+ unsigned int mutex_id;
+
+ if (phy_data->comm_owned)
+ return 0;
+
+ /* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
+ * the driver needs to take the software mutex and then the hardware
+ * mutexes before being able to use the busses.
+ */
+ mutex_lock(&xgbe_phy_comm_lock);
+
+ /* Clear the mutexes */
+ XP_IOWRITE(pdata, XP_I2C_MUTEX, XGBE_MUTEX_RELEASE);
+ XP_IOWRITE(pdata, XP_MDIO_MUTEX, XGBE_MUTEX_RELEASE);
+
+ /* Mutex formats are the same for I2C and MDIO/GPIO */
+ mutex_id = 0;
+ XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id);
+ XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1);
+
+ timeout = jiffies + (5 * HZ);
+ while (time_before(jiffies, timeout)) {
+ /* Must be all zeroes in order to obtain the mutex */
+ if (XP_IOREAD(pdata, XP_I2C_MUTEX) ||
+ XP_IOREAD(pdata, XP_MDIO_MUTEX)) {
+ usleep_range(100, 200);
+ continue;
+ }
+
+ /* Obtain the mutex */
+ XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
+ XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
+
+ phy_data->comm_owned = 1;
+ return 0;
+ }
+
+ mutex_unlock(&xgbe_phy_comm_lock);
+
+ netdev_err(pdata->netdev, "unable to obtain hardware mutexes\n");
+
+ return -ETIMEDOUT;
+}
+
+static int xgbe_phy_mdio_mii_write(struct xgbe_prv_data *pdata, int addr,
+ int reg, u16 val)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ if (reg & MII_ADDR_C45) {
+ if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
+ return -ENOTSUPP;
+ } else {
+ if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
+ return -ENOTSUPP;
+ }
+
+ return pdata->hw_if.write_ext_mii_regs(pdata, addr, reg, val);
+}
+
+static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val)
+{
+ __be16 *mii_val;
+ u8 mii_data[3];
+ int ret;
+
+ ret = xgbe_phy_sfp_get_mux(pdata);
+ if (ret)
+ return ret;
+
+ mii_data[0] = reg & 0xff;
+ mii_val = (__be16 *)&mii_data[1];
+ *mii_val = cpu_to_be16(val);
+
+ ret = xgbe_phy_i2c_write(pdata, XGBE_SFP_PHY_ADDRESS,
+ mii_data, sizeof(mii_data));
+
+ xgbe_phy_sfp_put_mux(pdata);
+
+ return ret;
+}
+
+static int xgbe_phy_mii_write(struct mii_bus *mii, int addr, int reg, u16 val)
+{
+ struct xgbe_prv_data *pdata = mii->priv;
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ ret = xgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return ret;
+
+ if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+ ret = xgbe_phy_i2c_mii_write(pdata, reg, val);
+ else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
+ ret = xgbe_phy_mdio_mii_write(pdata, addr, reg, val);
+ else
+ ret = -ENOTSUPP;
+
+ xgbe_phy_put_comm_ownership(pdata);
+
+ return ret;
+}
+
+static int xgbe_phy_mdio_mii_read(struct xgbe_prv_data *pdata, int addr,
+ int reg)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ if (reg & MII_ADDR_C45) {
+ if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
+ return -ENOTSUPP;
+ } else {
+ if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
+ return -ENOTSUPP;
+ }
+
+ return pdata->hw_if.read_ext_mii_regs(pdata, addr, reg);
+}
+
+static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg)
+{
+ __be16 mii_val;
+ u8 mii_reg;
+ int ret;
+
+ ret = xgbe_phy_sfp_get_mux(pdata);
+ if (ret)
+ return ret;
+
+ mii_reg = reg;
+ ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_PHY_ADDRESS,
+ &mii_reg, sizeof(mii_reg),
+ &mii_val, sizeof(mii_val));
+ if (!ret)
+ ret = be16_to_cpu(mii_val);
+
+ xgbe_phy_sfp_put_mux(pdata);
+
+ return ret;
+}
+
+static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg)
+{
+ struct xgbe_prv_data *pdata = mii->priv;
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ ret = xgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return ret;
+
+ if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+ ret = xgbe_phy_i2c_mii_read(pdata, reg);
+ else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
+ ret = xgbe_phy_mdio_mii_read(pdata, addr, reg);
+ else
+ ret = -ENOTSUPP;
+
+ xgbe_phy_put_comm_ownership(pdata);
+
+ return ret;
+}
+
+static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ if (phy_data->sfp_mod_absent) {
+ pdata->phy.speed = SPEED_UNKNOWN;
+ pdata->phy.duplex = DUPLEX_UNKNOWN;
+ pdata->phy.autoneg = AUTONEG_ENABLE;
+ pdata->phy.advertising = pdata->phy.supported;
+ }
+
+ pdata->phy.advertising &= ~ADVERTISED_Autoneg;
+ pdata->phy.advertising &= ~ADVERTISED_TP;
+ pdata->phy.advertising &= ~ADVERTISED_FIBRE;
+ pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
+ pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
+ pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full;
+ pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC;
+
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ case XGBE_SFP_BASE_1000_SX:
+ case XGBE_SFP_BASE_1000_LX:
+ case XGBE_SFP_BASE_1000_CX:
+ pdata->phy.speed = SPEED_UNKNOWN;
+ pdata->phy.duplex = DUPLEX_UNKNOWN;
+ pdata->phy.autoneg = AUTONEG_ENABLE;
+ pdata->phy.advertising |= ADVERTISED_Autoneg;
+ break;
+ case XGBE_SFP_BASE_10000_SR:
+ case XGBE_SFP_BASE_10000_LR:
+ case XGBE_SFP_BASE_10000_LRM:
+ case XGBE_SFP_BASE_10000_ER:
+ case XGBE_SFP_BASE_10000_CR:
+ default:
+ pdata->phy.speed = SPEED_10000;
+ pdata->phy.duplex = DUPLEX_FULL;
+ pdata->phy.autoneg = AUTONEG_DISABLE;
+ break;
+ }
+
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ case XGBE_SFP_BASE_1000_CX:
+ case XGBE_SFP_BASE_10000_CR:
+ pdata->phy.advertising |= ADVERTISED_TP;
+ break;
+ default:
+ pdata->phy.advertising |= ADVERTISED_FIBRE;
+ }
+
+ switch (phy_data->sfp_speed) {
+ case XGBE_SFP_SPEED_100_1000:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+ pdata->phy.advertising |= ADVERTISED_100baseT_Full;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+ pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+ break;
+ case XGBE_SFP_SPEED_1000:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+ pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+ break;
+ case XGBE_SFP_SPEED_10000:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+ pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
+ break;
+ default:
+ /* Choose the fastest supported speed */
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+ pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
+ else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+ pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+ else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+ pdata->phy.advertising |= ADVERTISED_100baseT_Full;
+ }
+}
+
+static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
+ enum xgbe_sfp_speed sfp_speed)
+{
+ u8 *sfp_base, min, max;
+
+ sfp_base = sfp_eeprom->base;
+
+ switch (sfp_speed) {
+ case XGBE_SFP_SPEED_1000:
+ min = XGBE_SFP_BASE_BR_1GBE_MIN;
+ max = XGBE_SFP_BASE_BR_1GBE_MAX;
+ break;
+ case XGBE_SFP_SPEED_10000:
+ min = XGBE_SFP_BASE_BR_10GBE_MIN;
+ max = XGBE_SFP_BASE_BR_10GBE_MAX;
+ break;
+ default:
+ return false;
+ }
+
+ return ((sfp_base[XGBE_SFP_BASE_BR] >= min) &&
+ (sfp_base[XGBE_SFP_BASE_BR] <= max));
+}
+
+static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ if (phy_data->phydev) {
+ phy_detach(phy_data->phydev);
+ phy_device_remove(phy_data->phydev);
+ phy_device_free(phy_data->phydev);
+ phy_data->phydev = NULL;
+ }
+}
+
+static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int phy_id = phy_data->phydev->phy_id;
+
+ if ((phy_id & 0xfffffff0) != 0x01ff0cc0)
+ return false;
+
+ /* Enable Base-T AN */
+ phy_write(phy_data->phydev, 0x16, 0x0001);
+ phy_write(phy_data->phydev, 0x00, 0x9140);
+ phy_write(phy_data->phydev, 0x16, 0x0000);
+
+ /* Enable SGMII at 100Base-T/1000Base-T Full Duplex */
+ phy_write(phy_data->phydev, 0x1b, 0x9084);
+ phy_write(phy_data->phydev, 0x09, 0x0e00);
+ phy_write(phy_data->phydev, 0x00, 0x8140);
+ phy_write(phy_data->phydev, 0x04, 0x0d01);
+ phy_write(phy_data->phydev, 0x00, 0x9140);
+
+ phy_data->phydev->supported = PHY_GBIT_FEATURES;
+ phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ phy_data->phydev->advertising = phy_data->phydev->supported;
+
+ netif_dbg(pdata, drv, pdata->netdev,
+ "Finisar PHY quirk in place\n");
+
+ return true;
+}
+
+static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
+{
+ if (xgbe_phy_finisar_phy_quirks(pdata))
+ return;
+}
+
+static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct phy_device *phydev;
+ int ret;
+
+ /* If we already have a PHY, just return */
+ if (phy_data->phydev)
+ return 0;
+
+ /* Check for the use of an external PHY */
+ if (phy_data->phydev_mode == XGBE_MDIO_MODE_NONE)
+ return 0;
+
+ /* For SFP, only use an external PHY if available */
+ if ((phy_data->port_mode == XGBE_PORT_MODE_SFP) &&
+ !phy_data->sfp_phy_avail)
+ return 0;
+
+ /* Create and connect to the PHY device */
+ phydev = get_phy_device(phy_data->mii, phy_data->mdio_addr,
+ (phy_data->phydev_mode == XGBE_MDIO_MODE_CL45));
+ if (IS_ERR(phydev)) {
+ netdev_err(pdata->netdev, "get_phy_device failed\n");
+ return -ENODEV;
+ }
+ netif_dbg(pdata, drv, pdata->netdev, "external PHY id is %#010x\n",
+ phydev->phy_id);
+
+ /*TODO: If c45, add request_module based on one of the MMD ids? */
+
+ ret = phy_device_register(phydev);
+ if (ret) {
+ netdev_err(pdata->netdev, "phy_device_register failed\n");
+ phy_device_free(phydev);
+ return ret;
+ }
+
+ ret = phy_attach_direct(pdata->netdev, phydev, phydev->dev_flags,
+ PHY_INTERFACE_MODE_SGMII);
+ if (ret) {
+ netdev_err(pdata->netdev, "phy_attach_direct failed\n");
+ phy_device_remove(phydev);
+ phy_device_free(phydev);
+ return ret;
+ }
+ phy_data->phydev = phydev;
+
+ xgbe_phy_external_phy_quirks(pdata);
+ phydev->advertising &= pdata->phy.advertising;
+
+ phy_start_aneg(phy_data->phydev);
+
+ return 0;
+}
+
+static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ if (!phy_data->sfp_changed)
+ return;
+
+ phy_data->sfp_phy_avail = 0;
+
+ if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+ return;
+
+ /* Check access to the PHY by reading CTRL1 */
+ ret = xgbe_phy_i2c_mii_read(pdata, MII_BMCR);
+ if (ret < 0)
+ return;
+
+ /* Successfully accessed the PHY */
+ phy_data->sfp_phy_avail = 1;
+}
+
+static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
+
+ if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+ XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
+ return false;
+
+ if (!memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+ XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) {
+ phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
+ phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
+ phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
+ if (phy_data->sfp_changed)
+ netif_dbg(pdata, drv, pdata->netdev,
+ "Bel-Fuse SFP quirk in place\n");
+ return true;
+ }
+
+ return false;
+}
+
+static bool xgbe_phy_sfp_parse_quirks(struct xgbe_prv_data *pdata)
+{
+ if (xgbe_phy_belfuse_parse_quirks(pdata))
+ return true;
+
+ return false;
+}
+
+static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
+ u8 *sfp_base;
+
+ sfp_base = sfp_eeprom->base;
+
+ if (sfp_base[XGBE_SFP_BASE_ID] != XGBE_SFP_ID_SFP)
+ return;
+
+ if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP)
+ return;
+
+ if (xgbe_phy_sfp_parse_quirks(pdata))
+ return;
+
+ /* Assume ACTIVE cable unless told it is PASSIVE */
+ if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) {
+ phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE;
+ phy_data->sfp_cable_len = sfp_base[XGBE_SFP_BASE_CU_CABLE_LEN];
+ } else {
+ phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
+ }
+
+ /* Determine the type of SFP */
+ if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
+ phy_data->sfp_base = XGBE_SFP_BASE_10000_SR;
+ else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR)
+ phy_data->sfp_base = XGBE_SFP_BASE_10000_LR;
+ else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LRM)
+ phy_data->sfp_base = XGBE_SFP_BASE_10000_LRM;
+ else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_ER)
+ phy_data->sfp_base = XGBE_SFP_BASE_10000_ER;
+ else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_SX)
+ phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
+ else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_LX)
+ phy_data->sfp_base = XGBE_SFP_BASE_1000_LX;
+ else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_CX)
+ phy_data->sfp_base = XGBE_SFP_BASE_1000_CX;
+ else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T)
+ phy_data->sfp_base = XGBE_SFP_BASE_1000_T;
+ else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) &&
+ xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
+ phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
+
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ phy_data->sfp_speed = XGBE_SFP_SPEED_100_1000;
+ break;
+ case XGBE_SFP_BASE_1000_SX:
+ case XGBE_SFP_BASE_1000_LX:
+ case XGBE_SFP_BASE_1000_CX:
+ phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
+ break;
+ case XGBE_SFP_BASE_10000_SR:
+ case XGBE_SFP_BASE_10000_LR:
+ case XGBE_SFP_BASE_10000_LRM:
+ case XGBE_SFP_BASE_10000_ER:
+ case XGBE_SFP_BASE_10000_CR:
+ phy_data->sfp_speed = XGBE_SFP_SPEED_10000;
+ break;
+ default:
+ break;
+ }
+}
+
+static void xgbe_phy_sfp_eeprom_info(struct xgbe_prv_data *pdata,
+ struct xgbe_sfp_eeprom *sfp_eeprom)
+{
+ struct xgbe_sfp_ascii sfp_ascii;
+ char *sfp_data = (char *)&sfp_ascii;
+
+ netif_dbg(pdata, drv, pdata->netdev, "SFP detected:\n");
+ memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+ XGBE_SFP_BASE_VENDOR_NAME_LEN);
+ sfp_data[XGBE_SFP_BASE_VENDOR_NAME_LEN] = '\0';
+ netif_dbg(pdata, drv, pdata->netdev, " vendor: %s\n",
+ sfp_data);
+
+ memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+ XGBE_SFP_BASE_VENDOR_PN_LEN);
+ sfp_data[XGBE_SFP_BASE_VENDOR_PN_LEN] = '\0';
+ netif_dbg(pdata, drv, pdata->netdev, " part number: %s\n",
+ sfp_data);
+
+ memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_REV],
+ XGBE_SFP_BASE_VENDOR_REV_LEN);
+ sfp_data[XGBE_SFP_BASE_VENDOR_REV_LEN] = '\0';
+ netif_dbg(pdata, drv, pdata->netdev, " revision level: %s\n",
+ sfp_data);
+
+ memcpy(sfp_data, &sfp_eeprom->extd[XGBE_SFP_BASE_VENDOR_SN],
+ XGBE_SFP_BASE_VENDOR_SN_LEN);
+ sfp_data[XGBE_SFP_BASE_VENDOR_SN_LEN] = '\0';
+ netif_dbg(pdata, drv, pdata->netdev, " serial number: %s\n",
+ sfp_data);
+}
+
+static bool xgbe_phy_sfp_verify_eeprom(u8 cc_in, u8 *buf, unsigned int len)
+{
+ u8 cc;
+
+ for (cc = 0; len; buf++, len--)
+ cc += *buf;
+
+ return (cc == cc_in) ? true : false;
+}
+
+static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct xgbe_sfp_eeprom sfp_eeprom;
+ u8 eeprom_addr;
+ int ret;
+
+ ret = xgbe_phy_sfp_get_mux(pdata);
+ if (ret) {
+ netdev_err(pdata->netdev, "I2C error setting SFP MUX\n");
+ return ret;
+ }
+
+ /* Read the SFP serial ID eeprom */
+ eeprom_addr = 0;
+ ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_SERIAL_ID_ADDRESS,
+ &eeprom_addr, sizeof(eeprom_addr),
+ &sfp_eeprom, sizeof(sfp_eeprom));
+ if (ret) {
+ netdev_err(pdata->netdev, "I2C error reading SFP EEPROM\n");
+ goto put;
+ }
+
+ /* Validate the contents read */
+ if (!xgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[XGBE_SFP_BASE_CC],
+ sfp_eeprom.base,
+ sizeof(sfp_eeprom.base) - 1)) {
+ ret = -EINVAL;
+ goto put;
+ }
+
+ if (!xgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[XGBE_SFP_EXTD_CC],
+ sfp_eeprom.extd,
+ sizeof(sfp_eeprom.extd) - 1)) {
+ ret = -EINVAL;
+ goto put;
+ }
+
+ /* Check for an added or changed SFP */
+ if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) {
+ phy_data->sfp_changed = 1;
+
+ if (netif_msg_drv(pdata))
+ xgbe_phy_sfp_eeprom_info(pdata, &sfp_eeprom);
+
+ memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom));
+
+ if (sfp_eeprom.extd[XGBE_SFP_EXTD_SFF_8472]) {
+ u8 diag_type = sfp_eeprom.extd[XGBE_SFP_EXTD_DIAG];
+
+ if (!(diag_type & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
+ phy_data->sfp_diags = 1;
+ }
+
+ xgbe_phy_free_phy_device(pdata);
+ } else {
+ phy_data->sfp_changed = 0;
+ }
+
+put:
+ xgbe_phy_sfp_put_mux(pdata);
+
+ return ret;
+}
+
+static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int gpio_input;
+ u8 gpio_reg, gpio_ports[2];
+ int ret;
+
+ /* Read the input port registers */
+ gpio_reg = 0;
+ ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address,
+ &gpio_reg, sizeof(gpio_reg),
+ gpio_ports, sizeof(gpio_ports));
+ if (ret) {
+ netdev_err(pdata->netdev, "I2C error reading SFP GPIOs\n");
+ return;
+ }
+
+ gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
+
+ if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) {
+ /* No GPIO, just assume the module is present for now */
+ phy_data->sfp_mod_absent = 0;
+ } else {
+ if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
+ phy_data->sfp_mod_absent = 0;
+ }
+
+ if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) &&
+ (gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
+ phy_data->sfp_rx_los = 1;
+
+ if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) &&
+ (gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
+ phy_data->sfp_tx_fault = 1;
+}
+
+static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ xgbe_phy_free_phy_device(pdata);
+
+ phy_data->sfp_mod_absent = 1;
+ phy_data->sfp_phy_avail = 0;
+ memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom));
+}
+
+static void xgbe_phy_sfp_reset(struct xgbe_phy_data *phy_data)
+{
+ phy_data->sfp_rx_los = 0;
+ phy_data->sfp_tx_fault = 0;
+ phy_data->sfp_mod_absent = 1;
+ phy_data->sfp_diags = 0;
+ phy_data->sfp_base = XGBE_SFP_BASE_UNKNOWN;
+ phy_data->sfp_cable = XGBE_SFP_CABLE_UNKNOWN;
+ phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN;
+}
+
+static void xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ /* Reset the SFP signals and info */
+ xgbe_phy_sfp_reset(phy_data);
+
+ ret = xgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return;
+
+ /* Read the SFP signals and check for module presence */
+ xgbe_phy_sfp_signals(pdata);
+ if (phy_data->sfp_mod_absent) {
+ xgbe_phy_sfp_mod_absent(pdata);
+ goto put;
+ }
+
+ ret = xgbe_phy_sfp_read_eeprom(pdata);
+ if (ret) {
+ /* Treat any error as if there isn't an SFP plugged in */
+ xgbe_phy_sfp_reset(phy_data);
+ xgbe_phy_sfp_mod_absent(pdata);
+ goto put;
+ }
+
+ xgbe_phy_sfp_parse_eeprom(pdata);
+
+ xgbe_phy_sfp_external_phy(pdata);
+
+put:
+ xgbe_phy_sfp_phy_settings(pdata);
+
+ xgbe_phy_put_comm_ownership(pdata);
+}
+
+static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ u16 lcl_adv = 0, rmt_adv = 0;
+ u8 fc;
+
+ pdata->phy.tx_pause = 0;
+ pdata->phy.rx_pause = 0;
+
+ if (!phy_data->phydev)
+ return;
+
+ if (phy_data->phydev->advertising & ADVERTISED_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_CAP;
+ if (phy_data->phydev->advertising & ADVERTISED_Asym_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+ if (phy_data->phydev->pause) {
+ pdata->phy.lp_advertising |= ADVERTISED_Pause;
+ rmt_adv |= LPA_PAUSE_CAP;
+ }
+ if (phy_data->phydev->asym_pause) {
+ pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+ rmt_adv |= LPA_PAUSE_ASYM;
+ }
+
+ fc = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+ if (fc & FLOW_CTRL_TX)
+ pdata->phy.tx_pause = 1;
+ if (fc & FLOW_CTRL_RX)
+ pdata->phy.rx_pause = 1;
+}
+
+static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
+{
+ enum xgbe_mode mode;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_TP;
+
+ /* Use external PHY to determine flow control */
+ if (pdata->phy.pause_autoneg)
+ xgbe_phy_phydev_flowctrl(pdata);
+
+ switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) {
+ case XGBE_SGMII_AN_LINK_SPEED_100:
+ if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
+ pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
+ mode = XGBE_MODE_SGMII_100;
+ } else {
+ /* Half-duplex not supported */
+ pdata->phy.lp_advertising |= ADVERTISED_100baseT_Half;
+ mode = XGBE_MODE_UNKNOWN;
+ }
+ break;
+ case XGBE_SGMII_AN_LINK_SPEED_1000:
+ if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+ mode = XGBE_MODE_SGMII_1000;
+ } else {
+ /* Half-duplex not supported */
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
+ mode = XGBE_MODE_UNKNOWN;
+ }
+ break;
+ default:
+ mode = XGBE_MODE_UNKNOWN;
+ }
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
+{
+ enum xgbe_mode mode;
+ unsigned int ad_reg, lp_reg;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_FIBRE;
+
+ /* Compare Advertisement and Link Partner register */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_LP_ABILITY);
+ if (lp_reg & 0x100)
+ pdata->phy.lp_advertising |= ADVERTISED_Pause;
+ if (lp_reg & 0x80)
+ pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+ if (pdata->phy.pause_autoneg) {
+ /* Set flow control based on auto-negotiation result */
+ pdata->phy.tx_pause = 0;
+ pdata->phy.rx_pause = 0;
+
+ if (ad_reg & lp_reg & 0x100) {
+ pdata->phy.tx_pause = 1;
+ pdata->phy.rx_pause = 1;
+ } else if (ad_reg & lp_reg & 0x80) {
+ if (ad_reg & 0x100)
+ pdata->phy.rx_pause = 1;
+ else if (lp_reg & 0x100)
+ pdata->phy.tx_pause = 1;
+ }
+ }
+
+ if (lp_reg & 0x40)
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
+ if (lp_reg & 0x20)
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+
+ /* Half duplex is not supported */
+ ad_reg &= lp_reg;
+ mode = (ad_reg & 0x20) ? XGBE_MODE_X : XGBE_MODE_UNKNOWN;
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_mode mode;
+ unsigned int ad_reg, lp_reg;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+ /* Use external PHY to determine flow control */
+ if (pdata->phy.pause_autoneg)
+ xgbe_phy_phydev_flowctrl(pdata);
+
+ /* Compare Advertisement and Link Partner register 2 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+ if (lp_reg & 0x80)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+ if (lp_reg & 0x20)
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+
+ ad_reg &= lp_reg;
+ if (ad_reg & 0x80) {
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ mode = XGBE_MODE_KR;
+ break;
+ default:
+ mode = XGBE_MODE_SFI;
+ break;
+ }
+ } else if (ad_reg & 0x20) {
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ mode = XGBE_MODE_KX_1000;
+ break;
+ case XGBE_PORT_MODE_1000BASE_X:
+ mode = XGBE_MODE_X;
+ break;
+ case XGBE_PORT_MODE_SFP:
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ if (phy_data->phydev &&
+ (phy_data->phydev->speed == SPEED_100))
+ mode = XGBE_MODE_SGMII_100;
+ else
+ mode = XGBE_MODE_SGMII_1000;
+ break;
+ case XGBE_SFP_BASE_1000_SX:
+ case XGBE_SFP_BASE_1000_LX:
+ case XGBE_SFP_BASE_1000_CX:
+ default:
+ mode = XGBE_MODE_X;
+ break;
+ }
+ break;
+ default:
+ if (phy_data->phydev &&
+ (phy_data->phydev->speed == SPEED_100))
+ mode = XGBE_MODE_SGMII_100;
+ else
+ mode = XGBE_MODE_SGMII_1000;
+ break;
+ }
+ } else {
+ mode = XGBE_MODE_UNKNOWN;
+ }
+
+ /* Compare Advertisement and Link Partner register 3 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+ if (lp_reg & 0xc000)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
+{
+ enum xgbe_mode mode;
+ unsigned int ad_reg, lp_reg;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+ /* Compare Advertisement and Link Partner register 1 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
+ if (lp_reg & 0x400)
+ pdata->phy.lp_advertising |= ADVERTISED_Pause;
+ if (lp_reg & 0x800)
+ pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+ if (pdata->phy.pause_autoneg) {
+ /* Set flow control based on auto-negotiation result */
+ pdata->phy.tx_pause = 0;
+ pdata->phy.rx_pause = 0;
+
+ if (ad_reg & lp_reg & 0x400) {
+ pdata->phy.tx_pause = 1;
+ pdata->phy.rx_pause = 1;
+ } else if (ad_reg & lp_reg & 0x800) {
+ if (ad_reg & 0x400)
+ pdata->phy.rx_pause = 1;
+ else if (lp_reg & 0x400)
+ pdata->phy.tx_pause = 1;
+ }
+ }
+
+ /* Compare Advertisement and Link Partner register 2 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+ if (lp_reg & 0x80)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+ if (lp_reg & 0x20)
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+
+ ad_reg &= lp_reg;
+ if (ad_reg & 0x80)
+ mode = XGBE_MODE_KR;
+ else if (ad_reg & 0x20)
+ mode = XGBE_MODE_KX_1000;
+ else
+ mode = XGBE_MODE_UNKNOWN;
+
+ /* Compare Advertisement and Link Partner register 3 */
+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+ if (lp_reg & 0xc000)
+ pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+ return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
+{
+ switch (pdata->an_mode) {
+ case XGBE_AN_MODE_CL73:
+ return xgbe_phy_an73_outcome(pdata);
+ case XGBE_AN_MODE_CL73_REDRV:
+ return xgbe_phy_an73_redrv_outcome(pdata);
+ case XGBE_AN_MODE_CL37:
+ return xgbe_phy_an37_outcome(pdata);
+ case XGBE_AN_MODE_CL37_SGMII:
+ return xgbe_phy_an37_sgmii_outcome(pdata);
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int advertising;
+
+ /* Without a re-driver, just return current advertising */
+ if (!phy_data->redrv)
+ return pdata->phy.advertising;
+
+ /* With the KR re-driver we need to advertise a single speed */
+ advertising = pdata->phy.advertising;
+ advertising &= ~ADVERTISED_1000baseKX_Full;
+ advertising &= ~ADVERTISED_10000baseKR_Full;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ advertising |= ADVERTISED_10000baseKR_Full;
+ break;
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ advertising |= ADVERTISED_1000baseKX_Full;
+ break;
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_NBASE_T:
+ advertising |= ADVERTISED_1000baseKX_Full;
+ break;
+ case XGBE_PORT_MODE_10GBASE_T:
+ if (phy_data->phydev &&
+ (phy_data->phydev->speed == SPEED_10000))
+ advertising |= ADVERTISED_10000baseKR_Full;
+ else
+ advertising |= ADVERTISED_1000baseKX_Full;
+ break;
+ case XGBE_PORT_MODE_10GBASE_R:
+ advertising |= ADVERTISED_10000baseKR_Full;
+ break;
+ case XGBE_PORT_MODE_SFP:
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ case XGBE_SFP_BASE_1000_SX:
+ case XGBE_SFP_BASE_1000_LX:
+ case XGBE_SFP_BASE_1000_CX:
+ advertising |= ADVERTISED_1000baseKX_Full;
+ break;
+ default:
+ advertising |= ADVERTISED_10000baseKR_Full;
+ break;
+ }
+ break;
+ default:
+ advertising |= ADVERTISED_10000baseKR_Full;
+ break;
+ }
+
+ return advertising;
+}
+
+static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ ret = xgbe_phy_find_phy_device(pdata);
+ if (ret)
+ return ret;
+
+ if (!phy_data->phydev)
+ return 0;
+
+ phy_data->phydev->autoneg = pdata->phy.autoneg;
+ phy_data->phydev->advertising = phy_data->phydev->supported &
+ pdata->phy.advertising;
+
+ if (pdata->phy.autoneg != AUTONEG_ENABLE) {
+ phy_data->phydev->speed = pdata->phy.speed;
+ phy_data->phydev->duplex = pdata->phy.duplex;
+ }
+
+ ret = phy_start_aneg(phy_data->phydev);
+
+ return ret;
+}
+
+static enum xgbe_an_mode xgbe_phy_an_sfp_mode(struct xgbe_phy_data *phy_data)
+{
+ switch (phy_data->sfp_base) {
+ case XGBE_SFP_BASE_1000_T:
+ return XGBE_AN_MODE_CL37_SGMII;
+ case XGBE_SFP_BASE_1000_SX:
+ case XGBE_SFP_BASE_1000_LX:
+ case XGBE_SFP_BASE_1000_CX:
+ return XGBE_AN_MODE_CL37;
+ default:
+ return XGBE_AN_MODE_NONE;
+ }
+}
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ /* A KR re-driver will always require CL73 AN */
+ if (phy_data->redrv)
+ return XGBE_AN_MODE_CL73_REDRV;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ return XGBE_AN_MODE_CL73;
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ return XGBE_AN_MODE_NONE;
+ case XGBE_PORT_MODE_1000BASE_T:
+ return XGBE_AN_MODE_CL37_SGMII;
+ case XGBE_PORT_MODE_1000BASE_X:
+ return XGBE_AN_MODE_CL37;
+ case XGBE_PORT_MODE_NBASE_T:
+ return XGBE_AN_MODE_CL37_SGMII;
+ case XGBE_PORT_MODE_10GBASE_T:
+ return XGBE_AN_MODE_CL73;
+ case XGBE_PORT_MODE_10GBASE_R:
+ return XGBE_AN_MODE_NONE;
+ case XGBE_PORT_MODE_SFP:
+ return xgbe_phy_an_sfp_mode(phy_data);
+ default:
+ return XGBE_AN_MODE_NONE;
+ }
+}
+
+static int xgbe_phy_set_redrv_mode_mdio(struct xgbe_prv_data *pdata,
+ enum xgbe_phy_redrv_mode mode)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ u16 redrv_reg, redrv_val;
+
+ redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
+ redrv_val = (u16)mode;
+
+ return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr,
+ redrv_reg, redrv_val);
+}
+
+static int xgbe_phy_set_redrv_mode_i2c(struct xgbe_prv_data *pdata,
+ enum xgbe_phy_redrv_mode mode)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int redrv_reg;
+ int ret;
+
+ /* Calculate the register to write */
+ redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
+
+ ret = xgbe_phy_redrv_write(pdata, redrv_reg, mode);
+
+ return ret;
+}
+
+static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_phy_redrv_mode mode;
+ int ret;
+
+ if (!phy_data->redrv)
+ return;
+
+ mode = XGBE_PHY_REDRV_MODE_CX;
+ if ((phy_data->port_mode == XGBE_PORT_MODE_SFP) &&
+ (phy_data->sfp_base != XGBE_SFP_BASE_1000_CX) &&
+ (phy_data->sfp_base != XGBE_SFP_BASE_10000_CR))
+ mode = XGBE_PHY_REDRV_MODE_SR;
+
+ ret = xgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return;
+
+ if (phy_data->redrv_if)
+ xgbe_phy_set_redrv_mode_i2c(pdata, mode);
+ else
+ xgbe_phy_set_redrv_mode_mdio(pdata, mode);
+
+ xgbe_phy_put_comm_ownership(pdata);
+}
+
+static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
+{
+ if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+ return;
+
+ /* Log if a previous command did not complete */
+ netif_dbg(pdata, link, pdata->netdev,
+ "firmware mailbox not ready for command\n");
+}
+
+static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
+{
+ unsigned int wait;
+
+ /* Wait for command to complete */
+ wait = XGBE_RATECHANGE_COUNT;
+ while (wait--) {
+ if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+ return;
+
+ usleep_range(1000, 2000);
+ }
+
+ netif_dbg(pdata, link, pdata->netdev,
+ "firmware mailbox command did not complete\n");
+}
+
+static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
+{
+ unsigned int s0;
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* Receiver Reset Cycle */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 5);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ netif_dbg(pdata, link, pdata->netdev, "receiver reset complete\n");
+}
+
+static void xgbe_phy_power_off(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, 0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_UNKNOWN;
+
+ netif_dbg(pdata, link, pdata->netdev, "phy powered off\n");
+}
+
+static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 10G/SFI */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 3);
+ if (phy_data->sfp_cable != XGBE_SFP_CABLE_PASSIVE) {
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+ } else {
+ if (phy_data->sfp_cable_len <= 1)
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
+ else if (phy_data->sfp_cable_len <= 3)
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
+ else
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+ }
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_SFI;
+
+ netif_dbg(pdata, link, pdata->netdev, "10GbE SFI mode set\n");
+}
+
+static void xgbe_phy_x_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 1G/X */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_X;
+
+ netif_dbg(pdata, link, pdata->netdev, "1GbE X mode set\n");
+}
+
+static void xgbe_phy_sgmii_1000_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 1G/SGMII */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_SGMII_1000;
+
+ netif_dbg(pdata, link, pdata->netdev, "1GbE SGMII mode set\n");
+}
+
+static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 1G/SGMII */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_SGMII_100;
+
+ netif_dbg(pdata, link, pdata->netdev, "100MbE SGMII mode set\n");
+}
+
+static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 10G/KR */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 4);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_KR;
+
+ netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+}
+
+static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 2.5G/KX */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 2);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_KX_2500;
+
+ netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+}
+
+static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int s0;
+
+ xgbe_phy_set_redrv_mode(pdata);
+
+ xgbe_phy_start_ratechange(pdata);
+
+ /* 1G/KX */
+ s0 = 0;
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+
+ /* Call FW to make the change */
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+ XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+ XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+ xgbe_phy_complete_ratechange(pdata);
+
+ phy_data->cur_mode = XGBE_MODE_KX_1000;
+
+ netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+}
+
+static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ return phy_data->cur_mode;
+}
+
+static enum xgbe_mode xgbe_phy_switch_baset_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ /* No switching if not 10GBase-T */
+ if (phy_data->port_mode != XGBE_PORT_MODE_10GBASE_T)
+ return xgbe_phy_cur_mode(pdata);
+
+ switch (xgbe_phy_cur_mode(pdata)) {
+ case XGBE_MODE_SGMII_100:
+ case XGBE_MODE_SGMII_1000:
+ return XGBE_MODE_KR;
+ case XGBE_MODE_KR:
+ default:
+ return XGBE_MODE_SGMII_1000;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_switch_bp_2500_mode(struct xgbe_prv_data *pdata)
+{
+ return XGBE_MODE_KX_2500;
+}
+
+static enum xgbe_mode xgbe_phy_switch_bp_mode(struct xgbe_prv_data *pdata)
+{
+ /* If we are in KR switch to KX, and vice-versa */
+ switch (xgbe_phy_cur_mode(pdata)) {
+ case XGBE_MODE_KX_1000:
+ return XGBE_MODE_KR;
+ case XGBE_MODE_KR:
+ default:
+ return XGBE_MODE_KX_1000;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ return xgbe_phy_switch_bp_mode(pdata);
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ return xgbe_phy_switch_bp_2500_mode(pdata);
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_NBASE_T:
+ case XGBE_PORT_MODE_10GBASE_T:
+ return xgbe_phy_switch_baset_mode(pdata);
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_10GBASE_R:
+ case XGBE_PORT_MODE_SFP:
+ /* No switching, so just return current mode */
+ return xgbe_phy_cur_mode(pdata);
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_basex_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_1000:
+ return XGBE_MODE_X;
+ case SPEED_10000:
+ return XGBE_MODE_KR;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_baset_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_100:
+ return XGBE_MODE_SGMII_100;
+ case SPEED_1000:
+ return XGBE_MODE_SGMII_1000;
+ case SPEED_10000:
+ return XGBE_MODE_KR;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_sfp_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_100:
+ return XGBE_MODE_SGMII_100;
+ case SPEED_1000:
+ if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
+ return XGBE_MODE_SGMII_1000;
+ else
+ return XGBE_MODE_X;
+ case SPEED_10000:
+ case SPEED_UNKNOWN:
+ return XGBE_MODE_SFI;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_bp_2500_mode(int speed)
+{
+ switch (speed) {
+ case SPEED_2500:
+ return XGBE_MODE_KX_2500;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_bp_mode(int speed)
+{
+ switch (speed) {
+ case SPEED_1000:
+ return XGBE_MODE_KX_1000;
+ case SPEED_10000:
+ return XGBE_MODE_KR;
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
+ int speed)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ return xgbe_phy_get_bp_mode(speed);
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ return xgbe_phy_get_bp_2500_mode(speed);
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_NBASE_T:
+ case XGBE_PORT_MODE_10GBASE_T:
+ return xgbe_phy_get_baset_mode(phy_data, speed);
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_10GBASE_R:
+ return xgbe_phy_get_basex_mode(phy_data, speed);
+ case XGBE_PORT_MODE_SFP:
+ return xgbe_phy_get_sfp_mode(phy_data, speed);
+ default:
+ return XGBE_MODE_UNKNOWN;
+ }
+}
+
+static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ xgbe_phy_kx_1000_mode(pdata);
+ break;
+ case XGBE_MODE_KX_2500:
+ xgbe_phy_kx_2500_mode(pdata);
+ break;
+ case XGBE_MODE_KR:
+ xgbe_phy_kr_mode(pdata);
+ break;
+ case XGBE_MODE_SGMII_100:
+ xgbe_phy_sgmii_100_mode(pdata);
+ break;
+ case XGBE_MODE_SGMII_1000:
+ xgbe_phy_sgmii_1000_mode(pdata);
+ break;
+ case XGBE_MODE_X:
+ xgbe_phy_x_mode(pdata);
+ break;
+ case XGBE_MODE_SFI:
+ xgbe_phy_sfi_mode(pdata);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode, u32 advert)
+{
+ if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+ if (pdata->phy.advertising & advert)
+ return true;
+ } else {
+ enum xgbe_mode cur_mode;
+
+ cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
+ if (cur_mode == mode)
+ return true;
+ }
+
+ return false;
+}
+
+static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_X:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseT_Full);
+ case XGBE_MODE_KR:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_10000baseT_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_SGMII_100:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_100baseT_Full);
+ case XGBE_MODE_SGMII_1000:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseT_Full);
+ case XGBE_MODE_KR:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_10000baseT_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (mode) {
+ case XGBE_MODE_X:
+ if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
+ return false;
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseT_Full);
+ case XGBE_MODE_SGMII_100:
+ if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+ return false;
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_100baseT_Full);
+ case XGBE_MODE_SGMII_1000:
+ if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+ return false;
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseT_Full);
+ case XGBE_MODE_SFI:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_10000baseT_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_2500:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_2500baseX_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_use_bp_mode(struct xgbe_prv_data *pdata,
+ enum xgbe_mode mode)
+{
+ switch (mode) {
+ case XGBE_MODE_KX_1000:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_1000baseKX_Full);
+ case XGBE_MODE_KR:
+ return xgbe_phy_check_mode(pdata, mode,
+ ADVERTISED_10000baseKR_Full);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ return xgbe_phy_use_bp_mode(pdata, mode);
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ return xgbe_phy_use_bp_2500_mode(pdata, mode);
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_NBASE_T:
+ case XGBE_PORT_MODE_10GBASE_T:
+ return xgbe_phy_use_baset_mode(pdata, mode);
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_10GBASE_R:
+ return xgbe_phy_use_basex_mode(pdata, mode);
+ case XGBE_PORT_MODE_SFP:
+ return xgbe_phy_use_sfp_mode(pdata, mode);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed_basex_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_1000:
+ return (phy_data->port_mode == XGBE_PORT_MODE_1000BASE_X);
+ case SPEED_10000:
+ return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_R);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_100:
+ case SPEED_1000:
+ return true;
+ case SPEED_10000:
+ return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_phy_data *phy_data,
+ int speed)
+{
+ switch (speed) {
+ case SPEED_100:
+ return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
+ case SPEED_1000:
+ return ((phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000) ||
+ (phy_data->sfp_speed == XGBE_SFP_SPEED_1000));
+ case SPEED_10000:
+ return (phy_data->sfp_speed == XGBE_SFP_SPEED_10000);
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed_bp_2500_mode(int speed)
+{
+ switch (speed) {
+ case SPEED_2500:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed_bp_mode(int speed)
+{
+ switch (speed) {
+ case SPEED_1000:
+ case SPEED_10000:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ return xgbe_phy_valid_speed_bp_mode(speed);
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ return xgbe_phy_valid_speed_bp_2500_mode(speed);
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_NBASE_T:
+ case XGBE_PORT_MODE_10GBASE_T:
+ return xgbe_phy_valid_speed_baset_mode(phy_data, speed);
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_10GBASE_R:
+ return xgbe_phy_valid_speed_basex_mode(phy_data, speed);
+ case XGBE_PORT_MODE_SFP:
+ return xgbe_phy_valid_speed_sfp_mode(phy_data, speed);
+ default:
+ return false;
+ }
+}
+
+static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+ int ret;
+
+ *an_restart = 0;
+
+ if (phy_data->port_mode == XGBE_PORT_MODE_SFP) {
+ /* Check SFP signals */
+ xgbe_phy_sfp_detect(pdata);
+
+ if (phy_data->sfp_changed) {
+ *an_restart = 1;
+ return 0;
+ }
+
+ if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los)
+ return 0;
+ }
+
+ if (phy_data->phydev) {
+ /* Check external PHY */
+ ret = phy_read_status(phy_data->phydev);
+ if (ret < 0)
+ return 0;
+
+ if ((pdata->phy.autoneg == AUTONEG_ENABLE) &&
+ !phy_aneg_done(phy_data->phydev))
+ return 0;
+
+ if (!phy_data->phydev->link)
+ return 0;
+ }
+
+ /* Link status is latched low, so read once to clear
+ * and then read again to get current state
+ */
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+ if (reg & MDIO_STAT1_LSTATUS)
+ return 1;
+
+ /* No link, attempt a receiver reset cycle */
+ if (phy_data->rrc_count++) {
+ phy_data->rrc_count = 0;
+ xgbe_phy_rrc(pdata);
+ }
+
+ return 0;
+}
+
+static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+
+ reg = XP_IOREAD(pdata, XP_PROP_3);
+
+ phy_data->sfp_gpio_address = XGBE_GPIO_ADDRESS_PCA9555 +
+ XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR);
+
+ phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK);
+
+ phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3,
+ GPIO_RX_LOS);
+ phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3,
+ GPIO_TX_FAULT);
+ phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3,
+ GPIO_MOD_ABS);
+ phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3,
+ GPIO_RATE_SELECT);
+
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(pdata->dev, "SFP: gpio_address=%#x\n",
+ phy_data->sfp_gpio_address);
+ dev_dbg(pdata->dev, "SFP: gpio_mask=%#x\n",
+ phy_data->sfp_gpio_mask);
+ dev_dbg(pdata->dev, "SFP: gpio_rx_los=%u\n",
+ phy_data->sfp_gpio_rx_los);
+ dev_dbg(pdata->dev, "SFP: gpio_tx_fault=%u\n",
+ phy_data->sfp_gpio_tx_fault);
+ dev_dbg(pdata->dev, "SFP: gpio_mod_absent=%u\n",
+ phy_data->sfp_gpio_mod_absent);
+ dev_dbg(pdata->dev, "SFP: gpio_rate_select=%u\n",
+ phy_data->sfp_gpio_rate_select);
+ }
+}
+
+static void xgbe_phy_sfp_comm_setup(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg, mux_addr_hi, mux_addr_lo;
+
+ reg = XP_IOREAD(pdata, XP_PROP_4);
+
+ mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI);
+ mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO);
+ if (mux_addr_lo == XGBE_SFP_DIRECT)
+ return;
+
+ phy_data->sfp_comm = XGBE_SFP_COMM_PCA9545;
+ phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo;
+ phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN);
+
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(pdata->dev, "SFP: mux_address=%#x\n",
+ phy_data->sfp_mux_address);
+ dev_dbg(pdata->dev, "SFP: mux_channel=%u\n",
+ phy_data->sfp_mux_channel);
+ }
+}
+
+static void xgbe_phy_sfp_setup(struct xgbe_prv_data *pdata)
+{
+ xgbe_phy_sfp_comm_setup(pdata);
+ xgbe_phy_sfp_gpio_setup(pdata);
+}
+
+static int xgbe_phy_int_mdio_reset(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int ret;
+
+ ret = pdata->hw_if.set_gpio(pdata, phy_data->mdio_reset_gpio);
+ if (ret)
+ return ret;
+
+ ret = pdata->hw_if.clr_gpio(pdata, phy_data->mdio_reset_gpio);
+
+ return ret;
+}
+
+static int xgbe_phy_i2c_mdio_reset(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ u8 gpio_reg, gpio_ports[2], gpio_data[3];
+ int ret;
+
+ /* Read the output port registers */
+ gpio_reg = 2;
+ ret = xgbe_phy_i2c_read(pdata, phy_data->mdio_reset_addr,
+ &gpio_reg, sizeof(gpio_reg),
+ gpio_ports, sizeof(gpio_ports));
+ if (ret)
+ return ret;
+
+ /* Prepare to write the GPIO data */
+ gpio_data[0] = 2;
+ gpio_data[1] = gpio_ports[0];
+ gpio_data[2] = gpio_ports[1];
+
+ /* Set the GPIO pin */
+ if (phy_data->mdio_reset_gpio < 8)
+ gpio_data[1] |= (1 << (phy_data->mdio_reset_gpio % 8));
+ else
+ gpio_data[2] |= (1 << (phy_data->mdio_reset_gpio % 8));
+
+ /* Write the output port registers */
+ ret = xgbe_phy_i2c_write(pdata, phy_data->mdio_reset_addr,
+ gpio_data, sizeof(gpio_data));
+ if (ret)
+ return ret;
+
+ /* Clear the GPIO pin */
+ if (phy_data->mdio_reset_gpio < 8)
+ gpio_data[1] &= ~(1 << (phy_data->mdio_reset_gpio % 8));
+ else
+ gpio_data[2] &= ~(1 << (phy_data->mdio_reset_gpio % 8));
+
+ /* Write the output port registers */
+ ret = xgbe_phy_i2c_write(pdata, phy_data->mdio_reset_addr,
+ gpio_data, sizeof(gpio_data));
+
+ return ret;
+}
+
+static int xgbe_phy_mdio_reset(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ if (phy_data->conn_type != XGBE_CONN_TYPE_MDIO)
+ return 0;
+
+ ret = xgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return ret;
+
+ if (phy_data->mdio_reset == XGBE_MDIO_RESET_I2C_GPIO)
+ ret = xgbe_phy_i2c_mdio_reset(pdata);
+ else if (phy_data->mdio_reset == XGBE_MDIO_RESET_INT_GPIO)
+ ret = xgbe_phy_int_mdio_reset(pdata);
+
+ xgbe_phy_put_comm_ownership(pdata);
+
+ return ret;
+}
+
+static bool xgbe_phy_redrv_error(struct xgbe_phy_data *phy_data)
+{
+ if (!phy_data->redrv)
+ return false;
+
+ if (phy_data->redrv_if >= XGBE_PHY_REDRV_IF_MAX)
+ return true;
+
+ switch (phy_data->redrv_model) {
+ case XGBE_PHY_REDRV_MODEL_4223:
+ if (phy_data->redrv_lane > 3)
+ return true;
+ break;
+ case XGBE_PHY_REDRV_MODEL_4227:
+ if (phy_data->redrv_lane > 1)
+ return true;
+ break;
+ default:
+ return true;
+ }
+
+ return false;
+}
+
+static int xgbe_phy_mdio_reset_setup(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ unsigned int reg;
+
+ if (phy_data->conn_type != XGBE_CONN_TYPE_MDIO)
+ return 0;
+
+ reg = XP_IOREAD(pdata, XP_PROP_3);
+ phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET);
+ switch (phy_data->mdio_reset) {
+ case XGBE_MDIO_RESET_NONE:
+ case XGBE_MDIO_RESET_I2C_GPIO:
+ case XGBE_MDIO_RESET_INT_GPIO:
+ break;
+ default:
+ dev_err(pdata->dev, "unsupported MDIO reset (%#x)\n",
+ phy_data->mdio_reset);
+ return -EINVAL;
+ }
+
+ if (phy_data->mdio_reset == XGBE_MDIO_RESET_I2C_GPIO) {
+ phy_data->mdio_reset_addr = XGBE_GPIO_ADDRESS_PCA9555 +
+ XP_GET_BITS(reg, XP_PROP_3,
+ MDIO_RESET_I2C_ADDR);
+ phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3,
+ MDIO_RESET_I2C_GPIO);
+ } else if (phy_data->mdio_reset == XGBE_MDIO_RESET_INT_GPIO) {
+ phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3,
+ MDIO_RESET_INT_GPIO);
+ }
+
+ return 0;
+}
+
+static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+ return false;
+ break;
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+ return false;
+ break;
+ case XGBE_PORT_MODE_1000BASE_T:
+ if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000))
+ return false;
+ break;
+ case XGBE_PORT_MODE_1000BASE_X:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+ return false;
+ break;
+ case XGBE_PORT_MODE_NBASE_T:
+ if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500))
+ return false;
+ break;
+ case XGBE_PORT_MODE_10GBASE_T:
+ if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+ return false;
+ break;
+ case XGBE_PORT_MODE_10GBASE_R:
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+ return false;
+ break;
+ case XGBE_PORT_MODE_SFP:
+ if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+ (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool xgbe_phy_conn_type_mismatch(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_BACKPLANE:
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ if (phy_data->conn_type == XGBE_CONN_TYPE_BACKPLANE)
+ return false;
+ break;
+ case XGBE_PORT_MODE_1000BASE_T:
+ case XGBE_PORT_MODE_1000BASE_X:
+ case XGBE_PORT_MODE_NBASE_T:
+ case XGBE_PORT_MODE_10GBASE_T:
+ case XGBE_PORT_MODE_10GBASE_R:
+ if (phy_data->conn_type == XGBE_CONN_TYPE_MDIO)
+ return false;
+ break;
+ case XGBE_PORT_MODE_SFP:
+ if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool xgbe_phy_port_enabled(struct xgbe_prv_data *pdata)
+{
+ unsigned int reg;
+
+ reg = XP_IOREAD(pdata, XP_PROP_0);
+ if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS))
+ return false;
+ if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE))
+ return false;
+
+ return true;
+}
+
+static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ /* If we have an external PHY, free it */
+ xgbe_phy_free_phy_device(pdata);
+
+ /* Reset SFP data */
+ xgbe_phy_sfp_reset(phy_data);
+ xgbe_phy_sfp_mod_absent(pdata);
+
+ /* Power off the PHY */
+ xgbe_phy_power_off(pdata);
+
+ /* Stop the I2C controller */
+ pdata->i2c_if.i2c_stop(pdata);
+}
+
+static int xgbe_phy_start(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ /* Start the I2C controller */
+ ret = pdata->i2c_if.i2c_start(pdata);
+ if (ret)
+ return ret;
+
+ /* Start in highest supported mode */
+ xgbe_phy_set_mode(pdata, phy_data->start_mode);
+
+ /* After starting the I2C controller, we can check for an SFP */
+ switch (phy_data->port_mode) {
+ case XGBE_PORT_MODE_SFP:
+ xgbe_phy_sfp_detect(pdata);
+ break;
+ default:
+ break;
+ }
+
+ /* If we have an external PHY, start it */
+ ret = xgbe_phy_find_phy_device(pdata);
+ if (ret)
+ goto err_i2c;
+
+ return 0;
+
+err_i2c:
+ pdata->i2c_if.i2c_stop(pdata);
+
+ return ret;
+}
+
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+ enum xgbe_mode cur_mode;
+ int ret;
+
+ /* Reset by power cycling the PHY */
+ cur_mode = phy_data->cur_mode;
+ xgbe_phy_power_off(pdata);
+ xgbe_phy_set_mode(pdata, cur_mode);
+
+ if (!phy_data->phydev)
+ return 0;
+
+ /* Reset the external PHY */
+ ret = xgbe_phy_mdio_reset(pdata);
+ if (ret)
+ return ret;
+
+ return phy_init_hw(phy_data->phydev);
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+ /* Unregister for driving external PHYs */
+ mdiobus_unregister(phy_data->mii);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+ struct xgbe_phy_data *phy_data;
+ struct mii_bus *mii;
+ unsigned int reg;
+ int ret;
+
+ /* Check if enabled */
+ if (!xgbe_phy_port_enabled(pdata)) {
+ dev_info(pdata->dev, "device is not enabled\n");
+ return -ENODEV;
+ }
+
+ /* Initialize the I2C controller */
+ ret = pdata->i2c_if.i2c_init(pdata);
+ if (ret)
+ return ret;
+
+ phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
+ if (!phy_data)
+ return -ENOMEM;
+ pdata->phy_data = phy_data;
+
+ reg = XP_IOREAD(pdata, XP_PROP_0);
+ phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE);
+ phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID);
+ phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS);
+ phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE);
+ phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR);
+ if (netif_msg_probe(pdata)) {
+ dev_dbg(pdata->dev, "port mode=%u\n", phy_data->port_mode);
+ dev_dbg(pdata->dev, "port id=%u\n", phy_data->port_id);
+ dev_dbg(pdata->dev, "port speeds=%#x\n", phy_data->port_speeds);
+ dev_dbg(pdata->dev, "conn type=%u\n", phy_data->conn_type);
+ dev_dbg(pdata->dev, "mdio addr=%u\n", phy_data->mdio_addr);
+ }
+
+ reg = XP_IOREAD(pdata, XP_PROP_4);
+ phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT);
+ phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF);
+ phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR);
+ phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE);
+ phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL);
+ if (phy_data->redrv && netif_msg_probe(pdata)) {
+ dev_dbg(pdata->dev, "redrv present\n");
+ dev_dbg(pdata->dev, "redrv i/f=%u\n", phy_data->redrv_if);
+ dev_dbg(pdata->dev, "redrv addr=%#x\n", phy_data->redrv_addr);
+ dev_dbg(pdata->dev, "redrv lane=%u\n", phy_data->redrv_lane);
+ dev_dbg(pdata->dev, "redrv model=%u\n", phy_data->redrv_model);
+ }
+
+ /* Validate the connection requested */
+ if (xgbe_phy_conn_type_mismatch(pdata)) {
+ dev_err(pdata->dev, "phy mode/connection mismatch (%#x/%#x)\n",
+ phy_data->port_mode, phy_data->conn_type);
+ return -EINVAL;
+ }
+
+ /* Validate the mode requested */
+ if (xgbe_phy_port_mode_mismatch(pdata)) {
+ dev_err(pdata->dev, "phy mode/speed mismatch (%#x/%#x)\n",
+ phy_data->port_mode, phy_data->port_speeds);
+ return -EINVAL;
+ }
+
+ /* Check for and validate MDIO reset support */
+ ret = xgbe_phy_mdio_reset_setup(pdata);
+ if (ret)
+ return ret;
+
+ /* Validate the re-driver information */
+ if (xgbe_phy_redrv_error(phy_data)) {
+ dev_err(pdata->dev, "phy re-driver settings error\n");
+ return -EINVAL;
+ }
+ pdata->kr_redrv = phy_data->redrv;
+
+ /* Indicate current mode is unknown */
+ phy_data->cur_mode = XGBE_MODE_UNKNOWN;
+
+ /* Initialize supported features */
+ pdata->phy.supported = 0;
+
+ switch (phy_data->port_mode) {
+ /* Backplane support */
+ case XGBE_PORT_MODE_BACKPLANE:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_Backplane;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+ pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
+ phy_data->start_mode = XGBE_MODE_KX_1000;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+ pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+ pdata->phy.supported |=
+ SUPPORTED_10000baseR_FEC;
+ phy_data->start_mode = XGBE_MODE_KR;
+ }
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+ break;
+ case XGBE_PORT_MODE_BACKPLANE_2500:
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_Backplane;
+ pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+ phy_data->start_mode = XGBE_MODE_KX_2500;
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+ break;
+
+ /* MDIO 1GBase-T support */
+ case XGBE_PORT_MODE_1000BASE_T:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_TP;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+ pdata->phy.supported |= SUPPORTED_100baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_100;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+ pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_1000;
+ }
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+ break;
+
+ /* MDIO Base-X support */
+ case XGBE_PORT_MODE_1000BASE_X:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_FIBRE;
+ pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_X;
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+ break;
+
+ /* MDIO NBase-T support */
+ case XGBE_PORT_MODE_NBASE_T:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_TP;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+ pdata->phy.supported |= SUPPORTED_100baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_100;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+ pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_1000;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500) {
+ pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+ phy_data->start_mode = XGBE_MODE_KX_2500;
+ }
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
+ break;
+
+ /* 10GBase-T support */
+ case XGBE_PORT_MODE_10GBASE_T:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_TP;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+ pdata->phy.supported |= SUPPORTED_100baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_100;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+ pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_1000;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+ pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_KR;
+ }
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+ break;
+
+ /* 10GBase-R support */
+ case XGBE_PORT_MODE_10GBASE_R:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_TP;
+ pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+ pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
+ phy_data->start_mode = XGBE_MODE_SFI;
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+ break;
+
+ /* SFP support */
+ case XGBE_PORT_MODE_SFP:
+ pdata->phy.supported |= SUPPORTED_Autoneg;
+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ pdata->phy.supported |= SUPPORTED_TP;
+ pdata->phy.supported |= SUPPORTED_FIBRE;
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+ pdata->phy.supported |= SUPPORTED_100baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_100;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+ pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SGMII_1000;
+ }
+ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+ pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+ phy_data->start_mode = XGBE_MODE_SFI;
+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+ pdata->phy.supported |=
+ SUPPORTED_10000baseR_FEC;
+ }
+
+ phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+
+ xgbe_phy_sfp_setup(pdata);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (netif_msg_probe(pdata))
+ dev_dbg(pdata->dev, "phy supported=%#x\n",
+ pdata->phy.supported);
+
+ if ((phy_data->conn_type & XGBE_CONN_TYPE_MDIO) &&
+ (phy_data->phydev_mode != XGBE_MDIO_MODE_NONE)) {
+ ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr,
+ phy_data->phydev_mode);
+ if (ret) {
+ dev_err(pdata->dev,
+ "mdio port/clause not compatible (%d/%u)\n",
+ phy_data->mdio_addr, phy_data->phydev_mode);
+ return -EINVAL;
+ }
+ }
+
+ if (phy_data->redrv && !phy_data->redrv_if) {
+ ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr,
+ XGBE_MDIO_MODE_CL22);
+ if (ret) {
+ dev_err(pdata->dev,
+ "redriver mdio port not compatible (%u)\n",
+ phy_data->redrv_addr);
+ return -EINVAL;
+ }
+ }
+
+ /* Register for driving external PHYs */
+ mii = devm_mdiobus_alloc(pdata->dev);
+ if (!mii) {
+ dev_err(pdata->dev, "mdiobus_alloc failed\n");
+ return -ENOMEM;
+ }
+
+ mii->priv = pdata;
+ mii->name = "amd-xgbe-mii";
+ mii->read = xgbe_phy_mii_read;
+ mii->write = xgbe_phy_mii_write;
+ mii->parent = pdata->dev;
+ mii->phy_mask = ~0;
+ snprintf(mii->id, sizeof(mii->id), "%s", dev_name(pdata->dev));
+ ret = mdiobus_register(mii);
+ if (ret) {
+ dev_err(pdata->dev, "mdiobus_register failed\n");
+ return ret;
+ }
+ phy_data->mii = mii;
+
+ return 0;
+}
+
+void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *phy_if)
+{
+ struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
+
+ phy_impl->init = xgbe_phy_init;
+ phy_impl->exit = xgbe_phy_exit;
+
+ phy_impl->reset = xgbe_phy_reset;
+ phy_impl->start = xgbe_phy_start;
+ phy_impl->stop = xgbe_phy_stop;
+
+ phy_impl->link_status = xgbe_phy_link_status;
+
+ phy_impl->valid_speed = xgbe_phy_valid_speed;
+
+ phy_impl->use_mode = xgbe_phy_use_mode;
+ phy_impl->set_mode = xgbe_phy_set_mode;
+ phy_impl->get_mode = xgbe_phy_get_mode;
+ phy_impl->switch_mode = xgbe_phy_switch_mode;
+ phy_impl->cur_mode = xgbe_phy_cur_mode;
+
+ phy_impl->an_mode = xgbe_phy_an_mode;
+
+ phy_impl->an_config = xgbe_phy_an_config;
+
+ phy_impl->an_advertising = xgbe_phy_an_advertising;
+
+ phy_impl->an_outcome = xgbe_phy_an_outcome;
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
new file mode 100644
index 000000000000..84d4c51cab8c
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
@@ -0,0 +1,642 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * 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 of Advanced Micro Devices, Inc. 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 <COPYRIGHT HOLDER> 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.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and 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.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/property.h>
+#include <linux/acpi.h>
+#include <linux/mdio.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgbe_acpi_match[];
+
+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
+{
+ const struct acpi_device_id *id;
+
+ id = acpi_match_device(xgbe_acpi_match, pdata->dev);
+
+ return id ? (struct xgbe_version_data *)id->driver_data : NULL;
+}
+
+static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+{
+ struct device *dev = pdata->dev;
+ u32 property;
+ int ret;
+
+ /* Obtain the system clock setting */
+ ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property);
+ if (ret) {
+ dev_err(dev, "unable to obtain %s property\n",
+ XGBE_ACPI_DMA_FREQ);
+ return ret;
+ }
+ pdata->sysclk_rate = property;
+
+ /* Obtain the PTP clock setting */
+ ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property);
+ if (ret) {
+ dev_err(dev, "unable to obtain %s property\n",
+ XGBE_ACPI_PTP_FREQ);
+ return ret;
+ }
+ pdata->ptpclk_rate = property;
+
+ return 0;
+}
+#else /* CONFIG_ACPI */
+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
+{
+ return NULL;
+}
+
+static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_ACPI */
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgbe_of_match[];
+
+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
+{
+ const struct of_device_id *id;
+
+ id = of_match_device(xgbe_of_match, pdata->dev);
+
+ return id ? (struct xgbe_version_data *)id->data : NULL;
+}
+
+static int xgbe_of_support(struct xgbe_prv_data *pdata)
+{
+ struct device *dev = pdata->dev;
+
+ /* Obtain the system clock setting */
+ pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
+ if (IS_ERR(pdata->sysclk)) {
+ dev_err(dev, "dma devm_clk_get failed\n");
+ return PTR_ERR(pdata->sysclk);
+ }
+ pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
+
+ /* Obtain the PTP clock setting */
+ pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
+ if (IS_ERR(pdata->ptpclk)) {
+ dev_err(dev, "ptp devm_clk_get failed\n");
+ return PTR_ERR(pdata->ptpclk);
+ }
+ pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
+
+ return 0;
+}
+
+static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+ struct device *dev = pdata->dev;
+ struct device_node *phy_node;
+ struct platform_device *phy_pdev;
+
+ phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
+ if (phy_node) {
+ /* Old style device tree:
+ * The XGBE and PHY resources are separate
+ */
+ phy_pdev = of_find_device_by_node(phy_node);
+ of_node_put(phy_node);
+ } else {
+ /* New style device tree:
+ * The XGBE and PHY resources are grouped together with
+ * the PHY resources listed last
+ */
+ get_device(dev);
+ phy_pdev = pdata->platdev;
+ }
+
+ return phy_pdev;
+}
+#else /* CONFIG_OF */
+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
+{
+ return NULL;
+}
+
+static int xgbe_of_support(struct xgbe_prv_data *pdata)
+{
+ return -EINVAL;
+}
+
+static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
+static unsigned int xgbe_resource_count(struct platform_device *pdev,
+ unsigned int type)
+{
+ unsigned int count;
+ int i;
+
+ for (i = 0, count = 0; i < pdev->num_resources; i++) {
+ struct resource *res = &pdev->resource[i];
+
+ if (type == resource_type(res))
+ count++;
+ }
+
+ return count;
+}
+
+static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+ struct platform_device *phy_pdev;
+
+ if (pdata->use_acpi) {
+ get_device(pdata->dev);
+ phy_pdev = pdata->platdev;
+ } else {
+ phy_pdev = xgbe_of_get_phy_pdev(pdata);
+ }
+
+ return phy_pdev;
+}
+
+static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata)
+{
+ return pdata->use_acpi ? xgbe_acpi_vdata(pdata)
+ : xgbe_of_vdata(pdata);
+}
+
+static int xgbe_platform_probe(struct platform_device *pdev)
+{
+ struct xgbe_prv_data *pdata;
+ struct device *dev = &pdev->dev;
+ struct platform_device *phy_pdev;
+ struct resource *res;
+ const char *phy_mode;
+ unsigned int phy_memnum, phy_irqnum;
+ unsigned int dma_irqnum, dma_irqend;
+ enum dev_dma_attr attr;
+ int ret;
+
+ pdata = xgbe_alloc_pdata(dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto err_alloc;
+ }
+
+ pdata->platdev = pdev;
+ pdata->adev = ACPI_COMPANION(dev);
+ platform_set_drvdata(pdev, pdata);
+
+ /* Check if we should use ACPI or DT */
+ pdata->use_acpi = dev->of_node ? 0 : 1;
+
+ /* Get the version data */
+ pdata->vdata = xgbe_get_vdata(pdata);
+
+ phy_pdev = xgbe_get_phy_pdev(pdata);
+ if (!phy_pdev) {
+ dev_err(dev, "unable to obtain phy device\n");
+ ret = -EINVAL;
+ goto err_phydev;
+ }
+ pdata->phy_platdev = phy_pdev;
+ pdata->phy_dev = &phy_pdev->dev;
+
+ if (pdev == phy_pdev) {
+ /* New style device tree or ACPI:
+ * The XGBE and PHY resources are grouped together with
+ * the PHY resources listed last
+ */
+ phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
+ phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
+ dma_irqnum = 1;
+ dma_irqend = phy_irqnum;
+ } else {
+ /* Old style device tree:
+ * The XGBE and PHY resources are separate
+ */
+ phy_memnum = 0;
+ phy_irqnum = 0;
+ dma_irqnum = 1;
+ dma_irqend = xgbe_resource_count(pdev, IORESOURCE_IRQ);
+ }
+
+ /* Obtain the mmio areas for the device */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pdata->xgmac_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->xgmac_regs)) {
+ dev_err(dev, "xgmac ioremap failed\n");
+ ret = PTR_ERR(pdata->xgmac_regs);
+ goto err_io;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ pdata->xpcs_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->xpcs_regs)) {
+ dev_err(dev, "xpcs ioremap failed\n");
+ ret = PTR_ERR(pdata->xpcs_regs);
+ goto err_io;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs);
+
+ res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+ pdata->rxtx_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->rxtx_regs)) {
+ dev_err(dev, "rxtx ioremap failed\n");
+ ret = PTR_ERR(pdata->rxtx_regs);
+ goto err_io;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs);
+
+ res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+ pdata->sir0_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->sir0_regs)) {
+ dev_err(dev, "sir0 ioremap failed\n");
+ ret = PTR_ERR(pdata->sir0_regs);
+ goto err_io;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs);
+
+ res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+ pdata->sir1_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->sir1_regs)) {
+ dev_err(dev, "sir1 ioremap failed\n");
+ ret = PTR_ERR(pdata->sir1_regs);
+ goto err_io;
+ }
+ if (netif_msg_probe(pdata))
+ dev_dbg(dev, "sir1_regs = %p\n", pdata->sir1_regs);
+
+ /* Retrieve the MAC address */
+ ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
+ pdata->mac_addr,
+ sizeof(pdata->mac_addr));
+ if (ret || !is_valid_ether_addr(pdata->mac_addr)) {
+ dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY);
+ if (!ret)
+ ret = -EINVAL;
+ goto err_io;
+ }
+
+ /* Retrieve the PHY mode - it must be "xgmii" */
+ ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY,
+ &phy_mode);
+ if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) {
+ dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY);
+ if (!ret)
+ ret = -EINVAL;
+ goto err_io;
+ }
+ pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
+
+ /* Check for per channel interrupt support */
+ if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) {
+ pdata->per_channel_irq = 1;
+ pdata->channel_irq_mode = XGBE_IRQ_MODE_EDGE;
+ }
+
+ /* Obtain device settings unique to ACPI/OF */
+ if (pdata->use_acpi)
+ ret = xgbe_acpi_support(pdata);
+ else
+ ret = xgbe_of_support(pdata);
+ if (ret)
+ goto err_io;
+
+ /* Set the DMA coherency values */
+ attr = device_get_dma_attr(dev);
+ if (attr == DEV_DMA_NOT_SUPPORTED) {
+ dev_err(dev, "DMA is not supported");
+ ret = -ENODEV;
+ goto err_io;
+ }
+ pdata->coherent = (attr == DEV_DMA_COHERENT);
+ if (pdata->coherent) {
+ pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+ pdata->arcache = XGBE_DMA_OS_ARCACHE;
+ pdata->awcache = XGBE_DMA_OS_AWCACHE;
+ } else {
+ pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
+ pdata->arcache = XGBE_DMA_SYS_ARCACHE;
+ pdata->awcache = XGBE_DMA_SYS_AWCACHE;
+ }
+
+ /* Set the maximum fifo amounts */
+ pdata->tx_max_fifo_size = pdata->vdata->tx_max_fifo_size;
+ pdata->rx_max_fifo_size = pdata->vdata->rx_max_fifo_size;
+
+ /* Set the hardware channel and queue counts */
+ xgbe_set_counts(pdata);
+
+ /* Always have XGMAC and XPCS (auto-negotiation) interrupts */
+ pdata->irq_count = 2;
+
+ /* Get the device interrupt */
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(dev, "platform_get_irq 0 failed\n");
+ goto err_io;
+ }
+ pdata->dev_irq = ret;
+
+ /* Get the per channel DMA interrupts */
+ if (pdata->per_channel_irq) {
+ unsigned int i, max = ARRAY_SIZE(pdata->channel_irq);
+
+ for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) {
+ ret = platform_get_irq(pdata->platdev, dma_irqnum++);
+ if (ret < 0) {
+ netdev_err(pdata->netdev,
+ "platform_get_irq %u failed\n",
+ dma_irqnum - 1);
+ goto err_io;
+ }
+
+ pdata->channel_irq[i] = ret;
+ }
+
+ pdata->channel_irq_count = max;
+
+ pdata->irq_count += max;
+ }
+
+ /* Get the auto-negotiation interrupt */
+ ret = platform_get_irq(phy_pdev, phy_irqnum++);
+ if (ret < 0) {
+ dev_err(dev, "platform_get_irq phy 0 failed\n");
+ goto err_io;
+ }
+ pdata->an_irq = ret;
+
+ /* Configure the netdev resource */
+ ret = xgbe_config_netdev(pdata);
+ if (ret)
+ goto err_io;
+
+ netdev_notice(pdata->netdev, "net device enabled\n");
+
+ return 0;
+
+err_io:
+ platform_device_put(phy_pdev);
+
+err_phydev:
+ xgbe_free_pdata(pdata);
+
+err_alloc:
+ dev_notice(dev, "net device not enabled\n");
+
+ return ret;
+}
+
+static int xgbe_platform_remove(struct platform_device *pdev)
+{
+ struct xgbe_prv_data *pdata = platform_get_drvdata(pdev);
+
+ xgbe_deconfig_netdev(pdata);
+
+ platform_device_put(pdata->phy_platdev);
+
+ xgbe_free_pdata(pdata);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xgbe_platform_suspend(struct device *dev)
+{
+ struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
+ struct net_device *netdev = pdata->netdev;
+ int ret = 0;
+
+ DBGPR("-->xgbe_suspend\n");
+
+ if (netif_running(netdev))
+ ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+
+ pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+ pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+ DBGPR("<--xgbe_suspend\n");
+
+ return ret;
+}
+
+static int xgbe_platform_resume(struct device *dev)
+{
+ struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
+ struct net_device *netdev = pdata->netdev;
+ int ret = 0;
+
+ DBGPR("-->xgbe_resume\n");
+
+ pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+ if (netif_running(netdev)) {
+ ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
+
+ /* Schedule a restart in case the link or phy state changed
+ * while we were powered down.
+ */
+ schedule_work(&pdata->restart_work);
+ }
+
+ DBGPR("<--xgbe_resume\n");
+
+ return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct xgbe_version_data xgbe_v1 = {
+ .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1,
+ .xpcs_access = XGBE_XPCS_ACCESS_V1,
+ .tx_max_fifo_size = 81920,
+ .rx_max_fifo_size = 81920,
+ .tx_tstamp_workaround = 1,
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgbe_acpi_match[] = {
+ { .id = "AMDI8001",
+ .driver_data = (kernel_ulong_t)&xgbe_v1 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgbe_of_match[] = {
+ { .compatible = "amd,xgbe-seattle-v1a",
+ .data = &xgbe_v1 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, xgbe_of_match);
+#endif
+
+static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops,
+ xgbe_platform_suspend, xgbe_platform_resume);
+
+static struct platform_driver xgbe_driver = {
+ .driver = {
+ .name = XGBE_DRV_NAME,
+#ifdef CONFIG_ACPI
+ .acpi_match_table = xgbe_acpi_match,
+#endif
+#ifdef CONFIG_OF
+ .of_match_table = xgbe_of_match,
+#endif
+ .pm = &xgbe_platform_pm_ops,
+ },
+ .probe = xgbe_platform_probe,
+ .remove = xgbe_platform_remove,
+};
+
+int xgbe_platform_init(void)
+{
+ return platform_driver_register(&xgbe_driver);
+}
+
+void xgbe_platform_exit(void)
+{
+ platform_driver_unregister(&xgbe_driver);
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 5dd17dcea2f8..f52a9bd05bac 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -127,9 +127,10 @@
#include <linux/timecounter.h>
#include <linux/net_tstamp.h>
#include <net/dcbnl.h>
+#include <linux/completion.h>
#define XGBE_DRV_NAME "amd-xgbe"
-#define XGBE_DRV_VERSION "1.0.2"
+#define XGBE_DRV_VERSION "1.0.3"
#define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver"
/* Descriptor related defines */
@@ -158,7 +159,8 @@
#define XGBE_MAX_DMA_CHANNELS 16
#define XGBE_MAX_QUEUES 16
-#define XGBE_DMA_STOP_TIMEOUT 5
+#define XGBE_PRIORITY_QUEUES 8
+#define XGBE_DMA_STOP_TIMEOUT 1
/* DMA cache settings - Outer sharable, write-back, write-allocate */
#define XGBE_DMA_OS_AXDOMAIN 0x2
@@ -170,6 +172,10 @@
#define XGBE_DMA_SYS_ARCACHE 0x0
#define XGBE_DMA_SYS_AWCACHE 0x0
+/* DMA channel interrupt modes */
+#define XGBE_IRQ_MODE_EDGE 0
+#define XGBE_IRQ_MODE_LEVEL 1
+
#define XGBE_DMA_INTERRUPT_MASK 0x31c7
#define XGMAC_MIN_PACKET 60
@@ -177,18 +183,19 @@
#define XGMAC_MAX_STD_PACKET 1518
#define XGMAC_JUMBO_PACKET_MTU 9000
#define XGMAC_MAX_JUMBO_PACKET 9018
+#define XGMAC_ETH_PREAMBLE (12 + 8) /* Inter-frame gap + preamble */
+
+#define XGMAC_PFC_DATA_LEN 46
+#define XGMAC_PFC_DELAYS 14000
+
+#define XGMAC_PRIO_QUEUES(_cnt) \
+ min_t(unsigned int, IEEE_8021QAZ_MAX_TCS, (_cnt))
/* Common property names */
#define XGBE_MAC_ADDR_PROPERTY "mac-address"
#define XGBE_PHY_MODE_PROPERTY "phy-mode"
#define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt"
#define XGBE_SPEEDSET_PROPERTY "amd,speed-set"
-#define XGBE_BLWC_PROPERTY "amd,serdes-blwc"
-#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate"
-#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
-#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp"
-#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
-#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
/* Device-tree clock names */
#define XGBE_DMA_CLOCK "dma_clk"
@@ -198,6 +205,20 @@
#define XGBE_ACPI_DMA_FREQ "amd,dma-freq"
#define XGBE_ACPI_PTP_FREQ "amd,ptp-freq"
+/* PCI BAR mapping */
+#define XGBE_XGMAC_BAR 0
+#define XGBE_XPCS_BAR 1
+#define XGBE_MAC_PROP_OFFSET 0x1d000
+#define XGBE_I2C_CTRL_OFFSET 0x1e000
+
+/* PCI MSIx support */
+#define XGBE_MSIX_BASE_COUNT 4
+#define XGBE_MSIX_MIN_COUNT (XGBE_MSIX_BASE_COUNT + 1)
+
+/* PCI clock frequencies */
+#define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */
+#define XGBE_V2_PTP_CLOCK_FREQ 125000000 /* 125 MHz */
+
/* Timestamp support - values based on 50MHz PTP clock
* 50MHz => 20 nsec
*/
@@ -208,7 +229,12 @@
#define XGMAC_DRIVER_CONTEXT 1
#define XGMAC_IOCTL_CONTEXT 2
-#define XGBE_FIFO_MAX 81920
+#define XGMAC_FIFO_MIN_ALLOC 2048
+#define XGMAC_FIFO_UNIT 256
+#define XGMAC_FIFO_ALIGN(_x) \
+ (((_x) + XGMAC_FIFO_UNIT - 1) & ~(XGMAC_FIFO_UNIT - 1))
+#define XGMAC_FIFO_FC_OFF 2048
+#define XGMAC_FIFO_FC_MIN 4096
#define XGBE_TC_MIN_QUANTUM 10
@@ -233,6 +259,14 @@
/* Flow control queue count */
#define XGMAC_MAX_FLOW_CONTROL_QUEUES 8
+/* Flow control threshold units */
+#define XGMAC_FLOW_CONTROL_UNIT 512
+#define XGMAC_FLOW_CONTROL_ALIGN(_x) \
+ (((_x) + XGMAC_FLOW_CONTROL_UNIT - 1) & ~(XGMAC_FLOW_CONTROL_UNIT - 1))
+#define XGMAC_FLOW_CONTROL_VALUE(_x) \
+ (((_x) < 1024) ? 0 : ((_x) / XGMAC_FLOW_CONTROL_UNIT) - 2)
+#define XGMAC_FLOW_CONTROL_MAX 33280
+
/* Maximum MAC address hash table size (256 bits = 8 bytes) */
#define XGBE_MAC_HASH_TABLE_SIZE 8
@@ -244,46 +278,19 @@
/* Auto-negotiation */
#define XGBE_AN_MS_TIMEOUT 500
-#define XGBE_LINK_TIMEOUT 10
-
-#define XGBE_AN_INT_CMPLT 0x01
-#define XGBE_AN_INC_LINK 0x02
-#define XGBE_AN_PG_RCV 0x04
-#define XGBE_AN_INT_MASK 0x07
-
-/* Rate-change complete wait/retry count */
-#define XGBE_RATECHANGE_COUNT 500
-
-/* Default SerDes settings */
-#define XGBE_SPEED_10000_BLWC 0
-#define XGBE_SPEED_10000_CDR 0x7
-#define XGBE_SPEED_10000_PLL 0x1
-#define XGBE_SPEED_10000_PQ 0x12
-#define XGBE_SPEED_10000_RATE 0x0
-#define XGBE_SPEED_10000_TXAMP 0xa
-#define XGBE_SPEED_10000_WORD 0x7
-#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1
-#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f
-
-#define XGBE_SPEED_2500_BLWC 1
-#define XGBE_SPEED_2500_CDR 0x2
-#define XGBE_SPEED_2500_PLL 0x0
-#define XGBE_SPEED_2500_PQ 0xa
-#define XGBE_SPEED_2500_RATE 0x1
-#define XGBE_SPEED_2500_TXAMP 0xf
-#define XGBE_SPEED_2500_WORD 0x1
-#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3
-#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0
-
-#define XGBE_SPEED_1000_BLWC 1
-#define XGBE_SPEED_1000_CDR 0x2
-#define XGBE_SPEED_1000_PLL 0x0
-#define XGBE_SPEED_1000_PQ 0xa
-#define XGBE_SPEED_1000_RATE 0x3
-#define XGBE_SPEED_1000_TXAMP 0xf
-#define XGBE_SPEED_1000_WORD 0x1
-#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3
-#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0
+#define XGBE_LINK_TIMEOUT 5
+
+#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
+#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
+#define XGBE_SGMII_AN_LINK_SPEED_100 0x04
+#define XGBE_SGMII_AN_LINK_SPEED_1000 0x08
+#define XGBE_SGMII_AN_LINK_DUPLEX BIT(4)
+
+/* ECC correctable error notification window (seconds) */
+#define XGBE_ECC_LIMIT 60
+
+/* MDIO port types */
+#define XGMAC_MAX_C22_PORT 3
struct xgbe_prv_data;
@@ -461,6 +468,7 @@ enum xgbe_state {
XGBE_DOWN,
XGBE_LINK_INIT,
XGBE_LINK_ERR,
+ XGBE_STOPPED,
};
enum xgbe_int {
@@ -480,6 +488,12 @@ enum xgbe_int_state {
XGMAC_INT_STATE_RESTORE,
};
+enum xgbe_ecc_sec {
+ XGBE_ECC_SEC_TX,
+ XGBE_ECC_SEC_RX,
+ XGBE_ECC_SEC_DESC,
+};
+
enum xgbe_speed {
XGBE_SPEED_1000 = 0,
XGBE_SPEED_2500,
@@ -487,6 +501,19 @@ enum xgbe_speed {
XGBE_SPEEDS,
};
+enum xgbe_xpcs_access {
+ XGBE_XPCS_ACCESS_V1 = 0,
+ XGBE_XPCS_ACCESS_V2,
+};
+
+enum xgbe_an_mode {
+ XGBE_AN_MODE_CL73 = 0,
+ XGBE_AN_MODE_CL73_REDRV,
+ XGBE_AN_MODE_CL37,
+ XGBE_AN_MODE_CL37_SGMII,
+ XGBE_AN_MODE_NONE,
+};
+
enum xgbe_an {
XGBE_AN_READY = 0,
XGBE_AN_PAGE_RECEIVED,
@@ -504,8 +531,14 @@ enum xgbe_rx {
};
enum xgbe_mode {
- XGBE_MODE_KR = 0,
- XGBE_MODE_KX,
+ XGBE_MODE_KX_1000 = 0,
+ XGBE_MODE_KX_2500,
+ XGBE_MODE_KR,
+ XGBE_MODE_X,
+ XGBE_MODE_SGMII_100,
+ XGBE_MODE_SGMII_1000,
+ XGBE_MODE_SFI,
+ XGBE_MODE_UNKNOWN,
};
enum xgbe_speedset {
@@ -513,6 +546,12 @@ enum xgbe_speedset {
XGBE_SPEEDSET_2500_10000,
};
+enum xgbe_mdio_mode {
+ XGBE_MDIO_MODE_NONE = 0,
+ XGBE_MDIO_MODE_CL22,
+ XGBE_MDIO_MODE_CL45,
+};
+
struct xgbe_phy {
u32 supported;
u32 advertising;
@@ -531,6 +570,43 @@ struct xgbe_phy {
int rx_pause;
};
+enum xgbe_i2c_cmd {
+ XGBE_I2C_CMD_READ = 0,
+ XGBE_I2C_CMD_WRITE,
+};
+
+struct xgbe_i2c_op {
+ enum xgbe_i2c_cmd cmd;
+
+ unsigned int target;
+
+ void *buf;
+ unsigned int len;
+};
+
+struct xgbe_i2c_op_state {
+ struct xgbe_i2c_op *op;
+
+ unsigned int tx_len;
+ unsigned char *tx_buf;
+
+ unsigned int rx_len;
+ unsigned char *rx_buf;
+
+ unsigned int tx_abort_source;
+
+ int ret;
+};
+
+struct xgbe_i2c {
+ unsigned int started;
+ unsigned int max_speed_mode;
+ unsigned int rx_fifo_size;
+ unsigned int tx_fifo_size;
+
+ struct xgbe_i2c_op_state op_state;
+};
+
struct xgbe_mmc_stats {
/* Tx Stats */
u64 txoctetcount_gb;
@@ -601,9 +677,15 @@ struct xgbe_hw_if {
int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
- int (*set_gmii_speed)(struct xgbe_prv_data *);
- int (*set_gmii_2500_speed)(struct xgbe_prv_data *);
- int (*set_xgmii_speed)(struct xgbe_prv_data *);
+ int (*set_speed)(struct xgbe_prv_data *, int);
+
+ int (*set_ext_mii_mode)(struct xgbe_prv_data *, unsigned int,
+ enum xgbe_mdio_mode);
+ int (*read_ext_mii_regs)(struct xgbe_prv_data *, int, int);
+ int (*write_ext_mii_regs)(struct xgbe_prv_data *, int, int, u16);
+
+ int (*set_gpio)(struct xgbe_prv_data *, unsigned int);
+ int (*clr_gpio)(struct xgbe_prv_data *, unsigned int);
void (*enable_tx)(struct xgbe_prv_data *);
void (*disable_tx)(struct xgbe_prv_data *);
@@ -682,11 +764,65 @@ struct xgbe_hw_if {
int (*disable_rss)(struct xgbe_prv_data *);
int (*set_rss_hash_key)(struct xgbe_prv_data *, const u8 *);
int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
+
+ /* For ECC */
+ void (*disable_ecc_ded)(struct xgbe_prv_data *);
+ void (*disable_ecc_sec)(struct xgbe_prv_data *, enum xgbe_ecc_sec);
+};
+
+/* This structure represents implementation specific routines for an
+ * implementation of a PHY. All routines are required unless noted below.
+ * Optional routines:
+ * kr_training_pre, kr_training_post
+ */
+struct xgbe_phy_impl_if {
+ /* Perform Setup/teardown actions */
+ int (*init)(struct xgbe_prv_data *);
+ void (*exit)(struct xgbe_prv_data *);
+
+ /* Perform start/stop specific actions */
+ int (*reset)(struct xgbe_prv_data *);
+ int (*start)(struct xgbe_prv_data *);
+ void (*stop)(struct xgbe_prv_data *);
+
+ /* Return the link status */
+ int (*link_status)(struct xgbe_prv_data *, int *);
+
+ /* Indicate if a particular speed is valid */
+ bool (*valid_speed)(struct xgbe_prv_data *, int);
+
+ /* Check if the specified mode can/should be used */
+ bool (*use_mode)(struct xgbe_prv_data *, enum xgbe_mode);
+ /* Switch the PHY into various modes */
+ void (*set_mode)(struct xgbe_prv_data *, enum xgbe_mode);
+ /* Retrieve mode needed for a specific speed */
+ enum xgbe_mode (*get_mode)(struct xgbe_prv_data *, int);
+ /* Retrieve new/next mode when trying to auto-negotiate */
+ enum xgbe_mode (*switch_mode)(struct xgbe_prv_data *);
+ /* Retrieve current mode */
+ enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *);
+
+ /* Retrieve current auto-negotiation mode */
+ enum xgbe_an_mode (*an_mode)(struct xgbe_prv_data *);
+
+ /* Configure auto-negotiation settings */
+ int (*an_config)(struct xgbe_prv_data *);
+
+ /* Set/override auto-negotiation advertisement settings */
+ unsigned int (*an_advertising)(struct xgbe_prv_data *);
+
+ /* Process results of auto-negotiation */
+ enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
+
+ /* Pre/Post KR training enablement support */
+ void (*kr_training_pre)(struct xgbe_prv_data *);
+ void (*kr_training_post)(struct xgbe_prv_data *);
};
struct xgbe_phy_if {
- /* For initial PHY setup */
- void (*phy_init)(struct xgbe_prv_data *);
+ /* For PHY setup/teardown */
+ int (*phy_init)(struct xgbe_prv_data *);
+ void (*phy_exit)(struct xgbe_prv_data *);
/* For PHY support when setting device up/down */
int (*phy_reset)(struct xgbe_prv_data *);
@@ -696,6 +832,30 @@ struct xgbe_phy_if {
/* For PHY support while device is up */
void (*phy_status)(struct xgbe_prv_data *);
int (*phy_config_aneg)(struct xgbe_prv_data *);
+
+ /* For PHY settings validation */
+ bool (*phy_valid_speed)(struct xgbe_prv_data *, int);
+
+ /* For single interrupt support */
+ irqreturn_t (*an_isr)(int, struct xgbe_prv_data *);
+
+ /* PHY implementation specific services */
+ struct xgbe_phy_impl_if phy_impl;
+};
+
+struct xgbe_i2c_if {
+ /* For initial I2C setup */
+ int (*i2c_init)(struct xgbe_prv_data *);
+
+ /* For I2C support when setting device up/down */
+ int (*i2c_start)(struct xgbe_prv_data *);
+ void (*i2c_stop)(struct xgbe_prv_data *);
+
+ /* For performing I2C operations */
+ int (*i2c_xfer)(struct xgbe_prv_data *, struct xgbe_i2c_op *);
+
+ /* For single interrupt support */
+ irqreturn_t (*i2c_isr)(int, struct xgbe_prv_data *);
};
struct xgbe_desc_if {
@@ -755,11 +915,28 @@ struct xgbe_hw_features {
unsigned int aux_snap_num; /* Number of Aux snapshot inputs */
};
+struct xgbe_version_data {
+ void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
+ enum xgbe_xpcs_access xpcs_access;
+ unsigned int mmc_64bit;
+ unsigned int tx_max_fifo_size;
+ unsigned int rx_max_fifo_size;
+ unsigned int tx_tstamp_workaround;
+ unsigned int ecc_support;
+ unsigned int i2c_support;
+};
+
struct xgbe_prv_data {
struct net_device *netdev;
- struct platform_device *pdev;
+ struct pci_dev *pcidev;
+ struct platform_device *platdev;
struct acpi_device *adev;
struct device *dev;
+ struct platform_device *phy_platdev;
+ struct device *phy_dev;
+
+ /* Version related data */
+ struct xgbe_version_data *vdata;
/* ACPI or DT flag */
unsigned int use_acpi;
@@ -770,12 +947,17 @@ struct xgbe_prv_data {
void __iomem *rxtx_regs; /* SerDes Rx/Tx CSRs */
void __iomem *sir0_regs; /* SerDes integration registers (1/2) */
void __iomem *sir1_regs; /* SerDes integration registers (2/2) */
+ void __iomem *xprop_regs; /* XGBE property registers */
+ void __iomem *xi2c_regs; /* XGBE I2C CSRs */
/* Overall device lock */
spinlock_t lock;
/* XPCS indirect addressing lock */
spinlock_t xpcs_lock;
+ unsigned int xpcs_window;
+ unsigned int xpcs_window_size;
+ unsigned int xpcs_window_mask;
/* RSS addressing mutex */
struct mutex rss_mutex;
@@ -783,12 +965,39 @@ struct xgbe_prv_data {
/* Flags representing xgbe_state */
unsigned long dev_state;
+ /* ECC support */
+ unsigned long tx_sec_period;
+ unsigned long tx_ded_period;
+ unsigned long rx_sec_period;
+ unsigned long rx_ded_period;
+ unsigned long desc_sec_period;
+ unsigned long desc_ded_period;
+
+ unsigned int tx_sec_count;
+ unsigned int tx_ded_count;
+ unsigned int rx_sec_count;
+ unsigned int rx_ded_count;
+ unsigned int desc_ded_count;
+ unsigned int desc_sec_count;
+
+ struct msix_entry *msix_entries;
int dev_irq;
+ int ecc_irq;
+ int i2c_irq;
+ int channel_irq[XGBE_MAX_DMA_CHANNELS];
+
unsigned int per_channel_irq;
+ unsigned int irq_shared;
+ unsigned int irq_count;
+ unsigned int channel_irq_count;
+ unsigned int channel_irq_mode;
+
+ char ecc_name[IFNAMSIZ + 32];
struct xgbe_hw_if hw_if;
struct xgbe_phy_if phy_if;
struct xgbe_desc_if desc_if;
+ struct xgbe_i2c_if i2c_if;
/* AXI DMA settings */
unsigned int coherent;
@@ -803,12 +1012,16 @@ struct xgbe_prv_data {
/* Rings for Tx/Rx on a DMA channel */
struct xgbe_channel *channel;
+ unsigned int tx_max_channel_count;
+ unsigned int rx_max_channel_count;
unsigned int channel_count;
unsigned int tx_ring_count;
unsigned int tx_desc_count;
unsigned int rx_ring_count;
unsigned int rx_desc_count;
+ unsigned int tx_max_q_count;
+ unsigned int rx_max_q_count;
unsigned int tx_q_count;
unsigned int rx_q_count;
@@ -820,11 +1033,13 @@ struct xgbe_prv_data {
unsigned int tx_threshold;
unsigned int tx_pbl;
unsigned int tx_osp_mode;
+ unsigned int tx_max_fifo_size;
/* Rx settings */
unsigned int rx_sf_mode;
unsigned int rx_threshold;
unsigned int rx_pbl;
+ unsigned int rx_max_fifo_size;
/* Tx coalescing settings */
unsigned int tx_usecs;
@@ -842,6 +1057,8 @@ struct xgbe_prv_data {
unsigned int pause_autoneg;
unsigned int tx_pause;
unsigned int rx_pause;
+ unsigned int rx_rfa[XGBE_MAX_QUEUES];
+ unsigned int rx_rfd[XGBE_MAX_QUEUES];
/* Receive Side Scaling settings */
u8 rss_key[XGBE_RSS_HASH_KEY_SIZE];
@@ -881,13 +1098,16 @@ struct xgbe_prv_data {
struct ieee_pfc *pfc;
unsigned int q2tc_map[XGBE_MAX_QUEUES];
unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS];
+ unsigned int pfcq[XGBE_MAX_QUEUES];
+ unsigned int pfc_rfa;
u8 num_tcs;
/* Hardware features of the device */
struct xgbe_hw_features hw_feat;
- /* Device restart work structure */
+ /* Device work structures */
struct work_struct restart_work;
+ struct work_struct stopdev_work;
/* Keeps track of power mode */
unsigned int power_down;
@@ -901,9 +1121,14 @@ struct xgbe_prv_data {
int phy_speed;
/* MDIO/PHY related settings */
+ unsigned int phy_started;
+ void *phy_data;
struct xgbe_phy phy;
int mdio_mmd;
unsigned long link_check;
+ struct completion mdio_complete;
+
+ unsigned int kr_redrv;
char an_name[IFNAMSIZ + 32];
struct workqueue_struct *an_workqueue;
@@ -911,23 +1136,9 @@ struct xgbe_prv_data {
int an_irq;
struct work_struct an_irq_work;
- unsigned int speed_set;
-
- /* SerDes UEFI configurable settings.
- * Switching between modes/speeds requires new values for some
- * SerDes settings. The values can be supplied as device
- * properties in array format. The first array entry is for
- * 1GbE, second for 2.5GbE and third for 10GbE
- */
- u32 serdes_blwc[XGBE_SPEEDS];
- u32 serdes_cdr_rate[XGBE_SPEEDS];
- u32 serdes_pq_skew[XGBE_SPEEDS];
- u32 serdes_tx_amp[XGBE_SPEEDS];
- u32 serdes_dfe_tap_cfg[XGBE_SPEEDS];
- u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
-
/* Auto-negotiation state machine support */
unsigned int an_int;
+ unsigned int an_status;
struct mutex an_mutex;
enum xgbe_an an_result;
enum xgbe_an an_state;
@@ -938,6 +1149,13 @@ struct xgbe_prv_data {
unsigned int parallel_detect;
unsigned int fec_ability;
unsigned long an_start;
+ enum xgbe_an_mode an_mode;
+
+ /* I2C support */
+ struct xgbe_i2c i2c;
+ struct mutex i2c_mutex;
+ struct completion i2c_complete;
+ char i2c_name[IFNAMSIZ + 32];
unsigned int lpm_ctrl; /* CTRL1 for resume */
@@ -948,14 +1166,36 @@ struct xgbe_prv_data {
unsigned int debugfs_xpcs_mmd;
unsigned int debugfs_xpcs_reg;
+
+ unsigned int debugfs_xprop_reg;
+
+ unsigned int debugfs_xi2c_reg;
#endif
};
/* Function prototypes*/
+struct xgbe_prv_data *xgbe_alloc_pdata(struct device *);
+void xgbe_free_pdata(struct xgbe_prv_data *);
+void xgbe_set_counts(struct xgbe_prv_data *);
+int xgbe_config_netdev(struct xgbe_prv_data *);
+void xgbe_deconfig_netdev(struct xgbe_prv_data *);
+
+int xgbe_platform_init(void);
+void xgbe_platform_exit(void);
+#ifdef CONFIG_PCI
+int xgbe_pci_init(void);
+void xgbe_pci_exit(void);
+#else
+static inline int xgbe_pci_init(void) { return 0; }
+static inline void xgbe_pci_exit(void) { }
+#endif
void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *);
+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *);
+void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *);
void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
+void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *);
const struct net_device_ops *xgbe_get_netdev_ops(void);
const struct ethtool_ops *xgbe_get_ethtool_ops(void);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 23d72af83d82..e1a51d8892fc 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -52,6 +52,7 @@ static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
{
buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
+ SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) |
SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
@@ -78,10 +79,10 @@ static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf)
}
}
-static void xgene_cle_dn_to_hw(struct xgene_cle_ptree_ewdn *dn,
+static void xgene_cle_dn_to_hw(const struct xgene_cle_ptree_ewdn *dn,
u32 *buf, u32 jb)
{
- struct xgene_cle_ptree_branch *br;
+ const struct xgene_cle_ptree_branch *br;
u32 i, j = 0;
u32 npp;
@@ -204,17 +205,385 @@ static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata,
return 0;
}
+static const struct xgene_cle_ptree_ewdn xgene_init_ptree_dn[] = {
+ {
+ /* PKT_TYPE_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = NO_BYTE,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 2,
+ .branch = {
+ {
+ /* IPV4 */
+ .valid = 1,
+ .next_packet_pointer = 22,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = PKT_PROT_NODE,
+ .next_branch = 0,
+ .data = 0x8,
+ .mask = 0x0
+ },
+ {
+ .valid = 0,
+ .next_packet_pointer = 262,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = LAST_NODE,
+ .next_branch = 0,
+ .data = 0x0,
+ .mask = 0xffff
+ }
+ },
+ },
+ {
+ /* PKT_PROT_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = NO_BYTE,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 3,
+ .branch = {
+ {
+ /* TCP */
+ .valid = 1,
+ .next_packet_pointer = 26,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 0,
+ .data = 0x0600,
+ .mask = 0x00ff
+ },
+ {
+ /* UDP */
+ .valid = 1,
+ .next_packet_pointer = 26,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 0,
+ .data = 0x1100,
+ .mask = 0x00ff
+ },
+ {
+ .valid = 0,
+ .next_packet_pointer = 26,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 0,
+ .data = 0x0,
+ .mask = 0xffff
+ }
+ }
+ },
+ {
+ /* RSS_IPV4_TCP_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = BOTH_BYTES,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 6,
+ .branch = {
+ {
+ /* SRC IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 28,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 1,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* SRC IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 30,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 2,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 32,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 3,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 34,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 4,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP SRC Port */
+ .valid = 0,
+ .next_packet_pointer = 36,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_TCP_NODE,
+ .next_branch = 5,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP DST Port */
+ .valid = 0,
+ .next_packet_pointer = 256,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = LAST_NODE,
+ .next_branch = 0,
+ .data = 0x0,
+ .mask = 0xffff
+ }
+ }
+ },
+ {
+ /* RSS_IPV4_UDP_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = BOTH_BYTES,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 6,
+ .branch = {
+ {
+ /* SRC IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 28,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 1,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* SRC IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 30,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 2,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 32,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 3,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 34,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 4,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP SRC Port */
+ .valid = 0,
+ .next_packet_pointer = 36,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_UDP_NODE,
+ .next_branch = 5,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP DST Port */
+ .valid = 0,
+ .next_packet_pointer = 258,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = LAST_NODE,
+ .next_branch = 0,
+ .data = 0x0,
+ .mask = 0xffff
+ }
+ }
+ },
+ {
+ /* RSS_IPV4_OTHERS_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = BOTH_BYTES,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 6,
+ .branch = {
+ {
+ /* SRC IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 28,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 1,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* SRC IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 30,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 2,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B01 */
+ .valid = 0,
+ .next_packet_pointer = 32,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 3,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* DST IPV4 B23 */
+ .valid = 0,
+ .next_packet_pointer = 34,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 4,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP SRC Port */
+ .valid = 0,
+ .next_packet_pointer = 36,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = RSS_IPV4_OTHERS_NODE,
+ .next_branch = 5,
+ .data = 0x0,
+ .mask = 0xffff
+ },
+ {
+ /* TCP DST Port */
+ .valid = 0,
+ .next_packet_pointer = 260,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = LAST_NODE,
+ .next_branch = 0,
+ .data = 0x0,
+ .mask = 0xffff
+ }
+ }
+ },
+
+ {
+ /* LAST NODE */
+ .node_type = EWDN,
+ .last_node = 1,
+ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = NO_BYTE,
+ .result_pointer = DB_RES_DROP,
+ .num_branches = 1,
+ .branch = {
+ {
+ .valid = 0,
+ .next_packet_pointer = 0,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+ .next_node = MAX_NODES,
+ .next_branch = 0,
+ .data = 0,
+ .mask = 0xffff
+ }
+ }
+ }
+};
+
static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
struct xgene_enet_cle *cle)
{
struct xgene_cle_ptree *ptree = &cle->ptree;
- struct xgene_cle_ptree_ewdn *dn = ptree->dn;
+ const struct xgene_cle_ptree_ewdn *dn = xgene_init_ptree_dn;
+ int num_dn = ARRAY_SIZE(xgene_init_ptree_dn);
struct xgene_cle_ptree_kn *kn = ptree->kn;
u32 buf[CLE_DRAM_REGS];
int i, j, ret;
memset(buf, 0, sizeof(buf));
- for (i = 0; i < ptree->num_dn; i++) {
+ for (i = 0; i < num_dn; i++) {
xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes);
ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node,
PTREE_RAM, CLE_CMD_WR);
@@ -224,8 +593,8 @@ static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
/* continue node index for key node */
memset(buf, 0, sizeof(buf));
- for (j = i; j < (ptree->num_kn + ptree->num_dn); j++) {
- xgene_cle_kn_to_hw(&kn[j - ptree->num_dn], buf);
+ for (j = i; j < (ptree->num_kn + num_dn); j++) {
+ xgene_cle_kn_to_hw(&kn[j - num_dn], buf);
ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node,
PTREE_RAM, CLE_CMD_WR);
if (ret)
@@ -346,11 +715,15 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
idx = i % pdata->rxq_cnt;
pool_id = pdata->rx_ring[idx]->buf_pool->id;
- fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(pool_id);
dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
nfpsel = 0;
- idt_reg = 0;
+ if (pdata->rx_ring[idx]->page_pool) {
+ pool_id = pdata->rx_ring[idx]->page_pool->id;
+ nfpsel = xgene_enet_get_fpsel(pool_id);
+ }
+ idt_reg = 0;
xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg);
ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
RSS_IDT, CLE_CMD_WR);
@@ -400,320 +773,41 @@ static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata)
static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
{
struct xgene_enet_cle *enet_cle = &pdata->cle;
+ u32 def_qid, def_fpsel, def_nxtfpsel, pool_id;
struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
- struct xgene_cle_ptree_branch *br;
- u32 def_qid, def_fpsel, pool_id;
struct xgene_cle_ptree *ptree;
struct xgene_cle_ptree_kn kn;
int ret;
- struct xgene_cle_ptree_ewdn ptree_dn[] = {
- {
- /* PKT_TYPE_NODE */
- .node_type = EWDN,
- .last_node = 0,
- .hdr_len_store = 1,
- .hdr_extn = NO_BYTE,
- .byte_store = NO_BYTE,
- .search_byte_store = NO_BYTE,
- .result_pointer = DB_RES_DROP,
- .num_branches = 2,
- .branch = {
- {
- /* IPV4 */
- .valid = 1,
- .next_packet_pointer = 22,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = PKT_PROT_NODE,
- .next_branch = 0,
- .data = 0x8,
- .mask = 0x0
- },
- {
- .valid = 0,
- .next_packet_pointer = 262,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = LAST_NODE,
- .next_branch = 0,
- .data = 0x0,
- .mask = 0xffff
- }
- },
- },
- {
- /* PKT_PROT_NODE */
- .node_type = EWDN,
- .last_node = 0,
- .hdr_len_store = 1,
- .hdr_extn = NO_BYTE,
- .byte_store = NO_BYTE,
- .search_byte_store = NO_BYTE,
- .result_pointer = DB_RES_DROP,
- .num_branches = 3,
- .branch = {
- {
- /* TCP */
- .valid = 1,
- .next_packet_pointer = 26,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 0,
- .data = 0x0600,
- .mask = 0x00ff
- },
- {
- /* UDP */
- .valid = 1,
- .next_packet_pointer = 26,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 0,
- .data = 0x1100,
- .mask = 0x00ff
- },
- {
- .valid = 0,
- .next_packet_pointer = 260,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = LAST_NODE,
- .next_branch = 0,
- .data = 0x0,
- .mask = 0xffff
- }
- }
- },
- {
- /* RSS_IPV4_TCP_NODE */
- .node_type = EWDN,
- .last_node = 0,
- .hdr_len_store = 1,
- .hdr_extn = NO_BYTE,
- .byte_store = NO_BYTE,
- .search_byte_store = BOTH_BYTES,
- .result_pointer = DB_RES_DROP,
- .num_branches = 6,
- .branch = {
- {
- /* SRC IPV4 B01 */
- .valid = 0,
- .next_packet_pointer = 28,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 1,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* SRC IPV4 B23 */
- .valid = 0,
- .next_packet_pointer = 30,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 2,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* DST IPV4 B01 */
- .valid = 0,
- .next_packet_pointer = 32,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 3,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* DST IPV4 B23 */
- .valid = 0,
- .next_packet_pointer = 34,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 4,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* TCP SRC Port */
- .valid = 0,
- .next_packet_pointer = 36,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_TCP_NODE,
- .next_branch = 5,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* TCP DST Port */
- .valid = 0,
- .next_packet_pointer = 256,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = LAST_NODE,
- .next_branch = 0,
- .data = 0x0,
- .mask = 0xffff
- }
- }
- },
- {
- /* RSS_IPV4_UDP_NODE */
- .node_type = EWDN,
- .last_node = 0,
- .hdr_len_store = 1,
- .hdr_extn = NO_BYTE,
- .byte_store = NO_BYTE,
- .search_byte_store = BOTH_BYTES,
- .result_pointer = DB_RES_DROP,
- .num_branches = 6,
- .branch = {
- {
- /* SRC IPV4 B01 */
- .valid = 0,
- .next_packet_pointer = 28,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 1,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* SRC IPV4 B23 */
- .valid = 0,
- .next_packet_pointer = 30,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 2,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* DST IPV4 B01 */
- .valid = 0,
- .next_packet_pointer = 32,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 3,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* DST IPV4 B23 */
- .valid = 0,
- .next_packet_pointer = 34,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 4,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* TCP SRC Port */
- .valid = 0,
- .next_packet_pointer = 36,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = RSS_IPV4_UDP_NODE,
- .next_branch = 5,
- .data = 0x0,
- .mask = 0xffff
- },
- {
- /* TCP DST Port */
- .valid = 0,
- .next_packet_pointer = 258,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = LAST_NODE,
- .next_branch = 0,
- .data = 0x0,
- .mask = 0xffff
- }
- }
- },
- {
- /* LAST NODE */
- .node_type = EWDN,
- .last_node = 1,
- .hdr_len_store = 1,
- .hdr_extn = NO_BYTE,
- .byte_store = NO_BYTE,
- .search_byte_store = NO_BYTE,
- .result_pointer = DB_RES_DROP,
- .num_branches = 1,
- .branch = {
- {
- .valid = 0,
- .next_packet_pointer = 0,
- .jump_bw = JMP_FW,
- .jump_rel = JMP_ABS,
- .operation = EQT,
- .next_node = MAX_NODES,
- .next_branch = 0,
- .data = 0,
- .mask = 0xffff
- }
- }
- }
- };
+
+ if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+ return -EINVAL;
ptree = &enet_cle->ptree;
ptree->start_pkt = 12; /* Ethertype */
- if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
- ret = xgene_cle_setup_rss(pdata);
- if (ret) {
- netdev_err(pdata->ndev, "RSS initialization failed\n");
- return ret;
- }
- } else {
- br = &ptree_dn[PKT_PROT_NODE].branch[0];
- br->valid = 0;
- br->next_packet_pointer = 260;
- br->next_node = LAST_NODE;
- br->data = 0x0000;
- br->mask = 0xffff;
+
+ ret = xgene_cle_setup_rss(pdata);
+ if (ret) {
+ netdev_err(pdata->ndev, "RSS initialization failed\n");
+ return ret;
}
def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
pool_id = pdata->rx_ring[0]->buf_pool->id;
- def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+ def_fpsel = xgene_enet_get_fpsel(pool_id);
+ def_nxtfpsel = 0;
+ if (pdata->rx_ring[0]->page_pool) {
+ pool_id = pdata->rx_ring[0]->page_pool->id;
+ def_nxtfpsel = xgene_enet_get_fpsel(pool_id);
+ }
memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
+ dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_ACCEPT].dstqid = def_qid;
dbptr[DB_RES_ACCEPT].cle_priority = 1;
dbptr[DB_RES_DEF].fpsel = def_fpsel;
+ dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_DEF].dstqid = def_qid;
dbptr[DB_RES_DEF].cle_priority = 7;
xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF],
@@ -727,10 +821,8 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
kn.key[0].priority = 0;
kn.key[0].result_pointer = DB_RES_ACCEPT;
- ptree->dn = ptree_dn;
ptree->kn = &kn;
ptree->dbptr = dbptr;
- ptree->num_dn = MAX_NODES;
ptree->num_kn = 1;
ptree->num_dbptr = DB_MAX_PTRS;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
index 9ac9f8e145ec..18fe8d56082c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
@@ -91,6 +91,8 @@
#define CLE_DSTQIDH_LEN 5
#define CLE_FPSEL_POS 21
#define CLE_FPSEL_LEN 4
+#define CLE_NFPSEL_POS 17
+#define CLE_NFPSEL_LEN 4
#define CLE_PRIORITY_POS 5
#define CLE_PRIORITY_LEN 3
@@ -104,6 +106,7 @@ enum xgene_cle_ptree_nodes {
PKT_PROT_NODE,
RSS_IPV4_TCP_NODE,
RSS_IPV4_UDP_NODE,
+ RSS_IPV4_OTHERS_NODE,
LAST_NODE,
MAX_NODES
};
@@ -275,10 +278,8 @@ struct xgene_cle_dbptr {
};
struct xgene_cle_ptree {
- struct xgene_cle_ptree_ewdn *dn;
struct xgene_cle_ptree_kn *kn;
struct xgene_cle_dbptr *dbptr;
- u32 num_dn;
u32 num_kn;
u32 num_dbptr;
u32 start_node;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index d372d4235c81..28fdedc30b74 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -163,6 +163,74 @@ static void xgene_get_ethtool_stats(struct net_device *ndev,
*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
}
+static void xgene_get_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *pp)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+ pp->autoneg = pdata->pause_autoneg;
+ pp->tx_pause = pdata->tx_pause;
+ pp->rx_pause = pdata->rx_pause;
+}
+
+static int xgene_set_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *pp)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = ndev->phydev;
+ u32 oldadv, newadv;
+
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+ pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+ if (!phydev)
+ return -EINVAL;
+
+ if (!(phydev->supported & SUPPORTED_Pause) ||
+ (!(phydev->supported & SUPPORTED_Asym_Pause) &&
+ pp->rx_pause != pp->tx_pause))
+ return -EINVAL;
+
+ pdata->pause_autoneg = pp->autoneg;
+ pdata->tx_pause = pp->tx_pause;
+ pdata->rx_pause = pp->rx_pause;
+
+ oldadv = phydev->advertising;
+ newadv = oldadv & ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+
+ if (pp->rx_pause)
+ newadv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+
+ if (pp->tx_pause)
+ newadv ^= ADVERTISED_Asym_Pause;
+
+ if (oldadv ^ newadv) {
+ phydev->advertising = newadv;
+
+ if (phydev->autoneg)
+ return phy_start_aneg(phydev);
+
+ if (!pp->autoneg) {
+ pdata->mac_ops->flowctl_tx(pdata,
+ pdata->tx_pause);
+ pdata->mac_ops->flowctl_rx(pdata,
+ pdata->rx_pause);
+ }
+ }
+
+ } else {
+ if (pp->autoneg)
+ return -EINVAL;
+
+ pdata->tx_pause = pp->tx_pause;
+ pdata->rx_pause = pp->rx_pause;
+
+ pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
+ pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
+ }
+
+ return 0;
+}
+
static const struct ethtool_ops xgene_ethtool_ops = {
.get_drvinfo = xgene_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -171,6 +239,8 @@ static const struct ethtool_ops xgene_ethtool_ops = {
.get_ethtool_stats = xgene_get_ethtool_stats,
.get_link_ksettings = xgene_get_link_ksettings,
.set_link_ksettings = xgene_set_link_ksettings,
+ .get_pauseparam = xgene_get_pauseparam,
+ .set_pauseparam = xgene_set_pauseparam
};
void xgene_enet_set_ethtool_ops(struct net_device *ndev)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 5390ae89136c..06e681697c17 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -504,6 +504,56 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
}
+static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
+static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
+ bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, &data);
+
+ if (enable)
+ data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+ else
+ data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+
+ xgene_enet_wr_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, data);
+}
+
+static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+
+ if (enable)
+ data |= TX_FLOW_EN;
+ else
+ data &= ~TX_FLOW_EN;
+
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
+
+ pdata->mac_ops->enable_tx_pause(pdata, enable);
+}
+
+static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+
+ if (enable)
+ data |= RX_FLOW_EN;
+ else
+ data &= ~RX_FLOW_EN;
+
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
+}
+
static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
{
u32 value;
@@ -527,6 +577,17 @@ 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);
+ /* Configure HW pause frame generation */
+ xgene_enet_rd_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, &value);
+ value = (DEF_QUANTA << 16) | (value & 0xFFFF);
+ xgene_enet_wr_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, value);
+
+ xgene_enet_wr_csr(pdata, RXBUF_PAUSE_THRESH, DEF_PAUSE_THRES);
+ xgene_enet_wr_csr(pdata, RXBUF_PAUSE_OFF_THRESH, DEF_PAUSE_OFF_THRES);
+
+ xgene_gmac_flowctl_tx(pdata, pdata->tx_pause);
+ xgene_gmac_flowctl_rx(pdata, pdata->rx_pause);
+
/* Rx-Tx traffic resume */
xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
@@ -550,12 +611,14 @@ static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
}
static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
u32 cb;
- u32 fpsel;
+ u32 fpsel, nxtfpsel;
- fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
cb |= CFG_CLE_BYPASS_EN0;
@@ -565,6 +628,7 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
}
@@ -652,16 +716,14 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
@@ -671,24 +733,24 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = pdata->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < pdata->txq_cnt; i++) {
ring = pdata->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
@@ -698,6 +760,48 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
}
}
+static u32 xgene_enet_flowctrl_cfg(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = ndev->phydev;
+ u16 lcladv, rmtadv = 0;
+ u32 rx_pause, tx_pause;
+ u8 flowctl = 0;
+
+ if (!phydev->duplex || !pdata->pause_autoneg)
+ return 0;
+
+ if (pdata->tx_pause)
+ flowctl |= FLOW_CTRL_TX;
+
+ if (pdata->rx_pause)
+ flowctl |= FLOW_CTRL_RX;
+
+ lcladv = mii_advertise_flowctrl(flowctl);
+
+ if (phydev->pause)
+ rmtadv = LPA_PAUSE_CAP;
+
+ if (phydev->asym_pause)
+ rmtadv |= LPA_PAUSE_ASYM;
+
+ flowctl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+ tx_pause = !!(flowctl & FLOW_CTRL_TX);
+ rx_pause = !!(flowctl & FLOW_CTRL_RX);
+
+ if (tx_pause != pdata->tx_pause) {
+ pdata->tx_pause = tx_pause;
+ pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
+ }
+
+ if (rx_pause != pdata->rx_pause) {
+ pdata->rx_pause = rx_pause;
+ pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
+ }
+
+ return 0;
+}
+
static void xgene_enet_adjust_link(struct net_device *ndev)
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
@@ -712,6 +816,8 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
mac_ops->tx_enable(pdata);
phy_print_status(phydev);
}
+
+ xgene_enet_flowctrl_cfg(ndev);
} else {
mac_ops->rx_disable(pdata);
mac_ops->tx_disable(pdata);
@@ -785,6 +891,8 @@ int xgene_enet_phy_connect(struct net_device *ndev)
phy_dev->supported &= ~SUPPORTED_10baseT_Half &
~SUPPORTED_100baseT_Half &
~SUPPORTED_1000baseT_Half;
+ phy_dev->supported |= SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause;
phy_dev->advertising = phy_dev->supported;
return 0;
@@ -902,6 +1010,10 @@ const struct xgene_mac_ops xgene_gmac_ops = {
.tx_disable = xgene_gmac_tx_disable,
.set_speed = xgene_gmac_set_speed,
.set_mac_addr = xgene_gmac_set_mac_addr,
+ .set_framesize = xgene_enet_set_frame_size,
+ .enable_tx_pause = xgene_gmac_enable_tx_pause,
+ .flowctl_tx = xgene_gmac_flowctl_tx,
+ .flowctl_rx = xgene_gmac_flowctl_rx,
};
const struct xgene_port_ops xgene_gport_ops = {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 06e598c8bc16..5f83037bb96b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -165,10 +165,23 @@ enum xgene_enet_rm {
#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)
#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
+#define CFG_CLE_NXTFPSEL0_SET(dst, val) xgene_set_bits(dst, val, 20, 4)
#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2)
#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
-#define CFG_CLE_DSTQID0(val) (val & GENMASK(11, 0))
-#define CFG_CLE_FPSEL0(val) ((val << 16) & GENMASK(19, 16))
+#define CFG_CLE_DSTQID0(val) ((val) & GENMASK(11, 0))
+#define CFG_CLE_FPSEL0(val) (((val) << 16) & GENMASK(19, 16))
+#define CSR_ECM_CFG_0_ADDR 0x0220
+#define CSR_ECM_CFG_1_ADDR 0x0224
+#define CSR_MULTI_DPF0_ADDR 0x0230
+#define RXBUF_PAUSE_THRESH 0x0534
+#define RXBUF_PAUSE_OFF_THRESH 0x0540
+#define DEF_PAUSE_THRES 0x7d
+#define DEF_PAUSE_OFF_THRES 0x6d
+#define DEF_QUANTA 0x8000
+#define NORM_PAUSE_OPCODE 0x0001
+#define PAUSE_XON_EN BIT(30)
+#define MULTI_DPF_AUTOCTRL BIT(28)
+#define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
#define ICM_CONFIG0_REG_0_ADDR 0x0400
#define ICM_CONFIG2_REG_0_ADDR 0x0410
#define RX_DV_GATE_REG_0_ADDR 0x05fc
@@ -196,6 +209,8 @@ enum xgene_enet_rm {
#define SOFT_RESET1 BIT(31)
#define TX_EN BIT(0)
#define RX_EN BIT(2)
+#define TX_FLOW_EN BIT(4)
+#define RX_FLOW_EN BIT(5)
#define ENET_LHD_MODE BIT(25)
#define ENET_GHD_MODE BIT(26)
#define FULL_DUPLEX2 BIT(0)
@@ -346,6 +361,14 @@ static inline bool xgene_enet_is_bufpool(u16 id)
return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
}
+static inline u8 xgene_enet_get_fpsel(u16 id)
+{
+ if (xgene_enet_is_bufpool(id))
+ return xgene_enet_ring_bufnum(id) - RING_BUFNUM_BUFPOOL;
+
+ return 0;
+}
+
static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
{
bool is_bufpool = xgene_enet_is_bufpool(id);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 8158d4698734..523b8eff6d7b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -37,6 +37,9 @@ static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
struct xgene_enet_raw_desc16 *raw_desc;
int i;
+ if (!buf_pool)
+ return;
+
for (i = 0; i < buf_pool->slots; i++) {
raw_desc = &buf_pool->raw_desc16[i];
@@ -47,6 +50,86 @@ static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
}
}
+static u16 xgene_enet_get_data_len(u64 bufdatalen)
+{
+ u16 hw_len, mask;
+
+ hw_len = GET_VAL(BUFDATALEN, bufdatalen);
+
+ if (unlikely(hw_len == 0x7800)) {
+ return 0;
+ } else if (!(hw_len & BIT(14))) {
+ mask = GENMASK(13, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_16K;
+ } else if (!(hw_len & GENMASK(13, 12))) {
+ mask = GENMASK(11, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_4K;
+ } else {
+ mask = GENMASK(11, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_2K;
+ }
+}
+
+static u16 xgene_enet_set_data_len(u32 size)
+{
+ u16 hw_len;
+
+ hw_len = (size == SIZE_4K) ? BIT(14) : 0;
+
+ return hw_len;
+}
+
+static int xgene_enet_refill_pagepool(struct xgene_enet_desc_ring *buf_pool,
+ u32 nbuf)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ struct xgene_enet_pdata *pdata;
+ struct net_device *ndev;
+ dma_addr_t dma_addr;
+ struct device *dev;
+ struct page *page;
+ u32 slots, tail;
+ u16 hw_len;
+ int i;
+
+ if (unlikely(!buf_pool))
+ return 0;
+
+ ndev = buf_pool->ndev;
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+ slots = buf_pool->slots - 1;
+ tail = buf_pool->tail;
+
+ for (i = 0; i < nbuf; i++) {
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ page = dev_alloc_page();
+ if (unlikely(!page))
+ return -ENOMEM;
+
+ dma_addr = dma_map_page(dev, page, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev, dma_addr))) {
+ put_page(page);
+ return -ENOMEM;
+ }
+
+ hw_len = xgene_enet_set_data_len(PAGE_SIZE);
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, hw_len) |
+ SET_BIT(COHERENT));
+
+ buf_pool->frag_page[tail] = page;
+ tail = (tail + 1) & slots;
+ }
+
+ pdata->ring_ops->wr_cmd(buf_pool, nbuf);
+ buf_pool->tail = tail;
+
+ return 0;
+}
+
static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
u32 nbuf)
{
@@ -64,8 +147,9 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
ndev = buf_pool->ndev;
dev = ndev_to_dev(buf_pool->ndev);
pdata = netdev_priv(ndev);
+
bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
- len = XGENE_ENET_MAX_MTU;
+ len = XGENE_ENET_STD_MTU;
for (i = 0; i < nbuf; i++) {
raw_desc = &buf_pool->raw_desc16[tail];
@@ -122,6 +206,25 @@ static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
}
}
+static void xgene_enet_delete_pagepool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct device *dev = ndev_to_dev(buf_pool->ndev);
+ dma_addr_t dma_addr;
+ struct page *page;
+ int i;
+
+ /* Free up the buffers held by hardware */
+ for (i = 0; i < buf_pool->slots; i++) {
+ page = buf_pool->frag_page[i];
+ if (page) {
+ dma_addr = buf_pool->frag_dma_addr[i];
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ put_page(page);
+ }
+ }
+}
+
static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
{
struct xgene_enet_desc_ring *rx_ring = data;
@@ -216,11 +319,11 @@ static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
}
}
- spin_unlock(&pdata->mss_lock);
-
/* No slots with ref_count = 0 available, return busy */
if (!mss_index_found)
- return -EBUSY;
+ mss_index = -EBUSY;
+
+ spin_unlock(&pdata->mss_lock);
return mss_index;
}
@@ -515,23 +618,67 @@ static void xgene_enet_skip_csum(struct sk_buff *skb)
}
}
+static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
+ struct xgene_enet_raw_desc *raw_desc,
+ struct xgene_enet_raw_desc *exp_desc)
+{
+ __le64 *desc = (void *)exp_desc;
+ dma_addr_t dma_addr;
+ struct device *dev;
+ struct page *page;
+ u16 slots, head;
+ u32 frag_size;
+ int i;
+
+ if (!buf_pool || !raw_desc || !exp_desc ||
+ (!GET_VAL(NV, le64_to_cpu(raw_desc->m0))))
+ return;
+
+ dev = ndev_to_dev(buf_pool->ndev);
+ slots = buf_pool->slots - 1;
+ head = buf_pool->head;
+
+ for (i = 0; i < 4; i++) {
+ frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+ if (!frag_size)
+ break;
+
+ dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ page = buf_pool->frag_page[head];
+ put_page(page);
+
+ buf_pool->frag_page[head] = NULL;
+ head = (head + 1) & slots;
+ }
+ buf_pool->head = head;
+}
+
static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
- struct xgene_enet_raw_desc *raw_desc)
+ struct xgene_enet_raw_desc *raw_desc,
+ struct xgene_enet_raw_desc *exp_desc)
{
+ struct xgene_enet_desc_ring *buf_pool, *page_pool;
+ u32 datalen, frag_size, skb_index;
struct net_device *ndev;
- struct device *dev;
- struct xgene_enet_desc_ring *buf_pool;
- u32 datalen, skb_index;
+ dma_addr_t dma_addr;
struct sk_buff *skb;
+ struct device *dev;
+ struct page *page;
+ u16 slots, head;
+ int i, ret = 0;
+ __le64 *desc;
u8 status;
- int ret = 0;
+ bool nv;
ndev = rx_ring->ndev;
dev = ndev_to_dev(rx_ring->ndev);
buf_pool = rx_ring->buf_pool;
+ page_pool = rx_ring->page_pool;
dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
- XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+ XGENE_ENET_STD_MTU, DMA_FROM_DEVICE);
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
skb = buf_pool->rx_skb[skb_index];
buf_pool->rx_skb[skb_index] = NULL;
@@ -541,6 +688,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) {
dev_kfree_skb_any(skb);
+ xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
status);
ret = -EIO;
@@ -548,11 +696,44 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
}
/* strip off CRC as HW isn't doing this */
- datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
- datalen = (datalen & DATALEN_MASK) - 4;
- prefetch(skb->data - NET_IP_ALIGN);
+ datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
+
+ nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
+ if (!nv)
+ datalen -= 4;
+
skb_put(skb, datalen);
+ prefetch(skb->data - NET_IP_ALIGN);
+
+ if (!nv)
+ goto skip_jumbo;
+ slots = page_pool->slots - 1;
+ head = page_pool->head;
+ desc = (void *)exp_desc;
+
+ for (i = 0; i < 4; i++) {
+ frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+ if (!frag_size)
+ break;
+
+ dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ page = page_pool->frag_page[head];
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0,
+ frag_size, PAGE_SIZE);
+
+ datalen += frag_size;
+
+ page_pool->frag_page[head] = NULL;
+ head = (head + 1) & slots;
+ }
+
+ page_pool->head = head;
+ rx_ring->npagepool -= skb_shinfo(skb)->nr_frags;
+
+skip_jumbo:
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, ndev);
if (likely((ndev->features & NETIF_F_IP_CSUM) &&
@@ -563,7 +744,15 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
rx_ring->rx_packets++;
rx_ring->rx_bytes += datalen;
napi_gro_receive(&rx_ring->napi, skb);
+
out:
+ if (rx_ring->npagepool <= 0) {
+ ret = xgene_enet_refill_pagepool(page_pool, NUM_NXTBUFPOOL);
+ rx_ring->npagepool = NUM_NXTBUFPOOL;
+ if (ret)
+ return ret;
+ }
+
if (--rx_ring->nbufpool == 0) {
ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
rx_ring->nbufpool = NUM_BUFPOOL;
@@ -611,7 +800,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
desc_count++;
}
if (is_rx_desc(raw_desc)) {
- ret = xgene_enet_rx_frame(ring, raw_desc);
+ ret = xgene_enet_rx_frame(ring, raw_desc, exp_desc);
} else {
ret = xgene_enet_tx_completion(ring, raw_desc);
is_completion = true;
@@ -854,7 +1043,7 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
{
- struct xgene_enet_desc_ring *buf_pool;
+ struct xgene_enet_desc_ring *buf_pool, *page_pool;
struct xgene_enet_desc_ring *ring;
int i;
@@ -867,18 +1056,28 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
xgene_enet_delete_ring(ring->cp_ring);
pdata->tx_ring[i] = NULL;
}
+
}
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i];
if (ring) {
+ page_pool = ring->page_pool;
+ if (page_pool) {
+ xgene_enet_delete_pagepool(page_pool);
+ xgene_enet_delete_ring(page_pool);
+ pdata->port_ops->clear(pdata, page_pool);
+ }
+
buf_pool = ring->buf_pool;
xgene_enet_delete_bufpool(buf_pool);
xgene_enet_delete_ring(buf_pool);
pdata->port_ops->clear(pdata, buf_pool);
+
xgene_enet_delete_ring(ring);
pdata->rx_ring[i] = NULL;
}
+
}
}
@@ -931,8 +1130,10 @@ static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
{
+ struct xgene_enet_desc_ring *page_pool;
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
+ void *p;
int i;
for (i = 0; i < pdata->txq_cnt; i++) {
@@ -940,10 +1141,13 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
if (ring) {
if (ring->cp_ring && ring->cp_ring->cp_skb)
devm_kfree(dev, ring->cp_ring->cp_skb);
+
if (ring->cp_ring && pdata->cq_cnt)
xgene_enet_free_desc_ring(ring->cp_ring);
+
xgene_enet_free_desc_ring(ring);
}
+
}
for (i = 0; i < pdata->rxq_cnt; i++) {
@@ -952,8 +1156,21 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
if (ring->buf_pool) {
if (ring->buf_pool->rx_skb)
devm_kfree(dev, ring->buf_pool->rx_skb);
+
xgene_enet_free_desc_ring(ring->buf_pool);
}
+
+ page_pool = ring->page_pool;
+ if (page_pool) {
+ p = page_pool->frag_page;
+ if (p)
+ devm_kfree(dev, p);
+
+ p = page_pool->frag_dma_addr;
+ if (p)
+ devm_kfree(dev, p);
+ }
+
xgene_enet_free_desc_ring(ring);
}
}
@@ -1071,19 +1288,20 @@ static u8 xgene_start_cpu_bufnum(struct xgene_enet_pdata *pdata)
static int xgene_enet_create_desc_rings(struct net_device *ndev)
{
- struct xgene_enet_pdata *pdata = netdev_priv(ndev);
- struct device *dev = ndev_to_dev(ndev);
struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_enet_desc_ring *page_pool = NULL;
struct xgene_enet_desc_ring *buf_pool = NULL;
- enum xgene_ring_owner owner;
- dma_addr_t dma_exp_bufs;
- u8 cpu_bufnum;
+ struct device *dev = ndev_to_dev(ndev);
u8 eth_bufnum = pdata->eth_bufnum;
u8 bp_bufnum = pdata->bp_bufnum;
u16 ring_num = pdata->ring_num;
+ enum xgene_ring_owner owner;
+ dma_addr_t dma_exp_bufs;
+ u16 ring_id, slots;
__le64 *exp_bufs;
- u16 ring_id;
int i, ret, size;
+ u8 cpu_bufnum;
cpu_bufnum = xgene_start_cpu_bufnum(pdata);
@@ -1103,7 +1321,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
owner = xgene_derive_ring_owner(pdata);
ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
- RING_CFGSIZE_2KB,
+ RING_CFGSIZE_16KB,
ring_id);
if (!buf_pool) {
ret = -ENOMEM;
@@ -1111,7 +1329,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
}
rx_ring->nbufpool = NUM_BUFPOOL;
- rx_ring->buf_pool = buf_pool;
+ rx_ring->npagepool = NUM_NXTBUFPOOL;
rx_ring->irq = pdata->irqs[i];
buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
sizeof(struct sk_buff *),
@@ -1124,6 +1342,42 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
rx_ring->buf_pool = buf_pool;
pdata->rx_ring[i] = rx_ring;
+
+ if ((pdata->enet_id == XGENE_ENET1 && pdata->rxq_cnt > 4) ||
+ (pdata->enet_id == XGENE_ENET2 && pdata->rxq_cnt > 16)) {
+ break;
+ }
+
+ /* allocate next buffer pool for jumbo packets */
+ owner = xgene_derive_ring_owner(pdata);
+ ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
+ page_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB,
+ ring_id);
+ if (!page_pool) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ slots = page_pool->slots;
+ page_pool->frag_page = devm_kcalloc(dev, slots,
+ sizeof(struct page *),
+ GFP_KERNEL);
+ if (!page_pool->frag_page) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ page_pool->frag_dma_addr = devm_kcalloc(dev, slots,
+ sizeof(dma_addr_t),
+ GFP_KERNEL);
+ if (!page_pool->frag_dma_addr) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ page_pool->dst_ring_num = xgene_enet_dst_ring_num(page_pool);
+ rx_ring->page_pool = page_pool;
}
for (i = 0; i < pdata->txq_cnt; i++) {
@@ -1247,13 +1501,31 @@ static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
return ret;
}
+static int xgene_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int frame_size;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ frame_size = (new_mtu > ETH_DATA_LEN) ? (new_mtu + 18) : 0x600;
+
+ xgene_enet_close(ndev);
+ ndev->mtu = new_mtu;
+ pdata->mac_ops->set_framesize(pdata, frame_size);
+ xgene_enet_open(ndev);
+
+ return 0;
+}
+
static const struct net_device_ops xgene_ndev_ops = {
.ndo_open = xgene_enet_open,
.ndo_stop = xgene_enet_close,
.ndo_start_xmit = xgene_enet_start_xmit,
.ndo_tx_timeout = xgene_enet_timeout,
.ndo_get_stats64 = xgene_enet_get_stats64,
- .ndo_change_mtu = eth_change_mtu,
+ .ndo_change_mtu = xgene_change_mtu,
.ndo_set_mac_address = xgene_enet_set_mac_address,
};
@@ -1382,9 +1654,13 @@ static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
- if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+ pdata->sfp_gpio_en = false;
+ if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII ||
+ (!device_property_present(dev, "sfp-gpios") &&
+ !device_property_present(dev, "rxlos-gpios")))
return;
+ pdata->sfp_gpio_en = true;
pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
if (IS_ERR(pdata->sfp_rdy))
pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
@@ -1515,10 +1791,12 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
{
struct xgene_enet_cle *enet_cle = &pdata->cle;
+ struct xgene_enet_desc_ring *page_pool;
struct net_device *ndev = pdata->ndev;
struct xgene_enet_desc_ring *buf_pool;
- u16 dst_ring_num;
+ u16 dst_ring_num, ring_id;
int i, ret;
+ u32 count;
ret = pdata->port_ops->reset(pdata);
if (ret)
@@ -1534,9 +1812,18 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
for (i = 0; i < pdata->rxq_cnt; i++) {
buf_pool = pdata->rx_ring[i]->buf_pool;
xgene_enet_init_bufpool(buf_pool);
- ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+ page_pool = pdata->rx_ring[i]->page_pool;
+ xgene_enet_init_bufpool(page_pool);
+
+ count = pdata->rx_buff_cnt;
+ ret = xgene_enet_refill_bufpool(buf_pool, count);
if (ret)
goto err;
+
+ ret = xgene_enet_refill_pagepool(page_pool, count);
+ if (ret)
+ goto err;
+
}
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
@@ -1555,10 +1842,17 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
netdev_err(ndev, "Preclass Tree init error\n");
goto err;
}
+
} else {
- pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
+ buf_pool = pdata->rx_ring[0]->buf_pool;
+ page_pool = pdata->rx_ring[0]->page_pool;
+ ring_id = (page_pool) ? page_pool->id : 0;
+ pdata->port_ops->cle_bypass(pdata, dst_ring_num,
+ buf_pool->id, ring_id);
}
+ ndev->max_mtu = XGENE_ENET_MAX_MTU;
pdata->phy_speed = SPEED_UNKNOWN;
pdata->mac_ops->init(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0cda58f5a840..52571741da9f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -41,11 +41,14 @@
#include "../../../phy/mdio-xgene.h"
#define XGENE_DRV_VERSION "v1.0"
-#define XGENE_ENET_MAX_MTU 1536
-#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MAX_MTU 9600
+#define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN)
+
#define BUFLEN_16K (16 * 1024)
-#define NUM_PKT_BUF 64
+#define NUM_PKT_BUF 1024
#define NUM_BUFPOOL 32
+#define NUM_NXTBUFPOOL 8
#define MAX_EXP_BUFFS 256
#define NUM_MSS_REG 4
#define XGENE_MIN_ENET_FRAME_SIZE 60
@@ -88,6 +91,12 @@ enum xgene_enet_id {
XGENE_ENET2
};
+enum xgene_enet_buf_len {
+ SIZE_2K = 2048,
+ SIZE_4K = 4096,
+ SIZE_16K = 16384
+};
+
/* software context of a descriptor ring */
struct xgene_enet_desc_ring {
struct net_device *ndev;
@@ -107,14 +116,18 @@ struct xgene_enet_desc_ring {
dma_addr_t irq_mbox_dma;
void *irq_mbox_addr;
u16 dst_ring_num;
- u8 nbufpool;
+ u16 nbufpool;
+ int npagepool;
u8 index;
+ u32 flags;
struct sk_buff *(*rx_skb);
struct sk_buff *(*cp_skb);
dma_addr_t *frag_dma_addr;
+ struct page *(*frag_page);
enum xgene_enet_ring_cfgsize cfgsize;
struct xgene_enet_desc_ring *cp_ring;
struct xgene_enet_desc_ring *buf_pool;
+ struct xgene_enet_desc_ring *page_pool;
struct napi_struct napi;
union {
void *desc_addr;
@@ -143,8 +156,12 @@ struct xgene_mac_ops {
void (*rx_disable)(struct xgene_enet_pdata *pdata);
void (*set_speed)(struct xgene_enet_pdata *pdata);
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
+ void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize);
void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
void (*link_state)(struct work_struct *work);
+ void (*enable_tx_pause)(struct xgene_enet_pdata *pdata, bool enable);
+ void (*flowctl_rx)(struct xgene_enet_pdata *pdata, bool enable);
+ void (*flowctl_tx)(struct xgene_enet_pdata *pdata, bool enable);
};
struct xgene_port_ops {
@@ -152,7 +169,7 @@ struct xgene_port_ops {
void (*clear)(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring);
void (*cle_bypass)(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id);
+ u32 dst_ring_num, u16 bufpool_id, u16 nxtbufpool_id);
void (*shutdown)(struct xgene_enet_pdata *pdata);
};
@@ -219,6 +236,10 @@ struct xgene_enet_pdata {
u8 rx_delay;
bool mdio_driver;
struct gpio_desc *sfp_rdy;
+ bool sfp_gpio_en;
+ u32 pause_autoneg;
+ bool tx_pause;
+ bool rx_pause;
};
struct xgene_indirect_ctl {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
index af51dd5844ce..4ff40559f970 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
@@ -119,6 +119,7 @@ static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
ring_id_buf |= PREFETCH_BUF_EN;
+
if (is_bufpool)
ring_id_buf |= IS_BUFFER_POOL;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index d12e9cbae820..a8e063bdee3b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -343,6 +343,11 @@ static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
xgene_enet_wr_mcx_csr(p, icm2_addr, icm2);
}
+static void xgene_sgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
static void xgene_sgmii_enable_autoneg(struct xgene_enet_pdata *p)
{
u32 data, loop = 10;
@@ -360,11 +365,39 @@ static void xgene_sgmii_enable_autoneg(struct xgene_enet_pdata *p)
netdev_err(p->ndev, "Auto-negotiation failed\n");
}
+static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
+{
+ u32 data;
+
+ data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
+
+ if (set)
+ data |= bits;
+ else
+ data &= ~bits;
+
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
+}
+
+static void xgene_sgmac_flowctl_tx(struct xgene_enet_pdata *p, bool enable)
+{
+ xgene_sgmac_rxtx(p, TX_FLOW_EN, enable);
+
+ p->mac_ops->enable_tx_pause(p, enable);
+}
+
+static void xgene_sgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+ xgene_sgmac_rxtx(pdata, RX_FLOW_EN, enable);
+}
+
static void xgene_sgmac_init(struct xgene_enet_pdata *p)
{
+ u32 pause_thres_reg, pause_off_thres_reg;
u32 enet_spare_cfg_reg, rsif_config_reg;
u32 cfg_bypass_reg, rx_dv_gate_reg;
- u32 data, offset;
+ u32 data, data1, data2, offset;
+ u32 multi_dpf_reg;
if (!(p->enet_id == XGENE_ENET2 && p->mdio_driver))
xgene_sgmac_reset(p);
@@ -400,24 +433,50 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
xgene_enet_wr_csr(p, rsif_config_reg, data);
- /* Bypass traffic gating */
- xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
- xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
- xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg, RESUME_RX0);
-}
+ /* Configure HW pause frame generation */
+ multi_dpf_reg = (p->enet_id == XGENE_ENET1) ? CSR_MULTI_DPF0_ADDR :
+ XG_MCX_MULTI_DPF0_ADDR;
+ data = xgene_enet_rd_mcx_csr(p, multi_dpf_reg);
+ data = (DEF_QUANTA << 16) | (data & 0xffff);
+ xgene_enet_wr_mcx_csr(p, multi_dpf_reg, data);
+
+ if (p->enet_id != XGENE_ENET1) {
+ data = xgene_enet_rd_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR);
+ data = (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
+ xgene_enet_wr_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR, data);
+ }
-static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
-{
- u32 data;
+ pause_thres_reg = (p->enet_id == XGENE_ENET1) ? RXBUF_PAUSE_THRESH :
+ XG_RXBUF_PAUSE_THRESH;
+ pause_off_thres_reg = (p->enet_id == XGENE_ENET1) ?
+ RXBUF_PAUSE_OFF_THRESH : 0;
- data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
+ if (p->enet_id == XGENE_ENET1) {
+ data1 = xgene_enet_rd_csr(p, pause_thres_reg);
+ data2 = xgene_enet_rd_csr(p, pause_off_thres_reg);
+
+ if (!(p->port_id % 2)) {
+ data1 = (data1 & 0xffff0000) | DEF_PAUSE_THRES;
+ data2 = (data2 & 0xffff0000) | DEF_PAUSE_OFF_THRES;
+ } else {
+ data1 = (data1 & 0xffff) | (DEF_PAUSE_THRES << 16);
+ data2 = (data2 & 0xffff) | (DEF_PAUSE_OFF_THRES << 16);
+ }
- if (set)
- data |= bits;
- else
- data &= ~bits;
+ xgene_enet_wr_csr(p, pause_thres_reg, data1);
+ xgene_enet_wr_csr(p, pause_off_thres_reg, data2);
+ } else {
+ data = (DEF_PAUSE_OFF_THRES << 16) | DEF_PAUSE_THRES;
+ xgene_enet_wr_csr(p, pause_thres_reg, data);
+ }
- xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
+ xgene_sgmac_flowctl_tx(p, p->tx_pause);
+ xgene_sgmac_flowctl_rx(p, p->rx_pause);
+
+ /* Bypass traffic gating */
+ xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
+ xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
+ xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg, RESUME_RX0);
}
static void xgene_sgmac_rx_enable(struct xgene_enet_pdata *p)
@@ -484,11 +543,12 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
}
static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
- u32 data, fpsel;
u32 cle_bypass_reg0, cle_bypass_reg1;
u32 offset = p->port_id * MAC_OFFSET;
+ u32 data, fpsel, nxtfpsel;
if (p->enet_id == XGENE_ENET1) {
cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR;
@@ -501,24 +561,24 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
data = CFG_CLE_BYPASS_EN0;
xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data);
- fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
- data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
+ data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel) |
+ CFG_CLE_NXTFPSEL0(nxtfpsel);
xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
}
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
@@ -528,24 +588,23 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
{
struct device *dev = &p->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < p->rxq_cnt; i++) {
ring = p->rx_ring[i]->buf_pool;
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = p->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < p->txq_cnt; i++) {
ring = p->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
@@ -586,6 +645,25 @@ static void xgene_enet_link_state(struct work_struct *work)
schedule_delayed_work(&p->link_work, poll_interval);
}
+static void xgene_sgmac_enable_tx_pause(struct xgene_enet_pdata *p, bool enable)
+{
+ u32 data, ecm_cfg_addr;
+
+ if (p->enet_id == XGENE_ENET1) {
+ ecm_cfg_addr = (!(p->port_id % 2)) ? CSR_ECM_CFG_0_ADDR :
+ CSR_ECM_CFG_1_ADDR;
+ } else {
+ ecm_cfg_addr = XG_MCX_ECM_CFG_0_ADDR;
+ }
+
+ data = xgene_enet_rd_mcx_csr(p, ecm_cfg_addr);
+ if (enable)
+ data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+ else
+ data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+ xgene_enet_wr_mcx_csr(p, ecm_cfg_addr, data);
+}
+
const struct xgene_mac_ops xgene_sgmac_ops = {
.init = xgene_sgmac_init,
.reset = xgene_sgmac_reset,
@@ -595,7 +673,11 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
.tx_disable = xgene_sgmac_tx_disable,
.set_speed = xgene_sgmac_set_speed,
.set_mac_addr = xgene_sgmac_set_mac_addr,
- .link_state = xgene_enet_link_state
+ .set_framesize = xgene_sgmac_set_frame_size,
+ .link_state = xgene_enet_link_state,
+ .enable_tx_pause = xgene_sgmac_enable_tx_pause,
+ .flowctl_tx = xgene_sgmac_flowctl_tx,
+ .flowctl_rx = xgene_sgmac_flowctl_rx
};
const struct xgene_port_ops xgene_sgport_ops = {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index 6475f383ba83..ece19e6d68e3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -101,6 +101,14 @@ static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata,
wr_addr);
}
+static void xgene_enet_wr_axg_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
u32 offset, u32 *val)
{
@@ -174,6 +182,14 @@ static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
return success;
}
+static void xgene_enet_rd_axg_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
{
struct net_device *ndev = pdata->ndev;
@@ -250,6 +266,12 @@ static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata,
xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, data);
}
+static void xgene_xgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR,
+ ((((size + 2) >> 2) << 16) | size));
+}
+
static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -259,6 +281,51 @@ static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
return data;
}
+static void xgene_xgmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
+ bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_axg_csr(pdata, XGENET_CSR_ECM_CFG_0_ADDR, &data);
+
+ if (enable)
+ data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+ else
+ data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+
+ xgene_enet_wr_axg_csr(pdata, XGENET_CSR_ECM_CFG_0_ADDR, data);
+}
+
+static void xgene_xgmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+
+ if (enable)
+ data |= HSTTCTLEN;
+ else
+ data &= ~HSTTCTLEN;
+
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+
+ pdata->mac_ops->enable_tx_pause(pdata, enable);
+}
+
+static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+
+ if (enable)
+ data |= HSTRCTLEN;
+ else
+ data &= ~HSTRCTLEN;
+
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+}
+
static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -282,6 +349,23 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
+
+ /* Configure HW pause frame generation */
+ xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, &data);
+ data = (DEF_QUANTA << 16) | (data & 0xFFFF);
+ xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, data);
+
+ if (pdata->enet_id != XGENE_ENET1) {
+ xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, &data);
+ data = (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
+ xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, data);
+ }
+
+ data = (XG_DEF_PAUSE_OFF_THRES << 16) | XG_DEF_PAUSE_THRES;
+ xgene_enet_wr_csr(pdata, XG_RXBUF_PAUSE_THRESH, data);
+
+ xgene_xgmac_flowctl_tx(pdata, pdata->tx_pause);
+ xgene_xgmac_flowctl_rx(pdata, pdata->rx_pause);
}
static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
@@ -350,44 +434,47 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
}
static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
- u32 cb, fpsel;
+ u32 cb, fpsel, nxtfpsel;
xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
cb |= CFG_CLE_BYPASS_EN0;
CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
- fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
+ pr_info("+ cle_bypass: fpsel: %d nxtfpsel: %d\n", fpsel, nxtfpsel);
}
static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = pdata->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < pdata->txq_cnt; i++) {
ring = pdata->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
@@ -400,31 +487,44 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
}
+static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+
+ pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
+ if (IS_ERR(pdata->sfp_rdy))
+ pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
+
+ if (IS_ERR(pdata->sfp_rdy))
+ return -ENODEV;
+
+ return 0;
+}
+
static void xgene_enet_link_state(struct work_struct *work)
{
struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
struct xgene_enet_pdata, link_work);
- struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
struct net_device *ndev = pdata->ndev;
u32 link_status, poll_interval;
link_status = xgene_enet_link_status(pdata);
- if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
+ if (pdata->sfp_gpio_en && link_status &&
+ (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) &&
+ !gpiod_get_value(pdata->sfp_rdy))
link_status = 0;
if (link_status) {
@@ -458,8 +558,12 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
.rx_disable = xgene_xgmac_rx_disable,
.tx_disable = xgene_xgmac_tx_disable,
.set_mac_addr = xgene_xgmac_set_mac_addr,
+ .set_framesize = xgene_xgmac_set_frame_size,
.set_mss = xgene_xgmac_set_mss,
- .link_state = xgene_enet_link_state
+ .link_state = xgene_enet_link_state,
+ .enable_tx_pause = xgene_xgmac_enable_tx_pause,
+ .flowctl_rx = xgene_xgmac_flowctl_rx,
+ .flowctl_tx = xgene_xgmac_flowctl_tx
};
const struct xgene_port_ops xgene_xgport_ops = {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
index 360ccbd95566..03b847ad8937 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -59,6 +59,11 @@
#define HSTMAXFRAME_LENGTH_ADDR 0x0020
#define XG_MCX_RX_DV_GATE_REG_0_ADDR 0x0004
+#define XG_MCX_ECM_CFG_0_ADDR 0x0074
+#define XG_MCX_MULTI_DPF0_ADDR 0x007c
+#define XG_MCX_MULTI_DPF1_ADDR 0x0080
+#define XG_DEF_PAUSE_THRES 0x390
+#define XG_DEF_PAUSE_OFF_THRES 0x2c0
#define XG_RSIF_CONFIG_REG_ADDR 0x00a0
#define XCLE_BYPASS_REG0_ADDR 0x0160
#define XCLE_BYPASS_REG1_ADDR 0x0164
@@ -70,6 +75,10 @@
#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
+#define XGENET_CSR_ECM_CFG_0_ADDR 0x0880
+#define XGENET_CSR_MULTI_DPF0_ADDR 0x0888
+#define XGENET_CSR_MULTI_DPF1_ADDR 0x088c
+#define XG_RXBUF_PAUSE_THRESH 0x0020
#define XG_MCX_ICM_CONFIG0_REG_0_ADDR 0x00e0
#define XG_MCX_ICM_CONFIG2_REG_0_ADDR 0x00e8
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
index a65d7a60f116..2b2d87089987 100644
--- a/drivers/net/ethernet/apple/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -1237,7 +1237,6 @@ static const struct net_device_ops bmac_netdev_ops = {
.ndo_start_xmit = bmac_output,
.ndo_set_rx_mode = bmac_set_multicast,
.ndo_set_mac_address = bmac_set_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
index e58a7c73766e..96dd5300e0e5 100644
--- a/drivers/net/ethernet/apple/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -102,7 +102,6 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_start_xmit = mace_xmit_start,
.ndo_set_rx_mode = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index 89914ca17a49..857df9c45f04 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -186,7 +186,6 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_tx_timeout = mace_tx_timeout,
.ndo_set_rx_mode = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig
index 689045186064..e743ddf46343 100644
--- a/drivers/net/ethernet/arc/Kconfig
+++ b/drivers/net/ethernet/arc/Kconfig
@@ -17,13 +17,14 @@ if NET_VENDOR_ARC
config ARC_EMAC_CORE
tristate
+ depends on ARC || ARCH_ROCKCHIP || COMPILE_TEST
select MII
select PHYLIB
config ARC_EMAC
tristate "ARC EMAC support"
select ARC_EMAC_CORE
- depends on OF_IRQ && OF_NET && HAS_DMA
+ depends on OF_IRQ && OF_NET && HAS_DMA && (ARC || COMPILE_TEST)
---help---
On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x
non-standard on-chip ethernet device ARC EMAC 10/100 is used.
@@ -32,7 +33,7 @@ config ARC_EMAC
config EMAC_ROCKCHIP
tristate "Rockchip EMAC support"
select ARC_EMAC_CORE
- depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA
+ depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA && (ARCH_ROCKCHIP || COMPILE_TEST)
---help---
Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers.
This selects Rockchip SoC glue layer support for the
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index be865b4dada2..abc9f2a59054 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -636,7 +636,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
if (unlikely(dma_mapping_error(&ndev->dev, addr))) {
stats->tx_dropped++;
stats->tx_errors++;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr);
diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h
index 6cac919272ea..d4a409139ea2 100644
--- a/drivers/net/ethernet/atheros/alx/alx.h
+++ b/drivers/net/ethernet/atheros/alx/alx.h
@@ -50,6 +50,10 @@ struct alx_buffer {
};
struct alx_rx_queue {
+ struct net_device *netdev;
+ struct device *dev;
+ struct alx_napi *np;
+
struct alx_rrd *rrd;
dma_addr_t rrd_dma;
@@ -58,16 +62,26 @@ struct alx_rx_queue {
struct alx_buffer *bufs;
+ u16 count;
u16 write_idx, read_idx;
u16 rrd_read_idx;
+ u16 queue_idx;
};
#define ALX_RX_ALLOC_THRESH 32
struct alx_tx_queue {
+ struct net_device *netdev;
+ struct device *dev;
+
struct alx_txd *tpd;
dma_addr_t tpd_dma;
+
struct alx_buffer *bufs;
+
+ u16 count;
u16 write_idx, read_idx;
+ u16 queue_idx;
+ u16 p_reg, c_reg;
};
#define ALX_DEFAULT_TX_WORK 128
@@ -76,6 +90,18 @@ enum alx_device_quirks {
ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0),
};
+struct alx_napi {
+ struct napi_struct napi;
+ struct alx_priv *alx;
+ struct alx_rx_queue *rxq;
+ struct alx_tx_queue *txq;
+ int vec_idx;
+ u32 vec_mask;
+ char irq_lbl[IFNAMSIZ + 8];
+};
+
+#define ALX_MAX_NAPIS 8
+
#define ALX_FLAG_USING_MSIX BIT(0)
#define ALX_FLAG_USING_MSI BIT(1)
@@ -87,7 +113,6 @@ struct alx_priv {
/* msi-x vectors */
int num_vec;
struct msix_entry *msix_entries;
- char irq_lbl[IFNAMSIZ + 8];
/* all descriptor memory */
struct {
@@ -96,6 +121,11 @@ struct alx_priv {
unsigned int size;
} descmem;
+ struct alx_napi *qnapi[ALX_MAX_NAPIS];
+ int num_txq;
+ int num_rxq;
+ int num_napi;
+
/* protect int_mask updates */
spinlock_t irq_lock;
u32 int_mask;
@@ -104,10 +134,6 @@ struct alx_priv {
unsigned int rx_ringsz;
unsigned int rxbuf_size;
- struct napi_struct napi;
- struct alx_tx_queue txq;
- struct alx_rx_queue rxq;
-
struct work_struct link_check_wk;
struct work_struct reset_wk;
diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c
index 08e22df2a300..2f4eabf652e8 100644
--- a/drivers/net/ethernet/atheros/alx/ethtool.c
+++ b/drivers/net/ethernet/atheros/alx/ethtool.c
@@ -125,64 +125,75 @@ static u32 alx_get_supported_speeds(struct alx_hw *hw)
return supported;
}
-static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int alx_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
+ u32 supported, advertising;
- ecmd->supported = SUPPORTED_Autoneg |
+ supported = SUPPORTED_Autoneg |
SUPPORTED_TP |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause;
if (alx_hw_giga(hw))
- ecmd->supported |= SUPPORTED_1000baseT_Full;
- ecmd->supported |= alx_get_supported_speeds(hw);
+ supported |= SUPPORTED_1000baseT_Full;
+ supported |= alx_get_supported_speeds(hw);
- ecmd->advertising = ADVERTISED_TP;
+ advertising = ADVERTISED_TP;
if (hw->adv_cfg & ADVERTISED_Autoneg)
- ecmd->advertising |= hw->adv_cfg;
+ advertising |= hw->adv_cfg;
- ecmd->port = PORT_TP;
- ecmd->phy_address = 0;
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = 0;
if (hw->adv_cfg & ADVERTISED_Autoneg)
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
else
- ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.autoneg = AUTONEG_DISABLE;
if (hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg) {
if (hw->flowctrl & ALX_FC_RX) {
- ecmd->advertising |= ADVERTISED_Pause;
+ advertising |= ADVERTISED_Pause;
if (!(hw->flowctrl & ALX_FC_TX))
- ecmd->advertising |= ADVERTISED_Asym_Pause;
+ advertising |= ADVERTISED_Asym_Pause;
} else if (hw->flowctrl & ALX_FC_TX) {
- ecmd->advertising |= ADVERTISED_Asym_Pause;
+ advertising |= ADVERTISED_Asym_Pause;
}
}
- ethtool_cmd_speed_set(ecmd, hw->link_speed);
- ecmd->duplex = hw->duplex;
+ cmd->base.speed = hw->link_speed;
+ cmd->base.duplex = hw->duplex;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
-static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int alx_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct alx_priv *alx = netdev_priv(netdev);
struct alx_hw *hw = &alx->hw;
u32 adv_cfg;
+ u32 advertising;
ASSERT_RTNL();
- if (ecmd->autoneg == AUTONEG_ENABLE) {
- if (ecmd->advertising & ~alx_get_supported_speeds(hw))
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
+
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
+ if (advertising & ~alx_get_supported_speeds(hw))
return -EINVAL;
- adv_cfg = ecmd->advertising | ADVERTISED_Autoneg;
+ adv_cfg = advertising | ADVERTISED_Autoneg;
} else {
- adv_cfg = alx_speed_to_ethadv(ethtool_cmd_speed(ecmd),
- ecmd->duplex);
+ adv_cfg = alx_speed_to_ethadv(cmd->base.speed,
+ cmd->base.duplex);
if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full)
return -EINVAL;
@@ -300,8 +311,6 @@ static int alx_get_sset_count(struct net_device *netdev, int sset)
}
const struct ethtool_ops alx_ethtool_ops = {
- .get_settings = alx_get_settings,
- .set_settings = alx_set_settings,
.get_pauseparam = alx_get_pauseparam,
.set_pauseparam = alx_set_pauseparam,
.get_msglevel = alx_get_msglevel,
@@ -310,4 +319,6 @@ const struct ethtool_ops alx_ethtool_ops = {
.get_strings = alx_get_strings,
.get_sset_count = alx_get_sset_count,
.get_ethtool_stats = alx_get_ethtool_stats,
+ .get_link_ksettings = alx_get_link_ksettings,
+ .set_link_ksettings = alx_set_link_ksettings,
};
diff --git a/drivers/net/ethernet/atheros/alx/hw.h b/drivers/net/ethernet/atheros/alx/hw.h
index 0191477ace51..e42d7e0947eb 100644
--- a/drivers/net/ethernet/atheros/alx/hw.h
+++ b/drivers/net/ethernet/atheros/alx/hw.h
@@ -351,7 +351,6 @@ struct alx_rrd {
#define ALX_MAX_JUMBO_PKT_SIZE (9*1024)
#define ALX_MAX_TSO_PKT_SIZE (7*1024)
#define ALX_MAX_FRAME_SIZE ALX_MAX_JUMBO_PKT_SIZE
-#define ALX_MIN_FRAME_SIZE (ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN)
#define ALX_MAX_RX_QUEUES 8
#define ALX_MAX_TX_QUEUES 4
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index c0f84b73574d..c8f525574d68 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -51,16 +51,12 @@
const char alx_drv_name[] = "alx";
-static bool msix = false;
-module_param(msix, bool, 0);
-MODULE_PARM_DESC(msix, "Enable msi-x interrupt support");
-
-static void alx_free_txbuf(struct alx_priv *alx, int entry)
+static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)
{
- struct alx_buffer *txb = &alx->txq.bufs[entry];
+ struct alx_buffer *txb = &txq->bufs[entry];
if (dma_unmap_len(txb, size)) {
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(txq->dev,
dma_unmap_addr(txb, dma),
dma_unmap_len(txb, size),
DMA_TO_DEVICE);
@@ -75,7 +71,7 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry)
static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
{
- struct alx_rx_queue *rxq = &alx->rxq;
+ struct alx_rx_queue *rxq = alx->qnapi[0]->rxq;
struct sk_buff *skb;
struct alx_buffer *cur_buf;
dma_addr_t dma;
@@ -143,24 +139,42 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
return count;
}
-static inline int alx_tpd_avail(struct alx_priv *alx)
+static struct alx_tx_queue *alx_tx_queue_mapping(struct alx_priv *alx,
+ struct sk_buff *skb)
{
- struct alx_tx_queue *txq = &alx->txq;
+ unsigned int r_idx = skb->queue_mapping;
+
+ if (r_idx >= alx->num_txq)
+ r_idx = r_idx % alx->num_txq;
+ return alx->qnapi[r_idx]->txq;
+}
+
+static struct netdev_queue *alx_get_tx_queue(const struct alx_tx_queue *txq)
+{
+ return netdev_get_tx_queue(txq->netdev, txq->queue_idx);
+}
+
+static inline int alx_tpd_avail(struct alx_tx_queue *txq)
+{
if (txq->write_idx >= txq->read_idx)
- return alx->tx_ringsz + txq->read_idx - txq->write_idx - 1;
+ return txq->count + txq->read_idx - txq->write_idx - 1;
return txq->read_idx - txq->write_idx - 1;
}
-static bool alx_clean_tx_irq(struct alx_priv *alx)
+static bool alx_clean_tx_irq(struct alx_tx_queue *txq)
{
- struct alx_tx_queue *txq = &alx->txq;
+ struct alx_priv *alx;
+ struct netdev_queue *tx_queue;
u16 hw_read_idx, sw_read_idx;
unsigned int total_bytes = 0, total_packets = 0;
int budget = ALX_DEFAULT_TX_WORK;
+ alx = netdev_priv(txq->netdev);
+ tx_queue = alx_get_tx_queue(txq);
+
sw_read_idx = txq->read_idx;
- hw_read_idx = alx_read_mem16(&alx->hw, ALX_TPD_PRI0_CIDX);
+ hw_read_idx = alx_read_mem16(&alx->hw, txq->c_reg);
if (sw_read_idx != hw_read_idx) {
while (sw_read_idx != hw_read_idx && budget > 0) {
@@ -173,19 +187,19 @@ static bool alx_clean_tx_irq(struct alx_priv *alx)
budget--;
}
- alx_free_txbuf(alx, sw_read_idx);
+ alx_free_txbuf(txq, sw_read_idx);
- if (++sw_read_idx == alx->tx_ringsz)
+ if (++sw_read_idx == txq->count)
sw_read_idx = 0;
}
txq->read_idx = sw_read_idx;
- netdev_completed_queue(alx->dev, total_packets, total_bytes);
+ netdev_tx_completed_queue(tx_queue, total_packets, total_bytes);
}
- if (netif_queue_stopped(alx->dev) && netif_carrier_ok(alx->dev) &&
- alx_tpd_avail(alx) > alx->tx_ringsz/4)
- netif_wake_queue(alx->dev);
+ if (netif_tx_queue_stopped(tx_queue) && netif_carrier_ok(alx->dev) &&
+ alx_tpd_avail(txq) > txq->count / 4)
+ netif_tx_wake_queue(tx_queue);
return sw_read_idx == hw_read_idx;
}
@@ -200,15 +214,17 @@ static void alx_schedule_reset(struct alx_priv *alx)
schedule_work(&alx->reset_wk);
}
-static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
+static int alx_clean_rx_irq(struct alx_rx_queue *rxq, int budget)
{
- struct alx_rx_queue *rxq = &alx->rxq;
+ struct alx_priv *alx;
struct alx_rrd *rrd;
struct alx_buffer *rxb;
struct sk_buff *skb;
u16 length, rfd_cleaned = 0;
int work = 0;
+ alx = netdev_priv(rxq->netdev);
+
while (work < budget) {
rrd = &rxq->rrd[rxq->rrd_read_idx];
if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT)))
@@ -224,7 +240,7 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
}
rxb = &rxq->bufs[rxq->read_idx];
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(rxq->dev,
dma_unmap_addr(rxb, dma),
dma_unmap_len(rxb, size),
DMA_FROM_DEVICE);
@@ -242,7 +258,7 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
length = ALX_GET_FIELD(le32_to_cpu(rrd->word3),
RRD_PKTLEN) - ETH_FCS_LEN;
skb_put(skb, length);
- skb->protocol = eth_type_trans(skb, alx->dev);
+ skb->protocol = eth_type_trans(skb, rxq->netdev);
skb_checksum_none_assert(skb);
if (alx->dev->features & NETIF_F_RXCSUM &&
@@ -259,13 +275,13 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
}
}
- napi_gro_receive(&alx->napi, skb);
+ napi_gro_receive(&rxq->np->napi, skb);
work++;
next_pkt:
- if (++rxq->read_idx == alx->rx_ringsz)
+ if (++rxq->read_idx == rxq->count)
rxq->read_idx = 0;
- if (++rxq->rrd_read_idx == alx->rx_ringsz)
+ if (++rxq->rrd_read_idx == rxq->count)
rxq->rrd_read_idx = 0;
if (++rfd_cleaned > ALX_RX_ALLOC_THRESH)
@@ -280,23 +296,26 @@ next_pkt:
static int alx_poll(struct napi_struct *napi, int budget)
{
- struct alx_priv *alx = container_of(napi, struct alx_priv, napi);
+ struct alx_napi *np = container_of(napi, struct alx_napi, napi);
+ struct alx_priv *alx = np->alx;
struct alx_hw *hw = &alx->hw;
unsigned long flags;
- bool tx_complete;
- int work;
+ bool tx_complete = true;
+ int work = 0;
- tx_complete = alx_clean_tx_irq(alx);
- work = alx_clean_rx_irq(alx, budget);
+ if (np->txq)
+ tx_complete = alx_clean_tx_irq(np->txq);
+ if (np->rxq)
+ work = alx_clean_rx_irq(np->rxq, budget);
if (!tx_complete || work == budget)
return budget;
- napi_complete(&alx->napi);
+ napi_complete(&np->napi);
/* enable interrupt */
if (alx->flags & ALX_FLAG_USING_MSIX) {
- alx_mask_msix(hw, 1, false);
+ alx_mask_msix(hw, np->vec_idx, false);
} else {
spin_lock_irqsave(&alx->irq_lock, flags);
alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
@@ -350,7 +369,7 @@ static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr)
goto out;
if (intr & (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0)) {
- napi_schedule(&alx->napi);
+ napi_schedule(&alx->qnapi[0]->napi);
/* mask rx/tx interrupt, enable them when napi complete */
alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
alx_write_mem32(hw, ALX_IMR, alx->int_mask);
@@ -365,15 +384,15 @@ static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr)
static irqreturn_t alx_intr_msix_ring(int irq, void *data)
{
- struct alx_priv *alx = data;
- struct alx_hw *hw = &alx->hw;
+ struct alx_napi *np = data;
+ struct alx_hw *hw = &np->alx->hw;
/* mask interrupt to ACK chip */
- alx_mask_msix(hw, 1, true);
+ alx_mask_msix(hw, np->vec_idx, true);
/* clear interrupt status */
- alx_write_mem32(hw, ALX_ISR, (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0));
+ alx_write_mem32(hw, ALX_ISR, np->vec_mask);
- napi_schedule(&alx->napi);
+ napi_schedule(&np->napi);
return IRQ_HANDLED;
}
@@ -424,63 +443,79 @@ static irqreturn_t alx_intr_legacy(int irq, void *data)
return alx_intr_handle(alx, intr);
}
+static const u16 txring_header_reg[] = {ALX_TPD_PRI0_ADDR_LO,
+ ALX_TPD_PRI1_ADDR_LO,
+ ALX_TPD_PRI2_ADDR_LO,
+ ALX_TPD_PRI3_ADDR_LO};
+
static void alx_init_ring_ptrs(struct alx_priv *alx)
{
struct alx_hw *hw = &alx->hw;
u32 addr_hi = ((u64)alx->descmem.dma) >> 32;
+ struct alx_napi *np;
+ int i;
+
+ for (i = 0; i < alx->num_napi; i++) {
+ np = alx->qnapi[i];
+ if (np->txq) {
+ np->txq->read_idx = 0;
+ np->txq->write_idx = 0;
+ alx_write_mem32(hw,
+ txring_header_reg[np->txq->queue_idx],
+ np->txq->tpd_dma);
+ }
+
+ if (np->rxq) {
+ np->rxq->read_idx = 0;
+ np->rxq->write_idx = 0;
+ np->rxq->rrd_read_idx = 0;
+ alx_write_mem32(hw, ALX_RRD_ADDR_LO, np->rxq->rrd_dma);
+ alx_write_mem32(hw, ALX_RFD_ADDR_LO, np->rxq->rfd_dma);
+ }
+ }
+
+ alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
+ alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
- alx->rxq.read_idx = 0;
- alx->rxq.write_idx = 0;
- alx->rxq.rrd_read_idx = 0;
alx_write_mem32(hw, ALX_RX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_RRD_ADDR_LO, alx->rxq.rrd_dma);
alx_write_mem32(hw, ALX_RRD_RING_SZ, alx->rx_ringsz);
- alx_write_mem32(hw, ALX_RFD_ADDR_LO, alx->rxq.rfd_dma);
alx_write_mem32(hw, ALX_RFD_RING_SZ, alx->rx_ringsz);
alx_write_mem32(hw, ALX_RFD_BUF_SZ, alx->rxbuf_size);
- alx->txq.read_idx = 0;
- alx->txq.write_idx = 0;
- alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_TPD_PRI0_ADDR_LO, alx->txq.tpd_dma);
- alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
-
/* load these pointers into the chip */
alx_write_mem32(hw, ALX_SRAM9, ALX_SRAM_LOAD_PTR);
}
-static void alx_free_txring_buf(struct alx_priv *alx)
+static void alx_free_txring_buf(struct alx_tx_queue *txq)
{
- struct alx_tx_queue *txq = &alx->txq;
int i;
if (!txq->bufs)
return;
- for (i = 0; i < alx->tx_ringsz; i++)
- alx_free_txbuf(alx, i);
+ for (i = 0; i < txq->count; i++)
+ alx_free_txbuf(txq, i);
- memset(txq->bufs, 0, alx->tx_ringsz * sizeof(struct alx_buffer));
- memset(txq->tpd, 0, alx->tx_ringsz * sizeof(struct alx_txd));
+ memset(txq->bufs, 0, txq->count * sizeof(struct alx_buffer));
+ memset(txq->tpd, 0, txq->count * sizeof(struct alx_txd));
txq->write_idx = 0;
txq->read_idx = 0;
- netdev_reset_queue(alx->dev);
+ netdev_tx_reset_queue(alx_get_tx_queue(txq));
}
-static void alx_free_rxring_buf(struct alx_priv *alx)
+static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
{
- struct alx_rx_queue *rxq = &alx->rxq;
struct alx_buffer *cur_buf;
u16 i;
- if (rxq == NULL)
+ if (!rxq->bufs)
return;
- for (i = 0; i < alx->rx_ringsz; i++) {
+ for (i = 0; i < rxq->count; i++) {
cur_buf = rxq->bufs + i;
if (cur_buf->skb) {
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(rxq->dev,
dma_unmap_addr(cur_buf, dma),
dma_unmap_len(cur_buf, size),
DMA_FROM_DEVICE);
@@ -498,8 +533,14 @@ static void alx_free_rxring_buf(struct alx_priv *alx)
static void alx_free_buffers(struct alx_priv *alx)
{
- alx_free_txring_buf(alx);
- alx_free_rxring_buf(alx);
+ int i;
+
+ for (i = 0; i < alx->num_txq; i++)
+ if (alx->qnapi[i] && alx->qnapi[i]->txq)
+ alx_free_txring_buf(alx->qnapi[i]->txq);
+
+ if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+ alx_free_rxring_buf(alx->qnapi[0]->rxq);
}
static int alx_reinit_rings(struct alx_priv *alx)
@@ -573,19 +614,41 @@ static int alx_set_mac_address(struct net_device *netdev, void *data)
return 0;
}
-static int alx_alloc_descriptors(struct alx_priv *alx)
+static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq,
+ int offset)
{
- alx->txq.bufs = kcalloc(alx->tx_ringsz,
- sizeof(struct alx_buffer),
- GFP_KERNEL);
- if (!alx->txq.bufs)
+ txq->bufs = kcalloc(txq->count, sizeof(struct alx_buffer), GFP_KERNEL);
+ if (!txq->bufs)
return -ENOMEM;
- alx->rxq.bufs = kcalloc(alx->rx_ringsz,
- sizeof(struct alx_buffer),
- GFP_KERNEL);
- if (!alx->rxq.bufs)
- goto out_free;
+ txq->tpd = alx->descmem.virt + offset;
+ txq->tpd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_txd) * txq->count;
+
+ return offset;
+}
+
+static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq,
+ int offset)
+{
+ rxq->bufs = kcalloc(rxq->count, sizeof(struct alx_buffer), GFP_KERNEL);
+ if (!rxq->bufs)
+ return -ENOMEM;
+
+ rxq->rrd = alx->descmem.virt + offset;
+ rxq->rrd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_rrd) * rxq->count;
+
+ rxq->rfd = alx->descmem.virt + offset;
+ rxq->rfd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_rfd) * rxq->count;
+
+ return offset;
+}
+
+static int alx_alloc_rings(struct alx_priv *alx)
+{
+ int i, offset = 0;
/* physical tx/rx ring descriptors
*
@@ -593,7 +656,8 @@ static int alx_alloc_descriptors(struct alx_priv *alx)
* 4G boundary (hardware has a single register for high 32 bits
* of addresses only)
*/
- alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz +
+ alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz *
+ alx->num_txq +
sizeof(struct alx_rrd) * alx->rx_ringsz +
sizeof(struct alx_rfd) * alx->rx_ringsz;
alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
@@ -601,87 +665,178 @@ static int alx_alloc_descriptors(struct alx_priv *alx)
&alx->descmem.dma,
GFP_KERNEL);
if (!alx->descmem.virt)
- goto out_free;
-
- alx->txq.tpd = alx->descmem.virt;
- alx->txq.tpd_dma = alx->descmem.dma;
+ return -ENOMEM;
- /* alignment requirement for next block */
+ /* alignment requirements */
BUILD_BUG_ON(sizeof(struct alx_txd) % 8);
+ BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
- alx->rxq.rrd =
- (void *)((u8 *)alx->descmem.virt +
- sizeof(struct alx_txd) * alx->tx_ringsz);
- alx->rxq.rrd_dma = alx->descmem.dma +
- sizeof(struct alx_txd) * alx->tx_ringsz;
+ for (i = 0; i < alx->num_txq; i++) {
+ offset = alx_alloc_tx_ring(alx, alx->qnapi[i]->txq, offset);
+ if (offset < 0) {
+ netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
+ return -ENOMEM;
+ }
+ }
- /* alignment requirement for next block */
- BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
+ offset = alx_alloc_rx_ring(alx, alx->qnapi[0]->rxq, offset);
+ if (offset < 0) {
+ netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
+ return -ENOMEM;
+ }
- alx->rxq.rfd =
- (void *)((u8 *)alx->descmem.virt +
- sizeof(struct alx_txd) * alx->tx_ringsz +
- sizeof(struct alx_rrd) * alx->rx_ringsz);
- alx->rxq.rfd_dma = alx->descmem.dma +
- sizeof(struct alx_txd) * alx->tx_ringsz +
- sizeof(struct alx_rrd) * alx->rx_ringsz;
+ alx_reinit_rings(alx);
return 0;
-out_free:
- kfree(alx->txq.bufs);
- kfree(alx->rxq.bufs);
- return -ENOMEM;
}
-static int alx_alloc_rings(struct alx_priv *alx)
+static void alx_free_rings(struct alx_priv *alx)
{
- int err;
+ int i;
- err = alx_alloc_descriptors(alx);
- if (err)
- return err;
+ alx_free_buffers(alx);
- alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
- alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
+ for (i = 0; i < alx->num_txq; i++)
+ if (alx->qnapi[i] && alx->qnapi[i]->txq)
+ kfree(alx->qnapi[i]->txq->bufs);
- netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
+ if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+ kfree(alx->qnapi[0]->rxq->bufs);
- alx_reinit_rings(alx);
- return 0;
+ if (!alx->descmem.virt)
+ dma_free_coherent(&alx->hw.pdev->dev,
+ alx->descmem.size,
+ alx->descmem.virt,
+ alx->descmem.dma);
}
-static void alx_free_rings(struct alx_priv *alx)
+static void alx_free_napis(struct alx_priv *alx)
{
- netif_napi_del(&alx->napi);
- alx_free_buffers(alx);
+ struct alx_napi *np;
+ int i;
- kfree(alx->txq.bufs);
- kfree(alx->rxq.bufs);
+ for (i = 0; i < alx->num_napi; i++) {
+ np = alx->qnapi[i];
+ if (!np)
+ continue;
- dma_free_coherent(&alx->hw.pdev->dev,
- alx->descmem.size,
- alx->descmem.virt,
- alx->descmem.dma);
+ netif_napi_del(&np->napi);
+ kfree(np->txq);
+ kfree(np->rxq);
+ kfree(np);
+ alx->qnapi[i] = NULL;
+ }
}
+static const u16 tx_pidx_reg[] = {ALX_TPD_PRI0_PIDX, ALX_TPD_PRI1_PIDX,
+ ALX_TPD_PRI2_PIDX, ALX_TPD_PRI3_PIDX};
+static const u16 tx_cidx_reg[] = {ALX_TPD_PRI0_CIDX, ALX_TPD_PRI1_CIDX,
+ ALX_TPD_PRI2_CIDX, ALX_TPD_PRI3_CIDX};
+static const u32 tx_vect_mask[] = {ALX_ISR_TX_Q0, ALX_ISR_TX_Q1,
+ ALX_ISR_TX_Q2, ALX_ISR_TX_Q3};
+static const u32 rx_vect_mask[] = {ALX_ISR_RX_Q0, ALX_ISR_RX_Q1,
+ ALX_ISR_RX_Q2, ALX_ISR_RX_Q3,
+ ALX_ISR_RX_Q4, ALX_ISR_RX_Q5,
+ ALX_ISR_RX_Q6, ALX_ISR_RX_Q7};
+
+static int alx_alloc_napis(struct alx_priv *alx)
+{
+ struct alx_napi *np;
+ struct alx_rx_queue *rxq;
+ struct alx_tx_queue *txq;
+ int i;
+
+ alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
+
+ /* allocate alx_napi structures */
+ for (i = 0; i < alx->num_napi; i++) {
+ np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
+ if (!np)
+ goto err_out;
+
+ np->alx = alx;
+ netif_napi_add(alx->dev, &np->napi, alx_poll, 64);
+ alx->qnapi[i] = np;
+ }
+
+ /* allocate tx queues */
+ for (i = 0; i < alx->num_txq; i++) {
+ np = alx->qnapi[i];
+ txq = kzalloc(sizeof(*txq), GFP_KERNEL);
+ if (!txq)
+ goto err_out;
+
+ np->txq = txq;
+ txq->p_reg = tx_pidx_reg[i];
+ txq->c_reg = tx_cidx_reg[i];
+ txq->queue_idx = i;
+ txq->count = alx->tx_ringsz;
+ txq->netdev = alx->dev;
+ txq->dev = &alx->hw.pdev->dev;
+ np->vec_mask |= tx_vect_mask[i];
+ alx->int_mask |= tx_vect_mask[i];
+ }
+
+ /* allocate rx queues */
+ np = alx->qnapi[0];
+ rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
+ if (!rxq)
+ goto err_out;
+
+ np->rxq = rxq;
+ rxq->np = alx->qnapi[0];
+ rxq->queue_idx = 0;
+ rxq->count = alx->rx_ringsz;
+ rxq->netdev = alx->dev;
+ rxq->dev = &alx->hw.pdev->dev;
+ np->vec_mask |= rx_vect_mask[0];
+ alx->int_mask |= rx_vect_mask[0];
+
+ return 0;
+
+err_out:
+ netdev_err(alx->dev, "error allocating internal structures\n");
+ alx_free_napis(alx);
+ return -ENOMEM;
+}
+
+static const int txq_vec_mapping_shift[] = {
+ 0, ALX_MSI_MAP_TBL1_TXQ0_SHIFT,
+ 0, ALX_MSI_MAP_TBL1_TXQ1_SHIFT,
+ 1, ALX_MSI_MAP_TBL2_TXQ2_SHIFT,
+ 1, ALX_MSI_MAP_TBL2_TXQ3_SHIFT,
+};
+
static void alx_config_vector_mapping(struct alx_priv *alx)
{
struct alx_hw *hw = &alx->hw;
- u32 tbl = 0;
+ u32 tbl[2] = {0, 0};
+ int i, vector, idx, shift;
if (alx->flags & ALX_FLAG_USING_MSIX) {
- tbl |= 1 << ALX_MSI_MAP_TBL1_TXQ0_SHIFT;
- tbl |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
+ /* tx mappings */
+ for (i = 0, vector = 1; i < alx->num_txq; i++, vector++) {
+ idx = txq_vec_mapping_shift[i * 2];
+ shift = txq_vec_mapping_shift[i * 2 + 1];
+ tbl[idx] |= vector << shift;
+ }
+
+ /* rx mapping */
+ tbl[0] |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
}
- alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl);
- alx_write_mem32(hw, ALX_MSI_MAP_TBL2, 0);
+ alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl[0]);
+ alx_write_mem32(hw, ALX_MSI_MAP_TBL2, tbl[1]);
alx_write_mem32(hw, ALX_MSI_ID_MAP, 0);
}
static bool alx_enable_msix(struct alx_priv *alx)
{
- int i, err, num_vec = 2;
+ int i, err, num_vec, num_txq, num_rxq;
+
+ num_txq = min_t(int, num_online_cpus(), ALX_MAX_TX_QUEUES);
+ num_rxq = 1;
+ num_vec = max_t(int, num_txq, num_rxq) + 1;
alx->msix_entries = kcalloc(num_vec, sizeof(struct msix_entry),
GFP_KERNEL);
@@ -701,6 +856,10 @@ static bool alx_enable_msix(struct alx_priv *alx)
}
alx->num_vec = num_vec;
+ alx->num_napi = num_vec - 1;
+ alx->num_txq = num_txq;
+ alx->num_rxq = num_rxq;
+
return true;
}
@@ -714,14 +873,29 @@ static int alx_request_msix(struct alx_priv *alx)
if (err)
goto out_err;
- vector++;
- sprintf(alx->irq_lbl, "%s-TxRx-0", netdev->name);
-
- err = request_irq(alx->msix_entries[vector].vector,
- alx_intr_msix_ring, 0, alx->irq_lbl, alx);
+ for (i = 0; i < alx->num_napi; i++) {
+ struct alx_napi *np = alx->qnapi[i];
+
+ vector++;
+
+ if (np->txq && np->rxq)
+ sprintf(np->irq_lbl, "%s-TxRx-%u", netdev->name,
+ np->txq->queue_idx);
+ else if (np->txq)
+ sprintf(np->irq_lbl, "%s-tx-%u", netdev->name,
+ np->txq->queue_idx);
+ else if (np->rxq)
+ sprintf(np->irq_lbl, "%s-rx-%u", netdev->name,
+ np->rxq->queue_idx);
+ else
+ sprintf(np->irq_lbl, "%s-unused", netdev->name);
+
+ np->vec_idx = vector;
+ err = request_irq(alx->msix_entries[vector].vector,
+ alx_intr_msix_ring, 0, np->irq_lbl, np);
if (err)
goto out_free;
-
+ }
return 0;
out_free:
@@ -729,7 +903,8 @@ out_free:
vector--;
for (i = 0; i < vector; i++)
- free_irq(alx->msix_entries[free_vector++].vector, alx);
+ free_irq(alx->msix_entries[free_vector++].vector,
+ alx->qnapi[i]);
out_err:
return err;
@@ -744,6 +919,9 @@ static void alx_init_intr(struct alx_priv *alx, bool msix)
if (!(alx->flags & ALX_FLAG_USING_MSIX)) {
alx->num_vec = 1;
+ alx->num_napi = 1;
+ alx->num_txq = 1;
+ alx->num_rxq = 1;
if (!pci_enable_msi(alx->hw.pdev))
alx->flags |= ALX_FLAG_USING_MSI;
@@ -799,6 +977,25 @@ static void alx_irq_disable(struct alx_priv *alx)
}
}
+static int alx_realloc_resources(struct alx_priv *alx)
+{
+ int err;
+
+ alx_free_rings(alx);
+ alx_free_napis(alx);
+ alx_disable_advanced_intr(alx);
+
+ err = alx_alloc_napis(alx);
+ if (err)
+ return err;
+
+ err = alx_alloc_rings(alx);
+ if (err)
+ return err;
+
+ return 0;
+}
+
static int alx_request_irq(struct alx_priv *alx)
{
struct pci_dev *pdev = alx->hw.pdev;
@@ -815,8 +1012,9 @@ static int alx_request_irq(struct alx_priv *alx)
goto out;
/* msix request failed, realloc resources */
- alx_disable_advanced_intr(alx);
- alx_init_intr(alx, false);
+ err = alx_realloc_resources(alx);
+ if (err)
+ goto out;
}
if (alx->flags & ALX_FLAG_USING_MSI) {
@@ -845,12 +1043,13 @@ out:
static void alx_free_irq(struct alx_priv *alx)
{
struct pci_dev *pdev = alx->hw.pdev;
- int i;
+ int i, vector = 0;
if (alx->flags & ALX_FLAG_USING_MSIX) {
- /* we have only 2 vectors without multi queue support */
- for (i = 0; i < 2; i++)
- free_irq(alx->msix_entries[i].vector, alx);
+ free_irq(alx->msix_entries[vector++].vector, alx);
+ for (i = 0; i < alx->num_napi; i++)
+ free_irq(alx->msix_entries[vector++].vector,
+ alx->qnapi[i]);
} else {
free_irq(pdev->irq, alx);
}
@@ -892,6 +1091,9 @@ static int alx_init_sw(struct alx_priv *alx)
hw->smb_timer = 400;
hw->mtu = alx->dev->mtu;
alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
+ /* MTU range: 34 - 9256 */
+ alx->dev->min_mtu = 34;
+ alx->dev->max_mtu = ALX_MAX_FRAME_LEN(ALX_MAX_FRAME_SIZE);
alx->tx_ringsz = 256;
alx->rx_ringsz = 512;
hw->imt = 200;
@@ -932,11 +1134,14 @@ static netdev_features_t alx_fix_features(struct net_device *netdev,
static void alx_netif_stop(struct alx_priv *alx)
{
+ int i;
+
netif_trans_update(alx->dev);
if (netif_carrier_ok(alx->dev)) {
netif_carrier_off(alx->dev);
netif_tx_disable(alx->dev);
- napi_disable(&alx->napi);
+ for (i = 0; i < alx->num_napi; i++)
+ napi_disable(&alx->qnapi[i]->napi);
}
}
@@ -994,13 +1199,6 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
struct alx_priv *alx = netdev_priv(netdev);
int max_frame = ALX_MAX_FRAME_LEN(mtu);
- if ((max_frame < ALX_MIN_FRAME_SIZE) ||
- (max_frame > ALX_MAX_FRAME_SIZE))
- return -EINVAL;
-
- if (netdev->mtu == mtu)
- return 0;
-
netdev->mtu = mtu;
alx->hw.mtu = mtu;
alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
@@ -1012,8 +1210,11 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
static void alx_netif_start(struct alx_priv *alx)
{
+ int i;
+
netif_tx_wake_all_queues(alx->dev);
- napi_enable(&alx->napi);
+ for (i = 0; i < alx->num_napi; i++)
+ napi_enable(&alx->qnapi[i]->napi);
netif_carrier_on(alx->dev);
}
@@ -1021,21 +1222,28 @@ static int __alx_open(struct alx_priv *alx, bool resume)
{
int err;
- alx_init_intr(alx, msix);
+ alx_init_intr(alx, true);
if (!resume)
netif_carrier_off(alx->dev);
- err = alx_alloc_rings(alx);
+ err = alx_alloc_napis(alx);
if (err)
goto out_disable_adv_intr;
+ err = alx_alloc_rings(alx);
+ if (err)
+ goto out_free_rings;
+
alx_configure(alx);
err = alx_request_irq(alx);
if (err)
goto out_free_rings;
+ netif_set_real_num_tx_queues(alx->dev, alx->num_txq);
+ netif_set_real_num_rx_queues(alx->dev, alx->num_rxq);
+
/* clear old interrupts */
alx_write_mem32(&alx->hw, ALX_ISR, ~(u32)ALX_ISR_DIS);
@@ -1049,6 +1257,7 @@ static int __alx_open(struct alx_priv *alx, bool resume)
out_free_rings:
alx_free_rings(alx);
+ alx_free_napis(alx);
out_disable_adv_intr:
alx_disable_advanced_intr(alx);
return err;
@@ -1059,6 +1268,7 @@ static void __alx_stop(struct alx_priv *alx)
alx_halt(alx);
alx_free_irq(alx);
alx_free_rings(alx);
+ alx_free_napis(alx);
}
static const char *alx_speed_desc(struct alx_hw *hw)
@@ -1241,9 +1451,8 @@ static int alx_tso(struct sk_buff *skb, struct alx_txd *first)
return 1;
}
-static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
+static int alx_map_tx_skb(struct alx_tx_queue *txq, struct sk_buff *skb)
{
- struct alx_tx_queue *txq = &alx->txq;
struct alx_txd *tpd, *first_tpd;
dma_addr_t dma;
int maplen, f, first_idx = txq->write_idx;
@@ -1252,7 +1461,7 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
tpd = first_tpd;
if (tpd->word1 & (1 << TPD_LSO_V2_SHIFT)) {
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
tpd = &txq->tpd[txq->write_idx];
@@ -1262,9 +1471,9 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
}
maplen = skb_headlen(skb);
- dma = dma_map_single(&alx->hw.pdev->dev, skb->data, maplen,
+ dma = dma_map_single(txq->dev, skb->data, maplen,
DMA_TO_DEVICE);
- if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+ if (dma_mapping_error(txq->dev, dma))
goto err_dma;
dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
@@ -1278,16 +1487,16 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
frag = &skb_shinfo(skb)->frags[f];
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
tpd = &txq->tpd[txq->write_idx];
tpd->word1 = first_tpd->word1;
maplen = skb_frag_size(frag);
- dma = skb_frag_dma_map(&alx->hw.pdev->dev, frag, 0,
+ dma = skb_frag_dma_map(txq->dev, frag, 0,
maplen, DMA_TO_DEVICE);
- if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+ if (dma_mapping_error(txq->dev, dma))
goto err_dma;
dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
dma_unmap_addr_set(&txq->bufs[txq->write_idx], dma, dma);
@@ -1300,7 +1509,7 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
tpd->word1 |= cpu_to_le32(1 << TPD_EOP_SHIFT);
txq->bufs[txq->write_idx].skb = skb;
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
return 0;
@@ -1308,23 +1517,24 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
err_dma:
f = first_idx;
while (f != txq->write_idx) {
- alx_free_txbuf(alx, f);
- if (++f == alx->tx_ringsz)
+ alx_free_txbuf(txq, f);
+ if (++f == txq->count)
f = 0;
}
return -ENOMEM;
}
-static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
+static netdev_tx_t alx_start_xmit_ring(struct sk_buff *skb,
+ struct alx_tx_queue *txq)
{
- struct alx_priv *alx = netdev_priv(netdev);
- struct alx_tx_queue *txq = &alx->txq;
+ struct alx_priv *alx;
struct alx_txd *first;
int tso;
- if (alx_tpd_avail(alx) < alx_tpd_req(skb)) {
- netif_stop_queue(alx->dev);
+ alx = netdev_priv(txq->netdev);
+
+ if (alx_tpd_avail(txq) < alx_tpd_req(skb)) {
+ netif_tx_stop_queue(alx_get_tx_queue(txq));
goto drop;
}
@@ -1337,17 +1547,17 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
else if (!tso && alx_tx_csum(skb, first))
goto drop;
- if (alx_map_tx_skb(alx, skb) < 0)
+ if (alx_map_tx_skb(txq, skb) < 0)
goto drop;
- netdev_sent_queue(alx->dev, skb->len);
+ netdev_tx_sent_queue(alx_get_tx_queue(txq), skb->len);
/* flush updates before updating hardware */
wmb();
- alx_write_mem16(&alx->hw, ALX_TPD_PRI0_PIDX, txq->write_idx);
+ alx_write_mem16(&alx->hw, txq->p_reg, txq->write_idx);
- if (alx_tpd_avail(alx) < alx->tx_ringsz/8)
- netif_stop_queue(alx->dev);
+ if (alx_tpd_avail(txq) < txq->count / 8)
+ netif_tx_stop_queue(alx_get_tx_queue(txq));
return NETDEV_TX_OK;
@@ -1356,6 +1566,13 @@ drop:
return NETDEV_TX_OK;
}
+static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct alx_priv *alx = netdev_priv(netdev);
+ return alx_start_xmit_ring(skb, alx_tx_queue_mapping(alx, skb));
+}
+
static void alx_tx_timeout(struct net_device *dev)
{
struct alx_priv *alx = netdev_priv(dev);
@@ -1413,10 +1630,12 @@ static int alx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
static void alx_poll_controller(struct net_device *netdev)
{
struct alx_priv *alx = netdev_priv(netdev);
+ int i;
if (alx->flags & ALX_FLAG_USING_MSIX) {
alx_intr_msix_misc(0, alx);
- alx_intr_msix_ring(0, alx);
+ for (i = 0; i < alx->num_txq; i++)
+ alx_intr_msix_ring(0, alx->qnapi[i]);
} else if (alx->flags & ALX_FLAG_USING_MSI)
alx_intr_msi(0, alx);
else
@@ -1533,7 +1752,8 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_pci_release;
}
- netdev = alloc_etherdev(sizeof(*alx));
+ netdev = alloc_etherdev_mqs(sizeof(*alx),
+ ALX_MAX_TX_QUEUES, 1);
if (!netdev) {
err = -ENOMEM;
goto out_pci_release;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 872b7abb0196..cfe86a20c899 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -26,46 +26,52 @@
#include "atl1c.h"
-static int atl1c_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1c_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
+ u32 supported, advertising;
- ecmd->supported = (SUPPORTED_10baseT_Half |
+ supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M)
- ecmd->supported |= SUPPORTED_1000baseT_Full;
+ supported |= SUPPORTED_1000baseT_Full;
- ecmd->advertising = ADVERTISED_TP;
+ advertising = ADVERTISED_TP;
- ecmd->advertising |= hw->autoneg_advertised;
+ advertising |= hw->autoneg_advertised;
- ecmd->port = PORT_TP;
- ecmd->phy_address = 0;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = 0;
if (adapter->link_speed != SPEED_0) {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+ cmd->base.speed = adapter->link_speed;
if (adapter->link_duplex == FULL_DUPLEX)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
else
- ecmd->duplex = DUPLEX_HALF;
+ cmd->base.duplex = DUPLEX_HALF;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
- ecmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
+
return 0;
}
-static int atl1c_set_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1c_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
@@ -74,12 +80,12 @@ static int atl1c_set_settings(struct net_device *netdev,
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
- if (ecmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
autoneg_advertised = ADVERTISED_Autoneg;
} else {
- u32 speed = ethtool_cmd_speed(ecmd);
+ u32 speed = cmd->base.speed;
if (speed == SPEED_1000) {
- if (ecmd->duplex != DUPLEX_FULL) {
+ if (cmd->base.duplex != DUPLEX_FULL) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"1000M half is invalid\n");
@@ -88,12 +94,12 @@ static int atl1c_set_settings(struct net_device *netdev,
}
autoneg_advertised = ADVERTISED_1000baseT_Full;
} else if (speed == SPEED_100) {
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_100baseT_Full;
else
autoneg_advertised = ADVERTISED_100baseT_Half;
} else {
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_10baseT_Full;
else
autoneg_advertised = ADVERTISED_10baseT_Half;
@@ -284,8 +290,6 @@ static int atl1c_nway_reset(struct net_device *netdev)
}
static const struct ethtool_ops atl1c_ethtool_ops = {
- .get_settings = atl1c_get_settings,
- .set_settings = atl1c_set_settings,
.get_drvinfo = atl1c_get_drvinfo,
.get_regs_len = atl1c_get_regs_len,
.get_regs = atl1c_get_regs,
@@ -297,6 +301,8 @@ static const struct ethtool_ops atl1c_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_eeprom_len = atl1c_get_eeprom_len,
.get_eeprom = atl1c_get_eeprom,
+ .get_link_ksettings = atl1c_get_link_ksettings,
+ .set_link_ksettings = atl1c_set_link_ksettings,
};
void atl1c_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index a3200ea6d765..773d3b7d8dd5 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -519,6 +519,26 @@ static int atl1c_set_features(struct net_device *netdev,
return 0;
}
+static void atl1c_set_max_mtu(struct net_device *netdev)
+{
+ struct atl1c_adapter *adapter = netdev_priv(netdev);
+ struct atl1c_hw *hw = &adapter->hw;
+
+ switch (hw->nic_type) {
+ /* These (GbE) devices support jumbo packets, max_mtu 6122 */
+ case athr_l1c:
+ case athr_l1d:
+ case athr_l1d_2:
+ netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+ break;
+ /* The 10/100 devices don't support jumbo packets, max_mtu 1500 */
+ default:
+ netdev->max_mtu = ETH_DATA_LEN;
+ break;
+ }
+}
+
/**
* atl1c_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
@@ -529,22 +549,9 @@ static int atl1c_set_features(struct net_device *netdev,
static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
- struct atl1c_hw *hw = &adapter->hw;
- int old_mtu = netdev->mtu;
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
- /* Fast Ethernet controller doesn't support jumbo packet */
- if (((hw->nic_type == athr_l2c ||
- hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) ||
- max_frame < ETH_ZLEN + ETH_FCS_LEN ||
- max_frame > MAX_JUMBO_FRAME_SIZE) {
- if (netif_msg_link(adapter))
- dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
- return -EINVAL;
- }
+
/* set MTU */
- if (old_mtu != new_mtu && netif_running(netdev)) {
+ if (netif_running(netdev)) {
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
netdev->mtu = new_mtu;
@@ -2511,6 +2518,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
netdev->netdev_ops = &atl1c_netdev_ops;
netdev->watchdog_timeo = AT_TX_WATCHDOG;
+ netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
atl1c_set_ethtool_ops(netdev);
/* TODO: add when ready */
@@ -2613,6 +2621,9 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_err(&pdev->dev, "net device private data init failed\n");
goto err_sw_init;
}
+ /* set max MTU */
+ atl1c_set_max_mtu(netdev);
+
atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
/* Init GPHY as early as possible due to power saving issue */
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
index 8e3dbd4d9f79..cb489e7e8374 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
@@ -26,73 +26,83 @@
#include "atl1e.h"
-static int atl1e_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1e_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_hw *hw = &adapter->hw;
+ u32 supported, advertising;
- ecmd->supported = (SUPPORTED_10baseT_Half |
+ supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
if (hw->nic_type == athr_l1e)
- ecmd->supported |= SUPPORTED_1000baseT_Full;
+ supported |= SUPPORTED_1000baseT_Full;
- ecmd->advertising = ADVERTISED_TP;
+ advertising = ADVERTISED_TP;
- ecmd->advertising |= ADVERTISED_Autoneg;
- ecmd->advertising |= hw->autoneg_advertised;
+ advertising |= ADVERTISED_Autoneg;
+ advertising |= hw->autoneg_advertised;
- ecmd->port = PORT_TP;
- ecmd->phy_address = 0;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = 0;
if (adapter->link_speed != SPEED_0) {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+ cmd->base.speed = adapter->link_speed;
if (adapter->link_duplex == FULL_DUPLEX)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
else
- ecmd->duplex = DUPLEX_HALF;
+ cmd->base.duplex = DUPLEX_HALF;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
- ecmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
+
return 0;
}
-static int atl1e_set_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1e_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
struct atl1e_hw *hw = &adapter->hw;
+ u32 advertising;
+
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
- if (ecmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
u16 adv4, adv9;
- if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+ if (advertising & ADVERTISE_1000_FULL) {
if (hw->nic_type == athr_l1e) {
hw->autoneg_advertised =
- ecmd->advertising & AT_ADV_MASK;
+ advertising & AT_ADV_MASK;
} else {
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
- } else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+ } else if (advertising & ADVERTISE_1000_HALF) {
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
} else {
hw->autoneg_advertised =
- ecmd->advertising & AT_ADV_MASK;
+ advertising & AT_ADV_MASK;
}
- ecmd->advertising = hw->autoneg_advertised |
+ advertising = hw->autoneg_advertised |
ADVERTISED_TP | ADVERTISED_Autoneg;
adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL;
@@ -367,8 +377,6 @@ static int atl1e_nway_reset(struct net_device *netdev)
}
static const struct ethtool_ops atl1e_ethtool_ops = {
- .get_settings = atl1e_get_settings,
- .set_settings = atl1e_set_settings,
.get_drvinfo = atl1e_get_drvinfo,
.get_regs_len = atl1e_get_regs_len,
.get_regs = atl1e_get_regs,
@@ -380,6 +388,8 @@ static const struct ethtool_ops atl1e_ethtool_ops = {
.get_eeprom_len = atl1e_get_eeprom_len,
.get_eeprom = atl1e_get_eeprom,
.set_eeprom = atl1e_set_eeprom,
+ .get_link_ksettings = atl1e_get_link_ksettings,
+ .set_link_ksettings = atl1e_set_link_ksettings,
};
void atl1e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 974713b19ab6..e96091b652a7 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -439,16 +439,10 @@ static int atl1e_set_features(struct net_device *netdev,
static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
{
struct atl1e_adapter *adapter = netdev_priv(netdev);
- int old_mtu = netdev->mtu;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- netdev_warn(adapter->netdev, "invalid MTU setting\n");
- return -EINVAL;
- }
/* set MTU */
- if (old_mtu != new_mtu && netif_running(netdev)) {
+ if (netif_running(netdev)) {
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
netdev->mtu = new_mtu;
@@ -2272,6 +2266,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
netdev->netdev_ops = &atl1e_netdev_ops;
netdev->watchdog_timeo = AT_TX_WATCHDOG;
+ /* MTU range: 42 - 8170 */
+ netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+ netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
atl1e_set_ethtool_ops(netdev);
netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 529bca718334..7dad8e4b9d2a 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2701,23 +2701,15 @@ static void atl1_reset_dev_task(struct work_struct *work)
static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
{
struct atl1_adapter *adapter = netdev_priv(netdev);
- int old_mtu = netdev->mtu;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- if (netif_msg_link(adapter))
- dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
- return -EINVAL;
- }
-
adapter->hw.max_frame_size = max_frame;
adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
adapter->rx_buffer_len = (max_frame + 7) & ~7;
adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
netdev->mtu = new_mtu;
- if ((old_mtu != new_mtu) && netif_running(netdev)) {
+ if (netif_running(netdev)) {
atl1_down(adapter);
atl1_up(adapter);
}
@@ -3031,6 +3023,11 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* is this valid? see atl1_setup_mac_ctrl() */
netdev->features |= NETIF_F_RXCSUM;
+ /* MTU range: 42 - 10218 */
+ netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+ netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
/*
* patch for some L1 of old version,
* the final version of L1 may not need these
@@ -3217,66 +3214,72 @@ static int atl1_get_sset_count(struct net_device *netdev, int sset)
}
}
-static int atl1_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct atl1_adapter *adapter = netdev_priv(netdev);
struct atl1_hw *hw = &adapter->hw;
+ u32 supported, advertising;
- ecmd->supported = (SUPPORTED_10baseT_Half |
+ supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg | SUPPORTED_TP);
- ecmd->advertising = ADVERTISED_TP;
+ advertising = ADVERTISED_TP;
if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
hw->media_type == MEDIA_TYPE_1000M_FULL) {
- ecmd->advertising |= ADVERTISED_Autoneg;
+ advertising |= ADVERTISED_Autoneg;
if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
- ecmd->advertising |= ADVERTISED_Autoneg;
- ecmd->advertising |=
+ advertising |= ADVERTISED_Autoneg;
+ advertising |=
(ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Full);
} else
- ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+ advertising |= (ADVERTISED_1000baseT_Full);
}
- ecmd->port = PORT_TP;
- ecmd->phy_address = 0;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = 0;
if (netif_carrier_ok(adapter->netdev)) {
u16 link_speed, link_duplex;
atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
- ethtool_cmd_speed_set(ecmd, link_speed);
+ cmd->base.speed = link_speed;
if (link_duplex == FULL_DUPLEX)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
else
- ecmd->duplex = DUPLEX_HALF;
+ cmd->base.duplex = DUPLEX_HALF;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
- ecmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
hw->media_type == MEDIA_TYPE_1000M_FULL)
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
else
- ecmd->autoneg = AUTONEG_DISABLE;
+ cmd->base.autoneg = AUTONEG_DISABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
-static int atl1_set_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl1_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct atl1_adapter *adapter = netdev_priv(netdev);
struct atl1_hw *hw = &adapter->hw;
u16 phy_data;
int ret_val = 0;
u16 old_media_type = hw->media_type;
+ u32 advertising;
if (netif_running(adapter->netdev)) {
if (netif_msg_link(adapter))
@@ -3285,12 +3288,12 @@ static int atl1_set_settings(struct net_device *netdev,
atl1_down(adapter);
}
- if (ecmd->autoneg == AUTONEG_ENABLE)
+ if (cmd->base.autoneg == AUTONEG_ENABLE)
hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
else {
- u32 speed = ethtool_cmd_speed(ecmd);
+ u32 speed = cmd->base.speed;
if (speed == SPEED_1000) {
- if (ecmd->duplex != DUPLEX_FULL) {
+ if (cmd->base.duplex != DUPLEX_FULL) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"1000M half is invalid\n");
@@ -3299,12 +3302,12 @@ static int atl1_set_settings(struct net_device *netdev,
}
hw->media_type = MEDIA_TYPE_1000M_FULL;
} else if (speed == SPEED_100) {
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
hw->media_type = MEDIA_TYPE_100M_FULL;
else
hw->media_type = MEDIA_TYPE_100M_HALF;
} else {
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
hw->media_type = MEDIA_TYPE_10M_FULL;
else
hw->media_type = MEDIA_TYPE_10M_HALF;
@@ -3312,7 +3315,7 @@ static int atl1_set_settings(struct net_device *netdev,
}
switch (hw->media_type) {
case MEDIA_TYPE_AUTO_SENSOR:
- ecmd->advertising =
+ advertising =
ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
@@ -3321,12 +3324,12 @@ static int atl1_set_settings(struct net_device *netdev,
ADVERTISED_Autoneg | ADVERTISED_TP;
break;
case MEDIA_TYPE_1000M_FULL:
- ecmd->advertising =
+ advertising =
ADVERTISED_1000baseT_Full |
ADVERTISED_Autoneg | ADVERTISED_TP;
break;
default:
- ecmd->advertising = 0;
+ advertising = 0;
break;
}
if (atl1_phy_setup_autoneg_adv(hw)) {
@@ -3666,8 +3669,6 @@ static int atl1_nway_reset(struct net_device *netdev)
}
static const struct ethtool_ops atl1_ethtool_ops = {
- .get_settings = atl1_get_settings,
- .set_settings = atl1_set_settings,
.get_drvinfo = atl1_get_drvinfo,
.get_wol = atl1_get_wol,
.set_wol = atl1_set_wol,
@@ -3684,6 +3685,8 @@ static const struct ethtool_ops atl1_ethtool_ops = {
.nway_reset = atl1_nway_reset,
.get_ethtool_stats = atl1_get_ethtool_stats,
.get_sset_count = atl1_get_sset_count,
+ .get_link_ksettings = atl1_get_link_ksettings,
+ .set_link_ksettings = atl1_set_link_ksettings,
};
module_pci_driver(atl1_driver);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 2ff465848b65..63f2deec2a52 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -253,7 +253,7 @@ static int atl2_configure(struct atl2_adapter *adapter)
/* set MTU */
ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +
- ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);
+ ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
/* 1590 */
ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);
@@ -925,15 +925,11 @@ static int atl2_change_mtu(struct net_device *netdev, int new_mtu)
struct atl2_adapter *adapter = netdev_priv(netdev);
struct atl2_hw *hw = &adapter->hw;
- if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
- return -EINVAL;
-
/* set MTU */
- if (hw->max_frame_size != new_mtu) {
- netdev->mtu = new_mtu;
- ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE +
- VLAN_SIZE + ETHERNET_FCS_SIZE);
- }
+ netdev->mtu = new_mtu;
+ hw->max_frame_size = new_mtu;
+ ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN);
return 0;
}
@@ -1398,6 +1394,8 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &atl2_netdev_ops;
netdev->ethtool_ops = &atl2_ethtool_ops;
netdev->watchdog_timeo = 5 * HZ;
+ netdev->min_mtu = 40;
+ netdev->max_mtu = ETH_DATA_LEN + VLAN_HLEN;
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
netdev->mem_start = mmio_start;
@@ -1739,81 +1737,87 @@ static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)
pci_write_config_word(adapter->pdev, reg, *value);
}
-static int atl2_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl2_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct atl2_adapter *adapter = netdev_priv(netdev);
struct atl2_hw *hw = &adapter->hw;
+ u32 supported, advertising;
- ecmd->supported = (SUPPORTED_10baseT_Half |
+ supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
- ecmd->advertising = ADVERTISED_TP;
+ advertising = ADVERTISED_TP;
- ecmd->advertising |= ADVERTISED_Autoneg;
- ecmd->advertising |= hw->autoneg_advertised;
+ advertising |= ADVERTISED_Autoneg;
+ advertising |= hw->autoneg_advertised;
- ecmd->port = PORT_TP;
- ecmd->phy_address = 0;
- ecmd->transceiver = XCVR_INTERNAL;
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = 0;
if (adapter->link_speed != SPEED_0) {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+ cmd->base.speed = adapter->link_speed;
if (adapter->link_duplex == FULL_DUPLEX)
- ecmd->duplex = DUPLEX_FULL;
+ cmd->base.duplex = DUPLEX_FULL;
else
- ecmd->duplex = DUPLEX_HALF;
+ cmd->base.duplex = DUPLEX_HALF;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
- ecmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
- ecmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
+
return 0;
}
-static int atl2_set_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+static int atl2_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
struct atl2_adapter *adapter = netdev_priv(netdev);
struct atl2_hw *hw = &adapter->hw;
+ u32 advertising;
+
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
msleep(1);
- if (ecmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
#define MY_ADV_MASK (ADVERTISE_10_HALF | \
ADVERTISE_10_FULL | \
ADVERTISE_100_HALF| \
ADVERTISE_100_FULL)
- if ((ecmd->advertising & MY_ADV_MASK) == MY_ADV_MASK) {
+ if ((advertising & MY_ADV_MASK) == MY_ADV_MASK) {
hw->MediaType = MEDIA_TYPE_AUTO_SENSOR;
hw->autoneg_advertised = MY_ADV_MASK;
- } else if ((ecmd->advertising & MY_ADV_MASK) ==
- ADVERTISE_100_FULL) {
+ } else if ((advertising & MY_ADV_MASK) == ADVERTISE_100_FULL) {
hw->MediaType = MEDIA_TYPE_100M_FULL;
hw->autoneg_advertised = ADVERTISE_100_FULL;
- } else if ((ecmd->advertising & MY_ADV_MASK) ==
- ADVERTISE_100_HALF) {
+ } else if ((advertising & MY_ADV_MASK) == ADVERTISE_100_HALF) {
hw->MediaType = MEDIA_TYPE_100M_HALF;
hw->autoneg_advertised = ADVERTISE_100_HALF;
- } else if ((ecmd->advertising & MY_ADV_MASK) ==
- ADVERTISE_10_FULL) {
+ } else if ((advertising & MY_ADV_MASK) == ADVERTISE_10_FULL) {
hw->MediaType = MEDIA_TYPE_10M_FULL;
hw->autoneg_advertised = ADVERTISE_10_FULL;
- } else if ((ecmd->advertising & MY_ADV_MASK) ==
- ADVERTISE_10_HALF) {
+ } else if ((advertising & MY_ADV_MASK) == ADVERTISE_10_HALF) {
hw->MediaType = MEDIA_TYPE_10M_HALF;
hw->autoneg_advertised = ADVERTISE_10_HALF;
} else {
clear_bit(__ATL2_RESETTING, &adapter->flags);
return -EINVAL;
}
- ecmd->advertising = hw->autoneg_advertised |
+ advertising = hw->autoneg_advertised |
ADVERTISED_TP | ADVERTISED_Autoneg;
} else {
clear_bit(__ATL2_RESETTING, &adapter->flags);
@@ -2082,8 +2086,6 @@ static int atl2_nway_reset(struct net_device *netdev)
}
static const struct ethtool_ops atl2_ethtool_ops = {
- .get_settings = atl2_get_settings,
- .set_settings = atl2_set_settings,
.get_drvinfo = atl2_get_drvinfo,
.get_regs_len = atl2_get_regs_len,
.get_regs = atl2_get_regs,
@@ -2096,6 +2098,8 @@ static const struct ethtool_ops atl2_ethtool_ops = {
.get_eeprom_len = atl2_get_eeprom_len,
.get_eeprom = atl2_get_eeprom,
.set_eeprom = atl2_set_eeprom,
+ .get_link_ksettings = atl2_get_link_ksettings,
+ .set_link_ksettings = atl2_set_link_ksettings,
};
#define LBYTESWAP(a) ((((a) & 0x00ff00ff) << 8) | \
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.h b/drivers/net/ethernet/atheros/atlx/atl2.h
index 2f27d4c4c3ad..c64a6bdfa7ae 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.h
+++ b/drivers/net/ethernet/atheros/atlx/atl2.h
@@ -228,12 +228,9 @@ static void atl2_force_ps(struct atl2_hw *hw);
#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */
/* The size (in bytes) of a ethernet packet */
-#define ENET_HEADER_SIZE 14
#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */
#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */
-#define ETHERNET_FCS_SIZE 4
#define MAX_JUMBO_FRAME_SIZE 0x2000
-#define VLAN_SIZE 4
struct tx_pkt_header {
unsigned pkt_size:11;
diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c
index e078d8da978c..5711fbbd6ae3 100644
--- a/drivers/net/ethernet/aurora/nb8800.c
+++ b/drivers/net/ethernet/aurora/nb8800.c
@@ -975,8 +975,10 @@ static int nb8800_open(struct net_device *dev)
phydev = of_phy_connect(dev, priv->phy_node,
nb8800_link_reconfigure, 0,
priv->phy_mode);
- if (!phydev)
+ if (!phydev) {
+ err = -ENODEV;
goto err_free_irq;
+ }
nb8800_pause_adv(dev);
@@ -1032,20 +1034,9 @@ static const struct net_device_ops nb8800_netdev_ops = {
.ndo_set_mac_address = nb8800_set_mac_address,
.ndo_set_rx_mode = nb8800_set_rx_mode,
.ndo_do_ioctl = nb8800_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
-static int nb8800_nway_reset(struct net_device *dev)
-{
- struct phy_device *phydev = dev->phydev;
-
- if (!phydev)
- return -ENODEV;
-
- return genphy_restart_aneg(phydev);
-}
-
static void nb8800_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pp)
{
@@ -1164,7 +1155,7 @@ static void nb8800_get_ethtool_stats(struct net_device *dev,
}
static const struct ethtool_ops nb8800_ethtool_ops = {
- .nway_reset = nb8800_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_pauseparam = nb8800_get_pauseparam,
.set_pauseparam = nb8800_set_pauseparam,
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index bd8c80c0b71c..940fb24bba21 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -110,7 +110,7 @@ config TIGON3
depends on PCI
select PHYLIB
select HWMON
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
@@ -120,7 +120,7 @@ config TIGON3
config BNX2X
tristate "Broadcom NetXtremeII 10Gb support"
depends on PCI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select FW_LOADER
select ZLIB_INFLATE
select LIBCRC32C
@@ -203,4 +203,14 @@ config BNXT_SRIOV
Virtualization support in the NetXtreme-C/E products. This
allows for virtual function acceleration in virtual environments.
+config BNXT_DCB
+ bool "Data Center Bridging (DCB) Support"
+ default n
+ depends on BNXT && DCB
+ ---help---
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver.
+
+ If unsure, say N.
+
endif # NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 17aa33c5567d..1df3048a3cdb 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -59,8 +59,8 @@
#define B44_TX_TIMEOUT (5 * HZ)
/* hardware minimum and maximum for a single frame's data payload */
-#define B44_MIN_MTU 60
-#define B44_MAX_MTU 1500
+#define B44_MIN_MTU ETH_ZLEN
+#define B44_MAX_MTU ETH_DATA_LEN
#define B44_RX_RING_SIZE 512
#define B44_DEF_RX_RING_PENDING 200
@@ -1064,9 +1064,6 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
{
struct b44 *bp = netdev_priv(dev);
- if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU)
- return -EINVAL;
-
if (!netif_running(dev)) {
/* We'll just catch it later when the
* device is up'd.
@@ -2377,6 +2374,8 @@ static int b44_init_one(struct ssb_device *sdev,
dev->netdev_ops = &b44_netdev_ops;
netif_napi_add(dev, &bp->napi, b44_poll, 64);
dev->watchdog_timeo = B44_TX_TIMEOUT;
+ dev->min_mtu = B44_MIN_MTU;
+ dev->max_mtu = B44_MAX_MTU;
dev->irq = sdev->irq;
dev->ethtool_ops = &b44_ethtool_ops;
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 537090952c45..3b14d5144228 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1434,11 +1434,8 @@ static int bcm_enet_nway_reset(struct net_device *dev)
struct bcm_enet_priv *priv;
priv = netdev_priv(dev);
- if (priv->has_phy) {
- if (!dev->phydev)
- return -ENODEV;
- return genphy_restart_aneg(dev->phydev);
- }
+ if (priv->has_phy)
+ return phy_ethtool_nway_reset(dev);
return -EOPNOTSUPP;
}
@@ -1623,20 +1620,19 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
/*
- * calculate actual hardware mtu
+ * adjust mtu, can't be called while device is running
*/
-static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
+static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
{
- int actual_mtu;
+ struct bcm_enet_priv *priv = netdev_priv(dev);
+ int actual_mtu = new_mtu;
- actual_mtu = mtu;
+ if (netif_running(dev))
+ return -EBUSY;
/* add ethernet header + vlan tag size */
actual_mtu += VLAN_ETH_HLEN;
- if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
- return -EINVAL;
-
/*
* setup maximum size before we get overflow mark in
* descriptor, note that this will not prevent reception of
@@ -1651,22 +1647,7 @@ static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
*/
priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
priv->dma_maxburst * 4);
- return 0;
-}
-
-/*
- * adjust mtu, can't be called while device is running
- */
-static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
-{
- int ret;
-
- if (netif_running(dev))
- return -EBUSY;
- ret = compute_hw_mtu(netdev_priv(dev), new_mtu);
- if (ret)
- return ret;
dev->mtu = new_mtu;
return 0;
}
@@ -1756,7 +1737,7 @@ static int bcm_enet_probe(struct platform_device *pdev)
priv->enet_is_sw = false;
priv->dma_maxburst = BCMENET_DMA_MAXBURST;
- ret = compute_hw_mtu(priv, dev->mtu);
+ ret = bcm_enet_change_mtu(dev, dev->mtu);
if (ret)
goto out;
@@ -1889,6 +1870,9 @@ static int bcm_enet_probe(struct platform_device *pdev)
netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
dev->ethtool_ops = &bcm_enet_ethtool_ops;
+ /* MTU range: 46 - 2028 */
+ dev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ dev->max_mtu = BCMENET_MAX_MTU - VLAN_ETH_HLEN;
SET_NETDEV_DEV(dev, &pdev->dev);
ret = register_netdev(dev);
@@ -2743,7 +2727,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev)
priv->dma_chan_width = pd->dma_chan_width;
}
- ret = compute_hw_mtu(priv, dev->mtu);
+ ret = bcm_enet_change_mtu(dev, dev->mtu);
if (ret)
goto out;
diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
index c16ec3a51876..4a4ffc0c4c65 100644
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -80,6 +80,24 @@ static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
}
+static int bcma_phy_connect(struct bgmac *bgmac)
+{
+ struct phy_device *phy_dev;
+ char bus_id[MII_BUS_ID_SIZE + 3];
+
+ /* Connect to the PHY */
+ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
+ bgmac->phyaddr);
+ phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phy_dev)) {
+ dev_err(bgmac->dev, "PHY connection failed\n");
+ return PTR_ERR(phy_dev);
+ }
+
+ return 0;
+}
+
static const struct bcma_device_id bgmac_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
BCMA_ANY_REV, BCMA_ANY_CLASS),
@@ -275,6 +293,10 @@ static int bgmac_probe(struct bcma_device *core)
bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
+ if (bgmac->mii_bus)
+ bgmac->phy_connect = bcma_phy_connect;
+ else
+ bgmac->phy_connect = bgmac_phy_connect_direct;
err = bgmac_enet_probe(bgmac);
if (err)
diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index be52f270c2c1..6f736c19872f 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -14,11 +14,21 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bcma/bcma.h>
+#include <linux/brcmphy.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include "bgmac.h"
+#define NICPM_IOMUX_CTRL 0x00000008
+
+#define NICPM_IOMUX_CTRL_INIT_VAL 0x3196e000
+#define NICPM_IOMUX_CTRL_SPD_SHIFT 10
+#define NICPM_IOMUX_CTRL_SPD_10M 0
+#define NICPM_IOMUX_CTRL_SPD_100M 1
+#define NICPM_IOMUX_CTRL_SPD_1000M 2
+
static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
{
return readl(bgmac->plat.base + offset);
@@ -86,6 +96,54 @@ static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
WARN_ON(1);
}
+static void bgmac_nicpm_speed_set(struct net_device *net_dev)
+{
+ struct bgmac *bgmac = netdev_priv(net_dev);
+ u32 val;
+
+ if (!bgmac->plat.nicpm_base)
+ return;
+
+ val = NICPM_IOMUX_CTRL_INIT_VAL;
+ switch (bgmac->net_dev->phydev->speed) {
+ default:
+ netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n");
+ case SPEED_1000:
+ val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+ break;
+ case SPEED_100:
+ val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+ break;
+ case SPEED_10:
+ val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+ break;
+ }
+
+ writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
+
+ bgmac_adjust_link(bgmac->net_dev);
+}
+
+static int platform_phy_connect(struct bgmac *bgmac)
+{
+ struct phy_device *phy_dev;
+
+ if (bgmac->plat.nicpm_base)
+ phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+ bgmac->dev->of_node,
+ bgmac_nicpm_speed_set);
+ else
+ phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+ bgmac->dev->of_node,
+ bgmac_adjust_link);
+ if (!phy_dev) {
+ dev_err(bgmac->dev, "PHY connection failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int bgmac_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -102,7 +160,6 @@ static int bgmac_probe(struct platform_device *pdev)
/* Set the features of the 4707 family */
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
- bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
@@ -142,6 +199,14 @@ static int bgmac_probe(struct platform_device *pdev)
if (IS_ERR(bgmac->plat.idm_base))
return PTR_ERR(bgmac->plat.idm_base);
+ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
+ if (regs) {
+ bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
+ regs);
+ if (IS_ERR(bgmac->plat.nicpm_base))
+ return PTR_ERR(bgmac->plat.nicpm_base);
+ }
+
bgmac->read = platform_bgmac_read;
bgmac->write = platform_bgmac_write;
bgmac->idm_read = platform_bgmac_idm_read;
@@ -151,6 +216,12 @@ static int bgmac_probe(struct platform_device *pdev)
bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
+ if (of_parse_phandle(np, "phy-handle", 0)) {
+ bgmac->phy_connect = platform_phy_connect;
+ } else {
+ bgmac->phy_connect = bgmac_phy_connect_direct;
+ bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
+ }
return bgmac_enet_probe(bgmac);
}
@@ -167,6 +238,7 @@ static int bgmac_remove(struct platform_device *pdev)
static const struct of_device_id bgmac_of_enet_match[] = {
{.compatible = "brcm,amac",},
{.compatible = "brcm,nsp-amac",},
+ {.compatible = "brcm,ns2-amac",},
{},
};
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 49f4cafe5438..0e066dc6b8cc 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1085,6 +1085,9 @@ static void bgmac_enable(struct bgmac *bgmac)
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
static void bgmac_chip_init(struct bgmac *bgmac)
{
+ /* Clear any erroneously pending interrupts */
+ bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
+
/* 1 interrupt per received frame */
bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);
@@ -1391,7 +1394,7 @@ static const struct ethtool_ops bgmac_ethtool_ops = {
* MII
**************************************************/
-static void bgmac_adjust_link(struct net_device *net_dev)
+void bgmac_adjust_link(struct net_device *net_dev)
{
struct bgmac *bgmac = netdev_priv(net_dev);
struct phy_device *phy_dev = net_dev->phydev;
@@ -1414,8 +1417,9 @@ static void bgmac_adjust_link(struct net_device *net_dev)
phy_print_status(phy_dev);
}
}
+EXPORT_SYMBOL_GPL(bgmac_adjust_link);
-static int bgmac_phy_connect_direct(struct bgmac *bgmac)
+int bgmac_phy_connect_direct(struct bgmac *bgmac)
{
struct fixed_phy_status fphy_status = {
.link = 1,
@@ -1440,24 +1444,7 @@ static int bgmac_phy_connect_direct(struct bgmac *bgmac)
return err;
}
-
-static int bgmac_phy_connect(struct bgmac *bgmac)
-{
- struct phy_device *phy_dev;
- char bus_id[MII_BUS_ID_SIZE + 3];
-
- /* Connect to the PHY */
- snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
- bgmac->phyaddr);
- phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
- PHY_INTERFACE_MODE_MII);
- if (IS_ERR(phy_dev)) {
- dev_err(bgmac->dev, "PHY connection failed\n");
- return PTR_ERR(phy_dev);
- }
-
- return 0;
-}
+EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);
int bgmac_enet_probe(struct bgmac *info)
{
@@ -1510,10 +1497,7 @@ int bgmac_enet_probe(struct bgmac *info)
netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
- if (!bgmac->mii_bus)
- err = bgmac_phy_connect_direct(bgmac);
- else
- err = bgmac_phy_connect(bgmac);
+ err = bgmac_phy_connect(bgmac);
if (err) {
dev_err(bgmac->dev, "Cannot connect to phy\n");
goto err_dma_free;
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 80836b4c9f38..71f493f2451f 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -463,6 +463,7 @@ struct bgmac {
struct {
void *base;
void *idm_base;
+ void *nicpm_base;
} plat;
struct {
struct bcma_device *core;
@@ -513,10 +514,13 @@ struct bgmac {
u32 (*get_bus_clock)(struct bgmac *bgmac);
void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
u32 set);
+ int (*phy_connect)(struct bgmac *bgmac);
};
int bgmac_enet_probe(struct bgmac *info);
void bgmac_enet_remove(struct bgmac *bgmac);
+void bgmac_adjust_link(struct net_device *net_dev);
+int bgmac_phy_connect_direct(struct bgmac *bgmac);
struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
@@ -583,4 +587,9 @@ static inline void bgmac_set(struct bgmac *bgmac, u16 offset, u32 set)
{
bgmac_maskset(bgmac, offset, ~0, set);
}
+
+static inline int bgmac_phy_connect(struct bgmac *bgmac)
+{
+ return bgmac->phy_connect(bgmac);
+}
#endif /* _BGMAC_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 1f7034d739b0..d5d1026be4b7 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -254,13 +254,10 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
{
u32 diff;
- /* Tell compiler to fetch tx_prod and tx_cons from memory. */
- barrier();
-
/* The ring uses 256 indices for 255 entries, one of them
* needs to be skipped.
*/
- diff = txr->tx_prod - txr->tx_cons;
+ diff = READ_ONCE(txr->tx_prod) - READ_ONCE(txr->tx_cons);
if (unlikely(diff >= BNX2_TX_DESC_CNT)) {
diff &= 0xffff;
if (diff == BNX2_TX_DESC_CNT)
@@ -2304,7 +2301,7 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
- if (bp->dev->mtu > 1500) {
+ if (bp->dev->mtu > ETH_DATA_LEN) {
u32 val;
/* Set extended packet length bit */
@@ -2358,7 +2355,7 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
}
- if (bp->dev->mtu > 1500) {
+ if (bp->dev->mtu > ETH_DATA_LEN) {
/* Set extended packet length bit */
bnx2_write_phy(bp, 0x18, 0x7);
bnx2_read_phy(bp, 0x18, &val);
@@ -2839,10 +2836,8 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
{
u16 cons;
- /* Tell compiler that status block fields can change. */
- barrier();
- cons = *bnapi->hw_tx_cons_ptr;
- barrier();
+ cons = READ_ONCE(*bnapi->hw_tx_cons_ptr);
+
if (unlikely((cons & BNX2_MAX_TX_DESC_CNT) == BNX2_MAX_TX_DESC_CNT))
cons++;
return cons;
@@ -3141,10 +3136,8 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
{
u16 cons;
- /* Tell compiler that status block fields can change. */
- barrier();
- cons = *bnapi->hw_rx_cons_ptr;
- barrier();
+ cons = READ_ONCE(*bnapi->hw_rx_cons_ptr);
+
if (unlikely((cons & BNX2_MAX_RX_DESC_CNT) == BNX2_MAX_RX_DESC_CNT))
cons++;
return cons;
@@ -5007,12 +5000,12 @@ bnx2_init_chip(struct bnx2 *bp)
/* Program the MTU. Also include 4 bytes for CRC32. */
mtu = bp->dev->mtu;
val = mtu + ETH_HLEN + ETH_FCS_LEN;
- if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
+ if (val > (MAX_ETHERNET_PACKET_SIZE + ETH_HLEN + 4))
val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
- if (mtu < 1500)
- mtu = 1500;
+ if (mtu < ETH_DATA_LEN)
+ mtu = ETH_DATA_LEN;
bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu));
bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
@@ -6904,12 +6897,14 @@ bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
/* All ethtool functions called with rtnl_lock */
static int
-bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+bnx2_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct bnx2 *bp = netdev_priv(dev);
int support_serdes = 0, support_copper = 0;
+ u32 supported, advertising;
- cmd->supported = SUPPORTED_Autoneg;
+ supported = SUPPORTED_Autoneg;
if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
support_serdes = 1;
support_copper = 1;
@@ -6919,56 +6914,59 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
support_copper = 1;
if (support_serdes) {
- cmd->supported |= SUPPORTED_1000baseT_Full |
+ supported |= SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE;
if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
- cmd->supported |= SUPPORTED_2500baseX_Full;
-
+ supported |= SUPPORTED_2500baseX_Full;
}
if (support_copper) {
- cmd->supported |= SUPPORTED_10baseT_Half |
+ supported |= SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_TP;
-
}
spin_lock_bh(&bp->phy_lock);
- cmd->port = bp->phy_port;
- cmd->advertising = bp->advertising;
+ cmd->base.port = bp->phy_port;
+ advertising = bp->advertising;
if (bp->autoneg & AUTONEG_SPEED) {
- cmd->autoneg = AUTONEG_ENABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
} else {
- cmd->autoneg = AUTONEG_DISABLE;
+ cmd->base.autoneg = AUTONEG_DISABLE;
}
if (netif_carrier_ok(dev)) {
- ethtool_cmd_speed_set(cmd, bp->line_speed);
- cmd->duplex = bp->duplex;
+ cmd->base.speed = bp->line_speed;
+ cmd->base.duplex = bp->duplex;
if (!(bp->phy_flags & BNX2_PHY_FLAG_SERDES)) {
if (bp->phy_flags & BNX2_PHY_FLAG_MDIX)
- cmd->eth_tp_mdix = ETH_TP_MDI_X;
+ cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
else
- cmd->eth_tp_mdix = ETH_TP_MDI;
+ cmd->base.eth_tp_mdix = ETH_TP_MDI;
}
}
else {
- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
- cmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
spin_unlock_bh(&bp->phy_lock);
- cmd->transceiver = XCVR_INTERNAL;
- cmd->phy_address = bp->phy_addr;
+ cmd->base.phy_address = bp->phy_addr;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
static int
-bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+bnx2_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct bnx2 *bp = netdev_priv(dev);
u8 autoneg = bp->autoneg;
@@ -6979,24 +6977,26 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
spin_lock_bh(&bp->phy_lock);
- if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
+ if (cmd->base.port != PORT_TP && cmd->base.port != PORT_FIBRE)
goto err_out_unlock;
- if (cmd->port != bp->phy_port &&
+ if (cmd->base.port != bp->phy_port &&
!(bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP))
goto err_out_unlock;
/* If device is down, we can store the settings only if the user
* is setting the currently active port.
*/
- if (!netif_running(dev) && cmd->port != bp->phy_port)
+ if (!netif_running(dev) && cmd->base.port != bp->phy_port)
goto err_out_unlock;
- if (cmd->autoneg == AUTONEG_ENABLE) {
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
autoneg |= AUTONEG_SPEED;
- advertising = cmd->advertising;
- if (cmd->port == PORT_TP) {
+ ethtool_convert_link_mode_to_legacy_u32(
+ &advertising, cmd->link_modes.advertising);
+
+ if (cmd->base.port == PORT_TP) {
advertising &= ETHTOOL_ALL_COPPER_SPEED;
if (!advertising)
advertising = ETHTOOL_ALL_COPPER_SPEED;
@@ -7008,11 +7008,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising |= ADVERTISED_Autoneg;
}
else {
- u32 speed = ethtool_cmd_speed(cmd);
- if (cmd->port == PORT_FIBRE) {
+ u32 speed = cmd->base.speed;
+
+ if (cmd->base.port == PORT_FIBRE) {
if ((speed != SPEED_1000 &&
speed != SPEED_2500) ||
- (cmd->duplex != DUPLEX_FULL))
+ (cmd->base.duplex != DUPLEX_FULL))
goto err_out_unlock;
if (speed == SPEED_2500 &&
@@ -7023,7 +7024,7 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
autoneg &= ~AUTONEG_SPEED;
req_line_speed = speed;
- req_duplex = cmd->duplex;
+ req_duplex = cmd->base.duplex;
advertising = 0;
}
@@ -7037,7 +7038,7 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
* brought up.
*/
if (netif_running(dev))
- err = bnx2_setup_phy(bp, cmd->port);
+ err = bnx2_setup_phy(bp, cmd->base.port);
err_out_unlock:
spin_unlock_bh(&bp->phy_lock);
@@ -7822,8 +7823,6 @@ static int bnx2_set_channels(struct net_device *dev,
}
static const struct ethtool_ops bnx2_ethtool_ops = {
- .get_settings = bnx2_get_settings,
- .set_settings = bnx2_set_settings,
.get_drvinfo = bnx2_get_drvinfo,
.get_regs_len = bnx2_get_regs_len,
.get_regs = bnx2_get_regs,
@@ -7847,6 +7846,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
.get_sset_count = bnx2_get_sset_count,
.get_channels = bnx2_get_channels,
.set_channels = bnx2_set_channels,
+ .get_link_ksettings = bnx2_get_link_ksettings,
+ .set_link_ksettings = bnx2_set_link_ksettings,
};
/* Called with rtnl_lock */
@@ -7923,10 +7924,6 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
{
struct bnx2 *bp = netdev_priv(dev);
- if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
- ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
- return -EINVAL;
-
dev->mtu = new_mtu;
return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size,
false);
@@ -8619,6 +8616,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
dev->features |= dev->hw_features;
dev->priv_flags |= IFF_UNICAST_FLT;
+ dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
+ dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;
if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index 380234d72b95..a09ec47461c9 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -6530,9 +6530,9 @@ struct l2_fhdr {
#define MII_BNX2_AER_AER_AN_MMD 0x3800
#define MII_BNX2_BLK_ADDR_COMBO_IEEEB0 0xffe0
-#define MIN_ETHERNET_PACKET_SIZE 60
-#define MAX_ETHERNET_PACKET_SIZE 1514
-#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+#define MIN_ETHERNET_PACKET_SIZE (ETH_ZLEN - ETH_HLEN)
+#define MAX_ETHERNET_PACKET_SIZE ETH_DATA_LEN
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9000
#define BNX2_RX_COPY_THRESH 128
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 7dd7490fdac1..0a23034bbe3f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1396,9 +1396,9 @@ struct bnx2x {
int tx_ring_size;
/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
-#define ETH_OVREHEAD (ETH_HLEN + 8 + 8)
-#define ETH_MIN_PACKET_SIZE 60
-#define ETH_MAX_PACKET_SIZE 1500
+#define ETH_OVERHEAD (ETH_HLEN + 8 + 8)
+#define ETH_MIN_PACKET_SIZE (ETH_ZLEN - ETH_HLEN)
+#define ETH_MAX_PACKET_SIZE ETH_DATA_LEN
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
/* TCP with Timestamp Option (32) + IPv6 (40) */
#define ETH_MAX_TPA_HEADER_SIZE 72
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 0a9108cd4c45..3e199d3e461e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -724,7 +724,7 @@ static void bnx2x_gro_ipv6_csum(struct bnx2x *bp, struct sk_buff *skb)
static void bnx2x_gro_csum(struct bnx2x *bp, struct sk_buff *skb,
void (*gro_func)(struct bnx2x*, struct sk_buff*))
{
- skb_set_network_header(skb, 0);
+ skb_reset_network_header(skb);
gro_func(bp, skb);
tcp_gro_complete(skb);
}
@@ -2023,7 +2023,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
mtu = bp->dev->mtu;
fp->rx_buf_size = BNX2X_FW_RX_ALIGN_START +
IP_HEADER_ALIGNMENT_PADDING +
- ETH_OVREHEAD +
+ ETH_OVERHEAD +
mtu +
BNX2X_FW_RX_ALIGN_END;
/* Note : rx_buf_size doesn't take into account NET_SKB_PAD */
@@ -3248,13 +3248,14 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
rmb();
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
- napi_complete(napi);
- /* Re-enable interrupts */
- DP(NETIF_MSG_RX_STATUS,
- "Update index to %d\n", fp->fp_hc_idx);
- bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_hc_idx),
- IGU_INT_ENABLE, 1);
+ if (napi_complete_done(napi, rx_work_done)) {
+ /* Re-enable interrupts */
+ DP(NETIF_MSG_RX_STATUS,
+ "Update index to %d\n", fp->fp_hc_idx);
+ bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
+ le16_to_cpu(fp->fp_hc_idx),
+ IGU_INT_ENABLE, 1);
+ }
} else {
rx_work_done = budget;
}
@@ -4855,12 +4856,6 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
return -EAGAIN;
}
- if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
- ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
- BNX2X_ERR("Can't support requested MTU size\n");
- return -EINVAL;
- }
-
/* This does not race with packet allocation
* because the actual alloc size is
* only updated as part of load
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 1fb80100e5e7..05356efdbf93 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -34,12 +34,6 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
u8 dev_addr, u16 addr, u8 byte_cnt,
u8 *o_buf, u8);
/********************************************************/
-#define ETH_HLEN 14
-/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
-#define ETH_OVREHEAD (ETH_HLEN + 8 + 8)
-#define ETH_MIN_PACKET_SIZE 60
-#define ETH_MAX_PACKET_SIZE 1500
-#define ETH_MAX_JUMBO_PACKET_SIZE 9600
#define MDIO_ACCESS_TIMEOUT 1000
#define WC_LANE_MAX 4
#define I2C_SWITCH_WIDTH 2
@@ -1917,7 +1911,7 @@ static int bnx2x_emac_enable(struct link_params *params,
/* Enable emac for jumbo packets */
EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
(EMAC_RX_MTU_SIZE_JUMBO_ENA |
- (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
+ (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD)));
/* Strip CRC */
REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
@@ -2314,19 +2308,19 @@ static int bnx2x_bmac1_enable(struct link_params *params,
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
/* Set rx mtu */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
bnx2x_update_pfc_bmac1(params, vars);
/* Set tx mtu */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
/* Set cnt max size */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
@@ -2384,18 +2378,18 @@ static int bnx2x_bmac2_enable(struct link_params *params,
udelay(30);
/* Set RX MTU */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
udelay(30);
/* Set TX MTU */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
udelay(30);
/* Set cnt max size */
- wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD - 2;
wb_data[1] = 0;
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
udelay(30);
@@ -2516,7 +2510,7 @@ static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
} else {
u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
- ETH_OVREHEAD)/16;
+ ETH_OVERHEAD)/16;
REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
/* Update threshold */
REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 4febe60eadc2..688617ac8c29 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12080,8 +12080,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
mtu_size, mtu);
/* if valid: update device mtu */
- if (((mtu_size + ETH_HLEN) >=
- ETH_MIN_PACKET_SIZE) &&
+ if ((mtu_size >= ETH_MIN_PACKET_SIZE) &&
(mtu_size <=
ETH_MAX_JUMBO_PACKET_SIZE))
bp->dev->mtu = mtu_size;
@@ -13315,6 +13314,10 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
dev->dcbnl_ops = &bnx2x_dcbnl_ops;
#endif
+ /* MTU range, 46 - 9600 */
+ dev->min_mtu = ETH_MIN_PACKET_SIZE;
+ dev->max_mtu = ETH_MAX_JUMBO_PACKET_SIZE;
+
/* get_port_hwinfo() will set prtad and mmds properly */
bp->mdio.prtad = MDIO_PRTAD_NONE;
bp->mdio.mmds = 0;
diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
index 97e78e217928..6082ed1b5ea0 100644
--- a/drivers/net/ethernet/broadcom/bnxt/Makefile
+++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_BNXT) += bnxt_en.o
-bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o
+bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index f08a20b921e7..9608cb49a11c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -52,8 +52,10 @@
#include "bnxt_hsi.h"
#include "bnxt.h"
+#include "bnxt_ulp.h"
#include "bnxt_sriov.h"
#include "bnxt_ethtool.h"
+#include "bnxt_dcb.h"
#define BNXT_TX_TIMEOUT (5 * HZ)
@@ -186,11 +188,11 @@ static const u16 bnxt_vf_req_snif[] = {
};
static const u16 bnxt_async_events_arr[] = {
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
+ ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
+ ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
+ ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
+ ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
+ ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
};
static bool bnxt_vf_pciid(enum board_idx idx)
@@ -1476,8 +1478,8 @@ next_rx_no_prod:
}
#define BNXT_GET_EVENT_PORT(data) \
- ((data) & \
- HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
+ ((data) & \
+ ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
static int bnxt_async_event_process(struct bnxt *bp,
struct hwrm_async_event_cmpl *cmpl)
@@ -1486,7 +1488,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
/* TODO CHIMP_FW: Define event id's for link change, error etc */
switch (event_id) {
- case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: {
+ case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: {
u32 data1 = le32_to_cpu(cmpl->event_data1);
struct bnxt_link_info *link_info = &bp->link_info;
@@ -1499,15 +1501,16 @@ static int bnxt_async_event_process(struct bnxt *bp,
netdev_warn(bp->dev, "Link speed %d no longer supported\n",
speed);
}
+ set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event);
/* fall thru */
}
- case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
+ case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event);
break;
- case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
+ case ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
set_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event);
break;
- case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: {
+ case ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: {
u32 data1 = le32_to_cpu(cmpl->event_data1);
u16 port_id = BNXT_GET_EVENT_PORT(data1);
@@ -1520,18 +1523,17 @@ static int bnxt_async_event_process(struct bnxt *bp,
set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
break;
}
- case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
+ case ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
if (BNXT_PF(bp))
goto async_event_process_exit;
set_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event);
break;
default:
- netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n",
- event_id);
goto async_event_process_exit;
}
schedule_work(&bp->sp_task);
async_event_process_exit:
+ bnxt_ulp_async_events(bp, cmpl);
return 0;
}
@@ -3115,27 +3117,46 @@ int hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 msg_len,
return rc;
}
-static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
+ int bmap_size)
{
struct hwrm_func_drv_rgtr_input req = {0};
- int i;
DECLARE_BITMAP(async_events_bmap, 256);
u32 *events = (u32 *)async_events_bmap;
+ 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);
+ cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
memset(async_events_bmap, 0, sizeof(async_events_bmap));
for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++)
__set_bit(bnxt_async_events_arr[i], async_events_bmap);
+ if (bmap && bmap_size) {
+ for (i = 0; i < bmap_size; i++) {
+ if (test_bit(i, bmap))
+ __set_bit(i, async_events_bmap);
+ }
+ }
+
for (i = 0; i < 8; i++)
req.async_event_fwd[i] |= cpu_to_le32(events[i]);
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
+{
+ struct hwrm_func_drv_rgtr_input req = {0};
+
+ 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);
+
req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
req.ver_maj = DRV_VER_MAJ;
req.ver_min = DRV_VER_MIN;
@@ -3144,6 +3165,7 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
if (BNXT_PF(bp)) {
DECLARE_BITMAP(vf_req_snif_bmap, 256);
u32 *data = (u32 *)vf_req_snif_bmap;
+ int i;
memset(vf_req_snif_bmap, 0, sizeof(vf_req_snif_bmap));
for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++)
@@ -3433,13 +3455,7 @@ static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss)
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_CFG, -1, -1);
if (set_rss) {
- vnic->hash_type = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
-
- req.hash_type = cpu_to_le32(vnic->hash_type);
-
+ req.hash_type = cpu_to_le32(bp->rss_hash_cfg);
if (vnic->flags & BNXT_VNIC_RSS_FLAG) {
if (BNXT_CHIP_TYPE_NITRO_A0(bp))
max_rings = bp->rx_nr_rings - 1;
@@ -3531,7 +3547,7 @@ static int bnxt_hwrm_vnic_ctx_alloc(struct bnxt *bp, u16 vnic_id, u16 ctx_idx)
return rc;
}
-static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
+int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
{
unsigned int ring = 0, grp_idx;
struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
@@ -3579,6 +3595,9 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
#endif
if ((bp->flags & BNXT_FLAG_STRIP_VLAN) || def_vlan)
req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
+ if (!vnic_id && bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP))
+ req.flags |=
+ cpu_to_le32(VNIC_CFG_REQ_FLAGS_ROCE_DUAL_VNIC_MODE);
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
}
@@ -4156,7 +4175,7 @@ func_qcfg_exit:
return rc;
}
-int bnxt_hwrm_func_qcaps(struct bnxt *bp)
+static int bnxt_hwrm_func_qcaps(struct bnxt *bp)
{
int rc = 0;
struct hwrm_func_qcaps_input req = {0};
@@ -4170,6 +4189,11 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp)
if (rc)
goto hwrm_func_qcaps_exit;
+ if (resp->flags & cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_ROCE_V1_SUPPORTED))
+ bp->flags |= BNXT_FLAG_ROCEV1_CAP;
+ if (resp->flags & cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED))
+ bp->flags |= BNXT_FLAG_ROCEV2_CAP;
+
bp->tx_push_thresh = 0;
if (resp->flags &
cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED))
@@ -4266,12 +4290,16 @@ static int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
goto qportcfg_exit;
}
bp->max_tc = resp->max_configurable_queues;
+ bp->max_lltc = resp->max_configurable_lossless_queues;
if (bp->max_tc > BNXT_MAX_QUEUE)
bp->max_tc = BNXT_MAX_QUEUE;
if (resp->queue_cfg_info & QUEUE_QPORTCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG)
bp->max_tc = 1;
+ if (bp->max_lltc > bp->max_tc)
+ bp->max_lltc = bp->max_tc;
+
qptr = &resp->queue_id0;
for (i = 0; i < bp->max_tc; i++) {
bp->q_info[i].queue_id = *qptr++;
@@ -4743,16 +4771,134 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
return 0;
}
-static int bnxt_setup_msix(struct bnxt *bp)
+static void bnxt_setup_msix(struct bnxt *bp)
{
- struct msix_entry *msix_ent;
+ const int len = sizeof(bp->irq_tbl[0].name);
struct net_device *dev = bp->dev;
- int i, total_vecs, rc = 0, min = 1;
+ int tcs, i;
+
+ 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);
+ }
+ }
+ }
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ char *attr;
+
+ if (bp->flags & BNXT_FLAG_SHARED_RINGS)
+ attr = "TxRx";
+ else if (i < bp->rx_nr_rings)
+ attr = "rx";
+ else
+ attr = "tx";
+
+ snprintf(bp->irq_tbl[i].name, len, "%s-%s-%d", dev->name, attr,
+ i);
+ bp->irq_tbl[i].handler = bnxt_msix;
+ }
+}
+
+static void bnxt_setup_inta(struct bnxt *bp)
+{
const int len = sizeof(bp->irq_tbl[0].name);
- bp->flags &= ~BNXT_FLAG_USING_MSIX;
- total_vecs = bp->cp_nr_rings;
+ if (netdev_get_num_tc(bp->dev))
+ netdev_reset_tc(bp->dev);
+
+ snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx",
+ 0);
+ bp->irq_tbl[0].handler = bnxt_inta;
+}
+
+static int bnxt_setup_int_mode(struct bnxt *bp)
+{
+ int rc;
+
+ if (bp->flags & BNXT_FLAG_USING_MSIX)
+ bnxt_setup_msix(bp);
+ else
+ bnxt_setup_inta(bp);
+ rc = bnxt_set_real_num_queues(bp);
+ return rc;
+}
+
+unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ return bp->vf.max_stat_ctxs;
+#endif
+ return bp->pf.max_stat_ctxs;
+}
+
+void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ bp->vf.max_stat_ctxs = max;
+ else
+#endif
+ bp->pf.max_stat_ctxs = max;
+}
+
+unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ return bp->vf.max_cp_rings;
+#endif
+ return bp->pf.max_cp_rings;
+}
+
+void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ bp->vf.max_cp_rings = max;
+ else
+#endif
+ bp->pf.max_cp_rings = max;
+}
+
+static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ return bp->vf.max_irqs;
+#endif
+ return bp->pf.max_irqs;
+}
+
+void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+ if (BNXT_VF(bp))
+ bp->vf.max_irqs = max_irqs;
+ else
+#endif
+ bp->pf.max_irqs = max_irqs;
+}
+
+static int bnxt_init_msix(struct bnxt *bp)
+{
+ int i, total_vecs, rc = 0, min = 1;
+ struct msix_entry *msix_ent;
+
+ total_vecs = bnxt_get_max_func_irqs(bp);
msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
if (!msix_ent)
return -ENOMEM;
@@ -4773,8 +4919,10 @@ static int bnxt_setup_msix(struct bnxt *bp)
bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
if (bp->irq_tbl) {
- int tcs;
+ for (i = 0; i < total_vecs; i++)
+ bp->irq_tbl[i].vector = msix_ent[i].vector;
+ bp->total_irqs = total_vecs;
/* Trim rings based upon num of vectors allocated */
rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings,
total_vecs, min == 1);
@@ -4782,43 +4930,10 @@ static int bnxt_setup_msix(struct bnxt *bp)
goto msix_setup_exit;
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 = total_vecs;
+ bp->cp_nr_rings = (min == 1) ?
+ max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
+ bp->tx_nr_rings + bp->rx_nr_rings;
- for (i = 0; i < bp->cp_nr_rings; i++) {
- char *attr;
-
- bp->irq_tbl[i].vector = msix_ent[i].vector;
- if (bp->flags & BNXT_FLAG_SHARED_RINGS)
- attr = "TxRx";
- else if (i < bp->rx_nr_rings)
- attr = "rx";
- else
- attr = "tx";
-
- snprintf(bp->irq_tbl[i].name, len,
- "%s-%s-%d", dev->name, attr, 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;
@@ -4828,52 +4943,54 @@ static int bnxt_setup_msix(struct bnxt *bp)
return 0;
msix_setup_exit:
- netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc);
+ netdev_err(bp->dev, "bnxt_init_msix err: %x\n", rc);
+ kfree(bp->irq_tbl);
+ bp->irq_tbl = NULL;
pci_disable_msix(bp->pdev);
kfree(msix_ent);
return rc;
}
-static int bnxt_setup_inta(struct bnxt *bp)
+static int bnxt_init_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;
- }
+ if (!bp->irq_tbl)
+ return -ENOMEM;
+
+ bp->total_irqs = 1;
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->flags |= BNXT_FLAG_SHARED_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;
+ return 0;
}
-static int bnxt_setup_int_mode(struct bnxt *bp)
+static int bnxt_init_int_mode(struct bnxt *bp)
{
int rc = 0;
if (bp->flags & BNXT_FLAG_MSIX_CAP)
- rc = bnxt_setup_msix(bp);
+ rc = bnxt_init_msix(bp);
if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) {
/* fallback to INTA */
- rc = bnxt_setup_inta(bp);
+ rc = bnxt_init_inta(bp);
}
return rc;
}
+static void bnxt_clear_int_mode(struct bnxt *bp)
+{
+ if (bp->flags & BNXT_FLAG_USING_MSIX)
+ pci_disable_msix(bp->pdev);
+
+ kfree(bp->irq_tbl);
+ bp->irq_tbl = NULL;
+ bp->flags &= ~BNXT_FLAG_USING_MSIX;
+}
+
static void bnxt_free_irq(struct bnxt *bp)
{
struct bnxt_irq *irq;
@@ -4892,10 +5009,6 @@ static void bnxt_free_irq(struct bnxt *bp)
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)
@@ -4967,7 +5080,6 @@ static void bnxt_init_napi(struct bnxt *bp)
bnapi = bp->bnapi[cp_nr_rings];
netif_napi_add(bp->dev, &bnapi->napi,
bnxt_poll_nitroa0, 64);
- napi_hash_add(&bnapi->napi);
}
} else {
bnapi = bp->bnapi[0];
@@ -4999,7 +5111,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
}
}
-static void bnxt_tx_disable(struct bnxt *bp)
+void bnxt_tx_disable(struct bnxt *bp)
{
int i;
struct bnxt_tx_ring_info *txr;
@@ -5017,7 +5129,7 @@ static void bnxt_tx_disable(struct bnxt *bp)
netif_carrier_off(bp->dev);
}
-static void bnxt_tx_enable(struct bnxt *bp)
+void bnxt_tx_enable(struct bnxt *bp)
{
int i;
struct bnxt_tx_ring_info *txr;
@@ -5109,6 +5221,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
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;
+ u16 diff;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
@@ -5196,6 +5309,23 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
link_info->link_up = 0;
}
mutex_unlock(&bp->hwrm_cmd_lock);
+
+ diff = link_info->support_auto_speeds ^ link_info->advertising;
+ if ((link_info->support_auto_speeds | diff) !=
+ link_info->support_auto_speeds) {
+ /* An advertised speed is no longer supported, so we need to
+ * update the advertisement settings. See bnxt_reset() for
+ * comments about the rtnl_lock() sequence below.
+ */
+ clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+ rtnl_lock();
+ link_info->advertising = link_info->support_auto_speeds;
+ if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
+ (link_info->autoneg & BNXT_AUTONEG_SPEED))
+ bnxt_hwrm_set_link_setting(bp, true, false);
+ set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+ rtnl_unlock();
+ }
return 0;
}
@@ -5360,7 +5490,7 @@ static int bnxt_hwrm_shutdown_link(struct bnxt *bp)
return 0;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
- req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN);
+ req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN);
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
}
@@ -5423,6 +5553,12 @@ static int bnxt_update_phy_setting(struct bnxt *bp)
update_link = true;
}
+ /* The last close may have shutdown the link, so need to call
+ * PHY_CFG to bring it back up.
+ */
+ if (!netif_carrier_ok(bp->dev))
+ update_link = true;
+
if (!bnxt_eee_config_ok(bp))
update_eee = true;
@@ -5543,22 +5679,7 @@ int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
static int bnxt_open(struct net_device *dev)
{
struct bnxt *bp = netdev_priv(dev);
- int rc = 0;
- if (!test_bit(BNXT_STATE_FN_RST_DONE, &bp->state)) {
- rc = bnxt_hwrm_func_reset(bp);
- if (rc) {
- netdev_err(bp->dev, "hwrm chip reset failure rc: %x\n",
- rc);
- rc = -EBUSY;
- return rc;
- }
- /* Do func_reset during the 1st PF open only to prevent killing
- * the VFs when the PF is brought down and up.
- */
- if (BNXT_PF(bp))
- set_bit(BNXT_STATE_FN_RST_DONE, &bp->state);
- }
return __bnxt_open_nic(bp, true, true);
}
@@ -6116,6 +6237,10 @@ static void bnxt_sp_task(struct work_struct *work)
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)) {
+ if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
+ &bp->sp_event))
+ bnxt_hwrm_phy_qcaps(bp);
+
rc = bnxt_update_link(bp, true);
if (rc)
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
@@ -6303,9 +6428,6 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
{
struct bnxt *bp = netdev_priv(dev);
- if (new_mtu < 60 || new_mtu > 9500)
- return -EINVAL;
-
if (netif_running(dev))
bnxt_close_nic(bp, false, false);
@@ -6318,17 +6440,10 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
- struct tc_to_netdev *ntc)
+int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
{
struct bnxt *bp = netdev_priv(dev);
bool sh = false;
- u8 tc;
-
- if (ntc->type != TC_SETUP_MQPRIO)
- return -EINVAL;
-
- tc = ntc->tc;
if (tc > bp->max_tc) {
netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n",
@@ -6371,6 +6486,15 @@ static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
return 0;
}
+static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+ struct tc_to_netdev *ntc)
+{
+ if (ntc->type != TC_SETUP_MQPRIO)
+ return -EINVAL;
+
+ return bnxt_setup_mq_tc(dev, ntc->tc);
+}
+
#ifdef CONFIG_RFS_ACCEL
static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
struct bnxt_ntuple_filter *f2)
@@ -6659,11 +6783,15 @@ static void bnxt_remove_one(struct pci_dev *pdev)
cancel_work_sync(&bp->sp_task);
bp->sp_event = 0;
+ bnxt_clear_int_mode(bp);
bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp);
+ bnxt_dcb_free(bp);
pci_iounmap(pdev, bp->bar2);
pci_iounmap(pdev, bp->bar1);
pci_iounmap(pdev, bp->bar0);
+ kfree(bp->edev);
+ bp->edev = NULL;
free_netdev(dev);
pci_release_regions(pdev);
@@ -6772,6 +6900,39 @@ int bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx, bool shared)
return bnxt_trim_rings(bp, max_rx, max_tx, cp, shared);
}
+static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
+ bool shared)
+{
+ int rc;
+
+ rc = bnxt_get_max_rings(bp, max_rx, max_tx, shared);
+ if (rc)
+ return rc;
+
+ if (bp->flags & BNXT_FLAG_ROCE_CAP) {
+ int max_cp, max_stat, max_irq;
+
+ /* Reserve minimum resources for RoCE */
+ max_cp = bnxt_get_max_func_cp_rings(bp);
+ max_stat = bnxt_get_max_func_stat_ctxs(bp);
+ max_irq = bnxt_get_max_func_irqs(bp);
+ if (max_cp <= BNXT_MIN_ROCE_CP_RINGS ||
+ max_irq <= BNXT_MIN_ROCE_CP_RINGS ||
+ max_stat <= BNXT_MIN_ROCE_STAT_CTXS)
+ return 0;
+
+ max_cp -= BNXT_MIN_ROCE_CP_RINGS;
+ max_irq -= BNXT_MIN_ROCE_CP_RINGS;
+ max_stat -= BNXT_MIN_ROCE_STAT_CTXS;
+ max_cp = min_t(int, max_cp, max_irq);
+ max_cp = min_t(int, max_cp, max_stat);
+ rc = bnxt_trim_rings(bp, max_rx, max_tx, max_cp, shared);
+ if (rc)
+ rc = 0;
+ }
+ return rc;
+}
+
static int bnxt_set_dflt_rings(struct bnxt *bp)
{
int dflt_rings, max_rx_rings, max_tx_rings, rc;
@@ -6780,7 +6941,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp)
if (sh)
bp->flags |= BNXT_FLAG_SHARED_RINGS;
dflt_rings = netif_get_num_default_rss_queues();
- rc = bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, sh);
+ rc = bnxt_get_dflt_rings(bp, &max_rx_rings, &max_tx_rings, sh);
if (rc)
return rc;
bp->rx_nr_rings = min_t(int, dflt_rings, max_rx_rings);
@@ -6796,6 +6957,13 @@ static int bnxt_set_dflt_rings(struct bnxt *bp)
return rc;
}
+void bnxt_restore_pf_fw_resources(struct bnxt *bp)
+{
+ ASSERT_RTNL();
+ bnxt_hwrm_func_qcaps(bp);
+ bnxt_subtract_ulp_resources(bp, BNXT_ROCE_ULP);
+}
+
static void bnxt_parse_log_pcie_link(struct bnxt *bp)
{
enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
@@ -6884,6 +7052,12 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
dev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 60 - 9500 */
+ dev->min_mtu = ETH_ZLEN;
+ dev->max_mtu = 9500;
+
+ bnxt_dcb_init(bp);
+
#ifdef CONFIG_BNXT_SRIOV
init_waitqueue_head(&bp->sriov_cfg_wait);
#endif
@@ -6895,6 +7069,12 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto init_err;
+ rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0);
+ if (rc)
+ goto init_err;
+
+ bp->ulp_probe = bnxt_ulp_probe;
+
/* Get the MAX capabilities for this function */
rc = bnxt_hwrm_func_qcaps(bp);
if (rc) {
@@ -6916,14 +7096,22 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
bnxt_set_tpa_flags(bp);
bnxt_set_ring_params(bp);
- if (BNXT_PF(bp))
- bp->pf.max_irqs = max_irqs;
-#if defined(CONFIG_BNXT_SRIOV)
- else
- bp->vf.max_irqs = max_irqs;
-#endif
+ bnxt_set_max_func_irqs(bp, max_irqs);
bnxt_set_dflt_rings(bp);
+ /* Default RSS hash cfg. */
+ bp->rss_hash_cfg = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+ if (!BNXT_CHIP_NUM_57X0X(bp->chip_num) &&
+ !BNXT_CHIP_TYPE_NITRO_A0(bp) &&
+ bp->hwrm_spec_code >= 0x10501) {
+ bp->flags |= BNXT_FLAG_UDP_RSS_CAP;
+ bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+ }
+
if (BNXT_PF(bp) && !BNXT_CHIP_TYPE_NITRO_A0(bp)) {
dev->hw_features |= NETIF_F_NTUPLE;
if (bnxt_rfs_capable(bp)) {
@@ -6939,10 +7127,18 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto init_err;
- rc = register_netdev(dev);
+ rc = bnxt_hwrm_func_reset(bp);
+ if (rc)
+ goto init_err;
+
+ rc = bnxt_init_int_mode(bp);
if (rc)
goto init_err;
+ rc = register_netdev(dev);
+ if (rc)
+ goto init_err_clr_int;
+
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);
@@ -6951,6 +7147,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
+init_err_clr_int:
+ bnxt_clear_int_mode(bp);
+
init_err:
pci_iounmap(pdev, bp->bar0);
pci_release_regions(pdev);
@@ -6980,6 +7179,8 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
rtnl_lock();
netif_device_detach(netdev);
+ bnxt_ulp_stop(bp);
+
if (state == pci_channel_io_perm_failure) {
rtnl_unlock();
return PCI_ERS_RESULT_DISCONNECT;
@@ -6988,8 +7189,6 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
if (netif_running(netdev))
bnxt_close(netdev);
- /* So that func_reset will be done during slot_reset */
- clear_bit(BNXT_STATE_FN_RST_DONE, &bp->state);
pci_disable_device(pdev);
rtnl_unlock();
@@ -7023,11 +7222,14 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
} else {
pci_set_master(pdev);
- if (netif_running(netdev))
+ err = bnxt_hwrm_func_reset(bp);
+ if (!err && netif_running(netdev))
err = bnxt_open(netdev);
- if (!err)
+ if (!err) {
result = PCI_ERS_RESULT_RECOVERED;
+ bnxt_ulp_start(bp);
+ }
}
if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev))
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 51b164a0e844..16defe9ececc 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -11,10 +11,10 @@
#define BNXT_H
#define DRV_MODULE_NAME "bnxt_en"
-#define DRV_MODULE_VERSION "1.5.0"
+#define DRV_MODULE_VERSION "1.6.0"
#define DRV_VER_MAJ 1
-#define DRV_VER_MIN 5
+#define DRV_VER_MIN 6
#define DRV_VER_UPD 0
struct tx_bd {
@@ -387,6 +387,9 @@ struct rx_tpa_end_cmp_ext {
#define DB_KEY_TX_PUSH (0x4 << 28)
#define DB_LONG_TX_PUSH (0x2 << 24)
+#define BNXT_MIN_ROCE_CP_RINGS 2
+#define BNXT_MIN_ROCE_STAT_CTXS 1
+
#define INVALID_HW_RING_ID ((u16)-1)
/* The hardware supports certain page sizes. Use the supported page sizes
@@ -700,7 +703,6 @@ struct bnxt_vnic_info {
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;
@@ -952,7 +954,12 @@ struct bnxt {
#define BNXT_FLAG_RFS 0x100
#define BNXT_FLAG_SHARED_RINGS 0x200
#define BNXT_FLAG_PORT_STATS 0x400
+ #define BNXT_FLAG_UDP_RSS_CAP 0x800
#define BNXT_FLAG_EEE_CAP 0x1000
+ #define BNXT_FLAG_ROCEV1_CAP 0x8000
+ #define BNXT_FLAG_ROCEV2_CAP 0x10000
+ #define BNXT_FLAG_ROCE_CAP (BNXT_FLAG_ROCEV1_CAP | \
+ BNXT_FLAG_ROCEV2_CAP)
#define BNXT_FLAG_CHIP_NITRO_A0 0x1000000
#define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \
@@ -965,6 +972,9 @@ struct bnxt {
#define BNXT_SINGLE_PF(bp) (BNXT_PF(bp) && !BNXT_NPAR(bp))
#define BNXT_CHIP_TYPE_NITRO_A0(bp) ((bp)->flags & BNXT_FLAG_CHIP_NITRO_A0)
+ struct bnxt_en_dev *edev;
+ struct bnxt_en_dev * (*ulp_probe)(struct net_device *);
+
struct bnxt_napi **bnapi;
struct bnxt_rx_ring_info *rx_ring;
@@ -1007,8 +1017,10 @@ struct bnxt {
struct bnxt_ring_grp_info *grp_info;
struct bnxt_vnic_info *vnic_info;
int nr_vnics;
+ u32 rss_hash_cfg;
u8 max_tc;
+ u8 max_lltc; /* lossless TCs */
struct bnxt_queue_info q_info[BNXT_MAX_QUEUE];
unsigned int current_interval;
@@ -1019,11 +1031,18 @@ struct bnxt {
unsigned long state;
#define BNXT_STATE_OPEN 0
#define BNXT_STATE_IN_SP_TASK 1
-#define BNXT_STATE_FN_RST_DONE 2
struct bnxt_irq *irq_tbl;
+ int total_irqs;
u8 mac_addr[ETH_ALEN];
+#ifdef CONFIG_BNXT_DCB
+ struct ieee_pfc *ieee_pfc;
+ struct ieee_ets *ieee_ets;
+ u8 dcbx_cap;
+ u8 default_pri;
+#endif /* CONFIG_BNXT_DCB */
+
u32 msg_enable;
u32 hwrm_spec_code;
@@ -1089,6 +1108,7 @@ struct bnxt {
#define BNXT_RESET_TASK_SILENT_SP_EVENT 11
#define BNXT_GENEVE_ADD_PORT_SP_EVENT 12
#define BNXT_GENEVE_DEL_PORT_SP_EVENT 13
+#define BNXT_LINK_SPEED_CHNG_SP_EVENT 14
struct bnxt_pf_info pf;
#ifdef CONFIG_BNXT_SRIOV
@@ -1114,6 +1134,13 @@ struct bnxt {
u32 lpi_tmr_hi;
};
+#define BNXT_RX_STATS_OFFSET(counter) \
+ (offsetof(struct rx_port_stats, counter) / 8)
+
+#define BNXT_TX_STATS_OFFSET(counter) \
+ ((offsetof(struct tx_port_stats, counter) + \
+ sizeof(struct rx_port_stats) + 512) / 8)
+
#ifdef CONFIG_NET_RX_BUSY_POLL
static inline void bnxt_enable_poll(struct bnxt_napi *bnapi)
{
@@ -1216,12 +1243,23 @@ 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 hwrm_send_message_silent(struct bnxt *, void *, u32, int);
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
+ int bmap_size);
+int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
int bnxt_hwrm_set_coal(struct bnxt *);
-int bnxt_hwrm_func_qcaps(struct bnxt *);
+unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
+void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
+unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
+void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max);
+void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max);
+void bnxt_tx_disable(struct bnxt *bp);
+void bnxt_tx_enable(struct bnxt *bp);
int bnxt_hwrm_set_pause(struct bnxt *);
int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
int bnxt_hwrm_fw_set_time(struct bnxt *);
int bnxt_open_nic(struct bnxt *, bool, bool);
int bnxt_close_nic(struct bnxt *, bool, bool);
+int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
+void bnxt_restore_pf_fw_resources(struct bnxt *bp);
#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
new file mode 100644
index 000000000000..fdf2d8caf7bf
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
@@ -0,0 +1,502 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-2016 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/netdevice.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_dcb.h"
+
+#ifdef CONFIG_BNXT_DCB
+static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+ struct hwrm_queue_pri2cos_cfg_input req = {0};
+ int rc = 0, i;
+ u8 *pri2cos;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
+ req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
+ QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
+
+ pri2cos = &req.pri0_cos_queue_id;
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ req.enables |= cpu_to_le32(
+ QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
+
+ pri2cos[i] = bp->q_info[ets->prio_tc[i]].queue_id;
+ }
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ return rc;
+}
+
+static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+ struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_queue_pri2cos_qcfg_input req = {0};
+ int rc = 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
+ req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc) {
+ u8 *pri2cos = &resp->pri0_cos_queue_id;
+ int i, j;
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ u8 queue_id = pri2cos[i];
+
+ for (j = 0; j < bp->max_tc; j++) {
+ if (bp->q_info[j].queue_id == queue_id) {
+ ets->prio_tc[i] = j;
+ break;
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
+ u8 max_tc)
+{
+ struct hwrm_queue_cos2bw_cfg_input req = {0};
+ struct bnxt_cos2bw_cfg cos2bw;
+ int rc = 0, i;
+ void *data;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
+ data = &req.unused_0;
+ for (i = 0; i < max_tc; i++, data += sizeof(cos2bw) - 4) {
+ req.enables |= cpu_to_le32(
+ QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << i);
+
+ memset(&cos2bw, 0, sizeof(cos2bw));
+ cos2bw.queue_id = bp->q_info[i].queue_id;
+ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
+ cos2bw.tsa =
+ QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
+ cos2bw.pri_lvl = i;
+ } else {
+ cos2bw.tsa =
+ QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS;
+ cos2bw.bw_weight = ets->tc_tx_bw[i];
+ }
+ memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
+ if (i == 0) {
+ req.queue_id0 = cos2bw.queue_id;
+ req.unused_0 = 0;
+ }
+ }
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ return rc;
+}
+
+static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+ struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_queue_cos2bw_qcfg_input req = {0};
+ struct bnxt_cos2bw_cfg cos2bw;
+ void *data;
+ int rc, i;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ return rc;
+
+ data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
+ for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) {
+ int j;
+
+ memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4);
+ if (i == 0)
+ cos2bw.queue_id = resp->queue_id0;
+
+ for (j = 0; j < bp->max_tc; j++) {
+ if (bp->q_info[j].queue_id != cos2bw.queue_id)
+ continue;
+ if (cos2bw.tsa ==
+ QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
+ ets->tc_tsa[j] = IEEE_8021QAZ_TSA_STRICT;
+ } else {
+ ets->tc_tsa[j] = IEEE_8021QAZ_TSA_ETS;
+ ets->tc_tx_bw[j] = cos2bw.bw_weight;
+ }
+ }
+ }
+ return 0;
+}
+
+static int bnxt_hwrm_queue_cfg(struct bnxt *bp, unsigned int lltc_mask)
+{
+ struct hwrm_queue_cfg_input req = {0};
+ int i;
+
+ if (netif_running(bp->dev))
+ bnxt_tx_disable(bp);
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_CFG, -1, -1);
+ req.flags = cpu_to_le32(QUEUE_CFG_REQ_FLAGS_PATH_BIDIR);
+ req.enables = cpu_to_le32(QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE);
+
+ /* Configure lossless queues to lossy first */
+ req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
+ for (i = 0; i < bp->max_tc; i++) {
+ if (BNXT_LLQ(bp->q_info[i].queue_profile)) {
+ req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
+ hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ bp->q_info[i].queue_profile =
+ QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
+ }
+ }
+
+ /* Now configure desired queues to lossless */
+ req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
+ for (i = 0; i < bp->max_tc; i++) {
+ if (lltc_mask & (1 << i)) {
+ req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
+ hwrm_send_message(bp, &req, sizeof(req),
+ HWRM_CMD_TIMEOUT);
+ bp->q_info[i].queue_profile =
+ QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
+ }
+ }
+ if (netif_running(bp->dev))
+ bnxt_tx_enable(bp);
+
+ return 0;
+}
+
+static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
+{
+ struct hwrm_queue_pfcenable_cfg_input req = {0};
+ struct ieee_ets *my_ets = bp->ieee_ets;
+ unsigned int tc_mask = 0, pri_mask = 0;
+ u8 i, pri, lltc_count = 0;
+ bool need_q_recfg = false;
+ int rc;
+
+ if (!my_ets)
+ return -EINVAL;
+
+ for (i = 0; i < bp->max_tc; i++) {
+ for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) {
+ if ((pfc->pfc_en & (1 << pri)) &&
+ (my_ets->prio_tc[pri] == i)) {
+ pri_mask |= 1 << pri;
+ tc_mask |= 1 << i;
+ }
+ }
+ if (tc_mask & (1 << i))
+ lltc_count++;
+ }
+ if (lltc_count > bp->max_lltc)
+ return -EINVAL;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
+ req.flags = cpu_to_le32(pri_mask);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < bp->max_tc; i++) {
+ if (tc_mask & (1 << i)) {
+ if (!BNXT_LLQ(bp->q_info[i].queue_profile))
+ need_q_recfg = true;
+ }
+ }
+
+ if (need_q_recfg)
+ rc = bnxt_hwrm_queue_cfg(bp, tc_mask);
+
+ return rc;
+}
+
+static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
+{
+ struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_queue_pfcenable_qcfg_input req = {0};
+ u8 pri_mask;
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ return rc;
+
+ pri_mask = le32_to_cpu(resp->flags);
+ pfc->pfc_en = pri_mask;
+ return 0;
+}
+
+static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
+{
+ int total_ets_bw = 0;
+ u8 max_tc = 0;
+ int i;
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ if (ets->prio_tc[i] > bp->max_tc) {
+ netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n",
+ ets->prio_tc[i]);
+ return -EINVAL;
+ }
+ if (ets->prio_tc[i] > max_tc)
+ max_tc = ets->prio_tc[i];
+
+ if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc)
+ return -EINVAL;
+
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ total_ets_bw += ets->tc_tx_bw[i];
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ }
+ if (total_ets_bw > 100)
+ return -EINVAL;
+
+ *tc = max_tc + 1;
+ return 0;
+}
+
+static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct ieee_ets *my_ets = bp->ieee_ets;
+
+ ets->ets_cap = bp->max_tc;
+
+ if (!my_ets) {
+ int rc;
+
+ if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
+ return 0;
+
+ my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
+ if (!my_ets)
+ return 0;
+ rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
+ if (rc)
+ return 0;
+ rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
+ if (rc)
+ return 0;
+ }
+
+ ets->cbs = my_ets->cbs;
+ memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
+ memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
+ memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
+ memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
+ return 0;
+}
+
+static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct ieee_ets *my_ets = bp->ieee_ets;
+ u8 max_tc = 0;
+ int rc, i;
+
+ if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+ !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+ return -EINVAL;
+
+ rc = bnxt_ets_validate(bp, ets, &max_tc);
+ if (!rc) {
+ if (!my_ets) {
+ my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
+ if (!my_ets)
+ return -ENOMEM;
+ /* initialize PRI2TC mappings to invalid value */
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+ my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS;
+ bp->ieee_ets = my_ets;
+ }
+ rc = bnxt_setup_mq_tc(dev, max_tc);
+ if (rc)
+ return rc;
+ rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc);
+ if (rc)
+ return rc;
+ rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets);
+ if (rc)
+ return rc;
+ memcpy(my_ets, ets, sizeof(*my_ets));
+ }
+ return rc;
+}
+
+static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ __le64 *stats = (__le64 *)bp->hw_rx_port_stats;
+ struct ieee_pfc *my_pfc = bp->ieee_pfc;
+ long rx_off, tx_off;
+ int i, rc;
+
+ pfc->pfc_cap = bp->max_lltc;
+
+ if (!my_pfc) {
+ if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
+ return 0;
+
+ my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
+ if (!my_pfc)
+ return 0;
+ bp->ieee_pfc = my_pfc;
+ rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc);
+ if (rc)
+ return 0;
+ }
+
+ pfc->pfc_en = my_pfc->pfc_en;
+ pfc->mbc = my_pfc->mbc;
+ pfc->delay = my_pfc->delay;
+
+ if (!stats)
+ return 0;
+
+ rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0);
+ tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0);
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) {
+ pfc->requests[i] = le64_to_cpu(*(stats + tx_off));
+ pfc->indications[i] = le64_to_cpu(*(stats + rx_off));
+ }
+
+ return 0;
+}
+
+static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct ieee_pfc *my_pfc = bp->ieee_pfc;
+ int rc;
+
+ if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+ !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+ return -EINVAL;
+
+ if (!my_pfc) {
+ my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
+ if (!my_pfc)
+ return -ENOMEM;
+ bp->ieee_pfc = my_pfc;
+ }
+ rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc);
+ if (!rc)
+ memcpy(my_pfc, pfc, sizeof(*my_pfc));
+
+ return rc;
+}
+
+static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc = -EINVAL;
+
+ if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+ !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+ return -EINVAL;
+
+ rc = dcb_ieee_setapp(dev, app);
+ return rc;
+}
+
+static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+
+ if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+ return -EINVAL;
+
+ rc = dcb_ieee_delapp(dev, app);
+ return rc;
+}
+
+static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ return bp->dcbx_cap;
+}
+
+static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ /* only support IEEE */
+ if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE))
+ return 1;
+
+ if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp))
+ return 1;
+
+ if (mode == bp->dcbx_cap)
+ return 0;
+
+ bp->dcbx_cap = mode;
+ return 0;
+}
+
+static const struct dcbnl_rtnl_ops dcbnl_ops = {
+ .ieee_getets = bnxt_dcbnl_ieee_getets,
+ .ieee_setets = bnxt_dcbnl_ieee_setets,
+ .ieee_getpfc = bnxt_dcbnl_ieee_getpfc,
+ .ieee_setpfc = bnxt_dcbnl_ieee_setpfc,
+ .ieee_setapp = bnxt_dcbnl_ieee_setapp,
+ .ieee_delapp = bnxt_dcbnl_ieee_delapp,
+ .getdcbx = bnxt_dcbnl_getdcbx,
+ .setdcbx = bnxt_dcbnl_setdcbx,
+};
+
+void bnxt_dcb_init(struct bnxt *bp)
+{
+ if (bp->hwrm_spec_code < 0x10501)
+ return;
+
+ bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
+ if (BNXT_PF(bp))
+ bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
+ else
+ bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
+ bp->dev->dcbnl_ops = &dcbnl_ops;
+}
+
+void bnxt_dcb_free(struct bnxt *bp)
+{
+ kfree(bp->ieee_pfc);
+ kfree(bp->ieee_ets);
+ bp->ieee_pfc = NULL;
+ bp->ieee_ets = NULL;
+}
+
+#else
+
+void bnxt_dcb_init(struct bnxt *bp)
+{
+}
+
+void bnxt_dcb_free(struct bnxt *bp)
+{
+}
+
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
new file mode 100644
index 000000000000..35a0d28cf2fd
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
@@ -0,0 +1,41 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-2016 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_DCB_H
+#define BNXT_DCB_H
+
+#include <net/dcbnl.h>
+
+struct bnxt_dcb {
+ u8 max_tc;
+ struct ieee_pfc *ieee_pfc;
+ struct ieee_ets *ieee_ets;
+ u8 dcbx_cap;
+ u8 default_pri;
+};
+
+struct bnxt_cos2bw_cfg {
+ u8 pad[3];
+ u8 queue_id;
+ __le32 min_bw;
+ __le32 max_bw;
+ u8 tsa;
+ u8 pri_lvl;
+ u8 bw_weight;
+ u8 unused;
+};
+
+#define BNXT_LLQ(q_profile) \
+ ((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS)
+
+#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300
+
+void bnxt_dcb_init(struct bnxt *bp);
+void bnxt_dcb_free(struct bnxt *bp);
+#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index a7e04ff4eaed..784aa77610bc 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -107,16 +107,9 @@ static int bnxt_set_coalesce(struct net_device *dev,
#define BNXT_NUM_STATS 21
-#define BNXT_RX_STATS_OFFSET(counter) \
- (offsetof(struct rx_port_stats, counter) / 8)
-
#define BNXT_RX_STATS_ENTRY(counter) \
{ BNXT_RX_STATS_OFFSET(counter), __stringify(counter) }
-#define BNXT_TX_STATS_OFFSET(counter) \
- ((offsetof(struct tx_port_stats, counter) + \
- sizeof(struct rx_port_stats) + 512) / 8)
-
#define BNXT_TX_STATS_ENTRY(counter) \
{ BNXT_TX_STATS_OFFSET(counter), __stringify(counter) }
@@ -150,6 +143,14 @@ static const struct {
BNXT_RX_STATS_ENTRY(rx_tagged_frames),
BNXT_RX_STATS_ENTRY(rx_double_tagged_frames),
BNXT_RX_STATS_ENTRY(rx_good_frames),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri0),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri1),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri2),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri3),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri4),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri5),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri6),
+ BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri7),
BNXT_RX_STATS_ENTRY(rx_undrsz_frames),
BNXT_RX_STATS_ENTRY(rx_eee_lpi_events),
BNXT_RX_STATS_ENTRY(rx_eee_lpi_duration),
@@ -179,6 +180,14 @@ static const struct {
BNXT_TX_STATS_ENTRY(tx_fcs_err_frames),
BNXT_TX_STATS_ENTRY(tx_err),
BNXT_TX_STATS_ENTRY(tx_fifo_underruns),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri0),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri1),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri2),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri3),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri4),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri5),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri6),
+ BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri7),
BNXT_TX_STATS_ENTRY(tx_eee_lpi_events),
BNXT_TX_STATS_ENTRY(tx_eee_lpi_duration),
BNXT_TX_STATS_ENTRY(tx_total_collisions),
@@ -542,6 +551,146 @@ fltr_err:
return rc;
}
+#endif
+
+static u64 get_ethtool_ipv4_rss(struct bnxt *bp)
+{
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4)
+ return RXH_IP_SRC | RXH_IP_DST;
+ return 0;
+}
+
+static u64 get_ethtool_ipv6_rss(struct bnxt *bp)
+{
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6)
+ return RXH_IP_SRC | RXH_IP_DST;
+ return 0;
+}
+
+static int bnxt_grxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+{
+ cmd->data = 0;
+ switch (cmd->flow_type) {
+ case TCP_V4_FLOW:
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4)
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ cmd->data |= get_ethtool_ipv4_rss(bp);
+ break;
+ case UDP_V4_FLOW:
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4)
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case IPV4_FLOW:
+ cmd->data |= get_ethtool_ipv4_rss(bp);
+ break;
+
+ case TCP_V6_FLOW:
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6)
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ cmd->data |= get_ethtool_ipv6_rss(bp);
+ break;
+ case UDP_V6_FLOW:
+ if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6)
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case IPV6_FLOW:
+ cmd->data |= get_ethtool_ipv6_rss(bp);
+ break;
+ }
+ return 0;
+}
+
+#define RXH_4TUPLE (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)
+#define RXH_2TUPLE (RXH_IP_SRC | RXH_IP_DST)
+
+static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+{
+ u32 rss_hash_cfg = bp->rss_hash_cfg;
+ int tuple, rc = 0;
+
+ if (cmd->data == RXH_4TUPLE)
+ tuple = 4;
+ else if (cmd->data == RXH_2TUPLE)
+ tuple = 2;
+ else if (!cmd->data)
+ tuple = 0;
+ else
+ return -EINVAL;
+
+ if (cmd->flow_type == TCP_V4_FLOW) {
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
+ if (tuple == 4)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
+ } else if (cmd->flow_type == UDP_V4_FLOW) {
+ if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
+ return -EINVAL;
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
+ if (tuple == 4)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
+ } else if (cmd->flow_type == TCP_V6_FLOW) {
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+ if (tuple == 4)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+ } else if (cmd->flow_type == UDP_V6_FLOW) {
+ if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
+ return -EINVAL;
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+ if (tuple == 4)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+ } else if (tuple == 4) {
+ return -EINVAL;
+ }
+
+ switch (cmd->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case IPV4_FLOW:
+ if (tuple == 2)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
+ else if (!tuple)
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
+ break;
+
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case IPV6_FLOW:
+ if (tuple == 2)
+ rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
+ else if (!tuple)
+ rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
+ break;
+ }
+
+ if (bp->rss_hash_cfg == rss_hash_cfg)
+ return 0;
+
+ bp->rss_hash_cfg = rss_hash_cfg;
+ if (netif_running(bp->dev)) {
+ bnxt_close_nic(bp, false, false);
+ rc = bnxt_open_nic(bp, false, false);
+ }
+ return rc;
+}
static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
@@ -550,6 +699,7 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
int rc = 0;
switch (cmd->cmd) {
+#ifdef CONFIG_RFS_ACCEL
case ETHTOOL_GRXRINGS:
cmd->data = bp->rx_nr_rings;
break;
@@ -566,6 +716,11 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
case ETHTOOL_GRXCLSRULE:
rc = bnxt_grxclsrule(bp, cmd);
break;
+#endif
+
+ case ETHTOOL_GRXFH:
+ rc = bnxt_grxfh(bp, cmd);
+ break;
default:
rc = -EOPNOTSUPP;
@@ -574,7 +729,23 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
return rc;
}
-#endif
+
+static int bnxt_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXFH:
+ rc = bnxt_srxfh(bp, cmd);
+ break;
+
+ default:
+ rc = -EOPNOTSUPP;
+ break;
+ }
+ return rc;
+}
static u32 bnxt_get_rxfh_indir_size(struct net_device *dev)
{
@@ -1885,9 +2056,8 @@ const struct ethtool_ops bnxt_ethtool_ops = {
.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
+ .set_rxnfc = bnxt_set_rxnfc,
.get_rxfh_indir_size = bnxt_get_rxfh_indir_size,
.get_rxfh_key_size = bnxt_get_rxfh_key_size,
.get_rxfh = bnxt_get_rxfh,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
index 04a96cc3498a..2ddfa51519a1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -1,6 +1,7 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2016 Broadcom Corporation
+ * Copyright (c) 2016 Broadcom Limited
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -10,29 +11,22 @@
#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;
-};
+/* HSI and HWRM Specification 1.6.0 */
+#define HWRM_VERSION_MAJOR 1
+#define HWRM_VERSION_MINOR 6
+#define HWRM_VERSION_UPDATE 0
+
+#define HWRM_VERSION_STR "1.6.0"
+/*
+ * 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 */
/* Statistics Ejection Buffer Completion Record (16 bytes) */
struct eject_cmpl {
@@ -50,77 +44,77 @@ struct eject_cmpl {
/* 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
+ #define CMPL_TYPE_MASK 0x3fUL
+ #define CMPL_TYPE_SFT 0
+ #define CMPL_TYPE_HWRM_DONE 0x20UL
__le16 sequence_id;
__le32 unused_1;
__le32 v;
- #define HWRM_CMPL_V 0x1UL
+ #define 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
- #define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK 0xffc0UL
- #define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT 6
+ #define FWD_REQ_CMPL_TYPE_MASK 0x3fUL
+ #define FWD_REQ_CMPL_TYPE_SFT 0
+ #define FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ 0x22UL
+ #define FWD_REQ_CMPL_REQ_LEN_MASK 0xffc0UL
+ #define 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
+ #define FWD_REQ_CMPL_V 0x1UL
+ #define FWD_REQ_CMPL_REQ_BUF_ADDR_MASK 0xfffffffeUL
+ #define 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
+ #define FWD_RESP_CMPL_TYPE_MASK 0x3fUL
+ #define FWD_RESP_CMPL_TYPE_SFT 0
+ #define FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP 0x24UL
__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
+ #define FWD_RESP_CMPL_V 0x1UL
+ #define FWD_RESP_CMPL_RESP_BUF_ADDR_MASK 0xfffffffeUL
+ #define 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
+ #define ASYNC_EVENT_CMPL_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE 0x7UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD 0x21UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR 0x30UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE 0x33UL
- #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE 0x1UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE 0x7UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD 0x21UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR 0x30UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE 0x33UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL
__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
+ #define ASYNC_EVENT_CMPL_V 0x1UL
+ #define ASYNC_EVENT_CMPL_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
@@ -129,670 +123,391 @@ struct hwrm_async_event_cmpl {
/* 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
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
__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
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (0x0UL << 0)
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (0x1UL << 0)
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK 0xeUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0UL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (0x0UL << 0)
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (0x1UL << 0)
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK 0xeUL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0UL
+ #define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4
};
/* 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
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE 0x1UL
__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
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK 0xffffUL
+ #define 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
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
__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
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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_NEW_LINK_SPEED_100MBPS_100GB (0x3e8UL << 1)
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB
- #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
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK 0xfffeUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (0x1UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (0xaUL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (0x14UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (0x19UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (0x64UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (0xc8UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (0x3e8UL << 1)
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL
+ #define 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
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
__le32 event_data2;
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_ETS 0x1UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_PFC 0x2UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_APP 0x4UL
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
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_MASK 0xff0000UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_SFT 16
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_NONE (0xffUL << 16)
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_LAST ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_NONE
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_MASK 0xff000000UL
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_SFT 24
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_NONE (0xffUL << 24)
+ #define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_LAST ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_NONE
};
/* 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
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
__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
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V 0x1UL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK 0xff0000UL
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (0x0UL << 16)
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (0x1UL << 16)
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (0x2UL << 16)
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (0x3UL << 16)
- #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK 0xff0000UL
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (0x0UL << 16)
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (0x1UL << 16)
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (0x2UL << 16)
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (0x3UL << 16)
+ #define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN
};
/* HWRM Asynchronous Event Completion Record for link speed config not allowed (16 bytes) */
struct hwrm_async_event_cmpl_link_speed_cfg_not_allowed {
__le16 type;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK 0x3fUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
__le32 event_data2;
u8 opaque_v;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
};
/* HWRM Asynchronous Event Completion Record for link speed configuration change (16 bytes) */
struct hwrm_async_event_cmpl_link_speed_cfg_change {
__le16 type;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK 0x3fUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
__le32 event_data2;
u8 opaque_v;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK 0xfeUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE 0x10000UL
- #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG 0x20000UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE 0x10000UL
+ #define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG 0x20000UL
};
/* 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
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
__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
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V 0x1UL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define 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
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ __le16 event_id;
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
+ __le32 event_data2;
+ u8 opaque_v;
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V 0x1UL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT 1
+ u8 timestamp_lo;
+ __le16 timestamp_hi;
+ __le32 event_data1;
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record to indicate completion of FLR related processing (16 bytes) */
+struct hwrm_async_event_cmpl_func_flr_proc_cmplt {
+ __le16 type;
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
__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
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_V 0x1UL
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_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
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
__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
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V 0x1UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK 0x70000UL
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK 0x70000UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16
};
/* 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
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD 0x21UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD 0x21UL
__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
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V 0x1UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK 0x70000UL
- #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK 0x70000UL
+ #define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16
};
/* 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
+ #define ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR 0x30UL
+ #define ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR 0x30UL
__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
+ #define ASYNC_EVENT_CMPL_VF_FLR_V 0x1UL
+ #define ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK 0xffffUL
+ #define 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
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
__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
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__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
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0
};
/* HWRM Asynchronous Event Completion Record for PF-VF communication status change (16 bytes) */
struct hwrm_async_event_cmpl_pf_vf_comm_status_change {
__le16 type;
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK 0x3fUL
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
__le32 event_data2;
u8 opaque_v;
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED 0x1UL
+ #define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED 0x1UL
};
/* HWRM Asynchronous Event Completion Record for VF configuration change (16 bytes) */
struct hwrm_async_event_cmpl_vf_cfg_change {
__le16 type;
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK 0x3fUL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT 0
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE 0x33UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE 0x33UL
__le32 event_data2;
u8 opaque_v;
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK 0xfeUL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT 1
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V 0x1UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE 0x2UL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE 0x4UL
- #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE 0x8UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE 0x1UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE 0x2UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE 0x4UL
+ #define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE 0x8UL
};
/* 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
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT 0x2eUL
__le16 event_id;
- #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR 0xffUL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR 0xffUL
__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
- #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL 0x1UL
- #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL 0x2UL
- #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK 0xffUL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING 0x0UL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL 0x1UL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL 0x2UL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL
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
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_V 0x1UL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT 1
u8 timestamp_lo;
__le16 timestamp_hi;
__le32 event_data1;
- #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL
-};
-
-/* HW Resource Manager Specification 1.5.1 */
-#define HWRM_VERSION_MAJOR 1
-#define HWRM_VERSION_MINOR 5
-#define HWRM_VERSION_UPDATE 1
-
-#define HWRM_VERSION_STR "1.5.1"
-/*
- * 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_BUF_UNRGTR (0xeUL)
- #define HWRM_FUNC_VF_CFG (0xfUL)
- #define RESERVED1 (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_PORT_PHY_CFG (0x20UL)
- #define HWRM_PORT_MAC_CFG (0x21UL)
- #define HWRM_PORT_TS_QUERY (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_PORT_PHY_QCAPS (0x2aUL)
- #define HWRM_PORT_PHY_I2C_WRITE (0x2bUL)
- #define HWRM_PORT_PHY_I2C_READ (0x2cUL)
- #define HWRM_QUEUE_QPORTCFG (0x30UL)
- #define HWRM_QUEUE_QCFG (0x31UL)
- #define HWRM_QUEUE_CFG (0x32UL)
- #define RESERVED2 (0x33UL)
- #define RESERVED3 (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_VNIC_QCAPS (0x4aUL)
- #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 RESERVED5 (0x64UL)
- #define RESERVED6 (0x65UL)
- #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (0x70UL)
- #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (0x71UL)
- #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 RESERVED4 (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_CFA_EM_FLOW_ALLOC (0x9cUL)
- #define HWRM_CFA_EM_FLOW_FREE (0x9dUL)
- #define HWRM_CFA_EM_FLOW_CFG (0x9eUL)
- #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_FW_SET_TIME (0xc8UL)
- #define HWRM_FW_GET_TIME (0xc9UL)
- #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_WOL_FILTER_ALLOC (0xf0UL)
- #define HWRM_WOL_FILTER_FREE (0xf1UL)
- #define HWRM_WOL_FILTER_QCFG (0xf2UL)
- #define HWRM_WOL_REASON_QCFG (0xf3UL)
- #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_INSTALL_UPDATE (0xfff3UL)
- #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 cmd_err;
- 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;
+ #define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL
};
/* hwrm_ver_get */
@@ -1041,6 +756,7 @@ struct hwrm_func_qcaps_output {
#define FUNC_QCAPS_RESP_FLAGS_TX_BW_CFG_SUPPORTED 0x100UL
#define FUNC_QCAPS_RESP_FLAGS_VF_TX_RING_RL_SUPPORTED 0x200UL
#define FUNC_QCAPS_RESP_FLAGS_VF_BW_CFG_SUPPORTED 0x400UL
+ #define FUNC_QCAPS_RESP_FLAGS_STD_TX_RING_MODE_SUPPORTED 0x800UL
u8 mac_address[6];
__le16 max_rsscos_ctx;
__le16 max_cmpl_rings;
@@ -1090,6 +806,7 @@ struct hwrm_func_qcfg_output {
#define FUNC_QCFG_RESP_FLAGS_OOB_WOL_MAGICPKT_ENABLED 0x1UL
#define FUNC_QCFG_RESP_FLAGS_OOB_WOL_BMP_ENABLED 0x2UL
#define FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED 0x4UL
+ #define FUNC_QCFG_RESP_FLAGS_STD_TX_RING_MODE_ENABLED 0x8UL
u8 mac_address[6];
__le16 pci_id;
__le16 alloc_rsscos_ctx;
@@ -1166,6 +883,7 @@ struct hwrm_func_cfg_input {
#define FUNC_CFG_REQ_FLAGS_DISABLE_STP 0x40UL
#define FUNC_CFG_REQ_FLAGS_DISABLE_LLDP 0x80UL
#define FUNC_CFG_REQ_FLAGS_DISABLE_PTPV2 0x100UL
+ #define FUNC_CFG_REQ_FLAGS_STD_TX_RING_MODE 0x200UL
__le32 enables;
#define FUNC_CFG_REQ_ENABLES_MTU 0x1UL
#define FUNC_CFG_REQ_ENABLES_MRU 0x2UL
@@ -1399,6 +1117,7 @@ struct hwrm_func_drv_rgtr_input {
#define FUNC_DRV_RGTR_REQ_OS_TYPE_ESXI 0x68UL
#define FUNC_DRV_RGTR_REQ_OS_TYPE_WIN864 0x73UL
#define FUNC_DRV_RGTR_REQ_OS_TYPE_WIN2012R2 0x74UL
+ #define FUNC_DRV_RGTR_REQ_OS_TYPE_UEFI 0x8000UL
u8 ver_maj;
u8 ver_min;
u8 ver_upd;
@@ -1531,6 +1250,7 @@ struct hwrm_func_drv_qver_output {
#define FUNC_DRV_QVER_RESP_OS_TYPE_ESXI 0x68UL
#define FUNC_DRV_QVER_RESP_OS_TYPE_WIN864 0x73UL
#define FUNC_DRV_QVER_RESP_OS_TYPE_WIN2012R2 0x74UL
+ #define FUNC_DRV_QVER_RESP_OS_TYPE_UEFI 0x8000UL
u8 ver_maj;
u8 ver_min;
u8 ver_upd;
@@ -1549,7 +1269,7 @@ struct hwrm_port_phy_cfg_input {
__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_DEPRECATED 0x2UL
#define PORT_PHY_CFG_REQ_FLAGS_FORCE 0x4UL
#define PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG 0x8UL
#define PORT_PHY_CFG_REQ_FLAGS_EEE_ENABLE 0x10UL
@@ -1562,6 +1282,7 @@ struct hwrm_port_phy_cfg_input {
#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE 0x800UL
#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_ENABLE 0x1000UL
#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_DISABLE 0x2000UL
+ #define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN 0x4000UL
__le32 enables;
#define PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE 0x1UL
#define PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX 0x2UL
@@ -2091,31 +1812,6 @@ struct hwrm_port_lpbk_clr_stats_output {
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_port_phy_qcaps */
/* Input (24 bytes) */
struct hwrm_port_phy_qcaps_input {
@@ -2337,6 +2033,39 @@ struct hwrm_queue_cfg_output {
u8 valid;
};
+/* hwrm_queue_pfcenable_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_pfcenable_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 (16 bytes) */
+struct hwrm_queue_pfcenable_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 flags;
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI0_PFC_ENABLED 0x1UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI1_PFC_ENABLED 0x2UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI2_PFC_ENABLED 0x4UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI3_PFC_ENABLED 0x8UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI4_PFC_ENABLED 0x10UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI5_PFC_ENABLED 0x20UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI6_PFC_ENABLED 0x40UL
+ #define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI7_PFC_ENABLED 0x80UL
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
/* hwrm_queue_pfcenable_cfg */
/* Input (24 bytes) */
struct hwrm_queue_pfcenable_cfg_input {
@@ -2371,6 +2100,48 @@ struct hwrm_queue_pfcenable_cfg_output {
u8 valid;
};
+/* hwrm_queue_pri2cos_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_pri2cos_qcfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le32 flags;
+ #define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH 0x1UL
+ #define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_TX (0x0UL << 0)
+ #define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_RX (0x1UL << 0)
+ #define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_LAST QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_RX
+ #define QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN 0x2UL
+ u8 port_id;
+ u8 unused_0[3];
+};
+
+/* Output (24 bytes) */
+struct hwrm_queue_pri2cos_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 pri0_cos_queue_id;
+ u8 pri1_cos_queue_id;
+ u8 pri2_cos_queue_id;
+ u8 pri3_cos_queue_id;
+ u8 pri4_cos_queue_id;
+ u8 pri5_cos_queue_id;
+ u8 pri6_cos_queue_id;
+ u8 pri7_cos_queue_id;
+ u8 queue_cfg_info;
+ #define QUEUE_PRI2COS_QCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG 0x1UL
+ u8 unused_0;
+ __le16 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
/* hwrm_queue_pri2cos_cfg */
/* Input (40 bytes) */
struct hwrm_queue_pri2cos_cfg_input {
@@ -2421,6 +2192,257 @@ struct hwrm_queue_pri2cos_cfg_output {
u8 valid;
};
+/* hwrm_queue_cos2bw_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_cos2bw_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 (112 bytes) */
+struct hwrm_queue_cos2bw_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 queue_id0;
+ u8 unused_0;
+ __le16 unused_1;
+ __le32 queue_id0_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id0_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id0_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id0_pri_lvl;
+ u8 queue_id0_bw_weight;
+ u8 queue_id1;
+ __le32 queue_id1_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id1_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id1_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id1_pri_lvl;
+ u8 queue_id1_bw_weight;
+ u8 queue_id2;
+ __le32 queue_id2_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id2_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id2_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id2_pri_lvl;
+ u8 queue_id2_bw_weight;
+ u8 queue_id3;
+ __le32 queue_id3_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id3_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id3_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id3_pri_lvl;
+ u8 queue_id3_bw_weight;
+ u8 queue_id4;
+ __le32 queue_id4_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id4_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id4_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id4_pri_lvl;
+ u8 queue_id4_bw_weight;
+ u8 queue_id5;
+ __le32 queue_id5_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id5_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id5_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id5_pri_lvl;
+ u8 queue_id5_bw_weight;
+ u8 queue_id6;
+ __le32 queue_id6_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id6_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id6_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id6_pri_lvl;
+ u8 queue_id6_bw_weight;
+ u8 queue_id7;
+ __le32 queue_id7_min_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID
+ __le32 queue_id7_max_bw;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_SFT 0
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_RSVD 0x10000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_SFT 29
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID
+ u8 queue_id7_tsa_assign;
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_SP 0x0UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_ETS 0x1UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+ #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST 0xffUL
+ u8 queue_id7_pri_lvl;
+ u8 queue_id7_bw_weight;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 unused_5;
+ u8 valid;
+};
+
/* hwrm_queue_cos2bw_cfg */
/* Input (128 bytes) */
struct hwrm_queue_cos2bw_cfg_input {
@@ -3802,7 +3824,9 @@ struct hwrm_stat_ctx_alloc_input {
__le64 resp_addr;
__le64 stats_dma_addr;
__le32 update_period_ms;
- __le32 unused_0;
+ u8 stat_ctx_flags;
+ #define STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE 0x1UL
+ u8 unused_0[3];
};
/* Output (16 bytes) */
@@ -4023,6 +4047,75 @@ struct hwrm_fw_set_time_output {
u8 valid;
};
+/* hwrm_fw_set_structured_data */
+/* Input (32 bytes) */
+struct hwrm_fw_set_structured_data_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 src_data_addr;
+ __le16 data_len;
+ u8 hdr_cnt;
+ u8 unused_0;
+ __le16 port_id;
+ __le16 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_set_structured_data_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_get_structured_data */
+/* Input (40 bytes) */
+struct hwrm_fw_get_structured_data_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 dest_data_addr;
+ __le16 data_len;
+ __le16 structure_id;
+ __le16 subtype;
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_ALL 0xffffUL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_ADMIN 0x100UL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_PEER 0x101UL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_OPERATIONAL 0x102UL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_ADMIN 0x200UL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_PEER 0x201UL
+ #define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_OPERATIONAL 0x202UL
+ u8 count;
+ u8 unused_0;
+ __le16 port_id;
+ __le16 unused_1[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_get_structured_data_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 hdr_cnt;
+ u8 unused_0;
+ __le16 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 unused_4;
+ u8 valid;
+};
+
/* hwrm_exec_fwd_resp */
/* Input (128 bytes) */
struct hwrm_exec_fwd_resp_input {
@@ -4515,4 +4608,363 @@ struct hwrm_nvm_install_update_output {
u8 valid;
};
+/* Hardware Resource Manager Specification */
+/* 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_BUF_UNRGTR (0xeUL)
+ #define HWRM_FUNC_VF_CFG (0xfUL)
+ #define RESERVED1 (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_PORT_PHY_CFG (0x20UL)
+ #define HWRM_PORT_MAC_CFG (0x21UL)
+ #define HWRM_PORT_TS_QUERY (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 RESERVED7 (0x29UL)
+ #define HWRM_PORT_PHY_QCAPS (0x2aUL)
+ #define HWRM_PORT_PHY_I2C_WRITE (0x2bUL)
+ #define HWRM_PORT_PHY_I2C_READ (0x2cUL)
+ #define HWRM_PORT_LED_CFG (0x2dUL)
+ #define HWRM_PORT_LED_QCFG (0x2eUL)
+ #define HWRM_PORT_LED_QCAPS (0x2fUL)
+ #define HWRM_QUEUE_QPORTCFG (0x30UL)
+ #define HWRM_QUEUE_QCFG (0x31UL)
+ #define HWRM_QUEUE_CFG (0x32UL)
+ #define RESERVED2 (0x33UL)
+ #define RESERVED3 (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_VNIC_QCAPS (0x4aUL)
+ #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 RESERVED5 (0x64UL)
+ #define RESERVED6 (0x65UL)
+ #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (0x70UL)
+ #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (0x71UL)
+ #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 RESERVED4 (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_CFA_EM_FLOW_ALLOC (0x9cUL)
+ #define HWRM_CFA_EM_FLOW_FREE (0x9dUL)
+ #define HWRM_CFA_EM_FLOW_CFG (0x9eUL)
+ #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_FW_SET_TIME (0xc8UL)
+ #define HWRM_FW_GET_TIME (0xc9UL)
+ #define HWRM_FW_SET_STRUCTURED_DATA (0xcaUL)
+ #define HWRM_FW_GET_STRUCTURED_DATA (0xcbUL)
+ #define HWRM_FW_IPC_MAILBOX (0xccUL)
+ #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_WOL_FILTER_ALLOC (0xf0UL)
+ #define HWRM_WOL_FILTER_FREE (0xf1UL)
+ #define HWRM_WOL_FILTER_QCFG (0xf2UL)
+ #define HWRM_WOL_REASON_QCFG (0xf3UL)
+ #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_GET_VARIABLE (0xfff1UL)
+ #define HWRM_NVM_SET_VARIABLE (0xfff2UL)
+ #define HWRM_NVM_INSTALL_UPDATE (0xfff3UL)
+ #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 cmd_err;
+ 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;
+};
+
+/* Periodic Statistics Context DMA to host (160 bytes) */
+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;
+};
+
+/* Structure data header (16 bytes) */
+struct hwrm_struct_hdr {
+ __le16 struct_id;
+ #define STRUCT_HDR_STRUCT_ID_LLDP_CFG 0x41bUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_ETS_CFG 0x41dUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_PFC_CFG 0x41fUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_APP_CFG 0x421UL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_STATE_CFG 0x422UL
+ #define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC_CFG 0x424UL
+ #define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE_CFG 0x426UL
+ __le16 len;
+ u8 version;
+ u8 count;
+ __le16 subtype;
+ __le16 next_offset;
+ #define STRUCT_HDR_NEXT_OFFSET_LAST 0x0UL
+ __le16 unused_0[3];
+};
+
+/* DCBX Application configuration structure (8 bytes) */
+struct hwrm_struct_data_dcbx_app_cfg {
+ __le16 protocol_id;
+ u8 protocol_selector;
+ #define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_ETHER_TYPE 0x1UL
+ #define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_TCP_PORT 0x2UL
+ #define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_UDP_PORT 0x3UL
+ #define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_TCP_UDP_PORT 0x4UL
+ u8 priority;
+ u8 valid;
+ u8 unused_0[3];
+};
+
#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
index 60e2af8678bd..c69602508666 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -34,8 +34,7 @@ static int bnxt_hwrm_fwd_async_event_cmpl(struct bnxt *bp,
/* broadcast this async event to all VFs */
req.encap_async_event_target_id = cpu_to_le16(0xffff);
async_cmpl = (struct hwrm_async_event_cmpl *)req.encap_async_event_cmpl;
- async_cmpl->type =
- cpu_to_le16(HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT);
+ async_cmpl->type = cpu_to_le16(ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT);
async_cmpl->event_id = cpu_to_le16(event_id);
mutex_lock(&bp->hwrm_cmd_lock);
@@ -288,7 +287,7 @@ int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link)
}
if (vf->flags & (BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED))
rc = bnxt_hwrm_fwd_async_event_cmpl(bp, vf,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
+ ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
return rc;
}
@@ -421,15 +420,7 @@ static int bnxt_hwrm_func_cfg(struct bnxt *bp, int num_vfs)
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, pf->max_cp_rings, 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 = (pf->max_cp_rings - bp->cp_nr_rings) / num_vfs; */
+ vf_cp_rings = (pf->max_cp_rings - bp->cp_nr_rings) / num_vfs;
vf_stat_ctx = (pf->max_stat_ctxs - bp->num_stat_ctxs) / num_vfs;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
vf_rx_rings = (pf->max_rx_rings - bp->rx_nr_rings * 2) /
@@ -578,8 +569,7 @@ void bnxt_sriov_disable(struct bnxt *bp)
if (pci_vfs_assigned(bp->pdev)) {
bnxt_hwrm_fwd_async_event_cmpl(
- bp, NULL,
- HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
+ bp, NULL, ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
netdev_warn(bp->dev, "Unable to free %d VFs because some are assigned to VMs.\n",
num_vfs);
} else {
@@ -592,7 +582,9 @@ void bnxt_sriov_disable(struct bnxt *bp)
bp->pf.active_vfs = 0;
/* Reclaim all resources for the PF. */
- bnxt_hwrm_func_qcaps(bp);
+ rtnl_lock();
+ bnxt_restore_pf_fw_resources(bp);
+ rtnl_unlock();
}
int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
new file mode 100644
index 000000000000..8b7464b76501
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -0,0 +1,346 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <asm/byteorder.h>
+#include <linux/bitmap.h>
+
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_ulp.h"
+
+static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
+ struct bnxt_ulp_ops *ulp_ops, void *handle)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_ulp *ulp;
+
+ ASSERT_RTNL();
+ if (ulp_id >= BNXT_MAX_ULP)
+ return -EINVAL;
+
+ ulp = &edev->ulp_tbl[ulp_id];
+ if (rcu_access_pointer(ulp->ulp_ops)) {
+ netdev_err(bp->dev, "ulp id %d already registered\n", ulp_id);
+ return -EBUSY;
+ }
+ if (ulp_id == BNXT_ROCE_ULP) {
+ unsigned int max_stat_ctxs;
+
+ max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
+ if (max_stat_ctxs <= BNXT_MIN_ROCE_STAT_CTXS ||
+ bp->num_stat_ctxs == max_stat_ctxs)
+ return -ENOMEM;
+ bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs -
+ BNXT_MIN_ROCE_STAT_CTXS);
+ }
+
+ atomic_set(&ulp->ref_count, 0);
+ ulp->handle = handle;
+ rcu_assign_pointer(ulp->ulp_ops, ulp_ops);
+
+ if (ulp_id == BNXT_ROCE_ULP) {
+ if (test_bit(BNXT_STATE_OPEN, &bp->state))
+ bnxt_hwrm_vnic_cfg(bp, 0);
+ }
+
+ return 0;
+}
+
+static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_ulp *ulp;
+ int i = 0;
+
+ ASSERT_RTNL();
+ if (ulp_id >= BNXT_MAX_ULP)
+ return -EINVAL;
+
+ ulp = &edev->ulp_tbl[ulp_id];
+ if (!rcu_access_pointer(ulp->ulp_ops)) {
+ netdev_err(bp->dev, "ulp id %d not registered\n", ulp_id);
+ return -EINVAL;
+ }
+ if (ulp_id == BNXT_ROCE_ULP) {
+ unsigned int max_stat_ctxs;
+
+ max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
+ bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs + 1);
+ }
+ if (ulp->max_async_event_id)
+ bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0);
+
+ RCU_INIT_POINTER(ulp->ulp_ops, NULL);
+ synchronize_rcu();
+ ulp->max_async_event_id = 0;
+ ulp->async_events_bmap = NULL;
+ while (atomic_read(&ulp->ref_count) != 0 && i < 10) {
+ msleep(100);
+ i++;
+ }
+ return 0;
+}
+
+static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
+ struct bnxt_msix_entry *ent, int num_msix)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ int max_idx, max_cp_rings;
+ int avail_msix, i, idx;
+
+ ASSERT_RTNL();
+ if (ulp_id != BNXT_ROCE_ULP)
+ return -EINVAL;
+
+ if (!(bp->flags & BNXT_FLAG_USING_MSIX))
+ return -ENODEV;
+
+ max_cp_rings = bnxt_get_max_func_cp_rings(bp);
+ max_idx = min_t(int, bp->total_irqs, max_cp_rings);
+ avail_msix = max_idx - bp->cp_nr_rings;
+ if (!avail_msix)
+ return -ENOMEM;
+ if (avail_msix > num_msix)
+ avail_msix = num_msix;
+
+ idx = max_idx - avail_msix;
+ for (i = 0; i < avail_msix; i++) {
+ ent[i].vector = bp->irq_tbl[idx + i].vector;
+ ent[i].ring_idx = idx + i;
+ ent[i].db_offset = (idx + i) * 0x80;
+ }
+ bnxt_set_max_func_irqs(bp, max_idx - avail_msix);
+ bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
+ edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
+ return avail_msix;
+}
+
+static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ int max_cp_rings, msix_requested;
+
+ ASSERT_RTNL();
+ if (ulp_id != BNXT_ROCE_ULP)
+ return -EINVAL;
+
+ max_cp_rings = bnxt_get_max_func_cp_rings(bp);
+ msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
+ bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
+ edev->ulp_tbl[ulp_id].msix_requested = 0;
+ bnxt_set_max_func_irqs(bp, bp->total_irqs);
+ return 0;
+}
+
+void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id)
+{
+ ASSERT_RTNL();
+ if (bnxt_ulp_registered(bp->edev, ulp_id)) {
+ struct bnxt_en_dev *edev = bp->edev;
+ unsigned int msix_req, max;
+
+ msix_req = edev->ulp_tbl[ulp_id].msix_requested;
+ max = bnxt_get_max_func_cp_rings(bp);
+ bnxt_set_max_func_cp_rings(bp, max - msix_req);
+ max = bnxt_get_max_func_stat_ctxs(bp);
+ bnxt_set_max_func_stat_ctxs(bp, max - 1);
+ }
+}
+
+static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
+ struct bnxt_fw_msg *fw_msg)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ struct input *req;
+ int rc;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ req = fw_msg->msg;
+ req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
+ rc = _hwrm_send_message(bp, fw_msg->msg, fw_msg->msg_len,
+ fw_msg->timeout);
+ if (!rc) {
+ struct output *resp = bp->hwrm_cmd_resp_addr;
+ u32 len = le16_to_cpu(resp->resp_len);
+
+ if (fw_msg->resp_max_len < len)
+ len = fw_msg->resp_max_len;
+
+ memcpy(fw_msg->resp, resp, len);
+ }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static void bnxt_ulp_get(struct bnxt_ulp *ulp)
+{
+ atomic_inc(&ulp->ref_count);
+}
+
+static void bnxt_ulp_put(struct bnxt_ulp *ulp)
+{
+ atomic_dec(&ulp->ref_count);
+}
+
+void bnxt_ulp_stop(struct bnxt *bp)
+{
+ struct bnxt_en_dev *edev = bp->edev;
+ struct bnxt_ulp_ops *ops;
+ int i;
+
+ if (!edev)
+ return;
+
+ for (i = 0; i < BNXT_MAX_ULP; i++) {
+ struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+ ops = rtnl_dereference(ulp->ulp_ops);
+ if (!ops || !ops->ulp_stop)
+ continue;
+ ops->ulp_stop(ulp->handle);
+ }
+}
+
+void bnxt_ulp_start(struct bnxt *bp)
+{
+ struct bnxt_en_dev *edev = bp->edev;
+ struct bnxt_ulp_ops *ops;
+ int i;
+
+ if (!edev)
+ return;
+
+ for (i = 0; i < BNXT_MAX_ULP; i++) {
+ struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+ ops = rtnl_dereference(ulp->ulp_ops);
+ if (!ops || !ops->ulp_start)
+ continue;
+ ops->ulp_start(ulp->handle);
+ }
+}
+
+void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs)
+{
+ struct bnxt_en_dev *edev = bp->edev;
+ struct bnxt_ulp_ops *ops;
+ int i;
+
+ if (!edev)
+ return;
+
+ for (i = 0; i < BNXT_MAX_ULP; i++) {
+ struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+ rcu_read_lock();
+ ops = rcu_dereference(ulp->ulp_ops);
+ if (!ops || !ops->ulp_sriov_config) {
+ rcu_read_unlock();
+ continue;
+ }
+ bnxt_ulp_get(ulp);
+ rcu_read_unlock();
+ ops->ulp_sriov_config(ulp->handle, num_vfs);
+ bnxt_ulp_put(ulp);
+ }
+}
+
+void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl)
+{
+ u16 event_id = le16_to_cpu(cmpl->event_id);
+ struct bnxt_en_dev *edev = bp->edev;
+ struct bnxt_ulp_ops *ops;
+ int i;
+
+ if (!edev)
+ return;
+
+ rcu_read_lock();
+ for (i = 0; i < BNXT_MAX_ULP; i++) {
+ struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+ ops = rcu_dereference(ulp->ulp_ops);
+ if (!ops || !ops->ulp_async_notifier)
+ continue;
+ if (!ulp->async_events_bmap ||
+ event_id > ulp->max_async_event_id)
+ continue;
+
+ /* Read max_async_event_id first before testing the bitmap. */
+ smp_rmb();
+ if (test_bit(event_id, ulp->async_events_bmap))
+ ops->ulp_async_notifier(ulp->handle, cmpl);
+ }
+ rcu_read_unlock();
+}
+
+static int bnxt_register_async_events(struct bnxt_en_dev *edev, int ulp_id,
+ unsigned long *events_bmap, u16 max_id)
+{
+ struct net_device *dev = edev->net;
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_ulp *ulp;
+
+ if (ulp_id >= BNXT_MAX_ULP)
+ return -EINVAL;
+
+ ulp = &edev->ulp_tbl[ulp_id];
+ ulp->async_events_bmap = events_bmap;
+ /* Make sure bnxt_ulp_async_events() sees this order */
+ smp_wmb();
+ ulp->max_async_event_id = max_id;
+ bnxt_hwrm_func_rgtr_async_events(bp, events_bmap, max_id + 1);
+ return 0;
+}
+
+static const struct bnxt_en_ops bnxt_en_ops_tbl = {
+ .bnxt_register_device = bnxt_register_dev,
+ .bnxt_unregister_device = bnxt_unregister_dev,
+ .bnxt_request_msix = bnxt_req_msix_vecs,
+ .bnxt_free_msix = bnxt_free_msix_vecs,
+ .bnxt_send_fw_msg = bnxt_send_msg,
+ .bnxt_register_fw_async_events = bnxt_register_async_events,
+};
+
+struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ struct bnxt_en_dev *edev;
+
+ edev = bp->edev;
+ if (!edev) {
+ edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+ if (!edev)
+ return ERR_PTR(-ENOMEM);
+ edev->en_ops = &bnxt_en_ops_tbl;
+ if (bp->flags & BNXT_FLAG_ROCEV1_CAP)
+ edev->flags |= BNXT_EN_FLAG_ROCEV1_CAP;
+ if (bp->flags & BNXT_FLAG_ROCEV2_CAP)
+ edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
+ edev->net = dev;
+ edev->pdev = bp->pdev;
+ bp->edev = edev;
+ }
+ return bp->edev;
+}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
new file mode 100644
index 000000000000..74f816e46a33
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
@@ -0,0 +1,93 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef BNXT_ULP_H
+#define BNXT_ULP_H
+
+#define BNXT_ROCE_ULP 0
+#define BNXT_OTHER_ULP 1
+#define BNXT_MAX_ULP 2
+
+#define BNXT_MIN_ROCE_CP_RINGS 2
+#define BNXT_MIN_ROCE_STAT_CTXS 1
+
+struct hwrm_async_event_cmpl;
+struct bnxt;
+
+struct bnxt_ulp_ops {
+ /* async_notifier() cannot sleep (in BH context) */
+ void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *);
+ void (*ulp_stop)(void *);
+ void (*ulp_start)(void *);
+ void (*ulp_sriov_config)(void *, int);
+};
+
+struct bnxt_msix_entry {
+ u32 vector;
+ u32 ring_idx;
+ u32 db_offset;
+};
+
+struct bnxt_fw_msg {
+ void *msg;
+ int msg_len;
+ void *resp;
+ int resp_max_len;
+ int timeout;
+};
+
+struct bnxt_ulp {
+ void *handle;
+ struct bnxt_ulp_ops __rcu *ulp_ops;
+ unsigned long *async_events_bmap;
+ u16 max_async_event_id;
+ u16 msix_requested;
+ atomic_t ref_count;
+};
+
+struct bnxt_en_dev {
+ struct net_device *net;
+ struct pci_dev *pdev;
+ u32 flags;
+ #define BNXT_EN_FLAG_ROCEV1_CAP 0x1
+ #define BNXT_EN_FLAG_ROCEV2_CAP 0x2
+ #define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \
+ BNXT_EN_FLAG_ROCEV2_CAP)
+ const struct bnxt_en_ops *en_ops;
+ struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP];
+};
+
+struct bnxt_en_ops {
+ int (*bnxt_register_device)(struct bnxt_en_dev *, int,
+ struct bnxt_ulp_ops *, void *);
+ int (*bnxt_unregister_device)(struct bnxt_en_dev *, int);
+ int (*bnxt_request_msix)(struct bnxt_en_dev *, int,
+ struct bnxt_msix_entry *, int);
+ int (*bnxt_free_msix)(struct bnxt_en_dev *, int);
+ int (*bnxt_send_fw_msg)(struct bnxt_en_dev *, int,
+ struct bnxt_fw_msg *);
+ int (*bnxt_register_fw_async_events)(struct bnxt_en_dev *, int,
+ unsigned long *, u16);
+};
+
+static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id)
+{
+ if (edev && rcu_access_pointer(edev->ulp_tbl[ulp_id].ulp_ops))
+ return true;
+ return false;
+}
+
+void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id);
+void bnxt_ulp_stop(struct bnxt *bp);
+void bnxt_ulp_start(struct bnxt *bp);
+void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
+void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
+struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev);
+
+#endif
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index a4e60e56c14f..f92896835d2a 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -971,13 +971,6 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
return phy_ethtool_set_eee(priv->phydev, e);
}
-static int bcmgenet_nway_reset(struct net_device *dev)
-{
- struct bcmgenet_priv *priv = netdev_priv(dev);
-
- return genphy_restart_aneg(priv->phydev);
-}
-
/* standard ethtool support functions. */
static const struct ethtool_ops bcmgenet_ethtool_ops = {
.get_strings = bcmgenet_get_strings,
@@ -991,7 +984,7 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
.set_wol = bcmgenet_set_wol,
.get_eee = bcmgenet_get_eee,
.set_eee = bcmgenet_set_eee,
- .nway_reset = bcmgenet_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_coalesce = bcmgenet_get_coalesce,
.set_coalesce = bcmgenet_set_coalesce,
.get_link_ksettings = bcmgenet_get_link_ksettings,
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index f1b81187a201..435a2e4739d1 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2147,15 +2147,6 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
}
}
-static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
-{
- if (new_mtu > ENET_PACKET_SIZE)
- return -EINVAL;
- _dev->mtu = new_mtu;
- pr_info("changing the mtu to %d\n", new_mtu);
- return 0;
-}
-
static const struct net_device_ops sbmac_netdev_ops = {
.ndo_open = sbmac_open,
.ndo_stop = sbmac_close,
@@ -2163,7 +2154,6 @@ static const struct net_device_ops sbmac_netdev_ops = {
.ndo_set_rx_mode = sbmac_set_rx_mode,
.ndo_tx_timeout = sbmac_tx_timeout,
.ndo_do_ioctl = sbmac_mii_ioctl,
- .ndo_change_mtu = sb1250_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2229,6 +2219,8 @@ static int sbmac_init(struct platform_device *pldev, long long base)
dev->netdev_ops = &sbmac_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
+ dev->min_mtu = 0;
+ dev->max_mtu = ENET_PACKET_SIZE;
netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index a927a730da10..185e9e047aa9 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -124,7 +124,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define TG3_TX_TIMEOUT (5 * HZ)
/* hardware minimum and maximum for a single frame's data payload */
-#define TG3_MIN_MTU 60
+#define TG3_MIN_MTU ETH_ZLEN
#define TG3_MAX_MTU(tp) \
(tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500)
@@ -14199,9 +14199,6 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
int err;
bool reset_phy = false;
- if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
- return -EINVAL;
-
if (!netif_running(dev)) {
/* We'll just catch it later when the
* device is up'd.
@@ -17799,6 +17796,10 @@ static int tg3_init_one(struct pci_dev *pdev,
dev->hw_features |= features;
dev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 60 - 9000 or 1500, depending on hardware */
+ dev->min_mtu = TG3_MIN_MTU;
+ dev->max_mtu = TG3_MAX_MTU(tp);
+
if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 &&
!tg3_flag(tp, TSO_CAPABLE) &&
!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index f42f672b0e7e..112030828c4b 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3296,9 +3296,6 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
struct bnad *bnad = netdev_priv(netdev);
u32 rx_count = 0, frame, new_frame;
- if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
- return -EINVAL;
-
mutex_lock(&bnad->conf_mutex);
mtu = netdev->mtu;
@@ -3465,6 +3462,10 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
netdev->mem_start = bnad->mmio_start;
netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
+ /* MTU range: 46 - 9000 */
+ netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ netdev->max_mtu = BNAD_JUMBO_MTU;
+
netdev->netdev_ops = &bnad_netdev_ops;
bnad_set_ethtool_ops(netdev);
}
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 31f61a744d66..286593922139 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -240,40 +240,46 @@ static const char *bnad_net_stats_strings[] = {
#define BNAD_ETHTOOL_STATS_NUM ARRAY_SIZE(bnad_net_stats_strings)
static int
-bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+bnad_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
- cmd->supported = SUPPORTED_10000baseT_Full;
- cmd->advertising = ADVERTISED_10000baseT_Full;
- cmd->autoneg = AUTONEG_DISABLE;
- cmd->supported |= SUPPORTED_FIBRE;
- cmd->advertising |= ADVERTISED_FIBRE;
- cmd->port = PORT_FIBRE;
- cmd->phy_address = 0;
+ u32 supported, advertising;
+
+ supported = SUPPORTED_10000baseT_Full;
+ advertising = ADVERTISED_10000baseT_Full;
+ cmd->base.autoneg = AUTONEG_DISABLE;
+ supported |= SUPPORTED_FIBRE;
+ advertising |= ADVERTISED_FIBRE;
+ cmd->base.port = PORT_FIBRE;
+ cmd->base.phy_address = 0;
if (netif_carrier_ok(netdev)) {
- ethtool_cmd_speed_set(cmd, SPEED_10000);
- cmd->duplex = DUPLEX_FULL;
+ cmd->base.speed = SPEED_10000;
+ cmd->base.duplex = DUPLEX_FULL;
} else {
- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
- cmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
}
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->maxtxpkt = 0;
- cmd->maxrxpkt = 0;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
static int
-bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+bnad_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
{
/* 10G full duplex setting supported only */
- if (cmd->autoneg == AUTONEG_ENABLE)
- return -EOPNOTSUPP; else {
- if ((ethtool_cmd_speed(cmd) == SPEED_10000)
- && (cmd->duplex == DUPLEX_FULL))
- return 0;
- }
+ if (cmd->base.autoneg == AUTONEG_ENABLE)
+ return -EOPNOTSUPP;
+
+ if ((cmd->base.speed == SPEED_10000) &&
+ (cmd->base.duplex == DUPLEX_FULL))
+ return 0;
return -EOPNOTSUPP;
}
@@ -1118,8 +1124,6 @@ out:
}
static const struct ethtool_ops bnad_ethtool_ops = {
- .get_settings = bnad_get_settings,
- .set_settings = bnad_set_settings,
.get_drvinfo = bnad_get_drvinfo,
.get_wol = bnad_get_wol,
.get_link = ethtool_op_get_link,
@@ -1137,6 +1141,8 @@ static const struct ethtool_ops bnad_ethtool_ops = {
.set_eeprom = bnad_set_eeprom,
.flash_device = bnad_flash_device,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_link_ksettings = bnad_get_link_ksettings,
+ .set_link_ksettings = bnad_set_link_ksettings,
};
void
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index ec09fcece711..538544a7c642 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -32,19 +32,28 @@
#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
-
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
#include "macb.h"
#define MACB_RX_BUFFER_SIZE 128
#define RX_BUFFER_MULTIPLE 64 /* bytes */
-#define RX_RING_SIZE 512 /* must be power of 2 */
-#define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
-#define TX_RING_SIZE 128 /* must be power of 2 */
-#define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
+#define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */
+#define MIN_RX_RING_SIZE 64
+#define MAX_RX_RING_SIZE 8192
+#define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+ * (bp)->rx_ring_size)
+
+#define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */
+#define MIN_TX_RING_SIZE 64
+#define MAX_TX_RING_SIZE 4096
+#define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+ * (bp)->tx_ring_size)
/* level of occupied TX descriptors under which we wake up TX process */
-#define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4)
+#define MACB_TX_WAKEUP_THRESH(bp) (3 * (bp)->tx_ring_size / 4)
#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
| MACB_BIT(ISR_ROVR))
@@ -53,10 +62,13 @@
| MACB_BIT(TXERR))
#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
-#define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
-#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
+/* Max length of transmit frame must be a multiple of 8 bytes */
+#define MACB_TX_LEN_ALIGN 8
+#define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
+#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
-#define GEM_MTU_MIN_SIZE 68
+#define GEM_MTU_MIN_SIZE ETH_MIN_MTU
+#define MACB_NETIF_LSO (NETIF_F_TSO | NETIF_F_UFO)
#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
#define MACB_WOL_ENABLED (0x1 << 1)
@@ -67,45 +79,47 @@
#define MACB_HALT_TIMEOUT 1230
/* Ring buffer accessors */
-static unsigned int macb_tx_ring_wrap(unsigned int index)
+static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
{
- return index & (TX_RING_SIZE - 1);
+ return index & (bp->tx_ring_size - 1);
}
static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
unsigned int index)
{
- return &queue->tx_ring[macb_tx_ring_wrap(index)];
+ return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
}
static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
unsigned int index)
{
- return &queue->tx_skb[macb_tx_ring_wrap(index)];
+ return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)];
}
static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
{
dma_addr_t offset;
- offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+ offset = macb_tx_ring_wrap(queue->bp, index) *
+ sizeof(struct macb_dma_desc);
return queue->tx_ring_dma + offset;
}
-static unsigned int macb_rx_ring_wrap(unsigned int index)
+static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
{
- return index & (RX_RING_SIZE - 1);
+ return index & (bp->rx_ring_size - 1);
}
static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
{
- return &bp->rx_ring[macb_rx_ring_wrap(index)];
+ return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
}
static void *macb_rx_buffer(struct macb *bp, unsigned int index)
{
- return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
+ return bp->rx_buffers + bp->rx_buffer_size *
+ macb_rx_ring_wrap(bp, index);
}
/* I/O accessors */
@@ -608,7 +622,8 @@ static void macb_tx_error_task(struct work_struct *work)
*/
if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
+ macb_tx_ring_wrap(bp, tail),
+ skb->data);
bp->stats.tx_packets++;
bp->stats.tx_bytes += skb->len;
}
@@ -700,7 +715,8 @@ static void macb_tx_interrupt(struct macb_queue *queue)
/* First, update TX stats if needed */
if (skb) {
netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
+ macb_tx_ring_wrap(bp, tail),
+ skb->data);
bp->stats.tx_packets++;
bp->stats.tx_bytes += skb->len;
}
@@ -720,7 +736,7 @@ static void macb_tx_interrupt(struct macb_queue *queue)
queue->tx_tail = tail;
if (__netif_subqueue_stopped(bp->dev, queue_index) &&
CIRC_CNT(queue->tx_head, queue->tx_tail,
- TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
+ bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
netif_wake_subqueue(bp->dev, queue_index);
}
@@ -731,8 +747,8 @@ static void gem_rx_refill(struct macb *bp)
dma_addr_t paddr;
while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
- RX_RING_SIZE) > 0) {
- entry = macb_rx_ring_wrap(bp->rx_prepared_head);
+ bp->rx_ring_size) > 0) {
+ entry = macb_rx_ring_wrap(bp, bp->rx_prepared_head);
/* Make hw descriptor updates visible to CPU */
rmb();
@@ -759,7 +775,7 @@ static void gem_rx_refill(struct macb *bp)
bp->rx_skbuff[entry] = skb;
- if (entry == RX_RING_SIZE - 1)
+ if (entry == bp->rx_ring_size - 1)
paddr |= MACB_BIT(RX_WRAP);
macb_set_addr(&(bp->rx_ring[entry]), paddr);
bp->rx_ring[entry].ctrl = 0;
@@ -813,7 +829,7 @@ static int gem_rx(struct macb *bp, int budget)
dma_addr_t addr;
bool rxused;
- entry = macb_rx_ring_wrap(bp->rx_tail);
+ entry = macb_rx_ring_wrap(bp, bp->rx_tail);
desc = &bp->rx_ring[entry];
/* Make hw descriptor updates visible to CPU */
@@ -895,8 +911,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
len = desc->ctrl & bp->rx_frm_len_mask;
netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
- macb_rx_ring_wrap(first_frag),
- macb_rx_ring_wrap(last_frag), len);
+ macb_rx_ring_wrap(bp, first_frag),
+ macb_rx_ring_wrap(bp, last_frag), len);
/* The ethernet header starts NET_IP_ALIGN bytes into the
* first buffer. Since the header is 14 bytes, this makes the
@@ -969,12 +985,12 @@ static inline void macb_init_rx_ring(struct macb *bp)
int i;
addr = bp->rx_buffers_dma;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < bp->rx_ring_size; i++) {
bp->rx_ring[i].addr = addr;
bp->rx_ring[i].ctrl = 0;
addr += bp->rx_buffer_size;
}
- bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+ bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
bp->rx_tail = 0;
}
@@ -1214,7 +1230,8 @@ static void macb_poll_controller(struct net_device *dev)
static unsigned int macb_tx_map(struct macb *bp,
struct macb_queue *queue,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ unsigned int hdrlen)
{
dma_addr_t mapping;
unsigned int len, entry, i, tx_head = queue->tx_head;
@@ -1222,15 +1239,28 @@ static unsigned int macb_tx_map(struct macb *bp,
struct macb_dma_desc *desc;
unsigned int offset, size, count = 0;
unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
- unsigned int eof = 1;
- u32 ctrl;
+ unsigned int eof = 1, mss_mfs = 0;
+ u32 ctrl, lso_ctrl = 0, seq_ctrl = 0;
+
+ /* LSO */
+ if (skb_shinfo(skb)->gso_size != 0) {
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ /* UDP - UFO */
+ lso_ctrl = MACB_LSO_UFO_ENABLE;
+ else
+ /* TCP - TSO */
+ lso_ctrl = MACB_LSO_TSO_ENABLE;
+ }
/* First, map non-paged data */
len = skb_headlen(skb);
+
+ /* first buffer length */
+ size = hdrlen;
+
offset = 0;
while (len) {
- size = min(len, bp->max_tx_length);
- entry = macb_tx_ring_wrap(tx_head);
+ entry = macb_tx_ring_wrap(bp, tx_head);
tx_skb = &queue->tx_skb[entry];
mapping = dma_map_single(&bp->pdev->dev,
@@ -1249,6 +1279,8 @@ static unsigned int macb_tx_map(struct macb *bp,
offset += size;
count++;
tx_head++;
+
+ size = min(len, bp->max_tx_length);
}
/* Then, map paged data from fragments */
@@ -1259,7 +1291,7 @@ static unsigned int macb_tx_map(struct macb *bp,
offset = 0;
while (len) {
size = min(len, bp->max_tx_length);
- entry = macb_tx_ring_wrap(tx_head);
+ entry = macb_tx_ring_wrap(bp, tx_head);
tx_skb = &queue->tx_skb[entry];
mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
@@ -1297,14 +1329,29 @@ static unsigned int macb_tx_map(struct macb *bp,
* to set the end of TX queue
*/
i = tx_head;
- entry = macb_tx_ring_wrap(i);
+ entry = macb_tx_ring_wrap(bp, i);
ctrl = MACB_BIT(TX_USED);
desc = &queue->tx_ring[entry];
desc->ctrl = ctrl;
+ if (lso_ctrl) {
+ if (lso_ctrl == MACB_LSO_UFO_ENABLE)
+ /* include header and FCS in value given to h/w */
+ mss_mfs = skb_shinfo(skb)->gso_size +
+ skb_transport_offset(skb) +
+ ETH_FCS_LEN;
+ else /* TSO */ {
+ mss_mfs = skb_shinfo(skb)->gso_size;
+ /* TCP Sequence Number Source Select
+ * can be set only for TSO
+ */
+ seq_ctrl = 0;
+ }
+ }
+
do {
i--;
- entry = macb_tx_ring_wrap(i);
+ entry = macb_tx_ring_wrap(bp, i);
tx_skb = &queue->tx_skb[entry];
desc = &queue->tx_ring[entry];
@@ -1313,9 +1360,19 @@ static unsigned int macb_tx_map(struct macb *bp,
ctrl |= MACB_BIT(TX_LAST);
eof = 0;
}
- if (unlikely(entry == (TX_RING_SIZE - 1)))
+ if (unlikely(entry == (bp->tx_ring_size - 1)))
ctrl |= MACB_BIT(TX_WRAP);
+ /* First descriptor is header descriptor */
+ if (i == queue->tx_head) {
+ ctrl |= MACB_BF(TX_LSO, lso_ctrl);
+ ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
+ } else
+ /* Only set MSS/MFS on payload descriptors
+ * (second or later descriptor)
+ */
+ ctrl |= MACB_BF(MSS_MFS, mss_mfs);
+
/* Set TX buffer descriptor */
macb_set_addr(desc, tx_skb->mapping);
/* desc->addr must be visible to hardware before clearing
@@ -1341,6 +1398,43 @@ dma_error:
return 0;
}
+static netdev_features_t macb_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ unsigned int nr_frags, f;
+ unsigned int hdrlen;
+
+ /* Validate LSO compatibility */
+
+ /* there is only one buffer */
+ if (!skb_is_nonlinear(skb))
+ return features;
+
+ /* length of header */
+ hdrlen = skb_transport_offset(skb);
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ hdrlen += tcp_hdrlen(skb);
+
+ /* For LSO:
+ * When software supplies two or more payload buffers all payload buffers
+ * apart from the last must be a multiple of 8 bytes in size.
+ */
+ if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN))
+ return features & ~MACB_NETIF_LSO;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ /* No need to check last fragment */
+ nr_frags--;
+ for (f = 0; f < nr_frags; f++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+ if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN))
+ return features & ~MACB_NETIF_LSO;
+ }
+ return features;
+}
+
static inline int macb_clear_csum(struct sk_buff *skb)
{
/* no change for packets without checksum offloading */
@@ -1365,7 +1459,28 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct macb *bp = netdev_priv(dev);
struct macb_queue *queue = &bp->queues[queue_index];
unsigned long flags;
- unsigned int count, nr_frags, frag_size, f;
+ unsigned int desc_cnt, nr_frags, frag_size, f;
+ unsigned int hdrlen;
+ bool is_lso, is_udp = 0;
+
+ is_lso = (skb_shinfo(skb)->gso_size != 0);
+
+ if (is_lso) {
+ is_udp = !!(ip_hdr(skb)->protocol == IPPROTO_UDP);
+
+ /* length of headers */
+ if (is_udp)
+ /* only queue eth + ip headers separately for UDP */
+ hdrlen = skb_transport_offset(skb);
+ else
+ hdrlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ if (skb_headlen(skb) < hdrlen) {
+ netdev_err(bp->dev, "Error - LSO headers fragmented!!!\n");
+ /* if this is required, would need to copy to single buffer */
+ return NETDEV_TX_BUSY;
+ }
+ } else
+ hdrlen = min(skb_headlen(skb), bp->max_tx_length);
#if defined(DEBUG) && defined(VERBOSE_DEBUG)
netdev_vdbg(bp->dev,
@@ -1380,17 +1495,22 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
* socket buffer: skb fragments of jumbo frames may need to be
* split into many buffer descriptors.
*/
- count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
+ if (is_lso && (skb_headlen(skb) > hdrlen))
+ /* extra header descriptor if also payload in first buffer */
+ desc_cnt = DIV_ROUND_UP((skb_headlen(skb) - hdrlen), bp->max_tx_length) + 1;
+ else
+ desc_cnt = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++) {
frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
- count += DIV_ROUND_UP(frag_size, bp->max_tx_length);
+ desc_cnt += DIV_ROUND_UP(frag_size, bp->max_tx_length);
}
spin_lock_irqsave(&bp->lock, flags);
/* This is a hard error, log it. */
- if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < count) {
+ if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
+ bp->tx_ring_size) < desc_cnt) {
netif_stop_subqueue(dev, queue_index);
spin_unlock_irqrestore(&bp->lock, flags);
netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
@@ -1404,7 +1524,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* Map socket buffer for DMA transfer */
- if (!macb_tx_map(bp, queue, skb)) {
+ if (!macb_tx_map(bp, queue, skb, hdrlen)) {
dev_kfree_skb_any(skb);
goto unlock;
}
@@ -1416,7 +1536,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
- if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < 1)
+ if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
netif_stop_subqueue(dev, queue_index);
unlock:
@@ -1455,7 +1575,7 @@ static void gem_free_rx_buffers(struct macb *bp)
if (!bp->rx_skbuff)
return;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < bp->rx_ring_size; i++) {
skb = bp->rx_skbuff[i];
if (!skb)
@@ -1480,7 +1600,7 @@ static void macb_free_rx_buffers(struct macb *bp)
{
if (bp->rx_buffers) {
dma_free_coherent(&bp->pdev->dev,
- RX_RING_SIZE * bp->rx_buffer_size,
+ bp->rx_ring_size * bp->rx_buffer_size,
bp->rx_buffers, bp->rx_buffers_dma);
bp->rx_buffers = NULL;
}
@@ -1493,7 +1613,7 @@ static void macb_free_consistent(struct macb *bp)
bp->macbgem_ops.mog_free_rx_buffers(bp);
if (bp->rx_ring) {
- dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp),
bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
}
@@ -1502,7 +1622,7 @@ static void macb_free_consistent(struct macb *bp)
kfree(queue->tx_skb);
queue->tx_skb = NULL;
if (queue->tx_ring) {
- dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
queue->tx_ring, queue->tx_ring_dma);
queue->tx_ring = NULL;
}
@@ -1513,14 +1633,14 @@ static int gem_alloc_rx_buffers(struct macb *bp)
{
int size;
- size = RX_RING_SIZE * sizeof(struct sk_buff *);
+ size = bp->rx_ring_size * sizeof(struct sk_buff *);
bp->rx_skbuff = kzalloc(size, GFP_KERNEL);
if (!bp->rx_skbuff)
return -ENOMEM;
-
- netdev_dbg(bp->dev,
- "Allocated %d RX struct sk_buff entries at %p\n",
- RX_RING_SIZE, bp->rx_skbuff);
+ else
+ netdev_dbg(bp->dev,
+ "Allocated %d RX struct sk_buff entries at %p\n",
+ bp->rx_ring_size, bp->rx_skbuff);
return 0;
}
@@ -1528,7 +1648,7 @@ static int macb_alloc_rx_buffers(struct macb *bp)
{
int size;
- size = RX_RING_SIZE * bp->rx_buffer_size;
+ size = bp->rx_ring_size * bp->rx_buffer_size;
bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
&bp->rx_buffers_dma, GFP_KERNEL);
if (!bp->rx_buffers)
@@ -1547,7 +1667,7 @@ static int macb_alloc_consistent(struct macb *bp)
int size;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- size = TX_RING_BYTES;
+ size = TX_RING_BYTES(bp);
queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
&queue->tx_ring_dma,
GFP_KERNEL);
@@ -1558,13 +1678,13 @@ static int macb_alloc_consistent(struct macb *bp)
q, size, (unsigned long)queue->tx_ring_dma,
queue->tx_ring);
- size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
+ size = bp->tx_ring_size * sizeof(struct macb_tx_skb);
queue->tx_skb = kmalloc(size, GFP_KERNEL);
if (!queue->tx_skb)
goto out_err;
}
- size = RX_RING_BYTES;
+ size = RX_RING_BYTES(bp);
bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
&bp->rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
@@ -1590,11 +1710,11 @@ static void gem_init_rings(struct macb *bp)
int i;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- for (i = 0; i < TX_RING_SIZE; i++) {
- macb_set_addr(&(queue->tx_ring[i]), 0);
+ for (i = 0; i < bp->tx_ring_size; i++) {
+ queue->tx_ring[i].addr = 0;
queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
}
- queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+ queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
queue->tx_head = 0;
queue->tx_tail = 0;
}
@@ -1611,13 +1731,13 @@ static void macb_init_rings(struct macb *bp)
macb_init_rx_ring(bp);
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < bp->tx_ring_size; i++) {
bp->queues[0].tx_ring[i].addr = 0;
bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
}
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
- bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+ bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
}
static void macb_reset_hw(struct macb *bp)
@@ -1986,19 +2106,9 @@ static int macb_close(struct net_device *dev)
static int macb_change_mtu(struct net_device *dev, int new_mtu)
{
- struct macb *bp = netdev_priv(dev);
- u32 max_mtu;
-
if (netif_running(dev))
return -EBUSY;
- max_mtu = ETH_DATA_LEN;
- if (bp->caps & MACB_CAPS_JUMBO)
- max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
-
- if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE))
- return -EINVAL;
-
dev->mtu = new_mtu;
return 0;
@@ -2158,8 +2268,8 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
| MACB_GREGS_VERSION;
- tail = macb_tx_ring_wrap(bp->queues[0].tx_tail);
- head = macb_tx_ring_wrap(bp->queues[0].tx_head);
+ tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail);
+ head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head);
regs_buff[0] = macb_readl(bp, NCR);
regs_buff[1] = macb_or_gem_readl(bp, NCFGR);
@@ -2214,6 +2324,56 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return 0;
}
+static void macb_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct macb *bp = netdev_priv(netdev);
+
+ ring->rx_max_pending = MAX_RX_RING_SIZE;
+ ring->tx_max_pending = MAX_TX_RING_SIZE;
+
+ ring->rx_pending = bp->rx_ring_size;
+ ring->tx_pending = bp->tx_ring_size;
+}
+
+static int macb_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct macb *bp = netdev_priv(netdev);
+ u32 new_rx_size, new_tx_size;
+ unsigned int reset = 0;
+
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+
+ new_rx_size = clamp_t(u32, ring->rx_pending,
+ MIN_RX_RING_SIZE, MAX_RX_RING_SIZE);
+ new_rx_size = roundup_pow_of_two(new_rx_size);
+
+ new_tx_size = clamp_t(u32, ring->tx_pending,
+ MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);
+ new_tx_size = roundup_pow_of_two(new_tx_size);
+
+ if ((new_tx_size == bp->tx_ring_size) &&
+ (new_rx_size == bp->rx_ring_size)) {
+ /* nothing to do */
+ return 0;
+ }
+
+ if (netif_running(bp->dev)) {
+ reset = 1;
+ macb_close(bp->dev);
+ }
+
+ bp->rx_ring_size = new_rx_size;
+ bp->tx_ring_size = new_tx_size;
+
+ if (reset)
+ macb_open(bp->dev);
+
+ return 0;
+}
+
static const struct ethtool_ops macb_ethtool_ops = {
.get_regs_len = macb_get_regs_len,
.get_regs = macb_get_regs,
@@ -2223,6 +2383,8 @@ static const struct ethtool_ops macb_ethtool_ops = {
.set_wol = macb_set_wol,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_ringparam = macb_get_ringparam,
+ .set_ringparam = macb_set_ringparam,
};
static const struct ethtool_ops gem_ethtool_ops = {
@@ -2235,6 +2397,8 @@ static const struct ethtool_ops gem_ethtool_ops = {
.get_sset_count = gem_get_sset_count,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_ringparam = macb_get_ringparam,
+ .set_ringparam = macb_set_ringparam,
};
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2298,6 +2462,7 @@ static const struct net_device_ops macb_netdev_ops = {
.ndo_poll_controller = macb_poll_controller,
#endif
.ndo_set_features = macb_set_features,
+ .ndo_features_check = macb_features_check,
};
/* Configure peripheral capabilities according to device tree
@@ -2429,6 +2594,9 @@ static int macb_init(struct platform_device *pdev)
int err;
u32 val;
+ bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
+ bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
/* set the queue register mapping once for all: queue0 has a special
* register mapping but we don't want to test the queue index then
* compute the corresponding register offset at run time.
@@ -2501,6 +2669,11 @@ static int macb_init(struct platform_device *pdev)
/* Set features */
dev->hw_features = NETIF_F_SG;
+
+ /* Check LSO capability */
+ if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
+ dev->hw_features |= MACB_NETIF_LSO;
+
/* Checksum offload is only available on gem with packet buffer */
if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
@@ -2800,7 +2973,6 @@ static const struct net_device_ops at91ether_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = macb_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = at91ether_poll_controller,
#endif
@@ -3035,6 +3207,13 @@ static int macb_probe(struct platform_device *pdev)
goto err_out_free_netdev;
}
+ /* MTU range: 68 - 1500 or 10240 */
+ dev->min_mtu = GEM_MTU_MIN_SIZE;
+ if (bp->caps & MACB_CAPS_JUMBO)
+ dev->max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
+ else
+ dev->max_mtu = ETH_DATA_LEN;
+
mac = of_get_mac_address(np);
if (mac)
ether_addr_copy(bp->dev->dev_addr, mac);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 8bed4b52fef5..d67adad67be1 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -382,6 +382,10 @@
#define GEM_TX_PKT_BUFF_OFFSET 21
#define GEM_TX_PKT_BUFF_SIZE 1
+/* Bitfields in DCFG6. */
+#define GEM_PBUF_LSO_OFFSET 27
+#define GEM_PBUF_LSO_SIZE 1
+
/* Constants for CLK */
#define MACB_CLK_DIV8 0
#define MACB_CLK_DIV16 1
@@ -414,6 +418,10 @@
#define MACB_CAPS_SG_DISABLED 0x40000000
#define MACB_CAPS_MACB_IS_GEM 0x80000000
+/* LSO settings */
+#define MACB_LSO_UFO_ENABLE 0x01
+#define MACB_LSO_TSO_ENABLE 0x02
+
/* Bit manipulation macros */
#define MACB_BIT(name) \
(1 << MACB_##name##_OFFSET)
@@ -545,6 +553,12 @@ struct macb_dma_desc {
#define MACB_TX_LAST_SIZE 1
#define MACB_TX_NOCRC_OFFSET 16
#define MACB_TX_NOCRC_SIZE 1
+#define MACB_MSS_MFS_OFFSET 16
+#define MACB_MSS_MFS_SIZE 14
+#define MACB_TX_LSO_OFFSET 17
+#define MACB_TX_LSO_SIZE 2
+#define MACB_TX_TCP_SEQ_SRC_OFFSET 19
+#define MACB_TX_TCP_SEQ_SRC_SIZE 1
#define MACB_TX_BUF_EXHAUSTED_OFFSET 27
#define MACB_TX_BUF_EXHAUSTED_SIZE 1
#define MACB_TX_UNDERRUN_OFFSET 28
@@ -811,6 +825,9 @@ struct macb {
void *rx_buffers;
size_t rx_buffer_size;
+ unsigned int rx_ring_size;
+ unsigned int tx_ring_size;
+
unsigned int num_queues;
unsigned int queue_mask;
struct macb_queue queues[MACB_MAX_QUEUES];
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 63efa0dc45ba..ce7de6f72512 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -394,7 +394,7 @@ struct xgmac_priv {
};
/* XGMAC Configuration Settings */
-#define MAX_MTU 9000
+#define XGMAC_MAX_MTU 9000
#define PAUSE_TIME 0x400
#define DMA_RX_RING_SZ 256
@@ -1360,20 +1360,6 @@ out:
*/
static int xgmac_change_mtu(struct net_device *dev, int new_mtu)
{
- struct xgmac_priv *priv = netdev_priv(dev);
- int old_mtu;
-
- if ((new_mtu < 46) || (new_mtu > MAX_MTU)) {
- netdev_err(priv->dev, "invalid MTU, max MTU is: %d\n", MAX_MTU);
- return -EINVAL;
- }
-
- old_mtu = dev->mtu;
-
- /* return early if the buffer sizes will not change */
- if (old_mtu == new_mtu)
- return 0;
-
/* Stop everything, get ready to change the MTU */
if (!netif_running(dev))
return 0;
@@ -1544,15 +1530,14 @@ static const struct net_device_ops xgmac_netdev_ops = {
.ndo_set_features = xgmac_set_features,
};
-static int xgmac_ethtool_getsettings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+static int xgmac_ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
- cmd->autoneg = 0;
- cmd->duplex = DUPLEX_FULL;
- ethtool_cmd_speed_set(cmd, 10000);
- cmd->supported = 0;
- cmd->advertising = 0;
- cmd->transceiver = XCVR_INTERNAL;
+ cmd->base.autoneg = 0;
+ cmd->base.duplex = DUPLEX_FULL;
+ cmd->base.speed = 10000;
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 0);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 0);
return 0;
}
@@ -1695,7 +1680,6 @@ static int xgmac_set_wol(struct net_device *dev,
}
static const struct ethtool_ops xgmac_ethtool_ops = {
- .get_settings = xgmac_ethtool_getsettings,
.get_link = ethtool_op_get_link,
.get_pauseparam = xgmac_get_pauseparam,
.set_pauseparam = xgmac_set_pauseparam,
@@ -1704,6 +1688,7 @@ static const struct ethtool_ops xgmac_ethtool_ops = {
.get_wol = xgmac_get_wol,
.set_wol = xgmac_set_wol,
.get_sset_count = xgmac_get_sset_count,
+ .get_link_ksettings = xgmac_ethtool_get_link_ksettings,
};
/**
@@ -1804,6 +1789,10 @@ static int xgmac_probe(struct platform_device *pdev)
ndev->features |= ndev->hw_features;
ndev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 46 - 9000 */
+ ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ ndev->max_mtu = XGMAC_MAX_MTU;
+
/* Get the MAC address */
xgmac_get_mac_addr(priv->base, ndev->dev_addr, 0);
if (!is_valid_ether_addr(ndev->dev_addr))
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 92f411c9f0df..bbc8bd16cb97 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -53,7 +53,7 @@ config THUNDER_NIC_RGX
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select FW_LOADER
select LIBCRC32C
---help---
@@ -74,4 +74,16 @@ config OCTEON_MGMT_ETHERNET
port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
CN54XX, CN52XX, and CN6XXX chips.
+config LIQUIDIO_VF
+ tristate "Cavium LiquidIO VF support"
+ depends on 64BIT && PCI_MSI
+ select PTP_1588_CLOCK
+ ---help---
+ This driver supports Cavium LiquidIO Intelligent Server Adapter
+ based on CN23XX chips.
+
+ To compile this driver as a module, choose M here: The module
+ will be called liquidio_vf. MSI-X interrupt support is required
+ for this driver to work correctly
+
endif # NET_VENDOR_CAVIUM
diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile
index 5a27b2a44039..c4d411d1aa28 100644
--- a/drivers/net/ethernet/cavium/liquidio/Makefile
+++ b/drivers/net/ethernet/cavium/liquidio/Makefile
@@ -11,8 +11,32 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.o \
cn66xx_device.o \
cn68xx_device.o \
cn23xx_pf_device.o \
+ cn23xx_vf_device.o \
+ octeon_mailbox.o \
octeon_mem_ops.o \
octeon_droq.o \
octeon_nic.o
liquidio-objs := lio_main.o octeon_console.o $(liquidio-y)
+
+obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o
+
+ifeq ($(CONFIG_LIQUIDIO)$(CONFIG_LIQUIDIO_VF), yy)
+ liquidio_vf-objs := lio_vf_main.o
+else
+liquidio_vf-$(CONFIG_LIQUIDIO_VF) += lio_ethtool.o \
+ lio_core.o \
+ request_manager.o \
+ response_manager.o \
+ octeon_device.o \
+ cn66xx_device.o \
+ cn68xx_device.o \
+ cn23xx_pf_device.o \
+ cn23xx_vf_device.o \
+ octeon_mailbox.o \
+ octeon_mem_ops.o \
+ octeon_droq.o \
+ octeon_nic.o
+
+liquidio_vf-objs := lio_vf_main.o $(liquidio_vf-y)
+endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index 380a64115a98..962dcbcef8b5 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -1,28 +1,23 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
-#include <linux/netdevice.h>
#include <linux/vmalloc.h>
+#include <linux/etherdevice.h>
#include "liquidio_common.h"
#include "octeon_droq.h"
#include "octeon_iq.h"
@@ -30,6 +25,7 @@
#include "octeon_device.h"
#include "cn23xx_pf_device.h"
#include "octeon_main.h"
+#include "octeon_mailbox.h"
#define RESET_NOTDONE 0
#define RESET_DONE 1
@@ -40,11 +36,6 @@
*/
#define CN23XX_INPUT_JABBER 64600
-#define LIOLUT_RING_DISTRIBUTION 9
-const int liolut_num_vfs_to_rings_per_vf[LIOLUT_RING_DISTRIBUTION] = {
- 0, 8, 4, 2, 2, 2, 1, 1, 1
-};
-
void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct)
{
int i = 0;
@@ -309,9 +300,10 @@ u32 cn23xx_pf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us)
static void cn23xx_setup_global_mac_regs(struct octeon_device *oct)
{
- u64 reg_val;
u16 mac_no = oct->pcie_port;
u16 pf_num = oct->pf_num;
+ u64 reg_val;
+ u64 temp;
/* programming SRN and TRS for each MAC(0..3) */
@@ -333,6 +325,14 @@ static void cn23xx_setup_global_mac_regs(struct octeon_device *oct)
/* setting TRS <23:16> */
reg_val = reg_val |
(oct->sriov_info.trs << CN23XX_PKT_MAC_CTL_RINFO_TRS_BIT_POS);
+ /* setting RPVF <39:32> */
+ temp = oct->sriov_info.rings_per_vf & 0xff;
+ reg_val |= (temp << CN23XX_PKT_MAC_CTL_RINFO_RPVF_BIT_POS);
+
+ /* setting NVFS <55:48> */
+ temp = oct->sriov_info.max_vfs & 0xff;
+ reg_val |= (temp << CN23XX_PKT_MAC_CTL_RINFO_NVFS_BIT_POS);
+
/* write these settings to MAC register */
octeon_write_csr64(oct, CN23XX_SLI_PKT_MAC_RINFO64(mac_no, pf_num),
reg_val);
@@ -399,11 +399,12 @@ static int cn23xx_reset_io_queues(struct octeon_device *oct)
static int cn23xx_pf_setup_global_input_regs(struct octeon_device *oct)
{
+ struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
+ struct octeon_instr_queue *iq;
+ u64 intr_threshold, reg_val;
u32 q_no, ern, srn;
u64 pf_num;
- u64 intr_threshold, reg_val;
- struct octeon_instr_queue *iq;
- struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
+ u64 vf_num;
pf_num = oct->pf_num;
@@ -414,12 +415,22 @@ static int cn23xx_pf_setup_global_input_regs(struct octeon_device *oct)
return -1;
/** Set the MAC_NUM and PVF_NUM in IQ_PKT_CONTROL reg
- * for all queues.Only PF can set these bits.
- * bits 29:30 indicate the MAC num.
- * bits 32:47 indicate the PVF num.
- */
+ * for all queues.Only PF can set these bits.
+ * bits 29:30 indicate the MAC num.
+ * bits 32:47 indicate the PVF num.
+ */
for (q_no = 0; q_no < ern; q_no++) {
reg_val = oct->pcie_port << CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
+
+ /* for VF assigned queues. */
+ if (q_no < oct->sriov_info.pf_srn) {
+ vf_num = q_no / oct->sriov_info.rings_per_vf;
+ vf_num += 1; /* VF1, VF2,........ */
+ } else {
+ vf_num = 0;
+ }
+
+ reg_val |= vf_num << CN23XX_PKT_INPUT_CTL_VF_NUM_POS;
reg_val |= pf_num << CN23XX_PKT_INPUT_CTL_PF_NUM_POS;
octeon_write_csr64(oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
@@ -530,8 +541,8 @@ static void cn23xx_pf_setup_global_output_regs(struct octeon_device *oct)
writeq(0x40, (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_WMARK);
/** Disabling setting OQs in reset when ring has no dorebells
- * enabling this will cause of head of line blocking
- */
+ * enabling this will cause of head of line blocking
+ */
/* Do it only for pass1.1. and pass1.2 */
if ((oct->rev_id == OCTEON_CN23XX_REV_1_0) ||
(oct->rev_id == OCTEON_CN23XX_REV_1_1))
@@ -662,6 +673,118 @@ static void cn23xx_setup_oq_regs(struct octeon_device *oct, u32 oq_no)
}
}
+static void cn23xx_pf_mbox_thread(struct work_struct *work)
+{
+ struct cavium_wk *wk = (struct cavium_wk *)work;
+ struct octeon_mbox *mbox = (struct octeon_mbox *)wk->ctxptr;
+ struct octeon_device *oct = mbox->oct_dev;
+ u64 mbox_int_val, val64;
+ u32 q_no, i;
+
+ if (oct->rev_id < OCTEON_CN23XX_REV_1_1) {
+ /*read and clear by writing 1*/
+ mbox_int_val = readq(mbox->mbox_int_reg);
+ writeq(mbox_int_val, mbox->mbox_int_reg);
+
+ for (i = 0; i < oct->sriov_info.num_vfs_alloced; i++) {
+ q_no = i * oct->sriov_info.rings_per_vf;
+
+ val64 = readq(oct->mbox[q_no]->mbox_write_reg);
+
+ if (val64 && (val64 != OCTEON_PFVFACK)) {
+ if (octeon_mbox_read(oct->mbox[q_no]))
+ octeon_mbox_process_message(
+ oct->mbox[q_no]);
+ }
+ }
+
+ schedule_delayed_work(&wk->work, msecs_to_jiffies(10));
+ } else {
+ octeon_mbox_process_message(mbox);
+ }
+}
+
+static int cn23xx_setup_pf_mbox(struct octeon_device *oct)
+{
+ struct octeon_mbox *mbox = NULL;
+ u16 mac_no = oct->pcie_port;
+ u16 pf_num = oct->pf_num;
+ u32 q_no, i;
+
+ if (!oct->sriov_info.max_vfs)
+ return 0;
+
+ for (i = 0; i < oct->sriov_info.max_vfs; i++) {
+ q_no = i * oct->sriov_info.rings_per_vf;
+
+ mbox = vmalloc(sizeof(*mbox));
+ if (!mbox)
+ goto free_mbox;
+
+ memset(mbox, 0, sizeof(struct octeon_mbox));
+
+ spin_lock_init(&mbox->lock);
+
+ mbox->oct_dev = oct;
+
+ mbox->q_no = q_no;
+
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+
+ /* PF mbox interrupt reg */
+ mbox->mbox_int_reg = (u8 *)oct->mmio[0].hw_addr +
+ CN23XX_SLI_MAC_PF_MBOX_INT(mac_no, pf_num);
+
+ /* PF writes into SIG0 reg */
+ mbox->mbox_write_reg = (u8 *)oct->mmio[0].hw_addr +
+ CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q_no, 0);
+
+ /* PF reads from SIG1 reg */
+ mbox->mbox_read_reg = (u8 *)oct->mmio[0].hw_addr +
+ CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q_no, 1);
+
+ /*Mail Box Thread creation*/
+ INIT_DELAYED_WORK(&mbox->mbox_poll_wk.work,
+ cn23xx_pf_mbox_thread);
+ mbox->mbox_poll_wk.ctxptr = (void *)mbox;
+
+ oct->mbox[q_no] = mbox;
+
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ }
+
+ if (oct->rev_id < OCTEON_CN23XX_REV_1_1)
+ schedule_delayed_work(&oct->mbox[0]->mbox_poll_wk.work,
+ msecs_to_jiffies(0));
+
+ return 0;
+
+free_mbox:
+ while (i) {
+ i--;
+ vfree(oct->mbox[i]);
+ }
+
+ return 1;
+}
+
+static int cn23xx_free_pf_mbox(struct octeon_device *oct)
+{
+ u32 q_no, i;
+
+ if (!oct->sriov_info.max_vfs)
+ return 0;
+
+ for (i = 0; i < oct->sriov_info.max_vfs; i++) {
+ q_no = i * oct->sriov_info.rings_per_vf;
+ cancel_delayed_work_sync(
+ &oct->mbox[q_no]->mbox_poll_wk.work);
+ vfree(oct->mbox[q_no]);
+ }
+
+ return 0;
+}
+
static int cn23xx_enable_io_queues(struct octeon_device *oct)
{
u64 reg_val;
@@ -856,6 +979,29 @@ static u64 cn23xx_pf_msix_interrupt_handler(void *dev)
return ret;
}
+static void cn23xx_handle_pf_mbox_intr(struct octeon_device *oct)
+{
+ struct delayed_work *work;
+ u64 mbox_int_val;
+ u32 i, q_no;
+
+ mbox_int_val = readq(oct->mbox[0]->mbox_int_reg);
+
+ for (i = 0; i < oct->sriov_info.num_vfs_alloced; i++) {
+ q_no = i * oct->sriov_info.rings_per_vf;
+
+ if (mbox_int_val & BIT_ULL(q_no)) {
+ writeq(BIT_ULL(q_no),
+ oct->mbox[0]->mbox_int_reg);
+ if (octeon_mbox_read(oct->mbox[q_no])) {
+ work = &oct->mbox[q_no]->mbox_poll_wk.work;
+ schedule_delayed_work(work,
+ msecs_to_jiffies(0));
+ }
+ }
+ }
+}
+
static irqreturn_t cn23xx_interrupt_handler(void *dev)
{
struct octeon_device *oct = (struct octeon_device *)dev;
@@ -871,6 +1017,10 @@ static irqreturn_t cn23xx_interrupt_handler(void *dev)
dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Error Intr: 0x%016llx\n",
oct->octeon_id, CVM_CAST64(intr64));
+ /* When VFs write into MBOX_SIG2 reg,these intr is set in PF */
+ if (intr64 & CN23XX_INTR_VF_MBOX)
+ cn23xx_handle_pf_mbox_intr(oct);
+
if (oct->msix_on != LIO_FLAG_MSIX_ENABLED) {
if (intr64 & CN23XX_INTR_PKT_DATA)
oct->int_status |= OCT_DEV_INTR_PKT_DATA;
@@ -961,6 +1111,13 @@ static void cn23xx_enable_pf_interrupt(struct octeon_device *oct, u8 intr_flag)
intr_val = readq(cn23xx->intr_enb_reg64);
intr_val |= CN23XX_INTR_PKT_DATA;
writeq(intr_val, cn23xx->intr_enb_reg64);
+ } else if ((intr_flag & OCTEON_MBOX_INTR) &&
+ (oct->sriov_info.max_vfs > 0)) {
+ if (oct->rev_id >= OCTEON_CN23XX_REV_1_1) {
+ intr_val = readq(cn23xx->intr_enb_reg64);
+ intr_val |= CN23XX_INTR_VF_MBOX;
+ writeq(intr_val, cn23xx->intr_enb_reg64);
+ }
}
}
@@ -976,6 +1133,13 @@ static void cn23xx_disable_pf_interrupt(struct octeon_device *oct, u8 intr_flag)
intr_val = readq(cn23xx->intr_enb_reg64);
intr_val &= ~CN23XX_INTR_PKT_DATA;
writeq(intr_val, cn23xx->intr_enb_reg64);
+ } else if ((intr_flag & OCTEON_MBOX_INTR) &&
+ (oct->sriov_info.max_vfs > 0)) {
+ if (oct->rev_id >= OCTEON_CN23XX_REV_1_1) {
+ intr_val = readq(cn23xx->intr_enb_reg64);
+ intr_val &= ~CN23XX_INTR_VF_MBOX;
+ writeq(intr_val, cn23xx->intr_enb_reg64);
+ }
}
}
@@ -1048,50 +1212,59 @@ static void cn23xx_setup_reg_address(struct octeon_device *oct)
static int cn23xx_sriov_config(struct octeon_device *oct)
{
- u32 total_rings;
struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
- /* num_vfs is already filled for us */
+ u32 max_rings, total_rings, max_vfs, rings_per_vf;
u32 pf_srn, num_pf_rings;
+ u32 max_possible_vfs;
cn23xx->conf =
- (struct octeon_config *)oct_get_config_info(oct, LIO_23XX);
+ (struct octeon_config *)oct_get_config_info(oct, LIO_23XX);
switch (oct->rev_id) {
case OCTEON_CN23XX_REV_1_0:
- total_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_0;
+ max_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_0;
+ max_possible_vfs = CN23XX_MAX_VFS_PER_PF_PASS_1_0;
break;
case OCTEON_CN23XX_REV_1_1:
- total_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_1;
+ max_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_1;
+ max_possible_vfs = CN23XX_MAX_VFS_PER_PF_PASS_1_1;
break;
default:
- total_rings = CN23XX_MAX_RINGS_PER_PF;
+ max_rings = CN23XX_MAX_RINGS_PER_PF;
+ max_possible_vfs = CN23XX_MAX_VFS_PER_PF;
break;
}
- if (!oct->sriov_info.num_pf_rings) {
- if (total_rings > num_present_cpus())
- num_pf_rings = num_present_cpus();
- else
- num_pf_rings = total_rings;
- } else {
- num_pf_rings = oct->sriov_info.num_pf_rings;
- if (num_pf_rings > total_rings) {
- dev_warn(&oct->pci_dev->dev,
- "num_queues_per_pf requested %u is more than available rings. Reducing to %u\n",
- num_pf_rings, total_rings);
- num_pf_rings = total_rings;
- }
- }
+ if (max_rings <= num_present_cpus())
+ num_pf_rings = 1;
+ else
+ num_pf_rings = num_present_cpus();
+
+#ifdef CONFIG_PCI_IOV
+ max_vfs = min_t(u32,
+ (max_rings - num_pf_rings), max_possible_vfs);
+ rings_per_vf = 1;
+#else
+ max_vfs = 0;
+ rings_per_vf = 0;
+#endif
+
+ total_rings = num_pf_rings + max_vfs;
- total_rings = num_pf_rings;
/* the first ring of the pf */
pf_srn = total_rings - num_pf_rings;
oct->sriov_info.trs = total_rings;
+ oct->sriov_info.max_vfs = max_vfs;
+ oct->sriov_info.rings_per_vf = rings_per_vf;
oct->sriov_info.pf_srn = pf_srn;
oct->sriov_info.num_pf_rings = num_pf_rings;
- dev_dbg(&oct->pci_dev->dev, "trs:%d pf_srn:%d num_pf_rings:%d\n",
- oct->sriov_info.trs, oct->sriov_info.pf_srn,
- oct->sriov_info.num_pf_rings);
+ dev_notice(&oct->pci_dev->dev, "trs:%d max_vfs:%d rings_per_vf:%d pf_srn:%d num_pf_rings:%d\n",
+ oct->sriov_info.trs, oct->sriov_info.max_vfs,
+ oct->sriov_info.rings_per_vf, oct->sriov_info.pf_srn,
+ oct->sriov_info.num_pf_rings);
+
+ oct->sriov_info.sriov_enabled = 0;
+
return 0;
}
@@ -1119,6 +1292,9 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
oct->fn_list.setup_iq_regs = cn23xx_setup_iq_regs;
oct->fn_list.setup_oq_regs = cn23xx_setup_oq_regs;
+ oct->fn_list.setup_mbox = cn23xx_setup_pf_mbox;
+ oct->fn_list.free_mbox = cn23xx_free_pf_mbox;
+
oct->fn_list.process_interrupt_regs = cn23xx_interrupt_handler;
oct->fn_list.msix_interrupt_handler = cn23xx_pf_msix_interrupt_handler;
@@ -1209,8 +1385,7 @@ void cn23xx_dump_iq_regs(struct octeon_device *oct)
dev_dbg(&oct->pci_dev->dev, "SLI_PKT[%d]_INPUT_CTL [0x%x]: 0x%016llx\n",
q_no, CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
CVM_CAST64(octeon_read_csr64
- (oct,
- CN23XX_SLI_IQ_PKT_CONTROL64(q_no))));
+ (oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no))));
}
pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, &regval);
@@ -1235,3 +1410,24 @@ int cn23xx_fw_loaded(struct octeon_device *oct)
val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1);
return (val >> 1) & 1ULL;
}
+
+void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
+ u8 *mac)
+{
+ if (oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vfidx)) {
+ struct octeon_mbox_cmd mbox_cmd;
+
+ mbox_cmd.msg.u64 = 0;
+ mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+ mbox_cmd.msg.s.resp_needed = 0;
+ mbox_cmd.msg.s.cmd = OCTEON_PF_CHANGED_VF_MACADDR;
+ mbox_cmd.msg.s.len = 1;
+ mbox_cmd.recv_len = 0;
+ mbox_cmd.recv_status = 0;
+ mbox_cmd.fn = NULL;
+ mbox_cmd.fn_arg = 0;
+ ether_addr_copy(mbox_cmd.msg.s.params, mac);
+ mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf;
+ octeon_mbox_write(oct, &mbox_cmd);
+ }
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
index 21b5c9051967..2fedd91f3df8 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
@@ -1,34 +1,31 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn23xx_device.h
* \brief Host Driver: Routines that perform CN23XX specific operations.
-*/
+ */
#ifndef __CN23XX_PF_DEVICE_H__
#define __CN23XX_PF_DEVICE_H__
#include "cn23xx_pf_regs.h"
+#define LIO_CMD_WAIT_TM 100
+
/* Register address and configuration for a CN23XX devices.
* If device specific changes need to be made then add a struct to include
* device specific fields as shown in the commented section
@@ -56,4 +53,7 @@ u32 cn23xx_pf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
int cn23xx_fw_loaded(struct octeon_device *oct);
+
+void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
+ u8 *mac);
#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
index 03d79d95ab75..e6d4ad99cc38 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
@@ -1,29 +1,24 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn23xx_regs.h
* \brief Host Driver: Register Address and Register Mask values for
* Octeon CN23XX devices.
-*/
+ */
#ifndef __CN23XX_PF_REGS_H__
#define __CN23XX_PF_REGS_H__
@@ -63,7 +58,7 @@
#define CN23XX_CONFIG_SRIOV_BAR_START 0x19C
#define CN23XX_CONFIG_SRIOV_BARX(i) \
- (CN23XX_CONFIG_SRIOV_BAR_START + (i * 4))
+ (CN23XX_CONFIG_SRIOV_BAR_START + ((i) * 4))
#define CN23XX_CONFIG_SRIOV_BAR_PF 0x08
#define CN23XX_CONFIG_SRIOV_BAR_64BIT 0x04
#define CN23XX_CONFIG_SRIOV_BAR_IO 0x01
@@ -513,7 +508,7 @@
/* 4 Registers (64 - bit) */
#define CN23XX_SLI_S2M_PORT_CTL_START 0x23D80
#define CN23XX_SLI_S2M_PORTX_CTL(port) \
- (CN23XX_SLI_S2M_PORT_CTL_START + (port * 0x10))
+ (CN23XX_SLI_S2M_PORT_CTL_START + ((port) * 0x10))
#define CN23XX_SLI_MAC_NUMBER 0x20050
@@ -554,26 +549,26 @@
* Provides DMA Engine Queue Enable
*/
#define CN23XX_DPI_DMA_ENG0_ENB 0x0001df0000000080ULL
-#define CN23XX_DPI_DMA_ENG_ENB(eng) (CN23XX_DPI_DMA_ENG0_ENB + (eng * 8))
+#define CN23XX_DPI_DMA_ENG_ENB(eng) (CN23XX_DPI_DMA_ENG0_ENB + ((eng) * 8))
/* 8 register (64-bit) - DPI_DMA(0..7)_REQQ_CTL
* Provides control bits for transaction on 8 Queues
*/
#define CN23XX_DPI_DMA_REQQ0_CTL 0x0001df0000000180ULL
#define CN23XX_DPI_DMA_REQQ_CTL(q_no) \
- (CN23XX_DPI_DMA_REQQ0_CTL + (q_no * 8))
+ (CN23XX_DPI_DMA_REQQ0_CTL + ((q_no) * 8))
/* 6 register (64-bit) - DPI_ENG(0..5)_BUF
* Provides DMA Engine FIFO (Queue) Size
*/
#define CN23XX_DPI_DMA_ENG0_BUF 0x0001df0000000880ULL
#define CN23XX_DPI_DMA_ENG_BUF(eng) \
- (CN23XX_DPI_DMA_ENG0_BUF + (eng * 8))
+ (CN23XX_DPI_DMA_ENG0_BUF + ((eng) * 8))
/* 4 Registers (64-bit) */
#define CN23XX_DPI_SLI_PRT_CFG_START 0x0001df0000000900ULL
#define CN23XX_DPI_SLI_PRTX_CFG(port) \
- (CN23XX_DPI_SLI_PRT_CFG_START + (port * 0x8))
+ (CN23XX_DPI_SLI_PRT_CFG_START + ((port) * 0x8))
/* Masks for DPI_DMA_CONTROL Register */
#define CN23XX_DPI_DMA_COMMIT_MODE BIT_ULL(58)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
new file mode 100644
index 000000000000..b6117b6a1de2
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -0,0 +1,722 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "cn23xx_vf_device.h"
+#include "octeon_main.h"
+#include "octeon_mailbox.h"
+
+u32 cn23xx_vf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us)
+{
+ /* This gives the SLI clock per microsec */
+ u32 oqticks_per_us = (u32)oct->pfvf_hsword.coproc_tics_per_us;
+
+ /* This gives the clock cycles per millisecond */
+ oqticks_per_us *= 1000;
+
+ /* This gives the oq ticks (1024 core clock cycles) per millisecond */
+ oqticks_per_us /= 1024;
+
+ /* time_intr is in microseconds. The next 2 steps gives the oq ticks
+ * corressponding to time_intr.
+ */
+ oqticks_per_us *= time_intr_in_us;
+ oqticks_per_us /= 1000;
+
+ return oqticks_per_us;
+}
+
+static int cn23xx_vf_reset_io_queues(struct octeon_device *oct, u32 num_queues)
+{
+ u32 loop = BUSY_READING_REG_VF_LOOP_COUNT;
+ int ret_val = 0;
+ u32 q_no;
+ u64 d64;
+
+ for (q_no = 0; q_no < num_queues; q_no++) {
+ /* set RST bit to 1. This bit applies to both IQ and OQ */
+ d64 = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ d64 |= CN23XX_PKT_INPUT_CTL_RST;
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ d64);
+ }
+
+ /* wait until the RST bit is clear or the RST and QUIET bits are set */
+ for (q_no = 0; q_no < num_queues; q_no++) {
+ u64 reg_val = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ while ((READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) &&
+ !(READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_QUIET) &&
+ loop) {
+ WRITE_ONCE(reg_val, octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)));
+ loop--;
+ }
+ if (!loop) {
+ dev_err(&oct->pci_dev->dev,
+ "clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
+ q_no);
+ return -1;
+ }
+ WRITE_ONCE(reg_val, READ_ONCE(reg_val) &
+ ~CN23XX_PKT_INPUT_CTL_RST);
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ READ_ONCE(reg_val));
+
+ WRITE_ONCE(reg_val, octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)));
+ if (READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) {
+ dev_err(&oct->pci_dev->dev,
+ "clearing the reset failed for qno: %u\n",
+ q_no);
+ ret_val = -1;
+ }
+ }
+
+ return ret_val;
+}
+
+static int cn23xx_vf_setup_global_input_regs(struct octeon_device *oct)
+{
+ struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+ struct octeon_instr_queue *iq;
+ u64 q_no, intr_threshold;
+ u64 d64;
+
+ if (cn23xx_vf_reset_io_queues(oct, oct->sriov_info.rings_per_vf))
+ return -1;
+
+ for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+ void __iomem *inst_cnt_reg;
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_DOORBELL(q_no),
+ 0xFFFFFFFF);
+ iq = oct->instr_queue[q_no];
+
+ if (iq)
+ inst_cnt_reg = iq->inst_cnt_reg;
+ else
+ inst_cnt_reg = (u8 *)oct->mmio[0].hw_addr +
+ CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no);
+
+ d64 = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no));
+
+ d64 &= 0xEFFFFFFFFFFFFFFFL;
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+ d64);
+
+ /* Select ES, RO, NS, RDSIZE,DPTR Fomat#0 for
+ * the Input Queues
+ */
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ CN23XX_PKT_INPUT_CTL_MASK);
+
+ /* set the wmark level to trigger PI_INT */
+ intr_threshold = CFG_GET_IQ_INTR_PKT(cn23xx->conf) &
+ CN23XX_PKT_IN_DONE_WMARK_MASK;
+
+ writeq((readq(inst_cnt_reg) &
+ ~(CN23XX_PKT_IN_DONE_WMARK_MASK <<
+ CN23XX_PKT_IN_DONE_WMARK_BIT_POS)) |
+ (intr_threshold << CN23XX_PKT_IN_DONE_WMARK_BIT_POS),
+ inst_cnt_reg);
+ }
+ return 0;
+}
+
+static void cn23xx_vf_setup_global_output_regs(struct octeon_device *oct)
+{
+ u32 reg_val;
+ u32 q_no;
+
+ for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKTS_CREDIT(q_no),
+ 0xFFFFFFFF);
+
+ reg_val =
+ octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKTS_SENT(q_no));
+
+ reg_val &= 0xEFFFFFFFFFFFFFFFL;
+
+ reg_val =
+ octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+
+ /* set IPTR & DPTR */
+ reg_val |=
+ (CN23XX_PKT_OUTPUT_CTL_IPTR | CN23XX_PKT_OUTPUT_CTL_DPTR);
+
+ /* reset BMODE */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_BMODE);
+
+ /* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+ * for Output Queue ScatterList reset ROR_P, NSR_P
+ */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR_P);
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR_P);
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ES_P);
+#else
+ reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES_P);
+#endif
+ /* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+ * for Output Queue Data reset ROR, NSR
+ */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR);
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR);
+ /* set the ES bit */
+ reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES);
+
+ /* write all the selected settings */
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no),
+ reg_val);
+ }
+}
+
+static int cn23xx_setup_vf_device_regs(struct octeon_device *oct)
+{
+ if (cn23xx_vf_setup_global_input_regs(oct))
+ return -1;
+
+ cn23xx_vf_setup_global_output_regs(oct);
+
+ return 0;
+}
+
+static void cn23xx_setup_vf_iq_regs(struct octeon_device *oct, u32 iq_no)
+{
+ struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
+ u64 pkt_in_done;
+
+ /* Write the start of the input queue's ring and its size */
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(iq_no),
+ iq->base_addr_dma);
+ octeon_write_csr(oct, CN23XX_VF_SLI_IQ_SIZE(iq_no), iq->max_count);
+
+ /* Remember the doorbell & instruction count register addr
+ * for this queue
+ */
+ iq->doorbell_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_DOORBELL(iq_no);
+ iq->inst_cnt_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq_no);
+ dev_dbg(&oct->pci_dev->dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n",
+ iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
+
+ /* Store the current instruction counter (used in flush_iq
+ * calculation)
+ */
+ pkt_in_done = readq(iq->inst_cnt_reg);
+
+ if (oct->msix_on) {
+ /* Set CINT_ENB to enable IQ interrupt */
+ writeq((pkt_in_done | CN23XX_INTR_CINT_ENB),
+ iq->inst_cnt_reg);
+ }
+ iq->reset_instr_cnt = 0;
+}
+
+static void cn23xx_setup_vf_oq_regs(struct octeon_device *oct, u32 oq_no)
+{
+ struct octeon_droq *droq = oct->droq[oq_no];
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_OQ_BASE_ADDR64(oq_no),
+ droq->desc_ring_dma);
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_SIZE(oq_no), droq->max_count);
+
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq_no),
+ (droq->buffer_size | (OCT_RH_SIZE << 16)));
+
+ /* Get the mapped address of the pkt_sent and pkts_credit regs */
+ droq->pkts_sent_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_SENT(oq_no);
+ droq->pkts_credit_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq_no);
+}
+
+static void cn23xx_vf_mbox_thread(struct work_struct *work)
+{
+ struct cavium_wk *wk = (struct cavium_wk *)work;
+ struct octeon_mbox *mbox = (struct octeon_mbox *)wk->ctxptr;
+
+ octeon_mbox_process_message(mbox);
+}
+
+static int cn23xx_free_vf_mbox(struct octeon_device *oct)
+{
+ cancel_delayed_work_sync(&oct->mbox[0]->mbox_poll_wk.work);
+ vfree(oct->mbox[0]);
+ return 0;
+}
+
+static int cn23xx_setup_vf_mbox(struct octeon_device *oct)
+{
+ struct octeon_mbox *mbox = NULL;
+
+ mbox = vmalloc(sizeof(*mbox));
+ if (!mbox)
+ return 1;
+
+ memset(mbox, 0, sizeof(struct octeon_mbox));
+
+ spin_lock_init(&mbox->lock);
+
+ mbox->oct_dev = oct;
+
+ mbox->q_no = 0;
+
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+
+ /* VF mbox interrupt reg */
+ mbox->mbox_int_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_PKT_MBOX_INT(0);
+ /* VF reads from SIG0 reg */
+ mbox->mbox_read_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 0);
+ /* VF writes into SIG1 reg */
+ mbox->mbox_write_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 1);
+
+ INIT_DELAYED_WORK(&mbox->mbox_poll_wk.work,
+ cn23xx_vf_mbox_thread);
+
+ mbox->mbox_poll_wk.ctxptr = mbox;
+
+ oct->mbox[0] = mbox;
+
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+
+ return 0;
+}
+
+static int cn23xx_enable_vf_io_queues(struct octeon_device *oct)
+{
+ u32 q_no;
+
+ for (q_no = 0; q_no < oct->num_iqs; q_no++) {
+ u64 reg_val;
+
+ /* set the corresponding IQ IS_64B bit */
+ if (oct->io_qmask.iq64B & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ reg_val |= CN23XX_PKT_INPUT_CTL_IS_64B;
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+ }
+
+ /* set the corresponding IQ ENB bit */
+ if (oct->io_qmask.iq & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ reg_val |= CN23XX_PKT_INPUT_CTL_RING_ENB;
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+ }
+ }
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ u32 reg_val;
+
+ /* set the corresponding OQ ENB bit */
+ if (oct->io_qmask.oq & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr(
+ oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+ reg_val |= CN23XX_PKT_OUTPUT_CTL_RING_ENB;
+ octeon_write_csr(
+ oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no), reg_val);
+ }
+ }
+
+ return 0;
+}
+
+static void cn23xx_disable_vf_io_queues(struct octeon_device *oct)
+{
+ u32 num_queues = oct->num_iqs;
+
+ /* per HRM, rings can only be disabled via reset operation,
+ * NOT via SLI_PKT()_INPUT/OUTPUT_CONTROL[ENB]
+ */
+ if (num_queues < oct->num_oqs)
+ num_queues = oct->num_oqs;
+
+ cn23xx_vf_reset_io_queues(oct, num_queues);
+}
+
+void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct)
+{
+ struct octeon_mbox_cmd mbox_cmd;
+
+ mbox_cmd.msg.u64 = 0;
+ mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+ mbox_cmd.msg.s.resp_needed = 0;
+ mbox_cmd.msg.s.cmd = OCTEON_VF_FLR_REQUEST;
+ mbox_cmd.msg.s.len = 1;
+ mbox_cmd.q_no = 0;
+ mbox_cmd.recv_len = 0;
+ mbox_cmd.recv_status = 0;
+ mbox_cmd.fn = NULL;
+ mbox_cmd.fn_arg = 0;
+
+ octeon_mbox_write(oct, &mbox_cmd);
+}
+
+static void octeon_pfvf_hs_callback(struct octeon_device *oct,
+ struct octeon_mbox_cmd *cmd,
+ void *arg)
+{
+ u32 major = 0;
+
+ memcpy((uint8_t *)&oct->pfvf_hsword, cmd->msg.s.params,
+ CN23XX_MAILBOX_MSGPARAM_SIZE);
+ if (cmd->recv_len > 1) {
+ major = ((struct lio_version *)(cmd->data))->major;
+ major = major << 16;
+ }
+
+ atomic_set((atomic_t *)arg, major | 1);
+}
+
+int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct)
+{
+ struct octeon_mbox_cmd mbox_cmd;
+ u32 q_no, count = 0;
+ atomic_t status;
+ u32 pfmajor;
+ u32 vfmajor;
+ u32 ret;
+
+ /* Sending VF_ACTIVE indication to the PF driver */
+ dev_dbg(&oct->pci_dev->dev, "requesting info from pf\n");
+
+ mbox_cmd.msg.u64 = 0;
+ mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+ mbox_cmd.msg.s.resp_needed = 1;
+ mbox_cmd.msg.s.cmd = OCTEON_VF_ACTIVE;
+ mbox_cmd.msg.s.len = 2;
+ mbox_cmd.data[0] = 0;
+ ((struct lio_version *)&mbox_cmd.data[0])->major =
+ LIQUIDIO_BASE_MAJOR_VERSION;
+ ((struct lio_version *)&mbox_cmd.data[0])->minor =
+ LIQUIDIO_BASE_MINOR_VERSION;
+ ((struct lio_version *)&mbox_cmd.data[0])->micro =
+ LIQUIDIO_BASE_MICRO_VERSION;
+ mbox_cmd.q_no = 0;
+ mbox_cmd.recv_len = 0;
+ mbox_cmd.recv_status = 0;
+ mbox_cmd.fn = (octeon_mbox_callback_t)octeon_pfvf_hs_callback;
+ mbox_cmd.fn_arg = &status;
+
+ /* Interrupts are not enabled at this point.
+ * Enable them with default oq ticks
+ */
+ oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
+
+ octeon_mbox_write(oct, &mbox_cmd);
+
+ atomic_set(&status, 0);
+
+ do {
+ schedule_timeout_uninterruptible(1);
+ } while ((!atomic_read(&status)) && (count++ < 100000));
+
+ /* Disable the interrupt so that the interrupsts will be reenabled
+ * with the oq ticks received from the PF
+ */
+ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+ ret = atomic_read(&status);
+ if (!ret) {
+ dev_err(&oct->pci_dev->dev, "octeon_pfvf_handshake timeout\n");
+ return 1;
+ }
+
+ for (q_no = 0 ; q_no < oct->num_iqs ; q_no++)
+ oct->instr_queue[q_no]->txpciq.s.pkind = oct->pfvf_hsword.pkind;
+
+ vfmajor = LIQUIDIO_BASE_MAJOR_VERSION;
+ pfmajor = ret >> 16;
+ if (pfmajor != vfmajor) {
+ dev_err(&oct->pci_dev->dev,
+ "VF Liquidio driver (major version %d) is not compatible with Liquidio PF driver (major version %d)\n",
+ vfmajor, pfmajor);
+ return 1;
+ }
+
+ dev_dbg(&oct->pci_dev->dev,
+ "VF Liquidio driver (major version %d), Liquidio PF driver (major version %d)\n",
+ vfmajor, pfmajor);
+
+ dev_dbg(&oct->pci_dev->dev, "got data from pf pkind is %d\n",
+ oct->pfvf_hsword.pkind);
+
+ return 0;
+}
+
+static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector)
+{
+ struct octeon_device *oct = ioq_vector->oct_dev;
+ u64 mbox_int_val;
+
+ if (!ioq_vector->droq_index) {
+ /* read and clear by writing 1 */
+ mbox_int_val = readq(oct->mbox[0]->mbox_int_reg);
+ writeq(mbox_int_val, oct->mbox[0]->mbox_int_reg);
+ if (octeon_mbox_read(oct->mbox[0]))
+ schedule_delayed_work(&oct->mbox[0]->mbox_poll_wk.work,
+ msecs_to_jiffies(0));
+ }
+}
+
+static u64 cn23xx_vf_msix_interrupt_handler(void *dev)
+{
+ struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev;
+ struct octeon_device *oct = ioq_vector->oct_dev;
+ struct octeon_droq *droq = oct->droq[ioq_vector->droq_index];
+ u64 pkts_sent;
+ u64 ret = 0;
+
+ dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct);
+ pkts_sent = readq(droq->pkts_sent_reg);
+
+ /* If our device has interrupted, then proceed. Also check
+ * for all f's if interrupt was triggered on an error
+ * and the PCI read fails.
+ */
+ if (!pkts_sent || (pkts_sent == 0xFFFFFFFFFFFFFFFFULL))
+ return ret;
+
+ /* Write count reg in sli_pkt_cnts to clear these int. */
+ if ((pkts_sent & CN23XX_INTR_PO_INT) ||
+ (pkts_sent & CN23XX_INTR_PI_INT)) {
+ if (pkts_sent & CN23XX_INTR_PO_INT)
+ ret |= MSIX_PO_INT;
+ }
+
+ if (pkts_sent & CN23XX_INTR_PI_INT)
+ /* We will clear the count when we update the read_index. */
+ ret |= MSIX_PI_INT;
+
+ if (pkts_sent & CN23XX_INTR_MBOX_INT) {
+ cn23xx_handle_vf_mbox_intr(ioq_vector);
+ ret |= MSIX_MBOX_INT;
+ }
+
+ return ret;
+}
+
+static u32 cn23xx_update_read_index(struct octeon_instr_queue *iq)
+{
+ u32 pkt_in_done = readl(iq->inst_cnt_reg);
+ u32 last_done;
+ u32 new_idx;
+
+ last_done = pkt_in_done - iq->pkt_in_done;
+ iq->pkt_in_done = pkt_in_done;
+
+ /* Modulo of the new index with the IQ size will give us
+ * the new index. The iq->reset_instr_cnt is always zero for
+ * cn23xx, so no extra adjustments are needed.
+ */
+ new_idx = (iq->octeon_read_index +
+ (u32)(last_done & CN23XX_PKT_IN_DONE_CNT_MASK)) %
+ iq->max_count;
+
+ return new_idx;
+}
+
+static void cn23xx_enable_vf_interrupt(struct octeon_device *oct, u8 intr_flag)
+{
+ struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+ u32 q_no, time_threshold;
+
+ if (intr_flag & OCTEON_OUTPUT_INTR) {
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ /* Set up interrupt packet and time thresholds
+ * for all the OQs
+ */
+ time_threshold = cn23xx_vf_get_oq_ticks(
+ oct, (u32)CFG_GET_OQ_INTR_TIME(cn23xx->conf));
+
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+ (CFG_GET_OQ_INTR_PKT(cn23xx->conf) |
+ ((u64)time_threshold << 32)));
+ }
+ }
+
+ if (intr_flag & OCTEON_INPUT_INTR) {
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ /* Set CINT_ENB to enable IQ interrupt */
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+ ((octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) &
+ ~CN23XX_PKT_IN_DONE_CNT_MASK) |
+ CN23XX_INTR_CINT_ENB));
+ }
+ }
+
+ /* Set queue-0 MBOX_ENB to enable VF mailbox interrupt */
+ if (intr_flag & OCTEON_MBOX_INTR) {
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_PKT_MBOX_INT(0),
+ (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) |
+ CN23XX_INTR_MBOX_ENB));
+ }
+}
+
+static void cn23xx_disable_vf_interrupt(struct octeon_device *oct, u8 intr_flag)
+{
+ u32 q_no;
+
+ if (intr_flag & OCTEON_OUTPUT_INTR) {
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ /* Write all 1's in INT_LEVEL reg to disable PO_INT */
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+ 0x3fffffffffffff);
+ }
+ }
+ if (intr_flag & OCTEON_INPUT_INTR) {
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+ (octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) &
+ ~(CN23XX_INTR_CINT_ENB |
+ CN23XX_PKT_IN_DONE_CNT_MASK)));
+ }
+ }
+
+ if (intr_flag & OCTEON_MBOX_INTR) {
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_PKT_MBOX_INT(0),
+ (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) &
+ ~CN23XX_INTR_MBOX_ENB));
+ }
+}
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
+{
+ struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+ u32 rings_per_vf, ring_flag;
+ u64 reg_val;
+
+ if (octeon_map_pci_barx(oct, 0, 0))
+ return 1;
+
+ /* INPUT_CONTROL[RPVF] gives the VF IOq count */
+ reg_val = octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(0));
+
+ oct->pf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_PF_NUM_POS) &
+ CN23XX_PKT_INPUT_CTL_PF_NUM_MASK;
+ oct->vf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_VF_NUM_POS) &
+ CN23XX_PKT_INPUT_CTL_VF_NUM_MASK;
+
+ reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
+
+ rings_per_vf = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
+
+ ring_flag = 0;
+
+ cn23xx->conf = oct_get_config_info(oct, LIO_23XX);
+ if (!cn23xx->conf) {
+ dev_err(&oct->pci_dev->dev, "%s No Config found for CN23XX\n",
+ __func__);
+ octeon_unmap_pci_barx(oct, 0);
+ return 1;
+ }
+
+ if (oct->sriov_info.rings_per_vf > rings_per_vf) {
+ dev_warn(&oct->pci_dev->dev,
+ "num_queues:%d greater than PF configured rings_per_vf:%d. Reducing to %d.\n",
+ oct->sriov_info.rings_per_vf, rings_per_vf,
+ rings_per_vf);
+ oct->sriov_info.rings_per_vf = rings_per_vf;
+ } else {
+ if (rings_per_vf > num_present_cpus()) {
+ dev_warn(&oct->pci_dev->dev,
+ "PF configured rings_per_vf:%d greater than num_cpu:%d. Using rings_per_vf:%d equal to num cpus\n",
+ rings_per_vf,
+ num_present_cpus(),
+ num_present_cpus());
+ oct->sriov_info.rings_per_vf =
+ num_present_cpus();
+ } else {
+ oct->sriov_info.rings_per_vf = rings_per_vf;
+ }
+ }
+
+ oct->fn_list.setup_iq_regs = cn23xx_setup_vf_iq_regs;
+ oct->fn_list.setup_oq_regs = cn23xx_setup_vf_oq_regs;
+ oct->fn_list.setup_mbox = cn23xx_setup_vf_mbox;
+ oct->fn_list.free_mbox = cn23xx_free_vf_mbox;
+
+ oct->fn_list.msix_interrupt_handler = cn23xx_vf_msix_interrupt_handler;
+
+ oct->fn_list.setup_device_regs = cn23xx_setup_vf_device_regs;
+ oct->fn_list.update_iq_read_idx = cn23xx_update_read_index;
+
+ oct->fn_list.enable_interrupt = cn23xx_enable_vf_interrupt;
+ oct->fn_list.disable_interrupt = cn23xx_disable_vf_interrupt;
+
+ oct->fn_list.enable_io_queues = cn23xx_enable_vf_io_queues;
+ oct->fn_list.disable_io_queues = cn23xx_disable_vf_io_queues;
+
+ return 0;
+}
+
+void cn23xx_dump_vf_iq_regs(struct octeon_device *oct)
+{
+ u32 regval, q_no;
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_DOORBELL_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_DOORBELL(0),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_DOORBELL(0))));
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_BASEADDR_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_BASE_ADDR64(0),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(0))));
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_FIFO_RSIZE_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_SIZE(0),
+ CVM_CAST64(octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_SIZE(0))));
+
+ for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
+ dev_dbg(&oct->pci_dev->dev, "SLI_PKT[%d]_INPUT_CTL [0x%x]: 0x%016llx\n",
+ q_no, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no))));
+ }
+
+ pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, &regval);
+ dev_dbg(&oct->pci_dev->dev, "Config DevCtl [0x%x]: 0x%08x\n",
+ CN23XX_CONFIG_PCIE_DEVCTL, regval);
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
new file mode 100644
index 000000000000..3f98c7334957
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+/*! \file cn23xx_device.h
+ * \brief Host Driver: Routines that perform CN23XX specific operations.
+ */
+
+#ifndef __CN23XX_VF_DEVICE_H__
+#define __CN23XX_VF_DEVICE_H__
+
+#include "cn23xx_vf_regs.h"
+
+/* Register address and configuration for a CN23XX devices.
+ * If device specific changes need to be made then add a struct to include
+ * device specific fields as shown in the commented section
+ */
+struct octeon_cn23xx_vf {
+ struct octeon_config *conf;
+};
+
+#define BUSY_READING_REG_VF_LOOP_COUNT 10000
+
+#define CN23XX_MAILBOX_MSGPARAM_SIZE 6
+
+#define MAX_VF_IP_OP_PENDING_PKT_COUNT 100
+
+void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct);
+
+int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct);
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
+
+u32 cn23xx_vf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
+
+void cn23xx_dump_vf_initialized_regs(struct octeon_device *oct);
+#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
new file mode 100644
index 000000000000..d33dd8f4226f
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
@@ -0,0 +1,274 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+/*! \file cn23xx_vf_regs.h
+ * \brief Host Driver: Register Address and Register Mask values for
+ * Octeon CN23XX vf functions.
+ */
+
+#ifndef __CN23XX_VF_REGS_H__
+#define __CN23XX_VF_REGS_H__
+
+#define CN23XX_CONFIG_XPANSION_BAR 0x38
+
+#define CN23XX_CONFIG_PCIE_CAP 0x70
+#define CN23XX_CONFIG_PCIE_DEVCAP 0x74
+#define CN23XX_CONFIG_PCIE_DEVCTL 0x78
+#define CN23XX_CONFIG_PCIE_LINKCAP 0x7C
+#define CN23XX_CONFIG_PCIE_LINKCTL 0x80
+#define CN23XX_CONFIG_PCIE_SLOTCAP 0x84
+#define CN23XX_CONFIG_PCIE_SLOTCTL 0x88
+
+#define CN23XX_CONFIG_PCIE_FLTMSK 0x720
+
+/* The input jabber is used to determine the TSO max size.
+ * Due to H/W limitation, this need to be reduced to 60000
+ * in order to to H/W TSO and avoid the WQE malfarmation
+ * PKO_BUG_24989_WQE_LEN
+ */
+#define CN23XX_DEFAULT_INPUT_JABBER 0xEA60 /*60000*/
+
+/* ############## BAR0 Registers ################ */
+
+/* Each Input Queue register is at a 16-byte Offset in BAR0 */
+#define CN23XX_VF_IQ_OFFSET 0x20000
+
+/*###################### REQUEST QUEUE #########################*/
+
+/* 64 registers for Input Queue Instr Count - SLI_PKT_IN_DONE0_CNTS */
+#define CN23XX_VF_SLI_IQ_INSTR_COUNT_START64 0x10040
+
+/* 64 registers for Input Queues Start Addr - SLI_PKT0_INSTR_BADDR */
+#define CN23XX_VF_SLI_IQ_BASE_ADDR_START64 0x10010
+
+/* 64 registers for Input Doorbell - SLI_PKT0_INSTR_BAOFF_DBELL */
+#define CN23XX_VF_SLI_IQ_DOORBELL_START 0x10020
+
+/* 64 registers for Input Queue size - SLI_PKT0_INSTR_FIFO_RSIZE */
+#define CN23XX_VF_SLI_IQ_SIZE_START 0x10030
+
+/* 64 registers (64-bit) - ES, RO, NS, Arbitration for Input Queue Data &
+ * gather list fetches. SLI_PKT(0..63)_INPUT_CONTROL.
+ */
+#define CN23XX_VF_SLI_IQ_PKT_CONTROL_START64 0x10000
+
+/*------- Request Queue Macros ---------*/
+#define CN23XX_VF_SLI_IQ_PKT_CONTROL64(iq) \
+ (CN23XX_VF_SLI_IQ_PKT_CONTROL_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_BASE_ADDR64(iq) \
+ (CN23XX_VF_SLI_IQ_BASE_ADDR_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_SIZE(iq) \
+ (CN23XX_VF_SLI_IQ_SIZE_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_DOORBELL(iq) \
+ (CN23XX_VF_SLI_IQ_DOORBELL_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq) \
+ (CN23XX_VF_SLI_IQ_INSTR_COUNT_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Masks ----------------*/
+#define CN23XX_PKT_INPUT_CTL_VF_NUM BIT_ULL(32)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM BIT(29)
+/* Number of instructions to be read in one MAC read request.
+ * setting to Max value(4)
+ */
+#define CN23XX_PKT_INPUT_CTL_RDSIZE (3 << 25)
+#define CN23XX_PKT_INPUT_CTL_IS_64B BIT(24)
+#define CN23XX_PKT_INPUT_CTL_RST BIT(23)
+#define CN23XX_PKT_INPUT_CTL_QUIET BIT(28)
+#define CN23XX_PKT_INPUT_CTL_RING_ENB BIT(22)
+#define CN23XX_PKT_INPUT_CTL_DATA_NS BIT(8)
+#define CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP BIT(6)
+#define CN23XX_PKT_INPUT_CTL_DATA_RO BIT(5)
+#define CN23XX_PKT_INPUT_CTL_USE_CSR BIT(4)
+#define CN23XX_PKT_INPUT_CTL_GATHER_NS BIT(3)
+#define CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP (2)
+#define CN23XX_PKT_INPUT_CTL_GATHER_RO (1)
+
+/** Rings per Virtual Function [RO] **/
+#define CN23XX_PKT_INPUT_CTL_RPVF_MASK (0x3F)
+#define CN23XX_PKT_INPUT_CTL_RPVF_POS (48)
+/* These bits[47:44][RO] give the Physical function number info within the MAC*/
+#define CN23XX_PKT_INPUT_CTL_PF_NUM_MASK (0x7)
+#define CN23XX_PKT_INPUT_CTL_PF_NUM_POS (45)
+/** These bits[43:32][RO] give the virtual function number info within the PF*/
+#define CN23XX_PKT_INPUT_CTL_VF_NUM_MASK (0x1FFF)
+#define CN23XX_PKT_INPUT_CTL_VF_NUM_POS (32)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM_MASK (0x3)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM_POS (29)
+#define CN23XX_PKT_IN_DONE_WMARK_MASK (0xFFFFULL)
+#define CN23XX_PKT_IN_DONE_WMARK_BIT_POS (32)
+#define CN23XX_PKT_IN_DONE_CNT_MASK (0x00000000FFFFFFFFULL)
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+#define CN23XX_PKT_INPUT_CTL_MASK \
+ (CN23XX_PKT_INPUT_CTL_RDSIZE \
+ | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP \
+ | CN23XX_PKT_INPUT_CTL_USE_CSR)
+#else
+#define CN23XX_PKT_INPUT_CTL_MASK \
+ (CN23XX_PKT_INPUT_CTL_RDSIZE \
+ | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP \
+ | CN23XX_PKT_INPUT_CTL_USE_CSR \
+ | CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP)
+#endif
+
+/** Masks for SLI_PKT_IN_DONE(0..63)_CNTS Register */
+#define CN23XX_IN_DONE_CNTS_PI_INT BIT_ULL(62)
+#define CN23XX_IN_DONE_CNTS_CINT_ENB BIT_ULL(48)
+
+/*############################ OUTPUT QUEUE #########################*/
+
+/* 64 registers for Output queue control - SLI_PKT(0..63)_OUTPUT_CONTROL */
+#define CN23XX_VF_SLI_OQ_PKT_CONTROL_START 0x10050
+
+/* 64 registers for Output queue buffer and info size - SLI_PKT0_OUT_SIZE */
+#define CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE 0x10060
+
+/* 64 registers for Output Queue Start Addr - SLI_PKT0_SLIST_BADDR */
+#define CN23XX_VF_SLI_OQ_BASE_ADDR_START64 0x10070
+
+/* 64 registers for Output Queue Packet Credits - SLI_PKT0_SLIST_BAOFF_DBELL */
+#define CN23XX_VF_SLI_OQ_PKT_CREDITS_START 0x10080
+
+/* 64 registers for Output Queue size - SLI_PKT0_SLIST_FIFO_RSIZE */
+#define CN23XX_VF_SLI_OQ_SIZE_START 0x10090
+
+/* 64 registers for Output Queue Packet Count - SLI_PKT0_CNTS */
+#define CN23XX_VF_SLI_OQ_PKT_SENT_START 0x100B0
+
+/* 64 registers for Output Queue INT Levels - SLI_PKT0_INT_LEVELS */
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 0x100A0
+
+/* Each Output Queue register is at a 16-byte Offset in BAR0 */
+#define CN23XX_VF_OQ_OFFSET 0x20000
+
+/*------- Output Queue Macros ---------*/
+
+#define CN23XX_VF_SLI_OQ_PKT_CONTROL(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_CONTROL_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BASE_ADDR64(oq) \
+ (CN23XX_VF_SLI_OQ_BASE_ADDR_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_SIZE(oq) \
+ (CN23XX_VF_SLI_OQ_SIZE_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq) \
+ (CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_SENT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_SENT_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_CREDITS_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+/* Macro's for accessing CNT and TIME separately from INT_LEVELS */
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_CNT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_TIME(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + \
+ ((oq) * CN23XX_VF_OQ_OFFSET) + 4)
+
+/*------------------ Masks ----------------*/
+#define CN23XX_PKT_OUTPUT_CTL_TENB BIT(13)
+#define CN23XX_PKT_OUTPUT_CTL_CENB BIT(12)
+#define CN23XX_PKT_OUTPUT_CTL_IPTR BIT(11)
+#define CN23XX_PKT_OUTPUT_CTL_ES BIT(9)
+#define CN23XX_PKT_OUTPUT_CTL_NSR BIT(8)
+#define CN23XX_PKT_OUTPUT_CTL_ROR BIT(7)
+#define CN23XX_PKT_OUTPUT_CTL_DPTR BIT(6)
+#define CN23XX_PKT_OUTPUT_CTL_BMODE BIT(5)
+#define CN23XX_PKT_OUTPUT_CTL_ES_P BIT(3)
+#define CN23XX_PKT_OUTPUT_CTL_NSR_P BIT(2)
+#define CN23XX_PKT_OUTPUT_CTL_ROR_P BIT(1)
+#define CN23XX_PKT_OUTPUT_CTL_RING_ENB BIT(0)
+
+/*######################### Mailbox Reg Macros ########################*/
+#define CN23XX_VF_SLI_PKT_MBOX_INT_START 0x10210
+#define CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START 0x10200
+
+#define CN23XX_SLI_MBOX_OFFSET 0x20000
+#define CN23XX_SLI_MBOX_SIG_IDX_OFFSET 0x8
+
+#define CN23XX_VF_SLI_PKT_MBOX_INT(q) \
+ (CN23XX_VF_SLI_PKT_MBOX_INT_START + ((q) * CN23XX_SLI_MBOX_OFFSET))
+
+#define CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q, idx) \
+ (CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START + \
+ ((q) * CN23XX_SLI_MBOX_OFFSET + \
+ (idx) * CN23XX_SLI_MBOX_SIG_IDX_OFFSET))
+
+/*######################## INTERRUPTS #########################*/
+
+#define CN23XX_VF_SLI_INT_SUM_START 0x100D0
+
+#define CN23XX_VF_SLI_INT_SUM(q) \
+ (CN23XX_VF_SLI_INT_SUM_START + ((q) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Interrupt Masks ----------------*/
+
+#define CN23XX_INTR_PO_INT BIT_ULL(63)
+#define CN23XX_INTR_PI_INT BIT_ULL(62)
+#define CN23XX_INTR_MBOX_INT BIT_ULL(61)
+#define CN23XX_INTR_RESEND BIT_ULL(60)
+
+#define CN23XX_INTR_CINT_ENB BIT_ULL(48)
+#define CN23XX_INTR_MBOX_ENB BIT(0)
+
+/*############################ MIO #########################*/
+#define CN23XX_MIO_PTP_CLOCK_CFG 0x0001070000000f00ULL
+#define CN23XX_MIO_PTP_CLOCK_LO 0x0001070000000f08ULL
+#define CN23XX_MIO_PTP_CLOCK_HI 0x0001070000000f10ULL
+#define CN23XX_MIO_PTP_CLOCK_COMP 0x0001070000000f18ULL
+#define CN23XX_MIO_PTP_TIMESTAMP 0x0001070000000f20ULL
+#define CN23XX_MIO_PTP_EVT_CNT 0x0001070000000f28ULL
+#define CN23XX_MIO_PTP_CKOUT_THRESH_LO 0x0001070000000f30ULL
+#define CN23XX_MIO_PTP_CKOUT_THRESH_HI 0x0001070000000f38ULL
+#define CN23XX_MIO_PTP_CKOUT_HI_INCR 0x0001070000000f40ULL
+#define CN23XX_MIO_PTP_CKOUT_LO_INCR 0x0001070000000f48ULL
+#define CN23XX_MIO_PTP_PPS_THRESH_LO 0x0001070000000f50ULL
+#define CN23XX_MIO_PTP_PPS_THRESH_HI 0x0001070000000f58ULL
+#define CN23XX_MIO_PTP_PPS_HI_INCR 0x0001070000000f60ULL
+#define CN23XX_MIO_PTP_PPS_LO_INCR 0x0001070000000f68ULL
+
+/*############################ RST #########################*/
+#define CN23XX_RST_BOOT 0x0001180006001600ULL
+
+/*######################## MSIX TABLE #########################*/
+
+#define CN23XX_MSIX_TABLE_ADDR_START 0x0
+#define CN23XX_MSIX_TABLE_DATA_START 0x8
+
+#define CN23XX_MSIX_TABLE_SIZE 0x10
+#define CN23XX_MSIX_TABLE_ENTRIES 0x41
+
+#define CN23XX_MSIX_ENTRY_VECTOR_CTL BIT_ULL(32)
+
+#define CN23XX_MSIX_TABLE_ADDR(idx) \
+ (CN23XX_MSIX_TABLE_ADDR_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#define CN23XX_MSIX_TABLE_DATA(idx) \
+ (CN23XX_MSIX_TABLE_DATA_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
index e779af88621b..bdec051107a6 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
#include "liquidio_common.h"
@@ -275,7 +271,6 @@ void lio_cn6xxx_setup_iq_regs(struct octeon_device *oct, u32 iq_no)
{
struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
- /* Disable Packet-by-Packet mode; No Parse Mode or Skip length */
octeon_write_csr64(oct, CN6XXX_SLI_IQ_PKT_INSTR_HDR64(iq_no), 0);
/* Write the start of the input queue's ring and its size */
@@ -378,7 +373,7 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
/* Reset the doorbell register for each Input queue. */
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
- if (!(oct->io_qmask.iq & (1ULL << i)))
+ if (!(oct->io_qmask.iq & BIT_ULL(i)))
continue;
octeon_write_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i), 0xFFFFFFFF);
d32 = octeon_read_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i));
@@ -400,9 +395,8 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
;
/* Reset the doorbell register for each Output queue. */
- /* for (i = 0; i < oct->num_oqs; i++) { */
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
- if (!(oct->io_qmask.oq & (1ULL << i)))
+ if (!(oct->io_qmask.oq & BIT_ULL(i)))
continue;
octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i), 0xFFFFFFFF);
d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i));
@@ -537,15 +531,14 @@ static int lio_cn6xxx_process_droq_intr_regs(struct octeon_device *oct)
oct->droq_intr = 0;
- /* for (oq_no = 0; oq_no < oct->num_oqs; oq_no++) { */
for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct); oq_no++) {
- if (!(droq_mask & (1ULL << oq_no)))
+ if (!(droq_mask & BIT_ULL(oq_no)))
continue;
droq = oct->droq[oq_no];
pkt_count = octeon_droq_check_hw_for_pkts(droq);
if (pkt_count) {
- oct->droq_intr |= (1ULL << oq_no);
+ oct->droq_intr |= BIT_ULL(oq_no);
if (droq->ops.poll_mode) {
u32 value;
u32 reg;
@@ -721,8 +714,6 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
struct octeon_config *conf6xxx)
{
- /* int total_instrs = 0; */
-
if (CFG_GET_IQ_MAX_Q(conf6xxx) > CN6XXX_MAX_INPUT_QUEUES) {
dev_err(&oct->pci_dev->dev, "%s: Num IQ (%d) exceeds Max (%d)\n",
__func__, CFG_GET_IQ_MAX_Q(conf6xxx),
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h
index a40a91394079..8ed57134ee0c 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn66xx_device.h
* \brief Host Driver: Routines that perform CN66XX specific operations.
*/
@@ -96,8 +91,8 @@ void lio_cn6xxx_setup_reg_address(struct octeon_device *oct, void *chip,
struct octeon_reg_list *reg_list);
u32 lio_cn6xxx_coprocessor_clock(struct octeon_device *oct);
u32 lio_cn6xxx_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
-int lio_setup_cn66xx_octeon_device(struct octeon_device *);
+int lio_setup_cn66xx_octeon_device(struct octeon_device *oct);
int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
- struct octeon_config *);
+ struct octeon_config *conf6xxx);
#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
index 5e3aff242ad3..b248966837b4 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn66xx_regs.h
* \brief Host Driver: Register Address and Register Mask values for
* Octeon CN66XX devices.
@@ -443,10 +438,10 @@
#define CN6XXX_SLI_S2M_PORT0_CTL 0x3D80
#define CN6XXX_SLI_S2M_PORT1_CTL 0x3D90
#define CN6XXX_SLI_S2M_PORTX_CTL(port) \
- (CN6XXX_SLI_S2M_PORT0_CTL + (port * 0x10))
+ (CN6XXX_SLI_S2M_PORT0_CTL + ((port) * 0x10))
#define CN6XXX_SLI_INT_ENB64(port) \
- (CN6XXX_SLI_INT_ENB64_PORT0 + (port * 0x10))
+ (CN6XXX_SLI_INT_ENB64_PORT0 + ((port) * 0x10))
#define CN6XXX_SLI_MAC_NUMBER 0x3E00
@@ -458,7 +453,7 @@
#define CN6XXX_PCI_BAR1_OFFSET 0x8
#define CN6XXX_BAR1_REG(idx, port) \
- (CN6XXX_BAR1_INDEX_START + (port * CN6XXX_PEM_OFFSET) + \
+ (CN6XXX_BAR1_INDEX_START + ((port) * CN6XXX_PEM_OFFSET) + \
(CN6XXX_PCI_BAR1_OFFSET * (idx)))
/*############################ DPI #########################*/
@@ -476,17 +471,17 @@
#define CN6XXX_DPI_DMA_ENG0_ENB 0x0001df0000000080ULL
#define CN6XXX_DPI_DMA_ENG_ENB(q_no) \
- (CN6XXX_DPI_DMA_ENG0_ENB + (q_no * 8))
+ (CN6XXX_DPI_DMA_ENG0_ENB + ((q_no) * 8))
#define CN6XXX_DPI_DMA_ENG0_BUF 0x0001df0000000880ULL
#define CN6XXX_DPI_DMA_ENG_BUF(q_no) \
- (CN6XXX_DPI_DMA_ENG0_BUF + (q_no * 8))
+ (CN6XXX_DPI_DMA_ENG0_BUF + ((q_no) * 8))
#define CN6XXX_DPI_SLI_PRT0_CFG 0x0001df0000000900ULL
#define CN6XXX_DPI_SLI_PRT1_CFG 0x0001df0000000908ULL
#define CN6XXX_DPI_SLI_PRTX_CFG(port) \
- (CN6XXX_DPI_SLI_PRT0_CFG + (port * 0x10))
+ (CN6XXX_DPI_SLI_PRT0_CFG + ((port) * 0x10))
#define CN6XXX_DPI_DMA_COMMIT_MODE BIT_ULL(58)
#define CN6XXX_DPI_DMA_PKT_HP BIT_ULL(57)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
index dbf3566ead53..50b533ff58e6 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
#include "liquidio_common.h"
@@ -76,7 +72,7 @@ static void lio_cn68xx_setup_pkt_ctl_regs(struct octeon_device *oct)
pktctl = octeon_read_csr64(oct, CN6XXX_SLI_PKT_CTL);
/* 68XX specific */
- max_oqs = CFG_GET_OQ_MAX_Q(CHIP_FIELD(oct, cn6xxx, conf));
+ max_oqs = CFG_GET_OQ_MAX_Q(CHIP_CONF(oct, cn6xxx));
tx_pipe = octeon_read_csr64(oct, CN68XX_SLI_TX_PIPE);
tx_pipe &= 0xffffffffff00ffffULL; /* clear out NUMP field */
tx_pipe |= max_oqs << 16; /* put max_oqs in NUMP field */
diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h
index ea7bdcce6044..66b8d6bf5ec4 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn68xx_device.h
* \brief Host Driver: Routines that perform CN68XX specific operations.
*/
diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h b/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h
index d45a0f4aaf1f..0b742f09e49d 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file cn68xx_regs.h
* \brief Host Driver: Register Address and Register Mask values for
* Octeon CN68XX devices. The register map for CN66XX is the same
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 201eddb3013a..f629c2fe04a4 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/if_vlan.h>
#include "liquidio_common.h"
@@ -89,13 +85,6 @@ void octeon_update_tx_completion_counters(void *buf, int reqtype,
}
(*pkts_compl)++;
-/*TODO, Use some other pound define to suggest
- * the fact that iqs are not tied to netdevs
- * and can take traffic from different netdevs
- * hence bql reporting is done per packet
- * than in bulk. Usage of NO_NAPI in txq completion is
- * a little confusing
- */
*bytes_compl += skb->len;
}
@@ -264,3 +253,34 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
nctrl->ncmd.s.cmd);
}
}
+
+void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
+{
+ bool macaddr_changed = false;
+ struct net_device *netdev;
+ struct lio *lio;
+
+ rtnl_lock();
+
+ netdev = oct->props[0].netdev;
+ lio = GET_LIO(netdev);
+
+ lio->linfo.macaddr_is_admin_asgnd = true;
+
+ if (!ether_addr_equal(netdev->dev_addr, mac)) {
+ macaddr_changed = true;
+ ether_addr_copy(netdev->dev_addr, mac);
+ ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, mac);
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
+ }
+
+ rtnl_unlock();
+
+ if (macaddr_changed)
+ dev_info(&oct->pci_dev->dev,
+ "PF changed VF's MAC address to %pM\n", mac);
+
+ /* no need to notify the firmware of the macaddr change because
+ * the PF did that already
+ */
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index f163e0abbeb2..b00c3002360e 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/netdevice.h>
#include <linux/net_tstamp.h>
#include <linux/pci.h>
@@ -33,6 +29,7 @@
#include "cn66xx_regs.h"
#include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
+#include "cn23xx_vf_device.h"
static int octnet_get_link_stats(struct net_device *netdev);
@@ -74,9 +71,9 @@ enum {
INTERFACE_MODE_MIXED,
};
-#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
#define OCT_ETHTOOL_REGDUMP_LEN 4096
#define OCT_ETHTOOL_REGDUMP_LEN_23XX (4096 * 11)
+#define OCT_ETHTOOL_REGDUMP_LEN_23XX_VF (4096 * 2)
#define OCT_ETHTOOL_REGSVER 1
/* statistics of PF */
@@ -87,9 +84,9 @@ static const char oct_stats_strings[][ETH_GSTRING_LEN] = {
"tx_bytes",
"rx_errors", /*jabber_err+l2_err+frame_err */
"tx_errors", /*fw_err_pko+fw_err_link+fw_err_drop */
- "rx_dropped", /*st->fromwire.total_rcvd - st->fromwire.fw_total_rcvd
- *+st->fromwire.dmac_drop + st->fromwire.fw_err_drop
- */
+ "rx_dropped", /*st->fromwire.total_rcvd - st->fromwire.fw_total_rcvd +
+ *st->fromwire.dmac_drop + st->fromwire.fw_err_drop
+ */
"tx_dropped",
"tx_total_sent",
@@ -152,6 +149,19 @@ static const char oct_stats_strings[][ETH_GSTRING_LEN] = {
"link_state_changes",
};
+/* statistics of VF */
+static const char oct_vf_stats_strings[][ETH_GSTRING_LEN] = {
+ "rx_packets",
+ "tx_packets",
+ "rx_bytes",
+ "tx_bytes",
+ "rx_errors", /* jabber_err + l2_err+frame_err */
+ "tx_errors", /* fw_err_pko + fw_err_link+fw_err_drop */
+ "rx_dropped", /* total_rcvd - fw_total_rcvd + dmac_drop + fw_err_drop */
+ "tx_dropped",
+ "link_state_changes",
+};
+
/* statistics of host tx queue */
static const char oct_iq_stats_strings[][ETH_GSTRING_LEN] = {
"packets", /*oct->instr_queue[iq_no]->stats.tx_done*/
@@ -197,25 +207,28 @@ static const char oct_priv_flags_strings[][ETH_GSTRING_LEN] = {
#define OCTNIC_NCMD_AUTONEG_ON 0x1
#define OCTNIC_NCMD_PHY_ON 0x2
-static int lio_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int lio_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *ecmd)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct oct_link_info *linfo;
+ u32 supported, advertising;
linfo = &lio->linfo;
if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI ||
linfo->link.s.if_mode == INTERFACE_MODE_RXAUI ||
linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
- ecmd->port = PORT_FIBRE;
- ecmd->supported =
- (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE |
- SUPPORTED_Pause);
- ecmd->advertising =
- (ADVERTISED_10000baseT_Full | ADVERTISED_Pause);
- ecmd->transceiver = XCVR_EXTERNAL;
- ecmd->autoneg = AUTONEG_DISABLE;
+ ecmd->base.port = PORT_FIBRE;
+ supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE |
+ SUPPORTED_Pause);
+ advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Pause);
+ ethtool_convert_legacy_u32_to_link_mode(
+ ecmd->link_modes.supported, supported);
+ ethtool_convert_legacy_u32_to_link_mode(
+ ecmd->link_modes.advertising, advertising);
+ ecmd->base.autoneg = AUTONEG_DISABLE;
} else {
dev_err(&oct->pci_dev->dev, "Unknown link interface reported %d\n",
@@ -223,11 +236,11 @@ static int lio_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
}
if (linfo->link.s.link_up) {
- ethtool_cmd_speed_set(ecmd, linfo->link.s.speed);
- ecmd->duplex = linfo->link.s.duplex;
+ ecmd->base.speed = linfo->link.s.speed;
+ ecmd->base.duplex = linfo->link.s.duplex;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
- ecmd->duplex = DUPLEX_UNKNOWN;
+ ecmd->base.speed = SPEED_UNKNOWN;
+ ecmd->base.duplex = DUPLEX_UNKNOWN;
}
return 0;
@@ -251,6 +264,23 @@ lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
}
static void
+lio_get_vf_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+ struct octeon_device *oct;
+ struct lio *lio;
+
+ lio = GET_LIO(netdev);
+ oct = lio->oct_dev;
+
+ memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+ strcpy(drvinfo->driver, "liquidio_vf");
+ strcpy(drvinfo->version, LIQUIDIO_VERSION);
+ strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
+ ETHTOOL_FWVERS_LEN);
+ strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
+}
+
+static void
lio_ethtool_get_channels(struct net_device *dev,
struct ethtool_channels *channel)
{
@@ -259,14 +289,14 @@ lio_ethtool_get_channels(struct net_device *dev,
u32 max_rx = 0, max_tx = 0, tx_count = 0, rx_count = 0;
if (OCTEON_CN6XXX(oct)) {
- struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+ struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
max_rx = CFG_GET_OQ_MAX_Q(conf6x);
max_tx = CFG_GET_IQ_MAX_Q(conf6x);
rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf6x, lio->ifidx);
tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf6x, lio->ifidx);
} else if (OCTEON_CN23XX_PF(oct)) {
- struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+ struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
max_rx = CFG_GET_OQ_MAX_Q(conf23);
max_tx = CFG_GET_IQ_MAX_Q(conf23);
@@ -589,14 +619,14 @@ lio_ethtool_get_ringparam(struct net_device *netdev,
rx_pending = 0;
if (OCTEON_CN6XXX(oct)) {
- struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+ struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
tx_max_pending = CN6XXX_MAX_IQ_DESCRIPTORS;
rx_max_pending = CN6XXX_MAX_OQ_DESCRIPTORS;
rx_pending = CFG_GET_NUM_RX_DESCS_NIC_IF(conf6x, lio->ifidx);
tx_pending = CFG_GET_NUM_TX_DESCS_NIC_IF(conf6x, lio->ifidx);
} else if (OCTEON_CN23XX_PF(oct)) {
- struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+ struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
tx_max_pending = CN23XX_MAX_IQ_DESCRIPTORS;
rx_max_pending = CN23XX_MAX_OQ_DESCRIPTORS;
@@ -757,9 +787,6 @@ lio_get_ethtool_stats(struct net_device *netdev,
/*sum of oct->instr_queue[iq_no]->stats.tx_dropped */
data[i++] = CVM_CAST64(netstats->tx_dropped);
- /*data[i++] = CVM_CAST64(stats->multicast); */
- /*data[i++] = CVM_CAST64(stats->collisions); */
-
/* firmware tx stats */
/*per_core_stats[cvmx_get_core_num()].link_stats[mdata->from_ifidx].
*fromhost.fw_total_sent
@@ -910,9 +937,8 @@ lio_get_ethtool_stats(struct net_device *netdev,
/*lio->link_changes*/
data[i++] = CVM_CAST64(lio->link_changes);
- /* TX -- lio_update_stats(lio); */
for (j = 0; j < MAX_OCTEON_INSTR_QUEUES(oct_dev); j++) {
- if (!(oct_dev->io_qmask.iq & (1ULL << j)))
+ if (!(oct_dev->io_qmask.iq & BIT_ULL(j)))
continue;
/*packets to network port*/
/*# of packets tx to network */
@@ -954,9 +980,8 @@ lio_get_ethtool_stats(struct net_device *netdev,
}
/* RX */
- /* for (j = 0; j < oct_dev->num_oqs; j++) { */
for (j = 0; j < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); j++) {
- if (!(oct_dev->io_qmask.oq & (1ULL << j)))
+ if (!(oct_dev->io_qmask.oq & BIT_ULL(j)))
continue;
/*packets send to TCP/IP network stack */
@@ -992,6 +1017,109 @@ lio_get_ethtool_stats(struct net_device *netdev,
}
}
+static void lio_vf_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats
+ __attribute__((unused)),
+ u64 *data)
+{
+ struct net_device_stats *netstats = &netdev->stats;
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct_dev = lio->oct_dev;
+ int i = 0, j, vj;
+
+ netdev->netdev_ops->ndo_get_stats(netdev);
+ /* sum of oct->droq[oq_no]->stats->rx_pkts_received */
+ data[i++] = CVM_CAST64(netstats->rx_packets);
+ /* sum of oct->instr_queue[iq_no]->stats.tx_done */
+ data[i++] = CVM_CAST64(netstats->tx_packets);
+ /* sum of oct->droq[oq_no]->stats->rx_bytes_received */
+ data[i++] = CVM_CAST64(netstats->rx_bytes);
+ /* sum of oct->instr_queue[iq_no]->stats.tx_tot_bytes */
+ data[i++] = CVM_CAST64(netstats->tx_bytes);
+ data[i++] = CVM_CAST64(netstats->rx_errors);
+ data[i++] = CVM_CAST64(netstats->tx_errors);
+ /* sum of oct->droq[oq_no]->stats->rx_dropped +
+ * oct->droq[oq_no]->stats->dropped_nodispatch +
+ * oct->droq[oq_no]->stats->dropped_toomany +
+ * oct->droq[oq_no]->stats->dropped_nomem
+ */
+ data[i++] = CVM_CAST64(netstats->rx_dropped);
+ /* sum of oct->instr_queue[iq_no]->stats.tx_dropped */
+ data[i++] = CVM_CAST64(netstats->tx_dropped);
+ /* lio->link_changes */
+ data[i++] = CVM_CAST64(lio->link_changes);
+
+ for (vj = 0; vj < lio->linfo.num_txpciq; vj++) {
+ j = lio->linfo.txpciq[vj].s.q_no;
+
+ /* packets to network port */
+ /* # of packets tx to network */
+ data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
+ /* # of bytes tx to network */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.tx_tot_bytes);
+ /* # of packets dropped */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.tx_dropped);
+ /* # of tx fails due to queue full */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.tx_iq_busy);
+ /* XXX gather entries sent */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.sgentry_sent);
+
+ /* instruction to firmware: data and control */
+ /* # of instructions to the queue */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.instr_posted);
+ /* # of instructions processed */
+ data[i++] =
+ CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_processed);
+ /* # of instructions could not be processed */
+ data[i++] =
+ CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_dropped);
+ /* bytes sent through the queue */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.bytes_sent);
+ /* tso request */
+ data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_gso);
+ /* vxlan request */
+ data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_vxlan);
+ /* txq restart */
+ data[i++] = CVM_CAST64(
+ oct_dev->instr_queue[j]->stats.tx_restart);
+ }
+
+ /* RX */
+ for (vj = 0; vj < lio->linfo.num_rxpciq; vj++) {
+ j = lio->linfo.rxpciq[vj].s.q_no;
+
+ /* packets send to TCP/IP network stack */
+ /* # of packets to network stack */
+ data[i++] = CVM_CAST64(
+ oct_dev->droq[j]->stats.rx_pkts_received);
+ /* # of bytes to network stack */
+ data[i++] = CVM_CAST64(
+ oct_dev->droq[j]->stats.rx_bytes_received);
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem +
+ oct_dev->droq[j]->stats.dropped_toomany +
+ oct_dev->droq[j]->stats.rx_dropped);
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_dropped);
+
+ /* control and data path */
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
+ data[i++] =
+ CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
+
+ data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_vxlan);
+ data[i++] =
+ CVM_CAST64(oct_dev->droq[j]->stats.rx_alloc_failure);
+ }
+}
+
static void lio_get_priv_flags_strings(struct lio *lio, u8 *data)
{
struct octeon_device *oct_dev = lio->oct_dev;
@@ -999,6 +1127,7 @@ static void lio_get_priv_flags_strings(struct lio *lio, u8 *data)
switch (oct_dev->chip_id) {
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
for (i = 0; i < ARRAY_SIZE(oct_priv_flags_strings); i++) {
sprintf(data, "%s", oct_priv_flags_strings[i]);
data += ETH_GSTRING_LEN;
@@ -1030,7 +1159,55 @@ static void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
- if (!(oct_dev->io_qmask.iq & (1ULL << i)))
+ if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
+ continue;
+ for (j = 0; j < num_iq_stats; j++) {
+ sprintf(data, "tx-%d-%s", i,
+ oct_iq_stats_strings[j]);
+ data += ETH_GSTRING_LEN;
+ }
+ }
+
+ num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
+ for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
+ if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
+ continue;
+ for (j = 0; j < num_oq_stats; j++) {
+ sprintf(data, "rx-%d-%s", i,
+ oct_droq_stats_strings[j]);
+ data += ETH_GSTRING_LEN;
+ }
+ }
+ break;
+
+ case ETH_SS_PRIV_FLAGS:
+ lio_get_priv_flags_strings(lio, data);
+ break;
+ default:
+ netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
+ break;
+ }
+}
+
+static void lio_vf_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
+{
+ int num_iq_stats, num_oq_stats, i, j;
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct_dev = lio->oct_dev;
+ int num_stats;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ num_stats = ARRAY_SIZE(oct_vf_stats_strings);
+ for (j = 0; j < num_stats; j++) {
+ sprintf(data, "%s", oct_vf_stats_strings[j]);
+ data += ETH_GSTRING_LEN;
+ }
+
+ num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
+ for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
+ if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
continue;
for (j = 0; j < num_iq_stats; j++) {
sprintf(data, "tx-%d-%s", i,
@@ -1040,9 +1217,8 @@ static void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
}
num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
- /* for (i = 0; i < oct_dev->num_oqs; i++) { */
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
- if (!(oct_dev->io_qmask.oq & (1ULL << i)))
+ if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
continue;
for (j = 0; j < num_oq_stats; j++) {
sprintf(data, "rx-%d-%s", i,
@@ -1067,6 +1243,7 @@ static int lio_get_priv_flags_ss_count(struct lio *lio)
switch (oct_dev->chip_id) {
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
return ARRAY_SIZE(oct_priv_flags_strings);
case OCTEON_CN68XX:
case OCTEON_CN66XX:
@@ -1094,6 +1271,23 @@ static int lio_get_sset_count(struct net_device *netdev, int sset)
}
}
+static int lio_vf_get_sset_count(struct net_device *netdev, int sset)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct_dev = lio->oct_dev;
+
+ switch (sset) {
+ case ETH_SS_STATS:
+ return (ARRAY_SIZE(oct_vf_stats_strings) +
+ ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
+ ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
+ case ETH_SS_PRIV_FLAGS:
+ return lio_get_priv_flags_ss_count(lio);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int lio_get_intr_coalesce(struct net_device *netdev,
struct ethtool_coalesce *intr_coal)
{
@@ -1106,6 +1300,7 @@ static int lio_get_intr_coalesce(struct net_device *netdev,
switch (oct->chip_id) {
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
if (!intrmod_cfg->rx_enable) {
intr_coal->rx_coalesce_usecs = intrmod_cfg->rx_usecs;
intr_coal->rx_max_coalesced_frames =
@@ -1152,7 +1347,7 @@ static int lio_get_intr_coalesce(struct net_device *netdev,
intr_coal->rx_max_coalesced_frames_low =
intrmod_cfg->rx_mincnt_trigger;
}
- if (OCTEON_CN23XX_PF(oct) &&
+ if ((OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) &&
(intrmod_cfg->tx_enable)) {
intr_coal->use_adaptive_tx_coalesce = intrmod_cfg->tx_enable;
intr_coal->tx_max_coalesced_frames_high =
@@ -1510,6 +1705,26 @@ oct_cfg_rx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal)
oct->intrmod.rx_frames = rx_max_coalesced_frames;
break;
}
+ case OCTEON_CN23XX_VF_VID: {
+ int q_no;
+
+ if (!intr_coal->rx_max_coalesced_frames)
+ rx_max_coalesced_frames = oct->intrmod.rx_frames;
+ else
+ rx_max_coalesced_frames =
+ intr_coal->rx_max_coalesced_frames;
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+ (octeon_read_csr64(
+ oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no)) &
+ (0x3fffff00000000UL)) |
+ rx_max_coalesced_frames);
+ /* consider writing to resend bit here */
+ }
+ oct->intrmod.rx_frames = rx_max_coalesced_frames;
+ break;
+ }
default:
return -EINVAL;
}
@@ -1563,6 +1778,27 @@ static int oct_cfg_rx_intrtime(struct lio *lio,
oct->intrmod.rx_usecs = rx_coalesce_usecs;
break;
}
+ case OCTEON_CN23XX_VF_VID: {
+ u64 time_threshold;
+ int q_no;
+
+ if (!intr_coal->rx_coalesce_usecs)
+ rx_coalesce_usecs = oct->intrmod.rx_usecs;
+ else
+ rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
+
+ time_threshold =
+ cn23xx_vf_get_oq_ticks(oct, (u32)rx_coalesce_usecs);
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+ (oct->intrmod.rx_frames |
+ (time_threshold << 32)));
+ /* consider setting resend bit */
+ }
+ oct->intrmod.rx_usecs = rx_coalesce_usecs;
+ break;
+ }
default:
return -EINVAL;
}
@@ -1584,6 +1820,7 @@ oct_cfg_tx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal
case OCTEON_CN68XX:
case OCTEON_CN66XX:
break;
+ case OCTEON_CN23XX_VF_VID:
case OCTEON_CN23XX_PF_VID: {
int q_no;
@@ -1642,6 +1879,7 @@ static int lio_set_intr_coalesce(struct net_device *netdev,
}
break;
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
break;
default:
return -EINVAL;
@@ -1704,86 +1942,6 @@ static int lio_get_ts_info(struct net_device *netdev,
return 0;
}
-static int lio_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-{
- struct lio *lio = GET_LIO(netdev);
- struct octeon_device *oct = lio->oct_dev;
- struct oct_link_info *linfo;
- struct octnic_ctrl_pkt nctrl;
- int ret = 0;
-
- /* get the link info */
- linfo = &lio->linfo;
-
- if (ecmd->autoneg != AUTONEG_ENABLE && ecmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
-
- if (ecmd->autoneg == AUTONEG_DISABLE && ((ecmd->speed != SPEED_100 &&
- ecmd->speed != SPEED_10) ||
- (ecmd->duplex != DUPLEX_HALF &&
- ecmd->duplex != DUPLEX_FULL)))
- return -EINVAL;
-
- /* Ethtool Support is not provided for XAUI, RXAUI, and XFI Interfaces
- * as they operate at fixed Speed and Duplex settings
- */
- if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI ||
- linfo->link.s.if_mode == INTERFACE_MODE_RXAUI ||
- linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
- dev_info(&oct->pci_dev->dev,
- "Autonegotiation, duplex and speed settings cannot be modified.\n");
- return -EINVAL;
- }
-
- memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
-
- nctrl.ncmd.u64 = 0;
- nctrl.ncmd.s.cmd = OCTNET_CMD_SET_SETTINGS;
- nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
- nctrl.wait_time = 1000;
- nctrl.netpndev = (u64)netdev;
- nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
-
- /* Passing the parameters sent by ethtool like Speed, Autoneg & Duplex
- * to SE core application using ncmd.s.more & ncmd.s.param
- */
- if (ecmd->autoneg == AUTONEG_ENABLE) {
- /* Autoneg ON */
- nctrl.ncmd.s.more = OCTNIC_NCMD_PHY_ON |
- OCTNIC_NCMD_AUTONEG_ON;
- nctrl.ncmd.s.param1 = ecmd->advertising;
- } else {
- /* Autoneg OFF */
- nctrl.ncmd.s.more = OCTNIC_NCMD_PHY_ON;
-
- nctrl.ncmd.s.param2 = ecmd->duplex;
-
- nctrl.ncmd.s.param1 = ecmd->speed;
- }
-
- ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
- if (ret < 0) {
- dev_err(&oct->pci_dev->dev, "Failed to set settings\n");
- return -1;
- }
-
- return 0;
-}
-
-static int lio_nway_reset(struct net_device *netdev)
-{
- if (netif_running(netdev)) {
- struct ethtool_cmd ecmd;
-
- memset(&ecmd, 0, sizeof(struct ethtool_cmd));
- ecmd.autoneg = 0;
- ecmd.speed = 0;
- ecmd.duplex = 0;
- lio_set_settings(netdev, &ecmd);
- }
- return 0;
-}
-
/* Return register dump len. */
static int lio_get_regs_len(struct net_device *dev)
{
@@ -1793,6 +1951,8 @@ static int lio_get_regs_len(struct net_device *dev)
switch (oct->chip_id) {
case OCTEON_CN23XX_PF_VID:
return OCT_ETHTOOL_REGDUMP_LEN_23XX;
+ case OCTEON_CN23XX_VF_VID:
+ return OCT_ETHTOOL_REGDUMP_LEN_23XX_VF;
default:
return OCT_ETHTOOL_REGDUMP_LEN;
}
@@ -2018,6 +2178,123 @@ static int cn23xx_read_csr_reg(char *s, struct octeon_device *oct)
return len;
}
+static int cn23xx_vf_read_csr_reg(char *s, struct octeon_device *oct)
+{
+ int len = 0;
+ u32 reg;
+ int i;
+
+ /* PCI Window Registers */
+
+ len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_PKTS_CREDIT(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_SIZE(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_PKT_CONTROL(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_BASE_ADDR64(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_OQ_PKTS_SENT(i);
+ len += sprintf(s + len, "\n[%08x] (SLI_PKT%d_CNTS): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = 0x100c0 + i * CN23XX_VF_OQ_OFFSET;
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = 0x100d0 + i * CN23XX_VF_IQ_OFFSET;
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_VF_INT_SUM): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_PKT_CONTROL64(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_BASE_ADDR64(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_DOORBELL(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_SIZE(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+ reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
+ len += sprintf(s + len,
+ "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
+ reg, i, (u64)octeon_read_csr64(oct, reg));
+ }
+
+ return len;
+}
+
static int cn6xxx_read_csr_reg(char *s, struct octeon_device *oct)
{
u32 reg;
@@ -2164,6 +2441,10 @@ static void lio_get_regs(struct net_device *dev,
memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX);
len += cn23xx_read_csr_reg(regbuf + len, oct);
break;
+ case OCTEON_CN23XX_VF_VID:
+ memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX_VF);
+ len += cn23xx_vf_read_csr_reg(regbuf + len, oct);
+ break;
case OCTEON_CN68XX:
case OCTEON_CN66XX:
memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN);
@@ -2194,7 +2475,7 @@ static int lio_set_priv_flags(struct net_device *netdev, u32 flags)
}
static const struct ethtool_ops lio_ethtool_ops = {
- .get_settings = lio_get_settings,
+ .get_link_ksettings = lio_get_link_ksettings,
.get_link = ethtool_op_get_link,
.get_drvinfo = lio_get_drvinfo,
.get_ringparam = lio_ethtool_get_ringparam,
@@ -2211,8 +2492,26 @@ static const struct ethtool_ops lio_ethtool_ops = {
.get_msglevel = lio_get_msglevel,
.set_msglevel = lio_set_msglevel,
.get_sset_count = lio_get_sset_count,
- .nway_reset = lio_nway_reset,
- .set_settings = lio_set_settings,
+ .get_coalesce = lio_get_intr_coalesce,
+ .set_coalesce = lio_set_intr_coalesce,
+ .get_priv_flags = lio_get_priv_flags,
+ .set_priv_flags = lio_set_priv_flags,
+ .get_ts_info = lio_get_ts_info,
+};
+
+static const struct ethtool_ops lio_vf_ethtool_ops = {
+ .get_link_ksettings = lio_get_link_ksettings,
+ .get_link = ethtool_op_get_link,
+ .get_drvinfo = lio_get_vf_drvinfo,
+ .get_ringparam = lio_ethtool_get_ringparam,
+ .get_channels = lio_ethtool_get_channels,
+ .get_strings = lio_vf_get_strings,
+ .get_ethtool_stats = lio_vf_get_ethtool_stats,
+ .get_regs_len = lio_get_regs_len,
+ .get_regs = lio_get_regs,
+ .get_msglevel = lio_get_msglevel,
+ .set_msglevel = lio_set_msglevel,
+ .get_sset_count = lio_vf_get_sset_count,
.get_coalesce = lio_get_intr_coalesce,
.set_coalesce = lio_set_intr_coalesce,
.get_priv_flags = lio_get_priv_flags,
@@ -2222,5 +2521,11 @@ static const struct ethtool_ops lio_ethtool_ops = {
void liquidio_set_ethtool_ops(struct net_device *netdev)
{
- netdev->ethtool_ops = &lio_ethtool_ops;
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ if (OCTEON_CN23XX_VF(oct))
+ netdev->ethtool_ops = &lio_vf_ethtool_ops;
+ else
+ netdev->ethtool_ops = &lio_ethtool_ops;
}
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index afc6f9dc8119..39a9665c9d00 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -1,28 +1,22 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-#include <linux/version.h>
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/firmware.h>
-#include <linux/ptp_clock_kernel.h>
#include <net/vxlan.h>
#include <linux/kthread.h>
#include "liquidio_common.h"
@@ -46,6 +40,7 @@ MODULE_VERSION(LIQUIDIO_VERSION);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210SV_NAME LIO_FW_NAME_SUFFIX);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210NV_NAME LIO_FW_NAME_SUFFIX);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_410NV_NAME LIO_FW_NAME_SUFFIX);
+MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_23XX_NAME LIO_FW_NAME_SUFFIX);
static int ddr_timeout = 10000;
module_param(ddr_timeout, int, 0644);
@@ -54,9 +49,6 @@ MODULE_PARM_DESC(ddr_timeout,
#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
-#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
- (octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
-
static int debug = -1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
@@ -65,10 +57,6 @@ static char fw_type[LIO_MAX_FW_TYPE_LEN];
module_param_string(fw_type, fw_type, sizeof(fw_type), 0000);
MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded. Default \"nic\"");
-static int conf_type;
-module_param(conf_type, int, 0);
-MODULE_PARM_DESC(conf_type, "select octeon configuration 0 default 1 ovs");
-
static int ptp_enable = 1;
/* Bit mask values for lio->ifstate */
@@ -180,6 +168,10 @@ struct octeon_device_priv {
unsigned long napi_mask;
};
+#ifdef CONFIG_PCI_IOV
+static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs);
+#endif
+
static int octeon_device_init(struct octeon_device *);
static int liquidio_stop(struct net_device *netdev);
static void liquidio_remove(struct pci_dev *pdev);
@@ -197,9 +189,8 @@ static void octeon_droq_bh(unsigned long pdev)
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
- /* for (q_no = 0; q_no < oct->num_oqs; q_no++) { */
for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) {
- if (!(oct->io_qmask.oq & (1ULL << q_no)))
+ if (!(oct->io_qmask.oq & BIT_ULL(q_no)))
continue;
reschedule |= octeon_droq_process_packets(oct, oct->droq[q_no],
MAX_PACKET_BUDGET);
@@ -234,7 +225,7 @@ static int lio_wait_for_oq_pkts(struct octeon_device *oct)
pending_pkts = 0;
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
- if (!(oct->io_qmask.oq & (1ULL << i)))
+ if (!(oct->io_qmask.oq & BIT_ULL(i)))
continue;
pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]);
}
@@ -316,7 +307,7 @@ static inline void pcierror_quiesce_device(struct octeon_device *oct)
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
struct octeon_instr_queue *iq;
- if (!(oct->io_qmask.iq & (1ULL << i)))
+ if (!(oct->io_qmask.iq & BIT_ULL(i)))
continue;
iq = oct->instr_queue[i];
@@ -382,7 +373,6 @@ static void stop_pci_io(struct octeon_device *oct)
dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
lio_get_state_string(&oct->status));
- /* cn63xx_cleanup_aer_uncorrect_error_status(oct->pci_dev); */
/* making it a common function for all OCTEON models */
cleanup_aer_uncorrect_error_status(oct->pci_dev);
}
@@ -518,6 +508,9 @@ static struct pci_driver liquidio_pci_driver = {
.suspend = liquidio_suspend,
.resume = liquidio_resume,
#endif
+#ifdef CONFIG_PCI_IOV
+ .sriov_configure = liquidio_enable_sriov,
+#endif
};
/**
@@ -763,6 +756,7 @@ static void delete_glists(struct lio *lio)
}
kfree((void *)lio->glist);
+ kfree((void *)lio->glist_lock);
}
/**
@@ -933,7 +927,6 @@ static inline void update_link_status(struct net_device *netdev,
if (lio->linfo.link.s.link_up) {
netif_carrier_on(netdev);
- /* start_txq(netdev); */
txqs_wake(netdev);
} else {
netif_carrier_off(netdev);
@@ -1011,7 +1004,7 @@ static void liquidio_schedule_droq_pkt_handlers(struct octeon_device *oct)
if (oct->int_status & OCT_DEV_INTR_PKT_DATA) {
for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct);
oq_no++) {
- if (!(oct->droq_intr & (1ULL << oq_no)))
+ if (!(oct->droq_intr & BIT_ULL(oq_no)))
continue;
droq = oct->droq[oq_no];
@@ -1322,6 +1315,7 @@ liquidio_probe(struct pci_dev *pdev,
complete(&first_stage);
if (octeon_device_init(oct_dev)) {
+ complete(&hs->init);
liquidio_remove(pdev);
return -ENOMEM;
}
@@ -1346,7 +1340,15 @@ liquidio_probe(struct pci_dev *pdev,
oct_dev->watchdog_task = kthread_create(
liquidio_watchdog, oct_dev,
"liowd/%02hhx:%02hhx.%hhx", bus, device, function);
- wake_up_process(oct_dev->watchdog_task);
+ if (!IS_ERR(oct_dev->watchdog_task)) {
+ wake_up_process(oct_dev->watchdog_task);
+ } else {
+ oct_dev->watchdog_task = NULL;
+ dev_err(&oct_dev->pci_dev->dev,
+ "failed to create kernel_thread\n");
+ liquidio_remove(pdev);
+ return -1;
+ }
}
}
@@ -1410,6 +1412,8 @@ static void octeon_destroy_resources(struct octeon_device *oct)
if (lio_wait_for_oq_pkts(oct))
dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");
+ /* fallthrough */
+ case OCT_DEV_INTR_SET_DONE:
/* Disable interrupts */
oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
@@ -1436,12 +1440,20 @@ static void octeon_destroy_resources(struct octeon_device *oct)
pci_disable_msi(oct->pci_dev);
}
+ /* fallthrough */
+ case OCT_DEV_MSIX_ALLOC_VECTOR_DONE:
if (OCTEON_CN23XX_PF(oct))
octeon_free_ioq_vector(oct);
+
+ /* fallthrough */
+ case OCT_DEV_MBOX_SETUP_DONE:
+ if (OCTEON_CN23XX_PF(oct))
+ oct->fn_list.free_mbox(oct);
+
/* fallthrough */
case OCT_DEV_IN_RESET:
case OCT_DEV_DROQ_INIT_DONE:
- /*atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE);*/
+ /* Wait for any pending operations */
mdelay(100);
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
if (!(oct->io_qmask.oq & BIT_ULL(i)))
@@ -1472,6 +1484,10 @@ static void octeon_destroy_resources(struct octeon_device *oct)
continue;
octeon_delete_instr_queue(oct, i);
}
+#ifdef CONFIG_PCI_IOV
+ if (oct->sriov_info.sriov_enabled)
+ pci_disable_sriov(oct->pci_dev);
+#endif
/* fallthrough */
case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
octeon_free_sc_buffer_pool(oct);
@@ -1491,10 +1507,13 @@ static void octeon_destroy_resources(struct octeon_device *oct)
octeon_unmap_pci_barx(oct, 1);
/* fallthrough */
- case OCT_DEV_BEGIN_STATE:
+ case OCT_DEV_PCI_ENABLE_DONE:
+ pci_clear_master(oct->pci_dev);
/* Disable the device, releasing the PCI INT */
pci_disable_device(oct->pci_dev);
+ /* fallthrough */
+ case OCT_DEV_BEGIN_STATE:
/* Nothing to be done here either */
break;
} /* end switch (oct->status) */
@@ -1764,6 +1783,7 @@ static int octeon_pci_os_setup(struct octeon_device *oct)
if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
+ pci_disable_device(oct->pci_dev);
return 1;
}
@@ -2426,7 +2446,6 @@ static int liquidio_napi_poll(struct napi_struct *napi, int budget)
* Return back if tx_done is false.
*/
update_txq_status(oct, iq_no);
- /*tx_done = (iq->flush_index == iq->octeon_read_index);*/
} else {
dev_err(&oct->pci_dev->dev, "%s: iq (%d) num invalid\n",
__func__, iq_no);
@@ -2868,17 +2887,6 @@ static int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
struct octnic_ctrl_pkt nctrl;
int ret = 0;
- /* Limit the MTU to make sure the ethernet packets are between 68 bytes
- * and 16000 bytes
- */
- if ((new_mtu < LIO_MIN_MTU_SIZE) ||
- (new_mtu > LIO_MAX_MTU_SIZE)) {
- dev_err(&oct->pci_dev->dev, "Invalid MTU: %d\n", new_mtu);
- dev_err(&oct->pci_dev->dev, "Valid range %d and %d\n",
- LIO_MIN_MTU_SIZE, LIO_MAX_MTU_SIZE);
- return -EINVAL;
- }
-
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
nctrl.ncmd.u64 = 0;
@@ -3567,7 +3575,152 @@ static void liquidio_del_vxlan_port(struct net_device *netdev,
OCTNET_CMD_VXLAN_PORT_DEL);
}
-static struct net_device_ops lionetdevops = {
+static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
+ u8 *mac, bool is_admin_assigned)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ if (vfidx < 0 || vfidx >= oct->sriov_info.max_vfs)
+ return -EINVAL;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
+ /* vfidx is 0 based, but vf_num (param1) is 1 based */
+ nctrl.ncmd.s.param1 = vfidx + 1;
+ nctrl.ncmd.s.param2 = (is_admin_assigned ? 1 : 0);
+ nctrl.ncmd.s.more = 1;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.cb_fn = 0;
+ nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+ nctrl.udd[0] = 0;
+ /* The MAC Address is presented in network byte order. */
+ ether_addr_copy((u8 *)&nctrl.udd[0] + 2, mac);
+
+ oct->sriov_info.vf_macaddr[vfidx] = nctrl.udd[0];
+
+ octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+ return 0;
+}
+
+static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ int retval;
+
+ retval = __liquidio_set_vf_mac(netdev, vfidx, mac, true);
+ if (!retval)
+ cn23xx_tell_vf_its_macaddr_changed(oct, vfidx, mac);
+
+ return retval;
+}
+
+static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx,
+ u16 vlan, u8 qos, __be16 vlan_proto)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ u16 vlantci;
+
+ if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+ return -EINVAL;
+
+ if (vlan_proto != htons(ETH_P_8021Q))
+ return -EPROTONOSUPPORT;
+
+ if (vlan >= VLAN_N_VID || qos > 7)
+ return -EINVAL;
+
+ if (vlan)
+ vlantci = vlan | (u16)qos << VLAN_PRIO_SHIFT;
+ else
+ vlantci = 0;
+
+ if (oct->sriov_info.vf_vlantci[vfidx] == vlantci)
+ return 0;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ if (vlan)
+ nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
+ else
+ nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
+
+ nctrl.ncmd.s.param1 = vlantci;
+ nctrl.ncmd.s.param2 =
+ vfidx + 1; /* vfidx is 0 based, but vf_num (param2) is 1 based */
+ nctrl.ncmd.s.more = 0;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.cb_fn = 0;
+ nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+ octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+ oct->sriov_info.vf_vlantci[vfidx] = vlantci;
+
+ return 0;
+}
+
+static int liquidio_get_vf_config(struct net_device *netdev, int vfidx,
+ struct ifla_vf_info *ivi)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ u8 *macaddr;
+
+ if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+ return -EINVAL;
+
+ ivi->vf = vfidx;
+ macaddr = 2 + (u8 *)&oct->sriov_info.vf_macaddr[vfidx];
+ ether_addr_copy(&ivi->mac[0], macaddr);
+ ivi->vlan = oct->sriov_info.vf_vlantci[vfidx] & VLAN_VID_MASK;
+ ivi->qos = oct->sriov_info.vf_vlantci[vfidx] >> VLAN_PRIO_SHIFT;
+ ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx];
+ return 0;
+}
+
+static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
+ int linkstate)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+
+ if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+ return -EINVAL;
+
+ if (oct->sriov_info.vf_linkstate[vfidx] == linkstate)
+ return 0;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+ nctrl.ncmd.s.cmd = OCTNET_CMD_SET_VF_LINKSTATE;
+ nctrl.ncmd.s.param1 =
+ vfidx + 1; /* vfidx is 0 based, but vf_num (param1) is 1 based */
+ nctrl.ncmd.s.param2 = linkstate;
+ nctrl.ncmd.s.more = 0;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.cb_fn = 0;
+ nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+ octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+ oct->sriov_info.vf_linkstate[vfidx] = linkstate;
+
+ return 0;
+}
+
+static const struct net_device_ops lionetdevops = {
.ndo_open = liquidio_open,
.ndo_stop = liquidio_stop,
.ndo_start_xmit = liquidio_xmit,
@@ -3584,6 +3737,11 @@ static struct net_device_ops lionetdevops = {
.ndo_set_features = liquidio_set_features,
.ndo_udp_tunnel_add = liquidio_add_vxlan_port,
.ndo_udp_tunnel_del = liquidio_del_vxlan_port,
+ .ndo_set_vf_mac = liquidio_set_vf_mac,
+ .ndo_set_vf_vlan = liquidio_set_vf_vlan,
+ .ndo_get_vf_config = liquidio_get_vf_config,
+ .ndo_set_vf_link_state = liquidio_set_vf_link_state,
+ .ndo_select_queue = select_q
};
/** \brief Entry point for the liquidio module
@@ -3595,7 +3753,7 @@ static int __init liquidio_init(void)
init_completion(&first_stage);
- octeon_init_device_list(conf_type);
+ octeon_init_device_list(OCTEON_CONFIG_TYPE_DEFAULT);
if (liquidio_init_pci())
return -EINVAL;
@@ -3816,9 +3974,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev);
- if (num_iqueues > 1)
- lionetdevops.ndo_select_queue = select_q;
-
/* Associate the routines that will handle different
* netdev tasks.
*/
@@ -3891,6 +4046,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
netdev->hw_features = netdev->hw_features &
~NETIF_F_HW_VLAN_CTAG_RX;
+ /* MTU range: 68 - 16000 */
+ netdev->min_mtu = LIO_MIN_MTU_SIZE;
+ netdev->max_mtu = LIO_MAX_MTU_SIZE;
+
/* Point to the properties for octeon device to which this
* interface belongs.
*/
@@ -3902,6 +4061,19 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
"if%d gmx: %d hw_addr: 0x%llx\n", i,
lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
+ for (j = 0; j < octeon_dev->sriov_info.max_vfs; j++) {
+ u8 vfmac[ETH_ALEN];
+
+ random_ether_addr(&vfmac[0]);
+ if (__liquidio_set_vf_mac(netdev, j,
+ &vfmac[0], false)) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "Error setting VF%d MAC address\n",
+ j);
+ goto setup_nic_dev_fail;
+ }
+ }
+
/* 64-bit swap required on LE machines */
octeon_swap_8B_data(&lio->linfo.hw_addr, 1);
for (j = 0; j < 6; j++)
@@ -3997,6 +4169,101 @@ setup_nic_wait_intr:
return -ENODEV;
}
+#ifdef CONFIG_PCI_IOV
+static int octeon_enable_sriov(struct octeon_device *oct)
+{
+ unsigned int num_vfs_alloced = oct->sriov_info.num_vfs_alloced;
+ struct pci_dev *vfdev;
+ int err;
+ u32 u;
+
+ if (OCTEON_CN23XX_PF(oct) && num_vfs_alloced) {
+ err = pci_enable_sriov(oct->pci_dev,
+ oct->sriov_info.num_vfs_alloced);
+ if (err) {
+ dev_err(&oct->pci_dev->dev,
+ "OCTEON: Failed to enable PCI sriov: %d\n",
+ err);
+ oct->sriov_info.num_vfs_alloced = 0;
+ return err;
+ }
+ oct->sriov_info.sriov_enabled = 1;
+
+ /* init lookup table that maps DPI ring number to VF pci_dev
+ * struct pointer
+ */
+ u = 0;
+ vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ OCTEON_CN23XX_VF_VID, NULL);
+ while (vfdev) {
+ if (vfdev->is_virtfn &&
+ (vfdev->physfn == oct->pci_dev)) {
+ oct->sriov_info.dpiring_to_vfpcidev_lut[u] =
+ vfdev;
+ u += oct->sriov_info.rings_per_vf;
+ }
+ vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ OCTEON_CN23XX_VF_VID, vfdev);
+ }
+ }
+
+ return num_vfs_alloced;
+}
+
+static int lio_pci_sriov_disable(struct octeon_device *oct)
+{
+ int u;
+
+ if (pci_vfs_assigned(oct->pci_dev)) {
+ dev_err(&oct->pci_dev->dev, "VFs are still assigned to VMs.\n");
+ return -EPERM;
+ }
+
+ pci_disable_sriov(oct->pci_dev);
+
+ u = 0;
+ while (u < MAX_POSSIBLE_VFS) {
+ oct->sriov_info.dpiring_to_vfpcidev_lut[u] = NULL;
+ u += oct->sriov_info.rings_per_vf;
+ }
+
+ oct->sriov_info.num_vfs_alloced = 0;
+ dev_info(&oct->pci_dev->dev, "oct->pf_num:%d disabled VFs\n",
+ oct->pf_num);
+
+ return 0;
+}
+
+static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs)
+{
+ struct octeon_device *oct = pci_get_drvdata(dev);
+ int ret = 0;
+
+ if ((num_vfs == oct->sriov_info.num_vfs_alloced) &&
+ (oct->sriov_info.sriov_enabled)) {
+ dev_info(&oct->pci_dev->dev, "oct->pf_num:%d already enabled num_vfs:%d\n",
+ oct->pf_num, num_vfs);
+ return 0;
+ }
+
+ if (!num_vfs) {
+ ret = lio_pci_sriov_disable(oct);
+ } else if (num_vfs > oct->sriov_info.max_vfs) {
+ dev_err(&oct->pci_dev->dev,
+ "OCTEON: Max allowed VFs:%d user requested:%d",
+ oct->sriov_info.max_vfs, num_vfs);
+ ret = -EPERM;
+ } else {
+ oct->sriov_info.num_vfs_alloced = num_vfs;
+ ret = octeon_enable_sriov(oct);
+ dev_info(&oct->pci_dev->dev, "oct->pf_num:%d num_vfs:%d\n",
+ oct->pf_num, num_vfs);
+ }
+
+ return ret;
+}
+#endif
+
/**
* \brief initialize the NIC
* @param oct octeon device
@@ -4102,6 +4369,52 @@ static void nic_starter(struct work_struct *work)
complete(&handshake[oct->octeon_id].started);
}
+static int
+octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf)
+{
+ struct octeon_device *oct = (struct octeon_device *)buf;
+ struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
+ int i, notice, vf_idx;
+ u64 *data, vf_num;
+
+ notice = recv_pkt->rh.r.ossp;
+ data = (u64 *)get_rbd(recv_pkt->buffer_ptr[0]);
+
+ /* the first 64-bit word of data is the vf_num */
+ vf_num = data[0];
+ octeon_swap_8B_data(&vf_num, 1);
+ vf_idx = (int)vf_num - 1;
+
+ if (notice == VF_DRV_LOADED) {
+ if (!(oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx))) {
+ oct->sriov_info.vf_drv_loaded_mask |= BIT_ULL(vf_idx);
+ dev_info(&oct->pci_dev->dev,
+ "driver for VF%d was loaded\n", vf_idx);
+ try_module_get(THIS_MODULE);
+ }
+ } else if (notice == VF_DRV_REMOVED) {
+ if (oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx)) {
+ oct->sriov_info.vf_drv_loaded_mask &= ~BIT_ULL(vf_idx);
+ dev_info(&oct->pci_dev->dev,
+ "driver for VF%d was removed\n", vf_idx);
+ module_put(THIS_MODULE);
+ }
+ } else if (notice == VF_DRV_MACADDR_CHANGED) {
+ u8 *b = (u8 *)&data[1];
+
+ oct->sriov_info.vf_macaddr[vf_idx] = data[1];
+ dev_info(&oct->pci_dev->dev,
+ "VF driver changed VF%d's MAC address to %pM\n",
+ vf_idx, b + 2);
+ }
+
+ for (i = 0; i < recv_pkt->buffer_count; i++)
+ recv_buffer_free(recv_pkt->buffer_ptr[i]);
+ octeon_free_recv_info(recv_info);
+
+ return 0;
+}
+
/**
* \brief Device initialization for each Octeon device that is probed
* @param octeon_dev octeon device
@@ -4121,6 +4434,8 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
if (octeon_pci_os_setup(octeon_dev))
return 1;
+ atomic_set(&octeon_dev->status, OCT_DEV_PCI_ENABLE_DONE);
+
/* Identify the Octeon type and map the BAR address space. */
if (octeon_chip_specific_setup(octeon_dev)) {
dev_err(&octeon_dev->pci_dev->dev, "Chip specific setup failed\n");
@@ -4160,6 +4475,9 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
octeon_core_drv_init,
octeon_dev);
+ octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC,
+ OPCODE_NIC_VF_DRV_NOTICE,
+ octeon_recv_vf_drv_notice, octeon_dev);
INIT_DELAYED_WORK(&octeon_dev->nic_poll_work.work, nic_starter);
octeon_dev->nic_poll_work.ctxptr = (void *)octeon_dev;
schedule_delayed_work(&octeon_dev->nic_poll_work.work,
@@ -4167,7 +4485,10 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
atomic_set(&octeon_dev->status, OCT_DEV_DISPATCH_INIT_DONE);
- octeon_set_io_queues_off(octeon_dev);
+ if (octeon_set_io_queues_off(octeon_dev)) {
+ dev_err(&octeon_dev->pci_dev->dev, "setting io queues off failed\n");
+ return 1;
+ }
if (OCTEON_CN23XX_PF(octeon_dev)) {
ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
@@ -4189,9 +4510,6 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
if (octeon_setup_instr_queues(octeon_dev)) {
dev_err(&octeon_dev->pci_dev->dev,
"instruction queue initialization failed\n");
- /* On error, release any previously allocated queues */
- for (j = 0; j < octeon_dev->num_iqs; j++)
- octeon_delete_instr_queue(octeon_dev, j);
return 1;
}
atomic_set(&octeon_dev->status, OCT_DEV_INSTR_QUEUE_INIT_DONE);
@@ -4207,19 +4525,23 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
if (octeon_setup_output_queues(octeon_dev)) {
dev_err(&octeon_dev->pci_dev->dev, "Output queue initialization failed\n");
- /* Release any previously allocated queues */
- for (j = 0; j < octeon_dev->num_oqs; j++)
- octeon_delete_droq(octeon_dev, j);
return 1;
}
atomic_set(&octeon_dev->status, OCT_DEV_DROQ_INIT_DONE);
if (OCTEON_CN23XX_PF(octeon_dev)) {
+ if (octeon_dev->fn_list.setup_mbox(octeon_dev)) {
+ dev_err(&octeon_dev->pci_dev->dev, "OCTEON: Mailbox setup failed\n");
+ return 1;
+ }
+ atomic_set(&octeon_dev->status, OCT_DEV_MBOX_SETUP_DONE);
+
if (octeon_allocate_ioq_vector(octeon_dev)) {
dev_err(&octeon_dev->pci_dev->dev, "OCTEON: ioq vector allocation failed\n");
return 1;
}
+ atomic_set(&octeon_dev->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE);
} else {
/* The input and output queue registers were setup earlier (the
@@ -4247,6 +4569,8 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
/* Enable Octeon device interrupts */
octeon_dev->fn_list.enable_interrupt(octeon_dev, OCTEON_ALL_INTR);
+ atomic_set(&octeon_dev->status, OCT_DEV_INTR_SET_DONE);
+
/* Enable the input and output queues for this Octeon device */
ret = octeon_dev->fn_list.enable_io_queues(octeon_dev);
if (ret) {
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
new file mode 100644
index 000000000000..70d96c10c673
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -0,0 +1,3251 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <net/vxlan.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "octeon_nic.h"
+#include "octeon_main.h"
+#include "octeon_network.h"
+#include "cn23xx_vf_device.h"
+
+MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
+MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Virtual Function Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(LIQUIDIO_VERSION);
+
+static int debug = -1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
+
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
+/* Bit mask values for lio->ifstate */
+#define LIO_IFSTATE_DROQ_OPS 0x01
+#define LIO_IFSTATE_REGISTERED 0x02
+#define LIO_IFSTATE_RUNNING 0x04
+#define LIO_IFSTATE_RX_TIMESTAMP_ENABLED 0x08
+
+struct liquidio_if_cfg_context {
+ int octeon_id;
+
+ wait_queue_head_t wc;
+
+ int cond;
+};
+
+struct liquidio_if_cfg_resp {
+ u64 rh;
+ struct liquidio_if_cfg_info cfg_info;
+ u64 status;
+};
+
+struct liquidio_rx_ctl_context {
+ int octeon_id;
+
+ wait_queue_head_t wc;
+
+ int cond;
+};
+
+struct oct_timestamp_resp {
+ u64 rh;
+ u64 timestamp;
+ u64 status;
+};
+
+union tx_info {
+ u64 u64;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ u16 gso_size;
+ u16 gso_segs;
+ u32 reserved;
+#else
+ u32 reserved;
+ u16 gso_segs;
+ u16 gso_size;
+#endif
+ } s;
+};
+
+#define OCTNIC_MAX_SG (MAX_SKB_FRAGS)
+
+#define OCTNIC_GSO_MAX_HEADER_SIZE 128
+#define OCTNIC_GSO_MAX_SIZE \
+ (CN23XX_DEFAULT_INPUT_JABBER - OCTNIC_GSO_MAX_HEADER_SIZE)
+
+struct octnic_gather {
+ /* List manipulation. Next and prev pointers. */
+ struct list_head list;
+
+ /* Size of the gather component at sg in bytes. */
+ int sg_size;
+
+ /* Number of bytes that sg was adjusted to make it 8B-aligned. */
+ int adjust;
+
+ /* Gather component that can accommodate max sized fragment list
+ * received from the IP layer.
+ */
+ struct octeon_sg_entry *sg;
+};
+
+struct octeon_device_priv {
+ /* Tasklet structures for this device. */
+ struct tasklet_struct droq_tasklet;
+ unsigned long napi_mask;
+};
+
+static int
+liquidio_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void liquidio_vf_remove(struct pci_dev *pdev);
+static int octeon_device_init(struct octeon_device *oct);
+static int liquidio_stop(struct net_device *netdev);
+
+static int lio_wait_for_oq_pkts(struct octeon_device *oct)
+{
+ struct octeon_device_priv *oct_priv =
+ (struct octeon_device_priv *)oct->priv;
+ int retry = MAX_VF_IP_OP_PENDING_PKT_COUNT;
+ int pkt_cnt = 0, pending_pkts;
+ int i;
+
+ do {
+ pending_pkts = 0;
+
+ for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
+ if (!(oct->io_qmask.oq & BIT_ULL(i)))
+ continue;
+ pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]);
+ }
+ if (pkt_cnt > 0) {
+ pending_pkts += pkt_cnt;
+ tasklet_schedule(&oct_priv->droq_tasklet);
+ }
+ pkt_cnt = 0;
+ schedule_timeout_uninterruptible(1);
+
+ } while (retry-- && pending_pkts);
+
+ return pkt_cnt;
+}
+
+/**
+ * \brief wait for all pending requests to complete
+ * @param oct Pointer to Octeon device
+ *
+ * Called during shutdown sequence
+ */
+static int wait_for_pending_requests(struct octeon_device *oct)
+{
+ int i, pcount = 0;
+
+ for (i = 0; i < MAX_VF_IP_OP_PENDING_PKT_COUNT; i++) {
+ pcount = atomic_read(
+ &oct->response_list[OCTEON_ORDERED_SC_LIST]
+ .pending_req_count);
+ if (pcount)
+ schedule_timeout_uninterruptible(HZ / 10);
+ else
+ break;
+ }
+
+ if (pcount)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * \brief Cause device to go quiet so it can be safely removed/reset/etc
+ * @param oct Pointer to Octeon device
+ */
+static void pcierror_quiesce_device(struct octeon_device *oct)
+{
+ int i;
+
+ /* Disable the input and output queues now. No more packets will
+ * arrive from Octeon, but we should wait for all packet processing
+ * to finish.
+ */
+
+ /* To allow for in-flight requests */
+ schedule_timeout_uninterruptible(100);
+
+ if (wait_for_pending_requests(oct))
+ dev_err(&oct->pci_dev->dev, "There were pending requests\n");
+
+ /* Force all requests waiting to be fetched by OCTEON to complete. */
+ for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
+ struct octeon_instr_queue *iq;
+
+ if (!(oct->io_qmask.iq & BIT_ULL(i)))
+ continue;
+ iq = oct->instr_queue[i];
+
+ if (atomic_read(&iq->instr_pending)) {
+ spin_lock_bh(&iq->lock);
+ iq->fill_cnt = 0;
+ iq->octeon_read_index = iq->host_write_index;
+ iq->stats.instr_processed +=
+ atomic_read(&iq->instr_pending);
+ lio_process_iq_request_list(oct, iq, 0);
+ spin_unlock_bh(&iq->lock);
+ }
+ }
+
+ /* Force all pending ordered list requests to time out. */
+ lio_process_ordered_list(oct, 1);
+
+ /* We do not need to wait for output queue packets to be processed. */
+}
+
+/**
+ * \brief Cleanup PCI AER uncorrectable error status
+ * @param dev Pointer to PCI device
+ */
+static void cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+{
+ u32 status, mask;
+ int pos = 0x100;
+
+ pr_info("%s :\n", __func__);
+
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+ if (dev->error_state == pci_channel_io_normal)
+ status &= ~mask; /* Clear corresponding nonfatal bits */
+ else
+ status &= mask; /* Clear corresponding fatal bits */
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+}
+
+/**
+ * \brief Stop all PCI IO to a given device
+ * @param dev Pointer to Octeon device
+ */
+static void stop_pci_io(struct octeon_device *oct)
+{
+ struct msix_entry *msix_entries;
+ int i;
+
+ /* No more instructions will be forwarded. */
+ atomic_set(&oct->status, OCT_DEV_IN_RESET);
+
+ for (i = 0; i < oct->ifcount; i++)
+ netif_device_detach(oct->props[i].netdev);
+
+ /* Disable interrupts */
+ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+ pcierror_quiesce_device(oct);
+ if (oct->msix_on) {
+ msix_entries = (struct msix_entry *)oct->msix_entries;
+ for (i = 0; i < oct->num_msix_irqs; i++) {
+ /* clear the affinity_cpumask */
+ irq_set_affinity_hint(msix_entries[i].vector,
+ NULL);
+ free_irq(msix_entries[i].vector,
+ &oct->ioq_vector[i]);
+ }
+ pci_disable_msix(oct->pci_dev);
+ kfree(oct->msix_entries);
+ oct->msix_entries = NULL;
+ octeon_free_ioq_vector(oct);
+ }
+ dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
+ lio_get_state_string(&oct->status));
+
+ /* making it a common function for all OCTEON models */
+ cleanup_aer_uncorrect_error_status(oct->pci_dev);
+
+ pci_disable_device(oct->pci_dev);
+}
+
+/**
+ * \brief called when PCI error is detected
+ * @param pdev Pointer to PCI device
+ * @param state The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t liquidio_pcie_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct octeon_device *oct = pci_get_drvdata(pdev);
+
+ /* Non-correctable Non-fatal errors */
+ if (state == pci_channel_io_normal) {
+ dev_err(&oct->pci_dev->dev, "Non-correctable non-fatal error reported:\n");
+ cleanup_aer_uncorrect_error_status(oct->pci_dev);
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ }
+
+ /* Non-correctable Fatal errors */
+ dev_err(&oct->pci_dev->dev, "Non-correctable FATAL reported by PCI AER driver\n");
+ stop_pci_io(oct);
+
+ return PCI_ERS_RESULT_DISCONNECT;
+}
+
+/* For PCI-E Advanced Error Recovery (AER) Interface */
+static const struct pci_error_handlers liquidio_vf_err_handler = {
+ .error_detected = liquidio_pcie_error_detected,
+};
+
+static const struct pci_device_id liquidio_vf_pci_tbl[] = {
+ {
+ PCI_VENDOR_ID_CAVIUM, OCTEON_CN23XX_VF_VID,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0
+ }
+};
+MODULE_DEVICE_TABLE(pci, liquidio_vf_pci_tbl);
+
+static struct pci_driver liquidio_vf_pci_driver = {
+ .name = "LiquidIO_VF",
+ .id_table = liquidio_vf_pci_tbl,
+ .probe = liquidio_vf_probe,
+ .remove = liquidio_vf_remove,
+ .err_handler = &liquidio_vf_err_handler, /* For AER */
+};
+
+/**
+ * \brief check interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to check
+ */
+static int ifstate_check(struct lio *lio, int state_flag)
+{
+ return atomic_read(&lio->ifstate) & state_flag;
+}
+
+/**
+ * \brief set interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to set
+ */
+static void ifstate_set(struct lio *lio, int state_flag)
+{
+ atomic_set(&lio->ifstate, (atomic_read(&lio->ifstate) | state_flag));
+}
+
+/**
+ * \brief clear interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to clear
+ */
+static void ifstate_reset(struct lio *lio, int state_flag)
+{
+ atomic_set(&lio->ifstate, (atomic_read(&lio->ifstate) & ~(state_flag)));
+}
+
+/**
+ * \brief Stop Tx queues
+ * @param netdev network device
+ */
+static void txqs_stop(struct net_device *netdev)
+{
+ if (netif_is_multiqueue(netdev)) {
+ int i;
+
+ for (i = 0; i < netdev->num_tx_queues; i++)
+ netif_stop_subqueue(netdev, i);
+ } else {
+ netif_stop_queue(netdev);
+ }
+}
+
+/**
+ * \brief Start Tx queues
+ * @param netdev network device
+ */
+static void txqs_start(struct net_device *netdev)
+{
+ if (netif_is_multiqueue(netdev)) {
+ int i;
+
+ for (i = 0; i < netdev->num_tx_queues; i++)
+ netif_start_subqueue(netdev, i);
+ } else {
+ netif_start_queue(netdev);
+ }
+}
+
+/**
+ * \brief Wake Tx queues
+ * @param netdev network device
+ */
+static void txqs_wake(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+
+ if (netif_is_multiqueue(netdev)) {
+ int i;
+
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ int qno = lio->linfo.txpciq[i % (lio->linfo.num_txpciq)]
+ .s.q_no;
+ if (__netif_subqueue_stopped(netdev, i)) {
+ INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, qno,
+ tx_restart, 1);
+ netif_wake_subqueue(netdev, i);
+ }
+ }
+ } else {
+ INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, lio->txq,
+ tx_restart, 1);
+ netif_wake_queue(netdev);
+ }
+}
+
+/**
+ * \brief Start Tx queue
+ * @param netdev network device
+ */
+static void start_txq(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+
+ if (lio->linfo.link.s.link_up) {
+ txqs_start(netdev);
+ return;
+ }
+}
+
+/**
+ * \brief Wake a queue
+ * @param netdev network device
+ * @param q which queue to wake
+ */
+static void wake_q(struct net_device *netdev, int q)
+{
+ if (netif_is_multiqueue(netdev))
+ netif_wake_subqueue(netdev, q);
+ else
+ netif_wake_queue(netdev);
+}
+
+/**
+ * \brief Stop a queue
+ * @param netdev network device
+ * @param q which queue to stop
+ */
+static void stop_q(struct net_device *netdev, int q)
+{
+ if (netif_is_multiqueue(netdev))
+ netif_stop_subqueue(netdev, q);
+ else
+ netif_stop_queue(netdev);
+}
+
+/**
+ * Remove the node at the head of the list. The list would be empty at
+ * the end of this call if there are no more nodes in the list.
+ */
+static struct list_head *list_delete_head(struct list_head *root)
+{
+ struct list_head *node;
+
+ if ((root->prev == root) && (root->next == root))
+ node = NULL;
+ else
+ node = root->next;
+
+ if (node)
+ list_del(node);
+
+ return node;
+}
+
+/**
+ * \brief Delete gather lists
+ * @param lio per-network private data
+ */
+static void delete_glists(struct lio *lio)
+{
+ struct octnic_gather *g;
+ int i;
+
+ if (!lio->glist)
+ return;
+
+ for (i = 0; i < lio->linfo.num_txpciq; i++) {
+ do {
+ g = (struct octnic_gather *)
+ list_delete_head(&lio->glist[i]);
+ if (g) {
+ if (g->sg)
+ kfree((void *)((unsigned long)g->sg -
+ g->adjust));
+ kfree(g);
+ }
+ } while (g);
+ }
+
+ kfree(lio->glist);
+ kfree(lio->glist_lock);
+}
+
+/**
+ * \brief Setup gather lists
+ * @param lio per-network private data
+ */
+static int setup_glists(struct lio *lio, int num_iqs)
+{
+ struct octnic_gather *g;
+ int i, j;
+
+ lio->glist_lock =
+ kzalloc(sizeof(*lio->glist_lock) * num_iqs, GFP_KERNEL);
+ if (!lio->glist_lock)
+ return 1;
+
+ lio->glist =
+ kzalloc(sizeof(*lio->glist) * num_iqs, GFP_KERNEL);
+ if (!lio->glist) {
+ kfree(lio->glist_lock);
+ return 1;
+ }
+
+ for (i = 0; i < num_iqs; i++) {
+ spin_lock_init(&lio->glist_lock[i]);
+
+ INIT_LIST_HEAD(&lio->glist[i]);
+
+ for (j = 0; j < lio->tx_qsize; j++) {
+ g = kzalloc(sizeof(*g), GFP_KERNEL);
+ if (!g)
+ break;
+
+ g->sg_size = ((ROUNDUP4(OCTNIC_MAX_SG) >> 2) *
+ OCT_SG_ENTRY_SIZE);
+
+ g->sg = kmalloc(g->sg_size + 8, GFP_KERNEL);
+ if (!g->sg) {
+ kfree(g);
+ break;
+ }
+
+ /* The gather component should be aligned on 64-bit
+ * boundary
+ */
+ if (((unsigned long)g->sg) & 7) {
+ g->adjust = 8 - (((unsigned long)g->sg) & 7);
+ g->sg = (struct octeon_sg_entry *)
+ ((unsigned long)g->sg + g->adjust);
+ }
+ list_add_tail(&g->list, &lio->glist[i]);
+ }
+
+ if (j != lio->tx_qsize) {
+ delete_glists(lio);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Print link information
+ * @param netdev network device
+ */
+static void print_link_info(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+
+ if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) {
+ struct oct_link_info *linfo = &lio->linfo;
+
+ if (linfo->link.s.link_up) {
+ netif_info(lio, link, lio->netdev, "%d Mbps %s Duplex UP\n",
+ linfo->link.s.speed,
+ (linfo->link.s.duplex) ? "Full" : "Half");
+ } else {
+ netif_info(lio, link, lio->netdev, "Link Down\n");
+ }
+ }
+}
+
+/**
+ * \brief Routine to notify MTU change
+ * @param work work_struct data structure
+ */
+static void octnet_link_status_change(struct work_struct *work)
+{
+ struct cavium_wk *wk = (struct cavium_wk *)work;
+ struct lio *lio = (struct lio *)wk->ctxptr;
+
+ rtnl_lock();
+ call_netdevice_notifiers(NETDEV_CHANGEMTU, lio->netdev);
+ rtnl_unlock();
+}
+
+/**
+ * \brief Sets up the mtu status change work
+ * @param netdev network device
+ */
+static int setup_link_status_change_wq(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ lio->link_status_wq.wq = alloc_workqueue("link-status",
+ WQ_MEM_RECLAIM, 0);
+ if (!lio->link_status_wq.wq) {
+ dev_err(&oct->pci_dev->dev, "unable to create cavium link status wq\n");
+ return -1;
+ }
+ INIT_DELAYED_WORK(&lio->link_status_wq.wk.work,
+ octnet_link_status_change);
+ lio->link_status_wq.wk.ctxptr = lio;
+
+ return 0;
+}
+
+static void cleanup_link_status_change_wq(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+
+ if (lio->link_status_wq.wq) {
+ cancel_delayed_work_sync(&lio->link_status_wq.wk.work);
+ destroy_workqueue(lio->link_status_wq.wq);
+ }
+}
+
+/**
+ * \brief Update link status
+ * @param netdev network device
+ * @param ls link status structure
+ *
+ * Called on receipt of a link status response from the core application to
+ * update each interface's link status.
+ */
+static void update_link_status(struct net_device *netdev,
+ union oct_link_status *ls)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ if ((lio->intf_open) && (lio->linfo.link.u64 != ls->u64)) {
+ lio->linfo.link.u64 = ls->u64;
+
+ print_link_info(netdev);
+ lio->link_changes++;
+
+ if (lio->linfo.link.s.link_up) {
+ netif_carrier_on(netdev);
+ txqs_wake(netdev);
+ } else {
+ netif_carrier_off(netdev);
+ txqs_stop(netdev);
+ }
+
+ if (lio->linfo.link.s.mtu < netdev->mtu) {
+ dev_warn(&oct->pci_dev->dev,
+ "PF has changed the MTU for gmx port. Reducing the mtu from %d to %d\n",
+ netdev->mtu, lio->linfo.link.s.mtu);
+ lio->mtu = lio->linfo.link.s.mtu;
+ netdev->mtu = lio->linfo.link.s.mtu;
+ queue_delayed_work(lio->link_status_wq.wq,
+ &lio->link_status_wq.wk.work, 0);
+ }
+ }
+}
+
+static void update_txq_status(struct octeon_device *oct, int iq_num)
+{
+ struct octeon_instr_queue *iq = oct->instr_queue[iq_num];
+ struct net_device *netdev;
+ struct lio *lio;
+
+ netdev = oct->props[iq->ifidx].netdev;
+ lio = GET_LIO(netdev);
+ if (netif_is_multiqueue(netdev)) {
+ if (__netif_subqueue_stopped(netdev, iq->q_index) &&
+ lio->linfo.link.s.link_up &&
+ (!octnet_iq_is_full(oct, iq_num))) {
+ netif_wake_subqueue(netdev, iq->q_index);
+ INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq_num,
+ tx_restart, 1);
+ } else {
+ if (!octnet_iq_is_full(oct, lio->txq)) {
+ INCR_INSTRQUEUE_PKT_COUNT(
+ lio->oct_dev, lio->txq, tx_restart, 1);
+ wake_q(netdev, lio->txq);
+ }
+ }
+ }
+}
+
+static
+int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret)
+{
+ struct octeon_device *oct = droq->oct_dev;
+ struct octeon_device_priv *oct_priv =
+ (struct octeon_device_priv *)oct->priv;
+
+ if (droq->ops.poll_mode) {
+ droq->ops.napi_fn(droq);
+ } else {
+ if (ret & MSIX_PO_INT) {
+ dev_err(&oct->pci_dev->dev,
+ "should not come here should not get rx when poll mode = 0 for vf\n");
+ tasklet_schedule(&oct_priv->droq_tasklet);
+ return 1;
+ }
+ /* this will be flushed periodically by check iq db */
+ if (ret & MSIX_PI_INT)
+ return 0;
+ }
+ return 0;
+}
+
+static irqreturn_t
+liquidio_msix_intr_handler(int irq __attribute__((unused)), void *dev)
+{
+ struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev;
+ struct octeon_device *oct = ioq_vector->oct_dev;
+ struct octeon_droq *droq = oct->droq[ioq_vector->droq_index];
+ u64 ret;
+
+ ret = oct->fn_list.msix_interrupt_handler(ioq_vector);
+
+ if ((ret & MSIX_PO_INT) || (ret & MSIX_PI_INT))
+ liquidio_schedule_msix_droq_pkt_handler(droq, ret);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * \brief Setup interrupt for octeon device
+ * @param oct octeon device
+ *
+ * Enable interrupt in Octeon device as given in the PCI interrupt mask.
+ */
+static int octeon_setup_interrupt(struct octeon_device *oct)
+{
+ struct msix_entry *msix_entries;
+ int num_alloc_ioq_vectors;
+ int num_ioq_vectors;
+ int irqret;
+ int i;
+
+ if (oct->msix_on) {
+ oct->num_msix_irqs = oct->sriov_info.rings_per_vf;
+
+ oct->msix_entries = kcalloc(
+ oct->num_msix_irqs, sizeof(struct msix_entry), GFP_KERNEL);
+ if (!oct->msix_entries)
+ return 1;
+
+ msix_entries = (struct msix_entry *)oct->msix_entries;
+
+ for (i = 0; i < oct->num_msix_irqs; i++)
+ msix_entries[i].entry = i;
+ num_alloc_ioq_vectors = pci_enable_msix_range(
+ oct->pci_dev, msix_entries,
+ oct->num_msix_irqs,
+ oct->num_msix_irqs);
+ if (num_alloc_ioq_vectors < 0) {
+ dev_err(&oct->pci_dev->dev, "unable to Allocate MSI-X interrupts\n");
+ kfree(oct->msix_entries);
+ oct->msix_entries = NULL;
+ return 1;
+ }
+ dev_dbg(&oct->pci_dev->dev, "OCTEON: Enough MSI-X interrupts are allocated...\n");
+
+ num_ioq_vectors = oct->num_msix_irqs;
+
+ for (i = 0; i < num_ioq_vectors; i++) {
+ irqret = request_irq(msix_entries[i].vector,
+ liquidio_msix_intr_handler, 0,
+ "octeon", &oct->ioq_vector[i]);
+ if (irqret) {
+ dev_err(&oct->pci_dev->dev,
+ "OCTEON: Request_irq failed for MSIX interrupt Error: %d\n",
+ irqret);
+
+ while (i) {
+ i--;
+ irq_set_affinity_hint(
+ msix_entries[i].vector, NULL);
+ free_irq(msix_entries[i].vector,
+ &oct->ioq_vector[i]);
+ }
+ pci_disable_msix(oct->pci_dev);
+ kfree(oct->msix_entries);
+ oct->msix_entries = NULL;
+ return 1;
+ }
+ oct->ioq_vector[i].vector = msix_entries[i].vector;
+ /* assign the cpu mask for this msix interrupt vector */
+ irq_set_affinity_hint(
+ msix_entries[i].vector,
+ (&oct->ioq_vector[i].affinity_mask));
+ }
+ dev_dbg(&oct->pci_dev->dev,
+ "OCTEON[%d]: MSI-X enabled\n", oct->octeon_id);
+ }
+ return 0;
+}
+
+/**
+ * \brief PCI probe handler
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static int
+liquidio_vf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent __attribute__((unused)))
+{
+ struct octeon_device *oct_dev = NULL;
+
+ oct_dev = octeon_allocate_device(pdev->device,
+ sizeof(struct octeon_device_priv));
+
+ if (!oct_dev) {
+ dev_err(&pdev->dev, "Unable to allocate device\n");
+ return -ENOMEM;
+ }
+ oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED;
+
+ dev_info(&pdev->dev, "Initializing device %x:%x.\n",
+ (u32)pdev->vendor, (u32)pdev->device);
+
+ /* Assign octeon_device for this device to the private data area. */
+ pci_set_drvdata(pdev, oct_dev);
+
+ /* set linux specific device pointer */
+ oct_dev->pci_dev = pdev;
+
+ if (octeon_device_init(oct_dev)) {
+ liquidio_vf_remove(pdev);
+ return -ENOMEM;
+ }
+
+ dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n");
+
+ return 0;
+}
+
+/**
+ * \brief PCI FLR for each Octeon device.
+ * @param oct octeon device
+ */
+static void octeon_pci_flr(struct octeon_device *oct)
+{
+ u16 status;
+
+ pci_save_state(oct->pci_dev);
+
+ pci_cfg_access_lock(oct->pci_dev);
+
+ /* Quiesce the device completely */
+ pci_write_config_word(oct->pci_dev, PCI_COMMAND,
+ PCI_COMMAND_INTX_DISABLE);
+
+ /* Wait for Transaction Pending bit clean */
+ msleep(100);
+ pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA, &status);
+ if (status & PCI_EXP_DEVSTA_TRPND) {
+ dev_info(&oct->pci_dev->dev, "Function reset incomplete after 100ms, sleeping for 5 seconds\n");
+ ssleep(5);
+ pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA,
+ &status);
+ if (status & PCI_EXP_DEVSTA_TRPND)
+ dev_info(&oct->pci_dev->dev, "Function reset still incomplete after 5s, reset anyway\n");
+ }
+ pcie_capability_set_word(oct->pci_dev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_BCR_FLR);
+ mdelay(100);
+
+ pci_cfg_access_unlock(oct->pci_dev);
+
+ pci_restore_state(oct->pci_dev);
+}
+
+/**
+ *\brief Destroy resources associated with octeon device
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static void octeon_destroy_resources(struct octeon_device *oct)
+{
+ struct msix_entry *msix_entries;
+ int i;
+
+ switch (atomic_read(&oct->status)) {
+ case OCT_DEV_RUNNING:
+ case OCT_DEV_CORE_OK:
+ /* No more instructions will be forwarded. */
+ atomic_set(&oct->status, OCT_DEV_IN_RESET);
+
+ oct->app_mode = CVM_DRV_INVALID_APP;
+ dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
+ lio_get_state_string(&oct->status));
+
+ schedule_timeout_uninterruptible(HZ / 10);
+
+ /* fallthrough */
+ case OCT_DEV_HOST_OK:
+ /* fallthrough */
+ case OCT_DEV_IO_QUEUES_DONE:
+ if (wait_for_pending_requests(oct))
+ dev_err(&oct->pci_dev->dev, "There were pending requests\n");
+
+ if (lio_wait_for_instr_fetch(oct))
+ dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");
+
+ /* Disable the input and output queues now. No more packets will
+ * arrive from Octeon, but we should wait for all packet
+ * processing to finish.
+ */
+ oct->fn_list.disable_io_queues(oct);
+
+ if (lio_wait_for_oq_pkts(oct))
+ dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");
+
+ case OCT_DEV_INTR_SET_DONE:
+ /* Disable interrupts */
+ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+ if (oct->msix_on) {
+ msix_entries = (struct msix_entry *)oct->msix_entries;
+ for (i = 0; i < oct->num_msix_irqs; i++) {
+ irq_set_affinity_hint(msix_entries[i].vector,
+ NULL);
+ free_irq(msix_entries[i].vector,
+ &oct->ioq_vector[i]);
+ }
+ pci_disable_msix(oct->pci_dev);
+ kfree(oct->msix_entries);
+ oct->msix_entries = NULL;
+ }
+ /* Soft reset the octeon device before exiting */
+ if (oct->pci_dev->reset_fn)
+ octeon_pci_flr(oct);
+ else
+ cn23xx_vf_ask_pf_to_do_flr(oct);
+
+ /* fallthrough */
+ case OCT_DEV_MSIX_ALLOC_VECTOR_DONE:
+ octeon_free_ioq_vector(oct);
+
+ /* fallthrough */
+ case OCT_DEV_MBOX_SETUP_DONE:
+ oct->fn_list.free_mbox(oct);
+
+ /* fallthrough */
+ case OCT_DEV_IN_RESET:
+ case OCT_DEV_DROQ_INIT_DONE:
+ mdelay(100);
+ for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
+ if (!(oct->io_qmask.oq & BIT_ULL(i)))
+ continue;
+ octeon_delete_droq(oct, i);
+ }
+
+ /* fallthrough */
+ case OCT_DEV_RESP_LIST_INIT_DONE:
+ octeon_delete_response_list(oct);
+
+ /* fallthrough */
+ case OCT_DEV_INSTR_QUEUE_INIT_DONE:
+ for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
+ if (!(oct->io_qmask.iq & BIT_ULL(i)))
+ continue;
+ octeon_delete_instr_queue(oct, i);
+ }
+
+ /* fallthrough */
+ case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
+ octeon_free_sc_buffer_pool(oct);
+
+ /* fallthrough */
+ case OCT_DEV_DISPATCH_INIT_DONE:
+ octeon_delete_dispatch_list(oct);
+ cancel_delayed_work_sync(&oct->nic_poll_work.work);
+
+ /* fallthrough */
+ case OCT_DEV_PCI_MAP_DONE:
+ octeon_unmap_pci_barx(oct, 0);
+ octeon_unmap_pci_barx(oct, 1);
+
+ /* fallthrough */
+ case OCT_DEV_PCI_ENABLE_DONE:
+ pci_clear_master(oct->pci_dev);
+ /* Disable the device, releasing the PCI INT */
+ pci_disable_device(oct->pci_dev);
+
+ /* fallthrough */
+ case OCT_DEV_BEGIN_STATE:
+ /* Nothing to be done here either */
+ break;
+ }
+}
+
+/**
+ * \brief Callback for rx ctrl
+ * @param status status of request
+ * @param buf pointer to resp structure
+ */
+static void rx_ctl_callback(struct octeon_device *oct,
+ u32 status, void *buf)
+{
+ struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
+ struct liquidio_rx_ctl_context *ctx;
+
+ ctx = (struct liquidio_rx_ctl_context *)sc->ctxptr;
+
+ oct = lio_get_device(ctx->octeon_id);
+ if (status)
+ dev_err(&oct->pci_dev->dev, "rx ctl instruction failed. Status: %llx\n",
+ CVM_CAST64(status));
+ WRITE_ONCE(ctx->cond, 1);
+
+ /* This barrier is required to be sure that the response has been
+ * written fully before waking up the handler
+ */
+ wmb();
+
+ wake_up_interruptible(&ctx->wc);
+}
+
+/**
+ * \brief Send Rx control command
+ * @param lio per-network private data
+ * @param start_stop whether to start or stop
+ */
+static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+{
+ struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
+ int ctx_size = sizeof(struct liquidio_rx_ctl_context);
+ struct liquidio_rx_ctl_context *ctx;
+ struct octeon_soft_command *sc;
+ union octnet_cmd *ncmd;
+ int retval;
+
+ if (oct->props[lio->ifidx].rx_on == start_stop)
+ return;
+
+ sc = (struct octeon_soft_command *)
+ octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+ 16, ctx_size);
+
+ ncmd = (union octnet_cmd *)sc->virtdptr;
+ ctx = (struct liquidio_rx_ctl_context *)sc->ctxptr;
+
+ WRITE_ONCE(ctx->cond, 0);
+ ctx->octeon_id = lio_get_device_id(oct);
+ init_waitqueue_head(&ctx->wc);
+
+ ncmd->u64 = 0;
+ ncmd->s.cmd = OCTNET_CMD_RX_CTL;
+ ncmd->s.param1 = start_stop;
+
+ octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
+
+ sc->iq_no = lio->linfo.txpciq[0].s.q_no;
+
+ octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
+ OPCODE_NIC_CMD, 0, 0, 0);
+
+ sc->callback = rx_ctl_callback;
+ sc->callback_arg = sc;
+ sc->wait_time = 5000;
+
+ retval = octeon_send_soft_command(oct, sc);
+ if (retval == IQ_SEND_FAILED) {
+ netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
+ } else {
+ /* Sleep on a wait queue till the cond flag indicates that the
+ * response arrived or timed-out.
+ */
+ if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR)
+ return;
+ oct->props[lio->ifidx].rx_on = start_stop;
+ }
+
+ octeon_free_soft_command(oct, sc);
+}
+
+/**
+ * \brief Destroy NIC device interface
+ * @param oct octeon device
+ * @param ifidx which interface to destroy
+ *
+ * Cleanup associated with each interface for an Octeon device when NIC
+ * module is being unloaded or if initialization fails during load.
+ */
+static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
+{
+ struct net_device *netdev = oct->props[ifidx].netdev;
+ struct napi_struct *napi, *n;
+ struct lio *lio;
+
+ if (!netdev) {
+ dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n",
+ __func__, ifidx);
+ return;
+ }
+
+ lio = GET_LIO(netdev);
+
+ dev_dbg(&oct->pci_dev->dev, "NIC device cleanup\n");
+
+ if (atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING)
+ liquidio_stop(netdev);
+
+ if (oct->props[lio->ifidx].napi_enabled == 1) {
+ list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+ napi_disable(napi);
+
+ oct->props[lio->ifidx].napi_enabled = 0;
+
+ oct->droq[0]->ops.poll_mode = 0;
+ }
+
+ if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
+ unregister_netdev(netdev);
+
+ cleanup_link_status_change_wq(netdev);
+
+ delete_glists(lio);
+
+ free_netdev(netdev);
+
+ oct->props[ifidx].gmxport = -1;
+
+ oct->props[ifidx].netdev = NULL;
+}
+
+/**
+ * \brief Stop complete NIC functionality
+ * @param oct octeon device
+ */
+static int liquidio_stop_nic_module(struct octeon_device *oct)
+{
+ struct lio *lio;
+ int i, j;
+
+ dev_dbg(&oct->pci_dev->dev, "Stopping network interfaces\n");
+ if (!oct->ifcount) {
+ dev_err(&oct->pci_dev->dev, "Init for Octeon was not completed\n");
+ return 1;
+ }
+
+ spin_lock_bh(&oct->cmd_resp_wqlock);
+ oct->cmd_resp_state = OCT_DRV_OFFLINE;
+ spin_unlock_bh(&oct->cmd_resp_wqlock);
+
+ for (i = 0; i < oct->ifcount; i++) {
+ lio = GET_LIO(oct->props[i].netdev);
+ for (j = 0; j < lio->linfo.num_rxpciq; j++)
+ octeon_unregister_droq_ops(oct,
+ lio->linfo.rxpciq[j].s.q_no);
+ }
+
+ for (i = 0; i < oct->ifcount; i++)
+ liquidio_destroy_nic_device(oct, i);
+
+ dev_dbg(&oct->pci_dev->dev, "Network interfaces stopped\n");
+ return 0;
+}
+
+/**
+ * \brief Cleans up resources at unload time
+ * @param pdev PCI device structure
+ */
+static void liquidio_vf_remove(struct pci_dev *pdev)
+{
+ struct octeon_device *oct_dev = pci_get_drvdata(pdev);
+
+ dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
+
+ if (oct_dev->app_mode == CVM_DRV_NIC_APP)
+ liquidio_stop_nic_module(oct_dev);
+
+ /* Reset the octeon device and cleanup all memory allocated for
+ * the octeon device by driver.
+ */
+ octeon_destroy_resources(oct_dev);
+
+ dev_info(&oct_dev->pci_dev->dev, "Device removed\n");
+
+ /* This octeon device has been removed. Update the global
+ * data structure to reflect this. Free the device structure.
+ */
+ octeon_free_device_mem(oct_dev);
+}
+
+/**
+ * \brief PCI initialization for each Octeon device.
+ * @param oct octeon device
+ */
+static int octeon_pci_os_setup(struct octeon_device *oct)
+{
+#ifdef CONFIG_PCI_IOV
+ /* setup PCI stuff first */
+ if (!oct->pci_dev->physfn)
+ octeon_pci_flr(oct);
+#endif
+
+ if (pci_enable_device(oct->pci_dev)) {
+ dev_err(&oct->pci_dev->dev, "pci_enable_device failed\n");
+ return 1;
+ }
+
+ if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
+ dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
+ pci_disable_device(oct->pci_dev);
+ return 1;
+ }
+
+ /* Enable PCI DMA Master. */
+ pci_set_master(oct->pci_dev);
+
+ return 0;
+}
+
+static int skb_iq(struct lio *lio, struct sk_buff *skb)
+{
+ int q = 0;
+
+ if (netif_is_multiqueue(lio->netdev))
+ q = skb->queue_mapping % lio->linfo.num_txpciq;
+
+ return q;
+}
+
+/**
+ * \brief Check Tx queue state for a given network buffer
+ * @param lio per-network private data
+ * @param skb network buffer
+ */
+static int check_txq_state(struct lio *lio, struct sk_buff *skb)
+{
+ int q = 0, iq = 0;
+
+ if (netif_is_multiqueue(lio->netdev)) {
+ q = skb->queue_mapping;
+ iq = lio->linfo.txpciq[(q % (lio->linfo.num_txpciq))].s.q_no;
+ } else {
+ iq = lio->txq;
+ q = iq;
+ }
+
+ if (octnet_iq_is_full(lio->oct_dev, iq))
+ return 0;
+
+ if (__netif_subqueue_stopped(lio->netdev, q)) {
+ INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq, tx_restart, 1);
+ wake_q(lio->netdev, q);
+ }
+
+ return 1;
+}
+
+/**
+ * \brief Unmap and free network buffer
+ * @param buf buffer
+ */
+static void free_netbuf(void *buf)
+{
+ struct octnet_buf_free_info *finfo;
+ struct sk_buff *skb;
+ struct lio *lio;
+
+ finfo = (struct octnet_buf_free_info *)buf;
+ skb = finfo->skb;
+ lio = finfo->lio;
+
+ dma_unmap_single(&lio->oct_dev->pci_dev->dev, finfo->dptr, skb->len,
+ DMA_TO_DEVICE);
+
+ check_txq_state(lio, skb);
+
+ tx_buffer_free(skb);
+}
+
+/**
+ * \brief Unmap and free gather buffer
+ * @param buf buffer
+ */
+static void free_netsgbuf(void *buf)
+{
+ struct octnet_buf_free_info *finfo;
+ struct octnic_gather *g;
+ struct sk_buff *skb;
+ int i, frags, iq;
+ struct lio *lio;
+
+ finfo = (struct octnet_buf_free_info *)buf;
+ skb = finfo->skb;
+ lio = finfo->lio;
+ g = finfo->g;
+ frags = skb_shinfo(skb)->nr_frags;
+
+ dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+ g->sg[0].ptr[0], (skb->len - skb->data_len),
+ DMA_TO_DEVICE);
+
+ i = 1;
+ while (frags--) {
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ pci_unmap_page((lio->oct_dev)->pci_dev,
+ g->sg[(i >> 2)].ptr[(i & 3)],
+ frag->size, DMA_TO_DEVICE);
+ i++;
+ }
+
+ dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+ finfo->dptr, g->sg_size,
+ DMA_TO_DEVICE);
+
+ iq = skb_iq(lio, skb);
+
+ spin_lock(&lio->glist_lock[iq]);
+ list_add_tail(&g->list, &lio->glist[iq]);
+ spin_unlock(&lio->glist_lock[iq]);
+
+ check_txq_state(lio, skb); /* mq support: sub-queue state check */
+
+ tx_buffer_free(skb);
+}
+
+/**
+ * \brief Unmap and free gather buffer with response
+ * @param buf buffer
+ */
+static void free_netsgbuf_with_resp(void *buf)
+{
+ struct octnet_buf_free_info *finfo;
+ struct octeon_soft_command *sc;
+ struct octnic_gather *g;
+ struct sk_buff *skb;
+ int i, frags, iq;
+ struct lio *lio;
+
+ sc = (struct octeon_soft_command *)buf;
+ skb = (struct sk_buff *)sc->callback_arg;
+ finfo = (struct octnet_buf_free_info *)&skb->cb;
+
+ lio = finfo->lio;
+ g = finfo->g;
+ frags = skb_shinfo(skb)->nr_frags;
+
+ dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+ g->sg[0].ptr[0], (skb->len - skb->data_len),
+ DMA_TO_DEVICE);
+
+ i = 1;
+ while (frags--) {
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ pci_unmap_page((lio->oct_dev)->pci_dev,
+ g->sg[(i >> 2)].ptr[(i & 3)],
+ frag->size, DMA_TO_DEVICE);
+ i++;
+ }
+
+ dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+ finfo->dptr, g->sg_size,
+ DMA_TO_DEVICE);
+
+ iq = skb_iq(lio, skb);
+
+ spin_lock(&lio->glist_lock[iq]);
+ list_add_tail(&g->list, &lio->glist[iq]);
+ spin_unlock(&lio->glist_lock[iq]);
+
+ /* Don't free the skb yet */
+
+ check_txq_state(lio, skb);
+}
+
+/**
+ * \brief Setup output queue
+ * @param oct octeon device
+ * @param q_no which queue
+ * @param num_descs how many descriptors
+ * @param desc_size size of each descriptor
+ * @param app_ctx application context
+ */
+static int octeon_setup_droq(struct octeon_device *oct, int q_no, int num_descs,
+ int desc_size, void *app_ctx)
+{
+ int ret_val;
+
+ dev_dbg(&oct->pci_dev->dev, "Creating Droq: %d\n", q_no);
+ /* droq creation and local register settings. */
+ ret_val = octeon_create_droq(oct, q_no, num_descs, desc_size, app_ctx);
+ if (ret_val < 0)
+ return ret_val;
+
+ if (ret_val == 1) {
+ dev_dbg(&oct->pci_dev->dev, "Using default droq %d\n", q_no);
+ return 0;
+ }
+
+ /* Enable the droq queues */
+ octeon_set_droq_pkt_op(oct, q_no, 1);
+
+ /* Send Credit for Octeon Output queues. Credits are always
+ * sent after the output queue is enabled.
+ */
+ writel(oct->droq[q_no]->max_count, oct->droq[q_no]->pkts_credit_reg);
+
+ return ret_val;
+}
+
+/**
+ * \brief Callback for getting interface configuration
+ * @param status status of request
+ * @param buf pointer to resp structure
+ */
+static void if_cfg_callback(struct octeon_device *oct,
+ u32 status __attribute__((unused)), void *buf)
+{
+ struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
+ struct liquidio_if_cfg_context *ctx;
+ struct liquidio_if_cfg_resp *resp;
+
+ resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
+ ctx = (struct liquidio_if_cfg_context *)sc->ctxptr;
+
+ oct = lio_get_device(ctx->octeon_id);
+ if (resp->status)
+ dev_err(&oct->pci_dev->dev, "nic if cfg instruction failed. Status: %llx\n",
+ CVM_CAST64(resp->status));
+ WRITE_ONCE(ctx->cond, 1);
+
+ snprintf(oct->fw_info.liquidio_firmware_version, 32, "%s",
+ resp->cfg_info.liquidio_firmware_version);
+
+ /* This barrier is required to be sure that the response has been
+ * written fully before waking up the handler
+ */
+ wmb();
+
+ wake_up_interruptible(&ctx->wc);
+}
+
+/**
+ * \brief Select queue based on hash
+ * @param dev Net device
+ * @param skb sk_buff structure
+ * @returns selected queue number
+ */
+static u16 select_q(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv __attribute__((unused)),
+ select_queue_fallback_t fallback __attribute__((unused)))
+{
+ struct lio *lio;
+ u32 qindex;
+
+ lio = GET_LIO(dev);
+
+ qindex = skb_tx_hash(dev, skb);
+
+ return (u16)(qindex % (lio->linfo.num_txpciq));
+}
+
+/** Routine to push packets arriving on Octeon interface upto network layer.
+ * @param oct_id - octeon device id.
+ * @param skbuff - skbuff struct to be passed to network layer.
+ * @param len - size of total data received.
+ * @param rh - Control header associated with the packet
+ * @param param - additional control data with the packet
+ * @param arg - farg registered in droq_ops
+ */
+static void
+liquidio_push_packet(u32 octeon_id __attribute__((unused)),
+ void *skbuff,
+ u32 len,
+ union octeon_rh *rh,
+ void *param,
+ void *arg)
+{
+ struct napi_struct *napi = param;
+ struct octeon_droq *droq =
+ container_of(param, struct octeon_droq, napi);
+ struct net_device *netdev = (struct net_device *)arg;
+ struct sk_buff *skb = (struct sk_buff *)skbuff;
+ u16 vtag = 0;
+
+ if (netdev) {
+ struct lio *lio = GET_LIO(netdev);
+ int packet_was_received;
+
+ /* Do not proceed if the interface is not in RUNNING state. */
+ if (!ifstate_check(lio, LIO_IFSTATE_RUNNING)) {
+ recv_buffer_free(skb);
+ droq->stats.rx_dropped++;
+ return;
+ }
+
+ skb->dev = netdev;
+
+ skb_record_rx_queue(skb, droq->q_no);
+ if (likely(len > MIN_SKB_SIZE)) {
+ struct octeon_skb_page_info *pg_info;
+ unsigned char *va;
+
+ pg_info = ((struct octeon_skb_page_info *)(skb->cb));
+ if (pg_info->page) {
+ /* For Paged allocation use the frags */
+ va = page_address(pg_info->page) +
+ pg_info->page_offset;
+ memcpy(skb->data, va, MIN_SKB_SIZE);
+ skb_put(skb, MIN_SKB_SIZE);
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+ pg_info->page,
+ pg_info->page_offset +
+ MIN_SKB_SIZE,
+ len - MIN_SKB_SIZE,
+ LIO_RXBUFFER_SZ);
+ }
+ } else {
+ struct octeon_skb_page_info *pg_info =
+ ((struct octeon_skb_page_info *)(skb->cb));
+ skb_copy_to_linear_data(skb,
+ page_address(pg_info->page) +
+ pg_info->page_offset, len);
+ skb_put(skb, len);
+ put_page(pg_info->page);
+ }
+
+ skb_pull(skb, rh->r_dh.len * 8);
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ if ((netdev->features & NETIF_F_RXCSUM) &&
+ (((rh->r_dh.encap_on) &&
+ (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) ||
+ (!(rh->r_dh.encap_on) &&
+ (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED))))
+ /* checksum has already been verified */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Setting Encapsulation field on basis of status received
+ * from the firmware
+ */
+ if (rh->r_dh.encap_on) {
+ skb->encapsulation = 1;
+ skb->csum_level = 1;
+ droq->stats.rx_vxlan++;
+ }
+
+ /* inbound VLAN tag */
+ if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ rh->r_dh.vlan) {
+ u16 priority = rh->r_dh.priority;
+ u16 vid = rh->r_dh.vlan;
+
+ vtag = (priority << VLAN_PRIO_SHIFT) | vid;
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag);
+ }
+
+ packet_was_received = (napi_gro_receive(napi, skb) != GRO_DROP);
+
+ if (packet_was_received) {
+ droq->stats.rx_bytes_received += len;
+ droq->stats.rx_pkts_received++;
+ netdev->last_rx = jiffies;
+ } else {
+ droq->stats.rx_dropped++;
+ netif_info(lio, rx_err, lio->netdev,
+ "droq:%d error rx_dropped:%llu\n",
+ droq->q_no, droq->stats.rx_dropped);
+ }
+
+ } else {
+ recv_buffer_free(skb);
+ }
+}
+
+/**
+ * \brief callback when receive interrupt occurs and we are in NAPI mode
+ * @param arg pointer to octeon output queue
+ */
+static void liquidio_vf_napi_drv_callback(void *arg)
+{
+ struct octeon_droq *droq = arg;
+
+ napi_schedule_irqoff(&droq->napi);
+}
+
+/**
+ * \brief Entry point for NAPI polling
+ * @param napi NAPI structure
+ * @param budget maximum number of items to process
+ */
+static int liquidio_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct octeon_instr_queue *iq;
+ struct octeon_device *oct;
+ struct octeon_droq *droq;
+ int tx_done = 0, iq_no;
+ int work_done;
+
+ droq = container_of(napi, struct octeon_droq, napi);
+ oct = droq->oct_dev;
+ iq_no = droq->q_no;
+
+ /* Handle Droq descriptors */
+ work_done = octeon_process_droq_poll_cmd(oct, droq->q_no,
+ POLL_EVENT_PROCESS_PKTS,
+ budget);
+
+ /* Flush the instruction queue */
+ iq = oct->instr_queue[iq_no];
+ if (iq) {
+ /* Process iq buffers with in the budget limits */
+ tx_done = octeon_flush_iq(oct, iq, 1, budget);
+ /* Update iq read-index rather than waiting for next interrupt.
+ * Return back if tx_done is false.
+ */
+ update_txq_status(oct, iq_no);
+ } else {
+ dev_err(&oct->pci_dev->dev, "%s: iq (%d) num invalid\n",
+ __func__, iq_no);
+ }
+
+ if ((work_done < budget) && (tx_done)) {
+ napi_complete(napi);
+ octeon_process_droq_poll_cmd(droq->oct_dev, droq->q_no,
+ POLL_EVENT_ENABLE_INTR, 0);
+ return 0;
+ }
+
+ return (!tx_done) ? (budget) : (work_done);
+}
+
+/**
+ * \brief Setup input and output queues
+ * @param octeon_dev octeon device
+ * @param ifidx Interface index
+ *
+ * Note: Queues are with respect to the octeon device. Thus
+ * an input queue is for egress packets, and output queues
+ * are for ingress packets.
+ */
+static int setup_io_queues(struct octeon_device *octeon_dev, int ifidx)
+{
+ struct octeon_droq_ops droq_ops;
+ struct net_device *netdev;
+ static int cpu_id_modulus;
+ struct octeon_droq *droq;
+ struct napi_struct *napi;
+ static int cpu_id;
+ int num_tx_descs;
+ struct lio *lio;
+ int retval = 0;
+ int q, q_no;
+
+ netdev = octeon_dev->props[ifidx].netdev;
+
+ lio = GET_LIO(netdev);
+
+ memset(&droq_ops, 0, sizeof(struct octeon_droq_ops));
+
+ droq_ops.fptr = liquidio_push_packet;
+ droq_ops.farg = netdev;
+
+ droq_ops.poll_mode = 1;
+ droq_ops.napi_fn = liquidio_vf_napi_drv_callback;
+ cpu_id = 0;
+ cpu_id_modulus = num_present_cpus();
+
+ /* set up DROQs. */
+ for (q = 0; q < lio->linfo.num_rxpciq; q++) {
+ q_no = lio->linfo.rxpciq[q].s.q_no;
+
+ retval = octeon_setup_droq(
+ octeon_dev, q_no,
+ CFG_GET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(octeon_dev),
+ lio->ifidx),
+ CFG_GET_NUM_RX_BUF_SIZE_NIC_IF(octeon_get_conf(octeon_dev),
+ lio->ifidx),
+ NULL);
+ if (retval) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "%s : Runtime DROQ(RxQ) creation failed.\n",
+ __func__);
+ return 1;
+ }
+
+ droq = octeon_dev->droq[q_no];
+ napi = &droq->napi;
+ netif_napi_add(netdev, napi, liquidio_napi_poll, 64);
+
+ /* designate a CPU for this droq */
+ droq->cpu_id = cpu_id;
+ cpu_id++;
+ if (cpu_id >= cpu_id_modulus)
+ cpu_id = 0;
+
+ octeon_register_droq_ops(octeon_dev, q_no, &droq_ops);
+ }
+
+ /* 23XX VF can send/recv control messages (via the first VF-owned
+ * droq) from the firmware even if the ethX interface is down,
+ * so that's why poll_mode must be off for the first droq.
+ */
+ octeon_dev->droq[0]->ops.poll_mode = 0;
+
+ /* set up IQs. */
+ for (q = 0; q < lio->linfo.num_txpciq; q++) {
+ num_tx_descs = CFG_GET_NUM_TX_DESCS_NIC_IF(
+ octeon_get_conf(octeon_dev), lio->ifidx);
+ retval = octeon_setup_iq(octeon_dev, ifidx, q,
+ lio->linfo.txpciq[q], num_tx_descs,
+ netdev_get_tx_queue(netdev, q));
+ if (retval) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ " %s : Runtime IQ(TxQ) creation failed.\n",
+ __func__);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Net device open for LiquidIO
+ * @param netdev network device
+ */
+static int liquidio_open(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct napi_struct *napi, *n;
+
+ if (!oct->props[lio->ifidx].napi_enabled) {
+ list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+ napi_enable(napi);
+
+ oct->props[lio->ifidx].napi_enabled = 1;
+
+ oct->droq[0]->ops.poll_mode = 1;
+ }
+
+ ifstate_set(lio, LIO_IFSTATE_RUNNING);
+
+ /* Ready for link status updates */
+ lio->intf_open = 1;
+
+ netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
+ start_txq(netdev);
+
+ /* tell Octeon to start forwarding packets to host */
+ send_rx_ctrl_cmd(lio, 1);
+
+ dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name);
+
+ return 0;
+}
+
+/**
+ * \brief Net device stop for LiquidIO
+ * @param netdev network device
+ */
+static int liquidio_stop(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
+ /* Inform that netif carrier is down */
+ lio->intf_open = 0;
+ lio->linfo.link.s.link_up = 0;
+
+ netif_carrier_off(netdev);
+ lio->link_changes++;
+
+ /* tell Octeon to stop forwarding packets to host */
+ send_rx_ctrl_cmd(lio, 0);
+
+ ifstate_reset(lio, LIO_IFSTATE_RUNNING);
+
+ txqs_stop(netdev);
+
+ dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
+
+ return 0;
+}
+
+/**
+ * \brief Converts a mask based on net device flags
+ * @param netdev network device
+ *
+ * This routine generates a octnet_ifflags mask from the net device flags
+ * received from the OS.
+ */
+static enum octnet_ifflags get_new_flags(struct net_device *netdev)
+{
+ enum octnet_ifflags f = OCTNET_IFFLAG_UNICAST;
+
+ if (netdev->flags & IFF_PROMISC)
+ f |= OCTNET_IFFLAG_PROMISC;
+
+ if (netdev->flags & IFF_ALLMULTI)
+ f |= OCTNET_IFFLAG_ALLMULTI;
+
+ if (netdev->flags & IFF_MULTICAST) {
+ f |= OCTNET_IFFLAG_MULTICAST;
+
+ /* Accept all multicast addresses if there are more than we
+ * can handle
+ */
+ if (netdev_mc_count(netdev) > MAX_OCTEON_MULTICAST_ADDR)
+ f |= OCTNET_IFFLAG_ALLMULTI;
+ }
+
+ if (netdev->flags & IFF_BROADCAST)
+ f |= OCTNET_IFFLAG_BROADCAST;
+
+ return f;
+}
+
+static void liquidio_set_uc_list(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ struct netdev_hw_addr *ha;
+ u64 *mac;
+
+ if (lio->netdev_uc_count == netdev_uc_count(netdev))
+ return;
+
+ if (netdev_uc_count(netdev) > MAX_NCTRL_UDD) {
+ dev_err(&oct->pci_dev->dev, "too many MAC addresses in netdev uc list\n");
+ return;
+ }
+
+ lio->netdev_uc_count = netdev_uc_count(netdev);
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+ nctrl.ncmd.s.cmd = OCTNET_CMD_SET_UC_LIST;
+ nctrl.ncmd.s.more = lio->netdev_uc_count;
+ nctrl.ncmd.s.param1 = oct->vf_num;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ /* copy all the addresses into the udd */
+ mac = &nctrl.udd[0];
+ netdev_for_each_uc_addr(ha, netdev) {
+ ether_addr_copy(((u8 *)mac) + 2, ha->addr);
+ mac++;
+ }
+
+ octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+}
+
+/**
+ * \brief Net device set_multicast_list
+ * @param netdev network device
+ */
+static void liquidio_set_mcast_list(struct net_device *netdev)
+{
+ int mc_count = min(netdev_mc_count(netdev), MAX_OCTEON_MULTICAST_ADDR);
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ struct netdev_hw_addr *ha;
+ u64 *mc;
+ int ret;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ /* Create a ctrl pkt command to be sent to core app. */
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = OCTNET_CMD_SET_MULTI_LIST;
+ nctrl.ncmd.s.param1 = get_new_flags(netdev);
+ nctrl.ncmd.s.param2 = mc_count;
+ nctrl.ncmd.s.more = mc_count;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ /* copy all the addresses into the udd */
+ mc = &nctrl.udd[0];
+ netdev_for_each_mc_addr(ha, netdev) {
+ *mc = 0;
+ ether_addr_copy(((u8 *)mc) + 2, ha->addr);
+ /* no need to swap bytes */
+ if (++mc > &nctrl.udd[mc_count])
+ break;
+ }
+
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+
+ /* Apparently, any activity in this call from the kernel has to
+ * be atomic. So we won't wait for response.
+ */
+ nctrl.wait_time = 0;
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
+ ret);
+ }
+
+ liquidio_set_uc_list(netdev);
+}
+
+/**
+ * \brief Net device set_mac_address
+ * @param netdev network device
+ */
+static int liquidio_set_mac(struct net_device *netdev, void *p)
+{
+ struct sockaddr *addr = (struct sockaddr *)p;
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ int ret = 0;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
+ return 0;
+
+ if (lio->linfo.macaddr_is_admin_asgnd)
+ return -EPERM;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
+ nctrl.ncmd.s.param1 = 0;
+ nctrl.ncmd.s.more = 1;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+ nctrl.wait_time = 100;
+
+ nctrl.udd[0] = 0;
+ /* The MAC Address is presented in network byte order. */
+ ether_addr_copy((u8 *)&nctrl.udd[0] + 2, addr->sa_data);
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
+ return -ENOMEM;
+ }
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data);
+
+ return 0;
+}
+
+/**
+ * \brief Net device get_stats
+ * @param netdev network device
+ */
+static struct net_device_stats *liquidio_get_stats(struct net_device *netdev)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct net_device_stats *stats = &netdev->stats;
+ u64 pkts = 0, drop = 0, bytes = 0;
+ struct oct_droq_stats *oq_stats;
+ struct oct_iq_stats *iq_stats;
+ struct octeon_device *oct;
+ int i, iq_no, oq_no;
+
+ oct = lio->oct_dev;
+
+ for (i = 0; i < lio->linfo.num_txpciq; i++) {
+ iq_no = lio->linfo.txpciq[i].s.q_no;
+ iq_stats = &oct->instr_queue[iq_no]->stats;
+ pkts += iq_stats->tx_done;
+ drop += iq_stats->tx_dropped;
+ bytes += iq_stats->tx_tot_bytes;
+ }
+
+ stats->tx_packets = pkts;
+ stats->tx_bytes = bytes;
+ stats->tx_dropped = drop;
+
+ pkts = 0;
+ drop = 0;
+ bytes = 0;
+
+ for (i = 0; i < lio->linfo.num_rxpciq; i++) {
+ oq_no = lio->linfo.rxpciq[i].s.q_no;
+ oq_stats = &oct->droq[oq_no]->stats;
+ pkts += oq_stats->rx_pkts_received;
+ drop += (oq_stats->rx_dropped +
+ oq_stats->dropped_nodispatch +
+ oq_stats->dropped_toomany +
+ oq_stats->dropped_nomem);
+ bytes += oq_stats->rx_bytes_received;
+ }
+
+ stats->rx_bytes = bytes;
+ stats->rx_packets = pkts;
+ stats->rx_dropped = drop;
+
+ return stats;
+}
+
+/**
+ * \brief Net device change_mtu
+ * @param netdev network device
+ */
+static int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ lio->mtu = new_mtu;
+
+ netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n",
+ netdev->mtu, new_mtu);
+ dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
+ netdev->name, netdev->mtu, new_mtu);
+
+ netdev->mtu = new_mtu;
+
+ return 0;
+}
+
+/**
+ * \brief Handler for SIOCSHWTSTAMP ioctl
+ * @param netdev network device
+ * @param ifr interface request
+ * @param cmd command
+ */
+static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct hwtstamp_config conf;
+
+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf)))
+ return -EFAULT;
+
+ if (conf.flags)
+ return -EINVAL;
+
+ switch (conf.tx_type) {
+ case HWTSTAMP_TX_ON:
+ case HWTSTAMP_TX_OFF:
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (conf.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_SOME:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ conf.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (conf.rx_filter == HWTSTAMP_FILTER_ALL)
+ ifstate_set(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
+
+ else
+ ifstate_reset(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
+
+ return copy_to_user(ifr->ifr_data, &conf, sizeof(conf)) ? -EFAULT : 0;
+}
+
+/**
+ * \brief ioctl handler
+ * @param netdev network device
+ * @param ifr interface request
+ * @param cmd command
+ */
+static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return hwtstamp_ioctl(netdev, ifr);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void handle_timestamp(struct octeon_device *oct, u32 status, void *buf)
+{
+ struct sk_buff *skb = (struct sk_buff *)buf;
+ struct octnet_buf_free_info *finfo;
+ struct oct_timestamp_resp *resp;
+ struct octeon_soft_command *sc;
+ struct lio *lio;
+
+ finfo = (struct octnet_buf_free_info *)skb->cb;
+ lio = finfo->lio;
+ sc = finfo->sc;
+ oct = lio->oct_dev;
+ resp = (struct oct_timestamp_resp *)sc->virtrptr;
+
+ if (status != OCTEON_REQUEST_DONE) {
+ dev_err(&oct->pci_dev->dev, "Tx timestamp instruction failed. Status: %llx\n",
+ CVM_CAST64(status));
+ resp->timestamp = 0;
+ }
+
+ octeon_swap_8B_data(&resp->timestamp, 1);
+
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+ struct skb_shared_hwtstamps ts;
+ u64 ns = resp->timestamp;
+
+ netif_info(lio, tx_done, lio->netdev,
+ "Got resulting SKBTX_HW_TSTAMP skb=%p ns=%016llu\n",
+ skb, (unsigned long long)ns);
+ ts.hwtstamp = ns_to_ktime(ns + lio->ptp_adjust);
+ skb_tstamp_tx(skb, &ts);
+ }
+
+ octeon_free_soft_command(oct, sc);
+ tx_buffer_free(skb);
+}
+
+/* \brief Send a data packet that will be timestamped
+ * @param oct octeon device
+ * @param ndata pointer to network data
+ * @param finfo pointer to private network data
+ */
+static int send_nic_timestamp_pkt(struct octeon_device *oct,
+ struct octnic_data_pkt *ndata,
+ struct octnet_buf_free_info *finfo)
+{
+ struct octeon_soft_command *sc;
+ int ring_doorbell;
+ struct lio *lio;
+ int retval;
+ u32 len;
+
+ lio = finfo->lio;
+
+ sc = octeon_alloc_soft_command_resp(oct, &ndata->cmd,
+ sizeof(struct oct_timestamp_resp));
+ finfo->sc = sc;
+
+ if (!sc) {
+ dev_err(&oct->pci_dev->dev, "No memory for timestamped data packet\n");
+ return IQ_SEND_FAILED;
+ }
+
+ if (ndata->reqtype == REQTYPE_NORESP_NET)
+ ndata->reqtype = REQTYPE_RESP_NET;
+ else if (ndata->reqtype == REQTYPE_NORESP_NET_SG)
+ ndata->reqtype = REQTYPE_RESP_NET_SG;
+
+ sc->callback = handle_timestamp;
+ sc->callback_arg = finfo->skb;
+ sc->iq_no = ndata->q_no;
+
+ len = (u32)((struct octeon_instr_ih3 *)(&sc->cmd.cmd3.ih3))->dlengsz;
+
+ ring_doorbell = 1;
+
+ retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
+ sc, len, ndata->reqtype);
+
+ if (retval == IQ_SEND_FAILED) {
+ dev_err(&oct->pci_dev->dev, "timestamp data packet failed status: %x\n",
+ retval);
+ octeon_free_soft_command(oct, sc);
+ } else {
+ netif_info(lio, tx_queued, lio->netdev, "Queued timestamp packet\n");
+ }
+
+ return retval;
+}
+
+/** \brief Transmit networks packets to the Octeon interface
+ * @param skbuff skbuff struct to be passed to network layer.
+ * @param netdev pointer to network device
+ * @returns whether the packet was transmitted to the device okay or not
+ * (NETDEV_TX_OK or NETDEV_TX_BUSY)
+ */
+static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct octnet_buf_free_info *finfo;
+ union octnic_cmd_setup cmdsetup;
+ struct octnic_data_pkt ndata;
+ struct octeon_instr_irh *irh;
+ struct oct_iq_stats *stats;
+ struct octeon_device *oct;
+ int q_idx = 0, iq_no = 0;
+ union tx_info *tx_info;
+ struct lio *lio;
+ int status = 0;
+ u64 dptr = 0;
+ u32 tag = 0;
+ int j;
+
+ lio = GET_LIO(netdev);
+ oct = lio->oct_dev;
+
+ if (netif_is_multiqueue(netdev)) {
+ q_idx = skb->queue_mapping;
+ q_idx = (q_idx % (lio->linfo.num_txpciq));
+ tag = q_idx;
+ iq_no = lio->linfo.txpciq[q_idx].s.q_no;
+ } else {
+ iq_no = lio->txq;
+ }
+
+ stats = &oct->instr_queue[iq_no]->stats;
+
+ /* Check for all conditions in which the current packet cannot be
+ * transmitted.
+ */
+ if (!(atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING) ||
+ (!lio->linfo.link.s.link_up) || (skb->len <= 0)) {
+ netif_info(lio, tx_err, lio->netdev, "Transmit failed link_status : %d\n",
+ lio->linfo.link.s.link_up);
+ goto lio_xmit_failed;
+ }
+
+ /* Use space in skb->cb to store info used to unmap and
+ * free the buffers.
+ */
+ finfo = (struct octnet_buf_free_info *)skb->cb;
+ finfo->lio = lio;
+ finfo->skb = skb;
+ finfo->sc = NULL;
+
+ /* Prepare the attributes for the data to be passed to OSI. */
+ memset(&ndata, 0, sizeof(struct octnic_data_pkt));
+
+ ndata.buf = finfo;
+
+ ndata.q_no = iq_no;
+
+ if (netif_is_multiqueue(netdev)) {
+ if (octnet_iq_is_full(oct, ndata.q_no)) {
+ /* defer sending if queue is full */
+ netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n",
+ ndata.q_no);
+ stats->tx_iq_busy++;
+ return NETDEV_TX_BUSY;
+ }
+ } else {
+ if (octnet_iq_is_full(oct, lio->txq)) {
+ /* defer sending if queue is full */
+ stats->tx_iq_busy++;
+ netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n",
+ ndata.q_no);
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ ndata.datasize = skb->len;
+
+ cmdsetup.u64 = 0;
+ cmdsetup.s.iq_no = iq_no;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (skb->encapsulation) {
+ cmdsetup.s.tnl_csum = 1;
+ stats->tx_vxlan++;
+ } else {
+ cmdsetup.s.transport_csum = 1;
+ }
+ }
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ cmdsetup.s.timestamp = 1;
+ }
+
+ if (!skb_shinfo(skb)->nr_frags) {
+ cmdsetup.s.u.datasize = skb->len;
+ octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
+ /* Offload checksum calculation for TCP/UDP packets */
+ dptr = dma_map_single(&oct->pci_dev->dev,
+ skb->data,
+ skb->len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
+ dev_err(&oct->pci_dev->dev, "%s DMA mapping error 1\n",
+ __func__);
+ return NETDEV_TX_BUSY;
+ }
+
+ ndata.cmd.cmd3.dptr = dptr;
+ finfo->dptr = dptr;
+ ndata.reqtype = REQTYPE_NORESP_NET;
+
+ } else {
+ struct skb_frag_struct *frag;
+ struct octnic_gather *g;
+ int i, frags;
+
+ spin_lock(&lio->glist_lock[q_idx]);
+ g = (struct octnic_gather *)list_delete_head(
+ &lio->glist[q_idx]);
+ spin_unlock(&lio->glist_lock[q_idx]);
+
+ if (!g) {
+ netif_info(lio, tx_err, lio->netdev,
+ "Transmit scatter gather: glist null!\n");
+ goto lio_xmit_failed;
+ }
+
+ cmdsetup.s.gather = 1;
+ cmdsetup.s.u.gatherptrs = (skb_shinfo(skb)->nr_frags + 1);
+ octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
+
+ memset(g->sg, 0, g->sg_size);
+
+ g->sg[0].ptr[0] = dma_map_single(&oct->pci_dev->dev,
+ skb->data,
+ (skb->len - skb->data_len),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&oct->pci_dev->dev, g->sg[0].ptr[0])) {
+ dev_err(&oct->pci_dev->dev, "%s DMA mapping error 2\n",
+ __func__);
+ return NETDEV_TX_BUSY;
+ }
+ add_sg_size(&g->sg[0], (skb->len - skb->data_len), 0);
+
+ frags = skb_shinfo(skb)->nr_frags;
+ i = 1;
+ while (frags--) {
+ frag = &skb_shinfo(skb)->frags[i - 1];
+
+ g->sg[(i >> 2)].ptr[(i & 3)] =
+ dma_map_page(&oct->pci_dev->dev,
+ frag->page.p,
+ frag->page_offset,
+ frag->size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&oct->pci_dev->dev,
+ g->sg[i >> 2].ptr[i & 3])) {
+ dma_unmap_single(&oct->pci_dev->dev,
+ g->sg[0].ptr[0],
+ skb->len - skb->data_len,
+ DMA_TO_DEVICE);
+ for (j = 1; j < i; j++) {
+ frag = &skb_shinfo(skb)->frags[j - 1];
+ dma_unmap_page(&oct->pci_dev->dev,
+ g->sg[j >> 2].ptr[j & 3],
+ frag->size,
+ DMA_TO_DEVICE);
+ }
+ dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n",
+ __func__);
+ return NETDEV_TX_BUSY;
+ }
+
+ add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3));
+ i++;
+ }
+
+ dptr = dma_map_single(&oct->pci_dev->dev,
+ g->sg, g->sg_size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
+ dev_err(&oct->pci_dev->dev, "%s DMA mapping error 4\n",
+ __func__);
+ dma_unmap_single(&oct->pci_dev->dev, g->sg[0].ptr[0],
+ skb->len - skb->data_len,
+ DMA_TO_DEVICE);
+ for (j = 1; j <= frags; j++) {
+ frag = &skb_shinfo(skb)->frags[j - 1];
+ dma_unmap_page(&oct->pci_dev->dev,
+ g->sg[j >> 2].ptr[j & 3],
+ frag->size, DMA_TO_DEVICE);
+ }
+ return NETDEV_TX_BUSY;
+ }
+
+ ndata.cmd.cmd3.dptr = dptr;
+ finfo->dptr = dptr;
+ finfo->g = g;
+
+ ndata.reqtype = REQTYPE_NORESP_NET_SG;
+ }
+
+ irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh;
+ tx_info = (union tx_info *)&ndata.cmd.cmd3.ossp[0];
+
+ if (skb_shinfo(skb)->gso_size) {
+ tx_info->s.gso_size = skb_shinfo(skb)->gso_size;
+ tx_info->s.gso_segs = skb_shinfo(skb)->gso_segs;
+ }
+
+ /* HW insert VLAN tag */
+ if (skb_vlan_tag_present(skb)) {
+ irh->priority = skb_vlan_tag_get(skb) >> VLAN_PRIO_SHIFT;
+ irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
+ }
+
+ if (unlikely(cmdsetup.s.timestamp))
+ status = send_nic_timestamp_pkt(oct, &ndata, finfo);
+ else
+ status = octnet_send_nic_data_pkt(oct, &ndata);
+ if (status == IQ_SEND_FAILED)
+ goto lio_xmit_failed;
+
+ netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
+
+ if (status == IQ_SEND_STOP) {
+ dev_err(&oct->pci_dev->dev, "Rcvd IQ_SEND_STOP signal; stopping IQ-%d\n",
+ iq_no);
+ stop_q(lio->netdev, q_idx);
+ }
+
+ netif_trans_update(netdev);
+
+ if (skb_shinfo(skb)->gso_size)
+ stats->tx_done += skb_shinfo(skb)->gso_segs;
+ else
+ stats->tx_done++;
+ stats->tx_tot_bytes += skb->len;
+
+ return NETDEV_TX_OK;
+
+lio_xmit_failed:
+ stats->tx_dropped++;
+ netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n",
+ iq_no, stats->tx_dropped);
+ if (dptr)
+ dma_unmap_single(&oct->pci_dev->dev, dptr,
+ ndata.datasize, DMA_TO_DEVICE);
+ tx_buffer_free(skb);
+ return NETDEV_TX_OK;
+}
+
+/** \brief Network device Tx timeout
+ * @param netdev pointer to network device
+ */
+static void liquidio_tx_timeout(struct net_device *netdev)
+{
+ struct lio *lio;
+
+ lio = GET_LIO(netdev);
+
+ netif_info(lio, tx_err, lio->netdev,
+ "Transmit timeout tx_dropped:%ld, waking up queues now!!\n",
+ netdev->stats.tx_dropped);
+ netif_trans_update(netdev);
+ txqs_wake(netdev);
+}
+
+static int
+liquidio_vlan_rx_add_vid(struct net_device *netdev,
+ __be16 proto __attribute__((unused)), u16 vid)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ int ret = 0;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
+ nctrl.ncmd.s.param1 = vid;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.wait_time = 100;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
+ ret);
+ }
+
+ return ret;
+}
+
+static int
+liquidio_vlan_rx_kill_vid(struct net_device *netdev,
+ __be16 proto __attribute__((unused)), u16 vid)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ int ret = 0;
+
+ memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
+ nctrl.ncmd.s.param1 = vid;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.wait_time = 100;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
+ ret);
+ }
+ return ret;
+}
+
+/** Sending command to enable/disable RX checksum offload
+ * @param netdev pointer to network device
+ * @param command OCTNET_CMD_TNL_RX_CSUM_CTL
+ * @param rx_cmd_bit OCTNET_CMD_RXCSUM_ENABLE/
+ * OCTNET_CMD_RXCSUM_DISABLE
+ * @returns SUCCESS or FAILURE
+ */
+static int liquidio_set_rxcsum_command(struct net_device *netdev, int command,
+ u8 rx_cmd)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ int ret = 0;
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = command;
+ nctrl.ncmd.s.param1 = rx_cmd;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.wait_time = 100;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev, "DEVFLAGS RXCSUM change failed in core (ret:0x%x)\n",
+ ret);
+ }
+ return ret;
+}
+
+/** Sending command to add/delete VxLAN UDP port to firmware
+ * @param netdev pointer to network device
+ * @param command OCTNET_CMD_VXLAN_PORT_CONFIG
+ * @param vxlan_port VxLAN port to be added or deleted
+ * @param vxlan_cmd_bit OCTNET_CMD_VXLAN_PORT_ADD,
+ * OCTNET_CMD_VXLAN_PORT_DEL
+ * @returns SUCCESS or FAILURE
+ */
+static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
+ u16 vxlan_port, u8 vxlan_cmd_bit)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+ struct octnic_ctrl_pkt nctrl;
+ int ret = 0;
+
+ nctrl.ncmd.u64 = 0;
+ nctrl.ncmd.s.cmd = command;
+ nctrl.ncmd.s.more = vxlan_cmd_bit;
+ nctrl.ncmd.s.param1 = vxlan_port;
+ nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+ nctrl.wait_time = 100;
+ nctrl.netpndev = (u64)netdev;
+ nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+ ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+ if (ret < 0) {
+ dev_err(&oct->pci_dev->dev,
+ "DEVFLAGS VxLAN port add/delete failed in core (ret : 0x%x)\n",
+ ret);
+ }
+ return ret;
+}
+
+/** \brief Net device fix features
+ * @param netdev pointer to network device
+ * @param request features requested
+ * @returns updated features list
+ */
+static netdev_features_t liquidio_fix_features(struct net_device *netdev,
+ netdev_features_t request)
+{
+ struct lio *lio = netdev_priv(netdev);
+
+ if ((request & NETIF_F_RXCSUM) &&
+ !(lio->dev_capability & NETIF_F_RXCSUM))
+ request &= ~NETIF_F_RXCSUM;
+
+ if ((request & NETIF_F_HW_CSUM) &&
+ !(lio->dev_capability & NETIF_F_HW_CSUM))
+ request &= ~NETIF_F_HW_CSUM;
+
+ if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
+ request &= ~NETIF_F_TSO;
+
+ if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
+ request &= ~NETIF_F_TSO6;
+
+ if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
+ request &= ~NETIF_F_LRO;
+
+ /* Disable LRO if RXCSUM is off */
+ if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
+ (lio->dev_capability & NETIF_F_LRO))
+ request &= ~NETIF_F_LRO;
+
+ return request;
+}
+
+/** \brief Net device set features
+ * @param netdev pointer to network device
+ * @param features features to enable/disable
+ */
+static int liquidio_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct lio *lio = netdev_priv(netdev);
+
+ if (!((netdev->features ^ features) & NETIF_F_LRO))
+ return 0;
+
+ if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO))
+ liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
+ OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+ else if (!(features & NETIF_F_LRO) &&
+ (lio->dev_capability & NETIF_F_LRO))
+ liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,
+ OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+ if (!(netdev->features & NETIF_F_RXCSUM) &&
+ (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
+ (features & NETIF_F_RXCSUM))
+ liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+ OCTNET_CMD_RXCSUM_ENABLE);
+ else if ((netdev->features & NETIF_F_RXCSUM) &&
+ (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
+ !(features & NETIF_F_RXCSUM))
+ liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+ OCTNET_CMD_RXCSUM_DISABLE);
+
+ return 0;
+}
+
+static void liquidio_add_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+ return;
+
+ liquidio_vxlan_port_command(netdev,
+ OCTNET_CMD_VXLAN_PORT_CONFIG,
+ htons(ti->port),
+ OCTNET_CMD_VXLAN_PORT_ADD);
+}
+
+static void liquidio_del_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+ return;
+
+ liquidio_vxlan_port_command(netdev,
+ OCTNET_CMD_VXLAN_PORT_CONFIG,
+ htons(ti->port),
+ OCTNET_CMD_VXLAN_PORT_DEL);
+}
+
+static const struct net_device_ops lionetdevops = {
+ .ndo_open = liquidio_open,
+ .ndo_stop = liquidio_stop,
+ .ndo_start_xmit = liquidio_xmit,
+ .ndo_get_stats = liquidio_get_stats,
+ .ndo_set_mac_address = liquidio_set_mac,
+ .ndo_set_rx_mode = liquidio_set_mcast_list,
+ .ndo_tx_timeout = liquidio_tx_timeout,
+ .ndo_vlan_rx_add_vid = liquidio_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = liquidio_vlan_rx_kill_vid,
+ .ndo_change_mtu = liquidio_change_mtu,
+ .ndo_do_ioctl = liquidio_ioctl,
+ .ndo_fix_features = liquidio_fix_features,
+ .ndo_set_features = liquidio_set_features,
+ .ndo_udp_tunnel_add = liquidio_add_vxlan_port,
+ .ndo_udp_tunnel_del = liquidio_del_vxlan_port,
+ .ndo_select_queue = select_q,
+};
+
+static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)
+{
+ struct octeon_device *oct = (struct octeon_device *)buf;
+ struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
+ union oct_link_status *ls;
+ int gmxport = 0;
+ int i;
+
+ if (recv_pkt->buffer_size[0] != sizeof(*ls)) {
+ dev_err(&oct->pci_dev->dev, "Malformed NIC_INFO, len=%d, ifidx=%d\n",
+ recv_pkt->buffer_size[0],
+ recv_pkt->rh.r_nic_info.gmxport);
+ goto nic_info_err;
+ }
+
+ gmxport = recv_pkt->rh.r_nic_info.gmxport;
+ ls = (union oct_link_status *)get_rbd(recv_pkt->buffer_ptr[0]);
+
+ octeon_swap_8B_data((u64 *)ls, (sizeof(union oct_link_status)) >> 3);
+
+ for (i = 0; i < oct->ifcount; i++) {
+ if (oct->props[i].gmxport == gmxport) {
+ update_link_status(oct->props[i].netdev, ls);
+ break;
+ }
+ }
+
+nic_info_err:
+ for (i = 0; i < recv_pkt->buffer_count; i++)
+ recv_buffer_free(recv_pkt->buffer_ptr[i]);
+ octeon_free_recv_info(recv_info);
+ return 0;
+}
+
+/**
+ * \brief Setup network interfaces
+ * @param octeon_dev octeon device
+ *
+ * Called during init time for each device. It assumes the NIC
+ * is already up and running. The link information for each
+ * interface is passed in link_info.
+ */
+static int setup_nic_devices(struct octeon_device *octeon_dev)
+{
+ int retval, num_iqueues, num_oqueues;
+ struct liquidio_if_cfg_context *ctx;
+ u32 resp_size, ctx_size, data_size;
+ struct liquidio_if_cfg_resp *resp;
+ struct octeon_soft_command *sc;
+ union oct_nic_if_cfg if_cfg;
+ struct octdev_props *props;
+ struct net_device *netdev;
+ struct lio_version *vdata;
+ struct lio *lio = NULL;
+ u8 mac[ETH_ALEN], i, j;
+ u32 ifidx_or_pfnum;
+
+ ifidx_or_pfnum = octeon_dev->pf_num;
+
+ /* This is to handle link status changes */
+ octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC, OPCODE_NIC_INFO,
+ lio_nic_info, octeon_dev);
+
+ /* REQTYPE_RESP_NET and REQTYPE_SOFT_COMMAND do not have free functions.
+ * They are handled directly.
+ */
+ octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET,
+ free_netbuf);
+
+ octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET_SG,
+ free_netsgbuf);
+
+ octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_RESP_NET_SG,
+ free_netsgbuf_with_resp);
+
+ for (i = 0; i < octeon_dev->ifcount; i++) {
+ resp_size = sizeof(struct liquidio_if_cfg_resp);
+ ctx_size = sizeof(struct liquidio_if_cfg_context);
+ data_size = sizeof(struct lio_version);
+ sc = (struct octeon_soft_command *)
+ octeon_alloc_soft_command(octeon_dev, data_size,
+ resp_size, ctx_size);
+ resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
+ ctx = (struct liquidio_if_cfg_context *)sc->ctxptr;
+ vdata = (struct lio_version *)sc->virtdptr;
+
+ *((u64 *)vdata) = 0;
+ vdata->major = cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION);
+ vdata->minor = cpu_to_be16(LIQUIDIO_BASE_MINOR_VERSION);
+ vdata->micro = cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION);
+
+ WRITE_ONCE(ctx->cond, 0);
+ ctx->octeon_id = lio_get_device_id(octeon_dev);
+ init_waitqueue_head(&ctx->wc);
+
+ if_cfg.u64 = 0;
+
+ if_cfg.s.num_iqueues = octeon_dev->sriov_info.rings_per_vf;
+ if_cfg.s.num_oqueues = octeon_dev->sriov_info.rings_per_vf;
+ if_cfg.s.base_queue = 0;
+
+ sc->iq_no = 0;
+
+ octeon_prepare_soft_command(octeon_dev, sc, OPCODE_NIC,
+ OPCODE_NIC_IF_CFG, 0, if_cfg.u64,
+ 0);
+
+ sc->callback = if_cfg_callback;
+ sc->callback_arg = sc;
+ sc->wait_time = 5000;
+
+ retval = octeon_send_soft_command(octeon_dev, sc);
+ if (retval == IQ_SEND_FAILED) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "iq/oq config failed status: %x\n", retval);
+ /* Soft instr is freed by driver in case of failure. */
+ goto setup_nic_dev_fail;
+ }
+
+ /* Sleep on a wait queue till the cond flag indicates that the
+ * response arrived or timed-out.
+ */
+ if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR) {
+ dev_err(&octeon_dev->pci_dev->dev, "Wait interrupted\n");
+ goto setup_nic_wait_intr;
+ }
+
+ retval = resp->status;
+ if (retval) {
+ dev_err(&octeon_dev->pci_dev->dev, "iq/oq config failed\n");
+ goto setup_nic_dev_fail;
+ }
+
+ octeon_swap_8B_data((u64 *)(&resp->cfg_info),
+ (sizeof(struct liquidio_if_cfg_info)) >> 3);
+
+ num_iqueues = hweight64(resp->cfg_info.iqmask);
+ num_oqueues = hweight64(resp->cfg_info.oqmask);
+
+ if (!(num_iqueues) || !(num_oqueues)) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "Got bad iqueues (%016llx) or oqueues (%016llx) from firmware.\n",
+ resp->cfg_info.iqmask, resp->cfg_info.oqmask);
+ goto setup_nic_dev_fail;
+ }
+ dev_dbg(&octeon_dev->pci_dev->dev,
+ "interface %d, iqmask %016llx, oqmask %016llx, numiqueues %d, numoqueues %d\n",
+ i, resp->cfg_info.iqmask, resp->cfg_info.oqmask,
+ num_iqueues, num_oqueues);
+
+ netdev = alloc_etherdev_mq(LIO_SIZE, num_iqueues);
+
+ if (!netdev) {
+ dev_err(&octeon_dev->pci_dev->dev, "Device allocation failed\n");
+ goto setup_nic_dev_fail;
+ }
+
+ SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev);
+
+ /* Associate the routines that will handle different
+ * netdev tasks.
+ */
+ netdev->netdev_ops = &lionetdevops;
+
+ lio = GET_LIO(netdev);
+
+ memset(lio, 0, sizeof(struct lio));
+
+ lio->ifidx = ifidx_or_pfnum;
+
+ props = &octeon_dev->props[i];
+ props->gmxport = resp->cfg_info.linfo.gmxport;
+ props->netdev = netdev;
+
+ lio->linfo.num_rxpciq = num_oqueues;
+ lio->linfo.num_txpciq = num_iqueues;
+
+ for (j = 0; j < num_oqueues; j++) {
+ lio->linfo.rxpciq[j].u64 =
+ resp->cfg_info.linfo.rxpciq[j].u64;
+ }
+ for (j = 0; j < num_iqueues; j++) {
+ lio->linfo.txpciq[j].u64 =
+ resp->cfg_info.linfo.txpciq[j].u64;
+ }
+
+ lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr;
+ lio->linfo.gmxport = resp->cfg_info.linfo.gmxport;
+ lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64;
+ lio->linfo.macaddr_is_admin_asgnd =
+ resp->cfg_info.linfo.macaddr_is_admin_asgnd;
+
+ lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
+
+ lio->dev_capability = NETIF_F_HIGHDMA
+ | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
+ | NETIF_F_SG | NETIF_F_RXCSUM
+ | NETIF_F_TSO | NETIF_F_TSO6
+ | NETIF_F_GRO
+ | NETIF_F_LRO;
+ netif_set_gso_max_size(netdev, OCTNIC_GSO_MAX_SIZE);
+
+ /* Copy of transmit encapsulation capabilities:
+ * TSO, TSO6, Checksums for this device
+ */
+ lio->enc_dev_capability = NETIF_F_IP_CSUM
+ | NETIF_F_IPV6_CSUM
+ | NETIF_F_GSO_UDP_TUNNEL
+ | NETIF_F_HW_CSUM | NETIF_F_SG
+ | NETIF_F_RXCSUM
+ | NETIF_F_TSO | NETIF_F_TSO6
+ | NETIF_F_LRO;
+
+ netdev->hw_enc_features =
+ (lio->enc_dev_capability & ~NETIF_F_LRO);
+ netdev->vlan_features = lio->dev_capability;
+ /* Add any unchangeable hw features */
+ lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_TX;
+
+ netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
+
+ netdev->hw_features = lio->dev_capability;
+
+ /* MTU range: 68 - 16000 */
+ netdev->min_mtu = LIO_MIN_MTU_SIZE;
+ netdev->max_mtu = LIO_MAX_MTU_SIZE;
+
+ /* Point to the properties for octeon device to which this
+ * interface belongs.
+ */
+ lio->oct_dev = octeon_dev;
+ lio->octprops = props;
+ lio->netdev = netdev;
+
+ dev_dbg(&octeon_dev->pci_dev->dev,
+ "if%d gmx: %d hw_addr: 0x%llx\n", i,
+ lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
+
+ /* 64-bit swap required on LE machines */
+ octeon_swap_8B_data(&lio->linfo.hw_addr, 1);
+ for (j = 0; j < ETH_ALEN; j++)
+ mac[j] = *((u8 *)(((u8 *)&lio->linfo.hw_addr) + 2 + j));
+
+ /* Copy MAC Address to OS network device structure */
+ ether_addr_copy(netdev->dev_addr, mac);
+
+ if (setup_io_queues(octeon_dev, i)) {
+ dev_err(&octeon_dev->pci_dev->dev, "I/O queues creation failed\n");
+ goto setup_nic_dev_fail;
+ }
+
+ ifstate_set(lio, LIO_IFSTATE_DROQ_OPS);
+
+ /* For VFs, enable Octeon device interrupts here,
+ * as this is contingent upon IO queue setup
+ */
+ octeon_dev->fn_list.enable_interrupt(octeon_dev,
+ OCTEON_ALL_INTR);
+
+ /* By default all interfaces on a single Octeon uses the same
+ * tx and rx queues
+ */
+ lio->txq = lio->linfo.txpciq[0].s.q_no;
+ lio->rxq = lio->linfo.rxpciq[0].s.q_no;
+
+ lio->tx_qsize = octeon_get_tx_qsize(octeon_dev, lio->txq);
+ lio->rx_qsize = octeon_get_rx_qsize(octeon_dev, lio->rxq);
+
+ if (setup_glists(lio, num_iqueues)) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "Gather list allocation failed\n");
+ goto setup_nic_dev_fail;
+ }
+
+ /* Register ethtool support */
+ liquidio_set_ethtool_ops(netdev);
+ if (lio->oct_dev->chip_id == OCTEON_CN23XX_VF_VID)
+ octeon_dev->priv_flags = OCT_PRIV_FLAG_DEFAULT;
+ else
+ octeon_dev->priv_flags = 0x0;
+
+ if (netdev->features & NETIF_F_LRO)
+ liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
+ OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+
+ if ((debug != -1) && (debug & NETIF_MSG_HW))
+ liquidio_set_feature(netdev, OCTNET_CMD_VERBOSE_ENABLE,
+ 0);
+
+ if (setup_link_status_change_wq(netdev))
+ goto setup_nic_dev_fail;
+
+ /* Register the network device with the OS */
+ if (register_netdev(netdev)) {
+ dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
+ goto setup_nic_dev_fail;
+ }
+
+ dev_dbg(&octeon_dev->pci_dev->dev,
+ "Setup NIC ifidx:%d mac:%02x%02x%02x%02x%02x%02x\n",
+ i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ netif_carrier_off(netdev);
+ lio->link_changes++;
+
+ ifstate_set(lio, LIO_IFSTATE_REGISTERED);
+
+ /* Sending command to firmware to enable Rx checksum offload
+ * by default at the time of setup of Liquidio driver for
+ * this device
+ */
+ liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+ OCTNET_CMD_RXCSUM_ENABLE);
+ liquidio_set_feature(netdev, OCTNET_CMD_TNL_TX_CSUM_CTL,
+ OCTNET_CMD_TXCSUM_ENABLE);
+
+ dev_dbg(&octeon_dev->pci_dev->dev,
+ "NIC ifidx:%d Setup successful\n", i);
+
+ octeon_free_soft_command(octeon_dev, sc);
+ }
+
+ return 0;
+
+setup_nic_dev_fail:
+
+ octeon_free_soft_command(octeon_dev, sc);
+
+setup_nic_wait_intr:
+
+ while (i--) {
+ dev_err(&octeon_dev->pci_dev->dev,
+ "NIC ifidx:%d Setup failed\n", i);
+ liquidio_destroy_nic_device(octeon_dev, i);
+ }
+ return -ENODEV;
+}
+
+/**
+ * \brief initialize the NIC
+ * @param oct octeon device
+ *
+ * This initialization routine is called once the Octeon device application is
+ * up and running
+ */
+static int liquidio_init_nic_module(struct octeon_device *oct)
+{
+ struct oct_intrmod_cfg *intrmod_cfg;
+ int num_nic_ports = 1;
+ int i, retval = 0;
+
+ dev_dbg(&oct->pci_dev->dev, "Initializing network interfaces\n");
+
+ /* only default iq and oq were initialized
+ * initialize the rest as well run port_config command for each port
+ */
+ oct->ifcount = num_nic_ports;
+ memset(oct->props, 0,
+ sizeof(struct octdev_props) * num_nic_ports);
+
+ for (i = 0; i < MAX_OCTEON_LINKS; i++)
+ oct->props[i].gmxport = -1;
+
+ retval = setup_nic_devices(oct);
+ if (retval) {
+ dev_err(&oct->pci_dev->dev, "Setup NIC devices failed\n");
+ goto octnet_init_failure;
+ }
+
+ /* Initialize interrupt moderation params */
+ intrmod_cfg = &((struct octeon_device *)oct)->intrmod;
+ intrmod_cfg->rx_enable = 1;
+ intrmod_cfg->check_intrvl = LIO_INTRMOD_CHECK_INTERVAL;
+ intrmod_cfg->maxpkt_ratethr = LIO_INTRMOD_MAXPKT_RATETHR;
+ intrmod_cfg->minpkt_ratethr = LIO_INTRMOD_MINPKT_RATETHR;
+ intrmod_cfg->rx_maxcnt_trigger = LIO_INTRMOD_RXMAXCNT_TRIGGER;
+ intrmod_cfg->rx_maxtmr_trigger = LIO_INTRMOD_RXMAXTMR_TRIGGER;
+ intrmod_cfg->rx_mintmr_trigger = LIO_INTRMOD_RXMINTMR_TRIGGER;
+ intrmod_cfg->rx_mincnt_trigger = LIO_INTRMOD_RXMINCNT_TRIGGER;
+ intrmod_cfg->tx_enable = 1;
+ intrmod_cfg->tx_maxcnt_trigger = LIO_INTRMOD_TXMAXCNT_TRIGGER;
+ intrmod_cfg->tx_mincnt_trigger = LIO_INTRMOD_TXMINCNT_TRIGGER;
+ intrmod_cfg->rx_frames = CFG_GET_OQ_INTR_PKT(octeon_get_conf(oct));
+ intrmod_cfg->rx_usecs = CFG_GET_OQ_INTR_TIME(octeon_get_conf(oct));
+ intrmod_cfg->tx_frames = CFG_GET_IQ_INTR_PKT(octeon_get_conf(oct));
+ dev_dbg(&oct->pci_dev->dev, "Network interfaces ready\n");
+
+ return retval;
+
+octnet_init_failure:
+
+ oct->ifcount = 0;
+
+ return retval;
+}
+
+/**
+ * \brief Device initialization for each Octeon device that is probed
+ * @param octeon_dev octeon device
+ */
+static int octeon_device_init(struct octeon_device *oct)
+{
+ u32 rev_id;
+ int j;
+
+ atomic_set(&oct->status, OCT_DEV_BEGIN_STATE);
+
+ /* Enable access to the octeon device and make its DMA capability
+ * known to the OS.
+ */
+ if (octeon_pci_os_setup(oct))
+ return 1;
+ atomic_set(&oct->status, OCT_DEV_PCI_ENABLE_DONE);
+
+ oct->chip_id = OCTEON_CN23XX_VF_VID;
+ pci_read_config_dword(oct->pci_dev, 8, &rev_id);
+ oct->rev_id = rev_id & 0xff;
+
+ if (cn23xx_setup_octeon_vf_device(oct))
+ return 1;
+
+ atomic_set(&oct->status, OCT_DEV_PCI_MAP_DONE);
+
+ oct->app_mode = CVM_DRV_NIC_APP;
+
+ /* Initialize the dispatch mechanism used to push packets arriving on
+ * Octeon Output queues.
+ */
+ if (octeon_init_dispatch_list(oct))
+ return 1;
+
+ atomic_set(&oct->status, OCT_DEV_DISPATCH_INIT_DONE);
+
+ if (octeon_set_io_queues_off(oct)) {
+ dev_err(&oct->pci_dev->dev, "setting io queues off failed\n");
+ return 1;
+ }
+
+ if (oct->fn_list.setup_device_regs(oct)) {
+ dev_err(&oct->pci_dev->dev, "device registers configuration failed\n");
+ return 1;
+ }
+
+ /* Initialize soft command buffer pool */
+ if (octeon_setup_sc_buffer_pool(oct)) {
+ dev_err(&oct->pci_dev->dev, "sc buffer pool allocation failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_SC_BUFF_POOL_INIT_DONE);
+
+ /* Setup the data structures that manage this Octeon's Input queues. */
+ if (octeon_setup_instr_queues(oct)) {
+ dev_err(&oct->pci_dev->dev, "instruction queue initialization failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_INSTR_QUEUE_INIT_DONE);
+
+ /* Initialize lists to manage the requests of different types that
+ * arrive from user & kernel applications for this octeon device.
+ */
+ if (octeon_setup_response_list(oct)) {
+ dev_err(&oct->pci_dev->dev, "Response list allocation failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_RESP_LIST_INIT_DONE);
+
+ if (octeon_setup_output_queues(oct)) {
+ dev_err(&oct->pci_dev->dev, "Output queue initialization failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE);
+
+ if (oct->fn_list.setup_mbox(oct)) {
+ dev_err(&oct->pci_dev->dev, "Mailbox setup failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_MBOX_SETUP_DONE);
+
+ if (octeon_allocate_ioq_vector(oct)) {
+ dev_err(&oct->pci_dev->dev, "ioq vector allocation failed\n");
+ return 1;
+ }
+ atomic_set(&oct->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE);
+
+ dev_info(&oct->pci_dev->dev, "OCTEON_CN23XX VF Version: %s, %d ioqs\n",
+ LIQUIDIO_VERSION, oct->sriov_info.rings_per_vf);
+
+ /* Setup the interrupt handler and record the INT SUM register address*/
+ if (octeon_setup_interrupt(oct))
+ return 1;
+
+ if (cn23xx_octeon_pfvf_handshake(oct))
+ return 1;
+
+ /* Enable Octeon device interrupts */
+ oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
+
+ atomic_set(&oct->status, OCT_DEV_INTR_SET_DONE);
+
+ /* Enable the input and output queues for this Octeon device */
+ if (oct->fn_list.enable_io_queues(oct)) {
+ dev_err(&oct->pci_dev->dev, "enabling io queues failed\n");
+ return 1;
+ }
+
+ atomic_set(&oct->status, OCT_DEV_IO_QUEUES_DONE);
+
+ atomic_set(&oct->status, OCT_DEV_HOST_OK);
+
+ /* Send Credit for Octeon Output queues. Credits are always sent after
+ * the output queue is enabled.
+ */
+ for (j = 0; j < oct->num_oqs; j++)
+ writel(oct->droq[j]->max_count, oct->droq[j]->pkts_credit_reg);
+
+ /* Packets can start arriving on the output queues from this point. */
+
+ atomic_set(&oct->status, OCT_DEV_CORE_OK);
+
+ atomic_set(&oct->status, OCT_DEV_RUNNING);
+
+ if (liquidio_init_nic_module(oct))
+ return 1;
+
+ return 0;
+}
+
+static int __init liquidio_vf_init(void)
+{
+ octeon_init_device_list(0);
+ return pci_register_driver(&liquidio_vf_pci_driver);
+}
+
+static void __exit liquidio_vf_exit(void)
+{
+ pci_unregister_driver(&liquidio_vf_pci_driver);
+
+ pr_info("LiquidIO_VF network module is now unloaded\n");
+}
+
+module_init(liquidio_vf_init);
+module_exit(liquidio_vf_exit);
diff --git a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
index 0d990accb65e..ba329f6ca779 100644
--- a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
+++ b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file liquidio_common.h
* \brief Common: Structures and macros used in PCI-NIC package by core and
* host driver.
@@ -68,12 +63,10 @@ enum octeon_tag_type {
*/
#define OPCODE_CORE 0 /* used for generic core operations */
#define OPCODE_NIC 1 /* used for NIC operations */
-#define OPCODE_LAST OPCODE_NIC
-
/* Subcodes are used by host driver/apps to identify the sub-operation
* for the core. They only need to by unique for a given subsystem.
*/
-#define OPCODE_SUBCODE(op, sub) (((op & 0x0f) << 8) | ((sub) & 0x7f))
+#define OPCODE_SUBCODE(op, sub) ((((op) & 0x0f) << 8) | ((sub) & 0x7f))
/** OPCODE_CORE subcodes. For future use. */
@@ -89,13 +82,13 @@ enum octeon_tag_type {
#define OPCODE_NIC_TIMESTAMP 0x07
#define OPCODE_NIC_INTRMOD_CFG 0x08
#define OPCODE_NIC_IF_CFG 0x09
+#define OPCODE_NIC_VF_DRV_NOTICE 0x0A
+#define VF_DRV_LOADED 1
+#define VF_DRV_REMOVED -1
+#define VF_DRV_MACADDR_CHANGED 2
#define CORE_DRV_TEST_SCATTER_OP 0xFFF5
-#define OPCODE_SLOW_PATH(rh) \
- (OPCODE_SUBCODE(rh->r.opcode, rh->r.subcode) != \
- OPCODE_SUBCODE(OPCODE_NIC, OPCODE_NIC_NW_DATA))
-
/* Application codes advertised by the core driver initialization packet. */
#define CVM_DRV_APP_START 0x0
#define CVM_DRV_NO_APP 0
@@ -105,31 +98,15 @@ enum octeon_tag_type {
#define CVM_DRV_INVALID_APP (CVM_DRV_APP_START + 0x2)
#define CVM_DRV_APP_END (CVM_DRV_INVALID_APP - 1)
-/* Macro to increment index.
- * Index is incremented by count; if the sum exceeds
- * max, index is wrapped-around to the start.
- */
-#define INCR_INDEX(index, count, max) \
-do { \
- if (((index) + (count)) >= (max)) \
- index = ((index) + (count)) - (max); \
- else \
- index += (count); \
-} while (0)
-
-#define INCR_INDEX_BY1(index, max) \
-do { \
- if ((++(index)) == (max)) \
- index = 0; \
-} while (0)
-
-#define DECR_INDEX(index, count, max) \
-do { \
- if ((count) > (index)) \
- index = ((max) - ((count - index))); \
- else \
- index -= count; \
-} while (0)
+static inline u32 incr_index(u32 index, u32 count, u32 max)
+{
+ if ((index + count) >= max)
+ index = index + count - max;
+ else
+ index += count;
+
+ return index;
+}
#define OCT_BOARD_NAME 32
#define OCT_SERIAL_LEN 64
@@ -235,6 +212,8 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,
#define OCTNET_CMD_ID_ACTIVE 0x1a
+#define OCTNET_CMD_SET_UC_LIST 0x1b
+#define OCTNET_CMD_SET_VF_LINKSTATE 0x1c
#define OCTNET_CMD_VXLAN_PORT_ADD 0x0
#define OCTNET_CMD_VXLAN_PORT_DEL 0x1
#define OCTNET_CMD_RXCSUM_ENABLE 0x0
@@ -731,13 +710,15 @@ struct oct_link_info {
#ifdef __BIG_ENDIAN_BITFIELD
u64 gmxport:16;
- u64 rsvd:32;
+ u64 macaddr_is_admin_asgnd:1;
+ u64 rsvd:31;
u64 num_txpciq:8;
u64 num_rxpciq:8;
#else
u64 num_rxpciq:8;
u64 num_txpciq:8;
- u64 rsvd:32;
+ u64 rsvd:31;
+ u64 macaddr_is_admin_asgnd:1;
u64 gmxport:16;
#endif
@@ -827,6 +808,16 @@ struct oct_link_stats {
};
+static inline int opcode_slow_path(union octeon_rh *rh)
+{
+ u16 subcode1, subcode2;
+
+ subcode1 = OPCODE_SUBCODE((rh)->r.opcode, (rh)->r.subcode);
+ subcode2 = OPCODE_SUBCODE(OPCODE_NIC, OPCODE_NIC_NW_DATA);
+
+ return (subcode2 != subcode1);
+}
+
#define LIO68XX_LED_CTRL_ADDR 0x3501
#define LIO68XX_LED_CTRL_CFGON 0x1f
#define LIO68XX_LED_CTRL_CFGOFF 0x100
diff --git a/drivers/net/ethernet/cavium/liquidio/liquidio_image.h b/drivers/net/ethernet/cavium/liquidio/liquidio_image.h
index 93819bd8602b..78a3685f6fe0 100644
--- a/drivers/net/ethernet/cavium/liquidio/liquidio_image.h
+++ b/drivers/net/ethernet/cavium/liquidio/liquidio_image.h
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#ifndef _LIQUIDIO_IMAGE_H_
#define _LIQUIDIO_IMAGE_H_
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_config.h b/drivers/net/ethernet/cavium/liquidio/octeon_config.h
index c76556809ed1..1cb3514fc949 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_config.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_config.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file octeon_config.h
* \brief Host Driver: Configuration data structures for the host driver.
*/
@@ -65,9 +60,15 @@
#define DEFAULT_NUM_NIC_PORTS_68XX_210NV 2
/* CN23xx IQ configuration macros */
+#define CN23XX_MAX_VFS_PER_PF_PASS_1_0 8
+#define CN23XX_MAX_VFS_PER_PF_PASS_1_1 31
+#define CN23XX_MAX_VFS_PER_PF 63
+#define CN23XX_MAX_RINGS_PER_VF 8
+
#define CN23XX_MAX_RINGS_PER_PF_PASS_1_0 12
#define CN23XX_MAX_RINGS_PER_PF_PASS_1_1 32
#define CN23XX_MAX_RINGS_PER_PF 64
+#define CN23XX_MAX_RINGS_PER_VF 8
#define CN23XX_MAX_INPUT_QUEUES CN23XX_MAX_RINGS_PER_PF
#define CN23XX_MAX_IQ_DESCRIPTORS 2048
@@ -466,4 +467,7 @@ struct octeon_config {
#define MAX_POSSIBLE_OCTEON_INSTR_QUEUES CN23XX_MAX_INPUT_QUEUES
#define MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES CN23XX_MAX_OUTPUT_QUEUES
+
+#define MAX_POSSIBLE_VFS 64
+
#endif /* __OCTEON_CONFIG_H__ */
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_console.c b/drivers/net/ethernet/cavium/liquidio/octeon_console.c
index 01a50f3b0c8e..3265e0b7923e 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_console.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_console.c
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/**
* @file octeon_console.c
*/
@@ -76,9 +71,9 @@ MODULE_PARM_DESC(console_bitmask,
#define OCTEON_CONSOLE_POLL_INTERVAL_MS 100 /* 10 times per second */
/* First three members of cvmx_bootmem_desc are left in original
-** positions for backwards compatibility.
-** Assumes big endian target
-*/
+ * positions for backwards compatibility.
+ * Assumes big endian target
+ */
struct cvmx_bootmem_desc {
/** spinlock to control access to list */
u32 lock;
@@ -143,46 +138,6 @@ struct octeon_pci_console_desc {
};
/**
- * This macro returns the size of a member of a structure.
- * Logically it is the same as "sizeof(s::field)" in C++, but
- * C lacks the "::" operator.
- */
-#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field)
-
-/**
- * This macro returns a member of the cvmx_bootmem_desc
- * structure. These members can't be directly addressed as
- * they might be in memory not directly reachable. In the case
- * where bootmem is compiled with LINUX_HOST, the structure
- * itself might be located on a remote Octeon. The argument
- * "field" is the member name of the cvmx_bootmem_desc to read.
- * Regardless of the type of the field, the return type is always
- * a u64.
- */
-#define CVMX_BOOTMEM_DESC_GET_FIELD(oct, field) \
- __cvmx_bootmem_desc_get(oct, oct->bootmem_desc_addr, \
- offsetof(struct cvmx_bootmem_desc, field), \
- SIZEOF_FIELD(struct cvmx_bootmem_desc, field))
-
-#define __cvmx_bootmem_lock(flags) (flags = flags)
-#define __cvmx_bootmem_unlock(flags) (flags = flags)
-
-/**
- * This macro returns a member of the
- * cvmx_bootmem_named_block_desc structure. These members can't
- * be directly addressed as they might be in memory not directly
- * reachable. In the case where bootmem is compiled with
- * LINUX_HOST, the structure itself might be located on a remote
- * Octeon. The argument "field" is the member name of the
- * cvmx_bootmem_named_block_desc to read. Regardless of the type
- * of the field, the return type is always a u64. The "addr"
- * parameter is the physical address of the structure.
- */
-#define CVMX_BOOTMEM_NAMED_GET_FIELD(oct, addr, field) \
- __cvmx_bootmem_desc_get(oct, addr, \
- offsetof(struct cvmx_bootmem_named_block_desc, field), \
- SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
-/**
* \brief determines if a given console has debug enabled.
* @param console console to check
* @returns 1 = enabled. 0 otherwise
@@ -263,10 +218,15 @@ static int __cvmx_bootmem_check_version(struct octeon_device *oct,
oct->bootmem_desc_addr =
octeon_read_device_mem64(oct,
BOOTLOADER_PCI_READ_DESC_ADDR);
- major_version =
- (u32)CVMX_BOOTMEM_DESC_GET_FIELD(oct, major_version);
- minor_version =
- (u32)CVMX_BOOTMEM_DESC_GET_FIELD(oct, minor_version);
+ major_version = (u32)__cvmx_bootmem_desc_get(
+ oct, oct->bootmem_desc_addr,
+ offsetof(struct cvmx_bootmem_desc, major_version),
+ FIELD_SIZEOF(struct cvmx_bootmem_desc, major_version));
+ minor_version = (u32)__cvmx_bootmem_desc_get(
+ oct, oct->bootmem_desc_addr,
+ offsetof(struct cvmx_bootmem_desc, minor_version),
+ FIELD_SIZEOF(struct cvmx_bootmem_desc, minor_version));
+
dev_dbg(&oct->pci_dev->dev, "%s: major_version=%d\n", __func__,
major_version);
if ((major_version > 3) ||
@@ -289,10 +249,20 @@ static const struct cvmx_bootmem_named_block_desc
u64 named_addr = cvmx_bootmem_phy_named_block_find(oct, name, flags);
if (named_addr) {
- desc->base_addr = CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr,
- base_addr);
- desc->size =
- CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr, size);
+ desc->base_addr = __cvmx_bootmem_desc_get(
+ oct, named_addr,
+ offsetof(struct cvmx_bootmem_named_block_desc,
+ base_addr),
+ FIELD_SIZEOF(
+ struct cvmx_bootmem_named_block_desc,
+ base_addr));
+ desc->size = __cvmx_bootmem_desc_get(oct, named_addr,
+ offsetof(struct cvmx_bootmem_named_block_desc,
+ size),
+ FIELD_SIZEOF(
+ struct cvmx_bootmem_named_block_desc,
+ size));
+
strncpy(desc->name, name, sizeof(desc->name));
desc->name[sizeof(desc->name) - 1] = 0;
return &oct->bootmem_named_block_desc;
@@ -307,22 +277,41 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
{
u64 result = 0;
- __cvmx_bootmem_lock(flags);
if (!__cvmx_bootmem_check_version(oct, 3)) {
u32 i;
- u64 named_block_array_addr =
- CVMX_BOOTMEM_DESC_GET_FIELD(oct,
- named_block_array_addr);
- u32 num_blocks = (u32)
- CVMX_BOOTMEM_DESC_GET_FIELD(oct, nb_num_blocks);
- u32 name_length = (u32)
- CVMX_BOOTMEM_DESC_GET_FIELD(oct, named_block_name_len);
+
+ u64 named_block_array_addr = __cvmx_bootmem_desc_get(
+ oct, oct->bootmem_desc_addr,
+ offsetof(struct cvmx_bootmem_desc,
+ named_block_array_addr),
+ FIELD_SIZEOF(struct cvmx_bootmem_desc,
+ named_block_array_addr));
+ u32 num_blocks = (u32)__cvmx_bootmem_desc_get(
+ oct, oct->bootmem_desc_addr,
+ offsetof(struct cvmx_bootmem_desc,
+ nb_num_blocks),
+ FIELD_SIZEOF(struct cvmx_bootmem_desc,
+ nb_num_blocks));
+
+ u32 name_length = (u32)__cvmx_bootmem_desc_get(
+ oct, oct->bootmem_desc_addr,
+ offsetof(struct cvmx_bootmem_desc,
+ named_block_name_len),
+ FIELD_SIZEOF(struct cvmx_bootmem_desc,
+ named_block_name_len));
+
u64 named_addr = named_block_array_addr;
for (i = 0; i < num_blocks; i++) {
- u64 named_size =
- CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr,
- size);
+ u64 named_size = __cvmx_bootmem_desc_get(
+ oct, named_addr,
+ offsetof(
+ struct cvmx_bootmem_named_block_desc,
+ size),
+ FIELD_SIZEOF(
+ struct cvmx_bootmem_named_block_desc,
+ size));
+
if (name && named_size) {
char *name_tmp =
kmalloc(name_length + 1, GFP_KERNEL);
@@ -347,7 +336,6 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
sizeof(struct cvmx_bootmem_named_block_desc);
}
}
- __cvmx_bootmem_unlock(flags);
return result;
}
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index 586b68899b06..a8df493a5012 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
@@ -32,6 +28,7 @@
#include "cn66xx_regs.h"
#include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
+#include "cn23xx_vf_device.h"
/** Default configuration
* for CN66XX OCTEON Models.
@@ -520,11 +517,6 @@ static struct octeon_config default_cn23xx_conf = {
}
};
-enum {
- OCTEON_CONFIG_TYPE_DEFAULT = 0,
- NUM_OCTEON_CONFS,
-};
-
static struct octeon_config_ptr {
u32 conf_type;
} oct_conf_info[MAX_OCTEON_DEVICES] = {
@@ -580,15 +572,17 @@ static void *__retrieve_octeon_config_info(struct octeon_device *oct,
switch (oct_conf_info[oct_id].conf_type) {
case OCTEON_CONFIG_TYPE_DEFAULT:
if (oct->chip_id == OCTEON_CN66XX) {
- ret = (void *)&default_cn66xx_conf;
+ ret = &default_cn66xx_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_210NV)) {
- ret = (void *)&default_cn68xx_210nv_conf;
+ ret = &default_cn68xx_210nv_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_410NV)) {
- ret = (void *)&default_cn68xx_conf;
+ ret = &default_cn68xx_conf;
} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
- ret = (void *)&default_cn23xx_conf;
+ ret = &default_cn23xx_conf;
+ } else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
+ ret = &default_cn23xx_conf;
}
break;
default:
@@ -604,6 +598,7 @@ static int __verify_octeon_config_info(struct octeon_device *oct, void *conf)
case OCTEON_CN68XX:
return lio_validate_cn6xxx_config_info(oct, conf);
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
return 0;
default:
break;
@@ -649,12 +644,12 @@ void octeon_free_device_mem(struct octeon_device *oct)
int i;
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
- if (oct->io_qmask.oq & (1ULL << i))
+ if (oct->io_qmask.oq & BIT_ULL(i))
vfree(oct->droq[i]);
}
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
- if (oct->io_qmask.iq & (1ULL << i))
+ if (oct->io_qmask.iq & BIT_ULL(i))
vfree(oct->instr_queue[i]);
}
@@ -681,6 +676,9 @@ static struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
case OCTEON_CN23XX_PF_VID:
configsize = sizeof(struct octeon_cn23xx_pf);
break;
+ case OCTEON_CN23XX_VF_VID:
+ configsize = sizeof(struct octeon_cn23xx_vf);
+ break;
default:
pr_err("%s: Unknown PCI Device: 0x%x\n",
__func__,
@@ -756,6 +754,9 @@ octeon_allocate_ioq_vector(struct octeon_device *oct)
if (OCTEON_CN23XX_PF(oct))
num_ioqs = oct->sriov_info.num_pf_rings;
+ else if (OCTEON_CN23XX_VF(oct))
+ num_ioqs = oct->sriov_info.rings_per_vf;
+
size = sizeof(struct octeon_ioq_vector) * num_ioqs;
oct->ioq_vector = vmalloc(size);
@@ -767,6 +768,7 @@ octeon_allocate_ioq_vector(struct octeon_device *oct)
ioq_vector->oct_dev = oct;
ioq_vector->iq_index = i;
ioq_vector->droq_index = i;
+ ioq_vector->mbox = oct->mbox[i];
cpu_num = i % num_online_cpus();
cpumask_set_cpu(cpu_num, &ioq_vector->affinity_mask);
@@ -795,10 +797,11 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
if (OCTEON_CN6XXX(oct))
num_descs =
- CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
+ CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx));
else if (OCTEON_CN23XX_PF(oct))
- num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn23xx_pf,
- conf));
+ num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf));
+ else if (OCTEON_CN23XX_VF(oct))
+ num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_vf));
oct->num_iqs = 0;
@@ -821,6 +824,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
if (octeon_init_instr_queue(oct, txpciq, num_descs)) {
/* prevent memory leak */
vfree(oct->instr_queue[0]);
+ oct->instr_queue[0] = NULL;
return 1;
}
@@ -837,14 +841,15 @@ int octeon_setup_output_queues(struct octeon_device *oct)
if (OCTEON_CN6XXX(oct)) {
num_descs =
- CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
+ CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn6xxx));
desc_size =
- CFG_GET_DEF_RX_BUF_SIZE(CHIP_FIELD(oct, cn6xxx, conf));
+ CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn6xxx));
} else if (OCTEON_CN23XX_PF(oct)) {
- num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn23xx_pf,
- conf));
- desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_FIELD(oct, cn23xx_pf,
- conf));
+ num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf));
+ desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf));
+ } else if (OCTEON_CN23XX_VF(oct)) {
+ num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_vf));
+ desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_vf));
}
oct->num_oqs = 0;
oct->droq[0] = vmalloc_node(sizeof(*oct->droq[0]), numa_node);
@@ -853,19 +858,63 @@ int octeon_setup_output_queues(struct octeon_device *oct)
if (!oct->droq[0])
return 1;
- if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL))
+ if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL)) {
+ vfree(oct->droq[oq_no]);
+ oct->droq[oq_no] = NULL;
return 1;
+ }
oct->num_oqs++;
return 0;
}
-void octeon_set_io_queues_off(struct octeon_device *oct)
+int octeon_set_io_queues_off(struct octeon_device *oct)
{
+ int loop = BUSY_READING_REG_VF_LOOP_COUNT;
+
if (OCTEON_CN6XXX(oct)) {
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
+ } else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
+ u32 q_no;
+
+ /* IOQs will already be in reset.
+ * If RST bit is set, wait for quiet bit to be set.
+ * Once quiet bit is set, clear the RST bit.
+ */
+ for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
+ u64 reg_val = octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+
+ while ((reg_val & CN23XX_PKT_INPUT_CTL_RST) &&
+ !(reg_val & CN23XX_PKT_INPUT_CTL_QUIET) &&
+ loop) {
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
+ loop--;
+ }
+ if (!loop) {
+ dev_err(&oct->pci_dev->dev,
+ "clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
+ q_no);
+ return -1;
+ }
+
+ reg_val = reg_val & ~CN23XX_PKT_INPUT_CTL_RST;
+ octeon_write_csr64(oct,
+ CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
+ reg_val);
+
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
+ if (reg_val & CN23XX_PKT_INPUT_CTL_RST) {
+ dev_err(&oct->pci_dev->dev,
+ "unable to reset qno %u\n", q_no);
+ return -1;
+ }
+ }
}
+ return 0;
}
void octeon_set_droq_pkt_op(struct octeon_device *oct,
@@ -1070,10 +1119,10 @@ int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
if (OCTEON_CN6XXX(oct))
num_nic_ports =
- CFG_GET_NUM_NIC_PORTS(CHIP_FIELD(oct, cn6xxx, conf));
+ CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn6xxx));
else if (OCTEON_CN23XX_PF(oct))
num_nic_ports =
- CFG_GET_NUM_NIC_PORTS(CHIP_FIELD(oct, cn23xx_pf, conf));
+ CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn23xx_pf));
if (atomic_read(&oct->status) >= OCT_DEV_RUNNING) {
dev_err(&oct->pci_dev->dev, "Received CORE OK when device state is 0x%x\n",
@@ -1143,7 +1192,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
{
if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES(oct)) &&
- (oct->io_qmask.iq & (1ULL << q_no)))
+ (oct->io_qmask.iq & BIT_ULL(q_no)))
return oct->instr_queue[q_no]->max_count;
return -1;
@@ -1152,7 +1201,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
{
if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES(oct)) &&
- (oct->io_qmask.oq & (1ULL << q_no)))
+ (oct->io_qmask.oq & BIT_ULL(q_no)))
return oct->droq[q_no]->max_count;
return -1;
}
@@ -1168,10 +1217,13 @@ struct octeon_config *octeon_get_conf(struct octeon_device *oct)
if (OCTEON_CN6XXX(oct)) {
default_oct_conf =
- (struct octeon_config *)(CHIP_FIELD(oct, cn6xxx, conf));
+ (struct octeon_config *)(CHIP_CONF(oct, cn6xxx));
} else if (OCTEON_CN23XX_PF(oct)) {
default_oct_conf = (struct octeon_config *)
- (CHIP_FIELD(oct, cn23xx_pf, conf));
+ (CHIP_CONF(oct, cn23xx_pf));
+ } else if (OCTEON_CN23XX_VF(oct)) {
+ default_oct_conf = (struct octeon_config *)
+ (CHIP_CONF(oct, cn23xx_vf));
}
return default_oct_conf;
}
@@ -1322,7 +1374,7 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
/*write resend. Writing RESEND in SLI_PKTX_CNTS should be enough
*to trigger tx interrupts as well, if they are pending.
*/
- if (oct && OCTEON_CN23XX_PF(oct)) {
+ if (oct && (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))) {
if (droq)
writeq(CN23XX_INTR_RESEND, droq->pkts_sent_reg);
/*we race with firmrware here. read and write the IN_DONE_CNTS*/
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
index da15c2ae9330..18f6836250a6 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
@@ -1,25 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file octeon_device.h
* \brief Host Driver: This file defines the octeon device structure.
*/
@@ -38,6 +33,7 @@
#define OCTEON_CN68XX 0x0091
#define OCTEON_CN66XX 0x0092
#define OCTEON_CN23XX_PF_VID 0x9702
+#define OCTEON_CN23XX_VF_VID 0x9712
/**RevisionId for the chips */
#define OCTEON_CN23XX_REV_1_0 0x00
@@ -52,7 +48,14 @@ enum octeon_pci_swap_mode {
OCTEON_PCI_32BIT_LW_SWAP = 3
};
+enum {
+ OCTEON_CONFIG_TYPE_DEFAULT = 0,
+ NUM_OCTEON_CONFS,
+};
+
+#define OCTEON_INPUT_INTR (1)
#define OCTEON_OUTPUT_INTR (2)
+#define OCTEON_MBOX_INTR (4)
#define OCTEON_ALL_INTR 0xff
/*--------------- PCI BAR1 index registers -------------*/
@@ -70,26 +73,30 @@ enum octeon_pci_swap_mode {
* as it is initialized.
*/
#define OCT_DEV_BEGIN_STATE 0x0
-#define OCT_DEV_PCI_MAP_DONE 0x1
-#define OCT_DEV_DISPATCH_INIT_DONE 0x2
-#define OCT_DEV_INSTR_QUEUE_INIT_DONE 0x3
-#define OCT_DEV_SC_BUFF_POOL_INIT_DONE 0x4
-#define OCT_DEV_RESP_LIST_INIT_DONE 0x5
-#define OCT_DEV_DROQ_INIT_DONE 0x6
-#define OCT_DEV_IO_QUEUES_DONE 0x7
-#define OCT_DEV_CONSOLE_INIT_DONE 0x8
-#define OCT_DEV_HOST_OK 0x9
-#define OCT_DEV_CORE_OK 0xa
-#define OCT_DEV_RUNNING 0xb
-#define OCT_DEV_IN_RESET 0xc
-#define OCT_DEV_STATE_INVALID 0xd
+#define OCT_DEV_PCI_ENABLE_DONE 0x1
+#define OCT_DEV_PCI_MAP_DONE 0x2
+#define OCT_DEV_DISPATCH_INIT_DONE 0x3
+#define OCT_DEV_INSTR_QUEUE_INIT_DONE 0x4
+#define OCT_DEV_SC_BUFF_POOL_INIT_DONE 0x5
+#define OCT_DEV_RESP_LIST_INIT_DONE 0x6
+#define OCT_DEV_DROQ_INIT_DONE 0x7
+#define OCT_DEV_MBOX_SETUP_DONE 0x8
+#define OCT_DEV_MSIX_ALLOC_VECTOR_DONE 0x9
+#define OCT_DEV_INTR_SET_DONE 0xa
+#define OCT_DEV_IO_QUEUES_DONE 0xb
+#define OCT_DEV_CONSOLE_INIT_DONE 0xc
+#define OCT_DEV_HOST_OK 0xd
+#define OCT_DEV_CORE_OK 0xe
+#define OCT_DEV_RUNNING 0xf
+#define OCT_DEV_IN_RESET 0x10
+#define OCT_DEV_STATE_INVALID 0x11
#define OCT_DEV_STATES OCT_DEV_STATE_INVALID
/** Octeon Device interrupts
- * These interrupt bits are set in int_status filed of
- * octeon_device structure
- */
+ * These interrupt bits are set in int_status filed of
+ * octeon_device structure
+ */
#define OCT_DEV_INTR_DMA0_FORCE 0x01
#define OCT_DEV_INTR_DMA1_FORCE 0x02
#define OCT_DEV_INTR_PKT_DATA 0x04
@@ -208,6 +215,10 @@ struct octeon_fn_list {
irqreturn_t (*process_interrupt_regs)(void *);
u64 (*msix_interrupt_handler)(void *);
+
+ int (*setup_mbox)(struct octeon_device *);
+ int (*free_mbox)(struct octeon_device *);
+
int (*soft_reset)(struct octeon_device *);
int (*setup_device_regs)(struct octeon_device *);
void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int);
@@ -284,6 +295,7 @@ struct octdev_props {
#define LIO_FLAG_MSIX_ENABLED 0x1
#define MSIX_PO_INT 0x1
#define MSIX_PI_INT 0x2
+#define MSIX_MBOX_INT 0x4
struct octeon_pf_vf_hs_word {
#ifdef __LITTLE_ENDIAN_BITFIELD
@@ -322,14 +334,39 @@ struct octeon_pf_vf_hs_word {
};
struct octeon_sriov_info {
+ /* Number of rings assigned to VF */
+ u32 rings_per_vf;
+
+ /** Max Number of VF devices that can be enabled. This variable can
+ * specified during load time or it will be derived after allocating
+ * PF queues. When max_vfs is derived then each VF will get one queue
+ **/
+ u32 max_vfs;
+
+ /** Number of VF devices enabled using sysfs. */
+ u32 num_vfs_alloced;
+
/* Actual rings left for PF device */
u32 num_pf_rings;
- /* SRN of PF usable IO queues */
+ /* SRN of PF usable IO queues */
u32 pf_srn;
+
/* total pf rings */
u32 trs;
+ u32 sriov_enabled;
+
+ /*lookup table that maps DPI ring number to VF pci_dev struct pointer*/
+ struct pci_dev *dpiring_to_vfpcidev_lut[MAX_POSSIBLE_VFS];
+
+ u64 vf_macaddr[MAX_POSSIBLE_VFS];
+
+ u16 vf_vlantci[MAX_POSSIBLE_VFS];
+
+ int vf_linkstate[MAX_POSSIBLE_VFS];
+
+ u64 vf_drv_loaded_mask;
};
struct octeon_ioq_vector {
@@ -337,6 +374,7 @@ struct octeon_ioq_vector {
int iq_index;
int droq_index;
int vector;
+ struct octeon_mbox *mbox;
struct cpumask affinity_mask;
u32 ioq_num;
};
@@ -365,8 +403,13 @@ struct octeon_device {
/** Octeon Chip type. */
u16 chip_id;
+
u16 rev_id;
+
u16 pf_num;
+
+ u16 vf_num;
+
/** This device's id - set by the driver. */
u32 octeon_id;
@@ -474,6 +517,9 @@ struct octeon_device {
int msix_on;
+ /** Mail Box details of each octeon queue. */
+ struct octeon_mbox *mbox[MAX_POSSIBLE_VFS];
+
/** IOq information of it's corresponding MSI-X interrupt. */
struct octeon_ioq_vector *ioq_vector;
@@ -490,11 +536,14 @@ struct octeon_device {
#define OCT_DRV_ONLINE 1
#define OCT_DRV_OFFLINE 2
-#define OCTEON_CN6XXX(oct) ((oct->chip_id == OCTEON_CN66XX) || \
- (oct->chip_id == OCTEON_CN68XX))
-#define OCTEON_CN23XX_PF(oct) (oct->chip_id == OCTEON_CN23XX_PF_VID)
-#define CHIP_FIELD(oct, TYPE, field) \
- (((struct octeon_ ## TYPE *)(oct->chip))->field)
+#define OCTEON_CN6XXX(oct) ({ \
+ typeof(oct) _oct = (oct); \
+ ((_oct->chip_id == OCTEON_CN66XX) || \
+ (_oct->chip_id == OCTEON_CN68XX)); })
+#define OCTEON_CN23XX_PF(oct) ((oct)->chip_id == OCTEON_CN23XX_PF_VID)
+#define OCTEON_CN23XX_VF(oct) ((oct)->chip_id == OCTEON_CN23XX_VF_VID)
+#define CHIP_CONF(oct, TYPE) \
+ (((struct octeon_ ## TYPE *)((oct)->chip))->conf)
struct oct_intrmod_cmd {
struct octeon_device *oct_dev;
@@ -508,7 +557,7 @@ struct oct_intrmod_cmd {
void octeon_init_device_list(int conf_type);
/** Free memory for Input and Output queue structures for a octeon device */
-void octeon_free_device_mem(struct octeon_device *);
+void octeon_free_device_mem(struct octeon_device *oct);
/* Look up a free entry in the octeon_device table and allocate resources
* for the octeon_device structure for an octeon device. Called at init
@@ -606,16 +655,16 @@ void lio_pci_writeq(struct octeon_device *oct, u64 val, u64 addr);
/* Routines for reading and writing CSRs */
#define octeon_write_csr(oct_dev, reg_off, value) \
- writel(value, oct_dev->mmio[0].hw_addr + reg_off)
+ writel(value, (oct_dev)->mmio[0].hw_addr + (reg_off))
#define octeon_write_csr64(oct_dev, reg_off, val64) \
- writeq(val64, oct_dev->mmio[0].hw_addr + reg_off)
+ writeq(val64, (oct_dev)->mmio[0].hw_addr + (reg_off))
#define octeon_read_csr(oct_dev, reg_off) \
- readl(oct_dev->mmio[0].hw_addr + reg_off)
+ readl((oct_dev)->mmio[0].hw_addr + (reg_off))
#define octeon_read_csr64(oct_dev, reg_off) \
- readq(oct_dev->mmio[0].hw_addr + reg_off)
+ readq((oct_dev)->mmio[0].hw_addr + (reg_off))
/**
* Checks if memory access is okay
@@ -724,7 +773,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no);
/** Turns off the input and output queues for the device
* @param oct which octeon to disable
*/
-void octeon_set_io_queues_off(struct octeon_device *oct);
+int octeon_set_io_queues_off(struct octeon_device *oct);
/** Turns on or off the given output queue for the device
* @param oct which octeon to change
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
index f60e5320daf4..0be87d119a97 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
@@ -1,24 +1,20 @@
/**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-* Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file 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 file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT. See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
@@ -32,9 +28,7 @@
#include "cn66xx_regs.h"
#include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
-
-#define CVM_MIN(d1, d2) (((d1) < (d2)) ? (d1) : (d2))
-#define CVM_MAX(d1, d2) (((d1) > (d2)) ? (d1) : (d2))
+#include "cn23xx_vf_device.h"
struct niclist {
struct list_head list;
@@ -258,13 +252,18 @@ int octeon_init_droq(struct octeon_device *oct,
c_num_descs = num_descs;
c_buf_size = desc_size;
if (OCTEON_CN6XXX(oct)) {
- struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+ struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf6x);
c_refill_threshold =
(u32)CFG_GET_OQ_REFILL_THRESHOLD(conf6x);
} else if (OCTEON_CN23XX_PF(oct)) {
- struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+ struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
+
+ c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf23);
+ c_refill_threshold = (u32)CFG_GET_OQ_REFILL_THRESHOLD(conf23);
+ } else if (OCTEON_CN23XX_VF(oct)) {
+ struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_vf);
c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf23);
c_refill_threshold = (u32)CFG_GET_OQ_REFILL_THRESHOLD(conf23);
@@ -337,7 +336,7 @@ int octeon_init_droq(struct octeon_device *oct,
/* For 56xx Pass1, this function won't be called, so no checks. */
oct->fn_list.setup_oq_regs(oct, q_no);
- oct->io_qmask.oq |= (1ULL << q_no);
+ oct->io_qmask.oq |= BIT_ULL(q_no);
return 0;
@@ -409,7 +408,7 @@ static inline struct octeon_recv_info *octeon_create_recv_info(
recv_pkt->buffer_ptr[i] = droq->recv_buf_list[idx].buffer;
droq->recv_buf_list[idx].buffer = NULL;
- INCR_INDEX_BY1(idx, droq->max_count);
+ idx = incr_index(idx, 1, droq->max_count);
bytes_left -= droq->buffer_size;
i++;
buf_cnt--;
@@ -440,14 +439,15 @@ octeon_droq_refill_pullup_descs(struct octeon_droq *droq,
droq->recv_buf_list[refill_index].buffer = NULL;
desc_ring[refill_index].buffer_ptr = 0;
do {
- INCR_INDEX_BY1(droq->refill_idx,
- droq->max_count);
+ droq->refill_idx = incr_index(droq->refill_idx,
+ 1,
+ droq->max_count);
desc_refilled++;
droq->refill_count--;
} while (droq->recv_buf_list[droq->refill_idx].
buffer);
}
- INCR_INDEX_BY1(refill_index, droq->max_count);
+ refill_index = incr_index(refill_index, 1, droq->max_count);
} /* while */
return desc_refilled;
}
@@ -514,7 +514,8 @@ octeon_droq_refill(struct octeon_device *octeon_dev, struct octeon_droq *droq)
/* Reset any previous values in the length field. */
droq->info_list[droq->refill_idx].length = 0;
- INCR_INDEX_BY1(droq->refill_idx, droq->max_count);
+ droq->refill_idx = incr_index(droq->refill_idx, 1,
+ droq->max_count);
desc_refilled++;
droq->refill_count--;
}
@@ -599,7 +600,8 @@ static inline void octeon_droq_drop_packets(struct octeon_device *oct,
buf_cnt = 1;
}
- INCR_INDEX(droq->read_idx, buf_cnt, droq->max_count);
+ droq->read_idx = incr_index(droq->read_idx, buf_cnt,
+ droq->max_count);
droq->refill_count += buf_cnt;
}
}
@@ -639,11 +641,12 @@ octeon_droq_fast_process_packets(struct octeon_device *oct,
rh = &info->rh;
total_len += (u32)info->length;
- if (OPCODE_SLOW_PATH(rh)) {
+ if (opcode_slow_path(rh)) {
u32 buf_cnt;
buf_cnt = octeon_droq_dispatch_pkt(oct, droq, rh, info);
- INCR_INDEX(droq->read_idx, buf_cnt, droq->max_count);
+ droq->read_idx = incr_index(droq->read_idx,
+ buf_cnt, droq->max_count);
droq->refill_count += buf_cnt;
} else {
if (info->length <= droq->buffer_size) {
@@ -657,7 +660,8 @@ octeon_droq_fast_process_packets(struct octeon_device *oct,
droq->recv_buf_list[droq->read_idx].buffer =
NULL;
- INCR_INDEX_BY1(droq->read_idx, droq->max_count);
+ droq->read_idx = incr_index(droq->read_idx, 1,
+ droq->max_count);
droq->refill_count++;
} else {
nicbuf = octeon_fast_packet_alloc((u32)
@@ -689,8 +693,9 @@ octeon_droq_fast_process_packets(struct octeon_device *oct,
}
pkt_len += cpy_len;
- INCR_INDEX_BY1(droq->read_idx,
- droq->max_count);
+ droq->read_idx =
+ incr_index(droq->read_idx, 1,
+ droq->max_count);
droq->refill_count++;
}
}
@@ -804,9 +809,8 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct,
while (total_pkts_processed < budget) {
octeon_droq_check_hw_for_pkts(droq);
- pkts_available =
- CVM_MIN((budget - total_pkts_processed),
- (u32)(atomic_read(&droq->pkts_pending)));
+ pkts_available = min((budget - total_pkts_processed),
+ (u32)(atomic_read(&droq->pkts_pending)));
if (pkts_available == 0)
break;
@@ -891,6 +895,10 @@ octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd,
lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
}
break;
+
+ case OCTEON_CN23XX_VF_VID:
+ lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
+ break;
}
return 0;
}
@@ -988,7 +996,8 @@ int octeon_create_droq(struct octeon_device *oct,
if (!droq)
droq = vmalloc(sizeof(*droq));
if (!droq)
- goto create_droq_fail;
+ return -1;
+
memset(droq, 0, sizeof(struct octeon_droq));
/*Disable the pkt o/p for this Q */
@@ -996,7 +1005,11 @@ int octeon_create_droq(struct octeon_device *oct,
oct->droq[q_no] = droq;
/* Initialize the Droq */
- octeon_init_droq(oct, q_no, num_descs, desc_size, app_ctx);
+ if (octeon_init_droq(oct, q_no, num_descs, desc_size, app_ctx)) {
+ vfree(oct->droq[q_no]);
+ oct->droq[q_no] = NULL;
+ return -1;
+ }
oct->num_oqs++;
@@ -1009,8 +1022,4 @@ int octeon_create_droq(struct octeon_device *oct,
* the same time.
*/
return 0;
-
-create_droq_fail:
- octeon_delete_droq(oct, q_no);
- return -ENOMEM;
}
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.h b/drivers/net/ethernet/cavium/liquidio/octeon_droq.h
index 5be002d5dba4..e62074090681 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -13,13 +13,8 @@
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file octeon_droq.h
* \brief Implementation of Octeon Output queues. "Output" is with
* respect to the Octeon device on the NIC. From this driver's point of
@@ -81,7 +76,7 @@ struct octeon_skb_page_info {
* the Octeon device. Since the descriptor ring keeps physical (bus)
* addresses, this field is required for the driver to keep track of
* the virtual address pointers.
-*/
+ */
struct octeon_recv_buffer {
/** Packet buffer, including metadata. */
void *buffer;
@@ -121,7 +116,6 @@ struct oct_droq_stats {
/** Num of Packets dropped due to receive path failures. */
u64 rx_dropped;
- /** Num of vxlan packets received; */
u64 rx_vxlan;
/** Num of failures of recv_buffer_alloc() */
@@ -359,7 +353,7 @@ struct octeon_droq {
* @param q_no - droq no. ranges from 0 - 3.
* @param app_ctx - pointer to application context
* @return Success: 0 Failure: 1
-*/
+ */
int octeon_init_droq(struct octeon_device *oct_dev,
u32 q_no,
u32 num_descs,
@@ -372,7 +366,7 @@ int octeon_init_droq(struct octeon_device *oct_dev,
* @param oct_dev - pointer to the octeon device structure
* @param q_no - droq no. ranges from 0 - 3.
* @return: Success: 0 Failure: 1
-*/
+ */
int octeon_delete_droq(struct octeon_device *oct_dev, u32 q_no);
/** Register a change in droq operations. The ops field has a pointer to a
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_iq.h b/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
index e4d426ba18dc..e04ca8f0b4a7 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -13,13 +13,8 @@
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file octeon_iq.h
* \brief Host Driver: Implementation of Octeon input queues. "Input" is
* with respect to the Octeon device on the NIC. From this driver's
@@ -69,7 +64,6 @@ struct oct_iq_stats {
u64 tx_vxlan; /* tunnel */
u64 tx_dmamap_fail;
u64 tx_restart;
- /*u64 tx_timeout_count;*/
};
#define OCT_IQ_STATS_SIZE (sizeof(struct oct_iq_stats))
@@ -78,7 +72,7 @@ struct oct_iq_stats {
* The input queue is used to post raw (instruction) mode data or packet
* data to Octeon device from the host. Each input queue (upto 4) for
* a Octeon device has one such structure to represent it.
-*/
+ */
struct octeon_instr_queue {
struct octeon_device *oct_dev;
@@ -118,8 +112,8 @@ struct octeon_instr_queue {
u32 octeon_read_index;
/** This index aids in finding the window in the queue where Octeon
- * has read the commands.
- */
+ * has read the commands.
+ */
u32 flush_index;
/** This field keeps track of the instructions pending in this queue. */
@@ -150,8 +144,8 @@ struct octeon_instr_queue {
u64 last_db_time;
/** The doorbell timeout. If the doorbell was not rung for this time and
- * fill_cnt is non-zero, ring the doorbell again.
- */
+ * fill_cnt is non-zero, ring the doorbell again.
+ */
u32 db_timeout;
/** Statistics for this input queue. */
@@ -309,6 +303,9 @@ struct octeon_sc_buffer_pool {
atomic_t alloc_buf_count;
};
+#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
+ (((octeon_dev_ptr)->instr_queue[iq_no]->stats.field) += count)
+
int octeon_setup_sc_buffer_pool(struct octeon_device *oct);
int octeon_free_sc_buffer_pool(struct octeon_device *oct);
struct octeon_soft_command *
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
new file mode 100644
index 000000000000..73696b427f06
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
@@ -0,0 +1,318 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "octeon_main.h"
+#include "octeon_mailbox.h"
+
+/**
+ * octeon_mbox_read:
+ * @oct: Pointer mailbox
+ *
+ * Reads the 8-bytes of data from the mbox register
+ * Writes back the acknowldgement inidcating completion of read
+ */
+int octeon_mbox_read(struct octeon_mbox *mbox)
+{
+ union octeon_mbox_message msg;
+ int ret = 0;
+
+ spin_lock(&mbox->lock);
+
+ msg.u64 = readq(mbox->mbox_read_reg);
+
+ if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
+ spin_unlock(&mbox->lock);
+ return 0;
+ }
+
+ if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
+ mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
+ mbox->mbox_req.recv_len++;
+ } else {
+ if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
+ mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
+ msg.u64;
+ mbox->mbox_resp.recv_len++;
+ } else {
+ if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
+ (msg.s.type == OCTEON_MBOX_REQUEST)) {
+ mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
+ mbox->state |=
+ OCTEON_MBOX_STATE_REQUEST_RECEIVING;
+ mbox->mbox_req.msg.u64 = msg.u64;
+ mbox->mbox_req.q_no = mbox->q_no;
+ mbox->mbox_req.recv_len = 1;
+ } else {
+ if ((mbox->state &
+ OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
+ (msg.s.type == OCTEON_MBOX_RESPONSE)) {
+ mbox->state &=
+ ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
+ mbox->state |=
+ OCTEON_MBOX_STATE_RESPONSE_RECEIVING
+ ;
+ mbox->mbox_resp.msg.u64 = msg.u64;
+ mbox->mbox_resp.q_no = mbox->q_no;
+ mbox->mbox_resp.recv_len = 1;
+ } else {
+ writeq(OCTEON_PFVFERR,
+ mbox->mbox_read_reg);
+ mbox->state |= OCTEON_MBOX_STATE_ERROR;
+ spin_unlock(&mbox->lock);
+ return 1;
+ }
+ }
+ }
+ }
+
+ if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
+ if (mbox->mbox_req.recv_len < msg.s.len) {
+ ret = 0;
+ } else {
+ mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
+ mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
+ ret = 1;
+ }
+ } else {
+ if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
+ if (mbox->mbox_resp.recv_len < msg.s.len) {
+ ret = 0;
+ } else {
+ mbox->state &=
+ ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
+ mbox->state |=
+ OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
+ ret = 1;
+ }
+ } else {
+ WARN_ON(1);
+ }
+ }
+
+ writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
+
+ spin_unlock(&mbox->lock);
+
+ return ret;
+}
+
+/**
+ * octeon_mbox_write:
+ * @oct: Pointer Octeon Device
+ * @mbox_cmd: Cmd to send to mailbox.
+ *
+ * Populates the queue specific mbox structure
+ * with cmd information.
+ * Write the cmd to mbox register
+ */
+int octeon_mbox_write(struct octeon_device *oct,
+ struct octeon_mbox_cmd *mbox_cmd)
+{
+ struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
+ u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mbox->lock, flags);
+
+ if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
+ !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ return OCTEON_MBOX_STATUS_FAILED;
+ }
+
+ if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
+ !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ return OCTEON_MBOX_STATUS_BUSY;
+ }
+
+ if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
+ memcpy(&mbox->mbox_resp, mbox_cmd,
+ sizeof(struct octeon_mbox_cmd));
+ mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
+ }
+
+ spin_unlock_irqrestore(&mbox->lock, flags);
+
+ count = 0;
+
+ while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
+ schedule_timeout_uninterruptible(LIO_MBOX_WRITE_WAIT_TIME);
+ if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
+ ret = OCTEON_MBOX_STATUS_FAILED;
+ break;
+ }
+ }
+
+ if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
+ writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
+ for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
+ count = 0;
+ while (readq(mbox->mbox_write_reg) !=
+ OCTEON_PFVFACK) {
+ schedule_timeout_uninterruptible(10);
+ if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
+ ret = OCTEON_MBOX_STATUS_FAILED;
+ break;
+ }
+ }
+ writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
+ }
+ }
+
+ spin_lock_irqsave(&mbox->lock, flags);
+ if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ } else {
+ if ((!mbox_cmd->msg.s.resp_needed) ||
+ (ret == OCTEON_MBOX_STATUS_FAILED)) {
+ mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
+ if (!(mbox->state &
+ (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
+ OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ }
+ }
+ spin_unlock_irqrestore(&mbox->lock, flags);
+
+ return ret;
+}
+
+/**
+ * octeon_mbox_process_cmd:
+ * @mbox: Pointer mailbox
+ * @mbox_cmd: Pointer to command received
+ *
+ * Process the cmd received in mbox
+ */
+static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
+ struct octeon_mbox_cmd *mbox_cmd)
+{
+ struct octeon_device *oct = mbox->oct_dev;
+
+ switch (mbox_cmd->msg.s.cmd) {
+ case OCTEON_VF_ACTIVE:
+ dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
+ mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
+ mbox_cmd->msg.s.resp_needed = 1;
+ mbox_cmd->msg.s.len = 2;
+ mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
+ ((struct lio_version *)&mbox_cmd->data[0])->major =
+ LIQUIDIO_BASE_MAJOR_VERSION;
+ ((struct lio_version *)&mbox_cmd->data[0])->minor =
+ LIQUIDIO_BASE_MINOR_VERSION;
+ ((struct lio_version *)&mbox_cmd->data[0])->micro =
+ LIQUIDIO_BASE_MICRO_VERSION;
+ memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
+ /* Sending core cofig info to the corresponding active VF.*/
+ octeon_mbox_write(oct, mbox_cmd);
+ break;
+
+ case OCTEON_VF_FLR_REQUEST:
+ dev_info(&oct->pci_dev->dev,
+ "got a request for FLR from VF that owns DPI ring %u\n",
+ mbox->q_no);
+ pcie_capability_set_word(
+ oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no],
+ PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
+ break;
+
+ case OCTEON_PF_CHANGED_VF_MACADDR:
+ if (OCTEON_CN23XX_VF(oct))
+ octeon_pf_changed_vf_macaddr(oct,
+ mbox_cmd->msg.s.params);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ *octeon_mbox_process_message:
+ *
+ * Process the received mbox message.
+ */
+int octeon_mbox_process_message(struct octeon_mbox *mbox)
+{
+ struct octeon_mbox_cmd mbox_cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mbox->lock, flags);
+
+ if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
+ if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
+ OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
+ memcpy(&mbox_cmd, &mbox->mbox_resp,
+ sizeof(struct octeon_mbox_cmd));
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ mbox_cmd.recv_status = 1;
+ if (mbox_cmd.fn)
+ mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
+ mbox_cmd.fn_arg);
+ return 0;
+ }
+
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ return 0;
+ }
+
+ if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
+ memcpy(&mbox_cmd, &mbox->mbox_resp,
+ sizeof(struct octeon_mbox_cmd));
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ mbox_cmd.recv_status = 0;
+ if (mbox_cmd.fn)
+ mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
+ return 0;
+ }
+
+ if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
+ memcpy(&mbox_cmd, &mbox->mbox_req,
+ sizeof(struct octeon_mbox_cmd));
+ if (!mbox_cmd.msg.s.resp_needed) {
+ mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
+ if (!(mbox->state &
+ OCTEON_MBOX_STATE_RESPONSE_PENDING))
+ mbox->state = OCTEON_MBOX_STATE_IDLE;
+ writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+ }
+
+ spin_unlock_irqrestore(&mbox->lock, flags);
+ octeon_mbox_process_cmd(mbox, &mbox_cmd);
+ return 0;
+ }
+
+ WARN_ON(1);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h
new file mode 100644
index 000000000000..fe60a3e6247b
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h
@@ -0,0 +1,115 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ * Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
+#ifndef __MAILBOX_H__
+#define __MAILBOX_H__
+
+/* Macros for Mail Box Communication */
+
+#define OCTEON_MBOX_DATA_MAX 32
+
+#define OCTEON_VF_ACTIVE 0x1
+#define OCTEON_VF_FLR_REQUEST 0x2
+#define OCTEON_PF_CHANGED_VF_MACADDR 0x4
+
+/*Macro for Read acknowldgement*/
+#define OCTEON_PFVFACK 0xffffffffffffffff
+#define OCTEON_PFVFSIG 0x1122334455667788
+#define OCTEON_PFVFERR 0xDEADDEADDEADDEAD
+
+#define LIO_MBOX_WRITE_WAIT_CNT 1000
+#define LIO_MBOX_WRITE_WAIT_TIME 10
+
+enum octeon_mbox_cmd_status {
+ OCTEON_MBOX_STATUS_SUCCESS = 0,
+ OCTEON_MBOX_STATUS_FAILED = 1,
+ OCTEON_MBOX_STATUS_BUSY = 2
+};
+
+enum octeon_mbox_message_type {
+ OCTEON_MBOX_REQUEST = 0,
+ OCTEON_MBOX_RESPONSE = 1
+};
+
+union octeon_mbox_message {
+ u64 u64;
+ struct {
+ u16 type : 1;
+ u16 resp_needed : 1;
+ u16 cmd : 6;
+ u16 len : 8;
+ u8 params[6];
+ } s;
+};
+
+typedef void (*octeon_mbox_callback_t)(void *, void *, void *);
+
+struct octeon_mbox_cmd {
+ union octeon_mbox_message msg;
+ u64 data[OCTEON_MBOX_DATA_MAX];
+ u32 q_no;
+ u32 recv_len;
+ u32 recv_status;
+ octeon_mbox_callback_t fn;
+ void *fn_arg;
+};
+
+enum octeon_mbox_state {
+ OCTEON_MBOX_STATE_IDLE = 1,
+ OCTEON_MBOX_STATE_REQUEST_RECEIVING = 2,
+ OCTEON_MBOX_STATE_REQUEST_RECEIVED = 4,
+ OCTEON_MBOX_STATE_RESPONSE_PENDING = 8,
+ OCTEON_MBOX_STATE_RESPONSE_RECEIVING = 16,
+ OCTEON_MBOX_STATE_RESPONSE_RECEIVED = 16,
+ OCTEON_MBOX_STATE_ERROR = 32
+};
+
+struct octeon_mbox {
+ /** A spinlock to protect access to this q_mbox. */
+ spinlock_t lock;
+
+ struct octeon_device *oct_dev;
+
+ u32 q_no;
+
+ enum octeon_mbox_state state;
+
+ struct cavium_wk mbox_poll_wk;
+
+ /** SLI_MAC_PF_MBOX_INT for PF, SLI_PKT_MBOX_INT for VF. */
+ void *mbox_int_reg;
+
+ /** SLI_PKT_PF_VF_MBOX_SIG(0) for PF, SLI_PKT_PF_VF_MBOX_SIG(1) for VF.
+ */
+ void *mbox_write_reg;
+
+ /** SLI_PKT_PF_VF_MBOX_SIG(1) for PF, SLI_PKT_PF_VF_MBOX_SIG(0) for VF.
+ */
+ void *mbox_read_reg;
+
+ struct octeon_mbox_cmd mbox_req;
+
+ struct octeon_mbox_cmd mbox_resp;
+
+};
+
+int octeon_mbox_read(struct octeon_mbox *mbox);
+int octeon_mbox_write(struct octeon_device *oct,
+ struct octeon_mbox_cmd *mbox_cmd);
+int octeon_mbox_process_message(struct octeon_mbox *mbox);
+
+#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_main.h b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
index 366298f7bcb2..8cd389148166 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_main.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -13,13 +13,8 @@
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
+ ***********************************************************************/
/*! \file octeon_main.h
* \brief Host Driver: This file is included by all host driver source files
* to include common definitions.
@@ -66,7 +61,7 @@ void octeon_update_tx_completion_counters(void *buf, int reqtype,
unsigned int *bytes_compl);
void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
unsigned int bytes_compl);
-
+void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac);
/** Swap 8B blocks */
static inline void octeon_swap_8B_data(u64 *data, u32 blocks)
{
@@ -78,10 +73,10 @@ static inline void octeon_swap_8B_data(u64 *data, u32 blocks)
}
/**
- * \brief unmaps a PCI BAR
- * @param oct Pointer to Octeon device
- * @param baridx bar index
- */
+ * \brief unmaps a PCI BAR
+ * @param oct Pointer to Octeon device
+ * @param baridx bar index
+ */
static inline void octeon_unmap_pci_barx(struct octeon_device *oct, int baridx)
{
dev_dbg(&oct->pci_dev->dev, "Freeing PCI mapped regions for Bar%d\n",
@@ -116,7 +111,7 @@ static inline int octeon_map_pci_barx(struct octeon_device *oct,
mapped_len = oct->mmio[baridx].len;
if (!mapped_len)
- return 1;
+ goto err_release_region;
if (max_map_len && (mapped_len > max_map_len))
mapped_len = max_map_len;
@@ -132,11 +127,15 @@ static inline int octeon_map_pci_barx(struct octeon_device *oct,
if (!oct->mmio[baridx].hw_addr) {
dev_err(&oct->pci_dev->dev, "error ioremap for bar %d\n",
baridx);
- return 1;
+ goto err_release_region;
}
oct->mmio[baridx].done = 1;
return 0;
+
+err_release_region:
+ pci_release_region(oct->pci_dev, baridx * 2);
+ return 1;
}
static inline void *
@@ -203,24 +202,6 @@ out:
return errno;
}
-static inline void
-sleep_atomic_cond(wait_queue_head_t *waitq, atomic_t *pcond)
-{
- wait_queue_t we;
-
- init_waitqueue_entry(&we, current);
- add_wait_queue(waitq, &we);
- while (!atomic_read(pcond)) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (signal_pending(current))
- goto out;
- schedule();
- }
-out:
- set_current_state(TASK_RUNNING);
- remove_wait_queue(waitq, &we);
-}
-
/* Gives up the CPU for a timeout period.
* Check that the condition is not true before we go to sleep for a
* timeout period.
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
index 0dc081a99b30..13a18c9a7a51 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
#include <linux/netdevice.h>
#include "liquidio_common.h"
@@ -39,7 +36,7 @@ octeon_toggle_bar1_swapmode(struct octeon_device *oct, u32 idx)
oct->fn_list.bar1_idx_write(oct, idx, mask);
}
#else
-#define octeon_toggle_bar1_swapmode(oct, idx) (oct = oct)
+#define octeon_toggle_bar1_swapmode(oct, idx)
#endif
static void
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h
index 11b183377b44..bae2fdd89503 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
/*! \file octeon_mem_ops.h
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
index e5d1debd05ad..6bb89419006e 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
/*! \file octeon_network.h
@@ -29,7 +26,7 @@
#include <linux/ptp_clock_kernel.h>
#define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE)
-#define LIO_MIN_MTU_SIZE 68
+#define LIO_MIN_MTU_SIZE ETH_MIN_MTU
struct oct_nic_stats_resp {
u64 rh;
@@ -126,12 +123,13 @@ struct lio {
/* work queue for link status */
struct cavium_wq link_status_wq;
+ int netdev_uc_count;
};
#define LIO_SIZE (sizeof(struct lio))
#define GET_LIO(netdev) ((struct lio *)netdev_priv(netdev))
-#define CIU3_WDOG(c) (0x1010000020000ULL + (c << 3))
+#define CIU3_WDOG(c) (0x1010000020000ULL + ((c) << 3))
#define CIU3_WDOG_MASK 12ULL
#define LIO_MONITOR_WDOG_EXPIRE 1
#define LIO_MONITOR_CORE_STUCK_MSGD 2
@@ -342,9 +340,9 @@ static inline void tx_buffer_free(void *buffer)
}
#define lio_dma_alloc(oct, size, dma_addr) \
- dma_alloc_coherent(&oct->pci_dev->dev, size, dma_addr, GFP_KERNEL)
+ dma_alloc_coherent(&(oct)->pci_dev->dev, size, dma_addr, GFP_KERNEL)
#define lio_dma_free(oct, size, virt_addr, dma_addr) \
- dma_free_coherent(&oct->pci_dev->dev, size, virt_addr, dma_addr)
+ dma_free_coherent(&(oct)->pci_dev->dev, size, virt_addr, dma_addr)
static inline
void *get_rbd(struct sk_buff *skb)
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
index 40ac1fe88956..c3d6a8228362 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.h b/drivers/net/ethernet/cavium/liquidio/octeon_nic.h
index 4b8da67b995f..0c7a5c9b2932 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
/*! \file octeon_nic.h
@@ -67,7 +64,7 @@ struct octnic_ctrl_pkt {
octnic_ctrl_pkt_cb_fn_t cb_fn;
};
-#define MAX_UDD_SIZE(nctrl) (sizeof(nctrl->udd))
+#define MAX_UDD_SIZE(nctrl) (sizeof((nctrl)->udd))
/** Structure of data information passed by the NIC module to the OSI
* layer when forwarding data to Octeon device software.
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 90866bb50033..3ce66759e80a 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -31,9 +28,7 @@
#include "octeon_network.h"
#include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
-
-#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
- (octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
+#include "cn23xx_vf_device.h"
struct iq_post_status {
int status;
@@ -71,9 +66,12 @@ int octeon_init_instr_queue(struct octeon_device *oct,
int numa_node = cpu_to_node(iq_no % num_online_cpus());
if (OCTEON_CN6XXX(oct))
- conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn6xxx, conf)));
+ conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn6xxx)));
else if (OCTEON_CN23XX_PF(oct))
- conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn23xx_pf, conf)));
+ conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_pf)));
+ else if (OCTEON_CN23XX_VF(oct))
+ conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_vf)));
+
if (!conf) {
dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n",
oct->chip_id);
@@ -145,7 +143,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
spin_lock_init(&iq->iq_flush_running_lock);
- oct->io_qmask.iq |= (1ULL << iq_no);
+ oct->io_qmask.iq |= BIT_ULL(iq_no);
/* Set the 32B/64B mode for each input queue */
oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no);
@@ -157,6 +155,8 @@ int octeon_init_instr_queue(struct octeon_device *oct,
WQ_MEM_RECLAIM,
0);
if (!oct->check_db_wq[iq_no].wq) {
+ vfree(iq->request_list);
+ iq->request_list = NULL;
lio_dma_free(oct, q_size, iq->base_addr, iq->base_addr_dma);
dev_err(&oct->pci_dev->dev, "check db wq create failed for iq %d\n",
iq_no);
@@ -183,10 +183,13 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
if (OCTEON_CN6XXX(oct))
desc_size =
- CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn6xxx, conf));
+ CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn6xxx));
else if (OCTEON_CN23XX_PF(oct))
desc_size =
- CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn23xx_pf, conf));
+ CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_pf));
+ else if (OCTEON_CN23XX_VF(oct))
+ desc_size =
+ CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_vf));
vfree(iq->request_list);
@@ -239,7 +242,9 @@ int octeon_setup_iq(struct octeon_device *oct,
}
oct->num_iqs++;
- oct->fn_list.enable_io_queues(oct);
+ if (oct->fn_list.enable_io_queues(oct))
+ return 1;
+
return 0;
}
@@ -250,9 +255,8 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct)
do {
instr_cnt = 0;
- /*for (i = 0; i < oct->num_iqs; i++) {*/
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
- if (!(oct->io_qmask.iq & (1ULL << i)))
+ if (!(oct->io_qmask.iq & BIT_ULL(i)))
continue;
pending =
atomic_read(&oct->
@@ -319,7 +323,8 @@ __post_command2(struct octeon_instr_queue *iq, u8 *cmd)
/* "index" is returned, host_write_index is modified. */
st.index = iq->host_write_index;
- INCR_INDEX_BY1(iq->host_write_index, iq->max_count);
+ iq->host_write_index = incr_index(iq->host_write_index, 1,
+ iq->max_count);
iq->fill_cnt++;
/* Flush the command into memory. We need to be sure the data is in
@@ -389,7 +394,7 @@ lio_process_iq_request_list(struct octeon_device *oct,
case REQTYPE_SOFT_COMMAND:
sc = buf;
- if (OCTEON_CN23XX_PF(oct))
+ if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))
irh = (struct octeon_instr_irh *)
&sc->cmd.cmd3.irh;
else
@@ -434,7 +439,7 @@ lio_process_iq_request_list(struct octeon_device *oct,
skip_this:
inst_count++;
- INCR_INDEX_BY1(old, iq->max_count);
+ old = incr_index(old, 1, iq->max_count);
if ((napi_budget) && (inst_count >= napi_budget))
break;
@@ -577,8 +582,6 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no,
/* This is only done here to expedite packets being flushed
* for cases where there are no IQ completion interrupts.
*/
- /*if (iq->do_auto_flush)*/
- /* octeon_flush_iq(oct, iq, 2, 0);*/
return st.status;
}
@@ -604,7 +607,7 @@ octeon_prepare_soft_command(struct octeon_device *oct,
oct_cfg = octeon_get_conf(oct);
- if (OCTEON_CN23XX_PF(oct)) {
+ if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
ih3->pkind = oct->instr_queue[sc->iq_no]->txpciq.s.pkind;
@@ -697,7 +700,7 @@ int octeon_send_soft_command(struct octeon_device *oct,
struct octeon_instr_irh *irh;
u32 len;
- if (OCTEON_CN23XX_PF(oct)) {
+ if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
if (ih3->dlengsz) {
WARN_ON(!sc->dmadptr);
@@ -749,8 +752,10 @@ int octeon_setup_sc_buffer_pool(struct octeon_device *oct)
lio_dma_alloc(oct,
SOFT_COMMAND_BUFFER_SIZE,
(dma_addr_t *)&dma_addr);
- if (!sc)
+ if (!sc) {
+ octeon_free_sc_buffer_pool(oct);
return 1;
+ }
sc->dma_addr = dma_addr;
sc->size = SOFT_COMMAND_BUFFER_SIZE;
diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c
index be52178d8cb6..2fbaae96b505 100644
--- a/drivers/net/ethernet/cavium/liquidio/response_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -81,17 +78,14 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev,
spin_lock_bh(&ordered_sc_list->lock);
if (ordered_sc_list->head.next == &ordered_sc_list->head) {
- /* ordered_sc_list is empty; there is
- * nothing to process
- */
- spin_unlock_bh
- (&ordered_sc_list->lock);
+ spin_unlock_bh(&ordered_sc_list->lock);
return 1;
}
sc = (struct octeon_soft_command *)ordered_sc_list->
head.next;
- if (OCTEON_CN23XX_PF(octeon_dev)) {
+ if (OCTEON_CN23XX_PF(octeon_dev) ||
+ OCTEON_CN23XX_VF(octeon_dev)) {
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
rptr = sc->cmd.cmd3.rptr;
} else {
diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.h b/drivers/net/ethernet/cavium/liquidio/response_manager.h
index 7a48752dcb10..cbb2d84e8932 100644
--- a/drivers/net/ethernet/cavium/liquidio/response_manager.h
+++ b/drivers/net/ethernet/cavium/liquidio/response_manager.h
@@ -4,7 +4,7 @@
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
@@ -15,9 +15,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
**********************************************************************/
/*! \file response_manager.h
@@ -85,7 +82,6 @@ enum {
/** A value of 0x00000000 indicates no error i.e. success */
#define DRIVER_ERROR_NONE 0x00000000
-/** (Major number: 0x0000; Minor Number: 0x0001) */
#define DRIVER_ERROR_REQ_PENDING 0x00000001
#define DRIVER_ERROR_REQ_TIMEOUT 0x00000003
#define DRIVER_ERROR_REQ_EINTR 0x00000004
diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
index 4ab404f45b21..16e12c45904b 100644
--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
@@ -645,16 +645,6 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
struct octeon_mgmt *p = netdev_priv(netdev);
int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
- /* Limit the MTU to make sure the ethernet packets are between
- * 64 bytes and 16383 bytes.
- */
- if (size_without_fcs < 64 || size_without_fcs > 16383) {
- dev_warn(p->dev, "MTU must be between %d and %d.\n",
- 64 - OCTEON_MGMT_RX_HEADROOM,
- 16383 - OCTEON_MGMT_RX_HEADROOM);
- return -EINVAL;
- }
-
netdev->mtu = new_mtu;
cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
@@ -1491,6 +1481,9 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
+ netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM;
+ netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM;
+
mac = of_get_mac_address(pdev->dev.of_node);
if (mac)
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 86bd93ce2ea3..e739c7153562 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -149,6 +149,12 @@ struct nicvf_rss_info {
u64 key[RSS_HASH_KEY_SIZE];
} ____cacheline_aligned_in_smp;
+struct nicvf_pfc {
+ u8 autoneg;
+ u8 fc_rx;
+ u8 fc_tx;
+};
+
enum rx_stats_reg_offset {
RX_OCTS = 0x0,
RX_UCAST = 0x1,
@@ -292,11 +298,13 @@ struct nicvf {
u8 node;
u8 cpi_alg;
bool link_up;
+ u8 mac_type;
u8 duplex;
u32 speed;
bool tns_mode;
bool loopback_supported;
struct nicvf_rss_info rss_info;
+ struct nicvf_pfc pfc;
struct tasklet_struct qs_err_task;
struct work_struct reset_task;
@@ -357,6 +365,7 @@ struct nicvf {
#define NIC_MBOX_MSG_SNICVF_PTR 0x15 /* Send sqet nicvf ptr to PVF */
#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */
#define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */
+#define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */
#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
@@ -446,6 +455,7 @@ struct bgx_stats_msg {
/* Physical interface link status */
struct bgx_link_status {
u8 msg;
+ u8 mac_type;
u8 link_up;
u8 duplex;
u32 speed;
@@ -498,6 +508,14 @@ struct reset_stat_cfg {
u16 sq_stat_mask;
};
+struct pfc {
+ u8 msg;
+ u8 get; /* Get or set PFC settings */
+ u8 autoneg;
+ u8 fc_rx;
+ u8 fc_tx;
+};
+
/* 128 bit shared memory between PF and each VF */
union nic_mbx {
struct { u8 msg; } msg;
@@ -516,6 +534,7 @@ union nic_mbx {
struct nicvf_ptr nicvf;
struct set_loopback lbk;
struct reset_stat_cfg reset_stat;
+ struct pfc pfc;
};
#define NIC_NODE_ID_MASK 0x03
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 6677b96e1f3f..767234e2e8f9 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -809,6 +809,15 @@ static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk)
bgx_lmac_internal_loopback(nic->node, bgx_idx, lmac_idx, lbk->enable);
+ /* Enable moving average calculation.
+ * Keep the LVL/AVG delay to HW enforced minimum so that, not too many
+ * packets sneek in between average calculations.
+ */
+ nic_reg_write(nic, NIC_PF_CQ_AVG_CFG,
+ (BIT_ULL(20) | 0x2ull << 14 | 0x1));
+ nic_reg_write(nic, NIC_PF_RRM_AVG_CFG,
+ (BIT_ULL(20) | 0x3ull << 14 | 0x1));
+
return 0;
}
@@ -889,6 +898,30 @@ static void nic_enable_vf(struct nicpf *nic, int vf, bool enable)
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, enable);
}
+static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
+{
+ int bgx, lmac;
+ struct pfc pfc;
+ union nic_mbx mbx = {};
+
+ if (vf >= nic->num_vf_en)
+ return;
+ bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+ if (cfg->get) {
+ bgx_lmac_get_pfc(nic->node, bgx, lmac, &pfc);
+ mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+ mbx.pfc.autoneg = pfc.autoneg;
+ mbx.pfc.fc_rx = pfc.fc_rx;
+ mbx.pfc.fc_tx = pfc.fc_tx;
+ nic_send_msg_to_vf(nic, vf, &mbx);
+ } else {
+ bgx_lmac_set_pfc(nic->node, bgx, lmac, cfg);
+ nic_mbx_send_ack(nic, vf);
+ }
+}
+
/* Interrupt handler to handle mailbox messages from VFs */
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
{
@@ -1028,6 +1061,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
case NIC_MBOX_MSG_RESET_STAT_COUNTER:
ret = nic_reset_stat_counters(nic, vf, &mbx.reset_stat);
break;
+ case NIC_MBOX_MSG_PFC:
+ nic_pause_frame(nic, vf, &mbx.pfc);
+ goto unlock;
default:
dev_err(&nic->pdev->dev,
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1258,6 +1294,7 @@ static void nic_poll_for_link(struct work_struct *work)
mbx.link_status.link_up = link.link_up;
mbx.link_status.duplex = link.duplex;
mbx.link_status.speed = link.speed;
+ mbx.link_status.mac_type = link.mac_type;
nic_send_msg_to_vf(nic, vf, &mbx);
}
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index 432bf6be57cb..2e74bbaa38e1 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -116,29 +116,65 @@ static const unsigned int nicvf_n_hw_stats = ARRAY_SIZE(nicvf_hw_stats);
static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats);
static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats);
-static int nicvf_get_settings(struct net_device *netdev,
- struct ethtool_cmd *cmd)
+static int nicvf_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
{
struct nicvf *nic = netdev_priv(netdev);
+ u32 supported, advertising;
- cmd->supported = 0;
- cmd->transceiver = XCVR_EXTERNAL;
+ supported = 0;
+ advertising = 0;
if (!nic->link_up) {
- cmd->duplex = DUPLEX_UNKNOWN;
- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
return 0;
}
- if (nic->speed <= 1000) {
- cmd->port = PORT_MII;
- cmd->autoneg = AUTONEG_ENABLE;
- } else {
- cmd->port = PORT_FIBRE;
- cmd->autoneg = AUTONEG_DISABLE;
+ switch (nic->speed) {
+ case SPEED_1000:
+ cmd->base.port = PORT_MII | PORT_TP;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+ supported |= SUPPORTED_MII | SUPPORTED_TP;
+ supported |= SUPPORTED_1000baseT_Full |
+ SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_10baseT_Half;
+ supported |= SUPPORTED_Autoneg;
+ advertising |= ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_10baseT_Half;
+ break;
+ case SPEED_10000:
+ if (nic->mac_type == BGX_MODE_RXAUI) {
+ cmd->base.port = PORT_TP;
+ supported |= SUPPORTED_TP;
+ } else {
+ cmd->base.port = PORT_FIBRE;
+ supported |= SUPPORTED_FIBRE;
+ }
+ cmd->base.autoneg = AUTONEG_DISABLE;
+ supported |= SUPPORTED_10000baseT_Full;
+ break;
+ case SPEED_40000:
+ cmd->base.port = PORT_FIBRE;
+ cmd->base.autoneg = AUTONEG_DISABLE;
+ supported |= SUPPORTED_FIBRE;
+ supported |= SUPPORTED_40000baseCR4_Full;
+ break;
}
- cmd->duplex = nic->duplex;
- ethtool_cmd_speed_set(cmd, nic->speed);
+ cmd->base.duplex = nic->duplex;
+ cmd->base.speed = nic->speed;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
@@ -690,8 +726,56 @@ static int nicvf_set_channels(struct net_device *dev,
return err;
}
+static void nicvf_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct nicvf *nic = netdev_priv(dev);
+ union nic_mbx mbx = {};
+
+ /* Supported only for 10G/40G interfaces */
+ if ((nic->mac_type == BGX_MODE_SGMII) ||
+ (nic->mac_type == BGX_MODE_QSGMII) ||
+ (nic->mac_type == BGX_MODE_RGMII))
+ return;
+
+ mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+ mbx.pfc.get = 1;
+ if (!nicvf_send_msg_to_pf(nic, &mbx)) {
+ pause->autoneg = nic->pfc.autoneg;
+ pause->rx_pause = nic->pfc.fc_rx;
+ pause->tx_pause = nic->pfc.fc_tx;
+ }
+}
+
+static int nicvf_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct nicvf *nic = netdev_priv(dev);
+ union nic_mbx mbx = {};
+
+ /* Supported only for 10G/40G interfaces */
+ if ((nic->mac_type == BGX_MODE_SGMII) ||
+ (nic->mac_type == BGX_MODE_QSGMII) ||
+ (nic->mac_type == BGX_MODE_RGMII))
+ return -EOPNOTSUPP;
+
+ if (pause->autoneg)
+ return -EOPNOTSUPP;
+
+ mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+ mbx.pfc.get = 0;
+ mbx.pfc.fc_rx = pause->rx_pause;
+ mbx.pfc.fc_tx = pause->tx_pause;
+ if (nicvf_send_msg_to_pf(nic, &mbx))
+ return -EAGAIN;
+
+ nic->pfc.fc_rx = pause->rx_pause;
+ nic->pfc.fc_tx = pause->tx_pause;
+
+ return 0;
+}
+
static const struct ethtool_ops nicvf_ethtool_ops = {
- .get_settings = nicvf_get_settings,
.get_link = nicvf_get_link,
.get_drvinfo = nicvf_get_drvinfo,
.get_msglevel = nicvf_get_msglevel,
@@ -711,7 +795,10 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
.set_rxfh = nicvf_set_rxfh,
.get_channels = nicvf_get_channels,
.set_channels = nicvf_set_channels,
+ .get_pauseparam = nicvf_get_pauseparam,
+ .set_pauseparam = nicvf_set_pauseparam,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_link_ksettings = nicvf_get_link_ksettings,
};
void nicvf_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 8a37012c9c89..2006f58b14b1 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -221,6 +221,7 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
nic->link_up = mbx.link_status.link_up;
nic->duplex = mbx.link_status.duplex;
nic->speed = mbx.link_status.speed;
+ nic->mac_type = mbx.link_status.mac_type;
if (nic->link_up) {
netdev_info(nic->netdev, "%s: Link is Up %d Mbps %s\n",
nic->netdev->name, nic->speed,
@@ -255,6 +256,12 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
nic->pnicvf = (struct nicvf *)mbx.nicvf.nicvf;
nic->pf_acked = true;
break;
+ case NIC_MBOX_MSG_PFC:
+ nic->pfc.autoneg = mbx.pfc.autoneg;
+ nic->pfc.fc_rx = mbx.pfc.fc_rx;
+ nic->pfc.fc_tx = mbx.pfc.fc_tx;
+ nic->pf_acked = true;
+ break;
default:
netdev_err(nic->netdev,
"Invalid message from PF, msg 0x%x\n", mbx.msg.msg);
@@ -637,6 +644,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
struct cmp_queue *cq = &qs->cq[cq_idx];
struct cqe_rx_t *cq_desc;
struct netdev_queue *txq;
+ struct snd_queue *sq;
unsigned int tx_pkts = 0, tx_bytes = 0;
spin_lock_bh(&cq->lock);
@@ -702,16 +710,20 @@ loop:
done:
/* Wakeup TXQ if its stopped earlier due to SQ full */
- if (tx_done) {
+ sq = &nic->qs->sq[cq_idx];
+ if (tx_done ||
+ (atomic_read(&sq->free_cnt) >= MIN_SQ_DESC_PER_PKT_XMIT)) {
netdev = nic->pnicvf->netdev;
txq = netdev_get_tx_queue(netdev,
nicvf_netdev_qidx(nic, cq_idx));
if (tx_pkts)
netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
- nic = nic->pnicvf;
+ /* To read updated queue and carrier status */
+ smp_mb();
if (netif_tx_queue_stopped(txq) && netif_carrier_ok(netdev)) {
- netif_tx_start_queue(txq);
+ netif_tx_wake_queue(txq);
+ nic = nic->pnicvf;
this_cpu_inc(nic->drv_stats->txq_wake);
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
@@ -1047,6 +1059,9 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev)
struct nicvf *nic = netdev_priv(netdev);
int qid = skb_get_queue_mapping(skb);
struct netdev_queue *txq = netdev_get_tx_queue(netdev, qid);
+ struct nicvf *snic;
+ struct snd_queue *sq;
+ int tmp;
/* Check for minimum packet length */
if (skb->len <= ETH_HLEN) {
@@ -1054,13 +1069,39 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
- if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
+ snic = nic;
+ /* Get secondary Qset's SQ structure */
+ if (qid >= MAX_SND_QUEUES_PER_QS) {
+ tmp = qid / MAX_SND_QUEUES_PER_QS;
+ snic = (struct nicvf *)nic->snicvf[tmp - 1];
+ if (!snic) {
+ netdev_warn(nic->netdev,
+ "Secondary Qset#%d's ptr not initialized\n",
+ tmp - 1);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ qid = qid % MAX_SND_QUEUES_PER_QS;
+ }
+
+ sq = &snic->qs->sq[qid];
+ if (!netif_tx_queue_stopped(txq) &&
+ !nicvf_sq_append_skb(snic, sq, skb, qid)) {
netif_tx_stop_queue(txq);
- this_cpu_inc(nic->drv_stats->txq_stop);
- if (netif_msg_tx_err(nic))
- netdev_warn(netdev,
- "%s: Transmit ring full, stopping SQ%d\n",
- netdev->name, qid);
+
+ /* Barrier, so that stop_queue visible to other cpus */
+ smp_mb();
+
+ /* Check again, incase another cpu freed descriptors */
+ if (atomic_read(&sq->free_cnt) > MIN_SQ_DESC_PER_PKT_XMIT) {
+ netif_tx_wake_queue(txq);
+ } else {
+ this_cpu_inc(nic->drv_stats->txq_stop);
+ if (netif_msg_tx_err(nic))
+ netdev_warn(netdev,
+ "%s: Transmit ring full, stopping SQ%d\n",
+ netdev->name, qid);
+ }
return NETDEV_TX_BUSY;
}
@@ -1291,20 +1332,17 @@ napi_del:
static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct nicvf *nic = netdev_priv(netdev);
-
- if (new_mtu > NIC_HW_MAX_FRS)
- return -EINVAL;
-
- if (new_mtu < NIC_HW_MIN_FRS)
- return -EINVAL;
+ int orig_mtu = netdev->mtu;
netdev->mtu = new_mtu;
if (!netif_running(netdev))
return 0;
- if (nicvf_update_hw_max_frs(nic, new_mtu))
+ if (nicvf_update_hw_max_frs(nic, new_mtu)) {
+ netdev->mtu = orig_mtu;
return -EINVAL;
+ }
return 0;
}
@@ -1631,6 +1669,10 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &nicvf_netdev_ops;
netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
+ /* MTU range: 64 - 9200 */
+ netdev->min_mtu = NIC_HW_MIN_FRS;
+ netdev->max_mtu = NIC_HW_MAX_FRS;
+
INIT_WORK(&nic->reset_task, nicvf_reset_task);
err = register_netdev(netdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 747ef0882976..d2ac133e36f1 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -544,14 +544,18 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
nicvf_send_msg_to_pf(nic, &mbx);
mbx.rq.msg = NIC_MBOX_MSG_RQ_BP_CFG;
- mbx.rq.cfg = (1ULL << 63) | (1ULL << 62) | (qs->vnic_id << 0);
+ mbx.rq.cfg = BIT_ULL(63) | BIT_ULL(62) |
+ (RQ_PASS_RBDR_LVL << 16) | (RQ_PASS_CQ_LVL << 8) |
+ (qs->vnic_id << 0);
nicvf_send_msg_to_pf(nic, &mbx);
/* RQ drop config
* Enable CQ drop to reserve sufficient CQEs for all tx packets
*/
mbx.rq.msg = NIC_MBOX_MSG_RQ_DROP_CFG;
- mbx.rq.cfg = (1ULL << 62) | (RQ_CQ_DROP << 8);
+ mbx.rq.cfg = BIT_ULL(63) | BIT_ULL(62) |
+ (RQ_PASS_RBDR_LVL << 40) | (RQ_DROP_RBDR_LVL << 32) |
+ (RQ_PASS_CQ_LVL << 16) | (RQ_DROP_CQ_LVL << 8);
nicvf_send_msg_to_pf(nic, &mbx);
if (!nic->sqs_mode && (qidx == 0)) {
@@ -650,6 +654,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
sq_cfg.ldwb = 0;
sq_cfg.qsize = SND_QSIZE;
sq_cfg.tstmp_bgx_intf = 0;
+ sq_cfg.cq_limit = 0;
nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, *(u64 *)&sq_cfg);
/* Set threshold value for interrupt generation */
@@ -1185,30 +1190,12 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
}
/* Append an skb to a SQ for packet transfer. */
-int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb)
+int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
+ struct sk_buff *skb, u8 sq_num)
{
int i, size;
int subdesc_cnt, tso_sqe = 0;
- int sq_num, qentry;
- struct queue_set *qs;
- struct snd_queue *sq;
-
- sq_num = skb_get_queue_mapping(skb);
- if (sq_num >= MAX_SND_QUEUES_PER_QS) {
- /* Get secondary Qset's SQ structure */
- i = sq_num / MAX_SND_QUEUES_PER_QS;
- if (!nic->snicvf[i - 1]) {
- netdev_warn(nic->netdev,
- "Secondary Qset#%d's ptr not initialized\n",
- i - 1);
- return 1;
- }
- nic = (struct nicvf *)nic->snicvf[i - 1];
- sq_num = sq_num % MAX_SND_QUEUES_PER_QS;
- }
-
- qs = nic->qs;
- sq = &qs->sq[sq_num];
+ int qentry;
subdesc_cnt = nicvf_sq_subdesc_required(nic, skb);
if (subdesc_cnt > atomic_read(&sq->free_cnt))
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 2e3c940c1093..9e2104675bc9 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -85,12 +85,26 @@
#define MAX_CQES_FOR_TX ((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \
MAX_CQE_PER_PKT_XMIT)
-/* Calculate number of CQEs to reserve for all SQEs.
- * Its 1/256th level of CQ size.
- * '+ 1' to account for pipelining
+
+/* RED and Backpressure levels of CQ for pkt reception
+ * For CQ, level is a measure of emptiness i.e 0x0 means full
+ * eg: For CQ of size 4K, and for pass/drop levels of 160/144
+ * HW accepts pkt if unused CQE >= 2560
+ * RED accepts pkt if unused CQE < 2304 & >= 2560
+ * DROPs pkts if unused CQE < 2304
+ */
+#define RQ_PASS_CQ_LVL 160ULL
+#define RQ_DROP_CQ_LVL 144ULL
+
+/* RED and Backpressure levels of RBDR for pkt reception
+ * For RBDR, level is a measure of fullness i.e 0x0 means empty
+ * eg: For RBDR of size 8K, and for pass/drop levels of 4/0
+ * HW accepts pkt if unused RBs >= 256
+ * RED accepts pkt if unused RBs < 256 & >= 0
+ * DROPs pkts if unused RBs < 0
*/
-#define RQ_CQ_DROP ((256 / (CMP_QUEUE_LEN / \
- (CMP_QUEUE_LEN - MAX_CQES_FOR_TX))) + 1)
+#define RQ_PASS_RBDR_LVL 8ULL
+#define RQ_DROP_RBDR_LVL 0ULL
/* Descriptor size in bytes */
#define SND_QUEUE_DESC_SIZE 16
@@ -292,7 +306,8 @@ void nicvf_sq_disable(struct nicvf *nic, int qidx);
void nicvf_put_sq_desc(struct snd_queue *sq, int desc_cnt);
void nicvf_sq_free_used_descs(struct net_device *netdev,
struct snd_queue *sq, int qidx);
-int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb);
+int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
+ struct sk_buff *skb, u8 sq_num);
struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx);
void nicvf_rbdr_task(unsigned long data);
diff --git a/drivers/net/ethernet/cavium/thunder/q_struct.h b/drivers/net/ethernet/cavium/thunder/q_struct.h
index 9e6d9876bfd0..f36347237a54 100644
--- a/drivers/net/ethernet/cavium/thunder/q_struct.h
+++ b/drivers/net/ethernet/cavium/thunder/q_struct.h
@@ -624,7 +624,9 @@ struct cq_cfg {
struct sq_cfg {
#if defined(__BIG_ENDIAN_BITFIELD)
- u64 reserved_20_63:44;
+ u64 reserved_32_63:32;
+ u64 cq_limit:8;
+ u64 reserved_20_23:4;
u64 ena:1;
u64 reserved_18_18:1;
u64 reset:1;
@@ -642,7 +644,9 @@ struct sq_cfg {
u64 reset:1;
u64 reserved_18_18:1;
u64 ena:1;
- u64 reserved_20_63:44;
+ u64 reserved_20_23:4;
+ u64 cq_limit:8;
+ u64 reserved_32_63:32;
#endif
};
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 050e21fbb147..9211c750e064 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -161,6 +161,7 @@ void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status)
return;
lmac = &bgx->lmac[lmacid];
+ link->mac_type = lmac->lmac_type;
link->link_up = lmac->link_up;
link->duplex = lmac->last_duplex;
link->speed = lmac->last_speed;
@@ -211,6 +212,47 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
}
EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
+void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
+{
+ struct pfc *pfc = (struct pfc *)pause;
+ struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+ struct lmac *lmac;
+ u64 cfg;
+
+ if (!bgx)
+ return;
+ lmac = &bgx->lmac[lmacid];
+ if (lmac->is_sgmii)
+ return;
+
+ cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL);
+ pfc->fc_rx = cfg & RX_EN;
+ pfc->fc_tx = cfg & TX_EN;
+ pfc->autoneg = 0;
+}
+EXPORT_SYMBOL(bgx_lmac_get_pfc);
+
+void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause)
+{
+ struct pfc *pfc = (struct pfc *)pause;
+ struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+ struct lmac *lmac;
+ u64 cfg;
+
+ if (!bgx)
+ return;
+ lmac = &bgx->lmac[lmacid];
+ if (lmac->is_sgmii)
+ return;
+
+ cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL);
+ cfg &= ~(RX_EN | TX_EN);
+ cfg |= (pfc->fc_rx ? RX_EN : 0x00);
+ cfg |= (pfc->fc_tx ? TX_EN : 0x00);
+ bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, cfg);
+}
+EXPORT_SYMBOL(bgx_lmac_set_pfc);
+
static void bgx_sgmii_change_link_state(struct lmac *lmac)
{
struct bgx *bgx = lmac->bgx;
@@ -524,6 +566,18 @@ static int bgx_lmac_xaui_init(struct bgx *bgx, struct lmac *lmac)
cfg |= SMU_TX_CTL_DIC_EN;
bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_CTL, cfg);
+ /* Enable receive and transmission of pause frames */
+ bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, ((0xffffULL << 32) |
+ BCK_EN | DRP_EN | TX_EN | RX_EN));
+ /* Configure pause time and interval */
+ bgx_reg_write(bgx, lmacid,
+ BGX_SMUX_TX_PAUSE_PKT_TIME, DEFAULT_PAUSE_TIME);
+ cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL);
+ cfg &= ~0xFFFFull;
+ bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL,
+ cfg | (DEFAULT_PAUSE_TIME - 0x1000));
+ bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_ZERO, 0x01);
+
/* take lmac_count into account */
bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_THRESH, (0x100 - 1));
/* max packet size */
@@ -970,11 +1024,25 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
lmac_set_training(bgx, lmac, lmac->lmacid);
lmac_set_lane2sds(bgx, lmac);
- /* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */
olmac = &bgx->lmac[idx + 1];
- olmac->lmac_type = lmac->lmac_type;
+ /* Check if other LMAC on the same DLM is already configured by
+ * firmware, if so use the same config or else set as same, as
+ * that of LMAC 0/2.
+ * This check is needed as on 80xx only one lane of each of the
+ * DLM of BGX0 is used, so have to rely on firmware for
+ * distingushing 80xx from 81xx.
+ */
+ cmr_cfg = bgx_reg_read(bgx, idx + 1, BGX_CMRX_CFG);
+ lmac_type = (u8)((cmr_cfg >> 8) & 0x07);
+ lane_to_sds = (u8)(cmr_cfg & 0xFF);
+ if ((lmac_type == 0) && (lane_to_sds == 0xE4)) {
+ olmac->lmac_type = lmac->lmac_type;
+ lmac_set_lane2sds(bgx, olmac);
+ } else {
+ olmac->lmac_type = lmac_type;
+ olmac->lane_to_sds = lane_to_sds;
+ }
lmac_set_training(bgx, olmac, olmac->lmacid);
- lmac_set_lane2sds(bgx, olmac);
}
}
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 01cc7c859131..c18ebfeb2039 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -27,6 +27,7 @@
#define MAX_BGX_CHANS_PER_LMAC 16
#define MAX_DMAC_PER_LMAC 8
#define MAX_FRAME_SIZE 9216
+#define DEFAULT_PAUSE_TIME 0xFFFF
#define BGX_ID_MASK 0x3
@@ -126,7 +127,10 @@
#define SMU_RX_CTL_STATUS (3ull << 0)
#define BGX_SMUX_TX_APPEND 0x20100
#define SMU_TX_APPEND_FCS_D BIT_ULL(2)
+#define BGX_SMUX_TX_PAUSE_PKT_TIME 0x20110
#define BGX_SMUX_TX_MIN_PKT 0x20118
+#define BGX_SMUX_TX_PAUSE_PKT_INTERVAL 0x20120
+#define BGX_SMUX_TX_PAUSE_ZERO 0x20138
#define BGX_SMUX_TX_INT 0x20140
#define BGX_SMUX_TX_CTL 0x20178
#define SMU_TX_CTL_DIC_EN BIT_ULL(0)
@@ -136,6 +140,11 @@
#define BGX_SMUX_CTL 0x20200
#define SMU_CTL_RX_IDLE BIT_ULL(0)
#define SMU_CTL_TX_IDLE BIT_ULL(1)
+#define BGX_SMUX_CBFC_CTL 0x20218
+#define RX_EN BIT_ULL(0)
+#define TX_EN BIT_ULL(1)
+#define BCK_EN BIT_ULL(2)
+#define DRP_EN BIT_ULL(3)
#define BGX_GMP_PCS_MRX_CTL 0x30000
#define PCS_MRX_CTL_RST_AN BIT_ULL(9)
@@ -207,6 +216,9 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
void bgx_lmac_internal_loopback(int node, int bgx_idx,
int lmac_idx, bool enable);
+void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
+void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
+
void xcv_init_hw(void);
void xcv_setup_link(bool link_up, int link_speed);
diff --git a/drivers/net/ethernet/chelsio/cxgb/common.h b/drivers/net/ethernet/chelsio/cxgb/common.h
index 53b1f9478383..6916c62f2487 100644
--- a/drivers/net/ethernet/chelsio/cxgb/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb/common.h
@@ -85,6 +85,11 @@ struct t1_rx_mode {
#define SPEED_INVALID 0xffff
#define DUPLEX_INVALID 0xff
+/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
+#define PM3393_MAX_FRAME_SIZE 9600
+
+#define VSC7326_MAX_MTU 9600
+
enum {
CHBT_BOARD_N110,
CHBT_BOARD_N210,
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index f5f1b0b51ebd..81d1d0bc7553 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -825,8 +825,6 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu)
if (!mac->ops->set_mtu)
return -EOPNOTSUPP;
- if (new_mtu < 68)
- return -EINVAL;
if ((ret = mac->ops->set_mtu(mac, new_mtu)))
return ret;
dev->mtu = new_mtu;
@@ -1101,6 +1099,22 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
netdev->ethtool_ops = &t1_ethtool_ops;
+
+ switch (bi->board) {
+ case CHBT_BOARD_CHT110:
+ case CHBT_BOARD_N110:
+ case CHBT_BOARD_N210:
+ case CHBT_BOARD_CHT210:
+ netdev->max_mtu = PM3393_MAX_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN);
+ break;
+ case CHBT_BOARD_CHN204:
+ netdev->max_mtu = VSC7326_MAX_MTU;
+ break;
+ default:
+ netdev->max_mtu = ETH_DATA_LEN;
+ break;
+ }
}
if (t1_init_sw_modules(adapter, bi) < 0) {
diff --git a/drivers/net/ethernet/chelsio/cxgb/pm3393.c b/drivers/net/ethernet/chelsio/cxgb/pm3393.c
index eb462d7db427..c27908e66f5e 100644
--- a/drivers/net/ethernet/chelsio/cxgb/pm3393.c
+++ b/drivers/net/ethernet/chelsio/cxgb/pm3393.c
@@ -47,9 +47,6 @@
#define OFFSET(REG_ADDR) ((REG_ADDR) << 2)
-/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
-#define MAX_FRAME_SIZE 9600
-
#define IPG 12
#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
@@ -331,10 +328,7 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu)
{
int enabled = cmac->instance->enabled;
- /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
- mtu += 14 + 4;
- if (mtu > MAX_FRAME_SIZE)
- return -EINVAL;
+ mtu += ETH_HLEN + ETH_FCS_LEN;
/* Disable Rx/Tx MAC before configuring it. */
if (enabled)
diff --git a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
index 6f30b6f78553..bdc895bd2a46 100644
--- a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
+++ b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
@@ -11,8 +11,6 @@
/* 30 minutes for full statistics update */
#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
-#define MAX_MTU 9600
-
/* The egress WM value 0x01a01fff should be used only when the
* interface is down (MAC port disabled). This is a workaround
* for disabling the T2/MAC flow-control. When the interface is
@@ -452,9 +450,6 @@ static int mac_set_mtu(struct cmac *mac, int mtu)
{
int port = mac->instance->index;
- if (mtu > MAX_MTU)
- return -EINVAL;
-
/* max_len includes header and FCS */
vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
return 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 43da891fab97..092b3c16440b 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2531,8 +2531,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
struct adapter *adapter = pi->adapter;
int ret;
- if (new_mtu < 81) /* accommodate SACK */
- return -EINVAL;
if ((ret = t3_mac_set_mtu(&pi->mac, new_mtu)))
return ret;
dev->mtu = new_mtu;
@@ -3295,6 +3293,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &cxgb_netdev_ops;
netdev->ethtool_ops = &cxgb_ethtool_ops;
+ netdev->min_mtu = 81;
+ netdev->max_mtu = ETH_MAX_MTU;
}
pci_set_drvdata(pdev, adapter);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 2125903043fb..0bce1bf9ca0f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -635,6 +635,7 @@ struct tx_sw_desc;
struct sge_txq {
unsigned int in_use; /* # of in-use Tx descriptors */
+ unsigned int q_type; /* Q type Eth/Ctrl/Ofld */
unsigned int size; /* # of descriptors */
unsigned int cidx; /* SW consumer index */
unsigned int pidx; /* producer index */
@@ -665,7 +666,7 @@ struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
unsigned long mapping_err; /* # of I/O MMU packet mapping errors */
} ____cacheline_aligned_in_smp;
-struct sge_ofld_txq { /* state for an SGE offload Tx queue */
+struct sge_uld_txq { /* state for an SGE offload Tx queue */
struct sge_txq q;
struct adapter *adap;
struct sk_buff_head sendq; /* list of backpressured packets */
@@ -693,14 +694,20 @@ struct sge_uld_rxq_info {
u8 uld; /* uld type */
};
+struct sge_uld_txq_info {
+ struct sge_uld_txq *uldtxq; /* Txq's for ULD */
+ atomic_t users; /* num users */
+ u16 ntxq; /* # of egress uld queues */
+};
+
struct sge {
struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
- struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS];
struct sge_ctrl_txq ctrlq[MAX_CTRL_QUEUES];
struct sge_eth_rxq ethrxq[MAX_ETH_QSETS];
struct sge_rspq fw_evtq ____cacheline_aligned_in_smp;
struct sge_uld_rxq_info **uld_rxq_info;
+ struct sge_uld_txq_info **uld_txq_info;
struct sge_rspq intrq ____cacheline_aligned_in_smp;
spinlock_t intrq_lock;
@@ -1298,8 +1305,9 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
unsigned int cmplqid);
int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
unsigned int cmplqid);
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
- struct net_device *dev, unsigned int iqid);
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+ struct net_device *dev, unsigned int iqid,
+ unsigned int uld_type);
irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
int t4_sge_init(struct adapter *adap);
void t4_sge_start(struct adapter *adap);
@@ -1661,4 +1669,7 @@ int t4_uld_mem_alloc(struct adapter *adap);
void t4_uld_clean_up(struct adapter *adap);
void t4_register_netevent_notifier(void);
void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
+void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+ unsigned int n, bool unmap);
+void free_txq(struct adapter *adap, struct sge_txq *q);
#endif /* __CXGB4_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 20455d082cb8..acc231293e4d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -2512,18 +2512,6 @@ do { \
RL("FLLow:", fl.low);
RL("FLStarving:", fl.starving);
- } else if (ofld_idx < ofld_entries) {
- const struct sge_ofld_txq *tx =
- &adap->sge.ofldtxq[ofld_idx * 4];
- int n = min(4, adap->sge.ofldqsets - 4 * ofld_idx);
-
- S("QType:", "OFLD-Txq");
- T("TxQ ID:", q.cntxt_id);
- T("TxQ size:", q.size);
- T("TxQ inuse:", q.in_use);
- T("TxQ CIDX:", q.cidx);
- T("TxQ PIDX:", q.pidx);
-
} else if (ctrl_idx < ctrl_entries) {
const struct sge_ctrl_txq *tx = &adap->sge.ctrlq[ctrl_idx * 4];
int n = min(4, adap->params.nports - 4 * ctrl_idx);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 19dc9e25aa72..66c37fac59b2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -134,24 +134,6 @@ MODULE_FIRMWARE(FW5_FNAME);
MODULE_FIRMWARE(FW6_FNAME);
/*
- * Normally we're willing to become the firmware's Master PF but will be happy
- * if another PF has already become the Master and initialized the adapter.
- * Setting "force_init" will cause this driver to forcibly establish itself as
- * the Master PF and initialize the adapter.
- */
-static uint force_init;
-
-module_param(force_init, uint, 0644);
-MODULE_PARM_DESC(force_init, "Forcibly become Master PF and initialize adapter,"
- "deprecated parameter");
-
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0644);
-MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T4 default message enable bitmap, "
- "deprecated parameter");
-
-/*
* The driver uses the best interrupt scheme available on a platform in the
* order MSI-X, MSI, legacy INTx interrupts. This parameter determines which
* of these schemes the driver may consider as follows:
@@ -179,16 +161,6 @@ MODULE_PARM_DESC(msi, "whether to use INTx (0), MSI (1) or MSI-X (2)");
*/
static int rx_dma_offset = 2;
-#ifdef CONFIG_PCI_IOV
-/* Configure the number of PCI-E Virtual Function which are to be instantiated
- * on SR-IOV Capable Physical Functions.
- */
-static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV];
-
-module_param_array(num_vf, uint, NULL, 0644);
-MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3, deprecated parameter - please use the pci sysfs interface.");
-#endif
-
/* TX Queue select used to determine what algorithm to use for selecting TX
* queue. Select between the kernel provided function (select_queue=0) or user
* cxgb_select_queue function (select_queue=1)
@@ -530,15 +502,15 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
txq->restarts++;
- if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
+ if (txq->q_type == CXGB4_TXQ_ETH) {
struct sge_eth_txq *eq;
eq = container_of(txq, struct sge_eth_txq, q);
netif_tx_wake_queue(eq->txq);
} else {
- struct sge_ofld_txq *oq;
+ struct sge_uld_txq *oq;
- oq = container_of(txq, struct sge_ofld_txq, q);
+ oq = container_of(txq, struct sge_uld_txq, q);
tasklet_schedule(&oq->qresume_tsk);
}
} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
@@ -885,15 +857,6 @@ static int setup_sge_queues(struct adapter *adap)
}
}
- j = s->ofldqsets / adap->params.nports; /* iscsi queues per channel */
- for_each_ofldtxq(s, i) {
- err = t4_sge_alloc_ofld_txq(adap, &s->ofldtxq[i],
- adap->port[i / j],
- s->fw_evtq.cntxt_id);
- if (err)
- goto freeout;
- }
-
for_each_port(adap, i) {
/* Note that cmplqid below is 0 if we don't
* have RDMA queues, and that's the right value.
@@ -1922,8 +1885,18 @@ static void disable_dbs(struct adapter *adap)
for_each_ethrxq(&adap->sge, i)
disable_txq_db(&adap->sge.ethtxq[i].q);
- for_each_ofldtxq(&adap->sge, i)
- disable_txq_db(&adap->sge.ofldtxq[i].q);
+ if (is_offload(adap)) {
+ struct sge_uld_txq_info *txq_info =
+ adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+ if (txq_info) {
+ for_each_ofldtxq(&adap->sge, i) {
+ struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+ disable_txq_db(&txq->q);
+ }
+ }
+ }
for_each_port(adap, i)
disable_txq_db(&adap->sge.ctrlq[i].q);
}
@@ -1934,8 +1907,18 @@ static void enable_dbs(struct adapter *adap)
for_each_ethrxq(&adap->sge, i)
enable_txq_db(adap, &adap->sge.ethtxq[i].q);
- for_each_ofldtxq(&adap->sge, i)
- enable_txq_db(adap, &adap->sge.ofldtxq[i].q);
+ if (is_offload(adap)) {
+ struct sge_uld_txq_info *txq_info =
+ adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+ if (txq_info) {
+ for_each_ofldtxq(&adap->sge, i) {
+ struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+ enable_txq_db(adap, &txq->q);
+ }
+ }
+ }
for_each_port(adap, i)
enable_txq_db(adap, &adap->sge.ctrlq[i].q);
}
@@ -2006,8 +1989,17 @@ static void recover_all_queues(struct adapter *adap)
for_each_ethrxq(&adap->sge, i)
sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
- for_each_ofldtxq(&adap->sge, i)
- sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
+ if (is_offload(adap)) {
+ struct sge_uld_txq_info *txq_info =
+ adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+ if (txq_info) {
+ for_each_ofldtxq(&adap->sge, i) {
+ struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+ sync_txq_pidx(adap, &txq->q);
+ }
+ }
+ }
for_each_port(adap, i)
sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
}
@@ -2502,8 +2494,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
int ret;
struct port_info *pi = netdev_priv(dev);
- if (new_mtu < 81 || new_mtu > MAX_MTU) /* accommodate SACK */
- return -EINVAL;
ret = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, new_mtu, -1,
-1, -1, -1, true);
if (!ret)
@@ -3993,7 +3983,7 @@ static inline bool is_x_10g_port(const struct link_config *lc)
static void cfg_queues(struct adapter *adap)
{
struct sge *s = &adap->sge;
- int i, n10g = 0, qidx = 0;
+ int i = 0, n10g = 0, qidx = 0;
#ifndef CONFIG_CHELSIO_T4_DCB
int q10g = 0;
#endif
@@ -4008,8 +3998,7 @@ static void cfg_queues(struct adapter *adap)
adap->params.crypto = 0;
}
- for_each_port(adap, i)
- n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
+ n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
#ifdef CONFIG_CHELSIO_T4_DCB
/* For Data Center Bridging support we need to be able to support up
* to 8 Traffic Priorities; each of which will be assigned to its
@@ -4077,9 +4066,6 @@ static void cfg_queues(struct adapter *adap)
for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++)
s->ctrlq[i].q.size = 512;
- for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++)
- s->ofldtxq[i].q.size = 1024;
-
init_rspq(adap, &s->fw_evtq, 0, 1, 1024, 64);
init_rspq(adap, &s->intrq, 0, 1, 512, 64);
}
@@ -4715,7 +4701,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->name = pci_name(pdev);
adapter->mbox = func;
adapter->pf = func;
- adapter->msg_enable = dflt_msg_enable;
+ adapter->msg_enable = DFLT_MSG_ENABLE;
memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
spin_lock_init(&adapter->stats_lock);
@@ -4803,6 +4789,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 81 - 9600 */
+ netdev->min_mtu = 81;
+ netdev->max_mtu = MAX_MTU;
+
netdev->netdev_ops = &cxgb4_netdev_ops;
#ifdef CONFIG_CHELSIO_T4_DCB
netdev->dcbnl_ops = &cxgb4_dcb_ops;
@@ -4971,17 +4961,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
sriov:
#ifdef CONFIG_PCI_IOV
- if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0) {
- dev_warn(&pdev->dev,
- "Enabling SR-IOV VFs using the num_vf module "
- "parameter is deprecated - please use the pci sysfs "
- "interface instead.\n");
- if (pci_enable_sriov(pdev, num_vf[func]) == 0)
- dev_info(&pdev->dev,
- "instantiated %u virtual functions\n",
- num_vf[func]);
- }
-
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) {
err = -ENOMEM;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
index 49d2debb334e..52af62e0ecb6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
@@ -113,7 +113,7 @@ static int fill_action_fields(struct adapter *adap,
}
/* Re-direct to specified port in hardware. */
- if (is_tcf_mirred_redirect(a)) {
+ if (is_tcf_mirred_egress_redirect(a)) {
struct net_device *n_dev;
unsigned int i, index;
bool found = false;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
index 2471ff465d5c..8098902c094a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -447,6 +447,106 @@ static void quiesce_rx_uld(struct adapter *adap, unsigned int uld_type)
quiesce_rx(adap, &rxq_info->uldrxq[idx].rspq);
}
+static void
+free_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info)
+{
+ int nq = txq_info->ntxq;
+ int i;
+
+ for (i = 0; i < nq; i++) {
+ struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+ if (txq && txq->q.desc) {
+ tasklet_kill(&txq->qresume_tsk);
+ t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
+ txq->q.cntxt_id);
+ free_tx_desc(adap, &txq->q, txq->q.in_use, false);
+ kfree(txq->q.sdesc);
+ __skb_queue_purge(&txq->sendq);
+ free_txq(adap, &txq->q);
+ }
+ }
+}
+
+static int
+alloc_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info,
+ unsigned int uld_type)
+{
+ struct sge *s = &adap->sge;
+ int nq = txq_info->ntxq;
+ int i, j, err;
+
+ j = nq / adap->params.nports;
+ for (i = 0; i < nq; i++) {
+ struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+ txq->q.size = 1024;
+ err = t4_sge_alloc_uld_txq(adap, txq, adap->port[i / j],
+ s->fw_evtq.cntxt_id, uld_type);
+ if (err)
+ goto freeout;
+ }
+ return 0;
+freeout:
+ free_sge_txq_uld(adap, txq_info);
+ return err;
+}
+
+static void
+release_sge_txq_uld(struct adapter *adap, unsigned int uld_type)
+{
+ struct sge_uld_txq_info *txq_info = NULL;
+ int tx_uld_type = TX_ULD(uld_type);
+
+ txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+ if (txq_info && atomic_dec_and_test(&txq_info->users)) {
+ free_sge_txq_uld(adap, txq_info);
+ kfree(txq_info->uldtxq);
+ kfree(txq_info);
+ adap->sge.uld_txq_info[tx_uld_type] = NULL;
+ }
+}
+
+static int
+setup_sge_txq_uld(struct adapter *adap, unsigned int uld_type,
+ const struct cxgb4_uld_info *uld_info)
+{
+ struct sge_uld_txq_info *txq_info = NULL;
+ int tx_uld_type, i;
+
+ tx_uld_type = TX_ULD(uld_type);
+ txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+ if ((tx_uld_type == CXGB4_TX_OFLD) && txq_info &&
+ (atomic_inc_return(&txq_info->users) > 1))
+ return 0;
+
+ txq_info = kzalloc(sizeof(*txq_info), GFP_KERNEL);
+ if (!txq_info)
+ return -ENOMEM;
+
+ i = min_t(int, uld_info->ntxq, num_online_cpus());
+ txq_info->ntxq = roundup(i, adap->params.nports);
+
+ txq_info->uldtxq = kcalloc(txq_info->ntxq, sizeof(struct sge_uld_txq),
+ GFP_KERNEL);
+ if (!txq_info->uldtxq) {
+ kfree(txq_info);
+ return -ENOMEM;
+ }
+
+ if (alloc_sge_txq_uld(adap, txq_info, tx_uld_type)) {
+ kfree(txq_info->uldtxq);
+ kfree(txq_info);
+ return -ENOMEM;
+ }
+
+ atomic_inc(&txq_info->users);
+ adap->sge.uld_txq_info[tx_uld_type] = txq_info;
+ return 0;
+}
+
static void uld_queue_init(struct adapter *adap, unsigned int uld_type,
struct cxgb4_lld_info *lli)
{
@@ -472,7 +572,15 @@ int t4_uld_mem_alloc(struct adapter *adap)
if (!s->uld_rxq_info)
goto err_uld;
+ s->uld_txq_info = kzalloc(CXGB4_TX_MAX *
+ sizeof(struct sge_uld_txq_info *),
+ GFP_KERNEL);
+ if (!s->uld_txq_info)
+ goto err_uld_rx;
return 0;
+
+err_uld_rx:
+ kfree(s->uld_rxq_info);
err_uld:
kfree(adap->uld);
return -ENOMEM;
@@ -482,6 +590,7 @@ void t4_uld_mem_free(struct adapter *adap)
{
struct sge *s = &adap->sge;
+ kfree(s->uld_txq_info);
kfree(s->uld_rxq_info);
kfree(adap->uld);
}
@@ -616,6 +725,9 @@ int cxgb4_register_uld(enum cxgb4_uld type,
ret = -EBUSY;
goto free_irq;
}
+ ret = setup_sge_txq_uld(adap, type, p);
+ if (ret)
+ goto free_irq;
adap->uld[type] = *p;
uld_attach(adap, type);
adap_idx++;
@@ -644,6 +756,7 @@ out:
break;
adap->uld[type].handle = NULL;
adap->uld[type].add = NULL;
+ release_sge_txq_uld(adap, type);
if (adap->flags & FULL_INIT_DONE)
quiesce_rx_uld(adap, type);
if (adap->flags & USING_MSIX)
@@ -679,6 +792,7 @@ int cxgb4_unregister_uld(enum cxgb4_uld type)
continue;
adap->uld[type].handle = NULL;
adap->uld[type].add = NULL;
+ release_sge_txq_uld(adap, type);
if (adap->flags & FULL_INIT_DONE)
quiesce_rx_uld(adap, type);
if (adap->flags & USING_MSIX)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 2996793b1aaa..4c856605fdfa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -77,6 +77,8 @@ enum {
/* Special asynchronous notification message */
#define CXGB4_MSG_AN ((void *)1)
+#define TX_ULD(uld)(((uld) != CXGB4_ULD_CRYPTO) ? CXGB4_TX_OFLD :\
+ CXGB4_TX_CRYPTO)
struct serv_entry {
void *data;
@@ -223,6 +225,19 @@ enum cxgb4_uld {
CXGB4_ULD_MAX
};
+enum cxgb4_tx_uld {
+ CXGB4_TX_OFLD,
+ CXGB4_TX_CRYPTO,
+ CXGB4_TX_MAX
+};
+
+enum cxgb4_txq_type {
+ CXGB4_TXQ_ETH,
+ CXGB4_TXQ_ULD,
+ CXGB4_TXQ_CTRL,
+ CXGB4_TXQ_MAX
+};
+
enum cxgb4_state {
CXGB4_STATE_UP,
CXGB4_STATE_START_RECOVERY,
@@ -316,6 +331,7 @@ struct cxgb4_uld_info {
void *handle;
unsigned int nrxq;
unsigned int rxq_size;
+ unsigned int ntxq;
bool ciq;
bool lro;
void *(*add)(const struct cxgb4_lld_info *p);
@@ -333,6 +349,7 @@ struct cxgb4_uld_info {
int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type);
int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
+int cxgb4_crypto_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);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index e19a0ca8e5dd..9f606478c29c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -377,8 +377,8 @@ unmap: dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
* Reclaims Tx descriptors from an SGE Tx queue and frees the associated
* Tx buffers. Called with the Tx queue lock held.
*/
-static void free_tx_desc(struct adapter *adap, struct sge_txq *q,
- unsigned int n, bool unmap)
+void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+ unsigned int n, bool unmap)
{
struct tx_sw_desc *d;
unsigned int cidx = q->cidx;
@@ -1543,7 +1543,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
* inability to map packets. A periodic timer attempts to restart
* queues so marked.
*/
-static void txq_stop_maperr(struct sge_ofld_txq *q)
+static void txq_stop_maperr(struct sge_uld_txq *q)
{
q->mapping_err++;
q->q.stops++;
@@ -1559,7 +1559,7 @@ static void txq_stop_maperr(struct sge_ofld_txq *q)
* Stops an offload Tx queue that has become full and modifies the packet
* being written to request a wakeup.
*/
-static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
+static void ofldtxq_stop(struct sge_uld_txq *q, struct sk_buff *skb)
{
struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data;
@@ -1586,7 +1586,7 @@ static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
* boolean "service_ofldq_running" to make sure that only one instance
* is ever running at a time ...
*/
-static void service_ofldq(struct sge_ofld_txq *q)
+static void service_ofldq(struct sge_uld_txq *q)
{
u64 *pos, *before, *end;
int credits;
@@ -1706,7 +1706,7 @@ static void service_ofldq(struct sge_ofld_txq *q)
*
* Send an offload packet through an SGE offload queue.
*/
-static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
+static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb)
{
skb->priority = calc_tx_flits_ofld(skb); /* save for restart */
spin_lock(&q->sendq.lock);
@@ -1735,7 +1735,7 @@ static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
*/
static void restart_ofldq(unsigned long data)
{
- struct sge_ofld_txq *q = (struct sge_ofld_txq *)data;
+ struct sge_uld_txq *q = (struct sge_uld_txq *)data;
spin_lock(&q->sendq.lock);
q->full = 0; /* the queue actually is completely empty now */
@@ -1767,17 +1767,23 @@ static inline unsigned int is_ctrl_pkt(const struct sk_buff *skb)
return skb->queue_mapping & 1;
}
-static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
+static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
+ unsigned int tx_uld_type)
{
+ struct sge_uld_txq_info *txq_info;
+ struct sge_uld_txq *txq;
unsigned int idx = skb_txq(skb);
+ txq_info = adap->sge.uld_txq_info[tx_uld_type];
+ txq = &txq_info->uldtxq[idx];
+
if (unlikely(is_ctrl_pkt(skb))) {
/* Single ctrl queue is a requirement for LE workaround path */
if (adap->tids.nsftids)
idx = 0;
return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
}
- return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
+ return ofld_xmit(txq, skb);
}
/**
@@ -1794,7 +1800,7 @@ int t4_ofld_send(struct adapter *adap, struct sk_buff *skb)
int ret;
local_bh_disable();
- ret = ofld_send(adap, skb);
+ ret = uld_send(adap, skb, CXGB4_TX_OFLD);
local_bh_enable();
return ret;
}
@@ -1813,6 +1819,39 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
}
EXPORT_SYMBOL(cxgb4_ofld_send);
+/**
+ * t4_crypto_send - send crypto packet
+ * @adap: the adapter
+ * @skb: the packet
+ *
+ * Sends crypto packet. We use the packet queue_mapping to select the
+ * appropriate Tx queue as follows: bit 0 indicates whether the packet
+ * should be sent as regular or control, bits 1-15 select the queue.
+ */
+static int t4_crypto_send(struct adapter *adap, struct sk_buff *skb)
+{
+ int ret;
+
+ local_bh_disable();
+ ret = uld_send(adap, skb, CXGB4_TX_CRYPTO);
+ local_bh_enable();
+ return ret;
+}
+
+/**
+ * cxgb4_crypto_send - send crypto packet
+ * @dev: the net device
+ * @skb: the packet
+ *
+ * Sends crypto packet. This is an exported version of @t4_crypto_send,
+ * intended for ULDs.
+ */
+int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb)
+{
+ return t4_crypto_send(netdev2adap(dev), skb);
+}
+EXPORT_SYMBOL(cxgb4_crypto_send);
+
static inline void copy_frags(struct sk_buff *skb,
const struct pkt_gl *gl, unsigned int offset)
{
@@ -2479,7 +2518,7 @@ static void sge_tx_timer_cb(unsigned long data)
for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
for (m = s->txq_maperr[i]; m; m &= m - 1) {
unsigned long id = __ffs(m) + i * BITS_PER_LONG;
- struct sge_ofld_txq *txq = s->egr_map[id];
+ struct sge_uld_txq *txq = s->egr_map[id];
clear_bit(id, s->txq_maperr);
tasklet_schedule(&txq->qresume_tsk);
@@ -2799,6 +2838,7 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_ETH;
init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd)));
txq->txq = netdevq;
txq->tso = txq->tx_cso = txq->vlan_ins = 0;
@@ -2852,6 +2892,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_CTRL;
init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid)));
txq->adap = adap;
skb_queue_head_init(&txq->sendq);
@@ -2872,13 +2913,15 @@ int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
return t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param, &val);
}
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
- struct net_device *dev, unsigned int iqid)
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+ struct net_device *dev, unsigned int iqid,
+ unsigned int uld_type)
{
int ret, nentries;
struct fw_eq_ofld_cmd c;
struct sge *s = &adap->sge;
struct port_info *pi = netdev_priv(dev);
+ int cmd = FW_EQ_OFLD_CMD;
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@ -2891,7 +2934,9 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
return -ENOMEM;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F |
+ if (unlikely(uld_type == CXGB4_TX_CRYPTO))
+ cmd = FW_EQ_CTRL_CMD;
+ c.op_to_vfn = htonl(FW_CMD_OP_V(cmd) | FW_CMD_REQUEST_F |
FW_CMD_WRITE_F | FW_CMD_EXEC_F |
FW_EQ_OFLD_CMD_PFN_V(adap->pf) |
FW_EQ_OFLD_CMD_VFN_V(0));
@@ -2919,6 +2964,7 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_ULD;
init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd)));
txq->adap = adap;
skb_queue_head_init(&txq->sendq);
@@ -2928,7 +2974,7 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
return 0;
}
-static void free_txq(struct adapter *adap, struct sge_txq *q)
+void free_txq(struct adapter *adap, struct sge_txq *q)
{
struct sge *s = &adap->sge;
@@ -3025,21 +3071,6 @@ void t4_free_sge_resources(struct adapter *adap)
}
}
- /* clean up offload Tx queues */
- for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
- struct sge_ofld_txq *q = &adap->sge.ofldtxq[i];
-
- if (q->q.desc) {
- tasklet_kill(&q->qresume_tsk);
- t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
- q->q.cntxt_id);
- free_tx_desc(adap, &q->q, q->q.in_use, false);
- kfree(q->q.sdesc);
- __skb_queue_purge(&q->sendq);
- free_txq(adap, &q->q);
- }
- }
-
/* clean up control Tx queues */
for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
@@ -3092,12 +3123,34 @@ void t4_sge_stop(struct adapter *adap)
if (s->tx_timer.function)
del_timer_sync(&s->tx_timer);
- for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++) {
- struct sge_ofld_txq *q = &s->ofldtxq[i];
+ if (is_offload(adap)) {
+ struct sge_uld_txq_info *txq_info;
+
+ txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+ if (txq_info) {
+ struct sge_uld_txq *txq = txq_info->uldtxq;
- if (q->q.desc)
- tasklet_kill(&q->qresume_tsk);
+ for_each_ofldtxq(&adap->sge, i) {
+ if (txq->q.desc)
+ tasklet_kill(&txq->qresume_tsk);
+ }
+ }
}
+
+ if (is_pci_uld(adap)) {
+ struct sge_uld_txq_info *txq_info;
+
+ txq_info = adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+ if (txq_info) {
+ struct sge_uld_txq *txq = txq_info->uldtxq;
+
+ for_each_ofldtxq(&adap->sge, i) {
+ if (txq->q.desc)
+ tasklet_kill(&txq->qresume_tsk);
+ }
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
struct sge_ctrl_txq *cq = &s->ctrlq[i];
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index a37481c04a87..0d1a134c8174 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -70,13 +70,6 @@
NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0644);
-MODULE_PARM_DESC(dflt_msg_enable,
- "default adapter ethtool message level bitmap, "
- "deprecated parameter");
-
/*
* The driver uses the best interrupt scheme available on a platform in the
* order MSI-X then MSI. This parameter determines which of these schemes the
@@ -1108,10 +1101,6 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
int ret;
struct port_info *pi = netdev_priv(dev);
- /* accommodate SACK */
- if (new_mtu < 81)
- return -EINVAL;
-
ret = t4vf_set_rxmode(pi->adapter, pi->viid, new_mtu,
-1, -1, -1, -1, true);
if (!ret)
@@ -2895,7 +2884,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
* Initialize adapter level features.
*/
adapter->name = pci_name(pdev);
- adapter->msg_enable = dflt_msg_enable;
+ adapter->msg_enable = DFLT_MSG_ENABLE;
err = adap_init0(adapter);
if (err)
goto err_unmap_bar;
@@ -2966,6 +2955,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_HIGHDMA;
netdev->priv_flags |= IFF_UNICAST_FLT;
+ netdev->min_mtu = 81;
+ netdev->max_mtu = ETH_MAX_MTU;
netdev->netdev_ops = &cxgb4vf_netdev_ops;
netdev->ethtool_ops = &cxgb4vf_ethtool_ops;
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index c363b58552e9..3647b28e8de0 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -1266,7 +1266,6 @@ static const struct net_device_ops net_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = net_poll_controller,
#endif
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index 9a161e981529..a1de0d12927d 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -753,7 +753,6 @@ static const struct net_device_ops ep93xx_netdev_ops = {
.ndo_start_xmit = ep93xx_xmit,
.ndo_do_ioctl = ep93xx_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
index 07719676c305..b600fbbbf679 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -172,7 +172,6 @@ static const struct net_device_ops mac89x0_netdev_ops = {
.ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
/* Probe for the CS8900 card in slot E. We won't bother looking
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 130f910e4785..9023c858715d 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -33,7 +33,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.3.0.20"
+#define DRV_VERSION "2.3.0.31"
#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 48f82ab6c25b..cdd7a1a59aa7 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1166,12 +1166,18 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, q_number);
if (netdev->features & NETIF_F_RXHASH) {
- skb_set_hash(skb, rss_hash,
- (rss_type &
- (NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX |
- NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 |
- NIC_CFG_RSS_HASH_TYPE_TCP_IPV4)) ?
- PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
+ switch (rss_type) {
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
+ case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
+ skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
+ break;
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
+ case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
+ skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
+ break;
+ }
}
/* Hardware does not provide whole packet checksum. It only
@@ -1843,9 +1849,6 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
struct enic *enic = netdev_priv(netdev);
int running = netif_running(netdev);
- if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
- return -EINVAL;
-
if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
return -EOPNOTSUPP;
@@ -2751,6 +2754,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 68 - 9000 */
+ netdev->min_mtu = ENIC_MIN_MTU;
+ netdev->max_mtu = ENIC_MAX_MTU;
+
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Cannot register net device, aborting\n");
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.h b/drivers/net/ethernet/cisco/enic/enic_res.h
index 69f60afd6577..81f98a8b60e9 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.h
+++ b/drivers/net/ethernet/cisco/enic/enic_res.h
@@ -30,7 +30,7 @@
#define ENIC_MIN_RQ_DESCS 64
#define ENIC_MAX_RQ_DESCS 4096
-#define ENIC_MIN_MTU 68
+#define ENIC_MIN_MTU ETH_MIN_MTU
#define ENIC_MAX_MTU 9000
#define ENIC_MULTICAST_PERFECT_FILTERS 32
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index f45385f5c6e5..f1a81c52afe3 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1382,7 +1382,6 @@ static const struct net_device_ops dm9000_netdev_ops = {
.ndo_tx_timeout = dm9000_timeout,
.ndo_set_rx_mode = dm9000_hash_table,
.ndo_do_ioctl = dm9000_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_features = dm9000_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index cadcee645f74..90c573b8ccaf 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1956,7 +1956,6 @@ static const struct net_device_ops de_netdev_ops = {
.ndo_start_xmit = de_start_xmit,
.ndo_get_stats = de_get_stats,
.ndo_tx_timeout = de_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index 6620fc861c47..51fda3a6b13f 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -1085,7 +1085,6 @@ static const struct net_device_ops de4x5_netdev_ops = {
.ndo_get_stats = de4x5_get_stats,
.ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = de4x5_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address= eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index 8ed0fd8b1dda..df4994919456 100644
--- a/drivers/net/ethernet/dec/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -352,7 +352,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = dmfe_stop,
.ndo_start_xmit = dmfe_start_xmit,
.ndo_set_rx_mode = dmfe_set_filter_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index bbde90bc74fe..5f1377449b8f 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1282,7 +1282,6 @@ static const struct net_device_ops tulip_netdev_ops = {
.ndo_get_stats = tulip_get_stats,
.ndo_do_ioctl = private_ioctl,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index e750b5ddc0fb..e1c4133b8787 100644
--- a/drivers/net/ethernet/dec/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -269,7 +269,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = uli526x_stop,
.ndo_start_xmit = uli526x_start_xmit,
.ndo_set_rx_mode = uli526x_set_filter_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 1f62b9423851..feda96d585e7 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -353,7 +353,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 0e721cedfa67..19e4ea15b504 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -174,7 +174,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_open = xircom_open,
.ndo_stop = xircom_close,
.ndo_start_xmit = xircom_start_xmit,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index 78f144696d6b..8c95a8a81e3c 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -76,7 +76,6 @@ static void rio_free_tx (struct net_device *dev, int irq);
static void tx_error (struct net_device *dev, int tx_status);
static int receive_packet (struct net_device *dev);
static void rio_error (struct net_device *dev, int int_status);
-static int change_mtu (struct net_device *dev, int new_mtu);
static void set_multicast (struct net_device *dev);
static struct net_device_stats *get_stats (struct net_device *dev);
static int clear_stats (struct net_device *dev);
@@ -106,7 +105,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_rx_mode = set_multicast,
.ndo_do_ioctl = rio_ioctl,
.ndo_tx_timeout = rio_tx_timeout,
- .ndo_change_mtu = change_mtu,
};
static int
@@ -230,6 +228,10 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
#if 0
dev->features = NETIF_F_IP_CSUM;
#endif
+ /* MTU range: 68 - 1536 or 8000 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = np->jumbo ? MAX_JUMBO : PACKET_SIZE;
+
pci_set_drvdata (pdev, dev);
ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -1198,22 +1200,6 @@ clear_stats (struct net_device *dev)
return 0;
}
-
-static int
-change_mtu (struct net_device *dev, int new_mtu)
-{
- struct netdev_private *np = netdev_priv(dev);
- int max = (np->jumbo) ? MAX_JUMBO : 1536;
-
- if ((new_mtu < 68) || (new_mtu > max)) {
- return -EINVAL;
- }
-
- dev->mtu = new_mtu;
-
- return 0;
-}
-
static void
set_multicast (struct net_device *dev)
{
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 79d80090eac8..eab36acfc0d1 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -580,6 +580,10 @@ static int sundance_probe1(struct pci_dev *pdev,
dev->ethtool_ops = &ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
+ /* MTU range: 68 - 8191 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = 8191;
+
pci_set_drvdata(pdev, dev);
i = register_netdev(dev);
@@ -713,8 +717,6 @@ err_out_netdev:
static int change_mtu(struct net_device *dev, int new_mtu)
{
- if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */
- return -EINVAL;
if (netif_running(dev))
return -EBUSY;
dev->mtu = new_mtu;
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index c3b64cdd0dec..2a17c59f69f9 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -767,7 +767,6 @@ static const struct net_device_ops dnet_netdev_ops = {
.ndo_do_ioctl = dnet_ioctl,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int dnet_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c
index f7b42483921c..57650953ff83 100644
--- a/drivers/net/ethernet/ec_bhf.c
+++ b/drivers/net/ethernet/ec_bhf.c
@@ -482,7 +482,6 @@ static const struct net_device_ops ec_bhf_netdev_ops = {
.ndo_open = ec_bhf_open,
.ndo_stop = ec_bhf_stop,
.ndo_get_stats64 = ec_bhf_get_stats,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr
};
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 93aa2939142a..7e1633bf5a22 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1406,23 +1406,6 @@ drop:
return NETDEV_TX_OK;
}
-static int be_change_mtu(struct net_device *netdev, int new_mtu)
-{
- struct be_adapter *adapter = netdev_priv(netdev);
- struct device *dev = &adapter->pdev->dev;
-
- if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) {
- dev_info(dev, "MTU must be between %d and %d bytes\n",
- BE_MIN_MTU, BE_MAX_MTU);
- return -EINVAL;
- }
-
- dev_info(dev, "MTU changed from %d to %d bytes\n",
- netdev->mtu, new_mtu);
- netdev->mtu = new_mtu;
- return 0;
-}
-
static inline bool be_in_all_promisc(struct be_adapter *adapter)
{
return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
@@ -5215,7 +5198,6 @@ static const struct net_device_ops be_netdev_ops = {
.ndo_start_xmit = be_xmit,
.ndo_set_rx_mode = be_set_rx_mode,
.ndo_set_mac_address = be_mac_addr_set,
- .ndo_change_mtu = be_change_mtu,
.ndo_get_stats64 = be_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = be_vlan_add_vid,
@@ -5265,6 +5247,10 @@ static void be_netdev_init(struct net_device *netdev)
netdev->netdev_ops = &be_netdev_ops;
netdev->ethtool_ops = &be_ethtool_ops;
+
+ /* MTU range: 256 - 9000 */
+ netdev->min_mtu = BE_MIN_MTU;
+ netdev->max_mtu = BE_MAX_MTU;
}
static void be_cleanup(struct be_adapter *adapter)
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index c044667a0a25..45abc81f6f55 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/of_net.h>
#include <linux/module.h>
#include <net/ethoc.h>
@@ -221,6 +222,9 @@ struct ethoc {
struct mii_bus *mdio;
struct clk *clk;
s8 phy_id;
+
+ int old_link;
+ int old_duplex;
};
/**
@@ -572,7 +576,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
/* We always handle the dropped packet interrupt */
if (pending & INT_MASK_BUSY) {
- dev_err(&dev->dev, "packet dropped\n");
+ dev_dbg(&dev->dev, "packet dropped\n");
dev->stats.rx_dropped++;
}
@@ -667,6 +671,32 @@ static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
static void ethoc_mdio_poll(struct net_device *dev)
{
+ struct ethoc *priv = netdev_priv(dev);
+ struct phy_device *phydev = dev->phydev;
+ bool changed = false;
+ u32 mode;
+
+ if (priv->old_link != phydev->link) {
+ changed = true;
+ priv->old_link = phydev->link;
+ }
+
+ if (priv->old_duplex != phydev->duplex) {
+ changed = true;
+ priv->old_duplex = phydev->duplex;
+ }
+
+ if (!changed)
+ return;
+
+ mode = ethoc_read(priv, MODER);
+ if (phydev->duplex == DUPLEX_FULL)
+ mode |= MODER_FULLD;
+ else
+ mode &= ~MODER_FULLD;
+ ethoc_write(priv, MODER, mode);
+
+ phy_print_status(phydev);
}
static int ethoc_mdio_probe(struct net_device *dev)
@@ -685,6 +715,9 @@ static int ethoc_mdio_probe(struct net_device *dev)
return -ENXIO;
}
+ priv->old_duplex = -1;
+ priv->old_link = -1;
+
err = phy_connect_direct(dev, phy, ethoc_mdio_poll,
PHY_INTERFACE_MODE_GMII);
if (err) {
@@ -721,6 +754,9 @@ static int ethoc_open(struct net_device *dev)
netif_start_queue(dev);
}
+ priv->old_link = -1;
+ priv->old_duplex = -1;
+
phy_start(dev->phydev);
napi_enable(&priv->napi);
@@ -966,6 +1002,7 @@ static int ethoc_set_ringparam(struct net_device *dev,
const struct ethtool_ops ethoc_ethtool_ops = {
.get_regs_len = ethoc_get_regs_len,
.get_regs = ethoc_get_regs,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_ringparam = ethoc_get_ringparam,
.set_ringparam = ethoc_set_ringparam,
@@ -1122,11 +1159,9 @@ static int ethoc_probe(struct platform_device *pdev)
memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
priv->phy_id = pdata->phy_id;
} else {
- const uint8_t *mac;
+ const void *mac;
- mac = of_get_property(pdev->dev.of_node,
- "local-mac-address",
- NULL);
+ mac = of_get_mac_address(pdev->dev.of_node);
if (mac)
memcpy(netdev->dev_addr, mac, IFHWADDRLEN);
priv->phy_id = -1;
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index c08bd763172a..6967b287b6e7 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -472,7 +472,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = mii_ioctl,
.ndo_tx_timeout = fealnx_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index d1ca45fbb164..6e490fd2345d 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -8,7 +8,7 @@ config NET_VENDOR_FREESCALE
depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
M523x || M527x || M5272 || M528x || M520x || M532x || \
ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) || \
- ARCH_LAYERSCAPE
+ ARCH_LAYERSCAPE || COMPILE_TEST
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -25,7 +25,7 @@ config FEC
ARCH_MXC || SOC_IMX28)
default ARCH_MXC || SOC_IMX28 if ARM
select PHYLIB
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire and Freescale i.MX processors.
@@ -65,6 +65,7 @@ config FSL_PQ_MDIO
config FSL_XGMAC_MDIO
tristate "Freescale XGMAC MDIO"
select PHYLIB
+ depends on OF
select OF_MDIO
---help---
This driver supports the MDIO bus on the Fman 10G Ethernet MACs, and
@@ -85,6 +86,7 @@ config UGETH_TX_ON_DEMAND
config GIANFAR
tristate "Gianfar Ethernet"
+ depends on HAS_DMA
select FSL_PQ_MDIO
select PHYLIB
select CRC32
@@ -93,4 +95,6 @@ config GIANFAR
and MPC86xx family of chips, the eTSEC on LS1021A and the FEC
on the 8540.
+source "drivers/net/ethernet/freescale/dpaa/Kconfig"
+
endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index cbe21dc7e37e..4a13115155c9 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
obj-$(CONFIG_FSL_FMAN) += fman/
+obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/
diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig
new file mode 100644
index 000000000000..f3a3454805f9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig
@@ -0,0 +1,10 @@
+menuconfig FSL_DPAA_ETH
+ tristate "DPAA Ethernet"
+ depends on FSL_SOC && FSL_DPAA && FSL_FMAN
+ select PHYLIB
+ select FSL_FMAN_MAC
+ ---help---
+ Data Path Acceleration Architecture Ethernet driver,
+ supporting the Freescale QorIQ chips.
+ Depends on Freescale Buffer Manager and Queue Manager
+ driver and Frame Manager Driver.
diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile
new file mode 100644
index 000000000000..7db50bccb137
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale DPAA Ethernet controllers
+#
+
+# Include FMan headers
+FMAN = $(srctree)/drivers/net/ethernet/freescale/fman
+ccflags-y += -I$(FMAN)
+
+obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o
+
+fsl_dpa-objs += dpaa_eth.o dpaa_ethtool.o dpaa_eth_sysfs.o
+CFLAGS_dpaa_eth.o := -I$(src)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
new file mode 100644
index 000000000000..3c48a84dec86
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -0,0 +1,2753 @@
+/* Copyright 2008 - 2016 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/io.h>
+#include <linux/if_arp.h>
+#include <linux/if_vlan.h>
+#include <linux/icmp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/highmem.h>
+#include <linux/percpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/sort.h>
+#include <soc/fsl/bman.h>
+#include <soc/fsl/qman.h>
+
+#include "fman.h"
+#include "fman_port.h"
+#include "mac.h"
+#include "dpaa_eth.h"
+
+/* CREATE_TRACE_POINTS only needs to be defined once. Other dpaa files
+ * using trace events only need to #include <trace/events/sched.h>
+ */
+#define CREATE_TRACE_POINTS
+#include "dpaa_eth_trace.h"
+
+static int debug = -1;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level (0=none,...,16=all)");
+
+static u16 tx_timeout = 1000;
+module_param(tx_timeout, ushort, 0444);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+#define FM_FD_STAT_RX_ERRORS \
+ (FM_FD_ERR_DMA | FM_FD_ERR_PHYSICAL | \
+ FM_FD_ERR_SIZE | FM_FD_ERR_CLS_DISCARD | \
+ FM_FD_ERR_EXTRACTION | FM_FD_ERR_NO_SCHEME | \
+ FM_FD_ERR_PRS_TIMEOUT | FM_FD_ERR_PRS_ILL_INSTRUCT | \
+ FM_FD_ERR_PRS_HDR_ERR)
+
+#define FM_FD_STAT_TX_ERRORS \
+ (FM_FD_ERR_UNSUPPORTED_FORMAT | \
+ FM_FD_ERR_LENGTH | FM_FD_ERR_DMA)
+
+#define DPAA_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+ NETIF_MSG_IFDOWN)
+
+#define DPAA_INGRESS_CS_THRESHOLD 0x10000000
+/* Ingress congestion threshold on FMan ports
+ * The size in bytes of the ingress tail-drop threshold on FMan ports.
+ * Traffic piling up above this value will be rejected by QMan and discarded
+ * by FMan.
+ */
+
+/* Size in bytes of the FQ taildrop threshold */
+#define DPAA_FQ_TD 0x200000
+
+#define DPAA_CS_THRESHOLD_1G 0x06000000
+/* Egress congestion threshold on 1G ports, range 0x1000 .. 0x10000000
+ * The size in bytes of the egress Congestion State notification threshold on
+ * 1G ports. The 1G dTSECs can quite easily be flooded by cores doing Tx in a
+ * tight loop (e.g. by sending UDP datagrams at "while(1) speed"),
+ * and the larger the frame size, the more acute the problem.
+ * So we have to find a balance between these factors:
+ * - avoiding the device staying congested for a prolonged time (risking
+ * the netdev watchdog to fire - see also the tx_timeout module param);
+ * - affecting performance of protocols such as TCP, which otherwise
+ * behave well under the congestion notification mechanism;
+ * - preventing the Tx cores from tightly-looping (as if the congestion
+ * threshold was too low to be effective);
+ * - running out of memory if the CS threshold is set too high.
+ */
+
+#define DPAA_CS_THRESHOLD_10G 0x10000000
+/* The size in bytes of the egress Congestion State notification threshold on
+ * 10G ports, range 0x1000 .. 0x10000000
+ */
+
+/* Largest value that the FQD's OAL field can hold */
+#define FSL_QMAN_MAX_OAL 127
+
+/* Default alignment for start of data in an Rx FD */
+#define DPAA_FD_DATA_ALIGNMENT 16
+
+/* Values for the L3R field of the FM Parse Results
+ */
+/* L3 Type field: First IP Present IPv4 */
+#define FM_L3_PARSE_RESULT_IPV4 0x8000
+/* L3 Type field: First IP Present IPv6 */
+#define FM_L3_PARSE_RESULT_IPV6 0x4000
+/* Values for the L4R field of the FM Parse Results */
+/* L4 Type field: UDP */
+#define FM_L4_PARSE_RESULT_UDP 0x40
+/* L4 Type field: TCP */
+#define FM_L4_PARSE_RESULT_TCP 0x20
+
+#define DPAA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */
+#define DPAA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */
+
+#define FSL_DPAA_BPID_INV 0xff
+#define FSL_DPAA_ETH_MAX_BUF_COUNT 128
+#define FSL_DPAA_ETH_REFILL_THRESHOLD 80
+
+#define DPAA_TX_PRIV_DATA_SIZE 16
+#define DPAA_PARSE_RESULTS_SIZE sizeof(struct fman_prs_result)
+#define DPAA_TIME_STAMP_SIZE 8
+#define DPAA_HASH_RESULTS_SIZE 8
+#define DPAA_RX_PRIV_DATA_SIZE (u16)(DPAA_TX_PRIV_DATA_SIZE + \
+ dpaa_rx_extra_headroom)
+
+#define DPAA_ETH_RX_QUEUES 128
+
+#define DPAA_ENQUEUE_RETRIES 100000
+
+enum port_type {RX, TX};
+
+struct fm_port_fqs {
+ struct dpaa_fq *tx_defq;
+ struct dpaa_fq *tx_errq;
+ struct dpaa_fq *rx_defq;
+ struct dpaa_fq *rx_errq;
+};
+
+/* All the dpa bps in use at any moment */
+static struct dpaa_bp *dpaa_bp_array[BM_MAX_NUM_OF_POOLS];
+
+/* The raw buffer size must be cacheline aligned */
+#define DPAA_BP_RAW_SIZE 4096
+/* When using more than one buffer pool, the raw sizes are as follows:
+ * 1 bp: 4KB
+ * 2 bp: 2KB, 4KB
+ * 3 bp: 1KB, 2KB, 4KB
+ * 4 bp: 1KB, 2KB, 4KB, 8KB
+ */
+static inline size_t bpool_buffer_raw_size(u8 index, u8 cnt)
+{
+ size_t res = DPAA_BP_RAW_SIZE / 4;
+ u8 i;
+
+ for (i = (cnt < 3) ? cnt : 3; i < 3 + index; i++)
+ res *= 2;
+ return res;
+}
+
+/* FMan-DMA requires 16-byte alignment for Rx buffers, but SKB_DATA_ALIGN is
+ * even stronger (SMP_CACHE_BYTES-aligned), so we just get away with that,
+ * via SKB_WITH_OVERHEAD(). We can't rely on netdev_alloc_frag() giving us
+ * half-page-aligned buffers, so we reserve some more space for start-of-buffer
+ * alignment.
+ */
+#define dpaa_bp_size(raw_size) SKB_WITH_OVERHEAD((raw_size) - SMP_CACHE_BYTES)
+
+static int dpaa_max_frm;
+
+static int dpaa_rx_extra_headroom;
+
+#define dpaa_get_max_mtu() \
+ (dpaa_max_frm - (VLAN_ETH_HLEN + ETH_FCS_LEN))
+
+static int dpaa_netdev_init(struct net_device *net_dev,
+ const struct net_device_ops *dpaa_ops,
+ u16 tx_timeout)
+{
+ struct dpaa_priv *priv = netdev_priv(net_dev);
+ struct device *dev = net_dev->dev.parent;
+ struct dpaa_percpu_priv *percpu_priv;
+ const u8 *mac_addr;
+ int i, err;
+
+ /* Although we access another CPU's private data here
+ * we do it at initialization so it is safe
+ */
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ percpu_priv->net_dev = net_dev;
+ }
+
+ net_dev->netdev_ops = dpaa_ops;
+ mac_addr = priv->mac_dev->addr;
+
+ net_dev->mem_start = priv->mac_dev->res->start;
+ net_dev->mem_end = priv->mac_dev->res->end;
+
+ net_dev->min_mtu = ETH_MIN_MTU;
+ net_dev->max_mtu = dpaa_get_max_mtu();
+
+ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_LLTX);
+
+ net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA;
+ /* The kernels enables GSO automatically, if we declare NETIF_F_SG.
+ * For conformity, we'll still declare GSO explicitly.
+ */
+ net_dev->features |= NETIF_F_GSO;
+
+ net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ /* we do not want shared skbs on TX */
+ net_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+
+ net_dev->features |= net_dev->hw_features;
+ net_dev->vlan_features = net_dev->features;
+
+ memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len);
+ memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
+
+ net_dev->ethtool_ops = &dpaa_ethtool_ops;
+
+ net_dev->needed_headroom = priv->tx_headroom;
+ net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout);
+
+ /* start without the RUNNING flag, phylib controls it later */
+ netif_carrier_off(net_dev);
+
+ err = register_netdev(net_dev);
+ if (err < 0) {
+ dev_err(dev, "register_netdev() = %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int dpaa_stop(struct net_device *net_dev)
+{
+ struct mac_device *mac_dev;
+ struct dpaa_priv *priv;
+ int i, err, error;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ netif_tx_stop_all_queues(net_dev);
+ /* Allow the Fman (Tx) port to process in-flight frames before we
+ * try switching it off.
+ */
+ usleep_range(5000, 10000);
+
+ err = mac_dev->stop(mac_dev);
+ if (err < 0)
+ netif_err(priv, ifdown, net_dev, "mac_dev->stop() = %d\n",
+ err);
+
+ for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
+ error = fman_port_disable(mac_dev->port[i]);
+ if (error)
+ err = error;
+ }
+
+ if (net_dev->phydev)
+ phy_disconnect(net_dev->phydev);
+ net_dev->phydev = NULL;
+
+ return err;
+}
+
+static void dpaa_tx_timeout(struct net_device *net_dev)
+{
+ struct dpaa_percpu_priv *percpu_priv;
+ const struct dpaa_priv *priv;
+
+ priv = netdev_priv(net_dev);
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+ netif_crit(priv, timer, net_dev, "Transmit timeout latency: %u ms\n",
+ jiffies_to_msecs(jiffies - dev_trans_start(net_dev)));
+
+ percpu_priv->stats.tx_errors++;
+}
+
+/* Calculates the statistics for the given device by adding the statistics
+ * collected by each CPU.
+ */
+static struct rtnl_link_stats64 *dpaa_get_stats64(struct net_device *net_dev,
+ struct rtnl_link_stats64 *s)
+{
+ int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64);
+ struct dpaa_priv *priv = netdev_priv(net_dev);
+ struct dpaa_percpu_priv *percpu_priv;
+ u64 *netstats = (u64 *)s;
+ u64 *cpustats;
+ int i, j;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ cpustats = (u64 *)&percpu_priv->stats;
+
+ /* add stats from all CPUs */
+ for (j = 0; j < numstats; j++)
+ netstats[j] += cpustats[j];
+ }
+
+ return s;
+}
+
+static struct mac_device *dpaa_mac_dev_get(struct platform_device *pdev)
+{
+ struct platform_device *of_dev;
+ struct dpaa_eth_data *eth_data;
+ struct device *dpaa_dev, *dev;
+ struct device_node *mac_node;
+ struct mac_device *mac_dev;
+
+ dpaa_dev = &pdev->dev;
+ eth_data = dpaa_dev->platform_data;
+ if (!eth_data)
+ return ERR_PTR(-ENODEV);
+
+ mac_node = eth_data->mac_node;
+
+ of_dev = of_find_device_by_node(mac_node);
+ if (!of_dev) {
+ dev_err(dpaa_dev, "of_find_device_by_node(%s) failed\n",
+ mac_node->full_name);
+ of_node_put(mac_node);
+ return ERR_PTR(-EINVAL);
+ }
+ of_node_put(mac_node);
+
+ dev = &of_dev->dev;
+
+ mac_dev = dev_get_drvdata(dev);
+ if (!mac_dev) {
+ dev_err(dpaa_dev, "dev_get_drvdata(%s) failed\n",
+ dev_name(dev));
+ return ERR_PTR(-EINVAL);
+ }
+
+ return mac_dev;
+}
+
+static int dpaa_set_mac_address(struct net_device *net_dev, void *addr)
+{
+ const struct dpaa_priv *priv;
+ struct mac_device *mac_dev;
+ struct sockaddr old_addr;
+ int err;
+
+ priv = netdev_priv(net_dev);
+
+ memcpy(old_addr.sa_data, net_dev->dev_addr, ETH_ALEN);
+
+ err = eth_mac_addr(net_dev, addr);
+ if (err < 0) {
+ netif_err(priv, drv, net_dev, "eth_mac_addr() = %d\n", err);
+ return err;
+ }
+
+ mac_dev = priv->mac_dev;
+
+ err = mac_dev->change_addr(mac_dev->fman_mac,
+ (enet_addr_t *)net_dev->dev_addr);
+ if (err < 0) {
+ netif_err(priv, drv, net_dev, "mac_dev->change_addr() = %d\n",
+ err);
+ /* reverting to previous address */
+ eth_mac_addr(net_dev, &old_addr);
+
+ return err;
+ }
+
+ return 0;
+}
+
+static void dpaa_set_rx_mode(struct net_device *net_dev)
+{
+ const struct dpaa_priv *priv;
+ int err;
+
+ priv = netdev_priv(net_dev);
+
+ if (!!(net_dev->flags & IFF_PROMISC) != priv->mac_dev->promisc) {
+ priv->mac_dev->promisc = !priv->mac_dev->promisc;
+ err = priv->mac_dev->set_promisc(priv->mac_dev->fman_mac,
+ priv->mac_dev->promisc);
+ if (err < 0)
+ netif_err(priv, drv, net_dev,
+ "mac_dev->set_promisc() = %d\n",
+ err);
+ }
+
+ err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
+ if (err < 0)
+ netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
+ err);
+}
+
+static struct dpaa_bp *dpaa_bpid2pool(int bpid)
+{
+ if (WARN_ON(bpid < 0 || bpid >= BM_MAX_NUM_OF_POOLS))
+ return NULL;
+
+ return dpaa_bp_array[bpid];
+}
+
+/* checks if this bpool is already allocated */
+static bool dpaa_bpid2pool_use(int bpid)
+{
+ if (dpaa_bpid2pool(bpid)) {
+ atomic_inc(&dpaa_bp_array[bpid]->refs);
+ return true;
+ }
+
+ return false;
+}
+
+/* called only once per bpid by dpaa_bp_alloc_pool() */
+static void dpaa_bpid2pool_map(int bpid, struct dpaa_bp *dpaa_bp)
+{
+ dpaa_bp_array[bpid] = dpaa_bp;
+ atomic_set(&dpaa_bp->refs, 1);
+}
+
+static int dpaa_bp_alloc_pool(struct dpaa_bp *dpaa_bp)
+{
+ int err;
+
+ if (dpaa_bp->size == 0 || dpaa_bp->config_count == 0) {
+ pr_err("%s: Buffer pool is not properly initialized! Missing size or initial number of buffers\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* If the pool is already specified, we only create one per bpid */
+ if (dpaa_bp->bpid != FSL_DPAA_BPID_INV &&
+ dpaa_bpid2pool_use(dpaa_bp->bpid))
+ return 0;
+
+ if (dpaa_bp->bpid == FSL_DPAA_BPID_INV) {
+ dpaa_bp->pool = bman_new_pool();
+ if (!dpaa_bp->pool) {
+ pr_err("%s: bman_new_pool() failed\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ dpaa_bp->bpid = (u8)bman_get_bpid(dpaa_bp->pool);
+ }
+
+ if (dpaa_bp->seed_cb) {
+ err = dpaa_bp->seed_cb(dpaa_bp);
+ if (err)
+ goto pool_seed_failed;
+ }
+
+ dpaa_bpid2pool_map(dpaa_bp->bpid, dpaa_bp);
+
+ return 0;
+
+pool_seed_failed:
+ pr_err("%s: pool seeding failed\n", __func__);
+ bman_free_pool(dpaa_bp->pool);
+
+ return err;
+}
+
+/* remove and free all the buffers from the given buffer pool */
+static void dpaa_bp_drain(struct dpaa_bp *bp)
+{
+ u8 num = 8;
+ int ret;
+
+ do {
+ struct bm_buffer bmb[8];
+ int i;
+
+ ret = bman_acquire(bp->pool, bmb, num);
+ if (ret < 0) {
+ if (num == 8) {
+ /* we have less than 8 buffers left;
+ * drain them one by one
+ */
+ num = 1;
+ ret = 1;
+ continue;
+ } else {
+ /* Pool is fully drained */
+ break;
+ }
+ }
+
+ if (bp->free_buf_cb)
+ for (i = 0; i < num; i++)
+ bp->free_buf_cb(bp, &bmb[i]);
+ } while (ret > 0);
+}
+
+static void dpaa_bp_free(struct dpaa_bp *dpaa_bp)
+{
+ struct dpaa_bp *bp = dpaa_bpid2pool(dpaa_bp->bpid);
+
+ /* the mapping between bpid and dpaa_bp is done very late in the
+ * allocation procedure; if something failed before the mapping, the bp
+ * was not configured, therefore we don't need the below instructions
+ */
+ if (!bp)
+ return;
+
+ if (!atomic_dec_and_test(&bp->refs))
+ return;
+
+ if (bp->free_buf_cb)
+ dpaa_bp_drain(bp);
+
+ dpaa_bp_array[bp->bpid] = NULL;
+ bman_free_pool(bp->pool);
+}
+
+static void dpaa_bps_free(struct dpaa_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < DPAA_BPS_NUM; i++)
+ dpaa_bp_free(priv->dpaa_bps[i]);
+}
+
+/* Use multiple WQs for FQ assignment:
+ * - Tx Confirmation queues go to WQ1.
+ * - Rx Error and Tx Error queues go to WQ2 (giving them a better chance
+ * to be scheduled, in case there are many more FQs in WQ3).
+ * - Rx Default and Tx queues go to WQ3 (no differentiation between
+ * Rx and Tx traffic).
+ * This ensures that Tx-confirmed buffers are timely released. In particular,
+ * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they
+ * are greatly outnumbered by other FQs in the system, while
+ * dequeue scheduling is round-robin.
+ */
+static inline void dpaa_assign_wq(struct dpaa_fq *fq)
+{
+ switch (fq->fq_type) {
+ case FQ_TYPE_TX_CONFIRM:
+ case FQ_TYPE_TX_CONF_MQ:
+ fq->wq = 1;
+ break;
+ case FQ_TYPE_RX_ERROR:
+ case FQ_TYPE_TX_ERROR:
+ fq->wq = 2;
+ break;
+ case FQ_TYPE_RX_DEFAULT:
+ case FQ_TYPE_TX:
+ fq->wq = 3;
+ break;
+ default:
+ WARN(1, "Invalid FQ type %d for FQID %d!\n",
+ fq->fq_type, fq->fqid);
+ }
+}
+
+static struct dpaa_fq *dpaa_fq_alloc(struct device *dev,
+ u32 start, u32 count,
+ struct list_head *list,
+ enum dpaa_fq_type fq_type)
+{
+ struct dpaa_fq *dpaa_fq;
+ int i;
+
+ dpaa_fq = devm_kzalloc(dev, sizeof(*dpaa_fq) * count,
+ GFP_KERNEL);
+ if (!dpaa_fq)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ dpaa_fq[i].fq_type = fq_type;
+ dpaa_fq[i].fqid = start ? start + i : 0;
+ list_add_tail(&dpaa_fq[i].list, list);
+ }
+
+ for (i = 0; i < count; i++)
+ dpaa_assign_wq(dpaa_fq + i);
+
+ return dpaa_fq;
+}
+
+static int dpaa_alloc_all_fqs(struct device *dev, struct list_head *list,
+ struct fm_port_fqs *port_fqs)
+{
+ struct dpaa_fq *dpaa_fq;
+
+ dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_RX_ERROR);
+ if (!dpaa_fq)
+ goto fq_alloc_failed;
+
+ port_fqs->rx_errq = &dpaa_fq[0];
+
+ dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_RX_DEFAULT);
+ if (!dpaa_fq)
+ goto fq_alloc_failed;
+
+ port_fqs->rx_defq = &dpaa_fq[0];
+
+ if (!dpaa_fq_alloc(dev, 0, DPAA_ETH_TXQ_NUM, list, FQ_TYPE_TX_CONF_MQ))
+ goto fq_alloc_failed;
+
+ dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_TX_ERROR);
+ if (!dpaa_fq)
+ goto fq_alloc_failed;
+
+ port_fqs->tx_errq = &dpaa_fq[0];
+
+ dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_TX_CONFIRM);
+ if (!dpaa_fq)
+ goto fq_alloc_failed;
+
+ port_fqs->tx_defq = &dpaa_fq[0];
+
+ if (!dpaa_fq_alloc(dev, 0, DPAA_ETH_TXQ_NUM, list, FQ_TYPE_TX))
+ goto fq_alloc_failed;
+
+ return 0;
+
+fq_alloc_failed:
+ dev_err(dev, "dpaa_fq_alloc() failed\n");
+ return -ENOMEM;
+}
+
+static u32 rx_pool_channel;
+static DEFINE_SPINLOCK(rx_pool_channel_init);
+
+static int dpaa_get_channel(void)
+{
+ spin_lock(&rx_pool_channel_init);
+ if (!rx_pool_channel) {
+ u32 pool;
+ int ret;
+
+ ret = qman_alloc_pool(&pool);
+
+ if (!ret)
+ rx_pool_channel = pool;
+ }
+ spin_unlock(&rx_pool_channel_init);
+ if (!rx_pool_channel)
+ return -ENOMEM;
+ return rx_pool_channel;
+}
+
+static void dpaa_release_channel(void)
+{
+ qman_release_pool(rx_pool_channel);
+}
+
+static void dpaa_eth_add_channel(u16 channel)
+{
+ u32 pool = QM_SDQCR_CHANNELS_POOL_CONV(channel);
+ const cpumask_t *cpus = qman_affine_cpus();
+ struct qman_portal *portal;
+ int cpu;
+
+ for_each_cpu(cpu, cpus) {
+ portal = qman_get_affine_portal(cpu);
+ qman_p_static_dequeue_add(portal, pool);
+ }
+}
+
+/* Congestion group state change notification callback.
+ * Stops the device's egress queues while they are congested and
+ * wakes them upon exiting congested state.
+ * Also updates some CGR-related stats.
+ */
+static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr,
+ int congested)
+{
+ struct dpaa_priv *priv = (struct dpaa_priv *)container_of(cgr,
+ struct dpaa_priv, cgr_data.cgr);
+
+ if (congested) {
+ priv->cgr_data.congestion_start_jiffies = jiffies;
+ netif_tx_stop_all_queues(priv->net_dev);
+ priv->cgr_data.cgr_congested_count++;
+ } else {
+ priv->cgr_data.congested_jiffies +=
+ (jiffies - priv->cgr_data.congestion_start_jiffies);
+ netif_tx_wake_all_queues(priv->net_dev);
+ }
+}
+
+static int dpaa_eth_cgr_init(struct dpaa_priv *priv)
+{
+ struct qm_mcc_initcgr initcgr;
+ u32 cs_th;
+ int err;
+
+ err = qman_alloc_cgrid(&priv->cgr_data.cgr.cgrid);
+ if (err < 0) {
+ if (netif_msg_drv(priv))
+ pr_err("%s: Error %d allocating CGR ID\n",
+ __func__, err);
+ goto out_error;
+ }
+ priv->cgr_data.cgr.cb = dpaa_eth_cgscn;
+
+ /* Enable Congestion State Change Notifications and CS taildrop */
+ initcgr.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES;
+ initcgr.cgr.cscn_en = QM_CGR_EN;
+
+ /* Set different thresholds based on the MAC speed.
+ * This may turn suboptimal if the MAC is reconfigured at a speed
+ * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link.
+ * In such cases, we ought to reconfigure the threshold, too.
+ */
+ if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
+ cs_th = DPAA_CS_THRESHOLD_10G;
+ else
+ cs_th = DPAA_CS_THRESHOLD_1G;
+ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+ initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
+ initcgr.cgr.cstd_en = QM_CGR_EN;
+
+ err = qman_create_cgr(&priv->cgr_data.cgr, QMAN_CGR_FLAG_USE_INIT,
+ &initcgr);
+ if (err < 0) {
+ if (netif_msg_drv(priv))
+ pr_err("%s: Error %d creating CGR with ID %d\n",
+ __func__, err, priv->cgr_data.cgr.cgrid);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+ goto out_error;
+ }
+ if (netif_msg_drv(priv))
+ pr_debug("Created CGR %d for netdev with hwaddr %pM on QMan channel %d\n",
+ priv->cgr_data.cgr.cgrid, priv->mac_dev->addr,
+ priv->cgr_data.cgr.chan);
+
+out_error:
+ return err;
+}
+
+static inline void dpaa_setup_ingress(const struct dpaa_priv *priv,
+ struct dpaa_fq *fq,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE;
+ fq->channel = priv->channel;
+}
+
+static inline void dpaa_setup_egress(const struct dpaa_priv *priv,
+ struct dpaa_fq *fq,
+ struct fman_port *port,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ if (port) {
+ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL;
+ fq->channel = (u16)fman_port_get_qman_channel_id(port);
+ } else {
+ fq->flags = QMAN_FQ_FLAG_NO_MODIFY;
+ }
+}
+
+static void dpaa_fq_setup(struct dpaa_priv *priv,
+ const struct dpaa_fq_cbs *fq_cbs,
+ struct fman_port *tx_port)
+{
+ int egress_cnt = 0, conf_cnt = 0, num_portals = 0, cpu;
+ const cpumask_t *affine_cpus = qman_affine_cpus();
+ u16 portals[NR_CPUS];
+ struct dpaa_fq *fq;
+
+ for_each_cpu(cpu, affine_cpus)
+ portals[num_portals++] = qman_affine_channel(cpu);
+ if (num_portals == 0)
+ dev_err(priv->net_dev->dev.parent,
+ "No Qman software (affine) channels found");
+
+ /* Initialize each FQ in the list */
+ list_for_each_entry(fq, &priv->dpaa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ dpaa_setup_ingress(priv, fq, &fq_cbs->rx_defq);
+ break;
+ case FQ_TYPE_RX_ERROR:
+ dpaa_setup_ingress(priv, fq, &fq_cbs->rx_errq);
+ break;
+ case FQ_TYPE_TX:
+ dpaa_setup_egress(priv, fq, tx_port,
+ &fq_cbs->egress_ern);
+ /* If we have more Tx queues than the number of cores,
+ * just ignore the extra ones.
+ */
+ if (egress_cnt < DPAA_ETH_TXQ_NUM)
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ break;
+ case FQ_TYPE_TX_CONF_MQ:
+ priv->conf_fqs[conf_cnt++] = &fq->fq_base;
+ /* fall through */
+ case FQ_TYPE_TX_CONFIRM:
+ dpaa_setup_ingress(priv, fq, &fq_cbs->tx_defq);
+ break;
+ case FQ_TYPE_TX_ERROR:
+ dpaa_setup_ingress(priv, fq, &fq_cbs->tx_errq);
+ break;
+ default:
+ dev_warn(priv->net_dev->dev.parent,
+ "Unknown FQ type detected!\n");
+ break;
+ }
+ }
+
+ /* Make sure all CPUs receive a corresponding Tx queue. */
+ while (egress_cnt < DPAA_ETH_TXQ_NUM) {
+ list_for_each_entry(fq, &priv->dpaa_fq_list, list) {
+ if (fq->fq_type != FQ_TYPE_TX)
+ continue;
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ if (egress_cnt == DPAA_ETH_TXQ_NUM)
+ break;
+ }
+ }
+}
+
+static inline int dpaa_tx_fq_to_id(const struct dpaa_priv *priv,
+ struct qman_fq *tx_fq)
+{
+ int i;
+
+ for (i = 0; i < DPAA_ETH_TXQ_NUM; i++)
+ if (priv->egress_fqs[i] == tx_fq)
+ return i;
+
+ return -EINVAL;
+}
+
+static int dpaa_fq_init(struct dpaa_fq *dpaa_fq, bool td_enable)
+{
+ const struct dpaa_priv *priv;
+ struct qman_fq *confq = NULL;
+ struct qm_mcc_initfq initfq;
+ struct device *dev;
+ struct qman_fq *fq;
+ int queue_id;
+ int err;
+
+ priv = netdev_priv(dpaa_fq->net_dev);
+ dev = dpaa_fq->net_dev->dev.parent;
+
+ if (dpaa_fq->fqid == 0)
+ dpaa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ dpaa_fq->init = !(dpaa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+ err = qman_create_fq(dpaa_fq->fqid, dpaa_fq->flags, &dpaa_fq->fq_base);
+ if (err) {
+ dev_err(dev, "qman_create_fq() failed\n");
+ return err;
+ }
+ fq = &dpaa_fq->fq_base;
+
+ if (dpaa_fq->init) {
+ memset(&initfq, 0, sizeof(initfq));
+
+ initfq.we_mask = QM_INITFQ_WE_FQCTRL;
+ /* Note: we may get to keep an empty FQ in cache */
+ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE;
+
+ /* Try to reduce the number of portal interrupts for
+ * Tx Confirmation FQs.
+ */
+ if (dpaa_fq->fq_type == FQ_TYPE_TX_CONFIRM)
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE;
+
+ /* FQ placement */
+ initfq.we_mask |= QM_INITFQ_WE_DESTWQ;
+
+ qm_fqd_set_destwq(&initfq.fqd, dpaa_fq->channel, dpaa_fq->wq);
+
+ /* Put all egress queues in a congestion group of their own.
+ * Sensu stricto, the Tx confirmation queues are Rx FQs,
+ * rather than Tx - but they nonetheless account for the
+ * memory footprint on behalf of egress traffic. We therefore
+ * place them in the netdev's CGR, along with the Tx FQs.
+ */
+ if (dpaa_fq->fq_type == FQ_TYPE_TX ||
+ dpaa_fq->fq_type == FQ_TYPE_TX_CONFIRM ||
+ dpaa_fq->fq_type == FQ_TYPE_TX_CONF_MQ) {
+ initfq.we_mask |= QM_INITFQ_WE_CGID;
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE;
+ initfq.fqd.cgid = (u8)priv->cgr_data.cgr.cgrid;
+ /* Set a fixed overhead accounting, in an attempt to
+ * reduce the impact of fixed-size skb shells and the
+ * driver's needed headroom on system memory. This is
+ * especially the case when the egress traffic is
+ * composed of small datagrams.
+ * Unfortunately, QMan's OAL value is capped to an
+ * insufficient value, but even that is better than
+ * no overhead accounting at all.
+ */
+ initfq.we_mask |= QM_INITFQ_WE_OAC;
+ qm_fqd_set_oac(&initfq.fqd, QM_OAC_CG);
+ qm_fqd_set_oal(&initfq.fqd,
+ min(sizeof(struct sk_buff) +
+ priv->tx_headroom,
+ (size_t)FSL_QMAN_MAX_OAL));
+ }
+
+ if (td_enable) {
+ initfq.we_mask |= QM_INITFQ_WE_TDTHRESH;
+ qm_fqd_set_taildrop(&initfq.fqd, DPAA_FQ_TD, 1);
+ initfq.fqd.fq_ctrl = QM_FQCTRL_TDE;
+ }
+
+ if (dpaa_fq->fq_type == FQ_TYPE_TX) {
+ queue_id = dpaa_tx_fq_to_id(priv, &dpaa_fq->fq_base);
+ if (queue_id >= 0)
+ confq = priv->conf_fqs[queue_id];
+ if (confq) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ /* ContextA: OVOM=1(use contextA2 bits instead of ICAD)
+ * A2V=1 (contextA A2 field is valid)
+ * A0V=1 (contextA A0 field is valid)
+ * B0V=1 (contextB field is valid)
+ * ContextA A2: EBD=1 (deallocate buffers inside FMan)
+ * ContextB B0(ASPID): 0 (absolute Virtual Storage ID)
+ */
+ initfq.fqd.context_a.hi = 0x1e000000;
+ initfq.fqd.context_a.lo = 0x80000000;
+ }
+ }
+
+ /* Put all the ingress queues in our "ingress CGR". */
+ if (priv->use_ingress_cgr &&
+ (dpaa_fq->fq_type == FQ_TYPE_RX_DEFAULT ||
+ dpaa_fq->fq_type == FQ_TYPE_RX_ERROR)) {
+ initfq.we_mask |= QM_INITFQ_WE_CGID;
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE;
+ initfq.fqd.cgid = (u8)priv->ingress_cgr.cgrid;
+ /* Set a fixed overhead accounting, just like for the
+ * egress CGR.
+ */
+ initfq.we_mask |= QM_INITFQ_WE_OAC;
+ qm_fqd_set_oac(&initfq.fqd, QM_OAC_CG);
+ qm_fqd_set_oal(&initfq.fqd,
+ min(sizeof(struct sk_buff) +
+ priv->tx_headroom,
+ (size_t)FSL_QMAN_MAX_OAL));
+ }
+
+ /* Initialization common to all ingress queues */
+ if (dpaa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ initfq.fqd.fq_ctrl |=
+ QM_FQCTRL_HOLDACTIVE;
+ initfq.fqd.context_a.stashing.exclusive =
+ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX |
+ QM_STASHING_EXCL_ANNOTATION;
+ qm_fqd_set_stashing(&initfq.fqd, 1, 2,
+ DIV_ROUND_UP(sizeof(struct qman_fq),
+ 64));
+ }
+
+ err = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ if (err < 0) {
+ dev_err(dev, "qman_init_fq(%u) = %d\n",
+ qman_fq_fqid(fq), err);
+ qman_destroy_fq(fq);
+ return err;
+ }
+ }
+
+ dpaa_fq->fqid = qman_fq_fqid(fq);
+
+ return 0;
+}
+
+static int dpaa_fq_free_entry(struct device *dev, struct qman_fq *fq)
+{
+ const struct dpaa_priv *priv;
+ struct dpaa_fq *dpaa_fq;
+ int err, error;
+
+ err = 0;
+
+ dpaa_fq = container_of(fq, struct dpaa_fq, fq_base);
+ priv = netdev_priv(dpaa_fq->net_dev);
+
+ if (dpaa_fq->init) {
+ err = qman_retire_fq(fq, NULL);
+ if (err < 0 && netif_msg_drv(priv))
+ dev_err(dev, "qman_retire_fq(%u) = %d\n",
+ qman_fq_fqid(fq), err);
+
+ error = qman_oos_fq(fq);
+ if (error < 0 && netif_msg_drv(priv)) {
+ dev_err(dev, "qman_oos_fq(%u) = %d\n",
+ qman_fq_fqid(fq), error);
+ if (err >= 0)
+ err = error;
+ }
+ }
+
+ qman_destroy_fq(fq);
+ list_del(&dpaa_fq->list);
+
+ return err;
+}
+
+static int dpaa_fq_free(struct device *dev, struct list_head *list)
+{
+ struct dpaa_fq *dpaa_fq, *tmp;
+ int err, error;
+
+ err = 0;
+ list_for_each_entry_safe(dpaa_fq, tmp, list, list) {
+ error = dpaa_fq_free_entry(dev, (struct qman_fq *)dpaa_fq);
+ if (error < 0 && err >= 0)
+ err = error;
+ }
+
+ return err;
+}
+
+static void dpaa_eth_init_tx_port(struct fman_port *port, struct dpaa_fq *errq,
+ struct dpaa_fq *defq,
+ struct dpaa_buffer_layout *buf_layout)
+{
+ struct fman_buffer_prefix_content buf_prefix_content;
+ struct fman_port_params params;
+ int err;
+
+ memset(&params, 0, sizeof(params));
+ memset(&buf_prefix_content, 0, sizeof(buf_prefix_content));
+
+ buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
+ buf_prefix_content.pass_prs_result = true;
+ buf_prefix_content.pass_hash_result = true;
+ buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
+
+ params.specific_params.non_rx_params.err_fqid = errq->fqid;
+ params.specific_params.non_rx_params.dflt_fqid = defq->fqid;
+
+ err = fman_port_config(port, &params);
+ if (err)
+ pr_err("%s: fman_port_config failed\n", __func__);
+
+ err = fman_port_cfg_buf_prefix_content(port, &buf_prefix_content);
+ if (err)
+ pr_err("%s: fman_port_cfg_buf_prefix_content failed\n",
+ __func__);
+
+ err = fman_port_init(port);
+ if (err)
+ pr_err("%s: fm_port_init failed\n", __func__);
+}
+
+static void dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp **bps,
+ size_t count, struct dpaa_fq *errq,
+ struct dpaa_fq *defq,
+ struct dpaa_buffer_layout *buf_layout)
+{
+ struct fman_buffer_prefix_content buf_prefix_content;
+ struct fman_port_rx_params *rx_p;
+ struct fman_port_params params;
+ int i, err;
+
+ memset(&params, 0, sizeof(params));
+ memset(&buf_prefix_content, 0, sizeof(buf_prefix_content));
+
+ buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
+ buf_prefix_content.pass_prs_result = true;
+ buf_prefix_content.pass_hash_result = true;
+ buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
+
+ rx_p = &params.specific_params.rx_params;
+ rx_p->err_fqid = errq->fqid;
+ rx_p->dflt_fqid = defq->fqid;
+
+ count = min(ARRAY_SIZE(rx_p->ext_buf_pools.ext_buf_pool), count);
+ rx_p->ext_buf_pools.num_of_pools_used = (u8)count;
+ for (i = 0; i < count; i++) {
+ rx_p->ext_buf_pools.ext_buf_pool[i].id = bps[i]->bpid;
+ rx_p->ext_buf_pools.ext_buf_pool[i].size = (u16)bps[i]->size;
+ }
+
+ err = fman_port_config(port, &params);
+ if (err)
+ pr_err("%s: fman_port_config failed\n", __func__);
+
+ err = fman_port_cfg_buf_prefix_content(port, &buf_prefix_content);
+ if (err)
+ pr_err("%s: fman_port_cfg_buf_prefix_content failed\n",
+ __func__);
+
+ err = fman_port_init(port);
+ if (err)
+ pr_err("%s: fm_port_init failed\n", __func__);
+}
+
+static void dpaa_eth_init_ports(struct mac_device *mac_dev,
+ struct dpaa_bp **bps, size_t count,
+ struct fm_port_fqs *port_fqs,
+ struct dpaa_buffer_layout *buf_layout,
+ struct device *dev)
+{
+ struct fman_port *rxport = mac_dev->port[RX];
+ struct fman_port *txport = mac_dev->port[TX];
+
+ dpaa_eth_init_tx_port(txport, port_fqs->tx_errq,
+ port_fqs->tx_defq, &buf_layout[TX]);
+ dpaa_eth_init_rx_port(rxport, bps, count, port_fqs->rx_errq,
+ port_fqs->rx_defq, &buf_layout[RX]);
+}
+
+static int dpaa_bman_release(const struct dpaa_bp *dpaa_bp,
+ struct bm_buffer *bmb, int cnt)
+{
+ int err;
+
+ err = bman_release(dpaa_bp->pool, bmb, cnt);
+ /* Should never occur, address anyway to avoid leaking the buffers */
+ if (unlikely(WARN_ON(err)) && dpaa_bp->free_buf_cb)
+ while (cnt-- > 0)
+ dpaa_bp->free_buf_cb(dpaa_bp, &bmb[cnt]);
+
+ return cnt;
+}
+
+static void dpaa_release_sgt_members(struct qm_sg_entry *sgt)
+{
+ struct bm_buffer bmb[DPAA_BUFF_RELEASE_MAX];
+ struct dpaa_bp *dpaa_bp;
+ int i = 0, j;
+
+ memset(bmb, 0, sizeof(bmb));
+
+ do {
+ dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+ if (!dpaa_bp)
+ return;
+
+ j = 0;
+ do {
+ WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+ bm_buffer_set64(&bmb[j], qm_sg_entry_get64(&sgt[i]));
+
+ j++; i++;
+ } while (j < ARRAY_SIZE(bmb) &&
+ !qm_sg_entry_is_final(&sgt[i - 1]) &&
+ sgt[i - 1].bpid == sgt[i].bpid);
+
+ dpaa_bman_release(dpaa_bp, bmb, j);
+ } while (!qm_sg_entry_is_final(&sgt[i - 1]));
+}
+
+static void dpaa_fd_release(const struct net_device *net_dev,
+ const struct qm_fd *fd)
+{
+ struct qm_sg_entry *sgt;
+ struct dpaa_bp *dpaa_bp;
+ struct bm_buffer bmb;
+ dma_addr_t addr;
+ void *vaddr;
+
+ bmb.data = 0;
+ bm_buffer_set64(&bmb, qm_fd_addr(fd));
+
+ dpaa_bp = dpaa_bpid2pool(fd->bpid);
+ if (!dpaa_bp)
+ return;
+
+ if (qm_fd_get_format(fd) == qm_fd_sg) {
+ vaddr = phys_to_virt(qm_fd_addr(fd));
+ sgt = vaddr + qm_fd_get_offset(fd);
+
+ dma_unmap_single(dpaa_bp->dev, qm_fd_addr(fd), dpaa_bp->size,
+ DMA_FROM_DEVICE);
+
+ dpaa_release_sgt_members(sgt);
+
+ addr = dma_map_single(dpaa_bp->dev, vaddr, dpaa_bp->size,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dpaa_bp->dev, addr)) {
+ dev_err(dpaa_bp->dev, "DMA mapping failed");
+ return;
+ }
+ bm_buffer_set64(&bmb, addr);
+ }
+
+ dpaa_bman_release(dpaa_bp, &bmb, 1);
+}
+
+static void count_ern(struct dpaa_percpu_priv *percpu_priv,
+ const union qm_mr_entry *msg)
+{
+ switch (msg->ern.rc & QM_MR_RC_MASK) {
+ case QM_MR_RC_CGR_TAILDROP:
+ percpu_priv->ern_cnt.cg_tdrop++;
+ break;
+ case QM_MR_RC_WRED:
+ percpu_priv->ern_cnt.wred++;
+ break;
+ case QM_MR_RC_ERROR:
+ percpu_priv->ern_cnt.err_cond++;
+ break;
+ case QM_MR_RC_ORPWINDOW_EARLY:
+ percpu_priv->ern_cnt.early_window++;
+ break;
+ case QM_MR_RC_ORPWINDOW_LATE:
+ percpu_priv->ern_cnt.late_window++;
+ break;
+ case QM_MR_RC_FQ_TAILDROP:
+ percpu_priv->ern_cnt.fq_tdrop++;
+ break;
+ case QM_MR_RC_ORPWINDOW_RETIRED:
+ percpu_priv->ern_cnt.fq_retired++;
+ break;
+ case QM_MR_RC_ORP_ZERO:
+ percpu_priv->ern_cnt.orp_zero++;
+ break;
+ }
+}
+
+/* Turn on HW checksum computation for this outgoing frame.
+ * If the current protocol is not something we support in this regard
+ * (or if the stack has already computed the SW checksum), we do nothing.
+ *
+ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value
+ * otherwise.
+ *
+ * Note that this function may modify the fd->cmd field and the skb data buffer
+ * (the Parse Results area).
+ */
+static int dpaa_enable_tx_csum(struct dpaa_priv *priv,
+ struct sk_buff *skb,
+ struct qm_fd *fd,
+ char *parse_results)
+{
+ struct fman_prs_result *parse_result;
+ u16 ethertype = ntohs(skb->protocol);
+ struct ipv6hdr *ipv6h = NULL;
+ struct iphdr *iph;
+ int retval = 0;
+ u8 l4_proto;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ /* Note: L3 csum seems to be already computed in sw, but we can't choose
+ * L4 alone from the FM configuration anyway.
+ */
+
+ /* Fill in some fields of the Parse Results array, so the FMan
+ * can find them as if they came from the FMan Parser.
+ */
+ parse_result = (struct fman_prs_result *)parse_results;
+
+ /* If we're dealing with VLAN, get the real Ethernet type */
+ if (ethertype == ETH_P_8021Q) {
+ /* We can't always assume the MAC header is set correctly
+ * by the stack, so reset to beginning of skb->data
+ */
+ skb_reset_mac_header(skb);
+ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
+ }
+
+ /* Fill in the relevant L3 parse result fields
+ * and read the L4 protocol type
+ */
+ switch (ethertype) {
+ case ETH_P_IP:
+ parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV4);
+ iph = ip_hdr(skb);
+ WARN_ON(!iph);
+ l4_proto = iph->protocol;
+ break;
+ case ETH_P_IPV6:
+ parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV6);
+ ipv6h = ipv6_hdr(skb);
+ WARN_ON(!ipv6h);
+ l4_proto = ipv6h->nexthdr;
+ break;
+ default:
+ /* We shouldn't even be here */
+ if (net_ratelimit())
+ netif_alert(priv, tx_err, priv->net_dev,
+ "Can't compute HW csum for L3 proto 0x%x\n",
+ ntohs(skb->protocol));
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* Fill in the relevant L4 parse result fields */
+ switch (l4_proto) {
+ case IPPROTO_UDP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_UDP;
+ break;
+ case IPPROTO_TCP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_TCP;
+ break;
+ default:
+ if (net_ratelimit())
+ netif_alert(priv, tx_err, priv->net_dev,
+ "Can't compute HW csum for L4 proto 0x%x\n",
+ l4_proto);
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* At index 0 is IPOffset_1 as defined in the Parse Results */
+ parse_result->ip_off[0] = (u8)skb_network_offset(skb);
+ parse_result->l4_off = (u8)skb_transport_offset(skb);
+
+ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */
+ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC;
+
+ /* On P1023 and similar platforms fd->cmd interpretation could
+ * be disabled by setting CONTEXT_A bit ICMD; currently this bit
+ * is not set so we do not need to check; in the future, if/when
+ * using context_a we need to check this bit
+ */
+
+return_error:
+ return retval;
+}
+
+static int dpaa_bp_add_8_bufs(const struct dpaa_bp *dpaa_bp)
+{
+ struct device *dev = dpaa_bp->dev;
+ struct bm_buffer bmb[8];
+ dma_addr_t addr;
+ void *new_buf;
+ u8 i;
+
+ for (i = 0; i < 8; i++) {
+ new_buf = netdev_alloc_frag(dpaa_bp->raw_size);
+ if (unlikely(!new_buf)) {
+ dev_err(dev, "netdev_alloc_frag() failed, size %zu\n",
+ dpaa_bp->raw_size);
+ goto release_previous_buffs;
+ }
+ new_buf = PTR_ALIGN(new_buf, SMP_CACHE_BYTES);
+
+ addr = dma_map_single(dev, new_buf,
+ dpaa_bp->size, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ dev_err(dpaa_bp->dev, "DMA map failed");
+ goto release_previous_buffs;
+ }
+
+ bmb[i].data = 0;
+ bm_buffer_set64(&bmb[i], addr);
+ }
+
+release_bufs:
+ return dpaa_bman_release(dpaa_bp, bmb, i);
+
+release_previous_buffs:
+ WARN_ONCE(1, "dpaa_eth: failed to add buffers on Rx\n");
+
+ bm_buffer_set64(&bmb[i], 0);
+ /* Avoid releasing a completely null buffer; bman_release() requires
+ * at least one buffer.
+ */
+ if (likely(i))
+ goto release_bufs;
+
+ return 0;
+}
+
+static int dpaa_bp_seed(struct dpaa_bp *dpaa_bp)
+{
+ int i;
+
+ /* Give each CPU an allotment of "config_count" buffers */
+ for_each_possible_cpu(i) {
+ int *count_ptr = per_cpu_ptr(dpaa_bp->percpu_count, i);
+ int j;
+
+ /* Although we access another CPU's counters here
+ * we do it at boot time so it is safe
+ */
+ for (j = 0; j < dpaa_bp->config_count; j += 8)
+ *count_ptr += dpaa_bp_add_8_bufs(dpaa_bp);
+ }
+ return 0;
+}
+
+/* Add buffers/(pages) for Rx processing whenever bpool count falls below
+ * REFILL_THRESHOLD.
+ */
+static int dpaa_eth_refill_bpool(struct dpaa_bp *dpaa_bp, int *countptr)
+{
+ int count = *countptr;
+ int new_bufs;
+
+ if (unlikely(count < FSL_DPAA_ETH_REFILL_THRESHOLD)) {
+ do {
+ new_bufs = dpaa_bp_add_8_bufs(dpaa_bp);
+ if (unlikely(!new_bufs)) {
+ /* Avoid looping forever if we've temporarily
+ * run out of memory. We'll try again at the
+ * next NAPI cycle.
+ */
+ break;
+ }
+ count += new_bufs;
+ } while (count < FSL_DPAA_ETH_MAX_BUF_COUNT);
+
+ *countptr = count;
+ if (unlikely(count < FSL_DPAA_ETH_MAX_BUF_COUNT))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
+{
+ struct dpaa_bp *dpaa_bp;
+ int *countptr;
+ int res, i;
+
+ for (i = 0; i < DPAA_BPS_NUM; i++) {
+ dpaa_bp = priv->dpaa_bps[i];
+ if (!dpaa_bp)
+ return -EINVAL;
+ countptr = this_cpu_ptr(dpaa_bp->percpu_count);
+ res = dpaa_eth_refill_bpool(dpaa_bp, countptr);
+ if (res)
+ return res;
+ }
+ return 0;
+}
+
+/* Cleanup function for outgoing frame descriptors that were built on Tx path,
+ * either contiguous frames or scatter/gather ones.
+ * Skb freeing is not handled here.
+ *
+ * This function may be called on error paths in the Tx function, so guard
+ * against cases when not all fd relevant fields were filled in.
+ *
+ * Return the skb backpointer, since for S/G frames the buffer containing it
+ * gets freed here.
+ */
+static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
+ const struct qm_fd *fd)
+{
+ const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+ struct device *dev = priv->net_dev->dev.parent;
+ dma_addr_t addr = qm_fd_addr(fd);
+ const struct qm_sg_entry *sgt;
+ struct sk_buff **skbh, *skb;
+ int nr_frags, i;
+
+ skbh = (struct sk_buff **)phys_to_virt(addr);
+ skb = *skbh;
+
+ if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
+ sizeof(struct qm_sg_entry) * (1 + nr_frags),
+ dma_dir);
+
+ /* The sgt buffer has been allocated with netdev_alloc_frag(),
+ * it's from lowmem.
+ */
+ sgt = phys_to_virt(addr + qm_fd_get_offset(fd));
+
+ /* sgt[0] is from lowmem, was dma_map_single()-ed */
+ dma_unmap_single(dev, qm_sg_addr(&sgt[0]),
+ qm_sg_entry_get_len(&sgt[0]), dma_dir);
+
+ /* remaining pages were mapped with skb_frag_dma_map() */
+ for (i = 1; i < nr_frags; i++) {
+ WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+ dma_unmap_page(dev, qm_sg_addr(&sgt[i]),
+ qm_sg_entry_get_len(&sgt[i]), dma_dir);
+ }
+
+ /* Free the page frag that we allocated on Tx */
+ skb_free_frag(phys_to_virt(addr));
+ } else {
+ dma_unmap_single(dev, addr,
+ skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
+ }
+
+ return skb;
+}
+
+/* Build a linear skb around the received buffer.
+ * We are guaranteed there is enough room at the end of the data buffer to
+ * accommodate the shared info area of the skb.
+ */
+static struct sk_buff *contig_fd_to_skb(const struct dpaa_priv *priv,
+ const struct qm_fd *fd)
+{
+ ssize_t fd_off = qm_fd_get_offset(fd);
+ dma_addr_t addr = qm_fd_addr(fd);
+ struct dpaa_bp *dpaa_bp;
+ struct sk_buff *skb;
+ void *vaddr;
+
+ vaddr = phys_to_virt(addr);
+ WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+ dpaa_bp = dpaa_bpid2pool(fd->bpid);
+ if (!dpaa_bp)
+ goto free_buffer;
+
+ skb = build_skb(vaddr, dpaa_bp->size +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+ if (unlikely(!skb)) {
+ WARN_ONCE(1, "Build skb failure on Rx\n");
+ goto free_buffer;
+ }
+ WARN_ON(fd_off != priv->rx_headroom);
+ skb_reserve(skb, fd_off);
+ skb_put(skb, qm_fd_get_length(fd));
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ return skb;
+
+free_buffer:
+ skb_free_frag(vaddr);
+ return NULL;
+}
+
+/* Build an skb with the data of the first S/G entry in the linear portion and
+ * the rest of the frame as skb fragments.
+ *
+ * The page fragment holding the S/G Table is recycled here.
+ */
+static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
+ const struct qm_fd *fd)
+{
+ ssize_t fd_off = qm_fd_get_offset(fd);
+ dma_addr_t addr = qm_fd_addr(fd);
+ const struct qm_sg_entry *sgt;
+ struct page *page, *head_page;
+ struct dpaa_bp *dpaa_bp;
+ void *vaddr, *sg_vaddr;
+ int frag_off, frag_len;
+ struct sk_buff *skb;
+ dma_addr_t sg_addr;
+ int page_offset;
+ unsigned int sz;
+ int *count_ptr;
+ int i;
+
+ vaddr = phys_to_virt(addr);
+ WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+ /* Iterate through the SGT entries and add data buffers to the skb */
+ sgt = vaddr + fd_off;
+ for (i = 0; i < DPAA_SGT_MAX_ENTRIES; i++) {
+ /* Extension bit is not supported */
+ WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+ sg_addr = qm_sg_addr(&sgt[i]);
+ sg_vaddr = phys_to_virt(sg_addr);
+ WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
+ SMP_CACHE_BYTES));
+
+ /* We may use multiple Rx pools */
+ dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+ if (!dpaa_bp)
+ goto free_buffers;
+
+ count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+ dma_unmap_single(dpaa_bp->dev, sg_addr, dpaa_bp->size,
+ DMA_FROM_DEVICE);
+ if (i == 0) {
+ sz = dpaa_bp->size +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ skb = build_skb(sg_vaddr, sz);
+ if (WARN_ON(unlikely(!skb)))
+ goto free_buffers;
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Make sure forwarded skbs will have enough space
+ * on Tx, if extra headers are added.
+ */
+ WARN_ON(fd_off != priv->rx_headroom);
+ skb_reserve(skb, fd_off);
+ skb_put(skb, qm_sg_entry_get_len(&sgt[i]));
+ } else {
+ /* Not the first S/G entry; all data from buffer will
+ * be added in an skb fragment; fragment index is offset
+ * by one since first S/G entry was incorporated in the
+ * linear part of the skb.
+ *
+ * Caution: 'page' may be a tail page.
+ */
+ page = virt_to_page(sg_vaddr);
+ head_page = virt_to_head_page(sg_vaddr);
+
+ /* Compute offset in (possibly tail) page */
+ page_offset = ((unsigned long)sg_vaddr &
+ (PAGE_SIZE - 1)) +
+ (page_address(page) - page_address(head_page));
+ /* page_offset only refers to the beginning of sgt[i];
+ * but the buffer itself may have an internal offset.
+ */
+ frag_off = qm_sg_entry_get_off(&sgt[i]) + page_offset;
+ frag_len = qm_sg_entry_get_len(&sgt[i]);
+ /* skb_add_rx_frag() does no checking on the page; if
+ * we pass it a tail page, we'll end up with
+ * bad page accounting and eventually with segafults.
+ */
+ skb_add_rx_frag(skb, i - 1, head_page, frag_off,
+ frag_len, dpaa_bp->size);
+ }
+ /* Update the pool count for the current {cpu x bpool} */
+ (*count_ptr)--;
+
+ if (qm_sg_entry_is_final(&sgt[i]))
+ break;
+ }
+ WARN_ONCE(i == DPAA_SGT_MAX_ENTRIES, "No final bit on SGT\n");
+
+ /* free the SG table buffer */
+ skb_free_frag(vaddr);
+
+ return skb;
+
+free_buffers:
+ /* compensate sw bpool counter changes */
+ for (i--; i > 0; i--) {
+ dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+ if (dpaa_bp) {
+ count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+ (*count_ptr)++;
+ }
+ }
+ /* free all the SG entries */
+ for (i = 0; i < DPAA_SGT_MAX_ENTRIES ; i++) {
+ sg_addr = qm_sg_addr(&sgt[i]);
+ sg_vaddr = phys_to_virt(sg_addr);
+ skb_free_frag(sg_vaddr);
+ dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+ if (dpaa_bp) {
+ count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+ (*count_ptr)--;
+ }
+
+ if (qm_sg_entry_is_final(&sgt[i]))
+ break;
+ }
+ /* free the SGT fragment */
+ skb_free_frag(vaddr);
+
+ return NULL;
+}
+
+static int skb_to_contig_fd(struct dpaa_priv *priv,
+ struct sk_buff *skb, struct qm_fd *fd,
+ int *offset)
+{
+ struct net_device *net_dev = priv->net_dev;
+ struct device *dev = net_dev->dev.parent;
+ enum dma_data_direction dma_dir;
+ unsigned char *buffer_start;
+ struct sk_buff **skbh;
+ dma_addr_t addr;
+ int err;
+
+ /* We are guaranteed to have at least tx_headroom bytes
+ * available, so just use that for offset.
+ */
+ fd->bpid = FSL_DPAA_BPID_INV;
+ buffer_start = skb->data - priv->tx_headroom;
+ dma_dir = DMA_TO_DEVICE;
+
+ skbh = (struct sk_buff **)buffer_start;
+ *skbh = skb;
+
+ /* Enable L3/L4 hardware checksum computation.
+ *
+ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+ * need to write into the skb.
+ */
+ err = dpaa_enable_tx_csum(priv, skb, fd,
+ ((char *)skbh) + DPAA_TX_PRIV_DATA_SIZE);
+ if (unlikely(err < 0)) {
+ if (net_ratelimit())
+ netif_err(priv, tx_err, net_dev, "HW csum error: %d\n",
+ err);
+ return err;
+ }
+
+ /* Fill in the rest of the FD fields */
+ qm_fd_set_contig(fd, priv->tx_headroom, skb->len);
+ fd->cmd |= FM_FD_CMD_FCO;
+
+ /* Map the entire buffer size that may be seen by FMan, but no more */
+ addr = dma_map_single(dev, skbh,
+ skb_tail_pointer(skb) - buffer_start, dma_dir);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ if (net_ratelimit())
+ netif_err(priv, tx_err, net_dev, "dma_map_single() failed\n");
+ return -EINVAL;
+ }
+ qm_fd_addr_set64(fd, addr);
+
+ return 0;
+}
+
+static int skb_to_sg_fd(struct dpaa_priv *priv,
+ struct sk_buff *skb, struct qm_fd *fd)
+{
+ const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+ const int nr_frags = skb_shinfo(skb)->nr_frags;
+ struct net_device *net_dev = priv->net_dev;
+ struct device *dev = net_dev->dev.parent;
+ struct qm_sg_entry *sgt;
+ struct sk_buff **skbh;
+ int i, j, err, sz;
+ void *buffer_start;
+ skb_frag_t *frag;
+ dma_addr_t addr;
+ size_t frag_len;
+ void *sgt_buf;
+
+ /* get a page frag to store the SGTable */
+ sz = SKB_DATA_ALIGN(priv->tx_headroom +
+ sizeof(struct qm_sg_entry) * (1 + nr_frags));
+ sgt_buf = netdev_alloc_frag(sz);
+ if (unlikely(!sgt_buf)) {
+ netdev_err(net_dev, "netdev_alloc_frag() failed for size %d\n",
+ sz);
+ return -ENOMEM;
+ }
+
+ /* Enable L3/L4 hardware checksum computation.
+ *
+ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+ * need to write into the skb.
+ */
+ err = dpaa_enable_tx_csum(priv, skb, fd,
+ sgt_buf + DPAA_TX_PRIV_DATA_SIZE);
+ if (unlikely(err < 0)) {
+ if (net_ratelimit())
+ netif_err(priv, tx_err, net_dev, "HW csum error: %d\n",
+ err);
+ goto csum_failed;
+ }
+
+ sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom);
+ qm_sg_entry_set_len(&sgt[0], skb_headlen(skb));
+ sgt[0].bpid = FSL_DPAA_BPID_INV;
+ sgt[0].offset = 0;
+ addr = dma_map_single(dev, skb->data,
+ skb_headlen(skb), dma_dir);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ dev_err(dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sg0_map_failed;
+ }
+ qm_sg_entry_set64(&sgt[0], addr);
+
+ /* populate the rest of SGT entries */
+ frag = &skb_shinfo(skb)->frags[0];
+ frag_len = frag->size;
+ for (i = 1; i <= nr_frags; i++, frag++) {
+ WARN_ON(!skb_frag_page(frag));
+ addr = skb_frag_dma_map(dev, frag, 0,
+ frag_len, dma_dir);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ dev_err(dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sg_map_failed;
+ }
+
+ qm_sg_entry_set_len(&sgt[i], frag_len);
+ sgt[i].bpid = FSL_DPAA_BPID_INV;
+ sgt[i].offset = 0;
+
+ /* keep the offset in the address */
+ qm_sg_entry_set64(&sgt[i], addr);
+ frag_len = frag->size;
+ }
+ qm_sg_entry_set_f(&sgt[i - 1], frag_len);
+
+ qm_fd_set_sg(fd, priv->tx_headroom, skb->len);
+
+ /* DMA map the SGT page */
+ buffer_start = (void *)sgt - priv->tx_headroom;
+ skbh = (struct sk_buff **)buffer_start;
+ *skbh = skb;
+
+ addr = dma_map_single(dev, buffer_start, priv->tx_headroom +
+ sizeof(struct qm_sg_entry) * (1 + nr_frags),
+ dma_dir);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ dev_err(dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sgt_map_failed;
+ }
+
+ fd->bpid = FSL_DPAA_BPID_INV;
+ fd->cmd |= FM_FD_CMD_FCO;
+ qm_fd_addr_set64(fd, addr);
+
+ return 0;
+
+sgt_map_failed:
+sg_map_failed:
+ for (j = 0; j < i; j++)
+ dma_unmap_page(dev, qm_sg_addr(&sgt[j]),
+ qm_sg_entry_get_len(&sgt[j]), dma_dir);
+sg0_map_failed:
+csum_failed:
+ skb_free_frag(sgt_buf);
+
+ return err;
+}
+
+static inline int dpaa_xmit(struct dpaa_priv *priv,
+ struct rtnl_link_stats64 *percpu_stats,
+ int queue,
+ struct qm_fd *fd)
+{
+ struct qman_fq *egress_fq;
+ int err, i;
+
+ egress_fq = priv->egress_fqs[queue];
+ if (fd->bpid == FSL_DPAA_BPID_INV)
+ fd->cmd |= qman_fq_fqid(priv->conf_fqs[queue]);
+
+ /* Trace this Tx fd */
+ trace_dpaa_tx_fd(priv->net_dev, egress_fq, fd);
+
+ for (i = 0; i < DPAA_ENQUEUE_RETRIES; i++) {
+ err = qman_enqueue(egress_fq, fd);
+ if (err != -EBUSY)
+ break;
+ }
+
+ if (unlikely(err < 0)) {
+ percpu_stats->tx_errors++;
+ percpu_stats->tx_fifo_errors++;
+ return err;
+ }
+
+ percpu_stats->tx_packets++;
+ percpu_stats->tx_bytes += qm_fd_get_length(fd);
+
+ return 0;
+}
+
+static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
+{
+ const int queue_mapping = skb_get_queue_mapping(skb);
+ bool nonlinear = skb_is_nonlinear(skb);
+ struct rtnl_link_stats64 *percpu_stats;
+ struct dpaa_percpu_priv *percpu_priv;
+ struct dpaa_priv *priv;
+ struct qm_fd fd;
+ int offset = 0;
+ int err = 0;
+
+ priv = netdev_priv(net_dev);
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+ percpu_stats = &percpu_priv->stats;
+
+ qm_fd_clear_fd(&fd);
+
+ if (!nonlinear) {
+ /* We're going to store the skb backpointer at the beginning
+ * of the data buffer, so we need a privately owned skb
+ *
+ * We've made sure skb is not shared in dev->priv_flags,
+ * we need to verify the skb head is not cloned
+ */
+ if (skb_cow_head(skb, priv->tx_headroom))
+ goto enomem;
+
+ WARN_ON(skb_is_nonlinear(skb));
+ }
+
+ /* MAX_SKB_FRAGS is equal or larger than our dpaa_SGT_MAX_ENTRIES;
+ * make sure we don't feed FMan with more fragments than it supports.
+ */
+ if (nonlinear &&
+ likely(skb_shinfo(skb)->nr_frags < DPAA_SGT_MAX_ENTRIES)) {
+ /* Just create a S/G fd based on the skb */
+ err = skb_to_sg_fd(priv, skb, &fd);
+ percpu_priv->tx_frag_skbuffs++;
+ } else {
+ /* If the egress skb contains more fragments than we support
+ * we have no choice but to linearize it ourselves.
+ */
+ if (unlikely(nonlinear) && __skb_linearize(skb))
+ goto enomem;
+
+ /* Finally, create a contig FD from this skb */
+ err = skb_to_contig_fd(priv, skb, &fd, &offset);
+ }
+ if (unlikely(err < 0))
+ goto skb_to_fd_failed;
+
+ if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
+ return NETDEV_TX_OK;
+
+ dpaa_cleanup_tx_fd(priv, &fd);
+skb_to_fd_failed:
+enomem:
+ percpu_stats->tx_errors++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static void dpaa_rx_error(struct net_device *net_dev,
+ const struct dpaa_priv *priv,
+ struct dpaa_percpu_priv *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ if (net_ratelimit())
+ netif_err(priv, hw, net_dev, "Err FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_RX_ERRORS);
+
+ percpu_priv->stats.rx_errors++;
+
+ if (fd->status & FM_FD_ERR_DMA)
+ percpu_priv->rx_errors.dme++;
+ if (fd->status & FM_FD_ERR_PHYSICAL)
+ percpu_priv->rx_errors.fpe++;
+ if (fd->status & FM_FD_ERR_SIZE)
+ percpu_priv->rx_errors.fse++;
+ if (fd->status & FM_FD_ERR_PRS_HDR_ERR)
+ percpu_priv->rx_errors.phe++;
+
+ dpaa_fd_release(net_dev, fd);
+}
+
+static void dpaa_tx_error(struct net_device *net_dev,
+ const struct dpaa_priv *priv,
+ struct dpaa_percpu_priv *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct sk_buff *skb;
+
+ if (net_ratelimit())
+ netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+
+ percpu_priv->stats.tx_errors++;
+
+ skb = dpaa_cleanup_tx_fd(priv, fd);
+ dev_kfree_skb(skb);
+}
+
+static int dpaa_eth_poll(struct napi_struct *napi, int budget)
+{
+ struct dpaa_napi_portal *np =
+ container_of(napi, struct dpaa_napi_portal, napi);
+
+ int cleaned = qman_p_poll_dqrr(np->p, budget);
+
+ if (cleaned < budget) {
+ napi_complete(napi);
+ qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+
+ } else if (np->down) {
+ qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+ }
+
+ return cleaned;
+}
+
+static void dpaa_tx_conf(struct net_device *net_dev,
+ const struct dpaa_priv *priv,
+ struct dpaa_percpu_priv *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct sk_buff *skb;
+
+ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) {
+ if (net_ratelimit())
+ netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+
+ percpu_priv->stats.tx_errors++;
+ }
+
+ percpu_priv->tx_confirm++;
+
+ skb = dpaa_cleanup_tx_fd(priv, fd);
+
+ consume_skb(skb);
+}
+
+static inline int dpaa_eth_napi_schedule(struct dpaa_percpu_priv *percpu_priv,
+ struct qman_portal *portal)
+{
+ if (unlikely(in_irq() || !in_serving_softirq())) {
+ /* Disable QMan IRQ and invoke NAPI */
+ qman_p_irqsource_remove(portal, QM_PIRQ_DQRI);
+
+ percpu_priv->np.p = portal;
+ napi_schedule(&percpu_priv->np.napi);
+ percpu_priv->in_interrupt++;
+ return 1;
+ }
+ return 0;
+}
+
+static enum qman_cb_dqrr_result rx_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct dpaa_fq *dpaa_fq = container_of(fq, struct dpaa_fq, fq_base);
+ struct dpaa_percpu_priv *percpu_priv;
+ struct net_device *net_dev;
+ struct dpaa_bp *dpaa_bp;
+ struct dpaa_priv *priv;
+
+ net_dev = dpaa_fq->net_dev;
+ priv = netdev_priv(net_dev);
+ dpaa_bp = dpaa_bpid2pool(dq->fd.bpid);
+ if (!dpaa_bp)
+ return qman_cb_dqrr_consume;
+
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ if (dpaa_eth_refill_bpools(priv))
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpaa_fd_release(net_dev, &dq->fd);
+ else
+ dpaa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct rtnl_link_stats64 *percpu_stats;
+ struct dpaa_percpu_priv *percpu_priv;
+ const struct qm_fd *fd = &dq->fd;
+ dma_addr_t addr = qm_fd_addr(fd);
+ enum qm_fd_format fd_format;
+ struct net_device *net_dev;
+ u32 fd_status = fd->status;
+ struct dpaa_bp *dpaa_bp;
+ struct dpaa_priv *priv;
+ unsigned int skb_len;
+ struct sk_buff *skb;
+ int *count_ptr;
+
+ net_dev = ((struct dpaa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+ dpaa_bp = dpaa_bpid2pool(dq->fd.bpid);
+ if (!dpaa_bp)
+ return qman_cb_dqrr_consume;
+
+ /* Trace the Rx fd */
+ trace_dpaa_rx_fd(net_dev, fq, &dq->fd);
+
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+ percpu_stats = &percpu_priv->stats;
+
+ if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal)))
+ return qman_cb_dqrr_stop;
+
+ /* Make sure we didn't run out of buffers */
+ if (unlikely(dpaa_eth_refill_bpools(priv))) {
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpaa_fd_release(net_dev, &dq->fd);
+ return qman_cb_dqrr_consume;
+ }
+
+ if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) {
+ if (net_ratelimit())
+ netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+ fd_status & FM_FD_STAT_RX_ERRORS);
+
+ percpu_stats->rx_errors++;
+ dpaa_fd_release(net_dev, fd);
+ return qman_cb_dqrr_consume;
+ }
+
+ dpaa_bp = dpaa_bpid2pool(fd->bpid);
+ if (!dpaa_bp)
+ return qman_cb_dqrr_consume;
+
+ dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
+
+ /* prefetch the first 64 bytes of the frame or the SGT start */
+ prefetch(phys_to_virt(addr) + qm_fd_get_offset(fd));
+
+ fd_format = qm_fd_get_format(fd);
+ /* The only FD types that we may receive are contig and S/G */
+ WARN_ON((fd_format != qm_fd_contig) && (fd_format != qm_fd_sg));
+
+ /* Account for either the contig buffer or the SGT buffer (depending on
+ * which case we were in) having been removed from the pool.
+ */
+ count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+ (*count_ptr)--;
+
+ if (likely(fd_format == qm_fd_contig))
+ skb = contig_fd_to_skb(priv, fd);
+ else
+ skb = sg_fd_to_skb(priv, fd);
+ if (!skb)
+ return qman_cb_dqrr_consume;
+
+ skb->protocol = eth_type_trans(skb, net_dev);
+
+ skb_len = skb->len;
+
+ if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+ return qman_cb_dqrr_consume;
+
+ percpu_stats->rx_packets++;
+ percpu_stats->rx_bytes += skb_len;
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result conf_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct dpaa_percpu_priv *percpu_priv;
+ struct net_device *net_dev;
+ struct dpaa_priv *priv;
+
+ net_dev = ((struct dpaa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ dpaa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result conf_dflt_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct dpaa_percpu_priv *percpu_priv;
+ struct net_device *net_dev;
+ struct dpaa_priv *priv;
+
+ net_dev = ((struct dpaa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ /* Trace the fd */
+ trace_dpaa_tx_conf_fd(net_dev, fq, &dq->fd);
+
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ dpaa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+static void egress_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const union qm_mr_entry *msg)
+{
+ const struct qm_fd *fd = &msg->ern.fd;
+ struct dpaa_percpu_priv *percpu_priv;
+ const struct dpaa_priv *priv;
+ struct net_device *net_dev;
+ struct sk_buff *skb;
+
+ net_dev = ((struct dpaa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+ percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+ percpu_priv->stats.tx_dropped++;
+ percpu_priv->stats.tx_fifo_errors++;
+ count_ern(percpu_priv, msg);
+
+ skb = dpaa_cleanup_tx_fd(priv, fd);
+ dev_kfree_skb_any(skb);
+}
+
+static const struct dpaa_fq_cbs dpaa_fq_cbs = {
+ .rx_defq = { .cb = { .dqrr = rx_default_dqrr } },
+ .tx_defq = { .cb = { .dqrr = conf_dflt_dqrr } },
+ .rx_errq = { .cb = { .dqrr = rx_error_dqrr } },
+ .tx_errq = { .cb = { .dqrr = conf_error_dqrr } },
+ .egress_ern = { .cb = { .ern = egress_ern } }
+};
+
+static void dpaa_eth_napi_enable(struct dpaa_priv *priv)
+{
+ struct dpaa_percpu_priv *percpu_priv;
+ int i;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ percpu_priv->np.down = 0;
+ napi_enable(&percpu_priv->np.napi);
+ }
+}
+
+static void dpaa_eth_napi_disable(struct dpaa_priv *priv)
+{
+ struct dpaa_percpu_priv *percpu_priv;
+ int i;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ percpu_priv->np.down = 1;
+ napi_disable(&percpu_priv->np.napi);
+ }
+}
+
+static int dpaa_open(struct net_device *net_dev)
+{
+ struct mac_device *mac_dev;
+ struct dpaa_priv *priv;
+ int err, i;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+ dpaa_eth_napi_enable(priv);
+
+ net_dev->phydev = mac_dev->init_phy(net_dev, priv->mac_dev);
+ if (!net_dev->phydev) {
+ netif_err(priv, ifup, net_dev, "init_phy() failed\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
+ err = fman_port_enable(mac_dev->port[i]);
+ if (err)
+ goto mac_start_failed;
+ }
+
+ err = priv->mac_dev->start(mac_dev);
+ if (err < 0) {
+ netif_err(priv, ifup, net_dev, "mac_dev->start() = %d\n", err);
+ goto mac_start_failed;
+ }
+
+ netif_tx_start_all_queues(net_dev);
+
+ return 0;
+
+mac_start_failed:
+ for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++)
+ fman_port_disable(mac_dev->port[i]);
+
+ dpaa_eth_napi_disable(priv);
+
+ return err;
+}
+
+static int dpaa_eth_stop(struct net_device *net_dev)
+{
+ struct dpaa_priv *priv;
+ int err;
+
+ err = dpaa_stop(net_dev);
+
+ priv = netdev_priv(net_dev);
+ dpaa_eth_napi_disable(priv);
+
+ return err;
+}
+
+static const struct net_device_ops dpaa_ops = {
+ .ndo_open = dpaa_open,
+ .ndo_start_xmit = dpaa_start_xmit,
+ .ndo_stop = dpaa_eth_stop,
+ .ndo_tx_timeout = dpaa_tx_timeout,
+ .ndo_get_stats64 = dpaa_get_stats64,
+ .ndo_set_mac_address = dpaa_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_rx_mode = dpaa_set_rx_mode,
+};
+
+static int dpaa_napi_add(struct net_device *net_dev)
+{
+ struct dpaa_priv *priv = netdev_priv(net_dev);
+ struct dpaa_percpu_priv *percpu_priv;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ netif_napi_add(net_dev, &percpu_priv->np.napi,
+ dpaa_eth_poll, NAPI_POLL_WEIGHT);
+ }
+
+ return 0;
+}
+
+static void dpaa_napi_del(struct net_device *net_dev)
+{
+ struct dpaa_priv *priv = netdev_priv(net_dev);
+ struct dpaa_percpu_priv *percpu_priv;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ netif_napi_del(&percpu_priv->np.napi);
+ }
+}
+
+static inline void dpaa_bp_free_pf(const struct dpaa_bp *bp,
+ struct bm_buffer *bmb)
+{
+ dma_addr_t addr = bm_buf_addr(bmb);
+
+ dma_unmap_single(bp->dev, addr, bp->size, DMA_FROM_DEVICE);
+
+ skb_free_frag(phys_to_virt(addr));
+}
+
+/* Alloc the dpaa_bp struct and configure default values */
+static struct dpaa_bp *dpaa_bp_alloc(struct device *dev)
+{
+ struct dpaa_bp *dpaa_bp;
+
+ dpaa_bp = devm_kzalloc(dev, sizeof(*dpaa_bp), GFP_KERNEL);
+ if (!dpaa_bp)
+ return ERR_PTR(-ENOMEM);
+
+ dpaa_bp->bpid = FSL_DPAA_BPID_INV;
+ dpaa_bp->percpu_count = devm_alloc_percpu(dev, *dpaa_bp->percpu_count);
+ dpaa_bp->config_count = FSL_DPAA_ETH_MAX_BUF_COUNT;
+
+ dpaa_bp->seed_cb = dpaa_bp_seed;
+ dpaa_bp->free_buf_cb = dpaa_bp_free_pf;
+
+ return dpaa_bp;
+}
+
+/* Place all ingress FQs (Rx Default, Rx Error) in a dedicated CGR.
+ * We won't be sending congestion notifications to FMan; for now, we just use
+ * this CGR to generate enqueue rejections to FMan in order to drop the frames
+ * before they reach our ingress queues and eat up memory.
+ */
+static int dpaa_ingress_cgr_init(struct dpaa_priv *priv)
+{
+ struct qm_mcc_initcgr initcgr;
+ u32 cs_th;
+ int err;
+
+ err = qman_alloc_cgrid(&priv->ingress_cgr.cgrid);
+ if (err < 0) {
+ if (netif_msg_drv(priv))
+ pr_err("Error %d allocating CGR ID\n", err);
+ goto out_error;
+ }
+
+ /* Enable CS TD, but disable Congestion State Change Notifications. */
+ initcgr.we_mask = QM_CGR_WE_CS_THRES;
+ initcgr.cgr.cscn_en = QM_CGR_EN;
+ cs_th = DPAA_INGRESS_CS_THRESHOLD;
+ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+ initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
+ initcgr.cgr.cstd_en = QM_CGR_EN;
+
+ /* This CGR will be associated with the SWP affined to the current CPU.
+ * However, we'll place all our ingress FQs in it.
+ */
+ err = qman_create_cgr(&priv->ingress_cgr, QMAN_CGR_FLAG_USE_INIT,
+ &initcgr);
+ if (err < 0) {
+ if (netif_msg_drv(priv))
+ pr_err("Error %d creating ingress CGR with ID %d\n",
+ err, priv->ingress_cgr.cgrid);
+ qman_release_cgrid(priv->ingress_cgr.cgrid);
+ goto out_error;
+ }
+ if (netif_msg_drv(priv))
+ pr_debug("Created ingress CGR %d for netdev with hwaddr %pM\n",
+ priv->ingress_cgr.cgrid, priv->mac_dev->addr);
+
+ priv->use_ingress_cgr = true;
+
+out_error:
+ return err;
+}
+
+static const struct of_device_id dpaa_match[];
+
+static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl)
+{
+ u16 headroom;
+
+ /* The frame headroom must accommodate:
+ * - the driver private data area
+ * - parse results, hash results, timestamp if selected
+ * If either hash results or time stamp are selected, both will
+ * be copied to/from the frame headroom, as TS is located between PR and
+ * HR in the IC and IC copy size has a granularity of 16bytes
+ * (see description of FMBM_RICP and FMBM_TICP registers in DPAARM)
+ *
+ * Also make sure the headroom is a multiple of data_align bytes
+ */
+ headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE +
+ DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE);
+
+ return DPAA_FD_DATA_ALIGNMENT ? ALIGN(headroom,
+ DPAA_FD_DATA_ALIGNMENT) :
+ headroom;
+}
+
+static int dpaa_eth_probe(struct platform_device *pdev)
+{
+ struct dpaa_bp *dpaa_bps[DPAA_BPS_NUM] = {NULL};
+ struct dpaa_percpu_priv *percpu_priv;
+ struct net_device *net_dev = NULL;
+ struct dpaa_fq *dpaa_fq, *tmp;
+ struct dpaa_priv *priv = NULL;
+ struct fm_port_fqs port_fqs;
+ struct mac_device *mac_dev;
+ int err = 0, i, channel;
+ struct device *dev;
+
+ dev = &pdev->dev;
+
+ /* Allocate this early, so we can store relevant information in
+ * the private area
+ */
+ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TXQ_NUM);
+ if (!net_dev) {
+ dev_err(dev, "alloc_etherdev_mq() failed\n");
+ goto alloc_etherdev_mq_failed;
+ }
+
+ /* Do this here, so we can be verbose early */
+ SET_NETDEV_DEV(net_dev, dev);
+ dev_set_drvdata(dev, net_dev);
+
+ priv = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+
+ priv->msg_enable = netif_msg_init(debug, DPAA_MSG_DEFAULT);
+
+ mac_dev = dpaa_mac_dev_get(pdev);
+ if (IS_ERR(mac_dev)) {
+ dev_err(dev, "dpaa_mac_dev_get() failed\n");
+ err = PTR_ERR(mac_dev);
+ goto mac_probe_failed;
+ }
+
+ /* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
+ * we choose conservatively and let the user explicitly set a higher
+ * MTU via ifconfig. Otherwise, the user may end up with different MTUs
+ * in the same LAN.
+ * If on the other hand fsl_fm_max_frm has been chosen below 1500,
+ * start with the maximum allowed.
+ */
+ net_dev->mtu = min(dpaa_get_max_mtu(), ETH_DATA_LEN);
+
+ netdev_dbg(net_dev, "Setting initial MTU on net device: %d\n",
+ net_dev->mtu);
+
+ priv->buf_layout[RX].priv_data_size = DPAA_RX_PRIV_DATA_SIZE; /* Rx */
+ priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
+
+ /* device used for DMA mapping */
+ arch_setup_dma_ops(dev, 0, 0, NULL, false);
+ err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ if (err) {
+ dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
+ goto dev_mask_failed;
+ }
+
+ /* bp init */
+ for (i = 0; i < DPAA_BPS_NUM; i++) {
+ int err;
+
+ dpaa_bps[i] = dpaa_bp_alloc(dev);
+ if (IS_ERR(dpaa_bps[i]))
+ return PTR_ERR(dpaa_bps[i]);
+ /* the raw size of the buffers used for reception */
+ dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
+ /* avoid runtime computations by keeping the usable size here */
+ dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
+ dpaa_bps[i]->dev = dev;
+
+ err = dpaa_bp_alloc_pool(dpaa_bps[i]);
+ if (err < 0) {
+ dpaa_bps_free(priv);
+ priv->dpaa_bps[i] = NULL;
+ goto bp_create_failed;
+ }
+ priv->dpaa_bps[i] = dpaa_bps[i];
+ }
+
+ INIT_LIST_HEAD(&priv->dpaa_fq_list);
+
+ memset(&port_fqs, 0, sizeof(port_fqs));
+
+ err = dpaa_alloc_all_fqs(dev, &priv->dpaa_fq_list, &port_fqs);
+ if (err < 0) {
+ dev_err(dev, "dpaa_alloc_all_fqs() failed\n");
+ goto fq_probe_failed;
+ }
+
+ priv->mac_dev = mac_dev;
+
+ channel = dpaa_get_channel();
+ if (channel < 0) {
+ dev_err(dev, "dpaa_get_channel() failed\n");
+ err = channel;
+ goto get_channel_failed;
+ }
+
+ priv->channel = (u16)channel;
+
+ /* Start a thread that will walk the CPUs with affine portals
+ * and add this pool channel to each's dequeue mask.
+ */
+ dpaa_eth_add_channel(priv->channel);
+
+ dpaa_fq_setup(priv, &dpaa_fq_cbs, priv->mac_dev->port[TX]);
+
+ /* Create a congestion group for this netdev, with
+ * dynamically-allocated CGR ID.
+ * Must be executed after probing the MAC, but before
+ * assigning the egress FQs to the CGRs.
+ */
+ err = dpaa_eth_cgr_init(priv);
+ if (err < 0) {
+ dev_err(dev, "Error initializing CGR\n");
+ goto tx_cgr_init_failed;
+ }
+
+ err = dpaa_ingress_cgr_init(priv);
+ if (err < 0) {
+ dev_err(dev, "Error initializing ingress CGR\n");
+ goto rx_cgr_init_failed;
+ }
+
+ /* Add the FQs to the interface, and make them active */
+ list_for_each_entry_safe(dpaa_fq, tmp, &priv->dpaa_fq_list, list) {
+ err = dpaa_fq_init(dpaa_fq, false);
+ if (err < 0)
+ goto fq_alloc_failed;
+ }
+
+ priv->tx_headroom = dpaa_get_headroom(&priv->buf_layout[TX]);
+ priv->rx_headroom = dpaa_get_headroom(&priv->buf_layout[RX]);
+
+ /* All real interfaces need their ports initialized */
+ dpaa_eth_init_ports(mac_dev, dpaa_bps, DPAA_BPS_NUM, &port_fqs,
+ &priv->buf_layout[0], dev);
+
+ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv);
+ if (!priv->percpu_priv) {
+ dev_err(dev, "devm_alloc_percpu() failed\n");
+ err = -ENOMEM;
+ goto alloc_percpu_failed;
+ }
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ memset(percpu_priv, 0, sizeof(*percpu_priv));
+ }
+
+ /* Initialize NAPI */
+ err = dpaa_napi_add(net_dev);
+ if (err < 0)
+ goto napi_add_failed;
+
+ err = dpaa_netdev_init(net_dev, &dpaa_ops, tx_timeout);
+ if (err < 0)
+ goto netdev_init_failed;
+
+ dpaa_eth_sysfs_init(&net_dev->dev);
+
+ netif_info(priv, probe, net_dev, "Probed interface %s\n",
+ net_dev->name);
+
+ return 0;
+
+netdev_init_failed:
+napi_add_failed:
+ dpaa_napi_del(net_dev);
+alloc_percpu_failed:
+ dpaa_fq_free(dev, &priv->dpaa_fq_list);
+fq_alloc_failed:
+ qman_delete_cgr_safe(&priv->ingress_cgr);
+ qman_release_cgrid(priv->ingress_cgr.cgrid);
+rx_cgr_init_failed:
+ qman_delete_cgr_safe(&priv->cgr_data.cgr);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+tx_cgr_init_failed:
+get_channel_failed:
+ dpaa_bps_free(priv);
+bp_create_failed:
+fq_probe_failed:
+dev_mask_failed:
+mac_probe_failed:
+ dev_set_drvdata(dev, NULL);
+ free_netdev(net_dev);
+alloc_etherdev_mq_failed:
+ for (i = 0; i < DPAA_BPS_NUM && dpaa_bps[i]; i++) {
+ if (atomic_read(&dpaa_bps[i]->refs) == 0)
+ devm_kfree(dev, dpaa_bps[i]);
+ }
+ return err;
+}
+
+static int dpaa_remove(struct platform_device *pdev)
+{
+ struct net_device *net_dev;
+ struct dpaa_priv *priv;
+ struct device *dev;
+ int err;
+
+ dev = &pdev->dev;
+ net_dev = dev_get_drvdata(dev);
+
+ priv = netdev_priv(net_dev);
+
+ dpaa_eth_sysfs_remove(dev);
+
+ dev_set_drvdata(dev, NULL);
+ unregister_netdev(net_dev);
+
+ err = dpaa_fq_free(dev, &priv->dpaa_fq_list);
+
+ qman_delete_cgr_safe(&priv->ingress_cgr);
+ qman_release_cgrid(priv->ingress_cgr.cgrid);
+ qman_delete_cgr_safe(&priv->cgr_data.cgr);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+
+ dpaa_napi_del(net_dev);
+
+ dpaa_bps_free(priv);
+
+ free_netdev(net_dev);
+
+ return err;
+}
+
+static struct platform_device_id dpaa_devtype[] = {
+ {
+ .name = "dpaa-ethernet",
+ .driver_data = 0,
+ }, {
+ }
+};
+MODULE_DEVICE_TABLE(platform, dpaa_devtype);
+
+static struct platform_driver dpaa_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ },
+ .id_table = dpaa_devtype,
+ .probe = dpaa_eth_probe,
+ .remove = dpaa_remove
+};
+
+static int __init dpaa_load(void)
+{
+ int err;
+
+ pr_debug("FSL DPAA Ethernet driver\n");
+
+ /* initialize dpaa_eth mirror values */
+ dpaa_rx_extra_headroom = fman_get_rx_extra_headroom();
+ dpaa_max_frm = fman_get_max_frm();
+
+ err = platform_driver_register(&dpaa_driver);
+ if (err < 0)
+ pr_err("Error, platform_driver_register() = %d\n", err);
+
+ return err;
+}
+module_init(dpaa_load);
+
+static void __exit dpaa_unload(void)
+{
+ platform_driver_unregister(&dpaa_driver);
+
+ /* Only one channel is used and needs to be released after all
+ * interfaces are removed
+ */
+ dpaa_release_channel();
+}
+module_exit(dpaa_unload);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DPAA Ethernet driver");
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
new file mode 100644
index 000000000000..1f9aebf3f3c5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
@@ -0,0 +1,185 @@
+/* Copyright 2008 - 2016 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __DPAA_H
+#define __DPAA_H
+
+#include <linux/netdevice.h>
+#include <soc/fsl/qman.h>
+#include <soc/fsl/bman.h>
+
+#include "fman.h"
+#include "mac.h"
+#include "dpaa_eth_trace.h"
+
+#define DPAA_ETH_TXQ_NUM NR_CPUS
+
+#define DPAA_BPS_NUM 3 /* number of bpools per interface */
+
+/* More detailed FQ types - used for fine-grained WQ assignments */
+enum dpaa_fq_type {
+ FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */
+ FQ_TYPE_RX_ERROR, /* Rx Error FQs */
+ FQ_TYPE_TX, /* "Real" Tx FQs */
+ FQ_TYPE_TX_CONFIRM, /* Tx default Conf FQ (actually an Rx FQ) */
+ FQ_TYPE_TX_CONF_MQ, /* Tx conf FQs (one for each Tx FQ) */
+ FQ_TYPE_TX_ERROR, /* Tx Error FQs (these are actually Rx FQs) */
+};
+
+struct dpaa_fq {
+ struct qman_fq fq_base;
+ struct list_head list;
+ struct net_device *net_dev;
+ bool init;
+ u32 fqid;
+ u32 flags;
+ u16 channel;
+ u8 wq;
+ enum dpaa_fq_type fq_type;
+};
+
+struct dpaa_fq_cbs {
+ struct qman_fq rx_defq;
+ struct qman_fq tx_defq;
+ struct qman_fq rx_errq;
+ struct qman_fq tx_errq;
+ struct qman_fq egress_ern;
+};
+
+struct dpaa_bp {
+ /* device used in the DMA mapping operations */
+ struct device *dev;
+ /* current number of buffers in the buffer pool alloted to each CPU */
+ int __percpu *percpu_count;
+ /* all buffers allocated for this pool have this raw size */
+ size_t raw_size;
+ /* all buffers in this pool have this same usable size */
+ size_t size;
+ /* the buffer pools are initialized with config_count buffers for each
+ * CPU; at runtime the number of buffers per CPU is constantly brought
+ * back to this level
+ */
+ u16 config_count;
+ u8 bpid;
+ struct bman_pool *pool;
+ /* bpool can be seeded before use by this cb */
+ int (*seed_cb)(struct dpaa_bp *);
+ /* bpool can be emptied before freeing by this cb */
+ void (*free_buf_cb)(const struct dpaa_bp *, struct bm_buffer *);
+ atomic_t refs;
+};
+
+struct dpaa_rx_errors {
+ u64 dme; /* DMA Error */
+ u64 fpe; /* Frame Physical Error */
+ u64 fse; /* Frame Size Error */
+ u64 phe; /* Header Error */
+};
+
+/* Counters for QMan ERN frames - one counter per rejection code */
+struct dpaa_ern_cnt {
+ u64 cg_tdrop; /* Congestion group taildrop */
+ u64 wred; /* WRED congestion */
+ u64 err_cond; /* Error condition */
+ u64 early_window; /* Order restoration, frame too early */
+ u64 late_window; /* Order restoration, frame too late */
+ u64 fq_tdrop; /* FQ taildrop */
+ u64 fq_retired; /* FQ is retired */
+ u64 orp_zero; /* ORP disabled */
+};
+
+struct dpaa_napi_portal {
+ struct napi_struct napi;
+ struct qman_portal *p;
+ bool down;
+};
+
+struct dpaa_percpu_priv {
+ struct net_device *net_dev;
+ struct dpaa_napi_portal np;
+ u64 in_interrupt;
+ u64 tx_confirm;
+ /* fragmented (non-linear) skbuffs received from the stack */
+ u64 tx_frag_skbuffs;
+ struct rtnl_link_stats64 stats;
+ struct dpaa_rx_errors rx_errors;
+ struct dpaa_ern_cnt ern_cnt;
+};
+
+struct dpaa_buffer_layout {
+ u16 priv_data_size;
+};
+
+struct dpaa_priv {
+ struct dpaa_percpu_priv __percpu *percpu_priv;
+ struct dpaa_bp *dpaa_bps[DPAA_BPS_NUM];
+ /* Store here the needed Tx headroom for convenience and speed
+ * (even though it can be computed based on the fields of buf_layout)
+ */
+ u16 tx_headroom;
+ struct net_device *net_dev;
+ struct mac_device *mac_dev;
+ struct qman_fq *egress_fqs[DPAA_ETH_TXQ_NUM];
+ struct qman_fq *conf_fqs[DPAA_ETH_TXQ_NUM];
+
+ u16 channel;
+ struct list_head dpaa_fq_list;
+
+ u32 msg_enable; /* net_device message level */
+
+ struct {
+ /* All egress queues to a given net device belong to one
+ * (and the same) congestion group.
+ */
+ struct qman_cgr cgr;
+ /* If congested, when it began. Used for performance stats. */
+ u32 congestion_start_jiffies;
+ /* Number of jiffies the Tx port was congested. */
+ u32 congested_jiffies;
+ /* Counter for the number of times the CGR
+ * entered congestion state
+ */
+ u32 cgr_congested_count;
+ } cgr_data;
+ /* Use a per-port CGR for ingress traffic. */
+ bool use_ingress_cgr;
+ struct qman_cgr ingress_cgr;
+
+ struct dpaa_buffer_layout buf_layout[2];
+ u16 rx_headroom;
+};
+
+/* from dpaa_ethtool.c */
+extern const struct ethtool_ops dpaa_ethtool_ops;
+
+/* from dpaa_eth_sysfs.c */
+void dpaa_eth_sysfs_remove(struct device *dev);
+void dpaa_eth_sysfs_init(struct device *dev);
+#endif /* __DPAA_H */
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
new file mode 100644
index 000000000000..ec75d1c6fa89
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
@@ -0,0 +1,165 @@
+/* Copyright 2008-2016 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of_net.h>
+#include "dpaa_eth.h"
+#include "mac.h"
+
+static ssize_t dpaa_eth_show_addr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev)
+ return sprintf(buf, "%llx",
+ (unsigned long long)mac_dev->res->start);
+ else
+ return sprintf(buf, "none");
+}
+
+static ssize_t dpaa_eth_show_fqids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+ struct dpaa_fq *prev = NULL;
+ char *prevstr = NULL;
+ struct dpaa_fq *tmp;
+ struct dpaa_fq *fq;
+ u32 first_fqid = 0;
+ u32 last_fqid = 0;
+ ssize_t bytes = 0;
+ char *str;
+ int i = 0;
+
+ list_for_each_entry_safe(fq, tmp, &priv->dpaa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ str = "Rx default";
+ break;
+ case FQ_TYPE_RX_ERROR:
+ str = "Rx error";
+ break;
+ case FQ_TYPE_TX_CONFIRM:
+ str = "Tx default confirmation";
+ break;
+ case FQ_TYPE_TX_CONF_MQ:
+ str = "Tx confirmation (mq)";
+ break;
+ case FQ_TYPE_TX_ERROR:
+ str = "Tx error";
+ break;
+ case FQ_TYPE_TX:
+ str = "Tx";
+ break;
+ default:
+ str = "Unknown";
+ }
+
+ if (prev && (abs(fq->fqid - prev->fqid) != 1 ||
+ str != prevstr)) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes,
+ "%s: %d\n", prevstr, prev->fqid);
+ else
+ bytes += sprintf(buf + bytes,
+ "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ if (prev && abs(fq->fqid - prev->fqid) == 1 &&
+ str == prevstr) {
+ last_fqid = fq->fqid;
+ } else {
+ first_fqid = fq->fqid;
+ last_fqid = fq->fqid;
+ }
+
+ prev = fq;
+ prevstr = str;
+ i++;
+ }
+
+ if (prev) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr,
+ prev->fqid);
+ else
+ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ return bytes;
+}
+
+static ssize_t dpaa_eth_show_bpids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+ ssize_t bytes = 0;
+ int i = 0;
+
+ for (i = 0; i < DPAA_BPS_NUM; i++)
+ bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, "%u\n",
+ priv->dpaa_bps[i]->bpid);
+
+ return bytes;
+}
+
+static struct device_attribute dpaa_eth_attrs[] = {
+ __ATTR(device_addr, 0444, dpaa_eth_show_addr, NULL),
+ __ATTR(fqids, 0444, dpaa_eth_show_fqids, NULL),
+ __ATTR(bpids, 0444, dpaa_eth_show_bpids, NULL),
+};
+
+void dpaa_eth_sysfs_init(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+ if (device_create_file(dev, &dpaa_eth_attrs[i])) {
+ dev_err(dev, "Error creating sysfs file\n");
+ while (i > 0)
+ device_remove_file(dev, &dpaa_eth_attrs[--i]);
+ return;
+ }
+}
+
+void dpaa_eth_sysfs_remove(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+ device_remove_file(dev, &dpaa_eth_attrs[i]);
+}
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
new file mode 100644
index 000000000000..409c1dc39430
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
@@ -0,0 +1,141 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM dpaa_eth
+
+#if !defined(_DPAA_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _DPAA_ETH_TRACE_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "dpaa_eth.h"
+#include <linux/tracepoint.h>
+
+#define fd_format_name(format) { qm_fd_##format, #format }
+#define fd_format_list \
+ fd_format_name(contig), \
+ fd_format_name(sg)
+
+/* This is used to declare a class of events.
+ * individual events of this type will be defined below.
+ */
+
+/* Store details about a frame descriptor and the FQ on which it was
+ * transmitted/received.
+ */
+DECLARE_EVENT_CLASS(dpaa_eth_fd,
+ /* Trace function prototype */
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ /* Repeat argument list here */
+ TP_ARGS(netdev, fq, fd),
+
+ /* A structure containing the relevant information we want to record.
+ * Declare name and type for each normal element, name, type and size
+ * for arrays. Use __string for variable length strings.
+ */
+ TP_STRUCT__entry(
+ __field(u32, fqid)
+ __field(u64, fd_addr)
+ __field(u8, fd_format)
+ __field(u16, fd_offset)
+ __field(u32, fd_length)
+ __field(u32, fd_status)
+ __string(name, netdev->name)
+ ),
+
+ /* The function that assigns values to the above declared fields */
+ TP_fast_assign(
+ __entry->fqid = fq->fqid;
+ __entry->fd_addr = qm_fd_addr_get64(fd);
+ __entry->fd_format = qm_fd_get_format(fd);
+ __entry->fd_offset = qm_fd_get_offset(fd);
+ __entry->fd_length = qm_fd_get_length(fd);
+ __entry->fd_status = fd->status;
+ __assign_str(name, netdev->name);
+ ),
+
+ /* This is what gets printed when the trace event is triggered */
+ TP_printk("[%s] fqid=%d, fd: addr=0x%llx, format=%s, off=%u, len=%u, status=0x%08x",
+ __get_str(name), __entry->fqid, __entry->fd_addr,
+ __print_symbolic(__entry->fd_format, fd_format_list),
+ __entry->fd_offset, __entry->fd_length, __entry->fd_status)
+);
+
+/* Now declare events of the above type. Format is:
+ * DEFINE_EVENT(class, name, proto, args), with proto and args same as for class
+ */
+
+/* Tx (egress) fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_tx_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* Rx fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_rx_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* Tx confirmation fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_tx_conf_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* If only one event of a certain type needs to be declared, use TRACE_EVENT().
+ * The syntax is the same as for DECLARE_EVENT_CLASS().
+ */
+
+#endif /* _DPAA_ETH_TRACE_H */
+
+/* This must be outside ifdef _DPAA_ETH_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE dpaa_eth_trace
+#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
new file mode 100644
index 000000000000..27e7044667d1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -0,0 +1,417 @@
+/* Copyright 2008-2016 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/string.h>
+
+#include "dpaa_eth.h"
+#include "mac.h"
+
+static const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = {
+ "interrupts",
+ "rx packets",
+ "tx packets",
+ "tx confirm",
+ "tx S/G",
+ "tx error",
+ "rx error",
+};
+
+static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
+ /* dpa rx errors */
+ "rx dma error",
+ "rx frame physical error",
+ "rx frame size error",
+ "rx header error",
+
+ /* demultiplexing errors */
+ "qman cg_tdrop",
+ "qman wred",
+ "qman error cond",
+ "qman early window",
+ "qman late window",
+ "qman fq tdrop",
+ "qman fq retired",
+ "qman orp disabled",
+
+ /* congestion related stats */
+ "congestion time (ms)",
+ "entered congestion",
+ "congested (0/1)"
+};
+
+#define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu)
+#define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global)
+
+static int dpaa_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *et_cmd)
+{
+ int err;
+
+ if (!net_dev->phydev) {
+ netdev_dbg(net_dev, "phy device not initialized\n");
+ return 0;
+ }
+
+ err = phy_ethtool_gset(net_dev->phydev, et_cmd);
+
+ return err;
+}
+
+static int dpaa_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *et_cmd)
+{
+ int err;
+
+ if (!net_dev->phydev) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ err = phy_ethtool_sset(net_dev->phydev, et_cmd);
+ if (err < 0)
+ netdev_err(net_dev, "phy_ethtool_sset() = %d\n", err);
+
+ return err;
+}
+
+static void dpaa_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ int len;
+
+ strlcpy(drvinfo->driver, KBUILD_MODNAME,
+ sizeof(drvinfo->driver));
+ len = snprintf(drvinfo->version, sizeof(drvinfo->version),
+ "%X", 0);
+ len = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+ "%X", 0);
+
+ if (len >= sizeof(drvinfo->fw_version)) {
+ /* Truncated output */
+ netdev_notice(net_dev, "snprintf() = %d\n", len);
+ }
+ strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+ sizeof(drvinfo->bus_info));
+}
+
+static u32 dpaa_get_msglevel(struct net_device *net_dev)
+{
+ return ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable;
+}
+
+static void dpaa_set_msglevel(struct net_device *net_dev,
+ u32 msg_enable)
+{
+ ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable = msg_enable;
+}
+
+static int dpaa_nway_reset(struct net_device *net_dev)
+{
+ int err;
+
+ if (!net_dev->phydev) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ err = 0;
+ if (net_dev->phydev->autoneg) {
+ err = phy_start_aneg(net_dev->phydev);
+ if (err < 0)
+ netdev_err(net_dev, "phy_start_aneg() = %d\n",
+ err);
+ }
+
+ return err;
+}
+
+static void dpaa_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct mac_device *mac_dev;
+ struct dpaa_priv *priv;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ if (!net_dev->phydev) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return;
+ }
+
+ epause->autoneg = mac_dev->autoneg_pause;
+ epause->rx_pause = mac_dev->rx_pause_active;
+ epause->tx_pause = mac_dev->tx_pause_active;
+}
+
+static int dpaa_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct mac_device *mac_dev;
+ struct phy_device *phydev;
+ bool rx_pause, tx_pause;
+ struct dpaa_priv *priv;
+ u32 newadv, oldadv;
+ int err;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ phydev = net_dev->phydev;
+ if (!phydev) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!(phydev->supported & SUPPORTED_Pause) ||
+ (!(phydev->supported & SUPPORTED_Asym_Pause) &&
+ (epause->rx_pause != epause->tx_pause)))
+ return -EINVAL;
+
+ /* The MAC should know how to handle PAUSE frame autonegotiation before
+ * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE
+ * settings.
+ */
+ mac_dev->autoneg_pause = !!epause->autoneg;
+ mac_dev->rx_pause_req = !!epause->rx_pause;
+ mac_dev->tx_pause_req = !!epause->tx_pause;
+
+ /* Determine the sym/asym advertised PAUSE capabilities from the desired
+ * rx/tx pause settings.
+ */
+ newadv = 0;
+ if (epause->rx_pause)
+ newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+ if (epause->tx_pause)
+ newadv |= ADVERTISED_Asym_Pause;
+
+ oldadv = phydev->advertising &
+ (ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+
+ /* If there are differences between the old and the new advertised
+ * values, restart PHY autonegotiation and advertise the new values.
+ */
+ if (oldadv != newadv) {
+ phydev->advertising &= ~(ADVERTISED_Pause
+ | ADVERTISED_Asym_Pause);
+ phydev->advertising |= newadv;
+ if (phydev->autoneg) {
+ err = phy_start_aneg(phydev);
+ if (err < 0)
+ netdev_err(net_dev, "phy_start_aneg() = %d\n",
+ err);
+ }
+ }
+
+ fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+ err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
+ if (err < 0)
+ netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
+
+ return err;
+}
+
+static int dpaa_get_sset_count(struct net_device *net_dev, int type)
+{
+ unsigned int total_stats, num_stats;
+
+ num_stats = num_online_cpus() + 1;
+ total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) +
+ DPAA_STATS_GLOBAL_LEN;
+
+ switch (type) {
+ case ETH_SS_STATS:
+ return total_stats;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus,
+ int crr_cpu, u64 *bp_count, u64 *data)
+{
+ int num_values = num_cpus + 1;
+ int crr = 0, j;
+
+ /* update current CPU's stats and also add them to the total values */
+ data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt;
+ data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets;
+ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets;
+ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm;
+ data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs;
+ data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors;
+ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors;
+
+ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors;
+ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors;
+
+ for (j = 0; j < DPAA_BPS_NUM; j++) {
+ data[crr * num_values + crr_cpu] = bp_count[j];
+ data[crr++ * num_values + num_cpus] += bp_count[j];
+ }
+}
+
+static void dpaa_get_ethtool_stats(struct net_device *net_dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num;
+ struct dpaa_percpu_priv *percpu_priv;
+ struct dpaa_rx_errors rx_errors;
+ unsigned int num_cpus, offset;
+ struct dpaa_ern_cnt ern_cnt;
+ struct dpaa_bp *dpaa_bp;
+ struct dpaa_priv *priv;
+ int total_stats, i, j;
+ bool cg_status;
+
+ total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS);
+ priv = netdev_priv(net_dev);
+ num_cpus = num_online_cpus();
+
+ memset(&bp_count, 0, sizeof(bp_count));
+ memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors));
+ memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt));
+ memset(data, 0, total_stats * sizeof(u64));
+
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ for (j = 0; j < DPAA_BPS_NUM; j++) {
+ dpaa_bp = priv->dpaa_bps[j];
+ if (!dpaa_bp->percpu_count)
+ continue;
+ bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i));
+ }
+ rx_errors.dme += percpu_priv->rx_errors.dme;
+ rx_errors.fpe += percpu_priv->rx_errors.fpe;
+ rx_errors.fse += percpu_priv->rx_errors.fse;
+ rx_errors.phe += percpu_priv->rx_errors.phe;
+
+ ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop;
+ ern_cnt.wred += percpu_priv->ern_cnt.wred;
+ ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond;
+ ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
+ ern_cnt.late_window += percpu_priv->ern_cnt.late_window;
+ ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop;
+ ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired;
+ ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero;
+
+ copy_stats(percpu_priv, num_cpus, i, bp_count, data);
+ }
+
+ offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM);
+ memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors));
+
+ offset += sizeof(struct dpaa_rx_errors) / sizeof(u64);
+ memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt));
+
+ /* gather congestion related counters */
+ cg_num = 0;
+ cg_status = 0;
+ cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies);
+ if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) {
+ cg_num = priv->cgr_data.cgr_congested_count;
+
+ /* reset congestion stats (like QMan API does */
+ priv->cgr_data.congested_jiffies = 0;
+ priv->cgr_data.cgr_congested_count = 0;
+ }
+
+ offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64);
+ data[offset++] = cg_time;
+ data[offset++] = cg_num;
+ data[offset++] = cg_status;
+}
+
+static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
+ u8 *data)
+{
+ unsigned int i, j, num_cpus, size;
+ char string_cpu[ETH_GSTRING_LEN];
+ u8 *strings;
+
+ memset(string_cpu, 0, sizeof(string_cpu));
+ strings = data;
+ num_cpus = num_online_cpus();
+ size = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN;
+
+ for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) {
+ for (j = 0; j < num_cpus; j++) {
+ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]",
+ dpaa_stats_percpu[i], j);
+ memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+ strings += ETH_GSTRING_LEN;
+ }
+ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]",
+ dpaa_stats_percpu[i]);
+ memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+ strings += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < DPAA_BPS_NUM; i++) {
+ for (j = 0; j < num_cpus; j++) {
+ snprintf(string_cpu, ETH_GSTRING_LEN,
+ "bpool %c [CPU %d]", 'a' + i, j);
+ memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+ strings += ETH_GSTRING_LEN;
+ }
+ snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]",
+ 'a' + i);
+ memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+ strings += ETH_GSTRING_LEN;
+ }
+ memcpy(strings, dpaa_stats_global, size);
+}
+
+const struct ethtool_ops dpaa_ethtool_ops = {
+ .get_settings = dpaa_get_settings,
+ .set_settings = dpaa_set_settings,
+ .get_drvinfo = dpaa_get_drvinfo,
+ .get_msglevel = dpaa_get_msglevel,
+ .set_msglevel = dpaa_set_msglevel,
+ .nway_reset = dpaa_nway_reset,
+ .get_pauseparam = dpaa_get_pauseparam,
+ .set_pauseparam = dpaa_set_pauseparam,
+ .get_link = ethtool_op_get_link,
+ .get_sset_count = dpaa_get_sset_count,
+ .get_ethtool_stats = dpaa_get_ethtool_stats,
+ .get_strings = dpaa_get_strings,
+};
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 12aef1b15356..38160c2bebcb 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1841,11 +1841,11 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
ret = clk_prepare_enable(fep->clk_ahb);
if (ret)
return ret;
- if (fep->clk_enet_out) {
- ret = clk_prepare_enable(fep->clk_enet_out);
- if (ret)
- goto failed_clk_enet_out;
- }
+
+ ret = clk_prepare_enable(fep->clk_enet_out);
+ if (ret)
+ goto failed_clk_enet_out;
+
if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex);
ret = clk_prepare_enable(fep->clk_ptp);
@@ -1857,23 +1857,20 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
}
mutex_unlock(&fep->ptp_clk_mutex);
}
- if (fep->clk_ref) {
- ret = clk_prepare_enable(fep->clk_ref);
- if (ret)
- goto failed_clk_ref;
- }
+
+ ret = clk_prepare_enable(fep->clk_ref);
+ if (ret)
+ goto failed_clk_ref;
} else {
clk_disable_unprepare(fep->clk_ahb);
- if (fep->clk_enet_out)
- clk_disable_unprepare(fep->clk_enet_out);
+ clk_disable_unprepare(fep->clk_enet_out);
if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex);
clk_disable_unprepare(fep->clk_ptp);
fep->ptp_clk_on = false;
mutex_unlock(&fep->ptp_clk_mutex);
}
- if (fep->clk_ref)
- clk_disable_unprepare(fep->clk_ref);
+ clk_disable_unprepare(fep->clk_ref);
}
return 0;
@@ -2365,16 +2362,6 @@ static inline void fec_enet_update_ethtool_stats(struct net_device *dev)
}
#endif /* !defined(CONFIG_M5272) */
-static int fec_enet_nway_reset(struct net_device *dev)
-{
- struct phy_device *phydev = dev->phydev;
-
- if (!phydev)
- return -ENODEV;
-
- return genphy_restart_aneg(phydev);
-}
-
/* ITR clock source is enet system clock (clk_ahb).
* TCTT unit is cycle_ns * 64 cycle
* So, the ICTT value = X us / (cycle_ns * 64)
@@ -2574,7 +2561,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
.get_drvinfo = fec_enet_get_drvinfo,
.get_regs_len = fec_enet_get_regs_len,
.get_regs = fec_enet_get_regs,
- .nway_reset = fec_enet_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_coalesce = fec_enet_get_coalesce,
.set_coalesce = fec_enet_set_coalesce,
@@ -3075,7 +3062,6 @@ static const struct net_device_ops fec_netdev_ops = {
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = fec_timeout,
.ndo_set_mac_address = fec_set_mac_address,
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 446ae9d60c71..aa8cf5d2a53c 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -802,7 +802,6 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
.ndo_set_mac_address = mpc52xx_fec_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mpc52xx_fec_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = mpc52xx_fec_tx_timeout,
.ndo_get_stats = mpc52xx_fec_get_stats,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 736db9d9b0ad..69ca42ce5dd5 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -879,13 +879,17 @@ static int mac_probe(struct platform_device *_of_dev)
priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
GFP_KERNEL);
- if (!priv->fixed_link)
+ if (!priv->fixed_link) {
+ err = -ENOMEM;
goto _return_dev_set_drvdata;
+ }
priv->phy_node = of_node_get(mac_node);
phy = of_phy_find_device(priv->phy_node);
- if (!phy)
+ if (!phy) {
+ err = -EINVAL;
goto _return_dev_set_drvdata;
+ }
priv->fixed_link->link = phy->link;
priv->fixed_link->speed = phy->speed;
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 4b86260584a0..d9f3a480ca1b 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -118,22 +118,22 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
if (sc & BD_ENET_TX_HB) /* No heartbeat */
- fep->stats.tx_heartbeat_errors++;
+ dev->stats.tx_heartbeat_errors++;
if (sc & BD_ENET_TX_LC) /* Late collision */
- fep->stats.tx_window_errors++;
+ dev->stats.tx_window_errors++;
if (sc & BD_ENET_TX_RL) /* Retrans limit */
- fep->stats.tx_aborted_errors++;
+ dev->stats.tx_aborted_errors++;
if (sc & BD_ENET_TX_UN) /* Underrun */
- fep->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
if (sc & BD_ENET_TX_CSL) /* Carrier lost */
- fep->stats.tx_carrier_errors++;
+ dev->stats.tx_carrier_errors++;
if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
- fep->stats.tx_errors++;
+ dev->stats.tx_errors++;
do_restart = 1;
}
} else
- fep->stats.tx_packets++;
+ dev->stats.tx_packets++;
if (sc & BD_ENET_TX_READY) {
dev_warn(fep->dev,
@@ -145,7 +145,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
* but we eventually sent the packet OK.
*/
if (sc & BD_ENET_TX_DEF)
- fep->stats.collisions++;
+ dev->stats.collisions++;
/* unmap */
if (fep->mapped_as_page[dirtyidx])
@@ -212,19 +212,19 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
*/
if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
- fep->stats.rx_errors++;
+ dev->stats.rx_errors++;
/* Frame too long or too short. */
if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
- fep->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
/* Frame alignment */
if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
- fep->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
/* CRC Error */
if (sc & BD_ENET_RX_CR)
- fep->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
/* FIFO overrun */
if (sc & BD_ENET_RX_OV)
- fep->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
skbn = fep->rx_skbuff[curidx];
} else {
@@ -233,9 +233,9 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
/*
* Process the incoming frame.
*/
- fep->stats.rx_packets++;
+ dev->stats.rx_packets++;
pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
- fep->stats.rx_bytes += pkt_len + 4;
+ dev->stats.rx_bytes += pkt_len + 4;
if (pkt_len <= fpi->rx_copybreak) {
/* +2 to make IP header L1 cache aligned */
@@ -277,7 +277,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
received++;
netif_receive_skb(skb);
} else {
- fep->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
skbn = skb;
}
}
@@ -543,7 +543,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
curidx = bdp - fep->tx_bd_base;
len = skb->len;
- fep->stats.tx_bytes += len;
+ dev->stats.tx_bytes += len;
if (nr_frags)
len -= skb->data_len;
fep->tx_free -= nr_frags + 1;
@@ -619,7 +619,7 @@ static void fs_timeout(struct net_device *dev)
unsigned long flags;
int wake = 0;
- fep->stats.tx_errors++;
+ dev->stats.tx_errors++;
spin_lock_irqsave(&fep->lock, flags);
@@ -774,12 +774,6 @@ static int fs_enet_close(struct net_device *dev)
return 0;
}
-static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
- return &fep->stats;
-}
-
/*************************************************************************/
static void fs_get_drvinfo(struct net_device *dev,
@@ -813,11 +807,6 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
regs->version = 0;
}
-static int fs_nway_reset(struct net_device *dev)
-{
- return 0;
-}
-
static u32 fs_get_msglevel(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -871,7 +860,7 @@ static int fs_set_tunable(struct net_device *dev,
static const struct ethtool_ops fs_ethtool_ops = {
.get_drvinfo = fs_get_drvinfo,
.get_regs_len = fs_get_regs_len,
- .nway_reset = fs_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_msglevel = fs_get_msglevel,
.set_msglevel = fs_set_msglevel,
@@ -905,14 +894,12 @@ extern void fs_mii_disconnect(struct net_device *dev);
static const struct net_device_ops fs_enet_netdev_ops = {
.ndo_open = fs_enet_open,
.ndo_stop = fs_enet_close,
- .ndo_get_stats = fs_enet_get_stats,
.ndo_start_xmit = fs_enet_start_xmit,
.ndo_tx_timeout = fs_timeout,
.ndo_set_rx_mode = fs_set_multicast_list,
.ndo_do_ioctl = fs_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = fs_enet_netpoll,
#endif
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
index fee24c822fad..5ce516c8a62a 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
@@ -137,7 +137,6 @@ struct fs_enet_private {
cbd_t __iomem *cur_rx;
cbd_t __iomem *cur_tx;
int tx_free;
- struct net_device_stats stats;
struct timer_list phy_timer_list;
const struct phy_info *phy;
u32 msg_enable;
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 9061c2f82b9c..756f7e763d5f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1339,7 +1339,10 @@ static int gfar_probe(struct platform_device *ofdev)
/* Fill in the dev structure */
dev->watchdog_timeo = TX_TIMEOUT;
+ /* MTU range: 50 - 9586 */
dev->mtu = 1500;
+ dev->min_mtu = 50;
+ dev->max_mtu = GFAR_JUMBO_FRAME_SIZE - ETH_HLEN;
dev->netdev_ops = &gfar_netdev_ops;
dev->ethtool_ops = &gfar_ethtool_ops;
@@ -2600,12 +2603,6 @@ static int gfar_set_mac_address(struct net_device *dev)
static int gfar_change_mtu(struct net_device *dev, int new_mtu)
{
struct gfar_private *priv = netdev_priv(dev);
- int frame_size = new_mtu + ETH_HLEN;
-
- if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) {
- netif_err(priv, drv, dev, "Invalid MTU setting\n");
- return -EINVAL;
- }
while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
cpu_relax();
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index 57798814160d..721be13081f9 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -72,7 +72,7 @@ struct gianfar_ptp_registers {
/* Bit definitions for the TMR_CTRL register */
#define ALM1P (1<<31) /* Alarm1 output polarity */
#define ALM2P (1<<30) /* Alarm2 output polarity */
-#define FS (1<<28) /* FIPER start indication */
+#define FIPERST (1<<28) /* FIPER start indication */
#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */
#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */
#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */
@@ -280,21 +280,26 @@ static irqreturn_t isr(int irq, void *priv)
* PTP clock operations
*/
-static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int ptp_gianfar_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
- u64 adj;
- u32 diff, tmr_add;
+ u64 adj, diff;
+ u32 tmr_add;
int neg_adj = 0;
struct etsects *etsects = container_of(ptp, struct etsects, caps);
- if (ppb < 0) {
+ if (scaled_ppm < 0) {
neg_adj = 1;
- ppb = -ppb;
+ scaled_ppm = -scaled_ppm;
}
tmr_add = etsects->tmr_add;
adj = tmr_add;
- adj *= ppb;
- diff = div_u64(adj, 1000000000ULL);
+
+ /* calculate diff as adj*(scaled_ppm/65536)/1000000
+ * and round() to the nearest integer
+ */
+ adj *= scaled_ppm;
+ diff = div_u64(adj, 8000000);
+ diff = (diff >> 13) + ((diff >> 12) & 1);
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
@@ -415,7 +420,7 @@ static struct ptp_clock_info ptp_gianfar_caps = {
.n_per_out = 0,
.n_pins = 0,
.pps = 1,
- .adjfreq = ptp_gianfar_adjfreq,
+ .adjfine = ptp_gianfar_adjfine,
.adjtime = ptp_gianfar_adjtime,
.gettime64 = ptp_gianfar_gettime,
.settime64 = ptp_gianfar_settime,
@@ -502,7 +507,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
set_alarm(etsects);
- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE|FRD);
+ gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
spin_unlock_irqrestore(&etsects->lock, flags);
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index f76d33279454..53c5fcf1436c 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -3681,7 +3681,6 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
.ndo_start_xmit = ucc_geth_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ucc_geth_set_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_rx_mode = ucc_geth_set_multi,
.ndo_tx_timeout = ucc_geth_timeout,
.ndo_do_ioctl = ucc_geth_ioctl,
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index 812a968a78e9..8ba636f61b50 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -332,13 +332,6 @@ static void uec_get_ethtool_stats(struct net_device *netdev,
}
}
-static int uec_nway_reset(struct net_device *netdev)
-{
- struct ucc_geth_private *ugeth = netdev_priv(netdev);
-
- return phy_start_aneg(ugeth->phydev);
-}
-
/* Report driver information */
static void
uec_get_drvinfo(struct net_device *netdev,
@@ -394,7 +387,7 @@ static const struct ethtool_ops uec_ethtool_ops = {
.get_regs = uec_get_regs,
.get_msglevel = uec_get_msglevel,
.set_msglevel = uec_set_msglevel,
- .nway_reset = uec_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_ringparam = uec_get_ringparam,
.set_ringparam = uec_set_ringparam,
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index 399cfd217288..51c4abc51bf4 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -225,7 +225,6 @@ static const struct net_device_ops fjn_netdev_ops = {
.ndo_tx_timeout = fjn_tx_timeout,
.ndo_set_config = fjn_config,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 39778892b3b3..854befde0a08 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -769,7 +769,6 @@ static const struct net_device_ops hip04_netdev_ops = {
.ndo_set_mac_address = hip04_set_mac_address,
.ndo_tx_timeout = hip04_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int hip04_alloc_ring(struct net_device *ndev, struct device *d)
@@ -898,7 +897,6 @@ static int hip04_mac_probe(struct platform_device *pdev)
INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task);
- ether_setup(ndev);
ndev->netdev_ops = &hip04_netdev_ops;
ndev->ethtool_ops = &hip04_ethtool_ops;
ndev->watchdog_timeo = TX_TIMEOUT;
diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c
index ced185962ef8..49863068c59e 100644
--- a/drivers/net/ethernet/hisilicon/hisi_femac.c
+++ b/drivers/net/ethernet/hisilicon/hisi_femac.c
@@ -712,7 +712,6 @@ static const struct net_device_ops hisi_femac_netdev_ops = {
.ndo_do_ioctl = hisi_femac_net_ioctl,
.ndo_set_mac_address = hisi_femac_set_mac_address,
.ndo_set_rx_mode = hisi_femac_net_set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
};
static void hisi_femac_core_reset(struct hisi_femac_priv *priv)
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index e69a6bed31a9..ee7e9ce2f5b3 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -11,8 +11,10 @@
#include <linux/interrupt.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <linux/of_net.h>
#include <linux/of_mdio.h>
+#include <linux/reset.h>
#include <linux/clk.h>
#include <linux/circ_buf.h>
@@ -183,12 +185,28 @@
#define DESC_DATA_LEN_OFF 16
#define DESC_BUFF_LEN_OFF 0
#define DESC_DATA_MASK 0x7ff
+#define DESC_SG BIT(30)
+#define DESC_FRAGS_NUM_OFF 11
/* DMA descriptor ring helpers */
#define dma_ring_incr(n, s) (((n) + 1) & ((s) - 1))
#define dma_cnt(n) ((n) >> 5)
#define dma_byte(n) ((n) << 5)
+#define HW_CAP_TSO BIT(0)
+#define GEMAC_V1 0
+#define GEMAC_V2 (GEMAC_V1 | HW_CAP_TSO)
+#define HAS_CAP_TSO(hw_cap) ((hw_cap) & HW_CAP_TSO)
+
+#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us"
+
+enum phy_reset_delays {
+ PRE_DELAY,
+ PULSE,
+ POST_DELAY,
+ DELAYS_NUM,
+};
+
struct hix5hd2_desc {
__le32 buff_addr;
__le32 cmd;
@@ -201,6 +219,27 @@ struct hix5hd2_desc_sw {
unsigned int size;
};
+struct hix5hd2_sg_desc_ring {
+ struct sg_desc *desc;
+ dma_addr_t phys_addr;
+};
+
+struct frags_info {
+ __le32 addr;
+ __le32 size;
+};
+
+/* hardware supported max skb frags num */
+#define SG_MAX_SKB_FRAGS 17
+struct sg_desc {
+ __le32 total_len;
+ __le32 resvd0;
+ __le32 linear_addr;
+ __le32 linear_len;
+ /* reserve one more frags for memory alignment */
+ struct frags_info frags[SG_MAX_SKB_FRAGS + 1];
+};
+
#define QUEUE_NUMS 4
struct hix5hd2_priv {
struct hix5hd2_desc_sw pool[QUEUE_NUMS];
@@ -208,6 +247,7 @@ struct hix5hd2_priv {
#define rx_bq pool[1]
#define tx_bq pool[2]
#define tx_rq pool[3]
+ struct hix5hd2_sg_desc_ring tx_ring;
void __iomem *base;
void __iomem *ctrl_base;
@@ -221,15 +261,30 @@ struct hix5hd2_priv {
struct device_node *phy_node;
phy_interface_t phy_mode;
+ unsigned long hw_cap;
unsigned int speed;
unsigned int duplex;
- struct clk *clk;
+ struct clk *mac_core_clk;
+ struct clk *mac_ifc_clk;
+ struct reset_control *mac_core_rst;
+ struct reset_control *mac_ifc_rst;
+ struct reset_control *phy_rst;
+ u32 phy_reset_delays[DELAYS_NUM];
struct mii_bus *bus;
struct napi_struct napi;
struct work_struct tx_timeout_task;
};
+static inline void hix5hd2_mac_interface_reset(struct hix5hd2_priv *priv)
+{
+ if (!priv->mac_ifc_rst)
+ return;
+
+ reset_control_assert(priv->mac_ifc_rst);
+ reset_control_deassert(priv->mac_ifc_rst);
+}
+
static void hix5hd2_config_port(struct net_device *dev, u32 speed, u32 duplex)
{
struct hix5hd2_priv *priv = netdev_priv(dev);
@@ -262,6 +317,7 @@ static void hix5hd2_config_port(struct net_device *dev, u32 speed, u32 duplex)
if (duplex)
val |= GMAC_FULL_DUPLEX;
writel_relaxed(val, priv->ctrl_base);
+ hix5hd2_mac_interface_reset(priv);
writel_relaxed(BIT_MODE_CHANGE_EN, priv->base + MODE_CHANGE_EN);
if (speed == SPEED_1000)
@@ -511,6 +567,27 @@ next:
return num;
}
+static void hix5hd2_clean_sg_desc(struct hix5hd2_priv *priv,
+ struct sk_buff *skb, u32 pos)
+{
+ struct sg_desc *desc;
+ dma_addr_t addr;
+ u32 len;
+ int i;
+
+ desc = priv->tx_ring.desc + pos;
+
+ addr = le32_to_cpu(desc->linear_addr);
+ len = le32_to_cpu(desc->linear_len);
+ dma_unmap_single(priv->dev, addr, len, DMA_TO_DEVICE);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ addr = le32_to_cpu(desc->frags[i].addr);
+ len = le32_to_cpu(desc->frags[i].size);
+ dma_unmap_page(priv->dev, addr, len, DMA_TO_DEVICE);
+ }
+}
+
static void hix5hd2_xmit_reclaim(struct net_device *dev)
{
struct sk_buff *skb;
@@ -538,8 +615,15 @@ static void hix5hd2_xmit_reclaim(struct net_device *dev)
pkts_compl++;
bytes_compl += skb->len;
desc = priv->tx_rq.desc + pos;
- addr = le32_to_cpu(desc->buff_addr);
- dma_unmap_single(priv->dev, addr, skb->len, DMA_TO_DEVICE);
+
+ if (skb_shinfo(skb)->nr_frags) {
+ hix5hd2_clean_sg_desc(priv, skb, pos);
+ } else {
+ addr = le32_to_cpu(desc->buff_addr);
+ dma_unmap_single(priv->dev, addr, skb->len,
+ DMA_TO_DEVICE);
+ }
+
priv->tx_skb[pos] = NULL;
dev_consume_skb_any(skb);
pos = dma_ring_incr(pos, TX_DESC_NUM);
@@ -600,12 +684,66 @@ static irqreturn_t hix5hd2_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static u32 hix5hd2_get_desc_cmd(struct sk_buff *skb, unsigned long hw_cap)
+{
+ u32 cmd = 0;
+
+ if (HAS_CAP_TSO(hw_cap)) {
+ if (skb_shinfo(skb)->nr_frags)
+ cmd |= DESC_SG;
+ cmd |= skb_shinfo(skb)->nr_frags << DESC_FRAGS_NUM_OFF;
+ } else {
+ cmd |= DESC_FL_FULL |
+ ((skb->len & DESC_DATA_MASK) << DESC_BUFF_LEN_OFF);
+ }
+
+ cmd |= (skb->len & DESC_DATA_MASK) << DESC_DATA_LEN_OFF;
+ cmd |= DESC_VLD_BUSY;
+
+ return cmd;
+}
+
+static int hix5hd2_fill_sg_desc(struct hix5hd2_priv *priv,
+ struct sk_buff *skb, u32 pos)
+{
+ struct sg_desc *desc;
+ dma_addr_t addr;
+ int ret;
+ int i;
+
+ desc = priv->tx_ring.desc + pos;
+
+ desc->total_len = cpu_to_le32(skb->len);
+ addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb),
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, addr)))
+ return -EINVAL;
+ desc->linear_addr = cpu_to_le32(addr);
+ desc->linear_len = cpu_to_le32(skb_headlen(skb));
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ int len = frag->size;
+
+ addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE);
+ ret = dma_mapping_error(priv->dev, addr);
+ if (unlikely(ret))
+ return -EINVAL;
+ desc->frags[i].addr = cpu_to_le32(addr);
+ desc->frags[i].size = cpu_to_le32(len);
+ }
+
+ return 0;
+}
+
static int hix5hd2_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct hix5hd2_priv *priv = netdev_priv(dev);
struct hix5hd2_desc *desc;
dma_addr_t addr;
u32 pos;
+ u32 cmd;
+ int ret;
/* software write pointer */
pos = dma_cnt(readl_relaxed(priv->base + TX_BQ_WR_ADDR));
@@ -616,18 +754,31 @@ static int hix5hd2_net_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- addr = dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->dev, addr)) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
desc = priv->tx_bq.desc + pos;
+
+ cmd = hix5hd2_get_desc_cmd(skb, priv->hw_cap);
+ desc->cmd = cpu_to_le32(cmd);
+
+ if (skb_shinfo(skb)->nr_frags) {
+ ret = hix5hd2_fill_sg_desc(priv, skb, pos);
+ if (unlikely(ret)) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+ addr = priv->tx_ring.phys_addr + pos * sizeof(struct sg_desc);
+ } else {
+ addr = dma_map_single(priv->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, addr))) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+ }
desc->buff_addr = cpu_to_le32(addr);
+
priv->tx_skb[pos] = skb;
- desc->cmd = cpu_to_le32(DESC_VLD_BUSY | DESC_FL_FULL |
- (skb->len & DESC_DATA_MASK) << DESC_DATA_LEN_OFF |
- (skb->len & DESC_DATA_MASK) << DESC_BUFF_LEN_OFF);
/* ensure desc updated */
wmb();
@@ -681,16 +832,26 @@ static int hix5hd2_net_open(struct net_device *dev)
struct phy_device *phy;
int ret;
- ret = clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->mac_core_clk);
+ if (ret < 0) {
+ netdev_err(dev, "failed to enable mac core clk %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->mac_ifc_clk);
if (ret < 0) {
- netdev_err(dev, "failed to enable clk %d\n", ret);
+ clk_disable_unprepare(priv->mac_core_clk);
+ netdev_err(dev, "failed to enable mac ifc clk %d\n", ret);
return ret;
}
phy = of_phy_connect(dev, priv->phy_node,
&hix5hd2_adjust_link, 0, priv->phy_mode);
- if (!phy)
+ if (!phy) {
+ clk_disable_unprepare(priv->mac_ifc_clk);
+ clk_disable_unprepare(priv->mac_core_clk);
return -ENODEV;
+ }
phy_start(phy);
hix5hd2_hw_init(priv);
@@ -721,7 +882,8 @@ static int hix5hd2_net_close(struct net_device *dev)
phy_disconnect(dev->phydev);
}
- clk_disable_unprepare(priv->clk);
+ clk_disable_unprepare(priv->mac_ifc_clk);
+ clk_disable_unprepare(priv->mac_core_clk);
return 0;
}
@@ -862,10 +1024,82 @@ error_free_pool:
return -ENOMEM;
}
+static int hix5hd2_init_sg_desc_queue(struct hix5hd2_priv *priv)
+{
+ struct sg_desc *desc;
+ dma_addr_t phys_addr;
+
+ desc = (struct sg_desc *)dma_alloc_coherent(priv->dev,
+ TX_DESC_NUM * sizeof(struct sg_desc),
+ &phys_addr, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ priv->tx_ring.desc = desc;
+ priv->tx_ring.phys_addr = phys_addr;
+
+ return 0;
+}
+
+static void hix5hd2_destroy_sg_desc_queue(struct hix5hd2_priv *priv)
+{
+ if (priv->tx_ring.desc) {
+ dma_free_coherent(priv->dev,
+ TX_DESC_NUM * sizeof(struct sg_desc),
+ priv->tx_ring.desc, priv->tx_ring.phys_addr);
+ priv->tx_ring.desc = NULL;
+ }
+}
+
+static inline void hix5hd2_mac_core_reset(struct hix5hd2_priv *priv)
+{
+ if (!priv->mac_core_rst)
+ return;
+
+ reset_control_assert(priv->mac_core_rst);
+ reset_control_deassert(priv->mac_core_rst);
+}
+
+static void hix5hd2_sleep_us(u32 time_us)
+{
+ u32 time_ms;
+
+ if (!time_us)
+ return;
+
+ time_ms = DIV_ROUND_UP(time_us, 1000);
+ if (time_ms < 20)
+ usleep_range(time_us, time_us + 500);
+ else
+ msleep(time_ms);
+}
+
+static void hix5hd2_phy_reset(struct hix5hd2_priv *priv)
+{
+ /* To make sure PHY hardware reset success,
+ * we must keep PHY in deassert state first and
+ * then complete the hardware reset operation
+ */
+ reset_control_deassert(priv->phy_rst);
+ hix5hd2_sleep_us(priv->phy_reset_delays[PRE_DELAY]);
+
+ reset_control_assert(priv->phy_rst);
+ /* delay some time to ensure reset ok,
+ * this depends on PHY hardware feature
+ */
+ hix5hd2_sleep_us(priv->phy_reset_delays[PULSE]);
+ reset_control_deassert(priv->phy_rst);
+ /* delay some time to ensure later MDIO access */
+ hix5hd2_sleep_us(priv->phy_reset_delays[POST_DELAY]);
+}
+
+static const struct of_device_id hix5hd2_of_match[];
+
static int hix5hd2_dev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
+ const struct of_device_id *of_id = NULL;
struct net_device *ndev;
struct hix5hd2_priv *priv;
struct resource *res;
@@ -883,6 +1117,13 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
priv->dev = dev;
priv->netdev = ndev;
+ of_id = of_match_device(hix5hd2_of_match, dev);
+ if (!of_id) {
+ ret = -EINVAL;
+ goto out_free_netdev;
+ }
+ priv->hw_cap = (unsigned long)of_id->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->base)) {
@@ -897,23 +1138,55 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
goto out_free_netdev;
}
- priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(priv->clk)) {
- netdev_err(ndev, "failed to get clk\n");
+ priv->mac_core_clk = devm_clk_get(&pdev->dev, "mac_core");
+ if (IS_ERR(priv->mac_core_clk)) {
+ netdev_err(ndev, "failed to get mac core clk\n");
ret = -ENODEV;
goto out_free_netdev;
}
- ret = clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->mac_core_clk);
if (ret < 0) {
- netdev_err(ndev, "failed to enable clk %d\n", ret);
+ netdev_err(ndev, "failed to enable mac core clk %d\n", ret);
goto out_free_netdev;
}
+ priv->mac_ifc_clk = devm_clk_get(&pdev->dev, "mac_ifc");
+ if (IS_ERR(priv->mac_ifc_clk))
+ priv->mac_ifc_clk = NULL;
+
+ ret = clk_prepare_enable(priv->mac_ifc_clk);
+ if (ret < 0) {
+ netdev_err(ndev, "failed to enable mac ifc clk %d\n", ret);
+ goto out_disable_mac_core_clk;
+ }
+
+ priv->mac_core_rst = devm_reset_control_get(dev, "mac_core");
+ if (IS_ERR(priv->mac_core_rst))
+ priv->mac_core_rst = NULL;
+ hix5hd2_mac_core_reset(priv);
+
+ priv->mac_ifc_rst = devm_reset_control_get(dev, "mac_ifc");
+ if (IS_ERR(priv->mac_ifc_rst))
+ priv->mac_ifc_rst = NULL;
+
+ priv->phy_rst = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(priv->phy_rst)) {
+ priv->phy_rst = NULL;
+ } else {
+ ret = of_property_read_u32_array(node,
+ PHY_RESET_DELAYS_PROPERTY,
+ priv->phy_reset_delays,
+ DELAYS_NUM);
+ if (ret)
+ goto out_disable_clk;
+ hix5hd2_phy_reset(priv);
+ }
+
bus = mdiobus_alloc();
if (bus == NULL) {
ret = -ENOMEM;
- goto out_free_netdev;
+ goto out_disable_clk;
}
bus->priv = priv;
@@ -972,22 +1245,38 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
ndev->ethtool_ops = &hix5hd2_ethtools_ops;
SET_NETDEV_DEV(ndev, dev);
+ if (HAS_CAP_TSO(priv->hw_cap))
+ ndev->hw_features |= NETIF_F_SG;
+
+ ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+ ndev->vlan_features |= ndev->features;
+
ret = hix5hd2_init_hw_desc_queue(priv);
if (ret)
goto out_phy_node;
netif_napi_add(ndev, &priv->napi, hix5hd2_poll, NAPI_POLL_WEIGHT);
+
+ if (HAS_CAP_TSO(priv->hw_cap)) {
+ ret = hix5hd2_init_sg_desc_queue(priv);
+ if (ret)
+ goto out_destroy_queue;
+ }
+
ret = register_netdev(priv->netdev);
if (ret) {
netdev_err(ndev, "register_netdev failed!");
goto out_destroy_queue;
}
- clk_disable_unprepare(priv->clk);
+ clk_disable_unprepare(priv->mac_ifc_clk);
+ clk_disable_unprepare(priv->mac_core_clk);
return ret;
out_destroy_queue:
+ if (HAS_CAP_TSO(priv->hw_cap))
+ hix5hd2_destroy_sg_desc_queue(priv);
netif_napi_del(&priv->napi);
hix5hd2_destroy_hw_desc_queue(priv);
out_phy_node:
@@ -996,6 +1285,10 @@ err_mdiobus:
mdiobus_unregister(bus);
err_free_mdio:
mdiobus_free(bus);
+out_disable_clk:
+ clk_disable_unprepare(priv->mac_ifc_clk);
+out_disable_mac_core_clk:
+ clk_disable_unprepare(priv->mac_core_clk);
out_free_netdev:
free_netdev(ndev);
@@ -1012,6 +1305,8 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
mdiobus_unregister(priv->bus);
mdiobus_free(priv->bus);
+ if (HAS_CAP_TSO(priv->hw_cap))
+ hix5hd2_destroy_sg_desc_queue(priv);
hix5hd2_destroy_hw_desc_queue(priv);
of_node_put(priv->phy_node);
cancel_work_sync(&priv->tx_timeout_task);
@@ -1021,7 +1316,10 @@ static int hix5hd2_dev_remove(struct platform_device *pdev)
}
static const struct of_device_id hix5hd2_of_match[] = {
- {.compatible = "hisilicon,hix5hd2-gmac",},
+ { .compatible = "hisilicon,hisi-gemac-v1", .data = (void *)GEMAC_V1 },
+ { .compatible = "hisilicon,hisi-gemac-v2", .data = (void *)GEMAC_V2 },
+ { .compatible = "hisilicon,hix5hd2-gemac", .data = (void *)GEMAC_V1 },
+ { .compatible = "hisilicon,hi3798cv200-gemac", .data = (void *)GEMAC_V2 },
{},
};
@@ -1029,7 +1327,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_of_match);
static struct platform_driver hix5hd2_dev_driver = {
.driver = {
- .name = "hix5hd2-gmac",
+ .name = "hisi-gemac",
.of_match_table = hix5hd2_of_match,
},
.probe = hix5hd2_dev_probe,
@@ -1038,6 +1336,6 @@ static struct platform_driver hix5hd2_dev_driver = {
module_platform_driver(hix5hd2_dev_driver);
-MODULE_DESCRIPTION("HISILICON HIX5HD2 Ethernet driver");
+MODULE_DESCRIPTION("HISILICON Gigabit Ethernet MAC driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:hix5hd2-gmac");
+MODULE_ALIAS("platform:hisi-gemac");
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
index e093cbf26c8c..8016854796fb 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -99,6 +99,8 @@ enum hnae_led_state {
#define HNS_RX_FLAG_L3ID_IPV6 0x1
#define HNS_RX_FLAG_L4ID_UDP 0x0
#define HNS_RX_FLAG_L4ID_TCP 0x1
+#define HNS_RX_FLAG_L4ID_SCTP 0x3
+
#define HNS_TXD_ASID_S 0
#define HNS_TXD_ASID_M (0xff << HNS_TXD_ASID_S)
@@ -426,8 +428,14 @@ enum hnae_media_type {
* get mac address
* set_mac_addr()
* set mac address
+ * clr_mc_addr()
+ * clear mcast tcam table
* set_mc_addr()
* set multicast mode
+ * add_uc_addr()
+ * add ucast address
+ * rm_uc_addr()
+ * remove ucast address
* set_mtu()
* set mtu
* update_stats()
@@ -488,6 +496,11 @@ struct hnae_ae_ops {
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 (*add_uc_addr)(struct hnae_handle *handle,
+ const unsigned char *addr);
+ int (*rm_uc_addr)(struct hnae_handle *handle,
+ const unsigned char *addr);
+ int (*clr_mc_addr)(struct hnae_handle *handle);
int (*set_mc_addr)(struct hnae_handle *handle, void *addr);
int (*set_mtu)(struct hnae_handle *handle, int new_mtu);
void (*set_tso_stats)(struct hnae_handle *handle, int enable);
@@ -590,7 +603,7 @@ static inline int hnae_alloc_buffer_attach(struct hnae_ring *ring, int i)
if (ret)
return ret;
- ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+ ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma);
return 0;
}
@@ -621,14 +634,14 @@ static inline void hnae_replace_buffer(struct hnae_ring *ring, int i,
bops->unmap_buffer(ring, &ring->desc_cb[i]);
ring->desc_cb[i] = *res_cb;
- ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+ ring->desc[i].addr = cpu_to_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[i].addr = cpu_to_le64(ring->desc_cb[i].dma
+ ring->desc_cb[i].page_offset);
ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index 2d0cb609adc3..0a9cdf00b31a 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -18,9 +18,6 @@
#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)
{
@@ -202,6 +199,28 @@ static int hns_ae_set_mac_address(struct hnae_handle *handle, void *p)
return 0;
}
+static int hns_ae_add_uc_address(struct hnae_handle *handle,
+ const unsigned char *addr)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+ return -ENOSPC;
+
+ return hns_mac_add_uc_addr(mac_cb, handle->vf_id, addr);
+}
+
+static int hns_ae_rm_uc_address(struct hnae_handle *handle,
+ const unsigned char *addr)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+ return -ENOSPC;
+
+ return hns_mac_rm_uc_addr(mac_cb, handle->vf_id, addr);
+}
+
static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr)
{
int ret;
@@ -235,6 +254,16 @@ static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr)
return ret;
}
+static int hns_ae_clr_multicast(struct hnae_handle *handle)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+ return 0;
+
+ return hns_mac_clr_multicast(mac_cb, handle->vf_id);
+}
+
static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu)
{
struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
@@ -823,7 +852,10 @@ static struct hnae_ae_ops hns_dsaf_ops = {
.get_coalesce_range = hns_ae_get_coalesce_range,
.set_promisc_mode = hns_ae_set_promisc_mode,
.set_mac_addr = hns_ae_set_mac_address,
+ .add_uc_addr = hns_ae_add_uc_address,
+ .rm_uc_addr = hns_ae_rm_uc_address,
.set_mc_addr = hns_ae_set_multicast_one,
+ .clr_mc_addr = hns_ae_clr_multicast,
.set_mtu = hns_ae_set_mtu,
.update_stats = hns_ae_update_stats,
.set_tso_stats = hns_ae_set_tso_stats,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 1e1eb92998fb..3382441fe7b5 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -37,8 +37,8 @@ static const struct mac_stats_string g_gmac_stats_string[] = {
{"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_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_pkts)},
+ {"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_bytes)},
{"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)},
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index ec8c738af726..3239d27143b9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -263,6 +263,46 @@ int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb,
return 0;
}
+int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+ const unsigned char *addr)
+{
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+ int ret;
+
+ if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+ return -ENOSPC;
+
+ memset(&mac_entry, 0, sizeof(mac_entry));
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_port_num = mac_cb->mac_id;
+ ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num);
+ if (ret)
+ return ret;
+
+ return hns_dsaf_set_mac_uc_entry(dsaf_dev, &mac_entry);
+}
+
+int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+ const unsigned char *addr)
+{
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+ int ret;
+
+ if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+ return -ENOSPC;
+
+ memset(&mac_entry, 0, sizeof(mac_entry));
+ memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+ mac_entry.in_port_num = mac_cb->mac_id;
+ ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num);
+ if (ret)
+ return ret;
+
+ return hns_dsaf_rm_mac_addr(dsaf_dev, &mac_entry);
+}
+
int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
u32 port_num, char *addr, bool enable)
{
@@ -330,13 +370,24 @@ int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac)
return 0;
}
+int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn)
+{
+ struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+ u8 port_num;
+ int ret = hns_mac_get_inner_port_num(mac_cb, vfn, &port_num);
+
+ if (ret)
+ return ret;
+
+ return hns_dsaf_clr_mac_mc_port(dsaf_dev, mac_cb->mac_id, port_num);
+}
+
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);
+ ether_addr_copy(param->addr, mac_cb->addr_entry_idx[0].addr);
param->mac_id = mac_cb->mac_id;
param->dev = mac_cb->dev;
}
@@ -353,8 +404,7 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb,
{
int ret;
struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
- u8 addr[MAC_NUM_OCTETS_PER_ADDR]
- = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct dsaf_drv_mac_single_dest_entry mac_entry;
/* directy return ok in debug network mode */
@@ -389,8 +439,7 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable)
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};
+ u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct mac_entry_idx *uc_mac_entry;
struct dsaf_drv_mac_single_dest_entry mac_entry;
@@ -453,8 +502,7 @@ int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu)
if (mac_cb->mac_type == HNAE_PORT_DEBUG)
max_frm = MAC_MAX_MTU_DBG;
- if ((new_mtu < MAC_MIN_MTU) || (new_frm > max_frm) ||
- (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size))
+ if (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size)
return -EINVAL;
if (!drv->config_max_frame_length)
@@ -869,6 +917,13 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb)
}
}
+ if (fwnode_property_read_u8_array(mac_cb->fw_port, "mc-mac-mask",
+ mac_cb->mc_mask, ETH_ALEN)) {
+ dev_warn(mac_cb->dev,
+ "no mc-mac-mask property, set to default value.\n");
+ eth_broadcast_addr(mac_cb->mc_mask);
+ }
+
return 0;
}
@@ -1082,6 +1137,8 @@ void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en)
{
struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+ hns_dsaf_set_promisc_tcam(mac_cb->dsaf_dev, mac_cb->mac_id, !!en);
+
if (mac_ctrl_drv->set_promiscuous)
mac_ctrl_drv->set_promiscuous(mac_ctrl_drv, en);
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
index d3a1f72ece0e..2bb3d1e93c64 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -31,7 +31,7 @@ struct dsaf_device;
#define MAC_MIN_MTU 68
#define MAC_MAX_MTU_DBG MAC_DEFAULT_MTU
-#define MAC_DEFAULT_PAUSE_TIME 0xff
+#define MAC_DEFAULT_PAUSE_TIME 0xffff
#define MAC_GMAC_IDX 0
#define MAC_XGMAC_IDX 1
@@ -56,9 +56,6 @@ struct dsaf_device;
/*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;
};
@@ -189,7 +186,7 @@ struct mac_statistics {
/*mac para struct ,mac get param from nic or dsaf when initialize*/
struct mac_params {
- char addr[MAC_NUM_OCTETS_PER_ADDR];
+ char addr[ETH_ALEN];
void *vaddr; /*virtual address*/
struct device *dev;
u8 mac_id;
@@ -214,7 +211,7 @@ struct mac_info {
};
struct mac_entry_idx {
- u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+ u8 addr[ETH_ALEN];
u16 vlan_id:12;
u16 valid:1;
u16 qos:3;
@@ -317,6 +314,7 @@ struct hns_mac_cb {
u8 __iomem *serdes_vaddr;
struct regmap *serdes_ctrl;
struct regmap *cpld_ctrl;
+ char mc_mask[ETH_ALEN];
u32 cpld_ctrl_reg;
u32 port_rst_off;
u32 port_mode_off;
@@ -409,7 +407,7 @@ struct mac_driver {
};
struct mac_stats_string {
- char desc[64];
+ char desc[ETH_GSTRING_LEN];
unsigned long offset;
};
@@ -463,5 +461,10 @@ int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en);
int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
u8 vmid, u8 *port_num);
+int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+ const unsigned char *addr);
+int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+ const unsigned char *addr);
+int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn);
#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
index 8ea3d95fa483..90dbda792614 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -591,6 +591,16 @@ static void hns_dsaf_voq_bp_all_thrd_cfg(struct dsaf_device *dsaf_dev)
}
}
+static void hns_dsaf_tbl_tcam_match_cfg(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_tbl_tcam_data *ptbl_tcam_data)
+{
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_L_REG,
+ ptbl_tcam_data->tbl_tcam_data_low);
+ dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_H_REG,
+ ptbl_tcam_data->tbl_tcam_data_high);
+}
+
/**
* hns_dsaf_tbl_tcam_data_cfg - tbl
* @dsaf_id: dsa fabric id
@@ -755,7 +765,7 @@ static void hns_dsaf_tbl_tcam_data_ucast_pul(
void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en)
{
- if (!HNS_DSAF_IS_DEBUG(dsaf_dev))
+ if (AE_IS_VER1(dsaf_dev->dsaf_ver) && !HNS_DSAF_IS_DEBUG(dsaf_dev))
dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG,
DSAF_CFG_MIX_MODE_S, !!en);
}
@@ -894,15 +904,16 @@ static void hns_dsaf_tcam_uc_cfg(
}
/**
- * hns_dsaf_tcam_mc_cfg - INT
- * @dsaf_id: dsa fabric id
- * @address,
- * @ptbl_tcam_data,
- * @ptbl_tcam_mcast,
+ * hns_dsaf_tcam_mc_cfg - cfg the tcam for mc
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address: tcam index
+ * @ptbl_tcam_data: tcam data struct pointer
+ * @ptbl_tcam_mcast: tcam mask struct pointer, it must be null for HNSv1
*/
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_data *ptbl_tcam_mask,
struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast)
{
spin_lock_bh(&dsaf_dev->tcam_lock);
@@ -913,7 +924,11 @@ static void hns_dsaf_tcam_mc_cfg(
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*/
+ /* Write Match Data */
+ if (ptbl_tcam_mask)
+ hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, ptbl_tcam_mask);
+
+ /* Write Puls */
hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
spin_unlock_bh(&dsaf_dev->tcam_lock);
@@ -944,6 +959,16 @@ static void hns_dsaf_tcam_mc_invld(struct dsaf_device *dsaf_dev, u32 address)
spin_unlock_bh(&dsaf_dev->tcam_lock);
}
+void hns_dsaf_tcam_addr_get(struct dsaf_drv_tbl_tcam_key *mac_key, u8 *addr)
+{
+ addr[0] = mac_key->high.bits.mac_0;
+ addr[1] = mac_key->high.bits.mac_1;
+ addr[2] = mac_key->high.bits.mac_2;
+ addr[3] = mac_key->high.bits.mac_3;
+ addr[4] = mac_key->low.bits.mac_4;
+ addr[5] = mac_key->low.bits.mac_5;
+}
+
/**
* hns_dsaf_tcam_uc_get - INT
* @dsaf_id: dsa fabric id
@@ -1369,6 +1394,12 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev)
if (HNS_DSAF_IS_DEBUG(dsaf_dev))
return 0;
+ if (AE_IS_VER1(dsaf_dev->dsaf_ver))
+ dsaf_dev->tcam_max_num = DSAF_TCAM_SUM;
+ else
+ dsaf_dev->tcam_max_num =
+ DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM;
+
spin_lock_init(&dsaf_dev->tcam_lock);
ret = hns_dsaf_init_hw(dsaf_dev);
if (ret)
@@ -1424,7 +1455,7 @@ static u16 hns_dsaf_find_soft_mac_entry(
u32 i;
soft_mac_entry = priv->soft_mac_tbl;
- for (i = 0; i < DSAF_TCAM_SUM; i++) {
+ for (i = 0; i < dsaf_dev->tcam_max_num; i++) {
/* invall tab entry */
if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) &&
(soft_mac_entry->tcam_key.high.val == mac_key->high.val) &&
@@ -1449,7 +1480,7 @@ static u16 hns_dsaf_find_empty_mac_entry(struct dsaf_device *dsaf_dev)
u32 i;
soft_mac_entry = priv->soft_mac_tbl;
- for (i = 0; i < DSAF_TCAM_SUM; i++) {
+ for (i = 0; i < dsaf_dev->tcam_max_num; i++) {
/* inv all entry */
if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX)
/* return find result --soft index */
@@ -1488,8 +1519,12 @@ static void hns_dsaf_set_mac_key(
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;
+ dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_VLAN_M,
+ DSAF_TBL_TCAM_KEY_VLAN_S, vlan_id);
+ dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_PORT_M,
+ DSAF_TBL_TCAM_KEY_PORT_S, port);
+
+ mac_key->low.bits.port_vlan = le16_to_cpu(mac_key->low.bits.port_vlan);
}
/**
@@ -1507,6 +1542,7 @@ int hns_dsaf_set_mac_uc_entry(
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_tbl_tcam_data tcam_data;
/* mac addr check */
if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1548,9 +1584,10 @@ int hns_dsaf_set_mac_uc_entry(
/* 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);
+ tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+ tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+ hns_dsaf_tcam_uc_cfg(dsaf_dev, entry_index, &tcam_data, &mac_data);
/* config software entry */
soft_mac_entry += entry_index;
@@ -1561,6 +1598,55 @@ int hns_dsaf_set_mac_uc_entry(
return 0;
}
+int hns_dsaf_rm_mac_addr(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+ u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+ struct dsaf_tbl_tcam_ucast_cfg mac_data;
+ struct dsaf_drv_tbl_tcam_key mac_key;
+
+ /* mac addr check */
+ if (!is_valid_ether_addr(mac_entry->addr)) {
+ dev_err(dsaf_dev->dev, "rm_uc_addr %s Mac %pM err!\n",
+ dsaf_dev->ae_dev.name, mac_entry->addr);
+ 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_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+ if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+ /* can not find the tcam entry, return 0 */
+ dev_info(dsaf_dev->dev,
+ "rm_uc_addr no tcam, %s Mac key(%#x:%#x)\n",
+ dsaf_dev->ae_dev.name,
+ mac_key.high.val, mac_key.low.val);
+ return 0;
+ }
+
+ dev_dbg(dsaf_dev->dev,
+ "rm_uc_addr, %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_uc_get(
+ dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&mac_key,
+ &mac_data);
+
+ /* unicast entry not used locally should not clear */
+ if (mac_entry->port_num != mac_data.tbl_ucast_out_port)
+ return -EFAULT;
+
+ return hns_dsaf_del_mac_entry(dsaf_dev,
+ mac_entry->in_vlan_id,
+ mac_entry->in_port_num,
+ mac_entry->addr);
+}
+
/**
* hns_dsaf_set_mac_mc_entry - set mac mc-entry
* @dsaf_dev: dsa fabric device struct pointer
@@ -1577,6 +1663,7 @@ int hns_dsaf_set_mac_mc_entry(
(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;
+ struct dsaf_tbl_tcam_data tcam_data;
/* mac addr check */
if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
@@ -1609,9 +1696,12 @@ int hns_dsaf_set_mac_mc_entry(
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);
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data,
+ &mac_data);
+
+ tmp_mac_key.high.val =
+ le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
}
mac_data.tbl_mcast_old_en = 0;
mac_data.tbl_mcast_item_vld = 1;
@@ -1623,9 +1713,11 @@ int hns_dsaf_set_mac_mc_entry(
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);
+ tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+ tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+ hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, NULL,
+ &mac_data);
/* config software entry */
soft_mac_entry += entry_index;
@@ -1636,6 +1728,16 @@ int hns_dsaf_set_mac_mc_entry(
return 0;
}
+static void hns_dsaf_mc_mask_bit_clear(char *dst, const char *src)
+{
+ u16 *a = (u16 *)dst;
+ const u16 *b = (const u16 *)src;
+
+ a[0] &= b[0];
+ a[1] &= b[1];
+ a[2] &= b[2];
+}
+
/**
* hns_dsaf_add_mac_mc_port - add mac mc-port
* @dsaf_dev: dsa fabric device struct pointer
@@ -1646,11 +1748,15 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
{
u16 entry_index = DSAF_INVALID_ENTRY_IDX;
struct dsaf_drv_tbl_tcam_key mac_key;
+ struct dsaf_drv_tbl_tcam_key mask_key;
+ struct dsaf_tbl_tcam_data *pmask_key = NULL;
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_priv *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;
+ struct dsaf_tbl_tcam_data tcam_data;
+ u8 mc_addr[ETH_ALEN];
+ u8 *mc_mask;
int mskid;
/*chechk mac addr */
@@ -1660,14 +1766,32 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
return -EINVAL;
}
+ ether_addr_copy(mc_addr, mac_entry->addr);
+ mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask;
+ if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) {
+ /* prepare for key data setting */
+ hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask);
+
+ /* config key mask */
+ hns_dsaf_set_mac_key(dsaf_dev, &mask_key,
+ 0x0,
+ 0xff,
+ mc_mask);
+
+ mask_key.high.val = le32_to_cpu(mask_key.high.val);
+ mask_key.low.val = le32_to_cpu(mask_key.low.val);
+
+ pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key);
+ }
+
/*config key */
hns_dsaf_set_mac_key(
dsaf_dev, &mac_key, mac_entry->in_vlan_id,
- mac_entry->in_port_num, mac_entry->addr);
+ mac_entry->in_port_num, mc_addr);
memset(&mac_data, 0, sizeof(struct dsaf_tbl_tcam_mcast_cfg));
- /*check exist? */
+ /* check if the tcam is 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*/
@@ -1681,11 +1805,15 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
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);
+ /* if exist, add in */
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data,
+ &mac_data);
+
+ tmp_mac_key.high.val =
+ le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
}
+
/* config hardware entry */
if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
mskid = mac_entry->port_num;
@@ -1708,9 +1836,12 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
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);
+ tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+ tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+ /* config mc entry with mask */
+ hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data,
+ pmask_key, &mac_data);
/*config software entry */
soft_mac_entry += entry_index;
@@ -1782,15 +1913,18 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
{
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_priv *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;
+ struct dsaf_tbl_tcam_data tcam_data;
int mskid;
const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0};
+ struct dsaf_drv_tbl_tcam_key mask_key, tmp_mac_key;
+ struct dsaf_tbl_tcam_data *pmask_key = NULL;
+ u8 mc_addr[ETH_ALEN];
+ u8 *mc_mask;
if (!(void *)mac_entry) {
dev_err(dsaf_dev->dev,
@@ -1798,10 +1932,6 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
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 %pM!\n",
@@ -1809,11 +1939,31 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
return -EINVAL;
}
- /*config key */
- hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num,
- mac_entry->addr);
+ /* always mask vlan_id field */
+ ether_addr_copy(mc_addr, mac_entry->addr);
+ mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask;
+
+ if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) {
+ /* prepare for key data setting */
+ hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask);
+
+ /* config key mask */
+ hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_addr);
+
+ mask_key.high.val = le32_to_cpu(mask_key.high.val);
+ mask_key.low.val = le32_to_cpu(mask_key.low.val);
- /*check is exist? */
+ pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key);
+ }
+
+ /* get key info */
+ vlan_id = mac_entry->in_vlan_id;
+ in_port_num = mac_entry->in_port_num;
+
+ /* config key */
+ hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, mc_addr);
+
+ /* check if the tcam entry is exist */
entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
if (entry_index == DSAF_INVALID_ENTRY_IDX) {
/*find none */
@@ -1829,10 +1979,11 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
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);
+ /* read entry */
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+ tmp_mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
/*del the port*/
if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
@@ -1857,15 +2008,87 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
/* 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);
+ } else { /* not zero, just del port, update */
+ tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+ tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+ hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index,
+ &tcam_data,
+ pmask_key, &mac_data);
}
return 0;
}
+int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, u8 mac_id,
+ u8 port_num)
+{
+ struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+ struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ int ret = 0, i;
+
+ if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+ return 0;
+
+ for (i = 0; i < DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM; i++) {
+ u8 addr[ETH_ALEN];
+ u8 port;
+
+ soft_mac_entry = priv->soft_mac_tbl + i;
+
+ hns_dsaf_tcam_addr_get(&soft_mac_entry->tcam_key, addr);
+ port = dsaf_get_field(
+ soft_mac_entry->tcam_key.low.bits.port_vlan,
+ DSAF_TBL_TCAM_KEY_PORT_M,
+ DSAF_TBL_TCAM_KEY_PORT_S);
+ /* check valid tcam mc entry */
+ if (soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX &&
+ port == mac_id &&
+ is_multicast_ether_addr(addr) &&
+ !is_broadcast_ether_addr(addr)) {
+ const u32 empty_msk[DSAF_PORT_MSK_NUM] = {0};
+ struct dsaf_drv_mac_single_dest_entry mac_entry;
+
+ /* disable receiving of this multicast address for
+ * the VF.
+ */
+ ether_addr_copy(mac_entry.addr, addr);
+ mac_entry.in_vlan_id = dsaf_get_field(
+ soft_mac_entry->tcam_key.low.bits.port_vlan,
+ DSAF_TBL_TCAM_KEY_VLAN_M,
+ DSAF_TBL_TCAM_KEY_VLAN_S);
+ mac_entry.in_port_num = mac_id;
+ mac_entry.port_num = port_num;
+ if (hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry)) {
+ ret = -EINVAL;
+ continue;
+ }
+
+ /* disable receiving of this multicast address for
+ * the mac port if all VF are disable
+ */
+ hns_dsaf_tcam_mc_get(dsaf_dev, i,
+ (struct dsaf_tbl_tcam_data *)
+ (&soft_mac_entry->tcam_key),
+ &mac_data);
+ dsaf_set_bit(mac_data.tbl_mcast_port_msk[mac_id / 32],
+ mac_id % 32, 0);
+ if (!memcmp(mac_data.tbl_mcast_port_msk, empty_msk,
+ sizeof(u32) * DSAF_PORT_MSK_NUM)) {
+ mac_entry.port_num = mac_id;
+ if (hns_dsaf_del_mac_mc_port(dsaf_dev,
+ &mac_entry)) {
+ ret = -EINVAL;
+ continue;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
/**
* hns_dsaf_get_mac_uc_entry - get mac uc entry
* @dsaf_dev: dsa fabric device struct pointer
@@ -1878,6 +2101,7 @@ int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
struct dsaf_drv_tbl_tcam_key mac_key;
struct dsaf_tbl_tcam_ucast_cfg mac_data;
+ struct dsaf_tbl_tcam_data tcam_data;
/* check macaddr */
if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1906,9 +2130,12 @@ int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
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);
+ /* read entry */
+ hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+ mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
+
mac_entry->port_num = mac_data.tbl_ucast_out_port;
return 0;
@@ -1926,6 +2153,7 @@ int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
struct dsaf_drv_tbl_tcam_key mac_key;
struct dsaf_tbl_tcam_mcast_cfg mac_data;
+ struct dsaf_tbl_tcam_data tcam_data;
/*check mac addr */
if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1955,8 +2183,10 @@ int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
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);
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+ mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
return 0;
@@ -1976,9 +2206,10 @@ int hns_dsaf_get_mac_entry_by_index(
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};
+ struct dsaf_tbl_tcam_data tcam_data;
+ char mac_addr[ETH_ALEN] = {0};
- if (entry_index >= DSAF_TCAM_SUM) {
+ if (entry_index >= dsaf_dev->tcam_max_num) {
/* find none, del error */
dev_err(dsaf_dev->dev, "get_uc_entry failed, %s\n",
dsaf_dev->ae_dev.name);
@@ -1986,8 +2217,10 @@ int hns_dsaf_get_mac_entry_by_index(
}
/* mc entry, do read opt */
- hns_dsaf_tcam_mc_get(dsaf_dev, entry_index,
- (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+ mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
@@ -2004,9 +2237,12 @@ int hns_dsaf_get_mac_entry_by_index(
/**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,
+ hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data,
&mac_uc_data);
+
+ mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+ mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
+
mac_entry->port_mask[0] = (1 << mac_uc_data.tbl_ucast_out_port);
}
@@ -2670,6 +2906,59 @@ int hns_dsaf_get_regs_count(void)
return DSAF_DUMP_REGS_NUM;
}
+/* Reserve the last TCAM entry for promisc support */
+#define dsaf_promisc_tcam_entry(port) \
+ (DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM + (port))
+void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
+ u32 port, bool enable)
+{
+ struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+ struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+ u16 entry_index;
+ struct dsaf_drv_tbl_tcam_key tbl_tcam_data, tbl_tcam_mask;
+ struct dsaf_tbl_tcam_mcast_cfg mac_data = {0};
+
+ if ((AE_IS_VER1(dsaf_dev->dsaf_ver)) || HNS_DSAF_IS_DEBUG(dsaf_dev))
+ return;
+
+ /* find the tcam entry index for promisc */
+ entry_index = dsaf_promisc_tcam_entry(port);
+
+ /* config key mask */
+ if (enable) {
+ memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data));
+ memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask));
+ dsaf_set_field(tbl_tcam_data.low.bits.port_vlan,
+ DSAF_TBL_TCAM_KEY_PORT_M,
+ DSAF_TBL_TCAM_KEY_PORT_S, port);
+ dsaf_set_field(tbl_tcam_mask.low.bits.port_vlan,
+ DSAF_TBL_TCAM_KEY_PORT_M,
+ DSAF_TBL_TCAM_KEY_PORT_S, 0xf);
+
+ /* SUB_QID */
+ dsaf_set_bit(mac_data.tbl_mcast_port_msk[0],
+ DSAF_SERVICE_NW_NUM, true);
+ mac_data.tbl_mcast_item_vld = true; /* item_vld bit */
+ } else {
+ mac_data.tbl_mcast_item_vld = false; /* item_vld bit */
+ }
+
+ dev_dbg(dsaf_dev->dev,
+ "set_promisc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+ dsaf_dev->ae_dev.name, tbl_tcam_data.high.val,
+ tbl_tcam_data.low.val, entry_index);
+
+ /* config promisc entry with mask */
+ hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index,
+ (struct dsaf_tbl_tcam_data *)&tbl_tcam_data,
+ (struct dsaf_tbl_tcam_data *)&tbl_tcam_mask,
+ &mac_data);
+
+ /* config software entry */
+ soft_mac_entry += entry_index;
+ soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
+}
+
/**
* dsaf_probe - probo dsaf dev
* @pdev: dasf platform device
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index c494fc52be74..cef6bf46ae93 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -35,8 +35,6 @@ struct hns_mac_cb;
#define DSAF_CFG_READ_CNT 30
-#define MAC_NUM_OCTETS_PER_ADDR 6
-
#define DSAF_DUMP_REGS_NUM 504
#define DSAF_STATIC_NUM 28
#define DSAF_V2_STATIC_NUM 44
@@ -165,7 +163,7 @@ enum dsaf_mode {
/*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];
+ u8 addr[ETH_ALEN];
u16 in_vlan_id; /* value of VlanId */
/* the vld input port num, dsaf-mode fix 0, */
@@ -179,7 +177,7 @@ struct dsaf_drv_mac_single_dest_entry {
/*only mc entry*/
struct dsaf_drv_mac_multi_dest_entry {
/* mac addr, match the entry*/
- u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+ u8 addr[ETH_ALEN];
u16 in_vlan_id;
/* this mac addr output port,*/
/* bit0-bit5 means Port0-Port5(1bit is vld)**/
@@ -308,8 +306,6 @@ struct dsaf_misc_op {
/* reset series function, it will be reset if the dereset is 0 */
void (*dsaf_reset)(struct dsaf_device *dsaf_dev, bool dereset);
void (*xge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
- void (*xge_core_srst)(struct dsaf_device *dsaf_dev, u32 port,
- bool dereset);
void (*ge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
void (*ppe_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
void (*ppe_comm_srst)(struct dsaf_device *dsaf_dev, bool dereset);
@@ -343,6 +339,7 @@ struct dsaf_device {
enum hal_dsaf_mode dsaf_en;
enum hal_dsaf_tc_mode dsaf_tc_mode;
u32 dsaf_ver;
+ u16 tcam_max_num; /* max TCAM entry for user except promisc */
struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM];
struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM];
@@ -360,6 +357,11 @@ static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev)
return (void *)((u8 *)dsaf_dev + sizeof(*dsaf_dev));
}
+#define DSAF_TBL_TCAM_KEY_PORT_S 0
+#define DSAF_TBL_TCAM_KEY_PORT_M (((1ULL << 4) - 1) << 0)
+#define DSAF_TBL_TCAM_KEY_VLAN_S 4
+#define DSAF_TBL_TCAM_KEY_VLAN_M (((1ULL << 12) - 1) << 4)
+
struct dsaf_drv_tbl_tcam_key {
union {
struct {
@@ -373,11 +375,9 @@ struct dsaf_drv_tbl_tcam_key {
} 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;
+ u16 port_vlan;
+ u8 mac_5;
+ u8 mac_4;
} bits;
u32 val;
@@ -461,10 +461,19 @@ 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);
+void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
+ u32 port, bool enable);
void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id,
u32 *en);
int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id,
u32 en);
+int hns_dsaf_rm_mac_addr(
+ struct dsaf_device *dsaf_dev,
+ struct dsaf_drv_mac_single_dest_entry *mac_entry);
+
+int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev,
+ u8 mac_id, u8 port_num);
+
#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
index 67accce1d33d..a2c22d084ce9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -23,7 +23,6 @@ enum _dsm_op_index {
enum _dsm_rst_type {
HNS_DSAF_RESET_FUNC = 0x1,
HNS_PPE_RESET_FUNC = 0x2,
- HNS_XGE_CORE_RESET_FUNC = 0x3,
HNS_XGE_RESET_FUNC = 0x4,
HNS_GE_RESET_FUNC = 0x5,
HNS_DSAF_CHN_RESET_FUNC = 0x6,
@@ -213,26 +212,6 @@ static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
HNS_XGE_RESET_FUNC, port, dereset);
}
-static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev,
- u32 port, bool dereset)
-{
- u32 reg_val = 0;
- u32 reg_addr;
-
- if (port >= DSAF_XGE_NUM)
- return;
-
- reg_val |= XGMAC_TRX_CORE_SRST_M
- << dsaf_dev->mac_cb[port]->port_rst_off;
-
- if (!dereset)
- reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG;
- else
- reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG;
-
- dsaf_write_sub(dsaf_dev, reg_addr, reg_val);
-}
-
/**
* hns_dsaf_srst_chns - reset dsaf channels
* @dsaf_dev: dsaf device struct pointer
@@ -293,14 +272,6 @@ void hns_dsaf_roce_srst_acpi(struct dsaf_device *dsaf_dev, bool dereset)
HNS_ROCE_RESET_FUNC, 0, dereset);
}
-static void
-hns_dsaf_xge_core_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
- u32 port, bool dereset)
-{
- hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC,
- HNS_XGE_CORE_RESET_FUNC, port, dereset);
-}
-
static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port,
bool dereset)
{
@@ -597,7 +568,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
misc_op->dsaf_reset = hns_dsaf_rst;
misc_op->xge_srst = hns_dsaf_xge_srst_by_port;
- misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port;
misc_op->ge_srst = hns_dsaf_ge_srst_by_port;
misc_op->ppe_srst = hns_ppe_srst_by_port;
misc_op->ppe_comm_srst = hns_ppe_com_srst;
@@ -615,7 +585,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
misc_op->dsaf_reset = hns_dsaf_rst_acpi;
misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi;
- misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port_acpi;
misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi;
misc_op->ppe_srst = hns_ppe_srst_by_port_acpi;
misc_op->ppe_comm_srst = hns_ppe_com_srst;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index 878950a42e6c..87226685f742 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -41,6 +41,9 @@
#define DSAF_SW_PORT_NUM 8
#define DSAF_TOTAL_QUEUE_NUM 129
+/* reserved a tcam entry for each port to support promisc by fuzzy match */
+#define DSAFV2_MAC_FUZZY_TCAM_NUM DSAF_MAX_PORT_NUM
+
#define DSAF_TCAM_SUM 512
#define DSAF_LINE_SUM (2048 * 14)
@@ -297,6 +300,8 @@
#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_TBL_TCAM_MATCH_CFG_H_REG 0x5130
+#define DSAF_TBL_TCAM_MATCH_CFG_L_REG 0x5134
#define DSAF_INODE_FIFO_WL_0_REG 0x6000
#define DSAF_ONODE_FIFO_WL_0_REG 0x6020
@@ -309,7 +314,6 @@
#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
@@ -698,8 +702,6 @@
#define XGMAC_RX_SYMBOLERRPKTS 0x0210
#define XGMAC_RX_FCSERRPKTS 0x0218
-#define XGMAC_TRX_CORE_SRST_M 0x2080
-
#define DSAF_SRAM_INIT_OVER_M 0xff
#define DSAFV2_SRAM_INIT_OVER_M 0x3ff
#define DSAF_SRAM_INIT_OVER_S 0
@@ -978,6 +980,11 @@
#define XGMAC_ENABLE_TX_B 0
#define XGMAC_ENABLE_RX_B 1
+#define XGMAC_UNIDIR_EN_B 0
+#define XGMAC_RF_TX_EN_B 1
+#define XGMAC_LF_RF_INSERT_S 2
+#define XGMAC_LF_RF_INSERT_M (0x3 << XGMAC_LF_RF_INSERT_S)
+
#define XGMAC_CTL_TX_FCS_B 0
#define XGMAC_CTL_TX_PAD_B 1
#define XGMAC_CTL_TX_PREAMBLE_TRANS_B 3
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
index 8f4f0e8da984..aae830a93050 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
@@ -108,6 +108,31 @@ static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value)
}
/**
+ * hns_xgmac_tx_lf_rf_insert - insert lf rf control about xgmac
+ * @mac_drv: mac driver
+ * @mode: inserf rf or lf
+ */
+static void hns_xgmac_lf_rf_insert(struct mac_driver *mac_drv, u32 mode)
+{
+ dsaf_set_dev_field(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG,
+ XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, mode);
+}
+
+/**
+ * hns_xgmac__lf_rf_control_init - initial the lf rf control register
+ * @mac_drv: mac driver
+ */
+static void hns_xgmac_lf_rf_control_init(struct mac_driver *mac_drv)
+{
+ u32 val = 0;
+
+ dsaf_set_bit(val, XGMAC_UNIDIR_EN_B, 0);
+ dsaf_set_bit(val, XGMAC_RF_TX_EN_B, 1);
+ dsaf_set_field(val, XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, 0);
+ dsaf_write_reg(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, val);
+}
+
+/**
*hns_xgmac_enable - enable xgmac port
*@drv: mac driver
*@mode: mode of mac port
@@ -115,12 +140,8 @@ static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value)
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;
- dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 1);
- mdelay(10);
+ hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_NO_LF_RF_INSERT);
/*enable XGE rX/tX */
if (mode == MAC_COMM_MODE_TX) {
@@ -143,9 +164,6 @@ static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode)
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);
@@ -155,9 +173,7 @@ static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode)
hns_xgmac_tx_enable(drv, 0);
hns_xgmac_rx_enable(drv, 0);
}
-
- mdelay(10);
- dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 0);
+ hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_LF_INSERT);
}
/**
@@ -203,6 +219,7 @@ static void hns_xgmac_init(void *mac_drv)
dsaf_dev->misc_op->xge_srst(dsaf_dev, port, 1);
mdelay(100);
+ hns_xgmac_lf_rf_control_init(drv);
hns_xgmac_exc_irq_en(drv, 0);
hns_xgmac_pma_fec_enable(drv, 0x0, 0x0);
@@ -788,7 +805,7 @@ static int hns_xgmac_get_sset_count(int stringset)
*/
static int hns_xgmac_get_regs_count(void)
{
- return ETH_XGMAC_DUMP_NUM;
+ return HNS_XGMAC_DUMP_NUM;
}
void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
index 139f7297c7b4..da6c5343d3e1 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
@@ -10,6 +10,7 @@
#ifndef _HNS_XGMAC_H
#define _HNS_XGMAC_H
-#define ETH_XGMAC_DUMP_NUM (214)
-
+#define HNS_XGMAC_DUMP_NUM 214
+#define HNS_XGMAC_NO_LF_RF_INSERT 0x0
+#define HNS_XGMAC_LF_INSERT 0x2
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index dff7b60345d8..672b64606321 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -22,6 +22,7 @@
#include "hnae.h"
#include "hns_enet.h"
+#include "hns_dsaf_mac.h"
#define NIC_MAX_Q_PER_VF 16
#define HNS_NIC_TX_TIMEOUT (5 * HZ)
@@ -565,6 +566,71 @@ static void get_rx_desc_bnum(u32 bnum_flag, int *out_bnum)
HNS_RXD_BUFNUM_M, HNS_RXD_BUFNUM_S);
}
+static void hns_nic_rx_checksum(struct hns_nic_ring_data *ring_data,
+ struct sk_buff *skb, u32 flag)
+{
+ struct net_device *netdev = ring_data->napi.dev;
+ u32 l3id;
+ u32 l4id;
+
+ /* check if RX checksum offload is enabled */
+ if (unlikely(!(netdev->features & NETIF_F_RXCSUM)))
+ return;
+
+ /* In hardware, we only support checksum for the following protocols:
+ * 1) IPv4,
+ * 2) TCP(over IPv4 or IPv6),
+ * 3) UDP(over IPv4 or IPv6),
+ * 4) SCTP(over IPv4 or IPv6)
+ * but we support many L3(IPv4, IPv6, MPLS, PPPoE etc) and L4(TCP,
+ * UDP, GRE, SCTP, IGMP, ICMP etc.) protocols.
+ *
+ * Hardware limitation:
+ * Our present hardware RX Descriptor lacks L3/L4 checksum "Status &
+ * Error" bit (which usually can be used to indicate whether checksum
+ * was calculated by the hardware and if there was any error encountered
+ * during checksum calculation).
+ *
+ * Software workaround:
+ * We do get info within the RX descriptor about the kind of L3/L4
+ * protocol coming in the packet and the error status. These errors
+ * might not just be checksum errors but could be related to version,
+ * length of IPv4, UDP, TCP etc.
+ * Because there is no-way of knowing if it is a L3/L4 error due to bad
+ * checksum or any other L3/L4 error, we will not (cannot) convey
+ * checksum status for such cases to upper stack and will not maintain
+ * the RX L3/L4 checksum counters as well.
+ */
+
+ l3id = hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S);
+ l4id = hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S);
+
+ /* check L3 protocol for which checksum is supported */
+ if ((l3id != HNS_RX_FLAG_L3ID_IPV4) && (l3id != HNS_RX_FLAG_L3ID_IPV6))
+ return;
+
+ /* check for any(not just checksum)flagged L3 protocol errors */
+ if (unlikely(hnae_get_bit(flag, HNS_RXD_L3E_B)))
+ return;
+
+ /* we do not support checksum of fragmented packets */
+ if (unlikely(hnae_get_bit(flag, HNS_RXD_FRAG_B)))
+ return;
+
+ /* check L4 protocol for which checksum is supported */
+ if ((l4id != HNS_RX_FLAG_L4ID_TCP) &&
+ (l4id != HNS_RX_FLAG_L4ID_UDP) &&
+ (l4id != HNS_RX_FLAG_L4ID_SCTP))
+ return;
+
+ /* check for any(not just checksum)flagged L4 protocol errors */
+ if (unlikely(hnae_get_bit(flag, HNS_RXD_L4E_B)))
+ return;
+
+ /* now, this has to be a packet with valid RX checksum */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
struct sk_buff **out_skb, int *out_bnum)
{
@@ -683,13 +749,10 @@ out_bnum_err:
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;
+ /* indicate to upper stack if our hardware has already calculated
+ * the RX checksum
+ */
+ hns_nic_rx_checksum(ring_data, skb, bnum_flag);
return 0;
}
@@ -1426,10 +1489,6 @@ static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu)
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;
@@ -1496,6 +1555,29 @@ static netdev_features_t hns_nic_fix_features(
return features;
}
+static int hns_nic_uc_sync(struct net_device *netdev, const unsigned char *addr)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ if (h->dev->ops->add_uc_addr)
+ return h->dev->ops->add_uc_addr(h, addr);
+
+ return 0;
+}
+
+static int hns_nic_uc_unsync(struct net_device *netdev,
+ const unsigned char *addr)
+{
+ struct hns_nic_priv *priv = netdev_priv(netdev);
+ struct hnae_handle *h = priv->ae_handle;
+
+ if (h->dev->ops->rm_uc_addr)
+ return h->dev->ops->rm_uc_addr(h, addr);
+
+ return 0;
+}
+
/**
* nic_set_multicast_list - set mutl mac address
* @netdev: net device
@@ -1514,6 +1596,10 @@ void hns_set_multicast_list(struct net_device *ndev)
return;
}
+ if (h->dev->ops->clr_mc_addr)
+ if (h->dev->ops->clr_mc_addr(h))
+ netdev_err(ndev, "clear multicast address fail\n");
+
if (h->dev->ops->set_mc_addr) {
netdev_for_each_mc_addr(ha, ndev)
if (h->dev->ops->set_mc_addr(h, ha->addr))
@@ -1534,6 +1620,9 @@ void hns_nic_set_rx_mode(struct net_device *ndev)
}
hns_set_multicast_list(ndev);
+
+ if (__dev_uc_sync(ndev, hns_nic_uc_sync, hns_nic_uc_unsync))
+ netdev_err(ndev, "sync uc address fail\n");
}
struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev,
@@ -1992,14 +2081,20 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
+ /* MTU range: 68 - 9578 (v1) or 9706 (v2) */
+ ndev->min_mtu = MAC_MIN_MTU;
switch (priv->enet_ver) {
case AE_VERSION_2:
ndev->features |= NETIF_F_TSO | NETIF_F_TSO6;
ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6;
+ ndev->max_mtu = MAC_MAX_MTU_V2 -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
break;
default:
+ ndev->max_mtu = MAC_MAX_MTU -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
break;
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 87d5c94b2810..3ac2183dbd21 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -1178,7 +1178,8 @@ static int hns_nic_nway_reset(struct net_device *netdev)
struct phy_device *phy = netdev->phydev;
if (netif_running(netdev)) {
- if (phy)
+ /* if autoneg is disabled, don't restart auto-negotiation */
+ if (phy && phy->autoneg == AUTONEG_ENABLE)
ret = genphy_restart_aneg(phy);
}
diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
index 631dbc7b4dbb..1a31bee6e728 100644
--- a/drivers/net/ethernet/hp/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -427,7 +427,6 @@ static const struct net_device_ops hp100_bm_netdev_ops = {
.ndo_start_xmit = hp100_start_xmit_bm,
.ndo_get_stats = hp100_get_stats,
.ndo_set_rx_mode = hp100_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -438,7 +437,6 @@ static const struct net_device_ops hp100_netdev_ops = {
.ndo_start_xmit = hp100_start_xmit,
.ndo_get_stats = hp100_get_stats,
.ndo_set_rx_mode = hp100_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index ce235b776793..945883842533 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1118,7 +1118,6 @@ static const struct net_device_ops i596_netdev_ops = {
.ndo_start_xmit = i596_start_xmit,
.ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = i596_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index 5d353c660068..dc983450354b 100644
--- a/drivers/net/ethernet/i825xx/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -981,7 +981,6 @@ static const struct net_device_ops ether1_netdev_ops = {
.ndo_set_rx_mode = ether1_setmulticastlist,
.ndo_tx_timeout = ether1_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index 3dbc53c21baa..e86773325cbe 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1037,7 +1037,6 @@ static const struct net_device_ops i596_netdev_ops = {
.ndo_start_xmit = i596_start_xmit,
.ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = i596_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 21c84cc9c871..8bb15a8c2a40 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -337,7 +337,6 @@ static const struct net_device_ops sun3_82586_netdev_ops = {
.ndo_get_stats = sun3_82586_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr)
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index bd719e25dd76..702446a93697 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -1981,14 +1981,6 @@ out:
ehea_update_bcmc_registrations();
}
-static int ehea_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
{
swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
@@ -2970,7 +2962,6 @@ static const struct net_device_ops ehea_netdev_ops = {
.ndo_set_mac_address = ehea_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = ehea_set_multicast_list,
- .ndo_change_mtu = ehea_change_mtu,
.ndo_vlan_rx_add_vid = ehea_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ehea_vlan_rx_kill_vid,
.ndo_tx_timeout = ehea_tx_watchdog,
@@ -3043,13 +3034,16 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
NETIF_F_IP_CSUM;
dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
+ /* MTU range: 68 - 9022 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = EHEA_MAX_PACKET_SIZE;
+
INIT_WORK(&port->reset_task, ehea_reset_port);
INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats);
init_waitqueue_head(&port->swqe_avail_wq);
init_waitqueue_head(&port->restart_wq);
- memset(&port->stats, 0, sizeof(struct net_device_stats));
ret = register_netdev(dev);
if (ret) {
pr_err("register_netdev failed. ret=%d\n", ret);
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 8f139197f1aa..52a69c925965 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1099,9 +1099,6 @@ static int emac_change_mtu(struct net_device *ndev, int new_mtu)
struct emac_instance *dev = netdev_priv(ndev);
int ret = 0;
- if (new_mtu < EMAC_MIN_MTU || new_mtu > dev->max_mtu)
- return -EINVAL;
-
DBG(dev, "change_mtu(%d)" NL, new_mtu);
if (netif_running(ndev)) {
@@ -2564,7 +2561,7 @@ static int emac_init_config(struct emac_instance *dev)
if (emac_read_uint_prop(np, "cell-index", &dev->cell_index, 1))
return -ENXIO;
if (emac_read_uint_prop(np, "max-frame-size", &dev->max_mtu, 0))
- dev->max_mtu = 1500;
+ dev->max_mtu = ETH_DATA_LEN;
if (emac_read_uint_prop(np, "rx-fifo-size", &dev->rx_fifo_size, 0))
dev->rx_fifo_size = 2048;
if (emac_read_uint_prop(np, "tx-fifo-size", &dev->tx_fifo_size, 0))
@@ -2718,7 +2715,6 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = emac_set_mac_address,
.ndo_start_xmit = emac_start_xmit,
- .ndo_change_mtu = eth_change_mtu,
};
static const struct net_device_ops emac_gige_netdev_ops = {
@@ -2891,6 +2887,10 @@ static int emac_probe(struct platform_device *ofdev)
ndev->netdev_ops = &emac_netdev_ops;
ndev->ethtool_ops = &emac_ethtool_ops;
+ /* MTU range: 46 - 1500 or whatever is in OF */
+ ndev->min_mtu = EMAC_MIN_MTU;
+ ndev->max_mtu = dev->max_mtu;
+
netif_carrier_off(ndev);
err = register_netdev(ndev);
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index a36022ba4e42..fbece63395a8 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1410,9 +1410,6 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
int i, rc;
int need_restart = 0;
- if (new_mtu < IBMVETH_MIN_MTU)
- return -EINVAL;
-
for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size)
break;
@@ -1612,6 +1609,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
netdev->hw_features |= NETIF_F_TSO;
}
+ netdev->min_mtu = IBMVETH_MIN_MTU;
+ netdev->max_mtu = ETH_MAX_MTU;
+
memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
if (firmware_has_feature(FW_FEATURE_CMO))
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 0fbf686f5e7c..c12596676bbb 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -901,17 +901,6 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
return 0;
}
-static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
-{
- struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-
- if (new_mtu > adapter->req_mtu || new_mtu < adapter->min_mtu)
- return -EINVAL;
-
- netdev->mtu = new_mtu;
- return 0;
-}
-
static void ibmvnic_tx_timeout(struct net_device *dev)
{
struct ibmvnic_adapter *adapter = netdev_priv(dev);
@@ -1028,7 +1017,6 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
.ndo_set_rx_mode = ibmvnic_set_multi,
.ndo_set_mac_address = ibmvnic_set_mac,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = ibmvnic_change_mtu,
.ndo_tx_timeout = ibmvnic_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ibmvnic_netpoll_controller,
@@ -2638,10 +2626,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
break;
case MIN_MTU:
adapter->min_mtu = be64_to_cpu(crq->query_capability.number);
+ netdev->min_mtu = adapter->min_mtu;
netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu);
break;
case MAX_MTU:
adapter->max_mtu = be64_to_cpu(crq->query_capability.number);
+ netdev->max_mtu = adapter->max_mtu;
netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu);
break;
case MAX_MULTICAST_FILTERS:
@@ -3667,6 +3657,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
netdev->real_num_tx_queues = adapter->req_tx_queues;
netdev->mtu = adapter->req_mtu;
+ netdev->min_mtu = adapter->min_mtu;
+ netdev->max_mtu = adapter->max_mtu;
if (adapter->failover) {
adapter->failover = false;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index c0e17433f623..1349b45f014d 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -58,7 +58,7 @@ config E1000E
tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
depends on PCI && (!SPARC32 || BROKEN)
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -83,7 +83,7 @@ config E1000E_HWTS
config IGB
tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on PCI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select I2C
select I2C_ALGOBIT
---help---
@@ -156,7 +156,7 @@ config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
depends on PCI
select MDIO
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Intel(R) 10GbE PCI Express family of
adapters. For more information on how to identify your adapter, go
@@ -213,7 +213,7 @@ config IXGBEVF
config I40E
tristate "Intel(R) Ethernet Controller XL710 Family support"
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
depends on PCI
---help---
This driver supports Intel(R) Ethernet Controller XL710 Family of
@@ -264,7 +264,7 @@ config FM10K
tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
default n
depends on PCI_MSI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Intel(R) FM10000 Ethernet Switch Host
Interface. For more information on how to identify your adapter,
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 068789e694c9..25c6dfd500b4 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2286,14 +2286,6 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)
return 0;
}
-static int e100_change_mtu(struct net_device *netdev, int new_mtu)
-{
- if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
- return -EINVAL;
- netdev->mtu = new_mtu;
- return 0;
-}
-
static int e100_asf(struct nic *nic)
{
/* ASF can be enabled from eeprom */
@@ -2834,7 +2826,6 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = e100_set_multicast_list,
.ndo_set_mac_address = e100_set_mac_address,
- .ndo_change_mtu = e100_change_mtu,
.ndo_do_ioctl = e100_do_ioctl,
.ndo_tx_timeout = e100_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index f42129d09e2c..93fc6c67306b 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1085,6 +1085,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 46 - 16110 */
+ netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
/* initialize eeprom parameters */
@@ -3549,13 +3553,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
- if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- e_err(probe, "Invalid MTU setting\n");
- return -EINVAL;
- }
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
/* Adapter-specific max frame size limits. */
switch (hw->mac_type) {
@@ -5257,8 +5255,8 @@ static void e1000_netpoll(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- disable_irq(adapter->pdev->irq);
- e1000_intr(adapter->pdev->irq, netdev);
+ if (disable_hardirq(adapter->pdev->irq))
+ e1000_intr(adapter->pdev->irq, netdev);
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 7017281ba2dc..ffcf35af4881 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5974,19 +5974,12 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
/* Jumbo frame support */
- if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) &&
+ if ((new_mtu > ETH_DATA_LEN) &&
!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
e_err("Jumbo Frames not supported.\n");
return -EINVAL;
}
- /* Supported frame sizes */
- if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) ||
- (max_frame > adapter->max_hw_frame_size)) {
- e_err("Unsupported MTU setting\n");
- return -EINVAL;
- }
-
/* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
if ((adapter->hw.mac.type >= e1000_pch2lan) &&
!(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
@@ -6762,13 +6755,13 @@ static void e1000_netpoll(struct net_device *netdev)
e1000_intr_msix(adapter->pdev->irq, netdev);
break;
case E1000E_INT_MODE_MSI:
- disable_irq(adapter->pdev->irq);
- e1000_intr_msi(adapter->pdev->irq, netdev);
+ if (disable_hardirq(adapter->pdev->irq))
+ e1000_intr_msi(adapter->pdev->irq, netdev);
enable_irq(adapter->pdev->irq);
break;
default: /* E1000E_INT_MODE_LEGACY */
- disable_irq(adapter->pdev->irq);
- e1000_intr(adapter->pdev->irq, netdev);
+ if (disable_hardirq(adapter->pdev->irq))
+ e1000_intr(adapter->pdev->irq, netdev);
enable_irq(adapter->pdev->irq);
break;
}
@@ -7187,6 +7180,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
+ /* MTU range: 68 - max_hw_frame_size */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = adapter->max_hw_frame_size -
+ (VLAN_ETH_HLEN + ETH_FCS_LEN);
+
if (e1000e_enable_mng_pass_thru(&adapter->hw))
adapter->flags |= FLAG_MNG_PT_ENABLED;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 05629381be6b..bc5ef6eb3dd6 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -706,16 +706,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)
return err;
}
-static int fm10k_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < 68 || new_mtu > FM10K_MAX_JUMBO_FRAME_SIZE)
- return -EINVAL;
-
- dev->mtu = new_mtu;
-
- return 0;
-}
-
/**
* fm10k_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
@@ -1405,7 +1395,6 @@ static const struct net_device_ops fm10k_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_start_xmit = fm10k_xmit_frame,
.ndo_set_mac_address = fm10k_set_mac,
- .ndo_change_mtu = fm10k_change_mtu,
.ndo_tx_timeout = fm10k_tx_timeout,
.ndo_vlan_rx_add_vid = fm10k_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = fm10k_vlan_rx_kill_vid,
@@ -1490,5 +1479,9 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
dev->hw_features |= hw_features;
+ /* MTU range: 68 - 15342 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = FM10K_MAX_JUMBO_FRAME_SIZE;
+
return dev;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 6d61e443bdf8..ba8d30984bee 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -39,6 +39,7 @@
#include <linux/iommu.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <linux/hashtable.h>
#include <linux/string.h>
#include <linux/in.h>
#include <linux/ip.h>
@@ -355,9 +356,11 @@ struct i40e_pf {
#define I40E_FLAG_NO_DCB_SUPPORT BIT_ULL(45)
#define I40E_FLAG_USE_SET_LLDP_MIB BIT_ULL(46)
#define I40E_FLAG_STOP_FW_LLDP BIT_ULL(47)
-#define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48)
+#define I40E_FLAG_PHY_CONTROLS_LEDS BIT_ULL(48)
#define I40E_FLAG_PF_MAC BIT_ULL(50)
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(51)
+#define I40E_FLAG_HAVE_CRT_RETIMER BIT_ULL(52)
+#define I40E_FLAG_PTP_L4_CAPABLE BIT_ULL(53)
/* tracks features that get auto disabled by errors */
u64 auto_disable_flags;
@@ -428,11 +431,13 @@ struct i40e_pf {
struct ptp_clock_info ptp_caps;
struct sk_buff *ptp_tx_skb;
struct hwtstamp_config tstamp_config;
- unsigned long last_rx_ptp_check;
- spinlock_t tmreg_lock; /* Used to protect the device time registers. */
+ struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
u64 ptp_base_adj;
u32 tx_hwtstamp_timeouts;
u32 rx_hwtstamp_cleared;
+ u32 latch_event_flags;
+ spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
+ unsigned long latch_events[4];
bool ptp_tx;
bool ptp_rx;
u16 rss_table_size; /* HW RSS table size */
@@ -445,6 +450,20 @@ struct i40e_pf {
u16 phy_led_val;
};
+/**
+ * i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key
+ * @macaddr: the MAC Address as the base key
+ *
+ * Simply copies the address and returns it as a u64 for hashing
+ **/
+static inline u64 i40e_addr_to_hkey(const u8 *macaddr)
+{
+ u64 key = 0;
+
+ ether_addr_copy((u8 *)&key, macaddr);
+ return key;
+}
+
enum i40e_filter_state {
I40E_FILTER_INVALID = 0, /* Invalid state */
I40E_FILTER_NEW, /* New, not sent to FW yet */
@@ -454,13 +473,10 @@ enum i40e_filter_state {
/* There is no 'removed' state; the filter struct is freed */
};
struct i40e_mac_filter {
- struct list_head list;
+ struct hlist_node hlist;
u8 macaddr[ETH_ALEN];
#define I40E_VLAN_ANY -1
s16 vlan;
- u8 counter; /* number of instances of this filter */
- bool is_vf; /* filter belongs to a VF */
- bool is_netdev; /* filter belongs to a netdev */
enum i40e_filter_state state;
};
@@ -501,9 +517,11 @@ 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;
+ /* Per VSI lock to protect elements/hash (MAC filter) */
+ spinlock_t mac_filter_hash_lock;
+ /* Fixed size hash table with 2^8 buckets for MAC filters */
+ DECLARE_HASHTABLE(mac_filter_hash, 8);
+ bool has_vlan_filter;
/* VSI stats */
struct rtnl_link_stats64 net_stats;
@@ -579,6 +597,7 @@ struct i40e_vsi {
u16 veb_idx; /* index of VEB parent */
struct kobject *kobj; /* sysfs object */
bool current_isup; /* Sync 'link up' logging */
+ enum i40e_aq_link_speed current_speed; /* Sync link speed logging */
void *priv; /* client driver data reference. */
@@ -608,6 +627,8 @@ struct i40e_q_vector {
unsigned long hung_detected; /* Set/Reset for hung_detection logic */
cpumask_t affinity_mask;
+ struct irq_affinity_notify affinity_notify;
+
struct rcu_head rcu; /* to avoid race with update stats on free */
char name[I40E_INT_NAME_STR_LEN];
bool arm_wb_state;
@@ -705,6 +726,25 @@ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
u16 rss_table_size, u16 rss_size);
struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id);
+/**
+ * i40e_find_vsi_by_type - Find and return Flow Director VSI
+ * @pf: PF to search for VSI
+ * @type: Value indicating type of VSI we are looking for
+ **/
+static inline struct i40e_vsi *
+i40e_find_vsi_by_type(struct i40e_pf *pf, u16 type)
+{
+ int i;
+
+ for (i = 0; i < pf->num_alloc_vsi; i++) {
+ struct i40e_vsi *vsi = pf->vsi[i];
+
+ if (vsi && vsi->type == type)
+ return vsi;
+ }
+
+ return NULL;
+}
void i40e_update_stats(struct i40e_vsi *vsi);
void i40e_update_eth_stats(struct i40e_vsi *vsi);
struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
@@ -721,16 +761,12 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf);
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
void i40e_set_ethtool_ops(struct net_device *netdev);
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
- u8 *macaddr, s16 vlan,
- bool is_vf, bool is_netdev);
-void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan,
- bool is_vf, bool is_netdev);
+ const u8 *macaddr, s16 vlan);
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
u16 uplink, u32 param1);
int i40e_vsi_release(struct i40e_vsi *vsi);
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
- struct i40e_vsi *start_vsi);
#ifdef I40E_FCOE
void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
struct i40e_vsi_context *ctxt,
@@ -740,7 +776,8 @@ void i40e_service_event_schedule(struct i40e_pf *pf);
void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id,
u8 *msg, u16 len);
-int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
+int i40e_vsi_start_rings(struct i40e_vsi *vsi);
+void i40e_vsi_stop_rings(struct i40e_vsi *vsi);
int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
u16 downlink_seid, u8 enabled_tc);
@@ -815,15 +852,15 @@ int i40e_open(struct net_device *netdev);
int i40e_close(struct net_device *netdev);
int i40e_vsi_open(struct i40e_vsi *vsi);
void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
+int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
-int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
-struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev);
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev);
+void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
+void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
+struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
+ const u8 *macaddr);
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr);
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev);
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
#ifdef I40E_FCOE
int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
struct tc_to_netdev *tc);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 738b42a44f20..56fb27298936 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -964,11 +964,11 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
desc_idx = ntc;
+ hw->aq.arq_last_status =
+ (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
flags = le16_to_cpu(desc->flags);
if (flags & I40E_AQ_FLAG_ERR) {
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
- hw->aq.arq_last_status =
- (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
i40e_debug(hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index 67e396b2b347..b2101a51534c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1642,6 +1642,10 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_1000BASE_LX = 0x1C,
I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D,
I40E_PHY_TYPE_20GBASE_KR2 = 0x1E,
+ I40E_PHY_TYPE_25GBASE_KR = 0x1F,
+ I40E_PHY_TYPE_25GBASE_CR = 0x20,
+ I40E_PHY_TYPE_25GBASE_SR = 0x21,
+ I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_MAX
};
@@ -1650,6 +1654,7 @@ enum i40e_aq_phy_type {
#define I40E_LINK_SPEED_10GB_SHIFT 0x3
#define I40E_LINK_SPEED_40GB_SHIFT 0x4
#define I40E_LINK_SPEED_20GB_SHIFT 0x5
+#define I40E_LINK_SPEED_25GB_SHIFT 0x6
enum i40e_aq_link_speed {
I40E_LINK_SPEED_UNKNOWN = 0,
@@ -1657,7 +1662,8 @@ enum i40e_aq_link_speed {
I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
- I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT)
+ I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
+ I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
};
struct i40e_aqc_module_desc {
@@ -1680,6 +1686,8 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_LINK_ENABLED 0x08
#define I40E_AQ_PHY_AN_ENABLED 0x10
#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR 0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS 0x80
__le16 eee_capability;
#define I40E_AQ_EEE_100BASE_TX 0x0002
#define I40E_AQ_EEE_1000BASE_T 0x0004
@@ -1690,7 +1698,22 @@ struct i40e_aq_get_phy_abilities_resp {
__le32 eeer_val;
u8 d3_lpan;
#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR 0x01
+#define I40E_AQ_ENABLE_FEC_RS 0x02
+#define I40E_AQ_REQUEST_FEC_KR 0x04
+#define I40E_AQ_REQUEST_FEC_RS 0x08
+#define I40E_AQ_ENABLE_FEC_AUTO 0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK 0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT 5
+
+ u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
u8 qualified_module_count;
@@ -1712,7 +1735,20 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
__le16 eee_capability;
__le32 eeer;
u8 low_power_ctrl;
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS BIT(3)
+#define I40E_AQ_SET_FEC_AUTO BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT 0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+ u8 reserved;
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1792,9 +1828,18 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_LINK_TX_DRAINED 0x01
#define I40E_AQ_LINK_TX_FLUSHED 0x03
#define I40E_AQ_LINK_FORCED_40G 0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR 0X00
+#define I40E_AQ_25G_NOT_PRESENT 0X01
+#define I40E_AQ_25G_NVM_CRC_ERR 0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR 0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
u8 external_power_ability;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c
index 250db0b244b7..7fe72abc0b4a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_client.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_client.c
@@ -287,6 +287,7 @@ void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)
}
cdev->client->ops->close(&cdev->lan_info, cdev->client,
reset);
+ clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
i40e_client_release_qvlist(&cdev->lan_info);
}
}
@@ -406,37 +407,6 @@ int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id,
}
/**
- * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi
- * @pf: board private structure
- * @type: vsi type
- * @start_vsi: a VSI pointer from where to start the search
- *
- * Returns non NULL on success or NULL for failure
- **/
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf,
- enum i40e_vsi_type type,
- struct i40e_vsi *start_vsi)
-{
- struct i40e_vsi *vsi;
- int i = 0;
-
- if (start_vsi) {
- for (i = 0; i < pf->num_alloc_vsi; i++) {
- vsi = pf->vsi[i];
- if (vsi == start_vsi)
- break;
- }
- }
- for (; i < pf->num_alloc_vsi; i++) {
- vsi = pf->vsi[i];
- if (vsi && vsi->type == type)
- return vsi;
- }
-
- return NULL;
-}
-
-/**
* i40e_client_add_instance - add a client instance struct to the instance list
* @pf: pointer to the board struct
* @client: pointer to a client struct in the client list.
@@ -565,7 +535,7 @@ void i40e_client_subtask(struct i40e_pf *pf)
if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state))
continue;
} else {
- dev_warn(&pf->pdev->dev, "This client %s is being instanciated at probe\n",
+ dev_warn(&pf->pdev->dev, "This client %s is being instantiated at probe\n",
client->name);
}
@@ -575,29 +545,25 @@ void i40e_client_subtask(struct i40e_pf *pf)
continue;
if (!existing) {
- /* Also up the ref_cnt for no. of instances of this
- * client.
- */
- atomic_inc(&client->ref_cnt);
dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n",
client->name, pf->hw.pf_id,
pf->hw.bus.device, pf->hw.bus.func);
}
mutex_lock(&i40e_client_instance_mutex);
- /* Send an Open request to the client */
- atomic_inc(&cdev->ref_cnt);
- if (client->ops && client->ops->open)
- ret = client->ops->open(&cdev->lan_info, client);
- atomic_dec(&cdev->ref_cnt);
- if (!ret) {
- set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
- } else {
- /* remove client instance */
- mutex_unlock(&i40e_client_instance_mutex);
- i40e_client_del_instance(pf, client);
- atomic_dec(&client->ref_cnt);
- continue;
+ if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,
+ &cdev->state)) {
+ /* Send an Open request to the client */
+ if (client->ops && client->ops->open)
+ ret = client->ops->open(&cdev->lan_info,
+ client);
+ if (!ret) {
+ set_bit(__I40E_CLIENT_INSTANCE_OPENED,
+ &cdev->state);
+ } else {
+ /* remove client instance */
+ i40e_client_del_instance(pf, client);
+ }
}
mutex_unlock(&i40e_client_instance_mutex);
}
@@ -694,10 +660,6 @@ static int i40e_client_release(struct i40e_client *client)
continue;
pf = (struct i40e_pf *)cdev->lan_info.pf;
if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
- if (atomic_read(&cdev->ref_cnt) > 0) {
- ret = I40E_ERR_NOT_READY;
- goto out;
- }
if (client->ops && client->ops->close)
client->ops->close(&cdev->lan_info, client,
false);
@@ -710,11 +672,9 @@ static int i40e_client_release(struct i40e_client *client)
}
/* delete the client instance from the list */
list_move(&cdev->list, &cdevs_tmp);
- atomic_dec(&client->ref_cnt);
dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",
client->name);
}
-out:
mutex_unlock(&i40e_client_instance_mutex);
/* free the client device and release its vsi */
@@ -1040,17 +1000,10 @@ int i40e_unregister_client(struct i40e_client *client)
ret = -ENODEV;
goto out;
}
- if (atomic_read(&client->ref_cnt) == 0) {
- clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
- list_del(&client->list);
- pr_info("i40e: Unregistered client %s with return code %d\n",
- client->name, ret);
- } else {
- ret = I40E_ERR_NOT_READY;
- pr_err("i40e: Client %s failed unregister - client has open instances\n",
- client->name);
- }
-
+ clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
+ list_del(&client->list);
+ pr_info("i40e: Unregistered client %s with return code %d\n",
+ client->name, ret);
out:
mutex_unlock(&i40e_client_mutex);
return ret;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.h b/drivers/net/ethernet/intel/i40e/i40e_client.h
index 38a6c36a6a0e..528bd79b05fe 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_client.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_client.h
@@ -203,8 +203,6 @@ struct i40e_client_instance {
struct i40e_info lan_info;
struct i40e_client *client;
unsigned long state;
- /* A count of all the in-progress calls to the client */
- atomic_t ref_cnt;
};
struct i40e_client {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 2154a34c1dd8..128735975caa 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -53,6 +53,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
case I40E_DEV_ID_20G_KR2_A:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_KX_X722:
@@ -1183,6 +1185,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_1000BASE_LX:
case I40E_PHY_TYPE_40GBASE_SR4:
case I40E_PHY_TYPE_40GBASE_LR4:
+ case I40E_PHY_TYPE_25GBASE_LR:
+ case I40E_PHY_TYPE_25GBASE_SR:
media = I40E_MEDIA_TYPE_FIBER;
break;
case I40E_PHY_TYPE_100BASE_TX:
@@ -1197,6 +1201,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_10GBASE_SFPP_CU:
case I40E_PHY_TYPE_40GBASE_AOC:
case I40E_PHY_TYPE_10GBASE_AOC:
+ case I40E_PHY_TYPE_25GBASE_CR:
media = I40E_MEDIA_TYPE_DA;
break;
case I40E_PHY_TYPE_1000BASE_KX:
@@ -1204,6 +1209,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_10GBASE_KR:
case I40E_PHY_TYPE_40GBASE_KR4:
case I40E_PHY_TYPE_20GBASE_KR2:
+ case I40E_PHY_TYPE_25GBASE_KR:
media = I40E_MEDIA_TYPE_BACKPLANE;
break;
case I40E_PHY_TYPE_SGMII:
@@ -1608,8 +1614,10 @@ 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)
+ if (report_init) {
hw->phy.phy_types = le32_to_cpu(abilities->phy_type);
+ hw->phy.phy_types |= ((u64)abilities->phy_type_ext << 32);
+ }
return status;
}
@@ -1701,10 +1709,13 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
/* Copy over all the old settings */
config.phy_type = abilities.phy_type;
+ config.phy_type_ext = abilities.phy_type_ext;
config.link_speed = abilities.link_speed;
config.eee_capability = abilities.eee_capability;
config.eeer = abilities.eeer_val;
config.low_power_ctrl = abilities.d3_lpan;
+ config.fec_config = abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_PHY_FEC_CONFIG_MASK;
status = i40e_aq_set_phy_config(hw, &config, NULL);
if (status)
@@ -1849,12 +1860,13 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
else
hw_link_info->crc_enable = false;
- if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE))
+ if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_IS_ENABLED))
hw_link_info->lse_enable = true;
else
hw_link_info->lse_enable = false;
- if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
+ if ((hw->mac.type == I40E_MAC_XL710) &&
+ (hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
@@ -2169,6 +2181,40 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
}
/**
+ * i40e_aq_set_vsi_bc_promisc_on_vlan
+ * @hw: pointer to the hw struct
+ * @seid: vsi number
+ * @enable: set broadcast promiscuous enable/disable for a given VLAN
+ * @vid: The VLAN tag filter - capture any broadcast packet with this VLAN tag
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
+ u16 seid, bool enable, u16 vid,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
+ (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
+ i40e_status status;
+ u16 flags = 0;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_vsi_promiscuous_modes);
+
+ if (enable)
+ flags |= I40E_AQC_SET_VSI_PROMISC_BROADCAST;
+
+ cmd->promiscuous_flags = cpu_to_le16(flags);
+ cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_BROADCAST);
+ cmd->seid = cpu_to_le16(seid);
+ cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
* i40e_aq_set_vsi_broadcast
* @hw: pointer to the hw struct
* @seid: vsi number
@@ -2494,7 +2540,10 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw)
if (status)
return status;
- if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+ /* extra checking needed to ensure link info to user is timely */
+ if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) &&
+ ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) ||
+ !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) {
status = i40e_aq_get_phy_capabilities(hw, false, false,
&abilities, NULL);
if (status)
@@ -3144,6 +3193,14 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
break;
case I40E_AQ_CAP_ID_MNG_MODE:
p->management_mode = number;
+ if (major_rev > 1) {
+ p->mng_protocols_over_mctp = logical_id;
+ i40e_debug(hw, I40E_DEBUG_INIT,
+ "HW Capability: Protocols over MCTP = %d\n",
+ p->mng_protocols_over_mctp);
+ } else {
+ p->mng_protocols_over_mctp = 0;
+ }
break;
case I40E_AQ_CAP_ID_NPAR_ACTIVE:
p->npar_enable = number;
@@ -3310,8 +3367,10 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
/* partition id is 1-based, and functions are evenly spread
* across the ports as partitions
*/
- hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
- hw->num_partitions = num_functions / hw->num_ports;
+ if (hw->num_ports != 0) {
+ hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
+ hw->num_partitions = num_functions / hw->num_ports;
+ }
/* additional HW specific goodies that might
* someday be HW version specific
@@ -4391,7 +4450,92 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
}
/**
- * i40e_read_phy_register
+ * i40e_read_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
+ u16 reg, u8 phy_addr, u16 *value)
+{
+ i40e_status status = I40E_ERR_TIMEOUT;
+ u8 port_num = (u8)hw->func_caps.mdio_port_num;
+ u32 command = 0;
+ u16 retry = 1000;
+
+ command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+ (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+ (I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) |
+ (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+ (I40E_GLGEN_MSCA_MDICMD_MASK);
+ wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+ do {
+ command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+ if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+ status = 0;
+ break;
+ }
+ udelay(10);
+ retry--;
+ } while (retry);
+
+ if (status) {
+ i40e_debug(hw, I40E_DEBUG_PHY,
+ "PHY: Can't write command to external PHY.\n");
+ } else {
+ command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
+ *value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
+ I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
+ }
+
+ return status;
+}
+
+/**
+ * i40e_write_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes specified PHY register value
+ **/
+i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
+ u16 reg, u8 phy_addr, u16 value)
+{
+ i40e_status status = I40E_ERR_TIMEOUT;
+ u8 port_num = (u8)hw->func_caps.mdio_port_num;
+ u32 command = 0;
+ u16 retry = 1000;
+
+ command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
+ wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
+
+ command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+ (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+ (I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) |
+ (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+ (I40E_GLGEN_MSCA_MDICMD_MASK);
+
+ wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+ do {
+ command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+ if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+ status = 0;
+ break;
+ }
+ udelay(10);
+ retry--;
+ } while (retry);
+
+ return status;
+}
+
+/**
+ * i40e_read_phy_register_clause45
* @hw: pointer to the HW structure
* @page: registers page number
* @reg: register address in the page
@@ -4400,9 +4544,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
*
* Reads specified PHY register value
**/
-i40e_status i40e_read_phy_register(struct i40e_hw *hw,
- u8 page, u16 reg, u8 phy_addr,
- u16 *value)
+i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0;
@@ -4412,8 +4555,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
- (I40E_MDIO_OPCODE_ADDRESS) |
- (I40E_MDIO_STCODE) |
+ (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+ (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -4435,8 +4578,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
- (I40E_MDIO_OPCODE_READ) |
- (I40E_MDIO_STCODE) |
+ (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
+ (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT;
@@ -4466,7 +4609,7 @@ phy_read_end:
}
/**
- * i40e_write_phy_register
+ * i40e_write_phy_register_clause45
* @hw: pointer to the HW structure
* @page: registers page number
* @reg: register address in the page
@@ -4475,9 +4618,8 @@ phy_read_end:
*
* Writes value to specified PHY register
**/
-i40e_status i40e_write_phy_register(struct i40e_hw *hw,
- u8 page, u16 reg, u8 phy_addr,
- u16 value)
+i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0;
@@ -4487,8 +4629,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
- (I40E_MDIO_OPCODE_ADDRESS) |
- (I40E_MDIO_STCODE) |
+ (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+ (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -4512,8 +4654,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
- (I40E_MDIO_OPCODE_WRITE) |
- (I40E_MDIO_STCODE) |
+ (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
+ (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT;
@@ -4534,6 +4676,78 @@ phy_write_end:
}
/**
+ * i40e_write_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes value to specified PHY register
+ **/
+i40e_status i40e_write_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value)
+{
+ i40e_status status;
+
+ switch (hw->device_id) {
+ case I40E_DEV_ID_1G_BASE_T_X722:
+ status = i40e_write_phy_register_clause22(hw, reg, phy_addr,
+ value);
+ break;
+ case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_10G_BASE_T_X722:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
+ status = i40e_write_phy_register_clause45(hw, page, reg,
+ phy_addr, value);
+ break;
+ default:
+ status = I40E_ERR_UNKNOWN_PHY;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * i40e_read_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+i40e_status i40e_read_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value)
+{
+ i40e_status status;
+
+ switch (hw->device_id) {
+ case I40E_DEV_ID_1G_BASE_T_X722:
+ status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
+ value);
+ break;
+ case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_10G_BASE_T_X722:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
+ status = i40e_read_phy_register_clause45(hw, page, reg,
+ phy_addr, value);
+ break;
+ default:
+ status = I40E_ERR_UNKNOWN_PHY;
+ break;
+ }
+
+ return status;
+}
+
+/**
* i40e_get_phy_address
* @hw: pointer to the HW structure
* @dev_num: PHY port num that address we want
@@ -4575,14 +4789,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
led_addr++) {
- status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, &led_reg);
+ status = i40e_read_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ &led_reg);
if (status)
goto phy_blinking_end;
led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0;
- status = i40e_write_phy_register(hw,
+ status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
led_reg);
@@ -4594,20 +4810,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
if (time > 0 && interval > 0) {
for (i = 0; i < time * 1000; i += interval) {
- status = i40e_read_phy_register(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr,
- &led_reg);
+ status = i40e_read_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, &led_reg);
if (status)
goto restore_config;
if (led_reg & I40E_PHY_LED_MANUAL_ON)
led_reg = 0;
else
led_reg = I40E_PHY_LED_MANUAL_ON;
- status = i40e_write_phy_register(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr,
- led_reg);
+ status = i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, led_reg);
if (status)
goto restore_config;
msleep(interval);
@@ -4615,8 +4829,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
}
restore_config:
- status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
- phy_addr, led_ctl);
+ status = i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, led_ctl);
phy_blinking_end:
return status;
@@ -4647,8 +4862,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
temp_addr++) {
- status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
- temp_addr, phy_addr, &reg_val);
+ status = i40e_read_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ temp_addr, phy_addr,
+ &reg_val);
if (status)
return status;
*val = reg_val;
@@ -4681,41 +4898,42 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num);
-
- status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
- phy_addr, &led_reg);
+ status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, &led_reg);
if (status)
return status;
led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0;
- status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_reg);
+ status = i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ led_reg);
if (status)
return status;
}
- status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, &led_reg);
+ status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, &led_reg);
if (status)
goto restore_config;
if (on)
led_reg = I40E_PHY_LED_MANUAL_ON;
else
led_reg = 0;
- status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_reg);
+ status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, led_reg);
if (status)
goto restore_config;
if (mode & I40E_PHY_LED_MODE_ORIG) {
led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
- status = i40e_write_phy_register(hw,
+ status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl);
}
return status;
restore_config:
- status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
- phy_addr, led_ctl);
+ status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr, led_ctl);
return status;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 0c1875b5b16d..f1f41f12902f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -134,7 +134,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
struct rtnl_link_stats64 *nstat;
struct i40e_mac_filter *f;
struct i40e_vsi *vsi;
- int i;
+ int i, bkt;
vsi = i40e_dbg_find_vsi(pf, seid);
if (!vsi) {
@@ -166,13 +166,13 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
pf->hw.mac.addr,
pf->hw.mac.san_addr,
pf->hw.mac.port_addr);
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
dev_info(&pf->pdev->dev,
- " mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\n",
- f->macaddr, f->vlan, f->is_netdev, f->is_vf,
- f->counter, i40e_filter_state_string[f->state]);
+ " mac_filter_hash: %pM vid=%d, state %s\n",
+ f->macaddr, f->vlan,
+ i40e_filter_state_string[f->state]);
}
- dev_info(&pf->pdev->dev, " active_filters %d, promisc_threshold %d, overflow promisc %s\n",
+ dev_info(&pf->pdev->dev, " active_filters %u, promisc_threshold %u, overflow promisc %s\n",
vsi->active_filters, vsi->promisc_threshold,
(test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?
"ON" : "OFF"));
@@ -867,86 +867,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, "deleting relay %d\n", veb_seid);
i40e_veb_release(pf->veb[i]);
-
- } else if (strncmp(cmd_buf, "add macaddr", 11) == 0) {
- struct i40e_mac_filter *f;
- int vlan = 0;
- u8 ma[6];
- int ret;
-
- cnt = sscanf(&cmd_buf[11],
- "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i",
- &vsi_seid,
- &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5],
- &vlan);
- if (cnt == 7) {
- vlan = 0;
- } else if (cnt != 8) {
- dev_info(&pf->pdev->dev,
- "add macaddr: 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,
- "add macaddr: VSI %d not found\n", vsi_seid);
- goto command_write_done;
- }
-
- spin_lock_bh(&vsi->mac_filter_list_lock);
- f = i40e_add_filter(vsi, ma, vlan, false, false);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
- ret = i40e_sync_vsi_filters(vsi);
- if (f && !ret)
- dev_info(&pf->pdev->dev,
- "add macaddr: %pM vlan=%d added to VSI %d\n",
- ma, vlan, vsi_seid);
- else
- dev_info(&pf->pdev->dev,
- "add macaddr: %pM vlan=%d to VSI %d failed, f=%p ret=%d\n",
- ma, vlan, vsi_seid, f, ret);
-
- } else if (strncmp(cmd_buf, "del macaddr", 11) == 0) {
- int vlan = 0;
- u8 ma[6];
- int ret;
-
- cnt = sscanf(&cmd_buf[11],
- "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i",
- &vsi_seid,
- &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5],
- &vlan);
- if (cnt == 7) {
- vlan = 0;
- } else if (cnt != 8) {
- dev_info(&pf->pdev->dev,
- "del macaddr: 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 macaddr: VSI %d not found\n", vsi_seid);
- goto command_write_done;
- }
-
- spin_lock_bh(&vsi->mac_filter_list_lock);
- i40e_del_filter(vsi, ma, vlan, false, false);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
- ret = i40e_sync_vsi_filters(vsi);
- if (!ret)
- dev_info(&pf->pdev->dev,
- "del macaddr: %pM vlan=%d removed from VSI %d\n",
- ma, vlan, vsi_seid);
- else
- dev_info(&pf->pdev->dev,
- "del macaddr: %pM vlan=%d from VSI %d failed, ret=%d\n",
- ma, vlan, vsi_seid, ret);
-
} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {
i40e_status ret;
u16 vid;
@@ -1210,24 +1130,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev,
"dump debug fwdata <cluster_id> <table_id> <index>\n");
}
-
- } else if (strncmp(cmd_buf, "msg_enable", 10) == 0) {
- u32 level;
- cnt = sscanf(&cmd_buf[10], "%i", &level);
- if (cnt) {
- if (I40E_DEBUG_USER & level) {
- pf->hw.debug_mask = level;
- dev_info(&pf->pdev->dev,
- "set hw.debug_mask = 0x%08x\n",
- pf->hw.debug_mask);
- }
- pf->msg_enable = level;
- dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n",
- pf->msg_enable);
- } else {
- dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n",
- pf->msg_enable);
- }
} else if (strncmp(cmd_buf, "pfr", 3) == 0) {
dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n");
i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
@@ -1633,8 +1535,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, " del vsi [vsi_seid]\n");
dev_info(&pf->pdev->dev, " add relay <uplink_seid> <vsi_seid>\n");
dev_info(&pf->pdev->dev, " del relay <relay_seid>\n");
- dev_info(&pf->pdev->dev, " add macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n");
- dev_info(&pf->pdev->dev, " del macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n");
dev_info(&pf->pdev->dev, " add pvid <vsi_seid> <vid>\n");
dev_info(&pf->pdev->dev, " del pvid <vsi_seid>\n");
dev_info(&pf->pdev->dev, " dump switch\n");
@@ -1644,7 +1544,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, " dump desc aq\n");
dev_info(&pf->pdev->dev, " dump reset stats\n");
dev_info(&pf->pdev->dev, " dump debug fwdata <cluster_id> <table_id> <index>\n");
- dev_info(&pf->pdev->dev, " msg_enable [level]\n");
dev_info(&pf->pdev->dev, " read <reg>\n");
dev_info(&pf->pdev->dev, " write <reg> <value>\n");
dev_info(&pf->pdev->dev, " clear_stats vsi [seid]\n");
diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h
index dd4457d29e98..8e46098bad57 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_devids.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h
@@ -39,6 +39,8 @@
#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_25G_B 0x158A
+#define I40E_DEV_ID_25G_SFP28 0x158B
#define I40E_DEV_ID_KX_X722 0x37CE
#define I40E_DEV_ID_QSFP_X722 0x37CF
#define I40E_DEV_ID_SFP_X722 0x37D0
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 92bc8846f1ba..cc1465aac2ef 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -104,7 +104,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
* The PF_STATs are appended to the netdev stats only when ethtool -S
* is queried on the base PF netdev, not on the VMDq or FCoE netdev.
*/
-static struct i40e_stats i40e_gstrings_stats[] = {
+static const struct i40e_stats i40e_gstrings_stats[] = {
I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),
I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),
I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast),
@@ -216,7 +216,6 @@ enum i40e_ethtool_test_id {
I40E_ETH_TEST_REG = 0,
I40E_ETH_TEST_EEPROM,
I40E_ETH_TEST_INTR,
- I40E_ETH_TEST_LOOPBACK,
I40E_ETH_TEST_LINK,
};
@@ -224,32 +223,27 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)",
"Eeprom test (offline)",
"Interrupt test (offline)",
- "Loopback test (offline)",
"Link test (on/offline)"
};
#define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN)
-static const char i40e_priv_flags_strings_gl[][ETH_GSTRING_LEN] = {
+static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
"MFP",
"LinkPolling",
"flow-director-atr",
"veb-stats",
"hw-atr-eviction",
- "vf-true-promisc-support",
};
-#define I40E_PRIV_FLAGS_GL_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings_gl)
+#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
-static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
- "NPAR",
- "LinkPolling",
- "flow-director-atr",
- "veb-stats",
- "hw-atr-eviction",
+/* Private flags with a global effect, restricted to PF 0 */
+static const char i40e_gl_priv_flags_strings[][ETH_GSTRING_LEN] = {
+ "vf-true-promisc-support",
};
-#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
+#define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_priv_flags_strings)
/**
* i40e_partition_setting_complaint - generic complaint for MFP restriction
@@ -271,8 +265,9 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf)
static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
u32 *advertising)
{
- enum i40e_aq_capabilities_phy_type phy_types = pf->hw.phy.phy_types;
struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info;
+ u64 phy_types = pf->hw.phy.phy_types;
+
*supported = 0x0;
*advertising = 0x0;
@@ -351,11 +346,13 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
*advertising |= ADVERTISED_20000baseKR2_Full;
}
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
- *supported |= SUPPORTED_10000baseKR_Full |
- SUPPORTED_Autoneg;
+ if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+ *supported |= SUPPORTED_10000baseKR_Full |
+ SUPPORTED_Autoneg;
*advertising |= ADVERTISED_Autoneg;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
- *advertising |= ADVERTISED_10000baseKR_Full;
+ if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+ *advertising |= ADVERTISED_10000baseKR_Full;
}
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
*supported |= SUPPORTED_10000baseKX4_Full |
@@ -365,11 +362,20 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
*advertising |= ADVERTISED_10000baseKX4_Full;
}
if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
- *supported |= SUPPORTED_1000baseKX_Full |
- SUPPORTED_Autoneg;
+ if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+ *supported |= SUPPORTED_1000baseKX_Full |
+ SUPPORTED_Autoneg;
*advertising |= ADVERTISED_Autoneg;
if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
- *advertising |= ADVERTISED_1000baseKX_Full;
+ if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+ *advertising |= ADVERTISED_1000baseKX_Full;
+ }
+ if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) {
+ *supported |= SUPPORTED_Autoneg;
+ *advertising |= ADVERTISED_Autoneg;
}
}
@@ -493,6 +499,14 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
ADVERTISED_1000baseKX_Full |
ADVERTISED_Autoneg;
break;
+ case I40E_PHY_TYPE_25GBASE_KR:
+ case I40E_PHY_TYPE_25GBASE_CR:
+ case I40E_PHY_TYPE_25GBASE_SR:
+ case I40E_PHY_TYPE_25GBASE_LR:
+ ecmd->supported = SUPPORTED_Autoneg;
+ ecmd->advertising = ADVERTISED_Autoneg;
+ /* TODO: add speeds when ethtool is ready to support*/
+ break;
default:
/* if we got here and link is up something bad is afoot */
netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
@@ -514,6 +528,14 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
case I40E_LINK_SPEED_40GB:
ethtool_cmd_speed_set(ecmd, SPEED_40000);
break;
+ case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+ ethtool_cmd_speed_set(ecmd, SPEED_25000);
+#else
+ netdev_info(netdev,
+ "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+ break;
case I40E_LINK_SPEED_20GB:
ethtool_cmd_speed_set(ecmd, SPEED_20000);
break;
@@ -978,6 +1000,10 @@ static u32 i40e_get_msglevel(struct net_device *netdev)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
+ u32 debug_mask = pf->hw.debug_mask;
+
+ if (debug_mask)
+ netdev_info(netdev, "i40e debug_mask: 0x%08X\n", debug_mask);
return pf->msg_enable;
}
@@ -989,7 +1015,8 @@ static void i40e_set_msglevel(struct net_device *netdev, u32 data)
if (I40E_DEBUG_USER & data)
pf->hw.debug_mask = data;
- pf->msg_enable = data;
+ else
+ pf->msg_enable = data;
}
static int i40e_get_regs_len(struct net_device *netdev)
@@ -1191,10 +1218,9 @@ static void i40e_get_drvinfo(struct net_device *netdev,
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;
if (pf->hw.pf_id == 0)
- drvinfo->n_priv_flags = I40E_PRIV_FLAGS_GL_STR_LEN;
- else
- drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
+ drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
}
static void i40e_get_ringparam(struct net_device *netdev,
@@ -1219,6 +1245,7 @@ static int i40e_set_ringparam(struct net_device *netdev,
{
struct i40e_ring *tx_rings = NULL, *rx_rings = NULL;
struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_hw *hw = &np->vsi->back->hw;
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
u32 new_rx_count, new_tx_count;
@@ -1311,10 +1338,6 @@ static int i40e_set_ringparam(struct net_device *netdev,
}
for (i = 0; i < vsi->num_queue_pairs; i++) {
- /* this is to allow wr32 to have something to write to
- * during early allocation of Rx buffers
- */
- u32 __iomem faketail = 0;
struct i40e_ring *ring;
u16 unused;
@@ -1326,7 +1349,10 @@ static int i40e_set_ringparam(struct net_device *netdev,
*/
rx_rings[i].desc = NULL;
rx_rings[i].rx_bi = NULL;
- rx_rings[i].tail = (u8 __iomem *)&faketail;
+ /* this is to allow wr32 to have something to write to
+ * during early allocation of Rx buffers
+ */
+ rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;
err = i40e_setup_rx_descriptors(&rx_rings[i]);
if (err)
goto rx_unwind;
@@ -1422,10 +1448,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)
return I40E_VSI_STATS_LEN(netdev);
}
case ETH_SS_PRIV_FLAGS:
- if (pf->hw.pf_id == 0)
- return I40E_PRIV_FLAGS_GL_STR_LEN;
- else
- return I40E_PRIV_FLAGS_STR_LEN;
+ return I40E_PRIV_FLAGS_STR_LEN +
+ (pf->hw.pf_id == 0 ? I40E_GL_PRIV_FLAGS_STR_LEN : 0);
default:
return -EOPNOTSUPP;
}
@@ -1536,10 +1560,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
switch (stringset) {
case ETH_SS_TEST:
- for (i = 0; i < I40E_TEST_LEN; i++) {
- memcpy(data, i40e_gstrings_test[i], ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ memcpy(data, i40e_gstrings_test,
+ I40E_TEST_LEN * ETH_GSTRING_LEN);
break;
case ETH_SS_STATS:
for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) {
@@ -1623,19 +1645,12 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */
break;
case ETH_SS_PRIV_FLAGS:
- if (pf->hw.pf_id == 0) {
- for (i = 0; i < I40E_PRIV_FLAGS_GL_STR_LEN; i++) {
- memcpy(data, i40e_priv_flags_strings_gl[i],
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
- } else {
- for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
- memcpy(data, i40e_priv_flags_strings[i],
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
- }
+ memcpy(data, i40e_priv_flags_strings,
+ I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
+ data += I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN;
+ if (pf->hw.pf_id == 0)
+ memcpy(data, i40e_gl_priv_flags_strings,
+ I40E_GL_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
break;
default:
break;
@@ -1666,8 +1681,19 @@ static int i40e_get_ts_info(struct net_device *dev,
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
- BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);
+
+ if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE)
+ info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+ BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
return 0;
}
@@ -1739,17 +1765,6 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data)
return *data;
}
-static int i40e_loopback_test(struct net_device *netdev, u64 *data)
-{
- struct i40e_netdev_priv *np = netdev_priv(netdev);
- struct i40e_pf *pf = np->vsi->back;
-
- netif_info(pf, hw, netdev, "loopback test not implemented\n");
- *data = 0;
-
- return *data;
-}
-
static inline bool i40e_active_vfs(struct i40e_pf *pf)
{
struct i40e_vf *vfs = pf->vf;
@@ -1763,17 +1778,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf)
static inline bool i40e_active_vmdqs(struct i40e_pf *pf)
{
- struct i40e_vsi **vsi = pf->vsi;
- int i;
-
- for (i = 0; i < pf->num_alloc_vsi; i++) {
- if (!vsi[i])
- continue;
- if (vsi[i]->type == I40E_VSI_VMDQ2)
- return true;
- }
-
- return false;
+ return !!i40e_find_vsi_by_type(pf, I40E_VSI_VMDQ2);
}
static void i40e_diag_test(struct net_device *netdev,
@@ -1795,7 +1800,6 @@ static void i40e_diag_test(struct net_device *netdev,
data[I40E_ETH_TEST_REG] = 1;
data[I40E_ETH_TEST_EEPROM] = 1;
data[I40E_ETH_TEST_INTR] = 1;
- data[I40E_ETH_TEST_LOOPBACK] = 1;
data[I40E_ETH_TEST_LINK] = 1;
eth_test->flags |= ETH_TEST_FL_FAILED;
clear_bit(__I40E_TESTING, &pf->state);
@@ -1823,9 +1827,6 @@ static void i40e_diag_test(struct net_device *netdev,
if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR]))
eth_test->flags |= ETH_TEST_FL_FAILED;
- if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK]))
- eth_test->flags |= ETH_TEST_FL_FAILED;
-
/* run reg test last, a reset is required after it */
if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG]))
eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -1846,7 +1847,6 @@ static void i40e_diag_test(struct net_device *netdev,
data[I40E_ETH_TEST_REG] = 0;
data[I40E_ETH_TEST_EEPROM] = 0;
data[I40E_ETH_TEST_INTR] = 0;
- data[I40E_ETH_TEST_LOOPBACK] = 0;
}
skip_ol_tests:
@@ -1925,7 +1925,7 @@ static int i40e_set_phys_id(struct net_device *netdev,
switch (state) {
case ETHTOOL_ID_ACTIVE:
- if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) {
+ if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
pf->led_status = i40e_led_get(hw);
} else {
i40e_aq_set_phy_debug(hw, I40E_PHY_DEBUG_ALL, NULL);
@@ -1935,20 +1935,20 @@ static int i40e_set_phys_id(struct net_device *netdev,
}
return blink_freq;
case ETHTOOL_ID_ON:
- if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY))
+ if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
i40e_led_set(hw, 0xf, false);
else
ret = i40e_led_set_phy(hw, true, pf->led_status, 0);
break;
case ETHTOOL_ID_OFF:
- if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY))
+ if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
i40e_led_set(hw, 0x0, false);
else
ret = i40e_led_set_phy(hw, false, pf->led_status, 0);
break;
case ETHTOOL_ID_INACTIVE:
- if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) {
- i40e_led_set(hw, false, pf->led_status);
+ if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
+ i40e_led_set(hw, pf->led_status, false);
} else {
ret = i40e_led_set_phy(hw, false, pf->led_status,
(pf->phy_led_val |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
index 58e6c1570335..b077ef8b00fa 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
@@ -1522,12 +1522,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);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_add_filter(vsi, hw->mac.san_addr, 0);
+ i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0);
+ i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0);
+ i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
/* use san mac */
ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 31c97e3937a4..ad4cf639430e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -41,7 +41,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 25
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@@ -86,6 +86,8 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28), 0},
/* required last entry */
{0, }
};
@@ -93,8 +95,8 @@ MODULE_DEVICE_TABLE(pci, i40e_pci_tbl);
#define I40E_MAX_VF_COUNT 128
static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)");
MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver");
@@ -286,8 +288,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
void i40e_service_event_schedule(struct i40e_pf *pf)
{
if (!test_bit(__I40E_DOWN, &pf->state) &&
- !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) &&
- !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+ !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
queue_work(i40e_wq, &pf->service_task);
}
@@ -1145,25 +1146,22 @@ void i40e_update_stats(struct i40e_vsi *vsi)
* @vsi: the VSI to be searched
* @macaddr: the MAC address
* @vlan: the vlan
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @is_netdev: make sure its a netdev filter, else doesn't matter
*
* Returns ptr to the filter object or NULL
**/
static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
- u8 *macaddr, s16 vlan,
- bool is_vf, bool is_netdev)
+ const u8 *macaddr, s16 vlan)
{
struct i40e_mac_filter *f;
+ u64 key;
if (!vsi || !macaddr)
return NULL;
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
+ key = i40e_addr_to_hkey(macaddr);
+ hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
if ((ether_addr_equal(macaddr, f->macaddr)) &&
- (vlan == f->vlan) &&
- (!is_vf || f->is_vf) &&
- (!is_netdev || f->is_netdev))
+ (vlan == f->vlan))
return f;
}
return NULL;
@@ -1173,24 +1171,21 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
* i40e_find_mac - Find a mac addr in the macvlan filters list
* @vsi: the VSI to be searched
* @macaddr: the MAC address we are searching for
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @is_netdev: make sure its a netdev filter, else doesn't matter
*
* Returns the first filter with the provided MAC address or NULL if
* MAC address was not found
**/
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev)
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)
{
struct i40e_mac_filter *f;
+ u64 key;
if (!vsi || !macaddr)
return NULL;
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if ((ether_addr_equal(macaddr, f->macaddr)) &&
- (!is_vf || f->is_vf) &&
- (!is_netdev || f->is_netdev))
+ key = i40e_addr_to_hkey(macaddr);
+ hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
+ if ((ether_addr_equal(macaddr, f->macaddr)))
return f;
}
return NULL;
@@ -1204,86 +1199,132 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
**/
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
{
- struct i40e_mac_filter *f;
+ /* If we have a PVID, always operate in VLAN mode */
+ if (vsi->info.pvid)
+ return true;
- /* Only -1 for all the filters denotes not in vlan mode
- * so we have to go through all the list in order to make sure
+ /* We need to operate in VLAN mode whenever we have any filters with
+ * a VLAN other than I40E_VLAN_ALL. We could check the table each
+ * time, incurring search cost repeatedly. However, we can notice two
+ * things:
+ *
+ * 1) the only place where we can gain a VLAN filter is in
+ * i40e_add_filter.
+ *
+ * 2) the only place where filters are actually removed is in
+ * i40e_sync_filters_subtask.
+ *
+ * Thus, we can simply use a boolean value, has_vlan_filters which we
+ * will set to true when we add a VLAN filter in i40e_add_filter. Then
+ * we have to perform the full search after deleting filters in
+ * i40e_sync_filters_subtask, but we already have to search
+ * filters here and can perform the check at the same time. This
+ * results in avoiding embedding a loop for VLAN mode inside another
+ * loop over all the filters, and should maintain correctness as noted
+ * above.
*/
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (f->vlan >= 0 || vsi->info.pvid)
- return true;
- }
-
- return false;
+ return vsi->has_vlan_filter;
}
/**
- * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans
- * @vsi: the VSI to be searched
- * @macaddr: the mac address to be filtered
- * @is_vf: true if it is a VF
- * @is_netdev: true if it is a netdev
+ * i40e_correct_mac_vlan_filters - Correct non-VLAN filters if necessary
+ * @vsi: the VSI to configure
+ * @tmp_add_list: list of filters ready to be added
+ * @tmp_del_list: list of filters ready to be deleted
+ * @vlan_filters: the number of active VLAN filters
*
- * Goes through all the macvlan filters and adds a
- * macvlan filter for each unique vlan that already exists
+ * Update VLAN=0 and VLAN=-1 (I40E_VLAN_ANY) filters properly so that they
+ * behave as expected. If we have any active VLAN filters remaining or about
+ * to be added then we need to update non-VLAN filters to be marked as VLAN=0
+ * so that they only match against untagged traffic. If we no longer have any
+ * active VLAN filters, we need to make all non-VLAN filters marked as VLAN=-1
+ * so that they match against both tagged and untagged traffic. In this way,
+ * we ensure that we correctly receive the desired traffic. This ensures that
+ * when we have an active VLAN we will receive only untagged traffic and
+ * traffic matching active VLANs. If we have no active VLANs then we will
+ * operate in non-VLAN mode and receive all traffic, tagged or untagged.
*
- * Returns first filter found on success, else NULL
- **/
-struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev)
+ * Finally, in a similar fashion, this function also corrects filters when
+ * there is an active PVID assigned to this VSI.
+ *
+ * In case of memory allocation failure return -ENOMEM. Otherwise, return 0.
+ *
+ * This function is only expected to be called from within
+ * i40e_sync_vsi_filters.
+ *
+ * NOTE: This function expects to be called while under the
+ * mac_filter_hash_lock
+ */
+static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
+ struct hlist_head *tmp_add_list,
+ struct hlist_head *tmp_del_list,
+ int vlan_filters)
{
- struct i40e_mac_filter *f;
+ struct i40e_mac_filter *f, *add_head;
+ struct hlist_node *h;
+ int bkt, new_vlan;
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (vsi->info.pvid)
- f->vlan = le16_to_cpu(vsi->info.pvid);
- if (!i40e_find_filter(vsi, macaddr, f->vlan,
- is_vf, is_netdev)) {
- if (!i40e_add_filter(vsi, macaddr, f->vlan,
- is_vf, is_netdev))
- return NULL;
- }
- }
+ /* To determine if a particular filter needs to be replaced we
+ * have the three following conditions:
+ *
+ * a) if we have a PVID assigned, then all filters which are
+ * not marked as VLAN=PVID must be replaced with filters that
+ * are.
+ * b) otherwise, if we have any active VLANS, all filters
+ * which are marked as VLAN=-1 must be replaced with
+ * filters marked as VLAN=0
+ * c) finally, if we do not have any active VLANS, all filters
+ * which are marked as VLAN=0 must be replaced with filters
+ * marked as VLAN=-1
+ */
- return list_first_entry_or_null(&vsi->mac_filter_list,
- struct i40e_mac_filter, list);
-}
+ /* Update the filters about to be added in place */
+ hlist_for_each_entry(f, tmp_add_list, hlist) {
+ if (vsi->info.pvid && f->vlan != vsi->info.pvid)
+ f->vlan = vsi->info.pvid;
+ else if (vlan_filters && f->vlan == I40E_VLAN_ANY)
+ f->vlan = 0;
+ else if (!vlan_filters && f->vlan == 0)
+ f->vlan = I40E_VLAN_ANY;
+ }
+
+ /* Update the remaining active filters */
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+ /* Combine the checks for whether a filter needs to be changed
+ * and then determine the new VLAN inside the if block, in
+ * order to avoid duplicating code for adding the new filter
+ * then deleting the old filter.
+ */
+ if ((vsi->info.pvid && f->vlan != vsi->info.pvid) ||
+ (vlan_filters && f->vlan == I40E_VLAN_ANY) ||
+ (!vlan_filters && f->vlan == 0)) {
+ /* Determine the new vlan we will be adding */
+ if (vsi->info.pvid)
+ new_vlan = vsi->info.pvid;
+ else if (vlan_filters)
+ new_vlan = 0;
+ else
+ new_vlan = I40E_VLAN_ANY;
-/**
- * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
- * @vsi: the VSI to be searched
- * @macaddr: the mac address to be removed
- * @is_vf: true if it is a VF
- * @is_netdev: true if it is a netdev
- *
- * Removes a given MAC address from a VSI, regardless of VLAN
- *
- * Returns 0 for success, or error
- **/
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
- bool is_vf, bool is_netdev)
-{
- struct i40e_mac_filter *f = NULL;
- int changed = 0;
+ /* Create the new filter */
+ add_head = i40e_add_filter(vsi, f->macaddr, new_vlan);
+ if (!add_head)
+ return -ENOMEM;
- WARN(!spin_is_locked(&vsi->mac_filter_list_lock),
- "Missing mac_filter_list_lock\n");
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if ((ether_addr_equal(macaddr, f->macaddr)) &&
- (is_vf == f->is_vf) &&
- (is_netdev == f->is_netdev)) {
- f->counter--;
- changed = 1;
- if (f->counter == 0)
- f->state = I40E_FILTER_REMOVE;
+ /* Put the replacement filter into the add list */
+ hash_del(&add_head->hlist);
+ hlist_add_head(&add_head->hlist, tmp_add_list);
+
+ /* Put the original filter into the delete list */
+ f->state = I40E_FILTER_REMOVE;
+ hash_del(&f->hlist);
+ hlist_add_head(&f->hlist, tmp_del_list);
}
}
- if (changed) {
- vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
- vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
- return 0;
- }
- return -ENOENT;
+
+ vsi->has_vlan_filter = !!vlan_filters;
+
+ return 0;
}
/**
@@ -1324,36 +1365,32 @@ static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
* @vsi: the VSI to be searched
* @macaddr: the MAC address
* @vlan: the vlan
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @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
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
* being held.
**/
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
- u8 *macaddr, s16 vlan,
- bool is_vf, bool is_netdev)
+ const u8 *macaddr, s16 vlan)
{
struct i40e_mac_filter *f;
- int changed = false;
+ u64 key;
if (!vsi || !macaddr)
return NULL;
- /* Do not allow broadcast filter to be added since broadcast filter
- * is added as part of add VSI for any newly created VSI except
- * FDIR VSI
- */
- if (is_broadcast_ether_addr(macaddr))
- return NULL;
-
- f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev);
+ f = i40e_find_filter(vsi, macaddr, vlan);
if (!f) {
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
- goto add_filter_out;
+ return NULL;
+
+ /* Update the boolean indicating if we need to function in
+ * VLAN mode.
+ */
+ if (vlan >= 0)
+ vsi->has_vlan_filter = true;
ether_addr_copy(f->macaddr, macaddr);
f->vlan = vlan;
@@ -1365,100 +1402,148 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
f->state = I40E_FILTER_FAILED;
else
f->state = I40E_FILTER_NEW;
- changed = true;
- INIT_LIST_HEAD(&f->list);
- list_add_tail(&f->list, &vsi->mac_filter_list);
- }
+ INIT_HLIST_NODE(&f->hlist);
- /* increment counter and add a new flag if needed */
- if (is_vf) {
- if (!f->is_vf) {
- f->is_vf = true;
- f->counter++;
- }
- } else if (is_netdev) {
- if (!f->is_netdev) {
- f->is_netdev = true;
- f->counter++;
- }
- } else {
- f->counter++;
- }
+ key = i40e_addr_to_hkey(macaddr);
+ hash_add(vsi->mac_filter_hash, &f->hlist, key);
- if (changed) {
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
}
-add_filter_out:
+ /* If we're asked to add a filter that has been marked for removal, it
+ * is safe to simply restore it to active state. __i40e_del_filter
+ * will have simply deleted any filters which were previously marked
+ * NEW or FAILED, so if it is currently marked REMOVE it must have
+ * previously been ACTIVE. Since we haven't yet run the sync filters
+ * task, just restore this filter to the ACTIVE state so that the
+ * sync task leaves it in place
+ */
+ if (f->state == I40E_FILTER_REMOVE)
+ f->state = I40E_FILTER_ACTIVE;
+
return f;
}
/**
- * i40e_del_filter - Remove a mac/vlan filter from the VSI
+ * __i40e_del_filter - Remove a specific filter from the VSI
+ * @vsi: VSI to remove from
+ * @f: the filter to remove from the list
+ *
+ * This function should be called instead of i40e_del_filter only if you know
+ * the exact filter you will remove already, such as via i40e_find_filter or
+ * i40e_find_mac.
+ *
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
+ * being held.
+ * ANOTHER NOTE: This function MUST be called from within the context of
+ * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
+ * instead of list_for_each_entry().
+ **/
+static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
+{
+ if (!f)
+ return;
+
+ if ((f->state == I40E_FILTER_FAILED) ||
+ (f->state == I40E_FILTER_NEW)) {
+ /* this one never got added by the FW. Just remove it,
+ * no need to sync anything.
+ */
+ hash_del(&f->hlist);
+ kfree(f);
+ } else {
+ f->state = I40E_FILTER_REMOVE;
+ vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+ vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+ }
+}
+
+/**
+ * i40e_del_filter - Remove a MAC/VLAN filter from the VSI
* @vsi: the VSI to be searched
* @macaddr: the MAC address
- * @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
+ * @vlan: the VLAN
*
- * NOTE: This function is expected to be called with mac_filter_list_lock
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
* being held.
* ANOTHER NOTE: This function MUST be called from within the context of
* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
* instead of list_for_each_entry().
**/
-void i40e_del_filter(struct i40e_vsi *vsi,
- u8 *macaddr, s16 vlan,
- bool is_vf, bool is_netdev)
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
{
struct i40e_mac_filter *f;
if (!vsi || !macaddr)
return;
- f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev);
- if (!f || f->counter == 0)
- return;
+ f = i40e_find_filter(vsi, macaddr, vlan);
+ __i40e_del_filter(vsi, f);
+}
- if (is_vf) {
- if (f->is_vf) {
- f->is_vf = false;
- f->counter--;
- }
- } else if (is_netdev) {
- if (f->is_netdev) {
- f->is_netdev = false;
- f->counter--;
- }
- } else {
- /* make sure we don't remove a filter in use by VF or netdev */
- int min_f = 0;
+/**
+ * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be filtered
+ *
+ * Goes through all the macvlan filters and adds a macvlan filter for each
+ * unique vlan that already exists. If a PVID has been assigned, instead only
+ * add the macaddr to that VLAN.
+ *
+ * Returns last filter added on success, else NULL
+ **/
+struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
+ const u8 *macaddr)
+{
+ struct i40e_mac_filter *f, *add = NULL;
+ struct hlist_node *h;
+ int bkt;
- min_f += (f->is_vf ? 1 : 0);
- min_f += (f->is_netdev ? 1 : 0);
+ if (vsi->info.pvid)
+ return i40e_add_filter(vsi, macaddr,
+ le16_to_cpu(vsi->info.pvid));
- if (f->counter > min_f)
- f->counter--;
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+ if (f->state == I40E_FILTER_REMOVE)
+ continue;
+ add = i40e_add_filter(vsi, macaddr, f->vlan);
+ if (!add)
+ return NULL;
}
- /* counter == 0 tells sync_filters_subtask to
- * remove the filter from the firmware's list
- */
- if (f->counter == 0) {
- if ((f->state == I40E_FILTER_FAILED) ||
- (f->state == I40E_FILTER_NEW)) {
- /* this one never got added by the FW. Just remove it,
- * no need to sync anything.
- */
- list_del(&f->list);
- kfree(f);
- } else {
- f->state = I40E_FILTER_REMOVE;
- vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
- vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+ return add;
+}
+
+/**
+ * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be removed
+ *
+ * Removes a given MAC address from a VSI, regardless of VLAN
+ *
+ * Returns 0 for success, or error
+ **/
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr)
+{
+ struct i40e_mac_filter *f;
+ struct hlist_node *h;
+ bool found = false;
+ int bkt;
+
+ WARN(!spin_is_locked(&vsi->mac_filter_hash_lock),
+ "Missing mac_filter_hash_lock\n");
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+ if (ether_addr_equal(macaddr, f->macaddr)) {
+ __i40e_del_filter(vsi, f);
+ found = true;
}
}
+
+ if (found)
+ return 0;
+ else
+ return -ENOENT;
}
/**
@@ -1499,10 +1584,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
else
netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
- spin_lock_bh(&vsi->mac_filter_list_lock);
- i40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true);
- i40e_put_mac_in_vlan(vsi, addr->sa_data, false, true);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_del_mac_all_vlan(vsi, netdev->dev_addr);
+ i40e_put_mac_in_vlan(vsi, addr->sa_data);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
ether_addr_copy(netdev->dev_addr, addr->sa_data);
if (vsi->type == I40E_VSI_MAIN) {
i40e_status ret;
@@ -1666,6 +1751,52 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
}
/**
+ * i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_sync(struct net_device *netdev, const u8 *addr)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_mac_filter *f;
+
+ if (i40e_is_vsi_in_vlan(vsi))
+ f = i40e_put_mac_in_vlan(vsi, addr);
+ else
+ f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY);
+
+ if (f)
+ return 0;
+ else
+ return -ENOMEM;
+}
+
+/**
+ * i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+
+ if (i40e_is_vsi_in_vlan(vsi))
+ i40e_del_mac_all_vlan(vsi, addr);
+ else
+ i40e_del_filter(vsi, addr, I40E_VLAN_ANY);
+
+ return 0;
+}
+
+/**
* i40e_set_rx_mode - NDO callback to set the netdev filters
* @netdev: network interface device structure
**/
@@ -1676,62 +1807,14 @@ static void i40e_set_rx_mode(struct net_device *netdev)
#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
- struct i40e_mac_filter *f, *ftmp;
struct i40e_vsi *vsi = np->vsi;
- struct netdev_hw_addr *uca;
- 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)) {
- if (i40e_is_vsi_in_vlan(vsi))
- i40e_put_mac_in_vlan(vsi, uca->addr,
- false, true);
- else
- i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY,
- false, true);
- }
- }
- netdev_for_each_mc_addr(mca, netdev) {
- if (!i40e_find_mac(vsi, mca->addr, false, true)) {
- if (i40e_is_vsi_in_vlan(vsi))
- i40e_put_mac_in_vlan(vsi, mca->addr,
- false, true);
- else
- i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY,
- false, true);
- }
- }
-
- /* remove filter if not in netdev list */
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-
- if (!f->is_netdev)
- continue;
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
- netdev_for_each_mc_addr(mca, netdev)
- if (ether_addr_equal(mca->addr, f->macaddr))
- goto bottom_of_search_loop;
+ __dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
+ __dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
- 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);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
/* check for other flag changes */
if (vsi->current_netdev_flags != vsi->netdev->flags) {
@@ -1746,21 +1829,26 @@ bottom_of_search_loop:
}
/**
- * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
- * @vsi: pointer to vsi struct
+ * i40e_undo_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.
+ * MAC filter entries from list were slated to be sent to firmware, either for
+ * addition or deletion.
**/
-static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
- struct list_head *from)
+static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
+ struct hlist_head *from)
{
- struct i40e_mac_filter *f, *ftmp;
+ struct i40e_mac_filter *f;
+ struct hlist_node *h;
+
+ hlist_for_each_entry_safe(f, h, from, hlist) {
+ u64 key = i40e_addr_to_hkey(f->macaddr);
- list_for_each_entry_safe(f, ftmp, from, list) {
/* Move the element back into MAC filter list*/
- list_move_tail(&f->list, &vsi->mac_filter_list);
+ hlist_del(&f->hlist);
+ hash_add(vsi->mac_filter_hash, &f->hlist, key);
}
}
@@ -1770,7 +1858,6 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
* @count: Number of filters added
* @add_list: return data from fw
* @head: pointer to first filter in current batch
- * @aq_err: status from fw
*
* MAC filter entries from list were slated to be added to device. Returns
* number of successful filters. Note that 0 does NOT mean success!
@@ -1778,45 +1865,146 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
static int
i40e_update_filter_state(int count,
struct i40e_aqc_add_macvlan_element_data *add_list,
- struct i40e_mac_filter *add_head, int aq_err)
+ struct i40e_mac_filter *add_head)
{
int retval = 0;
int i;
-
- if (!aq_err) {
- retval = count;
- /* Everything's good, mark all filters active. */
- for (i = 0; i < count ; i++) {
- add_head->state = I40E_FILTER_ACTIVE;
- add_head = list_next_entry(add_head, list);
- }
- } else if (aq_err == I40E_AQ_RC_ENOSPC) {
- /* Device ran out of filter space. Check the return value
- * for each filter to see which ones are active.
+ for (i = 0; i < count; i++) {
+ /* Always check status of each filter. We don't need to check
+ * the firmware return status because we pre-set the filter
+ * status to I40E_AQC_MM_ERR_NO_RES when sending the filter
+ * request to the adminq. Thus, if it no longer matches then
+ * we know the filter is active.
*/
- for (i = 0; i < count ; i++) {
- if (add_list[i].match_method ==
- I40E_AQC_MM_ERR_NO_RES) {
- add_head->state = I40E_FILTER_FAILED;
- } else {
- add_head->state = I40E_FILTER_ACTIVE;
- retval++;
- }
- add_head = list_next_entry(add_head, list);
- }
- } else {
- /* Some other horrible thing happened, fail all filters */
- retval = 0;
- for (i = 0; i < count ; i++) {
+ if (add_list[i].match_method == I40E_AQC_MM_ERR_NO_RES) {
add_head->state = I40E_FILTER_FAILED;
- add_head = list_next_entry(add_head, list);
+ } else {
+ add_head->state = I40E_FILTER_ACTIVE;
+ retval++;
}
+
+ add_head = hlist_entry(add_head->hlist.next,
+ typeof(struct i40e_mac_filter),
+ hlist);
}
+
return retval;
}
/**
+ * i40e_aqc_del_filters - Request firmware to delete a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @num_del: the number of filters to delete
+ * @retval: Set to -EIO on failure to delete
+ *
+ * Send a request to firmware via AdminQ to delete a set of filters. Uses
+ * *retval instead of a return value so that success does not force ret_val to
+ * be set to 0. This ensures that a sequence of calls to this function
+ * preserve the previous value of *retval on successful delete.
+ */
+static
+void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name,
+ struct i40e_aqc_remove_macvlan_element_data *list,
+ int num_del, int *retval)
+{
+ struct i40e_hw *hw = &vsi->back->hw;
+ i40e_status aq_ret;
+ int aq_err;
+
+ aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, list, num_del, NULL);
+ aq_err = hw->aq.asq_last_status;
+
+ /* Explicitly ignore and do not report when firmware returns ENOENT */
+ if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
+ *retval = -EIO;
+ dev_info(&vsi->back->pdev->dev,
+ "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
+ vsi_name, i40e_stat_str(hw, aq_ret),
+ i40e_aq_str(hw, aq_err));
+ }
+}
+
+/**
+ * i40e_aqc_add_filters - Request firmware to add a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @add_head: Position in the add hlist
+ * @num_add: the number of filters to add
+ * @promisc_change: set to true on exit if promiscuous mode was forced on
+ *
+ * Send a request to firmware via AdminQ to add a chunk of filters. Will set
+ * promisc_changed to true if the firmware has run out of space for more
+ * filters.
+ */
+static
+void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
+ struct i40e_aqc_add_macvlan_element_data *list,
+ struct i40e_mac_filter *add_head,
+ int num_add, bool *promisc_changed)
+{
+ struct i40e_hw *hw = &vsi->back->hw;
+ int aq_err, fcnt;
+
+ i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
+ aq_err = hw->aq.asq_last_status;
+ fcnt = i40e_update_filter_state(num_add, list, add_head);
+
+ if (fcnt != num_add) {
+ *promisc_changed = true;
+ set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ dev_warn(&vsi->back->pdev->dev,
+ "Error %s adding RX filters on %s, promiscuous mode forced on\n",
+ i40e_aq_str(hw, aq_err),
+ vsi_name);
+ }
+}
+
+/**
+ * i40e_aqc_broadcast_filter - Set promiscuous broadcast flags
+ * @vsi: pointer to the VSI
+ * @f: filter data
+ *
+ * This function sets or clears the promiscuous broadcast flags for VLAN
+ * filters in order to properly receive broadcast frames. Assumes that only
+ * broadcast filters are passed.
+ **/
+static
+void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
+ struct i40e_mac_filter *f)
+{
+ bool enable = f->state == I40E_FILTER_NEW;
+ struct i40e_hw *hw = &vsi->back->hw;
+ i40e_status aq_ret;
+
+ if (f->vlan == I40E_VLAN_ANY) {
+ aq_ret = i40e_aq_set_vsi_broadcast(hw,
+ vsi->seid,
+ enable,
+ NULL);
+ } else {
+ aq_ret = i40e_aq_set_vsi_bc_promisc_on_vlan(hw,
+ vsi->seid,
+ enable,
+ f->vlan,
+ NULL);
+ }
+
+ if (aq_ret) {
+ dev_warn(&vsi->back->pdev->dev,
+ "Error %s setting broadcast promiscuous mode on %s\n",
+ i40e_aq_str(hw, hw->aq.asq_last_status),
+ vsi_name);
+ f->state = I40E_FILTER_FAILED;
+ } else if (enable) {
+ f->state = I40E_FILTER_ACTIVE;
+ }
+}
+
+/**
* i40e_sync_vsi_filters - Update the VSI filter list to the HW
* @vsi: ptr to the VSI
*
@@ -1826,22 +2014,24 @@ i40e_update_filter_state(int count,
**/
int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
{
- struct i40e_mac_filter *f, *ftmp, *add_head = NULL;
- struct list_head tmp_add_list, tmp_del_list;
+ struct hlist_head tmp_add_list, tmp_del_list;
+ struct i40e_mac_filter *f, *add_head = NULL;
struct i40e_hw *hw = &vsi->back->hw;
+ unsigned int failed_filters = 0;
+ unsigned int vlan_filters = 0;
bool promisc_changed = false;
char vsi_name[16] = "PF";
int filter_list_len = 0;
- u32 changed_flags = 0;
i40e_status aq_ret = 0;
- int retval = 0;
+ u32 changed_flags = 0;
+ struct hlist_node *h;
struct i40e_pf *pf;
int num_add = 0;
int num_del = 0;
- int aq_err = 0;
+ int retval = 0;
u16 cmd_flags;
int list_size;
- int fcnt;
+ int bkt;
/* empty array typed pointers, kcalloc later */
struct i40e_aqc_add_macvlan_element_data *add_list;
@@ -1856,8 +2046,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
vsi->current_netdev_flags = vsi->netdev->flags;
}
- INIT_LIST_HEAD(&tmp_add_list);
- INIT_LIST_HEAD(&tmp_del_list);
+ INIT_HLIST_HEAD(&tmp_add_list);
+ INIT_HLIST_HEAD(&tmp_del_list);
if (vsi->type == I40E_VSI_SRIOV)
snprintf(vsi_name, sizeof(vsi_name) - 1, "VF %d", vsi->vf_id);
@@ -1867,43 +2057,64 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {
vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;
- spin_lock_bh(&vsi->mac_filter_list_lock);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
/* Create a list of filters to delete. */
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
if (f->state == I40E_FILTER_REMOVE) {
- WARN_ON(f->counter != 0);
/* Move the element into temporary del_list */
- list_move_tail(&f->list, &tmp_del_list);
- vsi->active_filters--;
+ hash_del(&f->hlist);
+ hlist_add_head(&f->hlist, &tmp_del_list);
+
+ /* Avoid counting removed filters */
+ continue;
}
if (f->state == I40E_FILTER_NEW) {
- WARN_ON(f->counter == 0);
- /* Move the element into temporary add_list */
- list_move_tail(&f->list, &tmp_add_list);
+ hash_del(&f->hlist);
+ hlist_add_head(&f->hlist, &tmp_add_list);
}
+
+ /* Count the number of active (current and new) VLAN
+ * filters we have now. Does not count filters which
+ * are marked for deletion.
+ */
+ if (f->vlan > 0)
+ vlan_filters++;
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+
+ retval = i40e_correct_mac_vlan_filters(vsi,
+ &tmp_add_list,
+ &tmp_del_list,
+ vlan_filters);
+ if (retval)
+ goto err_no_memory_locked;
+
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
}
/* Now process 'del_list' outside the lock */
- if (!list_empty(&tmp_del_list)) {
+ if (!hlist_empty(&tmp_del_list)) {
filter_list_len = hw->aq.asq_buf_size /
sizeof(struct i40e_aqc_remove_macvlan_element_data);
list_size = filter_list_len *
sizeof(struct i40e_aqc_remove_macvlan_element_data);
del_list = kzalloc(list_size, GFP_ATOMIC);
- if (!del_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);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
- retval = -ENOMEM;
- goto out;
- }
+ if (!del_list)
+ goto err_no_memory;
- list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) {
+ hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) {
cmd_flags = 0;
+ /* handle broadcast filters by updating the broadcast
+ * promiscuous flag instead of deleting a MAC filter.
+ */
+ if (is_broadcast_ether_addr(f->macaddr)) {
+ i40e_aqc_broadcast_filter(vsi, vsi_name, f);
+
+ hlist_del(&f->hlist);
+ kfree(f);
+ continue;
+ }
+
/* add to delete list */
ether_addr_copy(del_list[num_del].mac_addr, f->macaddr);
if (f->vlan == I40E_VLAN_ANY) {
@@ -1920,73 +2131,57 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
/* flush a full buffer */
if (num_del == filter_list_len) {
- aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid,
- del_list,
- num_del, NULL);
- aq_err = hw->aq.asq_last_status;
- num_del = 0;
+ i40e_aqc_del_filters(vsi, vsi_name, del_list,
+ num_del, &retval);
memset(del_list, 0, list_size);
-
- /* Explicitly ignore and do not report when
- * firmware returns ENOENT.
- */
- if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
- retval = -EIO;
- dev_info(&pf->pdev->dev,
- "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
- vsi_name,
- i40e_stat_str(hw, aq_ret),
- i40e_aq_str(hw, aq_err));
- }
+ num_del = 0;
}
/* Release memory for MAC filter entries which were
* synced up with HW.
*/
- list_del(&f->list);
+ hlist_del(&f->hlist);
kfree(f);
}
if (num_del) {
- aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list,
- num_del, NULL);
- aq_err = hw->aq.asq_last_status;
- num_del = 0;
-
- /* Explicitly ignore and do not report when firmware
- * returns ENOENT.
- */
- if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
- retval = -EIO;
- dev_info(&pf->pdev->dev,
- "ignoring delete macvlan error on %s, err %s aq_err %s\n",
- vsi_name,
- i40e_stat_str(hw, aq_ret),
- i40e_aq_str(hw, aq_err));
- }
+ i40e_aqc_del_filters(vsi, vsi_name, del_list,
+ num_del, &retval);
}
kfree(del_list);
del_list = NULL;
}
- if (!list_empty(&tmp_add_list)) {
+ if (!hlist_empty(&tmp_add_list)) {
/* Do all the adds now. */
filter_list_len = hw->aq.asq_buf_size /
sizeof(struct i40e_aqc_add_macvlan_element_data);
list_size = filter_list_len *
sizeof(struct i40e_aqc_add_macvlan_element_data);
add_list = kzalloc(list_size, GFP_ATOMIC);
- if (!add_list) {
- retval = -ENOMEM;
- goto out;
- }
+ if (!add_list)
+ goto err_no_memory;
+
num_add = 0;
- list_for_each_entry(f, &tmp_add_list, list) {
+ hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
&vsi->state)) {
f->state = I40E_FILTER_FAILED;
continue;
}
+
+ /* handle broadcast filters by updating the broadcast
+ * promiscuous flag instead of adding a MAC filter.
+ */
+ if (is_broadcast_ether_addr(f->macaddr)) {
+ u64 key = i40e_addr_to_hkey(f->macaddr);
+ i40e_aqc_broadcast_filter(vsi, vsi_name, f);
+
+ hlist_del(&f->hlist);
+ hash_add(vsi->mac_filter_hash, &f->hlist, key);
+ continue;
+ }
+
/* add to add array */
if (num_add == 0)
add_head = f;
@@ -2000,88 +2195,70 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
cpu_to_le16((u16)(f->vlan));
}
add_list[num_add].queue_number = 0;
+ /* set invalid match method for later detection */
+ add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;
cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
add_list[num_add].flags = cpu_to_le16(cmd_flags);
num_add++;
/* flush a full buffer */
if (num_add == filter_list_len) {
- aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
- add_list, num_add,
- NULL);
- aq_err = hw->aq.asq_last_status;
- fcnt = i40e_update_filter_state(num_add,
- add_list,
- add_head,
- aq_ret);
- vsi->active_filters += fcnt;
-
- if (fcnt != num_add) {
- promisc_changed = true;
- set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
- &vsi->state);
- vsi->promisc_threshold =
- (vsi->active_filters * 3) / 4;
- dev_warn(&pf->pdev->dev,
- "Error %s adding RX filters on %s, promiscuous mode forced on\n",
- i40e_aq_str(hw, aq_err),
- vsi_name);
- }
+ i40e_aqc_add_filters(vsi, vsi_name, add_list,
+ add_head, num_add,
+ &promisc_changed);
memset(add_list, 0, list_size);
num_add = 0;
}
}
if (num_add) {
- aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
- add_list, num_add, NULL);
- aq_err = hw->aq.asq_last_status;
- fcnt = i40e_update_filter_state(num_add, add_list,
- add_head, aq_ret);
- vsi->active_filters += fcnt;
- if (fcnt != num_add) {
- promisc_changed = true;
- set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
- &vsi->state);
- vsi->promisc_threshold =
- (vsi->active_filters * 3) / 4;
- dev_warn(&pf->pdev->dev,
- "Error %s adding RX filters on %s, promiscuous mode forced on\n",
- i40e_aq_str(hw, aq_err), vsi_name);
- }
+ i40e_aqc_add_filters(vsi, vsi_name, add_list, add_head,
+ num_add, &promisc_changed);
}
/* Now move all of the filters from the temp add list back to
* the VSI's list.
*/
- spin_lock_bh(&vsi->mac_filter_list_lock);
- list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {
- list_move_tail(&f->list, &vsi->mac_filter_list);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
+ u64 key = i40e_addr_to_hkey(f->macaddr);
+
+ hlist_del(&f->hlist);
+ hash_add(vsi->mac_filter_hash, &f->hlist, key);
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
kfree(add_list);
add_list = NULL;
}
- /* Check to see if we can drop out of overflow promiscuous mode. */
+ /* Determine the number of active and failed filters. */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ vsi->active_filters = 0;
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
+ if (f->state == I40E_FILTER_ACTIVE)
+ vsi->active_filters++;
+ else if (f->state == I40E_FILTER_FAILED)
+ failed_filters++;
+ }
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ /* If promiscuous mode has changed, we need to calculate a new
+ * threshold for when we are safe to exit
+ */
+ if (promisc_changed)
+ vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
+
+ /* Check if we are able to exit overflow promiscuous mode. We can
+ * safely exit if we didn't just enter, we no longer have any failed
+ * filters, and we have reduced filters below the threshold value.
+ */
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
+ !promisc_changed && !failed_filters &&
(vsi->active_filters < vsi->promisc_threshold)) {
- int failed_count = 0;
- /* See if we have any failed filters. We can't drop out of
- * promiscuous until these have all been deleted.
- */
- spin_lock_bh(&vsi->mac_filter_list_lock);
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (f->state == I40E_FILTER_FAILED)
- failed_count++;
- }
- spin_unlock_bh(&vsi->mac_filter_list_lock);
- if (!failed_count) {
- dev_info(&pf->pdev->dev,
- "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
- vsi_name);
- clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
- promisc_changed = true;
- vsi->promisc_threshold = 0;
- }
+ dev_info(&pf->pdev->dev,
+ "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
+ vsi_name);
+ clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ promisc_changed = true;
+ vsi->promisc_threshold = 0;
}
/* if the VF is not trusted do not do promisc */
@@ -2201,6 +2378,18 @@ out:
clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
return retval;
+
+err_no_memory:
+ /* Restore elements on the temporary add and delete lists */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+err_no_memory_locked:
+ i40e_undo_filter_entries(vsi, &tmp_del_list);
+ i40e_undo_filter_entries(vsi, &tmp_add_list);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+ clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+ return -ENOMEM;
}
/**
@@ -2239,13 +2428,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
struct i40e_vsi *vsi = np->vsi;
- /* MTU < 68 is an error and causes problems on some kernels */
- if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
- return -EINVAL;
-
netdev_info(netdev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
netdev->mtu = new_mtu;
@@ -2354,88 +2538,54 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)
}
/**
- * i40e_vsi_add_vlan - Add vsi membership for given vlan
+ * i40e_add_vlan_all_mac - Add a MAC/VLAN filter for each existing MAC address
* @vsi: the vsi being configured
* @vid: vlan id to be added (0 = untagged only , -1 = any)
+ *
+ * This is a helper function for adding a new MAC/VLAN filter with the
+ * specified VLAN for each existing MAC address already in the hash table.
+ * This function does *not* perform any accounting to update filters based on
+ * VLAN mode.
+ *
+ * NOTE: this function expects to be called while under the
+ * mac_filter_hash_lock
**/
-int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
+int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
{
- struct i40e_mac_filter *f, *ftmp, *add_f;
- bool is_netdev, is_vf;
-
- 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);
- if (!add_f) {
- 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;
- }
- }
+ struct i40e_mac_filter *f, *add_f;
+ struct hlist_node *h;
+ int bkt;
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
- add_f = i40e_add_filter(vsi, f->macaddr, vid, is_vf, is_netdev);
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+ if (f->state == I40E_FILTER_REMOVE)
+ continue;
+ add_f = i40e_add_filter(vsi, f->macaddr, vid);
if (!add_f) {
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;
}
}
- /* Now if we add a vlan tag, make sure to check if it is the first
- * tag (i.e. a "tag" -1 does exist) and if so replace the -1 "tag"
- * with 0, so we now accept untagged and specified tagged traffic
- * (and not all tags along with untagged)
- */
- if (vid > 0) {
- if (is_netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr,
- I40E_VLAN_ANY,
- is_vf, is_netdev)) {
- i40e_del_filter(vsi, vsi->netdev->dev_addr,
- I40E_VLAN_ANY, is_vf, is_netdev);
- add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0,
- is_vf, is_netdev);
- if (!add_f) {
- 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;
- }
- }
- }
+ return 0;
+}
- /* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */
- if (vid > 0 && !vsi->info.pvid) {
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
- 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;
- }
- }
- }
+/**
+ * i40e_vsi_add_vlan - Add VSI membership for given VLAN
+ * @vsi: the VSI being configured
+ * @vid: VLAN id to be added (0 = untagged only , -1 = any)
+ **/
+int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
+{
+ int err;
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ /* Locked once because all functions invoked below iterates list*/
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ err = i40e_add_vlan_all_mac(vsi, vid);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+ if (err)
+ return err;
/* schedule our worker thread which will take care of
* applying the new filter changes
@@ -2445,82 +2595,45 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
}
/**
- * i40e_vsi_kill_vlan - Remove vsi membership for given vlan
+ * i40e_rm_vlan_all_mac - Remove MAC/VLAN pair for all MAC with the given VLAN
* @vsi: the vsi being configured
* @vid: vlan id to be removed (0 = untagged only , -1 = any)
*
- * Return: 0 on success or negative otherwise
- **/
-int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
+ * This function should be used to remove all VLAN filters which match the
+ * given VID. It does not schedule the service event and does not take the
+ * mac_filter_hash_lock so it may be combined with other operations under
+ * a single invocation of the mac_filter_hash_lock.
+ *
+ * NOTE: this function expects to be called while under the
+ * mac_filter_hash_lock
+ */
+void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
{
- struct net_device *netdev = vsi->netdev;
- struct i40e_mac_filter *f, *ftmp, *add_f;
- bool is_vf, is_netdev;
- int filter_count = 0;
-
- 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);
-
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
- i40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev);
-
- /* go through all the filters for this VSI and if there is only
- * vid == 0 it means there are no other filters, so vid 0 must
- * be replaced with -1. This signifies that we should from now
- * on accept any traffic (with any tag present, or untagged)
- */
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
- if (is_netdev) {
- if (f->vlan &&
- ether_addr_equal(netdev->dev_addr, f->macaddr))
- filter_count++;
- }
-
- if (f->vlan)
- filter_count++;
- }
-
- if (!filter_count && is_netdev) {
- i40e_del_filter(vsi, netdev->dev_addr, 0, is_vf, is_netdev);
- f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
- is_vf, is_netdev);
- if (!f) {
- 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;
- }
- }
+ struct i40e_mac_filter *f;
+ struct hlist_node *h;
+ int bkt;
- if (!filter_count) {
- list_for_each_entry_safe(f, ftmp, &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);
- 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;
- }
- }
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+ if (f->vlan == vid)
+ __i40e_del_filter(vsi, f);
}
+}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+/**
+ * i40e_vsi_kill_vlan - Remove VSI membership for given VLAN
+ * @vsi: the VSI being configured
+ * @vid: VLAN id to be removed (0 = untagged only , -1 = any)
+ **/
+void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
+{
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_rm_vlan_all_mac(vsi, vid);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
/* schedule our worker thread which will take care of
* applying the new filter changes
*/
i40e_service_event_schedule(vsi->back);
- return 0;
}
/**
@@ -2542,7 +2655,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
struct i40e_vsi *vsi = np->vsi;
int ret = 0;
- if (vid > 4095)
+ if (vid >= VLAN_N_VID)
return -EINVAL;
/* If the network stack called us with vid = 0 then
@@ -2554,7 +2667,7 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
if (vid)
ret = i40e_vsi_add_vlan(vsi, vid);
- if (!ret && (vid < VLAN_N_VID))
+ if (!ret)
set_bit(vid, vsi->active_vlans);
return ret;
@@ -3322,6 +3435,33 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data)
}
/**
+ * i40e_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify,
+ const cpumask_t *mask)
+{
+ struct i40e_q_vector *q_vector =
+ container_of(notify, struct i40e_q_vector, affinity_notify);
+
+ q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40e_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40e_irq_affinity_release(struct kref *ref) {}
+
+/**
* i40e_vsi_request_irq_msix - Initialize MSI-X interrupts
* @vsi: the VSI being configured
* @basename: name for the vector
@@ -3336,10 +3476,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
int rx_int_idx = 0;
int tx_int_idx = 0;
int vector, err;
+ int irq_num;
for (vector = 0; vector < q_vectors; vector++) {
struct i40e_q_vector *q_vector = vsi->q_vectors[vector];
+ irq_num = pf->msix_entries[base + vector].vector;
+
if (q_vector->tx.ring && q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", basename, "TxRx", rx_int_idx++);
@@ -3354,7 +3497,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
/* skip this unused q_vector */
continue;
}
- err = request_irq(pf->msix_entries[base + vector].vector,
+ err = request_irq(irq_num,
vsi->irq_handler,
0,
q_vector->name,
@@ -3364,9 +3507,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
"MSIX request_irq failed, error: %d\n", err);
goto free_queue_irqs;
}
+
+ /* register for affinity change notifications */
+ q_vector->affinity_notify.notify = i40e_irq_affinity_notify;
+ q_vector->affinity_notify.release = i40e_irq_affinity_release;
+ irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
/* assign the mask for this irq */
- irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
- &q_vector->affinity_mask);
+ irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
}
vsi->irqs_ready = true;
@@ -3375,10 +3522,10 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
free_queue_irqs:
while (vector) {
vector--;
- irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
- NULL);
- free_irq(pf->msix_entries[base + vector].vector,
- &(vsi->q_vectors[vector]));
+ irq_num = pf->msix_entries[base + vector].vector;
+ irq_set_affinity_notifier(irq_num, NULL);
+ irq_set_affinity_hint(irq_num, NULL);
+ free_irq(irq_num, &vsi->q_vectors[vector]);
}
return err;
}
@@ -3480,7 +3627,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
(ena_mask & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) {
ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
icr0 &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
- dev_info(&pf->pdev->dev, "cleared PE_CRITERR\n");
+ dev_dbg(&pf->pdev->dev, "cleared PE_CRITERR\n");
}
/* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
@@ -3973,30 +4120,36 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
}
/**
- * i40e_vsi_control_rings - Start or stop a VSI's rings
+ * i40e_vsi_start_rings - Start a VSI's rings
* @vsi: the VSI being configured
- * @enable: start or stop the rings
**/
-int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request)
+int i40e_vsi_start_rings(struct i40e_vsi *vsi)
{
int ret = 0;
/* do rx first for enable and last for disable */
- if (request) {
- ret = i40e_vsi_control_rx(vsi, request);
- if (ret)
- return ret;
- ret = i40e_vsi_control_tx(vsi, request);
- } else {
- /* Ignore return value, we need to shutdown whatever we can */
- i40e_vsi_control_tx(vsi, request);
- i40e_vsi_control_rx(vsi, request);
- }
+ ret = i40e_vsi_control_rx(vsi, true);
+ if (ret)
+ return ret;
+ ret = i40e_vsi_control_tx(vsi, true);
return ret;
}
/**
+ * i40e_vsi_stop_rings - Stop a VSI's rings
+ * @vsi: the VSI being configured
+ **/
+void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
+{
+ /* do rx first for enable and last for disable
+ * Ignore return value, we need to shutdown whatever we can
+ */
+ i40e_vsi_control_tx(vsi, false);
+ i40e_vsi_control_rx(vsi, false);
+}
+
+/**
* i40e_vsi_free_irq - Free the irq association with the OS
* @vsi: the VSI being configured
**/
@@ -4017,19 +4170,23 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
vsi->irqs_ready = false;
for (i = 0; i < vsi->num_q_vectors; i++) {
- u16 vector = i + base;
+ int irq_num;
+ u16 vector;
+
+ vector = i + base;
+ irq_num = pf->msix_entries[vector].vector;
/* free only the irqs that were actually requested */
if (!vsi->q_vectors[i] ||
!vsi->q_vectors[i]->num_ringpairs)
continue;
+ /* clear the affinity notifier in the IRQ descriptor */
+ irq_set_affinity_notifier(irq_num, NULL);
/* clear the affinity_mask in the IRQ descriptor */
- irq_set_affinity_hint(pf->msix_entries[vector].vector,
- NULL);
- synchronize_irq(pf->msix_entries[vector].vector);
- free_irq(pf->msix_entries[vector].vector,
- vsi->q_vectors[i]);
+ irq_set_affinity_hint(irq_num, NULL);
+ synchronize_irq(irq_num);
+ free_irq(irq_num, vsi->q_vectors[i]);
/* Tear down the interrupt queue link list
*
@@ -5116,12 +5273,16 @@ out:
*/
void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
{
+ enum i40e_aq_link_speed new_speed;
char *speed = "Unknown";
char *fc = "Unknown";
- if (vsi->current_isup == isup)
+ new_speed = vsi->back->hw.phy.link_info.link_speed;
+
+ if ((vsi->current_isup == isup) && (vsi->current_speed == new_speed))
return;
vsi->current_isup = isup;
+ vsi->current_speed = new_speed;
if (!isup) {
netdev_info(vsi->netdev, "NIC Link is Down\n");
return;
@@ -5143,6 +5304,9 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
case I40E_LINK_SPEED_20GB:
speed = "20 G";
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = "25 G";
+ break;
case I40E_LINK_SPEED_10GB:
speed = "10 G";
break;
@@ -5190,7 +5354,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
i40e_configure_msi_and_legacy(vsi);
/* start rings */
- err = i40e_vsi_control_rings(vsi, true);
+ err = i40e_vsi_start_rings(vsi);
if (err)
return err;
@@ -5287,7 +5451,7 @@ void i40e_down(struct i40e_vsi *vsi)
netif_tx_disable(vsi->netdev);
}
i40e_vsi_disable_irq(vsi);
- i40e_vsi_control_rings(vsi, false);
+ i40e_vsi_stop_rings(vsi);
i40e_napi_disable_all(vsi);
for (i = 0; i < vsi->num_queue_pairs; i++) {
@@ -5833,19 +5997,6 @@ static void i40e_handle_lan_overflow_event(struct i40e_pf *pf,
}
/**
- * i40e_service_event_complete - Finish up the service event
- * @pf: board private structure
- **/
-static void i40e_service_event_complete(struct i40e_pf *pf)
-{
- WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state));
-
- /* flush memory to make sure state is correct before next watchog */
- smp_mb__before_atomic();
- clear_bit(__I40E_SERVICE_SCHED, &pf->state);
-}
-
-/**
* i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
* @pf: board private structure
**/
@@ -6670,7 +6821,6 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi);
static void i40e_fdir_sb_setup(struct i40e_pf *pf)
{
struct i40e_vsi *vsi;
- int i;
/* quick workaround for an NVM issue that leaves a critical register
* uninitialized
@@ -6681,6 +6831,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)
0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb,
0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21,
0x95b3a76d};
+ int i;
for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++)
wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]);
@@ -6690,13 +6841,7 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)
return;
/* find existing VSI and see if it needs configuring */
- vsi = NULL;
- for (i = 0; i < pf->num_alloc_vsi; i++) {
- if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
- vsi = pf->vsi[i];
- break;
- }
- }
+ vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
/* create a new VSI if none exists */
if (!vsi) {
@@ -6718,15 +6863,12 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)
**/
static void i40e_fdir_teardown(struct i40e_pf *pf)
{
- int i;
+ struct i40e_vsi *vsi;
i40e_fdir_filter_exit(pf);
- for (i = 0; i < pf->num_alloc_vsi; i++) {
- if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
- i40e_vsi_release(pf->vsi[i]);
- break;
- }
- }
+ vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
+ if (vsi)
+ i40e_vsi_release(vsi);
}
/**
@@ -7163,10 +7305,12 @@ static void i40e_service_task(struct work_struct *work)
/* don't bother with service tasks if a reset is in progress */
if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
- i40e_service_event_complete(pf);
return;
}
+ if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+ return;
+
i40e_detect_recover_hung(pf);
i40e_sync_filters_subtask(pf);
i40e_reset_subtask(pf);
@@ -7179,7 +7323,9 @@ static void i40e_service_task(struct work_struct *work)
i40e_sync_udp_filters_subtask(pf);
i40e_clean_adminq_subtask(pf);
- i40e_service_event_complete(pf);
+ /* flush memory to make sure state is correct before next watchdog */
+ smp_mb__before_atomic();
+ clear_bit(__I40E_SERVICE_SCHED, &pf->state);
/* If the tasks have taken longer than one timer cycle or there
* is more work to be done, reschedule the service task now
@@ -7354,7 +7500,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
pf->rss_table_size : 64;
vsi->netdev_registered = false;
vsi->work_limit = I40E_DEFAULT_IRQ_WORK;
- INIT_LIST_HEAD(&vsi->mac_filter_list);
+ hash_init(vsi->mac_filter_hash);
vsi->irqs_ready = false;
ret = i40e_set_num_rings_in_vsi(vsi);
@@ -7369,7 +7515,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
/* Initialize VSI lock */
- spin_lock_init(&vsi->mac_filter_list_lock);
+ spin_lock_init(&vsi->mac_filter_hash_lock);
pf->vsi[vsi_idx] = vsi;
ret = vsi_idx;
goto unlock_pf;
@@ -8345,8 +8491,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
i40e_pf_config_rss(pf);
}
- dev_info(&pf->pdev->dev, "RSS count/HW max RSS count: %d/%d\n",
- pf->alloc_rss_size, pf->rss_size_max);
+ dev_info(&pf->pdev->dev, "User requested queue count/HW max RSS count: %d/%d\n",
+ vsi->req_queue_pairs, pf->rss_size_max);
return pf->alloc_rss_size;
}
@@ -8489,15 +8635,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
int err = 0;
int size;
- pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
- (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
- if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
- if (I40E_DEBUG_USER & debug)
- pf->hw.debug_mask = debug;
- pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER),
- I40E_DEFAULT_MSG_ENABLE);
- }
-
/* Set default capability flags */
pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
I40E_FLAG_MSI_ENABLED |
@@ -8605,7 +8742,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
I40E_FLAG_NO_PCI_LINK_CHECK |
I40E_FLAG_USE_SET_LLDP_MIB |
- I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
+ I40E_FLAG_GENEVE_OFFLOAD_CAPABLE |
+ I40E_FLAG_PTP_L4_CAPABLE;
} else if ((pf->hw.aq.api_maj_ver > 1) ||
((pf->hw.aq.api_maj_ver == 1) &&
(pf->hw.aq.api_min_ver > 4))) {
@@ -9037,10 +9175,6 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
0, 0, nlflags, filter_mask, NULL);
}
-/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
- * inner mac plus all inner ethertypes.
- */
-#define I40E_MAX_TUNNEL_HDR_LEN 128
/**
* i40e_features_check - Validate encapsulated packet conforms to limits
* @skb: skb buff
@@ -9051,12 +9185,52 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features)
{
- if (skb->encapsulation &&
- ((skb_inner_network_header(skb) - skb_transport_header(skb)) >
- I40E_MAX_TUNNEL_HDR_LEN))
- return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+ size_t len;
+
+ /* No point in doing any of this if neither checksum nor GSO are
+ * being requested for this frame. We can rule out both by just
+ * checking for CHECKSUM_PARTIAL
+ */
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return features;
+
+ /* We cannot support GSO if the MSS is going to be less than
+ * 64 bytes. If it is then we need to drop support for GSO.
+ */
+ if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+ features &= ~NETIF_F_GSO_MASK;
+
+ /* MACLEN can support at most 63 words */
+ len = skb_network_header(skb) - skb->data;
+ if (len & ~(63 * 2))
+ goto out_err;
+
+ /* IPLEN and EIPLEN can support at most 127 dwords */
+ len = skb_transport_header(skb) - skb_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+
+ if (skb->encapsulation) {
+ /* L4TUNLEN can support 127 words */
+ len = skb_inner_network_header(skb) - skb_transport_header(skb);
+ if (len & ~(127 * 2))
+ goto out_err;
+
+ /* IPLEN can support at most 127 dwords */
+ len = skb_inner_transport_header(skb) -
+ skb_inner_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+ }
+
+ /* No need to validate L4LEN as TCP is the only protocol with a
+ * a flexible value and we support all possible values supported
+ * by TCP, which is at most 15 dwords
+ */
return features;
+out_err:
+ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
}
static const struct net_device_ops i40e_netdev_ops = {
@@ -9109,6 +9283,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
struct i40e_hw *hw = &pf->hw;
struct i40e_netdev_priv *np;
struct net_device *netdev;
+ u8 broadcast[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
int etherdev_size;
@@ -9169,20 +9344,38 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
* which must be replaced by a normal filter.
*/
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);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY);
+ spin_unlock_bh(&vsi->mac_filter_hash_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_hash_lock);
+ i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
}
+ /* Add the broadcast filter so that we initially will receive
+ * broadcast packets. Note that when a new VLAN is first added the
+ * driver will convert all filters marked I40E_VLAN_ANY into VLAN
+ * specific filters as part of transitioning into "vlan" operation.
+ * When more VLANs are added, the driver will copy each existing MAC
+ * filter and add it for the new VLAN.
+ *
+ * Broadcast filters are handled specially by
+ * i40e_sync_filters_subtask, as the driver must to set the broadcast
+ * promiscuous bit instead of adding this directly as a MAC/VLAN
+ * filter. The subtask will update the correct broadcast promiscuous
+ * bits as VLANs become active or inactive.
+ */
+ eth_broadcast_addr(broadcast);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_add_filter(vsi, broadcast, I40E_VLAN_ANY);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
ether_addr_copy(netdev->dev_addr, mac_addr);
ether_addr_copy(netdev->perm_addr, mac_addr);
@@ -9198,6 +9391,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
i40e_fcoe_config_netdev(netdev, vsi);
#endif
+ /* MTU range: 68 - 9706 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = I40E_MAX_RXBUFFER -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
return 0;
}
@@ -9260,11 +9458,12 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)
static int i40e_add_vsi(struct i40e_vsi *vsi)
{
int ret = -ENODEV;
- i40e_status aq_ret = 0;
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
struct i40e_vsi_context ctxt;
- struct i40e_mac_filter *f, *ftmp;
+ struct i40e_mac_filter *f;
+ struct hlist_node *h;
+ int bkt;
u8 enabled_tc = 0x1; /* TC0 enabled */
int f_count = 0;
@@ -9448,28 +9647,16 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
vsi->seid = ctxt.seid;
vsi->id = ctxt.vsi_number;
}
- /* Except FDIR VSI, for all othet VSI set the broadcast filter */
- if (vsi->type != I40E_VSI_FDIR) {
- aq_ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL);
- if (aq_ret) {
- ret = i40e_aq_rc_to_posix(aq_ret,
- hw->aq.asq_last_status);
- dev_info(&pf->pdev->dev,
- "set brdcast promisc failed, err %s, aq_err %s\n",
- i40e_stat_str(hw, aq_ret),
- i40e_aq_str(hw, hw->aq.asq_last_status));
- }
- }
vsi->active_filters = 0;
clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
- spin_lock_bh(&vsi->mac_filter_list_lock);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
/* If macvlan filters already exist, force them to get loaded */
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
f->state = I40E_FILTER_NEW;
f_count++;
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
if (f_count) {
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -9499,11 +9686,12 @@ err:
**/
int i40e_vsi_release(struct i40e_vsi *vsi)
{
- struct i40e_mac_filter *f, *ftmp;
+ struct i40e_mac_filter *f;
+ struct hlist_node *h;
struct i40e_veb *veb = NULL;
struct i40e_pf *pf;
u16 uplink_seid;
- int i, n;
+ int i, n, bkt;
pf = vsi->back;
@@ -9533,11 +9721,19 @@ 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);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+
+ /* clear the sync flag on all filters */
+ if (vsi->netdev) {
+ __dev_uc_unsync(vsi->netdev, NULL);
+ __dev_mc_unsync(vsi->netdev, NULL);
+ }
+
+ /* make sure any remaining filters are marked for deletion */
+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
+ __i40e_del_filter(vsi, f);
+
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
i40e_sync_vsi_filters(vsi);
@@ -10806,10 +11002,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mutex_init(&hw->aq.asq_mutex);
mutex_init(&hw->aq.arq_mutex);
- if (debug != -1) {
- pf->msg_enable = pf->hw.debug_mask;
- pf->msg_enable = debug;
- }
+ pf->msg_enable = netif_msg_init(debug,
+ NETIF_MSG_DRV |
+ NETIF_MSG_PROBE |
+ NETIF_MSG_LINK);
+ if (debug < -1)
+ pf->hw.debug_mask = debug;
/* do a special CORER for clearing PXE mode once at init */
if (hw->revision_id == 0 &&
@@ -10951,7 +11149,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = i40e_init_pf_dcb(pf);
if (err) {
dev_info(&pdev->dev, "DCB init failed %d, disabled\n", err);
- pf->flags &= ~(I40E_FLAG_DCB_CAPABLE & I40E_FLAG_DCB_ENABLED);
+ pf->flags &= ~(I40E_FLAG_DCB_CAPABLE | I40E_FLAG_DCB_ENABLED);
/* Continue without DCB enabled */
}
#endif /* CONFIG_I40E_DCB */
@@ -11209,7 +11407,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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
@@ -11221,9 +11418,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pf->main_vsi_seid);
if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) ||
- (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
- pf->flags |= I40E_FLAG_HAVE_10GBASET_PHY;
-
+ (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
+ pf->flags |= I40E_FLAG_PHY_CONTROLS_LEDS;
+ if (pf->hw.device_id == I40E_DEV_ID_SFP_I_X722)
+ pf->flags |= I40E_FLAG_HAVE_CRT_RETIMER;
/* print a string summarizing features */
i40e_print_features(pf);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 954efe3118db..38ee18f11124 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -722,9 +722,20 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
}
+ /* Clear error status on read */
+ if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+
return 0;
}
+ /* Clear status even it is not read and log */
+ if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
+ i40e_debug(hw, I40E_DEBUG_NVM,
+ "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ }
+
switch (hw->nvmupd_state) {
case I40E_NVMUPD_STATE_INIT:
status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
@@ -1074,6 +1085,11 @@ void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)
}
hw->nvm_wait_opcode = 0;
+ if (hw->aq.arq_last_status) {
+ hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
+ return;
+ }
+
switch (hw->nvmupd_state) {
case I40E_NVMUPD_STATE_INIT_WAIT:
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index 4660c5abc855..2551fc827444 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -144,6 +144,9 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable,
u16 vid,
struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
+ u16 seid, bool enable, u16 vid,
+ struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
u16 seid, bool enable,
struct i40e_asq_cmd_details *cmd_details);
@@ -362,10 +365,18 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details);
void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
-i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
- u16 reg, u8 phy_addr, u16 *value);
-i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
- u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
+ u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
+ u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+ u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+ u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index f1feceab758a..9e49ffafce28 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
struct timespec64 now, then;
- unsigned long flags;
then = ns_to_timespec64(delta);
- spin_lock_irqsave(&pf->tmreg_lock, flags);
+ mutex_lock(&pf->tmreg_lock);
i40e_ptp_read(pf, &now);
now = timespec64_add(now, then);
i40e_ptp_write(pf, (const struct timespec64 *)&now);
- spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+ mutex_unlock(&pf->tmreg_lock);
return 0;
}
@@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
- unsigned long flags;
- spin_lock_irqsave(&pf->tmreg_lock, flags);
+ mutex_lock(&pf->tmreg_lock);
i40e_ptp_read(pf, ts);
- spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+ mutex_unlock(&pf->tmreg_lock);
return 0;
}
@@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
- unsigned long flags;
- spin_lock_irqsave(&pf->tmreg_lock, flags);
+ mutex_lock(&pf->tmreg_lock);
i40e_ptp_write(pf, ts);
- spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+ mutex_unlock(&pf->tmreg_lock);
return 0;
}
@@ -230,6 +227,47 @@ static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
}
/**
+ * i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events
+ * @pf: the PF data structure
+ *
+ * This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers
+ * for noticed latch events. This allows the driver to keep track of the first
+ * time a latch event was noticed which will be used to help clear out Rx
+ * timestamps for packets that got dropped or lost.
+ *
+ * This function will return the current value of I40E_PRTTSYN_STAT_1 and is
+ * expected to be called only while under the ptp_rx_lock.
+ **/
+static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = &pf->hw;
+ u32 prttsyn_stat, new_latch_events;
+ int i;
+
+ prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+ new_latch_events = prttsyn_stat & ~pf->latch_event_flags;
+
+ /* Update the jiffies time for any newly latched timestamp. This
+ * ensures that we store the time that we first discovered a timestamp
+ * was latched by the hardware. The service task will later determine
+ * if we should free the latch and drop that timestamp should too much
+ * time pass. This flow ensures that we only update jiffies for new
+ * events latched since the last time we checked, and not all events
+ * currently latched, so that the service task accounting remains
+ * accurate.
+ */
+ for (i = 0; i < 4; i++) {
+ if (new_latch_events & BIT(i))
+ pf->latch_events[i] = jiffies;
+ }
+
+ /* Finally, we store the current status of the Rx timestamp latches */
+ pf->latch_event_flags = prttsyn_stat;
+
+ return prttsyn_stat;
+}
+
+/**
* i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
* @vsi: The VSI with the rings relevant to 1588
*
@@ -242,10 +280,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- struct i40e_ring *rx_ring;
- unsigned long rx_event;
- u32 prttsyn_stat;
- int n;
+ int i;
/* Since we cannot turn off the Rx timestamp logic if the device is
* configured for Tx timestamping, we check if Rx timestamping is
@@ -255,42 +290,30 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx)
return;
- prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+ spin_lock_bh(&pf->ptp_rx_lock);
- /* Unless all four receive timestamp registers are latched, we are not
- * concerned about a possible PTP Rx hang, so just update the timeout
- * counter and exit.
- */
- if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK <<
- I40E_PRTTSYN_STAT_1_RXT0_SHIFT) |
- (I40E_PRTTSYN_STAT_1_RXT1_MASK <<
- I40E_PRTTSYN_STAT_1_RXT1_SHIFT) |
- (I40E_PRTTSYN_STAT_1_RXT2_MASK <<
- I40E_PRTTSYN_STAT_1_RXT2_SHIFT) |
- (I40E_PRTTSYN_STAT_1_RXT3_MASK <<
- I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) {
- pf->last_rx_ptp_check = jiffies;
- return;
- }
+ /* Update current latch times for Rx events */
+ i40e_ptp_get_rx_events(pf);
- /* Determine the most recent watchdog or rx_timestamp event. */
- rx_event = pf->last_rx_ptp_check;
- for (n = 0; n < vsi->num_queue_pairs; n++) {
- rx_ring = vsi->rx_rings[n];
- if (time_after(rx_ring->last_rx_timestamp, rx_event))
- rx_event = rx_ring->last_rx_timestamp;
+ /* Check all the currently latched Rx events and see whether they have
+ * been latched for over a second. It is assumed that any timestamp
+ * should have been cleared within this time, or else it was captured
+ * for a dropped frame that the driver never received. Thus, we will
+ * clear any timestamp that has been latched for over 1 second.
+ */
+ for (i = 0; i < 4; i++) {
+ if ((pf->latch_event_flags & BIT(i)) &&
+ time_is_before_jiffies(pf->latch_events[i] + HZ)) {
+ rd32(hw, I40E_PRTTSYN_RXTIME_H(i));
+ pf->latch_event_flags &= ~BIT(i);
+ pf->rx_hwtstamp_cleared++;
+ dev_warn(&pf->pdev->dev,
+ "Clearing a missed Rx timestamp event for RXTIME[%d]\n",
+ i);
+ }
}
- /* Only need to read the high RXSTMP register to clear the lock */
- if (time_is_before_jiffies(rx_event + 5 * HZ)) {
- rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
- rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
- rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
- rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
- pf->last_rx_ptp_check = jiffies;
- pf->rx_hwtstamp_cleared++;
- WARN_ONCE(1, "Detected Rx timestamp register hang\n");
- }
+ spin_unlock_bh(&pf->ptp_rx_lock);
}
/**
@@ -353,14 +376,25 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index)
hw = &pf->hw;
- prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+ spin_lock_bh(&pf->ptp_rx_lock);
- if (!(prttsyn_stat & BIT(index)))
+ /* Get current Rx events and update latch times */
+ prttsyn_stat = i40e_ptp_get_rx_events(pf);
+
+ /* TODO: Should we warn about missing Rx timestamp event? */
+ if (!(prttsyn_stat & BIT(index))) {
+ spin_unlock_bh(&pf->ptp_rx_lock);
return;
+ }
+
+ /* Clear the latched event since we're about to read its register */
+ pf->latch_event_flags &= ~BIT(index);
lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));
hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index));
+ spin_unlock_bh(&pf->ptp_rx_lock);
+
ns = (((u64)hi) << 32) | lo;
i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns);
@@ -487,6 +521,8 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+ return -ERANGE;
pf->ptp_rx = true;
tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
I40E_PRTTSYN_CTL1_TSYNTYPE_V1 |
@@ -494,19 +530,26 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
- case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
- case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
- case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+ return -ERANGE;
+ /* fall through */
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
pf->ptp_rx = true;
tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
- I40E_PRTTSYN_CTL1_TSYNTYPE_V2 |
- I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
- config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ I40E_PRTTSYN_CTL1_TSYNTYPE_V2;
+ if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) {
+ tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ } else {
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ }
break;
case HWTSTAMP_FILTER_ALL:
default:
@@ -514,12 +557,15 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
}
/* Clear out all 1588-related registers to clear and unlatch them. */
+ spin_lock_bh(&pf->ptp_rx_lock);
rd32(hw, I40E_PRTTSYN_STAT_0);
rd32(hw, I40E_PRTTSYN_TXTIME_H);
rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
+ pf->latch_event_flags = 0;
+ spin_unlock_bh(&pf->ptp_rx_lock);
/* Enable/disable the Tx timestamp interrupt based on user input. */
regval = rd32(hw, I40E_PRTTSYN_CTL0);
@@ -658,10 +704,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
return;
}
- /* we have to initialize the lock first, since we can't control
- * when the user will enter the PHC device entry points
- */
- spin_lock_init(&pf->tmreg_lock);
+ mutex_init(&pf->tmreg_lock);
+ spin_lock_init(&pf->ptp_rx_lock);
/* ensure we have a clock device */
err = i40e_ptp_create_clock(pf);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 6287bf63c43c..352cf7cd2ef4 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -122,14 +122,10 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,
struct device *dev;
dma_addr_t dma;
u32 td_cmd = 0;
- u16 delay = 0;
u16 i;
/* find existing FDIR VSI */
- vsi = NULL;
- for (i = 0; i < pf->num_alloc_vsi; i++)
- if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR)
- vsi = pf->vsi[i];
+ vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
if (!vsi)
return -ENOENT;
@@ -137,15 +133,11 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,
dev = tx_ring->dev;
/* we need two descriptors to add/del a filter and we can wait */
- do {
- if (I40E_DESC_UNUSED(tx_ring) > 1)
- break;
+ for (i = I40E_FD_CLEAN_DELAY; I40E_DESC_UNUSED(tx_ring) < 2; i--) {
+ if (!i)
+ return -EAGAIN;
msleep_interruptible(1);
- delay++;
- } while (delay < I40E_FD_CLEAN_DELAY);
-
- if (!(I40E_DESC_UNUSED(tx_ring) > 1))
- return -EAGAIN;
+ }
dma = dma_map_single(dev, raw_packet,
I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE);
@@ -335,22 +327,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
return err ? -EOPNOTSUPP : 0;
}
-/**
- * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
- * a specific flow spec
- * @vsi: pointer to the targeted VSI
- * @fd_data: the flow director data required for the FDir descriptor
- * @add: true adds a filter, false removes it
- *
- * Returns 0 if the filters were successfully added or removed
- **/
-static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
- struct i40e_fdir_filter *fd_data,
- bool add)
-{
- return -EOPNOTSUPP;
-}
-
#define I40E_IP_DUMMY_PACKET_LEN 34
/**
* i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
@@ -433,12 +409,6 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
case UDP_V4_FLOW:
ret = i40e_add_del_fdir_udpv4(vsi, input, add);
break;
- case SCTP_V4_FLOW:
- ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
- break;
- case IPV4_FLOW:
- ret = i40e_add_del_fdir_ipv4(vsi, input, add);
- break;
case IP_USER_FLOW:
switch (input->ip4_proto) {
case IPPROTO_TCP:
@@ -447,15 +417,16 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
case IPPROTO_UDP:
ret = i40e_add_del_fdir_udpv4(vsi, input, add);
break;
- case IPPROTO_SCTP:
- ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
- break;
- default:
+ case IPPROTO_IP:
ret = i40e_add_del_fdir_ipv4(vsi, input, add);
break;
+ default:
+ /* We cannot support masking based on protocol */
+ goto unsupported_flow;
}
break;
default:
+unsupported_flow:
dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",
input->flow_type);
ret = -EINVAL;
@@ -645,7 +616,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)
return 0;
}
-#define WB_STRIDE 0x3
+#define WB_STRIDE 4
/**
* i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -761,7 +732,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
unsigned int j = i40e_get_tx_pending(tx_ring, false);
if (budget &&
- ((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
+ ((j / WB_STRIDE) == 0) && (j > 0) &&
!test_bit(__I40E_DOWN, &vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
@@ -1246,7 +1217,6 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
* because each write-back erases this info.
*/
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
- rx_desc->read.hdr_addr = 0;
rx_desc++;
bi++;
@@ -1437,13 +1407,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
I40E_RXD_QW1_STATUS_SHIFT;
- u32 rsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
+ u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
+ u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
- if (unlikely(rsyn)) {
- i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, rsyn);
- rx_ring->last_rx_timestamp = jiffies;
- }
+ if (unlikely(tsynvalid))
+ i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
@@ -1767,7 +1736,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
while (likely(total_rx_packets < budget)) {
union i40e_rx_desc *rx_desc;
struct sk_buff *skb;
- u32 rx_status;
u16 vlan_tag;
u8 rx_ptype;
u64 qword;
@@ -1781,21 +1749,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
- qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
- rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
- I40E_RXD_QW1_PTYPE_SHIFT;
- rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
- I40E_RXD_QW1_STATUS_SHIFT;
-
- if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
- break;
-
/* status_error_len will always be zero for unused descriptors
* because it's cleared in cleanup, and overlaps with hdr_addr
* which is always zero because packet split isn't used, if the
* hardware wrote DD then it will be non-zero
*/
- if (!rx_desc->wb.qword1.status_error_len)
+ if (!i40e_test_staterr(rx_desc,
+ BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
break;
/* This memory barrier is needed to keep us from reading
@@ -1829,6 +1789,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
+ qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
+
/* populate checksum, VLAN, and protocol */
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
@@ -2025,12 +1989,25 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
/* If work not completed, return budget and polling will return */
if (!clean_complete) {
+ const cpumask_t *aff_mask = &q_vector->affinity_mask;
+ int cpu_id = smp_processor_id();
+
+ /* It is possible that the interrupt affinity has changed but,
+ * if the cpu is pegged at 100%, polling will never exit while
+ * traffic continues and the interrupt will be stuck on this
+ * cpu. We check to make sure affinity is correct before we
+ * continue to poll, otherwise we must stop polling so the
+ * interrupt can move to the correct cpu.
+ */
+ if (likely(cpumask_test_cpu(cpu_id, aff_mask) ||
+ !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) {
tx_only:
- if (arm_wb) {
- q_vector->tx.ring[0].tx_stats.tx_force_wb++;
- i40e_enable_wb_on_itr(vsi, q_vector);
+ if (arm_wb) {
+ q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+ i40e_enable_wb_on_itr(vsi, q_vector);
+ }
+ return budget;
}
- return budget;
}
if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -2038,12 +2015,19 @@ tx_only:
/* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete_done(napi, work_done);
- if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
- i40e_update_enable_itr(vsi, q_vector);
- } else { /* Legacy mode */
+
+ /* If we're prematurely stopping polling to fix the interrupt
+ * affinity we want to make sure polling starts back up so we
+ * issue a call to i40e_force_wb which triggers a SW interrupt.
+ */
+ if (!clean_complete)
+ i40e_force_wb(vsi, q_vector);
+ else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))
i40e_irq_dynamic_enable_icr0(vsi->back, false);
- }
- return 0;
+ else
+ i40e_update_enable_itr(vsi, q_vector);
+
+ return min(work_done, budget - 1);
}
/**
@@ -2716,9 +2700,7 @@ 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;
+ u16 desc_count = 1;
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2801,8 +2783,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_bi = &tx_ring->tx_bi[i];
}
- /* set next_to_watch value indicating a packet is present */
- first->next_to_watch = tx_desc;
+ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
i++;
if (i == tx_ring->count)
@@ -2810,66 +2791,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(txring_txq(tx_ring), first->bytecount);
i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+ /* write last descriptor with EOP bit */
+ td_cmd |= I40E_TX_DESC_CMD_EOP;
+
+ /* We can OR these values together as they both are checked against
+ * 4 below and at this point desc_count will be used as a boolean value
+ * after this if/else block.
+ */
+ desc_count |= ++tx_ring->packet_stride;
+
/* 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.
+ * if queue is stopped
+ * mark RS bit
+ * reset packet counter
+ * else if xmit_more is supported and is true
+ * advance packet counter to 4
+ * reset desc_count to 0
*
- * Optimization: wmb to be issued only in case of tail update.
- * Also optimize the Descriptor WB path for RS bit with the same
- * algorithm.
+ * if desc_count >= 4
+ * mark RS bit
+ * reset packet counter
+ * if desc_count > 0
+ * update tail
*
- * Note: If there are less than 4 packets
+ * Note: If there are less than 4 descriptors
* pending and interrupts were disabled the service task will
* trigger a force WB.
*/
- if (skb->xmit_more &&
- !netif_xmit_stopped(txring_txq(tx_ring))) {
- tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
- tail_bump = false;
- } else if (!skb->xmit_more &&
- !netif_xmit_stopped(txring_txq(tx_ring)) &&
- (!(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 {
+ if (netif_xmit_stopped(txring_txq(tx_ring))) {
+ goto do_rs;
+ } else if (skb->xmit_more) {
+ /* set stride to arm on next packet and reset desc_count */
+ tx_ring->packet_stride = WB_STRIDE;
+ desc_count = 0;
+ } else if (desc_count >= WB_STRIDE) {
+do_rs:
+ /* write last descriptor with RS bit set */
+ td_cmd |= I40E_TX_DESC_CMD_RS;
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);
+ build_ctob(td_cmd, td_offset, size, td_tag);
+
+ /* Force memory writes to complete before letting h/w know there
+ * are new descriptors to fetch.
+ *
+ * We also use this memory barrier to make certain all of the
+ * status bits have been updated before next_to_watch is written.
+ */
+ wmb();
+
+ /* set next_to_watch value indicating a packet is present */
+ first->next_to_watch = tx_desc;
/* notify HW of packet */
- if (!tail_bump) {
- prefetchw(tx_desc + 1);
- } else {
- /* 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();
+ if (desc_count) {
writel(i, tx_ring->tail);
+
+ /* we need this if more than one processor can write to our tail
+ * at a time, it synchronizes IO on IA64/Altix systems
+ */
+ mmiowb();
}
+
return;
dma_error:
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index 508840585645..e065321ce8ed 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,
#define I40E_MAX_DATA_PER_TXD_ALIGNED \
(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
-/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is
- * the value I40E_MAX_DATA_PER_TXD_ALIGNED. It is needed due to the fact
- * that 12K is not a power of 2 and division is expensive. It is used to
- * approximate the number of descriptors used per linear buffer. Note
- * that this will overestimate in some cases as it doesn't account for the
- * fact that we will add up to 4K - 1 in aligning the 12K buffer, however
- * the error should not impact things much as large buffers usually mean
- * we will use fewer descriptors then there are frags in an skb.
+/**
+ * i40e_txd_use_count - estimate the number of descriptors needed for Tx
+ * @size: transmit request size in bytes
+ *
+ * Due to hardware alignment restrictions (4K alignment), we need to
+ * assume that we can have no more than 12K of data per descriptor, even
+ * though each descriptor can take up to 16K - 1 bytes of aligned memory.
+ * Thus, we need to divide by 12K. But division is slow! Instead,
+ * we decompose the operation into shifts and one relatively cheap
+ * multiply operation.
+ *
+ * To divide by 12K, we first divide by 4K, then divide by 3:
+ * To divide by 4K, shift right by 12 bits
+ * To divide by 3, multiply by 85, then divide by 256
+ * (Divide by 256 is done by shifting right by 8 bits)
+ * Finally, we add one to round up. Because 256 isn't an exact multiple of
+ * 3, we'll underestimate near each multiple of 12K. This is actually more
+ * accurate as we have 4K - 1 of wiggle room that we can fit into the last
+ * segment. For our purposes this is accurate out to 1M which is orders of
+ * magnitude greater than our largest possible GSO size.
+ *
+ * This would then be implemented as:
+ * return (((size >> 12) * 85) >> 8) + 1;
+ *
+ * Since multiplication and division are commutative, we can reorder
+ * operations into:
+ * return ((size * 85) >> 20) + 1;
*/
static inline unsigned int i40e_txd_use_count(unsigned int size)
{
- const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED;
- const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max;
- unsigned int adjust = ~(u32)0;
-
- /* if we rounded up on the reciprocal pull down the adjustment */
- if ((max * reciprocal) > adjust)
- adjust = ~(u32)(reciprocal - 1);
-
- return (u32)((((u64)size * reciprocal) + adjust) >> 32);
+ return ((size * 85) >> 20) + 1;
}
/* Tx Descriptors needed, worst case */
@@ -307,15 +318,12 @@ struct i40e_ring {
u8 atr_sample_rate;
u8 atr_count;
- unsigned long last_rx_timestamp;
-
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_LAST_XMIT_MORE_SET BIT(2)
/* stats structs */
struct i40e_queue_stats stats;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index bd5f13bef83c..edc0abdf4783 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -90,14 +90,23 @@ enum i40e_debug_mask {
I40E_DEBUG_ALL = 0xFFFFFFFF
};
-#define I40E_MDIO_STCODE 0
-#define I40E_MDIO_OPCODE_ADDRESS 0
-#define I40E_MDIO_OPCODE_WRITE I40E_MASK(1, \
+#define I40E_MDIO_CLAUSE22_STCODE_MASK I40E_MASK(1, \
+ I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ_INC_ADDR I40E_MASK(2, \
+#define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ I40E_MASK(3, \
+
+#define I40E_MDIO_CLAUSE45_STCODE_MASK I40E_MASK(0, \
+ I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK I40E_MASK(0, \
+ I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK I40E_MASK(2, \
+ I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK I40E_MASK(3, \
+ I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_PHY_COM_REG_PAGE 0x1E
#define I40E_PHY_LED_LINK_MODE_MASK 0xF0
@@ -204,47 +213,59 @@ struct i40e_link_status {
#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;
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;
-};
-
+ u64 phy_types;
+};
+
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+ BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+ I40E_PHY_TYPE_OFFSET)
#define I40E_HW_CAP_MAX_GPIO 30
/* Capabilities of a PF or a VF or the whole device */
struct i40e_hw_capabilities {
@@ -254,6 +275,10 @@ struct i40e_hw_capabilities {
#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3
u32 management_mode;
+ u32 mng_protocols_over_mctp;
+#define I40E_MNG_PROTOCOL_PLDM 0x2
+#define I40E_MNG_PROTOCOL_OEM_COMMANDS 0x4
+#define I40E_MNG_PROTOCOL_NCSI 0x8
u32 npar_enable;
u32 os2bmc;
u32 valid_functions;
@@ -366,6 +391,7 @@ enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_WRITING,
I40E_NVMUPD_STATE_INIT_WAIT,
I40E_NVMUPD_STATE_WRITE_WAIT,
+ I40E_NVMUPD_STATE_ERROR
};
/* nvm_access definition and its masks/shifts need to be accessible to
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
index f861d3109d1a..974ba2baf6ea 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
@@ -165,6 +165,10 @@ struct i40e_virtchnl_vsi_resource {
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000
#define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00100000
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+ I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+ I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
struct i40e_virtchnl_vf_resource {
u16 num_vsis;
u16 num_queue_pairs;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 54b8ee2583f1..a6198b727e24 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -674,6 +674,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
}
if (type == I40E_VSI_SRIOV) {
u64 hena = i40e_pf_get_default_rss_hena(pf);
+ u8 broadcast[ETH_ALEN];
vf->lan_vsi_idx = vsi->idx;
vf->lan_vsi_id = vsi->id;
@@ -686,17 +687,23 @@ 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);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
if (is_valid_ether_addr(vf->default_lan_addr.addr)) {
f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
- vf->port_vlan_id ? vf->port_vlan_id : -1,
- true, false);
+ vf->port_vlan_id ?
+ vf->port_vlan_id : -1);
if (!f)
dev_info(&pf->pdev->dev,
"Could not add MAC filter %pM for VF %d\n",
vf->default_lan_addr.addr, vf->vf_id);
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ eth_broadcast_addr(broadcast);
+ f = i40e_add_filter(vsi, broadcast,
+ vf->port_vlan_id ? vf->port_vlan_id : -1);
+ if (!f)
+ dev_info(&pf->pdev->dev,
+ "Could not allocate VF broadcast filter\n");
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),
(u32)hena);
i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id),
@@ -811,6 +818,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
vf->lan_vsi_idx = 0;
vf->lan_vsi_id = 0;
+ vf->num_mac = 0;
}
msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
@@ -990,7 +998,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
if (vf->lan_vsi_idx == 0)
goto complete_reset;
- i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false);
+ i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
complete_reset:
/* reallocate VF resources to reset the VSI state */
i40e_free_vf_res(vf);
@@ -1031,8 +1039,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
i40e_notify_client_of_vf_enable(pf, 0);
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);
+ i40e_vsi_stop_rings(pf->vsi[pf->vf[i].lan_vsi_idx]);
/* Disable IOV before freeing resources. This lets any VF drivers
* running in the host get themselves cleaned up before we yank
@@ -1449,9 +1456,9 @@ static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
{
struct i40e_mac_filter *f;
- int num_vlans = 0;
+ int num_vlans = 0, bkt;
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)
num_vlans++;
}
@@ -1481,6 +1488,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
struct i40e_vsi *vsi;
bool alluni = false;
int aq_err = 0;
+ int bkt;
vsi = i40e_find_vsi_from_id(pf, info->vsi_id);
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
@@ -1507,7 +1515,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
vf->port_vlan_id,
NULL);
} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID)
continue;
aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw,
@@ -1535,7 +1543,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
vf->vf_id,
i40e_stat_str(&pf->hw, aq_ret),
i40e_aq_str(&pf->hw, aq_err));
- goto error_param_int;
+ goto error_param;
}
}
@@ -1557,7 +1565,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
vf->port_vlan_id,
NULL);
} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
aq_ret = 0;
if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) {
aq_ret =
@@ -1580,15 +1588,16 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
allmulti, NULL,
true);
aq_err = pf->hw.aq.asq_last_status;
- if (aq_ret)
+ if (aq_ret) {
dev_err(&pf->pdev->dev,
"VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n",
vf->vf_id, info->flags,
i40e_stat_str(&pf->hw, aq_ret),
i40e_aq_str(&pf->hw, aq_err));
+ goto error_param;
+ }
}
-error_param_int:
if (!aq_ret) {
dev_info(&pf->pdev->dev,
"VF %d successfully set unicast promiscuous mode\n",
@@ -1757,7 +1766,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
goto error_param;
}
- if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], true))
+ if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))
aq_ret = I40E_ERR_TIMEOUT;
error_param:
/* send the response to the VF */
@@ -1796,8 +1805,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
goto error_param;
}
- if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false))
- aq_ret = I40E_ERR_TIMEOUT;
+ i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
error_param:
/* send the response to the VF */
@@ -1927,20 +1935,18 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
/* 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);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
/* add new addresses to the list */
for (i = 0; i < al->num_elements; i++) {
struct i40e_mac_filter *f;
- f = i40e_find_mac(vsi, al->list[i].addr, true, false);
+ f = i40e_find_mac(vsi, al->list[i].addr);
if (!f) {
if (i40e_is_vsi_in_vlan(vsi))
- f = i40e_put_mac_in_vlan(vsi, al->list[i].addr,
- true, false);
+ f = i40e_put_mac_in_vlan(vsi, al->list[i].addr);
else
- f = i40e_add_filter(vsi, al->list[i].addr, -1,
- true, false);
+ f = i40e_add_filter(vsi, al->list[i].addr, -1);
}
if (!f) {
@@ -1948,13 +1954,13 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
"Unable to add MAC filter %pM for VF %d\n",
al->list[i].addr, vf->vf_id);
ret = I40E_ERR_PARAM;
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
goto error_param;
} else {
vf->num_mac++;
}
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
/* program the updated filter list */
ret = i40e_sync_vsi_filters(vsi);
@@ -2003,18 +2009,18 @@ 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);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
/* delete addresses from the list */
for (i = 0; i < al->num_elements; i++)
- if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) {
+ if (i40e_del_mac_all_vlan(vsi, al->list[i].addr)) {
ret = I40E_ERR_INVALID_MAC_ADDR;
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
goto error_param;
} else {
vf->num_mac--;
}
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
/* program the updated filter list */
ret = i40e_sync_vsi_filters(vsi);
@@ -2139,9 +2145,8 @@ 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)
- vf->num_vlan--;
+ i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]);
+ vf->num_vlan--;
if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states))
i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid,
@@ -2153,11 +2158,6 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
false,
vfl->vlan_id[i],
NULL);
-
- if (ret)
- dev_err(&pf->pdev->dev,
- "Unable to delete VLAN filter %d for VF %d, error %d\n",
- vfl->vlan_id[i], vf->vf_id, ret);
}
error_param:
@@ -2689,6 +2689,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
struct i40e_mac_filter *f;
struct i40e_vf *vf;
int ret = 0;
+ int bkt;
/* validate the request */
if (vf_id >= pf->num_alloc_vfs) {
@@ -2715,23 +2716,22 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
/* Lock once because below invoked function add/del_filter requires
- * mac_filter_list_lock to be held
+ * mac_filter_hash_lock to be held
*/
- spin_lock_bh(&vsi->mac_filter_list_lock);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
/* delete the temporary mac address */
if (!is_zero_ether_addr(vf->default_lan_addr.addr))
i40e_del_filter(vsi, vf->default_lan_addr.addr,
- vf->port_vlan_id ? vf->port_vlan_id : -1,
- true, false);
+ vf->port_vlan_id ? vf->port_vlan_id : -1);
/* Delete all the filters for this VSI - we're going to kill it
* anyway.
*/
- list_for_each_entry(f, &vsi->mac_filter_list, list)
- i40e_del_filter(vsi, f->macaddr, f->vlan, true, false);
+ hash_for_each(vsi->mac_filter_hash, bkt, f, hlist)
+ i40e_del_filter(vsi, f->macaddr, f->vlan);
- spin_unlock_bh(&vsi->mac_filter_list_lock);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);
/* program mac filter */
@@ -2766,7 +2766,6 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
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;
@@ -2803,11 +2802,10 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
/* duplicate request, so just return success */
goto error_pvid;
- 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);
+ /* Locked once because multiple functions below iterate list */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
- if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) {
+ if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
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);
@@ -2830,19 +2828,23 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
*/
if ((!(vlan_id || qos) ||
vlanprio != le16_to_cpu(vsi->info.pvid)) &&
- vsi->info.pvid)
- ret = i40e_vsi_add_vlan(vsi, I40E_VLAN_ANY);
-
- if (vsi->info.pvid) {
- /* kill old VLAN */
- ret = i40e_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) &
- VLAN_VID_MASK));
+ vsi->info.pvid) {
+ ret = i40e_add_vlan_all_mac(vsi, I40E_VLAN_ANY);
if (ret) {
dev_info(&vsi->back->pdev->dev,
- "remove VLAN failed, ret=%d, aq_err=%d\n",
- ret, pf->hw.aq.asq_last_status);
+ "add VF VLAN failed, ret=%d aq_err=%d\n", ret,
+ vsi->back->hw.aq.asq_last_status);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+ goto error_pvid;
}
}
+
+ if (vsi->info.pvid) {
+ /* remove all filters on the old VLAN */
+ i40e_rm_vlan_all_mac(vsi, (le16_to_cpu(vsi->info.pvid) &
+ VLAN_VID_MASK));
+ }
+
if (vlan_id || qos)
ret = i40e_vsi_add_pvid(vsi, vlanprio);
else
@@ -2852,24 +2854,30 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
vlan_id, qos, vf_id);
- /* add new VLAN filter */
- ret = i40e_vsi_add_vlan(vsi, vlan_id);
+ /* add new VLAN filter for each MAC */
+ ret = i40e_add_vlan_all_mac(vsi, vlan_id);
if (ret) {
dev_info(&vsi->back->pdev->dev,
"add VF VLAN failed, ret=%d aq_err=%d\n", ret,
vsi->back->hw.aq.asq_last_status);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
goto error_pvid;
}
- /* Kill non-vlan MAC filters - ignore error return since
- * there might not be any non-vlan MAC filters.
- */
- i40e_vsi_kill_vlan(vsi, I40E_VLAN_ANY);
+
+ /* remove the previously added non-VLAN MAC filters */
+ i40e_rm_vlan_all_mac(vsi, I40E_VLAN_ANY);
}
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ /* Schedule the worker thread to take care of applying changes */
+ i40e_service_event_schedule(vsi->back);
+
if (ret) {
dev_err(&pf->pdev->dev, "Unable to update VF vsi context\n");
goto error_pvid;
}
+
/* The Port VLAN needs to be saved across resets the same as the
* default LAN MAC address.
*/
@@ -2926,6 +2934,9 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
case I40E_LINK_SPEED_40GB:
speed = 40000;
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = 25000;
+ break;
case I40E_LINK_SPEED_20GB:
speed = 20000;
break;
@@ -2940,7 +2951,7 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
}
if (max_tx_rate > speed) {
- dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.",
+ dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.\n",
max_tx_rate, vf->vf_id);
ret = -EINVAL;
goto error;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index 44f7ed7583dd..96385156b824 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -912,11 +912,11 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
desc_idx = ntc;
+ hw->aq.arq_last_status =
+ (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
flags = le16_to_cpu(desc->flags);
if (flags & I40E_AQ_FLAG_ERR) {
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
- hw->aq.arq_last_status =
- (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
i40e_debug(hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index 40b0eafd0c71..eeb9864bc5b1 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1639,6 +1639,10 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_1000BASE_LX = 0x1C,
I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D,
I40E_PHY_TYPE_20GBASE_KR2 = 0x1E,
+ I40E_PHY_TYPE_25GBASE_KR = 0x1F,
+ I40E_PHY_TYPE_25GBASE_CR = 0x20,
+ I40E_PHY_TYPE_25GBASE_SR = 0x21,
+ I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_MAX
};
@@ -1647,6 +1651,7 @@ enum i40e_aq_phy_type {
#define I40E_LINK_SPEED_10GB_SHIFT 0x3
#define I40E_LINK_SPEED_40GB_SHIFT 0x4
#define I40E_LINK_SPEED_20GB_SHIFT 0x5
+#define I40E_LINK_SPEED_25GB_SHIFT 0x6
enum i40e_aq_link_speed {
I40E_LINK_SPEED_UNKNOWN = 0,
@@ -1654,7 +1659,8 @@ enum i40e_aq_link_speed {
I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
- I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT)
+ I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
+ I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
};
struct i40e_aqc_module_desc {
@@ -1677,6 +1683,8 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_LINK_ENABLED 0x08
#define I40E_AQ_PHY_AN_ENABLED 0x10
#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR 0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS 0x80
__le16 eee_capability;
#define I40E_AQ_EEE_100BASE_TX 0x0002
#define I40E_AQ_EEE_1000BASE_T 0x0004
@@ -1687,7 +1695,22 @@ struct i40e_aq_get_phy_abilities_resp {
__le32 eeer_val;
u8 d3_lpan;
#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR 0x01
+#define I40E_AQ_ENABLE_FEC_RS 0x02
+#define I40E_AQ_REQUEST_FEC_KR 0x04
+#define I40E_AQ_REQUEST_FEC_RS 0x08
+#define I40E_AQ_ENABLE_FEC_AUTO 0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK 0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT 5
+
+ u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
u8 qualified_module_count;
@@ -1709,7 +1732,20 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
__le16 eee_capability;
__le32 eeer;
u8 low_power_ctrl;
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS BIT(3)
+#define I40E_AQ_SET_FEC_AUTO BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT 0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+ u8 reserved;
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1789,9 +1825,18 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_LINK_TX_DRAINED 0x01
#define I40E_AQ_LINK_TX_FLUSHED 0x03
#define I40E_AQ_LINK_FORCED_40G 0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR 0X00
+#define I40E_AQ_25G_NOT_PRESENT 0X01
+#define I40E_AQ_25G_NVM_CRC_ERR 0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR 0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
u8 external_power_ability;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
index 7953c13451b9..aa63b7fb993d 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
@@ -53,6 +53,8 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
case I40E_DEV_ID_20G_KR2_A:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_SFP_X722:
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
index 70235706915e..21dcaee1ad1d 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
@@ -39,6 +39,8 @@
#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_25G_B 0x158A
+#define I40E_DEV_ID_25G_SFP28 0x158B
#define I40E_DEV_ID_VF 0x154C
#define I40E_DEV_ID_VF_HV 0x1571
#define I40E_DEV_ID_SFP_X722 0x37D0
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
index d89d52109efa..ba6c6bda0e22 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
@@ -115,6 +115,10 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+ u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+ u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 75f2a2cdd738..df67ef37b7f3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -150,7 +150,7 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
return 0;
}
-#define WB_STRIDE 0x3
+#define WB_STRIDE 4
/**
* i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
unsigned int j = i40evf_get_tx_pending(tx_ring, false);
if (budget &&
- ((j / (WB_STRIDE + 1)) == 0) && (j > 0) &&
+ ((j / WB_STRIDE) == 0) && (j > 0) &&
!test_bit(__I40E_DOWN, &vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
@@ -705,7 +705,6 @@ bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
* because each write-back erases this info.
*/
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
- rx_desc->read.hdr_addr = 0;
rx_desc++;
bi++;
@@ -1209,7 +1208,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
while (likely(total_rx_packets < budget)) {
union i40e_rx_desc *rx_desc;
struct sk_buff *skb;
- u32 rx_status;
u16 vlan_tag;
u8 rx_ptype;
u64 qword;
@@ -1223,21 +1221,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
- qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
- rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
- I40E_RXD_QW1_PTYPE_SHIFT;
- rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
- I40E_RXD_QW1_STATUS_SHIFT;
-
- if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
- break;
-
/* status_error_len will always be zero for unused descriptors
* because it's cleared in cleanup, and overlaps with hdr_addr
* which is always zero because packet split isn't used, if the
* hardware wrote DD then it will be non-zero
*/
- if (!rx_desc->wb.qword1.status_error_len)
+ if (!i40e_test_staterr(rx_desc,
+ BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
break;
/* This memory barrier is needed to keep us from reading
@@ -1271,6 +1261,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
+ qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
+
/* populate checksum, VLAN, and protocol */
i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
@@ -1461,12 +1455,24 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
/* If work not completed, return budget and polling will return */
if (!clean_complete) {
+ const cpumask_t *aff_mask = &q_vector->affinity_mask;
+ int cpu_id = smp_processor_id();
+
+ /* It is possible that the interrupt affinity has changed but,
+ * if the cpu is pegged at 100%, polling will never exit while
+ * traffic continues and the interrupt will be stuck on this
+ * cpu. We check to make sure affinity is correct before we
+ * continue to poll, otherwise we must stop polling so the
+ * interrupt can move to the correct cpu.
+ */
+ if (likely(cpumask_test_cpu(cpu_id, aff_mask))) {
tx_only:
- if (arm_wb) {
- q_vector->tx.ring[0].tx_stats.tx_force_wb++;
- i40e_enable_wb_on_itr(vsi, q_vector);
+ if (arm_wb) {
+ q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+ i40e_enable_wb_on_itr(vsi, q_vector);
+ }
+ return budget;
}
- return budget;
}
if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -1474,8 +1480,17 @@ tx_only:
/* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete_done(napi, work_done);
- i40e_update_enable_itr(vsi, q_vector);
- return 0;
+
+ /* If we're prematurely stopping polling to fix the interrupt
+ * affinity we want to make sure polling starts back up so we
+ * issue a call to i40evf_force_wb which triggers a SW interrupt.
+ */
+ if (!clean_complete)
+ i40evf_force_wb(vsi, q_vector);
+ else
+ i40e_update_enable_itr(vsi, q_vector);
+
+ return min(work_done, budget - 1);
}
/**
@@ -1935,9 +1950,7 @@ static inline void i40evf_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;
+ u16 desc_count = 1;
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2020,8 +2033,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_bi = &tx_ring->tx_bi[i];
}
- /* set next_to_watch value indicating a packet is present */
- first->next_to_watch = tx_desc;
+ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
i++;
if (i == tx_ring->count)
@@ -2029,66 +2041,72 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_ring->next_to_use = i;
- netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+ /* write last descriptor with EOP bit */
+ td_cmd |= I40E_TX_DESC_CMD_EOP;
+
+ /* We can OR these values together as they both are checked against
+ * 4 below and at this point desc_count will be used as a boolean value
+ * after this if/else block.
+ */
+ desc_count |= ++tx_ring->packet_stride;
+
/* 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.
+ * if queue is stopped
+ * mark RS bit
+ * reset packet counter
+ * else if xmit_more is supported and is true
+ * advance packet counter to 4
+ * reset desc_count to 0
*
- * Optimization: wmb to be issued only in case of tail update.
- * Also optimize the Descriptor WB path for RS bit with the same
- * algorithm.
+ * if desc_count >= 4
+ * mark RS bit
+ * reset packet counter
+ * if desc_count > 0
+ * update tail
*
- * Note: If there are less than 4 packets
+ * Note: If there are less than 4 descriptors
* pending and interrupts were disabled the service task will
* trigger a force WB.
*/
- if (skb->xmit_more &&
- !netif_xmit_stopped(txring_txq(tx_ring))) {
- tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
- tail_bump = false;
- } else if (!skb->xmit_more &&
- !netif_xmit_stopped(txring_txq(tx_ring)) &&
- (!(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 {
+ if (netif_xmit_stopped(txring_txq(tx_ring))) {
+ goto do_rs;
+ } else if (skb->xmit_more) {
+ /* set stride to arm on next packet and reset desc_count */
+ tx_ring->packet_stride = WB_STRIDE;
+ desc_count = 0;
+ } else if (desc_count >= WB_STRIDE) {
+do_rs:
+ /* write last descriptor with RS bit set */
+ td_cmd |= I40E_TX_DESC_CMD_RS;
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);
+ build_ctob(td_cmd, td_offset, size, td_tag);
+
+ /* Force memory writes to complete before letting h/w know there
+ * are new descriptors to fetch.
+ *
+ * We also use this memory barrier to make certain all of the
+ * status bits have been updated before next_to_watch is written.
+ */
+ wmb();
+
+ /* set next_to_watch value indicating a packet is present */
+ first->next_to_watch = tx_desc;
/* notify HW of packet */
- if (!tail_bump) {
- prefetchw(tx_desc + 1);
- } else {
- /* 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();
+ if (desc_count) {
writel(i, tx_ring->tail);
+
+ /* we need this if more than one processor can write to our tail
+ * at a time, it synchronizes IO on IA64/Altix systems
+ */
+ mmiowb();
}
+
return;
dma_error:
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
index abcdecabbc56..a5fc789f78eb 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
@@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,
#define I40E_MAX_DATA_PER_TXD_ALIGNED \
(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
-/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is
- * the value I40E_MAX_DATA_PER_TXD_ALIGNED. It is needed due to the fact
- * that 12K is not a power of 2 and division is expensive. It is used to
- * approximate the number of descriptors used per linear buffer. Note
- * that this will overestimate in some cases as it doesn't account for the
- * fact that we will add up to 4K - 1 in aligning the 12K buffer, however
- * the error should not impact things much as large buffers usually mean
- * we will use fewer descriptors then there are frags in an skb.
+/**
+ * i40e_txd_use_count - estimate the number of descriptors needed for Tx
+ * @size: transmit request size in bytes
+ *
+ * Due to hardware alignment restrictions (4K alignment), we need to
+ * assume that we can have no more than 12K of data per descriptor, even
+ * though each descriptor can take up to 16K - 1 bytes of aligned memory.
+ * Thus, we need to divide by 12K. But division is slow! Instead,
+ * we decompose the operation into shifts and one relatively cheap
+ * multiply operation.
+ *
+ * To divide by 12K, we first divide by 4K, then divide by 3:
+ * To divide by 4K, shift right by 12 bits
+ * To divide by 3, multiply by 85, then divide by 256
+ * (Divide by 256 is done by shifting right by 8 bits)
+ * Finally, we add one to round up. Because 256 isn't an exact multiple of
+ * 3, we'll underestimate near each multiple of 12K. This is actually more
+ * accurate as we have 4K - 1 of wiggle room that we can fit into the last
+ * segment. For our purposes this is accurate out to 1M which is orders of
+ * magnitude greater than our largest possible GSO size.
+ *
+ * This would then be implemented as:
+ * return (((size >> 12) * 85) >> 8) + 1;
+ *
+ * Since multiplication and division are commutative, we can reorder
+ * operations into:
+ * return ((size * 85) >> 20) + 1;
*/
static inline unsigned int i40e_txd_use_count(unsigned int size)
{
- const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED;
- const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max;
- unsigned int adjust = ~(u32)0;
-
- /* if we rounded up on the reciprocal pull down the adjustment */
- if ((max * reciprocal) > adjust)
- adjust = ~(u32)(reciprocal - 1);
-
- return (u32)((((u64)size * reciprocal) + adjust) >> 32);
+ return ((size * 85) >> 20) + 1;
}
/* Tx Descriptors needed, worst case */
@@ -309,7 +320,6 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */
u8 packet_stride;
-#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 97f96e0d9c4c..c85e8a31c072 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -187,47 +187,59 @@ struct i40e_link_status {
#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;
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;
-};
-
+ u64 phy_types;
+};
+
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+ BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+ I40E_PHY_TYPE_OFFSET)
#define I40E_HW_CAP_MAX_GPIO 30
/* Capabilities of a PF or a VF or the whole device */
struct i40e_hw_capabilities {
@@ -237,6 +249,10 @@ struct i40e_hw_capabilities {
#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3
u32 management_mode;
+ u32 mng_protocols_over_mctp;
+#define I40E_MNG_PROTOCOL_PLDM 0x2
+#define I40E_MNG_PROTOCOL_OEM_COMMANDS 0x4
+#define I40E_MNG_PROTOCOL_NCSI 0x8
u32 npar_enable;
u32 os2bmc;
u32 valid_functions;
@@ -348,6 +364,7 @@ enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_WRITING,
I40E_NVMUPD_STATE_INIT_WAIT,
I40E_NVMUPD_STATE_WRITE_WAIT,
+ I40E_NVMUPD_STATE_ERROR
};
/* nvm_access definition and its masks/shifts need to be accessible to
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
index bd691ad86673..fc374f833aa9 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
@@ -162,6 +162,10 @@ struct i40e_virtchnl_vsi_resource {
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000
#define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00100000
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+ I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+ I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
struct i40e_virtchnl_vf_resource {
u16 num_vsis;
u16 num_queue_pairs;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index c5fd724313c7..fffe4cf2c20b 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -107,7 +107,8 @@ struct i40e_q_vector {
int v_idx; /* vector index in list */
char name[IFNAMSIZ + 9];
bool arm_wb_state;
- cpumask_var_t affinity_mask;
+ cpumask_t affinity_mask;
+ struct irq_affinity_notify affinity_notify;
};
/* Helper macros to switch between ints/sec and what the register uses.
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index a9940154eead..272d600c1ed0 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -85,6 +85,14 @@ static int i40evf_get_settings(struct net_device *netdev,
case I40E_LINK_SPEED_40GB:
ethtool_cmd_speed_set(ecmd, SPEED_40000);
break;
+ case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+ ethtool_cmd_speed_set(ecmd, SPEED_25000);
+#else
+ netdev_info(netdev,
+ "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+ break;
case I40E_LINK_SPEED_20GB:
ethtool_cmd_speed_set(ecmd, SPEED_20000);
break;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 14372810fc27..c0fc53361800 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -38,7 +38,7 @@ static const char i40evf_driver_string[] =
#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 25
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) \
@@ -207,6 +207,9 @@ static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)
{
struct i40e_hw *hw = &adapter->hw;
+ if (!adapter->msix_entries)
+ return;
+
wr32(hw, I40E_VFINT_DYN_CTL01, 0);
/* read flush */
@@ -496,6 +499,33 @@ static void i40evf_netpoll(struct net_device *netdev)
#endif
/**
+ * i40evf_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
+ const cpumask_t *mask)
+{
+ struct i40e_q_vector *q_vector =
+ container_of(notify, struct i40e_q_vector, affinity_notify);
+
+ q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40evf_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40evf_irq_affinity_release(struct kref *ref) {}
+
+/**
* i40evf_request_traffic_irqs - Initialize MSI-X interrupts
* @adapter: board private structure
*
@@ -507,6 +537,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
{
int vector, err, q_vectors;
int rx_int_idx = 0, tx_int_idx = 0;
+ int irq_num;
i40evf_irq_disable(adapter);
/* Decrement for Other and TCP Timer vectors */
@@ -514,6 +545,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
for (vector = 0; vector < q_vectors; vector++) {
struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
if (q_vector->tx.ring && q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -532,21 +564,23 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
/* skip this unused q_vector */
continue;
}
- err = request_irq(
- adapter->msix_entries[vector + NONQ_VECS].vector,
- i40evf_msix_clean_rings,
- 0,
- q_vector->name,
- q_vector);
+ err = request_irq(irq_num,
+ i40evf_msix_clean_rings,
+ 0,
+ q_vector->name,
+ q_vector);
if (err) {
dev_info(&adapter->pdev->dev,
"Request_irq failed, error: %d\n", err);
goto free_queue_irqs;
}
+ /* register for affinity change notifications */
+ q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
+ q_vector->affinity_notify.release =
+ i40evf_irq_affinity_release;
+ irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
/* assign the mask for this irq */
- irq_set_affinity_hint(
- adapter->msix_entries[vector + NONQ_VECS].vector,
- q_vector->affinity_mask);
+ irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
}
return 0;
@@ -554,11 +588,10 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
free_queue_irqs:
while (vector) {
vector--;
- irq_set_affinity_hint(
- adapter->msix_entries[vector + NONQ_VECS].vector,
- NULL);
- free_irq(adapter->msix_entries[vector + NONQ_VECS].vector,
- &adapter->q_vectors[vector]);
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+ irq_set_affinity_notifier(irq_num, NULL);
+ irq_set_affinity_hint(irq_num, NULL);
+ free_irq(irq_num, &adapter->q_vectors[vector]);
}
return err;
}
@@ -599,16 +632,18 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
**/
static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
{
- int i;
- int q_vectors;
+ int vector, irq_num, q_vectors;
+
+ if (!adapter->msix_entries)
+ return;
q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- for (i = 0; i < q_vectors; i++) {
- irq_set_affinity_hint(adapter->msix_entries[i+1].vector,
- NULL);
- free_irq(adapter->msix_entries[i+1].vector,
- &adapter->q_vectors[i]);
+ for (vector = 0; vector < q_vectors; vector++) {
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+ irq_set_affinity_notifier(irq_num, NULL);
+ irq_set_affinity_hint(irq_num, NULL);
+ free_irq(irq_num, &adapter->q_vectors[vector]);
}
}
@@ -622,6 +657,9 @@ static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ if (!adapter->msix_entries)
+ return;
+
free_irq(adapter->msix_entries[0].vector, netdev);
}
@@ -1396,6 +1434,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
int q_idx, num_q_vectors;
int napi_vectors;
+ if (!adapter->q_vectors)
+ return;
+
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
napi_vectors = adapter->num_active_queues;
@@ -1405,6 +1446,7 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
netif_napi_del(&q_vector->napi);
}
kfree(adapter->q_vectors);
+ adapter->q_vectors = NULL;
}
/**
@@ -1414,6 +1456,9 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
**/
void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
{
+ if (!adapter->msix_entries)
+ return;
+
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
@@ -1664,6 +1709,49 @@ restart_watchdog:
schedule_work(&adapter->adminq_task);
}
+static void i40evf_disable_vf(struct i40evf_adapter *adapter)
+{
+ struct i40evf_mac_filter *f, *ftmp;
+ struct i40evf_vlan_filter *fv, *fvtmp;
+
+ adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+
+ if (netif_running(adapter->netdev)) {
+ set_bit(__I40E_DOWN, &adapter->vsi.state);
+ netif_carrier_off(adapter->netdev);
+ netif_tx_disable(adapter->netdev);
+ adapter->link_up = false;
+ i40evf_napi_disable_all(adapter);
+ i40evf_irq_disable(adapter);
+ i40evf_free_traffic_irqs(adapter);
+ i40evf_free_all_tx_resources(adapter);
+ i40evf_free_all_rx_resources(adapter);
+ }
+
+ /* Delete all of the filters, both MAC and VLAN. */
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+ list_del(&f->list);
+ kfree(f);
+ }
+
+ list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) {
+ list_del(&fv->list);
+ kfree(fv);
+ }
+
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_queues(adapter);
+ i40evf_free_q_vectors(adapter);
+ kfree(adapter->vf_res);
+ i40evf_shutdown_adminq(&adapter->hw);
+ adapter->netdev->flags &= ~IFF_UP;
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+ adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+ adapter->state = __I40EVF_DOWN;
+ dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
+}
+
#define I40EVF_RESET_WAIT_MS 10
#define I40EVF_RESET_WAIT_COUNT 500
/**
@@ -1717,60 +1805,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++) {
+ /* sleep first to make sure a minimum wait time is met */
+ msleep(I40EVF_RESET_WAIT_MS);
+
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);
}
+
pci_set_master(adapter->pdev);
- /* extra wait to make sure minimum wait is met */
- msleep(I40EVF_RESET_WAIT_MS);
- if (i == I40EVF_RESET_WAIT_COUNT) {
- struct i40evf_mac_filter *ftmp;
- struct i40evf_vlan_filter *fv, *fvtmp;
- /* reset never finished */
+ if (i == I40EVF_RESET_WAIT_COUNT) {
dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
reg_val);
- adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
-
- if (netif_running(adapter->netdev)) {
- set_bit(__I40E_DOWN, &adapter->vsi.state);
- netif_carrier_off(netdev);
- netif_tx_disable(netdev);
- adapter->link_up = false;
- i40evf_napi_disable_all(adapter);
- i40evf_irq_disable(adapter);
- i40evf_free_traffic_irqs(adapter);
- i40evf_free_all_tx_resources(adapter);
- i40evf_free_all_rx_resources(adapter);
- }
-
- /* Delete all of the filters, both MAC and VLAN. */
- list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list,
- list) {
- list_del(&f->list);
- kfree(f);
- }
-
- list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list,
- list) {
- list_del(&fv->list);
- kfree(fv);
- }
-
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
- i40evf_free_queues(adapter);
- i40evf_free_q_vectors(adapter);
- kfree(adapter->vf_res);
- i40evf_shutdown_adminq(hw);
- adapter->netdev->flags &= ~IFF_UP;
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
- adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
- adapter->state = __I40EVF_DOWN;
- dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
+ i40evf_disable_vf(adapter);
return; /* Do not attempt to reinit. It's dead, Jim. */
}
@@ -2133,10 +2182,6 @@ static struct net_device_stats *i40evf_get_stats(struct net_device *netdev)
static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
- if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
- return -EINVAL;
netdev->mtu = new_mtu;
adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
@@ -2145,6 +2190,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
+/**
+ * i40evf_features_check - Validate encapsulated packet conforms to limits
+ * @skb: skb buff
+ * @netdev: This physical port's netdev
+ * @features: Offload features that the stack believes apply
+ **/
+static netdev_features_t i40evf_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ size_t len;
+
+ /* No point in doing any of this if neither checksum nor GSO are
+ * being requested for this frame. We can rule out both by just
+ * checking for CHECKSUM_PARTIAL
+ */
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return features;
+
+ /* We cannot support GSO if the MSS is going to be less than
+ * 64 bytes. If it is then we need to drop support for GSO.
+ */
+ if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+ features &= ~NETIF_F_GSO_MASK;
+
+ /* MACLEN can support at most 63 words */
+ len = skb_network_header(skb) - skb->data;
+ if (len & ~(63 * 2))
+ goto out_err;
+
+ /* IPLEN and EIPLEN can support at most 127 dwords */
+ len = skb_transport_header(skb) - skb_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+
+ if (skb->encapsulation) {
+ /* L4TUNLEN can support 127 words */
+ len = skb_inner_network_header(skb) - skb_transport_header(skb);
+ if (len & ~(127 * 2))
+ goto out_err;
+
+ /* IPLEN can support at most 127 dwords */
+ len = skb_inner_transport_header(skb) -
+ skb_inner_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+ }
+
+ /* No need to validate L4LEN as TCP is the only protocol with a
+ * a flexible value and we support all possible values supported
+ * by TCP, which is at most 15 dwords
+ */
+
+ return features;
+out_err:
+ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+}
+
#define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\
NETIF_F_HW_VLAN_CTAG_RX |\
NETIF_F_HW_VLAN_CTAG_FILTER)
@@ -2179,6 +2282,7 @@ 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,
+ .ndo_features_check = i40evf_features_check,
.ndo_fix_features = i40evf_fix_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = i40evf_netpoll,
@@ -2424,6 +2528,10 @@ static void i40evf_init_task(struct work_struct *work)
i40evf_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
+ /* MTU range: 68 - 9710 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN);
+
if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
adapter->hw.mac.addr);
@@ -2764,12 +2872,10 @@ static void i40evf_remove(struct pci_dev *pdev)
msleep(50);
}
- if (adapter->msix_entries) {
- i40evf_misc_irq_disable(adapter);
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
- i40evf_free_q_vectors(adapter);
- }
+ i40evf_misc_irq_disable(adapter);
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_q_vectors(adapter);
if (adapter->watchdog_timer.function)
del_timer_sync(&adapter->watchdog_timer);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index ddf478d6322b..2059a8e88908 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -836,6 +836,9 @@ static void i40evf_print_link_message(struct i40evf_adapter *adapter)
case I40E_LINK_SPEED_40GB:
speed = "40 G";
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = "25 G";
+ break;
case I40E_LINK_SPEED_20GB:
speed = "20 G";
break;
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 2688180a7acd..8aee314332a8 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -357,7 +357,8 @@
#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
-#define MAX_JUMBO_FRAME_SIZE 0x2600
+#define MAX_JUMBO_FRAME_SIZE 0x2600
+#define MAX_STD_JUMBO_FRAME_SIZE 9216
/* PBA constants */
#define E1000_PBA_34K 0x0022
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 9affd7c198bd..cae24a8ccf47 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2468,6 +2468,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 68 - 9216 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
/* before reading the NVM, reset the controller to put the device in a
@@ -5412,17 +5416,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
struct pci_dev *pdev = adapter->pdev;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
- if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- dev_err(&pdev->dev, "Invalid MTU setting\n");
- return -EINVAL;
- }
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9238
- if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
- dev_err(&pdev->dev, "MTU > 9216 not supported.\n");
- return -EINVAL;
- }
-
/* adjust max frame to be at least the size of a standard frame */
if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index a7895c4cbcc3..c30eea8399a7 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -226,7 +226,7 @@ static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
return 0;
}
-static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb)
+static int igb_ptp_adjfine_82580(struct ptp_clock_info *ptp, long scaled_ppm)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
@@ -235,13 +235,13 @@ static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb)
u64 rate;
u32 inca;
- if (ppb < 0) {
+ if (scaled_ppm < 0) {
neg_adj = 1;
- ppb = -ppb;
+ scaled_ppm = -scaled_ppm;
}
- rate = ppb;
- rate <<= 26;
- rate = div_u64(rate, 1953125);
+ rate = scaled_ppm;
+ rate <<= 13;
+ rate = div_u64(rate, 15625);
inca = rate & INCVALUE_MASK;
if (neg_adj)
@@ -1103,7 +1103,7 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.max_adj = 62499999;
adapter->ptp_caps.n_ext_ts = 0;
adapter->ptp_caps.pps = 0;
- adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
+ adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;
adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
@@ -1131,7 +1131,7 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.n_pins = IGB_N_SDP;
adapter->ptp_caps.pps = 1;
adapter->ptp_caps.pin_config = adapter->sdp_config;
- adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
+ adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;
adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210;
adapter->ptp_caps.gettime64 = igb_ptp_gettime_i210;
adapter->ptp_caps.settime64 = igb_ptp_settime_i210;
diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h
index ee1ef08d7fc4..f1789d192e24 100644
--- a/drivers/net/ethernet/intel/igbvf/defines.h
+++ b/drivers/net/ethernet/intel/igbvf/defines.h
@@ -85,7 +85,8 @@
#define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
#define E1000_TXD_STAT_DD 0x00000001 /* Desc Done */
-#define MAX_JUMBO_FRAME_SIZE 0x3F00
+#define MAX_JUMBO_FRAME_SIZE 0x3F00
+#define MAX_STD_JUMBO_FRAME_SIZE 9216
/* 802.1q VLAN Packet Size */
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 7dff7f6239cd..839ba110f7fb 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2360,16 +2360,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu)
struct igbvf_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- if (new_mtu < 68 || new_mtu > INT_MAX - ETH_HLEN - ETH_FCS_LEN ||
- max_frame > MAX_JUMBO_FRAME_SIZE)
- return -EINVAL;
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
- if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
- dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
- return -EINVAL;
- }
-
while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
usleep_range(1000, 2000);
/* igbvf_down has a dependency on max_frame_size */
@@ -2790,6 +2780,10 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_TX;
+ /* MTU range: 68 - 9216 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
/*reset the controller to put the device in a known good state */
err = hw->mac.ops.reset_hw(hw);
if (err) {
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 31f91459312f..5826b1ddedcf 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -487,6 +487,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features |= NETIF_F_HIGHDMA;
}
+ /* MTU range: 68 - 16114 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN;
+
/* make sure the EEPROM is good */
if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
@@ -1619,18 +1623,6 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
- int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
-
- /* MTU < 68 is an error for IPv4 traffic, just don't allow it */
- if ((new_mtu < 68) ||
- (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
- netif_err(adapter, probe, adapter->netdev,
- "Invalid MTU setting %d\n", new_mtu);
- return -EINVAL;
- }
-
- if (old_max_frame == max_frame)
- return 0;
if (netif_running(netdev))
ixgb_down(adapter, true);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index b06e32d0d22a..ef81c3d8c295 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -1027,4 +1027,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_ring *tx_ring);
u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter);
void ixgbe_store_reta(struct ixgbe_adapter *adapter);
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index fb51be74dd4c..805ab319e578 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -367,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
}
/* Negotiate the fc mode to use */
- ixgbe_fc_autoneg(hw);
+ hw->mac.ops.fc_autoneg(hw);
/* Disable any previous flow control settings */
fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -1179,6 +1179,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = {
.get_link_capabilities = &ixgbe_get_link_capabilities_82598,
.led_on = &ixgbe_led_on_generic,
.led_off = &ixgbe_led_off_generic,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.blink_led_start = &ixgbe_blink_led_start_generic,
.blink_led_stop = &ixgbe_blink_led_stop_generic,
.set_rar = &ixgbe_set_rar_generic,
@@ -1193,6 +1194,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = {
.set_vfta = &ixgbe_set_vfta_82598,
.fc_enable = &ixgbe_fc_enable_82598,
.setup_fc = ixgbe_setup_fc_generic,
+ .fc_autoneg = ixgbe_fc_autoneg,
.set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 63b25006ac90..e00aaeb91827 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -2204,6 +2204,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = {
.get_link_capabilities = &ixgbe_get_link_capabilities_82599,
.led_on = &ixgbe_led_on_generic,
.led_off = &ixgbe_led_off_generic,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.blink_led_start = &ixgbe_blink_led_start_generic,
.blink_led_stop = &ixgbe_blink_led_stop_generic,
.set_rar = &ixgbe_set_rar_generic,
@@ -2219,6 +2220,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = {
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
.setup_fc = ixgbe_setup_fc_generic,
+ .fc_autoneg = ixgbe_fc_autoneg,
.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = &ixgbe_setup_sfp_modules_82599,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 77d3039283f6..8832df3eba25 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -298,10 +298,12 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
IXGBE_WRITE_FLUSH(hw);
- /* Setup flow control */
- ret_val = hw->mac.ops.setup_fc(hw);
- if (ret_val)
- return ret_val;
+ /* Setup flow control if method for doing so */
+ if (hw->mac.ops.setup_fc) {
+ ret_val = hw->mac.ops.setup_fc(hw);
+ if (ret_val)
+ return ret_val;
+ }
/* Cashe bit indicating need for crosstalk fix */
switch (hw->mac.type) {
@@ -390,6 +392,9 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
status = hw->mac.ops.start_hw(hw);
}
+ /* Initialize the LED link active for LED blink support */
+ hw->mac.ops.init_led_link_act(hw);
+
return status;
}
@@ -773,6 +778,49 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_init_led_link_act_generic - Store the LED index link/activity.
+ * @hw: pointer to hardware structure
+ *
+ * Store the index for the link active LED. This will be used to support
+ * blinking the LED.
+ **/
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ u32 led_reg, led_mode;
+ u16 i;
+
+ led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ /* Get LED link active from the LEDCTL register */
+ for (i = 0; i < 4; i++) {
+ led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
+
+ if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
+ IXGBE_LED_LINK_ACTIVE) {
+ mac->led_link_act = i;
+ return 0;
+ }
+ }
+
+ /* If LEDCTL register does not have the LED link active set, then use
+ * known MAC defaults.
+ */
+ switch (hw->mac.type) {
+ case ixgbe_mac_x550em_a:
+ mac->led_link_act = 0;
+ break;
+ case ixgbe_mac_X550EM_x:
+ mac->led_link_act = 1;
+ break;
+ default:
+ mac->led_link_act = 2;
+ }
+
+ return 0;
+}
+
+/**
* ixgbe_led_on_generic - Turns on the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn on
@@ -2127,7 +2175,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
}
/* Negotiate the fc mode to use */
- ixgbe_fc_autoneg(hw);
+ hw->mac.ops.fc_autoneg(hw);
/* Disable any previous flow control settings */
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
@@ -2231,8 +2279,8 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
* Find the intersection between advertised settings and link partner's
* advertised settings
**/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
{
if ((!(adv_reg)) || (!(lp_reg)))
return IXGBE_ERR_FC_NOT_NEGOTIATED;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 6d4c260d0cbd..5b3e3c65927e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -49,6 +49,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw);
s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index f49f80380aa5..fd192bf29b26 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2225,11 +2225,11 @@ static int ixgbe_set_phys_id(struct net_device *netdev,
return 2;
case ETHTOOL_ID_ON:
- hw->mac.ops.led_on(hw, hw->bus.func);
+ hw->mac.ops.led_on(hw, hw->mac.led_link_act);
break;
case ETHTOOL_ID_OFF:
- hw->mac.ops.led_off(hw, hw->bus.func);
+ hw->mac.ops.led_off(hw, hw->mac.led_link_act);
break;
case ETHTOOL_ID_INACTIVE:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index fee1f2918ead..1e2f39ebd824 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -54,6 +54,7 @@
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
+#include <net/vxlan.h>
#include "ixgbe.h"
#include "ixgbe_common.h"
@@ -3070,6 +3071,9 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
return;
}
+ if (!adapter->msix_entries)
+ return;
+
for (vector = 0; vector < adapter->num_q_vectors; vector++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
struct msix_entry *entry = &adapter->msix_entries[vector];
@@ -5012,24 +5016,23 @@ fwd_queue_err:
return err;
}
-static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+static int ixgbe_upper_dev_walk(struct net_device *upper, void *data)
{
- struct net_device *upper;
- struct list_head *iter;
- int err;
+ if (netif_is_macvlan(upper)) {
+ struct macvlan_dev *dfwd = netdev_priv(upper);
+ struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
- netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
- if (netif_is_macvlan(upper)) {
- struct macvlan_dev *dfwd = netdev_priv(upper);
- struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
-
- if (dfwd->fwd_priv) {
- err = ixgbe_fwd_ring_up(upper, vadapter);
- if (err)
- continue;
- }
- }
+ if (dfwd->fwd_priv)
+ ixgbe_fwd_ring_up(upper, vadapter);
}
+
+ return 0;
+}
+
+static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+{
+ netdev_walk_all_upper_dev_rcu(adapter->netdev,
+ ixgbe_upper_dev_walk, NULL);
}
static void ixgbe_configure(struct ixgbe_adapter *adapter)
@@ -5448,12 +5451,25 @@ static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
spin_unlock(&adapter->fdir_perfect_lock);
}
+static int ixgbe_disable_macvlan(struct net_device *upper, void *data)
+{
+ if (netif_is_macvlan(upper)) {
+ struct macvlan_dev *vlan = netdev_priv(upper);
+
+ if (vlan->fwd_priv) {
+ netif_tx_stop_all_queues(upper);
+ netif_carrier_off(upper);
+ netif_tx_disable(upper);
+ }
+ }
+
+ return 0;
+}
+
void ixgbe_down(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
- struct net_device *upper;
- struct list_head *iter;
int i;
/* signal that we are down to the interrupt handler */
@@ -5477,17 +5493,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
netif_tx_disable(netdev);
/* disable any upper devices */
- netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
- if (netif_is_macvlan(upper)) {
- struct macvlan_dev *vlan = netdev_priv(upper);
-
- if (vlan->fwd_priv) {
- netif_tx_stop_all_queues(upper);
- netif_carrier_off(upper);
- netif_tx_disable(upper);
- }
- }
- }
+ netdev_walk_all_upper_dev_rcu(adapter->netdev,
+ ixgbe_disable_macvlan, NULL);
ixgbe_irq_disable(adapter);
@@ -5618,7 +5625,8 @@ static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
+static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
+ const struct ixgbe_info *ii)
{
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -5634,6 +5642,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_device_id = pdev->subsystem_device;
+ /* get_invariants needs the device IDs */
+ ii->get_invariants(hw);
+
/* Set common capability flags and settings */
rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
adapter->ring_feature[RING_F_RSS].limit = rss;
@@ -6049,11 +6060,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
- /* MTU < 68 is an error and causes problems on some kernels */
- if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
- return -EINVAL;
/*
* For 82599EB we cannot allow legacy VFs to enable their receive
@@ -6062,7 +6068,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
*/
if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
(adapter->hw.mac.type == ixgbe_mac_82599EB) &&
- (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+ (new_mtu > ETH_DATA_LEN))
e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -6728,6 +6734,18 @@ static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
#endif
}
+static int ixgbe_enable_macvlan(struct net_device *upper, void *data)
+{
+ if (netif_is_macvlan(upper)) {
+ struct macvlan_dev *vlan = netdev_priv(upper);
+
+ if (vlan->fwd_priv)
+ netif_tx_wake_all_queues(upper);
+ }
+
+ return 0;
+}
+
/**
* ixgbe_watchdog_link_is_up - update netif_carrier status and
* print link up message
@@ -6737,8 +6755,6 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
- struct net_device *upper;
- struct list_head *iter;
u32 link_speed = adapter->link_speed;
const char *speed_str;
bool flow_rx, flow_tx;
@@ -6809,14 +6825,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
/* enable any upper devices */
rtnl_lock();
- netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
- if (netif_is_macvlan(upper)) {
- struct macvlan_dev *vlan = netdev_priv(upper);
-
- if (vlan->fwd_priv)
- netif_tx_wake_all_queues(upper);
- }
- }
+ netdev_walk_all_upper_dev_rcu(adapter->netdev,
+ ixgbe_enable_macvlan, NULL);
rtnl_unlock();
/* update the default user priority for VFs */
@@ -7655,11 +7665,17 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
/* snag network header to get L4 type and address */
skb = first->skb;
hdr.network = skb_network_header(skb);
+ if (unlikely(hdr.network <= skb->data))
+ return;
if (skb->encapsulation &&
first->protocol == htons(ETH_P_IP) &&
- hdr.ipv4->protocol != IPPROTO_UDP) {
+ hdr.ipv4->protocol == IPPROTO_UDP) {
struct ixgbe_adapter *adapter = q_vector->adapter;
+ if (unlikely(skb_tail_pointer(skb) < hdr.network +
+ VXLAN_HEADROOM))
+ return;
+
/* verify the port is recognized as VXLAN */
if (adapter->vxlan_port &&
udp_hdr(skb)->dest == adapter->vxlan_port)
@@ -7670,6 +7686,12 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
hdr.network = skb_inner_network_header(skb);
}
+ /* Make sure we have at least [minimum IPv4 header + TCP]
+ * or [IPv6 header] bytes
+ */
+ if (unlikely(skb_tail_pointer(skb) < hdr.network + 40))
+ return;
+
/* Currently only IPv4/IPv6 with TCP is supported */
switch (hdr.ipv4->version) {
case IPVERSION:
@@ -7689,6 +7711,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
if (l4_proto != IPPROTO_TCP)
return;
+ if (unlikely(skb_tail_pointer(skb) < hdr.network +
+ hlen + sizeof(struct tcphdr)))
+ return;
+
th = (struct tcphdr *)(hdr.network + hlen);
/* skip this packet since the socket is closing */
@@ -8354,12 +8380,38 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
}
#ifdef CONFIG_NET_CLS_ACT
+struct upper_walk_data {
+ struct ixgbe_adapter *adapter;
+ u64 action;
+ int ifindex;
+ u8 queue;
+};
+
+static int get_macvlan_queue(struct net_device *upper, void *_data)
+{
+ if (netif_is_macvlan(upper)) {
+ struct macvlan_dev *dfwd = netdev_priv(upper);
+ struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+ struct upper_walk_data *data = _data;
+ struct ixgbe_adapter *adapter = data->adapter;
+ int ifindex = data->ifindex;
+
+ if (vadapter && vadapter->netdev->ifindex == ifindex) {
+ data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
+ data->action = data->queue;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
u8 *queue, u64 *action)
{
unsigned int num_vfs = adapter->num_vfs, vf;
+ struct upper_walk_data data;
struct net_device *upper;
- struct list_head *iter;
/* redirect to a SRIOV VF */
for (vf = 0; vf < num_vfs; ++vf) {
@@ -8377,17 +8429,16 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
}
/* redirect to a offloaded macvlan netdev */
- netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
- if (netif_is_macvlan(upper)) {
- struct macvlan_dev *dfwd = netdev_priv(upper);
- struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
-
- if (vadapter && vadapter->netdev->ifindex == ifindex) {
- *queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
- *action = *queue;
- return 0;
- }
- }
+ data.adapter = adapter;
+ data.ifindex = ifindex;
+ data.action = 0;
+ data.queue = 0;
+ if (netdev_walk_all_upper_dev_rcu(adapter->netdev,
+ get_macvlan_queue, &data)) {
+ *action = data.action;
+ *queue = data.queue;
+
+ return 0;
}
return -EINVAL;
@@ -8414,7 +8465,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,
}
/* Redirect to a VF or a offloaded macvlan */
- if (is_tcf_mirred_redirect(a)) {
+ if (is_tcf_mirred_egress_redirect(a)) {
int ifindex = tcf_mirred_ifindex(a);
err = handle_redirect_action(adapter, ifindex, queue,
@@ -9481,6 +9532,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->mac.ops = *ii->mac_ops;
hw->mac.type = ii->mac;
hw->mvals = ii->mvals;
+ if (ii->link_ops)
+ hw->link.ops = *ii->link_ops;
/* EEPROM */
hw->eeprom.ops = *ii->eeprom_ops;
@@ -9504,10 +9557,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->phy.mdio.mdio_read = ixgbe_mdio_read;
hw->phy.mdio.mdio_write = ixgbe_mdio_write;
- ii->get_invariants(hw);
-
/* setup the private structure */
- err = ixgbe_sw_init(adapter);
+ err = ixgbe_sw_init(adapter, ii);
if (err)
goto err_sw_init;
@@ -9616,6 +9667,10 @@ skip_sriov:
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
+ /* MTU range: 68 - 9710 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
#ifdef CONFIG_IXGBE_DCB
if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
netdev->dcbnl_ops = &dcbnl_ops;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 021ab9b89c71..3b8362085f57 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -109,8 +109,8 @@ static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)
*
* Returns an error code on error.
*/
-static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 *val, bool lock)
+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;
@@ -178,36 +178,6 @@ fail:
}
/**
- * 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
@@ -217,8 +187,8 @@ s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
*
* Returns an error code on error.
*/
-static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 val, bool lock)
+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;
@@ -273,33 +243,39 @@ 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
+ * ixgbe_probe_phy - Probe a single address for a PHY
+ * @hw: pointer to hardware structure
+ * @phy_addr: PHY address to probe
*
- * Returns an error code on error.
- */
-s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
- u8 addr, u16 reg, u16 val)
+ * Returns true if PHY found
+ **/
+static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr)
{
- return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
-}
+ u16 ext_ability = 0;
-/**
- * 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);
+ hw->phy.mdio.prtad = phy_addr;
+ if (mdio45_probe(&hw->phy.mdio, phy_addr) != 0)
+ return false;
+
+ if (ixgbe_get_phy_id(hw))
+ return false;
+
+ hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
+
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ hw->phy.ops.read_reg(hw,
+ MDIO_PMA_EXTABLE,
+ MDIO_MMD_PMAPMD,
+ &ext_ability);
+ if (ext_ability &
+ (MDIO_PMA_EXTABLE_10GBT |
+ MDIO_PMA_EXTABLE_1000BT))
+ hw->phy.type = ixgbe_phy_cu_unknown;
+ else
+ hw->phy.type = ixgbe_phy_generic;
+ }
+
+ return true;
}
/**
@@ -311,7 +287,7 @@ s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
{
u32 phy_addr;
- u16 ext_ability = 0;
+ u32 status = IXGBE_ERR_PHY_ADDR_INVALID;
if (!hw->phy.phy_semaphore_mask) {
if (hw->bus.lan_id)
@@ -320,37 +296,34 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
}
- if (hw->phy.type == ixgbe_phy_unknown) {
- for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
- hw->phy.mdio.prtad = phy_addr;
- if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) {
- ixgbe_get_phy_id(hw);
- hw->phy.type =
- ixgbe_get_phy_type_from_id(hw->phy.id);
-
- if (hw->phy.type == ixgbe_phy_unknown) {
- hw->phy.ops.read_reg(hw,
- MDIO_PMA_EXTABLE,
- MDIO_MMD_PMAPMD,
- &ext_ability);
- if (ext_ability &
- (MDIO_PMA_EXTABLE_10GBT |
- MDIO_PMA_EXTABLE_1000BT))
- hw->phy.type =
- ixgbe_phy_cu_unknown;
- else
- hw->phy.type =
- ixgbe_phy_generic;
- }
+ if (hw->phy.type != ixgbe_phy_unknown)
+ return 0;
- return 0;
- }
+ if (hw->phy.nw_mng_if_sel) {
+ phy_addr = (hw->phy.nw_mng_if_sel &
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
+ if (ixgbe_probe_phy(hw, phy_addr))
+ return 0;
+ else
+ return IXGBE_ERR_PHY_ADDR_INVALID;
+ }
+
+ for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
+ if (ixgbe_probe_phy(hw, phy_addr)) {
+ status = 0;
+ break;
}
- /* indicate no PHY found */
- hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
- return IXGBE_ERR_PHY_ADDR_INVALID;
}
- return 0;
+
+ /* Certain media types do not have a phy so an address will not
+ * be found and the code will take this path. Caller has to
+ * decide if it is an error or not.
+ */
+ if (status)
+ hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
+
+ return status;
}
/**
@@ -416,7 +389,8 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
- case X550_PHY_ID:
+ case X550_PHY_ID2:
+ case X550_PHY_ID3:
case X540_PHY_ID:
phy_type = ixgbe_phy_aq;
break;
@@ -427,6 +401,7 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
phy_type = ixgbe_phy_nl;
break;
case X557_PHY_ID:
+ case X557_PHY_ID2:
phy_type = ixgbe_phy_x550em_ext_t;
break;
default:
@@ -477,8 +452,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
*/
for (i = 0; i < 30; i++) {
msleep(100);
- hw->phy.ops.read_reg(hw, MDIO_CTRL1,
- MDIO_MMD_PHYXS, &ctrl);
+ hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &ctrl);
if (!(ctrl & MDIO_CTRL1_RESET)) {
udelay(2);
break;
@@ -705,53 +679,52 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
- if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
- /* Set or unset auto-negotiation 10G advertisement */
- hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
- MDIO_MMD_AN,
- &autoneg_reg);
+ /* Set or unset auto-negotiation 10G advertisement */
+ hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, &autoneg_reg);
- autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
- autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
-
- hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
- MDIO_MMD_AN,
- autoneg_reg);
- }
+ autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_10GB_FULL))
+ autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
- if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
- /* Set or unset auto-negotiation 1G advertisement */
- hw->phy.ops.read_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- MDIO_MMD_AN,
- &autoneg_reg);
+ hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, autoneg_reg);
- autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
- autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
+ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ MDIO_MMD_AN, &autoneg_reg);
- hw->phy.ops.write_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- MDIO_MMD_AN,
- autoneg_reg);
+ if (hw->mac.type == ixgbe_mac_X550) {
+ /* Set or unset auto-negotiation 5G advertisement */
+ autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_5GB_FULL))
+ autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
+
+ /* Set or unset auto-negotiation 2.5G advertisement */
+ autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised &
+ IXGBE_LINK_SPEED_2_5GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_2_5GB_FULL))
+ autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
}
- if (speed & IXGBE_LINK_SPEED_100_FULL) {
- /* Set or unset auto-negotiation 100M advertisement */
- hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN,
- &autoneg_reg);
+ /* Set or unset auto-negotiation 1G advertisement */
+ autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_1GB_FULL))
+ autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
- autoneg_reg &= ~(ADVERTISE_100FULL |
- ADVERTISE_100HALF);
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
- autoneg_reg |= ADVERTISE_100FULL;
+ hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ MDIO_MMD_AN, autoneg_reg);
- hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN,
- autoneg_reg);
- }
+ /* Set or unset auto-negotiation 100M advertisement */
+ hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
+
+ autoneg_reg &= ~(ADVERTISE_100FULL | ADVERTISE_100HALF);
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) &&
+ (speed & IXGBE_LINK_SPEED_100_FULL))
+ autoneg_reg |= ADVERTISE_100FULL;
+
+ hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
/* Blocked by MNG FW so don't reset PHY */
if (ixgbe_check_reset_blocked(hw))
@@ -830,6 +803,7 @@ static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
break;
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_x550em_a:
hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
break;
default:
@@ -2396,9 +2370,7 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
if (!on && ixgbe_mng_present(hw))
return 0;
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- &reg);
+ status = hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, &reg);
if (status)
return status;
@@ -2410,8 +2382,6 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
}
- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- reg);
+ status = hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, reg);
return status;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index cc735ec3e045..ecf05f838fc5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -195,12 +195,8 @@ s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 *sff8472_data);
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);
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 *val, bool lock);
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 val, bool lock);
#endif /* _IXGBE_PHY_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 31d82e3abac8..cf21273db201 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -874,19 +874,13 @@ struct ixgbe_thermal_sensor_data {
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB 0x4 /* 1Gb/s */
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB 0x6 /* 10Gb/s */
-#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */
#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */
#define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */
-#define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */
-#define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/
#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/
#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/
#define IXGBE_MII_2_5GBASE_T_ADVERTISE 0x0400
#define IXGBE_MII_5GBASE_T_ADVERTISE 0x0800
-#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */
-#define IXGBE_MII_100BASE_T_ADVERTISE_HALF 0x0080 /* half duplex, bit:7 */
#define IXGBE_MII_RESTART 0x200
-#define IXGBE_MII_AUTONEG_COMPLETE 0x20
#define IXGBE_MII_AUTONEG_LINK_UP 0x04
#define IXGBE_MII_AUTONEG_REG 0x0
@@ -1320,30 +1314,20 @@ struct ixgbe_thermal_sensor_data {
/* MDIO definitions */
#define IXGBE_MDIO_ZERO_DEV_TYPE 0x0
-#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
#define IXGBE_MDIO_PCS_DEV_TYPE 0x3
-#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
-#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
#define IXGBE_TWINAX_DEV 1
#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0 - 10G, 1 - 1G */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010
-#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */
-#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */
#define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT 0xC800 /* AUTO_NEG Vendor Status Reg */
#define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM 0xCC00 /* AUTO_NEG Vendor TX Reg */
#define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */
#define IXGBE_MDIO_AUTO_NEG_VEN_LSC 0x1 /* AUTO_NEG Vendor Tx LSC */
-#define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */
-#define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */
#define IXGBE_MDIO_AUTO_NEG_EEE_ADVT 0x3C /* AUTO_NEG EEE Advt Reg */
#define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */
@@ -1393,8 +1377,10 @@ struct ixgbe_thermal_sensor_data {
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
#define X540_PHY_ID 0x01540200
-#define X550_PHY_ID 0x01540220
+#define X550_PHY_ID2 0x01540223
+#define X550_PHY_ID3 0x01540221
#define X557_PHY_ID 0x01540240
+#define X557_PHY_ID2 0x01540250
#define QT2022_PHY_ID 0x0043A400
#define ATH_PHY_ID 0x03429050
#define AQ_FW_REV 0x20
@@ -3352,6 +3338,7 @@ struct ixgbe_mac_operations {
s32 (*led_off)(struct ixgbe_hw *, u32);
s32 (*blink_led_start)(struct ixgbe_hw *, u32);
s32 (*blink_led_stop)(struct ixgbe_hw *, u32);
+ s32 (*init_led_link_act)(struct ixgbe_hw *);
/* RAR, Multicast, VLAN */
s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
@@ -3372,6 +3359,7 @@ struct ixgbe_mac_operations {
/* Flow Control */
s32 (*fc_enable)(struct ixgbe_hw *);
s32 (*setup_fc)(struct ixgbe_hw *);
+ void (*fc_autoneg)(struct ixgbe_hw *);
/* Manageability interface */
s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
@@ -3410,16 +3398,28 @@ struct ixgbe_phy_operations {
s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);
s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
- s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
- s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
s32 (*check_overtemp)(struct ixgbe_hw *);
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);
+ s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
+ u8 *value);
+ s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
+ u8 value);
+};
+
+struct ixgbe_link_operations {
+ s32 (*read_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
+ s32 (*read_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 *val);
+ s32 (*write_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
+ s32 (*write_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 val);
+};
+
+struct ixgbe_link_info {
+ struct ixgbe_link_operations ops;
+ u8 addr;
};
struct ixgbe_eeprom_info {
@@ -3462,6 +3462,7 @@ struct ixgbe_mac_info {
u8 san_mac_rar_index;
struct ixgbe_thermal_sensor_data thermal_sensor_data;
bool set_lben;
+ u8 led_link_act;
};
struct ixgbe_phy_info {
@@ -3523,6 +3524,7 @@ struct ixgbe_hw {
struct ixgbe_addr_filter_info addr_ctrl;
struct ixgbe_fc_info fc;
struct ixgbe_phy_info phy;
+ struct ixgbe_link_info link;
struct ixgbe_eeprom_info eeprom;
struct ixgbe_bus_info bus;
struct ixgbe_mbx_info mbx;
@@ -3546,6 +3548,7 @@ struct ixgbe_info {
const struct ixgbe_eeprom_operations *eeprom_ops;
const struct ixgbe_phy_operations *phy_ops;
const struct ixgbe_mbx_operations *mbx_ops;
+ const struct ixgbe_link_operations *link_ops;
const u32 *mvals;
};
@@ -3593,17 +3596,35 @@ struct ixgbe_info {
#define IXGBE_FUSES0_REV_MASK (3u << 6)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
+#define IXGBE_KRM_LINK_S1(P) ((P) ? 0x8200 : 0x4200)
#define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C)
#define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C)
#define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248)
#define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C)
#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638)
#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00)
#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20(P) ((P) ? 0x9054 : 0x5054)
#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520)
#define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA ~(0x3 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR BIT(20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_LR (0x2 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN BIT(25)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN BIT(26)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN BIT(27)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10M ~(0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_100M BIT(28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G (0x2 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G (0x3 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN (0x4 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_2_5G (0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK (0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART BIT(31)
+
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B BIT(9)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS BIT(11)
@@ -3618,6 +3639,7 @@ struct ixgbe_info {
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR BIT(18)
#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX BIT(24)
#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR BIT(26)
+#define IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE BIT(28)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE BIT(29)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART BIT(31)
@@ -3627,6 +3649,8 @@ struct ixgbe_info {
#define IXGBE_KRM_AN_CNTL_8_LINEAR BIT(0)
#define IXGBE_KRM_AN_CNTL_8_LIMITING BIT(1)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE BIT(10)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE BIT(11)
#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D BIT(12)
#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D BIT(19)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index f2b1d48a16c3..e2ff823ee202 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -851,6 +851,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = {
.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic,
.led_on = &ixgbe_led_on_generic,
.led_off = &ixgbe_led_off_generic,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.blink_led_start = &ixgbe_blink_led_start_X540,
.blink_led_stop = &ixgbe_blink_led_stop_X540,
.set_rar = &ixgbe_set_rar_generic,
@@ -866,6 +867,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = {
.set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic,
.setup_fc = ixgbe_setup_fc_generic,
+ .fc_autoneg = ixgbe_fc_autoneg,
.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = NULL,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
index 7e6b9267ca9d..11fb433eb924 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -28,11 +28,31 @@
static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
+static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *);
+static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *);
+static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);
static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
+ struct ixgbe_link_info *link = &hw->link;
+
+ /* Start with X540 invariants, since so simular */
+ ixgbe_get_invariants_X540(hw);
+
+ if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
+ phy->ops.set_phy_power = NULL;
+
+ link->addr = IXGBE_CS4227;
+
+ return 0;
+}
+
+static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
/* Start with X540 invariants, since so simular */
ixgbe_get_invariants_X540(hw);
@@ -69,8 +89,7 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
*/
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);
+ return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
}
/**
@@ -83,8 +102,7 @@ static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
*/
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);
+ return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
}
/**
@@ -322,6 +340,68 @@ static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
return IXGBE_NOT_IMPLEMENTED;
}
+/**
+ * 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.
+ **/
+static 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 - Do 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.
+ **/
+static 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 - 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.
+ **/
+static 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 - Do 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.
+ **/
+static 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_init_eeprom_params_X550 - Initialize EEPROM params
* @hw: pointer to hardware structure
*
@@ -1128,47 +1208,17 @@ out:
return ret;
}
-/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+/**
+ * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
* @hw: pointer to hardware structure
- * @speed: the link speed to force
*
- * Configures the integrated KR PHY to use iXFI mode. Used to connect an
- * internal and external PHY at a specific speed, without autonegotiation.
+ * iXfI configuration needed for ixgbe_mac_X550EM_x devices.
**/
-static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
{
s32 status;
u32 reg_val;
- /* Disable AN and force speed to 10G Serial. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
- if (status)
- return status;
-
- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
-
- /* Select forced link speed for internal PHY. */
- switch (*speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
- break;
- default:
- /* Other link speeds are not supported by internal KR PHY. */
- return IXGBE_ERR_LINK_SETUP;
- }
-
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- if (status)
- return status;
-
/* Disable training protocol FSM. */
status = ixgbe_read_iosf_sb_reg_x550(hw,
IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
@@ -1228,20 +1278,106 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
status = ixgbe_write_iosf_sb_reg_x550(hw,
IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- if (status)
+ return status;
+}
+
+/**
+ * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
+ * internal PHY
+ * @hw: pointer to hardware structure
+ **/
+static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u32 link_ctrl;
+
+ /* Restart auto-negotiation. */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
+
+ if (status) {
+ hw_dbg(hw, "Auto-negotiation did not complete\n");
return status;
+ }
- /* Toggle port SW reset by AN reset. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+ link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
+
+ if (hw->mac.type == ixgbe_mac_x550em_a) {
+ u32 flx_mask_st20;
+
+ /* Indicate to FW that AN restart has been asserted */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
+
+ if (status) {
+ hw_dbg(hw, "Auto-negotiation did not complete\n");
+ return status;
+ }
+
+ flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
+ }
+
+ return status;
+}
+
+/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+ * @hw: pointer to hardware structure
+ * @speed: the link speed to force
+ *
+ * Configures the integrated KR PHY to use iXFI mode. Used to connect an
+ * internal and external PHY at a specific speed, without autonegotiation.
+ **/
+static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+{
+ s32 status;
+ u32 reg_val;
+
+ /* Disable AN and force speed to 10G Serial. */
+ status = ixgbe_read_iosf_sb_reg_x550(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status)
return status;
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+ reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+ reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+
+ /* Select forced link speed for internal PHY. */
+ switch (*speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+ break;
+ default:
+ /* Other link speeds are not supported by internal KR PHY. */
+ return IXGBE_ERR_LINK_SETUP;
+ }
+
status = ixgbe_write_iosf_sb_reg_x550(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ if (status)
+ return status;
+
+ /* Additional configuration needed for x550em_x */
+ if (hw->mac.type == ixgbe_mac_X550EM_x) {
+ status = ixgbe_setup_ixfi_x550em_x(hw);
+ if (status)
+ return status;
+ }
+
+ /* Toggle port SW reset by AN reset. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
return status;
}
@@ -1292,7 +1428,7 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
__always_unused bool autoneg_wait_to_complete)
{
s32 status;
- u16 slice, value;
+ u16 reg_slice, reg_val;
bool setup_linear = false;
/* Check if SFP module is supported and linear */
@@ -1308,71 +1444,68 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
if (status)
return status;
- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
- /* 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);
- if (status)
- goto i2c_err;
+ /* Configure internal PHY for KR/KX. */
+ ixgbe_setup_kr_speed_x550em(hw, speed);
- slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
- slice, value);
- if (status)
- goto i2c_err;
-
- /* 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);
- if (status)
- goto i2c_err;
+ /* Configure CS4227 LINE side to proper mode. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
+ if (setup_linear)
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ else
+ reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- 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 (status)
- goto i2c_err;
+ status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
+ reg_val);
- /* Setup XFI internal link. */
- status = ixgbe_setup_ixfi_x550em(hw, &speed);
- if (status) {
- hw_dbg(hw, "setup_ixfi failed with %d\n", status);
- return status;
- }
- } else {
- /* Configure internal PHY for KR/KX. */
- status = ixgbe_setup_kr_speed_x550em(hw, speed);
- if (status) {
- hw_dbg(hw, "setup_kr_speed failed with %d\n", status);
- return status;
- }
+ return status;
+}
- /* Configure CS4227 LINE side to proper mode. */
- slice = IXGBE_CS4227_LINE_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 (status)
- goto i2c_err;
+/**
+ * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
+ * @hw: pointer to hardware structure
+ * @speed: the link speed to force
+ *
+ * Configures the integrated PHY for native SFI mode. Used to connect the
+ * internal PHY directly to an SFP cage, without autonegotiation.
+ **/
+static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ s32 status;
+ u32 reg_val;
+
+ /* Disable all AN and force speed to 10G Serial. */
+ status = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ if (status)
+ return status;
+
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+
+ /* Select forced link speed for internal PHY. */
+ switch (*speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
+ break;
+ default:
+ /* Other link speeds are not supported by internal PHY. */
+ return IXGBE_ERR_LINK_SETUP;
}
- return 0;
+ status = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+ /* Toggle port SW reset by AN reset. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
-i2c_err:
- hw_dbg(hw, "combined i2c access failed with %d\n", status);
return status;
}
@@ -1388,45 +1521,39 @@ ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed,
{
bool setup_linear = false;
u32 reg_phy_int;
- s32 rc;
+ s32 ret_val;
/* Check if SFP module is supported and linear */
- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+ ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
/* If no SFP module present, then return success. Return success since
* SFP not present error is not excepted in the setup MAC link flow.
*/
- if (rc == IXGBE_ERR_SFP_NOT_PRESENT)
+ if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
return 0;
- if (!rc)
- return rc;
+ if (!ret_val)
+ return ret_val;
- /* Configure internal PHY for native SFI */
- rc = hw->mac.ops.read_iosf_sb_reg(hw,
- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY,
- &reg_phy_int);
- if (rc)
- return rc;
+ /* Configure internal PHY for native SFI based on module type */
+ ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
+ if (!ret_val)
+ return ret_val;
- if (setup_linear) {
- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR;
- } else {
- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING;
- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
- }
+ reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
+ if (!setup_linear)
+ reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
- rc = hw->mac.ops.write_iosf_sb_reg(hw,
- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY,
- reg_phy_int);
- if (rc)
- return rc;
+ ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
+ if (!ret_val)
+ return ret_val;
- /* Setup XFI/SFI internal link */
- return ixgbe_setup_ixfi_x550em(hw, &speed);
+ /* Setup SFI internal link. */
+ return ixgbe_setup_sfi_x550a(hw, &speed);
}
/**
@@ -1442,19 +1569,19 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
u32 reg_slice, slice_offset;
bool setup_linear = false;
u16 reg_phy_ext;
- s32 rc;
+ s32 ret_val;
/* Check if SFP module is supported and linear */
- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+ ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
/* If no SFP module present, then return success. Return success since
* SFP not present error is not excepted in the setup MAC link flow.
*/
- if (rc == IXGBE_ERR_SFP_NOT_PRESENT)
+ if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
return 0;
- if (!rc)
- return rc;
+ if (!ret_val)
+ return ret_val;
/* Configure internal PHY for KR/KX. */
ixgbe_setup_kr_speed_x550em(hw, speed);
@@ -1463,10 +1590,10 @@ ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed,
return IXGBE_ERR_PHY_ADDR_INVALID;
/* Get external PHY device id */
- rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
+ ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
- if (rc)
- return rc;
+ if (ret_val)
+ return ret_val;
/* When configuring quad port CS4223, the MAC instance is part
* of the slice offset.
@@ -1538,7 +1665,7 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
bool link_up_wait_to_complete)
{
u32 status;
- u16 autoneg_status;
+ u16 i, autoneg_status;
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
return IXGBE_ERR_CONFIG;
@@ -1550,14 +1677,18 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
if (status || !(*link_up))
return status;
- /* MAC link is up, so check external PHY link.
- * Read this twice back to back to indicate current status.
- */
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_status);
- if (status)
- return status;
+ /* MAC link is up, so check external PHY link.
+ * Link status is latching low, and can only be used to detect link
+ * drop, and not the current status of the link without performing
+ * back-to-back reads.
+ */
+ for (i = 0; i < 2; i++) {
+ status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
+ &autoneg_status);
+
+ if (status)
+ return status;
+ }
/* If external PHY link is not up, then indicate link not up */
if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
@@ -1575,7 +1706,7 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
__always_unused bool autoneg_wait_to_complete)
{
struct ixgbe_mac_info *mac = &hw->mac;
- u32 lval, sval;
+ u32 lval, sval, flx_val;
s32 rc;
rc = mac->ops.read_iosf_sb_reg(hw,
@@ -1609,14 +1740,55 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,
if (rc)
return rc;
- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+ if (rc)
+ return rc;
+
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+
rc = mac->ops.write_iosf_sb_reg(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
+ if (rc)
+ return rc;
+ rc = ixgbe_restart_an_internal_phy_x550em(hw);
return rc;
}
+/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
+ * @hw: pointer to hardware structure
+ **/
+static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+
+ switch (mac->ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ mac->ops.setup_fc = NULL;
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
+ break;
+ case ixgbe_media_type_backplane:
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
+ mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
+ break;
+ default:
+ break;
+ }
+}
+
/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
* @hw: pointer to hardware structure
**/
@@ -1664,6 +1836,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
default:
break;
}
+
+ /* Additional modification for X550em_a devices */
+ if (hw->mac.type == ixgbe_mac_x550em_a)
+ ixgbe_init_mac_link_ops_X550em_a(hw);
}
/** ixgbe_setup_sfp_modules_X550em - Setup SFP module
@@ -1740,7 +1916,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* Vendor alarm triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
@@ -1748,7 +1924,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
@@ -1757,7 +1933,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* Global alarm triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
@@ -1772,7 +1948,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
/* device fault alarm triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
return status;
@@ -1787,14 +1963,14 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* Vendor alarm 2 triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+ MDIO_MMD_AN, &reg);
if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
return status;
/* link connect/disconnect event occurred */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+ MDIO_MMD_AN, &reg);
if (status)
return status;
@@ -1826,20 +2002,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
/* Enable link status change alarm */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+ MDIO_MMD_AN, &reg);
if (status)
return status;
reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
+ MDIO_MMD_AN, reg);
if (status)
return status;
/* Enable high temperature failure and global fault alarms */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
return status;
@@ -1848,14 +2024,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
reg);
if (status)
return status;
/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
return status;
@@ -1864,14 +2040,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
IXGBE_MDIO_GLOBAL_ALARM_1_INT);
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
reg);
if (status)
return status;
/* Enable chip-wide vendor alarm */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
return status;
@@ -1879,7 +2055,7 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
reg);
return status;
@@ -1945,13 +2121,31 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
if (speed & IXGBE_LINK_SPEED_1GB_FULL)
reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
- /* Restart auto-negotiation. */
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
status = hw->mac.ops.write_iosf_sb_reg(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- return status;
+ if (hw->mac.type == ixgbe_mac_x550em_a) {
+ /* Set lane mode to KR auto negotiation */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+
+ if (status)
+ return status;
+
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ }
+
+ return ixgbe_restart_an_internal_phy_x550em(hw);
}
/** ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
@@ -2020,14 +2214,12 @@ static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
*link_up = false;
/* read this twice back to back to indicate current status */
- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
&autoneg_status);
if (ret)
return ret;
- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
&autoneg_status);
if (ret)
return ret;
@@ -2073,7 +2265,7 @@ static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
return 0;
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ MDIO_MMD_AN,
&speed);
if (status)
return status;
@@ -2134,10 +2326,10 @@ static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
/* To turn on the LED, set mode to ON. */
hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
+ MDIO_MMD_VEND1, &phy_data);
phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
+ MDIO_MMD_VEND1, phy_data);
return 0;
}
@@ -2156,10 +2348,10 @@ static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
/* To turn on the LED, set mode to ON. */
hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
+ MDIO_MMD_VEND1, &phy_data);
phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
+ MDIO_MMD_VEND1, phy_data);
return 0;
}
@@ -2180,7 +2372,7 @@ static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ MDIO_MMD_AN,
&an_lp_status);
if (status)
return status;
@@ -2281,6 +2473,90 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
return rc;
}
+/**
+ * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ **/
+static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+ u32 link_s1, lp_an_page_low, an_cntl_1;
+ s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ ixgbe_link_speed speed;
+ bool link_up;
+
+ /* AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ */
+ if (hw->fc.disable_fc_autoneg) {
+ hw_err(hw, "Flow control autoneg is disabled");
+ goto out;
+ }
+
+ hw->mac.ops.check_link(hw, &speed, &link_up, false);
+ if (!link_up) {
+ hw_err(hw, "The link is down");
+ goto out;
+ }
+
+ /* Check at auto-negotiation has completed */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_S1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
+
+ if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
+ hw_dbg(hw, "Auto-Negotiation did not complete\n");
+ status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ goto out;
+ }
+
+ /* Read the 10g AN autoc and LP ability registers and resolve
+ * local flow control settings accordingly
+ */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
+
+ if (status) {
+ hw_dbg(hw, "Auto-Negotiation did not complete\n");
+ goto out;
+ }
+
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
+
+ if (status) {
+ hw_dbg(hw, "Auto-Negotiation did not complete\n");
+ goto out;
+ }
+
+ status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
+ IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
+
+out:
+ if (!status) {
+ hw->fc.fc_was_autonegged = true;
+ } else {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
+}
+
+/**
+ * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
+ * @hw: pointer to hardware structure
+ **/
+static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
+{
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+}
+
/** ixgbe_enter_lplu_x550em - Transition to low power states
* @hw: pointer to hardware structure
*
@@ -2327,7 +2603,7 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
return ixgbe_set_copper_phy_power(hw, false);
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ MDIO_MMD_AN,
&speed);
if (status)
return status;
@@ -2349,20 +2625,20 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
/* Clear AN completed indication */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ MDIO_MMD_AN,
&autoneg_reg);
if (status)
return status;
- status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+ MDIO_MMD_AN,
&an_10g_cntl_reg);
if (status)
return status;
status = hw->phy.ops.read_reg(hw,
IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ MDIO_MMD_AN,
&autoneg_reg);
if (status)
return status;
@@ -2520,7 +2796,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
status = hw->phy.ops.read_reg(hw,
IXGBE_MDIO_TX_VENDOR_ALARMS_3,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ MDIO_MMD_PMAPMD,
&reg);
if (status)
return status;
@@ -2531,7 +2807,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
status = hw->phy.ops.read_reg(hw,
IXGBE_MDIO_GLOBAL_RES_PR_10,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
&reg);
if (status)
return status;
@@ -2540,7 +2816,7 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
status = hw->phy.ops.write_reg(hw,
IXGBE_MDIO_GLOBAL_RES_PR_10,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ MDIO_MMD_VEND1,
reg);
if (status)
return status;
@@ -2729,6 +3005,90 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
}
/**
+ * ixgbe_setup_fc_backplane_x550em_a - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u32 an_cntl = 0;
+
+ /* Validate the requested mode */
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
+ }
+
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ /* Set up the 1G and 10G flow control advertisement registers so the
+ * HW will be able to do FC autoneg once the cable is plugged in. If
+ * we link at 10G, the 1G advertisement is harmless and vice versa.
+ */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
+
+ if (status) {
+ hw_dbg(hw, "Auto-Negotiation did not complete\n");
+ return status;
+ }
+
+ /* The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /* Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+ an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
+ break;
+ case ixgbe_fc_rx_pause:
+ /* Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE, as such we fall
+ * through to the fc_full statement. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+ break;
+ default:
+ hw_err(hw, "Flow control param set incorrectly\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
+
+ /* Restart auto-negotiation. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
+
+ return status;
+}
+
+/**
* ixgbe_set_mux - Set mux for port 1 access with CS4227
* @hw: pointer to hardware structure
* @state: set mux if 1, clear if 0
@@ -2934,6 +3294,7 @@ static const struct ixgbe_mac_operations mac_ops_X550 = {
X550_COMMON_MAC
.led_on = ixgbe_led_on_generic,
.led_off = ixgbe_led_off_generic,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.reset_hw = &ixgbe_reset_hw_X540,
.get_media_type = &ixgbe_get_media_type_X540,
.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic,
@@ -2948,12 +3309,14 @@ static const struct ixgbe_mac_operations mac_ops_X550 = {
.prot_autoc_read = prot_autoc_read_generic,
.prot_autoc_write = prot_autoc_write_generic,
.setup_fc = ixgbe_setup_fc_generic,
+ .fc_autoneg = ixgbe_fc_autoneg,
};
static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
X550_COMMON_MAC
.led_on = ixgbe_led_on_t_x550em,
.led_off = ixgbe_led_off_t_x550em,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.reset_hw = &ixgbe_reset_hw_X550em,
.get_media_type = &ixgbe_get_media_type_X550em,
.get_san_mac_addr = NULL,
@@ -2966,6 +3329,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
.release_swfw_sync = &ixgbe_release_swfw_sync_X550em,
.init_swfw_sync = &ixgbe_init_swfw_sync_X540,
.setup_fc = NULL, /* defined later */
+ .fc_autoneg = ixgbe_fc_autoneg,
.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550,
.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550,
};
@@ -2974,6 +3338,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = {
X550_COMMON_MAC
.led_on = ixgbe_led_on_t_x550em,
.led_off = ixgbe_led_off_t_x550em,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
.reset_hw = ixgbe_reset_hw_X550em,
.get_media_type = ixgbe_get_media_type_X550em,
.get_san_mac_addr = NULL,
@@ -2985,6 +3350,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = {
.acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a,
.release_swfw_sync = ixgbe_release_swfw_sync_x550em_a,
.setup_fc = ixgbe_setup_fc_x550em,
+ .fc_autoneg = ixgbe_fc_autoneg,
.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a,
.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a,
};
@@ -3036,11 +3402,6 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = {
.identify = &ixgbe_identify_phy_x550em,
.read_reg = &ixgbe_read_phy_reg_generic,
.write_reg = &ixgbe_write_phy_reg_generic,
- .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 struct ixgbe_phy_operations phy_ops_x550em_a = {
@@ -3053,6 +3414,13 @@ static const struct ixgbe_phy_operations phy_ops_x550em_a = {
.write_reg_mdi = &ixgbe_write_phy_reg_mdi,
};
+static const struct ixgbe_link_operations link_ops_x550em_x = {
+ .read_link = &ixgbe_read_i2c_combined_generic,
+ .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked,
+ .write_link = &ixgbe_write_i2c_combined_generic,
+ .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked,
+};
+
static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
IXGBE_MVALS_INIT(X550)
};
@@ -3083,11 +3451,12 @@ const struct ixgbe_info ixgbe_X550EM_x_info = {
.phy_ops = &phy_ops_X550EM_x,
.mbx_ops = &mbx_ops_generic,
.mvals = ixgbe_mvals_X550EM_x,
+ .link_ops = &link_ops_x550em_x,
};
const struct ixgbe_info ixgbe_x550em_a_info = {
.mac = ixgbe_mac_x550em_a,
- .get_invariants = &ixgbe_get_invariants_X550_x,
+ .get_invariants = &ixgbe_get_invariants_X550_a,
.mac_ops = &mac_ops_x550em_a,
.eeprom_ops = &eeprom_ops_X550EM_x,
.phy_ops = &phy_ops_x550em_a,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index cbf70fe4028a..6d4bef5803f2 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1498,6 +1498,9 @@ static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter)
{
int i, q_vectors;
+ if (!adapter->msix_entries)
+ return;
+
q_vectors = adapter->num_msix_vectors;
i = q_vectors - 1;
@@ -2552,6 +2555,9 @@ static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)
**/
static void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter)
{
+ if (!adapter->msix_entries)
+ return;
+
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
@@ -3746,24 +3752,8 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
int ret;
- switch (adapter->hw.api_version) {
- case ixgbe_mbox_api_11:
- case ixgbe_mbox_api_12:
- max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
- break;
- default:
- if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
- max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
- break;
- }
-
- /* MTU < 68 is an error and causes problems on some kernels */
- if ((new_mtu < 68) || (max_frame > max_possible_frame))
- return -EINVAL;
-
spin_lock_bh(&adapter->mbx_lock);
/* notify the PF of our intent to use this size of frame */
ret = hw->mac.ops.set_rlpml(hw, max_frame);
@@ -3814,11 +3804,10 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state)
ixgbevf_free_irq(adapter);
ixgbevf_free_all_tx_resources(adapter);
ixgbevf_free_all_rx_resources(adapter);
+ ixgbevf_clear_interrupt_scheme(adapter);
rtnl_unlock();
}
- ixgbevf_clear_interrupt_scheme(adapter);
-
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
if (retval)
@@ -4108,6 +4097,23 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 68 - 1504 or 9710 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ switch (adapter->hw.api_version) {
+ case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
+ netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN);
+ break;
+ default:
+ if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
+ netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN);
+ else
+ netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN;
+ break;
+ }
+
if (IXGBE_REMOVED(hw->hw_addr)) {
err = -EIO;
goto err_sw_init;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 836ebd8ee768..f9fcab54783c 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2357,14 +2357,6 @@ jme_change_mtu(struct net_device *netdev, int new_mtu)
{
struct jme_adapter *jme = netdev_priv(netdev);
- if (new_mtu == jme->old_mtu)
- return 0;
-
- if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
- ((new_mtu) < IPV6_MIN_MTU))
- return -EINVAL;
-
-
netdev->mtu = new_mtu;
netdev_update_features(netdev);
@@ -3063,6 +3055,10 @@ jme_init_one(struct pci_dev *pdev,
if (using_dac)
netdev->features |= NETIF_F_HIGHDMA;
+ /* MTU range: 1280 - 9202*/
+ netdev->min_mtu = IPV6_MIN_MTU;
+ netdev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE - ETH_HLEN;
+
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 1799fe1415df..cbeea915f026 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1085,7 +1085,6 @@ static const struct net_device_ops korina_netdev_ops = {
.ndo_set_rx_mode = korina_multicast_list,
.ndo_tx_timeout = korina_tx_timeout,
.ndo_do_ioctl = korina_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index a167fd7ee13e..faea52da8dae 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -303,15 +303,9 @@ ltq_etop_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
}
-static int
-ltq_etop_nway_reset(struct net_device *dev)
-{
- return phy_start_aneg(dev->phydev);
-}
-
static const struct ethtool_ops ltq_etop_ethtool_ops = {
.get_drvinfo = ltq_etop_get_drvinfo,
- .nway_reset = ltq_etop_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
@@ -519,18 +513,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
static int
ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
{
- int ret = eth_change_mtu(dev, new_mtu);
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned long flags;
- if (!ret) {
- struct ltq_etop_priv *priv = netdev_priv(dev);
- unsigned long flags;
+ dev->mtu = new_mtu;
- spin_lock_irqsave(&priv->lock, flags);
- ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
- LTQ_ETOP_IGPLEN);
- spin_unlock_irqrestore(&priv->lock, flags);
- }
- return ret;
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, LTQ_ETOP_IGPLEN);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
}
static int
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 2664827ddecd..f4b7cf18fb0f 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_MARVELL
bool "Marvell devices"
default y
- depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET
+ depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET || COMPILE_TEST
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -18,7 +18,8 @@ if NET_VENDOR_MARVELL
config MV643XX_ETH
tristate "Marvell Discovery (643XX) and Orion ethernet support"
- depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
+ depends on (MV64X60 || PPC32 || PLAT_ORION || COMPILE_TEST) && INET
+ depends on HAS_DMA
select PHYLIB
select MVMDIO
---help---
@@ -43,6 +44,7 @@ config MVMDIO
config MVNETA_BM_ENABLE
tristate "Marvell Armada 38x/XP network interface BM support"
depends on MVNETA
+ depends on !64BIT
---help---
This driver supports auxiliary block of the network
interface units in the Marvell ARMADA XP and ARMADA 38x SoC
@@ -54,13 +56,15 @@ config MVNETA_BM_ENABLE
buffer management.
config MVNETA
- tristate "Marvell Armada 370/38x/XP network interface support"
- depends on PLAT_ORION
+ tristate "Marvell Armada 370/38x/XP/37xx network interface support"
+ depends on ARCH_MVEBU || COMPILE_TEST
+ depends on HAS_DMA
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.
+ Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
+ ARMADA 37xx SoC family.
Note that this driver is distinct from the mv643xx_eth
driver, which should be used for the older Marvell SoCs
@@ -68,16 +72,20 @@ config MVNETA
config MVNETA_BM
tristate
+ depends on !64BIT
default y if MVNETA=y && MVNETA_BM_ENABLE!=n
default MVNETA_BM_ENABLE
select HWBM
+ select GENERIC_ALLOCATOR
help
MVNETA_BM must not be 'm' if MVNETA=y, so this symbol ensures
that all dependencies are met.
config MVPP2
tristate "Marvell Armada 375 network interface support"
- depends on MACH_ARMADA_375
+ depends on MACH_ARMADA_375 || COMPILE_TEST
+ depends on HAS_DMA
+ depends on !64BIT
select MVMDIO
---help---
This driver supports the network interface units in the
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 5b12022adf1f..5f62c3d70df9 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -384,8 +384,6 @@ struct mv643xx_eth_private {
struct net_device *dev;
- struct phy_device *phy;
-
struct timer_list mib_counters_timer;
spinlock_t mib_counters_lock;
struct mib_counters mib_counters;
@@ -1236,7 +1234,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
DISABLE_AUTO_NEG_FOR_DUPLEX;
- if (mp->phy->autoneg == AUTONEG_ENABLE) {
+ if (dev->phydev->autoneg == AUTONEG_ENABLE) {
/* enable auto negotiation */
pscr &= ~autoneg_disable;
goto out_write;
@@ -1244,7 +1242,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
pscr |= autoneg_disable;
- if (mp->phy->speed == SPEED_1000) {
+ if (dev->phydev->speed == SPEED_1000) {
/* force gigabit, half duplex not supported */
pscr |= SET_GMII_SPEED_TO_1000;
pscr |= SET_FULL_DUPLEX_MODE;
@@ -1253,12 +1251,12 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
pscr &= ~SET_GMII_SPEED_TO_1000;
- if (mp->phy->speed == SPEED_100)
+ if (dev->phydev->speed == SPEED_100)
pscr |= SET_MII_SPEED_TO_100;
else
pscr &= ~SET_MII_SPEED_TO_100;
- if (mp->phy->duplex == DUPLEX_FULL)
+ if (dev->phydev->duplex == DUPLEX_FULL)
pscr |= SET_FULL_DUPLEX_MODE;
else
pscr &= ~SET_FULL_DUPLEX_MODE;
@@ -1499,55 +1497,69 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
};
static int
-mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp,
- struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp,
+ struct ethtool_link_ksettings *cmd)
{
+ struct net_device *dev = mp->dev;
int err;
+ u32 supported, advertising;
- err = phy_read_status(mp->phy);
+ err = phy_read_status(dev->phydev);
if (err == 0)
- err = phy_ethtool_gset(mp->phy, cmd);
+ err = phy_ethtool_ksettings_get(dev->phydev, cmd);
/*
* The MAC does not support 1000baseT_Half.
*/
- cmd->supported &= ~SUPPORTED_1000baseT_Half;
- cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+ ethtool_convert_link_mode_to_legacy_u32(&supported,
+ cmd->link_modes.supported);
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
+ supported &= ~SUPPORTED_1000baseT_Half;
+ advertising &= ~ADVERTISED_1000baseT_Half;
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return err;
}
static int
-mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
- struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phyless(struct mv643xx_eth_private *mp,
+ struct ethtool_link_ksettings *cmd)
{
u32 port_status;
+ u32 supported, advertising;
port_status = rdlp(mp, PORT_STATUS);
- cmd->supported = SUPPORTED_MII;
- cmd->advertising = ADVERTISED_MII;
+ supported = SUPPORTED_MII;
+ advertising = ADVERTISED_MII;
switch (port_status & PORT_SPEED_MASK) {
case PORT_SPEED_10:
- ethtool_cmd_speed_set(cmd, SPEED_10);
+ cmd->base.speed = SPEED_10;
break;
case PORT_SPEED_100:
- ethtool_cmd_speed_set(cmd, SPEED_100);
+ cmd->base.speed = SPEED_100;
break;
case PORT_SPEED_1000:
- ethtool_cmd_speed_set(cmd, SPEED_1000);
+ cmd->base.speed = SPEED_1000;
break;
default:
- cmd->speed = -1;
+ cmd->base.speed = -1;
break;
}
- cmd->duplex = (port_status & FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
- cmd->port = PORT_MII;
- cmd->phy_address = 0;
- cmd->transceiver = XCVR_INTERNAL;
- cmd->autoneg = AUTONEG_DISABLE;
- cmd->maxtxpkt = 1;
- cmd->maxrxpkt = 1;
+ cmd->base.duplex = (port_status & FULL_DUPLEX) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ cmd->base.port = PORT_MII;
+ cmd->base.phy_address = 0;
+ cmd->base.autoneg = AUTONEG_DISABLE;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
return 0;
}
@@ -1555,23 +1567,21 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
static void
mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
wol->supported = 0;
wol->wolopts = 0;
- if (mp->phy)
- phy_ethtool_get_wol(mp->phy, wol);
+ if (dev->phydev)
+ phy_ethtool_get_wol(dev->phydev, wol);
}
static int
mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
int err;
- if (mp->phy == NULL)
+ if (!dev->phydev)
return -EOPNOTSUPP;
- err = phy_ethtool_set_wol(mp->phy, wol);
+ err = phy_ethtool_set_wol(dev->phydev, wol);
/* Given that mv643xx_eth works without the marvell-specific PHY driver,
* this debugging hint is useful to have.
*/
@@ -1581,31 +1591,38 @@ mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
}
static int
-mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- if (mp->phy != NULL)
- return mv643xx_eth_get_settings_phy(mp, cmd);
+ if (dev->phydev)
+ return mv643xx_eth_get_link_ksettings_phy(mp, cmd);
else
- return mv643xx_eth_get_settings_phyless(mp, cmd);
+ return mv643xx_eth_get_link_ksettings_phyless(mp, cmd);
}
static int
-mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
+ struct ethtool_link_ksettings c = *cmd;
+ u32 advertising;
int ret;
- if (mp->phy == NULL)
+ if (!dev->phydev)
return -EINVAL;
/*
* The MAC does not support 1000baseT_Half.
*/
- cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ c.link_modes.advertising);
+ advertising &= ~ADVERTISED_1000baseT_Half;
+ ethtool_convert_legacy_u32_to_link_mode(c.link_modes.advertising,
+ advertising);
- ret = phy_ethtool_sset(mp->phy, cmd);
+ ret = phy_ethtool_ksettings_set(dev->phydev, &c);
if (!ret)
mv643xx_eth_adjust_link(dev);
return ret;
@@ -1622,16 +1639,6 @@ static void mv643xx_eth_get_drvinfo(struct net_device *dev,
strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
}
-static int mv643xx_eth_nway_reset(struct net_device *dev)
-{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
-
- if (mp->phy == NULL)
- return -EINVAL;
-
- return genphy_restart_aneg(mp->phy);
-}
-
static int
mv643xx_eth_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
{
@@ -1754,10 +1761,8 @@ static int mv643xx_eth_get_sset_count(struct net_device *dev, int sset)
}
static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
- .get_settings = mv643xx_eth_get_settings,
- .set_settings = mv643xx_eth_set_settings,
.get_drvinfo = mv643xx_eth_get_drvinfo,
- .nway_reset = mv643xx_eth_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_coalesce = mv643xx_eth_get_coalesce,
.set_coalesce = mv643xx_eth_set_coalesce,
@@ -1769,6 +1774,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
.get_wol = mv643xx_eth_get_wol,
.set_wol = mv643xx_eth_set_wol,
+ .get_link_ksettings = mv643xx_eth_get_link_ksettings,
+ .set_link_ksettings = mv643xx_eth_set_link_ksettings,
};
@@ -2328,19 +2335,21 @@ static inline void oom_timer_wrapper(unsigned long data)
static void port_start(struct mv643xx_eth_private *mp)
{
+ struct net_device *dev = mp->dev;
u32 pscr;
int i;
/*
* Perform PHY reset, if there is a PHY.
*/
- if (mp->phy != NULL) {
- struct ethtool_cmd cmd;
+ if (dev->phydev) {
+ struct ethtool_link_ksettings cmd;
- mv643xx_eth_get_settings(mp->dev, &cmd);
- phy_init_hw(mp->phy);
- mv643xx_eth_set_settings(mp->dev, &cmd);
- phy_start(mp->phy);
+ mv643xx_eth_get_link_ksettings(dev, &cmd);
+ phy_init_hw(dev->phydev);
+ mv643xx_eth_set_link_ksettings(
+ dev, (const struct ethtool_link_ksettings *)&cmd);
+ phy_start(dev->phydev);
}
/*
@@ -2352,7 +2361,7 @@ static void port_start(struct mv643xx_eth_private *mp)
wrlp(mp, PORT_SERIAL_CONTROL, pscr);
pscr |= DO_NOT_FORCE_LINK_FAIL;
- if (mp->phy == NULL)
+ if (!dev->phydev)
pscr |= FORCE_LINK_PASS;
wrlp(mp, PORT_SERIAL_CONTROL, pscr);
@@ -2536,8 +2545,8 @@ static int mv643xx_eth_stop(struct net_device *dev)
del_timer_sync(&mp->rx_oom);
netif_carrier_off(dev);
- if (mp->phy)
- phy_stop(mp->phy);
+ if (dev->phydev)
+ phy_stop(dev->phydev);
free_irq(dev->irq, dev);
port_reset(mp);
@@ -2555,13 +2564,12 @@ static int mv643xx_eth_stop(struct net_device *dev)
static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
int ret;
- if (mp->phy == NULL)
+ if (!dev->phydev)
return -ENOTSUPP;
- ret = phy_mii_ioctl(mp->phy, ifr, cmd);
+ ret = phy_mii_ioctl(dev->phydev, ifr, cmd);
if (!ret)
mv643xx_eth_adjust_link(dev);
return ret;
@@ -2571,9 +2579,6 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- if (new_mtu < 64 || new_mtu > 9500)
- return -EINVAL;
-
dev->mtu = new_mtu;
mv643xx_eth_recalc_skb_size(mp);
tx_set_rate(mp, 1000000000, 16777216);
@@ -3024,7 +3029,8 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
{
- struct phy_device *phy = mp->phy;
+ struct net_device *dev = mp->dev;
+ struct phy_device *phy = dev->phydev;
if (speed == 0) {
phy->autoneg = AUTONEG_ENABLE;
@@ -3042,6 +3048,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
{
+ struct net_device *dev = mp->dev;
u32 pscr;
pscr = rdlp(mp, PORT_SERIAL_CONTROL);
@@ -3051,7 +3058,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
}
pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
- if (mp->phy == NULL) {
+ if (!dev->phydev) {
pscr |= DISABLE_AUTO_NEG_SPEED_GMII;
if (speed == SPEED_1000)
pscr |= SET_GMII_SPEED_TO_1000;
@@ -3090,6 +3097,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
struct mv643xx_eth_platform_data *pd;
struct mv643xx_eth_private *mp;
struct net_device *dev;
+ struct phy_device *phydev = NULL;
struct resource *res;
int err;
@@ -3146,18 +3154,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
err = 0;
if (pd->phy_node) {
- mp->phy = of_phy_connect(mp->dev, pd->phy_node,
- mv643xx_eth_adjust_link, 0,
- get_phy_mode(mp));
- if (!mp->phy)
+ phydev = of_phy_connect(mp->dev, pd->phy_node,
+ mv643xx_eth_adjust_link, 0,
+ get_phy_mode(mp));
+ if (!phydev)
err = -ENODEV;
else
- phy_addr_set(mp, mp->phy->mdio.addr);
+ phy_addr_set(mp, phydev->mdio.addr);
} else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
- mp->phy = phy_scan(mp, pd->phy_addr);
+ phydev = phy_scan(mp, pd->phy_addr);
- if (IS_ERR(mp->phy))
- err = PTR_ERR(mp->phy);
+ if (IS_ERR(phydev))
+ err = PTR_ERR(phydev);
else
phy_init(mp, pd->speed, pd->duplex);
}
@@ -3206,6 +3214,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev->priv_flags |= IFF_UNICAST_FLT;
dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;
+ /* MTU range: 64 - 9500 */
+ dev->min_mtu = 64;
+ dev->max_mtu = 9500;
+
if (mp->shared->win_protect)
wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect);
@@ -3239,10 +3251,11 @@ out:
static int mv643xx_eth_remove(struct platform_device *pdev)
{
struct mv643xx_eth_private *mp = platform_get_drvdata(pdev);
+ struct net_device *dev = mp->dev;
unregister_netdev(mp->dev);
- if (mp->phy != NULL)
- phy_disconnect(mp->phy);
+ if (dev->phydev)
+ phy_disconnect(dev->phydev);
cancel_work_sync(&mp->tx_timeout_task);
if (!IS_ERR(mp->clk))
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 707bc4680b9b..e05e22705cf7 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -296,6 +296,12 @@
/* descriptor aligned size */
#define MVNETA_DESC_ALIGNED_SIZE 32
+/* Number of bytes to be taken into account by HW when putting incoming data
+ * to the buffers. It is needed in case NET_SKB_PAD exceeds maximum packet
+ * offset supported in MVNETA_RXQ_CONFIG_REG(q) registers.
+ */
+#define MVNETA_RX_PKT_OFFSET_CORRECTION 64
+
#define MVNETA_RX_PKT_SIZE(mtu) \
ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \
ETH_HLEN + ETH_FCS_LEN, \
@@ -391,6 +397,9 @@ struct mvneta_port {
spinlock_t lock;
bool is_stopped;
+ u32 cause_rx_tx;
+ struct napi_struct napi;
+
/* Core clock */
struct clk *clk;
/* AXI clock */
@@ -416,6 +425,10 @@ struct mvneta_port {
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
+
+ /* Flags for special SoC configurations */
+ bool neta_armada3700;
+ u16 rx_offset_correction;
};
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -561,6 +574,9 @@ struct mvneta_rx_queue {
u32 pkts_coal;
u32 time_coal;
+ /* Virtual address of the RX buffer */
+ void **buf_virt_addr;
+
/* Virtual address of the RX DMA descriptors array */
struct mvneta_rx_desc *descs;
@@ -955,14 +971,9 @@ static int mvneta_mbus_io_win_set(struct mvneta_port *pp, u32 base, u32 wsize,
return 0;
}
-/* Assign and initialize pools for port. In case of fail
- * buffer manager will remain disabled for current port.
- */
-static int mvneta_bm_port_init(struct platform_device *pdev,
- struct mvneta_port *pp)
+static int mvneta_bm_port_mbus_init(struct mvneta_port *pp)
{
- struct device_node *dn = pdev->dev.of_node;
- u32 long_pool_id, short_pool_id, wsize;
+ u32 wsize;
u8 target, attr;
int err;
@@ -981,6 +992,25 @@ static int mvneta_bm_port_init(struct platform_device *pdev,
netdev_info(pp->dev, "fail to configure mbus window to BM\n");
return err;
}
+ return 0;
+}
+
+/* Assign and initialize pools for port. In case of fail
+ * buffer manager will remain disabled for current port.
+ */
+static int mvneta_bm_port_init(struct platform_device *pdev,
+ struct mvneta_port *pp)
+{
+ struct device_node *dn = pdev->dev.of_node;
+ u32 long_pool_id, short_pool_id;
+
+ if (!pp->neta_armada3700) {
+ int ret;
+
+ ret = mvneta_bm_port_mbus_init(pp);
+ if (ret)
+ return ret;
+ }
if (of_property_read_u32(dn, "bm,pool-long", &long_pool_id)) {
netdev_info(pp->dev, "missing long pool id\n");
@@ -1349,22 +1379,27 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
for_each_present_cpu(cpu) {
int rxq_map = 0, txq_map = 0;
int rxq, txq;
+ if (!pp->neta_armada3700) {
+ for (rxq = 0; rxq < rxq_number; rxq++)
+ if ((rxq % max_cpu) == cpu)
+ rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
+
+ for (txq = 0; txq < txq_number; txq++)
+ if ((txq % max_cpu) == cpu)
+ txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
+
+ /* With only one TX queue we configure a special case
+ * which will allow to get all the irq on a single
+ * CPU
+ */
+ if (txq_number == 1)
+ txq_map = (cpu == pp->rxq_def) ?
+ MVNETA_CPU_TXQ_ACCESS(1) : 0;
- for (rxq = 0; rxq < rxq_number; rxq++)
- if ((rxq % max_cpu) == cpu)
- rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
-
- for (txq = 0; txq < txq_number; txq++)
- if ((txq % max_cpu) == cpu)
- txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
-
- /* With only one TX queue we configure a special case
- * which will allow to get all the irq on a single
- * CPU
- */
- if (txq_number == 1)
- txq_map = (cpu == pp->rxq_def) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ } else {
+ txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
+ rxq_map = MVNETA_CPU_RXQ_ACCESS_ALL_MASK;
+ }
mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
}
@@ -1573,10 +1608,14 @@ static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
- u32 phys_addr, u32 cookie)
+ u32 phys_addr, void *virt_addr,
+ struct mvneta_rx_queue *rxq)
{
- rx_desc->buf_cookie = cookie;
+ int i;
+
rx_desc->buf_phys_addr = phys_addr;
+ i = rx_desc - rxq->descs;
+ rxq->buf_virt_addr[i] = virt_addr;
}
/* Decrement sent descriptors counter */
@@ -1781,7 +1820,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
/* Refill processing for SW buffer management */
static int mvneta_rx_refill(struct mvneta_port *pp,
- struct mvneta_rx_desc *rx_desc)
+ struct mvneta_rx_desc *rx_desc,
+ struct mvneta_rx_queue *rxq)
{
dma_addr_t phys_addr;
@@ -1799,7 +1839,8 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
return -ENOMEM;
}
- mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
+ phys_addr += pp->rx_offset_correction;
+ mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
return 0;
}
@@ -1861,7 +1902,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
for (i = 0; i < rxq->size; i++) {
struct mvneta_rx_desc *rx_desc = rxq->descs + i;
- void *data = (void *)rx_desc->buf_cookie;
+ void *data = rxq->buf_virt_addr[i];
dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
@@ -1894,12 +1935,13 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
unsigned char *data;
dma_addr_t phys_addr;
u32 rx_status, frag_size;
- int rx_bytes, err;
+ int rx_bytes, err, index;
rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
- data = (unsigned char *)rx_desc->buf_cookie;
+ index = rx_desc - rxq->descs;
+ data = rxq->buf_virt_addr[index];
phys_addr = rx_desc->buf_phys_addr;
if (!mvneta_rxq_desc_is_first_last(rx_status) ||
@@ -1918,7 +1960,7 @@ err_drop_frame:
goto err_drop_frame;
dma_sync_single_range_for_cpu(dev->dev.parent,
- rx_desc->buf_phys_addr,
+ phys_addr,
MVNETA_MH_SIZE + NET_SKB_PAD,
rx_bytes,
DMA_FROM_DEVICE);
@@ -1938,7 +1980,7 @@ err_drop_frame:
}
/* Refill processing */
- err = mvneta_rx_refill(pp, rx_desc);
+ err = mvneta_rx_refill(pp, rx_desc, rxq);
if (err) {
netdev_err(dev, "Linux processing - Can't refill\n");
rxq->missed++;
@@ -2020,7 +2062,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
- data = (unsigned char *)rx_desc->buf_cookie;
+ data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
phys_addr = rx_desc->buf_phys_addr;
pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
bm_pool = &pp->bm_priv->bm_pools[pool_id];
@@ -2610,6 +2652,17 @@ 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;
+
+ mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+ napi_schedule(&pp->napi);
+
+ return IRQ_HANDLED;
+}
+
+/* Interrupt handling - the callback for request_percpu_irq() */
+static irqreturn_t mvneta_percpu_isr(int irq, void *dev_id)
+{
struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id;
disable_percpu_irq(port->pp->dev->irq);
@@ -2657,7 +2710,7 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
if (!netif_running(pp->dev)) {
- napi_complete(&port->napi);
+ napi_complete(napi);
return rx_done;
}
@@ -2686,7 +2739,8 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
*/
rx_queue = fls(((cause_rx_tx >> 8) & 0xff));
- cause_rx_tx |= port->cause_rx_tx;
+ cause_rx_tx |= pp->neta_armada3700 ? pp->cause_rx_tx :
+ port->cause_rx_tx;
if (rx_queue) {
rx_queue = rx_queue - 1;
@@ -2700,11 +2754,27 @@ static int mvneta_poll(struct napi_struct *napi, int budget)
if (budget > 0) {
cause_rx_tx = 0;
- napi_complete(&port->napi);
- enable_percpu_irq(pp->dev->irq, 0);
+ napi_complete(napi);
+
+ if (pp->neta_armada3700) {
+ unsigned long flags;
+
+ 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);
+ } else {
+ enable_percpu_irq(pp->dev->irq, 0);
+ }
}
- port->cause_rx_tx = cause_rx_tx;
+ if (pp->neta_armada3700)
+ pp->cause_rx_tx = cause_rx_tx;
+ else
+ port->cause_rx_tx = cause_rx_tx;
+
return rx_done;
}
@@ -2716,7 +2786,7 @@ static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
for (i = 0; i < num; i++) {
memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
- if (mvneta_rx_refill(pp, rxq->descs + i) != 0) {
+ if (mvneta_rx_refill(pp, rxq->descs + i, rxq) != 0) {
netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs filled\n",
__func__, rxq->id, i, num);
break;
@@ -2773,7 +2843,7 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
/* Set Offset */
- mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD);
+ mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD - pp->rx_offset_correction);
/* Set coalescing pkts and time */
mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
@@ -2784,14 +2854,14 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
mvneta_rxq_buf_size_set(pp, rxq,
MVNETA_RX_BUF_SIZE(pp->pkt_size));
mvneta_rxq_bm_disable(pp, rxq);
+ mvneta_rxq_fill(pp, rxq, rxq->size);
} else {
mvneta_rxq_bm_enable(pp, rxq);
mvneta_rxq_long_pool_set(pp, rxq);
mvneta_rxq_short_pool_set(pp, rxq);
+ mvneta_rxq_non_occup_desc_add(pp, rxq, rxq->size);
}
- mvneta_rxq_fill(pp, rxq, rxq->size);
-
return 0;
}
@@ -2974,11 +3044,16 @@ static void mvneta_start_dev(struct mvneta_port *pp)
/* start the Rx/Tx activity */
mvneta_port_enable(pp);
- /* Enable polling on the port */
- for_each_online_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ if (!pp->neta_armada3700) {
+ /* Enable polling on the port */
+ for_each_online_cpu(cpu) {
+ struct mvneta_pcpu_port *port =
+ per_cpu_ptr(pp->ports, cpu);
- napi_enable(&port->napi);
+ napi_enable(&port->napi);
+ }
+ } else {
+ napi_enable(&pp->napi);
}
/* Unmask interrupts. It has to be done from each CPU */
@@ -3000,10 +3075,15 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
phy_stop(ndev->phydev);
- for_each_online_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ if (!pp->neta_armada3700) {
+ for_each_online_cpu(cpu) {
+ struct mvneta_pcpu_port *port =
+ per_cpu_ptr(pp->ports, cpu);
- napi_disable(&port->napi);
+ napi_disable(&port->napi);
+ }
+ } else {
+ napi_disable(&pp->napi);
}
netif_carrier_off(pp->dev);
@@ -3024,29 +3104,6 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
mvneta_rx_reset(pp);
}
-/* Return positive if MTU is valid */
-static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
-{
- if (mtu < 68) {
- netdev_err(dev, "cannot change mtu to less than 68\n");
- return -EINVAL;
- }
-
- /* 9676 == 9700 - 20 and rounding to 8 */
- if (mtu > 9676) {
- netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu);
- mtu = 9676;
- }
-
- if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
- netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
- mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
- mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
- }
-
- return mtu;
-}
-
static void mvneta_percpu_enable(void *arg)
{
struct mvneta_port *pp = arg;
@@ -3067,9 +3124,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
struct mvneta_port *pp = netdev_priv(dev);
int ret;
- mtu = mvneta_check_mtu_valid(dev, mtu);
- if (mtu < 0)
- return -EINVAL;
+ if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
+ netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
+ mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
+ mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
+ }
dev->mtu = mtu;
@@ -3434,31 +3493,37 @@ static int mvneta_open(struct net_device *dev)
goto err_cleanup_rxqs;
/* Connect to port interrupt line */
- ret = request_percpu_irq(pp->dev->irq, mvneta_isr,
- MVNETA_DRIVER_NAME, pp->ports);
+ if (pp->neta_armada3700)
+ ret = request_irq(pp->dev->irq, mvneta_isr, 0,
+ dev->name, pp);
+ else
+ ret = request_percpu_irq(pp->dev->irq, mvneta_percpu_isr,
+ dev->name, pp->ports);
if (ret) {
netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq);
goto err_cleanup_txqs;
}
- /* Enable per-CPU interrupt on all the CPU to handle our RX
- * queue interrupts
- */
- on_each_cpu(mvneta_percpu_enable, pp, true);
+ if (!pp->neta_armada3700) {
+ /* Enable per-CPU interrupt on all the CPU to handle our RX
+ * queue interrupts
+ */
+ on_each_cpu(mvneta_percpu_enable, pp, true);
- pp->is_stopped = false;
- /* Register a CPU notifier to handle the case where our CPU
- * might be taken offline.
- */
- ret = cpuhp_state_add_instance_nocalls(online_hpstate,
- &pp->node_online);
- if (ret)
- goto err_free_irq;
+ pp->is_stopped = false;
+ /* Register a CPU notifier to handle the case where our CPU
+ * might be taken offline.
+ */
+ ret = cpuhp_state_add_instance_nocalls(online_hpstate,
+ &pp->node_online);
+ if (ret)
+ goto err_free_irq;
- ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
- &pp->node_dead);
- if (ret)
- goto err_free_online_hp;
+ ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+ &pp->node_dead);
+ if (ret)
+ goto err_free_online_hp;
+ }
/* In default link is down */
netif_carrier_off(pp->dev);
@@ -3474,13 +3539,20 @@ static int mvneta_open(struct net_device *dev)
return 0;
err_free_dead_hp:
- cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
- &pp->node_dead);
+ if (!pp->neta_armada3700)
+ cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+ &pp->node_dead);
err_free_online_hp:
- cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
+ if (!pp->neta_armada3700)
+ cpuhp_state_remove_instance_nocalls(online_hpstate,
+ &pp->node_online);
err_free_irq:
- on_each_cpu(mvneta_percpu_disable, pp, true);
- free_percpu_irq(pp->dev->irq, pp->ports);
+ if (pp->neta_armada3700) {
+ free_irq(pp->dev->irq, pp);
+ } else {
+ on_each_cpu(mvneta_percpu_disable, pp, true);
+ free_percpu_irq(pp->dev->irq, pp->ports);
+ }
err_cleanup_txqs:
mvneta_cleanup_txqs(pp);
err_cleanup_rxqs:
@@ -3493,23 +3565,31 @@ static int mvneta_stop(struct net_device *dev)
{
struct mvneta_port *pp = netdev_priv(dev);
- /* Inform that we are stopping so we don't want to setup the
- * driver for new CPUs in the notifiers. The code of the
- * notifier for CPU online is protected by the same spinlock,
- * so when we get the lock, the notifer work is done.
- */
- spin_lock(&pp->lock);
- pp->is_stopped = true;
- spin_unlock(&pp->lock);
+ if (!pp->neta_armada3700) {
+ /* Inform that we are stopping so we don't want to setup the
+ * driver for new CPUs in the notifiers. The code of the
+ * notifier for CPU online is protected by the same spinlock,
+ * so when we get the lock, the notifer work is done.
+ */
+ spin_lock(&pp->lock);
+ pp->is_stopped = true;
+ spin_unlock(&pp->lock);
- mvneta_stop_dev(pp);
- mvneta_mdio_remove(pp);
+ mvneta_stop_dev(pp);
+ mvneta_mdio_remove(pp);
+
+ cpuhp_state_remove_instance_nocalls(online_hpstate,
+ &pp->node_online);
+ cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+ &pp->node_dead);
+ on_each_cpu(mvneta_percpu_disable, pp, true);
+ free_percpu_irq(dev->irq, pp->ports);
+ } else {
+ mvneta_stop_dev(pp);
+ mvneta_mdio_remove(pp);
+ free_irq(dev->irq, pp);
+ }
- cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
- cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
- &pp->node_dead);
- on_each_cpu(mvneta_percpu_disable, pp, true);
- free_percpu_irq(dev->irq, pp->ports);
mvneta_cleanup_rxqs(pp);
mvneta_cleanup_txqs(pp);
@@ -3788,6 +3868,11 @@ static int mvneta_ethtool_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct mvneta_port *pp = netdev_priv(dev);
+
+ /* Current code for Armada 3700 doesn't support RSS features yet */
+ if (pp->neta_armada3700)
+ return -EOPNOTSUPP;
+
/* We require at least one supported parameter to be changed
* and no change in any of the unsupported parameters
*/
@@ -3808,6 +3893,10 @@ static int mvneta_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
{
struct mvneta_port *pp = netdev_priv(dev);
+ /* Current code for Armada 3700 doesn't support RSS features yet */
+ if (pp->neta_armada3700)
+ return -EOPNOTSUPP;
+
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
@@ -3832,6 +3921,7 @@ static const struct net_device_ops mvneta_netdev_ops = {
};
const struct ethtool_ops mvneta_eth_tool_ops = {
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.set_coalesce = mvneta_ethtool_set_coalesce,
.get_coalesce = mvneta_ethtool_get_coalesce,
@@ -3885,6 +3975,11 @@ static int mvneta_init(struct device *dev, struct mvneta_port *pp)
rxq->size = pp->rx_ring_size;
rxq->pkts_coal = MVNETA_RX_COAL_PKTS;
rxq->time_coal = MVNETA_RX_COAL_USEC;
+ rxq->buf_virt_addr = devm_kmalloc(pp->dev->dev.parent,
+ rxq->size * sizeof(void *),
+ GFP_KERNEL);
+ if (!rxq->buf_virt_addr)
+ return -ENOMEM;
}
return 0;
@@ -3909,16 +4004,29 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
win_enable = 0x3f;
win_protect = 0;
- for (i = 0; i < dram->num_cs; i++) {
- const struct mbus_dram_window *cs = dram->cs + i;
- mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
- (cs->mbus_attr << 8) | dram->mbus_dram_target_id);
+ if (dram) {
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ mvreg_write(pp, MVNETA_WIN_BASE(i),
+ (cs->base & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id);
- mvreg_write(pp, MVNETA_WIN_SIZE(i),
- (cs->size - 1) & 0xffff0000);
+ mvreg_write(pp, MVNETA_WIN_SIZE(i),
+ (cs->size - 1) & 0xffff0000);
- win_enable &= ~(1 << i);
- win_protect |= 3 << (2 * i);
+ win_enable &= ~(1 << i);
+ win_protect |= 3 << (2 * i);
+ }
+ } else {
+ /* For Armada3700 open default 4GB Mbus window, leaving
+ * arbitration of target/attribute to a different layer
+ * of configuration.
+ */
+ mvreg_write(pp, MVNETA_WIN_SIZE(0), 0xffff0000);
+ win_enable &= ~BIT(0);
+ win_protect = 3;
}
mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
@@ -4039,8 +4147,19 @@ static int mvneta_probe(struct platform_device *pdev)
pp->rxq_def = rxq_def;
+ /* Set RX packet offset correction for platforms, whose
+ * NET_SKB_PAD, exceeds 64B. It should be 64B for 64-bit
+ * platforms and 0B for 32-bit ones.
+ */
+ pp->rx_offset_correction =
+ max(0, NET_SKB_PAD - MVNETA_RX_PKT_OFFSET_CORRECTION);
+
pp->indir[0] = rxq_def;
+ /* Get special SoC configurations */
+ if (of_device_is_compatible(dn, "marvell,armada-3700-neta"))
+ pp->neta_armada3700 = true;
+
pp->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(pp->clk))
pp->clk = devm_clk_get(&pdev->dev, NULL);
@@ -4108,7 +4227,11 @@ static int mvneta_probe(struct platform_device *pdev)
pp->tx_csum_limit = tx_csum_limit;
dram_target_info = mv_mbus_dram_info();
- if (dram_target_info)
+ /* Armada3700 requires setting default configuration of Mbus
+ * windows, however without using filled mbus_dram_target_info
+ * structure.
+ */
+ if (dram_target_info || pp->neta_armada3700)
mvneta_conf_mbus_windows(pp, dram_target_info);
pp->tx_ring_size = MVNETA_MAX_TXD;
@@ -4141,11 +4264,20 @@ static int mvneta_probe(struct platform_device *pdev)
goto err_netdev;
}
- for_each_present_cpu(cpu) {
- struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ /* Armada3700 network controller does not support per-cpu
+ * operation, so only single NAPI should be initialized.
+ */
+ if (pp->neta_armada3700) {
+ netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT);
+ } else {
+ 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;
+ 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;
@@ -4154,6 +4286,11 @@ static int mvneta_probe(struct platform_device *pdev)
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
+ /* MTU range: 68 - 9676 */
+ dev->min_mtu = ETH_MIN_MTU;
+ /* 9676 == 9700 - 20 and rounding to 8 */
+ dev->max_mtu = 9676;
+
err = register_netdev(dev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register\n");
@@ -4230,6 +4367,7 @@ static int mvneta_remove(struct platform_device *pdev)
static const struct of_device_id mvneta_match[] = {
{ .compatible = "marvell,armada-370-neta" },
{ .compatible = "marvell,armada-xp-neta" },
+ { .compatible = "marvell,armada-3700-neta" },
{ }
};
MODULE_DEVICE_TABLE(of, mvneta_match);
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 1026c452e39d..dabc5418efcc 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -5453,29 +5453,6 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)
phy_stop(ndev->phydev);
}
-/* Return positive if MTU is valid */
-static inline int mvpp2_check_mtu_valid(struct net_device *dev, int mtu)
-{
- if (mtu < 68) {
- netdev_err(dev, "cannot change mtu to less than 68\n");
- return -EINVAL;
- }
-
- /* 9676 == 9700 - 20 and rounding to 8 */
- if (mtu > 9676) {
- netdev_info(dev, "illegal MTU value %d, round to 9676\n", mtu);
- mtu = 9676;
- }
-
- if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
- netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
- ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
- mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
- }
-
- return mtu;
-}
-
static int mvpp2_check_ringparam_valid(struct net_device *dev,
struct ethtool_ringparam *ring)
{
@@ -5717,10 +5694,10 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
struct mvpp2_port *port = netdev_priv(dev);
int err;
- mtu = mvpp2_check_mtu_valid(dev, mtu);
- if (mtu < 0) {
- err = mtu;
- goto error;
+ if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
+ netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
+ ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
+ mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
}
if (!netif_running(dev)) {
@@ -5946,6 +5923,7 @@ static const struct net_device_ops mvpp2_netdev_ops = {
};
static const struct ethtool_ops mvpp2_eth_tool_ops = {
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.set_coalesce = mvpp2_ethtool_set_coalesce,
.get_coalesce = mvpp2_ethtool_get_coalesce,
@@ -6212,6 +6190,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
dev->vlan_features |= features;
+ /* MTU range: 68 - 9676 */
+ dev->min_mtu = ETH_MIN_MTU;
+ /* 9676 == 9700 - 20 and rounding to 8 */
+ dev->max_mtu = 9676;
+
err = register_netdev(dev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register netdev\n");
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 5d5000c8edf1..3af2814ada23 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1209,9 +1209,6 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
int retval;
struct pxa168_eth_private *pep = netdev_priv(dev);
- if ((mtu > 9500) || (mtu < 68))
- return -EINVAL;
-
dev->mtu = mtu;
retval = set_port_config_ext(pep);
@@ -1396,6 +1393,7 @@ static void pxa168_get_drvinfo(struct net_device *dev,
static const struct ethtool_ops pxa168_ethtool_ops = {
.get_drvinfo = pxa168_get_drvinfo,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_ts_info = ethtool_op_get_ts_info,
.get_link_ksettings = pxa168_get_link_ksettings,
@@ -1459,6 +1457,10 @@ static int pxa168_eth_probe(struct platform_device *pdev)
dev->base_addr = 0;
dev->ethtool_ops = &pxa168_ethtool_ops;
+ /* MTU range: 68 - 9500 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = 9500;
+
INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
if (pdev->dev.of_node)
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 7173836fe361..9146a514fb33 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -1048,7 +1048,7 @@ static const char *skge_pause(enum pause_status status)
static void skge_link_up(struct skge_port *skge)
{
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
- LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+ LED_BLK_OFF|LED_SYNC_OFF|LED_REG_ON);
netif_carrier_on(skge->netdev);
netif_wake_queue(skge->netdev);
@@ -1062,7 +1062,7 @@ static void skge_link_up(struct skge_port *skge)
static void skge_link_down(struct skge_port *skge)
{
- skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
netif_carrier_off(skge->netdev);
netif_stop_queue(skge->netdev);
@@ -2668,7 +2668,7 @@ static int skge_down(struct net_device *dev)
if (hw->ports == 1)
free_irq(hw->pdev->irq, hw);
- skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
if (is_genesis(hw))
genesis_stop(skge);
else
@@ -2900,9 +2900,6 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
int err;
- if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
- return -EINVAL;
-
if (!netif_running(dev)) {
dev->mtu = new_mtu;
return 0;
@@ -3857,6 +3854,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
dev->watchdog_timeo = TX_WATCHDOG;
dev->irq = hw->pdev->irq;
+ /* MTU range: 60 - 9000 */
+ dev->min_mtu = ETH_ZLEN;
+ dev->max_mtu = ETH_JUMBO_MTU;
+
if (highmem)
dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/marvell/skge.h b/drivers/net/ethernet/marvell/skge.h
index a2eb34115844..3ea151ff9c43 100644
--- a/drivers/net/ethernet/marvell/skge.h
+++ b/drivers/net/ethernet/marvell/skge.h
@@ -662,8 +662,8 @@ enum {
LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */
LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */
LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */
- LED_ON = 1<<1, /* switch LED on */
- LED_OFF = 1<<0, /* switch LED off */
+ LED_REG_ON = 1<<1, /* switch LED on */
+ LED_REG_OFF = 1<<0, /* switch LED off */
};
/* Receive GMAC FIFO (YUKON) */
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 941c8e2c944e..b60ad0e56a9f 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -2398,16 +2398,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
u16 ctl, mode;
u32 imask;
- /* MTU size outside the spec */
- if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
- return -EINVAL;
-
- /* MTU > 1500 on yukon FE and FE+ not allowed */
- if (new_mtu > ETH_DATA_LEN &&
- (hw->chip_id == CHIP_ID_YUKON_FE ||
- hw->chip_id == CHIP_ID_YUKON_FE_P))
- return -EINVAL;
-
if (!netif_running(dev)) {
dev->mtu = new_mtu;
netdev_update_features(dev);
@@ -4808,6 +4798,14 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
dev->features |= dev->hw_features;
+ /* MTU range: 60 - 1500 or 9000 */
+ dev->min_mtu = ETH_ZLEN;
+ if (hw->chip_id == CHIP_ID_YUKON_FE ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
+ dev->max_mtu = ETH_DATA_LEN;
+ else
+ dev->max_mtu = ETH_JUMBO_MTU;
+
/* try to get mac address in the following order:
* 1) from device tree data
* 2) from internal registers set by bootloader
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 86a89cbd3ec9..3dd87889e67e 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -845,7 +845,7 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
drop:
spin_unlock(&eth->page_lock);
stats->tx_dropped++;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2247,7 +2247,6 @@ static const struct net_device_ops mtk_netdev_ops = {
.ndo_set_mac_address = mtk_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mtk_do_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = mtk_tx_timeout,
.ndo_get_stats64 = mtk_get_stats64,
.ndo_fix_features = mtk_fix_features,
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 5098e7f21987..22b1cc012bc9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -7,7 +7,7 @@ config MLX4_EN
depends on MAY_USE_DEVLINK
depends on PCI
select MLX4_CORE
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Mellanox Technologies ConnectX Ethernet
devices.
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index e36bebcab3f2..a49072b4fa52 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2679,15 +2679,13 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev)
if (!mailbox)
return ERR_PTR(-ENOMEM);
- mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL,
- &mailbox->dma);
+ mailbox->buf = pci_pool_zalloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL,
+ &mailbox->dma);
if (!mailbox->buf) {
kfree(mailbox);
return ERR_PTR(-ENOMEM);
}
- memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
-
return mailbox;
}
EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index e3be7e44ff51..09dd3776db76 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -65,7 +65,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
cq->ring = ring;
- cq->is_tx = mode;
+ cq->type = mode;
cq->vector = mdev->dev->caps.num_comp_vectors;
/* Allocate HW buffers on provided NUMA node.
@@ -104,7 +104,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
*cq->mcq.arm_db = 0;
memset(cq->buf, 0, cq->buf_size);
- if (cq->is_tx == RX) {
+ if (cq->type == RX) {
if (!mlx4_is_eq_vector_valid(mdev->dev, priv->port,
cq->vector)) {
cq->vector = cpumask_first(priv->rx_ring[cq->ring]->affinity_mask);
@@ -127,25 +127,17 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
/* For TX we use the same irq per
ring we assigned for the RX */
struct mlx4_en_cq *rx_cq;
- int xdp_index;
-
- /* The xdp tx irq must align with the rx ring that forwards to
- * it, so reindex these from 0. This should only happen when
- * tx_ring_num is not a multiple of rx_ring_num.
- */
- xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx;
- if (xdp_index >= 0)
- cq_idx = xdp_index;
+
cq_idx = cq_idx % priv->rx_ring_num;
rx_cq = priv->rx_cq[cq_idx];
cq->vector = rx_cq->vector;
}
- if (!cq->is_tx)
+ if (cq->type == RX)
cq->size = priv->rx_ring[cq->ring]->actual_size;
- if ((cq->is_tx && priv->hwtstamp_config.tx_type) ||
- (!cq->is_tx && priv->hwtstamp_config.rx_filter))
+ if ((cq->type != RX && priv->hwtstamp_config.tx_type) ||
+ (cq->type == RX && priv->hwtstamp_config.rx_filter))
timestamp_en = 1;
err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
@@ -154,10 +146,10 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
if (err)
goto free_eq;
- cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
+ cq->mcq.comp = cq->type != RX ? mlx4_en_tx_irq : mlx4_en_rx_irq;
cq->mcq.event = mlx4_en_cq_event;
- if (cq->is_tx)
+ if (cq->type != RX)
netif_tx_napi_add(cq->dev, &cq->napi, mlx4_en_poll_tx_cq,
NAPI_POLL_WEIGHT);
else
@@ -181,7 +173,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)
mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
if (mlx4_is_eq_vector_valid(mdev->dev, priv->port, cq->vector) &&
- cq->is_tx == RX)
+ cq->type == RX)
mlx4_release_eq(priv->mdev->dev, cq->vector);
cq->vector = 0;
cq->buf_size = 0;
@@ -193,10 +185,6 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
napi_disable(&cq->napi);
- if (!cq->is_tx) {
- napi_hash_del(&cq->napi);
- synchronize_rcu();
- }
netif_napi_del(&cq->napi);
mlx4_cq_free(priv->mdev->dev, &cq->mcq);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index bdda17d2ea0f..d9c9f86a30df 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -49,16 +49,19 @@
static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
{
- int i;
+ int i, t;
int err = 0;
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_cq[i]->moder_cnt = priv->tx_frames;
- priv->tx_cq[i]->moder_time = priv->tx_usecs;
- if (priv->port_up) {
- err = mlx4_en_set_cq_moder(priv, priv->tx_cq[i]);
- if (err)
- return err;
+ for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ priv->tx_cq[t][i]->moder_cnt = priv->tx_frames;
+ priv->tx_cq[t][i]->moder_time = priv->tx_usecs;
+ if (priv->port_up) {
+ err = mlx4_en_set_cq_moder(priv,
+ priv->tx_cq[t][i]);
+ if (err)
+ return err;
+ }
}
}
@@ -192,6 +195,10 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tx_prio_7_packets", "tx_prio_7_bytes",
"tx_novlan_packets", "tx_novlan_bytes",
+ /* xdp statistics */
+ "rx_xdp_drop",
+ "rx_xdp_tx",
+ "rx_xdp_tx_full",
};
static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
@@ -336,8 +343,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
switch (sset) {
case ETH_SS_STATS:
return bitmap_iterator_count(&it) +
- (priv->tx_ring_num * 2) +
- (priv->rx_ring_num * 3);
+ (priv->tx_ring_num[TX] * 2) +
+ (priv->rx_ring_num * (3 + NUM_XDP_STATS));
case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
@@ -360,6 +367,8 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
spin_lock_bh(&priv->stats_lock);
+ mlx4_en_fold_software_stats(dev);
+
for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
data[index++] = ((unsigned long *)&dev->stats)[i];
@@ -397,14 +406,21 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
if (bitmap_iterator_test(&it))
data[index++] = ((unsigned long *)&priv->pkstats)[i];
- for (i = 0; i < priv->tx_ring_num; i++) {
- data[index++] = priv->tx_ring[i]->packets;
- data[index++] = priv->tx_ring[i]->bytes;
+ for (i = 0; i < NUM_XDP_STATS; i++, bitmap_iterator_inc(&it))
+ if (bitmap_iterator_test(&it))
+ data[index++] = ((unsigned long *)&priv->xdp_stats)[i];
+
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ data[index++] = priv->tx_ring[TX][i]->packets;
+ data[index++] = priv->tx_ring[TX][i]->bytes;
}
for (i = 0; i < priv->rx_ring_num; i++) {
data[index++] = priv->rx_ring[i]->packets;
data[index++] = priv->rx_ring[i]->bytes;
data[index++] = priv->rx_ring[i]->dropped;
+ data[index++] = priv->rx_ring[i]->xdp_drop;
+ data[index++] = priv->rx_ring[i]->xdp_tx;
+ data[index++] = priv->rx_ring[i]->xdp_tx_full;
}
spin_unlock_bh(&priv->stats_lock);
@@ -467,7 +483,13 @@ static void mlx4_en_get_strings(struct net_device *dev,
strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[strings]);
- for (i = 0; i < priv->tx_ring_num; i++) {
+ for (i = 0; i < NUM_XDP_STATS; i++, strings++,
+ bitmap_iterator_inc(&it))
+ if (bitmap_iterator_test(&it))
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[strings]);
+
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
@@ -480,6 +502,12 @@ static void mlx4_en_get_strings(struct net_device *dev,
"rx%d_bytes", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_dropped", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_xdp_drop", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_xdp_tx", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_xdp_tx_full", i);
}
break;
case ETH_SS_PRIV_FLAGS:
@@ -1060,7 +1088,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :
priv->rx_ring[0]->size) &&
- tx_size == priv->tx_ring[0]->size)
+ tx_size == priv->tx_ring[TX][0]->size)
return 0;
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
@@ -1105,7 +1133,7 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
param->rx_pending = priv->port_up ?
priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;
- param->tx_pending = priv->tx_ring[0]->size;
+ param->tx_pending = priv->tx_ring[TX][0]->size;
}
static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
@@ -1710,7 +1738,7 @@ static void mlx4_en_get_channels(struct net_device *dev,
channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
channel->rx_count = priv->rx_ring_num;
- channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
+ channel->tx_count = priv->tx_ring_num[TX] / MLX4_EN_NUM_UP;
}
static int mlx4_en_set_channels(struct net_device *dev,
@@ -1721,6 +1749,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
struct mlx4_en_port_profile new_prof;
struct mlx4_en_priv *tmp;
int port_up = 0;
+ int xdp_count;
int err = 0;
if (channel->other_count || channel->combined_count ||
@@ -1729,20 +1758,25 @@ static int mlx4_en_set_channels(struct net_device *dev,
!channel->tx_count || !channel->rx_count)
return -EINVAL;
- if (channel->tx_count * MLX4_EN_NUM_UP <= priv->xdp_ring_num) {
- en_err(priv, "Minimum %d tx channels required with XDP on\n",
- priv->xdp_ring_num / MLX4_EN_NUM_UP + 1);
- return -EINVAL;
- }
-
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
mutex_lock(&mdev->state_lock);
+ xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0;
+ if (channel->tx_count * MLX4_EN_NUM_UP + xdp_count > MAX_TX_RINGS) {
+ err = -EINVAL;
+ en_err(priv,
+ "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n",
+ channel->tx_count * MLX4_EN_NUM_UP + xdp_count,
+ MAX_TX_RINGS);
+ goto out;
+ }
+
memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
new_prof.num_tx_rings_p_up = channel->tx_count;
- new_prof.tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
+ new_prof.tx_ring_num[TX] = channel->tx_count * MLX4_EN_NUM_UP;
+ new_prof.tx_ring_num[TX_XDP] = xdp_count;
new_prof.rx_ring_num = channel->rx_count;
err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
@@ -1756,14 +1790,13 @@ static int mlx4_en_set_channels(struct net_device *dev,
mlx4_en_safe_replace_resources(priv, tmp);
- netif_set_real_num_tx_queues(dev, priv->tx_ring_num -
- priv->xdp_ring_num);
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
if (dev->num_tc)
mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
- en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
+ en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]);
en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
if (port_up) {
@@ -1774,8 +1807,8 @@ static int mlx4_en_set_channels(struct net_device *dev,
err = mlx4_en_moderation_update(priv);
out:
- kfree(tmp);
mutex_unlock(&mdev->state_lock);
+ kfree(tmp);
return err;
}
@@ -1823,11 +1856,15 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
int ret = 0;
if (bf_enabled_new != bf_enabled_old) {
+ int t;
+
if (bf_enabled_new) {
bool bf_supported = true;
- for (i = 0; i < priv->tx_ring_num; i++)
- bf_supported &= priv->tx_ring[i]->bf_alloced;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+ for (i = 0; i < priv->tx_ring_num[t]; i++)
+ bf_supported &=
+ priv->tx_ring[t][i]->bf_alloced;
if (!bf_supported) {
en_err(priv, "BlueFlame is not supported\n");
@@ -1839,8 +1876,10 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
}
- for (i = 0; i < priv->tx_ring_num; i++)
- priv->tx_ring[i]->bf_enabled = bf_enabled_new;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+ for (i = 0; i < priv->tx_ring_num[t]; i++)
+ priv->tx_ring[t][i]->bf_enabled =
+ bf_enabled_new;
en_info(priv, "BlueFlame %s\n",
bf_enabled_new ? "Enabled" : "Disabled");
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index bf7628db098a..36a7a54bbb82 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -169,7 +169,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].tx_ppp = pfctx;
params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
- params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
+ params->prof[i].tx_ring_num[TX] = params->num_tx_rings_p_up *
MLX4_EN_NUM_UP;
params->prof[i].rss_rings = 0;
params->prof[i].inline_thold = inline_thold;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index fb8bb027b69c..bcd955339058 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -51,6 +51,9 @@
#include "mlx4_en.h"
#include "en_port.h"
+#define MLX4_EN_MAX_XDP_MTU ((int)(PAGE_SIZE - ETH_HLEN - (2 * VLAN_HLEN) - \
+ XDP_PACKET_HEADROOM))
+
int mlx4_en_setup_tc(struct net_device *dev, u8 up)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -1217,8 +1220,8 @@ static void mlx4_en_netpoll(struct net_device *dev)
struct mlx4_en_cq *cq;
int i;
- for (i = 0; i < priv->tx_ring_num; i++) {
- cq = priv->tx_cq[i];
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ cq = priv->tx_cq[TX][i];
napi_schedule(&cq->napi);
}
}
@@ -1302,12 +1305,14 @@ static void mlx4_en_tx_timeout(struct net_device *dev)
if (netif_msg_timer(priv))
en_warn(priv, "Tx timeout called on port:%d\n", priv->port);
- for (i = 0; i < priv->tx_ring_num; i++) {
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][i];
+
if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, i)))
continue;
en_warn(priv, "TX timeout on queue: %d, QP: 0x%x, CQ: 0x%x, Cons: 0x%x, Prod: 0x%x\n",
- i, priv->tx_ring[i]->qpn, priv->tx_ring[i]->cqn,
- priv->tx_ring[i]->cons, priv->tx_ring[i]->prod);
+ i, tx_ring->qpn, tx_ring->sp_cqn,
+ tx_ring->cons, tx_ring->prod);
}
priv->port_stats.tx_timeout++;
@@ -1322,6 +1327,7 @@ mlx4_en_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
struct mlx4_en_priv *priv = netdev_priv(dev);
spin_lock_bh(&priv->stats_lock);
+ mlx4_en_fold_software_stats(dev);
netdev_stats_to_stats64(stats, &dev->stats);
spin_unlock_bh(&priv->stats_lock);
@@ -1331,7 +1337,7 @@ mlx4_en_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
{
struct mlx4_en_cq *cq;
- int i;
+ int i, t;
/* If we haven't received a specific coalescing setting
* (module param), we set the moderation parameters as follows:
@@ -1356,10 +1362,12 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
priv->last_moder_bytes[i] = 0;
}
- for (i = 0; i < priv->tx_ring_num; i++) {
- cq = priv->tx_cq[i];
- cq->moder_cnt = priv->tx_frames;
- cq->moder_time = priv->tx_usecs;
+ for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ cq = priv->tx_cq[t][i];
+ cq->moder_cnt = priv->tx_frames;
+ cq->moder_time = priv->tx_usecs;
+ }
}
/* Reset auto-moderation params */
@@ -1390,10 +1398,8 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
return;
for (ring = 0; ring < priv->rx_ring_num; ring++) {
- spin_lock_bh(&priv->stats_lock);
- rx_packets = priv->rx_ring[ring]->packets;
- rx_bytes = priv->rx_ring[ring]->bytes;
- spin_unlock_bh(&priv->stats_lock);
+ rx_packets = READ_ONCE(priv->rx_ring[ring]->packets);
+ rx_bytes = READ_ONCE(priv->rx_ring[ring]->bytes);
rx_pkt_diff = ((unsigned long) (rx_packets -
priv->last_moder_packets[ring]));
@@ -1529,19 +1535,13 @@ static void mlx4_en_free_affinity_hint(struct mlx4_en_priv *priv, int ring_idx)
static void mlx4_en_init_recycle_ring(struct mlx4_en_priv *priv,
int tx_ring_idx)
{
- struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[tx_ring_idx];
- int rr_index;
+ struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX_XDP][tx_ring_idx];
+ int rr_index = tx_ring_idx;
- rr_index = (priv->xdp_ring_num - priv->tx_ring_num) + tx_ring_idx;
- if (rr_index >= 0) {
- tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc;
- tx_ring->recycle_ring = priv->rx_ring[rr_index];
- en_dbg(DRV, priv,
- "Set tx_ring[%d]->recycle_ring = rx_ring[%d]\n",
- tx_ring_idx, rr_index);
- } else {
- tx_ring->recycle_ring = NULL;
- }
+ tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc;
+ tx_ring->recycle_ring = priv->rx_ring[rr_index];
+ en_dbg(DRV, priv, "Set tx_ring[%d][%d]->recycle_ring = rx_ring[%d]\n",
+ TX_XDP, tx_ring_idx, rr_index);
}
int mlx4_en_start_port(struct net_device *dev)
@@ -1551,9 +1551,8 @@ int mlx4_en_start_port(struct net_device *dev)
struct mlx4_en_cq *cq;
struct mlx4_en_tx_ring *tx_ring;
int rx_index = 0;
- int tx_index = 0;
int err = 0;
- int i;
+ int i, t;
int j;
u8 mc_list[16] = {0};
@@ -1638,43 +1637,51 @@ int mlx4_en_start_port(struct net_device *dev)
goto rss_err;
/* Configure tx cq's and rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- /* Configure cq */
- cq = priv->tx_cq[i];
- err = mlx4_en_activate_cq(priv, cq, i);
- if (err) {
- en_err(priv, "Failed allocating Tx CQ\n");
- goto tx_err;
- }
- err = mlx4_en_set_cq_moder(priv, cq);
- if (err) {
- en_err(priv, "Failed setting cq moderation parameters\n");
- mlx4_en_deactivate_cq(priv, cq);
- goto tx_err;
- }
- en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
- cq->buf->wqe_index = cpu_to_be16(0xffff);
-
- /* Configure ring */
- tx_ring = priv->tx_ring[i];
- err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
- i / priv->num_tx_rings_p_up);
- if (err) {
- en_err(priv, "Failed allocating Tx ring\n");
- mlx4_en_deactivate_cq(priv, cq);
- goto tx_err;
- }
- tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
+ for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ u8 num_tx_rings_p_up = t == TX ? priv->num_tx_rings_p_up : 1;
- mlx4_en_init_recycle_ring(priv, i);
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ /* Configure cq */
+ cq = priv->tx_cq[t][i];
+ err = mlx4_en_activate_cq(priv, cq, i);
+ if (err) {
+ en_err(priv, "Failed allocating Tx CQ\n");
+ goto tx_err;
+ }
+ err = mlx4_en_set_cq_moder(priv, cq);
+ if (err) {
+ en_err(priv, "Failed setting cq moderation parameters\n");
+ mlx4_en_deactivate_cq(priv, cq);
+ goto tx_err;
+ }
+ en_dbg(DRV, priv,
+ "Resetting index of collapsed CQ:%d to -1\n", i);
+ cq->buf->wqe_index = cpu_to_be16(0xffff);
+
+ /* Configure ring */
+ tx_ring = priv->tx_ring[t][i];
+ err = mlx4_en_activate_tx_ring(priv, tx_ring,
+ cq->mcq.cqn,
+ i / num_tx_rings_p_up);
+ if (err) {
+ en_err(priv, "Failed allocating Tx ring\n");
+ mlx4_en_deactivate_cq(priv, cq);
+ goto tx_err;
+ }
+ if (t != TX_XDP) {
+ tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
+ tx_ring->recycle_ring = NULL;
+ } else {
+ mlx4_en_init_recycle_ring(priv, i);
+ }
- /* Arm CQ for TX completions */
- mlx4_en_arm_cq(priv, cq);
+ /* Arm CQ for TX completions */
+ mlx4_en_arm_cq(priv, cq);
- /* Set initial ownership of all Tx TXBBs to SW (1) */
- for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
- *((u32 *) (tx_ring->buf + j)) = 0xffffffff;
- ++tx_index;
+ /* Set initial ownership of all Tx TXBBs to SW (1) */
+ for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
+ *((u32 *)(tx_ring->buf + j)) = 0xffffffff;
+ }
}
/* Configure port */
@@ -1749,9 +1756,18 @@ int mlx4_en_start_port(struct net_device *dev)
return 0;
tx_err:
- while (tx_index--) {
- mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
- mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
+ if (t == MLX4_EN_NUM_TX_TYPES) {
+ t--;
+ i = priv->tx_ring_num[t];
+ }
+ while (t >= 0) {
+ while (i--) {
+ mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]);
+ mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]);
+ }
+ if (!t--)
+ break;
+ i = priv->tx_ring_num[t];
}
mlx4_en_destroy_drop_qp(priv);
rss_err:
@@ -1776,7 +1792,7 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_mc_list *mclist, *tmp;
struct ethtool_flow_id *flow, *tmp_flow;
- int i;
+ int i, t;
u8 mc_list[16] = {0};
if (!priv->port_up) {
@@ -1796,8 +1812,12 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
netif_tx_disable(dev);
+ spin_lock_bh(&priv->stats_lock);
+ mlx4_en_fold_software_stats(dev);
/* Set port as not active */
priv->port_up = false;
+ spin_unlock_bh(&priv->stats_lock);
+
priv->counter_index = MLX4_SINK_COUNTER_INDEX(mdev->dev);
/* Promsicuous mode */
@@ -1862,14 +1882,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
mlx4_en_destroy_drop_qp(priv);
/* Free TX Rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
- mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]);
+ mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]);
+ }
}
msleep(10);
- for (i = 0; i < priv->tx_ring_num; i++)
- mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+ for (i = 0; i < priv->tx_ring_num[t]; i++)
+ mlx4_en_free_tx_buf(dev, priv->tx_ring[t][i]);
if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
mlx4_en_delete_rss_steer_rules(priv);
@@ -1918,6 +1941,7 @@ static void mlx4_en_clear_stats(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring **tx_ring;
int i;
if (!mlx4_is_slave(mdev->dev))
@@ -1935,15 +1959,16 @@ static void mlx4_en_clear_stats(struct net_device *dev)
sizeof(priv->tx_priority_flowstats));
memset(&priv->pf_stats, 0, sizeof(priv->pf_stats));
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_ring[i]->bytes = 0;
- priv->tx_ring[i]->packets = 0;
- priv->tx_ring[i]->tx_csum = 0;
- priv->tx_ring[i]->tx_dropped = 0;
- priv->tx_ring[i]->queue_stopped = 0;
- priv->tx_ring[i]->wake_queue = 0;
- priv->tx_ring[i]->tso_packets = 0;
- priv->tx_ring[i]->xmit_more = 0;
+ tx_ring = priv->tx_ring[TX];
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ tx_ring[i]->bytes = 0;
+ tx_ring[i]->packets = 0;
+ tx_ring[i]->tx_csum = 0;
+ tx_ring[i]->tx_dropped = 0;
+ tx_ring[i]->queue_stopped = 0;
+ tx_ring[i]->wake_queue = 0;
+ tx_ring[i]->tso_packets = 0;
+ tx_ring[i]->xmit_more = 0;
}
for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_ring[i]->bytes = 0;
@@ -1999,17 +2024,20 @@ static int mlx4_en_close(struct net_device *dev)
static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
{
- int i;
+ int i, t;
#ifdef CONFIG_RFS_ACCEL
priv->dev->rx_cpu_rmap = NULL;
#endif
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (priv->tx_ring && priv->tx_ring[i])
- mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
- if (priv->tx_cq && priv->tx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ if (priv->tx_ring[t] && priv->tx_ring[t][i])
+ mlx4_en_destroy_tx_ring(priv,
+ &priv->tx_ring[t][i]);
+ if (priv->tx_cq[t] && priv->tx_cq[t][i])
+ mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
+ }
}
for (i = 0; i < priv->rx_ring_num; i++) {
@@ -2025,20 +2053,22 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
{
struct mlx4_en_port_profile *prof = priv->prof;
- int i;
+ int i, t;
int node;
/* Create tx Rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- node = cpu_to_node(i % num_online_cpus());
- if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
- prof->tx_ring_size, i, TX, node))
- goto err;
-
- if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
- prof->tx_ring_size, TXBB_SIZE,
- node, i))
- goto err;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ node = cpu_to_node(i % num_online_cpus());
+ if (mlx4_en_create_cq(priv, &priv->tx_cq[t][i],
+ prof->tx_ring_size, i, t, node))
+ goto err;
+
+ if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[t][i],
+ prof->tx_ring_size,
+ TXBB_SIZE, node, i))
+ goto err;
+ }
}
/* Create rx Rings */
@@ -2070,11 +2100,14 @@ err:
if (priv->rx_cq[i])
mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
}
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (priv->tx_ring[i])
- mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
- if (priv->tx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ for (i = 0; i < priv->tx_ring_num[t]; i++) {
+ if (priv->tx_ring[t][i])
+ mlx4_en_destroy_tx_ring(priv,
+ &priv->tx_ring[t][i]);
+ if (priv->tx_cq[t][i])
+ mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
+ }
}
return -ENOMEM;
}
@@ -2084,10 +2117,11 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst,
struct mlx4_en_priv *src,
struct mlx4_en_port_profile *prof)
{
+ int t;
+
memcpy(&dst->hwtstamp_config, &prof->hwtstamp_config,
sizeof(dst->hwtstamp_config));
dst->num_tx_rings_p_up = src->mdev->profile.num_tx_rings_p_up;
- dst->tx_ring_num = prof->tx_ring_num;
dst->rx_ring_num = prof->rx_ring_num;
dst->flags = prof->flags;
dst->mdev = src->mdev;
@@ -2097,33 +2131,50 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst,
dst->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
- dst->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS,
- GFP_KERNEL);
- if (!dst->tx_ring)
- return -ENOMEM;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ dst->tx_ring_num[t] = prof->tx_ring_num[t];
+ if (!dst->tx_ring_num[t])
+ continue;
- dst->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS,
- GFP_KERNEL);
- if (!dst->tx_cq) {
- kfree(dst->tx_ring);
- return -ENOMEM;
+ dst->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
+ MAX_TX_RINGS, GFP_KERNEL);
+ if (!dst->tx_ring[t])
+ goto err_free_tx;
+
+ dst->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
+ MAX_TX_RINGS, GFP_KERNEL);
+ if (!dst->tx_cq[t]) {
+ kfree(dst->tx_ring[t]);
+ goto err_free_tx;
+ }
}
+
return 0;
+
+err_free_tx:
+ while (t--) {
+ kfree(dst->tx_ring[t]);
+ kfree(dst->tx_cq[t]);
+ }
+ return -ENOMEM;
}
static void mlx4_en_update_priv(struct mlx4_en_priv *dst,
struct mlx4_en_priv *src)
{
+ int t;
memcpy(dst->rx_ring, src->rx_ring,
sizeof(struct mlx4_en_rx_ring *) * src->rx_ring_num);
memcpy(dst->rx_cq, src->rx_cq,
sizeof(struct mlx4_en_cq *) * src->rx_ring_num);
memcpy(&dst->hwtstamp_config, &src->hwtstamp_config,
sizeof(dst->hwtstamp_config));
- dst->tx_ring_num = src->tx_ring_num;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ dst->tx_ring_num[t] = src->tx_ring_num[t];
+ dst->tx_ring[t] = src->tx_ring[t];
+ dst->tx_cq[t] = src->tx_cq[t];
+ }
dst->rx_ring_num = src->rx_ring_num;
- dst->tx_ring = src->tx_ring;
- dst->tx_cq = src->tx_cq;
memcpy(dst->prof, src->prof, sizeof(struct mlx4_en_port_profile));
}
@@ -2131,14 +2182,18 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
struct mlx4_en_priv *tmp,
struct mlx4_en_port_profile *prof)
{
+ int t;
+
mlx4_en_copy_priv(tmp, priv, prof);
if (mlx4_en_alloc_resources(tmp)) {
en_warn(priv,
"%s: Resource allocation failed, using previous configuration\n",
__func__);
- kfree(tmp->tx_ring);
- kfree(tmp->tx_cq);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ kfree(tmp->tx_ring[t]);
+ kfree(tmp->tx_cq[t]);
+ }
return -ENOMEM;
}
return 0;
@@ -2155,6 +2210,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
+ int t;
en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
@@ -2188,12 +2244,27 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
mlx4_en_free_resources(priv);
mutex_unlock(&mdev->state_lock);
- kfree(priv->tx_ring);
- kfree(priv->tx_cq);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ kfree(priv->tx_ring[t]);
+ kfree(priv->tx_cq[t]);
+ }
free_netdev(dev);
}
+static bool mlx4_en_check_xdp_mtu(struct net_device *dev, int mtu)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ if (mtu > MLX4_EN_MAX_XDP_MTU) {
+ en_err(priv, "mtu:%d > max:%d when XDP prog is attached\n",
+ mtu, MLX4_EN_MAX_XDP_MTU);
+ return false;
+ }
+
+ return true;
+}
+
static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -2203,15 +2274,10 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
dev->mtu, new_mtu);
- if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
- en_err(priv, "Bad MTU size:%d.\n", new_mtu);
- return -EPERM;
- }
- if (priv->xdp_ring_num && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) {
- en_err(priv, "MTU size:%d requires frags but XDP running\n",
- new_mtu);
- return -EOPNOTSUPP;
- }
+ if (priv->tx_ring_num[TX_XDP] &&
+ !mlx4_en_check_xdp_mtu(dev, new_mtu))
+ return -ENOTSUPP;
+
dev->mtu = new_mtu;
if (netif_running(dev)) {
@@ -2598,7 +2664,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[queue_index];
+ struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][queue_index];
struct mlx4_update_qp_params params;
int err;
@@ -2626,18 +2692,21 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_port_profile new_prof;
struct bpf_prog *old_prog;
+ struct mlx4_en_priv *tmp;
+ int tx_changed = 0;
int xdp_ring_num;
int port_up = 0;
int err;
int i;
- xdp_ring_num = prog ? ALIGN(priv->rx_ring_num, MLX4_EN_NUM_UP) : 0;
+ xdp_ring_num = prog ? priv->rx_ring_num : 0;
/* No need to reconfigure buffers when simply swapping the
* program for a new one.
*/
- if (priv->xdp_ring_num == xdp_ring_num) {
+ if (priv->tx_ring_num[TX_XDP] == xdp_ring_num) {
if (prog) {
prog = bpf_prog_add(prog, priv->rx_ring_num - 1);
if (IS_ERR(prog))
@@ -2656,33 +2725,47 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
return 0;
}
- if (priv->num_frags > 1) {
- en_err(priv, "Cannot set XDP if MTU requires multiple frags\n");
+ if (!mlx4_en_check_xdp_mtu(dev, dev->mtu))
return -EOPNOTSUPP;
- }
- if (priv->tx_ring_num < xdp_ring_num + MLX4_EN_NUM_UP) {
- en_err(priv,
- "Minimum %d tx channels required to run XDP\n",
- (xdp_ring_num + MLX4_EN_NUM_UP) / MLX4_EN_NUM_UP);
- return -EINVAL;
- }
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
if (prog) {
prog = bpf_prog_add(prog, priv->rx_ring_num - 1);
- if (IS_ERR(prog))
- return PTR_ERR(prog);
+ if (IS_ERR(prog)) {
+ err = PTR_ERR(prog);
+ goto out;
+ }
}
mutex_lock(&mdev->state_lock);
+ memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
+ new_prof.tx_ring_num[TX_XDP] = xdp_ring_num;
+
+ if (priv->tx_ring_num[TX] + xdp_ring_num > MAX_TX_RINGS) {
+ tx_changed = 1;
+ new_prof.tx_ring_num[TX] =
+ MAX_TX_RINGS - ALIGN(xdp_ring_num, MLX4_EN_NUM_UP);
+ en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
+ }
+
+ err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+ if (err) {
+ if (prog)
+ bpf_prog_sub(prog, priv->rx_ring_num - 1);
+ goto unlock_out;
+ }
+
if (priv->port_up) {
port_up = 1;
mlx4_en_stop_port(dev, 1);
}
- priv->xdp_ring_num = xdp_ring_num;
- netif_set_real_num_tx_queues(dev, priv->tx_ring_num -
- priv->xdp_ring_num);
+ mlx4_en_safe_replace_resources(priv, tmp);
+ if (tx_changed)
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
for (i = 0; i < priv->rx_ring_num; i++) {
old_prog = rcu_dereference_protected(
@@ -2702,15 +2785,18 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
}
}
+unlock_out:
mutex_unlock(&mdev->state_lock);
- return 0;
+out:
+ kfree(tmp);
+ return err;
}
static bool mlx4_xdp_attached(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- return !!priv->xdp_ring_num;
+ return !!priv->tx_ring_num[TX_XDP];
}
static int mlx4_xdp(struct net_device *dev, struct netdev_xdp *xdp)
@@ -3047,6 +3133,10 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,
if (!mlx4_is_slave(dev))
bitmap_set(stats_bitmap->bitmap, last_i, NUM_PKT_STATS);
+ last_i += NUM_PKT_STATS;
+
+ bitmap_set(stats_bitmap->bitmap, last_i, NUM_XDP_STATS);
+ last_i += NUM_XDP_STATS;
}
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
@@ -3054,7 +3144,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
{
struct net_device *dev;
struct mlx4_en_priv *priv;
- int i;
+ int i, t;
int err;
dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
@@ -3062,7 +3152,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
if (dev == NULL)
return -ENOMEM;
- netif_set_real_num_tx_queues(dev, prof->tx_ring_num);
+ netif_set_real_num_tx_queues(dev, prof->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
SET_NETDEV_DEV(dev, &mdev->dev->persist->pdev->dev);
@@ -3099,21 +3189,27 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
MLX4_WQE_CTRL_SOLICITED);
priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
- priv->tx_ring_num = prof->tx_ring_num;
priv->tx_work_limit = MLX4_EN_DEFAULT_TX_WORK;
netdev_rss_key_fill(priv->rss_key, sizeof(priv->rss_key));
- priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS,
- GFP_KERNEL);
- if (!priv->tx_ring) {
- err = -ENOMEM;
- goto out;
- }
- priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS,
- GFP_KERNEL);
- if (!priv->tx_cq) {
- err = -ENOMEM;
- goto out;
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ priv->tx_ring_num[t] = prof->tx_ring_num[t];
+ if (!priv->tx_ring_num[t])
+ continue;
+
+ priv->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
+ MAX_TX_RINGS, GFP_KERNEL);
+ if (!priv->tx_ring[t]) {
+ err = -ENOMEM;
+ goto err_free_tx;
+ }
+ priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
+ MAX_TX_RINGS, GFP_KERNEL);
+ if (!priv->tx_cq[t]) {
+ kfree(priv->tx_ring[t]);
+ err = -ENOMEM;
+ goto out;
+ }
}
priv->rx_ring_num = prof->rx_ring_num;
priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
@@ -3196,7 +3292,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
else
dev->netdev_ops = &mlx4_netdev_ops;
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
- netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
dev->ethtool_ops = &mlx4_en_ethtool_ops;
@@ -3286,13 +3382,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
}
+ /* MTU range: 46 - hw-specific max */
+ dev->min_mtu = MLX4_EN_MIN_MTU;
+ dev->max_mtu = priv->max_mtu;
+
mdev->pndev[port] = dev;
mdev->upper[port] = NULL;
netif_carrier_off(dev);
mlx4_en_set_default_moderation(priv);
- en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
+ en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num[TX]);
en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
@@ -3352,6 +3452,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
return 0;
+err_free_tx:
+ while (t--) {
+ kfree(priv->tx_ring[t]);
+ kfree(priv->tx_cq[t]);
+ }
out:
mlx4_en_destroy_netdev(dev);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c
index 59473a0ebcdf..9166d90e7328 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c
@@ -147,6 +147,39 @@ static unsigned long en_stats_adder(__be64 *start, __be64 *next, int num)
return ret;
}
+void mlx4_en_fold_software_stats(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ unsigned long packets, bytes;
+ int i;
+
+ if (!priv->port_up || mlx4_is_master(mdev->dev))
+ return;
+
+ packets = 0;
+ bytes = 0;
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ const struct mlx4_en_rx_ring *ring = priv->rx_ring[i];
+
+ packets += READ_ONCE(ring->packets);
+ bytes += READ_ONCE(ring->bytes);
+ }
+ dev->stats.rx_packets = packets;
+ dev->stats.rx_bytes = bytes;
+
+ packets = 0;
+ bytes = 0;
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ const struct mlx4_en_tx_ring *ring = priv->tx_ring[TX][i];
+
+ packets += READ_ONCE(ring->packets);
+ bytes += READ_ONCE(ring->bytes);
+ }
+ dev->stats.tx_packets = packets;
+ dev->stats.tx_bytes = bytes;
+}
+
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
struct mlx4_counter tmp_counter_stats;
@@ -159,6 +192,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
u64 in_mod = reset << 8 | port;
int err;
int i, counter_index;
+ unsigned long sw_tx_dropped = 0;
unsigned long sw_rx_dropped = 0;
mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
@@ -174,40 +208,42 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
spin_lock_bh(&priv->stats_lock);
- stats->rx_packets = 0;
- stats->rx_bytes = 0;
+ mlx4_en_fold_software_stats(dev);
+
priv->port_stats.rx_chksum_good = 0;
priv->port_stats.rx_chksum_none = 0;
priv->port_stats.rx_chksum_complete = 0;
+ priv->xdp_stats.rx_xdp_drop = 0;
+ priv->xdp_stats.rx_xdp_tx = 0;
+ priv->xdp_stats.rx_xdp_tx_full = 0;
for (i = 0; i < priv->rx_ring_num; i++) {
- stats->rx_packets += priv->rx_ring[i]->packets;
- stats->rx_bytes += priv->rx_ring[i]->bytes;
- sw_rx_dropped += priv->rx_ring[i]->dropped;
- priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok;
- priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none;
- priv->port_stats.rx_chksum_complete += priv->rx_ring[i]->csum_complete;
+ const struct mlx4_en_rx_ring *ring = priv->rx_ring[i];
+
+ sw_rx_dropped += READ_ONCE(ring->dropped);
+ priv->port_stats.rx_chksum_good += READ_ONCE(ring->csum_ok);
+ priv->port_stats.rx_chksum_none += READ_ONCE(ring->csum_none);
+ priv->port_stats.rx_chksum_complete += READ_ONCE(ring->csum_complete);
+ priv->xdp_stats.rx_xdp_drop += READ_ONCE(ring->xdp_drop);
+ priv->xdp_stats.rx_xdp_tx += READ_ONCE(ring->xdp_tx);
+ priv->xdp_stats.rx_xdp_tx_full += READ_ONCE(ring->xdp_tx_full);
}
- stats->tx_packets = 0;
- stats->tx_bytes = 0;
- stats->tx_dropped = 0;
priv->port_stats.tx_chksum_offload = 0;
priv->port_stats.queue_stopped = 0;
priv->port_stats.wake_queue = 0;
priv->port_stats.tso_packets = 0;
priv->port_stats.xmit_more = 0;
- for (i = 0; i < priv->tx_ring_num; i++) {
- const struct mlx4_en_tx_ring *ring = priv->tx_ring[i];
-
- stats->tx_packets += ring->packets;
- stats->tx_bytes += ring->bytes;
- stats->tx_dropped += ring->tx_dropped;
- priv->port_stats.tx_chksum_offload += ring->tx_csum;
- priv->port_stats.queue_stopped += ring->queue_stopped;
- priv->port_stats.wake_queue += ring->wake_queue;
- priv->port_stats.tso_packets += ring->tso_packets;
- priv->port_stats.xmit_more += ring->xmit_more;
+ for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+ const struct mlx4_en_tx_ring *ring = priv->tx_ring[TX][i];
+
+ sw_tx_dropped += READ_ONCE(ring->tx_dropped);
+ priv->port_stats.tx_chksum_offload += READ_ONCE(ring->tx_csum);
+ priv->port_stats.queue_stopped += READ_ONCE(ring->queue_stopped);
+ priv->port_stats.wake_queue += READ_ONCE(ring->wake_queue);
+ priv->port_stats.tso_packets += READ_ONCE(ring->tso_packets);
+ priv->port_stats.xmit_more += READ_ONCE(ring->xmit_more);
}
+
if (mlx4_is_master(mdev->dev)) {
stats->rx_packets = en_stats_adder(&mlx4_en_stats->RTOT_prio_0,
&mlx4_en_stats->RTOT_prio_1,
@@ -245,7 +281,8 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
- stats->tx_dropped += be32_to_cpu(mlx4_en_stats->TDROP);
+ stats->tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP) +
+ sw_tx_dropped;
/* RX stats */
priv->pkstats.rx_multicast_packets = stats->multicast;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index f2e8beddcf44..3c37e216bbf3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -96,7 +96,6 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv,
struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
const struct mlx4_en_frag_info *frag_info;
struct page *page;
- dma_addr_t dma;
int i;
for (i = 0; i < priv->num_frags; i++) {
@@ -115,9 +114,10 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv,
for (i = 0; i < priv->num_frags; i++) {
frags[i] = ring_alloc[i];
- dma = ring_alloc[i].dma + ring_alloc[i].page_offset;
+ frags[i].page_offset += priv->frag_info[i].rx_headroom;
+ rx_desc->data[i].addr = cpu_to_be64(frags[i].dma +
+ frags[i].page_offset);
ring_alloc[i] = page_alloc[i];
- rx_desc->data[i].addr = cpu_to_be64(dma);
}
return 0;
@@ -250,7 +250,8 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
if (ring->page_cache.index > 0) {
frags[0] = ring->page_cache.buf[--ring->page_cache.index];
- rx_desc->data[0].addr = cpu_to_be64(frags[0].dma);
+ rx_desc->data[0].addr = cpu_to_be64(frags[0].dma +
+ frags[0].page_offset);
return 0;
}
@@ -688,18 +689,23 @@ out_loopback:
dev_kfree_skb_any(skb);
}
-static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring)
+static bool mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
{
- int index = ring->prod & ring->size_mask;
+ u32 missing = ring->actual_size - (ring->prod - ring->cons);
- while ((u32) (ring->prod - ring->cons) < ring->actual_size) {
- if (mlx4_en_prepare_rx_desc(priv, ring, index,
+ /* Try to batch allocations, but not too much. */
+ if (missing < 8)
+ return false;
+ do {
+ if (mlx4_en_prepare_rx_desc(priv, ring,
+ ring->prod & ring->size_mask,
GFP_ATOMIC | __GFP_COLD))
break;
ring->prod++;
- index = ring->prod & ring->size_mask;
- }
+ } while (--missing);
+
+ return true;
}
/* When hardware doesn't strip the vlan, we need to calculate the checksum
@@ -788,7 +794,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct bpf_prog *xdp_prog;
int doorbell_pending;
struct sk_buff *skb;
- int tx_index;
int index;
int nr;
unsigned int length;
@@ -808,7 +813,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
rcu_read_lock();
xdp_prog = rcu_dereference(ring->xdp_prog);
doorbell_pending = 0;
- tx_index = (priv->tx_ring_num - priv->xdp_ring_num) + cq->ring;
/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
* descriptor offset can be deduced from the CQE index instead of
@@ -877,8 +881,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
*/
length = be32_to_cpu(cqe->byte_cnt);
length -= ring->fcs_del;
- ring->bytes += length;
- ring->packets++;
l2_tunnel = (dev->hw_enc_features & NETIF_F_RXCSUM) &&
(cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
@@ -888,6 +890,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
if (xdp_prog) {
struct xdp_buff xdp;
dma_addr_t dma;
+ void *orig_data;
u32 act;
dma = be64_to_cpu(rx_desc->data[0].addr);
@@ -895,31 +898,43 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
priv->frag_info[0].frag_size,
DMA_FROM_DEVICE);
- xdp.data = page_address(frags[0].page) +
- frags[0].page_offset;
+ xdp.data_hard_start = page_address(frags[0].page);
+ xdp.data = xdp.data_hard_start + frags[0].page_offset;
xdp.data_end = xdp.data + length;
+ orig_data = xdp.data;
act = bpf_prog_run_xdp(xdp_prog, &xdp);
+
+ if (xdp.data != orig_data) {
+ length = xdp.data_end - xdp.data;
+ frags[0].page_offset = xdp.data -
+ xdp.data_hard_start;
+ }
+
switch (act) {
case XDP_PASS:
break;
case XDP_TX:
- if (likely(!mlx4_en_xmit_frame(frags, dev,
- length, tx_index,
+ if (likely(!mlx4_en_xmit_frame(ring, frags, dev,
+ length, cq->ring,
&doorbell_pending)))
goto consumed;
- goto xdp_drop; /* Drop on xmit failure */
+ goto xdp_drop_no_cnt; /* Drop on xmit failure */
default:
bpf_warn_invalid_xdp_action(act);
case XDP_ABORTED:
case XDP_DROP:
-xdp_drop:
+ ring->xdp_drop++;
+xdp_drop_no_cnt:
if (likely(mlx4_en_rx_recycle(ring, frags)))
goto consumed;
goto next;
}
}
+ ring->bytes += length;
+ ring->packets++;
+
if (likely(dev->features & NETIF_F_RXCSUM)) {
if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
MLX4_CQE_STATUS_UDP)) {
@@ -1081,15 +1096,20 @@ consumed:
out:
rcu_read_unlock();
- if (doorbell_pending)
- mlx4_en_xmit_doorbell(priv->tx_ring[tx_index]);
+ if (polled) {
+ if (doorbell_pending)
+ mlx4_en_xmit_doorbell(priv->tx_ring[TX_XDP][cq->ring]);
+
+ mlx4_cq_set_ci(&cq->mcq);
+ wmb(); /* ensure HW sees CQ consumer before we post new buffers */
+ ring->cons = cq->mcq.cons_index;
+ }
AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
- mlx4_cq_set_ci(&cq->mcq);
- wmb(); /* ensure HW sees CQ consumer before we post new buffers */
- ring->cons = cq->mcq.cons_index;
- mlx4_en_refill_rx_buffers(priv, ring);
- mlx4_en_update_rx_prod_db(ring);
+
+ if (mlx4_en_refill_rx_buffers(priv, ring))
+ mlx4_en_update_rx_prod_db(ring);
+
return polled;
}
@@ -1131,14 +1151,17 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
return budget;
/* Current cpu is not according to smp_irq_affinity -
- * probably affinity changed. need to stop this NAPI
- * poll, and restart it on the right CPU
+ * probably affinity changed. Need to stop this NAPI
+ * poll, and restart it on the right CPU.
+ * Try to avoid returning a too small value (like 0),
+ * to not fool net_rx_action() and its netdev_budget
*/
- done = 0;
+ if (done)
+ done--;
}
/* Done for now */
- napi_complete_done(napi, done);
- mlx4_en_arm_cq(priv, cq);
+ if (napi_complete_done(napi, done))
+ mlx4_en_arm_cq(priv, cq);
return done;
}
@@ -1151,37 +1174,41 @@ static const int frag_sizes[] = {
void mlx4_en_calc_rx_buf(struct net_device *dev)
{
- enum dma_data_direction dma_dir = PCI_DMA_FROMDEVICE;
struct mlx4_en_priv *priv = netdev_priv(dev);
int eff_mtu = MLX4_EN_EFF_MTU(dev->mtu);
- int order = MLX4_EN_ALLOC_PREFER_ORDER;
- u32 align = SMP_CACHE_BYTES;
- int buf_size = 0;
int i = 0;
/* bpf requires buffers to be set up as 1 packet per page.
* This only works when num_frags == 1.
*/
- if (priv->xdp_ring_num) {
- dma_dir = PCI_DMA_BIDIRECTIONAL;
- /* This will gain efficient xdp frame recycling at the expense
- * of more costly truesize accounting
+ if (priv->tx_ring_num[TX_XDP]) {
+ priv->frag_info[0].order = 0;
+ priv->frag_info[0].frag_size = eff_mtu;
+ priv->frag_info[0].frag_prefix_size = 0;
+ /* This will gain efficient xdp frame recycling at the
+ * expense of more costly truesize accounting
*/
- align = PAGE_SIZE;
- order = 0;
- }
-
- while (buf_size < eff_mtu) {
- priv->frag_info[i].order = order;
- priv->frag_info[i].frag_size =
- (eff_mtu > buf_size + frag_sizes[i]) ?
- frag_sizes[i] : eff_mtu - buf_size;
- priv->frag_info[i].frag_prefix_size = buf_size;
- priv->frag_info[i].frag_stride =
- ALIGN(priv->frag_info[i].frag_size, align);
- priv->frag_info[i].dma_dir = dma_dir;
- buf_size += priv->frag_info[i].frag_size;
- i++;
+ priv->frag_info[0].frag_stride = PAGE_SIZE;
+ priv->frag_info[0].dma_dir = PCI_DMA_BIDIRECTIONAL;
+ priv->frag_info[0].rx_headroom = XDP_PACKET_HEADROOM;
+ i = 1;
+ } else {
+ int buf_size = 0;
+
+ while (buf_size < eff_mtu) {
+ priv->frag_info[i].order = MLX4_EN_ALLOC_PREFER_ORDER;
+ priv->frag_info[i].frag_size =
+ (eff_mtu > buf_size + frag_sizes[i]) ?
+ frag_sizes[i] : eff_mtu - buf_size;
+ priv->frag_info[i].frag_prefix_size = buf_size;
+ priv->frag_info[i].frag_stride =
+ ALIGN(priv->frag_info[i].frag_size,
+ SMP_CACHE_BYTES);
+ priv->frag_info[i].dma_dir = PCI_DMA_FROMDEVICE;
+ priv->frag_info[i].rx_headroom = 0;
+ buf_size += priv->frag_info[i].frag_size;
+ i++;
+ }
}
priv->num_frags = i;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index c06346a82496..95290e1fc9fe 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
@@ -68,7 +68,7 @@ static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
eth_zero_addr(ethh->h_source);
ethh->h_proto = htons(ETH_P_ARP);
- skb_set_mac_header(skb, 0);
+ skb_reset_mac_header(skb);
for (i = 0; i < packet_size; ++i) /* fill our packet */
packet[i] = (unsigned char)(i & 0xff);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index e2509bba3e7c..5886ad78058f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -66,7 +66,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
ring->size = size;
ring->size_mask = size - 1;
- ring->stride = stride;
+ ring->sp_stride = stride;
ring->full_size = ring->size - HEADROOM - MAX_DESC_TXBBS;
tmp = size * sizeof(struct mlx4_en_tx_info);
@@ -90,22 +90,22 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
goto err_info;
}
}
- ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE);
+ ring->buf_size = ALIGN(size * ring->sp_stride, MLX4_EN_PAGE_SIZE);
/* Allocate HW buffers on provided NUMA node */
set_dev_node(&mdev->dev->persist->pdev->dev, node);
- err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ err = mlx4_alloc_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
set_dev_node(&mdev->dev->persist->pdev->dev, mdev->dev->numa_node);
if (err) {
en_err(priv, "Failed allocating hwq resources\n");
goto err_bounce;
}
- ring->buf = ring->wqres.buf.direct.buf;
+ ring->buf = ring->sp_wqres.buf.direct.buf;
en_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d buf_size:%d dma:%llx\n",
ring, ring->buf, ring->size, ring->buf_size,
- (unsigned long long) ring->wqres.buf.direct.map);
+ (unsigned long long) ring->sp_wqres.buf.direct.map);
err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn,
MLX4_RESERVE_ETH_BF_QP);
@@ -114,12 +114,12 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
goto err_hwq_res;
}
- err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp, GFP_KERNEL);
+ err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->sp_qp, GFP_KERNEL);
if (err) {
en_err(priv, "Failed allocating qp %d\n", ring->qpn);
goto err_reserve;
}
- ring->qp.event = mlx4_en_sqp_event;
+ ring->sp_qp.event = mlx4_en_sqp_event;
err = mlx4_bf_alloc(mdev->dev, &ring->bf, node);
if (err) {
@@ -141,7 +141,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
if (queue_index < priv->num_tx_rings_p_up)
cpumask_set_cpu(cpumask_local_spread(queue_index,
priv->mdev->dev->numa_node),
- &ring->affinity_mask);
+ &ring->sp_affinity_mask);
*pring = ring;
return 0;
@@ -149,7 +149,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
err_reserve:
mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
err_hwq_res:
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ mlx4_free_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
err_bounce:
kfree(ring->bounce_buf);
ring->bounce_buf = NULL;
@@ -171,10 +171,10 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
if (ring->bf_alloced)
mlx4_bf_free(mdev->dev, &ring->bf);
- mlx4_qp_remove(mdev->dev, &ring->qp);
- mlx4_qp_free(mdev->dev, &ring->qp);
+ mlx4_qp_remove(mdev->dev, &ring->sp_qp);
+ mlx4_qp_free(mdev->dev, &ring->sp_qp);
mlx4_qp_release_range(priv->mdev->dev, ring->qpn, 1);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ mlx4_free_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
kfree(ring->bounce_buf);
ring->bounce_buf = NULL;
kvfree(ring->tx_info);
@@ -190,7 +190,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_dev *mdev = priv->mdev;
int err;
- ring->cqn = cq;
+ ring->sp_cqn = cq;
ring->prod = 0;
ring->cons = 0xffffffff;
ring->last_nr_txbb = 1;
@@ -198,21 +198,21 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
memset(ring->buf, 0, ring->buf_size);
ring->free_tx_desc = mlx4_en_free_tx_desc;
- ring->qp_state = MLX4_QP_STATE_RST;
- ring->doorbell_qpn = cpu_to_be32(ring->qp.qpn << 8);
+ ring->sp_qp_state = MLX4_QP_STATE_RST;
+ ring->doorbell_qpn = cpu_to_be32(ring->sp_qp.qpn << 8);
ring->mr_key = cpu_to_be32(mdev->mr.key);
- mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, user_prio, &ring->context);
+ mlx4_en_fill_qp_context(priv, ring->size, ring->sp_stride, 1, 0, ring->qpn,
+ ring->sp_cqn, user_prio, &ring->sp_context);
if (ring->bf_alloced)
- ring->context.usr_page =
+ ring->sp_context.usr_page =
cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev,
ring->bf.uar->index));
- err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
- &ring->qp, &ring->qp_state);
- if (!cpumask_empty(&ring->affinity_mask))
- netif_set_xps_queue(priv->dev, &ring->affinity_mask,
+ err = mlx4_qp_to_ready(mdev->dev, &ring->sp_wqres.mtt, &ring->sp_context,
+ &ring->sp_qp, &ring->sp_qp_state);
+ if (!cpumask_empty(&ring->sp_affinity_mask))
+ netif_set_xps_queue(priv->dev, &ring->sp_affinity_mask,
ring->queue_index);
return err;
@@ -223,8 +223,8 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
{
struct mlx4_en_dev *mdev = priv->mdev;
- mlx4_qp_modify(mdev->dev, NULL, ring->qp_state,
- MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
+ mlx4_qp_modify(mdev->dev, NULL, ring->sp_qp_state,
+ MLX4_QP_STATE_RST, NULL, 0, 0, &ring->sp_qp);
}
static inline bool mlx4_en_is_tx_ring_full(struct mlx4_en_tx_ring *ring)
@@ -354,7 +354,7 @@ u32 mlx4_en_recycle_tx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_alloc frame = {
.page = tx_info->page,
.dma = tx_info->map0_dma,
- .page_offset = 0,
+ .page_offset = XDP_PACKET_HEADROOM,
.page_size = PAGE_SIZE,
};
@@ -392,7 +392,8 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
cnt++;
}
- netdev_tx_reset_queue(ring->tx_queue);
+ if (ring->tx_queue)
+ netdev_tx_reset_queue(ring->tx_queue);
if (cnt)
en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
@@ -405,7 +406,7 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_cq *mcq = &cq->mcq;
- struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
+ struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->type][cq->ring];
struct mlx4_cqe *cqe;
u16 index;
u16 new_index, ring_index, stamp_index;
@@ -807,7 +808,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
bool bf_ok;
tx_ind = skb_get_queue_mapping(skb);
- ring = priv->tx_ring[tx_ind];
+ ring = priv->tx_ring[TX][tx_ind];
if (!priv->port_up)
goto tx_drop;
@@ -1078,7 +1079,8 @@ tx_drop:
return NETDEV_TX_OK;
}
-netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
+netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring,
+ struct mlx4_en_rx_alloc *frame,
struct net_device *dev, unsigned int length,
int tx_ind, int *doorbell_pending)
{
@@ -1101,7 +1103,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
BUILD_BUG_ON_MSG(ALIGN(CTRL_SIZE + DS_SIZE, TXBB_SIZE) != TXBB_SIZE,
"mlx4_en_xmit_frame requires minimum size tx desc");
- ring = priv->tx_ring[tx_ind];
+ ring = priv->tx_ring[TX_XDP][tx_ind];
if (!priv->port_up)
goto tx_drop;
@@ -1130,7 +1132,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
tx_info->page = frame->page;
frame->page = NULL;
tx_info->map0_dma = dma;
- tx_info->map0_byte_count = length;
+ tx_info->map0_byte_count = PAGE_SIZE;
tx_info->nr_txbb = nr_txbb;
tx_info->nr_bytes = max_t(unsigned int, length, ETH_ZLEN);
tx_info->data_offset = (void *)data - (void *)tx_desc;
@@ -1139,9 +1141,10 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
tx_info->linear = 1;
tx_info->inl = 0;
- dma_sync_single_for_device(priv->ddev, dma, length, PCI_DMA_TODEVICE);
+ dma_sync_single_range_for_device(priv->ddev, dma, frame->page_offset,
+ length, PCI_DMA_TODEVICE);
- data->addr = cpu_to_be64(dma);
+ data->addr = cpu_to_be64(dma + frame->page_offset);
data->lkey = ring->mr_key;
dma_wmb();
data->byte_count = cpu_to_be32(length);
@@ -1153,8 +1156,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
((ring->prod & ring->size) ?
cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
- ring->packets++;
- ring->bytes += tx_info->nr_bytes;
+ rx_ring->xdp_tx++;
AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, length);
ring->prod += nr_txbb;
@@ -1178,7 +1180,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
return NETDEV_TX_OK;
tx_drop_count:
- ring->tx_dropped++;
+ rx_ring->xdp_tx_full++;
tx_drop:
return NETDEV_TX_BUSY;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index a3528dd1e72e..ba1c6cd0cc79 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -207,8 +207,11 @@ enum {
*/
enum cq_type {
- RX = 0,
- TX = 1,
+ /* keep tx types first */
+ TX,
+ TX_XDP,
+#define MLX4_EN_NUM_TX_TYPES (TX_XDP + 1)
+ RX,
};
@@ -278,46 +281,50 @@ struct mlx4_en_tx_ring {
u32 last_nr_txbb;
u32 cons;
unsigned long wake_queue;
+ struct netdev_queue *tx_queue;
+ u32 (*free_tx_desc)(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ int index, u8 owner,
+ u64 timestamp, int napi_mode);
+ struct mlx4_en_rx_ring *recycle_ring;
/* cache line used and dirtied in mlx4_en_xmit() */
u32 prod ____cacheline_aligned_in_smp;
+ unsigned int tx_dropped;
unsigned long bytes;
unsigned long packets;
unsigned long tx_csum;
unsigned long tso_packets;
unsigned long xmit_more;
- unsigned int tx_dropped;
struct mlx4_bf bf;
- unsigned long queue_stopped;
/* Following part should be mostly read */
- cpumask_t affinity_mask;
- struct mlx4_qp qp;
- struct mlx4_hwq_resources wqres;
+ __be32 doorbell_qpn;
+ __be32 mr_key;
u32 size; /* number of TXBBs */
u32 size_mask;
- u16 stride;
u32 full_size;
- u16 cqn; /* index of port CQ associated with this ring */
u32 buf_size;
- __be32 doorbell_qpn;
- __be32 mr_key;
void *buf;
struct mlx4_en_tx_info *tx_info;
- struct mlx4_en_rx_ring *recycle_ring;
- u32 (*free_tx_desc)(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring,
- int index, u8 owner,
- u64 timestamp, int napi_mode);
- u8 *bounce_buf;
- struct mlx4_qp_context context;
int qpn;
- enum mlx4_qp_state qp_state;
u8 queue_index;
bool bf_enabled;
bool bf_alloced;
- struct netdev_queue *tx_queue;
- int hwtstamp_tx_type;
+ u8 hwtstamp_tx_type;
+ u8 *bounce_buf;
+
+ /* Not used in fast path
+ * Only queue_stopped might be used if BQL is not properly working.
+ */
+ unsigned long queue_stopped;
+ struct mlx4_hwq_resources sp_wqres;
+ struct mlx4_qp sp_qp;
+ struct mlx4_qp_context sp_context;
+ cpumask_t sp_affinity_mask;
+ enum mlx4_qp_state sp_qp_state;
+ u16 sp_stride;
+ u16 sp_cqn; /* index of port CQ associated with this ring */
} ____cacheline_aligned_in_smp;
struct mlx4_en_rx_desc {
@@ -347,6 +354,9 @@ struct mlx4_en_rx_ring {
unsigned long csum_ok;
unsigned long csum_none;
unsigned long csum_complete;
+ unsigned long xdp_drop;
+ unsigned long xdp_tx;
+ unsigned long xdp_tx_full;
unsigned long dropped;
int hwtstamp_rx_filter;
cpumask_var_t affinity_mask;
@@ -361,7 +371,7 @@ struct mlx4_en_cq {
int size;
int buf_size;
int vector;
- enum cq_type is_tx;
+ enum cq_type type;
u16 moder_time;
u16 moder_cnt;
struct mlx4_cqe *buf;
@@ -372,7 +382,7 @@ struct mlx4_en_cq {
struct mlx4_en_port_profile {
u32 flags;
- u32 tx_ring_num;
+ u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES];
u32 rx_ring_num;
u32 tx_ring_size;
u32 rx_ring_size;
@@ -465,7 +475,8 @@ struct mlx4_en_frag_info {
u16 frag_prefix_size;
u32 frag_stride;
enum dma_data_direction dma_dir;
- int order;
+ u16 order;
+ u16 rx_headroom;
};
#ifdef CONFIG_MLX4_EN_DCB
@@ -569,17 +580,16 @@ struct mlx4_en_priv {
u32 flags;
u8 num_tx_rings_p_up;
u32 tx_work_limit;
- u32 tx_ring_num;
+ u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES];
u32 rx_ring_num;
u32 rx_skb_size;
struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
u16 num_frags;
u16 log_rx_info;
- int xdp_ring_num;
- struct mlx4_en_tx_ring **tx_ring;
+ struct mlx4_en_tx_ring **tx_ring[MLX4_EN_NUM_TX_TYPES];
struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS];
- struct mlx4_en_cq **tx_cq;
+ struct mlx4_en_cq **tx_cq[MLX4_EN_NUM_TX_TYPES];
struct mlx4_en_cq *rx_cq[MAX_RX_RINGS];
struct mlx4_qp drop_qp;
struct work_struct rx_mode_task;
@@ -597,6 +607,7 @@ struct mlx4_en_priv {
struct mlx4_en_flow_stats_rx rx_flowstats;
struct mlx4_en_flow_stats_tx tx_flowstats;
struct mlx4_en_port_stats port_stats;
+ struct mlx4_en_xdp_stats xdp_stats;
struct mlx4_en_stats_bitmap stats_bitmap;
struct list_head mc_list;
struct list_head curr_list;
@@ -685,7 +696,8 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq);
u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
void *accel_priv, select_queue_fallback_t fallback);
netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
-netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
+netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring,
+ struct mlx4_en_rx_alloc *frame,
struct net_device *dev, unsigned int length,
int tx_ind, int *doorbell_pending);
void mlx4_en_xmit_doorbell(struct mlx4_en_tx_ring *ring);
@@ -744,6 +756,7 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq);
int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
+void mlx4_en_fold_software_stats(struct net_device *dev);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h
index 7fd466c0b929..48641cb0367f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h
@@ -55,6 +55,13 @@ struct mlx4_en_perf_stats {
#define NUM_PERF_COUNTERS 6
};
+struct mlx4_en_xdp_stats {
+ unsigned long rx_xdp_drop;
+ unsigned long rx_xdp_tx;
+ unsigned long rx_xdp_tx_full;
+#define NUM_XDP_STATS 3
+};
+
#define NUM_MAIN_STATS 21
#define MLX4_NUM_PRIORITIES 8
@@ -107,7 +114,8 @@ enum {
};
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \
- NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS)
+ NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS + \
+ NUM_XDP_STATS)
#define MLX4_FIND_NETDEV_STAT(n) (offsetof(struct net_device_stats, n) / \
sizeof(((struct net_device_stats *)0)->n))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index 521cfdb7d11e..ddb4ca4ff930 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -14,7 +14,7 @@ config MLX5_CORE
config MLX5_CORE_EN
bool "Mellanox Technologies ConnectX-4 Ethernet support"
depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
default n
---help---
Ethernet support in Mellanox Technologies ConnectX-4 NIC.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 0343725d7f44..9f43beb86250 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -8,6 +8,6 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \
- en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o
+ en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o en_selftest.o
mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
index 2c6e3c7b7417..66bd213f35ce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
@@ -106,6 +106,63 @@ void mlx5_buf_free(struct mlx5_core_dev *dev, struct mlx5_buf *buf)
}
EXPORT_SYMBOL_GPL(mlx5_buf_free);
+int mlx5_frag_buf_alloc_node(struct mlx5_core_dev *dev, int size,
+ struct mlx5_frag_buf *buf, int node)
+{
+ int i;
+
+ buf->size = size;
+ buf->npages = 1 << get_order(size);
+ buf->page_shift = PAGE_SHIFT;
+ buf->frags = kcalloc(buf->npages, sizeof(struct mlx5_buf_list),
+ GFP_KERNEL);
+ if (!buf->frags)
+ goto err_out;
+
+ for (i = 0; i < buf->npages; i++) {
+ struct mlx5_buf_list *frag = &buf->frags[i];
+ int frag_sz = min_t(int, size, PAGE_SIZE);
+
+ frag->buf = mlx5_dma_zalloc_coherent_node(dev, frag_sz,
+ &frag->map, node);
+ if (!frag->buf)
+ goto err_free_buf;
+ if (frag->map & ((1 << buf->page_shift) - 1)) {
+ dma_free_coherent(&dev->pdev->dev, frag_sz,
+ buf->frags[i].buf, buf->frags[i].map);
+ mlx5_core_warn(dev, "unexpected map alignment: %pad, page_shift=%d\n",
+ &frag->map, buf->page_shift);
+ goto err_free_buf;
+ }
+ size -= frag_sz;
+ }
+
+ return 0;
+
+err_free_buf:
+ while (i--)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, buf->frags[i].buf,
+ buf->frags[i].map);
+ kfree(buf->frags);
+err_out:
+ return -ENOMEM;
+}
+
+void mlx5_frag_buf_free(struct mlx5_core_dev *dev, struct mlx5_frag_buf *buf)
+{
+ int size = buf->size;
+ int i;
+
+ for (i = 0; i < buf->npages; i++) {
+ int frag_sz = min_t(int, size, PAGE_SIZE);
+
+ dma_free_coherent(&dev->pdev->dev, frag_sz, buf->frags[i].buf,
+ buf->frags[i].map);
+ size -= frag_sz;
+ }
+ kfree(buf->frags);
+}
+
static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
int node)
{
@@ -230,3 +287,12 @@ void mlx5_fill_page_array(struct mlx5_buf *buf, __be64 *pas)
}
}
EXPORT_SYMBOL_GPL(mlx5_fill_page_array);
+
+void mlx5_fill_page_frag_array(struct mlx5_frag_buf *buf, __be64 *pas)
+{
+ int i;
+
+ for (i = 0; i < buf->npages; i++)
+ pas[i] = cpu_to_be64(buf->frags[i].map);
+}
+EXPORT_SYMBOL_GPL(mlx5_fill_page_frag_array);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index bfe410e8a469..3797cc7c1288 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -54,14 +54,6 @@ enum {
};
enum {
- NUM_LONG_LISTS = 2,
- NUM_MED_LISTS = 64,
- LONG_LIST_SIZE = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 +
- MLX5_CMD_DATA_BLOCK_SIZE,
- MED_LIST_SIZE = 16 + MLX5_CMD_DATA_BLOCK_SIZE,
-};
-
-enum {
MLX5_CMD_DELIVERY_STAT_OK = 0x0,
MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR = 0x1,
MLX5_CMD_DELIVERY_STAT_TOK_ERR = 0x2,
@@ -313,6 +305,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT:
case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER:
+ case MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT:
+ case MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT:
return MLX5_CMD_STAT_OK;
case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -414,11 +408,14 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
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_QUERY_FLOW_TABLE_ENTRY:
case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+ case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
+ case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
+ case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
+ case MLX5_CMD_OP_CREATE_QOS_PARA_VPORT:
*status = MLX5_DRIVER_STATUS_ABORTED;
*synd = MLX5_DRIVER_SYND;
return -EIO;
@@ -575,6 +572,12 @@ const char *mlx5_command_str(int command)
MLX5_COMMAND_STR_CASE(MODIFY_FLOW_TABLE);
MLX5_COMMAND_STR_CASE(ALLOC_ENCAP_HEADER);
MLX5_COMMAND_STR_CASE(DEALLOC_ENCAP_HEADER);
+ MLX5_COMMAND_STR_CASE(CREATE_SCHEDULING_ELEMENT);
+ MLX5_COMMAND_STR_CASE(DESTROY_SCHEDULING_ELEMENT);
+ MLX5_COMMAND_STR_CASE(QUERY_SCHEDULING_ELEMENT);
+ MLX5_COMMAND_STR_CASE(MODIFY_SCHEDULING_ELEMENT);
+ MLX5_COMMAND_STR_CASE(CREATE_QOS_PARA_VPORT);
+ MLX5_COMMAND_STR_CASE(DESTROY_QOS_PARA_VPORT);
default: return "unknown command opcode";
}
}
@@ -1058,14 +1061,13 @@ static struct mlx5_cmd_mailbox *alloc_cmd_box(struct mlx5_core_dev *dev,
if (!mailbox)
return ERR_PTR(-ENOMEM);
- mailbox->buf = pci_pool_alloc(dev->cmd.pool, flags,
- &mailbox->dma);
+ mailbox->buf = pci_pool_zalloc(dev->cmd.pool, flags,
+ &mailbox->dma);
if (!mailbox->buf) {
mlx5_core_dbg(dev, "failed allocation\n");
kfree(mailbox);
return ERR_PTR(-ENOMEM);
}
- memset(mailbox->buf, 0, sizeof(struct mlx5_cmd_prot_block));
mailbox->next = NULL;
return mailbox;
@@ -1356,10 +1358,10 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
{
unsigned long flags;
- if (msg->cache) {
- spin_lock_irqsave(&msg->cache->lock, flags);
- list_add_tail(&msg->list, &msg->cache->head);
- spin_unlock_irqrestore(&msg->cache->lock, flags);
+ if (msg->parent) {
+ spin_lock_irqsave(&msg->parent->lock, flags);
+ list_add_tail(&msg->list, &msg->parent->head);
+ spin_unlock_irqrestore(&msg->parent->lock, flags);
} else {
mlx5_free_cmd_msg(dev, msg);
}
@@ -1456,30 +1458,37 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size,
gfp_t gfp)
{
struct mlx5_cmd_msg *msg = ERR_PTR(-ENOMEM);
+ struct cmd_msg_cache *ch = NULL;
struct mlx5_cmd *cmd = &dev->cmd;
- struct cache_ent *ent = NULL;
-
- if (in_size > MED_LIST_SIZE && in_size <= LONG_LIST_SIZE)
- ent = &cmd->cache.large;
- else if (in_size > 16 && in_size <= MED_LIST_SIZE)
- ent = &cmd->cache.med;
-
- if (ent) {
- spin_lock_irq(&ent->lock);
- if (!list_empty(&ent->head)) {
- msg = list_entry(ent->head.next, typeof(*msg), list);
- /* For cached lists, we must explicitly state what is
- * the real size
- */
- msg->len = in_size;
- list_del(&msg->list);
+ int i;
+
+ if (in_size <= 16)
+ goto cache_miss;
+
+ for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
+ ch = &cmd->cache[i];
+ if (in_size > ch->max_inbox_size)
+ continue;
+ spin_lock_irq(&ch->lock);
+ if (list_empty(&ch->head)) {
+ spin_unlock_irq(&ch->lock);
+ continue;
}
- spin_unlock_irq(&ent->lock);
+ msg = list_entry(ch->head.next, typeof(*msg), list);
+ /* For cached lists, we must explicitly state what is
+ * the real size
+ */
+ msg->len = in_size;
+ list_del(&msg->list);
+ spin_unlock_irq(&ch->lock);
+ break;
}
- if (IS_ERR(msg))
- msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
+ if (!IS_ERR(msg))
+ return msg;
+cache_miss:
+ msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
return msg;
}
@@ -1577,58 +1586,56 @@ EXPORT_SYMBOL(mlx5_cmd_exec_cb);
static void destroy_msg_cache(struct mlx5_core_dev *dev)
{
- struct mlx5_cmd *cmd = &dev->cmd;
+ struct cmd_msg_cache *ch;
struct mlx5_cmd_msg *msg;
struct mlx5_cmd_msg *n;
+ int i;
- list_for_each_entry_safe(msg, n, &cmd->cache.large.head, list) {
- list_del(&msg->list);
- mlx5_free_cmd_msg(dev, msg);
- }
-
- list_for_each_entry_safe(msg, n, &cmd->cache.med.head, list) {
- list_del(&msg->list);
- mlx5_free_cmd_msg(dev, msg);
+ for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
+ ch = &dev->cmd.cache[i];
+ list_for_each_entry_safe(msg, n, &ch->head, list) {
+ list_del(&msg->list);
+ mlx5_free_cmd_msg(dev, msg);
+ }
}
}
-static int create_msg_cache(struct mlx5_core_dev *dev)
+static unsigned cmd_cache_num_ent[MLX5_NUM_COMMAND_CACHES] = {
+ 512, 32, 16, 8, 2
+};
+
+static unsigned cmd_cache_ent_size[MLX5_NUM_COMMAND_CACHES] = {
+ 16 + MLX5_CMD_DATA_BLOCK_SIZE,
+ 16 + MLX5_CMD_DATA_BLOCK_SIZE * 2,
+ 16 + MLX5_CMD_DATA_BLOCK_SIZE * 16,
+ 16 + MLX5_CMD_DATA_BLOCK_SIZE * 256,
+ 16 + MLX5_CMD_DATA_BLOCK_SIZE * 512,
+};
+
+static void create_msg_cache(struct mlx5_core_dev *dev)
{
struct mlx5_cmd *cmd = &dev->cmd;
+ struct cmd_msg_cache *ch;
struct mlx5_cmd_msg *msg;
- int err;
int i;
-
- spin_lock_init(&cmd->cache.large.lock);
- INIT_LIST_HEAD(&cmd->cache.large.head);
- spin_lock_init(&cmd->cache.med.lock);
- INIT_LIST_HEAD(&cmd->cache.med.head);
-
- for (i = 0; i < NUM_LONG_LISTS; i++) {
- msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0);
- if (IS_ERR(msg)) {
- err = PTR_ERR(msg);
- goto ex_err;
- }
- msg->cache = &cmd->cache.large;
- list_add_tail(&msg->list, &cmd->cache.large.head);
- }
-
- for (i = 0; i < NUM_MED_LISTS; i++) {
- msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0);
- if (IS_ERR(msg)) {
- err = PTR_ERR(msg);
- goto ex_err;
+ int k;
+
+ /* Initialize and fill the caches with initial entries */
+ for (k = 0; k < MLX5_NUM_COMMAND_CACHES; k++) {
+ ch = &cmd->cache[k];
+ spin_lock_init(&ch->lock);
+ INIT_LIST_HEAD(&ch->head);
+ ch->num_ent = cmd_cache_num_ent[k];
+ ch->max_inbox_size = cmd_cache_ent_size[k];
+ for (i = 0; i < ch->num_ent; i++) {
+ msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL | __GFP_NOWARN,
+ ch->max_inbox_size, 0);
+ if (IS_ERR(msg))
+ break;
+ msg->parent = ch;
+ list_add_tail(&msg->list, &ch->head);
}
- msg->cache = &cmd->cache.med;
- list_add_tail(&msg->list, &cmd->cache.med.head);
}
-
- return 0;
-
-ex_err:
- destroy_msg_cache(dev);
- return err;
}
static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
@@ -1751,11 +1758,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
cmd->mode = CMD_MODE_POLLING;
- err = create_msg_cache(dev);
- if (err) {
- dev_err(&dev->pdev->dev, "failed to create command cache\n");
- goto err_free_page;
- }
+ create_msg_cache(dev);
set_wqname(dev);
cmd->wq = create_singlethread_workqueue(cmd->wq_name);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 71382df59fc0..951dbd58594d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -77,9 +77,9 @@
MLX5_MPWRQ_WQE_PAGE_ORDER)
#define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2)
-#define MLX5E_REQUIRED_MTTS(rqs, wqes)\
- (rqs * wqes * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
-#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) <= U16_MAX)
+#define MLX5E_REQUIRED_MTTS(wqes) \
+ (wqes * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
+#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) - 1 <= U16_MAX)
#define MLX5_UMR_ALIGN (2048)
#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128)
@@ -150,12 +150,6 @@ static inline int mlx5_max_log_rq_size(int wq_type)
}
}
-enum {
- MLX5E_INLINE_MODE_L2,
- MLX5E_INLINE_MODE_VPORT_CONTEXT,
- MLX5_INLINE_MODE_NOT_REQUIRED,
-};
-
struct mlx5e_tx_wqe {
struct mlx5_wqe_ctrl_seg ctrl;
struct mlx5_wqe_eth_seg eth;
@@ -173,22 +167,28 @@ struct mlx5e_umr_wqe {
struct mlx5_wqe_data_seg data;
};
+extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
+
static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
"rx_cqe_moder",
+ "rx_cqe_compress",
};
enum mlx5e_priv_flag {
MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
+ MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 1),
};
-#define MLX5E_SET_PRIV_FLAG(priv, pflag, enable) \
- do { \
- if (enable) \
- priv->pflags |= pflag; \
- else \
- priv->pflags &= ~pflag; \
+#define MLX5E_SET_PFLAG(priv, pflag, enable) \
+ do { \
+ if (enable) \
+ (priv)->params.pflags |= (pflag); \
+ else \
+ (priv)->params.pflags &= ~(pflag); \
} while (0)
+#define MLX5E_GET_PFLAG(priv, pflag) (!!((priv)->params.pflags & (pflag)))
+
#ifdef CONFIG_MLX5_CORE_EN_DCB
#define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
#endif
@@ -207,8 +207,7 @@ struct mlx5e_params {
u16 num_channels;
u8 num_tc;
u8 rx_cq_period_mode;
- bool rx_cqe_compress_admin;
- bool rx_cqe_compress;
+ bool rx_cqe_compress_def;
struct mlx5e_cq_moder rx_cq_moderation;
struct mlx5e_cq_moder tx_cq_moderation;
u16 min_rx_wqes;
@@ -220,12 +219,34 @@ struct mlx5e_params {
u8 toeplitz_hash_key[40];
u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
bool vlan_strip_disable;
-#ifdef CONFIG_MLX5_CORE_EN_DCB
- struct ieee_ets ets;
-#endif
bool rx_am_enabled;
u32 lro_timeout;
+ u32 pflags;
+};
+
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+struct mlx5e_cee_config {
+ /* bw pct for priority group */
+ u8 pg_bw_pct[CEE_DCBX_MAX_PGS];
+ u8 prio_to_pg_map[CEE_DCBX_MAX_PRIO];
+ bool pfc_setting[CEE_DCBX_MAX_PRIO];
+ bool pfc_enable;
+};
+
+enum {
+ MLX5_DCB_CHG_RESET,
+ MLX5_DCB_NO_CHG,
+ MLX5_DCB_CHG_NO_RESET,
+};
+
+struct mlx5e_dcbx {
+ enum mlx5_dcbx_oper_mode mode;
+ struct mlx5e_cee_config cee_cfg; /* pending configuration */
+
+ /* The only setting that cannot be read from FW */
+ u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
};
+#endif
struct mlx5e_tstamp {
rwlock_t lock;
@@ -265,7 +286,7 @@ struct mlx5e_cq {
u16 decmprs_wqe_counter;
/* control */
- struct mlx5_wq_ctrl wq_ctrl;
+ struct mlx5_frag_wq_ctrl wq_ctrl;
} ____cacheline_aligned_in_smp;
struct mlx5e_rq;
@@ -326,7 +347,6 @@ struct mlx5e_rq {
struct {
struct mlx5e_mpw_info *info;
void *mtt_no_align;
- u32 mtt_offset;
} mpwqe;
};
struct {
@@ -361,6 +381,7 @@ struct mlx5e_rq {
u32 rqn;
struct mlx5e_channel *channel;
struct mlx5e_priv *priv;
+ struct mlx5_core_mkey umr_mkey;
} ____cacheline_aligned_in_smp;
struct mlx5e_umr_dma_info {
@@ -524,7 +545,7 @@ struct mlx5e_vxlan_db {
struct mlx5e_l2_rule {
u8 addr[ETH_ALEN + 2];
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
};
struct mlx5e_flow_table {
@@ -545,10 +566,10 @@ struct mlx5e_tc_table {
struct mlx5e_vlan_table {
struct mlx5e_flow_table ft;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- struct mlx5_flow_rule *active_vlans_rule[VLAN_N_VID];
- struct mlx5_flow_rule *untagged_rule;
- struct mlx5_flow_rule *any_vlan_rule;
- bool filter_disabled;
+ struct mlx5_flow_handle *active_vlans_rule[VLAN_N_VID];
+ struct mlx5_flow_handle *untagged_rule;
+ struct mlx5_flow_handle *any_vlan_rule;
+ bool filter_disabled;
};
struct mlx5e_l2_table {
@@ -566,14 +587,14 @@ struct mlx5e_l2_table {
/* L3/L4 traffic type classifier */
struct mlx5e_ttc_table {
struct mlx5e_flow_table ft;
- struct mlx5_flow_rule *rules[MLX5E_NUM_TT];
+ struct mlx5_flow_handle *rules[MLX5E_NUM_TT];
};
#define ARFS_HASH_SHIFT BITS_PER_BYTE
#define ARFS_HASH_SIZE BIT(BITS_PER_BYTE)
struct arfs_table {
struct mlx5e_flow_table ft;
- struct mlx5_flow_rule *default_rule;
+ struct mlx5_flow_handle *default_rule;
struct hlist_head rules_hash[ARFS_HASH_SIZE];
};
@@ -668,7 +689,6 @@ struct mlx5e_priv {
unsigned long state;
struct mutex state_lock; /* Protects Interface state */
- struct mlx5_core_mkey umr_mkey;
struct mlx5e_rq drop_rq;
struct mlx5e_channel **channel;
@@ -688,12 +708,15 @@ struct mlx5e_priv {
struct work_struct tx_timeout_work;
struct delayed_work update_stats_work;
- u32 pflags;
struct mlx5_core_dev *mdev;
struct net_device *netdev;
struct mlx5e_stats stats;
struct mlx5e_tstamp tstamp;
u16 q_counter;
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+ struct mlx5e_dcbx dcbx;
+#endif
+
const struct mlx5e_profile *profile;
void *ppriv;
};
@@ -735,6 +758,9 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
+int mlx5e_self_test_num(struct mlx5e_priv *priv);
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf);
int mlx5e_ethtool_get_flow(struct mlx5e_priv *priv, struct ethtool_rxnfc *info,
int location);
int mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
@@ -811,8 +837,7 @@ static inline void mlx5e_cq_arm(struct mlx5e_cq *cq)
static inline u32 mlx5e_get_wqe_mtt_offset(struct mlx5e_rq *rq, u16 wqe_ix)
{
- return rq->mpwqe.mtt_offset +
- wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8);
+ return wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8);
}
static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
@@ -825,6 +850,7 @@ extern const struct ethtool_ops mlx5e_ethtool_ops;
#ifdef CONFIG_MLX5_CORE_EN_DCB
extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops;
int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets);
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv);
#endif
#ifndef CONFIG_RFS_ACCEL
@@ -860,7 +886,8 @@ void mlx5e_destroy_tir(struct mlx5_core_dev *mdev,
struct mlx5e_tir *tir);
int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev);
void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev);
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev);
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+ bool enable_uc_lb);
struct mlx5_eswitch_rep;
int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
@@ -874,6 +901,7 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr);
void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
+void mlx5e_update_hw_rep_counters(struct mlx5e_priv *priv);
int mlx5e_create_direct_rqts(struct mlx5e_priv *priv);
void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
@@ -890,8 +918,16 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv);
int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
-struct rtnl_link_stats64 *
-mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout);
+void mlx5e_add_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti);
+void mlx5e_del_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti);
+
+int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+ void *sp);
+bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id);
+bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
+bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv);
#endif /* __MLX5_EN_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index a8cb38789774..68419a01db36 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -56,7 +56,7 @@ struct arfs_tuple {
struct arfs_rule {
struct mlx5e_priv *priv;
struct work_struct arfs_work;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
struct hlist_node hlist;
int rxq;
/* Flow ID passed to ndo_rx_flow_steer */
@@ -104,7 +104,7 @@ static int arfs_disable(struct mlx5e_priv *priv)
tt = arfs_get_tt(i);
/* Modify ttc rules destination to bypass the aRFS tables*/
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
- &dest);
+ &dest, NULL);
if (err) {
netdev_err(priv->netdev,
"%s: modify ttc destination failed\n",
@@ -137,7 +137,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv *priv)
tt = arfs_get_tt(i);
/* Modify ttc rules destination to point on the aRFS FTs */
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
- &dest);
+ &dest, NULL);
if (err) {
netdev_err(priv->netdev,
"%s: modify ttc destination failed err=%d\n",
@@ -151,7 +151,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv *priv)
static void arfs_destroy_table(struct arfs_table *arfs_t)
{
- mlx5_del_flow_rule(arfs_t->default_rule);
+ mlx5_del_flow_rules(arfs_t->default_rule);
mlx5e_destroy_flow_table(&arfs_t->ft);
}
@@ -174,6 +174,11 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
enum arfs_type type)
{
struct arfs_table *arfs_t = &priv->fs.arfs.arfs_tables[type];
+ struct mlx5_flow_act flow_act = {
+ .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+ .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+ .encap_id = 0,
+ };
struct mlx5_flow_destination dest;
struct mlx5e_tir *tir = priv->indir_tir;
struct mlx5_flow_spec *spec;
@@ -205,10 +210,9 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
goto out;
}
- arfs_t->default_rule = mlx5_add_flow_rule(arfs_t->ft.t, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- MLX5_FS_DEFAULT_FLOW_TAG,
- &dest);
+ arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, spec,
+ &flow_act,
+ &dest, 1);
if (IS_ERR(arfs_t->default_rule)) {
err = PTR_ERR(arfs_t->default_rule);
arfs_t->default_rule = NULL;
@@ -324,7 +328,7 @@ static int arfs_create_table(struct mlx5e_priv *priv,
int err;
ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
- MLX5E_ARFS_TABLE_SIZE, MLX5E_ARFS_FT_LEVEL);
+ MLX5E_ARFS_TABLE_SIZE, MLX5E_ARFS_FT_LEVEL, 0);
if (IS_ERR(ft->t)) {
err = PTR_ERR(ft->t);
ft->t = NULL;
@@ -396,7 +400,7 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
spin_unlock_bh(&priv->fs.arfs.arfs_lock);
hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) {
if (arfs_rule->rule)
- mlx5_del_flow_rule(arfs_rule->rule);
+ mlx5_del_flow_rules(arfs_rule->rule);
hlist_del(&arfs_rule->hlist);
kfree(arfs_rule);
}
@@ -420,7 +424,7 @@ static void arfs_del_rules(struct mlx5e_priv *priv)
hlist_for_each_entry_safe(rule, htmp, &del_list, hlist) {
cancel_work_sync(&rule->arfs_work);
if (rule->rule)
- mlx5_del_flow_rule(rule->rule);
+ mlx5_del_flow_rules(rule->rule);
hlist_del(&rule->hlist);
kfree(rule);
}
@@ -462,12 +466,17 @@ static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
return NULL;
}
-static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,
- struct arfs_rule *arfs_rule)
+static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
+ struct arfs_rule *arfs_rule)
{
+ struct mlx5_flow_act flow_act = {
+ .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+ .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+ .encap_id = 0,
+ };
struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
struct arfs_tuple *tuple = &arfs_rule->tuple;
- struct mlx5_flow_rule *rule = NULL;
+ struct mlx5_flow_handle *rule = NULL;
struct mlx5_flow_destination dest;
struct arfs_table *arfs_table;
struct mlx5_flow_spec *spec;
@@ -544,9 +553,7 @@ static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,
}
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dest.tir_num = priv->direct_tir[arfs_rule->rxq].tirn;
- rule = mlx5_add_flow_rule(ft, spec, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- MLX5_FS_DEFAULT_FLOW_TAG,
- &dest);
+ rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
netdev_err(priv->netdev, "%s: add rule(filter id=%d, rq idx=%d) failed, err=%d\n",
@@ -559,14 +566,14 @@ out:
}
static void arfs_modify_rule_rq(struct mlx5e_priv *priv,
- struct mlx5_flow_rule *rule, u16 rxq)
+ struct mlx5_flow_handle *rule, u16 rxq)
{
struct mlx5_flow_destination dst;
int err = 0;
dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dst.tir_num = priv->direct_tir[rxq].tirn;
- err = mlx5_modify_rule_destination(rule, &dst);
+ err = mlx5_modify_rule_destination(rule, &dst, NULL);
if (err)
netdev_warn(priv->netdev,
"Failed to modfiy aRFS rule destination to rq=%d\n", rxq);
@@ -578,7 +585,7 @@ static void arfs_handle_work(struct work_struct *work)
struct arfs_rule,
arfs_work);
struct mlx5e_priv *priv = arfs_rule->priv;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
mutex_lock(&priv->state_lock);
if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
index 13dc388667b6..2cd8e56a573b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
@@ -94,7 +94,7 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr)
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
/* Reset CQE compression to Admin default */
- mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_admin);
+ mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_def);
break;
case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_SOME:
@@ -111,6 +111,7 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
/* Disable CQE compression */
+ netdev_warn(dev, "Disabling cqe compression");
mlx5e_modify_rx_cqe_compression(priv, false);
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
index 029e856f72a0..f175518ff07a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
@@ -137,7 +137,8 @@ void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev)
mlx5_unmap_free_uar(mdev, &res->cq_uar);
}
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev)
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+ bool enable_uc_lb)
{
struct mlx5e_tir *tir;
void *in;
@@ -149,6 +150,10 @@ int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev)
if (!in)
return -ENOMEM;
+ if (enable_uc_lb)
+ MLX5_SET(modify_tir_in, in, ctx.self_lb_block,
+ MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST_);
+
MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
list_for_each_entry(tir, &mdev->mlx5e_res.td.tirs_list, list) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 762af16ed021..7f6c225666c1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -38,16 +38,77 @@
#define MLX5E_100MB (100000)
#define MLX5E_1GB (1000000)
+#define MLX5E_CEE_STATE_UP 1
+#define MLX5E_CEE_STATE_DOWN 0
+
+/* If dcbx mode is non-host set the dcbx mode to host.
+ */
+static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
+ enum mlx5_dcbx_oper_mode mode)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ u32 param[MLX5_ST_SZ_DW(dcbx_param)];
+ int err;
+
+ err = mlx5_query_port_dcbx_param(mdev, param);
+ if (err)
+ return err;
+
+ MLX5_SET(dcbx_param, param, version_admin, mode);
+ if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ MLX5_SET(dcbx_param, param, willing_admin, 1);
+
+ return mlx5_set_port_dcbx_param(mdev, param);
+}
+
+static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
+{
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+ int err;
+
+ if (!MLX5_CAP_GEN(priv->mdev, dcbx))
+ return 0;
+
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ return 0;
+
+ err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
+ if (err)
+ return err;
+
+ dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+ return 0;
+}
+
static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
struct ieee_ets *ets)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int err = 0;
+ int i;
if (!MLX5_CAP_GEN(priv->mdev, ets))
return -ENOTSUPP;
- memcpy(ets, &priv->params.ets, sizeof(*ets));
- return 0;
+ ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets->ets_cap; i++) {
+ err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < ets->ets_cap; i++) {
+ err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
+ if (err)
+ return err;
+ if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
+ priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+ }
+
+ memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
+
+ return err;
}
enum {
@@ -110,9 +171,6 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
int max_tc = mlx5_max_tc(mdev);
int err;
- if (!MLX5_CAP_GEN(mdev, ets))
- return -ENOTSUPP;
-
mlx5e_build_tc_group(ets, tc_group, max_tc);
mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
@@ -124,7 +182,14 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
if (err)
return err;
- return mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+ err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+
+ if (err)
+ return err;
+
+ memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
+
+ return err;
}
static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
@@ -170,6 +235,9 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
struct mlx5e_priv *priv = netdev_priv(netdev);
int err;
+ if (!MLX5_CAP_GEN(priv->mdev, ets))
+ return -ENOTSUPP;
+
err = mlx5e_dbcnl_validate_ets(netdev, ets);
if (err)
return err;
@@ -178,9 +246,6 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
if (err)
return err;
- memcpy(&priv->params.ets, ets, sizeof(*ets));
- priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
-
return 0;
}
@@ -222,13 +287,39 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
{
- return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+ u8 mode = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_VER_CEE;
+
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ mode |= DCB_CAP_DCBX_HOST;
+
+ return mode;
}
static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+ if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
+ return 0;
+
+ /* set dcbx to fw controlled */
+ if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
+ dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
+ return 1;
+
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
- (mode & DCB_CAP_DCBX_VER_CEE) ||
+ !(mode & DCB_CAP_DCBX_VER_CEE) ||
!(mode & DCB_CAP_DCBX_VER_IEEE) ||
!(mode & DCB_CAP_DCBX_HOST))
return 1;
@@ -304,6 +395,284 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
}
+static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct ieee_ets ets;
+ struct ieee_pfc pfc;
+ int err = -ENOTSUPP;
+ int i;
+
+ if (!MLX5_CAP_GEN(mdev, ets))
+ goto out;
+
+ memset(&ets, 0, sizeof(ets));
+ memset(&pfc, 0, sizeof(pfc));
+
+ ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
+ for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
+ ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
+ ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
+ ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+ ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i];
+ }
+
+ err = mlx5e_dbcnl_validate_ets(netdev, &ets);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to validate ETS: %d\n", __func__, err);
+ goto out;
+ }
+
+ err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to set ETS: %d\n", __func__, err);
+ goto out;
+ }
+
+ /* Set PFC */
+ pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
+ if (!cee_cfg->pfc_enable)
+ pfc.pfc_en = 0;
+ else
+ for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
+ pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
+
+ err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to set PFC: %d\n", __func__, err);
+ goto out;
+ }
+out:
+ return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
+}
+
+static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
+{
+ return MLX5E_CEE_STATE_UP;
+}
+
+static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
+ u8 *perm_addr)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+
+ if (!perm_addr)
+ return;
+
+ mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
+}
+
+static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
+ int priority, u8 prio_type,
+ u8 pgid, u8 bw_pct, u8 up_map)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ cee_cfg->prio_to_pg_map[priority] = pgid;
+}
+
+static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
+ int pgid, u8 bw_pct)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ cee_cfg->pg_bw_pct[pgid] = bw_pct;
+}
+
+static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
+ int priority, u8 *prio_type,
+ u8 *pgid, u8 *bw_pct, u8 *up_map)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ *prio_type = 0;
+ *bw_pct = 0;
+ *up_map = 0;
+
+ if (mlx5_query_port_prio_tc(mdev, priority, pgid))
+ *pgid = 0;
+}
+
+static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
+ int pgid, u8 *bw_pct)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct))
+ *bw_pct = 0;
+}
+
+static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
+ int priority, u8 setting)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (setting > 1)
+ return;
+
+ cee_cfg->pfc_setting[priority] = setting;
+}
+
+static int
+mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
+ int priority, u8 *setting)
+{
+ struct ieee_pfc pfc;
+ int err;
+
+ err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
+
+ if (err)
+ *setting = 0;
+ else
+ *setting = (pfc.pfc_en >> priority) & 0x01;
+
+ return err;
+}
+
+static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
+ int priority, u8 *setting)
+{
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (!setting)
+ return;
+
+ mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
+}
+
+static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
+ int capid, u8 *cap)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ u8 rval = 0;
+
+ switch (capid) {
+ case DCB_CAP_ATTR_PG:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_PFC:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_UP2TC:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_PG_TCS:
+ *cap = 1 << mlx5_max_tc(mdev);
+ break;
+ case DCB_CAP_ATTR_PFC_TCS:
+ *cap = 1 << mlx5_max_tc(mdev);
+ break;
+ case DCB_CAP_ATTR_GSP:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_BCN:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_DCBX:
+ *cap = (DCB_CAP_DCBX_LLD_MANAGED |
+ DCB_CAP_DCBX_VER_CEE |
+ DCB_CAP_DCBX_STATIC);
+ break;
+ default:
+ *cap = 0;
+ rval = 1;
+ break;
+ }
+
+ return rval;
+}
+
+static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
+ int tcs_id, u8 *num)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ switch (tcs_id) {
+ case DCB_NUMTCS_ATTR_PG:
+ case DCB_NUMTCS_ATTR_PFC:
+ *num = mlx5_max_tc(mdev) + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
+{
+ struct ieee_pfc pfc;
+
+ if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
+ return MLX5E_CEE_STATE_DOWN;
+
+ return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
+}
+
+static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
+ return;
+
+ cee_cfg->pfc_enable = state;
+}
+
const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_getets = mlx5e_dcbnl_ieee_getets,
.ieee_setets = mlx5e_dcbnl_ieee_setets,
@@ -313,4 +682,70 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_setpfc = mlx5e_dcbnl_ieee_setpfc,
.getdcbx = mlx5e_dcbnl_getdcbx,
.setdcbx = mlx5e_dcbnl_setdcbx,
+
+/* CEE interfaces */
+ .setall = mlx5e_dcbnl_setall,
+ .getstate = mlx5e_dcbnl_getstate,
+ .getpermhwaddr = mlx5e_dcbnl_getpermhwaddr,
+
+ .setpgtccfgtx = mlx5e_dcbnl_setpgtccfgtx,
+ .setpgbwgcfgtx = mlx5e_dcbnl_setpgbwgcfgtx,
+ .getpgtccfgtx = mlx5e_dcbnl_getpgtccfgtx,
+ .getpgbwgcfgtx = mlx5e_dcbnl_getpgbwgcfgtx,
+
+ .setpfccfg = mlx5e_dcbnl_setpfccfg,
+ .getpfccfg = mlx5e_dcbnl_getpfccfg,
+ .getcap = mlx5e_dcbnl_getcap,
+ .getnumtcs = mlx5e_dcbnl_getnumtcs,
+ .getpfcstate = mlx5e_dcbnl_getpfcstate,
+ .setpfcstate = mlx5e_dcbnl_setpfcstate,
};
+
+static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
+ enum mlx5_dcbx_oper_mode *mode)
+{
+ u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+ *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+
+ if (!mlx5_query_port_dcbx_param(priv->mdev, out))
+ *mode = MLX5_GET(dcbx_param, out, version_oper);
+
+ /* From driver's point of view, we only care if the mode
+ * is host (HOST) or non-host (AUTO)
+ */
+ if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+}
+
+static void mlx5e_ets_init(struct mlx5e_priv *priv)
+{
+ int i;
+ struct ieee_ets ets;
+
+ memset(&ets, 0, sizeof(ets));
+ ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets.ets_cap; i++) {
+ ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
+ ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
+ ets.prio_tc[i] = i;
+ }
+
+ memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
+
+ /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
+ ets.prio_tc[0] = 1;
+ ets.prio_tc[1] = 0;
+
+ mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+}
+
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
+{
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+ if (MLX5_CAP_GEN(priv->mdev, dcbx))
+ mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
+
+ mlx5e_ets_init(priv);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 27ff401cec20..352462af8d51 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -171,11 +171,17 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset)
return NUM_SW_COUNTERS +
MLX5E_NUM_Q_CNTRS(priv) +
NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS +
+ NUM_PCIE_COUNTERS +
MLX5E_NUM_RQ_STATS(priv) +
MLX5E_NUM_SQ_STATS(priv) +
- MLX5E_NUM_PFC_COUNTERS(priv);
+ MLX5E_NUM_PFC_COUNTERS(priv) +
+ ARRAY_SIZE(mlx5e_pme_status_desc) +
+ ARRAY_SIZE(mlx5e_pme_error_desc);
+
case ETH_SS_PRIV_FLAGS:
return ARRAY_SIZE(mlx5e_priv_flags);
+ case ETH_SS_TEST:
+ return mlx5e_self_test_num(priv);
/* fallthrough */
default:
return -EOPNOTSUPP;
@@ -213,6 +219,14 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
strcpy(data + (idx++) * ETH_GSTRING_LEN,
pport_2819_stats_desc[i].format);
+ for (i = 0; i < NUM_PCIE_PERF_COUNTERS; i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN,
+ pcie_perf_stats_desc[i].format);
+
+ for (i = 0; i < NUM_PCIE_TAS_COUNTERS; i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN,
+ pcie_tas_stats_desc[i].format);
+
for (prio = 0; prio < NUM_PPORT_PRIO; prio++) {
for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++)
sprintf(data + (idx++) * ETH_GSTRING_LEN,
@@ -237,6 +251,13 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
}
}
+ /* port module event counters */
+ for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_status_desc[i].format);
+
+ for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_error_desc[i].format);
+
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
return;
@@ -267,6 +288,9 @@ static void mlx5e_get_strings(struct net_device *dev,
break;
case ETH_SS_TEST:
+ for (i = 0; i < mlx5e_self_test_num(priv); i++)
+ strcpy(data + i * ETH_GSTRING_LEN,
+ mlx5e_self_tests[i]);
break;
case ETH_SS_STATS:
@@ -279,6 +303,7 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_priv *mlx5_priv;
int i, j, tc, prio, idx = 0;
unsigned long pfc_combined;
@@ -314,6 +339,14 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.RFC_2819_counters,
pport_2819_stats_desc, i);
+ for (i = 0; i < NUM_PCIE_PERF_COUNTERS; i++)
+ data[idx++] = MLX5E_READ_CTR32_BE(&priv->stats.pcie.pcie_perf_counters,
+ pcie_perf_stats_desc, i);
+
+ for (i = 0; i < NUM_PCIE_TAS_COUNTERS; i++)
+ data[idx++] = MLX5E_READ_CTR32_BE(&priv->stats.pcie.pcie_tas_counters,
+ pcie_tas_stats_desc, i);
+
for (prio = 0; prio < NUM_PPORT_PRIO; prio++) {
for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++)
data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.per_prio_counters[prio],
@@ -335,6 +368,16 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
}
}
+ /* port module event counters */
+ mlx5_priv = &priv->mdev->priv;
+ for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
+ data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.status_counters,
+ mlx5e_pme_status_desc, i);
+
+ for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
+ data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.error_counters,
+ mlx5e_pme_error_desc, i);
+
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
return;
@@ -456,8 +499,7 @@ static int mlx5e_set_ringparam(struct net_device *dev,
return -EINVAL;
}
- num_mtts = MLX5E_REQUIRED_MTTS(priv->params.num_channels,
- rx_pending_wqes);
+ num_mtts = MLX5E_REQUIRED_MTTS(rx_pending_wqes);
if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
!MLX5E_VALID_NUM_MTTS(num_mtts)) {
netdev_info(dev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n",
@@ -522,7 +564,6 @@ static int mlx5e_set_channels(struct net_device *dev,
unsigned int count = ch->combined_count;
bool arfs_enabled;
bool was_opened;
- u32 num_mtts;
int err = 0;
if (!count) {
@@ -541,14 +582,6 @@ static int mlx5e_set_channels(struct net_device *dev,
return -EINVAL;
}
- num_mtts = MLX5E_REQUIRED_MTTS(count, BIT(priv->params.log_rq_size));
- if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
- !MLX5E_VALID_NUM_MTTS(num_mtts)) {
- netdev_info(dev, "%s: rx count (%d) request can't be satisfied, try to reduce.\n",
- __func__, count);
- return -EINVAL;
- }
-
if (priv->params.num_channels == count)
return 0;
@@ -1438,6 +1471,35 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
return err;
}
+static int set_pflag_rx_cqe_compress(struct net_device *netdev,
+ bool enable)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int err = 0;
+ bool reset;
+
+ if (!MLX5_CAP_GEN(mdev, cqe_compression))
+ return -ENOTSUPP;
+
+ if (enable && priv->tstamp.hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
+ netdev_err(netdev, "Can't enable cqe compression while timestamping is enabled.\n");
+ return -EINVAL;
+ }
+
+ reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
+
+ if (reset)
+ mlx5e_close_locked(netdev);
+
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, enable);
+ priv->params.rx_cqe_compress_def = enable;
+
+ if (reset)
+ err = mlx5e_open_locked(netdev);
+ return err;
+}
+
static int mlx5e_handle_pflag(struct net_device *netdev,
u32 wanted_flags,
enum mlx5e_priv_flag flag,
@@ -1445,7 +1507,7 @@ static int mlx5e_handle_pflag(struct net_device *netdev,
{
struct mlx5e_priv *priv = netdev_priv(netdev);
bool enable = !!(wanted_flags & flag);
- u32 changes = wanted_flags ^ priv->pflags;
+ u32 changes = wanted_flags ^ priv->params.pflags;
int err;
if (!(changes & flag))
@@ -1458,7 +1520,7 @@ static int mlx5e_handle_pflag(struct net_device *netdev,
return err;
}
- MLX5E_SET_PRIV_FLAG(priv, flag, enable);
+ MLX5E_SET_PFLAG(priv, flag, enable);
return 0;
}
@@ -1468,20 +1530,26 @@ static int mlx5e_set_priv_flags(struct net_device *netdev, u32 pflags)
int err;
mutex_lock(&priv->state_lock);
-
err = mlx5e_handle_pflag(netdev, pflags,
MLX5E_PFLAG_RX_CQE_BASED_MODER,
set_pflag_rx_cqe_based_moder);
+ if (err)
+ goto out;
+
+ err = mlx5e_handle_pflag(netdev, pflags,
+ MLX5E_PFLAG_RX_CQE_COMPRESS,
+ set_pflag_rx_cqe_compress);
+out:
mutex_unlock(&priv->state_lock);
- return err ? -EINVAL : 0;
+ return err;
}
static u32 mlx5e_get_priv_flags(struct net_device *netdev)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
- return priv->pflags;
+ return priv->params.pflags;
}
static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
@@ -1535,5 +1603,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.get_module_info = mlx5e_get_module_info,
.get_module_eeprom = mlx5e_get_module_eeprom,
.get_priv_flags = mlx5e_get_priv_flags,
- .set_priv_flags = mlx5e_set_priv_flags
+ .set_priv_flags = mlx5e_set_priv_flags,
+ .self_test = mlx5e_self_test,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 36fbc6b21a33..1fe80de5d68f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -158,9 +158,14 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
enum mlx5e_vlan_rule_type rule_type,
u16 vid, struct mlx5_flow_spec *spec)
{
+ struct mlx5_flow_act flow_act = {
+ .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+ .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+ .encap_id = 0,
+ };
struct mlx5_flow_table *ft = priv->fs.vlan.ft.t;
struct mlx5_flow_destination dest;
- struct mlx5_flow_rule **rule_p;
+ struct mlx5_flow_handle **rule_p;
int err = 0;
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
@@ -187,10 +192,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
break;
}
- *rule_p = mlx5_add_flow_rule(ft, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- MLX5_FS_DEFAULT_FLOW_TAG,
- &dest);
+ *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(*rule_p)) {
err = PTR_ERR(*rule_p);
@@ -229,20 +231,20 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
switch (rule_type) {
case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
if (priv->fs.vlan.untagged_rule) {
- mlx5_del_flow_rule(priv->fs.vlan.untagged_rule);
+ mlx5_del_flow_rules(priv->fs.vlan.untagged_rule);
priv->fs.vlan.untagged_rule = NULL;
}
break;
case MLX5E_VLAN_RULE_TYPE_ANY_VID:
if (priv->fs.vlan.any_vlan_rule) {
- mlx5_del_flow_rule(priv->fs.vlan.any_vlan_rule);
+ mlx5_del_flow_rules(priv->fs.vlan.any_vlan_rule);
priv->fs.vlan.any_vlan_rule = NULL;
}
break;
case MLX5E_VLAN_RULE_TYPE_MATCH_VID:
mlx5e_vport_context_update_vlans(priv);
if (priv->fs.vlan.active_vlans_rule[vid]) {
- mlx5_del_flow_rule(priv->fs.vlan.active_vlans_rule[vid]);
+ mlx5_del_flow_rules(priv->fs.vlan.active_vlans_rule[vid]);
priv->fs.vlan.active_vlans_rule[vid] = NULL;
}
mlx5e_vport_context_update_vlans(priv);
@@ -560,7 +562,7 @@ static void mlx5e_cleanup_ttc_rules(struct mlx5e_ttc_table *ttc)
for (i = 0; i < MLX5E_NUM_TT; i++) {
if (!IS_ERR_OR_NULL(ttc->rules[i])) {
- mlx5_del_flow_rule(ttc->rules[i]);
+ mlx5_del_flow_rules(ttc->rules[i]);
ttc->rules[i] = NULL;
}
}
@@ -616,13 +618,19 @@ static struct {
},
};
-static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
- struct mlx5_flow_table *ft,
- struct mlx5_flow_destination *dest,
- u16 etype,
- u8 proto)
+static struct mlx5_flow_handle *
+mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
+ struct mlx5_flow_table *ft,
+ struct mlx5_flow_destination *dest,
+ u16 etype,
+ u8 proto)
{
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_act flow_act = {
+ .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+ .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+ .encap_id = 0,
+ };
+ struct mlx5_flow_handle *rule;
struct mlx5_flow_spec *spec;
int err = 0;
@@ -643,10 +651,7 @@ static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, etype);
}
- rule = mlx5_add_flow_rule(ft, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- MLX5_FS_DEFAULT_FLOW_TAG,
- dest);
+ rule = mlx5_add_flow_rules(ft, spec, &flow_act, dest, 1);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
netdev_err(priv->netdev, "%s: add rule failed\n", __func__);
@@ -660,7 +665,7 @@ static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv)
{
struct mlx5_flow_destination dest;
struct mlx5e_ttc_table *ttc;
- struct mlx5_flow_rule **rules;
+ struct mlx5_flow_handle **rules;
struct mlx5_flow_table *ft;
int tt;
int err;
@@ -776,7 +781,7 @@ static int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
int err;
ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
- MLX5E_TTC_TABLE_SIZE, MLX5E_TTC_FT_LEVEL);
+ MLX5E_TTC_TABLE_SIZE, MLX5E_TTC_FT_LEVEL, 0);
if (IS_ERR(ft->t)) {
err = PTR_ERR(ft->t);
ft->t = NULL;
@@ -801,7 +806,7 @@ static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
struct mlx5e_l2_rule *ai)
{
if (!IS_ERR_OR_NULL(ai->rule)) {
- mlx5_del_flow_rule(ai->rule);
+ mlx5_del_flow_rules(ai->rule);
ai->rule = NULL;
}
}
@@ -809,6 +814,11 @@ static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
struct mlx5e_l2_rule *ai, int type)
{
+ struct mlx5_flow_act flow_act = {
+ .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+ .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+ .encap_id = 0,
+ };
struct mlx5_flow_table *ft = priv->fs.l2.ft.t;
struct mlx5_flow_destination dest;
struct mlx5_flow_spec *spec;
@@ -847,9 +857,7 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
break;
}
- ai->rule = mlx5_add_flow_rule(ft, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- MLX5_FS_DEFAULT_FLOW_TAG, &dest);
+ ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(ai->rule)) {
netdev_err(priv->netdev, "%s: add l2 rule(mac:%pM) failed\n",
__func__, mv_dmac);
@@ -947,7 +955,7 @@ static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
ft->num_groups = 0;
ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
- MLX5E_L2_TABLE_SIZE, MLX5E_L2_FT_LEVEL);
+ MLX5E_L2_TABLE_SIZE, MLX5E_L2_FT_LEVEL, 0);
if (IS_ERR(ft->t)) {
err = PTR_ERR(ft->t);
@@ -1037,7 +1045,7 @@ static int mlx5e_create_vlan_table(struct mlx5e_priv *priv)
ft->num_groups = 0;
ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
- MLX5E_VLAN_TABLE_SIZE, MLX5E_VLAN_FT_LEVEL);
+ MLX5E_VLAN_TABLE_SIZE, MLX5E_VLAN_FT_LEVEL, 0);
if (IS_ERR(ft->t)) {
err = PTR_ERR(ft->t);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
index d17c24227900..3691451c728c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -36,7 +36,7 @@
struct mlx5e_ethtool_rule {
struct list_head list;
struct ethtool_rx_flow_spec flow_spec;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
struct mlx5e_ethtool_table *eth_ft;
};
@@ -99,7 +99,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
MLX5E_ETHTOOL_NUM_ENTRIES);
ft = mlx5_create_auto_grouped_flow_table(ns, prio,
table_size,
- MLX5E_ETHTOOL_NUM_GROUPS, 0);
+ MLX5E_ETHTOOL_NUM_GROUPS, 0, 0);
if (IS_ERR(ft))
return (void *)ft;
@@ -284,15 +284,16 @@ static bool outer_header_zero(u32 *match_criteria)
size - 1);
}
-static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv,
- struct mlx5_flow_table *ft,
- struct ethtool_rx_flow_spec *fs)
+static struct mlx5_flow_handle *
+add_ethtool_flow_rule(struct mlx5e_priv *priv,
+ struct mlx5_flow_table *ft,
+ struct ethtool_rx_flow_spec *fs)
{
struct mlx5_flow_destination *dst = NULL;
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_spec *spec;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
int err = 0;
- u32 action;
spec = mlx5_vzalloc(sizeof(*spec));
if (!spec)
@@ -303,7 +304,7 @@ static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv,
goto free;
if (fs->ring_cookie == RX_CLS_FLOW_DISC) {
- action = MLX5_FLOW_CONTEXT_ACTION_DROP;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
} else {
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
if (!dst) {
@@ -313,12 +314,12 @@ static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv,
dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dst->tir_num = priv->direct_tir[fs->ring_cookie].tirn;
- action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
}
spec->match_criteria_enable = (!outer_header_zero(spec->match_criteria));
- rule = mlx5_add_flow_rule(ft, spec, action,
- MLX5_FS_DEFAULT_FLOW_TAG, dst);
+ flow_act.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
+ rule = mlx5_add_flow_rules(ft, spec, &flow_act, dst, 1);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
netdev_err(priv->netdev, "%s: failed to add ethtool steering rule: %d\n",
@@ -335,7 +336,7 @@ static void del_ethtool_rule(struct mlx5e_priv *priv,
struct mlx5e_ethtool_rule *eth_rule)
{
if (eth_rule->rule)
- mlx5_del_flow_rule(eth_rule->rule);
+ mlx5_del_flow_rules(eth_rule->rule);
list_del(&eth_rule->list);
priv->fs.ethtool.tot_num_rules--;
put_flow_table(eth_rule->eth_ft);
@@ -475,7 +476,7 @@ int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
{
struct mlx5e_ethtool_table *eth_ft;
struct mlx5e_ethtool_rule *eth_rule;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
int num_tuples;
int err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 246d98ebb588..cbfa38fc72c0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -84,7 +84,8 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
switch (priv->params.rq_wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW;
- priv->params.mpwqe_log_stride_sz = priv->params.rx_cqe_compress ?
+ priv->params.mpwqe_log_stride_sz =
+ MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) ?
MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS :
MLX5_MPWRQ_LOG_STRIDE_SIZE;
priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ -
@@ -101,7 +102,7 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
BIT(priv->params.log_rq_size),
BIT(priv->params.mpwqe_log_stride_sz),
- priv->params.rx_cqe_compress_admin);
+ MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS));
}
static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv)
@@ -290,12 +291,36 @@ static void mlx5e_update_q_counter(struct mlx5e_priv *priv)
&qcnt->rx_out_of_buffer);
}
+static void mlx5e_update_pcie_counters(struct mlx5e_priv *priv)
+{
+ struct mlx5e_pcie_stats *pcie_stats = &priv->stats.pcie;
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int sz = MLX5_ST_SZ_BYTES(mpcnt_reg);
+ void *out;
+ u32 *in;
+
+ in = mlx5_vzalloc(sz);
+ if (!in)
+ return;
+
+ out = pcie_stats->pcie_perf_counters;
+ MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP);
+ mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);
+
+ out = pcie_stats->pcie_tas_counters;
+ MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_TIMERS_AND_STATES_COUNTERS_GROUP);
+ mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);
+
+ kvfree(in);
+}
+
void mlx5e_update_stats(struct mlx5e_priv *priv)
{
mlx5e_update_q_counter(priv);
mlx5e_update_vport_counters(priv);
mlx5e_update_pport_counters(priv);
mlx5e_update_sw_counters(priv);
+ mlx5e_update_pcie_counters(priv);
}
void mlx5e_update_stats_work(struct work_struct *work)
@@ -446,14 +471,50 @@ static void mlx5e_rq_free_mpwqe_info(struct mlx5e_rq *rq)
kfree(rq->mpwqe.info);
}
-static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
+static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv,
+ u64 npages, u8 page_shift,
+ struct mlx5_core_mkey *umr_mkey)
{
- struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
+ void *mkc;
+ u32 *in;
+ int err;
- if (rep && rep->vport != FDB_UPLINK_VPORT)
- return true;
+ if (!MLX5E_VALID_NUM_MTTS(npages))
+ return -EINVAL;
- return false;
+ in = mlx5_vzalloc(inlen);
+ if (!in)
+ return -ENOMEM;
+
+ mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
+
+ MLX5_SET(mkc, mkc, free, 1);
+ MLX5_SET(mkc, mkc, umr_en, 1);
+ MLX5_SET(mkc, mkc, lw, 1);
+ MLX5_SET(mkc, mkc, lr, 1);
+ MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
+
+ MLX5_SET(mkc, mkc, qpn, 0xffffff);
+ MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
+ MLX5_SET64(mkc, mkc, len, npages << page_shift);
+ MLX5_SET(mkc, mkc, translations_octword_size,
+ MLX5_MTT_OCTW(npages));
+ MLX5_SET(mkc, mkc, log_page_size, page_shift);
+
+ err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
+
+ kvfree(in);
+ return err;
+}
+
+static int mlx5e_create_rq_umr_mkey(struct mlx5e_rq *rq)
+{
+ struct mlx5e_priv *priv = rq->priv;
+ u64 num_mtts = MLX5E_REQUIRED_MTTS(BIT(priv->params.log_rq_size));
+
+ return mlx5e_create_umr_mkey(priv, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
}
static int mlx5e_create_rq(struct mlx5e_channel *c,
@@ -489,7 +550,13 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
rq->channel = c;
rq->ix = c->ix;
rq->priv = c->priv;
- rq->xdp_prog = priv->xdp_prog;
+
+ rq->xdp_prog = priv->xdp_prog ? bpf_prog_inc(priv->xdp_prog) : NULL;
+ if (IS_ERR(rq->xdp_prog)) {
+ err = PTR_ERR(rq->xdp_prog);
+ rq->xdp_prog = NULL;
+ goto err_rq_wq_destroy;
+ }
rq->buff.map_dir = DMA_FROM_DEVICE;
if (rq->xdp_prog)
@@ -506,18 +573,20 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
rq->alloc_wqe = mlx5e_alloc_rx_mpwqe;
rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
- rq->mpwqe.mtt_offset = c->ix *
- MLX5E_REQUIRED_MTTS(1, BIT(priv->params.log_rq_size));
-
rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz);
rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides);
rq->buff.wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides;
byte_count = rq->buff.wqe_sz;
- rq->mkey_be = cpu_to_be32(c->priv->umr_mkey.key);
- err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+
+ err = mlx5e_create_rq_umr_mkey(rq);
if (err)
goto err_rq_wq_destroy;
+ rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
+
+ err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+ if (err)
+ goto err_destroy_umr_mkey;
break;
default: /* MLX5_WQ_TYPE_LINKED_LIST */
rq->dma_info = kzalloc_node(wq_sz * sizeof(*rq->dma_info),
@@ -566,12 +635,14 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
rq->page_cache.head = 0;
rq->page_cache.tail = 0;
- if (rq->xdp_prog)
- bpf_prog_add(rq->xdp_prog, 1);
-
return 0;
+err_destroy_umr_mkey:
+ mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
+
err_rq_wq_destroy:
+ if (rq->xdp_prog)
+ bpf_prog_put(rq->xdp_prog);
mlx5_wq_destroy(&rq->wq_ctrl);
return err;
@@ -587,6 +658,7 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
switch (rq->wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
mlx5e_rq_free_mpwqe_info(rq);
+ mlx5_core_destroy_mkey(rq->priv->mdev, &rq->umr_mkey);
break;
default: /* MLX5_WQ_TYPE_LINKED_LIST */
kfree(rq->dma_info);
@@ -940,7 +1012,7 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
sq->bf_buf_size = (1 << MLX5_CAP_GEN(mdev, log_bf_reg_size)) / 2;
sq->max_inline = param->max_inline;
sq->min_inline_mode =
- MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5E_INLINE_MODE_VPORT_CONTEXT ?
+ MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5_CAP_INLINE_MODE_VPORT_CONTEXT ?
param->min_inline_mode : 0;
err = mlx5e_alloc_sq_db(sq, cpu_to_node(c->cpu));
@@ -1184,7 +1256,7 @@ static int mlx5e_create_cq(struct mlx5e_channel *c,
static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
{
- mlx5_wq_destroy(&cq->wq_ctrl);
+ mlx5_cqwq_destroy(&cq->wq_ctrl);
}
static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
@@ -1201,7 +1273,7 @@ static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
int err;
inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
- sizeof(u64) * cq->wq_ctrl.buf.npages;
+ sizeof(u64) * cq->wq_ctrl.frag_buf.npages;
in = mlx5_vzalloc(inlen);
if (!in)
return -ENOMEM;
@@ -1210,15 +1282,15 @@ static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
memcpy(cqc, param->cqc, sizeof(param->cqc));
- mlx5_fill_page_array(&cq->wq_ctrl.buf,
- (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
+ mlx5_fill_page_frag_array(&cq->wq_ctrl.frag_buf,
+ (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
MLX5_SET(cqc, cqc, cq_period_mode, param->cq_period_mode);
MLX5_SET(cqc, cqc, c_eqn, eqn);
MLX5_SET(cqc, cqc, uar_page, mcq->uar->index);
- MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift -
+ MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.frag_buf.page_shift -
MLX5_ADAPTER_PAGE_SHIFT);
MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma);
@@ -1536,7 +1608,6 @@ err_close_icosq_cq:
err_napi_del:
netif_napi_del(&c->napi);
- napi_hash_del(&c->napi);
kfree(c);
return err;
@@ -1557,9 +1628,6 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
mlx5e_close_cq(&c->icosq.cq);
netif_napi_del(&c->napi);
- napi_hash_del(&c->napi);
- synchronize_rcu();
-
kfree(c);
}
@@ -1652,7 +1720,7 @@ static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
}
MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
- if (priv->params.rx_cqe_compress) {
+ if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
MLX5_SET(cqc, cqc, cqe_comp_en, 1);
}
@@ -2124,7 +2192,7 @@ int mlx5e_open_locked(struct net_device *netdev)
goto err_clear_state_opened_flag;
}
- err = mlx5e_refresh_tirs_self_loopback_enable(priv->mdev);
+ err = mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
if (err) {
netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
__func__, err);
@@ -2642,7 +2710,7 @@ mqprio:
return mlx5e_setup_tc(dev, tc->tc);
}
-struct rtnl_link_stats64 *
+static struct rtnl_link_stats64 *
mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
struct mlx5e_priv *priv = netdev_priv(dev);
@@ -2650,13 +2718,20 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
struct mlx5e_vport_stats *vstats = &priv->stats.vport;
struct mlx5e_pport_stats *pstats = &priv->stats.pport;
- stats->rx_packets = sstats->rx_packets;
- stats->rx_bytes = sstats->rx_bytes;
- stats->tx_packets = sstats->tx_packets;
- stats->tx_bytes = sstats->tx_bytes;
+ if (mlx5e_is_uplink_rep(priv)) {
+ stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
+ stats->rx_bytes = PPORT_802_3_GET(pstats, a_octets_received_ok);
+ stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
+ stats->tx_bytes = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
+ } else {
+ stats->rx_packets = sstats->rx_packets;
+ stats->rx_bytes = sstats->rx_bytes;
+ stats->tx_packets = sstats->tx_packets;
+ stats->tx_bytes = sstats->tx_bytes;
+ stats->tx_dropped = sstats->tx_queue_dropped;
+ }
stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
- stats->tx_dropped = sstats->tx_queue_dropped;
stats->rx_length_errors =
PPORT_802_3_GET(pstats, a_in_range_length_errors) +
@@ -2853,31 +2928,13 @@ static int mlx5e_set_features(struct net_device *netdev,
return err ? -EINVAL : 0;
}
-#define MXL5_HW_MIN_MTU 64
-#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN)
-
static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
- struct mlx5_core_dev *mdev = priv->mdev;
bool was_opened;
- u16 max_mtu;
- u16 min_mtu;
int err = 0;
bool reset;
- mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
-
- max_mtu = MLX5E_HW2SW_MTU(max_mtu);
- min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU);
-
- if (new_mtu > max_mtu || new_mtu < min_mtu) {
- netdev_err(netdev,
- "%s: Bad MTU (%d), valid range is: [%d..%d]\n",
- __func__, new_mtu, min_mtu, max_mtu);
- return -EINVAL;
- }
-
mutex_lock(&priv->state_lock);
reset = !priv->params.lro_en &&
@@ -2947,6 +3004,20 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
}
+
+static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
+ int max_tx_rate)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ if (min_tx_rate)
+ return -EOPNOTSUPP;
+
+ return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1,
+ max_tx_rate);
+}
+
static int mlx5_vport_link2ifla(u8 esw_link)
{
switch (esw_link) {
@@ -3003,8 +3074,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
vf_stats);
}
-static void mlx5e_add_vxlan_port(struct net_device *netdev,
- struct udp_tunnel_info *ti)
+void mlx5e_add_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -3017,8 +3088,8 @@ static void mlx5e_add_vxlan_port(struct net_device *netdev,
mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
}
-static void mlx5e_del_vxlan_port(struct net_device *netdev,
- struct udp_tunnel_info *ti)
+void mlx5e_del_vxlan_port(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -3112,6 +3183,11 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
bool reset, was_opened;
int i;
+ if (prog && prog->xdp_adjust_head) {
+ netdev_err(netdev, "Does not support bpf_xdp_adjust_head()\n");
+ return -EOPNOTSUPP;
+ }
+
mutex_lock(&priv->state_lock);
if ((netdev->features & NETIF_F_LRO) && prog) {
@@ -3126,11 +3202,21 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
if (was_opened && reset)
mlx5e_close_locked(netdev);
+ if (was_opened && !reset) {
+ /* num_channels is invariant here, so we can take the
+ * batched reference right upfront.
+ */
+ prog = bpf_prog_add(prog, priv->params.num_channels);
+ if (IS_ERR(prog)) {
+ err = PTR_ERR(prog);
+ goto unlock;
+ }
+ }
- /* exchange programs */
+ /* exchange programs, extra prog reference we got from caller
+ * as long as we don't fail from this point onwards.
+ */
old_prog = xchg(&priv->xdp_prog, prog);
- if (prog)
- bpf_prog_add(prog, 1);
if (old_prog)
bpf_prog_put(old_prog);
@@ -3146,7 +3232,6 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
/* exchanging programs w/o reset, we update ref counts on behalf
* of the channels RQs here.
*/
- bpf_prog_add(prog, priv->params.num_channels);
for (i = 0; i < priv->params.num_channels; i++) {
struct mlx5e_channel *c = priv->channel[i];
@@ -3254,6 +3339,7 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
.ndo_set_vf_vlan = mlx5e_set_vf_vlan,
.ndo_set_vf_spoofchk = mlx5e_set_vf_spoofchk,
.ndo_set_vf_trust = mlx5e_set_vf_trust,
+ .ndo_set_vf_rate = mlx5e_set_vf_rate,
.ndo_get_vf_config = mlx5e_get_vf_config,
.ndo_set_vf_link_state = mlx5e_set_vf_link_state,
.ndo_get_vf_stats = mlx5e_get_vf_stats,
@@ -3262,6 +3348,8 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mlx5e_netpoll,
#endif
+ .ndo_has_offload_stats = mlx5e_has_offload_stats,
+ .ndo_get_offload_stats = mlx5e_get_offload_stats,
};
static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
@@ -3298,24 +3386,6 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
}
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-static void mlx5e_ets_init(struct mlx5e_priv *priv)
-{
- int i;
-
- priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
- for (i = 0; i < priv->params.ets.ets_cap; i++) {
- priv->params.ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
- priv->params.ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
- priv->params.ets.prio_tc[i] = i;
- }
-
- /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
- priv->params.ets.prio_tc[0] = 1;
- priv->params.ets.prio_tc[1] = 0;
-}
-#endif
-
void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
u32 *indirection_rqt, int len,
int num_channels)
@@ -3390,14 +3460,13 @@ static void mlx5e_query_min_inline(struct mlx5_core_dev *mdev,
u8 *min_inline_mode)
{
switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
- case MLX5E_INLINE_MODE_L2:
+ case MLX5_CAP_INLINE_MODE_L2:
*min_inline_mode = MLX5_INLINE_MODE_L2;
break;
- case MLX5E_INLINE_MODE_VPORT_CONTEXT:
- mlx5_query_nic_vport_min_inline(mdev,
- min_inline_mode);
+ case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
+ mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode);
break;
- case MLX5_INLINE_MODE_NOT_REQUIRED:
+ case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
*min_inline_mode = MLX5_INLINE_MODE_NONE;
break;
}
@@ -3439,17 +3508,16 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
/* set CQE compression */
- priv->params.rx_cqe_compress_admin = false;
+ priv->params.rx_cqe_compress_def = false;
if (MLX5_CAP_GEN(mdev, cqe_compression) &&
MLX5_CAP_GEN(mdev, vport_group_manager)) {
mlx5e_get_max_linkspeed(mdev, &link_speed);
mlx5e_get_pci_bw(mdev, &pci_bw);
mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n",
link_speed, pci_bw);
- priv->params.rx_cqe_compress_admin =
+ priv->params.rx_cqe_compress_def =
cqe_compress_heuristic(link_speed, pci_bw);
}
- priv->params.rx_cqe_compress = priv->params.rx_cqe_compress_admin;
mlx5e_set_rq_priv_params(priv);
if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
@@ -3480,12 +3548,9 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
/* Initialize pflags */
- MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
- priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
-
-#ifdef CONFIG_MLX5_CORE_EN_DCB
- mlx5e_ets_init(priv);
-#endif
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
+ priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, priv->params.rx_cqe_compress_def);
mutex_init(&priv->state_lock);
@@ -3523,7 +3588,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
#ifdef CONFIG_MLX5_CORE_EN_DCB
- netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
+ if (MLX5_CAP_GEN(mdev, qos))
+ netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
#endif
} else {
netdev->netdev_ops = &mlx5e_netdev_ops_basic;
@@ -3619,43 +3685,6 @@ static void mlx5e_destroy_q_counter(struct mlx5e_priv *priv)
mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter);
}
-static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
-{
- struct mlx5_core_dev *mdev = priv->mdev;
- u64 npages = MLX5E_REQUIRED_MTTS(priv->profile->max_nch(mdev),
- BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW));
- int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
- void *mkc;
- u32 *in;
- int err;
-
- in = mlx5_vzalloc(inlen);
- if (!in)
- return -ENOMEM;
-
- mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
-
- npages = min_t(u32, ALIGN(U16_MAX, 4) * 2, npages);
-
- MLX5_SET(mkc, mkc, free, 1);
- MLX5_SET(mkc, mkc, umr_en, 1);
- MLX5_SET(mkc, mkc, lw, 1);
- MLX5_SET(mkc, mkc, lr, 1);
- MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
-
- MLX5_SET(mkc, mkc, qpn, 0xffffff);
- MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
- MLX5_SET64(mkc, mkc, len, npages << PAGE_SHIFT);
- MLX5_SET(mkc, mkc, translations_octword_size,
- MLX5_MTT_OCTW(npages));
- MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT);
-
- err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen);
-
- kvfree(in);
- return err;
-}
-
static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
struct net_device *netdev,
const struct mlx5e_profile *profile,
@@ -3677,6 +3706,9 @@ static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
if (MLX5_CAP_GEN(mdev, vport_group_manager))
mlx5_eswitch_unregister_vport_rep(esw, 0);
+
+ if (priv->xdp_prog)
+ bpf_prog_put(priv->xdp_prog);
}
static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
@@ -3759,7 +3791,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
}
#ifdef CONFIG_MLX5_CORE_EN_DCB
- mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
+ mlx5e_dcbnl_initialize(priv);
#endif
return 0;
}
@@ -3787,7 +3819,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
rep.load = mlx5e_nic_rep_load;
rep.unload = mlx5e_nic_rep_unload;
rep.vport = FDB_UPLINK_VPORT;
- rep.priv_data = priv;
+ rep.netdev = netdev;
mlx5_eswitch_register_vport_rep(esw, 0, &rep);
}
}
@@ -3852,21 +3884,16 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
{
const struct mlx5e_profile *profile;
struct mlx5e_priv *priv;
+ u16 max_mtu;
int err;
priv = netdev_priv(netdev);
profile = priv->profile;
clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
- err = mlx5e_create_umr_mkey(priv);
- if (err) {
- mlx5_core_err(mdev, "create umr mkey failed, %d\n", err);
- goto out;
- }
-
err = profile->init_tx(priv);
if (err)
- goto err_destroy_umr_mkey;
+ goto out;
err = mlx5e_open_drop_rq(priv);
if (err) {
@@ -3882,6 +3909,11 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
mlx5e_init_l2_addr(priv);
+ /* MTU range: 68 - hw-specific max */
+ netdev->min_mtu = ETH_MIN_MTU;
+ mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
+ netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
mlx5e_set_dev_port_mtu(netdev);
if (profile->enable)
@@ -3901,9 +3933,6 @@ err_close_drop_rq:
err_cleanup_tx:
profile->cleanup_tx(priv);
-err_destroy_umr_mkey:
- mlx5_core_destroy_mkey(mdev, &priv->umr_mkey);
-
out:
return err;
}
@@ -3952,7 +3981,6 @@ void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
profile->cleanup_rx(priv);
mlx5e_close_drop_rq(priv);
profile->cleanup_tx(priv);
- mlx5_core_destroy_mkey(priv->mdev, &priv->umr_mkey);
cancel_delayed_work_sync(&priv->update_stats_work);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index bf1c09ca73c0..850378893b25 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -72,7 +72,29 @@ static void mlx5e_rep_get_strings(struct net_device *dev,
}
}
-static void mlx5e_update_sw_rep_counters(struct mlx5e_priv *priv)
+static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
+{
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+ struct mlx5_eswitch_rep *rep = priv->ppriv;
+ struct rtnl_link_stats64 *vport_stats;
+ struct ifla_vf_stats vf_stats;
+ int err;
+
+ err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats);
+ if (err) {
+ pr_warn("vport %d error %d reading stats\n", rep->vport, err);
+ return;
+ }
+
+ vport_stats = &priv->stats.vf_vport;
+ /* flip tx/rx as we are reporting the counters for the switch vport */
+ vport_stats->rx_packets = vf_stats.tx_packets;
+ vport_stats->rx_bytes = vf_stats.tx_bytes;
+ vport_stats->tx_packets = vf_stats.rx_packets;
+ vport_stats->tx_bytes = vf_stats.rx_bytes;
+}
+
+static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
{
struct mlx5e_sw_stats *s = &priv->stats.sw;
struct mlx5e_rq_stats *rq_stats;
@@ -95,6 +117,12 @@ static void mlx5e_update_sw_rep_counters(struct mlx5e_priv *priv)
}
}
+static void mlx5e_rep_update_stats(struct mlx5e_priv *priv)
+{
+ mlx5e_rep_update_sw_counters(priv);
+ mlx5e_rep_update_hw_counters(priv);
+}
+
static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
@@ -106,7 +134,7 @@ static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
mutex_lock(&priv->state_lock);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
- mlx5e_update_sw_rep_counters(priv);
+ mlx5e_rep_update_sw_counters(priv);
mutex_unlock(&priv->state_lock);
for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
@@ -180,7 +208,8 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
int mlx5e_nic_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
{
- struct mlx5e_priv *priv = rep->priv_data;
+ struct net_device *netdev = rep->netdev;
+ struct mlx5e_priv *priv = netdev_priv(netdev);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
return mlx5e_add_sqs_fwd_rules(priv);
@@ -198,7 +227,8 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
void mlx5e_nic_rep_unload(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
- struct mlx5e_priv *priv = rep->priv_data;
+ struct net_device *netdev = rep->netdev;
+ struct mlx5e_priv *priv = netdev_priv(netdev);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
mlx5e_remove_sqs_fwd_rules(priv);
@@ -208,6 +238,35 @@ void mlx5e_nic_rep_unload(struct mlx5_eswitch *esw,
mlx5e_tc_init(priv);
}
+static int mlx5e_rep_open(struct net_device *dev)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_eswitch_rep *rep = priv->ppriv;
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+ int err;
+
+ err = mlx5e_open(dev);
+ if (err)
+ return err;
+
+ err = mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP);
+ if (!err)
+ netif_carrier_on(dev);
+
+ return 0;
+}
+
+static int mlx5e_rep_close(struct net_device *dev)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_eswitch_rep *rep = priv->ppriv;
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+ (void)mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
+
+ return mlx5e_close(dev);
+}
+
static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
char *buf, size_t len)
{
@@ -230,6 +289,14 @@ static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
return -EOPNOTSUPP;
+ if (tc->egress_dev) {
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+ struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);
+
+ return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
+ proto, tc);
+ }
+
switch (tc->type) {
case TC_SETUP_CLSFLOWER:
switch (tc->cls_flower->command) {
@@ -245,17 +312,92 @@ static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
}
}
+bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
+{
+ struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+ if (rep && rep->vport == FDB_UPLINK_VPORT && esw->mode == SRIOV_OFFLOADS)
+ return true;
+
+ return false;
+}
+
+bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
+{
+ struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+
+ if (rep && rep->vport != FDB_UPLINK_VPORT)
+ return true;
+
+ return false;
+}
+
+bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
+ switch (attr_id) {
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+ if (mlx5e_is_vf_vport_rep(priv) || mlx5e_is_uplink_rep(priv))
+ return true;
+ }
+
+ return false;
+}
+
+static int
+mlx5e_get_sw_stats64(const struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5e_sw_stats *sstats = &priv->stats.sw;
+
+ stats->rx_packets = sstats->rx_packets;
+ stats->rx_bytes = sstats->rx_bytes;
+ stats->tx_packets = sstats->tx_packets;
+ stats->tx_bytes = sstats->tx_bytes;
+
+ stats->tx_dropped = sstats->tx_queue_dropped;
+
+ return 0;
+}
+
+int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+ void *sp)
+{
+ switch (attr_id) {
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+ return mlx5e_get_sw_stats64(dev, sp);
+ }
+
+ return -EINVAL;
+}
+
+static struct rtnl_link_stats64 *
+mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
+ memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
+ return stats;
+}
+
static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
.switchdev_port_attr_get = mlx5e_attr_get,
};
static const struct net_device_ops mlx5e_netdev_ops_rep = {
- .ndo_open = mlx5e_open,
- .ndo_stop = mlx5e_close,
+ .ndo_open = mlx5e_rep_open,
+ .ndo_stop = mlx5e_rep_close,
.ndo_start_xmit = mlx5e_xmit,
.ndo_get_phys_port_name = mlx5e_rep_get_phys_port_name,
.ndo_setup_tc = mlx5e_rep_ndo_setup_tc,
- .ndo_get_stats64 = mlx5e_get_stats,
+ .ndo_get_stats64 = mlx5e_rep_get_stats,
+ .ndo_udp_tunnel_add = mlx5e_add_vxlan_port,
+ .ndo_udp_tunnel_del = mlx5e_del_vxlan_port,
+ .ndo_has_offload_stats = mlx5e_has_offload_stats,
+ .ndo_get_offload_stats = mlx5e_get_offload_stats,
};
static void mlx5e_build_rep_netdev_priv(struct mlx5_core_dev *mdev,
@@ -328,7 +470,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_eswitch_rep *rep = priv->ppriv;
struct mlx5_core_dev *mdev = priv->mdev;
- struct mlx5_flow_rule *flow_rule;
+ struct mlx5_flow_handle *flow_rule;
int err;
int i;
@@ -360,7 +502,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
return 0;
err_del_flow_rule:
- mlx5_del_flow_rule(rep->vport_rx_rule);
+ mlx5_del_flow_rules(rep->vport_rx_rule);
err_destroy_direct_tirs:
mlx5e_destroy_direct_tirs(priv);
err_destroy_direct_rqts:
@@ -375,7 +517,7 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
int i;
mlx5e_tc_cleanup(priv);
- mlx5_del_flow_rule(rep->vport_rx_rule);
+ mlx5_del_flow_rules(rep->vport_rx_rule);
mlx5e_destroy_direct_tirs(priv);
for (i = 0; i < priv->params.num_channels; i++)
mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
@@ -405,7 +547,7 @@ static struct mlx5e_profile mlx5e_rep_profile = {
.cleanup_rx = mlx5e_cleanup_rep_rx,
.init_tx = mlx5e_init_rep_tx,
.cleanup_tx = mlx5e_cleanup_nic_tx,
- .update_stats = mlx5e_update_sw_rep_counters,
+ .update_stats = mlx5e_rep_update_stats,
.max_nch = mlx5e_get_rep_max_num_channels,
.max_tc = 1,
};
@@ -423,7 +565,7 @@ int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
return -EINVAL;
}
- rep->priv_data = netdev_priv(netdev);
+ rep->netdev = netdev;
err = mlx5e_attach_netdev(esw->dev, netdev);
if (err) {
@@ -445,7 +587,7 @@ err_detach_netdev:
mlx5e_detach_netdev(esw->dev, netdev);
err_destroy_netdev:
- mlx5e_destroy_netdev(esw->dev, rep->priv_data);
+ mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));
return err;
@@ -454,10 +596,9 @@ err_destroy_netdev:
void mlx5e_vport_rep_unload(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
- struct mlx5e_priv *priv = rep->priv_data;
- struct net_device *netdev = priv->netdev;
+ struct net_device *netdev = rep->netdev;
unregister_netdev(netdev);
mlx5e_detach_netdev(esw->dev, netdev);
- mlx5e_destroy_netdev(esw->dev, priv);
+ mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 33495d88aeb2..0e2fb3ed1790 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -164,14 +164,14 @@ void mlx5e_modify_rx_cqe_compression(struct mlx5e_priv *priv, bool val)
mutex_lock(&priv->state_lock);
- if (priv->params.rx_cqe_compress == val)
+ if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) == val)
goto unlock;
was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
if (was_opened)
mlx5e_close_locked(priv->netdev);
- priv->params.rx_cqe_compress = val;
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, val);
if (was_opened)
mlx5e_open_locked(priv->netdev);
@@ -737,10 +737,10 @@ static inline
struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
u16 wqe_counter, u32 cqe_bcnt)
{
- struct bpf_prog *xdp_prog = READ_ONCE(rq->xdp_prog);
struct mlx5e_dma_info *di;
struct sk_buff *skb;
void *va, *data;
+ bool consumed;
di = &rq->dma_info[wqe_counter];
va = page_address(di->page);
@@ -759,7 +759,11 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
return NULL;
}
- if (mlx5e_xdp_handle(rq, xdp_prog, di, data, cqe_bcnt))
+ rcu_read_lock();
+ consumed = mlx5e_xdp_handle(rq, READ_ONCE(rq->xdp_prog), di, data,
+ cqe_bcnt);
+ rcu_read_unlock();
+ if (consumed)
return NULL; /* page/packet was consumed by XDP */
skb = build_skb(va, RQ_PAGE_SIZE(rq));
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
new file mode 100644
index 000000000000..65442c36a6e1
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies, Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/udp.h>
+#include "en.h"
+
+enum {
+ MLX5E_ST_LINK_STATE,
+ MLX5E_ST_LINK_SPEED,
+ MLX5E_ST_HEALTH_INFO,
+#ifdef CONFIG_INET
+ MLX5E_ST_LOOPBACK,
+#endif
+ MLX5E_ST_NUM,
+};
+
+const char mlx5e_self_tests[MLX5E_ST_NUM][ETH_GSTRING_LEN] = {
+ "Link Test",
+ "Speed Test",
+ "Health Test",
+#ifdef CONFIG_INET
+ "Loopback Test",
+#endif
+};
+
+int mlx5e_self_test_num(struct mlx5e_priv *priv)
+{
+ return ARRAY_SIZE(mlx5e_self_tests);
+}
+
+static int mlx5e_test_health_info(struct mlx5e_priv *priv)
+{
+ struct mlx5_core_health *health = &priv->mdev->priv.health;
+
+ return health->sick ? 1 : 0;
+}
+
+static int mlx5e_test_link_state(struct mlx5e_priv *priv)
+{
+ u8 port_state;
+
+ if (!netif_carrier_ok(priv->netdev))
+ return 1;
+
+ port_state = mlx5_query_vport_state(priv->mdev, MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT, 0);
+ return port_state == VPORT_STATE_UP ? 0 : 1;
+}
+
+static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ u32 eth_proto_oper;
+ int i;
+
+ if (!netif_carrier_ok(priv->netdev))
+ return 1;
+
+ if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1))
+ return 1;
+
+ eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
+ for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) {
+ if (eth_proto_oper & MLX5E_PROT_MASK(i))
+ return 0;
+ }
+ return 1;
+}
+
+#ifdef CONFIG_INET
+/* loopback test */
+#define MLX5E_TEST_PKT_SIZE (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD - NET_IP_ALIGN)
+static const char mlx5e_test_text[ETH_GSTRING_LEN] = "MLX5E SELF TEST";
+#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
+
+struct mlx5ehdr {
+ __be32 version;
+ __be64 magic;
+ char text[ETH_GSTRING_LEN];
+};
+
+static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
+{
+ struct sk_buff *skb = NULL;
+ struct mlx5ehdr *mlxh;
+ struct ethhdr *ethh;
+ struct udphdr *udph;
+ struct iphdr *iph;
+ int datalen, iplen;
+
+ datalen = MLX5E_TEST_PKT_SIZE -
+ (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph));
+
+ skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);
+ if (!skb) {
+ netdev_err(priv->netdev, "\tFailed to alloc loopback skb\n");
+ return NULL;
+ }
+
+ prefetchw(skb->data);
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ /* Reserve for ethernet and IP header */
+ ethh = (struct ethhdr *)skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+
+ skb_set_network_header(skb, skb->len);
+ iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
+
+ skb_set_transport_header(skb, skb->len);
+ udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+
+ /* Fill ETH header */
+ ether_addr_copy(ethh->h_dest, priv->netdev->dev_addr);
+ eth_zero_addr(ethh->h_source);
+ ethh->h_proto = htons(ETH_P_IP);
+
+ /* Fill UDP header */
+ udph->source = htons(9);
+ udph->dest = htons(9); /* Discard Protocol */
+ udph->len = htons(datalen + sizeof(struct udphdr));
+ udph->check = 0;
+
+ /* Fill IP header */
+ iph->ihl = 5;
+ iph->ttl = 32;
+ iph->version = 4;
+ iph->protocol = IPPROTO_UDP;
+ iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen;
+ iph->tot_len = htons(iplen);
+ iph->frag_off = 0;
+ iph->saddr = 0;
+ iph->daddr = 0;
+ iph->tos = 0;
+ iph->id = 0;
+ ip_send_check(iph);
+
+ /* Fill test header and data */
+ mlxh = (struct mlx5ehdr *)skb_put(skb, sizeof(*mlxh));
+ mlxh->version = 0;
+ mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC);
+ strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text));
+ datalen -= sizeof(*mlxh);
+ memset(skb_put(skb, datalen), 0, datalen);
+
+ skb->csum = 0;
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ udp4_hwcsum(skb, iph->saddr, iph->daddr);
+
+ skb->protocol = htons(ETH_P_IP);
+ skb->pkt_type = PACKET_HOST;
+ skb->dev = priv->netdev;
+
+ return skb;
+}
+
+struct mlx5e_lbt_priv {
+ struct packet_type pt;
+ struct completion comp;
+ bool loopback_ok;
+};
+
+static int
+mlx5e_test_loopback_validate(struct sk_buff *skb,
+ struct net_device *ndev,
+ struct packet_type *pt,
+ struct net_device *orig_ndev)
+{
+ struct mlx5e_lbt_priv *lbtp = pt->af_packet_priv;
+ struct mlx5ehdr *mlxh;
+ struct ethhdr *ethh;
+ struct udphdr *udph;
+ struct iphdr *iph;
+
+ /* We are only going to peek, no need to clone the SKB */
+ if (skb->protocol != htons(ETH_P_IP))
+ goto out;
+
+ if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
+ goto out;
+
+ ethh = (struct ethhdr *)skb_mac_header(skb);
+ if (!ether_addr_equal(ethh->h_dest, orig_ndev->dev_addr))
+ goto out;
+
+ iph = ip_hdr(skb);
+ if (iph->protocol != IPPROTO_UDP)
+ goto out;
+
+ udph = udp_hdr(skb);
+ if (udph->dest != htons(9))
+ goto out;
+
+ mlxh = (struct mlx5ehdr *)((char *)udph + sizeof(*udph));
+ if (mlxh->magic != cpu_to_be64(MLX5E_TEST_MAGIC))
+ goto out; /* so close ! */
+
+ /* bingo */
+ lbtp->loopback_ok = true;
+ complete(&lbtp->comp);
+out:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
+ struct mlx5e_lbt_priv *lbtp)
+{
+ int err = 0;
+
+ err = mlx5e_refresh_tirs_self_loopback(priv->mdev, true);
+ if (err) {
+ netdev_err(priv->netdev,
+ "\tFailed to enable UC loopback err(%d)\n", err);
+ return err;
+ }
+
+ lbtp->loopback_ok = false;
+ init_completion(&lbtp->comp);
+
+ lbtp->pt.type = htons(ETH_P_ALL);
+ lbtp->pt.func = mlx5e_test_loopback_validate;
+ lbtp->pt.dev = priv->netdev;
+ lbtp->pt.af_packet_priv = lbtp;
+ dev_add_pack(&lbtp->pt);
+ return err;
+}
+
+static void mlx5e_test_loopback_cleanup(struct mlx5e_priv *priv,
+ struct mlx5e_lbt_priv *lbtp)
+{
+ dev_remove_pack(&lbtp->pt);
+ mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
+}
+
+#define MLX5E_LB_VERIFY_TIMEOUT (msecs_to_jiffies(200))
+static int mlx5e_test_loopback(struct mlx5e_priv *priv)
+{
+ struct mlx5e_lbt_priv *lbtp;
+ struct sk_buff *skb = NULL;
+ int err;
+
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+ netdev_err(priv->netdev,
+ "\tCan't perform loobpack test while device is down\n");
+ return -ENODEV;
+ }
+
+ lbtp = kzalloc(sizeof(*lbtp), GFP_KERNEL);
+ if (!lbtp)
+ return -ENOMEM;
+ lbtp->loopback_ok = false;
+
+ err = mlx5e_test_loopback_setup(priv, lbtp);
+ if (err)
+ goto out;
+
+ skb = mlx5e_test_get_udp_skb(priv);
+ if (!skb) {
+ err = -ENOMEM;
+ goto cleanup;
+ }
+
+ skb_set_queue_mapping(skb, 0);
+ err = dev_queue_xmit(skb);
+ if (err) {
+ netdev_err(priv->netdev,
+ "\tFailed to xmit loopback packet err(%d)\n",
+ err);
+ goto cleanup;
+ }
+
+ wait_for_completion_timeout(&lbtp->comp, MLX5E_LB_VERIFY_TIMEOUT);
+ err = !lbtp->loopback_ok;
+
+cleanup:
+ mlx5e_test_loopback_cleanup(priv, lbtp);
+out:
+ kfree(lbtp);
+ return err;
+}
+#endif
+
+static int (*mlx5e_st_func[MLX5E_ST_NUM])(struct mlx5e_priv *) = {
+ mlx5e_test_link_state,
+ mlx5e_test_link_speed,
+ mlx5e_test_health_info,
+#ifdef CONFIG_INET
+ mlx5e_test_loopback,
+#endif
+};
+
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf)
+{
+ struct mlx5e_priv *priv = netdev_priv(ndev);
+ int i;
+
+ memset(buf, 0, sizeof(u64) * MLX5E_ST_NUM);
+
+ mutex_lock(&priv->state_lock);
+ netdev_info(ndev, "Self test begin..\n");
+
+ for (i = 0; i < MLX5E_ST_NUM; i++) {
+ netdev_info(ndev, "\t[%d] %s start..\n",
+ i, mlx5e_self_tests[i]);
+ buf[i] = mlx5e_st_func[i](priv);
+ netdev_info(ndev, "\t[%d] %s end: result(%lld)\n",
+ i, mlx5e_self_tests[i], buf[i]);
+ }
+
+ mutex_unlock(&priv->state_lock);
+
+ for (i = 0; i < MLX5E_ST_NUM; i++) {
+ if (buf[i]) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ break;
+ }
+ }
+ netdev_info(ndev, "Self test out: status flags(0x%x)\n",
+ etest->flags);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index 57452fdc5154..f202f872f57f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -39,7 +39,7 @@
#define MLX5E_READ_CTR32_CPU(ptr, dsc, i) \
(*(u32 *)((char *)ptr + dsc[i].offset))
#define MLX5E_READ_CTR32_BE(ptr, dsc, i) \
- be64_to_cpu(*(__be32 *)((char *)ptr + dsc[i].offset))
+ be32_to_cpu(*(__be32 *)((char *)ptr + dsc[i].offset))
#define MLX5E_DECLARE_STAT(type, fld) #fld, offsetof(type, fld)
#define MLX5E_DECLARE_RX_STAT(type, fld) "rx%d_"#fld, offsetof(type, fld)
@@ -276,6 +276,32 @@ static const struct counter_desc pport_per_prio_pfc_stats_desc[] = {
{ "rx_%s_pause_transition", PPORT_PER_PRIO_OFF(rx_pause_transition) },
};
+#define PCIE_PERF_OFF(c) \
+ MLX5_BYTE_OFF(mpcnt_reg, counter_set.pcie_perf_cntrs_grp_data_layout.c)
+#define PCIE_PERF_GET(pcie_stats, c) \
+ MLX5_GET(mpcnt_reg, pcie_stats->pcie_perf_counters, \
+ counter_set.pcie_perf_cntrs_grp_data_layout.c)
+#define PCIE_TAS_OFF(c) \
+ MLX5_BYTE_OFF(mpcnt_reg, counter_set.pcie_tas_cntrs_grp_data_layout.c)
+#define PCIE_TAS_GET(pcie_stats, c) \
+ MLX5_GET(mpcnt_reg, pcie_stats->pcie_tas_counters, \
+ counter_set.pcie_tas_cntrs_grp_data_layout.c)
+
+struct mlx5e_pcie_stats {
+ __be64 pcie_perf_counters[MLX5_ST_SZ_QW(mpcnt_reg)];
+ __be64 pcie_tas_counters[MLX5_ST_SZ_QW(mpcnt_reg)];
+};
+
+static const struct counter_desc pcie_perf_stats_desc[] = {
+ { "rx_pci_signal_integrity", PCIE_PERF_OFF(rx_errors) },
+ { "tx_pci_signal_integrity", PCIE_PERF_OFF(tx_errors) },
+};
+
+static const struct counter_desc pcie_tas_stats_desc[] = {
+ { "tx_pci_transport_nonfatal_msg", PCIE_TAS_OFF(non_fatal_err_msg_sent) },
+ { "tx_pci_transport_fatal_msg", PCIE_TAS_OFF(fatal_err_msg_sent) },
+};
+
struct mlx5e_rq_stats {
u64 packets;
u64 bytes;
@@ -360,6 +386,8 @@ static const struct counter_desc sq_stats_desc[] = {
#define NUM_PPORT_802_3_COUNTERS ARRAY_SIZE(pport_802_3_stats_desc)
#define NUM_PPORT_2863_COUNTERS ARRAY_SIZE(pport_2863_stats_desc)
#define NUM_PPORT_2819_COUNTERS ARRAY_SIZE(pport_2819_stats_desc)
+#define NUM_PCIE_PERF_COUNTERS ARRAY_SIZE(pcie_perf_stats_desc)
+#define NUM_PCIE_TAS_COUNTERS ARRAY_SIZE(pcie_tas_stats_desc)
#define NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS \
ARRAY_SIZE(pport_per_prio_traffic_stats_desc)
#define NUM_PPORT_PER_PRIO_PFC_COUNTERS \
@@ -369,6 +397,7 @@ static const struct counter_desc sq_stats_desc[] = {
NUM_PPORT_2819_COUNTERS + \
NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS * \
NUM_PPORT_PRIO)
+#define NUM_PCIE_COUNTERS (NUM_PCIE_PERF_COUNTERS + NUM_PCIE_TAS_COUNTERS)
#define NUM_RQ_STATS ARRAY_SIZE(rq_stats_desc)
#define NUM_SQ_STATS ARRAY_SIZE(sq_stats_desc)
@@ -377,6 +406,25 @@ struct mlx5e_stats {
struct mlx5e_qcounter_stats qcnt;
struct mlx5e_vport_stats vport;
struct mlx5e_pport_stats pport;
+ struct mlx5e_pcie_stats pcie;
+ struct rtnl_link_stats64 vf_vport;
+};
+
+static const struct counter_desc mlx5e_pme_status_desc[] = {
+ { "module_plug", 0 },
+ { "module_unplug", 8 },
+};
+
+static const struct counter_desc mlx5e_pme_error_desc[] = {
+ { "module_pwr_budget_exd", 0 }, /* power budget exceed */
+ { "module_long_range", 8 }, /* long range for non MLNX cable */
+ { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */
+ { "module_no_eeprom", 24 }, /* no eeprom/retry time out */
+ { "module_enforce_part", 32 }, /* enforce part number list */
+ { "module_unknown_id", 40 }, /* unknown identifier */
+ { "module_high_temp", 48 }, /* high temperature */
+ { "module_bad_shorted", 56 }, /* bad or shorted cable/module */
+ { "module_unknown_status", 64 },
};
#endif /* __MLX5_EN_STATS_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 6bb21b31cfeb..f8829b517156 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -31,6 +31,7 @@
*/
#include <net/flow_dissector.h>
+#include <net/sch_generic.h>
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_skbedit.h>
@@ -40,28 +41,43 @@
#include <net/switchdev.h>
#include <net/tc_act/tc_mirred.h>
#include <net/tc_act/tc_vlan.h>
+#include <net/tc_act/tc_tunnel_key.h>
+#include <net/vxlan.h>
#include "en.h"
#include "en_tc.h"
#include "eswitch.h"
+#include "vxlan.h"
struct mlx5e_tc_flow {
struct rhash_head node;
u64 cookie;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
+ struct list_head encap; /* flows sharing the same encap */
struct mlx5_esw_flow_attr *attr;
};
+enum {
+ MLX5_HEADER_TYPE_VXLAN = 0x0,
+ MLX5_HEADER_TYPE_NVGRE = 0x1,
+};
+
#define MLX5E_TC_TABLE_NUM_ENTRIES 1024
#define MLX5E_TC_TABLE_NUM_GROUPS 4
-static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
- struct mlx5_flow_spec *spec,
- u32 action, u32 flow_tag)
+static struct mlx5_flow_handle *
+mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ struct mlx5_flow_spec *spec,
+ u32 action, u32 flow_tag)
{
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_flow_destination dest = { 0 };
+ struct mlx5_flow_act flow_act = {
+ .action = action,
+ .flow_tag = flow_tag,
+ .encap_id = 0,
+ };
struct mlx5_fc *counter = NULL;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
bool table_created = false;
if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
@@ -82,7 +98,7 @@ static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
MLX5E_TC_PRIO,
MLX5E_TC_TABLE_NUM_ENTRIES,
MLX5E_TC_TABLE_NUM_GROUPS,
- 0);
+ 0, 0);
if (IS_ERR(priv->fs.tc.t)) {
netdev_err(priv->netdev,
"Failed to create tc offload table\n");
@@ -94,9 +110,7 @@ static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
}
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
- rule = mlx5_add_flow_rule(priv->fs.tc.t, spec,
- action, flow_tag,
- &dest);
+ rule = mlx5_add_flow_rules(priv->fs.tc.t, spec, &flow_act, &dest, 1);
if (IS_ERR(rule))
goto err_add_rule;
@@ -114,9 +128,10 @@ err_create_ft:
return rule;
}
-static struct mlx5_flow_rule *mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
- struct mlx5_flow_spec *spec,
- struct mlx5_esw_flow_attr *attr)
+static struct mlx5_flow_handle *
+mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+ struct mlx5_flow_spec *spec,
+ struct mlx5_esw_flow_attr *attr)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
int err;
@@ -128,19 +143,39 @@ static struct mlx5_flow_rule *mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
}
+static void mlx5e_detach_encap(struct mlx5e_priv *priv,
+ struct mlx5e_tc_flow *flow) {
+ struct list_head *next = flow->encap.next;
+
+ list_del(&flow->encap);
+ if (list_empty(next)) {
+ struct mlx5_encap_entry *e;
+
+ e = list_entry(next, struct mlx5_encap_entry, flows);
+ if (e->n) {
+ mlx5_encap_dealloc(priv->mdev, e->encap_id);
+ neigh_release(e->n);
+ }
+ hlist_del_rcu(&e->encap_hlist);
+ kfree(e);
+ }
+}
+
static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
- struct mlx5_flow_rule *rule,
- struct mlx5_esw_flow_attr *attr)
+ struct mlx5e_tc_flow *flow)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_fc *counter = NULL;
- counter = mlx5_flow_rule_counter(rule);
+ counter = mlx5_flow_rule_counter(flow->rule);
- if (esw && esw->mode == SRIOV_OFFLOADS)
- mlx5_eswitch_del_vlan_action(esw, attr);
+ mlx5_del_flow_rules(flow->rule);
- mlx5_del_flow_rule(rule);
+ if (esw && esw->mode == SRIOV_OFFLOADS) {
+ mlx5_eswitch_del_vlan_action(esw, flow->attr);
+ if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
+ mlx5e_detach_encap(priv, flow);
+ }
mlx5_fc_destroy(priv->mdev, counter);
@@ -150,8 +185,125 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
}
}
-static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec,
- struct tc_cls_flower_offload *f)
+static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
+ struct tc_cls_flower_offload *f)
+{
+ void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+ outer_headers);
+ void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+ outer_headers);
+ void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+ misc_parameters);
+ void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+ misc_parameters);
+
+ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_dissector_key_keyid *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_KEYID,
+ f->key);
+ struct flow_dissector_key_keyid *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_KEYID,
+ f->mask);
+ MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni,
+ be32_to_cpu(mask->keyid));
+ MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni,
+ be32_to_cpu(key->keyid));
+ }
+}
+
+static int parse_tunnel_attr(struct mlx5e_priv *priv,
+ struct mlx5_flow_spec *spec,
+ struct tc_cls_flower_offload *f)
+{
+ void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+ outer_headers);
+ void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+ outer_headers);
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
+ struct flow_dissector_key_ports *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_PORTS,
+ f->key);
+ struct flow_dissector_key_ports *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_PORTS,
+ f->mask);
+
+ /* Full udp dst port must be given */
+ if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
+ return -EOPNOTSUPP;
+
+ /* udp src port isn't supported */
+ if (memchr_inv(&mask->src, 0, sizeof(mask->src)))
+ return -EOPNOTSUPP;
+
+ if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) &&
+ MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
+ parse_vxlan_attr(spec, f);
+ else
+ return -EOPNOTSUPP;
+
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+ udp_dport, ntohs(mask->dst));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+ udp_dport, ntohs(key->dst));
+
+ } else { /* udp dst port must be given */
+ return -EOPNOTSUPP;
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
+ struct flow_dissector_key_ipv4_addrs *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
+ f->key);
+ struct flow_dissector_key_ipv4_addrs *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
+ f->mask);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+ src_ipv4_src_ipv6.ipv4_layout.ipv4,
+ ntohl(mask->src));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+ src_ipv4_src_ipv6.ipv4_layout.ipv4,
+ ntohl(key->src));
+
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+ dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
+ ntohl(mask->dst));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+ dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
+ ntohl(key->dst));
+ }
+
+ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
+
+ /* Enforce DMAC when offloading incoming tunneled flows.
+ * Flow counters require a match on the DMAC.
+ */
+ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16);
+ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0);
+ ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
+ dmac_47_16), priv->netdev->dev_addr);
+
+ /* let software handle IP fragments */
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
+
+ return 0;
+}
+
+static int __parse_cls_flower(struct mlx5e_priv *priv,
+ struct mlx5_flow_spec *spec,
+ struct tc_cls_flower_offload *f,
+ u8 *min_inline)
{
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
outer_headers);
@@ -160,6 +312,8 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
u16 addr_type = 0;
u8 ip_proto = 0;
+ *min_inline = MLX5_INLINE_MODE_L2;
+
if (f->dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
@@ -167,18 +321,61 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
BIT(FLOW_DISSECTOR_KEY_VLAN) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
- BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+ BIT(FLOW_DISSECTOR_KEY_PORTS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
f->dissector->used_keys);
return -EOPNOTSUPP;
}
+ if ((dissector_uses_key(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
+ dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
+ dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
+ dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+ struct flow_dissector_key_control *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_CONTROL,
+ f->key);
+ switch (key->addr_type) {
+ case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
+ if (parse_tunnel_attr(priv, spec, f))
+ return -EOPNOTSUPP;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* In decap flow, header pointers should point to the inner
+ * headers, outer header were already set by parse_tunnel_attr
+ */
+ headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+ inner_headers);
+ headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+ inner_headers);
+ }
+
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
struct flow_dissector_key_control *key =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_CONTROL,
f->key);
+
+ struct flow_dissector_key_control *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_CONTROL,
+ f->mask);
addr_type = key->addr_type;
+
+ if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
+ key->flags & FLOW_DIS_IS_FRAGMENT);
+ }
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
@@ -201,6 +398,9 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
mask->ip_proto);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
key->ip_proto);
+
+ if (mask->ip_proto)
+ *min_inline = MLX5_INLINE_MODE_IP;
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
@@ -271,6 +471,9 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
&key->dst, sizeof(key->dst));
+
+ if (mask->src || mask->dst)
+ *min_inline = MLX5_INLINE_MODE_IP;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
@@ -296,6 +499,10 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
&key->dst, sizeof(key->dst));
+
+ if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
+ ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
+ *min_inline = MLX5_INLINE_MODE_IP;
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
@@ -336,11 +543,39 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec
"Only UDP and TCP transport are supported\n");
return -EINVAL;
}
+
+ if (mask->src || mask->dst)
+ *min_inline = MLX5_INLINE_MODE_TCP_UDP;
}
return 0;
}
+static int parse_cls_flower(struct mlx5e_priv *priv,
+ struct mlx5_flow_spec *spec,
+ struct tc_cls_flower_offload *f)
+{
+ struct mlx5_core_dev *dev = priv->mdev;
+ struct mlx5_eswitch *esw = dev->priv.eswitch;
+ struct mlx5_eswitch_rep *rep = priv->ppriv;
+ u8 min_inline;
+ int err;
+
+ err = __parse_cls_flower(priv, spec, f, &min_inline);
+
+ if (!err && esw->mode == SRIOV_OFFLOADS &&
+ rep->vport != FDB_UPLINK_VPORT) {
+ if (min_inline > esw->offloads.inline_mode) {
+ netdev_warn(priv->netdev,
+ "Flow is not offloaded due to min inline setting, required %d actual %d\n",
+ min_inline, esw->offloads.inline_mode);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return err;
+}
+
static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
u32 *action, u32 *flow_tag)
{
@@ -387,11 +622,243 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return 0;
}
+static inline int cmp_encap_info(struct mlx5_encap_info *a,
+ struct mlx5_encap_info *b)
+{
+ return memcmp(a, b, sizeof(*a));
+}
+
+static inline int hash_encap_info(struct mlx5_encap_info *info)
+{
+ return jhash(info, sizeof(*info), 0);
+}
+
+static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
+ struct net_device *mirred_dev,
+ struct net_device **out_dev,
+ struct flowi4 *fl4,
+ struct neighbour **out_n,
+ __be32 *saddr,
+ int *out_ttl)
+{
+ struct rtable *rt;
+ struct neighbour *n = NULL;
+ int ttl;
+
+#if IS_ENABLED(CONFIG_INET)
+ rt = ip_route_output_key(dev_net(mirred_dev), fl4);
+ if (IS_ERR(rt)) {
+ pr_warn("%s: no route to %pI4\n", __func__, &fl4->daddr);
+ return -EOPNOTSUPP;
+ }
+#else
+ return -EOPNOTSUPP;
+#endif
+
+ if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev)) {
+ pr_warn("%s: Can't offload the flow, netdevices aren't on the same HW e-switch\n",
+ __func__);
+ ip_rt_put(rt);
+ return -EOPNOTSUPP;
+ }
+
+ ttl = ip4_dst_hoplimit(&rt->dst);
+ n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
+ ip_rt_put(rt);
+ if (!n)
+ return -ENOMEM;
+
+ *out_n = n;
+ *saddr = fl4->saddr;
+ *out_ttl = ttl;
+ *out_dev = rt->dst.dev;
+
+ return 0;
+}
+
+static int gen_vxlan_header_ipv4(struct net_device *out_dev,
+ char buf[],
+ unsigned char h_dest[ETH_ALEN],
+ int ttl,
+ __be32 daddr,
+ __be32 saddr,
+ __be16 udp_dst_port,
+ __be32 vx_vni)
+{
+ int encap_size = VXLAN_HLEN + sizeof(struct iphdr) + ETH_HLEN;
+ struct ethhdr *eth = (struct ethhdr *)buf;
+ struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr));
+ struct udphdr *udp = (struct udphdr *)((char *)ip + sizeof(struct iphdr));
+ struct vxlanhdr *vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
+
+ memset(buf, 0, encap_size);
+
+ ether_addr_copy(eth->h_dest, h_dest);
+ ether_addr_copy(eth->h_source, out_dev->dev_addr);
+ eth->h_proto = htons(ETH_P_IP);
+
+ ip->daddr = daddr;
+ ip->saddr = saddr;
+
+ ip->ttl = ttl;
+ ip->protocol = IPPROTO_UDP;
+ ip->version = 0x4;
+ ip->ihl = 0x5;
+
+ udp->dest = udp_dst_port;
+ vxh->vx_flags = VXLAN_HF_VNI;
+ vxh->vx_vni = vxlan_vni_field(vx_vni);
+
+ return encap_size;
+}
+
+static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
+ struct net_device *mirred_dev,
+ struct mlx5_encap_entry *e,
+ struct net_device **out_dev)
+{
+ int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
+ struct flowi4 fl4 = {};
+ struct neighbour *n;
+ char *encap_header;
+ int encap_size;
+ __be32 saddr;
+ int ttl;
+ int err;
+
+ encap_header = kzalloc(max_encap_size, GFP_KERNEL);
+ if (!encap_header)
+ return -ENOMEM;
+
+ switch (e->tunnel_type) {
+ case MLX5_HEADER_TYPE_VXLAN:
+ fl4.flowi4_proto = IPPROTO_UDP;
+ fl4.fl4_dport = e->tun_info.tp_dst;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+ fl4.daddr = e->tun_info.daddr;
+
+ err = mlx5e_route_lookup_ipv4(priv, mirred_dev, out_dev,
+ &fl4, &n, &saddr, &ttl);
+ if (err)
+ goto out;
+
+ e->n = n;
+ e->out_dev = *out_dev;
+
+ if (!(n->nud_state & NUD_VALID)) {
+ err = -ENOTSUPP;
+ goto out;
+ }
+
+ neigh_ha_snapshot(e->h_dest, n, *out_dev);
+
+ switch (e->tunnel_type) {
+ case MLX5_HEADER_TYPE_VXLAN:
+ encap_size = gen_vxlan_header_ipv4(*out_dev, encap_header,
+ e->h_dest, ttl,
+ e->tun_info.daddr,
+ saddr, e->tun_info.tp_dst,
+ e->tun_info.tun_id);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
+ encap_size, encap_header, &e->encap_id);
+out:
+ kfree(encap_header);
+ return err;
+}
+
+static int mlx5e_attach_encap(struct mlx5e_priv *priv,
+ struct ip_tunnel_info *tun_info,
+ struct net_device *mirred_dev,
+ struct mlx5_esw_flow_attr *attr)
+{
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+ unsigned short family = ip_tunnel_info_af(tun_info);
+ struct ip_tunnel_key *key = &tun_info->key;
+ struct mlx5_encap_info info;
+ struct mlx5_encap_entry *e;
+ struct net_device *out_dev;
+ uintptr_t hash_key;
+ bool found = false;
+ int tunnel_type;
+ int err;
+
+ /* udp dst port must be given */
+ if (!memchr_inv(&key->tp_dst, 0, sizeof(key->tp_dst)))
+ return -EOPNOTSUPP;
+
+ if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) &&
+ MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
+ info.tp_dst = key->tp_dst;
+ info.tun_id = tunnel_id_to_key32(key->tun_id);
+ tunnel_type = MLX5_HEADER_TYPE_VXLAN;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ switch (family) {
+ case AF_INET:
+ info.daddr = key->u.ipv4.dst;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ hash_key = hash_encap_info(&info);
+
+ hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
+ encap_hlist, hash_key) {
+ if (!cmp_encap_info(&e->tun_info, &info)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ attr->encap = e;
+ return 0;
+ }
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+
+ e->tun_info = info;
+ e->tunnel_type = tunnel_type;
+ INIT_LIST_HEAD(&e->flows);
+
+ err = mlx5e_create_encap_header_ipv4(priv, mirred_dev, e, &out_dev);
+ if (err)
+ goto out_err;
+
+ attr->encap = e;
+ hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
+
+ return err;
+
+out_err:
+ kfree(e);
+ return err;
+}
+
static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
- struct mlx5_esw_flow_attr *attr)
+ struct mlx5e_tc_flow *flow)
{
+ struct mlx5_esw_flow_attr *attr = flow->attr;
+ struct ip_tunnel_info *info = NULL;
const struct tc_action *a;
LIST_HEAD(actions);
+ bool encap = false;
+ int err;
if (tc_no_actions(exts))
return -EINVAL;
@@ -407,22 +874,44 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
- if (is_tcf_mirred_redirect(a)) {
+ if (is_tcf_mirred_egress_redirect(a)) {
int ifindex = tcf_mirred_ifindex(a);
struct net_device *out_dev;
struct mlx5e_priv *out_priv;
out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex);
- if (!switchdev_port_same_parent_id(priv->netdev, out_dev)) {
+ if (switchdev_port_same_parent_id(priv->netdev,
+ out_dev)) {
+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ out_priv = netdev_priv(out_dev);
+ attr->out_rep = out_priv->ppriv;
+ } else if (encap) {
+ err = mlx5e_attach_encap(priv, info,
+ out_dev, attr);
+ if (err)
+ return err;
+ list_add(&flow->encap, &attr->encap->flows);
+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
+ MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ out_priv = netdev_priv(attr->encap->out_dev);
+ attr->out_rep = out_priv->ppriv;
+ } else {
pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
priv->netdev->name, out_dev->name);
return -EINVAL;
}
+ continue;
+ }
- attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- out_priv = netdev_priv(out_dev);
- attr->out_rep = out_priv->ppriv;
+ if (is_tcf_tunnel_set(a)) {
+ info = tcf_tunnel_info(a);
+ if (info)
+ encap = true;
+ else
+ return -EOPNOTSUPP;
continue;
}
@@ -439,6 +928,11 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
+ if (is_tcf_tunnel_release(a)) {
+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
+ continue;
+ }
+
return -EINVAL;
}
return 0;
@@ -453,25 +947,17 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
u32 flow_tag, action;
struct mlx5e_tc_flow *flow;
struct mlx5_flow_spec *spec;
- struct mlx5_flow_rule *old = NULL;
- struct mlx5_esw_flow_attr *old_attr = NULL;
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
if (esw && esw->mode == SRIOV_OFFLOADS)
fdb_flow = true;
- flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
- tc->ht_params);
- if (flow) {
- old = flow->rule;
- old_attr = flow->attr;
- } else {
- if (fdb_flow)
- flow = kzalloc(sizeof(*flow) + sizeof(struct mlx5_esw_flow_attr),
- GFP_KERNEL);
- else
- flow = kzalloc(sizeof(*flow), GFP_KERNEL);
- }
+ if (fdb_flow)
+ flow = kzalloc(sizeof(*flow) +
+ sizeof(struct mlx5_esw_flow_attr),
+ GFP_KERNEL);
+ else
+ flow = kzalloc(sizeof(*flow), GFP_KERNEL);
spec = mlx5_vzalloc(sizeof(*spec));
if (!spec || !flow) {
@@ -487,7 +973,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
if (fdb_flow) {
flow->attr = (struct mlx5_esw_flow_attr *)(flow + 1);
- err = parse_tc_fdb_actions(priv, f->exts, flow->attr);
+ err = parse_tc_fdb_actions(priv, f->exts, flow);
if (err < 0)
goto err_free;
flow->rule = mlx5e_tc_add_fdb_flow(priv, spec, flow->attr);
@@ -508,17 +994,13 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
if (err)
goto err_del_rule;
- if (old)
- mlx5e_tc_del_flow(priv, old, old_attr);
-
goto out;
err_del_rule:
- mlx5_del_flow_rule(flow->rule);
+ mlx5_del_flow_rules(flow->rule);
err_free:
- if (!old)
- kfree(flow);
+ kfree(flow);
out:
kvfree(spec);
return err;
@@ -537,7 +1019,8 @@ int mlx5e_delete_flower(struct mlx5e_priv *priv,
rhashtable_remove_fast(&tc->ht, &flow->node, tc->ht_params);
- mlx5e_tc_del_flow(priv, flow->rule, flow->attr);
+ mlx5e_tc_del_flow(priv, flow);
+
kfree(flow);
@@ -594,7 +1077,7 @@ static void _mlx5e_tc_del_flow(void *ptr, void *arg)
struct mlx5e_tc_flow *flow = ptr;
struct mlx5e_priv *priv = arg;
- mlx5e_tc_del_flow(priv, flow->rule, flow->attr);
+ mlx5e_tc_del_flow(priv, flow);
kfree(flow);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index aaca09002ca6..8ffcc8808e50 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -139,6 +139,8 @@ static const char *eqe_type_str(u8 type)
return "MLX5_EVENT_TYPE_PORT_CHANGE";
case MLX5_EVENT_TYPE_GPIO_EVENT:
return "MLX5_EVENT_TYPE_GPIO_EVENT";
+ case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
+ return "MLX5_EVENT_TYPE_PORT_MODULE_EVENT";
case MLX5_EVENT_TYPE_REMOTE_CONFIG:
return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
case MLX5_EVENT_TYPE_DB_BF_CONGESTION:
@@ -285,6 +287,11 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
mlx5_eswitch_vport_event(dev->priv.eswitch, eqe);
break;
#endif
+
+ case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
+ mlx5_port_module_event(dev, eqe);
+ break;
+
default:
mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
eqe->type, eq->eqn);
@@ -469,7 +476,7 @@ void mlx5_eq_cleanup(struct mlx5_core_dev *dev)
int mlx5_start_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
- u32 async_event_mask = MLX5_ASYNC_EVENT_MASK;
+ u64 async_event_mask = MLX5_ASYNC_EVENT_MASK;
int err;
if (MLX5_CAP_GEN(dev, pg))
@@ -480,6 +487,11 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
mlx5_core_is_pf(dev))
async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE);
+ if (MLX5_CAP_GEN(dev, port_module_event))
+ async_event_mask |= (1ull << MLX5_EVENT_TYPE_PORT_MODULE_EVENT);
+ else
+ mlx5_core_dbg(dev, "port_module_event is not set\n");
+
err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
"mlx5_cmd_eq", &dev->priv.uuari.uars[0]);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index be1f7333ab7f..d6807c3cc461 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -56,7 +56,7 @@ struct esw_uc_addr {
/* E-Switch MC FDB table hash node */
struct esw_mc_addr { /* SRIOV only */
struct l2addr_node node;
- struct mlx5_flow_rule *uplink_rule; /* Forward to uplink rule */
+ struct mlx5_flow_handle *uplink_rule; /* Forward to uplink rule */
u32 refcnt;
};
@@ -65,7 +65,7 @@ struct vport_addr {
struct l2addr_node node;
u8 action;
u32 vport;
- struct mlx5_flow_rule *flow_rule; /* SRIOV only */
+ struct mlx5_flow_handle *flow_rule; /* SRIOV only */
/* A flag indicating that mac was added due to mc promiscuous vport */
bool mc_promisc;
};
@@ -237,13 +237,14 @@ static void del_l2_table_entry(struct mlx5_core_dev *dev, u32 index)
}
/* E-Switch FDB */
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
{
int match_header = (is_zero_ether_addr(mac_c) ? 0 :
MLX5_MATCH_OUTER_HEADERS);
- struct mlx5_flow_rule *flow_rule = NULL;
+ struct mlx5_flow_handle *flow_rule = NULL;
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_destination dest;
struct mlx5_flow_spec *spec;
void *mv_misc = NULL;
@@ -285,10 +286,10 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
"\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
dmac_v, dmac_c, vport);
spec->match_criteria_enable = match_header;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule =
- mlx5_add_flow_rule(esw->fdb_table.fdb, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- 0, &dest);
+ mlx5_add_flow_rules(esw->fdb_table.fdb, spec,
+ &flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
esw_warn(esw->dev,
"FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
@@ -300,7 +301,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
return flow_rule;
}
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
{
u8 mac_c[ETH_ALEN];
@@ -309,7 +310,7 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
}
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
{
u8 mac_c[ETH_ALEN];
@@ -322,7 +323,7 @@ esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
}
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport)
{
u8 mac_c[ETH_ALEN];
@@ -361,7 +362,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw, int nvports)
memset(flow_group_in, 0, inlen);
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
- fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
+ fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0, 0);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create FDB Table err %d\n", err);
@@ -515,7 +516,7 @@ static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
del_l2_table_entry(esw->dev, esw_uc->table_index);
if (vaddr->flow_rule)
- mlx5_del_flow_rule(vaddr->flow_rule);
+ mlx5_del_flow_rules(vaddr->flow_rule);
vaddr->flow_rule = NULL;
l2addr_hash_del(esw_uc);
@@ -562,7 +563,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw,
case MLX5_ACTION_DEL:
if (!iter_vaddr)
continue;
- mlx5_del_flow_rule(iter_vaddr->flow_rule);
+ mlx5_del_flow_rules(iter_vaddr->flow_rule);
l2addr_hash_del(iter_vaddr);
break;
}
@@ -632,7 +633,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
esw_mc->uplink_rule);
if (vaddr->flow_rule)
- mlx5_del_flow_rule(vaddr->flow_rule);
+ mlx5_del_flow_rules(vaddr->flow_rule);
vaddr->flow_rule = NULL;
/* If the multicast mac is added as a result of mc promiscuous vport,
@@ -645,7 +646,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
update_allmulti_vports(esw, vaddr, esw_mc);
if (esw_mc->uplink_rule)
- mlx5_del_flow_rule(esw_mc->uplink_rule);
+ mlx5_del_flow_rules(esw_mc->uplink_rule);
l2addr_hash_del(esw_mc);
return 0;
@@ -828,14 +829,14 @@ static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num,
UPLINK_VPORT);
allmulti_addr->refcnt++;
} else if (vport->allmulti_rule) {
- mlx5_del_flow_rule(vport->allmulti_rule);
+ mlx5_del_flow_rules(vport->allmulti_rule);
vport->allmulti_rule = NULL;
if (--allmulti_addr->refcnt > 0)
goto promisc;
if (allmulti_addr->uplink_rule)
- mlx5_del_flow_rule(allmulti_addr->uplink_rule);
+ mlx5_del_flow_rules(allmulti_addr->uplink_rule);
allmulti_addr->uplink_rule = NULL;
}
@@ -847,7 +848,7 @@ promisc:
vport->promisc_rule = esw_fdb_set_vport_promisc_rule(esw,
vport_num);
} else if (vport->promisc_rule) {
- mlx5_del_flow_rule(vport->promisc_rule);
+ mlx5_del_flow_rules(vport->promisc_rule);
vport->promisc_rule = NULL;
}
}
@@ -1018,10 +1019,10 @@ static void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan))
- mlx5_del_flow_rule(vport->egress.allowed_vlan);
+ mlx5_del_flow_rules(vport->egress.allowed_vlan);
if (!IS_ERR_OR_NULL(vport->egress.drop_rule))
- mlx5_del_flow_rule(vport->egress.drop_rule);
+ mlx5_del_flow_rules(vport->egress.drop_rule);
vport->egress.allowed_vlan = NULL;
vport->egress.drop_rule = NULL;
@@ -1179,10 +1180,10 @@ static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (!IS_ERR_OR_NULL(vport->ingress.drop_rule))
- mlx5_del_flow_rule(vport->ingress.drop_rule);
+ mlx5_del_flow_rules(vport->ingress.drop_rule);
if (!IS_ERR_OR_NULL(vport->ingress.allow_rule))
- mlx5_del_flow_rule(vport->ingress.allow_rule);
+ mlx5_del_flow_rules(vport->ingress.allow_rule);
vport->ingress.drop_rule = NULL;
vport->ingress.allow_rule = NULL;
@@ -1212,6 +1213,7 @@ static void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_spec *spec;
int err = 0;
u8 *smac_v;
@@ -1264,10 +1266,10 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
}
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
vport->ingress.allow_rule =
- mlx5_add_flow_rule(vport->ingress.acl, spec,
- MLX5_FLOW_CONTEXT_ACTION_ALLOW,
- 0, NULL);
+ mlx5_add_flow_rules(vport->ingress.acl, spec,
+ &flow_act, NULL, 0);
if (IS_ERR(vport->ingress.allow_rule)) {
err = PTR_ERR(vport->ingress.allow_rule);
esw_warn(esw->dev,
@@ -1278,10 +1280,10 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
}
memset(spec, 0, sizeof(*spec));
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
vport->ingress.drop_rule =
- mlx5_add_flow_rule(vport->ingress.acl, spec,
- MLX5_FLOW_CONTEXT_ACTION_DROP,
- 0, NULL);
+ mlx5_add_flow_rules(vport->ingress.acl, spec,
+ &flow_act, NULL, 0);
if (IS_ERR(vport->ingress.drop_rule)) {
err = PTR_ERR(vport->ingress.drop_rule);
esw_warn(esw->dev,
@@ -1301,6 +1303,7 @@ out:
static int esw_vport_egress_config(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_spec *spec;
int err = 0;
@@ -1338,10 +1341,10 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
vport->egress.allowed_vlan =
- mlx5_add_flow_rule(vport->egress.acl, spec,
- MLX5_FLOW_CONTEXT_ACTION_ALLOW,
- 0, NULL);
+ mlx5_add_flow_rules(vport->egress.acl, spec,
+ &flow_act, NULL, 0);
if (IS_ERR(vport->egress.allowed_vlan)) {
err = PTR_ERR(vport->egress.allowed_vlan);
esw_warn(esw->dev,
@@ -1353,10 +1356,10 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
/* Drop others rule (star rule) */
memset(spec, 0, sizeof(*spec));
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
vport->egress.drop_rule =
- mlx5_add_flow_rule(vport->egress.acl, spec,
- MLX5_FLOW_CONTEXT_ACTION_DROP,
- 0, NULL);
+ mlx5_add_flow_rules(vport->egress.acl, spec,
+ &flow_act, NULL, 0);
if (IS_ERR(vport->egress.drop_rule)) {
err = PTR_ERR(vport->egress.drop_rule);
esw_warn(esw->dev,
@@ -1369,6 +1372,147 @@ out:
return err;
}
+/* Vport QoS management */
+static int esw_create_tsar(struct mlx5_eswitch *esw)
+{
+ u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+ struct mlx5_core_dev *dev = esw->dev;
+ int err;
+
+ if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
+ return 0;
+
+ if (esw->qos.enabled)
+ return -EEXIST;
+
+ err = mlx5_create_scheduling_element_cmd(dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ &tsar_ctx,
+ &esw->qos.root_tsar_id);
+ if (err) {
+ esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
+ return err;
+ }
+
+ esw->qos.enabled = true;
+ return 0;
+}
+
+static void esw_destroy_tsar(struct mlx5_eswitch *esw)
+{
+ int err;
+
+ if (!esw->qos.enabled)
+ return;
+
+ err = mlx5_destroy_scheduling_element_cmd(esw->dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ esw->qos.root_tsar_id);
+ if (err)
+ esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
+
+ esw->qos.enabled = false;
+}
+
+static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
+ u32 initial_max_rate)
+{
+ u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+ struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_core_dev *dev = esw->dev;
+ void *vport_elem;
+ int err = 0;
+
+ if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
+ !MLX5_CAP_QOS(dev, esw_scheduling))
+ return 0;
+
+ if (vport->qos.enabled)
+ return -EEXIST;
+
+ MLX5_SET(scheduling_context, &sched_ctx, element_type,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
+ vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
+ element_attributes);
+ MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
+ MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
+ esw->qos.root_tsar_id);
+ MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
+ initial_max_rate);
+
+ err = mlx5_create_scheduling_element_cmd(dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ &sched_ctx,
+ &vport->qos.esw_tsar_ix);
+ if (err) {
+ esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
+ vport_num, err);
+ return err;
+ }
+
+ vport->qos.enabled = true;
+ return 0;
+}
+
+static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
+{
+ struct mlx5_vport *vport = &esw->vports[vport_num];
+ int err = 0;
+
+ if (!vport->qos.enabled)
+ return;
+
+ err = mlx5_destroy_scheduling_element_cmd(esw->dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ vport->qos.esw_tsar_ix);
+ if (err)
+ esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
+ vport_num, err);
+
+ vport->qos.enabled = false;
+}
+
+static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
+ u32 max_rate)
+{
+ u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+ struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_core_dev *dev = esw->dev;
+ void *vport_elem;
+ u32 bitmask = 0;
+ int err = 0;
+
+ if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
+ return -EOPNOTSUPP;
+
+ if (!vport->qos.enabled)
+ return -EIO;
+
+ MLX5_SET(scheduling_context, &sched_ctx, element_type,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
+ vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
+ element_attributes);
+ MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
+ MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
+ esw->qos.root_tsar_id);
+ MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
+ max_rate);
+ bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
+
+ err = mlx5_modify_scheduling_element_cmd(dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ &sched_ctx,
+ vport->qos.esw_tsar_ix,
+ bitmask);
+ if (err) {
+ esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
+ vport_num, err);
+ return err;
+ }
+
+ return 0;
+}
+
static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
{
((u8 *)node_guid)[7] = mac[0];
@@ -1404,6 +1548,7 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
esw_vport_egress_config(esw, vport);
}
}
+
static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
int enable_events)
{
@@ -1417,6 +1562,10 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
/* Restore old vport configuration */
esw_apply_vport_conf(esw, vport);
+ /* Attach vport to the eswitch rate limiter */
+ if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate))
+ esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);
+
/* Sync with current vport context */
vport->enabled_events = enable_events;
vport->enabled = true;
@@ -1455,7 +1604,7 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num)
*/
esw_vport_change_handle_locked(vport);
vport->enabled_events = 0;
-
+ esw_vport_disable_qos(esw, vport_num);
if (vport_num && esw->mode == SRIOV_LEGACY) {
mlx5_modify_vport_admin_state(esw->dev,
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
@@ -1501,6 +1650,10 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
if (err)
goto abort;
+ err = esw_create_tsar(esw);
+ if (err)
+ esw_warn(esw->dev, "Failed to create eswitch TSAR");
+
enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : UC_ADDR_CHANGE;
for (i = 0; i <= nvfs; i++)
esw_enable_vport(esw, i, enabled_events);
@@ -1535,7 +1688,9 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
esw_disable_vport(esw, i);
if (mc_promisc && mc_promisc->uplink_rule)
- mlx5_del_flow_rule(mc_promisc->uplink_rule);
+ mlx5_del_flow_rules(mc_promisc->uplink_rule);
+
+ esw_destroy_tsar(esw);
if (esw->mode == SRIOV_LEGACY)
esw_destroy_legacy_fdb_table(esw);
@@ -1627,6 +1782,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
goto abort;
}
+ hash_init(esw->offloads.encap_tbl);
mutex_init(&esw->state_lock);
for (vport_num = 0; vport_num < total_vports; vport_num++) {
@@ -1642,6 +1798,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
esw->total_vports = total_vports;
esw->enabled_vports = 0;
esw->mode = SRIOV_NONE;
+ esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
dev->priv.eswitch = esw;
return 0;
@@ -1795,6 +1952,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
ivi->qos = evport->info.qos;
ivi->spoofchk = evport->info.spoofchk;
ivi->trusted = evport->info.trusted;
+ ivi->max_tx_rate = evport->info.max_rate;
mutex_unlock(&esw->state_lock);
return 0;
@@ -1888,6 +2046,27 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
return 0;
}
+int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw,
+ int vport, u32 max_rate)
+{
+ struct mlx5_vport *evport;
+ int err = 0;
+
+ if (!ESW_ALLOWED(esw))
+ return -EPERM;
+ if (!LEGAL_VPORT(esw, vport))
+ return -EINVAL;
+
+ mutex_lock(&esw->state_lock);
+ evport = &esw->vports[vport];
+ err = esw_vport_qos_config(esw, vport, max_rate);
+ if (!err)
+ evport->info.max_rate = max_rate;
+
+ mutex_unlock(&esw->state_lock);
+ return err;
+}
+
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
int vport,
struct ifla_vf_stats *vf_stats)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index 2e2938e08cda..8661dd3f542c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -97,16 +97,16 @@ struct vport_ingress {
struct mlx5_flow_group *allow_spoofchk_only_grp;
struct mlx5_flow_group *allow_untagged_only_grp;
struct mlx5_flow_group *drop_grp;
- struct mlx5_flow_rule *allow_rule;
- struct mlx5_flow_rule *drop_rule;
+ struct mlx5_flow_handle *allow_rule;
+ struct mlx5_flow_handle *drop_rule;
};
struct vport_egress {
struct mlx5_flow_table *acl;
struct mlx5_flow_group *allowed_vlans_grp;
struct mlx5_flow_group *drop_grp;
- struct mlx5_flow_rule *allowed_vlan;
- struct mlx5_flow_rule *drop_rule;
+ struct mlx5_flow_handle *allowed_vlan;
+ struct mlx5_flow_handle *drop_rule;
};
struct mlx5_vport_info {
@@ -115,6 +115,7 @@ struct mlx5_vport_info {
u8 qos;
u64 node_guid;
int link_state;
+ u32 max_rate;
bool spoofchk;
bool trusted;
};
@@ -124,8 +125,8 @@ struct mlx5_vport {
int vport;
struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE];
struct hlist_head mc_list[MLX5_L2_ADDR_HASH_SIZE];
- struct mlx5_flow_rule *promisc_rule;
- struct mlx5_flow_rule *allmulti_rule;
+ struct mlx5_flow_handle *promisc_rule;
+ struct mlx5_flow_handle *allmulti_rule;
struct work_struct vport_change_handler;
struct vport_ingress ingress;
@@ -133,6 +134,11 @@ struct mlx5_vport {
struct mlx5_vport_info info;
+ struct {
+ bool enabled;
+ u32 esw_tsar_ix;
+ } qos;
+
bool enabled;
u16 enabled_events;
};
@@ -156,7 +162,7 @@ struct mlx5_eswitch_fdb {
struct mlx5_flow_table *fdb;
struct mlx5_flow_group *send_to_vport_grp;
struct mlx5_flow_group *miss_grp;
- struct mlx5_flow_rule *miss_rule;
+ struct mlx5_flow_handle *miss_rule;
int vlan_push_pop_refcount;
} offloads;
};
@@ -169,7 +175,7 @@ enum {
};
struct mlx5_esw_sq {
- struct mlx5_flow_rule *send_to_vport_rule;
+ struct mlx5_flow_handle *send_to_vport_rule;
struct list_head list;
};
@@ -180,9 +186,9 @@ struct mlx5_eswitch_rep {
struct mlx5_eswitch_rep *rep);
u16 vport;
u8 hw_id[ETH_ALEN];
- void *priv_data;
+ struct net_device *netdev;
- struct mlx5_flow_rule *vport_rx_rule;
+ struct mlx5_flow_handle *vport_rx_rule;
struct list_head vport_sqs_list;
u16 vlan;
u32 vlan_refcount;
@@ -193,6 +199,8 @@ struct mlx5_esw_offload {
struct mlx5_flow_table *ft_offloads;
struct mlx5_flow_group *vport_rx_group;
struct mlx5_eswitch_rep *vport_reps;
+ DECLARE_HASHTABLE(encap_tbl, 8);
+ u8 inline_mode;
};
struct mlx5_eswitch {
@@ -209,6 +217,12 @@ struct mlx5_eswitch {
*/
struct mutex state_lock;
struct esw_mc_addr *mc_promisc;
+
+ struct {
+ bool enabled;
+ u32 root_tsar_id;
+ } qos;
+
struct mlx5_esw_offload offloads;
int mode;
};
@@ -234,6 +248,8 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
int vport, bool spoofchk);
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
int vport_num, bool setting);
+int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw,
+ int vport, u32 max_rate);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
int vport, struct ifla_vf_info *ivi);
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
@@ -243,11 +259,11 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
struct mlx5_flow_spec;
struct mlx5_esw_flow_attr;
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
struct mlx5_flow_spec *spec,
struct mlx5_esw_flow_attr *attr);
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn);
enum {
@@ -258,6 +274,24 @@ enum {
#define MLX5_FLOW_CONTEXT_ACTION_VLAN_POP 0x40
#define MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH 0x80
+struct mlx5_encap_info {
+ __be32 daddr;
+ __be32 tun_id;
+ __be16 tp_dst;
+};
+
+struct mlx5_encap_entry {
+ struct hlist_node encap_hlist;
+ struct list_head flows;
+ u32 encap_id;
+ struct neighbour *n;
+ struct mlx5_encap_info tun_info;
+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
+
+ struct net_device *out_dev;
+ int tunnel_type;
+};
+
struct mlx5_esw_flow_attr {
struct mlx5_eswitch_rep *in_rep;
struct mlx5_eswitch_rep *out_rep;
@@ -265,6 +299,7 @@ struct mlx5_esw_flow_attr {
int action;
u16 vlan;
bool vlan_handled;
+ struct mlx5_encap_entry *encap;
};
int mlx5_eswitch_sqs2vport_start(struct mlx5_eswitch *esw,
@@ -275,11 +310,15 @@ void mlx5_eswitch_sqs2vport_stop(struct mlx5_eswitch *esw,
int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode);
int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode);
+int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode);
+int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode);
+int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode);
void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
int vport_index,
struct mlx5_eswitch_rep *rep);
void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,
int vport_index);
+struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw);
int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
struct mlx5_esw_flow_attr *attr);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index d239f5d0ea36..466e161010f7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -43,33 +43,36 @@ enum {
FDB_SLOW_PATH
};
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
struct mlx5_flow_spec *spec,
struct mlx5_esw_flow_attr *attr)
{
- struct mlx5_flow_destination dest = { 0 };
+ struct mlx5_flow_destination dest[2] = {};
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_fc *counter = NULL;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
void *misc;
- int action;
+ int i = 0;
if (esw->mode != SRIOV_OFFLOADS)
return ERR_PTR(-EOPNOTSUPP);
/* per flow vlan pop/push is emulated, don't set that into the firmware */
- action = attr->action & ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH | MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
+ flow_act.action = attr->action & ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH | MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
- if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
- dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
- dest.vport_num = attr->out_rep->vport;
- action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- } else if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+ if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
+ dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
+ dest[i].vport_num = attr->out_rep->vport;
+ i++;
+ }
+ if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
counter = mlx5_fc_create(esw->dev, true);
if (IS_ERR(counter))
return ERR_CAST(counter);
- dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter = counter;
+ dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+ dest[i].counter = counter;
+ i++;
}
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
@@ -80,10 +83,14 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
MLX5_MATCH_MISC_PARAMETERS;
+ if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+ spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
- rule = mlx5_add_flow_rule((struct mlx5_flow_table *)esw->fdb_table.fdb,
- spec, action, 0, &dest);
+ if (attr->encap)
+ flow_act.encap_id = attr->encap->encap_id;
+ rule = mlx5_add_flow_rules((struct mlx5_flow_table *)esw->fdb_table.fdb,
+ spec, &flow_act, dest, i);
if (IS_ERR(rule))
mlx5_fc_destroy(esw->dev, counter);
@@ -270,11 +277,12 @@ out:
return err;
}
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn)
{
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_destination dest;
- struct mlx5_flow_rule *flow_rule;
+ struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
void *misc;
@@ -296,10 +304,10 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport_num = vport;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- 0, &dest);
+ flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+ &flow_act, &dest, 1);
if (IS_ERR(flow_rule))
esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule));
out:
@@ -316,7 +324,7 @@ void mlx5_eswitch_sqs2vport_stop(struct mlx5_eswitch *esw,
return;
list_for_each_entry_safe(esw_sq, tmp, &rep->vport_sqs_list, list) {
- mlx5_del_flow_rule(esw_sq->send_to_vport_rule);
+ mlx5_del_flow_rules(esw_sq->send_to_vport_rule);
list_del(&esw_sq->list);
kfree(esw_sq);
}
@@ -326,7 +334,7 @@ int mlx5_eswitch_sqs2vport_start(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
u16 *sqns_array, int sqns_num)
{
- struct mlx5_flow_rule *flow_rule;
+ struct mlx5_flow_handle *flow_rule;
struct mlx5_esw_sq *esw_sq;
int err;
int i;
@@ -362,8 +370,9 @@ out_err:
static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
{
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_destination dest;
- struct mlx5_flow_rule *flow_rule = NULL;
+ struct mlx5_flow_handle *flow_rule = NULL;
struct mlx5_flow_spec *spec;
int err = 0;
@@ -376,10 +385,10 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport_num = 0;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- 0, &dest);
+ flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+ &flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
esw_warn(esw->dev, "FDB: Failed to add miss flow rule err %d\n", err);
@@ -406,6 +415,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
u32 *flow_group_in;
void *match_criteria;
int table_size, ix, err = 0;
+ u32 flags = 0;
flow_group_in = mlx5_vzalloc(inlen);
if (!flow_group_in)
@@ -420,9 +430,14 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
esw_debug(dev, "Create offloads FDB table, log_max_size(%d)\n",
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
+ if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) &&
+ MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
+ flags |= MLX5_FLOW_TABLE_TUNNEL_EN;
+
fdb = mlx5_create_auto_grouped_flow_table(root_ns, FDB_FAST_PATH,
ESW_OFFLOADS_NUM_ENTRIES,
- ESW_OFFLOADS_NUM_GROUPS, 0);
+ ESW_OFFLOADS_NUM_GROUPS, 0,
+ flags);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create Fast path FDB Table err %d\n", err);
@@ -431,7 +446,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
esw->fdb_table.fdb = fdb;
table_size = nvports + MAX_PF_SQ + 1;
- fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0);
+ fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0, 0);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
@@ -502,7 +517,7 @@ static void esw_destroy_offloads_fdb_table(struct mlx5_eswitch *esw)
return;
esw_debug(esw->dev, "Destroy offloads FDB Table\n");
- mlx5_del_flow_rule(esw->fdb_table.offloads.miss_rule);
+ mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule);
mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
@@ -523,7 +538,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
return -ENOMEM;
}
- ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0);
+ ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0, 0);
if (IS_ERR(ft_offloads)) {
err = PTR_ERR(ft_offloads);
esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
@@ -586,11 +601,12 @@ static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
}
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
{
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_destination dest;
- struct mlx5_flow_rule *flow_rule;
+ struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
void *misc;
@@ -611,9 +627,9 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dest.tir_num = tirn;
- flow_rule = mlx5_add_flow_rule(esw->offloads.ft_offloads, spec,
- MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
- 0, &dest);
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
+ &flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
goto out;
@@ -641,6 +657,14 @@ static int esw_offloads_start(struct mlx5_eswitch *esw)
if (err1)
esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err);
}
+ if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
+ if (mlx5_eswitch_inline_mode_get(esw,
+ num_vfs,
+ &esw->offloads.inline_mode)) {
+ esw->offloads.inline_mode = MLX5_INLINE_MODE_L2;
+ esw_warn(esw->dev, "Inline mode is different between vports\n");
+ }
+ }
return err;
}
@@ -755,6 +779,50 @@ static int esw_mode_to_devlink(u16 mlx5_mode, u16 *mode)
return 0;
}
+static int esw_inline_mode_from_devlink(u8 mode, u8 *mlx5_mode)
+{
+ switch (mode) {
+ case DEVLINK_ESWITCH_INLINE_MODE_NONE:
+ *mlx5_mode = MLX5_INLINE_MODE_NONE;
+ break;
+ case DEVLINK_ESWITCH_INLINE_MODE_LINK:
+ *mlx5_mode = MLX5_INLINE_MODE_L2;
+ break;
+ case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
+ *mlx5_mode = MLX5_INLINE_MODE_IP;
+ break;
+ case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
+ *mlx5_mode = MLX5_INLINE_MODE_TCP_UDP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
+{
+ switch (mlx5_mode) {
+ case MLX5_INLINE_MODE_NONE:
+ *mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
+ break;
+ case MLX5_INLINE_MODE_L2:
+ *mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
+ break;
+ case MLX5_INLINE_MODE_IP:
+ *mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
+ break;
+ case MLX5_INLINE_MODE_TCP_UDP:
+ *mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
{
struct mlx5_core_dev *dev;
@@ -799,6 +867,95 @@ int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);
}
+int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+ struct mlx5_eswitch *esw = dev->priv.eswitch;
+ int num_vports = esw->enabled_vports;
+ int err;
+ int vport;
+ u8 mlx5_mode;
+
+ if (!MLX5_CAP_GEN(dev, vport_group_manager))
+ return -EOPNOTSUPP;
+
+ if (esw->mode == SRIOV_NONE)
+ return -EOPNOTSUPP;
+
+ if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+ MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+ return -EOPNOTSUPP;
+
+ err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
+ if (err)
+ goto out;
+
+ for (vport = 1; vport < num_vports; vport++) {
+ err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);
+ if (err) {
+ esw_warn(dev, "Failed to set min inline on vport %d\n",
+ vport);
+ goto revert_inline_mode;
+ }
+ }
+
+ esw->offloads.inline_mode = mlx5_mode;
+ return 0;
+
+revert_inline_mode:
+ while (--vport > 0)
+ mlx5_modify_nic_vport_min_inline(dev,
+ vport,
+ esw->offloads.inline_mode);
+out:
+ return err;
+}
+
+int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+ struct mlx5_eswitch *esw = dev->priv.eswitch;
+
+ if (!MLX5_CAP_GEN(dev, vport_group_manager))
+ return -EOPNOTSUPP;
+
+ if (esw->mode == SRIOV_NONE)
+ return -EOPNOTSUPP;
+
+ if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+ MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+ return -EOPNOTSUPP;
+
+ return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
+}
+
+int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode)
+{
+ struct mlx5_core_dev *dev = esw->dev;
+ int vport;
+ u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
+
+ if (!MLX5_CAP_GEN(dev, vport_group_manager))
+ return -EOPNOTSUPP;
+
+ if (esw->mode == SRIOV_NONE)
+ return -EOPNOTSUPP;
+
+ if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+ MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+ return -EOPNOTSUPP;
+
+ for (vport = 1; vport <= nvfs; vport++) {
+ mlx5_query_nic_vport_min_inline(dev, vport, &mlx5_mode);
+ if (vport > 1 && prev_mlx5_mode != mlx5_mode)
+ return -EINVAL;
+ prev_mlx5_mode = mlx5_mode;
+ }
+
+ *mode = mlx5_mode;
+ return 0;
+}
+
void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
int vport_index,
struct mlx5_eswitch_rep *__rep)
@@ -813,7 +970,7 @@ void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
rep->load = __rep->load;
rep->unload = __rep->unload;
rep->vport = __rep->vport;
- rep->priv_data = __rep->priv_data;
+ rep->netdev = __rep->netdev;
ether_addr_copy(rep->hw_id, __rep->hw_id);
INIT_LIST_HEAD(&rep->vport_sqs_list);
@@ -833,3 +990,13 @@ void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,
rep->valid = false;
}
+
+struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw)
+{
+#define UPLINK_REP_INDEX 0
+ struct mlx5_esw_offload *offloads = &esw->offloads;
+ struct mlx5_eswitch_rep *rep;
+
+ rep = &offloads->vport_reps[UPLINK_REP_INDEX];
+ return rep->netdev;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index 113c32326333..c4478ecd8056 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -37,6 +37,7 @@
#include "fs_core.h"
#include "fs_cmd.h"
#include "mlx5_core.h"
+#include "eswitch.h"
int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft)
@@ -61,8 +62,9 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
enum fs_flow_table_op_mod op_mod,
enum fs_flow_table_type type, unsigned int level,
unsigned int log_size, struct mlx5_flow_table
- *next_ft, unsigned int *table_id)
+ *next_ft, unsigned int *table_id, u32 flags)
{
+ int en_encap_decap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN);
u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
int err;
@@ -78,6 +80,9 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
MLX5_SET(create_flow_table_in, in, other_vport, 1);
}
+ MLX5_SET(create_flow_table_in, in, decap_en, en_encap_decap);
+ MLX5_SET(create_flow_table_in, in, encap_en, en_encap_decap);
+
switch (op_mod) {
case FS_FT_OP_MOD_NORMAL:
if (next_ft) {
@@ -243,6 +248,7 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
MLX5_SET(flow_context, in_flow_context, group_id, group_id);
MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag);
MLX5_SET(flow_context, in_flow_context, action, fte->action);
+ MLX5_SET(flow_context, in_flow_context, encap_id, fte->encap_id);
in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
match_value);
memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param));
@@ -453,27 +459,32 @@ void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev,
*bytes = MLX5_GET64(traffic_counter, stats, octets);
}
-#define MAX_ENCAP_SIZE (128)
-
-int mlx5_cmd_alloc_encap(struct mlx5_core_dev *dev,
- int header_type,
- size_t size,
- void *encap_header,
- u32 *encap_id)
+int mlx5_encap_alloc(struct mlx5_core_dev *dev,
+ int header_type,
+ size_t size,
+ void *encap_header,
+ u32 *encap_id)
{
+ int max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size);
u32 out[MLX5_ST_SZ_DW(alloc_encap_header_out)];
- u32 in[MLX5_ST_SZ_DW(alloc_encap_header_in) +
- (MAX_ENCAP_SIZE / sizeof(u32))];
- void *encap_header_in = MLX5_ADDR_OF(alloc_encap_header_in, in,
- encap_header);
- void *header = MLX5_ADDR_OF(encap_header_in, encap_header_in,
- encap_header);
- int inlen = header - (void *)in + size;
+ void *encap_header_in;
+ void *header;
+ int inlen;
int err;
+ u32 *in;
- if (size > MAX_ENCAP_SIZE)
+ if (size > MLX5_CAP_ESW(dev, max_encap_header_size))
return -EINVAL;
+ in = kzalloc(MLX5_ST_SZ_BYTES(alloc_encap_header_in) + max_encap_size,
+ GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
+
+ encap_header_in = MLX5_ADDR_OF(alloc_encap_header_in, in, encap_header);
+ header = MLX5_ADDR_OF(encap_header_in, encap_header_in, encap_header);
+ inlen = header - (void *)in + size;
+
memset(in, 0, inlen);
MLX5_SET(alloc_encap_header_in, in, opcode,
MLX5_CMD_OP_ALLOC_ENCAP_HEADER);
@@ -485,10 +496,11 @@ int mlx5_cmd_alloc_encap(struct mlx5_core_dev *dev,
err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
*encap_id = MLX5_GET(alloc_encap_header_out, out, encap_id);
+ kfree(in);
return err;
}
-void mlx5_cmd_dealloc_encap(struct mlx5_core_dev *dev, u32 encap_id)
+void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id)
{
u32 in[MLX5_ST_SZ_DW(dealloc_encap_header_in)];
u32 out[MLX5_ST_SZ_DW(dealloc_encap_header_out)];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
index c5bc4686c832..8fad80688536 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
@@ -38,7 +38,7 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
enum fs_flow_table_op_mod op_mod,
enum fs_flow_table_type type, unsigned int level,
unsigned int log_size, struct mlx5_flow_table
- *next_ft, unsigned int *table_id);
+ *next_ft, unsigned int *table_id, u32 flags);
int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft);
@@ -89,11 +89,4 @@ void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev,
struct mlx5_cmd_fc_bulk *b, u16 id,
u64 *packets, u64 *bytes);
-int mlx5_cmd_alloc_encap(struct mlx5_core_dev *dev,
- int header_type,
- size_t size,
- void *encap_header,
- u32 *encap_id);
-void mlx5_cmd_dealloc_encap(struct mlx5_core_dev *dev, u32 encap_id);
-
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 914e5466f729..a263d8904a4c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -153,6 +153,11 @@ static void del_rule(struct fs_node *node);
static void del_flow_table(struct fs_node *node);
static void del_flow_group(struct fs_node *node);
static void del_fte(struct fs_node *node);
+static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ struct mlx5_flow_destination *d2);
+static struct mlx5_flow_rule *
+find_flow_rule(struct fs_fte *fte,
+ struct mlx5_flow_destination *dest);
static void tree_init_node(struct fs_node *node,
unsigned int refcount,
@@ -369,6 +374,7 @@ static void del_rule(struct fs_node *node)
struct mlx5_core_dev *dev = get_dev(node);
int match_len = MLX5_ST_SZ_BYTES(fte_match_param);
int err;
+ bool update_fte = false;
match_value = mlx5_vzalloc(match_len);
if (!match_value) {
@@ -387,13 +393,23 @@ static void del_rule(struct fs_node *node)
list_del(&rule->next_ft);
mutex_unlock(&rule->dest_attr.ft->lock);
}
+
+ if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER &&
+ --fte->dests_size) {
+ modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
+ fte->action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ update_fte = true;
+ goto out;
+ }
+
if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
--fte->dests_size) {
modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST),
- err = mlx5_cmd_update_fte(dev, ft,
- fg->id,
- modify_mask,
- fte);
+ update_fte = true;
+ }
+out:
+ if (update_fte && fte->dests_size) {
+ err = mlx5_cmd_update_fte(dev, ft, fg->id, modify_mask, fte);
if (err)
mlx5_core_warn(dev,
"%s can't del rule fg id=%d fte_index=%d\n",
@@ -444,8 +460,7 @@ static void del_flow_group(struct fs_node *node)
fg->id, ft->id);
}
-static struct fs_fte *alloc_fte(u8 action,
- u32 flow_tag,
+static struct fs_fte *alloc_fte(struct mlx5_flow_act *flow_act,
u32 *match_value,
unsigned int index)
{
@@ -457,9 +472,10 @@ static struct fs_fte *alloc_fte(u8 action,
memcpy(fte->val, match_value, sizeof(fte->val));
fte->node.type = FS_TYPE_FLOW_ENTRY;
- fte->flow_tag = flow_tag;
+ fte->flow_tag = flow_act->flow_tag;
fte->index = index;
- fte->action = action;
+ fte->action = flow_act->action;
+ fte->encap_id = flow_act->encap_id;
return fte;
}
@@ -489,7 +505,8 @@ static struct mlx5_flow_group *alloc_flow_group(u32 *create_fg_in)
static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte,
enum fs_flow_table_type table_type,
- enum fs_flow_table_op_mod op_mod)
+ enum fs_flow_table_op_mod op_mod,
+ u32 flags)
{
struct mlx5_flow_table *ft;
@@ -503,6 +520,7 @@ static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_ft
ft->type = table_type;
ft->vport = vport;
ft->max_fte = max_fte;
+ ft->flags = flags;
INIT_LIST_HEAD(&ft->fwd_rules);
mutex_init(&ft->lock);
@@ -641,8 +659,8 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
return err;
}
-int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
- struct mlx5_flow_destination *dest)
+static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
+ struct mlx5_flow_destination *dest)
{
struct mlx5_flow_table *ft;
struct mlx5_flow_group *fg;
@@ -667,6 +685,28 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
return err;
}
+int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle,
+ struct mlx5_flow_destination *new_dest,
+ struct mlx5_flow_destination *old_dest)
+{
+ int i;
+
+ if (!old_dest) {
+ if (handle->num_rules != 1)
+ return -EINVAL;
+ return _mlx5_modify_rule_destination(handle->rule[0],
+ new_dest);
+ }
+
+ for (i = 0; i < handle->num_rules; i++) {
+ if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr))
+ return _mlx5_modify_rule_destination(handle->rule[i],
+ new_dest);
+ }
+
+ return -EINVAL;
+}
+
/* Modify/set FWD rules that point on old_next_ft to point on new_next_ft */
static int connect_fwd_rules(struct mlx5_core_dev *dev,
struct mlx5_flow_table *new_next_ft,
@@ -689,7 +729,7 @@ static int connect_fwd_rules(struct mlx5_core_dev *dev,
list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules);
mutex_unlock(&old_next_ft->lock);
list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) {
- err = mlx5_modify_rule_destination(iter, &dest);
+ err = _mlx5_modify_rule_destination(iter, &dest);
if (err)
pr_err("mlx5_core: failed to modify rule to point on flow table %d\n",
new_next_ft->id);
@@ -739,7 +779,8 @@ static void list_add_flow_table(struct mlx5_flow_table *ft,
static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
enum fs_flow_table_op_mod op_mod,
u16 vport, int prio,
- int max_fte, u32 level)
+ int max_fte, u32 level,
+ u32 flags)
{
struct mlx5_flow_table *next_ft = NULL;
struct mlx5_flow_table *ft;
@@ -772,7 +813,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
vport,
max_fte ? roundup_pow_of_two(max_fte) : 0,
root->table_type,
- op_mod);
+ op_mod, flags);
if (!ft) {
err = -ENOMEM;
goto unlock_root;
@@ -782,7 +823,8 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
next_ft = find_next_chained_ft(fs_prio);
err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->op_mod, ft->type,
- ft->level, log_table_sz, next_ft, &ft->id);
+ ft->level, log_table_sz, next_ft, &ft->id,
+ ft->flags);
if (err)
goto free_ft;
@@ -807,10 +849,11 @@ unlock_root:
struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
int prio, int max_fte,
- u32 level)
+ u32 level,
+ u32 flags)
{
return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, 0, prio,
- max_fte, level);
+ max_fte, level, flags);
}
struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
@@ -818,7 +861,7 @@ struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace
u32 level, u16 vport)
{
return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, vport, prio,
- max_fte, level);
+ max_fte, level, 0);
}
struct mlx5_flow_table *mlx5_create_lag_demux_flow_table(
@@ -826,7 +869,7 @@ struct mlx5_flow_table *mlx5_create_lag_demux_flow_table(
int prio, u32 level)
{
return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_LAG_DEMUX, 0, prio, 0,
- level);
+ level, 0);
}
EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table);
@@ -834,14 +877,15 @@ struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_nam
int prio,
int num_flow_table_entries,
int max_num_groups,
- u32 level)
+ u32 level,
+ u32 flags)
{
struct mlx5_flow_table *ft;
if (max_num_groups > num_flow_table_entries)
return ERR_PTR(-EINVAL);
- ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries, level);
+ ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries, level, flags);
if (IS_ERR(ft))
return ft;
@@ -918,55 +962,133 @@ static struct mlx5_flow_rule *alloc_rule(struct mlx5_flow_destination *dest)
return rule;
}
-/* fte should not be deleted while calling this function */
-static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
- struct mlx5_flow_group *fg,
- struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *alloc_handle(int num_rules)
+{
+ struct mlx5_flow_handle *handle;
+
+ handle = kzalloc(sizeof(*handle) + sizeof(handle->rule[0]) *
+ num_rules, GFP_KERNEL);
+ if (!handle)
+ return NULL;
+
+ handle->num_rules = num_rules;
+
+ return handle;
+}
+
+static void destroy_flow_handle(struct fs_fte *fte,
+ struct mlx5_flow_handle *handle,
+ struct mlx5_flow_destination *dest,
+ int i)
+{
+ for (; --i >= 0;) {
+ if (atomic_dec_and_test(&handle->rule[i]->node.refcount)) {
+ fte->dests_size--;
+ list_del(&handle->rule[i]->node.list);
+ kfree(handle->rule[i]);
+ }
+ }
+ kfree(handle);
+}
+
+static struct mlx5_flow_handle *
+create_flow_handle(struct fs_fte *fte,
+ struct mlx5_flow_destination *dest,
+ int dest_num,
+ int *modify_mask,
+ bool *new_rule)
{
+ struct mlx5_flow_handle *handle;
+ struct mlx5_flow_rule *rule = NULL;
+ static int count = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
+ static int dst = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
+ int type;
+ int i = 0;
+
+ handle = alloc_handle((dest_num) ? dest_num : 1);
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+
+ do {
+ if (dest) {
+ rule = find_flow_rule(fte, dest + i);
+ if (rule) {
+ atomic_inc(&rule->node.refcount);
+ goto rule_found;
+ }
+ }
+
+ *new_rule = true;
+ rule = alloc_rule(dest + i);
+ if (!rule)
+ goto free_rules;
+
+ /* Add dest to dests list- we need flow tables to be in the
+ * end of the list for forward to next prio rules.
+ */
+ tree_init_node(&rule->node, 1, del_rule);
+ if (dest &&
+ dest[i].type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
+ list_add(&rule->node.list, &fte->node.children);
+ else
+ list_add_tail(&rule->node.list, &fte->node.children);
+ if (dest) {
+ fte->dests_size++;
+
+ type = dest[i].type ==
+ MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+ *modify_mask |= type ? count : dst;
+ }
+rule_found:
+ handle->rule[i] = rule;
+ } while (++i < dest_num);
+
+ return handle;
+
+free_rules:
+ destroy_flow_handle(fte, handle, dest, i);
+ return ERR_PTR(-ENOMEM);
+}
+
+/* fte should not be deleted while calling this function */
+static struct mlx5_flow_handle *
+add_rule_fte(struct fs_fte *fte,
+ struct mlx5_flow_group *fg,
+ struct mlx5_flow_destination *dest,
+ int dest_num,
+ bool update_action)
+{
+ struct mlx5_flow_handle *handle;
struct mlx5_flow_table *ft;
- struct mlx5_flow_rule *rule;
int modify_mask = 0;
int err;
+ bool new_rule = false;
- rule = alloc_rule(dest);
- if (!rule)
- return ERR_PTR(-ENOMEM);
+ handle = create_flow_handle(fte, dest, dest_num, &modify_mask,
+ &new_rule);
+ if (IS_ERR(handle) || !new_rule)
+ goto out;
- fs_get_obj(ft, fg->node.parent);
- /* Add dest to dests list- we need flow tables to be in the
- * end of the list for forward to next prio rules.
- */
- tree_init_node(&rule->node, 1, del_rule);
- if (dest && dest->type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
- list_add(&rule->node.list, &fte->node.children);
- else
- list_add_tail(&rule->node.list, &fte->node.children);
- if (dest) {
- fte->dests_size++;
+ if (update_action)
+ modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
- modify_mask |= dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ?
- BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS) :
- BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
- }
-
- if (fte->dests_size == 1 || !dest)
+ fs_get_obj(ft, fg->node.parent);
+ if (!(fte->status & FS_FTE_STATUS_EXISTING))
err = mlx5_cmd_create_fte(get_dev(&ft->node),
ft, fg->id, fte);
else
err = mlx5_cmd_update_fte(get_dev(&ft->node),
ft, fg->id, modify_mask, fte);
if (err)
- goto free_rule;
+ goto free_handle;
fte->status |= FS_FTE_STATUS_EXISTING;
- return rule;
+out:
+ return handle;
-free_rule:
- list_del(&rule->node.list);
- kfree(rule);
- if (dest)
- fte->dests_size--;
+free_handle:
+ destroy_flow_handle(fte, handle, dest, handle->num_rules);
return ERR_PTR(err);
}
@@ -995,15 +1117,14 @@ static unsigned int get_free_fte_index(struct mlx5_flow_group *fg,
/* prev is output, prev->next = new_fte */
static struct fs_fte *create_fte(struct mlx5_flow_group *fg,
u32 *match_value,
- u8 action,
- u32 flow_tag,
+ struct mlx5_flow_act *flow_act,
struct list_head **prev)
{
struct fs_fte *fte;
int index;
index = get_free_fte_index(fg, prev);
- fte = alloc_fte(action, flow_tag, match_value, index);
+ fte = alloc_fte(flow_act, match_value, index);
if (IS_ERR(fte))
return fte;
@@ -1067,71 +1188,81 @@ out:
return fg;
}
+static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ struct mlx5_flow_destination *d2)
+{
+ if (d1->type == d2->type) {
+ if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
+ d1->vport_num == d2->vport_num) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
+ d1->ft == d2->ft) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
+ d1->tir_num == d2->tir_num))
+ return true;
+ }
+
+ return false;
+}
+
static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte,
struct mlx5_flow_destination *dest)
{
struct mlx5_flow_rule *rule;
list_for_each_entry(rule, &fte->node.children, node.list) {
- if (rule->dest_attr.type == dest->type) {
- if ((dest->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
- dest->vport_num == rule->dest_attr.vport_num) ||
- (dest->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
- dest->ft == rule->dest_attr.ft) ||
- (dest->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
- dest->tir_num == rule->dest_attr.tir_num))
- return rule;
- }
+ if (mlx5_flow_dests_cmp(&rule->dest_attr, dest))
+ return rule;
}
return NULL;
}
-static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg,
- u32 *match_value,
- u8 action,
- u32 flow_tag,
- struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
+ u32 *match_value,
+ struct mlx5_flow_act *flow_act,
+ struct mlx5_flow_destination *dest,
+ int dest_num)
{
- struct fs_fte *fte;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *handle;
struct mlx5_flow_table *ft;
struct list_head *prev;
+ struct fs_fte *fte;
+ int i;
nested_lock_ref_node(&fg->node, FS_MUTEX_PARENT);
fs_for_each_fte(fte, fg) {
nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
if (compare_match_value(&fg->mask, match_value, &fte->val) &&
- action == fte->action && flow_tag == fte->flow_tag) {
- rule = find_flow_rule(fte, dest);
- if (rule) {
- atomic_inc(&rule->node.refcount);
- unlock_ref_node(&fte->node);
- unlock_ref_node(&fg->node);
- return rule;
+ (flow_act->action & fte->action) &&
+ flow_act->flow_tag == fte->flow_tag) {
+ int old_action = fte->action;
+
+ fte->action |= flow_act->action;
+ handle = add_rule_fte(fte, fg, dest, dest_num,
+ old_action != flow_act->action);
+ if (IS_ERR(handle)) {
+ fte->action = old_action;
+ goto unlock_fte;
+ } else {
+ goto add_rules;
}
- rule = add_rule_fte(fte, fg, dest);
- unlock_ref_node(&fte->node);
- if (IS_ERR(rule))
- goto unlock_fg;
- else
- goto add_rule;
}
unlock_ref_node(&fte->node);
}
fs_get_obj(ft, fg->node.parent);
if (fg->num_ftes >= fg->max_ftes) {
- rule = ERR_PTR(-ENOSPC);
+ handle = ERR_PTR(-ENOSPC);
goto unlock_fg;
}
- fte = create_fte(fg, match_value, action, flow_tag, &prev);
+ fte = create_fte(fg, match_value, flow_act, &prev);
if (IS_ERR(fte)) {
- rule = (void *)fte;
+ handle = (void *)fte;
goto unlock_fg;
}
tree_init_node(&fte->node, 0, del_fte);
- rule = add_rule_fte(fte, fg, dest);
- if (IS_ERR(rule)) {
+ nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
+ handle = add_rule_fte(fte, fg, dest, dest_num, false);
+ if (IS_ERR(handle)) {
kfree(fte);
goto unlock_fg;
}
@@ -1140,19 +1271,24 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg,
tree_add_node(&fte->node, &fg->node);
list_add(&fte->node.list, prev);
-add_rule:
- tree_add_node(&rule->node, &fte->node);
+add_rules:
+ for (i = 0; i < handle->num_rules; i++) {
+ if (atomic_read(&handle->rule[i]->node.refcount) == 1)
+ tree_add_node(&handle->rule[i]->node, &fte->node);
+ }
+unlock_fte:
+ unlock_ref_node(&fte->node);
unlock_fg:
unlock_ref_node(&fg->node);
- return rule;
+ return handle;
}
-struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule)
+struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle)
{
struct mlx5_flow_rule *dst;
struct fs_fte *fte;
- fs_get_obj(fte, rule->node.parent);
+ fs_get_obj(fte, handle->rule[0]->node.parent);
fs_for_each_dst(dst, fte) {
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
@@ -1170,8 +1306,8 @@ static bool counter_is_valid(struct mlx5_fc *counter, u32 action)
if (!counter)
return false;
- /* Hardware support counter for a drop action only */
- return action == (MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT);
+ return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP |
+ MLX5_FLOW_CONTEXT_ACTION_FWD_DEST));
}
static bool dest_is_valid(struct mlx5_flow_destination *dest,
@@ -1191,18 +1327,22 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
return true;
}
-static struct mlx5_flow_rule *
-_mlx5_add_flow_rule(struct mlx5_flow_table *ft,
- struct mlx5_flow_spec *spec,
- u32 action,
- u32 flow_tag,
- struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *
+_mlx5_add_flow_rules(struct mlx5_flow_table *ft,
+ struct mlx5_flow_spec *spec,
+ struct mlx5_flow_act *flow_act,
+ struct mlx5_flow_destination *dest,
+ int dest_num)
+
{
struct mlx5_flow_group *g;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
+ int i;
- if (!dest_is_valid(dest, action, ft))
- return ERR_PTR(-EINVAL);
+ for (i = 0; i < dest_num; i++) {
+ if (!dest_is_valid(&dest[i], flow_act->action, ft))
+ return ERR_PTR(-EINVAL);
+ }
nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT);
fs_for_each_fg(g, ft)
@@ -1211,7 +1351,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft,
g->mask.match_criteria,
spec->match_criteria)) {
rule = add_rule_fg(g, spec->match_value,
- action, flow_tag, dest);
+ flow_act, dest, dest_num);
if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC)
goto unlock;
}
@@ -1223,8 +1363,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft,
goto unlock;
}
- rule = add_rule_fg(g, spec->match_value,
- action, flow_tag, dest);
+ rule = add_rule_fg(g, spec->match_value, flow_act, dest, dest_num);
if (IS_ERR(rule)) {
/* Remove assumes refcount > 0 and autogroup creates a group
* with a refcount = 0.
@@ -1245,22 +1384,22 @@ static bool fwd_next_prio_supported(struct mlx5_flow_table *ft)
(MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs)));
}
-struct mlx5_flow_rule *
-mlx5_add_flow_rule(struct mlx5_flow_table *ft,
- struct mlx5_flow_spec *spec,
- u32 action,
- u32 flow_tag,
- struct mlx5_flow_destination *dest)
+struct mlx5_flow_handle *
+mlx5_add_flow_rules(struct mlx5_flow_table *ft,
+ struct mlx5_flow_spec *spec,
+ struct mlx5_flow_act *flow_act,
+ struct mlx5_flow_destination *dest,
+ int dest_num)
{
struct mlx5_flow_root_namespace *root = find_root(&ft->node);
struct mlx5_flow_destination gen_dest;
struct mlx5_flow_table *next_ft = NULL;
- struct mlx5_flow_rule *rule = NULL;
- u32 sw_action = action;
+ struct mlx5_flow_handle *handle = NULL;
+ u32 sw_action = flow_act->action;
struct fs_prio *prio;
fs_get_obj(prio, ft->node.parent);
- if (action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
+ if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
if (!fwd_next_prio_supported(ft))
return ERR_PTR(-EOPNOTSUPP);
if (dest)
@@ -1271,34 +1410,40 @@ mlx5_add_flow_rule(struct mlx5_flow_table *ft,
gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
gen_dest.ft = next_ft;
dest = &gen_dest;
- action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ dest_num = 1;
+ flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
} else {
mutex_unlock(&root->chain_lock);
return ERR_PTR(-EOPNOTSUPP);
}
}
- rule = _mlx5_add_flow_rule(ft, spec, action, flow_tag, dest);
+ handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, dest_num);
if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
- if (!IS_ERR_OR_NULL(rule) &&
- (list_empty(&rule->next_ft))) {
+ if (!IS_ERR_OR_NULL(handle) &&
+ (list_empty(&handle->rule[0]->next_ft))) {
mutex_lock(&next_ft->lock);
- list_add(&rule->next_ft, &next_ft->fwd_rules);
+ list_add(&handle->rule[0]->next_ft,
+ &next_ft->fwd_rules);
mutex_unlock(&next_ft->lock);
- rule->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
+ handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
}
mutex_unlock(&root->chain_lock);
}
- return rule;
+ return handle;
}
-EXPORT_SYMBOL(mlx5_add_flow_rule);
+EXPORT_SYMBOL(mlx5_add_flow_rules);
-void mlx5_del_flow_rule(struct mlx5_flow_rule *rule)
+void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
{
- tree_remove_node(&rule->node);
+ int i;
+
+ for (i = handle->num_rules - 1; i >= 0; i--)
+ tree_remove_node(&handle->rule[i]->node);
+ kfree(handle);
}
-EXPORT_SYMBOL(mlx5_del_flow_rule);
+EXPORT_SYMBOL(mlx5_del_flow_rules);
/* Assuming prio->node.children(flow tables) is sorted by level */
static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
@@ -1678,7 +1823,7 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
if (!ns)
return -EINVAL;
- ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL);
+ ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL, 0);
if (IS_ERR(ft)) {
mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
return PTR_ERR(ft);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index 71ff03bceabb..8e668c63f69e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -94,6 +94,11 @@ struct mlx5_flow_rule {
u32 sw_action;
};
+struct mlx5_flow_handle {
+ int num_rules;
+ struct mlx5_flow_rule *rule[];
+};
+
/* Type of children is mlx5_flow_group */
struct mlx5_flow_table {
struct fs_node node;
@@ -112,6 +117,7 @@ struct mlx5_flow_table {
struct mutex lock;
/* FWD rules that point on this flow table */
struct list_head fwd_rules;
+ u32 flags;
};
struct mlx5_fc_cache {
@@ -145,6 +151,7 @@ struct fs_fte {
u32 flow_tag;
u32 index;
u32 action;
+ u32 encap_id;
enum fs_fte_status status;
struct mlx5_fc *counter;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index ada24e103b02..7b4c339a8a9a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -174,6 +174,41 @@ static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
return err;
}
+static void mlx5_set_driver_version(struct mlx5_core_dev *dev)
+{
+ int driver_ver_sz = MLX5_FLD_SZ_BYTES(set_driver_version_in,
+ driver_version);
+ u8 in[MLX5_ST_SZ_BYTES(set_driver_version_in)] = {0};
+ u8 out[MLX5_ST_SZ_BYTES(set_driver_version_out)] = {0};
+ int remaining_size = driver_ver_sz;
+ char *string;
+
+ if (!MLX5_CAP_GEN(dev, driver_version))
+ return;
+
+ string = MLX5_ADDR_OF(set_driver_version_in, in, driver_version);
+
+ strncpy(string, "Linux", remaining_size);
+
+ remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+ strncat(string, ",", remaining_size);
+
+ remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+ strncat(string, DRIVER_NAME, remaining_size);
+
+ remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+ strncat(string, ",", remaining_size);
+
+ remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+ strncat(string, DRIVER_VERSION, remaining_size);
+
+ /*Send the command*/
+ MLX5_SET(set_driver_version_in, in, opcode,
+ MLX5_CMD_OP_SET_DRIVER_VERSION);
+
+ mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
static int set_dma_caps(struct pci_dev *pdev)
{
int err;
@@ -1017,6 +1052,8 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_pagealloc_stop;
}
+ mlx5_set_driver_version(dev);
+
mlx5_start_health_poll(dev);
err = mlx5_query_hca_caps(dev);
@@ -1204,6 +1241,8 @@ static const struct devlink_ops mlx5_devlink_ops = {
#ifdef CONFIG_MLX5_CORE_EN
.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
.eswitch_mode_get = mlx5_devlink_eswitch_mode_get,
+ .eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set,
+ .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
#endif
};
@@ -1419,6 +1458,7 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x1017) }, /* ConnectX-5, PCIe 3.0 */
{ PCI_VDEVICE(MELLANOX, 0x1018), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5 VF */
{ PCI_VDEVICE(MELLANOX, 0x1019) }, /* ConnectX-5, PCIe 4.0 */
+ { PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5, PCIe 4.0 VF */
{ 0, }
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 63b9a0dba885..e0a8fbdd1446 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -86,6 +86,7 @@ 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_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe);
void mlx5_enter_error_state(struct mlx5_core_dev *dev);
void mlx5_disable_device(struct mlx5_core_dev *dev);
void mlx5_recover_device(struct mlx5_core_dev *dev);
@@ -97,6 +98,13 @@ int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs);
bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev);
int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
+int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ void *context, u32 *element_id);
+int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ void *context, u32 element_id,
+ u32 modify_bitmask);
+int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ u32 element_id);
int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
cycle_t mlx5_read_internal_timer(struct mlx5_core_dev *dev);
u32 mlx5_get_msix_vec(struct mlx5_core_dev *dev, int vecidx);
@@ -119,6 +127,12 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
void mlx5_dev_list_lock(void);
void mlx5_dev_list_unlock(void);
int mlx5_dev_list_trylock(void);
+int mlx5_encap_alloc(struct mlx5_core_dev *dev,
+ int header_type,
+ size_t size,
+ void *encap_header,
+ u32 *encap_id);
+void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id);
bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 34e7184e23c9..d2ec9d232a70 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -548,6 +548,26 @@ int mlx5_max_tc(struct mlx5_core_dev *mdev)
return num_tc - 1;
}
+int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out)
+{
+ u32 in[MLX5_ST_SZ_DW(dcbx_param)] = {0};
+
+ MLX5_SET(dcbx_param, in, port_number, 1);
+
+ return mlx5_core_access_reg(mdev, in, sizeof(in), out,
+ sizeof(in), MLX5_REG_DCBX_PARAM, 0, 0);
+}
+
+int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in)
+{
+ u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+ MLX5_SET(dcbx_param, in, port_number, 1);
+
+ return mlx5_core_access_reg(mdev, in, sizeof(out), out,
+ sizeof(out), MLX5_REG_DCBX_PARAM, 0, 1);
+}
+
int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc)
{
u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {0};
@@ -572,6 +592,28 @@ int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc)
}
EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
+int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
+ u8 prio, u8 *tc)
+{
+ u32 in[MLX5_ST_SZ_DW(qtct_reg)];
+ u32 out[MLX5_ST_SZ_DW(qtct_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(qtct_reg, in, port_number, 1);
+ MLX5_SET(qtct_reg, in, prio, prio);
+
+ err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_QTCT, 0, 0);
+ if (!err)
+ *tc = MLX5_GET(qtct_reg, out, tclass);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
+
static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
int inlen)
{
@@ -625,6 +667,27 @@ int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw)
}
EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
+int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
+ u8 tc, u8 *bw_pct)
+{
+ u32 out[MLX5_ST_SZ_DW(qetc_reg)];
+ void *ets_tcn_conf;
+ int err;
+
+ err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
+ if (err)
+ return err;
+
+ ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
+ tc_configuration[tc]);
+
+ *bw_pct = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
+ bw_allocation);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
+
int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
u8 *max_bw_value,
u8 *max_bw_units)
@@ -746,3 +809,60 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
*supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap));
*enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk));
}
+
+static const char *mlx5_pme_status[MLX5_MODULE_STATUS_NUM] = {
+ "Cable plugged", /* MLX5_MODULE_STATUS_PLUGGED = 0x1 */
+ "Cable unplugged", /* MLX5_MODULE_STATUS_UNPLUGGED = 0x2 */
+ "Cable error", /* MLX5_MODULE_STATUS_ERROR = 0x3 */
+};
+
+static const char *mlx5_pme_error[MLX5_MODULE_EVENT_ERROR_NUM] = {
+ "Power budget exceeded",
+ "Long Range for non MLNX cable",
+ "Bus stuck(I2C or data shorted)",
+ "No EEPROM/retry timeout",
+ "Enforce part number list",
+ "Unknown identifier",
+ "High Temperature",
+ "Bad or shorted cable/module",
+ "Unknown status",
+};
+
+void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe)
+{
+ enum port_module_event_status_type module_status;
+ enum port_module_event_error_type error_type;
+ struct mlx5_eqe_port_module *module_event_eqe;
+ struct mlx5_priv *priv = &dev->priv;
+ u8 module_num;
+
+ module_event_eqe = &eqe->data.port_module;
+ module_num = module_event_eqe->module;
+ module_status = module_event_eqe->module_status &
+ PORT_MODULE_EVENT_MODULE_STATUS_MASK;
+ error_type = module_event_eqe->error_type &
+ PORT_MODULE_EVENT_ERROR_TYPE_MASK;
+
+ if (module_status < MLX5_MODULE_STATUS_ERROR) {
+ priv->pme_stats.status_counters[module_status - 1]++;
+ } else if (module_status == MLX5_MODULE_STATUS_ERROR) {
+ if (error_type >= MLX5_MODULE_EVENT_ERROR_UNKNOWN)
+ /* Unknown error type */
+ error_type = MLX5_MODULE_EVENT_ERROR_UNKNOWN;
+ priv->pme_stats.error_counters[error_type]++;
+ }
+
+ if (!printk_ratelimit())
+ return;
+
+ if (module_status < MLX5_MODULE_STATUS_ERROR)
+ mlx5_core_info(dev,
+ "Port module event: module %u, %s\n",
+ module_num, mlx5_pme_status[module_status - 1]);
+
+ else if (module_status == MLX5_MODULE_STATUS_ERROR)
+ mlx5_core_info(dev,
+ "Port module event[error]: module %u, %s, %s\n",
+ module_num, mlx5_pme_status[module_status - 1],
+ mlx5_pme_error[error_type]);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rl.c b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
index 104902a93a0b..e651e4c02867 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/rl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
@@ -36,6 +36,71 @@
#include <linux/mlx5/cmd.h>
#include "mlx5_core.h"
+/* Scheduling element fw management */
+int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ void *ctx, u32 *element_id)
+{
+ u32 in[MLX5_ST_SZ_DW(create_scheduling_element_in)] = {0};
+ u32 out[MLX5_ST_SZ_DW(create_scheduling_element_in)] = {0};
+ void *schedc;
+ int err;
+
+ schedc = MLX5_ADDR_OF(create_scheduling_element_in, in,
+ scheduling_context);
+ MLX5_SET(create_scheduling_element_in, in, opcode,
+ MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT);
+ MLX5_SET(create_scheduling_element_in, in, scheduling_hierarchy,
+ hierarchy);
+ memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context));
+
+ err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+ if (err)
+ return err;
+
+ *element_id = MLX5_GET(create_scheduling_element_out, out,
+ scheduling_element_id);
+ return 0;
+}
+
+int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ void *ctx, u32 element_id,
+ u32 modify_bitmask)
+{
+ u32 in[MLX5_ST_SZ_DW(modify_scheduling_element_in)] = {0};
+ u32 out[MLX5_ST_SZ_DW(modify_scheduling_element_in)] = {0};
+ void *schedc;
+
+ schedc = MLX5_ADDR_OF(modify_scheduling_element_in, in,
+ scheduling_context);
+ MLX5_SET(modify_scheduling_element_in, in, opcode,
+ MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT);
+ MLX5_SET(modify_scheduling_element_in, in, scheduling_element_id,
+ element_id);
+ MLX5_SET(modify_scheduling_element_in, in, modify_bitmask,
+ modify_bitmask);
+ MLX5_SET(modify_scheduling_element_in, in, scheduling_hierarchy,
+ hierarchy);
+ memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context));
+
+ return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+ u32 element_id)
+{
+ u32 in[MLX5_ST_SZ_DW(destroy_scheduling_element_in)] = {0};
+ u32 out[MLX5_ST_SZ_DW(destroy_scheduling_element_in)] = {0};
+
+ MLX5_SET(destroy_scheduling_element_in, in, opcode,
+ MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
+ MLX5_SET(destroy_scheduling_element_in, in, scheduling_element_id,
+ element_id);
+ MLX5_SET(destroy_scheduling_element_in, in, scheduling_hierarchy,
+ hierarchy);
+
+ return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
/* Finds an entry where we can register the given rate
* If the rate already exists, return the entry where it is registered,
* otherwise return the first available entry.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index 525f17af108e..269e4401c342 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -113,15 +113,17 @@ static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
return mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
}
-void mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
- u8 *min_inline_mode)
+int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
+ u16 vport, u8 *min_inline)
{
u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {0};
+ int err;
- mlx5_query_nic_vport_context(mdev, 0, out, sizeof(out));
-
- *min_inline_mode = MLX5_GET(query_nic_vport_context_out, out,
- nic_vport_context.min_wqe_inline_mode);
+ err = mlx5_query_nic_vport_context(mdev, vport, out, sizeof(out));
+ if (!err)
+ *min_inline = MLX5_GET(query_nic_vport_context_out, out,
+ nic_vport_context.min_wqe_inline_mode);
+ return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/wq.c b/drivers/net/ethernet/mellanox/mlx5/core/wq.c
index 821a087c7ae2..921673c42bc9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/wq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/wq.c
@@ -101,13 +101,15 @@ err_db_free:
int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
void *cqc, struct mlx5_cqwq *wq,
- struct mlx5_wq_ctrl *wq_ctrl)
+ struct mlx5_frag_wq_ctrl *wq_ctrl)
{
int err;
- wq->log_stride = 6 + MLX5_GET(cqc, cqc, cqe_sz);
- wq->log_sz = MLX5_GET(cqc, cqc, log_cq_size);
- wq->sz_m1 = (1 << wq->log_sz) - 1;
+ wq->log_stride = 6 + MLX5_GET(cqc, cqc, cqe_sz);
+ wq->log_sz = MLX5_GET(cqc, cqc, log_cq_size);
+ wq->sz_m1 = (1 << wq->log_sz) - 1;
+ wq->log_frag_strides = PAGE_SHIFT - wq->log_stride;
+ wq->frag_sz_m1 = (1 << wq->log_frag_strides) - 1;
err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
if (err) {
@@ -115,14 +117,16 @@ int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
return err;
}
- err = mlx5_buf_alloc_node(mdev, mlx5_cqwq_get_byte_size(wq),
- &wq_ctrl->buf, param->buf_numa_node);
+ err = mlx5_frag_buf_alloc_node(mdev, mlx5_cqwq_get_byte_size(wq),
+ &wq_ctrl->frag_buf,
+ param->buf_numa_node);
if (err) {
- mlx5_core_warn(mdev, "mlx5_buf_alloc_node() failed, %d\n", err);
+ mlx5_core_warn(mdev, "mlx5_frag_buf_alloc_node() failed, %d\n",
+ err);
goto err_db_free;
}
- wq->buf = wq_ctrl->buf.direct.buf;
+ wq->frag_buf = wq_ctrl->frag_buf;
wq->db = wq_ctrl->db.db;
wq_ctrl->mdev = mdev;
@@ -184,3 +188,9 @@ void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl)
mlx5_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
mlx5_db_free(wq_ctrl->mdev, &wq_ctrl->db);
}
+
+void mlx5_cqwq_destroy(struct mlx5_frag_wq_ctrl *wq_ctrl)
+{
+ mlx5_frag_buf_free(wq_ctrl->mdev, &wq_ctrl->frag_buf);
+ mlx5_db_free(wq_ctrl->mdev, &wq_ctrl->db);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/wq.h b/drivers/net/ethernet/mellanox/mlx5/core/wq.h
index 6c2a8f95093c..d8afed898c31 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/wq.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/wq.h
@@ -47,6 +47,12 @@ struct mlx5_wq_ctrl {
struct mlx5_db db;
};
+struct mlx5_frag_wq_ctrl {
+ struct mlx5_core_dev *mdev;
+ struct mlx5_frag_buf frag_buf;
+ struct mlx5_db db;
+};
+
struct mlx5_wq_cyc {
void *buf;
__be32 *db;
@@ -55,12 +61,14 @@ struct mlx5_wq_cyc {
};
struct mlx5_cqwq {
- void *buf;
+ struct mlx5_frag_buf frag_buf;
__be32 *db;
u32 sz_m1;
+ u32 frag_sz_m1;
u32 cc; /* consumer counter */
u8 log_sz;
u8 log_stride;
+ u8 log_frag_strides;
};
struct mlx5_wq_ll {
@@ -81,7 +89,7 @@ u32 mlx5_wq_cyc_get_size(struct mlx5_wq_cyc *wq);
int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
void *cqc, struct mlx5_cqwq *wq,
- struct mlx5_wq_ctrl *wq_ctrl);
+ struct mlx5_frag_wq_ctrl *wq_ctrl);
u32 mlx5_cqwq_get_size(struct mlx5_cqwq *wq);
int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
@@ -90,6 +98,7 @@ int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
u32 mlx5_wq_ll_get_size(struct mlx5_wq_ll *wq);
void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl);
+void mlx5_cqwq_destroy(struct mlx5_frag_wq_ctrl *wq_ctrl);
static inline u16 mlx5_wq_cyc_ctr2ix(struct mlx5_wq_cyc *wq, u16 ctr)
{
@@ -116,7 +125,10 @@ static inline u32 mlx5_cqwq_get_ci(struct mlx5_cqwq *wq)
static inline void *mlx5_cqwq_get_wqe(struct mlx5_cqwq *wq, u32 ix)
{
- return wq->buf + (ix << wq->log_stride);
+ unsigned int frag = (ix >> wq->log_frag_strides);
+
+ return wq->frag_buf.frags[frag].buf +
+ ((wq->frag_sz_m1 & ix) << wq->log_stride);
}
static inline u32 mlx5_cqwq_get_wrap_cnt(struct mlx5_cqwq *wq)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
index 5989f7cb5462..16f44b9aa076 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
@@ -19,6 +19,15 @@ config MLXSW_CORE_HWMON
---help---
Say Y here if you want to expose HWMON interface on mlxsw devices.
+config MLXSW_CORE_THERMAL
+ bool "Thermal zone support for Mellanox Technologies Switch ASICs"
+ depends on MLXSW_CORE && THERMAL
+ depends on !(MLXSW_CORE=y && THERMAL=m)
+ default y
+ ---help---
+ Say Y here if you want to automatically control fans speed according
+ ambient temperature reported by ASIC.
+
config MLXSW_PCI
tristate "PCI bus implementation for Mellanox Technologies Switch ASICs"
depends on PCI && HAS_DMA && HAS_IOMEM && MLXSW_CORE
@@ -29,9 +38,30 @@ config MLXSW_PCI
To compile this driver as a module, choose M here: the
module will be called mlxsw_pci.
+config MLXSW_I2C
+ tristate "I2C bus implementation for Mellanox Technologies Switch ASICs"
+ depends on I2C && MLXSW_CORE
+ default m
+ ---help---
+ This is I2C bus implementation for Mellanox Technologies Switch ASICs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mlxsw_i2c.
+
+config MLXSW_SWITCHIB
+ tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support"
+ depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
+ default m
+ ---help---
+ This driver supports Mellanox Technologies SwitchIB and SwitchIB-2
+ Infiniband Switch ASICs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mlxsw_switchib.
+
config MLXSW_SWITCHX2
tristate "Mellanox Technologies SwitchX-2 support"
- depends on MLXSW_CORE && NET_SWITCHDEV
+ depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
default m
---help---
This driver supports Mellanox Technologies SwitchX-2 Ethernet
@@ -42,7 +72,7 @@ config MLXSW_SWITCHX2
config MLXSW_SPECTRUM
tristate "Mellanox Technologies Spectrum support"
- depends on MLXSW_CORE && NET_SWITCHDEV && VLAN_8021Q
+ depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q
default m
---help---
This driver supports Mellanox Technologies Spectrum Ethernet
@@ -58,3 +88,14 @@ config MLXSW_SPECTRUM_DCB
---help---
Say Y here if you want to use Data Center Bridging (DCB) in the
driver.
+
+config MLXSW_MINIMAL
+ tristate "Mellanox Technologies minimal I2C support"
+ depends on MLXSW_CORE && MLXSW_I2C
+ default m
+ ---help---
+ This driver supports I2C access for Mellanox Technologies Switch
+ ASICs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mlxsw_minimal.
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index d20ae1838a64..fe8dadba15ab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -1,8 +1,13 @@
obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o
mlxsw_core-objs := core.o
mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
+mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o
obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
mlxsw_pci-objs := pci.o
+obj-$(CONFIG_MLXSW_I2C) += mlxsw_i2c.o
+mlxsw_i2c-objs := i2c.o
+obj-$(CONFIG_MLXSW_SWITCHIB) += mlxsw_switchib.o
+mlxsw_switchib-objs := switchib.o
obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o
mlxsw_switchx2-objs := switchx2.o
obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o
@@ -10,3 +15,5 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
spectrum_switchdev.o spectrum_router.o \
spectrum_kvdl.o
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o
+obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o
+mlxsw_minimal-objs := minimal.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
index 28271bedd957..56e19b0d2f8f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
@@ -513,6 +513,11 @@ static inline int mlxsw_cmd_unmap_fa(struct mlxsw_core *mlxsw_core)
* are no more sources in the table, will return resource id 0xFFF to indicate
* it.
*/
+
+#define MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID 0xffff
+#define MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES 100
+#define MLXSW_CMD_QUERY_RESOURCES_PER_QUERY 32
+
static inline int mlxsw_cmd_query_resources(struct mlxsw_core *mlxsw_core,
char *out_mbox, int index)
{
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index aa33d58b9f81..57a98849551b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -67,6 +67,7 @@
#include "trap.h"
#include "emad.h"
#include "reg.h"
+#include "resources.h"
static LIST_HEAD(mlxsw_core_driver_list);
static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock);
@@ -76,6 +77,7 @@ static const char mlxsw_core_driver_name[] = "mlxsw_core";
static struct dentry *mlxsw_core_dbg_root;
static struct workqueue_struct *mlxsw_wq;
+static struct workqueue_struct *mlxsw_owq;
struct mlxsw_core_pcpu_stats {
u64 trap_rx_packets[MLXSW_TRAP_ID_MAX];
@@ -89,6 +91,23 @@ struct mlxsw_core_pcpu_stats {
u32 port_rx_invalid;
};
+struct mlxsw_core_port {
+ struct devlink_port devlink_port;
+ void *port_driver_priv;
+ u8 local_port;
+};
+
+void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
+{
+ return mlxsw_core_port->port_driver_priv;
+}
+EXPORT_SYMBOL(mlxsw_core_port_driver_priv);
+
+static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port)
+{
+ return mlxsw_core_port->port_driver_priv != NULL;
+}
+
struct mlxsw_core {
struct mlxsw_driver *driver;
const struct mlxsw_bus *bus;
@@ -111,8 +130,10 @@ struct mlxsw_core {
struct {
u8 *mapping; /* lag_id+port_index to local_port mapping */
} lag;
- struct mlxsw_resources resources;
+ struct mlxsw_res res;
struct mlxsw_hwmon *hwmon;
+ struct mlxsw_thermal *thermal;
+ struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
unsigned long driver_priv[0];
/* driver_priv has to be always the last item */
};
@@ -552,33 +573,18 @@ free_skb:
dev_kfree_skb(skb);
}
-static const struct mlxsw_rx_listener mlxsw_emad_rx_listener = {
- .func = mlxsw_emad_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_ETHEMAD,
-};
-
-static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core)
-{
- char htgt_pl[MLXSW_REG_HTGT_LEN];
- char hpkt_pl[MLXSW_REG_HPKT_LEN];
- int err;
-
- mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD);
- err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
- if (err)
- return err;
-
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
- MLXSW_TRAP_ID_ETHEMAD);
- return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
-}
+static const struct mlxsw_listener mlxsw_emad_rx_listener =
+ MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
+ EMAD, DISCARD);
static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
{
u64 tid;
int err;
+ if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
+ return 0;
+
/* Set the upper 32 bits of the transaction ID field to a random
* number. This allows us to discard EMADs addressed to other
* devices.
@@ -590,39 +596,33 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
INIT_LIST_HEAD(&mlxsw_core->emad.trans_list);
spin_lock_init(&mlxsw_core->emad.trans_list_lock);
- err = mlxsw_core_rx_listener_register(mlxsw_core,
- &mlxsw_emad_rx_listener,
- mlxsw_core);
+ err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener,
+ mlxsw_core);
if (err)
return err;
- err = mlxsw_emad_traps_set(mlxsw_core);
+ err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core);
if (err)
goto err_emad_trap_set;
-
mlxsw_core->emad.use_emad = true;
return 0;
err_emad_trap_set:
- mlxsw_core_rx_listener_unregister(mlxsw_core,
- &mlxsw_emad_rx_listener,
- mlxsw_core);
+ mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
+ mlxsw_core);
return err;
}
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_TRAP_ID_ETHEMAD);
- mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+ if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
+ return;
- mlxsw_core_rx_listener_unregister(mlxsw_core,
- &mlxsw_emad_rx_listener,
- mlxsw_core);
+ mlxsw_core->emad.use_emad = false;
+ mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
+ mlxsw_core);
}
static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core,
@@ -822,17 +822,6 @@ static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind)
spin_lock(&mlxsw_core_driver_list_lock);
mlxsw_driver = __driver_find(kind);
- if (!mlxsw_driver) {
- spin_unlock(&mlxsw_core_driver_list_lock);
- request_module(MLXSW_MODULE_ALIAS_PREFIX "%s", kind);
- spin_lock(&mlxsw_core_driver_list_lock);
- mlxsw_driver = __driver_find(kind);
- }
- if (mlxsw_driver) {
- if (!try_module_get(mlxsw_driver->owner))
- mlxsw_driver = NULL;
- }
-
spin_unlock(&mlxsw_core_driver_list_lock);
return mlxsw_driver;
}
@@ -844,9 +833,6 @@ static void mlxsw_core_driver_put(const char *kind)
spin_lock(&mlxsw_core_driver_list_lock);
mlxsw_driver = __driver_find(kind);
spin_unlock(&mlxsw_core_driver_list_lock);
- if (!mlxsw_driver)
- return;
- module_put(mlxsw_driver->owner);
}
static int mlxsw_core_debugfs_init(struct mlxsw_core *mlxsw_core)
@@ -933,6 +919,21 @@ static void *__dl_port(struct devlink_port *devlink_port)
return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
}
+static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
+ enum devlink_port_type port_type)
+{
+ struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+ struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+ struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+ if (!mlxsw_driver->port_type_set)
+ return -EOPNOTSUPP;
+
+ return mlxsw_driver->port_type_set(mlxsw_core,
+ mlxsw_core_port->local_port,
+ port_type);
+}
+
static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
unsigned int sb_index, u16 pool_index,
u32 *p_threshold)
@@ -941,7 +942,8 @@ static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_port_pool_get)
+ if (!mlxsw_driver->sb_port_pool_get ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
pool_index, p_threshold);
@@ -955,7 +957,8 @@ static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_port_pool_set)
+ if (!mlxsw_driver->sb_port_pool_set ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
pool_index, threshold);
@@ -971,7 +974,8 @@ mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_tc_pool_bind_get)
+ if (!mlxsw_driver->sb_tc_pool_bind_get ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
tc_index, pool_type,
@@ -988,7 +992,8 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_tc_pool_bind_set)
+ if (!mlxsw_driver->sb_tc_pool_bind_set ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
tc_index, pool_type,
@@ -1026,7 +1031,8 @@ mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_occ_port_pool_get)
+ if (!mlxsw_driver->sb_occ_port_pool_get ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index,
pool_index, p_cur, p_max);
@@ -1042,7 +1048,8 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
- if (!mlxsw_driver->sb_occ_tc_port_bind_get)
+ if (!mlxsw_driver->sb_occ_tc_port_bind_get ||
+ !mlxsw_core_port_check(mlxsw_core_port))
return -EOPNOTSUPP;
return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port,
sb_index, tc_index,
@@ -1050,6 +1057,7 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
}
static const struct devlink_ops mlxsw_devlink_ops = {
+ .port_type_set = mlxsw_devlink_port_type_set,
.port_split = mlxsw_devlink_port_split,
.port_unsplit = mlxsw_devlink_port_unsplit,
.sb_pool_get = mlxsw_devlink_sb_pool_get,
@@ -1101,14 +1109,15 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
}
err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
- &mlxsw_core->resources);
+ &mlxsw_core->res);
if (err)
goto err_bus_init;
- if (mlxsw_core->resources.max_lag_valid &&
- mlxsw_core->resources.max_ports_in_lag_valid) {
- alloc_size = sizeof(u8) * mlxsw_core->resources.max_lag *
- mlxsw_core->resources.max_ports_in_lag;
+ if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
+ MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
+ alloc_size = sizeof(u8) *
+ MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) *
+ MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS);
mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL);
if (!mlxsw_core->lag.mapping) {
err = -ENOMEM;
@@ -1128,9 +1137,16 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
if (err)
goto err_hwmon_init;
- err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info);
+ err = mlxsw_thermal_init(mlxsw_core, mlxsw_bus_info,
+ &mlxsw_core->thermal);
if (err)
- goto err_driver_init;
+ goto err_thermal_init;
+
+ if (mlxsw_driver->init) {
+ err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info);
+ if (err)
+ goto err_driver_init;
+ }
err = mlxsw_core_debugfs_init(mlxsw_core);
if (err)
@@ -1139,8 +1155,11 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
return 0;
err_debugfs_init:
- mlxsw_core->driver->fini(mlxsw_core);
+ if (mlxsw_core->driver->fini)
+ mlxsw_core->driver->fini(mlxsw_core);
err_driver_init:
+ mlxsw_thermal_fini(mlxsw_core->thermal);
+err_thermal_init:
err_hwmon_init:
devlink_unregister(devlink);
err_devlink_register:
@@ -1165,11 +1184,13 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
struct devlink *devlink = priv_to_devlink(mlxsw_core);
mlxsw_core_debugfs_fini(mlxsw_core);
- mlxsw_core->driver->fini(mlxsw_core);
+ if (mlxsw_core->driver->fini)
+ mlxsw_core->driver->fini(mlxsw_core);
+ mlxsw_thermal_fini(mlxsw_core->thermal);
devlink_unregister(devlink);
mlxsw_emad_fini(mlxsw_core);
- mlxsw_core->bus->fini(mlxsw_core->bus_priv);
kfree(mlxsw_core->lag.mapping);
+ mlxsw_core->bus->fini(mlxsw_core->bus_priv);
free_percpu(mlxsw_core->pcpu_stats);
devlink_free(devlink);
mlxsw_core_driver_put(device_kind);
@@ -1346,6 +1367,75 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);
+static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener,
+ void *priv)
+{
+ if (listener->is_event)
+ return mlxsw_core_event_listener_register(mlxsw_core,
+ &listener->u.event_listener,
+ priv);
+ else
+ return mlxsw_core_rx_listener_register(mlxsw_core,
+ &listener->u.rx_listener,
+ priv);
+}
+
+static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener,
+ void *priv)
+{
+ if (listener->is_event)
+ mlxsw_core_event_listener_unregister(mlxsw_core,
+ &listener->u.event_listener,
+ priv);
+ else
+ mlxsw_core_rx_listener_unregister(mlxsw_core,
+ &listener->u.rx_listener,
+ priv);
+}
+
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener, void *priv)
+{
+ char hpkt_pl[MLXSW_REG_HPKT_LEN];
+ int err;
+
+ err = mlxsw_core_listener_register(mlxsw_core, listener, priv);
+ if (err)
+ return err;
+
+ mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id,
+ listener->trap_group, listener->is_ctrl);
+ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+ if (err)
+ goto err_trap_set;
+
+ return 0;
+
+err_trap_set:
+ mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+ return err;
+}
+EXPORT_SYMBOL(mlxsw_core_trap_register);
+
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener,
+ void *priv)
+{
+ char hpkt_pl[MLXSW_REG_HPKT_LEN];
+
+ if (!listener->is_event) {
+ mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action,
+ listener->trap_id, listener->trap_group,
+ listener->is_ctrl);
+ mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+ }
+
+ mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+}
+EXPORT_SYMBOL(mlxsw_core_trap_unregister);
+
static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
{
return atomic64_inc_return(&mlxsw_core->emad.tid);
@@ -1615,7 +1705,7 @@ EXPORT_SYMBOL(mlxsw_core_skb_receive);
static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core,
u16 lag_id, u8 port_index)
{
- return mlxsw_core->resources.max_ports_in_lag * lag_id +
+ return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id +
port_index;
}
@@ -1644,7 +1734,7 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
{
int i;
- for (i = 0; i < mlxsw_core->resources.max_ports_in_lag; i++) {
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) {
int index = mlxsw_core_lag_mapping_index(mlxsw_core,
lag_id, i);
@@ -1654,34 +1744,97 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear);
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core)
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+ enum mlxsw_res_id res_id)
{
- return &mlxsw_core->resources;
+ return mlxsw_res_valid(&mlxsw_core->res, res_id);
}
-EXPORT_SYMBOL(mlxsw_core_resources_get);
+EXPORT_SYMBOL(mlxsw_core_res_valid);
-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
- struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
- struct net_device *dev, bool split, u32 split_group)
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+ enum mlxsw_res_id res_id)
+{
+ return mlxsw_res_get(&mlxsw_core->res, res_id);
+}
+EXPORT_SYMBOL(mlxsw_core_res_get);
+
+int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port)
{
struct devlink *devlink = priv_to_devlink(mlxsw_core);
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+ int err;
- if (split)
- devlink_port_split_set(devlink_port, split_group);
- devlink_port_type_eth_set(devlink_port, dev);
- return devlink_port_register(devlink, devlink_port, local_port);
+ mlxsw_core_port->local_port = local_port;
+ err = devlink_port_register(devlink, devlink_port, local_port);
+ if (err)
+ memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
+ return err;
}
EXPORT_SYMBOL(mlxsw_core_port_init);
-void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port)
+void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
{
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
devlink_port_unregister(devlink_port);
+ memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
}
EXPORT_SYMBOL(mlxsw_core_port_fini);
+void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv, struct net_device *dev,
+ bool split, u32 split_group)
+{
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
+ struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+ mlxsw_core_port->port_driver_priv = port_driver_priv;
+ if (split)
+ devlink_port_split_set(devlink_port, split_group);
+ devlink_port_type_eth_set(devlink_port, dev);
+}
+EXPORT_SYMBOL(mlxsw_core_port_eth_set);
+
+void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv)
+{
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
+ struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+ mlxsw_core_port->port_driver_priv = port_driver_priv;
+ devlink_port_type_ib_set(devlink_port, NULL);
+}
+EXPORT_SYMBOL(mlxsw_core_port_ib_set);
+
+void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv)
+{
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
+ struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+ mlxsw_core_port->port_driver_priv = port_driver_priv;
+ devlink_port_type_clear(devlink_port);
+}
+EXPORT_SYMBOL(mlxsw_core_port_clear);
+
+enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
+ u8 local_port)
+{
+ struct mlxsw_core_port *mlxsw_core_port =
+ &mlxsw_core->ports[local_port];
+ struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+ return devlink_port->type;
+}
+EXPORT_SYMBOL(mlxsw_core_port_type_get);
+
static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
const char *buf, size_t size)
{
@@ -1748,6 +1901,18 @@ int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay)
}
EXPORT_SYMBOL(mlxsw_core_schedule_dw);
+int mlxsw_core_schedule_odw(struct delayed_work *dwork, unsigned long delay)
+{
+ return queue_delayed_work(mlxsw_owq, dwork, delay);
+}
+EXPORT_SYMBOL(mlxsw_core_schedule_odw);
+
+void mlxsw_core_flush_owq(void)
+{
+ flush_workqueue(mlxsw_owq);
+}
+EXPORT_SYMBOL(mlxsw_core_flush_owq);
+
static int __init mlxsw_core_module_init(void)
{
int err;
@@ -1755,6 +1920,12 @@ static int __init mlxsw_core_module_init(void)
mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, WQ_MEM_RECLAIM, 0);
if (!mlxsw_wq)
return -ENOMEM;
+ mlxsw_owq = alloc_ordered_workqueue("%s_ordered", WQ_MEM_RECLAIM,
+ mlxsw_core_driver_name);
+ if (!mlxsw_owq) {
+ err = -ENOMEM;
+ goto err_alloc_ordered_workqueue;
+ }
mlxsw_core_dbg_root = debugfs_create_dir(mlxsw_core_driver_name, NULL);
if (!mlxsw_core_dbg_root) {
err = -ENOMEM;
@@ -1763,6 +1934,8 @@ static int __init mlxsw_core_module_init(void)
return 0;
err_debugfs_create_dir:
+ destroy_workqueue(mlxsw_owq);
+err_alloc_ordered_workqueue:
destroy_workqueue(mlxsw_wq);
return err;
}
@@ -1770,6 +1943,7 @@ err_debugfs_create_dir:
static void __exit mlxsw_core_module_exit(void)
{
debugfs_remove_recursive(mlxsw_core_dbg_root);
+ destroy_workqueue(mlxsw_owq);
destroy_workqueue(mlxsw_wq);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index c4f550b6f783..a7f94fbc898b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -48,17 +48,11 @@
#include "trap.h"
#include "reg.h"
-
#include "cmd.h"
-
-#define MLXSW_MODULE_ALIAS_PREFIX "mlxsw-driver-"
-#define MODULE_MLXSW_DRIVER_ALIAS(kind) \
- MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind)
-
-#define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2"
-#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum"
+#include "resources.h"
struct mlxsw_core;
+struct mlxsw_core_port;
struct mlxsw_driver;
struct mlxsw_bus;
struct mlxsw_bus_info;
@@ -96,6 +90,50 @@ struct mlxsw_event_listener {
enum mlxsw_event_trap_id trap_id;
};
+struct mlxsw_listener {
+ u16 trap_id;
+ union {
+ struct mlxsw_rx_listener rx_listener;
+ struct mlxsw_event_listener event_listener;
+ } u;
+ enum mlxsw_reg_hpkt_action action;
+ enum mlxsw_reg_hpkt_action unreg_action;
+ u8 trap_group;
+ bool is_ctrl; /* should go via control buffer or not */
+ bool is_event;
+};
+
+#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _trap_group, \
+ _unreg_action) \
+ { \
+ .trap_id = MLXSW_TRAP_ID_##_trap_id, \
+ .u.rx_listener = \
+ { \
+ .func = _func, \
+ .local_port = MLXSW_PORT_DONT_CARE, \
+ .trap_id = MLXSW_TRAP_ID_##_trap_id, \
+ }, \
+ .action = MLXSW_REG_HPKT_ACTION_##_action, \
+ .unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action, \
+ .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \
+ .is_ctrl = _is_ctrl, \
+ .is_event = false, \
+ }
+
+#define MLXSW_EVENTL(_func, _trap_id, _trap_group) \
+ { \
+ .trap_id = MLXSW_TRAP_ID_##_trap_id, \
+ .u.event_listener = \
+ { \
+ .func = _func, \
+ .trap_id = MLXSW_TRAP_ID_##_trap_id, \
+ }, \
+ .action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \
+ .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \
+ .is_ctrl = false, \
+ .is_event = true, \
+ }
+
int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
const struct mlxsw_rx_listener *rxl,
void *priv);
@@ -110,6 +148,13 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core,
const struct mlxsw_event_listener *el,
void *priv);
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener,
+ void *priv);
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_listener *listener,
+ void *priv);
+
typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
size_t payload_len, unsigned long cb_priv);
@@ -148,25 +193,22 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core,
void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
u16 lag_id, u8 local_port);
-struct mlxsw_core_port {
- struct devlink_port devlink_port;
-};
-
-static inline void *
-mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
-{
- /* mlxsw_core_port is ensured to always be the first field in driver
- * port structure.
- */
- return mlxsw_core_port;
-}
-
-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
- struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
- struct net_device *dev, bool split, u32 split_group);
-void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port);
+void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
+int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
+void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
+void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv, struct net_device *dev,
+ bool split, u32 split_group);
+void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv);
+void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
+ void *port_driver_priv);
+enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
+ u8 local_port);
int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);
+int mlxsw_core_schedule_odw(struct delayed_work *dwork, unsigned long delay);
+void mlxsw_core_flush_owq(void);
#define MLXSW_CONFIG_PROFILE_SWID_COUNT 8
@@ -221,11 +263,13 @@ struct mlxsw_config_profile {
struct mlxsw_driver {
struct list_head list;
const char *kind;
- struct module *owner;
size_t priv_size;
int (*init)(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info);
void (*fini)(struct mlxsw_core *mlxsw_core);
+ int (*basic_trap_groups_set)(struct mlxsw_core *mlxsw_core);
+ int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port,
+ enum devlink_port_type new_type);
int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port,
unsigned int count);
int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port);
@@ -266,45 +310,25 @@ struct mlxsw_driver {
const struct mlxsw_config_profile *profile;
};
-struct mlxsw_resources {
- u32 max_span_valid:1,
- max_lag_valid:1,
- max_ports_in_lag_valid:1,
- kvd_size_valid:1,
- kvd_single_min_size_valid:1,
- kvd_double_min_size_valid:1,
- max_virtual_routers_valid:1,
- max_system_ports_valid:1,
- max_vlan_groups_valid:1,
- max_regions_valid:1,
- max_rif_valid:1;
- u8 max_span;
- u8 max_lag;
- u8 max_ports_in_lag;
- u32 kvd_size;
- u32 kvd_single_min_size;
- u32 kvd_double_min_size;
- u16 max_virtual_routers;
- u16 max_system_ports;
- u16 max_vlan_groups;
- u16 max_regions;
- u16 max_rif;
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+ enum mlxsw_res_id res_id);
- /* Internal resources.
- * Determined by the SW, not queried from the HW.
- */
- u32 kvd_single_size;
- u32 kvd_double_size;
- u32 kvd_linear_size;
-};
+#define MLXSW_CORE_RES_VALID(res, short_res_id) \
+ mlxsw_core_res_valid(res, MLXSW_RES_ID_##short_res_id)
+
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+ enum mlxsw_res_id res_id);
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core);
+#define MLXSW_CORE_RES_GET(res, short_res_id) \
+ mlxsw_core_res_get(res, MLXSW_RES_ID_##short_res_id)
+
+#define MLXSW_BUS_F_TXRX BIT(0)
struct mlxsw_bus {
const char *kind;
int (*init)(void *bus_priv, struct mlxsw_core *mlxsw_core,
const struct mlxsw_config_profile *profile,
- struct mlxsw_resources *resources);
+ struct mlxsw_res *res);
void (*fini)(void *bus_priv);
bool (*skb_transmit_busy)(void *bus_priv,
const struct mlxsw_tx_info *tx_info);
@@ -315,6 +339,7 @@ struct mlxsw_bus {
char *in_mbox, size_t in_mbox_size,
char *out_mbox, size_t out_mbox_size,
u8 *p_status);
+ u8 features;
};
struct mlxsw_bus_info {
@@ -350,4 +375,28 @@ static inline int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
#endif
+struct mlxsw_thermal;
+
+#ifdef CONFIG_MLXSW_CORE_THERMAL
+
+int mlxsw_thermal_init(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *mlxsw_bus_info,
+ struct mlxsw_thermal **p_thermal);
+void mlxsw_thermal_fini(struct mlxsw_thermal *thermal);
+
+#else
+
+static inline int mlxsw_thermal_init(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *mlxsw_bus_info,
+ struct mlxsw_thermal **p_thermal)
+{
+ return 0;
+}
+
+static inline void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
+{
+}
+
+#endif
+
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 1ac8bf187168..ab710e37af99 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -262,7 +262,7 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
{
- char mtcap_pl[MLXSW_REG_MTCAP_LEN];
+ char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
char mtmp_pl[MLXSW_REG_MTMP_LEN];
u8 sensor_count;
int i;
@@ -295,7 +295,7 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
{
- char mfcr_pl[MLXSW_REG_MFCR_LEN];
+ char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
enum mlxsw_reg_mfcr_pwm_frequency freq;
unsigned int type_index;
unsigned int num;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
new file mode 100644
index 000000000000..d866c98c1a97
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -0,0 +1,442 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+ * Copyright (c) 2016 Ivan Vecera <cera@cera.cz>
+ *
+ * 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/device.h>
+#include <linux/sysfs.h>
+#include <linux/thermal.h>
+#include <linux/err.h>
+
+#include "core.h"
+
+#define MLXSW_THERMAL_POLL_INT 1000 /* ms */
+#define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */
+#define MLXSW_THERMAL_MAX_STATE 10
+#define MLXSW_THERMAL_MAX_DUTY 255
+
+struct mlxsw_thermal_trip {
+ int type;
+ int temp;
+ int min_state;
+ int max_state;
+};
+
+static const struct mlxsw_thermal_trip default_thermal_trips[] = {
+ { /* In range - 0-40% PWM */
+ .type = THERMAL_TRIP_ACTIVE,
+ .temp = 75000,
+ .min_state = 0,
+ .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
+ },
+ { /* High - 40-100% PWM */
+ .type = THERMAL_TRIP_ACTIVE,
+ .temp = 80000,
+ .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
+ .max_state = MLXSW_THERMAL_MAX_STATE,
+ },
+ {
+ /* Very high - 100% PWM */
+ .type = THERMAL_TRIP_ACTIVE,
+ .temp = 85000,
+ .min_state = MLXSW_THERMAL_MAX_STATE,
+ .max_state = MLXSW_THERMAL_MAX_STATE,
+ },
+ { /* Warning */
+ .type = THERMAL_TRIP_HOT,
+ .temp = 105000,
+ .min_state = MLXSW_THERMAL_MAX_STATE,
+ .max_state = MLXSW_THERMAL_MAX_STATE,
+ },
+ { /* Critical - soft poweroff */
+ .type = THERMAL_TRIP_CRITICAL,
+ .temp = MLXSW_THERMAL_MAX_TEMP,
+ .min_state = MLXSW_THERMAL_MAX_STATE,
+ .max_state = MLXSW_THERMAL_MAX_STATE,
+ }
+};
+
+#define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
+
+/* Make sure all trips are writable */
+#define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
+
+struct mlxsw_thermal {
+ struct mlxsw_core *core;
+ const struct mlxsw_bus_info *bus_info;
+ struct thermal_zone_device *tzdev;
+ struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
+ struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
+ enum thermal_device_mode mode;
+};
+
+static inline u8 mlxsw_state_to_duty(int state)
+{
+ return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
+ MLXSW_THERMAL_MAX_STATE);
+}
+
+static inline int mlxsw_duty_to_state(u8 duty)
+{
+ return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
+ MLXSW_THERMAL_MAX_DUTY);
+}
+
+static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+
+ for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
+ if (thermal->cdevs[i] == cdev)
+ return i;
+
+ return -ENODEV;
+}
+
+static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
+ struct thermal_cooling_device *cdev)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+ struct device *dev = thermal->bus_info->dev;
+ int i, err;
+
+ /* If the cooling device is one of ours bind it */
+ if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+ return 0;
+
+ for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+ const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
+
+ err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
+ trip->max_state,
+ trip->min_state,
+ THERMAL_WEIGHT_DEFAULT);
+ if (err < 0) {
+ dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
+ return err;
+ }
+ }
+ return 0;
+}
+
+static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
+ struct thermal_cooling_device *cdev)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+ struct device *dev = thermal->bus_info->dev;
+ int i;
+ int err;
+
+ /* If the cooling device is our one unbind it */
+ if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+ return 0;
+
+ for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+ err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
+ if (err < 0) {
+ dev_err(dev, "Failed to unbind cooling device\n");
+ return err;
+ }
+ }
+ return 0;
+}
+
+static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
+ enum thermal_device_mode *mode)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ *mode = thermal->mode;
+
+ return 0;
+}
+
+static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
+ enum thermal_device_mode mode)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ mutex_lock(&tzdev->lock);
+
+ if (mode == THERMAL_DEVICE_ENABLED)
+ tzdev->polling_delay = MLXSW_THERMAL_POLL_INT;
+ else
+ tzdev->polling_delay = 0;
+
+ mutex_unlock(&tzdev->lock);
+
+ thermal->mode = mode;
+ thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
+
+ return 0;
+}
+
+static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
+ int *p_temp)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+ struct device *dev = thermal->bus_info->dev;
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
+ unsigned int temp;
+ int err;
+
+ mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
+
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
+ if (err) {
+ dev_err(dev, "Failed to query temp sensor\n");
+ return err;
+ }
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
+
+ *p_temp = (int) temp;
+ return 0;
+}
+
+static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
+ int trip,
+ enum thermal_trip_type *p_type)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+ return -EINVAL;
+
+ *p_type = thermal->trips[trip].type;
+ return 0;
+}
+
+static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
+ int trip, int *p_temp)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+ return -EINVAL;
+
+ *p_temp = thermal->trips[trip].temp;
+ return 0;
+}
+
+static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
+ int trip, int temp)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
+ temp > MLXSW_THERMAL_MAX_TEMP)
+ return -EINVAL;
+
+ thermal->trips[trip].temp = temp;
+ return 0;
+}
+
+static struct thermal_zone_device_ops mlxsw_thermal_ops = {
+ .bind = mlxsw_thermal_bind,
+ .unbind = mlxsw_thermal_unbind,
+ .get_mode = mlxsw_thermal_get_mode,
+ .set_mode = mlxsw_thermal_set_mode,
+ .get_temp = mlxsw_thermal_get_temp,
+ .get_trip_type = mlxsw_thermal_get_trip_type,
+ .get_trip_temp = mlxsw_thermal_get_trip_temp,
+ .set_trip_temp = mlxsw_thermal_set_trip_temp,
+};
+
+static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *p_state)
+{
+ *p_state = MLXSW_THERMAL_MAX_STATE;
+ return 0;
+}
+
+static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *p_state)
+
+{
+ struct mlxsw_thermal *thermal = cdev->devdata;
+ struct device *dev = thermal->bus_info->dev;
+ char mfsc_pl[MLXSW_REG_MFSC_LEN];
+ int err, idx;
+ u8 duty;
+
+ idx = mlxsw_get_cooling_device_idx(thermal, cdev);
+ if (idx < 0)
+ return idx;
+
+ mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
+ if (err) {
+ dev_err(dev, "Failed to query PWM duty\n");
+ return err;
+ }
+
+ duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
+ *p_state = mlxsw_duty_to_state(duty);
+ return 0;
+}
+
+static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+
+{
+ struct mlxsw_thermal *thermal = cdev->devdata;
+ struct device *dev = thermal->bus_info->dev;
+ char mfsc_pl[MLXSW_REG_MFSC_LEN];
+ int err, idx;
+
+ idx = mlxsw_get_cooling_device_idx(thermal, cdev);
+ if (idx < 0)
+ return idx;
+
+ mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
+ err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
+ if (err) {
+ dev_err(dev, "Failed to write PWM duty\n");
+ return err;
+ }
+ return 0;
+}
+
+static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
+ .get_max_state = mlxsw_thermal_get_max_state,
+ .get_cur_state = mlxsw_thermal_get_cur_state,
+ .set_cur_state = mlxsw_thermal_set_cur_state,
+};
+
+int mlxsw_thermal_init(struct mlxsw_core *core,
+ const struct mlxsw_bus_info *bus_info,
+ struct mlxsw_thermal **p_thermal)
+{
+ char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
+ enum mlxsw_reg_mfcr_pwm_frequency freq;
+ struct device *dev = bus_info->dev;
+ struct mlxsw_thermal *thermal;
+ u16 tacho_active;
+ u8 pwm_active;
+ int err, i;
+
+ thermal = devm_kzalloc(dev, sizeof(*thermal),
+ GFP_KERNEL);
+ if (!thermal)
+ return -ENOMEM;
+
+ thermal->core = core;
+ thermal->bus_info = bus_info;
+ memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
+
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
+ if (err) {
+ dev_err(dev, "Failed to probe PWMs\n");
+ goto err_free_thermal;
+ }
+ mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
+
+ for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
+ if (tacho_active & BIT(i)) {
+ char mfsl_pl[MLXSW_REG_MFSL_LEN];
+
+ mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
+
+ /* We need to query the register to preserve maximum */
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
+ mfsl_pl);
+ if (err)
+ goto err_free_thermal;
+
+ /* set the minimal RPMs to 0 */
+ mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
+ err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
+ mfsl_pl);
+ if (err)
+ goto err_free_thermal;
+ }
+ }
+ for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
+ if (pwm_active & BIT(i)) {
+ struct thermal_cooling_device *cdev;
+
+ cdev = thermal_cooling_device_register("Fan", thermal,
+ &mlxsw_cooling_ops);
+ if (IS_ERR(cdev)) {
+ err = PTR_ERR(cdev);
+ dev_err(dev, "Failed to register cooling device\n");
+ goto err_unreg_cdevs;
+ }
+ thermal->cdevs[i] = cdev;
+ }
+ }
+
+ thermal->tzdev = thermal_zone_device_register("mlxsw",
+ MLXSW_THERMAL_NUM_TRIPS,
+ MLXSW_THERMAL_TRIP_MASK,
+ thermal,
+ &mlxsw_thermal_ops,
+ NULL, 0,
+ MLXSW_THERMAL_POLL_INT);
+ if (IS_ERR(thermal->tzdev)) {
+ err = PTR_ERR(thermal->tzdev);
+ dev_err(dev, "Failed to register thermal zone\n");
+ goto err_unreg_cdevs;
+ }
+
+ thermal->mode = THERMAL_DEVICE_ENABLED;
+ *p_thermal = thermal;
+ return 0;
+err_unreg_cdevs:
+ for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
+ if (thermal->cdevs[i])
+ thermal_cooling_device_unregister(thermal->cdevs[i]);
+err_free_thermal:
+ devm_kfree(dev, thermal);
+ return err;
+}
+
+void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
+{
+ int i;
+
+ if (thermal->tzdev) {
+ thermal_zone_device_unregister(thermal->tzdev);
+ thermal->tzdev = NULL;
+ }
+
+ for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
+ if (thermal->cdevs[i]) {
+ thermal_cooling_device_unregister(thermal->cdevs[i]);
+ thermal->cdevs[i] = NULL;
+ }
+ }
+
+ devm_kfree(thermal->bus_info->dev, thermal);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
new file mode 100644
index 000000000000..e50c8db2602a
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -0,0 +1,582 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/i2c.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include "cmd.h"
+#include "core.h"
+#include "i2c.h"
+
+static const char mlxsw_i2c_driver_name[] = "mlxsw_i2c";
+
+#define MLXSW_I2C_CIR2_BASE 0x72000
+#define MLXSW_I2C_CIR_STATUS_OFF 0x18
+#define MLXSW_I2C_CIR2_OFF_STATUS (MLXSW_I2C_CIR2_BASE + \
+ MLXSW_I2C_CIR_STATUS_OFF)
+#define MLXSW_I2C_OPMOD_SHIFT 12
+#define MLXSW_I2C_GO_BIT_SHIFT 23
+#define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT 24
+#define MLXSW_I2C_GO_BIT BIT(MLXSW_I2C_GO_BIT_SHIFT)
+#define MLXSW_I2C_GO_OPMODE BIT(MLXSW_I2C_OPMOD_SHIFT)
+#define MLXSW_I2C_SET_IMM_CMD (MLXSW_I2C_GO_OPMODE | \
+ MLXSW_CMD_OPCODE_QUERY_FW)
+#define MLXSW_I2C_PUSH_IMM_CMD (MLXSW_I2C_GO_BIT | \
+ MLXSW_I2C_SET_IMM_CMD)
+#define MLXSW_I2C_SET_CMD (MLXSW_CMD_OPCODE_ACCESS_REG)
+#define MLXSW_I2C_PUSH_CMD (MLXSW_I2C_GO_BIT | MLXSW_I2C_SET_CMD)
+#define MLXSW_I2C_TLV_HDR_SIZE 0x10
+#define MLXSW_I2C_ADDR_WIDTH 4
+#define MLXSW_I2C_PUSH_CMD_SIZE (MLXSW_I2C_ADDR_WIDTH + 4)
+#define MLXSW_I2C_READ_SEMA_SIZE 4
+#define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28)
+#define MLXSW_I2C_MBOX_SIZE 20
+#define MLXSW_I2C_MBOX_OUT_PARAM_OFF 12
+#define MLXSW_I2C_MAX_BUFF_SIZE 32
+#define MLXSW_I2C_MBOX_OFFSET_BITS 20
+#define MLXSW_I2C_MBOX_SIZE_BITS 12
+#define MLXSW_I2C_ADDR_BUF_SIZE 4
+#define MLXSW_I2C_BLK_MAX 32
+#define MLXSW_I2C_RETRY 5
+#define MLXSW_I2C_TIMEOUT_MSECS 5000
+
+/**
+ * struct mlxsw_i2c - device private data:
+ * @cmd.mb_size_in: input mailbox size;
+ * @cmd.mb_off_in: input mailbox offset in register space;
+ * @cmd.mb_size_out: output mailbox size;
+ * @cmd.mb_off_out: output mailbox offset in register space;
+ * @cmd.lock: command execution lock;
+ * @dev: I2C device;
+ * @core: switch core pointer;
+ * @bus_info: bus info block;
+ */
+struct mlxsw_i2c {
+ struct {
+ u32 mb_size_in;
+ u32 mb_off_in;
+ u32 mb_size_out;
+ u32 mb_off_out;
+ struct mutex lock;
+ } cmd;
+ struct device *dev;
+ struct mlxsw_core *core;
+ struct mlxsw_bus_info bus_info;
+};
+
+#define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \
+ { .addr = (_client)->addr, \
+ .buf = (_addr_buf), \
+ .len = MLXSW_I2C_ADDR_BUF_SIZE, \
+ .flags = 0 }, \
+ { .addr = (_client)->addr, \
+ .buf = (_buf), \
+ .len = (_len), \
+ .flags = I2C_M_RD } }
+
+#define MLXSW_I2C_WRITE_MSG(_client, _buf, _len) \
+ { .addr = (_client)->addr, \
+ .buf = (u8 *)(_buf), \
+ .len = (_len), \
+ .flags = 0 }
+
+/* Routine converts in and out mail boxes offset and size. */
+static inline void
+mlxsw_i2c_convert_mbox(struct mlxsw_i2c *mlxsw_i2c, u8 *buf)
+{
+ u32 tmp;
+
+ /* Local in/out mailboxes: 20 bits for offset, 12 for size */
+ tmp = be32_to_cpup((__be32 *) buf);
+ mlxsw_i2c->cmd.mb_off_in = tmp &
+ GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0);
+ mlxsw_i2c->cmd.mb_size_in = (tmp & GENMASK(31,
+ MLXSW_I2C_MBOX_OFFSET_BITS)) >>
+ MLXSW_I2C_MBOX_OFFSET_BITS;
+
+ tmp = be32_to_cpup((__be32 *) (buf + MLXSW_I2C_ADDR_WIDTH));
+ mlxsw_i2c->cmd.mb_off_out = tmp &
+ GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0);
+ mlxsw_i2c->cmd.mb_size_out = (tmp & GENMASK(31,
+ MLXSW_I2C_MBOX_OFFSET_BITS)) >>
+ MLXSW_I2C_MBOX_OFFSET_BITS;
+}
+
+/* Routine obtains register size from mail box buffer. */
+static inline int mlxsw_i2c_get_reg_size(u8 *in_mbox)
+{
+ u16 tmp = be16_to_cpup((__be16 *) (in_mbox + MLXSW_I2C_TLV_HDR_SIZE));
+
+ return (tmp & 0x7ff) * 4 + MLXSW_I2C_TLV_HDR_SIZE;
+}
+
+/* Routine sets I2C device internal offset in the transaction buffer. */
+static inline void mlxsw_i2c_set_slave_addr(u8 *buf, u32 off)
+{
+ __be32 *val = (__be32 *) buf;
+
+ *val = htonl(off);
+}
+
+/* Routine waits until go bit is cleared. */
+static int mlxsw_i2c_wait_go_bit(struct i2c_client *client,
+ struct mlxsw_i2c *mlxsw_i2c, u8 *p_status)
+{
+ u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+ u8 buf[MLXSW_I2C_READ_SEMA_SIZE];
+ int len = MLXSW_I2C_READ_SEMA_SIZE;
+ struct i2c_msg read_sema[] =
+ MLXSW_I2C_READ_MSG(client, addr_buf, buf, len);
+ bool wait_done = false;
+ unsigned long end;
+ int i = 0, err;
+
+ mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_OFF_STATUS);
+
+ end = jiffies + msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+ do {
+ u32 ctrl;
+
+ err = i2c_transfer(client->adapter, read_sema,
+ ARRAY_SIZE(read_sema));
+
+ ctrl = be32_to_cpu(*(__be32 *) buf);
+ if (err == ARRAY_SIZE(read_sema)) {
+ if (!(ctrl & MLXSW_I2C_GO_BIT)) {
+ wait_done = true;
+ *p_status = ctrl >>
+ MLXSW_I2C_CIR_CTRL_STATUS_SHIFT;
+ break;
+ }
+ }
+ cond_resched();
+ } while ((time_before(jiffies, end)) || (i++ < MLXSW_I2C_RETRY));
+
+ if (wait_done) {
+ if (*p_status)
+ err = -EIO;
+ } else {
+ return -ETIMEDOUT;
+ }
+
+ return err > 0 ? 0 : err;
+}
+
+/* Routine posts a command to ASIC though mail box. */
+static int mlxsw_i2c_write_cmd(struct i2c_client *client,
+ struct mlxsw_i2c *mlxsw_i2c,
+ int immediate)
+{
+ __be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = {
+ 0, cpu_to_be32(MLXSW_I2C_PUSH_IMM_CMD)
+ };
+ __be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = {
+ 0, 0, 0, 0, 0, 0,
+ cpu_to_be32(client->adapter->nr & 0xffff),
+ cpu_to_be32(MLXSW_I2C_SET_IMM_CMD)
+ };
+ struct i2c_msg push_cmd =
+ MLXSW_I2C_WRITE_MSG(client, push_cmd_buf,
+ MLXSW_I2C_PUSH_CMD_SIZE);
+ struct i2c_msg prep_cmd =
+ MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE);
+ int err;
+
+ if (!immediate) {
+ push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_CMD);
+ prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_SET_CMD);
+ }
+ mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf,
+ MLXSW_I2C_CIR2_BASE);
+ mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf,
+ MLXSW_I2C_CIR2_OFF_STATUS);
+
+ /* Prepare Command Interface Register for transaction */
+ err = i2c_transfer(client->adapter, &prep_cmd, 1);
+ if (err < 0)
+ return err;
+ else if (err != 1)
+ return -EIO;
+
+ /* Write out Command Interface Register GO bit to push transaction */
+ err = i2c_transfer(client->adapter, &push_cmd, 1);
+ if (err < 0)
+ return err;
+ else if (err != 1)
+ return -EIO;
+
+ return 0;
+}
+
+/* Routine obtains mail box offsets from ASIC register space. */
+static int mlxsw_i2c_get_mbox(struct i2c_client *client,
+ struct mlxsw_i2c *mlxsw_i2c)
+{
+ u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+ u8 buf[MLXSW_I2C_MBOX_SIZE];
+ struct i2c_msg mbox_cmd[] =
+ MLXSW_I2C_READ_MSG(client, addr_buf, buf, MLXSW_I2C_MBOX_SIZE);
+ int err;
+
+ /* Read mail boxes offsets. */
+ mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_BASE);
+ err = i2c_transfer(client->adapter, mbox_cmd, 2);
+ if (err != 2) {
+ dev_err(&client->dev, "Could not obtain mail boxes\n");
+ if (!err)
+ return -EIO;
+ else
+ return err;
+ }
+
+ /* Convert mail boxes. */
+ mlxsw_i2c_convert_mbox(mlxsw_i2c, &buf[MLXSW_I2C_MBOX_OUT_PARAM_OFF]);
+
+ return err;
+}
+
+/* Routine sends I2C write transaction to ASIC device. */
+static int
+mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
+ u8 *p_status)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+ unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+ u8 tran_buf[MLXSW_I2C_MAX_BUFF_SIZE + MLXSW_I2C_ADDR_BUF_SIZE];
+ int off = mlxsw_i2c->cmd.mb_off_in, chunk_size, i, j;
+ unsigned long end;
+ struct i2c_msg write_tran =
+ MLXSW_I2C_WRITE_MSG(client, tran_buf, MLXSW_I2C_PUSH_CMD_SIZE);
+ int err;
+
+ for (i = 0; i < num; i++) {
+ chunk_size = (in_mbox_size > MLXSW_I2C_BLK_MAX) ?
+ MLXSW_I2C_BLK_MAX : in_mbox_size;
+ write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size;
+ mlxsw_i2c_set_slave_addr(tran_buf, off);
+ memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox +
+ chunk_size * i, chunk_size);
+
+ j = 0;
+ end = jiffies + timeout;
+ do {
+ err = i2c_transfer(client->adapter, &write_tran, 1);
+ if (err == 1)
+ break;
+
+ cond_resched();
+ } while ((time_before(jiffies, end)) ||
+ (j++ < MLXSW_I2C_RETRY));
+
+ if (err != 1) {
+ if (!err)
+ err = -EIO;
+ return err;
+ }
+
+ off += chunk_size;
+ in_mbox_size -= chunk_size;
+ }
+
+ /* Prepare and write out Command Interface Register for transaction. */
+ err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 0);
+ if (err) {
+ dev_err(&client->dev, "Could not start transaction");
+ return -EIO;
+ }
+
+ /* Wait until go bit is cleared. */
+ err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, p_status);
+ if (err) {
+ dev_err(&client->dev, "HW semaphore is not released");
+ return err;
+ }
+
+ /* Validate transaction completion status. */
+ if (*p_status) {
+ dev_err(&client->dev, "Bad transaction completion status %x\n",
+ *p_status);
+ return -EIO;
+ }
+
+ return err > 0 ? 0 : err;
+}
+
+/* Routine executes I2C command. */
+static int
+mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
+ size_t out_mbox_size, u8 *out_mbox, u8 *status)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+ unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+ u8 tran_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+ int num, chunk_size, reg_size, i, j;
+ int off = mlxsw_i2c->cmd.mb_off_out;
+ unsigned long end;
+ struct i2c_msg read_tran[] =
+ MLXSW_I2C_READ_MSG(client, tran_buf, NULL, 0);
+ int err;
+
+ WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32));
+
+ reg_size = mlxsw_i2c_get_reg_size(in_mbox);
+ num = reg_size / MLXSW_I2C_BLK_MAX;
+ if (reg_size % MLXSW_I2C_BLK_MAX)
+ num++;
+
+ if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
+ dev_err(&client->dev, "Could not acquire lock");
+ return -EINVAL;
+ }
+
+ err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
+ if (err)
+ goto cmd_fail;
+
+ /* No out mailbox is case of write transaction. */
+ if (!out_mbox) {
+ mutex_unlock(&mlxsw_i2c->cmd.lock);
+ return 0;
+ }
+
+ /* Send read transaction to get output mailbox content. */
+ read_tran[1].buf = out_mbox;
+ for (i = 0; i < num; i++) {
+ chunk_size = (reg_size > MLXSW_I2C_BLK_MAX) ?
+ MLXSW_I2C_BLK_MAX : reg_size;
+ read_tran[1].len = chunk_size;
+ mlxsw_i2c_set_slave_addr(tran_buf, off);
+
+ j = 0;
+ end = jiffies + timeout;
+ do {
+ err = i2c_transfer(client->adapter, read_tran,
+ ARRAY_SIZE(read_tran));
+ if (err == ARRAY_SIZE(read_tran))
+ break;
+
+ cond_resched();
+ } while ((time_before(jiffies, end)) ||
+ (j++ < MLXSW_I2C_RETRY));
+
+ if (err != ARRAY_SIZE(read_tran)) {
+ if (!err)
+ err = -EIO;
+
+ goto cmd_fail;
+ }
+
+ off += chunk_size;
+ reg_size -= chunk_size;
+ read_tran[1].buf += chunk_size;
+ }
+
+ mutex_unlock(&mlxsw_i2c->cmd.lock);
+
+ return 0;
+
+cmd_fail:
+ mutex_unlock(&mlxsw_i2c->cmd.lock);
+ return err;
+}
+
+static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
+ u32 in_mod, bool out_mbox_direct,
+ char *in_mbox, size_t in_mbox_size,
+ char *out_mbox, size_t out_mbox_size,
+ u8 *status)
+{
+ struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+ return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox,
+ out_mbox_size, out_mbox, status);
+}
+
+static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv,
+ const struct mlxsw_tx_info *tx_info)
+{
+ return false;
+}
+
+static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb,
+ const struct mlxsw_tx_info *tx_info)
+{
+ return 0;
+}
+
+static int
+mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_config_profile *profile,
+ struct mlxsw_res *resources)
+{
+ struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+ mlxsw_i2c->core = mlxsw_core;
+
+ return 0;
+}
+
+static void mlxsw_i2c_fini(void *bus_priv)
+{
+ struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+ mlxsw_i2c->core = NULL;
+}
+
+static const struct mlxsw_bus mlxsw_i2c_bus = {
+ .kind = "i2c",
+ .init = mlxsw_i2c_init,
+ .fini = mlxsw_i2c_fini,
+ .skb_transmit_busy = mlxsw_i2c_skb_transmit_busy,
+ .skb_transmit = mlxsw_i2c_skb_transmit,
+ .cmd_exec = mlxsw_i2c_cmd_exec,
+};
+
+static int mlxsw_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mlxsw_i2c *mlxsw_i2c;
+ u8 status;
+ int err;
+
+ mlxsw_i2c = devm_kzalloc(&client->dev, sizeof(*mlxsw_i2c), GFP_KERNEL);
+ if (!mlxsw_i2c)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, mlxsw_i2c);
+ mutex_init(&mlxsw_i2c->cmd.lock);
+
+ /* In order to use mailboxes through the i2c, special area is reserved
+ * on the i2c address space that can be used for input and output
+ * mailboxes. Such mailboxes are called local mailboxes. When using a
+ * local mailbox, software should specify 0 as the Input/Output
+ * parameters. The location of the Local Mailbox addresses on the i2c
+ * space can be retrieved through the QUERY_FW command.
+ * For this purpose QUERY_FW is to be issued with opcode modifier equal
+ * 0x01. For such command the output parameter is an immediate value.
+ * Here QUERY_FW command is invoked for ASIC probing and for getting
+ * local mailboxes addresses from immedate output parameters.
+ */
+
+ /* Prepare and write out Command Interface Register for transaction */
+ err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 1);
+ if (err) {
+ dev_err(&client->dev, "Could not start transaction");
+ goto errout;
+ }
+
+ /* Wait until go bit is cleared. */
+ err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status);
+ if (err) {
+ dev_err(&client->dev, "HW semaphore is not released");
+ goto errout;
+ }
+
+ /* Validate transaction completion status. */
+ if (status) {
+ dev_err(&client->dev, "Bad transaction completion status %x\n",
+ status);
+ err = -EIO;
+ goto errout;
+ }
+
+ /* Get mailbox offsets. */
+ err = mlxsw_i2c_get_mbox(client, mlxsw_i2c);
+ if (err < 0) {
+ dev_err(&client->dev, "Fail to get mailboxes\n");
+ goto errout;
+ }
+
+ dev_info(&client->dev, "%s mb size=%x off=0x%08x out mb size=%x off=0x%08x\n",
+ id->name, mlxsw_i2c->cmd.mb_size_in,
+ mlxsw_i2c->cmd.mb_off_in, mlxsw_i2c->cmd.mb_size_out,
+ mlxsw_i2c->cmd.mb_off_out);
+
+ /* Register device bus. */
+ mlxsw_i2c->bus_info.device_kind = id->name;
+ mlxsw_i2c->bus_info.device_name = client->name;
+ mlxsw_i2c->bus_info.dev = &client->dev;
+ mlxsw_i2c->dev = &client->dev;
+
+ err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
+ &mlxsw_i2c_bus, mlxsw_i2c);
+ if (err) {
+ dev_err(&client->dev, "Fail to register core bus\n");
+ return err;
+ }
+
+ return 0;
+
+errout:
+ i2c_set_clientdata(client, NULL);
+
+ return err;
+}
+
+static int mlxsw_i2c_remove(struct i2c_client *client)
+{
+ struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+
+ mlxsw_core_bus_device_unregister(mlxsw_i2c->core);
+ mutex_destroy(&mlxsw_i2c->cmd.lock);
+
+ return 0;
+}
+
+int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
+{
+ i2c_driver->probe = mlxsw_i2c_probe;
+ i2c_driver->remove = mlxsw_i2c_remove;
+ return i2c_add_driver(i2c_driver);
+}
+EXPORT_SYMBOL(mlxsw_i2c_driver_register);
+
+void mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver)
+{
+ i2c_del_driver(i2c_driver);
+}
+EXPORT_SYMBOL(mlxsw_i2c_driver_unregister);
+
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox switch I2C interface driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.h b/drivers/net/ethernet/mellanox/mlxsw/i2c.h
new file mode 100644
index 000000000000..daa24b213ea4
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.h
@@ -0,0 +1,60 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/i2c.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@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_I2C_H
+#define _MLXSW_I2C_H
+
+#include <linux/i2c.h>
+
+#if IS_ENABLED(CONFIG_MLXSW_I2C)
+
+int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver);
+void mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver);
+
+#else
+
+static inline int
+mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
+{
+ return -ENODEV;
+}
+
+static inline void
+mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver)
+{
+}
+
+#endif
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/ib.h b/drivers/net/ethernet/mellanox/mlxsw/ib.h
new file mode 100644
index 000000000000..ce313aaa6336
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/ib.h
@@ -0,0 +1,39 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/ib.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 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_IB_H
+#define _MLXSW_IB_H
+
+#define MLXSW_IB_DEFAULT_MTU 4096
+
+#endif /* _MLXSW_IB_H */
diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h
index a94dbda6590b..3c95e3ddd9c2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/item.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/item.h
@@ -55,7 +55,7 @@ struct mlxsw_item {
};
static inline unsigned int
-__mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
+__mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index,
size_t typesize)
{
BUG_ON(index && !item->step);
@@ -72,7 +72,8 @@ __mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
typesize);
}
-static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
+static inline u16 __mlxsw_item_get16(const char *buf,
+ const struct mlxsw_item *item,
unsigned short index)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));
@@ -87,7 +88,7 @@ static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
return tmp;
}
-static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item,
unsigned short index, u16 val)
{
unsigned int offset = __mlxsw_item_offset(item, index,
@@ -105,7 +106,8 @@ static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
b[offset] = cpu_to_be16(tmp);
}
-static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
+static inline u32 __mlxsw_item_get32(const char *buf,
+ const struct mlxsw_item *item,
unsigned short index)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));
@@ -120,7 +122,7 @@ static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
return tmp;
}
-static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item,
unsigned short index, u32 val)
{
unsigned int offset = __mlxsw_item_offset(item, index,
@@ -138,7 +140,8 @@ static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
b[offset] = cpu_to_be32(tmp);
}
-static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
+static inline u64 __mlxsw_item_get64(const char *buf,
+ const struct mlxsw_item *item,
unsigned short index)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -153,7 +156,7 @@ static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
return tmp;
}
-static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item,
unsigned short index, u64 val)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -170,8 +173,8 @@ static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
b[offset] = cpu_to_be64(tmp);
}
-static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
- struct mlxsw_item *item,
+static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst,
+ const struct mlxsw_item *item,
unsigned short index)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -180,7 +183,7 @@ static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
}
static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
- struct mlxsw_item *item,
+ const struct mlxsw_item *item,
unsigned short index)
{
unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -189,7 +192,8 @@ static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
}
static inline u16
-__mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
+__mlxsw_item_bit_array_offset(const struct mlxsw_item *item,
+ u16 index, u8 *shift)
{
u16 max_index, be_index;
u16 offset; /* byte offset inside the array */
@@ -212,7 +216,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
return item->offset + offset;
}
-static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
+static inline u8 __mlxsw_item_bit_array_get(const char *buf,
+ const struct mlxsw_item *item,
u16 index)
{
u8 shift, tmp;
@@ -224,7 +229,8 @@ static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
return tmp;
}
-static inline void __mlxsw_item_bit_array_set(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_bit_array_set(char *buf,
+ const struct mlxsw_item *item,
u16 index, u8 val)
{
u8 shift, tmp;
@@ -254,7 +260,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.size = {.bits = _sizebits,}, \
.name = #_type "_" #_cname "_" #_iname, \
}; \
-static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \
+static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \
{ \
return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
} \
@@ -275,7 +281,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline u16 \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
{ \
return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), \
index); \
@@ -295,7 +301,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.size = {.bits = _sizebits,}, \
.name = #_type "_" #_cname "_" #_iname, \
}; \
-static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \
+static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \
{ \
return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
} \
@@ -316,7 +322,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline u32 \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
{ \
return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), \
index); \
@@ -336,7 +342,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.size = {.bits = _sizebits,}, \
.name = #_type "_" #_cname "_" #_iname, \
}; \
-static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf) \
+static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf) \
{ \
return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
} \
@@ -357,7 +363,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline u64 \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index) \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
{ \
return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), \
index); \
@@ -377,7 +383,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline void \
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst) \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst) \
{ \
__mlxsw_item_memcpy_from(buf, dst, \
&__ITEM_NAME(_type, _cname, _iname), 0); \
@@ -399,7 +405,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline void \
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, \
unsigned short index, \
char *dst) \
{ \
@@ -424,7 +430,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \
.name = #_type "_" #_cname "_" #_iname, \
}; \
static inline u8 \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, u16 index) \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index) \
{ \
return __mlxsw_item_bit_array_get(buf, \
&__ITEM_NAME(_type, _cname, _iname), \
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
new file mode 100644
index 000000000000..3dd16267b76c
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -0,0 +1,97 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/minimal.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@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/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/types.h>
+
+#include "core.h"
+#include "i2c.h"
+
+static const char mlxsw_minimal_driver_name[] = "mlxsw_minimal";
+
+static const struct mlxsw_config_profile mlxsw_minimal_config_profile;
+
+static struct mlxsw_driver mlxsw_minimal_driver = {
+ .kind = mlxsw_minimal_driver_name,
+ .priv_size = 1,
+ .profile = &mlxsw_minimal_config_profile,
+};
+
+static const struct i2c_device_id mlxsw_minimal_i2c_id[] = {
+ { "mlxsw_minimal", 0},
+ { },
+};
+
+static struct i2c_driver mlxsw_minimal_i2c_driver = {
+ .driver.name = "mlxsw_minimal",
+ .class = I2C_CLASS_HWMON,
+ .id_table = mlxsw_minimal_i2c_id,
+};
+
+static int __init mlxsw_minimal_module_init(void)
+{
+ int err;
+
+ err = mlxsw_core_driver_register(&mlxsw_minimal_driver);
+ if (err)
+ return err;
+
+ err = mlxsw_i2c_driver_register(&mlxsw_minimal_i2c_driver);
+ if (err)
+ goto err_i2c_driver_register;
+
+ return 0;
+
+err_i2c_driver_register:
+ mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+
+ return err;
+}
+
+static void __exit mlxsw_minimal_module_exit(void)
+{
+ mlxsw_i2c_driver_unregister(&mlxsw_minimal_i2c_driver);
+ mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+}
+
+module_init(mlxsw_minimal_module_init);
+module_exit(mlxsw_minimal_module_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox minimal driver");
+MODULE_DEVICE_TABLE(i2c, mlxsw_minimal_i2c_id);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 912f71f84209..a223c85dfde0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -48,33 +48,17 @@
#include <linux/seq_file.h>
#include <linux/string.h>
+#include "pci_hw.h"
#include "pci.h"
#include "core.h"
#include "cmd.h"
#include "port.h"
+#include "resources.h"
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, }
-};
-
static struct dentry *mlxsw_pci_dbg_root;
-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();
- }
-}
-
#define mlxsw_pci_write32(mlxsw_pci, reg, val) \
iowrite32be(val, (mlxsw_pci)->hw_addr + (MLXSW_PCI_ ## reg))
#define mlxsw_pci_read32(mlxsw_pci, reg) \
@@ -238,8 +222,9 @@ static bool mlxsw_pci_elem_hw_owned(struct mlxsw_pci_queue *q, bool owner_bit)
return owner_bit != !!(q->consumer_counter & q->count);
}
-static char *mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
- u32 (*get_elem_owner_func)(char *))
+static char *
+mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
+ u32 (*get_elem_owner_func)(const char *))
{
struct mlxsw_pci_queue_elem_info *elem_info;
char *elem;
@@ -1154,76 +1139,8 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci,
mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask);
}
-#define MLXSW_RESOURCES_TABLE_END_ID 0xffff
-#define MLXSW_MAX_SPAN_ID 0x2420
-#define MLXSW_MAX_LAG_ID 0x2520
-#define MLXSW_MAX_PORTS_IN_LAG_ID 0x2521
-#define MLXSW_KVD_SIZE_ID 0x1001
-#define MLXSW_KVD_SINGLE_MIN_SIZE_ID 0x1002
-#define MLXSW_KVD_DOUBLE_MIN_SIZE_ID 0x1003
-#define MLXSW_MAX_VIRTUAL_ROUTERS_ID 0x2C01
-#define MLXSW_MAX_SYSTEM_PORT_ID 0x2502
-#define MLXSW_MAX_VLAN_GROUPS_ID 0x2906
-#define MLXSW_MAX_REGIONS_ID 0x2901
-#define MLXSW_MAX_RIF_ID 0x2C02
-#define MLXSW_RESOURCES_QUERY_MAX_QUERIES 100
-#define MLXSW_RESOURCES_PER_QUERY 32
-
-static void mlxsw_pci_resources_query_parse(int id, u64 val,
- struct mlxsw_resources *resources)
-{
- switch (id) {
- case MLXSW_MAX_SPAN_ID:
- resources->max_span = val;
- resources->max_span_valid = 1;
- break;
- case MLXSW_MAX_LAG_ID:
- resources->max_lag = val;
- resources->max_lag_valid = 1;
- break;
- case MLXSW_MAX_PORTS_IN_LAG_ID:
- resources->max_ports_in_lag = val;
- resources->max_ports_in_lag_valid = 1;
- break;
- case MLXSW_KVD_SIZE_ID:
- resources->kvd_size = val;
- resources->kvd_size_valid = 1;
- break;
- case MLXSW_KVD_SINGLE_MIN_SIZE_ID:
- resources->kvd_single_min_size = val;
- resources->kvd_single_min_size_valid = 1;
- break;
- case MLXSW_KVD_DOUBLE_MIN_SIZE_ID:
- resources->kvd_double_min_size = val;
- resources->kvd_double_min_size_valid = 1;
- break;
- case MLXSW_MAX_VIRTUAL_ROUTERS_ID:
- resources->max_virtual_routers = val;
- resources->max_virtual_routers_valid = 1;
- break;
- case MLXSW_MAX_SYSTEM_PORT_ID:
- resources->max_system_ports = val;
- resources->max_system_ports_valid = 1;
- break;
- case MLXSW_MAX_VLAN_GROUPS_ID:
- resources->max_vlan_groups = val;
- resources->max_vlan_groups_valid = 1;
- break;
- case MLXSW_MAX_REGIONS_ID:
- resources->max_regions = val;
- resources->max_regions_valid = 1;
- break;
- case MLXSW_MAX_RIF_ID:
- resources->max_rif = val;
- resources->max_rif_valid = 1;
- break;
- default:
- break;
- }
-}
-
static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
- struct mlxsw_resources *resources,
+ struct mlxsw_res *res,
u8 query_enabled)
{
int index, i;
@@ -1237,19 +1154,20 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
mlxsw_cmd_mbox_zero(mbox);
- for (index = 0; index < MLXSW_RESOURCES_QUERY_MAX_QUERIES; index++) {
+ for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
+ index++) {
err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index);
if (err)
return err;
- for (i = 0; i < MLXSW_RESOURCES_PER_QUERY; i++) {
+ for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
- if (id == MLXSW_RESOURCES_TABLE_END_ID)
+ if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
return 0;
- mlxsw_pci_resources_query_parse(id, data, resources);
+ mlxsw_res_parse(res, id, data);
}
}
@@ -1259,13 +1177,14 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
return -EIO;
}
-static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
- struct mlxsw_resources *resources)
+static int
+mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
+ struct mlxsw_res *res)
{
- u32 singles_size, doubles_size, linear_size;
+ u32 single_size, double_size, linear_size;
- if (!resources->kvd_single_min_size_valid ||
- !resources->kvd_double_min_size_valid ||
+ if (!MLXSW_RES_VALID(res, KVD_SINGLE_MIN_SIZE) ||
+ !MLXSW_RES_VALID(res, KVD_DOUBLE_MIN_SIZE) ||
!profile->used_kvd_split_data)
return -EIO;
@@ -1277,31 +1196,31 @@ static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *pr
* Both sizes must be a multiplications of the
* granularity from the profile.
*/
- doubles_size = (resources->kvd_size - linear_size);
- doubles_size *= profile->kvd_hash_double_parts;
- doubles_size /= (profile->kvd_hash_double_parts +
- profile->kvd_hash_single_parts);
- doubles_size /= profile->kvd_hash_granularity;
- doubles_size *= profile->kvd_hash_granularity;
- singles_size = resources->kvd_size - doubles_size -
- linear_size;
+ double_size = MLXSW_RES_GET(res, KVD_SIZE) - linear_size;
+ double_size *= profile->kvd_hash_double_parts;
+ double_size /= profile->kvd_hash_double_parts +
+ profile->kvd_hash_single_parts;
+ double_size /= profile->kvd_hash_granularity;
+ double_size *= profile->kvd_hash_granularity;
+ single_size = MLXSW_RES_GET(res, KVD_SIZE) - double_size -
+ linear_size;
/* Check results are legal. */
- if (singles_size < resources->kvd_single_min_size ||
- doubles_size < resources->kvd_double_min_size ||
- resources->kvd_size < linear_size)
+ if (single_size < MLXSW_RES_GET(res, KVD_SINGLE_MIN_SIZE) ||
+ double_size < MLXSW_RES_GET(res, KVD_DOUBLE_MIN_SIZE) ||
+ MLXSW_RES_GET(res, KVD_SIZE) < linear_size)
return -EIO;
- resources->kvd_single_size = singles_size;
- resources->kvd_double_size = doubles_size;
- resources->kvd_linear_size = linear_size;
+ MLXSW_RES_SET(res, KVD_SINGLE_SIZE, single_size);
+ MLXSW_RES_SET(res, KVD_DOUBLE_SIZE, double_size);
+ MLXSW_RES_SET(res, KVD_LINEAR_SIZE, linear_size);
return 0;
}
static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
const struct mlxsw_config_profile *profile,
- struct mlxsw_resources *resources)
+ struct mlxsw_res *res)
{
int i;
int err;
@@ -1390,22 +1309,22 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
mlxsw_cmd_mbox_config_profile_adaptive_routing_group_cap_set(
mbox, profile->adaptive_routing_group_cap);
}
- if (resources->kvd_size_valid) {
- err = mlxsw_pci_profile_get_kvd_sizes(profile, resources);
+ if (MLXSW_RES_VALID(res, KVD_SIZE)) {
+ err = mlxsw_pci_profile_get_kvd_sizes(profile, res);
if (err)
return err;
mlxsw_cmd_mbox_config_profile_set_kvd_linear_size_set(mbox, 1);
mlxsw_cmd_mbox_config_profile_kvd_linear_size_set(mbox,
- resources->kvd_linear_size);
+ MLXSW_RES_GET(res, KVD_LINEAR_SIZE));
mlxsw_cmd_mbox_config_profile_set_kvd_hash_single_size_set(mbox,
1);
mlxsw_cmd_mbox_config_profile_kvd_hash_single_size_set(mbox,
- resources->kvd_single_size);
+ MLXSW_RES_GET(res, KVD_SINGLE_SIZE));
mlxsw_cmd_mbox_config_profile_set_kvd_hash_double_size_set(
mbox, 1);
mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox,
- resources->kvd_double_size);
+ MLXSW_RES_GET(res, KVD_DOUBLE_SIZE));
}
for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++)
@@ -1543,7 +1462,7 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci,
static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
const struct mlxsw_config_profile *profile,
- struct mlxsw_resources *resources)
+ struct mlxsw_res *res)
{
struct mlxsw_pci *mlxsw_pci = bus_priv;
struct pci_dev *pdev = mlxsw_pci->pdev;
@@ -1602,12 +1521,12 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
if (err)
goto err_boardinfo;
- err = mlxsw_pci_resources_query(mlxsw_pci, mbox, resources,
+ err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res,
profile->resource_query_enable);
if (err)
goto err_query_resources;
- err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, resources);
+ err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res);
if (err)
goto err_config_profile;
@@ -1617,7 +1536,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
err = request_irq(mlxsw_pci->msix_entry.vector,
mlxsw_pci_eq_irq_handler, 0,
- mlxsw_pci_driver_name, mlxsw_pci);
+ mlxsw_pci->bus_info.device_kind, mlxsw_pci);
if (err) {
dev_err(&pdev->dev, "IRQ request failed\n");
goto err_request_eq_irq;
@@ -1836,6 +1755,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
.skb_transmit_busy = mlxsw_pci_skb_transmit_busy,
.skb_transmit = mlxsw_pci_skb_transmit,
.cmd_exec = mlxsw_pci_cmd_exec,
+ .features = MLXSW_BUS_F_TXRX,
};
static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
@@ -1863,6 +1783,7 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ const char *driver_name = pdev->driver->name;
struct mlxsw_pci *mlxsw_pci;
int err;
@@ -1876,7 +1797,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_pci_enable_device;
}
- err = pci_request_regions(pdev, mlxsw_pci_driver_name);
+ err = pci_request_regions(pdev, driver_name);
if (err) {
dev_err(&pdev->dev, "pci_request_regions failed\n");
goto err_pci_request_regions;
@@ -1927,7 +1848,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_msix_init;
}
- mlxsw_pci->bus_info.device_kind = mlxsw_pci_device_kind_get(id);
+ mlxsw_pci->bus_info.device_kind = driver_name;
mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
mlxsw_pci->bus_info.dev = &pdev->dev;
@@ -1979,33 +1900,30 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
kfree(mlxsw_pci);
}
-static struct pci_driver mlxsw_pci_driver = {
- .name = mlxsw_pci_driver_name,
- .id_table = mlxsw_pci_id_table,
- .probe = mlxsw_pci_probe,
- .remove = mlxsw_pci_remove,
-};
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+ pci_driver->probe = mlxsw_pci_probe;
+ pci_driver->remove = mlxsw_pci_remove;
+ return pci_register_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_register);
-static int __init mlxsw_pci_module_init(void)
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
{
- int err;
+ pci_unregister_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_unregister);
+static int __init mlxsw_pci_module_init(void)
+{
mlxsw_pci_dbg_root = debugfs_create_dir(mlxsw_pci_driver_name, NULL);
if (!mlxsw_pci_dbg_root)
return -ENOMEM;
- err = pci_register_driver(&mlxsw_pci_driver);
- if (err)
- goto err_register_driver;
return 0;
-
-err_register_driver:
- debugfs_remove_recursive(mlxsw_pci_dbg_root);
- return err;
}
static void __exit mlxsw_pci_module_exit(void)
{
- pci_unregister_driver(&mlxsw_pci_driver);
debugfs_remove_recursive(mlxsw_pci_dbg_root);
}
@@ -2015,4 +1933,3 @@ module_exit(mlxsw_pci_module_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
MODULE_DESCRIPTION("Mellanox switch PCI interface driver");
-MODULE_DEVICE_TABLE(pci, mlxsw_pci_id_table);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h
index d942a3e6fa41..d65582325cd5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h
@@ -1,7 +1,7 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/pci.h
- * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 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:
@@ -35,197 +35,31 @@
#ifndef _MLXSW_PCI_H
#define _MLXSW_PCI_H
-#include <linux/bitops.h>
+#include <linux/pci.h>
-#include "item.h"
+#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738
+#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84
+#define PCI_DEVICE_ID_MELLANOX_SWITCHIB 0xcb20
+#define PCI_DEVICE_ID_MELLANOX_SWITCHIB2 0xcf08
-#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
+#if IS_ENABLED(CONFIG_MLXSW_PCI)
-#define MLXSW_PCI_CIR_BASE 0x71000
-#define MLXSW_PCI_CIR_IN_PARAM_HI MLXSW_PCI_CIR_BASE
-#define MLXSW_PCI_CIR_IN_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x04)
-#define MLXSW_PCI_CIR_IN_MODIFIER (MLXSW_PCI_CIR_BASE + 0x08)
-#define MLXSW_PCI_CIR_OUT_PARAM_HI (MLXSW_PCI_CIR_BASE + 0x0C)
-#define MLXSW_PCI_CIR_OUT_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x10)
-#define MLXSW_PCI_CIR_TOKEN (MLXSW_PCI_CIR_BASE + 0x14)
-#define MLXSW_PCI_CIR_CTRL (MLXSW_PCI_CIR_BASE + 0x18)
-#define MLXSW_PCI_CIR_CTRL_GO_BIT BIT(23)
-#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT BIT(22)
-#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT 12
-#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT 24
-#define MLXSW_PCI_CIR_TIMEOUT_MSECS 1000
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver);
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver);
-#define MLXSW_PCI_SW_RESET 0xF0010
-#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000
-#define MLXSW_PCI_FW_READY 0xA1844
-#define MLXSW_PCI_FW_READY_MASK 0xFF
-#define MLXSW_PCI_FW_READY_MAGIC 0x5E
+#else
-#define MLXSW_PCI_DOORBELL_SDQ_OFFSET 0x000
-#define MLXSW_PCI_DOORBELL_RDQ_OFFSET 0x200
-#define MLXSW_PCI_DOORBELL_CQ_OFFSET 0x400
-#define MLXSW_PCI_DOORBELL_EQ_OFFSET 0x600
-#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET 0x800
-#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET 0xA00
+static inline int
+mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+ return 0;
+}
-#define MLXSW_PCI_DOORBELL(offset, type_offset, num) \
- ((offset) + (type_offset) + (num) * 4)
+static inline void
+mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
+{
+}
-#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
-
-#define MLXSW_PCI_AQ_PAGES 8
-#define MLXSW_PCI_AQ_SIZE (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
-#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */
-#define MLXSW_PCI_CQE_SIZE 16 /* 16 bytes per element */
-#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */
-#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
-#define MLXSW_PCI_CQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
-#define MLXSW_PCI_EQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
-#define MLXSW_PCI_EQE_UPDATE_COUNT 0x80
-
-#define MLXSW_PCI_WQE_SG_ENTRIES 3
-#define MLXSW_PCI_WQE_TYPE_ETHERNET 0xA
-
-/* pci_wqe_c
- * If set it indicates that a completion should be reported upon
- * execution of this descriptor.
- */
-MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
-
-/* pci_wqe_lp
- * Local Processing, set if packet should be processed by the local
- * switch hardware:
- * For Ethernet EMAD (Direct Route and non Direct Route) -
- * must be set if packet destination is local device
- * For InfiniBand CTL - must be set if packet destination is local device
- * Otherwise it must be clear
- * Local Process packets must not exceed the size of 2K (including payload
- * and headers).
- */
-MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
-
-/* pci_wqe_type
- * Packet type.
- */
-MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
-
-/* pci_wqe_byte_count
- * Size of i-th scatter/gather entry, 0 if entry is unused.
- */
-MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
-
-/* pci_wqe_address
- * Physical address of i-th scatter/gather entry.
- * Gather Entries must be 2Byte aligned.
- */
-MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
-
-/* pci_cqe_lag
- * Packet arrives from a port which is a LAG
- */
-MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
-
-/* pci_cqe_system_port/lag_id
- * When lag=0: System port on which the packet was received
- * When lag=1:
- * bits [15:4] LAG ID on which the packet was received
- * bits [3:0] sub_port on which the packet was received
- */
-MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
-MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
-MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
-
-/* pci_cqe_wqe_counter
- * WQE count of the WQEs completed on the associated dqn
- */
-MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
-
-/* pci_cqe_byte_count
- * Byte count of received packets including additional two
- * Reserved Bytes that are append to the end of the frame.
- * Reserved for Send CQE.
- */
-MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
-
-/* pci_cqe_trap_id
- * Trap ID that captured the packet.
- */
-MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
-
-/* pci_cqe_crc
- * Length include CRC. Indicates the length field includes
- * the packet's CRC.
- */
-MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
-
-/* pci_cqe_e
- * CQE with Error.
- */
-MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
-
-/* pci_cqe_sr
- * 1 - Send Queue
- * 0 - Receive Queue
- */
-MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
-
-/* pci_cqe_dqn
- * Descriptor Queue (DQ) Number.
- */
-MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
-
-/* pci_cqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
-
-/* pci_eqe_event_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
-#define MLXSW_PCI_EQE_EVENT_TYPE_COMP 0x00
-#define MLXSW_PCI_EQE_EVENT_TYPE_CMD 0x0A
-
-/* pci_eqe_event_sub_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
-
-/* pci_eqe_cqn
- * Completion Queue that triggeret this EQE.
- */
-MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
-
-/* pci_eqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
-
-/* pci_eqe_cmd_token
- * Command completion event - token
- */
-MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
-
-/* pci_eqe_cmd_status
- * Command completion event - status
- */
-MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
-
-/* pci_eqe_cmd_out_param_h
- * Command completion event - output parameter - higher part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
-
-/* pci_eqe_cmd_out_param_l
- * Command completion event - output parameter - lower part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+#endif
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
new file mode 100644
index 000000000000..d147ddd97997
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
@@ -0,0 +1,229 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
+ * Copyright (c) 2015-2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015-2016 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.
+ */
+
+#ifndef _MLXSW_PCI_HW_H
+#define _MLXSW_PCI_HW_H
+
+#include <linux/bitops.h>
+
+#include "item.h"
+
+#define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */
+#define MLXSW_PCI_PAGE_SIZE 4096
+
+#define MLXSW_PCI_CIR_BASE 0x71000
+#define MLXSW_PCI_CIR_IN_PARAM_HI MLXSW_PCI_CIR_BASE
+#define MLXSW_PCI_CIR_IN_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x04)
+#define MLXSW_PCI_CIR_IN_MODIFIER (MLXSW_PCI_CIR_BASE + 0x08)
+#define MLXSW_PCI_CIR_OUT_PARAM_HI (MLXSW_PCI_CIR_BASE + 0x0C)
+#define MLXSW_PCI_CIR_OUT_PARAM_LO (MLXSW_PCI_CIR_BASE + 0x10)
+#define MLXSW_PCI_CIR_TOKEN (MLXSW_PCI_CIR_BASE + 0x14)
+#define MLXSW_PCI_CIR_CTRL (MLXSW_PCI_CIR_BASE + 0x18)
+#define MLXSW_PCI_CIR_CTRL_GO_BIT BIT(23)
+#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT BIT(22)
+#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT 12
+#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT 24
+#define MLXSW_PCI_CIR_TIMEOUT_MSECS 1000
+
+#define MLXSW_PCI_SW_RESET 0xF0010
+#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0)
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000
+#define MLXSW_PCI_FW_READY 0xA1844
+#define MLXSW_PCI_FW_READY_MASK 0xFFFF
+#define MLXSW_PCI_FW_READY_MAGIC 0x5E
+
+#define MLXSW_PCI_DOORBELL_SDQ_OFFSET 0x000
+#define MLXSW_PCI_DOORBELL_RDQ_OFFSET 0x200
+#define MLXSW_PCI_DOORBELL_CQ_OFFSET 0x400
+#define MLXSW_PCI_DOORBELL_EQ_OFFSET 0x600
+#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET 0x800
+#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET 0xA00
+
+#define MLXSW_PCI_DOORBELL(offset, type_offset, num) \
+ ((offset) + (type_offset) + (num) * 4)
+
+#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
+
+#define MLXSW_PCI_AQ_PAGES 8
+#define MLXSW_PCI_AQ_SIZE (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
+#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE 16 /* 16 bytes per element */
+#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */
+#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
+#define MLXSW_PCI_CQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
+#define MLXSW_PCI_EQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
+#define MLXSW_PCI_EQE_UPDATE_COUNT 0x80
+
+#define MLXSW_PCI_WQE_SG_ENTRIES 3
+#define MLXSW_PCI_WQE_TYPE_ETHERNET 0xA
+
+/* pci_wqe_c
+ * If set it indicates that a completion should be reported upon
+ * execution of this descriptor.
+ */
+MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
+
+/* pci_wqe_lp
+ * Local Processing, set if packet should be processed by the local
+ * switch hardware:
+ * For Ethernet EMAD (Direct Route and non Direct Route) -
+ * must be set if packet destination is local device
+ * For InfiniBand CTL - must be set if packet destination is local device
+ * Otherwise it must be clear
+ * Local Process packets must not exceed the size of 2K (including payload
+ * and headers).
+ */
+MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
+
+/* pci_wqe_type
+ * Packet type.
+ */
+MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
+
+/* pci_wqe_byte_count
+ * Size of i-th scatter/gather entry, 0 if entry is unused.
+ */
+MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
+
+/* pci_wqe_address
+ * Physical address of i-th scatter/gather entry.
+ * Gather Entries must be 2Byte aligned.
+ */
+MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
+
+/* pci_cqe_lag
+ * Packet arrives from a port which is a LAG
+ */
+MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
+
+/* pci_cqe_system_port/lag_id
+ * When lag=0: System port on which the packet was received
+ * When lag=1:
+ * bits [15:4] LAG ID on which the packet was received
+ * bits [3:0] sub_port on which the packet was received
+ */
+MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
+MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
+MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
+
+/* pci_cqe_wqe_counter
+ * WQE count of the WQEs completed on the associated dqn
+ */
+MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
+
+/* pci_cqe_byte_count
+ * Byte count of received packets including additional two
+ * Reserved Bytes that are append to the end of the frame.
+ * Reserved for Send CQE.
+ */
+MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
+
+/* pci_cqe_trap_id
+ * Trap ID that captured the packet.
+ */
+MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
+
+/* pci_cqe_crc
+ * Length include CRC. Indicates the length field includes
+ * the packet's CRC.
+ */
+MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
+
+/* pci_cqe_e
+ * CQE with Error.
+ */
+MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
+
+/* pci_cqe_sr
+ * 1 - Send Queue
+ * 0 - Receive Queue
+ */
+MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
+
+/* pci_cqe_dqn
+ * Descriptor Queue (DQ) Number.
+ */
+MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
+
+/* pci_cqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_event_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
+#define MLXSW_PCI_EQE_EVENT_TYPE_COMP 0x00
+#define MLXSW_PCI_EQE_EVENT_TYPE_CMD 0x0A
+
+/* pci_eqe_event_sub_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
+
+/* pci_eqe_cqn
+ * Completion Queue that triggeret this EQE.
+ */
+MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
+
+/* pci_eqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_cmd_token
+ * Command completion event - token
+ */
+MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
+
+/* pci_eqe_cmd_status
+ * Command completion event - status
+ */
+MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
+
+/* pci_eqe_cmd_out_param_h
+ * Command completion event - output parameter - higher part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
+
+/* pci_eqe_cmd_out_param_l
+ * Command completion event - output parameter - lower part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/port.h b/drivers/net/ethernet/mellanox/mlxsw/port.h
index af371a82c35b..3d42146473b3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/port.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/port.h
@@ -44,6 +44,7 @@
#define MLXSW_PORT_SWID_DISABLED_PORT 255
#define MLXSW_PORT_SWID_ALL_SWIDS 254
+#define MLXSW_PORT_SWID_TYPE_IB 1
#define MLXSW_PORT_SWID_TYPE_ETH 2
#define MLXSW_PORT_MID 0xd000
@@ -51,6 +52,9 @@
#define MLXSW_PORT_MAX_PHY_PORTS 0x40
#define MLXSW_PORT_MAX_PORTS (MLXSW_PORT_MAX_PHY_PORTS + 1)
+#define MLXSW_PORT_MAX_IB_PHY_PORTS 36
+#define MLXSW_PORT_MAX_IB_PORTS (MLXSW_PORT_MAX_IB_PHY_PORTS + 1)
+
#define MLXSW_PORT_DEVID_BITS_OFFSET 10
#define MLXSW_PORT_PHY_BITS_OFFSET 4
#define MLXSW_PORT_PHY_BITS_MASK (MLXSW_PORT_MAX_PHY_PORTS - 1)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 6460c7256f2b..1357fe04391b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -48,8 +48,16 @@
struct mlxsw_reg_info {
u16 id;
u16 len; /* In u8 */
+ const char *name;
};
+#define MLXSW_REG_DEFINE(_name, _id, _len) \
+static const struct mlxsw_reg_info mlxsw_reg_##_name = { \
+ .id = _id, \
+ .len = _len, \
+ .name = #_name, \
+}
+
#define MLXSW_REG(type) (&mlxsw_reg_##type)
#define MLXSW_REG_LEN(type) MLXSW_REG(type)->len
#define MLXSW_REG_ZERO(type, payload) memset(payload, 0, MLXSW_REG(type)->len)
@@ -61,10 +69,7 @@ struct mlxsw_reg_info {
#define MLXSW_REG_SGCR_ID 0x2000
#define MLXSW_REG_SGCR_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_sgcr = {
- .id = MLXSW_REG_SGCR_ID,
- .len = MLXSW_REG_SGCR_LEN,
-};
+MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN);
/* reg_sgcr_llb
* Link Local Broadcast (Default=0)
@@ -87,10 +92,7 @@ static inline void mlxsw_reg_sgcr_pack(char *payload, bool llb)
#define MLXSW_REG_SPAD_ID 0x2002
#define MLXSW_REG_SPAD_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_spad = {
- .id = MLXSW_REG_SPAD_ID,
- .len = MLXSW_REG_SPAD_LEN,
-};
+MLXSW_REG_DEFINE(spad, MLXSW_REG_SPAD_ID, MLXSW_REG_SPAD_LEN);
/* reg_spad_base_mac
* Base MAC address for the switch partitions.
@@ -109,10 +111,7 @@ MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6);
#define MLXSW_REG_SMID_ID 0x2007
#define MLXSW_REG_SMID_LEN 0x240
-static const struct mlxsw_reg_info mlxsw_reg_smid = {
- .id = MLXSW_REG_SMID_ID,
- .len = MLXSW_REG_SMID_LEN,
-};
+MLXSW_REG_DEFINE(smid, MLXSW_REG_SMID_ID, MLXSW_REG_SMID_LEN);
/* reg_smid_swid
* Switch partition ID.
@@ -156,10 +155,7 @@ static inline void mlxsw_reg_smid_pack(char *payload, u16 mid,
#define MLXSW_REG_SSPR_ID 0x2008
#define MLXSW_REG_SSPR_LEN 0x8
-static const struct mlxsw_reg_info mlxsw_reg_sspr = {
- .id = MLXSW_REG_SSPR_ID,
- .len = MLXSW_REG_SSPR_LEN,
-};
+MLXSW_REG_DEFINE(sspr, MLXSW_REG_SSPR_ID, MLXSW_REG_SSPR_LEN);
/* reg_sspr_m
* Master - if set, then the record describes the master system port.
@@ -215,10 +211,7 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port)
#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,
-};
+MLXSW_REG_DEFINE(sfdat, MLXSW_REG_SFDAT_ID, MLXSW_REG_SFDAT_LEN);
/* reg_sfdat_swid
* Switch partition ID.
@@ -256,10 +249,7 @@ static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time)
#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,
-};
+MLXSW_REG_DEFINE(sfd, MLXSW_REG_SFD_ID, MLXSW_REG_SFD_LEN);
/* reg_sfd_swid
* Switch partition ID for queries. Reserved on Write.
@@ -580,10 +570,7 @@ mlxsw_reg_sfd_mc_pack(char *payload, int rec_index,
#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,
-};
+MLXSW_REG_DEFINE(sfn, MLXSW_REG_SFN_ID, MLXSW_REG_SFN_LEN);
/* reg_sfn_swid
* Switch partition ID.
@@ -701,10 +688,7 @@ static inline void mlxsw_reg_sfn_mac_lag_unpack(char *payload, int rec_index,
#define MLXSW_REG_SPMS_ID 0x200D
#define MLXSW_REG_SPMS_LEN 0x404
-static const struct mlxsw_reg_info mlxsw_reg_spms = {
- .id = MLXSW_REG_SPMS_ID,
- .len = MLXSW_REG_SPMS_LEN,
-};
+MLXSW_REG_DEFINE(spms, MLXSW_REG_SPMS_ID, MLXSW_REG_SPMS_LEN);
/* reg_spms_local_port
* Local port number.
@@ -748,10 +732,7 @@ static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid,
#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,
-};
+MLXSW_REG_DEFINE(spvid, MLXSW_REG_SPVID_ID, MLXSW_REG_SPVID_LEN);
/* reg_spvid_local_port
* Local port number.
@@ -792,10 +773,7 @@ static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid)
#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,
-};
+MLXSW_REG_DEFINE(spvm, MLXSW_REG_SPVM_ID, MLXSW_REG_SPVM_LEN);
/* reg_spvm_pt
* Priority tagged. If this bit is set, packets forwarded to the port with
@@ -891,10 +869,7 @@ static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port,
#define MLXSW_REG_SPAFT_ID 0x2010
#define MLXSW_REG_SPAFT_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_spaft = {
- .id = MLXSW_REG_SPAFT_ID,
- .len = MLXSW_REG_SPAFT_LEN,
-};
+MLXSW_REG_DEFINE(spaft, MLXSW_REG_SPAFT_ID, MLXSW_REG_SPAFT_LEN);
/* reg_spaft_local_port
* Local port number.
@@ -947,10 +922,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port,
#define MLXSW_REG_SFGC_ID 0x2011
#define MLXSW_REG_SFGC_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_sfgc = {
- .id = MLXSW_REG_SFGC_ID,
- .len = MLXSW_REG_SFGC_LEN,
-};
+MLXSW_REG_DEFINE(sfgc, MLXSW_REG_SFGC_ID, MLXSW_REG_SFGC_LEN);
enum mlxsw_reg_sfgc_type {
MLXSW_REG_SFGC_TYPE_BROADCAST,
@@ -1045,10 +1017,7 @@ mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
#define MLXSW_REG_SFTR_ID 0x2012
#define MLXSW_REG_SFTR_LEN 0x420
-static const struct mlxsw_reg_info mlxsw_reg_sftr = {
- .id = MLXSW_REG_SFTR_ID,
- .len = MLXSW_REG_SFTR_LEN,
-};
+MLXSW_REG_DEFINE(sftr, MLXSW_REG_SFTR_ID, MLXSW_REG_SFTR_LEN);
/* reg_sftr_swid
* Switch partition ID with which to associate the port.
@@ -1118,10 +1087,7 @@ static inline void mlxsw_reg_sftr_pack(char *payload,
#define MLXSW_REG_SFDF_ID 0x2013
#define MLXSW_REG_SFDF_LEN 0x14
-static const struct mlxsw_reg_info mlxsw_reg_sfdf = {
- .id = MLXSW_REG_SFDF_ID,
- .len = MLXSW_REG_SFDF_LEN,
-};
+MLXSW_REG_DEFINE(sfdf, MLXSW_REG_SFDF_ID, MLXSW_REG_SFDF_LEN);
/* reg_sfdf_swid
* Switch partition ID.
@@ -1205,10 +1171,7 @@ MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10);
#define MLXSW_REG_SLDR_ID 0x2014
#define MLXSW_REG_SLDR_LEN 0x0C /* counting in only one port in list */
-static const struct mlxsw_reg_info mlxsw_reg_sldr = {
- .id = MLXSW_REG_SLDR_ID,
- .len = MLXSW_REG_SLDR_LEN,
-};
+MLXSW_REG_DEFINE(sldr, MLXSW_REG_SLDR_ID, MLXSW_REG_SLDR_LEN);
enum mlxsw_reg_sldr_op {
/* Indicates a creation of a new LAG-ID, lag_id must be valid */
@@ -1288,10 +1251,7 @@ static inline void mlxsw_reg_sldr_lag_remove_port_pack(char *payload, u8 lag_id,
#define MLXSW_REG_SLCR_ID 0x2015
#define MLXSW_REG_SLCR_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_slcr = {
- .id = MLXSW_REG_SLCR_ID,
- .len = MLXSW_REG_SLCR_LEN,
-};
+MLXSW_REG_DEFINE(slcr, MLXSW_REG_SLCR_ID, MLXSW_REG_SLCR_LEN);
enum mlxsw_reg_slcr_pp {
/* Global Configuration (for all ports) */
@@ -1404,10 +1364,7 @@ static inline void mlxsw_reg_slcr_pack(char *payload, u16 lag_hash)
#define MLXSW_REG_SLCOR_ID 0x2016
#define MLXSW_REG_SLCOR_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_slcor = {
- .id = MLXSW_REG_SLCOR_ID,
- .len = MLXSW_REG_SLCOR_LEN,
-};
+MLXSW_REG_DEFINE(slcor, MLXSW_REG_SLCOR_ID, MLXSW_REG_SLCOR_LEN);
enum mlxsw_reg_slcor_col {
/* Port is added with collector disabled */
@@ -1490,10 +1447,7 @@ static inline void mlxsw_reg_slcor_col_disable_pack(char *payload,
#define MLXSW_REG_SPMLR_ID 0x2018
#define MLXSW_REG_SPMLR_LEN 0x8
-static const struct mlxsw_reg_info mlxsw_reg_spmlr = {
- .id = MLXSW_REG_SPMLR_ID,
- .len = MLXSW_REG_SPMLR_LEN,
-};
+MLXSW_REG_DEFINE(spmlr, MLXSW_REG_SPMLR_ID, MLXSW_REG_SPMLR_LEN);
/* reg_spmlr_local_port
* Local port number.
@@ -1544,10 +1498,7 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port,
#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,
-};
+MLXSW_REG_DEFINE(svfa, MLXSW_REG_SVFA_ID, MLXSW_REG_SVFA_LEN);
/* reg_svfa_swid
* Switch partition ID.
@@ -1636,10 +1587,7 @@ static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port,
#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,
-};
+MLXSW_REG_DEFINE(svpe, MLXSW_REG_SVPE_ID, MLXSW_REG_SVPE_LEN);
/* reg_svpe_local_port
* Local port number
@@ -1672,10 +1620,7 @@ static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port,
#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,
-};
+MLXSW_REG_DEFINE(sfmr, MLXSW_REG_SFMR_ID, MLXSW_REG_SFMR_LEN);
enum mlxsw_reg_sfmr_op {
MLXSW_REG_SFMR_OP_CREATE_FID,
@@ -1762,10 +1707,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
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,
-};
+MLXSW_REG_DEFINE(spvmlr, MLXSW_REG_SPVMLR_ID, MLXSW_REG_SPVMLR_LEN);
/* reg_spvmlr_local_port
* Local ingress port.
@@ -1815,6 +1757,146 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port,
}
}
+/* QPCR - QoS Policer Configuration Register
+ * -----------------------------------------
+ * The QPCR register is used to create policers - that limit
+ * the rate of bytes or packets via some trap group.
+ */
+#define MLXSW_REG_QPCR_ID 0x4004
+#define MLXSW_REG_QPCR_LEN 0x28
+
+MLXSW_REG_DEFINE(qpcr, MLXSW_REG_QPCR_ID, MLXSW_REG_QPCR_LEN);
+
+enum mlxsw_reg_qpcr_g {
+ MLXSW_REG_QPCR_G_GLOBAL = 2,
+ MLXSW_REG_QPCR_G_STORM_CONTROL = 3,
+};
+
+/* reg_qpcr_g
+ * The policer type.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, qpcr, g, 0x00, 14, 2);
+
+/* reg_qpcr_pid
+ * Policer ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, qpcr, pid, 0x00, 0, 14);
+
+/* reg_qpcr_color_aware
+ * Is the policer aware of colors.
+ * Must be 0 (unaware) for cpu port.
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, color_aware, 0x04, 15, 1);
+
+/* reg_qpcr_bytes
+ * Is policer limit is for bytes per sec or packets per sec.
+ * 0 - packets
+ * 1 - bytes
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, bytes, 0x04, 14, 1);
+
+enum mlxsw_reg_qpcr_ir_units {
+ MLXSW_REG_QPCR_IR_UNITS_M,
+ MLXSW_REG_QPCR_IR_UNITS_K,
+};
+
+/* reg_qpcr_ir_units
+ * Policer's units for cir and eir fields (for bytes limits only)
+ * 1 - 10^3
+ * 0 - 10^6
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, qpcr, ir_units, 0x04, 12, 1);
+
+enum mlxsw_reg_qpcr_rate_type {
+ MLXSW_REG_QPCR_RATE_TYPE_SINGLE = 1,
+ MLXSW_REG_QPCR_RATE_TYPE_DOUBLE = 2,
+};
+
+/* reg_qpcr_rate_type
+ * Policer can have one limit (single rate) or 2 limits with specific operation
+ * for packets that exceed the lower rate but not the upper one.
+ * (For cpu port must be single rate)
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, rate_type, 0x04, 8, 2);
+
+/* reg_qpc_cbs
+ * Policer's committed burst size.
+ * The policer is working with time slices of 50 nano sec. By default every
+ * slice is granted the proportionate share of the committed rate. If we want to
+ * allow a slice to exceed that share (while still keeping the rate per sec) we
+ * can allow burst. The burst size is between the default proportionate share
+ * (and no lower than 8) to 32Gb. (Even though giving a number higher than the
+ * committed rate will result in exceeding the rate). The burst size must be a
+ * log of 2 and will be determined by 2^cbs.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, cbs, 0x08, 24, 6);
+
+/* reg_qpcr_cir
+ * Policer's committed rate.
+ * The rate used for sungle rate, the lower rate for double rate.
+ * For bytes limits, the rate will be this value * the unit from ir_units.
+ * (Resolution error is up to 1%).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, cir, 0x0C, 0, 32);
+
+/* reg_qpcr_eir
+ * Policer's exceed rate.
+ * The higher rate for double rate, reserved for single rate.
+ * Lower rate for double rate policer.
+ * For bytes limits, the rate will be this value * the unit from ir_units.
+ * (Resolution error is up to 1%).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, eir, 0x10, 0, 32);
+
+#define MLXSW_REG_QPCR_DOUBLE_RATE_ACTION 2
+
+/* reg_qpcr_exceed_action.
+ * What to do with packets between the 2 limits for double rate.
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, exceed_action, 0x14, 0, 4);
+
+enum mlxsw_reg_qpcr_action {
+ /* Discard */
+ MLXSW_REG_QPCR_ACTION_DISCARD = 1,
+ /* Forward and set color to red.
+ * If the packet is intended to cpu port, it will be dropped.
+ */
+ MLXSW_REG_QPCR_ACTION_FORWARD = 2,
+};
+
+/* reg_qpcr_violate_action
+ * What to do with packets that cross the cir limit (for single rate) or the eir
+ * limit (for double rate).
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, violate_action, 0x18, 0, 4);
+
+static inline void mlxsw_reg_qpcr_pack(char *payload, u16 pid,
+ enum mlxsw_reg_qpcr_ir_units ir_units,
+ bool bytes, u32 cir, u16 cbs)
+{
+ MLXSW_REG_ZERO(qpcr, payload);
+ mlxsw_reg_qpcr_pid_set(payload, pid);
+ mlxsw_reg_qpcr_g_set(payload, MLXSW_REG_QPCR_G_GLOBAL);
+ mlxsw_reg_qpcr_rate_type_set(payload, MLXSW_REG_QPCR_RATE_TYPE_SINGLE);
+ mlxsw_reg_qpcr_violate_action_set(payload,
+ MLXSW_REG_QPCR_ACTION_DISCARD);
+ mlxsw_reg_qpcr_cir_set(payload, cir);
+ mlxsw_reg_qpcr_ir_units_set(payload, ir_units);
+ mlxsw_reg_qpcr_bytes_set(payload, bytes);
+ mlxsw_reg_qpcr_cbs_set(payload, cbs);
+}
+
/* QTCT - QoS Switch Traffic Class Table
* -------------------------------------
* Configures the mapping between the packet switch priority and the
@@ -1823,10 +1905,7 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port,
#define MLXSW_REG_QTCT_ID 0x400A
#define MLXSW_REG_QTCT_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_qtct = {
- .id = MLXSW_REG_QTCT_ID,
- .len = MLXSW_REG_QTCT_LEN,
-};
+MLXSW_REG_DEFINE(qtct, MLXSW_REG_QTCT_ID, MLXSW_REG_QTCT_LEN);
/* reg_qtct_local_port
* Local port number.
@@ -1875,10 +1954,7 @@ static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port,
#define MLXSW_REG_QEEC_ID 0x400D
#define MLXSW_REG_QEEC_LEN 0x1C
-static const struct mlxsw_reg_info mlxsw_reg_qeec = {
- .id = MLXSW_REG_QEEC_ID,
- .len = MLXSW_REG_QEEC_LEN,
-};
+MLXSW_REG_DEFINE(qeec, MLXSW_REG_QEEC_ID, MLXSW_REG_QEEC_LEN);
/* reg_qeec_local_port
* Local port number.
@@ -2000,10 +2076,7 @@ static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port,
#define MLXSW_REG_PMLP_ID 0x5002
#define MLXSW_REG_PMLP_LEN 0x40
-static const struct mlxsw_reg_info mlxsw_reg_pmlp = {
- .id = MLXSW_REG_PMLP_ID,
- .len = MLXSW_REG_PMLP_LEN,
-};
+MLXSW_REG_DEFINE(pmlp, MLXSW_REG_PMLP_ID, MLXSW_REG_PMLP_LEN);
/* reg_pmlp_rxtx
* 0 - Tx value is used for both Tx and Rx.
@@ -2059,10 +2132,7 @@ static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port)
#define MLXSW_REG_PMTU_ID 0x5003
#define MLXSW_REG_PMTU_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_pmtu = {
- .id = MLXSW_REG_PMTU_ID,
- .len = MLXSW_REG_PMTU_LEN,
-};
+MLXSW_REG_DEFINE(pmtu, MLXSW_REG_PMTU_ID, MLXSW_REG_PMTU_LEN);
/* reg_pmtu_local_port
* Local port number.
@@ -2116,10 +2186,7 @@ static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port,
#define MLXSW_REG_PTYS_ID 0x5004
#define MLXSW_REG_PTYS_LEN 0x40
-static const struct mlxsw_reg_info mlxsw_reg_ptys = {
- .id = MLXSW_REG_PTYS_ID,
- .len = MLXSW_REG_PTYS_LEN,
-};
+MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN);
/* reg_ptys_local_port
* Local port number.
@@ -2127,6 +2194,7 @@ static const struct mlxsw_reg_info mlxsw_reg_ptys = {
*/
MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8);
+#define MLXSW_REG_PTYS_PROTO_MASK_IB BIT(0)
#define MLXSW_REG_PTYS_PROTO_MASK_ETH BIT(2)
/* reg_ptys_proto_mask
@@ -2185,18 +2253,61 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4);
*/
MLXSW_ITEM32(reg, ptys, eth_proto_cap, 0x0C, 0, 32);
+/* reg_ptys_ib_link_width_cap
+ * IB port supported widths.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16);
+
+#define MLXSW_REG_PTYS_IB_SPEED_SDR BIT(0)
+#define MLXSW_REG_PTYS_IB_SPEED_DDR BIT(1)
+#define MLXSW_REG_PTYS_IB_SPEED_QDR BIT(2)
+#define MLXSW_REG_PTYS_IB_SPEED_FDR10 BIT(3)
+#define MLXSW_REG_PTYS_IB_SPEED_FDR BIT(4)
+#define MLXSW_REG_PTYS_IB_SPEED_EDR BIT(5)
+
+/* reg_ptys_ib_proto_cap
+ * IB port supported speeds and protocols.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16);
+
/* reg_ptys_eth_proto_admin
* Speed and protocol to set port to.
* Access: RW
*/
MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32);
+/* reg_ptys_ib_link_width_admin
+ * IB width to set port to.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16);
+
+/* reg_ptys_ib_proto_admin
+ * IB speeds and protocols to set port to.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16);
+
/* reg_ptys_eth_proto_oper
* The current speed and protocol configured for the port.
* Access: RO
*/
MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32);
+/* reg_ptys_ib_link_width_oper
+ * The current IB width to set port to.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16);
+
+/* reg_ptys_ib_proto_oper
+ * The current IB speed and protocol.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16);
+
/* reg_ptys_eth_proto_lp_advertise
* The protocols that were advertised by the link partner during
* autonegotiation.
@@ -2204,8 +2315,8 @@ MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32);
*/
MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32);
-static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port,
- u32 proto_admin)
+static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port,
+ u32 proto_admin)
{
MLXSW_REG_ZERO(ptys, payload);
mlxsw_reg_ptys_local_port_set(payload, local_port);
@@ -2213,9 +2324,10 @@ static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port,
mlxsw_reg_ptys_eth_proto_admin_set(payload, proto_admin);
}
-static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap,
- u32 *p_eth_proto_adm,
- u32 *p_eth_proto_oper)
+static inline void mlxsw_reg_ptys_eth_unpack(char *payload,
+ u32 *p_eth_proto_cap,
+ u32 *p_eth_proto_adm,
+ u32 *p_eth_proto_oper)
{
if (p_eth_proto_cap)
*p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload);
@@ -2225,6 +2337,33 @@ static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap,
*p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload);
}
+static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port,
+ u16 proto_admin, u16 link_width)
+{
+ MLXSW_REG_ZERO(ptys, payload);
+ mlxsw_reg_ptys_local_port_set(payload, local_port);
+ mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_IB);
+ mlxsw_reg_ptys_ib_proto_admin_set(payload, proto_admin);
+ mlxsw_reg_ptys_ib_link_width_admin_set(payload, link_width);
+}
+
+static inline void mlxsw_reg_ptys_ib_unpack(char *payload, u16 *p_ib_proto_cap,
+ u16 *p_ib_link_width_cap,
+ u16 *p_ib_proto_oper,
+ u16 *p_ib_link_width_oper)
+{
+ if (p_ib_proto_cap)
+ *p_ib_proto_cap = mlxsw_reg_ptys_ib_proto_cap_get(payload);
+ if (p_ib_link_width_cap)
+ *p_ib_link_width_cap =
+ mlxsw_reg_ptys_ib_link_width_cap_get(payload);
+ if (p_ib_proto_oper)
+ *p_ib_proto_oper = mlxsw_reg_ptys_ib_proto_oper_get(payload);
+ if (p_ib_link_width_oper)
+ *p_ib_link_width_oper =
+ mlxsw_reg_ptys_ib_link_width_oper_get(payload);
+}
+
/* PPAD - Port Physical Address Register
* -------------------------------------
* The PPAD register configures the per port physical MAC address.
@@ -2232,10 +2371,7 @@ static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap,
#define MLXSW_REG_PPAD_ID 0x5005
#define MLXSW_REG_PPAD_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_ppad = {
- .id = MLXSW_REG_PPAD_ID,
- .len = MLXSW_REG_PPAD_LEN,
-};
+MLXSW_REG_DEFINE(ppad, MLXSW_REG_PPAD_ID, MLXSW_REG_PPAD_LEN);
/* reg_ppad_single_base_mac
* 0: base_mac, local port should be 0 and mac[7:0] is
@@ -2273,10 +2409,7 @@ static inline void mlxsw_reg_ppad_pack(char *payload, bool single_base_mac,
#define MLXSW_REG_PAOS_ID 0x5006
#define MLXSW_REG_PAOS_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_paos = {
- .id = MLXSW_REG_PAOS_ID,
- .len = MLXSW_REG_PAOS_LEN,
-};
+MLXSW_REG_DEFINE(paos, MLXSW_REG_PAOS_ID, MLXSW_REG_PAOS_LEN);
/* reg_paos_swid
* Switch partition ID with which to associate the port.
@@ -2356,10 +2489,7 @@ static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port,
#define MLXSW_REG_PFCC_ID 0x5007
#define MLXSW_REG_PFCC_LEN 0x20
-static const struct mlxsw_reg_info mlxsw_reg_pfcc = {
- .id = MLXSW_REG_PFCC_ID,
- .len = MLXSW_REG_PFCC_LEN,
-};
+MLXSW_REG_DEFINE(pfcc, MLXSW_REG_PFCC_ID, MLXSW_REG_PFCC_LEN);
/* reg_pfcc_local_port
* Local port number.
@@ -2495,10 +2625,7 @@ static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port)
#define MLXSW_REG_PPCNT_ID 0x5008
#define MLXSW_REG_PPCNT_LEN 0x100
-static const struct mlxsw_reg_info mlxsw_reg_ppcnt = {
- .id = MLXSW_REG_PPCNT_ID,
- .len = MLXSW_REG_PPCNT_LEN,
-};
+MLXSW_REG_DEFINE(ppcnt, MLXSW_REG_PPCNT_ID, MLXSW_REG_PPCNT_LEN);
/* reg_ppcnt_swid
* For HCA: must be always 0.
@@ -2761,6 +2888,27 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port,
mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc);
}
+/* PLIB - Port Local to InfiniBand Port
+ * ------------------------------------
+ * The PLIB register performs mapping from Local Port into InfiniBand Port.
+ */
+#define MLXSW_REG_PLIB_ID 0x500A
+#define MLXSW_REG_PLIB_LEN 0x10
+
+MLXSW_REG_DEFINE(plib, MLXSW_REG_PLIB_ID, MLXSW_REG_PLIB_LEN);
+
+/* reg_plib_local_port
+ * Local port number.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, plib, local_port, 0x00, 16, 8);
+
+/* reg_plib_ib_port
+ * InfiniBand port remapping for local_port.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, plib, ib_port, 0x00, 0, 8);
+
/* PPTB - Port Prio To Buffer Register
* -----------------------------------
* Configures the switch priority to buffer table.
@@ -2768,10 +2916,7 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port,
#define MLXSW_REG_PPTB_ID 0x500B
#define MLXSW_REG_PPTB_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_pptb = {
- .id = MLXSW_REG_PPTB_ID,
- .len = MLXSW_REG_PPTB_LEN,
-};
+MLXSW_REG_DEFINE(pptb, MLXSW_REG_PPTB_ID, MLXSW_REG_PPTB_LEN);
enum {
MLXSW_REG_PPTB_MM_UM,
@@ -2865,10 +3010,7 @@ static inline void mlxsw_reg_pptb_prio_to_buff_pack(char *payload, u8 prio,
#define MLXSW_REG_PBMC_ID 0x500C
#define MLXSW_REG_PBMC_LEN 0x6C
-static const struct mlxsw_reg_info mlxsw_reg_pbmc = {
- .id = MLXSW_REG_PBMC_ID,
- .len = MLXSW_REG_PBMC_LEN,
-};
+MLXSW_REG_DEFINE(pbmc, MLXSW_REG_PBMC_ID, MLXSW_REG_PBMC_LEN);
/* reg_pbmc_local_port
* Local port number.
@@ -2978,10 +3120,7 @@ static inline void mlxsw_reg_pbmc_lossless_buffer_pack(char *payload,
#define MLXSW_REG_PSPA_ID 0x500D
#define MLXSW_REG_PSPA_LEN 0x8
-static const struct mlxsw_reg_info mlxsw_reg_pspa = {
- .id = MLXSW_REG_PSPA_ID,
- .len = MLXSW_REG_PSPA_LEN,
-};
+MLXSW_REG_DEFINE(pspa, MLXSW_REG_PSPA_ID, MLXSW_REG_PSPA_LEN);
/* reg_pspa_swid
* Switch partition ID.
@@ -3017,10 +3156,7 @@ static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u8 local_port)
#define MLXSW_REG_HTGT_ID 0x7002
#define MLXSW_REG_HTGT_LEN 0x100
-static const struct mlxsw_reg_info mlxsw_reg_htgt = {
- .id = MLXSW_REG_HTGT_ID,
- .len = MLXSW_REG_HTGT_LEN,
-};
+MLXSW_REG_DEFINE(htgt, MLXSW_REG_HTGT_ID, MLXSW_REG_HTGT_LEN);
/* reg_htgt_swid
* Switch partition ID.
@@ -3038,8 +3174,21 @@ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4);
enum mlxsw_reg_htgt_trap_group {
MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
- MLXSW_REG_HTGT_TRAP_GROUP_RX,
- MLXSW_REG_HTGT_TRAP_GROUP_CTRL,
+ MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX,
+ MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT,
};
/* reg_htgt_trap_group
@@ -3061,6 +3210,8 @@ enum {
*/
MLXSW_ITEM32(reg, htgt, pide, 0x04, 15, 1);
+#define MLXSW_REG_HTGT_INVALID_POLICER 0xff
+
/* reg_htgt_pid
* Policer ID for the trap group.
* Access: RW
@@ -3086,6 +3237,8 @@ MLXSW_ITEM32(reg, htgt, mirror_action, 0x08, 8, 2);
*/
MLXSW_ITEM32(reg, htgt, mirroring_agent, 0x08, 0, 3);
+#define MLXSW_REG_HTGT_DEFAULT_PRIORITY 0
+
/* reg_htgt_priority
* Trap group priority.
* In case a packet matches multiple classification rules, the packet will
@@ -3099,52 +3252,47 @@ MLXSW_ITEM32(reg, htgt, mirroring_agent, 0x08, 0, 3);
*/
MLXSW_ITEM32(reg, htgt, priority, 0x0C, 0, 4);
+#define MLXSW_REG_HTGT_DEFAULT_TC 7
+
/* reg_htgt_local_path_cpu_tclass
* CPU ingress traffic class for the trap group.
* Access: RW
*/
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
-
+enum mlxsw_reg_htgt_local_path_rdq {
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL = 0x13,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX = 0x14,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD = 0x15,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD = 0x15,
+};
/* reg_htgt_local_path_rdq
* Receive descriptor queue (RDQ) to use for the trap group.
* Access: RW
*/
MLXSW_ITEM32(reg, htgt, local_path_rdq, 0x10, 0, 6);
-static inline void mlxsw_reg_htgt_pack(char *payload,
- enum mlxsw_reg_htgt_trap_group group)
+static inline void mlxsw_reg_htgt_pack(char *payload, u8 group, u8 policer_id,
+ u8 priority, u8 tc)
{
- u8 swid, rdq;
-
MLXSW_REG_ZERO(htgt, payload);
- switch (group) {
- case MLXSW_REG_HTGT_TRAP_GROUP_EMAD:
- swid = MLXSW_PORT_SWID_ALL_SWIDS;
- rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD;
- 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;
+
+ if (policer_id == MLXSW_REG_HTGT_INVALID_POLICER) {
+ mlxsw_reg_htgt_pide_set(payload,
+ MLXSW_REG_HTGT_POLICER_DISABLE);
+ } else {
+ mlxsw_reg_htgt_pide_set(payload,
+ MLXSW_REG_HTGT_POLICER_ENABLE);
+ mlxsw_reg_htgt_pid_set(payload, policer_id);
}
- 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, 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);
mlxsw_reg_htgt_mirroring_agent_set(payload, 0);
- mlxsw_reg_htgt_priority_set(payload, 0);
- mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, 7);
- mlxsw_reg_htgt_local_path_rdq_set(payload, rdq);
+ mlxsw_reg_htgt_priority_set(payload, priority);
+ mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, tc);
+ mlxsw_reg_htgt_local_path_rdq_set(payload, group);
}
/* HPKT - Host Packet Trap
@@ -3154,10 +3302,7 @@ static inline void mlxsw_reg_htgt_pack(char *payload,
#define MLXSW_REG_HPKT_ID 0x7003
#define MLXSW_REG_HPKT_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_hpkt = {
- .id = MLXSW_REG_HPKT_ID,
- .len = MLXSW_REG_HPKT_LEN,
-};
+MLXSW_REG_DEFINE(hpkt, MLXSW_REG_HPKT_ID, MLXSW_REG_HPKT_LEN);
enum {
MLXSW_REG_HPKT_ACK_NOT_REQUIRED,
@@ -3221,6 +3366,7 @@ enum {
/* reg_hpkt_ctrl
* Configure dedicated buffer resources for control packets.
+ * Ignored by SwitchX-2.
* 0 - Keep factory defaults.
* 1 - Do not use control buffer for this trap ID.
* 2 - Use control buffer for this trap ID.
@@ -3228,25 +3374,18 @@ enum {
*/
MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2);
-static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, 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,
+ bool is_ctrl)
{
- 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);
+ mlxsw_reg_hpkt_ctrl_set(payload, is_ctrl ?
+ MLXSW_REG_HPKT_CTRL_PACKET_USE_BUFFER :
+ MLXSW_REG_HPKT_CTRL_PACKET_NO_BUFFER);
}
/* RGCR - Router General Configuration Register
@@ -3256,10 +3395,7 @@ static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id)
#define MLXSW_REG_RGCR_ID 0x8001
#define MLXSW_REG_RGCR_LEN 0x28
-static const struct mlxsw_reg_info mlxsw_reg_rgcr = {
- .id = MLXSW_REG_RGCR_ID,
- .len = MLXSW_REG_RGCR_LEN,
-};
+MLXSW_REG_DEFINE(rgcr, MLXSW_REG_RGCR_ID, MLXSW_REG_RGCR_LEN);
/* reg_rgcr_ipv4_en
* IPv4 router enable.
@@ -3330,10 +3466,7 @@ static inline void mlxsw_reg_rgcr_pack(char *payload, bool ipv4_en)
#define MLXSW_REG_RITR_ID 0x8002
#define MLXSW_REG_RITR_LEN 0x40
-static const struct mlxsw_reg_info mlxsw_reg_ritr = {
- .id = MLXSW_REG_RITR_ID,
- .len = MLXSW_REG_RITR_LEN,
-};
+MLXSW_REG_DEFINE(ritr, MLXSW_REG_RITR_ID, MLXSW_REG_RITR_LEN);
/* reg_ritr_enable
* Enables routing on the router interface.
@@ -3533,10 +3666,7 @@ static inline void mlxsw_reg_ritr_pack(char *payload, bool enable,
#define MLXSW_REG_RATR_ID 0x8008
#define MLXSW_REG_RATR_LEN 0x2C
-static const struct mlxsw_reg_info mlxsw_reg_ratr = {
- .id = MLXSW_REG_RATR_ID,
- .len = MLXSW_REG_RATR_LEN,
-};
+MLXSW_REG_DEFINE(ratr, MLXSW_REG_RATR_ID, MLXSW_REG_RATR_LEN);
enum mlxsw_reg_ratr_op {
/* Read */
@@ -3663,10 +3793,7 @@ static inline void mlxsw_reg_ratr_eth_entry_pack(char *payload,
#define MLXSW_REG_RALTA_ID 0x8010
#define MLXSW_REG_RALTA_LEN 0x04
-static const struct mlxsw_reg_info mlxsw_reg_ralta = {
- .id = MLXSW_REG_RALTA_ID,
- .len = MLXSW_REG_RALTA_LEN,
-};
+MLXSW_REG_DEFINE(ralta, MLXSW_REG_RALTA_ID, MLXSW_REG_RALTA_LEN);
/* reg_ralta_op
* opcode (valid for Write, must be 0 on Read)
@@ -3718,10 +3845,7 @@ static inline void mlxsw_reg_ralta_pack(char *payload, bool alloc,
#define MLXSW_REG_RALST_ID 0x8011
#define MLXSW_REG_RALST_LEN 0x104
-static const struct mlxsw_reg_info mlxsw_reg_ralst = {
- .id = MLXSW_REG_RALST_ID,
- .len = MLXSW_REG_RALST_LEN,
-};
+MLXSW_REG_DEFINE(ralst, MLXSW_REG_RALST_ID, MLXSW_REG_RALST_LEN);
/* reg_ralst_root_bin
* The bin number of the root bin.
@@ -3788,10 +3912,7 @@ static inline void mlxsw_reg_ralst_bin_pack(char *payload, u8 bin_number,
#define MLXSW_REG_RALTB_ID 0x8012
#define MLXSW_REG_RALTB_LEN 0x04
-static const struct mlxsw_reg_info mlxsw_reg_raltb = {
- .id = MLXSW_REG_RALTB_ID,
- .len = MLXSW_REG_RALTB_LEN,
-};
+MLXSW_REG_DEFINE(raltb, MLXSW_REG_RALTB_ID, MLXSW_REG_RALTB_LEN);
/* reg_raltb_virtual_router
* Virtual Router ID
@@ -3832,10 +3953,7 @@ static inline void mlxsw_reg_raltb_pack(char *payload, u16 virtual_router,
#define MLXSW_REG_RALUE_ID 0x8013
#define MLXSW_REG_RALUE_LEN 0x38
-static const struct mlxsw_reg_info mlxsw_reg_ralue = {
- .id = MLXSW_REG_RALUE_ID,
- .len = MLXSW_REG_RALUE_LEN,
-};
+MLXSW_REG_DEFINE(ralue, MLXSW_REG_RALUE_ID, MLXSW_REG_RALUE_LEN);
/* reg_ralue_protocol
* Protocol.
@@ -4095,10 +4213,7 @@ mlxsw_reg_ralue_act_ip2me_pack(char *payload)
#define MLXSW_REG_RAUHT_ID 0x8014
#define MLXSW_REG_RAUHT_LEN 0x74
-static const struct mlxsw_reg_info mlxsw_reg_rauht = {
- .id = MLXSW_REG_RAUHT_ID,
- .len = MLXSW_REG_RAUHT_LEN,
-};
+MLXSW_REG_DEFINE(rauht, MLXSW_REG_RAUHT_ID, MLXSW_REG_RAUHT_LEN);
enum mlxsw_reg_rauht_type {
MLXSW_REG_RAUHT_TYPE_IPV4,
@@ -4234,10 +4349,7 @@ static inline void mlxsw_reg_rauht_pack4(char *payload,
#define MLXSW_REG_RALEU_ID 0x8015
#define MLXSW_REG_RALEU_LEN 0x28
-static const struct mlxsw_reg_info mlxsw_reg_raleu = {
- .id = MLXSW_REG_RALEU_ID,
- .len = MLXSW_REG_RALEU_LEN,
-};
+MLXSW_REG_DEFINE(raleu, MLXSW_REG_RALEU_ID, MLXSW_REG_RALEU_LEN);
/* reg_raleu_protocol
* Protocol.
@@ -4309,10 +4421,7 @@ static inline void mlxsw_reg_raleu_pack(char *payload,
MLXSW_REG_RAUHTD_REC_MAX_NUM * MLXSW_REG_RAUHTD_REC_LEN)
#define MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC 4
-static const struct mlxsw_reg_info mlxsw_reg_rauhtd = {
- .id = MLXSW_REG_RAUHTD_ID,
- .len = MLXSW_REG_RAUHTD_LEN,
-};
+MLXSW_REG_DEFINE(rauhtd, MLXSW_REG_RAUHTD_ID, MLXSW_REG_RAUHTD_LEN);
#define MLXSW_REG_RAUHTD_FILTER_A BIT(0)
#define MLXSW_REG_RAUHTD_FILTER_RIF BIT(3)
@@ -4444,10 +4553,7 @@ static inline void mlxsw_reg_rauhtd_ent_ipv4_unpack(char *payload,
#define MLXSW_REG_MFCR_ID 0x9001
#define MLXSW_REG_MFCR_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_mfcr = {
- .id = MLXSW_REG_MFCR_ID,
- .len = MLXSW_REG_MFCR_LEN,
-};
+MLXSW_REG_DEFINE(mfcr, MLXSW_REG_MFCR_ID, MLXSW_REG_MFCR_LEN);
enum mlxsw_reg_mfcr_pwm_frequency {
MLXSW_REG_MFCR_PWM_FEQ_11HZ = 0x00,
@@ -4464,7 +4570,7 @@ enum mlxsw_reg_mfcr_pwm_frequency {
* Controls the frequency of the PWM signal.
* Access: RW
*/
-MLXSW_ITEM32(reg, mfcr, pwm_frequency, 0x00, 0, 6);
+MLXSW_ITEM32(reg, mfcr, pwm_frequency, 0x00, 0, 7);
#define MLXSW_MFCR_TACHOS_MAX 10
@@ -4507,10 +4613,7 @@ mlxsw_reg_mfcr_unpack(char *payload,
#define MLXSW_REG_MFSC_ID 0x9002
#define MLXSW_REG_MFSC_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_mfsc = {
- .id = MLXSW_REG_MFSC_ID,
- .len = MLXSW_REG_MFSC_LEN,
-};
+MLXSW_REG_DEFINE(mfsc, MLXSW_REG_MFSC_ID, MLXSW_REG_MFSC_LEN);
/* reg_mfsc_pwm
* Fan pwm to control / monitor.
@@ -4541,10 +4644,7 @@ static inline void mlxsw_reg_mfsc_pack(char *payload, u8 pwm,
#define MLXSW_REG_MFSM_ID 0x9003
#define MLXSW_REG_MFSM_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_mfsm = {
- .id = MLXSW_REG_MFSM_ID,
- .len = MLXSW_REG_MFSM_LEN,
-};
+MLXSW_REG_DEFINE(mfsm, MLXSW_REG_MFSM_ID, MLXSW_REG_MFSM_LEN);
/* reg_mfsm_tacho
* Fan tachometer index.
@@ -4564,6 +4664,54 @@ static inline void mlxsw_reg_mfsm_pack(char *payload, u8 tacho)
mlxsw_reg_mfsm_tacho_set(payload, tacho);
}
+/* MFSL - Management Fan Speed Limit Register
+ * ------------------------------------------
+ * The Fan Speed Limit register is used to configure the fan speed
+ * event / interrupt notification mechanism. Fan speed threshold are
+ * defined for both under-speed and over-speed.
+ */
+#define MLXSW_REG_MFSL_ID 0x9004
+#define MLXSW_REG_MFSL_LEN 0x0C
+
+MLXSW_REG_DEFINE(mfsl, MLXSW_REG_MFSL_ID, MLXSW_REG_MFSL_LEN);
+
+/* reg_mfsl_tacho
+ * Fan tachometer index.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mfsl, tacho, 0x00, 24, 4);
+
+/* reg_mfsl_tach_min
+ * Tachometer minimum value (minimum RPM).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mfsl, tach_min, 0x04, 0, 16);
+
+/* reg_mfsl_tach_max
+ * Tachometer maximum value (maximum RPM).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mfsl, tach_max, 0x08, 0, 16);
+
+static inline void mlxsw_reg_mfsl_pack(char *payload, u8 tacho,
+ u16 tach_min, u16 tach_max)
+{
+ MLXSW_REG_ZERO(mfsl, payload);
+ mlxsw_reg_mfsl_tacho_set(payload, tacho);
+ mlxsw_reg_mfsl_tach_min_set(payload, tach_min);
+ mlxsw_reg_mfsl_tach_max_set(payload, tach_max);
+}
+
+static inline void mlxsw_reg_mfsl_unpack(char *payload, u8 tacho,
+ u16 *p_tach_min, u16 *p_tach_max)
+{
+ if (p_tach_min)
+ *p_tach_min = mlxsw_reg_mfsl_tach_min_get(payload);
+
+ if (p_tach_max)
+ *p_tach_max = mlxsw_reg_mfsl_tach_max_get(payload);
+}
+
/* MTCAP - Management Temperature Capabilities
* -------------------------------------------
* This register exposes the capabilities of the device and
@@ -4572,10 +4720,7 @@ static inline void mlxsw_reg_mfsm_pack(char *payload, u8 tacho)
#define MLXSW_REG_MTCAP_ID 0x9009
#define MLXSW_REG_MTCAP_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_mtcap = {
- .id = MLXSW_REG_MTCAP_ID,
- .len = MLXSW_REG_MTCAP_LEN,
-};
+MLXSW_REG_DEFINE(mtcap, MLXSW_REG_MTCAP_ID, MLXSW_REG_MTCAP_LEN);
/* reg_mtcap_sensor_count
* Number of sensors supported by the device.
@@ -4593,10 +4738,7 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7);
#define MLXSW_REG_MTMP_ID 0x900A
#define MLXSW_REG_MTMP_LEN 0x20
-static const struct mlxsw_reg_info mlxsw_reg_mtmp = {
- .id = MLXSW_REG_MTMP_ID,
- .len = MLXSW_REG_MTMP_LEN,
-};
+MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
/* reg_mtmp_sensor_index
* Sensors index to access.
@@ -4679,10 +4821,7 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
#define MLXSW_REG_MPAT_ID 0x901A
#define MLXSW_REG_MPAT_LEN 0x78
-static const struct mlxsw_reg_info mlxsw_reg_mpat = {
- .id = MLXSW_REG_MPAT_ID,
- .len = MLXSW_REG_MPAT_LEN,
-};
+MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN);
/* reg_mpat_pa_id
* Port Analyzer ID.
@@ -4742,10 +4881,7 @@ static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
#define MLXSW_REG_MPAR_ID 0x901B
#define MLXSW_REG_MPAR_LEN 0x08
-static const struct mlxsw_reg_info mlxsw_reg_mpar = {
- .id = MLXSW_REG_MPAR_ID,
- .len = MLXSW_REG_MPAR_LEN,
-};
+MLXSW_REG_DEFINE(mpar, MLXSW_REG_MPAR_ID, MLXSW_REG_MPAR_LEN);
/* reg_mpar_local_port
* The local port to mirror the packets from.
@@ -4795,10 +4931,7 @@ static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port,
#define MLXSW_REG_MLCR_ID 0x902B
#define MLXSW_REG_MLCR_LEN 0x0C
-static const struct mlxsw_reg_info mlxsw_reg_mlcr = {
- .id = MLXSW_REG_MLCR_ID,
- .len = MLXSW_REG_MLCR_LEN,
-};
+MLXSW_REG_DEFINE(mlcr, MLXSW_REG_MLCR_ID, MLXSW_REG_MLCR_LEN);
/* reg_mlcr_local_port
* Local port number.
@@ -4839,10 +4972,7 @@ static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port,
#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,
-};
+MLXSW_REG_DEFINE(sbpr, MLXSW_REG_SBPR_ID, MLXSW_REG_SBPR_LEN);
/* shared direstion enum for SBPR, SBCM, SBPM */
enum mlxsw_reg_sbxx_dir {
@@ -4899,10 +5029,7 @@ static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool,
#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,
-};
+MLXSW_REG_DEFINE(sbcm, MLXSW_REG_SBCM_ID, MLXSW_REG_SBCM_LEN);
/* reg_sbcm_local_port
* Local port number.
@@ -4979,10 +5106,7 @@ static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff,
#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,
-};
+MLXSW_REG_DEFINE(sbpm, MLXSW_REG_SBPM_ID, MLXSW_REG_SBPM_LEN);
/* reg_sbpm_local_port
* Local port number.
@@ -5073,10 +5197,7 @@ static inline void mlxsw_reg_sbpm_unpack(char *payload, u32 *p_buff_occupancy,
#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,
-};
+MLXSW_REG_DEFINE(sbmm, MLXSW_REG_SBMM_ID, MLXSW_REG_SBMM_LEN);
/* reg_sbmm_prio
* Switch Priority.
@@ -5135,10 +5256,7 @@ static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff,
MLXSW_REG_SBSR_REC_LEN * \
MLXSW_REG_SBSR_REC_MAX_COUNT)
-static const struct mlxsw_reg_info mlxsw_reg_sbsr = {
- .id = MLXSW_REG_SBSR_ID,
- .len = MLXSW_REG_SBSR_LEN,
-};
+MLXSW_REG_DEFINE(sbsr, MLXSW_REG_SBSR_ID, MLXSW_REG_SBSR_LEN);
/* reg_sbsr_clr
* Clear Max Buffer Occupancy. When this bit is set, the max_buff_occupancy
@@ -5228,10 +5346,7 @@ static inline void mlxsw_reg_sbsr_rec_unpack(char *payload, int rec_index,
#define MLXSW_REG_SBIB_ID 0xB006
#define MLXSW_REG_SBIB_LEN 0x10
-static const struct mlxsw_reg_info mlxsw_reg_sbib = {
- .id = MLXSW_REG_SBIB_ID,
- .len = MLXSW_REG_SBIB_LEN,
-};
+MLXSW_REG_DEFINE(sbib, MLXSW_REG_SBIB_ID, MLXSW_REG_SBIB_LEN);
/* reg_sbib_local_port
* Local port number
@@ -5256,132 +5371,83 @@ static inline void mlxsw_reg_sbib_pack(char *payload, u8 local_port,
mlxsw_reg_sbib_buff_size_set(payload, buff_size);
}
+static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
+ MLXSW_REG(sgcr),
+ MLXSW_REG(spad),
+ MLXSW_REG(smid),
+ MLXSW_REG(sspr),
+ MLXSW_REG(sfdat),
+ MLXSW_REG(sfd),
+ MLXSW_REG(sfn),
+ MLXSW_REG(spms),
+ MLXSW_REG(spvid),
+ MLXSW_REG(spvm),
+ MLXSW_REG(spaft),
+ MLXSW_REG(sfgc),
+ MLXSW_REG(sftr),
+ MLXSW_REG(sfdf),
+ MLXSW_REG(sldr),
+ MLXSW_REG(slcr),
+ MLXSW_REG(slcor),
+ MLXSW_REG(spmlr),
+ MLXSW_REG(svfa),
+ MLXSW_REG(svpe),
+ MLXSW_REG(sfmr),
+ MLXSW_REG(spvmlr),
+ MLXSW_REG(qpcr),
+ MLXSW_REG(qtct),
+ MLXSW_REG(qeec),
+ MLXSW_REG(pmlp),
+ MLXSW_REG(pmtu),
+ MLXSW_REG(ptys),
+ MLXSW_REG(ppad),
+ MLXSW_REG(paos),
+ MLXSW_REG(pfcc),
+ MLXSW_REG(ppcnt),
+ MLXSW_REG(plib),
+ MLXSW_REG(pptb),
+ MLXSW_REG(pbmc),
+ MLXSW_REG(pspa),
+ MLXSW_REG(htgt),
+ MLXSW_REG(hpkt),
+ MLXSW_REG(rgcr),
+ MLXSW_REG(ritr),
+ MLXSW_REG(ratr),
+ MLXSW_REG(ralta),
+ MLXSW_REG(ralst),
+ MLXSW_REG(raltb),
+ MLXSW_REG(ralue),
+ MLXSW_REG(rauht),
+ MLXSW_REG(raleu),
+ MLXSW_REG(rauhtd),
+ MLXSW_REG(mfcr),
+ MLXSW_REG(mfsc),
+ MLXSW_REG(mfsm),
+ MLXSW_REG(mfsl),
+ MLXSW_REG(mtcap),
+ MLXSW_REG(mtmp),
+ MLXSW_REG(mpat),
+ MLXSW_REG(mpar),
+ MLXSW_REG(mlcr),
+ MLXSW_REG(sbpr),
+ MLXSW_REG(sbcm),
+ MLXSW_REG(sbpm),
+ MLXSW_REG(sbmm),
+ MLXSW_REG(sbsr),
+ MLXSW_REG(sbib),
+};
+
static inline const char *mlxsw_reg_id_str(u16 reg_id)
{
- switch (reg_id) {
- case MLXSW_REG_SGCR_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_SPAFT_ID:
- return "SPAFT";
- case MLXSW_REG_SFGC_ID:
- return "SFGC";
- case MLXSW_REG_SFTR_ID:
- return "SFTR";
- case MLXSW_REG_SFDF_ID:
- return "SFDF";
- case MLXSW_REG_SLDR_ID:
- return "SLDR";
- case MLXSW_REG_SLCR_ID:
- return "SLCR";
- case MLXSW_REG_SLCOR_ID:
- return "SLCOR";
- 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_QTCT_ID:
- return "QTCT";
- case MLXSW_REG_QEEC_ID:
- return "QEEC";
- case MLXSW_REG_PMLP_ID:
- return "PMLP";
- case MLXSW_REG_PMTU_ID:
- return "PMTU";
- case MLXSW_REG_PTYS_ID:
- return "PTYS";
- case MLXSW_REG_PPAD_ID:
- return "PPAD";
- case MLXSW_REG_PAOS_ID:
- return "PAOS";
- case MLXSW_REG_PFCC_ID:
- return "PFCC";
- case MLXSW_REG_PPCNT_ID:
- return "PPCNT";
- case MLXSW_REG_PPTB_ID:
- return "PPTB";
- 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_RGCR_ID:
- return "RGCR";
- case MLXSW_REG_RITR_ID:
- return "RITR";
- case MLXSW_REG_RATR_ID:
- return "RATR";
- case MLXSW_REG_RALTA_ID:
- return "RALTA";
- case MLXSW_REG_RALST_ID:
- return "RALST";
- case MLXSW_REG_RALTB_ID:
- return "RALTB";
- case MLXSW_REG_RALUE_ID:
- return "RALUE";
- case MLXSW_REG_RAUHT_ID:
- return "RAUHT";
- case MLXSW_REG_RALEU_ID:
- return "RALEU";
- case MLXSW_REG_RAUHTD_ID:
- return "RAUHTD";
- case MLXSW_REG_MFCR_ID:
- return "MFCR";
- case MLXSW_REG_MFSC_ID:
- return "MFSC";
- case MLXSW_REG_MFSM_ID:
- return "MFSM";
- case MLXSW_REG_MTCAP_ID:
- return "MTCAP";
- case MLXSW_REG_MPAT_ID:
- return "MPAT";
- case MLXSW_REG_MPAR_ID:
- return "MPAR";
- case MLXSW_REG_MTMP_ID:
- return "MTMP";
- case MLXSW_REG_MLCR_ID:
- return "MLCR";
- 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";
- case MLXSW_REG_SBSR_ID:
- return "SBSR";
- case MLXSW_REG_SBIB_ID:
- return "SBIB";
- default:
- return "*UNKNOWN*";
+ const struct mlxsw_reg_info *reg_info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_reg_infos); i++) {
+ reg_info = mlxsw_reg_infos[i];
+ if (reg_info->id == reg_id)
+ return reg_info->name;
}
+ return "*UNKNOWN*";
}
/* PUDE - Port Up / Down Event
diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h
new file mode 100644
index 000000000000..3c2171dbdba4
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h
@@ -0,0 +1,127 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/resources.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 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.
+ */
+
+#ifndef _MLXSW_RESOURCES_H
+#define _MLXSW_RESOURCES_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+enum mlxsw_res_id {
+ MLXSW_RES_ID_KVD_SIZE,
+ MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
+ MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
+ MLXSW_RES_ID_MAX_TRAP_GROUPS,
+ MLXSW_RES_ID_MAX_SPAN,
+ MLXSW_RES_ID_MAX_SYSTEM_PORT,
+ MLXSW_RES_ID_MAX_LAG,
+ MLXSW_RES_ID_MAX_LAG_MEMBERS,
+ MLXSW_RES_ID_MAX_BUFFER_SIZE,
+ MLXSW_RES_ID_MAX_CPU_POLICERS,
+ MLXSW_RES_ID_MAX_VRS,
+ MLXSW_RES_ID_MAX_RIFS,
+
+ /* Internal resources.
+ * Determined by the SW, not queried from the HW.
+ */
+ MLXSW_RES_ID_KVD_SINGLE_SIZE,
+ MLXSW_RES_ID_KVD_DOUBLE_SIZE,
+ MLXSW_RES_ID_KVD_LINEAR_SIZE,
+
+ __MLXSW_RES_ID_MAX,
+};
+
+static u16 mlxsw_res_ids[] = {
+ [MLXSW_RES_ID_KVD_SIZE] = 0x1001,
+ [MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
+ [MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
+ [MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
+ [MLXSW_RES_ID_MAX_SPAN] = 0x2420,
+ [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
+ [MLXSW_RES_ID_MAX_LAG] = 0x2520,
+ [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
+ [MLXSW_RES_ID_MAX_BUFFER_SIZE] = 0x2802, /* Bytes */
+ [MLXSW_RES_ID_MAX_CPU_POLICERS] = 0x2A13,
+ [MLXSW_RES_ID_MAX_VRS] = 0x2C01,
+ [MLXSW_RES_ID_MAX_RIFS] = 0x2C02,
+};
+
+struct mlxsw_res {
+ bool valid[__MLXSW_RES_ID_MAX];
+ u64 values[__MLXSW_RES_ID_MAX];
+};
+
+static inline bool mlxsw_res_valid(struct mlxsw_res *res,
+ enum mlxsw_res_id res_id)
+{
+ return res->valid[res_id];
+}
+
+#define MLXSW_RES_VALID(res, short_res_id) \
+ mlxsw_res_valid(res, MLXSW_RES_ID_##short_res_id)
+
+static inline u64 mlxsw_res_get(struct mlxsw_res *res,
+ enum mlxsw_res_id res_id)
+{
+ if (WARN_ON(!res->valid[res_id]))
+ return 0;
+ return res->values[res_id];
+}
+
+#define MLXSW_RES_GET(res, short_res_id) \
+ mlxsw_res_get(res, MLXSW_RES_ID_##short_res_id)
+
+static inline void mlxsw_res_set(struct mlxsw_res *res,
+ enum mlxsw_res_id res_id, u64 value)
+{
+ res->valid[res_id] = true;
+ res->values[res_id] = value;
+}
+
+#define MLXSW_RES_SET(res, short_res_id, value) \
+ mlxsw_res_set(res, MLXSW_RES_ID_##short_res_id, value)
+
+static inline void mlxsw_res_parse(struct mlxsw_res *res, u16 id, u64 value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_res_ids); i++) {
+ if (mlxsw_res_ids[i] == id) {
+ mlxsw_res_set(res, i, value);
+ return;
+ }
+ }
+}
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index dda5761e91bc..fece974b4edd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -53,12 +54,12 @@
#include <linux/dcbnl.h>
#include <linux/inetdevice.h>
#include <net/switchdev.h>
-#include <generated/utsrelease.h>
#include <net/pkt_cls.h>
#include <net/tc_act/tc_mirred.h>
#include <net/netevent.h>
#include "spectrum.h"
+#include "pci.h"
#include "core.h"
#include "reg.h"
#include "port.h"
@@ -156,7 +157,7 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
{
- char spad_pl[MLXSW_REG_SPAD_LEN];
+ char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
int err;
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl);
@@ -168,14 +169,13 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
static int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- if (!resources->max_span_valid)
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
return -EIO;
- mlxsw_sp->span.entries_count = resources->max_span;
+ mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ MAX_SPAN);
mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
sizeof(struct mlxsw_sp_span_entry),
GFP_KERNEL);
@@ -857,7 +857,7 @@ mlxsw_sp_port_get_sw_stats64(const struct net_device *dev,
return 0;
}
-static bool mlxsw_sp_port_has_offload_stats(int attr_id)
+static bool mlxsw_sp_port_has_offload_stats(const struct net_device *dev, int attr_id)
{
switch (attr_id) {
case IFLA_OFFLOAD_XSTATS_CPU_HIT:
@@ -1239,8 +1239,10 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
tcf_exts_to_list(cls->exts, &actions);
list_for_each_entry(a, &actions, list) {
- if (!is_tcf_mirred_mirror(a) || protocol != htons(ETH_P_ALL))
+ if (!is_tcf_mirred_egress_mirror(a) ||
+ protocol != htons(ETH_P_ALL)) {
return -ENOTSUPP;
+ }
err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, cls,
a, ingress);
@@ -1413,7 +1415,7 @@ err_port_pause_configure:
struct mlxsw_sp_port_hw_stats {
char str[ETH_GSTRING_LEN];
- u64 (*getter)(char *payload);
+ u64 (*getter)(const char *payload);
};
static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
@@ -1534,7 +1536,7 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
#define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
-static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(char *ppcnt_pl)
+static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(const char *ppcnt_pl)
{
u64 transmit_queue = mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl);
@@ -2002,12 +2004,12 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
int err;
autoneg = mlxsw_sp_port->link.autoneg;
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
- mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
- &eth_proto_oper);
+ mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
+ &eth_proto_oper);
mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd);
@@ -2036,11 +2038,11 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
bool autoneg;
int err;
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
- mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
+ mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
eth_proto_new = autoneg ?
@@ -2053,7 +2055,8 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
return -EINVAL;
}
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new);
+ mlxsw_reg_ptys_eth_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)
return err;
@@ -2091,8 +2094,8 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width)
u32 eth_proto_admin;
eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed);
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port,
- eth_proto_admin);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
+ eth_proto_admin);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
}
@@ -2210,8 +2213,8 @@ static int mlxsw_sp_port_pvid_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_port)
return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
}
-static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
- bool split, u8 module, u8 width, u8 lane)
+static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ bool split, u8 module, u8 width, u8 lane)
{
struct mlxsw_sp_port *mlxsw_sp_port;
struct net_device *dev;
@@ -2221,6 +2224,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
if (!dev)
return -ENOMEM;
+ SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
mlxsw_sp_port = netdev_priv(dev);
mlxsw_sp_port->dev = dev;
mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
@@ -2284,6 +2288,9 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
dev->hw_features |= NETIF_F_HW_TC;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
+
/* Each packet needs to have a Tx header (metadata) on top all other
* headers.
*/
@@ -2352,20 +2359,12 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
goto err_register_netdev;
}
- err = mlxsw_core_port_init(mlxsw_sp->core, &mlxsw_sp_port->core_port,
- mlxsw_sp_port->local_port, dev,
- mlxsw_sp_port->split, module);
- if (err) {
- dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
- mlxsw_sp_port->local_port);
- goto err_core_port_init;
- }
-
+ mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
+ mlxsw_sp_port, dev, mlxsw_sp_port->split,
+ module);
mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0);
return 0;
-err_core_port_init:
- unregister_netdev(dev);
err_register_netdev:
mlxsw_sp->ports[local_port] = NULL;
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2394,14 +2393,34 @@ err_port_active_vlans_alloc:
return err;
}
-static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ bool split, u8 module, u8 width, u8 lane)
+{
+ int err;
+
+ err = mlxsw_core_port_init(mlxsw_sp->core, local_port);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
+ local_port);
+ return err;
+ }
+ err = __mlxsw_sp_port_create(mlxsw_sp, local_port, false,
+ module, width, lane);
+ if (err)
+ goto err_port_create;
+ return 0;
+
+err_port_create:
+ mlxsw_core_port_fini(mlxsw_sp->core, local_port);
+ return err;
+}
+
+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;
cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw);
- mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
+ mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
mlxsw_sp->ports[local_port] = NULL;
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2417,12 +2436,24 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
free_netdev(mlxsw_sp_port->dev);
}
+static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+ __mlxsw_sp_port_remove(mlxsw_sp, local_port);
+ mlxsw_core_port_fini(mlxsw_sp->core, local_port);
+}
+
+static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+ return mlxsw_sp->ports[local_port] != NULL;
+}
+
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);
+ if (mlxsw_sp_port_created(mlxsw_sp, i))
+ mlxsw_sp_port_remove(mlxsw_sp, i);
kfree(mlxsw_sp->ports);
}
@@ -2446,8 +2477,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
if (!width)
continue;
mlxsw_sp->port_to_module[i] = module;
- err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width,
- lane);
+ err = mlxsw_sp_port_create(mlxsw_sp, i, false,
+ module, width, lane);
if (err)
goto err_port_create;
}
@@ -2456,7 +2487,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
err_port_create:
err_port_module_info_get:
for (i--; i >= 1; i--)
- mlxsw_sp_port_remove(mlxsw_sp, i);
+ if (mlxsw_sp_port_created(mlxsw_sp, i))
+ mlxsw_sp_port_remove(mlxsw_sp, i);
kfree(mlxsw_sp->ports);
return err;
}
@@ -2498,7 +2530,8 @@ static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
err_port_create:
for (i--; i >= 0; i--)
- mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+ if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+ mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
i = count;
err_port_swid_set:
for (i--; i >= 0; i--)
@@ -2588,7 +2621,8 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
}
for (i = 0; i < count; i++)
- mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+ if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+ mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count);
if (err) {
@@ -2633,7 +2667,8 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
base_port = base_port + 2;
for (i = 0; i < count; i++)
- mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+ if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+ mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
@@ -2663,54 +2698,8 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
}
}
-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)
+static void mlxsw_sp_rx_listener_no_mark_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];
@@ -2738,107 +2727,212 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port,
void *priv)
{
skb->offload_fwd_mark = 1;
- return mlxsw_sp_rx_listener_func(skb, local_port, priv);
+ return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
+}
+
+#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl) \
+ MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \
+ _is_ctrl, SP_##_trap_group, DISCARD)
+
+#define MLXSW_SP_RXL_MARK(_trap_id, _action, _trap_group, _is_ctrl) \
+ MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \
+ _is_ctrl, SP_##_trap_group, DISCARD)
+
+#define MLXSW_SP_EVENTL(_func, _trap_id) \
+ MLXSW_EVENTL(_func, _trap_id, SP_EVENT)
+
+static const struct mlxsw_listener mlxsw_sp_listener[] = {
+ /* Events */
+ MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE),
+ /* L2 traps */
+ MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true),
+ MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true),
+ MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, LLDP, true),
+ MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false),
+ MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false),
+ MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false),
+ MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, IGMP, false),
+ MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, IGMP, false),
+ MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, IGMP, false),
+ MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false),
+ MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false),
+ /* L3 traps */
+ MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+ MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+ MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+ MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, OSPF, false),
+ MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false),
+ MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false),
+ MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false),
+ MLXSW_SP_RXL_NO_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false),
+};
+
+static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
+{
+ char qpcr_pl[MLXSW_REG_QPCR_LEN];
+ enum mlxsw_reg_qpcr_ir_units ir_units;
+ int max_cpu_policers;
+ bool is_bytes;
+ u8 burst_size;
+ u32 rate;
+ int i, err;
+
+ if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
+ return -EIO;
+
+ max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
+
+ ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
+ for (i = 0; i < max_cpu_policers; i++) {
+ is_bytes = false;
+ switch (i) {
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
+ rate = 128;
+ burst_size = 7;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
+ rate = 16 * 1024;
+ burst_size = 10;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
+ rate = 1024;
+ burst_size = 7;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
+ is_bytes = true;
+ rate = 4 * 1024;
+ burst_size = 4;
+ break;
+ default:
+ continue;
+ }
+
+ mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate,
+ burst_size);
+ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
-#define MLXSW_SP_RXL(_func, _trap_id, _action) \
- { \
- .func = _func, \
- .local_port = MLXSW_PORT_DONT_CARE, \
- .trap_id = MLXSW_TRAP_ID_##_trap_id, \
- .action = MLXSW_REG_HPKT_ACTION_##_action, \
+static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+ char htgt_pl[MLXSW_REG_HTGT_LEN];
+ enum mlxsw_reg_htgt_trap_group i;
+ int max_cpu_policers;
+ int max_trap_groups;
+ u8 priority, tc;
+ u16 policer_id;
+ int err;
+
+ if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS))
+ return -EIO;
+
+ max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS);
+ max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
+
+ for (i = 0; i < max_trap_groups; i++) {
+ policer_id = i;
+ switch (i) {
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
+ priority = 5;
+ tc = 5;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
+ priority = 4;
+ tc = 4;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
+ priority = 3;
+ tc = 3;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
+ priority = 2;
+ tc = 2;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
+ priority = 1;
+ tc = 1;
+ break;
+ case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT:
+ priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY;
+ tc = MLXSW_REG_HTGT_DEFAULT_TC;
+ policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
+ break;
+ default:
+ continue;
+ }
+
+ if (max_cpu_policers <= policer_id &&
+ policer_id != MLXSW_REG_HTGT_INVALID_POLICER)
+ return -EIO;
+
+ mlxsw_reg_htgt_pack(htgt_pl, i, policer_id, priority, tc);
+ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+ if (err)
+ return err;
}
-static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = {
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, FDB_MC, TRAP_TO_CPU),
- /* Traps for specific L2 packet types, not trapped as FDB MC */
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, STP, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LACP, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, EAPOL, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LLDP, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MMRP, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MVRP, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RPVST, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, DHCP, MIRROR_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, IGMP_QUERY, MIRROR_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V1_REPORT, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_REPORT, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_LEAVE, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V3_REPORT, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPBC, MIRROR_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPUC, MIRROR_TO_CPU),
- /* L3 traps */
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MTUERROR, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, TTLERROR, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LBERROR, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, OSPF, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IP2ME, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RTR_INGRESS0, TRAP_TO_CPU),
- MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, HOST_MISS_IPV4, TRAP_TO_CPU),
-};
+ return 0;
+}
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);
+ err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
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);
+ err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
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);
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+ err = mlxsw_core_trap_register(mlxsw_sp->core,
+ &mlxsw_sp_listener[i],
+ mlxsw_sp);
if (err)
- goto err_rx_listener_register;
+ goto err_listener_register;
- mlxsw_reg_hpkt_pack(hpkt_pl, mlxsw_sp_rx_listener[i].action,
- 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:
+err_listener_register:
for (i--; i >= 0; i--) {
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD,
- 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);
+ mlxsw_core_trap_unregister(mlxsw_sp->core,
+ &mlxsw_sp_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_DISCARD,
- 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);
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+ mlxsw_core_trap_unregister(mlxsw_sp->core,
+ &mlxsw_sp_listener[i],
+ mlxsw_sp);
}
}
@@ -2889,7 +2983,6 @@ static int mlxsw_sp_flood_init(struct mlxsw_sp *mlxsw_sp)
static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
char slcr_pl[MLXSW_REG_SLCR_LEN];
int err;
@@ -2906,11 +2999,11 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
if (err)
return err;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- if (!(resources->max_lag_valid && resources->max_ports_in_lag_valid))
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
+ !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
return -EIO;
- mlxsw_sp->lags = kcalloc(resources->max_lag,
+ mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
sizeof(struct mlxsw_sp_upper),
GFP_KERNEL);
if (!mlxsw_sp->lags)
@@ -2924,6 +3017,17 @@ static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp)
kfree(mlxsw_sp->lags);
}
+static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+ char htgt_pl[MLXSW_REG_HTGT_LEN];
+
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+ MLXSW_REG_HTGT_INVALID_POLICER,
+ MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+ MLXSW_REG_HTGT_DEFAULT_TC);
+ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+}
+
static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info)
{
@@ -2942,16 +3046,10 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
return err;
}
- 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");
- return err;
- }
-
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;
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n");
+ return err;
}
err = mlxsw_sp_flood_init(mlxsw_sp);
@@ -3011,8 +3109,6 @@ err_lag_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);
return err;
}
@@ -3027,7 +3123,6 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_buffers_fini(mlxsw_sp);
mlxsw_sp_traps_fini(mlxsw_sp);
- mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
WARN_ON(!list_empty(&mlxsw_sp->vfids.list));
WARN_ON(!list_empty(&mlxsw_sp->fids));
}
@@ -3065,11 +3160,11 @@ static struct mlxsw_config_profile mlxsw_sp_config_profile = {
};
static struct mlxsw_driver mlxsw_sp_driver = {
- .kind = MLXSW_DEVICE_KIND_SPECTRUM,
- .owner = THIS_MODULE,
+ .kind = mlxsw_sp_driver_name,
.priv_size = sizeof(struct mlxsw_sp),
.init = mlxsw_sp_init,
.fini = mlxsw_sp_fini,
+ .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set,
.port_split = mlxsw_sp_port_split,
.port_unsplit = mlxsw_sp_port_unsplit,
.sb_pool_get = mlxsw_sp_sb_pool_get,
@@ -3092,19 +3187,30 @@ static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
}
+static int mlxsw_lower_dev_walk(struct net_device *lower_dev, void *data)
+{
+ struct mlxsw_sp_port **port = data;
+ int ret = 0;
+
+ if (mlxsw_sp_port_dev_check(lower_dev)) {
+ *port = netdev_priv(lower_dev);
+ ret = 1;
+ }
+
+ return ret;
+}
+
static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
{
- struct net_device *lower_dev;
- struct list_head *iter;
+ struct mlxsw_sp_port *port;
if (mlxsw_sp_port_dev_check(dev))
return netdev_priv(dev);
- netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
- if (mlxsw_sp_port_dev_check(lower_dev))
- return netdev_priv(lower_dev);
- }
- return NULL;
+ port = NULL;
+ netdev_walk_all_lower_dev(dev, mlxsw_lower_dev_walk, &port);
+
+ return port;
}
static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
@@ -3117,17 +3223,15 @@ static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
{
- struct net_device *lower_dev;
- struct list_head *iter;
+ struct mlxsw_sp_port *port;
if (mlxsw_sp_port_dev_check(dev))
return netdev_priv(dev);
- netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) {
- if (mlxsw_sp_port_dev_check(lower_dev))
- return netdev_priv(lower_dev);
- }
- return NULL;
+ port = NULL;
+ netdev_walk_all_lower_dev_rcu(dev, mlxsw_lower_dev_walk, &port);
+
+ return port;
}
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
@@ -3171,11 +3275,9 @@ static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *r,
static int mlxsw_sp_avail_rif_get(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_rif; i++)
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
if (!mlxsw_sp->rifs[i])
return i;
@@ -3698,14 +3800,15 @@ static bool mlxsw_sp_port_fdb_should_flush(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
u8 local_port = mlxsw_sp_port->local_port;
u16 lag_id = mlxsw_sp_port->lag_id;
- struct mlxsw_resources *resources;
+ u64 max_lag_members;
int i, count = 0;
if (!mlxsw_sp_port->lagged)
return true;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_ports_in_lag; i++) {
+ max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ MAX_LAG_MEMBERS);
+ for (i = 0; i < max_lag_members; i++) {
struct mlxsw_sp_port *lag_port;
lag_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
@@ -3911,13 +4014,13 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
struct net_device *lag_dev,
u16 *p_lag_id)
{
- struct mlxsw_resources *resources;
struct mlxsw_sp_upper *lag;
int free_lag_id = -1;
+ u64 max_lag;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_lag; i++) {
+ max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
+ for (i = 0; i < max_lag; i++) {
lag = mlxsw_sp_lag_get(mlxsw_sp, i);
if (lag->ref_count) {
if (lag->dev == lag_dev) {
@@ -3951,11 +4054,12 @@ mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
u16 lag_id, u8 *p_port_index)
{
- struct mlxsw_resources *resources;
+ u64 max_lag_members;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_ports_in_lag; i++) {
+ max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ MAX_LAG_MEMBERS);
+ for (i = 0; i < max_lag_members; i++) {
if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) {
*p_port_index = i;
return 0;
@@ -4652,6 +4756,16 @@ static struct notifier_block mlxsw_sp_router_netevent_nb __read_mostly = {
.notifier_call = mlxsw_sp_router_netevent_event,
};
+static const struct pci_device_id mlxsw_sp_pci_id_table[] = {
+ {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
+ {0, },
+};
+
+static struct pci_driver mlxsw_sp_pci_driver = {
+ .name = mlxsw_sp_driver_name,
+ .id_table = mlxsw_sp_pci_id_table,
+};
+
static int __init mlxsw_sp_module_init(void)
{
int err;
@@ -4663,8 +4777,15 @@ static int __init mlxsw_sp_module_init(void)
err = mlxsw_core_driver_register(&mlxsw_sp_driver);
if (err)
goto err_core_driver_register;
+
+ err = mlxsw_pci_driver_register(&mlxsw_sp_pci_driver);
+ if (err)
+ goto err_pci_driver_register;
+
return 0;
+err_pci_driver_register:
+ mlxsw_core_driver_unregister(&mlxsw_sp_driver);
err_core_driver_register:
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4674,6 +4795,7 @@ err_core_driver_register:
static void __exit mlxsw_sp_module_exit(void)
{
+ mlxsw_pci_driver_unregister(&mlxsw_sp_pci_driver);
mlxsw_core_driver_unregister(&mlxsw_sp_driver);
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4686,4 +4808,4 @@ 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);
+MODULE_DEVICE_TABLE(pci, mlxsw_sp_pci_id_table);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 97bbc1d21df8..cc1af19d699a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -316,7 +316,6 @@ struct mlxsw_sp_port_pcpu_stats {
};
struct mlxsw_sp_port {
- struct mlxsw_core_port core_port; /* must be first */
struct net_device *dev;
struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
struct mlxsw_sp *mlxsw_sp;
@@ -479,12 +478,9 @@ static inline struct mlxsw_sp_rif *
mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
const struct net_device *dev)
{
- struct mlxsw_resources *resources;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
-
- for (i = 0; i < resources->max_rif; i++)
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
if (mlxsw_sp->rifs[i] && mlxsw_sp->rifs[i]->dev == dev)
return mlxsw_sp->rifs[i];
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index bcaed8a38037..a7468262f118 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -611,6 +611,9 @@ int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core,
u32 pool_size = MLXSW_SP_BYTES_TO_CELLS(size);
enum mlxsw_reg_sbpr_mode mode;
+ if (size > MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE))
+ return -EINVAL;
+
mode = (enum mlxsw_reg_sbpr_mode) threshold_type;
return mlxsw_sp_sb_pr_write(mlxsw_sp, pool, dir, mode, pool_size);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index e83072da6272..53126bf68ea9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -382,12 +382,10 @@ static void mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
struct mlxsw_sp_vr *vr;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_virtual_routers; i++) {
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
vr = &mlxsw_sp->router.vrs[i];
if (!vr->used)
return vr;
@@ -429,14 +427,12 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
u32 tb_id,
enum mlxsw_sp_l3proto proto)
{
- struct mlxsw_resources *resources;
struct mlxsw_sp_vr *vr;
int i;
tb_id = mlxsw_sp_fix_tb_id(tb_id);
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_virtual_routers; i++) {
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
vr = &mlxsw_sp->router.vrs[i];
if (vr->used && vr->proto == proto && vr->tb_id == tb_id)
return vr;
@@ -572,21 +568,20 @@ static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
struct mlxsw_sp_vr *vr;
+ u64 max_vrs;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- if (!resources->max_virtual_routers_valid)
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
return -EIO;
- mlxsw_sp->router.vrs = kcalloc(resources->max_virtual_routers,
- sizeof(struct mlxsw_sp_vr),
+ max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
+ mlxsw_sp->router.vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
GFP_KERNEL);
if (!mlxsw_sp->router.vrs)
return -ENOMEM;
- for (i = 0; i < resources->max_virtual_routers; i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router.vrs[i];
vr->id = i;
}
@@ -598,6 +593,14 @@ static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
{
+ /* At this stage we're guaranteed not to have new incoming
+ * FIB notifications and the work queue is free from FIBs
+ * sitting on top of mlxsw netdevs. However, we can still
+ * have other FIBs queued. Flush the queue before flushing
+ * the device's tables. No need for locks, as we're the only
+ * writer.
+ */
+ mlxsw_core_flush_owq();
mlxsw_sp_router_fib_flush(mlxsw_sp);
kfree(mlxsw_sp->router.vrs);
}
@@ -1872,14 +1875,12 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
struct mlxsw_sp_fib_entry *fib_entry;
struct mlxsw_sp_fib_entry *tmp;
struct mlxsw_sp_vr *vr;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_virtual_routers; i++) {
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
vr = &mlxsw_sp->router.vrs[i];
if (!vr->used)
@@ -1903,6 +1904,9 @@ static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp)
{
int err;
+ if (mlxsw_sp->router.aborted)
+ return;
+ dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
mlxsw_sp_router_fib_flush(mlxsw_sp);
mlxsw_sp->router.aborted = true;
err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
@@ -1912,21 +1916,21 @@ static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp)
static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
char rgcr_pl[MLXSW_REG_RGCR_LEN];
+ u64 max_rifs;
int err;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- if (!resources->max_rif_valid)
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
return -EIO;
- mlxsw_sp->rifs = kcalloc(resources->max_rif,
- sizeof(struct mlxsw_sp_rif *), GFP_KERNEL);
+ max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
+ mlxsw_sp->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *),
+ GFP_KERNEL);
if (!mlxsw_sp->rifs)
return -ENOMEM;
mlxsw_reg_rgcr_pack(rgcr_pl, true);
- mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, resources->max_rif);
+ mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
if (err)
goto err_rgcr_fail;
@@ -1940,47 +1944,101 @@ err_rgcr_fail:
static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
{
- struct mlxsw_resources *resources;
char rgcr_pl[MLXSW_REG_RGCR_LEN];
int i;
mlxsw_reg_rgcr_pack(rgcr_pl, false);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_rif; i++)
+ for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
WARN_ON_ONCE(mlxsw_sp->rifs[i]);
kfree(mlxsw_sp->rifs);
}
-static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
- unsigned long event, void *ptr)
+struct mlxsw_sp_fib_event_work {
+ struct delayed_work dw;
+ struct fib_entry_notifier_info fen_info;
+ struct mlxsw_sp *mlxsw_sp;
+ unsigned long event;
+};
+
+static void mlxsw_sp_router_fib_event_work(struct work_struct *work)
{
- struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
- struct fib_entry_notifier_info *fen_info = ptr;
+ struct mlxsw_sp_fib_event_work *fib_work =
+ container_of(work, struct mlxsw_sp_fib_event_work, dw.work);
+ struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
int err;
- if (!net_eq(fen_info->info.net, &init_net))
- return NOTIFY_DONE;
-
- switch (event) {
+ /* Protect internal structures from changes */
+ rtnl_lock();
+ switch (fib_work->event) {
case FIB_EVENT_ENTRY_ADD:
- err = mlxsw_sp_router_fib4_add(mlxsw_sp, fen_info);
+ err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info);
if (err)
mlxsw_sp_router_fib4_abort(mlxsw_sp);
+ fib_info_put(fib_work->fen_info.fi);
break;
case FIB_EVENT_ENTRY_DEL:
- mlxsw_sp_router_fib4_del(mlxsw_sp, fen_info);
+ mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
+ fib_info_put(fib_work->fen_info.fi);
break;
case FIB_EVENT_RULE_ADD: /* fall through */
case FIB_EVENT_RULE_DEL:
mlxsw_sp_router_fib4_abort(mlxsw_sp);
break;
}
+ rtnl_unlock();
+ kfree(fib_work);
+}
+
+/* Called with rcu_read_lock() */
+static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
+ struct mlxsw_sp_fib_event_work *fib_work;
+ struct fib_notifier_info *info = ptr;
+
+ if (!net_eq(info->net, &init_net))
+ return NOTIFY_DONE;
+
+ fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
+ if (WARN_ON(!fib_work))
+ return NOTIFY_BAD;
+
+ INIT_DELAYED_WORK(&fib_work->dw, mlxsw_sp_router_fib_event_work);
+ fib_work->mlxsw_sp = mlxsw_sp;
+ fib_work->event = event;
+
+ switch (event) {
+ case FIB_EVENT_ENTRY_ADD: /* fall through */
+ case FIB_EVENT_ENTRY_DEL:
+ memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info));
+ /* Take referece on fib_info to prevent it from being
+ * freed while work is queued. Release it afterwards.
+ */
+ fib_info_hold(fib_work->fen_info.fi);
+ break;
+ }
+
+ mlxsw_core_schedule_odw(&fib_work->dw, 0);
+
return NOTIFY_DONE;
}
+static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
+{
+ struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
+
+ /* Flush pending FIB notifications and then flush the device's
+ * table before requesting another dump. The FIB notification
+ * block is unregistered, so no need to take RTNL.
+ */
+ mlxsw_core_flush_owq();
+ mlxsw_sp_router_fib_flush(mlxsw_sp);
+}
+
int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
{
int err;
@@ -1996,14 +2054,20 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
if (err)
goto err_vrs_init;
- err = mlxsw_sp_neigh_init(mlxsw_sp);
+ err = mlxsw_sp_neigh_init(mlxsw_sp);
if (err)
goto err_neigh_init;
mlxsw_sp->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
- register_fib_notifier(&mlxsw_sp->fib_nb);
+ err = register_fib_notifier(&mlxsw_sp->fib_nb,
+ mlxsw_sp_router_fib_dump_flush);
+ if (err)
+ goto err_register_fib_notifier;
+
return 0;
+err_register_fib_notifier:
+ mlxsw_sp_neigh_fini(mlxsw_sp);
err_neigh_init:
mlxsw_sp_vrs_fini(mlxsw_sp);
err_vrs_init:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 1e2c8eca3af1..b87ba7d36bc4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1196,11 +1196,12 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
u16 lag_id)
{
struct mlxsw_sp_port *mlxsw_sp_port;
- struct mlxsw_resources *resources;
+ u64 max_lag_members;
int i;
- resources = mlxsw_core_resources_get(mlxsw_sp->core);
- for (i = 0; i < resources->max_ports_in_lag; i++) {
+ max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ MAX_LAG_MEMBERS);
+ for (i = 0; i < max_lag_members; i++) {
mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
if (mlxsw_sp_port)
return mlxsw_sp_port;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c
new file mode 100644
index 000000000000..74341fe0eb25
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c
@@ -0,0 +1,605 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/switchib.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 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/pci.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 <net/switchdev.h>
+
+#include "pci.h"
+#include "core.h"
+#include "reg.h"
+#include "port.h"
+#include "trap.h"
+#include "txheader.h"
+#include "ib.h"
+
+static const char mlxsw_sib_driver_name[] = "mlxsw_switchib";
+static const char mlxsw_sib2_driver_name[] = "mlxsw_switchib2";
+
+struct mlxsw_sib_port;
+
+struct mlxsw_sib {
+ struct mlxsw_sib_port **ports;
+ struct mlxsw_core *core;
+ const struct mlxsw_bus_info *bus_info;
+};
+
+struct mlxsw_sib_port {
+ struct mlxsw_sib *mlxsw_sib;
+ u8 local_port;
+ struct {
+ u8 module;
+ } mapping;
+};
+
+/* tx_v1_hdr_version
+ * Tx header version.
+ * Must be set to 1.
+ */
+MLXSW_ITEM32(tx_v1, hdr, version, 0x00, 28, 4);
+
+/* tx_v1_hdr_ctl
+ * Packet control type.
+ * 0 - Ethernet control (e.g. EMADs, LACP)
+ * 1 - Ethernet data
+ */
+MLXSW_ITEM32(tx_v1, hdr, ctl, 0x00, 26, 2);
+
+/* tx_v1_hdr_proto
+ * Packet protocol type. Must be set to 1 (Ethernet).
+ */
+MLXSW_ITEM32(tx_v1, hdr, proto, 0x00, 21, 3);
+
+/* tx_v1_hdr_swid
+ * Switch partition ID. Must be set to 0.
+ */
+MLXSW_ITEM32(tx_v1, hdr, swid, 0x00, 12, 3);
+
+/* tx_v1_hdr_control_tclass
+ * Indicates if the packet should use the control TClass and not one
+ * of the data TClasses.
+ */
+MLXSW_ITEM32(tx_v1, hdr, control_tclass, 0x00, 6, 1);
+
+/* tx_v1_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_v1, hdr, port_mid, 0x04, 16, 16);
+
+/* tx_v1_hdr_type
+ * 0 - Data packets
+ * 6 - Control packets
+ */
+MLXSW_ITEM32(tx_v1, hdr, type, 0x0C, 0, 4);
+
+static void
+mlxsw_sib_tx_v1_hdr_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_v1_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
+ mlxsw_tx_v1_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
+ mlxsw_tx_v1_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
+ mlxsw_tx_v1_hdr_swid_set(txhdr, 0);
+ mlxsw_tx_v1_hdr_control_tclass_set(txhdr, 1);
+ mlxsw_tx_v1_hdr_port_mid_set(txhdr, tx_info->local_port);
+ mlxsw_tx_v1_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
+}
+
+static int
+mlxsw_sib_port_admin_status_set(struct mlxsw_sib_port *mlxsw_sib_port,
+ bool is_up)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+ char paos_pl[MLXSW_REG_PAOS_LEN];
+
+ mlxsw_reg_paos_pack(paos_pl, mlxsw_sib_port->local_port,
+ is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
+ MLXSW_PORT_ADMIN_STATUS_DOWN);
+ return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(paos), paos_pl);
+}
+
+static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port,
+ u16 mtu)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+ char pmtu_pl[MLXSW_REG_PMTU_LEN];
+ int max_mtu;
+ int err;
+
+ mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0);
+ err = mlxsw_reg_query(mlxsw_sib->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_sib_port->local_port, mtu);
+ return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl);
+}
+
+static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+ char plib_pl[MLXSW_REG_PLIB_LEN] = {0};
+ int err;
+
+ mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port);
+ mlxsw_reg_plib_ib_port_set(plib_pl, port);
+ err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl);
+ return err;
+}
+
+static int mlxsw_sib_port_swid_set(struct mlxsw_sib_port *mlxsw_sib_port,
+ u8 swid)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+ char pspa_pl[MLXSW_REG_PSPA_LEN];
+
+ mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sib_port->local_port);
+ return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pspa), pspa_pl);
+}
+
+static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib,
+ u8 local_port, u8 *p_module,
+ u8 *p_width)
+{
+ char pmlp_pl[MLXSW_REG_PMLP_LEN];
+ int err;
+
+ mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+ err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl);
+ if (err)
+ return err;
+ *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+ *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+ return 0;
+}
+
+static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port,
+ u16 speed, u16 width)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+ char ptys_pl[MLXSW_REG_PTYS_LEN];
+
+ mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed,
+ width);
+ return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl);
+}
+
+static bool mlxsw_sib_port_created(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+ return mlxsw_sib->ports[local_port] != NULL;
+}
+
+static int __mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
+ u8 module, u8 width)
+{
+ struct mlxsw_sib_port *mlxsw_sib_port;
+ int err;
+
+ mlxsw_sib_port = kzalloc(sizeof(*mlxsw_sib_port), GFP_KERNEL);
+ if (!mlxsw_sib_port)
+ return -ENOMEM;
+ mlxsw_sib_port->mlxsw_sib = mlxsw_sib;
+ mlxsw_sib_port->local_port = local_port;
+ mlxsw_sib_port->mapping.module = module;
+
+ err = mlxsw_sib_port_swid_set(mlxsw_sib_port, 0);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set SWID\n",
+ mlxsw_sib_port->local_port);
+ goto err_port_swid_set;
+ }
+
+ /* Expose the IB port number as it's front panel name */
+ err = mlxsw_sib_port_set(mlxsw_sib_port, module + 1);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set IB port\n",
+ mlxsw_sib_port->local_port);
+ goto err_port_ib_set;
+ }
+
+ /* Supports all speeds from SDR to FDR (bitmask) and support bus width
+ * of 1x, 2x and 4x (3 bits bitmask)
+ */
+ err = mlxsw_sib_port_speed_set(mlxsw_sib_port,
+ MLXSW_REG_PTYS_IB_SPEED_EDR - 1,
+ BIT(3) - 1);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set speed\n",
+ mlxsw_sib_port->local_port);
+ goto err_port_speed_set;
+ }
+
+ /* Change to the maximum MTU the device supports, the SMA will take
+ * care of the active MTU
+ */
+ err = mlxsw_sib_port_mtu_set(mlxsw_sib_port, MLXSW_IB_DEFAULT_MTU);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set MTU\n",
+ mlxsw_sib_port->local_port);
+ goto err_port_mtu_set;
+ }
+
+ err = mlxsw_sib_port_admin_status_set(mlxsw_sib_port, true);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to change admin state to UP\n",
+ mlxsw_sib_port->local_port);
+ goto err_port_admin_set;
+ }
+
+ mlxsw_core_port_ib_set(mlxsw_sib->core, mlxsw_sib_port->local_port,
+ mlxsw_sib_port);
+ mlxsw_sib->ports[local_port] = mlxsw_sib_port;
+ return 0;
+
+err_port_admin_set:
+err_port_mtu_set:
+err_port_speed_set:
+err_port_ib_set:
+ mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
+err_port_swid_set:
+ kfree(mlxsw_sib_port);
+ return err;
+}
+
+static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
+ u8 module, u8 width)
+{
+ int err;
+
+ err = mlxsw_core_port_init(mlxsw_sib->core, local_port);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n",
+ local_port);
+ return err;
+ }
+ err = __mlxsw_sib_port_create(mlxsw_sib, local_port, module, width);
+ if (err)
+ goto err_port_create;
+
+ return 0;
+
+err_port_create:
+ mlxsw_core_port_fini(mlxsw_sib->core, local_port);
+ return err;
+}
+
+static void __mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+ struct mlxsw_sib_port *mlxsw_sib_port = mlxsw_sib->ports[local_port];
+
+ mlxsw_core_port_clear(mlxsw_sib->core, local_port, mlxsw_sib);
+ mlxsw_sib->ports[local_port] = NULL;
+ mlxsw_sib_port_admin_status_set(mlxsw_sib_port, false);
+ mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
+ kfree(mlxsw_sib_port);
+}
+
+static void mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+ __mlxsw_sib_port_remove(mlxsw_sib, local_port);
+ mlxsw_core_port_fini(mlxsw_sib->core, local_port);
+}
+
+static void mlxsw_sib_ports_remove(struct mlxsw_sib *mlxsw_sib)
+{
+ int i;
+
+ for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++)
+ if (mlxsw_sib_port_created(mlxsw_sib, i))
+ mlxsw_sib_port_remove(mlxsw_sib, i);
+ kfree(mlxsw_sib->ports);
+}
+
+static int mlxsw_sib_ports_create(struct mlxsw_sib *mlxsw_sib)
+{
+ size_t alloc_size;
+ u8 module, width;
+ int i;
+ int err;
+
+ alloc_size = sizeof(struct mlxsw_sib_port *) * MLXSW_PORT_MAX_IB_PORTS;
+ mlxsw_sib->ports = kzalloc(alloc_size, GFP_KERNEL);
+ if (!mlxsw_sib->ports)
+ return -ENOMEM;
+
+ for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) {
+ err = mlxsw_sib_port_module_info_get(mlxsw_sib, i, &module,
+ &width);
+ if (err)
+ goto err_port_module_info_get;
+ if (!width)
+ continue;
+ err = mlxsw_sib_port_create(mlxsw_sib, i, module, width);
+ if (err)
+ goto err_port_create;
+ }
+ return 0;
+
+err_port_create:
+err_port_module_info_get:
+ for (i--; i >= 1; i--)
+ if (mlxsw_sib_port_created(mlxsw_sib, i))
+ mlxsw_sib_port_remove(mlxsw_sib, i);
+ kfree(mlxsw_sib->ports);
+ return err;
+}
+
+static void
+mlxsw_sib_pude_ib_event_func(struct mlxsw_sib_port *mlxsw_sib_port,
+ enum mlxsw_reg_pude_oper_status status)
+{
+ if (status == MLXSW_PORT_OPER_STATUS_UP)
+ pr_info("ib link for port %d - up\n",
+ mlxsw_sib_port->mapping.module + 1);
+ else
+ pr_info("ib link for port %d - down\n",
+ mlxsw_sib_port->mapping.module + 1);
+}
+
+static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg,
+ char *pude_pl, void *priv)
+{
+ struct mlxsw_sib *mlxsw_sib = priv;
+ struct mlxsw_sib_port *mlxsw_sib_port;
+ enum mlxsw_reg_pude_oper_status status;
+ u8 local_port;
+
+ local_port = mlxsw_reg_pude_local_port_get(pude_pl);
+ mlxsw_sib_port = mlxsw_sib->ports[local_port];
+ if (!mlxsw_sib_port) {
+ dev_warn(mlxsw_sib->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);
+ mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status);
+}
+
+static const struct mlxsw_listener mlxsw_sib_listener[] = {
+ MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE, EMAD),
+};
+
+static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib)
+{
+ int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
+ err = mlxsw_core_trap_register(mlxsw_sib->core,
+ &mlxsw_sib_listener[i],
+ mlxsw_sib);
+ if (err)
+ goto err_rx_listener_register;
+ }
+
+ return 0;
+
+err_rx_listener_register:
+ for (i--; i >= 0; i--) {
+ mlxsw_core_trap_unregister(mlxsw_sib->core,
+ &mlxsw_sib_listener[i],
+ mlxsw_sib);
+ }
+
+ return err;
+}
+
+static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
+ mlxsw_core_trap_unregister(mlxsw_sib->core,
+ &mlxsw_sib_listener[i], mlxsw_sib);
+ }
+}
+
+static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+ char htgt_pl[MLXSW_REG_HTGT_LEN];
+
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+ MLXSW_REG_HTGT_INVALID_POLICER,
+ MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+ MLXSW_REG_HTGT_DEFAULT_TC);
+ mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS);
+ mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD);
+ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+}
+
+static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *mlxsw_bus_info)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
+ int err;
+
+ mlxsw_sib->core = mlxsw_core;
+ mlxsw_sib->bus_info = mlxsw_bus_info;
+
+ err = mlxsw_sib_ports_create(mlxsw_sib);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Failed to create ports\n");
+ return err;
+ }
+
+ err = mlxsw_sib_taps_init(mlxsw_sib);
+ if (err) {
+ dev_err(mlxsw_sib->bus_info->dev, "Failed to set traps\n");
+ goto err_traps_init_err;
+ }
+
+ return 0;
+
+err_traps_init_err:
+ mlxsw_sib_ports_remove(mlxsw_sib);
+ return err;
+}
+
+static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core)
+{
+ struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
+
+ mlxsw_sib_traps_fini(mlxsw_sib);
+ mlxsw_sib_ports_remove(mlxsw_sib);
+}
+
+static struct mlxsw_config_profile mlxsw_sib_config_profile = {
+ .used_max_system_port = 1,
+ .max_system_port = 48000,
+ .used_max_ib_mc = 1,
+ .max_ib_mc = 27,
+ .used_max_pkey = 1,
+ .max_pkey = 32,
+ .swid_config = {
+ {
+ .used_type = 1,
+ .type = MLXSW_PORT_SWID_TYPE_IB,
+ }
+ },
+ .resource_query_enable = 0,
+};
+
+static struct mlxsw_driver mlxsw_sib_driver = {
+ .kind = mlxsw_sib_driver_name,
+ .priv_size = sizeof(struct mlxsw_sib),
+ .init = mlxsw_sib_init,
+ .fini = mlxsw_sib_fini,
+ .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set,
+ .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct,
+ .txhdr_len = MLXSW_TXHDR_LEN,
+ .profile = &mlxsw_sib_config_profile,
+};
+
+static struct mlxsw_driver mlxsw_sib2_driver = {
+ .kind = mlxsw_sib2_driver_name,
+ .priv_size = sizeof(struct mlxsw_sib),
+ .init = mlxsw_sib_init,
+ .fini = mlxsw_sib_fini,
+ .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set,
+ .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct,
+ .txhdr_len = MLXSW_TXHDR_LEN,
+ .profile = &mlxsw_sib_config_profile,
+};
+
+static const struct pci_device_id mlxsw_sib_pci_id_table[] = {
+ {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB), 0},
+ {0, },
+};
+
+static struct pci_driver mlxsw_sib_pci_driver = {
+ .name = mlxsw_sib_driver_name,
+ .id_table = mlxsw_sib_pci_id_table,
+};
+
+static const struct pci_device_id mlxsw_sib2_pci_id_table[] = {
+ {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB2), 0},
+ {0, },
+};
+
+static struct pci_driver mlxsw_sib2_pci_driver = {
+ .name = mlxsw_sib2_driver_name,
+ .id_table = mlxsw_sib2_pci_id_table,
+};
+
+static int __init mlxsw_sib_module_init(void)
+{
+ int err;
+
+ err = mlxsw_core_driver_register(&mlxsw_sib_driver);
+ if (err)
+ return err;
+
+ err = mlxsw_core_driver_register(&mlxsw_sib2_driver);
+ if (err)
+ goto err_sib2_driver_register;
+
+ err = mlxsw_pci_driver_register(&mlxsw_sib_pci_driver);
+ if (err)
+ goto err_sib_pci_driver_register;
+
+ err = mlxsw_pci_driver_register(&mlxsw_sib2_pci_driver);
+ if (err)
+ goto err_sib2_pci_driver_register;
+
+ return 0;
+
+err_sib2_pci_driver_register:
+ mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver);
+err_sib_pci_driver_register:
+ mlxsw_core_driver_unregister(&mlxsw_sib2_driver);
+err_sib2_driver_register:
+ mlxsw_core_driver_unregister(&mlxsw_sib_driver);
+ return err;
+}
+
+static void __exit mlxsw_sib_module_exit(void)
+{
+ mlxsw_pci_driver_unregister(&mlxsw_sib2_pci_driver);
+ mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver);
+ mlxsw_core_driver_unregister(&mlxsw_sib2_driver);
+ mlxsw_core_driver_unregister(&mlxsw_sib_driver);
+}
+
+module_init(mlxsw_sib_module_init);
+module_exit(mlxsw_sib_module_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Elad Raz <eladr@@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox SwitchIB and SwitchIB-2 driver");
+MODULE_ALIAS("mlxsw_switchib2");
+MODULE_DEVICE_TABLE(pci, mlxsw_sib_pci_id_table);
+MODULE_DEVICE_TABLE(pci, mlxsw_sib2_pci_id_table);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 92bda8703f87..150ccf5192a9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -3,7 +3,7 @@
* 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>
+ * Copyright (c) 2015-2016 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:
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/slab.h>
@@ -44,13 +45,14 @@
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <net/switchdev.h>
-#include <generated/utsrelease.h>
+#include "pci.h"
#include "core.h"
#include "reg.h"
#include "port.h"
#include "trap.h"
#include "txheader.h"
+#include "ib.h"
static const char mlxsw_sx_driver_name[] = "mlxsw_switchx2";
static const char mlxsw_sx_driver_version[] = "1.0";
@@ -74,11 +76,13 @@ struct mlxsw_sx_port_pcpu_stats {
};
struct mlxsw_sx_port {
- struct mlxsw_core_port core_port; /* must be first */
struct net_device *dev;
struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats;
struct mlxsw_sx *mlxsw_sx;
u8 local_port;
+ struct {
+ u8 module;
+ } mapping;
};
/* tx_hdr_version
@@ -214,14 +218,14 @@ static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port,
return 0;
}
-static int mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, u16 mtu)
+static int __mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port,
+ u16 mtu)
{
struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
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_sx_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
if (err)
@@ -235,6 +239,32 @@ static int mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, u16 mtu)
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
}
+static int mlxsw_sx_port_mtu_eth_set(struct mlxsw_sx_port *mlxsw_sx_port,
+ u16 mtu)
+{
+ mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
+ return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
+}
+
+static int mlxsw_sx_port_mtu_ib_set(struct mlxsw_sx_port *mlxsw_sx_port,
+ u16 mtu)
+{
+ return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
+}
+
+static int mlxsw_sx_port_ib_port_set(struct mlxsw_sx_port *mlxsw_sx_port,
+ u8 ib_port)
+{
+ struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
+ char plib_pl[MLXSW_REG_PLIB_LEN] = {0};
+ int err;
+
+ mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sx_port->local_port);
+ mlxsw_reg_plib_ib_port_set(plib_pl, ib_port);
+ err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(plib), plib_pl);
+ return err;
+}
+
static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid)
{
struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
@@ -254,18 +284,19 @@ mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port)
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl);
}
-static int mlxsw_sx_port_module_check(struct mlxsw_sx_port *mlxsw_sx_port,
- bool *p_usable)
+static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx,
+ u8 local_port, u8 *p_module,
+ u8 *p_width)
{
- struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
char pmlp_pl[MLXSW_REG_PMLP_LEN];
int err;
- mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sx_port->local_port);
+ mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl);
if (err)
return err;
- *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false;
+ *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+ *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
return 0;
}
@@ -343,7 +374,7 @@ static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu)
struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
int err;
- err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
+ err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, mtu);
if (err)
return err;
dev->mtu = mtu;
@@ -382,12 +413,26 @@ mlxsw_sx_port_get_stats64(struct net_device *dev,
return stats;
}
+static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name,
+ size_t len)
+{
+ struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
+ int err;
+
+ err = snprintf(name, len, "p%d", mlxsw_sx_port->mapping.module + 1);
+ if (err >= len)
+ return -EINVAL;
+
+ return 0;
+}
+
static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
.ndo_open = mlxsw_sx_port_open,
.ndo_stop = mlxsw_sx_port_stop,
.ndo_start_xmit = mlxsw_sx_port_xmit,
.ndo_change_mtu = mlxsw_sx_port_change_mtu,
.ndo_get_stats64 = mlxsw_sx_port_get_stats64,
+ .ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name,
};
static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
@@ -410,7 +455,7 @@ static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
struct mlxsw_sx_port_hw_stats {
char str[ETH_GSTRING_LEN];
- u64 (*getter)(char *payload);
+ u64 (*getter)(const char *payload);
};
static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = {
@@ -642,6 +687,7 @@ static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
};
#define MLXSW_SX_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sx_port_link_mode)
+#define MLXSW_SX_PORT_BASE_SPEED 10000 /* Mb/s */
static u32 mlxsw_sx_from_ptys_supported_port(u32 ptys_eth_proto)
{
@@ -741,14 +787,14 @@ static int mlxsw_sx_port_get_settings(struct net_device *dev,
u32 eth_proto_oper;
int err;
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sx->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);
+ mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap,
+ &eth_proto_admin, &eth_proto_oper);
cmd->supported = mlxsw_sx_from_ptys_supported_port(eth_proto_cap) |
mlxsw_sx_from_ptys_supported_link(eth_proto_cap) |
@@ -789,6 +835,18 @@ static u32 mlxsw_sx_to_ptys_speed(u32 speed)
return ptys_proto;
}
+static u32 mlxsw_sx_to_ptys_upper_speed(u32 upper_speed)
+{
+ u32 ptys_proto = 0;
+ int i;
+
+ for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
+ if (mlxsw_sx_port_link_mode[i].speed <= upper_speed)
+ ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
+ }
+ return ptys_proto;
+}
+
static int mlxsw_sx_port_set_settings(struct net_device *dev,
struct ethtool_cmd *cmd)
{
@@ -808,13 +866,14 @@ static int mlxsw_sx_port_set_settings(struct net_device *dev,
mlxsw_sx_to_ptys_advert_link(cmd->advertising) :
mlxsw_sx_to_ptys_speed(speed);
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sx->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);
+ mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
+ NULL);
eth_proto_new = eth_proto_new & eth_proto_cap;
if (!eth_proto_new) {
@@ -824,7 +883,8 @@ static int mlxsw_sx_port_set_settings(struct net_device *dev,
if (eth_proto_new == eth_proto_admin)
return 0;
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, eth_proto_new);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
+ eth_proto_new);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
if (err) {
netdev_err(dev, "Failed to set proto admin");
@@ -888,7 +948,7 @@ static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx)
{
- char spad_pl[MLXSW_REG_SPAD_LEN];
+ char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
int err;
err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(spad), spad_pl);
@@ -935,13 +995,28 @@ static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port,
return err;
}
-static int mlxsw_sx_port_speed_set(struct mlxsw_sx_port *mlxsw_sx_port,
- u32 speed)
+static int mlxsw_sx_port_ib_speed_set(struct mlxsw_sx_port *mlxsw_sx_port,
+ u16 speed, u16 width)
{
struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
char ptys_pl[MLXSW_REG_PTYS_LEN];
- mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, speed);
+ mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sx_port->local_port, speed,
+ width);
+ return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
+}
+
+static int
+mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width)
+{
+ struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
+ u32 upper_speed = MLXSW_SX_PORT_BASE_SPEED * width;
+ char ptys_pl[MLXSW_REG_PTYS_LEN];
+ u32 eth_proto_admin;
+
+ eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed);
+ mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
+ eth_proto_admin);
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
}
@@ -956,20 +1031,22 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port,
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl);
}
-static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
+ u8 module, u8 width)
{
struct mlxsw_sx_port *mlxsw_sx_port;
struct net_device *dev;
- bool usable;
int err;
dev = alloc_etherdev(sizeof(struct mlxsw_sx_port));
if (!dev)
return -ENOMEM;
+ SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev);
mlxsw_sx_port = netdev_priv(dev);
mlxsw_sx_port->dev = dev;
mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
mlxsw_sx_port->local_port = local_port;
+ mlxsw_sx_port->mapping.module = module;
mlxsw_sx_port->pcpu_stats =
netdev_alloc_pcpu_stats(struct mlxsw_sx_port_pcpu_stats);
@@ -994,24 +1071,14 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
NETIF_F_VLAN_CHALLENGED;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
+
/* Each packet needs to have a Tx header (metadata) on top all other
* headers.
*/
dev->needed_headroom = MLXSW_TXHDR_LEN;
- err = mlxsw_sx_port_module_check(mlxsw_sx_port, &usable);
- if (err) {
- dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to check module\n",
- mlxsw_sx_port->local_port);
- goto err_port_module_check;
- }
-
- if (!usable) {
- dev_dbg(mlxsw_sx->bus_info->dev, "Port %d: Not usable, skipping initialization\n",
- mlxsw_sx_port->local_port);
- goto port_not_usable;
- }
-
err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
if (err) {
dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
@@ -1026,15 +1093,14 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
goto err_port_swid_set;
}
- err = mlxsw_sx_port_speed_set(mlxsw_sx_port,
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4);
+ err = mlxsw_sx_port_speed_by_width_set(mlxsw_sx_port, width);
if (err) {
dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n",
mlxsw_sx_port->local_port);
goto err_port_speed_set;
}
- err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, ETH_DATA_LEN);
+ err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, ETH_DATA_LEN);
if (err) {
dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n",
mlxsw_sx_port->local_port);
@@ -1069,19 +1135,11 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
goto err_register_netdev;
}
- err = mlxsw_core_port_init(mlxsw_sx->core, &mlxsw_sx_port->core_port,
- mlxsw_sx_port->local_port, dev, false, 0);
- if (err) {
- dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
- mlxsw_sx_port->local_port);
- goto err_core_port_init;
- }
-
+ mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
+ mlxsw_sx_port, dev, false, 0);
mlxsw_sx->ports[local_port] = mlxsw_sx_port;
return 0;
-err_core_port_init:
- unregister_netdev(dev);
err_register_netdev:
err_port_mac_learning_mode_set:
err_port_stp_state_set:
@@ -1091,8 +1149,6 @@ err_port_speed_set:
mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
err_port_swid_set:
err_port_system_port_mapping_set:
-port_not_usable:
-err_port_module_check:
err_dev_addr_get:
free_percpu(mlxsw_sx_port->pcpu_stats);
err_alloc_stats:
@@ -1100,31 +1156,168 @@ err_alloc_stats:
return err;
}
-static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
+ u8 module, u8 width)
+{
+ int err;
+
+ err = mlxsw_core_port_init(mlxsw_sx->core, local_port);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
+ local_port);
+ return err;
+ }
+ err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, width);
+ if (err)
+ goto err_port_create;
+
+ return 0;
+
+err_port_create:
+ mlxsw_core_port_fini(mlxsw_sx->core, local_port);
+ return err;
+}
+
+static void __mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
{
struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
- if (!mlxsw_sx_port)
- return;
- mlxsw_core_port_fini(&mlxsw_sx_port->core_port);
+ mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx);
unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */
+ mlxsw_sx->ports[local_port] = NULL;
mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
free_percpu(mlxsw_sx_port->pcpu_stats);
free_netdev(mlxsw_sx_port->dev);
}
+static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+{
+ return mlxsw_sx->ports[local_port] != NULL;
+}
+
+static int __mlxsw_sx_port_ib_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
+ u8 module, u8 width)
+{
+ struct mlxsw_sx_port *mlxsw_sx_port;
+ int err;
+
+ mlxsw_sx_port = kzalloc(sizeof(*mlxsw_sx_port), GFP_KERNEL);
+ if (!mlxsw_sx_port)
+ return -ENOMEM;
+ mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
+ mlxsw_sx_port->local_port = local_port;
+ mlxsw_sx_port->mapping.module = module;
+
+ err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_system_port_mapping_set;
+ }
+
+ /* Adding port to Infiniband swid (1) */
+ err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 1);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_swid_set;
+ }
+
+ /* Expose the IB port number as it's front panel name */
+ err = mlxsw_sx_port_ib_port_set(mlxsw_sx_port, module + 1);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set IB port\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_ib_set;
+ }
+
+ /* Supports all speeds from SDR to FDR (bitmask) and support bus width
+ * of 1x, 2x and 4x (3 bits bitmask)
+ */
+ err = mlxsw_sx_port_ib_speed_set(mlxsw_sx_port,
+ MLXSW_REG_PTYS_IB_SPEED_EDR - 1,
+ BIT(3) - 1);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_speed_set;
+ }
+
+ /* Change to the maximum MTU the device supports, the SMA will take
+ * care of the active MTU
+ */
+ err = mlxsw_sx_port_mtu_ib_set(mlxsw_sx_port, MLXSW_IB_DEFAULT_MTU);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_mtu_set;
+ }
+
+ err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
+ if (err) {
+ dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to change admin state to UP\n",
+ mlxsw_sx_port->local_port);
+ goto err_port_admin_set;
+ }
+
+ mlxsw_core_port_ib_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
+ mlxsw_sx_port);
+ mlxsw_sx->ports[local_port] = mlxsw_sx_port;
+ return 0;
+
+err_port_admin_set:
+err_port_mtu_set:
+err_port_speed_set:
+err_port_ib_set:
+ mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
+err_port_swid_set:
+err_port_system_port_mapping_set:
+ kfree(mlxsw_sx_port);
+ return err;
+}
+
+static void __mlxsw_sx_port_ib_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+{
+ struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
+
+ mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx);
+ mlxsw_sx->ports[local_port] = NULL;
+ mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
+ mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
+ kfree(mlxsw_sx_port);
+}
+
+static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+{
+ enum devlink_port_type port_type =
+ mlxsw_core_port_type_get(mlxsw_sx->core, local_port);
+
+ if (port_type == DEVLINK_PORT_TYPE_ETH)
+ __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port);
+ else if (port_type == DEVLINK_PORT_TYPE_IB)
+ __mlxsw_sx_port_ib_remove(mlxsw_sx, local_port);
+}
+
+static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
+{
+ __mlxsw_sx_port_remove(mlxsw_sx, local_port);
+ mlxsw_core_port_fini(mlxsw_sx->core, local_port);
+}
+
static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx)
{
int i;
for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
- mlxsw_sx_port_remove(mlxsw_sx, i);
+ if (mlxsw_sx_port_created(mlxsw_sx, i))
+ mlxsw_sx_port_remove(mlxsw_sx, i);
kfree(mlxsw_sx->ports);
}
static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
{
size_t alloc_size;
+ u8 module, width;
int i;
int err;
@@ -1134,25 +1327,57 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
return -ENOMEM;
for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
- err = mlxsw_sx_port_create(mlxsw_sx, i);
+ err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &module,
+ &width);
+ if (err)
+ goto err_port_module_info_get;
+ if (!width)
+ continue;
+ err = mlxsw_sx_port_eth_create(mlxsw_sx, i, module, width);
if (err)
goto err_port_create;
}
return 0;
err_port_create:
+err_port_module_info_get:
for (i--; i >= 1; i--)
- mlxsw_sx_port_remove(mlxsw_sx, i);
+ if (mlxsw_sx_port_created(mlxsw_sx, i))
+ mlxsw_sx_port_remove(mlxsw_sx, i);
kfree(mlxsw_sx->ports);
return err;
}
+static void mlxsw_sx_pude_eth_event_func(struct mlxsw_sx_port *mlxsw_sx_port,
+ enum mlxsw_reg_pude_oper_status 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 {
+ netdev_info(mlxsw_sx_port->dev, "link down\n");
+ netif_carrier_off(mlxsw_sx_port->dev);
+ }
+}
+
+static void mlxsw_sx_pude_ib_event_func(struct mlxsw_sx_port *mlxsw_sx_port,
+ enum mlxsw_reg_pude_oper_status status)
+{
+ if (status == MLXSW_PORT_OPER_STATUS_UP)
+ pr_info("ib link for port %d - up\n",
+ mlxsw_sx_port->mapping.module + 1);
+ else
+ pr_info("ib link for port %d - down\n",
+ mlxsw_sx_port->mapping.module + 1);
+}
+
static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg,
char *pude_pl, void *priv)
{
struct mlxsw_sx *mlxsw_sx = priv;
struct mlxsw_sx_port *mlxsw_sx_port;
enum mlxsw_reg_pude_oper_status status;
+ enum devlink_port_type port_type;
u8 local_port;
local_port = mlxsw_reg_pude_local_port_get(pude_pl);
@@ -1164,59 +1389,11 @@ static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg,
}
status = mlxsw_reg_pude_oper_status_get(pude_pl);
- if (status == MLXSW_PORT_OPER_STATUS_UP) {
- netdev_info(mlxsw_sx_port->dev, "link up\n");
- netif_carrier_on(mlxsw_sx_port->dev);
- } else {
- netdev_info(mlxsw_sx_port->dev, "link down\n");
- netif_carrier_off(mlxsw_sx_port->dev);
- }
-}
-
-static struct mlxsw_event_listener mlxsw_sx_pude_event = {
- .func = mlxsw_sx_pude_event_func,
- .trap_id = MLXSW_TRAP_ID_PUDE,
-};
-
-static int mlxsw_sx_event_register(struct mlxsw_sx *mlxsw_sx,
- 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_sx_pude_event;
- break;
- }
- err = mlxsw_core_event_listener_register(mlxsw_sx->core, el, mlxsw_sx);
- if (err)
- return err;
-
- 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;
-
- return 0;
-
-err_event_trap_set:
- mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx);
- return err;
-}
-
-static void mlxsw_sx_event_unregister(struct mlxsw_sx *mlxsw_sx,
- enum mlxsw_event_trap_id trap_id)
-{
- struct mlxsw_event_listener *el;
-
- switch (trap_id) {
- case MLXSW_TRAP_ID_PUDE:
- el = &mlxsw_sx_pude_event;
- break;
- }
- mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx);
+ port_type = mlxsw_core_port_type_get(mlxsw_sx->core, local_port);
+ if (port_type == DEVLINK_PORT_TYPE_ETH)
+ mlxsw_sx_pude_eth_event_func(mlxsw_sx_port, status);
+ else if (port_type == DEVLINK_PORT_TYPE_IB)
+ mlxsw_sx_pude_ib_event_func(mlxsw_sx_port, status);
}
static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port,
@@ -1244,142 +1421,110 @@ static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port,
netif_receive_skb(skb);
}
-static const struct mlxsw_rx_listener mlxsw_sx_rx_listener[] = {
- {
- .func = mlxsw_sx_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_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_STP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_LACP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_EAPOL,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_LLDP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_MMRP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_MVRP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_RPVST,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_DHCP,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_IGMP_QUERY,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE,
- },
- {
- .func = mlxsw_sx_rx_listener_func,
- .local_port = MLXSW_PORT_DONT_CARE,
- .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT,
- },
+static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+ enum devlink_port_type new_type)
+{
+ struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core);
+ u8 module, width;
+ int err;
+
+ if (new_type == DEVLINK_PORT_TYPE_AUTO)
+ return -EOPNOTSUPP;
+
+ __mlxsw_sx_port_remove(mlxsw_sx, local_port);
+ err = mlxsw_sx_port_module_info_get(mlxsw_sx, local_port, &module,
+ &width);
+ if (err)
+ goto err_port_module_info_get;
+
+ if (new_type == DEVLINK_PORT_TYPE_ETH)
+ err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module,
+ width);
+ else if (new_type == DEVLINK_PORT_TYPE_IB)
+ err = __mlxsw_sx_port_ib_create(mlxsw_sx, local_port, module,
+ width);
+
+err_port_module_info_get:
+ return err;
+}
+
+#define MLXSW_SX_RXL(_trap_id) \
+ MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \
+ false, SX2_RX, FORWARD)
+
+static const struct mlxsw_listener mlxsw_sx_listener[] = {
+ MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE, EMAD),
+ MLXSW_SX_RXL(FDB_MC),
+ MLXSW_SX_RXL(STP),
+ MLXSW_SX_RXL(LACP),
+ MLXSW_SX_RXL(EAPOL),
+ MLXSW_SX_RXL(LLDP),
+ MLXSW_SX_RXL(MMRP),
+ MLXSW_SX_RXL(MVRP),
+ MLXSW_SX_RXL(RPVST),
+ MLXSW_SX_RXL(DHCP),
+ MLXSW_SX_RXL(IGMP_QUERY),
+ MLXSW_SX_RXL(IGMP_V1_REPORT),
+ MLXSW_SX_RXL(IGMP_V2_REPORT),
+ MLXSW_SX_RXL(IGMP_V2_LEAVE),
+ MLXSW_SX_RXL(IGMP_V3_REPORT),
};
static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx)
{
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);
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX,
+ MLXSW_REG_HTGT_INVALID_POLICER,
+ MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+ MLXSW_REG_HTGT_DEFAULT_TC);
+ mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX);
+
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl);
if (err)
return err;
- mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL);
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL,
+ MLXSW_REG_HTGT_INVALID_POLICER,
+ MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+ MLXSW_REG_HTGT_DEFAULT_TC);
+ mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_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],
- mlxsw_sx);
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) {
+ err = mlxsw_core_trap_register(mlxsw_sx->core,
+ &mlxsw_sx_listener[i],
+ mlxsw_sx);
if (err)
- goto err_rx_listener_register;
+ goto err_listener_register;
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
- mlxsw_sx_rx_listener[i].trap_id);
- err = mlxsw_reg_write(mlxsw_sx->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_sx->core,
- &mlxsw_sx_rx_listener[i],
- mlxsw_sx);
-err_rx_listener_register:
+err_listener_register:
for (i--; i >= 0; i--) {
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
- mlxsw_sx_rx_listener[i].trap_id);
- mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
-
- mlxsw_core_rx_listener_unregister(mlxsw_sx->core,
- &mlxsw_sx_rx_listener[i],
- mlxsw_sx);
+ mlxsw_core_trap_unregister(mlxsw_sx->core,
+ &mlxsw_sx_listener[i],
+ mlxsw_sx);
}
return err;
}
static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx)
{
- char hpkt_pl[MLXSW_REG_HPKT_LEN];
int i;
- for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) {
- mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
- mlxsw_sx_rx_listener[i].trap_id);
- mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
-
- mlxsw_core_rx_listener_unregister(mlxsw_sx->core,
- &mlxsw_sx_rx_listener[i],
- mlxsw_sx);
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) {
+ mlxsw_core_trap_unregister(mlxsw_sx->core,
+ &mlxsw_sx_listener[i],
+ mlxsw_sx);
}
}
@@ -1451,6 +1596,20 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx)
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl);
}
+static int mlxsw_sx_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+ char htgt_pl[MLXSW_REG_HTGT_LEN];
+
+ mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+ MLXSW_REG_HTGT_INVALID_POLICER,
+ MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+ MLXSW_REG_HTGT_DEFAULT_TC);
+ mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS);
+ mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
+ MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD);
+ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+}
+
static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info)
{
@@ -1472,16 +1631,10 @@ static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core,
return err;
}
- err = mlxsw_sx_event_register(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
- if (err) {
- dev_err(mlxsw_sx->bus_info->dev, "Failed to register for PUDE events\n");
- goto err_event_register;
- }
-
err = mlxsw_sx_traps_init(mlxsw_sx);
if (err) {
- dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps for RX\n");
- goto err_rx_listener_register;
+ dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps\n");
+ goto err_listener_register;
}
err = mlxsw_sx_flood_init(mlxsw_sx);
@@ -1494,9 +1647,7 @@ static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core,
err_flood_init:
mlxsw_sx_traps_fini(mlxsw_sx);
-err_rx_listener_register:
- mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
-err_event_register:
+err_listener_register:
mlxsw_sx_ports_remove(mlxsw_sx);
return err;
}
@@ -1506,7 +1657,6 @@ static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core)
struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sx_traps_fini(mlxsw_sx);
- mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
mlxsw_sx_ports_remove(mlxsw_sx);
}
@@ -1529,36 +1679,66 @@ static struct mlxsw_config_profile mlxsw_sx_config_profile = {
.used_flood_mode = 1,
.flood_mode = 3,
.used_max_ib_mc = 1,
- .max_ib_mc = 0,
+ .max_ib_mc = 6,
.used_max_pkey = 1,
.max_pkey = 0,
.swid_config = {
{
.used_type = 1,
.type = MLXSW_PORT_SWID_TYPE_ETH,
+ },
+ {
+ .used_type = 1,
+ .type = MLXSW_PORT_SWID_TYPE_IB,
}
},
.resource_query_enable = 0,
};
static struct mlxsw_driver mlxsw_sx_driver = {
- .kind = MLXSW_DEVICE_KIND_SWITCHX2,
- .owner = THIS_MODULE,
+ .kind = mlxsw_sx_driver_name,
.priv_size = sizeof(struct mlxsw_sx),
.init = mlxsw_sx_init,
.fini = mlxsw_sx_fini,
+ .basic_trap_groups_set = mlxsw_sx_basic_trap_groups_set,
.txhdr_construct = mlxsw_sx_txhdr_construct,
.txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sx_config_profile,
+ .port_type_set = mlxsw_sx_port_type_set,
+};
+
+static const struct pci_device_id mlxsw_sx_pci_id_table[] = {
+ {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
+ {0, },
+};
+
+static struct pci_driver mlxsw_sx_pci_driver = {
+ .name = mlxsw_sx_driver_name,
+ .id_table = mlxsw_sx_pci_id_table,
};
static int __init mlxsw_sx_module_init(void)
{
- return mlxsw_core_driver_register(&mlxsw_sx_driver);
+ int err;
+
+ err = mlxsw_core_driver_register(&mlxsw_sx_driver);
+ if (err)
+ return err;
+
+ err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver);
+ if (err)
+ goto err_pci_driver_register;
+
+ return 0;
+
+err_pci_driver_register:
+ mlxsw_core_driver_unregister(&mlxsw_sx_driver);
+ return err;
}
static void __exit mlxsw_sx_module_exit(void)
{
+ mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver);
mlxsw_core_driver_unregister(&mlxsw_sx_driver);
}
@@ -1568,4 +1748,4 @@ module_exit(mlxsw_sx_module_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
MODULE_DESCRIPTION("Mellanox SwitchX-2 driver");
-MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SWITCHX2);
+MODULE_DEVICE_TABLE(pci, mlxsw_sx_pci_id_table);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h
index ed8e30186400..7ab275deacac 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/trap.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h
@@ -62,6 +62,7 @@ enum {
MLXSW_TRAP_ID_OSPF = 0x55,
MLXSW_TRAP_ID_IP2ME = 0x5F,
MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70,
+ MLXSW_TRAP_ID_BGP_IPV4 = 0x88,
MLXSW_TRAP_ID_HOST_MISS_IPV4 = 0x90,
MLXSW_TRAP_ID_MAX = 0x1FF
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 1edc973df4c4..e7e1aff40bd9 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1063,7 +1063,6 @@ static const struct net_device_ops ks8851_netdev_ops = {
.ndo_start_xmit = ks8851_start_xmit,
.ndo_set_mac_address = ks8851_set_mac_address,
.ndo_set_rx_mode = ks8851_set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index 2fc5cd56c0a8..db628078a4e6 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -1285,7 +1285,6 @@ static const struct net_device_ops ks_netdev_ops = {
.ndo_start_xmit = ks_start_xmit,
.ndo_set_mac_address = ks_set_mac_address,
.ndo_set_rx_mode = ks_set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 280e761d3a97..97f6ef1fa7d0 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -5807,24 +5807,19 @@ static int netdev_change_mtu(struct net_device *dev, int new_mtu)
if (hw->dev_count > 1)
if (dev != hw_priv->dev)
return 0;
- if (new_mtu < 60)
- return -EINVAL;
- if (dev->mtu != new_mtu) {
- hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4;
- if (hw_mtu > MAX_RX_BUF_SIZE)
- return -EINVAL;
- if (hw_mtu > REGULAR_RX_BUF_SIZE) {
- hw->features |= RX_HUGE_FRAME;
- hw_mtu = MAX_RX_BUF_SIZE;
- } else {
- hw->features &= ~RX_HUGE_FRAME;
- hw_mtu = REGULAR_RX_BUF_SIZE;
- }
- hw_mtu = (hw_mtu + 3) & ~3;
- hw_priv->mtu = hw_mtu;
- dev->mtu = new_mtu;
+ hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4;
+ if (hw_mtu > REGULAR_RX_BUF_SIZE) {
+ hw->features |= RX_HUGE_FRAME;
+ hw_mtu = MAX_RX_BUF_SIZE;
+ } else {
+ hw->features &= ~RX_HUGE_FRAME;
+ hw_mtu = REGULAR_RX_BUF_SIZE;
}
+ hw_mtu = (hw_mtu + 3) & ~3;
+ hw_priv->mtu = hw_mtu;
+ dev->mtu = new_mtu;
+
return 0;
}
@@ -7099,6 +7094,12 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
+
+ /* MTU range: 60 - 1894 */
+ dev->min_mtu = ETH_ZLEN;
+ dev->max_mtu = MAX_RX_BUF_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
if (register_netdev(dev))
goto pcidev_init_reg_err;
port_set_power_saving(port, true);
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 0a26b11ca8f6..045b9106c0ff 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1544,7 +1544,6 @@ static const struct net_device_ops enc28j60_netdev_ops = {
.ndo_set_rx_mode = enc28j60_set_multicast_list,
.ndo_set_mac_address = enc28j60_set_mac_address,
.ndo_tx_timeout = enc28j60_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 4367dd6879a2..9774b50cff6e 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -444,7 +444,6 @@ static struct net_device_ops moxart_netdev_ops = {
.ndo_set_rx_mode = moxart_mac_set_rx_mode,
.ndo_set_mac_address = moxart_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int moxart_mac_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 6d1a956e3f77..e506ca876d0d 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -289,7 +289,7 @@ static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] =
{[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL };
module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL,
0444);
-MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board");
+MODULE_PARM_DESC(myri10ge_fw_names, "Firmware image names per board");
static int myri10ge_ecrc_enable = 1;
module_param(myri10ge_ecrc_enable, int, S_IRUGO);
@@ -3232,10 +3232,6 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
struct myri10ge_priv *mgp = netdev_priv(dev);
int error = 0;
- if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) {
- netdev_err(dev, "new mtu (%d) is not valid\n", new_mtu);
- return -EINVAL;
- }
netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu);
if (mgp->running) {
/* if we change the mtu on an active device, we must
@@ -4086,13 +4082,19 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
myri10ge_setup_dca(mgp);
#endif
pci_set_drvdata(pdev, mgp);
- if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
- myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
- if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
- myri10ge_initial_mtu = 68;
- netdev->netdev_ops = &myri10ge_netdev_ops;
+ /* MTU range: 68 - 9000 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+
+ if (myri10ge_initial_mtu > netdev->max_mtu)
+ myri10ge_initial_mtu = netdev->max_mtu;
+ if (myri10ge_initial_mtu < netdev->min_mtu)
+ myri10ge_initial_mtu = netdev->min_mtu;
+
netdev->mtu = myri10ge_initial_mtu;
+
+ netdev->netdev_ops = &myri10ge_netdev_ops;
netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
/* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */
diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
index acf3f11e38cc..a6caeb567c0d 100644
--- a/drivers/net/ethernet/natsemi/jazzsonic.c
+++ b/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -110,7 +110,6 @@ static const struct net_device_ops sonic_netdev_ops = {
.ndo_get_stats = sonic_get_stats,
.ndo_set_rx_mode = sonic_multicast_list,
.ndo_tx_timeout = sonic_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index d98f5b8a1c66..3ca6ae7caf55 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -190,7 +190,6 @@ static const struct net_device_ops macsonic_netdev_ops = {
.ndo_tx_timeout = sonic_tx_timeout,
.ndo_get_stats = sonic_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index ed89029ff75b..22b0821c1da0 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -929,6 +929,10 @@ static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->ethtool_ops = &ethtool_ops;
+ /* MTU range: 64 - 2024 */
+ dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
+ dev->max_mtu = NATSEMI_RX_LIMIT - NATSEMI_HEADERS;
+
if (mtu)
dev->mtu = mtu;
@@ -2526,9 +2530,6 @@ static void __set_rx_mode(struct net_device *dev)
static int natsemi_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < 64 || new_mtu > NATSEMI_RX_LIMIT-NATSEMI_HEADERS)
- return -EINVAL;
-
dev->mtu = new_mtu;
/* synchronized against open : rtnl_lock() held by caller */
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index 569ade6cf85c..93c4bdc0cdca 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -919,7 +919,7 @@ netdev_mangle_me_harder_failed:
ndev->stats.rx_dropped++;
}
} else {
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
}
nr++;
@@ -1679,14 +1679,6 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac)
}
}
-static int ns83820_change_mtu(struct net_device *ndev, int new_mtu)
-{
- if (new_mtu > RX_BUF_SIZE)
- return -EINVAL;
- ndev->mtu = new_mtu;
- return 0;
-}
-
static void ns83820_set_multicast(struct net_device *ndev)
{
struct ns83820 *dev = PRIV(ndev);
@@ -1933,7 +1925,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = ns83820_stop,
.ndo_start_xmit = ns83820_hard_start_xmit,
.ndo_get_stats = ns83820_get_stats,
- .ndo_change_mtu = ns83820_change_mtu,
.ndo_set_rx_mode = ns83820_set_multicast,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
@@ -2190,6 +2181,8 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
ndev->features |= NETIF_F_SG;
ndev->features |= NETIF_F_IP_CSUM;
+ ndev->min_mtu = 0;
+
#ifdef NS83820_VLAN_ACCEL_SUPPORT
/* We also support hardware vlan acceleration */
ndev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index 7007d212f3e4..9ee0f69a83c0 100644
--- a/drivers/net/ethernet/natsemi/xtsonic.c
+++ b/drivers/net/ethernet/natsemi/xtsonic.c
@@ -124,7 +124,6 @@ static const struct net_device_ops xtsonic_netdev_ops = {
.ndo_set_rx_mode = sonic_multicast_list,
.ndo_tx_timeout = sonic_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index eaa37c079a7c..564f682fa4dc 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6678,11 +6678,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
struct s2io_nic *sp = netdev_priv(dev);
int ret = 0;
- if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
- DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", dev->name);
- return -EPERM;
- }
-
dev->mtu = new_mtu;
if (netif_running(dev)) {
s2io_stop_all_tx_queue(sp);
@@ -8019,6 +8014,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
}
+ /* MTU range: 46 - 9600 */
+ dev->min_mtu = MIN_MTU;
+ dev->max_mtu = S2IO_JUMBO_SIZE;
+
/* store mac addresses from CAM to s2io_nic structure */
do_s2io_store_unicast_mc(sp);
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h
index 6ce4412fcc1a..cfa970417f81 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h
@@ -27,7 +27,7 @@
(((size) - (((u64)adrs) & ((size)-1))) & ((size)-1))
#endif
-#define VXGE_HW_MIN_MTU 68
+#define VXGE_HW_MIN_MTU ETH_MIN_MTU
#define VXGE_HW_MAX_MTU 9600
#define VXGE_HW_DEFAULT_MTU 1500
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index e0993eba5df3..e07b936f64ec 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -3074,11 +3074,6 @@ static int vxge_change_mtu(struct net_device *dev, int new_mtu)
vxge_debug_entryexit(vdev->level_trace,
"%s:%d", __func__, __LINE__);
- if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > VXGE_HW_MAX_MTU)) {
- vxge_debug_init(vdev->level_err,
- "%s: mtu size is invalid", dev->name);
- return -EPERM;
- }
/* check if device is down already */
if (unlikely(!is_vxge_card_up(vdev))) {
@@ -3462,6 +3457,10 @@ static int vxge_device_register(struct __vxge_hw_device *hldev,
"%s : using High DMA", __func__);
}
+ /* MTU range: 68 - 9600 */
+ ndev->min_mtu = VXGE_HW_MIN_MTU;
+ ndev->max_mtu = VXGE_HW_MAX_MTU;
+
ret = register_netdev(ndev);
if (ret) {
vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
index 87aa8a3e9112..76a19f1796af 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
@@ -62,6 +62,7 @@ enum nfp_bpf_action_type {
NN_ACT_TC_DROP,
NN_ACT_TC_REDIR,
NN_ACT_DIRECT,
+ NN_ACT_XDP,
};
/* Software register representation, hardware encoding in asm.h */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
index f8df5300f49c..335beb8b8b45 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
@@ -1126,7 +1126,7 @@ static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
meta->insn.src_reg * 2, true, 4);
}
-static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+static int mem_ldx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
if (meta->insn.off == offsetof(struct sk_buff, len))
emit_alu(nfp_prog, reg_both(meta->insn.dst_reg * 2),
@@ -1134,12 +1134,42 @@ static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
else
return -ENOTSUPP;
- wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
+ return 0;
+}
+
+static int mem_ldx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ u32 dst = reg_both(meta->insn.dst_reg * 2);
+
+ if (meta->insn.off != offsetof(struct xdp_md, data) &&
+ meta->insn.off != offsetof(struct xdp_md, data_end))
+ return -ENOTSUPP;
+
+ emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, NFP_BPF_ABI_PKT);
+
+ if (meta->insn.off == offsetof(struct xdp_md, data))
+ return 0;
+
+ emit_alu(nfp_prog, dst, dst, ALU_OP_ADD, NFP_BPF_ABI_LEN);
return 0;
}
-static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ int ret;
+
+ if (nfp_prog->act == NN_ACT_XDP)
+ ret = mem_ldx4_xdp(nfp_prog, meta);
+ else
+ ret = mem_ldx4_skb(nfp_prog, meta);
+
+ wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
+
+ return ret;
+}
+
+static int mem_stx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
if (meta->insn.off == offsetof(struct sk_buff, mark))
return wrp_set_mark(nfp_prog, meta->insn.src_reg * 2);
@@ -1147,6 +1177,18 @@ static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return -ENOTSUPP;
}
+static int mem_stx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ return -ENOTSUPP;
+}
+
+static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ if (nfp_prog->act == NN_ACT_XDP)
+ return mem_stx4_xdp(nfp_prog, meta);
+ return mem_stx4_skb(nfp_prog, meta);
+}
+
static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
if (meta->insn.off < 0) /* TODO */
@@ -1530,6 +1572,47 @@ static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
}
+static void nfp_outro_xdp(struct nfp_prog *nfp_prog)
+{
+ /* XDP return codes:
+ * 0 aborted 0x82 -> drop, count as stat3
+ * 1 drop 0x22 -> drop, count as stat1
+ * 2 pass 0x11 -> pass, count as stat0
+ * 3 tx 0x44 -> redir, count as stat2
+ * * unknown 0x82 -> drop, count as stat3
+ */
+ /* Target for aborts */
+ nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);
+
+ emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
+
+ emit_alu(nfp_prog, reg_a(0),
+ reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
+ emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x82), SHF_SC_L_SHF, 16);
+
+ /* Target for normal exits */
+ nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);
+
+ /* if R0 > 3 jump to abort */
+ emit_alu(nfp_prog, reg_none(), reg_imm(3), ALU_OP_SUB, reg_b(0));
+ emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0);
+
+ wrp_immed(nfp_prog, reg_b(2), 0x44112282);
+
+ emit_shf(nfp_prog, reg_a(1),
+ reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 3);
+
+ emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
+ emit_shf(nfp_prog, reg_b(2),
+ reg_imm(0xff), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0);
+
+ emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
+
+ emit_alu(nfp_prog, reg_a(0),
+ reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
+ emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
+}
+
static void nfp_outro(struct nfp_prog *nfp_prog)
{
switch (nfp_prog->act) {
@@ -1540,6 +1623,9 @@ static void nfp_outro(struct nfp_prog *nfp_prog)
case NN_ACT_TC_REDIR:
nfp_outro_tc_legacy(nfp_prog);
break;
+ case NN_ACT_XDP:
+ nfp_outro_xdp(nfp_prog);
+ break;
}
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c b/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c
index 144cae87f63a..b3361f9b8e5c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c
@@ -80,6 +80,9 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
{
const struct bpf_reg_state *reg0 = &env->cur_state.regs[0];
+ if (nfp_prog->act == NN_ACT_XDP)
+ return 0;
+
if (reg0->type != CONST_IMM) {
pr_info("unsupported exit state: %d, imm: %llx\n",
reg0->type, reg0->imm);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index ed824e11a1e3..2115f446031e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -75,7 +75,6 @@
/* Default size for MTU and freelist buffer sizes */
#define NFP_NET_DEFAULT_MTU 1500
-#define NFP_NET_DEFAULT_RX_BUFSZ 2048
/* Maximum number of bytes prepended to a packet */
#define NFP_NET_MAX_PREPEND 64
@@ -88,6 +87,9 @@
/* Queue/Ring definitions */
#define NFP_NET_MAX_TX_RINGS 64 /* Max. # of Tx rings per device */
#define NFP_NET_MAX_RX_RINGS 64 /* Max. # of Rx rings per device */
+#define NFP_NET_MAX_R_VECS (NFP_NET_MAX_TX_RINGS > NFP_NET_MAX_RX_RINGS ? \
+ NFP_NET_MAX_TX_RINGS : NFP_NET_MAX_RX_RINGS)
+#define NFP_NET_MAX_IRQS (NFP_NET_NON_Q_VECTORS + NFP_NET_MAX_R_VECS)
#define NFP_NET_MIN_TX_DESCS 256 /* Min. # of Tx descs per ring */
#define NFP_NET_MIN_RX_DESCS 256 /* Min. # of Rx descs per ring */
@@ -102,6 +104,10 @@
/* Offload definitions */
#define NFP_NET_N_VXLAN_PORTS (NFP_NET_CFG_VXLAN_SZ / sizeof(__be16))
+#define NFP_NET_RX_BUF_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
+#define NFP_NET_RX_BUF_NON_DATA (NFP_NET_RX_BUF_HEADROOM + \
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+
/* Forward declarations */
struct nfp_net;
struct nfp_net_r_vector;
@@ -165,7 +171,10 @@ struct nfp_net_tx_desc {
* on the head's buffer). Equal to skb->len for non-TSO packets.
*/
struct nfp_net_tx_buf {
- struct sk_buff *skb;
+ union {
+ struct sk_buff *skb;
+ void *frag;
+ };
dma_addr_t dma_addr;
short int fidx;
u16 pkt_cnt;
@@ -278,11 +287,11 @@ struct nfp_net_rx_hash {
/**
* struct nfp_net_rx_buf - software RX buffer descriptor
- * @skb: sk_buff associated with this buffer
+ * @frag: page fragment buffer
* @dma_addr: DMA mapping address of the buffer
*/
struct nfp_net_rx_buf {
- struct sk_buff *skb;
+ void *frag;
dma_addr_t dma_addr;
};
@@ -335,6 +344,7 @@ struct nfp_net_rx_ring {
* @napi: NAPI structure for this ring vec
* @tx_ring: Pointer to TX ring
* @rx_ring: Pointer to RX ring
+ * @xdp_ring: Pointer to an extra TX ring for XDP
* @irq_idx: Index into MSI-X table
* @rx_sync: Seqlock for atomic updates of RX stats
* @rx_pkts: Number of received packets
@@ -378,6 +388,8 @@ struct nfp_net_r_vector {
u64 hw_csum_rx_inner_ok;
u64 hw_csum_rx_error;
+ struct nfp_net_tx_ring *xdp_ring;
+
struct u64_stats_sync tx_sync;
u64 tx_pkts;
u64 tx_bytes;
@@ -421,12 +433,13 @@ struct nfp_stat_pair {
* @netdev: Backpointer to net_device structure
* @nfp_fallback: Is the driver used in fallback mode?
* @is_vf: Is the driver attached to a VF?
- * @is_nfp3200: Is the driver for a NFP-3200 card?
* @fw_loaded: Is the firmware loaded?
* @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf
+ * @bpf_offload_xdp: Offloaded BPF program is XDP
* @ctrl: Local copy of the control register/word.
* @fl_bufsz: Currently configured size of the freelist buffers
* @rx_offset: Offset in the RX buffers where packet data starts
+ * @xdp_prog: Installed XDP program
* @cpp: Pointer to the CPP handle
* @nfp_dev_cpp: Pointer to the NFP Device handle
* @ctrl_area: Pointer to the CPP area for the control BAR
@@ -446,12 +459,13 @@ struct nfp_stat_pair {
* @max_tx_rings: Maximum number of TX rings supported by the Firmware
* @max_rx_rings: Maximum number of RX rings supported by the Firmware
* @num_tx_rings: Currently configured number of TX rings
+ * @num_stack_tx_rings: Number of TX rings used by the stack (not XDP)
* @num_rx_rings: Currently configured number of RX rings
* @txd_cnt: Size of the TX ring in number of descriptors
* @rxd_cnt: Size of the RX ring in number of descriptors
* @tx_rings: Array of pre-allocated TX ring structures
* @rx_rings: Array of pre-allocated RX ring structures
- * @num_irqs: Number of allocated interrupt vectors
+ * @max_r_vecs: Number of allocated interrupt vectors for RX/TX
* @num_r_vecs: Number of used ring vectors
* @r_vecs: Pre-allocated array of ring vectors
* @irq_entries: Pre-allocated array of MSI-X entries
@@ -487,15 +501,17 @@ struct nfp_net {
unsigned nfp_fallback:1;
unsigned is_vf:1;
- unsigned is_nfp3200:1;
unsigned fw_loaded:1;
unsigned bpf_offload_skip_sw:1;
+ unsigned bpf_offload_xdp:1;
u32 ctrl;
u32 fl_bufsz;
u32 rx_offset;
+ struct bpf_prog *xdp_prog;
+
struct nfp_net_tx_ring *tx_rings;
struct nfp_net_rx_ring *rx_rings;
@@ -524,11 +540,12 @@ struct nfp_net {
struct timer_list rx_filter_stats_timer;
spinlock_t rx_filter_lock;
- int max_tx_rings;
- int max_rx_rings;
+ unsigned int max_tx_rings;
+ unsigned int max_rx_rings;
- int num_tx_rings;
- int num_rx_rings;
+ unsigned int num_tx_rings;
+ unsigned int num_stack_tx_rings;
+ unsigned int num_rx_rings;
int stride_tx;
int stride_rx;
@@ -536,11 +553,10 @@ struct nfp_net {
int txd_cnt;
int rxd_cnt;
- u8 num_irqs;
- u8 num_r_vecs;
- struct nfp_net_r_vector r_vecs[NFP_NET_MAX_TX_RINGS];
- struct msix_entry irq_entries[NFP_NET_NON_Q_VECTORS +
- NFP_NET_MAX_TX_RINGS];
+ unsigned int max_r_vecs;
+ unsigned int num_r_vecs;
+ struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS];
+ struct msix_entry irq_entries[NFP_NET_MAX_IRQS];
irq_handler_t lsc_handler;
char lsc_name[IFNAMSIZ + 8];
@@ -580,6 +596,13 @@ struct nfp_net {
struct dentry *debugfs_dir;
};
+struct nfp_net_ring_set {
+ unsigned int n_rings;
+ unsigned int mtu;
+ unsigned int dcnt;
+ void *rings;
+};
+
/* Functions to read/write from/to a BAR
* Performs any endian conversion necessary.
*/
@@ -593,16 +616,13 @@ static inline void nn_writeb(struct nfp_net *nn, int off, u8 val)
writeb(val, nn->ctrl_bar + off);
}
-/* NFP-3200 can't handle 16-bit accesses too well */
static inline u16 nn_readw(struct nfp_net *nn, int off)
{
- WARN_ON_ONCE(nn->is_nfp3200);
return readw(nn->ctrl_bar + off);
}
static inline void nn_writew(struct nfp_net *nn, int off, u16 val)
{
- WARN_ON_ONCE(nn->is_nfp3200);
writew(val, nn->ctrl_bar + off);
}
@@ -650,7 +670,7 @@ static inline void nn_pci_flush(struct nfp_net *nn)
#define NFP_QCP_QUEUE_STS_HI 0x000c
#define NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask 0x3ffff
-/* The offset of a QCP queues in the PCIe Target (same on NFP3200 and NFP6000 */
+/* The offset of a QCP queues in the PCIe Target */
#define NFP_PCIE_QUEUE(_q) (0x80000 + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & 0xff)))
/* nfp_qcp_ptr - Read or Write Pointer of a queue */
@@ -757,8 +777,9 @@ extern const char nfp_net_driver_version[];
void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
void __iomem *ctrl_bar);
-struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
- int max_tx_rings, int max_rx_rings);
+struct nfp_net *
+nfp_net_netdev_alloc(struct pci_dev *pdev,
+ unsigned int max_tx_rings, unsigned int max_rx_rings);
void nfp_net_netdev_free(struct nfp_net *nn);
int nfp_net_netdev_init(struct net_device *netdev);
void nfp_net_netdev_clean(struct net_device *netdev);
@@ -770,7 +791,9 @@ void nfp_net_rss_write_key(struct nfp_net *nn);
void nfp_net_coalesce_write_cfg(struct nfp_net *nn);
int nfp_net_irqs_alloc(struct nfp_net *nn);
void nfp_net_irqs_disable(struct nfp_net *nn);
-int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt);
+int
+nfp_net_ring_reconfig(struct nfp_net *nn, struct bpf_prog **xdp_prog,
+ struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx);
#ifdef CONFIG_NFP_NET_DEBUG
void nfp_net_debugfs_create(void);
@@ -796,8 +819,6 @@ static inline void nfp_net_debugfs_adapter_del(struct nfp_net *nn)
#endif /* CONFIG_NFP_NET_DEBUG */
void nfp_net_filter_stats_timer(unsigned long data);
-int
-nfp_net_bpf_offload(struct nfp_net *nn, u32 handle, __be16 proto,
- struct tc_cls_bpf_offload *cls_bpf);
+int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf);
#endif /* _NFP_NET_H_ */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index aee3fd2b6538..e8d448109e03 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -41,6 +41,7 @@
* Chris Telfer <chris.telfer@netronome.com>
*/
+#include <linux/bpf.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -50,6 +51,7 @@
#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/page_ref.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/msi.h>
@@ -80,6 +82,22 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
put_unaligned_le32(reg, fw_ver);
}
+static dma_addr_t
+nfp_net_dma_map_rx(struct nfp_net *nn, void *frag, unsigned int bufsz,
+ int direction)
+{
+ return dma_map_single(&nn->pdev->dev, frag + NFP_NET_RX_BUF_HEADROOM,
+ bufsz - NFP_NET_RX_BUF_NON_DATA, direction);
+}
+
+static void
+nfp_net_dma_unmap_rx(struct nfp_net *nn, dma_addr_t dma_addr,
+ unsigned int bufsz, int direction)
+{
+ dma_unmap_single(&nn->pdev->dev, dma_addr,
+ bufsz - NFP_NET_RX_BUF_NON_DATA, direction);
+}
+
/* Firmware reconfig
*
* Firmware reconfig may take a while so we have two versions of it -
@@ -249,43 +267,14 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update)
*/
/**
- * nfp_net_irq_unmask_msix() - Unmask MSI-X after automasking
- * @nn: NFP Network structure
- * @entry_nr: MSI-X table entry
- *
- * Clear the MSI-X table mask bit for the given entry bypassing Linux irq
- * handling subsystem. Use *only* to reenable automasked vectors.
- */
-static void nfp_net_irq_unmask_msix(struct nfp_net *nn, unsigned int entry_nr)
-{
- struct list_head *msi_head = &nn->pdev->dev.msi_list;
- struct msi_desc *entry;
- u32 off;
-
- /* All MSI-Xs have the same mask_base */
- entry = list_first_entry(msi_head, struct msi_desc, list);
-
- off = (PCI_MSIX_ENTRY_SIZE * entry_nr) +
- PCI_MSIX_ENTRY_VECTOR_CTRL;
- writel(0, entry->mask_base + off);
- readl(entry->mask_base);
-}
-
-/**
* nfp_net_irq_unmask() - Unmask automasked interrupt
* @nn: NFP Network structure
* @entry_nr: MSI-X table entry
*
- * If MSI-X auto-masking is enabled clear the mask bit, otherwise
- * clear the ICR for the entry.
+ * Clear the ICR for the IRQ entry.
*/
static void nfp_net_irq_unmask(struct nfp_net *nn, unsigned int entry_nr)
{
- if (nn->ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) {
- nfp_net_irq_unmask_msix(nn, entry_nr);
- return;
- }
-
nn_writeb(nn, NFP_NET_CFG_ICR(entry_nr), NFP_NET_CFG_ICR_UNMASKED);
nn_pci_flush(nn);
}
@@ -320,28 +309,6 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs)
}
/**
- * nfp_net_irqs_wanted() - Work out how many interrupt vectors we want
- * @nn: NFP Network structure
- *
- * We want a vector per CPU (or ring), whatever is smaller plus
- * NFP_NET_NON_Q_VECTORS for LSC etc.
- *
- * Return: Number of interrupts wanted
- */
-static int nfp_net_irqs_wanted(struct nfp_net *nn)
-{
- int ncpus;
- int vecs;
-
- ncpus = num_online_cpus();
-
- vecs = max_t(int, nn->num_tx_rings, nn->num_rx_rings);
- vecs = min_t(int, vecs, ncpus);
-
- return vecs + NFP_NET_NON_Q_VECTORS;
-}
-
-/**
* nfp_net_irqs_alloc() - allocates MSI-X irqs
* @nn: NFP Network structure
*
@@ -350,22 +317,24 @@ static int nfp_net_irqs_wanted(struct nfp_net *nn)
int nfp_net_irqs_alloc(struct nfp_net *nn)
{
int wanted_irqs;
+ unsigned int n;
- wanted_irqs = nfp_net_irqs_wanted(nn);
+ wanted_irqs = nn->num_r_vecs + NFP_NET_NON_Q_VECTORS;
- nn->num_irqs = nfp_net_msix_alloc(nn, wanted_irqs);
- if (nn->num_irqs == 0) {
+ n = nfp_net_msix_alloc(nn, wanted_irqs);
+ if (n == 0) {
nn_err(nn, "Failed to allocate MSI-X IRQs\n");
return 0;
}
- nn->num_r_vecs = nn->num_irqs - NFP_NET_NON_Q_VECTORS;
+ nn->max_r_vecs = n - NFP_NET_NON_Q_VECTORS;
+ nn->num_r_vecs = nn->max_r_vecs;
- if (nn->num_irqs < wanted_irqs)
+ if (n < wanted_irqs)
nn_warn(nn, "Unable to allocate %d vectors. Got %d instead\n",
- wanted_irqs, nn->num_irqs);
+ wanted_irqs, n);
- return nn->num_irqs;
+ return n;
}
/**
@@ -515,18 +484,19 @@ static void nfp_net_irqs_assign(struct net_device *netdev)
struct nfp_net_r_vector *r_vec;
int r;
- /* Assumes nn->num_tx_rings == nn->num_rx_rings */
- if (nn->num_tx_rings > nn->num_r_vecs) {
- nn_warn(nn, "More rings (%d) than vectors (%d).\n",
- nn->num_tx_rings, nn->num_r_vecs);
- nn->num_tx_rings = nn->num_r_vecs;
- nn->num_rx_rings = nn->num_r_vecs;
- }
+ if (nn->num_rx_rings > nn->num_r_vecs ||
+ nn->num_tx_rings > nn->num_r_vecs)
+ nn_warn(nn, "More rings (%d,%d) than vectors (%d).\n",
+ nn->num_rx_rings, nn->num_tx_rings, nn->num_r_vecs);
+
+ nn->num_rx_rings = min(nn->num_r_vecs, nn->num_rx_rings);
+ nn->num_tx_rings = min(nn->num_r_vecs, nn->num_tx_rings);
+ nn->num_stack_tx_rings = nn->num_tx_rings;
nn->lsc_handler = nfp_net_irq_lsc;
nn->exn_handler = nfp_net_irq_exn;
- for (r = 0; r < nn->num_r_vecs; r++) {
+ for (r = 0; r < nn->max_r_vecs; r++) {
r_vec = &nn->r_vecs[r];
r_vec->nfp_net = nn;
r_vec->handler = nfp_net_irq_rxtx;
@@ -605,7 +575,7 @@ static void nfp_net_aux_irq_free(struct nfp_net *nn, u32 ctrl_offset,
*
* Return: True if the ring is full.
*/
-static inline int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt)
+static int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt)
{
return (tx_ring->wr_p - tx_ring->rd_p) >= (tx_ring->cnt - dcnt);
}
@@ -745,6 +715,13 @@ static void nfp_net_tx_csum(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
u64_stats_update_end(&r_vec->tx_sync);
}
+static void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring)
+{
+ wmb();
+ nfp_qcp_wr_ptr_add(tx_ring->qcp_q, tx_ring->wr_ptr_add);
+ tx_ring->wr_ptr_add = 0;
+}
+
/**
* nfp_net_tx() - Main transmit entry point
* @skb: SKB to transmit
@@ -790,7 +767,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
if (dma_mapping_error(&nn->pdev->dev, dma_addr))
goto err_free;
- wr_idx = tx_ring->wr_p % tx_ring->cnt;
+ wr_idx = tx_ring->wr_p & (tx_ring->cnt - 1);
/* Stash the soft descriptor of the head then initialize it */
txbuf = &tx_ring->txbufs[wr_idx];
@@ -834,7 +811,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
if (dma_mapping_error(&nn->pdev->dev, dma_addr))
goto err_unmap;
- wr_idx = (wr_idx + 1) % tx_ring->cnt;
+ wr_idx = (wr_idx + 1) & (tx_ring->cnt - 1);
tx_ring->txbufs[wr_idx].skb = skb;
tx_ring->txbufs[wr_idx].dma_addr = dma_addr;
tx_ring->txbufs[wr_idx].fidx = f;
@@ -859,12 +836,8 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
nfp_net_tx_ring_stop(nd_q, tx_ring);
tx_ring->wr_ptr_add += nr_frags + 1;
- if (!skb->xmit_more || netif_xmit_stopped(nd_q)) {
- /* force memory write before we let HW know */
- wmb();
- nfp_qcp_wr_ptr_add(tx_ring->qcp_q, tx_ring->wr_ptr_add);
- tx_ring->wr_ptr_add = 0;
- }
+ if (!skb->xmit_more || netif_xmit_stopped(nd_q))
+ nfp_net_tx_xmit_more_flush(tx_ring);
skb_tx_timestamp(skb);
@@ -929,7 +902,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring)
todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p;
while (todo--) {
- idx = tx_ring->rd_p % tx_ring->cnt;
+ idx = tx_ring->rd_p & (tx_ring->cnt - 1);
tx_ring->rd_p++;
skb = tx_ring->txbufs[idx].skb;
@@ -986,6 +959,56 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring)
tx_ring->rd_p, tx_ring->wr_p, tx_ring->cnt);
}
+static void nfp_net_xdp_complete(struct nfp_net_tx_ring *tx_ring)
+{
+ struct nfp_net_r_vector *r_vec = tx_ring->r_vec;
+ struct nfp_net *nn = r_vec->nfp_net;
+ u32 done_pkts = 0, done_bytes = 0;
+ int idx, todo;
+ u32 qcp_rd_p;
+
+ /* Work out how many descriptors have been transmitted */
+ qcp_rd_p = nfp_qcp_rd_ptr_read(tx_ring->qcp_q);
+
+ if (qcp_rd_p == tx_ring->qcp_rd_p)
+ return;
+
+ if (qcp_rd_p > tx_ring->qcp_rd_p)
+ todo = qcp_rd_p - tx_ring->qcp_rd_p;
+ else
+ todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p;
+
+ while (todo--) {
+ idx = tx_ring->rd_p & (tx_ring->cnt - 1);
+ tx_ring->rd_p++;
+
+ if (!tx_ring->txbufs[idx].frag)
+ continue;
+
+ nfp_net_dma_unmap_rx(nn, tx_ring->txbufs[idx].dma_addr,
+ nn->fl_bufsz, DMA_BIDIRECTIONAL);
+ __free_page(virt_to_page(tx_ring->txbufs[idx].frag));
+
+ done_pkts++;
+ done_bytes += tx_ring->txbufs[idx].real_len;
+
+ tx_ring->txbufs[idx].dma_addr = 0;
+ tx_ring->txbufs[idx].frag = NULL;
+ tx_ring->txbufs[idx].fidx = -2;
+ }
+
+ tx_ring->qcp_rd_p = qcp_rd_p;
+
+ u64_stats_update_begin(&r_vec->tx_sync);
+ r_vec->tx_bytes += done_bytes;
+ r_vec->tx_pkts += done_pkts;
+ u64_stats_update_end(&r_vec->tx_sync);
+
+ WARN_ONCE(tx_ring->wr_p - tx_ring->rd_p > tx_ring->cnt,
+ "TX ring corruption rd_p=%u wr_p=%u cnt=%u\n",
+ tx_ring->rd_p, tx_ring->wr_p, tx_ring->cnt);
+}
+
/**
* nfp_net_tx_ring_reset() - Free any untransmitted buffers and reset pointers
* @nn: NFP Net device
@@ -996,39 +1019,47 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring)
static void
nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring)
{
+ struct nfp_net_r_vector *r_vec = tx_ring->r_vec;
const struct skb_frag_struct *frag;
- struct netdev_queue *nd_q;
struct pci_dev *pdev = nn->pdev;
+ struct netdev_queue *nd_q;
while (tx_ring->rd_p != tx_ring->wr_p) {
- int nr_frags, fidx, idx;
- struct sk_buff *skb;
+ struct nfp_net_tx_buf *tx_buf;
+ int idx;
- idx = tx_ring->rd_p % tx_ring->cnt;
- skb = tx_ring->txbufs[idx].skb;
- nr_frags = skb_shinfo(skb)->nr_frags;
- fidx = tx_ring->txbufs[idx].fidx;
+ idx = tx_ring->rd_p & (tx_ring->cnt - 1);
+ tx_buf = &tx_ring->txbufs[idx];
- if (fidx == -1) {
- /* unmap head */
- dma_unmap_single(&pdev->dev,
- tx_ring->txbufs[idx].dma_addr,
- skb_headlen(skb), DMA_TO_DEVICE);
+ if (tx_ring == r_vec->xdp_ring) {
+ nfp_net_dma_unmap_rx(nn, tx_buf->dma_addr,
+ nn->fl_bufsz, DMA_BIDIRECTIONAL);
+ __free_page(virt_to_page(tx_ring->txbufs[idx].frag));
} else {
- /* unmap fragment */
- frag = &skb_shinfo(skb)->frags[fidx];
- dma_unmap_page(&pdev->dev,
- tx_ring->txbufs[idx].dma_addr,
- skb_frag_size(frag), DMA_TO_DEVICE);
- }
+ struct sk_buff *skb = tx_ring->txbufs[idx].skb;
+ int nr_frags = skb_shinfo(skb)->nr_frags;
+
+ if (tx_buf->fidx == -1) {
+ /* unmap head */
+ dma_unmap_single(&pdev->dev, tx_buf->dma_addr,
+ skb_headlen(skb),
+ DMA_TO_DEVICE);
+ } else {
+ /* unmap fragment */
+ frag = &skb_shinfo(skb)->frags[tx_buf->fidx];
+ dma_unmap_page(&pdev->dev, tx_buf->dma_addr,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ }
- /* check for last gather fragment */
- if (fidx == nr_frags - 1)
- dev_kfree_skb_any(skb);
+ /* check for last gather fragment */
+ if (tx_buf->fidx == nr_frags - 1)
+ dev_kfree_skb_any(skb);
+ }
- tx_ring->txbufs[idx].dma_addr = 0;
- tx_ring->txbufs[idx].skb = NULL;
- tx_ring->txbufs[idx].fidx = -2;
+ tx_buf->dma_addr = 0;
+ tx_buf->skb = NULL;
+ tx_buf->fidx = -2;
tx_ring->qcp_rd_p++;
tx_ring->rd_p++;
@@ -1040,6 +1071,9 @@ nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring)
tx_ring->qcp_rd_p = 0;
tx_ring->wr_ptr_add = 0;
+ if (tx_ring == r_vec->xdp_ring)
+ return;
+
nd_q = netdev_get_tx_queue(nn->netdev, tx_ring->idx);
netdev_tx_reset_queue(nd_q);
}
@@ -1049,7 +1083,7 @@ static void nfp_net_tx_timeout(struct net_device *netdev)
struct nfp_net *nn = netdev_priv(netdev);
int i;
- for (i = 0; i < nn->num_tx_rings; i++) {
+ for (i = 0; i < nn->netdev->real_num_tx_queues; i++) {
if (!netif_tx_queue_stopped(netdev_get_tx_queue(netdev, i)))
continue;
nn_warn(nn, "TX timeout on ring: %d\n", i);
@@ -1059,69 +1093,112 @@ static void nfp_net_tx_timeout(struct net_device *netdev)
/* Receive processing
*/
+static unsigned int
+nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu)
+{
+ unsigned int fl_bufsz;
-/**
- * nfp_net_rx_space() - return the number of free slots on the RX ring
- * @rx_ring: RX ring structure
- *
- * Make sure we leave at least one slot free.
- *
- * Return: True if there is space on the RX ring
- */
-static inline int nfp_net_rx_space(struct nfp_net_rx_ring *rx_ring)
+ fl_bufsz = NFP_NET_RX_BUF_HEADROOM;
+ if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
+ fl_bufsz += NFP_NET_MAX_PREPEND;
+ else
+ fl_bufsz += nn->rx_offset;
+ fl_bufsz += ETH_HLEN + VLAN_HLEN * 2 + mtu;
+
+ fl_bufsz = SKB_DATA_ALIGN(fl_bufsz);
+ fl_bufsz += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ return fl_bufsz;
+}
+
+static void
+nfp_net_free_frag(void *frag, bool xdp)
{
- return (rx_ring->cnt - 1) - (rx_ring->wr_p - rx_ring->rd_p);
+ if (!xdp)
+ skb_free_frag(frag);
+ else
+ __free_page(virt_to_page(frag));
}
/**
- * nfp_net_rx_alloc_one() - Allocate and map skb for RX
+ * nfp_net_rx_alloc_one() - Allocate and map page frag for RX
* @rx_ring: RX ring structure of the skb
* @dma_addr: Pointer to storage for DMA address (output param)
* @fl_bufsz: size of freelist buffers
+ * @xdp: Whether XDP is enabled
*
- * This function will allcate a new skb, map it for DMA.
+ * This function will allcate a new page frag, map it for DMA.
*
- * Return: allocated skb or NULL on failure.
+ * Return: allocated page frag or NULL on failure.
*/
-static struct sk_buff *
+static void *
nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr,
- unsigned int fl_bufsz)
+ unsigned int fl_bufsz, bool xdp)
{
struct nfp_net *nn = rx_ring->r_vec->nfp_net;
- struct sk_buff *skb;
+ int direction;
+ void *frag;
- skb = netdev_alloc_skb(nn->netdev, fl_bufsz);
- if (!skb) {
- nn_warn_ratelimit(nn, "Failed to alloc receive SKB\n");
+ if (!xdp)
+ frag = netdev_alloc_frag(fl_bufsz);
+ else
+ frag = page_address(alloc_page(GFP_KERNEL | __GFP_COLD));
+ if (!frag) {
+ nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n");
return NULL;
}
- *dma_addr = dma_map_single(&nn->pdev->dev, skb->data,
- fl_bufsz, DMA_FROM_DEVICE);
+ direction = xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
+
+ *dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, direction);
if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) {
- dev_kfree_skb_any(skb);
+ nfp_net_free_frag(frag, xdp);
nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n");
return NULL;
}
- return skb;
+ return frag;
+}
+
+static void *
+nfp_net_napi_alloc_one(struct nfp_net *nn, int direction, dma_addr_t *dma_addr)
+{
+ void *frag;
+
+ if (!nn->xdp_prog)
+ frag = napi_alloc_frag(nn->fl_bufsz);
+ else
+ frag = page_address(alloc_page(GFP_ATOMIC | __GFP_COLD));
+ if (!frag) {
+ nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n");
+ return NULL;
+ }
+
+ *dma_addr = nfp_net_dma_map_rx(nn, frag, nn->fl_bufsz, direction);
+ if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) {
+ nfp_net_free_frag(frag, nn->xdp_prog);
+ nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n");
+ return NULL;
+ }
+
+ return frag;
}
/**
* nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings
* @rx_ring: RX ring structure
- * @skb: Skb to put on rings
+ * @frag: page fragment buffer
* @dma_addr: DMA address of skb mapping
*/
static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring,
- struct sk_buff *skb, dma_addr_t dma_addr)
+ void *frag, dma_addr_t dma_addr)
{
unsigned int wr_idx;
- wr_idx = rx_ring->wr_p % rx_ring->cnt;
+ wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1);
/* Stash SKB and DMA address away */
- rx_ring->rxbufs[wr_idx].skb = skb;
+ rx_ring->rxbufs[wr_idx].frag = frag;
rx_ring->rxbufs[wr_idx].dma_addr = dma_addr;
/* Fill freelist descriptor */
@@ -1153,12 +1230,12 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
unsigned int wr_idx, last_idx;
/* Move the empty entry to the end of the list */
- wr_idx = rx_ring->wr_p % rx_ring->cnt;
+ wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1);
last_idx = rx_ring->cnt - 1;
rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr;
- rx_ring->rxbufs[wr_idx].skb = rx_ring->rxbufs[last_idx].skb;
+ rx_ring->rxbufs[wr_idx].frag = rx_ring->rxbufs[last_idx].frag;
rx_ring->rxbufs[last_idx].dma_addr = 0;
- rx_ring->rxbufs[last_idx].skb = NULL;
+ rx_ring->rxbufs[last_idx].frag = NULL;
memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt);
rx_ring->wr_p = 0;
@@ -1170,15 +1247,17 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
* nfp_net_rx_ring_bufs_free() - Free any buffers currently on the RX ring
* @nn: NFP Net device
* @rx_ring: RX ring to remove buffers from
+ * @xdp: Whether XDP is enabled
*
* Assumes that the device is stopped and buffers are in [0, ring->cnt - 1)
* entries. After device is disabled nfp_net_rx_ring_reset() must be called
* to restore required ring geometry.
*/
static void
-nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
+nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring,
+ bool xdp)
{
- struct pci_dev *pdev = nn->pdev;
+ int direction = xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
unsigned int i;
for (i = 0; i < rx_ring->cnt - 1; i++) {
@@ -1186,14 +1265,14 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
* fails to allocate enough buffers and calls here to free
* already allocated ones.
*/
- if (!rx_ring->rxbufs[i].skb)
+ if (!rx_ring->rxbufs[i].frag)
continue;
- dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr,
- rx_ring->bufsz, DMA_FROM_DEVICE);
- dev_kfree_skb_any(rx_ring->rxbufs[i].skb);
+ nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[i].dma_addr,
+ rx_ring->bufsz, direction);
+ nfp_net_free_frag(rx_ring->rxbufs[i].frag, xdp);
rx_ring->rxbufs[i].dma_addr = 0;
- rx_ring->rxbufs[i].skb = NULL;
+ rx_ring->rxbufs[i].frag = NULL;
}
}
@@ -1201,9 +1280,11 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
* nfp_net_rx_ring_bufs_alloc() - Fill RX ring with buffers (don't give to FW)
* @nn: NFP Net device
* @rx_ring: RX ring to remove buffers from
+ * @xdp: Whether XDP is enabled
*/
static int
-nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
+nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring,
+ bool xdp)
{
struct nfp_net_rx_buf *rxbufs;
unsigned int i;
@@ -1211,11 +1292,11 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
rxbufs = rx_ring->rxbufs;
for (i = 0; i < rx_ring->cnt - 1; i++) {
- rxbufs[i].skb =
+ rxbufs[i].frag =
nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr,
- rx_ring->bufsz);
- if (!rxbufs[i].skb) {
- nfp_net_rx_ring_bufs_free(nn, rx_ring);
+ rx_ring->bufsz, xdp);
+ if (!rxbufs[i].frag) {
+ nfp_net_rx_ring_bufs_free(nn, rx_ring, xdp);
return -ENOMEM;
}
}
@@ -1232,7 +1313,7 @@ static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring)
unsigned int i;
for (i = 0; i < rx_ring->cnt - 1; i++)
- nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].skb,
+ nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].frag,
rx_ring->rxbufs[i].dma_addr);
}
@@ -1359,6 +1440,87 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
return data;
}
+static void
+nfp_net_rx_drop(struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring,
+ struct nfp_net_rx_buf *rxbuf, struct sk_buff *skb)
+{
+ u64_stats_update_begin(&r_vec->rx_sync);
+ r_vec->rx_drops++;
+ u64_stats_update_end(&r_vec->rx_sync);
+
+ /* skb is build based on the frag, free_skb() would free the frag
+ * so to be able to reuse it we need an extra ref.
+ */
+ if (skb && rxbuf && skb->head == rxbuf->frag)
+ page_ref_inc(virt_to_head_page(rxbuf->frag));
+ if (rxbuf)
+ nfp_net_rx_give_one(rx_ring, rxbuf->frag, rxbuf->dma_addr);
+ if (skb)
+ dev_kfree_skb_any(skb);
+}
+
+static void
+nfp_net_tx_xdp_buf(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring,
+ struct nfp_net_tx_ring *tx_ring,
+ struct nfp_net_rx_buf *rxbuf, unsigned int pkt_off,
+ unsigned int pkt_len)
+{
+ struct nfp_net_tx_buf *txbuf;
+ struct nfp_net_tx_desc *txd;
+ dma_addr_t new_dma_addr;
+ void *new_frag;
+ int wr_idx;
+
+ if (unlikely(nfp_net_tx_full(tx_ring, 1))) {
+ nfp_net_rx_drop(rx_ring->r_vec, rx_ring, rxbuf, NULL);
+ return;
+ }
+
+ new_frag = nfp_net_napi_alloc_one(nn, DMA_BIDIRECTIONAL, &new_dma_addr);
+ if (unlikely(!new_frag)) {
+ nfp_net_rx_drop(rx_ring->r_vec, rx_ring, rxbuf, NULL);
+ return;
+ }
+ nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr);
+
+ wr_idx = tx_ring->wr_p & (tx_ring->cnt - 1);
+
+ /* Stash the soft descriptor of the head then initialize it */
+ txbuf = &tx_ring->txbufs[wr_idx];
+ txbuf->frag = rxbuf->frag;
+ txbuf->dma_addr = rxbuf->dma_addr;
+ txbuf->fidx = -1;
+ txbuf->pkt_cnt = 1;
+ txbuf->real_len = pkt_len;
+
+ dma_sync_single_for_device(&nn->pdev->dev, rxbuf->dma_addr + pkt_off,
+ pkt_len, DMA_TO_DEVICE);
+
+ /* Build TX descriptor */
+ txd = &tx_ring->txds[wr_idx];
+ txd->offset_eop = PCIE_DESC_TX_EOP;
+ txd->dma_len = cpu_to_le16(pkt_len);
+ nfp_desc_set_dma_addr(txd, rxbuf->dma_addr + pkt_off);
+ txd->data_len = cpu_to_le16(pkt_len);
+
+ txd->flags = 0;
+ txd->mss = 0;
+ txd->l4_offset = 0;
+
+ tx_ring->wr_p++;
+ tx_ring->wr_ptr_add++;
+}
+
+static int nfp_net_run_xdp(struct bpf_prog *prog, void *data, unsigned int len)
+{
+ struct xdp_buff xdp;
+
+ xdp.data = data;
+ xdp.data_end = data + len;
+
+ return bpf_prog_run_xdp(prog, &xdp);
+}
+
/**
* nfp_net_rx() - receive up to @budget packets on @rx_ring
* @rx_ring: RX ring to receive from
@@ -1368,62 +1530,39 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
* more cleanly separate packet receive code from other bookkeeping
* functions performed in the napi poll function.
*
- * There are differences between the NFP-3200 firmware and the
- * NFP-6000 firmware. The NFP-3200 firmware uses a dedicated RX queue
- * to indicate that new packets have arrived. The NFP-6000 does not
- * have this queue and uses the DD bit in the RX descriptor. This
- * method cannot be used on the NFP-3200 as it causes a race
- * condition: The RX ring write pointer on the NFP-3200 is updated
- * after packets (and descriptors) have been DMAed. If the DD bit is
- * used and subsequently the read pointer is updated this may lead to
- * the RX queue to underflow (if the firmware has not yet update the
- * write pointer). Therefore we use slightly ugly conditional code
- * below to handle the differences. We may, in the future update the
- * NFP-3200 firmware to behave the same as the firmware on the
- * NFP-6000.
- *
* Return: Number of packets received.
*/
static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
{
struct nfp_net_r_vector *r_vec = rx_ring->r_vec;
struct nfp_net *nn = r_vec->nfp_net;
- unsigned int data_len, meta_len;
- int avail = 0, pkts_polled = 0;
- struct sk_buff *skb, *new_skb;
- struct nfp_net_rx_desc *rxd;
- dma_addr_t new_dma_addr;
- u32 qcp_wr_p;
+ struct nfp_net_tx_ring *tx_ring;
+ struct bpf_prog *xdp_prog;
+ unsigned int true_bufsz;
+ struct sk_buff *skb;
+ int pkts_polled = 0;
+ int rx_dma_map_dir;
int idx;
- if (nn->is_nfp3200) {
- /* Work out how many packets arrived */
- qcp_wr_p = nfp_qcp_wr_ptr_read(rx_ring->qcp_rx);
- idx = rx_ring->rd_p % rx_ring->cnt;
+ rcu_read_lock();
+ xdp_prog = READ_ONCE(nn->xdp_prog);
+ rx_dma_map_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
+ true_bufsz = xdp_prog ? PAGE_SIZE : nn->fl_bufsz;
+ tx_ring = r_vec->xdp_ring;
- if (qcp_wr_p == idx)
- /* No new packets */
- return 0;
-
- if (qcp_wr_p > idx)
- avail = qcp_wr_p - idx;
- else
- avail = qcp_wr_p + rx_ring->cnt - idx;
- } else {
- avail = budget + 1;
- }
+ while (pkts_polled < budget) {
+ unsigned int meta_len, data_len, data_off, pkt_len, pkt_off;
+ struct nfp_net_rx_buf *rxbuf;
+ struct nfp_net_rx_desc *rxd;
+ dma_addr_t new_dma_addr;
+ void *new_frag;
- while (avail > 0 && pkts_polled < budget) {
- idx = rx_ring->rd_p % rx_ring->cnt;
+ idx = rx_ring->rd_p & (rx_ring->cnt - 1);
rxd = &rx_ring->rxds[idx];
- if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) {
- if (nn->is_nfp3200)
- nn_dbg(nn, "RX descriptor not valid (DD)%d:%u rxd[0]=%#x rxd[1]=%#x\n",
- rx_ring->idx, idx,
- rxd->vals[0], rxd->vals[1]);
+ if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD))
break;
- }
+
/* Memory barrier to ensure that we won't do other reads
* before the DD bit.
*/
@@ -1431,27 +1570,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
rx_ring->rd_p++;
pkts_polled++;
- avail--;
-
- skb = rx_ring->rxbufs[idx].skb;
-
- new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr,
- nn->fl_bufsz);
- if (!new_skb) {
- nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb,
- rx_ring->rxbufs[idx].dma_addr);
- u64_stats_update_begin(&r_vec->rx_sync);
- r_vec->rx_drops++;
- u64_stats_update_end(&r_vec->rx_sync);
- continue;
- }
-
- dma_unmap_single(&nn->pdev->dev,
- rx_ring->rxbufs[idx].dma_addr,
- nn->fl_bufsz, DMA_FROM_DEVICE);
-
- nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr);
+ rxbuf = &rx_ring->rxbufs[idx];
/* < meta_len >
* <-- [rx_offset] -->
* ---------------------------------------------------------
@@ -1466,19 +1586,66 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
*/
meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK;
data_len = le16_to_cpu(rxd->rxd.data_len);
+ pkt_len = data_len - meta_len;
if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
- skb_reserve(skb, meta_len);
+ pkt_off = meta_len;
else
- skb_reserve(skb, nn->rx_offset);
- skb_put(skb, data_len - meta_len);
+ pkt_off = nn->rx_offset;
+ data_off = NFP_NET_RX_BUF_HEADROOM + pkt_off;
/* Stats update */
u64_stats_update_begin(&r_vec->rx_sync);
r_vec->rx_pkts++;
- r_vec->rx_bytes += skb->len;
+ r_vec->rx_bytes += pkt_len;
u64_stats_update_end(&r_vec->rx_sync);
+ if (xdp_prog && !(rxd->rxd.flags & PCIE_DESC_RX_BPF &&
+ nn->bpf_offload_xdp)) {
+ int act;
+
+ dma_sync_single_for_cpu(&nn->pdev->dev,
+ rxbuf->dma_addr + pkt_off,
+ pkt_len, DMA_FROM_DEVICE);
+ act = nfp_net_run_xdp(xdp_prog, rxbuf->frag + data_off,
+ pkt_len);
+ switch (act) {
+ case XDP_PASS:
+ break;
+ case XDP_TX:
+ nfp_net_tx_xdp_buf(nn, rx_ring, tx_ring, rxbuf,
+ pkt_off, pkt_len);
+ continue;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ case XDP_ABORTED:
+ case XDP_DROP:
+ nfp_net_rx_give_one(rx_ring, rxbuf->frag,
+ rxbuf->dma_addr);
+ continue;
+ }
+ }
+
+ skb = build_skb(rxbuf->frag, true_bufsz);
+ if (unlikely(!skb)) {
+ nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL);
+ continue;
+ }
+ new_frag = nfp_net_napi_alloc_one(nn, rx_dma_map_dir,
+ &new_dma_addr);
+ if (unlikely(!new_frag)) {
+ nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb);
+ continue;
+ }
+
+ nfp_net_dma_unmap_rx(nn, rxbuf->dma_addr, nn->fl_bufsz,
+ rx_dma_map_dir);
+
+ nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr);
+
+ skb_reserve(skb, data_off);
+ skb_put(skb, pkt_len);
+
if (nn->fw_ver.major <= 3) {
nfp_net_set_hash_desc(nn->netdev, skb, rxd);
} else if (meta_len) {
@@ -1486,12 +1653,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
end = nfp_net_parse_meta(nn->netdev, skb, meta_len);
if (unlikely(end != skb->data)) {
- u64_stats_update_begin(&r_vec->rx_sync);
- r_vec->rx_drops++;
- u64_stats_update_end(&r_vec->rx_sync);
-
- dev_kfree_skb_any(skb);
nn_warn_ratelimit(nn, "invalid RX packet metadata\n");
+ nfp_net_rx_drop(r_vec, rx_ring, NULL, skb);
continue;
}
}
@@ -1508,8 +1671,9 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
napi_gro_receive(&rx_ring->r_vec->napi, skb);
}
- if (nn->is_nfp3200)
- nfp_qcp_rd_ptr_add(rx_ring->qcp_rx, pkts_polled);
+ if (xdp_prog && tx_ring->wr_ptr_add)
+ nfp_net_tx_xmit_more_flush(tx_ring);
+ rcu_read_unlock();
return pkts_polled;
}
@@ -1525,21 +1689,19 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
{
struct nfp_net_r_vector *r_vec =
container_of(napi, struct nfp_net_r_vector, napi);
- struct nfp_net_rx_ring *rx_ring = r_vec->rx_ring;
- struct nfp_net_tx_ring *tx_ring = r_vec->tx_ring;
- struct nfp_net *nn = r_vec->nfp_net;
- struct netdev_queue *txq;
- unsigned int pkts_polled;
-
- tx_ring = &nn->tx_rings[rx_ring->idx];
- txq = netdev_get_tx_queue(nn->netdev, tx_ring->idx);
- nfp_net_tx_complete(tx_ring);
+ unsigned int pkts_polled = 0;
- pkts_polled = nfp_net_rx(rx_ring, budget);
+ if (r_vec->tx_ring)
+ nfp_net_tx_complete(r_vec->tx_ring);
+ if (r_vec->rx_ring) {
+ pkts_polled = nfp_net_rx(r_vec->rx_ring, budget);
+ if (r_vec->xdp_ring)
+ nfp_net_xdp_complete(r_vec->xdp_ring);
+ }
if (pkts_polled < budget) {
napi_complete_done(napi, pkts_polled);
- nfp_net_irq_unmask(nn, r_vec->irq_idx);
+ nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_idx);
}
return pkts_polled;
@@ -1575,10 +1737,12 @@ static void nfp_net_tx_ring_free(struct nfp_net_tx_ring *tx_ring)
* nfp_net_tx_ring_alloc() - Allocate resource for a TX ring
* @tx_ring: TX Ring structure to allocate
* @cnt: Ring buffer count
+ * @is_xdp: True if ring will be used for XDP
*
* Return: 0 on success, negative errno otherwise.
*/
-static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt)
+static int
+nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt, bool is_xdp)
{
struct nfp_net_r_vector *r_vec = tx_ring->r_vec;
struct nfp_net *nn = r_vec->nfp_net;
@@ -1598,11 +1762,14 @@ static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt)
if (!tx_ring->txbufs)
goto err_alloc;
- netif_set_xps_queue(nn->netdev, &r_vec->affinity_mask, tx_ring->idx);
+ if (!is_xdp)
+ netif_set_xps_queue(nn->netdev, &r_vec->affinity_mask,
+ tx_ring->idx);
- nn_dbg(nn, "TxQ%02d: QCidx=%02d cnt=%d dma=%#llx host=%p\n",
+ nn_dbg(nn, "TxQ%02d: QCidx=%02d cnt=%d dma=%#llx host=%p %s\n",
tx_ring->idx, tx_ring->qcidx,
- tx_ring->cnt, (unsigned long long)tx_ring->dma, tx_ring->txds);
+ tx_ring->cnt, (unsigned long long)tx_ring->dma, tx_ring->txds,
+ is_xdp ? "XDP" : "");
return 0;
@@ -1612,23 +1779,29 @@ err_alloc:
}
static struct nfp_net_tx_ring *
-nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, u32 buf_cnt)
+nfp_net_tx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s,
+ unsigned int num_stack_tx_rings)
{
struct nfp_net_tx_ring *rings;
unsigned int r;
- rings = kcalloc(nn->num_tx_rings, sizeof(*rings), GFP_KERNEL);
+ rings = kcalloc(s->n_rings, sizeof(*rings), GFP_KERNEL);
if (!rings)
return NULL;
- for (r = 0; r < nn->num_tx_rings; r++) {
- nfp_net_tx_ring_init(&rings[r], nn->tx_rings[r].r_vec, r);
+ for (r = 0; r < s->n_rings; r++) {
+ int bias = 0;
+
+ if (r >= num_stack_tx_rings)
+ bias = num_stack_tx_rings;
- if (nfp_net_tx_ring_alloc(&rings[r], buf_cnt))
+ nfp_net_tx_ring_init(&rings[r], &nn->r_vecs[r - bias], r);
+
+ if (nfp_net_tx_ring_alloc(&rings[r], s->dcnt, bias))
goto err_free_prev;
}
- return rings;
+ return s->rings = rings;
err_free_prev:
while (r--)
@@ -1637,28 +1810,27 @@ err_free_prev:
return NULL;
}
-static struct nfp_net_tx_ring *
-nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_tx_ring *rings)
+static void
+nfp_net_tx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s)
{
- struct nfp_net_tx_ring *old = nn->tx_rings;
- unsigned int r;
+ struct nfp_net_ring_set new = *s;
- for (r = 0; r < nn->num_tx_rings; r++)
- old[r].r_vec->tx_ring = &rings[r];
+ s->dcnt = nn->txd_cnt;
+ s->rings = nn->tx_rings;
+ s->n_rings = nn->num_tx_rings;
- nn->tx_rings = rings;
- return old;
+ nn->txd_cnt = new.dcnt;
+ nn->tx_rings = new.rings;
+ nn->num_tx_rings = new.n_rings;
}
static void
-nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_tx_ring *rings)
+nfp_net_tx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s)
{
+ struct nfp_net_tx_ring *rings = s->rings;
unsigned int r;
- if (!rings)
- return;
-
- for (r = 0; r < nn->num_tx_rings; r++)
+ for (r = 0; r < s->n_rings; r++)
nfp_net_tx_ring_free(&rings[r]);
kfree(rings);
@@ -1730,31 +1902,32 @@ err_alloc:
}
static struct nfp_net_rx_ring *
-nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz,
- u32 buf_cnt)
+nfp_net_rx_ring_set_prepare(struct nfp_net *nn, struct nfp_net_ring_set *s,
+ bool xdp)
{
+ unsigned int fl_bufsz = nfp_net_calc_fl_bufsz(nn, s->mtu);
struct nfp_net_rx_ring *rings;
unsigned int r;
- rings = kcalloc(nn->num_rx_rings, sizeof(*rings), GFP_KERNEL);
+ rings = kcalloc(s->n_rings, sizeof(*rings), GFP_KERNEL);
if (!rings)
return NULL;
- for (r = 0; r < nn->num_rx_rings; r++) {
- nfp_net_rx_ring_init(&rings[r], nn->rx_rings[r].r_vec, r);
+ for (r = 0; r < s->n_rings; r++) {
+ nfp_net_rx_ring_init(&rings[r], &nn->r_vecs[r], r);
- if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, buf_cnt))
+ if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, s->dcnt))
goto err_free_prev;
- if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r]))
+ if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r], xdp))
goto err_free_ring;
}
- return rings;
+ return s->rings = rings;
err_free_prev:
while (r--) {
- nfp_net_rx_ring_bufs_free(nn, &rings[r]);
+ nfp_net_rx_ring_bufs_free(nn, &rings[r], xdp);
err_free_ring:
nfp_net_rx_ring_free(&rings[r]);
}
@@ -1762,35 +1935,50 @@ err_free_ring:
return NULL;
}
-static struct nfp_net_rx_ring *
-nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_rx_ring *rings)
+static void
+nfp_net_rx_ring_set_swap(struct nfp_net *nn, struct nfp_net_ring_set *s)
{
- struct nfp_net_rx_ring *old = nn->rx_rings;
- unsigned int r;
+ struct nfp_net_ring_set new = *s;
- for (r = 0; r < nn->num_rx_rings; r++)
- old[r].r_vec->rx_ring = &rings[r];
+ s->mtu = nn->netdev->mtu;
+ s->dcnt = nn->rxd_cnt;
+ s->rings = nn->rx_rings;
+ s->n_rings = nn->num_rx_rings;
- nn->rx_rings = rings;
- return old;
+ nn->netdev->mtu = new.mtu;
+ nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, new.mtu);
+ nn->rxd_cnt = new.dcnt;
+ nn->rx_rings = new.rings;
+ nn->num_rx_rings = new.n_rings;
}
static void
-nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings)
+nfp_net_rx_ring_set_free(struct nfp_net *nn, struct nfp_net_ring_set *s,
+ bool xdp)
{
+ struct nfp_net_rx_ring *rings = s->rings;
unsigned int r;
- if (!rings)
- return;
-
- for (r = 0; r < nn->num_r_vecs; r++) {
- nfp_net_rx_ring_bufs_free(nn, &rings[r]);
+ for (r = 0; r < s->n_rings; r++) {
+ nfp_net_rx_ring_bufs_free(nn, &rings[r], xdp);
nfp_net_rx_ring_free(&rings[r]);
}
kfree(rings);
}
+static void
+nfp_net_vector_assign_rings(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
+ int idx)
+{
+ r_vec->rx_ring = idx < nn->num_rx_rings ? &nn->rx_rings[idx] : NULL;
+ r_vec->tx_ring =
+ idx < nn->num_stack_tx_rings ? &nn->tx_rings[idx] : NULL;
+
+ r_vec->xdp_ring = idx < nn->num_tx_rings - nn->num_stack_tx_rings ?
+ &nn->tx_rings[nn->num_stack_tx_rings + idx] : NULL;
+}
+
static int
nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
int idx)
@@ -1798,25 +1986,20 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx];
int err;
- r_vec->tx_ring = &nn->tx_rings[idx];
- nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx);
-
- r_vec->rx_ring = &nn->rx_rings[idx];
- nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx);
+ /* Setup NAPI */
+ netif_napi_add(nn->netdev, &r_vec->napi,
+ nfp_net_poll, NAPI_POLL_WEIGHT);
snprintf(r_vec->name, sizeof(r_vec->name),
"%s-rxtx-%d", nn->netdev->name, idx);
err = request_irq(entry->vector, r_vec->handler, 0, r_vec->name, r_vec);
if (err) {
+ netif_napi_del(&r_vec->napi);
nn_err(nn, "Error requesting IRQ %d\n", entry->vector);
return err;
}
disable_irq(entry->vector);
- /* Setup NAPI */
- netif_napi_add(nn->netdev, &r_vec->napi,
- nfp_net_poll, NAPI_POLL_WEIGHT);
-
irq_set_affinity_hint(entry->vector, &r_vec->affinity_mask);
nn_dbg(nn, "RV%02d: irq=%03d/%03d\n", idx, entry->vector, entry->entry);
@@ -1879,13 +2062,13 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn)
/* copy RX interrupt coalesce parameters */
value = (nn->rx_coalesce_max_frames << 16) |
(factor * nn->rx_coalesce_usecs);
- for (i = 0; i < nn->num_r_vecs; i++)
+ for (i = 0; i < nn->num_rx_rings; i++)
nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(i), value);
/* copy TX interrupt coalesce parameters */
value = (nn->tx_coalesce_max_frames << 16) |
(factor * nn->tx_coalesce_usecs);
- for (i = 0; i < nn->num_r_vecs; i++)
+ for (i = 0; i < nn->num_tx_rings; i++)
nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(i), value);
}
@@ -1901,9 +2084,8 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn)
{
nn_writel(nn, NFP_NET_CFG_MACADDR + 0,
get_unaligned_be32(nn->netdev->dev_addr));
- /* We can't do writew for NFP-3200 compatibility */
- nn_writel(nn, NFP_NET_CFG_MACADDR + 4,
- get_unaligned_be16(nn->netdev->dev_addr + 4) << 16);
+ nn_writew(nn, NFP_NET_CFG_MACADDR + 6,
+ get_unaligned_be16(nn->netdev->dev_addr + 4));
}
static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx)
@@ -1944,27 +2126,33 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn)
if (err)
nn_err(nn, "Could not disable device: %d\n", err);
- for (r = 0; r < nn->num_r_vecs; r++) {
- nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring);
- nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring);
+ for (r = 0; r < nn->num_rx_rings; r++)
+ nfp_net_rx_ring_reset(&nn->rx_rings[r]);
+ for (r = 0; r < nn->num_tx_rings; r++)
+ nfp_net_tx_ring_reset(nn, &nn->tx_rings[r]);
+ for (r = 0; r < nn->num_r_vecs; r++)
nfp_net_vec_clear_ring_data(nn, r);
- }
nn->ctrl = new_ctrl;
}
static void
-nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
- unsigned int idx)
+nfp_net_rx_ring_hw_cfg_write(struct nfp_net *nn,
+ struct nfp_net_rx_ring *rx_ring, unsigned int idx)
{
/* Write the DMA address, size and MSI-X info to the device */
- nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), r_vec->rx_ring->dma);
- nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(r_vec->rx_ring->cnt));
- nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), r_vec->irq_idx);
+ nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), rx_ring->dma);
+ nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(rx_ring->cnt));
+ nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), rx_ring->r_vec->irq_idx);
+}
- nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), r_vec->tx_ring->dma);
- nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(r_vec->tx_ring->cnt));
- nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx);
+static void
+nfp_net_tx_ring_hw_cfg_write(struct nfp_net *nn,
+ struct nfp_net_tx_ring *tx_ring, unsigned int idx)
+{
+ nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), tx_ring->dma);
+ nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(tx_ring->cnt));
+ nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), tx_ring->r_vec->irq_idx);
}
static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
@@ -1989,8 +2177,10 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
update |= NFP_NET_CFG_UPDATE_IRQMOD;
}
- for (r = 0; r < nn->num_r_vecs; r++)
- nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r);
+ for (r = 0; r < nn->num_tx_rings; r++)
+ nfp_net_tx_ring_hw_cfg_write(nn, &nn->tx_rings[r], r);
+ for (r = 0; r < nn->num_rx_rings; r++)
+ nfp_net_rx_ring_hw_cfg_write(nn, &nn->rx_rings[r], r);
nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ?
0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1);
@@ -2016,8 +2206,8 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
nn->ctrl = new_ctrl;
- for (r = 0; r < nn->num_r_vecs; r++)
- nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring);
+ for (r = 0; r < nn->num_rx_rings; r++)
+ nfp_net_rx_ring_fill_freelist(&nn->rx_rings[r]);
/* Since reconfiguration requests while NFP is down are ignored we
* have to wipe the entire VXLAN configuration and reinitialize it.
@@ -2068,6 +2258,15 @@ static void nfp_net_open_stack(struct nfp_net *nn)
static int nfp_net_netdev_open(struct net_device *netdev)
{
struct nfp_net *nn = netdev_priv(netdev);
+ struct nfp_net_ring_set rx = {
+ .n_rings = nn->num_rx_rings,
+ .mtu = nn->netdev->mtu,
+ .dcnt = nn->rxd_cnt,
+ };
+ struct nfp_net_ring_set tx = {
+ .n_rings = nn->num_tx_rings,
+ .dcnt = nn->txd_cnt,
+ };
int err, r;
if (nn->ctrl & NFP_NET_CFG_CTRL_ENABLE) {
@@ -2092,39 +2291,29 @@ static int nfp_net_netdev_open(struct net_device *netdev)
goto err_free_exn;
disable_irq(nn->irq_entries[NFP_NET_IRQ_LSC_IDX].vector);
- nn->rx_rings = kcalloc(nn->num_rx_rings, sizeof(*nn->rx_rings),
- GFP_KERNEL);
+ for (r = 0; r < nn->num_r_vecs; r++) {
+ err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r);
+ if (err)
+ goto err_cleanup_vec_p;
+ }
+
+ nn->rx_rings = nfp_net_rx_ring_set_prepare(nn, &rx, nn->xdp_prog);
if (!nn->rx_rings) {
err = -ENOMEM;
- goto err_free_lsc;
+ goto err_cleanup_vec;
}
- nn->tx_rings = kcalloc(nn->num_tx_rings, sizeof(*nn->tx_rings),
- GFP_KERNEL);
+
+ nn->tx_rings = nfp_net_tx_ring_set_prepare(nn, &tx,
+ nn->num_stack_tx_rings);
if (!nn->tx_rings) {
err = -ENOMEM;
goto err_free_rx_rings;
}
- for (r = 0; r < nn->num_r_vecs; r++) {
- err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r);
- if (err)
- goto err_free_prev_vecs;
+ for (r = 0; r < nn->max_r_vecs; r++)
+ nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r);
- err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt);
- if (err)
- goto err_cleanup_vec_p;
-
- err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring,
- nn->fl_bufsz, nn->rxd_cnt);
- if (err)
- goto err_free_tx_ring_p;
-
- err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring);
- if (err)
- goto err_flush_rx_ring_p;
- }
-
- err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings);
+ err = netif_set_real_num_tx_queues(netdev, nn->num_stack_tx_rings);
if (err)
goto err_free_rings;
@@ -2154,21 +2343,14 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0;
err_free_rings:
+ nfp_net_tx_ring_set_free(nn, &tx);
+err_free_rx_rings:
+ nfp_net_rx_ring_set_free(nn, &rx, nn->xdp_prog);
+err_cleanup_vec:
r = nn->num_r_vecs;
-err_free_prev_vecs:
- while (r--) {
- nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
-err_flush_rx_ring_p:
- nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring);
-err_free_tx_ring_p:
- nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring);
err_cleanup_vec_p:
+ while (r--)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
- }
- kfree(nn->tx_rings);
-err_free_rx_rings:
- kfree(nn->rx_rings);
-err_free_lsc:
nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
err_free_exn:
nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
@@ -2203,12 +2385,14 @@ static void nfp_net_close_free_all(struct nfp_net *nn)
{
unsigned int r;
- for (r = 0; r < nn->num_r_vecs; r++) {
- nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
- nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring);
- nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring);
- nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
+ for (r = 0; r < nn->num_rx_rings; r++) {
+ nfp_net_rx_ring_bufs_free(nn, &nn->rx_rings[r], nn->xdp_prog);
+ nfp_net_rx_ring_free(&nn->rx_rings[r]);
}
+ for (r = 0; r < nn->num_tx_rings; r++)
+ nfp_net_tx_ring_free(&nn->tx_rings[r]);
+ for (r = 0; r < nn->num_r_vecs; r++)
+ nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
kfree(nn->rx_rings);
kfree(nn->tx_rings);
@@ -2271,94 +2455,135 @@ static void nfp_net_set_rx_mode(struct net_device *netdev)
nn->ctrl = new_ctrl;
}
-static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
+static void nfp_net_rss_init_itbl(struct nfp_net *nn)
{
- unsigned int old_mtu, old_fl_bufsz, new_fl_bufsz;
- struct nfp_net *nn = netdev_priv(netdev);
- struct nfp_net_rx_ring *tmp_rings;
- int err;
-
- if (new_mtu < 68 || new_mtu > nn->max_mtu) {
- nn_err(nn, "New MTU (%d) is not valid\n", new_mtu);
- return -EINVAL;
- }
-
- old_mtu = netdev->mtu;
- old_fl_bufsz = nn->fl_bufsz;
- new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu;
-
- if (!netif_running(netdev)) {
- netdev->mtu = new_mtu;
- nn->fl_bufsz = new_fl_bufsz;
- return 0;
- }
+ int i;
- /* Prepare new rings */
- tmp_rings = nfp_net_shadow_rx_rings_prepare(nn, new_fl_bufsz,
- nn->rxd_cnt);
- if (!tmp_rings)
- return -ENOMEM;
+ for (i = 0; i < sizeof(nn->rss_itbl); i++)
+ nn->rss_itbl[i] =
+ ethtool_rxfh_indir_default(i, nn->num_rx_rings);
+}
- /* Stop device, swap in new rings, try to start the firmware */
- nfp_net_close_stack(nn);
- nfp_net_clear_config_and_disable(nn);
+static int
+nfp_net_ring_swap_enable(struct nfp_net *nn, unsigned int *num_vecs,
+ unsigned int *stack_tx_rings,
+ struct bpf_prog **xdp_prog,
+ struct nfp_net_ring_set *rx,
+ struct nfp_net_ring_set *tx)
+{
+ unsigned int r;
+ int err;
- tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings);
+ if (rx)
+ nfp_net_rx_ring_set_swap(nn, rx);
+ if (tx)
+ nfp_net_tx_ring_set_swap(nn, tx);
- netdev->mtu = new_mtu;
- nn->fl_bufsz = new_fl_bufsz;
+ swap(*num_vecs, nn->num_r_vecs);
+ swap(*stack_tx_rings, nn->num_stack_tx_rings);
+ *xdp_prog = xchg(&nn->xdp_prog, *xdp_prog);
- err = nfp_net_set_config_and_enable(nn);
- if (err) {
- const int err_new = err;
+ for (r = 0; r < nn->max_r_vecs; r++)
+ nfp_net_vector_assign_rings(nn, &nn->r_vecs[r], r);
- /* Try with old configuration and old rings */
- tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings);
+ if (!netif_is_rxfh_configured(nn->netdev))
+ nfp_net_rss_init_itbl(nn);
- netdev->mtu = old_mtu;
- nn->fl_bufsz = old_fl_bufsz;
+ err = netif_set_real_num_rx_queues(nn->netdev,
+ nn->num_rx_rings);
+ if (err)
+ return err;
- err = __nfp_net_set_config_and_enable(nn);
+ if (nn->netdev->real_num_tx_queues != nn->num_stack_tx_rings) {
+ err = netif_set_real_num_tx_queues(nn->netdev,
+ nn->num_stack_tx_rings);
if (err)
- nn_err(nn, "Can't restore MTU - FW communication failed (%d,%d)\n",
- err_new, err);
+ return err;
}
- nfp_net_shadow_rx_rings_free(nn, tmp_rings);
+ return __nfp_net_set_config_and_enable(nn);
+}
- nfp_net_open_stack(nn);
+static int
+nfp_net_check_config(struct nfp_net *nn, struct bpf_prog *xdp_prog,
+ struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx)
+{
+ /* XDP-enabled tests */
+ if (!xdp_prog)
+ return 0;
+ if (rx && nfp_net_calc_fl_bufsz(nn, rx->mtu) > PAGE_SIZE) {
+ nn_warn(nn, "MTU too large w/ XDP enabled\n");
+ return -EINVAL;
+ }
+ if (tx && tx->n_rings > nn->max_tx_rings) {
+ nn_warn(nn, "Insufficient number of TX rings w/ XDP enabled\n");
+ return -EINVAL;
+ }
- return err;
+ return 0;
}
-int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
-{
- struct nfp_net_tx_ring *tx_rings = NULL;
- struct nfp_net_rx_ring *rx_rings = NULL;
- u32 old_rxd_cnt, old_txd_cnt;
+static void
+nfp_net_ring_reconfig_down(struct nfp_net *nn, struct bpf_prog **xdp_prog,
+ struct nfp_net_ring_set *rx,
+ struct nfp_net_ring_set *tx,
+ unsigned int stack_tx_rings, unsigned int num_vecs)
+{
+ nn->netdev->mtu = rx ? rx->mtu : nn->netdev->mtu;
+ nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, nn->netdev->mtu);
+ nn->rxd_cnt = rx ? rx->dcnt : nn->rxd_cnt;
+ nn->txd_cnt = tx ? tx->dcnt : nn->txd_cnt;
+ nn->num_rx_rings = rx ? rx->n_rings : nn->num_rx_rings;
+ nn->num_tx_rings = tx ? tx->n_rings : nn->num_tx_rings;
+ nn->num_stack_tx_rings = stack_tx_rings;
+ nn->num_r_vecs = num_vecs;
+ *xdp_prog = xchg(&nn->xdp_prog, *xdp_prog);
+
+ if (!netif_is_rxfh_configured(nn->netdev))
+ nfp_net_rss_init_itbl(nn);
+}
+
+int
+nfp_net_ring_reconfig(struct nfp_net *nn, struct bpf_prog **xdp_prog,
+ struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx)
+{
+ unsigned int stack_tx_rings, num_vecs, r;
int err;
+ stack_tx_rings = tx ? tx->n_rings : nn->num_tx_rings;
+ if (*xdp_prog)
+ stack_tx_rings -= rx ? rx->n_rings : nn->num_rx_rings;
+
+ num_vecs = max(rx ? rx->n_rings : nn->num_rx_rings, stack_tx_rings);
+
+ err = nfp_net_check_config(nn, *xdp_prog, rx, tx);
+ if (err)
+ return err;
+
if (!netif_running(nn->netdev)) {
- nn->rxd_cnt = rxd_cnt;
- nn->txd_cnt = txd_cnt;
+ nfp_net_ring_reconfig_down(nn, xdp_prog, rx, tx,
+ stack_tx_rings, num_vecs);
return 0;
}
- old_rxd_cnt = nn->rxd_cnt;
- old_txd_cnt = nn->txd_cnt;
-
/* Prepare new rings */
- if (nn->rxd_cnt != rxd_cnt) {
- rx_rings = nfp_net_shadow_rx_rings_prepare(nn, nn->fl_bufsz,
- rxd_cnt);
- if (!rx_rings)
- return -ENOMEM;
+ for (r = nn->num_r_vecs; r < num_vecs; r++) {
+ err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r);
+ if (err) {
+ num_vecs = r;
+ goto err_cleanup_vecs;
+ }
}
- if (nn->txd_cnt != txd_cnt) {
- tx_rings = nfp_net_shadow_tx_rings_prepare(nn, txd_cnt);
- if (!tx_rings) {
- nfp_net_shadow_rx_rings_free(nn, rx_rings);
- return -ENOMEM;
+ if (rx) {
+ if (!nfp_net_rx_ring_set_prepare(nn, rx, *xdp_prog)) {
+ err = -ENOMEM;
+ goto err_cleanup_vecs;
+ }
+ }
+ if (tx) {
+ if (!nfp_net_tx_ring_set_prepare(nn, tx, stack_tx_rings)) {
+ err = -ENOMEM;
+ goto err_free_rx;
}
}
@@ -2366,39 +2591,51 @@ int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
nfp_net_close_stack(nn);
nfp_net_clear_config_and_disable(nn);
- if (rx_rings)
- rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings);
- if (tx_rings)
- tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings);
-
- nn->rxd_cnt = rxd_cnt;
- nn->txd_cnt = txd_cnt;
-
- err = nfp_net_set_config_and_enable(nn);
+ err = nfp_net_ring_swap_enable(nn, &num_vecs, &stack_tx_rings,
+ xdp_prog, rx, tx);
if (err) {
- const int err_new = err;
-
- /* Try with old configuration and old rings */
- if (rx_rings)
- rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings);
- if (tx_rings)
- tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings);
+ int err2;
- nn->rxd_cnt = old_rxd_cnt;
- nn->txd_cnt = old_txd_cnt;
+ nfp_net_clear_config_and_disable(nn);
- err = __nfp_net_set_config_and_enable(nn);
- if (err)
+ /* Try with old configuration and old rings */
+ err2 = nfp_net_ring_swap_enable(nn, &num_vecs, &stack_tx_rings,
+ xdp_prog, rx, tx);
+ if (err2)
nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n",
- err_new, err);
+ err, err2);
}
+ for (r = num_vecs - 1; r >= nn->num_r_vecs; r--)
+ nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
- nfp_net_shadow_rx_rings_free(nn, rx_rings);
- nfp_net_shadow_tx_rings_free(nn, tx_rings);
+ if (rx)
+ nfp_net_rx_ring_set_free(nn, rx, *xdp_prog);
+ if (tx)
+ nfp_net_tx_ring_set_free(nn, tx);
nfp_net_open_stack(nn);
return err;
+
+err_free_rx:
+ if (rx)
+ nfp_net_rx_ring_set_free(nn, rx, *xdp_prog);
+err_cleanup_vecs:
+ for (r = num_vecs - 1; r >= nn->num_r_vecs; r--)
+ nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
+ return err;
+}
+
+static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+ struct nfp_net_ring_set rx = {
+ .n_rings = nn->num_rx_rings,
+ .mtu = new_mtu,
+ .dcnt = nn->rxd_cnt,
+ };
+
+ return nfp_net_ring_reconfig(nn, &nn->xdp_prog, &rx, NULL);
}
static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev,
@@ -2455,8 +2692,12 @@ nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
if (proto != htons(ETH_P_ALL))
return -ENOTSUPP;
- if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn))
- return nfp_net_bpf_offload(nn, handle, proto, tc->cls_bpf);
+ if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) {
+ if (!nn->bpf_offload_xdp)
+ return nfp_net_bpf_offload(nn, tc->cls_bpf);
+ else
+ return -EBUSY;
+ }
return -EINVAL;
}
@@ -2664,6 +2905,91 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
nfp_net_set_vxlan_port(nn, idx, 0);
}
+static int nfp_net_xdp_offload(struct nfp_net *nn, struct bpf_prog *prog)
+{
+ struct tc_cls_bpf_offload cmd = {
+ .prog = prog,
+ };
+ int ret;
+
+ if (!nfp_net_ebpf_capable(nn))
+ return -EINVAL;
+
+ if (nn->ctrl & NFP_NET_CFG_CTRL_BPF) {
+ if (!nn->bpf_offload_xdp)
+ return prog ? -EBUSY : 0;
+ cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY;
+ } else {
+ if (!prog)
+ return 0;
+ cmd.command = TC_CLSBPF_ADD;
+ }
+
+ ret = nfp_net_bpf_offload(nn, &cmd);
+ /* Stop offload if replace not possible */
+ if (ret && cmd.command == TC_CLSBPF_REPLACE)
+ nfp_net_xdp_offload(nn, NULL);
+ nn->bpf_offload_xdp = prog && !ret;
+ return ret;
+}
+
+static int nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog)
+{
+ struct nfp_net_ring_set rx = {
+ .n_rings = nn->num_rx_rings,
+ .mtu = nn->netdev->mtu,
+ .dcnt = nn->rxd_cnt,
+ };
+ struct nfp_net_ring_set tx = {
+ .n_rings = nn->num_tx_rings,
+ .dcnt = nn->txd_cnt,
+ };
+ int err;
+
+ if (prog && prog->xdp_adjust_head) {
+ nn_err(nn, "Does not support bpf_xdp_adjust_head()\n");
+ return -EOPNOTSUPP;
+ }
+ if (!prog && !nn->xdp_prog)
+ return 0;
+ if (prog && nn->xdp_prog) {
+ prog = xchg(&nn->xdp_prog, prog);
+ bpf_prog_put(prog);
+ nfp_net_xdp_offload(nn, nn->xdp_prog);
+ return 0;
+ }
+
+ tx.n_rings += prog ? nn->num_rx_rings : -nn->num_rx_rings;
+
+ /* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */
+ err = nfp_net_ring_reconfig(nn, &prog, &rx, &tx);
+ if (err)
+ return err;
+
+ /* @prog got swapped and is now the old one */
+ if (prog)
+ bpf_prog_put(prog);
+
+ nfp_net_xdp_offload(nn, nn->xdp_prog);
+
+ return 0;
+}
+
+static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+
+ switch (xdp->command) {
+ case XDP_SETUP_PROG:
+ return nfp_net_xdp_setup(nn, xdp->prog);
+ case XDP_QUERY_PROG:
+ xdp->prog_attached = !!nn->xdp_prog;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct net_device_ops nfp_net_netdev_ops = {
.ndo_open = nfp_net_netdev_open,
.ndo_stop = nfp_net_netdev_close,
@@ -2678,6 +3004,7 @@ static const struct net_device_ops nfp_net_netdev_ops = {
.ndo_features_check = nfp_net_features_check,
.ndo_udp_tunnel_add = nfp_net_add_vxlan_port,
.ndo_udp_tunnel_del = nfp_net_del_vxlan_port,
+ .ndo_xdp = nfp_net_xdp,
};
/**
@@ -2686,8 +3013,7 @@ static const struct net_device_ops nfp_net_netdev_ops = {
*/
void nfp_net_info(struct nfp_net *nn)
{
- nn_info(nn, "Netronome %s %sNetdev: TxQs=%d/%d RxQs=%d/%d\n",
- nn->is_nfp3200 ? "NFP-32xx" : "NFP-6xxx",
+ nn_info(nn, "Netronome NFP-6xxx %sNetdev: TxQs=%d/%d RxQs=%d/%d\n",
nn->is_vf ? "VF " : "",
nn->num_tx_rings, nn->max_tx_rings,
nn->num_rx_rings, nn->max_rx_rings);
@@ -2728,11 +3054,11 @@ void nfp_net_info(struct nfp_net *nn)
* Return: NFP Net device structure, or ERR_PTR on error.
*/
struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
- int max_tx_rings, int max_rx_rings)
+ unsigned int max_tx_rings,
+ unsigned int max_rx_rings)
{
struct net_device *netdev;
struct nfp_net *nn;
- int nqs;
netdev = alloc_etherdev_mqs(sizeof(struct nfp_net),
max_tx_rings, max_rx_rings);
@@ -2748,9 +3074,12 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
nn->max_tx_rings = max_tx_rings;
nn->max_rx_rings = max_rx_rings;
- nqs = netif_get_num_default_rss_queues();
- nn->num_tx_rings = min_t(int, nqs, max_tx_rings);
- nn->num_rx_rings = min_t(int, nqs, max_rx_rings);
+ nn->num_tx_rings = min_t(unsigned int, max_tx_rings, num_online_cpus());
+ nn->num_rx_rings = min_t(unsigned int, max_rx_rings,
+ netif_get_num_default_rss_queues());
+
+ nn->num_r_vecs = max(nn->num_tx_rings, nn->num_rx_rings);
+ nn->num_r_vecs = min_t(unsigned int, nn->num_r_vecs, num_online_cpus());
nn->txd_cnt = NFP_NET_TX_DESCS_DEFAULT;
nn->rxd_cnt = NFP_NET_RX_DESCS_DEFAULT;
@@ -2782,13 +3111,9 @@ void nfp_net_netdev_free(struct nfp_net *nn)
*/
static void nfp_net_rss_init(struct nfp_net *nn)
{
- int i;
-
netdev_rss_key_fill(nn->rss_key, NFP_NET_CFG_RSS_KEY_SZ);
- for (i = 0; i < sizeof(nn->rss_itbl); i++)
- nn->rss_itbl[i] =
- ethtool_rxfh_indir_default(i, nn->num_rx_rings);
+ nfp_net_rss_init_itbl(nn);
/* Enable IPv4/IPv6 TCP by default */
nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP |
@@ -2826,12 +3151,18 @@ int nfp_net_netdev_init(struct net_device *netdev)
nfp_net_write_mac_addr(nn);
+ /* Determine RX packet/metadata boundary offset */
+ if (nn->fw_ver.major >= 2)
+ nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
+ else
+ nn->rx_offset = NFP_NET_RX_OFFSET;
+
/* Set default MTU and Freelist buffer size */
if (nn->max_mtu < NFP_NET_DEFAULT_MTU)
netdev->mtu = nn->max_mtu;
else
netdev->mtu = NFP_NET_DEFAULT_MTU;
- nn->fl_bufsz = NFP_NET_DEFAULT_RX_BUFSZ;
+ nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, netdev->mtu);
/* Advertise/enable offloads based on capabilities
*
@@ -2902,18 +3233,6 @@ int nfp_net_netdev_init(struct net_device *netdev)
nn->ctrl |= NFP_NET_CFG_CTRL_IRQMOD;
}
- /* On NFP-3200 enable MSI-X auto-masking, if supported and the
- * interrupts are not shared.
- */
- if (nn->is_nfp3200 && nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO)
- nn->ctrl |= NFP_NET_CFG_CTRL_MSIXAUTO;
-
- /* On NFP4000/NFP6000, determine RX packet/metadata boundary offset */
- if (nn->fw_ver.major >= 2)
- nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
- else
- nn->rx_offset = NFP_NET_RX_OFFSET;
-
/* Stash the re-configuration queue away. First odd queue in TX Bar */
nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
@@ -2927,9 +3246,13 @@ int nfp_net_netdev_init(struct net_device *netdev)
return err;
/* Finalise the netdev setup */
- ether_setup(netdev);
netdev->netdev_ops = &nfp_net_netdev_ops;
netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
+
+ /* MTU range: 68 - hw-specific max */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = nn->max_mtu;
+
netif_carrier_off(netdev);
nfp_net_set_ethtool_ops(netdev);
@@ -2944,5 +3267,11 @@ int nfp_net_netdev_init(struct net_device *netdev)
*/
void nfp_net_netdev_clean(struct net_device *netdev)
{
- unregister_netdev(netdev);
+ struct nfp_net *nn = netdev_priv(netdev);
+
+ if (nn->xdp_prog)
+ bpf_prog_put(nn->xdp_prog);
+ if (nn->bpf_offload_xdp)
+ nfp_net_xdp_offload(nn, NULL);
+ unregister_netdev(nn->netdev);
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index 93b10b441acb..385ba355c965 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -50,7 +50,7 @@
/**
* Configuration BAR size.
*
- * The configuration BAR is 8K in size, but on the NFP6000, due to
+ * The configuration BAR is 8K in size, but due to
* THB-350, 32k needs to be reserved.
*/
#define NFP_NET_CFG_BAR_SZ (32 * 1024)
@@ -186,18 +186,13 @@
#define NFP_NET_CFG_START_RXQ 0x004c
/**
- * NFP-3200 workaround (0x0050 - 0x0058)
- * @NFP_NET_CFG_SPARE_ADDR: DMA address for ME code to use (e.g. YDS-155 fix)
- */
-#define NFP_NET_CFG_SPARE_ADDR 0x0050
-/**
- * NFP6000/NFP4000 - Prepend configuration
+ * Prepend configuration
*/
#define NFP_NET_CFG_RX_OFFSET 0x0050
#define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */
/**
- * NFP6000/NFP4000 - VXLAN/UDP encap configuration
+ * VXLAN/UDP encap configuration
* @NFP_NET_CFG_VXLAN_PORT: Base address of table of tunnels' UDP dst ports
* @NFP_NET_CFG_VXLAN_SZ: Size of the UDP port table in bytes
*/
@@ -205,7 +200,7 @@
#define NFP_NET_CFG_VXLAN_SZ 0x0008
/**
- * NFP6000 - BPF section
+ * BPF section
* @NFP_NET_CFG_BPF_ABI: BPF ABI version
* @NFP_NET_CFG_BPF_CAP: BPF capabilities
* @NFP_NET_CFG_BPF_MAX_LEN: Maximum size of JITed BPF code in bytes
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
index f7c9a5bc4aa3..c66f3f954aa8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
@@ -44,8 +44,8 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
struct nfp_net_r_vector *r_vec = file->private;
struct nfp_net_rx_ring *rx_ring;
struct nfp_net_rx_desc *rxd;
- struct sk_buff *skb;
struct nfp_net *nn;
+ void *frag;
int i;
rtnl_lock();
@@ -73,10 +73,9 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
seq_printf(file, "%04d: 0x%08x 0x%08x", i,
rxd->vals[0], rxd->vals[1]);
- skb = READ_ONCE(rx_ring->rxbufs[i].skb);
- if (skb)
- seq_printf(file, " skb->head=%p skb->data=%p",
- skb->head, skb->data);
+ frag = READ_ONCE(rx_ring->rxbufs[i].frag);
+ if (frag)
+ seq_printf(file, " frag=%p", frag);
if (rx_ring->rxbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad",
@@ -115,6 +114,16 @@ static const struct file_operations nfp_rx_q_fops = {
.llseek = seq_lseek
};
+static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f);
+
+static const struct file_operations nfp_tx_q_fops = {
+ .owner = THIS_MODULE,
+ .open = nfp_net_debugfs_tx_q_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek
+};
+
static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
{
struct nfp_net_r_vector *r_vec = file->private;
@@ -127,10 +136,13 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
rtnl_lock();
- if (!r_vec->nfp_net || !r_vec->tx_ring)
+ if (debugfs_real_fops(file->file) == &nfp_tx_q_fops)
+ tx_ring = r_vec->tx_ring;
+ else
+ tx_ring = r_vec->xdp_ring;
+ if (!r_vec->nfp_net || !tx_ring)
goto out;
nn = r_vec->nfp_net;
- tx_ring = r_vec->tx_ring;
if (!netif_running(nn->netdev))
goto out;
@@ -149,9 +161,14 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
txd->vals[2], txd->vals[3]);
skb = READ_ONCE(tx_ring->txbufs[i].skb);
- if (skb)
- seq_printf(file, " skb->head=%p skb->data=%p",
- skb->head, skb->data);
+ if (skb) {
+ if (tx_ring == r_vec->tx_ring)
+ seq_printf(file, " skb->head=%p skb->data=%p",
+ skb->head, skb->data);
+ else
+ seq_printf(file, " frag=%p", skb);
+ }
+
if (tx_ring->txbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad",
&tx_ring->txbufs[i].dma_addr);
@@ -177,7 +194,7 @@ static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f)
return single_open(f, nfp_net_debugfs_tx_q_read, inode->i_private);
}
-static const struct file_operations nfp_tx_q_fops = {
+static const struct file_operations nfp_xdp_q_fops = {
.owner = THIS_MODULE,
.open = nfp_net_debugfs_tx_q_open,
.release = single_release,
@@ -187,7 +204,7 @@ static const struct file_operations nfp_tx_q_fops = {
void nfp_net_debugfs_adapter_add(struct nfp_net *nn)
{
- struct dentry *queues, *tx, *rx;
+ struct dentry *queues, *tx, *rx, *xdp;
char int_name[16];
int i;
@@ -205,16 +222,19 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn)
rx = debugfs_create_dir("rx", queues);
tx = debugfs_create_dir("tx", queues);
- if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx))
+ xdp = debugfs_create_dir("xdp", queues);
+ if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx) || IS_ERR_OR_NULL(xdp))
return;
- for (i = 0; i < nn->num_rx_rings; i++) {
+ for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) {
sprintf(int_name, "%d", i);
debugfs_create_file(int_name, S_IRUSR, rx,
&nn->r_vecs[i], &nfp_rx_q_fops);
+ debugfs_create_file(int_name, S_IRUSR, xdp,
+ &nn->r_vecs[i], &nfp_xdp_q_fops);
}
- for (i = 0; i < nn->num_tx_rings; i++) {
+ for (i = 0; i < min(nn->max_tx_rings, nn->max_r_vecs); i++) {
sprintf(int_name, "%d", i);
debugfs_create_file(int_name, S_IRUSR, tx,
&nn->r_vecs[i], &nfp_tx_q_fops);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index 3418f2277e9d..1b26e9646574 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -158,6 +158,28 @@ static void nfp_net_get_ringparam(struct net_device *netdev,
ring->tx_pending = nn->txd_cnt;
}
+static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
+{
+ struct nfp_net_ring_set *reconfig_rx = NULL, *reconfig_tx = NULL;
+ struct nfp_net_ring_set rx = {
+ .n_rings = nn->num_rx_rings,
+ .mtu = nn->netdev->mtu,
+ .dcnt = rxd_cnt,
+ };
+ struct nfp_net_ring_set tx = {
+ .n_rings = nn->num_tx_rings,
+ .dcnt = txd_cnt,
+ };
+
+ if (nn->rxd_cnt != rxd_cnt)
+ reconfig_rx = &rx;
+ if (nn->txd_cnt != txd_cnt)
+ reconfig_tx = &tx;
+
+ return nfp_net_ring_reconfig(nn, &nn->xdp_prog,
+ reconfig_rx, reconfig_tx);
+}
+
static int nfp_net_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
@@ -614,6 +636,76 @@ static int nfp_net_set_coalesce(struct net_device *netdev,
return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD);
}
+static void nfp_net_get_channels(struct net_device *netdev,
+ struct ethtool_channels *channel)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+ unsigned int num_tx_rings;
+
+ num_tx_rings = nn->num_tx_rings;
+ if (nn->xdp_prog)
+ num_tx_rings -= nn->num_rx_rings;
+
+ channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs);
+ channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs);
+ channel->max_combined = min(channel->max_rx, channel->max_tx);
+ channel->max_other = NFP_NET_NON_Q_VECTORS;
+ channel->combined_count = min(nn->num_rx_rings, num_tx_rings);
+ channel->rx_count = nn->num_rx_rings - channel->combined_count;
+ channel->tx_count = num_tx_rings - channel->combined_count;
+ channel->other_count = NFP_NET_NON_Q_VECTORS;
+}
+
+static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx,
+ unsigned int total_tx)
+{
+ struct nfp_net_ring_set *reconfig_rx = NULL, *reconfig_tx = NULL;
+ struct nfp_net_ring_set rx = {
+ .n_rings = total_rx,
+ .mtu = nn->netdev->mtu,
+ .dcnt = nn->rxd_cnt,
+ };
+ struct nfp_net_ring_set tx = {
+ .n_rings = total_tx,
+ .dcnt = nn->txd_cnt,
+ };
+
+ if (nn->num_rx_rings != total_rx)
+ reconfig_rx = &rx;
+ if (nn->num_stack_tx_rings != total_tx ||
+ (nn->xdp_prog && reconfig_rx))
+ reconfig_tx = &tx;
+
+ /* nfp_net_check_config() will catch tx.n_rings > nn->max_tx_rings */
+ if (nn->xdp_prog)
+ tx.n_rings += total_rx;
+
+ return nfp_net_ring_reconfig(nn, &nn->xdp_prog,
+ reconfig_rx, reconfig_tx);
+}
+
+static int nfp_net_set_channels(struct net_device *netdev,
+ struct ethtool_channels *channel)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+ unsigned int total_rx, total_tx;
+
+ /* Reject unsupported */
+ if (!channel->combined_count ||
+ channel->other_count != NFP_NET_NON_Q_VECTORS ||
+ (channel->rx_count && channel->tx_count))
+ return -EINVAL;
+
+ total_rx = channel->combined_count + channel->rx_count;
+ total_tx = channel->combined_count + channel->tx_count;
+
+ if (total_rx > min(nn->max_rx_rings, nn->max_r_vecs) ||
+ total_tx > min(nn->max_tx_rings, nn->max_r_vecs))
+ return -EINVAL;
+
+ return nfp_net_set_num_rings(nn, total_rx, total_tx);
+}
+
static const struct ethtool_ops nfp_net_ethtool_ops = {
.get_drvinfo = nfp_net_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -632,6 +724,8 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.get_regs = nfp_net_get_regs,
.get_coalesce = nfp_net_get_coalesce,
.set_coalesce = nfp_net_set_coalesce,
+ .get_channels = nfp_net_get_channels,
+ .set_channels = nfp_net_set_channels,
};
void nfp_net_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c
index 8acfb631a0ea..18a851eb3508 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_offload.c
@@ -111,6 +111,9 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
const struct tc_action *a;
LIST_HEAD(actions);
+ if (!cls_bpf->exts)
+ return NN_ACT_XDP;
+
/* TC direct action */
if (cls_bpf->exts_integrated) {
if (tc_no_actions(cls_bpf->exts))
@@ -128,7 +131,7 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
if (is_tcf_gact_shot(a))
return NN_ACT_TC_DROP;
- if (is_tcf_mirred_redirect(a) &&
+ if (is_tcf_mirred_egress_redirect(a) &&
tcf_mirred_ifindex(a) == nn->netdev->ifindex)
return NN_ACT_TC_REDIR;
}
@@ -233,9 +236,7 @@ static int nfp_net_bpf_stop(struct nfp_net *nn)
return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
}
-int
-nfp_net_bpf_offload(struct nfp_net *nn, u32 handle, __be16 proto,
- struct tc_cls_bpf_offload *cls_bpf)
+int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
{
struct nfp_bpf_result res;
dma_addr_t dma_addr;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
index 2800bbf65a89..d065235034d4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
@@ -63,9 +63,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn)
u8 mac_addr[ETH_ALEN];
put_unaligned_be32(nn_readl(nn, NFP_NET_CFG_MACADDR + 0), &mac_addr[0]);
- /* We can't do readw for NFP-3200 compatibility */
- put_unaligned_be16(nn_readl(nn, NFP_NET_CFG_MACADDR + 4) >> 16,
- &mac_addr[4]);
+ put_unaligned_be16(nn_readw(nn, NFP_NET_CFG_MACADDR + 6), &mac_addr[4]);
if (!is_valid_ether_addr(mac_addr)) {
eth_hw_addr_random(nn->netdev);
@@ -86,7 +84,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
int tx_bar_no, rx_bar_no;
u8 __iomem *ctrl_bar;
struct nfp_net *nn;
- int is_nfp3200;
u32 startq;
int stride;
int err;
@@ -101,15 +98,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
goto err_pci_disable;
}
- switch (pdev->device) {
- case PCI_DEVICE_NFP6000VF:
- is_nfp3200 = 0;
- break;
- default:
- err = -ENODEV;
- goto err_pci_regions;
- }
-
pci_set_master(pdev);
err = dma_set_mask_and_coherent(&pdev->dev,
@@ -149,15 +137,9 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
} else {
switch (fw_ver.major) {
case 1 ... 4:
- if (is_nfp3200) {
- stride = 2;
- tx_bar_no = NFP_NET_Q0_BAR;
- rx_bar_no = NFP_NET_Q1_BAR;
- } else {
- stride = 4;
- tx_bar_no = NFP_NET_Q0_BAR;
- rx_bar_no = tx_bar_no;
- }
+ stride = 4;
+ tx_bar_no = NFP_NET_Q0_BAR;
+ rx_bar_no = tx_bar_no;
break;
default:
dev_err(&pdev->dev, "Unsupported Firmware ABI %d.%d.%d.%d\n",
@@ -189,20 +171,10 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2;
}
- /* XXX Implement a workaround for THB-350 here. Ideally, we
- * have a different PCI ID for A rev VFs.
- */
- switch (pdev->device) {
- case PCI_DEVICE_NFP6000VF:
- startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
- tx_bar_off = NFP_PCIE_QUEUE(startq);
- startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
- rx_bar_off = NFP_PCIE_QUEUE(startq);
- break;
- default:
- err = -ENODEV;
- goto err_ctrl_unmap;
- }
+ startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
+ tx_bar_off = NFP_PCIE_QUEUE(startq);
+ startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
+ rx_bar_off = NFP_PCIE_QUEUE(startq);
/* Allocate and initialise the netdev */
nn = nfp_net_netdev_alloc(pdev, max_tx_rings, max_rx_rings);
@@ -214,7 +186,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
nn->fw_ver = fw_ver;
nn->ctrl_bar = ctrl_bar;
nn->is_vf = 1;
- nn->is_nfp3200 = is_nfp3200;
nn->stride_tx = stride;
nn->stride_rx = stride;
diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index adbc47f2d132..df4188cb43e0 100644
--- a/drivers/net/ethernet/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -304,7 +304,6 @@ static const struct net_device_ops netx_eth_netdev_ops = {
.ndo_start_xmit = netx_eth_hard_start_xmit,
.ndo_tx_timeout = netx_eth_timeout,
.ndo_set_rx_mode = netx_eth_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index 712d8bcb7d8c..119f6dca71f0 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -915,7 +915,6 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
.ndo_set_mac_address = w90p910_set_mac_address,
.ndo_do_ioctl = w90p910_ether_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static void __init get_mac_address(struct net_device *dev)
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 9b0d7f463ff3..3913f07279d2 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -3008,17 +3008,12 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
struct fe_priv *np = netdev_priv(dev);
int old_mtu;
- if (new_mtu < 64 || new_mtu > np->pkt_limit)
- return -EINVAL;
-
old_mtu = dev->mtu;
dev->mtu = new_mtu;
/* return early if the buffer sizes will not change */
if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN)
return 0;
- if (old_mtu == new_mtu)
- return 0;
/* synchronized against open : rtnl_lock() held by caller */
if (netif_running(dev)) {
@@ -5719,6 +5714,10 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
/* Add loopback capability to the device. */
dev->hw_features |= NETIF_F_LOOPBACK;
+ /* MTU range: 64 - 1500 or 9100 */
+ dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
+ dev->max_mtu = np->pkt_limit;
+
np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) ||
(id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) ||
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 8e13ec84c538..dd6b0d0f7fa5 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1256,7 +1256,6 @@ static const struct net_device_ops lpc_netdev_ops = {
.ndo_do_ioctl = lpc_eth_ioctl,
.ndo_set_mac_address = lpc_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int lpc_eth_drv_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 3cd87a41ac92..d461f419948e 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2260,16 +2260,10 @@ static int pch_gbe_set_mac(struct net_device *netdev, void *addr)
static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
{
struct pch_gbe_adapter *adapter = netdev_priv(netdev);
- int max_frame;
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
unsigned long old_rx_buffer_len = adapter->rx_buffer_len;
int err;
- max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
- (max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) {
- netdev_err(netdev, "Invalid MTU setting\n");
- return -EINVAL;
- }
if (max_frame <= PCH_GBE_FRAME_SIZE_2048)
adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
else if (max_frame <= PCH_GBE_FRAME_SIZE_4096)
@@ -2633,6 +2627,11 @@ static int pch_gbe_probe(struct pci_dev *pdev,
netdev->features = netdev->hw_features;
pch_gbe_set_ethtool_ops(netdev);
+ /* MTU range: 46 - 10300 */
+ netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ netdev->max_mtu = PCH_GBE_MAX_JUMBO_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN);
+
pch_gbe_mac_load_mac_addr(&adapter->hw);
pch_gbe_mac_reset_hw(&adapter->hw);
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index 91be2f02ef1c..2d04679a923a 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -568,7 +568,6 @@ static const struct net_device_ops hamachi_netdev_ops = {
.ndo_start_xmit = hamachi_start_xmit,
.ndo_get_stats = hamachi_get_stats,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = hamachi_tx_timeout,
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index fb1d1031b091..2a2ca5fa0c69 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -360,7 +360,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = yellowfin_close,
.ndo_start_xmit = yellowfin_start_xmit,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 2f4a837f0d6a..badfa1d562a4 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -53,7 +53,7 @@
* - Multiqueue RX/TX
*/
-#define PE_MIN_MTU 64
+#define PE_MIN_MTU (ETH_ZLEN + ETH_HLEN)
#define PE_MAX_MTU 9000
#define PE_DEF_MTU ETH_DATA_LEN
@@ -1611,9 +1611,6 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
int running;
int ret = 0;
- if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
- return -EINVAL;
-
running = netif_running(dev);
if (running) {
@@ -1635,7 +1632,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
}
/* Setup checksum channels if large MTU and none already allocated */
- if (new_mtu > 1500 && !mac->num_cs) {
+ if (new_mtu > PE_DEF_MTU && !mac->num_cs) {
pasemi_mac_setup_csrings(mac);
if (!mac->num_cs) {
ret = -ENOMEM;
@@ -1757,6 +1754,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->netdev_ops = &pasemi_netdev_ops;
dev->mtu = PE_DEF_MTU;
+
+ /* MTU range: 64 - 9000 */
+ dev->min_mtu = PE_MIN_MTU;
+ dev->max_mtu = PE_MAX_MTU;
+
/* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
index 32f2a45f4ab2..3cfd10503446 100644
--- a/drivers/net/ethernet/qlogic/Kconfig
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -110,4 +110,7 @@ config QEDE
config QED_RDMA
bool
+config QED_ISCSI
+ bool
+
endif # NET_VENDOR_QLOGIC
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index 2b10f1bcd151..a996801d442d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
@@ -987,20 +987,8 @@ int netxen_send_lro_cleanup(struct netxen_adapter *adapter)
int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- int max_mtu;
int rc = 0;
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- max_mtu = P3_MAX_MTU;
- else
- max_mtu = P2_MAX_MTU;
-
- if (mtu > max_mtu) {
- printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
- netdev->name, max_mtu);
- return -EINVAL;
- }
-
if (adapter->set_mtu)
rc = adapter->set_mtu(adapter, mtu);
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 7a0281a36c28..561fb94c7267 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1572,6 +1572,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->physical_port = i;
}
+ /* MTU range: 0 - 8000 (P2) or 9600 (P3) */
+ netdev->min_mtu = 0;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netdev->max_mtu = P3_MAX_MTU;
+ else
+ netdev->max_mtu = P2_MAX_MTU;
+
netxen_nic_clear_stats(adapter);
err = netxen_setup_intr(adapter);
diff --git a/drivers/net/ethernet/qlogic/qed/Makefile b/drivers/net/ethernet/qlogic/qed/Makefile
index 967acf322c09..729e43768e99 100644
--- a/drivers/net/ethernet/qlogic/qed/Makefile
+++ b/drivers/net/ethernet/qlogic/qed/Makefile
@@ -6,3 +6,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_QED_RDMA) += qed_roce.o
+qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 653bb5735f0c..44c184ebe3b0 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -35,6 +35,7 @@ extern const struct qed_common_ops qed_common_ops_pass;
#define QED_WFQ_UNIT 100
+#define ISCSI_BDQ_ID(_port_id) (_port_id)
#define QED_WID_SIZE (1024)
#define QED_PF_DEMS_SIZE (4)
@@ -154,7 +155,10 @@ struct qed_qm_iids {
u32 tids;
};
-enum QED_RESOURCES {
+/* HW / FW resources, output of features supported below, most information
+ * is received from MFW.
+ */
+enum qed_resources {
QED_SB,
QED_L2_QUEUE,
QED_VPORT,
@@ -166,6 +170,7 @@ enum QED_RESOURCES {
QED_RDMA_CNQ_RAM,
QED_ILT,
QED_LL2_QUEUE,
+ QED_CMDQS_CQS,
QED_RDMA_STATS_QUEUE,
QED_MAX_RESC,
};
@@ -174,6 +179,7 @@ enum QED_FEATURE {
QED_PF_L2_QUE,
QED_VF,
QED_RDMA_CNQ,
+ QED_VF_L2_QUE,
QED_MAX_FEATURES,
};
@@ -195,6 +201,11 @@ enum qed_dev_cap {
QED_DEV_CAP_ROCE,
};
+enum qed_wol_support {
+ QED_WOL_SUPPORT_NONE,
+ QED_WOL_SUPPORT_PME,
+};
+
struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
@@ -226,15 +237,9 @@ struct qed_hw_info {
u32 port_mode;
u32 hw_mode;
unsigned long device_capabilities;
-};
+ u16 mtu;
-struct qed_hw_cid_data {
- u32 cid;
- bool b_cid_allocated;
-
- /* Additional identifiers */
- u16 opaque_fid;
- u8 vport_id;
+ enum qed_wol_support b_wol_support;
};
/* maximun size of read/write commands (HW limit) */
@@ -378,7 +383,9 @@ struct qed_hwfn {
/* Protocol related */
bool using_ll2;
struct qed_ll2_info *p_ll2_info;
+ struct qed_ooo_info *p_ooo_info;
struct qed_rdma_info *p_rdma_info;
+ struct qed_iscsi_info *p_iscsi_info;
struct qed_pf_params pf_params;
bool b_rdma_enabled_in_prs;
@@ -403,9 +410,6 @@ struct qed_hwfn {
struct qed_dcbx_info *p_dcbx_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 */
@@ -538,7 +542,9 @@ struct qed_dev {
u8 mcp_rev;
u8 boot_mode;
- u8 wol;
+ /* WoL related configurations */
+ u8 wol_config;
+ u8 wol_mac[ETH_ALEN];
u32 int_mode;
enum qed_coalescing_mode int_coalescing_mode;
@@ -578,6 +584,8 @@ struct qed_dev {
/* Linux specific here */
struct qede_dev *edev;
struct pci_dev *pdev;
+ u32 flags;
+#define QED_FLAG_STORAGE_STARTED (BIT(0))
int msg_enable;
struct pci_params pci_params;
@@ -591,6 +599,7 @@ struct qed_dev {
union {
struct qed_common_cb_ops *common;
struct qed_eth_cb_ops *eth;
+ struct qed_iscsi_cb_ops *iscsi;
} protocol_ops;
void *ops_cookie;
@@ -600,7 +609,7 @@ struct qed_dev {
struct qed_cb_ll2_info *ll2;
u8 ll2_mac_address[ETH_ALEN];
#endif
-
+ DECLARE_HASHTABLE(connections, 10);
const struct firmware *firmware;
u32 rdma_max_sge;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index edae5fc5fccd..3b2250021c5f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -29,8 +29,10 @@
#include "qed_hw.h"
#include "qed_init_ops.h"
#include "qed_int.h"
+#include "qed_iscsi.h"
#include "qed_ll2.h"
#include "qed_mcp.h"
+#include "qed_ooo.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_sriov.h"
@@ -137,15 +139,6 @@ void qed_resc_free(struct qed_dev *cdev)
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);
@@ -155,6 +148,10 @@ void qed_resc_free(struct qed_dev *cdev)
#ifdef CONFIG_QED_LL2
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
#endif
+ if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
+ qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
+ qed_ooo_free(p_hwfn, p_hwfn->p_ooo_info);
+ }
qed_iov_free(p_hwfn);
qed_dmae_info_free(p_hwfn);
qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
@@ -411,6 +408,8 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
int qed_resc_alloc(struct qed_dev *cdev)
{
+ struct qed_iscsi_info *p_iscsi_info;
+ struct qed_ooo_info *p_ooo_info;
#ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info;
#endif
@@ -425,23 +424,6 @@ int qed_resc_alloc(struct qed_dev *cdev)
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)
- goto alloc_no_mem;
-
- p_hwfn->p_rx_cids = kzalloc(rx_size, GFP_KERNEL);
- if (!p_hwfn->p_rx_cids)
- goto alloc_no_mem;
- }
-
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
u32 n_eqes, num_cons;
@@ -533,6 +515,16 @@ int qed_resc_alloc(struct qed_dev *cdev)
p_hwfn->p_ll2_info = p_ll2_info;
}
#endif
+ if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
+ p_iscsi_info = qed_iscsi_alloc(p_hwfn);
+ if (!p_iscsi_info)
+ goto alloc_no_mem;
+ p_hwfn->p_iscsi_info = p_iscsi_info;
+ p_ooo_info = qed_ooo_alloc(p_hwfn);
+ if (!p_ooo_info)
+ goto alloc_no_mem;
+ p_hwfn->p_ooo_info = p_ooo_info;
+ }
/* DMA info initialization */
rc = qed_dmae_info_alloc(p_hwfn);
@@ -586,6 +578,10 @@ void qed_resc_setup(struct qed_dev *cdev)
if (p_hwfn->using_ll2)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
#endif
+ if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
+ qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info);
+ qed_ooo_setup(p_hwfn, p_hwfn->p_ooo_info);
+ }
}
}
@@ -1057,8 +1053,10 @@ int qed_hw_init(struct qed_dev *cdev,
bool allow_npar_tx_switch,
const u8 *bin_fw_data)
{
- u32 load_code, param;
- int rc, mfw_rc, i;
+ u32 load_code, param, drv_mb_param;
+ bool b_default_mtu = true;
+ struct qed_hwfn *p_hwfn;
+ int rc = 0, mfw_rc, i;
if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
@@ -1074,6 +1072,12 @@ int qed_hw_init(struct qed_dev *cdev,
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ /* If management didn't provide a default, set one of our own */
+ if (!p_hwfn->hw_info.mtu) {
+ p_hwfn->hw_info.mtu = 1500;
+ b_default_mtu = false;
+ }
+
if (IS_VF(cdev)) {
p_hwfn->b_int_enabled = 1;
continue;
@@ -1157,6 +1161,38 @@ int qed_hw_init(struct qed_dev *cdev,
p_hwfn->hw_init_done = true;
}
+ if (IS_PF(cdev)) {
+ p_hwfn = QED_LEADING_HWFN(cdev);
+ drv_mb_param = (FW_MAJOR_VERSION << 24) |
+ (FW_MINOR_VERSION << 16) |
+ (FW_REVISION_VERSION << 8) |
+ (FW_ENGINEERING_VERSION);
+ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
+ DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER,
+ drv_mb_param, &load_code, &param);
+ if (rc)
+ DP_INFO(p_hwfn, "Failed to update firmware version\n");
+
+ if (!b_default_mtu) {
+ rc = qed_mcp_ov_update_mtu(p_hwfn, p_hwfn->p_main_ptt,
+ p_hwfn->hw_info.mtu);
+ if (rc)
+ DP_INFO(p_hwfn,
+ "Failed to update default mtu\n");
+ }
+
+ rc = qed_mcp_ov_update_driver_state(p_hwfn,
+ p_hwfn->p_main_ptt,
+ QED_OV_DRIVER_STATE_DISABLED);
+ if (rc)
+ DP_INFO(p_hwfn, "Failed to update driver state\n");
+
+ rc = qed_mcp_ov_update_eswitch(p_hwfn, p_hwfn->p_main_ptt,
+ QED_OV_ESWITCH_VEB);
+ if (rc)
+ DP_INFO(p_hwfn, "Failed to update eswitch mode\n");
+ }
+
return 0;
}
@@ -1324,8 +1360,24 @@ int qed_hw_reset(struct qed_dev *cdev)
{
int rc = 0;
u32 unload_resp, unload_param;
+ u32 wol_param;
int i;
+ switch (cdev->wol_config) {
+ case QED_OV_WOL_DISABLED:
+ wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED;
+ break;
+ case QED_OV_WOL_ENABLED:
+ wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED;
+ break;
+ default:
+ DP_NOTICE(cdev,
+ "Unknown WoL configuration %02x\n", cdev->wol_config);
+ /* Fallthrough */
+ case QED_OV_WOL_DEFAULT:
+ wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
+ }
+
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
@@ -1354,8 +1406,7 @@ int qed_hw_reset(struct qed_dev *cdev)
/* 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,
+ DRV_MSG_CODE_UNLOAD_REQ, wol_param,
&unload_resp, &unload_param);
if (rc) {
DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_REQ failed\n");
@@ -1421,6 +1472,7 @@ static void get_function_id(struct qed_hwfn *p_hwfn)
static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
{
u32 *feat_num = p_hwfn->hw_info.feat_num;
+ struct qed_sb_cnt_info sb_cnt_info;
int num_features = 1;
if (IS_ENABLED(CONFIG_QED_RDMA) &&
@@ -1439,53 +1491,257 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
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);
+
+ memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
+ qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
+ feat_num[QED_VF_L2_QUE] =
+ min_t(u32,
+ RESC_NUM(p_hwfn, QED_L2_QUEUE) -
+ FEAT_NUM(p_hwfn, QED_PF_L2_QUE), sb_cnt_info.sb_iov_cnt);
+
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_PROBE,
+ "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d #SBS=%d num_features=%d\n",
+ (int)FEAT_NUM(p_hwfn, QED_PF_L2_QUE),
+ (int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE),
+ (int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ),
+ RESC_NUM(p_hwfn, QED_SB), num_features);
}
-static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
+static enum resource_id_enum qed_hw_get_mfw_res_id(enum qed_resources res_id)
+{
+ enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
+
+ switch (res_id) {
+ case QED_SB:
+ mfw_res_id = RESOURCE_NUM_SB_E;
+ break;
+ case QED_L2_QUEUE:
+ mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
+ break;
+ case QED_VPORT:
+ mfw_res_id = RESOURCE_NUM_VPORT_E;
+ break;
+ case QED_RSS_ENG:
+ mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
+ break;
+ case QED_PQ:
+ mfw_res_id = RESOURCE_NUM_PQ_E;
+ break;
+ case QED_RL:
+ mfw_res_id = RESOURCE_NUM_RL_E;
+ break;
+ case QED_MAC:
+ case QED_VLAN:
+ /* Each VFC resource can accommodate both a MAC and a VLAN */
+ mfw_res_id = RESOURCE_VFC_FILTER_E;
+ break;
+ case QED_ILT:
+ mfw_res_id = RESOURCE_ILT_E;
+ break;
+ case QED_LL2_QUEUE:
+ mfw_res_id = RESOURCE_LL2_QUEUE_E;
+ break;
+ case QED_RDMA_CNQ_RAM:
+ case QED_CMDQS_CQS:
+ /* CNQ/CMDQS are the same resource */
+ mfw_res_id = RESOURCE_CQS_E;
+ break;
+ case QED_RDMA_STATS_QUEUE:
+ mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
+ break;
+ default:
+ break;
+ }
+
+ return mfw_res_id;
+}
+
+static u32 qed_hw_get_dflt_resc_num(struct qed_hwfn *p_hwfn,
+ enum qed_resources res_id)
{
- u8 enabled_func_idx = p_hwfn->enabled_func_idx;
- u32 *resc_start = p_hwfn->hw_info.resc_start;
u8 num_funcs = p_hwfn->num_funcs_on_engine;
- u32 *resc_num = p_hwfn->hw_info.resc_num;
struct qed_sb_cnt_info sb_cnt_info;
- int i, max_vf_vlan_filters;
+ u32 dflt_resc_num = 0;
- memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
+ switch (res_id) {
+ case QED_SB:
+ memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
+ qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
+ dflt_resc_num = sb_cnt_info.sb_cnt;
+ break;
+ case QED_L2_QUEUE:
+ dflt_resc_num = MAX_NUM_L2_QUEUES_BB / num_funcs;
+ break;
+ case QED_VPORT:
+ dflt_resc_num = MAX_NUM_VPORTS_BB / num_funcs;
+ break;
+ case QED_RSS_ENG:
+ dflt_resc_num = ETH_RSS_ENGINE_NUM_BB / num_funcs;
+ break;
+ case QED_PQ:
+ /* The granularity of the PQs is 8 */
+ dflt_resc_num = MAX_QM_TX_QUEUES_BB / num_funcs;
+ dflt_resc_num &= ~0x7;
+ break;
+ case QED_RL:
+ dflt_resc_num = MAX_QM_GLOBAL_RLS / num_funcs;
+ break;
+ case QED_MAC:
+ case QED_VLAN:
+ /* Each VFC resource can accommodate both a MAC and a VLAN */
+ dflt_resc_num = ETH_NUM_MAC_FILTERS / num_funcs;
+ break;
+ case QED_ILT:
+ dflt_resc_num = PXP_NUM_ILT_RECORDS_BB / num_funcs;
+ break;
+ case QED_LL2_QUEUE:
+ dflt_resc_num = MAX_NUM_LL2_RX_QUEUES / num_funcs;
+ break;
+ case QED_RDMA_CNQ_RAM:
+ case QED_CMDQS_CQS:
+ /* CNQ/CMDQS are the same resource */
+ dflt_resc_num = NUM_OF_CMDQS_CQS / num_funcs;
+ break;
+ case QED_RDMA_STATS_QUEUE:
+ dflt_resc_num = RDMA_NUM_STATISTIC_COUNTERS_BB / num_funcs;
+ break;
+ default:
+ break;
+ }
-#ifdef CONFIG_QED_SRIOV
- max_vf_vlan_filters = QED_ETH_MAX_VF_NUM_VLAN_FILTERS;
-#else
- max_vf_vlan_filters = 0;
-#endif
+ return dflt_resc_num;
+}
+
+static const char *qed_hw_get_resc_name(enum qed_resources res_id)
+{
+ switch (res_id) {
+ case QED_SB:
+ return "SB";
+ case QED_L2_QUEUE:
+ return "L2_QUEUE";
+ case QED_VPORT:
+ return "VPORT";
+ case QED_RSS_ENG:
+ return "RSS_ENG";
+ case QED_PQ:
+ return "PQ";
+ case QED_RL:
+ return "RL";
+ case QED_MAC:
+ return "MAC";
+ case QED_VLAN:
+ return "VLAN";
+ case QED_RDMA_CNQ_RAM:
+ return "RDMA_CNQ_RAM";
+ case QED_ILT:
+ return "ILT";
+ case QED_LL2_QUEUE:
+ return "LL2_QUEUE";
+ case QED_CMDQS_CQS:
+ return "CMDQS_CQS";
+ case QED_RDMA_STATS_QUEUE:
+ return "RDMA_STATS_QUEUE";
+ default:
+ return "UNKNOWN_RESOURCE";
+ }
+}
- qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
+static int qed_hw_set_resc_info(struct qed_hwfn *p_hwfn,
+ enum qed_resources res_id)
+{
+ u32 dflt_resc_num = 0, dflt_resc_start = 0, mcp_resp, mcp_param;
+ u32 *p_resc_num, *p_resc_start;
+ struct resource_info resc_info;
+ int rc;
+
+ p_resc_num = &RESC_NUM(p_hwfn, res_id);
+ p_resc_start = &RESC_START(p_hwfn, res_id);
+
+ /* Default values assumes that each function received equal share */
+ dflt_resc_num = qed_hw_get_dflt_resc_num(p_hwfn, res_id);
+ if (!dflt_resc_num) {
+ DP_ERR(p_hwfn,
+ "Failed to get default amount for resource %d [%s]\n",
+ res_id, qed_hw_get_resc_name(res_id));
+ return -EINVAL;
+ }
+ dflt_resc_start = dflt_resc_num * p_hwfn->enabled_func_idx;
+
+ memset(&resc_info, 0, sizeof(resc_info));
+ resc_info.res_id = qed_hw_get_mfw_res_id(res_id);
+ if (resc_info.res_id == RESOURCE_NUM_INVALID) {
+ DP_ERR(p_hwfn,
+ "Failed to match resource %d [%s] with the MFW resources\n",
+ res_id, qed_hw_get_resc_name(res_id));
+ return -EINVAL;
+ }
+
+ rc = qed_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, &resc_info,
+ &mcp_resp, &mcp_param);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "MFW response failure for an allocation request for resource %d [%s]\n",
+ res_id, qed_hw_get_resc_name(res_id));
+ return rc;
+ }
- resc_num[QED_SB] = min_t(u32,
- (MAX_SB_PER_PATH_BB / num_funcs),
- sb_cnt_info.sb_cnt);
- 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] = min_t(u32, 64, resc_num[QED_VPORT]);
- 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] = PXP_NUM_ILT_RECORDS_BB / num_funcs;
- resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs;
- resc_num[QED_RDMA_CNQ_RAM] = NUM_OF_CMDQS_CQS / num_funcs;
- resc_num[QED_RDMA_STATS_QUEUE] = RDMA_NUM_STATISTIC_COUNTERS_BB /
- num_funcs;
-
- for (i = 0; i < QED_MAX_RESC; i++)
- resc_start[i] = resc_num[i] * enabled_func_idx;
+ /* Default driver values are applied in the following cases:
+ * - The resource allocation MB command is not supported by the MFW
+ * - There is an internal error in the MFW while processing the request
+ * - The resource ID is unknown to the MFW
+ */
+ if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK &&
+ mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED) {
+ DP_NOTICE(p_hwfn,
+ "Resource %d [%s]: No allocation info was received [mcp_resp 0x%x]. Applying default values [num %d, start %d].\n",
+ res_id,
+ qed_hw_get_resc_name(res_id),
+ mcp_resp, dflt_resc_num, dflt_resc_start);
+ *p_resc_num = dflt_resc_num;
+ *p_resc_start = dflt_resc_start;
+ goto out;
+ }
+
+ /* Special handling for status blocks; Would be revised in future */
+ if (res_id == QED_SB) {
+ resc_info.size -= 1;
+ resc_info.offset -= p_hwfn->enabled_func_idx;
+ }
+
+ *p_resc_num = resc_info.size;
+ *p_resc_start = resc_info.offset;
+
+out:
+ /* PQs have to divide by 8 [that's the HW granularity].
+ * Reduce number so it would fit.
+ */
+ if ((res_id == QED_PQ) && ((*p_resc_num % 8) || (*p_resc_start % 8))) {
+ DP_INFO(p_hwfn,
+ "PQs need to align by 8; Number %08x --> %08x, Start %08x --> %08x\n",
+ *p_resc_num,
+ (*p_resc_num) & ~0x7,
+ *p_resc_start, (*p_resc_start) & ~0x7);
+ *p_resc_num &= ~0x7;
+ *p_resc_start &= ~0x7;
+ }
+
+ return 0;
+}
+
+static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
+{
+ u8 res_id;
+ int rc;
+
+ for (res_id = 0; res_id < QED_MAX_RESC; res_id++) {
+ rc = qed_hw_set_resc_info(p_hwfn, res_id);
+ if (rc)
+ return rc;
+ }
/* Sanity for ILT */
- if (RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB) {
+ if ((RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB)) {
DP_NOTICE(p_hwfn, "Can't assign ILT pages [%08x,...,%08x]\n",
RESC_START(p_hwfn, QED_ILT),
RESC_END(p_hwfn, QED_ILT) - 1);
@@ -1495,34 +1751,12 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
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"
- "LL2_QUEUE = %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],
- RESC_NUM(p_hwfn, QED_LL2_QUEUE),
- RESC_START(p_hwfn, QED_LL2_QUEUE));
+ "The numbers for each resource are:\n");
+ for (res_id = 0; res_id < QED_MAX_RESC; res_id++)
+ DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, "%s = %d start = %d\n",
+ qed_hw_get_resc_name(res_id),
+ RESC_NUM(p_hwfn, res_id),
+ RESC_START(p_hwfn, res_id));
return 0;
}
@@ -1801,6 +2035,9 @@ qed_get_hw_info(struct qed_hwfn *p_hwfn,
qed_get_num_funcs(p_hwfn, p_ptt);
+ if (qed_mcp_is_init(p_hwfn))
+ p_hwfn->hw_info.mtu = p_hwfn->mcp_info->func_info.mtu;
+
return qed_hw_get_resc(p_hwfn);
}
@@ -1975,8 +2212,13 @@ int qed_hw_prepare(struct qed_dev *cdev,
void qed_hw_remove(struct qed_dev *cdev)
{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
int i;
+ if (IS_PF(cdev))
+ qed_mcp_ov_update_driver_state(p_hwfn, p_hwfn->p_main_ptt,
+ QED_OV_DRIVER_STATE_NOT_LOADED);
+
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
@@ -2037,12 +2279,12 @@ static void qed_chain_free_pbl(struct qed_dev *cdev, struct qed_chain *p_chain)
{
void **pp_virt_addr_tbl = p_chain->pbl.pp_virt_addr_tbl;
u32 page_cnt = p_chain->page_cnt, i, pbl_size;
- u8 *p_pbl_virt = p_chain->pbl.p_virt_table;
+ u8 *p_pbl_virt = p_chain->pbl_sp.p_virt_table;
if (!pp_virt_addr_tbl)
return;
- if (!p_chain->pbl.p_virt_table)
+ if (!p_pbl_virt)
goto out;
for (i = 0; i < page_cnt; i++) {
@@ -2060,7 +2302,8 @@ static void qed_chain_free_pbl(struct qed_dev *cdev, struct qed_chain *p_chain)
pbl_size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE;
dma_free_coherent(&cdev->pdev->dev,
pbl_size,
- p_chain->pbl.p_virt_table, p_chain->pbl.p_phys_table);
+ p_chain->pbl_sp.p_virt_table,
+ p_chain->pbl_sp.p_phys_table);
out:
vfree(p_chain->pbl.pp_virt_addr_tbl);
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 2777d5bb4380..785ab03683eb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -8526,6 +8526,41 @@ struct mdump_config_stc {
u32 valid_logs;
};
+enum resource_id_enum {
+ RESOURCE_NUM_SB_E = 0,
+ RESOURCE_NUM_L2_QUEUE_E = 1,
+ RESOURCE_NUM_VPORT_E = 2,
+ RESOURCE_NUM_VMQ_E = 3,
+ RESOURCE_FACTOR_NUM_RSS_PF_E = 4,
+ RESOURCE_FACTOR_RSS_PER_VF_E = 5,
+ RESOURCE_NUM_RL_E = 6,
+ RESOURCE_NUM_PQ_E = 7,
+ RESOURCE_NUM_VF_E = 8,
+ RESOURCE_VFC_FILTER_E = 9,
+ RESOURCE_ILT_E = 10,
+ RESOURCE_CQS_E = 11,
+ RESOURCE_GFT_PROFILES_E = 12,
+ RESOURCE_NUM_TC_E = 13,
+ RESOURCE_NUM_RSS_ENGINES_E = 14,
+ RESOURCE_LL2_QUEUE_E = 15,
+ RESOURCE_RDMA_STATS_QUEUE_E = 16,
+ RESOURCE_MAX_NUM,
+ RESOURCE_NUM_INVALID = 0xFFFFFFFF
+};
+
+/* Resource ID is to be filled by the driver in the MB request
+ * Size, offset & flags to be filled by the MFW in the MB response
+ */
+struct resource_info {
+ enum resource_id_enum res_id;
+ u32 size; /* number of allocated resources */
+ u32 offset; /* Offset of the 1st resource */
+ u32 vf_size;
+ u32 vf_offset;
+ u32 flags;
+#define RESOURCE_ELEMENT_STRICT (1 << 0)
+};
+
union drv_union_data {
u32 ver_str[MCP_DRV_VER_STR_SIZE_DWORD];
struct mcp_mac wol_mac;
@@ -8543,9 +8578,9 @@ union drv_union_data {
struct drv_version_stc drv_version;
struct lan_stats_stc lan_stats;
- u64 reserved_stats[11];
struct ocbb_data_stc ocbb_info;
struct temperature_status_stc temp_info;
+ struct resource_info resource;
struct bist_nvm_image_att nvm_image_att;
struct mdump_config_stc mdump_config;
};
@@ -8561,9 +8596,19 @@ struct public_drv_mb {
#define DRV_MSG_CODE_INIT_PHY 0x22000000
#define DRV_MSG_CODE_LINK_RESET 0x23000000
#define DRV_MSG_CODE_SET_DCBX 0x25000000
+#define DRV_MSG_CODE_OV_UPDATE_CURR_CFG 0x26000000
+#define DRV_MSG_CODE_OV_UPDATE_BUS_NUM 0x27000000
+#define DRV_MSG_CODE_OV_UPDATE_BOOT_PROGRESS 0x28000000
+#define DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER 0x29000000
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE 0x31000000
+#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000
+#define DRV_MSG_CODE_OV_UPDATE_MTU 0x33000000
+#define DRV_MSG_CODE_OV_UPDATE_WOL 0x38000000
+#define DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE 0x39000000
#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000
#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
+#define DRV_MSG_GET_RESOURCE_ALLOC_MSG 0x34000000
#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
#define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000
#define DRV_MSG_CODE_NVM_GET_FILE_ATT 0x00030000
@@ -8571,6 +8616,13 @@ struct public_drv_mb {
#define DRV_MSG_CODE_MCP_RESET 0x00090000
#define DRV_MSG_CODE_SET_VERSION 0x000f0000
#define DRV_MSG_CODE_MCP_HALT 0x00100000
+#define DRV_MSG_CODE_SET_VMAC 0x00110000
+#define DRV_MSG_CODE_GET_VMAC 0x00120000
+#define DRV_MSG_CODE_VMAC_TYPE_SHIFT 4
+#define DRV_MSG_CODE_VMAC_TYPE_MASK 0x30
+#define DRV_MSG_CODE_VMAC_TYPE_MAC 1
+#define DRV_MSG_CODE_VMAC_TYPE_WWNN 2
+#define DRV_MSG_CODE_VMAC_TYPE_WWPN 3
#define DRV_MSG_CODE_GET_STATS 0x00130000
#define DRV_MSG_CODE_STATS_TYPE_LAN 1
@@ -8582,11 +8634,16 @@ struct public_drv_mb {
#define DRV_MSG_CODE_BIST_TEST 0x001e0000
#define DRV_MSG_CODE_SET_LED_MODE 0x00200000
+#define DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL 0x002b0000
+#define DRV_MSG_CODE_OS_WOL 0x002e0000
#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 drv_mb_param;
-#define DRV_MB_PARAM_UNLOAD_WOL_MCP 0x00000001
+#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
#define DRV_MB_PARAM_DCBX_NOTIFY_MASK 0x000000FF
#define DRV_MB_PARAM_DCBX_NOTIFY_SHIFT 3
@@ -8599,13 +8656,59 @@ struct public_drv_mb {
#define DRV_MB_PARAM_LLDP_SEND_MASK 0x00000001
#define DRV_MB_PARAM_LLDP_SEND_SHIFT 0
+#define DRV_MB_PARAM_OV_CURR_CFG_SHIFT 0
+#define DRV_MB_PARAM_OV_CURR_CFG_MASK 0x0000000F
+#define DRV_MB_PARAM_OV_CURR_CFG_NONE 0
+#define DRV_MB_PARAM_OV_CURR_CFG_OS 1
+#define DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC 2
+#define DRV_MB_PARAM_OV_CURR_CFG_OTHER 3
+
+#define DRV_MB_PARAM_OV_STORM_FW_VER_SHIFT 0
+#define DRV_MB_PARAM_OV_STORM_FW_VER_MASK 0xFFFFFFFF
+#define DRV_MB_PARAM_OV_STORM_FW_VER_MAJOR_MASK 0xFF000000
+#define DRV_MB_PARAM_OV_STORM_FW_VER_MINOR_MASK 0x00FF0000
+#define DRV_MB_PARAM_OV_STORM_FW_VER_BUILD_MASK 0x0000FF00
+#define DRV_MB_PARAM_OV_STORM_FW_VER_DROP_MASK 0x000000FF
+
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_SHIFT 0
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_MASK 0xF
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_UNKNOWN 0x1
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED 0x2
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_LOADING 0x3
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED 0x4
+#define DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE 0x5
+
+#define DRV_MB_PARAM_OV_MTU_SIZE_SHIFT 0
+#define DRV_MB_PARAM_OV_MTU_SIZE_MASK 0xFFFFFFFF
+
+#define DRV_MB_PARAM_WOL_MASK (DRV_MB_PARAM_WOL_DEFAULT | \
+ DRV_MB_PARAM_WOL_DISABLED | \
+ DRV_MB_PARAM_WOL_ENABLED)
+#define DRV_MB_PARAM_WOL_DEFAULT DRV_MB_PARAM_UNLOAD_WOL_MCP
+#define DRV_MB_PARAM_WOL_DISABLED DRV_MB_PARAM_UNLOAD_WOL_DISABLED
+#define DRV_MB_PARAM_WOL_ENABLED DRV_MB_PARAM_UNLOAD_WOL_ENABLED
+
+#define DRV_MB_PARAM_ESWITCH_MODE_MASK (DRV_MB_PARAM_ESWITCH_MODE_NONE | \
+ DRV_MB_PARAM_ESWITCH_MODE_VEB | \
+ DRV_MB_PARAM_ESWITCH_MODE_VEPA)
+#define DRV_MB_PARAM_ESWITCH_MODE_NONE 0x0
+#define DRV_MB_PARAM_ESWITCH_MODE_VEB 0x1
+#define DRV_MB_PARAM_ESWITCH_MODE_VEPA 0x2
#define DRV_MB_PARAM_SET_LED_MODE_OPER 0x0
#define DRV_MB_PARAM_SET_LED_MODE_ON 0x1
#define DRV_MB_PARAM_SET_LED_MODE_OFF 0x2
+ /* Resource Allocation params - Driver version support */
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK 0xFFFF0000
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT 16
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK 0x0000FFFF
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT 0
+
#define DRV_MB_PARAM_BIST_REGISTER_TEST 1
#define DRV_MB_PARAM_BIST_CLOCK_TEST 2
+#define DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES 3
+#define DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX 4
#define DRV_MB_PARAM_BIST_RC_UNKNOWN 0
#define DRV_MB_PARAM_BIST_RC_PASSED 1
@@ -8614,6 +8717,8 @@ struct public_drv_mb {
#define DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT 0
#define DRV_MB_PARAM_BIST_TEST_INDEX_MASK 0x000000FF
+#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT 8
+#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_MASK 0x0000FF00
u32 fw_mb_header;
#define FW_MSG_CODE_MASK 0xffff0000
@@ -8628,15 +8733,27 @@ struct public_drv_mb {
#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_RESOURCE_ALLOC_OK 0x34000000
+#define FW_MSG_CODE_RESOURCE_ALLOC_UNKNOWN 0x35000000
+#define FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED 0x36000000
#define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE 0xb0010000
#define FW_MSG_CODE_NVM_OK 0x00010000
#define FW_MSG_CODE_OK 0x00160000
+#define FW_MSG_CODE_OS_WOL_SUPPORTED 0x00800000
+#define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED 0x00810000
+
#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 fw_mb_param;
+ /* get pf rdma protocol command responce */
+#define FW_MB_PARAM_GET_PF_RDMA_NONE 0x0
+#define FW_MB_PARAM_GET_PF_RDMA_ROCE 0x1
+#define FW_MB_PARAM_GET_PF_RDMA_IWARP 0x2
+#define FW_MB_PARAM_GET_PF_RDMA_BOTH 0x3
+
u32 drv_pulse_mb;
#define DRV_PULSE_SEQ_MASK 0x00007fff
#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c
index 2adedc6fb6cf..bb74e1c10ffe 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -3030,6 +3030,31 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
}
}
}
+
+ /* There's a possibility the igu_sb_cnt_iov doesn't properly reflect
+ * the number of VF SBs [especially for first VF on engine, as we can't
+ * diffrentiate between empty entries and its entries].
+ * Since we don't really support more SBs than VFs today, prevent any
+ * such configuration by sanitizing the number of SBs to equal the
+ * number of VFs.
+ */
+ if (IS_PF_SRIOV(p_hwfn)) {
+ u16 total_vfs = p_hwfn->cdev->p_iov_info->total_vfs;
+
+ if (total_vfs < p_igu_info->free_blks) {
+ DP_VERBOSE(p_hwfn,
+ (NETIF_MSG_INTR | QED_MSG_IOV),
+ "Limiting number of SBs for IOV - %04x --> %04x\n",
+ p_igu_info->free_blks,
+ p_hwfn->cdev->p_iov_info->total_vfs);
+ p_igu_info->free_blks = total_vfs;
+ } else if (total_vfs > p_igu_info->free_blks) {
+ DP_NOTICE(p_hwfn,
+ "IGU has only %04x SBs for VFs while the device has %04x VFs\n",
+ p_igu_info->free_blks, total_vfs);
+ return -EINVAL;
+ }
+ }
p_igu_info->igu_sb_cnt_iov = p_igu_info->free_blks;
DP_VERBOSE(
@@ -3163,7 +3188,12 @@ u16 qed_int_queue_id_from_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id)
return sb_id - p_info->igu_base_sb;
} else if ((sb_id >= p_info->igu_base_sb_iov) &&
(sb_id < p_info->igu_base_sb_iov + p_info->igu_sb_cnt_iov)) {
- return sb_id - p_info->igu_base_sb_iov + p_info->igu_sb_cnt;
+ /* We want the first VF queue to be adjacent to the
+ * last PF queue. Since L2 queues can be partial to
+ * SBs, we'll use the feature instead.
+ */
+ return sb_id - p_info->igu_base_sb_iov +
+ FEAT_NUM(p_hwfn, QED_PF_L2_QUE);
} else {
DP_NOTICE(p_hwfn, "SB %d not in range for function\n", sb_id);
return 0;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
new file mode 100644
index 000000000000..00efb1c4c57e
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
@@ -0,0 +1,1277 @@
+/* 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/log2.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/errno.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/qed/qed_iscsi_if.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_iscsi.h"
+#include "qed_ll2.h"
+#include "qed_mcp.h"
+#include "qed_sp.h"
+#include "qed_sriov.h"
+#include "qed_reg_addr.h"
+
+struct qed_iscsi_conn {
+ struct list_head list_entry;
+ bool free_on_delete;
+
+ u16 conn_id;
+ u32 icid;
+ u32 fw_cid;
+
+ u8 layer_code;
+ u8 offl_flags;
+ u8 connect_mode;
+ u32 initial_ack;
+ dma_addr_t sq_pbl_addr;
+ struct qed_chain r2tq;
+ struct qed_chain xhq;
+ struct qed_chain uhq;
+
+ struct tcp_upload_params *tcp_upload_params_virt_addr;
+ dma_addr_t tcp_upload_params_phys_addr;
+ struct scsi_terminate_extra_params *queue_cnts_virt_addr;
+ dma_addr_t queue_cnts_phys_addr;
+ dma_addr_t syn_phy_addr;
+
+ u16 syn_ip_payload_length;
+ u8 local_mac[6];
+ u8 remote_mac[6];
+ u16 vlan_id;
+ u8 tcp_flags;
+ u8 ip_version;
+ u32 remote_ip[4];
+ u32 local_ip[4];
+ u8 ka_max_probe_cnt;
+ u8 dup_ack_theshold;
+ u32 rcv_next;
+ u32 snd_una;
+ u32 snd_next;
+ u32 snd_max;
+ u32 snd_wnd;
+ u32 rcv_wnd;
+ u32 snd_wl1;
+ u32 cwnd;
+ u32 ss_thresh;
+ u16 srtt;
+ u16 rtt_var;
+ u32 ts_time;
+ u32 ts_recent;
+ u32 ts_recent_age;
+ u32 total_rt;
+ u32 ka_timeout_delta;
+ u32 rt_timeout_delta;
+ u8 dup_ack_cnt;
+ u8 snd_wnd_probe_cnt;
+ u8 ka_probe_cnt;
+ u8 rt_cnt;
+ u32 flow_label;
+ u32 ka_timeout;
+ u32 ka_interval;
+ u32 max_rt_time;
+ u32 initial_rcv_wnd;
+ u8 ttl;
+ u8 tos_or_tc;
+ u16 remote_port;
+ u16 local_port;
+ u16 mss;
+ u8 snd_wnd_scale;
+ u8 rcv_wnd_scale;
+ u32 ts_ticks_per_second;
+ u16 da_timeout_value;
+ u8 ack_frequency;
+
+ u8 update_flag;
+ u8 default_cq;
+ u32 max_seq_size;
+ u32 max_recv_pdu_length;
+ u32 max_send_pdu_length;
+ u32 first_seq_length;
+ u32 exp_stat_sn;
+ u32 stat_sn;
+ u16 physical_q0;
+ u16 physical_q1;
+ u8 abortive_dsconnect;
+};
+
+static int
+qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr,
+ void *event_context, iscsi_event_cb_t async_event_cb)
+{
+ struct iscsi_init_ramrod_params *p_ramrod = NULL;
+ struct scsi_init_func_queues *p_queue = NULL;
+ struct qed_iscsi_pf_params *p_params = NULL;
+ struct iscsi_spe_func_init *p_init = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = 0;
+ u32 dval;
+ u16 val;
+ u8 i;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = qed_spq_get_cid(p_hwfn);
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_INIT_FUNC,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_init;
+ p_init = &p_ramrod->iscsi_init_spe;
+ p_params = &p_hwfn->pf_params.iscsi_pf_params;
+ p_queue = &p_init->q_params;
+
+ SET_FIELD(p_init->hdr.flags,
+ ISCSI_SLOW_PATH_HDR_LAYER_CODE, ISCSI_SLOW_PATH_LAYER_CODE);
+ p_init->hdr.op_code = ISCSI_RAMROD_CMD_ID_INIT_FUNC;
+
+ val = p_params->half_way_close_timeout;
+ p_init->half_way_close_timeout = cpu_to_le16(val);
+ p_init->num_sq_pages_in_ring = p_params->num_sq_pages_in_ring;
+ p_init->num_r2tq_pages_in_ring = p_params->num_r2tq_pages_in_ring;
+ p_init->num_uhq_pages_in_ring = p_params->num_uhq_pages_in_ring;
+ p_init->func_params.log_page_size = p_params->log_page_size;
+ val = p_params->num_tasks;
+ p_init->func_params.num_tasks = cpu_to_le16(val);
+ p_init->debug_mode.flags = p_params->debug_mode;
+
+ DMA_REGPAIR_LE(p_queue->glbl_q_params_addr,
+ p_params->glbl_q_params_addr);
+
+ val = p_params->cq_num_entries;
+ p_queue->cq_num_entries = cpu_to_le16(val);
+ val = p_params->cmdq_num_entries;
+ p_queue->cmdq_num_entries = cpu_to_le16(val);
+ p_queue->num_queues = p_params->num_queues;
+ dval = (u8)p_hwfn->hw_info.resc_start[QED_CMDQS_CQS];
+ p_queue->queue_relative_offset = (u8)dval;
+ p_queue->cq_sb_pi = p_params->gl_rq_pi;
+ p_queue->cmdq_sb_pi = p_params->gl_cmd_pi;
+
+ for (i = 0; i < p_params->num_queues; i++) {
+ val = p_hwfn->sbs_info[i]->igu_sb_id;
+ p_queue->cq_cmdq_sb_num_arr[i] = cpu_to_le16(val);
+ }
+
+ p_queue->bdq_resource_id = ISCSI_BDQ_ID(p_hwfn->port_id);
+
+ DMA_REGPAIR_LE(p_queue->bdq_pbl_base_address[BDQ_ID_RQ],
+ p_params->bdq_pbl_base_addr[BDQ_ID_RQ]);
+ p_queue->bdq_pbl_num_entries[BDQ_ID_RQ] =
+ p_params->bdq_pbl_num_entries[BDQ_ID_RQ];
+ val = p_params->bdq_xoff_threshold[BDQ_ID_RQ];
+ p_queue->bdq_xoff_threshold[BDQ_ID_RQ] = cpu_to_le16(val);
+ val = p_params->bdq_xon_threshold[BDQ_ID_RQ];
+ p_queue->bdq_xon_threshold[BDQ_ID_RQ] = cpu_to_le16(val);
+
+ DMA_REGPAIR_LE(p_queue->bdq_pbl_base_address[BDQ_ID_IMM_DATA],
+ p_params->bdq_pbl_base_addr[BDQ_ID_IMM_DATA]);
+ p_queue->bdq_pbl_num_entries[BDQ_ID_IMM_DATA] =
+ p_params->bdq_pbl_num_entries[BDQ_ID_IMM_DATA];
+ val = p_params->bdq_xoff_threshold[BDQ_ID_IMM_DATA];
+ p_queue->bdq_xoff_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(val);
+ val = p_params->bdq_xon_threshold[BDQ_ID_IMM_DATA];
+ p_queue->bdq_xon_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(val);
+ val = p_params->rq_buffer_size;
+ p_queue->rq_buffer_size = cpu_to_le16(val);
+ if (p_params->is_target) {
+ SET_FIELD(p_queue->q_validity,
+ SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
+ if (p_queue->bdq_pbl_num_entries[BDQ_ID_IMM_DATA])
+ SET_FIELD(p_queue->q_validity,
+ SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID, 1);
+ SET_FIELD(p_queue->q_validity,
+ SCSI_INIT_FUNC_QUEUES_CMD_VALID, 1);
+ } else {
+ SET_FIELD(p_queue->q_validity,
+ SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
+ }
+ p_ramrod->tcp_init.two_msl_timer = cpu_to_le32(p_params->two_msl_timer);
+ val = p_params->tx_sws_timer;
+ p_ramrod->tcp_init.tx_sws_timer = cpu_to_le16(val);
+ p_ramrod->tcp_init.maxfinrt = p_params->max_fin_rt;
+
+ p_hwfn->p_iscsi_info->event_context = event_context;
+ p_hwfn->p_iscsi_info->event_cb = async_event_cb;
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_iscsi_conn_offload(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_spe_conn_offload *p_ramrod = NULL;
+ struct tcp_offload_params_opt2 *p_tcp2 = NULL;
+ struct tcp_offload_params *p_tcp = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ union qed_qm_pq_params pq_params;
+ u16 pq0_id = 0, pq1_id = 0;
+ dma_addr_t r2tq_pbl_addr;
+ dma_addr_t xhq_pbl_addr;
+ dma_addr_t uhq_pbl_addr;
+ int rc = 0;
+ u32 dval;
+ u16 wval;
+ u8 i;
+ u16 *p;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = p_conn->icid;
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_conn_offload;
+
+ /* Transmission PQ is the first of the PF */
+ memset(&pq_params, 0, sizeof(pq_params));
+ pq0_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ISCSI, &pq_params);
+ p_conn->physical_q0 = cpu_to_le16(pq0_id);
+ p_ramrod->iscsi.physical_q0 = cpu_to_le16(pq0_id);
+
+ /* iSCSI Pure-ACK PQ */
+ pq_params.iscsi.q_idx = 1;
+ pq1_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ISCSI, &pq_params);
+ p_conn->physical_q1 = cpu_to_le16(pq1_id);
+ p_ramrod->iscsi.physical_q1 = cpu_to_le16(pq1_id);
+
+ p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN;
+ SET_FIELD(p_ramrod->hdr.flags, ISCSI_SLOW_PATH_HDR_LAYER_CODE,
+ p_conn->layer_code);
+
+ p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
+ p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
+
+ DMA_REGPAIR_LE(p_ramrod->iscsi.sq_pbl_addr, p_conn->sq_pbl_addr);
+
+ r2tq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->r2tq);
+ DMA_REGPAIR_LE(p_ramrod->iscsi.r2tq_pbl_addr, r2tq_pbl_addr);
+
+ xhq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->xhq);
+ DMA_REGPAIR_LE(p_ramrod->iscsi.xhq_pbl_addr, xhq_pbl_addr);
+
+ uhq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->uhq);
+ DMA_REGPAIR_LE(p_ramrod->iscsi.uhq_pbl_addr, uhq_pbl_addr);
+
+ p_ramrod->iscsi.initial_ack = cpu_to_le32(p_conn->initial_ack);
+ p_ramrod->iscsi.flags = p_conn->offl_flags;
+ p_ramrod->iscsi.default_cq = p_conn->default_cq;
+ p_ramrod->iscsi.stat_sn = cpu_to_le32(p_conn->stat_sn);
+
+ if (!GET_FIELD(p_ramrod->iscsi.flags,
+ ISCSI_CONN_OFFLOAD_PARAMS_TCP_ON_CHIP_1B)) {
+ p_tcp = &p_ramrod->tcp;
+
+ p = (u16 *)p_conn->local_mac;
+ p_tcp->local_mac_addr_hi = swab16(get_unaligned(p));
+ p_tcp->local_mac_addr_mid = swab16(get_unaligned(p + 1));
+ p_tcp->local_mac_addr_lo = swab16(get_unaligned(p + 2));
+
+ p = (u16 *)p_conn->remote_mac;
+ p_tcp->remote_mac_addr_hi = swab16(get_unaligned(p));
+ p_tcp->remote_mac_addr_mid = swab16(get_unaligned(p + 1));
+ p_tcp->remote_mac_addr_lo = swab16(get_unaligned(p + 2));
+
+ p_tcp->vlan_id = cpu_to_le16(p_conn->vlan_id);
+
+ p_tcp->flags = p_conn->tcp_flags;
+ p_tcp->ip_version = p_conn->ip_version;
+ for (i = 0; i < 4; i++) {
+ dval = p_conn->remote_ip[i];
+ p_tcp->remote_ip[i] = cpu_to_le32(dval);
+ dval = p_conn->local_ip[i];
+ p_tcp->local_ip[i] = cpu_to_le32(dval);
+ }
+ p_tcp->ka_max_probe_cnt = p_conn->ka_max_probe_cnt;
+ p_tcp->dup_ack_theshold = p_conn->dup_ack_theshold;
+
+ p_tcp->rcv_next = cpu_to_le32(p_conn->rcv_next);
+ p_tcp->snd_una = cpu_to_le32(p_conn->snd_una);
+ p_tcp->snd_next = cpu_to_le32(p_conn->snd_next);
+ p_tcp->snd_max = cpu_to_le32(p_conn->snd_max);
+ p_tcp->snd_wnd = cpu_to_le32(p_conn->snd_wnd);
+ p_tcp->rcv_wnd = cpu_to_le32(p_conn->rcv_wnd);
+ p_tcp->snd_wl1 = cpu_to_le32(p_conn->snd_wl1);
+ p_tcp->cwnd = cpu_to_le32(p_conn->cwnd);
+ p_tcp->ss_thresh = cpu_to_le32(p_conn->ss_thresh);
+ p_tcp->srtt = cpu_to_le16(p_conn->srtt);
+ p_tcp->rtt_var = cpu_to_le16(p_conn->rtt_var);
+ p_tcp->ts_time = cpu_to_le32(p_conn->ts_time);
+ p_tcp->ts_recent = cpu_to_le32(p_conn->ts_recent);
+ p_tcp->ts_recent_age = cpu_to_le32(p_conn->ts_recent_age);
+ p_tcp->total_rt = cpu_to_le32(p_conn->total_rt);
+ dval = p_conn->ka_timeout_delta;
+ p_tcp->ka_timeout_delta = cpu_to_le32(dval);
+ dval = p_conn->rt_timeout_delta;
+ p_tcp->rt_timeout_delta = cpu_to_le32(dval);
+ p_tcp->dup_ack_cnt = p_conn->dup_ack_cnt;
+ p_tcp->snd_wnd_probe_cnt = p_conn->snd_wnd_probe_cnt;
+ p_tcp->ka_probe_cnt = p_conn->ka_probe_cnt;
+ p_tcp->rt_cnt = p_conn->rt_cnt;
+ p_tcp->flow_label = cpu_to_le32(p_conn->flow_label);
+ p_tcp->ka_timeout = cpu_to_le32(p_conn->ka_timeout);
+ p_tcp->ka_interval = cpu_to_le32(p_conn->ka_interval);
+ p_tcp->max_rt_time = cpu_to_le32(p_conn->max_rt_time);
+ dval = p_conn->initial_rcv_wnd;
+ p_tcp->initial_rcv_wnd = cpu_to_le32(dval);
+ p_tcp->ttl = p_conn->ttl;
+ p_tcp->tos_or_tc = p_conn->tos_or_tc;
+ p_tcp->remote_port = cpu_to_le16(p_conn->remote_port);
+ p_tcp->local_port = cpu_to_le16(p_conn->local_port);
+ p_tcp->mss = cpu_to_le16(p_conn->mss);
+ p_tcp->snd_wnd_scale = p_conn->snd_wnd_scale;
+ p_tcp->rcv_wnd_scale = p_conn->rcv_wnd_scale;
+ dval = p_conn->ts_ticks_per_second;
+ p_tcp->ts_ticks_per_second = cpu_to_le32(dval);
+ wval = p_conn->da_timeout_value;
+ p_tcp->da_timeout_value = cpu_to_le16(wval);
+ p_tcp->ack_frequency = p_conn->ack_frequency;
+ p_tcp->connect_mode = p_conn->connect_mode;
+ } else {
+ p_tcp2 =
+ &((struct iscsi_spe_conn_offload_option2 *)p_ramrod)->tcp;
+
+ p = (u16 *)p_conn->local_mac;
+ p_tcp2->local_mac_addr_hi = swab16(get_unaligned(p));
+ p_tcp2->local_mac_addr_mid = swab16(get_unaligned(p + 1));
+ p_tcp2->local_mac_addr_lo = swab16(get_unaligned(p + 2));
+
+ p = (u16 *)p_conn->remote_mac;
+ p_tcp2->remote_mac_addr_hi = swab16(get_unaligned(p));
+ p_tcp2->remote_mac_addr_mid = swab16(get_unaligned(p + 1));
+ p_tcp2->remote_mac_addr_lo = swab16(get_unaligned(p + 2));
+
+ p_tcp2->vlan_id = cpu_to_le16(p_conn->vlan_id);
+ p_tcp2->flags = p_conn->tcp_flags;
+
+ p_tcp2->ip_version = p_conn->ip_version;
+ for (i = 0; i < 4; i++) {
+ dval = p_conn->remote_ip[i];
+ p_tcp2->remote_ip[i] = cpu_to_le32(dval);
+ dval = p_conn->local_ip[i];
+ p_tcp2->local_ip[i] = cpu_to_le32(dval);
+ }
+
+ p_tcp2->flow_label = cpu_to_le32(p_conn->flow_label);
+ p_tcp2->ttl = p_conn->ttl;
+ p_tcp2->tos_or_tc = p_conn->tos_or_tc;
+ p_tcp2->remote_port = cpu_to_le16(p_conn->remote_port);
+ p_tcp2->local_port = cpu_to_le16(p_conn->local_port);
+ p_tcp2->mss = cpu_to_le16(p_conn->mss);
+ p_tcp2->rcv_wnd_scale = p_conn->rcv_wnd_scale;
+ p_tcp2->connect_mode = p_conn->connect_mode;
+ wval = p_conn->syn_ip_payload_length;
+ p_tcp2->syn_ip_payload_length = cpu_to_le16(wval);
+ p_tcp2->syn_phy_addr_lo = DMA_LO_LE(p_conn->syn_phy_addr);
+ p_tcp2->syn_phy_addr_hi = DMA_HI_LE(p_conn->syn_phy_addr);
+ }
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_conn_update_ramrod_params *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = -EINVAL;
+ u32 dval;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = p_conn->icid;
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_UPDATE_CONN,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_conn_update;
+ p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_UPDATE_CONN;
+ SET_FIELD(p_ramrod->hdr.flags,
+ ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
+
+ p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
+ p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
+ p_ramrod->flags = p_conn->update_flag;
+ p_ramrod->max_seq_size = cpu_to_le32(p_conn->max_seq_size);
+ dval = p_conn->max_recv_pdu_length;
+ p_ramrod->max_recv_pdu_length = cpu_to_le32(dval);
+ dval = p_conn->max_send_pdu_length;
+ p_ramrod->max_send_pdu_length = cpu_to_le32(dval);
+ dval = p_conn->first_seq_length;
+ p_ramrod->first_seq_length = cpu_to_le32(dval);
+ p_ramrod->exp_stat_sn = cpu_to_le32(p_conn->exp_stat_sn);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_spe_conn_termination *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = -EINVAL;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = p_conn->icid;
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_TERMINATION_CONN,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_conn_terminate;
+ p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_TERMINATION_CONN;
+ SET_FIELD(p_ramrod->hdr.flags,
+ ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
+
+ p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
+ p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
+ p_ramrod->abortive = p_conn->abortive_dsconnect;
+
+ DMA_REGPAIR_LE(p_ramrod->query_params_addr,
+ p_conn->tcp_upload_params_phys_addr);
+ DMA_REGPAIR_LE(p_ramrod->queue_cnts_addr, p_conn->queue_cnts_phys_addr);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_iscsi_conn_clear_sq(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_slow_path_hdr *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = -EINVAL;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = p_conn->icid;
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_CLEAR_SQ,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_empty;
+ p_ramrod->op_code = ISCSI_RAMROD_CMD_ID_CLEAR_SQ;
+ SET_FIELD(p_ramrod->flags,
+ ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static int qed_sp_iscsi_func_stop(struct qed_hwfn *p_hwfn,
+ enum spq_mode comp_mode,
+ struct qed_spq_comp_cb *p_comp_addr)
+{
+ struct iscsi_spe_func_dstry *p_ramrod = NULL;
+ struct qed_spq_entry *p_ent = NULL;
+ struct qed_sp_init_data init_data;
+ int rc = 0;
+
+ /* Get SPQ entry */
+ memset(&init_data, 0, sizeof(init_data));
+ init_data.cid = qed_spq_get_cid(p_hwfn);
+ init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+ init_data.comp_mode = comp_mode;
+ init_data.p_comp_data = p_comp_addr;
+
+ rc = qed_sp_init_request(p_hwfn, &p_ent,
+ ISCSI_RAMROD_CMD_ID_DESTROY_FUNC,
+ PROTOCOLID_ISCSI, &init_data);
+ if (rc)
+ return rc;
+
+ p_ramrod = &p_ent->ramrod.iscsi_destroy;
+ p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_DESTROY_FUNC;
+
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+static void __iomem *qed_iscsi_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid)
+{
+ return (u8 __iomem *)p_hwfn->doorbells +
+ qed_db_addr(cid, DQ_DEMS_LEGACY);
+}
+
+static void __iomem *qed_iscsi_get_primary_bdq_prod(struct qed_hwfn *p_hwfn,
+ u8 bdq_id)
+{
+ u8 bdq_function_id = ISCSI_BDQ_ID(p_hwfn->port_id);
+
+ return (u8 __iomem *)p_hwfn->regview + GTT_BAR0_MAP_REG_MSDM_RAM +
+ MSTORM_SCSI_BDQ_EXT_PROD_OFFSET(bdq_function_id,
+ bdq_id);
+}
+
+static void __iomem *qed_iscsi_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn,
+ u8 bdq_id)
+{
+ u8 bdq_function_id = ISCSI_BDQ_ID(p_hwfn->port_id);
+
+ return (u8 __iomem *)p_hwfn->regview + GTT_BAR0_MAP_REG_TSDM_RAM +
+ TSTORM_SCSI_BDQ_EXT_PROD_OFFSET(bdq_function_id,
+ bdq_id);
+}
+
+static int qed_iscsi_setup_connection(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn)
+{
+ if (!p_conn->queue_cnts_virt_addr)
+ goto nomem;
+ memset(p_conn->queue_cnts_virt_addr, 0,
+ sizeof(*p_conn->queue_cnts_virt_addr));
+
+ if (!p_conn->tcp_upload_params_virt_addr)
+ goto nomem;
+ memset(p_conn->tcp_upload_params_virt_addr, 0,
+ sizeof(*p_conn->tcp_upload_params_virt_addr));
+
+ if (!p_conn->r2tq.p_virt_addr)
+ goto nomem;
+ qed_chain_pbl_zero_mem(&p_conn->r2tq);
+
+ if (!p_conn->uhq.p_virt_addr)
+ goto nomem;
+ qed_chain_pbl_zero_mem(&p_conn->uhq);
+
+ if (!p_conn->xhq.p_virt_addr)
+ goto nomem;
+ qed_chain_pbl_zero_mem(&p_conn->xhq);
+
+ return 0;
+nomem:
+ return -ENOMEM;
+}
+
+static int qed_iscsi_allocate_connection(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn **p_out_conn)
+{
+ u16 uhq_num_elements = 0, xhq_num_elements = 0, r2tq_num_elements = 0;
+ struct scsi_terminate_extra_params *p_q_cnts = NULL;
+ struct qed_iscsi_pf_params *p_params = NULL;
+ struct tcp_upload_params *p_tcp = NULL;
+ struct qed_iscsi_conn *p_conn = NULL;
+ int rc = 0;
+
+ /* Try finding a free connection that can be used */
+ spin_lock_bh(&p_hwfn->p_iscsi_info->lock);
+ if (!list_empty(&p_hwfn->p_iscsi_info->free_list))
+ p_conn = list_first_entry(&p_hwfn->p_iscsi_info->free_list,
+ struct qed_iscsi_conn, list_entry);
+ if (p_conn) {
+ list_del(&p_conn->list_entry);
+ spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
+ *p_out_conn = p_conn;
+ return 0;
+ }
+ spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
+
+ /* Need to allocate a new connection */
+ p_params = &p_hwfn->pf_params.iscsi_pf_params;
+
+ p_conn = kzalloc(sizeof(*p_conn), GFP_KERNEL);
+ if (!p_conn)
+ return -ENOMEM;
+
+ p_q_cnts = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(*p_q_cnts),
+ &p_conn->queue_cnts_phys_addr,
+ GFP_KERNEL);
+ if (!p_q_cnts)
+ goto nomem_queue_cnts_param;
+ p_conn->queue_cnts_virt_addr = p_q_cnts;
+
+ p_tcp = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(*p_tcp),
+ &p_conn->tcp_upload_params_phys_addr,
+ GFP_KERNEL);
+ if (!p_tcp)
+ goto nomem_upload_param;
+ p_conn->tcp_upload_params_virt_addr = p_tcp;
+
+ r2tq_num_elements = p_params->num_r2tq_pages_in_ring *
+ QED_CHAIN_PAGE_SIZE / 0x80;
+ rc = qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_CONSUME_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ QED_CHAIN_CNT_TYPE_U16,
+ r2tq_num_elements, 0x80, &p_conn->r2tq);
+ if (rc)
+ goto nomem_r2tq;
+
+ uhq_num_elements = p_params->num_uhq_pages_in_ring *
+ QED_CHAIN_PAGE_SIZE / sizeof(struct iscsi_uhqe);
+ rc = qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_CONSUME_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ QED_CHAIN_CNT_TYPE_U16,
+ uhq_num_elements,
+ sizeof(struct iscsi_uhqe), &p_conn->uhq);
+ if (rc)
+ goto nomem_uhq;
+
+ xhq_num_elements = uhq_num_elements;
+ rc = qed_chain_alloc(p_hwfn->cdev,
+ QED_CHAIN_USE_TO_CONSUME_PRODUCE,
+ QED_CHAIN_MODE_PBL,
+ QED_CHAIN_CNT_TYPE_U16,
+ xhq_num_elements,
+ sizeof(struct iscsi_xhqe), &p_conn->xhq);
+ if (rc)
+ goto nomem;
+
+ p_conn->free_on_delete = true;
+ *p_out_conn = p_conn;
+ return 0;
+
+nomem:
+ qed_chain_free(p_hwfn->cdev, &p_conn->uhq);
+nomem_uhq:
+ qed_chain_free(p_hwfn->cdev, &p_conn->r2tq);
+nomem_r2tq:
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(struct tcp_upload_params),
+ p_conn->tcp_upload_params_virt_addr,
+ p_conn->tcp_upload_params_phys_addr);
+nomem_upload_param:
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ sizeof(struct scsi_terminate_extra_params),
+ p_conn->queue_cnts_virt_addr,
+ p_conn->queue_cnts_phys_addr);
+nomem_queue_cnts_param:
+ kfree(p_conn);
+
+ return -ENOMEM;
+}
+
+static int qed_iscsi_acquire_connection(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_in_conn,
+ struct qed_iscsi_conn **p_out_conn)
+{
+ struct qed_iscsi_conn *p_conn = NULL;
+ int rc = 0;
+ u32 icid;
+
+ spin_lock_bh(&p_hwfn->p_iscsi_info->lock);
+ rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ISCSI, &icid);
+ spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
+ if (rc)
+ return rc;
+
+ /* Use input connection or allocate a new one */
+ if (p_in_conn)
+ p_conn = p_in_conn;
+ else
+ rc = qed_iscsi_allocate_connection(p_hwfn, &p_conn);
+
+ if (!rc)
+ rc = qed_iscsi_setup_connection(p_hwfn, p_conn);
+
+ if (rc) {
+ spin_lock_bh(&p_hwfn->p_iscsi_info->lock);
+ qed_cxt_release_cid(p_hwfn, icid);
+ spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
+ return rc;
+ }
+
+ p_conn->icid = icid;
+ p_conn->conn_id = (u16)icid;
+ p_conn->fw_cid = (p_hwfn->hw_info.opaque_fid << 16) | icid;
+
+ *p_out_conn = p_conn;
+
+ return rc;
+}
+
+static void qed_iscsi_release_connection(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_conn *p_conn)
+{
+ spin_lock_bh(&p_hwfn->p_iscsi_info->lock);
+ list_add_tail(&p_conn->list_entry, &p_hwfn->p_iscsi_info->free_list);
+ qed_cxt_release_cid(p_hwfn, p_conn->icid);
+ spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
+}
+
+struct qed_iscsi_info *qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_iscsi_info *p_iscsi_info;
+
+ p_iscsi_info = kzalloc(sizeof(*p_iscsi_info), GFP_KERNEL);
+ if (!p_iscsi_info)
+ return NULL;
+
+ INIT_LIST_HEAD(&p_iscsi_info->free_list);
+ return p_iscsi_info;
+}
+
+void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info)
+{
+ spin_lock_init(&p_iscsi_info->lock);
+}
+
+void qed_iscsi_free(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info)
+{
+ kfree(p_iscsi_info);
+}
+
+static void _qed_iscsi_get_tstats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct tstorm_iscsi_stats_drv tstats;
+ u32 tstats_addr;
+
+ memset(&tstats, 0, sizeof(tstats));
+ tstats_addr = BAR0_MAP_REG_TSDM_RAM +
+ TSTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats));
+
+ p_stats->iscsi_rx_bytes_cnt =
+ HILO_64_REGPAIR(tstats.iscsi_rx_bytes_cnt);
+ p_stats->iscsi_rx_packet_cnt =
+ HILO_64_REGPAIR(tstats.iscsi_rx_packet_cnt);
+ p_stats->iscsi_cmdq_threshold_cnt =
+ le32_to_cpu(tstats.iscsi_cmdq_threshold_cnt);
+ p_stats->iscsi_rq_threshold_cnt =
+ le32_to_cpu(tstats.iscsi_rq_threshold_cnt);
+ p_stats->iscsi_immq_threshold_cnt =
+ le32_to_cpu(tstats.iscsi_immq_threshold_cnt);
+}
+
+static void _qed_iscsi_get_mstats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct mstorm_iscsi_stats_drv mstats;
+ u32 mstats_addr;
+
+ memset(&mstats, 0, sizeof(mstats));
+ mstats_addr = BAR0_MAP_REG_MSDM_RAM +
+ MSTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &mstats, mstats_addr, sizeof(mstats));
+
+ p_stats->iscsi_rx_dropped_pdus_task_not_valid =
+ HILO_64_REGPAIR(mstats.iscsi_rx_dropped_pdus_task_not_valid);
+}
+
+static void _qed_iscsi_get_ustats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct ustorm_iscsi_stats_drv ustats;
+ u32 ustats_addr;
+
+ memset(&ustats, 0, sizeof(ustats));
+ ustats_addr = BAR0_MAP_REG_USDM_RAM +
+ USTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &ustats, ustats_addr, sizeof(ustats));
+
+ p_stats->iscsi_rx_data_pdu_cnt =
+ HILO_64_REGPAIR(ustats.iscsi_rx_data_pdu_cnt);
+ p_stats->iscsi_rx_r2t_pdu_cnt =
+ HILO_64_REGPAIR(ustats.iscsi_rx_r2t_pdu_cnt);
+ p_stats->iscsi_rx_total_pdu_cnt =
+ HILO_64_REGPAIR(ustats.iscsi_rx_total_pdu_cnt);
+}
+
+static void _qed_iscsi_get_xstats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct xstorm_iscsi_stats_drv xstats;
+ u32 xstats_addr;
+
+ memset(&xstats, 0, sizeof(xstats));
+ xstats_addr = BAR0_MAP_REG_XSDM_RAM +
+ XSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &xstats, xstats_addr, sizeof(xstats));
+
+ p_stats->iscsi_tx_go_to_slow_start_event_cnt =
+ HILO_64_REGPAIR(xstats.iscsi_tx_go_to_slow_start_event_cnt);
+ p_stats->iscsi_tx_fast_retransmit_event_cnt =
+ HILO_64_REGPAIR(xstats.iscsi_tx_fast_retransmit_event_cnt);
+}
+
+static void _qed_iscsi_get_ystats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct ystorm_iscsi_stats_drv ystats;
+ u32 ystats_addr;
+
+ memset(&ystats, 0, sizeof(ystats));
+ ystats_addr = BAR0_MAP_REG_YSDM_RAM +
+ YSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &ystats, ystats_addr, sizeof(ystats));
+
+ p_stats->iscsi_tx_data_pdu_cnt =
+ HILO_64_REGPAIR(ystats.iscsi_tx_data_pdu_cnt);
+ p_stats->iscsi_tx_r2t_pdu_cnt =
+ HILO_64_REGPAIR(ystats.iscsi_tx_r2t_pdu_cnt);
+ p_stats->iscsi_tx_total_pdu_cnt =
+ HILO_64_REGPAIR(ystats.iscsi_tx_total_pdu_cnt);
+}
+
+static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_iscsi_stats *p_stats)
+{
+ struct pstorm_iscsi_stats_drv pstats;
+ u32 pstats_addr;
+
+ memset(&pstats, 0, sizeof(pstats));
+ pstats_addr = BAR0_MAP_REG_PSDM_RAM +
+ PSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id);
+ qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats));
+
+ p_stats->iscsi_tx_bytes_cnt =
+ HILO_64_REGPAIR(pstats.iscsi_tx_bytes_cnt);
+ p_stats->iscsi_tx_packet_cnt =
+ HILO_64_REGPAIR(pstats.iscsi_tx_packet_cnt);
+}
+
+static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_stats *stats)
+{
+ struct qed_ptt *p_ptt;
+
+ memset(stats, 0, sizeof(*stats));
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt) {
+ DP_ERR(p_hwfn, "Failed to acquire ptt\n");
+ return -EAGAIN;
+ }
+
+ _qed_iscsi_get_tstats(p_hwfn, p_ptt, stats);
+ _qed_iscsi_get_mstats(p_hwfn, p_ptt, stats);
+ _qed_iscsi_get_ustats(p_hwfn, p_ptt, stats);
+
+ _qed_iscsi_get_xstats(p_hwfn, p_ptt, stats);
+ _qed_iscsi_get_ystats(p_hwfn, p_ptt, stats);
+ _qed_iscsi_get_pstats(p_hwfn, p_ptt, stats);
+
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return 0;
+}
+
+struct qed_hash_iscsi_con {
+ struct hlist_node node;
+ struct qed_iscsi_conn *con;
+};
+
+static int qed_fill_iscsi_dev_info(struct qed_dev *cdev,
+ struct qed_dev_iscsi_info *info)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+
+ int rc;
+
+ memset(info, 0, sizeof(*info));
+ rc = qed_fill_dev_info(cdev, &info->common);
+
+ info->primary_dbq_rq_addr =
+ qed_iscsi_get_primary_bdq_prod(hwfn, BDQ_ID_RQ);
+ info->secondary_bdq_rq_addr =
+ qed_iscsi_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);
+
+ return rc;
+}
+
+static void qed_register_iscsi_ops(struct qed_dev *cdev,
+ struct qed_iscsi_cb_ops *ops, void *cookie)
+{
+ cdev->protocol_ops.iscsi = ops;
+ cdev->ops_cookie = cookie;
+}
+
+static struct qed_hash_iscsi_con *qed_iscsi_get_hash(struct qed_dev *cdev,
+ u32 handle)
+{
+ struct qed_hash_iscsi_con *hash_con = NULL;
+
+ if (!(cdev->flags & QED_FLAG_STORAGE_STARTED))
+ return NULL;
+
+ hash_for_each_possible(cdev->connections, hash_con, node, handle) {
+ if (hash_con->con->icid == handle)
+ break;
+ }
+
+ if (!hash_con || (hash_con->con->icid != handle))
+ return NULL;
+
+ return hash_con;
+}
+
+static int qed_iscsi_stop(struct qed_dev *cdev)
+{
+ int rc;
+
+ if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) {
+ DP_NOTICE(cdev, "iscsi already stopped\n");
+ return 0;
+ }
+
+ if (!hash_empty(cdev->connections)) {
+ DP_NOTICE(cdev,
+ "Can't stop iscsi - not all connections were returned\n");
+ return -EINVAL;
+ }
+
+ /* Stop the iscsi */
+ rc = qed_sp_iscsi_func_stop(QED_LEADING_HWFN(cdev),
+ QED_SPQ_MODE_EBLOCK, NULL);
+ cdev->flags &= ~QED_FLAG_STORAGE_STARTED;
+
+ return rc;
+}
+
+static int qed_iscsi_start(struct qed_dev *cdev,
+ struct qed_iscsi_tid *tasks,
+ void *event_context,
+ iscsi_event_cb_t async_event_cb)
+{
+ int rc;
+ struct qed_tid_mem *tid_info;
+
+ if (cdev->flags & QED_FLAG_STORAGE_STARTED) {
+ DP_NOTICE(cdev, "iscsi already started;\n");
+ return 0;
+ }
+
+ rc = qed_sp_iscsi_func_start(QED_LEADING_HWFN(cdev),
+ QED_SPQ_MODE_EBLOCK, NULL, event_context,
+ async_event_cb);
+ if (rc) {
+ DP_NOTICE(cdev, "Failed to start iscsi\n");
+ return rc;
+ }
+
+ cdev->flags |= QED_FLAG_STORAGE_STARTED;
+ hash_init(cdev->connections);
+
+ if (!tasks)
+ return 0;
+
+ tid_info = kzalloc(sizeof(*tid_info), GFP_KERNEL);
+
+ if (!tid_info) {
+ qed_iscsi_stop(cdev);
+ return -ENOMEM;
+ }
+
+ rc = qed_cxt_get_tid_mem_info(QED_LEADING_HWFN(cdev),
+ tid_info);
+ if (rc) {
+ DP_NOTICE(cdev, "Failed to gather task information\n");
+ qed_iscsi_stop(cdev);
+ kfree(tid_info);
+ return rc;
+ }
+
+ /* Fill task information */
+ tasks->size = tid_info->tid_size;
+ tasks->num_tids_per_block = tid_info->num_tids_per_block;
+ memcpy(tasks->blocks, tid_info->blocks,
+ MAX_TID_BLOCKS_ISCSI * sizeof(u8 *));
+
+ kfree(tid_info);
+
+ return 0;
+}
+
+static int qed_iscsi_acquire_conn(struct qed_dev *cdev,
+ u32 *handle,
+ u32 *fw_cid, void __iomem **p_doorbell)
+{
+ struct qed_hash_iscsi_con *hash_con;
+ int rc;
+
+ /* Allocate a hashed connection */
+ hash_con = kzalloc(sizeof(*hash_con), GFP_ATOMIC);
+ if (!hash_con)
+ return -ENOMEM;
+
+ /* Acquire the connection */
+ rc = qed_iscsi_acquire_connection(QED_LEADING_HWFN(cdev), NULL,
+ &hash_con->con);
+ if (rc) {
+ DP_NOTICE(cdev, "Failed to acquire Connection\n");
+ kfree(hash_con);
+ return rc;
+ }
+
+ /* Added the connection to hash table */
+ *handle = hash_con->con->icid;
+ *fw_cid = hash_con->con->fw_cid;
+ hash_add(cdev->connections, &hash_con->node, *handle);
+
+ if (p_doorbell)
+ *p_doorbell = qed_iscsi_get_db_addr(QED_LEADING_HWFN(cdev),
+ *handle);
+
+ return 0;
+}
+
+static int qed_iscsi_release_conn(struct qed_dev *cdev, u32 handle)
+{
+ struct qed_hash_iscsi_con *hash_con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ hlist_del(&hash_con->node);
+ qed_iscsi_release_connection(QED_LEADING_HWFN(cdev), hash_con->con);
+ kfree(hash_con);
+
+ return 0;
+}
+
+static int qed_iscsi_offload_conn(struct qed_dev *cdev,
+ u32 handle,
+ struct qed_iscsi_params_offload *conn_info)
+{
+ struct qed_hash_iscsi_con *hash_con;
+ struct qed_iscsi_conn *con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ /* Update the connection with information from the params */
+ con = hash_con->con;
+
+ ether_addr_copy(con->local_mac, conn_info->src.mac);
+ ether_addr_copy(con->remote_mac, conn_info->dst.mac);
+ memcpy(con->local_ip, conn_info->src.ip, sizeof(con->local_ip));
+ memcpy(con->remote_ip, conn_info->dst.ip, sizeof(con->remote_ip));
+ con->local_port = conn_info->src.port;
+ con->remote_port = conn_info->dst.port;
+
+ con->layer_code = conn_info->layer_code;
+ con->sq_pbl_addr = conn_info->sq_pbl_addr;
+ con->initial_ack = conn_info->initial_ack;
+ con->vlan_id = conn_info->vlan_id;
+ con->tcp_flags = conn_info->tcp_flags;
+ con->ip_version = conn_info->ip_version;
+ con->default_cq = conn_info->default_cq;
+ con->ka_max_probe_cnt = conn_info->ka_max_probe_cnt;
+ con->dup_ack_theshold = conn_info->dup_ack_theshold;
+ con->rcv_next = conn_info->rcv_next;
+ con->snd_una = conn_info->snd_una;
+ con->snd_next = conn_info->snd_next;
+ con->snd_max = conn_info->snd_max;
+ con->snd_wnd = conn_info->snd_wnd;
+ con->rcv_wnd = conn_info->rcv_wnd;
+ con->snd_wl1 = conn_info->snd_wl1;
+ con->cwnd = conn_info->cwnd;
+ con->ss_thresh = conn_info->ss_thresh;
+ con->srtt = conn_info->srtt;
+ con->rtt_var = conn_info->rtt_var;
+ con->ts_time = conn_info->ts_time;
+ con->ts_recent = conn_info->ts_recent;
+ con->ts_recent_age = conn_info->ts_recent_age;
+ con->total_rt = conn_info->total_rt;
+ con->ka_timeout_delta = conn_info->ka_timeout_delta;
+ con->rt_timeout_delta = conn_info->rt_timeout_delta;
+ con->dup_ack_cnt = conn_info->dup_ack_cnt;
+ con->snd_wnd_probe_cnt = conn_info->snd_wnd_probe_cnt;
+ con->ka_probe_cnt = conn_info->ka_probe_cnt;
+ con->rt_cnt = conn_info->rt_cnt;
+ con->flow_label = conn_info->flow_label;
+ con->ka_timeout = conn_info->ka_timeout;
+ con->ka_interval = conn_info->ka_interval;
+ con->max_rt_time = conn_info->max_rt_time;
+ con->initial_rcv_wnd = conn_info->initial_rcv_wnd;
+ con->ttl = conn_info->ttl;
+ con->tos_or_tc = conn_info->tos_or_tc;
+ con->remote_port = conn_info->remote_port;
+ con->local_port = conn_info->local_port;
+ con->mss = conn_info->mss;
+ con->snd_wnd_scale = conn_info->snd_wnd_scale;
+ con->rcv_wnd_scale = conn_info->rcv_wnd_scale;
+ con->ts_ticks_per_second = conn_info->ts_ticks_per_second;
+ con->da_timeout_value = conn_info->da_timeout_value;
+ con->ack_frequency = conn_info->ack_frequency;
+
+ /* Set default values on other connection fields */
+ con->offl_flags = 0x1;
+
+ return qed_sp_iscsi_conn_offload(QED_LEADING_HWFN(cdev), con,
+ QED_SPQ_MODE_EBLOCK, NULL);
+}
+
+static int qed_iscsi_update_conn(struct qed_dev *cdev,
+ u32 handle,
+ struct qed_iscsi_params_update *conn_info)
+{
+ struct qed_hash_iscsi_con *hash_con;
+ struct qed_iscsi_conn *con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ /* Update the connection with information from the params */
+ con = hash_con->con;
+ con->update_flag = conn_info->update_flag;
+ con->max_seq_size = conn_info->max_seq_size;
+ con->max_recv_pdu_length = conn_info->max_recv_pdu_length;
+ con->max_send_pdu_length = conn_info->max_send_pdu_length;
+ con->first_seq_length = conn_info->first_seq_length;
+ con->exp_stat_sn = conn_info->exp_stat_sn;
+
+ return qed_sp_iscsi_conn_update(QED_LEADING_HWFN(cdev), con,
+ QED_SPQ_MODE_EBLOCK, NULL);
+}
+
+static int qed_iscsi_clear_conn_sq(struct qed_dev *cdev, u32 handle)
+{
+ struct qed_hash_iscsi_con *hash_con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ return qed_sp_iscsi_conn_clear_sq(QED_LEADING_HWFN(cdev),
+ hash_con->con,
+ QED_SPQ_MODE_EBLOCK, NULL);
+}
+
+static int qed_iscsi_destroy_conn(struct qed_dev *cdev,
+ u32 handle, u8 abrt_conn)
+{
+ struct qed_hash_iscsi_con *hash_con;
+
+ hash_con = qed_iscsi_get_hash(cdev, handle);
+ if (!hash_con) {
+ DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+ handle);
+ return -EINVAL;
+ }
+
+ hash_con->con->abortive_dsconnect = abrt_conn;
+
+ return qed_sp_iscsi_conn_terminate(QED_LEADING_HWFN(cdev),
+ hash_con->con,
+ QED_SPQ_MODE_EBLOCK, NULL);
+}
+
+static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
+{
+ return qed_iscsi_get_stats(QED_LEADING_HWFN(cdev), stats);
+}
+
+static const struct qed_iscsi_ops qed_iscsi_ops_pass = {
+ .common = &qed_common_ops_pass,
+ .ll2 = &qed_ll2_ops_pass,
+ .fill_dev_info = &qed_fill_iscsi_dev_info,
+ .register_ops = &qed_register_iscsi_ops,
+ .start = &qed_iscsi_start,
+ .stop = &qed_iscsi_stop,
+ .acquire_conn = &qed_iscsi_acquire_conn,
+ .release_conn = &qed_iscsi_release_conn,
+ .offload_conn = &qed_iscsi_offload_conn,
+ .update_conn = &qed_iscsi_update_conn,
+ .destroy_conn = &qed_iscsi_destroy_conn,
+ .clear_sq = &qed_iscsi_clear_conn_sq,
+ .get_stats = &qed_iscsi_stats,
+};
+
+const struct qed_iscsi_ops *qed_get_iscsi_ops()
+{
+ return &qed_iscsi_ops_pass;
+}
+EXPORT_SYMBOL(qed_get_iscsi_ops);
+
+void qed_put_iscsi_ops(void)
+{
+}
+EXPORT_SYMBOL(qed_put_iscsi_ops);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
new file mode 100644
index 000000000000..67c25f3db4d5
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
@@ -0,0 +1,52 @@
+/* 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_ISCSI_H
+#define _QED_ISCSI_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/qed/tcp_common.h>
+#include <linux/qed/qed_iscsi_if.h>
+#include <linux/qed/qed_chain.h>
+#include "qed.h"
+#include "qed_hsi.h"
+#include "qed_mcp.h"
+#include "qed_sp.h"
+
+struct qed_iscsi_info {
+ spinlock_t lock; /* Connection resources. */
+ struct list_head free_list;
+ u16 max_num_outstanding_tasks;
+ void *event_context;
+ iscsi_event_cb_t event_cb;
+};
+
+#ifdef CONFIG_QED_LL2
+extern const struct qed_ll2_ops qed_ll2_ops_pass;
+#endif
+
+#if IS_ENABLED(CONFIG_QED_ISCSI)
+struct qed_iscsi_info *qed_iscsi_alloc(struct qed_hwfn *p_hwfn);
+
+void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info);
+
+void qed_iscsi_free(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info);
+#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
+static inline struct qed_iscsi_info *qed_iscsi_alloc(
+ struct qed_hwfn *p_hwfn) { return NULL; }
+static inline void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info) {}
+static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn,
+ struct qed_iscsi_info *p_iscsi_info) {}
+#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index ddd410a91e13..6a3727c4c0c6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -23,6 +23,7 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/bug.h>
+#include <linux/vmalloc.h>
#include "qed.h"
#include <linux/qed/qed_chain.h>
#include "qed_cxt.h"
@@ -41,6 +42,124 @@
#define QED_MAX_SGES_NUM 16
#define CRC32_POLY 0x1edc6f41
+void qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid)
+{
+ /* VFs' CIDs are 0-based in PF-view, and uninitialized on VF */
+ if (!p_cid->is_vf && IS_PF(p_hwfn->cdev))
+ qed_cxt_release_cid(p_hwfn, p_cid->cid);
+ vfree(p_cid);
+}
+
+/* The internal is only meant to be directly called by PFs initializeing CIDs
+ * for their VFs.
+ */
+struct qed_queue_cid *
+_qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ u32 cid,
+ u8 vf_qid,
+ struct qed_queue_start_common_params *p_params)
+{
+ bool b_is_same = (p_hwfn->hw_info.opaque_fid == opaque_fid);
+ struct qed_queue_cid *p_cid;
+ int rc;
+
+ p_cid = vmalloc(sizeof(*p_cid));
+ if (!p_cid)
+ return NULL;
+ memset(p_cid, 0, sizeof(*p_cid));
+
+ p_cid->opaque_fid = opaque_fid;
+ p_cid->cid = cid;
+ p_cid->vf_qid = vf_qid;
+ p_cid->rel = *p_params;
+
+ /* Don't try calculating the absolute indices for VFs */
+ if (IS_VF(p_hwfn->cdev)) {
+ p_cid->abs = p_cid->rel;
+ goto out;
+ }
+
+ /* Calculate the engine-absolute indices of the resources.
+ * This would guarantee they're valid later on.
+ * In some cases [SBs] we already have the right values.
+ */
+ rc = qed_fw_vport(p_hwfn, p_cid->rel.vport_id, &p_cid->abs.vport_id);
+ if (rc)
+ goto fail;
+
+ rc = qed_fw_l2_queue(p_hwfn, p_cid->rel.queue_id, &p_cid->abs.queue_id);
+ if (rc)
+ goto fail;
+
+ /* In case of a PF configuring its VF's queues, the stats-id is already
+ * absolute [since there's a single index that's suitable per-VF].
+ */
+ if (b_is_same) {
+ rc = qed_fw_vport(p_hwfn, p_cid->rel.stats_id,
+ &p_cid->abs.stats_id);
+ if (rc)
+ goto fail;
+ } else {
+ p_cid->abs.stats_id = p_cid->rel.stats_id;
+ }
+
+ /* SBs relevant information was already provided as absolute */
+ p_cid->abs.sb = p_cid->rel.sb;
+ p_cid->abs.sb_idx = p_cid->rel.sb_idx;
+
+ /* This is tricky - we're actually interested in whehter this is a PF
+ * entry meant for the VF.
+ */
+ if (!b_is_same)
+ p_cid->is_vf = true;
+out:
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_SP,
+ "opaque_fid: %04x CID %08x vport %02x [%02x] qzone %04x [%04x] stats %02x [%02x] SB %04x PI %02x\n",
+ p_cid->opaque_fid,
+ p_cid->cid,
+ p_cid->rel.vport_id,
+ p_cid->abs.vport_id,
+ p_cid->rel.queue_id,
+ p_cid->abs.queue_id,
+ p_cid->rel.stats_id,
+ p_cid->abs.stats_id, p_cid->abs.sb, p_cid->abs.sb_idx);
+
+ return p_cid;
+
+fail:
+ vfree(p_cid);
+ return NULL;
+}
+
+static struct qed_queue_cid *qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid, struct
+ qed_queue_start_common_params
+ *p_params)
+{
+ struct qed_queue_cid *p_cid;
+ u32 cid = 0;
+
+ /* Get a unique firmware CID for this queue, in case it's a PF.
+ * VF's don't need a CID as the queue configuration will be done
+ * by PF.
+ */
+ if (IS_PF(p_hwfn->cdev)) {
+ if (qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, &cid)) {
+ DP_NOTICE(p_hwfn, "Failed to acquire cid\n");
+ return NULL;
+ }
+ }
+
+ p_cid = _qed_eth_queue_to_cid(p_hwfn, opaque_fid, cid, 0, p_params);
+ if (!p_cid && IS_PF(p_hwfn->cdev))
+ qed_cxt_release_cid(p_hwfn, cid);
+
+ return p_cid;
+}
+
int qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn,
struct qed_sp_vport_start_params *p_params)
{
@@ -496,61 +615,26 @@ static int qed_filter_accept_cmd(struct qed_dev *cdev,
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;
-}
-
-int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
- u16 opaque_fid,
- u32 cid,
- struct qed_queue_start_common_params *p_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, bool b_use_zone_a_prod)
+int qed_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ 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_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
- 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[p_params->queue_id];
- p_rx_cid->cid = cid;
- p_rx_cid->opaque_fid = opaque_fid;
- p_rx_cid->vport_id = p_params->vport_id;
-
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
- if (rc)
- return rc;
-
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_rx_q_id);
- if (rc)
- 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, p_params->queue_id, p_params->vport_id, p_params->sb);
+ "opaque_fid=0x%x, cid=0x%x, rx_qzone=0x%x, vport_id=0x%x, sb_id=0x%x\n",
+ p_cid->opaque_fid, p_cid->cid,
+ p_cid->abs.queue_id, p_cid->abs.vport_id, p_cid->abs.sb);
/* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
- init_data.cid = cid;
- init_data.opaque_fid = opaque_fid;
+ init_data.cid = p_cid->cid;
+ init_data.opaque_fid = p_cid->opaque_fid;
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
rc = qed_sp_init_request(p_hwfn, &p_ent,
@@ -561,11 +645,11 @@ int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
p_ramrod = &p_ent->ramrod.rx_queue_start;
- p_ramrod->sb_id = cpu_to_le16(p_params->sb);
- p_ramrod->sb_index = p_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->sb_id = cpu_to_le16(p_cid->abs.sb);
+ p_ramrod->sb_index = p_cid->abs.sb_idx;
+ p_ramrod->vport_id = p_cid->abs.vport_id;
+ p_ramrod->stats_counter_id = p_cid->abs.stats_id;
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id);
p_ramrod->complete_cqe_flg = 0;
p_ramrod->complete_event_flg = 1;
@@ -575,85 +659,85 @@ int qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size);
DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr, cqe_pbl_addr);
- if (p_params->vf_qid || b_use_zone_a_prod) {
- p_ramrod->vf_rx_prod_index = p_params->vf_qid;
+ if (p_cid->is_vf) {
+ p_ramrod->vf_rx_prod_index = p_cid->vf_qid;
DP_VERBOSE(p_hwfn, QED_MSG_SP,
"Queue%s is meant for VF rxq[%02x]\n",
- b_use_zone_a_prod ? " [legacy]" : "",
- p_params->vf_qid);
- p_ramrod->vf_rx_prod_use_zone_a = b_use_zone_a_prod;
+ !!p_cid->b_legacy_vf ? " [legacy]" : "",
+ p_cid->vf_qid);
+ p_ramrod->vf_rx_prod_use_zone_a = !!p_cid->b_legacy_vf;
}
return qed_spq_post(p_hwfn, p_ent, NULL);
}
static int
-qed_sp_eth_rx_queue_start(struct qed_hwfn *p_hwfn,
- u16 opaque_fid,
- struct qed_queue_start_common_params *p_params,
+qed_eth_pf_rx_queue_start(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
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;
u32 init_prod_val = 0;
- u16 abs_l2_queue = 0;
- u8 abs_stats_id = 0;
- int rc;
- if (IS_VF(p_hwfn->cdev)) {
- return qed_vf_pf_rxq_start(p_hwfn,
- p_params->queue_id,
- p_params->sb,
- (u8)p_params->sb_idx,
- bd_max_bytes,
- bd_chain_phys_addr,
- cqe_pbl_addr, cqe_pbl_size, pp_prod);
- }
-
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_l2_queue);
- if (rc)
- return rc;
-
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id);
- if (rc)
- return rc;
-
- *pp_prod = (u8 __iomem *)p_hwfn->regview +
- GTT_BAR0_MAP_REG_MSDM_RAM +
- MSTORM_ETH_PF_PRODS_OFFSET(abs_l2_queue);
+ *pp_prod = p_hwfn->regview +
+ GTT_BAR0_MAP_REG_MSDM_RAM +
+ MSTORM_ETH_PF_PRODS_OFFSET(p_cid->abs.queue_id);
/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
(u32 *)(&init_prod_val));
+ return qed_eth_rxq_start_ramrod(p_hwfn, p_cid,
+ bd_max_bytes,
+ bd_chain_phys_addr,
+ cqe_pbl_addr, cqe_pbl_size);
+}
+
+static int
+qed_eth_rx_queue_start(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_queue_start_common_params *p_params,
+ u16 bd_max_bytes,
+ dma_addr_t bd_chain_phys_addr,
+ dma_addr_t cqe_pbl_addr,
+ u16 cqe_pbl_size,
+ struct qed_rxq_start_ret_params *p_ret_params)
+{
+ struct qed_queue_cid *p_cid;
+ int rc;
+
/* Allocate a CID for the queue */
- p_rx_cid = &p_hwfn->p_rx_cids[p_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;
+ p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params);
+ if (!p_cid)
+ return -ENOMEM;
- rc = qed_sp_eth_rxq_start_ramrod(p_hwfn,
- opaque_fid,
- p_rx_cid->cid,
- p_params,
- abs_stats_id,
+ if (IS_PF(p_hwfn->cdev)) {
+ rc = qed_eth_pf_rx_queue_start(p_hwfn, p_cid,
+ bd_max_bytes,
+ bd_chain_phys_addr,
+ cqe_pbl_addr, cqe_pbl_size,
+ &p_ret_params->p_prod);
+ } else {
+ rc = qed_vf_pf_rxq_start(p_hwfn, p_cid,
bd_max_bytes,
bd_chain_phys_addr,
- cqe_pbl_addr, cqe_pbl_size, false);
+ cqe_pbl_addr,
+ cqe_pbl_size, &p_ret_params->p_prod);
+ }
+ /* Provide the caller with a reference to as handler */
if (rc)
- qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
+ else
+ p_ret_params->p_handle = (void *)p_cid;
return rc;
}
int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
- u16 rx_queue_id,
+ void **pp_rxq_handles,
u8 num_rxqs,
u8 complete_cqe_flg,
u8 complete_event_flg,
@@ -663,8 +747,7 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
struct rx_queue_update_ramrod_data *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
- struct qed_hw_cid_data *p_rx_cid;
- u16 qid, abs_rx_q_id = 0;
+ struct qed_queue_cid *p_cid;
int rc = -EINVAL;
u8 i;
@@ -673,12 +756,11 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
init_data.p_comp_data = p_comp_data;
for (i = 0; i < num_rxqs; i++) {
- qid = rx_queue_id + i;
- p_rx_cid = &p_hwfn->p_rx_cids[qid];
+ p_cid = ((struct qed_queue_cid **)pp_rxq_handles)[i];
/* Get SPQ entry */
- init_data.cid = p_rx_cid->cid;
- init_data.opaque_fid = p_rx_cid->opaque_fid;
+ init_data.cid = p_cid->cid;
+ init_data.opaque_fid = p_cid->opaque_fid;
rc = qed_sp_init_request(p_hwfn, &p_ent,
ETH_RAMROD_RX_QUEUE_UPDATE,
@@ -687,10 +769,9 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
return rc;
p_ramrod = &p_ent->ramrod.rx_queue_update;
+ p_ramrod->vport_id = p_cid->abs.vport_id;
- qed_fw_vport(p_hwfn, p_rx_cid->vport_id, &p_ramrod->vport_id);
- qed_fw_l2_queue(p_hwfn, qid, &abs_rx_q_id);
- p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id);
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id);
p_ramrod->complete_cqe_flg = complete_cqe_flg;
p_ramrod->complete_event_flg = complete_event_flg;
@@ -702,24 +783,19 @@ int qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
return rc;
}
-int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
- u16 rx_queue_id,
- bool eq_completion_only, bool cqe_completion)
+static int
+qed_eth_pf_rx_queue_stop(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ bool b_eq_completion_only, bool b_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_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
- u16 abs_rx_q_id = 0;
- int rc = -EINVAL;
-
- if (IS_VF(p_hwfn->cdev))
- return qed_vf_pf_rxq_stop(p_hwfn, rx_queue_id, cqe_completion);
+ int rc;
- /* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
- init_data.cid = p_rx_cid->cid;
- init_data.opaque_fid = p_rx_cid->opaque_fid;
+ init_data.cid = p_cid->cid;
+ init_data.opaque_fid = p_cid->opaque_fid;
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
rc = qed_sp_init_request(p_hwfn, &p_ent,
@@ -729,62 +805,53 @@ int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
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);
+ p_ramrod->vport_id = p_cid->abs.vport_id;
+ p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_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;
+ p_ramrod->complete_cqe_flg = (!p_cid->is_vf &&
+ !b_eq_completion_only) ||
+ b_cqe_completion;
+ p_ramrod->complete_event_flg = p_cid->is_vf || b_eq_completion_only;
- rc = qed_spq_post(p_hwfn, p_ent, NULL);
- if (rc)
- return rc;
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+int qed_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
+ void *p_rxq,
+ bool eq_completion_only, bool cqe_completion)
+{
+ struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_rxq;
+ int rc = -EINVAL;
+
+ if (IS_PF(p_hwfn->cdev))
+ rc = qed_eth_pf_rx_queue_stop(p_hwfn, p_cid,
+ eq_completion_only,
+ cqe_completion);
+ else
+ rc = qed_vf_pf_rxq_stop(p_hwfn, p_cid, cqe_completion);
- return qed_sp_release_queue_cid(p_hwfn, p_rx_cid);
+ if (!rc)
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
+ return rc;
}
-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)
+int
+qed_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ dma_addr_t pbl_addr, u16 pbl_size, u16 pq_id)
{
struct tx_queue_start_ramrod_data *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
- struct qed_hw_cid_data *p_tx_cid;
- u16 pq_id, abs_tx_q_id = 0;
int rc = -EINVAL;
- u8 abs_vport_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;
-
- rc = qed_fw_l2_queue(p_hwfn, p_params->queue_id, &abs_tx_q_id);
- if (rc)
- return rc;
/* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
- init_data.cid = cid;
- init_data.opaque_fid = opaque_fid;
+ init_data.cid = p_cid->cid;
+ init_data.opaque_fid = p_cid->opaque_fid;
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
rc = qed_sp_init_request(p_hwfn, &p_ent,
@@ -794,96 +861,92 @@ int qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
return rc;
p_ramrod = &p_ent->ramrod.tx_queue_start;
- p_ramrod->vport_id = abs_vport_id;
+ p_ramrod->vport_id = p_cid->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->sb_id = cpu_to_le16(p_cid->abs.sb);
+ p_ramrod->sb_index = p_cid->abs.sb_idx;
+ p_ramrod->stats_counter_id = p_cid->abs.stats_id;
- p_ramrod->queue_zone_id = cpu_to_le16(abs_tx_q_id);
+ p_ramrod->queue_zone_id = cpu_to_le16(p_cid->abs.queue_id);
+ p_ramrod->same_as_last_id = cpu_to_le16(p_cid->abs.queue_id);
p_ramrod->pbl_size = cpu_to_le16(pbl_size);
DMA_REGPAIR_LE(p_ramrod->pbl_base_addr, 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,
+qed_eth_pf_tx_queue_start(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ u8 tc,
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;
- if (IS_VF(p_hwfn->cdev)) {
- return qed_vf_pf_txq_start(p_hwfn,
- p_params->queue_id,
- p_params->sb,
- p_params->sb_idx,
- pbl_addr, pbl_size, pp_doorbell);
- }
+ memset(&pq_params, 0, sizeof(pq_params));
- rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id);
+ rc = qed_eth_txq_start_ramrod(p_hwfn, p_cid,
+ pbl_addr, pbl_size,
+ qed_get_qm_pq(p_hwfn, PROTOCOLID_ETH,
+ &pq_params));
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));
+ /* Provide the caller with the necessary return values */
+ *pp_doorbell = p_hwfn->doorbells +
+ qed_db_addr(p_cid->cid, DQ_DEMS_LEGACY);
- /* 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;
+ return 0;
+}
- 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);
+static int
+qed_eth_tx_queue_start(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ struct qed_queue_start_common_params *p_params,
+ u8 tc,
+ dma_addr_t pbl_addr,
+ u16 pbl_size,
+ struct qed_txq_start_ret_params *p_ret_params)
+{
+ struct qed_queue_cid *p_cid;
+ int rc;
+
+ p_cid = qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params);
+ if (!p_cid)
+ return -EINVAL;
+
+ if (IS_PF(p_hwfn->cdev))
+ rc = qed_eth_pf_tx_queue_start(p_hwfn, p_cid, tc,
+ pbl_addr, pbl_size,
+ &p_ret_params->p_doorbell);
+ else
+ rc = qed_vf_pf_txq_start(p_hwfn, p_cid,
+ pbl_addr, pbl_size,
+ &p_ret_params->p_doorbell);
if (rc)
- qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
+ else
+ p_ret_params->p_handle = (void *)p_cid;
return rc;
}
-int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id)
+static int
+qed_eth_pf_tx_queue_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid)
{
- struct qed_hw_cid_data *p_tx_cid = &p_hwfn->p_tx_cids[tx_queue_id];
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
- int rc = -EINVAL;
-
- if (IS_VF(p_hwfn->cdev))
- return qed_vf_pf_txq_stop(p_hwfn, tx_queue_id);
+ int rc;
- /* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
- init_data.cid = p_tx_cid->cid;
- init_data.opaque_fid = p_tx_cid->opaque_fid;
+ init_data.cid = p_cid->cid;
+ init_data.opaque_fid = p_cid->opaque_fid;
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
rc = qed_sp_init_request(p_hwfn, &p_ent,
@@ -892,11 +955,22 @@ int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id)
if (rc)
return rc;
- rc = qed_spq_post(p_hwfn, p_ent, NULL);
- if (rc)
- return rc;
+ return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
+int qed_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, void *p_handle)
+{
+ struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_handle;
+ int rc;
+
+ if (IS_PF(p_hwfn->cdev))
+ rc = qed_eth_pf_tx_queue_stop(p_hwfn, p_cid);
+ else
+ rc = qed_vf_pf_txq_stop(p_hwfn, p_cid);
- return qed_sp_release_queue_cid(p_hwfn, p_tx_cid);
+ if (!rc)
+ qed_eth_queue_cid_release(p_hwfn, p_cid);
+ return rc;
}
static enum eth_filter_action qed_filter_action(enum qed_filter_opcode opcode)
@@ -1652,6 +1726,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
if (IS_PF(cdev)) {
int max_vf_vlan_filters = 0;
+ int max_vf_mac_filters = 0;
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
for_each_hwfn(cdev, i)
@@ -1665,11 +1740,18 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
info->num_queues = cdev->num_hwfns;
}
- if (IS_QED_SRIOV(cdev))
+ if (IS_QED_SRIOV(cdev)) {
max_vf_vlan_filters = cdev->p_iov_info->total_vfs *
QED_ETH_VF_NUM_VLAN_FILTERS;
- info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN) -
+ max_vf_mac_filters = cdev->p_iov_info->total_vfs *
+ QED_ETH_VF_NUM_MAC_FILTERS;
+ }
+ info->num_vlan_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+ QED_VLAN) -
max_vf_vlan_filters;
+ info->num_mac_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+ QED_MAC) -
+ max_vf_mac_filters;
ether_addr_copy(info->port_mac,
cdev->hwfns[0].hw_info.hw_mac_addr);
@@ -1683,7 +1765,9 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
}
qed_vf_get_num_vlan_filters(&cdev->hwfns[0],
- &info->num_vlan_filters);
+ (u8 *)&info->num_vlan_filters);
+ qed_vf_get_num_mac_filters(&cdev->hwfns[0],
+ (u8 *)&info->num_mac_filters);
qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac);
info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi;
@@ -1870,58 +1954,53 @@ static int qed_update_vport(struct qed_dev *cdev,
}
static int qed_start_rxq(struct qed_dev *cdev,
- struct qed_queue_start_common_params *params,
+ u8 rss_num,
+ struct qed_queue_start_common_params *p_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_rxq_start_ret_params *ret_params)
{
struct qed_hwfn *p_hwfn;
int rc, hwfn_index;
- hwfn_index = params->rss_id % cdev->num_hwfns;
+ hwfn_index = rss_num % 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);
+ p_params->queue_id = p_params->queue_id / cdev->num_hwfns;
+ p_params->stats_id = p_params->vport_id;
+ rc = qed_eth_rx_queue_start(p_hwfn,
+ p_hwfn->hw_info.opaque_fid,
+ p_params,
+ bd_max_bytes,
+ bd_chain_phys_addr,
+ cqe_pbl_addr, cqe_pbl_size, ret_params);
if (rc) {
- DP_ERR(cdev, "Failed to start RXQ#%d\n", params->queue_id);
+ DP_ERR(cdev, "Failed to start RXQ#%d\n", p_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);
+ "Started RX-Q %d [rss_num %d] on V-PORT %d and SB %d\n",
+ p_params->queue_id, rss_num, p_params->vport_id,
+ p_params->sb);
return 0;
}
-static int qed_stop_rxq(struct qed_dev *cdev,
- struct qed_stop_rxq_params *params)
+static int qed_stop_rxq(struct qed_dev *cdev, u8 rss_id, void *handle)
{
int rc, hwfn_index;
struct qed_hwfn *p_hwfn;
- hwfn_index = params->rss_id % cdev->num_hwfns;
- p_hwfn = &cdev->hwfns[hwfn_index];
+ hwfn_index = 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);
+ rc = qed_eth_rx_queue_stop(p_hwfn, handle, false, false);
if (rc) {
- DP_ERR(cdev, "Failed to stop RXQ#%d\n", params->rx_queue_id);
+ DP_ERR(cdev, "Failed to stop RXQ#%02x\n", rss_id);
return rc;
}
@@ -1929,26 +2008,24 @@ static int qed_stop_rxq(struct qed_dev *cdev,
}
static int qed_start_txq(struct qed_dev *cdev,
+ u8 rss_num,
struct qed_queue_start_common_params *p_params,
dma_addr_t pbl_addr,
u16 pbl_size,
- void __iomem **pp_doorbell)
+ struct qed_txq_start_ret_params *ret_params)
{
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;
+ hwfn_index = rss_num % cdev->num_hwfns;
+ p_hwfn = &cdev->hwfns[hwfn_index];
+ p_params->queue_id = p_params->queue_id / cdev->num_hwfns;
+ p_params->stats_id = p_params->vport_id;
- rc = qed_sp_eth_tx_queue_start(p_hwfn,
- p_hwfn->hw_info.opaque_fid,
- p_params,
- pbl_addr,
- pbl_size,
- pp_doorbell);
+ rc = qed_eth_tx_queue_start(p_hwfn,
+ p_hwfn->hw_info.opaque_fid,
+ p_params, 0,
+ pbl_addr, pbl_size, ret_params);
if (rc) {
DP_ERR(cdev, "Failed to start TXQ#%d\n", p_params->queue_id);
@@ -1956,8 +2033,8 @@ static int qed_start_txq(struct qed_dev *cdev,
}
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,
+ "Started TX-Q %d [rss_num %d] on V-PORT %d and SB %d\n",
+ p_params->queue_id, rss_num, p_params->vport_id,
p_params->sb);
return 0;
@@ -1971,19 +2048,17 @@ static int qed_fastpath_stop(struct qed_dev *cdev)
return 0;
}
-static int qed_stop_txq(struct qed_dev *cdev,
- struct qed_stop_txq_params *params)
+static int qed_stop_txq(struct qed_dev *cdev, u8 rss_id, void *handle)
{
struct qed_hwfn *p_hwfn;
int rc, hwfn_index;
- hwfn_index = params->rss_id % cdev->num_hwfns;
- p_hwfn = &cdev->hwfns[hwfn_index];
+ hwfn_index = 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);
+ rc = qed_eth_tx_queue_stop(p_hwfn, handle);
if (rc) {
- DP_ERR(cdev, "Failed to stop TXQ#%d\n", params->tx_queue_id);
+ DP_ERR(cdev, "Failed to stop TXQ#%02x\n", rss_id);
return rc;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h
index e495d62fcc03..48c9bfc28140 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h
@@ -78,11 +78,34 @@ struct qed_filter_mcast {
unsigned char mac[QED_MAX_MC_ADDRS][ETH_ALEN];
};
-int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
- u16 rx_queue_id,
- bool eq_completion_only, bool cqe_completion);
+/**
+ * @brief qed_eth_rx_queue_stop - This ramrod closes an Rx queue
+ *
+ * @param p_hwfn
+ * @param p_rxq Handler of queue to close
+ * @param eq_completion_only If True completion will be on
+ * EQe, if False completion will be
+ * on EQe if p_hwfn opaque
+ * different from the RXQ opaque
+ * otherwise on CQe.
+ * @param cqe_completion If True completion will be
+ * receive on CQe.
+ * @return int
+ */
+int
+qed_eth_rx_queue_stop(struct qed_hwfn *p_hwfn,
+ void *p_rxq,
+ bool eq_completion_only, bool cqe_completion);
-int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id);
+/**
+ * @brief qed_eth_tx_queue_stop - closes a Tx queue
+ *
+ * @param p_hwfn
+ * @param p_txq - handle to Tx queue needed to be closed
+ *
+ * @return int
+ */
+int qed_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, void *p_txq);
enum qed_tpa_mode {
QED_TPA_MODE_NONE,
@@ -196,19 +219,19 @@ int qed_sp_eth_filter_ucast(struct qed_hwfn *p_hwfn,
* @note At the moment - only used by non-linux VFs.
*
* @param p_hwfn
- * @param rx_queue_id RX Queue ID
- * @param num_rxqs Allow to update multiple rx
- * queues, from rx_queue_id to
- * (rx_queue_id + num_rxqs)
+ * @param pp_rxq_handlers An array of queue handlers to be updated.
+ * @param num_rxqs number of queues to update.
* @param complete_cqe_flg Post completion to the CQE Ring if set
* @param complete_event_flg Post completion to the Event Ring if set
+ * @param comp_mode
+ * @param p_comp_data
*
* @return int
*/
int
qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
- u16 rx_queue_id,
+ void **pp_rxq_handlers,
u8 num_rxqs,
u8 complete_cqe_flg,
u8 complete_event_flg,
@@ -217,27 +240,79 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats);
-int qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn,
- struct qed_sp_vport_start_params *p_params);
+void qed_reset_vport_stats(struct qed_dev *cdev);
+
+struct qed_queue_cid {
+ /* 'Relative' is a relative term ;-). Usually the indices [not counting
+ * SBs] would be PF-relative, but there are some cases where that isn't
+ * the case - specifically for a PF configuring its VF indices it's
+ * possible some fields [E.g., stats-id] in 'rel' would already be abs.
+ */
+ struct qed_queue_start_common_params rel;
+ struct qed_queue_start_common_params abs;
+ u32 cid;
+ u16 opaque_fid;
+
+ /* VFs queues are mapped differently, so we need to know the
+ * relative queue associated with them [0-based].
+ * Notice this is relevant on the *PF* queue-cid of its VF's queues,
+ * and not on the VF itself.
+ */
+ bool is_vf;
+ u8 vf_qid;
+
+ /* Legacy VFs might have Rx producer located elsewhere */
+ bool b_legacy_vf;
+};
-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, bool b_use_zone_a_prod);
-
-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);
+void qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid);
+
+struct qed_queue_cid *_qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn,
+ u16 opaque_fid,
+ u32 cid,
+ u8 vf_qid,
+ struct qed_queue_start_common_params
+ *p_params);
+
+int
+qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn,
+ struct qed_sp_vport_start_params *p_params);
+
+/**
+ * @brief - Starts an Rx queue, when queue_cid is already prepared
+ *
+ * @param p_hwfn
+ * @param p_cid
+ * @param bd_max_bytes
+ * @param bd_chain_phys_addr
+ * @param cqe_pbl_addr
+ * @param cqe_pbl_size
+ *
+ * @return int
+ */
+int
+qed_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ u16 bd_max_bytes,
+ dma_addr_t bd_chain_phys_addr,
+ dma_addr_t cqe_pbl_addr, u16 cqe_pbl_size);
+
+/**
+ * @brief - Starts a Tx queue, where queue_cid is already prepared
+ *
+ * @param p_hwfn
+ * @param p_cid
+ * @param pbl_addr
+ * @param pbl_size
+ * @param p_pq_params - parameters for choosing the PQ for this Tx queue
+ *
+ * @return int
+ */
+int
+qed_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ dma_addr_t pbl_addr, u16 pbl_size, u16 pq_id);
u8 qed_mcast_bin_from_mac(u8 *mac);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index 62ae55bd81b8..8e5cb7605b0f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -36,6 +36,7 @@
#include "qed_int.h"
#include "qed_ll2.h"
#include "qed_mcp.h"
+#include "qed_ooo.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_roce.h"
@@ -296,25 +297,34 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
list_del(&p_pkt->list_entry);
b_last_packet = list_empty(&p_tx->active_descq);
list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
- p_tx->cur_completing_packet = *p_pkt;
- p_tx->cur_completing_bd_idx = 1;
- b_last_frag = p_tx->cur_completing_bd_idx == p_pkt->bd_used;
- tx_frag = p_pkt->bds_set[0].tx_frag;
- if (p_ll2_conn->gsi_enable)
- qed_ll2b_release_tx_gsi_packet(p_hwfn,
- p_ll2_conn->my_id,
- p_pkt->cookie,
- tx_frag,
- b_last_frag,
- b_last_packet);
- else
- qed_ll2b_complete_tx_packet(p_hwfn,
- p_ll2_conn->my_id,
- p_pkt->cookie,
- tx_frag,
- b_last_frag,
- b_last_packet);
+ if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+ struct qed_ooo_buffer *p_buffer;
+ p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
+ qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,
+ p_buffer);
+ } else {
+ p_tx->cur_completing_packet = *p_pkt;
+ p_tx->cur_completing_bd_idx = 1;
+ b_last_frag =
+ p_tx->cur_completing_bd_idx == p_pkt->bd_used;
+ tx_frag = p_pkt->bds_set[0].tx_frag;
+ if (p_ll2_conn->gsi_enable)
+ qed_ll2b_release_tx_gsi_packet(p_hwfn,
+ p_ll2_conn->
+ my_id,
+ p_pkt->cookie,
+ tx_frag,
+ b_last_frag,
+ b_last_packet);
+ else
+ qed_ll2b_complete_tx_packet(p_hwfn,
+ p_ll2_conn->my_id,
+ p_pkt->cookie,
+ tx_frag,
+ b_last_frag,
+ b_last_packet);
+ }
}
}
@@ -540,12 +550,457 @@ static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);
- rx_buf_addr = p_pkt->rx_buf_addr;
- cookie = p_pkt->cookie;
+ if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+ struct qed_ooo_buffer *p_buffer;
+
+ p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
+ qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,
+ p_buffer);
+ } else {
+ rx_buf_addr = p_pkt->rx_buf_addr;
+ cookie = p_pkt->cookie;
+
+ b_last = list_empty(&p_rx->active_descq);
+ }
+ }
+}
+
+#if IS_ENABLED(CONFIG_QED_ISCSI)
+static u8 qed_ll2_convert_rx_parse_to_tx_flags(u16 parse_flags)
+{
+ u8 bd_flags = 0;
+
+ if (GET_FIELD(parse_flags, PARSING_AND_ERR_FLAGS_TAG8021QEXIST))
+ SET_FIELD(bd_flags, CORE_TX_BD_FLAGS_VLAN_INSERTION, 1);
+
+ return bd_flags;
+}
+
+static int qed_ll2_lb_rxq_handler(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn)
+{
+ struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
+ u16 packet_length = 0, parse_flags = 0, vlan = 0;
+ struct qed_ll2_rx_packet *p_pkt = NULL;
+ u32 num_ooo_add_to_peninsula = 0, cid;
+ union core_rx_cqe_union *cqe = NULL;
+ u16 cq_new_idx = 0, cq_old_idx = 0;
+ struct qed_ooo_buffer *p_buffer;
+ struct ooo_opaque *iscsi_ooo;
+ u8 placement_offset = 0;
+ u8 cqe_type;
+
+ cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);
+ cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
+ if (cq_new_idx == cq_old_idx)
+ return 0;
+
+ while (cq_new_idx != cq_old_idx) {
+ struct core_rx_fast_path_cqe *p_cqe_fp;
+
+ cqe = qed_chain_consume(&p_rx->rcq_chain);
+ cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
+ cqe_type = cqe->rx_cqe_sp.type;
+
+ if (cqe_type != CORE_RX_CQE_TYPE_REGULAR) {
+ DP_NOTICE(p_hwfn,
+ "Got a non-regular LB LL2 completion [type 0x%02x]\n",
+ cqe_type);
+ return -EINVAL;
+ }
+ p_cqe_fp = &cqe->rx_cqe_fp;
+
+ placement_offset = p_cqe_fp->placement_offset;
+ parse_flags = le16_to_cpu(p_cqe_fp->parse_flags.flags);
+ packet_length = le16_to_cpu(p_cqe_fp->packet_length);
+ vlan = le16_to_cpu(p_cqe_fp->vlan);
+ iscsi_ooo = (struct ooo_opaque *)&p_cqe_fp->opaque_data;
+ qed_ooo_save_history_entry(p_hwfn, p_hwfn->p_ooo_info,
+ iscsi_ooo);
+ cid = le32_to_cpu(iscsi_ooo->cid);
+
+ /* Process delete isle first */
+ if (iscsi_ooo->drop_size)
+ qed_ooo_delete_isles(p_hwfn, p_hwfn->p_ooo_info, cid,
+ iscsi_ooo->drop_isle,
+ iscsi_ooo->drop_size);
+
+ if (iscsi_ooo->ooo_opcode == TCP_EVENT_NOP)
+ continue;
+
+ /* Now process create/add/join isles */
+ if (list_empty(&p_rx->active_descq)) {
+ DP_NOTICE(p_hwfn,
+ "LL2 OOO RX chain has no submitted buffers\n"
+ );
+ return -EIO;
+ }
+
+ p_pkt = list_first_entry(&p_rx->active_descq,
+ struct qed_ll2_rx_packet, list_entry);
+
+ if ((iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_NEW_ISLE) ||
+ (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_ISLE_RIGHT) ||
+ (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_ISLE_LEFT) ||
+ (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_PEN) ||
+ (iscsi_ooo->ooo_opcode == TCP_EVENT_JOIN)) {
+ if (!p_pkt) {
+ DP_NOTICE(p_hwfn,
+ "LL2 OOO RX packet is not valid\n");
+ return -EIO;
+ }
+ list_del(&p_pkt->list_entry);
+ p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
+ p_buffer->packet_length = packet_length;
+ p_buffer->parse_flags = parse_flags;
+ p_buffer->vlan = vlan;
+ p_buffer->placement_offset = placement_offset;
+ qed_chain_consume(&p_rx->rxq_chain);
+ list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
+
+ switch (iscsi_ooo->ooo_opcode) {
+ case TCP_EVENT_ADD_NEW_ISLE:
+ qed_ooo_add_new_isle(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid,
+ iscsi_ooo->ooo_isle,
+ p_buffer);
+ break;
+ case TCP_EVENT_ADD_ISLE_RIGHT:
+ qed_ooo_add_new_buffer(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid,
+ iscsi_ooo->ooo_isle,
+ p_buffer,
+ QED_OOO_RIGHT_BUF);
+ break;
+ case TCP_EVENT_ADD_ISLE_LEFT:
+ qed_ooo_add_new_buffer(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid,
+ iscsi_ooo->ooo_isle,
+ p_buffer,
+ QED_OOO_LEFT_BUF);
+ break;
+ case TCP_EVENT_JOIN:
+ qed_ooo_add_new_buffer(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid,
+ iscsi_ooo->ooo_isle +
+ 1,
+ p_buffer,
+ QED_OOO_LEFT_BUF);
+ qed_ooo_join_isles(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid, iscsi_ooo->ooo_isle);
+ break;
+ case TCP_EVENT_ADD_PEN:
+ num_ooo_add_to_peninsula++;
+ qed_ooo_put_ready_buffer(p_hwfn,
+ p_hwfn->p_ooo_info,
+ p_buffer, true);
+ break;
+ }
+ } else {
+ DP_NOTICE(p_hwfn,
+ "Unexpected event (%d) TX OOO completion\n",
+ iscsi_ooo->ooo_opcode);
+ }
+ }
+
+ return 0;
+}
+
+static void
+qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn)
+{
+ struct qed_ooo_buffer *p_buffer;
+ int rc;
+ u16 l4_hdr_offset_w;
+ dma_addr_t first_frag;
+ u16 parse_flags;
+ u8 bd_flags;
+
+ /* Submit Tx buffers here */
+ while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,
+ p_hwfn->p_ooo_info))) {
+ l4_hdr_offset_w = 0;
+ bd_flags = 0;
+
+ first_frag = p_buffer->rx_buffer_phys_addr +
+ p_buffer->placement_offset;
+ parse_flags = p_buffer->parse_flags;
+ bd_flags = qed_ll2_convert_rx_parse_to_tx_flags(parse_flags);
+ SET_FIELD(bd_flags, CORE_TX_BD_FLAGS_FORCE_VLAN_MODE, 1);
+ SET_FIELD(bd_flags, CORE_TX_BD_FLAGS_L4_PROTOCOL, 1);
+
+ rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id, 1,
+ p_buffer->vlan, bd_flags,
+ l4_hdr_offset_w,
+ p_ll2_conn->tx_dest, 0,
+ first_frag,
+ p_buffer->packet_length,
+ p_buffer, true);
+ if (rc) {
+ qed_ooo_put_ready_buffer(p_hwfn, p_hwfn->p_ooo_info,
+ p_buffer, false);
+ break;
+ }
+ }
+}
+
+static void
+qed_ooo_submit_rx_buffers(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn)
+{
+ struct qed_ooo_buffer *p_buffer;
+ int rc;
+
+ while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
+ p_hwfn->p_ooo_info))) {
+ rc = qed_ll2_post_rx_buffer(p_hwfn,
+ p_ll2_conn->my_id,
+ p_buffer->rx_buffer_phys_addr,
+ 0, p_buffer, true);
+ if (rc) {
+ qed_ooo_put_free_buffer(p_hwfn,
+ p_hwfn->p_ooo_info, p_buffer);
+ break;
+ }
+ }
+}
+
+static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
+{
+ struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
+ int rc;
+
+ rc = qed_ll2_lb_rxq_handler(p_hwfn, p_ll2_conn);
+ if (rc)
+ return rc;
+
+ qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);
+ qed_ooo_submit_tx_buffers(p_hwfn, p_ll2_conn);
+
+ return 0;
+}
+
+static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
+{
+ struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
+ struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;
+ struct qed_ll2_tx_packet *p_pkt = NULL;
+ struct qed_ooo_buffer *p_buffer;
+ bool b_dont_submit_rx = false;
+ u16 new_idx = 0, num_bds = 0;
+ int rc;
+
+ new_idx = le16_to_cpu(*p_tx->p_fw_cons);
+ num_bds = ((s16)new_idx - (s16)p_tx->bds_idx);
+
+ if (!num_bds)
+ return 0;
+
+ while (num_bds) {
+ if (list_empty(&p_tx->active_descq))
+ return -EINVAL;
+
+ p_pkt = list_first_entry(&p_tx->active_descq,
+ struct qed_ll2_tx_packet, list_entry);
+ if (!p_pkt)
+ return -EINVAL;
+
+ if (p_pkt->bd_used != 1) {
+ DP_NOTICE(p_hwfn,
+ "Unexpectedly many BDs(%d) in TX OOO completion\n",
+ p_pkt->bd_used);
+ return -EINVAL;
+ }
+
+ list_del(&p_pkt->list_entry);
+
+ num_bds--;
+ p_tx->bds_idx++;
+ qed_chain_consume(&p_tx->txq_chain);
+
+ p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
+ list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
+
+ if (b_dont_submit_rx) {
+ qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,
+ p_buffer);
+ continue;
+ }
+
+ rc = qed_ll2_post_rx_buffer(p_hwfn, p_ll2_conn->my_id,
+ p_buffer->rx_buffer_phys_addr, 0,
+ p_buffer, true);
+ if (rc != 0) {
+ qed_ooo_put_free_buffer(p_hwfn,
+ p_hwfn->p_ooo_info, p_buffer);
+ b_dont_submit_rx = true;
+ }
+ }
+
+ qed_ooo_submit_tx_buffers(p_hwfn, p_ll2_conn);
+
+ return 0;
+}
+
+static int
+qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_info,
+ u16 rx_num_ooo_buffers, u16 mtu)
+{
+ struct qed_ooo_buffer *p_buf = NULL;
+ void *p_virt;
+ u16 buf_idx;
+ int rc = 0;
+
+ if (p_ll2_info->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ return rc;
+
+ if (!rx_num_ooo_buffers)
+ return -EINVAL;
+
+ for (buf_idx = 0; buf_idx < rx_num_ooo_buffers; buf_idx++) {
+ p_buf = kzalloc(sizeof(*p_buf), GFP_KERNEL);
+ if (!p_buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ p_buf->rx_buffer_size = mtu + 26 + ETH_CACHE_LINE_SIZE;
+ p_buf->rx_buffer_size = (p_buf->rx_buffer_size +
+ ETH_CACHE_LINE_SIZE - 1) &
+ ~(ETH_CACHE_LINE_SIZE - 1);
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ p_buf->rx_buffer_size,
+ &p_buf->rx_buffer_phys_addr,
+ GFP_KERNEL);
+ if (!p_virt) {
+ kfree(p_buf);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ p_buf->rx_buffer_virt_addr = p_virt;
+ qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info, p_buf);
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_LL2,
+ "Allocated [%04x] LL2 OOO buffers [each of size 0x%08x]\n",
+ rx_num_ooo_buffers, p_buf->rx_buffer_size);
+
+out:
+ return rc;
+}
+
+static void
+qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn)
+{
+ if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ return;
+
+ qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
+ qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);
+}
+
+static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn)
+{
+ struct qed_ooo_buffer *p_buffer;
+
+ if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+ return;
+
+ qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
+ while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
+ p_hwfn->p_ooo_info))) {
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ p_buffer->rx_buffer_size,
+ p_buffer->rx_buffer_virt_addr,
+ p_buffer->rx_buffer_phys_addr);
+ kfree(p_buffer);
+ }
+}
+
+static void qed_ll2_stop_ooo(struct qed_dev *cdev)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
+
+ DP_VERBOSE(cdev, QED_MSG_STORAGE, "Stopping LL2 OOO queue [%02x]\n",
+ *handle);
+
+ qed_ll2_terminate_connection(hwfn, *handle);
+ qed_ll2_release_connection(hwfn, *handle);
+ *handle = QED_LL2_UNUSED_HANDLE;
+}
+
+static int qed_ll2_start_ooo(struct qed_dev *cdev,
+ struct qed_ll2_params *params)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
+ struct qed_ll2_info *ll2_info;
+ int rc;
+
+ ll2_info = kzalloc(sizeof(*ll2_info), GFP_KERNEL);
+ if (!ll2_info)
+ return -ENOMEM;
+ ll2_info->conn_type = QED_LL2_TYPE_ISCSI_OOO;
+ ll2_info->mtu = params->mtu;
+ ll2_info->rx_drop_ttl0_flg = params->drop_ttl0_packets;
+ ll2_info->rx_vlan_removal_en = params->rx_vlan_stripping;
+ ll2_info->tx_tc = OOO_LB_TC;
+ ll2_info->tx_dest = CORE_TX_DEST_LB;
+
+ rc = qed_ll2_acquire_connection(hwfn, ll2_info,
+ QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
+ handle);
+ kfree(ll2_info);
+ if (rc) {
+ DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n");
+ goto out;
+ }
- b_last = list_empty(&p_rx->active_descq);
+ rc = qed_ll2_establish_connection(hwfn, *handle);
+ if (rc) {
+ DP_INFO(cdev, "Failed to establist LL2 OOO connection\n");
+ goto fail;
}
+
+ return 0;
+
+fail:
+ qed_ll2_release_connection(hwfn, *handle);
+out:
+ *handle = QED_LL2_UNUSED_HANDLE;
+ return rc;
}
+#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
+static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn,
+ void *p_cookie) { return -EINVAL; }
+static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn,
+ void *p_cookie) { return -EINVAL; }
+static inline int
+qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_info,
+ u16 rx_num_ooo_buffers, u16 mtu) { return 0; }
+static inline void
+qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn) { return; }
+static inline void
+qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
+ struct qed_ll2_info *p_ll2_conn) { return; }
+static inline void qed_ll2_stop_ooo(struct qed_dev *cdev) { return; }
+static inline int qed_ll2_start_ooo(struct qed_dev *cdev,
+ struct qed_ll2_params *params)
+ { return -EINVAL; }
+#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn,
@@ -588,7 +1043,8 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->drop_ttl0_flg = p_ll2_conn->rx_drop_ttl0_flg;
p_ramrod->inner_vlan_removal_en = p_ll2_conn->rx_vlan_removal_en;
p_ramrod->queue_id = p_ll2_conn->queue_id;
- p_ramrod->main_func_queue = 1;
+ p_ramrod->main_func_queue = (conn_type == QED_LL2_TYPE_ISCSI_OOO) ? 0
+ : 1;
if ((IS_MF_DEFAULT(p_hwfn) || IS_MF_SI(p_hwfn)) &&
p_ramrod->main_func_queue && (conn_type != QED_LL2_TYPE_ROCE)) {
@@ -619,6 +1075,11 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
return 0;
+ if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+ p_ll2_conn->tx_stats_en = 0;
+ else
+ p_ll2_conn->tx_stats_en = 1;
+
/* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
init_data.cid = p_ll2_conn->cid;
@@ -636,7 +1097,6 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));
p_ramrod->sb_index = p_tx->tx_sb_index;
p_ramrod->mtu = cpu_to_le16(p_ll2_conn->mtu);
- p_ll2_conn->tx_stats_en = 1;
p_ramrod->stats_en = p_ll2_conn->tx_stats_en;
p_ramrod->stats_id = p_ll2_conn->tx_stats_id;
@@ -860,9 +1320,19 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
if (rc)
goto q_allocate_fail;
+ rc = qed_ll2_acquire_connection_ooo(p_hwfn, p_ll2_info,
+ rx_num_desc * 2, p_params->mtu);
+ if (rc)
+ goto q_allocate_fail;
+
/* Register callbacks for the Rx/Tx queues */
- comp_rx_cb = qed_ll2_rxq_completion;
- comp_tx_cb = qed_ll2_txq_completion;
+ if (p_params->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+ comp_rx_cb = qed_ll2_lb_rxq_completion;
+ comp_tx_cb = qed_ll2_lb_txq_completion;
+ } else {
+ comp_rx_cb = qed_ll2_rxq_completion;
+ comp_tx_cb = qed_ll2_txq_completion;
+ }
if (rx_num_desc) {
qed_int_register_cb(p_hwfn, comp_rx_cb,
@@ -975,6 +1445,8 @@ int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
if (p_hwfn->hw_info.personality != QED_PCI_ETH_ROCE)
qed_wr(p_hwfn, p_hwfn->p_main_ptt, PRS_REG_USE_LIGHT_L2, 1);
+ qed_ll2_establish_connection_ooo(p_hwfn, p_ll2_conn);
+
return rc;
}
@@ -1213,6 +1685,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
u16 vlan,
u8 bd_flags,
u16 l4_hdr_offset_w,
+ enum qed_ll2_tx_dest e_tx_dest,
enum qed_ll2_roce_flavor_type qed_roce_flavor,
dma_addr_t first_frag,
u16 first_frag_len, void *cookie, u8 notify_fw)
@@ -1222,6 +1695,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
enum core_roce_flavor_type roce_flavor;
struct qed_ll2_tx_queue *p_tx;
struct qed_chain *p_tx_chain;
+ enum core_tx_dest tx_dest;
unsigned long flags;
int rc = 0;
@@ -1252,6 +1726,8 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
goto out;
}
+ tx_dest = e_tx_dest == QED_LL2_TX_DEST_NW ? CORE_TX_DEST_NW :
+ CORE_TX_DEST_LB;
if (qed_roce_flavor == QED_LL2_ROCE) {
roce_flavor = CORE_ROCE;
} else if (qed_roce_flavor == QED_LL2_RROCE) {
@@ -1266,7 +1742,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
num_of_bds, first_frag,
first_frag_len, cookie, notify_fw);
qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp,
- num_of_bds, CORE_TX_DEST_NW,
+ num_of_bds, tx_dest,
vlan, bd_flags, l4_hdr_offset_w,
roce_flavor,
first_frag, first_frag_len);
@@ -1341,6 +1817,9 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
qed_ll2_rxq_flush(p_hwfn, connection_handle);
}
+ if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+ qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
+
return rc;
}
@@ -1371,6 +1850,8 @@ void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
qed_cxt_release_cid(p_hwfn, p_ll2_conn->cid);
+ qed_ll2_release_connection_ooo(p_hwfn, p_ll2_conn);
+
mutex_lock(&p_ll2_conn->mutex);
p_ll2_conn->b_active = false;
mutex_unlock(&p_ll2_conn->mutex);
@@ -1517,6 +1998,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
enum qed_ll2_conn_type conn_type;
struct qed_ptt *p_ptt;
int rc, i;
+ u8 gsi_enable = 1;
/* Initialize LL2 locks & lists */
INIT_LIST_HEAD(&cdev->ll2->list);
@@ -1548,6 +2030,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
switch (QED_LEADING_HWFN(cdev)->hw_info.personality) {
case QED_PCI_ISCSI:
conn_type = QED_LL2_TYPE_ISCSI;
+ gsi_enable = 0;
break;
case QED_PCI_ETH_ROCE:
conn_type = QED_LL2_TYPE_ROCE;
@@ -1564,7 +2047,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
ll2_info.tx_tc = 0;
ll2_info.tx_dest = CORE_TX_DEST_NW;
- ll2_info.gsi_enable = 1;
+ ll2_info.gsi_enable = gsi_enable;
rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_info,
QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
@@ -1611,6 +2094,17 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
goto release_terminate;
}
+ if (cdev->hwfns[0].hw_info.personality == QED_PCI_ISCSI &&
+ cdev->hwfns[0].pf_params.iscsi_pf_params.ooo_enable) {
+ DP_VERBOSE(cdev, QED_MSG_STORAGE, "Starting OOO LL2 queue\n");
+ rc = qed_ll2_start_ooo(cdev, params);
+ if (rc) {
+ DP_INFO(cdev,
+ "Failed to initialize the OOO LL2 queue\n");
+ goto release_terminate;
+ }
+ }
+
p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
if (!p_ptt) {
DP_INFO(cdev, "Failed to acquire PTT\n");
@@ -1660,6 +2154,10 @@ static int qed_ll2_stop(struct qed_dev *cdev)
qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt);
eth_zero_addr(cdev->ll2_mac_address);
+ if (cdev->hwfns[0].hw_info.personality == QED_PCI_ISCSI &&
+ cdev->hwfns[0].pf_params.iscsi_pf_params.ooo_enable)
+ qed_ll2_stop_ooo(cdev);
+
rc = qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev),
cdev->ll2->handle);
if (rc)
@@ -1714,7 +2212,8 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev),
cdev->ll2->handle,
1 + skb_shinfo(skb)->nr_frags,
- vlan, flags, 0, 0 /* RoCE FLAVOR */,
+ vlan, flags, 0, QED_LL2_TX_DEST_NW,
+ 0 /* RoCE FLAVOR */,
mapping, skb->len, skb, 1);
if (rc)
goto err;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index 4e3d62a16cab..6625a3ae5a33 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -41,6 +41,12 @@ enum qed_ll2_conn_type {
MAX_QED_LL2_RX_CONN_TYPE
};
+enum qed_ll2_tx_dest {
+ QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
+ QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
+ QED_LL2_TX_DEST_MAX
+};
+
struct qed_ll2_rx_packet {
struct list_head list_entry;
struct core_rx_bd_with_buff_len *rxq_bd;
@@ -192,6 +198,8 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
* @param l4_hdr_offset_w L4 Header Offset from start of packet
* (in words). This is needed if both l4_csum
* and ipv6_ext are set
+ * @param e_tx_dest indicates if the packet is to be transmitted via
+ * loopback or to the network
* @param first_frag
* @param first_frag_len
* @param cookie
@@ -206,6 +214,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
u16 vlan,
u8 bd_flags,
u16 l4_hdr_offset_w,
+ enum qed_ll2_tx_dest e_tx_dest,
enum qed_ll2_roce_flavor_type qed_roce_flavor,
dma_addr_t first_frag,
u16 first_frag_len, void *cookie, u8 notify_fw);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 333c7442e48a..aeb98d8c5626 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -221,6 +221,10 @@ int qed_fill_dev_info(struct qed_dev *cdev,
dev_info->fw_eng = FW_ENGINEERING_VERSION;
dev_info->mf_mode = cdev->mf_mode;
dev_info->tx_switching = true;
+
+ if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support ==
+ QED_WOL_SUPPORT_PME)
+ dev_info->wol_support = true;
} else {
qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
&dev_info->fw_minor, &dev_info->fw_rev,
@@ -243,6 +247,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
&dev_info->mfw_rev, NULL);
}
+ dev_info->mtu = QED_LEADING_HWFN(cdev)->hw_info.mtu;
+
return 0;
}
@@ -1430,11 +1436,106 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
return status;
}
+static int qed_update_wol(struct qed_dev *cdev, bool enabled)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int rc = 0;
+
+ if (IS_VF(cdev))
+ return 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED
+ : QED_OV_WOL_DISABLED);
+ if (rc)
+ goto out;
+ rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
+
+out:
+ qed_ptt_release(hwfn, ptt);
+ return rc;
+}
+
+static int qed_update_drv_state(struct qed_dev *cdev, bool active)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int status = 0;
+
+ if (IS_VF(cdev))
+ return 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ?
+ QED_OV_DRIVER_STATE_ACTIVE :
+ QED_OV_DRIVER_STATE_DISABLED);
+
+ qed_ptt_release(hwfn, ptt);
+
+ return status;
+}
+
+static int qed_update_mac(struct qed_dev *cdev, u8 *mac)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int status = 0;
+
+ if (IS_VF(cdev))
+ return 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ status = qed_mcp_ov_update_mac(hwfn, ptt, mac);
+ if (status)
+ goto out;
+
+ status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
+
+out:
+ qed_ptt_release(hwfn, ptt);
+ return status;
+}
+
+static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int status = 0;
+
+ if (IS_VF(cdev))
+ return 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu);
+ if (status)
+ goto out;
+
+ status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
+
+out:
+ qed_ptt_release(hwfn, ptt);
+ return status;
+}
+
static struct qed_selftest_ops qed_selftest_ops_pass = {
.selftest_memory = &qed_selftest_memory,
.selftest_interrupt = &qed_selftest_interrupt,
.selftest_register = &qed_selftest_register,
.selftest_clock = &qed_selftest_clock,
+ .selftest_nvram = &qed_selftest_nvram,
};
const struct qed_common_ops qed_common_ops_pass = {
@@ -1464,6 +1565,10 @@ const struct qed_common_ops qed_common_ops_pass = {
.get_coalesce = &qed_get_coalesce,
.set_coalesce = &qed_set_coalesce,
.set_led = &qed_set_led,
+ .update_drv_state = &qed_update_drv_state,
+ .update_mac = &qed_update_mac,
+ .update_mtu = &qed_update_mtu,
+ .update_wol = &qed_update_wol,
};
void qed_get_protocol_stats(struct qed_dev *cdev,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index bdc9ba92f6d4..6dd3ce443484 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/etherdevice.h>
#include "qed.h"
#include "qed_dcbx.h"
#include "qed_hsi.h"
@@ -329,6 +330,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
struct qed_mcp_mb_params *p_mb_params)
{
u32 union_data_addr;
+
int rc;
/* MCP not initialized */
@@ -374,11 +376,32 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
u32 *o_mcp_param)
{
struct qed_mcp_mb_params mb_params;
+ union drv_union_data data_src;
int rc;
memset(&mb_params, 0, sizeof(mb_params));
+ memset(&data_src, 0, sizeof(data_src));
mb_params.cmd = cmd;
mb_params.param = param;
+
+ /* In case of UNLOAD_DONE, set the primary MAC */
+ if ((cmd == DRV_MSG_CODE_UNLOAD_DONE) &&
+ (p_hwfn->cdev->wol_config == QED_OV_WOL_ENABLED)) {
+ u8 *p_mac = p_hwfn->cdev->wol_mac;
+
+ data_src.wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1];
+ data_src.wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 |
+ p_mac[4] << 8 | p_mac[5];
+
+ DP_VERBOSE(p_hwfn,
+ (QED_MSG_SP | NETIF_MSG_IFDOWN),
+ "Setting WoL MAC: %pM --> [%08x,%08x]\n",
+ p_mac, data_src.wol_mac.mac_upper,
+ data_src.wol_mac.mac_lower);
+
+ mb_params.p_data_src = &data_src;
+ }
+
rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
if (rc)
return rc;
@@ -1001,28 +1024,89 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
return 0;
}
+/* Old MFW has a global configuration for all PFs regarding RDMA support */
+static void
+qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn,
+ enum qed_pci_personality *p_proto)
+{
+ /* There wasn't ever a legacy MFW that published iwarp.
+ * So at this point, this is either plain l2 or RoCE.
+ */
+ if (test_bit(QED_DEV_CAP_ROCE, &p_hwfn->hw_info.device_capabilities))
+ *p_proto = QED_PCI_ETH_ROCE;
+ else
+ *p_proto = QED_PCI_ETH;
+
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP,
+ "According to Legacy capabilities, L2 personality is %08x\n",
+ (u32) *p_proto);
+}
+
+static int
+qed_mcp_get_shmem_proto_mfw(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_pci_personality *p_proto)
+{
+ u32 resp = 0, param = 0;
+ int rc;
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL, 0, &resp, &param);
+ if (rc)
+ return rc;
+ if (resp != FW_MSG_CODE_OK) {
+ DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP,
+ "MFW lacks support for command; Returns %08x\n",
+ resp);
+ return -EINVAL;
+ }
+
+ switch (param) {
+ case FW_MB_PARAM_GET_PF_RDMA_NONE:
+ *p_proto = QED_PCI_ETH;
+ break;
+ case FW_MB_PARAM_GET_PF_RDMA_ROCE:
+ *p_proto = QED_PCI_ETH_ROCE;
+ break;
+ case FW_MB_PARAM_GET_PF_RDMA_BOTH:
+ DP_NOTICE(p_hwfn,
+ "Current day drivers don't support RoCE & iWARP. Default to RoCE-only\n");
+ *p_proto = QED_PCI_ETH_ROCE;
+ break;
+ case FW_MB_PARAM_GET_PF_RDMA_IWARP:
+ default:
+ DP_NOTICE(p_hwfn,
+ "MFW answers GET_PF_RDMA_PROTOCOL but param is %08x\n",
+ param);
+ return -EINVAL;
+ }
+
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_IFUP,
+ "According to capabilities, L2 personality is %08x [resp %08x param %08x]\n",
+ (u32) *p_proto, resp, param);
+ return 0;
+}
+
static int
qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
struct public_func *p_info,
+ struct qed_ptt *p_ptt,
enum qed_pci_personality *p_proto)
{
int rc = 0;
switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) {
case FUNC_MF_CFG_PROTOCOL_ETHERNET:
- if (test_bit(QED_DEV_CAP_ROCE,
- &p_hwfn->hw_info.device_capabilities))
- *p_proto = QED_PCI_ETH_ROCE;
- else
- *p_proto = QED_PCI_ETH;
+ if (qed_mcp_get_shmem_proto_mfw(p_hwfn, p_ptt, p_proto))
+ qed_mcp_get_shmem_proto_legacy(p_hwfn, p_proto);
break;
case FUNC_MF_CFG_PROTOCOL_ISCSI:
*p_proto = QED_PCI_ISCSI;
break;
case FUNC_MF_CFG_PROTOCOL_ROCE:
DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n");
- rc = -EINVAL;
- break;
+ /* Fallthrough */
default:
rc = -EINVAL;
}
@@ -1042,7 +1126,8 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
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)) {
+ if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, p_ptt,
+ &info->protocol)) {
DP_ERR(p_hwfn, "Unknown personality %08x\n",
(u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK));
return -EINVAL;
@@ -1057,6 +1142,9 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
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);
+
+ /* Store primary MAC for later possible WoL */
+ memcpy(&p_hwfn->cdev->wol_mac, info->mac, ETH_ALEN);
} else {
DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n");
}
@@ -1068,13 +1156,30 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
+ info->mtu = (u16)shmem_info.mtu_size;
+
+ p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_NONE;
+ p_hwfn->cdev->wol_config = (u8)QED_OV_WOL_DEFAULT;
+ if (qed_mcp_is_init(p_hwfn)) {
+ u32 resp = 0, param = 0;
+ int rc;
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_OS_WOL, 0, &resp, &param);
+ if (rc)
+ return rc;
+ if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED)
+ p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_PME;
+ }
+
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",
+ "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 wol %02x\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);
+ info->wwn_port, info->wwn_node,
+ info->ovlan, (u8)p_hwfn->hw_info.b_wol_support);
return 0;
}
@@ -1223,6 +1328,178 @@ int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0;
}
+int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_client client)
+{
+ u32 resp = 0, param = 0;
+ u32 drv_mb_param;
+ int rc;
+
+ switch (client) {
+ case QED_OV_CLIENT_DRV:
+ drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OS;
+ break;
+ case QED_OV_CLIENT_USER:
+ drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_OTHER;
+ break;
+ case QED_OV_CLIENT_VENDOR_SPEC:
+ drv_mb_param = DRV_MB_PARAM_OV_CURR_CFG_VENDOR_SPEC;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Invalid client type %d\n", client);
+ return -EINVAL;
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_CURR_CFG,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_ERR(p_hwfn, "MCP response failure, aborting\n");
+
+ return rc;
+}
+
+int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_driver_state drv_state)
+{
+ u32 resp = 0, param = 0;
+ u32 drv_mb_param;
+ int rc;
+
+ switch (drv_state) {
+ case QED_OV_DRIVER_STATE_NOT_LOADED:
+ drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_NOT_LOADED;
+ break;
+ case QED_OV_DRIVER_STATE_DISABLED:
+ drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_DISABLED;
+ break;
+ case QED_OV_DRIVER_STATE_ACTIVE:
+ drv_mb_param = DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE_ACTIVE;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Invalid driver state %d\n", drv_state);
+ return -EINVAL;
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_DRIVER_STATE,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_ERR(p_hwfn, "Failed to send driver state\n");
+
+ return rc;
+}
+
+int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u16 mtu)
+{
+ u32 resp = 0, param = 0;
+ u32 drv_mb_param;
+ int rc;
+
+ drv_mb_param = (u32)mtu << DRV_MB_PARAM_OV_MTU_SIZE_SHIFT;
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_MTU,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_ERR(p_hwfn, "Failed to send mtu value, rc = %d\n", rc);
+
+ return rc;
+}
+
+int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u8 *mac)
+{
+ struct qed_mcp_mb_params mb_params;
+ union drv_union_data union_data;
+ int rc;
+
+ memset(&mb_params, 0, sizeof(mb_params));
+ mb_params.cmd = DRV_MSG_CODE_SET_VMAC;
+ mb_params.param = DRV_MSG_CODE_VMAC_TYPE_MAC <<
+ DRV_MSG_CODE_VMAC_TYPE_SHIFT;
+ mb_params.param |= MCP_PF_ID(p_hwfn);
+ ether_addr_copy(&union_data.raw_data[0], mac);
+ mb_params.p_data_src = &union_data;
+ rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+ if (rc)
+ DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc);
+
+ /* Store primary MAC for later possible WoL */
+ memcpy(p_hwfn->cdev->wol_mac, mac, ETH_ALEN);
+
+ return rc;
+}
+
+int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, enum qed_ov_wol wol)
+{
+ u32 resp = 0, param = 0;
+ u32 drv_mb_param;
+ int rc;
+
+ if (p_hwfn->hw_info.b_wol_support == QED_WOL_SUPPORT_NONE) {
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "Can't change WoL configuration when WoL isn't supported\n");
+ return -EINVAL;
+ }
+
+ switch (wol) {
+ case QED_OV_WOL_DEFAULT:
+ drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT;
+ break;
+ case QED_OV_WOL_DISABLED:
+ drv_mb_param = DRV_MB_PARAM_WOL_DISABLED;
+ break;
+ case QED_OV_WOL_ENABLED:
+ drv_mb_param = DRV_MB_PARAM_WOL_ENABLED;
+ break;
+ default:
+ DP_ERR(p_hwfn, "Invalid wol state %d\n", wol);
+ return -EINVAL;
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_WOL,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc);
+
+ /* Store the WoL update for a future unload */
+ p_hwfn->cdev->wol_config = (u8)wol;
+
+ return rc;
+}
+
+int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_eswitch eswitch)
+{
+ u32 resp = 0, param = 0;
+ u32 drv_mb_param;
+ int rc;
+
+ switch (eswitch) {
+ case QED_OV_ESWITCH_NONE:
+ drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_NONE;
+ break;
+ case QED_OV_ESWITCH_VEB:
+ drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEB;
+ break;
+ case QED_OV_ESWITCH_VEPA:
+ drv_mb_param = DRV_MB_PARAM_ESWITCH_MODE_VEPA;
+ break;
+ default:
+ DP_ERR(p_hwfn, "Invalid eswitch mode %d\n", eswitch);
+ return -EINVAL;
+ }
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_ERR(p_hwfn, "Failed to send eswitch mode, rc = %d\n", rc);
+
+ return rc;
+}
+
int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, enum qed_led_mode mode)
{
@@ -1271,6 +1548,52 @@ int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn,
return rc;
}
+int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len)
+{
+ u32 bytes_left = len, offset = 0, bytes_to_copy, read_len = 0;
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ u32 resp = 0, resp_param = 0;
+ struct qed_ptt *p_ptt;
+ int rc = 0;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+
+ while (bytes_left > 0) {
+ bytes_to_copy = min_t(u32, bytes_left, MCP_DRV_NVM_BUF_LEN);
+
+ rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_NVM_READ_NVRAM,
+ addr + offset +
+ (bytes_to_copy <<
+ DRV_MB_PARAM_NVM_LEN_SHIFT),
+ &resp, &resp_param,
+ &read_len,
+ (u32 *)(p_buf + offset));
+
+ if (rc || (resp != FW_MSG_CODE_NVM_OK)) {
+ DP_NOTICE(cdev, "MCP command rc = %d\n", rc);
+ break;
+ }
+
+ /* This can be a lengthy process, and it's possible scheduler
+ * isn't preemptable. Sleep a bit to prevent CPU hogging.
+ */
+ if (bytes_left % 0x1000 <
+ (bytes_left - read_len) % 0x1000)
+ usleep_range(1000, 2000);
+
+ offset += read_len;
+ bytes_left -= read_len;
+ }
+
+ cdev->mcp_nvm_resp = resp;
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return rc;
+}
+
int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 drv_mb_param = 0, rsp, param;
@@ -1312,3 +1635,101 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
return rc;
}
+
+int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *num_images)
+{
+ u32 drv_mb_param = 0, rsp;
+ int rc = 0;
+
+ drv_mb_param = (DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES <<
+ DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+ drv_mb_param, &rsp, num_images);
+ if (rc)
+ return rc;
+
+ if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
+ rc = -EINVAL;
+
+ return rc;
+}
+
+int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct bist_nvm_image_att *p_image_att,
+ u32 image_index)
+{
+ u32 buf_size = 0, param, resp = 0, resp_param = 0;
+ int rc;
+
+ param = DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX <<
+ DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT;
+ param |= image_index << DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT;
+
+ rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_BIST_TEST, param,
+ &resp, &resp_param,
+ &buf_size,
+ (u32 *)p_image_att);
+ if (rc)
+ return rc;
+
+ if (((resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
+ (p_image_att->return_code != 1))
+ rc = -EINVAL;
+
+ return rc;
+}
+
+#define QED_RESC_ALLOC_VERSION_MAJOR 1
+#define QED_RESC_ALLOC_VERSION_MINOR 0
+#define QED_RESC_ALLOC_VERSION \
+ ((QED_RESC_ALLOC_VERSION_MAJOR << \
+ DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT) | \
+ (QED_RESC_ALLOC_VERSION_MINOR << \
+ DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT))
+int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct resource_info *p_resc_info,
+ u32 *p_mcp_resp, u32 *p_mcp_param)
+{
+ struct qed_mcp_mb_params mb_params;
+ union drv_union_data union_data;
+ int rc;
+
+ memset(&mb_params, 0, sizeof(mb_params));
+ memset(&union_data, 0, sizeof(union_data));
+ mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
+ mb_params.param = QED_RESC_ALLOC_VERSION;
+
+ /* Need to have a sufficient large struct, as the cmd_and_union
+ * is going to do memcpy from and to it.
+ */
+ memcpy(&union_data.resource, p_resc_info, sizeof(*p_resc_info));
+
+ mb_params.p_data_src = &union_data;
+ mb_params.p_data_dst = &union_data;
+ rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+ if (rc)
+ return rc;
+
+ /* Copy the data back */
+ memcpy(p_resc_info, &union_data.resource, sizeof(*p_resc_info));
+ *p_mcp_resp = mb_params.mcp_resp;
+ *p_mcp_param = mb_params.mcp_param;
+
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_SP,
+ "MFW resource_info: version 0x%x, res_id 0x%x, size 0x%x, offset 0x%x, vf_size 0x%x, vf_offset 0x%x, flags 0x%x\n",
+ *p_mcp_param,
+ p_resc_info->res_id,
+ p_resc_info->size,
+ p_resc_info->offset,
+ p_resc_info->vf_size,
+ p_resc_info->vf_offset, p_resc_info->flags);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index dff520ed069b..407a2c1830fb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -92,6 +92,8 @@ struct qed_mcp_function_info {
#define QED_MCP_VLAN_UNSET (0xffff)
u16 ovlan;
+
+ u16 mtu;
};
struct qed_mcp_nvm_common {
@@ -147,6 +149,30 @@ union qed_mcp_protocol_stats {
struct qed_mcp_rdma_stats rdma_stats;
};
+enum qed_ov_eswitch {
+ QED_OV_ESWITCH_NONE,
+ QED_OV_ESWITCH_VEB,
+ QED_OV_ESWITCH_VEPA
+};
+
+enum qed_ov_client {
+ QED_OV_CLIENT_DRV,
+ QED_OV_CLIENT_USER,
+ QED_OV_CLIENT_VENDOR_SPEC
+};
+
+enum qed_ov_driver_state {
+ QED_OV_DRIVER_STATE_NOT_LOADED,
+ QED_OV_DRIVER_STATE_DISABLED,
+ QED_OV_DRIVER_STATE_ACTIVE
+};
+
+enum qed_ov_wol {
+ QED_OV_WOL_DEFAULT,
+ QED_OV_WOL_DISABLED,
+ QED_OV_WOL_ENABLED
+};
+
/**
* @brief - returns the link params of the hw function
*
@@ -278,6 +304,69 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
struct qed_mcp_drv_version *p_ver);
/**
+ * @brief Notify MFW about the change in base device properties
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param client - qed client type
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_client client);
+
+/**
+ * @brief Notify MFW about the driver state
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param drv_state - Driver state
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_driver_state(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_driver_state drv_state);
+
+/**
+ * @brief Send MTU size to MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param mtu - MTU size
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u16 mtu);
+
+/**
+ * @brief Send MAC address to MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param mac - MAC address
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u8 *mac);
+
+/**
+ * @brief Send WOL mode to MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param wol - WOL mode
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_wol wol);
+
+/**
* @brief Set LED status
*
* @param p_hwfn
@@ -291,6 +380,18 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
enum qed_led_mode mode);
/**
+ * @brief Read from nvm
+ *
+ * @param cdev
+ * @param addr - nvm offset
+ * @param p_buf - nvm read buffer
+ * @param len - buffer len
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len);
+
+/**
* @brief Bist register test
*
* @param p_hwfn - hw function
@@ -312,6 +413,35 @@ int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn,
int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt);
+/**
+ * @brief Bist nvm test - get number of images
+ *
+ * @param p_hwfn - hw function
+ * @param p_ptt - PTT required for register access
+ * @param num_images - number of images if operation was
+ * successful. 0 if not.
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *num_images);
+
+/**
+ * @brief Bist nvm test - get image attributes by index
+ *
+ * @param p_hwfn - hw function
+ * @param p_ptt - PTT required for register access
+ * @param p_image_att - Attributes of image
+ * @param image_index - Index of image to get information for
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct bist_nvm_image_att *p_image_att,
+ u32 image_index);
+
/* 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
@@ -546,4 +676,32 @@ int __qed_configure_pf_min_bandwidth(struct qed_hwfn *p_hwfn,
int qed_mcp_mask_parities(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u32 mask_parities);
+/**
+ * @brief Send eswitch mode to MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param eswitch - eswitch mode
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_ov_update_eswitch(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ enum qed_ov_eswitch eswitch);
+
+/**
+ * @brief - Gets the MFW allocation info for the given resource
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param p_resc_info - descriptor of requested resource
+ * @param p_mcp_resp
+ * @param p_mcp_param
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct resource_info *p_resc_info,
+ u32 *p_mcp_resp, u32 *p_mcp_param);
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ooo.c b/drivers/net/ethernet/qlogic/qed/qed_ooo.c
new file mode 100644
index 000000000000..155abcb507fd
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_ooo.c
@@ -0,0 +1,501 @@
+/* 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/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "qed.h"
+#include "qed_iscsi.h"
+#include "qed_ll2.h"
+#include "qed_ooo.h"
+
+static struct qed_ooo_archipelago
+*qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info
+ *p_ooo_info,
+ u32 cid)
+{
+ struct qed_ooo_archipelago *p_archipelago = NULL;
+
+ list_for_each_entry(p_archipelago,
+ &p_ooo_info->archipelagos_list, list_entry) {
+ if (p_archipelago->cid == cid)
+ return p_archipelago;
+ }
+
+ return NULL;
+}
+
+static struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 isle)
+{
+ struct qed_ooo_archipelago *p_archipelago = NULL;
+ struct qed_ooo_isle *p_isle = NULL;
+ u8 the_num_of_isle = 1;
+
+ p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
+ if (!p_archipelago) {
+ DP_NOTICE(p_hwfn,
+ "Connection %d is not found in OOO list\n", cid);
+ return NULL;
+ }
+
+ list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) {
+ if (the_num_of_isle == isle)
+ return p_isle;
+ the_num_of_isle++;
+ }
+
+ return NULL;
+}
+
+void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct ooo_opaque *p_cqe)
+{
+ struct qed_ooo_history *p_history = &p_ooo_info->ooo_history;
+
+ if (p_history->head_idx == p_history->num_of_cqes)
+ p_history->head_idx = 0;
+ p_history->p_cqes[p_history->head_idx] = *p_cqe;
+ p_history->head_idx++;
+}
+
+struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn)
+{
+ struct qed_ooo_info *p_ooo_info;
+ u16 max_num_archipelagos = 0;
+ u16 max_num_isles = 0;
+ u32 i;
+
+ if (p_hwfn->hw_info.personality != QED_PCI_ISCSI) {
+ DP_NOTICE(p_hwfn,
+ "Failed to allocate qed_ooo_info: unknown personality\n");
+ return NULL;
+ }
+
+ max_num_archipelagos = p_hwfn->pf_params.iscsi_pf_params.num_cons;
+ max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos;
+
+ if (!max_num_archipelagos) {
+ DP_NOTICE(p_hwfn,
+ "Failed to allocate qed_ooo_info: unknown amount of connections\n");
+ return NULL;
+ }
+
+ p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL);
+ if (!p_ooo_info)
+ return NULL;
+
+ INIT_LIST_HEAD(&p_ooo_info->free_buffers_list);
+ INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list);
+ INIT_LIST_HEAD(&p_ooo_info->free_isles_list);
+ INIT_LIST_HEAD(&p_ooo_info->free_archipelagos_list);
+ INIT_LIST_HEAD(&p_ooo_info->archipelagos_list);
+
+ p_ooo_info->p_isles_mem = kcalloc(max_num_isles,
+ sizeof(struct qed_ooo_isle),
+ GFP_KERNEL);
+ if (!p_ooo_info->p_isles_mem)
+ goto no_isles_mem;
+
+ for (i = 0; i < max_num_isles; i++) {
+ INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list);
+ list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry,
+ &p_ooo_info->free_isles_list);
+ }
+
+ p_ooo_info->p_archipelagos_mem =
+ kcalloc(max_num_archipelagos,
+ sizeof(struct qed_ooo_archipelago),
+ GFP_KERNEL);
+ if (!p_ooo_info->p_archipelagos_mem)
+ goto no_archipelagos_mem;
+
+ for (i = 0; i < max_num_archipelagos; i++) {
+ INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list);
+ list_add_tail(&p_ooo_info->p_archipelagos_mem[i].list_entry,
+ &p_ooo_info->free_archipelagos_list);
+ }
+
+ p_ooo_info->ooo_history.p_cqes =
+ kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES,
+ sizeof(struct ooo_opaque),
+ GFP_KERNEL);
+ if (!p_ooo_info->ooo_history.p_cqes)
+ goto no_history_mem;
+
+ return p_ooo_info;
+
+no_history_mem:
+ kfree(p_ooo_info->p_archipelagos_mem);
+no_archipelagos_mem:
+ kfree(p_ooo_info->p_isles_mem);
+no_isles_mem:
+ kfree(p_ooo_info);
+ return NULL;
+}
+
+void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info, u32 cid)
+{
+ struct qed_ooo_archipelago *p_archipelago;
+ struct qed_ooo_buffer *p_buffer;
+ struct qed_ooo_isle *p_isle;
+ bool b_found = false;
+
+ if (list_empty(&p_ooo_info->archipelagos_list))
+ return;
+
+ list_for_each_entry(p_archipelago,
+ &p_ooo_info->archipelagos_list, list_entry) {
+ if (p_archipelago->cid == cid) {
+ list_del(&p_archipelago->list_entry);
+ b_found = true;
+ break;
+ }
+ }
+
+ if (!b_found)
+ return;
+
+ while (!list_empty(&p_archipelago->isles_list)) {
+ p_isle = list_first_entry(&p_archipelago->isles_list,
+ struct qed_ooo_isle, list_entry);
+
+ list_del(&p_isle->list_entry);
+
+ while (!list_empty(&p_isle->buffers_list)) {
+ p_buffer = list_first_entry(&p_isle->buffers_list,
+ struct qed_ooo_buffer,
+ list_entry);
+
+ if (!p_buffer)
+ break;
+
+ list_del(&p_buffer->list_entry);
+ list_add_tail(&p_buffer->list_entry,
+ &p_ooo_info->free_buffers_list);
+ }
+ list_add_tail(&p_isle->list_entry,
+ &p_ooo_info->free_isles_list);
+ }
+
+ list_add_tail(&p_archipelago->list_entry,
+ &p_ooo_info->free_archipelagos_list);
+}
+
+void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info)
+{
+ struct qed_ooo_archipelago *p_arch;
+ struct qed_ooo_buffer *p_buffer;
+ struct qed_ooo_isle *p_isle;
+
+ while (!list_empty(&p_ooo_info->archipelagos_list)) {
+ p_arch = list_first_entry(&p_ooo_info->archipelagos_list,
+ struct qed_ooo_archipelago,
+ list_entry);
+
+ list_del(&p_arch->list_entry);
+
+ while (!list_empty(&p_arch->isles_list)) {
+ p_isle = list_first_entry(&p_arch->isles_list,
+ struct qed_ooo_isle,
+ list_entry);
+
+ list_del(&p_isle->list_entry);
+
+ while (!list_empty(&p_isle->buffers_list)) {
+ p_buffer =
+ list_first_entry(&p_isle->buffers_list,
+ struct qed_ooo_buffer,
+ list_entry);
+
+ if (!p_buffer)
+ break;
+
+ list_del(&p_buffer->list_entry);
+ list_add_tail(&p_buffer->list_entry,
+ &p_ooo_info->free_buffers_list);
+ }
+ list_add_tail(&p_isle->list_entry,
+ &p_ooo_info->free_isles_list);
+ }
+ list_add_tail(&p_arch->list_entry,
+ &p_ooo_info->free_archipelagos_list);
+ }
+ if (!list_empty(&p_ooo_info->ready_buffers_list))
+ list_splice_tail_init(&p_ooo_info->ready_buffers_list,
+ &p_ooo_info->free_buffers_list);
+}
+
+void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info)
+{
+ qed_ooo_release_all_isles(p_hwfn, p_ooo_info);
+ memset(p_ooo_info->ooo_history.p_cqes, 0,
+ p_ooo_info->ooo_history.num_of_cqes *
+ sizeof(struct ooo_opaque));
+ p_ooo_info->ooo_history.head_idx = 0;
+}
+
+void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info)
+{
+ struct qed_ooo_buffer *p_buffer;
+
+ qed_ooo_release_all_isles(p_hwfn, p_ooo_info);
+ while (!list_empty(&p_ooo_info->free_buffers_list)) {
+ p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
+ struct qed_ooo_buffer, list_entry);
+
+ if (!p_buffer)
+ break;
+
+ list_del(&p_buffer->list_entry);
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+ p_buffer->rx_buffer_size,
+ p_buffer->rx_buffer_virt_addr,
+ p_buffer->rx_buffer_phys_addr);
+ kfree(p_buffer);
+ }
+
+ kfree(p_ooo_info->p_isles_mem);
+ kfree(p_ooo_info->p_archipelagos_mem);
+ kfree(p_ooo_info->ooo_history.p_cqes);
+ kfree(p_ooo_info);
+}
+
+void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer)
+{
+ list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list);
+}
+
+struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info)
+{
+ struct qed_ooo_buffer *p_buffer = NULL;
+
+ if (!list_empty(&p_ooo_info->free_buffers_list)) {
+ p_buffer = list_first_entry(&p_ooo_info->free_buffers_list,
+ struct qed_ooo_buffer, list_entry);
+
+ list_del(&p_buffer->list_entry);
+ }
+
+ return p_buffer;
+}
+
+void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer, u8 on_tail)
+{
+ if (on_tail)
+ list_add_tail(&p_buffer->list_entry,
+ &p_ooo_info->ready_buffers_list);
+ else
+ list_add(&p_buffer->list_entry,
+ &p_ooo_info->ready_buffers_list);
+}
+
+struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info)
+{
+ struct qed_ooo_buffer *p_buffer = NULL;
+
+ if (!list_empty(&p_ooo_info->ready_buffers_list)) {
+ p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list,
+ struct qed_ooo_buffer, list_entry);
+
+ list_del(&p_buffer->list_entry);
+ }
+
+ return p_buffer;
+}
+
+void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 drop_isle, u8 drop_size)
+{
+ struct qed_ooo_archipelago *p_archipelago = NULL;
+ struct qed_ooo_isle *p_isle = NULL;
+ u8 isle_idx;
+
+ p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
+ for (isle_idx = 0; isle_idx < drop_size; isle_idx++) {
+ p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle);
+ if (!p_isle) {
+ DP_NOTICE(p_hwfn,
+ "Isle %d is not found(cid %d)\n",
+ drop_isle, cid);
+ return;
+ }
+ if (list_empty(&p_isle->buffers_list))
+ DP_NOTICE(p_hwfn,
+ "Isle %d is empty(cid %d)\n", drop_isle, cid);
+ else
+ list_splice_tail_init(&p_isle->buffers_list,
+ &p_ooo_info->free_buffers_list);
+
+ list_del(&p_isle->list_entry);
+ p_ooo_info->cur_isles_number--;
+ list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list);
+ }
+
+ if (list_empty(&p_archipelago->isles_list)) {
+ list_del(&p_archipelago->list_entry);
+ list_add(&p_archipelago->list_entry,
+ &p_ooo_info->free_archipelagos_list);
+ }
+}
+
+void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 ooo_isle,
+ struct qed_ooo_buffer *p_buffer)
+{
+ struct qed_ooo_archipelago *p_archipelago = NULL;
+ struct qed_ooo_isle *p_prev_isle = NULL;
+ struct qed_ooo_isle *p_isle = NULL;
+
+ if (ooo_isle > 1) {
+ p_prev_isle = qed_ooo_seek_isle(p_hwfn,
+ p_ooo_info, cid, ooo_isle - 1);
+ if (!p_prev_isle) {
+ DP_NOTICE(p_hwfn,
+ "Isle %d is not found(cid %d)\n",
+ ooo_isle - 1, cid);
+ return;
+ }
+ }
+ p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
+ if (!p_archipelago && (ooo_isle != 1)) {
+ DP_NOTICE(p_hwfn,
+ "Connection %d is not found in OOO list\n", cid);
+ return;
+ }
+
+ if (!list_empty(&p_ooo_info->free_isles_list)) {
+ p_isle = list_first_entry(&p_ooo_info->free_isles_list,
+ struct qed_ooo_isle, list_entry);
+
+ list_del(&p_isle->list_entry);
+ if (!list_empty(&p_isle->buffers_list)) {
+ DP_NOTICE(p_hwfn, "Free isle is not empty\n");
+ INIT_LIST_HEAD(&p_isle->buffers_list);
+ }
+ } else {
+ DP_NOTICE(p_hwfn, "No more free isles\n");
+ return;
+ }
+
+ if (!p_archipelago &&
+ !list_empty(&p_ooo_info->free_archipelagos_list)) {
+ p_archipelago =
+ list_first_entry(&p_ooo_info->free_archipelagos_list,
+ struct qed_ooo_archipelago, list_entry);
+
+ list_del(&p_archipelago->list_entry);
+ if (!list_empty(&p_archipelago->isles_list)) {
+ DP_NOTICE(p_hwfn,
+ "Free OOO connection is not empty\n");
+ INIT_LIST_HEAD(&p_archipelago->isles_list);
+ }
+ p_archipelago->cid = cid;
+ list_add(&p_archipelago->list_entry,
+ &p_ooo_info->archipelagos_list);
+ } else if (!p_archipelago) {
+ DP_NOTICE(p_hwfn, "No more free OOO connections\n");
+ list_add(&p_isle->list_entry,
+ &p_ooo_info->free_isles_list);
+ list_add(&p_buffer->list_entry,
+ &p_ooo_info->free_buffers_list);
+ return;
+ }
+
+ list_add(&p_buffer->list_entry, &p_isle->buffers_list);
+ p_ooo_info->cur_isles_number++;
+ p_ooo_info->gen_isles_number++;
+
+ if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number)
+ p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number;
+
+ if (!p_prev_isle)
+ list_add(&p_isle->list_entry, &p_archipelago->isles_list);
+ else
+ list_add(&p_isle->list_entry, &p_prev_isle->list_entry);
+}
+
+void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid,
+ u8 ooo_isle,
+ struct qed_ooo_buffer *p_buffer, u8 buffer_side)
+{
+ struct qed_ooo_isle *p_isle = NULL;
+
+ p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle);
+ if (!p_isle) {
+ DP_NOTICE(p_hwfn,
+ "Isle %d is not found(cid %d)\n", ooo_isle, cid);
+ return;
+ }
+
+ if (buffer_side == QED_OOO_LEFT_BUF)
+ list_add(&p_buffer->list_entry, &p_isle->buffers_list);
+ else
+ list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list);
+}
+
+void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle)
+{
+ struct qed_ooo_archipelago *p_archipelago = NULL;
+ struct qed_ooo_isle *p_right_isle = NULL;
+ struct qed_ooo_isle *p_left_isle = NULL;
+
+ p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
+ left_isle + 1);
+ if (!p_right_isle) {
+ DP_NOTICE(p_hwfn,
+ "Right isle %d is not found(cid %d)\n",
+ left_isle + 1, cid);
+ return;
+ }
+
+ p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid);
+ list_del(&p_right_isle->list_entry);
+ p_ooo_info->cur_isles_number--;
+ if (left_isle) {
+ p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid,
+ left_isle);
+ if (!p_left_isle) {
+ DP_NOTICE(p_hwfn,
+ "Left isle %d is not found(cid %d)\n",
+ left_isle, cid);
+ return;
+ }
+ list_splice_tail_init(&p_right_isle->buffers_list,
+ &p_left_isle->buffers_list);
+ } else {
+ list_splice_tail_init(&p_right_isle->buffers_list,
+ &p_ooo_info->ready_buffers_list);
+ if (list_empty(&p_archipelago->isles_list)) {
+ list_del(&p_archipelago->list_entry);
+ list_add(&p_archipelago->list_entry,
+ &p_ooo_info->free_archipelagos_list);
+ }
+ }
+ list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list);
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ooo.h b/drivers/net/ethernet/qlogic/qed/qed_ooo.h
new file mode 100644
index 000000000000..7a0670a9a074
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qed/qed_ooo.h
@@ -0,0 +1,176 @@
+/* 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_OOO_H
+#define _QED_OOO_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "qed.h"
+
+#define QED_MAX_NUM_ISLES 256
+#define QED_MAX_NUM_OOO_HISTORY_ENTRIES 512
+
+#define QED_OOO_LEFT_BUF 0
+#define QED_OOO_RIGHT_BUF 1
+
+struct qed_ooo_buffer {
+ struct list_head list_entry;
+ void *rx_buffer_virt_addr;
+ dma_addr_t rx_buffer_phys_addr;
+ u32 rx_buffer_size;
+ u16 packet_length;
+ u16 parse_flags;
+ u16 vlan;
+ u8 placement_offset;
+};
+
+struct qed_ooo_isle {
+ struct list_head list_entry;
+ struct list_head buffers_list;
+};
+
+struct qed_ooo_archipelago {
+ struct list_head list_entry;
+ struct list_head isles_list;
+ u32 cid;
+};
+
+struct qed_ooo_history {
+ struct ooo_opaque *p_cqes;
+ u32 head_idx;
+ u32 num_of_cqes;
+};
+
+struct qed_ooo_info {
+ struct list_head free_buffers_list;
+ struct list_head ready_buffers_list;
+ struct list_head free_isles_list;
+ struct list_head free_archipelagos_list;
+ struct list_head archipelagos_list;
+ struct qed_ooo_archipelago *p_archipelagos_mem;
+ struct qed_ooo_isle *p_isles_mem;
+ struct qed_ooo_history ooo_history;
+ u32 cur_isles_number;
+ u32 max_isles_number;
+ u32 gen_isles_number;
+};
+
+#if IS_ENABLED(CONFIG_QED_ISCSI)
+void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct ooo_opaque *p_cqe);
+
+struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn);
+
+void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid);
+
+void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info);
+
+void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info);
+
+void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info);
+
+void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer);
+
+struct qed_ooo_buffer *
+qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info);
+
+void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer, u8 on_tail);
+
+struct qed_ooo_buffer *
+qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info);
+
+void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 drop_isle, u8 drop_size);
+
+void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid,
+ u8 ooo_isle, struct qed_ooo_buffer *p_buffer);
+
+void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid,
+ u8 ooo_isle,
+ struct qed_ooo_buffer *p_buffer, u8 buffer_side);
+
+void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info, u32 cid,
+ u8 left_isle);
+#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
+static inline void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct ooo_opaque *p_cqe) {}
+
+static inline struct qed_ooo_info *qed_ooo_alloc(
+ struct qed_hwfn *p_hwfn) { return NULL; }
+
+static inline void
+qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid) {}
+
+static inline void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info)
+ {}
+
+static inline void qed_ooo_setup(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info) {}
+
+static inline void qed_ooo_free(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info) {}
+
+static inline void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer) {}
+
+static inline struct qed_ooo_buffer *
+qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info) { return NULL; }
+
+static inline void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ struct qed_ooo_buffer *p_buffer,
+ u8 on_tail) {}
+
+static inline struct qed_ooo_buffer *
+qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info) { return NULL; }
+
+static inline void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 drop_isle, u8 drop_size) {}
+
+static inline void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 ooo_isle,
+ struct qed_ooo_buffer *p_buffer) {}
+
+static inline void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info,
+ u32 cid, u8 ooo_isle,
+ struct qed_ooo_buffer *p_buffer,
+ u8 buffer_side) {}
+
+static inline void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
+ struct qed_ooo_info *p_ooo_info, u32 cid,
+ u8 left_isle) {}
+#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
index b414a0542177..97544205a8c1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
@@ -82,6 +82,8 @@
0x1c80000UL
#define BAR0_MAP_REG_XSDM_RAM \
0x1e00000UL
+#define BAR0_MAP_REG_YSDM_RAM \
+ 0x1e80000UL
#define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \
0x5011f4UL
#define PRS_REG_SEARCH_TCP \
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
index f3a825a8f8d5..2a16547c8966 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -2658,7 +2658,6 @@ static int qed_roce_ll2_start(struct qed_dev *cdev,
DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n");
return -ENOMEM;
}
- memset(roce_ll2, 0, sizeof(*roce_ll2));
roce_ll2->handle = QED_LL2_UNUSED_HANDLE;
roce_ll2->cbs = params->cbs;
roce_ll2->cb_cookie = params->cb_cookie;
@@ -2772,6 +2771,7 @@ static int qed_roce_ll2_tx(struct qed_dev *cdev,
/* Tx header */
rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), roce_ll2->handle,
1 + pkt->n_seg, 0, flags, 0,
+ QED_LL2_TX_DEST_NW,
qed_roce_flavor, pkt->header.baddr,
pkt->header.len, pkt, 1);
if (rc) {
diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.c b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
index 9b7678f26909..48bfaecaf6dc 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
@@ -1,3 +1,4 @@
+#include <linux/crc32.h>
#include "qed.h"
#include "qed_dev_api.h"
#include "qed_mcp.h"
@@ -75,3 +76,103 @@ int qed_selftest_clock(struct qed_dev *cdev)
return rc;
}
+
+int qed_selftest_nvram(struct qed_dev *cdev)
+{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
+ u32 num_images, i, j, nvm_crc, calc_crc;
+ struct bist_nvm_image_att image_att;
+ u8 *buf = NULL;
+ __be32 val;
+ int rc;
+
+ if (!p_ptt) {
+ DP_ERR(p_hwfn, "failed to acquire ptt\n");
+ return -EBUSY;
+ }
+
+ /* Acquire from MFW the amount of available images */
+ rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
+ if (rc || !num_images) {
+ DP_ERR(p_hwfn, "Failed getting number of images\n");
+ return -EINVAL;
+ }
+
+ /* Iterate over images and validate CRC */
+ for (i = 0; i < num_images; i++) {
+ /* This mailbox returns information about the image required for
+ * reading it.
+ */
+ rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
+ &image_att, i);
+ if (rc) {
+ DP_ERR(p_hwfn,
+ "Failed getting image index %d attributes\n",
+ i);
+ goto err0;
+ }
+
+ /* After MFW crash dump is collected - the image's CRC stops
+ * being valid.
+ */
+ if (image_att.image_type == NVM_TYPE_MDUMP)
+ continue;
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n",
+ i, image_att.len);
+
+ /* Allocate a buffer for holding the nvram image */
+ buf = kzalloc(image_att.len, GFP_KERNEL);
+ if (!buf) {
+ rc = -ENOMEM;
+ goto err0;
+ }
+
+ /* Read image into buffer */
+ rc = qed_mcp_nvm_read(p_hwfn->cdev, image_att.nvm_start_addr,
+ buf, image_att.len);
+ if (rc) {
+ DP_ERR(p_hwfn,
+ "Failed reading image index %d from nvm.\n", i);
+ goto err1;
+ }
+
+ /* Convert the buffer into big-endian format (excluding the
+ * closing 4 bytes of CRC).
+ */
+ for (j = 0; j < image_att.len - 4; j += 4) {
+ val = cpu_to_be32(*(u32 *)&buf[j]);
+ *(u32 *)&buf[j] = (__force u32)val;
+ }
+
+ /* Calc CRC for the "actual" image buffer, i.e. not including
+ * the last 4 CRC bytes.
+ */
+ nvm_crc = *(u32 *)(buf + image_att.len - 4);
+ calc_crc = crc32(0xffffffff, buf, image_att.len - 4);
+ calc_crc = (__force u32)~cpu_to_be32(calc_crc);
+ DP_VERBOSE(p_hwfn, QED_MSG_SP,
+ "nvm crc 0x%x, calc_crc 0x%x\n", nvm_crc, calc_crc);
+
+ if (calc_crc != nvm_crc) {
+ rc = -EINVAL;
+ goto err1;
+ }
+
+ /* Done with this image; Free to prevent double release
+ * on subsequent failure.
+ */
+ kfree(buf);
+ buf = NULL;
+ }
+
+ qed_ptt_release(p_hwfn, p_ptt);
+ return 0;
+
+err1:
+ kfree(buf);
+err0:
+ qed_ptt_release(p_hwfn, p_ptt);
+ return rc;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.h b/drivers/net/ethernet/qlogic/qed/qed_selftest.h
index 50eb0b49950f..739ddb730967 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_selftest.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.h
@@ -37,4 +37,14 @@ int qed_selftest_register(struct qed_dev *cdev);
* @return int
*/
int qed_selftest_clock(struct qed_dev *cdev);
+
+/**
+ * @brief qed_selftest_nvram - Perform nvram test
+ *
+ * @param cdev
+ *
+ * @return int
+ */
+int qed_selftest_nvram(struct qed_dev *cdev);
+
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index b2c08e4d2a9b..9c897bc68d05 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -110,8 +110,8 @@ union qed_spq_req_comp {
};
struct qed_spq_comp_done {
- u64 done;
- u8 fw_return_code;
+ unsigned int done;
+ u8 fw_return_code;
};
struct qed_spq_entry {
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
index 2888eb0628f8..d0a58282f2a8 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
@@ -347,11 +347,11 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn,
/* Place EQ address in RAMROD */
DMA_REGPAIR_LE(p_ramrod->event_ring_pbl_addr,
- p_hwfn->p_eq->chain.pbl.p_phys_table);
+ p_hwfn->p_eq->chain.pbl_sp.p_phys_table);
page_cnt = (u8)qed_chain_get_page_cnt(&p_hwfn->p_eq->chain);
p_ramrod->event_ring_num_pages = page_cnt;
DMA_REGPAIR_LE(p_ramrod->consolid_q_pbl_addr,
- p_hwfn->p_consq->chain.pbl.p_phys_table);
+ p_hwfn->p_consq->chain.pbl_sp.p_phys_table);
qed_tunn_set_pf_start_params(p_hwfn, p_tunn, &p_ramrod->tunnel_config);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index 9fbaf9429fd0..f022469bdcf8 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -24,7 +24,9 @@
#include "qed_hsi.h"
#include "qed_hw.h"
#include "qed_int.h"
+#include "qed_iscsi.h"
#include "qed_mcp.h"
+#include "qed_ooo.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_sriov.h"
@@ -35,7 +37,11 @@
***************************************************************************/
#define SPQ_HIGH_PRI_RESERVE_DEFAULT (1)
-#define SPQ_BLOCK_SLEEP_LENGTH (1000)
+
+#define SPQ_BLOCK_DELAY_MAX_ITER (10)
+#define SPQ_BLOCK_DELAY_US (10)
+#define SPQ_BLOCK_SLEEP_MAX_ITER (1000)
+#define SPQ_BLOCK_SLEEP_MS (5)
/***************************************************************************
* Blocking Imp. (BLOCK/EBLOCK mode)
@@ -48,60 +54,88 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
comp_done = (struct qed_spq_comp_done *)cookie;
- comp_done->done = 0x1;
- comp_done->fw_return_code = fw_return_code;
+ comp_done->fw_return_code = fw_return_code;
- /* make update visible to waiting thread */
- smp_wmb();
+ /* Make sure completion done is visible on waiting thread */
+ smp_store_release(&comp_done->done, 0x1);
}
-static int qed_spq_block(struct qed_hwfn *p_hwfn,
- struct qed_spq_entry *p_ent,
- u8 *p_fw_ret)
+static int __qed_spq_block(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *p_fw_ret, bool sleep_between_iter)
{
- int sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
struct qed_spq_comp_done *comp_done;
- int rc;
+ u32 iter_cnt;
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) {
+ iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER
+ : SPQ_BLOCK_DELAY_MAX_ITER;
+
+ while (iter_cnt--) {
+ /* Validate we receive completion update */
+ if (READ_ONCE(comp_done->done) == 1) {
+ /* Read updated FW return value */
+ smp_read_barrier_depends();
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
}
- usleep_range(5000, 10000);
- sleep_count--;
+
+ if (sleep_between_iter)
+ msleep(SPQ_BLOCK_SLEEP_MS);
+ else
+ udelay(SPQ_BLOCK_DELAY_US);
+ }
+
+ return -EBUSY;
+}
+
+static int qed_spq_block(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *p_fw_ret, bool skip_quick_poll)
+{
+ struct qed_spq_comp_done *comp_done;
+ int rc;
+
+ /* A relatively short polling period w/o sleeping, to allow the FW to
+ * complete the ramrod and thus possibly to avoid the following sleeps.
+ */
+ if (!skip_quick_poll) {
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, false);
+ if (!rc)
+ return 0;
}
+ /* Move to polling with a sleeping period between iterations */
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+ if (!rc)
+ return 0;
+
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)
+ if (rc) {
DP_NOTICE(p_hwfn, "MCP drain failed\n");
+ goto err;
+ }
/* 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--;
- }
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+ if (!rc)
+ return 0;
+ comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
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");
+err:
+ DP_NOTICE(p_hwfn,
+ "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n",
+ le32_to_cpu(p_ent->elem.hdr.cid),
+ p_ent->elem.hdr.cmd_id,
+ p_ent->elem.hdr.protocol_id,
+ le16_to_cpu(p_ent->elem.hdr.echo));
return -EBUSY;
}
@@ -245,6 +279,28 @@ qed_async_event_completion(struct qed_hwfn *p_hwfn,
return qed_sriov_eqe_event(p_hwfn,
p_eqe->opcode,
p_eqe->echo, &p_eqe->data);
+ case PROTOCOLID_ISCSI:
+ if (!IS_ENABLED(CONFIG_QED_ISCSI))
+ return -EINVAL;
+ if (p_eqe->opcode == ISCSI_EVENT_TYPE_ASYN_DELETE_OOO_ISLES) {
+ u32 cid = le32_to_cpu(p_eqe->data.iscsi_info.cid);
+
+ qed_ooo_release_connection_isles(p_hwfn,
+ p_hwfn->p_ooo_info,
+ cid);
+ return 0;
+ }
+
+ if (p_hwfn->p_iscsi_info->event_cb) {
+ struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info;
+
+ return p_iscsi->event_cb(p_iscsi->event_context,
+ p_eqe->opcode, &p_eqe->data);
+ } else {
+ DP_NOTICE(p_hwfn,
+ "iSCSI async completion is not set\n");
+ return -EINVAL;
+ }
default:
DP_NOTICE(p_hwfn,
"Unknown Async completion for protocol: %d\n",
@@ -725,7 +781,8 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
* 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);
+ rc = qed_spq_block(p_hwfn, p_ent, fw_return_code,
+ p_ent->queue == &p_spq->unlimited_pending);
if (p_ent->queue == &p_spq->unlimited_pending) {
/* This is an allocated p_ent which does not need to
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index d2d6621fe0e5..85b09dd1787a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -109,7 +109,8 @@ static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn,
}
static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
- int rel_vf_id, bool b_enabled_only)
+ int rel_vf_id,
+ bool b_enabled_only, bool b_non_malicious)
{
if (!p_hwfn->pf_iov_info) {
DP_NOTICE(p_hwfn->cdev, "No iov info\n");
@@ -124,6 +125,10 @@ static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
b_enabled_only)
return false;
+ if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
+ b_non_malicious)
+ return false;
+
return true;
}
@@ -138,7 +143,8 @@ static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn,
return NULL;
}
- if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only))
+ if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id,
+ b_enabled_only, false))
vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
else
DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n",
@@ -542,7 +548,8 @@ int qed_iov_hw_info(struct qed_hwfn *p_hwfn)
return 0;
}
-static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+bool _qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn,
+ int vfid, bool b_fail_malicious)
{
/* Check PF supports sriov */
if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) ||
@@ -550,12 +557,17 @@ static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
return false;
/* Check VF validity */
- if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true))
+ if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
return false;
return true;
}
+bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+{
+ return _qed_iov_pf_sanity_check(p_hwfn, vfid, true);
+}
+
static void qed_iov_set_vf_to_disable(struct qed_dev *cdev,
u16 rel_vf_id, u8 to_disable)
{
@@ -652,6 +664,9 @@ static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn,
qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
+ /* It's possible VF was previously considered malicious */
+ vf->b_malicious = false;
+
rc = qed_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs);
if (rc)
return rc;
@@ -793,37 +808,70 @@ static void qed_iov_free_vf_igu_sbs(struct qed_hwfn *p_hwfn,
static int qed_iov_init_hw_for_vf(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
- u16 rel_vf_id, u16 num_rx_queues)
+ struct qed_iov_vf_init_params *p_params)
{
u8 num_of_vf_avaiable_chains = 0;
struct qed_vf_info *vf = NULL;
+ u16 qid, num_irqs;
int rc = 0;
u32 cids;
u8 i;
- vf = qed_iov_get_vf_info(p_hwfn, rel_vf_id, false);
+ vf = qed_iov_get_vf_info(p_hwfn, p_params->rel_vf_id, false);
if (!vf) {
DP_ERR(p_hwfn, "qed_iov_init_hw_for_vf : vf is NULL\n");
return -EINVAL;
}
if (vf->b_init) {
- DP_NOTICE(p_hwfn, "VF[%d] is already active.\n", rel_vf_id);
+ DP_NOTICE(p_hwfn, "VF[%d] is already active.\n",
+ p_params->rel_vf_id);
return -EINVAL;
}
+ /* Perform sanity checking on the requested queue_id */
+ for (i = 0; i < p_params->num_queues; i++) {
+ u16 min_vf_qzone = FEAT_NUM(p_hwfn, QED_PF_L2_QUE);
+ u16 max_vf_qzone = min_vf_qzone +
+ FEAT_NUM(p_hwfn, QED_VF_L2_QUE) - 1;
+
+ qid = p_params->req_rx_queue[i];
+ if (qid < min_vf_qzone || qid > max_vf_qzone) {
+ DP_NOTICE(p_hwfn,
+ "Can't enable Rx qid [%04x] for VF[%d]: qids [0x%04x,...,0x%04x] available\n",
+ qid,
+ p_params->rel_vf_id,
+ min_vf_qzone, max_vf_qzone);
+ return -EINVAL;
+ }
+
+ qid = p_params->req_tx_queue[i];
+ if (qid > max_vf_qzone) {
+ DP_NOTICE(p_hwfn,
+ "Can't enable Tx qid [%04x] for VF[%d]: max qid 0x%04x\n",
+ qid, p_params->rel_vf_id, max_vf_qzone);
+ return -EINVAL;
+ }
+
+ /* If client *really* wants, Tx qid can be shared with PF */
+ if (qid < min_vf_qzone)
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_IOV,
+ "VF[%d] is using PF qid [0x%04x] for Txq[0x%02x]\n",
+ p_params->rel_vf_id, qid, i);
+ }
+
/* Limit number of queues according to number of CIDs */
qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, &cids);
DP_VERBOSE(p_hwfn,
QED_MSG_IOV,
"VF[%d] - requesting to initialize for 0x%04x queues [0x%04x CIDs available]\n",
- vf->relative_vf_id, num_rx_queues, (u16) cids);
- num_rx_queues = min_t(u16, num_rx_queues, ((u16) cids));
+ vf->relative_vf_id, p_params->num_queues, (u16)cids);
+ num_irqs = min_t(u16, p_params->num_queues, ((u16)cids));
num_of_vf_avaiable_chains = qed_iov_alloc_vf_igu_sbs(p_hwfn,
p_ptt,
- vf,
- num_rx_queues);
+ vf, num_irqs);
if (!num_of_vf_avaiable_chains) {
DP_ERR(p_hwfn, "no available igu sbs\n");
return -ENOMEM;
@@ -834,25 +882,22 @@ static int qed_iov_init_hw_for_vf(struct qed_hwfn *p_hwfn,
vf->num_txqs = num_of_vf_avaiable_chains;
for (i = 0; i < vf->num_rxqs; i++) {
- u16 queue_id = qed_int_queue_id_from_sb_id(p_hwfn,
- vf->igu_sbs[i]);
+ struct qed_vf_q_info *p_queue = &vf->vf_queues[i];
- if (queue_id > RESC_NUM(p_hwfn, QED_L2_QUEUE)) {
- DP_NOTICE(p_hwfn,
- "VF[%d] will require utilizing of out-of-bounds queues - %04x\n",
- vf->relative_vf_id, queue_id);
- return -EINVAL;
- }
+ p_queue->fw_rx_qid = p_params->req_rx_queue[i];
+ p_queue->fw_tx_qid = p_params->req_tx_queue[i];
/* CIDs are per-VF, so no problem having them 0-based. */
- vf->vf_queues[i].fw_rx_qid = queue_id;
- vf->vf_queues[i].fw_tx_qid = queue_id;
- vf->vf_queues[i].fw_cid = i;
+ p_queue->fw_cid = i;
DP_VERBOSE(p_hwfn, QED_MSG_IOV,
- "VF[%d] - [%d] SB %04x, Tx/Rx queue %04x CID %04x\n",
- vf->relative_vf_id, i, vf->igu_sbs[i], queue_id, i);
+ "VF[%d] - Q[%d] SB %04x, qid [Rx %04x Tx %04x] CID %04x\n",
+ vf->relative_vf_id,
+ i, vf->igu_sbs[i],
+ p_queue->fw_rx_qid,
+ p_queue->fw_tx_qid, p_queue->fw_cid);
}
+
rc = qed_iov_enable_vf_access(p_hwfn, p_ptt, vf);
if (!rc) {
vf->b_init = true;
@@ -1172,8 +1217,19 @@ static void qed_iov_vf_cleanup(struct qed_hwfn *p_hwfn,
p_vf->num_active_rxqs = 0;
- for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++)
- p_vf->vf_queues[i].rxq_active = 0;
+ for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) {
+ struct qed_vf_q_info *p_queue = &p_vf->vf_queues[i];
+
+ if (p_queue->p_rx_cid) {
+ qed_eth_queue_cid_release(p_hwfn, p_queue->p_rx_cid);
+ p_queue->p_rx_cid = NULL;
+ }
+
+ if (p_queue->p_tx_cid) {
+ qed_eth_queue_cid_release(p_hwfn, p_queue->p_tx_cid);
+ p_queue->p_tx_cid = NULL;
+ }
+ }
memset(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config));
memset(&p_vf->acquire, 0, sizeof(p_vf->acquire));
@@ -1579,21 +1635,21 @@ static int qed_iov_configure_vport_forced(struct qed_hwfn *p_hwfn,
/* Update all the Rx queues */
for (i = 0; i < QED_MAX_VF_CHAINS_PER_PF; i++) {
- u16 qid;
+ struct qed_queue_cid *p_cid;
- if (!p_vf->vf_queues[i].rxq_active)
+ p_cid = p_vf->vf_queues[i].p_rx_cid;
+ if (!p_cid)
continue;
- qid = p_vf->vf_queues[i].fw_rx_qid;
-
- rc = qed_sp_eth_rx_queues_update(p_hwfn, qid,
+ rc = qed_sp_eth_rx_queues_update(p_hwfn,
+ (void **)&p_cid,
1, 0, 1,
QED_SPQ_MODE_EBLOCK,
NULL);
if (rc) {
DP_NOTICE(p_hwfn,
"Failed to send Rx update fo queue[0x%04x]\n",
- qid);
+ p_cid->rel.queue_id);
return rc;
}
}
@@ -1767,23 +1823,34 @@ static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn,
struct qed_queue_start_common_params params;
struct qed_iov_vf_mbx *mbx = &vf->vf_mbx;
u8 status = PFVF_STATUS_NO_RESOURCE;
+ struct qed_vf_q_info *p_queue;
struct vfpf_start_rxq_tlv *req;
bool b_legacy_vf = false;
int rc;
- memset(&params, 0, sizeof(params));
req = &mbx->req_virt->start_rxq;
if (!qed_iov_validate_rxq(p_hwfn, vf, req->rx_qid) ||
!qed_iov_validate_sb(p_hwfn, vf, req->hw_sb))
goto out;
- params.queue_id = vf->vf_queues[req->rx_qid].fw_rx_qid;
- params.vf_qid = req->rx_qid;
+ /* Acquire a new queue-cid */
+ p_queue = &vf->vf_queues[req->rx_qid];
+
+ memset(&params, 0, sizeof(params));
+ params.queue_id = p_queue->fw_rx_qid;
params.vport_id = vf->vport_id;
+ params.stats_id = vf->abs_vf_id + 0x10;
params.sb = req->hw_sb;
params.sb_idx = req->sb_index;
+ p_queue->p_rx_cid = _qed_eth_queue_to_cid(p_hwfn,
+ vf->opaque_fid,
+ p_queue->fw_cid,
+ req->rx_qid, &params);
+ if (!p_queue->p_rx_cid)
+ goto out;
+
/* Legacy VFs have their Producers in a different location, which they
* calculate on their own and clean the producer prior to this.
*/
@@ -1796,21 +1863,19 @@ static void qed_iov_vf_mbx_start_rxq(struct qed_hwfn *p_hwfn,
MSTORM_ETH_VF_PRODS_OFFSET(vf->abs_vf_id, req->rx_qid),
0);
}
+ p_queue->p_rx_cid->b_legacy_vf = b_legacy_vf;
- rc = qed_sp_eth_rxq_start_ramrod(p_hwfn, vf->opaque_fid,
- vf->vf_queues[req->rx_qid].fw_cid,
- &params,
- vf->abs_vf_id + 0x10,
- req->bd_max_bytes,
- req->rxq_addr,
- req->cqe_pbl_addr, req->cqe_pbl_size,
- b_legacy_vf);
-
+ rc = qed_eth_rxq_start_ramrod(p_hwfn,
+ p_queue->p_rx_cid,
+ req->bd_max_bytes,
+ req->rxq_addr,
+ req->cqe_pbl_addr, req->cqe_pbl_size);
if (rc) {
status = PFVF_STATUS_FAILURE;
+ qed_eth_queue_cid_release(p_hwfn, p_queue->p_rx_cid);
+ p_queue->p_rx_cid = NULL;
} else {
status = PFVF_STATUS_SUCCESS;
- vf->vf_queues[req->rx_qid].rxq_active = true;
vf->num_active_rxqs++;
}
@@ -1867,7 +1932,9 @@ static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn,
u8 status = PFVF_STATUS_NO_RESOURCE;
union qed_qm_pq_params pq_params;
struct vfpf_start_txq_tlv *req;
+ struct qed_vf_q_info *p_queue;
int rc;
+ u16 pq;
/* Prepare the parameters which would choose the right PQ */
memset(&pq_params, 0, sizeof(pq_params));
@@ -1881,24 +1948,31 @@ static void qed_iov_vf_mbx_start_txq(struct qed_hwfn *p_hwfn,
!qed_iov_validate_sb(p_hwfn, vf, req->hw_sb))
goto out;
- params.queue_id = vf->vf_queues[req->tx_qid].fw_tx_qid;
+ /* Acquire a new queue-cid */
+ p_queue = &vf->vf_queues[req->tx_qid];
+
+ params.queue_id = p_queue->fw_tx_qid;
params.vport_id = vf->vport_id;
+ params.stats_id = vf->abs_vf_id + 0x10;
params.sb = req->hw_sb;
params.sb_idx = req->sb_index;
- rc = qed_sp_eth_txq_start_ramrod(p_hwfn,
- vf->opaque_fid,
- vf->vf_queues[req->tx_qid].fw_cid,
- &params,
- vf->abs_vf_id + 0x10,
- req->pbl_addr,
- req->pbl_size, &pq_params);
+ p_queue->p_tx_cid = _qed_eth_queue_to_cid(p_hwfn,
+ vf->opaque_fid,
+ p_queue->fw_cid,
+ req->tx_qid, &params);
+ if (!p_queue->p_tx_cid)
+ goto out;
+ pq = qed_get_qm_pq(p_hwfn, PROTOCOLID_ETH, &pq_params);
+ rc = qed_eth_txq_start_ramrod(p_hwfn, p_queue->p_tx_cid,
+ req->pbl_addr, req->pbl_size, pq);
if (rc) {
status = PFVF_STATUS_FAILURE;
+ qed_eth_queue_cid_release(p_hwfn, p_queue->p_tx_cid);
+ p_queue->p_tx_cid = NULL;
} else {
status = PFVF_STATUS_SUCCESS;
- vf->vf_queues[req->tx_qid].txq_active = true;
}
out:
@@ -1909,6 +1983,7 @@ static int qed_iov_vf_stop_rxqs(struct qed_hwfn *p_hwfn,
struct qed_vf_info *vf,
u16 rxq_id, u8 num_rxqs, bool cqe_completion)
{
+ struct qed_vf_q_info *p_queue;
int rc = 0;
int qid;
@@ -1916,16 +1991,18 @@ static int qed_iov_vf_stop_rxqs(struct qed_hwfn *p_hwfn,
return -EINVAL;
for (qid = rxq_id; qid < rxq_id + num_rxqs; qid++) {
- if (vf->vf_queues[qid].rxq_active) {
- rc = qed_sp_eth_rx_queue_stop(p_hwfn,
- vf->vf_queues[qid].
- fw_rx_qid, false,
- cqe_completion);
+ p_queue = &vf->vf_queues[qid];
- if (rc)
- return rc;
- }
- vf->vf_queues[qid].rxq_active = false;
+ if (!p_queue->p_rx_cid)
+ continue;
+
+ rc = qed_eth_rx_queue_stop(p_hwfn,
+ p_queue->p_rx_cid,
+ false, cqe_completion);
+ if (rc)
+ return rc;
+
+ vf->vf_queues[qid].p_rx_cid = NULL;
vf->num_active_rxqs--;
}
@@ -1936,22 +2013,24 @@ static int qed_iov_vf_stop_txqs(struct qed_hwfn *p_hwfn,
struct qed_vf_info *vf, u16 txq_id, u8 num_txqs)
{
int rc = 0;
+ struct qed_vf_q_info *p_queue;
int qid;
if (txq_id + num_txqs > ARRAY_SIZE(vf->vf_queues))
return -EINVAL;
for (qid = txq_id; qid < txq_id + num_txqs; qid++) {
- if (vf->vf_queues[qid].txq_active) {
- rc = qed_sp_eth_tx_queue_stop(p_hwfn,
- vf->vf_queues[qid].
- fw_tx_qid);
+ p_queue = &vf->vf_queues[qid];
+ if (!p_queue->p_tx_cid)
+ continue;
- if (rc)
- return rc;
- }
- vf->vf_queues[qid].txq_active = false;
+ rc = qed_eth_tx_queue_stop(p_hwfn, p_queue->p_tx_cid);
+ if (rc)
+ return rc;
+
+ p_queue->p_tx_cid = NULL;
}
+
return rc;
}
@@ -2006,10 +2085,11 @@ static void qed_iov_vf_mbx_update_rxqs(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
struct qed_vf_info *vf)
{
+ struct qed_queue_cid *handlers[QED_MAX_VF_CHAINS_PER_PF];
u16 length = sizeof(struct pfvf_def_resp_tlv);
struct qed_iov_vf_mbx *mbx = &vf->vf_mbx;
struct vfpf_update_rxq_tlv *req;
- u8 status = PFVF_STATUS_SUCCESS;
+ u8 status = PFVF_STATUS_FAILURE;
u8 complete_event_flg;
u8 complete_cqe_flg;
u16 qid;
@@ -2020,29 +2100,36 @@ static void qed_iov_vf_mbx_update_rxqs(struct qed_hwfn *p_hwfn,
complete_cqe_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_CQE_FLAG);
complete_event_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_EVENT_FLAG);
+ /* Validate inputs */
+ if (req->num_rxqs + req->rx_qid > QED_MAX_VF_CHAINS_PER_PF ||
+ !qed_iov_validate_rxq(p_hwfn, vf, req->rx_qid)) {
+ DP_INFO(p_hwfn, "VF[%d]: Incorrect Rxqs [%04x, %02x]\n",
+ vf->relative_vf_id, req->rx_qid, req->num_rxqs);
+ goto out;
+ }
+
for (i = 0; i < req->num_rxqs; i++) {
qid = req->rx_qid + i;
-
- if (!vf->vf_queues[qid].rxq_active) {
- DP_NOTICE(p_hwfn, "VF rx_qid = %d isn`t active!\n",
- qid);
- status = PFVF_STATUS_FAILURE;
- break;
+ if (!vf->vf_queues[qid].p_rx_cid) {
+ DP_INFO(p_hwfn,
+ "VF[%d] rx_qid = %d isn`t active!\n",
+ vf->relative_vf_id, qid);
+ goto out;
}
- rc = qed_sp_eth_rx_queues_update(p_hwfn,
- vf->vf_queues[qid].fw_rx_qid,
- 1,
- complete_cqe_flg,
- complete_event_flg,
- QED_SPQ_MODE_EBLOCK, NULL);
-
- if (rc) {
- status = PFVF_STATUS_FAILURE;
- break;
- }
+ handlers[i] = vf->vf_queues[qid].p_rx_cid;
}
+ rc = qed_sp_eth_rx_queues_update(p_hwfn, (void **)&handlers,
+ req->num_rxqs,
+ complete_cqe_flg,
+ complete_event_flg,
+ QED_SPQ_MODE_EBLOCK, NULL);
+ if (rc)
+ goto out;
+
+ status = PFVF_STATUS_SUCCESS;
+out:
qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UPDATE_RXQ,
length, status);
}
@@ -2253,7 +2340,7 @@ qed_iov_vp_update_rss_param(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn,
"rss_ind_table[%d] = %d, rxq is out of range\n",
i, q_idx);
- else if (!vf->vf_queues[q_idx].rxq_active)
+ else if (!vf->vf_queues[q_idx].p_rx_cid)
DP_NOTICE(p_hwfn,
"rss_ind_table[%d] = %d, rxq is not active\n",
i, q_idx);
@@ -2804,6 +2891,13 @@ qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn,
return rc;
}
+ /* Workaround to make VF-PF channel ready, as FW
+ * doesn't do that as a part of FLR.
+ */
+ REG_WR(p_hwfn,
+ GTT_BAR0_MAP_REG_USDM_RAM +
+ USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1);
+
/* VF_STOPPED has to be set only after final cleanup
* but prior to re-enabling the VF.
*/
@@ -2942,7 +3036,8 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
mbx->first_tlv = mbx->req_virt->first_tlv;
/* check if tlv type is known */
- if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+ if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) &&
+ !p_vf->b_malicious) {
switch (mbx->first_tlv.tl.type) {
case CHANNEL_TLV_ACQUIRE:
qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf);
@@ -2984,6 +3079,15 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
break;
}
+ } else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
+ p_vf->abs_vf_id, mbx->first_tlv.tl.type);
+
+ qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
+ mbx->first_tlv.tl.type,
+ sizeof(struct pfvf_def_resp_tlv),
+ PFVF_STATUS_MALICIOUS);
} else {
/* unknown TLV - this may belong to a VF driver from the future
* - a version written after this PF driver was written, which
@@ -3033,20 +3137,30 @@ static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn,
memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH);
}
-static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
- u16 abs_vfid, struct regpair *vf_msg)
+static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn,
+ u16 abs_vfid)
{
- u8 min = (u8)p_hwfn->cdev->p_iov_info->first_vf_in_pf;
- struct qed_vf_info *p_vf;
+ u8 min = (u8) p_hwfn->cdev->p_iov_info->first_vf_in_pf;
- if (!qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) {
+ if (!_qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
DP_VERBOSE(p_hwfn,
QED_MSG_IOV,
- "Got a message from VF [abs 0x%08x] that cannot be handled by PF\n",
+ "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n",
abs_vfid);
- return 0;
+ return NULL;
}
- p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
+
+ return &p_hwfn->pf_iov_info->vfs_array[(u8) abs_vfid - min];
+}
+
+static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
+ u16 abs_vfid, struct regpair *vf_msg)
+{
+ struct qed_vf_info *p_vf = qed_sriov_get_vf_from_absid(p_hwfn,
+ abs_vfid);
+
+ if (!p_vf)
+ return 0;
/* List the physical address of the request so that handler
* could later on copy the message from it.
@@ -3060,6 +3174,23 @@ static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
return 0;
}
+static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn,
+ struct malicious_vf_eqe_data *p_data)
+{
+ struct qed_vf_info *p_vf;
+
+ p_vf = qed_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id);
+
+ if (!p_vf)
+ return;
+
+ DP_INFO(p_hwfn,
+ "VF [%d] - Malicious behavior [%02x]\n",
+ p_vf->abs_vf_id, p_data->err_id);
+
+ p_vf->b_malicious = true;
+}
+
int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
u8 opcode, __le16 echo, union event_ring_data *data)
{
@@ -3067,6 +3198,9 @@ int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
case COMMON_EVENT_VF_PF_CHANNEL:
return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo),
&data->vf_pf_channel.msg_addr);
+ case COMMON_EVENT_MALICIOUS_VF:
+ qed_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
+ return 0;
default:
DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n",
opcode);
@@ -3083,7 +3217,7 @@ u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id)
goto out;
for (i = rel_vf_id; i < p_iov->total_vfs; i++)
- if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true))
+ if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
return i;
out:
@@ -3130,6 +3264,12 @@ static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn,
return;
}
+ if (vf_info->b_malicious) {
+ DP_NOTICE(p_hwfn->cdev,
+ "Can't set forced MAC to malicious VF [%d]\n", vfid);
+ return;
+ }
+
feature = 1 << MAC_ADDR_FORCED;
memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
@@ -3153,6 +3293,12 @@ static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn,
return;
}
+ if (vf_info->b_malicious) {
+ DP_NOTICE(p_hwfn->cdev,
+ "Can't set forced vlan to malicious VF [%d]\n", vfid);
+ return;
+ }
+
feature = 1 << VLAN_ADDR_FORCED;
vf_info->bulletin.p_virt->pvid = pvid;
if (pvid)
@@ -3367,7 +3513,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
qed_for_each_vf(hwfn, j) {
int k;
- if (!qed_iov_is_valid_vfid(hwfn, j, true))
+ if (!qed_iov_is_valid_vfid(hwfn, j, true, false))
continue;
/* Wait until VF is disabled before releasing */
@@ -3394,9 +3540,28 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
return 0;
}
+static void qed_sriov_enable_qid_config(struct qed_hwfn *hwfn,
+ u16 vfid,
+ struct qed_iov_vf_init_params *params)
+{
+ u16 base, i;
+
+ /* Since we have an equal resource distribution per-VF, and we assume
+ * PF has acquired the QED_PF_L2_QUE first queues, we start setting
+ * sequentially from there.
+ */
+ base = FEAT_NUM(hwfn, QED_PF_L2_QUE) + vfid * params->num_queues;
+
+ params->rel_vf_id = vfid;
+ for (i = 0; i < params->num_queues; i++) {
+ params->req_rx_queue[i] = base + i;
+ params->req_tx_queue[i] = base + i;
+ }
+}
+
static int qed_sriov_enable(struct qed_dev *cdev, int num)
{
- struct qed_sb_cnt_info sb_cnt_info;
+ struct qed_iov_vf_init_params params;
int i, j, rc;
if (num >= RESC_NUM(&cdev->hwfns[0], QED_VPORT)) {
@@ -3405,11 +3570,17 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num)
return -EINVAL;
}
+ memset(&params, 0, sizeof(params));
+
/* Initialize HW for VF access */
for_each_hwfn(cdev, j) {
struct qed_hwfn *hwfn = &cdev->hwfns[j];
struct qed_ptt *ptt = qed_ptt_acquire(hwfn);
- int num_sbs = 0, limit = 16;
+
+ /* Make sure not to use more than 16 queues per VF */
+ params.num_queues = min_t(int,
+ FEAT_NUM(hwfn, QED_VF_L2_QUE) / num,
+ 16);
if (!ptt) {
DP_ERR(hwfn, "Failed to acquire ptt\n");
@@ -3417,19 +3588,12 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num)
goto err;
}
- if (IS_MF_DEFAULT(hwfn))
- limit = MAX_NUM_VFS_BB / hwfn->num_funcs_on_engine;
-
- memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
- qed_int_get_num_sbs(hwfn, &sb_cnt_info);
- num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit);
-
for (i = 0; i < num; i++) {
- if (!qed_iov_is_valid_vfid(hwfn, i, false))
+ if (!qed_iov_is_valid_vfid(hwfn, i, false, true))
continue;
- rc = qed_iov_init_hw_for_vf(hwfn,
- ptt, i, num_sbs / num);
+ qed_sriov_enable_qid_config(hwfn, i, &params);
+ rc = qed_iov_init_hw_for_vf(hwfn, ptt, &params);
if (rc) {
DP_ERR(cdev, "Failed to enable VF[%d]\n", i);
qed_ptt_release(hwfn, ptt);
@@ -3477,7 +3641,7 @@ static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid)
return -EINVAL;
}
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"Cannot set VF[%d] MAC (VF is not active)\n", vfid);
return -EINVAL;
@@ -3509,7 +3673,7 @@ static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid)
return -EINVAL;
}
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"Cannot set VF[%d] MAC (VF is not active)\n", vfid);
return -EINVAL;
@@ -3543,7 +3707,7 @@ static int qed_get_vf_config(struct qed_dev *cdev,
if (IS_VF(cdev))
return -EINVAL;
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, false)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"VF index [%d] isn't active\n", vf_id);
return -EINVAL;
@@ -3647,7 +3811,7 @@ static int qed_set_vf_link_state(struct qed_dev *cdev,
if (IS_VF(cdev))
return -EINVAL;
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"VF index [%d] isn't active\n", vf_id);
return -EINVAL;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
index 0dd23e409b3f..509c02b4772e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
@@ -58,6 +58,23 @@ struct qed_public_vf_info {
int tx_rate;
};
+struct qed_iov_vf_init_params {
+ u16 rel_vf_id;
+
+ /* Number of requested Queues; Currently, don't support different
+ * number of Rx/Tx queues.
+ */
+
+ u16 num_queues;
+
+ /* Allow the client to choose which qzones to use for Rx/Tx,
+ * and which queue_base to use for Tx queues on a per-queue basis.
+ * Notice values should be relative to the PF resources.
+ */
+ u16 req_rx_queue[QED_MAX_VF_CHAINS_PER_PF];
+ u16 req_tx_queue[QED_MAX_VF_CHAINS_PER_PF];
+};
+
/* This struct is part of qed_dev and contains data relevant to all hwfns;
* Initialized only if SR-IOV cpabability is exposed in PCIe config space.
*/
@@ -99,10 +116,10 @@ struct qed_iov_vf_mbx {
struct qed_vf_q_info {
u16 fw_rx_qid;
+ struct qed_queue_cid *p_rx_cid;
u16 fw_tx_qid;
+ struct qed_queue_cid *p_tx_cid;
u8 fw_cid;
- u8 rxq_active;
- u8 txq_active;
};
enum vf_state {
@@ -132,6 +149,7 @@ struct qed_vf_info {
struct qed_iov_vf_mbx vf_mbx;
enum vf_state state;
bool b_init;
+ bool b_malicious;
u8 to_disable;
struct qed_bulletin bulletin;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index abf5bf11f865..60b31a8ede73 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -388,18 +388,18 @@ free_p_iov:
#define MSTORM_QZONE_START(dev) (TSTORM_QZONE_START + \
(TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev)))
-int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
- u8 rx_qid,
- u16 sb,
- u8 sb_index,
- 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
+qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ 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_vf_iov *p_iov = p_hwfn->vf_iov_info;
struct pfvf_start_queue_resp_tlv *resp;
struct vfpf_start_rxq_tlv *req;
+ u8 rx_qid = p_cid->rel.queue_id;
int rc;
/* clear mailbox and prep first tlv */
@@ -409,21 +409,22 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
req->cqe_pbl_addr = cqe_pbl_addr;
req->cqe_pbl_size = cqe_pbl_size;
req->rxq_addr = bd_chain_phys_addr;
- req->hw_sb = sb;
- req->sb_index = sb_index;
+ req->hw_sb = p_cid->rel.sb;
+ req->sb_index = p_cid->rel.sb_idx;
req->bd_max_bytes = bd_max_bytes;
req->stat_id = -1;
/* If PF is legacy, we'll need to calculate producers ourselves
* as well as clean them.
*/
- if (pp_prod && p_iov->b_pre_fp_hsi) {
+ if (p_iov->b_pre_fp_hsi) {
u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid];
u32 init_prod_val = 0;
- *pp_prod = (u8 __iomem *)p_hwfn->regview +
- MSTORM_QZONE_START(p_hwfn->cdev) +
- hw_qid * MSTORM_QZONE_SIZE;
+ *pp_prod = (u8 __iomem *)
+ p_hwfn->regview +
+ MSTORM_QZONE_START(p_hwfn->cdev) +
+ hw_qid * MSTORM_QZONE_SIZE;
/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
@@ -444,7 +445,7 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
}
/* Learn the address of the producer from the response */
- if (pp_prod && !p_iov->b_pre_fp_hsi) {
+ if (!p_iov->b_pre_fp_hsi) {
u32 init_prod_val = 0;
*pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset;
@@ -462,7 +463,8 @@ exit:
return rc;
}
-int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, u16 rx_qid, bool cqe_completion)
+int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid, bool cqe_completion)
{
struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
struct vfpf_stop_rxqs_tlv *req;
@@ -472,7 +474,7 @@ int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, u16 rx_qid, bool cqe_completion)
/* clear mailbox and prep first tlv */
req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_RXQS, sizeof(*req));
- req->rx_qid = rx_qid;
+ req->rx_qid = p_cid->rel.queue_id;
req->num_rxqs = 1;
req->cqe_completion = cqe_completion;
@@ -496,28 +498,28 @@ exit:
return rc;
}
-int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
- u16 tx_queue_id,
- u16 sb,
- u8 sb_index,
- dma_addr_t pbl_addr,
- u16 pbl_size, void __iomem **pp_doorbell)
+int
+qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ dma_addr_t pbl_addr,
+ u16 pbl_size, void __iomem **pp_doorbell)
{
struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
struct pfvf_start_queue_resp_tlv *resp;
struct vfpf_start_txq_tlv *req;
+ u16 qid = p_cid->rel.queue_id;
int rc;
/* clear mailbox and prep first tlv */
req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_TXQ, sizeof(*req));
- req->tx_qid = tx_queue_id;
+ req->tx_qid = qid;
/* Tx */
req->pbl_addr = pbl_addr;
req->pbl_size = pbl_size;
- req->hw_sb = sb;
- req->sb_index = sb_index;
+ req->hw_sb = p_cid->rel.sb;
+ req->sb_index = p_cid->rel.sb_idx;
/* add list termination tlv */
qed_add_tlv(p_hwfn, &p_iov->offset,
@@ -533,33 +535,29 @@ int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
goto exit;
}
- if (pp_doorbell) {
- /* Modern PFs provide the actual offsets, while legacy
- * provided only the queue id.
- */
- if (!p_iov->b_pre_fp_hsi) {
- *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
- resp->offset;
- } else {
- u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id];
- u32 db_addr;
-
- db_addr = qed_db_addr_vf(cid, DQ_DEMS_LEGACY);
- *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
- db_addr;
- }
+ /* Modern PFs provide the actual offsets, while legacy
+ * provided only the queue id.
+ */
+ if (!p_iov->b_pre_fp_hsi) {
+ *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + resp->offset;
+ } else {
+ u8 cid = p_iov->acquire_resp.resc.cid[qid];
- DP_VERBOSE(p_hwfn, QED_MSG_IOV,
- "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
- tx_queue_id, *pp_doorbell, resp->offset);
+ *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
+ qed_db_addr_vf(cid,
+ DQ_DEMS_LEGACY);
}
+
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
+ qid, *pp_doorbell, resp->offset);
exit:
qed_vf_pf_req_end(p_hwfn, rc);
return rc;
}
-int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid)
+int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid)
{
struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
struct vfpf_stop_txqs_tlv *req;
@@ -569,7 +567,7 @@ int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid)
/* clear mailbox and prep first tlv */
req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_TXQS, sizeof(*req));
- req->tx_qid = tx_qid;
+ req->tx_qid = p_cid->rel.queue_id;
req->num_txqs = 1;
/* add list termination tlv */
@@ -1171,6 +1169,13 @@ void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters)
*num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters;
}
+void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters)
+{
+ struct qed_vf_iov *p_vf = p_hwfn->vf_iov_info;
+
+ *num_mac_filters = p_vf->acquire_resp.resc.num_mac_filters;
+}
+
bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
{
struct qed_bulletin_content *bulletin;
@@ -1230,8 +1235,8 @@ static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac,
&is_mac_forced);
- if (is_mac_exist && is_mac_forced && cookie)
- ops->force_mac(cookie, mac);
+ if (is_mac_exist && cookie)
+ ops->force_mac(cookie, mac, !!is_mac_forced);
/* Always update link configuration according to bulletin */
qed_link_update(hwfn);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h
index 35db7a28aa13..11eb3854e6f2 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h
@@ -40,6 +40,7 @@ enum {
PFVF_STATUS_NOT_SUPPORTED,
PFVF_STATUS_NO_RESOURCE,
PFVF_STATUS_FORCED,
+ PFVF_STATUS_MALICIOUS,
};
/* vf pf channel tlvs */
@@ -622,6 +623,14 @@ void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn,
u8 *num_vlan_filters);
/**
+ * @brief Get number of MAC filters allocated for VF by qed
+ *
+ * @param p_hwfn
+ * @param num_rxqs - allocated MAC filters
+ */
+void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters);
+
+/**
* @brief Check if VF can set a MAC address
*
* @param p_hwfn
@@ -657,10 +666,7 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn);
/**
* @brief VF - start the RX Queue by sending a message to the PF
* @param p_hwfn
- * @param cid - zero based within the VF
- * @param rx_queue_id - zero based within the VF
- * @param sb - VF status block for this queue
- * @param sb_index - Index within the status block
+ * @param p_cid - Only relative fields are relevant
* @param bd_max_bytes - maximum number of bytes per bd
* @param bd_chain_phys_addr - physical address of bd chain
* @param cqe_pbl_addr - physical address of pbl
@@ -671,9 +677,7 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn);
* @return int
*/
int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
- u8 rx_queue_id,
- u16 sb,
- u8 sb_index,
+ struct qed_queue_cid *p_cid,
u16 bd_max_bytes,
dma_addr_t bd_chain_phys_addr,
dma_addr_t cqe_pbl_addr,
@@ -693,24 +697,23 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
*
* @return int
*/
-int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
- u16 tx_queue_id,
- u16 sb,
- u8 sb_index,
- dma_addr_t pbl_addr,
- u16 pbl_size, void __iomem **pp_doorbell);
+int
+qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid,
+ dma_addr_t pbl_addr,
+ u16 pbl_size, void __iomem **pp_doorbell);
/**
* @brief VF - stop the RX queue by sending a message to the PF
*
* @param p_hwfn
- * @param rx_qid
+ * @param p_cid
* @param cqe_completion
*
* @return int
*/
int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn,
- u16 rx_qid, bool cqe_completion);
+ struct qed_queue_cid *p_cid, bool cqe_completion);
/**
* @brief VF - stop the TX queue by sending a message to the PF
@@ -720,7 +723,7 @@ int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn,
*
* @return int
*/
-int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid);
+int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid);
/**
* @brief VF - send a vport update command
@@ -871,6 +874,11 @@ static inline void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn,
{
}
+static inline void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn,
+ u8 *num_mac_filters)
+{
+}
+
static inline bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
{
return false;
@@ -888,9 +896,7 @@ static inline int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
}
static inline int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
- u8 rx_queue_id,
- u16 sb,
- u8 sb_index,
+ struct qed_queue_cid *p_cid,
u16 bd_max_bytes,
dma_addr_t bd_chain_phys_adr,
dma_addr_t cqe_pbl_addr,
@@ -900,9 +906,7 @@ static inline int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
}
static inline int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
- u16 tx_queue_id,
- u16 sb,
- u8 sb_index,
+ struct qed_queue_cid *p_cid,
dma_addr_t pbl_addr,
u16 pbl_size, void __iomem **pp_doorbell)
{
@@ -910,12 +914,14 @@ static inline int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
}
static inline int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn,
- u16 rx_qid, bool cqe_completion)
+ struct qed_queue_cid *p_cid,
+ bool cqe_completion)
{
return -EINVAL;
}
-static inline int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid)
+static inline int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn,
+ struct qed_queue_cid *p_cid)
{
return -EINVAL;
}
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 974689a13337..c79dc78746fc 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -16,6 +16,7 @@
#include <linux/bitmap.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
+#include <linux/bpf.h>
#include <linux/io.h>
#include <linux/qed/common_hsi.h>
#include <linux/qed/eth_common.h>
@@ -127,10 +128,9 @@ struct qede_dev {
const struct qed_eth_ops *ops;
- struct qed_dev_eth_info dev_info;
+ 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)
+#define QEDE_MAX_TSS_CNT(edev) ((edev)->dev_info.num_queues)
struct qede_fastpath *fp_array;
u8 req_num_tx;
@@ -139,17 +139,9 @@ struct qede_dev {
u8 fp_num_rx;
u16 req_queues;
u16 num_queues;
- u8 num_tc;
#define QEDE_QUEUE_CNT(edev) ((edev)->num_queues)
#define QEDE_RSS_COUNT(edev) ((edev)->num_queues - (edev)->fp_num_tx)
-#define QEDE_TSS_COUNT(edev) (((edev)->num_queues - (edev)->fp_num_rx) * \
- (edev)->num_tc)
-#define QEDE_TX_IDX(edev, txqidx) ((edev)->fp_num_rx + (txqidx) % \
- QEDE_TSS_COUNT(edev))
-#define QEDE_TC_IDX(edev, txqidx) ((txqidx) / QEDE_TSS_COUNT(edev))
-#define QEDE_TX_QUEUE(edev, txqidx) \
- (&(edev)->fp_array[QEDE_TX_IDX((edev), (txqidx))].txqs[QEDE_TC_IDX(\
- (edev), (txqidx))])
+#define QEDE_TSS_COUNT(edev) ((edev)->num_queues - (edev)->fp_num_rx)
struct qed_int_info int_info;
unsigned char primary_mac[ETH_ALEN];
@@ -193,7 +185,11 @@ struct qede_dev {
u16 vxlan_dst_port;
u16 geneve_dst_port;
+ bool wol_enabled;
+
struct qede_rdma_dev rdma_info;
+
+ struct bpf_prog *xdp_prog;
};
enum QEDE_STATE {
@@ -223,39 +219,67 @@ enum qede_agg_state {
};
struct qede_agg_info {
- struct sw_rx_data replace_buf;
- dma_addr_t replace_buf_mapping;
- struct sw_rx_data start_buf;
- dma_addr_t start_buf_mapping;
- struct eth_fast_path_rx_tpa_start_cqe start_cqe;
- enum qede_agg_state agg_state;
+ /* rx_buf is a data buffer that can be placed / consumed from rx bd
+ * chain. It has two purposes: We will preallocate the data buffer
+ * for each aggregation when we open the interface and will place this
+ * buffer on the rx-bd-ring when we receive TPA_START. We don't want
+ * to be in a state where allocation fails, as we can't reuse the
+ * consumer buffer in the rx-chain since FW may still be writing to it
+ * (since header needs to be modified for TPA).
+ * The second purpose is to keep a pointer to the bd buffer during
+ * aggregation.
+ */
+ struct sw_rx_data buffer;
+ dma_addr_t buffer_mapping;
+
struct sk_buff *skb;
- int frag_id;
+
+ /* We need some structs from the start cookie until termination */
u16 vlan_tag;
+ u16 start_cqe_bd_len;
+ u8 start_cqe_placement_offset;
+
+ u8 state;
+ u8 frag_id;
+
+ u8 tunnel_type;
};
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;
+ __le16 *hw_cons_ptr;
+ void __iomem *hw_rxq_prod_addr;
+
+ /* Required for the allocation of replacement buffers */
+ struct device *dev;
+
+ struct bpf_prog *xdp_prog;
+
+ u16 sw_rx_cons;
+ u16 sw_rx_prod;
+
+ u16 num_rx_buffers; /* Slowpath */
+ u8 data_direction;
+ u8 rxq_id;
+
+ u32 rx_buf_size;
+ u32 rx_buf_seg_size;
+
+ u64 rcv_pkts;
+
+ struct sw_rx_data *sw_rx_ring;
+ struct qed_chain rx_bd_ring;
+ struct qed_chain rx_comp_ring ____cacheline_aligned;
/* GRO */
- struct qede_agg_info tpa_info[ETH_TPA_MAX_AGGS_NUM];
+ struct qede_agg_info tpa_info[ETH_TPA_MAX_AGGS_NUM];
- int rx_buf_size;
- unsigned int rx_buf_seg_size;
+ u64 rx_hw_errors;
+ u64 rx_alloc_errors;
+ u64 rx_ip_frags;
- u16 num_rx_buffers;
- u16 rxq_id;
+ u64 xdp_no_pass;
- u64 rcv_pkts;
- u64 rx_hw_errors;
- u64 rx_alloc_errors;
- u64 rx_ip_frags;
+ void *handle;
};
union db_prod {
@@ -271,20 +295,39 @@ struct sw_tx_bd {
};
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;
- u64 xmit_pkts;
- u64 stopped_cnt;
-
- bool is_legacy;
+ u8 is_xdp;
+ bool is_legacy;
+ u16 sw_tx_cons;
+ u16 sw_tx_prod;
+ u16 num_tx_buffers; /* Slowpath only */
+
+ u64 xmit_pkts;
+ u64 stopped_cnt;
+
+ __le16 *hw_cons_ptr;
+
+ /* Needed for the mapping of packets */
+ struct device *dev;
+
+ void __iomem *doorbell_addr;
+ union db_prod tx_db;
+ int index; /* Slowpath only */
+#define QEDE_TXQ_XDP_TO_IDX(edev, txq) ((txq)->index - \
+ QEDE_MAX_TSS_CNT(edev))
+#define QEDE_TXQ_IDX_TO_XDP(edev, idx) ((idx) + QEDE_MAX_TSS_CNT(edev))
+
+ /* Regular Tx requires skb + metadata for release purpose,
+ * while XDP requires only the pages themselves.
+ */
+ union {
+ struct sw_tx_bd *skbs;
+ struct page **pages;
+ } sw_tx_ring;
+
+ struct qed_chain tx_pbl;
+
+ /* Slowpath; Should be kept in end [unless missing padding] */
+ void *handle;
};
#define BD_UNMAP_ADDR(bd) HILO_U64(le32_to_cpu((bd)->addr.hi), \
@@ -301,13 +344,16 @@ struct qede_fastpath {
struct qede_dev *edev;
#define QEDE_FASTPATH_TX BIT(0)
#define QEDE_FASTPATH_RX BIT(1)
+#define QEDE_FASTPATH_XDP BIT(2)
#define QEDE_FASTPATH_COMBINED (QEDE_FASTPATH_TX | QEDE_FASTPATH_RX)
u8 type;
u8 id;
+ u8 xdp_xmit;
struct napi_struct napi;
struct qed_sb_info *sb_info;
struct qede_rx_queue *rxq;
- struct qede_tx_queue *txqs;
+ struct qede_tx_queue *txq;
+ struct qede_tx_queue *xdp_tx;
#define VEC_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8)
char name[VEC_NAME_SIZE];
@@ -320,6 +366,7 @@ struct qede_fastpath {
#define XMIT_L4_CSUM BIT(0)
#define XMIT_LSO BIT(1)
#define XMIT_ENC BIT(2)
+#define XMIT_ENC_GSO_L4_CSUM BIT(3)
#define QEDE_CSUM_ERROR BIT(0)
#define QEDE_CSUM_UNNECESSARY BIT(1)
@@ -329,8 +376,13 @@ struct qede_fastpath {
#define QEDE_SP_VXLAN_PORT_CONFIG 2
#define QEDE_SP_GENEVE_PORT_CONFIG 3
-union qede_reload_args {
- u16 mtu;
+struct qede_reload_args {
+ void (*func)(struct qede_dev *edev, struct qede_reload_args *args);
+ union {
+ netdev_features_t features;
+ struct bpf_prog *new_prog;
+ u16 mtu;
+ } u;
};
#ifdef CONFIG_DCB
@@ -339,15 +391,14 @@ void qede_set_dcbnl_ops(struct net_device *ndev);
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);
+ struct qede_reload_args *args, bool is_locked);
int qede_change_mtu(struct net_device *dev, int new_mtu);
void qede_fill_by_demand_stats(struct qede_dev *edev);
+void __qede_lock(struct qede_dev *edev);
+void __qede_unlock(struct qede_dev *edev);
bool qede_has_rx_work(struct qede_rx_queue *rxq);
int qede_txq_has_work(struct qede_tx_queue *txq);
-void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, struct qede_dev *edev,
- u8 count);
+void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, u8 count);
void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
#define RX_RING_SIZE_POW 13
@@ -362,8 +413,9 @@ void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
#define NUM_TX_BDS_MIN 128
#define NUM_TX_BDS_DEF NUM_TX_BDS_MAX
-#define QEDE_MIN_PKT_LEN 64
-#define QEDE_RX_HDR_SIZE 256
+#define QEDE_MIN_PKT_LEN 64
+#define QEDE_RX_HDR_SIZE 256
+#define QEDE_MAX_JUMBO_PACKET_SIZE 9600
#define for_each_queue(i) for (i = 0; i < edev->num_queues; i++)
#endif /* _QEDE_H_ */
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 7567cc464b88..1c48f445c93b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -16,13 +16,6 @@
#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)
@@ -39,12 +32,10 @@ static const struct {
QEDE_RQSTAT(rx_hw_errors),
QEDE_RQSTAT(rx_alloc_errors),
QEDE_RQSTAT(rx_ip_frags),
+ QEDE_RQSTAT(xdp_no_pass),
};
#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)))
#define QEDE_TQSTAT_OFFSET(stat_name) \
(offsetof(struct qede_tx_queue, stat_name))
#define QEDE_TQSTAT_STRING(stat_name) (#stat_name)
@@ -59,10 +50,12 @@ static const struct {
QEDE_TQSTAT(stopped_cnt),
};
-#define QEDE_TQSTATS_DATA(dev, sindex, tssid, tcid) \
- (*((u64 *)(((void *)(&dev->fp_array[tssid].txqs[tcid])) +\
- qede_tqstats_arr[(sindex)].offset)))
-
+#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)
static const struct {
u64 offset;
char string[ETH_GSTRING_LEN];
@@ -136,10 +129,6 @@ static const struct {
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)
enum {
@@ -157,6 +146,7 @@ enum qede_ethtool_tests {
QEDE_ETHTOOL_MEMORY_TEST,
QEDE_ETHTOOL_REGISTER_TEST,
QEDE_ETHTOOL_CLOCK_TEST,
+ QEDE_ETHTOOL_NVRAM_TEST,
QEDE_ETHTOOL_TEST_MAX
};
@@ -166,41 +156,63 @@ static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
"Memory (online)\t\t",
"Register (online)\t",
"Clock (online)\t\t",
+ "Nvram (online)\t\t",
};
+static void qede_get_strings_stats_txq(struct qede_dev *edev,
+ struct qede_tx_queue *txq, u8 **buf)
+{
+ int i;
+
+ for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
+ if (txq->is_xdp)
+ sprintf(*buf, "%d [XDP]: %s",
+ QEDE_TXQ_XDP_TO_IDX(edev, txq),
+ qede_tqstats_arr[i].string);
+ else
+ sprintf(*buf, "%d: %s", txq->index,
+ qede_tqstats_arr[i].string);
+ *buf += ETH_GSTRING_LEN;
+ }
+}
+
+static void qede_get_strings_stats_rxq(struct qede_dev *edev,
+ struct qede_rx_queue *rxq, u8 **buf)
+{
+ int i;
+
+ for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
+ sprintf(*buf, "%d: %s", rxq->rxq_id,
+ qede_rqstats_arr[i].string);
+ *buf += ETH_GSTRING_LEN;
+ }
+}
+
static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
{
- int i, j, k;
+ struct qede_fastpath *fp;
+ int i;
- for (i = 0, k = 0; i < QEDE_QUEUE_CNT(edev); i++) {
- int tc;
+ /* Account for queue statistics */
+ for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
+ fp = &edev->fp_array[i];
- if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
- for (j = 0; j < QEDE_NUM_RQSTATS; j++)
- sprintf(buf + (k + j) * ETH_GSTRING_LEN,
- "%d: %s", i,
- qede_rqstats_arr[j].string);
- k += QEDE_NUM_RQSTATS;
- }
+ if (fp->type & QEDE_FASTPATH_RX)
+ qede_get_strings_stats_rxq(edev, fp->rxq, &buf);
- if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
- for (tc = 0; tc < edev->num_tc; tc++) {
- for (j = 0; j < QEDE_NUM_TQSTATS; j++)
- sprintf(buf + (k + j) *
- ETH_GSTRING_LEN,
- "%d.%d: %s", i, tc,
- qede_tqstats_arr[j].string);
- k += QEDE_NUM_TQSTATS;
- }
- }
+ if (fp->type & QEDE_FASTPATH_XDP)
+ qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);
+
+ if (fp->type & QEDE_FASTPATH_TX)
+ qede_get_strings_stats_txq(edev, fp->txq, &buf);
}
- for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) {
+ /* Account for non-queue statistics */
+ for (i = 0; i < QEDE_NUM_STATS; i++) {
if (IS_VF(edev) && qede_stats_arr[i].pf_only)
continue;
- strcpy(buf + (k + j) * ETH_GSTRING_LEN,
- qede_stats_arr[i].string);
- j++;
+ strcpy(buf, qede_stats_arr[i].string);
+ buf += ETH_GSTRING_LEN;
}
}
@@ -226,42 +238,61 @@ static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
}
}
+static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf)
+{
+ int i;
+
+ for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
+ **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset));
+ (*buf)++;
+ }
+}
+
+static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf)
+{
+ int i;
+
+ for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
+ **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset));
+ (*buf)++;
+ }
+}
+
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;
+ struct qede_fastpath *fp;
+ int i;
qede_fill_by_demand_stats(edev);
- mutex_lock(&edev->qede_lock);
+ /* Need to protect the access to the fastpath array */
+ __qede_lock(edev);
- for (qid = 0; qid < QEDE_QUEUE_CNT(edev); qid++) {
- int tc;
+ for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
+ fp = &edev->fp_array[i];
- if (edev->fp_array[qid].type & QEDE_FASTPATH_RX) {
- for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++)
- buf[cnt++] = QEDE_RQSTATS_DATA(edev, sidx, qid);
- }
+ if (fp->type & QEDE_FASTPATH_RX)
+ qede_get_ethtool_stats_rxq(fp->rxq, &buf);
- if (edev->fp_array[qid].type & QEDE_FASTPATH_TX) {
- for (tc = 0; tc < edev->num_tc; tc++) {
- for (sidx = 0; sidx < QEDE_NUM_TQSTATS; sidx++)
- buf[cnt++] = QEDE_TQSTATS_DATA(edev,
- sidx,
- qid, tc);
- }
- }
+ if (fp->type & QEDE_FASTPATH_XDP)
+ qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);
+
+ if (fp->type & QEDE_FASTPATH_TX)
+ qede_get_ethtool_stats_txq(fp->txq, &buf);
}
- for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++) {
- if (IS_VF(edev) && qede_stats_arr[sidx].pf_only)
+ for (i = 0; i < QEDE_NUM_STATS; i++) {
+ if (IS_VF(edev) && qede_stats_arr[i].pf_only)
continue;
- buf[cnt++] = QEDE_STATS_DATA(edev, sidx);
+ *buf = *((u64 *)(((void *)&edev->stats) +
+ qede_stats_arr[i].offset));
+
+ buf++;
}
- mutex_unlock(&edev->qede_lock);
+ __qede_unlock(edev);
}
static int qede_get_sset_count(struct net_device *dev, int stringset)
@@ -278,8 +309,18 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
if (qede_stats_arr[i].pf_only)
num_stats--;
}
- return num_stats + QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS +
- QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * edev->num_tc;
+
+ /* Account for the Regular Tx statistics */
+ num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS;
+
+ /* Account for the Regular Rx statistics */
+ num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
+
+ /* Account for XDP statistics [if needed] */
+ if (edev->xdp_prog)
+ num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS;
+ return num_stats;
+
case ETH_SS_PRIV_FLAGS:
return QEDE_PRI_FLAG_LEN;
case ETH_SS_TEST:
@@ -325,7 +366,7 @@ static const struct qede_link_mode_mapping qed_lm_map[] = {
{ \
int i; \
\
- for (i = 0; i < QED_LM_COUNT; i++) { \
+ for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \
if ((caps) & (qed_lm_map[i].qed_link_mode)) \
__set_bit(qed_lm_map[i].ethtool_link_mode,\
lk_ksettings->link_modes.name); \
@@ -336,7 +377,7 @@ static const struct qede_link_mode_mapping qed_lm_map[] = {
{ \
int i; \
\
- for (i = 0; i < QED_LM_COUNT; i++) { \
+ for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \
if (test_bit(qed_lm_map[i].ethtool_link_mode, \
lk_ksettings->link_modes.name)) \
caps |= qed_lm_map[i].qed_link_mode; \
@@ -350,6 +391,8 @@ static int qede_get_link_ksettings(struct net_device *dev,
struct qede_dev *edev = netdev_priv(dev);
struct qed_link_output current_link;
+ __qede_lock(edev);
+
memset(&current_link, 0, sizeof(current_link));
edev->ops->common->get_link(edev->cdev, &current_link);
@@ -369,6 +412,9 @@ static int qede_get_link_ksettings(struct net_device *dev,
base->speed = SPEED_UNKNOWN;
base->duplex = DUPLEX_UNKNOWN;
}
+
+ __qede_unlock(edev);
+
base->port = current_link.port;
base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
AUTONEG_DISABLE;
@@ -488,6 +534,45 @@ static void qede_get_drvinfo(struct net_device *ndev,
strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
}
+static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+
+ if (edev->dev_info.common.wol_support) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0;
+ }
+}
+
+static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+ struct qede_dev *edev = netdev_priv(ndev);
+ bool wol_requested;
+ int rc;
+
+ if (wol->wolopts & ~WAKE_MAGIC) {
+ DP_INFO(edev,
+ "Can't support WoL options other than magic-packet\n");
+ return -EINVAL;
+ }
+
+ wol_requested = !!(wol->wolopts & WAKE_MAGIC);
+ if (wol_requested == edev->wol_enabled)
+ return 0;
+
+ /* Need to actually change configuration */
+ if (!edev->dev_info.common.wol_support) {
+ DP_INFO(edev, "Device doesn't support WoL\n");
+ return -EINVAL;
+ }
+
+ rc = edev->ops->common->update_wol(edev->cdev, wol_requested);
+ if (!rc)
+ edev->wol_enabled = wol_requested;
+
+ return rc;
+}
+
static u32 qede_get_msglevel(struct net_device *ndev)
{
struct qede_dev *edev = netdev_priv(ndev);
@@ -638,8 +723,7 @@ static int qede_set_ringparam(struct net_device *dev,
edev->q_num_rx_buffers = ering->rx_pending;
edev->q_num_tx_buffers = ering->tx_pending;
- if (netif_running(edev->ndev))
- qede_reload(edev, NULL, NULL);
+ qede_reload(edev, NULL, false);
return 0;
}
@@ -724,35 +808,27 @@ static int qede_get_regs_len(struct net_device *ndev)
return -EINVAL;
}
-static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args)
+static void qede_update_mtu(struct qede_dev *edev,
+ struct qede_reload_args *args)
{
- edev->ndev->mtu = args->mtu;
+ edev->ndev->mtu = args->u.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;
- }
+ struct qede_reload_args args;
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);
+ /* Set the mtu field and re-start the interface if needed */
+ args.u.mtu = new_mtu;
+ args.func = &qede_update_mtu;
+ qede_reload(edev, &args, false);
- qede_update_mtu(edev, &args);
+ edev->ops->common->update_mtu(edev->cdev, new_mtu);
return 0;
}
@@ -836,8 +912,7 @@ static int qede_set_channels(struct net_device *dev,
sizeof(edev->rss_params.rss_ind_table));
}
- if (netif_running(dev))
- qede_reload(edev, NULL, NULL);
+ qede_reload(edev, NULL, false);
return 0;
}
@@ -1143,7 +1218,7 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
for_each_queue(i) {
if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
- txq = edev->fp_array[i].txqs;
+ txq = edev->fp_array[i].txq;
break;
}
}
@@ -1155,7 +1230,7 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
/* 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;
+ txq->sw_tx_ring.skbs[idx].skb = skb;
first_bd = qed_chain_produce(&txq->tx_pbl);
memset(first_bd, 0, sizeof(*first_bd));
val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
@@ -1209,7 +1284,7 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
txq->sw_tx_cons++;
- txq->sw_tx_ring[idx].skb = NULL;
+ txq->sw_tx_ring.skbs[idx].skb = NULL;
return 0;
}
@@ -1277,13 +1352,13 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev)
break;
}
- qede_recycle_rx_bd_ring(rxq, edev, 1);
+ qede_recycle_rx_bd_ring(rxq, 1);
qed_chain_recycle_consumed(&rxq->rx_comp_ring);
break;
}
DP_INFO(edev, "Not the transmitted packet\n");
- qede_recycle_rx_bd_ring(rxq, edev, 1);
+ qede_recycle_rx_bd_ring(rxq, 1);
qed_chain_recycle_consumed(&rxq->rx_comp_ring);
}
@@ -1405,6 +1480,11 @@ static void qede_self_test(struct net_device *dev,
buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
etest->flags |= ETH_TEST_FL_FAILED;
}
+
+ if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) {
+ buf[QEDE_ETHTOOL_NVRAM_TEST] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
}
static int qede_set_tunable(struct net_device *dev,
@@ -1455,6 +1535,8 @@ static const struct ethtool_ops qede_ethtool_ops = {
.get_drvinfo = qede_get_drvinfo,
.get_regs_len = qede_get_regs_len,
.get_regs = qede_get_regs,
+ .get_wol = qede_get_wol,
+ .set_wol = qede_set_wol,
.get_msglevel = qede_get_msglevel,
.set_msglevel = qede_set_msglevel,
.nway_reset = qede_nway_reset,
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 85f46dbecd5b..aecdd1c5c0ea 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -94,11 +94,26 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id);
#define TX_TIMEOUT (5 * HZ)
+/* Utilize last protocol index for XDP */
+#define XDP_PI 11
+
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_shutdown(struct pci_dev *pdev);
static void qede_link_update(void *dev, struct qed_link_output *link);
+/* The qede lock is used to protect driver state change and driver flows that
+ * are not reentrant.
+ */
+void __qede_lock(struct qede_dev *edev)
+{
+ mutex_lock(&edev->qede_lock);
+}
+
+void __qede_unlock(struct qede_dev *edev)
+{
+ mutex_unlock(&edev->qede_lock);
+}
+
#ifdef CONFIG_QED_SRIOV
static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos,
__be16 vlan_proto)
@@ -166,15 +181,20 @@ static struct pci_driver qede_pci_driver = {
.id_table = qede_pci_tbl,
.probe = qede_probe,
.remove = qede_remove,
+ .shutdown = qede_shutdown,
#ifdef CONFIG_QED_SRIOV
.sriov_configure = qede_sriov_configure,
#endif
};
-static void qede_force_mac(void *dev, u8 *mac)
+static void qede_force_mac(void *dev, u8 *mac, bool forced)
{
struct qede_dev *edev = dev;
+ /* MAC hints take effect only if we haven't set one already */
+ if (is_valid_ether_addr(edev->ndev->dev_addr) && !forced)
+ return;
+
ether_addr_copy(edev->ndev->dev_addr, mac);
ether_addr_copy(edev->primary_mac, mac);
}
@@ -284,12 +304,12 @@ 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 sk_buff *skb = txq->sw_tx_ring.skbs[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;
+ bool data_split = txq->sw_tx_ring.skbs[idx].flags & QEDE_TSO_SPLIT_BD;
int i, split_bd_len = 0;
if (unlikely(!skb)) {
@@ -329,20 +349,19 @@ static int qede_free_tx_pkt(struct qede_dev *edev,
/* Free skb */
dev_kfree_skb_any(skb);
- txq->sw_tx_ring[idx].skb = NULL;
- txq->sw_tx_ring[idx].flags = 0;
+ txq->sw_tx_ring.skbs[idx].skb = NULL;
+ txq->sw_tx_ring.skbs[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,
+static void qede_free_failed_tx_pkt(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 sk_buff *skb = txq->sw_tx_ring.skbs[idx].skb;
struct eth_tx_bd *tx_data_bd;
int i, split_bd_len = 0;
@@ -359,7 +378,7 @@ static void qede_free_failed_tx_pkt(struct qede_dev *edev,
nbd--;
}
- dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+ dma_unmap_single(txq->dev, BD_UNMAP_ADDR(first_bd),
BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
/* Unmap the data of the skb frags */
@@ -367,7 +386,7 @@ static void qede_free_failed_tx_pkt(struct qede_dev *edev,
tx_data_bd = (struct eth_tx_bd *)
qed_chain_produce(&txq->tx_pbl);
if (tx_data_bd->nbytes)
- dma_unmap_page(&edev->pdev->dev,
+ dma_unmap_page(txq->dev,
BD_UNMAP_ADDR(tx_data_bd),
BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
}
@@ -378,12 +397,11 @@ static void qede_free_failed_tx_pkt(struct qede_dev *edev,
/* Free skb */
dev_kfree_skb_any(skb);
- txq->sw_tx_ring[idx].skb = NULL;
- txq->sw_tx_ring[idx].flags = 0;
+ txq->sw_tx_ring.skbs[idx].skb = NULL;
+ txq->sw_tx_ring.skbs[idx].flags = 0;
}
-static u32 qede_xmit_type(struct qede_dev *edev,
- struct sk_buff *skb, int *ipv6_ext)
+static u32 qede_xmit_type(struct sk_buff *skb, int *ipv6_ext)
{
u32 rc = XMIT_L4_CSUM;
__be16 l3_proto;
@@ -396,8 +414,19 @@ static u32 qede_xmit_type(struct qede_dev *edev,
(ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
*ipv6_ext = 1;
- if (skb->encapsulation)
+ if (skb->encapsulation) {
rc |= XMIT_ENC;
+ if (skb_is_gso(skb)) {
+ unsigned short gso_type = skb_shinfo(skb)->gso_type;
+
+ if ((gso_type & SKB_GSO_UDP_TUNNEL_CSUM) ||
+ (gso_type & SKB_GSO_GRE_CSUM))
+ rc |= XMIT_ENC_GSO_L4_CSUM;
+
+ rc |= XMIT_LSO;
+ return rc;
+ }
+ }
if (skb_is_gso(skb))
rc |= XMIT_LSO;
@@ -439,18 +468,16 @@ static void qede_set_params_for_ipv6_ext(struct sk_buff *skb,
second_bd->data.bitfields2 = cpu_to_le16(bd2_bits2);
}
-static int map_frag_to_bd(struct qede_dev *edev,
+static int map_frag_to_bd(struct qede_tx_queue *txq,
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,
+ mapping = skb_frag_dma_map(txq->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");
+ if (unlikely(dma_mapping_error(txq->dev, mapping)))
return -ENOMEM;
- }
/* Setup the data pointer of the frag data */
BD_SET_UNMAP_ADDR_LEN(bd, mapping, skb_frag_size(frag));
@@ -470,8 +497,7 @@ static u16 qede_get_skb_hlen(struct sk_buff *skb, bool is_encap_pkt)
/* +2 for 1st BD for headers and 2nd BD for headlen (if required) */
#if ((MAX_SKB_FRAGS + 2) > ETH_TX_MAX_BDS_PER_NON_LSO_PACKET)
-static bool qede_pkt_req_lin(struct qede_dev *edev, struct sk_buff *skb,
- u8 xmit_type)
+static bool qede_pkt_req_lin(struct sk_buff *skb, u8 xmit_type)
{
int allowed_frags = ETH_TX_MAX_BDS_PER_NON_LSO_PACKET - 1;
@@ -507,6 +533,47 @@ static inline void qede_update_tx_producer(struct qede_tx_queue *txq)
mmiowb();
}
+static int qede_xdp_xmit(struct qede_dev *edev, struct qede_fastpath *fp,
+ struct sw_rx_data *metadata, u16 padding, u16 length)
+{
+ struct qede_tx_queue *txq = fp->xdp_tx;
+ u16 idx = txq->sw_tx_prod & NUM_TX_BDS_MAX;
+ struct eth_tx_1st_bd *first_bd;
+
+ if (!qed_chain_get_elem_left(&txq->tx_pbl)) {
+ txq->stopped_cnt++;
+ return -ENOMEM;
+ }
+
+ 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 =
+ BIT(ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT);
+ first_bd->data.bitfields |=
+ (length & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) <<
+ ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT;
+ first_bd->data.nbds = 1;
+
+ /* We can safely ignore the offset, as it's 0 for XDP */
+ BD_SET_UNMAP_ADDR_LEN(first_bd, metadata->mapping + padding, length);
+
+ /* Synchronize the buffer back to device, as program [probably]
+ * has changed it.
+ */
+ dma_sync_single_for_device(&edev->pdev->dev,
+ metadata->mapping + padding,
+ length, PCI_DMA_TODEVICE);
+
+ txq->sw_tx_ring.pages[idx] = metadata->data;
+ txq->sw_tx_prod++;
+
+ /* Mark the fastpath for future XDP doorbell */
+ fp->xdp_xmit = 1;
+
+ return 0;
+}
+
/* Main transmit function */
static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
struct net_device *ndev)
@@ -530,15 +597,15 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
/* Get tx-queue context and netdev index */
txq_index = skb_get_queue_mapping(skb);
WARN_ON(txq_index >= QEDE_TSS_COUNT(edev));
- txq = QEDE_TX_QUEUE(edev, txq_index);
+ txq = edev->fp_array[edev->fp_num_rx + txq_index].txq;
netdev_txq = netdev_get_tx_queue(ndev, txq_index);
WARN_ON(qed_chain_get_elem_left(&txq->tx_pbl) < (MAX_SKB_FRAGS + 1));
- xmit_type = qede_xmit_type(edev, skb, &ipv6_ext);
+ xmit_type = qede_xmit_type(skb, &ipv6_ext);
#if ((MAX_SKB_FRAGS + 2) > ETH_TX_MAX_BDS_PER_NON_LSO_PACKET)
- if (qede_pkt_req_lin(edev, skb, xmit_type)) {
+ if (qede_pkt_req_lin(skb, xmit_type)) {
if (skb_linearize(skb)) {
DP_NOTICE(edev,
"SKB linearization failed - silently dropping this SKB\n");
@@ -550,7 +617,7 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
/* 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;
+ txq->sw_tx_ring.skbs[idx].skb = skb;
first_bd = (struct eth_tx_1st_bd *)
qed_chain_produce(&txq->tx_pbl);
memset(first_bd, 0, sizeof(*first_bd));
@@ -558,11 +625,11 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
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,
+ mapping = dma_map_single(txq->dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
+ if (unlikely(dma_mapping_error(txq->dev, mapping))) {
DP_NOTICE(edev, "SKB mapping failed\n");
- qede_free_failed_tx_pkt(edev, txq, first_bd, 0, false);
+ qede_free_failed_tx_pkt(txq, first_bd, 0, false);
qede_update_tx_producer(txq);
return NETDEV_TX_OK;
}
@@ -633,6 +700,12 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
if (unlikely(xmit_type & XMIT_ENC)) {
first_bd->data.bd_flags.bitfields |=
1 << ETH_TX_1ST_BD_FLAGS_TUNN_IP_CSUM_SHIFT;
+
+ if (xmit_type & XMIT_ENC_GSO_L4_CSUM) {
+ u8 tmp = ETH_TX_1ST_BD_FLAGS_TUNN_L4_CSUM_SHIFT;
+
+ first_bd->data.bd_flags.bitfields |= 1 << tmp;
+ }
hlen = qede_get_skb_hlen(skb, true);
} else {
first_bd->data.bd_flags.bitfields |=
@@ -664,7 +737,7 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
/* this marks the BD as one that has no
* individual mapping
*/
- txq->sw_tx_ring[idx].flags |= QEDE_TSO_SPLIT_BD;
+ txq->sw_tx_ring.skbs[idx].flags |= QEDE_TSO_SPLIT_BD;
first_bd->nbytes = cpu_to_le16(hlen);
@@ -680,12 +753,11 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
/* 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,
+ rc = map_frag_to_bd(txq,
&skb_shinfo(skb)->frags[frag_idx],
tx_data_bd);
if (rc) {
- qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
- data_split);
+ qede_free_failed_tx_pkt(txq, first_bd, nbd, data_split);
qede_update_tx_producer(txq);
return NETDEV_TX_OK;
}
@@ -705,12 +777,11 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
memset(tx_data_bd, 0, sizeof(*tx_data_bd));
- rc = map_frag_to_bd(edev,
+ rc = map_frag_to_bd(txq,
&skb_shinfo(skb)->frags[frag_idx],
tx_data_bd);
if (rc) {
- qede_free_failed_tx_pkt(edev, txq, first_bd, nbd,
- data_split);
+ qede_free_failed_tx_pkt(txq, first_bd, nbd, data_split);
qede_update_tx_producer(txq);
return NETDEV_TX_OK;
}
@@ -775,6 +846,27 @@ int qede_txq_has_work(struct qede_tx_queue *txq)
return hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl);
}
+static void qede_xdp_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
+{
+ struct eth_tx_1st_bd *bd;
+ u16 hw_bd_cons;
+
+ hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
+ barrier();
+
+ while (hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl)) {
+ bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
+
+ dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(bd),
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ __free_page(txq->sw_tx_ring.pages[txq->sw_tx_cons &
+ NUM_TX_BDS_MAX]);
+
+ txq->sw_tx_cons++;
+ txq->xmit_pkts++;
+ }
+}
+
static int qede_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
{
struct netdev_queue *netdev_txq;
@@ -858,16 +950,6 @@ bool qede_has_rx_work(struct qede_rx_queue *rxq)
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;
-}
-
static inline void qede_rx_bd_ring_consume(struct qede_rx_queue *rxq)
{
qed_chain_consume(&rxq->rx_bd_ring);
@@ -877,8 +959,7 @@ static inline void qede_rx_bd_ring_consume(struct qede_rx_queue *rxq)
/* This function reuses the buffer(from an offset) from
* consumer index to producer index in the bd ring
*/
-static inline void qede_reuse_page(struct qede_dev *edev,
- struct qede_rx_queue *rxq,
+static inline void qede_reuse_page(struct qede_rx_queue *rxq,
struct sw_rx_data *curr_cons)
{
struct eth_rx_bd *rx_bd_prod = qed_chain_produce(&rxq->rx_bd_ring);
@@ -900,27 +981,62 @@ static inline void qede_reuse_page(struct qede_dev *edev,
/* In case of allocation failures reuse buffers
* from consumer index to produce buffers for firmware
*/
-void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq,
- struct qede_dev *edev, u8 count)
+void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, u8 count)
{
struct sw_rx_data *curr_cons;
for (; count > 0; count--) {
curr_cons = &rxq->sw_rx_ring[rxq->sw_rx_cons & NUM_RX_BDS_MAX];
- qede_reuse_page(edev, rxq, curr_cons);
+ qede_reuse_page(rxq, curr_cons);
qede_rx_bd_ring_consume(rxq);
}
}
-static inline int qede_realloc_rx_buffer(struct qede_dev *edev,
- struct qede_rx_queue *rxq,
+static int qede_alloc_rx_buffer(struct qede_rx_queue *rxq)
+{
+ struct sw_rx_data *sw_rx_data;
+ struct eth_rx_bd *rx_bd;
+ dma_addr_t mapping;
+ struct page *data;
+
+ data = alloc_pages(GFP_ATOMIC, 0);
+ if (unlikely(!data))
+ return -ENOMEM;
+
+ /* Map the entire page as it would be used
+ * for multiple RX buffer segment size mapping.
+ */
+ mapping = dma_map_page(rxq->dev, data, 0,
+ PAGE_SIZE, rxq->data_direction);
+ if (unlikely(dma_mapping_error(rxq->dev, mapping))) {
+ __free_page(data);
+ return -ENOMEM;
+ }
+
+ sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX];
+ sw_rx_data->page_offset = 0;
+ sw_rx_data->data = data;
+ 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;
+}
+
+static inline int qede_realloc_rx_buffer(struct qede_rx_queue *rxq,
struct sw_rx_data *curr_cons)
{
/* Move to the next segment in the page */
curr_cons->page_offset += rxq->rx_buf_seg_size;
if (curr_cons->page_offset == PAGE_SIZE) {
- if (unlikely(qede_alloc_rx_buffer(edev, rxq))) {
+ if (unlikely(qede_alloc_rx_buffer(rxq))) {
/* Since we failed to allocate new buffer
* current buffer can be used again.
*/
@@ -929,15 +1045,15 @@ static inline int qede_realloc_rx_buffer(struct qede_dev *edev,
return -ENOMEM;
}
- dma_unmap_page(&edev->pdev->dev, curr_cons->mapping,
- PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_unmap_page(rxq->dev, curr_cons->mapping,
+ PAGE_SIZE, rxq->data_direction);
} else {
/* Increment refcount of the page as we don't want
* network stack to take the ownership of the page
* which can be recycled multiple times by the driver.
*/
page_ref_inc(curr_cons->data);
- qede_reuse_page(edev, rxq, curr_cons);
+ qede_reuse_page(rxq, curr_cons);
}
return 0;
@@ -971,22 +1087,20 @@ void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq)
mmiowb();
}
-static u32 qede_get_rxhash(struct qede_dev *edev,
- u8 bitfields,
- __le32 rss_hash, enum pkt_hash_types *rxhash_type)
+static void qede_get_rxhash(struct sk_buff *skb, u8 bitfields, __le32 rss_hash)
{
+ enum pkt_hash_types hash_type = PKT_HASH_TYPE_NONE;
enum rss_hash_type htype;
+ u32 hash = 0;
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);
+ if (htype) {
+ hash_type = ((htype == RSS_HASH_TYPE_IPV4) ||
+ (htype == RSS_HASH_TYPE_IPV6)) ?
+ PKT_HASH_TYPE_L3 : PKT_HASH_TYPE_L4;
+ hash = le32_to_cpu(rss_hash);
}
- *rxhash_type = PKT_HASH_TYPE_NONE;
- return 0;
+ skb_set_hash(skb, hash, hash_type);
}
static void qede_set_skb_csum(struct sk_buff *skb, u8 csum_flag)
@@ -1002,12 +1116,14 @@ static void qede_set_skb_csum(struct sk_buff *skb, u8 csum_flag)
static inline void qede_skb_receive(struct qede_dev *edev,
struct qede_fastpath *fp,
+ struct qede_rx_queue *rxq,
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);
+ fp->rxq->rcv_pkts++;
}
static void qede_set_gro_params(struct qede_dev *edev,
@@ -1035,7 +1151,7 @@ static int qede_fill_frag_skb(struct qede_dev *edev,
struct qede_agg_info *tpa_info = &rxq->tpa_info[tpa_agg_index];
struct sk_buff *skb = tpa_info->skb;
- if (unlikely(tpa_info->agg_state != QEDE_AGG_STATE_START))
+ if (unlikely(tpa_info->state != QEDE_AGG_STATE_START))
goto out;
/* Add one frag and update the appropriate fields in the skb */
@@ -1043,7 +1159,7 @@ static int qede_fill_frag_skb(struct qede_dev *edev,
current_bd->data, current_bd->page_offset,
len_on_bd);
- if (unlikely(qede_realloc_rx_buffer(edev, rxq, current_bd))) {
+ if (unlikely(qede_realloc_rx_buffer(rxq, current_bd))) {
/* Incr page ref count to reuse on allocation failure
* so that it doesn't get freed while freeing SKB.
*/
@@ -1061,8 +1177,9 @@ static int qede_fill_frag_skb(struct qede_dev *edev,
return 0;
out:
- tpa_info->agg_state = QEDE_AGG_STATE_ERROR;
- qede_recycle_rx_bd_ring(rxq, edev, 1);
+ tpa_info->state = QEDE_AGG_STATE_ERROR;
+ qede_recycle_rx_bd_ring(rxq, 1);
+
return -ENOMEM;
}
@@ -1073,12 +1190,10 @@ static void qede_tpa_start(struct qede_dev *edev,
struct qede_agg_info *tpa_info = &rxq->tpa_info[cqe->tpa_agg_index];
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 *replace_buf = &tpa_info->replace_buf;
- dma_addr_t mapping = tpa_info->replace_buf_mapping;
+ struct sw_rx_data *replace_buf = &tpa_info->buffer;
+ dma_addr_t mapping = tpa_info->buffer_mapping;
struct sw_rx_data *sw_rx_data_cons;
struct sw_rx_data *sw_rx_data_prod;
- enum pkt_hash_types rxhash_type;
- u32 rxhash;
sw_rx_data_cons = &rxq->sw_rx_ring[rxq->sw_rx_cons & NUM_RX_BDS_MAX];
sw_rx_data_prod = &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX];
@@ -1099,11 +1214,11 @@ static void qede_tpa_start(struct qede_dev *edev,
/* move partial skb from cons to pool (don't unmap yet)
* save mapping, incase we drop the packet later on.
*/
- tpa_info->start_buf = *sw_rx_data_cons;
+ tpa_info->buffer = *sw_rx_data_cons;
mapping = HILO_U64(le32_to_cpu(rx_bd_cons->addr.hi),
le32_to_cpu(rx_bd_cons->addr.lo));
- tpa_info->start_buf_mapping = mapping;
+ tpa_info->buffer_mapping = mapping;
rxq->sw_rx_cons++;
/* set tpa state to start only if we are able to allocate skb
@@ -1114,27 +1229,27 @@ static void qede_tpa_start(struct qede_dev *edev,
le16_to_cpu(cqe->len_on_first_bd));
if (unlikely(!tpa_info->skb)) {
DP_NOTICE(edev, "Failed to allocate SKB for gro\n");
- tpa_info->agg_state = QEDE_AGG_STATE_ERROR;
+ tpa_info->state = QEDE_AGG_STATE_ERROR;
goto cons_buf;
}
- skb_put(tpa_info->skb, le16_to_cpu(cqe->len_on_first_bd));
- memcpy(&tpa_info->start_cqe, cqe, sizeof(tpa_info->start_cqe));
-
/* Start filling in the aggregation info */
+ skb_put(tpa_info->skb, le16_to_cpu(cqe->len_on_first_bd));
tpa_info->frag_id = 0;
- tpa_info->agg_state = QEDE_AGG_STATE_START;
+ tpa_info->state = QEDE_AGG_STATE_START;
- rxhash = qede_get_rxhash(edev, cqe->bitfields,
- cqe->rss_hash, &rxhash_type);
- skb_set_hash(tpa_info->skb, rxhash, rxhash_type);
+ /* Store some information from first CQE */
+ tpa_info->start_cqe_placement_offset = cqe->placement_offset;
+ tpa_info->start_cqe_bd_len = le16_to_cpu(cqe->len_on_first_bd);
if ((le16_to_cpu(cqe->pars_flags.flags) >>
PARSING_AND_ERR_FLAGS_TAG8021QEXIST_SHIFT) &
- PARSING_AND_ERR_FLAGS_TAG8021QEXIST_MASK)
+ PARSING_AND_ERR_FLAGS_TAG8021QEXIST_MASK)
tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
else
tpa_info->vlan_tag = 0;
+ qede_get_rxhash(tpa_info->skb, cqe->bitfields, cqe->rss_hash);
+
/* This is needed in order to enable forwarding support */
qede_set_gro_params(edev, tpa_info->skb, cqe);
@@ -1146,7 +1261,7 @@ cons_buf: /* We still need to handle bd_len_list to consume buffers */
if (unlikely(cqe->ext_bd_len_list[1])) {
DP_ERR(edev,
"Unlikely - got a TPA aggregation with more than one ext_bd_len_list entry in the TPA start\n");
- tpa_info->agg_state = QEDE_AGG_STATE_ERROR;
+ tpa_info->state = QEDE_AGG_STATE_ERROR;
}
}
@@ -1197,7 +1312,7 @@ static void qede_gro_receive(struct qede_dev *edev,
#ifdef CONFIG_INET
if (skb_shinfo(skb)->gso_size) {
- skb_set_network_header(skb, 0);
+ skb_reset_network_header(skb);
switch (skb->protocol) {
case htons(ETH_P_IP):
@@ -1216,7 +1331,7 @@ static void qede_gro_receive(struct qede_dev *edev,
send_skb:
skb_record_rx_queue(skb, fp->rxq->rxq_id);
- qede_skb_receive(edev, fp, skb, vlan_tag);
+ qede_skb_receive(edev, fp, fp->rxq, skb, vlan_tag);
}
static inline void qede_tpa_cont(struct qede_dev *edev,
@@ -1253,7 +1368,7 @@ static void qede_tpa_end(struct qede_dev *edev,
DP_ERR(edev,
"Strange - TPA emd with more than a single len_list entry\n");
- if (unlikely(tpa_info->agg_state != QEDE_AGG_STATE_START))
+ if (unlikely(tpa_info->state != QEDE_AGG_STATE_START))
goto err;
/* Sanity */
@@ -1267,14 +1382,9 @@ static void qede_tpa_end(struct qede_dev *edev,
le16_to_cpu(cqe->total_packet_len), skb->len);
memcpy(skb->data,
- page_address(tpa_info->start_buf.data) +
- tpa_info->start_cqe.placement_offset +
- tpa_info->start_buf.page_offset,
- le16_to_cpu(tpa_info->start_cqe.len_on_first_bd));
-
- /* Recycle [mapped] start buffer for the next replacement */
- tpa_info->replace_buf = tpa_info->start_buf;
- tpa_info->replace_buf_mapping = tpa_info->start_buf_mapping;
+ page_address(tpa_info->buffer.data) +
+ tpa_info->start_cqe_placement_offset +
+ tpa_info->buffer.page_offset, tpa_info->start_cqe_bd_len);
/* Finalize the SKB */
skb->protocol = eth_type_trans(skb, edev->ndev);
@@ -1287,18 +1397,11 @@ static void qede_tpa_end(struct qede_dev *edev,
qede_gro_receive(edev, fp, skb, tpa_info->vlan_tag);
- tpa_info->agg_state = QEDE_AGG_STATE_NONE;
+ tpa_info->state = QEDE_AGG_STATE_NONE;
return;
err:
- /* The BD starting the aggregation is still mapped; Re-use it for
- * future aggregations [as replacement buffer]
- */
- memcpy(&tpa_info->replace_buf, &tpa_info->start_buf,
- sizeof(struct sw_rx_data));
- tpa_info->replace_buf_mapping = tpa_info->start_buf_mapping;
- tpa_info->start_buf.data = NULL;
- tpa_info->agg_state = QEDE_AGG_STATE_NONE;
+ tpa_info->state = QEDE_AGG_STATE_NONE;
dev_kfree_skb_any(tpa_info->skb);
tpa_info->skb = NULL;
}
@@ -1380,238 +1483,364 @@ static bool qede_pkt_is_ip_fragmented(struct eth_fast_path_rx_reg_cqe *cqe,
return false;
}
-static int qede_rx_int(struct qede_fastpath *fp, int budget)
+/* Return true iff packet is to be passed to stack */
+static bool qede_rx_xdp(struct qede_dev *edev,
+ struct qede_fastpath *fp,
+ struct qede_rx_queue *rxq,
+ struct bpf_prog *prog,
+ struct sw_rx_data *bd,
+ struct eth_fast_path_rx_reg_cqe *cqe)
{
- 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;
+ u16 len = le16_to_cpu(cqe->len_on_first_bd);
+ struct xdp_buff xdp;
+ enum xdp_action act;
- hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
- sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+ xdp.data = page_address(bd->data) + cqe->placement_offset;
+ xdp.data_end = xdp.data + len;
- /* 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.
+ /* Queues always have a full reset currently, so for the time
+ * being until there's atomic program replace just mark read
+ * side for map helpers.
*/
- rmb();
+ rcu_read_lock();
+ act = bpf_prog_run_xdp(prog, &xdp);
+ rcu_read_unlock();
- /* 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;
- struct page *data;
- __le16 flags;
- u16 len, pad;
- u32 rx_hash;
-
- /* 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->id,
- (struct eth_slow_path_rx_cqe *)cqe);
- goto next_cqe;
+ if (act == XDP_PASS)
+ return true;
+
+ /* Count number of packets not to be passed to stack */
+ rxq->xdp_no_pass++;
+
+ switch (act) {
+ case XDP_TX:
+ /* We need the replacement buffer before transmit. */
+ if (qede_alloc_rx_buffer(rxq)) {
+ qede_recycle_rx_bd_ring(rxq, 1);
+ return false;
}
- if (cqe_type != ETH_RX_CQE_TYPE_REGULAR) {
- switch (cqe_type) {
- case ETH_RX_CQE_TYPE_TPA_START:
- qede_tpa_start(edev, rxq,
- &cqe->fast_path_tpa_start);
- goto next_cqe;
- case ETH_RX_CQE_TYPE_TPA_CONT:
- qede_tpa_cont(edev, rxq,
- &cqe->fast_path_tpa_cont);
- goto next_cqe;
- case ETH_RX_CQE_TYPE_TPA_END:
- qede_tpa_end(edev, fp,
- &cqe->fast_path_tpa_end);
- goto next_rx_only;
- default:
- break;
- }
+ /* Now if there's a transmission problem, we'd still have to
+ * throw current buffer, as replacement was already allocated.
+ */
+ if (qede_xdp_xmit(edev, fp, bd, cqe->placement_offset, len)) {
+ dma_unmap_page(rxq->dev, bd->mapping,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ __free_page(bd->data);
}
- /* 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->len_on_first_bd);
- pad = fp_cqe->placement_offset;
- flags = cqe->fast_path_regular.pars_flags.flags;
-
- /* If this is an error packet then drop it */
- parse_flag = le16_to_cpu(flags);
-
- csum_flag = qede_check_csum(parse_flag);
- if (unlikely(csum_flag == QEDE_CSUM_ERROR)) {
- if (qede_pkt_is_ip_fragmented(&cqe->fast_path_regular,
- parse_flag)) {
- rxq->rx_ip_frags++;
- goto alloc_skb;
- }
+ /* Regardless, we've consumed an Rx BD */
+ qede_rx_bd_ring_consume(rxq);
+ return false;
- DP_NOTICE(edev,
- "CQE in CONS = %u has error, flags = %x, dropping incoming packet\n",
- sw_comp_cons, parse_flag);
- rxq->rx_hw_errors++;
- qede_recycle_rx_bd_ring(rxq, edev, fp_cqe->bd_num);
- goto next_cqe;
- }
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ case XDP_ABORTED:
+ case XDP_DROP:
+ qede_recycle_rx_bd_ring(rxq, cqe->bd_num);
+ }
-alloc_skb:
- skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
- if (unlikely(!skb)) {
- DP_NOTICE(edev,
- "skb allocation failed, dropping incoming packet\n");
- qede_recycle_rx_bd_ring(rxq, edev, fp_cqe->bd_num);
- rxq->rx_alloc_errors++;
- goto next_cqe;
+ return false;
+}
+
+static struct sk_buff *qede_rx_allocate_skb(struct qede_dev *edev,
+ struct qede_rx_queue *rxq,
+ struct sw_rx_data *bd, u16 len,
+ u16 pad)
+{
+ unsigned int offset = bd->page_offset;
+ struct skb_frag_struct *frag;
+ struct page *page = bd->data;
+ unsigned int pull_len;
+ struct sk_buff *skb;
+ unsigned char *va;
+
+ /* Allocate a new SKB with a sufficient large header len */
+ skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
+ if (unlikely(!skb))
+ return NULL;
+
+ /* Copy data into SKB - if it's small, we can simply copy it and
+ * re-use the already allcoated & mapped memory.
+ */
+ if (len + pad <= edev->rx_copybreak) {
+ memcpy(skb_put(skb, len),
+ page_address(page) + pad + offset, len);
+ qede_reuse_page(rxq, bd);
+ goto out;
+ }
+
+ frag = &skb_shinfo(skb)->frags[0];
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+ page, pad + offset, len, rxq->rx_buf_seg_size);
+
+ va = skb_frag_address(frag);
+ pull_len = eth_get_headlen(va, QEDE_RX_HDR_SIZE);
+
+ /* Align the pull_len to optimize memcpy */
+ memcpy(skb->data, va, ALIGN(pull_len, sizeof(long)));
+
+ /* Correct the skb & frag sizes offset after the pull */
+ skb_frag_size_sub(frag, pull_len);
+ frag->page_offset += pull_len;
+ skb->data_len -= pull_len;
+ skb->tail += pull_len;
+
+ if (unlikely(qede_realloc_rx_buffer(rxq, bd))) {
+ /* Incr page ref count to reuse on allocation failure so
+ * that it doesn't get freed while freeing SKB [as its
+ * already mapped there].
+ */
+ page_ref_inc(page);
+ dev_kfree_skb_any(skb);
+ return NULL;
+ }
+
+out:
+ /* We've consumed the first BD and prepared an SKB */
+ qede_rx_bd_ring_consume(rxq);
+ return skb;
+}
+
+static int qede_rx_build_jumbo(struct qede_dev *edev,
+ struct qede_rx_queue *rxq,
+ struct sk_buff *skb,
+ struct eth_fast_path_rx_reg_cqe *cqe,
+ u16 first_bd_len)
+{
+ u16 pkt_len = le16_to_cpu(cqe->pkt_len);
+ struct sw_rx_data *bd;
+ u16 bd_cons_idx;
+ u8 num_frags;
+
+ pkt_len -= first_bd_len;
+
+ /* We've already used one BD for the SKB. Now take care of the rest */
+ for (num_frags = cqe->bd_num - 1; num_frags > 0; num_frags--) {
+ u16 cur_size = pkt_len > rxq->rx_buf_size ? rxq->rx_buf_size :
+ pkt_len;
+
+ if (unlikely(!cur_size)) {
+ DP_ERR(edev,
+ "Still got %d BDs for mapping jumbo, but length became 0\n",
+ num_frags);
+ goto out;
}
- /* Copy data into SKB */
- if (len + pad <= edev->rx_copybreak) {
- memcpy(skb_put(skb, len),
- page_address(data) + pad +
- sw_rx_data->page_offset, len);
- qede_reuse_page(edev, rxq, sw_rx_data);
+ /* We need a replacement buffer for each BD */
+ if (unlikely(qede_alloc_rx_buffer(rxq)))
+ goto out;
+
+ /* Now that we've allocated the replacement buffer,
+ * we can safely consume the next BD and map it to the SKB.
+ */
+ bd_cons_idx = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
+ bd = &rxq->sw_rx_ring[bd_cons_idx];
+ qede_rx_bd_ring_consume(rxq);
+
+ dma_unmap_page(rxq->dev, bd->mapping,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
+ bd->data, 0, cur_size);
+
+ skb->truesize += PAGE_SIZE;
+ skb->data_len += cur_size;
+ skb->len += cur_size;
+ pkt_len -= cur_size;
+ }
+
+ if (unlikely(pkt_len))
+ DP_ERR(edev,
+ "Mapped all BDs of jumbo, but still have %d bytes\n",
+ pkt_len);
+
+out:
+ return num_frags;
+}
+
+static int qede_rx_process_tpa_cqe(struct qede_dev *edev,
+ struct qede_fastpath *fp,
+ struct qede_rx_queue *rxq,
+ union eth_rx_cqe *cqe,
+ enum eth_rx_cqe_type type)
+{
+ switch (type) {
+ case ETH_RX_CQE_TYPE_TPA_START:
+ qede_tpa_start(edev, rxq, &cqe->fast_path_tpa_start);
+ return 0;
+ case ETH_RX_CQE_TYPE_TPA_CONT:
+ qede_tpa_cont(edev, rxq, &cqe->fast_path_tpa_cont);
+ return 0;
+ case ETH_RX_CQE_TYPE_TPA_END:
+ qede_tpa_end(edev, fp, &cqe->fast_path_tpa_end);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int qede_rx_process_cqe(struct qede_dev *edev,
+ struct qede_fastpath *fp,
+ struct qede_rx_queue *rxq)
+{
+ struct bpf_prog *xdp_prog = READ_ONCE(rxq->xdp_prog);
+ struct eth_fast_path_rx_reg_cqe *fp_cqe;
+ u16 len, pad, bd_cons_idx, parse_flag;
+ enum eth_rx_cqe_type cqe_type;
+ union eth_rx_cqe *cqe;
+ struct sw_rx_data *bd;
+ struct sk_buff *skb;
+ __le16 flags;
+ u8 csum_flag;
+
+ /* 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;
+
+ /* Process an unlikely slowpath event */
+ if (unlikely(cqe_type == ETH_RX_CQE_TYPE_SLOW_PATH)) {
+ struct eth_slow_path_rx_cqe *sp_cqe;
+
+ sp_cqe = (struct eth_slow_path_rx_cqe *)cqe;
+ edev->ops->eth_cqe_completion(edev->cdev, fp->id, sp_cqe);
+ return 0;
+ }
+
+ /* Handle TPA cqes */
+ if (cqe_type != ETH_RX_CQE_TYPE_REGULAR)
+ return qede_rx_process_tpa_cqe(edev, fp, rxq, cqe, cqe_type);
+
+ /* Get the data from the SW ring; Consume it only after it's evident
+ * we wouldn't recycle it.
+ */
+ bd_cons_idx = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
+ bd = &rxq->sw_rx_ring[bd_cons_idx];
+
+ fp_cqe = &cqe->fast_path_regular;
+ len = le16_to_cpu(fp_cqe->len_on_first_bd);
+ pad = fp_cqe->placement_offset;
+
+ /* Run eBPF program if one is attached */
+ if (xdp_prog)
+ if (!qede_rx_xdp(edev, fp, rxq, xdp_prog, bd, fp_cqe))
+ return 1;
+
+ /* If this is an error packet then drop it */
+ flags = cqe->fast_path_regular.pars_flags.flags;
+ parse_flag = le16_to_cpu(flags);
+
+ csum_flag = qede_check_csum(parse_flag);
+ if (unlikely(csum_flag == QEDE_CSUM_ERROR)) {
+ if (qede_pkt_is_ip_fragmented(fp_cqe, parse_flag)) {
+ rxq->rx_ip_frags++;
} else {
- struct skb_frag_struct *frag;
- unsigned int pull_len;
- unsigned char *va;
-
- frag = &skb_shinfo(skb)->frags[0];
-
- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, data,
- pad + sw_rx_data->page_offset,
- len, rxq->rx_buf_seg_size);
-
- va = skb_frag_address(frag);
- pull_len = eth_get_headlen(va, QEDE_RX_HDR_SIZE);
-
- /* Align the pull_len to optimize memcpy */
- memcpy(skb->data, va, ALIGN(pull_len, sizeof(long)));
-
- skb_frag_size_sub(frag, pull_len);
- frag->page_offset += pull_len;
- skb->data_len -= pull_len;
- skb->tail += pull_len;
-
- if (unlikely(qede_realloc_rx_buffer(edev, rxq,
- sw_rx_data))) {
- DP_ERR(edev, "Failed to allocate rx buffer\n");
- /* Incr page ref count to reuse on allocation
- * failure so that it doesn't get freed while
- * freeing SKB.
- */
-
- page_ref_inc(sw_rx_data->data);
- rxq->rx_alloc_errors++;
- qede_recycle_rx_bd_ring(rxq, edev,
- fp_cqe->bd_num);
- dev_kfree_skb_any(skb);
- goto next_cqe;
- }
+ DP_NOTICE(edev,
+ "CQE has error, flags = %x, dropping incoming packet\n",
+ parse_flag);
+ rxq->rx_hw_errors++;
+ qede_recycle_rx_bd_ring(rxq, fp_cqe->bd_num);
+ return 0;
}
+ }
- qede_rx_bd_ring_consume(rxq);
+ /* Basic validation passed; Need to prepare an SKB. This would also
+ * guarantee to finally consume the first BD upon success.
+ */
+ skb = qede_rx_allocate_skb(edev, rxq, bd, len, pad);
+ if (!skb) {
+ rxq->rx_alloc_errors++;
+ qede_recycle_rx_bd_ring(rxq, fp_cqe->bd_num);
+ return 0;
+ }
- if (fp_cqe->bd_num != 1) {
- u16 pkt_len = le16_to_cpu(fp_cqe->pkt_len);
- u8 num_frags;
-
- pkt_len -= len;
-
- for (num_frags = fp_cqe->bd_num - 1; num_frags > 0;
- num_frags--) {
- u16 cur_size = pkt_len > rxq->rx_buf_size ?
- rxq->rx_buf_size : pkt_len;
- if (unlikely(!cur_size)) {
- DP_ERR(edev,
- "Still got %d BDs for mapping jumbo, but length became 0\n",
- num_frags);
- qede_recycle_rx_bd_ring(rxq, edev,
- num_frags);
- dev_kfree_skb_any(skb);
- goto next_cqe;
- }
-
- if (unlikely(qede_alloc_rx_buffer(edev, rxq))) {
- qede_recycle_rx_bd_ring(rxq, edev,
- num_frags);
- dev_kfree_skb_any(skb);
- goto next_cqe;
- }
-
- sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
- sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
- qede_rx_bd_ring_consume(rxq);
-
- dma_unmap_page(&edev->pdev->dev,
- sw_rx_data->mapping,
- PAGE_SIZE, DMA_FROM_DEVICE);
-
- skb_fill_page_desc(skb,
- skb_shinfo(skb)->nr_frags++,
- sw_rx_data->data, 0,
- cur_size);
-
- skb->truesize += PAGE_SIZE;
- skb->data_len += cur_size;
- skb->len += cur_size;
- pkt_len -= cur_size;
- }
+ /* In case of Jumbo packet, several PAGE_SIZEd buffers will be pointed
+ * by a single cqe.
+ */
+ if (fp_cqe->bd_num > 1) {
+ u16 unmapped_frags = qede_rx_build_jumbo(edev, rxq, skb,
+ fp_cqe, len);
- if (unlikely(pkt_len))
- DP_ERR(edev,
- "Mapped all BDs of jumbo, but still have %d bytes\n",
- pkt_len);
+ if (unlikely(unmapped_frags > 0)) {
+ qede_recycle_rx_bd_ring(rxq, unmapped_frags);
+ dev_kfree_skb_any(skb);
+ return 0;
}
+ }
- skb->protocol = eth_type_trans(skb, edev->ndev);
+ /* The SKB contains all the data. Now prepare meta-magic */
+ skb->protocol = eth_type_trans(skb, edev->ndev);
+ qede_get_rxhash(skb, fp_cqe->bitfields, fp_cqe->rss_hash);
+ qede_set_skb_csum(skb, csum_flag);
+ skb_record_rx_queue(skb, rxq->rxq_id);
- rx_hash = qede_get_rxhash(edev, fp_cqe->bitfields,
- fp_cqe->rss_hash, &rxhash_type);
+ /* SKB is prepared - pass it to stack */
+ qede_skb_receive(edev, fp, rxq, skb, le16_to_cpu(fp_cqe->vlan_tag));
- skb_set_hash(skb, rx_hash, rxhash_type);
+ return 1;
+}
- qede_set_skb_csum(skb, csum_flag);
+static int qede_rx_int(struct qede_fastpath *fp, int budget)
+{
+ struct qede_rx_queue *rxq = fp->rxq;
+ struct qede_dev *edev = fp->edev;
+ u16 hw_comp_cons, sw_comp_cons;
+ int work_done = 0;
- skb_record_rx_queue(skb, fp->rxq->rxq_id);
+ hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
+ sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
- qede_skb_receive(edev, fp, skb, le16_to_cpu(fp_cqe->vlan_tag));
-next_rx_only:
- rx_pkt++;
+ /* 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();
-next_cqe: /* don't consume bd rx buffer */
+ /* Loop to complete all indicated BDs */
+ while ((sw_comp_cons != hw_comp_cons) && (work_done < budget)) {
+ qede_rx_process_cqe(edev, fp, rxq);
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... */
+ work_done++;
+ }
/* Update producers */
qede_update_rx_prod(edev, rxq);
- rxq->rcv_pkts += rx_pkt;
+ return work_done;
+}
+
+static bool qede_poll_is_more_work(struct qede_fastpath *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 (likely(fp->type & QEDE_FASTPATH_RX))
+ if (qede_has_rx_work(fp->rxq))
+ return true;
- return rx_pkt;
+ if (fp->type & QEDE_FASTPATH_XDP)
+ if (qede_txq_has_work(fp->xdp_tx))
+ return true;
+
+ if (likely(fp->type & QEDE_FASTPATH_TX))
+ if (qede_txq_has_work(fp->txq))
+ return true;
+
+ return false;
}
static int qede_poll(struct napi_struct *napi, int budget)
@@ -1620,48 +1849,35 @@ static int qede_poll(struct napi_struct *napi, int budget)
napi);
struct qede_dev *edev = fp->edev;
int rx_work_done = 0;
- u8 tc;
- for (tc = 0; tc < edev->num_tc; tc++)
- if (likely(fp->type & QEDE_FASTPATH_TX) &&
- qede_txq_has_work(&fp->txqs[tc]))
- qede_tx_int(edev, &fp->txqs[tc]);
+ if (likely(fp->type & QEDE_FASTPATH_TX) && qede_txq_has_work(fp->txq))
+ qede_tx_int(edev, fp->txq);
+
+ if ((fp->type & QEDE_FASTPATH_XDP) && qede_txq_has_work(fp->xdp_tx))
+ qede_xdp_tx_int(edev, fp->xdp_tx);
rx_work_done = (likely(fp->type & QEDE_FASTPATH_RX) &&
qede_has_rx_work(fp->rxq)) ?
qede_rx_int(fp, budget) : 0;
if (rx_work_done < budget) {
- 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();
-
- /* Fall out from the NAPI loop if needed */
- if (!((likely(fp->type & QEDE_FASTPATH_RX) &&
- qede_has_rx_work(fp->rxq)) ||
- (likely(fp->type & QEDE_FASTPATH_TX) &&
- qede_has_tx_work(fp)))) {
+ if (!qede_poll_is_more_work(fp)) {
napi_complete(napi);
/* Update and reenable interrupts */
- qed_sb_ack(fp->sb_info, IGU_INT_ENABLE,
- 1 /*update*/);
+ qed_sb_ack(fp->sb_info, IGU_INT_ENABLE, 1);
} else {
rx_work_done = budget;
}
}
+ if (fp->xdp_xmit) {
+ u16 xdp_prod = qed_chain_get_prod_idx(&fp->xdp_tx->tx_pbl);
+
+ fp->xdp_xmit = 0;
+ fp->xdp_tx->tx_db.data.bd_prod = cpu_to_le16(xdp_prod);
+ qede_update_tx_producer(fp->xdp_tx);
+ }
+
return rx_work_done;
}
@@ -1912,7 +2128,7 @@ static int qede_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct qede_dev *edev = netdev_priv(dev);
struct qede_vlan *vlan, *tmp;
- int rc;
+ int rc = 0;
DP_VERBOSE(edev, NETIF_MSG_IFUP, "Adding vlan 0x%04x\n", vid);
@@ -1936,6 +2152,7 @@ static int qede_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
}
/* If interface is down, cache this VLAN ID and return */
+ __qede_lock(edev);
if (edev->state != QEDE_STATE_OPEN) {
DP_VERBOSE(edev, NETIF_MSG_IFDOWN,
"Interface is down, VLAN %d will be configured when interface is up\n",
@@ -1943,8 +2160,7 @@ static int qede_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
if (vid != 0)
edev->non_configured_vlans++;
list_add(&vlan->list, &edev->vlan_list);
-
- return 0;
+ goto out;
}
/* Check for the filter limit.
@@ -1960,7 +2176,7 @@ static int qede_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
DP_ERR(edev, "Failed to configure VLAN %d\n",
vlan->vid);
kfree(vlan);
- return -EINVAL;
+ goto out;
}
vlan->configured = true;
@@ -1977,7 +2193,9 @@ static int qede_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
list_add(&vlan->list, &edev->vlan_list);
- return 0;
+out:
+ __qede_unlock(edev);
+ return rc;
}
static void qede_del_vlan_from_list(struct qede_dev *edev,
@@ -2054,11 +2272,12 @@ static int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{
struct qede_dev *edev = netdev_priv(dev);
struct qede_vlan *vlan = NULL;
- int rc;
+ int rc = 0;
DP_VERBOSE(edev, NETIF_MSG_IFDOWN, "Removing vlan 0x%04x\n", vid);
/* Find whether entry exists */
+ __qede_lock(edev);
list_for_each_entry(vlan, &edev->vlan_list, list)
if (vlan->vid == vid)
break;
@@ -2066,7 +2285,7 @@ static int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
if (!vlan || (vlan->vid != vid)) {
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
"Vlan isn't configured\n");
- return 0;
+ goto out;
}
if (edev->state != QEDE_STATE_OPEN) {
@@ -2076,7 +2295,7 @@ static int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
DP_VERBOSE(edev, NETIF_MSG_IFDOWN,
"Interface is down, removing VLAN from list only\n");
qede_del_vlan_from_list(edev, vlan);
- return 0;
+ goto out;
}
/* Remove vlan */
@@ -2085,7 +2304,7 @@ static int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
vid);
if (rc) {
DP_ERR(edev, "Failed to remove VLAN %d\n", vid);
- return -EINVAL;
+ goto out;
}
}
@@ -2096,6 +2315,8 @@ static int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
*/
rc = qede_configure_vlan_filters(edev);
+out:
+ __qede_unlock(edev);
return rc;
}
@@ -2125,7 +2346,13 @@ static void qede_vlan_mark_nonconfigured(struct qede_dev *edev)
edev->accept_any_vlan = false;
}
-static int qede_set_features(struct net_device *dev, netdev_features_t features)
+static void qede_set_features_reload(struct qede_dev *edev,
+ struct qede_reload_args *args)
+{
+ edev->ndev->features = args->u.features;
+}
+
+int qede_set_features(struct net_device *dev, netdev_features_t features)
{
struct qede_dev *edev = netdev_priv(dev);
netdev_features_t changes = features ^ dev->features;
@@ -2139,9 +2366,23 @@ static int qede_set_features(struct net_device *dev, netdev_features_t features)
need_reload = edev->gro_disable;
}
- if (need_reload && netif_running(edev->ndev)) {
- dev->features = features;
- qede_reload(edev, NULL, NULL);
+ if (need_reload) {
+ struct qede_reload_args args;
+
+ args.u.features = features;
+ args.func = &qede_set_features_reload;
+
+ /* Make sure that we definitely need to reload.
+ * In case of an eBPF attached program, there will be no FW
+ * aggregations, so no need to actually reload.
+ */
+ __qede_lock(edev);
+ if (edev->xdp_prog)
+ args.func(edev, &args);
+ else
+ qede_reload(edev, &args, true);
+ __qede_unlock(edev);
+
return 1;
}
@@ -2218,6 +2459,82 @@ static void qede_udp_tunnel_del(struct net_device *dev,
schedule_delayed_work(&edev->sp_task, 0);
}
+/* 8B udp header + 8B base tunnel header + 32B option length */
+#define QEDE_MAX_TUN_HDR_LEN 48
+
+static netdev_features_t qede_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ if (skb->encapsulation) {
+ u8 l4_proto = 0;
+
+ switch (vlan_get_protocol(skb)) {
+ case htons(ETH_P_IP):
+ l4_proto = ip_hdr(skb)->protocol;
+ break;
+ case htons(ETH_P_IPV6):
+ l4_proto = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ return features;
+ }
+
+ /* Disable offloads for geneve tunnels, as HW can't parse
+ * the geneve header which has option length greater than 32B.
+ */
+ if ((l4_proto == IPPROTO_UDP) &&
+ ((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) > QEDE_MAX_TUN_HDR_LEN))
+ return features & ~(NETIF_F_CSUM_MASK |
+ NETIF_F_GSO_MASK);
+ }
+
+ return features;
+}
+
+static void qede_xdp_reload_func(struct qede_dev *edev,
+ struct qede_reload_args *args)
+{
+ struct bpf_prog *old;
+
+ old = xchg(&edev->xdp_prog, args->u.new_prog);
+ if (old)
+ bpf_prog_put(old);
+}
+
+static int qede_xdp_set(struct qede_dev *edev, struct bpf_prog *prog)
+{
+ struct qede_reload_args args;
+
+ if (prog && prog->xdp_adjust_head) {
+ DP_ERR(edev, "Does not support bpf_xdp_adjust_head()\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* If we're called, there was already a bpf reference increment */
+ args.func = &qede_xdp_reload_func;
+ args.u.new_prog = prog;
+ qede_reload(edev, &args, false);
+
+ return 0;
+}
+
+static int qede_xdp(struct net_device *dev, struct netdev_xdp *xdp)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+
+ switch (xdp->command) {
+ case XDP_SETUP_PROG:
+ return qede_xdp_set(edev, xdp->prog);
+ case XDP_QUERY_PROG:
+ xdp->prog_attached = !!edev->xdp_prog;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct net_device_ops qede_netdev_ops = {
.ndo_open = qede_open,
.ndo_stop = qede_close,
@@ -2242,6 +2559,8 @@ static const struct net_device_ops qede_netdev_ops = {
#endif
.ndo_udp_tunnel_add = qede_udp_tunnel_add,
.ndo_udp_tunnel_del = qede_udp_tunnel_del,
+ .ndo_features_check = qede_features_check,
+ .ndo_xdp = qede_xdp,
};
/* -------------------------------------------------------------------------
@@ -2282,8 +2601,6 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev,
memset(&edev->stats, 0, sizeof(edev->stats));
memcpy(&edev->dev_info, info, sizeof(*info));
- edev->num_tc = edev->dev_info.num_tc;
-
INIT_LIST_HEAD(&edev->vlan_list);
return edev;
@@ -2308,6 +2625,8 @@ static void qede_init_ndev(struct qede_dev *edev)
qede_set_ethtool_ops(ndev);
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+
/* user-changeble features */
hw_features = NETIF_F_GRO | NETIF_F_SG |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -2315,11 +2634,14 @@ static void qede_init_ndev(struct qede_dev *edev)
/* Encap features*/
hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
- NETIF_F_TSO_ECN;
+ NETIF_F_TSO_ECN | NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_GRE_CSUM;
ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO_ECN |
NETIF_F_TSO6 | NETIF_F_GSO_GRE |
- NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM;
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_GRE_CSUM;
ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
NETIF_F_HIGHDMA;
@@ -2329,8 +2651,14 @@ static void qede_init_ndev(struct qede_dev *edev)
ndev->hw_features = hw_features;
+ /* MTU range: 46 - 9600 */
+ ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ ndev->max_mtu = QEDE_MAX_JUMBO_PACKET_SIZE;
+
/* Set network device HW mac */
ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac);
+
+ ndev->mtu = edev->dev_info.common.mtu;
}
/* This function converts from 32b param to two params of level and module
@@ -2370,7 +2698,8 @@ static void qede_free_fp_array(struct qede_dev *edev)
kfree(fp->sb_info);
kfree(fp->rxq);
- kfree(fp->txqs);
+ kfree(fp->xdp_tx);
+ kfree(fp->txq);
}
kfree(edev->fp_array);
}
@@ -2403,7 +2732,7 @@ static int qede_alloc_fp_array(struct qede_dev *edev)
for_each_queue(i) {
fp = &edev->fp_array[i];
- fp->sb_info = kcalloc(1, sizeof(*fp->sb_info), GFP_KERNEL);
+ fp->sb_info = kzalloc(sizeof(*fp->sb_info), GFP_KERNEL);
if (!fp->sb_info) {
DP_NOTICE(edev, "sb info struct allocation failed\n");
goto err;
@@ -2420,21 +2749,22 @@ static int qede_alloc_fp_array(struct qede_dev *edev)
}
if (fp->type & QEDE_FASTPATH_TX) {
- fp->txqs = kcalloc(edev->num_tc, sizeof(*fp->txqs),
- GFP_KERNEL);
- if (!fp->txqs) {
- DP_NOTICE(edev,
- "TXQ array allocation failed\n");
+ fp->txq = kzalloc(sizeof(*fp->txq), GFP_KERNEL);
+ if (!fp->txq)
goto err;
- }
}
if (fp->type & QEDE_FASTPATH_RX) {
- fp->rxq = kcalloc(1, sizeof(*fp->rxq), GFP_KERNEL);
- if (!fp->rxq) {
- DP_NOTICE(edev,
- "RXQ struct allocation failed\n");
+ fp->rxq = kzalloc(sizeof(*fp->rxq), GFP_KERNEL);
+ if (!fp->rxq)
goto err;
+
+ if (edev->xdp_prog) {
+ fp->xdp_tx = kzalloc(sizeof(*fp->xdp_tx),
+ GFP_KERNEL);
+ if (!fp->xdp_tx)
+ goto err;
+ fp->type |= QEDE_FASTPATH_XDP;
}
}
}
@@ -2451,12 +2781,11 @@ static void qede_sp_task(struct work_struct *work)
sp_task.work);
struct qed_dev *cdev = edev->cdev;
- mutex_lock(&edev->qede_lock);
+ __qede_lock(edev);
- if (edev->state == QEDE_STATE_OPEN) {
- if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags))
+ if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags))
+ if (edev->state == QEDE_STATE_OPEN)
qede_config_rx_mode(edev->ndev);
- }
if (test_and_clear_bit(QEDE_SP_VXLAN_PORT_CONFIG, &edev->sp_flags)) {
struct qed_tunn_params tunn_params;
@@ -2476,16 +2805,16 @@ static void qede_sp_task(struct work_struct *work)
qed_ops->tunn_config(cdev, &tunn_params);
}
- mutex_unlock(&edev->qede_lock);
+ __qede_unlock(edev);
}
static void qede_update_pf_params(struct qed_dev *cdev)
{
struct qed_pf_params pf_params;
- /* 64 rx + 64 tx */
+ /* 64 rx + 64 tx + 64 XDP */
memset(&pf_params, 0, sizeof(struct qed_pf_params));
- pf_params.eth_pf_params.num_cons = 128;
+ pf_params.eth_pf_params.num_cons = 192;
qed_ops->common->update_pf_params(cdev, &pf_params);
}
@@ -2634,10 +2963,16 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
pci_set_drvdata(pdev, NULL);
+ /* Release edev's reference to XDP's bpf if such exist */
+ if (edev->xdp_prog)
+ bpf_prog_put(edev->xdp_prog);
+
free_netdev(ndev);
/* Use global ops since we've freed edev */
qed_ops->common->slowpath_stop(cdev);
+ if (system_state == SYSTEM_POWER_OFF)
+ return;
qed_ops->common->remove(cdev);
dev_info(&pdev->dev, "Ending qede_remove successfully\n");
@@ -2648,6 +2983,11 @@ static void qede_remove(struct pci_dev *pdev)
__qede_remove(pdev, QEDE_REMOVE_NORMAL);
}
+static void qede_shutdown(struct pci_dev *pdev)
+{
+ __qede_remove(pdev, QEDE_REMOVE_NORMAL);
+}
+
/* -------------------------------------------------------------------------
* START OF LOAD / UNLOAD
* -------------------------------------------------------------------------
@@ -2731,7 +3071,7 @@ static void qede_free_rx_buffers(struct qede_dev *edev,
data = rx_buf->data;
dma_unmap_page(&edev->pdev->dev,
- rx_buf->mapping, PAGE_SIZE, DMA_FROM_DEVICE);
+ rx_buf->mapping, PAGE_SIZE, rxq->data_direction);
rx_buf->data = NULL;
__free_page(data);
@@ -2747,7 +3087,7 @@ static void qede_free_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
struct qede_agg_info *tpa_info = &rxq->tpa_info[i];
- struct sw_rx_data *replace_buf = &tpa_info->replace_buf;
+ struct sw_rx_data *replace_buf = &tpa_info->buffer;
if (replace_buf->data) {
dma_unmap_page(&edev->pdev->dev,
@@ -2773,52 +3113,15 @@ static void qede_free_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
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;
- struct page *data;
-
- data = alloc_pages(GFP_ATOMIC, 0);
- if (unlikely(!data)) {
- DP_NOTICE(edev, "Failed to allocate Rx data [page]\n");
- return -ENOMEM;
- }
-
- /* Map the entire page as it would be used
- * for multiple RX buffer segment size mapping.
- */
- mapping = dma_map_page(&edev->pdev->dev, data, 0,
- PAGE_SIZE, DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
- __free_page(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->page_offset = 0;
- sw_rx_data->data = data;
- 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;
-}
-
static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
{
dma_addr_t mapping;
int i;
+ /* Don't perform FW aggregations in case of XDP */
+ if (edev->xdp_prog)
+ edev->gro_disable = 1;
+
if (edev->gro_disable)
return 0;
@@ -2829,7 +3132,7 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
struct qede_agg_info *tpa_info = &rxq->tpa_info[i];
- struct sw_rx_data *replace_buf = &tpa_info->replace_buf;
+ struct sw_rx_data *replace_buf = &tpa_info->buffer;
replace_buf->data = alloc_pages(GFP_ATOMIC, 0);
if (unlikely(!replace_buf->data)) {
@@ -2847,10 +3150,9 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
}
replace_buf->mapping = mapping;
- tpa_info->replace_buf.page_offset = 0;
-
- tpa_info->replace_buf_mapping = mapping;
- tpa_info->agg_state = QEDE_AGG_STATE_NONE;
+ tpa_info->buffer.page_offset = 0;
+ tpa_info->buffer_mapping = mapping;
+ tpa_info->state = QEDE_AGG_STATE_NONE;
}
return 0;
@@ -2872,8 +3174,13 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
if (rxq->rx_buf_size > PAGE_SIZE)
rxq->rx_buf_size = PAGE_SIZE;
- /* Segment size to spilt a page in multiple equal parts */
- rxq->rx_buf_seg_size = roundup_pow_of_two(rxq->rx_buf_size);
+ /* Segment size to spilt a page in multiple equal parts,
+ * unless XDP is used in which case we'd use the entire page.
+ */
+ if (!edev->xdp_prog)
+ rxq->rx_buf_seg_size = roundup_pow_of_two(rxq->rx_buf_size);
+ else
+ rxq->rx_buf_seg_size = PAGE_SIZE;
/* Allocate the parallel driver ring for Rx buffers */
size = sizeof(*rxq->sw_rx_ring) * RX_RING_SIZE;
@@ -2909,7 +3216,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
/* Allocate buffers for the Rx ring */
for (i = 0; i < rxq->num_rx_buffers; i++) {
- rc = qede_alloc_rx_buffer(edev, rxq);
+ rc = qede_alloc_rx_buffer(rxq);
if (rc) {
DP_ERR(edev,
"Rx buffers allocation failed at index %d\n", i);
@@ -2925,7 +3232,10 @@ err:
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);
+ if (txq->is_xdp)
+ kfree(txq->sw_tx_ring.pages);
+ else
+ kfree(txq->sw_tx_ring.skbs);
/* Free the real RQ ring used by FW */
edev->ops->common->chain_free(edev->cdev, &txq->tx_pbl);
@@ -2934,17 +3244,22 @@ static void qede_free_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq)
/* 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;
+ int size, rc;
txq->num_tx_buffers = edev->q_num_tx_buffers;
/* Allocate the parallel driver ring for Tx buffers */
- size = sizeof(*txq->sw_tx_ring) * TX_RING_SIZE;
- txq->sw_tx_ring = kzalloc(size, GFP_KERNEL);
- if (!txq->sw_tx_ring) {
- DP_NOTICE(edev, "Tx buffers ring allocation failed\n");
- goto err;
+ if (txq->is_xdp) {
+ size = sizeof(*txq->sw_tx_ring.pages) * TX_RING_SIZE;
+ txq->sw_tx_ring.pages = kzalloc(size, GFP_KERNEL);
+ if (!txq->sw_tx_ring.pages)
+ goto err;
+ } else {
+ size = sizeof(*txq->sw_tx_ring.skbs) * TX_RING_SIZE;
+ txq->sw_tx_ring.skbs = kzalloc(size, GFP_KERNEL);
+ if (!txq->sw_tx_ring.skbs)
+ goto err;
}
rc = edev->ops->common->chain_alloc(edev->cdev,
@@ -2966,16 +3281,13 @@ err:
/* 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);
if (fp->type & QEDE_FASTPATH_RX)
qede_free_mem_rxq(edev, fp->rxq);
if (fp->type & QEDE_FASTPATH_TX)
- for (tc = 0; tc < edev->num_tc; tc++)
- qede_free_mem_txq(edev, &fp->txqs[tc]);
+ qede_free_mem_txq(edev, fp->txq);
}
/* This function allocates all memory needed for a single fp (i.e. an entity
@@ -2983,28 +3295,31 @@ static void qede_free_mem_fp(struct qede_dev *edev, struct qede_fastpath *fp)
*/
static int qede_alloc_mem_fp(struct qede_dev *edev, struct qede_fastpath *fp)
{
- int rc, tc;
+ int rc = 0;
rc = qede_alloc_mem_sb(edev, fp->sb_info, fp->id);
if (rc)
- goto err;
+ goto out;
if (fp->type & QEDE_FASTPATH_RX) {
rc = qede_alloc_mem_rxq(edev, fp->rxq);
if (rc)
- goto err;
+ goto out;
+ }
+
+ if (fp->type & QEDE_FASTPATH_XDP) {
+ rc = qede_alloc_mem_txq(edev, fp->xdp_tx);
+ if (rc)
+ goto out;
}
if (fp->type & QEDE_FASTPATH_TX) {
- for (tc = 0; tc < edev->num_tc; tc++) {
- rc = qede_alloc_mem_txq(edev, &fp->txqs[tc]);
- if (rc)
- goto err;
- }
+ rc = qede_alloc_mem_txq(edev, fp->txq);
+ if (rc)
+ goto out;
}
- return 0;
-err:
+out:
return rc;
}
@@ -3043,7 +3358,7 @@ static int qede_alloc_mem_load(struct qede_dev *edev)
/* This function inits fp content and resets the SB, RXQ and TXQ structures */
static void qede_init_fp(struct qede_dev *edev)
{
- int queue_id, rxq_index = 0, txq_index = 0, tc;
+ int queue_id, rxq_index = 0, txq_index = 0;
struct qede_fastpath *fp;
for_each_queue(queue_id) {
@@ -3052,25 +3367,28 @@ static void qede_init_fp(struct qede_dev *edev)
fp->edev = edev;
fp->id = queue_id;
- memset((void *)&fp->napi, 0, sizeof(fp->napi));
-
- memset((void *)fp->sb_info, 0, sizeof(*fp->sb_info));
+ if (fp->type & QEDE_FASTPATH_XDP) {
+ fp->xdp_tx->index = QEDE_TXQ_IDX_TO_XDP(edev,
+ rxq_index);
+ fp->xdp_tx->is_xdp = 1;
+ }
if (fp->type & QEDE_FASTPATH_RX) {
- memset((void *)fp->rxq, 0, sizeof(*fp->rxq));
fp->rxq->rxq_id = rxq_index++;
+
+ /* Determine how to map buffers for this queue */
+ if (fp->type & QEDE_FASTPATH_XDP)
+ fp->rxq->data_direction = DMA_BIDIRECTIONAL;
+ else
+ fp->rxq->data_direction = DMA_FROM_DEVICE;
+ fp->rxq->dev = &edev->pdev->dev;
}
if (fp->type & QEDE_FASTPATH_TX) {
- memset((void *)fp->txqs, 0,
- (edev->num_tc * sizeof(*fp->txqs)));
- for (tc = 0; tc < edev->num_tc; tc++) {
- fp->txqs[tc].index = txq_index +
- tc * QEDE_TSS_COUNT(edev);
- if (edev->dev_info.is_legacy)
- fp->txqs[tc].is_legacy = true;
- }
- txq_index++;
+ fp->txq->index = txq_index++;
+ if (edev->dev_info.is_legacy)
+ fp->txq->is_legacy = 1;
+ fp->txq->dev = &edev->pdev->dev;
}
snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@@ -3238,11 +3556,18 @@ static int qede_drain_txq(struct qede_dev *edev,
return 0;
}
+static int qede_stop_txq(struct qede_dev *edev,
+ struct qede_tx_queue *txq, int rss_id)
+{
+ return edev->ops->q_tx_stop(edev->cdev, rss_id, txq->handle);
+}
+
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;
+ struct qede_fastpath *fp;
+ int rc, i;
/* Disable the vport */
memset(&vport_update_params, 0, sizeof(vport_update_params));
@@ -3259,53 +3584,49 @@ static int qede_stop_queues(struct qede_dev *edev)
/* Flush Tx queues. If needed, request drain from MCP */
for_each_queue(i) {
- struct qede_fastpath *fp = &edev->fp_array[i];
+ fp = &edev->fp_array[i];
if (fp->type & QEDE_FASTPATH_TX) {
- for (tc = 0; tc < edev->num_tc; tc++) {
- struct qede_tx_queue *txq = &fp->txqs[tc];
+ rc = qede_drain_txq(edev, fp->txq, true);
+ if (rc)
+ return rc;
+ }
- rc = qede_drain_txq(edev, txq, true);
- if (rc)
- return rc;
- }
+ if (fp->type & QEDE_FASTPATH_XDP) {
+ rc = qede_drain_txq(edev, fp->xdp_tx, true);
+ if (rc)
+ return rc;
}
}
/* Stop all Queues in reverse order */
for (i = QEDE_QUEUE_CNT(edev) - 1; i >= 0; i--) {
- struct qed_stop_rxq_params rx_params;
+ fp = &edev->fp_array[i];
/* Stop the Tx Queue(s) */
- if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
- for (tc = 0; tc < edev->num_tc; tc++) {
- struct qed_stop_txq_params tx_params;
- u8 val;
-
- tx_params.rss_id = i;
- val = edev->fp_array[i].txqs[tc].index;
- tx_params.tx_queue_id = val;
- 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;
- }
- }
+ if (fp->type & QEDE_FASTPATH_TX) {
+ rc = qede_stop_txq(edev, fp->txq, i);
+ if (rc)
+ return rc;
}
/* Stop the Rx Queue */
- if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
- memset(&rx_params, 0, sizeof(rx_params));
- rx_params.rss_id = i;
- rx_params.rx_queue_id = edev->fp_array[i].rxq->rxq_id;
-
- rc = edev->ops->q_rx_stop(cdev, &rx_params);
+ if (fp->type & QEDE_FASTPATH_RX) {
+ rc = edev->ops->q_rx_stop(cdev, i, fp->rxq->handle);
if (rc) {
DP_ERR(edev, "Failed to stop RXQ #%d\n", i);
return rc;
}
}
+
+ /* Stop the XDP forwarding queue */
+ if (fp->type & QEDE_FASTPATH_XDP) {
+ rc = qede_stop_txq(edev, fp->xdp_tx, i);
+ if (rc)
+ return rc;
+
+ bpf_prog_put(fp->rxq->xdp_prog);
+ }
}
/* Stop the vport */
@@ -3316,9 +3637,55 @@ static int qede_stop_queues(struct qede_dev *edev)
return rc;
}
+static int qede_start_txq(struct qede_dev *edev,
+ struct qede_fastpath *fp,
+ struct qede_tx_queue *txq, u8 rss_id, u16 sb_idx)
+{
+ dma_addr_t phys_table = qed_chain_get_pbl_phys(&txq->tx_pbl);
+ u32 page_cnt = qed_chain_get_page_cnt(&txq->tx_pbl);
+ struct qed_queue_start_common_params params;
+ struct qed_txq_start_ret_params ret_params;
+ int rc;
+
+ memset(&params, 0, sizeof(params));
+ memset(&ret_params, 0, sizeof(ret_params));
+
+ /* Let the XDP queue share the queue-zone with one of the regular txq.
+ * We don't really care about its coalescing.
+ */
+ if (txq->is_xdp)
+ params.queue_id = QEDE_TXQ_XDP_TO_IDX(edev, txq);
+ else
+ params.queue_id = txq->index;
+
+ params.sb = fp->sb_info->igu_sb_id;
+ params.sb_idx = sb_idx;
+
+ rc = edev->ops->q_tx_start(edev->cdev, rss_id, &params, phys_table,
+ page_cnt, &ret_params);
+ if (rc) {
+ DP_ERR(edev, "Start TXQ #%d failed %d\n", txq->index, rc);
+ return rc;
+ }
+
+ txq->doorbell_addr = ret_params.p_doorbell;
+ txq->handle = ret_params.p_handle;
+
+ /* Determine the FW consumer address associated */
+ txq->hw_cons_ptr = &fp->sb_info->sb_virt->pi_array[sb_idx];
+
+ /* Prepare the doorbell parameters */
+ 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;
+
+ return rc;
+}
+
static int qede_start_queues(struct qede_dev *edev, bool clear_stats)
{
- int rc, tc, i;
int vlan_removal_en = 1;
struct qed_dev *cdev = edev->cdev;
struct qed_update_vport_params vport_update_params;
@@ -3326,6 +3693,7 @@ static int qede_start_queues(struct qede_dev *edev, bool clear_stats)
struct qed_dev_info *qed_info = &edev->dev_info.common;
struct qed_start_vport_params start = {0};
bool reset_rss_indir = false;
+ int rc, i;
if (!edev->num_queues) {
DP_ERR(edev,
@@ -3357,11 +3725,12 @@ static int qede_start_queues(struct qede_dev *edev, bool clear_stats)
u32 page_cnt;
if (fp->type & QEDE_FASTPATH_RX) {
+ struct qed_rxq_start_ret_params ret_params;
struct qede_rx_queue *rxq = fp->rxq;
__le16 *val;
+ memset(&ret_params, 0, sizeof(ret_params));
memset(&q_params, 0, sizeof(q_params));
- q_params.rss_id = i;
q_params.queue_id = rxq->rxq_id;
q_params.vport_id = 0;
q_params.sb = fp->sb_info->igu_sb_id;
@@ -3371,60 +3740,44 @@ static int qede_start_queues(struct qede_dev *edev, bool clear_stats)
qed_chain_get_pbl_phys(&rxq->rx_comp_ring);
page_cnt = qed_chain_get_page_cnt(&rxq->rx_comp_ring);
- rc = edev->ops->q_rx_start(cdev, &q_params,
+ rc = edev->ops->q_rx_start(cdev, i, &q_params,
rxq->rx_buf_size,
rxq->rx_bd_ring.p_phys_addr,
p_phys_table,
- page_cnt,
- &rxq->hw_rxq_prod_addr);
+ page_cnt, &ret_params);
if (rc) {
DP_ERR(edev, "Start RXQ #%d failed %d\n", i,
rc);
return rc;
}
+ /* Use the return parameters */
+ rxq->hw_rxq_prod_addr = ret_params.p_prod;
+ rxq->handle = ret_params.p_handle;
+
val = &fp->sb_info->sb_virt->pi_array[RX_PI];
rxq->hw_cons_ptr = val;
qede_update_rx_prod(edev, rxq);
}
- if (!(fp->type & QEDE_FASTPATH_TX))
- continue;
-
- for (tc = 0; tc < edev->num_tc; tc++) {
- struct qede_tx_queue *txq = &fp->txqs[tc];
-
- p_phys_table = qed_chain_get_pbl_phys(&txq->tx_pbl);
- page_cnt = qed_chain_get_page_cnt(&txq->tx_pbl);
-
- 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);
+ if (fp->type & QEDE_FASTPATH_XDP) {
+ rc = qede_start_txq(edev, fp, fp->xdp_tx, i, XDP_PI);
+ if (rc)
+ return rc;
- rc = edev->ops->q_tx_start(cdev, &q_params,
- p_phys_table, page_cnt,
- &txq->doorbell_addr);
- if (rc) {
- DP_ERR(edev, "Start TXQ #%d failed %d\n",
- txq->index, rc);
+ fp->rxq->xdp_prog = bpf_prog_add(edev->xdp_prog, 1);
+ if (IS_ERR(fp->rxq->xdp_prog)) {
+ rc = PTR_ERR(fp->rxq->xdp_prog);
+ fp->rxq->xdp_prog = NULL;
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;
+ if (fp->type & QEDE_FASTPATH_TX) {
+ rc = qede_start_txq(edev, fp, fp->txq, i, TX_PI(0));
+ if (rc)
+ return rc;
}
}
@@ -3519,15 +3872,18 @@ enum qede_unload_mode {
QEDE_UNLOAD_NORMAL,
};
-static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode)
+static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
+ bool is_locked)
{
struct qed_link_params link_params;
int rc;
DP_INFO(edev, "Starting qede unload\n");
+ if (!is_locked)
+ __qede_lock(edev);
+
qede_roce_dev_event_close(edev);
- mutex_lock(&edev->qede_lock);
edev->state = QEDE_STATE_CLOSED;
/* Close OS Tx */
@@ -3559,7 +3915,8 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode)
qede_free_fp_array(edev);
out:
- mutex_unlock(&edev->qede_lock);
+ if (!is_locked)
+ __qede_unlock(edev);
DP_INFO(edev, "Ending qede unload\n");
}
@@ -3568,7 +3925,8 @@ enum qede_load_mode {
QEDE_LOAD_RELOAD,
};
-static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
+static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
+ bool is_locked)
{
struct qed_link_params link_params;
struct qed_link_output link_output;
@@ -3576,21 +3934,24 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
DP_INFO(edev, "Starting qede load\n");
+ if (!is_locked)
+ __qede_lock(edev);
+
rc = qede_set_num_queues(edev);
if (rc)
- goto err0;
+ goto out;
rc = qede_alloc_fp_array(edev);
if (rc)
- goto err0;
+ goto out;
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_QUEUE_CNT(edev), edev->num_tc);
+ DP_INFO(edev, "Allocated %d Rx, %d Tx queues\n",
+ QEDE_RSS_COUNT(edev), QEDE_TSS_COUNT(edev));
rc = qede_set_real_num_queues(edev);
if (rc)
@@ -3612,10 +3973,6 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
/* 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);
-
/* Program un-configured VLANs */
qede_configure_vlan_filters(edev);
@@ -3630,10 +3987,12 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
qede_roce_dev_event_open(edev);
qede_link_update(edev, &link_output);
+ edev->state = QEDE_STATE_OPEN;
+
DP_INFO(edev, "Ending successfully qede load\n");
- return 0;
+ goto out;
err4:
qede_sync_free_irqs(edev);
memset(&edev->int_info.msix_cnt, 0, sizeof(struct qed_int_info));
@@ -3647,26 +4006,40 @@ err1:
edev->num_queues = 0;
edev->fp_num_tx = 0;
edev->fp_num_rx = 0;
-err0:
+out:
+ if (!is_locked)
+ __qede_unlock(edev);
+
return rc;
}
+/* 'func' should be able to run between unload and reload assuming interface
+ * is actually running, or afterwards in case it's currently DOWN.
+ */
void qede_reload(struct qede_dev *edev,
- void (*func)(struct qede_dev *, union qede_reload_args *),
- union qede_reload_args *args)
+ struct qede_reload_args *args, bool is_locked)
{
- qede_unload(edev, QEDE_UNLOAD_NORMAL);
- /* Call function handler to update parameters
- * needed for function load.
- */
- if (func)
- func(edev, args);
+ if (!is_locked)
+ __qede_lock(edev);
- qede_load(edev, QEDE_LOAD_RELOAD);
+ /* Since qede_lock is held, internal state wouldn't change even
+ * if netdev state would start transitioning. Check whether current
+ * internal configuration indicates device is up, then reload.
+ */
+ if (edev->state == QEDE_STATE_OPEN) {
+ qede_unload(edev, QEDE_UNLOAD_NORMAL, true);
+ if (args)
+ args->func(edev, args);
+ qede_load(edev, QEDE_LOAD_RELOAD, true);
+
+ /* Since no one is going to do it for us, re-configure */
+ qede_config_rx_mode(edev->ndev);
+ } else if (args) {
+ args->func(edev, args);
+ }
- mutex_lock(&edev->qede_lock);
- qede_config_rx_mode(edev->ndev);
- mutex_unlock(&edev->qede_lock);
+ if (!is_locked)
+ __qede_unlock(edev);
}
/* called with rtnl_lock */
@@ -3679,13 +4052,14 @@ static int qede_open(struct net_device *ndev)
edev->ops->common->set_power_state(edev->cdev, PCI_D0);
- rc = qede_load(edev, QEDE_LOAD_NORMAL);
-
+ rc = qede_load(edev, QEDE_LOAD_NORMAL, false);
if (rc)
return rc;
udp_tunnel_get_rx_info(ndev);
+ edev->ops->common->update_drv_state(edev->cdev, true);
+
return 0;
}
@@ -3693,7 +4067,9 @@ static int qede_close(struct net_device *ndev)
{
struct qede_dev *edev = netdev_priv(ndev);
- qede_unload(edev, QEDE_UNLOAD_NORMAL);
+ qede_unload(edev, QEDE_UNLOAD_NORMAL, false);
+
+ edev->ops->common->update_drv_state(edev->cdev, false);
return 0;
}
@@ -3755,6 +4131,8 @@ static int qede_set_mac_addr(struct net_device *ndev, void *p)
if (rc)
return rc;
+ edev->ops->common->update_mac(edev->cdev, addr->sa_data);
+
/* 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,
@@ -3821,15 +4199,8 @@ 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);
- }
+ set_bit(QEDE_SP_RX_MODE, &edev->sp_flags);
+ schedule_delayed_work(&edev->sp_task, 0);
}
/* Must be called with qede_lock held */
@@ -3877,7 +4248,7 @@ static void qede_config_rx_mode(struct net_device *ndev)
/* Check for promiscuous */
if ((ndev->flags & IFF_PROMISC) ||
- (uc_count > 15)) { /* @@@TBD resource allocation - 1 */
+ (uc_count > edev->dev_info.num_mac_filters - 1)) {
accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC;
} else {
/* Add MAC filters according to the unicast secondary macs */
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index b09a6b80d107..5c100ab86c00 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3755,7 +3755,6 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
.ndo_open = ql3xxx_open,
.ndo_start_xmit = ql3xxx_send,
.ndo_stop = ql3xxx_close,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ql3xxx_set_mac_address,
.ndo_tx_timeout = ql3xxx_tx_timeout,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 509b596cf1e8..838cc0ceafd8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1024,12 +1024,6 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int rc = 0;
- if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
- dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
- " not supported\n", P3P_MAX_MTU, P3P_MIN_MTU);
- return -EINVAL;
- }
-
rc = qlcnic_fw_cmd_set_mtu(adapter, mtu);
if (!rc)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 3ae3968b0edf..4c0cce962585 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2342,6 +2342,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->irq = adapter->msix_entries[0].vector;
+ /* MTU range: 68 - 9600 */
+ netdev->min_mtu = P3P_MIN_MTU;
+ netdev->max_mtu = P3P_MAX_MTU;
+
err = qlcnic_set_real_num_queues(adapter, adapter->drv_tx_rings,
adapter->drv_sds_rings);
if (err)
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index fd4a8e473f11..1409412ab39d 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4788,6 +4788,13 @@ static int qlge_probe(struct pci_dev *pdev,
ndev->ethtool_ops = &qlge_ethtool_ops;
ndev->watchdog_timeo = 10 * HZ;
+ /* MTU range: this driver only supports 1500 or 9000, so this only
+ * filters out values above or below, and we'll rely on
+ * qlge_change_mtu to make sure only 1500 or 9000 are allowed
+ */
+ ndev->min_mtu = ETH_DATA_LEN;
+ ndev->max_mtu = 9000;
+
err = register_netdev(ndev);
if (err) {
dev_err(&pdev->dev, "net device registration failed.\n");
diff --git a/drivers/net/ethernet/qualcomm/emac/Makefile b/drivers/net/ethernet/qualcomm/emac/Makefile
index 01ee144c6386..7a6687982dae 100644
--- a/drivers/net/ethernet/qualcomm/emac/Makefile
+++ b/drivers/net/ethernet/qualcomm/emac/Makefile
@@ -4,4 +4,6 @@
obj-$(CONFIG_QCOM_EMAC) += qcom-emac.o
-qcom-emac-objs := emac.o emac-mac.o emac-phy.o emac-sgmii.o
+qcom-emac-objs := emac.o emac-mac.o emac-phy.o emac-sgmii.o \
+ emac-sgmii-fsm9900.o emac-sgmii-qdf2432.o \
+ emac-sgmii-qdf2400.o
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii-fsm9900.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-fsm9900.c
new file mode 100644
index 000000000000..af690e1a6e7b
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-fsm9900.c
@@ -0,0 +1,245 @@
+/* Copyright (c) 2015-2016, 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.
+ */
+
+/* Qualcomm Technologies, Inc. FSM9900 EMAC SGMII Controller driver.
+ */
+
+#include <linux/iopoll.h>
+#include "emac.h"
+
+/* EMAC_QSERDES register offsets */
+#define EMAC_QSERDES_COM_SYS_CLK_CTRL 0x0000
+#define EMAC_QSERDES_COM_PLL_CNTRL 0x0014
+#define EMAC_QSERDES_COM_PLL_IP_SETI 0x0018
+#define EMAC_QSERDES_COM_PLL_CP_SETI 0x0024
+#define EMAC_QSERDES_COM_PLL_IP_SETP 0x0028
+#define EMAC_QSERDES_COM_PLL_CP_SETP 0x002c
+#define EMAC_QSERDES_COM_SYSCLK_EN_SEL 0x0038
+#define EMAC_QSERDES_COM_RESETSM_CNTRL 0x0040
+#define EMAC_QSERDES_COM_PLLLOCK_CMP1 0x0044
+#define EMAC_QSERDES_COM_PLLLOCK_CMP2 0x0048
+#define EMAC_QSERDES_COM_PLLLOCK_CMP3 0x004c
+#define EMAC_QSERDES_COM_PLLLOCK_CMP_EN 0x0050
+#define EMAC_QSERDES_COM_DEC_START1 0x0064
+#define EMAC_QSERDES_COM_DIV_FRAC_START1 0x0098
+#define EMAC_QSERDES_COM_DIV_FRAC_START2 0x009c
+#define EMAC_QSERDES_COM_DIV_FRAC_START3 0x00a0
+#define EMAC_QSERDES_COM_DEC_START2 0x00a4
+#define EMAC_QSERDES_COM_PLL_CRCTRL 0x00ac
+#define EMAC_QSERDES_COM_RESET_SM 0x00bc
+#define EMAC_QSERDES_TX_BIST_MODE_LANENO 0x0100
+#define EMAC_QSERDES_TX_TX_EMP_POST1_LVL 0x0108
+#define EMAC_QSERDES_TX_TX_DRV_LVL 0x010c
+#define EMAC_QSERDES_TX_LANE_MODE 0x0150
+#define EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN 0x0170
+#define EMAC_QSERDES_RX_CDR_CONTROL 0x0200
+#define EMAC_QSERDES_RX_CDR_CONTROL2 0x0210
+#define EMAC_QSERDES_RX_RX_EQ_GAIN12 0x0230
+
+/* EMAC_SGMII register offsets */
+#define EMAC_SGMII_PHY_SERDES_START 0x0000
+#define EMAC_SGMII_PHY_CMN_PWR_CTRL 0x0004
+#define EMAC_SGMII_PHY_RX_PWR_CTRL 0x0008
+#define EMAC_SGMII_PHY_TX_PWR_CTRL 0x000C
+#define EMAC_SGMII_PHY_LANE_CTRL1 0x0018
+#define EMAC_SGMII_PHY_CDR_CTRL0 0x0058
+#define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x0080
+#define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4
+
+#define PLL_IPSETI(x) ((x) & 0x3f)
+
+#define PLL_CPSETI(x) ((x) & 0xff)
+
+#define PLL_IPSETP(x) ((x) & 0x3f)
+
+#define PLL_CPSETP(x) ((x) & 0x1f)
+
+#define PLL_RCTRL(x) (((x) & 0xf) << 4)
+#define PLL_CCTRL(x) ((x) & 0xf)
+
+#define LANE_MODE(x) ((x) & 0x1f)
+
+#define SYSCLK_CM BIT(4)
+#define SYSCLK_AC_COUPLE BIT(3)
+
+#define OCP_EN BIT(5)
+#define PLL_DIV_FFEN BIT(2)
+#define PLL_DIV_ORD BIT(1)
+
+#define SYSCLK_SEL_CMOS BIT(3)
+
+#define FRQ_TUNE_MODE BIT(4)
+
+#define PLLLOCK_CMP_EN BIT(0)
+
+#define DEC_START1_MUX BIT(7)
+#define DEC_START1(x) ((x) & 0x7f)
+
+#define DIV_FRAC_START_MUX BIT(7)
+#define DIV_FRAC_START(x) ((x) & 0x7f)
+
+#define DIV_FRAC_START3_MUX BIT(4)
+#define DIV_FRAC_START3(x) ((x) & 0xf)
+
+#define DEC_START2_MUX BIT(1)
+#define DEC_START2 BIT(0)
+
+#define READY BIT(5)
+
+#define TX_EMP_POST1_LVL_MUX BIT(5)
+#define TX_EMP_POST1_LVL(x) ((x) & 0x1f)
+
+#define TX_DRV_LVL_MUX BIT(4)
+#define TX_DRV_LVL(x) ((x) & 0xf)
+
+#define EMP_EN_MUX BIT(1)
+#define EMP_EN BIT(0)
+
+#define SECONDORDERENABLE BIT(6)
+#define FIRSTORDER_THRESH(x) (((x) & 0x7) << 3)
+#define SECONDORDERGAIN(x) ((x) & 0x7)
+
+#define RX_EQ_GAIN2(x) (((x) & 0xf) << 4)
+#define RX_EQ_GAIN1(x) ((x) & 0xf)
+
+#define SERDES_START BIT(0)
+
+#define BIAS_EN BIT(6)
+#define PLL_EN BIT(5)
+#define SYSCLK_EN BIT(4)
+#define CLKBUF_L_EN BIT(3)
+#define PLL_TXCLK_EN BIT(1)
+#define PLL_RXCLK_EN BIT(0)
+
+#define L0_RX_SIGDET_EN BIT(7)
+#define L0_RX_TERM_MODE(x) (((x) & 3) << 4)
+#define L0_RX_I_EN BIT(1)
+
+#define L0_TX_EN BIT(5)
+#define L0_CLKBUF_EN BIT(4)
+#define L0_TRAN_BIAS_EN BIT(1)
+
+#define L0_RX_EQUALIZE_ENABLE BIT(6)
+#define L0_RESET_TSYNC_EN BIT(4)
+#define L0_DRV_LVL(x) ((x) & 0xf)
+
+#define PWRDN_B BIT(0)
+#define CDR_MAX_CNT(x) ((x) & 0xff)
+
+#define PLLLOCK_CMP(x) ((x) & 0xff)
+
+#define SERDES_START_WAIT_TIMES 100
+
+struct emac_reg_write {
+ unsigned int offset;
+ u32 val;
+};
+
+static void emac_reg_write_all(void __iomem *base,
+ const struct emac_reg_write *itr, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; ++itr, ++i)
+ writel(itr->val, base + itr->offset);
+}
+
+static const struct emac_reg_write physical_coding_sublayer_programming[] = {
+ {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)},
+ {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B},
+ {EMAC_SGMII_PHY_CMN_PWR_CTRL,
+ BIAS_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | PLL_RXCLK_EN},
+ {EMAC_SGMII_PHY_TX_PWR_CTRL, L0_TX_EN | L0_CLKBUF_EN | L0_TRAN_BIAS_EN},
+ {EMAC_SGMII_PHY_RX_PWR_CTRL,
+ L0_RX_SIGDET_EN | L0_RX_TERM_MODE(1) | L0_RX_I_EN},
+ {EMAC_SGMII_PHY_CMN_PWR_CTRL,
+ BIAS_EN | PLL_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN |
+ PLL_RXCLK_EN},
+ {EMAC_SGMII_PHY_LANE_CTRL1,
+ L0_RX_EQUALIZE_ENABLE | L0_RESET_TSYNC_EN | L0_DRV_LVL(15)},
+};
+
+static const struct emac_reg_write sysclk_refclk_setting[] = {
+ {EMAC_QSERDES_COM_SYSCLK_EN_SEL, SYSCLK_SEL_CMOS},
+ {EMAC_QSERDES_COM_SYS_CLK_CTRL, SYSCLK_CM | SYSCLK_AC_COUPLE},
+};
+
+static const struct emac_reg_write pll_setting[] = {
+ {EMAC_QSERDES_COM_PLL_IP_SETI, PLL_IPSETI(1)},
+ {EMAC_QSERDES_COM_PLL_CP_SETI, PLL_CPSETI(59)},
+ {EMAC_QSERDES_COM_PLL_IP_SETP, PLL_IPSETP(10)},
+ {EMAC_QSERDES_COM_PLL_CP_SETP, PLL_CPSETP(9)},
+ {EMAC_QSERDES_COM_PLL_CRCTRL, PLL_RCTRL(15) | PLL_CCTRL(11)},
+ {EMAC_QSERDES_COM_PLL_CNTRL, OCP_EN | PLL_DIV_FFEN | PLL_DIV_ORD},
+ {EMAC_QSERDES_COM_DEC_START1, DEC_START1_MUX | DEC_START1(2)},
+ {EMAC_QSERDES_COM_DEC_START2, DEC_START2_MUX | DEC_START2},
+ {EMAC_QSERDES_COM_DIV_FRAC_START1,
+ DIV_FRAC_START_MUX | DIV_FRAC_START(85)},
+ {EMAC_QSERDES_COM_DIV_FRAC_START2,
+ DIV_FRAC_START_MUX | DIV_FRAC_START(42)},
+ {EMAC_QSERDES_COM_DIV_FRAC_START3,
+ DIV_FRAC_START3_MUX | DIV_FRAC_START3(3)},
+ {EMAC_QSERDES_COM_PLLLOCK_CMP1, PLLLOCK_CMP(43)},
+ {EMAC_QSERDES_COM_PLLLOCK_CMP2, PLLLOCK_CMP(104)},
+ {EMAC_QSERDES_COM_PLLLOCK_CMP3, PLLLOCK_CMP(0)},
+ {EMAC_QSERDES_COM_PLLLOCK_CMP_EN, PLLLOCK_CMP_EN},
+ {EMAC_QSERDES_COM_RESETSM_CNTRL, FRQ_TUNE_MODE},
+};
+
+static const struct emac_reg_write cdr_setting[] = {
+ {EMAC_QSERDES_RX_CDR_CONTROL,
+ SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(2)},
+ {EMAC_QSERDES_RX_CDR_CONTROL2,
+ SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(4)},
+};
+
+static const struct emac_reg_write tx_rx_setting[] = {
+ {EMAC_QSERDES_TX_BIST_MODE_LANENO, 0},
+ {EMAC_QSERDES_TX_TX_DRV_LVL, TX_DRV_LVL_MUX | TX_DRV_LVL(15)},
+ {EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN, EMP_EN_MUX | EMP_EN},
+ {EMAC_QSERDES_TX_TX_EMP_POST1_LVL,
+ TX_EMP_POST1_LVL_MUX | TX_EMP_POST1_LVL(1)},
+ {EMAC_QSERDES_RX_RX_EQ_GAIN12, RX_EQ_GAIN2(15) | RX_EQ_GAIN1(15)},
+ {EMAC_QSERDES_TX_LANE_MODE, LANE_MODE(8)},
+};
+
+int emac_sgmii_init_fsm9900(struct emac_adapter *adpt)
+{
+ struct emac_phy *phy = &adpt->phy;
+ unsigned int i;
+
+ emac_reg_write_all(phy->base, physical_coding_sublayer_programming,
+ ARRAY_SIZE(physical_coding_sublayer_programming));
+ emac_reg_write_all(phy->base, sysclk_refclk_setting,
+ ARRAY_SIZE(sysclk_refclk_setting));
+ emac_reg_write_all(phy->base, pll_setting, ARRAY_SIZE(pll_setting));
+ emac_reg_write_all(phy->base, cdr_setting, ARRAY_SIZE(cdr_setting));
+ emac_reg_write_all(phy->base, tx_rx_setting, ARRAY_SIZE(tx_rx_setting));
+
+ /* Power up the Ser/Des engine */
+ writel(SERDES_START, phy->base + EMAC_SGMII_PHY_SERDES_START);
+
+ for (i = 0; i < SERDES_START_WAIT_TIMES; i++) {
+ if (readl(phy->base + EMAC_QSERDES_COM_RESET_SM) & READY)
+ break;
+ usleep_range(100, 200);
+ }
+
+ if (i == SERDES_START_WAIT_TIMES) {
+ netdev_err(adpt->netdev, "error: ser/des failed to start\n");
+ return -EIO;
+ }
+ /* Mask out all the SGMII Interrupt */
+ writel(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2400.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2400.c
new file mode 100644
index 000000000000..5b8419498ef1
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2400.c
@@ -0,0 +1,217 @@
+/* Copyright (c) 2015-2016, 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.
+ */
+
+/* Qualcomm Technologies, Inc. QDF2400 EMAC SGMII Controller driver.
+ */
+
+#include <linux/iopoll.h>
+#include "emac.h"
+
+/* EMAC_SGMII register offsets */
+#define EMAC_SGMII_PHY_TX_PWR_CTRL 0x000C
+#define EMAC_SGMII_PHY_LANE_CTRL1 0x0018
+#define EMAC_SGMII_PHY_CDR_CTRL0 0x0058
+#define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x0080
+#define EMAC_SGMII_PHY_RESET_CTRL 0x00a8
+#define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4
+
+/* SGMII digital lane registers */
+#define EMAC_SGMII_LN_DRVR_CTRL0 0x000C
+#define EMAC_SGMII_LN_DRVR_TAP_EN 0x0018
+#define EMAC_SGMII_LN_TX_MARGINING 0x001C
+#define EMAC_SGMII_LN_TX_PRE 0x0020
+#define EMAC_SGMII_LN_TX_POST 0x0024
+#define EMAC_SGMII_LN_TX_BAND_MODE 0x0060
+#define EMAC_SGMII_LN_LANE_MODE 0x0064
+#define EMAC_SGMII_LN_PARALLEL_RATE 0x007C
+#define EMAC_SGMII_LN_CML_CTRL_MODE0 0x00C0
+#define EMAC_SGMII_LN_MIXER_CTRL_MODE0 0x00D8
+#define EMAC_SGMII_LN_VGA_INITVAL 0x013C
+#define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0 0x0184
+#define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0 0x0190
+#define EMAC_SGMII_LN_UCDR_SO_CONFIG 0x019C
+#define EMAC_SGMII_LN_RX_BAND 0x01A4
+#define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0 0x01C0
+#define EMAC_SGMII_LN_RSM_CONFIG 0x01F8
+#define EMAC_SGMII_LN_SIGDET_ENABLES 0x0230
+#define EMAC_SGMII_LN_SIGDET_CNTRL 0x0234
+#define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL 0x0238
+#define EMAC_SGMII_LN_RX_EN_SIGNAL 0x02AC
+#define EMAC_SGMII_LN_RX_MISC_CNTRL0 0x02B8
+#define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV 0x02C8
+
+/* SGMII digital lane register values */
+#define UCDR_STEP_BY_TWO_MODE0 BIT(7)
+#define UCDR_xO_GAIN_MODE(x) ((x) & 0x7f)
+#define UCDR_ENABLE BIT(6)
+#define UCDR_SO_SATURATION(x) ((x) & 0x3f)
+
+#define SIGDET_LP_BYP_PS4 BIT(7)
+#define SIGDET_EN_PS0_TO_PS2 BIT(6)
+
+#define TXVAL_VALID_INIT BIT(4)
+#define KR_PCIGEN3_MODE BIT(0)
+
+#define MAIN_EN BIT(0)
+
+#define TX_MARGINING_MUX BIT(6)
+#define TX_MARGINING(x) ((x) & 0x3f)
+
+#define TX_PRE_MUX BIT(6)
+
+#define TX_POST_MUX BIT(6)
+
+#define CML_GEAR_MODE(x) (((x) & 7) << 3)
+#define CML2CMOS_IBOOST_MODE(x) ((x) & 7)
+
+#define MIXER_LOADB_MODE(x) (((x) & 0xf) << 2)
+#define MIXER_DATARATE_MODE(x) ((x) & 3)
+
+#define VGA_THRESH_DFE(x) ((x) & 0x3f)
+
+#define SIGDET_LP_BYP_PS0_TO_PS2 BIT(5)
+#define SIGDET_FLT_BYP BIT(0)
+
+#define SIGDET_LVL(x) (((x) & 0xf) << 4)
+
+#define SIGDET_DEGLITCH_CTRL(x) (((x) & 0xf) << 1)
+
+#define INVERT_PCS_RX_CLK BIT(7)
+
+#define DRVR_LOGIC_CLK_EN BIT(4)
+#define DRVR_LOGIC_CLK_DIV(x) ((x) & 0xf)
+
+#define PARALLEL_RATE_MODE0(x) ((x) & 0x3)
+
+#define BAND_MODE0(x) ((x) & 0x3)
+
+#define LANE_MODE(x) ((x) & 0x1f)
+
+#define CDR_PD_SEL_MODE0(x) (((x) & 0x3) << 5)
+#define EN_DLL_MODE0 BIT(4)
+#define EN_IQ_DCC_MODE0 BIT(3)
+#define EN_IQCAL_MODE0 BIT(2)
+
+#define BYPASS_RSM_SAMP_CAL BIT(1)
+#define BYPASS_RSM_DLL_CAL BIT(0)
+
+#define L0_RX_EQUALIZE_ENABLE BIT(6)
+
+#define PWRDN_B BIT(0)
+
+#define CDR_MAX_CNT(x) ((x) & 0xff)
+
+#define SERDES_START_WAIT_TIMES 100
+
+struct emac_reg_write {
+ unsigned int offset;
+ u32 val;
+};
+
+static void emac_reg_write_all(void __iomem *base,
+ const struct emac_reg_write *itr, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; ++itr, ++i)
+ writel(itr->val, base + itr->offset);
+}
+
+static const struct emac_reg_write sgmii_laned[] = {
+ /* CDR Settings */
+ {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0,
+ UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)},
+ {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)},
+ {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)},
+
+ /* TX/RX Settings */
+ {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2},
+
+ {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE},
+ {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN},
+ {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)},
+ {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX},
+ {EMAC_SGMII_LN_TX_POST, TX_POST_MUX},
+
+ {EMAC_SGMII_LN_CML_CTRL_MODE0,
+ CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)},
+ {EMAC_SGMII_LN_MIXER_CTRL_MODE0,
+ MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)},
+ {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)},
+ {EMAC_SGMII_LN_SIGDET_ENABLES,
+ SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP},
+ {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)},
+
+ {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)},
+ {EMAC_SGMII_LN_RX_MISC_CNTRL0, INVERT_PCS_RX_CLK},
+ {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV,
+ DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)},
+
+ {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)},
+ {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(1)},
+ {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(2)},
+ {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)},
+ {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(2) |
+ EN_DLL_MODE0 | EN_IQ_DCC_MODE0 | EN_IQCAL_MODE0},
+ {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL},
+};
+
+static const struct emac_reg_write physical_coding_sublayer_programming[] = {
+ {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B},
+ {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)},
+ {EMAC_SGMII_PHY_TX_PWR_CTRL, 0},
+ {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE},
+};
+
+int emac_sgmii_init_qdf2400(struct emac_adapter *adpt)
+{
+ struct emac_phy *phy = &adpt->phy;
+ void __iomem *phy_regs = phy->base;
+ void __iomem *laned = phy->digital;
+ unsigned int i;
+ u32 lnstatus;
+
+ /* PCS lane-x init */
+ emac_reg_write_all(phy->base, physical_coding_sublayer_programming,
+ ARRAY_SIZE(physical_coding_sublayer_programming));
+
+ /* SGMII lane-x init */
+ emac_reg_write_all(phy->digital, sgmii_laned, ARRAY_SIZE(sgmii_laned));
+
+ /* Power up PCS and start reset lane state machine */
+
+ writel(0, phy_regs + EMAC_SGMII_PHY_RESET_CTRL);
+ writel(1, laned + SGMII_LN_RSM_START);
+
+ /* Wait for c_ready assertion */
+ for (i = 0; i < SERDES_START_WAIT_TIMES; i++) {
+ lnstatus = readl(phy_regs + SGMII_PHY_LN_LANE_STATUS);
+ if (lnstatus & BIT(1))
+ break;
+ usleep_range(100, 200);
+ }
+
+ if (i == SERDES_START_WAIT_TIMES) {
+ netdev_err(adpt->netdev, "SGMII failed to start\n");
+ return -EIO;
+ }
+
+ /* Disable digital and SERDES loopback */
+ writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN0);
+ writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN2);
+ writel(0, phy_regs + SGMII_PHY_LN_CDR_CTRL1);
+
+ /* Mask out all the SGMII Interrupt */
+ writel(0, phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2432.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2432.c
new file mode 100644
index 000000000000..6170200d7479
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii-qdf2432.c
@@ -0,0 +1,210 @@
+/* Copyright (c) 2015-2016, 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.
+ */
+
+/* Qualcomm Technologies, Inc. QDF2432 EMAC SGMII Controller driver.
+ */
+
+#include <linux/iopoll.h>
+#include "emac.h"
+
+/* EMAC_SGMII register offsets */
+#define EMAC_SGMII_PHY_TX_PWR_CTRL 0x000C
+#define EMAC_SGMII_PHY_LANE_CTRL1 0x0018
+#define EMAC_SGMII_PHY_CDR_CTRL0 0x0058
+#define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x0080
+#define EMAC_SGMII_PHY_RESET_CTRL 0x00a8
+#define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4
+
+/* SGMII digital lane registers */
+#define EMAC_SGMII_LN_DRVR_CTRL0 0x000C
+#define EMAC_SGMII_LN_DRVR_TAP_EN 0x0018
+#define EMAC_SGMII_LN_TX_MARGINING 0x001C
+#define EMAC_SGMII_LN_TX_PRE 0x0020
+#define EMAC_SGMII_LN_TX_POST 0x0024
+#define EMAC_SGMII_LN_TX_BAND_MODE 0x0060
+#define EMAC_SGMII_LN_LANE_MODE 0x0064
+#define EMAC_SGMII_LN_PARALLEL_RATE 0x0078
+#define EMAC_SGMII_LN_CML_CTRL_MODE0 0x00B8
+#define EMAC_SGMII_LN_MIXER_CTRL_MODE0 0x00D0
+#define EMAC_SGMII_LN_VGA_INITVAL 0x0134
+#define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0 0x017C
+#define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0 0x0188
+#define EMAC_SGMII_LN_UCDR_SO_CONFIG 0x0194
+#define EMAC_SGMII_LN_RX_BAND 0x019C
+#define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0 0x01B8
+#define EMAC_SGMII_LN_RSM_CONFIG 0x01F0
+#define EMAC_SGMII_LN_SIGDET_ENABLES 0x0224
+#define EMAC_SGMII_LN_SIGDET_CNTRL 0x0228
+#define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL 0x022C
+#define EMAC_SGMII_LN_RX_EN_SIGNAL 0x02A0
+#define EMAC_SGMII_LN_RX_MISC_CNTRL0 0x02AC
+#define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV 0x02BC
+
+/* SGMII digital lane register values */
+#define UCDR_STEP_BY_TWO_MODE0 BIT(7)
+#define UCDR_xO_GAIN_MODE(x) ((x) & 0x7f)
+#define UCDR_ENABLE BIT(6)
+#define UCDR_SO_SATURATION(x) ((x) & 0x3f)
+
+#define SIGDET_LP_BYP_PS4 BIT(7)
+#define SIGDET_EN_PS0_TO_PS2 BIT(6)
+
+#define TXVAL_VALID_INIT BIT(4)
+#define KR_PCIGEN3_MODE BIT(0)
+
+#define MAIN_EN BIT(0)
+
+#define TX_MARGINING_MUX BIT(6)
+#define TX_MARGINING(x) ((x) & 0x3f)
+
+#define TX_PRE_MUX BIT(6)
+
+#define TX_POST_MUX BIT(6)
+
+#define CML_GEAR_MODE(x) (((x) & 7) << 3)
+#define CML2CMOS_IBOOST_MODE(x) ((x) & 7)
+
+#define MIXER_LOADB_MODE(x) (((x) & 0xf) << 2)
+#define MIXER_DATARATE_MODE(x) ((x) & 3)
+
+#define VGA_THRESH_DFE(x) ((x) & 0x3f)
+
+#define SIGDET_LP_BYP_PS0_TO_PS2 BIT(5)
+#define SIGDET_FLT_BYP BIT(0)
+
+#define SIGDET_LVL(x) (((x) & 0xf) << 4)
+
+#define SIGDET_DEGLITCH_CTRL(x) (((x) & 0xf) << 1)
+
+#define DRVR_LOGIC_CLK_EN BIT(4)
+#define DRVR_LOGIC_CLK_DIV(x) ((x) & 0xf)
+
+#define PARALLEL_RATE_MODE0(x) ((x) & 0x3)
+
+#define BAND_MODE0(x) ((x) & 0x3)
+
+#define LANE_MODE(x) ((x) & 0x1f)
+
+#define CDR_PD_SEL_MODE0(x) (((x) & 0x3) << 5)
+#define BYPASS_RSM_SAMP_CAL BIT(1)
+#define BYPASS_RSM_DLL_CAL BIT(0)
+
+#define L0_RX_EQUALIZE_ENABLE BIT(6)
+
+#define PWRDN_B BIT(0)
+
+#define CDR_MAX_CNT(x) ((x) & 0xff)
+
+#define SERDES_START_WAIT_TIMES 100
+
+struct emac_reg_write {
+ unsigned int offset;
+ u32 val;
+};
+
+static void emac_reg_write_all(void __iomem *base,
+ const struct emac_reg_write *itr, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; ++itr, ++i)
+ writel(itr->val, base + itr->offset);
+}
+
+static const struct emac_reg_write sgmii_laned[] = {
+ /* CDR Settings */
+ {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0,
+ UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)},
+ {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)},
+ {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)},
+
+ /* TX/RX Settings */
+ {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2},
+
+ {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE},
+ {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN},
+ {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)},
+ {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX},
+ {EMAC_SGMII_LN_TX_POST, TX_POST_MUX},
+
+ {EMAC_SGMII_LN_CML_CTRL_MODE0,
+ CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)},
+ {EMAC_SGMII_LN_MIXER_CTRL_MODE0,
+ MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)},
+ {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)},
+ {EMAC_SGMII_LN_SIGDET_ENABLES,
+ SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP},
+ {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)},
+
+ {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)},
+ {EMAC_SGMII_LN_RX_MISC_CNTRL0, 0},
+ {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV,
+ DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)},
+
+ {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)},
+ {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(2)},
+ {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(3)},
+ {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)},
+ {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(3)},
+ {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL},
+};
+
+static const struct emac_reg_write physical_coding_sublayer_programming[] = {
+ {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B},
+ {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)},
+ {EMAC_SGMII_PHY_TX_PWR_CTRL, 0},
+ {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE},
+};
+
+int emac_sgmii_init_qdf2432(struct emac_adapter *adpt)
+{
+ struct emac_phy *phy = &adpt->phy;
+ void __iomem *phy_regs = phy->base;
+ void __iomem *laned = phy->digital;
+ unsigned int i;
+ u32 lnstatus;
+
+ /* PCS lane-x init */
+ emac_reg_write_all(phy->base, physical_coding_sublayer_programming,
+ ARRAY_SIZE(physical_coding_sublayer_programming));
+
+ /* SGMII lane-x init */
+ emac_reg_write_all(phy->digital, sgmii_laned, ARRAY_SIZE(sgmii_laned));
+
+ /* Power up PCS and start reset lane state machine */
+
+ writel(0, phy_regs + EMAC_SGMII_PHY_RESET_CTRL);
+ writel(1, laned + SGMII_LN_RSM_START);
+
+ /* Wait for c_ready assertion */
+ for (i = 0; i < SERDES_START_WAIT_TIMES; i++) {
+ lnstatus = readl(phy_regs + SGMII_PHY_LN_LANE_STATUS);
+ if (lnstatus & BIT(1))
+ break;
+ usleep_range(100, 200);
+ }
+
+ if (i == SERDES_START_WAIT_TIMES) {
+ netdev_err(adpt->netdev, "SGMII failed to start\n");
+ return -EIO;
+ }
+
+ /* Disable digital and SERDES loopback */
+ writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN0);
+ writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN2);
+ writel(0, phy_regs + SGMII_PHY_LN_CDR_CTRL1);
+
+ /* Mask out all the SGMII Interrupt */
+ writel(0, phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
index 72fe343c7a36..bf722a9bb09d 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
@@ -20,448 +20,33 @@
#include "emac-mac.h"
#include "emac-sgmii.h"
-/* EMAC_QSERDES register offsets */
-#define EMAC_QSERDES_COM_SYS_CLK_CTRL 0x000000
-#define EMAC_QSERDES_COM_PLL_CNTRL 0x000014
-#define EMAC_QSERDES_COM_PLL_IP_SETI 0x000018
-#define EMAC_QSERDES_COM_PLL_CP_SETI 0x000024
-#define EMAC_QSERDES_COM_PLL_IP_SETP 0x000028
-#define EMAC_QSERDES_COM_PLL_CP_SETP 0x00002c
-#define EMAC_QSERDES_COM_SYSCLK_EN_SEL 0x000038
-#define EMAC_QSERDES_COM_RESETSM_CNTRL 0x000040
-#define EMAC_QSERDES_COM_PLLLOCK_CMP1 0x000044
-#define EMAC_QSERDES_COM_PLLLOCK_CMP2 0x000048
-#define EMAC_QSERDES_COM_PLLLOCK_CMP3 0x00004c
-#define EMAC_QSERDES_COM_PLLLOCK_CMP_EN 0x000050
-#define EMAC_QSERDES_COM_DEC_START1 0x000064
-#define EMAC_QSERDES_COM_DIV_FRAC_START1 0x000098
-#define EMAC_QSERDES_COM_DIV_FRAC_START2 0x00009c
-#define EMAC_QSERDES_COM_DIV_FRAC_START3 0x0000a0
-#define EMAC_QSERDES_COM_DEC_START2 0x0000a4
-#define EMAC_QSERDES_COM_PLL_CRCTRL 0x0000ac
-#define EMAC_QSERDES_COM_RESET_SM 0x0000bc
-#define EMAC_QSERDES_TX_BIST_MODE_LANENO 0x000100
-#define EMAC_QSERDES_TX_TX_EMP_POST1_LVL 0x000108
-#define EMAC_QSERDES_TX_TX_DRV_LVL 0x00010c
-#define EMAC_QSERDES_TX_LANE_MODE 0x000150
-#define EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN 0x000170
-#define EMAC_QSERDES_RX_CDR_CONTROL 0x000200
-#define EMAC_QSERDES_RX_CDR_CONTROL2 0x000210
-#define EMAC_QSERDES_RX_RX_EQ_GAIN12 0x000230
-
/* EMAC_SGMII register offsets */
-#define EMAC_SGMII_PHY_SERDES_START 0x000000
-#define EMAC_SGMII_PHY_CMN_PWR_CTRL 0x000004
-#define EMAC_SGMII_PHY_RX_PWR_CTRL 0x000008
-#define EMAC_SGMII_PHY_TX_PWR_CTRL 0x00000C
-#define EMAC_SGMII_PHY_LANE_CTRL1 0x000018
-#define EMAC_SGMII_PHY_AUTONEG_CFG2 0x000048
-#define EMAC_SGMII_PHY_CDR_CTRL0 0x000058
-#define EMAC_SGMII_PHY_SPEED_CFG1 0x000074
-#define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x000080
-#define EMAC_SGMII_PHY_RESET_CTRL 0x0000a8
-#define EMAC_SGMII_PHY_IRQ_CMD 0x0000ac
-#define EMAC_SGMII_PHY_INTERRUPT_CLEAR 0x0000b0
-#define EMAC_SGMII_PHY_INTERRUPT_MASK 0x0000b4
-#define EMAC_SGMII_PHY_INTERRUPT_STATUS 0x0000b8
-#define EMAC_SGMII_PHY_RX_CHK_STATUS 0x0000d4
-#define EMAC_SGMII_PHY_AUTONEG0_STATUS 0x0000e0
-#define EMAC_SGMII_PHY_AUTONEG1_STATUS 0x0000e4
-
-/* EMAC_QSERDES_COM_PLL_IP_SETI */
-#define PLL_IPSETI(x) ((x) & 0x3f)
-
-/* EMAC_QSERDES_COM_PLL_CP_SETI */
-#define PLL_CPSETI(x) ((x) & 0xff)
-
-/* EMAC_QSERDES_COM_PLL_IP_SETP */
-#define PLL_IPSETP(x) ((x) & 0x3f)
-
-/* EMAC_QSERDES_COM_PLL_CP_SETP */
-#define PLL_CPSETP(x) ((x) & 0x1f)
-
-/* EMAC_QSERDES_COM_PLL_CRCTRL */
-#define PLL_RCTRL(x) (((x) & 0xf) << 4)
-#define PLL_CCTRL(x) ((x) & 0xf)
-
-/* SGMII v2 PHY registers per lane */
-#define EMAC_SGMII_PHY_LN_OFFSET 0x0400
-
-/* SGMII v2 digital lane registers */
-#define EMAC_SGMII_LN_DRVR_CTRL0 0x00C
-#define EMAC_SGMII_LN_DRVR_TAP_EN 0x018
-#define EMAC_SGMII_LN_TX_MARGINING 0x01C
-#define EMAC_SGMII_LN_TX_PRE 0x020
-#define EMAC_SGMII_LN_TX_POST 0x024
-#define EMAC_SGMII_LN_TX_BAND_MODE 0x060
-#define EMAC_SGMII_LN_LANE_MODE 0x064
-#define EMAC_SGMII_LN_PARALLEL_RATE 0x078
-#define EMAC_SGMII_LN_CML_CTRL_MODE0 0x0B8
-#define EMAC_SGMII_LN_MIXER_CTRL_MODE0 0x0D0
-#define EMAC_SGMII_LN_VGA_INITVAL 0x134
-#define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0 0x17C
-#define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0 0x188
-#define EMAC_SGMII_LN_UCDR_SO_CONFIG 0x194
-#define EMAC_SGMII_LN_RX_BAND 0x19C
-#define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0 0x1B8
-#define EMAC_SGMII_LN_RSM_CONFIG 0x1F0
-#define EMAC_SGMII_LN_SIGDET_ENABLES 0x224
-#define EMAC_SGMII_LN_SIGDET_CNTRL 0x228
-#define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL 0x22C
-#define EMAC_SGMII_LN_RX_EN_SIGNAL 0x2A0
-#define EMAC_SGMII_LN_RX_MISC_CNTRL0 0x2AC
-#define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV 0x2BC
-
-/* SGMII v2 digital lane register values */
-#define UCDR_STEP_BY_TWO_MODE0 BIT(7)
-#define UCDR_xO_GAIN_MODE(x) ((x) & 0x7f)
-#define UCDR_ENABLE BIT(6)
-#define UCDR_SO_SATURATION(x) ((x) & 0x3f)
-#define SIGDET_LP_BYP_PS4 BIT(7)
-#define SIGDET_EN_PS0_TO_PS2 BIT(6)
-#define EN_ACCOUPLEVCM_SW_MUX BIT(5)
-#define EN_ACCOUPLEVCM_SW BIT(4)
-#define RX_SYNC_EN BIT(3)
-#define RXTERM_HIGHZ_PS5 BIT(2)
-#define SIGDET_EN_PS3 BIT(1)
-#define EN_ACCOUPLE_VCM_PS3 BIT(0)
-#define UFS_MODE BIT(5)
-#define TXVAL_VALID_INIT BIT(4)
-#define TXVAL_VALID_MUX BIT(3)
-#define TXVAL_VALID BIT(2)
-#define USB3P1_MODE BIT(1)
-#define KR_PCIGEN3_MODE BIT(0)
-#define PRE_EN BIT(3)
-#define POST_EN BIT(2)
-#define MAIN_EN_MUX BIT(1)
-#define MAIN_EN BIT(0)
-#define TX_MARGINING_MUX BIT(6)
-#define TX_MARGINING(x) ((x) & 0x3f)
-#define TX_PRE_MUX BIT(6)
-#define TX_PRE(x) ((x) & 0x3f)
-#define TX_POST_MUX BIT(6)
-#define TX_POST(x) ((x) & 0x3f)
-#define CML_GEAR_MODE(x) (((x) & 7) << 3)
-#define CML2CMOS_IBOOST_MODE(x) ((x) & 7)
-#define MIXER_LOADB_MODE(x) (((x) & 0xf) << 2)
-#define MIXER_DATARATE_MODE(x) ((x) & 3)
-#define VGA_THRESH_DFE(x) ((x) & 0x3f)
-#define SIGDET_LP_BYP_PS0_TO_PS2 BIT(5)
-#define SIGDET_LP_BYP_MUX BIT(4)
-#define SIGDET_LP_BYP BIT(3)
-#define SIGDET_EN_MUX BIT(2)
-#define SIGDET_EN BIT(1)
-#define SIGDET_FLT_BYP BIT(0)
-#define SIGDET_LVL(x) (((x) & 0xf) << 4)
-#define SIGDET_BW_CTRL(x) ((x) & 0xf)
-#define SIGDET_DEGLITCH_CTRL(x) (((x) & 0xf) << 1)
-#define SIGDET_DEGLITCH_BYP BIT(0)
-#define INVERT_PCS_RX_CLK BIT(7)
-#define PWM_EN BIT(6)
-#define RXBIAS_SEL(x) (((x) & 0x3) << 4)
-#define EBDAC_SIGN BIT(3)
-#define EDAC_SIGN BIT(2)
-#define EN_AUXTAP1SIGN_INVERT BIT(1)
-#define EN_DAC_CHOPPING BIT(0)
-#define DRVR_LOGIC_CLK_EN BIT(4)
-#define DRVR_LOGIC_CLK_DIV(x) ((x) & 0xf)
-#define PARALLEL_RATE_MODE2(x) (((x) & 0x3) << 4)
-#define PARALLEL_RATE_MODE1(x) (((x) & 0x3) << 2)
-#define PARALLEL_RATE_MODE0(x) ((x) & 0x3)
-#define BAND_MODE2(x) (((x) & 0x3) << 4)
-#define BAND_MODE1(x) (((x) & 0x3) << 2)
-#define BAND_MODE0(x) ((x) & 0x3)
-#define LANE_SYNC_MODE BIT(5)
-#define LANE_MODE(x) ((x) & 0x1f)
-#define CDR_PD_SEL_MODE0(x) (((x) & 0x3) << 5)
-#define EN_DLL_MODE0 BIT(4)
-#define EN_IQ_DCC_MODE0 BIT(3)
-#define EN_IQCAL_MODE0 BIT(2)
-#define EN_QPATH_MODE0 BIT(1)
-#define EN_EPATH_MODE0 BIT(0)
-#define FORCE_TSYNC_ACK BIT(7)
-#define FORCE_CMN_ACK BIT(6)
-#define FORCE_CMN_READY BIT(5)
-#define EN_RCLK_DEGLITCH BIT(4)
-#define BYPASS_RSM_CDR_RESET BIT(3)
-#define BYPASS_RSM_TSYNC BIT(2)
-#define BYPASS_RSM_SAMP_CAL BIT(1)
-#define BYPASS_RSM_DLL_CAL BIT(0)
-
-/* EMAC_QSERDES_COM_SYS_CLK_CTRL */
-#define SYSCLK_CM BIT(4)
-#define SYSCLK_AC_COUPLE BIT(3)
-
-/* EMAC_QSERDES_COM_PLL_CNTRL */
-#define OCP_EN BIT(5)
-#define PLL_DIV_FFEN BIT(2)
-#define PLL_DIV_ORD BIT(1)
-
-/* EMAC_QSERDES_COM_SYSCLK_EN_SEL */
-#define SYSCLK_SEL_CMOS BIT(3)
-
-/* EMAC_QSERDES_COM_RESETSM_CNTRL */
-#define FRQ_TUNE_MODE BIT(4)
-
-/* EMAC_QSERDES_COM_PLLLOCK_CMP_EN */
-#define PLLLOCK_CMP_EN BIT(0)
-
-/* EMAC_QSERDES_COM_DEC_START1 */
-#define DEC_START1_MUX BIT(7)
-#define DEC_START1(x) ((x) & 0x7f)
-
-/* EMAC_QSERDES_COM_DIV_FRAC_START1 * EMAC_QSERDES_COM_DIV_FRAC_START2 */
-#define DIV_FRAC_START_MUX BIT(7)
-#define DIV_FRAC_START(x) ((x) & 0x7f)
-
-/* EMAC_QSERDES_COM_DIV_FRAC_START3 */
-#define DIV_FRAC_START3_MUX BIT(4)
-#define DIV_FRAC_START3(x) ((x) & 0xf)
-
-/* EMAC_QSERDES_COM_DEC_START2 */
-#define DEC_START2_MUX BIT(1)
-#define DEC_START2 BIT(0)
-
-/* EMAC_QSERDES_COM_RESET_SM */
-#define READY BIT(5)
-
-/* EMAC_QSERDES_TX_TX_EMP_POST1_LVL */
-#define TX_EMP_POST1_LVL_MUX BIT(5)
-#define TX_EMP_POST1_LVL(x) ((x) & 0x1f)
-#define TX_EMP_POST1_LVL_BMSK 0x1f
-#define TX_EMP_POST1_LVL_SHFT 0
-
-/* EMAC_QSERDES_TX_TX_DRV_LVL */
-#define TX_DRV_LVL_MUX BIT(4)
-#define TX_DRV_LVL(x) ((x) & 0xf)
-
-/* EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN */
-#define EMP_EN_MUX BIT(1)
-#define EMP_EN BIT(0)
-
-/* EMAC_QSERDES_RX_CDR_CONTROL & EMAC_QSERDES_RX_CDR_CONTROL2 */
-#define HBW_PD_EN BIT(7)
-#define SECONDORDERENABLE BIT(6)
-#define FIRSTORDER_THRESH(x) (((x) & 0x7) << 3)
-#define SECONDORDERGAIN(x) ((x) & 0x7)
-
-/* EMAC_QSERDES_RX_RX_EQ_GAIN12 */
-#define RX_EQ_GAIN2(x) (((x) & 0xf) << 4)
-#define RX_EQ_GAIN1(x) ((x) & 0xf)
-
-/* EMAC_SGMII_PHY_SERDES_START */
-#define SERDES_START BIT(0)
-
-/* EMAC_SGMII_PHY_CMN_PWR_CTRL */
-#define BIAS_EN BIT(6)
-#define PLL_EN BIT(5)
-#define SYSCLK_EN BIT(4)
-#define CLKBUF_L_EN BIT(3)
-#define PLL_TXCLK_EN BIT(1)
-#define PLL_RXCLK_EN BIT(0)
-
-/* EMAC_SGMII_PHY_RX_PWR_CTRL */
-#define L0_RX_SIGDET_EN BIT(7)
-#define L0_RX_TERM_MODE(x) (((x) & 3) << 4)
-#define L0_RX_I_EN BIT(1)
-
-/* EMAC_SGMII_PHY_TX_PWR_CTRL */
-#define L0_TX_EN BIT(5)
-#define L0_CLKBUF_EN BIT(4)
-#define L0_TRAN_BIAS_EN BIT(1)
-
-/* EMAC_SGMII_PHY_LANE_CTRL1 */
-#define L0_RX_EQUALIZE_ENABLE BIT(6)
-#define L0_RESET_TSYNC_EN BIT(4)
-#define L0_DRV_LVL(x) ((x) & 0xf)
-
-/* EMAC_SGMII_PHY_AUTONEG_CFG2 */
+#define EMAC_SGMII_PHY_AUTONEG_CFG2 0x0048
+#define EMAC_SGMII_PHY_SPEED_CFG1 0x0074
+#define EMAC_SGMII_PHY_IRQ_CMD 0x00ac
+#define EMAC_SGMII_PHY_INTERRUPT_CLEAR 0x00b0
+#define EMAC_SGMII_PHY_INTERRUPT_STATUS 0x00b8
+
#define FORCE_AN_TX_CFG BIT(5)
#define FORCE_AN_RX_CFG BIT(4)
#define AN_ENABLE BIT(0)
-/* EMAC_SGMII_PHY_SPEED_CFG1 */
#define DUPLEX_MODE BIT(4)
#define SPDMODE_1000 BIT(1)
#define SPDMODE_100 BIT(0)
#define SPDMODE_10 0
-#define SPDMODE_BMSK 3
-#define SPDMODE_SHFT 0
-
-/* EMAC_SGMII_PHY_POW_DWN_CTRL0 */
-#define PWRDN_B BIT(0)
-#define CDR_MAX_CNT(x) ((x) & 0xff)
-
-/* EMAC_QSERDES_TX_BIST_MODE_LANENO */
-#define BIST_LANE_NUMBER(x) (((x) & 3) << 5)
-#define BISTMODE(x) ((x) & 0x1f)
-
-/* EMAC_QSERDES_COM_PLLLOCK_CMPx */
-#define PLLLOCK_CMP(x) ((x) & 0xff)
-/* EMAC_SGMII_PHY_RESET_CTRL */
-#define PHY_SW_RESET BIT(0)
-
-/* EMAC_SGMII_PHY_IRQ_CMD */
#define IRQ_GLOBAL_CLEAR BIT(0)
-/* EMAC_SGMII_PHY_INTERRUPT_MASK */
#define DECODE_CODE_ERR BIT(7)
#define DECODE_DISP_ERR BIT(6)
-#define PLL_UNLOCK BIT(5)
-#define AN_ILLEGAL_TERM BIT(4)
-#define SYNC_FAIL BIT(3)
-#define AN_START BIT(2)
-#define AN_END BIT(1)
-#define AN_REQUEST BIT(0)
#define SGMII_PHY_IRQ_CLR_WAIT_TIME 10
-#define SGMII_PHY_INTERRUPT_ERR (\
- DECODE_CODE_ERR |\
- DECODE_DISP_ERR)
-
-#define SGMII_ISR_AN_MASK (\
- AN_REQUEST |\
- AN_START |\
- AN_END |\
- AN_ILLEGAL_TERM |\
- PLL_UNLOCK |\
- SYNC_FAIL)
-
-#define SGMII_ISR_MASK (\
- SGMII_PHY_INTERRUPT_ERR |\
- SGMII_ISR_AN_MASK)
-
-/* SGMII TX_CONFIG */
-#define TXCFG_LINK 0x8000
-#define TXCFG_MODE_BMSK 0x1c00
-#define TXCFG_1000_FULL 0x1800
-#define TXCFG_100_FULL 0x1400
-#define TXCFG_100_HALF 0x0400
-#define TXCFG_10_FULL 0x1000
-#define TXCFG_10_HALF 0x0000
+#define SGMII_PHY_INTERRUPT_ERR (DECODE_CODE_ERR | DECODE_DISP_ERR)
#define SERDES_START_WAIT_TIMES 100
-struct emac_reg_write {
- unsigned int offset;
- u32 val;
-};
-
-static void emac_reg_write_all(void __iomem *base,
- const struct emac_reg_write *itr, size_t size)
-{
- size_t i;
-
- for (i = 0; i < size; ++itr, ++i)
- writel(itr->val, base + itr->offset);
-}
-
-static const struct emac_reg_write physical_coding_sublayer_programming_v1[] = {
- {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)},
- {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B},
- {EMAC_SGMII_PHY_CMN_PWR_CTRL,
- BIAS_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | PLL_RXCLK_EN},
- {EMAC_SGMII_PHY_TX_PWR_CTRL, L0_TX_EN | L0_CLKBUF_EN | L0_TRAN_BIAS_EN},
- {EMAC_SGMII_PHY_RX_PWR_CTRL,
- L0_RX_SIGDET_EN | L0_RX_TERM_MODE(1) | L0_RX_I_EN},
- {EMAC_SGMII_PHY_CMN_PWR_CTRL,
- BIAS_EN | PLL_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN |
- PLL_RXCLK_EN},
- {EMAC_SGMII_PHY_LANE_CTRL1,
- L0_RX_EQUALIZE_ENABLE | L0_RESET_TSYNC_EN | L0_DRV_LVL(15)},
-};
-
-static const struct emac_reg_write sysclk_refclk_setting[] = {
- {EMAC_QSERDES_COM_SYSCLK_EN_SEL, SYSCLK_SEL_CMOS},
- {EMAC_QSERDES_COM_SYS_CLK_CTRL, SYSCLK_CM | SYSCLK_AC_COUPLE},
-};
-
-static const struct emac_reg_write pll_setting[] = {
- {EMAC_QSERDES_COM_PLL_IP_SETI, PLL_IPSETI(1)},
- {EMAC_QSERDES_COM_PLL_CP_SETI, PLL_CPSETI(59)},
- {EMAC_QSERDES_COM_PLL_IP_SETP, PLL_IPSETP(10)},
- {EMAC_QSERDES_COM_PLL_CP_SETP, PLL_CPSETP(9)},
- {EMAC_QSERDES_COM_PLL_CRCTRL, PLL_RCTRL(15) | PLL_CCTRL(11)},
- {EMAC_QSERDES_COM_PLL_CNTRL, OCP_EN | PLL_DIV_FFEN | PLL_DIV_ORD},
- {EMAC_QSERDES_COM_DEC_START1, DEC_START1_MUX | DEC_START1(2)},
- {EMAC_QSERDES_COM_DEC_START2, DEC_START2_MUX | DEC_START2},
- {EMAC_QSERDES_COM_DIV_FRAC_START1,
- DIV_FRAC_START_MUX | DIV_FRAC_START(85)},
- {EMAC_QSERDES_COM_DIV_FRAC_START2,
- DIV_FRAC_START_MUX | DIV_FRAC_START(42)},
- {EMAC_QSERDES_COM_DIV_FRAC_START3,
- DIV_FRAC_START3_MUX | DIV_FRAC_START3(3)},
- {EMAC_QSERDES_COM_PLLLOCK_CMP1, PLLLOCK_CMP(43)},
- {EMAC_QSERDES_COM_PLLLOCK_CMP2, PLLLOCK_CMP(104)},
- {EMAC_QSERDES_COM_PLLLOCK_CMP3, PLLLOCK_CMP(0)},
- {EMAC_QSERDES_COM_PLLLOCK_CMP_EN, PLLLOCK_CMP_EN},
- {EMAC_QSERDES_COM_RESETSM_CNTRL, FRQ_TUNE_MODE},
-};
-
-static const struct emac_reg_write cdr_setting[] = {
- {EMAC_QSERDES_RX_CDR_CONTROL,
- SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(2)},
- {EMAC_QSERDES_RX_CDR_CONTROL2,
- SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(4)},
-};
-
-static const struct emac_reg_write tx_rx_setting[] = {
- {EMAC_QSERDES_TX_BIST_MODE_LANENO, 0},
- {EMAC_QSERDES_TX_TX_DRV_LVL, TX_DRV_LVL_MUX | TX_DRV_LVL(15)},
- {EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN, EMP_EN_MUX | EMP_EN},
- {EMAC_QSERDES_TX_TX_EMP_POST1_LVL,
- TX_EMP_POST1_LVL_MUX | TX_EMP_POST1_LVL(1)},
- {EMAC_QSERDES_RX_RX_EQ_GAIN12, RX_EQ_GAIN2(15) | RX_EQ_GAIN1(15)},
- {EMAC_QSERDES_TX_LANE_MODE, LANE_MODE(8)},
-};
-
-static const struct emac_reg_write sgmii_v2_laned[] = {
- /* CDR Settings */
- {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0,
- UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)},
- {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)},
- {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)},
-
- /* TX/RX Settings */
- {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2},
-
- {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE},
- {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN},
- {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)},
- {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX},
- {EMAC_SGMII_LN_TX_POST, TX_POST_MUX},
-
- {EMAC_SGMII_LN_CML_CTRL_MODE0,
- CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)},
- {EMAC_SGMII_LN_MIXER_CTRL_MODE0,
- MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)},
- {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)},
- {EMAC_SGMII_LN_SIGDET_ENABLES,
- SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP},
- {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)},
-
- {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)},
- {EMAC_SGMII_LN_RX_MISC_CNTRL0, 0},
- {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV,
- DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)},
-
- {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)},
- {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(2)},
- {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(3)},
- {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)},
- {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(3)},
- {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL},
-};
-
-static const struct emac_reg_write physical_coding_sublayer_programming_v2[] = {
- {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B},
- {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)},
- {EMAC_SGMII_PHY_TX_PWR_CTRL, 0},
- {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE},
-};
-
static int emac_sgmii_link_init(struct emac_adapter *adpt)
{
struct phy_device *phydev = adpt->phydev;
@@ -536,98 +121,6 @@ static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits)
return 0;
}
-int emac_sgmii_init_v1(struct emac_adapter *adpt)
-{
- struct emac_phy *phy = &adpt->phy;
- unsigned int i;
- int ret;
-
- ret = emac_sgmii_link_init(adpt);
- if (ret)
- return ret;
-
- emac_reg_write_all(phy->base, physical_coding_sublayer_programming_v1,
- ARRAY_SIZE(physical_coding_sublayer_programming_v1));
- emac_reg_write_all(phy->base, sysclk_refclk_setting,
- ARRAY_SIZE(sysclk_refclk_setting));
- emac_reg_write_all(phy->base, pll_setting, ARRAY_SIZE(pll_setting));
- emac_reg_write_all(phy->base, cdr_setting, ARRAY_SIZE(cdr_setting));
- emac_reg_write_all(phy->base, tx_rx_setting,
- ARRAY_SIZE(tx_rx_setting));
-
- /* Power up the Ser/Des engine */
- writel(SERDES_START, phy->base + EMAC_SGMII_PHY_SERDES_START);
-
- for (i = 0; i < SERDES_START_WAIT_TIMES; i++) {
- if (readl(phy->base + EMAC_QSERDES_COM_RESET_SM) & READY)
- break;
- usleep_range(100, 200);
- }
-
- if (i == SERDES_START_WAIT_TIMES) {
- netdev_err(adpt->netdev, "error: ser/des failed to start\n");
- return -EIO;
- }
- /* Mask out all the SGMII Interrupt */
- writel(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
-
- emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR);
-
- return 0;
-}
-
-int emac_sgmii_init_v2(struct emac_adapter *adpt)
-{
- struct emac_phy *phy = &adpt->phy;
- void __iomem *phy_regs = phy->base;
- void __iomem *laned = phy->digital;
- unsigned int i;
- u32 lnstatus;
- int ret;
-
- ret = emac_sgmii_link_init(adpt);
- if (ret)
- return ret;
-
- /* PCS lane-x init */
- emac_reg_write_all(phy->base, physical_coding_sublayer_programming_v2,
- ARRAY_SIZE(physical_coding_sublayer_programming_v2));
-
- /* SGMII lane-x init */
- emac_reg_write_all(phy->digital,
- sgmii_v2_laned, ARRAY_SIZE(sgmii_v2_laned));
-
- /* Power up PCS and start reset lane state machine */
-
- writel(0, phy_regs + EMAC_SGMII_PHY_RESET_CTRL);
- writel(1, laned + SGMII_LN_RSM_START);
-
- /* Wait for c_ready assertion */
- for (i = 0; i < SERDES_START_WAIT_TIMES; i++) {
- lnstatus = readl(phy_regs + SGMII_PHY_LN_LANE_STATUS);
- if (lnstatus & BIT(1))
- break;
- usleep_range(100, 200);
- }
-
- if (i == SERDES_START_WAIT_TIMES) {
- netdev_err(adpt->netdev, "SGMII failed to start\n");
- return -EIO;
- }
-
- /* Disable digital and SERDES loopback */
- writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN0);
- writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN2);
- writel(0, phy_regs + SGMII_PHY_LN_CDR_CTRL1);
-
- /* Mask out all the SGMII Interrupt */
- writel(0, phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK);
-
- emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR);
-
- return 0;
-}
-
static void emac_sgmii_reset_prepare(struct emac_adapter *adpt)
{
struct emac_phy *phy = &adpt->phy;
@@ -651,44 +144,72 @@ void emac_sgmii_reset(struct emac_adapter *adpt)
{
int ret;
- clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 19200000);
emac_sgmii_reset_prepare(adpt);
+ ret = emac_sgmii_link_init(adpt);
+ if (ret) {
+ netdev_err(adpt->netdev, "unsupported link speed\n");
+ return;
+ }
+
ret = adpt->phy.initialize(adpt);
if (ret)
netdev_err(adpt->netdev,
"could not reinitialize internal PHY (error=%i)\n",
ret);
-
- clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 125000000);
}
static int emac_sgmii_acpi_match(struct device *dev, void *data)
{
+#ifdef CONFIG_ACPI
static const struct acpi_device_id match_table[] = {
{
.id = "QCOM8071",
- .driver_data = (kernel_ulong_t)emac_sgmii_init_v2,
},
{}
};
const struct acpi_device_id *id = acpi_match_device(match_table, dev);
emac_sgmii_initialize *initialize = data;
- if (id)
- *initialize = (emac_sgmii_initialize)id->driver_data;
+ if (id) {
+ acpi_handle handle = ACPI_HANDLE(dev);
+ unsigned long long hrv;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
+ if (status) {
+ if (status == AE_NOT_FOUND)
+ /* Older versions of the QDF2432 ACPI tables do
+ * not have an _HRV property.
+ */
+ hrv = 1;
+ else
+ /* Something is wrong with the tables */
+ return 0;
+ }
- return !!id;
+ switch (hrv) {
+ case 1:
+ *initialize = emac_sgmii_init_qdf2432;
+ return 1;
+ case 2:
+ *initialize = emac_sgmii_init_qdf2400;
+ return 1;
+ }
+ }
+#endif
+
+ return 0;
}
static const struct of_device_id emac_sgmii_dt_match[] = {
{
.compatible = "qcom,fsm9900-emac-sgmii",
- .data = emac_sgmii_init_v1,
+ .data = emac_sgmii_init_fsm9900,
},
{
.compatible = "qcom,qdf2432-emac-sgmii",
- .data = emac_sgmii_init_v2,
+ .data = emac_sgmii_init_qdf2432,
},
{}
};
@@ -765,6 +286,8 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
if (ret)
goto error;
+ emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR);
+
/* We've remapped the addresses, so we don't need the device any
* more. of_find_device_by_node() says we should release it.
*/
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
index ce79212ff403..80ed3dc3157a 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
@@ -16,9 +16,11 @@
struct emac_adapter;
struct platform_device;
-int emac_sgmii_init_v1(struct emac_adapter *adpt);
-int emac_sgmii_init_v2(struct emac_adapter *adpt);
int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt);
void emac_sgmii_reset(struct emac_adapter *adpt);
+int emac_sgmii_init_fsm9900(struct emac_adapter *adpt);
+int emac_sgmii_init_qdf2432(struct emac_adapter *adpt);
+int emac_sgmii_init_qdf2400(struct emac_adapter *adpt);
+
#endif
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 57b35aeac51a..ae32f855e31b 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -239,15 +239,8 @@ static void emac_rx_mode_set(struct net_device *netdev)
/* Change the Maximum Transfer Unit (MTU) */
static int emac_change_mtu(struct net_device *netdev, int new_mtu)
{
- unsigned int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
struct emac_adapter *adpt = netdev_priv(netdev);
- if ((max_frame < EMAC_MIN_ETH_FRAME_SIZE) ||
- (max_frame > EMAC_MAX_ETH_FRAME_SIZE)) {
- netdev_err(adpt->netdev, "error: invalid MTU setting\n");
- return -EINVAL;
- }
-
netif_info(adpt, hw, adpt->netdev,
"changing MTU from %d to %d\n", netdev->mtu,
new_mtu);
@@ -680,6 +673,12 @@ static int emac_probe(struct platform_device *pdev)
netdev->vlan_features |= NETIF_F_SG | NETIF_F_HW_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
+ /* MTU range: 46 - 9194 */
+ netdev->min_mtu = EMAC_MIN_ETH_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+ netdev->max_mtu = EMAC_MAX_ETH_FRAME_SIZE -
+ (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
INIT_WORK(&adpt->work_thread, emac_work_thread);
/* Initialize queues */
diff --git a/drivers/net/ethernet/qualcomm/qca_framing.h b/drivers/net/ethernet/qualcomm/qca_framing.h
index 5d965959c978..d5e795dcdf47 100644
--- a/drivers/net/ethernet/qualcomm/qca_framing.h
+++ b/drivers/net/ethernet/qualcomm/qca_framing.h
@@ -43,9 +43,9 @@
/* Frame length is invalid */
#define QCAFRM_INVFRAME (QCAFRM_ERR_BASE - 4)
-/* Min/Max Ethernet MTU */
-#define QCAFRM_ETHMINMTU 46
-#define QCAFRM_ETHMAXMTU 1500
+/* Min/Max Ethernet MTU: 46/1500 */
+#define QCAFRM_ETHMINMTU (ETH_ZLEN - ETH_HLEN)
+#define QCAFRM_ETHMAXMTU ETH_DATA_LEN
/* Min/Max frame lengths */
#define QCAFRM_ETHMINLEN (QCAFRM_ETHMINMTU + ETH_HLEN)
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index 6e2add979471..513e6c74e199 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -780,24 +780,12 @@ qcaspi_netdev_uninit(struct net_device *dev)
dev_kfree_skb(qca->rx_skb);
}
-static int
-qcaspi_netdev_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < QCAFRM_ETHMINMTU) || (new_mtu > QCAFRM_ETHMAXMTU))
- return -EINVAL;
-
- dev->mtu = new_mtu;
-
- return 0;
-}
-
static const struct net_device_ops qcaspi_netdev_ops = {
.ndo_init = qcaspi_netdev_init,
.ndo_uninit = qcaspi_netdev_uninit,
.ndo_open = qcaspi_netdev_open,
.ndo_stop = qcaspi_netdev_close,
.ndo_start_xmit = qcaspi_netdev_xmit,
- .ndo_change_mtu = qcaspi_netdev_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = qcaspi_netdev_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -814,6 +802,10 @@ qcaspi_netdev_setup(struct net_device *dev)
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->tx_queue_len = 100;
+ /* MTU range: 46 - 1500 */
+ dev->min_mtu = QCAFRM_ETHMINMTU;
+ dev->max_mtu = QCAFRM_ETHMAXMTU;
+
qca = netdev_priv(dev);
memset(qca, 0, sizeof(struct qcaspi));
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index 5ef5d728c250..4ff4e0491406 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -969,7 +969,6 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_start_xmit = r6040_start_xmit,
.ndo_get_stats = r6040_get_stats,
.ndo_set_rx_mode = r6040_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = r6040_ioctl,
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 5297bf77211c..b7c89ebcf4a2 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1277,10 +1277,6 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
struct cp_private *cp = netdev_priv(dev);
- /* check for invalid MTU, according to hardware limits */
- if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
- return -EINVAL;
-
/* if network interface not up, no need for complexity */
if (!netif_running(dev)) {
dev->mtu = new_mtu;
@@ -2010,6 +2006,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
NETIF_F_HIGHDMA;
+ /* MTU range: 60 - 4096 */
+ dev->min_mtu = CP_MIN_MTU;
+ dev->max_mtu = CP_MAX_MTU;
+
rc = register_netdev(dev);
if (rc)
goto err_out_iomap;
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index da4c2d8a4173..9bc047ac883b 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -924,19 +924,10 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
return 0;
}
-static int rtl8139_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < 68 || new_mtu > MAX_ETH_DATA_SIZE)
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_open = rtl8139_open,
.ndo_stop = rtl8139_close,
.ndo_get_stats64 = rtl8139_get_stats64,
- .ndo_change_mtu = rtl8139_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = rtl8139_set_mac_address,
.ndo_start_xmit = rtl8139_start_xmit,
@@ -1022,6 +1013,10 @@ static int rtl8139_init_one(struct pci_dev *pdev,
dev->hw_features |= NETIF_F_RXALL;
dev->hw_features |= NETIF_F_RXFCS;
+ /* MTU range: 68 - 1770 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = MAX_ETH_DATA_SIZE;
+
/* tp zeroed and aligned in alloc_etherdev */
tp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index 5cb96785fb63..570ed3bd3cbf 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -245,7 +245,6 @@ static const struct net_device_ops atp_netdev_ops = {
.ndo_start_xmit = atp_send_packet,
.ndo_set_rx_mode = set_rx_mode,
.ndo_tx_timeout = tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index bf000d819a21..f9b97f5946f8 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -2344,6 +2344,13 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
}
}
+static int rtl8169_nway_reset(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ return mii_nway_restart(&tp->mii);
+}
+
static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
@@ -2359,6 +2366,7 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_sset_count = rtl8169_get_sset_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
.get_ts_info = ethtool_op_get_ts_info,
+ .nway_reset = rtl8169_nway_reset,
};
static void rtl8169_get_mac_version(struct rtl8169_private *tp,
@@ -6673,10 +6681,6 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
{
struct rtl8169_private *tp = netdev_priv(dev);
- if (new_mtu < ETH_ZLEN ||
- new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
- return -EINVAL;
-
if (new_mtu > ETH_DATA_LEN)
rtl_hw_jumbo_enable(tp);
else
@@ -8431,6 +8435,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->hw_features |= NETIF_F_RXALL;
dev->hw_features |= NETIF_F_RXFCS;
+ /* MTU range: 60 - hw-specific max */
+ dev->min_mtu = ETH_ZLEN;
+ dev->max_mtu = rtl_chip_infos[chipset].jumbo_max;
+
tp->hw_start = cfg->hw_start;
tp->event_slow = cfg->event_slow;
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index 85ec447c2d18..27be51f0a421 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -37,7 +37,7 @@ config RAVB
select MII
select MDIO_BITBANG
select PHYLIB
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
help
Renesas Ethernet AVB device driver.
This driver supports the following SoCs:
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index d6a217874a8b..92d7692c840d 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1789,7 +1789,6 @@ static const struct net_device_ops ravb_netdev_ops = {
.ndo_do_ioctl = ravb_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
};
/* MDIO bus init function */
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 1a92de705199..f341c1bc7001 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2914,7 +2914,6 @@ static const struct net_device_ops sh_eth_netdev_ops = {
.ndo_do_ioctl = sh_eth_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static const struct net_device_ops sh_eth_netdev_ops_tsu = {
@@ -2929,7 +2928,6 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
.ndo_do_ioctl = sh_eth_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
};
#ifdef CONFIG_OF
diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index 2eb9b49569d5..ee9675db5bf9 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -72,6 +72,7 @@ struct rocker {
struct rocker_dma_ring_info event_ring;
struct notifier_block fib_nb;
struct rocker_world_ops *wops;
+ struct workqueue_struct *rocker_owq;
void *wpriv;
};
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 24b746406bc7..7c450b5a1138 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -28,6 +28,7 @@
#include <linux/if_bridge.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
+#include <linux/workqueue.h>
#include <net/switchdev.h>
#include <net/rtnetlink.h>
#include <net/netevent.h>
@@ -1953,12 +1954,6 @@ static int rocker_port_change_mtu(struct net_device *dev, int new_mtu)
int running = netif_running(dev);
int err;
-#define ROCKER_PORT_MIN_MTU 68
-#define ROCKER_PORT_MAX_MTU 9000
-
- if (new_mtu < ROCKER_PORT_MIN_MTU || new_mtu > ROCKER_PORT_MAX_MTU)
- return -EINVAL;
-
if (running)
rocker_port_stop(dev);
@@ -2171,28 +2166,70 @@ static const struct switchdev_ops rocker_port_switchdev_ops = {
.switchdev_port_obj_dump = rocker_port_obj_dump,
};
-static int rocker_router_fib_event(struct notifier_block *nb,
- unsigned long event, void *ptr)
+struct rocker_fib_event_work {
+ struct work_struct work;
+ struct fib_entry_notifier_info fen_info;
+ struct rocker *rocker;
+ unsigned long event;
+};
+
+static void rocker_router_fib_event_work(struct work_struct *work)
{
- struct rocker *rocker = container_of(nb, struct rocker, fib_nb);
- struct fib_entry_notifier_info *fen_info = ptr;
+ struct rocker_fib_event_work *fib_work =
+ container_of(work, struct rocker_fib_event_work, work);
+ struct rocker *rocker = fib_work->rocker;
int err;
- switch (event) {
+ /* Protect internal structures from changes */
+ rtnl_lock();
+ switch (fib_work->event) {
case FIB_EVENT_ENTRY_ADD:
- err = rocker_world_fib4_add(rocker, fen_info);
+ err = rocker_world_fib4_add(rocker, &fib_work->fen_info);
if (err)
rocker_world_fib4_abort(rocker);
- else
+ fib_info_put(fib_work->fen_info.fi);
break;
case FIB_EVENT_ENTRY_DEL:
- rocker_world_fib4_del(rocker, fen_info);
+ rocker_world_fib4_del(rocker, &fib_work->fen_info);
+ fib_info_put(fib_work->fen_info.fi);
break;
case FIB_EVENT_RULE_ADD: /* fall through */
case FIB_EVENT_RULE_DEL:
rocker_world_fib4_abort(rocker);
break;
}
+ rtnl_unlock();
+ kfree(fib_work);
+}
+
+/* Called with rcu_read_lock() */
+static int rocker_router_fib_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct rocker *rocker = container_of(nb, struct rocker, fib_nb);
+ struct rocker_fib_event_work *fib_work;
+
+ fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
+ if (WARN_ON(!fib_work))
+ return NOTIFY_BAD;
+
+ INIT_WORK(&fib_work->work, rocker_router_fib_event_work);
+ fib_work->rocker = rocker;
+ fib_work->event = event;
+
+ switch (event) {
+ case FIB_EVENT_ENTRY_ADD: /* fall through */
+ case FIB_EVENT_ENTRY_DEL:
+ memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info));
+ /* Take referece on fib_info to prevent it from being
+ * freed while work is queued. Release it afterwards.
+ */
+ fib_info_hold(fib_work->fen_info.fi);
+ break;
+ }
+
+ queue_work(rocker->rocker_owq, &fib_work->work);
+
return NOTIFY_DONE;
}
@@ -2536,9 +2573,11 @@ static void rocker_port_dev_addr_init(struct rocker_port *rocker_port)
}
}
+#define ROCKER_PORT_MIN_MTU ETH_MIN_MTU
+#define ROCKER_PORT_MAX_MTU 9000
static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
{
- const struct pci_dev *pdev = rocker->pdev;
+ struct pci_dev *pdev = rocker->pdev;
struct rocker_port *rocker_port;
struct net_device *dev;
int err;
@@ -2546,6 +2585,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
dev = alloc_etherdev(sizeof(struct rocker_port));
if (!dev)
return -ENOMEM;
+ SET_NETDEV_DEV(dev, &pdev->dev);
rocker_port = netdev_priv(dev);
rocker_port->dev = dev;
rocker_port->rocker = rocker;
@@ -2570,6 +2610,10 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG;
+ /* MTU range: 68 - 9000 */
+ dev->min_mtu = ROCKER_PORT_MIN_MTU;
+ dev->max_mtu = ROCKER_PORT_MAX_MTU;
+
err = rocker_world_port_pre_init(rocker_port);
if (err) {
dev_err(&pdev->dev, "port world pre-init failed\n");
@@ -2753,6 +2797,21 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_request_event_irq;
}
+ rocker->rocker_owq = alloc_ordered_workqueue(rocker_driver_name,
+ WQ_MEM_RECLAIM);
+ if (!rocker->rocker_owq) {
+ err = -ENOMEM;
+ goto err_alloc_ordered_workqueue;
+ }
+
+ /* Only FIBs pointing to our own netdevs are programmed into
+ * the device, so no need to pass a callback.
+ */
+ rocker->fib_nb.notifier_call = rocker_router_fib_event;
+ err = register_fib_notifier(&rocker->fib_nb, NULL);
+ if (err)
+ goto err_register_fib_notifier;
+
rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
err = rocker_probe_ports(rocker);
@@ -2761,15 +2820,16 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_probe_ports;
}
- rocker->fib_nb.notifier_call = rocker_router_fib_event;
- register_fib_notifier(&rocker->fib_nb);
-
dev_info(&pdev->dev, "Rocker switch with id %*phN\n",
(int)sizeof(rocker->hw.id), &rocker->hw.id);
return 0;
err_probe_ports:
+ unregister_fib_notifier(&rocker->fib_nb);
+err_register_fib_notifier:
+ destroy_workqueue(rocker->rocker_owq);
+err_alloc_ordered_workqueue:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
err_request_event_irq:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_CMD), rocker);
@@ -2795,9 +2855,10 @@ static void rocker_remove(struct pci_dev *pdev)
{
struct rocker *rocker = pci_get_drvdata(pdev);
+ rocker_remove_ports(rocker);
unregister_fib_notifier(&rocker->fib_nb);
rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
- rocker_remove_ports(rocker);
+ destroy_workqueue(rocker->rocker_owq);
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_CMD), rocker);
rocker_dma_rings_fini(rocker);
@@ -2839,20 +2900,37 @@ static bool rocker_port_dev_check_under(const struct net_device *dev,
return true;
}
+struct rocker_walk_data {
+ struct rocker *rocker;
+ struct rocker_port *port;
+};
+
+static int rocker_lower_dev_walk(struct net_device *lower_dev, void *_data)
+{
+ struct rocker_walk_data *data = _data;
+ int ret = 0;
+
+ if (rocker_port_dev_check_under(lower_dev, data->rocker)) {
+ data->port = netdev_priv(lower_dev);
+ ret = 1;
+ }
+
+ return ret;
+}
+
struct rocker_port *rocker_port_dev_lower_find(struct net_device *dev,
struct rocker *rocker)
{
- struct net_device *lower_dev;
- struct list_head *iter;
+ struct rocker_walk_data data;
if (rocker_port_dev_check_under(dev, rocker))
return netdev_priv(dev);
- netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
- if (rocker_port_dev_check_under(lower_dev, rocker))
- return netdev_priv(lower_dev);
- }
- return NULL;
+ data.rocker = rocker;
+ data.port = NULL;
+ netdev_walk_all_lower_dev(dev, rocker_lower_dev_walk, &data);
+
+ return data.port;
}
static int rocker_netdevice_event(struct notifier_block *unused,
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 4ca461322d60..7cd76b6b5cb9 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -2516,6 +2516,7 @@ static void ofdpa_fini(struct rocker *rocker)
int bkt;
del_timer_sync(&ofdpa->fdb_cleanup_timer);
+ flush_workqueue(rocker->rocker_owq);
spin_lock_irqsave(&ofdpa->flow_tbl_lock, flags);
hash_for_each_safe(ofdpa->flow_tbl, bkt, tmp, flow_entry, entry)
diff --git a/drivers/net/ethernet/samsung/Kconfig b/drivers/net/ethernet/samsung/Kconfig
index 2360d8150777..fbd5e06654c6 100644
--- a/drivers/net/ethernet/samsung/Kconfig
+++ b/drivers/net/ethernet/samsung/Kconfig
@@ -21,7 +21,7 @@ config SXGBE_ETH
depends on HAS_IOMEM && HAS_DMA
select PHYLIB
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This is the driver for the SXGBE 10G Ethernet IP block found on
Samsung platforms.
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 5cb51b609f02..c61f260e18a4 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -384,7 +384,6 @@ struct sxgbe_tx_queue {
dma_addr_t *tx_skbuff_dma;
struct sk_buff **tx_skbuff;
struct timer_list txtimer;
- spinlock_t tx_lock; /* lock for tx queues */
unsigned int cur_tx;
unsigned int dirty_tx;
u32 tx_count_frames;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index ea44a2456ce1..cddcff5a00a7 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -426,9 +426,6 @@ static int init_tx_ring(struct device *dev, u8 queue_no,
tx_ring->dirty_tx = 0;
tx_ring->cur_tx = 0;
- /* initialise TX queue lock */
- spin_lock_init(&tx_ring->tx_lock);
-
return 0;
dmamem_err:
@@ -743,7 +740,7 @@ static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue *tqueue)
dev_txq = netdev_get_tx_queue(priv->dev, queue_no);
- spin_lock(&tqueue->tx_lock);
+ __netif_tx_lock(dev_txq, smp_processor_id());
priv->xstats.tx_clean++;
while (tqueue->dirty_tx != tqueue->cur_tx) {
@@ -781,18 +778,13 @@ static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue *tqueue)
/* wake up queue */
if (unlikely(netif_tx_queue_stopped(dev_txq) &&
- sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv))) {
- netif_tx_lock(priv->dev);
- if (netif_tx_queue_stopped(dev_txq) &&
- sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv)) {
- if (netif_msg_tx_done(priv))
- pr_debug("%s: restart transmit\n", __func__);
- netif_tx_wake_queue(dev_txq);
- }
- netif_tx_unlock(priv->dev);
+ sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv))) {
+ if (netif_msg_tx_done(priv))
+ pr_debug("%s: restart transmit\n", __func__);
+ netif_tx_wake_queue(dev_txq);
}
- spin_unlock(&tqueue->tx_lock);
+ __netif_tx_unlock(dev_txq);
}
/**
@@ -1304,9 +1296,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
tqueue->hwts_tx_en)))
ctxt_desc_req = 1;
- /* get the spinlock */
- spin_lock(&tqueue->tx_lock);
-
if (priv->tx_path_in_lpi_mode)
sxgbe_disable_eee_mode(priv);
@@ -1316,8 +1305,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_err(dev, "%s: Tx Ring is full when %d queue is awake\n",
__func__, txq_index);
}
- /* release the spin lock in case of BUSY */
- spin_unlock(&tqueue->tx_lock);
return NETDEV_TX_BUSY;
}
@@ -1436,8 +1423,6 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->dma->enable_dma_transmission(priv->ioaddr, txq_index);
- spin_unlock(&tqueue->tx_lock);
-
return NETDEV_TX_OK;
}
@@ -1820,19 +1805,6 @@ static int sxgbe_set_features(struct net_device *dev,
*/
static int sxgbe_change_mtu(struct net_device *dev, int new_mtu)
{
- /* RFC 791, page 25, "Every internet module must be able to forward
- * a datagram of 68 octets without further fragmentation."
- */
- if (new_mtu < MIN_MTU || (new_mtu > MAX_MTU)) {
- netdev_err(dev, "invalid MTU, MTU should be in between %d and %d\n",
- MIN_MTU, MAX_MTU);
- return -EINVAL;
- }
-
- /* Return if the buffer sizes will not change */
- if (dev->mtu == new_mtu)
- return 0;
-
dev->mtu = new_mtu;
if (!netif_running(dev))
@@ -2144,6 +2116,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
/* assign filtering support */
ndev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 68 - 9000 */
+ ndev->min_mtu = MIN_MTU;
+ ndev->max_mtu = MAX_MTU;
+
priv->msg_enable = netif_msg_init(debug, default_msg_level);
/* Enable TCP segmentation offload for all DMA channels */
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index bdac936a68bc..244c1e171017 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -745,7 +745,6 @@ static const struct net_device_ops ether3_netdev_ops = {
.ndo_set_rx_mode = ether3_setmulticastlist,
.ndo_tx_timeout = ether3_timeout,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index c2bd5378ffda..ed34196028b8 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -714,7 +714,6 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
.ndo_tx_timeout = timeout,
.ndo_set_rx_mode = sgiseeq_set_multicast,
.ndo_set_mac_address = sgiseeq_set_mac_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 4dd92b7b80f4..46f7be85f5a3 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -1,20 +1,19 @@
config SFC
- tristate "Solarflare SFC4000/SFC9000/SFC9100-family support"
+ tristate "Solarflare SFC9000/SFC9100-family support"
depends on PCI
select MDIO
select CRC32
select I2C
select I2C_ALGOBIT
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports 10/40-gigabit Ethernet cards based on
- the Solarflare SFC4000, SFC9000-family and SFC9100-family
- controllers.
+ the Solarflare SFC9000-family and SFC9100-family controllers.
To compile this driver as a module, choose M here. The module
will be called sfc.
config SFC_MTD
- bool "Solarflare SFC4000/SFC9000/SFC9100-family MTD support"
+ bool "Solarflare SFC9000/SFC9100-family MTD support"
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
---help---
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index ce8470fe79d5..520cfcc17785 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -1,7 +1,6 @@
-sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \
- rx.o selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
- tenxpress.o txc43128_phy.o falcon_boards.o \
- mcdi.o mcdi_port.o mcdi_mon.o ptp.o
+sfc-y += efx.o nic.o farch.o siena.o ef10.o tx.o rx.o \
+ selftest.o ethtool.o ptp.o tx_tso.o \
+ mcdi.o mcdi_port.o mcdi_mon.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o ef10_sriov.o
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 00279da6a1e8..de2947ccc5ad 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -2086,6 +2086,92 @@ static inline void efx_ef10_push_tx_desc(struct efx_tx_queue *tx_queue,
ER_DZ_TX_DESC_UPD, tx_queue->queue);
}
+/* Add Firmware-Assisted TSO v2 option descriptors to a queue.
+ */
+static int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb,
+ bool *data_mapped)
+{
+ struct efx_tx_buffer *buffer;
+ struct tcphdr *tcp;
+ struct iphdr *ip;
+
+ u16 ipv4_id;
+ u32 seqnum;
+ u32 mss;
+
+ EFX_WARN_ON_ONCE_PARANOID(tx_queue->tso_version != 2);
+
+ mss = skb_shinfo(skb)->gso_size;
+
+ if (unlikely(mss < 4)) {
+ WARN_ONCE(1, "MSS of %u is too small for TSO v2\n", mss);
+ return -EINVAL;
+ }
+
+ ip = ip_hdr(skb);
+ if (ip->version == 4) {
+ /* Modify IPv4 header if needed. */
+ ip->tot_len = 0;
+ ip->check = 0;
+ ipv4_id = ip->id;
+ } else {
+ /* Modify IPv6 header if needed. */
+ struct ipv6hdr *ipv6 = ipv6_hdr(skb);
+
+ ipv6->payload_len = 0;
+ ipv4_id = 0;
+ }
+
+ tcp = tcp_hdr(skb);
+ seqnum = ntohl(tcp->seq);
+
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+
+ buffer->flags = EFX_TX_BUF_OPTION;
+ buffer->len = 0;
+ buffer->unmap_len = 0;
+ EFX_POPULATE_QWORD_5(buffer->option,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_OPTION_TYPE,
+ ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
+ ESF_DZ_TX_TSO_IP_ID, ipv4_id,
+ ESF_DZ_TX_TSO_TCP_SEQNO, seqnum
+ );
+ ++tx_queue->insert_count;
+
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+
+ buffer->flags = EFX_TX_BUF_OPTION;
+ buffer->len = 0;
+ buffer->unmap_len = 0;
+ EFX_POPULATE_QWORD_4(buffer->option,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_OPTION_TYPE,
+ ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
+ ESF_DZ_TX_TSO_TCP_MSS, mss
+ );
+ ++tx_queue->insert_count;
+
+ return 0;
+}
+
+static u32 efx_ef10_tso_versions(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ u32 tso_versions = 0;
+
+ if (nic_data->datapath_caps &
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))
+ tso_versions |= BIT(1);
+ if (nic_data->datapath_caps2 &
+ (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN))
+ tso_versions |= BIT(2);
+ return tso_versions;
+}
+
static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_TXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
@@ -2095,6 +2181,7 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
struct efx_channel *channel = tx_queue->channel;
struct efx_nic *efx = tx_queue->efx;
struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ bool tso_v2 = false;
size_t inlen;
dma_addr_t dma_addr;
efx_qword_t *txd;
@@ -2102,13 +2189,21 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
int i;
BUILD_BUG_ON(MC_CMD_INIT_TXQ_OUT_LEN != 0);
+ /* TSOv2 is a limited resource that can only be configured on a limited
+ * number of queues. TSO without checksum offload is not really a thing,
+ * so we only enable it for those queues.
+ */
+ if (csum_offload && (nic_data->datapath_caps2 &
+ (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN))) {
+ tso_v2 = true;
+ netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
+ channel->channel);
+ }
+
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_SIZE, tx_queue->ptr_mask + 1);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_TARGET_EVQ, channel->channel);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_LABEL, tx_queue->queue);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_INSTANCE, tx_queue->queue);
- MCDI_POPULATE_DWORD_2(inbuf, INIT_TXQ_IN_FLAGS,
- INIT_TXQ_IN_FLAG_IP_CSUM_DIS, !csum_offload,
- INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_OWNER_ID, 0);
MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_PORT_ID, nic_data->vport_id);
@@ -2124,10 +2219,30 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
inlen = MC_CMD_INIT_TXQ_IN_LEN(entries);
- rc = efx_mcdi_rpc(efx, MC_CMD_INIT_TXQ, inbuf, inlen,
- NULL, 0, NULL);
- if (rc)
- goto fail;
+ do {
+ MCDI_POPULATE_DWORD_3(inbuf, INIT_TXQ_IN_FLAGS,
+ /* This flag was removed from mcdi_pcol.h for
+ * the non-_EXT version of INIT_TXQ. However,
+ * firmware still honours it.
+ */
+ INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, tso_v2,
+ INIT_TXQ_IN_FLAG_IP_CSUM_DIS, !csum_offload,
+ INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload);
+
+ rc = efx_mcdi_rpc_quiet(efx, MC_CMD_INIT_TXQ, inbuf, inlen,
+ NULL, 0, NULL);
+ if (rc == -ENOSPC && tso_v2) {
+ /* Retry without TSOv2 if we're short on contexts. */
+ tso_v2 = false;
+ netif_warn(efx, probe, efx->net_dev,
+ "TSOv2 context not available to segment in hardware. TCP performance may be reduced.\n");
+ } else if (rc) {
+ efx_mcdi_display_error(efx, MC_CMD_INIT_TXQ,
+ MC_CMD_INIT_TXQ_EXT_IN_LEN,
+ NULL, 0, rc);
+ goto fail;
+ }
+ } while (rc);
/* A previous user of this TX queue might have set us up the
* bomb by writing a descriptor to the TX push collector but
@@ -2146,8 +2261,11 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
ESF_DZ_TX_OPTION_IP_CSUM, csum_offload);
tx_queue->write_count = 1;
- if (nic_data->datapath_caps &
- (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN)) {
+ if (tso_v2) {
+ tx_queue->handle_tso = efx_ef10_tx_tso_desc;
+ tx_queue->tso_version = 2;
+ } else if (nic_data->datapath_caps &
+ (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN)) {
tx_queue->tso_version = 1;
}
@@ -2202,6 +2320,25 @@ static inline void efx_ef10_notify_tx_desc(struct efx_tx_queue *tx_queue)
ER_DZ_TX_DESC_UPD_DWORD, tx_queue->queue);
}
+#define EFX_EF10_MAX_TX_DESCRIPTOR_LEN 0x3fff
+
+static unsigned int efx_ef10_tx_limit_len(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len)
+{
+ if (len > EFX_EF10_MAX_TX_DESCRIPTOR_LEN) {
+ /* If we need to break across multiple descriptors we should
+ * stop at a page boundary. This assumes the length limit is
+ * greater than the page size.
+ */
+ dma_addr_t end = dma_addr + EFX_EF10_MAX_TX_DESCRIPTOR_LEN;
+
+ BUILD_BUG_ON(EFX_EF10_MAX_TX_DESCRIPTOR_LEN < EFX_PAGE_SIZE);
+ len = (end & (~(EFX_PAGE_SIZE - 1))) - dma_addr;
+ }
+
+ return len;
+}
+
static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
{
unsigned int old_write_count = tx_queue->write_count;
@@ -2245,6 +2382,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
}
}
+#define RSS_MODE_HASH_ADDRS (1 << RSS_MODE_HASH_SRC_ADDR_LBN |\
+ 1 << RSS_MODE_HASH_DST_ADDR_LBN)
+#define RSS_MODE_HASH_PORTS (1 << RSS_MODE_HASH_SRC_PORT_LBN |\
+ 1 << RSS_MODE_HASH_DST_PORT_LBN)
+#define RSS_CONTEXT_FLAGS_DEFAULT (1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_IPV4_EN_LBN |\
+ 1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_TCPV4_EN_LBN |\
+ 1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_IPV6_EN_LBN |\
+ 1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_TCPV6_EN_LBN |\
+ (RSS_MODE_HASH_ADDRS | RSS_MODE_HASH_PORTS) << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TCP_IPV4_RSS_MODE_LBN |\
+ RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV4_RSS_MODE_LBN |\
+ RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_OTHER_IPV4_RSS_MODE_LBN |\
+ (RSS_MODE_HASH_ADDRS | RSS_MODE_HASH_PORTS) << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TCP_IPV6_RSS_MODE_LBN |\
+ RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV6_RSS_MODE_LBN |\
+ RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_OTHER_IPV6_RSS_MODE_LBN)
+
+static int efx_ef10_get_rss_flags(struct efx_nic *efx, u32 context, u32 *flags)
+{
+ /* Firmware had a bug (sfc bug 61952) where it would not actually
+ * fill in the flags field in the response to MC_CMD_RSS_CONTEXT_GET_FLAGS.
+ * This meant that it would always contain whatever was previously
+ * in the MCDI buffer. Fortunately, all firmware versions with
+ * this bug have the same default flags value for a newly-allocated
+ * RSS context, and the only time we want to get the flags is just
+ * after allocating. Moreover, the response has a 32-bit hole
+ * where the context ID would be in the request, so we can use an
+ * overlength buffer in the request and pre-fill the flags field
+ * with what we believe the default to be. Thus if the firmware
+ * has the bug, it will leave our pre-filled value in the flags
+ * field of the response, and we will get the right answer.
+ *
+ * However, this does mean that this function should NOT be used if
+ * the RSS context flags might not be their defaults - it is ONLY
+ * reliably correct for a newly-allocated RSS context.
+ */
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN);
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN);
+ size_t outlen;
+ int rc;
+
+ /* Check we have a hole for the context ID */
+ BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_GET_FLAGS_IN_LEN != MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_FLAGS_OFST);
+ MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_FLAGS_IN_RSS_CONTEXT_ID, context);
+ MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_FLAGS_OUT_FLAGS,
+ RSS_CONTEXT_FLAGS_DEFAULT);
+ rc = efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_GET_FLAGS, inbuf,
+ sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+ if (rc == 0) {
+ if (outlen < MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN)
+ rc = -EIO;
+ else
+ *flags = MCDI_DWORD(outbuf, RSS_CONTEXT_GET_FLAGS_OUT_FLAGS);
+ }
+ return rc;
+}
+
+/* Attempt to enable 4-tuple UDP hashing on the specified RSS context.
+ * If we fail, we just leave the RSS context at its default hash settings,
+ * which is safe but may slightly reduce performance.
+ * Defaults are 4-tuple for TCP and 2-tuple for UDP and other-IP, so we
+ * just need to set the UDP ports flags (for both IP versions).
+ */
+static void efx_ef10_set_rss_flags(struct efx_nic *efx, u32 context)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN);
+ u32 flags;
+
+ BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN != 0);
+
+ if (efx_ef10_get_rss_flags(efx, context, &flags) != 0)
+ return;
+ MCDI_SET_DWORD(inbuf, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID, context);
+ flags |= RSS_MODE_HASH_PORTS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV4_RSS_MODE_LBN;
+ flags |= RSS_MODE_HASH_PORTS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV6_RSS_MODE_LBN;
+ MCDI_SET_DWORD(inbuf, RSS_CONTEXT_SET_FLAGS_IN_FLAGS, flags);
+ if (!efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_SET_FLAGS, inbuf, sizeof(inbuf),
+ NULL, 0, NULL))
+ /* Succeeded, so UDP 4-tuple is now enabled */
+ efx->rx_hash_udp_4tuple = true;
+}
+
static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context,
bool exclusive, unsigned *context_size)
{
@@ -2290,6 +2507,10 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context,
if (context_size)
*context_size = rss_spread;
+ if (nic_data->datapath_caps &
+ 1 << MC_CMD_GET_CAPABILITIES_OUT_ADDITIONAL_RSS_MODES_LBN)
+ efx_ef10_set_rss_flags(efx, *context);
+
return 0;
}
@@ -5385,6 +5606,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.tx_init = efx_ef10_tx_init,
.tx_remove = efx_ef10_tx_remove,
.tx_write = efx_ef10_tx_write,
+ .tx_limit_len = efx_ef10_tx_limit_len,
.rx_push_rss_config = efx_ef10_vf_rx_push_rss_config,
.rx_probe = efx_ef10_rx_probe,
.rx_init = efx_ef10_rx_init,
@@ -5491,6 +5713,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.tx_init = efx_ef10_tx_init,
.tx_remove = efx_ef10_tx_remove,
.tx_write = efx_ef10_tx_write,
+ .tx_limit_len = efx_ef10_tx_limit_len,
.rx_push_rss_config = efx_ef10_pf_rx_push_rss_config,
.rx_probe = efx_ef10_rx_probe,
.rx_init = efx_ef10_rx_init,
@@ -5550,6 +5773,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
#endif
.get_mac_address = efx_ef10_get_mac_address_pf,
.set_mac_address = efx_ef10_set_mac_address,
+ .tso_versions = efx_ef10_tso_versions,
.revision = EFX_REV_HUNT_A0,
.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
diff --git a/drivers/net/ethernet/sfc/ef10_regs.h b/drivers/net/ethernet/sfc/ef10_regs.h
index 62a55dde61d5..2c4bf9476c37 100644
--- a/drivers/net/ethernet/sfc/ef10_regs.h
+++ b/drivers/net/ethernet/sfc/ef10_regs.h
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare network controllers and boards
- * Copyright 2012-2013 Solarflare Communications Inc.
+ * Copyright 2012-2015 Solarflare 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 as published
@@ -147,8 +147,14 @@
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_RX_DROP_EVENT_LBN 58
#define ESF_DZ_RX_DROP_EVENT_WIDTH 1
-#define ESF_DZ_RX_EV_RSVD2_LBN 54
-#define ESF_DZ_RX_EV_RSVD2_WIDTH 4
+#define ESF_DD_RX_EV_RSVD2_LBN 54
+#define ESF_DD_RX_EV_RSVD2_WIDTH 4
+#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
+#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_LBN 56
+#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_RX_EV_RSVD2_LBN 54
+#define ESF_EZ_RX_EV_RSVD2_WIDTH 2
#define ESF_DZ_RX_EV_SOFT2_LBN 52
#define ESF_DZ_RX_EV_SOFT2_WIDTH 2
#define ESF_DZ_RX_DSC_PTR_LBITS_LBN 48
@@ -192,12 +198,21 @@
#define ESF_DZ_RX_MAC_CLASS_WIDTH 1
#define ESE_DZ_MAC_CLASS_MCAST 1
#define ESE_DZ_MAC_CLASS_UCAST 0
-#define ESF_DZ_RX_EV_SOFT1_LBN 32
-#define ESF_DZ_RX_EV_SOFT1_WIDTH 3
-#define ESF_DZ_RX_EV_RSVD1_LBN 31
-#define ESF_DZ_RX_EV_RSVD1_WIDTH 1
-#define ESF_DZ_RX_ABORT_LBN 30
-#define ESF_DZ_RX_ABORT_WIDTH 1
+#define ESF_DD_RX_EV_SOFT1_LBN 32
+#define ESF_DD_RX_EV_SOFT1_WIDTH 3
+#define ESF_EZ_RX_EV_SOFT1_LBN 34
+#define ESF_EZ_RX_EV_SOFT1_WIDTH 1
+#define ESF_EZ_RX_ENCAP_HDR_LBN 32
+#define ESF_EZ_RX_ENCAP_HDR_WIDTH 2
+#define ESE_EZ_ENCAP_HDR_GRE 2
+#define ESE_EZ_ENCAP_HDR_VXLAN 1
+#define ESE_EZ_ENCAP_HDR_NONE 0
+#define ESF_DD_RX_EV_RSVD1_LBN 30
+#define ESF_DD_RX_EV_RSVD1_WIDTH 2
+#define ESF_EZ_RX_EV_RSVD1_LBN 31
+#define ESF_EZ_RX_EV_RSVD1_WIDTH 1
+#define ESF_EZ_RX_ABORT_LBN 30
+#define ESF_EZ_RX_ABORT_WIDTH 1
#define ESF_DZ_RX_ECC_ERR_LBN 29
#define ESF_DZ_RX_ECC_ERR_WIDTH 1
#define ESF_DZ_RX_CRC1_ERR_LBN 28
@@ -235,6 +250,12 @@
#define ESE_DZ_TX_OPTION_DESC_TSO 7
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
+#define ESF_DZ_TX_OPTION_TS_AT_TXDP_LBN 8
+#define ESF_DZ_TX_OPTION_TS_AT_TXDP_WIDTH 1
+#define ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM_LBN 7
+#define ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM_WIDTH 1
+#define ESF_DZ_TX_OPTION_INNER_IP_CSUM_LBN 6
+#define ESF_DZ_TX_OPTION_INNER_IP_CSUM_WIDTH 1
#define ESF_DZ_TX_TIMESTAMP_LBN 5
#define ESF_DZ_TX_TIMESTAMP_WIDTH 1
#define ESF_DZ_TX_OPTION_CRC_MODE_LBN 2
@@ -257,14 +278,22 @@
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_TX_DROP_EVENT_LBN 58
#define ESF_DZ_TX_DROP_EVENT_WIDTH 1
-#define ESF_DZ_TX_EV_RSVD_LBN 48
-#define ESF_DZ_TX_EV_RSVD_WIDTH 10
+#define ESF_DD_TX_EV_RSVD_LBN 48
+#define ESF_DD_TX_EV_RSVD_WIDTH 10
+#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
+#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_IP_INNER_CHKSUM_ERR_LBN 56
+#define ESF_EZ_IP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_TX_EV_RSVD_LBN 48
+#define ESF_EZ_TX_EV_RSVD_WIDTH 8
#define ESF_DZ_TX_SOFT2_LBN 32
#define ESF_DZ_TX_SOFT2_WIDTH 16
-#define ESF_DZ_TX_CAN_MERGE_LBN 31
-#define ESF_DZ_TX_CAN_MERGE_WIDTH 1
-#define ESF_DZ_TX_SOFT1_LBN 24
-#define ESF_DZ_TX_SOFT1_WIDTH 7
+#define ESF_DD_TX_SOFT1_LBN 24
+#define ESF_DD_TX_SOFT1_WIDTH 8
+#define ESF_EZ_TX_CAN_MERGE_LBN 31
+#define ESF_EZ_TX_CAN_MERGE_WIDTH 1
+#define ESF_EZ_TX_SOFT1_LBN 24
+#define ESF_EZ_TX_SOFT1_WIDTH 7
#define ESF_DZ_TX_QLABEL_LBN 16
#define ESF_DZ_TX_QLABEL_WIDTH 5
#define ESF_DZ_TX_DESCR_INDX_LBN 0
@@ -301,6 +330,10 @@
#define ESE_DZ_TX_OPTION_DESC_TSO 7
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
+#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
+#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
+#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
+#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
#define ESF_DZ_TX_TSO_TCP_FLAGS_LBN 48
#define ESF_DZ_TX_TSO_TCP_FLAGS_WIDTH 8
#define ESF_DZ_TX_TSO_IP_ID_LBN 32
@@ -308,6 +341,46 @@
#define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
#define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
+/* TX_TSO_FATSO2A_DESC */
+#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
+#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
+#define ESF_DZ_TX_OPTION_TYPE_LBN 60
+#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
+#define ESE_DZ_TX_OPTION_DESC_TSO 7
+#define ESE_DZ_TX_OPTION_DESC_VLAN 6
+#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
+#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
+#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
+#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B 3
+#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A 2
+#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
+#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
+#define ESF_DZ_TX_TSO_IP_ID_LBN 32
+#define ESF_DZ_TX_TSO_IP_ID_WIDTH 16
+#define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
+#define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
+
+
+/* TX_TSO_FATSO2B_DESC */
+#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
+#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
+#define ESF_DZ_TX_OPTION_TYPE_LBN 60
+#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
+#define ESE_DZ_TX_OPTION_DESC_TSO 7
+#define ESE_DZ_TX_OPTION_DESC_VLAN 6
+#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
+#define ESF_DZ_TX_TSO_OPTION_TYPE_LBN 56
+#define ESF_DZ_TX_TSO_OPTION_TYPE_WIDTH 4
+#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B 3
+#define ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A 2
+#define ESE_DZ_TX_TSO_OPTION_DESC_ENCAP 1
+#define ESE_DZ_TX_TSO_OPTION_DESC_NORMAL 0
+#define ESF_DZ_TX_TSO_OUTER_IP_ID_LBN 0
+#define ESF_DZ_TX_TSO_OUTER_IP_ID_WIDTH 16
+#define ESF_DZ_TX_TSO_TCP_MSS_LBN 32
+#define ESF_DZ_TX_TSO_TCP_MSS_WIDTH 16
+
+
/*************************************************************************/
/* TX_DESC_UPD_REG: Transmit descriptor update register.
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 6b89e4a7b164..5a5dcad8c49a 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -82,7 +82,6 @@ const char *const efx_reset_type_names[] = {
[RESET_TYPE_DISABLE] = "DISABLE",
[RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG",
[RESET_TYPE_INT_ERROR] = "INT_ERROR",
- [RESET_TYPE_RX_RECOVERY] = "RX_RECOVERY",
[RESET_TYPE_DMA_ERROR] = "DMA_ERROR",
[RESET_TYPE_TX_SKIP] = "TX_SKIP",
[RESET_TYPE_MC_FAILURE] = "MC_FAILURE",
@@ -356,7 +355,7 @@ static int efx_probe_eventq(struct efx_channel *channel)
/* Build an event queue with room for one event per tx and rx buffer,
* plus some extra for link state events and MCDI completions. */
entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
- EFX_BUG_ON_PARANOID(entries > EFX_MAX_EVQ_SIZE);
+ EFX_WARN_ON_PARANOID(entries > EFX_MAX_EVQ_SIZE);
channel->eventq_mask = max(entries, EFX_MIN_EVQ_SIZE) - 1;
return efx_nic_probe_eventq(channel);
@@ -733,16 +732,7 @@ static void efx_stop_datapath(struct efx_nic *efx)
}
rc = efx->type->fini_dmaq(efx);
- if (rc && EFX_WORKAROUND_7803(efx)) {
- /* Schedule a reset to recover from the flush failure. The
- * descriptor caches reference memory we're about to free,
- * but falcon_reconfigure_mac_wrapper() won't reconnect
- * the MACs because of the pending reset.
- */
- netif_err(efx, drv, efx->net_dev,
- "Resetting to recover from flush failure\n");
- efx_schedule_reset(efx, RESET_TYPE_ALL);
- } else if (rc) {
+ if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
} else {
netif_dbg(efx, drv, efx->net_dev,
@@ -1892,15 +1882,13 @@ static void efx_start_all(struct efx_nic *efx)
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);
- /* If link state detection is normally event-driven, we have
+ /* Link state detection is normally event-driven; we have
* to poll now because we could have missed a change
*/
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
- mutex_lock(&efx->mac_lock);
- if (efx->phy_op->poll(efx))
- efx_link_status_changed(efx);
- mutex_unlock(&efx->mac_lock);
- }
+ mutex_lock(&efx->mac_lock);
+ if (efx->phy_op->poll(efx))
+ efx_link_status_changed(efx);
+ mutex_unlock(&efx->mac_lock);
efx->type->start_stats(efx);
efx->type->pull_stats(efx);
@@ -2113,10 +2101,9 @@ static void efx_init_napi(struct efx_nic *efx)
static void efx_fini_napi_channel(struct efx_channel *channel)
{
- if (channel->napi_dev) {
+ if (channel->napi_dev)
netif_napi_del(&channel->napi_str);
- napi_hash_del(&channel->napi_str);
- }
+
channel->napi_dev = NULL;
}
@@ -2266,18 +2253,6 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
rc = efx_check_disabled(efx);
if (rc)
return rc;
- if (new_mtu > EFX_MAX_MTU) {
- netif_err(efx, drv, efx->net_dev,
- "Requested MTU of %d too big (max: %d)\n",
- new_mtu, EFX_MAX_MTU);
- return -EINVAL;
- }
- if (new_mtu < EFX_MIN_MTU) {
- netif_err(efx, drv, efx->net_dev,
- "Requested MTU of %d too small (min: %d)\n",
- new_mtu, EFX_MIN_MTU);
- return -EINVAL;
- }
netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
@@ -2481,6 +2456,8 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->priv_flags |= IFF_UNICAST_FLT;
net_dev->ethtool_ops = &efx_ethtool_ops;
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
+ net_dev->min_mtu = EFX_MIN_MTU;
+ net_dev->max_mtu = EFX_MAX_MTU;
rtnl_lock();
@@ -2853,12 +2830,6 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
/* PCI device ID table */
static const struct pci_device_id efx_pci_table[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
- PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
- .driver_data = (unsigned long) &falcon_a1_nic_type},
- {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
- PCI_DEVICE_ID_SOLARFLARE_SFC4000B),
- .driver_data = (unsigned long) &falcon_b0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0803), /* SFC9020 */
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0813), /* SFL9021 */
@@ -3211,23 +3182,6 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
efx = netdev_priv(net_dev);
efx->type = (const struct efx_nic_type *) entry->driver_data;
efx->fixed_features |= NETIF_F_HIGHDMA;
- net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
- NETIF_F_TSO | NETIF_F_RXCSUM);
- if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
- net_dev->features |= NETIF_F_TSO6;
- /* Mask for features that also apply to VLAN devices */
- net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG |
- NETIF_F_HIGHDMA | NETIF_F_ALL_TSO |
- NETIF_F_RXCSUM);
-
- net_dev->hw_features = net_dev->features & ~efx->fixed_features;
-
- /* Disable VLAN filtering by default. It may be enforced if
- * the feature is fixed (i.e. VLAN filters are required to
- * receive VLAN tagged packets due to vPort restrictions).
- */
- net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
- net_dev->features |= efx->fixed_features;
pci_set_drvdata(pci_dev, efx);
SET_NETDEV_DEV(net_dev, &pci_dev->dev);
@@ -3250,6 +3204,27 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto fail3;
+ net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_RXCSUM);
+ if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
+ net_dev->features |= NETIF_F_TSO6;
+ /* Check whether device supports TSO */
+ if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
+ net_dev->features &= ~NETIF_F_ALL_TSO;
+ /* Mask for features that also apply to VLAN devices */
+ net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG |
+ NETIF_F_HIGHDMA | NETIF_F_ALL_TSO |
+ NETIF_F_RXCSUM);
+
+ net_dev->hw_features = net_dev->features & ~efx->fixed_features;
+
+ /* Disable VLAN filtering by default. It may be enforced if
+ * the feature is fixed (i.e. VLAN filters are required to
+ * receive VLAN tagged packets due to vPort restrictions).
+ */
+ net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+ net_dev->features |= efx->fixed_features;
+
rc = efx_register_netdev(efx);
if (rc)
goto fail4;
diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h
index c94f56271dd4..6fa824211d91 100644
--- a/drivers/net/ethernet/sfc/enum.h
+++ b/drivers/net/ethernet/sfc/enum.h
@@ -148,7 +148,6 @@ enum efx_loopback_mode {
* @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
* @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
* @RESET_TYPE_INT_ERROR: reset due to internal error
- * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
* @RESET_TYPE_DMA_ERROR: DMA error
* @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
* @RESET_TYPE_MC_FAILURE: MC reboot/assertion
@@ -166,15 +165,13 @@ enum reset_type {
RESET_TYPE_MAX_METHOD,
RESET_TYPE_TX_WATCHDOG,
RESET_TYPE_INT_ERROR,
- RESET_TYPE_RX_RECOVERY,
RESET_TYPE_DMA_ERROR,
RESET_TYPE_TX_SKIP,
RESET_TYPE_MC_FAILURE,
/* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but
* it doesn't fit the scope hierarchy (not well-ordered by inclusion).
* We encode this by having its enum value be greater than
- * RESET_TYPE_MAX_METHOD. This also prevents issuing it with
- * efx_ioctl_reset.
+ * RESET_TYPE_MAX_METHOD.
*/
RESET_TYPE_MCDI_TIMEOUT,
RESET_TYPE_MAX,
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 445ccdb6bc67..f644216eda1b 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -69,8 +69,10 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
+ EFX_ETHTOOL_UINT_TXQ_STAT(tso_fallbacks),
EFX_ETHTOOL_UINT_TXQ_STAT(pushes),
EFX_ETHTOOL_UINT_TXQ_STAT(pio_packets),
+ EFX_ETHTOOL_UINT_TXQ_STAT(cb_packets),
EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
@@ -167,9 +169,8 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
- efx_mcdi_print_fwver(efx, info->fw_version,
- sizeof(info->fw_version));
+ efx_mcdi_print_fwver(efx, info->fw_version,
+ sizeof(info->fw_version));
strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
}
@@ -332,12 +333,12 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
"core", 0, "registers", NULL);
if (efx->phy_op->run_tests != NULL) {
- EFX_BUG_ON_PARANOID(efx->phy_op->test_name == NULL);
+ EFX_WARN_ON_PARANOID(efx->phy_op->test_name == NULL);
for (i = 0; true; ++i) {
const char *name;
- EFX_BUG_ON_PARANOID(i >= EFX_MAX_PHY_TESTS);
+ EFX_WARN_ON_PARANOID(i >= EFX_MAX_PHY_TESTS);
name = efx->phy_op->test_name(efx, i);
if (name == NULL)
break;
@@ -964,35 +965,33 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
return 0;
case ETHTOOL_GRXFH: {
- unsigned min_revision = 0;
-
info->data = 0;
switch (info->flow_type) {
+ case UDP_V4_FLOW:
+ if (efx->rx_hash_udp_4tuple)
+ /* fall through */
case TCP_V4_FLOW:
- info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */
- case UDP_V4_FLOW:
case SCTP_V4_FLOW:
case AH_ESP_V4_FLOW:
case IPV4_FLOW:
info->data |= RXH_IP_SRC | RXH_IP_DST;
- min_revision = EFX_REV_FALCON_B0;
break;
+ case UDP_V6_FLOW:
+ if (efx->rx_hash_udp_4tuple)
+ /* fall through */
case TCP_V6_FLOW:
- info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */
- case UDP_V6_FLOW:
case SCTP_V6_FLOW:
case AH_ESP_V6_FLOW:
case IPV6_FLOW:
info->data |= RXH_IP_SRC | RXH_IP_DST;
- min_revision = EFX_REV_SIENA_A0;
break;
default:
break;
}
- if (efx_nic_rev(efx) < min_revision)
- info->data = 0;
return 0;
}
@@ -1265,9 +1264,7 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
- return ((efx_nic_rev(efx) < EFX_REV_FALCON_B0 ||
- efx->n_rx_channels == 1) ?
- 0 : ARRAY_SIZE(efx->rx_indir_table));
+ return (efx->n_rx_channels == 1) ? 0 : ARRAY_SIZE(efx->rx_indir_table);
}
static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key,
diff --git a/drivers/net/ethernet/sfc/falcon/Kconfig b/drivers/net/ethernet/sfc/falcon/Kconfig
new file mode 100644
index 000000000000..6248e96253a2
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/Kconfig
@@ -0,0 +1,21 @@
+config SFC_FALCON
+ tristate "Solarflare SFC4000 support"
+ depends on PCI
+ select MDIO
+ select CRC32
+ select I2C
+ select I2C_ALGOBIT
+ ---help---
+ This driver supports 10-gigabit Ethernet cards based on
+ the Solarflare SFC4000 controller.
+
+ To compile this driver as a module, choose M here. The module
+ will be called sfc-falcon.
+config SFC_FALCON_MTD
+ bool "Solarflare SFC4000 MTD support"
+ depends on SFC_FALCON && MTD && !(SFC_FALCON=y && MTD=m)
+ default y
+ ---help---
+ This exposes the on-board flash and/or EEPROM as MTD devices
+ (e.g. /dev/mtd1). This is required to update the boot
+ configuration under Linux.
diff --git a/drivers/net/ethernet/sfc/falcon/Makefile b/drivers/net/ethernet/sfc/falcon/Makefile
new file mode 100644
index 000000000000..aa1b45979ca4
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/Makefile
@@ -0,0 +1,6 @@
+sfc-falcon-y += efx.o nic.o farch.o falcon.o tx.o rx.o selftest.o \
+ ethtool.o qt202x_phy.o mdio_10g.o tenxpress.o \
+ txc43128_phy.o falcon_boards.o
+
+sfc-falcon-$(CONFIG_SFC_FALCON_MTD) += mtd.o
+obj-$(CONFIG_SFC_FALCON) += sfc-falcon.o
diff --git a/drivers/net/ethernet/sfc/falcon/bitfield.h b/drivers/net/ethernet/sfc/falcon/bitfield.h
new file mode 100644
index 000000000000..230fd77bd311
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/bitfield.h
@@ -0,0 +1,542 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_BITFIELD_H
+#define EF4_BITFIELD_H
+
+/*
+ * Efx bitfield access
+ *
+ * Efx NICs make extensive use of bitfields up to 128 bits
+ * wide. Since there is no native 128-bit datatype on most systems,
+ * and since 64-bit datatypes are inefficient on 32-bit systems and
+ * vice versa, we wrap accesses in a way that uses the most efficient
+ * datatype.
+ *
+ * The NICs are PCI devices and therefore little-endian. Since most
+ * of the quantities that we deal with are DMAed to/from host memory,
+ * we define our datatypes (ef4_oword_t, ef4_qword_t and
+ * ef4_dword_t) to be little-endian.
+ */
+
+/* Lowest bit numbers and widths */
+#define EF4_DUMMY_FIELD_LBN 0
+#define EF4_DUMMY_FIELD_WIDTH 0
+#define EF4_WORD_0_LBN 0
+#define EF4_WORD_0_WIDTH 16
+#define EF4_WORD_1_LBN 16
+#define EF4_WORD_1_WIDTH 16
+#define EF4_DWORD_0_LBN 0
+#define EF4_DWORD_0_WIDTH 32
+#define EF4_DWORD_1_LBN 32
+#define EF4_DWORD_1_WIDTH 32
+#define EF4_DWORD_2_LBN 64
+#define EF4_DWORD_2_WIDTH 32
+#define EF4_DWORD_3_LBN 96
+#define EF4_DWORD_3_WIDTH 32
+#define EF4_QWORD_0_LBN 0
+#define EF4_QWORD_0_WIDTH 64
+
+/* Specified attribute (e.g. LBN) of the specified field */
+#define EF4_VAL(field, attribute) field ## _ ## attribute
+/* Low bit number of the specified field */
+#define EF4_LOW_BIT(field) EF4_VAL(field, LBN)
+/* Bit width of the specified field */
+#define EF4_WIDTH(field) EF4_VAL(field, WIDTH)
+/* High bit number of the specified field */
+#define EF4_HIGH_BIT(field) (EF4_LOW_BIT(field) + EF4_WIDTH(field) - 1)
+/* Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 64 bits.
+ */
+#define EF4_MASK64(width) \
+ ((width) == 64 ? ~((u64) 0) : \
+ (((((u64) 1) << (width))) - 1))
+
+/* Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 32 bits. Use
+ * EF4_MASK64 for higher width fields.
+ */
+#define EF4_MASK32(width) \
+ ((width) == 32 ? ~((u32) 0) : \
+ (((((u32) 1) << (width))) - 1))
+
+/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */
+typedef union ef4_dword {
+ __le32 u32[1];
+} ef4_dword_t;
+
+/* A quadword (i.e. 8 byte) datatype - little-endian in HW */
+typedef union ef4_qword {
+ __le64 u64[1];
+ __le32 u32[2];
+ ef4_dword_t dword[2];
+} ef4_qword_t;
+
+/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */
+typedef union ef4_oword {
+ __le64 u64[2];
+ ef4_qword_t qword[2];
+ __le32 u32[4];
+ ef4_dword_t dword[4];
+} ef4_oword_t;
+
+/* Format string and value expanders for printk */
+#define EF4_DWORD_FMT "%08x"
+#define EF4_QWORD_FMT "%08x:%08x"
+#define EF4_OWORD_FMT "%08x:%08x:%08x:%08x"
+#define EF4_DWORD_VAL(dword) \
+ ((unsigned int) le32_to_cpu((dword).u32[0]))
+#define EF4_QWORD_VAL(qword) \
+ ((unsigned int) le32_to_cpu((qword).u32[1])), \
+ ((unsigned int) le32_to_cpu((qword).u32[0]))
+#define EF4_OWORD_VAL(oword) \
+ ((unsigned int) le32_to_cpu((oword).u32[3])), \
+ ((unsigned int) le32_to_cpu((oword).u32[2])), \
+ ((unsigned int) le32_to_cpu((oword).u32[1])), \
+ ((unsigned int) le32_to_cpu((oword).u32[0]))
+
+/*
+ * Extract bit field portion [low,high) from the native-endian element
+ * which contains bits [min,max).
+ *
+ * For example, suppose "element" represents the high 32 bits of a
+ * 64-bit value, and we wish to extract the bits belonging to the bit
+ * field occupying bits 28-45 of this 64-bit value.
+ *
+ * Then EF4_EXTRACT ( element, 32, 63, 28, 45 ) would give
+ *
+ * ( element ) << 4
+ *
+ * The result will contain the relevant bits filled in in the range
+ * [0,high-low), with garbage in bits [high-low+1,...).
+ */
+#define EF4_EXTRACT_NATIVE(native_element, min, max, low, high) \
+ ((low) > (max) || (high) < (min) ? 0 : \
+ (low) > (min) ? \
+ (native_element) >> ((low) - (min)) : \
+ (native_element) << ((min) - (low)))
+
+/*
+ * Extract bit field portion [low,high) from the 64-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EF4_EXTRACT64(element, min, max, low, high) \
+ EF4_EXTRACT_NATIVE(le64_to_cpu(element), min, max, low, high)
+
+/*
+ * Extract bit field portion [low,high) from the 32-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EF4_EXTRACT32(element, min, max, low, high) \
+ EF4_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high)
+
+#define EF4_EXTRACT_OWORD64(oword, low, high) \
+ ((EF4_EXTRACT64((oword).u64[0], 0, 63, low, high) | \
+ EF4_EXTRACT64((oword).u64[1], 64, 127, low, high)) & \
+ EF4_MASK64((high) + 1 - (low)))
+
+#define EF4_EXTRACT_QWORD64(qword, low, high) \
+ (EF4_EXTRACT64((qword).u64[0], 0, 63, low, high) & \
+ EF4_MASK64((high) + 1 - (low)))
+
+#define EF4_EXTRACT_OWORD32(oword, low, high) \
+ ((EF4_EXTRACT32((oword).u32[0], 0, 31, low, high) | \
+ EF4_EXTRACT32((oword).u32[1], 32, 63, low, high) | \
+ EF4_EXTRACT32((oword).u32[2], 64, 95, low, high) | \
+ EF4_EXTRACT32((oword).u32[3], 96, 127, low, high)) & \
+ EF4_MASK32((high) + 1 - (low)))
+
+#define EF4_EXTRACT_QWORD32(qword, low, high) \
+ ((EF4_EXTRACT32((qword).u32[0], 0, 31, low, high) | \
+ EF4_EXTRACT32((qword).u32[1], 32, 63, low, high)) & \
+ EF4_MASK32((high) + 1 - (low)))
+
+#define EF4_EXTRACT_DWORD(dword, low, high) \
+ (EF4_EXTRACT32((dword).u32[0], 0, 31, low, high) & \
+ EF4_MASK32((high) + 1 - (low)))
+
+#define EF4_OWORD_FIELD64(oword, field) \
+ EF4_EXTRACT_OWORD64(oword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field))
+
+#define EF4_QWORD_FIELD64(qword, field) \
+ EF4_EXTRACT_QWORD64(qword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field))
+
+#define EF4_OWORD_FIELD32(oword, field) \
+ EF4_EXTRACT_OWORD32(oword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field))
+
+#define EF4_QWORD_FIELD32(qword, field) \
+ EF4_EXTRACT_QWORD32(qword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field))
+
+#define EF4_DWORD_FIELD(dword, field) \
+ EF4_EXTRACT_DWORD(dword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field))
+
+#define EF4_OWORD_IS_ZERO64(oword) \
+ (((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0)
+
+#define EF4_QWORD_IS_ZERO64(qword) \
+ (((qword).u64[0]) == (__force __le64) 0)
+
+#define EF4_OWORD_IS_ZERO32(oword) \
+ (((oword).u32[0] | (oword).u32[1] | (oword).u32[2] | (oword).u32[3]) \
+ == (__force __le32) 0)
+
+#define EF4_QWORD_IS_ZERO32(qword) \
+ (((qword).u32[0] | (qword).u32[1]) == (__force __le32) 0)
+
+#define EF4_DWORD_IS_ZERO(dword) \
+ (((dword).u32[0]) == (__force __le32) 0)
+
+#define EF4_OWORD_IS_ALL_ONES64(oword) \
+ (((oword).u64[0] & (oword).u64[1]) == ~((__force __le64) 0))
+
+#define EF4_QWORD_IS_ALL_ONES64(qword) \
+ ((qword).u64[0] == ~((__force __le64) 0))
+
+#define EF4_OWORD_IS_ALL_ONES32(oword) \
+ (((oword).u32[0] & (oword).u32[1] & (oword).u32[2] & (oword).u32[3]) \
+ == ~((__force __le32) 0))
+
+#define EF4_QWORD_IS_ALL_ONES32(qword) \
+ (((qword).u32[0] & (qword).u32[1]) == ~((__force __le32) 0))
+
+#define EF4_DWORD_IS_ALL_ONES(dword) \
+ ((dword).u32[0] == ~((__force __le32) 0))
+
+#if BITS_PER_LONG == 64
+#define EF4_OWORD_FIELD EF4_OWORD_FIELD64
+#define EF4_QWORD_FIELD EF4_QWORD_FIELD64
+#define EF4_OWORD_IS_ZERO EF4_OWORD_IS_ZERO64
+#define EF4_QWORD_IS_ZERO EF4_QWORD_IS_ZERO64
+#define EF4_OWORD_IS_ALL_ONES EF4_OWORD_IS_ALL_ONES64
+#define EF4_QWORD_IS_ALL_ONES EF4_QWORD_IS_ALL_ONES64
+#else
+#define EF4_OWORD_FIELD EF4_OWORD_FIELD32
+#define EF4_QWORD_FIELD EF4_QWORD_FIELD32
+#define EF4_OWORD_IS_ZERO EF4_OWORD_IS_ZERO32
+#define EF4_QWORD_IS_ZERO EF4_QWORD_IS_ZERO32
+#define EF4_OWORD_IS_ALL_ONES EF4_OWORD_IS_ALL_ONES32
+#define EF4_QWORD_IS_ALL_ONES EF4_QWORD_IS_ALL_ONES32
+#endif
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the bit field [low,high) that lies within
+ * the range [min,max).
+ */
+#define EF4_INSERT_NATIVE64(min, max, low, high, value) \
+ (((low > max) || (high < min)) ? 0 : \
+ ((low > min) ? \
+ (((u64) (value)) << (low - min)) : \
+ (((u64) (value)) >> (min - low))))
+
+#define EF4_INSERT_NATIVE32(min, max, low, high, value) \
+ (((low > max) || (high < min)) ? 0 : \
+ ((low > min) ? \
+ (((u32) (value)) << (low - min)) : \
+ (((u32) (value)) >> (min - low))))
+
+#define EF4_INSERT_NATIVE(min, max, low, high, value) \
+ ((((max - min) >= 32) || ((high - low) >= 32)) ? \
+ EF4_INSERT_NATIVE64(min, max, low, high, value) : \
+ EF4_INSERT_NATIVE32(min, max, low, high, value))
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the named bit field that lies within the
+ * range [min,max).
+ */
+#define EF4_INSERT_FIELD_NATIVE(min, max, field, value) \
+ EF4_INSERT_NATIVE(min, max, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+/*
+ * Construct bit field
+ *
+ * Creates the portion of the named bit fields that lie within the
+ * range [min,max).
+ */
+#define EF4_INSERT_FIELDS_NATIVE(min, max, \
+ field1, value1, \
+ field2, value2, \
+ field3, value3, \
+ field4, value4, \
+ field5, value5, \
+ field6, value6, \
+ field7, value7, \
+ field8, value8, \
+ field9, value9, \
+ field10, value10) \
+ (EF4_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field4, (value4)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field5, (value5)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field6, (value6)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) | \
+ EF4_INSERT_FIELD_NATIVE((min), (max), field10, (value10)))
+
+#define EF4_INSERT_FIELDS64(...) \
+ cpu_to_le64(EF4_INSERT_FIELDS_NATIVE(__VA_ARGS__))
+
+#define EF4_INSERT_FIELDS32(...) \
+ cpu_to_le32(EF4_INSERT_FIELDS_NATIVE(__VA_ARGS__))
+
+#define EF4_POPULATE_OWORD64(oword, ...) do { \
+ (oword).u64[0] = EF4_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
+ (oword).u64[1] = EF4_INSERT_FIELDS64(64, 127, __VA_ARGS__); \
+ } while (0)
+
+#define EF4_POPULATE_QWORD64(qword, ...) do { \
+ (qword).u64[0] = EF4_INSERT_FIELDS64(0, 63, __VA_ARGS__); \
+ } while (0)
+
+#define EF4_POPULATE_OWORD32(oword, ...) do { \
+ (oword).u32[0] = EF4_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
+ (oword).u32[1] = EF4_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
+ (oword).u32[2] = EF4_INSERT_FIELDS32(64, 95, __VA_ARGS__); \
+ (oword).u32[3] = EF4_INSERT_FIELDS32(96, 127, __VA_ARGS__); \
+ } while (0)
+
+#define EF4_POPULATE_QWORD32(qword, ...) do { \
+ (qword).u32[0] = EF4_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
+ (qword).u32[1] = EF4_INSERT_FIELDS32(32, 63, __VA_ARGS__); \
+ } while (0)
+
+#define EF4_POPULATE_DWORD(dword, ...) do { \
+ (dword).u32[0] = EF4_INSERT_FIELDS32(0, 31, __VA_ARGS__); \
+ } while (0)
+
+#if BITS_PER_LONG == 64
+#define EF4_POPULATE_OWORD EF4_POPULATE_OWORD64
+#define EF4_POPULATE_QWORD EF4_POPULATE_QWORD64
+#else
+#define EF4_POPULATE_OWORD EF4_POPULATE_OWORD32
+#define EF4_POPULATE_QWORD EF4_POPULATE_QWORD32
+#endif
+
+/* Populate an octword field with various numbers of arguments */
+#define EF4_POPULATE_OWORD_10 EF4_POPULATE_OWORD
+#define EF4_POPULATE_OWORD_9(oword, ...) \
+ EF4_POPULATE_OWORD_10(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_8(oword, ...) \
+ EF4_POPULATE_OWORD_9(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_7(oword, ...) \
+ EF4_POPULATE_OWORD_8(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_6(oword, ...) \
+ EF4_POPULATE_OWORD_7(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_5(oword, ...) \
+ EF4_POPULATE_OWORD_6(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_4(oword, ...) \
+ EF4_POPULATE_OWORD_5(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_3(oword, ...) \
+ EF4_POPULATE_OWORD_4(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_2(oword, ...) \
+ EF4_POPULATE_OWORD_3(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_OWORD_1(oword, ...) \
+ EF4_POPULATE_OWORD_2(oword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_ZERO_OWORD(oword) \
+ EF4_POPULATE_OWORD_1(oword, EF4_DUMMY_FIELD, 0)
+#define EF4_SET_OWORD(oword) \
+ EF4_POPULATE_OWORD_4(oword, \
+ EF4_DWORD_0, 0xffffffff, \
+ EF4_DWORD_1, 0xffffffff, \
+ EF4_DWORD_2, 0xffffffff, \
+ EF4_DWORD_3, 0xffffffff)
+
+/* Populate a quadword field with various numbers of arguments */
+#define EF4_POPULATE_QWORD_10 EF4_POPULATE_QWORD
+#define EF4_POPULATE_QWORD_9(qword, ...) \
+ EF4_POPULATE_QWORD_10(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_8(qword, ...) \
+ EF4_POPULATE_QWORD_9(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_7(qword, ...) \
+ EF4_POPULATE_QWORD_8(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_6(qword, ...) \
+ EF4_POPULATE_QWORD_7(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_5(qword, ...) \
+ EF4_POPULATE_QWORD_6(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_4(qword, ...) \
+ EF4_POPULATE_QWORD_5(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_3(qword, ...) \
+ EF4_POPULATE_QWORD_4(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_2(qword, ...) \
+ EF4_POPULATE_QWORD_3(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_QWORD_1(qword, ...) \
+ EF4_POPULATE_QWORD_2(qword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_ZERO_QWORD(qword) \
+ EF4_POPULATE_QWORD_1(qword, EF4_DUMMY_FIELD, 0)
+#define EF4_SET_QWORD(qword) \
+ EF4_POPULATE_QWORD_2(qword, \
+ EF4_DWORD_0, 0xffffffff, \
+ EF4_DWORD_1, 0xffffffff)
+
+/* Populate a dword field with various numbers of arguments */
+#define EF4_POPULATE_DWORD_10 EF4_POPULATE_DWORD
+#define EF4_POPULATE_DWORD_9(dword, ...) \
+ EF4_POPULATE_DWORD_10(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_8(dword, ...) \
+ EF4_POPULATE_DWORD_9(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_7(dword, ...) \
+ EF4_POPULATE_DWORD_8(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_6(dword, ...) \
+ EF4_POPULATE_DWORD_7(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_5(dword, ...) \
+ EF4_POPULATE_DWORD_6(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_4(dword, ...) \
+ EF4_POPULATE_DWORD_5(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_3(dword, ...) \
+ EF4_POPULATE_DWORD_4(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_2(dword, ...) \
+ EF4_POPULATE_DWORD_3(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_POPULATE_DWORD_1(dword, ...) \
+ EF4_POPULATE_DWORD_2(dword, EF4_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EF4_ZERO_DWORD(dword) \
+ EF4_POPULATE_DWORD_1(dword, EF4_DUMMY_FIELD, 0)
+#define EF4_SET_DWORD(dword) \
+ EF4_POPULATE_DWORD_1(dword, EF4_DWORD_0, 0xffffffff)
+
+/*
+ * Modify a named field within an already-populated structure. Used
+ * for read-modify-write operations.
+ *
+ */
+#define EF4_INVERT_OWORD(oword) do { \
+ (oword).u64[0] = ~((oword).u64[0]); \
+ (oword).u64[1] = ~((oword).u64[1]); \
+ } while (0)
+
+#define EF4_AND_OWORD(oword, from, mask) \
+ do { \
+ (oword).u64[0] = (from).u64[0] & (mask).u64[0]; \
+ (oword).u64[1] = (from).u64[1] & (mask).u64[1]; \
+ } while (0)
+
+#define EF4_OR_OWORD(oword, from, mask) \
+ do { \
+ (oword).u64[0] = (from).u64[0] | (mask).u64[0]; \
+ (oword).u64[1] = (from).u64[1] | (mask).u64[1]; \
+ } while (0)
+
+#define EF4_INSERT64(min, max, low, high, value) \
+ cpu_to_le64(EF4_INSERT_NATIVE(min, max, low, high, value))
+
+#define EF4_INSERT32(min, max, low, high, value) \
+ cpu_to_le32(EF4_INSERT_NATIVE(min, max, low, high, value))
+
+#define EF4_INPLACE_MASK64(min, max, low, high) \
+ EF4_INSERT64(min, max, low, high, EF4_MASK64((high) + 1 - (low)))
+
+#define EF4_INPLACE_MASK32(min, max, low, high) \
+ EF4_INSERT32(min, max, low, high, EF4_MASK32((high) + 1 - (low)))
+
+#define EF4_SET_OWORD64(oword, low, high, value) do { \
+ (oword).u64[0] = (((oword).u64[0] \
+ & ~EF4_INPLACE_MASK64(0, 63, low, high)) \
+ | EF4_INSERT64(0, 63, low, high, value)); \
+ (oword).u64[1] = (((oword).u64[1] \
+ & ~EF4_INPLACE_MASK64(64, 127, low, high)) \
+ | EF4_INSERT64(64, 127, low, high, value)); \
+ } while (0)
+
+#define EF4_SET_QWORD64(qword, low, high, value) do { \
+ (qword).u64[0] = (((qword).u64[0] \
+ & ~EF4_INPLACE_MASK64(0, 63, low, high)) \
+ | EF4_INSERT64(0, 63, low, high, value)); \
+ } while (0)
+
+#define EF4_SET_OWORD32(oword, low, high, value) do { \
+ (oword).u32[0] = (((oword).u32[0] \
+ & ~EF4_INPLACE_MASK32(0, 31, low, high)) \
+ | EF4_INSERT32(0, 31, low, high, value)); \
+ (oword).u32[1] = (((oword).u32[1] \
+ & ~EF4_INPLACE_MASK32(32, 63, low, high)) \
+ | EF4_INSERT32(32, 63, low, high, value)); \
+ (oword).u32[2] = (((oword).u32[2] \
+ & ~EF4_INPLACE_MASK32(64, 95, low, high)) \
+ | EF4_INSERT32(64, 95, low, high, value)); \
+ (oword).u32[3] = (((oword).u32[3] \
+ & ~EF4_INPLACE_MASK32(96, 127, low, high)) \
+ | EF4_INSERT32(96, 127, low, high, value)); \
+ } while (0)
+
+#define EF4_SET_QWORD32(qword, low, high, value) do { \
+ (qword).u32[0] = (((qword).u32[0] \
+ & ~EF4_INPLACE_MASK32(0, 31, low, high)) \
+ | EF4_INSERT32(0, 31, low, high, value)); \
+ (qword).u32[1] = (((qword).u32[1] \
+ & ~EF4_INPLACE_MASK32(32, 63, low, high)) \
+ | EF4_INSERT32(32, 63, low, high, value)); \
+ } while (0)
+
+#define EF4_SET_DWORD32(dword, low, high, value) do { \
+ (dword).u32[0] = (((dword).u32[0] \
+ & ~EF4_INPLACE_MASK32(0, 31, low, high)) \
+ | EF4_INSERT32(0, 31, low, high, value)); \
+ } while (0)
+
+#define EF4_SET_OWORD_FIELD64(oword, field, value) \
+ EF4_SET_OWORD64(oword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+#define EF4_SET_QWORD_FIELD64(qword, field, value) \
+ EF4_SET_QWORD64(qword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+#define EF4_SET_OWORD_FIELD32(oword, field, value) \
+ EF4_SET_OWORD32(oword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+#define EF4_SET_QWORD_FIELD32(qword, field, value) \
+ EF4_SET_QWORD32(qword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+#define EF4_SET_DWORD_FIELD(dword, field, value) \
+ EF4_SET_DWORD32(dword, EF4_LOW_BIT(field), \
+ EF4_HIGH_BIT(field), value)
+
+
+
+#if BITS_PER_LONG == 64
+#define EF4_SET_OWORD_FIELD EF4_SET_OWORD_FIELD64
+#define EF4_SET_QWORD_FIELD EF4_SET_QWORD_FIELD64
+#else
+#define EF4_SET_OWORD_FIELD EF4_SET_OWORD_FIELD32
+#define EF4_SET_QWORD_FIELD EF4_SET_QWORD_FIELD32
+#endif
+
+/* Used to avoid compiler warnings about shift range exceeding width
+ * of the data types when dma_addr_t is only 32 bits wide.
+ */
+#define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t))
+#define EF4_DMA_TYPE_WIDTH(width) \
+ (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
+
+
+/* Static initialiser */
+#define EF4_OWORD32(a, b, c, d) \
+ { .u32 = { cpu_to_le32(a), cpu_to_le32(b), \
+ cpu_to_le32(c), cpu_to_le32(d) } }
+
+#endif /* EF4_BITFIELD_H */
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
new file mode 100644
index 000000000000..5c5cb3c4c12e
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -0,0 +1,3350 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2005-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/topology.h>
+#include <linux/gfp.h>
+#include <linux/aer.h>
+#include <linux/interrupt.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "nic.h"
+#include "selftest.h"
+
+#include "workarounds.h"
+
+/**************************************************************************
+ *
+ * Type name strings
+ *
+ **************************************************************************
+ */
+
+/* Loopback mode names (see LOOPBACK_MODE()) */
+const unsigned int ef4_loopback_mode_max = LOOPBACK_MAX;
+const char *const ef4_loopback_mode_names[] = {
+ [LOOPBACK_NONE] = "NONE",
+ [LOOPBACK_DATA] = "DATAPATH",
+ [LOOPBACK_GMAC] = "GMAC",
+ [LOOPBACK_XGMII] = "XGMII",
+ [LOOPBACK_XGXS] = "XGXS",
+ [LOOPBACK_XAUI] = "XAUI",
+ [LOOPBACK_GMII] = "GMII",
+ [LOOPBACK_SGMII] = "SGMII",
+ [LOOPBACK_XGBR] = "XGBR",
+ [LOOPBACK_XFI] = "XFI",
+ [LOOPBACK_XAUI_FAR] = "XAUI_FAR",
+ [LOOPBACK_GMII_FAR] = "GMII_FAR",
+ [LOOPBACK_SGMII_FAR] = "SGMII_FAR",
+ [LOOPBACK_XFI_FAR] = "XFI_FAR",
+ [LOOPBACK_GPHY] = "GPHY",
+ [LOOPBACK_PHYXS] = "PHYXS",
+ [LOOPBACK_PCS] = "PCS",
+ [LOOPBACK_PMAPMD] = "PMA/PMD",
+ [LOOPBACK_XPORT] = "XPORT",
+ [LOOPBACK_XGMII_WS] = "XGMII_WS",
+ [LOOPBACK_XAUI_WS] = "XAUI_WS",
+ [LOOPBACK_XAUI_WS_FAR] = "XAUI_WS_FAR",
+ [LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR",
+ [LOOPBACK_GMII_WS] = "GMII_WS",
+ [LOOPBACK_XFI_WS] = "XFI_WS",
+ [LOOPBACK_XFI_WS_FAR] = "XFI_WS_FAR",
+ [LOOPBACK_PHYXS_WS] = "PHYXS_WS",
+};
+
+const unsigned int ef4_reset_type_max = RESET_TYPE_MAX;
+const char *const ef4_reset_type_names[] = {
+ [RESET_TYPE_INVISIBLE] = "INVISIBLE",
+ [RESET_TYPE_ALL] = "ALL",
+ [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL",
+ [RESET_TYPE_WORLD] = "WORLD",
+ [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
+ [RESET_TYPE_DATAPATH] = "DATAPATH",
+ [RESET_TYPE_DISABLE] = "DISABLE",
+ [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG",
+ [RESET_TYPE_INT_ERROR] = "INT_ERROR",
+ [RESET_TYPE_RX_RECOVERY] = "RX_RECOVERY",
+ [RESET_TYPE_DMA_ERROR] = "DMA_ERROR",
+ [RESET_TYPE_TX_SKIP] = "TX_SKIP",
+};
+
+/* Reset workqueue. If any NIC has a hardware failure then a reset will be
+ * queued onto this work queue. This is not a per-nic work queue, because
+ * ef4_reset_work() acquires the rtnl lock, so resets are naturally serialised.
+ */
+static struct workqueue_struct *reset_workqueue;
+
+/* How often and how many times to poll for a reset while waiting for a
+ * BIST that another function started to complete.
+ */
+#define BIST_WAIT_DELAY_MS 100
+#define BIST_WAIT_DELAY_COUNT 100
+
+/**************************************************************************
+ *
+ * Configurable values
+ *
+ *************************************************************************/
+
+/*
+ * Use separate channels for TX and RX events
+ *
+ * Set this to 1 to use separate channels for TX and RX. It allows us
+ * to control interrupt affinity separately for TX and RX.
+ *
+ * This is only used in MSI-X interrupt mode
+ */
+bool ef4_separate_tx_channels;
+module_param(ef4_separate_tx_channels, bool, 0444);
+MODULE_PARM_DESC(ef4_separate_tx_channels,
+ "Use separate channels for TX and RX");
+
+/* This is the weight assigned to each of the (per-channel) virtual
+ * NAPI devices.
+ */
+static int napi_weight = 64;
+
+/* This is the time (in jiffies) between invocations of the hardware
+ * monitor.
+ * On Falcon-based NICs, this will:
+ * - Check the on-board hardware monitor;
+ * - Poll the link state and reconfigure the hardware as necessary.
+ * On Siena-based NICs for power systems with EEH support, this will give EEH a
+ * chance to start.
+ */
+static unsigned int ef4_monitor_interval = 1 * HZ;
+
+/* Initial interrupt moderation settings. They can be modified after
+ * module load with ethtool.
+ *
+ * The default for RX should strike a balance between increasing the
+ * round-trip latency and reducing overhead.
+ */
+static unsigned int rx_irq_mod_usec = 60;
+
+/* Initial interrupt moderation settings. They can be modified after
+ * module load with ethtool.
+ *
+ * This default is chosen to ensure that a 10G link does not go idle
+ * while a TX queue is stopped after it has become full. A queue is
+ * restarted when it drops below half full. The time this takes (assuming
+ * worst case 3 descriptors per packet and 1024 descriptors) is
+ * 512 / 3 * 1.2 = 205 usec.
+ */
+static unsigned int tx_irq_mod_usec = 150;
+
+/* This is the first interrupt mode to try out of:
+ * 0 => MSI-X
+ * 1 => MSI
+ * 2 => legacy
+ */
+static unsigned int interrupt_mode;
+
+/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS),
+ * i.e. the number of CPUs among which we may distribute simultaneous
+ * interrupt handling.
+ *
+ * Cards without MSI-X will only target one CPU via legacy or MSI interrupt.
+ * The default (0) means to assign an interrupt to each core.
+ */
+static unsigned int rss_cpus;
+module_param(rss_cpus, uint, 0444);
+MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
+
+static bool phy_flash_cfg;
+module_param(phy_flash_cfg, bool, 0644);
+MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
+
+static unsigned irq_adapt_low_thresh = 8000;
+module_param(irq_adapt_low_thresh, uint, 0644);
+MODULE_PARM_DESC(irq_adapt_low_thresh,
+ "Threshold score for reducing IRQ moderation");
+
+static unsigned irq_adapt_high_thresh = 16000;
+module_param(irq_adapt_high_thresh, uint, 0644);
+MODULE_PARM_DESC(irq_adapt_high_thresh,
+ "Threshold score for increasing IRQ moderation");
+
+static unsigned debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
+ NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
+ NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
+ NETIF_MSG_TX_ERR | NETIF_MSG_HW);
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
+
+/**************************************************************************
+ *
+ * Utility functions and prototypes
+ *
+ *************************************************************************/
+
+static int ef4_soft_enable_interrupts(struct ef4_nic *efx);
+static void ef4_soft_disable_interrupts(struct ef4_nic *efx);
+static void ef4_remove_channel(struct ef4_channel *channel);
+static void ef4_remove_channels(struct ef4_nic *efx);
+static const struct ef4_channel_type ef4_default_channel_type;
+static void ef4_remove_port(struct ef4_nic *efx);
+static void ef4_init_napi_channel(struct ef4_channel *channel);
+static void ef4_fini_napi(struct ef4_nic *efx);
+static void ef4_fini_napi_channel(struct ef4_channel *channel);
+static void ef4_fini_struct(struct ef4_nic *efx);
+static void ef4_start_all(struct ef4_nic *efx);
+static void ef4_stop_all(struct ef4_nic *efx);
+
+#define EF4_ASSERT_RESET_SERIALISED(efx) \
+ do { \
+ if ((efx->state == STATE_READY) || \
+ (efx->state == STATE_RECOVERY) || \
+ (efx->state == STATE_DISABLED)) \
+ ASSERT_RTNL(); \
+ } while (0)
+
+static int ef4_check_disabled(struct ef4_nic *efx)
+{
+ if (efx->state == STATE_DISABLED || efx->state == STATE_RECOVERY) {
+ netif_err(efx, drv, efx->net_dev,
+ "device is disabled due to earlier errors\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+/**************************************************************************
+ *
+ * Event queue processing
+ *
+ *************************************************************************/
+
+/* Process channel's event queue
+ *
+ * This function is responsible for processing the event queue of a
+ * single channel. The caller must guarantee that this function will
+ * never be concurrently called more than once on the same channel,
+ * though different channels may be being processed concurrently.
+ */
+static int ef4_process_channel(struct ef4_channel *channel, int budget)
+{
+ struct ef4_tx_queue *tx_queue;
+ int spent;
+
+ if (unlikely(!channel->enabled))
+ return 0;
+
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ tx_queue->pkts_compl = 0;
+ tx_queue->bytes_compl = 0;
+ }
+
+ spent = ef4_nic_process_eventq(channel, budget);
+ if (spent && ef4_channel_has_rx_queue(channel)) {
+ struct ef4_rx_queue *rx_queue =
+ ef4_channel_get_rx_queue(channel);
+
+ ef4_rx_flush_packet(channel);
+ ef4_fast_push_rx_descriptors(rx_queue, true);
+ }
+
+ /* Update BQL */
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->bytes_compl) {
+ netdev_tx_completed_queue(tx_queue->core_txq,
+ tx_queue->pkts_compl, tx_queue->bytes_compl);
+ }
+ }
+
+ return spent;
+}
+
+/* NAPI poll handler
+ *
+ * NAPI guarantees serialisation of polls of the same device, which
+ * provides the guarantee required by ef4_process_channel().
+ */
+static void ef4_update_irq_mod(struct ef4_nic *efx, struct ef4_channel *channel)
+{
+ int step = efx->irq_mod_step_us;
+
+ if (channel->irq_mod_score < irq_adapt_low_thresh) {
+ if (channel->irq_moderation_us > step) {
+ channel->irq_moderation_us -= step;
+ efx->type->push_irq_moderation(channel);
+ }
+ } else if (channel->irq_mod_score > irq_adapt_high_thresh) {
+ if (channel->irq_moderation_us <
+ efx->irq_rx_moderation_us) {
+ channel->irq_moderation_us += step;
+ efx->type->push_irq_moderation(channel);
+ }
+ }
+
+ channel->irq_count = 0;
+ channel->irq_mod_score = 0;
+}
+
+static int ef4_poll(struct napi_struct *napi, int budget)
+{
+ struct ef4_channel *channel =
+ container_of(napi, struct ef4_channel, napi_str);
+ struct ef4_nic *efx = channel->efx;
+ int spent;
+
+ if (!ef4_channel_lock_napi(channel))
+ return budget;
+
+ netif_vdbg(efx, intr, efx->net_dev,
+ "channel %d NAPI poll executing on CPU %d\n",
+ channel->channel, raw_smp_processor_id());
+
+ spent = ef4_process_channel(channel, budget);
+
+ if (spent < budget) {
+ if (ef4_channel_has_rx_queue(channel) &&
+ efx->irq_rx_adaptive &&
+ unlikely(++channel->irq_count == 1000)) {
+ ef4_update_irq_mod(efx, channel);
+ }
+
+ ef4_filter_rfs_expire(channel);
+
+ /* There is no race here; although napi_disable() will
+ * only wait for napi_complete(), this isn't a problem
+ * since ef4_nic_eventq_read_ack() will have no effect if
+ * interrupts have already been disabled.
+ */
+ napi_complete(napi);
+ ef4_nic_eventq_read_ack(channel);
+ }
+
+ ef4_channel_unlock_napi(channel);
+ return spent;
+}
+
+/* Create event queue
+ * Event queue memory allocations are done only once. If the channel
+ * is reset, the memory buffer will be reused; this guards against
+ * errors during channel reset and also simplifies interrupt handling.
+ */
+static int ef4_probe_eventq(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+ unsigned long entries;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "chan %d create event queue\n", channel->channel);
+
+ /* Build an event queue with room for one event per tx and rx buffer,
+ * plus some extra for link state events and MCDI completions. */
+ entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
+ EF4_BUG_ON_PARANOID(entries > EF4_MAX_EVQ_SIZE);
+ channel->eventq_mask = max(entries, EF4_MIN_EVQ_SIZE) - 1;
+
+ return ef4_nic_probe_eventq(channel);
+}
+
+/* Prepare channel's event queue */
+static int ef4_init_eventq(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+ int rc;
+
+ EF4_WARN_ON_PARANOID(channel->eventq_init);
+
+ netif_dbg(efx, drv, efx->net_dev,
+ "chan %d init event queue\n", channel->channel);
+
+ rc = ef4_nic_init_eventq(channel);
+ if (rc == 0) {
+ efx->type->push_irq_moderation(channel);
+ channel->eventq_read_ptr = 0;
+ channel->eventq_init = true;
+ }
+ return rc;
+}
+
+/* Enable event queue processing and NAPI */
+void ef4_start_eventq(struct ef4_channel *channel)
+{
+ netif_dbg(channel->efx, ifup, channel->efx->net_dev,
+ "chan %d start event queue\n", channel->channel);
+
+ /* Make sure the NAPI handler sees the enabled flag set */
+ channel->enabled = true;
+ smp_wmb();
+
+ ef4_channel_enable(channel);
+ napi_enable(&channel->napi_str);
+ ef4_nic_eventq_read_ack(channel);
+}
+
+/* Disable event queue processing and NAPI */
+void ef4_stop_eventq(struct ef4_channel *channel)
+{
+ if (!channel->enabled)
+ return;
+
+ napi_disable(&channel->napi_str);
+ while (!ef4_channel_disable(channel))
+ usleep_range(1000, 20000);
+ channel->enabled = false;
+}
+
+static void ef4_fini_eventq(struct ef4_channel *channel)
+{
+ if (!channel->eventq_init)
+ return;
+
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "chan %d fini event queue\n", channel->channel);
+
+ ef4_nic_fini_eventq(channel);
+ channel->eventq_init = false;
+}
+
+static void ef4_remove_eventq(struct ef4_channel *channel)
+{
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "chan %d remove event queue\n", channel->channel);
+
+ ef4_nic_remove_eventq(channel);
+}
+
+/**************************************************************************
+ *
+ * Channel handling
+ *
+ *************************************************************************/
+
+/* Allocate and initialise a channel structure. */
+static struct ef4_channel *
+ef4_alloc_channel(struct ef4_nic *efx, int i, struct ef4_channel *old_channel)
+{
+ struct ef4_channel *channel;
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_tx_queue *tx_queue;
+ int j;
+
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ channel->efx = efx;
+ channel->channel = i;
+ channel->type = &ef4_default_channel_type;
+
+ for (j = 0; j < EF4_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ tx_queue->efx = efx;
+ tx_queue->queue = i * EF4_TXQ_TYPES + j;
+ tx_queue->channel = channel;
+ }
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->efx = efx;
+ setup_timer(&rx_queue->slow_fill, ef4_rx_slow_fill,
+ (unsigned long)rx_queue);
+
+ return channel;
+}
+
+/* Allocate and initialise a channel structure, copying parameters
+ * (but not resources) from an old channel structure.
+ */
+static struct ef4_channel *
+ef4_copy_channel(const struct ef4_channel *old_channel)
+{
+ struct ef4_channel *channel;
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_tx_queue *tx_queue;
+ int j;
+
+ channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ *channel = *old_channel;
+
+ channel->napi_dev = NULL;
+ INIT_HLIST_NODE(&channel->napi_str.napi_hash_node);
+ channel->napi_str.napi_id = 0;
+ channel->napi_str.state = 0;
+ memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+ for (j = 0; j < EF4_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ if (tx_queue->channel)
+ tx_queue->channel = channel;
+ tx_queue->buffer = NULL;
+ memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
+ }
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->buffer = NULL;
+ memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+ setup_timer(&rx_queue->slow_fill, ef4_rx_slow_fill,
+ (unsigned long)rx_queue);
+
+ return channel;
+}
+
+static int ef4_probe_channel(struct ef4_channel *channel)
+{
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+ int rc;
+
+ netif_dbg(channel->efx, probe, channel->efx->net_dev,
+ "creating channel %d\n", channel->channel);
+
+ rc = channel->type->pre_probe(channel);
+ if (rc)
+ goto fail;
+
+ rc = ef4_probe_eventq(channel);
+ if (rc)
+ goto fail;
+
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ rc = ef4_probe_tx_queue(tx_queue);
+ if (rc)
+ goto fail;
+ }
+
+ ef4_for_each_channel_rx_queue(rx_queue, channel) {
+ rc = ef4_probe_rx_queue(rx_queue);
+ if (rc)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ ef4_remove_channel(channel);
+ return rc;
+}
+
+static void
+ef4_get_channel_name(struct ef4_channel *channel, char *buf, size_t len)
+{
+ struct ef4_nic *efx = channel->efx;
+ const char *type;
+ int number;
+
+ number = channel->channel;
+ if (efx->tx_channel_offset == 0) {
+ type = "";
+ } else if (channel->channel < efx->tx_channel_offset) {
+ type = "-rx";
+ } else {
+ type = "-tx";
+ number -= efx->tx_channel_offset;
+ }
+ snprintf(buf, len, "%s%s-%d", efx->name, type, number);
+}
+
+static void ef4_set_channel_names(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ channel->type->get_name(channel,
+ efx->msi_context[channel->channel].name,
+ sizeof(efx->msi_context[0].name));
+}
+
+static int ef4_probe_channels(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+ int rc;
+
+ /* Restart special buffer allocation */
+ efx->next_buffer_table = 0;
+
+ /* Probe channels in reverse, so that any 'extra' channels
+ * use the start of the buffer table. This allows the traffic
+ * channels to be resized without moving them or wasting the
+ * entries before them.
+ */
+ ef4_for_each_channel_rev(channel, efx) {
+ rc = ef4_probe_channel(channel);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create channel %d\n",
+ channel->channel);
+ goto fail;
+ }
+ }
+ ef4_set_channel_names(efx);
+
+ return 0;
+
+fail:
+ ef4_remove_channels(efx);
+ return rc;
+}
+
+/* Channels are shutdown and reinitialised whilst the NIC is running
+ * to propagate configuration changes (mtu, checksum offload), or
+ * to clear hardware error conditions
+ */
+static void ef4_start_datapath(struct ef4_nic *efx)
+{
+ netdev_features_t old_features = efx->net_dev->features;
+ bool old_rx_scatter = efx->rx_scatter;
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_channel *channel;
+ size_t rx_buf_len;
+
+ /* Calculate the rx buffer allocation parameters required to
+ * support the current MTU, including padding for header
+ * alignment and overruns.
+ */
+ efx->rx_dma_len = (efx->rx_prefix_size +
+ EF4_MAX_FRAME_LEN(efx->net_dev->mtu) +
+ efx->type->rx_buffer_padding);
+ rx_buf_len = (sizeof(struct ef4_rx_page_state) +
+ efx->rx_ip_align + efx->rx_dma_len);
+ if (rx_buf_len <= PAGE_SIZE) {
+ efx->rx_scatter = efx->type->always_rx_scatter;
+ efx->rx_buffer_order = 0;
+ } else if (efx->type->can_rx_scatter) {
+ BUILD_BUG_ON(EF4_RX_USR_BUF_SIZE % L1_CACHE_BYTES);
+ BUILD_BUG_ON(sizeof(struct ef4_rx_page_state) +
+ 2 * ALIGN(NET_IP_ALIGN + EF4_RX_USR_BUF_SIZE,
+ EF4_RX_BUF_ALIGNMENT) >
+ PAGE_SIZE);
+ efx->rx_scatter = true;
+ efx->rx_dma_len = EF4_RX_USR_BUF_SIZE;
+ efx->rx_buffer_order = 0;
+ } else {
+ efx->rx_scatter = false;
+ efx->rx_buffer_order = get_order(rx_buf_len);
+ }
+
+ ef4_rx_config_page_split(efx);
+ if (efx->rx_buffer_order)
+ netif_dbg(efx, drv, efx->net_dev,
+ "RX buf len=%u; page order=%u batch=%u\n",
+ efx->rx_dma_len, efx->rx_buffer_order,
+ efx->rx_pages_per_batch);
+ else
+ netif_dbg(efx, drv, efx->net_dev,
+ "RX buf len=%u step=%u bpp=%u; page batch=%u\n",
+ efx->rx_dma_len, efx->rx_page_buf_step,
+ efx->rx_bufs_per_page, efx->rx_pages_per_batch);
+
+ /* Restore previously fixed features in hw_features and remove
+ * features which are fixed now
+ */
+ efx->net_dev->hw_features |= efx->net_dev->features;
+ efx->net_dev->hw_features &= ~efx->fixed_features;
+ efx->net_dev->features |= efx->fixed_features;
+ if (efx->net_dev->features != old_features)
+ netdev_features_change(efx->net_dev);
+
+ /* RX filters may also have scatter-enabled flags */
+ if (efx->rx_scatter != old_rx_scatter)
+ efx->type->filter_update_rx_scatter(efx);
+
+ /* We must keep at least one descriptor in a TX ring empty.
+ * We could avoid this when the queue size does not exactly
+ * match the hardware ring size, but it's not that important.
+ * Therefore we stop the queue when one more skb might fill
+ * the ring completely. We wake it when half way back to
+ * empty.
+ */
+ efx->txq_stop_thresh = efx->txq_entries - ef4_tx_max_skb_descs(efx);
+ efx->txq_wake_thresh = efx->txq_stop_thresh / 2;
+
+ /* Initialise the channels */
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ ef4_init_tx_queue(tx_queue);
+ atomic_inc(&efx->active_queues);
+ }
+
+ ef4_for_each_channel_rx_queue(rx_queue, channel) {
+ ef4_init_rx_queue(rx_queue);
+ atomic_inc(&efx->active_queues);
+ ef4_stop_eventq(channel);
+ ef4_fast_push_rx_descriptors(rx_queue, false);
+ ef4_start_eventq(channel);
+ }
+
+ WARN_ON(channel->rx_pkt_n_frags);
+ }
+
+ if (netif_device_present(efx->net_dev))
+ netif_tx_wake_all_queues(efx->net_dev);
+}
+
+static void ef4_stop_datapath(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+ int rc;
+
+ EF4_ASSERT_RESET_SERIALISED(efx);
+ BUG_ON(efx->port_enabled);
+
+ /* Stop RX refill */
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_rx_queue(rx_queue, channel)
+ rx_queue->refill_enabled = false;
+ }
+
+ ef4_for_each_channel(channel, efx) {
+ /* RX packet processing is pipelined, so wait for the
+ * NAPI handler to complete. At least event queue 0
+ * might be kept active by non-data events, so don't
+ * use napi_synchronize() but actually disable NAPI
+ * temporarily.
+ */
+ if (ef4_channel_has_rx_queue(channel)) {
+ ef4_stop_eventq(channel);
+ ef4_start_eventq(channel);
+ }
+ }
+
+ rc = efx->type->fini_dmaq(efx);
+ if (rc && EF4_WORKAROUND_7803(efx)) {
+ /* Schedule a reset to recover from the flush failure. The
+ * descriptor caches reference memory we're about to free,
+ * but falcon_reconfigure_mac_wrapper() won't reconnect
+ * the MACs because of the pending reset.
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "Resetting to recover from flush failure\n");
+ ef4_schedule_reset(efx, RESET_TYPE_ALL);
+ } else if (rc) {
+ netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
+ } else {
+ netif_dbg(efx, drv, efx->net_dev,
+ "successfully flushed all queues\n");
+ }
+
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_rx_queue(rx_queue, channel)
+ ef4_fini_rx_queue(rx_queue);
+ ef4_for_each_possible_channel_tx_queue(tx_queue, channel)
+ ef4_fini_tx_queue(tx_queue);
+ }
+}
+
+static void ef4_remove_channel(struct ef4_channel *channel)
+{
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "destroy chan %d\n", channel->channel);
+
+ ef4_for_each_channel_rx_queue(rx_queue, channel)
+ ef4_remove_rx_queue(rx_queue);
+ ef4_for_each_possible_channel_tx_queue(tx_queue, channel)
+ ef4_remove_tx_queue(tx_queue);
+ ef4_remove_eventq(channel);
+ channel->type->post_remove(channel);
+}
+
+static void ef4_remove_channels(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ ef4_remove_channel(channel);
+}
+
+int
+ef4_realloc_channels(struct ef4_nic *efx, u32 rxq_entries, u32 txq_entries)
+{
+ struct ef4_channel *other_channel[EF4_MAX_CHANNELS], *channel;
+ u32 old_rxq_entries, old_txq_entries;
+ unsigned i, next_buffer_table = 0;
+ int rc, rc2;
+
+ rc = ef4_check_disabled(efx);
+ if (rc)
+ return rc;
+
+ /* Not all channels should be reallocated. We must avoid
+ * reallocating their buffer table entries.
+ */
+ ef4_for_each_channel(channel, efx) {
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_tx_queue *tx_queue;
+
+ if (channel->type->copy)
+ continue;
+ next_buffer_table = max(next_buffer_table,
+ channel->eventq.index +
+ channel->eventq.entries);
+ ef4_for_each_channel_rx_queue(rx_queue, channel)
+ next_buffer_table = max(next_buffer_table,
+ rx_queue->rxd.index +
+ rx_queue->rxd.entries);
+ ef4_for_each_channel_tx_queue(tx_queue, channel)
+ next_buffer_table = max(next_buffer_table,
+ tx_queue->txd.index +
+ tx_queue->txd.entries);
+ }
+
+ ef4_device_detach_sync(efx);
+ ef4_stop_all(efx);
+ ef4_soft_disable_interrupts(efx);
+
+ /* Clone channels (where possible) */
+ memset(other_channel, 0, sizeof(other_channel));
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ if (channel->type->copy)
+ channel = channel->type->copy(channel);
+ if (!channel) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ other_channel[i] = channel;
+ }
+
+ /* Swap entry counts and channel pointers */
+ old_rxq_entries = efx->rxq_entries;
+ old_txq_entries = efx->txq_entries;
+ efx->rxq_entries = rxq_entries;
+ efx->txq_entries = txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+
+ /* Restart buffer table allocation */
+ efx->next_buffer_table = next_buffer_table;
+
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ if (!channel->type->copy)
+ continue;
+ rc = ef4_probe_channel(channel);
+ if (rc)
+ goto rollback;
+ ef4_init_napi_channel(efx->channel[i]);
+ }
+
+out:
+ /* Destroy unused channel structures */
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = other_channel[i];
+ if (channel && channel->type->copy) {
+ ef4_fini_napi_channel(channel);
+ ef4_remove_channel(channel);
+ kfree(channel);
+ }
+ }
+
+ rc2 = ef4_soft_enable_interrupts(efx);
+ if (rc2) {
+ rc = rc ? rc : rc2;
+ netif_err(efx, drv, efx->net_dev,
+ "unable to restart interrupts on channel reallocation\n");
+ ef4_schedule_reset(efx, RESET_TYPE_DISABLE);
+ } else {
+ ef4_start_all(efx);
+ netif_device_attach(efx->net_dev);
+ }
+ return rc;
+
+rollback:
+ /* Swap back */
+ efx->rxq_entries = old_rxq_entries;
+ efx->txq_entries = old_txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+ goto out;
+}
+
+void ef4_schedule_slow_fill(struct ef4_rx_queue *rx_queue)
+{
+ mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
+}
+
+static const struct ef4_channel_type ef4_default_channel_type = {
+ .pre_probe = ef4_channel_dummy_op_int,
+ .post_remove = ef4_channel_dummy_op_void,
+ .get_name = ef4_get_channel_name,
+ .copy = ef4_copy_channel,
+ .keep_eventq = false,
+};
+
+int ef4_channel_dummy_op_int(struct ef4_channel *channel)
+{
+ return 0;
+}
+
+void ef4_channel_dummy_op_void(struct ef4_channel *channel)
+{
+}
+
+/**************************************************************************
+ *
+ * Port handling
+ *
+ **************************************************************************/
+
+/* This ensures that the kernel is kept informed (via
+ * netif_carrier_on/off) of the link status, and also maintains the
+ * link status's stop on the port's TX queue.
+ */
+void ef4_link_status_changed(struct ef4_nic *efx)
+{
+ struct ef4_link_state *link_state = &efx->link_state;
+
+ /* SFC Bug 5356: A net_dev notifier is registered, so we must ensure
+ * that no events are triggered between unregister_netdev() and the
+ * driver unloading. A more general condition is that NETDEV_CHANGE
+ * can only be generated between NETDEV_UP and NETDEV_DOWN */
+ if (!netif_running(efx->net_dev))
+ return;
+
+ if (link_state->up != netif_carrier_ok(efx->net_dev)) {
+ efx->n_link_state_changes++;
+
+ if (link_state->up)
+ netif_carrier_on(efx->net_dev);
+ else
+ netif_carrier_off(efx->net_dev);
+ }
+
+ /* Status message for kernel log */
+ if (link_state->up)
+ netif_info(efx, link, efx->net_dev,
+ "link up at %uMbps %s-duplex (MTU %d)\n",
+ link_state->speed, link_state->fd ? "full" : "half",
+ efx->net_dev->mtu);
+ else
+ netif_info(efx, link, efx->net_dev, "link down\n");
+}
+
+void ef4_link_set_advertising(struct ef4_nic *efx, u32 advertising)
+{
+ efx->link_advertising = advertising;
+ if (advertising) {
+ if (advertising & ADVERTISED_Pause)
+ efx->wanted_fc |= (EF4_FC_TX | EF4_FC_RX);
+ else
+ efx->wanted_fc &= ~(EF4_FC_TX | EF4_FC_RX);
+ if (advertising & ADVERTISED_Asym_Pause)
+ efx->wanted_fc ^= EF4_FC_TX;
+ }
+}
+
+void ef4_link_set_wanted_fc(struct ef4_nic *efx, u8 wanted_fc)
+{
+ efx->wanted_fc = wanted_fc;
+ if (efx->link_advertising) {
+ if (wanted_fc & EF4_FC_RX)
+ efx->link_advertising |= (ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause);
+ else
+ efx->link_advertising &= ~(ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause);
+ if (wanted_fc & EF4_FC_TX)
+ efx->link_advertising ^= ADVERTISED_Asym_Pause;
+ }
+}
+
+static void ef4_fini_port(struct ef4_nic *efx);
+
+/* We assume that efx->type->reconfigure_mac will always try to sync RX
+ * filters and therefore needs to read-lock the filter table against freeing
+ */
+void ef4_mac_reconfigure(struct ef4_nic *efx)
+{
+ down_read(&efx->filter_sem);
+ efx->type->reconfigure_mac(efx);
+ up_read(&efx->filter_sem);
+}
+
+/* Push loopback/power/transmit disable settings to the PHY, and reconfigure
+ * the MAC appropriately. All other PHY configuration changes are pushed
+ * through phy_op->set_settings(), and pushed asynchronously to the MAC
+ * through ef4_monitor().
+ *
+ * Callers must hold the mac_lock
+ */
+int __ef4_reconfigure_port(struct ef4_nic *efx)
+{
+ enum ef4_phy_mode phy_mode;
+ int rc;
+
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+ /* Disable PHY transmit in mac level loopbacks */
+ phy_mode = efx->phy_mode;
+ if (LOOPBACK_INTERNAL(efx))
+ efx->phy_mode |= PHY_MODE_TX_DISABLED;
+ else
+ efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
+
+ rc = efx->type->reconfigure_port(efx);
+
+ if (rc)
+ efx->phy_mode = phy_mode;
+
+ return rc;
+}
+
+/* Reinitialise the MAC to pick up new PHY settings, even if the port is
+ * disabled. */
+int ef4_reconfigure_port(struct ef4_nic *efx)
+{
+ int rc;
+
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ mutex_lock(&efx->mac_lock);
+ rc = __ef4_reconfigure_port(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ return rc;
+}
+
+/* Asynchronous work item for changing MAC promiscuity and multicast
+ * hash. Avoid a drain/rx_ingress enable by reconfiguring the current
+ * MAC directly. */
+static void ef4_mac_work(struct work_struct *data)
+{
+ struct ef4_nic *efx = container_of(data, struct ef4_nic, mac_work);
+
+ mutex_lock(&efx->mac_lock);
+ if (efx->port_enabled)
+ ef4_mac_reconfigure(efx);
+ mutex_unlock(&efx->mac_lock);
+}
+
+static int ef4_probe_port(struct ef4_nic *efx)
+{
+ int rc;
+
+ netif_dbg(efx, probe, efx->net_dev, "create port\n");
+
+ if (phy_flash_cfg)
+ efx->phy_mode = PHY_MODE_SPECIAL;
+
+ /* Connect up MAC/PHY operations table */
+ rc = efx->type->probe_port(efx);
+ if (rc)
+ return rc;
+
+ /* Initialise MAC address to permanent address */
+ ether_addr_copy(efx->net_dev->dev_addr, efx->net_dev->perm_addr);
+
+ return 0;
+}
+
+static int ef4_init_port(struct ef4_nic *efx)
+{
+ int rc;
+
+ netif_dbg(efx, drv, efx->net_dev, "init port\n");
+
+ mutex_lock(&efx->mac_lock);
+
+ rc = efx->phy_op->init(efx);
+ if (rc)
+ goto fail1;
+
+ efx->port_initialized = true;
+
+ /* Reconfigure the MAC before creating dma queues (required for
+ * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
+ ef4_mac_reconfigure(efx);
+
+ /* Ensure the PHY advertises the correct flow control settings */
+ rc = efx->phy_op->reconfigure(efx);
+ if (rc && rc != -EPERM)
+ goto fail2;
+
+ mutex_unlock(&efx->mac_lock);
+ return 0;
+
+fail2:
+ efx->phy_op->fini(efx);
+fail1:
+ mutex_unlock(&efx->mac_lock);
+ return rc;
+}
+
+static void ef4_start_port(struct ef4_nic *efx)
+{
+ netif_dbg(efx, ifup, efx->net_dev, "start port\n");
+ BUG_ON(efx->port_enabled);
+
+ mutex_lock(&efx->mac_lock);
+ efx->port_enabled = true;
+
+ /* Ensure MAC ingress/egress is enabled */
+ ef4_mac_reconfigure(efx);
+
+ mutex_unlock(&efx->mac_lock);
+}
+
+/* Cancel work for MAC reconfiguration, periodic hardware monitoring
+ * and the async self-test, wait for them to finish and prevent them
+ * being scheduled again. This doesn't cover online resets, which
+ * should only be cancelled when removing the device.
+ */
+static void ef4_stop_port(struct ef4_nic *efx)
+{
+ netif_dbg(efx, ifdown, efx->net_dev, "stop port\n");
+
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ mutex_lock(&efx->mac_lock);
+ efx->port_enabled = false;
+ mutex_unlock(&efx->mac_lock);
+
+ /* Serialise against ef4_set_multicast_list() */
+ netif_addr_lock_bh(efx->net_dev);
+ netif_addr_unlock_bh(efx->net_dev);
+
+ cancel_delayed_work_sync(&efx->monitor_work);
+ ef4_selftest_async_cancel(efx);
+ cancel_work_sync(&efx->mac_work);
+}
+
+static void ef4_fini_port(struct ef4_nic *efx)
+{
+ netif_dbg(efx, drv, efx->net_dev, "shut down port\n");
+
+ if (!efx->port_initialized)
+ return;
+
+ efx->phy_op->fini(efx);
+ efx->port_initialized = false;
+
+ efx->link_state.up = false;
+ ef4_link_status_changed(efx);
+}
+
+static void ef4_remove_port(struct ef4_nic *efx)
+{
+ netif_dbg(efx, drv, efx->net_dev, "destroying port\n");
+
+ efx->type->remove_port(efx);
+}
+
+/**************************************************************************
+ *
+ * NIC handling
+ *
+ **************************************************************************/
+
+static LIST_HEAD(ef4_primary_list);
+static LIST_HEAD(ef4_unassociated_list);
+
+static bool ef4_same_controller(struct ef4_nic *left, struct ef4_nic *right)
+{
+ return left->type == right->type &&
+ left->vpd_sn && right->vpd_sn &&
+ !strcmp(left->vpd_sn, right->vpd_sn);
+}
+
+static void ef4_associate(struct ef4_nic *efx)
+{
+ struct ef4_nic *other, *next;
+
+ if (efx->primary == efx) {
+ /* Adding primary function; look for secondaries */
+
+ netif_dbg(efx, probe, efx->net_dev, "adding to primary list\n");
+ list_add_tail(&efx->node, &ef4_primary_list);
+
+ list_for_each_entry_safe(other, next, &ef4_unassociated_list,
+ node) {
+ if (ef4_same_controller(efx, other)) {
+ list_del(&other->node);
+ netif_dbg(other, probe, other->net_dev,
+ "moving to secondary list of %s %s\n",
+ pci_name(efx->pci_dev),
+ efx->net_dev->name);
+ list_add_tail(&other->node,
+ &efx->secondary_list);
+ other->primary = efx;
+ }
+ }
+ } else {
+ /* Adding secondary function; look for primary */
+
+ list_for_each_entry(other, &ef4_primary_list, node) {
+ if (ef4_same_controller(efx, other)) {
+ netif_dbg(efx, probe, efx->net_dev,
+ "adding to secondary list of %s %s\n",
+ pci_name(other->pci_dev),
+ other->net_dev->name);
+ list_add_tail(&efx->node,
+ &other->secondary_list);
+ efx->primary = other;
+ return;
+ }
+ }
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "adding to unassociated list\n");
+ list_add_tail(&efx->node, &ef4_unassociated_list);
+ }
+}
+
+static void ef4_dissociate(struct ef4_nic *efx)
+{
+ struct ef4_nic *other, *next;
+
+ list_del(&efx->node);
+ efx->primary = NULL;
+
+ list_for_each_entry_safe(other, next, &efx->secondary_list, node) {
+ list_del(&other->node);
+ netif_dbg(other, probe, other->net_dev,
+ "moving to unassociated list\n");
+ list_add_tail(&other->node, &ef4_unassociated_list);
+ other->primary = NULL;
+ }
+}
+
+/* This configures the PCI device to enable I/O and DMA. */
+static int ef4_init_io(struct ef4_nic *efx)
+{
+ struct pci_dev *pci_dev = efx->pci_dev;
+ dma_addr_t dma_mask = efx->type->max_dma_mask;
+ unsigned int mem_map_size = efx->type->mem_map_size(efx);
+ int rc, bar;
+
+ netif_dbg(efx, probe, efx->net_dev, "initialising I/O\n");
+
+ bar = efx->type->mem_bar;
+
+ rc = pci_enable_device(pci_dev);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to enable PCI device\n");
+ goto fail1;
+ }
+
+ pci_set_master(pci_dev);
+
+ /* Set the PCI DMA mask. Try all possibilities from our
+ * genuine mask down to 32 bits, because some architectures
+ * (e.g. x86_64 with iommu_sac_force set) will allow 40 bit
+ * masks event though they reject 46 bit masks.
+ */
+ while (dma_mask > 0x7fffffffUL) {
+ rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
+ if (rc == 0)
+ break;
+ dma_mask >>= 1;
+ }
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "could not find a suitable DMA mask\n");
+ goto fail2;
+ }
+ netif_dbg(efx, probe, efx->net_dev,
+ "using DMA mask %llx\n", (unsigned long long) dma_mask);
+
+ efx->membase_phys = pci_resource_start(efx->pci_dev, bar);
+ rc = pci_request_region(pci_dev, bar, "sfc");
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "request for memory BAR failed\n");
+ rc = -EIO;
+ goto fail3;
+ }
+ efx->membase = ioremap_nocache(efx->membase_phys, mem_map_size);
+ if (!efx->membase) {
+ netif_err(efx, probe, efx->net_dev,
+ "could not map memory BAR at %llx+%x\n",
+ (unsigned long long)efx->membase_phys, mem_map_size);
+ rc = -ENOMEM;
+ goto fail4;
+ }
+ netif_dbg(efx, probe, efx->net_dev,
+ "memory BAR at %llx+%x (virtual %p)\n",
+ (unsigned long long)efx->membase_phys, mem_map_size,
+ efx->membase);
+
+ return 0;
+
+ fail4:
+ pci_release_region(efx->pci_dev, bar);
+ fail3:
+ efx->membase_phys = 0;
+ fail2:
+ pci_disable_device(efx->pci_dev);
+ fail1:
+ return rc;
+}
+
+static void ef4_fini_io(struct ef4_nic *efx)
+{
+ int bar;
+
+ netif_dbg(efx, drv, efx->net_dev, "shutting down I/O\n");
+
+ if (efx->membase) {
+ iounmap(efx->membase);
+ efx->membase = NULL;
+ }
+
+ if (efx->membase_phys) {
+ bar = efx->type->mem_bar;
+ pci_release_region(efx->pci_dev, bar);
+ efx->membase_phys = 0;
+ }
+
+ /* Don't disable bus-mastering if VFs are assigned */
+ if (!pci_vfs_assigned(efx->pci_dev))
+ pci_disable_device(efx->pci_dev);
+}
+
+void ef4_set_default_rx_indir_table(struct ef4_nic *efx)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
+ efx->rx_indir_table[i] =
+ ethtool_rxfh_indir_default(i, efx->rss_spread);
+}
+
+static unsigned int ef4_wanted_parallelism(struct ef4_nic *efx)
+{
+ cpumask_var_t thread_mask;
+ unsigned int count;
+ int cpu;
+
+ if (rss_cpus) {
+ count = rss_cpus;
+ } else {
+ if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) {
+ netif_warn(efx, probe, efx->net_dev,
+ "RSS disabled due to allocation failure\n");
+ return 1;
+ }
+
+ count = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpumask_test_cpu(cpu, thread_mask)) {
+ ++count;
+ cpumask_or(thread_mask, thread_mask,
+ topology_sibling_cpumask(cpu));
+ }
+ }
+
+ free_cpumask_var(thread_mask);
+ }
+
+ return count;
+}
+
+/* Probe the number and type of interrupts we are able to obtain, and
+ * the resulting numbers of channels and RX queues.
+ */
+static int ef4_probe_interrupts(struct ef4_nic *efx)
+{
+ unsigned int extra_channels = 0;
+ unsigned int i, j;
+ int rc;
+
+ for (i = 0; i < EF4_MAX_EXTRA_CHANNELS; i++)
+ if (efx->extra_channel_type[i])
+ ++extra_channels;
+
+ if (efx->interrupt_mode == EF4_INT_MODE_MSIX) {
+ struct msix_entry xentries[EF4_MAX_CHANNELS];
+ unsigned int n_channels;
+
+ n_channels = ef4_wanted_parallelism(efx);
+ if (ef4_separate_tx_channels)
+ n_channels *= 2;
+ n_channels += extra_channels;
+ n_channels = min(n_channels, efx->max_channels);
+
+ for (i = 0; i < n_channels; i++)
+ xentries[i].entry = i;
+ rc = pci_enable_msix_range(efx->pci_dev,
+ xentries, 1, n_channels);
+ if (rc < 0) {
+ /* Fall back to single channel MSI */
+ efx->interrupt_mode = EF4_INT_MODE_MSI;
+ netif_err(efx, drv, efx->net_dev,
+ "could not enable MSI-X\n");
+ } else if (rc < n_channels) {
+ netif_err(efx, drv, efx->net_dev,
+ "WARNING: Insufficient MSI-X vectors"
+ " available (%d < %u).\n", rc, n_channels);
+ netif_err(efx, drv, efx->net_dev,
+ "WARNING: Performance may be reduced.\n");
+ n_channels = rc;
+ }
+
+ if (rc > 0) {
+ efx->n_channels = n_channels;
+ if (n_channels > extra_channels)
+ n_channels -= extra_channels;
+ if (ef4_separate_tx_channels) {
+ efx->n_tx_channels = min(max(n_channels / 2,
+ 1U),
+ efx->max_tx_channels);
+ efx->n_rx_channels = max(n_channels -
+ efx->n_tx_channels,
+ 1U);
+ } else {
+ efx->n_tx_channels = min(n_channels,
+ efx->max_tx_channels);
+ efx->n_rx_channels = n_channels;
+ }
+ for (i = 0; i < efx->n_channels; i++)
+ ef4_get_channel(efx, i)->irq =
+ xentries[i].vector;
+ }
+ }
+
+ /* Try single interrupt MSI */
+ if (efx->interrupt_mode == EF4_INT_MODE_MSI) {
+ efx->n_channels = 1;
+ efx->n_rx_channels = 1;
+ efx->n_tx_channels = 1;
+ rc = pci_enable_msi(efx->pci_dev);
+ if (rc == 0) {
+ ef4_get_channel(efx, 0)->irq = efx->pci_dev->irq;
+ } else {
+ netif_err(efx, drv, efx->net_dev,
+ "could not enable MSI\n");
+ efx->interrupt_mode = EF4_INT_MODE_LEGACY;
+ }
+ }
+
+ /* Assume legacy interrupts */
+ if (efx->interrupt_mode == EF4_INT_MODE_LEGACY) {
+ efx->n_channels = 1 + (ef4_separate_tx_channels ? 1 : 0);
+ efx->n_rx_channels = 1;
+ efx->n_tx_channels = 1;
+ efx->legacy_irq = efx->pci_dev->irq;
+ }
+
+ /* Assign extra channels if possible */
+ j = efx->n_channels;
+ for (i = 0; i < EF4_MAX_EXTRA_CHANNELS; i++) {
+ if (!efx->extra_channel_type[i])
+ continue;
+ if (efx->interrupt_mode != EF4_INT_MODE_MSIX ||
+ efx->n_channels <= extra_channels) {
+ efx->extra_channel_type[i]->handle_no_channel(efx);
+ } else {
+ --j;
+ ef4_get_channel(efx, j)->type =
+ efx->extra_channel_type[i];
+ }
+ }
+
+ efx->rss_spread = efx->n_rx_channels;
+
+ return 0;
+}
+
+static int ef4_soft_enable_interrupts(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel, *end_channel;
+ int rc;
+
+ BUG_ON(efx->state == STATE_DISABLED);
+
+ efx->irq_soft_enabled = true;
+ smp_wmb();
+
+ ef4_for_each_channel(channel, efx) {
+ if (!channel->type->keep_eventq) {
+ rc = ef4_init_eventq(channel);
+ if (rc)
+ goto fail;
+ }
+ ef4_start_eventq(channel);
+ }
+
+ return 0;
+fail:
+ end_channel = channel;
+ ef4_for_each_channel(channel, efx) {
+ if (channel == end_channel)
+ break;
+ ef4_stop_eventq(channel);
+ if (!channel->type->keep_eventq)
+ ef4_fini_eventq(channel);
+ }
+
+ return rc;
+}
+
+static void ef4_soft_disable_interrupts(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ if (efx->state == STATE_DISABLED)
+ return;
+
+ efx->irq_soft_enabled = false;
+ smp_wmb();
+
+ if (efx->legacy_irq)
+ synchronize_irq(efx->legacy_irq);
+
+ ef4_for_each_channel(channel, efx) {
+ if (channel->irq)
+ synchronize_irq(channel->irq);
+
+ ef4_stop_eventq(channel);
+ if (!channel->type->keep_eventq)
+ ef4_fini_eventq(channel);
+ }
+}
+
+static int ef4_enable_interrupts(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel, *end_channel;
+ int rc;
+
+ BUG_ON(efx->state == STATE_DISABLED);
+
+ if (efx->eeh_disabled_legacy_irq) {
+ enable_irq(efx->legacy_irq);
+ efx->eeh_disabled_legacy_irq = false;
+ }
+
+ efx->type->irq_enable_master(efx);
+
+ ef4_for_each_channel(channel, efx) {
+ if (channel->type->keep_eventq) {
+ rc = ef4_init_eventq(channel);
+ if (rc)
+ goto fail;
+ }
+ }
+
+ rc = ef4_soft_enable_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ return 0;
+
+fail:
+ end_channel = channel;
+ ef4_for_each_channel(channel, efx) {
+ if (channel == end_channel)
+ break;
+ if (channel->type->keep_eventq)
+ ef4_fini_eventq(channel);
+ }
+
+ efx->type->irq_disable_non_ev(efx);
+
+ return rc;
+}
+
+static void ef4_disable_interrupts(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_soft_disable_interrupts(efx);
+
+ ef4_for_each_channel(channel, efx) {
+ if (channel->type->keep_eventq)
+ ef4_fini_eventq(channel);
+ }
+
+ efx->type->irq_disable_non_ev(efx);
+}
+
+static void ef4_remove_interrupts(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ /* Remove MSI/MSI-X interrupts */
+ ef4_for_each_channel(channel, efx)
+ channel->irq = 0;
+ pci_disable_msi(efx->pci_dev);
+ pci_disable_msix(efx->pci_dev);
+
+ /* Remove legacy interrupt */
+ efx->legacy_irq = 0;
+}
+
+static void ef4_set_channels(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+
+ efx->tx_channel_offset =
+ ef4_separate_tx_channels ?
+ efx->n_channels - efx->n_tx_channels : 0;
+
+ /* We need to mark which channels really have RX and TX
+ * queues, and adjust the TX queue numbers if we have separate
+ * RX-only and TX-only channels.
+ */
+ ef4_for_each_channel(channel, efx) {
+ if (channel->channel < efx->n_rx_channels)
+ channel->rx_queue.core_index = channel->channel;
+ else
+ channel->rx_queue.core_index = -1;
+
+ ef4_for_each_channel_tx_queue(tx_queue, channel)
+ tx_queue->queue -= (efx->tx_channel_offset *
+ EF4_TXQ_TYPES);
+ }
+}
+
+static int ef4_probe_nic(struct ef4_nic *efx)
+{
+ int rc;
+
+ netif_dbg(efx, probe, efx->net_dev, "creating NIC\n");
+
+ /* Carry out hardware-type specific initialisation */
+ rc = efx->type->probe(efx);
+ if (rc)
+ return rc;
+
+ do {
+ if (!efx->max_channels || !efx->max_tx_channels) {
+ netif_err(efx, drv, efx->net_dev,
+ "Insufficient resources to allocate"
+ " any channels\n");
+ rc = -ENOSPC;
+ goto fail1;
+ }
+
+ /* Determine the number of channels and queues by trying
+ * to hook in MSI-X interrupts.
+ */
+ rc = ef4_probe_interrupts(efx);
+ if (rc)
+ goto fail1;
+
+ ef4_set_channels(efx);
+
+ /* dimension_resources can fail with EAGAIN */
+ rc = efx->type->dimension_resources(efx);
+ if (rc != 0 && rc != -EAGAIN)
+ goto fail2;
+
+ if (rc == -EAGAIN)
+ /* try again with new max_channels */
+ ef4_remove_interrupts(efx);
+
+ } while (rc == -EAGAIN);
+
+ if (efx->n_channels > 1)
+ netdev_rss_key_fill(&efx->rx_hash_key,
+ sizeof(efx->rx_hash_key));
+ ef4_set_default_rx_indir_table(efx);
+
+ netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
+ netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
+
+ /* Initialise the interrupt moderation settings */
+ efx->irq_mod_step_us = DIV_ROUND_UP(efx->timer_quantum_ns, 1000);
+ ef4_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true,
+ true);
+
+ return 0;
+
+fail2:
+ ef4_remove_interrupts(efx);
+fail1:
+ efx->type->remove(efx);
+ return rc;
+}
+
+static void ef4_remove_nic(struct ef4_nic *efx)
+{
+ netif_dbg(efx, drv, efx->net_dev, "destroying NIC\n");
+
+ ef4_remove_interrupts(efx);
+ efx->type->remove(efx);
+}
+
+static int ef4_probe_filters(struct ef4_nic *efx)
+{
+ int rc;
+
+ spin_lock_init(&efx->filter_lock);
+ init_rwsem(&efx->filter_sem);
+ mutex_lock(&efx->mac_lock);
+ down_write(&efx->filter_sem);
+ rc = efx->type->filter_table_probe(efx);
+ if (rc)
+ goto out_unlock;
+
+#ifdef CONFIG_RFS_ACCEL
+ if (efx->type->offload_features & NETIF_F_NTUPLE) {
+ struct ef4_channel *channel;
+ int i, success = 1;
+
+ ef4_for_each_channel(channel, efx) {
+ channel->rps_flow_id =
+ kcalloc(efx->type->max_rx_ip_filters,
+ sizeof(*channel->rps_flow_id),
+ GFP_KERNEL);
+ if (!channel->rps_flow_id)
+ success = 0;
+ else
+ for (i = 0;
+ i < efx->type->max_rx_ip_filters;
+ ++i)
+ channel->rps_flow_id[i] =
+ RPS_FLOW_ID_INVALID;
+ }
+
+ if (!success) {
+ ef4_for_each_channel(channel, efx)
+ kfree(channel->rps_flow_id);
+ efx->type->filter_table_remove(efx);
+ rc = -ENOMEM;
+ goto out_unlock;
+ }
+
+ efx->rps_expire_index = efx->rps_expire_channel = 0;
+ }
+#endif
+out_unlock:
+ up_write(&efx->filter_sem);
+ mutex_unlock(&efx->mac_lock);
+ return rc;
+}
+
+static void ef4_remove_filters(struct ef4_nic *efx)
+{
+#ifdef CONFIG_RFS_ACCEL
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ kfree(channel->rps_flow_id);
+#endif
+ down_write(&efx->filter_sem);
+ efx->type->filter_table_remove(efx);
+ up_write(&efx->filter_sem);
+}
+
+static void ef4_restore_filters(struct ef4_nic *efx)
+{
+ down_read(&efx->filter_sem);
+ efx->type->filter_table_restore(efx);
+ up_read(&efx->filter_sem);
+}
+
+/**************************************************************************
+ *
+ * NIC startup/shutdown
+ *
+ *************************************************************************/
+
+static int ef4_probe_all(struct ef4_nic *efx)
+{
+ int rc;
+
+ rc = ef4_probe_nic(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev, "failed to create NIC\n");
+ goto fail1;
+ }
+
+ rc = ef4_probe_port(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev, "failed to create port\n");
+ goto fail2;
+ }
+
+ BUILD_BUG_ON(EF4_DEFAULT_DMAQ_SIZE < EF4_RXQ_MIN_ENT);
+ if (WARN_ON(EF4_DEFAULT_DMAQ_SIZE < EF4_TXQ_MIN_ENT(efx))) {
+ rc = -EINVAL;
+ goto fail3;
+ }
+ efx->rxq_entries = efx->txq_entries = EF4_DEFAULT_DMAQ_SIZE;
+
+ rc = ef4_probe_filters(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create filter tables\n");
+ goto fail4;
+ }
+
+ rc = ef4_probe_channels(efx);
+ if (rc)
+ goto fail5;
+
+ return 0;
+
+ fail5:
+ ef4_remove_filters(efx);
+ fail4:
+ fail3:
+ ef4_remove_port(efx);
+ fail2:
+ ef4_remove_nic(efx);
+ fail1:
+ return rc;
+}
+
+/* If the interface is supposed to be running but is not, start
+ * the hardware and software data path, regular activity for the port
+ * (MAC statistics, link polling, etc.) and schedule the port to be
+ * reconfigured. Interrupts must already be enabled. This function
+ * is safe to call multiple times, so long as the NIC is not disabled.
+ * Requires the RTNL lock.
+ */
+static void ef4_start_all(struct ef4_nic *efx)
+{
+ EF4_ASSERT_RESET_SERIALISED(efx);
+ BUG_ON(efx->state == STATE_DISABLED);
+
+ /* Check that it is appropriate to restart the interface. All
+ * of these flags are safe to read under just the rtnl lock */
+ if (efx->port_enabled || !netif_running(efx->net_dev) ||
+ efx->reset_pending)
+ return;
+
+ ef4_start_port(efx);
+ ef4_start_datapath(efx);
+
+ /* Start the hardware monitor if there is one */
+ if (efx->type->monitor != NULL)
+ queue_delayed_work(efx->workqueue, &efx->monitor_work,
+ ef4_monitor_interval);
+
+ efx->type->start_stats(efx);
+ efx->type->pull_stats(efx);
+ spin_lock_bh(&efx->stats_lock);
+ efx->type->update_stats(efx, NULL, NULL);
+ spin_unlock_bh(&efx->stats_lock);
+}
+
+/* Quiesce the hardware and software data path, and regular activity
+ * for the port without bringing the link down. Safe to call multiple
+ * times with the NIC in almost any state, but interrupts should be
+ * enabled. Requires the RTNL lock.
+ */
+static void ef4_stop_all(struct ef4_nic *efx)
+{
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ /* port_enabled can be read safely under the rtnl lock */
+ if (!efx->port_enabled)
+ return;
+
+ /* update stats before we go down so we can accurately count
+ * rx_nodesc_drops
+ */
+ efx->type->pull_stats(efx);
+ spin_lock_bh(&efx->stats_lock);
+ efx->type->update_stats(efx, NULL, NULL);
+ spin_unlock_bh(&efx->stats_lock);
+ efx->type->stop_stats(efx);
+ ef4_stop_port(efx);
+
+ /* Stop the kernel transmit interface. This is only valid if
+ * the device is stopped or detached; otherwise the watchdog
+ * may fire immediately.
+ */
+ WARN_ON(netif_running(efx->net_dev) &&
+ netif_device_present(efx->net_dev));
+ netif_tx_disable(efx->net_dev);
+
+ ef4_stop_datapath(efx);
+}
+
+static void ef4_remove_all(struct ef4_nic *efx)
+{
+ ef4_remove_channels(efx);
+ ef4_remove_filters(efx);
+ ef4_remove_port(efx);
+ ef4_remove_nic(efx);
+}
+
+/**************************************************************************
+ *
+ * Interrupt moderation
+ *
+ **************************************************************************/
+unsigned int ef4_usecs_to_ticks(struct ef4_nic *efx, unsigned int usecs)
+{
+ if (usecs == 0)
+ return 0;
+ if (usecs * 1000 < efx->timer_quantum_ns)
+ return 1; /* never round down to 0 */
+ return usecs * 1000 / efx->timer_quantum_ns;
+}
+
+unsigned int ef4_ticks_to_usecs(struct ef4_nic *efx, unsigned int ticks)
+{
+ /* We must round up when converting ticks to microseconds
+ * because we round down when converting the other way.
+ */
+ return DIV_ROUND_UP(ticks * efx->timer_quantum_ns, 1000);
+}
+
+/* Set interrupt moderation parameters */
+int ef4_init_irq_moderation(struct ef4_nic *efx, unsigned int tx_usecs,
+ unsigned int rx_usecs, bool rx_adaptive,
+ bool rx_may_override_tx)
+{
+ struct ef4_channel *channel;
+ unsigned int timer_max_us;
+
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ timer_max_us = efx->timer_max_ns / 1000;
+
+ if (tx_usecs > timer_max_us || rx_usecs > timer_max_us)
+ return -EINVAL;
+
+ if (tx_usecs != rx_usecs && efx->tx_channel_offset == 0 &&
+ !rx_may_override_tx) {
+ netif_err(efx, drv, efx->net_dev, "Channels are shared. "
+ "RX and TX IRQ moderation must be equal\n");
+ return -EINVAL;
+ }
+
+ efx->irq_rx_adaptive = rx_adaptive;
+ efx->irq_rx_moderation_us = rx_usecs;
+ ef4_for_each_channel(channel, efx) {
+ if (ef4_channel_has_rx_queue(channel))
+ channel->irq_moderation_us = rx_usecs;
+ else if (ef4_channel_has_tx_queues(channel))
+ channel->irq_moderation_us = tx_usecs;
+ }
+
+ return 0;
+}
+
+void ef4_get_irq_moderation(struct ef4_nic *efx, unsigned int *tx_usecs,
+ unsigned int *rx_usecs, bool *rx_adaptive)
+{
+ *rx_adaptive = efx->irq_rx_adaptive;
+ *rx_usecs = efx->irq_rx_moderation_us;
+
+ /* If channels are shared between RX and TX, so is IRQ
+ * moderation. Otherwise, IRQ moderation is the same for all
+ * TX channels and is not adaptive.
+ */
+ if (efx->tx_channel_offset == 0) {
+ *tx_usecs = *rx_usecs;
+ } else {
+ struct ef4_channel *tx_channel;
+
+ tx_channel = efx->channel[efx->tx_channel_offset];
+ *tx_usecs = tx_channel->irq_moderation_us;
+ }
+}
+
+/**************************************************************************
+ *
+ * Hardware monitor
+ *
+ **************************************************************************/
+
+/* Run periodically off the general workqueue */
+static void ef4_monitor(struct work_struct *data)
+{
+ struct ef4_nic *efx = container_of(data, struct ef4_nic,
+ monitor_work.work);
+
+ netif_vdbg(efx, timer, efx->net_dev,
+ "hardware monitor executing on CPU %d\n",
+ raw_smp_processor_id());
+ BUG_ON(efx->type->monitor == NULL);
+
+ /* If the mac_lock is already held then it is likely a port
+ * reconfiguration is already in place, which will likely do
+ * most of the work of monitor() anyway. */
+ if (mutex_trylock(&efx->mac_lock)) {
+ if (efx->port_enabled)
+ efx->type->monitor(efx);
+ mutex_unlock(&efx->mac_lock);
+ }
+
+ queue_delayed_work(efx->workqueue, &efx->monitor_work,
+ ef4_monitor_interval);
+}
+
+/**************************************************************************
+ *
+ * ioctls
+ *
+ *************************************************************************/
+
+/* Net device ioctl
+ * Context: process, rtnl_lock() held.
+ */
+static int ef4_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+
+ /* Convert phy_id from older PRTAD/DEVAD format */
+ if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
+ (data->phy_id & 0xfc00) == 0x0400)
+ data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400;
+
+ return mdio_mii_ioctl(&efx->mdio, data, cmd);
+}
+
+/**************************************************************************
+ *
+ * NAPI interface
+ *
+ **************************************************************************/
+
+static void ef4_init_napi_channel(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+
+ channel->napi_dev = efx->net_dev;
+ netif_napi_add(channel->napi_dev, &channel->napi_str,
+ ef4_poll, napi_weight);
+ ef4_channel_busy_poll_init(channel);
+}
+
+static void ef4_init_napi(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ ef4_init_napi_channel(channel);
+}
+
+static void ef4_fini_napi_channel(struct ef4_channel *channel)
+{
+ if (channel->napi_dev)
+ netif_napi_del(&channel->napi_str);
+
+ channel->napi_dev = NULL;
+}
+
+static void ef4_fini_napi(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ ef4_fini_napi_channel(channel);
+}
+
+/**************************************************************************
+ *
+ * Kernel netpoll interface
+ *
+ *************************************************************************/
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/* Although in the common case interrupts will be disabled, this is not
+ * guaranteed. However, all our work happens inside the NAPI callback,
+ * so no locking is required.
+ */
+static void ef4_netpoll(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ ef4_schedule_channel(channel);
+}
+
+#endif
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static int ef4_busy_poll(struct napi_struct *napi)
+{
+ struct ef4_channel *channel =
+ container_of(napi, struct ef4_channel, napi_str);
+ struct ef4_nic *efx = channel->efx;
+ int budget = 4;
+ int old_rx_packets, rx_packets;
+
+ if (!netif_running(efx->net_dev))
+ return LL_FLUSH_FAILED;
+
+ if (!ef4_channel_try_lock_poll(channel))
+ return LL_FLUSH_BUSY;
+
+ old_rx_packets = channel->rx_queue.rx_packets;
+ ef4_process_channel(channel, budget);
+
+ rx_packets = channel->rx_queue.rx_packets - old_rx_packets;
+
+ /* There is no race condition with NAPI here.
+ * NAPI will automatically be rescheduled if it yielded during busy
+ * polling, because it was not able to take the lock and thus returned
+ * the full budget.
+ */
+ ef4_channel_unlock_poll(channel);
+
+ return rx_packets;
+}
+#endif
+
+/**************************************************************************
+ *
+ * Kernel net device interface
+ *
+ *************************************************************************/
+
+/* Context: process, rtnl_lock() held. */
+int ef4_net_open(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int rc;
+
+ netif_dbg(efx, ifup, efx->net_dev, "opening device on CPU %d\n",
+ raw_smp_processor_id());
+
+ rc = ef4_check_disabled(efx);
+ if (rc)
+ return rc;
+ if (efx->phy_mode & PHY_MODE_SPECIAL)
+ return -EBUSY;
+
+ /* Notify the kernel of the link state polled during driver load,
+ * before the monitor starts running */
+ ef4_link_status_changed(efx);
+
+ ef4_start_all(efx);
+ ef4_selftest_async_start(efx);
+ return 0;
+}
+
+/* Context: process, rtnl_lock() held.
+ * Note that the kernel will ignore our return code; this method
+ * should really be a void.
+ */
+int ef4_net_stop(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
+ raw_smp_processor_id());
+
+ /* Stop the device and flush all the channels */
+ ef4_stop_all(efx);
+
+ return 0;
+}
+
+/* Context: process, dev_base_lock or RTNL held, non-blocking. */
+static struct rtnl_link_stats64 *ef4_net_stats(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ spin_lock_bh(&efx->stats_lock);
+ efx->type->update_stats(efx, NULL, stats);
+ spin_unlock_bh(&efx->stats_lock);
+
+ return stats;
+}
+
+/* Context: netif_tx_lock held, BHs disabled. */
+static void ef4_watchdog(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX stuck with port_enabled=%d: resetting channels\n",
+ efx->port_enabled);
+
+ ef4_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
+}
+
+
+/* Context: process, rtnl_lock() held. */
+static int ef4_change_mtu(struct net_device *net_dev, int new_mtu)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int rc;
+
+ rc = ef4_check_disabled(efx);
+ if (rc)
+ return rc;
+
+ netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
+
+ ef4_device_detach_sync(efx);
+ ef4_stop_all(efx);
+
+ mutex_lock(&efx->mac_lock);
+ net_dev->mtu = new_mtu;
+ ef4_mac_reconfigure(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ ef4_start_all(efx);
+ netif_device_attach(efx->net_dev);
+ return 0;
+}
+
+static int ef4_set_mac_address(struct net_device *net_dev, void *data)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct sockaddr *addr = data;
+ u8 *new_addr = addr->sa_data;
+ u8 old_addr[6];
+ int rc;
+
+ if (!is_valid_ether_addr(new_addr)) {
+ netif_err(efx, drv, efx->net_dev,
+ "invalid ethernet MAC address requested: %pM\n",
+ new_addr);
+ return -EADDRNOTAVAIL;
+ }
+
+ /* save old address */
+ ether_addr_copy(old_addr, net_dev->dev_addr);
+ ether_addr_copy(net_dev->dev_addr, new_addr);
+ if (efx->type->set_mac_address) {
+ rc = efx->type->set_mac_address(efx);
+ if (rc) {
+ ether_addr_copy(net_dev->dev_addr, old_addr);
+ return rc;
+ }
+ }
+
+ /* Reconfigure the MAC */
+ mutex_lock(&efx->mac_lock);
+ ef4_mac_reconfigure(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ return 0;
+}
+
+/* Context: netif_addr_lock held, BHs disabled. */
+static void ef4_set_rx_mode(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ if (efx->port_enabled)
+ queue_work(efx->workqueue, &efx->mac_work);
+ /* Otherwise ef4_start_port() will do this */
+}
+
+static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int rc;
+
+ /* If disabling RX n-tuple filtering, clear existing filters */
+ if (net_dev->features & ~data & NETIF_F_NTUPLE) {
+ rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL);
+ if (rc)
+ return rc;
+ }
+
+ /* If Rx VLAN filter is changed, update filters via mac_reconfigure */
+ if ((net_dev->features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) {
+ /* ef4_set_rx_mode() will schedule MAC work to update filters
+ * when a new features are finally set in net_dev.
+ */
+ ef4_set_rx_mode(net_dev);
+ }
+
+ return 0;
+}
+
+static const struct net_device_ops ef4_netdev_ops = {
+ .ndo_open = ef4_net_open,
+ .ndo_stop = ef4_net_stop,
+ .ndo_get_stats64 = ef4_net_stats,
+ .ndo_tx_timeout = ef4_watchdog,
+ .ndo_start_xmit = ef4_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = ef4_ioctl,
+ .ndo_change_mtu = ef4_change_mtu,
+ .ndo_set_mac_address = ef4_set_mac_address,
+ .ndo_set_rx_mode = ef4_set_rx_mode,
+ .ndo_set_features = ef4_set_features,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ef4_netpoll,
+#endif
+ .ndo_setup_tc = ef4_setup_tc,
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = ef4_busy_poll,
+#endif
+#ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = ef4_filter_rfs,
+#endif
+};
+
+static void ef4_update_name(struct ef4_nic *efx)
+{
+ strcpy(efx->name, efx->net_dev->name);
+ ef4_mtd_rename(efx);
+ ef4_set_channel_names(efx);
+}
+
+static int ef4_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
+
+ if ((net_dev->netdev_ops == &ef4_netdev_ops) &&
+ event == NETDEV_CHANGENAME)
+ ef4_update_name(netdev_priv(net_dev));
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ef4_netdev_notifier = {
+ .notifier_call = ef4_netdev_event,
+};
+
+static ssize_t
+show_phy_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ return sprintf(buf, "%d\n", efx->phy_type);
+}
+static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL);
+
+static int ef4_register_netdev(struct ef4_nic *efx)
+{
+ struct net_device *net_dev = efx->net_dev;
+ struct ef4_channel *channel;
+ int rc;
+
+ net_dev->watchdog_timeo = 5 * HZ;
+ net_dev->irq = efx->pci_dev->irq;
+ net_dev->netdev_ops = &ef4_netdev_ops;
+ net_dev->ethtool_ops = &ef4_ethtool_ops;
+ net_dev->gso_max_segs = EF4_TSO_MAX_SEGS;
+ net_dev->min_mtu = EF4_MIN_MTU;
+ net_dev->max_mtu = EF4_MAX_MTU;
+
+ rtnl_lock();
+
+ /* Enable resets to be scheduled and check whether any were
+ * already requested. If so, the NIC is probably hosed so we
+ * abort.
+ */
+ efx->state = STATE_READY;
+ smp_mb(); /* ensure we change state before checking reset_pending */
+ if (efx->reset_pending) {
+ netif_err(efx, probe, efx->net_dev,
+ "aborting probe due to scheduled reset\n");
+ rc = -EIO;
+ goto fail_locked;
+ }
+
+ rc = dev_alloc_name(net_dev, net_dev->name);
+ if (rc < 0)
+ goto fail_locked;
+ ef4_update_name(efx);
+
+ /* Always start with carrier off; PHY events will detect the link */
+ netif_carrier_off(net_dev);
+
+ rc = register_netdevice(net_dev);
+ if (rc)
+ goto fail_locked;
+
+ ef4_for_each_channel(channel, efx) {
+ struct ef4_tx_queue *tx_queue;
+ ef4_for_each_channel_tx_queue(tx_queue, channel)
+ ef4_init_tx_queue_core_txq(tx_queue);
+ }
+
+ ef4_associate(efx);
+
+ rtnl_unlock();
+
+ rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "failed to init net dev attributes\n");
+ goto fail_registered;
+ }
+ return 0;
+
+fail_registered:
+ rtnl_lock();
+ ef4_dissociate(efx);
+ unregister_netdevice(net_dev);
+fail_locked:
+ efx->state = STATE_UNINIT;
+ rtnl_unlock();
+ netif_err(efx, drv, efx->net_dev, "could not register net dev\n");
+ return rc;
+}
+
+static void ef4_unregister_netdev(struct ef4_nic *efx)
+{
+ if (!efx->net_dev)
+ return;
+
+ BUG_ON(netdev_priv(efx->net_dev) != efx);
+
+ if (ef4_dev_registered(efx)) {
+ strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+ device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+ unregister_netdev(efx->net_dev);
+ }
+}
+
+/**************************************************************************
+ *
+ * Device reset and suspend
+ *
+ **************************************************************************/
+
+/* Tears down the entire software state and most of the hardware state
+ * before reset. */
+void ef4_reset_down(struct ef4_nic *efx, enum reset_type method)
+{
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ ef4_stop_all(efx);
+ ef4_disable_interrupts(efx);
+
+ mutex_lock(&efx->mac_lock);
+ if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
+ method != RESET_TYPE_DATAPATH)
+ efx->phy_op->fini(efx);
+ efx->type->fini(efx);
+}
+
+/* This function will always ensure that the locks acquired in
+ * ef4_reset_down() are released. A failure return code indicates
+ * that we were unable to reinitialise the hardware, and the
+ * driver should be disabled. If ok is false, then the rx and tx
+ * engines are not restarted, pending a RESET_DISABLE. */
+int ef4_reset_up(struct ef4_nic *efx, enum reset_type method, bool ok)
+{
+ int rc;
+
+ EF4_ASSERT_RESET_SERIALISED(efx);
+
+ /* Ensure that SRAM is initialised even if we're disabling the device */
+ rc = efx->type->init(efx);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n");
+ goto fail;
+ }
+
+ if (!ok)
+ goto fail;
+
+ if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
+ method != RESET_TYPE_DATAPATH) {
+ rc = efx->phy_op->init(efx);
+ if (rc)
+ goto fail;
+ rc = efx->phy_op->reconfigure(efx);
+ if (rc && rc != -EPERM)
+ netif_err(efx, drv, efx->net_dev,
+ "could not restore PHY settings\n");
+ }
+
+ rc = ef4_enable_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ down_read(&efx->filter_sem);
+ ef4_restore_filters(efx);
+ up_read(&efx->filter_sem);
+
+ mutex_unlock(&efx->mac_lock);
+
+ ef4_start_all(efx);
+
+ return 0;
+
+fail:
+ efx->port_initialized = false;
+
+ mutex_unlock(&efx->mac_lock);
+
+ return rc;
+}
+
+/* Reset the NIC using the specified method. Note that the reset may
+ * fail, in which case the card will be left in an unusable state.
+ *
+ * Caller must hold the rtnl_lock.
+ */
+int ef4_reset(struct ef4_nic *efx, enum reset_type method)
+{
+ int rc, rc2;
+ bool disabled;
+
+ netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
+ RESET_TYPE(method));
+
+ ef4_device_detach_sync(efx);
+ ef4_reset_down(efx, method);
+
+ rc = efx->type->reset(efx, method);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev, "failed to reset hardware\n");
+ goto out;
+ }
+
+ /* Clear flags for the scopes we covered. We assume the NIC and
+ * driver are now quiescent so that there is no race here.
+ */
+ if (method < RESET_TYPE_MAX_METHOD)
+ efx->reset_pending &= -(1 << (method + 1));
+ else /* it doesn't fit into the well-ordered scope hierarchy */
+ __clear_bit(method, &efx->reset_pending);
+
+ /* Reinitialise bus-mastering, which may have been turned off before
+ * the reset was scheduled. This is still appropriate, even in the
+ * RESET_TYPE_DISABLE since this driver generally assumes the hardware
+ * can respond to requests. */
+ pci_set_master(efx->pci_dev);
+
+out:
+ /* Leave device stopped if necessary */
+ disabled = rc ||
+ method == RESET_TYPE_DISABLE ||
+ method == RESET_TYPE_RECOVER_OR_DISABLE;
+ rc2 = ef4_reset_up(efx, method, !disabled);
+ if (rc2) {
+ disabled = true;
+ if (!rc)
+ rc = rc2;
+ }
+
+ if (disabled) {
+ dev_close(efx->net_dev);
+ netif_err(efx, drv, efx->net_dev, "has been disabled\n");
+ efx->state = STATE_DISABLED;
+ } else {
+ netif_dbg(efx, drv, efx->net_dev, "reset complete\n");
+ netif_device_attach(efx->net_dev);
+ }
+ return rc;
+}
+
+/* Try recovery mechanisms.
+ * For now only EEH is supported.
+ * Returns 0 if the recovery mechanisms are unsuccessful.
+ * Returns a non-zero value otherwise.
+ */
+int ef4_try_recovery(struct ef4_nic *efx)
+{
+#ifdef CONFIG_EEH
+ /* A PCI error can occur and not be seen by EEH because nothing
+ * happens on the PCI bus. In this case the driver may fail and
+ * schedule a 'recover or reset', leading to this recovery handler.
+ * Manually call the eeh failure check function.
+ */
+ struct eeh_dev *eehdev = pci_dev_to_eeh_dev(efx->pci_dev);
+ if (eeh_dev_check_failure(eehdev)) {
+ /* The EEH mechanisms will handle the error and reset the
+ * device if necessary.
+ */
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/* The worker thread exists so that code that cannot sleep can
+ * schedule a reset for later.
+ */
+static void ef4_reset_work(struct work_struct *data)
+{
+ struct ef4_nic *efx = container_of(data, struct ef4_nic, reset_work);
+ unsigned long pending;
+ enum reset_type method;
+
+ pending = ACCESS_ONCE(efx->reset_pending);
+ method = fls(pending) - 1;
+
+ if ((method == RESET_TYPE_RECOVER_OR_DISABLE ||
+ method == RESET_TYPE_RECOVER_OR_ALL) &&
+ ef4_try_recovery(efx))
+ return;
+
+ if (!pending)
+ return;
+
+ rtnl_lock();
+
+ /* We checked the state in ef4_schedule_reset() but it may
+ * have changed by now. Now that we have the RTNL lock,
+ * it cannot change again.
+ */
+ if (efx->state == STATE_READY)
+ (void)ef4_reset(efx, method);
+
+ rtnl_unlock();
+}
+
+void ef4_schedule_reset(struct ef4_nic *efx, enum reset_type type)
+{
+ enum reset_type method;
+
+ if (efx->state == STATE_RECOVERY) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "recovering: skip scheduling %s reset\n",
+ RESET_TYPE(type));
+ return;
+ }
+
+ switch (type) {
+ case RESET_TYPE_INVISIBLE:
+ case RESET_TYPE_ALL:
+ case RESET_TYPE_RECOVER_OR_ALL:
+ case RESET_TYPE_WORLD:
+ case RESET_TYPE_DISABLE:
+ case RESET_TYPE_RECOVER_OR_DISABLE:
+ case RESET_TYPE_DATAPATH:
+ method = type;
+ netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
+ RESET_TYPE(method));
+ break;
+ default:
+ method = efx->type->map_reset_reason(type);
+ netif_dbg(efx, drv, efx->net_dev,
+ "scheduling %s reset for %s\n",
+ RESET_TYPE(method), RESET_TYPE(type));
+ break;
+ }
+
+ set_bit(method, &efx->reset_pending);
+ smp_mb(); /* ensure we change reset_pending before checking state */
+
+ /* If we're not READY then just leave the flags set as the cue
+ * to abort probing or reschedule the reset later.
+ */
+ if (ACCESS_ONCE(efx->state) != STATE_READY)
+ return;
+
+ queue_work(reset_workqueue, &efx->reset_work);
+}
+
+/**************************************************************************
+ *
+ * List of NICs we support
+ *
+ **************************************************************************/
+
+/* PCI device ID table */
+static const struct pci_device_id ef4_pci_table[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
+ .driver_data = (unsigned long) &falcon_a1_nic_type},
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000B),
+ .driver_data = (unsigned long) &falcon_b0_nic_type},
+ {0} /* end of list */
+};
+
+/**************************************************************************
+ *
+ * Dummy PHY/MAC operations
+ *
+ * Can be used for some unimplemented operations
+ * Needed so all function pointers are valid and do not have to be tested
+ * before use
+ *
+ **************************************************************************/
+int ef4_port_dummy_op_int(struct ef4_nic *efx)
+{
+ return 0;
+}
+void ef4_port_dummy_op_void(struct ef4_nic *efx) {}
+
+static bool ef4_port_dummy_op_poll(struct ef4_nic *efx)
+{
+ return false;
+}
+
+static const struct ef4_phy_operations ef4_dummy_phy_operations = {
+ .init = ef4_port_dummy_op_int,
+ .reconfigure = ef4_port_dummy_op_int,
+ .poll = ef4_port_dummy_op_poll,
+ .fini = ef4_port_dummy_op_void,
+};
+
+/**************************************************************************
+ *
+ * Data housekeeping
+ *
+ **************************************************************************/
+
+/* This zeroes out and then fills in the invariants in a struct
+ * ef4_nic (including all sub-structures).
+ */
+static int ef4_init_struct(struct ef4_nic *efx,
+ struct pci_dev *pci_dev, struct net_device *net_dev)
+{
+ int i;
+
+ /* Initialise common structures */
+ INIT_LIST_HEAD(&efx->node);
+ INIT_LIST_HEAD(&efx->secondary_list);
+ spin_lock_init(&efx->biu_lock);
+#ifdef CONFIG_SFC_FALCON_MTD
+ INIT_LIST_HEAD(&efx->mtd_list);
+#endif
+ INIT_WORK(&efx->reset_work, ef4_reset_work);
+ INIT_DELAYED_WORK(&efx->monitor_work, ef4_monitor);
+ INIT_DELAYED_WORK(&efx->selftest_work, ef4_selftest_async_work);
+ efx->pci_dev = pci_dev;
+ efx->msg_enable = debug;
+ efx->state = STATE_UNINIT;
+ strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
+
+ efx->net_dev = net_dev;
+ efx->rx_prefix_size = efx->type->rx_prefix_size;
+ efx->rx_ip_align =
+ NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
+ efx->rx_packet_hash_offset =
+ efx->type->rx_hash_offset - efx->type->rx_prefix_size;
+ efx->rx_packet_ts_offset =
+ efx->type->rx_ts_offset - efx->type->rx_prefix_size;
+ spin_lock_init(&efx->stats_lock);
+ mutex_init(&efx->mac_lock);
+ efx->phy_op = &ef4_dummy_phy_operations;
+ efx->mdio.dev = net_dev;
+ INIT_WORK(&efx->mac_work, ef4_mac_work);
+ init_waitqueue_head(&efx->flush_wq);
+
+ for (i = 0; i < EF4_MAX_CHANNELS; i++) {
+ efx->channel[i] = ef4_alloc_channel(efx, i, NULL);
+ if (!efx->channel[i])
+ goto fail;
+ efx->msi_context[i].efx = efx;
+ efx->msi_context[i].index = i;
+ }
+
+ /* Higher numbered interrupt modes are less capable! */
+ efx->interrupt_mode = max(efx->type->max_interrupt_mode,
+ interrupt_mode);
+
+ /* Would be good to use the net_dev name, but we're too early */
+ snprintf(efx->workqueue_name, sizeof(efx->workqueue_name), "sfc%s",
+ pci_name(pci_dev));
+ efx->workqueue = create_singlethread_workqueue(efx->workqueue_name);
+ if (!efx->workqueue)
+ goto fail;
+
+ return 0;
+
+fail:
+ ef4_fini_struct(efx);
+ return -ENOMEM;
+}
+
+static void ef4_fini_struct(struct ef4_nic *efx)
+{
+ int i;
+
+ for (i = 0; i < EF4_MAX_CHANNELS; i++)
+ kfree(efx->channel[i]);
+
+ kfree(efx->vpd_sn);
+
+ if (efx->workqueue) {
+ destroy_workqueue(efx->workqueue);
+ efx->workqueue = NULL;
+ }
+}
+
+void ef4_update_sw_stats(struct ef4_nic *efx, u64 *stats)
+{
+ u64 n_rx_nodesc_trunc = 0;
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ n_rx_nodesc_trunc += channel->n_rx_nodesc_trunc;
+ stats[GENERIC_STAT_rx_nodesc_trunc] = n_rx_nodesc_trunc;
+ stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops);
+}
+
+/**************************************************************************
+ *
+ * PCI interface
+ *
+ **************************************************************************/
+
+/* Main body of final NIC shutdown code
+ * This is called only at module unload (or hotplug removal).
+ */
+static void ef4_pci_remove_main(struct ef4_nic *efx)
+{
+ /* Flush reset_work. It can no longer be scheduled since we
+ * are not READY.
+ */
+ BUG_ON(efx->state == STATE_READY);
+ cancel_work_sync(&efx->reset_work);
+
+ ef4_disable_interrupts(efx);
+ ef4_nic_fini_interrupt(efx);
+ ef4_fini_port(efx);
+ efx->type->fini(efx);
+ ef4_fini_napi(efx);
+ ef4_remove_all(efx);
+}
+
+/* Final NIC shutdown
+ * This is called only at module unload (or hotplug removal). A PF can call
+ * this on its VFs to ensure they are unbound first.
+ */
+static void ef4_pci_remove(struct pci_dev *pci_dev)
+{
+ struct ef4_nic *efx;
+
+ efx = pci_get_drvdata(pci_dev);
+ if (!efx)
+ return;
+
+ /* Mark the NIC as fini, then stop the interface */
+ rtnl_lock();
+ ef4_dissociate(efx);
+ dev_close(efx->net_dev);
+ ef4_disable_interrupts(efx);
+ efx->state = STATE_UNINIT;
+ rtnl_unlock();
+
+ ef4_unregister_netdev(efx);
+
+ ef4_mtd_remove(efx);
+
+ ef4_pci_remove_main(efx);
+
+ ef4_fini_io(efx);
+ netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");
+
+ ef4_fini_struct(efx);
+ free_netdev(efx->net_dev);
+
+ pci_disable_pcie_error_reporting(pci_dev);
+};
+
+/* NIC VPD information
+ * Called during probe to display the part number of the
+ * installed NIC. VPD is potentially very large but this should
+ * always appear within the first 512 bytes.
+ */
+#define SFC_VPD_LEN 512
+static void ef4_probe_vpd_strings(struct ef4_nic *efx)
+{
+ struct pci_dev *dev = efx->pci_dev;
+ char vpd_data[SFC_VPD_LEN];
+ ssize_t vpd_size;
+ int ro_start, ro_size, i, j;
+
+ /* Get the vpd data from the device */
+ vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
+ if (vpd_size <= 0) {
+ netif_err(efx, drv, efx->net_dev, "Unable to read VPD\n");
+ return;
+ }
+
+ /* Get the Read only section */
+ ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA);
+ if (ro_start < 0) {
+ netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
+ return;
+ }
+
+ ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
+ j = ro_size;
+ i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
+ if (i + j > vpd_size)
+ j = vpd_size - i;
+
+ /* Get the Part number */
+ i = pci_vpd_find_info_keyword(vpd_data, i, j, "PN");
+ if (i < 0) {
+ netif_err(efx, drv, efx->net_dev, "Part number not found\n");
+ return;
+ }
+
+ j = pci_vpd_info_field_size(&vpd_data[i]);
+ i += PCI_VPD_INFO_FLD_HDR_SIZE;
+ if (i + j > vpd_size) {
+ netif_err(efx, drv, efx->net_dev, "Incomplete part number\n");
+ return;
+ }
+
+ netif_info(efx, drv, efx->net_dev,
+ "Part Number : %.*s\n", j, &vpd_data[i]);
+
+ i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
+ j = ro_size;
+ i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
+ if (i < 0) {
+ netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
+ return;
+ }
+
+ j = pci_vpd_info_field_size(&vpd_data[i]);
+ i += PCI_VPD_INFO_FLD_HDR_SIZE;
+ if (i + j > vpd_size) {
+ netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
+ return;
+ }
+
+ efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
+ if (!efx->vpd_sn)
+ return;
+
+ snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
+}
+
+
+/* Main body of NIC initialisation
+ * This is called at module load (or hotplug insertion, theoretically).
+ */
+static int ef4_pci_probe_main(struct ef4_nic *efx)
+{
+ int rc;
+
+ /* Do start-of-day initialisation */
+ rc = ef4_probe_all(efx);
+ if (rc)
+ goto fail1;
+
+ ef4_init_napi(efx);
+
+ rc = efx->type->init(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to initialise NIC\n");
+ goto fail3;
+ }
+
+ rc = ef4_init_port(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to initialise port\n");
+ goto fail4;
+ }
+
+ rc = ef4_nic_init_interrupt(efx);
+ if (rc)
+ goto fail5;
+ rc = ef4_enable_interrupts(efx);
+ if (rc)
+ goto fail6;
+
+ return 0;
+
+ fail6:
+ ef4_nic_fini_interrupt(efx);
+ fail5:
+ ef4_fini_port(efx);
+ fail4:
+ efx->type->fini(efx);
+ fail3:
+ ef4_fini_napi(efx);
+ ef4_remove_all(efx);
+ fail1:
+ return rc;
+}
+
+/* NIC initialisation
+ *
+ * This is called at module load (or hotplug insertion,
+ * theoretically). It sets up PCI mappings, resets the NIC,
+ * sets up and registers the network devices with the kernel and hooks
+ * the interrupt service routine. It does not prepare the device for
+ * transmission; this is left to the first time one of the network
+ * interfaces is brought up (i.e. ef4_net_open).
+ */
+static int ef4_pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *entry)
+{
+ struct net_device *net_dev;
+ struct ef4_nic *efx;
+ int rc;
+
+ /* Allocate and initialise a struct net_device and struct ef4_nic */
+ net_dev = alloc_etherdev_mqs(sizeof(*efx), EF4_MAX_CORE_TX_QUEUES,
+ EF4_MAX_RX_QUEUES);
+ if (!net_dev)
+ return -ENOMEM;
+ efx = netdev_priv(net_dev);
+ efx->type = (const struct ef4_nic_type *) entry->driver_data;
+ efx->fixed_features |= NETIF_F_HIGHDMA;
+
+ pci_set_drvdata(pci_dev, efx);
+ SET_NETDEV_DEV(net_dev, &pci_dev->dev);
+ rc = ef4_init_struct(efx, pci_dev, net_dev);
+ if (rc)
+ goto fail1;
+
+ netif_info(efx, probe, efx->net_dev,
+ "Solarflare NIC detected\n");
+
+ ef4_probe_vpd_strings(efx);
+
+ /* Set up basic I/O (BAR mappings etc) */
+ rc = ef4_init_io(efx);
+ if (rc)
+ goto fail2;
+
+ rc = ef4_pci_probe_main(efx);
+ if (rc)
+ goto fail3;
+
+ net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
+ NETIF_F_RXCSUM);
+ /* Mask for features that also apply to VLAN devices */
+ net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG |
+ NETIF_F_HIGHDMA | NETIF_F_RXCSUM);
+
+ net_dev->hw_features = net_dev->features & ~efx->fixed_features;
+
+ /* Disable VLAN filtering by default. It may be enforced if
+ * the feature is fixed (i.e. VLAN filters are required to
+ * receive VLAN tagged packets due to vPort restrictions).
+ */
+ net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+ net_dev->features |= efx->fixed_features;
+
+ rc = ef4_register_netdev(efx);
+ if (rc)
+ goto fail4;
+
+ netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");
+
+ /* Try to create MTDs, but allow this to fail */
+ rtnl_lock();
+ rc = ef4_mtd_probe(efx);
+ rtnl_unlock();
+ if (rc && rc != -EPERM)
+ netif_warn(efx, probe, efx->net_dev,
+ "failed to create MTDs (%d)\n", rc);
+
+ rc = pci_enable_pcie_error_reporting(pci_dev);
+ if (rc && rc != -EINVAL)
+ netif_notice(efx, probe, efx->net_dev,
+ "PCIE error reporting unavailable (%d).\n",
+ rc);
+
+ return 0;
+
+ fail4:
+ ef4_pci_remove_main(efx);
+ fail3:
+ ef4_fini_io(efx);
+ fail2:
+ ef4_fini_struct(efx);
+ fail1:
+ WARN_ON(rc > 0);
+ netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
+ free_netdev(net_dev);
+ return rc;
+}
+
+static int ef4_pm_freeze(struct device *dev)
+{
+ struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+
+ rtnl_lock();
+
+ if (efx->state != STATE_DISABLED) {
+ efx->state = STATE_UNINIT;
+
+ ef4_device_detach_sync(efx);
+
+ ef4_stop_all(efx);
+ ef4_disable_interrupts(efx);
+ }
+
+ rtnl_unlock();
+
+ return 0;
+}
+
+static int ef4_pm_thaw(struct device *dev)
+{
+ int rc;
+ struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+
+ rtnl_lock();
+
+ if (efx->state != STATE_DISABLED) {
+ rc = ef4_enable_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ mutex_lock(&efx->mac_lock);
+ efx->phy_op->reconfigure(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ ef4_start_all(efx);
+
+ netif_device_attach(efx->net_dev);
+
+ efx->state = STATE_READY;
+
+ efx->type->resume_wol(efx);
+ }
+
+ rtnl_unlock();
+
+ /* Reschedule any quenched resets scheduled during ef4_pm_freeze() */
+ queue_work(reset_workqueue, &efx->reset_work);
+
+ return 0;
+
+fail:
+ rtnl_unlock();
+
+ return rc;
+}
+
+static int ef4_pm_poweroff(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct ef4_nic *efx = pci_get_drvdata(pci_dev);
+
+ efx->type->fini(efx);
+
+ efx->reset_pending = 0;
+
+ pci_save_state(pci_dev);
+ return pci_set_power_state(pci_dev, PCI_D3hot);
+}
+
+/* Used for both resume and restore */
+static int ef4_pm_resume(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct ef4_nic *efx = pci_get_drvdata(pci_dev);
+ int rc;
+
+ rc = pci_set_power_state(pci_dev, PCI_D0);
+ if (rc)
+ return rc;
+ pci_restore_state(pci_dev);
+ rc = pci_enable_device(pci_dev);
+ if (rc)
+ return rc;
+ pci_set_master(efx->pci_dev);
+ rc = efx->type->reset(efx, RESET_TYPE_ALL);
+ if (rc)
+ return rc;
+ rc = efx->type->init(efx);
+ if (rc)
+ return rc;
+ rc = ef4_pm_thaw(dev);
+ return rc;
+}
+
+static int ef4_pm_suspend(struct device *dev)
+{
+ int rc;
+
+ ef4_pm_freeze(dev);
+ rc = ef4_pm_poweroff(dev);
+ if (rc)
+ ef4_pm_resume(dev);
+ return rc;
+}
+
+static const struct dev_pm_ops ef4_pm_ops = {
+ .suspend = ef4_pm_suspend,
+ .resume = ef4_pm_resume,
+ .freeze = ef4_pm_freeze,
+ .thaw = ef4_pm_thaw,
+ .poweroff = ef4_pm_poweroff,
+ .restore = ef4_pm_resume,
+};
+
+/* A PCI error affecting this device was detected.
+ * At this point MMIO and DMA may be disabled.
+ * Stop the software path and request a slot reset.
+ */
+static pci_ers_result_t ef4_io_error_detected(struct pci_dev *pdev,
+ enum pci_channel_state state)
+{
+ pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+ struct ef4_nic *efx = pci_get_drvdata(pdev);
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ rtnl_lock();
+
+ if (efx->state != STATE_DISABLED) {
+ efx->state = STATE_RECOVERY;
+ efx->reset_pending = 0;
+
+ ef4_device_detach_sync(efx);
+
+ ef4_stop_all(efx);
+ ef4_disable_interrupts(efx);
+
+ status = PCI_ERS_RESULT_NEED_RESET;
+ } else {
+ /* If the interface is disabled we don't want to do anything
+ * with it.
+ */
+ status = PCI_ERS_RESULT_RECOVERED;
+ }
+
+ rtnl_unlock();
+
+ pci_disable_device(pdev);
+
+ return status;
+}
+
+/* Fake a successful reset, which will be performed later in ef4_io_resume. */
+static pci_ers_result_t ef4_io_slot_reset(struct pci_dev *pdev)
+{
+ struct ef4_nic *efx = pci_get_drvdata(pdev);
+ pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+ int rc;
+
+ if (pci_enable_device(pdev)) {
+ netif_err(efx, hw, efx->net_dev,
+ "Cannot re-enable PCI device after reset.\n");
+ status = PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ rc = pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (rc) {
+ netif_err(efx, hw, efx->net_dev,
+ "pci_cleanup_aer_uncorrect_error_status failed (%d)\n", rc);
+ /* Non-fatal error. Continue. */
+ }
+
+ return status;
+}
+
+/* Perform the actual reset and resume I/O operations. */
+static void ef4_io_resume(struct pci_dev *pdev)
+{
+ struct ef4_nic *efx = pci_get_drvdata(pdev);
+ int rc;
+
+ rtnl_lock();
+
+ if (efx->state == STATE_DISABLED)
+ goto out;
+
+ rc = ef4_reset(efx, RESET_TYPE_ALL);
+ if (rc) {
+ netif_err(efx, hw, efx->net_dev,
+ "ef4_reset failed after PCI error (%d)\n", rc);
+ } else {
+ efx->state = STATE_READY;
+ netif_dbg(efx, hw, efx->net_dev,
+ "Done resetting and resuming IO after PCI error.\n");
+ }
+
+out:
+ rtnl_unlock();
+}
+
+/* For simplicity and reliability, we always require a slot reset and try to
+ * reset the hardware when a pci error affecting the device is detected.
+ * We leave both the link_reset and mmio_enabled callback unimplemented:
+ * 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 const struct pci_error_handlers ef4_err_handlers = {
+ .error_detected = ef4_io_error_detected,
+ .slot_reset = ef4_io_slot_reset,
+ .resume = ef4_io_resume,
+};
+
+static struct pci_driver ef4_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ef4_pci_table,
+ .probe = ef4_pci_probe,
+ .remove = ef4_pci_remove,
+ .driver.pm = &ef4_pm_ops,
+ .err_handler = &ef4_err_handlers,
+};
+
+/**************************************************************************
+ *
+ * Kernel module interface
+ *
+ *************************************************************************/
+
+module_param(interrupt_mode, uint, 0444);
+MODULE_PARM_DESC(interrupt_mode,
+ "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");
+
+static int __init ef4_init_module(void)
+{
+ int rc;
+
+ printk(KERN_INFO "Solarflare Falcon driver v" EF4_DRIVER_VERSION "\n");
+
+ rc = register_netdevice_notifier(&ef4_netdev_notifier);
+ if (rc)
+ goto err_notifier;
+
+ reset_workqueue = create_singlethread_workqueue("sfc_reset");
+ if (!reset_workqueue) {
+ rc = -ENOMEM;
+ goto err_reset;
+ }
+
+ rc = pci_register_driver(&ef4_pci_driver);
+ if (rc < 0)
+ goto err_pci;
+
+ return 0;
+
+ err_pci:
+ destroy_workqueue(reset_workqueue);
+ err_reset:
+ unregister_netdevice_notifier(&ef4_netdev_notifier);
+ err_notifier:
+ return rc;
+}
+
+static void __exit ef4_exit_module(void)
+{
+ printk(KERN_INFO "Solarflare Falcon driver unloading\n");
+
+ pci_unregister_driver(&ef4_pci_driver);
+ destroy_workqueue(reset_workqueue);
+ unregister_netdevice_notifier(&ef4_netdev_notifier);
+
+}
+
+module_init(ef4_init_module);
+module_exit(ef4_exit_module);
+
+MODULE_AUTHOR("Solarflare Communications and "
+ "Michael Brown <mbrown@fensystems.co.uk>");
+MODULE_DESCRIPTION("Solarflare Falcon network driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ef4_pci_table);
diff --git a/drivers/net/ethernet/sfc/falcon/efx.h b/drivers/net/ethernet/sfc/falcon/efx.h
new file mode 100644
index 000000000000..c89456fa148c
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/efx.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_EFX_H
+#define EF4_EFX_H
+
+#include "net_driver.h"
+#include "filter.h"
+
+/* All controllers use BAR 0 for I/O space and BAR 2(&3) for memory */
+/* All VFs use BAR 0/1 for memory */
+#define EF4_MEM_BAR 2
+#define EF4_MEM_VF_BAR 0
+
+int ef4_net_open(struct net_device *net_dev);
+int ef4_net_stop(struct net_device *net_dev);
+
+/* TX */
+int ef4_probe_tx_queue(struct ef4_tx_queue *tx_queue);
+void ef4_remove_tx_queue(struct ef4_tx_queue *tx_queue);
+void ef4_init_tx_queue(struct ef4_tx_queue *tx_queue);
+void ef4_init_tx_queue_core_txq(struct ef4_tx_queue *tx_queue);
+void ef4_fini_tx_queue(struct ef4_tx_queue *tx_queue);
+netdev_tx_t ef4_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev);
+netdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb);
+void ef4_xmit_done(struct ef4_tx_queue *tx_queue, unsigned int index);
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
+ struct tc_to_netdev *tc);
+unsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx);
+extern bool ef4_separate_tx_channels;
+
+/* RX */
+void ef4_set_default_rx_indir_table(struct ef4_nic *efx);
+void ef4_rx_config_page_split(struct ef4_nic *efx);
+int ef4_probe_rx_queue(struct ef4_rx_queue *rx_queue);
+void ef4_remove_rx_queue(struct ef4_rx_queue *rx_queue);
+void ef4_init_rx_queue(struct ef4_rx_queue *rx_queue);
+void ef4_fini_rx_queue(struct ef4_rx_queue *rx_queue);
+void ef4_fast_push_rx_descriptors(struct ef4_rx_queue *rx_queue, bool atomic);
+void ef4_rx_slow_fill(unsigned long context);
+void __ef4_rx_packet(struct ef4_channel *channel);
+void ef4_rx_packet(struct ef4_rx_queue *rx_queue, unsigned int index,
+ unsigned int n_frags, unsigned int len, u16 flags);
+static inline void ef4_rx_flush_packet(struct ef4_channel *channel)
+{
+ if (channel->rx_pkt_n_frags)
+ __ef4_rx_packet(channel);
+}
+void ef4_schedule_slow_fill(struct ef4_rx_queue *rx_queue);
+
+#define EF4_MAX_DMAQ_SIZE 4096UL
+#define EF4_DEFAULT_DMAQ_SIZE 1024UL
+#define EF4_MIN_DMAQ_SIZE 512UL
+
+#define EF4_MAX_EVQ_SIZE 16384UL
+#define EF4_MIN_EVQ_SIZE 512UL
+
+/* Maximum number of TCP segments we support for soft-TSO */
+#define EF4_TSO_MAX_SEGS 100
+
+/* The smallest [rt]xq_entries that the driver supports. RX minimum
+ * is a bit arbitrary. For TX, we must have space for at least 2
+ * TSO skbs.
+ */
+#define EF4_RXQ_MIN_ENT 128U
+#define EF4_TXQ_MIN_ENT(efx) (2 * ef4_tx_max_skb_descs(efx))
+
+static inline bool ef4_rss_enabled(struct ef4_nic *efx)
+{
+ return efx->rss_spread > 1;
+}
+
+/* Filters */
+
+void ef4_mac_reconfigure(struct ef4_nic *efx);
+
+/**
+ * ef4_filter_insert_filter - add or replace a filter
+ * @efx: NIC in which to insert the filter
+ * @spec: Specification for the filter
+ * @replace_equal: Flag for whether the specified filter may replace an
+ * existing filter with equal priority
+ *
+ * On success, return the filter ID.
+ * On failure, return a negative error code.
+ *
+ * If existing filters have equal match values to the new filter spec,
+ * then the new filter might replace them or the function might fail,
+ * as follows.
+ *
+ * 1. If the existing filters have lower priority, or @replace_equal
+ * is set and they have equal priority, replace them.
+ *
+ * 2. If the existing filters have higher priority, return -%EPERM.
+ *
+ * 3. If !ef4_filter_is_mc_recipient(@spec), or the NIC does not
+ * support delivery to multiple recipients, return -%EEXIST.
+ *
+ * This implies that filters for multiple multicast recipients must
+ * all be inserted with the same priority and @replace_equal = %false.
+ */
+static inline s32 ef4_filter_insert_filter(struct ef4_nic *efx,
+ struct ef4_filter_spec *spec,
+ bool replace_equal)
+{
+ return efx->type->filter_insert(efx, spec, replace_equal);
+}
+
+/**
+ * ef4_filter_remove_id_safe - remove a filter by ID, carefully
+ * @efx: NIC from which to remove the filter
+ * @priority: Priority of filter, as passed to @ef4_filter_insert_filter
+ * @filter_id: ID of filter, as returned by @ef4_filter_insert_filter
+ *
+ * This function will range-check @filter_id, so it is safe to call
+ * with a value passed from userland.
+ */
+static inline int ef4_filter_remove_id_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id)
+{
+ return efx->type->filter_remove_safe(efx, priority, filter_id);
+}
+
+/**
+ * ef4_filter_get_filter_safe - retrieve a filter by ID, carefully
+ * @efx: NIC from which to remove the filter
+ * @priority: Priority of filter, as passed to @ef4_filter_insert_filter
+ * @filter_id: ID of filter, as returned by @ef4_filter_insert_filter
+ * @spec: Buffer in which to store filter specification
+ *
+ * This function will range-check @filter_id, so it is safe to call
+ * with a value passed from userland.
+ */
+static inline int
+ef4_filter_get_filter_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id, struct ef4_filter_spec *spec)
+{
+ return efx->type->filter_get_safe(efx, priority, filter_id, spec);
+}
+
+static inline u32 ef4_filter_count_rx_used(struct ef4_nic *efx,
+ enum ef4_filter_priority priority)
+{
+ return efx->type->filter_count_rx_used(efx, priority);
+}
+static inline u32 ef4_filter_get_rx_id_limit(struct ef4_nic *efx)
+{
+ return efx->type->filter_get_rx_id_limit(efx);
+}
+static inline s32 ef4_filter_get_rx_ids(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 *buf, u32 size)
+{
+ return efx->type->filter_get_rx_ids(efx, priority, buf, size);
+}
+#ifdef CONFIG_RFS_ACCEL
+int ef4_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id);
+bool __ef4_filter_rfs_expire(struct ef4_nic *efx, unsigned quota);
+static inline void ef4_filter_rfs_expire(struct ef4_channel *channel)
+{
+ if (channel->rfs_filters_added >= 60 &&
+ __ef4_filter_rfs_expire(channel->efx, 100))
+ channel->rfs_filters_added -= 60;
+}
+#define ef4_filter_rfs_enabled() 1
+#else
+static inline void ef4_filter_rfs_expire(struct ef4_channel *channel) {}
+#define ef4_filter_rfs_enabled() 0
+#endif
+bool ef4_filter_is_mc_recipient(const struct ef4_filter_spec *spec);
+
+/* Channels */
+int ef4_channel_dummy_op_int(struct ef4_channel *channel);
+void ef4_channel_dummy_op_void(struct ef4_channel *channel);
+int ef4_realloc_channels(struct ef4_nic *efx, u32 rxq_entries, u32 txq_entries);
+
+/* Ports */
+int ef4_reconfigure_port(struct ef4_nic *efx);
+int __ef4_reconfigure_port(struct ef4_nic *efx);
+
+/* Ethtool support */
+extern const struct ethtool_ops ef4_ethtool_ops;
+
+/* Reset handling */
+int ef4_reset(struct ef4_nic *efx, enum reset_type method);
+void ef4_reset_down(struct ef4_nic *efx, enum reset_type method);
+int ef4_reset_up(struct ef4_nic *efx, enum reset_type method, bool ok);
+int ef4_try_recovery(struct ef4_nic *efx);
+
+/* Global */
+void ef4_schedule_reset(struct ef4_nic *efx, enum reset_type type);
+unsigned int ef4_usecs_to_ticks(struct ef4_nic *efx, unsigned int usecs);
+unsigned int ef4_ticks_to_usecs(struct ef4_nic *efx, unsigned int ticks);
+int ef4_init_irq_moderation(struct ef4_nic *efx, unsigned int tx_usecs,
+ unsigned int rx_usecs, bool rx_adaptive,
+ bool rx_may_override_tx);
+void ef4_get_irq_moderation(struct ef4_nic *efx, unsigned int *tx_usecs,
+ unsigned int *rx_usecs, bool *rx_adaptive);
+void ef4_stop_eventq(struct ef4_channel *channel);
+void ef4_start_eventq(struct ef4_channel *channel);
+
+/* Dummy PHY ops for PHY drivers */
+int ef4_port_dummy_op_int(struct ef4_nic *efx);
+void ef4_port_dummy_op_void(struct ef4_nic *efx);
+
+/* Update the generic software stats in the passed stats array */
+void ef4_update_sw_stats(struct ef4_nic *efx, u64 *stats);
+
+/* MTD */
+#ifdef CONFIG_SFC_FALCON_MTD
+int ef4_mtd_add(struct ef4_nic *efx, struct ef4_mtd_partition *parts,
+ size_t n_parts, size_t sizeof_part);
+static inline int ef4_mtd_probe(struct ef4_nic *efx)
+{
+ return efx->type->mtd_probe(efx);
+}
+void ef4_mtd_rename(struct ef4_nic *efx);
+void ef4_mtd_remove(struct ef4_nic *efx);
+#else
+static inline int ef4_mtd_probe(struct ef4_nic *efx) { return 0; }
+static inline void ef4_mtd_rename(struct ef4_nic *efx) {}
+static inline void ef4_mtd_remove(struct ef4_nic *efx) {}
+#endif
+
+static inline void ef4_schedule_channel(struct ef4_channel *channel)
+{
+ netif_vdbg(channel->efx, intr, channel->efx->net_dev,
+ "channel %d scheduling NAPI poll on CPU%d\n",
+ channel->channel, raw_smp_processor_id());
+
+ napi_schedule(&channel->napi_str);
+}
+
+static inline void ef4_schedule_channel_irq(struct ef4_channel *channel)
+{
+ channel->event_test_cpu = raw_smp_processor_id();
+ ef4_schedule_channel(channel);
+}
+
+void ef4_link_status_changed(struct ef4_nic *efx);
+void ef4_link_set_advertising(struct ef4_nic *efx, u32);
+void ef4_link_set_wanted_fc(struct ef4_nic *efx, u8);
+
+static inline void ef4_device_detach_sync(struct ef4_nic *efx)
+{
+ struct net_device *dev = efx->net_dev;
+
+ /* Lock/freeze all TX queues so that we can be sure the
+ * TX scheduler is stopped when we're done and before
+ * netif_device_present() becomes false.
+ */
+ netif_tx_lock_bh(dev);
+ netif_device_detach(dev);
+ netif_tx_unlock_bh(dev);
+}
+
+static inline bool ef4_rwsem_assert_write_locked(struct rw_semaphore *sem)
+{
+ if (WARN_ON(down_read_trylock(sem))) {
+ up_read(sem);
+ return false;
+ }
+ return true;
+}
+
+#endif /* EF4_EFX_H */
diff --git a/drivers/net/ethernet/sfc/falcon/enum.h b/drivers/net/ethernet/sfc/falcon/enum.h
new file mode 100644
index 000000000000..30a1136fc909
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/enum.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2007-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_ENUM_H
+#define EF4_ENUM_H
+
+/**
+ * enum ef4_loopback_mode - loopback modes
+ * @LOOPBACK_NONE: no loopback
+ * @LOOPBACK_DATA: data path loopback
+ * @LOOPBACK_GMAC: loopback within GMAC
+ * @LOOPBACK_XGMII: loopback after XMAC
+ * @LOOPBACK_XGXS: loopback within BPX after XGXS
+ * @LOOPBACK_XAUI: loopback within BPX before XAUI serdes
+ * @LOOPBACK_GMII: loopback within BPX after GMAC
+ * @LOOPBACK_SGMII: loopback within BPX within SGMII
+ * @LOOPBACK_XGBR: loopback within BPX within XGBR
+ * @LOOPBACK_XFI: loopback within BPX before XFI serdes
+ * @LOOPBACK_XAUI_FAR: loopback within BPX after XAUI serdes
+ * @LOOPBACK_GMII_FAR: loopback within BPX before SGMII
+ * @LOOPBACK_SGMII_FAR: loopback within BPX after SGMII
+ * @LOOPBACK_XFI_FAR: loopback after XFI serdes
+ * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level
+ * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level
+ * @LOOPBACK_PCS: loopback within 10G PHY at PCS level
+ * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level
+ * @LOOPBACK_XPORT: cross port loopback
+ * @LOOPBACK_XGMII_WS: wireside loopback excluding XMAC
+ * @LOOPBACK_XAUI_WS: wireside loopback within BPX within XAUI serdes
+ * @LOOPBACK_XAUI_WS_FAR: wireside loopback within BPX including XAUI serdes
+ * @LOOPBACK_XAUI_WS_NEAR: wireside loopback within BPX excluding XAUI serdes
+ * @LOOPBACK_GMII_WS: wireside loopback excluding GMAC
+ * @LOOPBACK_XFI_WS: wireside loopback excluding XFI serdes
+ * @LOOPBACK_XFI_WS_FAR: wireside loopback including XFI serdes
+ * @LOOPBACK_PHYXS_WS: wireside loopback within 10G PHY at PHYXS level
+ */
+/* Please keep up-to-date w.r.t the following two #defines */
+enum ef4_loopback_mode {
+ LOOPBACK_NONE = 0,
+ LOOPBACK_DATA = 1,
+ LOOPBACK_GMAC = 2,
+ LOOPBACK_XGMII = 3,
+ LOOPBACK_XGXS = 4,
+ LOOPBACK_XAUI = 5,
+ LOOPBACK_GMII = 6,
+ LOOPBACK_SGMII = 7,
+ LOOPBACK_XGBR = 8,
+ LOOPBACK_XFI = 9,
+ LOOPBACK_XAUI_FAR = 10,
+ LOOPBACK_GMII_FAR = 11,
+ LOOPBACK_SGMII_FAR = 12,
+ LOOPBACK_XFI_FAR = 13,
+ LOOPBACK_GPHY = 14,
+ LOOPBACK_PHYXS = 15,
+ LOOPBACK_PCS = 16,
+ LOOPBACK_PMAPMD = 17,
+ LOOPBACK_XPORT = 18,
+ LOOPBACK_XGMII_WS = 19,
+ LOOPBACK_XAUI_WS = 20,
+ LOOPBACK_XAUI_WS_FAR = 21,
+ LOOPBACK_XAUI_WS_NEAR = 22,
+ LOOPBACK_GMII_WS = 23,
+ LOOPBACK_XFI_WS = 24,
+ LOOPBACK_XFI_WS_FAR = 25,
+ LOOPBACK_PHYXS_WS = 26,
+ LOOPBACK_MAX
+};
+#define LOOPBACK_TEST_MAX LOOPBACK_PMAPMD
+
+/* These loopbacks occur within the controller */
+#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_DATA) | \
+ (1 << LOOPBACK_GMAC) | \
+ (1 << LOOPBACK_XGMII)| \
+ (1 << LOOPBACK_XGXS) | \
+ (1 << LOOPBACK_XAUI) | \
+ (1 << LOOPBACK_GMII) | \
+ (1 << LOOPBACK_SGMII) | \
+ (1 << LOOPBACK_SGMII) | \
+ (1 << LOOPBACK_XGBR) | \
+ (1 << LOOPBACK_XFI) | \
+ (1 << LOOPBACK_XAUI_FAR) | \
+ (1 << LOOPBACK_GMII_FAR) | \
+ (1 << LOOPBACK_SGMII_FAR) | \
+ (1 << LOOPBACK_XFI_FAR) | \
+ (1 << LOOPBACK_XGMII_WS) | \
+ (1 << LOOPBACK_XAUI_WS) | \
+ (1 << LOOPBACK_XAUI_WS_FAR) | \
+ (1 << LOOPBACK_XAUI_WS_NEAR) | \
+ (1 << LOOPBACK_GMII_WS) | \
+ (1 << LOOPBACK_XFI_WS) | \
+ (1 << LOOPBACK_XFI_WS_FAR))
+
+#define LOOPBACKS_WS ((1 << LOOPBACK_XGMII_WS) | \
+ (1 << LOOPBACK_XAUI_WS) | \
+ (1 << LOOPBACK_XAUI_WS_FAR) | \
+ (1 << LOOPBACK_XAUI_WS_NEAR) | \
+ (1 << LOOPBACK_GMII_WS) | \
+ (1 << LOOPBACK_XFI_WS) | \
+ (1 << LOOPBACK_XFI_WS_FAR) | \
+ (1 << LOOPBACK_PHYXS_WS))
+
+#define LOOPBACKS_EXTERNAL(_efx) \
+ ((_efx)->loopback_modes & ~LOOPBACKS_INTERNAL & \
+ ~(1 << LOOPBACK_NONE))
+
+#define LOOPBACK_MASK(_efx) \
+ (1 << (_efx)->loopback_mode)
+
+#define LOOPBACK_INTERNAL(_efx) \
+ (!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx)))
+
+#define LOOPBACK_EXTERNAL(_efx) \
+ (!!(LOOPBACK_MASK(_efx) & LOOPBACKS_EXTERNAL(_efx)))
+
+#define LOOPBACK_CHANGED(_from, _to, _mask) \
+ (!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask)))
+
+#define LOOPBACK_OUT_OF(_from, _to, _mask) \
+ ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask)))
+
+/*****************************************************************************/
+
+/**
+ * enum reset_type - reset types
+ *
+ * %RESET_TYPE_INVSIBLE, %RESET_TYPE_ALL, %RESET_TYPE_WORLD and
+ * %RESET_TYPE_DISABLE specify the method/scope of the reset. The
+ * other valuesspecify reasons, which ef4_schedule_reset() will choose
+ * a method for.
+ *
+ * Reset methods are numbered in order of increasing scope.
+ *
+ * @RESET_TYPE_INVISIBLE: Reset datapath and MAC
+ * @RESET_TYPE_RECOVER_OR_ALL: Try to recover. Apply RESET_TYPE_ALL
+ * if unsuccessful.
+ * @RESET_TYPE_ALL: Reset datapath, MAC and PHY
+ * @RESET_TYPE_WORLD: Reset as much as possible
+ * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if
+ * unsuccessful.
+ * @RESET_TYPE_DATAPATH: Reset datapath only.
+ * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
+ * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
+ * @RESET_TYPE_INT_ERROR: reset due to internal error
+ * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
+ * @RESET_TYPE_DMA_ERROR: DMA error
+ * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
+ */
+enum reset_type {
+ RESET_TYPE_INVISIBLE,
+ RESET_TYPE_RECOVER_OR_ALL,
+ RESET_TYPE_ALL,
+ RESET_TYPE_WORLD,
+ RESET_TYPE_RECOVER_OR_DISABLE,
+ RESET_TYPE_DATAPATH,
+ RESET_TYPE_DISABLE,
+ RESET_TYPE_MAX_METHOD,
+ RESET_TYPE_TX_WATCHDOG,
+ RESET_TYPE_INT_ERROR,
+ RESET_TYPE_RX_RECOVERY,
+ RESET_TYPE_DMA_ERROR,
+ RESET_TYPE_TX_SKIP,
+ RESET_TYPE_MAX,
+};
+
+#endif /* EF4_ENUM_H */
diff --git a/drivers/net/ethernet/sfc/falcon/ethtool.c b/drivers/net/ethernet/sfc/falcon/ethtool.c
new file mode 100644
index 000000000000..8e1929b01a32
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/ethtool.c
@@ -0,0 +1,1343 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <linux/in.h>
+#include "net_driver.h"
+#include "workarounds.h"
+#include "selftest.h"
+#include "efx.h"
+#include "filter.h"
+#include "nic.h"
+
+struct ef4_sw_stat_desc {
+ const char *name;
+ enum {
+ EF4_ETHTOOL_STAT_SOURCE_nic,
+ EF4_ETHTOOL_STAT_SOURCE_channel,
+ EF4_ETHTOOL_STAT_SOURCE_tx_queue
+ } source;
+ unsigned offset;
+ u64(*get_stat) (void *field); /* Reader function */
+};
+
+/* Initialiser for a struct ef4_sw_stat_desc with type-checking */
+#define EF4_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
+ get_stat_function) { \
+ .name = #stat_name, \
+ .source = EF4_ETHTOOL_STAT_SOURCE_##source_name, \
+ .offset = ((((field_type *) 0) == \
+ &((struct ef4_##source_name *)0)->field) ? \
+ offsetof(struct ef4_##source_name, field) : \
+ offsetof(struct ef4_##source_name, field)), \
+ .get_stat = get_stat_function, \
+}
+
+static u64 ef4_get_uint_stat(void *field)
+{
+ return *(unsigned int *)field;
+}
+
+static u64 ef4_get_atomic_stat(void *field)
+{
+ return atomic_read((atomic_t *) field);
+}
+
+#define EF4_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \
+ EF4_ETHTOOL_STAT(field, nic, field, \
+ atomic_t, ef4_get_atomic_stat)
+
+#define EF4_ETHTOOL_UINT_CHANNEL_STAT(field) \
+ EF4_ETHTOOL_STAT(field, channel, n_##field, \
+ unsigned int, ef4_get_uint_stat)
+
+#define EF4_ETHTOOL_UINT_TXQ_STAT(field) \
+ EF4_ETHTOOL_STAT(tx_##field, tx_queue, field, \
+ unsigned int, ef4_get_uint_stat)
+
+static const struct ef4_sw_stat_desc ef4_sw_stat_desc[] = {
+ EF4_ETHTOOL_UINT_TXQ_STAT(merge_events),
+ EF4_ETHTOOL_UINT_TXQ_STAT(pushes),
+ EF4_ETHTOOL_UINT_TXQ_STAT(cb_packets),
+ EF4_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
+ EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
+};
+
+#define EF4_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(ef4_sw_stat_desc)
+
+#define EF4_ETHTOOL_EEPROM_MAGIC 0xEFAB
+
+/**************************************************************************
+ *
+ * Ethtool operations
+ *
+ **************************************************************************
+ */
+
+/* Identify device by flashing LEDs */
+static int ef4_ethtool_phys_id(struct net_device *net_dev,
+ enum ethtool_phys_id_state state)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ enum ef4_led_mode mode = EF4_LED_DEFAULT;
+
+ switch (state) {
+ case ETHTOOL_ID_ON:
+ mode = EF4_LED_ON;
+ break;
+ case ETHTOOL_ID_OFF:
+ mode = EF4_LED_OFF;
+ break;
+ case ETHTOOL_ID_INACTIVE:
+ mode = EF4_LED_DEFAULT;
+ break;
+ case ETHTOOL_ID_ACTIVE:
+ return 1; /* cycle on/off once per second */
+ }
+
+ efx->type->set_id_led(efx, mode);
+ return 0;
+}
+
+/* This must be called with rtnl_lock held. */
+static int ef4_ethtool_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_link_state *link_state = &efx->link_state;
+
+ mutex_lock(&efx->mac_lock);
+ efx->phy_op->get_settings(efx, ecmd);
+ mutex_unlock(&efx->mac_lock);
+
+ /* Both MACs support pause frames (bidirectional and respond-only) */
+ ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+
+ if (LOOPBACK_INTERNAL(efx)) {
+ ethtool_cmd_speed_set(ecmd, link_state->speed);
+ ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF;
+ }
+
+ return 0;
+}
+
+/* This must be called with rtnl_lock held. */
+static int ef4_ethtool_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int rc;
+
+ /* GMAC does not support 1000Mbps HD */
+ if ((ethtool_cmd_speed(ecmd) == SPEED_1000) &&
+ (ecmd->duplex != DUPLEX_FULL)) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "rejecting unsupported 1000Mbps HD setting\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&efx->mac_lock);
+ rc = efx->phy_op->set_settings(efx, ecmd);
+ mutex_unlock(&efx->mac_lock);
+ return rc;
+}
+
+static void ef4_ethtool_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+ strlcpy(info->version, EF4_DRIVER_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
+}
+
+static int ef4_ethtool_get_regs_len(struct net_device *net_dev)
+{
+ return ef4_nic_get_regs_len(netdev_priv(net_dev));
+}
+
+static void ef4_ethtool_get_regs(struct net_device *net_dev,
+ struct ethtool_regs *regs, void *buf)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ regs->version = efx->type->revision;
+ ef4_nic_get_regs(efx, buf);
+}
+
+static u32 ef4_ethtool_get_msglevel(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ return efx->msg_enable;
+}
+
+static void ef4_ethtool_set_msglevel(struct net_device *net_dev, u32 msg_enable)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ efx->msg_enable = msg_enable;
+}
+
+/**
+ * ef4_fill_test - fill in an individual self-test entry
+ * @test_index: Index of the test
+ * @strings: Ethtool strings, or %NULL
+ * @data: Ethtool test results, or %NULL
+ * @test: Pointer to test result (used only if data != %NULL)
+ * @unit_format: Unit name format (e.g. "chan\%d")
+ * @unit_id: Unit id (e.g. 0 for "chan0")
+ * @test_format: Test name format (e.g. "loopback.\%s.tx.sent")
+ * @test_id: Test id (e.g. "PHYXS" for "loopback.PHYXS.tx_sent")
+ *
+ * Fill in an individual self-test entry.
+ */
+static void ef4_fill_test(unsigned int test_index, u8 *strings, u64 *data,
+ int *test, const char *unit_format, int unit_id,
+ const char *test_format, const char *test_id)
+{
+ char unit_str[ETH_GSTRING_LEN], test_str[ETH_GSTRING_LEN];
+
+ /* Fill data value, if applicable */
+ if (data)
+ data[test_index] = *test;
+
+ /* Fill string, if applicable */
+ if (strings) {
+ if (strchr(unit_format, '%'))
+ snprintf(unit_str, sizeof(unit_str),
+ unit_format, unit_id);
+ else
+ strcpy(unit_str, unit_format);
+ snprintf(test_str, sizeof(test_str), test_format, test_id);
+ snprintf(strings + test_index * ETH_GSTRING_LEN,
+ ETH_GSTRING_LEN,
+ "%-6s %-24s", unit_str, test_str);
+ }
+}
+
+#define EF4_CHANNEL_NAME(_channel) "chan%d", _channel->channel
+#define EF4_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
+#define EF4_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
+#define EF4_LOOPBACK_NAME(_mode, _counter) \
+ "loopback.%s." _counter, STRING_TABLE_LOOKUP(_mode, ef4_loopback_mode)
+
+/**
+ * ef4_fill_loopback_test - fill in a block of loopback self-test entries
+ * @efx: Efx NIC
+ * @lb_tests: Efx loopback self-test results structure
+ * @mode: Loopback test mode
+ * @test_index: Starting index of the test
+ * @strings: Ethtool strings, or %NULL
+ * @data: Ethtool test results, or %NULL
+ *
+ * Fill in a block of loopback self-test entries. Return new test
+ * index.
+ */
+static int ef4_fill_loopback_test(struct ef4_nic *efx,
+ struct ef4_loopback_self_tests *lb_tests,
+ enum ef4_loopback_mode mode,
+ unsigned int test_index,
+ u8 *strings, u64 *data)
+{
+ struct ef4_channel *channel =
+ ef4_get_channel(efx, efx->tx_channel_offset);
+ struct ef4_tx_queue *tx_queue;
+
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ ef4_fill_test(test_index++, strings, data,
+ &lb_tests->tx_sent[tx_queue->queue],
+ EF4_TX_QUEUE_NAME(tx_queue),
+ EF4_LOOPBACK_NAME(mode, "tx_sent"));
+ ef4_fill_test(test_index++, strings, data,
+ &lb_tests->tx_done[tx_queue->queue],
+ EF4_TX_QUEUE_NAME(tx_queue),
+ EF4_LOOPBACK_NAME(mode, "tx_done"));
+ }
+ ef4_fill_test(test_index++, strings, data,
+ &lb_tests->rx_good,
+ "rx", 0,
+ EF4_LOOPBACK_NAME(mode, "rx_good"));
+ ef4_fill_test(test_index++, strings, data,
+ &lb_tests->rx_bad,
+ "rx", 0,
+ EF4_LOOPBACK_NAME(mode, "rx_bad"));
+
+ return test_index;
+}
+
+/**
+ * ef4_ethtool_fill_self_tests - get self-test details
+ * @efx: Efx NIC
+ * @tests: Efx self-test results structure, or %NULL
+ * @strings: Ethtool strings, or %NULL
+ * @data: Ethtool test results, or %NULL
+ *
+ * Get self-test number of strings, strings, and/or test results.
+ * Return number of strings (== number of test results).
+ *
+ * The reason for merging these three functions is to make sure that
+ * they can never be inconsistent.
+ */
+static int ef4_ethtool_fill_self_tests(struct ef4_nic *efx,
+ struct ef4_self_tests *tests,
+ u8 *strings, u64 *data)
+{
+ struct ef4_channel *channel;
+ unsigned int n = 0, i;
+ enum ef4_loopback_mode mode;
+
+ ef4_fill_test(n++, strings, data, &tests->phy_alive,
+ "phy", 0, "alive", NULL);
+ ef4_fill_test(n++, strings, data, &tests->nvram,
+ "core", 0, "nvram", NULL);
+ ef4_fill_test(n++, strings, data, &tests->interrupt,
+ "core", 0, "interrupt", NULL);
+
+ /* Event queues */
+ ef4_for_each_channel(channel, efx) {
+ ef4_fill_test(n++, strings, data,
+ &tests->eventq_dma[channel->channel],
+ EF4_CHANNEL_NAME(channel),
+ "eventq.dma", NULL);
+ ef4_fill_test(n++, strings, data,
+ &tests->eventq_int[channel->channel],
+ EF4_CHANNEL_NAME(channel),
+ "eventq.int", NULL);
+ }
+
+ ef4_fill_test(n++, strings, data, &tests->memory,
+ "core", 0, "memory", NULL);
+ ef4_fill_test(n++, strings, data, &tests->registers,
+ "core", 0, "registers", NULL);
+
+ if (efx->phy_op->run_tests != NULL) {
+ EF4_BUG_ON_PARANOID(efx->phy_op->test_name == NULL);
+
+ for (i = 0; true; ++i) {
+ const char *name;
+
+ EF4_BUG_ON_PARANOID(i >= EF4_MAX_PHY_TESTS);
+ name = efx->phy_op->test_name(efx, i);
+ if (name == NULL)
+ break;
+
+ ef4_fill_test(n++, strings, data, &tests->phy_ext[i],
+ "phy", 0, name, NULL);
+ }
+ }
+
+ /* Loopback tests */
+ for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
+ if (!(efx->loopback_modes & (1 << mode)))
+ continue;
+ n = ef4_fill_loopback_test(efx,
+ &tests->loopback[mode], mode, n,
+ strings, data);
+ }
+
+ return n;
+}
+
+static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 *strings)
+{
+ size_t n_stats = 0;
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx) {
+ if (ef4_channel_has_tx_queues(channel)) {
+ n_stats++;
+ if (strings != NULL) {
+ snprintf(strings, ETH_GSTRING_LEN,
+ "tx-%u.tx_packets",
+ channel->tx_queue[0].queue /
+ EF4_TXQ_TYPES);
+
+ strings += ETH_GSTRING_LEN;
+ }
+ }
+ }
+ ef4_for_each_channel(channel, efx) {
+ if (ef4_channel_has_rx_queue(channel)) {
+ n_stats++;
+ if (strings != NULL) {
+ snprintf(strings, ETH_GSTRING_LEN,
+ "rx-%d.rx_packets", channel->channel);
+ strings += ETH_GSTRING_LEN;
+ }
+ }
+ }
+ return n_stats;
+}
+
+static int ef4_ethtool_get_sset_count(struct net_device *net_dev,
+ int string_set)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ switch (string_set) {
+ case ETH_SS_STATS:
+ return efx->type->describe_stats(efx, NULL) +
+ EF4_ETHTOOL_SW_STAT_COUNT +
+ ef4_describe_per_queue_stats(efx, NULL);
+ case ETH_SS_TEST:
+ return ef4_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
+ default:
+ return -EINVAL;
+ }
+}
+
+static void ef4_ethtool_get_strings(struct net_device *net_dev,
+ u32 string_set, u8 *strings)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int i;
+
+ switch (string_set) {
+ case ETH_SS_STATS:
+ strings += (efx->type->describe_stats(efx, strings) *
+ ETH_GSTRING_LEN);
+ for (i = 0; i < EF4_ETHTOOL_SW_STAT_COUNT; i++)
+ strlcpy(strings + i * ETH_GSTRING_LEN,
+ ef4_sw_stat_desc[i].name, ETH_GSTRING_LEN);
+ strings += EF4_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
+ strings += (ef4_describe_per_queue_stats(efx, strings) *
+ ETH_GSTRING_LEN);
+ break;
+ case ETH_SS_TEST:
+ ef4_ethtool_fill_self_tests(efx, NULL, strings, NULL);
+ break;
+ default:
+ /* No other string sets */
+ break;
+ }
+}
+
+static void ef4_ethtool_get_stats(struct net_device *net_dev,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ const struct ef4_sw_stat_desc *stat;
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+ int i;
+
+ spin_lock_bh(&efx->stats_lock);
+
+ /* Get NIC statistics */
+ data += efx->type->update_stats(efx, data, NULL);
+
+ /* Get software statistics */
+ for (i = 0; i < EF4_ETHTOOL_SW_STAT_COUNT; i++) {
+ stat = &ef4_sw_stat_desc[i];
+ switch (stat->source) {
+ case EF4_ETHTOOL_STAT_SOURCE_nic:
+ data[i] = stat->get_stat((void *)efx + stat->offset);
+ break;
+ case EF4_ETHTOOL_STAT_SOURCE_channel:
+ data[i] = 0;
+ ef4_for_each_channel(channel, efx)
+ data[i] += stat->get_stat((void *)channel +
+ stat->offset);
+ break;
+ case EF4_ETHTOOL_STAT_SOURCE_tx_queue:
+ data[i] = 0;
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_tx_queue(tx_queue, channel)
+ data[i] +=
+ stat->get_stat((void *)tx_queue
+ + stat->offset);
+ }
+ break;
+ }
+ }
+ data += EF4_ETHTOOL_SW_STAT_COUNT;
+
+ spin_unlock_bh(&efx->stats_lock);
+
+ ef4_for_each_channel(channel, efx) {
+ if (ef4_channel_has_tx_queues(channel)) {
+ *data = 0;
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ *data += tx_queue->tx_packets;
+ }
+ data++;
+ }
+ }
+ ef4_for_each_channel(channel, efx) {
+ if (ef4_channel_has_rx_queue(channel)) {
+ *data = 0;
+ ef4_for_each_channel_rx_queue(rx_queue, channel) {
+ *data += rx_queue->rx_packets;
+ }
+ data++;
+ }
+ }
+}
+
+static void ef4_ethtool_self_test(struct net_device *net_dev,
+ struct ethtool_test *test, u64 *data)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_self_tests *ef4_tests;
+ bool already_up;
+ int rc = -ENOMEM;
+
+ ef4_tests = kzalloc(sizeof(*ef4_tests), GFP_KERNEL);
+ if (!ef4_tests)
+ goto fail;
+
+ if (efx->state != STATE_READY) {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ netif_info(efx, drv, efx->net_dev, "starting %sline testing\n",
+ (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+
+ /* We need rx buffers and interrupts. */
+ already_up = (efx->net_dev->flags & IFF_UP);
+ if (!already_up) {
+ rc = dev_open(efx->net_dev);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "failed opening device.\n");
+ goto out;
+ }
+ }
+
+ rc = ef4_selftest(efx, ef4_tests, test->flags);
+
+ if (!already_up)
+ dev_close(efx->net_dev);
+
+ netif_info(efx, drv, efx->net_dev, "%s %sline self-tests\n",
+ rc == 0 ? "passed" : "failed",
+ (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+
+out:
+ ef4_ethtool_fill_self_tests(efx, ef4_tests, NULL, data);
+ kfree(ef4_tests);
+fail:
+ if (rc)
+ test->flags |= ETH_TEST_FL_FAILED;
+}
+
+/* Restart autonegotiation */
+static int ef4_ethtool_nway_reset(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ return mdio45_nway_restart(&efx->mdio);
+}
+
+/*
+ * Each channel has a single IRQ and moderation timer, started by any
+ * completion (or other event). Unless the module parameter
+ * separate_tx_channels is set, IRQs and moderation are therefore
+ * shared between RX and TX completions. In this case, when RX IRQ
+ * moderation is explicitly changed then TX IRQ moderation is
+ * automatically changed too, but otherwise we fail if the two values
+ * are requested to be different.
+ *
+ * The hardware does not support a limit on the number of completions
+ * before an IRQ, so we do not use the max_frames fields. We should
+ * report and require that max_frames == (usecs != 0), but this would
+ * invalidate existing user documentation.
+ *
+ * The hardware does not have distinct settings for interrupt
+ * moderation while the previous IRQ is being handled, so we should
+ * not use the 'irq' fields. However, an earlier developer
+ * misunderstood the meaning of the 'irq' fields and the driver did
+ * not support the standard fields. To avoid invalidating existing
+ * user documentation, we report and accept changes through either the
+ * standard or 'irq' fields. If both are changed at the same time, we
+ * prefer the standard field.
+ *
+ * We implement adaptive IRQ moderation, but use a different algorithm
+ * from that assumed in the definition of struct ethtool_coalesce.
+ * Therefore we do not use any of the adaptive moderation parameters
+ * in it.
+ */
+
+static int ef4_ethtool_get_coalesce(struct net_device *net_dev,
+ struct ethtool_coalesce *coalesce)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ unsigned int tx_usecs, rx_usecs;
+ bool rx_adaptive;
+
+ ef4_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &rx_adaptive);
+
+ coalesce->tx_coalesce_usecs = tx_usecs;
+ coalesce->tx_coalesce_usecs_irq = tx_usecs;
+ coalesce->rx_coalesce_usecs = rx_usecs;
+ coalesce->rx_coalesce_usecs_irq = rx_usecs;
+ coalesce->use_adaptive_rx_coalesce = rx_adaptive;
+
+ return 0;
+}
+
+static int ef4_ethtool_set_coalesce(struct net_device *net_dev,
+ struct ethtool_coalesce *coalesce)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_channel *channel;
+ unsigned int tx_usecs, rx_usecs;
+ bool adaptive, rx_may_override_tx;
+ int rc;
+
+ if (coalesce->use_adaptive_tx_coalesce)
+ return -EINVAL;
+
+ ef4_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &adaptive);
+
+ if (coalesce->rx_coalesce_usecs != rx_usecs)
+ rx_usecs = coalesce->rx_coalesce_usecs;
+ else
+ rx_usecs = coalesce->rx_coalesce_usecs_irq;
+
+ adaptive = coalesce->use_adaptive_rx_coalesce;
+
+ /* If channels are shared, TX IRQ moderation can be quietly
+ * overridden unless it is changed from its old value.
+ */
+ rx_may_override_tx = (coalesce->tx_coalesce_usecs == tx_usecs &&
+ coalesce->tx_coalesce_usecs_irq == tx_usecs);
+ if (coalesce->tx_coalesce_usecs != tx_usecs)
+ tx_usecs = coalesce->tx_coalesce_usecs;
+ else
+ tx_usecs = coalesce->tx_coalesce_usecs_irq;
+
+ rc = ef4_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive,
+ rx_may_override_tx);
+ if (rc != 0)
+ return rc;
+
+ ef4_for_each_channel(channel, efx)
+ efx->type->push_irq_moderation(channel);
+
+ return 0;
+}
+
+static void ef4_ethtool_get_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ ring->rx_max_pending = EF4_MAX_DMAQ_SIZE;
+ ring->tx_max_pending = EF4_MAX_DMAQ_SIZE;
+ ring->rx_pending = efx->rxq_entries;
+ ring->tx_pending = efx->txq_entries;
+}
+
+static int ef4_ethtool_set_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ u32 txq_entries;
+
+ if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
+ ring->rx_pending > EF4_MAX_DMAQ_SIZE ||
+ ring->tx_pending > EF4_MAX_DMAQ_SIZE)
+ return -EINVAL;
+
+ if (ring->rx_pending < EF4_RXQ_MIN_ENT) {
+ netif_err(efx, drv, efx->net_dev,
+ "RX queues cannot be smaller than %u\n",
+ EF4_RXQ_MIN_ENT);
+ return -EINVAL;
+ }
+
+ txq_entries = max(ring->tx_pending, EF4_TXQ_MIN_ENT(efx));
+ if (txq_entries != ring->tx_pending)
+ netif_warn(efx, drv, efx->net_dev,
+ "increasing TX queue size to minimum of %u\n",
+ txq_entries);
+
+ return ef4_realloc_channels(efx, ring->rx_pending, txq_entries);
+}
+
+static int ef4_ethtool_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ u8 wanted_fc, old_fc;
+ u32 old_adv;
+ int rc = 0;
+
+ mutex_lock(&efx->mac_lock);
+
+ wanted_fc = ((pause->rx_pause ? EF4_FC_RX : 0) |
+ (pause->tx_pause ? EF4_FC_TX : 0) |
+ (pause->autoneg ? EF4_FC_AUTO : 0));
+
+ if ((wanted_fc & EF4_FC_TX) && !(wanted_fc & EF4_FC_RX)) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "Flow control unsupported: tx ON rx OFF\n");
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if ((wanted_fc & EF4_FC_AUTO) && !efx->link_advertising) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "Autonegotiation is disabled\n");
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Hook for Falcon bug 11482 workaround */
+ if (efx->type->prepare_enable_fc_tx &&
+ (wanted_fc & EF4_FC_TX) && !(efx->wanted_fc & EF4_FC_TX))
+ efx->type->prepare_enable_fc_tx(efx);
+
+ old_adv = efx->link_advertising;
+ old_fc = efx->wanted_fc;
+ ef4_link_set_wanted_fc(efx, wanted_fc);
+ if (efx->link_advertising != old_adv ||
+ (efx->wanted_fc ^ old_fc) & EF4_FC_AUTO) {
+ rc = efx->phy_op->reconfigure(efx);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "Unable to advertise requested flow "
+ "control setting\n");
+ goto out;
+ }
+ }
+
+ /* Reconfigure the MAC. The PHY *may* generate a link state change event
+ * if the user just changed the advertised capabilities, but there's no
+ * harm doing this twice */
+ ef4_mac_reconfigure(efx);
+
+out:
+ mutex_unlock(&efx->mac_lock);
+
+ return rc;
+}
+
+static void ef4_ethtool_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ pause->rx_pause = !!(efx->wanted_fc & EF4_FC_RX);
+ pause->tx_pause = !!(efx->wanted_fc & EF4_FC_TX);
+ pause->autoneg = !!(efx->wanted_fc & EF4_FC_AUTO);
+}
+
+static void ef4_ethtool_get_wol(struct net_device *net_dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ return efx->type->get_wol(efx, wol);
+}
+
+
+static int ef4_ethtool_set_wol(struct net_device *net_dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ return efx->type->set_wol(efx, wol->wolopts);
+}
+
+static int ef4_ethtool_reset(struct net_device *net_dev, u32 *flags)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int rc;
+
+ rc = efx->type->map_reset_flags(flags);
+ if (rc < 0)
+ return rc;
+
+ return ef4_reset(efx, rc);
+}
+
+/* MAC address mask including only I/G bit */
+static const u8 mac_addr_ig_mask[ETH_ALEN] __aligned(2) = {0x01, 0, 0, 0, 0, 0};
+
+#define IP4_ADDR_FULL_MASK ((__force __be32)~0)
+#define IP_PROTO_FULL_MASK 0xFF
+#define PORT_FULL_MASK ((__force __be16)~0)
+#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
+
+static inline void ip6_fill_mask(__be32 *mask)
+{
+ mask[0] = mask[1] = mask[2] = mask[3] = ~(__be32)0;
+}
+
+static int ef4_ethtool_get_class_rule(struct ef4_nic *efx,
+ struct ethtool_rx_flow_spec *rule)
+{
+ struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec;
+ struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec;
+ struct ethtool_usrip4_spec *uip_entry = &rule->h_u.usr_ip4_spec;
+ struct ethtool_usrip4_spec *uip_mask = &rule->m_u.usr_ip4_spec;
+ struct ethtool_tcpip6_spec *ip6_entry = &rule->h_u.tcp_ip6_spec;
+ struct ethtool_tcpip6_spec *ip6_mask = &rule->m_u.tcp_ip6_spec;
+ struct ethtool_usrip6_spec *uip6_entry = &rule->h_u.usr_ip6_spec;
+ struct ethtool_usrip6_spec *uip6_mask = &rule->m_u.usr_ip6_spec;
+ struct ethhdr *mac_entry = &rule->h_u.ether_spec;
+ struct ethhdr *mac_mask = &rule->m_u.ether_spec;
+ struct ef4_filter_spec spec;
+ int rc;
+
+ rc = ef4_filter_get_filter_safe(efx, EF4_FILTER_PRI_MANUAL,
+ rule->location, &spec);
+ if (rc)
+ return rc;
+
+ if (spec.dmaq_id == EF4_FILTER_RX_DMAQ_ID_DROP)
+ rule->ring_cookie = RX_CLS_FLOW_DISC;
+ else
+ rule->ring_cookie = spec.dmaq_id;
+
+ if ((spec.match_flags & EF4_FILTER_MATCH_ETHER_TYPE) &&
+ spec.ether_type == htons(ETH_P_IP) &&
+ (spec.match_flags & EF4_FILTER_MATCH_IP_PROTO) &&
+ (spec.ip_proto == IPPROTO_TCP || spec.ip_proto == IPPROTO_UDP) &&
+ !(spec.match_flags &
+ ~(EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_OUTER_VID |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_REM_HOST |
+ EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_PORT | EF4_FILTER_MATCH_REM_PORT))) {
+ rule->flow_type = ((spec.ip_proto == IPPROTO_TCP) ?
+ TCP_V4_FLOW : UDP_V4_FLOW);
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_HOST) {
+ ip_entry->ip4dst = spec.loc_host[0];
+ ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_HOST) {
+ ip_entry->ip4src = spec.rem_host[0];
+ ip_mask->ip4src = IP4_ADDR_FULL_MASK;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_PORT) {
+ ip_entry->pdst = spec.loc_port;
+ ip_mask->pdst = PORT_FULL_MASK;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_PORT) {
+ ip_entry->psrc = spec.rem_port;
+ ip_mask->psrc = PORT_FULL_MASK;
+ }
+ } else if ((spec.match_flags & EF4_FILTER_MATCH_ETHER_TYPE) &&
+ spec.ether_type == htons(ETH_P_IPV6) &&
+ (spec.match_flags & EF4_FILTER_MATCH_IP_PROTO) &&
+ (spec.ip_proto == IPPROTO_TCP || spec.ip_proto == IPPROTO_UDP) &&
+ !(spec.match_flags &
+ ~(EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_OUTER_VID |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_REM_HOST |
+ EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_PORT | EF4_FILTER_MATCH_REM_PORT))) {
+ rule->flow_type = ((spec.ip_proto == IPPROTO_TCP) ?
+ TCP_V6_FLOW : UDP_V6_FLOW);
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_HOST) {
+ memcpy(ip6_entry->ip6dst, spec.loc_host,
+ sizeof(ip6_entry->ip6dst));
+ ip6_fill_mask(ip6_mask->ip6dst);
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_HOST) {
+ memcpy(ip6_entry->ip6src, spec.rem_host,
+ sizeof(ip6_entry->ip6src));
+ ip6_fill_mask(ip6_mask->ip6src);
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_PORT) {
+ ip6_entry->pdst = spec.loc_port;
+ ip6_mask->pdst = PORT_FULL_MASK;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_PORT) {
+ ip6_entry->psrc = spec.rem_port;
+ ip6_mask->psrc = PORT_FULL_MASK;
+ }
+ } else if (!(spec.match_flags &
+ ~(EF4_FILTER_MATCH_LOC_MAC | EF4_FILTER_MATCH_LOC_MAC_IG |
+ EF4_FILTER_MATCH_REM_MAC | EF4_FILTER_MATCH_ETHER_TYPE |
+ EF4_FILTER_MATCH_OUTER_VID))) {
+ rule->flow_type = ETHER_FLOW;
+ if (spec.match_flags &
+ (EF4_FILTER_MATCH_LOC_MAC | EF4_FILTER_MATCH_LOC_MAC_IG)) {
+ ether_addr_copy(mac_entry->h_dest, spec.loc_mac);
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_MAC)
+ eth_broadcast_addr(mac_mask->h_dest);
+ else
+ ether_addr_copy(mac_mask->h_dest,
+ mac_addr_ig_mask);
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_MAC) {
+ ether_addr_copy(mac_entry->h_source, spec.rem_mac);
+ eth_broadcast_addr(mac_mask->h_source);
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_ETHER_TYPE) {
+ mac_entry->h_proto = spec.ether_type;
+ mac_mask->h_proto = ETHER_TYPE_FULL_MASK;
+ }
+ } else if (spec.match_flags & EF4_FILTER_MATCH_ETHER_TYPE &&
+ spec.ether_type == htons(ETH_P_IP) &&
+ !(spec.match_flags &
+ ~(EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_OUTER_VID |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_REM_HOST |
+ EF4_FILTER_MATCH_IP_PROTO))) {
+ rule->flow_type = IPV4_USER_FLOW;
+ uip_entry->ip_ver = ETH_RX_NFC_IP4;
+ if (spec.match_flags & EF4_FILTER_MATCH_IP_PROTO) {
+ uip_mask->proto = IP_PROTO_FULL_MASK;
+ uip_entry->proto = spec.ip_proto;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_HOST) {
+ uip_entry->ip4dst = spec.loc_host[0];
+ uip_mask->ip4dst = IP4_ADDR_FULL_MASK;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_HOST) {
+ uip_entry->ip4src = spec.rem_host[0];
+ uip_mask->ip4src = IP4_ADDR_FULL_MASK;
+ }
+ } else if (spec.match_flags & EF4_FILTER_MATCH_ETHER_TYPE &&
+ spec.ether_type == htons(ETH_P_IPV6) &&
+ !(spec.match_flags &
+ ~(EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_OUTER_VID |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_REM_HOST |
+ EF4_FILTER_MATCH_IP_PROTO))) {
+ rule->flow_type = IPV6_USER_FLOW;
+ if (spec.match_flags & EF4_FILTER_MATCH_IP_PROTO) {
+ uip6_mask->l4_proto = IP_PROTO_FULL_MASK;
+ uip6_entry->l4_proto = spec.ip_proto;
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_LOC_HOST) {
+ memcpy(uip6_entry->ip6dst, spec.loc_host,
+ sizeof(uip6_entry->ip6dst));
+ ip6_fill_mask(uip6_mask->ip6dst);
+ }
+ if (spec.match_flags & EF4_FILTER_MATCH_REM_HOST) {
+ memcpy(uip6_entry->ip6src, spec.rem_host,
+ sizeof(uip6_entry->ip6src));
+ ip6_fill_mask(uip6_mask->ip6src);
+ }
+ } else {
+ /* The above should handle all filters that we insert */
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (spec.match_flags & EF4_FILTER_MATCH_OUTER_VID) {
+ rule->flow_type |= FLOW_EXT;
+ rule->h_ext.vlan_tci = spec.outer_vid;
+ rule->m_ext.vlan_tci = htons(0xfff);
+ }
+
+ return rc;
+}
+
+static int
+ef4_ethtool_get_rxnfc(struct net_device *net_dev,
+ struct ethtool_rxnfc *info, u32 *rule_locs)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ switch (info->cmd) {
+ case ETHTOOL_GRXRINGS:
+ info->data = efx->n_rx_channels;
+ return 0;
+
+ case ETHTOOL_GRXFH: {
+ unsigned min_revision = 0;
+
+ info->data = 0;
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case IPV4_FLOW:
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ min_revision = EF4_REV_FALCON_B0;
+ break;
+ default:
+ break;
+ }
+ if (ef4_nic_rev(efx) < min_revision)
+ info->data = 0;
+ return 0;
+ }
+
+ case ETHTOOL_GRXCLSRLCNT:
+ info->data = ef4_filter_get_rx_id_limit(efx);
+ if (info->data == 0)
+ return -EOPNOTSUPP;
+ info->data |= RX_CLS_LOC_SPECIAL;
+ info->rule_cnt =
+ ef4_filter_count_rx_used(efx, EF4_FILTER_PRI_MANUAL);
+ return 0;
+
+ case ETHTOOL_GRXCLSRULE:
+ if (ef4_filter_get_rx_id_limit(efx) == 0)
+ return -EOPNOTSUPP;
+ return ef4_ethtool_get_class_rule(efx, &info->fs);
+
+ case ETHTOOL_GRXCLSRLALL: {
+ s32 rc;
+ info->data = ef4_filter_get_rx_id_limit(efx);
+ if (info->data == 0)
+ return -EOPNOTSUPP;
+ rc = ef4_filter_get_rx_ids(efx, EF4_FILTER_PRI_MANUAL,
+ rule_locs, info->rule_cnt);
+ if (rc < 0)
+ return rc;
+ info->rule_cnt = rc;
+ return 0;
+ }
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static inline bool ip6_mask_is_full(__be32 mask[4])
+{
+ return !~(mask[0] & mask[1] & mask[2] & mask[3]);
+}
+
+static inline bool ip6_mask_is_empty(__be32 mask[4])
+{
+ return !(mask[0] | mask[1] | mask[2] | mask[3]);
+}
+
+static int ef4_ethtool_set_class_rule(struct ef4_nic *efx,
+ struct ethtool_rx_flow_spec *rule)
+{
+ struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec;
+ struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec;
+ struct ethtool_usrip4_spec *uip_entry = &rule->h_u.usr_ip4_spec;
+ struct ethtool_usrip4_spec *uip_mask = &rule->m_u.usr_ip4_spec;
+ struct ethtool_tcpip6_spec *ip6_entry = &rule->h_u.tcp_ip6_spec;
+ struct ethtool_tcpip6_spec *ip6_mask = &rule->m_u.tcp_ip6_spec;
+ struct ethtool_usrip6_spec *uip6_entry = &rule->h_u.usr_ip6_spec;
+ struct ethtool_usrip6_spec *uip6_mask = &rule->m_u.usr_ip6_spec;
+ struct ethhdr *mac_entry = &rule->h_u.ether_spec;
+ struct ethhdr *mac_mask = &rule->m_u.ether_spec;
+ struct ef4_filter_spec spec;
+ int rc;
+
+ /* Check that user wants us to choose the location */
+ if (rule->location != RX_CLS_LOC_ANY)
+ return -EINVAL;
+
+ /* Range-check ring_cookie */
+ if (rule->ring_cookie >= efx->n_rx_channels &&
+ rule->ring_cookie != RX_CLS_FLOW_DISC)
+ return -EINVAL;
+
+ /* Check for unsupported extensions */
+ if ((rule->flow_type & FLOW_EXT) &&
+ (rule->m_ext.vlan_etype || rule->m_ext.data[0] ||
+ rule->m_ext.data[1]))
+ return -EINVAL;
+
+ ef4_filter_init_rx(&spec, EF4_FILTER_PRI_MANUAL,
+ efx->rx_scatter ? EF4_FILTER_FLAG_RX_SCATTER : 0,
+ (rule->ring_cookie == RX_CLS_FLOW_DISC) ?
+ EF4_FILTER_RX_DMAQ_ID_DROP : rule->ring_cookie);
+
+ switch (rule->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ spec.match_flags = (EF4_FILTER_MATCH_ETHER_TYPE |
+ EF4_FILTER_MATCH_IP_PROTO);
+ spec.ether_type = htons(ETH_P_IP);
+ spec.ip_proto = ((rule->flow_type & ~FLOW_EXT) == TCP_V4_FLOW ?
+ IPPROTO_TCP : IPPROTO_UDP);
+ if (ip_mask->ip4dst) {
+ if (ip_mask->ip4dst != IP4_ADDR_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_HOST;
+ spec.loc_host[0] = ip_entry->ip4dst;
+ }
+ if (ip_mask->ip4src) {
+ if (ip_mask->ip4src != IP4_ADDR_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_HOST;
+ spec.rem_host[0] = ip_entry->ip4src;
+ }
+ if (ip_mask->pdst) {
+ if (ip_mask->pdst != PORT_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_PORT;
+ spec.loc_port = ip_entry->pdst;
+ }
+ if (ip_mask->psrc) {
+ if (ip_mask->psrc != PORT_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_PORT;
+ spec.rem_port = ip_entry->psrc;
+ }
+ if (ip_mask->tos)
+ return -EINVAL;
+ break;
+
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ spec.match_flags = (EF4_FILTER_MATCH_ETHER_TYPE |
+ EF4_FILTER_MATCH_IP_PROTO);
+ spec.ether_type = htons(ETH_P_IPV6);
+ spec.ip_proto = ((rule->flow_type & ~FLOW_EXT) == TCP_V6_FLOW ?
+ IPPROTO_TCP : IPPROTO_UDP);
+ if (!ip6_mask_is_empty(ip6_mask->ip6dst)) {
+ if (!ip6_mask_is_full(ip6_mask->ip6dst))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_HOST;
+ memcpy(spec.loc_host, ip6_entry->ip6dst, sizeof(spec.loc_host));
+ }
+ if (!ip6_mask_is_empty(ip6_mask->ip6src)) {
+ if (!ip6_mask_is_full(ip6_mask->ip6src))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_HOST;
+ memcpy(spec.rem_host, ip6_entry->ip6src, sizeof(spec.rem_host));
+ }
+ if (ip6_mask->pdst) {
+ if (ip6_mask->pdst != PORT_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_PORT;
+ spec.loc_port = ip6_entry->pdst;
+ }
+ if (ip6_mask->psrc) {
+ if (ip6_mask->psrc != PORT_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_PORT;
+ spec.rem_port = ip6_entry->psrc;
+ }
+ if (ip6_mask->tclass)
+ return -EINVAL;
+ break;
+
+ case IPV4_USER_FLOW:
+ if (uip_mask->l4_4_bytes || uip_mask->tos || uip_mask->ip_ver ||
+ uip_entry->ip_ver != ETH_RX_NFC_IP4)
+ return -EINVAL;
+ spec.match_flags = EF4_FILTER_MATCH_ETHER_TYPE;
+ spec.ether_type = htons(ETH_P_IP);
+ if (uip_mask->ip4dst) {
+ if (uip_mask->ip4dst != IP4_ADDR_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_HOST;
+ spec.loc_host[0] = uip_entry->ip4dst;
+ }
+ if (uip_mask->ip4src) {
+ if (uip_mask->ip4src != IP4_ADDR_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_HOST;
+ spec.rem_host[0] = uip_entry->ip4src;
+ }
+ if (uip_mask->proto) {
+ if (uip_mask->proto != IP_PROTO_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_IP_PROTO;
+ spec.ip_proto = uip_entry->proto;
+ }
+ break;
+
+ case IPV6_USER_FLOW:
+ if (uip6_mask->l4_4_bytes || uip6_mask->tclass)
+ return -EINVAL;
+ spec.match_flags = EF4_FILTER_MATCH_ETHER_TYPE;
+ spec.ether_type = htons(ETH_P_IPV6);
+ if (!ip6_mask_is_empty(uip6_mask->ip6dst)) {
+ if (!ip6_mask_is_full(uip6_mask->ip6dst))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_HOST;
+ memcpy(spec.loc_host, uip6_entry->ip6dst, sizeof(spec.loc_host));
+ }
+ if (!ip6_mask_is_empty(uip6_mask->ip6src)) {
+ if (!ip6_mask_is_full(uip6_mask->ip6src))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_HOST;
+ memcpy(spec.rem_host, uip6_entry->ip6src, sizeof(spec.rem_host));
+ }
+ if (uip6_mask->l4_proto) {
+ if (uip6_mask->l4_proto != IP_PROTO_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_IP_PROTO;
+ spec.ip_proto = uip6_entry->l4_proto;
+ }
+ break;
+
+ case ETHER_FLOW:
+ if (!is_zero_ether_addr(mac_mask->h_dest)) {
+ if (ether_addr_equal(mac_mask->h_dest,
+ mac_addr_ig_mask))
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_MAC_IG;
+ else if (is_broadcast_ether_addr(mac_mask->h_dest))
+ spec.match_flags |= EF4_FILTER_MATCH_LOC_MAC;
+ else
+ return -EINVAL;
+ ether_addr_copy(spec.loc_mac, mac_entry->h_dest);
+ }
+ if (!is_zero_ether_addr(mac_mask->h_source)) {
+ if (!is_broadcast_ether_addr(mac_mask->h_source))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_REM_MAC;
+ ether_addr_copy(spec.rem_mac, mac_entry->h_source);
+ }
+ if (mac_mask->h_proto) {
+ if (mac_mask->h_proto != ETHER_TYPE_FULL_MASK)
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_ETHER_TYPE;
+ spec.ether_type = mac_entry->h_proto;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((rule->flow_type & FLOW_EXT) && rule->m_ext.vlan_tci) {
+ if (rule->m_ext.vlan_tci != htons(0xfff))
+ return -EINVAL;
+ spec.match_flags |= EF4_FILTER_MATCH_OUTER_VID;
+ spec.outer_vid = rule->h_ext.vlan_tci;
+ }
+
+ rc = ef4_filter_insert_filter(efx, &spec, true);
+ if (rc < 0)
+ return rc;
+
+ rule->location = rc;
+ return 0;
+}
+
+static int ef4_ethtool_set_rxnfc(struct net_device *net_dev,
+ struct ethtool_rxnfc *info)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ if (ef4_filter_get_rx_id_limit(efx) == 0)
+ return -EOPNOTSUPP;
+
+ switch (info->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ return ef4_ethtool_set_class_rule(efx, &info->fs);
+
+ case ETHTOOL_SRXCLSRLDEL:
+ return ef4_filter_remove_id_safe(efx, EF4_FILTER_PRI_MANUAL,
+ info->fs.location);
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static u32 ef4_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ return ((ef4_nic_rev(efx) < EF4_REV_FALCON_B0 ||
+ efx->n_rx_channels == 1) ?
+ 0 : ARRAY_SIZE(efx->rx_indir_table));
+}
+
+static int ef4_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+ if (indir)
+ memcpy(indir, efx->rx_indir_table, sizeof(efx->rx_indir_table));
+ return 0;
+}
+
+static int ef4_ethtool_set_rxfh(struct net_device *net_dev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+
+ /* We do not allow change in unsupported parameters */
+ if (key ||
+ (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
+ return -EOPNOTSUPP;
+ if (!indir)
+ return 0;
+
+ return efx->type->rx_push_rss_config(efx, true, indir);
+}
+
+static int ef4_ethtool_get_module_eeprom(struct net_device *net_dev,
+ struct ethtool_eeprom *ee,
+ u8 *data)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int ret;
+
+ if (!efx->phy_op || !efx->phy_op->get_module_eeprom)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&efx->mac_lock);
+ ret = efx->phy_op->get_module_eeprom(efx, ee, data);
+ mutex_unlock(&efx->mac_lock);
+
+ return ret;
+}
+
+static int ef4_ethtool_get_module_info(struct net_device *net_dev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ int ret;
+
+ if (!efx->phy_op || !efx->phy_op->get_module_info)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&efx->mac_lock);
+ ret = efx->phy_op->get_module_info(efx, modinfo);
+ mutex_unlock(&efx->mac_lock);
+
+ return ret;
+}
+
+const struct ethtool_ops ef4_ethtool_ops = {
+ .get_settings = ef4_ethtool_get_settings,
+ .set_settings = ef4_ethtool_set_settings,
+ .get_drvinfo = ef4_ethtool_get_drvinfo,
+ .get_regs_len = ef4_ethtool_get_regs_len,
+ .get_regs = ef4_ethtool_get_regs,
+ .get_msglevel = ef4_ethtool_get_msglevel,
+ .set_msglevel = ef4_ethtool_set_msglevel,
+ .nway_reset = ef4_ethtool_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_coalesce = ef4_ethtool_get_coalesce,
+ .set_coalesce = ef4_ethtool_set_coalesce,
+ .get_ringparam = ef4_ethtool_get_ringparam,
+ .set_ringparam = ef4_ethtool_set_ringparam,
+ .get_pauseparam = ef4_ethtool_get_pauseparam,
+ .set_pauseparam = ef4_ethtool_set_pauseparam,
+ .get_sset_count = ef4_ethtool_get_sset_count,
+ .self_test = ef4_ethtool_self_test,
+ .get_strings = ef4_ethtool_get_strings,
+ .set_phys_id = ef4_ethtool_phys_id,
+ .get_ethtool_stats = ef4_ethtool_get_stats,
+ .get_wol = ef4_ethtool_get_wol,
+ .set_wol = ef4_ethtool_set_wol,
+ .reset = ef4_ethtool_reset,
+ .get_rxnfc = ef4_ethtool_get_rxnfc,
+ .set_rxnfc = ef4_ethtool_set_rxnfc,
+ .get_rxfh_indir_size = ef4_ethtool_get_rxfh_indir_size,
+ .get_rxfh = ef4_ethtool_get_rxfh,
+ .set_rxfh = ef4_ethtool_set_rxfh,
+ .get_module_info = ef4_ethtool_get_module_info,
+ .get_module_eeprom = ef4_ethtool_get_module_eeprom,
+};
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c
index 1a7092602aec..c6ff0cc5ef18 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon/falcon.c
@@ -145,7 +145,7 @@
#define GENERIC_SW_STAT(ext_name) \
[GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
-static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
+static const struct ef4_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
FALCON_DMA_STAT(tx_bytes, XgTxOctets),
FALCON_DMA_STAT(tx_packets, XgTxPkts),
FALCON_DMA_STAT(tx_pause, XgTxPausePkts),
@@ -273,34 +273,34 @@ struct falcon_nvconfig_board_v3 {
#define SPI_DEV_TYPE_BLOCK_SIZE_LBN 24
#define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH 5
#define SPI_DEV_TYPE_FIELD(type, field) \
- (((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(EFX_WIDTH(field)))
+ (((type) >> EF4_LOW_BIT(field)) & EF4_MASK32(EF4_WIDTH(field)))
#define FALCON_NVCONFIG_OFFSET 0x300
#define FALCON_NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
struct falcon_nvconfig {
- efx_oword_t ee_vpd_cfg_reg; /* 0x300 */
+ ef4_oword_t ee_vpd_cfg_reg; /* 0x300 */
u8 mac_address[2][8]; /* 0x310 */
- efx_oword_t pcie_sd_ctl0123_reg; /* 0x320 */
- efx_oword_t pcie_sd_ctl45_reg; /* 0x330 */
- efx_oword_t pcie_pcs_ctl_stat_reg; /* 0x340 */
- efx_oword_t hw_init_reg; /* 0x350 */
- efx_oword_t nic_stat_reg; /* 0x360 */
- efx_oword_t glb_ctl_reg; /* 0x370 */
- efx_oword_t srm_cfg_reg; /* 0x380 */
- efx_oword_t spare_reg; /* 0x390 */
+ ef4_oword_t pcie_sd_ctl0123_reg; /* 0x320 */
+ ef4_oword_t pcie_sd_ctl45_reg; /* 0x330 */
+ ef4_oword_t pcie_pcs_ctl_stat_reg; /* 0x340 */
+ ef4_oword_t hw_init_reg; /* 0x350 */
+ ef4_oword_t nic_stat_reg; /* 0x360 */
+ ef4_oword_t glb_ctl_reg; /* 0x370 */
+ ef4_oword_t srm_cfg_reg; /* 0x380 */
+ ef4_oword_t spare_reg; /* 0x390 */
__le16 board_magic_num; /* 0x3A0 */
__le16 board_struct_ver;
__le16 board_checksum;
struct falcon_nvconfig_board_v2 board_v2;
- efx_oword_t ee_base_page_reg; /* 0x3B0 */
+ ef4_oword_t ee_base_page_reg; /* 0x3B0 */
struct falcon_nvconfig_board_v3 board_v3; /* 0x3C0 */
} __packed;
/*************************************************************************/
-static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
-static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
+static int falcon_reset_hw(struct ef4_nic *efx, enum reset_type method);
+static void falcon_reconfigure_mac_wrapper(struct ef4_nic *efx);
static const unsigned int
/* "Large" EEPROM device: Atmel AT25640 or similar
@@ -326,40 +326,40 @@ default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN)
*/
static void falcon_setsda(void *data, int state)
{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
+ struct ef4_nic *efx = (struct ef4_nic *)data;
+ ef4_oword_t reg;
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN, !state);
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
+ ef4_reado(efx, &reg, FR_AB_GPIO_CTL);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN, !state);
+ ef4_writeo(efx, &reg, FR_AB_GPIO_CTL);
}
static void falcon_setscl(void *data, int state)
{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
+ struct ef4_nic *efx = (struct ef4_nic *)data;
+ ef4_oword_t reg;
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO0_OEN, !state);
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
+ ef4_reado(efx, &reg, FR_AB_GPIO_CTL);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_GPIO0_OEN, !state);
+ ef4_writeo(efx, &reg, FR_AB_GPIO_CTL);
}
static int falcon_getsda(void *data)
{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
+ struct ef4_nic *efx = (struct ef4_nic *)data;
+ ef4_oword_t reg;
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- return EFX_OWORD_FIELD(reg, FRF_AB_GPIO3_IN);
+ ef4_reado(efx, &reg, FR_AB_GPIO_CTL);
+ return EF4_OWORD_FIELD(reg, FRF_AB_GPIO3_IN);
}
static int falcon_getscl(void *data)
{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
+ struct ef4_nic *efx = (struct ef4_nic *)data;
+ ef4_oword_t reg;
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN);
+ ef4_reado(efx, &reg, FR_AB_GPIO_CTL);
+ return EF4_OWORD_FIELD(reg, FRF_AB_GPIO0_IN);
}
static const struct i2c_algo_bit_data falcon_i2c_bit_operations = {
@@ -372,35 +372,35 @@ static const struct i2c_algo_bit_data falcon_i2c_bit_operations = {
.timeout = DIV_ROUND_UP(HZ, 20),
};
-static void falcon_push_irq_moderation(struct efx_channel *channel)
+static void falcon_push_irq_moderation(struct ef4_channel *channel)
{
- efx_dword_t timer_cmd;
- struct efx_nic *efx = channel->efx;
+ ef4_dword_t timer_cmd;
+ struct ef4_nic *efx = channel->efx;
/* Set timer register */
if (channel->irq_moderation_us) {
unsigned int ticks;
- ticks = efx_usecs_to_ticks(efx, channel->irq_moderation_us);
- EFX_POPULATE_DWORD_2(timer_cmd,
+ ticks = ef4_usecs_to_ticks(efx, channel->irq_moderation_us);
+ EF4_POPULATE_DWORD_2(timer_cmd,
FRF_AB_TC_TIMER_MODE,
FFE_BB_TIMER_MODE_INT_HLDOFF,
FRF_AB_TC_TIMER_VAL,
ticks - 1);
} else {
- EFX_POPULATE_DWORD_2(timer_cmd,
+ EF4_POPULATE_DWORD_2(timer_cmd,
FRF_AB_TC_TIMER_MODE,
FFE_BB_TIMER_MODE_DIS,
FRF_AB_TC_TIMER_VAL, 0);
}
BUILD_BUG_ON(FR_AA_TIMER_COMMAND_KER != FR_BZ_TIMER_COMMAND_P0);
- efx_writed_page_locked(efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
+ ef4_writed_page_locked(efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
channel->channel);
}
-static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
+static void falcon_deconfigure_mac_wrapper(struct ef4_nic *efx);
-static void falcon_prepare_flush(struct efx_nic *efx)
+static void falcon_prepare_flush(struct ef4_nic *efx)
{
falcon_deconfigure_mac_wrapper(efx);
@@ -420,26 +420,26 @@ static void falcon_prepare_flush(struct efx_nic *efx)
*
* NB most hardware supports MSI interrupts
*/
-static inline void falcon_irq_ack_a1(struct efx_nic *efx)
+static inline void falcon_irq_ack_a1(struct ef4_nic *efx)
{
- efx_dword_t reg;
+ ef4_dword_t reg;
- EFX_POPULATE_DWORD_1(reg, FRF_AA_INT_ACK_KER_FIELD, 0xb7eb7e);
- efx_writed(efx, &reg, FR_AA_INT_ACK_KER);
- efx_readd(efx, &reg, FR_AA_WORK_AROUND_BROKEN_PCI_READS);
+ EF4_POPULATE_DWORD_1(reg, FRF_AA_INT_ACK_KER_FIELD, 0xb7eb7e);
+ ef4_writed(efx, &reg, FR_AA_INT_ACK_KER);
+ ef4_readd(efx, &reg, FR_AA_WORK_AROUND_BROKEN_PCI_READS);
}
static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
{
- struct efx_nic *efx = dev_id;
- efx_oword_t *int_ker = efx->irq_status.addr;
+ struct ef4_nic *efx = dev_id;
+ ef4_oword_t *int_ker = efx->irq_status.addr;
int syserr;
int queues;
/* Check to see if this is our interrupt. If it isn't, we
* exit without having touched the hardware.
*/
- if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) {
+ if (unlikely(EF4_OWORD_IS_ZERO(*int_ker))) {
netif_vdbg(efx, intr, efx->net_dev,
"IRQ %d on CPU %d not for me\n", irq,
raw_smp_processor_id());
@@ -447,30 +447,30 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
}
efx->last_irq_cpu = raw_smp_processor_id();
netif_vdbg(efx, intr, efx->net_dev,
- "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
- irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ "IRQ %d on CPU %d status " EF4_OWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EF4_OWORD_VAL(*int_ker));
if (!likely(ACCESS_ONCE(efx->irq_soft_enabled)))
return IRQ_HANDLED;
/* Check to see if we have a serious error condition */
- syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
+ syserr = EF4_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
- return efx_farch_fatal_interrupt(efx);
+ return ef4_farch_fatal_interrupt(efx);
/* Determine interrupting queues, clear interrupt status
* register and acknowledge the device interrupt.
*/
- BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS);
- queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q);
- EFX_ZERO_OWORD(*int_ker);
+ BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EF4_MAX_CHANNELS);
+ queues = EF4_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q);
+ EF4_ZERO_OWORD(*int_ker);
wmb(); /* Ensure the vector is cleared before interrupt ack */
falcon_irq_ack_a1(efx);
if (queues & 1)
- efx_schedule_channel_irq(efx_get_channel(efx, 0));
+ ef4_schedule_channel_irq(ef4_get_channel(efx, 0));
if (queues & 2)
- efx_schedule_channel_irq(efx_get_channel(efx, 1));
+ ef4_schedule_channel_irq(ef4_get_channel(efx, 1));
return IRQ_HANDLED;
}
@@ -480,7 +480,7 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
*
**************************************************************************
*/
-static int dummy_rx_push_rss_config(struct efx_nic *efx, bool user,
+static int dummy_rx_push_rss_config(struct ef4_nic *efx, bool user,
const u32 *rx_indir_table)
{
(void) efx;
@@ -489,19 +489,19 @@ static int dummy_rx_push_rss_config(struct efx_nic *efx, bool user,
return -ENOSYS;
}
-static int falcon_b0_rx_push_rss_config(struct efx_nic *efx, bool user,
+static int falcon_b0_rx_push_rss_config(struct ef4_nic *efx, bool user,
const u32 *rx_indir_table)
{
- efx_oword_t temp;
+ ef4_oword_t temp;
(void) user;
/* Set hash key for IPv4 */
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
- efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
+ ef4_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
memcpy(efx->rx_indir_table, rx_indir_table,
sizeof(efx->rx_indir_table));
- efx_farch_rx_push_indir_table(efx);
+ ef4_farch_rx_push_indir_table(efx);
return 0;
}
@@ -512,17 +512,17 @@ static int falcon_b0_rx_push_rss_config(struct efx_nic *efx, bool user,
**************************************************************************
*/
-#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
+#define FALCON_SPI_MAX_LEN sizeof(ef4_oword_t)
-static int falcon_spi_poll(struct efx_nic *efx)
+static int falcon_spi_poll(struct ef4_nic *efx)
{
- efx_oword_t reg;
- efx_reado(efx, &reg, FR_AB_EE_SPI_HCMD);
- return EFX_OWORD_FIELD(reg, FRF_AB_EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
+ ef4_oword_t reg;
+ ef4_reado(efx, &reg, FR_AB_EE_SPI_HCMD);
+ return EF4_OWORD_FIELD(reg, FRF_AB_EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
}
/* Wait for SPI command completion */
-static int falcon_spi_wait(struct efx_nic *efx)
+static int falcon_spi_wait(struct ef4_nic *efx)
{
/* Most commands will finish quickly, so we start polling at
* very short intervals. Sometimes the command may have to
@@ -550,13 +550,13 @@ static int falcon_spi_wait(struct efx_nic *efx)
}
static int
-falcon_spi_cmd(struct efx_nic *efx, const struct falcon_spi_device *spi,
+falcon_spi_cmd(struct ef4_nic *efx, const struct falcon_spi_device *spi,
unsigned int command, int address,
const void *in, void *out, size_t len)
{
bool addressed = (address >= 0);
bool reading = (out != NULL);
- efx_oword_t reg;
+ ef4_oword_t reg;
int rc;
/* Input validation */
@@ -570,18 +570,18 @@ falcon_spi_cmd(struct efx_nic *efx, const struct falcon_spi_device *spi,
/* Program address register, if we have an address */
if (addressed) {
- EFX_POPULATE_OWORD_1(reg, FRF_AB_EE_SPI_HADR_ADR, address);
- efx_writeo(efx, &reg, FR_AB_EE_SPI_HADR);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_EE_SPI_HADR_ADR, address);
+ ef4_writeo(efx, &reg, FR_AB_EE_SPI_HADR);
}
/* Program data register, if we have data */
if (in != NULL) {
memcpy(&reg, in, len);
- efx_writeo(efx, &reg, FR_AB_EE_SPI_HDATA);
+ ef4_writeo(efx, &reg, FR_AB_EE_SPI_HDATA);
}
/* Issue read/write command */
- EFX_POPULATE_OWORD_7(reg,
+ EF4_POPULATE_OWORD_7(reg,
FRF_AB_EE_SPI_HCMD_CMD_EN, 1,
FRF_AB_EE_SPI_HCMD_SF_SEL, spi->device_id,
FRF_AB_EE_SPI_HCMD_DABCNT, len,
@@ -590,7 +590,7 @@ falcon_spi_cmd(struct efx_nic *efx, const struct falcon_spi_device *spi,
FRF_AB_EE_SPI_HCMD_ADBCNT,
(addressed ? spi->addr_len : 0),
FRF_AB_EE_SPI_HCMD_ENC, command);
- efx_writeo(efx, &reg, FR_AB_EE_SPI_HCMD);
+ ef4_writeo(efx, &reg, FR_AB_EE_SPI_HCMD);
/* Wait for read/write to complete */
rc = falcon_spi_wait(efx);
@@ -599,7 +599,7 @@ falcon_spi_cmd(struct efx_nic *efx, const struct falcon_spi_device *spi,
/* Read data */
if (out != NULL) {
- efx_reado(efx, &reg, FR_AB_EE_SPI_HDATA);
+ ef4_reado(efx, &reg, FR_AB_EE_SPI_HDATA);
memcpy(out, &reg, len);
}
@@ -614,7 +614,7 @@ falcon_spi_munge_command(const struct falcon_spi_device *spi,
}
static int
-falcon_spi_read(struct efx_nic *efx, const struct falcon_spi_device *spi,
+falcon_spi_read(struct ef4_nic *efx, const struct falcon_spi_device *spi,
loff_t start, size_t len, size_t *retlen, u8 *buffer)
{
size_t block_len, pos = 0;
@@ -644,10 +644,10 @@ falcon_spi_read(struct efx_nic *efx, const struct falcon_spi_device *spi,
return rc;
}
-#ifdef CONFIG_SFC_MTD
+#ifdef CONFIG_SFC_FALCON_MTD
struct falcon_mtd_partition {
- struct efx_mtd_partition common;
+ struct ef4_mtd_partition common;
const struct falcon_spi_device *spi;
size_t offset;
};
@@ -664,7 +664,7 @@ falcon_spi_write_limit(const struct falcon_spi_device *spi, size_t start)
/* Wait up to 10 ms for buffered write completion */
static int
-falcon_spi_wait_write(struct efx_nic *efx, const struct falcon_spi_device *spi)
+falcon_spi_wait_write(struct ef4_nic *efx, const struct falcon_spi_device *spi)
{
unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
u8 status;
@@ -689,7 +689,7 @@ falcon_spi_wait_write(struct efx_nic *efx, const struct falcon_spi_device *spi)
}
static int
-falcon_spi_write(struct efx_nic *efx, const struct falcon_spi_device *spi,
+falcon_spi_write(struct ef4_nic *efx, const struct falcon_spi_device *spi,
loff_t start, size_t len, size_t *retlen, const u8 *buffer)
{
u8 verify_buffer[FALCON_SPI_MAX_LEN];
@@ -741,7 +741,7 @@ static int
falcon_spi_slow_wait(struct falcon_mtd_partition *part, bool uninterruptible)
{
const struct falcon_spi_device *spi = part->spi;
- struct efx_nic *efx = part->common.mtd.priv;
+ struct ef4_nic *efx = part->common.mtd.priv;
u8 status;
int rc, i;
@@ -765,7 +765,7 @@ falcon_spi_slow_wait(struct falcon_mtd_partition *part, bool uninterruptible)
}
static int
-falcon_spi_unlock(struct efx_nic *efx, const struct falcon_spi_device *spi)
+falcon_spi_unlock(struct ef4_nic *efx, const struct falcon_spi_device *spi)
{
const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
SPI_STATUS_BP0);
@@ -805,7 +805,7 @@ static int
falcon_spi_erase(struct falcon_mtd_partition *part, loff_t start, size_t len)
{
const struct falcon_spi_device *spi = part->spi;
- struct efx_nic *efx = part->common.mtd.priv;
+ struct ef4_nic *efx = part->common.mtd.priv;
unsigned pos, block_len;
u8 empty[FALCON_SPI_VERIFY_BUF_LEN];
u8 buffer[FALCON_SPI_VERIFY_BUF_LEN];
@@ -849,9 +849,9 @@ falcon_spi_erase(struct falcon_mtd_partition *part, loff_t start, size_t len)
return rc;
}
-static void falcon_mtd_rename(struct efx_mtd_partition *part)
+static void falcon_mtd_rename(struct ef4_mtd_partition *part)
{
- struct efx_nic *efx = part->mtd.priv;
+ struct ef4_nic *efx = part->mtd.priv;
snprintf(part->name, sizeof(part->name), "%s %s",
efx->name, part->type_name);
@@ -861,7 +861,7 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
size_t len, size_t *retlen, u8 *buffer)
{
struct falcon_mtd_partition *part = to_falcon_mtd_partition(mtd);
- struct efx_nic *efx = mtd->priv;
+ struct ef4_nic *efx = mtd->priv;
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -877,7 +877,7 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
{
struct falcon_mtd_partition *part = to_falcon_mtd_partition(mtd);
- struct efx_nic *efx = mtd->priv;
+ struct ef4_nic *efx = mtd->priv;
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -893,7 +893,7 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
size_t len, size_t *retlen, const u8 *buffer)
{
struct falcon_mtd_partition *part = to_falcon_mtd_partition(mtd);
- struct efx_nic *efx = mtd->priv;
+ struct ef4_nic *efx = mtd->priv;
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -909,7 +909,7 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
static int falcon_mtd_sync(struct mtd_info *mtd)
{
struct falcon_mtd_partition *part = to_falcon_mtd_partition(mtd);
- struct efx_nic *efx = mtd->priv;
+ struct ef4_nic *efx = mtd->priv;
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -919,7 +919,7 @@ static int falcon_mtd_sync(struct mtd_info *mtd)
return rc;
}
-static int falcon_mtd_probe(struct efx_nic *efx)
+static int falcon_mtd_probe(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
struct falcon_mtd_partition *parts;
@@ -963,13 +963,13 @@ static int falcon_mtd_probe(struct efx_nic *efx)
n_parts++;
}
- rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
+ rc = ef4_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
if (rc)
kfree(parts);
return rc;
}
-#endif /* CONFIG_SFC_MTD */
+#endif /* CONFIG_SFC_FALCON_MTD */
/**************************************************************************
*
@@ -979,27 +979,27 @@ static int falcon_mtd_probe(struct efx_nic *efx)
*/
/* Configure the XAUI driver that is an output from Falcon */
-static void falcon_setup_xaui(struct efx_nic *efx)
+static void falcon_setup_xaui(struct ef4_nic *efx)
{
- efx_oword_t sdctl, txdrv;
+ ef4_oword_t sdctl, txdrv;
/* Move the XAUI into low power, unless there is no PHY, in
* which case the XAUI will have to drive a cable. */
if (efx->phy_type == PHY_TYPE_NONE)
return;
- efx_reado(efx, &sdctl, FR_AB_XX_SD_CTL);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
- EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
- efx_writeo(efx, &sdctl, FR_AB_XX_SD_CTL);
-
- EFX_POPULATE_OWORD_8(txdrv,
+ ef4_reado(efx, &sdctl, FR_AB_XX_SD_CTL);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
+ EF4_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
+ ef4_writeo(efx, &sdctl, FR_AB_XX_SD_CTL);
+
+ EF4_POPULATE_OWORD_8(txdrv,
FRF_AB_XX_DEQD, FFE_AB_XX_TXDRV_DEQ_DEF,
FRF_AB_XX_DEQC, FFE_AB_XX_TXDRV_DEQ_DEF,
FRF_AB_XX_DEQB, FFE_AB_XX_TXDRV_DEQ_DEF,
@@ -1008,27 +1008,27 @@ static void falcon_setup_xaui(struct efx_nic *efx)
FRF_AB_XX_DTXC, FFE_AB_XX_TXDRV_DTX_DEF,
FRF_AB_XX_DTXB, FFE_AB_XX_TXDRV_DTX_DEF,
FRF_AB_XX_DTXA, FFE_AB_XX_TXDRV_DTX_DEF);
- efx_writeo(efx, &txdrv, FR_AB_XX_TXDRV_CTL);
+ ef4_writeo(efx, &txdrv, FR_AB_XX_TXDRV_CTL);
}
-int falcon_reset_xaui(struct efx_nic *efx)
+int falcon_reset_xaui(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg;
+ ef4_oword_t reg;
int count;
/* Don't fetch MAC statistics over an XMAC reset */
WARN_ON(nic_data->stats_disable_count == 0);
/* Start reset sequence */
- EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
- efx_writeo(efx, &reg, FR_AB_XX_PWR_RST);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
+ ef4_writeo(efx, &reg, FR_AB_XX_PWR_RST);
/* Wait up to 10 ms for completion, then reinitialise */
for (count = 0; count < 1000; count++) {
- efx_reado(efx, &reg, FR_AB_XX_PWR_RST);
- if (EFX_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 &&
- EFX_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) {
+ ef4_reado(efx, &reg, FR_AB_XX_PWR_RST);
+ if (EF4_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 &&
+ EF4_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) {
falcon_setup_xaui(efx);
return 0;
}
@@ -1039,12 +1039,12 @@ int falcon_reset_xaui(struct efx_nic *efx)
return -ETIMEDOUT;
}
-static void falcon_ack_status_intr(struct efx_nic *efx)
+static void falcon_ack_status_intr(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg;
+ ef4_oword_t reg;
- if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx))
+ if ((ef4_nic_rev(efx) != EF4_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx))
return;
/* We expect xgmii faults if the wireside link is down */
@@ -1056,33 +1056,33 @@ static void falcon_ack_status_intr(struct efx_nic *efx)
if (nic_data->xmac_poll_required)
return;
- efx_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK);
+ ef4_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK);
}
-static bool falcon_xgxs_link_ok(struct efx_nic *efx)
+static bool falcon_xgxs_link_ok(struct ef4_nic *efx)
{
- efx_oword_t reg;
+ ef4_oword_t reg;
bool align_done, link_ok = false;
int sync_status;
/* Read link status */
- efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
+ ef4_reado(efx, &reg, FR_AB_XX_CORE_STAT);
- align_done = EFX_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE);
- sync_status = EFX_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT);
+ align_done = EF4_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE);
+ sync_status = EF4_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT);
if (align_done && (sync_status == FFE_AB_XX_STAT_ALL_LANES))
link_ok = true;
/* Clear link status ready for next read */
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES);
- efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES);
+ ef4_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
return link_ok;
}
-static bool falcon_xmac_link_ok(struct efx_nic *efx)
+static bool falcon_xmac_link_ok(struct ef4_nic *efx)
{
/*
* Check MAC's XGXS link status except when using XGMII loopback
@@ -1094,66 +1094,66 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx)
falcon_xgxs_link_ok(efx)) &&
(!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) ||
LOOPBACK_INTERNAL(efx) ||
- efx_mdio_phyxgxs_lane_sync(efx));
+ ef4_mdio_phyxgxs_lane_sync(efx));
}
-static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
+static void falcon_reconfigure_xmac_core(struct ef4_nic *efx)
{
unsigned int max_frame_len;
- efx_oword_t reg;
- bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX);
- bool tx_fc = !!(efx->link_state.fc & EFX_FC_TX);
+ ef4_oword_t reg;
+ bool rx_fc = !!(efx->link_state.fc & EF4_FC_RX);
+ bool tx_fc = !!(efx->link_state.fc & EF4_FC_TX);
/* Configure MAC - cut-thru mode is hard wired on */
- EFX_POPULATE_OWORD_3(reg,
+ EF4_POPULATE_OWORD_3(reg,
FRF_AB_XM_RX_JUMBO_MODE, 1,
FRF_AB_XM_TX_STAT_EN, 1,
FRF_AB_XM_RX_STAT_EN, 1);
- efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
+ ef4_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
/* Configure TX */
- EFX_POPULATE_OWORD_6(reg,
+ EF4_POPULATE_OWORD_6(reg,
FRF_AB_XM_TXEN, 1,
FRF_AB_XM_TX_PRMBL, 1,
FRF_AB_XM_AUTO_PAD, 1,
FRF_AB_XM_TXCRC, 1,
FRF_AB_XM_FCNTL, tx_fc,
FRF_AB_XM_IPG, 0x3);
- efx_writeo(efx, &reg, FR_AB_XM_TX_CFG);
+ ef4_writeo(efx, &reg, FR_AB_XM_TX_CFG);
/* Configure RX */
- EFX_POPULATE_OWORD_5(reg,
+ EF4_POPULATE_OWORD_5(reg,
FRF_AB_XM_RXEN, 1,
FRF_AB_XM_AUTO_DEPAD, 0,
FRF_AB_XM_ACPT_ALL_MCAST, 1,
FRF_AB_XM_ACPT_ALL_UCAST, !efx->unicast_filter,
FRF_AB_XM_PASS_CRC_ERR, 1);
- efx_writeo(efx, &reg, FR_AB_XM_RX_CFG);
+ ef4_writeo(efx, &reg, FR_AB_XM_RX_CFG);
/* Set frame length */
- max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
- EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
- efx_writeo(efx, &reg, FR_AB_XM_RX_PARAM);
- EFX_POPULATE_OWORD_2(reg,
+ max_frame_len = EF4_MAX_FRAME_LEN(efx->net_dev->mtu);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
+ ef4_writeo(efx, &reg, FR_AB_XM_RX_PARAM);
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len,
FRF_AB_XM_TX_JUMBO_MODE, 1);
- efx_writeo(efx, &reg, FR_AB_XM_TX_PARAM);
+ ef4_writeo(efx, &reg, FR_AB_XM_TX_PARAM);
- EFX_POPULATE_OWORD_2(reg,
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
FRF_AB_XM_DIS_FCNTL, !rx_fc);
- efx_writeo(efx, &reg, FR_AB_XM_FC);
+ ef4_writeo(efx, &reg, FR_AB_XM_FC);
/* Set MAC address */
memcpy(&reg, &efx->net_dev->dev_addr[0], 4);
- efx_writeo(efx, &reg, FR_AB_XM_ADR_LO);
+ ef4_writeo(efx, &reg, FR_AB_XM_ADR_LO);
memcpy(&reg, &efx->net_dev->dev_addr[4], 2);
- efx_writeo(efx, &reg, FR_AB_XM_ADR_HI);
+ ef4_writeo(efx, &reg, FR_AB_XM_ADR_HI);
}
-static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
+static void falcon_reconfigure_xgxs_core(struct ef4_nic *efx)
{
- efx_oword_t reg;
+ ef4_oword_t reg;
bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS);
bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI);
bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII);
@@ -1161,12 +1161,12 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
/* XGXS block is flaky and will need to be reset if moving
* into our out of XGMII, XGXS or XAUI loopbacks. */
- efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
- old_xgxs_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN);
- old_xgmii_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN);
+ ef4_reado(efx, &reg, FR_AB_XX_CORE_STAT);
+ old_xgxs_loopback = EF4_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN);
+ old_xgmii_loopback = EF4_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN);
- efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
- old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA);
+ ef4_reado(efx, &reg, FR_AB_XX_SD_CTL);
+ old_xaui_loopback = EF4_OWORD_FIELD(reg, FRF_AB_XX_LPBKA);
/* The PHY driver may have turned XAUI off */
if ((xgxs_loopback != old_xgxs_loopback) ||
@@ -1174,30 +1174,30 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
(xgmii_loopback != old_xgmii_loopback))
falcon_reset_xaui(efx);
- efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG,
+ ef4_reado(efx, &reg, FR_AB_XX_CORE_STAT);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG,
(xgxs_loopback || xaui_loopback) ?
FFE_AB_XX_FORCE_SIG_ALL_LANES : 0);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback);
- efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback);
+ ef4_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
- efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback);
- efx_writeo(efx, &reg, FR_AB_XX_SD_CTL);
+ ef4_reado(efx, &reg, FR_AB_XX_SD_CTL);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback);
+ ef4_writeo(efx, &reg, FR_AB_XX_SD_CTL);
}
/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
-static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
+static bool falcon_xmac_link_ok_retry(struct ef4_nic *efx, int tries)
{
bool mac_up = falcon_xmac_link_ok(efx);
if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS ||
- efx_phy_mode_disabled(efx->phy_mode))
+ ef4_phy_mode_disabled(efx->phy_mode))
/* XAUI link is expected to be down */
return mac_up;
@@ -1217,16 +1217,16 @@ static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
return mac_up;
}
-static bool falcon_xmac_check_fault(struct efx_nic *efx)
+static bool falcon_xmac_check_fault(struct ef4_nic *efx)
{
return !falcon_xmac_link_ok_retry(efx, 5);
}
-static int falcon_reconfigure_xmac(struct efx_nic *efx)
+static int falcon_reconfigure_xmac(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_farch_filter_sync_rx_mode(efx);
+ ef4_farch_filter_sync_rx_mode(efx);
falcon_reconfigure_xgxs_core(efx);
falcon_reconfigure_xmac_core(efx);
@@ -1239,7 +1239,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx)
return 0;
}
-static void falcon_poll_xmac(struct efx_nic *efx)
+static void falcon_poll_xmac(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
@@ -1258,32 +1258,32 @@ static void falcon_poll_xmac(struct efx_nic *efx)
**************************************************************************
*/
-static void falcon_push_multicast_hash(struct efx_nic *efx)
+static void falcon_push_multicast_hash(struct ef4_nic *efx)
{
- union efx_multicast_hash *mc_hash = &efx->multicast_hash;
+ union ef4_multicast_hash *mc_hash = &efx->multicast_hash;
WARN_ON(!mutex_is_locked(&efx->mac_lock));
- efx_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0);
- efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
+ ef4_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0);
+ ef4_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
}
-static void falcon_reset_macs(struct efx_nic *efx)
+static void falcon_reset_macs(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg, mac_ctrl;
+ ef4_oword_t reg, mac_ctrl;
int count;
- if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
+ if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0) {
/* It's not safe to use GLB_CTL_REG to reset the
* macs, so instead use the internal MAC resets
*/
- EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
- efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
+ ef4_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
for (count = 0; count < 10000; count++) {
- efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
- if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
+ ef4_reado(efx, &reg, FR_AB_XM_GLB_CFG);
+ if (EF4_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
0)
return;
udelay(10);
@@ -1296,22 +1296,22 @@ static void falcon_reset_macs(struct efx_nic *efx)
/* Mac stats will fail whist the TX fifo is draining */
WARN_ON(nic_data->stats_disable_count == 0);
- efx_reado(efx, &mac_ctrl, FR_AB_MAC_CTRL);
- EFX_SET_OWORD_FIELD(mac_ctrl, FRF_BB_TXFIFO_DRAIN_EN, 1);
- efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
+ ef4_reado(efx, &mac_ctrl, FR_AB_MAC_CTRL);
+ EF4_SET_OWORD_FIELD(mac_ctrl, FRF_BB_TXFIFO_DRAIN_EN, 1);
+ ef4_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
- efx_reado(efx, &reg, FR_AB_GLB_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGRX, 1);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_EM, 1);
- efx_writeo(efx, &reg, FR_AB_GLB_CTL);
+ ef4_reado(efx, &reg, FR_AB_GLB_CTL);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_RST_XGRX, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_AB_RST_EM, 1);
+ ef4_writeo(efx, &reg, FR_AB_GLB_CTL);
count = 0;
while (1) {
- efx_reado(efx, &reg, FR_AB_GLB_CTL);
- if (!EFX_OWORD_FIELD(reg, FRF_AB_RST_XGTX) &&
- !EFX_OWORD_FIELD(reg, FRF_AB_RST_XGRX) &&
- !EFX_OWORD_FIELD(reg, FRF_AB_RST_EM)) {
+ ef4_reado(efx, &reg, FR_AB_GLB_CTL);
+ if (!EF4_OWORD_FIELD(reg, FRF_AB_RST_XGTX) &&
+ !EF4_OWORD_FIELD(reg, FRF_AB_RST_XGRX) &&
+ !EF4_OWORD_FIELD(reg, FRF_AB_RST_EM)) {
netif_dbg(efx, hw, efx->net_dev,
"Completed MAC reset after %d loops\n",
count);
@@ -1327,47 +1327,47 @@ static void falcon_reset_macs(struct efx_nic *efx)
/* Ensure the correct MAC is selected before statistics
* are re-enabled by the caller */
- efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
+ ef4_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
falcon_setup_xaui(efx);
}
-static void falcon_drain_tx_fifo(struct efx_nic *efx)
+static void falcon_drain_tx_fifo(struct ef4_nic *efx)
{
- efx_oword_t reg;
+ ef4_oword_t reg;
- if ((efx_nic_rev(efx) < EFX_REV_FALCON_B0) ||
+ if ((ef4_nic_rev(efx) < EF4_REV_FALCON_B0) ||
(efx->loopback_mode != LOOPBACK_NONE))
return;
- efx_reado(efx, &reg, FR_AB_MAC_CTRL);
+ ef4_reado(efx, &reg, FR_AB_MAC_CTRL);
/* There is no point in draining more than once */
- if (EFX_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN))
+ if (EF4_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN))
return;
falcon_reset_macs(efx);
}
-static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
+static void falcon_deconfigure_mac_wrapper(struct ef4_nic *efx)
{
- efx_oword_t reg;
+ ef4_oword_t reg;
- if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
+ if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0)
return;
/* Isolate the MAC -> RX */
- efx_reado(efx, &reg, FR_AZ_RX_CFG);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0);
- efx_writeo(efx, &reg, FR_AZ_RX_CFG);
+ ef4_reado(efx, &reg, FR_AZ_RX_CFG);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0);
+ ef4_writeo(efx, &reg, FR_AZ_RX_CFG);
/* Isolate TX -> MAC */
falcon_drain_tx_fifo(efx);
}
-static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
+static void falcon_reconfigure_mac_wrapper(struct ef4_nic *efx)
{
- struct efx_link_state *link_state = &efx->link_state;
- efx_oword_t reg;
+ struct ef4_link_state *link_state = &efx->link_state;
+ ef4_oword_t reg;
int link_speed, isolate;
isolate = !!ACCESS_ONCE(efx->reset_pending);
@@ -1383,7 +1383,7 @@ static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
* as advertised. Disable to ensure packets are not
* indefinitely held and TX queue can be flushed at any point
* while the link is down. */
- EFX_POPULATE_OWORD_5(reg,
+ EF4_POPULATE_OWORD_5(reg,
FRF_AB_MAC_XOFF_VAL, 0xffff /* max pause time */,
FRF_AB_MAC_BCAD_ACPT, 1,
FRF_AB_MAC_UC_PROM, !efx->unicast_filter,
@@ -1391,30 +1391,30 @@ static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
FRF_AB_MAC_SPEED, link_speed);
/* On B0, MAC backpressure can be disabled and packets get
* discarded. */
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ EF4_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
!link_state->up || isolate);
}
- efx_writeo(efx, &reg, FR_AB_MAC_CTRL);
+ ef4_writeo(efx, &reg, FR_AB_MAC_CTRL);
/* Restore the multicast hash registers. */
falcon_push_multicast_hash(efx);
- efx_reado(efx, &reg, FR_AZ_RX_CFG);
+ ef4_reado(efx, &reg, FR_AZ_RX_CFG);
/* Enable XOFF signal from RX FIFO (we enabled it during NIC
* initialisation but it may read back as 0) */
- EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
/* Unisolate the MAC -> RX */
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate);
- efx_writeo(efx, &reg, FR_AZ_RX_CFG);
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0)
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate);
+ ef4_writeo(efx, &reg, FR_AZ_RX_CFG);
}
-static void falcon_stats_request(struct efx_nic *efx)
+static void falcon_stats_request(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg;
+ ef4_oword_t reg;
WARN_ON(nic_data->stats_pending);
WARN_ON(nic_data->stats_disable_count);
@@ -1424,16 +1424,16 @@ static void falcon_stats_request(struct efx_nic *efx)
wmb(); /* ensure done flag is clear */
/* Initiate DMA transfer of stats */
- EFX_POPULATE_OWORD_2(reg,
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_MAC_STAT_DMA_CMD, 1,
FRF_AB_MAC_STAT_DMA_ADR,
efx->stats_buffer.dma_addr);
- efx_writeo(efx, &reg, FR_AB_MAC_STAT_DMA);
+ ef4_writeo(efx, &reg, FR_AB_MAC_STAT_DMA);
mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2));
}
-static void falcon_stats_complete(struct efx_nic *efx)
+static void falcon_stats_complete(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
@@ -1443,7 +1443,7 @@ static void falcon_stats_complete(struct efx_nic *efx)
nic_data->stats_pending = false;
if (FALCON_XMAC_STATS_DMA_FLAG(efx)) {
rmb(); /* read the done flag before the stats */
- efx_nic_update_stats(falcon_stat_desc, FALCON_STAT_COUNT,
+ ef4_nic_update_stats(falcon_stat_desc, FALCON_STAT_COUNT,
falcon_stat_mask, nic_data->stats,
efx->stats_buffer.addr, true);
} else {
@@ -1454,7 +1454,7 @@ static void falcon_stats_complete(struct efx_nic *efx)
static void falcon_stats_timer_func(unsigned long context)
{
- struct efx_nic *efx = (struct efx_nic *)context;
+ struct ef4_nic *efx = (struct ef4_nic *)context;
struct falcon_nic_data *nic_data = efx->nic_data;
spin_lock(&efx->stats_lock);
@@ -1466,9 +1466,9 @@ static void falcon_stats_timer_func(unsigned long context)
spin_unlock(&efx->stats_lock);
}
-static bool falcon_loopback_link_poll(struct efx_nic *efx)
+static bool falcon_loopback_link_poll(struct ef4_nic *efx)
{
- struct efx_link_state old_state = efx->link_state;
+ struct ef4_link_state old_state = efx->link_state;
WARN_ON(!mutex_is_locked(&efx->mac_lock));
WARN_ON(!LOOPBACK_INTERNAL(efx));
@@ -1478,14 +1478,14 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx)
efx->link_state.up = true;
efx->link_state.speed = 10000;
- return !efx_link_state_equal(&efx->link_state, &old_state);
+ return !ef4_link_state_equal(&efx->link_state, &old_state);
}
-static int falcon_reconfigure_port(struct efx_nic *efx)
+static int falcon_reconfigure_port(struct ef4_nic *efx)
{
int rc;
- WARN_ON(efx_nic_rev(efx) > EFX_REV_FALCON_B0);
+ WARN_ON(ef4_nic_rev(efx) > EF4_REV_FALCON_B0);
/* Poll the PHY link state *before* reconfiguring it. This means we
* will pick up the correct speed (in loopback) to select the correct
@@ -1508,7 +1508,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx)
falcon_start_nic_stats(efx);
/* Synchronise efx->link_state with the kernel */
- efx_link_status_changed(efx);
+ ef4_link_status_changed(efx);
return 0;
}
@@ -1520,13 +1520,13 @@ static int falcon_reconfigure_port(struct efx_nic *efx)
* flow control on this end.
*/
-static void falcon_a1_prepare_enable_fc_tx(struct efx_nic *efx)
+static void falcon_a1_prepare_enable_fc_tx(struct ef4_nic *efx)
{
/* Schedule a reset to recover */
- efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
+ ef4_schedule_reset(efx, RESET_TYPE_INVISIBLE);
}
-static void falcon_b0_prepare_enable_fc_tx(struct efx_nic *efx)
+static void falcon_b0_prepare_enable_fc_tx(struct ef4_nic *efx)
{
/* Recover by resetting the EM block */
falcon_stop_nic_stats(efx);
@@ -1543,21 +1543,21 @@ static void falcon_b0_prepare_enable_fc_tx(struct efx_nic *efx)
*/
/* Wait for GMII access to complete */
-static int falcon_gmii_wait(struct efx_nic *efx)
+static int falcon_gmii_wait(struct ef4_nic *efx)
{
- efx_oword_t md_stat;
+ ef4_oword_t md_stat;
int count;
/* wait up to 50ms - taken max from datasheet */
for (count = 0; count < 5000; count++) {
- efx_reado(efx, &md_stat, FR_AB_MD_STAT);
- if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
- if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
- EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
+ ef4_reado(efx, &md_stat, FR_AB_MD_STAT);
+ if (EF4_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
+ if (EF4_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
+ EF4_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
netif_err(efx, hw, efx->net_dev,
"error from GMII access "
- EFX_OWORD_FMT"\n",
- EFX_OWORD_VAL(md_stat));
+ EF4_OWORD_FMT"\n",
+ EF4_OWORD_VAL(md_stat));
return -EIO;
}
return 0;
@@ -1572,9 +1572,9 @@ static int falcon_gmii_wait(struct efx_nic *efx)
static int falcon_mdio_write(struct net_device *net_dev,
int prtad, int devad, u16 addr, u16 value)
{
- struct efx_nic *efx = netdev_priv(net_dev);
+ struct ef4_nic *efx = netdev_priv(net_dev);
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg;
+ ef4_oword_t reg;
int rc;
netif_vdbg(efx, hw, efx->net_dev,
@@ -1589,30 +1589,30 @@ static int falcon_mdio_write(struct net_device *net_dev,
goto out;
/* Write the address/ID register */
- EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
- efx_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
+ ef4_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
- EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
+ EF4_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
FRF_AB_MD_DEV_ADR, devad);
- efx_writeo(efx, &reg, FR_AB_MD_ID);
+ ef4_writeo(efx, &reg, FR_AB_MD_ID);
/* Write data */
- EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_TXD, value);
- efx_writeo(efx, &reg, FR_AB_MD_TXD);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_MD_TXD, value);
+ ef4_writeo(efx, &reg, FR_AB_MD_TXD);
- EFX_POPULATE_OWORD_2(reg,
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_MD_WRC, 1,
FRF_AB_MD_GC, 0);
- efx_writeo(efx, &reg, FR_AB_MD_CS);
+ ef4_writeo(efx, &reg, FR_AB_MD_CS);
/* Wait for data to be written */
rc = falcon_gmii_wait(efx);
if (rc) {
/* Abort the write operation */
- EFX_POPULATE_OWORD_2(reg,
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_MD_WRC, 0,
FRF_AB_MD_GC, 1);
- efx_writeo(efx, &reg, FR_AB_MD_CS);
+ ef4_writeo(efx, &reg, FR_AB_MD_CS);
udelay(10);
}
@@ -1625,9 +1625,9 @@ out:
static int falcon_mdio_read(struct net_device *net_dev,
int prtad, int devad, u16 addr)
{
- struct efx_nic *efx = netdev_priv(net_dev);
+ struct ef4_nic *efx = netdev_priv(net_dev);
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t reg;
+ ef4_oword_t reg;
int rc;
mutex_lock(&nic_data->mdio_lock);
@@ -1637,31 +1637,31 @@ static int falcon_mdio_read(struct net_device *net_dev,
if (rc)
goto out;
- EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
- efx_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
+ EF4_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
+ ef4_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
- EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
+ EF4_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
FRF_AB_MD_DEV_ADR, devad);
- efx_writeo(efx, &reg, FR_AB_MD_ID);
+ ef4_writeo(efx, &reg, FR_AB_MD_ID);
/* Request data to be read */
- EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0);
- efx_writeo(efx, &reg, FR_AB_MD_CS);
+ EF4_POPULATE_OWORD_2(reg, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0);
+ ef4_writeo(efx, &reg, FR_AB_MD_CS);
/* Wait for data to become available */
rc = falcon_gmii_wait(efx);
if (rc == 0) {
- efx_reado(efx, &reg, FR_AB_MD_RXD);
- rc = EFX_OWORD_FIELD(reg, FRF_AB_MD_RXD);
+ ef4_reado(efx, &reg, FR_AB_MD_RXD);
+ rc = EF4_OWORD_FIELD(reg, FRF_AB_MD_RXD);
netif_vdbg(efx, hw, efx->net_dev,
"read from MDIO %d register %d.%d, got %04x\n",
prtad, devad, addr, rc);
} else {
/* Abort the read operation */
- EFX_POPULATE_OWORD_2(reg,
+ EF4_POPULATE_OWORD_2(reg,
FRF_AB_MD_RIC, 0,
FRF_AB_MD_GC, 1);
- efx_writeo(efx, &reg, FR_AB_MD_CS);
+ ef4_writeo(efx, &reg, FR_AB_MD_CS);
netif_dbg(efx, hw, efx->net_dev,
"read from MDIO %d register %d.%d, got error %d\n",
@@ -1674,7 +1674,7 @@ out:
}
/* This call is responsible for hooking in the MAC and PHY operations */
-static int falcon_probe_port(struct efx_nic *efx)
+static int falcon_probe_port(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -1709,15 +1709,15 @@ static int falcon_probe_port(struct efx_nic *efx)
efx->link_state.fd = true;
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
- efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0)
+ efx->wanted_fc = EF4_FC_RX | EF4_FC_TX;
else
- efx->wanted_fc = EFX_FC_RX;
+ efx->wanted_fc = EF4_FC_RX;
if (efx->mdio.mmds & MDIO_DEVS_AN)
- efx->wanted_fc |= EFX_FC_AUTO;
+ efx->wanted_fc |= EF4_FC_AUTO;
/* Allocate buffer for stats */
- rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
+ rc = ef4_nic_alloc_buffer(efx, &efx->stats_buffer,
FALCON_MAC_STATS_SIZE, GFP_KERNEL);
if (rc)
return rc;
@@ -1730,40 +1730,40 @@ static int falcon_probe_port(struct efx_nic *efx)
return 0;
}
-static void falcon_remove_port(struct efx_nic *efx)
+static void falcon_remove_port(struct ef4_nic *efx)
{
efx->phy_op->remove(efx);
- efx_nic_free_buffer(efx, &efx->stats_buffer);
+ ef4_nic_free_buffer(efx, &efx->stats_buffer);
}
/* Global events are basically PHY events */
static bool
-falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
+falcon_handle_global_event(struct ef4_channel *channel, ef4_qword_t *event)
{
- struct efx_nic *efx = channel->efx;
+ struct ef4_nic *efx = channel->efx;
struct falcon_nic_data *nic_data = efx->nic_data;
- if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
- EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
- EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR))
+ if (EF4_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
+ EF4_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
+ EF4_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR))
/* Ignored */
return true;
- if ((efx_nic_rev(efx) == EFX_REV_FALCON_B0) &&
- EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
+ if ((ef4_nic_rev(efx) == EF4_REV_FALCON_B0) &&
+ EF4_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
nic_data->xmac_poll_required = true;
return true;
}
- if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
- EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
- EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
+ if (ef4_nic_rev(efx) <= EF4_REV_FALCON_A1 ?
+ EF4_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
+ EF4_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
netif_err(efx, rx_err, efx->net_dev,
"channel %d seen global RX_RESET event. Resetting.\n",
channel->channel);
atomic_inc(&efx->rx_reset);
- efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
+ ef4_schedule_reset(efx, EF4_WORKAROUND_6555(efx) ?
RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
return true;
}
@@ -1778,7 +1778,7 @@ falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
**************************************************************************/
static int
-falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
+falcon_read_nvram(struct ef4_nic *efx, struct falcon_nvconfig *nvconfig_out)
{
struct falcon_nic_data *nic_data = efx->nic_data;
struct falcon_nvconfig *nvconfig;
@@ -1849,52 +1849,52 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
return rc;
}
-static int falcon_test_nvram(struct efx_nic *efx)
+static int falcon_test_nvram(struct ef4_nic *efx)
{
return falcon_read_nvram(efx, NULL);
}
-static const struct efx_farch_register_test falcon_b0_register_tests[] = {
+static const struct ef4_farch_register_test falcon_b0_register_tests[] = {
{ FR_AZ_ADR_REGION,
- EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
+ EF4_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
{ FR_AZ_RX_CFG,
- EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) },
{ FR_AZ_TX_CFG,
- EFX_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AZ_TX_RESERVED,
- EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
+ EF4_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
{ FR_AB_MAC_CTRL,
- EFX_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AZ_SRM_TX_DC_CFG,
- EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AZ_RX_DC_CFG,
- EFX_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AZ_RX_DC_PF_WM,
- EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
{ FR_BZ_DP_CTRL,
- EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_GM_CFG2,
- EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_GMF_CFG0,
- EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_GLB_CFG,
- EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_TX_CFG,
- EFX_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_RX_CFG,
- EFX_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_RX_PARAM,
- EFX_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_FC,
- EFX_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XM_ADR_LO,
- EFX_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) },
{ FR_AB_XX_SD_CTL,
- EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
+ EF4_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
};
static int
-falcon_b0_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
+falcon_b0_test_chip(struct ef4_nic *efx, struct ef4_self_tests *tests)
{
enum reset_type reset_method = RESET_TYPE_INVISIBLE;
int rc, rc2;
@@ -1908,18 +1908,18 @@ falcon_b0_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
else
efx->loopback_mode = __ffs(efx->loopback_modes);
}
- __efx_reconfigure_port(efx);
+ __ef4_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);
- efx_reset_down(efx, reset_method);
+ ef4_reset_down(efx, reset_method);
tests->registers =
- efx_farch_test_registers(efx, falcon_b0_register_tests,
+ ef4_farch_test_registers(efx, falcon_b0_register_tests,
ARRAY_SIZE(falcon_b0_register_tests))
? -1 : 1;
rc = falcon_reset_hw(efx, reset_method);
- rc2 = efx_reset_up(efx, reset_method, rc == 0);
+ rc2 = ef4_reset_up(efx, reset_method, rc == 0);
return rc ? rc : rc2;
}
@@ -1974,10 +1974,10 @@ static int falcon_map_reset_flags(u32 *flags)
/* Resets NIC to known state. This routine must be called in process
* context and is allowed to sleep. */
-static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+static int __falcon_reset_hw(struct ef4_nic *efx, enum reset_type method)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t glb_ctl_reg_ker;
+ ef4_oword_t glb_ctl_reg_ker;
int rc;
netif_dbg(efx, hw, efx->net_dev, "performing %s hardware reset\n",
@@ -1992,7 +1992,7 @@ static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
"function prior to hardware reset\n");
goto fail1;
}
- if (efx_nic_is_dual_func(efx)) {
+ if (ef4_nic_is_dual_func(efx)) {
rc = pci_save_state(nic_data->pci_dev2);
if (rc) {
netif_err(efx, drv, efx->net_dev,
@@ -2003,12 +2003,12 @@ static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
}
}
- EFX_POPULATE_OWORD_2(glb_ctl_reg_ker,
+ EF4_POPULATE_OWORD_2(glb_ctl_reg_ker,
FRF_AB_EXT_PHY_RST_DUR,
FFE_AB_EXT_PHY_RST_DUR_10240US,
FRF_AB_SWRST, 1);
} else {
- EFX_POPULATE_OWORD_7(glb_ctl_reg_ker,
+ EF4_POPULATE_OWORD_7(glb_ctl_reg_ker,
/* exclude PHY from "invisible" reset */
FRF_AB_EXT_PHY_RST_CTL,
method == RESET_TYPE_INVISIBLE,
@@ -2021,14 +2021,14 @@ static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
FFE_AB_EXT_PHY_RST_DUR_10240US,
FRF_AB_SWRST, 1);
}
- efx_writeo(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
+ ef4_writeo(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
netif_dbg(efx, hw, efx->net_dev, "waiting for hardware reset\n");
schedule_timeout_uninterruptible(HZ / 20);
/* Restore PCI configuration if needed */
if (method == RESET_TYPE_WORLD) {
- if (efx_nic_is_dual_func(efx))
+ if (ef4_nic_is_dual_func(efx))
pci_restore_state(nic_data->pci_dev2);
pci_restore_state(efx->pci_dev);
netif_dbg(efx, drv, efx->net_dev,
@@ -2036,8 +2036,8 @@ static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
}
/* Assert that reset complete */
- efx_reado(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
- if (EFX_OWORD_FIELD(glb_ctl_reg_ker, FRF_AB_SWRST) != 0) {
+ ef4_reado(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
+ if (EF4_OWORD_FIELD(glb_ctl_reg_ker, FRF_AB_SWRST) != 0) {
rc = -ETIMEDOUT;
netif_err(efx, hw, efx->net_dev,
"timed out waiting for hardware reset\n");
@@ -2055,7 +2055,7 @@ fail3:
return rc;
}
-static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+static int falcon_reset_hw(struct ef4_nic *efx, enum reset_type method)
{
struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
@@ -2067,7 +2067,7 @@ static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
return rc;
}
-static void falcon_monitor(struct efx_nic *efx)
+static void falcon_monitor(struct ef4_nic *efx)
{
bool link_changed;
int rc;
@@ -2080,7 +2080,7 @@ static void falcon_monitor(struct efx_nic *efx)
"Board sensor %s; shutting down PHY\n",
(rc == -ERANGE) ? "reported fault" : "failed");
efx->phy_mode |= PHY_MODE_LOW_POWER;
- rc = __efx_reconfigure_port(efx);
+ rc = __ef4_reconfigure_port(efx);
WARN_ON(rc);
}
@@ -2099,7 +2099,7 @@ static void falcon_monitor(struct efx_nic *efx)
falcon_start_nic_stats(efx);
- efx_link_status_changed(efx);
+ ef4_link_status_changed(efx);
}
falcon_poll_xmac(efx);
@@ -2108,22 +2108,22 @@ static void falcon_monitor(struct efx_nic *efx)
/* Zeroes out the SRAM contents. This routine must be called in
* process context and is allowed to sleep.
*/
-static int falcon_reset_sram(struct efx_nic *efx)
+static int falcon_reset_sram(struct ef4_nic *efx)
{
- efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker;
+ ef4_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker;
int count;
/* Set the SRAM wake/sleep GPIO appropriately. */
- efx_reado(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OEN, 1);
- EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OUT, 1);
- efx_writeo(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
+ ef4_reado(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
+ EF4_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OEN, 1);
+ EF4_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OUT, 1);
+ ef4_writeo(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
/* Initiate SRAM reset */
- EFX_POPULATE_OWORD_2(srm_cfg_reg_ker,
+ EF4_POPULATE_OWORD_2(srm_cfg_reg_ker,
FRF_AZ_SRM_INIT_EN, 1,
FRF_AZ_SRM_NB_SZ, 0);
- efx_writeo(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
+ ef4_writeo(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
/* Wait for SRAM reset to complete */
count = 0;
@@ -2135,8 +2135,8 @@ static int falcon_reset_sram(struct efx_nic *efx)
schedule_timeout_uninterruptible(HZ / 50);
/* Check for reset complete */
- efx_reado(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
- if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, FRF_AZ_SRM_INIT_EN)) {
+ ef4_reado(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
+ if (!EF4_OWORD_FIELD(srm_cfg_reg_ker, FRF_AZ_SRM_INIT_EN)) {
netif_dbg(efx, hw, efx->net_dev,
"SRAM reset complete\n");
@@ -2148,7 +2148,7 @@ static int falcon_reset_sram(struct efx_nic *efx)
return -ETIMEDOUT;
}
-static void falcon_spi_device_init(struct efx_nic *efx,
+static void falcon_spi_device_init(struct ef4_nic *efx,
struct falcon_spi_device *spi_device,
unsigned int device_id, u32 device_type)
{
@@ -2174,7 +2174,7 @@ static void falcon_spi_device_init(struct efx_nic *efx,
}
/* Extract non-volatile configuration */
-static int falcon_probe_nvconfig(struct efx_nic *efx)
+static int falcon_probe_nvconfig(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
struct falcon_nvconfig *nvconfig;
@@ -2215,7 +2215,7 @@ out:
return rc;
}
-static int falcon_dimension_resources(struct efx_nic *efx)
+static int falcon_dimension_resources(struct ef4_nic *efx)
{
efx->rx_dc_base = 0x20000;
efx->tx_dc_base = 0x26000;
@@ -2223,18 +2223,18 @@ static int falcon_dimension_resources(struct efx_nic *efx)
}
/* Probe all SPI devices on the NIC */
-static void falcon_probe_spi_devices(struct efx_nic *efx)
+static void falcon_probe_spi_devices(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
- efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
+ ef4_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
int boot_dev;
- efx_reado(efx, &gpio_ctl, FR_AB_GPIO_CTL);
- efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
- efx_reado(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
+ ef4_reado(efx, &gpio_ctl, FR_AB_GPIO_CTL);
+ ef4_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+ ef4_reado(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
- if (EFX_OWORD_FIELD(gpio_ctl, FRF_AB_GPIO3_PWRUP_VALUE)) {
- boot_dev = (EFX_OWORD_FIELD(nic_stat, FRF_AB_SF_PRST) ?
+ if (EF4_OWORD_FIELD(gpio_ctl, FRF_AB_GPIO3_PWRUP_VALUE)) {
+ boot_dev = (EF4_OWORD_FIELD(nic_stat, FRF_AB_SF_PRST) ?
FFE_AB_SPI_DEVICE_FLASH : FFE_AB_SPI_DEVICE_EEPROM);
netif_dbg(efx, probe, efx->net_dev, "Booted from %s\n",
boot_dev == FFE_AB_SPI_DEVICE_FLASH ?
@@ -2246,12 +2246,12 @@ static void falcon_probe_spi_devices(struct efx_nic *efx)
netif_dbg(efx, probe, efx->net_dev,
"Booted from internal ASIC settings;"
" setting SPI config\n");
- EFX_POPULATE_OWORD_3(ee_vpd_cfg, FRF_AB_EE_VPD_EN, 0,
+ EF4_POPULATE_OWORD_3(ee_vpd_cfg, FRF_AB_EE_VPD_EN, 0,
/* 125 MHz / 7 ~= 20 MHz */
FRF_AB_EE_SF_CLOCK_DIV, 7,
/* 125 MHz / 63 ~= 2 MHz */
FRF_AB_EE_EE_CLOCK_DIV, 63);
- efx_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
+ ef4_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
}
mutex_init(&nic_data->spi_lock);
@@ -2266,12 +2266,12 @@ static void falcon_probe_spi_devices(struct efx_nic *efx)
large_eeprom_type);
}
-static unsigned int falcon_a1_mem_map_size(struct efx_nic *efx)
+static unsigned int falcon_a1_mem_map_size(struct ef4_nic *efx)
{
return 0x20000;
}
-static unsigned int falcon_b0_mem_map_size(struct efx_nic *efx)
+static unsigned int falcon_b0_mem_map_size(struct ef4_nic *efx)
{
/* Map everything up to and including the RSS indirection table.
* The PCI core takes care of mapping the MSI-X tables.
@@ -2280,7 +2280,7 @@ static unsigned int falcon_b0_mem_map_size(struct efx_nic *efx)
FR_BZ_RX_INDIRECTION_TBL_STEP * FR_BZ_RX_INDIRECTION_TBL_ROWS;
}
-static int falcon_probe_nic(struct efx_nic *efx)
+static int falcon_probe_nic(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data;
struct falcon_board *board;
@@ -2296,14 +2296,14 @@ static int falcon_probe_nic(struct efx_nic *efx)
rc = -ENODEV;
- if (efx_farch_fpga_ver(efx) != 0) {
+ if (ef4_farch_fpga_ver(efx) != 0) {
netif_err(efx, probe, efx->net_dev,
"Falcon FPGA not supported\n");
goto fail1;
}
- if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
- efx_oword_t nic_stat;
+ if (ef4_nic_rev(efx) <= EF4_REV_FALCON_A1) {
+ ef4_oword_t nic_stat;
struct pci_dev *dev;
u8 pci_rev = efx->pci_dev->revision;
@@ -2312,13 +2312,13 @@ static int falcon_probe_nic(struct efx_nic *efx)
"Falcon rev A0 not supported\n");
goto fail1;
}
- efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
- if (EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_10G) == 0) {
+ ef4_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+ if (EF4_OWORD_FIELD(nic_stat, FRF_AB_STRAP_10G) == 0) {
netif_err(efx, probe, efx->net_dev,
"Falcon rev A1 1G not supported\n");
goto fail1;
}
- if (EFX_OWORD_FIELD(nic_stat, FRF_AA_STRAP_PCIE) == 0) {
+ if (EF4_OWORD_FIELD(nic_stat, FRF_AA_STRAP_PCIE) == 0) {
netif_err(efx, probe, efx->net_dev,
"Falcon rev A1 PCI-X not supported\n");
goto fail1;
@@ -2350,7 +2350,7 @@ static int falcon_probe_nic(struct efx_nic *efx)
}
/* Allocate memory for INT_KER */
- rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t),
+ rc = ef4_nic_alloc_buffer(efx, &efx->irq_status, sizeof(ef4_oword_t),
GFP_KERNEL);
if (rc)
goto fail4;
@@ -2372,8 +2372,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
goto fail5;
}
- efx->max_channels = (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ? 4 :
- EFX_MAX_CHANNELS);
+ efx->max_channels = (ef4_nic_rev(efx) <= EF4_REV_FALCON_A1 ? 4 :
+ EF4_MAX_CHANNELS);
efx->max_tx_channels = efx->max_channels;
efx->timer_quantum_ns = 4968; /* 621 cycles */
efx->timer_max_ns = efx->type->timer_period_max *
@@ -2409,7 +2409,7 @@ static int falcon_probe_nic(struct efx_nic *efx)
i2c_del_adapter(&board->i2c_adap);
memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
fail5:
- efx_nic_free_buffer(efx, &efx->irq_status);
+ ef4_nic_free_buffer(efx, &efx->irq_status);
fail4:
fail3:
if (nic_data->pci_dev2) {
@@ -2422,66 +2422,66 @@ static int falcon_probe_nic(struct efx_nic *efx)
return rc;
}
-static void falcon_init_rx_cfg(struct efx_nic *efx)
+static void falcon_init_rx_cfg(struct ef4_nic *efx)
{
/* RX control FIFO thresholds (32 entries) */
const unsigned ctrl_xon_thr = 20;
const unsigned ctrl_xoff_thr = 25;
- efx_oword_t reg;
+ ef4_oword_t reg;
- efx_reado(efx, &reg, FR_AZ_RX_CFG);
- if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
+ ef4_reado(efx, &reg, FR_AZ_RX_CFG);
+ if (ef4_nic_rev(efx) <= EF4_REV_FALCON_A1) {
/* Data FIFO size is 5.5K. The RX DMA engine only
* supports scattering for user-mode queues, but will
* split DMA writes at intervals of RX_USR_BUF_SIZE
* (32-byte units) even for kernel-mode queues. We
* set it to be so large that that never happens.
*/
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_DESC_PUSH_EN, 0);
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_USR_BUF_SIZE,
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_DESC_PUSH_EN, 0);
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_USR_BUF_SIZE,
(3 * 4096) >> 5);
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, 512 >> 8);
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, 2048 >> 8);
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_TX_TH, ctrl_xon_thr);
- EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_TX_TH, ctrl_xoff_thr);
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, 512 >> 8);
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, 2048 >> 8);
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_TX_TH, ctrl_xon_thr);
+ EF4_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_TX_TH, ctrl_xoff_thr);
} else {
/* Data FIFO size is 80K; register fields moved */
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_DESC_PUSH_EN, 0);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_USR_BUF_SIZE,
- EFX_RX_USR_BUF_SIZE >> 5);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_DESC_PUSH_EN, 0);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_USR_BUF_SIZE,
+ EF4_RX_USR_BUF_SIZE >> 5);
/* Send XON and XOFF at ~3 * max MTU away from empty/full */
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, 27648 >> 8);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, 54272 >> 8);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, 27648 >> 8);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, 54272 >> 8);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
/* Enable hash insertion. This is broken for the
* 'Falcon' hash so also select Toeplitz TCP/IPv4 and
* IPv4 hashes. */
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_INSRT_HDR, 1);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_ALG, 1);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_IP_HASH, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_INSRT_HDR, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_ALG, 1);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_RX_IP_HASH, 1);
}
/* Always enable XOFF signal from RX FIFO. We enable
* or disable transmission of pause frames at the MAC. */
- EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
- efx_writeo(efx, &reg, FR_AZ_RX_CFG);
+ EF4_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
+ ef4_writeo(efx, &reg, FR_AZ_RX_CFG);
}
/* This call performs hardware-specific global initialisation, such as
* defining the descriptor cache sizes and number of RSS channels.
* It does not set up any buffers, descriptor rings or event queues.
*/
-static int falcon_init_nic(struct efx_nic *efx)
+static int falcon_init_nic(struct ef4_nic *efx)
{
- efx_oword_t temp;
+ ef4_oword_t temp;
int rc;
/* Use on-chip SRAM */
- efx_reado(efx, &temp, FR_AB_NIC_STAT);
- EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
- efx_writeo(efx, &temp, FR_AB_NIC_STAT);
+ ef4_reado(efx, &temp, FR_AB_NIC_STAT);
+ EF4_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
+ ef4_writeo(efx, &temp, FR_AB_NIC_STAT);
rc = falcon_reset_sram(efx);
if (rc)
@@ -2490,55 +2490,55 @@ static int falcon_init_nic(struct efx_nic *efx)
/* Clear the parity enables on the TX data fifos as
* they produce false parity errors because of timing issues
*/
- if (EFX_WORKAROUND_5129(efx)) {
- efx_reado(efx, &temp, FR_AZ_CSR_SPARE);
- EFX_SET_OWORD_FIELD(temp, FRF_AB_MEM_PERR_EN_TX_DATA, 0);
- efx_writeo(efx, &temp, FR_AZ_CSR_SPARE);
+ if (EF4_WORKAROUND_5129(efx)) {
+ ef4_reado(efx, &temp, FR_AZ_CSR_SPARE);
+ EF4_SET_OWORD_FIELD(temp, FRF_AB_MEM_PERR_EN_TX_DATA, 0);
+ ef4_writeo(efx, &temp, FR_AZ_CSR_SPARE);
}
- if (EFX_WORKAROUND_7244(efx)) {
- efx_reado(efx, &temp, FR_BZ_RX_FILTER_CTL);
- EFX_SET_OWORD_FIELD(temp, FRF_BZ_UDP_FULL_SRCH_LIMIT, 8);
- EFX_SET_OWORD_FIELD(temp, FRF_BZ_UDP_WILD_SRCH_LIMIT, 8);
- EFX_SET_OWORD_FIELD(temp, FRF_BZ_TCP_FULL_SRCH_LIMIT, 8);
- EFX_SET_OWORD_FIELD(temp, FRF_BZ_TCP_WILD_SRCH_LIMIT, 8);
- efx_writeo(efx, &temp, FR_BZ_RX_FILTER_CTL);
+ if (EF4_WORKAROUND_7244(efx)) {
+ ef4_reado(efx, &temp, FR_BZ_RX_FILTER_CTL);
+ EF4_SET_OWORD_FIELD(temp, FRF_BZ_UDP_FULL_SRCH_LIMIT, 8);
+ EF4_SET_OWORD_FIELD(temp, FRF_BZ_UDP_WILD_SRCH_LIMIT, 8);
+ EF4_SET_OWORD_FIELD(temp, FRF_BZ_TCP_FULL_SRCH_LIMIT, 8);
+ EF4_SET_OWORD_FIELD(temp, FRF_BZ_TCP_WILD_SRCH_LIMIT, 8);
+ ef4_writeo(efx, &temp, FR_BZ_RX_FILTER_CTL);
}
/* XXX This is documented only for Falcon A0/A1 */
/* Setup RX. Wait for descriptor is broken and must
* be disabled. RXDP recovery shouldn't be needed, but is.
*/
- efx_reado(efx, &temp, FR_AA_RX_SELF_RST);
- EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_NODESC_WAIT_DIS, 1);
- EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_SELF_RST_EN, 1);
- if (EFX_WORKAROUND_5583(efx))
- EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_ISCSI_DIS, 1);
- efx_writeo(efx, &temp, FR_AA_RX_SELF_RST);
+ ef4_reado(efx, &temp, FR_AA_RX_SELF_RST);
+ EF4_SET_OWORD_FIELD(temp, FRF_AA_RX_NODESC_WAIT_DIS, 1);
+ EF4_SET_OWORD_FIELD(temp, FRF_AA_RX_SELF_RST_EN, 1);
+ if (EF4_WORKAROUND_5583(efx))
+ EF4_SET_OWORD_FIELD(temp, FRF_AA_RX_ISCSI_DIS, 1);
+ ef4_writeo(efx, &temp, FR_AA_RX_SELF_RST);
/* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16
* descriptors (which is bad).
*/
- efx_reado(efx, &temp, FR_AZ_TX_CFG);
- EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
- efx_writeo(efx, &temp, FR_AZ_TX_CFG);
+ ef4_reado(efx, &temp, FR_AZ_TX_CFG);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
+ ef4_writeo(efx, &temp, FR_AZ_TX_CFG);
falcon_init_rx_cfg(efx);
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
falcon_b0_rx_push_rss_config(efx, false, efx->rx_indir_table);
/* Set destination of both TX and RX Flush events */
- EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
- efx_writeo(efx, &temp, FR_BZ_DP_CTRL);
+ EF4_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
+ ef4_writeo(efx, &temp, FR_BZ_DP_CTRL);
}
- efx_farch_init_common(efx);
+ ef4_farch_init_common(efx);
return 0;
}
-static void falcon_remove_nic(struct efx_nic *efx)
+static void falcon_remove_nic(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
struct falcon_board *board = falcon_board(efx);
@@ -2549,7 +2549,7 @@ static void falcon_remove_nic(struct efx_nic *efx)
i2c_del_adapter(&board->i2c_adap);
memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
- efx_nic_free_buffer(efx, &efx->irq_status);
+ ef4_nic_free_buffer(efx, &efx->irq_status);
__falcon_reset_hw(efx, RESET_TYPE_ALL);
@@ -2564,40 +2564,40 @@ static void falcon_remove_nic(struct efx_nic *efx)
efx->nic_data = NULL;
}
-static size_t falcon_describe_nic_stats(struct efx_nic *efx, u8 *names)
+static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 *names)
{
- return efx_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT,
+ return ef4_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT,
falcon_stat_mask, names);
}
-static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
+static size_t falcon_update_nic_stats(struct ef4_nic *efx, u64 *full_stats,
struct rtnl_link_stats64 *core_stats)
{
struct falcon_nic_data *nic_data = efx->nic_data;
u64 *stats = nic_data->stats;
- efx_oword_t cnt;
+ ef4_oword_t cnt;
if (!nic_data->stats_disable_count) {
- efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
+ ef4_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
stats[FALCON_STAT_rx_nodesc_drop_cnt] +=
- EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);
+ EF4_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);
if (nic_data->stats_pending &&
FALCON_XMAC_STATS_DMA_FLAG(efx)) {
nic_data->stats_pending = false;
rmb(); /* read the done flag before the stats */
- efx_nic_update_stats(
+ ef4_nic_update_stats(
falcon_stat_desc, FALCON_STAT_COUNT,
falcon_stat_mask,
stats, efx->stats_buffer.addr, true);
}
/* Update derived statistic */
- efx_update_diff_stat(&stats[FALCON_STAT_rx_bad_bytes],
+ ef4_update_diff_stat(&stats[FALCON_STAT_rx_bad_bytes],
stats[FALCON_STAT_rx_bytes] -
stats[FALCON_STAT_rx_good_bytes] -
stats[FALCON_STAT_rx_control] * 64);
- efx_update_sw_stats(efx, stats);
+ ef4_update_sw_stats(efx, stats);
}
if (full_stats)
@@ -2628,7 +2628,7 @@ static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
return FALCON_STAT_COUNT;
}
-void falcon_start_nic_stats(struct efx_nic *efx)
+void falcon_start_nic_stats(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
@@ -2641,12 +2641,12 @@ void falcon_start_nic_stats(struct efx_nic *efx)
/* We don't acutally pull stats on falcon. Wait 10ms so that
* they arrive when we call this just after start_stats
*/
-static void falcon_pull_nic_stats(struct efx_nic *efx)
+static void falcon_pull_nic_stats(struct ef4_nic *efx)
{
msleep(10);
}
-void falcon_stop_nic_stats(struct efx_nic *efx)
+void falcon_stop_nic_stats(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
int i;
@@ -2672,7 +2672,7 @@ void falcon_stop_nic_stats(struct efx_nic *efx)
spin_unlock_bh(&efx->stats_lock);
}
-static void falcon_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+static void falcon_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{
falcon_board(efx)->type->set_id_led(efx, mode);
}
@@ -2684,14 +2684,14 @@ static void falcon_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
**************************************************************************
*/
-static void falcon_get_wol(struct efx_nic *efx, struct ethtool_wolinfo *wol)
+static void falcon_get_wol(struct ef4_nic *efx, struct ethtool_wolinfo *wol)
{
wol->supported = 0;
wol->wolopts = 0;
memset(&wol->sopass, 0, sizeof(wol->sopass));
}
-static int falcon_set_wol(struct efx_nic *efx, u32 type)
+static int falcon_set_wol(struct ef4_nic *efx, u32 type)
{
if (type != 0)
return -EINVAL;
@@ -2705,9 +2705,8 @@ static int falcon_set_wol(struct efx_nic *efx, u32 type)
**************************************************************************
*/
-const struct efx_nic_type falcon_a1_nic_type = {
- .is_vf = false,
- .mem_bar = EFX_MEM_BAR,
+const struct ef4_nic_type falcon_a1_nic_type = {
+ .mem_bar = EF4_MEM_BAR,
.mem_map_size = falcon_a1_mem_map_size,
.probe = falcon_probe_nic,
.remove = falcon_remove_nic,
@@ -2721,11 +2720,11 @@ const struct efx_nic_type falcon_a1_nic_type = {
.probe_port = falcon_probe_port,
.remove_port = falcon_remove_port,
.handle_global_event = falcon_handle_global_event,
- .fini_dmaq = efx_farch_fini_dmaq,
+ .fini_dmaq = ef4_farch_fini_dmaq,
.prepare_flush = falcon_prepare_flush,
- .finish_flush = efx_port_dummy_op_void,
- .prepare_flr = efx_port_dummy_op_void,
- .finish_flr = efx_farch_finish_flr,
+ .finish_flush = ef4_port_dummy_op_void,
+ .prepare_flr = ef4_port_dummy_op_void,
+ .finish_flr = ef4_farch_finish_flr,
.describe_stats = falcon_describe_nic_stats,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
@@ -2739,47 +2738,48 @@ const struct efx_nic_type falcon_a1_nic_type = {
.check_mac_fault = falcon_xmac_check_fault,
.get_wol = falcon_get_wol,
.set_wol = falcon_set_wol,
- .resume_wol = efx_port_dummy_op_void,
+ .resume_wol = ef4_port_dummy_op_void,
.test_nvram = falcon_test_nvram,
- .irq_enable_master = efx_farch_irq_enable_master,
- .irq_test_generate = efx_farch_irq_test_generate,
- .irq_disable_non_ev = efx_farch_irq_disable_master,
- .irq_handle_msi = efx_farch_msi_interrupt,
+ .irq_enable_master = ef4_farch_irq_enable_master,
+ .irq_test_generate = ef4_farch_irq_test_generate,
+ .irq_disable_non_ev = ef4_farch_irq_disable_master,
+ .irq_handle_msi = ef4_farch_msi_interrupt,
.irq_handle_legacy = falcon_legacy_interrupt_a1,
- .tx_probe = efx_farch_tx_probe,
- .tx_init = efx_farch_tx_init,
- .tx_remove = efx_farch_tx_remove,
- .tx_write = efx_farch_tx_write,
+ .tx_probe = ef4_farch_tx_probe,
+ .tx_init = ef4_farch_tx_init,
+ .tx_remove = ef4_farch_tx_remove,
+ .tx_write = ef4_farch_tx_write,
+ .tx_limit_len = ef4_farch_tx_limit_len,
.rx_push_rss_config = dummy_rx_push_rss_config,
- .rx_probe = efx_farch_rx_probe,
- .rx_init = efx_farch_rx_init,
- .rx_remove = efx_farch_rx_remove,
- .rx_write = efx_farch_rx_write,
- .rx_defer_refill = efx_farch_rx_defer_refill,
- .ev_probe = efx_farch_ev_probe,
- .ev_init = efx_farch_ev_init,
- .ev_fini = efx_farch_ev_fini,
- .ev_remove = efx_farch_ev_remove,
- .ev_process = efx_farch_ev_process,
- .ev_read_ack = efx_farch_ev_read_ack,
- .ev_test_generate = efx_farch_ev_test_generate,
+ .rx_probe = ef4_farch_rx_probe,
+ .rx_init = ef4_farch_rx_init,
+ .rx_remove = ef4_farch_rx_remove,
+ .rx_write = ef4_farch_rx_write,
+ .rx_defer_refill = ef4_farch_rx_defer_refill,
+ .ev_probe = ef4_farch_ev_probe,
+ .ev_init = ef4_farch_ev_init,
+ .ev_fini = ef4_farch_ev_fini,
+ .ev_remove = ef4_farch_ev_remove,
+ .ev_process = ef4_farch_ev_process,
+ .ev_read_ack = ef4_farch_ev_read_ack,
+ .ev_test_generate = ef4_farch_ev_test_generate,
/* We don't expose the filter table on Falcon A1 as it is not
* mapped into function 0, but these implementations still
* work with a degenerate case of all tables set to size 0.
*/
- .filter_table_probe = efx_farch_filter_table_probe,
- .filter_table_restore = efx_farch_filter_table_restore,
- .filter_table_remove = efx_farch_filter_table_remove,
- .filter_insert = efx_farch_filter_insert,
- .filter_remove_safe = efx_farch_filter_remove_safe,
- .filter_get_safe = efx_farch_filter_get_safe,
- .filter_clear_rx = efx_farch_filter_clear_rx,
- .filter_count_rx_used = efx_farch_filter_count_rx_used,
- .filter_get_rx_id_limit = efx_farch_filter_get_rx_id_limit,
- .filter_get_rx_ids = efx_farch_filter_get_rx_ids,
-
-#ifdef CONFIG_SFC_MTD
+ .filter_table_probe = ef4_farch_filter_table_probe,
+ .filter_table_restore = ef4_farch_filter_table_restore,
+ .filter_table_remove = ef4_farch_filter_table_remove,
+ .filter_insert = ef4_farch_filter_insert,
+ .filter_remove_safe = ef4_farch_filter_remove_safe,
+ .filter_get_safe = ef4_farch_filter_get_safe,
+ .filter_clear_rx = ef4_farch_filter_clear_rx,
+ .filter_count_rx_used = ef4_farch_filter_count_rx_used,
+ .filter_get_rx_id_limit = ef4_farch_filter_get_rx_id_limit,
+ .filter_get_rx_ids = ef4_farch_filter_get_rx_ids,
+
+#ifdef CONFIG_SFC_FALCON_MTD
.mtd_probe = falcon_mtd_probe,
.mtd_rename = falcon_mtd_rename,
.mtd_read = falcon_mtd_read,
@@ -2788,7 +2788,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.mtd_sync = falcon_mtd_sync,
#endif
- .revision = EFX_REV_FALCON_A1,
+ .revision = EF4_REV_FALCON_A1,
.txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER,
.rxd_ptr_tbl_base = FR_AA_RX_DESC_PTR_TBL_KER,
.buf_tbl_base = FR_AA_BUF_FULL_TBL_KER,
@@ -2797,21 +2797,19 @@ const struct efx_nic_type falcon_a1_nic_type = {
.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
.rx_buffer_padding = 0x24,
.can_rx_scatter = false,
- .max_interrupt_mode = EFX_INT_MODE_MSI,
+ .max_interrupt_mode = EF4_INT_MODE_MSI,
.timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM,
- .mcdi_max_ver = -1,
};
-const struct efx_nic_type falcon_b0_nic_type = {
- .is_vf = false,
- .mem_bar = EFX_MEM_BAR,
+const struct ef4_nic_type falcon_b0_nic_type = {
+ .mem_bar = EF4_MEM_BAR,
.mem_map_size = falcon_b0_mem_map_size,
.probe = falcon_probe_nic,
.remove = falcon_remove_nic,
.init = falcon_init_nic,
.dimension_resources = falcon_dimension_resources,
- .fini = efx_port_dummy_op_void,
+ .fini = ef4_port_dummy_op_void,
.monitor = falcon_monitor,
.map_reset_reason = falcon_map_reset_reason,
.map_reset_flags = falcon_map_reset_flags,
@@ -2819,11 +2817,11 @@ const struct efx_nic_type falcon_b0_nic_type = {
.probe_port = falcon_probe_port,
.remove_port = falcon_remove_port,
.handle_global_event = falcon_handle_global_event,
- .fini_dmaq = efx_farch_fini_dmaq,
+ .fini_dmaq = ef4_farch_fini_dmaq,
.prepare_flush = falcon_prepare_flush,
- .finish_flush = efx_port_dummy_op_void,
- .prepare_flr = efx_port_dummy_op_void,
- .finish_flr = efx_farch_finish_flr,
+ .finish_flush = ef4_port_dummy_op_void,
+ .prepare_flr = ef4_port_dummy_op_void,
+ .finish_flr = ef4_farch_finish_flr,
.describe_stats = falcon_describe_nic_stats,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
@@ -2837,47 +2835,48 @@ const struct efx_nic_type falcon_b0_nic_type = {
.check_mac_fault = falcon_xmac_check_fault,
.get_wol = falcon_get_wol,
.set_wol = falcon_set_wol,
- .resume_wol = efx_port_dummy_op_void,
+ .resume_wol = ef4_port_dummy_op_void,
.test_chip = falcon_b0_test_chip,
.test_nvram = falcon_test_nvram,
- .irq_enable_master = efx_farch_irq_enable_master,
- .irq_test_generate = efx_farch_irq_test_generate,
- .irq_disable_non_ev = efx_farch_irq_disable_master,
- .irq_handle_msi = efx_farch_msi_interrupt,
- .irq_handle_legacy = efx_farch_legacy_interrupt,
- .tx_probe = efx_farch_tx_probe,
- .tx_init = efx_farch_tx_init,
- .tx_remove = efx_farch_tx_remove,
- .tx_write = efx_farch_tx_write,
+ .irq_enable_master = ef4_farch_irq_enable_master,
+ .irq_test_generate = ef4_farch_irq_test_generate,
+ .irq_disable_non_ev = ef4_farch_irq_disable_master,
+ .irq_handle_msi = ef4_farch_msi_interrupt,
+ .irq_handle_legacy = ef4_farch_legacy_interrupt,
+ .tx_probe = ef4_farch_tx_probe,
+ .tx_init = ef4_farch_tx_init,
+ .tx_remove = ef4_farch_tx_remove,
+ .tx_write = ef4_farch_tx_write,
+ .tx_limit_len = ef4_farch_tx_limit_len,
.rx_push_rss_config = falcon_b0_rx_push_rss_config,
- .rx_probe = efx_farch_rx_probe,
- .rx_init = efx_farch_rx_init,
- .rx_remove = efx_farch_rx_remove,
- .rx_write = efx_farch_rx_write,
- .rx_defer_refill = efx_farch_rx_defer_refill,
- .ev_probe = efx_farch_ev_probe,
- .ev_init = efx_farch_ev_init,
- .ev_fini = efx_farch_ev_fini,
- .ev_remove = efx_farch_ev_remove,
- .ev_process = efx_farch_ev_process,
- .ev_read_ack = efx_farch_ev_read_ack,
- .ev_test_generate = efx_farch_ev_test_generate,
- .filter_table_probe = efx_farch_filter_table_probe,
- .filter_table_restore = efx_farch_filter_table_restore,
- .filter_table_remove = efx_farch_filter_table_remove,
- .filter_update_rx_scatter = efx_farch_filter_update_rx_scatter,
- .filter_insert = efx_farch_filter_insert,
- .filter_remove_safe = efx_farch_filter_remove_safe,
- .filter_get_safe = efx_farch_filter_get_safe,
- .filter_clear_rx = efx_farch_filter_clear_rx,
- .filter_count_rx_used = efx_farch_filter_count_rx_used,
- .filter_get_rx_id_limit = efx_farch_filter_get_rx_id_limit,
- .filter_get_rx_ids = efx_farch_filter_get_rx_ids,
+ .rx_probe = ef4_farch_rx_probe,
+ .rx_init = ef4_farch_rx_init,
+ .rx_remove = ef4_farch_rx_remove,
+ .rx_write = ef4_farch_rx_write,
+ .rx_defer_refill = ef4_farch_rx_defer_refill,
+ .ev_probe = ef4_farch_ev_probe,
+ .ev_init = ef4_farch_ev_init,
+ .ev_fini = ef4_farch_ev_fini,
+ .ev_remove = ef4_farch_ev_remove,
+ .ev_process = ef4_farch_ev_process,
+ .ev_read_ack = ef4_farch_ev_read_ack,
+ .ev_test_generate = ef4_farch_ev_test_generate,
+ .filter_table_probe = ef4_farch_filter_table_probe,
+ .filter_table_restore = ef4_farch_filter_table_restore,
+ .filter_table_remove = ef4_farch_filter_table_remove,
+ .filter_update_rx_scatter = ef4_farch_filter_update_rx_scatter,
+ .filter_insert = ef4_farch_filter_insert,
+ .filter_remove_safe = ef4_farch_filter_remove_safe,
+ .filter_get_safe = ef4_farch_filter_get_safe,
+ .filter_clear_rx = ef4_farch_filter_clear_rx,
+ .filter_count_rx_used = ef4_farch_filter_count_rx_used,
+ .filter_get_rx_id_limit = ef4_farch_filter_get_rx_id_limit,
+ .filter_get_rx_ids = ef4_farch_filter_get_rx_ids,
#ifdef CONFIG_RFS_ACCEL
- .filter_rfs_insert = efx_farch_filter_rfs_insert,
- .filter_rfs_expire_one = efx_farch_filter_rfs_expire_one,
+ .filter_rfs_insert = ef4_farch_filter_rfs_insert,
+ .filter_rfs_expire_one = ef4_farch_filter_rfs_expire_one,
#endif
-#ifdef CONFIG_SFC_MTD
+#ifdef CONFIG_SFC_FALCON_MTD
.mtd_probe = falcon_mtd_probe,
.mtd_rename = falcon_mtd_rename,
.mtd_read = falcon_mtd_read,
@@ -2886,7 +2885,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.mtd_sync = falcon_mtd_sync,
#endif
- .revision = EFX_REV_FALCON_B0,
+ .revision = EF4_REV_FALCON_B0,
.txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
.rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
.buf_tbl_base = FR_BZ_BUF_FULL_TBL,
@@ -2897,9 +2896,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
.rx_hash_offset = FS_BZ_RX_PREFIX_HASH_OFST,
.rx_buffer_padding = 0,
.can_rx_scatter = true,
- .max_interrupt_mode = EFX_INT_MODE_MSIX,
+ .max_interrupt_mode = EF4_INT_MODE_MSIX,
.timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
- .mcdi_max_ver = -1,
.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
};
diff --git a/drivers/net/ethernet/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon/falcon_boards.c
index f6883b2b5da3..dec83a217093 100644
--- a/drivers/net/ethernet/sfc/falcon_boards.c
+++ b/drivers/net/ethernet/sfc/falcon/falcon_boards.c
@@ -66,7 +66,7 @@
#if IS_ENABLED(CONFIG_SENSORS_LM87)
-static int efx_poke_lm87(struct i2c_client *client, const u8 *reg_values)
+static int ef4_poke_lm87(struct i2c_client *client, const u8 *reg_values)
{
while (*reg_values) {
u8 reg = *reg_values++;
@@ -87,7 +87,7 @@ static const u8 falcon_lm87_common_regs[] = {
0
};
-static int efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info,
+static int ef4_init_lm87(struct ef4_nic *efx, const struct i2c_board_info *info,
const u8 *reg_values)
{
struct falcon_board *board = falcon_board(efx);
@@ -101,10 +101,10 @@ static int efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info,
i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
- rc = efx_poke_lm87(client, reg_values);
+ rc = ef4_poke_lm87(client, reg_values);
if (rc)
goto err;
- rc = efx_poke_lm87(client, falcon_lm87_common_regs);
+ rc = ef4_poke_lm87(client, falcon_lm87_common_regs);
if (rc)
goto err;
@@ -116,12 +116,12 @@ err:
return rc;
}
-static void efx_fini_lm87(struct efx_nic *efx)
+static void ef4_fini_lm87(struct ef4_nic *efx)
{
i2c_unregister_device(falcon_board(efx)->hwmon_client);
}
-static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+static int ef4_check_lm87(struct ef4_nic *efx, unsigned mask)
{
struct i2c_client *client = falcon_board(efx)->hwmon_client;
bool temp_crit, elec_fault, is_failure;
@@ -129,7 +129,7 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
s32 reg;
/* If link is up then do not monitor temperature */
- if (EFX_WORKAROUND_7884(efx) && efx->link_state.up)
+ if (EF4_WORKAROUND_7884(efx) && efx->link_state.up)
return 0;
reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
@@ -179,15 +179,15 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
#else /* !CONFIG_SENSORS_LM87 */
static inline int
-efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info,
+ef4_init_lm87(struct ef4_nic *efx, const struct i2c_board_info *info,
const u8 *reg_values)
{
return 0;
}
-static inline void efx_fini_lm87(struct efx_nic *efx)
+static inline void ef4_fini_lm87(struct ef4_nic *efx)
{
}
-static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+static inline int ef4_check_lm87(struct ef4_nic *efx, unsigned mask)
{
return 0;
}
@@ -255,7 +255,7 @@ static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
#define MAX664X_REG_RSL 0x02
#define MAX664X_REG_WLHO 0x0B
-static void sfe4001_poweroff(struct efx_nic *efx)
+static void sfe4001_poweroff(struct ef4_nic *efx)
{
struct i2c_client *ioexp_client = falcon_board(efx)->ioexp_client;
struct i2c_client *hwmon_client = falcon_board(efx)->hwmon_client;
@@ -269,7 +269,7 @@ static void sfe4001_poweroff(struct efx_nic *efx)
i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
}
-static int sfe4001_poweron(struct efx_nic *efx)
+static int sfe4001_poweron(struct ef4_nic *efx)
{
struct i2c_client *ioexp_client = falcon_board(efx)->ioexp_client;
struct i2c_client *hwmon_client = falcon_board(efx)->hwmon_client;
@@ -360,7 +360,7 @@ fail_on:
static ssize_t show_phy_flash_cfg(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev));
return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL));
}
@@ -368,8 +368,8 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
- enum efx_phy_mode old_mode, new_mode;
+ struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ enum ef4_phy_mode old_mode, new_mode;
int err;
rtnl_lock();
@@ -390,7 +390,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
falcon_stop_nic_stats(efx);
err = sfe4001_poweron(efx);
if (!err)
- err = efx_reconfigure_port(efx);
+ err = ef4_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL))
falcon_start_nic_stats(efx);
}
@@ -401,7 +401,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg);
-static void sfe4001_fini(struct efx_nic *efx)
+static void sfe4001_fini(struct ef4_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
@@ -413,13 +413,13 @@ static void sfe4001_fini(struct efx_nic *efx)
i2c_unregister_device(board->hwmon_client);
}
-static int sfe4001_check_hw(struct efx_nic *efx)
+static int sfe4001_check_hw(struct ef4_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
s32 status;
/* If XAUI link is up then do not monitor */
- if (EFX_WORKAROUND_7884(efx) && !nic_data->xmac_poll_required)
+ if (EF4_WORKAROUND_7884(efx) && !nic_data->xmac_poll_required)
return 0;
/* Check the powered status of the PHY. Lack of power implies that
@@ -450,7 +450,7 @@ static const struct i2c_board_info sfe4001_hwmon_info = {
* be turned on before the PHY can be used.
* Context: Process context, rtnl lock held
*/
-static int sfe4001_init(struct efx_nic *efx)
+static int sfe4001_init(struct ef4_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
int rc;
@@ -537,7 +537,7 @@ static const struct i2c_board_info sfe4002_hwmon_info = {
#define SFE4002_RX_LED (0) /* Green */
#define SFE4002_TX_LED (1) /* Amber */
-static void sfe4002_init_phy(struct efx_nic *efx)
+static void sfe4002_init_phy(struct ef4_nic *efx)
{
/* Set the TX and RX LEDs to reflect status and activity, and the
* fault LED off */
@@ -548,14 +548,14 @@ static void sfe4002_init_phy(struct efx_nic *efx)
falcon_qt202x_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
}
-static void sfe4002_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+static void sfe4002_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{
falcon_qt202x_set_led(
efx, SFE4002_FAULT_LED,
- (mode == EFX_LED_ON) ? QUAKE_LED_ON : QUAKE_LED_OFF);
+ (mode == EF4_LED_ON) ? QUAKE_LED_ON : QUAKE_LED_OFF);
}
-static int sfe4002_check_hw(struct efx_nic *efx)
+static int sfe4002_check_hw(struct ef4_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
@@ -565,12 +565,12 @@ static int sfe4002_check_hw(struct efx_nic *efx)
(board->major == 0 && board->minor == 0) ?
~LM87_ALARM_TEMP_EXT1 : ~0;
- return efx_check_lm87(efx, alarm_mask);
+ return ef4_check_lm87(efx, alarm_mask);
}
-static int sfe4002_init(struct efx_nic *efx)
+static int sfe4002_init(struct ef4_nic *efx)
{
- return efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
+ return ef4_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
}
/*****************************************************************************
@@ -599,7 +599,7 @@ static const struct i2c_board_info sfn4112f_hwmon_info = {
#define SFN4112F_ACT_LED 0
#define SFN4112F_LINK_LED 1
-static void sfn4112f_init_phy(struct efx_nic *efx)
+static void sfn4112f_init_phy(struct ef4_nic *efx)
{
falcon_qt202x_set_led(efx, SFN4112F_ACT_LED,
QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACT);
@@ -607,15 +607,15 @@ static void sfn4112f_init_phy(struct efx_nic *efx)
QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT);
}
-static void sfn4112f_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+static void sfn4112f_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{
int reg;
switch (mode) {
- case EFX_LED_OFF:
+ case EF4_LED_OFF:
reg = QUAKE_LED_OFF;
break;
- case EFX_LED_ON:
+ case EF4_LED_ON:
reg = QUAKE_LED_ON;
break;
default:
@@ -626,15 +626,15 @@ static void sfn4112f_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
falcon_qt202x_set_led(efx, SFN4112F_LINK_LED, reg);
}
-static int sfn4112f_check_hw(struct efx_nic *efx)
+static int sfn4112f_check_hw(struct ef4_nic *efx)
{
/* Mask out unused sensors */
- return efx_check_lm87(efx, ~0x48);
+ return ef4_check_lm87(efx, ~0x48);
}
-static int sfn4112f_init(struct efx_nic *efx)
+static int sfn4112f_init(struct ef4_nic *efx)
{
- return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
+ return ef4_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
}
/*****************************************************************************
@@ -663,7 +663,7 @@ static const struct i2c_board_info sfe4003_hwmon_info = {
#define SFE4003_LED_ON 1
#define SFE4003_LED_OFF 0
-static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+static void sfe4003_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{
struct falcon_board *board = falcon_board(efx);
@@ -673,10 +673,10 @@ static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
falcon_txc_set_gpio_val(
efx, SFE4003_RED_LED_GPIO,
- (mode == EFX_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF);
+ (mode == EF4_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF);
}
-static void sfe4003_init_phy(struct efx_nic *efx)
+static void sfe4003_init_phy(struct ef4_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
@@ -688,7 +688,7 @@ static void sfe4003_init_phy(struct efx_nic *efx)
falcon_txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
}
-static int sfe4003_check_hw(struct efx_nic *efx)
+static int sfe4003_check_hw(struct ef4_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
@@ -698,19 +698,19 @@ static int sfe4003_check_hw(struct efx_nic *efx)
(board->major == 0 && board->minor <= 2) ?
~LM87_ALARM_TEMP_EXT1 : ~0;
- return efx_check_lm87(efx, alarm_mask);
+ return ef4_check_lm87(efx, alarm_mask);
}
-static int sfe4003_init(struct efx_nic *efx)
+static int sfe4003_init(struct ef4_nic *efx)
{
- return efx_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs);
+ return ef4_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs);
}
static const struct falcon_board_type board_types[] = {
{
.id = FALCON_BOARD_SFE4001,
.init = sfe4001_init,
- .init_phy = efx_port_dummy_op_void,
+ .init_phy = ef4_port_dummy_op_void,
.fini = sfe4001_fini,
.set_id_led = tenxpress_set_id_led,
.monitor = sfe4001_check_hw,
@@ -719,7 +719,7 @@ static const struct falcon_board_type board_types[] = {
.id = FALCON_BOARD_SFE4002,
.init = sfe4002_init,
.init_phy = sfe4002_init_phy,
- .fini = efx_fini_lm87,
+ .fini = ef4_fini_lm87,
.set_id_led = sfe4002_set_id_led,
.monitor = sfe4002_check_hw,
},
@@ -727,7 +727,7 @@ static const struct falcon_board_type board_types[] = {
.id = FALCON_BOARD_SFE4003,
.init = sfe4003_init,
.init_phy = sfe4003_init_phy,
- .fini = efx_fini_lm87,
+ .fini = ef4_fini_lm87,
.set_id_led = sfe4003_set_id_led,
.monitor = sfe4003_check_hw,
},
@@ -735,13 +735,13 @@ static const struct falcon_board_type board_types[] = {
.id = FALCON_BOARD_SFN4112F,
.init = sfn4112f_init,
.init_phy = sfn4112f_init_phy,
- .fini = efx_fini_lm87,
+ .fini = ef4_fini_lm87,
.set_id_led = sfn4112f_set_id_led,
.monitor = sfn4112f_check_hw,
},
};
-int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
+int falcon_probe_board(struct ef4_nic *efx, u16 revision_info)
{
struct falcon_board *board = falcon_board(efx);
u8 type_id = FALCON_BOARD_TYPE(revision_info);
diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c
new file mode 100644
index 000000000000..05916c710d8c
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/farch.c
@@ -0,0 +1,2892 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/crc32.h>
+#include "net_driver.h"
+#include "bitfield.h"
+#include "efx.h"
+#include "nic.h"
+#include "farch_regs.h"
+#include "io.h"
+#include "workarounds.h"
+
+/* Falcon-architecture (SFC4000) support */
+
+/**************************************************************************
+ *
+ * Configurable values
+ *
+ **************************************************************************
+ */
+
+/* This is set to 16 for a good reason. In summary, if larger than
+ * 16, the descriptor cache holds more than a default socket
+ * buffer's worth of packets (for UDP we can only have at most one
+ * socket buffer's worth outstanding). This combined with the fact
+ * that we only get 1 TX event per descriptor cache means the NIC
+ * goes idle.
+ */
+#define TX_DC_ENTRIES 16
+#define TX_DC_ENTRIES_ORDER 1
+
+#define RX_DC_ENTRIES 64
+#define RX_DC_ENTRIES_ORDER 3
+
+/* If EF4_MAX_INT_ERRORS internal errors occur within
+ * EF4_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
+ * disable it.
+ */
+#define EF4_INT_ERROR_EXPIRE 3600
+#define EF4_MAX_INT_ERRORS 5
+
+/* Depth of RX flush request fifo */
+#define EF4_RX_FLUSH_COUNT 4
+
+/* Driver generated events */
+#define _EF4_CHANNEL_MAGIC_TEST 0x000101
+#define _EF4_CHANNEL_MAGIC_FILL 0x000102
+#define _EF4_CHANNEL_MAGIC_RX_DRAIN 0x000103
+#define _EF4_CHANNEL_MAGIC_TX_DRAIN 0x000104
+
+#define _EF4_CHANNEL_MAGIC(_code, _data) ((_code) << 8 | (_data))
+#define _EF4_CHANNEL_MAGIC_CODE(_magic) ((_magic) >> 8)
+
+#define EF4_CHANNEL_MAGIC_TEST(_channel) \
+ _EF4_CHANNEL_MAGIC(_EF4_CHANNEL_MAGIC_TEST, (_channel)->channel)
+#define EF4_CHANNEL_MAGIC_FILL(_rx_queue) \
+ _EF4_CHANNEL_MAGIC(_EF4_CHANNEL_MAGIC_FILL, \
+ ef4_rx_queue_index(_rx_queue))
+#define EF4_CHANNEL_MAGIC_RX_DRAIN(_rx_queue) \
+ _EF4_CHANNEL_MAGIC(_EF4_CHANNEL_MAGIC_RX_DRAIN, \
+ ef4_rx_queue_index(_rx_queue))
+#define EF4_CHANNEL_MAGIC_TX_DRAIN(_tx_queue) \
+ _EF4_CHANNEL_MAGIC(_EF4_CHANNEL_MAGIC_TX_DRAIN, \
+ (_tx_queue)->queue)
+
+static void ef4_farch_magic_event(struct ef4_channel *channel, u32 magic);
+
+/**************************************************************************
+ *
+ * Hardware access
+ *
+ **************************************************************************/
+
+static inline void ef4_write_buf_tbl(struct ef4_nic *efx, ef4_qword_t *value,
+ unsigned int index)
+{
+ ef4_sram_writeq(efx, efx->membase + efx->type->buf_tbl_base,
+ value, index);
+}
+
+static bool ef4_masked_compare_oword(const ef4_oword_t *a, const ef4_oword_t *b,
+ const ef4_oword_t *mask)
+{
+ return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) ||
+ ((a->u64[1] ^ b->u64[1]) & mask->u64[1]);
+}
+
+int ef4_farch_test_registers(struct ef4_nic *efx,
+ const struct ef4_farch_register_test *regs,
+ size_t n_regs)
+{
+ unsigned address = 0;
+ int i, j;
+ ef4_oword_t mask, imask, original, reg, buf;
+
+ for (i = 0; i < n_regs; ++i) {
+ address = regs[i].address;
+ mask = imask = regs[i].mask;
+ EF4_INVERT_OWORD(imask);
+
+ ef4_reado(efx, &original, address);
+
+ /* bit sweep on and off */
+ for (j = 0; j < 128; j++) {
+ if (!EF4_EXTRACT_OWORD32(mask, j, j))
+ continue;
+
+ /* Test this testable bit can be set in isolation */
+ EF4_AND_OWORD(reg, original, mask);
+ EF4_SET_OWORD32(reg, j, j, 1);
+
+ ef4_writeo(efx, &reg, address);
+ ef4_reado(efx, &buf, address);
+
+ if (ef4_masked_compare_oword(&reg, &buf, &mask))
+ goto fail;
+
+ /* Test this testable bit can be cleared in isolation */
+ EF4_OR_OWORD(reg, original, mask);
+ EF4_SET_OWORD32(reg, j, j, 0);
+
+ ef4_writeo(efx, &reg, address);
+ ef4_reado(efx, &buf, address);
+
+ if (ef4_masked_compare_oword(&reg, &buf, &mask))
+ goto fail;
+ }
+
+ ef4_writeo(efx, &original, address);
+ }
+
+ return 0;
+
+fail:
+ netif_err(efx, hw, efx->net_dev,
+ "wrote "EF4_OWORD_FMT" read "EF4_OWORD_FMT
+ " at address 0x%x mask "EF4_OWORD_FMT"\n", EF4_OWORD_VAL(reg),
+ EF4_OWORD_VAL(buf), address, EF4_OWORD_VAL(mask));
+ return -EIO;
+}
+
+/**************************************************************************
+ *
+ * Special buffer handling
+ * Special buffers are used for event queues and the TX and RX
+ * descriptor rings.
+ *
+ *************************************************************************/
+
+/*
+ * Initialise a special buffer
+ *
+ * This will define a buffer (previously allocated via
+ * ef4_alloc_special_buffer()) in the buffer table, allowing
+ * it to be used for event queues, descriptor rings etc.
+ */
+static void
+ef4_init_special_buffer(struct ef4_nic *efx, struct ef4_special_buffer *buffer)
+{
+ ef4_qword_t buf_desc;
+ unsigned int index;
+ dma_addr_t dma_addr;
+ int i;
+
+ EF4_BUG_ON_PARANOID(!buffer->buf.addr);
+
+ /* Write buffer descriptors to NIC */
+ for (i = 0; i < buffer->entries; i++) {
+ index = buffer->index + i;
+ dma_addr = buffer->buf.dma_addr + (i * EF4_BUF_SIZE);
+ netif_dbg(efx, probe, efx->net_dev,
+ "mapping special buffer %d at %llx\n",
+ index, (unsigned long long)dma_addr);
+ EF4_POPULATE_QWORD_3(buf_desc,
+ FRF_AZ_BUF_ADR_REGION, 0,
+ FRF_AZ_BUF_ADR_FBUF, dma_addr >> 12,
+ FRF_AZ_BUF_OWNER_ID_FBUF, 0);
+ ef4_write_buf_tbl(efx, &buf_desc, index);
+ }
+}
+
+/* Unmaps a buffer and clears the buffer table entries */
+static void
+ef4_fini_special_buffer(struct ef4_nic *efx, struct ef4_special_buffer *buffer)
+{
+ ef4_oword_t buf_tbl_upd;
+ unsigned int start = buffer->index;
+ unsigned int end = (buffer->index + buffer->entries - 1);
+
+ if (!buffer->entries)
+ return;
+
+ netif_dbg(efx, hw, efx->net_dev, "unmapping special buffers %d-%d\n",
+ buffer->index, buffer->index + buffer->entries - 1);
+
+ EF4_POPULATE_OWORD_4(buf_tbl_upd,
+ FRF_AZ_BUF_UPD_CMD, 0,
+ FRF_AZ_BUF_CLR_CMD, 1,
+ FRF_AZ_BUF_CLR_END_ID, end,
+ FRF_AZ_BUF_CLR_START_ID, start);
+ ef4_writeo(efx, &buf_tbl_upd, FR_AZ_BUF_TBL_UPD);
+}
+
+/*
+ * Allocate a new special buffer
+ *
+ * This allocates memory for a new buffer, clears it and allocates a
+ * new buffer ID range. It does not write into the buffer table.
+ *
+ * This call will allocate 4KB buffers, since 8KB buffers can't be
+ * used for event queues and descriptor rings.
+ */
+static int ef4_alloc_special_buffer(struct ef4_nic *efx,
+ struct ef4_special_buffer *buffer,
+ unsigned int len)
+{
+ len = ALIGN(len, EF4_BUF_SIZE);
+
+ if (ef4_nic_alloc_buffer(efx, &buffer->buf, len, GFP_KERNEL))
+ return -ENOMEM;
+ buffer->entries = len / EF4_BUF_SIZE;
+ BUG_ON(buffer->buf.dma_addr & (EF4_BUF_SIZE - 1));
+
+ /* Select new buffer ID */
+ buffer->index = efx->next_buffer_table;
+ efx->next_buffer_table += buffer->entries;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "allocating special buffers %d-%d at %llx+%x "
+ "(virt %p phys %llx)\n", buffer->index,
+ buffer->index + buffer->entries - 1,
+ (u64)buffer->buf.dma_addr, len,
+ buffer->buf.addr, (u64)virt_to_phys(buffer->buf.addr));
+
+ return 0;
+}
+
+static void
+ef4_free_special_buffer(struct ef4_nic *efx, struct ef4_special_buffer *buffer)
+{
+ if (!buffer->buf.addr)
+ return;
+
+ netif_dbg(efx, hw, efx->net_dev,
+ "deallocating special buffers %d-%d at %llx+%x "
+ "(virt %p phys %llx)\n", buffer->index,
+ buffer->index + buffer->entries - 1,
+ (u64)buffer->buf.dma_addr, buffer->buf.len,
+ buffer->buf.addr, (u64)virt_to_phys(buffer->buf.addr));
+
+ ef4_nic_free_buffer(efx, &buffer->buf);
+ buffer->entries = 0;
+}
+
+/**************************************************************************
+ *
+ * TX path
+ *
+ **************************************************************************/
+
+/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
+static inline void ef4_farch_notify_tx_desc(struct ef4_tx_queue *tx_queue)
+{
+ unsigned write_ptr;
+ ef4_dword_t reg;
+
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
+ EF4_POPULATE_DWORD_1(reg, FRF_AZ_TX_DESC_WPTR_DWORD, write_ptr);
+ ef4_writed_page(tx_queue->efx, &reg,
+ FR_AZ_TX_DESC_UPD_DWORD_P0, tx_queue->queue);
+}
+
+/* Write pointer and first descriptor for TX descriptor ring */
+static inline void ef4_farch_push_tx_desc(struct ef4_tx_queue *tx_queue,
+ const ef4_qword_t *txd)
+{
+ unsigned write_ptr;
+ ef4_oword_t reg;
+
+ BUILD_BUG_ON(FRF_AZ_TX_DESC_LBN != 0);
+ BUILD_BUG_ON(FR_AA_TX_DESC_UPD_KER != FR_BZ_TX_DESC_UPD_P0);
+
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
+ EF4_POPULATE_OWORD_2(reg, FRF_AZ_TX_DESC_PUSH_CMD, true,
+ FRF_AZ_TX_DESC_WPTR, write_ptr);
+ reg.qword[0] = *txd;
+ ef4_writeo_page(tx_queue->efx, &reg,
+ FR_BZ_TX_DESC_UPD_P0, tx_queue->queue);
+}
+
+
+/* For each entry inserted into the software descriptor ring, create a
+ * descriptor in the hardware TX descriptor ring (in host memory), and
+ * write a doorbell.
+ */
+void ef4_farch_tx_write(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_tx_buffer *buffer;
+ ef4_qword_t *txd;
+ unsigned write_ptr;
+ unsigned old_write_count = tx_queue->write_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;
+ buffer = &tx_queue->buffer[write_ptr];
+ txd = ef4_tx_desc(tx_queue, write_ptr);
+ ++tx_queue->write_count;
+
+ EF4_BUG_ON_PARANOID(buffer->flags & EF4_TX_BUF_OPTION);
+
+ /* Create TX descriptor ring entry */
+ BUILD_BUG_ON(EF4_TX_BUF_CONT != 1);
+ EF4_POPULATE_QWORD_4(*txd,
+ FSF_AZ_TX_KER_CONT,
+ buffer->flags & EF4_TX_BUF_CONT,
+ FSF_AZ_TX_KER_BYTE_COUNT, buffer->len,
+ FSF_AZ_TX_KER_BUF_REGION, 0,
+ FSF_AZ_TX_KER_BUF_ADDR, buffer->dma_addr);
+ } while (tx_queue->write_count != tx_queue->insert_count);
+
+ wmb(); /* Ensure descriptors are written before they are fetched */
+
+ if (ef4_nic_may_push_tx_desc(tx_queue, old_write_count)) {
+ txd = ef4_tx_desc(tx_queue,
+ old_write_count & tx_queue->ptr_mask);
+ ef4_farch_push_tx_desc(tx_queue, txd);
+ ++tx_queue->pushes;
+ } else {
+ ef4_farch_notify_tx_desc(tx_queue);
+ }
+}
+
+unsigned int ef4_farch_tx_limit_len(struct ef4_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len)
+{
+ /* Don't cross 4K boundaries with descriptors. */
+ unsigned int limit = (~dma_addr & (EF4_PAGE_SIZE - 1)) + 1;
+
+ len = min(limit, len);
+
+ if (EF4_WORKAROUND_5391(tx_queue->efx) && (dma_addr & 0xf))
+ len = min_t(unsigned int, len, 512 - (dma_addr & 0xf));
+
+ return len;
+}
+
+
+/* Allocate hardware resources for a TX queue */
+int ef4_farch_tx_probe(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ unsigned entries;
+
+ entries = tx_queue->ptr_mask + 1;
+ return ef4_alloc_special_buffer(efx, &tx_queue->txd,
+ entries * sizeof(ef4_qword_t));
+}
+
+void ef4_farch_tx_init(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ ef4_oword_t reg;
+
+ /* Pin TX descriptor ring */
+ ef4_init_special_buffer(efx, &tx_queue->txd);
+
+ /* Push TX descriptor ring to card */
+ EF4_POPULATE_OWORD_10(reg,
+ FRF_AZ_TX_DESCQ_EN, 1,
+ FRF_AZ_TX_ISCSI_DDIG_EN, 0,
+ FRF_AZ_TX_ISCSI_HDIG_EN, 0,
+ FRF_AZ_TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
+ FRF_AZ_TX_DESCQ_EVQ_ID,
+ tx_queue->channel->channel,
+ FRF_AZ_TX_DESCQ_OWNER_ID, 0,
+ FRF_AZ_TX_DESCQ_LABEL, tx_queue->queue,
+ FRF_AZ_TX_DESCQ_SIZE,
+ __ffs(tx_queue->txd.entries),
+ FRF_AZ_TX_DESCQ_TYPE, 0,
+ FRF_BZ_TX_NON_IP_DROP_DIS, 1);
+
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ int csum = tx_queue->queue & EF4_TXQ_TYPE_OFFLOAD;
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+ EF4_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS,
+ !csum);
+ }
+
+ ef4_writeo_table(efx, &reg, efx->type->txd_ptr_tbl_base,
+ tx_queue->queue);
+
+ if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0) {
+ /* Only 128 bits in this register */
+ BUILD_BUG_ON(EF4_MAX_TX_QUEUES > 128);
+
+ ef4_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
+ if (tx_queue->queue & EF4_TXQ_TYPE_OFFLOAD)
+ __clear_bit_le(tx_queue->queue, &reg);
+ else
+ __set_bit_le(tx_queue->queue, &reg);
+ ef4_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
+ }
+
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ EF4_POPULATE_OWORD_1(reg,
+ FRF_BZ_TX_PACE,
+ (tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI) ?
+ FFE_BZ_TX_PACE_OFF :
+ FFE_BZ_TX_PACE_RESERVED);
+ ef4_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL,
+ tx_queue->queue);
+ }
+}
+
+static void ef4_farch_flush_tx_queue(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ ef4_oword_t tx_flush_descq;
+
+ WARN_ON(atomic_read(&tx_queue->flush_outstanding));
+ atomic_set(&tx_queue->flush_outstanding, 1);
+
+ EF4_POPULATE_OWORD_2(tx_flush_descq,
+ FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
+ FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
+ ef4_writeo(efx, &tx_flush_descq, FR_AZ_TX_FLUSH_DESCQ);
+}
+
+void ef4_farch_tx_fini(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ ef4_oword_t tx_desc_ptr;
+
+ /* Remove TX descriptor ring from card */
+ EF4_ZERO_OWORD(tx_desc_ptr);
+ ef4_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+ tx_queue->queue);
+
+ /* Unpin TX descriptor ring */
+ ef4_fini_special_buffer(efx, &tx_queue->txd);
+}
+
+/* Free buffers backing TX queue */
+void ef4_farch_tx_remove(struct ef4_tx_queue *tx_queue)
+{
+ ef4_free_special_buffer(tx_queue->efx, &tx_queue->txd);
+}
+
+/**************************************************************************
+ *
+ * RX path
+ *
+ **************************************************************************/
+
+/* This creates an entry in the RX descriptor queue */
+static inline void
+ef4_farch_build_rx_desc(struct ef4_rx_queue *rx_queue, unsigned index)
+{
+ struct ef4_rx_buffer *rx_buf;
+ ef4_qword_t *rxd;
+
+ rxd = ef4_rx_desc(rx_queue, index);
+ rx_buf = ef4_rx_buffer(rx_queue, index);
+ EF4_POPULATE_QWORD_3(*rxd,
+ FSF_AZ_RX_KER_BUF_SIZE,
+ rx_buf->len -
+ rx_queue->efx->type->rx_buffer_padding,
+ FSF_AZ_RX_KER_BUF_REGION, 0,
+ FSF_AZ_RX_KER_BUF_ADDR, rx_buf->dma_addr);
+}
+
+/* This writes to the RX_DESC_WPTR register for the specified receive
+ * descriptor ring.
+ */
+void ef4_farch_rx_write(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ ef4_dword_t reg;
+ unsigned write_ptr;
+
+ while (rx_queue->notified_count != rx_queue->added_count) {
+ ef4_farch_build_rx_desc(
+ rx_queue,
+ rx_queue->notified_count & rx_queue->ptr_mask);
+ ++rx_queue->notified_count;
+ }
+
+ wmb();
+ write_ptr = rx_queue->added_count & rx_queue->ptr_mask;
+ EF4_POPULATE_DWORD_1(reg, FRF_AZ_RX_DESC_WPTR_DWORD, write_ptr);
+ ef4_writed_page(efx, &reg, FR_AZ_RX_DESC_UPD_DWORD_P0,
+ ef4_rx_queue_index(rx_queue));
+}
+
+int ef4_farch_rx_probe(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned entries;
+
+ entries = rx_queue->ptr_mask + 1;
+ return ef4_alloc_special_buffer(efx, &rx_queue->rxd,
+ entries * sizeof(ef4_qword_t));
+}
+
+void ef4_farch_rx_init(struct ef4_rx_queue *rx_queue)
+{
+ ef4_oword_t rx_desc_ptr;
+ struct ef4_nic *efx = rx_queue->efx;
+ bool is_b0 = ef4_nic_rev(efx) >= EF4_REV_FALCON_B0;
+ bool iscsi_digest_en = is_b0;
+ bool jumbo_en;
+
+ /* For kernel-mode queues in Falcon A1, the JUMBO flag enables
+ * DMA to continue after a PCIe page boundary (and scattering
+ * is not possible). In Falcon B0 and Siena, it enables
+ * scatter.
+ */
+ jumbo_en = !is_b0 || efx->rx_scatter;
+
+ netif_dbg(efx, hw, efx->net_dev,
+ "RX queue %d ring in special buffers %d-%d\n",
+ ef4_rx_queue_index(rx_queue), rx_queue->rxd.index,
+ rx_queue->rxd.index + rx_queue->rxd.entries - 1);
+
+ rx_queue->scatter_n = 0;
+
+ /* Pin RX descriptor ring */
+ ef4_init_special_buffer(efx, &rx_queue->rxd);
+
+ /* Push RX descriptor ring to card */
+ EF4_POPULATE_OWORD_10(rx_desc_ptr,
+ FRF_AZ_RX_ISCSI_DDIG_EN, iscsi_digest_en,
+ FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
+ FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
+ FRF_AZ_RX_DESCQ_EVQ_ID,
+ ef4_rx_queue_channel(rx_queue)->channel,
+ FRF_AZ_RX_DESCQ_OWNER_ID, 0,
+ FRF_AZ_RX_DESCQ_LABEL,
+ ef4_rx_queue_index(rx_queue),
+ FRF_AZ_RX_DESCQ_SIZE,
+ __ffs(rx_queue->rxd.entries),
+ FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
+ FRF_AZ_RX_DESCQ_JUMBO, jumbo_en,
+ FRF_AZ_RX_DESCQ_EN, 1);
+ ef4_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
+ ef4_rx_queue_index(rx_queue));
+}
+
+static void ef4_farch_flush_rx_queue(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ ef4_oword_t rx_flush_descq;
+
+ EF4_POPULATE_OWORD_2(rx_flush_descq,
+ FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
+ FRF_AZ_RX_FLUSH_DESCQ,
+ ef4_rx_queue_index(rx_queue));
+ ef4_writeo(efx, &rx_flush_descq, FR_AZ_RX_FLUSH_DESCQ);
+}
+
+void ef4_farch_rx_fini(struct ef4_rx_queue *rx_queue)
+{
+ ef4_oword_t rx_desc_ptr;
+ struct ef4_nic *efx = rx_queue->efx;
+
+ /* Remove RX descriptor ring from card */
+ EF4_ZERO_OWORD(rx_desc_ptr);
+ ef4_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
+ ef4_rx_queue_index(rx_queue));
+
+ /* Unpin RX descriptor ring */
+ ef4_fini_special_buffer(efx, &rx_queue->rxd);
+}
+
+/* Free buffers backing RX queue */
+void ef4_farch_rx_remove(struct ef4_rx_queue *rx_queue)
+{
+ ef4_free_special_buffer(rx_queue->efx, &rx_queue->rxd);
+}
+
+/**************************************************************************
+ *
+ * Flush handling
+ *
+ **************************************************************************/
+
+/* ef4_farch_flush_queues() must be woken up when all flushes are completed,
+ * or more RX flushes can be kicked off.
+ */
+static bool ef4_farch_flush_wake(struct ef4_nic *efx)
+{
+ /* Ensure that all updates are visible to ef4_farch_flush_queues() */
+ smp_mb();
+
+ return (atomic_read(&efx->active_queues) == 0 ||
+ (atomic_read(&efx->rxq_flush_outstanding) < EF4_RX_FLUSH_COUNT
+ && atomic_read(&efx->rxq_flush_pending) > 0));
+}
+
+static bool ef4_check_tx_flush_complete(struct ef4_nic *efx)
+{
+ bool i = true;
+ ef4_oword_t txd_ptr_tbl;
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ ef4_reado_table(efx, &txd_ptr_tbl,
+ FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue);
+ if (EF4_OWORD_FIELD(txd_ptr_tbl,
+ FRF_AZ_TX_DESCQ_FLUSH) ||
+ EF4_OWORD_FIELD(txd_ptr_tbl,
+ FRF_AZ_TX_DESCQ_EN)) {
+ netif_dbg(efx, hw, efx->net_dev,
+ "flush did not complete on TXQ %d\n",
+ tx_queue->queue);
+ i = false;
+ } else if (atomic_cmpxchg(&tx_queue->flush_outstanding,
+ 1, 0)) {
+ /* The flush is complete, but we didn't
+ * receive a flush completion event
+ */
+ netif_dbg(efx, hw, efx->net_dev,
+ "flush complete on TXQ %d, so drain "
+ "the queue\n", tx_queue->queue);
+ /* Don't need to increment active_queues as it
+ * has already been incremented for the queues
+ * which did not drain
+ */
+ ef4_farch_magic_event(channel,
+ EF4_CHANNEL_MAGIC_TX_DRAIN(
+ tx_queue));
+ }
+ }
+ }
+
+ return i;
+}
+
+/* Flush all the transmit queues, and continue flushing receive queues until
+ * they're all flushed. Wait for the DRAIN events to be received so that there
+ * are no more RX and TX events left on any channel. */
+static int ef4_farch_do_flush(struct ef4_nic *efx)
+{
+ unsigned timeout = msecs_to_jiffies(5000); /* 5s for all flushes and drains */
+ struct ef4_channel *channel;
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_tx_queue *tx_queue;
+ int rc = 0;
+
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ ef4_farch_flush_tx_queue(tx_queue);
+ }
+ ef4_for_each_channel_rx_queue(rx_queue, channel) {
+ rx_queue->flush_pending = true;
+ atomic_inc(&efx->rxq_flush_pending);
+ }
+ }
+
+ while (timeout && atomic_read(&efx->active_queues) > 0) {
+ /* The hardware supports four concurrent rx flushes, each of
+ * which may need to be retried if there is an outstanding
+ * descriptor fetch
+ */
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_rx_queue(rx_queue, channel) {
+ if (atomic_read(&efx->rxq_flush_outstanding) >=
+ EF4_RX_FLUSH_COUNT)
+ break;
+
+ if (rx_queue->flush_pending) {
+ rx_queue->flush_pending = false;
+ atomic_dec(&efx->rxq_flush_pending);
+ atomic_inc(&efx->rxq_flush_outstanding);
+ ef4_farch_flush_rx_queue(rx_queue);
+ }
+ }
+ }
+
+ timeout = wait_event_timeout(efx->flush_wq,
+ ef4_farch_flush_wake(efx),
+ timeout);
+ }
+
+ if (atomic_read(&efx->active_queues) &&
+ !ef4_check_tx_flush_complete(efx)) {
+ netif_err(efx, hw, efx->net_dev, "failed to flush %d queues "
+ "(rx %d+%d)\n", atomic_read(&efx->active_queues),
+ atomic_read(&efx->rxq_flush_outstanding),
+ atomic_read(&efx->rxq_flush_pending));
+ rc = -ETIMEDOUT;
+
+ atomic_set(&efx->active_queues, 0);
+ atomic_set(&efx->rxq_flush_pending, 0);
+ atomic_set(&efx->rxq_flush_outstanding, 0);
+ }
+
+ return rc;
+}
+
+int ef4_farch_fini_dmaq(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_rx_queue *rx_queue;
+ int rc = 0;
+
+ /* Do not attempt to write to the NIC during EEH recovery */
+ if (efx->state != STATE_RECOVERY) {
+ /* Only perform flush if DMA is enabled */
+ if (efx->pci_dev->is_busmaster) {
+ efx->type->prepare_flush(efx);
+ rc = ef4_farch_do_flush(efx);
+ efx->type->finish_flush(efx);
+ }
+
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_channel_rx_queue(rx_queue, channel)
+ ef4_farch_rx_fini(rx_queue);
+ ef4_for_each_channel_tx_queue(tx_queue, channel)
+ ef4_farch_tx_fini(tx_queue);
+ }
+ }
+
+ return rc;
+}
+
+/* Reset queue and flush accounting after FLR
+ *
+ * One possible cause of FLR recovery is that DMA may be failing (eg. if bus
+ * mastering was disabled), in which case we don't receive (RXQ) flush
+ * completion events. This means that efx->rxq_flush_outstanding remained at 4
+ * after the FLR; also, efx->active_queues was non-zero (as no flush completion
+ * events were received, and we didn't go through ef4_check_tx_flush_complete())
+ * If we don't fix this up, on the next call to ef4_realloc_channels() we won't
+ * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4
+ * for batched flush requests; and the efx->active_queues gets messed up because
+ * we keep incrementing for the newly initialised queues, but it never went to
+ * zero previously. Then we get a timeout every time we try to restart the
+ * queues, as it doesn't go back to zero when we should be flushing the queues.
+ */
+void ef4_farch_finish_flr(struct ef4_nic *efx)
+{
+ atomic_set(&efx->rxq_flush_pending, 0);
+ atomic_set(&efx->rxq_flush_outstanding, 0);
+ atomic_set(&efx->active_queues, 0);
+}
+
+
+/**************************************************************************
+ *
+ * Event queue processing
+ * Event queues are processed by per-channel tasklets.
+ *
+ **************************************************************************/
+
+/* Update a channel's event queue's read pointer (RPTR) register
+ *
+ * This writes the EVQ_RPTR_REG register for the specified channel's
+ * event queue.
+ */
+void ef4_farch_ev_read_ack(struct ef4_channel *channel)
+{
+ ef4_dword_t reg;
+ struct ef4_nic *efx = channel->efx;
+
+ EF4_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
+ channel->eventq_read_ptr & channel->eventq_mask);
+
+ /* For Falcon A1, EVQ_RPTR_KER is documented as having a step size
+ * of 4 bytes, but it is really 16 bytes just like later revisions.
+ */
+ ef4_writed(efx, &reg,
+ efx->type->evq_rptr_tbl_base +
+ FR_BZ_EVQ_RPTR_STEP * channel->channel);
+}
+
+/* Use HW to insert a SW defined event */
+void ef4_farch_generate_event(struct ef4_nic *efx, unsigned int evq,
+ ef4_qword_t *event)
+{
+ ef4_oword_t drv_ev_reg;
+
+ BUILD_BUG_ON(FRF_AZ_DRV_EV_DATA_LBN != 0 ||
+ FRF_AZ_DRV_EV_DATA_WIDTH != 64);
+ drv_ev_reg.u32[0] = event->u32[0];
+ drv_ev_reg.u32[1] = event->u32[1];
+ drv_ev_reg.u32[2] = 0;
+ drv_ev_reg.u32[3] = 0;
+ EF4_SET_OWORD_FIELD(drv_ev_reg, FRF_AZ_DRV_EV_QID, evq);
+ ef4_writeo(efx, &drv_ev_reg, FR_AZ_DRV_EV);
+}
+
+static void ef4_farch_magic_event(struct ef4_channel *channel, u32 magic)
+{
+ ef4_qword_t event;
+
+ EF4_POPULATE_QWORD_2(event, FSF_AZ_EV_CODE,
+ FSE_AZ_EV_CODE_DRV_GEN_EV,
+ FSF_AZ_DRV_GEN_EV_MAGIC, magic);
+ ef4_farch_generate_event(channel->efx, channel->channel, &event);
+}
+
+/* Handle a transmit completion event
+ *
+ * The NIC batches TX completion events; the message we receive is of
+ * the form "complete all TX events up to this index".
+ */
+static int
+ef4_farch_handle_tx_event(struct ef4_channel *channel, ef4_qword_t *event)
+{
+ unsigned int tx_ev_desc_ptr;
+ unsigned int tx_ev_q_label;
+ struct ef4_tx_queue *tx_queue;
+ struct ef4_nic *efx = channel->efx;
+ int tx_packets = 0;
+
+ if (unlikely(ACCESS_ONCE(efx->reset_pending)))
+ return 0;
+
+ if (likely(EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_COMP))) {
+ /* Transmit completion */
+ tx_ev_desc_ptr = EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
+ tx_ev_q_label = EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
+ tx_queue = ef4_channel_get_tx_queue(
+ channel, tx_ev_q_label % EF4_TXQ_TYPES);
+ tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
+ tx_queue->ptr_mask);
+ ef4_xmit_done(tx_queue, tx_ev_desc_ptr);
+ } else if (EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
+ /* Rewrite the FIFO write pointer */
+ tx_ev_q_label = EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
+ tx_queue = ef4_channel_get_tx_queue(
+ channel, tx_ev_q_label % EF4_TXQ_TYPES);
+
+ netif_tx_lock(efx->net_dev);
+ ef4_farch_notify_tx_desc(tx_queue);
+ netif_tx_unlock(efx->net_dev);
+ } else if (EF4_QWORD_FIELD(*event, FSF_AZ_TX_EV_PKT_ERR)) {
+ ef4_schedule_reset(efx, RESET_TYPE_DMA_ERROR);
+ } else {
+ netif_err(efx, tx_err, efx->net_dev,
+ "channel %d unexpected TX event "
+ EF4_QWORD_FMT"\n", channel->channel,
+ EF4_QWORD_VAL(*event));
+ }
+
+ return tx_packets;
+}
+
+/* Detect errors included in the rx_evt_pkt_ok bit. */
+static u16 ef4_farch_handle_rx_not_ok(struct ef4_rx_queue *rx_queue,
+ const ef4_qword_t *event)
+{
+ struct ef4_channel *channel = ef4_rx_queue_channel(rx_queue);
+ struct ef4_nic *efx = rx_queue->efx;
+ bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
+ bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
+ bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
+ bool rx_ev_other_err, rx_ev_pause_frm;
+ bool rx_ev_hdr_type, rx_ev_mcast_pkt;
+ unsigned rx_ev_pkt_type;
+
+ rx_ev_hdr_type = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
+ rx_ev_mcast_pkt = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_PKT);
+ rx_ev_tobe_disc = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_TOBE_DISC);
+ rx_ev_pkt_type = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_TYPE);
+ rx_ev_buf_owner_id_err = EF4_QWORD_FIELD(*event,
+ FSF_AZ_RX_EV_BUF_OWNER_ID_ERR);
+ rx_ev_ip_hdr_chksum_err = EF4_QWORD_FIELD(*event,
+ FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR);
+ rx_ev_tcp_udp_chksum_err = EF4_QWORD_FIELD(*event,
+ FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR);
+ rx_ev_eth_crc_err = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_ETH_CRC_ERR);
+ rx_ev_frm_trunc = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_FRM_TRUNC);
+ rx_ev_drib_nib = ((ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) ?
+ 0 : EF4_QWORD_FIELD(*event, FSF_AA_RX_EV_DRIB_NIB));
+ rx_ev_pause_frm = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_PAUSE_FRM_ERR);
+
+ /* Every error apart from tobe_disc and pause_frm */
+ rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
+ rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
+ rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
+
+ /* Count errors that are not in MAC stats. Ignore expected
+ * checksum errors during self-test. */
+ if (rx_ev_frm_trunc)
+ ++channel->n_rx_frm_trunc;
+ else if (rx_ev_tobe_disc)
+ ++channel->n_rx_tobe_disc;
+ else if (!efx->loopback_selftest) {
+ if (rx_ev_ip_hdr_chksum_err)
+ ++channel->n_rx_ip_hdr_chksum_err;
+ else if (rx_ev_tcp_udp_chksum_err)
+ ++channel->n_rx_tcp_udp_chksum_err;
+ }
+
+ /* TOBE_DISC is expected on unicast mismatches; don't print out an
+ * error message. FRM_TRUNC indicates RXDP dropped the packet due
+ * to a FIFO overflow.
+ */
+#ifdef DEBUG
+ if (rx_ev_other_err && net_ratelimit()) {
+ netif_dbg(efx, rx_err, efx->net_dev,
+ " RX queue %d unexpected RX event "
+ EF4_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
+ ef4_rx_queue_index(rx_queue), EF4_QWORD_VAL(*event),
+ rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
+ rx_ev_ip_hdr_chksum_err ?
+ " [IP_HDR_CHKSUM_ERR]" : "",
+ rx_ev_tcp_udp_chksum_err ?
+ " [TCP_UDP_CHKSUM_ERR]" : "",
+ rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
+ rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
+ rx_ev_drib_nib ? " [DRIB_NIB]" : "",
+ rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
+ rx_ev_pause_frm ? " [PAUSE]" : "");
+ }
+#endif
+
+ /* The frame must be discarded if any of these are true. */
+ return (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
+ rx_ev_tobe_disc | rx_ev_pause_frm) ?
+ EF4_RX_PKT_DISCARD : 0;
+}
+
+/* Handle receive events that are not in-order. Return true if this
+ * can be handled as a partial packet discard, false if it's more
+ * serious.
+ */
+static bool
+ef4_farch_handle_rx_bad_index(struct ef4_rx_queue *rx_queue, unsigned index)
+{
+ struct ef4_channel *channel = ef4_rx_queue_channel(rx_queue);
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned expected, dropped;
+
+ if (rx_queue->scatter_n &&
+ index == ((rx_queue->removed_count + rx_queue->scatter_n - 1) &
+ rx_queue->ptr_mask)) {
+ ++channel->n_rx_nodesc_trunc;
+ return true;
+ }
+
+ expected = rx_queue->removed_count & rx_queue->ptr_mask;
+ dropped = (index - expected) & rx_queue->ptr_mask;
+ netif_info(efx, rx_err, efx->net_dev,
+ "dropped %d events (index=%d expected=%d)\n",
+ dropped, index, expected);
+
+ ef4_schedule_reset(efx, EF4_WORKAROUND_5676(efx) ?
+ RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+ return false;
+}
+
+/* Handle a packet received event
+ *
+ * The NIC gives a "discard" flag if it's a unicast packet with the
+ * wrong destination address
+ * Also "is multicast" and "matches multicast filter" flags can be used to
+ * discard non-matching multicast packets.
+ */
+static void
+ef4_farch_handle_rx_event(struct ef4_channel *channel, const ef4_qword_t *event)
+{
+ unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
+ unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
+ unsigned expected_ptr;
+ bool rx_ev_pkt_ok, rx_ev_sop, rx_ev_cont;
+ u16 flags;
+ struct ef4_rx_queue *rx_queue;
+ struct ef4_nic *efx = channel->efx;
+
+ if (unlikely(ACCESS_ONCE(efx->reset_pending)))
+ return;
+
+ rx_ev_cont = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_JUMBO_CONT);
+ rx_ev_sop = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_SOP);
+ WARN_ON(EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
+ channel->channel);
+
+ rx_queue = ef4_channel_get_rx_queue(channel);
+
+ rx_ev_desc_ptr = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
+ expected_ptr = ((rx_queue->removed_count + rx_queue->scatter_n) &
+ rx_queue->ptr_mask);
+
+ /* Check for partial drops and other errors */
+ if (unlikely(rx_ev_desc_ptr != expected_ptr) ||
+ unlikely(rx_ev_sop != (rx_queue->scatter_n == 0))) {
+ if (rx_ev_desc_ptr != expected_ptr &&
+ !ef4_farch_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr))
+ return;
+
+ /* Discard all pending fragments */
+ if (rx_queue->scatter_n) {
+ ef4_rx_packet(
+ rx_queue,
+ rx_queue->removed_count & rx_queue->ptr_mask,
+ rx_queue->scatter_n, 0, EF4_RX_PKT_DISCARD);
+ rx_queue->removed_count += rx_queue->scatter_n;
+ rx_queue->scatter_n = 0;
+ }
+
+ /* Return if there is no new fragment */
+ if (rx_ev_desc_ptr != expected_ptr)
+ return;
+
+ /* Discard new fragment if not SOP */
+ if (!rx_ev_sop) {
+ ef4_rx_packet(
+ rx_queue,
+ rx_queue->removed_count & rx_queue->ptr_mask,
+ 1, 0, EF4_RX_PKT_DISCARD);
+ ++rx_queue->removed_count;
+ return;
+ }
+ }
+
+ ++rx_queue->scatter_n;
+ if (rx_ev_cont)
+ return;
+
+ rx_ev_byte_cnt = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT);
+ rx_ev_pkt_ok = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_OK);
+ rx_ev_hdr_type = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
+
+ if (likely(rx_ev_pkt_ok)) {
+ /* If packet is marked as OK then we can rely on the
+ * hardware checksum and classification.
+ */
+ flags = 0;
+ switch (rx_ev_hdr_type) {
+ case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP:
+ flags |= EF4_RX_PKT_TCP;
+ /* fall through */
+ case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
+ flags |= EF4_RX_PKT_CSUMMED;
+ /* fall through */
+ case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
+ case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
+ break;
+ }
+ } else {
+ flags = ef4_farch_handle_rx_not_ok(rx_queue, event);
+ }
+
+ /* Detect multicast packets that didn't match the filter */
+ rx_ev_mcast_pkt = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_PKT);
+ if (rx_ev_mcast_pkt) {
+ unsigned int rx_ev_mcast_hash_match =
+ EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_HASH_MATCH);
+
+ if (unlikely(!rx_ev_mcast_hash_match)) {
+ ++channel->n_rx_mcast_mismatch;
+ flags |= EF4_RX_PKT_DISCARD;
+ }
+ }
+
+ channel->irq_mod_score += 2;
+
+ /* Handle received packet */
+ ef4_rx_packet(rx_queue,
+ rx_queue->removed_count & rx_queue->ptr_mask,
+ rx_queue->scatter_n, rx_ev_byte_cnt, flags);
+ rx_queue->removed_count += rx_queue->scatter_n;
+ rx_queue->scatter_n = 0;
+}
+
+/* If this flush done event corresponds to a &struct ef4_tx_queue, then
+ * send an %EF4_CHANNEL_MAGIC_TX_DRAIN event to drain the event queue
+ * of all transmit completions.
+ */
+static void
+ef4_farch_handle_tx_flush_done(struct ef4_nic *efx, ef4_qword_t *event)
+{
+ struct ef4_tx_queue *tx_queue;
+ int qid;
+
+ qid = EF4_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
+ if (qid < EF4_TXQ_TYPES * efx->n_tx_channels) {
+ tx_queue = ef4_get_tx_queue(efx, qid / EF4_TXQ_TYPES,
+ qid % EF4_TXQ_TYPES);
+ if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
+ ef4_farch_magic_event(tx_queue->channel,
+ EF4_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
+ }
+ }
+}
+
+/* If this flush done event corresponds to a &struct ef4_rx_queue: If the flush
+ * was successful then send an %EF4_CHANNEL_MAGIC_RX_DRAIN, otherwise add
+ * the RX queue back to the mask of RX queues in need of flushing.
+ */
+static void
+ef4_farch_handle_rx_flush_done(struct ef4_nic *efx, ef4_qword_t *event)
+{
+ struct ef4_channel *channel;
+ struct ef4_rx_queue *rx_queue;
+ int qid;
+ bool failed;
+
+ qid = EF4_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
+ failed = EF4_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
+ if (qid >= efx->n_channels)
+ return;
+ channel = ef4_get_channel(efx, qid);
+ if (!ef4_channel_has_rx_queue(channel))
+ return;
+ rx_queue = ef4_channel_get_rx_queue(channel);
+
+ if (failed) {
+ netif_info(efx, hw, efx->net_dev,
+ "RXQ %d flush retry\n", qid);
+ rx_queue->flush_pending = true;
+ atomic_inc(&efx->rxq_flush_pending);
+ } else {
+ ef4_farch_magic_event(ef4_rx_queue_channel(rx_queue),
+ EF4_CHANNEL_MAGIC_RX_DRAIN(rx_queue));
+ }
+ atomic_dec(&efx->rxq_flush_outstanding);
+ if (ef4_farch_flush_wake(efx))
+ wake_up(&efx->flush_wq);
+}
+
+static void
+ef4_farch_handle_drain_event(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+
+ WARN_ON(atomic_read(&efx->active_queues) == 0);
+ atomic_dec(&efx->active_queues);
+ if (ef4_farch_flush_wake(efx))
+ wake_up(&efx->flush_wq);
+}
+
+static void ef4_farch_handle_generated_event(struct ef4_channel *channel,
+ ef4_qword_t *event)
+{
+ struct ef4_nic *efx = channel->efx;
+ struct ef4_rx_queue *rx_queue =
+ ef4_channel_has_rx_queue(channel) ?
+ ef4_channel_get_rx_queue(channel) : NULL;
+ unsigned magic, code;
+
+ magic = EF4_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
+ code = _EF4_CHANNEL_MAGIC_CODE(magic);
+
+ if (magic == EF4_CHANNEL_MAGIC_TEST(channel)) {
+ channel->event_test_cpu = raw_smp_processor_id();
+ } else if (rx_queue && magic == EF4_CHANNEL_MAGIC_FILL(rx_queue)) {
+ /* The queue must be empty, so we won't receive any rx
+ * events, so ef4_process_channel() won't refill the
+ * queue. Refill it here */
+ ef4_fast_push_rx_descriptors(rx_queue, true);
+ } else if (rx_queue && magic == EF4_CHANNEL_MAGIC_RX_DRAIN(rx_queue)) {
+ ef4_farch_handle_drain_event(channel);
+ } else if (code == _EF4_CHANNEL_MAGIC_TX_DRAIN) {
+ ef4_farch_handle_drain_event(channel);
+ } else {
+ netif_dbg(efx, hw, efx->net_dev, "channel %d received "
+ "generated event "EF4_QWORD_FMT"\n",
+ channel->channel, EF4_QWORD_VAL(*event));
+ }
+}
+
+static void
+ef4_farch_handle_driver_event(struct ef4_channel *channel, ef4_qword_t *event)
+{
+ struct ef4_nic *efx = channel->efx;
+ unsigned int ev_sub_code;
+ unsigned int ev_sub_data;
+
+ ev_sub_code = EF4_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBCODE);
+ ev_sub_data = EF4_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
+
+ switch (ev_sub_code) {
+ case FSE_AZ_TX_DESCQ_FLS_DONE_EV:
+ netif_vdbg(efx, hw, efx->net_dev, "channel %d TXQ %d flushed\n",
+ channel->channel, ev_sub_data);
+ ef4_farch_handle_tx_flush_done(efx, event);
+ break;
+ case FSE_AZ_RX_DESCQ_FLS_DONE_EV:
+ netif_vdbg(efx, hw, efx->net_dev, "channel %d RXQ %d flushed\n",
+ channel->channel, ev_sub_data);
+ ef4_farch_handle_rx_flush_done(efx, event);
+ break;
+ case FSE_AZ_EVQ_INIT_DONE_EV:
+ netif_dbg(efx, hw, efx->net_dev,
+ "channel %d EVQ %d initialised\n",
+ channel->channel, ev_sub_data);
+ break;
+ case FSE_AZ_SRM_UPD_DONE_EV:
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d SRAM update done\n", channel->channel);
+ break;
+ case FSE_AZ_WAKE_UP_EV:
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d RXQ %d wakeup event\n",
+ channel->channel, ev_sub_data);
+ break;
+ case FSE_AZ_TIMER_EV:
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d RX queue %d timer expired\n",
+ channel->channel, ev_sub_data);
+ break;
+ case FSE_AA_RX_RECOVER_EV:
+ netif_err(efx, rx_err, efx->net_dev,
+ "channel %d seen DRIVER RX_RESET event. "
+ "Resetting.\n", channel->channel);
+ atomic_inc(&efx->rx_reset);
+ ef4_schedule_reset(efx,
+ EF4_WORKAROUND_6555(efx) ?
+ RESET_TYPE_RX_RECOVERY :
+ RESET_TYPE_DISABLE);
+ break;
+ case FSE_BZ_RX_DSC_ERROR_EV:
+ netif_err(efx, rx_err, efx->net_dev,
+ "RX DMA Q %d reports descriptor fetch error."
+ " RX Q %d is disabled.\n", ev_sub_data,
+ ev_sub_data);
+ ef4_schedule_reset(efx, RESET_TYPE_DMA_ERROR);
+ break;
+ case FSE_BZ_TX_DSC_ERROR_EV:
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX DMA Q %d reports descriptor fetch error."
+ " TX Q %d is disabled.\n", ev_sub_data,
+ ev_sub_data);
+ ef4_schedule_reset(efx, RESET_TYPE_DMA_ERROR);
+ break;
+ default:
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d unknown driver event code %d "
+ "data %04x\n", channel->channel, ev_sub_code,
+ ev_sub_data);
+ break;
+ }
+}
+
+int ef4_farch_ev_process(struct ef4_channel *channel, int budget)
+{
+ struct ef4_nic *efx = channel->efx;
+ unsigned int read_ptr;
+ ef4_qword_t event, *p_event;
+ int ev_code;
+ int tx_packets = 0;
+ int spent = 0;
+
+ if (budget <= 0)
+ return spent;
+
+ read_ptr = channel->eventq_read_ptr;
+
+ for (;;) {
+ p_event = ef4_event(channel, read_ptr);
+ event = *p_event;
+
+ if (!ef4_event_present(&event))
+ /* End of events */
+ break;
+
+ netif_vdbg(channel->efx, intr, channel->efx->net_dev,
+ "channel %d event is "EF4_QWORD_FMT"\n",
+ channel->channel, EF4_QWORD_VAL(event));
+
+ /* Clear this event by marking it all ones */
+ EF4_SET_QWORD(*p_event);
+
+ ++read_ptr;
+
+ ev_code = EF4_QWORD_FIELD(event, FSF_AZ_EV_CODE);
+
+ switch (ev_code) {
+ case FSE_AZ_EV_CODE_RX_EV:
+ ef4_farch_handle_rx_event(channel, &event);
+ if (++spent == budget)
+ goto out;
+ break;
+ case FSE_AZ_EV_CODE_TX_EV:
+ tx_packets += ef4_farch_handle_tx_event(channel,
+ &event);
+ if (tx_packets > efx->txq_entries) {
+ spent = budget;
+ goto out;
+ }
+ break;
+ case FSE_AZ_EV_CODE_DRV_GEN_EV:
+ ef4_farch_handle_generated_event(channel, &event);
+ break;
+ case FSE_AZ_EV_CODE_DRIVER_EV:
+ ef4_farch_handle_driver_event(channel, &event);
+ break;
+ case FSE_AZ_EV_CODE_GLOBAL_EV:
+ if (efx->type->handle_global_event &&
+ efx->type->handle_global_event(channel, &event))
+ break;
+ /* else fall through */
+ default:
+ netif_err(channel->efx, hw, channel->efx->net_dev,
+ "channel %d unknown event type %d (data "
+ EF4_QWORD_FMT ")\n", channel->channel,
+ ev_code, EF4_QWORD_VAL(event));
+ }
+ }
+
+out:
+ channel->eventq_read_ptr = read_ptr;
+ return spent;
+}
+
+/* Allocate buffer table entries for event queue */
+int ef4_farch_ev_probe(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+ unsigned entries;
+
+ entries = channel->eventq_mask + 1;
+ return ef4_alloc_special_buffer(efx, &channel->eventq,
+ entries * sizeof(ef4_qword_t));
+}
+
+int ef4_farch_ev_init(struct ef4_channel *channel)
+{
+ ef4_oword_t reg;
+ struct ef4_nic *efx = channel->efx;
+
+ netif_dbg(efx, hw, efx->net_dev,
+ "channel %d event queue in special buffers %d-%d\n",
+ channel->channel, channel->eventq.index,
+ channel->eventq.index + channel->eventq.entries - 1);
+
+ /* Pin event queue buffer */
+ ef4_init_special_buffer(efx, &channel->eventq);
+
+ /* Fill event queue with all ones (i.e. empty events) */
+ memset(channel->eventq.buf.addr, 0xff, channel->eventq.buf.len);
+
+ /* Push event queue to card */
+ EF4_POPULATE_OWORD_3(reg,
+ FRF_AZ_EVQ_EN, 1,
+ FRF_AZ_EVQ_SIZE, __ffs(channel->eventq.entries),
+ FRF_AZ_EVQ_BUF_BASE_ID, channel->eventq.index);
+ ef4_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
+ channel->channel);
+
+ return 0;
+}
+
+void ef4_farch_ev_fini(struct ef4_channel *channel)
+{
+ ef4_oword_t reg;
+ struct ef4_nic *efx = channel->efx;
+
+ /* Remove event queue from card */
+ EF4_ZERO_OWORD(reg);
+ ef4_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
+ channel->channel);
+
+ /* Unpin event queue */
+ ef4_fini_special_buffer(efx, &channel->eventq);
+}
+
+/* Free buffers backing event queue */
+void ef4_farch_ev_remove(struct ef4_channel *channel)
+{
+ ef4_free_special_buffer(channel->efx, &channel->eventq);
+}
+
+
+void ef4_farch_ev_test_generate(struct ef4_channel *channel)
+{
+ ef4_farch_magic_event(channel, EF4_CHANNEL_MAGIC_TEST(channel));
+}
+
+void ef4_farch_rx_defer_refill(struct ef4_rx_queue *rx_queue)
+{
+ ef4_farch_magic_event(ef4_rx_queue_channel(rx_queue),
+ EF4_CHANNEL_MAGIC_FILL(rx_queue));
+}
+
+/**************************************************************************
+ *
+ * Hardware interrupts
+ * The hardware interrupt handler does very little work; all the event
+ * queue processing is carried out by per-channel tasklets.
+ *
+ **************************************************************************/
+
+/* Enable/disable/generate interrupts */
+static inline void ef4_farch_interrupts(struct ef4_nic *efx,
+ bool enabled, bool force)
+{
+ ef4_oword_t int_en_reg_ker;
+
+ EF4_POPULATE_OWORD_3(int_en_reg_ker,
+ FRF_AZ_KER_INT_LEVE_SEL, efx->irq_level,
+ FRF_AZ_KER_INT_KER, force,
+ FRF_AZ_DRV_INT_EN_KER, enabled);
+ ef4_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
+}
+
+void ef4_farch_irq_enable_master(struct ef4_nic *efx)
+{
+ EF4_ZERO_OWORD(*((ef4_oword_t *) efx->irq_status.addr));
+ wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
+
+ ef4_farch_interrupts(efx, true, false);
+}
+
+void ef4_farch_irq_disable_master(struct ef4_nic *efx)
+{
+ /* Disable interrupts */
+ ef4_farch_interrupts(efx, false, false);
+}
+
+/* Generate a test interrupt
+ * Interrupt must already have been enabled, otherwise nasty things
+ * may happen.
+ */
+int ef4_farch_irq_test_generate(struct ef4_nic *efx)
+{
+ ef4_farch_interrupts(efx, true, true);
+ return 0;
+}
+
+/* Process a fatal interrupt
+ * Disable bus mastering ASAP and schedule a reset
+ */
+irqreturn_t ef4_farch_fatal_interrupt(struct ef4_nic *efx)
+{
+ struct falcon_nic_data *nic_data = efx->nic_data;
+ ef4_oword_t *int_ker = efx->irq_status.addr;
+ ef4_oword_t fatal_intr;
+ int error, mem_perr;
+
+ ef4_reado(efx, &fatal_intr, FR_AZ_FATAL_INTR_KER);
+ error = EF4_OWORD_FIELD(fatal_intr, FRF_AZ_FATAL_INTR);
+
+ netif_err(efx, hw, efx->net_dev, "SYSTEM ERROR "EF4_OWORD_FMT" status "
+ EF4_OWORD_FMT ": %s\n", EF4_OWORD_VAL(*int_ker),
+ EF4_OWORD_VAL(fatal_intr),
+ error ? "disabling bus mastering" : "no recognised error");
+
+ /* If this is a memory parity error dump which blocks are offending */
+ mem_perr = (EF4_OWORD_FIELD(fatal_intr, FRF_AZ_MEM_PERR_INT_KER) ||
+ EF4_OWORD_FIELD(fatal_intr, FRF_AZ_SRM_PERR_INT_KER));
+ if (mem_perr) {
+ ef4_oword_t reg;
+ ef4_reado(efx, &reg, FR_AZ_MEM_STAT);
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR: memory parity error "EF4_OWORD_FMT"\n",
+ EF4_OWORD_VAL(reg));
+ }
+
+ /* Disable both devices */
+ pci_clear_master(efx->pci_dev);
+ if (ef4_nic_is_dual_func(efx))
+ pci_clear_master(nic_data->pci_dev2);
+ ef4_farch_irq_disable_master(efx);
+
+ /* Count errors and reset or disable the NIC accordingly */
+ if (efx->int_error_count == 0 ||
+ time_after(jiffies, efx->int_error_expire)) {
+ efx->int_error_count = 0;
+ efx->int_error_expire =
+ jiffies + EF4_INT_ERROR_EXPIRE * HZ;
+ }
+ if (++efx->int_error_count < EF4_MAX_INT_ERRORS) {
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR - reset scheduled\n");
+ ef4_schedule_reset(efx, RESET_TYPE_INT_ERROR);
+ } else {
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR - max number of errors seen."
+ "NIC will be disabled\n");
+ ef4_schedule_reset(efx, RESET_TYPE_DISABLE);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Handle a legacy interrupt
+ * Acknowledges the interrupt and schedule event queue processing.
+ */
+irqreturn_t ef4_farch_legacy_interrupt(int irq, void *dev_id)
+{
+ struct ef4_nic *efx = dev_id;
+ bool soft_enabled = ACCESS_ONCE(efx->irq_soft_enabled);
+ ef4_oword_t *int_ker = efx->irq_status.addr;
+ irqreturn_t result = IRQ_NONE;
+ struct ef4_channel *channel;
+ ef4_dword_t reg;
+ u32 queues;
+ int syserr;
+
+ /* Read the ISR which also ACKs the interrupts */
+ ef4_readd(efx, &reg, FR_BZ_INT_ISR0);
+ queues = EF4_EXTRACT_DWORD(reg, 0, 31);
+
+ /* Legacy interrupts are disabled too late by the EEH kernel
+ * code. Disable them earlier.
+ * If an EEH error occurred, the read will have returned all ones.
+ */
+ if (EF4_DWORD_IS_ALL_ONES(reg) && ef4_try_recovery(efx) &&
+ !efx->eeh_disabled_legacy_irq) {
+ disable_irq_nosync(efx->legacy_irq);
+ efx->eeh_disabled_legacy_irq = true;
+ }
+
+ /* Handle non-event-queue sources */
+ if (queues & (1U << efx->irq_level) && soft_enabled) {
+ syserr = EF4_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
+ if (unlikely(syserr))
+ return ef4_farch_fatal_interrupt(efx);
+ efx->last_irq_cpu = raw_smp_processor_id();
+ }
+
+ if (queues != 0) {
+ efx->irq_zero_count = 0;
+
+ /* Schedule processing of any interrupting queues */
+ if (likely(soft_enabled)) {
+ ef4_for_each_channel(channel, efx) {
+ if (queues & 1)
+ ef4_schedule_channel_irq(channel);
+ queues >>= 1;
+ }
+ }
+ result = IRQ_HANDLED;
+
+ } else {
+ ef4_qword_t *event;
+
+ /* Legacy ISR read can return zero once (SF bug 15783) */
+
+ /* We can't return IRQ_HANDLED more than once on seeing ISR=0
+ * because this might be a shared interrupt. */
+ if (efx->irq_zero_count++ == 0)
+ result = IRQ_HANDLED;
+
+ /* Ensure we schedule or rearm all event queues */
+ if (likely(soft_enabled)) {
+ ef4_for_each_channel(channel, efx) {
+ event = ef4_event(channel,
+ channel->eventq_read_ptr);
+ if (ef4_event_present(event))
+ ef4_schedule_channel_irq(channel);
+ else
+ ef4_farch_ev_read_ack(channel);
+ }
+ }
+ }
+
+ if (result == IRQ_HANDLED)
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d status " EF4_DWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EF4_DWORD_VAL(reg));
+
+ return result;
+}
+
+/* Handle an MSI interrupt
+ *
+ * Handle an MSI hardware interrupt. This routine schedules event
+ * queue processing. No interrupt acknowledgement cycle is necessary.
+ * Also, we never need to check that the interrupt is for us, since
+ * MSI interrupts cannot be shared.
+ */
+irqreturn_t ef4_farch_msi_interrupt(int irq, void *dev_id)
+{
+ struct ef4_msi_context *context = dev_id;
+ struct ef4_nic *efx = context->efx;
+ ef4_oword_t *int_ker = efx->irq_status.addr;
+ int syserr;
+
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d status " EF4_OWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EF4_OWORD_VAL(*int_ker));
+
+ if (!likely(ACCESS_ONCE(efx->irq_soft_enabled)))
+ return IRQ_HANDLED;
+
+ /* Handle non-event-queue sources */
+ if (context->index == efx->irq_level) {
+ syserr = EF4_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
+ if (unlikely(syserr))
+ return ef4_farch_fatal_interrupt(efx);
+ efx->last_irq_cpu = raw_smp_processor_id();
+ }
+
+ /* Schedule processing of the channel */
+ ef4_schedule_channel_irq(efx->channel[context->index]);
+
+ return IRQ_HANDLED;
+}
+
+/* Setup RSS indirection table.
+ * This maps from the hash value of the packet to RXQ
+ */
+void ef4_farch_rx_push_indir_table(struct ef4_nic *efx)
+{
+ size_t i = 0;
+ ef4_dword_t dword;
+
+ BUG_ON(ef4_nic_rev(efx) < EF4_REV_FALCON_B0);
+
+ BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
+ FR_BZ_RX_INDIRECTION_TBL_ROWS);
+
+ for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
+ EF4_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
+ efx->rx_indir_table[i]);
+ ef4_writed(efx, &dword,
+ FR_BZ_RX_INDIRECTION_TBL +
+ FR_BZ_RX_INDIRECTION_TBL_STEP * i);
+ }
+}
+
+/* Looks at available SRAM resources and works out how many queues we
+ * can support, and where things like descriptor caches should live.
+ *
+ * SRAM is split up as follows:
+ * 0 buftbl entries for channels
+ * efx->vf_buftbl_base buftbl entries for SR-IOV
+ * efx->rx_dc_base RX descriptor caches
+ * efx->tx_dc_base TX descriptor caches
+ */
+void ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw)
+{
+ unsigned vi_count, buftbl_min;
+
+ /* Account for the buffer table entries backing the datapath channels
+ * and the descriptor caches for those channels.
+ */
+ buftbl_min = ((efx->n_rx_channels * EF4_MAX_DMAQ_SIZE +
+ efx->n_tx_channels * EF4_TXQ_TYPES * EF4_MAX_DMAQ_SIZE +
+ efx->n_channels * EF4_MAX_EVQ_SIZE)
+ * sizeof(ef4_qword_t) / EF4_BUF_SIZE);
+ vi_count = max(efx->n_channels, efx->n_tx_channels * EF4_TXQ_TYPES);
+
+ efx->tx_dc_base = sram_lim_qw - vi_count * TX_DC_ENTRIES;
+ efx->rx_dc_base = efx->tx_dc_base - vi_count * RX_DC_ENTRIES;
+}
+
+u32 ef4_farch_fpga_ver(struct ef4_nic *efx)
+{
+ ef4_oword_t altera_build;
+ ef4_reado(efx, &altera_build, FR_AZ_ALTERA_BUILD);
+ return EF4_OWORD_FIELD(altera_build, FRF_AZ_ALTERA_BUILD_VER);
+}
+
+void ef4_farch_init_common(struct ef4_nic *efx)
+{
+ ef4_oword_t temp;
+
+ /* Set positions of descriptor caches in SRAM. */
+ EF4_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR, efx->tx_dc_base);
+ ef4_writeo(efx, &temp, FR_AZ_SRM_TX_DC_CFG);
+ EF4_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR, efx->rx_dc_base);
+ ef4_writeo(efx, &temp, FR_AZ_SRM_RX_DC_CFG);
+
+ /* Set TX descriptor cache size. */
+ BUILD_BUG_ON(TX_DC_ENTRIES != (8 << TX_DC_ENTRIES_ORDER));
+ EF4_POPULATE_OWORD_1(temp, FRF_AZ_TX_DC_SIZE, TX_DC_ENTRIES_ORDER);
+ ef4_writeo(efx, &temp, FR_AZ_TX_DC_CFG);
+
+ /* Set RX descriptor cache size. Set low watermark to size-8, as
+ * this allows most efficient prefetching.
+ */
+ BUILD_BUG_ON(RX_DC_ENTRIES != (8 << RX_DC_ENTRIES_ORDER));
+ EF4_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_SIZE, RX_DC_ENTRIES_ORDER);
+ ef4_writeo(efx, &temp, FR_AZ_RX_DC_CFG);
+ EF4_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_PF_LWM, RX_DC_ENTRIES - 8);
+ ef4_writeo(efx, &temp, FR_AZ_RX_DC_PF_WM);
+
+ /* Program INT_KER address */
+ EF4_POPULATE_OWORD_2(temp,
+ FRF_AZ_NORM_INT_VEC_DIS_KER,
+ EF4_INT_MODE_USE_MSI(efx),
+ FRF_AZ_INT_ADR_KER, efx->irq_status.dma_addr);
+ ef4_writeo(efx, &temp, FR_AZ_INT_ADR_KER);
+
+ /* Use a valid MSI-X vector */
+ efx->irq_level = 0;
+
+ /* Enable all the genuinely fatal interrupts. (They are still
+ * masked by the overall interrupt mask, controlled by
+ * falcon_interrupts()).
+ *
+ * Note: All other fatal interrupts are enabled
+ */
+ EF4_POPULATE_OWORD_3(temp,
+ FRF_AZ_ILL_ADR_INT_KER_EN, 1,
+ FRF_AZ_RBUF_OWN_INT_KER_EN, 1,
+ FRF_AZ_TBUF_OWN_INT_KER_EN, 1);
+ EF4_INVERT_OWORD(temp);
+ ef4_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
+
+ /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
+ * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
+ */
+ ef4_reado(efx, &temp, FR_AZ_TX_RESERVED);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER, 0xfe);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER_EN, 1);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_PUSH_EN, 1);
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_DIS_NON_IP_EV, 1);
+ /* Enable SW_EV to inherit in char driver - assume harmless here */
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1);
+ /* Prefetch threshold 2 => fetch when descriptor cache half empty */
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2);
+ /* Disable hardware watchdog which can misfire */
+ EF4_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
+ /* Squash TX of packets of 16 bytes or less */
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0)
+ EF4_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
+ ef4_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ EF4_POPULATE_OWORD_4(temp,
+ /* Default values */
+ FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
+ FRF_BZ_TX_PACE_SB_AF, 0xb,
+ FRF_BZ_TX_PACE_FB_BASE, 0,
+ /* Allow large pace values in the
+ * fast bin. */
+ FRF_BZ_TX_PACE_BIN_TH,
+ FFE_BZ_TX_PACE_RESERVED);
+ ef4_writeo(efx, &temp, FR_BZ_TX_PACE);
+ }
+}
+
+/**************************************************************************
+ *
+ * Filter tables
+ *
+ **************************************************************************
+ */
+
+/* "Fudge factors" - difference between programmed value and actual depth.
+ * Due to pipelined implementation we need to program H/W with a value that
+ * is larger than the hop limit we want.
+ */
+#define EF4_FARCH_FILTER_CTL_SRCH_FUDGE_WILD 3
+#define EF4_FARCH_FILTER_CTL_SRCH_FUDGE_FULL 1
+
+/* Hard maximum search limit. Hardware will time-out beyond 200-something.
+ * We also need to avoid infinite loops in ef4_farch_filter_search() when the
+ * table is full.
+ */
+#define EF4_FARCH_FILTER_CTL_SRCH_MAX 200
+
+/* Don't try very hard to find space for performance hints, as this is
+ * counter-productive. */
+#define EF4_FARCH_FILTER_CTL_SRCH_HINT_MAX 5
+
+enum ef4_farch_filter_type {
+ EF4_FARCH_FILTER_TCP_FULL = 0,
+ EF4_FARCH_FILTER_TCP_WILD,
+ EF4_FARCH_FILTER_UDP_FULL,
+ EF4_FARCH_FILTER_UDP_WILD,
+ EF4_FARCH_FILTER_MAC_FULL = 4,
+ EF4_FARCH_FILTER_MAC_WILD,
+ EF4_FARCH_FILTER_UC_DEF = 8,
+ EF4_FARCH_FILTER_MC_DEF,
+ EF4_FARCH_FILTER_TYPE_COUNT, /* number of specific types */
+};
+
+enum ef4_farch_filter_table_id {
+ EF4_FARCH_FILTER_TABLE_RX_IP = 0,
+ EF4_FARCH_FILTER_TABLE_RX_MAC,
+ EF4_FARCH_FILTER_TABLE_RX_DEF,
+ EF4_FARCH_FILTER_TABLE_TX_MAC,
+ EF4_FARCH_FILTER_TABLE_COUNT,
+};
+
+enum ef4_farch_filter_index {
+ EF4_FARCH_FILTER_INDEX_UC_DEF,
+ EF4_FARCH_FILTER_INDEX_MC_DEF,
+ EF4_FARCH_FILTER_SIZE_RX_DEF,
+};
+
+struct ef4_farch_filter_spec {
+ u8 type:4;
+ u8 priority:4;
+ u8 flags;
+ u16 dmaq_id;
+ u32 data[3];
+};
+
+struct ef4_farch_filter_table {
+ enum ef4_farch_filter_table_id id;
+ u32 offset; /* address of table relative to BAR */
+ unsigned size; /* number of entries */
+ unsigned step; /* step between entries */
+ unsigned used; /* number currently used */
+ unsigned long *used_bitmap;
+ struct ef4_farch_filter_spec *spec;
+ unsigned search_limit[EF4_FARCH_FILTER_TYPE_COUNT];
+};
+
+struct ef4_farch_filter_state {
+ struct ef4_farch_filter_table table[EF4_FARCH_FILTER_TABLE_COUNT];
+};
+
+static void
+ef4_farch_filter_table_clear_entry(struct ef4_nic *efx,
+ struct ef4_farch_filter_table *table,
+ unsigned int filter_idx);
+
+/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
+ * key derived from the n-tuple. The initial LFSR state is 0xffff. */
+static u16 ef4_farch_filter_hash(u32 key)
+{
+ u16 tmp;
+
+ /* First 16 rounds */
+ tmp = 0x1fff ^ key >> 16;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ tmp = tmp ^ tmp >> 9;
+ /* Last 16 rounds */
+ tmp = tmp ^ tmp << 13 ^ key;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ return tmp ^ tmp >> 9;
+}
+
+/* To allow for hash collisions, filter search continues at these
+ * increments from the first possible entry selected by the hash. */
+static u16 ef4_farch_filter_increment(u32 key)
+{
+ return key * 2 - 1;
+}
+
+static enum ef4_farch_filter_table_id
+ef4_farch_filter_spec_table_id(const struct ef4_farch_filter_spec *spec)
+{
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_IP !=
+ (EF4_FARCH_FILTER_TCP_FULL >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_IP !=
+ (EF4_FARCH_FILTER_TCP_WILD >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_IP !=
+ (EF4_FARCH_FILTER_UDP_FULL >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_IP !=
+ (EF4_FARCH_FILTER_UDP_WILD >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_MAC !=
+ (EF4_FARCH_FILTER_MAC_FULL >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_RX_MAC !=
+ (EF4_FARCH_FILTER_MAC_WILD >> 2));
+ BUILD_BUG_ON(EF4_FARCH_FILTER_TABLE_TX_MAC !=
+ EF4_FARCH_FILTER_TABLE_RX_MAC + 2);
+ return (spec->type >> 2) + ((spec->flags & EF4_FILTER_FLAG_TX) ? 2 : 0);
+}
+
+static void ef4_farch_filter_push_rx_config(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ struct ef4_farch_filter_table *table;
+ ef4_oword_t filter_ctl;
+
+ ef4_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+
+ table = &state->table[EF4_FARCH_FILTER_TABLE_RX_IP];
+ EF4_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_TCP_FULL] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
+ EF4_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_TCP_WILD] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
+ EF4_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_UDP_FULL] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
+ EF4_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_UDP_WILD] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
+
+ table = &state->table[EF4_FARCH_FILTER_TABLE_RX_MAC];
+ if (table->size) {
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_MAC_FULL] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
+ table->search_limit[EF4_FARCH_FILTER_MAC_WILD] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ table = &state->table[EF4_FARCH_FILTER_TABLE_RX_DEF];
+ if (table->size) {
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_UNICAST_NOMATCH_Q_ID,
+ table->spec[EF4_FARCH_FILTER_INDEX_UC_DEF].dmaq_id);
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED,
+ !!(table->spec[EF4_FARCH_FILTER_INDEX_UC_DEF].flags &
+ EF4_FILTER_FLAG_RX_RSS));
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_MULTICAST_NOMATCH_Q_ID,
+ table->spec[EF4_FARCH_FILTER_INDEX_MC_DEF].dmaq_id);
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED,
+ !!(table->spec[EF4_FARCH_FILTER_INDEX_MC_DEF].flags &
+ EF4_FILTER_FLAG_RX_RSS));
+
+ /* There is a single bit to enable RX scatter for all
+ * unmatched packets. Only set it if scatter is
+ * enabled in both filter specs.
+ */
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q,
+ !!(table->spec[EF4_FARCH_FILTER_INDEX_UC_DEF].flags &
+ table->spec[EF4_FARCH_FILTER_INDEX_MC_DEF].flags &
+ EF4_FILTER_FLAG_RX_SCATTER));
+ } else if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ /* We don't expose 'default' filters because unmatched
+ * packets always go to the queue number found in the
+ * RSS table. But we still need to set the RX scatter
+ * bit here.
+ */
+ EF4_SET_OWORD_FIELD(
+ filter_ctl, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q,
+ efx->rx_scatter);
+ }
+
+ ef4_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+}
+
+static void ef4_farch_filter_push_tx_limits(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ struct ef4_farch_filter_table *table;
+ ef4_oword_t tx_cfg;
+
+ ef4_reado(efx, &tx_cfg, FR_AZ_TX_CFG);
+
+ table = &state->table[EF4_FARCH_FILTER_TABLE_TX_MAC];
+ if (table->size) {
+ EF4_SET_OWORD_FIELD(
+ tx_cfg, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
+ table->search_limit[EF4_FARCH_FILTER_MAC_FULL] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
+ EF4_SET_OWORD_FIELD(
+ tx_cfg, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
+ table->search_limit[EF4_FARCH_FILTER_MAC_WILD] +
+ EF4_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ ef4_writeo(efx, &tx_cfg, FR_AZ_TX_CFG);
+}
+
+static int
+ef4_farch_filter_from_gen_spec(struct ef4_farch_filter_spec *spec,
+ const struct ef4_filter_spec *gen_spec)
+{
+ bool is_full = false;
+
+ if ((gen_spec->flags & EF4_FILTER_FLAG_RX_RSS) &&
+ gen_spec->rss_context != EF4_FILTER_RSS_CONTEXT_DEFAULT)
+ return -EINVAL;
+
+ spec->priority = gen_spec->priority;
+ spec->flags = gen_spec->flags;
+ spec->dmaq_id = gen_spec->dmaq_id;
+
+ switch (gen_spec->match_flags) {
+ case (EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT |
+ EF4_FILTER_MATCH_REM_HOST | EF4_FILTER_MATCH_REM_PORT):
+ is_full = true;
+ /* fall through */
+ case (EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT): {
+ __be32 rhost, host1, host2;
+ __be16 rport, port1, port2;
+
+ EF4_BUG_ON_PARANOID(!(gen_spec->flags & EF4_FILTER_FLAG_RX));
+
+ if (gen_spec->ether_type != htons(ETH_P_IP))
+ return -EPROTONOSUPPORT;
+ if (gen_spec->loc_port == 0 ||
+ (is_full && gen_spec->rem_port == 0))
+ return -EADDRNOTAVAIL;
+ switch (gen_spec->ip_proto) {
+ case IPPROTO_TCP:
+ spec->type = (is_full ? EF4_FARCH_FILTER_TCP_FULL :
+ EF4_FARCH_FILTER_TCP_WILD);
+ break;
+ case IPPROTO_UDP:
+ spec->type = (is_full ? EF4_FARCH_FILTER_UDP_FULL :
+ EF4_FARCH_FILTER_UDP_WILD);
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+
+ /* Filter is constructed in terms of source and destination,
+ * with the odd wrinkle that the ports are swapped in a UDP
+ * wildcard filter. We need to convert from local and remote
+ * (= zero for wildcard) addresses.
+ */
+ rhost = is_full ? gen_spec->rem_host[0] : 0;
+ rport = is_full ? gen_spec->rem_port : 0;
+ host1 = rhost;
+ host2 = gen_spec->loc_host[0];
+ if (!is_full && gen_spec->ip_proto == IPPROTO_UDP) {
+ port1 = gen_spec->loc_port;
+ port2 = rport;
+ } else {
+ port1 = rport;
+ port2 = gen_spec->loc_port;
+ }
+ spec->data[0] = ntohl(host1) << 16 | ntohs(port1);
+ spec->data[1] = ntohs(port2) << 16 | ntohl(host1) >> 16;
+ spec->data[2] = ntohl(host2);
+
+ break;
+ }
+
+ case EF4_FILTER_MATCH_LOC_MAC | EF4_FILTER_MATCH_OUTER_VID:
+ is_full = true;
+ /* fall through */
+ case EF4_FILTER_MATCH_LOC_MAC:
+ spec->type = (is_full ? EF4_FARCH_FILTER_MAC_FULL :
+ EF4_FARCH_FILTER_MAC_WILD);
+ spec->data[0] = is_full ? ntohs(gen_spec->outer_vid) : 0;
+ spec->data[1] = (gen_spec->loc_mac[2] << 24 |
+ gen_spec->loc_mac[3] << 16 |
+ gen_spec->loc_mac[4] << 8 |
+ gen_spec->loc_mac[5]);
+ spec->data[2] = (gen_spec->loc_mac[0] << 8 |
+ gen_spec->loc_mac[1]);
+ break;
+
+ case EF4_FILTER_MATCH_LOC_MAC_IG:
+ spec->type = (is_multicast_ether_addr(gen_spec->loc_mac) ?
+ EF4_FARCH_FILTER_MC_DEF :
+ EF4_FARCH_FILTER_UC_DEF);
+ memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
+ break;
+
+ default:
+ return -EPROTONOSUPPORT;
+ }
+
+ return 0;
+}
+
+static void
+ef4_farch_filter_to_gen_spec(struct ef4_filter_spec *gen_spec,
+ const struct ef4_farch_filter_spec *spec)
+{
+ bool is_full = false;
+
+ /* *gen_spec should be completely initialised, to be consistent
+ * with ef4_filter_init_{rx,tx}() and in case we want to copy
+ * it back to userland.
+ */
+ memset(gen_spec, 0, sizeof(*gen_spec));
+
+ gen_spec->priority = spec->priority;
+ gen_spec->flags = spec->flags;
+ gen_spec->dmaq_id = spec->dmaq_id;
+
+ switch (spec->type) {
+ case EF4_FARCH_FILTER_TCP_FULL:
+ case EF4_FARCH_FILTER_UDP_FULL:
+ is_full = true;
+ /* fall through */
+ case EF4_FARCH_FILTER_TCP_WILD:
+ case EF4_FARCH_FILTER_UDP_WILD: {
+ __be32 host1, host2;
+ __be16 port1, port2;
+
+ gen_spec->match_flags =
+ EF4_FILTER_MATCH_ETHER_TYPE |
+ EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT;
+ if (is_full)
+ gen_spec->match_flags |= (EF4_FILTER_MATCH_REM_HOST |
+ EF4_FILTER_MATCH_REM_PORT);
+ gen_spec->ether_type = htons(ETH_P_IP);
+ gen_spec->ip_proto =
+ (spec->type == EF4_FARCH_FILTER_TCP_FULL ||
+ spec->type == EF4_FARCH_FILTER_TCP_WILD) ?
+ IPPROTO_TCP : IPPROTO_UDP;
+
+ host1 = htonl(spec->data[0] >> 16 | spec->data[1] << 16);
+ port1 = htons(spec->data[0]);
+ host2 = htonl(spec->data[2]);
+ port2 = htons(spec->data[1] >> 16);
+ if (spec->flags & EF4_FILTER_FLAG_TX) {
+ gen_spec->loc_host[0] = host1;
+ gen_spec->rem_host[0] = host2;
+ } else {
+ gen_spec->loc_host[0] = host2;
+ gen_spec->rem_host[0] = host1;
+ }
+ if (!!(gen_spec->flags & EF4_FILTER_FLAG_TX) ^
+ (!is_full && gen_spec->ip_proto == IPPROTO_UDP)) {
+ gen_spec->loc_port = port1;
+ gen_spec->rem_port = port2;
+ } else {
+ gen_spec->loc_port = port2;
+ gen_spec->rem_port = port1;
+ }
+
+ break;
+ }
+
+ case EF4_FARCH_FILTER_MAC_FULL:
+ is_full = true;
+ /* fall through */
+ case EF4_FARCH_FILTER_MAC_WILD:
+ gen_spec->match_flags = EF4_FILTER_MATCH_LOC_MAC;
+ if (is_full)
+ gen_spec->match_flags |= EF4_FILTER_MATCH_OUTER_VID;
+ gen_spec->loc_mac[0] = spec->data[2] >> 8;
+ gen_spec->loc_mac[1] = spec->data[2];
+ gen_spec->loc_mac[2] = spec->data[1] >> 24;
+ gen_spec->loc_mac[3] = spec->data[1] >> 16;
+ gen_spec->loc_mac[4] = spec->data[1] >> 8;
+ gen_spec->loc_mac[5] = spec->data[1];
+ gen_spec->outer_vid = htons(spec->data[0]);
+ break;
+
+ case EF4_FARCH_FILTER_UC_DEF:
+ case EF4_FARCH_FILTER_MC_DEF:
+ gen_spec->match_flags = EF4_FILTER_MATCH_LOC_MAC_IG;
+ gen_spec->loc_mac[0] = spec->type == EF4_FARCH_FILTER_MC_DEF;
+ break;
+
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+static void
+ef4_farch_filter_init_rx_auto(struct ef4_nic *efx,
+ struct ef4_farch_filter_spec *spec)
+{
+ /* If there's only one channel then disable RSS for non VF
+ * traffic, thereby allowing VFs to use RSS when the PF can't.
+ */
+ spec->priority = EF4_FILTER_PRI_AUTO;
+ spec->flags = (EF4_FILTER_FLAG_RX |
+ (ef4_rss_enabled(efx) ? EF4_FILTER_FLAG_RX_RSS : 0) |
+ (efx->rx_scatter ? EF4_FILTER_FLAG_RX_SCATTER : 0));
+ spec->dmaq_id = 0;
+}
+
+/* Build a filter entry and return its n-tuple key. */
+static u32 ef4_farch_filter_build(ef4_oword_t *filter,
+ struct ef4_farch_filter_spec *spec)
+{
+ u32 data3;
+
+ switch (ef4_farch_filter_spec_table_id(spec)) {
+ case EF4_FARCH_FILTER_TABLE_RX_IP: {
+ bool is_udp = (spec->type == EF4_FARCH_FILTER_UDP_FULL ||
+ spec->type == EF4_FARCH_FILTER_UDP_WILD);
+ EF4_POPULATE_OWORD_7(
+ *filter,
+ FRF_BZ_RSS_EN,
+ !!(spec->flags & EF4_FILTER_FLAG_RX_RSS),
+ FRF_BZ_SCATTER_EN,
+ !!(spec->flags & EF4_FILTER_FLAG_RX_SCATTER),
+ FRF_BZ_TCP_UDP, is_udp,
+ FRF_BZ_RXQ_ID, spec->dmaq_id,
+ EF4_DWORD_2, spec->data[2],
+ EF4_DWORD_1, spec->data[1],
+ EF4_DWORD_0, spec->data[0]);
+ data3 = is_udp;
+ break;
+ }
+
+ case EF4_FARCH_FILTER_TABLE_RX_MAC: {
+ bool is_wild = spec->type == EF4_FARCH_FILTER_MAC_WILD;
+ EF4_POPULATE_OWORD_7(
+ *filter,
+ FRF_CZ_RMFT_RSS_EN,
+ !!(spec->flags & EF4_FILTER_FLAG_RX_RSS),
+ FRF_CZ_RMFT_SCATTER_EN,
+ !!(spec->flags & EF4_FILTER_FLAG_RX_SCATTER),
+ FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
+ FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
+ FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
+ FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
+ FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
+ data3 = is_wild;
+ break;
+ }
+
+ case EF4_FARCH_FILTER_TABLE_TX_MAC: {
+ bool is_wild = spec->type == EF4_FARCH_FILTER_MAC_WILD;
+ EF4_POPULATE_OWORD_5(*filter,
+ FRF_CZ_TMFT_TXQ_ID, spec->dmaq_id,
+ FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
+ FRF_CZ_TMFT_SRC_MAC_HI, spec->data[2],
+ FRF_CZ_TMFT_SRC_MAC_LO, spec->data[1],
+ FRF_CZ_TMFT_VLAN_ID, spec->data[0]);
+ data3 = is_wild | spec->dmaq_id << 1;
+ break;
+ }
+
+ default:
+ BUG();
+ }
+
+ return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
+}
+
+static bool ef4_farch_filter_equal(const struct ef4_farch_filter_spec *left,
+ const struct ef4_farch_filter_spec *right)
+{
+ if (left->type != right->type ||
+ memcmp(left->data, right->data, sizeof(left->data)))
+ return false;
+
+ if (left->flags & EF4_FILTER_FLAG_TX &&
+ left->dmaq_id != right->dmaq_id)
+ return false;
+
+ return true;
+}
+
+/*
+ * Construct/deconstruct external filter IDs. At least the RX filter
+ * IDs must be ordered by matching priority, for RX NFC semantics.
+ *
+ * Deconstruction needs to be robust against invalid IDs so that
+ * ef4_filter_remove_id_safe() and ef4_filter_get_filter_safe() can
+ * accept user-provided IDs.
+ */
+
+#define EF4_FARCH_FILTER_MATCH_PRI_COUNT 5
+
+static const u8 ef4_farch_filter_type_match_pri[EF4_FARCH_FILTER_TYPE_COUNT] = {
+ [EF4_FARCH_FILTER_TCP_FULL] = 0,
+ [EF4_FARCH_FILTER_UDP_FULL] = 0,
+ [EF4_FARCH_FILTER_TCP_WILD] = 1,
+ [EF4_FARCH_FILTER_UDP_WILD] = 1,
+ [EF4_FARCH_FILTER_MAC_FULL] = 2,
+ [EF4_FARCH_FILTER_MAC_WILD] = 3,
+ [EF4_FARCH_FILTER_UC_DEF] = 4,
+ [EF4_FARCH_FILTER_MC_DEF] = 4,
+};
+
+static const enum ef4_farch_filter_table_id ef4_farch_filter_range_table[] = {
+ EF4_FARCH_FILTER_TABLE_RX_IP, /* RX match pri 0 */
+ EF4_FARCH_FILTER_TABLE_RX_IP,
+ EF4_FARCH_FILTER_TABLE_RX_MAC,
+ EF4_FARCH_FILTER_TABLE_RX_MAC,
+ EF4_FARCH_FILTER_TABLE_RX_DEF, /* RX match pri 4 */
+ EF4_FARCH_FILTER_TABLE_TX_MAC, /* TX match pri 0 */
+ EF4_FARCH_FILTER_TABLE_TX_MAC, /* TX match pri 1 */
+};
+
+#define EF4_FARCH_FILTER_INDEX_WIDTH 13
+#define EF4_FARCH_FILTER_INDEX_MASK ((1 << EF4_FARCH_FILTER_INDEX_WIDTH) - 1)
+
+static inline u32
+ef4_farch_filter_make_id(const struct ef4_farch_filter_spec *spec,
+ unsigned int index)
+{
+ unsigned int range;
+
+ range = ef4_farch_filter_type_match_pri[spec->type];
+ if (!(spec->flags & EF4_FILTER_FLAG_RX))
+ range += EF4_FARCH_FILTER_MATCH_PRI_COUNT;
+
+ return range << EF4_FARCH_FILTER_INDEX_WIDTH | index;
+}
+
+static inline enum ef4_farch_filter_table_id
+ef4_farch_filter_id_table_id(u32 id)
+{
+ unsigned int range = id >> EF4_FARCH_FILTER_INDEX_WIDTH;
+
+ if (range < ARRAY_SIZE(ef4_farch_filter_range_table))
+ return ef4_farch_filter_range_table[range];
+ else
+ return EF4_FARCH_FILTER_TABLE_COUNT; /* invalid */
+}
+
+static inline unsigned int ef4_farch_filter_id_index(u32 id)
+{
+ return id & EF4_FARCH_FILTER_INDEX_MASK;
+}
+
+u32 ef4_farch_filter_get_rx_id_limit(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ unsigned int range = EF4_FARCH_FILTER_MATCH_PRI_COUNT - 1;
+ enum ef4_farch_filter_table_id table_id;
+
+ do {
+ table_id = ef4_farch_filter_range_table[range];
+ if (state->table[table_id].size != 0)
+ return range << EF4_FARCH_FILTER_INDEX_WIDTH |
+ state->table[table_id].size;
+ } while (range--);
+
+ return 0;
+}
+
+s32 ef4_farch_filter_insert(struct ef4_nic *efx,
+ struct ef4_filter_spec *gen_spec,
+ bool replace_equal)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ struct ef4_farch_filter_table *table;
+ struct ef4_farch_filter_spec spec;
+ ef4_oword_t filter;
+ int rep_index, ins_index;
+ unsigned int depth = 0;
+ int rc;
+
+ rc = ef4_farch_filter_from_gen_spec(&spec, gen_spec);
+ if (rc)
+ return rc;
+
+ table = &state->table[ef4_farch_filter_spec_table_id(&spec)];
+ if (table->size == 0)
+ return -EINVAL;
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: type %d search_limit=%d", __func__, spec.type,
+ table->search_limit[spec.type]);
+
+ if (table->id == EF4_FARCH_FILTER_TABLE_RX_DEF) {
+ /* One filter spec per type */
+ BUILD_BUG_ON(EF4_FARCH_FILTER_INDEX_UC_DEF != 0);
+ BUILD_BUG_ON(EF4_FARCH_FILTER_INDEX_MC_DEF !=
+ EF4_FARCH_FILTER_MC_DEF - EF4_FARCH_FILTER_UC_DEF);
+ rep_index = spec.type - EF4_FARCH_FILTER_UC_DEF;
+ ins_index = rep_index;
+
+ spin_lock_bh(&efx->filter_lock);
+ } else {
+ /* Search concurrently for
+ * (1) a filter to be replaced (rep_index): any filter
+ * with the same match values, up to the current
+ * search depth for this type, and
+ * (2) the insertion point (ins_index): (1) or any
+ * free slot before it or up to the maximum search
+ * depth for this priority
+ * We fail if we cannot find (2).
+ *
+ * We can stop once either
+ * (a) we find (1), in which case we have definitely
+ * found (2) as well; or
+ * (b) we have searched exhaustively for (1), and have
+ * either found (2) or searched exhaustively for it
+ */
+ u32 key = ef4_farch_filter_build(&filter, &spec);
+ unsigned int hash = ef4_farch_filter_hash(key);
+ unsigned int incr = ef4_farch_filter_increment(key);
+ unsigned int max_rep_depth = table->search_limit[spec.type];
+ unsigned int max_ins_depth =
+ spec.priority <= EF4_FILTER_PRI_HINT ?
+ EF4_FARCH_FILTER_CTL_SRCH_HINT_MAX :
+ EF4_FARCH_FILTER_CTL_SRCH_MAX;
+ unsigned int i = hash & (table->size - 1);
+
+ ins_index = -1;
+ depth = 1;
+
+ spin_lock_bh(&efx->filter_lock);
+
+ for (;;) {
+ if (!test_bit(i, table->used_bitmap)) {
+ if (ins_index < 0)
+ ins_index = i;
+ } else if (ef4_farch_filter_equal(&spec,
+ &table->spec[i])) {
+ /* Case (a) */
+ if (ins_index < 0)
+ ins_index = i;
+ rep_index = i;
+ break;
+ }
+
+ if (depth >= max_rep_depth &&
+ (ins_index >= 0 || depth >= max_ins_depth)) {
+ /* Case (b) */
+ if (ins_index < 0) {
+ rc = -EBUSY;
+ goto out;
+ }
+ rep_index = -1;
+ break;
+ }
+
+ i = (i + incr) & (table->size - 1);
+ ++depth;
+ }
+ }
+
+ /* If we found a filter to be replaced, check whether we
+ * should do so
+ */
+ if (rep_index >= 0) {
+ struct ef4_farch_filter_spec *saved_spec =
+ &table->spec[rep_index];
+
+ if (spec.priority == saved_spec->priority && !replace_equal) {
+ rc = -EEXIST;
+ goto out;
+ }
+ if (spec.priority < saved_spec->priority) {
+ rc = -EPERM;
+ goto out;
+ }
+ if (saved_spec->priority == EF4_FILTER_PRI_AUTO ||
+ saved_spec->flags & EF4_FILTER_FLAG_RX_OVER_AUTO)
+ spec.flags |= EF4_FILTER_FLAG_RX_OVER_AUTO;
+ }
+
+ /* Insert the filter */
+ if (ins_index != rep_index) {
+ __set_bit(ins_index, table->used_bitmap);
+ ++table->used;
+ }
+ table->spec[ins_index] = spec;
+
+ if (table->id == EF4_FARCH_FILTER_TABLE_RX_DEF) {
+ ef4_farch_filter_push_rx_config(efx);
+ } else {
+ if (table->search_limit[spec.type] < depth) {
+ table->search_limit[spec.type] = depth;
+ if (spec.flags & EF4_FILTER_FLAG_TX)
+ ef4_farch_filter_push_tx_limits(efx);
+ else
+ ef4_farch_filter_push_rx_config(efx);
+ }
+
+ ef4_writeo(efx, &filter,
+ table->offset + table->step * ins_index);
+
+ /* If we were able to replace a filter by inserting
+ * at a lower depth, clear the replaced filter
+ */
+ if (ins_index != rep_index && rep_index >= 0)
+ ef4_farch_filter_table_clear_entry(efx, table,
+ rep_index);
+ }
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: filter type %d index %d rxq %u set",
+ __func__, spec.type, ins_index, spec.dmaq_id);
+ rc = ef4_farch_filter_make_id(&spec, ins_index);
+
+out:
+ spin_unlock_bh(&efx->filter_lock);
+ return rc;
+}
+
+static void
+ef4_farch_filter_table_clear_entry(struct ef4_nic *efx,
+ struct ef4_farch_filter_table *table,
+ unsigned int filter_idx)
+{
+ static ef4_oword_t filter;
+
+ EF4_WARN_ON_PARANOID(!test_bit(filter_idx, table->used_bitmap));
+ BUG_ON(table->offset == 0); /* can't clear MAC default filters */
+
+ __clear_bit(filter_idx, table->used_bitmap);
+ --table->used;
+ memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
+
+ ef4_writeo(efx, &filter, table->offset + table->step * filter_idx);
+
+ /* If this filter required a greater search depth than
+ * any other, the search limit for its type can now be
+ * decreased. However, it is hard to determine that
+ * unless the table has become completely empty - in
+ * which case, all its search limits can be set to 0.
+ */
+ if (unlikely(table->used == 0)) {
+ memset(table->search_limit, 0, sizeof(table->search_limit));
+ if (table->id == EF4_FARCH_FILTER_TABLE_TX_MAC)
+ ef4_farch_filter_push_tx_limits(efx);
+ else
+ ef4_farch_filter_push_rx_config(efx);
+ }
+}
+
+static int ef4_farch_filter_remove(struct ef4_nic *efx,
+ struct ef4_farch_filter_table *table,
+ unsigned int filter_idx,
+ enum ef4_filter_priority priority)
+{
+ struct ef4_farch_filter_spec *spec = &table->spec[filter_idx];
+
+ if (!test_bit(filter_idx, table->used_bitmap) ||
+ spec->priority != priority)
+ return -ENOENT;
+
+ if (spec->flags & EF4_FILTER_FLAG_RX_OVER_AUTO) {
+ ef4_farch_filter_init_rx_auto(efx, spec);
+ ef4_farch_filter_push_rx_config(efx);
+ } else {
+ ef4_farch_filter_table_clear_entry(efx, table, filter_idx);
+ }
+
+ return 0;
+}
+
+int ef4_farch_filter_remove_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ unsigned int filter_idx;
+ struct ef4_farch_filter_spec *spec;
+ int rc;
+
+ table_id = ef4_farch_filter_id_table_id(filter_id);
+ if ((unsigned int)table_id >= EF4_FARCH_FILTER_TABLE_COUNT)
+ return -ENOENT;
+ table = &state->table[table_id];
+
+ filter_idx = ef4_farch_filter_id_index(filter_id);
+ if (filter_idx >= table->size)
+ return -ENOENT;
+ spec = &table->spec[filter_idx];
+
+ spin_lock_bh(&efx->filter_lock);
+ rc = ef4_farch_filter_remove(efx, table, filter_idx, priority);
+ spin_unlock_bh(&efx->filter_lock);
+
+ return rc;
+}
+
+int ef4_farch_filter_get_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id, struct ef4_filter_spec *spec_buf)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ struct ef4_farch_filter_spec *spec;
+ unsigned int filter_idx;
+ int rc;
+
+ table_id = ef4_farch_filter_id_table_id(filter_id);
+ if ((unsigned int)table_id >= EF4_FARCH_FILTER_TABLE_COUNT)
+ return -ENOENT;
+ table = &state->table[table_id];
+
+ filter_idx = ef4_farch_filter_id_index(filter_id);
+ if (filter_idx >= table->size)
+ return -ENOENT;
+ spec = &table->spec[filter_idx];
+
+ spin_lock_bh(&efx->filter_lock);
+
+ if (test_bit(filter_idx, table->used_bitmap) &&
+ spec->priority == priority) {
+ ef4_farch_filter_to_gen_spec(spec_buf, spec);
+ rc = 0;
+ } else {
+ rc = -ENOENT;
+ }
+
+ spin_unlock_bh(&efx->filter_lock);
+
+ return rc;
+}
+
+static void
+ef4_farch_filter_table_clear(struct ef4_nic *efx,
+ enum ef4_farch_filter_table_id table_id,
+ enum ef4_filter_priority priority)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ struct ef4_farch_filter_table *table = &state->table[table_id];
+ unsigned int filter_idx;
+
+ spin_lock_bh(&efx->filter_lock);
+ for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
+ if (table->spec[filter_idx].priority != EF4_FILTER_PRI_AUTO)
+ ef4_farch_filter_remove(efx, table,
+ filter_idx, priority);
+ }
+ spin_unlock_bh(&efx->filter_lock);
+}
+
+int ef4_farch_filter_clear_rx(struct ef4_nic *efx,
+ enum ef4_filter_priority priority)
+{
+ ef4_farch_filter_table_clear(efx, EF4_FARCH_FILTER_TABLE_RX_IP,
+ priority);
+ ef4_farch_filter_table_clear(efx, EF4_FARCH_FILTER_TABLE_RX_MAC,
+ priority);
+ ef4_farch_filter_table_clear(efx, EF4_FARCH_FILTER_TABLE_RX_DEF,
+ priority);
+ return 0;
+}
+
+u32 ef4_farch_filter_count_rx_used(struct ef4_nic *efx,
+ enum ef4_filter_priority priority)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ unsigned int filter_idx;
+ u32 count = 0;
+
+ spin_lock_bh(&efx->filter_lock);
+
+ for (table_id = EF4_FARCH_FILTER_TABLE_RX_IP;
+ table_id <= EF4_FARCH_FILTER_TABLE_RX_DEF;
+ table_id++) {
+ table = &state->table[table_id];
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (test_bit(filter_idx, table->used_bitmap) &&
+ table->spec[filter_idx].priority == priority)
+ ++count;
+ }
+ }
+
+ spin_unlock_bh(&efx->filter_lock);
+
+ return count;
+}
+
+s32 ef4_farch_filter_get_rx_ids(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 *buf, u32 size)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ unsigned int filter_idx;
+ s32 count = 0;
+
+ spin_lock_bh(&efx->filter_lock);
+
+ for (table_id = EF4_FARCH_FILTER_TABLE_RX_IP;
+ table_id <= EF4_FARCH_FILTER_TABLE_RX_DEF;
+ table_id++) {
+ table = &state->table[table_id];
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (test_bit(filter_idx, table->used_bitmap) &&
+ table->spec[filter_idx].priority == priority) {
+ if (count == size) {
+ count = -EMSGSIZE;
+ goto out;
+ }
+ buf[count++] = ef4_farch_filter_make_id(
+ &table->spec[filter_idx], filter_idx);
+ }
+ }
+ }
+out:
+ spin_unlock_bh(&efx->filter_lock);
+
+ return count;
+}
+
+/* Restore filter stater after reset */
+void ef4_farch_filter_table_restore(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ ef4_oword_t filter;
+ unsigned int filter_idx;
+
+ spin_lock_bh(&efx->filter_lock);
+
+ for (table_id = 0; table_id < EF4_FARCH_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+
+ /* Check whether this is a regular register table */
+ if (table->step == 0)
+ continue;
+
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (!test_bit(filter_idx, table->used_bitmap))
+ continue;
+ ef4_farch_filter_build(&filter, &table->spec[filter_idx]);
+ ef4_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+ }
+
+ ef4_farch_filter_push_rx_config(efx);
+ ef4_farch_filter_push_tx_limits(efx);
+
+ spin_unlock_bh(&efx->filter_lock);
+}
+
+void ef4_farch_filter_table_remove(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+
+ for (table_id = 0; table_id < EF4_FARCH_FILTER_TABLE_COUNT; table_id++) {
+ kfree(state->table[table_id].used_bitmap);
+ vfree(state->table[table_id].spec);
+ }
+ kfree(state);
+}
+
+int ef4_farch_filter_table_probe(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state;
+ struct ef4_farch_filter_table *table;
+ unsigned table_id;
+
+ state = kzalloc(sizeof(struct ef4_farch_filter_state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+ efx->filter_state = state;
+
+ if (ef4_nic_rev(efx) >= EF4_REV_FALCON_B0) {
+ table = &state->table[EF4_FARCH_FILTER_TABLE_RX_IP];
+ table->id = EF4_FARCH_FILTER_TABLE_RX_IP;
+ table->offset = FR_BZ_RX_FILTER_TBL0;
+ table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
+ table->step = FR_BZ_RX_FILTER_TBL0_STEP;
+ }
+
+ for (table_id = 0; table_id < EF4_FARCH_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+ if (table->size == 0)
+ continue;
+ table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!table->used_bitmap)
+ goto fail;
+ table->spec = vzalloc(table->size * sizeof(*table->spec));
+ if (!table->spec)
+ goto fail;
+ }
+
+ table = &state->table[EF4_FARCH_FILTER_TABLE_RX_DEF];
+ if (table->size) {
+ /* RX default filters must always exist */
+ struct ef4_farch_filter_spec *spec;
+ unsigned i;
+
+ for (i = 0; i < EF4_FARCH_FILTER_SIZE_RX_DEF; i++) {
+ spec = &table->spec[i];
+ spec->type = EF4_FARCH_FILTER_UC_DEF + i;
+ ef4_farch_filter_init_rx_auto(efx, spec);
+ __set_bit(i, table->used_bitmap);
+ }
+ }
+
+ ef4_farch_filter_push_rx_config(efx);
+
+ return 0;
+
+fail:
+ ef4_farch_filter_table_remove(efx);
+ return -ENOMEM;
+}
+
+/* Update scatter enable flags for filters pointing to our own RX queues */
+void ef4_farch_filter_update_rx_scatter(struct ef4_nic *efx)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ enum ef4_farch_filter_table_id table_id;
+ struct ef4_farch_filter_table *table;
+ ef4_oword_t filter;
+ unsigned int filter_idx;
+
+ spin_lock_bh(&efx->filter_lock);
+
+ for (table_id = EF4_FARCH_FILTER_TABLE_RX_IP;
+ table_id <= EF4_FARCH_FILTER_TABLE_RX_DEF;
+ table_id++) {
+ table = &state->table[table_id];
+
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (!test_bit(filter_idx, table->used_bitmap) ||
+ table->spec[filter_idx].dmaq_id >=
+ efx->n_rx_channels)
+ continue;
+
+ if (efx->rx_scatter)
+ table->spec[filter_idx].flags |=
+ EF4_FILTER_FLAG_RX_SCATTER;
+ else
+ table->spec[filter_idx].flags &=
+ ~EF4_FILTER_FLAG_RX_SCATTER;
+
+ if (table_id == EF4_FARCH_FILTER_TABLE_RX_DEF)
+ /* Pushed by ef4_farch_filter_push_rx_config() */
+ continue;
+
+ ef4_farch_filter_build(&filter, &table->spec[filter_idx]);
+ ef4_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+ }
+
+ ef4_farch_filter_push_rx_config(efx);
+
+ spin_unlock_bh(&efx->filter_lock);
+}
+
+#ifdef CONFIG_RFS_ACCEL
+
+s32 ef4_farch_filter_rfs_insert(struct ef4_nic *efx,
+ struct ef4_filter_spec *gen_spec)
+{
+ return ef4_farch_filter_insert(efx, gen_spec, true);
+}
+
+bool ef4_farch_filter_rfs_expire_one(struct ef4_nic *efx, u32 flow_id,
+ unsigned int index)
+{
+ struct ef4_farch_filter_state *state = efx->filter_state;
+ struct ef4_farch_filter_table *table =
+ &state->table[EF4_FARCH_FILTER_TABLE_RX_IP];
+
+ if (test_bit(index, table->used_bitmap) &&
+ table->spec[index].priority == EF4_FILTER_PRI_HINT &&
+ rps_may_expire_flow(efx->net_dev, table->spec[index].dmaq_id,
+ flow_id, index)) {
+ ef4_farch_filter_table_clear_entry(efx, table, index);
+ return true;
+ }
+
+ return false;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
+
+void ef4_farch_filter_sync_rx_mode(struct ef4_nic *efx)
+{
+ struct net_device *net_dev = efx->net_dev;
+ struct netdev_hw_addr *ha;
+ union ef4_multicast_hash *mc_hash = &efx->multicast_hash;
+ u32 crc;
+ int bit;
+
+ if (!ef4_dev_registered(efx))
+ return;
+
+ netif_addr_lock_bh(net_dev);
+
+ efx->unicast_filter = !(net_dev->flags & IFF_PROMISC);
+
+ /* Build multicast hash table */
+ if (net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+ memset(mc_hash, 0xff, sizeof(*mc_hash));
+ } else {
+ memset(mc_hash, 0x00, sizeof(*mc_hash));
+ netdev_for_each_mc_addr(ha, net_dev) {
+ crc = ether_crc_le(ETH_ALEN, ha->addr);
+ bit = crc & (EF4_MCAST_HASH_ENTRIES - 1);
+ __set_bit_le(bit, mc_hash);
+ }
+
+ /* Broadcast packets go through the multicast hash filter.
+ * ether_crc_le() of the broadcast address is 0xbe2612ff
+ * so we always add bit 0xff to the mask.
+ */
+ __set_bit_le(0xff, mc_hash);
+ }
+
+ netif_addr_unlock_bh(net_dev);
+}
diff --git a/drivers/net/ethernet/sfc/falcon/farch_regs.h b/drivers/net/ethernet/sfc/falcon/farch_regs.h
new file mode 100644
index 000000000000..8095f273d574
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/farch_regs.h
@@ -0,0 +1,2932 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2012 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_FARCH_REGS_H
+#define EF4_FARCH_REGS_H
+
+/*
+ * Falcon hardware architecture definitions have a name prefix following
+ * the format:
+ *
+ * F<type>_<min-rev><max-rev>_
+ *
+ * The following <type> strings are used:
+ *
+ * MMIO register MC register Host memory structure
+ * -------------------------------------------------------------
+ * Address R MCR
+ * Bitfield RF MCRF SF
+ * Enumerator FE MCFE SE
+ *
+ * <min-rev> is the first revision to which the definition applies:
+ *
+ * A: Falcon A1 (SFC4000AB)
+ * B: Falcon B0 (SFC4000BA)
+ * C: Siena A0 (SFL9021AA)
+ *
+ * If the definition has been changed or removed in later revisions
+ * then <max-rev> is the last revision to which the definition applies;
+ * otherwise it is "Z".
+ */
+
+/**************************************************************************
+ *
+ * Falcon/Siena registers and descriptors
+ *
+ **************************************************************************
+ */
+
+/* ADR_REGION_REG: Address region register */
+#define FR_AZ_ADR_REGION 0x00000000
+#define FRF_AZ_ADR_REGION3_LBN 96
+#define FRF_AZ_ADR_REGION3_WIDTH 18
+#define FRF_AZ_ADR_REGION2_LBN 64
+#define FRF_AZ_ADR_REGION2_WIDTH 18
+#define FRF_AZ_ADR_REGION1_LBN 32
+#define FRF_AZ_ADR_REGION1_WIDTH 18
+#define FRF_AZ_ADR_REGION0_LBN 0
+#define FRF_AZ_ADR_REGION0_WIDTH 18
+
+/* INT_EN_REG_KER: Kernel driver Interrupt enable register */
+#define FR_AZ_INT_EN_KER 0x00000010
+#define FRF_AZ_KER_INT_LEVE_SEL_LBN 8
+#define FRF_AZ_KER_INT_LEVE_SEL_WIDTH 6
+#define FRF_AZ_KER_INT_CHAR_LBN 4
+#define FRF_AZ_KER_INT_CHAR_WIDTH 1
+#define FRF_AZ_KER_INT_KER_LBN 3
+#define FRF_AZ_KER_INT_KER_WIDTH 1
+#define FRF_AZ_DRV_INT_EN_KER_LBN 0
+#define FRF_AZ_DRV_INT_EN_KER_WIDTH 1
+
+/* INT_EN_REG_CHAR: Char Driver interrupt enable register */
+#define FR_BZ_INT_EN_CHAR 0x00000020
+#define FRF_BZ_CHAR_INT_LEVE_SEL_LBN 8
+#define FRF_BZ_CHAR_INT_LEVE_SEL_WIDTH 6
+#define FRF_BZ_CHAR_INT_CHAR_LBN 4
+#define FRF_BZ_CHAR_INT_CHAR_WIDTH 1
+#define FRF_BZ_CHAR_INT_KER_LBN 3
+#define FRF_BZ_CHAR_INT_KER_WIDTH 1
+#define FRF_BZ_DRV_INT_EN_CHAR_LBN 0
+#define FRF_BZ_DRV_INT_EN_CHAR_WIDTH 1
+
+/* INT_ADR_REG_KER: Interrupt host address for Kernel driver */
+#define FR_AZ_INT_ADR_KER 0x00000030
+#define FRF_AZ_NORM_INT_VEC_DIS_KER_LBN 64
+#define FRF_AZ_NORM_INT_VEC_DIS_KER_WIDTH 1
+#define FRF_AZ_INT_ADR_KER_LBN 0
+#define FRF_AZ_INT_ADR_KER_WIDTH 64
+
+/* INT_ADR_REG_CHAR: Interrupt host address for Char driver */
+#define FR_BZ_INT_ADR_CHAR 0x00000040
+#define FRF_BZ_NORM_INT_VEC_DIS_CHAR_LBN 64
+#define FRF_BZ_NORM_INT_VEC_DIS_CHAR_WIDTH 1
+#define FRF_BZ_INT_ADR_CHAR_LBN 0
+#define FRF_BZ_INT_ADR_CHAR_WIDTH 64
+
+/* INT_ACK_KER: Kernel interrupt acknowledge register */
+#define FR_AA_INT_ACK_KER 0x00000050
+#define FRF_AA_INT_ACK_KER_FIELD_LBN 0
+#define FRF_AA_INT_ACK_KER_FIELD_WIDTH 32
+
+/* INT_ISR0_REG: Function 0 Interrupt Acknowledge Status register */
+#define FR_BZ_INT_ISR0 0x00000090
+#define FRF_BZ_INT_ISR_REG_LBN 0
+#define FRF_BZ_INT_ISR_REG_WIDTH 64
+
+/* HW_INIT_REG: Hardware initialization register */
+#define FR_AZ_HW_INIT 0x000000c0
+#define FRF_BB_BDMRD_CPLF_FULL_LBN 124
+#define FRF_BB_BDMRD_CPLF_FULL_WIDTH 1
+#define FRF_BB_PCIE_CPL_TIMEOUT_CTRL_LBN 121
+#define FRF_BB_PCIE_CPL_TIMEOUT_CTRL_WIDTH 3
+#define FRF_CZ_TX_MRG_TAGS_LBN 120
+#define FRF_CZ_TX_MRG_TAGS_WIDTH 1
+#define FRF_AB_TRGT_MASK_ALL_LBN 100
+#define FRF_AB_TRGT_MASK_ALL_WIDTH 1
+#define FRF_AZ_DOORBELL_DROP_LBN 92
+#define FRF_AZ_DOORBELL_DROP_WIDTH 8
+#define FRF_AB_TX_RREQ_MASK_EN_LBN 76
+#define FRF_AB_TX_RREQ_MASK_EN_WIDTH 1
+#define FRF_AB_PE_EIDLE_DIS_LBN 75
+#define FRF_AB_PE_EIDLE_DIS_WIDTH 1
+#define FRF_AA_FC_BLOCKING_EN_LBN 45
+#define FRF_AA_FC_BLOCKING_EN_WIDTH 1
+#define FRF_BZ_B2B_REQ_EN_LBN 45
+#define FRF_BZ_B2B_REQ_EN_WIDTH 1
+#define FRF_AA_B2B_REQ_EN_LBN 44
+#define FRF_AA_B2B_REQ_EN_WIDTH 1
+#define FRF_BB_FC_BLOCKING_EN_LBN 44
+#define FRF_BB_FC_BLOCKING_EN_WIDTH 1
+#define FRF_AZ_POST_WR_MASK_LBN 40
+#define FRF_AZ_POST_WR_MASK_WIDTH 4
+#define FRF_AZ_TLP_TC_LBN 34
+#define FRF_AZ_TLP_TC_WIDTH 3
+#define FRF_AZ_TLP_ATTR_LBN 32
+#define FRF_AZ_TLP_ATTR_WIDTH 2
+#define FRF_AB_INTB_VEC_LBN 24
+#define FRF_AB_INTB_VEC_WIDTH 5
+#define FRF_AB_INTA_VEC_LBN 16
+#define FRF_AB_INTA_VEC_WIDTH 5
+#define FRF_AZ_WD_TIMER_LBN 8
+#define FRF_AZ_WD_TIMER_WIDTH 8
+#define FRF_AZ_US_DISABLE_LBN 5
+#define FRF_AZ_US_DISABLE_WIDTH 1
+#define FRF_AZ_TLP_EP_LBN 4
+#define FRF_AZ_TLP_EP_WIDTH 1
+#define FRF_AZ_ATTR_SEL_LBN 3
+#define FRF_AZ_ATTR_SEL_WIDTH 1
+#define FRF_AZ_TD_SEL_LBN 1
+#define FRF_AZ_TD_SEL_WIDTH 1
+#define FRF_AZ_TLP_TD_LBN 0
+#define FRF_AZ_TLP_TD_WIDTH 1
+
+/* EE_SPI_HCMD_REG: SPI host command register */
+#define FR_AB_EE_SPI_HCMD 0x00000100
+#define FRF_AB_EE_SPI_HCMD_CMD_EN_LBN 31
+#define FRF_AB_EE_SPI_HCMD_CMD_EN_WIDTH 1
+#define FRF_AB_EE_WR_TIMER_ACTIVE_LBN 28
+#define FRF_AB_EE_WR_TIMER_ACTIVE_WIDTH 1
+#define FRF_AB_EE_SPI_HCMD_SF_SEL_LBN 24
+#define FRF_AB_EE_SPI_HCMD_SF_SEL_WIDTH 1
+#define FRF_AB_EE_SPI_HCMD_DABCNT_LBN 16
+#define FRF_AB_EE_SPI_HCMD_DABCNT_WIDTH 5
+#define FRF_AB_EE_SPI_HCMD_READ_LBN 15
+#define FRF_AB_EE_SPI_HCMD_READ_WIDTH 1
+#define FRF_AB_EE_SPI_HCMD_DUBCNT_LBN 12
+#define FRF_AB_EE_SPI_HCMD_DUBCNT_WIDTH 2
+#define FRF_AB_EE_SPI_HCMD_ADBCNT_LBN 8
+#define FRF_AB_EE_SPI_HCMD_ADBCNT_WIDTH 2
+#define FRF_AB_EE_SPI_HCMD_ENC_LBN 0
+#define FRF_AB_EE_SPI_HCMD_ENC_WIDTH 8
+
+/* USR_EV_CFG: User Level Event Configuration register */
+#define FR_CZ_USR_EV_CFG 0x00000100
+#define FRF_CZ_USREV_DIS_LBN 16
+#define FRF_CZ_USREV_DIS_WIDTH 1
+#define FRF_CZ_DFLT_EVQ_LBN 0
+#define FRF_CZ_DFLT_EVQ_WIDTH 10
+
+/* EE_SPI_HADR_REG: SPI host address register */
+#define FR_AB_EE_SPI_HADR 0x00000110
+#define FRF_AB_EE_SPI_HADR_DUBYTE_LBN 24
+#define FRF_AB_EE_SPI_HADR_DUBYTE_WIDTH 8
+#define FRF_AB_EE_SPI_HADR_ADR_LBN 0
+#define FRF_AB_EE_SPI_HADR_ADR_WIDTH 24
+
+/* EE_SPI_HDATA_REG: SPI host data register */
+#define FR_AB_EE_SPI_HDATA 0x00000120
+#define FRF_AB_EE_SPI_HDATA3_LBN 96
+#define FRF_AB_EE_SPI_HDATA3_WIDTH 32
+#define FRF_AB_EE_SPI_HDATA2_LBN 64
+#define FRF_AB_EE_SPI_HDATA2_WIDTH 32
+#define FRF_AB_EE_SPI_HDATA1_LBN 32
+#define FRF_AB_EE_SPI_HDATA1_WIDTH 32
+#define FRF_AB_EE_SPI_HDATA0_LBN 0
+#define FRF_AB_EE_SPI_HDATA0_WIDTH 32
+
+/* EE_BASE_PAGE_REG: Expansion ROM base mirror register */
+#define FR_AB_EE_BASE_PAGE 0x00000130
+#define FRF_AB_EE_EXPROM_MASK_LBN 16
+#define FRF_AB_EE_EXPROM_MASK_WIDTH 13
+#define FRF_AB_EE_EXP_ROM_WINDOW_BASE_LBN 0
+#define FRF_AB_EE_EXP_ROM_WINDOW_BASE_WIDTH 13
+
+/* EE_VPD_CFG0_REG: SPI/VPD configuration register 0 */
+#define FR_AB_EE_VPD_CFG0 0x00000140
+#define FRF_AB_EE_SF_FASTRD_EN_LBN 127
+#define FRF_AB_EE_SF_FASTRD_EN_WIDTH 1
+#define FRF_AB_EE_SF_CLOCK_DIV_LBN 120
+#define FRF_AB_EE_SF_CLOCK_DIV_WIDTH 7
+#define FRF_AB_EE_VPD_WIP_POLL_LBN 119
+#define FRF_AB_EE_VPD_WIP_POLL_WIDTH 1
+#define FRF_AB_EE_EE_CLOCK_DIV_LBN 112
+#define FRF_AB_EE_EE_CLOCK_DIV_WIDTH 7
+#define FRF_AB_EE_EE_WR_TMR_VALUE_LBN 96
+#define FRF_AB_EE_EE_WR_TMR_VALUE_WIDTH 16
+#define FRF_AB_EE_VPDW_LENGTH_LBN 80
+#define FRF_AB_EE_VPDW_LENGTH_WIDTH 15
+#define FRF_AB_EE_VPDW_BASE_LBN 64
+#define FRF_AB_EE_VPDW_BASE_WIDTH 15
+#define FRF_AB_EE_VPD_WR_CMD_EN_LBN 56
+#define FRF_AB_EE_VPD_WR_CMD_EN_WIDTH 8
+#define FRF_AB_EE_VPD_BASE_LBN 32
+#define FRF_AB_EE_VPD_BASE_WIDTH 24
+#define FRF_AB_EE_VPD_LENGTH_LBN 16
+#define FRF_AB_EE_VPD_LENGTH_WIDTH 15
+#define FRF_AB_EE_VPD_AD_SIZE_LBN 8
+#define FRF_AB_EE_VPD_AD_SIZE_WIDTH 5
+#define FRF_AB_EE_VPD_ACCESS_ON_LBN 5
+#define FRF_AB_EE_VPD_ACCESS_ON_WIDTH 1
+#define FRF_AB_EE_VPD_ACCESS_BLOCK_LBN 4
+#define FRF_AB_EE_VPD_ACCESS_BLOCK_WIDTH 1
+#define FRF_AB_EE_VPD_DEV_SF_SEL_LBN 2
+#define FRF_AB_EE_VPD_DEV_SF_SEL_WIDTH 1
+#define FRF_AB_EE_VPD_EN_AD9_MODE_LBN 1
+#define FRF_AB_EE_VPD_EN_AD9_MODE_WIDTH 1
+#define FRF_AB_EE_VPD_EN_LBN 0
+#define FRF_AB_EE_VPD_EN_WIDTH 1
+
+/* EE_VPD_SW_CNTL_REG: VPD access SW control register */
+#define FR_AB_EE_VPD_SW_CNTL 0x00000150
+#define FRF_AB_EE_VPD_CYCLE_PENDING_LBN 31
+#define FRF_AB_EE_VPD_CYCLE_PENDING_WIDTH 1
+#define FRF_AB_EE_VPD_CYC_WRITE_LBN 28
+#define FRF_AB_EE_VPD_CYC_WRITE_WIDTH 1
+#define FRF_AB_EE_VPD_CYC_ADR_LBN 0
+#define FRF_AB_EE_VPD_CYC_ADR_WIDTH 15
+
+/* EE_VPD_SW_DATA_REG: VPD access SW data register */
+#define FR_AB_EE_VPD_SW_DATA 0x00000160
+#define FRF_AB_EE_VPD_CYC_DAT_LBN 0
+#define FRF_AB_EE_VPD_CYC_DAT_WIDTH 32
+
+/* PBMX_DBG_IADDR_REG: Capture Module address register */
+#define FR_CZ_PBMX_DBG_IADDR 0x000001f0
+#define FRF_CZ_PBMX_DBG_IADDR_LBN 0
+#define FRF_CZ_PBMX_DBG_IADDR_WIDTH 32
+
+/* PCIE_CORE_INDIRECT_REG: Indirect Access to PCIE Core registers */
+#define FR_BB_PCIE_CORE_INDIRECT 0x000001f0
+#define FRF_BB_PCIE_CORE_TARGET_DATA_LBN 32
+#define FRF_BB_PCIE_CORE_TARGET_DATA_WIDTH 32
+#define FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_LBN 15
+#define FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_WIDTH 1
+#define FRF_BB_PCIE_CORE_TARGET_REG_ADRS_LBN 0
+#define FRF_BB_PCIE_CORE_TARGET_REG_ADRS_WIDTH 12
+
+/* PBMX_DBG_IDATA_REG: Capture Module data register */
+#define FR_CZ_PBMX_DBG_IDATA 0x000001f8
+#define FRF_CZ_PBMX_DBG_IDATA_LBN 0
+#define FRF_CZ_PBMX_DBG_IDATA_WIDTH 64
+
+/* NIC_STAT_REG: NIC status register */
+#define FR_AB_NIC_STAT 0x00000200
+#define FRF_BB_AER_DIS_LBN 34
+#define FRF_BB_AER_DIS_WIDTH 1
+#define FRF_BB_EE_STRAP_EN_LBN 31
+#define FRF_BB_EE_STRAP_EN_WIDTH 1
+#define FRF_BB_EE_STRAP_LBN 24
+#define FRF_BB_EE_STRAP_WIDTH 4
+#define FRF_BB_REVISION_ID_LBN 17
+#define FRF_BB_REVISION_ID_WIDTH 7
+#define FRF_AB_ONCHIP_SRAM_LBN 16
+#define FRF_AB_ONCHIP_SRAM_WIDTH 1
+#define FRF_AB_SF_PRST_LBN 9
+#define FRF_AB_SF_PRST_WIDTH 1
+#define FRF_AB_EE_PRST_LBN 8
+#define FRF_AB_EE_PRST_WIDTH 1
+#define FRF_AB_ATE_MODE_LBN 3
+#define FRF_AB_ATE_MODE_WIDTH 1
+#define FRF_AB_STRAP_PINS_LBN 0
+#define FRF_AB_STRAP_PINS_WIDTH 3
+
+/* GPIO_CTL_REG: GPIO control register */
+#define FR_AB_GPIO_CTL 0x00000210
+#define FRF_AB_GPIO_OUT3_LBN 112
+#define FRF_AB_GPIO_OUT3_WIDTH 16
+#define FRF_AB_GPIO_IN3_LBN 104
+#define FRF_AB_GPIO_IN3_WIDTH 8
+#define FRF_AB_GPIO_PWRUP_VALUE3_LBN 96
+#define FRF_AB_GPIO_PWRUP_VALUE3_WIDTH 8
+#define FRF_AB_GPIO_OUT2_LBN 80
+#define FRF_AB_GPIO_OUT2_WIDTH 16
+#define FRF_AB_GPIO_IN2_LBN 72
+#define FRF_AB_GPIO_IN2_WIDTH 8
+#define FRF_AB_GPIO_PWRUP_VALUE2_LBN 64
+#define FRF_AB_GPIO_PWRUP_VALUE2_WIDTH 8
+#define FRF_AB_GPIO15_OEN_LBN 63
+#define FRF_AB_GPIO15_OEN_WIDTH 1
+#define FRF_AB_GPIO14_OEN_LBN 62
+#define FRF_AB_GPIO14_OEN_WIDTH 1
+#define FRF_AB_GPIO13_OEN_LBN 61
+#define FRF_AB_GPIO13_OEN_WIDTH 1
+#define FRF_AB_GPIO12_OEN_LBN 60
+#define FRF_AB_GPIO12_OEN_WIDTH 1
+#define FRF_AB_GPIO11_OEN_LBN 59
+#define FRF_AB_GPIO11_OEN_WIDTH 1
+#define FRF_AB_GPIO10_OEN_LBN 58
+#define FRF_AB_GPIO10_OEN_WIDTH 1
+#define FRF_AB_GPIO9_OEN_LBN 57
+#define FRF_AB_GPIO9_OEN_WIDTH 1
+#define FRF_AB_GPIO8_OEN_LBN 56
+#define FRF_AB_GPIO8_OEN_WIDTH 1
+#define FRF_AB_GPIO15_OUT_LBN 55
+#define FRF_AB_GPIO15_OUT_WIDTH 1
+#define FRF_AB_GPIO14_OUT_LBN 54
+#define FRF_AB_GPIO14_OUT_WIDTH 1
+#define FRF_AB_GPIO13_OUT_LBN 53
+#define FRF_AB_GPIO13_OUT_WIDTH 1
+#define FRF_AB_GPIO12_OUT_LBN 52
+#define FRF_AB_GPIO12_OUT_WIDTH 1
+#define FRF_AB_GPIO11_OUT_LBN 51
+#define FRF_AB_GPIO11_OUT_WIDTH 1
+#define FRF_AB_GPIO10_OUT_LBN 50
+#define FRF_AB_GPIO10_OUT_WIDTH 1
+#define FRF_AB_GPIO9_OUT_LBN 49
+#define FRF_AB_GPIO9_OUT_WIDTH 1
+#define FRF_AB_GPIO8_OUT_LBN 48
+#define FRF_AB_GPIO8_OUT_WIDTH 1
+#define FRF_AB_GPIO15_IN_LBN 47
+#define FRF_AB_GPIO15_IN_WIDTH 1
+#define FRF_AB_GPIO14_IN_LBN 46
+#define FRF_AB_GPIO14_IN_WIDTH 1
+#define FRF_AB_GPIO13_IN_LBN 45
+#define FRF_AB_GPIO13_IN_WIDTH 1
+#define FRF_AB_GPIO12_IN_LBN 44
+#define FRF_AB_GPIO12_IN_WIDTH 1
+#define FRF_AB_GPIO11_IN_LBN 43
+#define FRF_AB_GPIO11_IN_WIDTH 1
+#define FRF_AB_GPIO10_IN_LBN 42
+#define FRF_AB_GPIO10_IN_WIDTH 1
+#define FRF_AB_GPIO9_IN_LBN 41
+#define FRF_AB_GPIO9_IN_WIDTH 1
+#define FRF_AB_GPIO8_IN_LBN 40
+#define FRF_AB_GPIO8_IN_WIDTH 1
+#define FRF_AB_GPIO15_PWRUP_VALUE_LBN 39
+#define FRF_AB_GPIO15_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO14_PWRUP_VALUE_LBN 38
+#define FRF_AB_GPIO14_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO13_PWRUP_VALUE_LBN 37
+#define FRF_AB_GPIO13_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO12_PWRUP_VALUE_LBN 36
+#define FRF_AB_GPIO12_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO11_PWRUP_VALUE_LBN 35
+#define FRF_AB_GPIO11_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO10_PWRUP_VALUE_LBN 34
+#define FRF_AB_GPIO10_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO9_PWRUP_VALUE_LBN 33
+#define FRF_AB_GPIO9_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO8_PWRUP_VALUE_LBN 32
+#define FRF_AB_GPIO8_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_CLK156_OUT_EN_LBN 31
+#define FRF_AB_CLK156_OUT_EN_WIDTH 1
+#define FRF_AB_USE_NIC_CLK_LBN 30
+#define FRF_AB_USE_NIC_CLK_WIDTH 1
+#define FRF_AB_GPIO5_OEN_LBN 29
+#define FRF_AB_GPIO5_OEN_WIDTH 1
+#define FRF_AB_GPIO4_OEN_LBN 28
+#define FRF_AB_GPIO4_OEN_WIDTH 1
+#define FRF_AB_GPIO3_OEN_LBN 27
+#define FRF_AB_GPIO3_OEN_WIDTH 1
+#define FRF_AB_GPIO2_OEN_LBN 26
+#define FRF_AB_GPIO2_OEN_WIDTH 1
+#define FRF_AB_GPIO1_OEN_LBN 25
+#define FRF_AB_GPIO1_OEN_WIDTH 1
+#define FRF_AB_GPIO0_OEN_LBN 24
+#define FRF_AB_GPIO0_OEN_WIDTH 1
+#define FRF_AB_GPIO7_OUT_LBN 23
+#define FRF_AB_GPIO7_OUT_WIDTH 1
+#define FRF_AB_GPIO6_OUT_LBN 22
+#define FRF_AB_GPIO6_OUT_WIDTH 1
+#define FRF_AB_GPIO5_OUT_LBN 21
+#define FRF_AB_GPIO5_OUT_WIDTH 1
+#define FRF_AB_GPIO4_OUT_LBN 20
+#define FRF_AB_GPIO4_OUT_WIDTH 1
+#define FRF_AB_GPIO3_OUT_LBN 19
+#define FRF_AB_GPIO3_OUT_WIDTH 1
+#define FRF_AB_GPIO2_OUT_LBN 18
+#define FRF_AB_GPIO2_OUT_WIDTH 1
+#define FRF_AB_GPIO1_OUT_LBN 17
+#define FRF_AB_GPIO1_OUT_WIDTH 1
+#define FRF_AB_GPIO0_OUT_LBN 16
+#define FRF_AB_GPIO0_OUT_WIDTH 1
+#define FRF_AB_GPIO7_IN_LBN 15
+#define FRF_AB_GPIO7_IN_WIDTH 1
+#define FRF_AB_GPIO6_IN_LBN 14
+#define FRF_AB_GPIO6_IN_WIDTH 1
+#define FRF_AB_GPIO5_IN_LBN 13
+#define FRF_AB_GPIO5_IN_WIDTH 1
+#define FRF_AB_GPIO4_IN_LBN 12
+#define FRF_AB_GPIO4_IN_WIDTH 1
+#define FRF_AB_GPIO3_IN_LBN 11
+#define FRF_AB_GPIO3_IN_WIDTH 1
+#define FRF_AB_GPIO2_IN_LBN 10
+#define FRF_AB_GPIO2_IN_WIDTH 1
+#define FRF_AB_GPIO1_IN_LBN 9
+#define FRF_AB_GPIO1_IN_WIDTH 1
+#define FRF_AB_GPIO0_IN_LBN 8
+#define FRF_AB_GPIO0_IN_WIDTH 1
+#define FRF_AB_GPIO7_PWRUP_VALUE_LBN 7
+#define FRF_AB_GPIO7_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO6_PWRUP_VALUE_LBN 6
+#define FRF_AB_GPIO6_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO5_PWRUP_VALUE_LBN 5
+#define FRF_AB_GPIO5_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO4_PWRUP_VALUE_LBN 4
+#define FRF_AB_GPIO4_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO3_PWRUP_VALUE_LBN 3
+#define FRF_AB_GPIO3_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO2_PWRUP_VALUE_LBN 2
+#define FRF_AB_GPIO2_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO1_PWRUP_VALUE_LBN 1
+#define FRF_AB_GPIO1_PWRUP_VALUE_WIDTH 1
+#define FRF_AB_GPIO0_PWRUP_VALUE_LBN 0
+#define FRF_AB_GPIO0_PWRUP_VALUE_WIDTH 1
+
+/* GLB_CTL_REG: Global control register */
+#define FR_AB_GLB_CTL 0x00000220
+#define FRF_AB_EXT_PHY_RST_CTL_LBN 63
+#define FRF_AB_EXT_PHY_RST_CTL_WIDTH 1
+#define FRF_AB_XAUI_SD_RST_CTL_LBN 62
+#define FRF_AB_XAUI_SD_RST_CTL_WIDTH 1
+#define FRF_AB_PCIE_SD_RST_CTL_LBN 61
+#define FRF_AB_PCIE_SD_RST_CTL_WIDTH 1
+#define FRF_AA_PCIX_RST_CTL_LBN 60
+#define FRF_AA_PCIX_RST_CTL_WIDTH 1
+#define FRF_BB_BIU_RST_CTL_LBN 60
+#define FRF_BB_BIU_RST_CTL_WIDTH 1
+#define FRF_AB_PCIE_STKY_RST_CTL_LBN 59
+#define FRF_AB_PCIE_STKY_RST_CTL_WIDTH 1
+#define FRF_AB_PCIE_NSTKY_RST_CTL_LBN 58
+#define FRF_AB_PCIE_NSTKY_RST_CTL_WIDTH 1
+#define FRF_AB_PCIE_CORE_RST_CTL_LBN 57
+#define FRF_AB_PCIE_CORE_RST_CTL_WIDTH 1
+#define FRF_AB_XGRX_RST_CTL_LBN 56
+#define FRF_AB_XGRX_RST_CTL_WIDTH 1
+#define FRF_AB_XGTX_RST_CTL_LBN 55
+#define FRF_AB_XGTX_RST_CTL_WIDTH 1
+#define FRF_AB_EM_RST_CTL_LBN 54
+#define FRF_AB_EM_RST_CTL_WIDTH 1
+#define FRF_AB_EV_RST_CTL_LBN 53
+#define FRF_AB_EV_RST_CTL_WIDTH 1
+#define FRF_AB_SR_RST_CTL_LBN 52
+#define FRF_AB_SR_RST_CTL_WIDTH 1
+#define FRF_AB_RX_RST_CTL_LBN 51
+#define FRF_AB_RX_RST_CTL_WIDTH 1
+#define FRF_AB_TX_RST_CTL_LBN 50
+#define FRF_AB_TX_RST_CTL_WIDTH 1
+#define FRF_AB_EE_RST_CTL_LBN 49
+#define FRF_AB_EE_RST_CTL_WIDTH 1
+#define FRF_AB_CS_RST_CTL_LBN 48
+#define FRF_AB_CS_RST_CTL_WIDTH 1
+#define FRF_AB_HOT_RST_CTL_LBN 40
+#define FRF_AB_HOT_RST_CTL_WIDTH 2
+#define FRF_AB_RST_EXT_PHY_LBN 31
+#define FRF_AB_RST_EXT_PHY_WIDTH 1
+#define FRF_AB_RST_XAUI_SD_LBN 30
+#define FRF_AB_RST_XAUI_SD_WIDTH 1
+#define FRF_AB_RST_PCIE_SD_LBN 29
+#define FRF_AB_RST_PCIE_SD_WIDTH 1
+#define FRF_AA_RST_PCIX_LBN 28
+#define FRF_AA_RST_PCIX_WIDTH 1
+#define FRF_BB_RST_BIU_LBN 28
+#define FRF_BB_RST_BIU_WIDTH 1
+#define FRF_AB_RST_PCIE_STKY_LBN 27
+#define FRF_AB_RST_PCIE_STKY_WIDTH 1
+#define FRF_AB_RST_PCIE_NSTKY_LBN 26
+#define FRF_AB_RST_PCIE_NSTKY_WIDTH 1
+#define FRF_AB_RST_PCIE_CORE_LBN 25
+#define FRF_AB_RST_PCIE_CORE_WIDTH 1
+#define FRF_AB_RST_XGRX_LBN 24
+#define FRF_AB_RST_XGRX_WIDTH 1
+#define FRF_AB_RST_XGTX_LBN 23
+#define FRF_AB_RST_XGTX_WIDTH 1
+#define FRF_AB_RST_EM_LBN 22
+#define FRF_AB_RST_EM_WIDTH 1
+#define FRF_AB_RST_EV_LBN 21
+#define FRF_AB_RST_EV_WIDTH 1
+#define FRF_AB_RST_SR_LBN 20
+#define FRF_AB_RST_SR_WIDTH 1
+#define FRF_AB_RST_RX_LBN 19
+#define FRF_AB_RST_RX_WIDTH 1
+#define FRF_AB_RST_TX_LBN 18
+#define FRF_AB_RST_TX_WIDTH 1
+#define FRF_AB_RST_SF_LBN 17
+#define FRF_AB_RST_SF_WIDTH 1
+#define FRF_AB_RST_CS_LBN 16
+#define FRF_AB_RST_CS_WIDTH 1
+#define FRF_AB_INT_RST_DUR_LBN 4
+#define FRF_AB_INT_RST_DUR_WIDTH 3
+#define FRF_AB_EXT_PHY_RST_DUR_LBN 1
+#define FRF_AB_EXT_PHY_RST_DUR_WIDTH 3
+#define FFE_AB_EXT_PHY_RST_DUR_10240US 7
+#define FFE_AB_EXT_PHY_RST_DUR_5120US 6
+#define FFE_AB_EXT_PHY_RST_DUR_2560US 5
+#define FFE_AB_EXT_PHY_RST_DUR_1280US 4
+#define FFE_AB_EXT_PHY_RST_DUR_640US 3
+#define FFE_AB_EXT_PHY_RST_DUR_320US 2
+#define FFE_AB_EXT_PHY_RST_DUR_160US 1
+#define FFE_AB_EXT_PHY_RST_DUR_80US 0
+#define FRF_AB_SWRST_LBN 0
+#define FRF_AB_SWRST_WIDTH 1
+
+/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */
+#define FR_AZ_FATAL_INTR_KER 0x00000230
+#define FRF_CZ_SRAM_PERR_INT_P_KER_EN_LBN 44
+#define FRF_CZ_SRAM_PERR_INT_P_KER_EN_WIDTH 1
+#define FRF_AB_PCI_BUSERR_INT_KER_EN_LBN 43
+#define FRF_AB_PCI_BUSERR_INT_KER_EN_WIDTH 1
+#define FRF_CZ_MBU_PERR_INT_KER_EN_LBN 43
+#define FRF_CZ_MBU_PERR_INT_KER_EN_WIDTH 1
+#define FRF_AZ_SRAM_OOB_INT_KER_EN_LBN 42
+#define FRF_AZ_SRAM_OOB_INT_KER_EN_WIDTH 1
+#define FRF_AZ_BUFID_OOB_INT_KER_EN_LBN 41
+#define FRF_AZ_BUFID_OOB_INT_KER_EN_WIDTH 1
+#define FRF_AZ_MEM_PERR_INT_KER_EN_LBN 40
+#define FRF_AZ_MEM_PERR_INT_KER_EN_WIDTH 1
+#define FRF_AZ_RBUF_OWN_INT_KER_EN_LBN 39
+#define FRF_AZ_RBUF_OWN_INT_KER_EN_WIDTH 1
+#define FRF_AZ_TBUF_OWN_INT_KER_EN_LBN 38
+#define FRF_AZ_TBUF_OWN_INT_KER_EN_WIDTH 1
+#define FRF_AZ_RDESCQ_OWN_INT_KER_EN_LBN 37
+#define FRF_AZ_RDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define FRF_AZ_TDESCQ_OWN_INT_KER_EN_LBN 36
+#define FRF_AZ_TDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define FRF_AZ_EVQ_OWN_INT_KER_EN_LBN 35
+#define FRF_AZ_EVQ_OWN_INT_KER_EN_WIDTH 1
+#define FRF_AZ_EVF_OFLO_INT_KER_EN_LBN 34
+#define FRF_AZ_EVF_OFLO_INT_KER_EN_WIDTH 1
+#define FRF_AZ_ILL_ADR_INT_KER_EN_LBN 33
+#define FRF_AZ_ILL_ADR_INT_KER_EN_WIDTH 1
+#define FRF_AZ_SRM_PERR_INT_KER_EN_LBN 32
+#define FRF_AZ_SRM_PERR_INT_KER_EN_WIDTH 1
+#define FRF_CZ_SRAM_PERR_INT_P_KER_LBN 12
+#define FRF_CZ_SRAM_PERR_INT_P_KER_WIDTH 1
+#define FRF_AB_PCI_BUSERR_INT_KER_LBN 11
+#define FRF_AB_PCI_BUSERR_INT_KER_WIDTH 1
+#define FRF_CZ_MBU_PERR_INT_KER_LBN 11
+#define FRF_CZ_MBU_PERR_INT_KER_WIDTH 1
+#define FRF_AZ_SRAM_OOB_INT_KER_LBN 10
+#define FRF_AZ_SRAM_OOB_INT_KER_WIDTH 1
+#define FRF_AZ_BUFID_DC_OOB_INT_KER_LBN 9
+#define FRF_AZ_BUFID_DC_OOB_INT_KER_WIDTH 1
+#define FRF_AZ_MEM_PERR_INT_KER_LBN 8
+#define FRF_AZ_MEM_PERR_INT_KER_WIDTH 1
+#define FRF_AZ_RBUF_OWN_INT_KER_LBN 7
+#define FRF_AZ_RBUF_OWN_INT_KER_WIDTH 1
+#define FRF_AZ_TBUF_OWN_INT_KER_LBN 6
+#define FRF_AZ_TBUF_OWN_INT_KER_WIDTH 1
+#define FRF_AZ_RDESCQ_OWN_INT_KER_LBN 5
+#define FRF_AZ_RDESCQ_OWN_INT_KER_WIDTH 1
+#define FRF_AZ_TDESCQ_OWN_INT_KER_LBN 4
+#define FRF_AZ_TDESCQ_OWN_INT_KER_WIDTH 1
+#define FRF_AZ_EVQ_OWN_INT_KER_LBN 3
+#define FRF_AZ_EVQ_OWN_INT_KER_WIDTH 1
+#define FRF_AZ_EVF_OFLO_INT_KER_LBN 2
+#define FRF_AZ_EVF_OFLO_INT_KER_WIDTH 1
+#define FRF_AZ_ILL_ADR_INT_KER_LBN 1
+#define FRF_AZ_ILL_ADR_INT_KER_WIDTH 1
+#define FRF_AZ_SRM_PERR_INT_KER_LBN 0
+#define FRF_AZ_SRM_PERR_INT_KER_WIDTH 1
+
+/* FATAL_INTR_REG_CHAR: Fatal interrupt register for Char */
+#define FR_BZ_FATAL_INTR_CHAR 0x00000240
+#define FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_LBN 44
+#define FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_WIDTH 1
+#define FRF_BB_PCI_BUSERR_INT_CHAR_EN_LBN 43
+#define FRF_BB_PCI_BUSERR_INT_CHAR_EN_WIDTH 1
+#define FRF_CZ_MBU_PERR_INT_CHAR_EN_LBN 43
+#define FRF_CZ_MBU_PERR_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_SRAM_OOB_INT_CHAR_EN_LBN 42
+#define FRF_BZ_SRAM_OOB_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_BUFID_OOB_INT_CHAR_EN_LBN 41
+#define FRF_BZ_BUFID_OOB_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_MEM_PERR_INT_CHAR_EN_LBN 40
+#define FRF_BZ_MEM_PERR_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_RBUF_OWN_INT_CHAR_EN_LBN 39
+#define FRF_BZ_RBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_TBUF_OWN_INT_CHAR_EN_LBN 38
+#define FRF_BZ_TBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_LBN 37
+#define FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_LBN 36
+#define FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_EVQ_OWN_INT_CHAR_EN_LBN 35
+#define FRF_BZ_EVQ_OWN_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_EVF_OFLO_INT_CHAR_EN_LBN 34
+#define FRF_BZ_EVF_OFLO_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_ILL_ADR_INT_CHAR_EN_LBN 33
+#define FRF_BZ_ILL_ADR_INT_CHAR_EN_WIDTH 1
+#define FRF_BZ_SRM_PERR_INT_CHAR_EN_LBN 32
+#define FRF_BZ_SRM_PERR_INT_CHAR_EN_WIDTH 1
+#define FRF_CZ_SRAM_PERR_INT_P_CHAR_LBN 12
+#define FRF_CZ_SRAM_PERR_INT_P_CHAR_WIDTH 1
+#define FRF_BB_PCI_BUSERR_INT_CHAR_LBN 11
+#define FRF_BB_PCI_BUSERR_INT_CHAR_WIDTH 1
+#define FRF_CZ_MBU_PERR_INT_CHAR_LBN 11
+#define FRF_CZ_MBU_PERR_INT_CHAR_WIDTH 1
+#define FRF_BZ_SRAM_OOB_INT_CHAR_LBN 10
+#define FRF_BZ_SRAM_OOB_INT_CHAR_WIDTH 1
+#define FRF_BZ_BUFID_DC_OOB_INT_CHAR_LBN 9
+#define FRF_BZ_BUFID_DC_OOB_INT_CHAR_WIDTH 1
+#define FRF_BZ_MEM_PERR_INT_CHAR_LBN 8
+#define FRF_BZ_MEM_PERR_INT_CHAR_WIDTH 1
+#define FRF_BZ_RBUF_OWN_INT_CHAR_LBN 7
+#define FRF_BZ_RBUF_OWN_INT_CHAR_WIDTH 1
+#define FRF_BZ_TBUF_OWN_INT_CHAR_LBN 6
+#define FRF_BZ_TBUF_OWN_INT_CHAR_WIDTH 1
+#define FRF_BZ_RDESCQ_OWN_INT_CHAR_LBN 5
+#define FRF_BZ_RDESCQ_OWN_INT_CHAR_WIDTH 1
+#define FRF_BZ_TDESCQ_OWN_INT_CHAR_LBN 4
+#define FRF_BZ_TDESCQ_OWN_INT_CHAR_WIDTH 1
+#define FRF_BZ_EVQ_OWN_INT_CHAR_LBN 3
+#define FRF_BZ_EVQ_OWN_INT_CHAR_WIDTH 1
+#define FRF_BZ_EVF_OFLO_INT_CHAR_LBN 2
+#define FRF_BZ_EVF_OFLO_INT_CHAR_WIDTH 1
+#define FRF_BZ_ILL_ADR_INT_CHAR_LBN 1
+#define FRF_BZ_ILL_ADR_INT_CHAR_WIDTH 1
+#define FRF_BZ_SRM_PERR_INT_CHAR_LBN 0
+#define FRF_BZ_SRM_PERR_INT_CHAR_WIDTH 1
+
+/* DP_CTRL_REG: Datapath control register */
+#define FR_BZ_DP_CTRL 0x00000250
+#define FRF_BZ_FLS_EVQ_ID_LBN 0
+#define FRF_BZ_FLS_EVQ_ID_WIDTH 12
+
+/* MEM_STAT_REG: Memory status register */
+#define FR_AZ_MEM_STAT 0x00000260
+#define FRF_AB_MEM_PERR_VEC_LBN 53
+#define FRF_AB_MEM_PERR_VEC_WIDTH 38
+#define FRF_AB_MBIST_CORR_LBN 38
+#define FRF_AB_MBIST_CORR_WIDTH 15
+#define FRF_AB_MBIST_ERR_LBN 0
+#define FRF_AB_MBIST_ERR_WIDTH 40
+#define FRF_CZ_MEM_PERR_VEC_LBN 0
+#define FRF_CZ_MEM_PERR_VEC_WIDTH 35
+
+/* CS_DEBUG_REG: Debug register */
+#define FR_AZ_CS_DEBUG 0x00000270
+#define FRF_AB_GLB_DEBUG2_SEL_LBN 50
+#define FRF_AB_GLB_DEBUG2_SEL_WIDTH 3
+#define FRF_AB_DEBUG_BLK_SEL2_LBN 47
+#define FRF_AB_DEBUG_BLK_SEL2_WIDTH 3
+#define FRF_AB_DEBUG_BLK_SEL1_LBN 44
+#define FRF_AB_DEBUG_BLK_SEL1_WIDTH 3
+#define FRF_AB_DEBUG_BLK_SEL0_LBN 41
+#define FRF_AB_DEBUG_BLK_SEL0_WIDTH 3
+#define FRF_CZ_CS_PORT_NUM_LBN 40
+#define FRF_CZ_CS_PORT_NUM_WIDTH 2
+#define FRF_AB_MISC_DEBUG_ADDR_LBN 36
+#define FRF_AB_MISC_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_SERDES_DEBUG_ADDR_LBN 31
+#define FRF_AB_SERDES_DEBUG_ADDR_WIDTH 5
+#define FRF_CZ_CS_PORT_FPE_LBN 1
+#define FRF_CZ_CS_PORT_FPE_WIDTH 35
+#define FRF_AB_EM_DEBUG_ADDR_LBN 26
+#define FRF_AB_EM_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_SR_DEBUG_ADDR_LBN 21
+#define FRF_AB_SR_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_EV_DEBUG_ADDR_LBN 16
+#define FRF_AB_EV_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_RX_DEBUG_ADDR_LBN 11
+#define FRF_AB_RX_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_TX_DEBUG_ADDR_LBN 6
+#define FRF_AB_TX_DEBUG_ADDR_WIDTH 5
+#define FRF_AB_CS_BIU_DEBUG_ADDR_LBN 1
+#define FRF_AB_CS_BIU_DEBUG_ADDR_WIDTH 5
+#define FRF_AZ_CS_DEBUG_EN_LBN 0
+#define FRF_AZ_CS_DEBUG_EN_WIDTH 1
+
+/* DRIVER_REG: Driver scratch register [0-7] */
+#define FR_AZ_DRIVER 0x00000280
+#define FR_AZ_DRIVER_STEP 16
+#define FR_AZ_DRIVER_ROWS 8
+#define FRF_AZ_DRIVER_DW0_LBN 0
+#define FRF_AZ_DRIVER_DW0_WIDTH 32
+
+/* ALTERA_BUILD_REG: Altera build register */
+#define FR_AZ_ALTERA_BUILD 0x00000300
+#define FRF_AZ_ALTERA_BUILD_VER_LBN 0
+#define FRF_AZ_ALTERA_BUILD_VER_WIDTH 32
+
+/* CSR_SPARE_REG: Spare register */
+#define FR_AZ_CSR_SPARE 0x00000310
+#define FRF_AB_MEM_PERR_EN_LBN 64
+#define FRF_AB_MEM_PERR_EN_WIDTH 38
+#define FRF_CZ_MEM_PERR_EN_LBN 64
+#define FRF_CZ_MEM_PERR_EN_WIDTH 35
+#define FRF_AB_MEM_PERR_EN_TX_DATA_LBN 72
+#define FRF_AB_MEM_PERR_EN_TX_DATA_WIDTH 2
+#define FRF_AZ_CSR_SPARE_BITS_LBN 0
+#define FRF_AZ_CSR_SPARE_BITS_WIDTH 32
+
+/* PCIE_SD_CTL0123_REG: PCIE SerDes control register 0 to 3 */
+#define FR_AB_PCIE_SD_CTL0123 0x00000320
+#define FRF_AB_PCIE_TESTSIG_H_LBN 96
+#define FRF_AB_PCIE_TESTSIG_H_WIDTH 19
+#define FRF_AB_PCIE_TESTSIG_L_LBN 64
+#define FRF_AB_PCIE_TESTSIG_L_WIDTH 19
+#define FRF_AB_PCIE_OFFSET_LBN 56
+#define FRF_AB_PCIE_OFFSET_WIDTH 8
+#define FRF_AB_PCIE_OFFSETEN_H_LBN 55
+#define FRF_AB_PCIE_OFFSETEN_H_WIDTH 1
+#define FRF_AB_PCIE_OFFSETEN_L_LBN 54
+#define FRF_AB_PCIE_OFFSETEN_L_WIDTH 1
+#define FRF_AB_PCIE_HIVMODE_H_LBN 53
+#define FRF_AB_PCIE_HIVMODE_H_WIDTH 1
+#define FRF_AB_PCIE_HIVMODE_L_LBN 52
+#define FRF_AB_PCIE_HIVMODE_L_WIDTH 1
+#define FRF_AB_PCIE_PARRESET_H_LBN 51
+#define FRF_AB_PCIE_PARRESET_H_WIDTH 1
+#define FRF_AB_PCIE_PARRESET_L_LBN 50
+#define FRF_AB_PCIE_PARRESET_L_WIDTH 1
+#define FRF_AB_PCIE_LPBKWDRV_H_LBN 49
+#define FRF_AB_PCIE_LPBKWDRV_H_WIDTH 1
+#define FRF_AB_PCIE_LPBKWDRV_L_LBN 48
+#define FRF_AB_PCIE_LPBKWDRV_L_WIDTH 1
+#define FRF_AB_PCIE_LPBK_LBN 40
+#define FRF_AB_PCIE_LPBK_WIDTH 8
+#define FRF_AB_PCIE_PARLPBK_LBN 32
+#define FRF_AB_PCIE_PARLPBK_WIDTH 8
+#define FRF_AB_PCIE_RXTERMADJ_H_LBN 30
+#define FRF_AB_PCIE_RXTERMADJ_H_WIDTH 2
+#define FRF_AB_PCIE_RXTERMADJ_L_LBN 28
+#define FRF_AB_PCIE_RXTERMADJ_L_WIDTH 2
+#define FFE_AB_PCIE_RXTERMADJ_MIN15PCNT 3
+#define FFE_AB_PCIE_RXTERMADJ_PL10PCNT 2
+#define FFE_AB_PCIE_RXTERMADJ_MIN17PCNT 1
+#define FFE_AB_PCIE_RXTERMADJ_NOMNL 0
+#define FRF_AB_PCIE_TXTERMADJ_H_LBN 26
+#define FRF_AB_PCIE_TXTERMADJ_H_WIDTH 2
+#define FRF_AB_PCIE_TXTERMADJ_L_LBN 24
+#define FRF_AB_PCIE_TXTERMADJ_L_WIDTH 2
+#define FFE_AB_PCIE_TXTERMADJ_MIN15PCNT 3
+#define FFE_AB_PCIE_TXTERMADJ_PL10PCNT 2
+#define FFE_AB_PCIE_TXTERMADJ_MIN17PCNT 1
+#define FFE_AB_PCIE_TXTERMADJ_NOMNL 0
+#define FRF_AB_PCIE_RXEQCTL_H_LBN 18
+#define FRF_AB_PCIE_RXEQCTL_H_WIDTH 2
+#define FRF_AB_PCIE_RXEQCTL_L_LBN 16
+#define FRF_AB_PCIE_RXEQCTL_L_WIDTH 2
+#define FFE_AB_PCIE_RXEQCTL_OFF_ALT 3
+#define FFE_AB_PCIE_RXEQCTL_OFF 2
+#define FFE_AB_PCIE_RXEQCTL_MIN 1
+#define FFE_AB_PCIE_RXEQCTL_MAX 0
+#define FRF_AB_PCIE_HIDRV_LBN 8
+#define FRF_AB_PCIE_HIDRV_WIDTH 8
+#define FRF_AB_PCIE_LODRV_LBN 0
+#define FRF_AB_PCIE_LODRV_WIDTH 8
+
+/* PCIE_SD_CTL45_REG: PCIE SerDes control register 4 and 5 */
+#define FR_AB_PCIE_SD_CTL45 0x00000330
+#define FRF_AB_PCIE_DTX7_LBN 60
+#define FRF_AB_PCIE_DTX7_WIDTH 4
+#define FRF_AB_PCIE_DTX6_LBN 56
+#define FRF_AB_PCIE_DTX6_WIDTH 4
+#define FRF_AB_PCIE_DTX5_LBN 52
+#define FRF_AB_PCIE_DTX5_WIDTH 4
+#define FRF_AB_PCIE_DTX4_LBN 48
+#define FRF_AB_PCIE_DTX4_WIDTH 4
+#define FRF_AB_PCIE_DTX3_LBN 44
+#define FRF_AB_PCIE_DTX3_WIDTH 4
+#define FRF_AB_PCIE_DTX2_LBN 40
+#define FRF_AB_PCIE_DTX2_WIDTH 4
+#define FRF_AB_PCIE_DTX1_LBN 36
+#define FRF_AB_PCIE_DTX1_WIDTH 4
+#define FRF_AB_PCIE_DTX0_LBN 32
+#define FRF_AB_PCIE_DTX0_WIDTH 4
+#define FRF_AB_PCIE_DEQ7_LBN 28
+#define FRF_AB_PCIE_DEQ7_WIDTH 4
+#define FRF_AB_PCIE_DEQ6_LBN 24
+#define FRF_AB_PCIE_DEQ6_WIDTH 4
+#define FRF_AB_PCIE_DEQ5_LBN 20
+#define FRF_AB_PCIE_DEQ5_WIDTH 4
+#define FRF_AB_PCIE_DEQ4_LBN 16
+#define FRF_AB_PCIE_DEQ4_WIDTH 4
+#define FRF_AB_PCIE_DEQ3_LBN 12
+#define FRF_AB_PCIE_DEQ3_WIDTH 4
+#define FRF_AB_PCIE_DEQ2_LBN 8
+#define FRF_AB_PCIE_DEQ2_WIDTH 4
+#define FRF_AB_PCIE_DEQ1_LBN 4
+#define FRF_AB_PCIE_DEQ1_WIDTH 4
+#define FRF_AB_PCIE_DEQ0_LBN 0
+#define FRF_AB_PCIE_DEQ0_WIDTH 4
+
+/* PCIE_PCS_CTL_STAT_REG: PCIE PCS control and status register */
+#define FR_AB_PCIE_PCS_CTL_STAT 0x00000340
+#define FRF_AB_PCIE_PRBSERRCOUNT0_H_LBN 52
+#define FRF_AB_PCIE_PRBSERRCOUNT0_H_WIDTH 4
+#define FRF_AB_PCIE_PRBSERRCOUNT0_L_LBN 48
+#define FRF_AB_PCIE_PRBSERRCOUNT0_L_WIDTH 4
+#define FRF_AB_PCIE_PRBSERR_LBN 40
+#define FRF_AB_PCIE_PRBSERR_WIDTH 8
+#define FRF_AB_PCIE_PRBSERRH0_LBN 32
+#define FRF_AB_PCIE_PRBSERRH0_WIDTH 8
+#define FRF_AB_PCIE_FASTINIT_H_LBN 15
+#define FRF_AB_PCIE_FASTINIT_H_WIDTH 1
+#define FRF_AB_PCIE_FASTINIT_L_LBN 14
+#define FRF_AB_PCIE_FASTINIT_L_WIDTH 1
+#define FRF_AB_PCIE_CTCDISABLE_H_LBN 13
+#define FRF_AB_PCIE_CTCDISABLE_H_WIDTH 1
+#define FRF_AB_PCIE_CTCDISABLE_L_LBN 12
+#define FRF_AB_PCIE_CTCDISABLE_L_WIDTH 1
+#define FRF_AB_PCIE_PRBSSYNC_H_LBN 11
+#define FRF_AB_PCIE_PRBSSYNC_H_WIDTH 1
+#define FRF_AB_PCIE_PRBSSYNC_L_LBN 10
+#define FRF_AB_PCIE_PRBSSYNC_L_WIDTH 1
+#define FRF_AB_PCIE_PRBSERRACK_H_LBN 9
+#define FRF_AB_PCIE_PRBSERRACK_H_WIDTH 1
+#define FRF_AB_PCIE_PRBSERRACK_L_LBN 8
+#define FRF_AB_PCIE_PRBSERRACK_L_WIDTH 1
+#define FRF_AB_PCIE_PRBSSEL_LBN 0
+#define FRF_AB_PCIE_PRBSSEL_WIDTH 8
+
+/* DEBUG_DATA_OUT_REG: Live Debug and Debug 2 out ports */
+#define FR_BB_DEBUG_DATA_OUT 0x00000350
+#define FRF_BB_DEBUG2_PORT_LBN 25
+#define FRF_BB_DEBUG2_PORT_WIDTH 15
+#define FRF_BB_DEBUG1_PORT_LBN 0
+#define FRF_BB_DEBUG1_PORT_WIDTH 25
+
+/* EVQ_RPTR_REGP0: Event queue read pointer register */
+#define FR_BZ_EVQ_RPTR_P0 0x00000400
+#define FR_BZ_EVQ_RPTR_P0_STEP 8192
+#define FR_BZ_EVQ_RPTR_P0_ROWS 1024
+/* EVQ_RPTR_REG_KER: Event queue read pointer register */
+#define FR_AA_EVQ_RPTR_KER 0x00011b00
+#define FR_AA_EVQ_RPTR_KER_STEP 4
+#define FR_AA_EVQ_RPTR_KER_ROWS 4
+/* EVQ_RPTR_REG: Event queue read pointer register */
+#define FR_BZ_EVQ_RPTR 0x00fa0000
+#define FR_BZ_EVQ_RPTR_STEP 16
+#define FR_BB_EVQ_RPTR_ROWS 4096
+#define FR_CZ_EVQ_RPTR_ROWS 1024
+/* EVQ_RPTR_REGP123: Event queue read pointer register */
+#define FR_BB_EVQ_RPTR_P123 0x01000400
+#define FR_BB_EVQ_RPTR_P123_STEP 8192
+#define FR_BB_EVQ_RPTR_P123_ROWS 3072
+#define FRF_AZ_EVQ_RPTR_VLD_LBN 15
+#define FRF_AZ_EVQ_RPTR_VLD_WIDTH 1
+#define FRF_AZ_EVQ_RPTR_LBN 0
+#define FRF_AZ_EVQ_RPTR_WIDTH 15
+
+/* TIMER_COMMAND_REGP0: Timer Command Registers */
+#define FR_BZ_TIMER_COMMAND_P0 0x00000420
+#define FR_BZ_TIMER_COMMAND_P0_STEP 8192
+#define FR_BZ_TIMER_COMMAND_P0_ROWS 1024
+/* TIMER_COMMAND_REG_KER: Timer Command Registers */
+#define FR_AA_TIMER_COMMAND_KER 0x00000420
+#define FR_AA_TIMER_COMMAND_KER_STEP 8192
+#define FR_AA_TIMER_COMMAND_KER_ROWS 4
+/* TIMER_COMMAND_REGP123: Timer Command Registers */
+#define FR_BB_TIMER_COMMAND_P123 0x01000420
+#define FR_BB_TIMER_COMMAND_P123_STEP 8192
+#define FR_BB_TIMER_COMMAND_P123_ROWS 3072
+#define FRF_CZ_TC_TIMER_MODE_LBN 14
+#define FRF_CZ_TC_TIMER_MODE_WIDTH 2
+#define FRF_AB_TC_TIMER_MODE_LBN 12
+#define FRF_AB_TC_TIMER_MODE_WIDTH 2
+#define FRF_CZ_TC_TIMER_VAL_LBN 0
+#define FRF_CZ_TC_TIMER_VAL_WIDTH 14
+#define FRF_AB_TC_TIMER_VAL_LBN 0
+#define FRF_AB_TC_TIMER_VAL_WIDTH 12
+
+/* DRV_EV_REG: Driver generated event register */
+#define FR_AZ_DRV_EV 0x00000440
+#define FRF_AZ_DRV_EV_QID_LBN 64
+#define FRF_AZ_DRV_EV_QID_WIDTH 12
+#define FRF_AZ_DRV_EV_DATA_LBN 0
+#define FRF_AZ_DRV_EV_DATA_WIDTH 64
+
+/* EVQ_CTL_REG: Event queue control register */
+#define FR_AZ_EVQ_CTL 0x00000450
+#define FRF_CZ_RX_EVQ_WAKEUP_MASK_LBN 15
+#define FRF_CZ_RX_EVQ_WAKEUP_MASK_WIDTH 10
+#define FRF_BB_RX_EVQ_WAKEUP_MASK_LBN 15
+#define FRF_BB_RX_EVQ_WAKEUP_MASK_WIDTH 6
+#define FRF_AZ_EVQ_OWNERR_CTL_LBN 14
+#define FRF_AZ_EVQ_OWNERR_CTL_WIDTH 1
+#define FRF_AZ_EVQ_FIFO_AF_TH_LBN 7
+#define FRF_AZ_EVQ_FIFO_AF_TH_WIDTH 7
+#define FRF_AZ_EVQ_FIFO_NOTAF_TH_LBN 0
+#define FRF_AZ_EVQ_FIFO_NOTAF_TH_WIDTH 7
+
+/* EVQ_CNT1_REG: Event counter 1 register */
+#define FR_AZ_EVQ_CNT1 0x00000460
+#define FRF_AZ_EVQ_CNT_PRE_FIFO_LBN 120
+#define FRF_AZ_EVQ_CNT_PRE_FIFO_WIDTH 7
+#define FRF_AZ_EVQ_CNT_TOBIU_LBN 100
+#define FRF_AZ_EVQ_CNT_TOBIU_WIDTH 20
+#define FRF_AZ_EVQ_TX_REQ_CNT_LBN 80
+#define FRF_AZ_EVQ_TX_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_RX_REQ_CNT_LBN 60
+#define FRF_AZ_EVQ_RX_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_EM_REQ_CNT_LBN 40
+#define FRF_AZ_EVQ_EM_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_CSR_REQ_CNT_LBN 20
+#define FRF_AZ_EVQ_CSR_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_ERR_REQ_CNT_LBN 0
+#define FRF_AZ_EVQ_ERR_REQ_CNT_WIDTH 20
+
+/* EVQ_CNT2_REG: Event counter 2 register */
+#define FR_AZ_EVQ_CNT2 0x00000470
+#define FRF_AZ_EVQ_UPD_REQ_CNT_LBN 104
+#define FRF_AZ_EVQ_UPD_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_CLR_REQ_CNT_LBN 84
+#define FRF_AZ_EVQ_CLR_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_RDY_CNT_LBN 80
+#define FRF_AZ_EVQ_RDY_CNT_WIDTH 4
+#define FRF_AZ_EVQ_WU_REQ_CNT_LBN 60
+#define FRF_AZ_EVQ_WU_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_WET_REQ_CNT_LBN 40
+#define FRF_AZ_EVQ_WET_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_INIT_REQ_CNT_LBN 20
+#define FRF_AZ_EVQ_INIT_REQ_CNT_WIDTH 20
+#define FRF_AZ_EVQ_TM_REQ_CNT_LBN 0
+#define FRF_AZ_EVQ_TM_REQ_CNT_WIDTH 20
+
+/* USR_EV_REG: Event mailbox register */
+#define FR_CZ_USR_EV 0x00000540
+#define FR_CZ_USR_EV_STEP 8192
+#define FR_CZ_USR_EV_ROWS 1024
+#define FRF_CZ_USR_EV_DATA_LBN 0
+#define FRF_CZ_USR_EV_DATA_WIDTH 32
+
+/* BUF_TBL_CFG_REG: Buffer table configuration register */
+#define FR_AZ_BUF_TBL_CFG 0x00000600
+#define FRF_AZ_BUF_TBL_MODE_LBN 3
+#define FRF_AZ_BUF_TBL_MODE_WIDTH 1
+
+/* SRM_RX_DC_CFG_REG: SRAM receive descriptor cache configuration register */
+#define FR_AZ_SRM_RX_DC_CFG 0x00000610
+#define FRF_AZ_SRM_CLK_TMP_EN_LBN 21
+#define FRF_AZ_SRM_CLK_TMP_EN_WIDTH 1
+#define FRF_AZ_SRM_RX_DC_BASE_ADR_LBN 0
+#define FRF_AZ_SRM_RX_DC_BASE_ADR_WIDTH 21
+
+/* SRM_TX_DC_CFG_REG: SRAM transmit descriptor cache configuration register */
+#define FR_AZ_SRM_TX_DC_CFG 0x00000620
+#define FRF_AZ_SRM_TX_DC_BASE_ADR_LBN 0
+#define FRF_AZ_SRM_TX_DC_BASE_ADR_WIDTH 21
+
+/* SRM_CFG_REG: SRAM configuration register */
+#define FR_AZ_SRM_CFG 0x00000630
+#define FRF_AZ_SRM_OOB_ADR_INTEN_LBN 5
+#define FRF_AZ_SRM_OOB_ADR_INTEN_WIDTH 1
+#define FRF_AZ_SRM_OOB_BUF_INTEN_LBN 4
+#define FRF_AZ_SRM_OOB_BUF_INTEN_WIDTH 1
+#define FRF_AZ_SRM_INIT_EN_LBN 3
+#define FRF_AZ_SRM_INIT_EN_WIDTH 1
+#define FRF_AZ_SRM_NUM_BANK_LBN 2
+#define FRF_AZ_SRM_NUM_BANK_WIDTH 1
+#define FRF_AZ_SRM_BANK_SIZE_LBN 0
+#define FRF_AZ_SRM_BANK_SIZE_WIDTH 2
+
+/* BUF_TBL_UPD_REG: Buffer table update register */
+#define FR_AZ_BUF_TBL_UPD 0x00000650
+#define FRF_AZ_BUF_UPD_CMD_LBN 63
+#define FRF_AZ_BUF_UPD_CMD_WIDTH 1
+#define FRF_AZ_BUF_CLR_CMD_LBN 62
+#define FRF_AZ_BUF_CLR_CMD_WIDTH 1
+#define FRF_AZ_BUF_CLR_END_ID_LBN 32
+#define FRF_AZ_BUF_CLR_END_ID_WIDTH 20
+#define FRF_AZ_BUF_CLR_START_ID_LBN 0
+#define FRF_AZ_BUF_CLR_START_ID_WIDTH 20
+
+/* SRM_UPD_EVQ_REG: Buffer table update register */
+#define FR_AZ_SRM_UPD_EVQ 0x00000660
+#define FRF_AZ_SRM_UPD_EVQ_ID_LBN 0
+#define FRF_AZ_SRM_UPD_EVQ_ID_WIDTH 12
+
+/* SRAM_PARITY_REG: SRAM parity register. */
+#define FR_AZ_SRAM_PARITY 0x00000670
+#define FRF_CZ_BYPASS_ECC_LBN 3
+#define FRF_CZ_BYPASS_ECC_WIDTH 1
+#define FRF_CZ_SEC_INT_LBN 2
+#define FRF_CZ_SEC_INT_WIDTH 1
+#define FRF_CZ_FORCE_SRAM_DOUBLE_ERR_LBN 1
+#define FRF_CZ_FORCE_SRAM_DOUBLE_ERR_WIDTH 1
+#define FRF_AB_FORCE_SRAM_PERR_LBN 0
+#define FRF_AB_FORCE_SRAM_PERR_WIDTH 1
+#define FRF_CZ_FORCE_SRAM_SINGLE_ERR_LBN 0
+#define FRF_CZ_FORCE_SRAM_SINGLE_ERR_WIDTH 1
+
+/* RX_CFG_REG: Receive configuration register */
+#define FR_AZ_RX_CFG 0x00000800
+#define FRF_CZ_RX_MIN_KBUF_SIZE_LBN 72
+#define FRF_CZ_RX_MIN_KBUF_SIZE_WIDTH 14
+#define FRF_CZ_RX_HDR_SPLIT_EN_LBN 71
+#define FRF_CZ_RX_HDR_SPLIT_EN_WIDTH 1
+#define FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_LBN 62
+#define FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH 9
+#define FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_LBN 53
+#define FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH 9
+#define FRF_CZ_RX_PRE_RFF_IPG_LBN 49
+#define FRF_CZ_RX_PRE_RFF_IPG_WIDTH 4
+#define FRF_BZ_RX_TCP_SUP_LBN 48
+#define FRF_BZ_RX_TCP_SUP_WIDTH 1
+#define FRF_BZ_RX_INGR_EN_LBN 47
+#define FRF_BZ_RX_INGR_EN_WIDTH 1
+#define FRF_BZ_RX_IP_HASH_LBN 46
+#define FRF_BZ_RX_IP_HASH_WIDTH 1
+#define FRF_BZ_RX_HASH_ALG_LBN 45
+#define FRF_BZ_RX_HASH_ALG_WIDTH 1
+#define FRF_BZ_RX_HASH_INSRT_HDR_LBN 44
+#define FRF_BZ_RX_HASH_INSRT_HDR_WIDTH 1
+#define FRF_BZ_RX_DESC_PUSH_EN_LBN 43
+#define FRF_BZ_RX_DESC_PUSH_EN_WIDTH 1
+#define FRF_BZ_RX_RDW_PATCH_EN_LBN 42
+#define FRF_BZ_RX_RDW_PATCH_EN_WIDTH 1
+#define FRF_BB_RX_PCI_BURST_SIZE_LBN 39
+#define FRF_BB_RX_PCI_BURST_SIZE_WIDTH 3
+#define FRF_BZ_RX_OWNERR_CTL_LBN 38
+#define FRF_BZ_RX_OWNERR_CTL_WIDTH 1
+#define FRF_BZ_RX_XON_TX_TH_LBN 33
+#define FRF_BZ_RX_XON_TX_TH_WIDTH 5
+#define FRF_AA_RX_DESC_PUSH_EN_LBN 35
+#define FRF_AA_RX_DESC_PUSH_EN_WIDTH 1
+#define FRF_AA_RX_RDW_PATCH_EN_LBN 34
+#define FRF_AA_RX_RDW_PATCH_EN_WIDTH 1
+#define FRF_AA_RX_PCI_BURST_SIZE_LBN 31
+#define FRF_AA_RX_PCI_BURST_SIZE_WIDTH 3
+#define FRF_BZ_RX_XOFF_TX_TH_LBN 28
+#define FRF_BZ_RX_XOFF_TX_TH_WIDTH 5
+#define FRF_AA_RX_OWNERR_CTL_LBN 30
+#define FRF_AA_RX_OWNERR_CTL_WIDTH 1
+#define FRF_AA_RX_XON_TX_TH_LBN 25
+#define FRF_AA_RX_XON_TX_TH_WIDTH 5
+#define FRF_BZ_RX_USR_BUF_SIZE_LBN 19
+#define FRF_BZ_RX_USR_BUF_SIZE_WIDTH 9
+#define FRF_AA_RX_XOFF_TX_TH_LBN 20
+#define FRF_AA_RX_XOFF_TX_TH_WIDTH 5
+#define FRF_AA_RX_USR_BUF_SIZE_LBN 11
+#define FRF_AA_RX_USR_BUF_SIZE_WIDTH 9
+#define FRF_BZ_RX_XON_MAC_TH_LBN 10
+#define FRF_BZ_RX_XON_MAC_TH_WIDTH 9
+#define FRF_AA_RX_XON_MAC_TH_LBN 6
+#define FRF_AA_RX_XON_MAC_TH_WIDTH 5
+#define FRF_BZ_RX_XOFF_MAC_TH_LBN 1
+#define FRF_BZ_RX_XOFF_MAC_TH_WIDTH 9
+#define FRF_AA_RX_XOFF_MAC_TH_LBN 1
+#define FRF_AA_RX_XOFF_MAC_TH_WIDTH 5
+#define FRF_AZ_RX_XOFF_MAC_EN_LBN 0
+#define FRF_AZ_RX_XOFF_MAC_EN_WIDTH 1
+
+/* RX_FILTER_CTL_REG: Receive filter control registers */
+#define FR_BZ_RX_FILTER_CTL 0x00000810
+#define FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_LBN 94
+#define FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_WIDTH 8
+#define FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_LBN 86
+#define FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_WIDTH 8
+#define FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_LBN 85
+#define FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_WIDTH 1
+#define FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_LBN 69
+#define FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_WIDTH 16
+#define FRF_CZ_MULTICAST_NOMATCH_Q_ID_LBN 57
+#define FRF_CZ_MULTICAST_NOMATCH_Q_ID_WIDTH 12
+#define FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_LBN 56
+#define FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_LBN 55
+#define FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define FRF_CZ_UNICAST_NOMATCH_Q_ID_LBN 43
+#define FRF_CZ_UNICAST_NOMATCH_Q_ID_WIDTH 12
+#define FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_LBN 42
+#define FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_LBN 41
+#define FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_LBN 40
+#define FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_WIDTH 1
+#define FRF_BZ_UDP_FULL_SRCH_LIMIT_LBN 32
+#define FRF_BZ_UDP_FULL_SRCH_LIMIT_WIDTH 8
+#define FRF_BZ_NUM_KER_LBN 24
+#define FRF_BZ_NUM_KER_WIDTH 2
+#define FRF_BZ_UDP_WILD_SRCH_LIMIT_LBN 16
+#define FRF_BZ_UDP_WILD_SRCH_LIMIT_WIDTH 8
+#define FRF_BZ_TCP_WILD_SRCH_LIMIT_LBN 8
+#define FRF_BZ_TCP_WILD_SRCH_LIMIT_WIDTH 8
+#define FRF_BZ_TCP_FULL_SRCH_LIMIT_LBN 0
+#define FRF_BZ_TCP_FULL_SRCH_LIMIT_WIDTH 8
+
+/* RX_FLUSH_DESCQ_REG: Receive flush descriptor queue register */
+#define FR_AZ_RX_FLUSH_DESCQ 0x00000820
+#define FRF_AZ_RX_FLUSH_DESCQ_CMD_LBN 24
+#define FRF_AZ_RX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FRF_AZ_RX_FLUSH_DESCQ_LBN 0
+#define FRF_AZ_RX_FLUSH_DESCQ_WIDTH 12
+
+/* RX_DESC_UPD_REGP0: Receive descriptor update register. */
+#define FR_BZ_RX_DESC_UPD_P0 0x00000830
+#define FR_BZ_RX_DESC_UPD_P0_STEP 8192
+#define FR_BZ_RX_DESC_UPD_P0_ROWS 1024
+/* RX_DESC_UPD_REG_KER: Receive descriptor update register. */
+#define FR_AA_RX_DESC_UPD_KER 0x00000830
+#define FR_AA_RX_DESC_UPD_KER_STEP 8192
+#define FR_AA_RX_DESC_UPD_KER_ROWS 4
+/* RX_DESC_UPD_REGP123: Receive descriptor update register. */
+#define FR_BB_RX_DESC_UPD_P123 0x01000830
+#define FR_BB_RX_DESC_UPD_P123_STEP 8192
+#define FR_BB_RX_DESC_UPD_P123_ROWS 3072
+#define FRF_AZ_RX_DESC_WPTR_LBN 96
+#define FRF_AZ_RX_DESC_WPTR_WIDTH 12
+#define FRF_AZ_RX_DESC_PUSH_CMD_LBN 95
+#define FRF_AZ_RX_DESC_PUSH_CMD_WIDTH 1
+#define FRF_AZ_RX_DESC_LBN 0
+#define FRF_AZ_RX_DESC_WIDTH 64
+
+/* RX_DC_CFG_REG: Receive descriptor cache configuration register */
+#define FR_AZ_RX_DC_CFG 0x00000840
+#define FRF_AB_RX_MAX_PF_LBN 2
+#define FRF_AB_RX_MAX_PF_WIDTH 2
+#define FRF_AZ_RX_DC_SIZE_LBN 0
+#define FRF_AZ_RX_DC_SIZE_WIDTH 2
+#define FFE_AZ_RX_DC_SIZE_64 3
+#define FFE_AZ_RX_DC_SIZE_32 2
+#define FFE_AZ_RX_DC_SIZE_16 1
+#define FFE_AZ_RX_DC_SIZE_8 0
+
+/* RX_DC_PF_WM_REG: Receive descriptor cache pre-fetch watermark register */
+#define FR_AZ_RX_DC_PF_WM 0x00000850
+#define FRF_AZ_RX_DC_PF_HWM_LBN 6
+#define FRF_AZ_RX_DC_PF_HWM_WIDTH 6
+#define FRF_AZ_RX_DC_PF_LWM_LBN 0
+#define FRF_AZ_RX_DC_PF_LWM_WIDTH 6
+
+/* RX_RSS_TKEY_REG: RSS Toeplitz hash key */
+#define FR_BZ_RX_RSS_TKEY 0x00000860
+#define FRF_BZ_RX_RSS_TKEY_HI_LBN 64
+#define FRF_BZ_RX_RSS_TKEY_HI_WIDTH 64
+#define FRF_BZ_RX_RSS_TKEY_LO_LBN 0
+#define FRF_BZ_RX_RSS_TKEY_LO_WIDTH 64
+
+/* RX_NODESC_DROP_REG: Receive dropped packet counter register */
+#define FR_AZ_RX_NODESC_DROP 0x00000880
+#define FRF_CZ_RX_NODESC_DROP_CNT_LBN 0
+#define FRF_CZ_RX_NODESC_DROP_CNT_WIDTH 32
+#define FRF_AB_RX_NODESC_DROP_CNT_LBN 0
+#define FRF_AB_RX_NODESC_DROP_CNT_WIDTH 16
+
+/* RX_SELF_RST_REG: Receive self reset register */
+#define FR_AA_RX_SELF_RST 0x00000890
+#define FRF_AA_RX_ISCSI_DIS_LBN 17
+#define FRF_AA_RX_ISCSI_DIS_WIDTH 1
+#define FRF_AA_RX_SW_RST_REG_LBN 16
+#define FRF_AA_RX_SW_RST_REG_WIDTH 1
+#define FRF_AA_RX_NODESC_WAIT_DIS_LBN 9
+#define FRF_AA_RX_NODESC_WAIT_DIS_WIDTH 1
+#define FRF_AA_RX_SELF_RST_EN_LBN 8
+#define FRF_AA_RX_SELF_RST_EN_WIDTH 1
+#define FRF_AA_RX_MAX_PF_LAT_LBN 4
+#define FRF_AA_RX_MAX_PF_LAT_WIDTH 4
+#define FRF_AA_RX_MAX_LU_LAT_LBN 0
+#define FRF_AA_RX_MAX_LU_LAT_WIDTH 4
+
+/* RX_DEBUG_REG: undocumented register */
+#define FR_AZ_RX_DEBUG 0x000008a0
+#define FRF_AZ_RX_DEBUG_LBN 0
+#define FRF_AZ_RX_DEBUG_WIDTH 64
+
+/* RX_PUSH_DROP_REG: Receive descriptor push dropped counter register */
+#define FR_AZ_RX_PUSH_DROP 0x000008b0
+#define FRF_AZ_RX_PUSH_DROP_CNT_LBN 0
+#define FRF_AZ_RX_PUSH_DROP_CNT_WIDTH 32
+
+/* RX_RSS_IPV6_REG1: IPv6 RSS Toeplitz hash key low bytes */
+#define FR_CZ_RX_RSS_IPV6_REG1 0x000008d0
+#define FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN 0
+#define FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH 128
+
+/* RX_RSS_IPV6_REG2: IPv6 RSS Toeplitz hash key middle bytes */
+#define FR_CZ_RX_RSS_IPV6_REG2 0x000008e0
+#define FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN 0
+#define FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH 128
+
+/* RX_RSS_IPV6_REG3: IPv6 RSS Toeplitz hash key upper bytes and IPv6 RSS settings */
+#define FR_CZ_RX_RSS_IPV6_REG3 0x000008f0
+#define FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_LBN 66
+#define FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_WIDTH 1
+#define FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_LBN 65
+#define FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_WIDTH 1
+#define FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_LBN 64
+#define FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_WIDTH 1
+#define FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN 0
+#define FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH 64
+
+/* TX_FLUSH_DESCQ_REG: Transmit flush descriptor queue register */
+#define FR_AZ_TX_FLUSH_DESCQ 0x00000a00
+#define FRF_AZ_TX_FLUSH_DESCQ_CMD_LBN 12
+#define FRF_AZ_TX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FRF_AZ_TX_FLUSH_DESCQ_LBN 0
+#define FRF_AZ_TX_FLUSH_DESCQ_WIDTH 12
+
+/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */
+#define FR_BZ_TX_DESC_UPD_P0 0x00000a10
+#define FR_BZ_TX_DESC_UPD_P0_STEP 8192
+#define FR_BZ_TX_DESC_UPD_P0_ROWS 1024
+/* TX_DESC_UPD_REG_KER: Transmit descriptor update register. */
+#define FR_AA_TX_DESC_UPD_KER 0x00000a10
+#define FR_AA_TX_DESC_UPD_KER_STEP 8192
+#define FR_AA_TX_DESC_UPD_KER_ROWS 8
+/* TX_DESC_UPD_REGP123: Transmit descriptor update register. */
+#define FR_BB_TX_DESC_UPD_P123 0x01000a10
+#define FR_BB_TX_DESC_UPD_P123_STEP 8192
+#define FR_BB_TX_DESC_UPD_P123_ROWS 3072
+#define FRF_AZ_TX_DESC_WPTR_LBN 96
+#define FRF_AZ_TX_DESC_WPTR_WIDTH 12
+#define FRF_AZ_TX_DESC_PUSH_CMD_LBN 95
+#define FRF_AZ_TX_DESC_PUSH_CMD_WIDTH 1
+#define FRF_AZ_TX_DESC_LBN 0
+#define FRF_AZ_TX_DESC_WIDTH 95
+
+/* TX_DC_CFG_REG: Transmit descriptor cache configuration register */
+#define FR_AZ_TX_DC_CFG 0x00000a20
+#define FRF_AZ_TX_DC_SIZE_LBN 0
+#define FRF_AZ_TX_DC_SIZE_WIDTH 2
+#define FFE_AZ_TX_DC_SIZE_32 2
+#define FFE_AZ_TX_DC_SIZE_16 1
+#define FFE_AZ_TX_DC_SIZE_8 0
+
+/* TX_CHKSM_CFG_REG: Transmit checksum configuration register */
+#define FR_AA_TX_CHKSM_CFG 0x00000a30
+#define FRF_AA_TX_Q_CHKSM_DIS_96_127_LBN 96
+#define FRF_AA_TX_Q_CHKSM_DIS_96_127_WIDTH 32
+#define FRF_AA_TX_Q_CHKSM_DIS_64_95_LBN 64
+#define FRF_AA_TX_Q_CHKSM_DIS_64_95_WIDTH 32
+#define FRF_AA_TX_Q_CHKSM_DIS_32_63_LBN 32
+#define FRF_AA_TX_Q_CHKSM_DIS_32_63_WIDTH 32
+#define FRF_AA_TX_Q_CHKSM_DIS_0_31_LBN 0
+#define FRF_AA_TX_Q_CHKSM_DIS_0_31_WIDTH 32
+
+/* TX_CFG_REG: Transmit configuration register */
+#define FR_AZ_TX_CFG 0x00000a50
+#define FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_LBN 114
+#define FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_WIDTH 8
+#define FRF_CZ_TX_FILTER_TEST_MODE_BIT_LBN 113
+#define FRF_CZ_TX_FILTER_TEST_MODE_BIT_WIDTH 1
+#define FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_LBN 105
+#define FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_LBN 97
+#define FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_LBN 89
+#define FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_LBN 81
+#define FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_LBN 73
+#define FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_LBN 65
+#define FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_LBN 64
+#define FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_WIDTH 1
+#define FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_LBN 48
+#define FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_WIDTH 16
+#define FRF_CZ_TX_FILTER_EN_BIT_LBN 47
+#define FRF_CZ_TX_FILTER_EN_BIT_WIDTH 1
+#define FRF_AZ_TX_IP_ID_P0_OFS_LBN 16
+#define FRF_AZ_TX_IP_ID_P0_OFS_WIDTH 15
+#define FRF_AZ_TX_NO_EOP_DISC_EN_LBN 5
+#define FRF_AZ_TX_NO_EOP_DISC_EN_WIDTH 1
+#define FRF_AZ_TX_P1_PRI_EN_LBN 4
+#define FRF_AZ_TX_P1_PRI_EN_WIDTH 1
+#define FRF_AZ_TX_OWNERR_CTL_LBN 2
+#define FRF_AZ_TX_OWNERR_CTL_WIDTH 1
+#define FRF_AA_TX_NON_IP_DROP_DIS_LBN 1
+#define FRF_AA_TX_NON_IP_DROP_DIS_WIDTH 1
+#define FRF_AZ_TX_IP_ID_REP_EN_LBN 0
+#define FRF_AZ_TX_IP_ID_REP_EN_WIDTH 1
+
+/* TX_PUSH_DROP_REG: Transmit push dropped register */
+#define FR_AZ_TX_PUSH_DROP 0x00000a60
+#define FRF_AZ_TX_PUSH_DROP_CNT_LBN 0
+#define FRF_AZ_TX_PUSH_DROP_CNT_WIDTH 32
+
+/* TX_RESERVED_REG: Transmit configuration register */
+#define FR_AZ_TX_RESERVED 0x00000a80
+#define FRF_AZ_TX_EVT_CNT_LBN 121
+#define FRF_AZ_TX_EVT_CNT_WIDTH 7
+#define FRF_AZ_TX_PREF_AGE_CNT_LBN 119
+#define FRF_AZ_TX_PREF_AGE_CNT_WIDTH 2
+#define FRF_AZ_TX_RD_COMP_TMR_LBN 96
+#define FRF_AZ_TX_RD_COMP_TMR_WIDTH 23
+#define FRF_AZ_TX_PUSH_EN_LBN 89
+#define FRF_AZ_TX_PUSH_EN_WIDTH 1
+#define FRF_AZ_TX_PUSH_CHK_DIS_LBN 88
+#define FRF_AZ_TX_PUSH_CHK_DIS_WIDTH 1
+#define FRF_AZ_TX_D_FF_FULL_P0_LBN 85
+#define FRF_AZ_TX_D_FF_FULL_P0_WIDTH 1
+#define FRF_AZ_TX_DMAR_ST_P0_LBN 81
+#define FRF_AZ_TX_DMAR_ST_P0_WIDTH 1
+#define FRF_AZ_TX_DMAQ_ST_LBN 78
+#define FRF_AZ_TX_DMAQ_ST_WIDTH 1
+#define FRF_AZ_TX_RX_SPACER_LBN 64
+#define FRF_AZ_TX_RX_SPACER_WIDTH 8
+#define FRF_AZ_TX_DROP_ABORT_EN_LBN 60
+#define FRF_AZ_TX_DROP_ABORT_EN_WIDTH 1
+#define FRF_AZ_TX_SOFT_EVT_EN_LBN 59
+#define FRF_AZ_TX_SOFT_EVT_EN_WIDTH 1
+#define FRF_AZ_TX_PS_EVT_DIS_LBN 58
+#define FRF_AZ_TX_PS_EVT_DIS_WIDTH 1
+#define FRF_AZ_TX_RX_SPACER_EN_LBN 57
+#define FRF_AZ_TX_RX_SPACER_EN_WIDTH 1
+#define FRF_AZ_TX_XP_TIMER_LBN 52
+#define FRF_AZ_TX_XP_TIMER_WIDTH 5
+#define FRF_AZ_TX_PREF_SPACER_LBN 44
+#define FRF_AZ_TX_PREF_SPACER_WIDTH 8
+#define FRF_AZ_TX_PREF_WD_TMR_LBN 22
+#define FRF_AZ_TX_PREF_WD_TMR_WIDTH 22
+#define FRF_AZ_TX_ONLY1TAG_LBN 21
+#define FRF_AZ_TX_ONLY1TAG_WIDTH 1
+#define FRF_AZ_TX_PREF_THRESHOLD_LBN 19
+#define FRF_AZ_TX_PREF_THRESHOLD_WIDTH 2
+#define FRF_AZ_TX_ONE_PKT_PER_Q_LBN 18
+#define FRF_AZ_TX_ONE_PKT_PER_Q_WIDTH 1
+#define FRF_AZ_TX_DIS_NON_IP_EV_LBN 17
+#define FRF_AZ_TX_DIS_NON_IP_EV_WIDTH 1
+#define FRF_AA_TX_DMA_FF_THR_LBN 16
+#define FRF_AA_TX_DMA_FF_THR_WIDTH 1
+#define FRF_AZ_TX_DMA_SPACER_LBN 8
+#define FRF_AZ_TX_DMA_SPACER_WIDTH 8
+#define FRF_AA_TX_TCP_DIS_LBN 7
+#define FRF_AA_TX_TCP_DIS_WIDTH 1
+#define FRF_BZ_TX_FLUSH_MIN_LEN_EN_LBN 7
+#define FRF_BZ_TX_FLUSH_MIN_LEN_EN_WIDTH 1
+#define FRF_AA_TX_IP_DIS_LBN 6
+#define FRF_AA_TX_IP_DIS_WIDTH 1
+#define FRF_AZ_TX_MAX_CPL_LBN 2
+#define FRF_AZ_TX_MAX_CPL_WIDTH 2
+#define FFE_AZ_TX_MAX_CPL_16 3
+#define FFE_AZ_TX_MAX_CPL_8 2
+#define FFE_AZ_TX_MAX_CPL_4 1
+#define FFE_AZ_TX_MAX_CPL_NOLIMIT 0
+#define FRF_AZ_TX_MAX_PREF_LBN 0
+#define FRF_AZ_TX_MAX_PREF_WIDTH 2
+#define FFE_AZ_TX_MAX_PREF_32 3
+#define FFE_AZ_TX_MAX_PREF_16 2
+#define FFE_AZ_TX_MAX_PREF_8 1
+#define FFE_AZ_TX_MAX_PREF_OFF 0
+
+/* TX_PACE_REG: Transmit pace control register */
+#define FR_BZ_TX_PACE 0x00000a90
+#define FRF_BZ_TX_PACE_SB_NOT_AF_LBN 19
+#define FRF_BZ_TX_PACE_SB_NOT_AF_WIDTH 10
+#define FRF_BZ_TX_PACE_SB_AF_LBN 9
+#define FRF_BZ_TX_PACE_SB_AF_WIDTH 10
+#define FRF_BZ_TX_PACE_FB_BASE_LBN 5
+#define FRF_BZ_TX_PACE_FB_BASE_WIDTH 4
+#define FRF_BZ_TX_PACE_BIN_TH_LBN 0
+#define FRF_BZ_TX_PACE_BIN_TH_WIDTH 5
+
+/* TX_PACE_DROP_QID_REG: PACE Drop QID Counter */
+#define FR_BZ_TX_PACE_DROP_QID 0x00000aa0
+#define FRF_BZ_TX_PACE_QID_DRP_CNT_LBN 0
+#define FRF_BZ_TX_PACE_QID_DRP_CNT_WIDTH 16
+
+/* TX_VLAN_REG: Transmit VLAN tag register */
+#define FR_BB_TX_VLAN 0x00000ae0
+#define FRF_BB_TX_VLAN_EN_LBN 127
+#define FRF_BB_TX_VLAN_EN_WIDTH 1
+#define FRF_BB_TX_VLAN7_PORT1_EN_LBN 125
+#define FRF_BB_TX_VLAN7_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN7_PORT0_EN_LBN 124
+#define FRF_BB_TX_VLAN7_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN7_LBN 112
+#define FRF_BB_TX_VLAN7_WIDTH 12
+#define FRF_BB_TX_VLAN6_PORT1_EN_LBN 109
+#define FRF_BB_TX_VLAN6_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN6_PORT0_EN_LBN 108
+#define FRF_BB_TX_VLAN6_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN6_LBN 96
+#define FRF_BB_TX_VLAN6_WIDTH 12
+#define FRF_BB_TX_VLAN5_PORT1_EN_LBN 93
+#define FRF_BB_TX_VLAN5_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN5_PORT0_EN_LBN 92
+#define FRF_BB_TX_VLAN5_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN5_LBN 80
+#define FRF_BB_TX_VLAN5_WIDTH 12
+#define FRF_BB_TX_VLAN4_PORT1_EN_LBN 77
+#define FRF_BB_TX_VLAN4_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN4_PORT0_EN_LBN 76
+#define FRF_BB_TX_VLAN4_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN4_LBN 64
+#define FRF_BB_TX_VLAN4_WIDTH 12
+#define FRF_BB_TX_VLAN3_PORT1_EN_LBN 61
+#define FRF_BB_TX_VLAN3_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN3_PORT0_EN_LBN 60
+#define FRF_BB_TX_VLAN3_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN3_LBN 48
+#define FRF_BB_TX_VLAN3_WIDTH 12
+#define FRF_BB_TX_VLAN2_PORT1_EN_LBN 45
+#define FRF_BB_TX_VLAN2_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN2_PORT0_EN_LBN 44
+#define FRF_BB_TX_VLAN2_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN2_LBN 32
+#define FRF_BB_TX_VLAN2_WIDTH 12
+#define FRF_BB_TX_VLAN1_PORT1_EN_LBN 29
+#define FRF_BB_TX_VLAN1_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN1_PORT0_EN_LBN 28
+#define FRF_BB_TX_VLAN1_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN1_LBN 16
+#define FRF_BB_TX_VLAN1_WIDTH 12
+#define FRF_BB_TX_VLAN0_PORT1_EN_LBN 13
+#define FRF_BB_TX_VLAN0_PORT1_EN_WIDTH 1
+#define FRF_BB_TX_VLAN0_PORT0_EN_LBN 12
+#define FRF_BB_TX_VLAN0_PORT0_EN_WIDTH 1
+#define FRF_BB_TX_VLAN0_LBN 0
+#define FRF_BB_TX_VLAN0_WIDTH 12
+
+/* TX_IPFIL_PORTEN_REG: Transmit filter control register */
+#define FR_BZ_TX_IPFIL_PORTEN 0x00000af0
+#define FRF_BZ_TX_MADR0_FIL_EN_LBN 64
+#define FRF_BZ_TX_MADR0_FIL_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL31_PORT_EN_LBN 62
+#define FRF_BB_TX_IPFIL31_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL30_PORT_EN_LBN 60
+#define FRF_BB_TX_IPFIL30_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL29_PORT_EN_LBN 58
+#define FRF_BB_TX_IPFIL29_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL28_PORT_EN_LBN 56
+#define FRF_BB_TX_IPFIL28_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL27_PORT_EN_LBN 54
+#define FRF_BB_TX_IPFIL27_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL26_PORT_EN_LBN 52
+#define FRF_BB_TX_IPFIL26_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL25_PORT_EN_LBN 50
+#define FRF_BB_TX_IPFIL25_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL24_PORT_EN_LBN 48
+#define FRF_BB_TX_IPFIL24_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL23_PORT_EN_LBN 46
+#define FRF_BB_TX_IPFIL23_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL22_PORT_EN_LBN 44
+#define FRF_BB_TX_IPFIL22_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL21_PORT_EN_LBN 42
+#define FRF_BB_TX_IPFIL21_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL20_PORT_EN_LBN 40
+#define FRF_BB_TX_IPFIL20_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL19_PORT_EN_LBN 38
+#define FRF_BB_TX_IPFIL19_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL18_PORT_EN_LBN 36
+#define FRF_BB_TX_IPFIL18_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL17_PORT_EN_LBN 34
+#define FRF_BB_TX_IPFIL17_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL16_PORT_EN_LBN 32
+#define FRF_BB_TX_IPFIL16_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL15_PORT_EN_LBN 30
+#define FRF_BB_TX_IPFIL15_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL14_PORT_EN_LBN 28
+#define FRF_BB_TX_IPFIL14_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL13_PORT_EN_LBN 26
+#define FRF_BB_TX_IPFIL13_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL12_PORT_EN_LBN 24
+#define FRF_BB_TX_IPFIL12_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL11_PORT_EN_LBN 22
+#define FRF_BB_TX_IPFIL11_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL10_PORT_EN_LBN 20
+#define FRF_BB_TX_IPFIL10_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL9_PORT_EN_LBN 18
+#define FRF_BB_TX_IPFIL9_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL8_PORT_EN_LBN 16
+#define FRF_BB_TX_IPFIL8_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL7_PORT_EN_LBN 14
+#define FRF_BB_TX_IPFIL7_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL6_PORT_EN_LBN 12
+#define FRF_BB_TX_IPFIL6_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL5_PORT_EN_LBN 10
+#define FRF_BB_TX_IPFIL5_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL4_PORT_EN_LBN 8
+#define FRF_BB_TX_IPFIL4_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL3_PORT_EN_LBN 6
+#define FRF_BB_TX_IPFIL3_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL2_PORT_EN_LBN 4
+#define FRF_BB_TX_IPFIL2_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL1_PORT_EN_LBN 2
+#define FRF_BB_TX_IPFIL1_PORT_EN_WIDTH 1
+#define FRF_BB_TX_IPFIL0_PORT_EN_LBN 0
+#define FRF_BB_TX_IPFIL0_PORT_EN_WIDTH 1
+
+/* TX_IPFIL_TBL: Transmit IP source address filter table */
+#define FR_BB_TX_IPFIL_TBL 0x00000b00
+#define FR_BB_TX_IPFIL_TBL_STEP 16
+#define FR_BB_TX_IPFIL_TBL_ROWS 16
+#define FRF_BB_TX_IPFIL_MASK_1_LBN 96
+#define FRF_BB_TX_IPFIL_MASK_1_WIDTH 32
+#define FRF_BB_TX_IP_SRC_ADR_1_LBN 64
+#define FRF_BB_TX_IP_SRC_ADR_1_WIDTH 32
+#define FRF_BB_TX_IPFIL_MASK_0_LBN 32
+#define FRF_BB_TX_IPFIL_MASK_0_WIDTH 32
+#define FRF_BB_TX_IP_SRC_ADR_0_LBN 0
+#define FRF_BB_TX_IP_SRC_ADR_0_WIDTH 32
+
+/* MD_TXD_REG: PHY management transmit data register */
+#define FR_AB_MD_TXD 0x00000c00
+#define FRF_AB_MD_TXD_LBN 0
+#define FRF_AB_MD_TXD_WIDTH 16
+
+/* MD_RXD_REG: PHY management receive data register */
+#define FR_AB_MD_RXD 0x00000c10
+#define FRF_AB_MD_RXD_LBN 0
+#define FRF_AB_MD_RXD_WIDTH 16
+
+/* MD_CS_REG: PHY management configuration & status register */
+#define FR_AB_MD_CS 0x00000c20
+#define FRF_AB_MD_RD_EN_CMD_LBN 15
+#define FRF_AB_MD_RD_EN_CMD_WIDTH 1
+#define FRF_AB_MD_WR_EN_CMD_LBN 14
+#define FRF_AB_MD_WR_EN_CMD_WIDTH 1
+#define FRF_AB_MD_ADDR_CMD_LBN 13
+#define FRF_AB_MD_ADDR_CMD_WIDTH 1
+#define FRF_AB_MD_PT_LBN 7
+#define FRF_AB_MD_PT_WIDTH 3
+#define FRF_AB_MD_PL_LBN 6
+#define FRF_AB_MD_PL_WIDTH 1
+#define FRF_AB_MD_INT_CLR_LBN 5
+#define FRF_AB_MD_INT_CLR_WIDTH 1
+#define FRF_AB_MD_GC_LBN 4
+#define FRF_AB_MD_GC_WIDTH 1
+#define FRF_AB_MD_PRSP_LBN 3
+#define FRF_AB_MD_PRSP_WIDTH 1
+#define FRF_AB_MD_RIC_LBN 2
+#define FRF_AB_MD_RIC_WIDTH 1
+#define FRF_AB_MD_RDC_LBN 1
+#define FRF_AB_MD_RDC_WIDTH 1
+#define FRF_AB_MD_WRC_LBN 0
+#define FRF_AB_MD_WRC_WIDTH 1
+
+/* MD_PHY_ADR_REG: PHY management PHY address register */
+#define FR_AB_MD_PHY_ADR 0x00000c30
+#define FRF_AB_MD_PHY_ADR_LBN 0
+#define FRF_AB_MD_PHY_ADR_WIDTH 16
+
+/* MD_ID_REG: PHY management ID register */
+#define FR_AB_MD_ID 0x00000c40
+#define FRF_AB_MD_PRT_ADR_LBN 11
+#define FRF_AB_MD_PRT_ADR_WIDTH 5
+#define FRF_AB_MD_DEV_ADR_LBN 6
+#define FRF_AB_MD_DEV_ADR_WIDTH 5
+
+/* MD_STAT_REG: PHY management status & mask register */
+#define FR_AB_MD_STAT 0x00000c50
+#define FRF_AB_MD_PINT_LBN 4
+#define FRF_AB_MD_PINT_WIDTH 1
+#define FRF_AB_MD_DONE_LBN 3
+#define FRF_AB_MD_DONE_WIDTH 1
+#define FRF_AB_MD_BSERR_LBN 2
+#define FRF_AB_MD_BSERR_WIDTH 1
+#define FRF_AB_MD_LNFL_LBN 1
+#define FRF_AB_MD_LNFL_WIDTH 1
+#define FRF_AB_MD_BSY_LBN 0
+#define FRF_AB_MD_BSY_WIDTH 1
+
+/* MAC_STAT_DMA_REG: Port MAC statistical counter DMA register */
+#define FR_AB_MAC_STAT_DMA 0x00000c60
+#define FRF_AB_MAC_STAT_DMA_CMD_LBN 48
+#define FRF_AB_MAC_STAT_DMA_CMD_WIDTH 1
+#define FRF_AB_MAC_STAT_DMA_ADR_LBN 0
+#define FRF_AB_MAC_STAT_DMA_ADR_WIDTH 48
+
+/* MAC_CTRL_REG: Port MAC control register */
+#define FR_AB_MAC_CTRL 0x00000c80
+#define FRF_AB_MAC_XOFF_VAL_LBN 16
+#define FRF_AB_MAC_XOFF_VAL_WIDTH 16
+#define FRF_BB_TXFIFO_DRAIN_EN_LBN 7
+#define FRF_BB_TXFIFO_DRAIN_EN_WIDTH 1
+#define FRF_AB_MAC_XG_DISTXCRC_LBN 5
+#define FRF_AB_MAC_XG_DISTXCRC_WIDTH 1
+#define FRF_AB_MAC_BCAD_ACPT_LBN 4
+#define FRF_AB_MAC_BCAD_ACPT_WIDTH 1
+#define FRF_AB_MAC_UC_PROM_LBN 3
+#define FRF_AB_MAC_UC_PROM_WIDTH 1
+#define FRF_AB_MAC_LINK_STATUS_LBN 2
+#define FRF_AB_MAC_LINK_STATUS_WIDTH 1
+#define FRF_AB_MAC_SPEED_LBN 0
+#define FRF_AB_MAC_SPEED_WIDTH 2
+#define FFE_AB_MAC_SPEED_10G 3
+#define FFE_AB_MAC_SPEED_1G 2
+#define FFE_AB_MAC_SPEED_100M 1
+#define FFE_AB_MAC_SPEED_10M 0
+
+/* GEN_MODE_REG: General Purpose mode register (external interrupt mask) */
+#define FR_BB_GEN_MODE 0x00000c90
+#define FRF_BB_XFP_PHY_INT_POL_SEL_LBN 3
+#define FRF_BB_XFP_PHY_INT_POL_SEL_WIDTH 1
+#define FRF_BB_XG_PHY_INT_POL_SEL_LBN 2
+#define FRF_BB_XG_PHY_INT_POL_SEL_WIDTH 1
+#define FRF_BB_XFP_PHY_INT_MASK_LBN 1
+#define FRF_BB_XFP_PHY_INT_MASK_WIDTH 1
+#define FRF_BB_XG_PHY_INT_MASK_LBN 0
+#define FRF_BB_XG_PHY_INT_MASK_WIDTH 1
+
+/* MAC_MC_HASH_REG0: Multicast address hash table */
+#define FR_AB_MAC_MC_HASH_REG0 0x00000ca0
+#define FRF_AB_MAC_MCAST_HASH0_LBN 0
+#define FRF_AB_MAC_MCAST_HASH0_WIDTH 128
+
+/* MAC_MC_HASH_REG1: Multicast address hash table */
+#define FR_AB_MAC_MC_HASH_REG1 0x00000cb0
+#define FRF_AB_MAC_MCAST_HASH1_LBN 0
+#define FRF_AB_MAC_MCAST_HASH1_WIDTH 128
+
+/* GM_CFG1_REG: GMAC configuration register 1 */
+#define FR_AB_GM_CFG1 0x00000e00
+#define FRF_AB_GM_SW_RST_LBN 31
+#define FRF_AB_GM_SW_RST_WIDTH 1
+#define FRF_AB_GM_SIM_RST_LBN 30
+#define FRF_AB_GM_SIM_RST_WIDTH 1
+#define FRF_AB_GM_RST_RX_MAC_CTL_LBN 19
+#define FRF_AB_GM_RST_RX_MAC_CTL_WIDTH 1
+#define FRF_AB_GM_RST_TX_MAC_CTL_LBN 18
+#define FRF_AB_GM_RST_TX_MAC_CTL_WIDTH 1
+#define FRF_AB_GM_RST_RX_FUNC_LBN 17
+#define FRF_AB_GM_RST_RX_FUNC_WIDTH 1
+#define FRF_AB_GM_RST_TX_FUNC_LBN 16
+#define FRF_AB_GM_RST_TX_FUNC_WIDTH 1
+#define FRF_AB_GM_LOOP_LBN 8
+#define FRF_AB_GM_LOOP_WIDTH 1
+#define FRF_AB_GM_RX_FC_EN_LBN 5
+#define FRF_AB_GM_RX_FC_EN_WIDTH 1
+#define FRF_AB_GM_TX_FC_EN_LBN 4
+#define FRF_AB_GM_TX_FC_EN_WIDTH 1
+#define FRF_AB_GM_SYNC_RXEN_LBN 3
+#define FRF_AB_GM_SYNC_RXEN_WIDTH 1
+#define FRF_AB_GM_RX_EN_LBN 2
+#define FRF_AB_GM_RX_EN_WIDTH 1
+#define FRF_AB_GM_SYNC_TXEN_LBN 1
+#define FRF_AB_GM_SYNC_TXEN_WIDTH 1
+#define FRF_AB_GM_TX_EN_LBN 0
+#define FRF_AB_GM_TX_EN_WIDTH 1
+
+/* GM_CFG2_REG: GMAC configuration register 2 */
+#define FR_AB_GM_CFG2 0x00000e10
+#define FRF_AB_GM_PAMBL_LEN_LBN 12
+#define FRF_AB_GM_PAMBL_LEN_WIDTH 4
+#define FRF_AB_GM_IF_MODE_LBN 8
+#define FRF_AB_GM_IF_MODE_WIDTH 2
+#define FFE_AB_IF_MODE_BYTE_MODE 2
+#define FFE_AB_IF_MODE_NIBBLE_MODE 1
+#define FRF_AB_GM_HUGE_FRM_EN_LBN 5
+#define FRF_AB_GM_HUGE_FRM_EN_WIDTH 1
+#define FRF_AB_GM_LEN_CHK_LBN 4
+#define FRF_AB_GM_LEN_CHK_WIDTH 1
+#define FRF_AB_GM_PAD_CRC_EN_LBN 2
+#define FRF_AB_GM_PAD_CRC_EN_WIDTH 1
+#define FRF_AB_GM_CRC_EN_LBN 1
+#define FRF_AB_GM_CRC_EN_WIDTH 1
+#define FRF_AB_GM_FD_LBN 0
+#define FRF_AB_GM_FD_WIDTH 1
+
+/* GM_IPG_REG: GMAC IPG register */
+#define FR_AB_GM_IPG 0x00000e20
+#define FRF_AB_GM_NONB2B_IPG1_LBN 24
+#define FRF_AB_GM_NONB2B_IPG1_WIDTH 7
+#define FRF_AB_GM_NONB2B_IPG2_LBN 16
+#define FRF_AB_GM_NONB2B_IPG2_WIDTH 7
+#define FRF_AB_GM_MIN_IPG_ENF_LBN 8
+#define FRF_AB_GM_MIN_IPG_ENF_WIDTH 8
+#define FRF_AB_GM_B2B_IPG_LBN 0
+#define FRF_AB_GM_B2B_IPG_WIDTH 7
+
+/* GM_HD_REG: GMAC half duplex register */
+#define FR_AB_GM_HD 0x00000e30
+#define FRF_AB_GM_ALT_BOFF_VAL_LBN 20
+#define FRF_AB_GM_ALT_BOFF_VAL_WIDTH 4
+#define FRF_AB_GM_ALT_BOFF_EN_LBN 19
+#define FRF_AB_GM_ALT_BOFF_EN_WIDTH 1
+#define FRF_AB_GM_BP_NO_BOFF_LBN 18
+#define FRF_AB_GM_BP_NO_BOFF_WIDTH 1
+#define FRF_AB_GM_DIS_BOFF_LBN 17
+#define FRF_AB_GM_DIS_BOFF_WIDTH 1
+#define FRF_AB_GM_EXDEF_TX_EN_LBN 16
+#define FRF_AB_GM_EXDEF_TX_EN_WIDTH 1
+#define FRF_AB_GM_RTRY_LIMIT_LBN 12
+#define FRF_AB_GM_RTRY_LIMIT_WIDTH 4
+#define FRF_AB_GM_COL_WIN_LBN 0
+#define FRF_AB_GM_COL_WIN_WIDTH 10
+
+/* GM_MAX_FLEN_REG: GMAC maximum frame length register */
+#define FR_AB_GM_MAX_FLEN 0x00000e40
+#define FRF_AB_GM_MAX_FLEN_LBN 0
+#define FRF_AB_GM_MAX_FLEN_WIDTH 16
+
+/* GM_TEST_REG: GMAC test register */
+#define FR_AB_GM_TEST 0x00000e70
+#define FRF_AB_GM_MAX_BOFF_LBN 3
+#define FRF_AB_GM_MAX_BOFF_WIDTH 1
+#define FRF_AB_GM_REG_TX_FLOW_EN_LBN 2
+#define FRF_AB_GM_REG_TX_FLOW_EN_WIDTH 1
+#define FRF_AB_GM_TEST_PAUSE_LBN 1
+#define FRF_AB_GM_TEST_PAUSE_WIDTH 1
+#define FRF_AB_GM_SHORT_SLOT_LBN 0
+#define FRF_AB_GM_SHORT_SLOT_WIDTH 1
+
+/* GM_ADR1_REG: GMAC station address register 1 */
+#define FR_AB_GM_ADR1 0x00000f00
+#define FRF_AB_GM_ADR_B0_LBN 24
+#define FRF_AB_GM_ADR_B0_WIDTH 8
+#define FRF_AB_GM_ADR_B1_LBN 16
+#define FRF_AB_GM_ADR_B1_WIDTH 8
+#define FRF_AB_GM_ADR_B2_LBN 8
+#define FRF_AB_GM_ADR_B2_WIDTH 8
+#define FRF_AB_GM_ADR_B3_LBN 0
+#define FRF_AB_GM_ADR_B3_WIDTH 8
+
+/* GM_ADR2_REG: GMAC station address register 2 */
+#define FR_AB_GM_ADR2 0x00000f10
+#define FRF_AB_GM_ADR_B4_LBN 24
+#define FRF_AB_GM_ADR_B4_WIDTH 8
+#define FRF_AB_GM_ADR_B5_LBN 16
+#define FRF_AB_GM_ADR_B5_WIDTH 8
+
+/* GMF_CFG0_REG: GMAC FIFO configuration register 0 */
+#define FR_AB_GMF_CFG0 0x00000f20
+#define FRF_AB_GMF_FTFENRPLY_LBN 20
+#define FRF_AB_GMF_FTFENRPLY_WIDTH 1
+#define FRF_AB_GMF_STFENRPLY_LBN 19
+#define FRF_AB_GMF_STFENRPLY_WIDTH 1
+#define FRF_AB_GMF_FRFENRPLY_LBN 18
+#define FRF_AB_GMF_FRFENRPLY_WIDTH 1
+#define FRF_AB_GMF_SRFENRPLY_LBN 17
+#define FRF_AB_GMF_SRFENRPLY_WIDTH 1
+#define FRF_AB_GMF_WTMENRPLY_LBN 16
+#define FRF_AB_GMF_WTMENRPLY_WIDTH 1
+#define FRF_AB_GMF_FTFENREQ_LBN 12
+#define FRF_AB_GMF_FTFENREQ_WIDTH 1
+#define FRF_AB_GMF_STFENREQ_LBN 11
+#define FRF_AB_GMF_STFENREQ_WIDTH 1
+#define FRF_AB_GMF_FRFENREQ_LBN 10
+#define FRF_AB_GMF_FRFENREQ_WIDTH 1
+#define FRF_AB_GMF_SRFENREQ_LBN 9
+#define FRF_AB_GMF_SRFENREQ_WIDTH 1
+#define FRF_AB_GMF_WTMENREQ_LBN 8
+#define FRF_AB_GMF_WTMENREQ_WIDTH 1
+#define FRF_AB_GMF_HSTRSTFT_LBN 4
+#define FRF_AB_GMF_HSTRSTFT_WIDTH 1
+#define FRF_AB_GMF_HSTRSTST_LBN 3
+#define FRF_AB_GMF_HSTRSTST_WIDTH 1
+#define FRF_AB_GMF_HSTRSTFR_LBN 2
+#define FRF_AB_GMF_HSTRSTFR_WIDTH 1
+#define FRF_AB_GMF_HSTRSTSR_LBN 1
+#define FRF_AB_GMF_HSTRSTSR_WIDTH 1
+#define FRF_AB_GMF_HSTRSTWT_LBN 0
+#define FRF_AB_GMF_HSTRSTWT_WIDTH 1
+
+/* GMF_CFG1_REG: GMAC FIFO configuration register 1 */
+#define FR_AB_GMF_CFG1 0x00000f30
+#define FRF_AB_GMF_CFGFRTH_LBN 16
+#define FRF_AB_GMF_CFGFRTH_WIDTH 5
+#define FRF_AB_GMF_CFGXOFFRTX_LBN 0
+#define FRF_AB_GMF_CFGXOFFRTX_WIDTH 16
+
+/* GMF_CFG2_REG: GMAC FIFO configuration register 2 */
+#define FR_AB_GMF_CFG2 0x00000f40
+#define FRF_AB_GMF_CFGHWM_LBN 16
+#define FRF_AB_GMF_CFGHWM_WIDTH 6
+#define FRF_AB_GMF_CFGLWM_LBN 0
+#define FRF_AB_GMF_CFGLWM_WIDTH 6
+
+/* GMF_CFG3_REG: GMAC FIFO configuration register 3 */
+#define FR_AB_GMF_CFG3 0x00000f50
+#define FRF_AB_GMF_CFGHWMFT_LBN 16
+#define FRF_AB_GMF_CFGHWMFT_WIDTH 6
+#define FRF_AB_GMF_CFGFTTH_LBN 0
+#define FRF_AB_GMF_CFGFTTH_WIDTH 6
+
+/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */
+#define FR_AB_GMF_CFG4 0x00000f60
+#define FRF_AB_GMF_HSTFLTRFRM_LBN 0
+#define FRF_AB_GMF_HSTFLTRFRM_WIDTH 18
+
+/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */
+#define FR_AB_GMF_CFG5 0x00000f70
+#define FRF_AB_GMF_CFGHDPLX_LBN 22
+#define FRF_AB_GMF_CFGHDPLX_WIDTH 1
+#define FRF_AB_GMF_SRFULL_LBN 21
+#define FRF_AB_GMF_SRFULL_WIDTH 1
+#define FRF_AB_GMF_HSTSRFULLCLR_LBN 20
+#define FRF_AB_GMF_HSTSRFULLCLR_WIDTH 1
+#define FRF_AB_GMF_CFGBYTMODE_LBN 19
+#define FRF_AB_GMF_CFGBYTMODE_WIDTH 1
+#define FRF_AB_GMF_HSTDRPLT64_LBN 18
+#define FRF_AB_GMF_HSTDRPLT64_WIDTH 1
+#define FRF_AB_GMF_HSTFLTRFRMDC_LBN 0
+#define FRF_AB_GMF_HSTFLTRFRMDC_WIDTH 18
+
+/* TX_SRC_MAC_TBL: Transmit IP source address filter table */
+#define FR_BB_TX_SRC_MAC_TBL 0x00001000
+#define FR_BB_TX_SRC_MAC_TBL_STEP 16
+#define FR_BB_TX_SRC_MAC_TBL_ROWS 16
+#define FRF_BB_TX_SRC_MAC_ADR_1_LBN 64
+#define FRF_BB_TX_SRC_MAC_ADR_1_WIDTH 48
+#define FRF_BB_TX_SRC_MAC_ADR_0_LBN 0
+#define FRF_BB_TX_SRC_MAC_ADR_0_WIDTH 48
+
+/* TX_SRC_MAC_CTL_REG: Transmit MAC source address filter control */
+#define FR_BB_TX_SRC_MAC_CTL 0x00001100
+#define FRF_BB_TX_SRC_DROP_CTR_LBN 16
+#define FRF_BB_TX_SRC_DROP_CTR_WIDTH 16
+#define FRF_BB_TX_SRC_FLTR_EN_LBN 15
+#define FRF_BB_TX_SRC_FLTR_EN_WIDTH 1
+#define FRF_BB_TX_DROP_CTR_CLR_LBN 12
+#define FRF_BB_TX_DROP_CTR_CLR_WIDTH 1
+#define FRF_BB_TX_MAC_QID_SEL_LBN 0
+#define FRF_BB_TX_MAC_QID_SEL_WIDTH 3
+
+/* XM_ADR_LO_REG: XGMAC address register low */
+#define FR_AB_XM_ADR_LO 0x00001200
+#define FRF_AB_XM_ADR_LO_LBN 0
+#define FRF_AB_XM_ADR_LO_WIDTH 32
+
+/* XM_ADR_HI_REG: XGMAC address register high */
+#define FR_AB_XM_ADR_HI 0x00001210
+#define FRF_AB_XM_ADR_HI_LBN 0
+#define FRF_AB_XM_ADR_HI_WIDTH 16
+
+/* XM_GLB_CFG_REG: XGMAC global configuration */
+#define FR_AB_XM_GLB_CFG 0x00001220
+#define FRF_AB_XM_RMTFLT_GEN_LBN 17
+#define FRF_AB_XM_RMTFLT_GEN_WIDTH 1
+#define FRF_AB_XM_DEBUG_MODE_LBN 16
+#define FRF_AB_XM_DEBUG_MODE_WIDTH 1
+#define FRF_AB_XM_RX_STAT_EN_LBN 11
+#define FRF_AB_XM_RX_STAT_EN_WIDTH 1
+#define FRF_AB_XM_TX_STAT_EN_LBN 10
+#define FRF_AB_XM_TX_STAT_EN_WIDTH 1
+#define FRF_AB_XM_RX_JUMBO_MODE_LBN 6
+#define FRF_AB_XM_RX_JUMBO_MODE_WIDTH 1
+#define FRF_AB_XM_WAN_MODE_LBN 5
+#define FRF_AB_XM_WAN_MODE_WIDTH 1
+#define FRF_AB_XM_INTCLR_MODE_LBN 3
+#define FRF_AB_XM_INTCLR_MODE_WIDTH 1
+#define FRF_AB_XM_CORE_RST_LBN 0
+#define FRF_AB_XM_CORE_RST_WIDTH 1
+
+/* XM_TX_CFG_REG: XGMAC transmit configuration */
+#define FR_AB_XM_TX_CFG 0x00001230
+#define FRF_AB_XM_TX_PROG_LBN 24
+#define FRF_AB_XM_TX_PROG_WIDTH 1
+#define FRF_AB_XM_IPG_LBN 16
+#define FRF_AB_XM_IPG_WIDTH 4
+#define FRF_AB_XM_FCNTL_LBN 10
+#define FRF_AB_XM_FCNTL_WIDTH 1
+#define FRF_AB_XM_TXCRC_LBN 8
+#define FRF_AB_XM_TXCRC_WIDTH 1
+#define FRF_AB_XM_EDRC_LBN 6
+#define FRF_AB_XM_EDRC_WIDTH 1
+#define FRF_AB_XM_AUTO_PAD_LBN 5
+#define FRF_AB_XM_AUTO_PAD_WIDTH 1
+#define FRF_AB_XM_TX_PRMBL_LBN 2
+#define FRF_AB_XM_TX_PRMBL_WIDTH 1
+#define FRF_AB_XM_TXEN_LBN 1
+#define FRF_AB_XM_TXEN_WIDTH 1
+#define FRF_AB_XM_TX_RST_LBN 0
+#define FRF_AB_XM_TX_RST_WIDTH 1
+
+/* XM_RX_CFG_REG: XGMAC receive configuration */
+#define FR_AB_XM_RX_CFG 0x00001240
+#define FRF_AB_XM_PASS_LENERR_LBN 26
+#define FRF_AB_XM_PASS_LENERR_WIDTH 1
+#define FRF_AB_XM_PASS_CRC_ERR_LBN 25
+#define FRF_AB_XM_PASS_CRC_ERR_WIDTH 1
+#define FRF_AB_XM_PASS_PRMBLE_ERR_LBN 24
+#define FRF_AB_XM_PASS_PRMBLE_ERR_WIDTH 1
+#define FRF_AB_XM_REJ_BCAST_LBN 20
+#define FRF_AB_XM_REJ_BCAST_WIDTH 1
+#define FRF_AB_XM_ACPT_ALL_MCAST_LBN 11
+#define FRF_AB_XM_ACPT_ALL_MCAST_WIDTH 1
+#define FRF_AB_XM_ACPT_ALL_UCAST_LBN 9
+#define FRF_AB_XM_ACPT_ALL_UCAST_WIDTH 1
+#define FRF_AB_XM_AUTO_DEPAD_LBN 8
+#define FRF_AB_XM_AUTO_DEPAD_WIDTH 1
+#define FRF_AB_XM_RXCRC_LBN 3
+#define FRF_AB_XM_RXCRC_WIDTH 1
+#define FRF_AB_XM_RX_PRMBL_LBN 2
+#define FRF_AB_XM_RX_PRMBL_WIDTH 1
+#define FRF_AB_XM_RXEN_LBN 1
+#define FRF_AB_XM_RXEN_WIDTH 1
+#define FRF_AB_XM_RX_RST_LBN 0
+#define FRF_AB_XM_RX_RST_WIDTH 1
+
+/* XM_MGT_INT_MASK: documentation to be written for sum_XM_MGT_INT_MASK */
+#define FR_AB_XM_MGT_INT_MASK 0x00001250
+#define FRF_AB_XM_MSK_STA_INTR_LBN 16
+#define FRF_AB_XM_MSK_STA_INTR_WIDTH 1
+#define FRF_AB_XM_MSK_STAT_CNTR_HF_LBN 9
+#define FRF_AB_XM_MSK_STAT_CNTR_HF_WIDTH 1
+#define FRF_AB_XM_MSK_STAT_CNTR_OF_LBN 8
+#define FRF_AB_XM_MSK_STAT_CNTR_OF_WIDTH 1
+#define FRF_AB_XM_MSK_PRMBLE_ERR_LBN 2
+#define FRF_AB_XM_MSK_PRMBLE_ERR_WIDTH 1
+#define FRF_AB_XM_MSK_RMTFLT_LBN 1
+#define FRF_AB_XM_MSK_RMTFLT_WIDTH 1
+#define FRF_AB_XM_MSK_LCLFLT_LBN 0
+#define FRF_AB_XM_MSK_LCLFLT_WIDTH 1
+
+/* XM_FC_REG: XGMAC flow control register */
+#define FR_AB_XM_FC 0x00001270
+#define FRF_AB_XM_PAUSE_TIME_LBN 16
+#define FRF_AB_XM_PAUSE_TIME_WIDTH 16
+#define FRF_AB_XM_RX_MAC_STAT_LBN 11
+#define FRF_AB_XM_RX_MAC_STAT_WIDTH 1
+#define FRF_AB_XM_TX_MAC_STAT_LBN 10
+#define FRF_AB_XM_TX_MAC_STAT_WIDTH 1
+#define FRF_AB_XM_MCNTL_PASS_LBN 8
+#define FRF_AB_XM_MCNTL_PASS_WIDTH 2
+#define FRF_AB_XM_REJ_CNTL_UCAST_LBN 6
+#define FRF_AB_XM_REJ_CNTL_UCAST_WIDTH 1
+#define FRF_AB_XM_REJ_CNTL_MCAST_LBN 5
+#define FRF_AB_XM_REJ_CNTL_MCAST_WIDTH 1
+#define FRF_AB_XM_ZPAUSE_LBN 2
+#define FRF_AB_XM_ZPAUSE_WIDTH 1
+#define FRF_AB_XM_XMIT_PAUSE_LBN 1
+#define FRF_AB_XM_XMIT_PAUSE_WIDTH 1
+#define FRF_AB_XM_DIS_FCNTL_LBN 0
+#define FRF_AB_XM_DIS_FCNTL_WIDTH 1
+
+/* XM_PAUSE_TIME_REG: XGMAC pause time register */
+#define FR_AB_XM_PAUSE_TIME 0x00001290
+#define FRF_AB_XM_TX_PAUSE_CNT_LBN 16
+#define FRF_AB_XM_TX_PAUSE_CNT_WIDTH 16
+#define FRF_AB_XM_RX_PAUSE_CNT_LBN 0
+#define FRF_AB_XM_RX_PAUSE_CNT_WIDTH 16
+
+/* XM_TX_PARAM_REG: XGMAC transmit parameter register */
+#define FR_AB_XM_TX_PARAM 0x000012d0
+#define FRF_AB_XM_TX_JUMBO_MODE_LBN 31
+#define FRF_AB_XM_TX_JUMBO_MODE_WIDTH 1
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_HI_LBN 19
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH 11
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN 16
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH 3
+#define FRF_AB_XM_PAD_CHAR_LBN 0
+#define FRF_AB_XM_PAD_CHAR_WIDTH 8
+
+/* XM_RX_PARAM_REG: XGMAC receive parameter register */
+#define FR_AB_XM_RX_PARAM 0x000012e0
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_HI_LBN 3
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH 11
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN 0
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH 3
+
+/* XM_MGT_INT_MSK_REG: XGMAC management interrupt mask register */
+#define FR_AB_XM_MGT_INT_MSK 0x000012f0
+#define FRF_AB_XM_STAT_CNTR_OF_LBN 9
+#define FRF_AB_XM_STAT_CNTR_OF_WIDTH 1
+#define FRF_AB_XM_STAT_CNTR_HF_LBN 8
+#define FRF_AB_XM_STAT_CNTR_HF_WIDTH 1
+#define FRF_AB_XM_PRMBLE_ERR_LBN 2
+#define FRF_AB_XM_PRMBLE_ERR_WIDTH 1
+#define FRF_AB_XM_RMTFLT_LBN 1
+#define FRF_AB_XM_RMTFLT_WIDTH 1
+#define FRF_AB_XM_LCLFLT_LBN 0
+#define FRF_AB_XM_LCLFLT_WIDTH 1
+
+/* XX_PWR_RST_REG: XGXS/XAUI powerdown/reset register */
+#define FR_AB_XX_PWR_RST 0x00001300
+#define FRF_AB_XX_PWRDND_SIG_LBN 31
+#define FRF_AB_XX_PWRDND_SIG_WIDTH 1
+#define FRF_AB_XX_PWRDNC_SIG_LBN 30
+#define FRF_AB_XX_PWRDNC_SIG_WIDTH 1
+#define FRF_AB_XX_PWRDNB_SIG_LBN 29
+#define FRF_AB_XX_PWRDNB_SIG_WIDTH 1
+#define FRF_AB_XX_PWRDNA_SIG_LBN 28
+#define FRF_AB_XX_PWRDNA_SIG_WIDTH 1
+#define FRF_AB_XX_SIM_MODE_LBN 27
+#define FRF_AB_XX_SIM_MODE_WIDTH 1
+#define FRF_AB_XX_RSTPLLCD_SIG_LBN 25
+#define FRF_AB_XX_RSTPLLCD_SIG_WIDTH 1
+#define FRF_AB_XX_RSTPLLAB_SIG_LBN 24
+#define FRF_AB_XX_RSTPLLAB_SIG_WIDTH 1
+#define FRF_AB_XX_RESETD_SIG_LBN 23
+#define FRF_AB_XX_RESETD_SIG_WIDTH 1
+#define FRF_AB_XX_RESETC_SIG_LBN 22
+#define FRF_AB_XX_RESETC_SIG_WIDTH 1
+#define FRF_AB_XX_RESETB_SIG_LBN 21
+#define FRF_AB_XX_RESETB_SIG_WIDTH 1
+#define FRF_AB_XX_RESETA_SIG_LBN 20
+#define FRF_AB_XX_RESETA_SIG_WIDTH 1
+#define FRF_AB_XX_RSTXGXSRX_SIG_LBN 18
+#define FRF_AB_XX_RSTXGXSRX_SIG_WIDTH 1
+#define FRF_AB_XX_RSTXGXSTX_SIG_LBN 17
+#define FRF_AB_XX_RSTXGXSTX_SIG_WIDTH 1
+#define FRF_AB_XX_SD_RST_ACT_LBN 16
+#define FRF_AB_XX_SD_RST_ACT_WIDTH 1
+#define FRF_AB_XX_PWRDND_EN_LBN 15
+#define FRF_AB_XX_PWRDND_EN_WIDTH 1
+#define FRF_AB_XX_PWRDNC_EN_LBN 14
+#define FRF_AB_XX_PWRDNC_EN_WIDTH 1
+#define FRF_AB_XX_PWRDNB_EN_LBN 13
+#define FRF_AB_XX_PWRDNB_EN_WIDTH 1
+#define FRF_AB_XX_PWRDNA_EN_LBN 12
+#define FRF_AB_XX_PWRDNA_EN_WIDTH 1
+#define FRF_AB_XX_RSTPLLCD_EN_LBN 9
+#define FRF_AB_XX_RSTPLLCD_EN_WIDTH 1
+#define FRF_AB_XX_RSTPLLAB_EN_LBN 8
+#define FRF_AB_XX_RSTPLLAB_EN_WIDTH 1
+#define FRF_AB_XX_RESETD_EN_LBN 7
+#define FRF_AB_XX_RESETD_EN_WIDTH 1
+#define FRF_AB_XX_RESETC_EN_LBN 6
+#define FRF_AB_XX_RESETC_EN_WIDTH 1
+#define FRF_AB_XX_RESETB_EN_LBN 5
+#define FRF_AB_XX_RESETB_EN_WIDTH 1
+#define FRF_AB_XX_RESETA_EN_LBN 4
+#define FRF_AB_XX_RESETA_EN_WIDTH 1
+#define FRF_AB_XX_RSTXGXSRX_EN_LBN 2
+#define FRF_AB_XX_RSTXGXSRX_EN_WIDTH 1
+#define FRF_AB_XX_RSTXGXSTX_EN_LBN 1
+#define FRF_AB_XX_RSTXGXSTX_EN_WIDTH 1
+#define FRF_AB_XX_RST_XX_EN_LBN 0
+#define FRF_AB_XX_RST_XX_EN_WIDTH 1
+
+/* XX_SD_CTL_REG: XGXS/XAUI powerdown/reset control register */
+#define FR_AB_XX_SD_CTL 0x00001310
+#define FRF_AB_XX_TERMADJ1_LBN 17
+#define FRF_AB_XX_TERMADJ1_WIDTH 1
+#define FRF_AB_XX_TERMADJ0_LBN 16
+#define FRF_AB_XX_TERMADJ0_WIDTH 1
+#define FRF_AB_XX_HIDRVD_LBN 15
+#define FRF_AB_XX_HIDRVD_WIDTH 1
+#define FRF_AB_XX_LODRVD_LBN 14
+#define FRF_AB_XX_LODRVD_WIDTH 1
+#define FRF_AB_XX_HIDRVC_LBN 13
+#define FRF_AB_XX_HIDRVC_WIDTH 1
+#define FRF_AB_XX_LODRVC_LBN 12
+#define FRF_AB_XX_LODRVC_WIDTH 1
+#define FRF_AB_XX_HIDRVB_LBN 11
+#define FRF_AB_XX_HIDRVB_WIDTH 1
+#define FRF_AB_XX_LODRVB_LBN 10
+#define FRF_AB_XX_LODRVB_WIDTH 1
+#define FRF_AB_XX_HIDRVA_LBN 9
+#define FRF_AB_XX_HIDRVA_WIDTH 1
+#define FRF_AB_XX_LODRVA_LBN 8
+#define FRF_AB_XX_LODRVA_WIDTH 1
+#define FRF_AB_XX_LPBKD_LBN 3
+#define FRF_AB_XX_LPBKD_WIDTH 1
+#define FRF_AB_XX_LPBKC_LBN 2
+#define FRF_AB_XX_LPBKC_WIDTH 1
+#define FRF_AB_XX_LPBKB_LBN 1
+#define FRF_AB_XX_LPBKB_WIDTH 1
+#define FRF_AB_XX_LPBKA_LBN 0
+#define FRF_AB_XX_LPBKA_WIDTH 1
+
+/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */
+#define FR_AB_XX_TXDRV_CTL 0x00001320
+#define FRF_AB_XX_DEQD_LBN 28
+#define FRF_AB_XX_DEQD_WIDTH 4
+#define FRF_AB_XX_DEQC_LBN 24
+#define FRF_AB_XX_DEQC_WIDTH 4
+#define FRF_AB_XX_DEQB_LBN 20
+#define FRF_AB_XX_DEQB_WIDTH 4
+#define FRF_AB_XX_DEQA_LBN 16
+#define FRF_AB_XX_DEQA_WIDTH 4
+#define FRF_AB_XX_DTXD_LBN 12
+#define FRF_AB_XX_DTXD_WIDTH 4
+#define FRF_AB_XX_DTXC_LBN 8
+#define FRF_AB_XX_DTXC_WIDTH 4
+#define FRF_AB_XX_DTXB_LBN 4
+#define FRF_AB_XX_DTXB_WIDTH 4
+#define FRF_AB_XX_DTXA_LBN 0
+#define FRF_AB_XX_DTXA_WIDTH 4
+
+/* XX_PRBS_CTL_REG: documentation to be written for sum_XX_PRBS_CTL_REG */
+#define FR_AB_XX_PRBS_CTL 0x00001330
+#define FRF_AB_XX_CH3_RX_PRBS_SEL_LBN 30
+#define FRF_AB_XX_CH3_RX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH3_RX_PRBS_INV_LBN 29
+#define FRF_AB_XX_CH3_RX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH3_RX_PRBS_CHKEN_LBN 28
+#define FRF_AB_XX_CH3_RX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH2_RX_PRBS_SEL_LBN 26
+#define FRF_AB_XX_CH2_RX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH2_RX_PRBS_INV_LBN 25
+#define FRF_AB_XX_CH2_RX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH2_RX_PRBS_CHKEN_LBN 24
+#define FRF_AB_XX_CH2_RX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH1_RX_PRBS_SEL_LBN 22
+#define FRF_AB_XX_CH1_RX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH1_RX_PRBS_INV_LBN 21
+#define FRF_AB_XX_CH1_RX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH1_RX_PRBS_CHKEN_LBN 20
+#define FRF_AB_XX_CH1_RX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH0_RX_PRBS_SEL_LBN 18
+#define FRF_AB_XX_CH0_RX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH0_RX_PRBS_INV_LBN 17
+#define FRF_AB_XX_CH0_RX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH0_RX_PRBS_CHKEN_LBN 16
+#define FRF_AB_XX_CH0_RX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH3_TX_PRBS_SEL_LBN 14
+#define FRF_AB_XX_CH3_TX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH3_TX_PRBS_INV_LBN 13
+#define FRF_AB_XX_CH3_TX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH3_TX_PRBS_CHKEN_LBN 12
+#define FRF_AB_XX_CH3_TX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH2_TX_PRBS_SEL_LBN 10
+#define FRF_AB_XX_CH2_TX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH2_TX_PRBS_INV_LBN 9
+#define FRF_AB_XX_CH2_TX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH2_TX_PRBS_CHKEN_LBN 8
+#define FRF_AB_XX_CH2_TX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH1_TX_PRBS_SEL_LBN 6
+#define FRF_AB_XX_CH1_TX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH1_TX_PRBS_INV_LBN 5
+#define FRF_AB_XX_CH1_TX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH1_TX_PRBS_CHKEN_LBN 4
+#define FRF_AB_XX_CH1_TX_PRBS_CHKEN_WIDTH 1
+#define FRF_AB_XX_CH0_TX_PRBS_SEL_LBN 2
+#define FRF_AB_XX_CH0_TX_PRBS_SEL_WIDTH 2
+#define FRF_AB_XX_CH0_TX_PRBS_INV_LBN 1
+#define FRF_AB_XX_CH0_TX_PRBS_INV_WIDTH 1
+#define FRF_AB_XX_CH0_TX_PRBS_CHKEN_LBN 0
+#define FRF_AB_XX_CH0_TX_PRBS_CHKEN_WIDTH 1
+
+/* XX_PRBS_CHK_REG: documentation to be written for sum_XX_PRBS_CHK_REG */
+#define FR_AB_XX_PRBS_CHK 0x00001340
+#define FRF_AB_XX_REV_LB_EN_LBN 16
+#define FRF_AB_XX_REV_LB_EN_WIDTH 1
+#define FRF_AB_XX_CH3_DEG_DET_LBN 15
+#define FRF_AB_XX_CH3_DEG_DET_WIDTH 1
+#define FRF_AB_XX_CH3_LFSR_LOCK_IND_LBN 14
+#define FRF_AB_XX_CH3_LFSR_LOCK_IND_WIDTH 1
+#define FRF_AB_XX_CH3_PRBS_FRUN_LBN 13
+#define FRF_AB_XX_CH3_PRBS_FRUN_WIDTH 1
+#define FRF_AB_XX_CH3_ERR_CHK_LBN 12
+#define FRF_AB_XX_CH3_ERR_CHK_WIDTH 1
+#define FRF_AB_XX_CH2_DEG_DET_LBN 11
+#define FRF_AB_XX_CH2_DEG_DET_WIDTH 1
+#define FRF_AB_XX_CH2_LFSR_LOCK_IND_LBN 10
+#define FRF_AB_XX_CH2_LFSR_LOCK_IND_WIDTH 1
+#define FRF_AB_XX_CH2_PRBS_FRUN_LBN 9
+#define FRF_AB_XX_CH2_PRBS_FRUN_WIDTH 1
+#define FRF_AB_XX_CH2_ERR_CHK_LBN 8
+#define FRF_AB_XX_CH2_ERR_CHK_WIDTH 1
+#define FRF_AB_XX_CH1_DEG_DET_LBN 7
+#define FRF_AB_XX_CH1_DEG_DET_WIDTH 1
+#define FRF_AB_XX_CH1_LFSR_LOCK_IND_LBN 6
+#define FRF_AB_XX_CH1_LFSR_LOCK_IND_WIDTH 1
+#define FRF_AB_XX_CH1_PRBS_FRUN_LBN 5
+#define FRF_AB_XX_CH1_PRBS_FRUN_WIDTH 1
+#define FRF_AB_XX_CH1_ERR_CHK_LBN 4
+#define FRF_AB_XX_CH1_ERR_CHK_WIDTH 1
+#define FRF_AB_XX_CH0_DEG_DET_LBN 3
+#define FRF_AB_XX_CH0_DEG_DET_WIDTH 1
+#define FRF_AB_XX_CH0_LFSR_LOCK_IND_LBN 2
+#define FRF_AB_XX_CH0_LFSR_LOCK_IND_WIDTH 1
+#define FRF_AB_XX_CH0_PRBS_FRUN_LBN 1
+#define FRF_AB_XX_CH0_PRBS_FRUN_WIDTH 1
+#define FRF_AB_XX_CH0_ERR_CHK_LBN 0
+#define FRF_AB_XX_CH0_ERR_CHK_WIDTH 1
+
+/* XX_PRBS_ERR_REG: documentation to be written for sum_XX_PRBS_ERR_REG */
+#define FR_AB_XX_PRBS_ERR 0x00001350
+#define FRF_AB_XX_CH3_PRBS_ERR_CNT_LBN 24
+#define FRF_AB_XX_CH3_PRBS_ERR_CNT_WIDTH 8
+#define FRF_AB_XX_CH2_PRBS_ERR_CNT_LBN 16
+#define FRF_AB_XX_CH2_PRBS_ERR_CNT_WIDTH 8
+#define FRF_AB_XX_CH1_PRBS_ERR_CNT_LBN 8
+#define FRF_AB_XX_CH1_PRBS_ERR_CNT_WIDTH 8
+#define FRF_AB_XX_CH0_PRBS_ERR_CNT_LBN 0
+#define FRF_AB_XX_CH0_PRBS_ERR_CNT_WIDTH 8
+
+/* XX_CORE_STAT_REG: XAUI XGXS core status register */
+#define FR_AB_XX_CORE_STAT 0x00001360
+#define FRF_AB_XX_FORCE_SIG3_LBN 31
+#define FRF_AB_XX_FORCE_SIG3_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG3_VAL_LBN 30
+#define FRF_AB_XX_FORCE_SIG3_VAL_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG2_LBN 29
+#define FRF_AB_XX_FORCE_SIG2_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG2_VAL_LBN 28
+#define FRF_AB_XX_FORCE_SIG2_VAL_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG1_LBN 27
+#define FRF_AB_XX_FORCE_SIG1_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG1_VAL_LBN 26
+#define FRF_AB_XX_FORCE_SIG1_VAL_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG0_LBN 25
+#define FRF_AB_XX_FORCE_SIG0_WIDTH 1
+#define FRF_AB_XX_FORCE_SIG0_VAL_LBN 24
+#define FRF_AB_XX_FORCE_SIG0_VAL_WIDTH 1
+#define FRF_AB_XX_XGXS_LB_EN_LBN 23
+#define FRF_AB_XX_XGXS_LB_EN_WIDTH 1
+#define FRF_AB_XX_XGMII_LB_EN_LBN 22
+#define FRF_AB_XX_XGMII_LB_EN_WIDTH 1
+#define FRF_AB_XX_MATCH_FAULT_LBN 21
+#define FRF_AB_XX_MATCH_FAULT_WIDTH 1
+#define FRF_AB_XX_ALIGN_DONE_LBN 20
+#define FRF_AB_XX_ALIGN_DONE_WIDTH 1
+#define FRF_AB_XX_SYNC_STAT3_LBN 19
+#define FRF_AB_XX_SYNC_STAT3_WIDTH 1
+#define FRF_AB_XX_SYNC_STAT2_LBN 18
+#define FRF_AB_XX_SYNC_STAT2_WIDTH 1
+#define FRF_AB_XX_SYNC_STAT1_LBN 17
+#define FRF_AB_XX_SYNC_STAT1_WIDTH 1
+#define FRF_AB_XX_SYNC_STAT0_LBN 16
+#define FRF_AB_XX_SYNC_STAT0_WIDTH 1
+#define FRF_AB_XX_COMMA_DET_CH3_LBN 15
+#define FRF_AB_XX_COMMA_DET_CH3_WIDTH 1
+#define FRF_AB_XX_COMMA_DET_CH2_LBN 14
+#define FRF_AB_XX_COMMA_DET_CH2_WIDTH 1
+#define FRF_AB_XX_COMMA_DET_CH1_LBN 13
+#define FRF_AB_XX_COMMA_DET_CH1_WIDTH 1
+#define FRF_AB_XX_COMMA_DET_CH0_LBN 12
+#define FRF_AB_XX_COMMA_DET_CH0_WIDTH 1
+#define FRF_AB_XX_CGRP_ALIGN_CH3_LBN 11
+#define FRF_AB_XX_CGRP_ALIGN_CH3_WIDTH 1
+#define FRF_AB_XX_CGRP_ALIGN_CH2_LBN 10
+#define FRF_AB_XX_CGRP_ALIGN_CH2_WIDTH 1
+#define FRF_AB_XX_CGRP_ALIGN_CH1_LBN 9
+#define FRF_AB_XX_CGRP_ALIGN_CH1_WIDTH 1
+#define FRF_AB_XX_CGRP_ALIGN_CH0_LBN 8
+#define FRF_AB_XX_CGRP_ALIGN_CH0_WIDTH 1
+#define FRF_AB_XX_CHAR_ERR_CH3_LBN 7
+#define FRF_AB_XX_CHAR_ERR_CH3_WIDTH 1
+#define FRF_AB_XX_CHAR_ERR_CH2_LBN 6
+#define FRF_AB_XX_CHAR_ERR_CH2_WIDTH 1
+#define FRF_AB_XX_CHAR_ERR_CH1_LBN 5
+#define FRF_AB_XX_CHAR_ERR_CH1_WIDTH 1
+#define FRF_AB_XX_CHAR_ERR_CH0_LBN 4
+#define FRF_AB_XX_CHAR_ERR_CH0_WIDTH 1
+#define FRF_AB_XX_DISPERR_CH3_LBN 3
+#define FRF_AB_XX_DISPERR_CH3_WIDTH 1
+#define FRF_AB_XX_DISPERR_CH2_LBN 2
+#define FRF_AB_XX_DISPERR_CH2_WIDTH 1
+#define FRF_AB_XX_DISPERR_CH1_LBN 1
+#define FRF_AB_XX_DISPERR_CH1_WIDTH 1
+#define FRF_AB_XX_DISPERR_CH0_LBN 0
+#define FRF_AB_XX_DISPERR_CH0_WIDTH 1
+
+/* RX_DESC_PTR_TBL_KER: Receive descriptor pointer table */
+#define FR_AA_RX_DESC_PTR_TBL_KER 0x00011800
+#define FR_AA_RX_DESC_PTR_TBL_KER_STEP 16
+#define FR_AA_RX_DESC_PTR_TBL_KER_ROWS 4
+/* RX_DESC_PTR_TBL: Receive descriptor pointer table */
+#define FR_BZ_RX_DESC_PTR_TBL 0x00f40000
+#define FR_BZ_RX_DESC_PTR_TBL_STEP 16
+#define FR_BB_RX_DESC_PTR_TBL_ROWS 4096
+#define FR_CZ_RX_DESC_PTR_TBL_ROWS 1024
+#define FRF_CZ_RX_HDR_SPLIT_LBN 90
+#define FRF_CZ_RX_HDR_SPLIT_WIDTH 1
+#define FRF_AA_RX_RESET_LBN 89
+#define FRF_AA_RX_RESET_WIDTH 1
+#define FRF_AZ_RX_ISCSI_DDIG_EN_LBN 88
+#define FRF_AZ_RX_ISCSI_DDIG_EN_WIDTH 1
+#define FRF_AZ_RX_ISCSI_HDIG_EN_LBN 87
+#define FRF_AZ_RX_ISCSI_HDIG_EN_WIDTH 1
+#define FRF_AZ_RX_DESC_PREF_ACT_LBN 86
+#define FRF_AZ_RX_DESC_PREF_ACT_WIDTH 1
+#define FRF_AZ_RX_DC_HW_RPTR_LBN 80
+#define FRF_AZ_RX_DC_HW_RPTR_WIDTH 6
+#define FRF_AZ_RX_DESCQ_HW_RPTR_LBN 68
+#define FRF_AZ_RX_DESCQ_HW_RPTR_WIDTH 12
+#define FRF_AZ_RX_DESCQ_SW_WPTR_LBN 56
+#define FRF_AZ_RX_DESCQ_SW_WPTR_WIDTH 12
+#define FRF_AZ_RX_DESCQ_BUF_BASE_ID_LBN 36
+#define FRF_AZ_RX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FRF_AZ_RX_DESCQ_EVQ_ID_LBN 24
+#define FRF_AZ_RX_DESCQ_EVQ_ID_WIDTH 12
+#define FRF_AZ_RX_DESCQ_OWNER_ID_LBN 10
+#define FRF_AZ_RX_DESCQ_OWNER_ID_WIDTH 14
+#define FRF_AZ_RX_DESCQ_LABEL_LBN 5
+#define FRF_AZ_RX_DESCQ_LABEL_WIDTH 5
+#define FRF_AZ_RX_DESCQ_SIZE_LBN 3
+#define FRF_AZ_RX_DESCQ_SIZE_WIDTH 2
+#define FFE_AZ_RX_DESCQ_SIZE_4K 3
+#define FFE_AZ_RX_DESCQ_SIZE_2K 2
+#define FFE_AZ_RX_DESCQ_SIZE_1K 1
+#define FFE_AZ_RX_DESCQ_SIZE_512 0
+#define FRF_AZ_RX_DESCQ_TYPE_LBN 2
+#define FRF_AZ_RX_DESCQ_TYPE_WIDTH 1
+#define FRF_AZ_RX_DESCQ_JUMBO_LBN 1
+#define FRF_AZ_RX_DESCQ_JUMBO_WIDTH 1
+#define FRF_AZ_RX_DESCQ_EN_LBN 0
+#define FRF_AZ_RX_DESCQ_EN_WIDTH 1
+
+/* TX_DESC_PTR_TBL_KER: Transmit descriptor pointer */
+#define FR_AA_TX_DESC_PTR_TBL_KER 0x00011900
+#define FR_AA_TX_DESC_PTR_TBL_KER_STEP 16
+#define FR_AA_TX_DESC_PTR_TBL_KER_ROWS 8
+/* TX_DESC_PTR_TBL: Transmit descriptor pointer */
+#define FR_BZ_TX_DESC_PTR_TBL 0x00f50000
+#define FR_BZ_TX_DESC_PTR_TBL_STEP 16
+#define FR_BB_TX_DESC_PTR_TBL_ROWS 4096
+#define FR_CZ_TX_DESC_PTR_TBL_ROWS 1024
+#define FRF_CZ_TX_DPT_Q_MASK_WIDTH_LBN 94
+#define FRF_CZ_TX_DPT_Q_MASK_WIDTH_WIDTH 2
+#define FRF_CZ_TX_DPT_ETH_FILT_EN_LBN 93
+#define FRF_CZ_TX_DPT_ETH_FILT_EN_WIDTH 1
+#define FRF_CZ_TX_DPT_IP_FILT_EN_LBN 92
+#define FRF_CZ_TX_DPT_IP_FILT_EN_WIDTH 1
+#define FRF_BZ_TX_NON_IP_DROP_DIS_LBN 91
+#define FRF_BZ_TX_NON_IP_DROP_DIS_WIDTH 1
+#define FRF_BZ_TX_IP_CHKSM_DIS_LBN 90
+#define FRF_BZ_TX_IP_CHKSM_DIS_WIDTH 1
+#define FRF_BZ_TX_TCP_CHKSM_DIS_LBN 89
+#define FRF_BZ_TX_TCP_CHKSM_DIS_WIDTH 1
+#define FRF_AZ_TX_DESCQ_EN_LBN 88
+#define FRF_AZ_TX_DESCQ_EN_WIDTH 1
+#define FRF_AZ_TX_ISCSI_DDIG_EN_LBN 87
+#define FRF_AZ_TX_ISCSI_DDIG_EN_WIDTH 1
+#define FRF_AZ_TX_ISCSI_HDIG_EN_LBN 86
+#define FRF_AZ_TX_ISCSI_HDIG_EN_WIDTH 1
+#define FRF_AZ_TX_DC_HW_RPTR_LBN 80
+#define FRF_AZ_TX_DC_HW_RPTR_WIDTH 6
+#define FRF_AZ_TX_DESCQ_HW_RPTR_LBN 68
+#define FRF_AZ_TX_DESCQ_HW_RPTR_WIDTH 12
+#define FRF_AZ_TX_DESCQ_SW_WPTR_LBN 56
+#define FRF_AZ_TX_DESCQ_SW_WPTR_WIDTH 12
+#define FRF_AZ_TX_DESCQ_BUF_BASE_ID_LBN 36
+#define FRF_AZ_TX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FRF_AZ_TX_DESCQ_EVQ_ID_LBN 24
+#define FRF_AZ_TX_DESCQ_EVQ_ID_WIDTH 12
+#define FRF_AZ_TX_DESCQ_OWNER_ID_LBN 10
+#define FRF_AZ_TX_DESCQ_OWNER_ID_WIDTH 14
+#define FRF_AZ_TX_DESCQ_LABEL_LBN 5
+#define FRF_AZ_TX_DESCQ_LABEL_WIDTH 5
+#define FRF_AZ_TX_DESCQ_SIZE_LBN 3
+#define FRF_AZ_TX_DESCQ_SIZE_WIDTH 2
+#define FFE_AZ_TX_DESCQ_SIZE_4K 3
+#define FFE_AZ_TX_DESCQ_SIZE_2K 2
+#define FFE_AZ_TX_DESCQ_SIZE_1K 1
+#define FFE_AZ_TX_DESCQ_SIZE_512 0
+#define FRF_AZ_TX_DESCQ_TYPE_LBN 1
+#define FRF_AZ_TX_DESCQ_TYPE_WIDTH 2
+#define FRF_AZ_TX_DESCQ_FLUSH_LBN 0
+#define FRF_AZ_TX_DESCQ_FLUSH_WIDTH 1
+
+/* EVQ_PTR_TBL_KER: Event queue pointer table */
+#define FR_AA_EVQ_PTR_TBL_KER 0x00011a00
+#define FR_AA_EVQ_PTR_TBL_KER_STEP 16
+#define FR_AA_EVQ_PTR_TBL_KER_ROWS 4
+/* EVQ_PTR_TBL: Event queue pointer table */
+#define FR_BZ_EVQ_PTR_TBL 0x00f60000
+#define FR_BZ_EVQ_PTR_TBL_STEP 16
+#define FR_CZ_EVQ_PTR_TBL_ROWS 1024
+#define FR_BB_EVQ_PTR_TBL_ROWS 4096
+#define FRF_BZ_EVQ_RPTR_IGN_LBN 40
+#define FRF_BZ_EVQ_RPTR_IGN_WIDTH 1
+#define FRF_AB_EVQ_WKUP_OR_INT_EN_LBN 39
+#define FRF_AB_EVQ_WKUP_OR_INT_EN_WIDTH 1
+#define FRF_CZ_EVQ_DOS_PROTECT_EN_LBN 39
+#define FRF_CZ_EVQ_DOS_PROTECT_EN_WIDTH 1
+#define FRF_AZ_EVQ_NXT_WPTR_LBN 24
+#define FRF_AZ_EVQ_NXT_WPTR_WIDTH 15
+#define FRF_AZ_EVQ_EN_LBN 23
+#define FRF_AZ_EVQ_EN_WIDTH 1
+#define FRF_AZ_EVQ_SIZE_LBN 20
+#define FRF_AZ_EVQ_SIZE_WIDTH 3
+#define FFE_AZ_EVQ_SIZE_32K 6
+#define FFE_AZ_EVQ_SIZE_16K 5
+#define FFE_AZ_EVQ_SIZE_8K 4
+#define FFE_AZ_EVQ_SIZE_4K 3
+#define FFE_AZ_EVQ_SIZE_2K 2
+#define FFE_AZ_EVQ_SIZE_1K 1
+#define FFE_AZ_EVQ_SIZE_512 0
+#define FRF_AZ_EVQ_BUF_BASE_ID_LBN 0
+#define FRF_AZ_EVQ_BUF_BASE_ID_WIDTH 20
+
+/* BUF_HALF_TBL_KER: Buffer table in half buffer table mode direct access by driver */
+#define FR_AA_BUF_HALF_TBL_KER 0x00018000
+#define FR_AA_BUF_HALF_TBL_KER_STEP 8
+#define FR_AA_BUF_HALF_TBL_KER_ROWS 4096
+/* BUF_HALF_TBL: Buffer table in half buffer table mode direct access by driver */
+#define FR_BZ_BUF_HALF_TBL 0x00800000
+#define FR_BZ_BUF_HALF_TBL_STEP 8
+#define FR_CZ_BUF_HALF_TBL_ROWS 147456
+#define FR_BB_BUF_HALF_TBL_ROWS 524288
+#define FRF_AZ_BUF_ADR_HBUF_ODD_LBN 44
+#define FRF_AZ_BUF_ADR_HBUF_ODD_WIDTH 20
+#define FRF_AZ_BUF_OWNER_ID_HBUF_ODD_LBN 32
+#define FRF_AZ_BUF_OWNER_ID_HBUF_ODD_WIDTH 12
+#define FRF_AZ_BUF_ADR_HBUF_EVEN_LBN 12
+#define FRF_AZ_BUF_ADR_HBUF_EVEN_WIDTH 20
+#define FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_LBN 0
+#define FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
+
+/* BUF_FULL_TBL_KER: Buffer table in full buffer table mode direct access by driver */
+#define FR_AA_BUF_FULL_TBL_KER 0x00018000
+#define FR_AA_BUF_FULL_TBL_KER_STEP 8
+#define FR_AA_BUF_FULL_TBL_KER_ROWS 4096
+/* BUF_FULL_TBL: Buffer table in full buffer table mode direct access by driver */
+#define FR_BZ_BUF_FULL_TBL 0x00800000
+#define FR_BZ_BUF_FULL_TBL_STEP 8
+#define FR_CZ_BUF_FULL_TBL_ROWS 147456
+#define FR_BB_BUF_FULL_TBL_ROWS 917504
+#define FRF_AZ_BUF_FULL_UNUSED_LBN 51
+#define FRF_AZ_BUF_FULL_UNUSED_WIDTH 13
+#define FRF_AZ_IP_DAT_BUF_SIZE_LBN 50
+#define FRF_AZ_IP_DAT_BUF_SIZE_WIDTH 1
+#define FRF_AZ_BUF_ADR_REGION_LBN 48
+#define FRF_AZ_BUF_ADR_REGION_WIDTH 2
+#define FFE_AZ_BUF_ADR_REGN3 3
+#define FFE_AZ_BUF_ADR_REGN2 2
+#define FFE_AZ_BUF_ADR_REGN1 1
+#define FFE_AZ_BUF_ADR_REGN0 0
+#define FRF_AZ_BUF_ADR_FBUF_LBN 14
+#define FRF_AZ_BUF_ADR_FBUF_WIDTH 34
+#define FRF_AZ_BUF_OWNER_ID_FBUF_LBN 0
+#define FRF_AZ_BUF_OWNER_ID_FBUF_WIDTH 14
+
+/* RX_FILTER_TBL0: TCP/IPv4 Receive filter table */
+#define FR_BZ_RX_FILTER_TBL0 0x00f00000
+#define FR_BZ_RX_FILTER_TBL0_STEP 32
+#define FR_BZ_RX_FILTER_TBL0_ROWS 8192
+/* RX_FILTER_TBL1: TCP/IPv4 Receive filter table */
+#define FR_BB_RX_FILTER_TBL1 0x00f00010
+#define FR_BB_RX_FILTER_TBL1_STEP 32
+#define FR_BB_RX_FILTER_TBL1_ROWS 8192
+#define FRF_BZ_RSS_EN_LBN 110
+#define FRF_BZ_RSS_EN_WIDTH 1
+#define FRF_BZ_SCATTER_EN_LBN 109
+#define FRF_BZ_SCATTER_EN_WIDTH 1
+#define FRF_BZ_TCP_UDP_LBN 108
+#define FRF_BZ_TCP_UDP_WIDTH 1
+#define FRF_BZ_RXQ_ID_LBN 96
+#define FRF_BZ_RXQ_ID_WIDTH 12
+#define FRF_BZ_DEST_IP_LBN 64
+#define FRF_BZ_DEST_IP_WIDTH 32
+#define FRF_BZ_DEST_PORT_TCP_LBN 48
+#define FRF_BZ_DEST_PORT_TCP_WIDTH 16
+#define FRF_BZ_SRC_IP_LBN 16
+#define FRF_BZ_SRC_IP_WIDTH 32
+#define FRF_BZ_SRC_TCP_DEST_UDP_LBN 0
+#define FRF_BZ_SRC_TCP_DEST_UDP_WIDTH 16
+
+/* RX_MAC_FILTER_TBL0: Receive Ethernet filter table */
+#define FR_CZ_RX_MAC_FILTER_TBL0 0x00f00010
+#define FR_CZ_RX_MAC_FILTER_TBL0_STEP 32
+#define FR_CZ_RX_MAC_FILTER_TBL0_ROWS 512
+#define FRF_CZ_RMFT_RSS_EN_LBN 75
+#define FRF_CZ_RMFT_RSS_EN_WIDTH 1
+#define FRF_CZ_RMFT_SCATTER_EN_LBN 74
+#define FRF_CZ_RMFT_SCATTER_EN_WIDTH 1
+#define FRF_CZ_RMFT_IP_OVERRIDE_LBN 73
+#define FRF_CZ_RMFT_IP_OVERRIDE_WIDTH 1
+#define FRF_CZ_RMFT_RXQ_ID_LBN 61
+#define FRF_CZ_RMFT_RXQ_ID_WIDTH 12
+#define FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60
+#define FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1
+#define FRF_CZ_RMFT_DEST_MAC_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_WIDTH 48
+#define FRF_CZ_RMFT_VLAN_ID_LBN 0
+#define FRF_CZ_RMFT_VLAN_ID_WIDTH 12
+
+/* TIMER_TBL: Timer table */
+#define FR_BZ_TIMER_TBL 0x00f70000
+#define FR_BZ_TIMER_TBL_STEP 16
+#define FR_CZ_TIMER_TBL_ROWS 1024
+#define FR_BB_TIMER_TBL_ROWS 4096
+#define FRF_CZ_TIMER_Q_EN_LBN 33
+#define FRF_CZ_TIMER_Q_EN_WIDTH 1
+#define FRF_CZ_INT_ARMD_LBN 32
+#define FRF_CZ_INT_ARMD_WIDTH 1
+#define FRF_CZ_INT_PEND_LBN 31
+#define FRF_CZ_INT_PEND_WIDTH 1
+#define FRF_CZ_HOST_NOTIFY_MODE_LBN 30
+#define FRF_CZ_HOST_NOTIFY_MODE_WIDTH 1
+#define FRF_CZ_RELOAD_TIMER_VAL_LBN 16
+#define FRF_CZ_RELOAD_TIMER_VAL_WIDTH 14
+#define FRF_CZ_TIMER_MODE_LBN 14
+#define FRF_CZ_TIMER_MODE_WIDTH 2
+#define FFE_CZ_TIMER_MODE_INT_HLDOFF 3
+#define FFE_CZ_TIMER_MODE_TRIG_START 2
+#define FFE_CZ_TIMER_MODE_IMMED_START 1
+#define FFE_CZ_TIMER_MODE_DIS 0
+#define FRF_BB_TIMER_MODE_LBN 12
+#define FRF_BB_TIMER_MODE_WIDTH 2
+#define FFE_BB_TIMER_MODE_INT_HLDOFF 2
+#define FFE_BB_TIMER_MODE_TRIG_START 2
+#define FFE_BB_TIMER_MODE_IMMED_START 1
+#define FFE_BB_TIMER_MODE_DIS 0
+#define FRF_CZ_TIMER_VAL_LBN 0
+#define FRF_CZ_TIMER_VAL_WIDTH 14
+#define FRF_BB_TIMER_VAL_LBN 0
+#define FRF_BB_TIMER_VAL_WIDTH 12
+
+/* TX_PACE_TBL: Transmit pacing table */
+#define FR_BZ_TX_PACE_TBL 0x00f80000
+#define FR_BZ_TX_PACE_TBL_STEP 16
+#define FR_CZ_TX_PACE_TBL_ROWS 1024
+#define FR_BB_TX_PACE_TBL_ROWS 4096
+#define FRF_BZ_TX_PACE_LBN 0
+#define FRF_BZ_TX_PACE_WIDTH 5
+
+/* RX_INDIRECTION_TBL: RX Indirection Table */
+#define FR_BZ_RX_INDIRECTION_TBL 0x00fb0000
+#define FR_BZ_RX_INDIRECTION_TBL_STEP 16
+#define FR_BZ_RX_INDIRECTION_TBL_ROWS 128
+#define FRF_BZ_IT_QUEUE_LBN 0
+#define FRF_BZ_IT_QUEUE_WIDTH 6
+
+/* TX_FILTER_TBL0: TCP/IPv4 Transmit filter table */
+#define FR_CZ_TX_FILTER_TBL0 0x00fc0000
+#define FR_CZ_TX_FILTER_TBL0_STEP 16
+#define FR_CZ_TX_FILTER_TBL0_ROWS 8192
+#define FRF_CZ_TIFT_TCP_UDP_LBN 108
+#define FRF_CZ_TIFT_TCP_UDP_WIDTH 1
+#define FRF_CZ_TIFT_TXQ_ID_LBN 96
+#define FRF_CZ_TIFT_TXQ_ID_WIDTH 12
+#define FRF_CZ_TIFT_DEST_IP_LBN 64
+#define FRF_CZ_TIFT_DEST_IP_WIDTH 32
+#define FRF_CZ_TIFT_DEST_PORT_TCP_LBN 48
+#define FRF_CZ_TIFT_DEST_PORT_TCP_WIDTH 16
+#define FRF_CZ_TIFT_SRC_IP_LBN 16
+#define FRF_CZ_TIFT_SRC_IP_WIDTH 32
+#define FRF_CZ_TIFT_SRC_TCP_DEST_UDP_LBN 0
+#define FRF_CZ_TIFT_SRC_TCP_DEST_UDP_WIDTH 16
+
+/* TX_MAC_FILTER_TBL0: Transmit Ethernet filter table */
+#define FR_CZ_TX_MAC_FILTER_TBL0 0x00fe0000
+#define FR_CZ_TX_MAC_FILTER_TBL0_STEP 16
+#define FR_CZ_TX_MAC_FILTER_TBL0_ROWS 512
+#define FRF_CZ_TMFT_TXQ_ID_LBN 61
+#define FRF_CZ_TMFT_TXQ_ID_WIDTH 12
+#define FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60
+#define FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1
+#define FRF_CZ_TMFT_SRC_MAC_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_WIDTH 48
+#define FRF_CZ_TMFT_VLAN_ID_LBN 0
+#define FRF_CZ_TMFT_VLAN_ID_WIDTH 12
+
+/* MC_TREG_SMEM: MC Shared Memory */
+#define FR_CZ_MC_TREG_SMEM 0x00ff0000
+#define FR_CZ_MC_TREG_SMEM_STEP 4
+#define FR_CZ_MC_TREG_SMEM_ROWS 512
+#define FRF_CZ_MC_TREG_SMEM_ROW_LBN 0
+#define FRF_CZ_MC_TREG_SMEM_ROW_WIDTH 32
+
+/* MSIX_VECTOR_TABLE: MSIX Vector Table */
+#define FR_BB_MSIX_VECTOR_TABLE 0x00ff0000
+#define FR_BZ_MSIX_VECTOR_TABLE_STEP 16
+#define FR_BB_MSIX_VECTOR_TABLE_ROWS 64
+/* MSIX_VECTOR_TABLE: MSIX Vector Table */
+#define FR_CZ_MSIX_VECTOR_TABLE 0x00000000
+/* FR_BZ_MSIX_VECTOR_TABLE_STEP 16 */
+#define FR_CZ_MSIX_VECTOR_TABLE_ROWS 1024
+#define FRF_BZ_MSIX_VECTOR_RESERVED_LBN 97
+#define FRF_BZ_MSIX_VECTOR_RESERVED_WIDTH 31
+#define FRF_BZ_MSIX_VECTOR_MASK_LBN 96
+#define FRF_BZ_MSIX_VECTOR_MASK_WIDTH 1
+#define FRF_BZ_MSIX_MESSAGE_DATA_LBN 64
+#define FRF_BZ_MSIX_MESSAGE_DATA_WIDTH 32
+#define FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_LBN 32
+#define FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_WIDTH 32
+#define FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_LBN 0
+#define FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_WIDTH 32
+
+/* MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define FR_BB_MSIX_PBA_TABLE 0x00ff2000
+#define FR_BZ_MSIX_PBA_TABLE_STEP 4
+#define FR_BB_MSIX_PBA_TABLE_ROWS 2
+/* MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define FR_CZ_MSIX_PBA_TABLE 0x00008000
+/* FR_BZ_MSIX_PBA_TABLE_STEP 4 */
+#define FR_CZ_MSIX_PBA_TABLE_ROWS 32
+#define FRF_BZ_MSIX_PBA_PEND_DWORD_LBN 0
+#define FRF_BZ_MSIX_PBA_PEND_DWORD_WIDTH 32
+
+/* SRM_DBG_REG: SRAM debug access */
+#define FR_BZ_SRM_DBG 0x03000000
+#define FR_BZ_SRM_DBG_STEP 8
+#define FR_CZ_SRM_DBG_ROWS 262144
+#define FR_BB_SRM_DBG_ROWS 2097152
+#define FRF_BZ_SRM_DBG_LBN 0
+#define FRF_BZ_SRM_DBG_WIDTH 64
+
+/* TB_MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define FR_CZ_TB_MSIX_PBA_TABLE 0x00008000
+#define FR_CZ_TB_MSIX_PBA_TABLE_STEP 4
+#define FR_CZ_TB_MSIX_PBA_TABLE_ROWS 1024
+#define FRF_CZ_TB_MSIX_PBA_PEND_DWORD_LBN 0
+#define FRF_CZ_TB_MSIX_PBA_PEND_DWORD_WIDTH 32
+
+/* DRIVER_EV */
+#define FSF_AZ_DRIVER_EV_SUBCODE_LBN 56
+#define FSF_AZ_DRIVER_EV_SUBCODE_WIDTH 4
+#define FSE_BZ_TX_DSC_ERROR_EV 15
+#define FSE_BZ_RX_DSC_ERROR_EV 14
+#define FSE_AA_RX_RECOVER_EV 11
+#define FSE_AZ_TIMER_EV 10
+#define FSE_AZ_TX_PKT_NON_TCP_UDP 9
+#define FSE_AZ_WAKE_UP_EV 6
+#define FSE_AZ_SRM_UPD_DONE_EV 5
+#define FSE_AB_EVQ_NOT_EN_EV 3
+#define FSE_AZ_EVQ_INIT_DONE_EV 2
+#define FSE_AZ_RX_DESCQ_FLS_DONE_EV 1
+#define FSE_AZ_TX_DESCQ_FLS_DONE_EV 0
+#define FSF_AZ_DRIVER_EV_SUBDATA_LBN 0
+#define FSF_AZ_DRIVER_EV_SUBDATA_WIDTH 14
+
+/* EVENT_ENTRY */
+#define FSF_AZ_EV_CODE_LBN 60
+#define FSF_AZ_EV_CODE_WIDTH 4
+#define FSE_CZ_EV_CODE_MCDI_EV 12
+#define FSE_CZ_EV_CODE_USER_EV 8
+#define FSE_AZ_EV_CODE_DRV_GEN_EV 7
+#define FSE_AZ_EV_CODE_GLOBAL_EV 6
+#define FSE_AZ_EV_CODE_DRIVER_EV 5
+#define FSE_AZ_EV_CODE_TX_EV 2
+#define FSE_AZ_EV_CODE_RX_EV 0
+#define FSF_AZ_EV_DATA_LBN 0
+#define FSF_AZ_EV_DATA_WIDTH 60
+
+/* GLOBAL_EV */
+#define FSF_BB_GLB_EV_RX_RECOVERY_LBN 12
+#define FSF_BB_GLB_EV_RX_RECOVERY_WIDTH 1
+#define FSF_AA_GLB_EV_RX_RECOVERY_LBN 11
+#define FSF_AA_GLB_EV_RX_RECOVERY_WIDTH 1
+#define FSF_BB_GLB_EV_XG_MGT_INTR_LBN 11
+#define FSF_BB_GLB_EV_XG_MGT_INTR_WIDTH 1
+#define FSF_AB_GLB_EV_XFP_PHY0_INTR_LBN 10
+#define FSF_AB_GLB_EV_XFP_PHY0_INTR_WIDTH 1
+#define FSF_AB_GLB_EV_XG_PHY0_INTR_LBN 9
+#define FSF_AB_GLB_EV_XG_PHY0_INTR_WIDTH 1
+#define FSF_AB_GLB_EV_G_PHY0_INTR_LBN 7
+#define FSF_AB_GLB_EV_G_PHY0_INTR_WIDTH 1
+
+/* LEGACY_INT_VEC */
+#define FSF_AZ_NET_IVEC_FATAL_INT_LBN 64
+#define FSF_AZ_NET_IVEC_FATAL_INT_WIDTH 1
+#define FSF_AZ_NET_IVEC_INT_Q_LBN 40
+#define FSF_AZ_NET_IVEC_INT_Q_WIDTH 4
+#define FSF_AZ_NET_IVEC_INT_FLAG_LBN 32
+#define FSF_AZ_NET_IVEC_INT_FLAG_WIDTH 1
+#define FSF_AZ_NET_IVEC_EVQ_FIFO_HF_LBN 1
+#define FSF_AZ_NET_IVEC_EVQ_FIFO_HF_WIDTH 1
+#define FSF_AZ_NET_IVEC_EVQ_FIFO_AF_LBN 0
+#define FSF_AZ_NET_IVEC_EVQ_FIFO_AF_WIDTH 1
+
+/* MC_XGMAC_FLTR_RULE_DEF */
+#define FSF_CZ_MC_XFRC_MODE_LBN 416
+#define FSF_CZ_MC_XFRC_MODE_WIDTH 1
+#define FSE_CZ_MC_XFRC_MODE_LAYERED 1
+#define FSE_CZ_MC_XFRC_MODE_SIMPLE 0
+#define FSF_CZ_MC_XFRC_HASH_LBN 384
+#define FSF_CZ_MC_XFRC_HASH_WIDTH 32
+#define FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_LBN 256
+#define FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_WIDTH 128
+#define FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_LBN 128
+#define FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_WIDTH 128
+#define FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_LBN 0
+#define FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_WIDTH 128
+
+/* RX_EV */
+#define FSF_CZ_RX_EV_PKT_NOT_PARSED_LBN 58
+#define FSF_CZ_RX_EV_PKT_NOT_PARSED_WIDTH 1
+#define FSF_CZ_RX_EV_IPV6_PKT_LBN 57
+#define FSF_CZ_RX_EV_IPV6_PKT_WIDTH 1
+#define FSF_AZ_RX_EV_PKT_OK_LBN 56
+#define FSF_AZ_RX_EV_PKT_OK_WIDTH 1
+#define FSF_AZ_RX_EV_PAUSE_FRM_ERR_LBN 55
+#define FSF_AZ_RX_EV_PAUSE_FRM_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_LBN 54
+#define FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_IP_FRAG_ERR_LBN 53
+#define FSF_AZ_RX_EV_IP_FRAG_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
+#define FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
+#define FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_ETH_CRC_ERR_LBN 50
+#define FSF_AZ_RX_EV_ETH_CRC_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_FRM_TRUNC_LBN 49
+#define FSF_AZ_RX_EV_FRM_TRUNC_WIDTH 1
+#define FSF_AA_RX_EV_DRIB_NIB_LBN 49
+#define FSF_AA_RX_EV_DRIB_NIB_WIDTH 1
+#define FSF_AZ_RX_EV_TOBE_DISC_LBN 47
+#define FSF_AZ_RX_EV_TOBE_DISC_WIDTH 1
+#define FSF_AZ_RX_EV_PKT_TYPE_LBN 44
+#define FSF_AZ_RX_EV_PKT_TYPE_WIDTH 3
+#define FSE_AZ_RX_EV_PKT_TYPE_VLAN_JUMBO 5
+#define FSE_AZ_RX_EV_PKT_TYPE_VLAN_LLC 4
+#define FSE_AZ_RX_EV_PKT_TYPE_VLAN 3
+#define FSE_AZ_RX_EV_PKT_TYPE_JUMBO 2
+#define FSE_AZ_RX_EV_PKT_TYPE_LLC 1
+#define FSE_AZ_RX_EV_PKT_TYPE_ETH 0
+#define FSF_AZ_RX_EV_HDR_TYPE_LBN 42
+#define FSF_AZ_RX_EV_HDR_TYPE_WIDTH 2
+#define FSE_AZ_RX_EV_HDR_TYPE_OTHER 3
+#define FSE_AB_RX_EV_HDR_TYPE_IPV4_OTHER 2
+#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER 2
+#define FSE_AB_RX_EV_HDR_TYPE_IPV4_UDP 1
+#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP 1
+#define FSE_AB_RX_EV_HDR_TYPE_IPV4_TCP 0
+#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP 0
+#define FSF_AZ_RX_EV_DESC_Q_EMPTY_LBN 41
+#define FSF_AZ_RX_EV_DESC_Q_EMPTY_WIDTH 1
+#define FSF_AZ_RX_EV_MCAST_HASH_MATCH_LBN 40
+#define FSF_AZ_RX_EV_MCAST_HASH_MATCH_WIDTH 1
+#define FSF_AZ_RX_EV_MCAST_PKT_LBN 39
+#define FSF_AZ_RX_EV_MCAST_PKT_WIDTH 1
+#define FSF_AA_RX_EV_RECOVERY_FLAG_LBN 37
+#define FSF_AA_RX_EV_RECOVERY_FLAG_WIDTH 1
+#define FSF_AZ_RX_EV_Q_LABEL_LBN 32
+#define FSF_AZ_RX_EV_Q_LABEL_WIDTH 5
+#define FSF_AZ_RX_EV_JUMBO_CONT_LBN 31
+#define FSF_AZ_RX_EV_JUMBO_CONT_WIDTH 1
+#define FSF_AZ_RX_EV_PORT_LBN 30
+#define FSF_AZ_RX_EV_PORT_WIDTH 1
+#define FSF_AZ_RX_EV_BYTE_CNT_LBN 16
+#define FSF_AZ_RX_EV_BYTE_CNT_WIDTH 14
+#define FSF_AZ_RX_EV_SOP_LBN 15
+#define FSF_AZ_RX_EV_SOP_WIDTH 1
+#define FSF_AZ_RX_EV_ISCSI_PKT_OK_LBN 14
+#define FSF_AZ_RX_EV_ISCSI_PKT_OK_WIDTH 1
+#define FSF_AZ_RX_EV_ISCSI_DDIG_ERR_LBN 13
+#define FSF_AZ_RX_EV_ISCSI_DDIG_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_ISCSI_HDIG_ERR_LBN 12
+#define FSF_AZ_RX_EV_ISCSI_HDIG_ERR_WIDTH 1
+#define FSF_AZ_RX_EV_DESC_PTR_LBN 0
+#define FSF_AZ_RX_EV_DESC_PTR_WIDTH 12
+
+/* RX_KER_DESC */
+#define FSF_AZ_RX_KER_BUF_SIZE_LBN 48
+#define FSF_AZ_RX_KER_BUF_SIZE_WIDTH 14
+#define FSF_AZ_RX_KER_BUF_REGION_LBN 46
+#define FSF_AZ_RX_KER_BUF_REGION_WIDTH 2
+#define FSF_AZ_RX_KER_BUF_ADDR_LBN 0
+#define FSF_AZ_RX_KER_BUF_ADDR_WIDTH 46
+
+/* RX_USER_DESC */
+#define FSF_AZ_RX_USER_2BYTE_OFFSET_LBN 20
+#define FSF_AZ_RX_USER_2BYTE_OFFSET_WIDTH 12
+#define FSF_AZ_RX_USER_BUF_ID_LBN 0
+#define FSF_AZ_RX_USER_BUF_ID_WIDTH 20
+
+/* TX_EV */
+#define FSF_AZ_TX_EV_PKT_ERR_LBN 38
+#define FSF_AZ_TX_EV_PKT_ERR_WIDTH 1
+#define FSF_AZ_TX_EV_PKT_TOO_BIG_LBN 37
+#define FSF_AZ_TX_EV_PKT_TOO_BIG_WIDTH 1
+#define FSF_AZ_TX_EV_Q_LABEL_LBN 32
+#define FSF_AZ_TX_EV_Q_LABEL_WIDTH 5
+#define FSF_AZ_TX_EV_PORT_LBN 16
+#define FSF_AZ_TX_EV_PORT_WIDTH 1
+#define FSF_AZ_TX_EV_WQ_FF_FULL_LBN 15
+#define FSF_AZ_TX_EV_WQ_FF_FULL_WIDTH 1
+#define FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_LBN 14
+#define FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define FSF_AZ_TX_EV_COMP_LBN 12
+#define FSF_AZ_TX_EV_COMP_WIDTH 1
+#define FSF_AZ_TX_EV_DESC_PTR_LBN 0
+#define FSF_AZ_TX_EV_DESC_PTR_WIDTH 12
+
+/* TX_KER_DESC */
+#define FSF_AZ_TX_KER_CONT_LBN 62
+#define FSF_AZ_TX_KER_CONT_WIDTH 1
+#define FSF_AZ_TX_KER_BYTE_COUNT_LBN 48
+#define FSF_AZ_TX_KER_BYTE_COUNT_WIDTH 14
+#define FSF_AZ_TX_KER_BUF_REGION_LBN 46
+#define FSF_AZ_TX_KER_BUF_REGION_WIDTH 2
+#define FSF_AZ_TX_KER_BUF_ADDR_LBN 0
+#define FSF_AZ_TX_KER_BUF_ADDR_WIDTH 46
+
+/* TX_USER_DESC */
+#define FSF_AZ_TX_USER_SW_EV_EN_LBN 48
+#define FSF_AZ_TX_USER_SW_EV_EN_WIDTH 1
+#define FSF_AZ_TX_USER_CONT_LBN 46
+#define FSF_AZ_TX_USER_CONT_WIDTH 1
+#define FSF_AZ_TX_USER_BYTE_CNT_LBN 33
+#define FSF_AZ_TX_USER_BYTE_CNT_WIDTH 13
+#define FSF_AZ_TX_USER_BUF_ID_LBN 13
+#define FSF_AZ_TX_USER_BUF_ID_WIDTH 20
+#define FSF_AZ_TX_USER_BYTE_OFS_LBN 0
+#define FSF_AZ_TX_USER_BYTE_OFS_WIDTH 13
+
+/* USER_EV */
+#define FSF_CZ_USER_QID_LBN 32
+#define FSF_CZ_USER_QID_WIDTH 10
+#define FSF_CZ_USER_EV_REG_VALUE_LBN 0
+#define FSF_CZ_USER_EV_REG_VALUE_WIDTH 32
+
+/**************************************************************************
+ *
+ * Falcon B0 PCIe core indirect registers
+ *
+ **************************************************************************
+ */
+
+#define FPCR_BB_PCIE_DEVICE_CTRL_STAT 0x68
+
+#define FPCR_BB_PCIE_LINK_CTRL_STAT 0x70
+
+#define FPCR_BB_ACK_RPL_TIMER 0x700
+#define FPCRF_BB_ACK_TL_LBN 0
+#define FPCRF_BB_ACK_TL_WIDTH 16
+#define FPCRF_BB_RPL_TL_LBN 16
+#define FPCRF_BB_RPL_TL_WIDTH 16
+
+#define FPCR_BB_ACK_FREQ 0x70C
+#define FPCRF_BB_ACK_FREQ_LBN 0
+#define FPCRF_BB_ACK_FREQ_WIDTH 7
+
+/**************************************************************************
+ *
+ * Pseudo-registers and fields
+ *
+ **************************************************************************
+ */
+
+/* Interrupt acknowledge work-around register (A0/A1 only) */
+#define FR_AA_WORK_AROUND_BROKEN_PCI_READS 0x0070
+
+/* EE_SPI_HCMD_REG: SPI host command register */
+/* Values for the EE_SPI_HCMD_SF_SEL register field */
+#define FFE_AB_SPI_DEVICE_EEPROM 0
+#define FFE_AB_SPI_DEVICE_FLASH 1
+
+/* NIC_STAT_REG: NIC status register */
+#define FRF_AB_STRAP_10G_LBN 2
+#define FRF_AB_STRAP_10G_WIDTH 1
+#define FRF_AA_STRAP_PCIE_LBN 0
+#define FRF_AA_STRAP_PCIE_WIDTH 1
+
+/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */
+#define FRF_AZ_FATAL_INTR_LBN 0
+#define FRF_AZ_FATAL_INTR_WIDTH 12
+
+/* SRM_CFG_REG: SRAM configuration register */
+/* We treat the number of SRAM banks and bank size as a single field */
+#define FRF_AZ_SRM_NB_SZ_LBN FRF_AZ_SRM_BANK_SIZE_LBN
+#define FRF_AZ_SRM_NB_SZ_WIDTH \
+ (FRF_AZ_SRM_BANK_SIZE_WIDTH + FRF_AZ_SRM_NUM_BANK_WIDTH)
+#define FFE_AB_SRM_NB1_SZ2M 0
+#define FFE_AB_SRM_NB1_SZ4M 1
+#define FFE_AB_SRM_NB1_SZ8M 2
+#define FFE_AB_SRM_NB_SZ_DEF 3
+#define FFE_AB_SRM_NB2_SZ4M 4
+#define FFE_AB_SRM_NB2_SZ8M 5
+#define FFE_AB_SRM_NB2_SZ16M 6
+#define FFE_AB_SRM_NB_SZ_RES 7
+
+/* RX_DESC_UPD_REGP0: Receive descriptor update register. */
+/* We write just the last dword of these registers */
+#define FR_AZ_RX_DESC_UPD_DWORD_P0 \
+ (BUILD_BUG_ON_ZERO(FR_AA_RX_DESC_UPD_KER != FR_BZ_RX_DESC_UPD_P0) + \
+ FR_BZ_RX_DESC_UPD_P0 + 3 * 4)
+#define FRF_AZ_RX_DESC_WPTR_DWORD_LBN (FRF_AZ_RX_DESC_WPTR_LBN - 3 * 32)
+#define FRF_AZ_RX_DESC_WPTR_DWORD_WIDTH FRF_AZ_RX_DESC_WPTR_WIDTH
+
+/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */
+#define FR_AZ_TX_DESC_UPD_DWORD_P0 \
+ (BUILD_BUG_ON_ZERO(FR_AA_TX_DESC_UPD_KER != FR_BZ_TX_DESC_UPD_P0) + \
+ FR_BZ_TX_DESC_UPD_P0 + 3 * 4)
+#define FRF_AZ_TX_DESC_WPTR_DWORD_LBN (FRF_AZ_TX_DESC_WPTR_LBN - 3 * 32)
+#define FRF_AZ_TX_DESC_WPTR_DWORD_WIDTH FRF_AZ_TX_DESC_WPTR_WIDTH
+
+/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */
+#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_LBN 12
+#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_WIDTH 1
+
+/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */
+#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_LBN 12
+#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
+
+/* XM_TX_PARAM_REG: XGMAC transmit parameter register */
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_LBN FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN
+#define FRF_AB_XM_MAX_TX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH + \
+ FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH)
+
+/* XM_RX_PARAM_REG: XGMAC receive parameter register */
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_LBN FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN
+#define FRF_AB_XM_MAX_RX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH + \
+ FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH)
+
+/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */
+/* Default values */
+#define FFE_AB_XX_TXDRV_DEQ_DEF 0xe /* deq=.6 */
+#define FFE_AB_XX_TXDRV_DTX_DEF 0x5 /* 1.25 */
+#define FFE_AB_XX_SD_CTL_DRV_DEF 0 /* 20mA */
+
+/* XX_CORE_STAT_REG: XAUI XGXS core status register */
+/* XGXS all-lanes status fields */
+#define FRF_AB_XX_SYNC_STAT_LBN FRF_AB_XX_SYNC_STAT0_LBN
+#define FRF_AB_XX_SYNC_STAT_WIDTH 4
+#define FRF_AB_XX_COMMA_DET_LBN FRF_AB_XX_COMMA_DET_CH0_LBN
+#define FRF_AB_XX_COMMA_DET_WIDTH 4
+#define FRF_AB_XX_CHAR_ERR_LBN FRF_AB_XX_CHAR_ERR_CH0_LBN
+#define FRF_AB_XX_CHAR_ERR_WIDTH 4
+#define FRF_AB_XX_DISPERR_LBN FRF_AB_XX_DISPERR_CH0_LBN
+#define FRF_AB_XX_DISPERR_WIDTH 4
+#define FFE_AB_XX_STAT_ALL_LANES 0xf
+#define FRF_AB_XX_FORCE_SIG_LBN FRF_AB_XX_FORCE_SIG0_VAL_LBN
+#define FRF_AB_XX_FORCE_SIG_WIDTH 8
+#define FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff
+
+/* RX_MAC_FILTER_TBL0 */
+/* RMFT_DEST_MAC is wider than 32 bits */
+#define FRF_CZ_RMFT_DEST_MAC_LO_LBN FRF_CZ_RMFT_DEST_MAC_LBN
+#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
+#define FRF_CZ_RMFT_DEST_MAC_HI_LBN (FRF_CZ_RMFT_DEST_MAC_LBN + 32)
+#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH (FRF_CZ_RMFT_DEST_MAC_WIDTH - 32)
+
+/* TX_MAC_FILTER_TBL0 */
+/* TMFT_SRC_MAC is wider than 32 bits */
+#define FRF_CZ_TMFT_SRC_MAC_LO_LBN FRF_CZ_TMFT_SRC_MAC_LBN
+#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
+#define FRF_CZ_TMFT_SRC_MAC_HI_LBN (FRF_CZ_TMFT_SRC_MAC_LBN + 32)
+#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH (FRF_CZ_TMFT_SRC_MAC_WIDTH - 32)
+
+/* TX_PACE_TBL */
+/* Values >20 are documented as reserved, but will result in a queue going
+ * into the fast bin with a pace value of zero. */
+#define FFE_BZ_TX_PACE_OFF 0
+#define FFE_BZ_TX_PACE_RESERVED 21
+
+/* DRIVER_EV */
+/* Sub-fields of an RX flush completion event */
+#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
+#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1
+#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_LBN 0
+#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_WIDTH 12
+
+/* EVENT_ENTRY */
+/* Magic number field for event test */
+#define FSF_AZ_DRV_GEN_EV_MAGIC_LBN 0
+#define FSF_AZ_DRV_GEN_EV_MAGIC_WIDTH 32
+
+/* RX packet prefix */
+#define FS_BZ_RX_PREFIX_HASH_OFST 12
+#define FS_BZ_RX_PREFIX_SIZE 16
+
+#endif /* EF4_FARCH_REGS_H */
diff --git a/drivers/net/ethernet/sfc/falcon/filter.h b/drivers/net/ethernet/sfc/falcon/filter.h
new file mode 100644
index 000000000000..647f6b2725c5
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/filter.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_FILTER_H
+#define EF4_FILTER_H
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <asm/byteorder.h>
+
+/**
+ * enum ef4_filter_match_flags - Flags for hardware filter match type
+ * @EF4_FILTER_MATCH_REM_HOST: Match by remote IP host address
+ * @EF4_FILTER_MATCH_LOC_HOST: Match by local IP host address
+ * @EF4_FILTER_MATCH_REM_MAC: Match by remote MAC address
+ * @EF4_FILTER_MATCH_REM_PORT: Match by remote TCP/UDP port
+ * @EF4_FILTER_MATCH_LOC_MAC: Match by local MAC address
+ * @EF4_FILTER_MATCH_LOC_PORT: Match by local TCP/UDP port
+ * @EF4_FILTER_MATCH_ETHER_TYPE: Match by Ether-type
+ * @EF4_FILTER_MATCH_INNER_VID: Match by inner VLAN ID
+ * @EF4_FILTER_MATCH_OUTER_VID: Match by outer VLAN ID
+ * @EF4_FILTER_MATCH_IP_PROTO: Match by IP transport protocol
+ * @EF4_FILTER_MATCH_LOC_MAC_IG: Match by local MAC address I/G bit.
+ * Used for RX default unicast and multicast/broadcast filters.
+ *
+ * Only some combinations are supported, depending on NIC type:
+ *
+ * - Falcon supports RX filters matching by {TCP,UDP}/IPv4 4-tuple or
+ * local 2-tuple (only implemented for Falcon B0)
+ *
+ * - Siena supports RX and TX filters matching by {TCP,UDP}/IPv4 4-tuple
+ * or local 2-tuple, or local MAC with or without outer VID, and RX
+ * default filters
+ *
+ * - Huntington supports filter matching controlled by firmware, potentially
+ * using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit,
+ * with or without outer and inner VID
+ */
+enum ef4_filter_match_flags {
+ EF4_FILTER_MATCH_REM_HOST = 0x0001,
+ EF4_FILTER_MATCH_LOC_HOST = 0x0002,
+ EF4_FILTER_MATCH_REM_MAC = 0x0004,
+ EF4_FILTER_MATCH_REM_PORT = 0x0008,
+ EF4_FILTER_MATCH_LOC_MAC = 0x0010,
+ EF4_FILTER_MATCH_LOC_PORT = 0x0020,
+ EF4_FILTER_MATCH_ETHER_TYPE = 0x0040,
+ EF4_FILTER_MATCH_INNER_VID = 0x0080,
+ EF4_FILTER_MATCH_OUTER_VID = 0x0100,
+ EF4_FILTER_MATCH_IP_PROTO = 0x0200,
+ EF4_FILTER_MATCH_LOC_MAC_IG = 0x0400,
+};
+
+/**
+ * enum ef4_filter_priority - priority of a hardware filter specification
+ * @EF4_FILTER_PRI_HINT: Performance hint
+ * @EF4_FILTER_PRI_AUTO: Automatic filter based on device address list
+ * or hardware requirements. This may only be used by the filter
+ * implementation for each NIC type.
+ * @EF4_FILTER_PRI_MANUAL: Manually configured filter
+ * @EF4_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level
+ * networking and SR-IOV)
+ */
+enum ef4_filter_priority {
+ EF4_FILTER_PRI_HINT = 0,
+ EF4_FILTER_PRI_AUTO,
+ EF4_FILTER_PRI_MANUAL,
+ EF4_FILTER_PRI_REQUIRED,
+};
+
+/**
+ * enum ef4_filter_flags - flags for hardware filter specifications
+ * @EF4_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues.
+ * By default, matching packets will be delivered only to the
+ * specified queue. If this flag is set, they will be delivered
+ * to a range of queues offset from the specified queue number
+ * according to the indirection table.
+ * @EF4_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
+ * queue.
+ * @EF4_FILTER_FLAG_RX_OVER_AUTO: Indicates a filter that is
+ * overriding an automatic filter (priority
+ * %EF4_FILTER_PRI_AUTO). This may only be set by the filter
+ * implementation for each type. A removal request will restore
+ * the automatic filter in its place.
+ * @EF4_FILTER_FLAG_RX: Filter is for RX
+ * @EF4_FILTER_FLAG_TX: Filter is for TX
+ */
+enum ef4_filter_flags {
+ EF4_FILTER_FLAG_RX_RSS = 0x01,
+ EF4_FILTER_FLAG_RX_SCATTER = 0x02,
+ EF4_FILTER_FLAG_RX_OVER_AUTO = 0x04,
+ EF4_FILTER_FLAG_RX = 0x08,
+ EF4_FILTER_FLAG_TX = 0x10,
+};
+
+/**
+ * struct ef4_filter_spec - specification for a hardware filter
+ * @match_flags: Match type flags, from &enum ef4_filter_match_flags
+ * @priority: Priority of the filter, from &enum ef4_filter_priority
+ * @flags: Miscellaneous flags, from &enum ef4_filter_flags
+ * @rss_context: RSS context to use, if %EF4_FILTER_FLAG_RX_RSS is set
+ * @dmaq_id: Source/target queue index, or %EF4_FILTER_RX_DMAQ_ID_DROP for
+ * an RX drop filter
+ * @outer_vid: Outer VLAN ID to match, if %EF4_FILTER_MATCH_OUTER_VID is set
+ * @inner_vid: Inner VLAN ID to match, if %EF4_FILTER_MATCH_INNER_VID is set
+ * @loc_mac: Local MAC address to match, if %EF4_FILTER_MATCH_LOC_MAC or
+ * %EF4_FILTER_MATCH_LOC_MAC_IG is set
+ * @rem_mac: Remote MAC address to match, if %EF4_FILTER_MATCH_REM_MAC is set
+ * @ether_type: Ether-type to match, if %EF4_FILTER_MATCH_ETHER_TYPE is set
+ * @ip_proto: IP transport protocol to match, if %EF4_FILTER_MATCH_IP_PROTO
+ * is set
+ * @loc_host: Local IP host to match, if %EF4_FILTER_MATCH_LOC_HOST is set
+ * @rem_host: Remote IP host to match, if %EF4_FILTER_MATCH_REM_HOST is set
+ * @loc_port: Local TCP/UDP port to match, if %EF4_FILTER_MATCH_LOC_PORT is set
+ * @rem_port: Remote TCP/UDP port to match, if %EF4_FILTER_MATCH_REM_PORT is set
+ *
+ * The ef4_filter_init_rx() or ef4_filter_init_tx() function *must* be
+ * used to initialise the structure. The ef4_filter_set_*() functions
+ * may then be used to set @rss_context, @match_flags and related
+ * fields.
+ *
+ * The @priority field is used by software to determine whether a new
+ * filter may replace an old one. The hardware priority of a filter
+ * depends on which fields are matched.
+ */
+struct ef4_filter_spec {
+ u32 match_flags:12;
+ u32 priority:2;
+ u32 flags:6;
+ u32 dmaq_id:12;
+ u32 rss_context;
+ __be16 outer_vid __aligned(4); /* allow jhash2() of match values */
+ __be16 inner_vid;
+ u8 loc_mac[ETH_ALEN];
+ u8 rem_mac[ETH_ALEN];
+ __be16 ether_type;
+ u8 ip_proto;
+ __be32 loc_host[4];
+ __be32 rem_host[4];
+ __be16 loc_port;
+ __be16 rem_port;
+ /* total 64 bytes */
+};
+
+enum {
+ EF4_FILTER_RSS_CONTEXT_DEFAULT = 0xffffffff,
+ EF4_FILTER_RX_DMAQ_ID_DROP = 0xfff
+};
+
+static inline void ef4_filter_init_rx(struct ef4_filter_spec *spec,
+ enum ef4_filter_priority priority,
+ enum ef4_filter_flags flags,
+ unsigned rxq_id)
+{
+ memset(spec, 0, sizeof(*spec));
+ spec->priority = priority;
+ spec->flags = EF4_FILTER_FLAG_RX | flags;
+ spec->rss_context = EF4_FILTER_RSS_CONTEXT_DEFAULT;
+ spec->dmaq_id = rxq_id;
+}
+
+static inline void ef4_filter_init_tx(struct ef4_filter_spec *spec,
+ unsigned txq_id)
+{
+ memset(spec, 0, sizeof(*spec));
+ spec->priority = EF4_FILTER_PRI_REQUIRED;
+ spec->flags = EF4_FILTER_FLAG_TX;
+ spec->dmaq_id = txq_id;
+}
+
+/**
+ * ef4_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
+ * @spec: Specification to initialise
+ * @proto: Transport layer protocol number
+ * @host: Local host address (network byte order)
+ * @port: Local port (network byte order)
+ */
+static inline int
+ef4_filter_set_ipv4_local(struct ef4_filter_spec *spec, u8 proto,
+ __be32 host, __be16 port)
+{
+ spec->match_flags |=
+ EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT;
+ spec->ether_type = htons(ETH_P_IP);
+ spec->ip_proto = proto;
+ spec->loc_host[0] = host;
+ spec->loc_port = port;
+ return 0;
+}
+
+/**
+ * ef4_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
+ * @spec: Specification to initialise
+ * @proto: Transport layer protocol number
+ * @lhost: Local host address (network byte order)
+ * @lport: Local port (network byte order)
+ * @rhost: Remote host address (network byte order)
+ * @rport: Remote port (network byte order)
+ */
+static inline int
+ef4_filter_set_ipv4_full(struct ef4_filter_spec *spec, u8 proto,
+ __be32 lhost, __be16 lport,
+ __be32 rhost, __be16 rport)
+{
+ spec->match_flags |=
+ EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT |
+ EF4_FILTER_MATCH_REM_HOST | EF4_FILTER_MATCH_REM_PORT;
+ spec->ether_type = htons(ETH_P_IP);
+ spec->ip_proto = proto;
+ spec->loc_host[0] = lhost;
+ spec->loc_port = lport;
+ spec->rem_host[0] = rhost;
+ spec->rem_port = rport;
+ return 0;
+}
+
+enum {
+ EF4_FILTER_VID_UNSPEC = 0xffff,
+};
+
+/**
+ * ef4_filter_set_eth_local - specify local Ethernet address and/or VID
+ * @spec: Specification to initialise
+ * @vid: Outer VLAN ID to match, or %EF4_FILTER_VID_UNSPEC
+ * @addr: Local Ethernet MAC address, or %NULL
+ */
+static inline int ef4_filter_set_eth_local(struct ef4_filter_spec *spec,
+ u16 vid, const u8 *addr)
+{
+ if (vid == EF4_FILTER_VID_UNSPEC && addr == NULL)
+ return -EINVAL;
+
+ if (vid != EF4_FILTER_VID_UNSPEC) {
+ spec->match_flags |= EF4_FILTER_MATCH_OUTER_VID;
+ spec->outer_vid = htons(vid);
+ }
+ if (addr != NULL) {
+ spec->match_flags |= EF4_FILTER_MATCH_LOC_MAC;
+ ether_addr_copy(spec->loc_mac, addr);
+ }
+ return 0;
+}
+
+/**
+ * ef4_filter_set_uc_def - specify matching otherwise-unmatched unicast
+ * @spec: Specification to initialise
+ */
+static inline int ef4_filter_set_uc_def(struct ef4_filter_spec *spec)
+{
+ spec->match_flags |= EF4_FILTER_MATCH_LOC_MAC_IG;
+ return 0;
+}
+
+/**
+ * ef4_filter_set_mc_def - specify matching otherwise-unmatched multicast
+ * @spec: Specification to initialise
+ */
+static inline int ef4_filter_set_mc_def(struct ef4_filter_spec *spec)
+{
+ spec->match_flags |= EF4_FILTER_MATCH_LOC_MAC_IG;
+ spec->loc_mac[0] = 1;
+ return 0;
+}
+
+#endif /* EF4_FILTER_H */
diff --git a/drivers/net/ethernet/sfc/falcon/io.h b/drivers/net/ethernet/sfc/falcon/io.h
new file mode 100644
index 000000000000..7085ee1d5e2b
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/io.h
@@ -0,0 +1,290 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_IO_H
+#define EF4_IO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+/**************************************************************************
+ *
+ * NIC register I/O
+ *
+ **************************************************************************
+ *
+ * Notes on locking strategy for the Falcon architecture:
+ *
+ * Many CSRs are very wide and cannot be read or written atomically.
+ * Writes from the host are buffered by the Bus Interface Unit (BIU)
+ * up to 128 bits. Whenever the host writes part of such a register,
+ * the BIU collects the written value and does not write to the
+ * underlying register until all 4 dwords have been written. A
+ * similar buffering scheme applies to host access to the NIC's 64-bit
+ * SRAM.
+ *
+ * Writes to different CSRs and 64-bit SRAM words must be serialised,
+ * since interleaved access can result in lost writes. We use
+ * ef4_nic::biu_lock for this.
+ *
+ * We also serialise reads from 128-bit CSRs and SRAM with the same
+ * spinlock. This may not be necessary, but it doesn't really matter
+ * as there are no such reads on the fast path.
+ *
+ * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are
+ * 128-bit but are special-cased in the BIU to avoid the need for
+ * locking in the host:
+ *
+ * - They are write-only.
+ * - The semantics of writing to these registers are such that
+ * replacing the low 96 bits with zero does not affect functionality.
+ * - If the host writes to the last dword address of such a register
+ * (i.e. the high 32 bits) the underlying register will always be
+ * written. If the collector and the current write together do not
+ * provide values for all 128 bits of the register, the low 96 bits
+ * will be written as zero.
+ * - If the host writes to the address of any other part of such a
+ * register while the collector already holds values for some other
+ * register, the write is discarded and the collector maintains its
+ * current state.
+ *
+ * The EF10 architecture exposes very few registers to the host and
+ * most of them are only 32 bits wide. The only exceptions are the MC
+ * doorbell register pair, which has its own latching, and
+ * TX_DESC_UPD, which works in a similar way to the Falcon
+ * architecture.
+ */
+
+#if BITS_PER_LONG == 64
+#define EF4_USE_QWORD_IO 1
+#endif
+
+#ifdef EF4_USE_QWORD_IO
+static inline void _ef4_writeq(struct ef4_nic *efx, __le64 value,
+ unsigned int reg)
+{
+ __raw_writeq((__force u64)value, efx->membase + reg);
+}
+static inline __le64 _ef4_readq(struct ef4_nic *efx, unsigned int reg)
+{
+ return (__force __le64)__raw_readq(efx->membase + reg);
+}
+#endif
+
+static inline void _ef4_writed(struct ef4_nic *efx, __le32 value,
+ unsigned int reg)
+{
+ __raw_writel((__force u32)value, efx->membase + reg);
+}
+static inline __le32 _ef4_readd(struct ef4_nic *efx, unsigned int reg)
+{
+ return (__force __le32)__raw_readl(efx->membase + reg);
+}
+
+/* Write a normal 128-bit CSR, locking as appropriate. */
+static inline void ef4_writeo(struct ef4_nic *efx, const ef4_oword_t *value,
+ unsigned int reg)
+{
+ unsigned long flags __attribute__ ((unused));
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing register %x with " EF4_OWORD_FMT "\n", reg,
+ EF4_OWORD_VAL(*value));
+
+ spin_lock_irqsave(&efx->biu_lock, flags);
+#ifdef EF4_USE_QWORD_IO
+ _ef4_writeq(efx, value->u64[0], reg + 0);
+ _ef4_writeq(efx, value->u64[1], reg + 8);
+#else
+ _ef4_writed(efx, value->u32[0], reg + 0);
+ _ef4_writed(efx, value->u32[1], reg + 4);
+ _ef4_writed(efx, value->u32[2], reg + 8);
+ _ef4_writed(efx, value->u32[3], reg + 12);
+#endif
+ mmiowb();
+ spin_unlock_irqrestore(&efx->biu_lock, flags);
+}
+
+/* Write 64-bit SRAM through the supplied mapping, locking as appropriate. */
+static inline void ef4_sram_writeq(struct ef4_nic *efx, void __iomem *membase,
+ const ef4_qword_t *value, unsigned int index)
+{
+ unsigned int addr = index * sizeof(*value);
+ unsigned long flags __attribute__ ((unused));
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing SRAM address %x with " EF4_QWORD_FMT "\n",
+ addr, EF4_QWORD_VAL(*value));
+
+ spin_lock_irqsave(&efx->biu_lock, flags);
+#ifdef EF4_USE_QWORD_IO
+ __raw_writeq((__force u64)value->u64[0], membase + addr);
+#else
+ __raw_writel((__force u32)value->u32[0], membase + addr);
+ __raw_writel((__force u32)value->u32[1], membase + addr + 4);
+#endif
+ mmiowb();
+ spin_unlock_irqrestore(&efx->biu_lock, flags);
+}
+
+/* Write a 32-bit CSR or the last dword of a special 128-bit CSR */
+static inline void ef4_writed(struct ef4_nic *efx, const ef4_dword_t *value,
+ unsigned int reg)
+{
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing register %x with "EF4_DWORD_FMT"\n",
+ reg, EF4_DWORD_VAL(*value));
+
+ /* No lock required */
+ _ef4_writed(efx, value->u32[0], reg);
+}
+
+/* Read a 128-bit CSR, locking as appropriate. */
+static inline void ef4_reado(struct ef4_nic *efx, ef4_oword_t *value,
+ unsigned int reg)
+{
+ unsigned long flags __attribute__ ((unused));
+
+ spin_lock_irqsave(&efx->biu_lock, flags);
+ value->u32[0] = _ef4_readd(efx, reg + 0);
+ value->u32[1] = _ef4_readd(efx, reg + 4);
+ value->u32[2] = _ef4_readd(efx, reg + 8);
+ value->u32[3] = _ef4_readd(efx, reg + 12);
+ spin_unlock_irqrestore(&efx->biu_lock, flags);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from register %x, got " EF4_OWORD_FMT "\n", reg,
+ EF4_OWORD_VAL(*value));
+}
+
+/* Read 64-bit SRAM through the supplied mapping, locking as appropriate. */
+static inline void ef4_sram_readq(struct ef4_nic *efx, void __iomem *membase,
+ ef4_qword_t *value, unsigned int index)
+{
+ unsigned int addr = index * sizeof(*value);
+ unsigned long flags __attribute__ ((unused));
+
+ spin_lock_irqsave(&efx->biu_lock, flags);
+#ifdef EF4_USE_QWORD_IO
+ value->u64[0] = (__force __le64)__raw_readq(membase + addr);
+#else
+ value->u32[0] = (__force __le32)__raw_readl(membase + addr);
+ value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
+#endif
+ spin_unlock_irqrestore(&efx->biu_lock, flags);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from SRAM address %x, got "EF4_QWORD_FMT"\n",
+ addr, EF4_QWORD_VAL(*value));
+}
+
+/* Read a 32-bit CSR or SRAM */
+static inline void ef4_readd(struct ef4_nic *efx, ef4_dword_t *value,
+ unsigned int reg)
+{
+ value->u32[0] = _ef4_readd(efx, reg);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from register %x, got "EF4_DWORD_FMT"\n",
+ reg, EF4_DWORD_VAL(*value));
+}
+
+/* Write a 128-bit CSR forming part of a table */
+static inline void
+ef4_writeo_table(struct ef4_nic *efx, const ef4_oword_t *value,
+ unsigned int reg, unsigned int index)
+{
+ ef4_writeo(efx, value, reg + index * sizeof(ef4_oword_t));
+}
+
+/* Read a 128-bit CSR forming part of a table */
+static inline void ef4_reado_table(struct ef4_nic *efx, ef4_oword_t *value,
+ unsigned int reg, unsigned int index)
+{
+ ef4_reado(efx, value, reg + index * sizeof(ef4_oword_t));
+}
+
+/* Page size used as step between per-VI registers */
+#define EF4_VI_PAGE_SIZE 0x2000
+
+/* Calculate offset to page-mapped register */
+#define EF4_PAGED_REG(page, reg) \
+ ((page) * EF4_VI_PAGE_SIZE + (reg))
+
+/* Write the whole of RX_DESC_UPD or TX_DESC_UPD */
+static inline void _ef4_writeo_page(struct ef4_nic *efx, ef4_oword_t *value,
+ unsigned int reg, unsigned int page)
+{
+ reg = EF4_PAGED_REG(page, reg);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing register %x with " EF4_OWORD_FMT "\n", reg,
+ EF4_OWORD_VAL(*value));
+
+#ifdef EF4_USE_QWORD_IO
+ _ef4_writeq(efx, value->u64[0], reg + 0);
+ _ef4_writeq(efx, value->u64[1], reg + 8);
+#else
+ _ef4_writed(efx, value->u32[0], reg + 0);
+ _ef4_writed(efx, value->u32[1], reg + 4);
+ _ef4_writed(efx, value->u32[2], reg + 8);
+ _ef4_writed(efx, value->u32[3], reg + 12);
+#endif
+}
+#define ef4_writeo_page(efx, value, reg, page) \
+ _ef4_writeo_page(efx, value, \
+ reg + \
+ BUILD_BUG_ON_ZERO((reg) != 0x830 && (reg) != 0xa10), \
+ page)
+
+/* Write a page-mapped 32-bit CSR (EVQ_RPTR, EVQ_TMR (EF10), or the
+ * high bits of RX_DESC_UPD or TX_DESC_UPD)
+ */
+static inline void
+_ef4_writed_page(struct ef4_nic *efx, const ef4_dword_t *value,
+ unsigned int reg, unsigned int page)
+{
+ ef4_writed(efx, value, EF4_PAGED_REG(page, reg));
+}
+#define ef4_writed_page(efx, value, reg, page) \
+ _ef4_writed_page(efx, value, \
+ reg + \
+ BUILD_BUG_ON_ZERO((reg) != 0x400 && \
+ (reg) != 0x420 && \
+ (reg) != 0x830 && \
+ (reg) != 0x83c && \
+ (reg) != 0xa18 && \
+ (reg) != 0xa1c), \
+ page)
+
+/* Write TIMER_COMMAND. This is a page-mapped 32-bit CSR, but a bug
+ * in the BIU means that writes to TIMER_COMMAND[0] invalidate the
+ * collector register.
+ */
+static inline void _ef4_writed_page_locked(struct ef4_nic *efx,
+ const ef4_dword_t *value,
+ unsigned int reg,
+ unsigned int page)
+{
+ unsigned long flags __attribute__ ((unused));
+
+ if (page == 0) {
+ spin_lock_irqsave(&efx->biu_lock, flags);
+ ef4_writed(efx, value, EF4_PAGED_REG(page, reg));
+ spin_unlock_irqrestore(&efx->biu_lock, flags);
+ } else {
+ ef4_writed(efx, value, EF4_PAGED_REG(page, reg));
+ }
+}
+#define ef4_writed_page_locked(efx, value, reg, page) \
+ _ef4_writed_page_locked(efx, value, \
+ reg + BUILD_BUG_ON_ZERO((reg) != 0x420), \
+ page)
+
+#endif /* EF4_IO_H */
diff --git a/drivers/net/ethernet/sfc/mdio_10g.c b/drivers/net/ethernet/sfc/falcon/mdio_10g.c
index 8ff954c59efa..e7d7c09296aa 100644
--- a/drivers/net/ethernet/sfc/mdio_10g.c
+++ b/drivers/net/ethernet/sfc/falcon/mdio_10g.c
@@ -16,7 +16,7 @@
#include "mdio_10g.h"
#include "workarounds.h"
-unsigned efx_mdio_id_oui(u32 id)
+unsigned ef4_mdio_id_oui(u32 id)
{
unsigned oui = 0;
int i;
@@ -31,19 +31,19 @@ unsigned efx_mdio_id_oui(u32 id)
return oui;
}
-int efx_mdio_reset_mmd(struct efx_nic *port, int mmd,
+int ef4_mdio_reset_mmd(struct ef4_nic *port, int mmd,
int spins, int spintime)
{
u32 ctrl;
/* Catch callers passing values in the wrong units (or just silly) */
- EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
+ EF4_BUG_ON_PARANOID(spins * spintime >= 5000);
- efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET);
+ ef4_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET);
/* Wait for the reset bit to clear. */
do {
msleep(spintime);
- ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1);
+ ctrl = ef4_mdio_read(port, mmd, MDIO_CTRL1);
spins--;
} while (spins && (ctrl & MDIO_CTRL1_RESET));
@@ -51,13 +51,13 @@ int efx_mdio_reset_mmd(struct efx_nic *port, int mmd,
return spins ? spins : -ETIMEDOUT;
}
-static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd)
+static int ef4_mdio_check_mmd(struct ef4_nic *efx, int mmd)
{
int status;
if (mmd != MDIO_MMD_AN) {
/* Read MMD STATUS2 to check it is responding. */
- status = efx_mdio_read(efx, mmd, MDIO_STAT2);
+ status = ef4_mdio_read(efx, mmd, MDIO_STAT2);
if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) {
netif_err(efx, hw, efx->net_dev,
"PHY MMD %d not responding.\n", mmd);
@@ -72,7 +72,7 @@ static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd)
#define MDIO45_RESET_TIME 1000 /* ms */
#define MDIO45_RESET_ITERS 100
-int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
+int ef4_mdio_wait_reset_mmds(struct ef4_nic *efx, unsigned int mmd_mask)
{
const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
int tries = MDIO45_RESET_ITERS;
@@ -86,7 +86,7 @@ int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
in_reset = 0;
while (mask) {
if (mask & 1) {
- stat = efx_mdio_read(efx, mmd, MDIO_CTRL1);
+ stat = ef4_mdio_read(efx, mmd, MDIO_CTRL1);
if (stat < 0) {
netif_err(efx, hw, efx->net_dev,
"failed to read status of"
@@ -113,7 +113,7 @@ int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
return rc;
}
-int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask)
+int ef4_mdio_check_mmds(struct ef4_nic *efx, unsigned int mmd_mask)
{
int mmd = 0, probe_mmd, devs1, devs2;
u32 devices;
@@ -125,8 +125,8 @@ int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask)
__ffs(mmd_mask);
/* Check all the expected MMDs are present */
- devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1);
- devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2);
+ devs1 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS1);
+ devs2 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS2);
if (devs1 < 0 || devs2 < 0) {
netif_err(efx, hw, efx->net_dev,
"failed to read devices present\n");
@@ -143,7 +143,7 @@ int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask)
/* Check all required MMDs are responding and happy. */
while (mmd_mask) {
- if ((mmd_mask & 1) && efx_mdio_check_mmd(efx, mmd))
+ if ((mmd_mask & 1) && ef4_mdio_check_mmd(efx, mmd))
return -EIO;
mmd_mask = mmd_mask >> 1;
mmd++;
@@ -152,7 +152,7 @@ int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask)
return 0;
}
-bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
+bool ef4_mdio_links_ok(struct ef4_nic *efx, unsigned int mmd_mask)
{
/* If the port is in loopback, then we should only consider a subset
* of mmd's */
@@ -160,7 +160,7 @@ bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
return true;
else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS)
return false;
- else if (efx_phy_mode_disabled(efx->phy_mode))
+ else if (ef4_phy_mode_disabled(efx->phy_mode))
return false;
else if (efx->loopback_mode == LOOPBACK_PHYXS)
mmd_mask &= ~(MDIO_DEVS_PHYXS |
@@ -178,59 +178,59 @@ bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
return mdio45_links_ok(&efx->mdio, mmd_mask);
}
-void efx_mdio_transmit_disable(struct efx_nic *efx)
+void ef4_mdio_transmit_disable(struct ef4_nic *efx)
{
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL,
efx->phy_mode & PHY_MODE_TX_DISABLED);
}
-void efx_mdio_phy_reconfigure(struct efx_nic *efx)
+void ef4_mdio_phy_reconfigure(struct ef4_nic *efx)
{
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK,
efx->loopback_mode == LOOPBACK_PMAPMD);
- efx_mdio_set_flag(efx, MDIO_MMD_PCS,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PCS,
MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK,
efx->loopback_mode == LOOPBACK_PCS);
- efx_mdio_set_flag(efx, MDIO_MMD_PHYXS,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS,
MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK,
efx->loopback_mode == LOOPBACK_PHYXS_WS);
}
-static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
+static void ef4_mdio_set_mmd_lpower(struct ef4_nic *efx,
int lpower, int mmd)
{
- int stat = efx_mdio_read(efx, mmd, MDIO_STAT1);
+ int stat = ef4_mdio_read(efx, mmd, MDIO_STAT1);
netif_vdbg(efx, drv, efx->net_dev, "Setting low power mode for MMD %d to %d\n",
mmd, lpower);
if (stat & MDIO_STAT1_LPOWERABLE) {
- efx_mdio_set_flag(efx, mmd, MDIO_CTRL1,
+ ef4_mdio_set_flag(efx, mmd, MDIO_CTRL1,
MDIO_CTRL1_LPOWER, lpower);
}
}
-void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
+void ef4_mdio_set_mmds_lpower(struct ef4_nic *efx,
int low_power, unsigned int mmd_mask)
{
int mmd = 0;
mmd_mask &= ~MDIO_DEVS_AN;
while (mmd_mask) {
if (mmd_mask & 1)
- efx_mdio_set_mmd_lpower(efx, low_power, mmd);
+ ef4_mdio_set_mmd_lpower(efx, low_power, mmd);
mmd_mask = (mmd_mask >> 1);
mmd++;
}
}
/**
- * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO.
+ * ef4_mdio_set_settings - Set (some of) the PHY settings over MDIO.
* @efx: Efx NIC
* @ecmd: New settings
*/
-int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+int ef4_mdio_set_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd)
{
struct ethtool_cmd prev = { .cmd = ETHTOOL_GSET };
@@ -252,16 +252,16 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
(ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported)
return -EINVAL;
- efx_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg);
- efx_mdio_an_reconfigure(efx);
+ ef4_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg);
+ ef4_mdio_an_reconfigure(efx);
return 0;
}
/**
- * efx_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
+ * ef4_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
* @efx: Efx NIC
*/
-void efx_mdio_an_reconfigure(struct efx_nic *efx)
+void ef4_mdio_an_reconfigure(struct ef4_nic *efx)
{
int reg;
@@ -273,32 +273,32 @@ void efx_mdio_an_reconfigure(struct efx_nic *efx)
reg |= ADVERTISE_PAUSE_CAP;
if (efx->link_advertising & ADVERTISED_Asym_Pause)
reg |= ADVERTISE_PAUSE_ASYM;
- efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
+ ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
/* Set up the (extended) next page */
efx->phy_op->set_npage_adv(efx, efx->link_advertising);
/* Enable and restart AN */
- reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
+ reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP;
- efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
+ ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
}
-u8 efx_mdio_get_pause(struct efx_nic *efx)
+u8 ef4_mdio_get_pause(struct ef4_nic *efx)
{
- BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX));
+ BUILD_BUG_ON(EF4_FC_AUTO & (EF4_FC_RX | EF4_FC_TX));
- if (!(efx->wanted_fc & EFX_FC_AUTO))
+ if (!(efx->wanted_fc & EF4_FC_AUTO))
return efx->wanted_fc;
WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
return mii_resolve_flowctrl_fdx(
mii_advertise_flowctrl(efx->wanted_fc),
- efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA));
+ ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA));
}
-int efx_mdio_test_alive(struct efx_nic *efx)
+int ef4_mdio_test_alive(struct ef4_nic *efx)
{
int rc;
int devad = __ffs(efx->mdio.mmds);
@@ -306,8 +306,8 @@ int efx_mdio_test_alive(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
- physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
- physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
+ physid1 = ef4_mdio_read(efx, devad, MDIO_DEVID1);
+ physid2 = ef4_mdio_read(efx, devad, MDIO_DEVID2);
if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
(physid2 == 0x0000) || (physid2 == 0xffff)) {
@@ -315,7 +315,7 @@ int efx_mdio_test_alive(struct efx_nic *efx)
"no MDIO PHY present with ID %d\n", efx->mdio.prtad);
rc = -EINVAL;
} else {
- rc = efx_mdio_check_mmds(efx, efx->mdio.mmds);
+ rc = ef4_mdio_check_mmds(efx, efx->mdio.mmds);
}
mutex_unlock(&efx->mac_lock);
diff --git a/drivers/net/ethernet/sfc/mdio_10g.h b/drivers/net/ethernet/sfc/falcon/mdio_10g.h
index 4a2dc4c281b7..885cf7a834a6 100644
--- a/drivers/net/ethernet/sfc/mdio_10g.h
+++ b/drivers/net/ethernet/sfc/falcon/mdio_10g.h
@@ -7,8 +7,8 @@
* by the Free Software Foundation, incorporated herein by reference.
*/
-#ifndef EFX_MDIO_10G_H
-#define EFX_MDIO_10G_H
+#ifndef EF4_MDIO_10G_H
+#define EF4_MDIO_10G_H
#include <linux/mdio.h>
@@ -18,35 +18,35 @@
#include "efx.h"
-static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; }
-static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
-unsigned efx_mdio_id_oui(u32 id);
+static inline unsigned ef4_mdio_id_rev(u32 id) { return id & 0xf; }
+static inline unsigned ef4_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
+unsigned ef4_mdio_id_oui(u32 id);
-static inline int efx_mdio_read(struct efx_nic *efx, int devad, int addr)
+static inline int ef4_mdio_read(struct ef4_nic *efx, int devad, int addr)
{
return efx->mdio.mdio_read(efx->net_dev, efx->mdio.prtad, devad, addr);
}
static inline void
-efx_mdio_write(struct efx_nic *efx, int devad, int addr, int value)
+ef4_mdio_write(struct ef4_nic *efx, int devad, int addr, int value)
{
efx->mdio.mdio_write(efx->net_dev, efx->mdio.prtad, devad, addr, value);
}
-static inline u32 efx_mdio_read_id(struct efx_nic *efx, int mmd)
+static inline u32 ef4_mdio_read_id(struct ef4_nic *efx, int mmd)
{
- u16 id_low = efx_mdio_read(efx, mmd, MDIO_DEVID2);
- u16 id_hi = efx_mdio_read(efx, mmd, MDIO_DEVID1);
+ u16 id_low = ef4_mdio_read(efx, mmd, MDIO_DEVID2);
+ u16 id_hi = ef4_mdio_read(efx, mmd, MDIO_DEVID1);
return (id_hi << 16) | (id_low);
}
-static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx)
+static inline bool ef4_mdio_phyxgxs_lane_sync(struct ef4_nic *efx)
{
int i, lane_status;
bool sync;
for (i = 0; i < 2; ++i)
- lane_status = efx_mdio_read(efx, MDIO_MMD_PHYXS,
+ lane_status = ef4_mdio_read(efx, MDIO_MMD_PHYXS,
MDIO_PHYXS_LNSTAT);
sync = !!(lane_status & MDIO_PHYXS_LNSTAT_ALIGN);
@@ -56,7 +56,7 @@ static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx)
return sync;
}
-const char *efx_mdio_mmd_name(int mmd);
+const char *ef4_mdio_mmd_name(int mmd);
/*
* Reset a specific MMD and wait for reset to clear.
@@ -64,47 +64,47 @@ const char *efx_mdio_mmd_name(int mmd);
*
* This function will sleep
*/
-int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd, int spins, int spintime);
+int ef4_mdio_reset_mmd(struct ef4_nic *efx, int mmd, int spins, int spintime);
-/* As efx_mdio_check_mmd but for multiple MMDs */
-int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask);
+/* As ef4_mdio_check_mmd but for multiple MMDs */
+int ef4_mdio_check_mmds(struct ef4_nic *efx, unsigned int mmd_mask);
/* Check the link status of specified mmds in bit mask */
-bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
+bool ef4_mdio_links_ok(struct ef4_nic *efx, unsigned int mmd_mask);
/* Generic transmit disable support though PMAPMD */
-void efx_mdio_transmit_disable(struct efx_nic *efx);
+void ef4_mdio_transmit_disable(struct ef4_nic *efx);
/* Generic part of reconfigure: set/clear loopback bits */
-void efx_mdio_phy_reconfigure(struct efx_nic *efx);
+void ef4_mdio_phy_reconfigure(struct ef4_nic *efx);
/* Set the power state of the specified MMDs */
-void efx_mdio_set_mmds_lpower(struct efx_nic *efx, int low_power,
+void ef4_mdio_set_mmds_lpower(struct ef4_nic *efx, int low_power,
unsigned int mmd_mask);
/* Set (some of) the PHY settings over MDIO */
-int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+int ef4_mdio_set_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd);
/* Push advertising flags and restart autonegotiation */
-void efx_mdio_an_reconfigure(struct efx_nic *efx);
+void ef4_mdio_an_reconfigure(struct ef4_nic *efx);
/* Get pause parameters from AN if available (otherwise return
* requested pause parameters)
*/
-u8 efx_mdio_get_pause(struct efx_nic *efx);
+u8 ef4_mdio_get_pause(struct ef4_nic *efx);
/* Wait for specified MMDs to exit reset within a timeout */
-int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask);
+int ef4_mdio_wait_reset_mmds(struct ef4_nic *efx, unsigned int mmd_mask);
/* Set or clear flag, debouncing */
static inline void
-efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr,
+ef4_mdio_set_flag(struct ef4_nic *efx, int devad, int addr,
int mask, bool state)
{
mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state);
}
/* Liveness self-test for MDIO PHYs */
-int efx_mdio_test_alive(struct efx_nic *efx);
+int ef4_mdio_test_alive(struct ef4_nic *efx);
-#endif /* EFX_MDIO_10G_H */
+#endif /* EF4_MDIO_10G_H */
diff --git a/drivers/net/ethernet/sfc/falcon/mtd.c b/drivers/net/ethernet/sfc/falcon/mtd.c
new file mode 100644
index 000000000000..cde593cb1052
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/mtd.c
@@ -0,0 +1,133 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+
+#include "net_driver.h"
+#include "efx.h"
+
+#define to_ef4_mtd_partition(mtd) \
+ container_of(mtd, struct ef4_mtd_partition, mtd)
+
+/* MTD interface */
+
+static int ef4_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ struct ef4_nic *efx = mtd->priv;
+ int rc;
+
+ rc = efx->type->mtd_erase(mtd, erase->addr, erase->len);
+ if (rc == 0) {
+ erase->state = MTD_ERASE_DONE;
+ } else {
+ erase->state = MTD_ERASE_FAILED;
+ erase->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+ }
+ mtd_erase_callback(erase);
+ return rc;
+}
+
+static void ef4_mtd_sync(struct mtd_info *mtd)
+{
+ struct ef4_mtd_partition *part = to_ef4_mtd_partition(mtd);
+ struct ef4_nic *efx = mtd->priv;
+ int rc;
+
+ rc = efx->type->mtd_sync(mtd);
+ if (rc)
+ pr_err("%s: %s sync failed (%d)\n",
+ part->name, part->dev_type_name, rc);
+}
+
+static void ef4_mtd_remove_partition(struct ef4_mtd_partition *part)
+{
+ int rc;
+
+ for (;;) {
+ rc = mtd_device_unregister(&part->mtd);
+ if (rc != -EBUSY)
+ break;
+ ssleep(1);
+ }
+ WARN_ON(rc);
+ list_del(&part->node);
+}
+
+int ef4_mtd_add(struct ef4_nic *efx, struct ef4_mtd_partition *parts,
+ size_t n_parts, size_t sizeof_part)
+{
+ struct ef4_mtd_partition *part;
+ size_t i;
+
+ for (i = 0; i < n_parts; i++) {
+ part = (struct ef4_mtd_partition *)((char *)parts +
+ i * sizeof_part);
+
+ part->mtd.writesize = 1;
+
+ part->mtd.owner = THIS_MODULE;
+ part->mtd.priv = efx;
+ part->mtd.name = part->name;
+ part->mtd._erase = ef4_mtd_erase;
+ part->mtd._read = efx->type->mtd_read;
+ part->mtd._write = efx->type->mtd_write;
+ part->mtd._sync = ef4_mtd_sync;
+
+ efx->type->mtd_rename(part);
+
+ if (mtd_device_register(&part->mtd, NULL, 0))
+ goto fail;
+
+ /* Add to list in order - ef4_mtd_remove() depends on this */
+ list_add_tail(&part->node, &efx->mtd_list);
+ }
+
+ return 0;
+
+fail:
+ while (i--) {
+ part = (struct ef4_mtd_partition *)((char *)parts +
+ i * sizeof_part);
+ ef4_mtd_remove_partition(part);
+ }
+ /* Failure is unlikely here, but probably means we're out of memory */
+ return -ENOMEM;
+}
+
+void ef4_mtd_remove(struct ef4_nic *efx)
+{
+ struct ef4_mtd_partition *parts, *part, *next;
+
+ WARN_ON(ef4_dev_registered(efx));
+
+ if (list_empty(&efx->mtd_list))
+ return;
+
+ parts = list_first_entry(&efx->mtd_list, struct ef4_mtd_partition,
+ node);
+
+ list_for_each_entry_safe(part, next, &efx->mtd_list, node)
+ ef4_mtd_remove_partition(part);
+
+ kfree(parts);
+}
+
+void ef4_mtd_rename(struct ef4_nic *efx)
+{
+ struct ef4_mtd_partition *part;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(part, &efx->mtd_list, node)
+ efx->type->mtd_rename(part);
+}
diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h
new file mode 100644
index 000000000000..210b28f7d2a1
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -0,0 +1,1464 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2005-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+/* Common definitions for all Efx net driver code */
+
+#ifndef EF4_NET_DRIVER_H
+#define EF4_NET_DRIVER_H
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/timer.h>
+#include <linux/mdio.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
+#include <linux/vmalloc.h>
+#include <linux/i2c.h>
+#include <linux/mtd/mtd.h>
+#include <net/busy_poll.h>
+
+#include "enum.h"
+#include "bitfield.h"
+#include "filter.h"
+
+/**************************************************************************
+ *
+ * Build definitions
+ *
+ **************************************************************************/
+
+#define EF4_DRIVER_VERSION "4.1"
+
+#ifdef DEBUG
+#define EF4_BUG_ON_PARANOID(x) BUG_ON(x)
+#define EF4_WARN_ON_PARANOID(x) WARN_ON(x)
+#else
+#define EF4_BUG_ON_PARANOID(x) do {} while (0)
+#define EF4_WARN_ON_PARANOID(x) do {} while (0)
+#endif
+
+/**************************************************************************
+ *
+ * Efx data structures
+ *
+ **************************************************************************/
+
+#define EF4_MAX_CHANNELS 32U
+#define EF4_MAX_RX_QUEUES EF4_MAX_CHANNELS
+#define EF4_EXTRA_CHANNEL_IOV 0
+#define EF4_EXTRA_CHANNEL_PTP 1
+#define EF4_MAX_EXTRA_CHANNELS 2U
+
+/* Checksum generation is a per-queue option in hardware, so each
+ * queue visible to the networking core is backed by two hardware TX
+ * queues. */
+#define EF4_MAX_TX_TC 2
+#define EF4_MAX_CORE_TX_QUEUES (EF4_MAX_TX_TC * EF4_MAX_CHANNELS)
+#define EF4_TXQ_TYPE_OFFLOAD 1 /* flag */
+#define EF4_TXQ_TYPE_HIGHPRI 2 /* flag */
+#define EF4_TXQ_TYPES 4
+#define EF4_MAX_TX_QUEUES (EF4_TXQ_TYPES * EF4_MAX_CHANNELS)
+
+/* Maximum possible MTU the driver supports */
+#define EF4_MAX_MTU (9 * 1024)
+
+/* Minimum MTU, from RFC791 (IP) */
+#define EF4_MIN_MTU 68
+
+/* Size of an RX scatter buffer. Small enough to pack 2 into a 4K page,
+ * and should be a multiple of the cache line size.
+ */
+#define EF4_RX_USR_BUF_SIZE (2048 - 256)
+
+/* If possible, we should ensure cache line alignment at start and end
+ * of every buffer. Otherwise, we just need to ensure 4-byte
+ * alignment of the network header.
+ */
+#if NET_IP_ALIGN == 0
+#define EF4_RX_BUF_ALIGNMENT L1_CACHE_BYTES
+#else
+#define EF4_RX_BUF_ALIGNMENT 4
+#endif
+
+struct ef4_self_tests;
+
+/**
+ * struct ef4_buffer - A general-purpose DMA buffer
+ * @addr: host base address of the buffer
+ * @dma_addr: DMA base address of the buffer
+ * @len: Buffer length, in bytes
+ *
+ * The NIC uses these buffers for its interrupt status registers and
+ * MAC stats dumps.
+ */
+struct ef4_buffer {
+ void *addr;
+ dma_addr_t dma_addr;
+ unsigned int len;
+};
+
+/**
+ * struct ef4_special_buffer - DMA buffer entered into buffer table
+ * @buf: Standard &struct ef4_buffer
+ * @index: Buffer index within controller;s buffer table
+ * @entries: Number of buffer table entries
+ *
+ * The NIC has a buffer table that maps buffers of size %EF4_BUF_SIZE.
+ * Event and descriptor rings are addressed via one or more buffer
+ * table entries (and so can be physically non-contiguous, although we
+ * currently do not take advantage of that). On Falcon and Siena we
+ * have to take care of allocating and initialising the entries
+ * ourselves. On later hardware this is managed by the firmware and
+ * @index and @entries are left as 0.
+ */
+struct ef4_special_buffer {
+ struct ef4_buffer buf;
+ unsigned int index;
+ unsigned int entries;
+};
+
+/**
+ * struct ef4_tx_buffer - buffer state for a TX descriptor
+ * @skb: When @flags & %EF4_TX_BUF_SKB, the associated socket buffer to be
+ * freed when descriptor completes
+ * @option: When @flags & %EF4_TX_BUF_OPTION, a NIC-specific option descriptor.
+ * @dma_addr: DMA address of the fragment.
+ * @flags: Flags for allocation and DMA mapping type
+ * @len: Length of this fragment.
+ * This field is zero when the queue slot is empty.
+ * @unmap_len: Length of this fragment to unmap
+ * @dma_offset: Offset of @dma_addr from the address of the backing DMA mapping.
+ * Only valid if @unmap_len != 0.
+ */
+struct ef4_tx_buffer {
+ const struct sk_buff *skb;
+ union {
+ ef4_qword_t option;
+ dma_addr_t dma_addr;
+ };
+ unsigned short flags;
+ unsigned short len;
+ unsigned short unmap_len;
+ unsigned short dma_offset;
+};
+#define EF4_TX_BUF_CONT 1 /* not last descriptor of packet */
+#define EF4_TX_BUF_SKB 2 /* buffer is last part of skb */
+#define EF4_TX_BUF_MAP_SINGLE 8 /* buffer was mapped with dma_map_single() */
+#define EF4_TX_BUF_OPTION 0x10 /* empty buffer for option descriptor */
+
+/**
+ * struct ef4_tx_queue - An Efx TX queue
+ *
+ * This is a ring buffer of TX fragments.
+ * Since the TX completion path always executes on the same
+ * CPU and the xmit path can operate on different CPUs,
+ * performance is increased by ensuring that the completion
+ * path and the xmit path operate on different cache lines.
+ * This is particularly important if the xmit path is always
+ * executing on one CPU which is different from the completion
+ * path. There is also a cache line for members which are
+ * read but not written on the fast path.
+ *
+ * @efx: The associated Efx NIC
+ * @queue: DMA queue number
+ * @channel: The associated channel
+ * @core_txq: The networking core TX queue structure
+ * @buffer: The software buffer ring
+ * @cb_page: Array of pages of copy buffers. Carved up according to
+ * %EF4_TX_CB_ORDER into %EF4_TX_CB_SIZE-sized chunks.
+ * @txd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
+ * @initialised: Has hardware queue been initialised?
+ * @tx_min_size: Minimum transmit size for this queue. Depends on HW.
+ * @read_count: Current read pointer.
+ * This is the number of buffers that have been removed from both rings.
+ * @old_write_count: The value of @write_count when last checked.
+ * This is here for performance reasons. The xmit path will
+ * only get the up-to-date value of @write_count if this
+ * variable indicates that the queue is empty. This is to
+ * avoid cache-line ping-pong between the xmit path and the
+ * completion path.
+ * @merge_events: Number of TX merged completion events
+ * @insert_count: Current insert pointer
+ * This is the number of buffers that have been added to the
+ * software ring.
+ * @write_count: Current write pointer
+ * This is the number of buffers that have been added to the
+ * hardware ring.
+ * @old_read_count: The value of read_count when last checked.
+ * This is here for performance reasons. The xmit path will
+ * only get the up-to-date value of read_count if this
+ * variable indicates that the queue is full. This is to
+ * avoid cache-line ping-pong between the xmit path and the
+ * completion path.
+ * @pushes: Number of times the TX push feature has been used
+ * @xmit_more_available: Are any packets waiting to be pushed to the NIC
+ * @cb_packets: Number of times the TX copybreak feature has been used
+ * @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 %EF4_EMPTY_COUNT_VALID; otherwise 0.
+ */
+struct ef4_tx_queue {
+ /* Members which don't change on the fast path */
+ struct ef4_nic *efx ____cacheline_aligned_in_smp;
+ unsigned queue;
+ struct ef4_channel *channel;
+ struct netdev_queue *core_txq;
+ struct ef4_tx_buffer *buffer;
+ struct ef4_buffer *cb_page;
+ struct ef4_special_buffer txd;
+ unsigned int ptr_mask;
+ bool initialised;
+ unsigned int tx_min_size;
+
+ /* Function pointers used in the fast path. */
+ int (*handle_tso)(struct ef4_tx_queue*, struct sk_buff*, bool *);
+
+ /* Members used mainly on the completion path */
+ unsigned int read_count ____cacheline_aligned_in_smp;
+ unsigned int old_write_count;
+ unsigned int merge_events;
+ unsigned int bytes_compl;
+ unsigned int pkts_compl;
+
+ /* Members used only on the xmit path */
+ unsigned int insert_count ____cacheline_aligned_in_smp;
+ unsigned int write_count;
+ unsigned int old_read_count;
+ unsigned int pushes;
+ bool xmit_more_available;
+ unsigned int cb_packets;
+ /* Statistics to supplement MAC stats */
+ unsigned long tx_packets;
+
+ /* Members shared between paths and sometimes updated */
+ unsigned int empty_read_count ____cacheline_aligned_in_smp;
+#define EF4_EMPTY_COUNT_VALID 0x80000000
+ atomic_t flush_outstanding;
+};
+
+#define EF4_TX_CB_ORDER 7
+#define EF4_TX_CB_SIZE (1 << EF4_TX_CB_ORDER) - NET_IP_ALIGN
+
+/**
+ * struct ef4_rx_buffer - An Efx RX data buffer
+ * @dma_addr: DMA base address of the buffer
+ * @page: The associated page buffer.
+ * Will be %NULL if the buffer slot is currently free.
+ * @page_offset: If pending: offset in @page of DMA base address.
+ * If completed: offset in @page of Ethernet header.
+ * @len: If pending: length for DMA descriptor.
+ * If completed: received length, excluding hash prefix.
+ * @flags: Flags for buffer and packet state. These are only set on the
+ * first buffer of a scattered packet.
+ */
+struct ef4_rx_buffer {
+ dma_addr_t dma_addr;
+ struct page *page;
+ u16 page_offset;
+ u16 len;
+ u16 flags;
+};
+#define EF4_RX_BUF_LAST_IN_PAGE 0x0001
+#define EF4_RX_PKT_CSUMMED 0x0002
+#define EF4_RX_PKT_DISCARD 0x0004
+#define EF4_RX_PKT_TCP 0x0040
+#define EF4_RX_PKT_PREFIX_LEN 0x0080 /* length is in prefix only */
+
+/**
+ * struct ef4_rx_page_state - Page-based rx buffer state
+ *
+ * Inserted at the start of every page allocated for receive buffers.
+ * Used to facilitate sharing dma mappings between recycled rx buffers
+ * and those passed up to the kernel.
+ *
+ * @dma_addr: The dma address of this page.
+ */
+struct ef4_rx_page_state {
+ dma_addr_t dma_addr;
+
+ unsigned int __pad[0] ____cacheline_aligned;
+};
+
+/**
+ * struct ef4_rx_queue - An Efx RX queue
+ * @efx: The associated Efx NIC
+ * @core_index: Index of network core RX queue. Will be >= 0 iff this
+ * is associated with a real RX queue.
+ * @buffer: The software buffer ring
+ * @rxd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
+ * @refill_enabled: Enable refill whenever fill level is low
+ * @flush_pending: Set when a RX flush is pending. Has the same lifetime as
+ * @rxq_flush_pending.
+ * @added_count: Number of buffers added to the receive queue.
+ * @notified_count: Number of buffers given to NIC (<= @added_count).
+ * @removed_count: Number of buffers removed from the receive queue.
+ * @scatter_n: Used by NIC specific receive code.
+ * @scatter_len: Used by NIC specific receive code.
+ * @page_ring: The ring to store DMA mapped pages for reuse.
+ * @page_add: Counter to calculate the write pointer for the recycle ring.
+ * @page_remove: Counter to calculate the read pointer for the recycle ring.
+ * @page_recycle_count: The number of pages that have been recycled.
+ * @page_recycle_failed: The number of pages that couldn't be recycled because
+ * the kernel still held a reference to them.
+ * @page_recycle_full: The number of pages that were released because the
+ * recycle ring was full.
+ * @page_ptr_mask: The number of pages in the RX recycle ring minus 1.
+ * @max_fill: RX descriptor maximum fill level (<= ring size)
+ * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
+ * (<= @max_fill)
+ * @min_fill: RX descriptor minimum non-zero fill level.
+ * This records the minimum fill level observed when a ring
+ * refill was triggered.
+ * @recycle_count: RX buffer recycle counter.
+ * @slow_fill: Timer used to defer ef4_nic_generate_fill_event().
+ */
+struct ef4_rx_queue {
+ struct ef4_nic *efx;
+ int core_index;
+ struct ef4_rx_buffer *buffer;
+ struct ef4_special_buffer rxd;
+ unsigned int ptr_mask;
+ bool refill_enabled;
+ bool flush_pending;
+
+ unsigned int added_count;
+ unsigned int notified_count;
+ unsigned int removed_count;
+ unsigned int scatter_n;
+ unsigned int scatter_len;
+ struct page **page_ring;
+ unsigned int page_add;
+ unsigned int page_remove;
+ unsigned int page_recycle_count;
+ unsigned int page_recycle_failed;
+ unsigned int page_recycle_full;
+ unsigned int page_ptr_mask;
+ unsigned int max_fill;
+ unsigned int fast_fill_trigger;
+ unsigned int min_fill;
+ unsigned int min_overfill;
+ unsigned int recycle_count;
+ struct timer_list slow_fill;
+ unsigned int slow_fill_count;
+ /* Statistics to supplement MAC stats */
+ unsigned long rx_packets;
+};
+
+/**
+ * struct ef4_channel - An Efx channel
+ *
+ * A channel comprises an event queue, at least one TX queue, at least
+ * one RX queue, and an associated tasklet for processing the event
+ * queue.
+ *
+ * @efx: Associated Efx NIC
+ * @channel: Channel instance number
+ * @type: Channel type definition
+ * @eventq_init: Event queue initialised flag
+ * @enabled: Channel enabled indicator
+ * @irq: IRQ number (MSI and MSI-X only)
+ * @irq_moderation_us: IRQ moderation value (in microseconds)
+ * @napi_dev: Net device used with NAPI
+ * @napi_str: NAPI control structure
+ * @state: state for NAPI vs busy polling
+ * @state_lock: lock protecting @state
+ * @eventq: Event queue buffer
+ * @eventq_mask: Event queue pointer mask
+ * @eventq_read_ptr: Event queue read pointer
+ * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
+ * @irq_count: Number of IRQs since last adaptive moderation decision
+ * @irq_mod_score: IRQ moderation score
+ * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
+ * indexed by filter ID
+ * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
+ * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
+ * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
+ * @n_rx_mcast_mismatch: Count of unmatched multicast frames
+ * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
+ * @n_rx_overlength: Count of RX_OVERLENGTH errors
+ * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
+ * @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
+ * lack of descriptors
+ * @n_rx_merge_events: Number of RX merged completion events
+ * @n_rx_merge_packets: Number of RX packets completed by merged events
+ * @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
+ * __ef4_rx_packet(), or zero if there is none
+ * @rx_pkt_index: Ring index of first buffer for next packet to be delivered
+ * by __ef4_rx_packet(), if @rx_pkt_n_frags != 0
+ * @rx_queue: RX queue for this channel
+ * @tx_queue: TX queues for this channel
+ */
+struct ef4_channel {
+ struct ef4_nic *efx;
+ int channel;
+ const struct ef4_channel_type *type;
+ bool eventq_init;
+ bool enabled;
+ int irq;
+ unsigned int irq_moderation_us;
+ struct net_device *napi_dev;
+ struct napi_struct napi_str;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ unsigned long busy_poll_state;
+#endif
+ struct ef4_special_buffer eventq;
+ unsigned int eventq_mask;
+ unsigned int eventq_read_ptr;
+ int event_test_cpu;
+
+ unsigned int irq_count;
+ unsigned int irq_mod_score;
+#ifdef CONFIG_RFS_ACCEL
+ unsigned int rfs_filters_added;
+#define RPS_FLOW_ID_INVALID 0xFFFFFFFF
+ u32 *rps_flow_id;
+#endif
+
+ unsigned n_rx_tobe_disc;
+ unsigned n_rx_ip_hdr_chksum_err;
+ unsigned n_rx_tcp_udp_chksum_err;
+ unsigned n_rx_mcast_mismatch;
+ unsigned n_rx_frm_trunc;
+ unsigned n_rx_overlength;
+ unsigned n_skbuff_leaks;
+ unsigned int n_rx_nodesc_trunc;
+ unsigned int n_rx_merge_events;
+ unsigned int n_rx_merge_packets;
+
+ unsigned int rx_pkt_n_frags;
+ unsigned int rx_pkt_index;
+
+ struct ef4_rx_queue rx_queue;
+ struct ef4_tx_queue tx_queue[EF4_TXQ_TYPES];
+};
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+enum ef4_channel_busy_poll_state {
+ EF4_CHANNEL_STATE_IDLE = 0,
+ EF4_CHANNEL_STATE_NAPI = BIT(0),
+ EF4_CHANNEL_STATE_NAPI_REQ_BIT = 1,
+ EF4_CHANNEL_STATE_NAPI_REQ = BIT(1),
+ EF4_CHANNEL_STATE_POLL_BIT = 2,
+ EF4_CHANNEL_STATE_POLL = BIT(2),
+ EF4_CHANNEL_STATE_DISABLE_BIT = 3,
+};
+
+static inline void ef4_channel_busy_poll_init(struct ef4_channel *channel)
+{
+ WRITE_ONCE(channel->busy_poll_state, EF4_CHANNEL_STATE_IDLE);
+}
+
+/* Called from the device poll routine to get ownership of a channel. */
+static inline bool ef4_channel_lock_napi(struct ef4_channel *channel)
+{
+ unsigned long prev, old = READ_ONCE(channel->busy_poll_state);
+
+ while (1) {
+ switch (old) {
+ case EF4_CHANNEL_STATE_POLL:
+ /* Ensure ef4_channel_try_lock_poll() wont starve us */
+ set_bit(EF4_CHANNEL_STATE_NAPI_REQ_BIT,
+ &channel->busy_poll_state);
+ /* fallthrough */
+ case EF4_CHANNEL_STATE_POLL | EF4_CHANNEL_STATE_NAPI_REQ:
+ return false;
+ default:
+ break;
+ }
+ prev = cmpxchg(&channel->busy_poll_state, old,
+ EF4_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;
+ }
+}
+
+static inline void ef4_channel_unlock_napi(struct ef4_channel *channel)
+{
+ /* Make sure write has completed from ef4_channel_lock_napi() */
+ smp_wmb();
+ WRITE_ONCE(channel->busy_poll_state, EF4_CHANNEL_STATE_IDLE);
+}
+
+/* Called from ef4_busy_poll(). */
+static inline bool ef4_channel_try_lock_poll(struct ef4_channel *channel)
+{
+ return cmpxchg(&channel->busy_poll_state, EF4_CHANNEL_STATE_IDLE,
+ EF4_CHANNEL_STATE_POLL) == EF4_CHANNEL_STATE_IDLE;
+}
+
+static inline void ef4_channel_unlock_poll(struct ef4_channel *channel)
+{
+ clear_bit_unlock(EF4_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state);
+}
+
+static inline bool ef4_channel_busy_polling(struct ef4_channel *channel)
+{
+ return test_bit(EF4_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state);
+}
+
+static inline void ef4_channel_enable(struct ef4_channel *channel)
+{
+ clear_bit_unlock(EF4_CHANNEL_STATE_DISABLE_BIT,
+ &channel->busy_poll_state);
+}
+
+/* Stop further polling or napi access.
+ * Returns false if the channel is currently busy polling.
+ */
+static inline bool ef4_channel_disable(struct ef4_channel *channel)
+{
+ set_bit(EF4_CHANNEL_STATE_DISABLE_BIT, &channel->busy_poll_state);
+ /* Implicit barrier in ef4_channel_busy_polling() */
+ return !ef4_channel_busy_polling(channel);
+}
+
+#else /* CONFIG_NET_RX_BUSY_POLL */
+
+static inline void ef4_channel_busy_poll_init(struct ef4_channel *channel)
+{
+}
+
+static inline bool ef4_channel_lock_napi(struct ef4_channel *channel)
+{
+ return true;
+}
+
+static inline void ef4_channel_unlock_napi(struct ef4_channel *channel)
+{
+}
+
+static inline bool ef4_channel_try_lock_poll(struct ef4_channel *channel)
+{
+ return false;
+}
+
+static inline void ef4_channel_unlock_poll(struct ef4_channel *channel)
+{
+}
+
+static inline bool ef4_channel_busy_polling(struct ef4_channel *channel)
+{
+ return false;
+}
+
+static inline void ef4_channel_enable(struct ef4_channel *channel)
+{
+}
+
+static inline bool ef4_channel_disable(struct ef4_channel *channel)
+{
+ return true;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+/**
+ * struct ef4_msi_context - Context for each MSI
+ * @efx: The associated NIC
+ * @index: Index of the channel/IRQ
+ * @name: Name of the channel/IRQ
+ *
+ * Unlike &struct ef4_channel, this is never reallocated and is always
+ * safe for the IRQ handler to access.
+ */
+struct ef4_msi_context {
+ struct ef4_nic *efx;
+ unsigned int index;
+ char name[IFNAMSIZ + 6];
+};
+
+/**
+ * struct ef4_channel_type - distinguishes traffic and extra channels
+ * @handle_no_channel: Handle failure to allocate an extra channel
+ * @pre_probe: Set up extra state prior to initialisation
+ * @post_remove: Tear down extra state after finalisation, if allocated.
+ * May be called on channels that have not been probed.
+ * @get_name: Generate the channel's name (used for its IRQ handler)
+ * @copy: Copy the channel state prior to reallocation. May be %NULL if
+ * reallocation is not supported.
+ * @receive_skb: Handle an skb ready to be passed to netif_receive_skb()
+ * @keep_eventq: Flag for whether event queue should be kept initialised
+ * while the device is stopped
+ */
+struct ef4_channel_type {
+ void (*handle_no_channel)(struct ef4_nic *);
+ int (*pre_probe)(struct ef4_channel *);
+ void (*post_remove)(struct ef4_channel *);
+ void (*get_name)(struct ef4_channel *, char *buf, size_t len);
+ struct ef4_channel *(*copy)(const struct ef4_channel *);
+ bool (*receive_skb)(struct ef4_channel *, struct sk_buff *);
+ bool keep_eventq;
+};
+
+enum ef4_led_mode {
+ EF4_LED_OFF = 0,
+ EF4_LED_ON = 1,
+ EF4_LED_DEFAULT = 2
+};
+
+#define STRING_TABLE_LOOKUP(val, member) \
+ ((val) < member ## _max) ? member ## _names[val] : "(invalid)"
+
+extern const char *const ef4_loopback_mode_names[];
+extern const unsigned int ef4_loopback_mode_max;
+#define LOOPBACK_MODE(efx) \
+ STRING_TABLE_LOOKUP((efx)->loopback_mode, ef4_loopback_mode)
+
+extern const char *const ef4_reset_type_names[];
+extern const unsigned int ef4_reset_type_max;
+#define RESET_TYPE(type) \
+ STRING_TABLE_LOOKUP(type, ef4_reset_type)
+
+enum ef4_int_mode {
+ /* Be careful if altering to correct macro below */
+ EF4_INT_MODE_MSIX = 0,
+ EF4_INT_MODE_MSI = 1,
+ EF4_INT_MODE_LEGACY = 2,
+ EF4_INT_MODE_MAX /* Insert any new items before this */
+};
+#define EF4_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EF4_INT_MODE_MSI)
+
+enum nic_state {
+ STATE_UNINIT = 0, /* device being probed/removed or is frozen */
+ STATE_READY = 1, /* hardware ready and netdev registered */
+ STATE_DISABLED = 2, /* device disabled due to hardware errors */
+ STATE_RECOVERY = 3, /* device recovering from PCI error */
+};
+
+/* Forward declaration */
+struct ef4_nic;
+
+/* Pseudo bit-mask flow control field */
+#define EF4_FC_RX FLOW_CTRL_RX
+#define EF4_FC_TX FLOW_CTRL_TX
+#define EF4_FC_AUTO 4
+
+/**
+ * struct ef4_link_state - Current state of the link
+ * @up: Link is up
+ * @fd: Link is full-duplex
+ * @fc: Actual flow control flags
+ * @speed: Link speed (Mbps)
+ */
+struct ef4_link_state {
+ bool up;
+ bool fd;
+ u8 fc;
+ unsigned int speed;
+};
+
+static inline bool ef4_link_state_equal(const struct ef4_link_state *left,
+ const struct ef4_link_state *right)
+{
+ return left->up == right->up && left->fd == right->fd &&
+ left->fc == right->fc && left->speed == right->speed;
+}
+
+/**
+ * struct ef4_phy_operations - Efx PHY operations table
+ * @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds,
+ * efx->loopback_modes.
+ * @init: Initialise PHY
+ * @fini: Shut down PHY
+ * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
+ * @poll: Update @link_state and report whether it changed.
+ * Serialised by the mac_lock.
+ * @get_settings: Get ethtool settings. Serialised by the mac_lock.
+ * @set_settings: Set ethtool settings. Serialised by the mac_lock.
+ * @set_npage_adv: Set abilities advertised in (Extended) Next Page
+ * (only needed where AN bit is set in mmds)
+ * @test_alive: Test that PHY is 'alive' (online)
+ * @test_name: Get the name of a PHY-specific test/result
+ * @run_tests: Run tests and record results as appropriate (offline).
+ * Flags are the ethtool tests flags.
+ */
+struct ef4_phy_operations {
+ int (*probe) (struct ef4_nic *efx);
+ int (*init) (struct ef4_nic *efx);
+ void (*fini) (struct ef4_nic *efx);
+ void (*remove) (struct ef4_nic *efx);
+ int (*reconfigure) (struct ef4_nic *efx);
+ bool (*poll) (struct ef4_nic *efx);
+ void (*get_settings) (struct ef4_nic *efx,
+ struct ethtool_cmd *ecmd);
+ int (*set_settings) (struct ef4_nic *efx,
+ struct ethtool_cmd *ecmd);
+ void (*set_npage_adv) (struct ef4_nic *efx, u32);
+ int (*test_alive) (struct ef4_nic *efx);
+ const char *(*test_name) (struct ef4_nic *efx, unsigned int index);
+ int (*run_tests) (struct ef4_nic *efx, int *results, unsigned flags);
+ int (*get_module_eeprom) (struct ef4_nic *efx,
+ struct ethtool_eeprom *ee,
+ u8 *data);
+ int (*get_module_info) (struct ef4_nic *efx,
+ struct ethtool_modinfo *modinfo);
+};
+
+/**
+ * enum ef4_phy_mode - PHY operating mode flags
+ * @PHY_MODE_NORMAL: on and should pass traffic
+ * @PHY_MODE_TX_DISABLED: on with TX disabled
+ * @PHY_MODE_LOW_POWER: set to low power through MDIO
+ * @PHY_MODE_OFF: switched off through external control
+ * @PHY_MODE_SPECIAL: on but will not pass traffic
+ */
+enum ef4_phy_mode {
+ PHY_MODE_NORMAL = 0,
+ PHY_MODE_TX_DISABLED = 1,
+ PHY_MODE_LOW_POWER = 2,
+ PHY_MODE_OFF = 4,
+ PHY_MODE_SPECIAL = 8,
+};
+
+static inline bool ef4_phy_mode_disabled(enum ef4_phy_mode mode)
+{
+ return !!(mode & ~PHY_MODE_TX_DISABLED);
+}
+
+/**
+ * struct ef4_hw_stat_desc - Description of a hardware statistic
+ * @name: Name of the statistic as visible through ethtool, or %NULL if
+ * it should not be exposed
+ * @dma_width: Width in bits (0 for non-DMA statistics)
+ * @offset: Offset within stats (ignored for non-DMA statistics)
+ */
+struct ef4_hw_stat_desc {
+ const char *name;
+ u16 dma_width;
+ u16 offset;
+};
+
+/* Number of bits used in a multicast filter hash address */
+#define EF4_MCAST_HASH_BITS 8
+
+/* Number of (single-bit) entries in a multicast filter hash */
+#define EF4_MCAST_HASH_ENTRIES (1 << EF4_MCAST_HASH_BITS)
+
+/* An Efx multicast filter hash */
+union ef4_multicast_hash {
+ u8 byte[EF4_MCAST_HASH_ENTRIES / 8];
+ ef4_oword_t oword[EF4_MCAST_HASH_ENTRIES / sizeof(ef4_oword_t) / 8];
+};
+
+/**
+ * struct ef4_nic - an Efx NIC
+ * @name: Device name (net device name or bus id before net device registered)
+ * @pci_dev: The PCI device
+ * @node: List node for maintaning primary/secondary function lists
+ * @primary: &struct ef4_nic instance for the primary function of this
+ * controller. May be the same structure, and may be %NULL if no
+ * primary function is bound. Serialised by rtnl_lock.
+ * @secondary_list: List of &struct ef4_nic instances for the secondary PCI
+ * functions of the controller, if this is for the primary function.
+ * Serialised by rtnl_lock.
+ * @type: Controller type attributes
+ * @legacy_irq: IRQ number
+ * @workqueue: Workqueue for port reconfigures and the HW monitor.
+ * Work items do not hold and must not acquire RTNL.
+ * @workqueue_name: Name of workqueue
+ * @reset_work: Scheduled reset workitem
+ * @membase_phys: Memory BAR value as physical address
+ * @membase: Memory BAR value
+ * @interrupt_mode: Interrupt mode
+ * @timer_quantum_ns: Interrupt timer quantum, in nanoseconds
+ * @timer_max_ns: Interrupt timer maximum value, in nanoseconds
+ * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
+ * @irq_rx_mod_step_us: Step size for IRQ moderation for RX event queues
+ * @irq_rx_moderation_us: IRQ moderation time for RX event queues
+ * @msg_enable: Log message enable flags
+ * @state: Device state number (%STATE_*). Serialised by the rtnl_lock.
+ * @reset_pending: Bitmask for pending resets
+ * @tx_queue: TX DMA queues
+ * @rx_queue: RX DMA queues
+ * @channel: Channels
+ * @msi_context: Context for each MSI
+ * @extra_channel_types: Types of extra (non-traffic) channels that
+ * should be allocated for this NIC
+ * @rxq_entries: Size of receive queues requested by user.
+ * @txq_entries: Size of transmit queues requested by user.
+ * @txq_stop_thresh: TX queue fill level at or above which we stop it.
+ * @txq_wake_thresh: TX queue fill level at or below which we wake it.
+ * @tx_dc_base: Base qword address in SRAM of TX queue descriptor caches
+ * @rx_dc_base: Base qword address in SRAM of RX queue descriptor caches
+ * @sram_lim_qw: Qword address limit of SRAM
+ * @next_buffer_table: First available buffer table id
+ * @n_channels: Number of channels in use
+ * @n_rx_channels: Number of channels used for RX (= number of RX queues)
+ * @n_tx_channels: Number of channels used for TX
+ * @rx_ip_align: RX DMA address offset to have IP header aligned in
+ * in accordance with NET_IP_ALIGN
+ * @rx_dma_len: Current maximum RX DMA length
+ * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
+ * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
+ * for use in sk_buff::truesize
+ * @rx_prefix_size: Size of RX prefix before packet data
+ * @rx_packet_hash_offset: Offset of RX flow hash from start of packet data
+ * (valid only if @rx_prefix_size != 0; always negative)
+ * @rx_packet_len_offset: Offset of RX packet length from start of packet data
+ * (valid only for NICs that set %EF4_RX_PKT_PREFIX_LEN; always negative)
+ * @rx_packet_ts_offset: Offset of timestamp from start of packet data
+ * (valid only if channel->sync_timestamps_enabled; always negative)
+ * @rx_hash_key: Toeplitz hash key for RSS
+ * @rx_indir_table: Indirection table for RSS
+ * @rx_scatter: Scatter mode enabled for receives
+ * @int_error_count: Number of internal errors seen recently
+ * @int_error_expire: Time at which error count will be expired
+ * @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will
+ * acknowledge but do nothing else.
+ * @irq_status: Interrupt status buffer
+ * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
+ * @irq_level: IRQ level/index for IRQs not triggered by an event queue
+ * @selftest_work: Work item for asynchronous self-test
+ * @mtd_list: List of MTDs attached to the NIC
+ * @nic_data: Hardware dependent state
+ * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
+ * ef4_monitor() and ef4_reconfigure_port()
+ * @port_enabled: Port enabled indicator.
+ * Serialises ef4_stop_all(), ef4_start_all(), ef4_monitor() and
+ * ef4_mac_work() with kernel interfaces. Safe to read under any
+ * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
+ * be held to modify it.
+ * @port_initialized: Port initialized?
+ * @net_dev: Operating system network device. Consider holding the rtnl lock
+ * @fixed_features: Features which cannot be turned off
+ * @stats_buffer: DMA buffer for statistics
+ * @phy_type: PHY type
+ * @phy_op: PHY interface
+ * @phy_data: PHY private data (including PHY-specific stats)
+ * @mdio: PHY MDIO interface
+ * @phy_mode: PHY operating mode. Serialised by @mac_lock.
+ * @link_advertising: Autonegotiation advertising flags
+ * @link_state: Current state of the link
+ * @n_link_state_changes: Number of times the link has changed state
+ * @unicast_filter: Flag for Falcon-arch simple unicast filter.
+ * Protected by @mac_lock.
+ * @multicast_hash: Multicast hash table for Falcon-arch.
+ * Protected by @mac_lock.
+ * @wanted_fc: Wanted flow control flags
+ * @fc_disable: When non-zero flow control is disabled. Typically used to
+ * ensure that network back pressure doesn't delay dma queue flushes.
+ * Serialised by the rtnl lock.
+ * @mac_work: Work item for changing MAC promiscuity and multicast hash
+ * @loopback_mode: Loopback status
+ * @loopback_modes: Supported loopback mode bitmask
+ * @loopback_selftest: Offline self-test private state
+ * @filter_sem: Filter table rw_semaphore, for freeing the table
+ * @filter_lock: Filter table lock, for mere content changes
+ * @filter_state: Architecture-dependent filter table state
+ * @rps_expire_channel: Next channel to check for expiry
+ * @rps_expire_index: Next index to check for expiry in
+ * @rps_expire_channel's @rps_flow_id
+ * @active_queues: Count of RX and TX queues that haven't been flushed and drained.
+ * @rxq_flush_pending: Count of number of receive queues that need to be flushed.
+ * Decremented when the ef4_flush_rx_queue() is called.
+ * @rxq_flush_outstanding: Count of number of RX flushes started but not yet
+ * completed (either success or failure). Not used when MCDI is used to
+ * flush receive queues.
+ * @flush_wq: wait queue used by ef4_nic_flush_queues() to wait for flush completions.
+ * @vpd_sn: Serial number read from VPD
+ * @monitor_work: Hardware monitor workitem
+ * @biu_lock: BIU (bus interface unit) lock
+ * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
+ * field is used by ef4_test_interrupts() to verify that an
+ * interrupt has occurred.
+ * @stats_lock: Statistics update lock. Must be held when calling
+ * ef4_nic_type::{update,start,stop}_stats.
+ * @n_rx_noskb_drops: Count of RX packets dropped due to failure to allocate an skb
+ *
+ * This is stored in the private area of the &struct net_device.
+ */
+struct ef4_nic {
+ /* The following fields should be written very rarely */
+
+ char name[IFNAMSIZ];
+ struct list_head node;
+ struct ef4_nic *primary;
+ struct list_head secondary_list;
+ struct pci_dev *pci_dev;
+ unsigned int port_num;
+ const struct ef4_nic_type *type;
+ int legacy_irq;
+ bool eeh_disabled_legacy_irq;
+ struct workqueue_struct *workqueue;
+ char workqueue_name[16];
+ struct work_struct reset_work;
+ resource_size_t membase_phys;
+ void __iomem *membase;
+
+ enum ef4_int_mode interrupt_mode;
+ unsigned int timer_quantum_ns;
+ unsigned int timer_max_ns;
+ bool irq_rx_adaptive;
+ unsigned int irq_mod_step_us;
+ unsigned int irq_rx_moderation_us;
+ u32 msg_enable;
+
+ enum nic_state state;
+ unsigned long reset_pending;
+
+ struct ef4_channel *channel[EF4_MAX_CHANNELS];
+ struct ef4_msi_context msi_context[EF4_MAX_CHANNELS];
+ const struct ef4_channel_type *
+ extra_channel_type[EF4_MAX_EXTRA_CHANNELS];
+
+ unsigned rxq_entries;
+ unsigned txq_entries;
+ unsigned int txq_stop_thresh;
+ unsigned int txq_wake_thresh;
+
+ unsigned tx_dc_base;
+ unsigned rx_dc_base;
+ unsigned sram_lim_qw;
+ unsigned next_buffer_table;
+
+ unsigned int max_channels;
+ unsigned int max_tx_channels;
+ unsigned n_channels;
+ unsigned n_rx_channels;
+ unsigned rss_spread;
+ unsigned tx_channel_offset;
+ unsigned n_tx_channels;
+ unsigned int rx_ip_align;
+ unsigned int rx_dma_len;
+ unsigned int rx_buffer_order;
+ unsigned int rx_buffer_truesize;
+ unsigned int rx_page_buf_step;
+ unsigned int rx_bufs_per_page;
+ unsigned int rx_pages_per_batch;
+ unsigned int rx_prefix_size;
+ int rx_packet_hash_offset;
+ int rx_packet_len_offset;
+ int rx_packet_ts_offset;
+ u8 rx_hash_key[40];
+ u32 rx_indir_table[128];
+ bool rx_scatter;
+
+ unsigned int_error_count;
+ unsigned long int_error_expire;
+
+ bool irq_soft_enabled;
+ struct ef4_buffer irq_status;
+ unsigned irq_zero_count;
+ unsigned irq_level;
+ struct delayed_work selftest_work;
+
+#ifdef CONFIG_SFC_FALCON_MTD
+ struct list_head mtd_list;
+#endif
+
+ void *nic_data;
+
+ struct mutex mac_lock;
+ struct work_struct mac_work;
+ bool port_enabled;
+
+ bool mc_bist_for_other_fn;
+ bool port_initialized;
+ struct net_device *net_dev;
+
+ netdev_features_t fixed_features;
+
+ struct ef4_buffer stats_buffer;
+ u64 rx_nodesc_drops_total;
+ u64 rx_nodesc_drops_while_down;
+ bool rx_nodesc_drops_prev_state;
+
+ unsigned int phy_type;
+ const struct ef4_phy_operations *phy_op;
+ void *phy_data;
+ struct mdio_if_info mdio;
+ enum ef4_phy_mode phy_mode;
+
+ u32 link_advertising;
+ struct ef4_link_state link_state;
+ unsigned int n_link_state_changes;
+
+ bool unicast_filter;
+ union ef4_multicast_hash multicast_hash;
+ u8 wanted_fc;
+ unsigned fc_disable;
+
+ atomic_t rx_reset;
+ enum ef4_loopback_mode loopback_mode;
+ u64 loopback_modes;
+
+ void *loopback_selftest;
+
+ struct rw_semaphore filter_sem;
+ spinlock_t filter_lock;
+ void *filter_state;
+#ifdef CONFIG_RFS_ACCEL
+ unsigned int rps_expire_channel;
+ unsigned int rps_expire_index;
+#endif
+
+ atomic_t active_queues;
+ atomic_t rxq_flush_pending;
+ atomic_t rxq_flush_outstanding;
+ wait_queue_head_t flush_wq;
+
+ char *vpd_sn;
+
+ /* The following fields may be written more often */
+
+ struct delayed_work monitor_work ____cacheline_aligned_in_smp;
+ spinlock_t biu_lock;
+ int last_irq_cpu;
+ spinlock_t stats_lock;
+ atomic_t n_rx_noskb_drops;
+};
+
+static inline int ef4_dev_registered(struct ef4_nic *efx)
+{
+ return efx->net_dev->reg_state == NETREG_REGISTERED;
+}
+
+static inline unsigned int ef4_port_num(struct ef4_nic *efx)
+{
+ return efx->port_num;
+}
+
+struct ef4_mtd_partition {
+ struct list_head node;
+ struct mtd_info mtd;
+ const char *dev_type_name;
+ const char *type_name;
+ char name[IFNAMSIZ + 20];
+};
+
+/**
+ * struct ef4_nic_type - Efx device type definition
+ * @mem_bar: Get the memory BAR
+ * @mem_map_size: Get memory BAR mapped size
+ * @probe: Probe the controller
+ * @remove: Free resources allocated by probe()
+ * @init: Initialise the controller
+ * @dimension_resources: Dimension controller resources (buffer table,
+ * and VIs once the available interrupt resources are clear)
+ * @fini: Shut down the controller
+ * @monitor: Periodic function for polling link state and hardware monitor
+ * @map_reset_reason: Map ethtool reset reason to a reset method
+ * @map_reset_flags: Map ethtool reset flags to a reset method, if possible
+ * @reset: Reset the controller hardware and possibly the PHY. This will
+ * be called while the controller is uninitialised.
+ * @probe_port: Probe the MAC and PHY
+ * @remove_port: Free resources allocated by probe_port()
+ * @handle_global_event: Handle a "global" event (may be %NULL)
+ * @fini_dmaq: Flush and finalise DMA queues (RX and TX queues)
+ * @prepare_flush: Prepare the hardware for flushing the DMA queues
+ * (for Falcon architecture)
+ * @finish_flush: Clean up after flushing the DMA queues (for Falcon
+ * architecture)
+ * @prepare_flr: Prepare for an FLR
+ * @finish_flr: Clean up after an FLR
+ * @describe_stats: Describe statistics for ethtool
+ * @update_stats: Update statistics not provided by event handling.
+ * Either argument may be %NULL.
+ * @start_stats: Start the regular fetching of statistics
+ * @pull_stats: Pull stats from the NIC and wait until they arrive.
+ * @stop_stats: Stop the regular fetching of statistics
+ * @set_id_led: Set state of identifying LED or revert to automatic function
+ * @push_irq_moderation: Apply interrupt moderation value
+ * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY
+ * @prepare_enable_fc_tx: Prepare MAC to enable pause frame TX (may be %NULL)
+ * @reconfigure_mac: Push MAC address, MTU, flow control and filter settings
+ * to the hardware. Serialised by the mac_lock.
+ * @check_mac_fault: Check MAC fault state. True if fault present.
+ * @get_wol: Get WoL configuration from driver state
+ * @set_wol: Push WoL configuration to the NIC
+ * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume)
+ * @test_chip: Test registers. May use ef4_farch_test_registers(), and is
+ * expected to reset the NIC.
+ * @test_nvram: Test validity of NVRAM contents
+ * @irq_enable_master: Enable IRQs on the NIC. Each event queue must
+ * be separately enabled after this.
+ * @irq_test_generate: Generate a test IRQ
+ * @irq_disable_non_ev: Disable non-event IRQs on the NIC. Each event
+ * queue must be separately disabled before this.
+ * @irq_handle_msi: Handle MSI for a channel. The @dev_id argument is
+ * a pointer to the &struct ef4_msi_context for the channel.
+ * @irq_handle_legacy: Handle legacy interrupt. The @dev_id argument
+ * is a pointer to the &struct ef4_nic.
+ * @tx_probe: Allocate resources for TX queue
+ * @tx_init: Initialise TX queue on the NIC
+ * @tx_remove: Free resources for TX queue
+ * @tx_write: Write TX descriptors and doorbell
+ * @rx_push_rss_config: Write RSS hash key and indirection table to the NIC
+ * @rx_probe: Allocate resources for RX queue
+ * @rx_init: Initialise RX queue on the NIC
+ * @rx_remove: Free resources for RX queue
+ * @rx_write: Write RX descriptors and doorbell
+ * @rx_defer_refill: Generate a refill reminder event
+ * @ev_probe: Allocate resources for event queue
+ * @ev_init: Initialise event queue on the NIC
+ * @ev_fini: Deinitialise event queue on the NIC
+ * @ev_remove: Free resources for event queue
+ * @ev_process: Process events for a queue, up to the given NAPI quota
+ * @ev_read_ack: Acknowledge read events on a queue, rearming its IRQ
+ * @ev_test_generate: Generate a test event
+ * @filter_table_probe: Probe filter capabilities and set up filter software state
+ * @filter_table_restore: Restore filters removed from hardware
+ * @filter_table_remove: Remove filters from hardware and tear down software state
+ * @filter_update_rx_scatter: Update filters after change to rx scatter setting
+ * @filter_insert: add or replace a filter
+ * @filter_remove_safe: remove a filter by ID, carefully
+ * @filter_get_safe: retrieve a filter by ID, carefully
+ * @filter_clear_rx: Remove all RX filters whose priority is less than or
+ * equal to the given priority and is not %EF4_FILTER_PRI_AUTO
+ * @filter_count_rx_used: Get the number of filters in use at a given priority
+ * @filter_get_rx_id_limit: Get maximum value of a filter id, plus 1
+ * @filter_get_rx_ids: Get list of RX filters at a given priority
+ * @filter_rfs_insert: Add or replace a filter for RFS. This must be
+ * atomic. The hardware change may be asynchronous but should
+ * not be delayed for long. It may fail if this can't be done
+ * atomically.
+ * @filter_rfs_expire_one: Consider expiring a filter inserted for RFS.
+ * This must check whether the specified table entry is used by RFS
+ * and that rps_may_expire_flow() returns true for it.
+ * @mtd_probe: Probe and add MTD partitions associated with this net device,
+ * using ef4_mtd_add()
+ * @mtd_rename: Set an MTD partition name using the net device name
+ * @mtd_read: Read from an MTD partition
+ * @mtd_erase: Erase part of an MTD partition
+ * @mtd_write: Write to an MTD partition
+ * @mtd_sync: Wait for write-back to complete on MTD partition. This
+ * also notifies the driver that a writer has finished using this
+ * partition.
+ * @set_mac_address: Set the MAC address of the device
+ * @revision: Hardware architecture revision
+ * @txd_ptr_tbl_base: TX descriptor ring base address
+ * @rxd_ptr_tbl_base: RX descriptor ring base address
+ * @buf_tbl_base: Buffer table base address
+ * @evq_ptr_tbl_base: Event queue pointer table base address
+ * @evq_rptr_tbl_base: Event queue read-pointer table base address
+ * @max_dma_mask: Maximum possible DMA mask
+ * @rx_prefix_size: Size of RX prefix before packet data
+ * @rx_hash_offset: Offset of RX flow hash within prefix
+ * @rx_ts_offset: Offset of timestamp within prefix
+ * @rx_buffer_padding: Size of padding at end of RX packet
+ * @can_rx_scatter: NIC is able to scatter packets to multiple buffers
+ * @always_rx_scatter: NIC will always scatter packets to multiple buffers
+ * @max_interrupt_mode: Highest capability interrupt mode supported
+ * from &enum ef4_init_mode.
+ * @timer_period_max: Maximum period of interrupt timer (in ticks)
+ * @offload_features: net_device feature flags for protocol offload
+ * features implemented in hardware
+ */
+struct ef4_nic_type {
+ unsigned int mem_bar;
+ unsigned int (*mem_map_size)(struct ef4_nic *efx);
+ int (*probe)(struct ef4_nic *efx);
+ void (*remove)(struct ef4_nic *efx);
+ int (*init)(struct ef4_nic *efx);
+ int (*dimension_resources)(struct ef4_nic *efx);
+ void (*fini)(struct ef4_nic *efx);
+ void (*monitor)(struct ef4_nic *efx);
+ enum reset_type (*map_reset_reason)(enum reset_type reason);
+ int (*map_reset_flags)(u32 *flags);
+ int (*reset)(struct ef4_nic *efx, enum reset_type method);
+ int (*probe_port)(struct ef4_nic *efx);
+ void (*remove_port)(struct ef4_nic *efx);
+ bool (*handle_global_event)(struct ef4_channel *channel, ef4_qword_t *);
+ int (*fini_dmaq)(struct ef4_nic *efx);
+ void (*prepare_flush)(struct ef4_nic *efx);
+ void (*finish_flush)(struct ef4_nic *efx);
+ void (*prepare_flr)(struct ef4_nic *efx);
+ void (*finish_flr)(struct ef4_nic *efx);
+ size_t (*describe_stats)(struct ef4_nic *efx, u8 *names);
+ size_t (*update_stats)(struct ef4_nic *efx, u64 *full_stats,
+ struct rtnl_link_stats64 *core_stats);
+ void (*start_stats)(struct ef4_nic *efx);
+ void (*pull_stats)(struct ef4_nic *efx);
+ void (*stop_stats)(struct ef4_nic *efx);
+ void (*set_id_led)(struct ef4_nic *efx, enum ef4_led_mode mode);
+ void (*push_irq_moderation)(struct ef4_channel *channel);
+ int (*reconfigure_port)(struct ef4_nic *efx);
+ void (*prepare_enable_fc_tx)(struct ef4_nic *efx);
+ int (*reconfigure_mac)(struct ef4_nic *efx);
+ bool (*check_mac_fault)(struct ef4_nic *efx);
+ void (*get_wol)(struct ef4_nic *efx, struct ethtool_wolinfo *wol);
+ int (*set_wol)(struct ef4_nic *efx, u32 type);
+ void (*resume_wol)(struct ef4_nic *efx);
+ int (*test_chip)(struct ef4_nic *efx, struct ef4_self_tests *tests);
+ int (*test_nvram)(struct ef4_nic *efx);
+ void (*irq_enable_master)(struct ef4_nic *efx);
+ int (*irq_test_generate)(struct ef4_nic *efx);
+ void (*irq_disable_non_ev)(struct ef4_nic *efx);
+ irqreturn_t (*irq_handle_msi)(int irq, void *dev_id);
+ irqreturn_t (*irq_handle_legacy)(int irq, void *dev_id);
+ int (*tx_probe)(struct ef4_tx_queue *tx_queue);
+ void (*tx_init)(struct ef4_tx_queue *tx_queue);
+ void (*tx_remove)(struct ef4_tx_queue *tx_queue);
+ void (*tx_write)(struct ef4_tx_queue *tx_queue);
+ unsigned int (*tx_limit_len)(struct ef4_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
+ int (*rx_push_rss_config)(struct ef4_nic *efx, bool user,
+ const u32 *rx_indir_table);
+ int (*rx_probe)(struct ef4_rx_queue *rx_queue);
+ void (*rx_init)(struct ef4_rx_queue *rx_queue);
+ void (*rx_remove)(struct ef4_rx_queue *rx_queue);
+ void (*rx_write)(struct ef4_rx_queue *rx_queue);
+ void (*rx_defer_refill)(struct ef4_rx_queue *rx_queue);
+ int (*ev_probe)(struct ef4_channel *channel);
+ int (*ev_init)(struct ef4_channel *channel);
+ void (*ev_fini)(struct ef4_channel *channel);
+ void (*ev_remove)(struct ef4_channel *channel);
+ int (*ev_process)(struct ef4_channel *channel, int quota);
+ void (*ev_read_ack)(struct ef4_channel *channel);
+ void (*ev_test_generate)(struct ef4_channel *channel);
+ int (*filter_table_probe)(struct ef4_nic *efx);
+ void (*filter_table_restore)(struct ef4_nic *efx);
+ void (*filter_table_remove)(struct ef4_nic *efx);
+ void (*filter_update_rx_scatter)(struct ef4_nic *efx);
+ s32 (*filter_insert)(struct ef4_nic *efx,
+ struct ef4_filter_spec *spec, bool replace);
+ int (*filter_remove_safe)(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id);
+ int (*filter_get_safe)(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id, struct ef4_filter_spec *);
+ int (*filter_clear_rx)(struct ef4_nic *efx,
+ enum ef4_filter_priority priority);
+ u32 (*filter_count_rx_used)(struct ef4_nic *efx,
+ enum ef4_filter_priority priority);
+ u32 (*filter_get_rx_id_limit)(struct ef4_nic *efx);
+ s32 (*filter_get_rx_ids)(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 *buf, u32 size);
+#ifdef CONFIG_RFS_ACCEL
+ s32 (*filter_rfs_insert)(struct ef4_nic *efx,
+ struct ef4_filter_spec *spec);
+ bool (*filter_rfs_expire_one)(struct ef4_nic *efx, u32 flow_id,
+ unsigned int index);
+#endif
+#ifdef CONFIG_SFC_FALCON_MTD
+ int (*mtd_probe)(struct ef4_nic *efx);
+ void (*mtd_rename)(struct ef4_mtd_partition *part);
+ int (*mtd_read)(struct mtd_info *mtd, loff_t start, size_t len,
+ size_t *retlen, u8 *buffer);
+ int (*mtd_erase)(struct mtd_info *mtd, loff_t start, size_t len);
+ int (*mtd_write)(struct mtd_info *mtd, loff_t start, size_t len,
+ size_t *retlen, const u8 *buffer);
+ int (*mtd_sync)(struct mtd_info *mtd);
+#endif
+ int (*get_mac_address)(struct ef4_nic *efx, unsigned char *perm_addr);
+ int (*set_mac_address)(struct ef4_nic *efx);
+
+ int revision;
+ unsigned int txd_ptr_tbl_base;
+ unsigned int rxd_ptr_tbl_base;
+ unsigned int buf_tbl_base;
+ unsigned int evq_ptr_tbl_base;
+ unsigned int evq_rptr_tbl_base;
+ u64 max_dma_mask;
+ unsigned int rx_prefix_size;
+ unsigned int rx_hash_offset;
+ unsigned int rx_ts_offset;
+ unsigned int rx_buffer_padding;
+ bool can_rx_scatter;
+ bool always_rx_scatter;
+ unsigned int max_interrupt_mode;
+ unsigned int timer_period_max;
+ netdev_features_t offload_features;
+ unsigned int max_rx_ip_filters;
+};
+
+/**************************************************************************
+ *
+ * Prototypes and inline functions
+ *
+ *************************************************************************/
+
+static inline struct ef4_channel *
+ef4_get_channel(struct ef4_nic *efx, unsigned index)
+{
+ EF4_BUG_ON_PARANOID(index >= efx->n_channels);
+ return efx->channel[index];
+}
+
+/* Iterate over all used channels */
+#define ef4_for_each_channel(_channel, _efx) \
+ for (_channel = (_efx)->channel[0]; \
+ _channel; \
+ _channel = (_channel->channel + 1 < (_efx)->n_channels) ? \
+ (_efx)->channel[_channel->channel + 1] : NULL)
+
+/* Iterate over all used channels in reverse */
+#define ef4_for_each_channel_rev(_channel, _efx) \
+ for (_channel = (_efx)->channel[(_efx)->n_channels - 1]; \
+ _channel; \
+ _channel = _channel->channel ? \
+ (_efx)->channel[_channel->channel - 1] : NULL)
+
+static inline struct ef4_tx_queue *
+ef4_get_tx_queue(struct ef4_nic *efx, unsigned index, unsigned type)
+{
+ EF4_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
+ type >= EF4_TXQ_TYPES);
+ return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
+}
+
+static inline bool ef4_channel_has_tx_queues(struct ef4_channel *channel)
+{
+ return channel->channel - channel->efx->tx_channel_offset <
+ channel->efx->n_tx_channels;
+}
+
+static inline struct ef4_tx_queue *
+ef4_channel_get_tx_queue(struct ef4_channel *channel, unsigned type)
+{
+ EF4_BUG_ON_PARANOID(!ef4_channel_has_tx_queues(channel) ||
+ type >= EF4_TXQ_TYPES);
+ return &channel->tx_queue[type];
+}
+
+static inline bool ef4_tx_queue_used(struct ef4_tx_queue *tx_queue)
+{
+ return !(tx_queue->efx->net_dev->num_tc < 2 &&
+ tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI);
+}
+
+/* Iterate over all TX queues belonging to a channel */
+#define ef4_for_each_channel_tx_queue(_tx_queue, _channel) \
+ if (!ef4_channel_has_tx_queues(_channel)) \
+ ; \
+ else \
+ for (_tx_queue = (_channel)->tx_queue; \
+ _tx_queue < (_channel)->tx_queue + EF4_TXQ_TYPES && \
+ ef4_tx_queue_used(_tx_queue); \
+ _tx_queue++)
+
+/* Iterate over all possible TX queues belonging to a channel */
+#define ef4_for_each_possible_channel_tx_queue(_tx_queue, _channel) \
+ if (!ef4_channel_has_tx_queues(_channel)) \
+ ; \
+ else \
+ for (_tx_queue = (_channel)->tx_queue; \
+ _tx_queue < (_channel)->tx_queue + EF4_TXQ_TYPES; \
+ _tx_queue++)
+
+static inline bool ef4_channel_has_rx_queue(struct ef4_channel *channel)
+{
+ return channel->rx_queue.core_index >= 0;
+}
+
+static inline struct ef4_rx_queue *
+ef4_channel_get_rx_queue(struct ef4_channel *channel)
+{
+ EF4_BUG_ON_PARANOID(!ef4_channel_has_rx_queue(channel));
+ return &channel->rx_queue;
+}
+
+/* Iterate over all RX queues belonging to a channel */
+#define ef4_for_each_channel_rx_queue(_rx_queue, _channel) \
+ if (!ef4_channel_has_rx_queue(_channel)) \
+ ; \
+ else \
+ for (_rx_queue = &(_channel)->rx_queue; \
+ _rx_queue; \
+ _rx_queue = NULL)
+
+static inline struct ef4_channel *
+ef4_rx_queue_channel(struct ef4_rx_queue *rx_queue)
+{
+ return container_of(rx_queue, struct ef4_channel, rx_queue);
+}
+
+static inline int ef4_rx_queue_index(struct ef4_rx_queue *rx_queue)
+{
+ return ef4_rx_queue_channel(rx_queue)->channel;
+}
+
+/* Returns a pointer to the specified receive buffer in the RX
+ * descriptor queue.
+ */
+static inline struct ef4_rx_buffer *ef4_rx_buffer(struct ef4_rx_queue *rx_queue,
+ unsigned int index)
+{
+ return &rx_queue->buffer[index];
+}
+
+/**
+ * EF4_MAX_FRAME_LEN - calculate maximum frame length
+ *
+ * This calculates the maximum frame length that will be used for a
+ * given MTU. The frame length will be equal to the MTU plus a
+ * constant amount of header space and padding. This is the quantity
+ * that the net driver will program into the MAC as the maximum frame
+ * length.
+ *
+ * The 10G MAC requires 8-byte alignment on the frame
+ * length, so we round up to the nearest 8.
+ *
+ * Re-clocking by the XGXS on RX can reduce an IPG to 32 bits (half an
+ * XGMII cycle). If the frame length reaches the maximum value in the
+ * same cycle, the XMAC can miss the IPG altogether. We work around
+ * this by adding a further 16 bytes.
+ */
+#define EF4_FRAME_PAD 16
+#define EF4_MAX_FRAME_LEN(mtu) \
+ (ALIGN(((mtu) + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN + EF4_FRAME_PAD), 8))
+
+/* Get all supported features.
+ * If a feature is not fixed, it is present in hw_features.
+ * If a feature is fixed, it does not present in hw_features, but
+ * always in features.
+ */
+static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx)
+{
+ const struct net_device *net_dev = efx->net_dev;
+
+ return net_dev->features | net_dev->hw_features;
+}
+
+/* Get the current TX queue insert index. */
+static inline unsigned int
+ef4_tx_queue_get_insert_index(const struct ef4_tx_queue *tx_queue)
+{
+ return tx_queue->insert_count & tx_queue->ptr_mask;
+}
+
+/* Get a TX buffer. */
+static inline struct ef4_tx_buffer *
+__ef4_tx_queue_get_insert_buffer(const struct ef4_tx_queue *tx_queue)
+{
+ return &tx_queue->buffer[ef4_tx_queue_get_insert_index(tx_queue)];
+}
+
+/* Get a TX buffer, checking it's not currently in use. */
+static inline struct ef4_tx_buffer *
+ef4_tx_queue_get_insert_buffer(const struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_tx_buffer *buffer =
+ __ef4_tx_queue_get_insert_buffer(tx_queue);
+
+ EF4_BUG_ON_PARANOID(buffer->len);
+ EF4_BUG_ON_PARANOID(buffer->flags);
+ EF4_BUG_ON_PARANOID(buffer->unmap_len);
+
+ return buffer;
+}
+
+#endif /* EF4_NET_DRIVER_H */
diff --git a/drivers/net/ethernet/sfc/falcon/nic.c b/drivers/net/ethernet/sfc/falcon/nic.c
new file mode 100644
index 000000000000..a8ecb33390da
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/nic.c
@@ -0,0 +1,527 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/cpu_rmap.h>
+#include "net_driver.h"
+#include "bitfield.h"
+#include "efx.h"
+#include "nic.h"
+#include "farch_regs.h"
+#include "io.h"
+#include "workarounds.h"
+
+/**************************************************************************
+ *
+ * Generic buffer handling
+ * These buffers are used for interrupt status, MAC stats, etc.
+ *
+ **************************************************************************/
+
+int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer,
+ unsigned int len, gfp_t gfp_flags)
+{
+ buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
+ &buffer->dma_addr, gfp_flags);
+ if (!buffer->addr)
+ return -ENOMEM;
+ buffer->len = len;
+ return 0;
+}
+
+void ef4_nic_free_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer)
+{
+ if (buffer->addr) {
+ dma_free_coherent(&efx->pci_dev->dev, buffer->len,
+ buffer->addr, buffer->dma_addr);
+ buffer->addr = NULL;
+ }
+}
+
+/* Check whether an event is present in the eventq at the current
+ * read pointer. Only useful for self-test.
+ */
+bool ef4_nic_event_present(struct ef4_channel *channel)
+{
+ return ef4_event_present(ef4_event(channel, channel->eventq_read_ptr));
+}
+
+void ef4_nic_event_test_start(struct ef4_channel *channel)
+{
+ channel->event_test_cpu = -1;
+ smp_wmb();
+ channel->efx->type->ev_test_generate(channel);
+}
+
+int ef4_nic_irq_test_start(struct ef4_nic *efx)
+{
+ efx->last_irq_cpu = -1;
+ smp_wmb();
+ return efx->type->irq_test_generate(efx);
+}
+
+/* Hook interrupt handler(s)
+ * Try MSI and then legacy interrupts.
+ */
+int ef4_nic_init_interrupt(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+ unsigned int n_irqs;
+ int rc;
+
+ if (!EF4_INT_MODE_USE_MSI(efx)) {
+ rc = request_irq(efx->legacy_irq,
+ efx->type->irq_handle_legacy, IRQF_SHARED,
+ efx->name, efx);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "failed to hook legacy IRQ %d\n",
+ efx->pci_dev->irq);
+ goto fail1;
+ }
+ return 0;
+ }
+
+#ifdef CONFIG_RFS_ACCEL
+ if (efx->interrupt_mode == EF4_INT_MODE_MSIX) {
+ efx->net_dev->rx_cpu_rmap =
+ alloc_irq_cpu_rmap(efx->n_rx_channels);
+ if (!efx->net_dev->rx_cpu_rmap) {
+ rc = -ENOMEM;
+ goto fail1;
+ }
+ }
+#endif
+
+ /* Hook MSI or MSI-X interrupt */
+ n_irqs = 0;
+ ef4_for_each_channel(channel, efx) {
+ rc = request_irq(channel->irq, efx->type->irq_handle_msi,
+ IRQF_PROBE_SHARED, /* Not shared */
+ efx->msi_context[channel->channel].name,
+ &efx->msi_context[channel->channel]);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "failed to hook IRQ %d\n", channel->irq);
+ goto fail2;
+ }
+ ++n_irqs;
+
+#ifdef CONFIG_RFS_ACCEL
+ if (efx->interrupt_mode == EF4_INT_MODE_MSIX &&
+ channel->channel < efx->n_rx_channels) {
+ rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap,
+ channel->irq);
+ if (rc)
+ goto fail2;
+ }
+#endif
+ }
+
+ return 0;
+
+ fail2:
+#ifdef CONFIG_RFS_ACCEL
+ free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+ efx->net_dev->rx_cpu_rmap = NULL;
+#endif
+ ef4_for_each_channel(channel, efx) {
+ if (n_irqs-- == 0)
+ break;
+ free_irq(channel->irq, &efx->msi_context[channel->channel]);
+ }
+ fail1:
+ return rc;
+}
+
+void ef4_nic_fini_interrupt(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+#ifdef CONFIG_RFS_ACCEL
+ free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+ efx->net_dev->rx_cpu_rmap = NULL;
+#endif
+
+ if (EF4_INT_MODE_USE_MSI(efx)) {
+ /* Disable MSI/MSI-X interrupts */
+ ef4_for_each_channel(channel, efx)
+ free_irq(channel->irq,
+ &efx->msi_context[channel->channel]);
+ } else {
+ /* Disable legacy interrupt */
+ free_irq(efx->legacy_irq, efx);
+ }
+}
+
+/* Register dump */
+
+#define REGISTER_REVISION_FA 1
+#define REGISTER_REVISION_FB 2
+#define REGISTER_REVISION_FC 3
+#define REGISTER_REVISION_FZ 3 /* last Falcon arch revision */
+#define REGISTER_REVISION_ED 4
+#define REGISTER_REVISION_EZ 4 /* latest EF10 revision */
+
+struct ef4_nic_reg {
+ u32 offset:24;
+ u32 min_revision:3, max_revision:3;
+};
+
+#define REGISTER(name, arch, min_rev, max_rev) { \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name, \
+ REGISTER_REVISION_ ## arch ## min_rev, \
+ REGISTER_REVISION_ ## arch ## max_rev \
+}
+#define REGISTER_AA(name) REGISTER(name, F, A, A)
+#define REGISTER_AB(name) REGISTER(name, F, A, B)
+#define REGISTER_AZ(name) REGISTER(name, F, A, Z)
+#define REGISTER_BB(name) REGISTER(name, F, B, B)
+#define REGISTER_BZ(name) REGISTER(name, F, B, Z)
+#define REGISTER_CZ(name) REGISTER(name, F, C, Z)
+
+static const struct ef4_nic_reg ef4_nic_regs[] = {
+ REGISTER_AZ(ADR_REGION),
+ REGISTER_AZ(INT_EN_KER),
+ REGISTER_BZ(INT_EN_CHAR),
+ REGISTER_AZ(INT_ADR_KER),
+ REGISTER_BZ(INT_ADR_CHAR),
+ /* INT_ACK_KER is WO */
+ /* INT_ISR0 is RC */
+ REGISTER_AZ(HW_INIT),
+ REGISTER_CZ(USR_EV_CFG),
+ REGISTER_AB(EE_SPI_HCMD),
+ REGISTER_AB(EE_SPI_HADR),
+ REGISTER_AB(EE_SPI_HDATA),
+ REGISTER_AB(EE_BASE_PAGE),
+ REGISTER_AB(EE_VPD_CFG0),
+ /* EE_VPD_SW_CNTL and EE_VPD_SW_DATA are not used */
+ /* PMBX_DBG_IADDR and PBMX_DBG_IDATA are indirect */
+ /* PCIE_CORE_INDIRECT is indirect */
+ REGISTER_AB(NIC_STAT),
+ REGISTER_AB(GPIO_CTL),
+ REGISTER_AB(GLB_CTL),
+ /* FATAL_INTR_KER and FATAL_INTR_CHAR are partly RC */
+ REGISTER_BZ(DP_CTRL),
+ REGISTER_AZ(MEM_STAT),
+ REGISTER_AZ(CS_DEBUG),
+ REGISTER_AZ(ALTERA_BUILD),
+ REGISTER_AZ(CSR_SPARE),
+ REGISTER_AB(PCIE_SD_CTL0123),
+ REGISTER_AB(PCIE_SD_CTL45),
+ REGISTER_AB(PCIE_PCS_CTL_STAT),
+ /* DEBUG_DATA_OUT is not used */
+ /* DRV_EV is WO */
+ REGISTER_AZ(EVQ_CTL),
+ REGISTER_AZ(EVQ_CNT1),
+ REGISTER_AZ(EVQ_CNT2),
+ REGISTER_AZ(BUF_TBL_CFG),
+ REGISTER_AZ(SRM_RX_DC_CFG),
+ REGISTER_AZ(SRM_TX_DC_CFG),
+ REGISTER_AZ(SRM_CFG),
+ /* BUF_TBL_UPD is WO */
+ REGISTER_AZ(SRM_UPD_EVQ),
+ REGISTER_AZ(SRAM_PARITY),
+ REGISTER_AZ(RX_CFG),
+ REGISTER_BZ(RX_FILTER_CTL),
+ /* RX_FLUSH_DESCQ is WO */
+ REGISTER_AZ(RX_DC_CFG),
+ REGISTER_AZ(RX_DC_PF_WM),
+ REGISTER_BZ(RX_RSS_TKEY),
+ /* RX_NODESC_DROP is RC */
+ REGISTER_AA(RX_SELF_RST),
+ /* RX_DEBUG, RX_PUSH_DROP are not used */
+ REGISTER_CZ(RX_RSS_IPV6_REG1),
+ REGISTER_CZ(RX_RSS_IPV6_REG2),
+ REGISTER_CZ(RX_RSS_IPV6_REG3),
+ /* TX_FLUSH_DESCQ is WO */
+ REGISTER_AZ(TX_DC_CFG),
+ REGISTER_AA(TX_CHKSM_CFG),
+ REGISTER_AZ(TX_CFG),
+ /* TX_PUSH_DROP is not used */
+ REGISTER_AZ(TX_RESERVED),
+ REGISTER_BZ(TX_PACE),
+ /* TX_PACE_DROP_QID is RC */
+ REGISTER_BB(TX_VLAN),
+ REGISTER_BZ(TX_IPFIL_PORTEN),
+ REGISTER_AB(MD_TXD),
+ REGISTER_AB(MD_RXD),
+ REGISTER_AB(MD_CS),
+ REGISTER_AB(MD_PHY_ADR),
+ REGISTER_AB(MD_ID),
+ /* MD_STAT is RC */
+ REGISTER_AB(MAC_STAT_DMA),
+ REGISTER_AB(MAC_CTRL),
+ REGISTER_BB(GEN_MODE),
+ REGISTER_AB(MAC_MC_HASH_REG0),
+ REGISTER_AB(MAC_MC_HASH_REG1),
+ REGISTER_AB(GM_CFG1),
+ REGISTER_AB(GM_CFG2),
+ /* GM_IPG and GM_HD are not used */
+ REGISTER_AB(GM_MAX_FLEN),
+ /* GM_TEST is not used */
+ REGISTER_AB(GM_ADR1),
+ REGISTER_AB(GM_ADR2),
+ REGISTER_AB(GMF_CFG0),
+ REGISTER_AB(GMF_CFG1),
+ REGISTER_AB(GMF_CFG2),
+ REGISTER_AB(GMF_CFG3),
+ REGISTER_AB(GMF_CFG4),
+ REGISTER_AB(GMF_CFG5),
+ REGISTER_BB(TX_SRC_MAC_CTL),
+ REGISTER_AB(XM_ADR_LO),
+ REGISTER_AB(XM_ADR_HI),
+ REGISTER_AB(XM_GLB_CFG),
+ REGISTER_AB(XM_TX_CFG),
+ REGISTER_AB(XM_RX_CFG),
+ REGISTER_AB(XM_MGT_INT_MASK),
+ REGISTER_AB(XM_FC),
+ REGISTER_AB(XM_PAUSE_TIME),
+ REGISTER_AB(XM_TX_PARAM),
+ REGISTER_AB(XM_RX_PARAM),
+ /* XM_MGT_INT_MSK (note no 'A') is RC */
+ REGISTER_AB(XX_PWR_RST),
+ REGISTER_AB(XX_SD_CTL),
+ REGISTER_AB(XX_TXDRV_CTL),
+ /* XX_PRBS_CTL, XX_PRBS_CHK and XX_PRBS_ERR are not used */
+ /* XX_CORE_STAT is partly RC */
+};
+
+struct ef4_nic_reg_table {
+ u32 offset:24;
+ u32 min_revision:3, max_revision:3;
+ u32 step:6, rows:21;
+};
+
+#define REGISTER_TABLE_DIMENSIONS(_, offset, arch, min_rev, max_rev, step, rows) { \
+ offset, \
+ REGISTER_REVISION_ ## arch ## min_rev, \
+ REGISTER_REVISION_ ## arch ## max_rev, \
+ step, rows \
+}
+#define REGISTER_TABLE(name, arch, min_rev, max_rev) \
+ REGISTER_TABLE_DIMENSIONS( \
+ name, arch ## R_ ## min_rev ## max_rev ## _ ## name, \
+ arch, min_rev, max_rev, \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _STEP, \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _ROWS)
+#define REGISTER_TABLE_AA(name) REGISTER_TABLE(name, F, A, A)
+#define REGISTER_TABLE_AZ(name) REGISTER_TABLE(name, F, A, Z)
+#define REGISTER_TABLE_BB(name) REGISTER_TABLE(name, F, B, B)
+#define REGISTER_TABLE_BZ(name) REGISTER_TABLE(name, F, B, Z)
+#define REGISTER_TABLE_BB_CZ(name) \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, B, B, \
+ FR_BZ_ ## name ## _STEP, \
+ FR_BB_ ## name ## _ROWS), \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, C, Z, \
+ FR_BZ_ ## name ## _STEP, \
+ FR_CZ_ ## name ## _ROWS)
+#define REGISTER_TABLE_CZ(name) REGISTER_TABLE(name, F, C, Z)
+
+static const struct ef4_nic_reg_table ef4_nic_reg_tables[] = {
+ /* DRIVER is not used */
+ /* EVQ_RPTR, TIMER_COMMAND, USR_EV and {RX,TX}_DESC_UPD are WO */
+ REGISTER_TABLE_BB(TX_IPFIL_TBL),
+ REGISTER_TABLE_BB(TX_SRC_MAC_TBL),
+ REGISTER_TABLE_AA(RX_DESC_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(RX_DESC_PTR_TBL),
+ REGISTER_TABLE_AA(TX_DESC_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL),
+ REGISTER_TABLE_AA(EVQ_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL),
+ /* We can't reasonably read all of the buffer table (up to 8MB!).
+ * However this driver will only use a few entries. Reading
+ * 1K entries allows for some expansion of queue count and
+ * size before we need to change the version. */
+ REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL_KER, FR_AA_BUF_FULL_TBL_KER,
+ F, A, A, 8, 1024),
+ REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL,
+ F, B, Z, 8, 1024),
+ REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0),
+ REGISTER_TABLE_BB_CZ(TIMER_TBL),
+ REGISTER_TABLE_BB_CZ(TX_PACE_TBL),
+ REGISTER_TABLE_BZ(RX_INDIRECTION_TBL),
+ /* TX_FILTER_TBL0 is huge and not used by this driver */
+ REGISTER_TABLE_CZ(TX_MAC_FILTER_TBL0),
+ REGISTER_TABLE_CZ(MC_TREG_SMEM),
+ /* MSIX_PBA_TABLE is not mapped */
+ /* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */
+ REGISTER_TABLE_BZ(RX_FILTER_TBL0),
+};
+
+size_t ef4_nic_get_regs_len(struct ef4_nic *efx)
+{
+ const struct ef4_nic_reg *reg;
+ const struct ef4_nic_reg_table *table;
+ size_t len = 0;
+
+ for (reg = ef4_nic_regs;
+ reg < ef4_nic_regs + ARRAY_SIZE(ef4_nic_regs);
+ reg++)
+ if (efx->type->revision >= reg->min_revision &&
+ efx->type->revision <= reg->max_revision)
+ len += sizeof(ef4_oword_t);
+
+ for (table = ef4_nic_reg_tables;
+ table < ef4_nic_reg_tables + ARRAY_SIZE(ef4_nic_reg_tables);
+ table++)
+ if (efx->type->revision >= table->min_revision &&
+ efx->type->revision <= table->max_revision)
+ len += table->rows * min_t(size_t, table->step, 16);
+
+ return len;
+}
+
+void ef4_nic_get_regs(struct ef4_nic *efx, void *buf)
+{
+ const struct ef4_nic_reg *reg;
+ const struct ef4_nic_reg_table *table;
+
+ for (reg = ef4_nic_regs;
+ reg < ef4_nic_regs + ARRAY_SIZE(ef4_nic_regs);
+ reg++) {
+ if (efx->type->revision >= reg->min_revision &&
+ efx->type->revision <= reg->max_revision) {
+ ef4_reado(efx, (ef4_oword_t *)buf, reg->offset);
+ buf += sizeof(ef4_oword_t);
+ }
+ }
+
+ for (table = ef4_nic_reg_tables;
+ table < ef4_nic_reg_tables + ARRAY_SIZE(ef4_nic_reg_tables);
+ table++) {
+ size_t size, i;
+
+ if (!(efx->type->revision >= table->min_revision &&
+ efx->type->revision <= table->max_revision))
+ continue;
+
+ size = min_t(size_t, table->step, 16);
+
+ for (i = 0; i < table->rows; i++) {
+ switch (table->step) {
+ case 4: /* 32-bit SRAM */
+ ef4_readd(efx, buf, table->offset + 4 * i);
+ break;
+ case 8: /* 64-bit SRAM */
+ ef4_sram_readq(efx,
+ efx->membase + table->offset,
+ buf, i);
+ break;
+ case 16: /* 128-bit-readable register */
+ ef4_reado_table(efx, buf, table->offset, i);
+ break;
+ case 32: /* 128-bit register, interleaved */
+ ef4_reado_table(efx, buf, table->offset, 2 * i);
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+ buf += size;
+ }
+ }
+}
+
+/**
+ * ef4_nic_describe_stats - Describe supported statistics for ethtool
+ * @desc: Array of &struct ef4_hw_stat_desc describing the statistics
+ * @count: Length of the @desc array
+ * @mask: Bitmask of which elements of @desc are enabled
+ * @names: Buffer to copy names to, or %NULL. The names are copied
+ * starting at intervals of %ETH_GSTRING_LEN bytes.
+ *
+ * Returns the number of visible statistics, i.e. the number of set
+ * bits in the first @count bits of @mask for which a name is defined.
+ */
+size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask, u8 *names)
+{
+ size_t visible = 0;
+ size_t index;
+
+ for_each_set_bit(index, mask, count) {
+ if (desc[index].name) {
+ if (names) {
+ strlcpy(names, desc[index].name,
+ ETH_GSTRING_LEN);
+ names += ETH_GSTRING_LEN;
+ }
+ ++visible;
+ }
+ }
+
+ return visible;
+}
+
+/**
+ * ef4_nic_update_stats - Convert statistics DMA buffer to array of u64
+ * @desc: Array of &struct ef4_hw_stat_desc describing the DMA buffer
+ * layout. DMA widths of 0, 16, 32 and 64 are supported; where
+ * the width is specified as 0 the corresponding element of
+ * @stats is not updated.
+ * @count: Length of the @desc array
+ * @mask: Bitmask of which elements of @desc are enabled
+ * @stats: Buffer to update with the converted statistics. The length
+ * of this array must be at least @count.
+ * @dma_buf: DMA buffer containing hardware statistics
+ * @accumulate: If set, the converted values will be added rather than
+ * directly stored to the corresponding elements of @stats
+ */
+void ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask,
+ u64 *stats, const void *dma_buf, bool accumulate)
+{
+ size_t index;
+
+ for_each_set_bit(index, mask, count) {
+ if (desc[index].dma_width) {
+ const void *addr = dma_buf + desc[index].offset;
+ u64 val;
+
+ switch (desc[index].dma_width) {
+ case 16:
+ val = le16_to_cpup((__le16 *)addr);
+ break;
+ case 32:
+ val = le32_to_cpup((__le32 *)addr);
+ break;
+ case 64:
+ val = le64_to_cpup((__le64 *)addr);
+ break;
+ default:
+ WARN_ON(1);
+ val = 0;
+ break;
+ }
+
+ if (accumulate)
+ stats[index] += val;
+ else
+ stats[index] = val;
+ }
+ }
+}
+
+void ef4_nic_fix_nodesc_drop_stat(struct ef4_nic *efx, u64 *rx_nodesc_drops)
+{
+ /* if down, or this is the first update after coming up */
+ if (!(efx->net_dev->flags & IFF_UP) || !efx->rx_nodesc_drops_prev_state)
+ efx->rx_nodesc_drops_while_down +=
+ *rx_nodesc_drops - efx->rx_nodesc_drops_total;
+ efx->rx_nodesc_drops_total = *rx_nodesc_drops;
+ efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP);
+ *rx_nodesc_drops -= efx->rx_nodesc_drops_while_down;
+}
diff --git a/drivers/net/ethernet/sfc/falcon/nic.h b/drivers/net/ethernet/sfc/falcon/nic.h
new file mode 100644
index 000000000000..a4c4592f6023
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/nic.h
@@ -0,0 +1,513 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_NIC_H
+#define EF4_NIC_H
+
+#include <linux/net_tstamp.h>
+#include <linux/i2c-algo-bit.h>
+#include "net_driver.h"
+#include "efx.h"
+
+enum {
+ EF4_REV_FALCON_A0 = 0,
+ EF4_REV_FALCON_A1 = 1,
+ EF4_REV_FALCON_B0 = 2,
+};
+
+static inline int ef4_nic_rev(struct ef4_nic *efx)
+{
+ return efx->type->revision;
+}
+
+u32 ef4_farch_fpga_ver(struct ef4_nic *efx);
+
+/* NIC has two interlinked PCI functions for the same port. */
+static inline bool ef4_nic_is_dual_func(struct ef4_nic *efx)
+{
+ return ef4_nic_rev(efx) < EF4_REV_FALCON_B0;
+}
+
+/* Read the current event from the event queue */
+static inline ef4_qword_t *ef4_event(struct ef4_channel *channel,
+ unsigned int index)
+{
+ return ((ef4_qword_t *) (channel->eventq.buf.addr)) +
+ (index & channel->eventq_mask);
+}
+
+/* See if an event is present
+ *
+ * We check both the high and low dword of the event for all ones. We
+ * wrote all ones when we cleared the event, and no valid event can
+ * have all ones in either its high or low dwords. This approach is
+ * robust against reordering.
+ *
+ * Note that using a single 64-bit comparison is incorrect; even
+ * though the CPU read will be atomic, the DMA write may not be.
+ */
+static inline int ef4_event_present(ef4_qword_t *event)
+{
+ return !(EF4_DWORD_IS_ALL_ONES(event->dword[0]) |
+ EF4_DWORD_IS_ALL_ONES(event->dword[1]));
+}
+
+/* Returns a pointer to the specified transmit descriptor in the TX
+ * descriptor queue belonging to the specified channel.
+ */
+static inline ef4_qword_t *
+ef4_tx_desc(struct ef4_tx_queue *tx_queue, unsigned int index)
+{
+ return ((ef4_qword_t *) (tx_queue->txd.buf.addr)) + index;
+}
+
+/* Get partner of a TX queue, seen as part of the same net core queue */
+static inline struct ef4_tx_queue *ef4_tx_queue_partner(struct ef4_tx_queue *tx_queue)
+{
+ if (tx_queue->queue & EF4_TXQ_TYPE_OFFLOAD)
+ return tx_queue - EF4_TXQ_TYPE_OFFLOAD;
+ else
+ return tx_queue + EF4_TXQ_TYPE_OFFLOAD;
+}
+
+/* Report whether this TX queue would be empty for the given write_count.
+ * May return false negative.
+ */
+static inline bool __ef4_nic_tx_is_empty(struct ef4_tx_queue *tx_queue,
+ unsigned int write_count)
+{
+ unsigned int empty_read_count = ACCESS_ONCE(tx_queue->empty_read_count);
+
+ if (empty_read_count == 0)
+ return false;
+
+ return ((empty_read_count ^ write_count) & ~EF4_EMPTY_COUNT_VALID) == 0;
+}
+
+/* Decide whether to push a TX descriptor to the NIC vs merely writing
+ * the doorbell. This can reduce latency when we are adding a single
+ * descriptor to an empty queue, but is otherwise pointless. Further,
+ * Falcon and Siena have hardware bugs (SF bug 33851) that may be
+ * triggered if we don't check this.
+ * We use the write_count used for the last doorbell push, to get the
+ * NIC's view of the tx queue.
+ */
+static inline bool ef4_nic_may_push_tx_desc(struct ef4_tx_queue *tx_queue,
+ unsigned int write_count)
+{
+ bool was_empty = __ef4_nic_tx_is_empty(tx_queue, write_count);
+
+ tx_queue->empty_read_count = 0;
+ return was_empty && tx_queue->write_count - write_count == 1;
+}
+
+/* Returns a pointer to the specified descriptor in the RX descriptor queue */
+static inline ef4_qword_t *
+ef4_rx_desc(struct ef4_rx_queue *rx_queue, unsigned int index)
+{
+ return ((ef4_qword_t *) (rx_queue->rxd.buf.addr)) + index;
+}
+
+enum {
+ PHY_TYPE_NONE = 0,
+ PHY_TYPE_TXC43128 = 1,
+ PHY_TYPE_88E1111 = 2,
+ PHY_TYPE_SFX7101 = 3,
+ PHY_TYPE_QT2022C2 = 4,
+ PHY_TYPE_PM8358 = 6,
+ PHY_TYPE_SFT9001A = 8,
+ PHY_TYPE_QT2025C = 9,
+ PHY_TYPE_SFT9001B = 10,
+};
+
+#define FALCON_XMAC_LOOPBACKS \
+ ((1 << LOOPBACK_XGMII) | \
+ (1 << LOOPBACK_XGXS) | \
+ (1 << LOOPBACK_XAUI))
+
+/* Alignment of PCIe DMA boundaries (4KB) */
+#define EF4_PAGE_SIZE 4096
+/* Size and alignment of buffer table entries (same) */
+#define EF4_BUF_SIZE EF4_PAGE_SIZE
+
+/* NIC-generic software stats */
+enum {
+ GENERIC_STAT_rx_noskb_drops,
+ GENERIC_STAT_rx_nodesc_trunc,
+ GENERIC_STAT_COUNT
+};
+
+/**
+ * struct falcon_board_type - board operations and type information
+ * @id: Board type id, as found in NVRAM
+ * @init: Allocate resources and initialise peripheral hardware
+ * @init_phy: Do board-specific PHY initialisation
+ * @fini: Shut down hardware and free resources
+ * @set_id_led: Set state of identifying LED or revert to automatic function
+ * @monitor: Board-specific health check function
+ */
+struct falcon_board_type {
+ u8 id;
+ int (*init) (struct ef4_nic *nic);
+ void (*init_phy) (struct ef4_nic *efx);
+ void (*fini) (struct ef4_nic *nic);
+ void (*set_id_led) (struct ef4_nic *efx, enum ef4_led_mode mode);
+ int (*monitor) (struct ef4_nic *nic);
+};
+
+/**
+ * struct falcon_board - board information
+ * @type: Type of board
+ * @major: Major rev. ('A', 'B' ...)
+ * @minor: Minor rev. (0, 1, ...)
+ * @i2c_adap: I2C adapter for on-board peripherals
+ * @i2c_data: Data for bit-banging algorithm
+ * @hwmon_client: I2C client for hardware monitor
+ * @ioexp_client: I2C client for power/port control
+ */
+struct falcon_board {
+ const struct falcon_board_type *type;
+ int major;
+ int minor;
+ struct i2c_adapter i2c_adap;
+ struct i2c_algo_bit_data i2c_data;
+ struct i2c_client *hwmon_client, *ioexp_client;
+};
+
+/**
+ * struct falcon_spi_device - a Falcon SPI (Serial Peripheral Interface) device
+ * @device_id: Controller's id for the device
+ * @size: Size (in bytes)
+ * @addr_len: Number of address bytes in read/write commands
+ * @munge_address: Flag whether addresses should be munged.
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
+ * use bit 3 of the command byte as address bit A8, rather
+ * than having a two-byte address. If this flag is set, then
+ * commands should be munged in this way.
+ * @erase_command: Erase command (or 0 if sector erase not needed).
+ * @erase_size: Erase sector size (in bytes)
+ * Erase commands affect sectors with this size and alignment.
+ * This must be a power of two.
+ * @block_size: Write block size (in bytes).
+ * Write commands are limited to blocks with this size and alignment.
+ */
+struct falcon_spi_device {
+ int device_id;
+ unsigned int size;
+ unsigned int addr_len;
+ unsigned int munge_address:1;
+ u8 erase_command;
+ unsigned int erase_size;
+ unsigned int block_size;
+};
+
+static inline bool falcon_spi_present(const struct falcon_spi_device *spi)
+{
+ return spi->size != 0;
+}
+
+enum {
+ FALCON_STAT_tx_bytes = GENERIC_STAT_COUNT,
+ FALCON_STAT_tx_packets,
+ FALCON_STAT_tx_pause,
+ FALCON_STAT_tx_control,
+ FALCON_STAT_tx_unicast,
+ FALCON_STAT_tx_multicast,
+ FALCON_STAT_tx_broadcast,
+ FALCON_STAT_tx_lt64,
+ FALCON_STAT_tx_64,
+ FALCON_STAT_tx_65_to_127,
+ FALCON_STAT_tx_128_to_255,
+ FALCON_STAT_tx_256_to_511,
+ FALCON_STAT_tx_512_to_1023,
+ FALCON_STAT_tx_1024_to_15xx,
+ FALCON_STAT_tx_15xx_to_jumbo,
+ FALCON_STAT_tx_gtjumbo,
+ FALCON_STAT_tx_non_tcpudp,
+ FALCON_STAT_tx_mac_src_error,
+ FALCON_STAT_tx_ip_src_error,
+ FALCON_STAT_rx_bytes,
+ FALCON_STAT_rx_good_bytes,
+ FALCON_STAT_rx_bad_bytes,
+ FALCON_STAT_rx_packets,
+ FALCON_STAT_rx_good,
+ FALCON_STAT_rx_bad,
+ FALCON_STAT_rx_pause,
+ FALCON_STAT_rx_control,
+ FALCON_STAT_rx_unicast,
+ FALCON_STAT_rx_multicast,
+ FALCON_STAT_rx_broadcast,
+ FALCON_STAT_rx_lt64,
+ FALCON_STAT_rx_64,
+ FALCON_STAT_rx_65_to_127,
+ FALCON_STAT_rx_128_to_255,
+ FALCON_STAT_rx_256_to_511,
+ FALCON_STAT_rx_512_to_1023,
+ FALCON_STAT_rx_1024_to_15xx,
+ FALCON_STAT_rx_15xx_to_jumbo,
+ FALCON_STAT_rx_gtjumbo,
+ FALCON_STAT_rx_bad_lt64,
+ FALCON_STAT_rx_bad_gtjumbo,
+ FALCON_STAT_rx_overflow,
+ FALCON_STAT_rx_symbol_error,
+ FALCON_STAT_rx_align_error,
+ FALCON_STAT_rx_length_error,
+ FALCON_STAT_rx_internal_error,
+ FALCON_STAT_rx_nodesc_drop_cnt,
+ FALCON_STAT_COUNT
+};
+
+/**
+ * struct falcon_nic_data - Falcon NIC state
+ * @pci_dev2: Secondary function of Falcon A
+ * @board: Board state and functions
+ * @stats: Hardware statistics
+ * @stats_disable_count: Nest count for disabling statistics fetches
+ * @stats_pending: Is there a pending DMA of MAC statistics.
+ * @stats_timer: A timer for regularly fetching MAC statistics.
+ * @spi_flash: SPI flash device
+ * @spi_eeprom: SPI EEPROM device
+ * @spi_lock: SPI bus lock
+ * @mdio_lock: MDIO bus lock
+ * @xmac_poll_required: XMAC link state needs polling
+ */
+struct falcon_nic_data {
+ struct pci_dev *pci_dev2;
+ struct falcon_board board;
+ u64 stats[FALCON_STAT_COUNT];
+ unsigned int stats_disable_count;
+ bool stats_pending;
+ struct timer_list stats_timer;
+ struct falcon_spi_device spi_flash;
+ struct falcon_spi_device spi_eeprom;
+ struct mutex spi_lock;
+ struct mutex mdio_lock;
+ bool xmac_poll_required;
+};
+
+static inline struct falcon_board *falcon_board(struct ef4_nic *efx)
+{
+ struct falcon_nic_data *data = efx->nic_data;
+ return &data->board;
+}
+
+struct ethtool_ts_info;
+
+extern const struct ef4_nic_type falcon_a1_nic_type;
+extern const struct ef4_nic_type falcon_b0_nic_type;
+
+/**************************************************************************
+ *
+ * Externs
+ *
+ **************************************************************************
+ */
+
+int falcon_probe_board(struct ef4_nic *efx, u16 revision_info);
+
+/* TX data path */
+static inline int ef4_nic_probe_tx(struct ef4_tx_queue *tx_queue)
+{
+ return tx_queue->efx->type->tx_probe(tx_queue);
+}
+static inline void ef4_nic_init_tx(struct ef4_tx_queue *tx_queue)
+{
+ tx_queue->efx->type->tx_init(tx_queue);
+}
+static inline void ef4_nic_remove_tx(struct ef4_tx_queue *tx_queue)
+{
+ tx_queue->efx->type->tx_remove(tx_queue);
+}
+static inline void ef4_nic_push_buffers(struct ef4_tx_queue *tx_queue)
+{
+ tx_queue->efx->type->tx_write(tx_queue);
+}
+
+/* RX data path */
+static inline int ef4_nic_probe_rx(struct ef4_rx_queue *rx_queue)
+{
+ return rx_queue->efx->type->rx_probe(rx_queue);
+}
+static inline void ef4_nic_init_rx(struct ef4_rx_queue *rx_queue)
+{
+ rx_queue->efx->type->rx_init(rx_queue);
+}
+static inline void ef4_nic_remove_rx(struct ef4_rx_queue *rx_queue)
+{
+ rx_queue->efx->type->rx_remove(rx_queue);
+}
+static inline void ef4_nic_notify_rx_desc(struct ef4_rx_queue *rx_queue)
+{
+ rx_queue->efx->type->rx_write(rx_queue);
+}
+static inline void ef4_nic_generate_fill_event(struct ef4_rx_queue *rx_queue)
+{
+ rx_queue->efx->type->rx_defer_refill(rx_queue);
+}
+
+/* Event data path */
+static inline int ef4_nic_probe_eventq(struct ef4_channel *channel)
+{
+ return channel->efx->type->ev_probe(channel);
+}
+static inline int ef4_nic_init_eventq(struct ef4_channel *channel)
+{
+ return channel->efx->type->ev_init(channel);
+}
+static inline void ef4_nic_fini_eventq(struct ef4_channel *channel)
+{
+ channel->efx->type->ev_fini(channel);
+}
+static inline void ef4_nic_remove_eventq(struct ef4_channel *channel)
+{
+ channel->efx->type->ev_remove(channel);
+}
+static inline int
+ef4_nic_process_eventq(struct ef4_channel *channel, int quota)
+{
+ return channel->efx->type->ev_process(channel, quota);
+}
+static inline void ef4_nic_eventq_read_ack(struct ef4_channel *channel)
+{
+ channel->efx->type->ev_read_ack(channel);
+}
+void ef4_nic_event_test_start(struct ef4_channel *channel);
+
+/* queue operations */
+int ef4_farch_tx_probe(struct ef4_tx_queue *tx_queue);
+void ef4_farch_tx_init(struct ef4_tx_queue *tx_queue);
+void ef4_farch_tx_fini(struct ef4_tx_queue *tx_queue);
+void ef4_farch_tx_remove(struct ef4_tx_queue *tx_queue);
+void ef4_farch_tx_write(struct ef4_tx_queue *tx_queue);
+unsigned int ef4_farch_tx_limit_len(struct ef4_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
+int ef4_farch_rx_probe(struct ef4_rx_queue *rx_queue);
+void ef4_farch_rx_init(struct ef4_rx_queue *rx_queue);
+void ef4_farch_rx_fini(struct ef4_rx_queue *rx_queue);
+void ef4_farch_rx_remove(struct ef4_rx_queue *rx_queue);
+void ef4_farch_rx_write(struct ef4_rx_queue *rx_queue);
+void ef4_farch_rx_defer_refill(struct ef4_rx_queue *rx_queue);
+int ef4_farch_ev_probe(struct ef4_channel *channel);
+int ef4_farch_ev_init(struct ef4_channel *channel);
+void ef4_farch_ev_fini(struct ef4_channel *channel);
+void ef4_farch_ev_remove(struct ef4_channel *channel);
+int ef4_farch_ev_process(struct ef4_channel *channel, int quota);
+void ef4_farch_ev_read_ack(struct ef4_channel *channel);
+void ef4_farch_ev_test_generate(struct ef4_channel *channel);
+
+/* filter operations */
+int ef4_farch_filter_table_probe(struct ef4_nic *efx);
+void ef4_farch_filter_table_restore(struct ef4_nic *efx);
+void ef4_farch_filter_table_remove(struct ef4_nic *efx);
+void ef4_farch_filter_update_rx_scatter(struct ef4_nic *efx);
+s32 ef4_farch_filter_insert(struct ef4_nic *efx, struct ef4_filter_spec *spec,
+ bool replace);
+int ef4_farch_filter_remove_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority,
+ u32 filter_id);
+int ef4_farch_filter_get_safe(struct ef4_nic *efx,
+ enum ef4_filter_priority priority, u32 filter_id,
+ struct ef4_filter_spec *);
+int ef4_farch_filter_clear_rx(struct ef4_nic *efx,
+ enum ef4_filter_priority priority);
+u32 ef4_farch_filter_count_rx_used(struct ef4_nic *efx,
+ enum ef4_filter_priority priority);
+u32 ef4_farch_filter_get_rx_id_limit(struct ef4_nic *efx);
+s32 ef4_farch_filter_get_rx_ids(struct ef4_nic *efx,
+ enum ef4_filter_priority priority, u32 *buf,
+ u32 size);
+#ifdef CONFIG_RFS_ACCEL
+s32 ef4_farch_filter_rfs_insert(struct ef4_nic *efx,
+ struct ef4_filter_spec *spec);
+bool ef4_farch_filter_rfs_expire_one(struct ef4_nic *efx, u32 flow_id,
+ unsigned int index);
+#endif
+void ef4_farch_filter_sync_rx_mode(struct ef4_nic *efx);
+
+bool ef4_nic_event_present(struct ef4_channel *channel);
+
+/* Some statistics are computed as A - B where A and B each increase
+ * linearly with some hardware counter(s) and the counters are read
+ * asynchronously. If the counters contributing to B are always read
+ * after those contributing to A, the computed value may be lower than
+ * the true value by some variable amount, and may decrease between
+ * subsequent computations.
+ *
+ * We should never allow statistics to decrease or to exceed the true
+ * value. Since the computed value will never be greater than the
+ * true value, we can achieve this by only storing the computed value
+ * when it increases.
+ */
+static inline void ef4_update_diff_stat(u64 *stat, u64 diff)
+{
+ if ((s64)(diff - *stat) > 0)
+ *stat = diff;
+}
+
+/* Interrupts */
+int ef4_nic_init_interrupt(struct ef4_nic *efx);
+int ef4_nic_irq_test_start(struct ef4_nic *efx);
+void ef4_nic_fini_interrupt(struct ef4_nic *efx);
+void ef4_farch_irq_enable_master(struct ef4_nic *efx);
+int ef4_farch_irq_test_generate(struct ef4_nic *efx);
+void ef4_farch_irq_disable_master(struct ef4_nic *efx);
+irqreturn_t ef4_farch_msi_interrupt(int irq, void *dev_id);
+irqreturn_t ef4_farch_legacy_interrupt(int irq, void *dev_id);
+irqreturn_t ef4_farch_fatal_interrupt(struct ef4_nic *efx);
+
+static inline int ef4_nic_event_test_irq_cpu(struct ef4_channel *channel)
+{
+ return ACCESS_ONCE(channel->event_test_cpu);
+}
+static inline int ef4_nic_irq_test_irq_cpu(struct ef4_nic *efx)
+{
+ return ACCESS_ONCE(efx->last_irq_cpu);
+}
+
+/* Global Resources */
+int ef4_nic_flush_queues(struct ef4_nic *efx);
+int ef4_farch_fini_dmaq(struct ef4_nic *efx);
+void ef4_farch_finish_flr(struct ef4_nic *efx);
+void falcon_start_nic_stats(struct ef4_nic *efx);
+void falcon_stop_nic_stats(struct ef4_nic *efx);
+int falcon_reset_xaui(struct ef4_nic *efx);
+void ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw);
+void ef4_farch_init_common(struct ef4_nic *efx);
+void ef4_farch_rx_push_indir_table(struct ef4_nic *efx);
+
+int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer,
+ unsigned int len, gfp_t gfp_flags);
+void ef4_nic_free_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer);
+
+/* Tests */
+struct ef4_farch_register_test {
+ unsigned address;
+ ef4_oword_t mask;
+};
+int ef4_farch_test_registers(struct ef4_nic *efx,
+ const struct ef4_farch_register_test *regs,
+ size_t n_regs);
+
+size_t ef4_nic_get_regs_len(struct ef4_nic *efx);
+void ef4_nic_get_regs(struct ef4_nic *efx, void *buf);
+
+size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask, u8 *names);
+void ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask, u64 *stats,
+ const void *dma_buf, bool accumulate);
+void ef4_nic_fix_nodesc_drop_stat(struct ef4_nic *efx, u64 *stat);
+
+#define EF4_MAX_FLUSH_TIME 5000
+
+void ef4_farch_generate_event(struct ef4_nic *efx, unsigned int evq,
+ ef4_qword_t *event);
+
+#endif /* EF4_NIC_H */
diff --git a/drivers/net/ethernet/sfc/phy.h b/drivers/net/ethernet/sfc/falcon/phy.h
index 803bf445c08e..362141cee313 100644
--- a/drivers/net/ethernet/sfc/phy.h
+++ b/drivers/net/ethernet/sfc/falcon/phy.h
@@ -7,20 +7,20 @@
* by the Free Software Foundation, incorporated herein by reference.
*/
-#ifndef EFX_PHY_H
-#define EFX_PHY_H
+#ifndef EF4_PHY_H
+#define EF4_PHY_H
/****************************************************************************
* 10Xpress (SFX7101) PHY
*/
-extern const struct efx_phy_operations falcon_sfx7101_phy_ops;
+extern const struct ef4_phy_operations falcon_sfx7101_phy_ops;
-void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
+void tenxpress_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode);
/****************************************************************************
* AMCC/Quake QT202x PHYs
*/
-extern const struct efx_phy_operations falcon_qt202x_phy_ops;
+extern const struct ef4_phy_operations falcon_qt202x_phy_ops;
/* These PHYs provide various H/W control states for LEDs */
#define QUAKE_LED_LINK_INVAL (0)
@@ -34,17 +34,17 @@ extern const struct efx_phy_operations falcon_qt202x_phy_ops;
#define QUAKE_LED_TXLINK (0)
#define QUAKE_LED_RXLINK (8)
-void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
+void falcon_qt202x_set_led(struct ef4_nic *p, int led, int state);
/****************************************************************************
* Transwitch CX4 retimer
*/
-extern const struct efx_phy_operations falcon_txc_phy_ops;
+extern const struct ef4_phy_operations falcon_txc_phy_ops;
#define TXC_GPIO_DIR_INPUT 0
#define TXC_GPIO_DIR_OUTPUT 1
-void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
-void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
+void falcon_txc_set_gpio_dir(struct ef4_nic *efx, int pin, int dir);
+void falcon_txc_set_gpio_val(struct ef4_nic *efx, int pin, int val);
#endif
diff --git a/drivers/net/ethernet/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/falcon/qt202x_phy.c
index efa3612affca..d29331652548 100644
--- a/drivers/net/ethernet/sfc/qt202x_phy.c
+++ b/drivers/net/ethernet/sfc/falcon/qt202x_phy.c
@@ -50,14 +50,14 @@
#define PCS_VEND1_REG 0xc000
#define PCS_VEND1_LBTXD_LBN 5
-void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode)
+void falcon_qt202x_set_led(struct ef4_nic *p, int led, int mode)
{
int addr = MDIO_QUAKE_LED0_REG + led;
- efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode);
+ ef4_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode);
}
struct qt202x_phy_data {
- enum efx_phy_mode phy_mode;
+ enum ef4_phy_mode phy_mode;
bool bug17190_in_bad_state;
unsigned long bug17190_timer;
u32 firmware_ver;
@@ -73,7 +73,7 @@ struct qt202x_phy_data {
#define BUG17190_INTERVAL (2 * HZ)
-static int qt2025c_wait_heartbeat(struct efx_nic *efx)
+static int qt2025c_wait_heartbeat(struct ef4_nic *efx)
{
unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME;
int reg, old_counter = 0;
@@ -81,7 +81,7 @@ static int qt2025c_wait_heartbeat(struct efx_nic *efx)
/* Wait for firmware heartbeat to start */
for (;;) {
int counter;
- reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG);
+ reg = ef4_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG);
if (reg < 0)
return reg;
counter = ((reg >> PCS_FW_HEARTB_LBN) &
@@ -105,14 +105,14 @@ static int qt2025c_wait_heartbeat(struct efx_nic *efx)
return 0;
}
-static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
+static int qt2025c_wait_fw_status_good(struct ef4_nic *efx)
{
unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME;
int reg;
/* Wait for firmware status to look good */
for (;;) {
- reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
+ reg = ef4_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
if (reg < 0)
return reg;
if ((reg &
@@ -127,15 +127,15 @@ static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
return 0;
}
-static void qt2025c_restart_firmware(struct efx_nic *efx)
+static void qt2025c_restart_firmware(struct ef4_nic *efx)
{
/* Restart microcontroller execution of firmware from RAM */
- efx_mdio_write(efx, 3, 0xe854, 0x00c0);
- efx_mdio_write(efx, 3, 0xe854, 0x0040);
+ ef4_mdio_write(efx, 3, 0xe854, 0x00c0);
+ ef4_mdio_write(efx, 3, 0xe854, 0x0040);
msleep(50);
}
-static int qt2025c_wait_reset(struct efx_nic *efx)
+static int qt2025c_wait_reset(struct ef4_nic *efx)
{
int rc;
@@ -160,14 +160,14 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
return rc;
}
-static void qt2025c_firmware_id(struct efx_nic *efx)
+static void qt2025c_firmware_id(struct ef4_nic *efx)
{
struct qt202x_phy_data *phy_data = efx->phy_data;
u8 firmware_id[9];
size_t i;
for (i = 0; i < sizeof(firmware_id); i++)
- firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS,
+ firmware_id[i] = ef4_mdio_read(efx, MDIO_MMD_PCS,
PCS_FW_PRODUCT_CODE_1 + i);
netif_info(efx, probe, efx->net_dev,
"QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n",
@@ -180,7 +180,7 @@ static void qt2025c_firmware_id(struct efx_nic *efx)
(firmware_id[4] << 8) | firmware_id[5];
}
-static void qt2025c_bug17190_workaround(struct efx_nic *efx)
+static void qt2025c_bug17190_workaround(struct ef4_nic *efx)
{
struct qt202x_phy_data *phy_data = efx->phy_data;
@@ -191,7 +191,7 @@ static void qt2025c_bug17190_workaround(struct efx_nic *efx)
* recover it.
*/
if (efx->link_state.up ||
- !efx_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) {
+ !ef4_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) {
phy_data->bug17190_in_bad_state = false;
return;
}
@@ -204,16 +204,16 @@ static void qt2025c_bug17190_workaround(struct efx_nic *efx)
if (time_after_eq(jiffies, phy_data->bug17190_timer)) {
netif_dbg(efx, hw, efx->net_dev, "bashing QT2025C PMA/PMD\n");
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
MDIO_PMA_CTRL1_LOOPBACK, true);
msleep(100);
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
MDIO_PMA_CTRL1_LOOPBACK, false);
phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL;
}
}
-static int qt2025c_select_phy_mode(struct efx_nic *efx)
+static int qt2025c_select_phy_mode(struct ef4_nic *efx)
{
struct qt202x_phy_data *phy_data = efx->phy_data;
struct falcon_board *board = falcon_board(efx);
@@ -233,7 +233,7 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020;
/* Only change mode if really necessary */
- reg = efx_mdio_read(efx, 1, 0xc319);
+ reg = ef4_mdio_read(efx, 1, 0xc319);
if ((reg & 0x0038) == phy_op_mode)
return 0;
netif_dbg(efx, hw, efx->net_dev, "Switching PHY to mode 0x%04x\n",
@@ -243,52 +243,52 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
* EEPROM (including the differences between board revisions), except
* that the operating mode is changed, and the PHY is prevented from
* unnecessarily reloading the main firmware image again. */
- efx_mdio_write(efx, 1, 0xc300, 0x0000);
+ ef4_mdio_write(efx, 1, 0xc300, 0x0000);
/* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9
* STOPs onto the firmware/module I2C bus to reset it, varies across
* board revisions, as the bus is connected to different GPIO/LED
* outputs on the PHY.) */
if (board->major == 0 && board->minor < 2) {
- efx_mdio_write(efx, 1, 0xc303, 0x4498);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4498);
for (i = 0; i < 9; i++) {
- efx_mdio_write(efx, 1, 0xc303, 0x4488);
- efx_mdio_write(efx, 1, 0xc303, 0x4480);
- efx_mdio_write(efx, 1, 0xc303, 0x4490);
- efx_mdio_write(efx, 1, 0xc303, 0x4498);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4488);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4480);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4490);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4498);
}
} else {
- efx_mdio_write(efx, 1, 0xc303, 0x0920);
- efx_mdio_write(efx, 1, 0xd008, 0x0004);
+ ef4_mdio_write(efx, 1, 0xc303, 0x0920);
+ ef4_mdio_write(efx, 1, 0xd008, 0x0004);
for (i = 0; i < 9; i++) {
- efx_mdio_write(efx, 1, 0xc303, 0x0900);
- efx_mdio_write(efx, 1, 0xd008, 0x0005);
- efx_mdio_write(efx, 1, 0xc303, 0x0920);
- efx_mdio_write(efx, 1, 0xd008, 0x0004);
+ ef4_mdio_write(efx, 1, 0xc303, 0x0900);
+ ef4_mdio_write(efx, 1, 0xd008, 0x0005);
+ ef4_mdio_write(efx, 1, 0xc303, 0x0920);
+ ef4_mdio_write(efx, 1, 0xd008, 0x0004);
}
- efx_mdio_write(efx, 1, 0xc303, 0x4900);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4900);
}
- efx_mdio_write(efx, 1, 0xc303, 0x4900);
- efx_mdio_write(efx, 1, 0xc302, 0x0004);
- efx_mdio_write(efx, 1, 0xc316, 0x0013);
- efx_mdio_write(efx, 1, 0xc318, 0x0054);
- efx_mdio_write(efx, 1, 0xc319, phy_op_mode);
- efx_mdio_write(efx, 1, 0xc31a, 0x0098);
- efx_mdio_write(efx, 3, 0x0026, 0x0e00);
- efx_mdio_write(efx, 3, 0x0027, 0x0013);
- efx_mdio_write(efx, 3, 0x0028, 0xa528);
- efx_mdio_write(efx, 1, 0xd006, 0x000a);
- efx_mdio_write(efx, 1, 0xd007, 0x0009);
- efx_mdio_write(efx, 1, 0xd008, 0x0004);
+ ef4_mdio_write(efx, 1, 0xc303, 0x4900);
+ ef4_mdio_write(efx, 1, 0xc302, 0x0004);
+ ef4_mdio_write(efx, 1, 0xc316, 0x0013);
+ ef4_mdio_write(efx, 1, 0xc318, 0x0054);
+ ef4_mdio_write(efx, 1, 0xc319, phy_op_mode);
+ ef4_mdio_write(efx, 1, 0xc31a, 0x0098);
+ ef4_mdio_write(efx, 3, 0x0026, 0x0e00);
+ ef4_mdio_write(efx, 3, 0x0027, 0x0013);
+ ef4_mdio_write(efx, 3, 0x0028, 0xa528);
+ ef4_mdio_write(efx, 1, 0xd006, 0x000a);
+ ef4_mdio_write(efx, 1, 0xd007, 0x0009);
+ ef4_mdio_write(efx, 1, 0xd008, 0x0004);
/* This additional write is not present in the boot EEPROM. It
* prevents the PHY's internal boot ROM doing another pointless (and
* slow) reload of the firmware image (the microcontroller's code
* memory is not affected by the microcontroller reset). */
- efx_mdio_write(efx, 1, 0xc317, 0x00ff);
+ ef4_mdio_write(efx, 1, 0xc317, 0x00ff);
/* PMA/PMD loopback sets RXIN to inverse polarity and the firmware
* restart doesn't reset it. We need to do that ourselves. */
- efx_mdio_set_flag(efx, 1, PMA_PMD_MODE_REG,
+ ef4_mdio_set_flag(efx, 1, PMA_PMD_MODE_REG,
1 << PMA_PMD_RXIN_SEL_LBN, false);
- efx_mdio_write(efx, 1, 0xc300, 0x0002);
+ ef4_mdio_write(efx, 1, 0xc300, 0x0002);
msleep(20);
/* Restart microcontroller execution of firmware from RAM */
@@ -306,7 +306,7 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
return 0;
}
-static int qt202x_reset_phy(struct efx_nic *efx)
+static int qt202x_reset_phy(struct ef4_nic *efx)
{
int rc;
@@ -319,7 +319,7 @@ static int qt202x_reset_phy(struct efx_nic *efx)
} else {
/* Reset the PHYXS MMD. This is documented as doing
* a complete soft reset. */
- rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
+ rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
QT2022C2_MAX_RESET_TIME /
QT2022C2_RESET_WAIT,
QT2022C2_RESET_WAIT);
@@ -339,7 +339,7 @@ static int qt202x_reset_phy(struct efx_nic *efx)
return rc;
}
-static int qt202x_phy_probe(struct efx_nic *efx)
+static int qt202x_phy_probe(struct ef4_nic *efx)
{
struct qt202x_phy_data *phy_data;
@@ -357,7 +357,7 @@ static int qt202x_phy_probe(struct efx_nic *efx)
return 0;
}
-static int qt202x_phy_init(struct efx_nic *efx)
+static int qt202x_phy_init(struct ef4_nic *efx)
{
u32 devid;
int rc;
@@ -368,11 +368,11 @@ static int qt202x_phy_init(struct efx_nic *efx)
return rc;
}
- devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
+ devid = ef4_mdio_read_id(efx, MDIO_MMD_PHYXS);
netif_info(efx, probe, efx->net_dev,
"PHY ID reg %x (OUI %06x model %02x revision %x)\n",
- devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
- efx_mdio_id_rev(devid));
+ devid, ef4_mdio_id_oui(devid), ef4_mdio_id_model(devid),
+ ef4_mdio_id_rev(devid));
if (efx->phy_type == PHY_TYPE_QT2025C)
qt2025c_firmware_id(efx);
@@ -380,12 +380,12 @@ static int qt202x_phy_init(struct efx_nic *efx)
return 0;
}
-static int qt202x_link_ok(struct efx_nic *efx)
+static int qt202x_link_ok(struct ef4_nic *efx)
{
- return efx_mdio_links_ok(efx, QT202X_REQUIRED_DEVS);
+ return ef4_mdio_links_ok(efx, QT202X_REQUIRED_DEVS);
}
-static bool qt202x_phy_poll(struct efx_nic *efx)
+static bool qt202x_phy_poll(struct ef4_nic *efx)
{
bool was_up = efx->link_state.up;
@@ -400,7 +400,7 @@ static bool qt202x_phy_poll(struct efx_nic *efx)
return efx->link_state.up != was_up;
}
-static int qt202x_phy_reconfigure(struct efx_nic *efx)
+static int qt202x_phy_reconfigure(struct ef4_nic *efx)
{
struct qt202x_phy_data *phy_data = efx->phy_data;
@@ -427,29 +427,29 @@ static int qt202x_phy_reconfigure(struct efx_nic *efx)
(phy_data->phy_mode & PHY_MODE_TX_DISABLED))
qt202x_reset_phy(efx);
- efx_mdio_transmit_disable(efx);
+ ef4_mdio_transmit_disable(efx);
}
- efx_mdio_phy_reconfigure(efx);
+ ef4_mdio_phy_reconfigure(efx);
phy_data->phy_mode = efx->phy_mode;
return 0;
}
-static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static void qt202x_phy_get_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd)
{
mdio45_ethtool_gset(&efx->mdio, ecmd);
}
-static void qt202x_phy_remove(struct efx_nic *efx)
+static void qt202x_phy_remove(struct ef4_nic *efx)
{
/* Free the context block */
kfree(efx->phy_data);
efx->phy_data = NULL;
}
-static int qt202x_phy_get_module_info(struct efx_nic *efx,
+static int qt202x_phy_get_module_info(struct ef4_nic *efx,
struct ethtool_modinfo *modinfo)
{
modinfo->type = ETH_MODULE_SFF_8079;
@@ -457,10 +457,10 @@ static int qt202x_phy_get_module_info(struct efx_nic *efx,
return 0;
}
-static int qt202x_phy_get_module_eeprom(struct efx_nic *efx,
+static int qt202x_phy_get_module_eeprom(struct ef4_nic *efx,
struct ethtool_eeprom *ee, u8 *data)
{
- int mmd, reg_base, rc, i;
+ int mmd, reg_base, rc, i;
if (efx->phy_type == PHY_TYPE_QT2025C) {
mmd = MDIO_MMD_PCS;
@@ -471,7 +471,7 @@ static int qt202x_phy_get_module_eeprom(struct efx_nic *efx,
}
for (i = 0; i < ee->len; i++) {
- rc = efx_mdio_read(efx, mmd, reg_base + ee->offset + i);
+ rc = ef4_mdio_read(efx, mmd, reg_base + ee->offset + i);
if (rc < 0)
return rc;
data[i] = rc;
@@ -480,16 +480,16 @@ static int qt202x_phy_get_module_eeprom(struct efx_nic *efx,
return 0;
}
-const struct efx_phy_operations falcon_qt202x_phy_ops = {
+const struct ef4_phy_operations falcon_qt202x_phy_ops = {
.probe = qt202x_phy_probe,
.init = qt202x_phy_init,
.reconfigure = qt202x_phy_reconfigure,
.poll = qt202x_phy_poll,
- .fini = efx_port_dummy_op_void,
+ .fini = ef4_port_dummy_op_void,
.remove = qt202x_phy_remove,
.get_settings = qt202x_phy_get_settings,
- .set_settings = efx_mdio_set_settings,
- .test_alive = efx_mdio_test_alive,
+ .set_settings = ef4_mdio_set_settings,
+ .test_alive = ef4_mdio_test_alive,
.get_module_eeprom = qt202x_phy_get_module_eeprom,
.get_module_info = qt202x_phy_get_module_info,
};
diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c
new file mode 100644
index 000000000000..250458cbdb4d
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/rx.c
@@ -0,0 +1,974 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2005-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/prefetch.h>
+#include <linux/moduleparam.h>
+#include <linux/iommu.h>
+#include <net/ip.h>
+#include <net/checksum.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "filter.h"
+#include "nic.h"
+#include "selftest.h"
+#include "workarounds.h"
+
+/* Preferred number of descriptors to fill at once */
+#define EF4_RX_PREFERRED_BATCH 8U
+
+/* Number of RX buffers to recycle pages for. When creating the RX page recycle
+ * ring, this number is divided by the number of buffers per page to calculate
+ * the number of pages to store in the RX page recycle ring.
+ */
+#define EF4_RECYCLE_RING_SIZE_IOMMU 4096
+#define EF4_RECYCLE_RING_SIZE_NOIOMMU (2 * EF4_RX_PREFERRED_BATCH)
+
+/* Size of buffer allocated for skb header area. */
+#define EF4_SKB_HEADERS 128u
+
+/* This is the percentage fill level below which new RX descriptors
+ * will be added to the RX descriptor ring.
+ */
+static unsigned int rx_refill_threshold;
+
+/* Each packet can consume up to ceil(max_frame_len / buffer_size) buffers */
+#define EF4_RX_MAX_FRAGS DIV_ROUND_UP(EF4_MAX_FRAME_LEN(EF4_MAX_MTU), \
+ EF4_RX_USR_BUF_SIZE)
+
+/*
+ * RX maximum head room required.
+ *
+ * This must be at least 1 to prevent overflow, plus one packet-worth
+ * to allow pipelined receives.
+ */
+#define EF4_RXD_HEAD_ROOM (1 + EF4_RX_MAX_FRAGS)
+
+static inline u8 *ef4_rx_buf_va(struct ef4_rx_buffer *buf)
+{
+ return page_address(buf->page) + buf->page_offset;
+}
+
+static inline u32 ef4_rx_buf_hash(struct ef4_nic *efx, const u8 *eh)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_hash_offset));
+#else
+ const u8 *data = eh + efx->rx_packet_hash_offset;
+ return (u32)data[0] |
+ (u32)data[1] << 8 |
+ (u32)data[2] << 16 |
+ (u32)data[3] << 24;
+#endif
+}
+
+static inline struct ef4_rx_buffer *
+ef4_rx_buf_next(struct ef4_rx_queue *rx_queue, struct ef4_rx_buffer *rx_buf)
+{
+ if (unlikely(rx_buf == ef4_rx_buffer(rx_queue, rx_queue->ptr_mask)))
+ return ef4_rx_buffer(rx_queue, 0);
+ else
+ return rx_buf + 1;
+}
+
+static inline void ef4_sync_rx_buffer(struct ef4_nic *efx,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int len)
+{
+ dma_sync_single_for_cpu(&efx->pci_dev->dev, rx_buf->dma_addr, len,
+ DMA_FROM_DEVICE);
+}
+
+void ef4_rx_config_page_split(struct ef4_nic *efx)
+{
+ efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align,
+ EF4_RX_BUF_ALIGNMENT);
+ efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
+ ((PAGE_SIZE - sizeof(struct ef4_rx_page_state)) /
+ efx->rx_page_buf_step);
+ efx->rx_buffer_truesize = (PAGE_SIZE << efx->rx_buffer_order) /
+ efx->rx_bufs_per_page;
+ efx->rx_pages_per_batch = DIV_ROUND_UP(EF4_RX_PREFERRED_BATCH,
+ efx->rx_bufs_per_page);
+}
+
+/* Check the RX page recycle ring for a page that can be reused. */
+static struct page *ef4_reuse_page(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ struct page *page;
+ struct ef4_rx_page_state *state;
+ unsigned index;
+
+ index = rx_queue->page_remove & rx_queue->page_ptr_mask;
+ page = rx_queue->page_ring[index];
+ if (page == NULL)
+ return NULL;
+
+ rx_queue->page_ring[index] = NULL;
+ /* page_remove cannot exceed page_add. */
+ if (rx_queue->page_remove != rx_queue->page_add)
+ ++rx_queue->page_remove;
+
+ /* If page_count is 1 then we hold the only reference to this page. */
+ if (page_count(page) == 1) {
+ ++rx_queue->page_recycle_count;
+ return page;
+ } else {
+ state = page_address(page);
+ dma_unmap_page(&efx->pci_dev->dev, state->dma_addr,
+ PAGE_SIZE << efx->rx_buffer_order,
+ DMA_FROM_DEVICE);
+ put_page(page);
+ ++rx_queue->page_recycle_failed;
+ }
+
+ return NULL;
+}
+
+/**
+ * ef4_init_rx_buffers - create EF4_RX_BATCH page-based RX buffers
+ *
+ * @rx_queue: Efx RX queue
+ *
+ * This allocates a batch of pages, maps them for DMA, and populates
+ * struct ef4_rx_buffers for each one. Return a negative error code or
+ * 0 on success. If a single page can be used for multiple buffers,
+ * then the page will either be inserted fully, or not at all.
+ */
+static int ef4_init_rx_buffers(struct ef4_rx_queue *rx_queue, bool atomic)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ struct ef4_rx_buffer *rx_buf;
+ struct page *page;
+ unsigned int page_offset;
+ struct ef4_rx_page_state *state;
+ dma_addr_t dma_addr;
+ unsigned index, count;
+
+ count = 0;
+ do {
+ page = ef4_reuse_page(rx_queue);
+ if (page == NULL) {
+ page = alloc_pages(__GFP_COLD | __GFP_COMP |
+ (atomic ? GFP_ATOMIC : GFP_KERNEL),
+ efx->rx_buffer_order);
+ if (unlikely(page == NULL))
+ return -ENOMEM;
+ dma_addr =
+ dma_map_page(&efx->pci_dev->dev, page, 0,
+ PAGE_SIZE << efx->rx_buffer_order,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(&efx->pci_dev->dev,
+ dma_addr))) {
+ __free_pages(page, efx->rx_buffer_order);
+ return -EIO;
+ }
+ state = page_address(page);
+ state->dma_addr = dma_addr;
+ } else {
+ state = page_address(page);
+ dma_addr = state->dma_addr;
+ }
+
+ dma_addr += sizeof(struct ef4_rx_page_state);
+ page_offset = sizeof(struct ef4_rx_page_state);
+
+ do {
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ rx_buf = ef4_rx_buffer(rx_queue, index);
+ rx_buf->dma_addr = dma_addr + efx->rx_ip_align;
+ rx_buf->page = page;
+ rx_buf->page_offset = page_offset + efx->rx_ip_align;
+ rx_buf->len = efx->rx_dma_len;
+ rx_buf->flags = 0;
+ ++rx_queue->added_count;
+ get_page(page);
+ dma_addr += efx->rx_page_buf_step;
+ page_offset += efx->rx_page_buf_step;
+ } while (page_offset + efx->rx_page_buf_step <= PAGE_SIZE);
+
+ rx_buf->flags = EF4_RX_BUF_LAST_IN_PAGE;
+ } while (++count < efx->rx_pages_per_batch);
+
+ return 0;
+}
+
+/* Unmap a DMA-mapped page. This function is only called for the final RX
+ * buffer in a page.
+ */
+static void ef4_unmap_rx_buffer(struct ef4_nic *efx,
+ struct ef4_rx_buffer *rx_buf)
+{
+ struct page *page = rx_buf->page;
+
+ if (page) {
+ struct ef4_rx_page_state *state = page_address(page);
+ dma_unmap_page(&efx->pci_dev->dev,
+ state->dma_addr,
+ PAGE_SIZE << efx->rx_buffer_order,
+ DMA_FROM_DEVICE);
+ }
+}
+
+static void ef4_free_rx_buffers(struct ef4_rx_queue *rx_queue,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int num_bufs)
+{
+ do {
+ if (rx_buf->page) {
+ put_page(rx_buf->page);
+ rx_buf->page = NULL;
+ }
+ rx_buf = ef4_rx_buf_next(rx_queue, rx_buf);
+ } while (--num_bufs);
+}
+
+/* Attempt to recycle the page if there is an RX recycle ring; the page can
+ * only be added if this is the final RX buffer, to prevent pages being used in
+ * the descriptor ring and appearing in the recycle ring simultaneously.
+ */
+static void ef4_recycle_rx_page(struct ef4_channel *channel,
+ struct ef4_rx_buffer *rx_buf)
+{
+ struct page *page = rx_buf->page;
+ struct ef4_rx_queue *rx_queue = ef4_channel_get_rx_queue(channel);
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned index;
+
+ /* Only recycle the page after processing the final buffer. */
+ if (!(rx_buf->flags & EF4_RX_BUF_LAST_IN_PAGE))
+ return;
+
+ index = rx_queue->page_add & rx_queue->page_ptr_mask;
+ if (rx_queue->page_ring[index] == NULL) {
+ unsigned read_index = rx_queue->page_remove &
+ rx_queue->page_ptr_mask;
+
+ /* The next slot in the recycle ring is available, but
+ * increment page_remove if the read pointer currently
+ * points here.
+ */
+ if (read_index == index)
+ ++rx_queue->page_remove;
+ rx_queue->page_ring[index] = page;
+ ++rx_queue->page_add;
+ return;
+ }
+ ++rx_queue->page_recycle_full;
+ ef4_unmap_rx_buffer(efx, rx_buf);
+ put_page(rx_buf->page);
+}
+
+static void ef4_fini_rx_buffer(struct ef4_rx_queue *rx_queue,
+ struct ef4_rx_buffer *rx_buf)
+{
+ /* Release the page reference we hold for the buffer. */
+ if (rx_buf->page)
+ put_page(rx_buf->page);
+
+ /* If this is the last buffer in a page, unmap and free it. */
+ if (rx_buf->flags & EF4_RX_BUF_LAST_IN_PAGE) {
+ ef4_unmap_rx_buffer(rx_queue->efx, rx_buf);
+ ef4_free_rx_buffers(rx_queue, rx_buf, 1);
+ }
+ rx_buf->page = NULL;
+}
+
+/* Recycle the pages that are used by buffers that have just been received. */
+static void ef4_recycle_rx_pages(struct ef4_channel *channel,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int n_frags)
+{
+ struct ef4_rx_queue *rx_queue = ef4_channel_get_rx_queue(channel);
+
+ do {
+ ef4_recycle_rx_page(channel, rx_buf);
+ rx_buf = ef4_rx_buf_next(rx_queue, rx_buf);
+ } while (--n_frags);
+}
+
+static void ef4_discard_rx_packet(struct ef4_channel *channel,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int n_frags)
+{
+ struct ef4_rx_queue *rx_queue = ef4_channel_get_rx_queue(channel);
+
+ ef4_recycle_rx_pages(channel, rx_buf, n_frags);
+
+ ef4_free_rx_buffers(rx_queue, rx_buf, n_frags);
+}
+
+/**
+ * ef4_fast_push_rx_descriptors - push new RX descriptors quickly
+ * @rx_queue: RX descriptor queue
+ *
+ * This will aim to fill the RX descriptor queue up to
+ * @rx_queue->@max_fill. If there is insufficient atomic
+ * memory to do so, a slow fill will be scheduled.
+ *
+ * The caller must provide serialisation (none is used here). In practise,
+ * this means this function must run from the NAPI handler, or be called
+ * when NAPI is disabled.
+ */
+void ef4_fast_push_rx_descriptors(struct ef4_rx_queue *rx_queue, bool atomic)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned int fill_level, batch_size;
+ int space, rc = 0;
+
+ if (!rx_queue->refill_enabled)
+ return;
+
+ /* Calculate current fill level, and exit if we don't need to fill */
+ fill_level = (rx_queue->added_count - rx_queue->removed_count);
+ EF4_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
+ if (fill_level >= rx_queue->fast_fill_trigger)
+ goto out;
+
+ /* Record minimum fill level */
+ if (unlikely(fill_level < rx_queue->min_fill)) {
+ if (fill_level)
+ rx_queue->min_fill = fill_level;
+ }
+
+ batch_size = efx->rx_pages_per_batch * efx->rx_bufs_per_page;
+ space = rx_queue->max_fill - fill_level;
+ EF4_BUG_ON_PARANOID(space < batch_size);
+
+ netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
+ "RX queue %d fast-filling descriptor ring from"
+ " level %d to level %d\n",
+ ef4_rx_queue_index(rx_queue), fill_level,
+ rx_queue->max_fill);
+
+
+ do {
+ rc = ef4_init_rx_buffers(rx_queue, atomic);
+ if (unlikely(rc)) {
+ /* Ensure that we don't leave the rx queue empty */
+ if (rx_queue->added_count == rx_queue->removed_count)
+ ef4_schedule_slow_fill(rx_queue);
+ goto out;
+ }
+ } while ((space -= batch_size) >= batch_size);
+
+ netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
+ "RX queue %d fast-filled descriptor ring "
+ "to level %d\n", ef4_rx_queue_index(rx_queue),
+ rx_queue->added_count - rx_queue->removed_count);
+
+ out:
+ if (rx_queue->notified_count != rx_queue->added_count)
+ ef4_nic_notify_rx_desc(rx_queue);
+}
+
+void ef4_rx_slow_fill(unsigned long context)
+{
+ struct ef4_rx_queue *rx_queue = (struct ef4_rx_queue *)context;
+
+ /* Post an event to cause NAPI to run and refill the queue */
+ ef4_nic_generate_fill_event(rx_queue);
+ ++rx_queue->slow_fill_count;
+}
+
+static void ef4_rx_packet__check_len(struct ef4_rx_queue *rx_queue,
+ struct ef4_rx_buffer *rx_buf,
+ int len)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
+
+ if (likely(len <= max_len))
+ return;
+
+ /* The packet must be discarded, but this is only a fatal error
+ * if the caller indicated it was
+ */
+ rx_buf->flags |= EF4_RX_PKT_DISCARD;
+
+ if ((len > rx_buf->len) && EF4_WORKAROUND_8071(efx)) {
+ if (net_ratelimit())
+ netif_err(efx, rx_err, efx->net_dev,
+ " RX queue %d seriously overlength "
+ "RX event (0x%x > 0x%x+0x%x). Leaking\n",
+ ef4_rx_queue_index(rx_queue), len, max_len,
+ efx->type->rx_buffer_padding);
+ ef4_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
+ } else {
+ if (net_ratelimit())
+ netif_err(efx, rx_err, efx->net_dev,
+ " RX queue %d overlength RX event "
+ "(0x%x > 0x%x)\n",
+ ef4_rx_queue_index(rx_queue), len, max_len);
+ }
+
+ ef4_rx_queue_channel(rx_queue)->n_rx_overlength++;
+}
+
+/* Pass a received packet up through GRO. GRO can handle pages
+ * regardless of checksum state and skbs with a good checksum.
+ */
+static void
+ef4_rx_packet_gro(struct ef4_channel *channel, struct ef4_rx_buffer *rx_buf,
+ unsigned int n_frags, u8 *eh)
+{
+ struct napi_struct *napi = &channel->napi_str;
+ gro_result_t gro_result;
+ struct ef4_nic *efx = channel->efx;
+ struct sk_buff *skb;
+
+ skb = napi_get_frags(napi);
+ if (unlikely(!skb)) {
+ struct ef4_rx_queue *rx_queue;
+
+ rx_queue = ef4_channel_get_rx_queue(channel);
+ ef4_free_rx_buffers(rx_queue, rx_buf, n_frags);
+ return;
+ }
+
+ if (efx->net_dev->features & NETIF_F_RXHASH)
+ skb_set_hash(skb, ef4_rx_buf_hash(efx, eh),
+ PKT_HASH_TYPE_L3);
+ skb->ip_summed = ((rx_buf->flags & EF4_RX_PKT_CSUMMED) ?
+ CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
+
+ for (;;) {
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+ rx_buf->page, rx_buf->page_offset,
+ rx_buf->len);
+ rx_buf->page = NULL;
+ skb->len += rx_buf->len;
+ if (skb_shinfo(skb)->nr_frags == n_frags)
+ break;
+
+ rx_buf = ef4_rx_buf_next(&channel->rx_queue, rx_buf);
+ }
+
+ skb->data_len = skb->len;
+ skb->truesize += n_frags * efx->rx_buffer_truesize;
+
+ skb_record_rx_queue(skb, channel->rx_queue.core_index);
+
+ gro_result = napi_gro_frags(napi);
+ if (gro_result != GRO_DROP)
+ channel->irq_mod_score += 2;
+}
+
+/* Allocate and construct an SKB around page fragments */
+static struct sk_buff *ef4_rx_mk_skb(struct ef4_channel *channel,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int n_frags,
+ u8 *eh, int hdr_len)
+{
+ struct ef4_nic *efx = channel->efx;
+ struct sk_buff *skb;
+
+ /* Allocate an SKB to store the headers */
+ skb = netdev_alloc_skb(efx->net_dev,
+ efx->rx_ip_align + efx->rx_prefix_size +
+ hdr_len);
+ if (unlikely(skb == NULL)) {
+ atomic_inc(&efx->n_rx_noskb_drops);
+ return NULL;
+ }
+
+ EF4_BUG_ON_PARANOID(rx_buf->len < hdr_len);
+
+ memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size,
+ efx->rx_prefix_size + hdr_len);
+ skb_reserve(skb, efx->rx_ip_align + efx->rx_prefix_size);
+ __skb_put(skb, hdr_len);
+
+ /* Append the remaining page(s) onto the frag list */
+ if (rx_buf->len > hdr_len) {
+ rx_buf->page_offset += hdr_len;
+ rx_buf->len -= hdr_len;
+
+ for (;;) {
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+ rx_buf->page, rx_buf->page_offset,
+ rx_buf->len);
+ rx_buf->page = NULL;
+ skb->len += rx_buf->len;
+ skb->data_len += rx_buf->len;
+ if (skb_shinfo(skb)->nr_frags == n_frags)
+ break;
+
+ rx_buf = ef4_rx_buf_next(&channel->rx_queue, rx_buf);
+ }
+ } else {
+ __free_pages(rx_buf->page, efx->rx_buffer_order);
+ rx_buf->page = NULL;
+ n_frags = 0;
+ }
+
+ skb->truesize += n_frags * efx->rx_buffer_truesize;
+
+ /* Move past the ethernet header */
+ skb->protocol = eth_type_trans(skb, efx->net_dev);
+
+ skb_mark_napi_id(skb, &channel->napi_str);
+
+ return skb;
+}
+
+void ef4_rx_packet(struct ef4_rx_queue *rx_queue, unsigned int index,
+ unsigned int n_frags, unsigned int len, u16 flags)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ struct ef4_channel *channel = ef4_rx_queue_channel(rx_queue);
+ struct ef4_rx_buffer *rx_buf;
+
+ rx_queue->rx_packets++;
+
+ rx_buf = ef4_rx_buffer(rx_queue, index);
+ rx_buf->flags |= flags;
+
+ /* Validate the number of fragments and completed length */
+ if (n_frags == 1) {
+ if (!(flags & EF4_RX_PKT_PREFIX_LEN))
+ ef4_rx_packet__check_len(rx_queue, rx_buf, len);
+ } else if (unlikely(n_frags > EF4_RX_MAX_FRAGS) ||
+ unlikely(len <= (n_frags - 1) * efx->rx_dma_len) ||
+ unlikely(len > n_frags * efx->rx_dma_len) ||
+ unlikely(!efx->rx_scatter)) {
+ /* If this isn't an explicit discard request, either
+ * the hardware or the driver is broken.
+ */
+ WARN_ON(!(len == 0 && rx_buf->flags & EF4_RX_PKT_DISCARD));
+ rx_buf->flags |= EF4_RX_PKT_DISCARD;
+ }
+
+ netif_vdbg(efx, rx_status, efx->net_dev,
+ "RX queue %d received ids %x-%x len %d %s%s\n",
+ ef4_rx_queue_index(rx_queue), index,
+ (index + n_frags - 1) & rx_queue->ptr_mask, len,
+ (rx_buf->flags & EF4_RX_PKT_CSUMMED) ? " [SUMMED]" : "",
+ (rx_buf->flags & EF4_RX_PKT_DISCARD) ? " [DISCARD]" : "");
+
+ /* Discard packet, if instructed to do so. Process the
+ * previous receive first.
+ */
+ if (unlikely(rx_buf->flags & EF4_RX_PKT_DISCARD)) {
+ ef4_rx_flush_packet(channel);
+ ef4_discard_rx_packet(channel, rx_buf, n_frags);
+ return;
+ }
+
+ if (n_frags == 1 && !(flags & EF4_RX_PKT_PREFIX_LEN))
+ rx_buf->len = len;
+
+ /* Release and/or sync the DMA mapping - assumes all RX buffers
+ * consumed in-order per RX queue.
+ */
+ ef4_sync_rx_buffer(efx, rx_buf, rx_buf->len);
+
+ /* Prefetch nice and early so data will (hopefully) be in cache by
+ * the time we look at it.
+ */
+ prefetch(ef4_rx_buf_va(rx_buf));
+
+ rx_buf->page_offset += efx->rx_prefix_size;
+ rx_buf->len -= efx->rx_prefix_size;
+
+ if (n_frags > 1) {
+ /* Release/sync DMA mapping for additional fragments.
+ * Fix length for last fragment.
+ */
+ unsigned int tail_frags = n_frags - 1;
+
+ for (;;) {
+ rx_buf = ef4_rx_buf_next(rx_queue, rx_buf);
+ if (--tail_frags == 0)
+ break;
+ ef4_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);
+ }
+ rx_buf->len = len - (n_frags - 1) * efx->rx_dma_len;
+ ef4_sync_rx_buffer(efx, rx_buf, rx_buf->len);
+ }
+
+ /* All fragments have been DMA-synced, so recycle pages. */
+ rx_buf = ef4_rx_buffer(rx_queue, index);
+ ef4_recycle_rx_pages(channel, rx_buf, n_frags);
+
+ /* Pipeline receives so that we give time for packet headers to be
+ * prefetched into cache.
+ */
+ ef4_rx_flush_packet(channel);
+ channel->rx_pkt_n_frags = n_frags;
+ channel->rx_pkt_index = index;
+}
+
+static void ef4_rx_deliver(struct ef4_channel *channel, u8 *eh,
+ struct ef4_rx_buffer *rx_buf,
+ unsigned int n_frags)
+{
+ struct sk_buff *skb;
+ u16 hdr_len = min_t(u16, rx_buf->len, EF4_SKB_HEADERS);
+
+ skb = ef4_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len);
+ if (unlikely(skb == NULL)) {
+ struct ef4_rx_queue *rx_queue;
+
+ rx_queue = ef4_channel_get_rx_queue(channel);
+ ef4_free_rx_buffers(rx_queue, rx_buf, n_frags);
+ return;
+ }
+ skb_record_rx_queue(skb, channel->rx_queue.core_index);
+
+ /* Set the SKB flags */
+ skb_checksum_none_assert(skb);
+ if (likely(rx_buf->flags & EF4_RX_PKT_CSUMMED))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ if (channel->type->receive_skb)
+ if (channel->type->receive_skb(channel, skb))
+ return;
+
+ /* Pass the packet up */
+ netif_receive_skb(skb);
+}
+
+/* Handle a received packet. Second half: Touches packet payload. */
+void __ef4_rx_packet(struct ef4_channel *channel)
+{
+ struct ef4_nic *efx = channel->efx;
+ struct ef4_rx_buffer *rx_buf =
+ ef4_rx_buffer(&channel->rx_queue, channel->rx_pkt_index);
+ u8 *eh = ef4_rx_buf_va(rx_buf);
+
+ /* Read length from the prefix if necessary. This already
+ * excludes the length of the prefix itself.
+ */
+ if (rx_buf->flags & EF4_RX_PKT_PREFIX_LEN)
+ rx_buf->len = le16_to_cpup((__le16 *)
+ (eh + efx->rx_packet_len_offset));
+
+ /* If we're in loopback test, then pass the packet directly to the
+ * loopback layer, and free the rx_buf here
+ */
+ if (unlikely(efx->loopback_selftest)) {
+ struct ef4_rx_queue *rx_queue;
+
+ ef4_loopback_rx_packet(efx, eh, rx_buf->len);
+ rx_queue = ef4_channel_get_rx_queue(channel);
+ ef4_free_rx_buffers(rx_queue, rx_buf,
+ channel->rx_pkt_n_frags);
+ goto out;
+ }
+
+ if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
+ rx_buf->flags &= ~EF4_RX_PKT_CSUMMED;
+
+ if ((rx_buf->flags & EF4_RX_PKT_TCP) && !channel->type->receive_skb &&
+ !ef4_channel_busy_polling(channel))
+ ef4_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh);
+ else
+ ef4_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags);
+out:
+ channel->rx_pkt_n_frags = 0;
+}
+
+int ef4_probe_rx_queue(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned int entries;
+ int rc;
+
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->rxq_entries), EF4_MIN_DMAQ_SIZE);
+ EF4_BUG_ON_PARANOID(entries > EF4_MAX_DMAQ_SIZE);
+ rx_queue->ptr_mask = entries - 1;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "creating RX queue %d size %#x mask %#x\n",
+ ef4_rx_queue_index(rx_queue), efx->rxq_entries,
+ rx_queue->ptr_mask);
+
+ /* Allocate RX buffers */
+ rx_queue->buffer = kcalloc(entries, sizeof(*rx_queue->buffer),
+ GFP_KERNEL);
+ if (!rx_queue->buffer)
+ return -ENOMEM;
+
+ rc = ef4_nic_probe_rx(rx_queue);
+ if (rc) {
+ kfree(rx_queue->buffer);
+ rx_queue->buffer = NULL;
+ }
+
+ return rc;
+}
+
+static void ef4_init_rx_recycle_ring(struct ef4_nic *efx,
+ struct ef4_rx_queue *rx_queue)
+{
+ unsigned int bufs_in_recycle_ring, page_ring_size;
+
+ /* Set the RX recycle ring size */
+#ifdef CONFIG_PPC64
+ bufs_in_recycle_ring = EF4_RECYCLE_RING_SIZE_IOMMU;
+#else
+ if (iommu_present(&pci_bus_type))
+ bufs_in_recycle_ring = EF4_RECYCLE_RING_SIZE_IOMMU;
+ else
+ bufs_in_recycle_ring = EF4_RECYCLE_RING_SIZE_NOIOMMU;
+#endif /* CONFIG_PPC64 */
+
+ page_ring_size = roundup_pow_of_two(bufs_in_recycle_ring /
+ efx->rx_bufs_per_page);
+ rx_queue->page_ring = kcalloc(page_ring_size,
+ sizeof(*rx_queue->page_ring), GFP_KERNEL);
+ rx_queue->page_ptr_mask = page_ring_size - 1;
+}
+
+void ef4_init_rx_queue(struct ef4_rx_queue *rx_queue)
+{
+ struct ef4_nic *efx = rx_queue->efx;
+ unsigned int max_fill, trigger, max_trigger;
+
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "initialising RX queue %d\n", ef4_rx_queue_index(rx_queue));
+
+ /* Initialise ptr fields */
+ rx_queue->added_count = 0;
+ rx_queue->notified_count = 0;
+ rx_queue->removed_count = 0;
+ rx_queue->min_fill = -1U;
+ ef4_init_rx_recycle_ring(efx, rx_queue);
+
+ rx_queue->page_remove = 0;
+ rx_queue->page_add = rx_queue->page_ptr_mask + 1;
+ rx_queue->page_recycle_count = 0;
+ rx_queue->page_recycle_failed = 0;
+ rx_queue->page_recycle_full = 0;
+
+ /* Initialise limit fields */
+ max_fill = efx->rxq_entries - EF4_RXD_HEAD_ROOM;
+ max_trigger =
+ max_fill - efx->rx_pages_per_batch * efx->rx_bufs_per_page;
+ if (rx_refill_threshold != 0) {
+ trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
+ if (trigger > max_trigger)
+ trigger = max_trigger;
+ } else {
+ trigger = max_trigger;
+ }
+
+ rx_queue->max_fill = max_fill;
+ rx_queue->fast_fill_trigger = trigger;
+ rx_queue->refill_enabled = true;
+
+ /* Set up RX descriptor ring */
+ ef4_nic_init_rx(rx_queue);
+}
+
+void ef4_fini_rx_queue(struct ef4_rx_queue *rx_queue)
+{
+ int i;
+ struct ef4_nic *efx = rx_queue->efx;
+ struct ef4_rx_buffer *rx_buf;
+
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "shutting down RX queue %d\n", ef4_rx_queue_index(rx_queue));
+
+ del_timer_sync(&rx_queue->slow_fill);
+
+ /* Release RX buffers from the current read ptr to the write ptr */
+ if (rx_queue->buffer) {
+ for (i = rx_queue->removed_count; i < rx_queue->added_count;
+ i++) {
+ unsigned index = i & rx_queue->ptr_mask;
+ rx_buf = ef4_rx_buffer(rx_queue, index);
+ ef4_fini_rx_buffer(rx_queue, rx_buf);
+ }
+ }
+
+ /* Unmap and release the pages in the recycle ring. Remove the ring. */
+ for (i = 0; i <= rx_queue->page_ptr_mask; i++) {
+ struct page *page = rx_queue->page_ring[i];
+ struct ef4_rx_page_state *state;
+
+ if (page == NULL)
+ continue;
+
+ state = page_address(page);
+ dma_unmap_page(&efx->pci_dev->dev, state->dma_addr,
+ PAGE_SIZE << efx->rx_buffer_order,
+ DMA_FROM_DEVICE);
+ put_page(page);
+ }
+ kfree(rx_queue->page_ring);
+ rx_queue->page_ring = NULL;
+}
+
+void ef4_remove_rx_queue(struct ef4_rx_queue *rx_queue)
+{
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "destroying RX queue %d\n", ef4_rx_queue_index(rx_queue));
+
+ ef4_nic_remove_rx(rx_queue);
+
+ kfree(rx_queue->buffer);
+ rx_queue->buffer = NULL;
+}
+
+
+module_param(rx_refill_threshold, uint, 0444);
+MODULE_PARM_DESC(rx_refill_threshold,
+ "RX descriptor ring refill threshold (%)");
+
+#ifdef CONFIG_RFS_ACCEL
+
+int ef4_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_channel *channel;
+ struct ef4_filter_spec spec;
+ struct flow_keys fk;
+ int rc;
+
+ if (flow_id == RPS_FLOW_ID_INVALID)
+ return -EINVAL;
+
+ if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+ return -EPROTONOSUPPORT;
+
+ if (fk.basic.n_proto != htons(ETH_P_IP) && fk.basic.n_proto != htons(ETH_P_IPV6))
+ return -EPROTONOSUPPORT;
+ if (fk.control.flags & FLOW_DIS_IS_FRAGMENT)
+ return -EPROTONOSUPPORT;
+
+ ef4_filter_init_rx(&spec, EF4_FILTER_PRI_HINT,
+ efx->rx_scatter ? EF4_FILTER_FLAG_RX_SCATTER : 0,
+ rxq_index);
+ spec.match_flags =
+ EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO |
+ EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT |
+ EF4_FILTER_MATCH_REM_HOST | EF4_FILTER_MATCH_REM_PORT;
+ spec.ether_type = fk.basic.n_proto;
+ spec.ip_proto = fk.basic.ip_proto;
+
+ if (fk.basic.n_proto == htons(ETH_P_IP)) {
+ spec.rem_host[0] = fk.addrs.v4addrs.src;
+ spec.loc_host[0] = fk.addrs.v4addrs.dst;
+ } else {
+ memcpy(spec.rem_host, &fk.addrs.v6addrs.src, sizeof(struct in6_addr));
+ memcpy(spec.loc_host, &fk.addrs.v6addrs.dst, sizeof(struct in6_addr));
+ }
+
+ spec.rem_port = fk.ports.src;
+ spec.loc_port = fk.ports.dst;
+
+ rc = efx->type->filter_rfs_insert(efx, &spec);
+ if (rc < 0)
+ return rc;
+
+ /* Remember this so we can check whether to expire the filter later */
+ channel = ef4_get_channel(efx, rxq_index);
+ channel->rps_flow_id[rc] = flow_id;
+ ++channel->rfs_filters_added;
+
+ if (spec.ether_type == htons(ETH_P_IP))
+ netif_info(efx, rx_status, efx->net_dev,
+ "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
+ (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
+ spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
+ ntohs(spec.loc_port), rxq_index, flow_id, rc);
+ else
+ netif_info(efx, rx_status, efx->net_dev,
+ "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
+ (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
+ spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
+ ntohs(spec.loc_port), rxq_index, flow_id, rc);
+
+ return rc;
+}
+
+bool __ef4_filter_rfs_expire(struct ef4_nic *efx, unsigned int quota)
+{
+ bool (*expire_one)(struct ef4_nic *efx, u32 flow_id, unsigned int index);
+ unsigned int channel_idx, index, size;
+ u32 flow_id;
+
+ if (!spin_trylock_bh(&efx->filter_lock))
+ return false;
+
+ expire_one = efx->type->filter_rfs_expire_one;
+ channel_idx = efx->rps_expire_channel;
+ index = efx->rps_expire_index;
+ size = efx->type->max_rx_ip_filters;
+ while (quota--) {
+ struct ef4_channel *channel = ef4_get_channel(efx, channel_idx);
+ flow_id = channel->rps_flow_id[index];
+
+ if (flow_id != RPS_FLOW_ID_INVALID &&
+ expire_one(efx, flow_id, index)) {
+ netif_info(efx, rx_status, efx->net_dev,
+ "expired filter %d [queue %u flow %u]\n",
+ index, channel_idx, flow_id);
+ channel->rps_flow_id[index] = RPS_FLOW_ID_INVALID;
+ }
+ if (++index == size) {
+ if (++channel_idx == efx->n_channels)
+ channel_idx = 0;
+ index = 0;
+ }
+ }
+ efx->rps_expire_channel = channel_idx;
+ efx->rps_expire_index = index;
+
+ spin_unlock_bh(&efx->filter_lock);
+ return true;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
+
+/**
+ * ef4_filter_is_mc_recipient - test whether spec is a multicast recipient
+ * @spec: Specification to test
+ *
+ * Return: %true if the specification is a non-drop RX filter that
+ * matches a local MAC address I/G bit value of 1 or matches a local
+ * IPv4 or IPv6 address value in the respective multicast address
+ * range. Otherwise %false.
+ */
+bool ef4_filter_is_mc_recipient(const struct ef4_filter_spec *spec)
+{
+ if (!(spec->flags & EF4_FILTER_FLAG_RX) ||
+ spec->dmaq_id == EF4_FILTER_RX_DMAQ_ID_DROP)
+ return false;
+
+ if (spec->match_flags &
+ (EF4_FILTER_MATCH_LOC_MAC | EF4_FILTER_MATCH_LOC_MAC_IG) &&
+ is_multicast_ether_addr(spec->loc_mac))
+ return true;
+
+ if ((spec->match_flags &
+ (EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_LOC_HOST)) ==
+ (EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_LOC_HOST)) {
+ if (spec->ether_type == htons(ETH_P_IP) &&
+ ipv4_is_multicast(spec->loc_host[0]))
+ return true;
+ if (spec->ether_type == htons(ETH_P_IPV6) &&
+ ((const u8 *)spec->loc_host)[0] == 0xff)
+ return true;
+ }
+
+ return false;
+}
diff --git a/drivers/net/ethernet/sfc/falcon/selftest.c b/drivers/net/ethernet/sfc/falcon/selftest.c
new file mode 100644
index 000000000000..92bc34c91547
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/selftest.c
@@ -0,0 +1,808 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2012 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel_stat.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/udp.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "nic.h"
+#include "selftest.h"
+#include "workarounds.h"
+
+/* IRQ latency can be enormous because:
+ * - All IRQs may be disabled on a CPU for a *long* time by e.g. a
+ * slow serial console or an old IDE driver doing error recovery
+ * - The PREEMPT_RT patches mostly deal with this, but also allow a
+ * tasklet or normal task to be given higher priority than our IRQ
+ * threads
+ * Try to avoid blaming the hardware for this.
+ */
+#define IRQ_TIMEOUT HZ
+
+/*
+ * Loopback test packet structure
+ *
+ * The self-test should stress every RSS vector, and unfortunately
+ * Falcon only performs RSS on TCP/UDP packets.
+ */
+struct ef4_loopback_payload {
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+} __packed;
+
+/* Loopback test source MAC address */
+static const u8 payload_source[ETH_ALEN] __aligned(2) = {
+ 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b,
+};
+
+static const char payload_msg[] =
+ "Hello world! This is an Efx loopback test in progress!";
+
+/* Interrupt mode names */
+static const unsigned int ef4_interrupt_mode_max = EF4_INT_MODE_MAX;
+static const char *const ef4_interrupt_mode_names[] = {
+ [EF4_INT_MODE_MSIX] = "MSI-X",
+ [EF4_INT_MODE_MSI] = "MSI",
+ [EF4_INT_MODE_LEGACY] = "legacy",
+};
+#define INT_MODE(efx) \
+ STRING_TABLE_LOOKUP(efx->interrupt_mode, ef4_interrupt_mode)
+
+/**
+ * ef4_loopback_state - persistent state during a loopback selftest
+ * @flush: Drop all packets in ef4_loopback_rx_packet
+ * @packet_count: Number of packets being used in this test
+ * @skbs: An array of skbs transmitted
+ * @offload_csum: Checksums are being offloaded
+ * @rx_good: RX good packet count
+ * @rx_bad: RX bad packet count
+ * @payload: Payload used in tests
+ */
+struct ef4_loopback_state {
+ bool flush;
+ int packet_count;
+ struct sk_buff **skbs;
+ bool offload_csum;
+ atomic_t rx_good;
+ atomic_t rx_bad;
+ struct ef4_loopback_payload payload;
+};
+
+/* How long to wait for all the packets to arrive (in ms) */
+#define LOOPBACK_TIMEOUT_MS 1000
+
+/**************************************************************************
+ *
+ * MII, NVRAM and register tests
+ *
+ **************************************************************************/
+
+static int ef4_test_phy_alive(struct ef4_nic *efx, struct ef4_self_tests *tests)
+{
+ int rc = 0;
+
+ if (efx->phy_op->test_alive) {
+ rc = efx->phy_op->test_alive(efx);
+ tests->phy_alive = rc ? -1 : 1;
+ }
+
+ return rc;
+}
+
+static int ef4_test_nvram(struct ef4_nic *efx, struct ef4_self_tests *tests)
+{
+ int rc = 0;
+
+ if (efx->type->test_nvram) {
+ rc = efx->type->test_nvram(efx);
+ if (rc == -EPERM)
+ rc = 0;
+ else
+ tests->nvram = rc ? -1 : 1;
+ }
+
+ return rc;
+}
+
+/**************************************************************************
+ *
+ * Interrupt and event queue testing
+ *
+ **************************************************************************/
+
+/* Test generation and receipt of interrupts */
+static int ef4_test_interrupts(struct ef4_nic *efx,
+ struct ef4_self_tests *tests)
+{
+ unsigned long timeout, wait;
+ int cpu;
+ int rc;
+
+ netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
+ tests->interrupt = -1;
+
+ rc = ef4_nic_irq_test_start(efx);
+ if (rc == -ENOTSUPP) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "direct interrupt testing not supported\n");
+ tests->interrupt = 0;
+ return 0;
+ }
+
+ timeout = jiffies + IRQ_TIMEOUT;
+ wait = 1;
+
+ /* Wait for arrival of test interrupt. */
+ netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
+ do {
+ schedule_timeout_uninterruptible(wait);
+ cpu = ef4_nic_irq_test_irq_cpu(efx);
+ if (cpu >= 0)
+ goto success;
+ wait *= 2;
+ } while (time_before(jiffies, timeout));
+
+ netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n");
+ return -ETIMEDOUT;
+
+ success:
+ netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n",
+ INT_MODE(efx), cpu);
+ tests->interrupt = 1;
+ return 0;
+}
+
+/* Test generation and receipt of interrupting events */
+static int ef4_test_eventq_irq(struct ef4_nic *efx,
+ struct ef4_self_tests *tests)
+{
+ struct ef4_channel *channel;
+ unsigned int read_ptr[EF4_MAX_CHANNELS];
+ unsigned long napi_ran = 0, dma_pend = 0, int_pend = 0;
+ unsigned long timeout, wait;
+
+ BUILD_BUG_ON(EF4_MAX_CHANNELS > BITS_PER_LONG);
+
+ ef4_for_each_channel(channel, efx) {
+ read_ptr[channel->channel] = channel->eventq_read_ptr;
+ set_bit(channel->channel, &dma_pend);
+ set_bit(channel->channel, &int_pend);
+ ef4_nic_event_test_start(channel);
+ }
+
+ timeout = jiffies + IRQ_TIMEOUT;
+ wait = 1;
+
+ /* Wait for arrival of interrupts. NAPI processing may or may
+ * not complete in time, but we can cope in any case.
+ */
+ do {
+ schedule_timeout_uninterruptible(wait);
+
+ ef4_for_each_channel(channel, efx) {
+ ef4_stop_eventq(channel);
+ if (channel->eventq_read_ptr !=
+ read_ptr[channel->channel]) {
+ set_bit(channel->channel, &napi_ran);
+ clear_bit(channel->channel, &dma_pend);
+ clear_bit(channel->channel, &int_pend);
+ } else {
+ if (ef4_nic_event_present(channel))
+ clear_bit(channel->channel, &dma_pend);
+ if (ef4_nic_event_test_irq_cpu(channel) >= 0)
+ clear_bit(channel->channel, &int_pend);
+ }
+ ef4_start_eventq(channel);
+ }
+
+ wait *= 2;
+ } while ((dma_pend || int_pend) && time_before(jiffies, timeout));
+
+ ef4_for_each_channel(channel, efx) {
+ bool dma_seen = !test_bit(channel->channel, &dma_pend);
+ bool int_seen = !test_bit(channel->channel, &int_pend);
+
+ tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
+ tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
+
+ if (dma_seen && int_seen) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "channel %d event queue passed (with%s NAPI)\n",
+ channel->channel,
+ test_bit(channel->channel, &napi_ran) ?
+ "" : "out");
+ } else {
+ /* Report failure and whether either interrupt or DMA
+ * worked
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d timed out waiting for event queue\n",
+ channel->channel);
+ if (int_seen)
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d saw interrupt "
+ "during event queue test\n",
+ channel->channel);
+ if (dma_seen)
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d event was generated, but "
+ "failed to trigger an interrupt\n",
+ channel->channel);
+ }
+ }
+
+ return (dma_pend || int_pend) ? -ETIMEDOUT : 0;
+}
+
+static int ef4_test_phy(struct ef4_nic *efx, struct ef4_self_tests *tests,
+ unsigned flags)
+{
+ int rc;
+
+ if (!efx->phy_op->run_tests)
+ return 0;
+
+ mutex_lock(&efx->mac_lock);
+ rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags);
+ mutex_unlock(&efx->mac_lock);
+ if (rc == -EPERM)
+ rc = 0;
+ else
+ netif_info(efx, drv, efx->net_dev,
+ "%s phy selftest\n", rc ? "Failed" : "Passed");
+
+ return rc;
+}
+
+/**************************************************************************
+ *
+ * Loopback testing
+ * NB Only one loopback test can be executing concurrently.
+ *
+ **************************************************************************/
+
+/* Loopback test RX callback
+ * This is called for each received packet during loopback testing.
+ */
+void ef4_loopback_rx_packet(struct ef4_nic *efx,
+ const char *buf_ptr, int pkt_len)
+{
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+ struct ef4_loopback_payload *received;
+ struct ef4_loopback_payload *payload;
+
+ BUG_ON(!buf_ptr);
+
+ /* If we are just flushing, then drop the packet */
+ if ((state == NULL) || state->flush)
+ return;
+
+ payload = &state->payload;
+
+ received = (struct ef4_loopback_payload *) buf_ptr;
+ received->ip.saddr = payload->ip.saddr;
+ if (state->offload_csum)
+ received->ip.check = payload->ip.check;
+
+ /* Check that header exists */
+ if (pkt_len < sizeof(received->header)) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw runt RX packet (length %d) in %s loopback "
+ "test\n", pkt_len, LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Check that the ethernet header exists */
+ if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw non-loopback RX packet in %s loopback test\n",
+ LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Check packet length */
+ if (pkt_len != sizeof(*payload)) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw incorrect RX packet length %d (wanted %d) in "
+ "%s loopback test\n", pkt_len, (int)sizeof(*payload),
+ LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Check that IP header matches */
+ if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw corrupted IP header in %s loopback test\n",
+ LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Check that msg and padding matches */
+ if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw corrupted RX packet in %s loopback test\n",
+ LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Check that iteration matches */
+ if (received->iteration != payload->iteration) {
+ netif_err(efx, drv, efx->net_dev,
+ "saw RX packet from iteration %d (wanted %d) in "
+ "%s loopback test\n", ntohs(received->iteration),
+ ntohs(payload->iteration), LOOPBACK_MODE(efx));
+ goto err;
+ }
+
+ /* Increase correct RX count */
+ netif_vdbg(efx, drv, efx->net_dev,
+ "got loopback RX in %s loopback test\n", LOOPBACK_MODE(efx));
+
+ atomic_inc(&state->rx_good);
+ return;
+
+ err:
+#ifdef DEBUG
+ if (atomic_read(&state->rx_bad) == 0) {
+ netif_err(efx, drv, efx->net_dev, "received packet:\n");
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
+ buf_ptr, pkt_len, 0);
+ netif_err(efx, drv, efx->net_dev, "expected packet:\n");
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
+ &state->payload, sizeof(state->payload), 0);
+ }
+#endif
+ atomic_inc(&state->rx_bad);
+}
+
+/* Initialise an ef4_selftest_state for a new iteration */
+static void ef4_iterate_state(struct ef4_nic *efx)
+{
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+ struct net_device *net_dev = efx->net_dev;
+ struct ef4_loopback_payload *payload = &state->payload;
+
+ /* Initialise the layerII header */
+ ether_addr_copy((u8 *)&payload->header.h_dest, net_dev->dev_addr);
+ ether_addr_copy((u8 *)&payload->header.h_source, payload_source);
+ payload->header.h_proto = htons(ETH_P_IP);
+
+ /* saddr set later and used as incrementing count */
+ payload->ip.daddr = htonl(INADDR_LOOPBACK);
+ payload->ip.ihl = 5;
+ payload->ip.check = (__force __sum16) htons(0xdead);
+ payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.version = IPVERSION;
+ payload->ip.protocol = IPPROTO_UDP;
+
+ /* Initialise udp header */
+ payload->udp.source = 0;
+ payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
+ sizeof(struct iphdr));
+ payload->udp.check = 0; /* checksum ignored */
+
+ /* Fill out payload */
+ payload->iteration = htons(ntohs(payload->iteration) + 1);
+ memcpy(&payload->msg, payload_msg, sizeof(payload_msg));
+
+ /* Fill out remaining state members */
+ atomic_set(&state->rx_good, 0);
+ atomic_set(&state->rx_bad, 0);
+ smp_wmb();
+}
+
+static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+ struct ef4_loopback_payload *payload;
+ struct sk_buff *skb;
+ int i;
+ netdev_tx_t rc;
+
+ /* Transmit N copies of buffer */
+ for (i = 0; i < state->packet_count; i++) {
+ /* Allocate an skb, holding an extra reference for
+ * transmit completion counting */
+ skb = alloc_skb(sizeof(state->payload), GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+ state->skbs[i] = skb;
+ skb_get(skb);
+
+ /* Copy the payload in, incrementing the source address to
+ * exercise the rss vectors */
+ payload = ((struct ef4_loopback_payload *)
+ skb_put(skb, sizeof(state->payload)));
+ memcpy(payload, &state->payload, sizeof(state->payload));
+ payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+
+ /* Ensure everything we've written is visible to the
+ * interrupt handler. */
+ smp_wmb();
+
+ netif_tx_lock_bh(efx->net_dev);
+ rc = ef4_enqueue_skb(tx_queue, skb);
+ netif_tx_unlock_bh(efx->net_dev);
+
+ if (rc != NETDEV_TX_OK) {
+ netif_err(efx, drv, efx->net_dev,
+ "TX queue %d could not transmit packet %d of "
+ "%d in %s loopback test\n", tx_queue->queue,
+ i + 1, state->packet_count,
+ LOOPBACK_MODE(efx));
+
+ /* Defer cleaning up the other skbs for the caller */
+ kfree_skb(skb);
+ return -EPIPE;
+ }
+ }
+
+ return 0;
+}
+
+static int ef4_poll_loopback(struct ef4_nic *efx)
+{
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+
+ return atomic_read(&state->rx_good) == state->packet_count;
+}
+
+static int ef4_end_loopback(struct ef4_tx_queue *tx_queue,
+ struct ef4_loopback_self_tests *lb_tests)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+ struct sk_buff *skb;
+ int tx_done = 0, rx_good, rx_bad;
+ int i, rc = 0;
+
+ netif_tx_lock_bh(efx->net_dev);
+
+ /* Count the number of tx completions, and decrement the refcnt. Any
+ * skbs not already completed will be free'd when the queue is flushed */
+ for (i = 0; i < state->packet_count; i++) {
+ skb = state->skbs[i];
+ if (skb && !skb_shared(skb))
+ ++tx_done;
+ dev_kfree_skb(skb);
+ }
+
+ netif_tx_unlock_bh(efx->net_dev);
+
+ /* Check TX completion and received packet counts */
+ rx_good = atomic_read(&state->rx_good);
+ rx_bad = atomic_read(&state->rx_bad);
+ if (tx_done != state->packet_count) {
+ /* Don't free the skbs; they will be picked up on TX
+ * overflow or channel teardown.
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "TX queue %d saw only %d out of an expected %d "
+ "TX completion events in %s loopback test\n",
+ tx_queue->queue, tx_done, state->packet_count,
+ LOOPBACK_MODE(efx));
+ rc = -ETIMEDOUT;
+ /* Allow to fall through so we see the RX errors as well */
+ }
+
+ /* We may always be up to a flush away from our desired packet total */
+ if (rx_good != state->packet_count) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "TX queue %d saw only %d out of an expected %d "
+ "received packets in %s loopback test\n",
+ tx_queue->queue, rx_good, state->packet_count,
+ LOOPBACK_MODE(efx));
+ rc = -ETIMEDOUT;
+ /* Fall through */
+ }
+
+ /* Update loopback test structure */
+ lb_tests->tx_sent[tx_queue->queue] += state->packet_count;
+ lb_tests->tx_done[tx_queue->queue] += tx_done;
+ lb_tests->rx_good += rx_good;
+ lb_tests->rx_bad += rx_bad;
+
+ return rc;
+}
+
+static int
+ef4_test_loopback(struct ef4_tx_queue *tx_queue,
+ struct ef4_loopback_self_tests *lb_tests)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ struct ef4_loopback_state *state = efx->loopback_selftest;
+ int i, begin_rc, end_rc;
+
+ for (i = 0; i < 3; i++) {
+ /* Determine how many packets to send */
+ state->packet_count = efx->txq_entries / 3;
+ state->packet_count = min(1 << (i << 2), state->packet_count);
+ state->skbs = kcalloc(state->packet_count,
+ sizeof(state->skbs[0]), GFP_KERNEL);
+ if (!state->skbs)
+ return -ENOMEM;
+ state->flush = false;
+
+ netif_dbg(efx, drv, efx->net_dev,
+ "TX queue %d testing %s loopback with %d packets\n",
+ tx_queue->queue, LOOPBACK_MODE(efx),
+ state->packet_count);
+
+ ef4_iterate_state(efx);
+ begin_rc = ef4_begin_loopback(tx_queue);
+
+ /* This will normally complete very quickly, but be
+ * prepared to wait much longer. */
+ msleep(1);
+ if (!ef4_poll_loopback(efx)) {
+ msleep(LOOPBACK_TIMEOUT_MS);
+ ef4_poll_loopback(efx);
+ }
+
+ end_rc = ef4_end_loopback(tx_queue, lb_tests);
+ kfree(state->skbs);
+
+ if (begin_rc || end_rc) {
+ /* Wait a while to ensure there are no packets
+ * floating around after a failure. */
+ schedule_timeout_uninterruptible(HZ / 10);
+ return begin_rc ? begin_rc : end_rc;
+ }
+ }
+
+ netif_dbg(efx, drv, efx->net_dev,
+ "TX queue %d passed %s loopback test with a burst length "
+ "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
+ state->packet_count);
+
+ return 0;
+}
+
+/* Wait for link up. On Falcon, we would prefer to rely on ef4_monitor, but
+ * any contention on the mac lock (via e.g. ef4_mac_mcast_work) causes it
+ * to delay and retry. Therefore, it's safer to just poll directly. Wait
+ * for link up and any faults to dissipate. */
+static int ef4_wait_for_link(struct ef4_nic *efx)
+{
+ struct ef4_link_state *link_state = &efx->link_state;
+ int count, link_up_count = 0;
+ bool link_up;
+
+ for (count = 0; count < 40; count++) {
+ schedule_timeout_uninterruptible(HZ / 10);
+
+ if (efx->type->monitor != NULL) {
+ mutex_lock(&efx->mac_lock);
+ efx->type->monitor(efx);
+ mutex_unlock(&efx->mac_lock);
+ }
+
+ mutex_lock(&efx->mac_lock);
+ link_up = link_state->up;
+ if (link_up)
+ link_up = !efx->type->check_mac_fault(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ if (link_up) {
+ if (++link_up_count == 2)
+ return 0;
+ } else {
+ link_up_count = 0;
+ }
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int ef4_test_loopbacks(struct ef4_nic *efx, struct ef4_self_tests *tests,
+ unsigned int loopback_modes)
+{
+ enum ef4_loopback_mode mode;
+ struct ef4_loopback_state *state;
+ struct ef4_channel *channel =
+ ef4_get_channel(efx, efx->tx_channel_offset);
+ struct ef4_tx_queue *tx_queue;
+ int rc = 0;
+
+ /* Set the port loopback_selftest member. From this point on
+ * all received packets will be dropped. Mark the state as
+ * "flushing" so all inflight packets are dropped */
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+ BUG_ON(efx->loopback_selftest);
+ state->flush = true;
+ efx->loopback_selftest = state;
+
+ /* Test all supported loopback modes */
+ for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
+ if (!(loopback_modes & (1 << mode)))
+ continue;
+
+ /* Move the port into the specified loopback mode. */
+ state->flush = true;
+ mutex_lock(&efx->mac_lock);
+ efx->loopback_mode = mode;
+ rc = __ef4_reconfigure_port(efx);
+ mutex_unlock(&efx->mac_lock);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "unable to move into %s loopback\n",
+ LOOPBACK_MODE(efx));
+ goto out;
+ }
+
+ rc = ef4_wait_for_link(efx);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "loopback %s never came up\n",
+ LOOPBACK_MODE(efx));
+ goto out;
+ }
+
+ /* Test all enabled types of TX queue */
+ ef4_for_each_channel_tx_queue(tx_queue, channel) {
+ state->offload_csum = (tx_queue->queue &
+ EF4_TXQ_TYPE_OFFLOAD);
+ rc = ef4_test_loopback(tx_queue,
+ &tests->loopback[mode]);
+ if (rc)
+ goto out;
+ }
+ }
+
+ out:
+ /* Remove the flush. The caller will remove the loopback setting */
+ state->flush = true;
+ efx->loopback_selftest = NULL;
+ wmb();
+ kfree(state);
+
+ if (rc == -EPERM)
+ rc = 0;
+
+ return rc;
+}
+
+/**************************************************************************
+ *
+ * Entry point
+ *
+ *************************************************************************/
+
+int ef4_selftest(struct ef4_nic *efx, struct ef4_self_tests *tests,
+ unsigned flags)
+{
+ enum ef4_loopback_mode loopback_mode = efx->loopback_mode;
+ int phy_mode = efx->phy_mode;
+ int rc_test = 0, rc_reset, rc;
+
+ ef4_selftest_async_cancel(efx);
+
+ /* Online (i.e. non-disruptive) testing
+ * This checks interrupt generation, event delivery and PHY presence. */
+
+ rc = ef4_test_phy_alive(efx, tests);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ rc = ef4_test_nvram(efx, tests);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ rc = ef4_test_interrupts(efx, tests);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ rc = ef4_test_eventq_irq(efx, tests);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ if (rc_test)
+ return rc_test;
+
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return ef4_test_phy(efx, tests, flags);
+
+ /* Offline (i.e. disruptive) testing
+ * This checks MAC and PHY loopback on the specified port. */
+
+ /* Detach the device so the kernel doesn't transmit during the
+ * loopback test and the watchdog timeout doesn't fire.
+ */
+ ef4_device_detach_sync(efx);
+
+ if (efx->type->test_chip) {
+ rc_reset = efx->type->test_chip(efx, tests);
+ if (rc_reset) {
+ netif_err(efx, hw, efx->net_dev,
+ "Unable to recover from chip test\n");
+ ef4_schedule_reset(efx, RESET_TYPE_DISABLE);
+ return rc_reset;
+ }
+
+ if ((tests->memory < 0 || tests->registers < 0) && !rc_test)
+ rc_test = -EIO;
+ }
+
+ /* Ensure that the phy is powered and out of loopback
+ * for the bist and loopback tests */
+ mutex_lock(&efx->mac_lock);
+ efx->phy_mode &= ~PHY_MODE_LOW_POWER;
+ efx->loopback_mode = LOOPBACK_NONE;
+ __ef4_reconfigure_port(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ rc = ef4_test_phy(efx, tests, flags);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ rc = ef4_test_loopbacks(efx, tests, efx->loopback_modes);
+ if (rc && !rc_test)
+ rc_test = rc;
+
+ /* restore the PHY to the previous state */
+ mutex_lock(&efx->mac_lock);
+ efx->phy_mode = phy_mode;
+ efx->loopback_mode = loopback_mode;
+ __ef4_reconfigure_port(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ netif_device_attach(efx->net_dev);
+
+ return rc_test;
+}
+
+void ef4_selftest_async_start(struct ef4_nic *efx)
+{
+ struct ef4_channel *channel;
+
+ ef4_for_each_channel(channel, efx)
+ ef4_nic_event_test_start(channel);
+ schedule_delayed_work(&efx->selftest_work, IRQ_TIMEOUT);
+}
+
+void ef4_selftest_async_cancel(struct ef4_nic *efx)
+{
+ cancel_delayed_work_sync(&efx->selftest_work);
+}
+
+void ef4_selftest_async_work(struct work_struct *data)
+{
+ struct ef4_nic *efx = container_of(data, struct ef4_nic,
+ selftest_work.work);
+ struct ef4_channel *channel;
+ int cpu;
+
+ ef4_for_each_channel(channel, efx) {
+ cpu = ef4_nic_event_test_irq_cpu(channel);
+ if (cpu < 0)
+ netif_err(efx, ifup, efx->net_dev,
+ "channel %d failed to trigger an interrupt\n",
+ channel->channel);
+ else
+ netif_dbg(efx, ifup, efx->net_dev,
+ "channel %d triggered interrupt on CPU %d\n",
+ channel->channel, cpu);
+ }
+}
diff --git a/drivers/net/ethernet/sfc/falcon/selftest.h b/drivers/net/ethernet/sfc/falcon/selftest.h
new file mode 100644
index 000000000000..be52a49c006a
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/selftest.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2012 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_SELFTEST_H
+#define EF4_SELFTEST_H
+
+#include "net_driver.h"
+
+/*
+ * Self tests
+ */
+
+struct ef4_loopback_self_tests {
+ int tx_sent[EF4_TXQ_TYPES];
+ int tx_done[EF4_TXQ_TYPES];
+ int rx_good;
+ int rx_bad;
+};
+
+#define EF4_MAX_PHY_TESTS 20
+
+/* Efx self test results
+ * For fields which are not counters, 1 indicates success and -1
+ * indicates failure; 0 indicates test could not be run.
+ */
+struct ef4_self_tests {
+ /* online tests */
+ int phy_alive;
+ int nvram;
+ int interrupt;
+ int eventq_dma[EF4_MAX_CHANNELS];
+ int eventq_int[EF4_MAX_CHANNELS];
+ /* offline tests */
+ int memory;
+ int registers;
+ int phy_ext[EF4_MAX_PHY_TESTS];
+ struct ef4_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
+};
+
+void ef4_loopback_rx_packet(struct ef4_nic *efx, const char *buf_ptr,
+ int pkt_len);
+int ef4_selftest(struct ef4_nic *efx, struct ef4_self_tests *tests,
+ unsigned flags);
+void ef4_selftest_async_start(struct ef4_nic *efx);
+void ef4_selftest_async_cancel(struct ef4_nic *efx);
+void ef4_selftest_async_work(struct work_struct *data);
+
+#endif /* EF4_SELFTEST_H */
diff --git a/drivers/net/ethernet/sfc/tenxpress.c b/drivers/net/ethernet/sfc/falcon/tenxpress.c
index 2c90e6b31575..acc548a1c4d6 100644
--- a/drivers/net/ethernet/sfc/tenxpress.c
+++ b/drivers/net/ethernet/sfc/falcon/tenxpress.c
@@ -143,27 +143,27 @@
#define LNPGA_PDOWN_WAIT (HZ / 5)
struct tenxpress_phy_data {
- enum efx_loopback_mode loopback_mode;
- enum efx_phy_mode phy_mode;
+ enum ef4_loopback_mode loopback_mode;
+ enum ef4_phy_mode phy_mode;
int bad_lp_tries;
};
-static int tenxpress_init(struct efx_nic *efx)
+static int tenxpress_init(struct ef4_nic *efx)
{
/* Enable 312.5 MHz clock */
- efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+ ef4_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
1 << CLK312_EN_LBN);
/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
1 << PMA_PMA_LED_ACTIVITY_LBN, true);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
SFX7101_PMA_PMD_LED_DEFAULT);
return 0;
}
-static int tenxpress_phy_probe(struct efx_nic *efx)
+static int tenxpress_phy_probe(struct ef4_nic *efx)
{
struct tenxpress_phy_data *phy_data;
@@ -185,18 +185,18 @@ static int tenxpress_phy_probe(struct efx_nic *efx)
return 0;
}
-static int tenxpress_phy_init(struct efx_nic *efx)
+static int tenxpress_phy_init(struct ef4_nic *efx)
{
int rc;
falcon_board(efx)->type->init_phy(efx);
if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
- rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
+ rc = ef4_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
return rc;
- rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS);
+ rc = ef4_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
return rc;
}
@@ -206,8 +206,8 @@ static int tenxpress_phy_init(struct efx_nic *efx)
return rc;
/* Reinitialise flow control settings */
- efx_link_set_wanted_fc(efx, efx->wanted_fc);
- efx_mdio_an_reconfigure(efx);
+ ef4_link_set_wanted_fc(efx, efx->wanted_fc);
+ ef4_mdio_an_reconfigure(efx);
schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
@@ -220,7 +220,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
/* Perform a "special software reset" on the PHY. The caller is
* responsible for saving and restoring the PHY hardware registers
* properly, and masking/unmasking LASI */
-static int tenxpress_special_reset(struct efx_nic *efx)
+static int tenxpress_special_reset(struct ef4_nic *efx)
{
int rc, reg;
@@ -230,14 +230,14 @@ static int tenxpress_special_reset(struct efx_nic *efx)
falcon_stop_nic_stats(efx);
/* Initiate reset */
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
+ reg = ef4_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
reg |= (1 << PMA_PMD_EXT_SSR_LBN);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
mdelay(200);
/* Wait for the blocks to come out of reset */
- rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
+ rc = ef4_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
goto out;
@@ -253,7 +253,7 @@ out:
return rc;
}
-static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
+static void sfx7101_check_bad_lp(struct ef4_nic *efx, bool link_ok)
{
struct tenxpress_phy_data *pd = efx->phy_data;
bool bad_lp;
@@ -263,7 +263,7 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
bad_lp = false;
} else {
/* Check that AN has started but not completed. */
- reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
+ reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
if (!(reg & MDIO_AN_STAT1_LPABLE))
return; /* LP status is unknown */
bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE);
@@ -278,7 +278,7 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
/* Use the RX (red) LED as an error indicator once we've seen AN
* failure several times in a row, and also log a message. */
if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+ reg = ef4_mdio_read(efx, MDIO_MMD_PMAPMD,
PMA_PMD_LED_OVERR_REG);
reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
if (!bad_lp) {
@@ -291,35 +291,35 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
" supports 10GBASE-T ONLY, so no link can"
" be established\n");
}
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
PMA_PMD_LED_OVERR_REG, reg);
pd->bad_lp_tries = bad_lp;
}
}
-static bool sfx7101_link_ok(struct efx_nic *efx)
+static bool sfx7101_link_ok(struct ef4_nic *efx)
{
- return efx_mdio_links_ok(efx,
+ return ef4_mdio_links_ok(efx,
MDIO_DEVS_PMAPMD |
MDIO_DEVS_PCS |
MDIO_DEVS_PHYXS);
}
-static void tenxpress_ext_loopback(struct efx_nic *efx)
+static void tenxpress_ext_loopback(struct ef4_nic *efx)
{
- efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
+ ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
1 << LOOPBACK_NEAR_LBN,
efx->loopback_mode == LOOPBACK_PHYXS);
}
-static void tenxpress_low_power(struct efx_nic *efx)
+static void tenxpress_low_power(struct ef4_nic *efx)
{
- efx_mdio_set_mmds_lpower(
+ ef4_mdio_set_mmds_lpower(
efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
TENXPRESS_REQUIRED_DEVS);
}
-static int tenxpress_phy_reconfigure(struct efx_nic *efx)
+static int tenxpress_phy_reconfigure(struct ef4_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
bool phy_mode_change, loop_reset;
@@ -340,10 +340,10 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx)
}
tenxpress_low_power(efx);
- efx_mdio_transmit_disable(efx);
- efx_mdio_phy_reconfigure(efx);
+ ef4_mdio_transmit_disable(efx);
+ ef4_mdio_phy_reconfigure(efx);
tenxpress_ext_loopback(efx);
- efx_mdio_an_reconfigure(efx);
+ ef4_mdio_an_reconfigure(efx);
phy_data->loopback_mode = efx->loopback_mode;
phy_data->phy_mode = efx->phy_mode;
@@ -352,30 +352,30 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx)
}
static void
-tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+tenxpress_get_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd);
/* Poll for link state changes */
-static bool tenxpress_phy_poll(struct efx_nic *efx)
+static bool tenxpress_phy_poll(struct ef4_nic *efx)
{
- struct efx_link_state old_state = efx->link_state;
+ struct ef4_link_state old_state = efx->link_state;
efx->link_state.up = sfx7101_link_ok(efx);
efx->link_state.speed = 10000;
efx->link_state.fd = true;
- efx->link_state.fc = efx_mdio_get_pause(efx);
+ efx->link_state.fc = ef4_mdio_get_pause(efx);
sfx7101_check_bad_lp(efx, efx->link_state.up);
- return !efx_link_state_equal(&efx->link_state, &old_state);
+ return !ef4_link_state_equal(&efx->link_state, &old_state);
}
-static void sfx7101_phy_fini(struct efx_nic *efx)
+static void sfx7101_phy_fini(struct ef4_nic *efx)
{
int reg;
/* Power down the LNPGA */
reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
/* Waiting here ensures that the board fini, which can turn
* off the power to the PHY, won't get run until the LNPGA
@@ -383,7 +383,7 @@ static void sfx7101_phy_fini(struct efx_nic *efx)
schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
}
-static void tenxpress_phy_remove(struct efx_nic *efx)
+static void tenxpress_phy_remove(struct ef4_nic *efx)
{
kfree(efx->phy_data);
efx->phy_data = NULL;
@@ -391,17 +391,17 @@ static void tenxpress_phy_remove(struct efx_nic *efx)
/* Override the RX, TX and link LEDs */
-void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+void tenxpress_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{
int reg;
switch (mode) {
- case EFX_LED_OFF:
+ case EF4_LED_OFF:
reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) |
(PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
(PMA_PMD_LED_OFF << PMA_PMD_LED_LINK_LBN);
break;
- case EFX_LED_ON:
+ case EF4_LED_ON:
reg = (PMA_PMD_LED_ON << PMA_PMD_LED_TX_LBN) |
(PMA_PMD_LED_ON << PMA_PMD_LED_RX_LBN) |
(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
@@ -411,14 +411,14 @@ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
break;
}
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
}
static const char *const sfx7101_test_names[] = {
"bist"
};
-static const char *sfx7101_test_name(struct efx_nic *efx, unsigned int index)
+static const char *sfx7101_test_name(struct ef4_nic *efx, unsigned int index)
{
if (index < ARRAY_SIZE(sfx7101_test_names))
return sfx7101_test_names[index];
@@ -426,7 +426,7 @@ static const char *sfx7101_test_name(struct efx_nic *efx, unsigned int index)
}
static int
-sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+sfx7101_run_tests(struct ef4_nic *efx, int *results, unsigned flags)
{
int rc;
@@ -437,21 +437,21 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
rc = tenxpress_special_reset(efx);
results[0] = rc ? -1 : 1;
- efx_mdio_an_reconfigure(efx);
+ ef4_mdio_an_reconfigure(efx);
return rc;
}
static void
-tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+tenxpress_get_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd)
{
u32 adv = 0, lpa = 0;
int reg;
- reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
+ reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
adv |= ADVERTISED_10000baseT_Full;
- reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
+ reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
if (reg & MDIO_AN_10GBT_STAT_LP10G)
lpa |= ADVERTISED_10000baseT_Full;
@@ -463,22 +463,22 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
ethtool_cmd_speed_set(ecmd, SPEED_10000);
}
-static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static int tenxpress_set_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd)
{
if (!ecmd->autoneg)
return -EINVAL;
- return efx_mdio_set_settings(efx, ecmd);
+ return ef4_mdio_set_settings(efx, ecmd);
}
-static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
+static void sfx7101_set_npage_adv(struct ef4_nic *efx, u32 advertising)
{
- efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ ef4_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADV10G,
advertising & ADVERTISED_10000baseT_Full);
}
-const struct efx_phy_operations falcon_sfx7101_phy_ops = {
+const struct ef4_phy_operations falcon_sfx7101_phy_ops = {
.probe = tenxpress_phy_probe,
.init = tenxpress_phy_init,
.reconfigure = tenxpress_phy_reconfigure,
@@ -488,7 +488,7 @@ const struct efx_phy_operations falcon_sfx7101_phy_ops = {
.get_settings = tenxpress_get_settings,
.set_settings = tenxpress_set_settings,
.set_npage_adv = sfx7101_set_npage_adv,
- .test_alive = efx_mdio_test_alive,
+ .test_alive = ef4_mdio_test_alive,
.test_name = sfx7101_test_name,
.run_tests = sfx7101_run_tests,
};
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
new file mode 100644
index 000000000000..104fb15a73f2
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -0,0 +1,649 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2005-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/pci.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/ipv6.h>
+#include <linux/slab.h>
+#include <net/ipv6.h>
+#include <linux/if_ether.h>
+#include <linux/highmem.h>
+#include <linux/cache.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "io.h"
+#include "nic.h"
+#include "tx.h"
+#include "workarounds.h"
+
+static inline u8 *ef4_tx_get_copy_buffer(struct ef4_tx_queue *tx_queue,
+ struct ef4_tx_buffer *buffer)
+{
+ unsigned int index = ef4_tx_queue_get_insert_index(tx_queue);
+ struct ef4_buffer *page_buf =
+ &tx_queue->cb_page[index >> (PAGE_SHIFT - EF4_TX_CB_ORDER)];
+ unsigned int offset =
+ ((index << EF4_TX_CB_ORDER) + NET_IP_ALIGN) & (PAGE_SIZE - 1);
+
+ if (unlikely(!page_buf->addr) &&
+ ef4_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE,
+ GFP_ATOMIC))
+ return NULL;
+ buffer->dma_addr = page_buf->dma_addr + offset;
+ buffer->unmap_len = 0;
+ return (u8 *)page_buf->addr + offset;
+}
+
+u8 *ef4_tx_get_copy_buffer_limited(struct ef4_tx_queue *tx_queue,
+ struct ef4_tx_buffer *buffer, size_t len)
+{
+ if (len > EF4_TX_CB_SIZE)
+ return NULL;
+ return ef4_tx_get_copy_buffer(tx_queue, buffer);
+}
+
+static void ef4_dequeue_buffer(struct ef4_tx_queue *tx_queue,
+ struct ef4_tx_buffer *buffer,
+ unsigned int *pkts_compl,
+ unsigned int *bytes_compl)
+{
+ if (buffer->unmap_len) {
+ struct device *dma_dev = &tx_queue->efx->pci_dev->dev;
+ dma_addr_t unmap_addr = buffer->dma_addr - buffer->dma_offset;
+ if (buffer->flags & EF4_TX_BUF_MAP_SINGLE)
+ dma_unmap_single(dma_dev, unmap_addr, buffer->unmap_len,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(dma_dev, unmap_addr, buffer->unmap_len,
+ DMA_TO_DEVICE);
+ buffer->unmap_len = 0;
+ }
+
+ if (buffer->flags & EF4_TX_BUF_SKB) {
+ (*pkts_compl)++;
+ (*bytes_compl) += buffer->skb->len;
+ dev_consume_skb_any((struct sk_buff *)buffer->skb);
+ netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev,
+ "TX queue %d transmission id %x complete\n",
+ tx_queue->queue, tx_queue->read_count);
+ }
+
+ buffer->len = 0;
+ buffer->flags = 0;
+}
+
+unsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx)
+{
+ /* This is probably too much since we don't have any TSO support;
+ * it's a left-over from when we had Software TSO. But it's safer
+ * to leave it as-is than try to determine a new bound.
+ */
+ /* Header and payload descriptor for each output segment, plus
+ * one for every input fragment boundary within a segment
+ */
+ unsigned int max_descs = EF4_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
+
+ /* Possibly one more per segment for the alignment workaround,
+ * or for option descriptors
+ */
+ if (EF4_WORKAROUND_5391(efx))
+ max_descs += EF4_TSO_MAX_SEGS;
+
+ /* Possibly more for PCIe page boundaries within input fragments */
+ if (PAGE_SIZE > EF4_PAGE_SIZE)
+ max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
+ DIV_ROUND_UP(GSO_MAX_SIZE, EF4_PAGE_SIZE));
+
+ return max_descs;
+}
+
+static void ef4_tx_maybe_stop_queue(struct ef4_tx_queue *txq1)
+{
+ /* We need to consider both queues that the net core sees as one */
+ struct ef4_tx_queue *txq2 = ef4_tx_queue_partner(txq1);
+ struct ef4_nic *efx = txq1->efx;
+ unsigned int fill_level;
+
+ fill_level = max(txq1->insert_count - txq1->old_read_count,
+ txq2->insert_count - txq2->old_read_count);
+ if (likely(fill_level < efx->txq_stop_thresh))
+ return;
+
+ /* We used the stale old_read_count above, which gives us a
+ * pessimistic estimate of the fill level (which may even
+ * validly be >= efx->txq_entries). Now try again using
+ * read_count (more likely to be a cache miss).
+ *
+ * If we read read_count and then conditionally stop the
+ * queue, it is possible for the completion path to race with
+ * us and complete all outstanding descriptors in the middle,
+ * after which there will be no more completions to wake it.
+ * Therefore we stop the queue first, then read read_count
+ * (with a memory barrier to ensure the ordering), then
+ * restart the queue if the fill level turns out to be low
+ * enough.
+ */
+ netif_tx_stop_queue(txq1->core_txq);
+ smp_mb();
+ txq1->old_read_count = ACCESS_ONCE(txq1->read_count);
+ txq2->old_read_count = ACCESS_ONCE(txq2->read_count);
+
+ fill_level = max(txq1->insert_count - txq1->old_read_count,
+ txq2->insert_count - txq2->old_read_count);
+ EF4_BUG_ON_PARANOID(fill_level >= efx->txq_entries);
+ if (likely(fill_level < efx->txq_stop_thresh)) {
+ smp_mb();
+ if (likely(!efx->loopback_selftest))
+ netif_tx_start_queue(txq1->core_txq);
+ }
+}
+
+static int ef4_enqueue_skb_copy(struct ef4_tx_queue *tx_queue,
+ struct sk_buff *skb)
+{
+ unsigned int min_len = tx_queue->tx_min_size;
+ unsigned int copy_len = skb->len;
+ struct ef4_tx_buffer *buffer;
+ u8 *copy_buffer;
+ int rc;
+
+ EF4_BUG_ON_PARANOID(copy_len > EF4_TX_CB_SIZE);
+
+ buffer = ef4_tx_queue_get_insert_buffer(tx_queue);
+
+ copy_buffer = ef4_tx_get_copy_buffer(tx_queue, buffer);
+ if (unlikely(!copy_buffer))
+ return -ENOMEM;
+
+ rc = skb_copy_bits(skb, 0, copy_buffer, copy_len);
+ EF4_WARN_ON_PARANOID(rc);
+ if (unlikely(copy_len < min_len)) {
+ memset(copy_buffer + copy_len, 0, min_len - copy_len);
+ buffer->len = min_len;
+ } else {
+ buffer->len = copy_len;
+ }
+
+ buffer->skb = skb;
+ buffer->flags = EF4_TX_BUF_SKB;
+
+ ++tx_queue->insert_count;
+ return rc;
+}
+
+static struct ef4_tx_buffer *ef4_tx_map_chunk(struct ef4_tx_queue *tx_queue,
+ dma_addr_t dma_addr,
+ size_t len)
+{
+ const struct ef4_nic_type *nic_type = tx_queue->efx->type;
+ struct ef4_tx_buffer *buffer;
+ unsigned int dma_len;
+
+ /* Map the fragment taking account of NIC-dependent DMA limits. */
+ do {
+ buffer = ef4_tx_queue_get_insert_buffer(tx_queue);
+ dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len);
+
+ buffer->len = dma_len;
+ buffer->dma_addr = dma_addr;
+ buffer->flags = EF4_TX_BUF_CONT;
+ len -= dma_len;
+ dma_addr += dma_len;
+ ++tx_queue->insert_count;
+ } while (len);
+
+ return buffer;
+}
+
+/* Map all data from an SKB for DMA and create descriptors on the queue.
+ */
+static int ef4_tx_map_data(struct ef4_tx_queue *tx_queue, struct sk_buff *skb)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ struct device *dma_dev = &efx->pci_dev->dev;
+ unsigned int frag_index, nr_frags;
+ dma_addr_t dma_addr, unmap_addr;
+ unsigned short dma_flags;
+ size_t len, unmap_len;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ frag_index = 0;
+
+ /* Map header data. */
+ len = skb_headlen(skb);
+ dma_addr = dma_map_single(dma_dev, skb->data, len, DMA_TO_DEVICE);
+ dma_flags = EF4_TX_BUF_MAP_SINGLE;
+ unmap_len = len;
+ unmap_addr = dma_addr;
+
+ if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
+ return -EIO;
+
+ /* Add descriptors for each fragment. */
+ do {
+ struct ef4_tx_buffer *buffer;
+ skb_frag_t *fragment;
+
+ buffer = ef4_tx_map_chunk(tx_queue, dma_addr, len);
+
+ /* The final descriptor for a fragment is responsible for
+ * unmapping the whole fragment.
+ */
+ buffer->flags = EF4_TX_BUF_CONT | dma_flags;
+ buffer->unmap_len = unmap_len;
+ buffer->dma_offset = buffer->dma_addr - unmap_addr;
+
+ if (frag_index >= nr_frags) {
+ /* Store SKB details with the final buffer for
+ * the completion.
+ */
+ buffer->skb = skb;
+ buffer->flags = EF4_TX_BUF_SKB | dma_flags;
+ return 0;
+ }
+
+ /* Move on to the next fragment. */
+ fragment = &skb_shinfo(skb)->frags[frag_index++];
+ len = skb_frag_size(fragment);
+ dma_addr = skb_frag_dma_map(dma_dev, fragment,
+ 0, len, DMA_TO_DEVICE);
+ dma_flags = 0;
+ unmap_len = len;
+ unmap_addr = dma_addr;
+
+ if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
+ return -EIO;
+ } while (1);
+}
+
+/* Remove buffers put into a tx_queue. None of the buffers must have
+ * an skb attached.
+ */
+static void ef4_enqueue_unwind(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_tx_buffer *buffer;
+
+ /* Work backwards until we hit the original insert pointer value */
+ while (tx_queue->insert_count != tx_queue->write_count) {
+ --tx_queue->insert_count;
+ buffer = __ef4_tx_queue_get_insert_buffer(tx_queue);
+ ef4_dequeue_buffer(tx_queue, buffer, NULL, NULL);
+ }
+}
+
+/*
+ * Add a socket buffer to a TX queue
+ *
+ * This maps all fragments of a socket buffer for DMA and adds them to
+ * the TX queue. The queue's insert pointer will be incremented by
+ * the number of fragments in the socket buffer.
+ *
+ * If any DMA mapping fails, any mapped fragments will be unmapped,
+ * the queue's insert pointer will be restored to its original value.
+ *
+ * This function is split out from ef4_hard_start_xmit to allow the
+ * loopback test to direct packets via specific TX queues.
+ *
+ * Returns NETDEV_TX_OK.
+ * You must hold netif_tx_lock() to call this function.
+ */
+netdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb)
+{
+ bool data_mapped = false;
+ unsigned int skb_len;
+
+ skb_len = skb->len;
+ EF4_WARN_ON_PARANOID(skb_is_gso(skb));
+
+ if (skb_len < tx_queue->tx_min_size ||
+ (skb->data_len && skb_len <= EF4_TX_CB_SIZE)) {
+ /* Pad short packets or coalesce short fragmented packets. */
+ if (ef4_enqueue_skb_copy(tx_queue, skb))
+ goto err;
+ tx_queue->cb_packets++;
+ data_mapped = true;
+ }
+
+ /* Map for DMA and create descriptors if we haven't done so already. */
+ if (!data_mapped && (ef4_tx_map_data(tx_queue, skb)))
+ goto err;
+
+ /* Update BQL */
+ netdev_tx_sent_queue(tx_queue->core_txq, skb_len);
+
+ /* Pass off to hardware */
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+ struct ef4_tx_queue *txq2 = ef4_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)
+ ef4_nic_push_buffers(txq2);
+
+ ef4_nic_push_buffers(tx_queue);
+ } else {
+ tx_queue->xmit_more_available = skb->xmit_more;
+ }
+
+ tx_queue->tx_packets++;
+
+ ef4_tx_maybe_stop_queue(tx_queue);
+
+ return NETDEV_TX_OK;
+
+
+err:
+ ef4_enqueue_unwind(tx_queue);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+/* Remove packets from the TX queue
+ *
+ * This removes packets from the TX queue, up to and including the
+ * specified index.
+ */
+static void ef4_dequeue_buffers(struct ef4_tx_queue *tx_queue,
+ unsigned int index,
+ unsigned int *pkts_compl,
+ unsigned int *bytes_compl)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ unsigned int stop_index, read_ptr;
+
+ stop_index = (index + 1) & tx_queue->ptr_mask;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
+
+ while (read_ptr != stop_index) {
+ struct ef4_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
+
+ if (!(buffer->flags & EF4_TX_BUF_OPTION) &&
+ unlikely(buffer->len == 0)) {
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX queue %d spurious TX completion id %x\n",
+ tx_queue->queue, read_ptr);
+ ef4_schedule_reset(efx, RESET_TYPE_TX_SKIP);
+ return;
+ }
+
+ ef4_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl);
+
+ ++tx_queue->read_count;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
+ }
+}
+
+/* Initiate a packet transmission. We use one channel per CPU
+ * (sharing when we have more CPUs than channels). On Falcon, the TX
+ * completion events will be directed back to the CPU that transmitted
+ * the packet, which should be cache-efficient.
+ *
+ * Context: non-blocking.
+ * Note that returning anything other than NETDEV_TX_OK will cause the
+ * OS to free the skb.
+ */
+netdev_tx_t ef4_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_tx_queue *tx_queue;
+ unsigned index, type;
+
+ EF4_WARN_ON_PARANOID(!netif_device_present(net_dev));
+
+ index = skb_get_queue_mapping(skb);
+ type = skb->ip_summed == CHECKSUM_PARTIAL ? EF4_TXQ_TYPE_OFFLOAD : 0;
+ if (index >= efx->n_tx_channels) {
+ index -= efx->n_tx_channels;
+ type |= EF4_TXQ_TYPE_HIGHPRI;
+ }
+ tx_queue = ef4_get_tx_queue(efx, index, type);
+
+ return ef4_enqueue_skb(tx_queue, skb);
+}
+
+void ef4_init_tx_queue_core_txq(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+
+ /* Must be inverse of queue lookup in ef4_hard_start_xmit() */
+ tx_queue->core_txq =
+ netdev_get_tx_queue(efx->net_dev,
+ tx_queue->queue / EF4_TXQ_TYPES +
+ ((tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI) ?
+ efx->n_tx_channels : 0));
+}
+
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
+ struct tc_to_netdev *ntc)
+{
+ struct ef4_nic *efx = netdev_priv(net_dev);
+ struct ef4_channel *channel;
+ struct ef4_tx_queue *tx_queue;
+ unsigned tc, num_tc;
+ int rc;
+
+ if (ntc->type != TC_SETUP_MQPRIO)
+ return -EINVAL;
+
+ num_tc = ntc->tc;
+
+ if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0 || num_tc > EF4_MAX_TX_TC)
+ return -EINVAL;
+
+ if (num_tc == net_dev->num_tc)
+ return 0;
+
+ for (tc = 0; tc < num_tc; tc++) {
+ net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
+ net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+ }
+
+ if (num_tc > net_dev->num_tc) {
+ /* Initialise high-priority queues as necessary */
+ ef4_for_each_channel(channel, efx) {
+ ef4_for_each_possible_channel_tx_queue(tx_queue,
+ channel) {
+ if (!(tx_queue->queue & EF4_TXQ_TYPE_HIGHPRI))
+ continue;
+ if (!tx_queue->buffer) {
+ rc = ef4_probe_tx_queue(tx_queue);
+ if (rc)
+ return rc;
+ }
+ if (!tx_queue->initialised)
+ ef4_init_tx_queue(tx_queue);
+ ef4_init_tx_queue_core_txq(tx_queue);
+ }
+ }
+ } else {
+ /* Reduce number of classes before number of queues */
+ net_dev->num_tc = num_tc;
+ }
+
+ rc = netif_set_real_num_tx_queues(net_dev,
+ max_t(int, num_tc, 1) *
+ efx->n_tx_channels);
+ if (rc)
+ return rc;
+
+ /* Do not destroy high-priority queues when they become
+ * unused. We would have to flush them first, and it is
+ * fairly difficult to flush a subset of TX queues. Leave
+ * it to ef4_fini_channels().
+ */
+
+ net_dev->num_tc = num_tc;
+ return 0;
+}
+
+void ef4_xmit_done(struct ef4_tx_queue *tx_queue, unsigned int index)
+{
+ unsigned fill_level;
+ struct ef4_nic *efx = tx_queue->efx;
+ struct ef4_tx_queue *txq2;
+ unsigned int pkts_compl = 0, bytes_compl = 0;
+
+ EF4_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
+
+ ef4_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
+ tx_queue->pkts_compl += pkts_compl;
+ tx_queue->bytes_compl += bytes_compl;
+
+ if (pkts_compl > 1)
+ ++tx_queue->merge_events;
+
+ /* See if we need to restart the netif queue. This memory
+ * barrier ensures that we write read_count (inside
+ * ef4_dequeue_buffers()) before reading the queue status.
+ */
+ smp_mb();
+ if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
+ likely(efx->port_enabled) &&
+ likely(netif_device_present(efx->net_dev))) {
+ txq2 = ef4_tx_queue_partner(tx_queue);
+ fill_level = max(tx_queue->insert_count - tx_queue->read_count,
+ txq2->insert_count - txq2->read_count);
+ if (fill_level <= efx->txq_wake_thresh)
+ netif_tx_wake_queue(tx_queue->core_txq);
+ }
+
+ /* Check whether the hardware queue is now empty */
+ if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
+ tx_queue->old_write_count = ACCESS_ONCE(tx_queue->write_count);
+ if (tx_queue->read_count == tx_queue->old_write_count) {
+ smp_mb();
+ tx_queue->empty_read_count =
+ tx_queue->read_count | EF4_EMPTY_COUNT_VALID;
+ }
+ }
+}
+
+static unsigned int ef4_tx_cb_page_count(struct ef4_tx_queue *tx_queue)
+{
+ return DIV_ROUND_UP(tx_queue->ptr_mask + 1, PAGE_SIZE >> EF4_TX_CB_ORDER);
+}
+
+int ef4_probe_tx_queue(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+ unsigned int entries;
+ int rc;
+
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->txq_entries), EF4_MIN_DMAQ_SIZE);
+ EF4_BUG_ON_PARANOID(entries > EF4_MAX_DMAQ_SIZE);
+ tx_queue->ptr_mask = entries - 1;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "creating TX queue %d size %#x mask %#x\n",
+ tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask);
+
+ /* Allocate software ring */
+ tx_queue->buffer = kcalloc(entries, sizeof(*tx_queue->buffer),
+ GFP_KERNEL);
+ if (!tx_queue->buffer)
+ return -ENOMEM;
+
+ tx_queue->cb_page = kcalloc(ef4_tx_cb_page_count(tx_queue),
+ sizeof(tx_queue->cb_page[0]), GFP_KERNEL);
+ if (!tx_queue->cb_page) {
+ rc = -ENOMEM;
+ goto fail1;
+ }
+
+ /* Allocate hardware ring */
+ rc = ef4_nic_probe_tx(tx_queue);
+ if (rc)
+ goto fail2;
+
+ return 0;
+
+fail2:
+ kfree(tx_queue->cb_page);
+ tx_queue->cb_page = NULL;
+fail1:
+ kfree(tx_queue->buffer);
+ tx_queue->buffer = NULL;
+ return rc;
+}
+
+void ef4_init_tx_queue(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_nic *efx = tx_queue->efx;
+
+ netif_dbg(efx, drv, efx->net_dev,
+ "initialising TX queue %d\n", tx_queue->queue);
+
+ tx_queue->insert_count = 0;
+ tx_queue->write_count = 0;
+ tx_queue->old_write_count = 0;
+ tx_queue->read_count = 0;
+ tx_queue->old_read_count = 0;
+ tx_queue->empty_read_count = 0 | EF4_EMPTY_COUNT_VALID;
+ tx_queue->xmit_more_available = false;
+
+ /* Some older hardware requires Tx writes larger than 32. */
+ tx_queue->tx_min_size = EF4_WORKAROUND_15592(efx) ? 33 : 0;
+
+ /* Set up TX descriptor ring */
+ ef4_nic_init_tx(tx_queue);
+
+ tx_queue->initialised = true;
+}
+
+void ef4_fini_tx_queue(struct ef4_tx_queue *tx_queue)
+{
+ struct ef4_tx_buffer *buffer;
+
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "shutting down TX queue %d\n", tx_queue->queue);
+
+ if (!tx_queue->buffer)
+ return;
+
+ /* Free any buffers left in the ring */
+ while (tx_queue->read_count != tx_queue->write_count) {
+ unsigned int pkts_compl = 0, bytes_compl = 0;
+ buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
+ ef4_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
+
+ ++tx_queue->read_count;
+ }
+ tx_queue->xmit_more_available = false;
+ netdev_tx_reset_queue(tx_queue->core_txq);
+}
+
+void ef4_remove_tx_queue(struct ef4_tx_queue *tx_queue)
+{
+ int i;
+
+ if (!tx_queue->buffer)
+ return;
+
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "destroying TX queue %d\n", tx_queue->queue);
+ ef4_nic_remove_tx(tx_queue);
+
+ if (tx_queue->cb_page) {
+ for (i = 0; i < ef4_tx_cb_page_count(tx_queue); i++)
+ ef4_nic_free_buffer(tx_queue->efx,
+ &tx_queue->cb_page[i]);
+ kfree(tx_queue->cb_page);
+ tx_queue->cb_page = NULL;
+ }
+
+ kfree(tx_queue->buffer);
+ tx_queue->buffer = NULL;
+}
diff --git a/drivers/net/ethernet/sfc/falcon/tx.h b/drivers/net/ethernet/sfc/falcon/tx.h
new file mode 100644
index 000000000000..a607eb0087a8
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/tx.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2015 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_TX_H
+#define EF4_TX_H
+
+#include <linux/types.h>
+
+/* Driver internal tx-path related declarations. */
+
+unsigned int ef4_tx_limit_len(struct ef4_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
+
+u8 *ef4_tx_get_copy_buffer_limited(struct ef4_tx_queue *tx_queue,
+ struct ef4_tx_buffer *buffer, size_t len);
+
+int ef4_enqueue_skb_tso(struct ef4_tx_queue *tx_queue, struct sk_buff *skb,
+ bool *data_mapped);
+
+#endif /* EF4_TX_H */
diff --git a/drivers/net/ethernet/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/falcon/txc43128_phy.c
index 194f67d9f3bf..18421f5e880f 100644
--- a/drivers/net/ethernet/sfc/txc43128_phy.c
+++ b/drivers/net/ethernet/sfc/falcon/txc43128_phy.c
@@ -158,8 +158,8 @@
struct txc43128_data {
unsigned long bug10934_timer;
- enum efx_phy_mode phy_mode;
- enum efx_loopback_mode loopback_mode;
+ enum ef4_phy_mode phy_mode;
+ enum ef4_loopback_mode loopback_mode;
};
/* The PHY sometimes needs a reset to bring the link back up. So long as
@@ -168,32 +168,32 @@ struct txc43128_data {
#define BUG10934_RESET_INTERVAL (5 * HZ)
/* Perform a reset that doesn't clear configuration changes */
-static void txc_reset_logic(struct efx_nic *efx);
+static void txc_reset_logic(struct ef4_nic *efx);
/* Set the output value of a gpio */
-void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
+void falcon_txc_set_gpio_val(struct ef4_nic *efx, int pin, int on)
{
- efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
+ ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
}
/* Set up the GPIO direction register */
-void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
+void falcon_txc_set_gpio_dir(struct ef4_nic *efx, int pin, int dir)
{
- efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
+ ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
}
/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
* global reset (it's less clear what reset of other MMDs does).*/
-static int txc_reset_phy(struct efx_nic *efx)
+static int txc_reset_phy(struct ef4_nic *efx)
{
- int rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
+ int rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
TXC_RESET_WAIT);
if (rc < 0)
goto fail;
/* Check that all the MMDs we expect are present and responding. */
- rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS);
+ rc = ef4_mdio_check_mmds(efx, TXC_REQUIRED_DEVS);
if (rc < 0)
goto fail;
@@ -205,28 +205,28 @@ fail:
}
/* Run a single BIST on one MMD */
-static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
+static int txc_bist_one(struct ef4_nic *efx, int mmd, int test)
{
int ctrl, bctl;
int lane;
int rc = 0;
/* Set PMA to test into loopback using Mt Diablo reg as per app note */
- ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
+ ctrl = ef4_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
- efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+ ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
/* The BIST app. note lists these as 3 distinct steps. */
/* Set the BIST type */
bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
- efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+ ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
/* Set the BSTEN bit in the BIST Control register to enable */
bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
- efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+ ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
/* Set the BSTRT bit in the BIST Control register */
- efx_mdio_write(efx, mmd, TXC_BIST_CTL,
+ ef4_mdio_write(efx, mmd, TXC_BIST_CTL,
bctl | (1 << TXC_BIST_CTRL_STRT_LBN));
/* Wait. */
@@ -234,22 +234,22 @@ static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
/* Set the BSTOP bit in the BIST Control register */
bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
- efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+ ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
/* The STOP bit should go off when things have stopped */
while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
- bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL);
+ bctl = ef4_mdio_read(efx, mmd, TXC_BIST_CTL);
/* Check all the error counts are 0 and all the frame counts are
non-zero */
for (lane = 0; lane < 4; lane++) {
- int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
+ int count = ef4_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
if (count != 0) {
netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
"Lane %d had %d errs\n", lane, count);
rc = -EIO;
}
- count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
+ count = ef4_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
if (count == 0) {
netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
"Lane %d got 0 frames\n", lane);
@@ -261,23 +261,23 @@ static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n");
/* Disable BIST */
- efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0);
+ ef4_mdio_write(efx, mmd, TXC_BIST_CTL, 0);
/* Turn off loopback */
ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
- efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+ ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
return rc;
}
-static int txc_bist(struct efx_nic *efx)
+static int txc_bist(struct ef4_nic *efx)
{
return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
}
/* Push the non-configurable defaults into the PHY. This must be
* done after every full reset */
-static void txc_apply_defaults(struct efx_nic *efx)
+static void txc_apply_defaults(struct ef4_nic *efx)
{
int mctrl;
@@ -287,33 +287,33 @@ static void txc_apply_defaults(struct efx_nic *efx)
* saves a picowatt or two */
/* Turn off preemphasis */
- efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
- efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
+ ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
+ ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
/* Turn down the amplitude */
- efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ ef4_mdio_write(efx, MDIO_MMD_PHYXS,
TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
- efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ ef4_mdio_write(efx, MDIO_MMD_PHYXS,
TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
/* Set the line side amplitude and preemphasis to the databook
* defaults as an erratum causes them to be 0 on at least some
* PHY rev.s */
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
/* Set up the LEDs */
- mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);
+ mctrl = ef4_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);
/* Set the Green and Red LEDs to their default modes */
mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
- efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
+ ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
/* Databook recommends doing this after configuration changes */
txc_reset_logic(efx);
@@ -321,7 +321,7 @@ static void txc_apply_defaults(struct efx_nic *efx)
falcon_board(efx)->type->init_phy(efx);
}
-static int txc43128_phy_probe(struct efx_nic *efx)
+static int txc43128_phy_probe(struct ef4_nic *efx)
{
struct txc43128_data *phy_data;
@@ -341,7 +341,7 @@ static int txc43128_phy_probe(struct efx_nic *efx)
}
/* Initialisation entry point for this PHY driver */
-static int txc43128_phy_init(struct efx_nic *efx)
+static int txc43128_phy_init(struct ef4_nic *efx)
{
int rc;
@@ -359,28 +359,28 @@ static int txc43128_phy_init(struct efx_nic *efx)
}
/* Set the lane power down state in the global registers */
-static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
+static void txc_glrgs_lane_power(struct ef4_nic *efx, int mmd)
{
int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
- int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ int ctl = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
if (!(efx->phy_mode & PHY_MODE_LOW_POWER))
ctl &= ~pd;
else
ctl |= pd;
- efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
+ ef4_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
}
/* Set the lane power down state in the analog control registers */
-static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
+static void txc_analog_lane_power(struct ef4_nic *efx, int mmd)
{
int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
| (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN)
| (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN);
- int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
- int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);
+ int txctl = ef4_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
+ int rxctl = ef4_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);
if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) {
txctl &= ~txpd;
@@ -390,14 +390,14 @@ static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
rxctl |= rxpd;
}
- efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
- efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
+ ef4_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
+ ef4_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
}
-static void txc_set_power(struct efx_nic *efx)
+static void txc_set_power(struct ef4_nic *efx)
{
/* According to the data book, all the MMDs can do low power */
- efx_mdio_set_mmds_lpower(efx,
+ ef4_mdio_set_mmds_lpower(efx,
!!(efx->phy_mode & PHY_MODE_LOW_POWER),
TXC_REQUIRED_DEVS);
@@ -411,15 +411,15 @@ static void txc_set_power(struct efx_nic *efx)
txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
}
-static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
+static void txc_reset_logic_mmd(struct ef4_nic *efx, int mmd)
{
- int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ int val = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
int tries = 50;
val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
- efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
+ ef4_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
while (--tries) {
- val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ val = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
break;
udelay(1);
@@ -431,7 +431,7 @@ static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
/* Perform a logic reset. This preserves the configuration registers
* and is needed for some configuration changes to take effect */
-static void txc_reset_logic(struct efx_nic *efx)
+static void txc_reset_logic(struct ef4_nic *efx)
{
/* The data sheet claims we can do the logic reset on either the
* PCS or the PHYXS and the result is a reset of both host- and
@@ -439,15 +439,15 @@ static void txc_reset_logic(struct efx_nic *efx)
txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
}
-static bool txc43128_phy_read_link(struct efx_nic *efx)
+static bool txc43128_phy_read_link(struct ef4_nic *efx)
{
- return efx_mdio_links_ok(efx, TXC_REQUIRED_DEVS);
+ return ef4_mdio_links_ok(efx, TXC_REQUIRED_DEVS);
}
-static int txc43128_phy_reconfigure(struct efx_nic *efx)
+static int txc43128_phy_reconfigure(struct ef4_nic *efx)
{
struct txc43128_data *phy_data = efx->phy_data;
- enum efx_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode;
+ enum ef4_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode;
bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) {
@@ -457,8 +457,8 @@ static int txc43128_phy_reconfigure(struct efx_nic *efx)
mode_change &= ~PHY_MODE_TX_DISABLED;
}
- efx_mdio_transmit_disable(efx);
- efx_mdio_phy_reconfigure(efx);
+ ef4_mdio_transmit_disable(efx);
+ ef4_mdio_phy_reconfigure(efx);
if (mode_change & PHY_MODE_LOW_POWER)
txc_set_power(efx);
@@ -475,13 +475,13 @@ static int txc43128_phy_reconfigure(struct efx_nic *efx)
return 0;
}
-static void txc43128_phy_fini(struct efx_nic *efx)
+static void txc43128_phy_fini(struct ef4_nic *efx)
{
/* Disable link events */
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
+ ef4_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
}
-static void txc43128_phy_remove(struct efx_nic *efx)
+static void txc43128_phy_remove(struct ef4_nic *efx)
{
kfree(efx->phy_data);
efx->phy_data = NULL;
@@ -489,7 +489,7 @@ static void txc43128_phy_remove(struct efx_nic *efx)
/* Periodic callback: this exists mainly to poll link status as we
* don't use LASI interrupts */
-static bool txc43128_phy_poll(struct efx_nic *efx)
+static bool txc43128_phy_poll(struct ef4_nic *efx)
{
struct txc43128_data *data = efx->phy_data;
bool was_up = efx->link_state.up;
@@ -516,14 +516,14 @@ static const char *const txc43128_test_names[] = {
"bist"
};
-static const char *txc43128_test_name(struct efx_nic *efx, unsigned int index)
+static const char *txc43128_test_name(struct ef4_nic *efx, unsigned int index)
{
if (index < ARRAY_SIZE(txc43128_test_names))
return txc43128_test_names[index];
return NULL;
}
-static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+static int txc43128_run_tests(struct ef4_nic *efx, int *results, unsigned flags)
{
int rc;
@@ -540,12 +540,12 @@ static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags)
return rc;
}
-static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static void txc43128_get_settings(struct ef4_nic *efx, struct ethtool_cmd *ecmd)
{
mdio45_ethtool_gset(&efx->mdio, ecmd);
}
-const struct efx_phy_operations falcon_txc_phy_ops = {
+const struct ef4_phy_operations falcon_txc_phy_ops = {
.probe = txc43128_phy_probe,
.init = txc43128_phy_init,
.reconfigure = txc43128_phy_reconfigure,
@@ -553,8 +553,8 @@ const struct efx_phy_operations falcon_txc_phy_ops = {
.fini = txc43128_phy_fini,
.remove = txc43128_phy_remove,
.get_settings = txc43128_get_settings,
- .set_settings = efx_mdio_set_settings,
- .test_alive = efx_mdio_test_alive,
+ .set_settings = ef4_mdio_set_settings,
+ .test_alive = ef4_mdio_test_alive,
.run_tests = txc43128_run_tests,
.test_name = txc43128_test_name,
};
diff --git a/drivers/net/ethernet/sfc/falcon/workarounds.h b/drivers/net/ethernet/sfc/falcon/workarounds.h
new file mode 100644
index 000000000000..6af800bc9633
--- /dev/null
+++ b/drivers/net/ethernet/sfc/falcon/workarounds.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2006-2013 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EF4_WORKAROUNDS_H
+#define EF4_WORKAROUNDS_H
+
+/*
+ * Hardware workarounds.
+ * Bug numbers are from Solarflare's Bugzilla.
+ */
+
+#define EF4_WORKAROUND_FALCON_A(efx) (ef4_nic_rev(efx) <= EF4_REV_FALCON_A1)
+#define EF4_WORKAROUND_FALCON_AB(efx) (ef4_nic_rev(efx) <= EF4_REV_FALCON_B0)
+#define EF4_WORKAROUND_10G(efx) 1
+
+/* Bit-bashed I2C reads cause performance drop */
+#define EF4_WORKAROUND_7884 EF4_WORKAROUND_10G
+/* Truncated IPv4 packets can confuse the TX packet parser */
+#define EF4_WORKAROUND_15592 EF4_WORKAROUND_FALCON_AB
+
+/* Spurious parity errors in TSORT buffers */
+#define EF4_WORKAROUND_5129 EF4_WORKAROUND_FALCON_A
+/* Unaligned read request >512 bytes after aligning may break TSORT */
+#define EF4_WORKAROUND_5391 EF4_WORKAROUND_FALCON_A
+/* iSCSI parsing errors */
+#define EF4_WORKAROUND_5583 EF4_WORKAROUND_FALCON_A
+/* RX events go missing */
+#define EF4_WORKAROUND_5676 EF4_WORKAROUND_FALCON_A
+/* RX_RESET on A1 */
+#define EF4_WORKAROUND_6555 EF4_WORKAROUND_FALCON_A
+/* Increase filter depth to avoid RX_RESET */
+#define EF4_WORKAROUND_7244 EF4_WORKAROUND_FALCON_A
+/* Flushes may never complete */
+#define EF4_WORKAROUND_7803 EF4_WORKAROUND_FALCON_AB
+/* Leak overlength packets rather than free */
+#define EF4_WORKAROUND_8071 EF4_WORKAROUND_FALCON_A
+
+#endif /* EF4_WORKAROUNDS_H */
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index 4762ec444cb8..e4ca2161af70 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -25,7 +25,7 @@
#include "io.h"
#include "workarounds.h"
-/* Falcon-architecture (SFC4000 and SFC9000-family) support */
+/* Falcon-architecture (SFC9000-family) support */
/**************************************************************************
*
@@ -177,7 +177,7 @@ efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
dma_addr_t dma_addr;
int i;
- EFX_BUG_ON_PARANOID(!buffer->buf.addr);
+ EFX_WARN_ON_PARANOID(!buffer->buf.addr);
/* Write buffer descriptors to NIC */
for (i = 0; i < buffer->entries; i++) {
@@ -332,7 +332,7 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
txd = efx_tx_desc(tx_queue, write_ptr);
++tx_queue->write_count;
- EFX_BUG_ON_PARANOID(buffer->flags & EFX_TX_BUF_OPTION);
+ EFX_WARN_ON_ONCE_PARANOID(buffer->flags & EFX_TX_BUF_OPTION);
/* Create TX descriptor ring entry */
BUILD_BUG_ON(EFX_TX_BUF_CONT != 1);
@@ -356,6 +356,18 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
}
}
+unsigned int efx_farch_tx_limit_len(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len)
+{
+ /* Don't cross 4K boundaries with descriptors. */
+ unsigned int limit = (~dma_addr & (EFX_PAGE_SIZE - 1)) + 1;
+
+ len = min(limit, len);
+
+ return len;
+}
+
+
/* Allocate hardware resources for a TX queue */
int efx_farch_tx_probe(struct efx_tx_queue *tx_queue)
{
@@ -369,6 +381,7 @@ int efx_farch_tx_probe(struct efx_tx_queue *tx_queue)
void efx_farch_tx_init(struct efx_tx_queue *tx_queue)
{
+ int csum = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
struct efx_nic *efx = tx_queue->efx;
efx_oword_t reg;
@@ -390,37 +403,18 @@ void efx_farch_tx_init(struct efx_tx_queue *tx_queue)
FRF_AZ_TX_DESCQ_TYPE, 0,
FRF_BZ_TX_NON_IP_DROP_DIS, 1);
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- int csum = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS,
- !csum);
- }
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS, !csum);
efx_writeo_table(efx, &reg, efx->type->txd_ptr_tbl_base,
tx_queue->queue);
- if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
- /* Only 128 bits in this register */
- BUILD_BUG_ON(EFX_MAX_TX_QUEUES > 128);
-
- efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
- if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
- __clear_bit_le(tx_queue->queue, &reg);
- else
- __set_bit_le(tx_queue->queue, &reg);
- efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
- }
-
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- EFX_POPULATE_OWORD_1(reg,
- FRF_BZ_TX_PACE,
- (tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
- FFE_BZ_TX_PACE_OFF :
- FFE_BZ_TX_PACE_RESERVED);
- efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL,
- tx_queue->queue);
- }
+ EFX_POPULATE_OWORD_1(reg,
+ FRF_BZ_TX_PACE,
+ (tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+ FFE_BZ_TX_PACE_OFF :
+ FFE_BZ_TX_PACE_RESERVED);
+ efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL, tx_queue->queue);
}
static void efx_farch_flush_tx_queue(struct efx_tx_queue *tx_queue)
@@ -517,16 +511,10 @@ void efx_farch_rx_init(struct efx_rx_queue *rx_queue)
{
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
- bool is_b0 = efx_nic_rev(efx) >= EFX_REV_FALCON_B0;
- bool iscsi_digest_en = is_b0;
bool jumbo_en;
- /* For kernel-mode queues in Falcon A1, the JUMBO flag enables
- * DMA to continue after a PCIe page boundary (and scattering
- * is not possible). In Falcon B0 and Siena, it enables
- * scatter.
- */
- jumbo_en = !is_b0 || efx->rx_scatter;
+ /* For kernel-mode queues in Siena, the JUMBO flag enables scatter. */
+ jumbo_en = efx->rx_scatter;
netif_dbg(efx, hw, efx->net_dev,
"RX queue %d ring in special buffers %d-%d\n",
@@ -540,8 +528,8 @@ void efx_farch_rx_init(struct efx_rx_queue *rx_queue)
/* Push RX descriptor ring to card */
EFX_POPULATE_OWORD_10(rx_desc_ptr,
- FRF_AZ_RX_ISCSI_DDIG_EN, iscsi_digest_en,
- FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
+ FRF_AZ_RX_ISCSI_DDIG_EN, true,
+ FRF_AZ_RX_ISCSI_HDIG_EN, true,
FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
FRF_AZ_RX_DESCQ_EVQ_ID,
efx_rx_queue_channel(rx_queue)->channel,
@@ -880,7 +868,7 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
struct efx_nic *efx = rx_queue->efx;
bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
- bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
+ bool rx_ev_frm_trunc, rx_ev_tobe_disc;
bool rx_ev_other_err, rx_ev_pause_frm;
bool rx_ev_hdr_type, rx_ev_mcast_pkt;
unsigned rx_ev_pkt_type;
@@ -897,12 +885,10 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR);
rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_ETH_CRC_ERR);
rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_FRM_TRUNC);
- rx_ev_drib_nib = ((efx_nic_rev(efx) >= EFX_REV_FALCON_B0) ?
- 0 : EFX_QWORD_FIELD(*event, FSF_AA_RX_EV_DRIB_NIB));
rx_ev_pause_frm = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_PAUSE_FRM_ERR);
/* Every error apart from tobe_disc and pause_frm */
- rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
+ rx_ev_other_err = (rx_ev_tcp_udp_chksum_err |
rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
@@ -927,7 +913,7 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
if (rx_ev_other_err && net_ratelimit()) {
netif_dbg(efx, rx_err, efx->net_dev,
" RX queue %d unexpected RX event "
- EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
+ EFX_QWORD_FMT "%s%s%s%s%s%s%s\n",
efx_rx_queue_index(rx_queue), EFX_QWORD_VAL(*event),
rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
rx_ev_ip_hdr_chksum_err ?
@@ -936,14 +922,13 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
" [TCP_UDP_CHKSUM_ERR]" : "",
rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
- rx_ev_drib_nib ? " [DRIB_NIB]" : "",
rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
/* The frame must be discarded if any of these are true. */
- return (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
+ return (rx_ev_eth_crc_err | rx_ev_frm_trunc |
rx_ev_tobe_disc | rx_ev_pause_frm) ?
EFX_RX_PKT_DISCARD : 0;
}
@@ -972,8 +957,7 @@ efx_farch_handle_rx_bad_index(struct efx_rx_queue *rx_queue, unsigned index)
"dropped %d events (index=%d expected=%d)\n",
dropped, index, expected);
- efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
- RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
return false;
}
@@ -1239,10 +1223,7 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
"channel %d seen DRIVER RX_RESET event. "
"Resetting.\n", channel->channel);
atomic_inc(&efx->rx_reset);
- efx_schedule_reset(efx,
- EFX_WORKAROUND_6555(efx) ?
- RESET_TYPE_RX_RECOVERY :
- RESET_TYPE_DISABLE);
+ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
break;
case FSE_BZ_RX_DSC_ERROR_EV:
if (ev_sub_data < EFX_VI_BASE) {
@@ -1379,13 +1360,11 @@ int efx_farch_ev_init(struct efx_channel *channel)
channel->channel, channel->eventq.index,
channel->eventq.index + channel->eventq.entries - 1);
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
- EFX_POPULATE_OWORD_3(reg,
- FRF_CZ_TIMER_Q_EN, 1,
- FRF_CZ_HOST_NOTIFY_MODE, 0,
- FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
- efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
- }
+ EFX_POPULATE_OWORD_3(reg,
+ FRF_CZ_TIMER_Q_EN, 1,
+ FRF_CZ_HOST_NOTIFY_MODE, 0,
+ FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
+ efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
/* Pin event queue buffer */
efx_init_special_buffer(efx, &channel->eventq);
@@ -1413,8 +1392,7 @@ void efx_farch_ev_fini(struct efx_channel *channel)
EFX_ZERO_OWORD(reg);
efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
channel->channel);
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
- efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
+ efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
/* Unpin event queue */
efx_fini_special_buffer(efx, &channel->eventq);
@@ -1488,7 +1466,6 @@ int efx_farch_irq_test_generate(struct efx_nic *efx)
*/
irqreturn_t efx_farch_fatal_interrupt(struct efx_nic *efx)
{
- struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t *int_ker = efx->irq_status.addr;
efx_oword_t fatal_intr;
int error, mem_perr;
@@ -1514,8 +1491,6 @@ irqreturn_t efx_farch_fatal_interrupt(struct efx_nic *efx)
/* Disable both devices */
pci_clear_master(efx->pci_dev);
- if (efx_nic_is_dual_func(efx))
- pci_clear_master(nic_data->pci_dev2);
efx_farch_irq_disable_master(efx);
/* Count errors and reset or disable the NIC accordingly */
@@ -1662,8 +1637,6 @@ void efx_farch_rx_push_indir_table(struct efx_nic *efx)
size_t i = 0;
efx_dword_t dword;
- BUG_ON(efx_nic_rev(efx) < EFX_REV_FALCON_B0);
-
BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
FR_BZ_RX_INDIRECTION_TBL_ROWS);
@@ -1791,8 +1764,7 @@ void efx_farch_init_common(struct efx_nic *efx)
FRF_AZ_ILL_ADR_INT_KER_EN, 1,
FRF_AZ_RBUF_OWN_INT_KER_EN, 1,
FRF_AZ_TBUF_OWN_INT_KER_EN, 1);
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
- EFX_SET_OWORD_FIELD(temp, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 1);
+ EFX_SET_OWORD_FIELD(temp, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 1);
EFX_INVERT_OWORD(temp);
efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
@@ -1812,22 +1784,18 @@ void efx_farch_init_common(struct efx_nic *efx)
/* Disable hardware watchdog which can misfire */
EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
/* Squash TX of packets of 16 bytes or less */
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
- EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
+ EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- EFX_POPULATE_OWORD_4(temp,
- /* Default values */
- FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
- FRF_BZ_TX_PACE_SB_AF, 0xb,
- FRF_BZ_TX_PACE_FB_BASE, 0,
- /* Allow large pace values in the
- * fast bin. */
- FRF_BZ_TX_PACE_BIN_TH,
- FFE_BZ_TX_PACE_RESERVED);
- efx_writeo(efx, &temp, FR_BZ_TX_PACE);
- }
+ EFX_POPULATE_OWORD_4(temp,
+ /* Default values */
+ FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
+ FRF_BZ_TX_PACE_SB_AF, 0xb,
+ FRF_BZ_TX_PACE_FB_BASE, 0,
+ /* Allow large pace values in the fast bin. */
+ FRF_BZ_TX_PACE_BIN_TH,
+ FFE_BZ_TX_PACE_RESERVED);
+ efx_writeo(efx, &temp, FR_BZ_TX_PACE);
}
/**************************************************************************
@@ -2011,7 +1979,7 @@ static void efx_farch_filter_push_rx_config(struct efx_nic *efx)
!!(table->spec[EFX_FARCH_FILTER_INDEX_UC_DEF].flags &
table->spec[EFX_FARCH_FILTER_INDEX_MC_DEF].flags &
EFX_FILTER_FLAG_RX_SCATTER));
- } else if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+ } else {
/* We don't expose 'default' filters because unmatched
* packets always go to the queue number found in the
* RSS table. But we still need to set the RX scatter
@@ -2073,7 +2041,7 @@ efx_farch_filter_from_gen_spec(struct efx_farch_filter_spec *spec,
__be32 rhost, host1, host2;
__be16 rport, port1, port2;
- EFX_BUG_ON_PARANOID(!(gen_spec->flags & EFX_FILTER_FLAG_RX));
+ EFX_WARN_ON_PARANOID(!(gen_spec->flags & EFX_FILTER_FLAG_RX));
if (gen_spec->ether_type != htons(ETH_P_IP))
return -EPROTONOSUPPORT;
@@ -2819,31 +2787,27 @@ int efx_farch_filter_table_probe(struct efx_nic *efx)
return -ENOMEM;
efx->filter_state = state;
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
- table->id = EFX_FARCH_FILTER_TABLE_RX_IP;
- table->offset = FR_BZ_RX_FILTER_TBL0;
- table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
- table->step = FR_BZ_RX_FILTER_TBL0_STEP;
- }
+ table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
+ table->id = EFX_FARCH_FILTER_TABLE_RX_IP;
+ table->offset = FR_BZ_RX_FILTER_TBL0;
+ table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
+ table->step = FR_BZ_RX_FILTER_TBL0_STEP;
- if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
- table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC];
- table->id = EFX_FARCH_FILTER_TABLE_RX_MAC;
- table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
- table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
- table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
-
- table = &state->table[EFX_FARCH_FILTER_TABLE_RX_DEF];
- table->id = EFX_FARCH_FILTER_TABLE_RX_DEF;
- table->size = EFX_FARCH_FILTER_SIZE_RX_DEF;
-
- table = &state->table[EFX_FARCH_FILTER_TABLE_TX_MAC];
- table->id = EFX_FARCH_FILTER_TABLE_TX_MAC;
- table->offset = FR_CZ_TX_MAC_FILTER_TBL0;
- table->size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
- table->step = FR_CZ_TX_MAC_FILTER_TBL0_STEP;
- }
+ table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC];
+ table->id = EFX_FARCH_FILTER_TABLE_RX_MAC;
+ table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
+ table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
+ table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
+
+ table = &state->table[EFX_FARCH_FILTER_TABLE_RX_DEF];
+ table->id = EFX_FARCH_FILTER_TABLE_RX_DEF;
+ table->size = EFX_FARCH_FILTER_SIZE_RX_DEF;
+
+ table = &state->table[EFX_FARCH_FILTER_TABLE_TX_MAC];
+ table->id = EFX_FARCH_FILTER_TABLE_TX_MAC;
+ table->offset = FR_CZ_TX_MAC_FILTER_TBL0;
+ table->size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
+ table->step = FR_CZ_TX_MAC_FILTER_TBL0_STEP;
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
table = &state->table[table_id];
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 241520943ada..995651341b94 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -15,7 +15,6 @@
#include "io.h"
#include "farch_regs.h"
#include "mcdi_pcol.h"
-#include "phy.h"
/**************************************************************************
*
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index c9aeb0701c9a..4472107ca8c1 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -129,14 +129,14 @@ struct efx_mcdi_data {
static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
{
- EFX_BUG_ON_PARANOID(!efx->mcdi);
+ EFX_WARN_ON_PARANOID(!efx->mcdi);
return &efx->mcdi->iface;
}
#ifdef CONFIG_SFC_MCDI_MON
static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
{
- EFX_BUG_ON_PARANOID(!efx->mcdi);
+ EFX_WARN_ON_PARANOID(!efx->mcdi);
return &efx->mcdi->hwmon;
}
#endif
diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c
index bc27d5b580f5..f97da05952c7 100644
--- a/drivers/net/ethernet/sfc/mcdi_mon.c
+++ b/drivers/net/ethernet/sfc/mcdi_mon.c
@@ -121,9 +121,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
}
if (!name)
name = "No sensor name available";
- EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
+ EFX_WARN_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
state_txt = sensor_status_names[state];
- EFX_BUG_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT);
+ EFX_WARN_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT);
unit = efx_hwmon_unit[hwmon_type];
if (!unit)
unit = "";
diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index ccceafc15896..35cc3d4fa5f6 100644
--- a/drivers/net/ethernet/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
@@ -276,6 +276,9 @@
/* The clock whose frequency you've attempted to set set
* doesn't exist on this NIC */
#define MC_CMD_ERR_NO_CLOCK 0x1015
+/* Returned by MC_CMD_TESTASSERT if the action that should
+ * have caused an assertion failed to do so. */
+#define MC_CMD_ERR_UNREACHABLE 0x1016
#define MC_CMD_ERR_CODE_OFST 0
@@ -933,6 +936,8 @@
#define MC_CMD_COPYCODE_IN_BOOT_MAGIC_SKIP_BOOT_ICORE_SYNC_WIDTH 1
#define MC_CMD_COPYCODE_IN_BOOT_MAGIC_FORCE_STANDALONE_LBN 5
#define MC_CMD_COPYCODE_IN_BOOT_MAGIC_FORCE_STANDALONE_WIDTH 1
+#define MC_CMD_COPYCODE_IN_BOOT_MAGIC_DISABLE_XIP_LBN 6
+#define MC_CMD_COPYCODE_IN_BOOT_MAGIC_DISABLE_XIP_WIDTH 1
/* Destination address */
#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4
#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8
@@ -1659,6 +1664,8 @@
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_CAPABILITIES_OFST 8
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_REPORT_SYNC_STATUS_LBN 0
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_REPORT_SYNC_STATUS_WIDTH 1
+#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_RX_TSTAMP_OOB_LBN 1
+#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_RX_TSTAMP_OOB_WIDTH 1
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED0_OFST 12
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED1_OFST 16
#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_OFST 20
@@ -2211,6 +2218,10 @@
#define MC_CMD_FW_HIGH_TX_RATE 0x3
/* enum: Reserved value */
#define MC_CMD_FW_PACKED_STREAM_HASH_MODE_1 0x4
+/* enum: Prefer to use firmware with additional "rules engine" filtering
+ * support
+ */
+#define MC_CMD_FW_RULES_ENGINE 0x5
/* enum: Only this option is allowed for non-admin functions */
#define MC_CMD_FW_DONT_CARE 0xffffffff
@@ -3654,12 +3665,27 @@
#define MC_CMD_0x38_PRIVILEGE_CTG SRIOV_CTG_ADMIN
-/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest */
+/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest: Legacy NVRAM_UPDATE_START request.
+ * Use NVRAM_UPDATE_START_V2_IN in new code
+ */
#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4
#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0
/* Enum values, see field(s): */
/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+/* MC_CMD_NVRAM_UPDATE_START_V2_IN msgrequest: Extended NVRAM_UPDATE_START
+ * request with additional flags indicating version of command in use. See
+ * MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT for details of extended functionality. Use
+ * paired up with NVRAM_UPDATE_FINISH_V2_IN.
+ */
+#define MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN 8
+#define MC_CMD_NVRAM_UPDATE_START_V2_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_UPDATE_START_V2_IN_FLAGS_OFST 4
+#define MC_CMD_NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT_LBN 0
+#define MC_CMD_NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT_WIDTH 1
+
/* MC_CMD_NVRAM_UPDATE_START_OUT msgresponse */
#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0
@@ -3784,16 +3810,81 @@
#define MC_CMD_0x3c_PRIVILEGE_CTG SRIOV_CTG_ADMIN
-/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest */
+/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest: Legacy NVRAM_UPDATE_FINISH
+ * request. Use NVRAM_UPDATE_FINISH_V2_IN in new code
+ */
#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8
#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0
/* Enum values, see field(s): */
/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4
-/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse */
+/* MC_CMD_NVRAM_UPDATE_FINISH_V2_IN msgrequest: Extended NVRAM_UPDATE_FINISH
+ * request with additional flags indicating version of NVRAM_UPDATE commands in
+ * use. See MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT for details of extended
+ * functionality. Use paired up with NVRAM_UPDATE_START_V2_IN.
+ */
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN 12
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_REBOOT_OFST 4
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_FLAGS_OFST 8
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT_LBN 0
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT_WIDTH 1
+
+/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse: Legacy NVRAM_UPDATE_FINISH
+ * response. Use NVRAM_UPDATE_FINISH_V2_OUT in new code
+ */
#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0
+/* MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT msgresponse:
+ *
+ * Extended NVRAM_UPDATE_FINISH response that communicates the result of secure
+ * firmware validation where applicable back to the host.
+ *
+ * Medford only: For signed firmware images, such as those for medford, the MC
+ * firmware verifies the signature before marking the firmware image as valid.
+ * This process takes a few seconds to complete. So is likely to take more than
+ * the MCDI timeout. Hence signature verification is initiated when
+ * MC_CMD_NVRAM_UPDATE_FINISH_V2_IN is received by the firmware, however, the
+ * MCDI command returns immediately with error code EAGAIN. Subsequent
+ * NVRAM_UPDATE_FINISH_V2_IN requests also return EAGAIN if the verification is
+ * in progress. Once the verification has completed, this response payload
+ * includes the results of the signature verification. Note that the nvram lock
+ * in firmware is only released after the verification has completed and the
+ * host has read back the result code from firmware.
+ */
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN 4
+/* Result of nvram update completion processing */
+#define MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE_OFST 0
+/* enum: Verify succeeded without any errors. */
+#define MC_CMD_NVRAM_VERIFY_RC_SUCCESS 0x1
+/* enum: CMS format verification failed due to an internal error. */
+#define MC_CMD_NVRAM_VERIFY_RC_CMS_CHECK_FAILED 0x2
+/* enum: Invalid CMS format in image metadata. */
+#define MC_CMD_NVRAM_VERIFY_RC_INVALID_CMS_FORMAT 0x3
+/* enum: Message digest verification failed due to an internal error. */
+#define MC_CMD_NVRAM_VERIFY_RC_MESSAGE_DIGEST_CHECK_FAILED 0x4
+/* enum: Error in message digest calculated over the reflash-header, payload
+ * and reflash-trailer.
+ */
+#define MC_CMD_NVRAM_VERIFY_RC_BAD_MESSAGE_DIGEST 0x5
+/* enum: Signature verification failed due to an internal error. */
+#define MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHECK_FAILED 0x6
+/* enum: There are no valid signatures in the image. */
+#define MC_CMD_NVRAM_VERIFY_RC_NO_VALID_SIGNATURES 0x7
+/* enum: Trusted approvers verification failed due to an internal error. */
+#define MC_CMD_NVRAM_VERIFY_RC_TRUSTED_APPROVERS_CHECK_FAILED 0x8
+/* enum: The Trusted approver's list is empty. */
+#define MC_CMD_NVRAM_VERIFY_RC_NO_TRUSTED_APPROVERS 0x9
+/* enum: Signature chain verification failed due to an internal error. */
+#define MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHAIN_CHECK_FAILED 0xa
+/* enum: The signers of the signatures in the image are not listed in the
+ * Trusted approver's list.
+ */
+#define MC_CMD_NVRAM_VERIFY_RC_NO_SIGNATURE_MATCH 0xb
+
/***********************************/
/* MC_CMD_REBOOT
@@ -4356,6 +4447,28 @@
/* MC_CMD_TESTASSERT_OUT msgresponse */
#define MC_CMD_TESTASSERT_OUT_LEN 0
+/* MC_CMD_TESTASSERT_V2_IN msgrequest */
+#define MC_CMD_TESTASSERT_V2_IN_LEN 4
+/* How to provoke the assertion */
+#define MC_CMD_TESTASSERT_V2_IN_TYPE_OFST 0
+/* enum: Assert using the FAIL_ASSERTION_WITH_USEFUL_VALUES macro. Unless
+ * you're testing firmware, this is what you want.
+ */
+#define MC_CMD_TESTASSERT_V2_IN_FAIL_ASSERTION_WITH_USEFUL_VALUES 0x0
+/* enum: Assert using assert(0); */
+#define MC_CMD_TESTASSERT_V2_IN_ASSERT_FALSE 0x1
+/* enum: Deliberately trigger a watchdog */
+#define MC_CMD_TESTASSERT_V2_IN_WATCHDOG 0x2
+/* enum: Deliberately trigger a trap by loading from an invalid address */
+#define MC_CMD_TESTASSERT_V2_IN_LOAD_TRAP 0x3
+/* enum: Deliberately trigger a trap by storing to an invalid address */
+#define MC_CMD_TESTASSERT_V2_IN_STORE_TRAP 0x4
+/* enum: Jump to an invalid address */
+#define MC_CMD_TESTASSERT_V2_IN_JUMP_TRAP 0x5
+
+/* MC_CMD_TESTASSERT_V2_OUT msgresponse */
+#define MC_CMD_TESTASSERT_V2_OUT_LEN 0
+
/***********************************/
/* MC_CMD_WORKAROUND
@@ -4421,6 +4534,7 @@
* (GET_PHY_CFG_OUT_MEDIA_TYPE); the valid 'page number' input values, and the
* output data, are interpreted on a per-type basis. For SFP+: PAGE=0 or 1
* returns a 128-byte block read from module I2C address 0xA0 offset 0 or 0x80.
+ * Anything else: currently undefined. Locks required: None. Return code: 0.
*/
#define MC_CMD_GET_PHY_MEDIA_INFO 0x4b
@@ -5362,12 +5476,14 @@
#define NVRAM_PARTITION_TYPE_EXPANSION_UEFI 0xd00
/* enum: Spare partition 0 */
#define NVRAM_PARTITION_TYPE_SPARE_0 0x1000
-/* enum: Spare partition 1 */
-#define NVRAM_PARTITION_TYPE_SPARE_1 0x1100
+/* enum: Used for XIP code of shmbooted images */
+#define NVRAM_PARTITION_TYPE_XIP_SCRATCH 0x1100
/* enum: Spare partition 2 */
#define NVRAM_PARTITION_TYPE_SPARE_2 0x1200
-/* enum: Spare partition 3 */
-#define NVRAM_PARTITION_TYPE_SPARE_3 0x1300
+/* enum: Manufacturing partition. Used during manufacture to pass information
+ * between XJTAG and Manftest.
+ */
+#define NVRAM_PARTITION_TYPE_MANUFACTURING 0x1300
/* enum: Spare partition 4 */
#define NVRAM_PARTITION_TYPE_SPARE_4 0x1400
/* enum: Spare partition 5 */
@@ -5402,6 +5518,14 @@
#define LICENSED_APP_ID_CAPTURE_SOLARSYSTEM 0x40
/* enum: Network Access Control */
#define LICENSED_APP_ID_NETWORK_ACCESS_CONTROL 0x80
+/* enum: TCP Direct */
+#define LICENSED_APP_ID_TCP_DIRECT 0x100
+/* enum: Low Latency */
+#define LICENSED_APP_ID_LOW_LATENCY 0x200
+/* enum: SolarCapture Tap */
+#define LICENSED_APP_ID_SOLARCAPTURE_TAP 0x400
+/* enum: Capture SolarSystem 40G */
+#define LICENSED_APP_ID_CAPTURE_SOLARSYSTEM_40G 0x800
#define LICENSED_APP_ID_ID_LBN 0
#define LICENSED_APP_ID_ID_WIDTH 32
@@ -5458,6 +5582,14 @@
#define LICENSED_V3_APPS_CAPTURE_SOLARSYSTEM_WIDTH 1
#define LICENSED_V3_APPS_NETWORK_ACCESS_CONTROL_LBN 7
#define LICENSED_V3_APPS_NETWORK_ACCESS_CONTROL_WIDTH 1
+#define LICENSED_V3_APPS_TCP_DIRECT_LBN 8
+#define LICENSED_V3_APPS_TCP_DIRECT_WIDTH 1
+#define LICENSED_V3_APPS_LOW_LATENCY_LBN 9
+#define LICENSED_V3_APPS_LOW_LATENCY_WIDTH 1
+#define LICENSED_V3_APPS_SOLARCAPTURE_TAP_LBN 10
+#define LICENSED_V3_APPS_SOLARCAPTURE_TAP_WIDTH 1
+#define LICENSED_V3_APPS_CAPTURE_SOLARSYSTEM_40G_LBN 11
+#define LICENSED_V3_APPS_CAPTURE_SOLARSYSTEM_40G_WIDTH 1
#define LICENSED_V3_APPS_MASK_LBN 0
#define LICENSED_V3_APPS_MASK_WIDTH 64
@@ -5988,6 +6120,8 @@
#define MC_CMD_INIT_TXQ_EXT_IN_FLAG_INNER_TCP_CSUM_EN_WIDTH 1
#define MC_CMD_INIT_TXQ_EXT_IN_FLAG_TSOV2_EN_LBN 12
#define MC_CMD_INIT_TXQ_EXT_IN_FLAG_TSOV2_EN_WIDTH 1
+#define MC_CMD_INIT_TXQ_EXT_IN_FLAG_CTPIO_LBN 13
+#define MC_CMD_INIT_TXQ_EXT_IN_FLAG_CTPIO_WIDTH 1
/* Owner ID to use if in buffer mode (zero if physical) */
#define MC_CMD_INIT_TXQ_EXT_IN_OWNER_ID_OFST 20
/* The port ID associated with the v-adaptor which should contain this DMAQ. */
@@ -7728,6 +7862,8 @@
* tests (Medford development only)
*/
#define MC_CMD_GET_CAPABILITIES_OUT_RXPD_FW_TYPE_LAYER2_PERF 0x7
+/* enum: Rules engine RX PD production firmware */
+#define MC_CMD_GET_CAPABILITIES_OUT_RXPD_FW_TYPE_RULES_ENGINE 0x8
/* enum: RX PD firmware for GUE parsing prototype (Medford development only) */
#define MC_CMD_GET_CAPABILITIES_OUT_RXPD_FW_TYPE_TESTFW_GUE_PROTOTYPE 0xe
/* enum: RX PD firmware parsing but not filtering network overlay tunnel
@@ -7763,6 +7899,8 @@
* tests (Medford development only)
*/
#define MC_CMD_GET_CAPABILITIES_OUT_TXPD_FW_TYPE_LAYER2_PERF 0x7
+/* enum: Rules engine TX PD production firmware */
+#define MC_CMD_GET_CAPABILITIES_OUT_TXPD_FW_TYPE_RULES_ENGINE 0x8
/* enum: RX PD firmware for GUE parsing prototype (Medford development only) */
#define MC_CMD_GET_CAPABILITIES_OUT_TXPD_FW_TYPE_TESTFW_GUE_PROTOTYPE 0xe
/* Hardware capabilities of NIC */
@@ -7913,6 +8051,8 @@
* tests (Medford development only)
*/
#define MC_CMD_GET_CAPABILITIES_V2_OUT_RXPD_FW_TYPE_LAYER2_PERF 0x7
+/* enum: Rules engine RX PD production firmware */
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_RXPD_FW_TYPE_RULES_ENGINE 0x8
/* enum: RX PD firmware for GUE parsing prototype (Medford development only) */
#define MC_CMD_GET_CAPABILITIES_V2_OUT_RXPD_FW_TYPE_TESTFW_GUE_PROTOTYPE 0xe
/* enum: RX PD firmware parsing but not filtering network overlay tunnel
@@ -7948,6 +8088,8 @@
* tests (Medford development only)
*/
#define MC_CMD_GET_CAPABILITIES_V2_OUT_TXPD_FW_TYPE_LAYER2_PERF 0x7
+/* enum: Rules engine TX PD production firmware */
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_TXPD_FW_TYPE_RULES_ENGINE 0x8
/* enum: RX PD firmware for GUE parsing prototype (Medford development only) */
#define MC_CMD_GET_CAPABILITIES_V2_OUT_TXPD_FW_TYPE_TESTFW_GUE_PROTOTYPE 0xe
/* Hardware capabilities of NIC */
@@ -7980,6 +8122,8 @@
#define MC_CMD_GET_CAPABILITIES_V2_OUT_RX_SNIFF_WIDTH 1
#define MC_CMD_GET_CAPABILITIES_V2_OUT_TX_SNIFF_LBN 11
#define MC_CMD_GET_CAPABILITIES_V2_OUT_TX_SNIFF_WIDTH 1
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_NVRAM_UPDATE_REPORT_VERIFY_RESULT_LBN 12
+#define MC_CMD_GET_CAPABILITIES_V2_OUT_NVRAM_UPDATE_REPORT_VERIFY_RESULT_WIDTH 1
/* Number of FATSOv2 contexts per datapath supported by this NIC. Not present
* on older firmware (check the length).
*/
@@ -8247,6 +8391,8 @@
#define MC_CMD_GET_CAPABILITIES_V3_OUT_RX_SNIFF_WIDTH 1
#define MC_CMD_GET_CAPABILITIES_V3_OUT_TX_SNIFF_LBN 11
#define MC_CMD_GET_CAPABILITIES_V3_OUT_TX_SNIFF_WIDTH 1
+#define MC_CMD_GET_CAPABILITIES_V3_OUT_NVRAM_UPDATE_REPORT_VERIFY_RESULT_LBN 12
+#define MC_CMD_GET_CAPABILITIES_V3_OUT_NVRAM_UPDATE_REPORT_VERIFY_RESULT_WIDTH 1
/* Number of FATSOv2 contexts per datapath supported by this NIC. Not present
* on older firmware (check the length).
*/
@@ -8304,7 +8450,7 @@
#define MC_CMD_GET_CAPABILITIES_V3_OUT_SIZE_PIO_BUFF_LEN 2
/* On chips later than Medford the amount of address space assigned to each VI
* is configurable. This is a global setting that the driver must query to
- * discover the VI to address mapping. Cut-through PIO (CTPIO) in not available
+ * discover the VI to address mapping. Cut-through PIO (CTPIO) is not available
* with 8k VI windows.
*/
#define MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_OFST 72
@@ -10283,6 +10429,8 @@
* more data is returned.
*/
#define MC_CMD_PCIE_TUNE_IN_POLL_EYE_PLOT 0x6
+/* enum: Enable the SERDES BIST and set it to generate a 200MHz square wave */
+#define MC_CMD_PCIE_TUNE_IN_BIST_SQUARE_WAVE 0x7
/* Align the arguments to 32 bits */
#define MC_CMD_PCIE_TUNE_IN_PCIE_TUNE_RSVD_OFST 1
#define MC_CMD_PCIE_TUNE_IN_PCIE_TUNE_RSVD_LEN 3
@@ -10468,6 +10616,12 @@
#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MINNUM 0
#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MAXNUM 126
+/* MC_CMD_PCIE_TUNE_BIST_SQUARE_WAVE_IN msgrequest */
+#define MC_CMD_PCIE_TUNE_BIST_SQUARE_WAVE_IN_LEN 0
+
+/* MC_CMD_PCIE_TUNE_BIST_SQUARE_WAVE_OUT msgrequest */
+#define MC_CMD_PCIE_TUNE_BIST_SQUARE_WAVE_OUT_LEN 0
+
/***********************************/
/* MC_CMD_LICENSING
@@ -10783,29 +10937,45 @@
#define MC_CMD_0xd4_PRIVILEGE_CTG SRIOV_CTG_GENERAL
/* MC_CMD_LICENSED_V3_VALIDATE_APP_IN msgrequest */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_LEN 72
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_LEN 56
+/* challenge for validation (384 bits) */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_LEN 48
/* application ID expressed as a single bit mask */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_OFST 48
#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LEN 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LO_OFST 0
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_HI_OFST 4
-/* challenge for validation */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_OFST 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_CHALLENGE_LEN 64
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_LO_OFST 48
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_IN_APP_ID_HI_OFST 52
/* MC_CMD_LICENSED_V3_VALIDATE_APP_OUT msgresponse */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_LEN 72
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_LEN 116
+/* validation response to challenge in the form of ECDSA signature consisting
+ * of two 384-bit integers, r and s, in big-endian order. The signature signs a
+ * SHA-384 digest of a message constructed from the concatenation of the input
+ * message and the remaining fields of this output message, e.g. challenge[48
+ * bytes] ... expiry_time[4 bytes] ...
+ */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_LEN 96
/* application expiry time */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_TIME_OFST 0
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_TIME_OFST 96
/* application expiry units */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNITS_OFST 4
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNITS_OFST 100
/* enum: expiry units are accounting units */
#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNIT_ACC 0x0
/* enum: expiry units are calendar days */
#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_EXPIRY_UNIT_DAYS 0x1
-/* validation response to challenge */
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_OFST 8
-#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_RESPONSE_LEN 64
+/* base MAC address of the NIC stored in NVRAM (note that this is a constant
+ * value for a given NIC regardless which function is calling, effectively this
+ * is PF0 base MAC address)
+ */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_BASE_MACADDR_OFST 104
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_BASE_MACADDR_LEN 6
+/* MAC address of v-adaptor associated with the client. If no such v-adapator
+ * exists, then the field is filled with 0xFF.
+ */
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_VADAPTOR_MACADDR_OFST 110
+#define MC_CMD_LICENSED_V3_VALIDATE_APP_OUT_VADAPTOR_MACADDR_LEN 6
/***********************************/
@@ -10835,6 +11005,70 @@
/***********************************/
+/* MC_CMD_LICENSING_V3_TEMPORARY
+ * Perform operations to support installation of a single temporary license in
+ * the adapter, in addition to those found in the licensing partition. See
+ * SF-116124-SW for an overview of how this could be used. The license is
+ * stored in MC persistent data and so will survive a MC reboot, but will be
+ * erased when the adapter is power cycled
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY 0xd6
+
+#define MC_CMD_0xd6_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_LEN 4
+/* operation code */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_OP_OFST 0
+/* enum: install a new license, overwriting any existing temporary license.
+ * This is an asynchronous operation owing to the time taken to validate an
+ * ECDSA license
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_SET 0x0
+/* enum: clear the license immediately rather than waiting for the next power
+ * cycle
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_CLEAR 0x1
+/* enum: get the status of the asynchronous MC_CMD_LICENSING_V3_TEMPORARY_SET
+ * operation
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS 0x2
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_SET msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LEN 164
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_OP_OFST 0
+/* ECDSA license and signature */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LICENSE_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_SET_LICENSE_LEN 160
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR_LEN 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_CLEAR_OP_OFST 0
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS msgrequest */
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS_LEN 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_IN_STATUS_OP_OFST 0
+
+/* MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS msgresponse */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LEN 12
+/* status code */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_STATUS_OFST 0
+/* enum: finished validating and installing license */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_OK 0x0
+/* enum: license validation and installation in progress */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_IN_PROGRESS 0x1
+/* enum: licensing error. More specific error messages are not provided to
+ * avoid exposing details of the licensing system to the client
+ */
+#define MC_CMD_LICENSING_V3_TEMPORARY_STATUS_ERROR 0x2
+/* bitmask of licensed features */
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_LEN 8
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_LO_OFST 4
+#define MC_CMD_LICENSING_V3_TEMPORARY_OUT_STATUS_LICENSED_FEATURES_HI_OFST 8
+
+
+/***********************************/
/* MC_CMD_SET_PORT_SNIFF_CONFIG
* Configure RX port sniffing for the physical port associated with the calling
* function. Only a privileged function may change the port sniffing
@@ -11705,6 +11939,66 @@
/* MC_CMD_RX_BALANCING_OUT msgresponse */
#define MC_CMD_RX_BALANCING_OUT_LEN 0
+
+/***********************************/
+/* MC_CMD_NVRAM_PRIVATE_APPEND
+ * Append a single TLV to the MC_USAGE_TLV partition. Returns MC_CMD_ERR_EEXIST
+ * if the tag is already present.
+ */
+#define MC_CMD_NVRAM_PRIVATE_APPEND 0x11c
+
+#define MC_CMD_0x11c_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_NVRAM_PRIVATE_APPEND_IN msgrequest */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENMIN 9
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENMAX 252
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LEN(num) (8+1*(num))
+/* The tag to be appended */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_TAG_OFST 0
+/* The length of the data */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_LENGTH_OFST 4
+/* The data to be contained in the TLV structure */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_OFST 8
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_LEN 1
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_MINNUM 1
+#define MC_CMD_NVRAM_PRIVATE_APPEND_IN_DATA_BUFFER_MAXNUM 244
+
+/* MC_CMD_NVRAM_PRIVATE_APPEND_OUT msgresponse */
+#define MC_CMD_NVRAM_PRIVATE_APPEND_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_XPM_VERIFY_CONTENTS
+ * Verify that the contents of the XPM memory is correct (Medford only). This
+ * is used during manufacture to check that the XPM memory has been programmed
+ * correctly at ATE.
+ */
+#define MC_CMD_XPM_VERIFY_CONTENTS 0x11b
+
+#define MC_CMD_0x11b_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_XPM_VERIFY_CONTENTS_IN msgrequest */
+#define MC_CMD_XPM_VERIFY_CONTENTS_IN_LEN 4
+/* Data type to be checked */
+#define MC_CMD_XPM_VERIFY_CONTENTS_IN_DATA_TYPE_OFST 0
+
+/* MC_CMD_XPM_VERIFY_CONTENTS_OUT msgresponse */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LENMIN 12
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LENMAX 252
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_LEN(num) (12+1*(num))
+/* Number of sectors found (test builds only) */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_NUM_SECTORS_OFST 0
+/* Number of bytes found (test builds only) */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_NUM_BYTES_OFST 4
+/* Length of signature */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIG_LENGTH_OFST 8
+/* Signature */
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_OFST 12
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_LEN 1
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_MINNUM 0
+#define MC_CMD_XPM_VERIFY_CONTENTS_OUT_SIGNATURE_MAXNUM 240
+
+
/***********************************/
/* MC_CMD_SET_EVQ_TMR
* Update the timer load, timer reload and timer mode values for a given EVQ.
@@ -11798,4 +12092,151 @@
*/
#define MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_STEP_OFST 32
+
+/***********************************/
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP
+ * When we use the TX_vFIFO_ULL mode, we can allocate common pools using the
+ * non used switch buffers.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP 0x11d
+
+#define MC_CMD_0x11d_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_IN msgrequest */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_LEN 20
+/* Desired instance. Must be set to a specific instance, which is a function
+ * local queue index.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_INSTANCE_OFST 0
+/* Will the common pool be used as TX_vFIFO_ULL (1) */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_MODE_OFST 4
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_ENABLED 0x1 /* enum */
+/* enum: Using this interface without TX_vFIFO_ULL is not supported for now */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_DISABLED 0x0
+/* Number of buffers to reserve for the common pool */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_SIZE_OFST 8
+/* TX datapath to which the Common Pool is connected to. */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_INGRESS_OFST 12
+/* enum: Extracts information from function */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_USE_FUNCTION_VALUE -0x1
+/* Network port or RX Engine to which the common pool connects. */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_EGRESS_OFST 16
+/* enum: Extracts information from function */
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_USE_FUNCTION_VALUE -0x1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT0 0x0 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT1 0x1 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT2 0x2 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_PORT3 0x3 /* enum */
+/* enum: To enable Switch loopback with Rx engine 0 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_RX_ENGINE0 0x4
+/* enum: To enable Switch loopback with Rx engine 1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_IN_RX_ENGINE1 0x5
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT msgresponse */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT_LEN 4
+/* ID of the common pool allocated */
+#define MC_CMD_ALLOCATE_TX_VFIFO_CP_OUT_CP_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO
+ * When we use the TX_vFIFO_ULL mode, we can allocate vFIFOs using the
+ * previously allocated common pools.
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO 0x11e
+
+#define MC_CMD_0x11e_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN msgrequest */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_LEN 20
+/* Common pool previously allocated to which the new vFIFO will be associated
+ */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_CP_OFST 0
+/* Port or RX engine to associate the vFIFO egress */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_EGRESS_OFST 4
+/* enum: Extracts information from common pool */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_USE_CP_VALUE -0x1
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT0 0x0 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT1 0x1 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT2 0x2 /* enum */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PORT3 0x3 /* enum */
+/* enum: To enable Switch loopback with Rx engine 0 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_RX_ENGINE0 0x4
+/* enum: To enable Switch loopback with Rx engine 1 */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_RX_ENGINE1 0x5
+/* Minimum number of buffers that the pool must have */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_SIZE_OFST 8
+/* enum: Do not check the space available */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_NO_MINIMUM 0x0
+/* Will the vFIFO be used as TX_vFIFO_ULL */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_MODE_OFST 12
+/* Network priority of the vFIFO,if applicable */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_PRIORITY_OFST 16
+/* enum: Search for the lowest unused priority */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_IN_LOWEST_AVAILABLE -0x1
+
+/* MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT msgresponse */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_LEN 8
+/* Short vFIFO ID */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_VID_OFST 0
+/* Network priority of the vFIFO */
+#define MC_CMD_ALLOCATE_TX_VFIFO_VFIFO_OUT_PRIORITY_OFST 4
+
+
+/***********************************/
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF
+ * This interface clears the configuration of the given vFIFO and leaves it
+ * ready to be re-used.
+ */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF 0x11f
+
+#define MC_CMD_0x11f_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF_IN msgrequest */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_IN_LEN 4
+/* Short vFIFO ID */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_IN_VFIFO_OFST 0
+
+/* MC_CMD_TEARDOWN_TX_VFIFO_VF_OUT msgresponse */
+#define MC_CMD_TEARDOWN_TX_VFIFO_VF_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP
+ * This interface clears the configuration of the given common pool and leaves
+ * it ready to be re-used.
+ */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP 0x121
+
+#define MC_CMD_0x121_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN msgrequest */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN_LEN 4
+/* Common pool ID given when pool allocated */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_IN_POOL_ID_OFST 0
+
+/* MC_CMD_DEALLOCATE_TX_VFIFO_CP_OUT msgresponse */
+#define MC_CMD_DEALLOCATE_TX_VFIFO_CP_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS
+ * This interface allows the host to find out how many common pool buffers are
+ * not yet assigned.
+ */
+#define MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS 0x124
+
+#define MC_CMD_0x124_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_IN msgrequest */
+#define MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_IN_LEN 0
+
+/* MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_OUT msgresponse */
+#define MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_OUT_LEN 8
+/* Available buffers for the ENG to NET vFIFOs. */
+#define MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_OUT_NET_OFST 0
+/* Available buffers for the ENG to ENG and NET to ENG vFIFOs. */
+#define MC_CMD_SWITCH_GET_UNASSIGNED_BUFFERS_OUT_ENG_OFST 4
+
+
#endif /* MCDI_PCOL_H */
diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c
index 2a9228a6e4a0..9dcd396784ae 100644
--- a/drivers/net/ethernet/sfc/mcdi_port.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -13,7 +13,6 @@
#include <linux/slab.h>
#include "efx.h"
-#include "phy.h"
#include "mcdi.h"
#include "mcdi_pcol.h"
#include "nic.h"
@@ -841,7 +840,7 @@ void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
u32 flags, fcntl, speed, lpa;
speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
- EFX_BUG_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
+ EFX_WARN_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
speed = efx_mcdi_event_link_speed[speed];
flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 99d8c82124bb..8692e829b40f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -41,13 +41,13 @@
*
**************************************************************************/
-#define EFX_DRIVER_VERSION "4.0"
+#define EFX_DRIVER_VERSION "4.1"
#ifdef DEBUG
-#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
+#define EFX_WARN_ON_ONCE_PARANOID(x) WARN_ON_ONCE(x)
#define EFX_WARN_ON_PARANOID(x) WARN_ON(x)
#else
-#define EFX_BUG_ON_PARANOID(x) do {} while (0)
+#define EFX_WARN_ON_ONCE_PARANOID(x) do {} while (0)
#define EFX_WARN_ON_PARANOID(x) do {} while (0)
#endif
@@ -139,8 +139,6 @@ struct efx_special_buffer {
* struct efx_tx_buffer - buffer state for a TX descriptor
* @skb: When @flags & %EFX_TX_BUF_SKB, the associated socket buffer to be
* freed when descriptor completes
- * @heap_buf: When @flags & %EFX_TX_BUF_HEAP, the associated heap buffer to be
- * freed when descriptor completes.
* @option: When @flags & %EFX_TX_BUF_OPTION, a NIC-specific option descriptor.
* @dma_addr: DMA address of the fragment.
* @flags: Flags for allocation and DMA mapping type
@@ -151,10 +149,7 @@ struct efx_special_buffer {
* Only valid if @unmap_len != 0.
*/
struct efx_tx_buffer {
- union {
- const struct sk_buff *skb;
- void *heap_buf;
- };
+ const struct sk_buff *skb;
union {
efx_qword_t option;
dma_addr_t dma_addr;
@@ -166,7 +161,6 @@ struct efx_tx_buffer {
};
#define EFX_TX_BUF_CONT 1 /* not last descriptor of packet */
#define EFX_TX_BUF_SKB 2 /* buffer is last part of skb */
-#define EFX_TX_BUF_HEAP 4 /* buffer was allocated with kmalloc() */
#define EFX_TX_BUF_MAP_SINGLE 8 /* buffer was mapped with dma_map_single() */
#define EFX_TX_BUF_OPTION 0x10 /* empty buffer for option descriptor */
@@ -189,13 +183,16 @@ struct efx_tx_buffer {
* @channel: The associated channel
* @core_txq: The networking core TX queue structure
* @buffer: The software buffer ring
- * @tsoh_page: Array of pages of TSO header buffers
+ * @cb_page: Array of pages of copy buffers. Carved up according to
+ * %EFX_TX_CB_ORDER into %EFX_TX_CB_SIZE-sized chunks.
* @txd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
* @piobuf: PIO buffer region for this TX queue (shared with its partner).
* Size of the region is efx_piobuf_size.
* @piobuf_offset: Buffer offset to be specified in PIO descriptors
* @initialised: Has hardware queue been initialised?
+ * @handle_tso: TSO xmit preparation handler. Sets up the TSO metadata and
+ * may also map tx data, depending on the nature of the TSO implementation.
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
* @old_write_count: The value of @write_count when last checked.
@@ -221,9 +218,11 @@ struct efx_tx_buffer {
* @tso_long_headers: Number of packets with headers too long for standard
* blocks
* @tso_packets: Number of packets via the TSO xmit path
+ * @tso_fallbacks: Number of times TSO fallback used
* @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
+ * @cb_packets: Number of times the TX copybreak feature has been used
* @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.
@@ -236,13 +235,16 @@ struct efx_tx_queue {
struct efx_channel *channel;
struct netdev_queue *core_txq;
struct efx_tx_buffer *buffer;
- struct efx_buffer *tsoh_page;
+ struct efx_buffer *cb_page;
struct efx_special_buffer txd;
unsigned int ptr_mask;
void __iomem *piobuf;
unsigned int piobuf_offset;
bool initialised;
+ /* Function pointers used in the fast path. */
+ int (*handle_tso)(struct efx_tx_queue*, struct sk_buff*, bool *);
+
/* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp;
unsigned int old_write_count;
@@ -257,9 +259,11 @@ struct efx_tx_queue {
unsigned int tso_bursts;
unsigned int tso_long_headers;
unsigned int tso_packets;
+ unsigned int tso_fallbacks;
unsigned int pushes;
unsigned int pio_packets;
bool xmit_more_available;
+ unsigned int cb_packets;
/* Statistics to supplement MAC stats */
unsigned long tx_packets;
@@ -269,6 +273,9 @@ struct efx_tx_queue {
atomic_t flush_outstanding;
};
+#define EFX_TX_CB_ORDER 7
+#define EFX_TX_CB_SIZE (1 << EFX_TX_CB_ORDER) - NET_IP_ALIGN
+
/**
* struct efx_rx_buffer - An Efx RX data buffer
* @dma_addr: DMA base address of the buffer
@@ -853,6 +860,7 @@ struct vfdi_status;
* @rx_hash_key: Toeplitz hash key for RSS
* @rx_indir_table: Indirection table for RSS
* @rx_scatter: Scatter mode enabled for receives
+ * @rx_hash_udp_4tuple: UDP 4-tuple hashing enabled
* @int_error_count: Number of internal errors seen recently
* @int_error_expire: Time at which error count will be expired
* @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will
@@ -990,6 +998,7 @@ struct efx_nic {
u8 rx_hash_key[40];
u32 rx_indir_table[128];
bool rx_scatter;
+ bool rx_hash_udp_4tuple;
unsigned int_error_count;
unsigned long int_error_expire;
@@ -1210,6 +1219,8 @@ struct efx_mtd_partition {
* and tx_type will already have been validated but this operation
* must validate and update rx_filter.
* @set_mac_address: Set the MAC address of the device
+ * @tso_versions: Returns mask of firmware-assisted TSO versions supported.
+ * If %NULL, then device does not support any TSO version.
* @revision: Hardware architecture revision
* @txd_ptr_tbl_base: TX descriptor ring base address
* @rxd_ptr_tbl_base: RX descriptor ring base address
@@ -1286,6 +1297,8 @@ struct efx_nic_type {
void (*tx_init)(struct efx_tx_queue *tx_queue);
void (*tx_remove)(struct efx_tx_queue *tx_queue);
void (*tx_write)(struct efx_tx_queue *tx_queue);
+ unsigned int (*tx_limit_len)(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
int (*rx_push_rss_config)(struct efx_nic *efx, bool user,
const u32 *rx_indir_table);
int (*rx_probe)(struct efx_rx_queue *rx_queue);
@@ -1364,6 +1377,7 @@ struct efx_nic_type {
void (*vswitching_remove)(struct efx_nic *efx);
int (*get_mac_address)(struct efx_nic *efx, unsigned char *perm_addr);
int (*set_mac_address)(struct efx_nic *efx);
+ u32 (*tso_versions)(struct efx_nic *efx);
int revision;
unsigned int txd_ptr_tbl_base;
@@ -1395,7 +1409,7 @@ struct efx_nic_type {
static inline struct efx_channel *
efx_get_channel(struct efx_nic *efx, unsigned index)
{
- EFX_BUG_ON_PARANOID(index >= efx->n_channels);
+ EFX_WARN_ON_ONCE_PARANOID(index >= efx->n_channels);
return efx->channel[index];
}
@@ -1416,8 +1430,8 @@ efx_get_channel(struct efx_nic *efx, unsigned index)
static inline struct efx_tx_queue *
efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
{
- EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
- type >= EFX_TXQ_TYPES);
+ EFX_WARN_ON_ONCE_PARANOID(index >= efx->n_tx_channels ||
+ type >= EFX_TXQ_TYPES);
return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
}
@@ -1430,8 +1444,8 @@ static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
static inline struct efx_tx_queue *
efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
{
- EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) ||
- type >= EFX_TXQ_TYPES);
+ EFX_WARN_ON_ONCE_PARANOID(!efx_channel_has_tx_queues(channel) ||
+ type >= EFX_TXQ_TYPES);
return &channel->tx_queue[type];
}
@@ -1468,7 +1482,7 @@ static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
static inline struct efx_rx_queue *
efx_channel_get_rx_queue(struct efx_channel *channel)
{
- EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel));
+ EFX_WARN_ON_ONCE_PARANOID(!efx_channel_has_rx_queue(channel));
return &channel->rx_queue;
}
@@ -1543,4 +1557,32 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx
return net_dev->features | net_dev->hw_features;
}
+/* Get the current TX queue insert index. */
+static inline unsigned int
+efx_tx_queue_get_insert_index(const struct efx_tx_queue *tx_queue)
+{
+ return tx_queue->insert_count & tx_queue->ptr_mask;
+}
+
+/* Get a TX buffer. */
+static inline struct efx_tx_buffer *
+__efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
+{
+ return &tx_queue->buffer[efx_tx_queue_get_insert_index(tx_queue)];
+}
+
+/* Get a TX buffer, checking it's not currently in use. */
+static inline struct efx_tx_buffer *
+efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
+{
+ struct efx_tx_buffer *buffer =
+ __efx_tx_queue_get_insert_buffer(tx_queue);
+
+ EFX_WARN_ON_ONCE_PARANOID(buffer->len);
+ EFX_WARN_ON_ONCE_PARANOID(buffer->flags);
+ EFX_WARN_ON_ONCE_PARANOID(buffer->unmap_len);
+
+ return buffer;
+}
+
#endif /* EFX_NET_DRIVER_H */
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 73bee7ea332a..223774635cba 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -18,11 +18,8 @@
#include "mcdi.h"
enum {
- EFX_REV_FALCON_A0 = 0,
- EFX_REV_FALCON_A1 = 1,
- EFX_REV_FALCON_B0 = 2,
- EFX_REV_SIENA_A0 = 3,
- EFX_REV_HUNT_A0 = 4,
+ EFX_REV_SIENA_A0 = 0,
+ EFX_REV_HUNT_A0 = 1,
};
static inline int efx_nic_rev(struct efx_nic *efx)
@@ -32,12 +29,6 @@ static inline int efx_nic_rev(struct efx_nic *efx)
u32 efx_farch_fpga_ver(struct efx_nic *efx);
-/* NIC has two interlinked PCI functions for the same port. */
-static inline bool efx_nic_is_dual_func(struct efx_nic *efx)
-{
- return efx_nic_rev(efx) < EFX_REV_FALCON_B0;
-}
-
/* Read the current event from the event queue */
static inline efx_qword_t *efx_event(struct efx_channel *channel,
unsigned int index)
@@ -144,11 +135,6 @@ enum {
PHY_TYPE_SFT9001B = 10,
};
-#define FALCON_XMAC_LOOPBACKS \
- ((1 << LOOPBACK_XGMII) | \
- (1 << LOOPBACK_XGXS) | \
- (1 << LOOPBACK_XAUI))
-
/* Alignment of PCIe DMA boundaries (4KB) */
#define EFX_PAGE_SIZE 4096
/* Size and alignment of buffer table entries (same) */
@@ -161,160 +147,6 @@ enum {
GENERIC_STAT_COUNT
};
-/**
- * struct falcon_board_type - board operations and type information
- * @id: Board type id, as found in NVRAM
- * @init: Allocate resources and initialise peripheral hardware
- * @init_phy: Do board-specific PHY initialisation
- * @fini: Shut down hardware and free resources
- * @set_id_led: Set state of identifying LED or revert to automatic function
- * @monitor: Board-specific health check function
- */
-struct falcon_board_type {
- u8 id;
- int (*init) (struct efx_nic *nic);
- void (*init_phy) (struct efx_nic *efx);
- void (*fini) (struct efx_nic *nic);
- void (*set_id_led) (struct efx_nic *efx, enum efx_led_mode mode);
- int (*monitor) (struct efx_nic *nic);
-};
-
-/**
- * struct falcon_board - board information
- * @type: Type of board
- * @major: Major rev. ('A', 'B' ...)
- * @minor: Minor rev. (0, 1, ...)
- * @i2c_adap: I2C adapter for on-board peripherals
- * @i2c_data: Data for bit-banging algorithm
- * @hwmon_client: I2C client for hardware monitor
- * @ioexp_client: I2C client for power/port control
- */
-struct falcon_board {
- const struct falcon_board_type *type;
- int major;
- int minor;
- struct i2c_adapter i2c_adap;
- struct i2c_algo_bit_data i2c_data;
- struct i2c_client *hwmon_client, *ioexp_client;
-};
-
-/**
- * struct falcon_spi_device - a Falcon SPI (Serial Peripheral Interface) device
- * @device_id: Controller's id for the device
- * @size: Size (in bytes)
- * @addr_len: Number of address bytes in read/write commands
- * @munge_address: Flag whether addresses should be munged.
- * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
- * use bit 3 of the command byte as address bit A8, rather
- * than having a two-byte address. If this flag is set, then
- * commands should be munged in this way.
- * @erase_command: Erase command (or 0 if sector erase not needed).
- * @erase_size: Erase sector size (in bytes)
- * Erase commands affect sectors with this size and alignment.
- * This must be a power of two.
- * @block_size: Write block size (in bytes).
- * Write commands are limited to blocks with this size and alignment.
- */
-struct falcon_spi_device {
- int device_id;
- unsigned int size;
- unsigned int addr_len;
- unsigned int munge_address:1;
- u8 erase_command;
- unsigned int erase_size;
- unsigned int block_size;
-};
-
-static inline bool falcon_spi_present(const struct falcon_spi_device *spi)
-{
- return spi->size != 0;
-}
-
-enum {
- FALCON_STAT_tx_bytes = GENERIC_STAT_COUNT,
- FALCON_STAT_tx_packets,
- FALCON_STAT_tx_pause,
- FALCON_STAT_tx_control,
- FALCON_STAT_tx_unicast,
- FALCON_STAT_tx_multicast,
- FALCON_STAT_tx_broadcast,
- FALCON_STAT_tx_lt64,
- FALCON_STAT_tx_64,
- FALCON_STAT_tx_65_to_127,
- FALCON_STAT_tx_128_to_255,
- FALCON_STAT_tx_256_to_511,
- FALCON_STAT_tx_512_to_1023,
- FALCON_STAT_tx_1024_to_15xx,
- FALCON_STAT_tx_15xx_to_jumbo,
- FALCON_STAT_tx_gtjumbo,
- FALCON_STAT_tx_non_tcpudp,
- FALCON_STAT_tx_mac_src_error,
- FALCON_STAT_tx_ip_src_error,
- FALCON_STAT_rx_bytes,
- FALCON_STAT_rx_good_bytes,
- FALCON_STAT_rx_bad_bytes,
- FALCON_STAT_rx_packets,
- FALCON_STAT_rx_good,
- FALCON_STAT_rx_bad,
- FALCON_STAT_rx_pause,
- FALCON_STAT_rx_control,
- FALCON_STAT_rx_unicast,
- FALCON_STAT_rx_multicast,
- FALCON_STAT_rx_broadcast,
- FALCON_STAT_rx_lt64,
- FALCON_STAT_rx_64,
- FALCON_STAT_rx_65_to_127,
- FALCON_STAT_rx_128_to_255,
- FALCON_STAT_rx_256_to_511,
- FALCON_STAT_rx_512_to_1023,
- FALCON_STAT_rx_1024_to_15xx,
- FALCON_STAT_rx_15xx_to_jumbo,
- FALCON_STAT_rx_gtjumbo,
- FALCON_STAT_rx_bad_lt64,
- FALCON_STAT_rx_bad_gtjumbo,
- FALCON_STAT_rx_overflow,
- FALCON_STAT_rx_symbol_error,
- FALCON_STAT_rx_align_error,
- FALCON_STAT_rx_length_error,
- FALCON_STAT_rx_internal_error,
- FALCON_STAT_rx_nodesc_drop_cnt,
- FALCON_STAT_COUNT
-};
-
-/**
- * struct falcon_nic_data - Falcon NIC state
- * @pci_dev2: Secondary function of Falcon A
- * @board: Board state and functions
- * @stats: Hardware statistics
- * @stats_disable_count: Nest count for disabling statistics fetches
- * @stats_pending: Is there a pending DMA of MAC statistics.
- * @stats_timer: A timer for regularly fetching MAC statistics.
- * @spi_flash: SPI flash device
- * @spi_eeprom: SPI EEPROM device
- * @spi_lock: SPI bus lock
- * @mdio_lock: MDIO bus lock
- * @xmac_poll_required: XMAC link state needs polling
- */
-struct falcon_nic_data {
- struct pci_dev *pci_dev2;
- struct falcon_board board;
- u64 stats[FALCON_STAT_COUNT];
- unsigned int stats_disable_count;
- bool stats_pending;
- struct timer_list stats_timer;
- struct falcon_spi_device spi_flash;
- struct falcon_spi_device spi_eeprom;
- struct mutex spi_lock;
- struct mutex mdio_lock;
- bool xmac_poll_required;
-};
-
-static inline struct falcon_board *falcon_board(struct efx_nic *efx)
-{
- struct falcon_nic_data *data = efx->nic_data;
- return &data->board;
-}
-
enum {
SIENA_STAT_tx_bytes = GENERIC_STAT_COUNT,
SIENA_STAT_tx_good_bytes,
@@ -681,6 +513,8 @@ void efx_farch_tx_init(struct efx_tx_queue *tx_queue);
void efx_farch_tx_fini(struct efx_tx_queue *tx_queue);
void efx_farch_tx_remove(struct efx_tx_queue *tx_queue);
void efx_farch_tx_write(struct efx_tx_queue *tx_queue);
+unsigned int efx_farch_tx_limit_len(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
int efx_farch_rx_probe(struct efx_rx_queue *rx_queue);
void efx_farch_rx_init(struct efx_rx_queue *rx_queue);
void efx_farch_rx_fini(struct efx_rx_queue *rx_queue);
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 77a5364f7a10..60cdb97f58e2 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -835,7 +835,7 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
ACCESS_ONCE(*start) = 0;
rc = efx_mcdi_rpc_start(efx, MC_CMD_PTP, synch_buf,
MC_CMD_PTP_IN_SYNCHRONIZE_LEN);
- EFX_BUG_ON_PARANOID(rc);
+ EFX_WARN_ON_ONCE_PARANOID(rc);
/* Wait for start from MCDI (or timeout) */
timeout = jiffies + msecs_to_jiffies(MAX_SYNCHRONISE_WAIT_MS);
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 02b0b5272c14..5f4ad4f3518f 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -335,7 +335,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic)
/* Calculate current fill level, and exit if we don't need to fill */
fill_level = (rx_queue->added_count - rx_queue->removed_count);
- EFX_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
+ EFX_WARN_ON_ONCE_PARANOID(fill_level > rx_queue->efx->rxq_entries);
if (fill_level >= rx_queue->fast_fill_trigger)
goto out;
@@ -347,7 +347,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic)
batch_size = efx->rx_pages_per_batch * efx->rx_bufs_per_page;
space = rx_queue->max_fill - fill_level;
- EFX_BUG_ON_PARANOID(space < batch_size);
+ EFX_WARN_ON_ONCE_PARANOID(space < batch_size);
netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
"RX queue %d fast-filling descriptor ring from"
@@ -400,21 +400,10 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
*/
rx_buf->flags |= EFX_RX_PKT_DISCARD;
- if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
- if (net_ratelimit())
- netif_err(efx, rx_err, efx->net_dev,
- " RX queue %d seriously overlength "
- "RX event (0x%x > 0x%x+0x%x). Leaking\n",
- efx_rx_queue_index(rx_queue), len, max_len,
- efx->type->rx_buffer_padding);
- efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
- } else {
- if (net_ratelimit())
- netif_err(efx, rx_err, efx->net_dev,
- " RX queue %d overlength RX event "
- "(0x%x > 0x%x)\n",
- efx_rx_queue_index(rx_queue), len, max_len);
- }
+ if (net_ratelimit())
+ netif_err(efx, rx_err, efx->net_dev,
+ "RX queue %d overlength RX event (%#x > %#x)\n",
+ efx_rx_queue_index(rx_queue), len, max_len);
efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
}
@@ -486,7 +475,7 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
return NULL;
}
- EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
+ EFX_WARN_ON_ONCE_PARANOID(rx_buf->len < hdr_len);
memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size,
efx->rx_prefix_size + hdr_len);
@@ -693,7 +682,7 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
/* Create the smallest power-of-two aligned ring */
entries = max(roundup_pow_of_two(efx->rxq_entries), EFX_MIN_DMAQ_SIZE);
- EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ EFX_WARN_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
rx_queue->ptr_mask = entries - 1;
netif_dbg(efx, probe, efx->net_dev,
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 04ed1b4c7cd9..a3901bc96586 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -20,7 +20,6 @@
#include "nic.h"
#include "farch_regs.h"
#include "io.h"
-#include "phy.h"
#include "workarounds.h"
#include "mcdi.h"
#include "mcdi_pcol.h"
@@ -718,7 +717,7 @@ static void siena_mcdi_request(struct efx_nic *efx,
unsigned int i;
unsigned int inlen_dw = DIV_ROUND_UP(sdu_len, 4);
- EFX_BUG_ON_PARANOID(hdr_len != 4);
+ EFX_WARN_ON_PARANOID(hdr_len != 4);
efx_writed(efx, hdr, pdu);
@@ -977,6 +976,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.tx_init = efx_farch_tx_init,
.tx_remove = efx_farch_tx_remove,
.tx_write = efx_farch_tx_write,
+ .tx_limit_len = efx_farch_tx_limit_len,
.rx_push_rss_config = siena_rx_push_rss_config,
.rx_probe = efx_farch_rx_probe,
.rx_init = efx_farch_rx_init,
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 233778911557..3c0151424d12 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -22,6 +22,7 @@
#include "efx.h"
#include "io.h"
#include "nic.h"
+#include "tx.h"
#include "workarounds.h"
#include "ef10_regs.h"
@@ -33,29 +34,30 @@ unsigned int efx_piobuf_size __read_mostly = EFX_PIOBUF_SIZE_DEF;
#endif /* EFX_USE_PIO */
-static inline unsigned int
-efx_tx_queue_get_insert_index(const struct efx_tx_queue *tx_queue)
+static inline u8 *efx_tx_get_copy_buffer(struct efx_tx_queue *tx_queue,
+ struct efx_tx_buffer *buffer)
{
- return tx_queue->insert_count & tx_queue->ptr_mask;
-}
+ unsigned int index = efx_tx_queue_get_insert_index(tx_queue);
+ struct efx_buffer *page_buf =
+ &tx_queue->cb_page[index >> (PAGE_SHIFT - EFX_TX_CB_ORDER)];
+ unsigned int offset =
+ ((index << EFX_TX_CB_ORDER) + NET_IP_ALIGN) & (PAGE_SIZE - 1);
-static inline struct efx_tx_buffer *
-__efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
-{
- return &tx_queue->buffer[efx_tx_queue_get_insert_index(tx_queue)];
+ if (unlikely(!page_buf->addr) &&
+ efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE,
+ GFP_ATOMIC))
+ return NULL;
+ buffer->dma_addr = page_buf->dma_addr + offset;
+ buffer->unmap_len = 0;
+ return (u8 *)page_buf->addr + offset;
}
-static inline struct efx_tx_buffer *
-efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
+u8 *efx_tx_get_copy_buffer_limited(struct efx_tx_queue *tx_queue,
+ struct efx_tx_buffer *buffer, size_t len)
{
- struct efx_tx_buffer *buffer =
- __efx_tx_queue_get_insert_buffer(tx_queue);
-
- EFX_BUG_ON_PARANOID(buffer->len);
- EFX_BUG_ON_PARANOID(buffer->flags);
- EFX_BUG_ON_PARANOID(buffer->unmap_len);
-
- return buffer;
+ if (len > EFX_TX_CB_SIZE)
+ return NULL;
+ return efx_tx_get_copy_buffer(tx_queue, buffer);
}
static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
@@ -82,35 +84,12 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev,
"TX queue %d transmission id %x complete\n",
tx_queue->queue, tx_queue->read_count);
- } else if (buffer->flags & EFX_TX_BUF_HEAP) {
- kfree(buffer->heap_buf);
}
buffer->len = 0;
buffer->flags = 0;
}
-static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
- struct sk_buff *skb);
-
-static inline unsigned
-efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
-{
- /* Depending on the NIC revision, we can use descriptor
- * lengths up to 8K or 8K-1. However, since PCI Express
- * devices must split read requests at 4K boundaries, there is
- * little benefit from using descriptors that cross those
- * boundaries and we keep things simple by not doing so.
- */
- unsigned len = (~dma_addr & (EFX_PAGE_SIZE - 1)) + 1;
-
- /* Work around hardware bug for unaligned buffers. */
- if (EFX_WORKAROUND_5391(efx) && (dma_addr & 0xf))
- len = min_t(unsigned, len, 512 - (dma_addr & 0xf));
-
- return len;
-}
-
unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
{
/* Header and payload descriptor for each output segment, plus
@@ -118,10 +97,8 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
*/
unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
- /* Possibly one more per segment for the alignment workaround,
- * or for option descriptors
- */
- if (EFX_WORKAROUND_5391(efx) || efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
+ /* Possibly one more per segment for option descriptors */
+ if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
max_descs += EFX_TSO_MAX_SEGS;
/* Possibly more for PCIe page boundaries within input fragments */
@@ -165,7 +142,7 @@ static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
fill_level = max(txq1->insert_count - txq1->old_read_count,
txq2->insert_count - txq2->old_read_count);
- EFX_BUG_ON_PARANOID(fill_level >= efx->txq_entries);
+ EFX_WARN_ON_ONCE_PARANOID(fill_level >= efx->txq_entries);
if (likely(fill_level < efx->txq_stop_thresh)) {
smp_mb();
if (likely(!efx->loopback_selftest))
@@ -173,6 +150,33 @@ static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
}
}
+static int efx_enqueue_skb_copy(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb)
+{
+ unsigned int copy_len = skb->len;
+ struct efx_tx_buffer *buffer;
+ u8 *copy_buffer;
+ int rc;
+
+ EFX_WARN_ON_ONCE_PARANOID(copy_len > EFX_TX_CB_SIZE);
+
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+
+ copy_buffer = efx_tx_get_copy_buffer(tx_queue, buffer);
+ if (unlikely(!copy_buffer))
+ return -ENOMEM;
+
+ rc = skb_copy_bits(skb, 0, copy_buffer, copy_len);
+ EFX_WARN_ON_PARANOID(rc);
+ buffer->len = copy_len;
+
+ buffer->skb = skb;
+ buffer->flags = EFX_TX_BUF_SKB;
+
+ ++tx_queue->insert_count;
+ return rc;
+}
+
#ifdef EFX_USE_PIO
struct efx_short_copy_buffer {
@@ -264,11 +268,11 @@ static void efx_skb_copy_bits_to_pio(struct efx_nic *efx, struct sk_buff *skb,
kunmap_atomic(vaddr);
}
- EFX_BUG_ON_PARANOID(skb_shinfo(skb)->frag_list);
+ EFX_WARN_ON_ONCE_PARANOID(skb_shinfo(skb)->frag_list);
}
-static struct efx_tx_buffer *
-efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
+static int efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb)
{
struct efx_tx_buffer *buffer =
efx_tx_queue_get_insert_buffer(tx_queue);
@@ -292,7 +296,7 @@ efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
efx_flush_copy_buffer(tx_queue->efx, piobuf, &copy_buf);
} else {
/* Pad the write to the size of a cache line.
- * We can do this because we know the skb_shared_info sruct is
+ * We can do this because we know the skb_shared_info struct is
* after the source, and the destination buffer is big enough.
*/
BUILD_BUG_ON(L1_CACHE_BYTES >
@@ -301,6 +305,9 @@ efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
ALIGN(skb->len, L1_CACHE_BYTES) >> 3);
}
+ buffer->skb = skb;
+ buffer->flags = EFX_TX_BUF_SKB | EFX_TX_BUF_OPTION;
+
EFX_POPULATE_QWORD_5(buffer->option,
ESF_DZ_TX_DESC_IS_OPT, 1,
ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_PIO,
@@ -308,127 +315,227 @@ efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
ESF_DZ_TX_PIO_BYTE_CNT, skb->len,
ESF_DZ_TX_PIO_BUF_ADDR,
tx_queue->piobuf_offset);
- ++tx_queue->pio_packets;
++tx_queue->insert_count;
- return buffer;
+ return 0;
}
#endif /* EFX_USE_PIO */
-/*
- * Add a socket buffer to a TX queue
- *
- * This maps all fragments of a socket buffer for DMA and adds them to
- * the TX queue. The queue's insert pointer will be incremented by
- * the number of fragments in the socket buffer.
- *
- * If any DMA mapping fails, any mapped fragments will be unmapped,
- * the queue's insert pointer will be restored to its original value.
- *
- * This function is split out from efx_hard_start_xmit to allow the
- * loopback test to direct packets via specific TX queues.
- *
- * Returns NETDEV_TX_OK.
- * You must hold netif_tx_lock() to call this function.
+static struct efx_tx_buffer *efx_tx_map_chunk(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr,
+ size_t len)
+{
+ const struct efx_nic_type *nic_type = tx_queue->efx->type;
+ struct efx_tx_buffer *buffer;
+ unsigned int dma_len;
+
+ /* Map the fragment taking account of NIC-dependent DMA limits. */
+ do {
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+ dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len);
+
+ buffer->len = dma_len;
+ buffer->dma_addr = dma_addr;
+ buffer->flags = EFX_TX_BUF_CONT;
+ len -= dma_len;
+ dma_addr += dma_len;
+ ++tx_queue->insert_count;
+ } while (len);
+
+ return buffer;
+}
+
+/* Map all data from an SKB for DMA and create descriptors on the queue.
*/
-netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
+static int efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
+ unsigned int segment_count)
{
struct efx_nic *efx = tx_queue->efx;
struct device *dma_dev = &efx->pci_dev->dev;
- struct efx_tx_buffer *buffer;
- unsigned int old_insert_count = tx_queue->insert_count;
- skb_frag_t *fragment;
- unsigned int len, unmap_len = 0;
- dma_addr_t dma_addr, unmap_addr = 0;
- unsigned int dma_len;
+ unsigned int frag_index, nr_frags;
+ dma_addr_t dma_addr, unmap_addr;
unsigned short dma_flags;
- int i = 0;
+ size_t len, unmap_len;
- if (skb_shinfo(skb)->gso_size)
- return efx_enqueue_skb_tso(tx_queue, skb);
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ frag_index = 0;
- /* Get size of the initial fragment */
+ /* Map header data. */
len = skb_headlen(skb);
+ dma_addr = dma_map_single(dma_dev, skb->data, len, DMA_TO_DEVICE);
+ dma_flags = EFX_TX_BUF_MAP_SINGLE;
+ unmap_len = len;
+ unmap_addr = dma_addr;
- /* Pad if necessary */
- if (EFX_WORKAROUND_15592(efx) && skb->len <= 32) {
- EFX_BUG_ON_PARANOID(skb->data_len);
- len = 32 + 1;
- if (skb_pad(skb, len - skb->len))
- return NETDEV_TX_OK;
- }
+ if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
+ return -EIO;
- /* Consider using PIO for short packets */
-#ifdef EFX_USE_PIO
- if (skb->len <= efx_piobuf_size && !skb->xmit_more &&
- efx_nic_may_tx_pio(tx_queue)) {
- buffer = efx_enqueue_skb_pio(tx_queue, skb);
- dma_flags = EFX_TX_BUF_OPTION;
- goto finish_packet;
+ if (segment_count) {
+ /* For TSO we need to put the header in to a separate
+ * descriptor. Map this separately if necessary.
+ */
+ size_t header_len = skb_transport_header(skb) - skb->data +
+ (tcp_hdr(skb)->doff << 2u);
+
+ if (header_len != len) {
+ tx_queue->tso_long_headers++;
+ efx_tx_map_chunk(tx_queue, dma_addr, header_len);
+ len -= header_len;
+ dma_addr += header_len;
+ }
}
-#endif
- /* Map for DMA. Use dma_map_single rather than dma_map_page
- * since this is more efficient on machines with sparse
- * memory.
- */
- dma_flags = EFX_TX_BUF_MAP_SINGLE;
- dma_addr = dma_map_single(dma_dev, skb->data, len, PCI_DMA_TODEVICE);
+ /* Add descriptors for each fragment. */
+ do {
+ struct efx_tx_buffer *buffer;
+ skb_frag_t *fragment;
- /* Process all fragments */
- while (1) {
- if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
- goto dma_err;
+ buffer = efx_tx_map_chunk(tx_queue, dma_addr, len);
+
+ /* The final descriptor for a fragment is responsible for
+ * unmapping the whole fragment.
+ */
+ buffer->flags = EFX_TX_BUF_CONT | dma_flags;
+ buffer->unmap_len = unmap_len;
+ buffer->dma_offset = buffer->dma_addr - unmap_addr;
+
+ if (frag_index >= nr_frags) {
+ /* Store SKB details with the final buffer for
+ * the completion.
+ */
+ buffer->skb = skb;
+ buffer->flags = EFX_TX_BUF_SKB | dma_flags;
+ return 0;
+ }
- /* Store fields for marking in the per-fragment final
- * descriptor */
+ /* Move on to the next fragment. */
+ fragment = &skb_shinfo(skb)->frags[frag_index++];
+ len = skb_frag_size(fragment);
+ dma_addr = skb_frag_dma_map(dma_dev, fragment,
+ 0, len, DMA_TO_DEVICE);
+ dma_flags = 0;
unmap_len = len;
unmap_addr = dma_addr;
- /* Add to TX queue, splitting across DMA boundaries */
- do {
- buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+ if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
+ return -EIO;
+ } while (1);
+}
+
+/* Remove buffers put into a tx_queue. None of the buffers must have
+ * an skb attached.
+ */
+static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
+{
+ struct efx_tx_buffer *buffer;
+
+ /* Work backwards until we hit the original insert pointer value */
+ while (tx_queue->insert_count != tx_queue->write_count) {
+ --tx_queue->insert_count;
+ buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
+ efx_dequeue_buffer(tx_queue, buffer, NULL, NULL);
+ }
+}
+
+/*
+ * Fallback to software TSO.
+ *
+ * This is used if we are unable to send a GSO packet through hardware TSO.
+ * This should only ever happen due to per-queue restrictions - unsupported
+ * packets should first be filtered by the feature flags.
+ *
+ * Returns 0 on success, error code otherwise.
+ */
+static int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb)
+{
+ struct sk_buff *segments, *next;
- dma_len = efx_max_tx_len(efx, dma_addr);
- if (likely(dma_len >= len))
- dma_len = len;
+ segments = skb_gso_segment(skb, 0);
+ if (IS_ERR(segments))
+ return PTR_ERR(segments);
- /* Fill out per descriptor fields */
- buffer->len = dma_len;
- buffer->dma_addr = dma_addr;
- buffer->flags = EFX_TX_BUF_CONT;
- len -= dma_len;
- dma_addr += dma_len;
- ++tx_queue->insert_count;
- } while (len);
+ dev_kfree_skb_any(skb);
+ skb = segments;
- /* Transfer ownership of the unmapping to the final buffer */
- buffer->flags = EFX_TX_BUF_CONT | dma_flags;
- buffer->unmap_len = unmap_len;
- buffer->dma_offset = buffer->dma_addr - unmap_addr;
- unmap_len = 0;
+ while (skb) {
+ next = skb->next;
+ skb->next = NULL;
- /* Get address and size of next fragment */
- if (i >= skb_shinfo(skb)->nr_frags)
- break;
- fragment = &skb_shinfo(skb)->frags[i];
- len = skb_frag_size(fragment);
- i++;
- /* Map for DMA */
- dma_flags = 0;
- dma_addr = skb_frag_dma_map(dma_dev, fragment, 0, len,
- DMA_TO_DEVICE);
+ if (next)
+ skb->xmit_more = true;
+ efx_enqueue_skb(tx_queue, skb);
+ skb = next;
}
- /* Transfer ownership of the skb to the final buffer */
+ return 0;
+}
+
+/*
+ * Add a socket buffer to a TX queue
+ *
+ * This maps all fragments of a socket buffer for DMA and adds them to
+ * the TX queue. The queue's insert pointer will be incremented by
+ * the number of fragments in the socket buffer.
+ *
+ * If any DMA mapping fails, any mapped fragments will be unmapped,
+ * the queue's insert pointer will be restored to its original value.
+ *
+ * This function is split out from efx_hard_start_xmit to allow the
+ * loopback test to direct packets via specific TX queues.
+ *
+ * Returns NETDEV_TX_OK.
+ * You must hold netif_tx_lock() to call this function.
+ */
+netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
+{
+ bool data_mapped = false;
+ unsigned int segments;
+ unsigned int skb_len;
+ int rc;
+
+ skb_len = skb->len;
+ segments = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 0;
+ if (segments == 1)
+ segments = 0; /* Don't use TSO for a single segment. */
+
+ /* Handle TSO first - it's *possible* (although unlikely) that we might
+ * be passed a packet to segment that's smaller than the copybreak/PIO
+ * size limit.
+ */
+ if (segments) {
+ EFX_WARN_ON_ONCE_PARANOID(!tx_queue->handle_tso);
+ rc = tx_queue->handle_tso(tx_queue, skb, &data_mapped);
+ if (rc == -EINVAL) {
+ rc = efx_tx_tso_fallback(tx_queue, skb);
+ tx_queue->tso_fallbacks++;
+ if (rc == 0)
+ return 0;
+ }
+ if (rc)
+ goto err;
#ifdef EFX_USE_PIO
-finish_packet:
+ } else if (skb_len <= efx_piobuf_size && !skb->xmit_more &&
+ efx_nic_may_tx_pio(tx_queue)) {
+ /* Use PIO for short packets with an empty queue. */
+ if (efx_enqueue_skb_pio(tx_queue, skb))
+ goto err;
+ tx_queue->pio_packets++;
+ data_mapped = true;
#endif
- buffer->skb = skb;
- buffer->flags = EFX_TX_BUF_SKB | dma_flags;
+ } else if (skb->data_len && skb_len <= EFX_TX_CB_SIZE) {
+ /* Pad short packets or coalesce short fragmented packets. */
+ if (efx_enqueue_skb_copy(tx_queue, skb))
+ goto err;
+ tx_queue->cb_packets++;
+ data_mapped = true;
+ }
- netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
+ /* Map for DMA and create descriptors if we haven't done so already. */
+ if (!data_mapped && (efx_tx_map_data(tx_queue, skb, segments)))
+ goto err;
- efx_tx_maybe_stop_queue(tx_queue);
+ /* Update BQL */
+ netdev_tx_sent_queue(tx_queue->core_txq, skb_len);
/* Pass off to hardware */
if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
@@ -446,37 +553,22 @@ finish_packet:
tx_queue->xmit_more_available = skb->xmit_more;
}
- tx_queue->tx_packets++;
+ if (segments) {
+ tx_queue->tso_bursts++;
+ tx_queue->tso_packets += segments;
+ tx_queue->tx_packets += segments;
+ } else {
+ tx_queue->tx_packets++;
+ }
+
+ efx_tx_maybe_stop_queue(tx_queue);
return NETDEV_TX_OK;
- dma_err:
- netif_err(efx, tx_err, efx->net_dev,
- " TX queue %d could not map skb with %d bytes %d "
- "fragments for DMA\n", tx_queue->queue, skb->len,
- skb_shinfo(skb)->nr_frags + 1);
- /* Mark the packet as transmitted, and free the SKB ourselves */
+err:
+ efx_enqueue_unwind(tx_queue);
dev_kfree_skb_any(skb);
-
- /* Work backwards until we hit the original insert pointer value */
- while (tx_queue->insert_count != old_insert_count) {
- unsigned int pkts_compl = 0, bytes_compl = 0;
- --tx_queue->insert_count;
- buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
- efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
- }
-
- /* Free the fragment we were mid-way through pushing */
- if (unmap_len) {
- if (dma_flags & EFX_TX_BUF_MAP_SINGLE)
- dma_unmap_single(dma_dev, unmap_addr, unmap_len,
- DMA_TO_DEVICE);
- else
- dma_unmap_page(dma_dev, unmap_addr, unmap_len,
- DMA_TO_DEVICE);
- }
-
return NETDEV_TX_OK;
}
@@ -576,7 +668,7 @@ int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
num_tc = ntc->tc;
- if (efx_nic_rev(efx) < EFX_REV_FALCON_B0 || num_tc > EFX_MAX_TX_TC)
+ if (num_tc > EFX_MAX_TX_TC)
return -EINVAL;
if (num_tc == net_dev->num_tc)
@@ -632,7 +724,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
struct efx_tx_queue *txq2;
unsigned int pkts_compl = 0, bytes_compl = 0;
- EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
+ EFX_WARN_ON_ONCE_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
tx_queue->pkts_compl += pkts_compl;
@@ -667,19 +759,9 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
}
}
-/* Size of page-based TSO header buffers. Larger blocks must be
- * allocated from the heap.
- */
-#define TSOH_STD_SIZE 128
-#define TSOH_PER_PAGE (PAGE_SIZE / TSOH_STD_SIZE)
-
-/* At most half the descriptors in the queue at any time will refer to
- * a TSO header buffer, since they must always be followed by a
- * payload descriptor referring to an skb.
- */
-static unsigned int efx_tsoh_page_count(struct efx_tx_queue *tx_queue)
+static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
{
- return DIV_ROUND_UP(tx_queue->ptr_mask + 1, 2 * TSOH_PER_PAGE);
+ return DIV_ROUND_UP(tx_queue->ptr_mask + 1, PAGE_SIZE >> EFX_TX_CB_ORDER);
}
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
@@ -690,7 +772,7 @@ int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
/* Create the smallest power-of-two aligned ring */
entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE);
- EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ EFX_WARN_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
tx_queue->ptr_mask = entries - 1;
netif_dbg(efx, probe, efx->net_dev,
@@ -703,14 +785,11 @@ int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
if (!tx_queue->buffer)
return -ENOMEM;
- if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD) {
- tx_queue->tsoh_page =
- kcalloc(efx_tsoh_page_count(tx_queue),
- sizeof(tx_queue->tsoh_page[0]), GFP_KERNEL);
- if (!tx_queue->tsoh_page) {
- rc = -ENOMEM;
- goto fail1;
- }
+ tx_queue->cb_page = kcalloc(efx_tx_cb_page_count(tx_queue),
+ sizeof(tx_queue->cb_page[0]), GFP_KERNEL);
+ if (!tx_queue->cb_page) {
+ rc = -ENOMEM;
+ goto fail1;
}
/* Allocate hardware ring */
@@ -721,8 +800,8 @@ int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
return 0;
fail2:
- kfree(tx_queue->tsoh_page);
- tx_queue->tsoh_page = NULL;
+ kfree(tx_queue->cb_page);
+ tx_queue->cb_page = NULL;
fail1:
kfree(tx_queue->buffer);
tx_queue->buffer = NULL;
@@ -731,7 +810,9 @@ fail1:
void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
{
- netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ struct efx_nic *efx = tx_queue->efx;
+
+ netif_dbg(efx, drv, efx->net_dev,
"initialising TX queue %d\n", tx_queue->queue);
tx_queue->insert_count = 0;
@@ -742,6 +823,11 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
tx_queue->xmit_more_available = false;
+ /* Set up default function pointers. These may get replaced by
+ * efx_nic_init_tx() based off NIC/queue capabilities.
+ */
+ tx_queue->handle_tso = efx_enqueue_skb_tso;
+
/* Set up TX descriptor ring */
efx_nic_init_tx(tx_queue);
@@ -781,589 +867,14 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
"destroying TX queue %d\n", tx_queue->queue);
efx_nic_remove_tx(tx_queue);
- if (tx_queue->tsoh_page) {
- for (i = 0; i < efx_tsoh_page_count(tx_queue); i++)
+ if (tx_queue->cb_page) {
+ for (i = 0; i < efx_tx_cb_page_count(tx_queue); i++)
efx_nic_free_buffer(tx_queue->efx,
- &tx_queue->tsoh_page[i]);
- kfree(tx_queue->tsoh_page);
- tx_queue->tsoh_page = NULL;
+ &tx_queue->cb_page[i]);
+ kfree(tx_queue->cb_page);
+ tx_queue->cb_page = NULL;
}
kfree(tx_queue->buffer);
tx_queue->buffer = NULL;
}
-
-
-/* Efx TCP segmentation acceleration.
- *
- * Why? Because by doing it here in the driver we can go significantly
- * faster than the GSO.
- *
- * Requires TX checksum offload support.
- */
-
-#define PTR_DIFF(p1, p2) ((u8 *)(p1) - (u8 *)(p2))
-
-/**
- * struct tso_state - TSO state for an SKB
- * @out_len: Remaining length in current segment
- * @seqnum: Current sequence number
- * @ipv4_id: Current IPv4 ID, host endian
- * @packet_space: Remaining space in current packet
- * @dma_addr: DMA address of current position
- * @in_len: Remaining length in current SKB fragment
- * @unmap_len: Length of SKB fragment
- * @unmap_addr: DMA address of SKB fragment
- * @dma_flags: TX buffer flags for DMA mapping - %EFX_TX_BUF_MAP_SINGLE or 0
- * @protocol: Network protocol (after any VLAN header)
- * @ip_off: Offset of IP header
- * @tcp_off: Offset of TCP header
- * @header_len: Number of bytes of header
- * @ip_base_len: IPv4 tot_len or IPv6 payload_len, before TCP payload
- * @header_dma_addr: Header DMA address, when using option descriptors
- * @header_unmap_len: Header DMA mapped length, or 0 if not using option
- * descriptors
- *
- * The state used during segmentation. It is put into this data structure
- * just to make it easy to pass into inline functions.
- */
-struct tso_state {
- /* Output position */
- unsigned out_len;
- unsigned seqnum;
- u16 ipv4_id;
- unsigned packet_space;
-
- /* Input position */
- dma_addr_t dma_addr;
- unsigned in_len;
- unsigned unmap_len;
- dma_addr_t unmap_addr;
- unsigned short dma_flags;
-
- __be16 protocol;
- unsigned int ip_off;
- unsigned int tcp_off;
- unsigned header_len;
- unsigned int ip_base_len;
- dma_addr_t header_dma_addr;
- unsigned int header_unmap_len;
-};
-
-
-/*
- * Verify that our various assumptions about sk_buffs and the conditions
- * under which TSO will be attempted hold true. Return the protocol number.
- */
-static __be16 efx_tso_check_protocol(struct sk_buff *skb)
-{
- __be16 protocol = skb->protocol;
-
- EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto !=
- protocol);
- if (protocol == htons(ETH_P_8021Q)) {
- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
- protocol = veh->h_vlan_encapsulated_proto;
- }
-
- if (protocol == htons(ETH_P_IP)) {
- EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP);
- } else {
- EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IPV6));
- EFX_BUG_ON_PARANOID(ipv6_hdr(skb)->nexthdr != NEXTHDR_TCP);
- }
- EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data)
- + (tcp_hdr(skb)->doff << 2u)) >
- skb_headlen(skb));
-
- return protocol;
-}
-
-static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer, unsigned int len)
-{
- u8 *result;
-
- EFX_BUG_ON_PARANOID(buffer->len);
- EFX_BUG_ON_PARANOID(buffer->flags);
- EFX_BUG_ON_PARANOID(buffer->unmap_len);
-
- if (likely(len <= TSOH_STD_SIZE - NET_IP_ALIGN)) {
- unsigned index =
- (tx_queue->insert_count & tx_queue->ptr_mask) / 2;
- struct efx_buffer *page_buf =
- &tx_queue->tsoh_page[index / TSOH_PER_PAGE];
- unsigned offset =
- TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + NET_IP_ALIGN;
-
- if (unlikely(!page_buf->addr) &&
- efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE,
- GFP_ATOMIC))
- return NULL;
-
- result = (u8 *)page_buf->addr + offset;
- buffer->dma_addr = page_buf->dma_addr + offset;
- buffer->flags = EFX_TX_BUF_CONT;
- } else {
- tx_queue->tso_long_headers++;
-
- buffer->heap_buf = kmalloc(NET_IP_ALIGN + len, GFP_ATOMIC);
- if (unlikely(!buffer->heap_buf))
- return NULL;
- result = (u8 *)buffer->heap_buf + NET_IP_ALIGN;
- buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_HEAP;
- }
-
- buffer->len = len;
-
- return result;
-}
-
-/**
- * efx_tx_queue_insert - push descriptors onto the TX queue
- * @tx_queue: Efx TX queue
- * @dma_addr: DMA address of fragment
- * @len: Length of fragment
- * @final_buffer: The final buffer inserted into the queue
- *
- * Push descriptors onto the TX queue.
- */
-static void efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
- dma_addr_t dma_addr, unsigned len,
- struct efx_tx_buffer **final_buffer)
-{
- struct efx_tx_buffer *buffer;
- struct efx_nic *efx = tx_queue->efx;
- unsigned dma_len;
-
- EFX_BUG_ON_PARANOID(len <= 0);
-
- while (1) {
- buffer = efx_tx_queue_get_insert_buffer(tx_queue);
- ++tx_queue->insert_count;
-
- EFX_BUG_ON_PARANOID(tx_queue->insert_count -
- tx_queue->read_count >=
- efx->txq_entries);
-
- buffer->dma_addr = dma_addr;
-
- dma_len = efx_max_tx_len(efx, dma_addr);
-
- /* If there is enough space to send then do so */
- if (dma_len >= len)
- break;
-
- buffer->len = dma_len;
- buffer->flags = EFX_TX_BUF_CONT;
- dma_addr += dma_len;
- len -= dma_len;
- }
-
- EFX_BUG_ON_PARANOID(!len);
- buffer->len = len;
- *final_buffer = buffer;
-}
-
-
-/*
- * Put a TSO header into the TX queue.
- *
- * This is special-cased because we know that it is small enough to fit in
- * a single fragment, and we know it doesn't cross a page boundary. It
- * also allows us to not worry about end-of-packet etc.
- */
-static int efx_tso_put_header(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer, u8 *header)
-{
- if (unlikely(buffer->flags & EFX_TX_BUF_HEAP)) {
- buffer->dma_addr = dma_map_single(&tx_queue->efx->pci_dev->dev,
- header, buffer->len,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(&tx_queue->efx->pci_dev->dev,
- buffer->dma_addr))) {
- kfree(buffer->heap_buf);
- buffer->len = 0;
- buffer->flags = 0;
- return -ENOMEM;
- }
- buffer->unmap_len = buffer->len;
- buffer->dma_offset = 0;
- buffer->flags |= EFX_TX_BUF_MAP_SINGLE;
- }
-
- ++tx_queue->insert_count;
- return 0;
-}
-
-
-/* Remove buffers put into a tx_queue. None of the buffers must have
- * an skb attached.
- */
-static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
- unsigned int insert_count)
-{
- struct efx_tx_buffer *buffer;
-
- /* Work backwards until we hit the original insert pointer value */
- while (tx_queue->insert_count != insert_count) {
- --tx_queue->insert_count;
- buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
- efx_dequeue_buffer(tx_queue, buffer, NULL, NULL);
- }
-}
-
-
-/* Parse the SKB header and initialise state. */
-static int tso_start(struct tso_state *st, struct efx_nic *efx,
- struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb)
-{
- struct device *dma_dev = &efx->pci_dev->dev;
- unsigned int header_len, in_len;
- bool use_opt_desc = false;
- dma_addr_t dma_addr;
-
- if (tx_queue->tso_version == 1)
- use_opt_desc = true;
-
- st->ip_off = skb_network_header(skb) - skb->data;
- st->tcp_off = skb_transport_header(skb) - skb->data;
- header_len = st->tcp_off + (tcp_hdr(skb)->doff << 2u);
- in_len = skb_headlen(skb) - header_len;
- st->header_len = header_len;
- st->in_len = in_len;
- if (st->protocol == htons(ETH_P_IP)) {
- st->ip_base_len = st->header_len - st->ip_off;
- st->ipv4_id = ntohs(ip_hdr(skb)->id);
- } else {
- st->ip_base_len = st->header_len - st->tcp_off;
- st->ipv4_id = 0;
- }
- st->seqnum = ntohl(tcp_hdr(skb)->seq);
-
- EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg);
- EFX_BUG_ON_PARANOID(tcp_hdr(skb)->syn);
- EFX_BUG_ON_PARANOID(tcp_hdr(skb)->rst);
-
- st->out_len = skb->len - header_len;
-
- if (!use_opt_desc) {
- st->header_unmap_len = 0;
-
- if (likely(in_len == 0)) {
- st->dma_flags = 0;
- st->unmap_len = 0;
- return 0;
- }
-
- dma_addr = dma_map_single(dma_dev, skb->data + header_len,
- in_len, DMA_TO_DEVICE);
- st->dma_flags = EFX_TX_BUF_MAP_SINGLE;
- st->dma_addr = dma_addr;
- st->unmap_addr = dma_addr;
- st->unmap_len = in_len;
- } else {
- dma_addr = dma_map_single(dma_dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
- st->header_dma_addr = dma_addr;
- st->header_unmap_len = skb_headlen(skb);
- st->dma_flags = 0;
- st->dma_addr = dma_addr + header_len;
- st->unmap_len = 0;
- }
-
- return unlikely(dma_mapping_error(dma_dev, dma_addr)) ? -ENOMEM : 0;
-}
-
-static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
- skb_frag_t *frag)
-{
- st->unmap_addr = skb_frag_dma_map(&efx->pci_dev->dev, frag, 0,
- skb_frag_size(frag), DMA_TO_DEVICE);
- if (likely(!dma_mapping_error(&efx->pci_dev->dev, st->unmap_addr))) {
- st->dma_flags = 0;
- st->unmap_len = skb_frag_size(frag);
- st->in_len = skb_frag_size(frag);
- st->dma_addr = st->unmap_addr;
- return 0;
- }
- return -ENOMEM;
-}
-
-
-/**
- * tso_fill_packet_with_fragment - form descriptors for the current fragment
- * @tx_queue: Efx TX queue
- * @skb: Socket buffer
- * @st: TSO state
- *
- * Form descriptors for the current fragment, until we reach the end
- * of fragment or end-of-packet.
- */
-static void tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb,
- struct tso_state *st)
-{
- struct efx_tx_buffer *buffer;
- int n;
-
- if (st->in_len == 0)
- return;
- if (st->packet_space == 0)
- return;
-
- EFX_BUG_ON_PARANOID(st->in_len <= 0);
- EFX_BUG_ON_PARANOID(st->packet_space <= 0);
-
- n = min(st->in_len, st->packet_space);
-
- st->packet_space -= n;
- st->out_len -= n;
- st->in_len -= n;
-
- efx_tx_queue_insert(tx_queue, st->dma_addr, n, &buffer);
-
- if (st->out_len == 0) {
- /* Transfer ownership of the skb */
- buffer->skb = skb;
- buffer->flags = EFX_TX_BUF_SKB;
- } else if (st->packet_space != 0) {
- buffer->flags = EFX_TX_BUF_CONT;
- }
-
- if (st->in_len == 0) {
- /* Transfer ownership of the DMA mapping */
- buffer->unmap_len = st->unmap_len;
- buffer->dma_offset = buffer->unmap_len - buffer->len;
- buffer->flags |= st->dma_flags;
- st->unmap_len = 0;
- }
-
- st->dma_addr += n;
-}
-
-
-/**
- * tso_start_new_packet - generate a new header and prepare for the new packet
- * @tx_queue: Efx TX queue
- * @skb: Socket buffer
- * @st: TSO state
- *
- * Generate a new header and prepare for the new packet. Return 0 on
- * success, or -%ENOMEM if failed to alloc header.
- */
-static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb,
- struct tso_state *st)
-{
- struct efx_tx_buffer *buffer =
- efx_tx_queue_get_insert_buffer(tx_queue);
- bool is_last = st->out_len <= skb_shinfo(skb)->gso_size;
- u8 tcp_flags_clear;
-
- if (!is_last) {
- st->packet_space = skb_shinfo(skb)->gso_size;
- tcp_flags_clear = 0x09; /* mask out FIN and PSH */
- } else {
- st->packet_space = st->out_len;
- tcp_flags_clear = 0x00;
- }
-
- if (!st->header_unmap_len) {
- /* Allocate and insert a DMA-mapped header buffer. */
- struct tcphdr *tsoh_th;
- unsigned ip_length;
- u8 *header;
- int rc;
-
- header = efx_tsoh_get_buffer(tx_queue, buffer, st->header_len);
- if (!header)
- return -ENOMEM;
-
- tsoh_th = (struct tcphdr *)(header + st->tcp_off);
-
- /* Copy and update the headers. */
- memcpy(header, skb->data, st->header_len);
-
- tsoh_th->seq = htonl(st->seqnum);
- ((u8 *)tsoh_th)[13] &= ~tcp_flags_clear;
-
- ip_length = st->ip_base_len + st->packet_space;
-
- if (st->protocol == htons(ETH_P_IP)) {
- struct iphdr *tsoh_iph =
- (struct iphdr *)(header + st->ip_off);
-
- tsoh_iph->tot_len = htons(ip_length);
- tsoh_iph->id = htons(st->ipv4_id);
- } else {
- struct ipv6hdr *tsoh_iph =
- (struct ipv6hdr *)(header + st->ip_off);
-
- tsoh_iph->payload_len = htons(ip_length);
- }
-
- rc = efx_tso_put_header(tx_queue, buffer, header);
- if (unlikely(rc))
- return rc;
- } else {
- /* Send the original headers with a TSO option descriptor
- * in front
- */
- u8 tcp_flags = ((u8 *)tcp_hdr(skb))[13] & ~tcp_flags_clear;
-
- buffer->flags = EFX_TX_BUF_OPTION;
- buffer->len = 0;
- buffer->unmap_len = 0;
- EFX_POPULATE_QWORD_5(buffer->option,
- ESF_DZ_TX_DESC_IS_OPT, 1,
- ESF_DZ_TX_OPTION_TYPE,
- ESE_DZ_TX_OPTION_DESC_TSO,
- ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
- ESF_DZ_TX_TSO_IP_ID, st->ipv4_id,
- ESF_DZ_TX_TSO_TCP_SEQNO, st->seqnum);
- ++tx_queue->insert_count;
-
- /* We mapped the headers in tso_start(). Unmap them
- * when the last segment is completed.
- */
- buffer = efx_tx_queue_get_insert_buffer(tx_queue);
- buffer->dma_addr = st->header_dma_addr;
- buffer->len = st->header_len;
- if (is_last) {
- buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_MAP_SINGLE;
- buffer->unmap_len = st->header_unmap_len;
- buffer->dma_offset = 0;
- /* Ensure we only unmap them once in case of a
- * later DMA mapping error and rollback
- */
- st->header_unmap_len = 0;
- } else {
- buffer->flags = EFX_TX_BUF_CONT;
- buffer->unmap_len = 0;
- }
- ++tx_queue->insert_count;
- }
-
- st->seqnum += skb_shinfo(skb)->gso_size;
-
- /* Linux leaves suitable gaps in the IP ID space for us to fill. */
- ++st->ipv4_id;
-
- ++tx_queue->tso_packets;
-
- ++tx_queue->tx_packets;
-
- return 0;
-}
-
-
-/**
- * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer
- * @tx_queue: Efx TX queue
- * @skb: Socket buffer
- *
- * Context: You must hold netif_tx_lock() to call this function.
- *
- * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if
- * @skb was not enqueued. In all cases @skb is consumed. Return
- * %NETDEV_TX_OK.
- */
-static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
- struct sk_buff *skb)
-{
- struct efx_nic *efx = tx_queue->efx;
- unsigned int old_insert_count = tx_queue->insert_count;
- int frag_i, rc;
- struct tso_state state;
-
- /* Find the packet protocol and sanity-check it */
- state.protocol = efx_tso_check_protocol(skb);
-
- rc = tso_start(&state, efx, tx_queue, skb);
- if (rc)
- goto mem_err;
-
- if (likely(state.in_len == 0)) {
- /* Grab the first payload fragment. */
- EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1);
- frag_i = 0;
- rc = tso_get_fragment(&state, efx,
- skb_shinfo(skb)->frags + frag_i);
- if (rc)
- goto mem_err;
- } else {
- /* Payload starts in the header area. */
- frag_i = -1;
- }
-
- if (tso_start_new_packet(tx_queue, skb, &state) < 0)
- goto mem_err;
-
- while (1) {
- tso_fill_packet_with_fragment(tx_queue, skb, &state);
-
- /* Move onto the next fragment? */
- if (state.in_len == 0) {
- if (++frag_i >= skb_shinfo(skb)->nr_frags)
- /* End of payload reached. */
- break;
- rc = tso_get_fragment(&state, efx,
- skb_shinfo(skb)->frags + frag_i);
- if (rc)
- goto mem_err;
- }
-
- /* Start at new packet? */
- if (state.packet_space == 0 &&
- tso_start_new_packet(tx_queue, skb, &state) < 0)
- goto mem_err;
- }
-
- netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
-
- efx_tx_maybe_stop_queue(tx_queue);
-
- /* Pass off to hardware */
- 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;
-
- mem_err:
- netif_err(efx, tx_err, efx->net_dev,
- "Out of memory for TSO headers, or DMA mapping error\n");
- dev_kfree_skb_any(skb);
-
- /* Free the DMA mapping we were in the process of writing out */
- if (state.unmap_len) {
- if (state.dma_flags & EFX_TX_BUF_MAP_SINGLE)
- dma_unmap_single(&efx->pci_dev->dev, state.unmap_addr,
- state.unmap_len, DMA_TO_DEVICE);
- else
- dma_unmap_page(&efx->pci_dev->dev, state.unmap_addr,
- state.unmap_len, DMA_TO_DEVICE);
- }
-
- /* Free the header DMA mapping, if using option descriptors */
- if (state.header_unmap_len)
- dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr,
- state.header_unmap_len, DMA_TO_DEVICE);
-
- efx_enqueue_unwind(tx_queue, old_insert_count);
- return NETDEV_TX_OK;
-}
diff --git a/drivers/net/ethernet/sfc/tx.h b/drivers/net/ethernet/sfc/tx.h
new file mode 100644
index 000000000000..1cccc97ec676
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tx.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2015 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EFX_TX_H
+#define EFX_TX_H
+
+#include <linux/types.h>
+
+/* Driver internal tx-path related declarations. */
+
+unsigned int efx_tx_limit_len(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len);
+
+u8 *efx_tx_get_copy_buffer_limited(struct efx_tx_queue *tx_queue,
+ struct efx_tx_buffer *buffer, size_t len);
+
+int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
+ bool *data_mapped);
+
+#endif /* EFX_TX_H */
diff --git a/drivers/net/ethernet/sfc/tx_tso.c b/drivers/net/ethernet/sfc/tx_tso.c
new file mode 100644
index 000000000000..e0cbda9ae859
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tx_tso.c
@@ -0,0 +1,451 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2005-2015 Solarflare 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 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/pci.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/ipv6.h>
+#include <linux/slab.h>
+#include <net/ipv6.h>
+#include <linux/if_ether.h>
+#include <linux/highmem.h>
+#include <linux/moduleparam.h>
+#include <linux/cache.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "io.h"
+#include "nic.h"
+#include "tx.h"
+#include "workarounds.h"
+#include "ef10_regs.h"
+
+/* Efx legacy TCP segmentation acceleration.
+ *
+ * Utilises firmware support to go faster than GSO (but not as fast as TSOv2).
+ *
+ * Requires TX checksum offload support.
+ */
+
+#define PTR_DIFF(p1, p2) ((u8 *)(p1) - (u8 *)(p2))
+
+/**
+ * struct tso_state - TSO state for an SKB
+ * @out_len: Remaining length in current segment
+ * @seqnum: Current sequence number
+ * @ipv4_id: Current IPv4 ID, host endian
+ * @packet_space: Remaining space in current packet
+ * @dma_addr: DMA address of current position
+ * @in_len: Remaining length in current SKB fragment
+ * @unmap_len: Length of SKB fragment
+ * @unmap_addr: DMA address of SKB fragment
+ * @protocol: Network protocol (after any VLAN header)
+ * @ip_off: Offset of IP header
+ * @tcp_off: Offset of TCP header
+ * @header_len: Number of bytes of header
+ * @ip_base_len: IPv4 tot_len or IPv6 payload_len, before TCP payload
+ * @header_dma_addr: Header DMA address
+ * @header_unmap_len: Header DMA mapped length
+ *
+ * The state used during segmentation. It is put into this data structure
+ * just to make it easy to pass into inline functions.
+ */
+struct tso_state {
+ /* Output position */
+ unsigned int out_len;
+ unsigned int seqnum;
+ u16 ipv4_id;
+ unsigned int packet_space;
+
+ /* Input position */
+ dma_addr_t dma_addr;
+ unsigned int in_len;
+ unsigned int unmap_len;
+ dma_addr_t unmap_addr;
+
+ __be16 protocol;
+ unsigned int ip_off;
+ unsigned int tcp_off;
+ unsigned int header_len;
+ unsigned int ip_base_len;
+ dma_addr_t header_dma_addr;
+ unsigned int header_unmap_len;
+};
+
+static inline void prefetch_ptr(struct efx_tx_queue *tx_queue)
+{
+ unsigned int insert_ptr = efx_tx_queue_get_insert_index(tx_queue);
+ char *ptr;
+
+ ptr = (char *) (tx_queue->buffer + insert_ptr);
+ prefetch(ptr);
+ prefetch(ptr + 0x80);
+
+ ptr = (char *) (((efx_qword_t *)tx_queue->txd.buf.addr) + insert_ptr);
+ prefetch(ptr);
+ prefetch(ptr + 0x80);
+}
+
+/**
+ * efx_tx_queue_insert - push descriptors onto the TX queue
+ * @tx_queue: Efx TX queue
+ * @dma_addr: DMA address of fragment
+ * @len: Length of fragment
+ * @final_buffer: The final buffer inserted into the queue
+ *
+ * Push descriptors onto the TX queue.
+ */
+static void efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
+ dma_addr_t dma_addr, unsigned int len,
+ struct efx_tx_buffer **final_buffer)
+{
+ struct efx_tx_buffer *buffer;
+ unsigned int dma_len;
+
+ EFX_WARN_ON_ONCE_PARANOID(len <= 0);
+
+ while (1) {
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+ ++tx_queue->insert_count;
+
+ EFX_WARN_ON_ONCE_PARANOID(tx_queue->insert_count -
+ tx_queue->read_count >=
+ tx_queue->efx->txq_entries);
+
+ buffer->dma_addr = dma_addr;
+
+ dma_len = tx_queue->efx->type->tx_limit_len(tx_queue,
+ dma_addr, len);
+
+ /* If there's space for everything this is our last buffer. */
+ if (dma_len >= len)
+ break;
+
+ buffer->len = dma_len;
+ buffer->flags = EFX_TX_BUF_CONT;
+ dma_addr += dma_len;
+ len -= dma_len;
+ }
+
+ EFX_WARN_ON_ONCE_PARANOID(!len);
+ buffer->len = len;
+ *final_buffer = buffer;
+}
+
+/*
+ * Verify that our various assumptions about sk_buffs and the conditions
+ * under which TSO will be attempted hold true. Return the protocol number.
+ */
+static __be16 efx_tso_check_protocol(struct sk_buff *skb)
+{
+ __be16 protocol = skb->protocol;
+
+ EFX_WARN_ON_ONCE_PARANOID(((struct ethhdr *)skb->data)->h_proto !=
+ protocol);
+ if (protocol == htons(ETH_P_8021Q)) {
+ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
+
+ protocol = veh->h_vlan_encapsulated_proto;
+ }
+
+ if (protocol == htons(ETH_P_IP)) {
+ EFX_WARN_ON_ONCE_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP);
+ } else {
+ EFX_WARN_ON_ONCE_PARANOID(protocol != htons(ETH_P_IPV6));
+ EFX_WARN_ON_ONCE_PARANOID(ipv6_hdr(skb)->nexthdr != NEXTHDR_TCP);
+ }
+ EFX_WARN_ON_ONCE_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data) +
+ (tcp_hdr(skb)->doff << 2u)) >
+ skb_headlen(skb));
+
+ return protocol;
+}
+
+/* Parse the SKB header and initialise state. */
+static int tso_start(struct tso_state *st, struct efx_nic *efx,
+ struct efx_tx_queue *tx_queue,
+ const struct sk_buff *skb)
+{
+ struct device *dma_dev = &efx->pci_dev->dev;
+ unsigned int header_len, in_len;
+ dma_addr_t dma_addr;
+
+ st->ip_off = skb_network_header(skb) - skb->data;
+ st->tcp_off = skb_transport_header(skb) - skb->data;
+ header_len = st->tcp_off + (tcp_hdr(skb)->doff << 2u);
+ in_len = skb_headlen(skb) - header_len;
+ st->header_len = header_len;
+ st->in_len = in_len;
+ if (st->protocol == htons(ETH_P_IP)) {
+ st->ip_base_len = st->header_len - st->ip_off;
+ st->ipv4_id = ntohs(ip_hdr(skb)->id);
+ } else {
+ st->ip_base_len = st->header_len - st->tcp_off;
+ st->ipv4_id = 0;
+ }
+ st->seqnum = ntohl(tcp_hdr(skb)->seq);
+
+ EFX_WARN_ON_ONCE_PARANOID(tcp_hdr(skb)->urg);
+ EFX_WARN_ON_ONCE_PARANOID(tcp_hdr(skb)->syn);
+ EFX_WARN_ON_ONCE_PARANOID(tcp_hdr(skb)->rst);
+
+ st->out_len = skb->len - header_len;
+
+ dma_addr = dma_map_single(dma_dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ st->header_dma_addr = dma_addr;
+ st->header_unmap_len = skb_headlen(skb);
+ st->dma_addr = dma_addr + header_len;
+ st->unmap_len = 0;
+
+ return unlikely(dma_mapping_error(dma_dev, dma_addr)) ? -ENOMEM : 0;
+}
+
+static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
+ skb_frag_t *frag)
+{
+ st->unmap_addr = skb_frag_dma_map(&efx->pci_dev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
+ if (likely(!dma_mapping_error(&efx->pci_dev->dev, st->unmap_addr))) {
+ st->unmap_len = skb_frag_size(frag);
+ st->in_len = skb_frag_size(frag);
+ st->dma_addr = st->unmap_addr;
+ return 0;
+ }
+ return -ENOMEM;
+}
+
+
+/**
+ * tso_fill_packet_with_fragment - form descriptors for the current fragment
+ * @tx_queue: Efx TX queue
+ * @skb: Socket buffer
+ * @st: TSO state
+ *
+ * Form descriptors for the current fragment, until we reach the end
+ * of fragment or end-of-packet.
+ */
+static void tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
+ const struct sk_buff *skb,
+ struct tso_state *st)
+{
+ struct efx_tx_buffer *buffer;
+ int n;
+
+ if (st->in_len == 0)
+ return;
+ if (st->packet_space == 0)
+ return;
+
+ EFX_WARN_ON_ONCE_PARANOID(st->in_len <= 0);
+ EFX_WARN_ON_ONCE_PARANOID(st->packet_space <= 0);
+
+ n = min(st->in_len, st->packet_space);
+
+ st->packet_space -= n;
+ st->out_len -= n;
+ st->in_len -= n;
+
+ efx_tx_queue_insert(tx_queue, st->dma_addr, n, &buffer);
+
+ if (st->out_len == 0) {
+ /* Transfer ownership of the skb */
+ buffer->skb = skb;
+ buffer->flags = EFX_TX_BUF_SKB;
+ } else if (st->packet_space != 0) {
+ buffer->flags = EFX_TX_BUF_CONT;
+ }
+
+ if (st->in_len == 0) {
+ /* Transfer ownership of the DMA mapping */
+ buffer->unmap_len = st->unmap_len;
+ buffer->dma_offset = buffer->unmap_len - buffer->len;
+ st->unmap_len = 0;
+ }
+
+ st->dma_addr += n;
+}
+
+
+#define TCP_FLAGS_OFFSET 13
+
+/**
+ * tso_start_new_packet - generate a new header and prepare for the new packet
+ * @tx_queue: Efx TX queue
+ * @skb: Socket buffer
+ * @st: TSO state
+ *
+ * Generate a new header and prepare for the new packet. Return 0 on
+ * success, or -%ENOMEM if failed to alloc header, or other negative error.
+ */
+static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
+ const struct sk_buff *skb,
+ struct tso_state *st)
+{
+ struct efx_tx_buffer *buffer =
+ efx_tx_queue_get_insert_buffer(tx_queue);
+ bool is_last = st->out_len <= skb_shinfo(skb)->gso_size;
+ u8 tcp_flags_mask, tcp_flags;
+
+ if (!is_last) {
+ st->packet_space = skb_shinfo(skb)->gso_size;
+ tcp_flags_mask = 0x09; /* mask out FIN and PSH */
+ } else {
+ st->packet_space = st->out_len;
+ tcp_flags_mask = 0x00;
+ }
+
+ if (WARN_ON(!st->header_unmap_len))
+ return -EINVAL;
+ /* Send the original headers with a TSO option descriptor
+ * in front
+ */
+ tcp_flags = ((u8 *)tcp_hdr(skb))[TCP_FLAGS_OFFSET] & ~tcp_flags_mask;
+
+ buffer->flags = EFX_TX_BUF_OPTION;
+ buffer->len = 0;
+ buffer->unmap_len = 0;
+ EFX_POPULATE_QWORD_5(buffer->option,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE,
+ ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
+ ESF_DZ_TX_TSO_IP_ID, st->ipv4_id,
+ ESF_DZ_TX_TSO_TCP_SEQNO, st->seqnum);
+ ++tx_queue->insert_count;
+
+ /* We mapped the headers in tso_start(). Unmap them
+ * when the last segment is completed.
+ */
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+ buffer->dma_addr = st->header_dma_addr;
+ buffer->len = st->header_len;
+ if (is_last) {
+ buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_MAP_SINGLE;
+ buffer->unmap_len = st->header_unmap_len;
+ buffer->dma_offset = 0;
+ /* Ensure we only unmap them once in case of a
+ * later DMA mapping error and rollback
+ */
+ st->header_unmap_len = 0;
+ } else {
+ buffer->flags = EFX_TX_BUF_CONT;
+ buffer->unmap_len = 0;
+ }
+ ++tx_queue->insert_count;
+
+ st->seqnum += skb_shinfo(skb)->gso_size;
+
+ /* Linux leaves suitable gaps in the IP ID space for us to fill. */
+ ++st->ipv4_id;
+
+ return 0;
+}
+
+/**
+ * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer
+ * @tx_queue: Efx TX queue
+ * @skb: Socket buffer
+ * @data_mapped: Did we map the data? Always set to true
+ * by this on success.
+ *
+ * Context: You must hold netif_tx_lock() to call this function.
+ *
+ * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if
+ * @skb was not enqueued. @skb is consumed unless return value is
+ * %EINVAL.
+ */
+int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb,
+ bool *data_mapped)
+{
+ struct efx_nic *efx = tx_queue->efx;
+ int frag_i, rc;
+ struct tso_state state;
+
+ if (tx_queue->tso_version != 1)
+ return -EINVAL;
+
+ prefetch(skb->data);
+
+ /* Find the packet protocol and sanity-check it */
+ state.protocol = efx_tso_check_protocol(skb);
+
+ EFX_WARN_ON_ONCE_PARANOID(tx_queue->write_count != tx_queue->insert_count);
+
+ rc = tso_start(&state, efx, tx_queue, skb);
+ if (rc)
+ goto fail;
+
+ if (likely(state.in_len == 0)) {
+ /* Grab the first payload fragment. */
+ EFX_WARN_ON_ONCE_PARANOID(skb_shinfo(skb)->nr_frags < 1);
+ frag_i = 0;
+ rc = tso_get_fragment(&state, efx,
+ skb_shinfo(skb)->frags + frag_i);
+ if (rc)
+ goto fail;
+ } else {
+ /* Payload starts in the header area. */
+ frag_i = -1;
+ }
+
+ rc = tso_start_new_packet(tx_queue, skb, &state);
+ if (rc)
+ goto fail;
+
+ prefetch_ptr(tx_queue);
+
+ while (1) {
+ tso_fill_packet_with_fragment(tx_queue, skb, &state);
+
+ /* Move onto the next fragment? */
+ if (state.in_len == 0) {
+ if (++frag_i >= skb_shinfo(skb)->nr_frags)
+ /* End of payload reached. */
+ break;
+ rc = tso_get_fragment(&state, efx,
+ skb_shinfo(skb)->frags + frag_i);
+ if (rc)
+ goto fail;
+ }
+
+ /* Start at new packet? */
+ if (state.packet_space == 0) {
+ rc = tso_start_new_packet(tx_queue, skb, &state);
+ if (rc)
+ goto fail;
+ }
+ }
+
+ *data_mapped = true;
+
+ return 0;
+
+fail:
+ if (rc == -ENOMEM)
+ netif_err(efx, tx_err, efx->net_dev,
+ "Out of memory for TSO headers, or DMA mapping error\n");
+ else
+ netif_err(efx, tx_err, efx->net_dev, "TSO failed, rc = %d\n", rc);
+
+ /* Free the DMA mapping we were in the process of writing out */
+ if (state.unmap_len) {
+ dma_unmap_page(&efx->pci_dev->dev, state.unmap_addr,
+ state.unmap_len, DMA_TO_DEVICE);
+ }
+
+ /* Free the header DMA mapping */
+ if (state.header_unmap_len)
+ dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr,
+ state.header_unmap_len, DMA_TO_DEVICE);
+
+ return rc;
+}
diff --git a/drivers/net/ethernet/sfc/workarounds.h b/drivers/net/ethernet/sfc/workarounds.h
index 351cd14cb9f9..103f827a1623 100644
--- a/drivers/net/ethernet/sfc/workarounds.h
+++ b/drivers/net/ethernet/sfc/workarounds.h
@@ -15,35 +15,14 @@
* Bug numbers are from Solarflare's Bugzilla.
*/
-#define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
-#define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
#define EFX_WORKAROUND_10G(efx) 1
/* Bit-bashed I2C reads cause performance drop */
#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
-/* Truncated IPv4 packets can confuse the TX packet parser */
-#define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB
/* Legacy interrupt storm when interrupt fifo fills */
#define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA
-/* Spurious parity errors in TSORT buffers */
-#define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
-/* Unaligned read request >512 bytes after aligning may break TSORT */
-#define EFX_WORKAROUND_5391 EFX_WORKAROUND_FALCON_A
-/* iSCSI parsing errors */
-#define EFX_WORKAROUND_5583 EFX_WORKAROUND_FALCON_A
-/* RX events go missing */
-#define EFX_WORKAROUND_5676 EFX_WORKAROUND_FALCON_A
-/* RX_RESET on A1 */
-#define EFX_WORKAROUND_6555 EFX_WORKAROUND_FALCON_A
-/* Increase filter depth to avoid RX_RESET */
-#define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A
-/* Flushes may never complete */
-#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_AB
-/* Leak overlength packets rather than free */
-#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
-
/* Lockup when writing event block registers at gen2/gen3 */
#define EFX_EF10_WORKAROUND_35388(efx) \
(((struct efx_ef10_nic_data *)efx->nic_data)->workaround_35388)
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 7a254da85dd7..42051ab98cf0 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1225,7 +1225,6 @@ static const struct net_device_ops ioc3_netdev_ops = {
.ndo_do_ioctl = ioc3_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ioc3_set_mac_address,
- .ndo_change_mtu = eth_change_mtu,
};
static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index aaa80f13859b..69d2d30e5ef1 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -815,7 +815,6 @@ static const struct net_device_ops meth_netdev_ops = {
.ndo_start_xmit = meth_tx,
.ndo_do_ioctl = meth_ioctl,
.ndo_tx_timeout = meth_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_set_rx_mode = meth_set_rx_mode,
diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
index 7426f8b21252..6c2e2b311c16 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -1386,7 +1386,6 @@ static const struct net_device_ops sc92031_netdev_ops = {
.ndo_open = sc92031_open,
.ndo_stop = sc92031_stop,
.ndo_set_rx_mode = sc92031_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = sc92031_tx_timeout,
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index 27be6c869315..210e35d079dd 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -1833,7 +1833,6 @@ static const struct net_device_ops sis190_netdev_ops = {
.ndo_start_xmit = sis190_start_xmit,
.ndo_tx_timeout = sis190_tx_timeout,
.ndo_set_rx_mode = sis190_set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = sis190_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index 6f85276376e8..39fca6c0b68d 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -400,7 +400,6 @@ static const struct net_device_ops sis900_netdev_ops = {
.ndo_start_xmit = sis900_start_xmit,
.ndo_set_config = sis900_set_config,
.ndo_set_rx_mode = set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = mii_ioctl,
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 7186b89269ad..fe9760ffab51 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -313,7 +313,6 @@ static const struct net_device_ops epic_netdev_ops = {
.ndo_get_stats = epic_get_stats,
.ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index cb49c9654f0a..4f19c6166182 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1753,7 +1753,6 @@ static const struct net_device_ops smc911x_netdev_ops = {
.ndo_start_xmit = smc911x_hard_start_xmit,
.ndo_tx_timeout = smc911x_timeout,
.ndo_set_rx_mode = smc911x_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index d496888b85d3..c8d84679ede7 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -809,7 +809,6 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_start_xmit = smc_wait_to_send_packet,
.ndo_tx_timeout = smc_timeout,
.ndo_set_rx_mode = smc_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
index db3c696d7002..f1c75e291e55 100644
--- a/drivers/net/ethernet/smsc/smc91c92_cs.c
+++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -294,7 +294,6 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_set_config = s9k_config,
.ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = smc_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 73212590d04a..65077c77082a 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
SMC_PUSH_DATA(lp, buf, len & ~1);
/* Send final ctl word with the last byte if there is one */
- SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+ SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len - 1]) : 0), ioaddr,
+ DATA_REG(lp));
/*
* If THROTTLE_TX_PKTS is set, we stop the queue here. This will
@@ -1762,7 +1763,6 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_start_xmit = smc_hard_start_xmit,
.ndo_tx_timeout = smc_timeout,
.ndo_set_rx_mode = smc_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2326,6 +2326,8 @@ static int smc_drv_probe(struct platform_device *pdev)
if (!device_property_read_u32(&pdev->dev, "reg-shift",
&val))
lp->io_shift = val;
+ lp->cfg.pxa_u16_align4 =
+ device_property_read_bool(&pdev->dev, "pxa-u16-align4");
}
#endif
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index ea8465467469..08b17adf0a65 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -86,11 +86,11 @@
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) \
+#define SMC_outw(lp, v, a, r) \
do { \
unsigned int __v = v, __smc_r = r; \
if (SMC_16BIT(lp)) \
- __SMC_outw(__v, a, __smc_r); \
+ __SMC_outw(lp, __v, a, __smc_r); \
else if (SMC_8BIT(lp)) \
SMC_outw_b(__v, a, __smc_r); \
else \
@@ -107,10 +107,10 @@
#define SMC_IRQ_FLAGS (-1) /* from resource */
/* We actually can't write halfwords properly if not word aligned */
-static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
+ bool use_align4_workaround)
{
- if ((machine_is_mainstone() || machine_is_stargate2() ||
- machine_is_pxa_idp()) && reg & 2) {
+ if (use_align4_workaround) {
unsigned int v = val << 16;
v |= readl(ioaddr + (reg & ~2)) & 0xffff;
writel(v, ioaddr + (reg & ~2));
@@ -119,6 +119,12 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
+#define __SMC_outw(lp, v, a, r) \
+ _SMC_outw_align4((v), (a), (r), \
+ IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \
+ (lp)->cfg.pxa_u16_align4)
+
+
#elif defined(CONFIG_SH_SH4202_MICRODEV)
#define SMC_CAN_USE_8BIT 0
@@ -129,7 +135,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000)
#define SMC_inl(a, r) inl((a) + (r) - 0xa0000000)
#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000)
-#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(lp, v, a, r) outw(v, (a) + (r) - 0xa0000000)
#define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000)
#define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l)
#define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l)
@@ -147,7 +153,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inb(a, r) inb(((u32)a) + (r))
#define SMC_inw(a, r) inw(((u32)a) + (r))
#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r))
-#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r))
+#define SMC_outw(lp, v, a, r) outw(v, ((u32)a) + (r))
#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
@@ -175,7 +181,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_outw(lp, v, a, r) writew(v, (a) + (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
@@ -207,7 +213,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
}
#define SMC_inw(a, r) _swapw(readw((a) + (r)))
-#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r))
+#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r))
#define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l)
#define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l)
@@ -241,7 +247,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
#define SMC_inw(a, r) ioread16((a) + (r))
#define SMC_inl(a, r) ioread32((a) + (r))
#define SMC_outb(v, a, r) iowrite8(v, (a) + (r))
-#define SMC_outw(v, a, r) iowrite16(v, (a) + (r))
+#define SMC_outw(lp, v, a, r) iowrite16(v, (a) + (r))
#define SMC_outl(v, a, r) iowrite32(v, (a) + (r))
#define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l)
@@ -303,6 +309,8 @@ struct smc_local {
/* the low address lines on some platforms aren't connected... */
int io_shift;
+ /* on some platforms a u16 write must be 4-bytes aligned */
+ bool half_word_align4;
struct smc91x_platdata cfg;
};
@@ -457,7 +465,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
#if ! SMC_CAN_USE_16BIT
-#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg)
+#define SMC_outw(lp, x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg)
#define SMC_inw(ioaddr, reg) SMC_inw_b(ioaddr, reg)
#define SMC_insw(a, r, p, l) BUG()
#define SMC_outsw(a, r, p, l) BUG()
@@ -909,7 +917,7 @@ static const char * chip_ids[ 16 ] = {
else if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, PN_REG(lp)); \
else \
- SMC_outw(x, ioaddr, PN_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, PN_REG(lp)); \
} while (0)
#define SMC_GET_AR(lp) \
@@ -937,7 +945,7 @@ static const char * chip_ids[ 16 ] = {
int __mask; \
local_irq_save(__flags); \
__mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
- SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \
+ SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \
local_irq_restore(__flags); \
} \
} while (0)
@@ -951,7 +959,7 @@ static const char * chip_ids[ 16 ] = {
if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, IM_REG(lp)); \
else \
- SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \
+ SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp)); \
} while (0)
#define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT)
@@ -961,22 +969,22 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT); \
else \
- SMC_outw(x, ioaddr, BANK_SELECT); \
+ SMC_outw(lp, x, ioaddr, BANK_SELECT); \
} while (0)
#define SMC_GET_BASE(lp) SMC_inw(ioaddr, BASE_REG(lp))
-#define SMC_SET_BASE(lp, x) SMC_outw(x, ioaddr, BASE_REG(lp))
+#define SMC_SET_BASE(lp, x) SMC_outw(lp, x, ioaddr, BASE_REG(lp))
#define SMC_GET_CONFIG(lp) SMC_inw(ioaddr, CONFIG_REG(lp))
-#define SMC_SET_CONFIG(lp, x) SMC_outw(x, ioaddr, CONFIG_REG(lp))
+#define SMC_SET_CONFIG(lp, x) SMC_outw(lp, x, ioaddr, CONFIG_REG(lp))
#define SMC_GET_COUNTER(lp) SMC_inw(ioaddr, COUNTER_REG(lp))
#define SMC_GET_CTL(lp) SMC_inw(ioaddr, CTL_REG(lp))
-#define SMC_SET_CTL(lp, x) SMC_outw(x, ioaddr, CTL_REG(lp))
+#define SMC_SET_CTL(lp, x) SMC_outw(lp, x, ioaddr, CTL_REG(lp))
#define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp))
@@ -987,20 +995,20 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \
else \
- SMC_outw(x, ioaddr, GP_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, GP_REG(lp)); \
} while (0)
-#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp))
+#define SMC_SET_MII(lp, x) SMC_outw(lp, x, ioaddr, MII_REG(lp))
#define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp))
-#define SMC_SET_MIR(lp, x) SMC_outw(x, ioaddr, MIR_REG(lp))
+#define SMC_SET_MIR(lp, x) SMC_outw(lp, x, ioaddr, MIR_REG(lp))
#define SMC_GET_MMU_CMD(lp) SMC_inw(ioaddr, MMU_CMD_REG(lp))
-#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
+#define SMC_SET_MMU_CMD(lp, x) SMC_outw(lp, x, ioaddr, MMU_CMD_REG(lp))
-#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
+#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
#define SMC_GET_PTR(lp) SMC_inw(ioaddr, PTR_REG(lp))
@@ -1009,14 +1017,14 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2)); \
else \
- SMC_outw(x, ioaddr, PTR_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, PTR_REG(lp)); \
} while (0)
#define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp))
#define SMC_GET_RCR(lp) SMC_inw(ioaddr, RCR_REG(lp))
-#define SMC_SET_RCR(lp, x) SMC_outw(x, ioaddr, RCR_REG(lp))
+#define SMC_SET_RCR(lp, x) SMC_outw(lp, x, ioaddr, RCR_REG(lp))
#define SMC_GET_REV(lp) SMC_inw(ioaddr, REV_REG(lp))
@@ -1027,12 +1035,12 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0)); \
else \
- SMC_outw(x, ioaddr, RPC_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, RPC_REG(lp)); \
} while (0)
#define SMC_GET_TCR(lp) SMC_inw(ioaddr, TCR_REG(lp))
-#define SMC_SET_TCR(lp, x) SMC_outw(x, ioaddr, TCR_REG(lp))
+#define SMC_SET_TCR(lp, x) SMC_outw(lp, x, ioaddr, TCR_REG(lp))
#ifndef SMC_GET_MAC_ADDR
#define SMC_GET_MAC_ADDR(lp, addr) \
@@ -1049,18 +1057,18 @@ static const char * chip_ids[ 16 ] = {
#define SMC_SET_MAC_ADDR(lp, addr) \
do { \
- SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
- SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
- SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
+ SMC_outw(lp, addr[0] | (addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
+ SMC_outw(lp, addr[2] | (addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
+ SMC_outw(lp, addr[4] | (addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
} while (0)
#define SMC_SET_MCAST(lp, x) \
do { \
const unsigned char *mt = (x); \
- SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
- SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
- SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
- SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
+ SMC_outw(lp, mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
+ SMC_outw(lp, mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
+ SMC_outw(lp, mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
+ SMC_outw(lp, mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
} while (0)
#define SMC_PUT_PKT_HDR(lp, status, length) \
@@ -1069,8 +1077,8 @@ static const char * chip_ids[ 16 ] = {
SMC_outl((status) | (length)<<16, ioaddr, \
DATA_REG(lp)); \
else { \
- SMC_outw(status, ioaddr, DATA_REG(lp)); \
- SMC_outw(length, ioaddr, DATA_REG(lp)); \
+ SMC_outw(lp, status, ioaddr, DATA_REG(lp)); \
+ SMC_outw(lp, length, ioaddr, DATA_REG(lp)); \
} \
} while (0)
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 8b0016a785c0..fa5ca0992be6 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1963,11 +1963,6 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
sizeof(info->bus_info));
}
-static int smsc911x_ethtool_nwayreset(struct net_device *dev)
-{
- return phy_start_aneg(dev->phydev);
-}
-
static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
@@ -2139,7 +2134,7 @@ static int smsc911x_ethtool_set_eeprom(struct net_device *dev,
static const struct ethtool_ops smsc911x_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_drvinfo = smsc911x_ethtool_getdrvinfo,
- .nway_reset = smsc911x_ethtool_nwayreset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_msglevel = smsc911x_ethtool_getmsglevel,
.set_msglevel = smsc911x_ethtool_setmsglevel,
.get_regs_len = smsc911x_ethtool_getregslen,
@@ -2159,7 +2154,6 @@ static const struct net_device_ops smsc911x_netdev_ops = {
.ndo_get_stats = smsc911x_get_stats,
.ndo_set_rx_mode = smsc911x_set_multicast_list,
.ndo_do_ioctl = smsc911x_do_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = smsc911x_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2591,6 +2585,9 @@ static int smsc911x_suspend(struct device *dev)
PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ |
PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+
return 0;
}
@@ -2600,6 +2597,9 @@ static int smsc911x_resume(struct device *dev)
struct smsc911x_data *pdata = netdev_priv(ndev);
unsigned int to = 100;
+ pm_runtime_enable(dev);
+ pm_runtime_resume(dev);
+
/* Note 3.11 from the datasheet:
* "When the LAN9220 is in a power saving state, a write of any
* data to the BYTE_TEST register will wake-up the device."
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index b7bfed4bc96b..3174aebb322f 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -254,14 +254,6 @@ static void smsc9420_ethtool_set_msglevel(struct net_device *netdev, u32 data)
pd->msg_enable = data;
}
-static int smsc9420_ethtool_nway_reset(struct net_device *netdev)
-{
- if (!netdev->phydev)
- return -ENODEV;
-
- return phy_start_aneg(netdev->phydev);
-}
-
static int smsc9420_ethtool_getregslen(struct net_device *dev)
{
/* all smsc9420 registers plus all phy registers */
@@ -417,7 +409,7 @@ static const struct ethtool_ops smsc9420_ethtool_ops = {
.get_drvinfo = smsc9420_ethtool_get_drvinfo,
.get_msglevel = smsc9420_ethtool_get_msglevel,
.set_msglevel = smsc9420_ethtool_set_msglevel,
- .nway_reset = smsc9420_ethtool_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = smsc9420_ethtool_get_eeprom_len,
.get_eeprom = smsc9420_ethtool_get_eeprom,
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 4b78168a5f3c..ab66248a4b78 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -4,7 +4,7 @@ config STMMAC_ETH
select MII
select PHYLIB
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
@@ -69,6 +69,17 @@ config DWMAC_MESON
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
+config DWMAC_OXNAS
+ tristate "Oxford Semiconductor OXNAS dwmac support"
+ default ARCH_OXNAS
+ depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST)
+ select MFD_SYSCON
+ help
+ Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs.
+
+ This selects the Oxford Semiconductor OXNASSoC glue layer support for
+ the stmmac device driver. This driver is used for OX820.
+
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"
default ARCH_ROCKCHIP
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 5d6ece5919b3..8f83a86ba13c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
+obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index b3e669af3005..026e8e9cb942 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -34,7 +34,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
unsigned int entry = priv->cur_tx;
struct dma_desc *desc = priv->dma_tx + entry;
unsigned int nopaged_len = skb_headlen(skb);
- unsigned int bmax;
+ unsigned int bmax, des2;
unsigned int i = 1, len;
if (priv->plat->enh_desc)
@@ -44,11 +44,12 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
len = nopaged_len - bmax;
- desc->des2 = dma_map_single(priv->device, skb->data,
- bmax, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = bmax;
/* do not close the descriptor and do not set own bit */
priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
@@ -60,12 +61,13 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
desc = priv->dma_tx + entry;
if (len > bmax) {
- desc->des2 = dma_map_single(priv->device,
- (skb->data + bmax * i),
- bmax, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i),
+ bmax, DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = bmax;
priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
STMMAC_CHAIN_MODE, 1,
@@ -73,12 +75,13 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
len -= bmax;
i++;
} else {
- desc->des2 = dma_map_single(priv->device,
- (skb->data + bmax * i), len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i), len,
+ DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = len;
/* last descriptor can be set now */
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
@@ -119,19 +122,19 @@ static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
struct dma_extended_desc *p = (struct dma_extended_desc *)des;
for (i = 0; i < (size - 1); i++) {
dma_phy += sizeof(struct dma_extended_desc);
- p->basic.des3 = (unsigned int)dma_phy;
+ p->basic.des3 = cpu_to_le32((unsigned int)dma_phy);
p++;
}
- p->basic.des3 = (unsigned int)phy_addr;
+ p->basic.des3 = cpu_to_le32((unsigned int)phy_addr);
} else {
struct dma_desc *p = (struct dma_desc *)des;
for (i = 0; i < (size - 1); i++) {
dma_phy += sizeof(struct dma_desc);
- p->des3 = (unsigned int)dma_phy;
+ p->des3 = cpu_to_le32((unsigned int)dma_phy);
p++;
}
- p->des3 = (unsigned int)phy_addr;
+ p->des3 = cpu_to_le32((unsigned int)phy_addr);
}
}
@@ -144,10 +147,10 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
* 1588-2002 time stamping is enabled, hence reinitialize it
* to keep explicit chaining in the descriptor.
*/
- p->des3 = (unsigned int)(priv->dma_rx_phy +
- (((priv->dirty_rx) + 1) %
- DMA_RX_SIZE) *
- sizeof(struct dma_desc));
+ p->des3 = cpu_to_le32((unsigned int)(priv->dma_rx_phy +
+ (((priv->dirty_rx) + 1) %
+ DMA_RX_SIZE) *
+ sizeof(struct dma_desc)));
}
static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
@@ -161,9 +164,9 @@ static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
* 1588-2002 time stamping is enabled, hence reinitialize it
* to keep explicit chaining in the descriptor.
*/
- p->des3 = (unsigned int)((priv->dma_tx_phy +
- ((priv->dirty_tx + 1) % DMA_TX_SIZE))
- * sizeof(struct dma_desc));
+ p->des3 = cpu_to_le32((unsigned int)((priv->dma_tx_phy +
+ ((priv->dirty_tx + 1) % DMA_TX_SIZE))
+ * sizeof(struct dma_desc)));
}
const struct stmmac_mode_ops chain_mode_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 6d2de4e01f6d..b13a144f72ad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -44,6 +44,7 @@
#define DWMAC_CORE_4_00 0x40
#define STMMAC_CHAN0 0 /* Always supported and default for all chips */
+/* These need to be power of two, and >= 4 */
#define DMA_TX_SIZE 512
#define DMA_RX_SIZE 512
#define STMMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1))
@@ -411,8 +412,8 @@ extern const struct stmmac_desc_ops ndesc_ops;
struct stmmac_dma_ops {
/* DMA core initialization */
int (*reset)(void __iomem *ioaddr);
- void (*init)(void __iomem *ioaddr, int pbl, int fb, int mb,
- int aal, u32 dma_tx, u32 dma_rx, int atds);
+ void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
+ u32 dma_tx, u32 dma_rx, int atds);
/* Configure the AXI Bus Mode Register */
void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
/* Dump DMA registers */
@@ -506,6 +507,12 @@ struct mac_link {
struct mii_regs {
unsigned int addr; /* MII Address */
unsigned int data; /* MII Data */
+ unsigned int addr_shift; /* MII address shift */
+ unsigned int reg_shift; /* MII reg shift */
+ unsigned int addr_mask; /* MII address mask */
+ unsigned int reg_mask; /* MII reg mask */
+ unsigned int clk_csr_shift;
+ unsigned int clk_csr_mask;
};
/* Helpers to manage the descriptors for chain and ring modes */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index e3c86d422109..faeeef75d7f1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -87,7 +87,7 @@
#define TDES0_ERROR_SUMMARY BIT(15)
#define TDES0_IP_HEADER_ERROR BIT(16)
#define TDES0_TIME_STAMP_STATUS BIT(17)
-#define TDES0_OWN BIT(31)
+#define TDES0_OWN ((u32)BIT(31)) /* silence sparse */
/* TDES1 */
#define TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
#define TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
@@ -130,7 +130,7 @@
#define ETDES0_FIRST_SEGMENT BIT(28)
#define ETDES0_LAST_SEGMENT BIT(29)
#define ETDES0_INTERRUPT BIT(30)
-#define ETDES0_OWN BIT(31)
+#define ETDES0_OWN ((u32)BIT(31)) /* silence sparse */
/* TDES1 */
#define ETDES1_BUFFER1_SIZE_MASK GENMASK(12, 0)
#define ETDES1_BUFFER2_SIZE_MASK GENMASK(28, 16)
@@ -170,19 +170,19 @@
/* Basic descriptor structure for normal and alternate descriptors */
struct dma_desc {
- unsigned int des0;
- unsigned int des1;
- unsigned int des2;
- unsigned int des3;
+ __le32 des0;
+ __le32 des1;
+ __le32 des2;
+ __le32 des3;
};
/* Extended descriptor structure (e.g. >= databook 3.50a) */
struct dma_extended_desc {
struct dma_desc basic; /* Basic descriptors */
- unsigned int des4; /* Extended Status */
- unsigned int des5; /* Reserved */
- unsigned int des6; /* Tx/Rx Timestamp Low */
- unsigned int des7; /* Tx/Rx Timestamp High */
+ __le32 des4; /* Extended Status */
+ __le32 des5; /* Reserved */
+ __le32 des6; /* Tx/Rx Timestamp Low */
+ __le32 des7; /* Tx/Rx Timestamp High */
};
/* Transmit checksum insertion control */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
index 7635a464ce41..1d181e205d6e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -35,47 +35,50 @@
/* Enhanced descriptors */
static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end)
{
- p->des1 |= ((BUF_SIZE_8KiB - 1) << ERDES1_BUFFER2_SIZE_SHIFT)
- & ERDES1_BUFFER2_SIZE_MASK;
+ p->des1 |= cpu_to_le32(((BUF_SIZE_8KiB - 1)
+ << ERDES1_BUFFER2_SIZE_SHIFT)
+ & ERDES1_BUFFER2_SIZE_MASK);
if (end)
- p->des1 |= ERDES1_END_RING;
+ p->des1 |= cpu_to_le32(ERDES1_END_RING);
}
static inline void enh_desc_end_tx_desc_on_ring(struct dma_desc *p, int end)
{
if (end)
- p->des0 |= ETDES0_END_RING;
+ p->des0 |= cpu_to_le32(ETDES0_END_RING);
else
- p->des0 &= ~ETDES0_END_RING;
+ p->des0 &= cpu_to_le32(~ETDES0_END_RING);
}
static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
{
if (unlikely(len > BUF_SIZE_4KiB)) {
- p->des1 |= (((len - BUF_SIZE_4KiB) << ETDES1_BUFFER2_SIZE_SHIFT)
+ p->des1 |= cpu_to_le32((((len - BUF_SIZE_4KiB)
+ << ETDES1_BUFFER2_SIZE_SHIFT)
& ETDES1_BUFFER2_SIZE_MASK) | (BUF_SIZE_4KiB
- & ETDES1_BUFFER1_SIZE_MASK);
+ & ETDES1_BUFFER1_SIZE_MASK));
} else
- p->des1 |= (len & ETDES1_BUFFER1_SIZE_MASK);
+ p->des1 |= cpu_to_le32((len & ETDES1_BUFFER1_SIZE_MASK));
}
/* Normal descriptors */
static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end)
{
- p->des1 |= ((BUF_SIZE_2KiB - 1) << RDES1_BUFFER2_SIZE_SHIFT)
- & RDES1_BUFFER2_SIZE_MASK;
+ p->des1 |= cpu_to_le32(((BUF_SIZE_2KiB - 1)
+ << RDES1_BUFFER2_SIZE_SHIFT)
+ & RDES1_BUFFER2_SIZE_MASK);
if (end)
- p->des1 |= RDES1_END_RING;
+ p->des1 |= cpu_to_le32(RDES1_END_RING);
}
static inline void ndesc_end_tx_desc_on_ring(struct dma_desc *p, int end)
{
if (end)
- p->des1 |= TDES1_END_RING;
+ p->des1 |= cpu_to_le32(TDES1_END_RING);
else
- p->des1 &= ~TDES1_END_RING;
+ p->des1 &= cpu_to_le32(~TDES1_END_RING);
}
static inline void norm_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
@@ -83,10 +86,11 @@ static inline void norm_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
if (unlikely(len > BUF_SIZE_2KiB)) {
unsigned int buffer1 = (BUF_SIZE_2KiB - 1)
& TDES1_BUFFER1_SIZE_MASK;
- p->des1 |= ((((len - buffer1) << TDES1_BUFFER2_SIZE_SHIFT)
- & TDES1_BUFFER2_SIZE_MASK) | buffer1);
+ p->des1 |= cpu_to_le32((((len - buffer1)
+ << TDES1_BUFFER2_SIZE_SHIFT)
+ & TDES1_BUFFER2_SIZE_MASK) | buffer1);
} else
- p->des1 |= (len & TDES1_BUFFER1_SIZE_MASK);
+ p->des1 |= cpu_to_le32((len & TDES1_BUFFER1_SIZE_MASK));
}
/* Specific functions used for Chain mode */
@@ -94,32 +98,32 @@ static inline void norm_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
/* Enhanced descriptors */
static inline void ehn_desc_rx_set_on_chain(struct dma_desc *p)
{
- p->des1 |= ERDES1_SECOND_ADDRESS_CHAINED;
+ p->des1 |= cpu_to_le32(ERDES1_SECOND_ADDRESS_CHAINED);
}
static inline void enh_desc_end_tx_desc_on_chain(struct dma_desc *p)
{
- p->des0 |= ETDES0_SECOND_ADDRESS_CHAINED;
+ p->des0 |= cpu_to_le32(ETDES0_SECOND_ADDRESS_CHAINED);
}
static inline void enh_set_tx_desc_len_on_chain(struct dma_desc *p, int len)
{
- p->des1 |= (len & ETDES1_BUFFER1_SIZE_MASK);
+ p->des1 |= cpu_to_le32(len & ETDES1_BUFFER1_SIZE_MASK);
}
/* Normal descriptors */
static inline void ndesc_rx_set_on_chain(struct dma_desc *p, int end)
{
- p->des1 |= RDES1_SECOND_ADDRESS_CHAINED;
+ p->des1 |= cpu_to_le32(RDES1_SECOND_ADDRESS_CHAINED);
}
static inline void ndesc_tx_set_on_chain(struct dma_desc *p)
{
- p->des1 |= TDES1_SECOND_ADDRESS_CHAINED;
+ p->des1 |= cpu_to_le32(TDES1_SECOND_ADDRESS_CHAINED);
}
static inline void norm_set_tx_desc_len_on_chain(struct dma_desc *p, int len)
{
- p->des1 |= len & TDES1_BUFFER1_SIZE_MASK;
+ p->des1 |= cpu_to_le32(len & TDES1_BUFFER1_SIZE_MASK);
}
#endif /* __DESC_COM_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index e6e6c2fcc4b7..3304095c934c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -71,9 +71,12 @@ err_remove_config_dt:
static const struct of_device_id dwmac_generic_match[] = {
{ .compatible = "st,spear600-gmac"},
+ { .compatible = "snps,dwmac-3.50a"},
{ .compatible = "snps,dwmac-3.610"},
{ .compatible = "snps,dwmac-3.70a"},
{ .compatible = "snps,dwmac-3.710"},
+ { .compatible = "snps,dwmac-4.00"},
+ { .compatible = "snps,dwmac-4.10a"},
{ .compatible = "snps,dwmac"},
{ }
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
new file mode 100644
index 000000000000..c35597586121
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
@@ -0,0 +1,217 @@
+/*
+ * Oxford Semiconductor OXNAS DWMAC glue layer
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+/* System Control regmap offsets */
+#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78
+#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100
+
+/* Control Register */
+#define DWMAC_CKEN_RX_IN 14
+#define DWMAC_CKEN_RXN_OUT 13
+#define DWMAC_CKEN_RX_OUT 12
+#define DWMAC_CKEN_TX_IN 10
+#define DWMAC_CKEN_TXN_OUT 9
+#define DWMAC_CKEN_TX_OUT 8
+#define DWMAC_RX_SOURCE 7
+#define DWMAC_TX_SOURCE 6
+#define DWMAC_LOW_TX_SOURCE 4
+#define DWMAC_AUTO_TX_SOURCE 3
+#define DWMAC_RGMII 2
+#define DWMAC_SIMPLE_MUX 1
+#define DWMAC_CKEN_GTX 0
+
+/* Delay register */
+#define DWMAC_TX_VARDELAY_SHIFT 0
+#define DWMAC_TXN_VARDELAY_SHIFT 8
+#define DWMAC_RX_VARDELAY_SHIFT 16
+#define DWMAC_RXN_VARDELAY_SHIFT 24
+#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT)
+#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT)
+#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT)
+#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT)
+
+struct oxnas_dwmac {
+ struct device *dev;
+ struct clk *clk;
+ struct regmap *regmap;
+};
+
+static int oxnas_dwmac_init(struct oxnas_dwmac *dwmac)
+{
+ unsigned int value;
+ int ret;
+
+ /* Reset HW here before changing the glue configuration */
+ ret = device_reset(dwmac->dev);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(dwmac->clk);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
+ if (ret < 0) {
+ clk_disable_unprepare(dwmac->clk);
+ return ret;
+ }
+
+ /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
+ value |= BIT(DWMAC_CKEN_GTX) |
+ /* Use simple mux for 25/125 Mhz clock switching */
+ BIT(DWMAC_SIMPLE_MUX) |
+ /* set auto switch tx clock source */
+ BIT(DWMAC_AUTO_TX_SOURCE) |
+ /* enable tx & rx vardelay */
+ BIT(DWMAC_CKEN_TX_OUT) |
+ BIT(DWMAC_CKEN_TXN_OUT) |
+ BIT(DWMAC_CKEN_TX_IN) |
+ BIT(DWMAC_CKEN_RX_OUT) |
+ BIT(DWMAC_CKEN_RXN_OUT) |
+ BIT(DWMAC_CKEN_RX_IN);
+ regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
+
+ /* set tx & rx vardelay */
+ value = DWMAC_TX_VARDELAY(4) |
+ DWMAC_TXN_VARDELAY(2) |
+ DWMAC_RX_VARDELAY(10) |
+ DWMAC_RXN_VARDELAY(8);
+ regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value);
+
+ return 0;
+}
+
+static int oxnas_dwmac_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct device_node *sysctrl;
+ struct oxnas_dwmac *dwmac;
+ int ret;
+
+ sysctrl = of_parse_phandle(pdev->dev.of_node, "oxsemi,sys-ctrl", 0);
+ if (!sysctrl) {
+ dev_err(&pdev->dev, "failed to get sys-ctrl node\n");
+ return -EINVAL;
+ }
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+ if (IS_ERR(plat_dat))
+ return PTR_ERR(plat_dat);
+
+ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+ if (!dwmac)
+ return -ENOMEM;
+
+ dwmac->dev = &pdev->dev;
+ plat_dat->bsp_priv = dwmac;
+
+ dwmac->regmap = syscon_node_to_regmap(sysctrl);
+ if (IS_ERR(dwmac->regmap)) {
+ dev_err(&pdev->dev, "failed to have sysctrl regmap\n");
+ return PTR_ERR(dwmac->regmap);
+ }
+
+ dwmac->clk = devm_clk_get(&pdev->dev, "gmac");
+ if (IS_ERR(dwmac->clk))
+ return PTR_ERR(dwmac->clk);
+
+ ret = oxnas_dwmac_init(dwmac);
+ if (ret)
+ return ret;
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ if (ret)
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+static int oxnas_dwmac_remove(struct platform_device *pdev)
+{
+ struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
+ int ret = stmmac_dvr_remove(&pdev->dev);
+
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int oxnas_dwmac_suspend(struct device *dev)
+{
+ struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(dev);
+ int ret;
+
+ ret = stmmac_suspend(dev);
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+static int oxnas_dwmac_resume(struct device *dev)
+{
+ struct oxnas_dwmac *dwmac = get_stmmac_bsp_priv(dev);
+ int ret;
+
+ ret = oxnas_dwmac_init(dwmac);
+ if (ret)
+ return ret;
+
+ ret = stmmac_resume(dev);
+
+ return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(oxnas_dwmac_pm_ops,
+ oxnas_dwmac_suspend, oxnas_dwmac_resume);
+
+static const struct of_device_id oxnas_dwmac_match[] = {
+ { .compatible = "oxsemi,ox820-dwmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
+
+static struct platform_driver oxnas_dwmac_driver = {
+ .probe = oxnas_dwmac_probe,
+ .remove = oxnas_dwmac_remove,
+ .driver = {
+ .name = "oxnas-dwmac",
+ .pm = &oxnas_dwmac_pm_ops,
+ .of_match_table = oxnas_dwmac_match,
+ },
+};
+module_platform_driver(oxnas_dwmac_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index d80c88bd2bba..77ab0a85f067 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -901,44 +901,6 @@ static void rk_gmac_powerdown(struct rk_priv_data *gmac)
gmac_clk_enable(gmac, false);
}
-static int rk_gmac_init(struct platform_device *pdev, void *priv)
-{
- struct rk_priv_data *bsp_priv = priv;
-
- return rk_gmac_powerup(bsp_priv);
-}
-
-static void rk_gmac_exit(struct platform_device *pdev, void *priv)
-{
- struct rk_priv_data *bsp_priv = priv;
-
- rk_gmac_powerdown(bsp_priv);
-}
-
-static void rk_gmac_suspend(struct platform_device *pdev, void *priv)
-{
- struct rk_priv_data *bsp_priv = priv;
-
- /* Keep the PHY up if we use Wake-on-Lan. */
- if (device_may_wakeup(&pdev->dev))
- return;
-
- rk_gmac_powerdown(bsp_priv);
- bsp_priv->suspended = true;
-}
-
-static void rk_gmac_resume(struct platform_device *pdev, void *priv)
-{
- struct rk_priv_data *bsp_priv = priv;
-
- /* The PHY was up for Wake-on-Lan. */
- if (!bsp_priv->suspended)
- return;
-
- rk_gmac_powerup(bsp_priv);
- bsp_priv->suspended = false;
-}
-
static void rk_fix_speed(void *priv, unsigned int speed)
{
struct rk_priv_data *bsp_priv = priv;
@@ -974,11 +936,7 @@ static int rk_gmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);
plat_dat->has_gmac = true;
- plat_dat->init = rk_gmac_init;
- plat_dat->exit = rk_gmac_exit;
plat_dat->fix_mac_speed = rk_fix_speed;
- plat_dat->suspend = rk_gmac_suspend;
- plat_dat->resume = rk_gmac_resume;
plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
if (IS_ERR(plat_dat->bsp_priv)) {
@@ -986,24 +944,65 @@ static int rk_gmac_probe(struct platform_device *pdev)
goto err_remove_config_dt;
}
- ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
+ ret = rk_gmac_powerup(plat_dat->bsp_priv);
if (ret)
goto err_remove_config_dt;
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
- goto err_gmac_exit;
+ goto err_gmac_powerdown;
return 0;
-err_gmac_exit:
- rk_gmac_exit(pdev, plat_dat->bsp_priv);
+err_gmac_powerdown:
+ rk_gmac_powerdown(plat_dat->bsp_priv);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);
return ret;
}
+static int rk_gmac_remove(struct platform_device *pdev)
+{
+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev);
+ int ret = stmmac_dvr_remove(&pdev->dev);
+
+ rk_gmac_powerdown(bsp_priv);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int rk_gmac_suspend(struct device *dev)
+{
+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
+ int ret = stmmac_suspend(dev);
+
+ /* Keep the PHY up if we use Wake-on-Lan. */
+ if (!device_may_wakeup(dev)) {
+ rk_gmac_powerdown(bsp_priv);
+ bsp_priv->suspended = true;
+ }
+
+ return ret;
+}
+
+static int rk_gmac_resume(struct device *dev)
+{
+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
+
+ /* The PHY was up for Wake-on-Lan. */
+ if (bsp_priv->suspended) {
+ rk_gmac_powerup(bsp_priv);
+ bsp_priv->suspended = false;
+ }
+
+ return stmmac_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);
+
static const struct of_device_id rk_gmac_dwmac_match[] = {
{ .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
@@ -1016,10 +1015,10 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
- .pm = &stmmac_pltfr_pm_ops,
+ .pm = &rk_gmac_pm_ops,
.of_match_table = rk_gmac_dwmac_match,
},
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 0c420e97de1e..1f997027ae51 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -380,8 +380,8 @@ static int socfpga_dwmac_resume(struct device *dev)
* control register 0, and can be modified by the phy driver
* framework.
*/
- if (priv->phydev)
- phy_resume(priv->phydev);
+ if (ndev->phydev)
+ phy_resume(ndev->phydev);
return stmmac_resume(dev);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 060b98c37a85..86e0e053804c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -126,8 +126,8 @@ struct sti_dwmac {
struct clk *clk; /* PHY clock */
u32 ctrl_reg; /* GMAC glue-logic control register */
int clk_sel_reg; /* GMAC ext clk selection register */
- struct device *dev;
struct regmap *regmap;
+ bool gmac_en;
u32 speed;
void (*fix_retime_src)(void *priv, unsigned int speed);
};
@@ -191,7 +191,7 @@ static void stih4xx_fix_retime_src(void *priv, u32 spd)
}
}
- if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk && freq)
+ if (src == TX_RETIME_SRC_CLKGEN && freq)
clk_set_rate(dwmac->clk, freq);
regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
@@ -222,26 +222,20 @@ static void stid127_fix_retime_src(void *priv, u32 spd)
freq = DWMAC_2_5MHZ;
}
- if (dwmac->clk && freq)
+ if (freq)
clk_set_rate(dwmac->clk, freq);
regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
}
-static int sti_dwmac_init(struct platform_device *pdev, void *priv)
+static int sti_dwmac_set_mode(struct sti_dwmac *dwmac)
{
- struct sti_dwmac *dwmac = priv;
struct regmap *regmap = dwmac->regmap;
int iface = dwmac->interface;
- struct device *dev = dwmac->dev;
- struct device_node *np = dev->of_node;
u32 reg = dwmac->ctrl_reg;
u32 val;
- if (dwmac->clk)
- clk_prepare_enable(dwmac->clk);
-
- if (of_property_read_bool(np, "st,gmac_en"))
+ if (dwmac->gmac_en)
regmap_update_bits(regmap, reg, EN_MASK, EN);
regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
@@ -249,18 +243,11 @@ static int sti_dwmac_init(struct platform_device *pdev, void *priv)
val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
regmap_update_bits(regmap, reg, ENMII_MASK, val);
- dwmac->fix_retime_src(priv, dwmac->speed);
+ dwmac->fix_retime_src(dwmac, dwmac->speed);
return 0;
}
-static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
-{
- struct sti_dwmac *dwmac = priv;
-
- if (dwmac->clk)
- clk_disable_unprepare(dwmac->clk);
-}
static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
struct platform_device *pdev)
{
@@ -270,9 +257,6 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
struct regmap *regmap;
int err;
- if (!np)
- return -EINVAL;
-
/* clk selection from extra syscfg register */
dwmac->clk_sel_reg = -ENXIO;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
@@ -289,9 +273,9 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
return err;
}
- dwmac->dev = dev;
dwmac->interface = of_get_phy_mode(np);
dwmac->regmap = regmap;
+ dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en");
dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
dwmac->tx_retime_src = TX_RETIME_SRC_NA;
dwmac->speed = SPEED_100;
@@ -359,28 +343,65 @@ static int sti_dwmac_probe(struct platform_device *pdev)
dwmac->fix_retime_src = data->fix_retime_src;
plat_dat->bsp_priv = dwmac;
- plat_dat->init = sti_dwmac_init;
- plat_dat->exit = sti_dwmac_exit;
plat_dat->fix_mac_speed = data->fix_retime_src;
- ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
+ ret = clk_prepare_enable(dwmac->clk);
if (ret)
goto err_remove_config_dt;
+ ret = sti_dwmac_set_mode(dwmac);
+ if (ret)
+ goto disable_clk;
+
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
- goto err_dwmac_exit;
+ goto disable_clk;
return 0;
-err_dwmac_exit:
- sti_dwmac_exit(pdev, plat_dat->bsp_priv);
+disable_clk:
+ clk_disable_unprepare(dwmac->clk);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);
return ret;
}
+static int sti_dwmac_remove(struct platform_device *pdev)
+{
+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
+ int ret = stmmac_dvr_remove(&pdev->dev);
+
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sti_dwmac_suspend(struct device *dev)
+{
+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
+ int ret = stmmac_suspend(dev);
+
+ clk_disable_unprepare(dwmac->clk);
+
+ return ret;
+}
+
+static int sti_dwmac_resume(struct device *dev)
+{
+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev);
+
+ clk_prepare_enable(dwmac->clk);
+ sti_dwmac_set_mode(dwmac);
+
+ return stmmac_resume(dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend,
+ sti_dwmac_resume);
+
static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
.fix_retime_src = stih4xx_fix_retime_src,
};
@@ -400,10 +421,10 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match);
static struct platform_driver sti_dwmac_driver = {
.probe = sti_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove = sti_dwmac_remove,
.driver = {
.name = "sti-dwmac",
- .pm = &stmmac_pltfr_pm_ops,
+ .pm = &sti_dwmac_pm_ops,
.of_match_table = sti_dwmac_match,
},
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index ff3e5ab39bd0..52b9407a8a39 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -225,7 +225,7 @@ enum rx_tx_priority_ratio {
#define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */
#define DMA_BUS_MODE_MB 0x04000000 /* Mixed burst */
-#define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */
+#define DMA_BUS_MODE_RPBL_MASK 0x007e0000 /* Rx-Programmable Burst Len */
#define DMA_BUS_MODE_RPBL_SHIFT 17
#define DMA_BUS_MODE_USP 0x00800000
#define DMA_BUS_MODE_MAXPBL 0x01000000
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 7df4ff158f3d..b21d03fe4f43 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -534,6 +534,12 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
mac->link.speed = GMAC_CONTROL_FES;
mac->mii.addr = GMAC_MII_ADDR;
mac->mii.data = GMAC_MII_DATA;
+ mac->mii.addr_shift = 11;
+ mac->mii.addr_mask = 0x0000F800;
+ mac->mii.reg_shift = 6;
+ mac->mii.reg_mask = 0x000007C0;
+ mac->mii.clk_csr_shift = 2;
+ mac->mii.clk_csr_mask = 0xF;
/* Get and dump the chip ID */
*synopsys_id = stmmac_get_synopsys_id(hwid);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index f35385266fbf..612d3aaac9a4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -84,37 +84,39 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
writel(value, ioaddr + DMA_AXI_BUS_MODE);
}
-static void dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
- int aal, u32 dma_tx, u32 dma_rx, int atds)
+static void dwmac1000_dma_init(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 dma_tx, u32 dma_rx, int atds)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
/*
* Set the DMA PBL (Programmable Burst Length) mode.
*
* Note: before stmmac core 3.50 this mode bit was 4xPBL, and
* post 3.5 mode bit acts as 8*PBL.
- *
- * This configuration doesn't take care about the Separate PBL
- * so only the bits: 13-8 are programmed with the PBL passed from the
- * platform.
*/
- value |= DMA_BUS_MODE_MAXPBL;
- value &= ~DMA_BUS_MODE_PBL_MASK;
- value |= (pbl << DMA_BUS_MODE_PBL_SHIFT);
+ if (dma_cfg->pblx8)
+ value |= DMA_BUS_MODE_MAXPBL;
+ value |= DMA_BUS_MODE_USP;
+ value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
+ value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
+ value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
/* Set the Fixed burst mode */
- if (fb)
+ if (dma_cfg->fixed_burst)
value |= DMA_BUS_MODE_FB;
/* Mixed Burst has no effect when fb is set */
- if (mb)
+ if (dma_cfg->mixed_burst)
value |= DMA_BUS_MODE_MB;
if (atds)
value |= DMA_BUS_MODE_ATDS;
- if (aal)
+ if (dma_cfg->aal)
value |= DMA_BUS_MODE_AAL;
writel(value, ioaddr + DMA_BUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 6418b2e07619..a1d582f47b1a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -192,6 +192,13 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr, int *synopsys_id)
mac->link.speed = 0;
mac->mii.addr = MAC_MII_ADDR;
mac->mii.data = MAC_MII_DATA;
+ mac->mii.addr_shift = 11;
+ mac->mii.addr_mask = 0x0000F800;
+ mac->mii.reg_shift = 6;
+ mac->mii.reg_mask = 0x000007C0;
+ mac->mii.clk_csr_shift = 2;
+ mac->mii.clk_csr_mask = 0xF;
+
/* Synopsys Id is not available on old chips */
*synopsys_id = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index 61f54c99a7de..e5664da382f3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -32,11 +32,12 @@
#include "dwmac100.h"
#include "dwmac_dma.h"
-static void dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
- int aal, u32 dma_tx, u32 dma_rx, int atds)
+static void dwmac100_dma_init(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 dma_tx, u32 dma_rx, int atds)
{
/* Enable Application Access by writing to DMA CSR0 */
- writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
+ writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
ioaddr + DMA_BUS_MODE);
/* Mask interrupts by writing to CSR7 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index 6f4f5ce25114..3e8d4fefa5e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -155,8 +155,11 @@ enum power_event {
#define MTL_CHAN_RX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x38)
#define MTL_OP_MODE_RSF BIT(5)
+#define MTL_OP_MODE_TXQEN BIT(3)
#define MTL_OP_MODE_TSF BIT(1)
+#define MTL_OP_MODE_TQS_MASK GENMASK(24, 16)
+
#define MTL_OP_MODE_TTC_MASK 0x70
#define MTL_OP_MODE_TTC_SHIFT 4
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 51019b794be5..eaed7cb21867 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -430,6 +430,12 @@ struct mac_device_info *dwmac4_setup(void __iomem *ioaddr, int mcbins,
mac->link.speed = GMAC_CONFIG_FES;
mac->mii.addr = GMAC_MDIO_ADDR;
mac->mii.data = GMAC_MDIO_DATA;
+ mac->mii.addr_shift = 21;
+ mac->mii.addr_mask = GENMASK(25, 21);
+ mac->mii.reg_shift = 16;
+ mac->mii.reg_mask = GENMASK(20, 16);
+ mac->mii.clk_csr_shift = 8;
+ mac->mii.clk_csr_mask = GENMASK(11, 8);
/* Get and dump the chip ID */
*synopsys_id = stmmac_get_synopsys_id(hwid);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index a601f8d43b75..a340fc8bd0de 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -23,7 +23,7 @@ static int dwmac4_wrback_get_tx_status(void *data, struct stmmac_extra_stats *x,
unsigned int tdes3;
int ret = tx_done;
- tdes3 = p->des3;
+ tdes3 = le32_to_cpu(p->des3);
/* Get tx owner first */
if (unlikely(tdes3 & TDES3_OWN))
@@ -77,9 +77,9 @@ static int dwmac4_wrback_get_rx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int rdes1 = p->des1;
- unsigned int rdes2 = p->des2;
- unsigned int rdes3 = p->des3;
+ unsigned int rdes1 = le32_to_cpu(p->des1);
+ unsigned int rdes2 = le32_to_cpu(p->des2);
+ unsigned int rdes3 = le32_to_cpu(p->des3);
int message_type;
int ret = good_frame;
@@ -176,47 +176,48 @@ static int dwmac4_wrback_get_rx_status(void *data, struct stmmac_extra_stats *x,
static int dwmac4_rd_get_tx_len(struct dma_desc *p)
{
- return (p->des2 & TDES2_BUFFER1_SIZE_MASK);
+ return (le32_to_cpu(p->des2) & TDES2_BUFFER1_SIZE_MASK);
}
static int dwmac4_get_tx_owner(struct dma_desc *p)
{
- return (p->des3 & TDES3_OWN) >> TDES3_OWN_SHIFT;
+ return (le32_to_cpu(p->des3) & TDES3_OWN) >> TDES3_OWN_SHIFT;
}
static void dwmac4_set_tx_owner(struct dma_desc *p)
{
- p->des3 |= TDES3_OWN;
+ p->des3 |= cpu_to_le32(TDES3_OWN);
}
static void dwmac4_set_rx_owner(struct dma_desc *p)
{
- p->des3 |= RDES3_OWN;
+ p->des3 |= cpu_to_le32(RDES3_OWN);
}
static int dwmac4_get_tx_ls(struct dma_desc *p)
{
- return (p->des3 & TDES3_LAST_DESCRIPTOR) >> TDES3_LAST_DESCRIPTOR_SHIFT;
+ return (le32_to_cpu(p->des3) & TDES3_LAST_DESCRIPTOR)
+ >> TDES3_LAST_DESCRIPTOR_SHIFT;
}
static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe)
{
- return (p->des3 & RDES3_PACKET_SIZE_MASK);
+ return (le32_to_cpu(p->des3) & RDES3_PACKET_SIZE_MASK);
}
static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p)
{
- p->des2 |= TDES2_TIMESTAMP_ENABLE;
+ p->des2 |= cpu_to_le32(TDES2_TIMESTAMP_ENABLE);
}
static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
{
/* Context type from W/B descriptor must be zero */
- if (p->des3 & TDES3_CONTEXT_TYPE)
+ if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE)
return -EINVAL;
/* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
- if (p->des3 & TDES3_TIMESTAMP_STATUS)
+ if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
return 0;
return 1;
@@ -227,9 +228,9 @@ static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
struct dma_desc *p = (struct dma_desc *)desc;
u64 ns;
- ns = p->des0;
+ ns = le32_to_cpu(p->des0);
/* convert high/sec time stamp value to nanosecond */
- ns += p->des1 * 1000000000ULL;
+ ns += le32_to_cpu(p->des1) * 1000000000ULL;
return ns;
}
@@ -264,7 +265,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
/* Get the status from normal w/b descriptor */
if (likely(p->des3 & TDES3_RS1V)) {
- if (likely(p->des1 & RDES1_TIMESTAMP_AVAILABLE)) {
+ if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) {
int i = 0;
/* Check if timestamp is OK from context descriptor */
@@ -287,10 +288,10 @@ exit:
static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
{
- p->des3 = RDES3_OWN | RDES3_BUFFER1_VALID_ADDR;
+ p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
if (!disable_rx_ic)
- p->des3 |= RDES3_INT_ON_COMPLETION_EN;
+ p->des3 |= cpu_to_le32(RDES3_INT_ON_COMPLETION_EN);
}
static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end)
@@ -305,9 +306,9 @@ static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
bool csum_flag, int mode, bool tx_own,
bool ls)
{
- unsigned int tdes3 = p->des3;
+ unsigned int tdes3 = le32_to_cpu(p->des3);
- p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK);
+ p->des2 |= cpu_to_le32(len & TDES2_BUFFER1_SIZE_MASK);
if (is_fs)
tdes3 |= TDES3_FIRST_DESCRIPTOR;
@@ -335,7 +336,7 @@ static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
*/
wmb();
- p->des3 = tdes3;
+ p->des3 = cpu_to_le32(tdes3);
}
static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs,
@@ -343,14 +344,14 @@ static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs,
bool ls, unsigned int tcphdrlen,
unsigned int tcppayloadlen)
{
- unsigned int tdes3 = p->des3;
+ unsigned int tdes3 = le32_to_cpu(p->des3);
if (len1)
- p->des2 |= (len1 & TDES2_BUFFER1_SIZE_MASK);
+ p->des2 |= cpu_to_le32((len1 & TDES2_BUFFER1_SIZE_MASK));
if (len2)
- p->des2 |= (len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT)
- & TDES2_BUFFER2_SIZE_MASK;
+ p->des2 |= cpu_to_le32((len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT)
+ & TDES2_BUFFER2_SIZE_MASK);
if (is_fs) {
tdes3 |= TDES3_FIRST_DESCRIPTOR |
@@ -378,7 +379,7 @@ static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs,
*/
wmb();
- p->des3 = tdes3;
+ p->des3 = cpu_to_le32(tdes3);
}
static void dwmac4_release_tx_desc(struct dma_desc *p, int mode)
@@ -389,7 +390,7 @@ static void dwmac4_release_tx_desc(struct dma_desc *p, int mode)
static void dwmac4_rd_set_tx_ic(struct dma_desc *p)
{
- p->des2 |= TDES2_INTERRUPT_ON_COMPLETION;
+ p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION);
}
static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
@@ -402,7 +403,8 @@ static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
for (i = 0; i < size; i++) {
pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(p),
- p->des0, p->des1, p->des2, p->des3);
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+ le32_to_cpu(p->des2), le32_to_cpu(p->des3));
p++;
}
}
@@ -411,8 +413,8 @@ static void dwmac4_set_mss_ctxt(struct dma_desc *p, unsigned int mss)
{
p->des0 = 0;
p->des1 = 0;
- p->des2 = mss;
- p->des3 = TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV;
+ p->des2 = cpu_to_le32(mss);
+ p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV);
}
const struct stmmac_desc_ops dwmac4_desc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 32bc2fc73cdc..8196ab5fc33c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -71,25 +71,29 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
writel(value, ioaddr + DMA_SYS_BUS_MODE);
}
-static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl,
+static void dwmac4_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
u32 dma_tx_phy, u32 dma_rx_phy,
u32 channel)
{
u32 value;
+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
/* set PBL for each channels. Currently we affect same configuration
* on each channel
*/
value = readl(ioaddr + DMA_CHAN_CONTROL(channel));
- value = value | DMA_BUS_MODE_PBL;
+ if (dma_cfg->pblx8)
+ value = value | DMA_BUS_MODE_PBL;
writel(value, ioaddr + DMA_CHAN_CONTROL(channel));
value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel));
- value = value | (pbl << DMA_BUS_MODE_PBL_SHIFT);
+ value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT);
writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel));
value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel));
- value = value | (pbl << DMA_BUS_MODE_RPBL_SHIFT);
+ value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel));
/* Mask interrupts by writing to CSR7 */
@@ -99,27 +103,28 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl,
writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel));
}
-static void dwmac4_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
- int aal, u32 dma_tx, u32 dma_rx, int atds)
+static void dwmac4_dma_init(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 dma_tx, u32 dma_rx, int atds)
{
u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
int i;
/* Set the Fixed burst mode */
- if (fb)
+ if (dma_cfg->fixed_burst)
value |= DMA_SYS_BUS_FB;
/* Mixed Burst has no effect when fb is set */
- if (mb)
+ if (dma_cfg->mixed_burst)
value |= DMA_SYS_BUS_MB;
- if (aal)
+ if (dma_cfg->aal)
value |= DMA_SYS_BUS_AAL;
writel(value, ioaddr + DMA_SYS_BUS_MODE);
for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
- dwmac4_dma_init_channel(ioaddr, pbl, dma_tx, dma_rx, i);
+ dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i);
}
static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel)
@@ -215,7 +220,17 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode,
else
mtl_tx_op |= MTL_OP_MODE_TTC_512;
}
-
+ /* For an IP with DWC_EQOS_NUM_TXQ == 1, the fields TXQEN and TQS are RO
+ * with reset values: TXQEN on, TQS == DWC_EQOS_TXFIFO_SIZE.
+ * For an IP with DWC_EQOS_NUM_TXQ > 1, the fields TXQEN and TQS are R/W
+ * with reset values: TXQEN off, TQS 256 bytes.
+ *
+ * Write the bits in both cases, since it will have no effect when RO.
+ * For DWC_EQOS_NUM_TXQ > 1, the top bits in MTL_OP_MODE_TQS_MASK might
+ * be RO, however, writing the whole TQS field will result in a value
+ * equal to DWC_EQOS_TXFIFO_SIZE, just like for DWC_EQOS_NUM_TXQ == 1.
+ */
+ mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK;
writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel));
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index e75549327c34..ce97e522566a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -30,7 +30,7 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int tdes0 = p->des0;
+ unsigned int tdes0 = le32_to_cpu(p->des0);
int ret = tx_done;
/* Get tx owner first */
@@ -95,7 +95,7 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
static int enh_desc_get_tx_len(struct dma_desc *p)
{
- return (p->des1 & ETDES1_BUFFER1_SIZE_MASK);
+ return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
}
static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
@@ -134,8 +134,8 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x,
struct dma_extended_desc *p)
{
- unsigned int rdes0 = p->basic.des0;
- unsigned int rdes4 = p->des4;
+ unsigned int rdes0 = le32_to_cpu(p->basic.des0);
+ unsigned int rdes4 = le32_to_cpu(p->des4);
if (unlikely(rdes0 & ERDES0_RX_MAC_ADDR)) {
int message_type = (rdes4 & ERDES4_MSG_TYPE_MASK) >> 8;
@@ -199,7 +199,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int rdes0 = p->des0;
+ unsigned int rdes0 = le32_to_cpu(p->des0);
int ret = good_frame;
if (unlikely(rdes0 & RDES0_OWN))
@@ -265,8 +265,8 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
{
- p->des0 |= RDES0_OWN;
- p->des1 |= ((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK);
+ p->des0 |= cpu_to_le32(RDES0_OWN);
+ p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK);
if (mode == STMMAC_CHAIN_MODE)
ehn_desc_rx_set_on_chain(p);
@@ -274,12 +274,12 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
ehn_desc_rx_set_on_ring(p, end);
if (disable_rx_ic)
- p->des1 |= ERDES1_DISABLE_IC;
+ p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
}
static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
{
- p->des0 &= ~ETDES0_OWN;
+ p->des0 &= cpu_to_le32(~ETDES0_OWN);
if (mode == STMMAC_CHAIN_MODE)
enh_desc_end_tx_desc_on_chain(p);
else
@@ -288,27 +288,27 @@ static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
static int enh_desc_get_tx_owner(struct dma_desc *p)
{
- return (p->des0 & ETDES0_OWN) >> 31;
+ return (le32_to_cpu(p->des0) & ETDES0_OWN) >> 31;
}
static void enh_desc_set_tx_owner(struct dma_desc *p)
{
- p->des0 |= ETDES0_OWN;
+ p->des0 |= cpu_to_le32(ETDES0_OWN);
}
static void enh_desc_set_rx_owner(struct dma_desc *p)
{
- p->des0 |= RDES0_OWN;
+ p->des0 |= cpu_to_le32(RDES0_OWN);
}
static int enh_desc_get_tx_ls(struct dma_desc *p)
{
- return (p->des0 & ETDES0_LAST_SEGMENT) >> 29;
+ return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29;
}
static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
{
- int ter = (p->des0 & ETDES0_END_RING) >> 21;
+ int ter = (le32_to_cpu(p->des0) & ETDES0_END_RING) >> 21;
memset(p, 0, offsetof(struct dma_desc, des2));
if (mode == STMMAC_CHAIN_MODE)
@@ -321,7 +321,7 @@ static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
bool csum_flag, int mode, bool tx_own,
bool ls)
{
- unsigned int tdes0 = p->des0;
+ unsigned int tdes0 = le32_to_cpu(p->des0);
if (mode == STMMAC_CHAIN_MODE)
enh_set_tx_desc_len_on_chain(p, len);
@@ -352,12 +352,12 @@ static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
*/
wmb();
- p->des0 = tdes0;
+ p->des0 = cpu_to_le32(tdes0);
}
static void enh_desc_set_tx_ic(struct dma_desc *p)
{
- p->des0 |= ETDES0_INTERRUPT;
+ p->des0 |= cpu_to_le32(ETDES0_INTERRUPT);
}
static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
@@ -372,18 +372,18 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
if (rx_coe_type == STMMAC_RX_COE_TYPE1)
csum = 2;
- return (((p->des0 & RDES0_FRAME_LEN_MASK) >> RDES0_FRAME_LEN_SHIFT) -
- csum);
+ return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
+ >> RDES0_FRAME_LEN_SHIFT) - csum);
}
static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
{
- p->des0 |= ETDES0_TIME_STAMP_ENABLE;
+ p->des0 |= cpu_to_le32(ETDES0_TIME_STAMP_ENABLE);
}
static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
{
- return (p->des0 & ETDES0_TIME_STAMP_STATUS) >> 17;
+ return (le32_to_cpu(p->des0) & ETDES0_TIME_STAMP_STATUS) >> 17;
}
static u64 enh_desc_get_timestamp(void *desc, u32 ats)
@@ -392,13 +392,13 @@ static u64 enh_desc_get_timestamp(void *desc, u32 ats)
if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
- ns = p->des6;
+ ns = le32_to_cpu(p->des6);
/* convert high/sec time stamp value to nanosecond */
- ns += p->des7 * 1000000000ULL;
+ ns += le32_to_cpu(p->des7) * 1000000000ULL;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
- ns = p->des2;
- ns += p->des3 * 1000000000ULL;
+ ns = le32_to_cpu(p->des2);
+ ns += le32_to_cpu(p->des3) * 1000000000ULL;
}
return ns;
@@ -408,10 +408,11 @@ static int enh_desc_get_rx_timestamp_status(void *desc, u32 ats)
{
if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
- return (p->basic.des0 & RDES0_IPC_CSUM_ERROR) >> 7;
+ return (le32_to_cpu(p->basic.des0) & RDES0_IPC_CSUM_ERROR) >> 7;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ if ((le32_to_cpu(p->des2) == 0xffffffff) &&
+ (le32_to_cpu(p->des3) == 0xffffffff))
/* timestamp is corrupted, hence don't store it */
return 0;
else
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 2beacd0d3043..fd78406e2e9a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -30,8 +30,8 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int tdes0 = p->des0;
- unsigned int tdes1 = p->des1;
+ unsigned int tdes0 = le32_to_cpu(p->des0);
+ unsigned int tdes1 = le32_to_cpu(p->des1);
int ret = tx_done;
/* Get tx owner first */
@@ -77,7 +77,7 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
static int ndesc_get_tx_len(struct dma_desc *p)
{
- return (p->des1 & RDES1_BUFFER1_SIZE_MASK);
+ return (le32_to_cpu(p->des1) & RDES1_BUFFER1_SIZE_MASK);
}
/* This function verifies if each incoming frame has some errors
@@ -88,7 +88,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p)
{
int ret = good_frame;
- unsigned int rdes0 = p->des0;
+ unsigned int rdes0 = le32_to_cpu(p->des0);
struct net_device_stats *stats = (struct net_device_stats *)data;
if (unlikely(rdes0 & RDES0_OWN))
@@ -141,8 +141,8 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
int end)
{
- p->des0 |= RDES0_OWN;
- p->des1 |= (BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK;
+ p->des0 |= cpu_to_le32(RDES0_OWN);
+ p->des1 |= cpu_to_le32((BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK);
if (mode == STMMAC_CHAIN_MODE)
ndesc_rx_set_on_chain(p, end);
@@ -150,12 +150,12 @@ static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
ndesc_rx_set_on_ring(p, end);
if (disable_rx_ic)
- p->des1 |= RDES1_DISABLE_IC;
+ p->des1 |= cpu_to_le32(RDES1_DISABLE_IC);
}
static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
{
- p->des0 &= ~TDES0_OWN;
+ p->des0 &= cpu_to_le32(~TDES0_OWN);
if (mode == STMMAC_CHAIN_MODE)
ndesc_tx_set_on_chain(p);
else
@@ -164,27 +164,27 @@ static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
static int ndesc_get_tx_owner(struct dma_desc *p)
{
- return (p->des0 & TDES0_OWN) >> 31;
+ return (le32_to_cpu(p->des0) & TDES0_OWN) >> 31;
}
static void ndesc_set_tx_owner(struct dma_desc *p)
{
- p->des0 |= TDES0_OWN;
+ p->des0 |= cpu_to_le32(TDES0_OWN);
}
static void ndesc_set_rx_owner(struct dma_desc *p)
{
- p->des0 |= RDES0_OWN;
+ p->des0 |= cpu_to_le32(RDES0_OWN);
}
static int ndesc_get_tx_ls(struct dma_desc *p)
{
- return (p->des1 & TDES1_LAST_SEGMENT) >> 30;
+ return (le32_to_cpu(p->des1) & TDES1_LAST_SEGMENT) >> 30;
}
static void ndesc_release_tx_desc(struct dma_desc *p, int mode)
{
- int ter = (p->des1 & TDES1_END_RING) >> 25;
+ int ter = (le32_to_cpu(p->des1) & TDES1_END_RING) >> 25;
memset(p, 0, offsetof(struct dma_desc, des2));
if (mode == STMMAC_CHAIN_MODE)
@@ -197,7 +197,7 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
bool csum_flag, int mode, bool tx_own,
bool ls)
{
- unsigned int tdes1 = p->des1;
+ unsigned int tdes1 = le32_to_cpu(p->des1);
if (is_fs)
tdes1 |= TDES1_FIRST_SEGMENT;
@@ -212,7 +212,7 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
if (ls)
tdes1 |= TDES1_LAST_SEGMENT;
- p->des1 = tdes1;
+ p->des1 = cpu_to_le32(tdes1);
if (mode == STMMAC_CHAIN_MODE)
norm_set_tx_desc_len_on_chain(p, len);
@@ -220,12 +220,12 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
norm_set_tx_desc_len_on_ring(p, len);
if (tx_own)
- p->des0 |= TDES0_OWN;
+ p->des0 |= cpu_to_le32(TDES0_OWN);
}
static void ndesc_set_tx_ic(struct dma_desc *p)
{
- p->des1 |= TDES1_INTERRUPT;
+ p->des1 |= cpu_to_le32(TDES1_INTERRUPT);
}
static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
@@ -241,19 +241,20 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
if (rx_coe_type == STMMAC_RX_COE_TYPE1)
csum = 2;
- return (((p->des0 & RDES0_FRAME_LEN_MASK) >> RDES0_FRAME_LEN_SHIFT) -
+ return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
+ >> RDES0_FRAME_LEN_SHIFT) -
csum);
}
static void ndesc_enable_tx_timestamp(struct dma_desc *p)
{
- p->des1 |= TDES1_TIME_STAMP_ENABLE;
+ p->des1 |= cpu_to_le32(TDES1_TIME_STAMP_ENABLE);
}
static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
{
- return (p->des0 & TDES0_TIME_STAMP_STATUS) >> 17;
+ return (le32_to_cpu(p->des0) & TDES0_TIME_STAMP_STATUS) >> 17;
}
static u64 ndesc_get_timestamp(void *desc, u32 ats)
@@ -261,9 +262,9 @@ static u64 ndesc_get_timestamp(void *desc, u32 ats)
struct dma_desc *p = (struct dma_desc *)desc;
u64 ns;
- ns = p->des2;
+ ns = le32_to_cpu(p->des2);
/* convert high/sec time stamp value to nanosecond */
- ns += p->des3 * 1000000000ULL;
+ ns += le32_to_cpu(p->des3) * 1000000000ULL;
return ns;
}
@@ -272,7 +273,8 @@ static int ndesc_get_rx_timestamp_status(void *desc, u32 ats)
{
struct dma_desc *p = (struct dma_desc *)desc;
- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ if ((le32_to_cpu(p->des2) == 0xffffffff) &&
+ (le32_to_cpu(p->des3) == 0xffffffff))
/* timestamp is corrupted, hence don't store it */
return 0;
else
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 7723b5d2499a..9983ce9bd90d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -34,7 +34,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
unsigned int entry = priv->cur_tx;
struct dma_desc *desc;
unsigned int nopaged_len = skb_headlen(skb);
- unsigned int bmax, len;
+ unsigned int bmax, len, des2;
if (priv->extend_desc)
desc = (struct dma_desc *)(priv->dma_etx + entry);
@@ -50,16 +50,17 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
if (nopaged_len > BUF_SIZE_8KiB) {
- desc->des2 = dma_map_single(priv->device, skb->data,
- bmax, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device, skb->data, bmax,
+ DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = bmax;
priv->tx_skbuff_dma[entry].is_jumbo = true;
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
STMMAC_RING_MODE, 0, false);
priv->tx_skbuff[entry] = NULL;
@@ -70,26 +71,28 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
else
desc = priv->dma_tx + entry;
- desc->des2 = dma_map_single(priv->device, skb->data + bmax,
- len, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device, skb->data + bmax, len,
+ DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = len;
priv->tx_skbuff_dma[entry].is_jumbo = true;
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
STMMAC_RING_MODE, 1, true);
} else {
- desc->des2 = dma_map_single(priv->device, skb->data,
- nopaged_len, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = nopaged_len;
priv->tx_skbuff_dma[entry].is_jumbo = true;
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
STMMAC_RING_MODE, 0, true);
}
@@ -115,13 +118,13 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
/* Fill DES3 in case of RING mode */
if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+ p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
}
/* In ring mode we need to fill the desc3 because it is used as buffer */
static void stmmac_init_desc3(struct dma_desc *p)
{
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+ p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
}
static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 4d2a759b8465..eab04aeeeb95 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -64,7 +64,6 @@ struct stmmac_priv {
dma_addr_t dma_tx_phy;
int tx_coalesce;
int hwts_tx_en;
- spinlock_t tx_lock;
bool tx_path_in_lpi_mode;
struct timer_list txtimer;
bool tso;
@@ -90,7 +89,6 @@ struct stmmac_priv {
struct mac_device_info *hw;
spinlock_t lock;
- struct phy_device *phydev ____cacheline_aligned_in_smp;
int oldlink;
int speed;
int oldduplex;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index c5d0142adda2..699ee1d30426 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -263,7 +263,7 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
- if (priv->plat->has_gmac)
+ if (priv->plat->has_gmac || priv->plat->has_gmac4)
strlcpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver));
else
strlcpy(info->driver, MAC100_ETHTOOL_NAME,
@@ -272,25 +272,26 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
}
-static int stmmac_ethtool_getsettings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = dev->phydev;
int rc;
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
struct rgmii_adv adv;
+ u32 supported, advertising, lp_advertising;
if (!priv->xstats.pcs_link) {
- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
- cmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
return 0;
}
- cmd->duplex = priv->xstats.pcs_duplex;
+ cmd->base.duplex = priv->xstats.pcs_duplex;
- ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed);
+ cmd->base.speed = priv->xstats.pcs_speed;
/* Get and convert ADV/LP_ADV from the HW AN registers */
if (!priv->hw->mac->pcs_get_adv_lp)
@@ -300,45 +301,59 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
/* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
+ ethtool_convert_link_mode_to_legacy_u32(
+ &supported, cmd->link_modes.supported);
+ ethtool_convert_link_mode_to_legacy_u32(
+ &advertising, cmd->link_modes.advertising);
+ ethtool_convert_link_mode_to_legacy_u32(
+ &lp_advertising, cmd->link_modes.lp_advertising);
+
if (adv.pause & STMMAC_PCS_PAUSE)
- cmd->advertising |= ADVERTISED_Pause;
+ advertising |= ADVERTISED_Pause;
if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
- cmd->advertising |= ADVERTISED_Asym_Pause;
+ advertising |= ADVERTISED_Asym_Pause;
if (adv.lp_pause & STMMAC_PCS_PAUSE)
- cmd->lp_advertising |= ADVERTISED_Pause;
+ lp_advertising |= ADVERTISED_Pause;
if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
- cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+ lp_advertising |= ADVERTISED_Asym_Pause;
/* Reg49[3] always set because ANE is always supported */
- cmd->autoneg = ADVERTISED_Autoneg;
- cmd->supported |= SUPPORTED_Autoneg;
- cmd->advertising |= ADVERTISED_Autoneg;
- cmd->lp_advertising |= ADVERTISED_Autoneg;
+ cmd->base.autoneg = ADVERTISED_Autoneg;
+ supported |= SUPPORTED_Autoneg;
+ advertising |= ADVERTISED_Autoneg;
+ lp_advertising |= ADVERTISED_Autoneg;
if (adv.duplex) {
- cmd->supported |= (SUPPORTED_1000baseT_Full |
- SUPPORTED_100baseT_Full |
- SUPPORTED_10baseT_Full);
- cmd->advertising |= (ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full |
- ADVERTISED_10baseT_Full);
+ supported |= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_10baseT_Full);
+ advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
} else {
- cmd->supported |= (SUPPORTED_1000baseT_Half |
- SUPPORTED_100baseT_Half |
- SUPPORTED_10baseT_Half);
- cmd->advertising |= (ADVERTISED_1000baseT_Half |
- ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Half);
+ supported |= (SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+ advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
}
if (adv.lp_duplex)
- cmd->lp_advertising |= (ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full |
- ADVERTISED_10baseT_Full);
+ lp_advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
else
- cmd->lp_advertising |= (ADVERTISED_1000baseT_Half |
- ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Half);
- cmd->port = PORT_OTHER;
+ lp_advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
+ cmd->base.port = PORT_OTHER;
+
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.supported, supported);
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.advertising, advertising);
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.lp_advertising, lp_advertising);
return 0;
}
@@ -353,16 +368,16 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
"link speed / duplex setting\n", dev->name);
return -EBUSY;
}
- cmd->transceiver = XCVR_INTERNAL;
- rc = phy_ethtool_gset(phy, cmd);
+ rc = phy_ethtool_ksettings_get(phy, cmd);
return rc;
}
-static int stmmac_ethtool_setsettings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+static int
+stmmac_ethtool_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = dev->phydev;
int rc;
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
@@ -370,7 +385,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
/* Only support ANE */
- if (cmd->autoneg != AUTONEG_ENABLE)
+ if (cmd->base.autoneg != AUTONEG_ENABLE)
return -EINVAL;
mask &= (ADVERTISED_1000baseT_Half |
@@ -391,9 +406,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
return 0;
}
- spin_lock(&priv->lock);
- rc = phy_ethtool_sset(phy, cmd);
- spin_unlock(&priv->lock);
+ rc = phy_ethtool_ksettings_set(phy, cmd);
return rc;
}
@@ -433,7 +446,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
memset(reg_space, 0x0, REG_SPACE_SIZE);
- if (!priv->plat->has_gmac) {
+ if (!(priv->plat->has_gmac || priv->plat->has_gmac4)) {
/* MAC registers */
for (i = 0; i < 12; i++)
reg_space[i] = readl(priv->ioaddr + (i * 4));
@@ -471,12 +484,12 @@ stmmac_get_pauseparam(struct net_device *netdev,
if (!adv_lp.pause)
return;
} else {
- if (!(priv->phydev->supported & SUPPORTED_Pause) ||
- !(priv->phydev->supported & SUPPORTED_Asym_Pause))
+ if (!(netdev->phydev->supported & SUPPORTED_Pause) ||
+ !(netdev->phydev->supported & SUPPORTED_Asym_Pause))
return;
}
- pause->autoneg = priv->phydev->autoneg;
+ pause->autoneg = netdev->phydev->autoneg;
if (priv->flow_ctrl & FLOW_RX)
pause->rx_pause = 1;
@@ -490,7 +503,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct stmmac_priv *priv = netdev_priv(netdev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = netdev->phydev;
int new_pause = FLOW_OFF;
if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
@@ -550,7 +563,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
}
}
if (priv->eee_enabled) {
- int val = phy_get_eee_err(priv->phydev);
+ int val = phy_get_eee_err(dev->phydev);
if (val)
priv->xstats.phy_eee_wakeup_error_n = val;
}
@@ -669,7 +682,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
edata->eee_active = priv->eee_active;
edata->tx_lpi_timer = priv->tx_lpi_timer;
- return phy_ethtool_get_eee(priv->phydev, edata);
+ return phy_ethtool_get_eee(dev->phydev, edata);
}
static int stmmac_ethtool_op_set_eee(struct net_device *dev,
@@ -694,7 +707,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
priv->tx_lpi_timer = edata->tx_lpi_timer;
}
- return phy_ethtool_set_eee(priv->phydev, edata);
+ return phy_ethtool_set_eee(dev->phydev, edata);
}
static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
@@ -853,13 +866,12 @@ static int stmmac_set_tunable(struct net_device *dev,
static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
- .get_settings = stmmac_ethtool_getsettings,
- .set_settings = stmmac_ethtool_setsettings,
.get_msglevel = stmmac_ethtool_getmsglevel,
.set_msglevel = stmmac_ethtool_setmsglevel,
.get_regs = stmmac_ethtool_gregs,
.get_regs_len = stmmac_ethtool_get_regs_len,
.get_link = ethtool_op_get_link,
+ .nway_reset = phy_ethtool_nway_reset,
.get_pauseparam = stmmac_get_pauseparam,
.set_pauseparam = stmmac_set_pauseparam,
.get_ethtool_stats = stmmac_get_ethtool_stats,
@@ -874,6 +886,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.set_coalesce = stmmac_set_coalesce,
.get_tunable = stmmac_get_tunable,
.set_tunable = stmmac_set_tunable,
+ .get_link_ksettings = stmmac_ethtool_get_link_ksettings,
+ .set_link_ksettings = stmmac_ethtool_set_link_ksettings,
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index caf069a465f2..3e405785b81c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -105,8 +105,8 @@ module_param(eee_timer, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
#define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
-/* By default the driver will use the ring mode to manage tx and rx descriptors
- * but passing this value so user can force to use the chain instead of the ring
+/* By default the driver will use the ring mode to manage tx and rx descriptors,
+ * but allow user to force to use the chain instead of the ring
*/
static unsigned int chain_mode;
module_param(chain_mode, int, S_IRUGO);
@@ -221,7 +221,8 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv)
*/
static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
{
- struct phy_device *phydev = priv->phydev;
+ struct net_device *ndev = priv->dev;
+ struct phy_device *phydev = ndev->phydev;
if (likely(priv->plat->fix_mac_speed))
priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
@@ -279,6 +280,7 @@ static void stmmac_eee_ctrl_timer(unsigned long arg)
*/
bool stmmac_eee_init(struct stmmac_priv *priv)
{
+ struct net_device *ndev = priv->dev;
unsigned long flags;
bool ret = false;
@@ -295,7 +297,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
int tx_lpi_timer = priv->tx_lpi_timer;
/* Check if the PHY supports EEE */
- if (phy_init_eee(priv->phydev, 1)) {
+ if (phy_init_eee(ndev->phydev, 1)) {
/* To manage at run-time if the EEE cannot be supported
* anymore (for example because the lp caps have been
* changed).
@@ -303,7 +305,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
*/
spin_lock_irqsave(&priv->lock, flags);
if (priv->eee_active) {
- pr_debug("stmmac: disable EEE\n");
+ netdev_dbg(priv->dev, "disable EEE\n");
del_timer_sync(&priv->eee_ctrl_timer);
priv->hw->mac->set_eee_timer(priv->hw, 0,
tx_lpi_timer);
@@ -327,12 +329,12 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
tx_lpi_timer);
}
/* Set HW EEE according to the speed */
- priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
+ priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link);
ret = true;
spin_unlock_irqrestore(&priv->lock, flags);
- pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
+ netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
}
out:
return ret;
@@ -450,8 +452,8 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
sizeof(struct hwtstamp_config)))
return -EFAULT;
- pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
- __func__, config.flags, config.tx_type, config.rx_filter);
+ netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
+ __func__, config.flags, config.tx_type, config.rx_filter);
/* reserved for future extensions */
if (config.flags)
@@ -697,7 +699,7 @@ static void stmmac_release_ptp(struct stmmac_priv *priv)
static void stmmac_adjust_link(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phydev = priv->phydev;
+ struct phy_device *phydev = dev->phydev;
unsigned long flags;
int new_state = 0;
unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
@@ -750,9 +752,9 @@ static void stmmac_adjust_link(struct net_device *dev)
stmmac_hw_fix_mac_speed(priv);
break;
default:
- if (netif_msg_link(priv))
- pr_warn("%s: Speed (%d) not 10/100\n",
- dev->name, phydev->speed);
+ netif_warn(priv, link, priv->dev,
+ "Speed (%d) not 10/100\n",
+ phydev->speed);
break;
}
@@ -805,10 +807,10 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
(interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
- pr_debug("STMMAC: PCS RGMII support enable\n");
+ netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
priv->hw->pcs = STMMAC_PCS_RGMII;
} else if (interface == PHY_INTERFACE_MODE_SGMII) {
- pr_debug("STMMAC: PCS SGMII support enable\n");
+ netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
priv->hw->pcs = STMMAC_PCS_SGMII;
}
}
@@ -843,15 +845,15 @@ static int stmmac_init_phy(struct net_device *dev)
snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
priv->plat->phy_addr);
- pr_debug("stmmac_init_phy: trying to attach to %s\n",
- phy_id_fmt);
+ netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__,
+ phy_id_fmt);
phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
interface);
}
if (IS_ERR_OR_NULL(phydev)) {
- pr_err("%s: Could not attach to PHY\n", dev->name);
+ netdev_err(priv->dev, "Could not attach to PHY\n");
if (!phydev)
return -ENODEV;
@@ -884,10 +886,8 @@ static int stmmac_init_phy(struct net_device *dev)
if (phydev->is_pseudo_fixed_link)
phydev->irq = PHY_POLL;
- pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)"
- " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
-
- priv->phydev = phydev;
+ netdev_dbg(priv->dev, "%s: attached to PHY (UID 0x%x) Link = %d\n",
+ __func__, phydev->phy_id, phydev->link);
return 0;
}
@@ -973,7 +973,8 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
if (!skb) {
- pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Rx init fails; skb is NULL\n", __func__);
return -ENOMEM;
}
priv->rx_skbuff[i] = skb;
@@ -981,15 +982,15 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
priv->dma_buf_sz,
DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
- pr_err("%s: DMA mapping error\n", __func__);
+ netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);
dev_kfree_skb_any(skb);
return -EINVAL;
}
if (priv->synopsys_id >= DWMAC_CORE_4_00)
- p->des0 = priv->rx_skbuff_dma[i];
+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]);
else
- p->des2 = priv->rx_skbuff_dma[i];
+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[i]);
if ((priv->hw->mode->init_desc3) &&
(priv->dma_buf_sz == BUF_SIZE_16KiB))
@@ -1031,13 +1032,14 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
priv->dma_buf_sz = bfsize;
- if (netif_msg_probe(priv)) {
- pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
- (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
+ netif_dbg(priv, probe, priv->dev,
+ "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n",
+ __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy);
+
+ /* RX INITIALIZATION */
+ netif_dbg(priv, probe, priv->dev,
+ "SKB addresses:\nskb\t\tskb data\tdma data\n");
- /* RX INITIALIZATION */
- pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
- }
for (i = 0; i < DMA_RX_SIZE; i++) {
struct dma_desc *p;
if (priv->extend_desc)
@@ -1049,10 +1051,9 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
if (ret)
goto err_init_rx_buffers;
- if (netif_msg_probe(priv))
- pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
- priv->rx_skbuff[i]->data,
- (unsigned int)priv->rx_skbuff_dma[i]);
+ netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n",
+ priv->rx_skbuff[i], priv->rx_skbuff[i]->data,
+ (unsigned int)priv->rx_skbuff_dma[i]);
}
priv->cur_rx = 0;
priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
@@ -1307,7 +1308,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
unsigned int bytes_compl = 0, pkts_compl = 0;
unsigned int entry = priv->dirty_tx;
- spin_lock(&priv->tx_lock);
+ netif_tx_lock(priv->dev);
priv->xstats.tx_clean++;
@@ -1378,22 +1379,17 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
if (unlikely(netif_queue_stopped(priv->dev) &&
- stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) {
- netif_tx_lock(priv->dev);
- if (netif_queue_stopped(priv->dev) &&
- stmmac_tx_avail(priv) > STMMAC_TX_THRESH) {
- if (netif_msg_tx_done(priv))
- pr_debug("%s: restart transmit\n", __func__);
- netif_wake_queue(priv->dev);
- }
- netif_tx_unlock(priv->dev);
+ stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) {
+ netif_dbg(priv, tx_done, priv->dev,
+ "%s: restart transmit\n", __func__);
+ netif_wake_queue(priv->dev);
}
if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
stmmac_enable_eee_mode(priv);
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
}
- spin_unlock(&priv->tx_lock);
+ netif_tx_unlock(priv->dev);
}
static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
@@ -1497,7 +1493,7 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv)
dwmac_mmc_ctrl(priv->mmcaddr, mode);
memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
} else
- pr_info(" No MAC Management Counters available\n");
+ netdev_info(priv->dev, "No MAC Management Counters available\n");
}
/**
@@ -1510,18 +1506,18 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv)
static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
{
if (priv->plat->enh_desc) {
- pr_info(" Enhanced/Alternate descriptors\n");
+ dev_info(priv->device, "Enhanced/Alternate descriptors\n");
/* GMAC older than 3.50 has no extended descriptors */
if (priv->synopsys_id >= DWMAC_CORE_3_50) {
- pr_info("\tEnabled extended descriptors\n");
+ dev_info(priv->device, "Enabled extended descriptors\n");
priv->extend_desc = 1;
} else
- pr_warn("Extended descriptors not supported\n");
+ dev_warn(priv->device, "Extended descriptors not supported\n");
priv->hw->desc = &enh_desc_ops;
} else {
- pr_info(" Normal descriptors\n");
+ dev_info(priv->device, "Normal descriptors\n");
priv->hw->desc = &ndesc_ops;
}
}
@@ -1562,8 +1558,8 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv)
priv->dev->dev_addr, 0);
if (!is_valid_ether_addr(priv->dev->dev_addr))
eth_hw_addr_random(priv->dev);
- pr_info("%s: device MAC address %pM\n", priv->dev->name,
- priv->dev->dev_addr);
+ netdev_info(priv->dev, "device MAC address %pM\n",
+ priv->dev->dev_addr);
}
}
@@ -1577,16 +1573,12 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv)
*/
static int stmmac_init_dma_engine(struct stmmac_priv *priv)
{
- int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, aal = 0;
- int mixed_burst = 0;
int atds = 0;
int ret = 0;
- if (priv->plat->dma_cfg) {
- pbl = priv->plat->dma_cfg->pbl;
- fixed_burst = priv->plat->dma_cfg->fixed_burst;
- mixed_burst = priv->plat->dma_cfg->mixed_burst;
- aal = priv->plat->dma_cfg->aal;
+ if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
+ dev_err(priv->device, "Invalid DMA configuration\n");
+ return -EINVAL;
}
if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
@@ -1598,8 +1590,8 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
return ret;
}
- priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
- aal, priv->dma_tx_phy, priv->dma_rx_phy, atds);
+ priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg,
+ priv->dma_tx_phy, priv->dma_rx_phy, atds);
if (priv->synopsys_id >= DWMAC_CORE_4_00) {
priv->rx_tail_addr = priv->dma_rx_phy +
@@ -1671,7 +1663,8 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
/* DMA initialization and SW reset */
ret = stmmac_init_dma_engine(priv);
if (ret < 0) {
- pr_err("%s: DMA engine initialization failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
+ __func__);
return ret;
}
@@ -1700,7 +1693,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
ret = priv->hw->mac->rx_ipc(priv->hw);
if (!ret) {
- pr_warn(" RX IPC Checksum Offload disabled\n");
+ netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
priv->plat->rx_coe = STMMAC_RX_COE_NONE;
priv->hw->rx_csum = 0;
}
@@ -1725,10 +1718,11 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
#ifdef CONFIG_DEBUG_FS
ret = stmmac_init_fs(dev);
if (ret < 0)
- pr_warn("%s: failed debugFS registration\n", __func__);
+ netdev_warn(priv->dev, "%s: failed debugFS registration\n",
+ __func__);
#endif
/* Start the ball rolling... */
- pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
+ netdev_dbg(priv->dev, "DMA RX/TX processes started...\n");
priv->hw->dma->start_tx(priv->ioaddr);
priv->hw->dma->start_rx(priv->ioaddr);
@@ -1783,8 +1777,9 @@ static int stmmac_open(struct net_device *dev)
priv->hw->pcs != STMMAC_PCS_RTBI) {
ret = stmmac_init_phy(dev);
if (ret) {
- pr_err("%s: Cannot attach to PHY (error: %d)\n",
- __func__, ret);
+ netdev_err(priv->dev,
+ "%s: Cannot attach to PHY (error: %d)\n",
+ __func__, ret);
return ret;
}
}
@@ -1798,33 +1793,36 @@ static int stmmac_open(struct net_device *dev)
ret = alloc_dma_desc_resources(priv);
if (ret < 0) {
- pr_err("%s: DMA descriptors allocation failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
+ __func__);
goto dma_desc_error;
}
ret = init_dma_desc_rings(dev, GFP_KERNEL);
if (ret < 0) {
- pr_err("%s: DMA descriptors initialization failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
+ __func__);
goto init_error;
}
ret = stmmac_hw_setup(dev, true);
if (ret < 0) {
- pr_err("%s: Hw setup failed\n", __func__);
+ netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
goto init_error;
}
stmmac_init_tx_coalesce(priv);
- if (priv->phydev)
- phy_start(priv->phydev);
+ if (dev->phydev)
+ phy_start(dev->phydev);
/* Request the IRQ lines */
ret = request_irq(dev->irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
- __func__, dev->irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the IRQ %d (error: %d)\n",
+ __func__, dev->irq, ret);
goto init_error;
}
@@ -1833,8 +1831,9 @@ static int stmmac_open(struct net_device *dev)
ret = request_irq(priv->wol_irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
- __func__, priv->wol_irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the WoL IRQ %d (%d)\n",
+ __func__, priv->wol_irq, ret);
goto wolirq_error;
}
}
@@ -1844,8 +1843,9 @@ static int stmmac_open(struct net_device *dev)
ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
- __func__, priv->lpi_irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the LPI IRQ %d (%d)\n",
+ __func__, priv->lpi_irq, ret);
goto lpiirq_error;
}
}
@@ -1864,8 +1864,8 @@ wolirq_error:
init_error:
free_dma_desc_resources(priv);
dma_desc_error:
- if (priv->phydev)
- phy_disconnect(priv->phydev);
+ if (dev->phydev)
+ phy_disconnect(dev->phydev);
return ret;
}
@@ -1884,10 +1884,9 @@ static int stmmac_release(struct net_device *dev)
del_timer_sync(&priv->eee_ctrl_timer);
/* Stop and disconnect the PHY */
- if (priv->phydev) {
- phy_stop(priv->phydev);
- phy_disconnect(priv->phydev);
- priv->phydev = NULL;
+ if (dev->phydev) {
+ phy_stop(dev->phydev);
+ phy_disconnect(dev->phydev);
}
netif_stop_queue(dev);
@@ -1947,7 +1946,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
desc = priv->dma_tx + priv->cur_tx;
- desc->des0 = des + (total_len - tmp_len);
+ desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
TSO_MAX_BUFF_SIZE : tmp_len;
@@ -1998,8 +1997,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
u8 proto_hdr_len;
int i;
- spin_lock(&priv->tx_lock);
-
/* Compute header lengths */
proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -2009,9 +2006,10 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
/* This is a hard error, log it. */
- pr_err("%s: Tx Ring full when queue awake\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Tx Ring full when queue awake\n",
+ __func__);
}
- spin_unlock(&priv->tx_lock);
return NETDEV_TX_BUSY;
}
@@ -2049,11 +2047,11 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
priv->tx_skbuff[first_entry] = skb;
- first->des0 = des;
+ first->des0 = cpu_to_le32(des);
/* Fill start of payload in buff2 of first descriptor */
if (pay_len)
- first->des1 = des + proto_hdr_len;
+ first->des1 = cpu_to_le32(des + proto_hdr_len);
/* If needed take extra descriptors to fill the remaining payload */
tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
@@ -2082,8 +2080,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
- if (netif_msg_hw(priv))
- pr_debug("%s: stop transmitted packets\n", __func__);
+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
+ __func__);
netif_stop_queue(dev);
}
@@ -2146,11 +2144,9 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr,
STMMAC_CHAN0);
- spin_unlock(&priv->tx_lock);
return NETDEV_TX_OK;
dma_map_err:
- spin_unlock(&priv->tx_lock);
dev_err(priv->device, "Tx dma map failed\n");
dev_kfree_skb(skb);
priv->dev->stats.tx_dropped++;
@@ -2182,14 +2178,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return stmmac_tso_xmit(skb, dev);
}
- spin_lock(&priv->tx_lock);
-
if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
- spin_unlock(&priv->tx_lock);
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
/* This is a hard error, log it. */
- pr_err("%s: Tx Ring full when queue awake\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Tx Ring full when queue awake\n",
+ __func__);
}
return NETDEV_TX_BUSY;
}
@@ -2242,13 +2237,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->tx_skbuff[entry] = NULL;
- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- desc->des0 = des;
- priv->tx_skbuff_dma[entry].buf = desc->des0;
- } else {
- desc->des2 = des;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
- }
+ priv->tx_skbuff_dma[entry].buf = des;
+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
+ desc->des0 = cpu_to_le32(des);
+ else
+ desc->des2 = cpu_to_le32(des);
priv->tx_skbuff_dma[entry].map_as_page = true;
priv->tx_skbuff_dma[entry].len = len;
@@ -2266,9 +2259,10 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
if (netif_msg_pktdata(priv)) {
void *tx_head;
- pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
- __func__, priv->cur_tx, priv->dirty_tx, first_entry,
- entry, first, nfrags);
+ netdev_dbg(priv->dev,
+ "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
+ __func__, priv->cur_tx, priv->dirty_tx, first_entry,
+ entry, first, nfrags);
if (priv->extend_desc)
tx_head = (void *)priv->dma_etx;
@@ -2277,13 +2271,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false);
- pr_debug(">>> frame to be transmitted: ");
+ netdev_dbg(priv->dev, ">>> frame to be transmitted: ");
print_pkt(skb->data, skb->len);
}
if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
- if (netif_msg_hw(priv))
- pr_debug("%s: stop transmitted packets\n", __func__);
+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
+ __func__);
netif_stop_queue(dev);
}
@@ -2319,13 +2313,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(priv->device, des))
goto dma_map_err;
- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- first->des0 = des;
- priv->tx_skbuff_dma[first_entry].buf = first->des0;
- } else {
- first->des2 = des;
- priv->tx_skbuff_dma[first_entry].buf = first->des2;
- }
+ priv->tx_skbuff_dma[first_entry].buf = des;
+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
+ first->des0 = cpu_to_le32(des);
+ else
+ first->des2 = cpu_to_le32(des);
priv->tx_skbuff_dma[first_entry].len = nopaged_len;
priv->tx_skbuff_dma[first_entry].last_segment = last_segment;
@@ -2357,12 +2349,10 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr,
STMMAC_CHAN0);
- spin_unlock(&priv->tx_lock);
return NETDEV_TX_OK;
dma_map_err:
- spin_unlock(&priv->tx_lock);
- dev_err(priv->device, "Tx dma map failed\n");
+ netdev_err(priv->dev, "Tx DMA map failed\n");
dev_kfree_skb(skb);
priv->dev->stats.tx_dropped++;
return NETDEV_TX_OK;
@@ -2433,16 +2423,16 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device,
priv->rx_skbuff_dma[entry])) {
- dev_err(priv->device, "Rx dma map failed\n");
+ netdev_err(priv->dev, "Rx DMA map failed\n");
dev_kfree_skb(skb);
break;
}
if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- p->des0 = priv->rx_skbuff_dma[entry];
+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
p->des1 = 0;
} else {
- p->des2 = priv->rx_skbuff_dma[entry];
+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
}
if (priv->hw->mode->refill_desc3)
priv->hw->mode->refill_desc3(priv, p);
@@ -2450,8 +2440,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
if (priv->rx_zeroc_thresh > 0)
priv->rx_zeroc_thresh--;
- if (netif_msg_rx_status(priv))
- pr_debug("\trefill entry #%d\n", entry);
+ netif_dbg(priv, rx_status, priv->dev,
+ "refill entry #%d\n", entry);
}
wmb();
@@ -2484,7 +2474,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
if (netif_msg_rx_status(priv)) {
void *rx_head;
- pr_info(">>>>>> %s: descriptor ring:\n", __func__);
+ netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
if (priv->extend_desc)
rx_head = (void *)priv->dma_erx;
else
@@ -2546,9 +2536,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
unsigned int des;
if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
- des = p->des0;
+ des = le32_to_cpu(p->des0);
else
- des = p->des2;
+ des = le32_to_cpu(p->des2);
frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
@@ -2557,9 +2547,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
* ignored
*/
if (frame_len > priv->dma_buf_sz) {
- pr_err("%s: len %d larger than size (%d)\n",
- priv->dev->name, frame_len,
- priv->dma_buf_sz);
+ netdev_err(priv->dev,
+ "len %d larger than size (%d)\n",
+ frame_len, priv->dma_buf_sz);
priv->dev->stats.rx_length_errors++;
break;
}
@@ -2571,11 +2561,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
frame_len -= ETH_FCS_LEN;
if (netif_msg_rx_status(priv)) {
- pr_info("\tdesc: %p [entry %d] buff=0x%x\n",
- p, entry, des);
+ netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n",
+ p, entry, des);
if (frame_len > ETH_FRAME_LEN)
- pr_debug("\tframe size %d, COE: %d\n",
- frame_len, status);
+ netdev_dbg(priv->dev, "frame size %d, COE: %d\n",
+ frame_len, status);
}
/* The zero-copy is always used for all the sizes
@@ -2612,8 +2602,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
} else {
skb = priv->rx_skbuff[entry];
if (unlikely(!skb)) {
- pr_err("%s: Inconsistent Rx chain\n",
- priv->dev->name);
+ netdev_err(priv->dev,
+ "%s: Inconsistent Rx chain\n",
+ priv->dev->name);
priv->dev->stats.rx_dropped++;
break;
}
@@ -2629,7 +2620,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
}
if (netif_msg_pktdata(priv)) {
- pr_debug("frame received (%dbytes)", frame_len);
+ netdev_dbg(priv->dev, "frame received (%dbytes)",
+ frame_len);
print_pkt(skb->data, frame_len);
}
@@ -2729,26 +2721,12 @@ static void stmmac_set_rx_mode(struct net_device *dev)
static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int max_mtu;
if (netif_running(dev)) {
- pr_err("%s: must be stopped to change its MTU\n", dev->name);
+ netdev_err(priv->dev, "must be stopped to change its MTU\n");
return -EBUSY;
}
- if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
- max_mtu = JUMBO_LEN;
- else
- max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
-
- if (priv->plat->maxmtu < max_mtu)
- max_mtu = priv->plat->maxmtu;
-
- if ((new_mtu < 46) || (new_mtu > max_mtu)) {
- pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
- return -EINVAL;
- }
-
dev->mtu = new_mtu;
netdev_update_features(dev);
@@ -2824,7 +2802,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
pm_wakeup_event(priv->device, 0);
if (unlikely(!dev)) {
- pr_err("%s: invalid dev pointer\n", __func__);
+ netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
return IRQ_NONE;
}
@@ -2882,7 +2860,6 @@ static void stmmac_poll_controller(struct net_device *dev)
*/
static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct stmmac_priv *priv = netdev_priv(dev);
int ret = -EOPNOTSUPP;
if (!netif_running(dev))
@@ -2892,9 +2869,9 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
- if (!priv->phydev)
+ if (!dev->phydev)
return -EINVAL;
- ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ ret = phy_mii_ioctl(dev->phydev, rq, cmd);
break;
case SIOCSHWTSTAMP:
ret = stmmac_hwtstamp_ioctl(dev, rq);
@@ -2922,14 +2899,17 @@ static void sysfs_display_ring(void *head, int size, int extend_desc,
x = *(u64 *) ep;
seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(ep),
- ep->basic.des0, ep->basic.des1,
- ep->basic.des2, ep->basic.des3);
+ le32_to_cpu(ep->basic.des0),
+ le32_to_cpu(ep->basic.des1),
+ le32_to_cpu(ep->basic.des2),
+ le32_to_cpu(ep->basic.des3));
ep++;
} else {
x = *(u64 *) p;
seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(ep),
- p->des0, p->des1, p->des2, p->des3);
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+ le32_to_cpu(p->des2), le32_to_cpu(p->des3));
p++;
}
seq_printf(seq, "\n");
@@ -2961,6 +2941,8 @@ static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
}
+/* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */
+
static const struct file_operations stmmac_rings_status_fops = {
.owner = THIS_MODULE,
.open = stmmac_sysfs_ring_open,
@@ -2983,11 +2965,11 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
seq_printf(seq, "\tDMA HW features\n");
seq_printf(seq, "==============================\n");
- seq_printf(seq, "\t10/100 Mbps %s\n",
+ seq_printf(seq, "\t10/100 Mbps: %s\n",
(priv->dma_cap.mbps_10_100) ? "Y" : "N");
- seq_printf(seq, "\t1000 Mbps %s\n",
+ seq_printf(seq, "\t1000 Mbps: %s\n",
(priv->dma_cap.mbps_1000) ? "Y" : "N");
- seq_printf(seq, "\tHalf duple %s\n",
+ seq_printf(seq, "\tHalf duplex: %s\n",
(priv->dma_cap.half_duplex) ? "Y" : "N");
seq_printf(seq, "\tHash Filter: %s\n",
(priv->dma_cap.hash_filter) ? "Y" : "N");
@@ -3005,9 +2987,9 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
(priv->dma_cap.rmon) ? "Y" : "N");
seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
(priv->dma_cap.time_stamp) ? "Y" : "N");
- seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
+ seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n",
(priv->dma_cap.atime_stamp) ? "Y" : "N");
- seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
+ seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n",
(priv->dma_cap.eee) ? "Y" : "N");
seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
seq_printf(seq, "\tChecksum Offload in TX: %s\n",
@@ -3054,8 +3036,7 @@ static int stmmac_init_fs(struct net_device *dev)
priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
- pr_err("ERROR %s/%s, debugfs create directory failed\n",
- STMMAC_RESOURCE_NAME, dev->name);
+ netdev_err(priv->dev, "ERROR failed to create debugfs directory\n");
return -ENOMEM;
}
@@ -3067,7 +3048,7 @@ static int stmmac_init_fs(struct net_device *dev)
&stmmac_rings_status_fops);
if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
- pr_info("ERROR creating stmmac ring debugfs file\n");
+ netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n");
debugfs_remove_recursive(priv->dbgfs_dir);
return -ENOMEM;
@@ -3079,7 +3060,7 @@ static int stmmac_init_fs(struct net_device *dev)
dev, &stmmac_dma_cap_fops);
if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
- pr_info("ERROR creating stmmac MMC debugfs file\n");
+ netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n");
debugfs_remove_recursive(priv->dbgfs_dir);
return -ENOMEM;
@@ -3151,11 +3132,11 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
} else {
if (chain_mode) {
priv->hw->mode = &chain_mode_ops;
- pr_info(" Chain mode enabled\n");
+ dev_info(priv->device, "Chain mode enabled\n");
priv->mode = STMMAC_CHAIN_MODE;
} else {
priv->hw->mode = &ring_mode_ops;
- pr_info(" Ring mode enabled\n");
+ dev_info(priv->device, "Ring mode enabled\n");
priv->mode = STMMAC_RING_MODE;
}
}
@@ -3163,7 +3144,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
/* Get the HW capability (new GMAC newer than 3.50a) */
priv->hw_cap_support = stmmac_get_hw_features(priv);
if (priv->hw_cap_support) {
- pr_info(" DMA HW capability register supported");
+ dev_info(priv->device, "DMA HW capability register supported\n");
/* We can override some gmac/dma configuration fields: e.g.
* enh_desc, tx_coe (e.g. that are passed through the
@@ -3188,8 +3169,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
else if (priv->dma_cap.rx_coe_type1)
priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
- } else
- pr_info(" No HW DMA feature register supported");
+ } else {
+ dev_info(priv->device, "No HW DMA feature register supported\n");
+ }
/* To use alternate (extended), normal or GMAC4 descriptor structures */
if (priv->synopsys_id >= DWMAC_CORE_4_00)
@@ -3199,20 +3181,20 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
if (priv->plat->rx_coe) {
priv->hw->rx_csum = priv->plat->rx_coe;
- pr_info(" RX Checksum Offload Engine supported\n");
+ dev_info(priv->device, "RX Checksum Offload Engine supported\n");
if (priv->synopsys_id < DWMAC_CORE_4_00)
- pr_info("\tCOE Type %d\n", priv->hw->rx_csum);
+ dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
}
if (priv->plat->tx_coe)
- pr_info(" TX Checksum insertion supported\n");
+ dev_info(priv->device, "TX Checksum insertion supported\n");
if (priv->plat->pmt) {
- pr_info(" Wake-Up On Lan supported\n");
+ dev_info(priv->device, "Wake-Up On Lan supported\n");
device_set_wakeup_capable(priv->device, 1);
}
if (priv->dma_cap.tsoen)
- pr_info(" TSO supported\n");
+ dev_info(priv->device, "TSO supported\n");
return 0;
}
@@ -3271,8 +3253,8 @@ int stmmac_dvr_probe(struct device *device,
priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
if (IS_ERR(priv->stmmac_clk)) {
- dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
- __func__);
+ netdev_warn(priv->dev, "%s: warning: cannot get CSR clock\n",
+ __func__);
/* If failed to obtain stmmac_clk and specific clk_csr value
* is NOT passed from the platform, probe fail.
*/
@@ -3321,7 +3303,7 @@ int stmmac_dvr_probe(struct device *device,
if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
ndev->hw_features |= NETIF_F_TSO;
priv->tso = true;
- pr_info(" TSO feature enabled\n");
+ dev_info(priv->device, "TSO feature enabled\n");
}
ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
@@ -3331,6 +3313,15 @@ int stmmac_dvr_probe(struct device *device,
#endif
priv->msg_enable = netif_msg_init(debug, default_msg_level);
+ /* MTU range: 46 - hw-specific max */
+ ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
+ ndev->max_mtu = JUMBO_LEN;
+ else
+ ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
+ if (priv->plat->maxmtu < ndev->max_mtu)
+ ndev->max_mtu = priv->plat->maxmtu;
+
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
@@ -3341,17 +3332,17 @@ int stmmac_dvr_probe(struct device *device,
*/
if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
priv->use_riwt = 1;
- pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+ netdev_info(priv->dev, "Enable RX Mitigation via HW Watchdog Timer\n");
}
netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
spin_lock_init(&priv->lock);
- spin_lock_init(&priv->tx_lock);
ret = register_netdev(ndev);
if (ret) {
- pr_err("%s: ERROR %i registering the device\n", __func__, ret);
+ netdev_err(priv->dev, "%s: ERROR %i registering the device\n",
+ __func__, ret);
goto error_netdev_register;
}
@@ -3374,8 +3365,9 @@ int stmmac_dvr_probe(struct device *device,
/* MDIO bus Registration */
ret = stmmac_mdio_register(ndev);
if (ret < 0) {
- pr_debug("%s: MDIO bus (id: %d) registration failed",
- __func__, priv->plat->bus_id);
+ netdev_err(priv->dev,
+ "%s: MDIO bus (id: %d) registration failed",
+ __func__, priv->plat->bus_id);
goto error_mdio_register;
}
}
@@ -3408,7 +3400,7 @@ int stmmac_dvr_remove(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
- pr_info("%s:\n\tremoving driver", __func__);
+ netdev_info(priv->dev, "%s: removing driver", __func__);
priv->hw->dma->stop_rx(priv->ioaddr);
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -3446,8 +3438,8 @@ int stmmac_suspend(struct device *dev)
if (!ndev || !netif_running(ndev))
return 0;
- if (priv->phydev)
- phy_stop(priv->phydev);
+ if (ndev->phydev)
+ phy_stop(ndev->phydev);
spin_lock_irqsave(&priv->lock, flags);
@@ -3541,8 +3533,8 @@ int stmmac_resume(struct device *dev)
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->phydev)
- phy_start(priv->phydev);
+ if (ndev->phydev)
+ phy_start(ndev->phydev);
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index ec295851812b..23322fd9e3ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -42,13 +42,6 @@
#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
-#define MII_PHY_ADDR_GMAC4_SHIFT 21
-#define MII_PHY_ADDR_GMAC4_MASK GENMASK(25, 21)
-#define MII_PHY_REG_GMAC4_SHIFT 16
-#define MII_PHY_REG_GMAC4_MASK GENMASK(20, 16)
-#define MII_CSR_CLK_GMAC4_SHIFT 8
-#define MII_CSR_CLK_GMAC4_MASK GENMASK(11, 8)
-
static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
{
unsigned long curr;
@@ -68,8 +61,8 @@ static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
/**
* stmmac_mdio_read
* @bus: points to the mii_bus structure
- * @phyaddr: MII addr reg bits 15-11
- * @phyreg: MII addr reg bits 10-6
+ * @phyaddr: MII addr
+ * @phyreg: MII reg
* Description: it reads data from the MII register from within the phy device.
* For the 7111 GMAC, we must set the bit 0 in the MII address register while
* accessing the PHY registers.
@@ -83,14 +76,20 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
unsigned int mii_data = priv->hw->mii.data;
int data;
- u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
- ((phyreg << 6) & (0x000007C0)));
- regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
+ u32 value = MII_BUSY;
+
+ value |= (phyaddr << priv->hw->mii.addr_shift)
+ & priv->hw->mii.addr_mask;
+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
+ value |= (priv->clk_csr & priv->hw->mii.clk_csr_mask)
+ << priv->hw->mii.clk_csr_shift;
+ if (priv->plat->has_gmac4)
+ value |= MII_GMAC4_READ;
if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
return -EBUSY;
- writel(regValue, priv->ioaddr + mii_address);
+ writel(value, priv->ioaddr + mii_address);
if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
return -EBUSY;
@@ -104,8 +103,8 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
/**
* stmmac_mdio_write
* @bus: points to the mii_bus structure
- * @phyaddr: MII addr reg bits 15-11
- * @phyreg: MII addr reg bits 10-6
+ * @phyaddr: MII addr
+ * @phyreg: MII reg
* @phydata: phy data
* Description: it writes the data into the MII register from within the device.
*/
@@ -117,85 +116,16 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data;
- u16 value =
- (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
- | MII_WRITE;
-
- value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
-
- /* Wait until any existing MII operation is complete */
- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
- return -EBUSY;
-
- /* Set the MII address register to write */
- writel(phydata, priv->ioaddr + mii_data);
- writel(value, priv->ioaddr + mii_address);
-
- /* Wait until any existing MII operation is complete */
- return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
-}
-
-/**
- * stmmac_mdio_read_gmac4
- * @bus: points to the mii_bus structure
- * @phyaddr: MII addr reg bits 25-21
- * @phyreg: MII addr reg bits 20-16
- * Description: it reads data from the MII register of GMAC4 from within
- * the phy device.
- */
-static int stmmac_mdio_read_gmac4(struct mii_bus *bus, int phyaddr, int phyreg)
-{
- struct net_device *ndev = bus->priv;
- struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned int mii_address = priv->hw->mii.addr;
- unsigned int mii_data = priv->hw->mii.data;
- int data;
- u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
- (MII_PHY_ADDR_GMAC4_MASK)) |
- ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
- (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_READ;
-
- value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
- << MII_CSR_CLK_GMAC4_SHIFT);
-
- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
- return -EBUSY;
-
- writel(value, priv->ioaddr + mii_address);
-
- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
- return -EBUSY;
-
- /* Read the data from the MII data register */
- data = (int)readl(priv->ioaddr + mii_data);
-
- return data;
-}
+ u32 value = MII_WRITE | MII_BUSY;
-/**
- * stmmac_mdio_write_gmac4
- * @bus: points to the mii_bus structure
- * @phyaddr: MII addr reg bits 25-21
- * @phyreg: MII addr reg bits 20-16
- * @phydata: phy data
- * Description: it writes the data into the MII register of GMAC4 from within
- * the device.
- */
-static int stmmac_mdio_write_gmac4(struct mii_bus *bus, int phyaddr, int phyreg,
- u16 phydata)
-{
- struct net_device *ndev = bus->priv;
- struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned int mii_address = priv->hw->mii.addr;
- unsigned int mii_data = priv->hw->mii.data;
-
- u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
- (MII_PHY_ADDR_GMAC4_MASK)) |
- ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
- (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_WRITE;
+ value |= (phyaddr << priv->hw->mii.addr_shift)
+ & priv->hw->mii.addr_mask;
+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
- value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
- << MII_CSR_CLK_GMAC4_SHIFT);
+ value |= ((priv->clk_csr & priv->hw->mii.clk_csr_mask)
+ << priv->hw->mii.clk_csr_shift);
+ if (priv->plat->has_gmac4)
+ value |= MII_GMAC4_WRITE;
/* Wait until any existing MII operation is complete */
if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
@@ -260,7 +190,7 @@ int stmmac_mdio_reset(struct mii_bus *bus)
#endif
if (data->phy_reset) {
- pr_debug("stmmac_mdio_reset: calling phy_reset\n");
+ netdev_dbg(ndev, "stmmac_mdio_reset: calling phy_reset\n");
data->phy_reset(priv->plat->bsp_priv);
}
@@ -305,13 +235,8 @@ int stmmac_mdio_register(struct net_device *ndev)
#endif
new_bus->name = "stmmac";
- if (priv->plat->has_gmac4) {
- new_bus->read = &stmmac_mdio_read_gmac4;
- new_bus->write = &stmmac_mdio_write_gmac4;
- } else {
- new_bus->read = &stmmac_mdio_read;
- new_bus->write = &stmmac_mdio_write;
- }
+ new_bus->read = &stmmac_mdio_read;
+ new_bus->write = &stmmac_mdio_write;
new_bus->reset = &stmmac_mdio_reset;
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
@@ -325,7 +250,7 @@ int stmmac_mdio_register(struct net_device *ndev)
else
err = mdiobus_register(new_bus);
if (err != 0) {
- pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
+ netdev_err(ndev, "Cannot register the MDIO bus\n");
goto bus_register_fail;
}
@@ -372,16 +297,16 @@ int stmmac_mdio_register(struct net_device *ndev)
irq_str = irq_num;
break;
}
- pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
- ndev->name, phydev->phy_id, addr,
- irq_str, phydev_name(phydev),
- act ? " active" : "");
+ netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
+ phydev->phy_id, addr,
+ irq_str, phydev_name(phydev),
+ act ? " active" : "");
found = 1;
}
}
if (!found && !mdio_node) {
- pr_warn("%s: No PHY found\n", ndev->name);
+ netdev_warn(ndev, "No PHY found\n");
mdiobus_unregister(new_bus);
mdiobus_free(new_bus);
return -ENODEV;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 56c8a2342c14..a2831773431a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -81,6 +81,7 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
plat->mdio_bus_data->phy_mask = 0;
plat->dma_cfg->pbl = 32;
+ plat->dma_cfg->pblx8 = true;
/* TODO: AXI */
/* Set default value for multicast hash bins */
@@ -115,6 +116,7 @@ static int quark_default_data(struct plat_stmmacenet_data *plat,
plat->mdio_bus_data->phy_mask = 0;
plat->dma_cfg->pbl = 16;
+ plat->dma_cfg->pblx8 = true;
plat->dma_cfg->fixed_burst = 1;
/* AXI (TODO) */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index ac3d39c69509..082cd48db6a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -292,6 +292,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
of_device_is_compatible(np, "snps,dwmac-4.10a")) {
plat->has_gmac4 = 1;
+ plat->has_gmac = 0;
plat->pmt = 1;
plat->tso_en = of_property_read_bool(np, "snps,tso");
}
@@ -303,21 +304,25 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
plat->force_sf_dma_mode = 1;
}
- if (of_find_property(np, "snps,pbl", NULL)) {
- dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
- GFP_KERNEL);
- if (!dma_cfg) {
- stmmac_remove_config_dt(pdev, plat);
- return ERR_PTR(-ENOMEM);
- }
- plat->dma_cfg = dma_cfg;
- of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
- dma_cfg->aal = of_property_read_bool(np, "snps,aal");
- dma_cfg->fixed_burst =
- of_property_read_bool(np, "snps,fixed-burst");
- dma_cfg->mixed_burst =
- of_property_read_bool(np, "snps,mixed-burst");
+ dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
+ GFP_KERNEL);
+ if (!dma_cfg) {
+ stmmac_remove_config_dt(pdev, plat);
+ return ERR_PTR(-ENOMEM);
}
+ plat->dma_cfg = dma_cfg;
+
+ of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ if (!dma_cfg->pbl)
+ dma_cfg->pbl = DEFAULT_DMA_PBL;
+ of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8");
+
+ dma_cfg->aal = of_property_read_bool(np, "snps,aal");
+ dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
+ dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
+
plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
if (plat->force_thresh_dma_mode) {
plat->force_sf_dma_mode = 0;
@@ -444,9 +449,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
ret = stmmac_suspend(dev);
- if (priv->plat->suspend)
- priv->plat->suspend(pdev, priv->plat->bsp_priv);
- else if (priv->plat->exit)
+ if (priv->plat->exit)
priv->plat->exit(pdev, priv->plat->bsp_priv);
return ret;
@@ -465,9 +468,7 @@ static int stmmac_pltfr_resume(struct device *dev)
struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
- if (priv->plat->resume)
- priv->plat->resume(pdev, priv->plat->bsp_priv);
- else if (priv->plat->init)
+ if (priv->plat->init)
priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(dev);
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index 062bce9acde6..e9e5ef241c6f 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -3863,9 +3863,6 @@ static int cas_change_mtu(struct net_device *dev, int new_mtu)
{
struct cas *cp = netdev_priv(dev);
- if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU)
- return -EINVAL;
-
dev->mtu = new_mtu;
if (!netif_running(dev) || !netif_device_present(dev))
return 0;
@@ -5115,6 +5112,10 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
+ /* MTU range: 60 - varies or 9000 */
+ dev->min_mtu = CAS_MIN_MTU;
+ dev->max_mtu = CAS_MAX_MTU;
+
if (register_netdev(dev)) {
dev_err(&pdev->dev, "Cannot register net device, aborting\n");
goto err_out_free_consistent;
diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c
index 0ac449acaf5b..335b87660638 100644
--- a/drivers/net/ethernet/sun/ldmvsw.c
+++ b/drivers/net/ethernet/sun/ldmvsw.c
@@ -139,7 +139,6 @@ static const struct net_device_ops vsw_ops = {
.ndo_set_mac_address = sunvnet_set_mac_addr_common,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = sunvnet_tx_timeout_common,
- .ndo_change_mtu = sunvnet_change_mtu_common,
.ndo_start_xmit = vsw_start_xmit,
.ndo_select_queue = vsw_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -239,6 +238,10 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
NETIF_F_HW_CSUM | NETIF_F_SG;
dev->features = dev->hw_features;
+ /* MTU range: 68 - 65535 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = VNET_MAX_MTU;
+
SET_NETDEV_DEV(dev, &vdev->dev);
return dev;
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index a2371aa14a49..f90d1af6d390 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -6754,9 +6754,6 @@ static int niu_change_mtu(struct net_device *dev, int new_mtu)
struct niu *np = netdev_priv(dev);
int err, orig_jumbo, new_jumbo;
- if (new_mtu < 68 || new_mtu > NIU_MAX_MTU)
- return -EINVAL;
-
orig_jumbo = (dev->mtu > ETH_DATA_LEN);
new_jumbo = (new_mtu > ETH_DATA_LEN);
@@ -9823,6 +9820,10 @@ static int niu_pci_init_one(struct pci_dev *pdev,
dev->irq = pdev->irq;
+ /* MTU range: 68 - 9216 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = NIU_MAX_MTU;
+
niu_assign_netdev_ops(dev);
err = niu_get_invariants(np);
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 02f452730d52..c4caf486cbef 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -1065,7 +1065,6 @@ static const struct net_device_ops bigmac_ops = {
.ndo_get_stats = bigmac_get_stats,
.ndo_set_rx_mode = bigmac_set_multicast,
.ndo_tx_timeout = bigmac_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index d6ad0fbd054e..66ecf0fcc330 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2476,9 +2476,9 @@ static void gem_set_multicast(struct net_device *dev)
}
/* Jumbo-grams don't seem to work :-( */
-#define GEM_MIN_MTU 68
+#define GEM_MIN_MTU ETH_MIN_MTU
#if 1
-#define GEM_MAX_MTU 1500
+#define GEM_MAX_MTU ETH_DATA_LEN
#else
#define GEM_MAX_MTU 9000
#endif
@@ -2487,9 +2487,6 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
{
struct gem *gp = netdev_priv(dev);
- if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
- return -EINVAL;
-
dev->mtu = new_mtu;
/* We'll just catch it later when the device is up'd or resumed */
@@ -2977,6 +2974,10 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
+ /* MTU range: 68 - 1500 (Jumbo mode is broken) */
+ dev->min_mtu = GEM_MIN_MTU;
+ dev->max_mtu = GEM_MAX_MTU;
+
/* Register with kernel */
if (register_netdev(dev)) {
pr_err("Cannot register net device, aborting\n");
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index cf4dcff051d5..ca96408058b0 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2669,7 +2669,6 @@ static const struct net_device_ops hme_netdev_ops = {
.ndo_tx_timeout = happy_meal_tx_timeout,
.ndo_get_stats = happy_meal_get_stats,
.ndo_set_rx_mode = happy_meal_set_multicast,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index 9582948145c1..a6bcdcdd947e 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -824,7 +824,6 @@ static const struct net_device_ops qec_ops = {
.ndo_start_xmit = qe_start_xmit,
.ndo_set_rx_mode = qe_set_multicast,
.ndo_tx_timeout = qe_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index a2f9b47de187..5356a7074796 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -159,7 +159,6 @@ static const struct net_device_ops vnet_ops = {
.ndo_set_mac_address = sunvnet_set_mac_addr_common,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = sunvnet_tx_timeout_common,
- .ndo_change_mtu = sunvnet_change_mtu_common,
.ndo_start_xmit = vnet_start_xmit,
.ndo_select_queue = vnet_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -202,6 +201,10 @@ static struct vnet *vnet_new(const u64 *local_mac,
NETIF_F_HW_CSUM | NETIF_F_SG;
dev->features = dev->hw_features;
+ /* MTU range: 68 - 65535 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = VNET_MAX_MTU;
+
SET_NETDEV_DEV(dev, &vdev->dev);
err = register_netdev(dev);
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index 904a5a12a85d..8878b75d68b4 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -704,9 +704,8 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)
return 0;
}
-/* Got back a STOPPED LDC message on port. If the queue is stopped,
- * wake it up so that we'll send out another START message at the
- * next TX.
+/* If the queue is stopped, wake it up so that we'll
+ * send out another START message at the next TX.
*/
static void maybe_tx_wakeup(struct vnet_port *port)
{
@@ -734,6 +733,7 @@ EXPORT_SYMBOL_GPL(sunvnet_port_is_up_common);
static int vnet_event_napi(struct vnet_port *port, int budget)
{
+ struct net_device *dev = VNET_PORT_TO_NET_DEVICE(port);
struct vio_driver_state *vio = &port->vio;
int tx_wakeup, err;
int npkts = 0;
@@ -747,6 +747,16 @@ ldc_ctrl:
if (event == LDC_EVENT_RESET) {
vnet_port_reset(port);
vio_port_up(vio);
+
+ /* If the device is running but its tx queue was
+ * stopped (due to flow control), restart it.
+ * This is necessary since vnet_port_reset()
+ * clears the tx drings and thus we may never get
+ * back a VIO_TYPE_DATA ACK packet - which is
+ * the normal mechanism to restart the tx queue.
+ */
+ if (netif_running(dev))
+ maybe_tx_wakeup(port);
}
port->rx_event = 0;
return 0;
@@ -1583,16 +1593,6 @@ void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp)
}
EXPORT_SYMBOL_GPL(sunvnet_set_rx_mode_common);
-int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < 68 || new_mtu > 65535)
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-EXPORT_SYMBOL_GPL(sunvnet_change_mtu_common);
-
int sunvnet_set_mac_addr_common(struct net_device *dev, void *p)
{
return -EINVAL;
diff --git a/drivers/net/ethernet/sun/sunvnet_common.h b/drivers/net/ethernet/sun/sunvnet_common.h
index bd36528af972..ce5c824128a3 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.h
+++ b/drivers/net/ethernet/sun/sunvnet_common.h
@@ -15,6 +15,8 @@
#define VNET_MINTSO 2048 /* VIO protocol's minimum TSO len */
#define VNET_MAXTSO 65535 /* VIO protocol's maximum TSO len */
+#define VNET_MAX_MTU 65535
+
/* VNET packets are sent in buffers with the first 6 bytes skipped
* so that after the ethernet header the IPv4/IPv6 headers are aligned
* properly.
@@ -125,7 +127,6 @@ int sunvnet_close_common(struct net_device *dev);
void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp);
int sunvnet_set_mac_addr_common(struct net_device *dev, void *p);
void sunvnet_tx_timeout_common(struct net_device *dev);
-int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu);
int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
struct vnet_port *(*vnet_tx_port)
(struct sk_buff *, struct net_device *));
diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
index 97d64bfed465..09f5a67da35e 100644
--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
@@ -2211,7 +2211,7 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev)
tx_error:
dwceqos_tx_rollback(lp, &trans);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return 0;
}
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 7108c68f16d3..baa3e4a5731c 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -761,16 +761,6 @@ static int bdx_change_mtu(struct net_device *ndev, int new_mtu)
{
ENTER;
- if (new_mtu == ndev->mtu)
- RET(0);
-
- /* enforce minimum frame size */
- if (new_mtu < ETH_ZLEN) {
- netdev_err(ndev, "mtu %d is less then minimal %d\n",
- new_mtu, ETH_ZLEN);
- RET(-EINVAL);
- }
-
ndev->mtu = new_mtu;
if (netif_running(ndev)) {
bdx_close(ndev);
@@ -2057,6 +2047,10 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef BDX_LLTX
ndev->features |= NETIF_F_LLTX;
#endif
+ /* MTU range: 60 - 16384 */
+ ndev->min_mtu = ETH_ZLEN;
+ ndev->max_mtu = BDX_MAX_MTU;
+
spin_lock_init(&priv->tx_lock);
/*bdx_hw_reset(priv); */
diff --git a/drivers/net/ethernet/tehuti/tehuti.h b/drivers/net/ethernet/tehuti/tehuti.h
index 709ebd6e28b4..8e7b4c9abf21 100644
--- a/drivers/net/ethernet/tehuti/tehuti.h
+++ b/drivers/net/ethernet/tehuti/tehuti.h
@@ -74,6 +74,9 @@
* ifcontig eth1 txqueuelen 3000 - to change it at runtime */
#define BDX_NDEV_TXQ_LEN 3000
+/* Max MTU for Jumbo Frame mode, per tehutinetworks.net Features FAQ is 16k */
+#define BDX_MAX_MTU (16 * 1024)
+
#define FIFO_SIZE 4096
#define FIFO_EXTRA_SPACE 1024
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 9904d740d528..296c8efd0038 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -74,13 +74,14 @@ config TI_CPSW
will be called cpsw.
config TI_CPTS
- bool "TI Common Platform Time Sync (CPTS) Support"
- depends on TI_CPSW
- select PTP_1588_CLOCK
+ tristate "TI Common Platform Time Sync (CPTS) Support"
+ depends on TI_CPSW || TI_KEYSTONE_NETCP
+ imply PTP_1588_CLOCK
---help---
This driver supports the Common Platform Time Sync unit of
- the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
- and Layer 2 packets, and the driver offers a PTP Hardware Clock.
+ the CPSW Ethernet Switch and Keystone 2 1g/10g Switch Subsystem.
+ The unit can time stamp PTP UDP/IPv4 and Layer 2 packets, and the
+ driver offers a PTP Hardware Clock.
config TI_KEYSTONE_NETCP
tristate "TI Keystone NETCP Core Support"
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index d420d9413e4a..1e7c10bf8713 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -12,8 +12,9 @@ obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o
+obj-$(CONFIG_TI_CPTS) += cpts.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw.o cpts.o
+ti_cpsw-y := cpsw.o
obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o
keystone_netcp-y := netcp_core.o
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 28097be2ff28..77c88fcf2b86 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1068,7 +1068,6 @@ static const struct net_device_ops cpmac_netdev_ops = {
.ndo_tx_timeout = cpmac_tx_timeout,
.ndo_set_rx_mode = cpmac_set_multicast_list,
.ndo_do_ioctl = cpmac_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b9087b828eff..b203143647e6 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -365,6 +365,11 @@ static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
__raw_writel(val, slave->regs + offset);
}
+struct cpsw_vector {
+ struct cpdma_chan *ch;
+ int budget;
+};
+
struct cpsw_common {
struct device *dev;
struct cpsw_platform_data data;
@@ -380,8 +385,8 @@ struct cpsw_common {
int rx_packet_max;
struct cpsw_slave *slaves;
struct cpdma_ctlr *dma;
- struct cpdma_chan *txch[CPSW_MAX_QUEUES];
- struct cpdma_chan *rxch[CPSW_MAX_QUEUES];
+ struct cpsw_vector txv[CPSW_MAX_QUEUES];
+ struct cpsw_vector rxv[CPSW_MAX_QUEUES];
struct cpsw_ale *ale;
bool quirk_irq;
bool rx_irq_disabled;
@@ -389,6 +394,7 @@ struct cpsw_common {
u32 irqs_table[IRQ_NUM];
struct cpts *cpts;
int rx_ch_num, tx_ch_num;
+ int speed;
};
struct cpsw_priv {
@@ -741,13 +747,100 @@ requeue:
return;
}
- ch = cpsw->rxch[skb_get_queue_mapping(new_skb)];
+ ch = cpsw->rxv[skb_get_queue_mapping(new_skb)].ch;
ret = cpdma_chan_submit(ch, new_skb, new_skb->data,
skb_tailroom(new_skb), 0);
if (WARN_ON(ret < 0))
dev_kfree_skb_any(new_skb);
}
+static void cpsw_split_res(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ u32 consumed_rate = 0, bigest_rate = 0;
+ struct cpsw_common *cpsw = priv->cpsw;
+ struct cpsw_vector *txv = cpsw->txv;
+ int i, ch_weight, rlim_ch_num = 0;
+ int budget, bigest_rate_ch = 0;
+ u32 ch_rate, max_rate;
+ int ch_budget = 0;
+
+ for (i = 0; i < cpsw->tx_ch_num; i++) {
+ ch_rate = cpdma_chan_get_rate(txv[i].ch);
+ if (!ch_rate)
+ continue;
+
+ rlim_ch_num++;
+ consumed_rate += ch_rate;
+ }
+
+ if (cpsw->tx_ch_num == rlim_ch_num) {
+ max_rate = consumed_rate;
+ } else if (!rlim_ch_num) {
+ ch_budget = CPSW_POLL_WEIGHT / cpsw->tx_ch_num;
+ bigest_rate = 0;
+ max_rate = consumed_rate;
+ } else {
+ max_rate = cpsw->speed * 1000;
+
+ /* if max_rate is less then expected due to reduced link speed,
+ * split proportionally according next potential max speed
+ */
+ if (max_rate < consumed_rate)
+ max_rate *= 10;
+
+ if (max_rate < consumed_rate)
+ max_rate *= 10;
+
+ ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate;
+ ch_budget = (CPSW_POLL_WEIGHT - ch_budget) /
+ (cpsw->tx_ch_num - rlim_ch_num);
+ bigest_rate = (max_rate - consumed_rate) /
+ (cpsw->tx_ch_num - rlim_ch_num);
+ }
+
+ /* split tx weight/budget */
+ budget = CPSW_POLL_WEIGHT;
+ for (i = 0; i < cpsw->tx_ch_num; i++) {
+ ch_rate = cpdma_chan_get_rate(txv[i].ch);
+ if (ch_rate) {
+ txv[i].budget = (ch_rate * CPSW_POLL_WEIGHT) / max_rate;
+ if (!txv[i].budget)
+ txv[i].budget++;
+ if (ch_rate > bigest_rate) {
+ bigest_rate_ch = i;
+ bigest_rate = ch_rate;
+ }
+
+ ch_weight = (ch_rate * 100) / max_rate;
+ if (!ch_weight)
+ ch_weight++;
+ cpdma_chan_set_weight(cpsw->txv[i].ch, ch_weight);
+ } else {
+ txv[i].budget = ch_budget;
+ if (!bigest_rate_ch)
+ bigest_rate_ch = i;
+ cpdma_chan_set_weight(cpsw->txv[i].ch, 0);
+ }
+
+ budget -= txv[i].budget;
+ }
+
+ if (budget)
+ txv[bigest_rate_ch].budget += budget;
+
+ /* split rx budget */
+ budget = CPSW_POLL_WEIGHT;
+ ch_budget = budget / cpsw->rx_ch_num;
+ for (i = 0; i < cpsw->rx_ch_num; i++) {
+ cpsw->rxv[i].budget = ch_budget;
+ budget -= ch_budget;
+ }
+
+ if (budget)
+ cpsw->rxv[0].budget += budget;
+}
+
static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
{
struct cpsw_common *cpsw = dev_id;
@@ -783,24 +876,25 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
static int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
{
u32 ch_map;
- int num_tx, ch;
+ int num_tx, cur_budget, ch;
struct cpsw_common *cpsw = napi_to_cpsw(napi_tx);
+ struct cpsw_vector *txv;
/* process every unprocessed channel */
ch_map = cpdma_ctrl_txchs_state(cpsw->dma);
- for (ch = 0, num_tx = 0; num_tx < budget; ch_map >>= 1, ch++) {
- if (!ch_map) {
- ch_map = cpdma_ctrl_txchs_state(cpsw->dma);
- if (!ch_map)
- break;
-
- ch = 0;
- }
-
+ for (ch = 0, num_tx = 0; ch_map; ch_map >>= 1, ch++) {
if (!(ch_map & 0x01))
continue;
- num_tx += cpdma_chan_process(cpsw->txch[ch], budget - num_tx);
+ txv = &cpsw->txv[ch];
+ if (unlikely(txv->budget > budget - num_tx))
+ cur_budget = budget - num_tx;
+ else
+ cur_budget = txv->budget;
+
+ num_tx += cpdma_chan_process(txv->ch, cur_budget);
+ if (num_tx >= budget)
+ break;
}
if (num_tx < budget) {
@@ -818,24 +912,25 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
static int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
{
u32 ch_map;
- int num_rx, ch;
+ int num_rx, cur_budget, ch;
struct cpsw_common *cpsw = napi_to_cpsw(napi_rx);
+ struct cpsw_vector *rxv;
/* process every unprocessed channel */
ch_map = cpdma_ctrl_rxchs_state(cpsw->dma);
- for (ch = 0, num_rx = 0; num_rx < budget; ch_map >>= 1, ch++) {
- if (!ch_map) {
- ch_map = cpdma_ctrl_rxchs_state(cpsw->dma);
- if (!ch_map)
- break;
-
- ch = 0;
- }
-
+ for (ch = 0, num_rx = 0; ch_map; ch_map >>= 1, ch++) {
if (!(ch_map & 0x01))
continue;
- num_rx += cpdma_chan_process(cpsw->rxch[ch], budget - num_rx);
+ rxv = &cpsw->rxv[ch];
+ if (unlikely(rxv->budget > budget - num_rx))
+ cur_budget = budget - num_rx;
+ else
+ cur_budget = rxv->budget;
+
+ num_rx += cpdma_chan_process(rxv->ch, cur_budget);
+ if (num_rx >= budget)
+ break;
}
if (num_rx < budget) {
@@ -926,14 +1021,56 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
slave->mac_control = mac_control;
}
+static int cpsw_get_common_speed(struct cpsw_common *cpsw)
+{
+ int i, speed;
+
+ for (i = 0, speed = 0; i < cpsw->data.slaves; i++)
+ if (cpsw->slaves[i].phy && cpsw->slaves[i].phy->link)
+ speed += cpsw->slaves[i].phy->speed;
+
+ return speed;
+}
+
+static int cpsw_need_resplit(struct cpsw_common *cpsw)
+{
+ int i, rlim_ch_num;
+ int speed, ch_rate;
+
+ /* re-split resources only in case speed was changed */
+ speed = cpsw_get_common_speed(cpsw);
+ if (speed == cpsw->speed || !speed)
+ return 0;
+
+ cpsw->speed = speed;
+
+ for (i = 0, rlim_ch_num = 0; i < cpsw->tx_ch_num; i++) {
+ ch_rate = cpdma_chan_get_rate(cpsw->txv[i].ch);
+ if (!ch_rate)
+ break;
+
+ rlim_ch_num++;
+ }
+
+ /* cases not dependent on speed */
+ if (!rlim_ch_num || rlim_ch_num == cpsw->tx_ch_num)
+ return 0;
+
+ return 1;
+}
+
static void cpsw_adjust_link(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
bool link = false;
for_each_slave(priv, _cpsw_adjust_link, priv, &link);
if (link) {
+ if (cpsw_need_resplit(cpsw))
+ cpsw_split_res(ndev);
+
netif_carrier_on(ndev);
if (netif_running(ndev))
netif_tx_wake_all_queues(ndev);
@@ -1075,7 +1212,7 @@ static void cpsw_get_ethtool_stats(struct net_device *ndev,
cpsw_gstrings_stats[l].stat_offset);
for (ch = 0; ch < cpsw->rx_ch_num; ch++) {
- cpdma_chan_get_stats(cpsw->rxch[ch], &ch_stats);
+ cpdma_chan_get_stats(cpsw->rxv[ch].ch, &ch_stats);
for (i = 0; i < CPSW_STATS_CH_LEN; i++, l++) {
p = (u8 *)&ch_stats +
cpsw_gstrings_ch_stats[i].stat_offset;
@@ -1084,7 +1221,7 @@ static void cpsw_get_ethtool_stats(struct net_device *ndev,
}
for (ch = 0; ch < cpsw->tx_ch_num; ch++) {
- cpdma_chan_get_stats(cpsw->txch[ch], &ch_stats);
+ cpdma_chan_get_stats(cpsw->txv[ch].ch, &ch_stats);
for (i = 0; i < CPSW_STATS_CH_LEN; i++, l++) {
p = (u8 *)&ch_stats +
cpsw_gstrings_ch_stats[i].stat_offset;
@@ -1281,7 +1418,7 @@ static int cpsw_fill_rx_channels(struct cpsw_priv *priv)
int ch, i, ret;
for (ch = 0; ch < cpsw->rx_ch_num; ch++) {
- ch_buf_num = cpdma_chan_get_rx_buf_num(cpsw->rxch[ch]);
+ ch_buf_num = cpdma_chan_get_rx_buf_num(cpsw->rxv[ch].ch);
for (i = 0; i < ch_buf_num; i++) {
skb = __netdev_alloc_skb_ip_align(priv->ndev,
cpsw->rx_packet_max,
@@ -1292,8 +1429,9 @@ static int cpsw_fill_rx_channels(struct cpsw_priv *priv)
}
skb_set_queue_mapping(skb, ch);
- ret = cpdma_chan_submit(cpsw->rxch[ch], skb, skb->data,
- skb_tailroom(skb), 0);
+ ret = cpdma_chan_submit(cpsw->rxv[ch].ch, skb,
+ skb->data, skb_tailroom(skb),
+ 0);
if (ret < 0) {
cpsw_err(priv, ifup,
"cannot submit skb to channel %d rx, error %d\n",
@@ -1376,10 +1514,6 @@ static int cpsw_ndo_open(struct net_device *ndev)
ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0);
if (!cpsw_common_res_usage_state(cpsw)) {
- /* setup tx dma to fixed prio and zero offset */
- cpdma_control_set(cpsw->dma, CPDMA_TX_PRIO_FIXED, 1);
- cpdma_control_set(cpsw->dma, CPDMA_RX_BUFFER_OFFSET, 0);
-
/* disable priority elevation */
__raw_writel(0, &cpsw->regs->ptype);
@@ -1406,9 +1540,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
if (ret < 0)
goto err_cleanup;
- if (cpts_register(cpsw->dev, cpsw->cpts,
- cpsw->data.cpts_clock_mult,
- cpsw->data.cpts_clock_shift))
+ if (cpts_register(cpsw->cpts))
dev_err(priv->dev, "error registering cpts device\n");
}
@@ -1427,8 +1559,6 @@ static int cpsw_ndo_open(struct net_device *ndev)
if (cpsw->data.dual_emac)
cpsw->slaves[priv->emac_port].open_stat = true;
- netif_tx_start_all_queues(ndev);
-
return 0;
err_cleanup:
@@ -1457,6 +1587,10 @@ static int cpsw_ndo_stop(struct net_device *ndev)
cpsw_ale_stop(cpsw->ale);
}
for_each_slave(priv, cpsw_slave_stop, cpsw);
+
+ if (cpsw_need_resplit(cpsw))
+ cpsw_split_res(ndev);
+
pm_runtime_put_sync(cpsw->dev);
if (cpsw->data.dual_emac)
cpsw->slaves[priv->emac_port].open_stat = false;
@@ -1481,7 +1615,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
}
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
- cpsw->cpts->tx_enable)
+ cpts_is_tx_enabled(cpsw->cpts))
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
skb_tx_timestamp(skb);
@@ -1490,7 +1624,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
if (q_idx >= cpsw->tx_ch_num)
q_idx = q_idx % cpsw->tx_ch_num;
- txch = cpsw->txch[q_idx];
+ txch = cpsw->txv[q_idx].ch;
ret = cpsw_tx_packet_submit(priv, skb, txch);
if (unlikely(ret != 0)) {
cpsw_err(priv, tx_err, "desc submit failed\n");
@@ -1513,14 +1647,15 @@ fail:
return NETDEV_TX_BUSY;
}
-#ifdef CONFIG_TI_CPTS
+#if IS_ENABLED(CONFIG_TI_CPTS)
static void cpsw_hwtstamp_v1(struct cpsw_common *cpsw)
{
struct cpsw_slave *slave = &cpsw->slaves[cpsw->data.active_slave];
u32 ts_en, seq_id;
- if (!cpsw->cpts->tx_enable && !cpsw->cpts->rx_enable) {
+ if (!cpts_is_tx_enabled(cpsw->cpts) &&
+ !cpts_is_rx_enabled(cpsw->cpts)) {
slave_write(slave, 0, CPSW1_TS_CTL);
return;
}
@@ -1528,10 +1663,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_common *cpsw)
seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
- if (cpsw->cpts->tx_enable)
+ if (cpts_is_tx_enabled(cpsw->cpts))
ts_en |= CPSW_V1_TS_TX_EN;
- if (cpsw->cpts->rx_enable)
+ if (cpts_is_rx_enabled(cpsw->cpts))
ts_en |= CPSW_V1_TS_RX_EN;
slave_write(slave, ts_en, CPSW1_TS_CTL);
@@ -1544,30 +1679,27 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
struct cpsw_common *cpsw = priv->cpsw;
u32 ctrl, mtype;
- if (cpsw->data.dual_emac)
- slave = &cpsw->slaves[priv->emac_port];
- else
- slave = &cpsw->slaves[cpsw->data.active_slave];
+ slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)];
ctrl = slave_read(slave, CPSW2_CONTROL);
switch (cpsw->version) {
case CPSW_VERSION_2:
ctrl &= ~CTRL_V2_ALL_TS_MASK;
- if (cpsw->cpts->tx_enable)
+ if (cpts_is_tx_enabled(cpsw->cpts))
ctrl |= CTRL_V2_TX_TS_BITS;
- if (cpsw->cpts->rx_enable)
+ if (cpts_is_rx_enabled(cpsw->cpts))
ctrl |= CTRL_V2_RX_TS_BITS;
break;
case CPSW_VERSION_3:
default:
ctrl &= ~CTRL_V3_ALL_TS_MASK;
- if (cpsw->cpts->tx_enable)
+ if (cpts_is_tx_enabled(cpsw->cpts))
ctrl |= CTRL_V3_TX_TS_BITS;
- if (cpsw->cpts->rx_enable)
+ if (cpts_is_rx_enabled(cpsw->cpts))
ctrl |= CTRL_V3_RX_TS_BITS;
break;
}
@@ -1603,7 +1735,7 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- cpts->rx_enable = 0;
+ cpts_rx_enable(cpts, 0);
break;
case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
@@ -1619,14 +1751,14 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
- cpts->rx_enable = 1;
+ cpts_rx_enable(cpts, 1);
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
break;
default:
return -ERANGE;
}
- cpts->tx_enable = cfg.tx_type == HWTSTAMP_TX_ON;
+ cpts_tx_enable(cpts, cfg.tx_type == HWTSTAMP_TX_ON);
switch (cpsw->version) {
case CPSW_VERSION_1:
@@ -1655,13 +1787,23 @@ static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
return -EOPNOTSUPP;
cfg.flags = 0;
- cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
- cfg.rx_filter = (cpts->rx_enable ?
+ cfg.tx_type = cpts_is_tx_enabled(cpts) ?
+ HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+ cfg.rx_filter = (cpts_is_rx_enabled(cpts) ?
HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE);
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
+#else
+static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+ return -EOPNOTSUPP;
+}
+static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
+{
+ return -EOPNOTSUPP;
+}
#endif /*CONFIG_TI_CPTS*/
static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
@@ -1674,12 +1816,10 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
return -EINVAL;
switch (cmd) {
-#ifdef CONFIG_TI_CPTS
case SIOCSHWTSTAMP:
return cpsw_hwtstamp_set(dev, req);
case SIOCGHWTSTAMP:
return cpsw_hwtstamp_get(dev, req);
-#endif
}
if (!cpsw->slaves[slave_no].phy)
@@ -1697,8 +1837,8 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
ndev->stats.tx_errors++;
cpsw_intr_disable(cpsw);
for (ch = 0; ch < cpsw->tx_ch_num; ch++) {
- cpdma_chan_stop(cpsw->txch[ch]);
- cpdma_chan_start(cpsw->txch[ch]);
+ cpdma_chan_stop(cpsw->txv[ch].ch);
+ cpdma_chan_start(cpsw->txv[ch].ch);
}
cpsw_intr_enable(cpsw);
@@ -1876,6 +2016,57 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
return ret;
}
+static int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ struct cpsw_slave *slave;
+ u32 min_rate;
+ u32 ch_rate;
+ int i, ret;
+
+ ch_rate = netdev_get_tx_queue(ndev, queue)->tx_maxrate;
+ if (ch_rate == rate)
+ return 0;
+
+ ch_rate = rate * 1000;
+ min_rate = cpdma_chan_get_min_rate(cpsw->dma);
+ if ((ch_rate < min_rate && ch_rate)) {
+ dev_err(priv->dev, "The channel rate cannot be less than %dMbps",
+ min_rate);
+ return -EINVAL;
+ }
+
+ if (rate > cpsw->speed) {
+ dev_err(priv->dev, "The channel rate cannot be more than 2Gbps");
+ return -EINVAL;
+ }
+
+ ret = pm_runtime_get_sync(cpsw->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(cpsw->dev);
+ return ret;
+ }
+
+ ret = cpdma_chan_set_rate(cpsw->txv[queue].ch, ch_rate);
+ pm_runtime_put(cpsw->dev);
+
+ if (ret)
+ return ret;
+
+ /* update rates for slaves tx queues */
+ for (i = 0; i < cpsw->data.slaves; i++) {
+ slave = &cpsw->slaves[i];
+ if (!slave->ndev)
+ continue;
+
+ netdev_get_tx_queue(slave->ndev, queue)->tx_maxrate = rate;
+ }
+
+ cpsw_split_res(ndev);
+ return ret;
+}
+
static const struct net_device_ops cpsw_netdev_ops = {
.ndo_open = cpsw_ndo_open,
.ndo_stop = cpsw_ndo_stop,
@@ -1883,9 +2074,9 @@ static const struct net_device_ops cpsw_netdev_ops = {
.ndo_set_mac_address = cpsw_ndo_set_mac_address,
.ndo_do_ioctl = cpsw_ndo_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = cpsw_ndo_tx_timeout,
.ndo_set_rx_mode = cpsw_ndo_set_rx_mode,
+ .ndo_set_tx_maxrate = cpsw_ndo_set_tx_maxrate,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
@@ -1935,10 +2126,10 @@ static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
priv->msg_enable = value;
}
+#if IS_ENABLED(CONFIG_TI_CPTS)
static int cpsw_get_ts_info(struct net_device *ndev,
struct ethtool_ts_info *info)
{
-#ifdef CONFIG_TI_CPTS
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
info->so_timestamping =
@@ -1955,7 +2146,12 @@ static int cpsw_get_ts_info(struct net_device *ndev,
info->rx_filters =
(1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+ return 0;
+}
#else
+static int cpsw_get_ts_info(struct net_device *ndev,
+ struct ethtool_ts_info *info)
+{
info->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
@@ -1963,31 +2159,34 @@ static int cpsw_get_ts_info(struct net_device *ndev,
info->phc_index = -1;
info->tx_types = 0;
info->rx_filters = 0;
-#endif
return 0;
}
+#endif
-static int cpsw_get_settings(struct net_device *ndev,
- struct ethtool_cmd *ecmd)
+static int cpsw_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *ecmd)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
int slave_no = cpsw_slave_index(cpsw, priv);
if (cpsw->slaves[slave_no].phy)
- return phy_ethtool_gset(cpsw->slaves[slave_no].phy, ecmd);
+ return phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy,
+ ecmd);
else
return -EOPNOTSUPP;
}
-static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+static int cpsw_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *ecmd)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
int slave_no = cpsw_slave_index(cpsw, priv);
if (cpsw->slaves[slave_no].phy)
- return phy_ethtool_sset(cpsw->slaves[slave_no].phy, ecmd);
+ return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy,
+ ecmd);
else
return -EOPNOTSUPP;
}
@@ -2102,28 +2301,31 @@ static int cpsw_update_channels_res(struct cpsw_priv *priv, int ch_num, int rx)
int (*poll)(struct napi_struct *, int);
struct cpsw_common *cpsw = priv->cpsw;
void (*handler)(void *, int, int);
- struct cpdma_chan **chan;
+ struct netdev_queue *queue;
+ struct cpsw_vector *vec;
int ret, *ch;
if (rx) {
ch = &cpsw->rx_ch_num;
- chan = cpsw->rxch;
+ vec = cpsw->rxv;
handler = cpsw_rx_handler;
poll = cpsw_rx_poll;
} else {
ch = &cpsw->tx_ch_num;
- chan = cpsw->txch;
+ vec = cpsw->txv;
handler = cpsw_tx_handler;
poll = cpsw_tx_poll;
}
while (*ch < ch_num) {
- chan[*ch] = cpdma_chan_create(cpsw->dma, *ch, handler, rx);
+ vec[*ch].ch = cpdma_chan_create(cpsw->dma, *ch, handler, rx);
+ queue = netdev_get_tx_queue(priv->ndev, *ch);
+ queue->tx_maxrate = 0;
- if (IS_ERR(chan[*ch]))
- return PTR_ERR(chan[*ch]);
+ if (IS_ERR(vec[*ch].ch))
+ return PTR_ERR(vec[*ch].ch);
- if (!chan[*ch])
+ if (!vec[*ch].ch)
return -EINVAL;
cpsw_info(priv, ifup, "created new %d %s channel\n", *ch,
@@ -2134,7 +2336,7 @@ static int cpsw_update_channels_res(struct cpsw_priv *priv, int ch_num, int rx)
while (*ch > ch_num) {
(*ch)--;
- ret = cpdma_chan_destroy(chan[*ch]);
+ ret = cpdma_chan_destroy(vec[*ch].ch);
if (ret)
return ret;
@@ -2221,6 +2423,8 @@ static int cpsw_set_channels(struct net_device *ndev,
if (ret)
goto err;
+ cpsw_split_res(ndev);
+
/* After this receive is started */
cpdma_ctlr_start(cpsw->dma);
cpsw_intr_enable(cpsw);
@@ -2239,14 +2443,48 @@ err:
return ret;
}
+static int cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(cpsw, priv);
+
+ if (cpsw->slaves[slave_no].phy)
+ return phy_ethtool_get_eee(cpsw->slaves[slave_no].phy, edata);
+ else
+ return -EOPNOTSUPP;
+}
+
+static int cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(cpsw, priv);
+
+ if (cpsw->slaves[slave_no].phy)
+ return phy_ethtool_set_eee(cpsw->slaves[slave_no].phy, edata);
+ else
+ return -EOPNOTSUPP;
+}
+
+static int cpsw_nway_reset(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(cpsw, priv);
+
+ if (cpsw->slaves[slave_no].phy)
+ return genphy_restart_aneg(cpsw->slaves[slave_no].phy);
+ else
+ return -EOPNOTSUPP;
+}
+
static const struct ethtool_ops cpsw_ethtool_ops = {
.get_drvinfo = cpsw_get_drvinfo,
.get_msglevel = cpsw_get_msglevel,
.set_msglevel = cpsw_set_msglevel,
.get_link = ethtool_op_get_link,
.get_ts_info = cpsw_get_ts_info,
- .get_settings = cpsw_get_settings,
- .set_settings = cpsw_set_settings,
.get_coalesce = cpsw_get_coalesce,
.set_coalesce = cpsw_set_coalesce,
.get_sset_count = cpsw_get_sset_count,
@@ -2262,6 +2500,11 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
.complete = cpsw_ethtool_op_complete,
.get_channels = cpsw_get_channels,
.set_channels = cpsw_set_channels,
+ .get_link_ksettings = cpsw_get_link_ksettings,
+ .set_link_ksettings = cpsw_set_link_ksettings,
+ .get_eee = cpsw_get_eee,
+ .set_eee = cpsw_set_eee,
+ .nway_reset = cpsw_nway_reset,
};
static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw,
@@ -2300,18 +2543,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->active_slave = prop;
- if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
- dev_err(&pdev->dev, "Missing cpts_clock_mult property in the DT.\n");
- return -EINVAL;
- }
- data->cpts_clock_mult = prop;
-
- if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
- dev_err(&pdev->dev, "Missing cpts_clock_shift property in the DT.\n");
- return -EINVAL;
- }
- data->cpts_clock_shift = prop;
-
data->slave_data = devm_kzalloc(&pdev->dev, data->slaves
* sizeof(struct cpsw_slave_data),
GFP_KERNEL);
@@ -2570,6 +2801,7 @@ static int cpsw_probe(struct platform_device *pdev)
struct cpdma_params dma_params;
struct cpsw_ale_params ale_params;
void __iomem *ss_regs;
+ void __iomem *cpts_regs;
struct resource *res, *ss_res;
const struct of_device_id *of_id;
struct gpio_descs *mode;
@@ -2597,12 +2829,6 @@ static int cpsw_probe(struct platform_device *pdev)
priv->dev = &ndev->dev;
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
cpsw->rx_packet_max = max(rx_packet_max, 128);
- cpsw->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
- if (!cpsw->cpts) {
- dev_err(&pdev->dev, "error allocating cpts\n");
- ret = -ENOMEM;
- goto clean_ndev_ret;
- }
mode = devm_gpiod_get_array_optional(&pdev->dev, "mode", GPIOD_OUT_LOW);
if (IS_ERR(mode)) {
@@ -2690,7 +2916,7 @@ static int cpsw_probe(struct platform_device *pdev)
switch (cpsw->version) {
case CPSW_VERSION_1:
cpsw->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
- cpsw->cpts->reg = ss_regs + CPSW1_CPTS_OFFSET;
+ cpts_regs = ss_regs + CPSW1_CPTS_OFFSET;
cpsw->hw_stats = ss_regs + CPSW1_HW_STATS;
dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET;
dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET;
@@ -2704,7 +2930,7 @@ static int cpsw_probe(struct platform_device *pdev)
case CPSW_VERSION_3:
case CPSW_VERSION_4:
cpsw->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
- cpsw->cpts->reg = ss_regs + CPSW2_CPTS_OFFSET;
+ cpts_regs = ss_regs + CPSW2_CPTS_OFFSET;
cpsw->hw_stats = ss_regs + CPSW2_HW_STATS;
dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET;
dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET;
@@ -2742,6 +2968,7 @@ static int cpsw_probe(struct platform_device *pdev)
dma_params.desc_align = 16;
dma_params.has_ext_regs = true;
dma_params.desc_hw_addr = dma_params.desc_mem_phys;
+ dma_params.bus_freq_mhz = cpsw->bus_freq_mhz;
cpsw->dma = cpdma_ctlr_create(&dma_params);
if (!cpsw->dma) {
@@ -2750,9 +2977,9 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_dt_ret;
}
- cpsw->txch[0] = cpdma_chan_create(cpsw->dma, 0, cpsw_tx_handler, 0);
- cpsw->rxch[0] = cpdma_chan_create(cpsw->dma, 0, cpsw_rx_handler, 1);
- if (WARN_ON(!cpsw->rxch[0] || !cpsw->txch[0])) {
+ cpsw->txv[0].ch = cpdma_chan_create(cpsw->dma, 0, cpsw_tx_handler, 0);
+ cpsw->rxv[0].ch = cpdma_chan_create(cpsw->dma, 0, cpsw_rx_handler, 1);
+ if (WARN_ON(!cpsw->rxv[0].ch || !cpsw->txv[0].ch)) {
dev_err(priv->dev, "error initializing dma channels\n");
ret = -ENOMEM;
goto clean_dma_ret;
@@ -2770,6 +2997,12 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_dma_ret;
}
+ cpsw->cpts = cpts_create(cpsw->dev, cpts_regs, cpsw->dev->of_node);
+ if (IS_ERR(cpsw->cpts)) {
+ ret = PTR_ERR(cpsw->cpts);
+ goto clean_ale_ret;
+ }
+
ndev->irq = platform_get_irq(pdev, 1);
if (ndev->irq < 0) {
dev_err(priv->dev, "error getting irq resource\n");
@@ -2828,6 +3061,7 @@ static int cpsw_probe(struct platform_device *pdev)
ndev->ethtool_ops = &cpsw_ethtool_ops;
netif_napi_add(ndev, &cpsw->napi_rx, cpsw_rx_poll, CPSW_POLL_WEIGHT);
netif_tx_napi_add(ndev, &cpsw->napi_tx, cpsw_tx_poll, CPSW_POLL_WEIGHT);
+ cpsw_split_res(ndev);
/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -2885,6 +3119,7 @@ static int cpsw_remove(struct platform_device *pdev)
unregister_netdev(cpsw->slaves[1].ndev);
unregister_netdev(ndev);
+ cpts_release(cpsw->cpts);
cpsw_ale_destroy(cpsw->ale);
cpdma_ctlr_destroy(cpsw->dma);
cpsw_remove_dt(pdev);
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index 16b54c6f32c2..6c3037aa2cd3 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -31,8 +31,6 @@ struct cpsw_platform_data {
u32 channels; /* number of cpdma channels (symmetric) */
u32 slaves; /* number of slave cpgmac ports */
u32 active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */
- u32 cpts_clock_mult; /* convert input clock ticks to nanoseconds */
- u32 cpts_clock_shift; /* convert input clock ticks to nanoseconds */
u32 ale_entries; /* ale table size */
u32 bd_ram_size; /*buffer descriptor ram size */
u32 mac_control; /* Mac control register */
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 85a55b4ff8c0..0c0d48e5bea4 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -31,10 +31,8 @@
#include "cpts.h"
-#ifdef CONFIG_TI_CPTS
-
-#define cpts_read32(c, r) __raw_readl(&c->reg->r)
-#define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r)
+#define cpts_read32(c, r) readl_relaxed(&c->reg->r)
+#define cpts_write32(c, v, r) writel_relaxed(v, &c->reg->r)
static int event_expired(struct cpts_event *event)
{
@@ -59,6 +57,26 @@ static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low)
return -1;
}
+static int cpts_purge_events(struct cpts *cpts)
+{
+ struct list_head *this, *next;
+ struct cpts_event *event;
+ int removed = 0;
+
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ if (event_expired(event)) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ ++removed;
+ }
+ }
+
+ if (removed)
+ pr_debug("cpts: event pool cleaned up %d\n", removed);
+ return removed ? 0 : -1;
+}
+
/*
* Returns zero if matching event type was found.
*/
@@ -71,10 +89,12 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
if (cpts_fifo_pop(cpts, &hi, &lo))
break;
- if (list_empty(&cpts->pool)) {
- pr_err("cpts: event pool is empty\n");
+
+ if (list_empty(&cpts->pool) && cpts_purge_events(cpts)) {
+ pr_err("cpts: event pool empty\n");
return -1;
}
+
event = list_first_entry(&cpts->pool, struct cpts_event, list);
event->tmo = jiffies + 2;
event->high = hi;
@@ -223,27 +243,9 @@ static void cpts_overflow_check(struct work_struct *work)
struct timespec64 ts;
struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
- cpts_write32(cpts, CPTS_EN, control);
- cpts_write32(cpts, TS_PEND_EN, int_enable);
cpts_ptp_gettime(&cpts->info, &ts);
pr_debug("cpts overflow check at %lld.%09lu\n", ts.tv_sec, ts.tv_nsec);
- schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
-}
-
-static void cpts_clk_init(struct device *dev, struct cpts *cpts)
-{
- cpts->refclk = devm_clk_get(dev, "cpts");
- if (IS_ERR(cpts->refclk)) {
- dev_err(dev, "Failed to get cpts refclk\n");
- cpts->refclk = NULL;
- return;
- }
- clk_prepare_enable(cpts->refclk);
-}
-
-static void cpts_clk_release(struct cpts *cpts)
-{
- clk_disable(cpts->refclk);
+ schedule_delayed_work(&cpts->overflow_work, cpts->ov_check_period);
}
static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
@@ -334,6 +336,7 @@ void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
memset(ssh, 0, sizeof(*ssh));
ssh->hwtstamp = ns_to_ktime(ns);
}
+EXPORT_SYMBOL_GPL(cpts_rx_timestamp);
void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
@@ -349,60 +352,170 @@ void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
ssh.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(skb, &ssh);
}
+EXPORT_SYMBOL_GPL(cpts_tx_timestamp);
-#endif /*CONFIG_TI_CPTS*/
-
-int cpts_register(struct device *dev, struct cpts *cpts,
- u32 mult, u32 shift)
+int cpts_register(struct cpts *cpts)
{
-#ifdef CONFIG_TI_CPTS
int err, i;
- unsigned long flags;
-
- cpts->info = cpts_info;
- cpts->clock = ptp_clock_register(&cpts->info, dev);
- if (IS_ERR(cpts->clock)) {
- err = PTR_ERR(cpts->clock);
- cpts->clock = NULL;
- return err;
- }
- spin_lock_init(&cpts->lock);
-
- cpts->cc.read = cpts_systim_read;
- cpts->cc.mask = CLOCKSOURCE_MASK(32);
- cpts->cc_mult = mult;
- cpts->cc.mult = mult;
- cpts->cc.shift = shift;
INIT_LIST_HEAD(&cpts->events);
INIT_LIST_HEAD(&cpts->pool);
for (i = 0; i < CPTS_MAX_EVENTS; i++)
list_add(&cpts->pool_data[i].list, &cpts->pool);
- cpts_clk_init(dev, cpts);
+ clk_enable(cpts->refclk);
+
cpts_write32(cpts, CPTS_EN, control);
cpts_write32(cpts, TS_PEND_EN, int_enable);
- spin_lock_irqsave(&cpts->lock, flags);
timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
- spin_unlock_irqrestore(&cpts->lock, flags);
-
- INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
- schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+ cpts->clock = ptp_clock_register(&cpts->info, cpts->dev);
+ if (IS_ERR(cpts->clock)) {
+ err = PTR_ERR(cpts->clock);
+ cpts->clock = NULL;
+ goto err_ptp;
+ }
cpts->phc_index = ptp_clock_index(cpts->clock);
-#endif
+
+ schedule_delayed_work(&cpts->overflow_work, cpts->ov_check_period);
return 0;
+
+err_ptp:
+ clk_disable(cpts->refclk);
+ return err;
}
+EXPORT_SYMBOL_GPL(cpts_register);
void cpts_unregister(struct cpts *cpts)
{
-#ifdef CONFIG_TI_CPTS
- if (cpts->clock) {
- ptp_clock_unregister(cpts->clock);
- cancel_delayed_work_sync(&cpts->overflow_work);
+ if (WARN_ON(!cpts->clock))
+ return;
+
+ cancel_delayed_work_sync(&cpts->overflow_work);
+
+ ptp_clock_unregister(cpts->clock);
+ cpts->clock = NULL;
+
+ cpts_write32(cpts, 0, int_enable);
+ cpts_write32(cpts, 0, control);
+
+ clk_disable(cpts->refclk);
+}
+EXPORT_SYMBOL_GPL(cpts_unregister);
+
+static void cpts_calc_mult_shift(struct cpts *cpts)
+{
+ u64 frac, maxsec, ns;
+ u32 freq;
+
+ freq = clk_get_rate(cpts->refclk);
+
+ /* Calc the maximum number of seconds which we can run before
+ * wrapping around.
+ */
+ maxsec = cpts->cc.mask;
+ do_div(maxsec, freq);
+ /* limit conversation rate to 10 sec as higher values will produce
+ * too small mult factors and so reduce the conversion accuracy
+ */
+ if (maxsec > 10)
+ maxsec = 10;
+
+ /* Calc overflow check period (maxsec / 2) */
+ cpts->ov_check_period = (HZ * maxsec) / 2;
+ dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n",
+ cpts->ov_check_period);
+
+ if (cpts->cc.mult || cpts->cc.shift)
+ return;
+
+ clocks_calc_mult_shift(&cpts->cc.mult, &cpts->cc.shift,
+ freq, NSEC_PER_SEC, maxsec);
+
+ frac = 0;
+ ns = cyclecounter_cyc2ns(&cpts->cc, freq, cpts->cc.mask, &frac);
+
+ dev_info(cpts->dev,
+ "CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n",
+ freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC));
+}
+
+static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
+{
+ int ret = -EINVAL;
+ u32 prop;
+
+ if (!of_property_read_u32(node, "cpts_clock_mult", &prop))
+ cpts->cc.mult = prop;
+
+ if (!of_property_read_u32(node, "cpts_clock_shift", &prop))
+ cpts->cc.shift = prop;
+
+ if ((cpts->cc.mult && !cpts->cc.shift) ||
+ (!cpts->cc.mult && cpts->cc.shift))
+ goto of_error;
+
+ return 0;
+
+of_error:
+ dev_err(cpts->dev, "CPTS: Missing property in the DT.\n");
+ return ret;
+}
+
+struct cpts *cpts_create(struct device *dev, void __iomem *regs,
+ struct device_node *node)
+{
+ struct cpts *cpts;
+ int ret;
+
+ cpts = devm_kzalloc(dev, sizeof(*cpts), GFP_KERNEL);
+ if (!cpts)
+ return ERR_PTR(-ENOMEM);
+
+ cpts->dev = dev;
+ cpts->reg = (struct cpsw_cpts __iomem *)regs;
+ spin_lock_init(&cpts->lock);
+ INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
+
+ ret = cpts_of_parse(cpts, node);
+ if (ret)
+ return ERR_PTR(ret);
+
+ cpts->refclk = devm_clk_get(dev, "cpts");
+ if (IS_ERR(cpts->refclk)) {
+ dev_err(dev, "Failed to get cpts refclk\n");
+ return ERR_PTR(PTR_ERR(cpts->refclk));
}
- if (cpts->refclk)
- cpts_clk_release(cpts);
-#endif
+
+ clk_prepare(cpts->refclk);
+
+ cpts->cc.read = cpts_systim_read;
+ cpts->cc.mask = CLOCKSOURCE_MASK(32);
+ cpts->info = cpts_info;
+
+ cpts_calc_mult_shift(cpts);
+ /* save cc.mult original value as it can be modified
+ * by cpts_ptp_adjfreq().
+ */
+ cpts->cc_mult = cpts->cc.mult;
+
+ return cpts;
}
+EXPORT_SYMBOL_GPL(cpts_create);
+
+void cpts_release(struct cpts *cpts)
+{
+ if (!cpts)
+ return;
+
+ if (WARN_ON(!cpts->refclk))
+ return;
+
+ clk_unprepare(cpts->refclk);
+}
+EXPORT_SYMBOL_GPL(cpts_release);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI CPTS driver");
+MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index 69a46b92c7d6..c96eca2b1b46 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -20,11 +20,14 @@
#ifndef _TI_CPTS_H_
#define _TI_CPTS_H_
+#if IS_ENABLED(CONFIG_TI_CPTS)
+
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clocksource.h>
#include <linux/device.h>
#include <linux/list.h>
+#include <linux/of.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/skbuff.h>
#include <linux/timecounter.h>
@@ -94,9 +97,6 @@ enum {
CPTS_EV_TX, /* Ethernet Transmit Event */
};
-/* This covers any input clock up to about 500 MHz. */
-#define CPTS_OVERFLOW_PERIOD (HZ * 8)
-
#define CPTS_FIFO_DEPTH 16
#define CPTS_MAX_EVENTS 32
@@ -108,10 +108,10 @@ struct cpts_event {
};
struct cpts {
+ struct device *dev;
struct cpsw_cpts __iomem *reg;
int tx_enable;
int rx_enable;
-#ifdef CONFIG_TI_CPTS
struct ptp_clock_info info;
struct ptp_clock *clock;
spinlock_t lock; /* protects time registers */
@@ -124,22 +124,86 @@ struct cpts {
struct list_head events;
struct list_head pool;
struct cpts_event pool_data[CPTS_MAX_EVENTS];
-#endif
+ unsigned long ov_check_period;
};
-#ifdef CONFIG_TI_CPTS
void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+int cpts_register(struct cpts *cpts);
+void cpts_unregister(struct cpts *cpts);
+struct cpts *cpts_create(struct device *dev, void __iomem *regs,
+ struct device_node *node);
+void cpts_release(struct cpts *cpts);
+
+static inline void cpts_rx_enable(struct cpts *cpts, int enable)
+{
+ cpts->rx_enable = enable;
+}
+
+static inline bool cpts_is_rx_enabled(struct cpts *cpts)
+{
+ return !!cpts->rx_enable;
+}
+
+static inline void cpts_tx_enable(struct cpts *cpts, int enable)
+{
+ cpts->tx_enable = enable;
+}
+
+static inline bool cpts_is_tx_enabled(struct cpts *cpts)
+{
+ return !!cpts->tx_enable;
+}
+
#else
+struct cpts;
+
static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
}
static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
}
+
+static inline
+struct cpts *cpts_create(struct device *dev, void __iomem *regs,
+ struct device_node *node)
+{
+ return NULL;
+}
+
+static inline void cpts_release(struct cpts *cpts)
+{
+}
+
+static inline int
+cpts_register(struct cpts *cpts)
+{
+ return 0;
+}
+
+static inline void cpts_unregister(struct cpts *cpts)
+{
+}
+
+static inline void cpts_rx_enable(struct cpts *cpts, int enable)
+{
+}
+
+static inline bool cpts_is_rx_enabled(struct cpts *cpts)
+{
+ return false;
+}
+
+static inline void cpts_tx_enable(struct cpts *cpts, int enable)
+{
+}
+
+static inline bool cpts_is_tx_enabled(struct cpts *cpts)
+{
+ return false;
+}
#endif
-int cpts_register(struct device *dev, struct cpts *cpts, u32 mult, u32 shift);
-void cpts_unregister(struct cpts *cpts);
#endif
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index c3f35f11a8fd..36518fc5c7cc 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -32,6 +32,7 @@
#define CPDMA_RXCONTROL 0x14
#define CPDMA_SOFTRESET 0x1c
#define CPDMA_RXTEARDOWN 0x18
+#define CPDMA_TX_PRI0_RATE 0x30
#define CPDMA_TXINTSTATRAW 0x80
#define CPDMA_TXINTSTATMASKED 0x84
#define CPDMA_TXINTMASKSET 0x88
@@ -68,6 +69,8 @@
#define CPDMA_TEARDOWN_VALUE 0xfffffffc
+#define CPDMA_MAX_RLIM_CNT 16384
+
struct cpdma_desc {
/* hardware fields */
u32 hw_next;
@@ -122,6 +125,33 @@ struct cpdma_chan {
struct cpdma_chan_stats stats;
/* offsets into dmaregs */
int int_set, int_clear, td;
+ int weight;
+ u32 rate_factor;
+ u32 rate;
+};
+
+struct cpdma_control_info {
+ u32 reg;
+ u32 shift, mask;
+ int access;
+#define ACCESS_RO BIT(0)
+#define ACCESS_WO BIT(1)
+#define ACCESS_RW (ACCESS_RO | ACCESS_WO)
+};
+
+static struct cpdma_control_info controls[] = {
+ [CPDMA_TX_RLIM] = {CPDMA_DMACONTROL, 8, 0xffff, ACCESS_RW},
+ [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
+ [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW},
+ [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW},
+ [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW},
+ [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW},
+ [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO},
+ [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW},
+ [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW},
+ [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW},
+ [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW},
+ [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW},
};
#define tx_chan_num(chan) (chan)
@@ -253,6 +283,211 @@ static void cpdma_desc_free(struct cpdma_desc_pool *pool,
gen_pool_free(pool->gen_pool, (unsigned long)desc, pool->desc_size);
}
+static int _cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
+{
+ struct cpdma_control_info *info = &controls[control];
+ u32 val;
+
+ if (!ctlr->params.has_ext_regs)
+ return -ENOTSUPP;
+
+ if (ctlr->state != CPDMA_STATE_ACTIVE)
+ return -EINVAL;
+
+ if (control < 0 || control >= ARRAY_SIZE(controls))
+ return -ENOENT;
+
+ if ((info->access & ACCESS_WO) != ACCESS_WO)
+ return -EPERM;
+
+ val = dma_reg_read(ctlr, info->reg);
+ val &= ~(info->mask << info->shift);
+ val |= (value & info->mask) << info->shift;
+ dma_reg_write(ctlr, info->reg, val);
+
+ return 0;
+}
+
+static int _cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
+{
+ struct cpdma_control_info *info = &controls[control];
+ int ret;
+
+ if (!ctlr->params.has_ext_regs)
+ return -ENOTSUPP;
+
+ if (ctlr->state != CPDMA_STATE_ACTIVE)
+ return -EINVAL;
+
+ if (control < 0 || control >= ARRAY_SIZE(controls))
+ return -ENOENT;
+
+ if ((info->access & ACCESS_RO) != ACCESS_RO)
+ return -EPERM;
+
+ ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
+ return ret;
+}
+
+/* cpdma_chan_set_chan_shaper - set shaper for a channel
+ * Has to be called under ctlr lock
+ */
+static int cpdma_chan_set_chan_shaper(struct cpdma_chan *chan)
+{
+ struct cpdma_ctlr *ctlr = chan->ctlr;
+ u32 rate_reg;
+ u32 rmask;
+ int ret;
+
+ if (!chan->rate)
+ return 0;
+
+ rate_reg = CPDMA_TX_PRI0_RATE + 4 * chan->chan_num;
+ dma_reg_write(ctlr, rate_reg, chan->rate_factor);
+
+ rmask = _cpdma_control_get(ctlr, CPDMA_TX_RLIM);
+ rmask |= chan->mask;
+
+ ret = _cpdma_control_set(ctlr, CPDMA_TX_RLIM, rmask);
+ return ret;
+}
+
+static int cpdma_chan_on(struct cpdma_chan *chan)
+{
+ struct cpdma_ctlr *ctlr = chan->ctlr;
+ struct cpdma_desc_pool *pool = ctlr->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ if (chan->state != CPDMA_STATE_IDLE) {
+ spin_unlock_irqrestore(&chan->lock, flags);
+ return -EBUSY;
+ }
+ if (ctlr->state != CPDMA_STATE_ACTIVE) {
+ spin_unlock_irqrestore(&chan->lock, flags);
+ return -EINVAL;
+ }
+ dma_reg_write(ctlr, chan->int_set, chan->mask);
+ chan->state = CPDMA_STATE_ACTIVE;
+ if (chan->head) {
+ chan_write(chan, hdp, desc_phys(pool, chan->head));
+ if (chan->rxfree)
+ chan_write(chan, rxfree, chan->count);
+ }
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+ return 0;
+}
+
+/* cpdma_chan_fit_rate - set rate for a channel and check if it's possible.
+ * rmask - mask of rate limited channels
+ * Returns min rate in Kb/s
+ */
+static int cpdma_chan_fit_rate(struct cpdma_chan *ch, u32 rate,
+ u32 *rmask, int *prio_mode)
+{
+ struct cpdma_ctlr *ctlr = ch->ctlr;
+ struct cpdma_chan *chan;
+ u32 old_rate = ch->rate;
+ u32 new_rmask = 0;
+ int rlim = 1;
+ int i;
+
+ *prio_mode = 0;
+ for (i = tx_chan_num(0); i < tx_chan_num(CPDMA_MAX_CHANNELS); i++) {
+ chan = ctlr->channels[i];
+ if (!chan) {
+ rlim = 0;
+ continue;
+ }
+
+ if (chan == ch)
+ chan->rate = rate;
+
+ if (chan->rate) {
+ if (rlim) {
+ new_rmask |= chan->mask;
+ } else {
+ ch->rate = old_rate;
+ dev_err(ctlr->dev, "Prev channel of %dch is not rate limited\n",
+ chan->chan_num);
+ return -EINVAL;
+ }
+ } else {
+ *prio_mode = 1;
+ rlim = 0;
+ }
+ }
+
+ *rmask = new_rmask;
+ return 0;
+}
+
+static u32 cpdma_chan_set_factors(struct cpdma_ctlr *ctlr,
+ struct cpdma_chan *ch)
+{
+ u32 delta = UINT_MAX, prev_delta = UINT_MAX, best_delta = UINT_MAX;
+ u32 best_send_cnt = 0, best_idle_cnt = 0;
+ u32 new_rate, best_rate = 0, rate_reg;
+ u64 send_cnt, idle_cnt;
+ u32 min_send_cnt, freq;
+ u64 divident, divisor;
+
+ if (!ch->rate) {
+ ch->rate_factor = 0;
+ goto set_factor;
+ }
+
+ freq = ctlr->params.bus_freq_mhz * 1000 * 32;
+ if (!freq) {
+ dev_err(ctlr->dev, "The bus frequency is not set\n");
+ return -EINVAL;
+ }
+
+ min_send_cnt = freq - ch->rate;
+ send_cnt = DIV_ROUND_UP(min_send_cnt, ch->rate);
+ while (send_cnt <= CPDMA_MAX_RLIM_CNT) {
+ divident = ch->rate * send_cnt;
+ divisor = min_send_cnt;
+ idle_cnt = DIV_ROUND_CLOSEST_ULL(divident, divisor);
+
+ divident = freq * idle_cnt;
+ divisor = idle_cnt + send_cnt;
+ new_rate = DIV_ROUND_CLOSEST_ULL(divident, divisor);
+
+ delta = new_rate >= ch->rate ? new_rate - ch->rate : delta;
+ if (delta < best_delta) {
+ best_delta = delta;
+ best_send_cnt = send_cnt;
+ best_idle_cnt = idle_cnt;
+ best_rate = new_rate;
+
+ if (!delta)
+ break;
+ }
+
+ if (prev_delta >= delta) {
+ prev_delta = delta;
+ send_cnt++;
+ continue;
+ }
+
+ idle_cnt++;
+ divident = freq * idle_cnt;
+ send_cnt = DIV_ROUND_CLOSEST_ULL(divident, ch->rate);
+ send_cnt -= idle_cnt;
+ prev_delta = UINT_MAX;
+ }
+
+ ch->rate = best_rate;
+ ch->rate_factor = best_send_cnt | (best_idle_cnt << 16);
+
+set_factor:
+ rate_reg = CPDMA_TX_PRI0_RATE + 4 * ch->chan_num;
+ dma_reg_write(ctlr, rate_reg, ch->rate_factor);
+ return 0;
+}
+
struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
{
struct cpdma_ctlr *ctlr;
@@ -283,8 +518,9 @@ EXPORT_SYMBOL_GPL(cpdma_ctlr_create);
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
{
+ struct cpdma_chan *chan;
unsigned long flags;
- int i;
+ int i, prio_mode;
spin_lock_irqsave(&ctlr->lock, flags);
if (ctlr->state != CPDMA_STATE_IDLE) {
@@ -320,10 +556,22 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
ctlr->state = CPDMA_STATE_ACTIVE;
+ prio_mode = 0;
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
- if (ctlr->channels[i])
- cpdma_chan_start(ctlr->channels[i]);
+ chan = ctlr->channels[i];
+ if (chan) {
+ cpdma_chan_set_chan_shaper(chan);
+ cpdma_chan_on(chan);
+
+ /* off prio mode if all tx channels are rate limited */
+ if (is_tx_chan(chan) && !chan->rate)
+ prio_mode = 1;
+ }
}
+
+ _cpdma_control_set(ctlr, CPDMA_TX_PRIO_FIXED, prio_mode);
+ _cpdma_control_set(ctlr, CPDMA_RX_BUFFER_OFFSET, 0);
+
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
@@ -335,7 +583,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
int i;
spin_lock_irqsave(&ctlr->lock, flags);
- if (ctlr->state == CPDMA_STATE_TEARDOWN) {
+ if (ctlr->state != CPDMA_STATE_ACTIVE) {
spin_unlock_irqrestore(&ctlr->lock, flags);
return -EINVAL;
}
@@ -422,30 +670,205 @@ u32 cpdma_ctrl_txchs_state(struct cpdma_ctlr *ctlr)
}
EXPORT_SYMBOL_GPL(cpdma_ctrl_txchs_state);
+static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr,
+ int rx, int desc_num,
+ int per_ch_desc)
+{
+ struct cpdma_chan *chan, *most_chan = NULL;
+ int desc_cnt = desc_num;
+ int most_dnum = 0;
+ int min, max, i;
+
+ if (!desc_num)
+ return;
+
+ if (rx) {
+ min = rx_chan_num(0);
+ max = rx_chan_num(CPDMA_MAX_CHANNELS);
+ } else {
+ min = tx_chan_num(0);
+ max = tx_chan_num(CPDMA_MAX_CHANNELS);
+ }
+
+ for (i = min; i < max; i++) {
+ chan = ctlr->channels[i];
+ if (!chan)
+ continue;
+
+ if (chan->weight)
+ chan->desc_num = (chan->weight * desc_num) / 100;
+ else
+ chan->desc_num = per_ch_desc;
+
+ desc_cnt -= chan->desc_num;
+
+ if (most_dnum < chan->desc_num) {
+ most_dnum = chan->desc_num;
+ most_chan = chan;
+ }
+ }
+ /* use remains */
+ most_chan->desc_num += desc_cnt;
+}
+
/**
* cpdma_chan_split_pool - Splits ctrl pool between all channels.
* Has to be called under ctlr lock
*/
-static void cpdma_chan_split_pool(struct cpdma_ctlr *ctlr)
+static int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr)
{
+ int tx_per_ch_desc = 0, rx_per_ch_desc = 0;
struct cpdma_desc_pool *pool = ctlr->pool;
+ int free_rx_num = 0, free_tx_num = 0;
+ int rx_weight = 0, tx_weight = 0;
+ int tx_desc_num, rx_desc_num;
struct cpdma_chan *chan;
- int ch_desc_num;
- int i;
+ int i, tx_num = 0;
if (!ctlr->chan_num)
- return;
-
- /* calculate average size of pool slice */
- ch_desc_num = pool->num_desc / ctlr->chan_num;
+ return 0;
- /* split ctlr pool */
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
chan = ctlr->channels[i];
- if (chan)
- chan->desc_num = ch_desc_num;
+ if (!chan)
+ continue;
+
+ if (is_rx_chan(chan)) {
+ if (!chan->weight)
+ free_rx_num++;
+ rx_weight += chan->weight;
+ } else {
+ if (!chan->weight)
+ free_tx_num++;
+ tx_weight += chan->weight;
+ tx_num++;
+ }
+ }
+
+ if (rx_weight > 100 || tx_weight > 100)
+ return -EINVAL;
+
+ tx_desc_num = (tx_num * pool->num_desc) / ctlr->chan_num;
+ rx_desc_num = pool->num_desc - tx_desc_num;
+
+ if (free_tx_num) {
+ tx_per_ch_desc = tx_desc_num - (tx_weight * tx_desc_num) / 100;
+ tx_per_ch_desc /= free_tx_num;
+ }
+ if (free_rx_num) {
+ rx_per_ch_desc = rx_desc_num - (rx_weight * rx_desc_num) / 100;
+ rx_per_ch_desc /= free_rx_num;
+ }
+
+ cpdma_chan_set_descs(ctlr, 0, tx_desc_num, tx_per_ch_desc);
+ cpdma_chan_set_descs(ctlr, 1, rx_desc_num, rx_per_ch_desc);
+
+ return 0;
+}
+
+/* cpdma_chan_set_weight - set weight of a channel in percentage.
+ * Tx and Rx channels have separate weights. That is 100% for RX
+ * and 100% for Tx. The weight is used to split cpdma resources
+ * in correct proportion required by the channels, including number
+ * of descriptors. The channel rate is not enough to know the
+ * weight of a channel as the maximum rate of an interface is needed.
+ * If weight = 0, then channel uses rest of descriptors leaved by
+ * weighted channels.
+ */
+int cpdma_chan_set_weight(struct cpdma_chan *ch, int weight)
+{
+ struct cpdma_ctlr *ctlr = ch->ctlr;
+ unsigned long flags, ch_flags;
+ int ret;
+
+ spin_lock_irqsave(&ctlr->lock, flags);
+ spin_lock_irqsave(&ch->lock, ch_flags);
+ if (ch->weight == weight) {
+ spin_unlock_irqrestore(&ch->lock, ch_flags);
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ return 0;
}
+ ch->weight = weight;
+ spin_unlock_irqrestore(&ch->lock, ch_flags);
+
+ /* re-split pool using new channel weight */
+ ret = cpdma_chan_split_pool(ctlr);
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_set_weight);
+
+/* cpdma_chan_get_min_rate - get minimum allowed rate for channel
+ * Should be called before cpdma_chan_set_rate.
+ * Returns min rate in Kb/s
+ */
+u32 cpdma_chan_get_min_rate(struct cpdma_ctlr *ctlr)
+{
+ unsigned int divident, divisor;
+
+ divident = ctlr->params.bus_freq_mhz * 32 * 1000;
+ divisor = 1 + CPDMA_MAX_RLIM_CNT;
+
+ return DIV_ROUND_UP(divident, divisor);
+}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_min_rate);
+
+/* cpdma_chan_set_rate - limits bandwidth for transmit channel.
+ * The bandwidth * limited channels have to be in order beginning from lowest.
+ * ch - transmit channel the bandwidth is configured for
+ * rate - bandwidth in Kb/s, if 0 - then off shaper
+ */
+int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate)
+{
+ struct cpdma_ctlr *ctlr = ch->ctlr;
+ unsigned long flags, ch_flags;
+ int ret, prio_mode;
+ u32 rmask;
+
+ if (!ch || !is_tx_chan(ch))
+ return -EINVAL;
+
+ if (ch->rate == rate)
+ return rate;
+
+ spin_lock_irqsave(&ctlr->lock, flags);
+ spin_lock_irqsave(&ch->lock, ch_flags);
+
+ ret = cpdma_chan_fit_rate(ch, rate, &rmask, &prio_mode);
+ if (ret)
+ goto err;
+
+ ret = cpdma_chan_set_factors(ctlr, ch);
+ if (ret)
+ goto err;
+
+ spin_unlock_irqrestore(&ch->lock, ch_flags);
+
+ /* on shapers */
+ _cpdma_control_set(ctlr, CPDMA_TX_RLIM, rmask);
+ _cpdma_control_set(ctlr, CPDMA_TX_PRIO_FIXED, prio_mode);
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ return ret;
+
+err:
+ spin_unlock_irqrestore(&ch->lock, ch_flags);
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpdma_chan_set_rate);
+
+u32 cpdma_chan_get_rate(struct cpdma_chan *ch)
+{
+ unsigned long flags;
+ u32 rate;
+
+ spin_lock_irqsave(&ch->lock, flags);
+ rate = ch->rate;
+ spin_unlock_irqrestore(&ch->lock, flags);
+
+ return rate;
+}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_rate);
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
cpdma_handler_fn handler, int rx_type)
@@ -474,7 +897,9 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
chan->state = CPDMA_STATE_IDLE;
chan->chan_num = chan_num;
chan->handler = handler;
+ chan->rate = 0;
chan->desc_num = ctlr->pool->num_desc / 2;
+ chan->weight = 0;
if (is_rx_chan(chan)) {
chan->hdp = ctlr->params.rxhdp + offset;
@@ -533,7 +958,7 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)
cpdma_chan_stop(chan);
ctlr->channels[chan->chan_num] = NULL;
ctlr->chan_num--;
-
+ devm_kfree(ctlr->dev, chan);
cpdma_chan_split_pool(ctlr);
spin_unlock_irqrestore(&ctlr->lock, flags);
@@ -768,28 +1193,20 @@ EXPORT_SYMBOL_GPL(cpdma_chan_process);
int cpdma_chan_start(struct cpdma_chan *chan)
{
- struct cpdma_ctlr *ctlr = chan->ctlr;
- struct cpdma_desc_pool *pool = ctlr->pool;
- unsigned long flags;
+ struct cpdma_ctlr *ctlr = chan->ctlr;
+ unsigned long flags;
+ int ret;
- spin_lock_irqsave(&chan->lock, flags);
- if (chan->state != CPDMA_STATE_IDLE) {
- spin_unlock_irqrestore(&chan->lock, flags);
- return -EBUSY;
- }
- if (ctlr->state != CPDMA_STATE_ACTIVE) {
- spin_unlock_irqrestore(&chan->lock, flags);
- return -EINVAL;
- }
- dma_reg_write(ctlr, chan->int_set, chan->mask);
- chan->state = CPDMA_STATE_ACTIVE;
- if (chan->head) {
- chan_write(chan, hdp, desc_phys(pool, chan->head));
- if (chan->rxfree)
- chan_write(chan, rxfree, chan->count);
- }
+ spin_lock_irqsave(&ctlr->lock, flags);
+ ret = cpdma_chan_set_chan_shaper(chan);
+ spin_unlock_irqrestore(&ctlr->lock, flags);
+ if (ret)
+ return ret;
+
+ ret = cpdma_chan_on(chan);
+ if (ret)
+ return ret;
- spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(cpdma_chan_start);
@@ -874,93 +1291,27 @@ int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
return 0;
}
-struct cpdma_control_info {
- u32 reg;
- u32 shift, mask;
- int access;
-#define ACCESS_RO BIT(0)
-#define ACCESS_WO BIT(1)
-#define ACCESS_RW (ACCESS_RO | ACCESS_WO)
-};
-
-static struct cpdma_control_info controls[] = {
- [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
- [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW},
- [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW},
- [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW},
- [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW},
- [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO},
- [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW},
- [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW},
- [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW},
- [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW},
- [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW},
-};
-
int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
{
unsigned long flags;
- struct cpdma_control_info *info = &controls[control];
int ret;
spin_lock_irqsave(&ctlr->lock, flags);
-
- ret = -ENOTSUPP;
- if (!ctlr->params.has_ext_regs)
- goto unlock_ret;
-
- ret = -EINVAL;
- if (ctlr->state != CPDMA_STATE_ACTIVE)
- goto unlock_ret;
-
- ret = -ENOENT;
- if (control < 0 || control >= ARRAY_SIZE(controls))
- goto unlock_ret;
-
- ret = -EPERM;
- if ((info->access & ACCESS_RO) != ACCESS_RO)
- goto unlock_ret;
-
- ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
-
-unlock_ret:
+ ret = _cpdma_control_get(ctlr, control);
spin_unlock_irqrestore(&ctlr->lock, flags);
+
return ret;
}
int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
{
unsigned long flags;
- struct cpdma_control_info *info = &controls[control];
int ret;
- u32 val;
spin_lock_irqsave(&ctlr->lock, flags);
-
- ret = -ENOTSUPP;
- if (!ctlr->params.has_ext_regs)
- goto unlock_ret;
-
- ret = -EINVAL;
- if (ctlr->state != CPDMA_STATE_ACTIVE)
- goto unlock_ret;
-
- ret = -ENOENT;
- if (control < 0 || control >= ARRAY_SIZE(controls))
- goto unlock_ret;
-
- ret = -EPERM;
- if ((info->access & ACCESS_WO) != ACCESS_WO)
- goto unlock_ret;
-
- val = dma_reg_read(ctlr, info->reg);
- val &= ~(info->mask << info->shift);
- val |= (value & info->mask) << info->shift;
- dma_reg_write(ctlr, info->reg, val);
- ret = 0;
-
-unlock_ret:
+ ret = _cpdma_control_set(ctlr, control, value);
spin_unlock_irqrestore(&ctlr->lock, flags);
+
return ret;
}
EXPORT_SYMBOL_GPL(cpdma_control_set);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index a07b22b12bc1..4a167db2abab 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -36,6 +36,7 @@ struct cpdma_params {
u32 desc_hw_addr;
int desc_mem_size;
int desc_align;
+ u32 bus_freq_mhz;
/*
* Some instances of embedded cpdma controllers have extra control and
@@ -90,8 +91,13 @@ int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
u32 cpdma_ctrl_rxchs_state(struct cpdma_ctlr *ctlr);
u32 cpdma_ctrl_txchs_state(struct cpdma_ctlr *ctlr);
bool cpdma_check_free_tx_desc(struct cpdma_chan *chan);
+int cpdma_chan_set_weight(struct cpdma_chan *ch, int weight);
+int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate);
+u32 cpdma_chan_get_rate(struct cpdma_chan *ch);
+u32 cpdma_chan_get_min_rate(struct cpdma_ctlr *ctlr);
enum cpdma_control {
+ CPDMA_TX_RLIM, /* read-write */
CPDMA_CMD_IDLE, /* write-only */
CPDMA_COPY_ERROR_FRAMES, /* read-write */
CPDMA_RX_OFF_LEN_UPDATE, /* read-write */
diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h
index 17a26a429b71..0f58c584ae09 100644
--- a/drivers/net/ethernet/ti/netcp.h
+++ b/drivers/net/ethernet/ti/netcp.h
@@ -121,7 +121,7 @@ struct netcp_packet {
bool rxtstamp_complete;
void *ts_context;
- int (*txtstamp_complete)(void *ctx, struct netcp_packet *pkt);
+ void (*txtstamp)(void *ctx, struct sk_buff *skb);
};
static inline u32 *netcp_push_psdata(struct netcp_packet *p_info,
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 32516661f180..c243335ed649 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -100,6 +100,11 @@ struct netcp_intf_modpriv {
void *module_priv;
};
+struct netcp_tx_cb {
+ void *ts_context;
+ void (*txtstamp)(void *context, struct sk_buff *skb);
+};
+
static LIST_HEAD(netcp_devices);
static LIST_HEAD(netcp_modules);
static DEFINE_MUTEX(netcp_modules_lock);
@@ -544,6 +549,7 @@ int netcp_register_rxhook(struct netcp_intf *netcp_priv, int order,
return 0;
}
+EXPORT_SYMBOL_GPL(netcp_register_rxhook);
int netcp_unregister_rxhook(struct netcp_intf *netcp_priv, int order,
netcp_hook_rtn *hook_rtn, void *hook_data)
@@ -566,6 +572,7 @@ int netcp_unregister_rxhook(struct netcp_intf *netcp_priv, int order,
return -ENOENT;
}
+EXPORT_SYMBOL_GPL(netcp_unregister_rxhook);
static void netcp_frag_free(bool is_frag, void *ptr)
{
@@ -730,6 +737,7 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
/* Call each of the RX hooks */
p_info.skb = skb;
+ skb->dev = netcp->ndev;
p_info.rxtstamp_complete = false;
list_for_each_entry(rx_hook, &netcp->rxhook_list_head, list) {
int ret;
@@ -987,6 +995,7 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
unsigned int budget)
{
struct knav_dma_desc *desc;
+ struct netcp_tx_cb *tx_cb;
struct sk_buff *skb;
unsigned int dma_sz;
dma_addr_t dma;
@@ -1014,6 +1023,10 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
continue;
}
+ tx_cb = (struct netcp_tx_cb *)skb->cb;
+ if (tx_cb->txtstamp)
+ tx_cb->txtstamp(tx_cb->ts_context, skb);
+
if (netif_subqueue_stopped(netcp->ndev, skb) &&
netif_running(netcp->ndev) &&
(knav_pool_count(netcp->tx_pool) >
@@ -1154,6 +1167,7 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp,
struct netcp_tx_pipe *tx_pipe = NULL;
struct netcp_hook_list *tx_hook;
struct netcp_packet p_info;
+ struct netcp_tx_cb *tx_cb;
unsigned int dma_sz;
dma_addr_t dma;
u32 tmp = 0;
@@ -1164,7 +1178,7 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp,
p_info.tx_pipe = NULL;
p_info.psdata_len = 0;
p_info.ts_context = NULL;
- p_info.txtstamp_complete = NULL;
+ p_info.txtstamp = NULL;
p_info.epib = desc->epib;
p_info.psdata = (u32 __force *)desc->psdata;
memset(p_info.epib, 0, KNAV_DMA_NUM_EPIB_WORDS * sizeof(__le32));
@@ -1189,6 +1203,10 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp,
goto out;
}
+ tx_cb = (struct netcp_tx_cb *)skb->cb;
+ tx_cb->ts_context = p_info.ts_context;
+ tx_cb->txtstamp = p_info.txtstamp;
+
/* update descriptor */
if (p_info.psdata_len) {
/* psdata points to both native-endian and device-endian data */
@@ -1568,7 +1586,7 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
/* open Tx completion queue */
snprintf(name, sizeof(name), "tx-compl-%s", ndev->name);
netcp->tx_compl_q = knav_queue_open(name, netcp->tx_compl_qid, 0);
- if (IS_ERR_OR_NULL(netcp->tx_compl_q)) {
+ if (IS_ERR(netcp->tx_compl_q)) {
ret = PTR_ERR(netcp->tx_compl_q);
goto fail;
}
@@ -1588,7 +1606,7 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
/* open Rx completion queue */
snprintf(name, sizeof(name), "rx-compl-%s", ndev->name);
netcp->rx_queue = knav_queue_open(name, netcp->rx_queue_id, 0);
- if (IS_ERR_OR_NULL(netcp->rx_queue)) {
+ if (IS_ERR(netcp->rx_queue)) {
ret = PTR_ERR(netcp->rx_queue);
goto fail;
}
@@ -1610,7 +1628,7 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
++i) {
snprintf(name, sizeof(name), "rx-fdq-%s-%d", ndev->name, i);
netcp->rx_fdq[i] = knav_queue_open(name, KNAV_QUEUE_GP, 0);
- if (IS_ERR_OR_NULL(netcp->rx_fdq[i])) {
+ if (IS_ERR(netcp->rx_fdq[i])) {
ret = PTR_ERR(netcp->rx_fdq[i]);
goto fail;
}
@@ -1766,21 +1784,6 @@ out:
return (ret == 0) ? 0 : err;
}
-static int netcp_ndo_change_mtu(struct net_device *ndev, int new_mtu)
-{
- struct netcp_intf *netcp = netdev_priv(ndev);
-
- /* MTU < 68 is an error for IPv4 traffic */
- if ((new_mtu < 68) ||
- (new_mtu > (NETCP_MAX_FRAME_SIZE - ETH_HLEN - ETH_FCS_LEN))) {
- dev_err(netcp->ndev_dev, "Invalid mtu size = %d\n", new_mtu);
- return -EINVAL;
- }
-
- ndev->mtu = new_mtu;
- return 0;
-}
-
static void netcp_ndo_tx_timeout(struct net_device *ndev)
{
struct netcp_intf *netcp = netdev_priv(ndev);
@@ -1886,7 +1889,6 @@ static const struct net_device_ops netcp_netdev_ops = {
.ndo_start_xmit = netcp_ndo_start_xmit,
.ndo_set_rx_mode = netcp_set_rx_mode,
.ndo_do_ioctl = netcp_ndo_ioctl,
- .ndo_change_mtu = netcp_ndo_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = netcp_rx_add_vid,
@@ -1923,6 +1925,10 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
ndev->hw_features = ndev->features;
ndev->vlan_features |= NETIF_F_SG;
+ /* MTU range: 68 - 9486 */
+ ndev->min_mtu = ETH_MIN_MTU;
+ ndev->max_mtu = NETCP_MAX_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
netcp = netdev_priv(ndev);
spin_lock_init(&netcp->lock);
INIT_LIST_HEAD(&netcp->module_head);
@@ -2070,7 +2076,6 @@ static void netcp_delete_interface(struct netcp_device *netcp_device,
if (module->release)
module->release(intf_modpriv->module_priv);
list_del(&intf_modpriv->intf_list);
- kfree(intf_modpriv);
}
WARN(!list_empty(&netcp->module_head), "%s interface module list is not empty!\n",
ndev->name);
@@ -2133,6 +2138,8 @@ static int netcp_probe(struct platform_device *pdev)
}
}
+ of_node_put(interfaces);
+
/* Add the device instance to the list */
list_add_tail(&netcp_device->device_list, &netcp_devices);
@@ -2145,6 +2152,8 @@ probe_quit_interface:
netcp_delete_interface(netcp_device, netcp_intf->ndev);
}
+ of_node_put(interfaces);
+
probe_quit:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -2165,7 +2174,6 @@ static int netcp_remove(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Removing module \"%s\"\n", module->name);
module->remove(netcp_device, inst_modpriv->module_priv);
list_del(&inst_modpriv->inst_list);
- kfree(inst_modpriv);
}
/* now that all modules are removed, clean up the interfaces */
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index d543298d6750..c7e547e4f2b1 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -23,10 +23,13 @@
#include <linux/of_mdio.h>
#include <linux/of_address.h>
#include <linux/if_vlan.h>
+#include <linux/ptp_classify.h>
+#include <linux/net_tstamp.h>
#include <linux/ethtool.h>
#include "cpsw_ale.h"
#include "netcp.h"
+#include "cpts.h"
#define NETCP_DRIVER_NAME "TI KeyStone Ethernet Driver"
#define NETCP_DRIVER_VERSION "v1.0"
@@ -51,6 +54,7 @@
#define GBE13_EMAC_OFFSET 0x100
#define GBE13_SLAVE_PORT2_OFFSET 0x200
#define GBE13_HW_STATS_OFFSET 0x300
+#define GBE13_CPTS_OFFSET 0x500
#define GBE13_ALE_OFFSET 0x600
#define GBE13_HOST_PORT_NUM 0
#define GBE13_NUM_ALE_ENTRIES 1024
@@ -74,6 +78,7 @@
#define GBENU_SLAVE_PORT_OFFSET 0x2000
#define GBENU_EMAC_OFFSET 0x2330
#define GBENU_HW_STATS_OFFSET 0x1a000
+#define GBENU_CPTS_OFFSET 0x1d000
#define GBENU_ALE_OFFSET 0x1e000
#define GBENU_HOST_PORT_NUM 0
#define GBENU_NUM_ALE_ENTRIES 1024
@@ -93,6 +98,7 @@
#define XGBE10_HOST_PORT_OFFSET 0x34
#define XGBE10_SLAVE_PORT_OFFSET 0x64
#define XGBE10_EMAC_OFFSET 0x400
+#define XGBE10_CPTS_OFFSET 0x600
#define XGBE10_ALE_OFFSET 0x700
#define XGBE10_HW_STATS_OFFSET 0x800
#define XGBE10_HOST_PORT_NUM 0
@@ -155,6 +161,7 @@
#define GBE_TX_QUEUE 648
#define GBE_TXHOOK_ORDER 0
+#define GBE_RXHOOK_ORDER 0
#define GBE_DEFAULT_ALE_AGEOUT 30
#define SLAVE_LINK_IS_XGMII(s) ((s)->link_interface >= XGMII_LINK_MAC_PHY)
#define NETCP_LINK_STATE_INVALID -1
@@ -169,6 +176,56 @@
#define HOST_TX_PRI_MAP_DEFAULT 0x00000000
+#if IS_ENABLED(CONFIG_TI_CPTS)
+/* Px_TS_CTL register fields */
+#define TS_RX_ANX_F_EN BIT(0)
+#define TS_RX_VLAN_LT1_EN BIT(1)
+#define TS_RX_VLAN_LT2_EN BIT(2)
+#define TS_RX_ANX_D_EN BIT(3)
+#define TS_TX_ANX_F_EN BIT(4)
+#define TS_TX_VLAN_LT1_EN BIT(5)
+#define TS_TX_VLAN_LT2_EN BIT(6)
+#define TS_TX_ANX_D_EN BIT(7)
+#define TS_LT2_EN BIT(8)
+#define TS_RX_ANX_E_EN BIT(9)
+#define TS_TX_ANX_E_EN BIT(10)
+#define TS_MSG_TYPE_EN_SHIFT 16
+#define TS_MSG_TYPE_EN_MASK 0xffff
+
+/* Px_TS_SEQ_LTYPE register fields */
+#define TS_SEQ_ID_OFS_SHIFT 16
+#define TS_SEQ_ID_OFS_MASK 0x3f
+
+/* Px_TS_CTL_LTYPE2 register fields */
+#define TS_107 BIT(16)
+#define TS_129 BIT(17)
+#define TS_130 BIT(18)
+#define TS_131 BIT(19)
+#define TS_132 BIT(20)
+#define TS_319 BIT(21)
+#define TS_320 BIT(22)
+#define TS_TTL_NONZERO BIT(23)
+#define TS_UNI_EN BIT(24)
+#define TS_UNI_EN_SHIFT 24
+
+#define TS_TX_ANX_ALL_EN \
+ (TS_TX_ANX_D_EN | TS_TX_ANX_E_EN | TS_TX_ANX_F_EN)
+
+#define TS_RX_ANX_ALL_EN \
+ (TS_RX_ANX_D_EN | TS_RX_ANX_E_EN | TS_RX_ANX_F_EN)
+
+#define TS_CTL_DST_PORT TS_319
+#define TS_CTL_DST_PORT_SHIFT 21
+
+#define TS_CTL_MADDR_ALL \
+ (TS_107 | TS_129 | TS_130 | TS_131 | TS_132)
+
+#define TS_CTL_MADDR_SHIFT 16
+
+/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
+#define EVENT_MSG_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#endif /* CONFIG_TI_CPTS */
+
struct xgbe_ss_regs {
u32 id_ver;
u32 synce_count;
@@ -616,6 +673,13 @@ struct gbe_hw_stats {
#define GBE_MAX_HW_STAT_MODS 9
#define GBE_HW_STATS_REG_MAP_SZ 0x100
+struct ts_ctl {
+ int uni;
+ u8 dst_port_map;
+ u8 maddr_map;
+ u8 ts_mcast_type;
+};
+
struct gbe_slave {
void __iomem *port_regs;
void __iomem *emac_regs;
@@ -630,6 +694,7 @@ struct gbe_slave {
u32 mac_control;
u8 phy_port_t;
struct device_node *phy_node;
+ struct ts_ctl ts_ctl;
struct list_head slave_list;
};
@@ -655,6 +720,7 @@ struct gbe_priv {
void __iomem *switch_regs;
void __iomem *host_port_regs;
void __iomem *ale_reg;
+ void __iomem *cpts_reg;
void __iomem *sgmii_port_regs;
void __iomem *sgmii_port34_regs;
void __iomem *xgbe_serdes_regs;
@@ -678,6 +744,9 @@ struct gbe_priv {
int num_et_stats;
/* Lock for updating the hwstats */
spinlock_t hw_stats_lock;
+
+ int cpts_registered;
+ struct cpts *cpts;
};
struct gbe_intf {
@@ -1840,8 +1909,8 @@ static void keystone_get_ethtool_stats(struct net_device *ndev,
spin_unlock_bh(&gbe_dev->hw_stats_lock);
}
-static int keystone_get_settings(struct net_device *ndev,
- struct ethtool_cmd *cmd)
+static int keystone_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
{
struct netcp_intf *netcp = netdev_priv(ndev);
struct phy_device *phy = ndev->phydev;
@@ -1858,20 +1927,28 @@ static int keystone_get_settings(struct net_device *ndev,
if (!gbe_intf->slave)
return -EINVAL;
- ret = phy_ethtool_gset(phy, cmd);
+ ret = phy_ethtool_ksettings_get(phy, cmd);
if (!ret)
- cmd->port = gbe_intf->slave->phy_port_t;
+ cmd->base.port = gbe_intf->slave->phy_port_t;
return ret;
}
-static int keystone_set_settings(struct net_device *ndev,
- struct ethtool_cmd *cmd)
+static int keystone_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *cmd)
{
struct netcp_intf *netcp = netdev_priv(ndev);
struct phy_device *phy = ndev->phydev;
struct gbe_intf *gbe_intf;
- u32 features = cmd->advertising & cmd->supported;
+ u8 port = cmd->base.port;
+ u32 advertising, supported;
+ u32 features;
+
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
+ ethtool_convert_link_mode_to_legacy_u32(&supported,
+ cmd->link_modes.supported);
+ features = advertising & supported;
if (!phy)
return -EINVAL;
@@ -1883,26 +1960,69 @@ static int keystone_set_settings(struct net_device *ndev,
if (!gbe_intf->slave)
return -EINVAL;
- if (cmd->port != gbe_intf->slave->phy_port_t) {
- if ((cmd->port == PORT_TP) && !(features & ADVERTISED_TP))
+ if (port != gbe_intf->slave->phy_port_t) {
+ if ((port == PORT_TP) && !(features & ADVERTISED_TP))
return -EINVAL;
- if ((cmd->port == PORT_AUI) && !(features & ADVERTISED_AUI))
+ if ((port == PORT_AUI) && !(features & ADVERTISED_AUI))
return -EINVAL;
- if ((cmd->port == PORT_BNC) && !(features & ADVERTISED_BNC))
+ if ((port == PORT_BNC) && !(features & ADVERTISED_BNC))
return -EINVAL;
- if ((cmd->port == PORT_MII) && !(features & ADVERTISED_MII))
+ if ((port == PORT_MII) && !(features & ADVERTISED_MII))
return -EINVAL;
- if ((cmd->port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE))
+ if ((port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE))
return -EINVAL;
}
- gbe_intf->slave->phy_port_t = cmd->port;
- return phy_ethtool_sset(phy, cmd);
+ gbe_intf->slave->phy_port_t = port;
+ return phy_ethtool_ksettings_set(phy, cmd);
+}
+
+#if IS_ENABLED(CONFIG_TI_CPTS)
+static int keystone_get_ts_info(struct net_device *ndev,
+ struct ethtool_ts_info *info)
+{
+ struct netcp_intf *netcp = netdev_priv(ndev);
+ struct gbe_intf *gbe_intf;
+
+ gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
+ if (!gbe_intf || !gbe_intf->gbe_dev->cpts)
+ return -EINVAL;
+
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = gbe_intf->gbe_dev->cpts->phc_index;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+ return 0;
}
+#else
+static int keystone_get_ts_info(struct net_device *ndev,
+ struct ethtool_ts_info *info)
+{
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+ info->phc_index = -1;
+ info->tx_types = 0;
+ info->rx_filters = 0;
+ return 0;
+}
+#endif /* CONFIG_TI_CPTS */
static const struct ethtool_ops keystone_ethtool_ops = {
.get_drvinfo = keystone_get_drvinfo,
@@ -1912,8 +2032,9 @@ static const struct ethtool_ops keystone_ethtool_ops = {
.get_strings = keystone_get_stat_strings,
.get_sset_count = keystone_get_sset_count,
.get_ethtool_stats = keystone_get_ethtool_stats,
- .get_settings = keystone_get_settings,
- .set_settings = keystone_set_settings,
+ .get_link_ksettings = keystone_get_link_ksettings,
+ .set_link_ksettings = keystone_set_link_ksettings,
+ .get_ts_info = keystone_get_ts_info,
};
#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
@@ -2357,16 +2478,279 @@ static int gbe_del_vid(void *intf_priv, int vid)
return 0;
}
+#if IS_ENABLED(CONFIG_TI_CPTS)
+#define HAS_PHY_TXTSTAMP(p) ((p)->drv && (p)->drv->txtstamp)
+#define HAS_PHY_RXTSTAMP(p) ((p)->drv && (p)->drv->rxtstamp)
+
+static void gbe_txtstamp(void *context, struct sk_buff *skb)
+{
+ struct gbe_intf *gbe_intf = context;
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+
+ cpts_tx_timestamp(gbe_dev->cpts, skb);
+}
+
+static bool gbe_need_txtstamp(struct gbe_intf *gbe_intf,
+ const struct netcp_packet *p_info)
+{
+ struct sk_buff *skb = p_info->skb;
+ unsigned int class = ptp_classify_raw(skb);
+
+ if (class == PTP_CLASS_NONE)
+ return false;
+
+ switch (class) {
+ case PTP_CLASS_V1_IPV4:
+ case PTP_CLASS_V1_IPV6:
+ case PTP_CLASS_V2_IPV4:
+ case PTP_CLASS_V2_IPV6:
+ case PTP_CLASS_V2_L2:
+ case (PTP_CLASS_V2_VLAN | PTP_CLASS_L2):
+ case (PTP_CLASS_V2_VLAN | PTP_CLASS_IPV4):
+ case (PTP_CLASS_V2_VLAN | PTP_CLASS_IPV6):
+ return true;
+ }
+
+ return false;
+}
+
+static int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf,
+ struct netcp_packet *p_info)
+{
+ struct phy_device *phydev = p_info->skb->dev->phydev;
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+
+ if (!(skb_shinfo(p_info->skb)->tx_flags & SKBTX_HW_TSTAMP) ||
+ !cpts_is_tx_enabled(gbe_dev->cpts))
+ return 0;
+
+ /* If phy has the txtstamp api, assume it will do it.
+ * We mark it here because skb_tx_timestamp() is called
+ * after all the txhooks are called.
+ */
+ if (phydev && HAS_PHY_TXTSTAMP(phydev)) {
+ skb_shinfo(p_info->skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ return 0;
+ }
+
+ if (gbe_need_txtstamp(gbe_intf, p_info)) {
+ p_info->txtstamp = gbe_txtstamp;
+ p_info->ts_context = (void *)gbe_intf;
+ skb_shinfo(p_info->skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ }
+
+ return 0;
+}
+
+static int gbe_rxtstamp(struct gbe_intf *gbe_intf, struct netcp_packet *p_info)
+{
+ struct phy_device *phydev = p_info->skb->dev->phydev;
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+
+ if (p_info->rxtstamp_complete)
+ return 0;
+
+ if (phydev && HAS_PHY_RXTSTAMP(phydev)) {
+ p_info->rxtstamp_complete = true;
+ return 0;
+ }
+
+ cpts_rx_timestamp(gbe_dev->cpts, p_info->skb);
+ p_info->rxtstamp_complete = true;
+
+ return 0;
+}
+
+static int gbe_hwtstamp_get(struct gbe_intf *gbe_intf, struct ifreq *ifr)
+{
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+ struct cpts *cpts = gbe_dev->cpts;
+ struct hwtstamp_config cfg;
+
+ if (!cpts)
+ return -EOPNOTSUPP;
+
+ cfg.flags = 0;
+ cfg.tx_type = cpts_is_tx_enabled(cpts) ?
+ HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+ cfg.rx_filter = (cpts_is_rx_enabled(cpts) ?
+ cpts->rx_enable : HWTSTAMP_FILTER_NONE);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static void gbe_hwtstamp(struct gbe_intf *gbe_intf)
+{
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+ struct gbe_slave *slave = gbe_intf->slave;
+ u32 ts_en, seq_id, ctl;
+
+ if (!cpts_is_rx_enabled(gbe_dev->cpts) &&
+ !cpts_is_tx_enabled(gbe_dev->cpts)) {
+ writel(0, GBE_REG_ADDR(slave, port_regs, ts_ctl));
+ return;
+ }
+
+ seq_id = (30 << TS_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
+ ts_en = EVENT_MSG_BITS << TS_MSG_TYPE_EN_SHIFT;
+ ctl = ETH_P_1588 | TS_TTL_NONZERO |
+ (slave->ts_ctl.dst_port_map << TS_CTL_DST_PORT_SHIFT) |
+ (slave->ts_ctl.uni ? TS_UNI_EN :
+ slave->ts_ctl.maddr_map << TS_CTL_MADDR_SHIFT);
+
+ if (cpts_is_tx_enabled(gbe_dev->cpts))
+ ts_en |= (TS_TX_ANX_ALL_EN | TS_TX_VLAN_LT1_EN);
+
+ if (cpts_is_rx_enabled(gbe_dev->cpts))
+ ts_en |= (TS_RX_ANX_ALL_EN | TS_RX_VLAN_LT1_EN);
+
+ writel(ts_en, GBE_REG_ADDR(slave, port_regs, ts_ctl));
+ writel(seq_id, GBE_REG_ADDR(slave, port_regs, ts_seq_ltype));
+ writel(ctl, GBE_REG_ADDR(slave, port_regs, ts_ctl_ltype2));
+}
+
+static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
+{
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+ struct cpts *cpts = gbe_dev->cpts;
+ struct hwtstamp_config cfg;
+
+ if (!cpts)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ cpts_tx_enable(cpts, 0);
+ break;
+ case HWTSTAMP_TX_ON:
+ cpts_tx_enable(cpts, 1);
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ cpts_rx_enable(cpts, 0);
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V1_L4_EVENT);
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V2_EVENT);
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ gbe_hwtstamp(gbe_intf);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static void gbe_register_cpts(struct gbe_priv *gbe_dev)
+{
+ if (!gbe_dev->cpts)
+ return;
+
+ if (gbe_dev->cpts_registered > 0)
+ goto done;
+
+ if (cpts_register(gbe_dev->cpts)) {
+ dev_err(gbe_dev->dev, "error registering cpts device\n");
+ return;
+ }
+
+done:
+ ++gbe_dev->cpts_registered;
+}
+
+static void gbe_unregister_cpts(struct gbe_priv *gbe_dev)
+{
+ if (!gbe_dev->cpts || (gbe_dev->cpts_registered <= 0))
+ return;
+
+ if (--gbe_dev->cpts_registered)
+ return;
+
+ cpts_unregister(gbe_dev->cpts);
+}
+#else
+static inline int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf,
+ struct netcp_packet *p_info)
+{
+ return 0;
+}
+
+static inline int gbe_rxtstamp(struct gbe_intf *gbe_intf,
+ struct netcp_packet *p_info)
+{
+ return 0;
+}
+
+static inline int gbe_hwtstamp(struct gbe_intf *gbe_intf,
+ struct ifreq *ifr, int cmd)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void gbe_register_cpts(struct gbe_priv *gbe_dev)
+{
+}
+
+static inline void gbe_unregister_cpts(struct gbe_priv *gbe_dev)
+{
+}
+
+static inline int gbe_hwtstamp_get(struct gbe_intf *gbe_intf, struct ifreq *req)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *req)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_TI_CPTS */
+
static int gbe_ioctl(void *intf_priv, struct ifreq *req, int cmd)
{
struct gbe_intf *gbe_intf = intf_priv;
struct phy_device *phy = gbe_intf->slave->phy;
- int ret = -EOPNOTSUPP;
+
+ if (!phy || !phy->drv->hwtstamp) {
+ switch (cmd) {
+ case SIOCGHWTSTAMP:
+ return gbe_hwtstamp_get(gbe_intf, req);
+ case SIOCSHWTSTAMP:
+ return gbe_hwtstamp_set(gbe_intf, req);
+ }
+ }
if (phy)
- ret = phy_mii_ioctl(phy, req, cmd);
+ return phy_mii_ioctl(phy, req, cmd);
- return ret;
+ return -EOPNOTSUPP;
}
static void netcp_ethss_timer(unsigned long arg)
@@ -2402,12 +2786,20 @@ static void netcp_ethss_timer(unsigned long arg)
add_timer(&gbe_dev->timer);
}
-static int gbe_tx_hook(int order, void *data, struct netcp_packet *p_info)
+static int gbe_txhook(int order, void *data, struct netcp_packet *p_info)
{
struct gbe_intf *gbe_intf = data;
p_info->tx_pipe = &gbe_intf->tx_pipe;
- return 0;
+
+ return gbe_txtstamp_mark_pkt(gbe_intf, p_info);
+}
+
+static int gbe_rxhook(int order, void *data, struct netcp_packet *p_info)
+{
+ struct gbe_intf *gbe_intf = data;
+
+ return gbe_rxtstamp(gbe_intf, p_info);
}
static int gbe_open(void *intf_priv, struct net_device *ndev)
@@ -2457,11 +2849,14 @@ static int gbe_open(void *intf_priv, struct net_device *ndev)
if (ret)
goto fail;
- netcp_register_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook,
- gbe_intf);
+ netcp_register_txhook(netcp, GBE_TXHOOK_ORDER, gbe_txhook, gbe_intf);
+ netcp_register_rxhook(netcp, GBE_RXHOOK_ORDER, gbe_rxhook, gbe_intf);
slave->open = true;
netcp_ethss_update_link_state(gbe_dev, slave, ndev);
+
+ gbe_register_cpts(gbe_dev);
+
return 0;
fail:
@@ -2473,16 +2868,36 @@ static int gbe_close(void *intf_priv, struct net_device *ndev)
{
struct gbe_intf *gbe_intf = intf_priv;
struct netcp_intf *netcp = netdev_priv(ndev);
+ struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
+
+ gbe_unregister_cpts(gbe_dev);
gbe_slave_stop(gbe_intf);
- netcp_unregister_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook,
- gbe_intf);
+
+ netcp_unregister_rxhook(netcp, GBE_RXHOOK_ORDER, gbe_rxhook, gbe_intf);
+ netcp_unregister_txhook(netcp, GBE_TXHOOK_ORDER, gbe_txhook, gbe_intf);
gbe_intf->slave->open = false;
atomic_set(&gbe_intf->slave->link_state, NETCP_LINK_STATE_INVALID);
return 0;
}
+#if IS_ENABLED(CONFIG_TI_CPTS)
+static void init_slave_ts_ctl(struct gbe_slave *slave)
+{
+ slave->ts_ctl.uni = 1;
+ slave->ts_ctl.dst_port_map =
+ (TS_CTL_DST_PORT >> TS_CTL_DST_PORT_SHIFT) & 0x3;
+ slave->ts_ctl.maddr_map =
+ (TS_CTL_MADDR_ALL >> TS_CTL_MADDR_SHIFT) & 0x1f;
+}
+
+#else
+static void init_slave_ts_ctl(struct gbe_slave *slave)
+{
+}
+#endif /* CONFIG_TI_CPTS */
+
static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
struct device_node *node)
{
@@ -2597,6 +3012,8 @@ static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
}
atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID);
+
+ init_slave_ts_ctl(slave);
return 0;
}
@@ -2787,6 +3204,7 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev,
XGBE10_HW_STATS_OFFSET + (GBE_HW_STATS_REG_MAP_SZ * i);
gbe_dev->ale_reg = gbe_dev->switch_regs + XGBE10_ALE_OFFSET;
+ gbe_dev->cpts_reg = gbe_dev->switch_regs + XGBE10_CPTS_OFFSET;
gbe_dev->ale_ports = gbe_dev->max_num_ports;
gbe_dev->host_port = XGBE10_HOST_PORT_NUM;
gbe_dev->ale_entries = XGBE10_NUM_ALE_ENTRIES;
@@ -2909,6 +3327,7 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev,
(GBE_HW_STATS_REG_MAP_SZ * (i & 0x1));
}
+ gbe_dev->cpts_reg = gbe_dev->switch_regs + GBE13_CPTS_OFFSET;
gbe_dev->ale_reg = gbe_dev->switch_regs + GBE13_ALE_OFFSET;
gbe_dev->ale_ports = gbe_dev->max_num_ports;
gbe_dev->host_port = GBE13_HOST_PORT_NUM;
@@ -2998,6 +3417,7 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev,
gbe_dev->hw_stats_regs[i] = gbe_dev->switch_regs +
GBENU_HW_STATS_OFFSET + (GBENU_HW_STATS_REG_MAP_SZ * i);
+ gbe_dev->cpts_reg = gbe_dev->switch_regs + GBENU_CPTS_OFFSET;
gbe_dev->ale_reg = gbe_dev->switch_regs + GBENU_ALE_OFFSET;
gbe_dev->ale_ports = gbe_dev->max_num_ports;
gbe_dev->host_port = GBENU_HOST_PORT_NUM;
@@ -3179,6 +3599,12 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n");
}
+ gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg, node);
+ if (IS_ENABLED(CONFIG_TI_CPTS) && IS_ERR(gbe_dev->cpts)) {
+ ret = PTR_ERR(gbe_dev->cpts);
+ goto free_sec_ports;
+ }
+
/* initialize host port */
gbe_init_host_port(gbe_dev);
@@ -3267,6 +3693,7 @@ static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv)
struct gbe_priv *gbe_dev = inst_priv;
del_timer_sync(&gbe_dev->timer);
+ cpts_release(gbe_dev->cpts);
cpsw_ale_stop(gbe_dev->ale);
cpsw_ale_destroy(gbe_dev->ale);
netcp_txpipe_close(&gbe_dev->tx_pipe);
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 6c7ec1ddd475..c8d53d8c83ee 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -772,7 +772,6 @@ static const struct net_device_ops tlan_netdev_ops = {
.ndo_get_stats = tlan_get_stats,
.ndo_set_rx_mode = tlan_set_multicast_list,
.ndo_do_ioctl = tlan_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig
index f59a6c265331..bdfeaf3d4fce 100644
--- a/drivers/net/ethernet/tile/Kconfig
+++ b/drivers/net/ethernet/tile/Kconfig
@@ -9,7 +9,7 @@ config TILE_NET
select CRC32
select TILE_GXIO_MPIPE if TILEGX
select HIGH_RES_TIMERS if TILEGX
- select PTP_1588_CLOCK if TILEGX
+ imply PTP_1588_CLOCK if TILEGX
---help---
This is a standard Linux network device driver for the
on-chip Tilera Gigabit Ethernet and XAUI interfaces.
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 11213a38c795..0aaf975bb347 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -59,6 +59,9 @@
/* Maximum number of packets to handle per "poll". */
#define TILE_NET_WEIGHT 64
+/* Maximum Jumbo Packet MTU */
+#define TILE_JUMBO_MAX_MTU 9000
+
/* Number of entries in each iqueue. */
#define IQUEUE_ENTRIES 512
@@ -2101,17 +2104,6 @@ static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EOPNOTSUPP;
}
-/* Change the MTU. */
-static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < 68)
- return -EINVAL;
- if (new_mtu > ((jumbo_num != 0) ? 9000 : 1500))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
/* Change the Ethernet address of the NIC.
*
* The hypervisor driver does not support changing MAC address. However,
@@ -2154,7 +2146,6 @@ static const struct net_device_ops tile_net_ops = {
.ndo_start_xmit = tile_net_tx,
.ndo_select_queue = tile_net_select_queue,
.ndo_do_ioctl = tile_net_ioctl,
- .ndo_change_mtu = tile_net_change_mtu,
.ndo_tx_timeout = tile_net_tx_timeout,
.ndo_set_mac_address = tile_net_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2174,7 +2165,11 @@ static void tile_net_setup(struct net_device *dev)
ether_setup(dev);
dev->netdev_ops = &tile_net_ops;
dev->watchdog_timeo = TILE_NET_TIMEOUT;
- dev->mtu = 1500;
+
+ /* MTU range: 68 - 1500 or 9000 */
+ dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = jumbo_num ? TILE_JUMBO_MAX_MTU : ETH_DATA_LEN;
features |= NETIF_F_HW_CSUM;
features |= NETIF_F_SG;
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 4ef605a90247..0a3b7dafa3ba 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -87,7 +87,7 @@
/* This should be 1500 if "jumbo" is not set in LIPP. */
/* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */
/* ISSUE: This has not been thoroughly tested (except at 1500). */
-#define TILE_NET_MTU 1500
+#define TILE_NET_MTU ETH_DATA_LEN
/* HACK: Define this to verify incoming packets. */
/* #define TILE_NET_VERIFY_INGRESS */
@@ -2095,26 +2095,6 @@ static struct rtnl_link_stats64 *tile_net_get_stats64(struct net_device *dev,
}
-/*
- * Change the "mtu".
- *
- * The "change_mtu" method is usually not needed.
- * If you need it, it must be like this.
- */
-static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
-{
- PDEBUG("tile_net_change_mtu()\n");
-
- /* Check ranges. */
- if ((new_mtu < 68) || (new_mtu > 1500))
- return -EINVAL;
-
- /* Accept the value. */
- dev->mtu = new_mtu;
-
- return 0;
-}
-
/*
* Change the Ethernet Address of the NIC.
@@ -2229,7 +2209,6 @@ static const struct net_device_ops tile_net_ops = {
.ndo_start_xmit = tile_net_tx,
.ndo_do_ioctl = tile_net_ioctl,
.ndo_get_stats64 = tile_net_get_stats64,
- .ndo_change_mtu = tile_net_change_mtu,
.ndo_tx_timeout = tile_net_tx_timeout,
.ndo_set_mac_address = tile_net_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2252,7 +2231,11 @@ static void tile_net_setup(struct net_device *dev)
dev->netdev_ops = &tile_net_ops;
dev->watchdog_timeo = TILE_NET_TIMEOUT;
dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
+
+ /* MTU range: 68 - 1500 */
dev->mtu = TILE_NET_MTU;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = TILE_NET_MTU;
features |= NETIF_F_HW_CSUM;
features |= NETIF_F_SG;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 272f2b1cb7ad..345316c749e7 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1114,24 +1114,6 @@ static int gelic_net_poll(struct napi_struct *napi, int budget)
}
return packets_done;
}
-/**
- * gelic_net_change_mtu - changes the MTU of an interface
- * @netdev: interface device structure
- * @new_mtu: new MTU value
- *
- * returns 0 on success, <0 on failure
- */
-int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
-{
- /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
- * and mtu is outbound only anyway */
- if ((new_mtu < GELIC_NET_MIN_MTU) ||
- (new_mtu > GELIC_NET_MAX_MTU)) {
- return -EINVAL;
- }
- netdev->mtu = new_mtu;
- return 0;
-}
/**
* gelic_card_interrupt - event handler for gelic_net
@@ -1446,7 +1428,6 @@ static const struct net_device_ops gelic_netdevice_ops = {
.ndo_stop = gelic_net_stop,
.ndo_start_xmit = gelic_net_xmit,
.ndo_set_rx_mode = gelic_net_set_multi,
- .ndo_change_mtu = gelic_net_change_mtu,
.ndo_tx_timeout = gelic_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -1513,6 +1494,10 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
netdev->features |= NETIF_F_VLAN_CHALLENGED;
}
+ /* MTU range: 64 - 1518 */
+ netdev->min_mtu = GELIC_NET_MIN_MTU;
+ netdev->max_mtu = GELIC_NET_MAX_MTU;
+
status = register_netdev(netdev);
if (status) {
dev_err(ctodev(card), "%s:Couldn't register %s %d\n",
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
index 8505196be9f5..003d0452d9cb 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
@@ -373,7 +373,6 @@ int gelic_net_stop(struct net_device *netdev);
int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
void gelic_net_set_multi(struct net_device *netdev);
void gelic_net_tx_timeout(struct net_device *netdev);
-int gelic_net_change_mtu(struct net_device *netdev, int new_mtu);
int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card);
/* shared ethtool ops */
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 928c1dca2673..eed18f88bdff 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -2558,7 +2558,6 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
.ndo_stop = gelic_wl_stop,
.ndo_start_xmit = gelic_net_xmit,
.ndo_set_rx_mode = gelic_net_set_multi,
- .ndo_change_mtu = gelic_net_change_mtu,
.ndo_tx_timeout = gelic_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 36a6e8b54d94..cb341dfe65ad 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -1279,25 +1279,6 @@ static int spider_net_poll(struct napi_struct *napi, int budget)
}
/**
- * spider_net_change_mtu - changes the MTU of an interface
- * @netdev: interface device structure
- * @new_mtu: new MTU value
- *
- * returns 0 on success, <0 on failure
- */
-static int
-spider_net_change_mtu(struct net_device *netdev, int new_mtu)
-{
- /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
- * and mtu is outbound only anyway */
- if ( (new_mtu < SPIDER_NET_MIN_MTU ) ||
- (new_mtu > SPIDER_NET_MAX_MTU) )
- return -EINVAL;
- netdev->mtu = new_mtu;
- return 0;
-}
-
-/**
* spider_net_set_mac - sets the MAC of an interface
* @netdev: interface device structure
* @ptr: pointer to new MAC address
@@ -2229,7 +2210,6 @@ static const struct net_device_ops spider_net_ops = {
.ndo_start_xmit = spider_net_xmit,
.ndo_set_rx_mode = spider_net_set_multi,
.ndo_set_mac_address = spider_net_set_mac,
- .ndo_change_mtu = spider_net_change_mtu,
.ndo_do_ioctl = spider_net_do_ioctl,
.ndo_tx_timeout = spider_net_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -2299,6 +2279,10 @@ spider_net_setup_netdev(struct spider_net_card *card)
/* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
* NETIF_F_HW_VLAN_CTAG_FILTER */
+ /* MTU range: 64 - 2294 */
+ netdev->min_mtu = SPIDER_NET_MIN_MTU;
+ netdev->max_mtu = SPIDER_NET_MAX_MTU;
+
netdev->irq = card->pdev->irq;
card->num_rx_ints = 0;
card->ignore_rx_ramfull = 0;
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 5b01b3fa9fec..3be61ed28741 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -747,7 +747,6 @@ static const struct net_device_ops tc35815_netdev_ops = {
.ndo_tx_timeout = tc35815_tx_timeout,
.ndo_do_ioctl = tc35815_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tc35815_poll_controller,
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 8fd131207ee1..f153ad729ce5 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1548,7 +1548,6 @@ static const struct net_device_ops tsi108_netdev_ops = {
.ndo_do_ioctl = tsi108_do_ioctl,
.ndo_set_mac_address = tsi108_set_mac,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 9d14731cdcb1..ba5c54249055 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -890,7 +890,6 @@ static const struct net_device_ops rhine_netdev_ops = {
.ndo_start_xmit = rhine_start_tx,
.ndo_get_stats64 = rhine_get_stats64,
.ndo_set_rx_mode = rhine_set_rx_mode,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 908e72e18ef7..4716e60e2ccb 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2284,13 +2284,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
struct velocity_info *vptr = netdev_priv(dev);
int ret = 0;
- if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
- VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n",
- vptr->netdev->name);
- ret = -EINVAL;
- goto out_0;
- }
-
if (!netif_running(dev)) {
dev->mtu = new_mtu;
goto out_0;
@@ -2864,6 +2857,10 @@ static int velocity_probe(struct device *dev, int irq,
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_IP_CSUM;
+ /* MTU range: 64 - 9000 */
+ netdev->min_mtu = VELOCITY_MIN_MTU;
+ netdev->max_mtu = VELOCITY_MAX_MTU;
+
ret = register_netdev(netdev);
if (ret < 0)
goto err_iounmap;
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index d2349a1bc6ba..e1296ef2cf66 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -1045,7 +1045,6 @@ static const struct net_device_ops w5100_netdev_ops = {
.ndo_set_rx_mode = w5100_set_rx_mode,
.ndo_set_mac_address = w5100_set_macaddr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int w5100_mmio_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index ca31a57dbc86..724fabd38a23 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -536,7 +536,6 @@ static const struct net_device_ops w5300_netdev_ops = {
.ndo_set_rx_mode = w5300_set_rx_mode,
.ndo_set_mac_address = w5300_set_macaddr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static int w5300_hw_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index a9bd665fd122..d73da8afe08e 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -37,6 +37,7 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
+#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/skbuff.h>
@@ -332,7 +333,7 @@ static void temac_do_set_mac_address(struct net_device *ndev)
mutex_unlock(&lp->indirect_mutex);
}
-static int temac_init_mac_address(struct net_device *ndev, void *address)
+static int temac_init_mac_address(struct net_device *ndev, const void *address)
{
memcpy(ndev->dev_addr, address, ETH_ALEN);
if (!is_valid_ether_addr(ndev->dev_addr))
@@ -967,13 +968,8 @@ static const struct attribute_group temac_attr_group = {
};
/* ethtool support */
-static int temac_nway_reset(struct net_device *ndev)
-{
- return phy_start_aneg(ndev->phydev);
-}
-
static const struct ethtool_ops temac_ethtool_ops = {
- .nway_reset = temac_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_ts_info = ethtool_op_get_ts_info,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
@@ -987,7 +983,7 @@ static int temac_of_probe(struct platform_device *op)
struct net_device *ndev;
const void *addr;
__be32 *p;
- int size, rc = 0;
+ int rc = 0;
/* Init network device structure */
ndev = alloc_etherdev(sizeof(*lp));
@@ -1079,13 +1075,13 @@ static int temac_of_probe(struct platform_device *op)
/* Retrieve the MAC address */
- addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
- if ((!addr) || (size != 6)) {
+ addr = of_get_mac_address(op->dev.of_node);
+ if (!addr) {
dev_err(&op->dev, "could not find MAC address\n");
rc = -ENODEV;
goto err_iounmap_2;
}
- temac_init_mac_address(ndev, (void *)addr);
+ temac_init_mac_address(ndev, addr);
rc = temac_mdio_setup(lp, op->dev.of_node);
if (rc)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index c688d68c39aa..b96e96919e31 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of_mdio.h>
+#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
@@ -292,7 +293,8 @@ out:
* This function is called to initialize the MAC address of the Axi Ethernet
* core. It writes to the UAW0 and UAW1 registers of the core.
*/
-static void axienet_set_mac_address(struct net_device *ndev, void *address)
+static void axienet_set_mac_address(struct net_device *ndev,
+ const void *address)
{
struct axienet_local *lp = netdev_priv(ndev);
@@ -1034,9 +1036,6 @@ static int axienet_change_mtu(struct net_device *ndev, int new_mtu)
XAE_TRL_SIZE) > lp->rxmem)
return -EINVAL;
- if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64))
- return -EINVAL;
-
ndev->mtu = new_mtu;
return 0;
@@ -1459,7 +1458,7 @@ static int axienet_probe(struct platform_device *pdev)
struct device_node *np;
struct axienet_local *lp;
struct net_device *ndev;
- u8 mac_addr[6];
+ const void *mac_addr;
struct resource *ethres, dmares;
u32 value;
@@ -1475,6 +1474,10 @@ static int axienet_probe(struct platform_device *pdev)
ndev->netdev_ops = &axienet_netdev_ops;
ndev->ethtool_ops = &axienet_ethtool_ops;
+ /* MTU range: 64 - 9000 */
+ ndev->min_mtu = 64;
+ ndev->max_mtu = XAE_JUMBO_MTU;
+
lp = netdev_priv(ndev);
lp->ndev = ndev;
lp->dev = &pdev->dev;
@@ -1566,13 +1569,12 @@ static int axienet_probe(struct platform_device *pdev)
}
/* Retrieve the MAC address */
- ret = of_property_read_u8_array(pdev->dev.of_node,
- "local-mac-address", mac_addr, 6);
- if (ret) {
+ mac_addr = of_get_mac_address(pdev->dev.of_node);
+ if (!mac_addr) {
dev_err(&pdev->dev, "could not find MAC address\n");
goto free_netdev;
}
- axienet_set_mac_address(ndev, (void *)mac_addr);
+ axienet_set_mac_address(ndev, mac_addr);
lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index ddced28e8247..3b08ec766076 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -466,7 +466,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_config = do_config,
.ndo_do_ioctl = do_ioctl,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index fa32391720fe..aee55c03def0 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1001,11 +1001,6 @@ static void ixp4xx_get_drvinfo(struct net_device *dev,
strlcpy(info->bus_info, "internal", sizeof(info->bus_info));
}
-static int ixp4xx_nway_reset(struct net_device *dev)
-{
- return phy_start_aneg(dev->phydev);
-}
-
int ixp46x_phc_index = -1;
EXPORT_SYMBOL_GPL(ixp46x_phc_index);
@@ -1037,7 +1032,7 @@ static int ixp4xx_get_ts_info(struct net_device *dev,
static const struct ethtool_ops ixp4xx_ethtool_ops = {
.get_drvinfo = ixp4xx_get_drvinfo,
- .nway_reset = ixp4xx_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_ts_info = ixp4xx_get_ts_info,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
@@ -1378,7 +1373,6 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
.ndo_start_xmit = eth_xmit,
.ndo_set_rx_mode = eth_set_mcast_list,
.ndo_do_ioctl = eth_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index 51acc6d86e91..3a639180e4a0 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -166,7 +166,6 @@ static const struct net_device_ops skfp_netdev_ops = {
.ndo_stop = skfp_close,
.ndo_start_xmit = skfp_send_pkt,
.ndo_get_stats = skfp_ctl_get_stats,
- .ndo_change_mtu = fddi_change_mtu,
.ndo_set_rx_mode = skfp_ctl_set_multicast_list,
.ndo_set_mac_address = skfp_ctl_set_mac_address,
.ndo_do_ioctl = skfp_ioctl,
diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 523e3d7cf7aa..bc47b354c104 100644
--- a/drivers/net/fjes/Makefile
+++ b/drivers/net/fjes/Makefile
@@ -27,4 +27,4 @@
obj-$(CONFIG_FUJITSU_ES) += fjes.o
-fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o
+fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o fjes_debugfs.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index a592fe21c698..0372be3ad8e3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -66,6 +66,10 @@ struct fjes_adapter {
bool interrupt_watch_enable;
struct fjes_hw hw;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dbg_adapter;
+#endif
};
extern char fjes_driver_name[];
@@ -74,4 +78,16 @@ extern const u32 fjes_support_mtu[];
void fjes_set_ethtool_ops(struct net_device *);
+#ifdef CONFIG_DEBUG_FS
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter);
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter);
+void fjes_dbg_init(void);
+void fjes_dbg_exit(void);
+#else
+static inline void fjes_dbg_adapter_init(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_adapter_exit(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_init(void) {}
+static inline void fjes_dbg_exit(void) {}
+#endif /* CONFIG_DEBUG_FS */
+
#endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
new file mode 100644
index 000000000000..30052ebd52bf
--- /dev/null
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -0,0 +1,117 @@
+/*
+ * FUJITSU Extended Socket Network Device driver
+ * Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * 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".
+ *
+ */
+
+/* debugfs support for fjes driver */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+
+#include "fjes.h"
+
+static struct dentry *fjes_debug_root;
+
+static const char * const ep_status_string[] = {
+ "unshared",
+ "shared",
+ "waiting",
+ "complete",
+};
+
+static int fjes_dbg_status_show(struct seq_file *m, void *v)
+{
+ struct fjes_adapter *adapter = m->private;
+ struct fjes_hw *hw = &adapter->hw;
+ int max_epid = hw->max_epid;
+ int my_epid = hw->my_epid;
+ int epidx;
+
+ seq_puts(m, "EPID\tSTATUS SAME_ZONE CONNECTED\n");
+ for (epidx = 0; epidx < max_epid; epidx++) {
+ if (epidx == my_epid) {
+ seq_printf(m, "ep%d\t%-16c %-16c %-16c\n",
+ epidx, '-', '-', '-');
+ } else {
+ seq_printf(m, "ep%d\t%-16s %-16c %-16c\n",
+ epidx,
+ ep_status_string[fjes_hw_get_partner_ep_status(hw, epidx)],
+ fjes_hw_epid_is_same_zone(hw, epidx) ? 'Y' : 'N',
+ fjes_hw_epid_is_shared(hw->hw_info.share, epidx) ? 'Y' : 'N');
+ }
+ }
+
+ return 0;
+}
+
+static int fjes_dbg_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, fjes_dbg_status_show, inode->i_private);
+}
+
+static const struct file_operations fjes_dbg_status_fops = {
+ .owner = THIS_MODULE,
+ .open = fjes_dbg_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter)
+{
+ const char *name = dev_name(&adapter->plat_dev->dev);
+ struct dentry *pfile;
+
+ adapter->dbg_adapter = debugfs_create_dir(name, fjes_debug_root);
+ if (!adapter->dbg_adapter) {
+ dev_err(&adapter->plat_dev->dev,
+ "debugfs entry for %s failed\n", name);
+ return;
+ }
+
+ pfile = debugfs_create_file("status", 0444, adapter->dbg_adapter,
+ adapter, &fjes_dbg_status_fops);
+ if (!pfile)
+ dev_err(&adapter->plat_dev->dev,
+ "debugfs status for %s failed\n", name);
+}
+
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
+{
+ debugfs_remove_recursive(adapter->dbg_adapter);
+ adapter->dbg_adapter = NULL;
+}
+
+void fjes_dbg_init(void)
+{
+ fjes_debug_root = debugfs_create_dir(fjes_driver_name, NULL);
+ if (!fjes_debug_root)
+ pr_info("init of debugfs failed\n");
+}
+
+void fjes_dbg_exit(void)
+{
+ debugfs_remove_recursive(fjes_debug_root);
+ fjes_debug_root = NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 9c218e140c41..6575f880f1be 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = {
FJES_STAT("tx_dropped", stats64.tx_dropped),
};
+#define FJES_EP_STATS_LEN 14
+#define FJES_STATS_LEN \
+ (ARRAY_SIZE(fjes_gstrings_stats) + \
+ ((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \
+ FJES_EP_STATS_LEN)
+
static void fjes_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
+ int epidx;
char *p;
int i;
@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device *netdev,
data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
? *(u64 *)p : *(u32 *)p;
}
+ for (epidx = 0; epidx < hw->max_epid; epidx++) {
+ if (epidx == hw->my_epid)
+ continue;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .com_regist_buf_exec;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .com_unregist_buf_exec;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .send_intr_zoneupdate;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .recv_intr_zoneupdate;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .tx_dropped_not_shared;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .tx_dropped_ver_mismatch;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .tx_dropped_buf_size_mismatch;
+ data[i++] = hw->ep_shm_info[epidx].ep_stats
+ .tx_dropped_vlanid_mismatch;
+ }
}
static void fjes_get_strings(struct net_device *netdev,
u32 stringset, u8 *data)
{
+ struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
u8 *p = data;
int i;
@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+ for (i = 0; i < hw->max_epid; i++) {
+ if (i == hw->my_epid)
+ continue;
+ sprintf(p, "ep%u_com_regist_buf_exec", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_com_unregist_buf_exec", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_send_intr_rx", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_send_intr_unshare", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_send_intr_zoneupdate", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_recv_intr_rx", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_recv_intr_unshare", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_recv_intr_stop", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_recv_intr_zoneupdate", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_tx_buffer_full", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_tx_dropped_not_shared", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_tx_dropped_ver_mismatch", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i);
+ p += ETH_GSTRING_LEN;
+ }
break;
}
}
@@ -84,7 +152,7 @@ static int fjes_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
case ETH_SS_STATS:
- return ARRAY_SIZE(fjes_gstrings_stats);
+ return FJES_STATS_LEN;
default:
return -EOPNOTSUPP;
}
@@ -121,12 +189,123 @@ static int fjes_get_settings(struct net_device *netdev,
return 0;
}
+static int fjes_get_regs_len(struct net_device *netdev)
+{
+#define FJES_REGS_LEN 37
+ return FJES_REGS_LEN * sizeof(u32);
+}
+
+static void fjes_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
+ u32 *regs_buff = p;
+
+ memset(p, 0, FJES_REGS_LEN * sizeof(u32));
+
+ regs->version = 1;
+
+ /* Information registers */
+ regs_buff[0] = rd32(XSCT_OWNER_EPID);
+ regs_buff[1] = rd32(XSCT_MAX_EP);
+
+ /* Device Control registers */
+ regs_buff[4] = rd32(XSCT_DCTL);
+
+ /* Command Control registers */
+ regs_buff[8] = rd32(XSCT_CR);
+ regs_buff[9] = rd32(XSCT_CS);
+ regs_buff[10] = rd32(XSCT_SHSTSAL);
+ regs_buff[11] = rd32(XSCT_SHSTSAH);
+
+ regs_buff[13] = rd32(XSCT_REQBL);
+ regs_buff[14] = rd32(XSCT_REQBAL);
+ regs_buff[15] = rd32(XSCT_REQBAH);
+
+ regs_buff[17] = rd32(XSCT_RESPBL);
+ regs_buff[18] = rd32(XSCT_RESPBAL);
+ regs_buff[19] = rd32(XSCT_RESPBAH);
+
+ /* Interrupt Control registers */
+ regs_buff[32] = rd32(XSCT_IS);
+ regs_buff[33] = rd32(XSCT_IMS);
+ regs_buff[34] = rd32(XSCT_IMC);
+ regs_buff[35] = rd32(XSCT_IG);
+ regs_buff[36] = rd32(XSCT_ICTL);
+}
+
+static int fjes_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+{
+ struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
+ int ret = 0;
+
+ if (dump->flag) {
+ if (hw->debug_mode)
+ return -EPERM;
+
+ hw->debug_mode = dump->flag;
+
+ /* enable debug mode */
+ mutex_lock(&hw->hw_info.lock);
+ ret = fjes_hw_start_debug(hw);
+ mutex_unlock(&hw->hw_info.lock);
+
+ if (ret)
+ hw->debug_mode = 0;
+ } else {
+ if (!hw->debug_mode)
+ return -EPERM;
+
+ /* disable debug mode */
+ mutex_lock(&hw->hw_info.lock);
+ ret = fjes_hw_stop_debug(hw);
+ mutex_unlock(&hw->hw_info.lock);
+ }
+
+ return ret;
+}
+
+static int fjes_get_dump_flag(struct net_device *netdev,
+ struct ethtool_dump *dump)
+{
+ struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
+
+ dump->len = hw->hw_info.trace_size;
+ dump->version = 1;
+ dump->flag = hw->debug_mode;
+
+ return 0;
+}
+
+static int fjes_get_dump_data(struct net_device *netdev,
+ struct ethtool_dump *dump, void *buf)
+{
+ struct fjes_adapter *adapter = netdev_priv(netdev);
+ struct fjes_hw *hw = &adapter->hw;
+ int ret = 0;
+
+ if (hw->hw_info.trace)
+ memcpy(buf, hw->hw_info.trace, hw->hw_info.trace_size);
+ else
+ ret = -EPERM;
+
+ return ret;
+}
+
static const struct ethtool_ops fjes_ethtool_ops = {
.get_settings = fjes_get_settings,
.get_drvinfo = fjes_get_drvinfo,
.get_ethtool_stats = fjes_get_ethtool_stats,
.get_strings = fjes_get_strings,
.get_sset_count = fjes_get_sset_count,
+ .get_regs = fjes_get_regs,
+ .get_regs_len = fjes_get_regs_len,
+ .set_dump = fjes_set_dump,
+ .get_dump_flag = fjes_get_dump_flag,
+ .get_dump_data = fjes_get_dump_data,
};
void fjes_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 0dbafedc0a34..9c652c04375b 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -21,6 +21,7 @@
#include "fjes_hw.h"
#include "fjes.h"
+#include "fjes_trace.h"
static void fjes_hw_update_zone_task(struct work_struct *);
static void fjes_hw_epstop_task(struct work_struct *);
@@ -342,6 +343,9 @@ int fjes_hw_init(struct fjes_hw *hw)
ret = fjes_hw_setup(hw);
+ hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
+ hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
+
return ret;
}
@@ -350,6 +354,18 @@ void fjes_hw_exit(struct fjes_hw *hw)
int ret;
if (hw->base) {
+
+ if (hw->debug_mode) {
+ /* disable debug mode */
+ mutex_lock(&hw->hw_info.lock);
+ fjes_hw_stop_debug(hw);
+ mutex_unlock(&hw->hw_info.lock);
+ }
+ vfree(hw->hw_info.trace);
+ hw->hw_info.trace = NULL;
+ hw->hw_info.trace_size = 0;
+ hw->debug_mode = 0;
+
ret = fjes_hw_reset(hw);
if (ret)
pr_err("%s: reset error", __func__);
@@ -371,7 +387,7 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
union REG_CR cr;
union REG_CS cs;
- int timeout;
+ int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
cr.reg = 0;
cr.bits.req_start = 1;
@@ -408,6 +424,8 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
}
}
+ trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret);
+
return ret;
}
@@ -427,11 +445,13 @@ int fjes_hw_request_info(struct fjes_hw *hw)
res_buf->info.code = 0;
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+ trace_fjes_hw_request_info(hw, res_buf);
result = 0;
if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
res_buf->info.length) {
+ trace_fjes_hw_request_info_err("Invalid res_buf");
result = -ENOMSG;
} else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->info.code) {
@@ -448,6 +468,7 @@ int fjes_hw_request_info(struct fjes_hw *hw)
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+ trace_fjes_hw_request_info_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -512,6 +533,8 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
res_buf->share_buffer.length = 0;
res_buf->share_buffer.code = 0;
+ trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
+
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -532,16 +555,20 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
result = 0;
+ trace_fjes_hw_register_buff_addr(res_buf, timeout);
+
if (res_buf->share_buffer.length !=
- FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+ FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
+ trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
result = -ENOMSG;
- else if (ret == FJES_CMD_STATUS_NORMAL) {
+ } else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->share_buffer.code) {
case FJES_CMD_REQ_RES_CODE_NORMAL:
result = 0;
set_bit(dest_epid, &hw->hw_info.buffer_share_bit);
break;
case FJES_CMD_REQ_RES_CODE_BUSY:
+ trace_fjes_hw_register_buff_addr_err("Busy Timeout");
result = -EBUSY;
break;
default:
@@ -554,6 +581,7 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+ trace_fjes_hw_register_buff_addr_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -595,6 +623,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
res_buf->unshare_buffer.length = 0;
res_buf->unshare_buffer.code = 0;
+ trace_fjes_hw_unregister_buff_addr_req(req_buf);
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -616,8 +645,11 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
result = 0;
+ trace_fjes_hw_unregister_buff_addr(res_buf, timeout);
+
if (res_buf->unshare_buffer.length !=
FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) {
+ trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf");
result = -ENOMSG;
} else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->unshare_buffer.code) {
@@ -626,6 +658,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
clear_bit(dest_epid, &hw->hw_info.buffer_share_bit);
break;
case FJES_CMD_REQ_RES_CODE_BUSY:
+ trace_fjes_hw_unregister_buff_addr_err("Busy Timeout");
result = -EBUSY;
break;
default:
@@ -638,6 +671,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+ trace_fjes_hw_unregister_buff_addr_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -752,6 +786,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
case EP_PARTNER_SHARED:
fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_TXRX_STOP_REQ);
+ hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
break;
default:
break;
@@ -1062,6 +1097,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
break;
}
mutex_unlock(&hw->hw_info.lock);
+
+ hw->ep_shm_info[epidx].ep_stats
+ .com_regist_buf_exec += 1;
}
if (test_bit(epidx, &unshare_bit)) {
@@ -1085,6 +1123,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
mutex_unlock(&hw->hw_info.lock);
+ hw->ep_shm_info[epidx].ep_stats
+ .com_unregist_buf_exec += 1;
+
if (ret == 0) {
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(
@@ -1099,6 +1140,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_TXRX_STOP_REQ);
+ hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
+
set_bit(epidx, &hw->txrx_stop_req_bit);
spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.
@@ -1147,3 +1190,125 @@ static void fjes_hw_epstop_task(struct work_struct *work)
}
}
}
+
+int fjes_hw_start_debug(struct fjes_hw *hw)
+{
+ union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+ union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+ enum fjes_dev_command_response_e ret;
+ int page_count;
+ int result = 0;
+ void *addr;
+ int i;
+
+ if (!hw->hw_info.trace)
+ return -EPERM;
+ memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
+
+ memset(req_buf, 0, hw->hw_info.req_buf_size);
+ memset(res_buf, 0, hw->hw_info.res_buf_size);
+
+ req_buf->start_trace.length =
+ FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size);
+ req_buf->start_trace.mode = hw->debug_mode;
+ req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
+ page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE;
+ for (i = 0; i < page_count; i++) {
+ addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE;
+ req_buf->start_trace.buffer[i] =
+ (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+ offset_in_page(addr));
+ }
+
+ res_buf->start_trace.length = 0;
+ res_buf->start_trace.code = 0;
+
+ trace_fjes_hw_start_debug_req(req_buf);
+ ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG);
+ trace_fjes_hw_start_debug(res_buf);
+
+ if (res_buf->start_trace.length !=
+ FJES_DEV_COMMAND_START_DBG_RES_LEN) {
+ result = -ENOMSG;
+ trace_fjes_hw_start_debug_err("Invalid res_buf");
+ } else if (ret == FJES_CMD_STATUS_NORMAL) {
+ switch (res_buf->start_trace.code) {
+ case FJES_CMD_REQ_RES_CODE_NORMAL:
+ result = 0;
+ break;
+ default:
+ result = -EPERM;
+ break;
+ }
+ } else {
+ switch (ret) {
+ case FJES_CMD_STATUS_UNKNOWN:
+ result = -EPERM;
+ break;
+ case FJES_CMD_STATUS_TIMEOUT:
+ trace_fjes_hw_start_debug_err("Busy Timeout");
+ result = -EBUSY;
+ break;
+ case FJES_CMD_STATUS_ERROR_PARAM:
+ case FJES_CMD_STATUS_ERROR_STATUS:
+ default:
+ result = -EPERM;
+ break;
+ }
+ }
+
+ return result;
+}
+
+int fjes_hw_stop_debug(struct fjes_hw *hw)
+{
+ union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+ union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+ enum fjes_dev_command_response_e ret;
+ int result = 0;
+
+ if (!hw->hw_info.trace)
+ return -EPERM;
+
+ memset(req_buf, 0, hw->hw_info.req_buf_size);
+ memset(res_buf, 0, hw->hw_info.res_buf_size);
+ req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN;
+
+ res_buf->stop_trace.length = 0;
+ res_buf->stop_trace.code = 0;
+
+ ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG);
+ trace_fjes_hw_stop_debug(res_buf);
+
+ if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) {
+ trace_fjes_hw_stop_debug_err("Invalid res_buf");
+ result = -ENOMSG;
+ } else if (ret == FJES_CMD_STATUS_NORMAL) {
+ switch (res_buf->stop_trace.code) {
+ case FJES_CMD_REQ_RES_CODE_NORMAL:
+ result = 0;
+ hw->debug_mode = 0;
+ break;
+ default:
+ result = -EPERM;
+ break;
+ }
+ } else {
+ switch (ret) {
+ case FJES_CMD_STATUS_UNKNOWN:
+ result = -EPERM;
+ break;
+ case FJES_CMD_STATUS_TIMEOUT:
+ result = -EBUSY;
+ trace_fjes_hw_stop_debug_err("Busy Timeout");
+ break;
+ case FJES_CMD_STATUS_ERROR_PARAM:
+ case FJES_CMD_STATUS_ERROR_STATUS:
+ default:
+ result = -EPERM;
+ break;
+ }
+ }
+
+ return result;
+}
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 1445ac99d6e3..3a6da0996a0e 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -33,6 +33,9 @@ struct fjes_hw;
#define EP_BUFFER_SUPPORT_VLAN_MAX 4
#define EP_BUFFER_INFO_SIZE 4096
+#define FJES_DEBUG_PAGE_SIZE 4096
+#define FJES_DEBUG_BUFFER_SIZE (16 * FJES_DEBUG_PAGE_SIZE)
+
#define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_TIMEOUT ((5 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_BUFF_TIMEOUT (60 * 3) /* sec */
@@ -94,6 +97,12 @@ struct fjes_hw;
#define FJES_DEV_RES_BUF_SIZE(maxep) \
FJES_DEV_COMMAND_INFO_RES_LEN(maxep)
+#define FJES_DEV_COMMAND_START_DBG_REQ_LEN(byte) \
+ (16 + (8 * (byte) / FJES_DEBUG_PAGE_SIZE))
+#define FJES_DEV_COMMAND_START_DBG_RES_LEN (8)
+#define FJES_DEV_COMMAND_STOP_DBG_REQ_LEN (4)
+#define FJES_DEV_COMMAND_STOP_DBG_RES_LEN (8)
+
/* Frame & MTU */
struct esmem_frame {
__le32 frame_size;
@@ -173,6 +182,8 @@ enum fjes_dev_command_request_type {
FJES_CMD_REQ_INFO = 0x0001,
FJES_CMD_REQ_SHARE_BUFFER = 0x0002,
FJES_CMD_REQ_UNSHARE_BUFFER = 0x0004,
+ FJES_CMD_REQ_START_DEBUG = 0x0100,
+ FJES_CMD_REQ_STOP_DEBUG = 0x0200,
};
/* parameter for command control */
@@ -228,6 +239,24 @@ union ep_buffer_info {
};
+/* statistics of EP */
+struct fjes_drv_ep_stats {
+ u64 com_regist_buf_exec;
+ u64 com_unregist_buf_exec;
+ u64 send_intr_rx;
+ u64 send_intr_unshare;
+ u64 send_intr_zoneupdate;
+ u64 recv_intr_rx;
+ u64 recv_intr_unshare;
+ u64 recv_intr_stop;
+ u64 recv_intr_zoneupdate;
+ u64 tx_buffer_full;
+ u64 tx_dropped_not_shared;
+ u64 tx_dropped_ver_mismatch;
+ u64 tx_dropped_buf_size_mismatch;
+ u64 tx_dropped_vlanid_mismatch;
+};
+
/* buffer pair for Extended Partition */
struct ep_share_mem_info {
struct epbuf_handler {
@@ -238,6 +267,7 @@ struct ep_share_mem_info {
} tx, rx;
struct rtnl_link_stats64 net_stats;
+ struct fjes_drv_ep_stats ep_stats;
u16 tx_status_work;
@@ -302,6 +332,8 @@ struct fjes_hw {
struct fjes_hw_info hw_info;
spinlock_t rx_status_lock; /* spinlock for rx_status */
+
+ u32 debug_mode;
};
int fjes_hw_init(struct fjes_hw *);
@@ -334,4 +366,6 @@ void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
+int fjes_hw_start_debug(struct fjes_hw *);
+int fjes_hw_stop_debug(struct fjes_hw *);
#endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index e46b1ebbbff4..b77e4ecf3cf2 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -27,9 +27,10 @@
#include <linux/interrupt.h>
#include "fjes.h"
+#include "fjes_trace.h"
#define MAJ 1
-#define MIN 1
+#define MIN 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
#define DRV_NAME "fjes"
char fjes_driver_name[] = DRV_NAME;
@@ -366,6 +367,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
FJES_ZONING_STATUS_ENABLE)) {
fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_INFO_UPDATE);
+ hw->ep_shm_info[epidx].ep_stats
+ .send_intr_zoneupdate += 1;
}
}
@@ -397,6 +400,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
adapter->force_reset = true;
return result;
}
+
+ hw->ep_shm_info[epidx].ep_stats
+ .com_regist_buf_exec += 1;
}
}
@@ -422,6 +428,8 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
result = fjes_hw_unregister_buff_addr(hw, epidx);
mutex_unlock(&hw->hw_info.lock);
+ hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1;
+
if (result)
reset_flag = true;
@@ -567,6 +575,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
FJES_RX_POLL_WORK)) {
fjes_hw_raise_interrupt(hw, epid,
REG_ICTL_MASK_RX_DATA);
+ hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1;
}
}
@@ -663,6 +672,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
if (pstatus != EP_PARTNER_SHARED) {
+ if (!is_multi)
+ hw->ep_shm_info[dest_epid].ep_stats
+ .tx_dropped_not_shared += 1;
ret = NETDEV_TX_OK;
} else if (!fjes_hw_check_epbuf_version(
&adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
@@ -670,6 +682,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
adapter->stats64.tx_carrier_errors += 1;
hw->ep_shm_info[dest_epid].net_stats
.tx_carrier_errors += 1;
+ hw->ep_shm_info[dest_epid].ep_stats
+ .tx_dropped_ver_mismatch += 1;
ret = NETDEV_TX_OK;
} else if (!fjes_hw_check_mtu(
@@ -679,12 +693,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
adapter->stats64.tx_errors += 1;
hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1;
+ hw->ep_shm_info[dest_epid].ep_stats
+ .tx_dropped_buf_size_mismatch += 1;
ret = NETDEV_TX_OK;
} else if (vlan &&
!fjes_hw_check_vlan_id(
&adapter->hw.ep_shm_info[dest_epid].rx,
vlan_id)) {
+ hw->ep_shm_info[dest_epid].ep_stats
+ .tx_dropped_vlanid_mismatch += 1;
ret = NETDEV_TX_OK;
} else {
if (len < VLAN_ETH_HLEN) {
@@ -718,6 +736,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
ret = NETDEV_TX_OK;
} else {
netif_trans_update(netdev);
+ hw->ep_shm_info[dest_epid].ep_stats
+ .tx_buffer_full += 1;
netif_tx_stop_queue(cur_queue);
if (!work_pending(&adapter->tx_stall_task))
@@ -885,6 +905,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
unsigned long flags;
status = fjes_hw_get_partner_ep_status(hw, src_epid);
+ trace_fjes_txrx_stop_req_irq_pre(hw, src_epid, status);
switch (status) {
case EP_PARTNER_UNSHARE:
case EP_PARTNER_COMPLETE:
@@ -915,6 +936,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
}
break;
}
+ trace_fjes_txrx_stop_req_irq_post(hw, src_epid);
}
static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
@@ -926,6 +948,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
status = fjes_hw_get_partner_ep_status(hw, src_epid);
+ trace_fjes_stop_req_irq_pre(hw, src_epid, status);
switch (status) {
case EP_PARTNER_WAITING:
spin_lock_irqsave(&hw->rx_status_lock, flags);
@@ -949,6 +972,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
queue_work(adapter->control_wq, &hw->epstop_task);
break;
}
+ trace_fjes_stop_req_irq_post(hw, src_epid);
}
static void fjes_update_zone_irq(struct fjes_adapter *adapter,
@@ -970,21 +994,33 @@ static irqreturn_t fjes_intr(int irq, void *data)
icr = fjes_hw_capture_interrupt_status(hw);
if (icr & REG_IS_MASK_IS_ASSERT) {
- if (icr & REG_ICTL_MASK_RX_DATA)
+ if (icr & REG_ICTL_MASK_RX_DATA) {
fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
+ hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+ .recv_intr_rx += 1;
+ }
- if (icr & REG_ICTL_MASK_DEV_STOP_REQ)
+ if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+ hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+ .recv_intr_stop += 1;
+ }
- if (icr & REG_ICTL_MASK_TXRX_STOP_REQ)
+ if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+ hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+ .recv_intr_unshare += 1;
+ }
if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
fjes_hw_set_irqmask(hw,
REG_ICTL_MASK_TXRX_STOP_DONE, true);
- if (icr & REG_ICTL_MASK_INFO_UPDATE)
+ if (icr & REG_ICTL_MASK_INFO_UPDATE) {
fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
+ hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+ .recv_intr_zoneupdate += 1;
+ }
ret = IRQ_HANDLED;
} else {
@@ -1221,6 +1257,8 @@ static int fjes_probe(struct platform_device *plat_dev)
netif_carrier_off(netdev);
+ fjes_dbg_adapter_init(adapter);
+
return 0;
err_hw_exit:
@@ -1238,6 +1276,8 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw;
+ fjes_dbg_adapter_exit(adapter);
+
cancel_delayed_work_sync(&adapter->interrupt_watch_task);
cancel_work_sync(&adapter->unshare_watch_task);
cancel_work_sync(&adapter->raise_intr_rxdata_task);
@@ -1276,6 +1316,8 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev->netdev_ops = &fjes_netdev_ops;
fjes_set_ethtool_ops(netdev);
netdev->mtu = fjes_support_mtu[3];
+ netdev->min_mtu = fjes_support_mtu[0];
+ netdev->max_mtu = fjes_support_mtu[3];
netdev->flags |= IFF_BROADCAST;
netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
}
@@ -1364,6 +1406,8 @@ static void fjes_watch_unshare_task(struct work_struct *work)
break;
}
mutex_unlock(&hw->hw_info.lock);
+ hw->ep_shm_info[epidx].ep_stats
+ .com_unregist_buf_exec += 1;
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
@@ -1406,6 +1450,9 @@ static void fjes_watch_unshare_task(struct work_struct *work)
}
mutex_unlock(&hw->hw_info.lock);
+ hw->ep_shm_info[epidx].ep_stats
+ .com_unregist_buf_exec += 1;
+
spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(
&hw->ep_shm_info[epidx].tx,
@@ -1437,9 +1484,13 @@ static int __init fjes_init_module(void)
pr_info("%s - version %s - %s\n",
fjes_driver_string, fjes_driver_version, fjes_copyright);
+ fjes_dbg_init();
+
result = platform_driver_register(&fjes_driver);
- if (result < 0)
+ if (result < 0) {
+ fjes_dbg_exit();
return result;
+ }
result = acpi_bus_register_driver(&fjes_acpi_driver);
if (result < 0)
@@ -1449,6 +1500,7 @@ static int __init fjes_init_module(void)
fail_acpi_driver:
platform_driver_unregister(&fjes_driver);
+ fjes_dbg_exit();
return result;
}
@@ -1459,6 +1511,7 @@ static void __exit fjes_exit_module(void)
{
acpi_bus_unregister_driver(&fjes_acpi_driver);
platform_driver_unregister(&fjes_driver);
+ fjes_dbg_exit();
}
module_exit(fjes_exit_module);
diff --git a/drivers/net/fjes/fjes_trace.c b/drivers/net/fjes/fjes_trace.c
new file mode 100644
index 000000000000..066fa765d5bb
--- /dev/null
+++ b/drivers/net/fjes/fjes_trace.c
@@ -0,0 +1,30 @@
+/*
+ * FUJITSU Extended Socket Network Device driver
+ * Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * 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/module.h>
+
+#ifndef __CHECKER__
+#include "fjes_hw.h"
+
+#define CREATE_TRACE_POINTS
+#include "fjes_trace.h"
+
+#endif /* __CHECKER__ */
diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h
new file mode 100644
index 000000000000..cca01a1b3d64
--- /dev/null
+++ b/drivers/net/fjes/fjes_trace.h
@@ -0,0 +1,380 @@
+/*
+ * FUJITSU Extended Socket Network Device driver
+ * Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * 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".
+ *
+ */
+
+#if !defined(FJES_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define FJES_TRACE_H_
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM fjes
+
+/* tracepoints for fjes_hw.c */
+
+TRACE_EVENT(fjes_hw_issue_request_command,
+ TP_PROTO(union REG_CR *cr, union REG_CS *cs, int timeout,
+ enum fjes_dev_command_response_e ret),
+ TP_ARGS(cr, cs, timeout, ret),
+ TP_STRUCT__entry(
+ __field(u16, cr_req)
+ __field(u8, cr_error)
+ __field(u16, cr_err_info)
+ __field(u8, cr_req_start)
+ __field(u16, cs_req)
+ __field(u8, cs_busy)
+ __field(u8, cs_complete)
+ __field(int, timeout)
+ __field(int, ret);
+ ),
+ TP_fast_assign(
+ __entry->cr_req = cr->bits.req_code;
+ __entry->cr_error = cr->bits.error;
+ __entry->cr_err_info = cr->bits.err_info;
+ __entry->cr_req_start = cr->bits.req_start;
+ __entry->cs_req = cs->bits.req_code;
+ __entry->cs_busy = cs->bits.busy;
+ __entry->cs_complete = cs->bits.complete;
+ __entry->timeout = timeout;
+ __entry->ret = ret;
+ ),
+ TP_printk("CR=[req=%04x, error=%u, err_info=%04x, req_start=%u], CS=[req=%04x, busy=%u, complete=%u], timeout=%d, ret=%d",
+ __entry->cr_req, __entry->cr_error, __entry->cr_err_info,
+ __entry->cr_req_start, __entry->cs_req, __entry->cs_busy,
+ __entry->cs_complete, __entry->timeout, __entry->ret)
+);
+
+TRACE_EVENT(fjes_hw_request_info,
+ TP_PROTO(struct fjes_hw *hw, union fjes_device_command_res *res_buf),
+ TP_ARGS(hw, res_buf),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, code)
+ __dynamic_array(u8, zone, hw->max_epid)
+ __dynamic_array(u8, status, hw->max_epid)
+ ),
+ TP_fast_assign(
+ int x;
+
+ __entry->length = res_buf->info.length;
+ __entry->code = res_buf->info.code;
+ for (x = 0; x < hw->max_epid; x++) {
+ *((u8 *)__get_dynamic_array(zone) + x) =
+ res_buf->info.info[x].zone;
+ *((u8 *)__get_dynamic_array(status) + x) =
+ res_buf->info.info[x].es_status;
+ }
+ ),
+ TP_printk("res_buf=[length=%d, code=%d, es_zones=%s, es_status=%s]",
+ __entry->length, __entry->code,
+ __print_array(__get_dynamic_array(zone),
+ __get_dynamic_array_len(zone) / sizeof(u8),
+ sizeof(u8)),
+ __print_array(__get_dynamic_array(status),
+ __get_dynamic_array_len(status) / sizeof(u8),
+ sizeof(u8)))
+);
+
+TRACE_EVENT(fjes_hw_request_info_err,
+ TP_PROTO(char *err),
+ TP_ARGS(err),
+ TP_STRUCT__entry(
+ __string(err, err)
+ ),
+ TP_fast_assign(
+ __assign_str(err, err);
+ ),
+ TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr_req,
+ TP_PROTO(union fjes_device_command_req *req_buf,
+ struct ep_share_mem_info *buf_pair),
+ TP_ARGS(req_buf, buf_pair),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, epid)
+ __field(u64, tx)
+ __field(size_t, tx_size)
+ __field(u64, rx)
+ __field(size_t, rx_size)
+ ),
+ TP_fast_assign(
+ void *tx, *rx;
+
+ tx = (void *)buf_pair->tx.buffer;
+ rx = (void *)buf_pair->rx.buffer;
+ __entry->length = req_buf->share_buffer.length;
+ __entry->epid = req_buf->share_buffer.epid;
+ __entry->tx_size = buf_pair->tx.size;
+ __entry->rx_size = buf_pair->rx.size;
+ __entry->tx = page_to_phys(vmalloc_to_page(tx)) +
+ offset_in_page(tx);
+ __entry->rx = page_to_phys(vmalloc_to_page(rx)) +
+ offset_in_page(rx);
+ ),
+ TP_printk("req_buf=[length=%d, epid=%d], TX=[phy=0x%016llx, size=%zu], RX=[phy=0x%016llx, size=%zu]",
+ __entry->length, __entry->epid, __entry->tx, __entry->tx_size,
+ __entry->rx, __entry->rx_size)
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr,
+ TP_PROTO(union fjes_device_command_res *res_buf, int timeout),
+ TP_ARGS(res_buf, timeout),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, code)
+ __field(int, timeout)
+ ),
+ TP_fast_assign(
+ __entry->length = res_buf->share_buffer.length;
+ __entry->code = res_buf->share_buffer.code;
+ __entry->timeout = timeout;
+ ),
+ TP_printk("res_buf=[length=%d, code=%d], timeout=%d",
+ __entry->length, __entry->code, __entry->timeout)
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr_err,
+ TP_PROTO(char *err),
+ TP_ARGS(err),
+ TP_STRUCT__entry(
+ __string(err, err)
+ ),
+ TP_fast_assign(
+ __assign_str(err, err);
+ ),
+ TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr_req,
+ TP_PROTO(union fjes_device_command_req *req_buf),
+ TP_ARGS(req_buf),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, epid)
+ ),
+ TP_fast_assign(
+ __entry->length = req_buf->unshare_buffer.length;
+ __entry->epid = req_buf->unshare_buffer.epid;
+ ),
+ TP_printk("req_buf=[length=%d, epid=%d]",
+ __entry->length, __entry->epid)
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr,
+ TP_PROTO(union fjes_device_command_res *res_buf, int timeout),
+ TP_ARGS(res_buf, timeout),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, code)
+ __field(int, timeout)
+ ),
+ TP_fast_assign(
+ __entry->length = res_buf->unshare_buffer.length;
+ __entry->code = res_buf->unshare_buffer.code;
+ __entry->timeout = timeout;
+ ),
+ TP_printk("res_buf=[length=%d, code=%d], timeout=%d",
+ __entry->length, __entry->code, __entry->timeout)
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr_err,
+ TP_PROTO(char *err),
+ TP_ARGS(err),
+ TP_STRUCT__entry(
+ __string(err, err)
+ ),
+ TP_fast_assign(
+ __assign_str(err, err);
+ ),
+ TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_start_debug_req,
+ TP_PROTO(union fjes_device_command_req *req_buf),
+ TP_ARGS(req_buf),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, mode)
+ __field(phys_addr_t, buffer)
+ ),
+ TP_fast_assign(
+ __entry->length = req_buf->start_trace.length;
+ __entry->mode = req_buf->start_trace.mode;
+ __entry->buffer = req_buf->start_trace.buffer[0];
+ ),
+ TP_printk("req_buf=[length=%d, mode=%d, buffer=%pap]",
+ __entry->length, __entry->mode, &__entry->buffer)
+);
+
+TRACE_EVENT(fjes_hw_start_debug,
+ TP_PROTO(union fjes_device_command_res *res_buf),
+ TP_ARGS(res_buf),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, code)
+ ),
+ TP_fast_assign(
+ __entry->length = res_buf->start_trace.length;
+ __entry->code = res_buf->start_trace.code;
+ ),
+ TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code)
+);
+
+TRACE_EVENT(fjes_hw_start_debug_err,
+ TP_PROTO(char *err),
+ TP_ARGS(err),
+ TP_STRUCT__entry(
+ __string(err, err)
+ ),
+ TP_fast_assign(
+ __assign_str(err, err)
+ ),
+ TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_stop_debug,
+ TP_PROTO(union fjes_device_command_res *res_buf),
+ TP_ARGS(res_buf),
+ TP_STRUCT__entry(
+ __field(int, length)
+ __field(int, code)
+ ),
+ TP_fast_assign(
+ __entry->length = res_buf->stop_trace.length;
+ __entry->code = res_buf->stop_trace.code;
+ ),
+ TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code)
+);
+
+TRACE_EVENT(fjes_hw_stop_debug_err,
+ TP_PROTO(char *err),
+ TP_ARGS(err),
+ TP_STRUCT__entry(
+ __string(err, err)
+ ),
+ TP_fast_assign(
+ __assign_str(err, err)
+ ),
+ TP_printk("%s", __get_str(err))
+);
+
+/* tracepoints for fjes_main.c */
+
+TRACE_EVENT(fjes_txrx_stop_req_irq_pre,
+ TP_PROTO(struct fjes_hw *hw, int src_epid,
+ enum ep_partner_status status),
+ TP_ARGS(hw, src_epid, status),
+ TP_STRUCT__entry(
+ __field(int, src_epid)
+ __field(enum ep_partner_status, status)
+ __field(u8, ep_status)
+ __field(unsigned long, txrx_stop_req_bit)
+ __field(u16, rx_status)
+ ),
+ TP_fast_assign(
+ __entry->src_epid = src_epid;
+ __entry->status = status;
+ __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+ __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+ __entry->rx_status =
+ hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+ ),
+ TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+ __entry->src_epid, __entry->status, __entry->ep_status,
+ __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_txrx_stop_req_irq_post,
+ TP_PROTO(struct fjes_hw *hw, int src_epid),
+ TP_ARGS(hw, src_epid),
+ TP_STRUCT__entry(
+ __field(int, src_epid)
+ __field(u8, ep_status)
+ __field(unsigned long, txrx_stop_req_bit)
+ __field(u16, rx_status)
+ ),
+ TP_fast_assign(
+ __entry->src_epid = src_epid;
+ __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+ __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+ __entry->rx_status = hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+ ),
+ TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+ __entry->src_epid, __entry->ep_status,
+ __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_stop_req_irq_pre,
+ TP_PROTO(struct fjes_hw *hw, int src_epid,
+ enum ep_partner_status status),
+ TP_ARGS(hw, src_epid, status),
+ TP_STRUCT__entry(
+ __field(int, src_epid)
+ __field(enum ep_partner_status, status)
+ __field(u8, ep_status)
+ __field(unsigned long, txrx_stop_req_bit)
+ __field(u16, rx_status)
+ ),
+ TP_fast_assign(
+ __entry->src_epid = src_epid;
+ __entry->status = status;
+ __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+ __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+ __entry->rx_status =
+ hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+ ),
+ TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+ __entry->src_epid, __entry->status, __entry->ep_status,
+ __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_stop_req_irq_post,
+ TP_PROTO(struct fjes_hw *hw, int src_epid),
+ TP_ARGS(hw, src_epid),
+ TP_STRUCT__entry(
+ __field(int, src_epid)
+ __field(u8, ep_status)
+ __field(unsigned long, txrx_stop_req_bit)
+ __field(u16, rx_status)
+ ),
+ TP_fast_assign(
+ __entry->src_epid = src_epid;
+ __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+ __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+ __entry->rx_status =
+ hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+ ),
+ TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+ __entry->src_epid, __entry->ep_status,
+ __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+#endif /* FJES_TRACE_H_ */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH ../../../drivers/net/fjes
+#define TRACE_INCLUDE_FILE fjes_trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 8b4822ad27cb..45301cb98bc1 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -43,43 +43,24 @@ struct geneve_net {
struct list_head sock_list;
};
-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, };
+static unsigned int geneve_net_id;
/* 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 ip_tunnel_info info;
struct geneve_sock __rcu *sock4; /* IPv4 socket used for geneve tunnel */
#if IS_ENABLED(CONFIG_IPV6)
struct geneve_sock __rcu *sock6; /* IPv6 socket used for geneve tunnel */
#endif
- u8 vni[3]; /* virtual network ID for tunnel */
- u8 ttl; /* TTL override */
- u8 tos; /* TOS override */
- union geneve_addr remote; /* IP address for link partner */
struct list_head next; /* geneve's per namespace list */
- __be32 label; /* IPv6 flowlabel override */
- __be16 dst_port;
- bool collect_md;
struct gro_cells gro_cells;
- u32 flags;
- struct dst_cache dst_cache;
+ bool collect_md;
+ bool use_udp6_rx_checksums;
};
-/* Geneve device flags */
-#define GENEVE_F_UDP_ZERO_CSUM_TX BIT(0)
-#define GENEVE_F_UDP_ZERO_CSUM6_TX BIT(1)
-#define GENEVE_F_UDP_ZERO_CSUM6_RX BIT(2)
-
struct geneve_sock {
bool collect_md;
struct list_head list;
@@ -87,7 +68,6 @@ struct geneve_sock {
struct rcu_head rcu;
int refcnt;
struct hlist_head vni_list[VNI_HASH_SIZE];
- u32 flags;
};
static inline __u32 geneve_net_vni_hash(u8 vni[3])
@@ -109,6 +89,31 @@ static __be64 vni_to_tunnel_id(const __u8 *vni)
#endif
}
+/* Convert 64 bit tunnel ID to 24 bit VNI. */
+static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni)
+{
+#ifdef __BIG_ENDIAN
+ vni[0] = (__force __u8)(tun_id >> 16);
+ vni[1] = (__force __u8)(tun_id >> 8);
+ vni[2] = (__force __u8)tun_id;
+#else
+ vni[0] = (__force __u8)((__force u64)tun_id >> 40);
+ vni[1] = (__force __u8)((__force u64)tun_id >> 48);
+ vni[2] = (__force __u8)((__force u64)tun_id >> 56);
+#endif
+}
+
+static bool eq_tun_id_and_vni(u8 *tun_id, u8 *vni)
+{
+#ifdef __BIG_ENDIAN
+ return (vni[0] == tun_id[2]) &&
+ (vni[1] == tun_id[1]) &&
+ (vni[2] == tun_id[0]);
+#else
+ return !memcmp(vni, &tun_id[5], 3);
+#endif
+}
+
static sa_family_t geneve_get_sk_family(struct geneve_sock *gs)
{
return gs->sock->sk->sk_family;
@@ -125,8 +130,8 @@ static struct geneve_dev *geneve_lookup(struct geneve_sock *gs,
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)) &&
- addr == geneve->remote.sin.sin_addr.s_addr)
+ if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) &&
+ addr == geneve->info.key.u.ipv4.dst)
return geneve;
}
return NULL;
@@ -144,8 +149,8 @@ static struct geneve_dev *geneve6_lookup(struct geneve_sock *gs,
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))
+ if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) &&
+ ipv6_addr_equal(&addr6, &geneve->info.key.u.ipv6.dst))
return geneve;
}
return NULL;
@@ -160,15 +165,12 @@ static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb)
static struct geneve_dev *geneve_lookup_skb(struct geneve_sock *gs,
struct sk_buff *skb)
{
- u8 *vni;
- __be32 addr;
static u8 zero_vni[3];
-#if IS_ENABLED(CONFIG_IPV6)
- static struct in6_addr zero_addr6;
-#endif
+ u8 *vni;
if (geneve_get_sk_family(gs) == AF_INET) {
struct iphdr *iph;
+ __be32 addr;
iph = ip_hdr(skb); /* outer IP header... */
@@ -183,6 +185,7 @@ static struct geneve_dev *geneve_lookup_skb(struct geneve_sock *gs,
return geneve_lookup(gs, addr, vni);
#if IS_ENABLED(CONFIG_IPV6)
} else if (geneve_get_sk_family(gs) == AF_INET6) {
+ static struct in6_addr zero_addr6;
struct ipv6hdr *ip6h;
struct in6_addr addr6;
@@ -305,13 +308,12 @@ static int geneve_init(struct net_device *dev)
return err;
}
- err = dst_cache_init(&geneve->dst_cache, GFP_KERNEL);
+ err = dst_cache_init(&geneve->info.dst_cache, GFP_KERNEL);
if (err) {
free_percpu(dev->tstats);
gro_cells_destroy(&geneve->gro_cells);
return err;
}
-
return 0;
}
@@ -319,7 +321,7 @@ static void geneve_uninit(struct net_device *dev)
{
struct geneve_dev *geneve = netdev_priv(dev);
- dst_cache_destroy(&geneve->dst_cache);
+ dst_cache_destroy(&geneve->info.dst_cache);
gro_cells_destroy(&geneve->gro_cells);
free_percpu(dev->tstats);
}
@@ -368,7 +370,7 @@ drop:
}
static struct socket *geneve_create_sock(struct net *net, bool ipv6,
- __be16 port, u32 flags)
+ __be16 port, bool ipv6_rx_csum)
{
struct socket *sock;
struct udp_port_cfg udp_conf;
@@ -379,8 +381,7 @@ static struct socket *geneve_create_sock(struct net *net, bool ipv6,
if (ipv6) {
udp_conf.family = AF_INET6;
udp_conf.ipv6_v6only = 1;
- udp_conf.use_udp6_rx_checksums =
- !(flags & GENEVE_F_UDP_ZERO_CSUM6_RX);
+ udp_conf.use_udp6_rx_checksums = ipv6_rx_csum;
} else {
udp_conf.family = AF_INET;
udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
@@ -491,7 +492,7 @@ static int geneve_gro_complete(struct sock *sk, struct sk_buff *skb,
/* Create new listen socket if needed */
static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port,
- bool ipv6, u32 flags)
+ bool ipv6, bool ipv6_rx_csum)
{
struct geneve_net *gn = net_generic(net, geneve_net_id);
struct geneve_sock *gs;
@@ -503,7 +504,7 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port,
if (!gs)
return ERR_PTR(-ENOMEM);
- sock = geneve_create_sock(net, ipv6, port, flags);
+ sock = geneve_create_sock(net, ipv6, port, ipv6_rx_csum);
if (IS_ERR(sock)) {
kfree(gs);
return ERR_CAST(sock);
@@ -579,21 +580,22 @@ static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6)
struct net *net = geneve->net;
struct geneve_net *gn = net_generic(net, geneve_net_id);
struct geneve_sock *gs;
+ __u8 vni[3];
__u32 hash;
- gs = geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, geneve->dst_port);
+ gs = geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, geneve->info.key.tp_dst);
if (gs) {
gs->refcnt++;
goto out;
}
- gs = geneve_socket_create(net, geneve->dst_port, ipv6, geneve->flags);
+ gs = geneve_socket_create(net, geneve->info.key.tp_dst, ipv6,
+ geneve->use_udp6_rx_checksums);
if (IS_ERR(gs))
return PTR_ERR(gs);
out:
gs->collect_md = geneve->collect_md;
- gs->flags = geneve->flags;
#if IS_ENABLED(CONFIG_IPV6)
if (ipv6)
rcu_assign_pointer(geneve->sock6, gs);
@@ -601,7 +603,8 @@ out:
#endif
rcu_assign_pointer(geneve->sock4, gs);
- hash = geneve_net_vni_hash(geneve->vni);
+ tunnel_id_to_vni(geneve->info.key.tun_id, vni);
+ hash = geneve_net_vni_hash(vni);
hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]);
return 0;
}
@@ -609,7 +612,7 @@ out:
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 ipv6 = !!(geneve->info.mode & IP_TUNNEL_INFO_IPV6);
bool metadata = geneve->collect_md;
int ret = 0;
@@ -636,67 +639,34 @@ static int geneve_stop(struct net_device *dev)
}
static void geneve_build_header(struct genevehdr *geneveh,
- __be16 tun_flags, u8 vni[3],
- u8 options_len, u8 *options)
+ const struct ip_tunnel_info *info)
{
geneveh->ver = GENEVE_VER;
- geneveh->opt_len = options_len / 4;
- geneveh->oam = !!(tun_flags & TUNNEL_OAM);
- geneveh->critical = !!(tun_flags & TUNNEL_CRIT_OPT);
+ geneveh->opt_len = info->options_len / 4;
+ geneveh->oam = !!(info->key.tun_flags & TUNNEL_OAM);
+ geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT);
geneveh->rsvd1 = 0;
- memcpy(geneveh->vni, vni, 3);
+ tunnel_id_to_vni(info->key.tun_id, geneveh->vni);
geneveh->proto_type = htons(ETH_P_TEB);
geneveh->rsvd2 = 0;
- memcpy(geneveh->options, options, options_len);
+ ip_tunnel_info_opts_get(geneveh->options, info);
}
-static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
- __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
- u32 flags, bool xnet)
+static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
+ const struct ip_tunnel_info *info,
+ bool xnet, int ip_hdr_len)
{
+ bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
struct genevehdr *gnvh;
int min_headroom;
int err;
- bool udp_sum = !(flags & GENEVE_F_UDP_ZERO_CSUM_TX);
-
- 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);
- if (unlikely(err))
- goto free_rt;
-
- err = udp_tunnel_handle_offloads(skb, udp_sum);
- if (err)
- goto free_rt;
-
- 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_rt:
- ip_rt_put(rt);
- return err;
-}
-
-#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,
- u32 flags, bool xnet)
-{
- struct genevehdr *gnvh;
- int min_headroom;
- int err;
- bool udp_sum = !(flags & GENEVE_F_UDP_ZERO_CSUM6_TX);
+ skb_reset_mac_header(skb);
skb_scrub_packet(skb, xnet);
- min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
- + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
+ min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
+ GENEVE_BASE_HLEN + info->options_len + ip_hdr_len;
err = skb_cow_head(skb, min_headroom);
if (unlikely(err))
goto free_dst;
@@ -705,9 +675,9 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
if (err)
goto free_dst;
- gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
- geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);
-
+ gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) +
+ info->options_len);
+ geneve_build_header(gnvh, info);
skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return 0;
@@ -715,12 +685,11 @@ 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)
+ const struct ip_tunnel_info *info)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
@@ -734,32 +703,22 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
memset(fl4, 0, sizeof(*fl4));
fl4->flowi4_mark = skb->mark;
fl4->flowi4_proto = IPPROTO_UDP;
+ fl4->daddr = info->key.u.ipv4.dst;
+ fl4->saddr = info->key.u.ipv4.src;
- if (info) {
- fl4->daddr = info->key.u.ipv4.dst;
- fl4->saddr = info->key.u.ipv4.src;
- fl4->flowi4_tos = RT_TOS(info->key.tos);
- dst_cache = &info->dst_cache;
- } else {
- tos = geneve->tos;
- if (tos == 1) {
- const struct iphdr *iip = ip_hdr(skb);
-
- tos = ip_tunnel_get_dsfield(iip, skb);
- use_cache = false;
- }
-
- fl4->flowi4_tos = RT_TOS(tos);
- fl4->daddr = geneve->remote.sin.sin_addr.s_addr;
- dst_cache = &geneve->dst_cache;
+ tos = info->key.tos;
+ if ((tos == 1) && !geneve->collect_md) {
+ tos = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
+ use_cache = false;
}
+ fl4->flowi4_tos = RT_TOS(tos);
+ dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) {
rt = dst_cache_get_ip4(dst_cache, &fl4->saddr);
if (rt)
return rt;
}
-
rt = ip_route_output_key(geneve->net, fl4);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
@@ -779,7 +738,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
struct net_device *dev,
struct flowi6 *fl6,
- struct ip_tunnel_info *info)
+ const struct ip_tunnel_info *info)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
@@ -795,34 +754,22 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
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->flowlabel = ip6_make_flowinfo(RT_TOS(info->key.tos),
- info->key.label);
- dst_cache = &info->dst_cache;
- } else {
- prio = geneve->tos;
- if (prio == 1) {
- const struct iphdr *iip = ip_hdr(skb);
-
- prio = ip_tunnel_get_dsfield(iip, skb);
- use_cache = false;
- }
-
- fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
- geneve->label);
- fl6->daddr = geneve->remote.sin6.sin6_addr;
- dst_cache = &geneve->dst_cache;
+ fl6->daddr = info->key.u.ipv6.dst;
+ fl6->saddr = info->key.u.ipv6.src;
+ prio = info->key.tos;
+ if ((prio == 1) && !geneve->collect_md) {
+ prio = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
+ use_cache = false;
}
+ fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
+ info->key.label);
+ dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) {
dst = dst_cache_get_ip6(dst_cache, &fl6->saddr);
if (dst)
return dst;
}
-
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);
@@ -839,199 +786,81 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
}
#endif
-/* Convert 64 bit tunnel ID to 24 bit VNI. */
-static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni)
+static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ struct geneve_dev *geneve,
+ const struct ip_tunnel_info *info)
{
-#ifdef __BIG_ENDIAN
- vni[0] = (__force __u8)(tun_id >> 16);
- vni[1] = (__force __u8)(tun_id >> 8);
- vni[2] = (__force __u8)tun_id;
-#else
- vni[0] = (__force __u8)((__force u64)tun_id >> 40);
- vni[1] = (__force __u8)((__force u64)tun_id >> 48);
- vni[2] = (__force __u8)((__force u64)tun_id >> 56);
-#endif
-}
-
-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 *gs4;
- struct rtable *rt = NULL;
- int err = -EINVAL;
+ bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
+ struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
+ const struct ip_tunnel_key *key = &info->key;
+ struct rtable *rt;
struct flowi4 fl4;
__u8 tos, ttl;
__be16 sport;
__be16 df;
- bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
- u32 flags = geneve->flags;
-
- gs4 = rcu_dereference(geneve->sock4);
- if (!gs4)
- goto tx_error;
-
- if (geneve->collect_md) {
- if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
- netdev_dbg(dev, "no tunnel metadata\n");
- goto tx_error;
- }
- if (info && ip_tunnel_info_af(info) != AF_INET)
- goto tx_error;
- }
+ int err;
rt = geneve_get_v4_rt(skb, dev, &fl4, info);
- if (IS_ERR(rt)) {
- err = PTR_ERR(rt);
- goto tx_error;
- }
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
- skb_reset_mac_header(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 (info->options_len)
- opts = ip_tunnel_info_opts(info);
-
- if (key->tun_flags & TUNNEL_CSUM)
- flags &= ~GENEVE_F_UDP_ZERO_CSUM_TX;
- else
- flags |= GENEVE_F_UDP_ZERO_CSUM_TX;
-
- err = geneve_build_skb(rt, skb, key->tun_flags, vni,
- info->options_len, opts, flags, xnet);
- if (unlikely(err))
- goto tx_error;
-
+ if (geneve->collect_md) {
tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
ttl = key->ttl;
- df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
} else {
- err = geneve_build_skb(rt, skb, 0, geneve->vni,
- 0, NULL, flags, xnet);
- if (unlikely(err))
- goto tx_error;
-
tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
- ttl = geneve->ttl;
- if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
- ttl = 1;
- ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
- df = 0;
+ ttl = key->ttl ? : ip4_dst_hoplimit(&rt->dst);
}
- 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)),
- !!(flags & GENEVE_F_UDP_ZERO_CSUM_TX));
-
- return NETDEV_TX_OK;
-
-tx_error:
- dev_kfree_skb(skb);
+ df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
- if (err == -ELOOP)
- dev->stats.collisions++;
- else if (err == -ENETUNREACH)
- dev->stats.tx_carrier_errors++;
+ err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
+ if (unlikely(err))
+ return err;
- dev->stats.tx_errors++;
- return NETDEV_TX_OK;
+ udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr,
+ tos, ttl, df, sport, geneve->info.key.tp_dst,
+ !net_eq(geneve->net, dev_net(geneve->dev)),
+ !(info->key.tun_flags & TUNNEL_CSUM));
+ return 0;
}
#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)
+static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ struct geneve_dev *geneve,
+ const struct ip_tunnel_info *info)
{
- struct geneve_dev *geneve = netdev_priv(dev);
+ bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
+ struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
+ const struct ip_tunnel_key *key = &info->key;
struct dst_entry *dst = NULL;
- struct geneve_sock *gs6;
- int err = -EINVAL;
struct flowi6 fl6;
__u8 prio, ttl;
__be16 sport;
- __be32 label;
- bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
- u32 flags = geneve->flags;
-
- gs6 = rcu_dereference(geneve->sock6);
- if (!gs6)
- goto tx_error;
-
- if (geneve->collect_md) {
- if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
- netdev_dbg(dev, "no tunnel metadata\n");
- goto tx_error;
- }
- }
+ int err;
dst = geneve_get_v6_dst(skb, dev, &fl6, info);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
- goto tx_error;
- }
+ if (IS_ERR(dst))
+ return PTR_ERR(dst);
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
- skb_reset_mac_header(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 (info->options_len)
- opts = ip_tunnel_info_opts(info);
-
- if (key->tun_flags & TUNNEL_CSUM)
- flags &= ~GENEVE_F_UDP_ZERO_CSUM6_TX;
- else
- flags |= GENEVE_F_UDP_ZERO_CSUM6_TX;
-
- err = geneve6_build_skb(dst, skb, key->tun_flags, vni,
- info->options_len, opts,
- flags, xnet);
- if (unlikely(err))
- goto tx_error;
-
+ if (geneve->collect_md) {
prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
ttl = key->ttl;
- label = info->key.label;
} else {
- err = geneve6_build_skb(dst, skb, 0, geneve->vni,
- 0, NULL, flags, xnet);
- if (unlikely(err))
- goto tx_error;
-
prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
ip_hdr(skb), skb);
- ttl = geneve->ttl;
- if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
- ttl = 1;
- ttl = ttl ? : ip6_dst_hoplimit(dst);
- label = geneve->label;
+ ttl = key->ttl ? : ip6_dst_hoplimit(dst);
}
+ err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr));
+ if (unlikely(err))
+ return err;
udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
- &fl6.saddr, &fl6.daddr, prio, ttl, label,
- sport, geneve->dst_port,
- !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX));
- return NETDEV_TX_OK;
-
-tx_error:
- dev_kfree_skb(skb);
-
- if (err == -ELOOP)
- dev->stats.collisions++;
- else if (err == -ENETUNREACH)
- dev->stats.tx_carrier_errors++;
-
- dev->stats.tx_errors++;
- return NETDEV_TX_OK;
+ &fl6.saddr, &fl6.daddr, prio, ttl,
+ info->key.label, sport, geneve->info.key.tp_dst,
+ !(info->key.tun_flags & TUNNEL_CSUM));
+ return 0;
}
#endif
@@ -1039,63 +868,61 @@ 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;
+ int err;
- if (geneve->collect_md)
+ if (geneve->collect_md) {
info = skb_tunnel_info(skb);
+ if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
+ err = -EINVAL;
+ netdev_dbg(dev, "no tunnel metadata\n");
+ goto tx_error;
+ }
+ } else {
+ info = &geneve->info;
+ }
#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_change_mtu(struct net_device *dev, int new_mtu, bool strict)
-{
- struct geneve_dev *geneve = netdev_priv(dev);
- /* The max_mtu calculation does not take account of GENEVE
- * options, to avoid excluding potentially valid
- * configurations.
- */
- int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len;
-
- if (geneve->remote.sa.sa_family == AF_INET6)
- max_mtu -= sizeof(struct ipv6hdr);
+ if (info->mode & IP_TUNNEL_INFO_IPV6)
+ err = geneve6_xmit_skb(skb, dev, geneve, info);
else
- max_mtu -= sizeof(struct iphdr);
-
- if (new_mtu < 68)
- return -EINVAL;
+#endif
+ err = geneve_xmit_skb(skb, dev, geneve, info);
- if (new_mtu > max_mtu) {
- if (strict)
- return -EINVAL;
+ if (likely(!err))
+ return NETDEV_TX_OK;
+tx_error:
+ dev_kfree_skb(skb);
- new_mtu = max_mtu;
- }
+ if (err == -ELOOP)
+ dev->stats.collisions++;
+ else if (err == -ENETUNREACH)
+ dev->stats.tx_carrier_errors++;
- dev->mtu = new_mtu;
- return 0;
+ dev->stats.tx_errors++;
+ return NETDEV_TX_OK;
}
static int geneve_change_mtu(struct net_device *dev, int new_mtu)
{
- return __geneve_change_mtu(dev, new_mtu, true);
+ /* Only possible if called internally, ndo_change_mtu path's new_mtu
+ * is guaranteed to be between dev->min_mtu and dev->max_mtu.
+ */
+ if (new_mtu > dev->max_mtu)
+ new_mtu = dev->max_mtu;
+
+ dev->mtu = new_mtu;
+ return 0;
}
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) {
+ struct rtable *rt;
+ struct flowi4 fl4;
+
rt = geneve_get_v4_rt(skb, dev, &fl4, info);
if (IS_ERR(rt))
return PTR_ERR(rt);
@@ -1104,6 +931,9 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
info->key.u.ipv4.src = fl4.saddr;
#if IS_ENABLED(CONFIG_IPV6)
} else if (ip_tunnel_info_af(info) == AF_INET6) {
+ struct dst_entry *dst;
+ struct flowi6 fl6;
+
dst = geneve_get_v6_dst(skb, dev, &fl6, info);
if (IS_ERR(dst))
return PTR_ERR(dst);
@@ -1117,7 +947,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
info->key.tp_src = udp_flow_src_port(geneve->net, skb,
1, USHRT_MAX, true);
- info->key.tp_dst = geneve->dst_port;
+ info->key.tp_dst = geneve->info.key.tp_dst;
return 0;
}
@@ -1187,6 +1017,14 @@ static void geneve_setup(struct net_device *dev)
dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+ /* MTU range: 68 - (something less than 65535) */
+ dev->min_mtu = ETH_MIN_MTU;
+ /* The max_mtu calculation does not take account of GENEVE
+ * options, to avoid excluding potentially valid
+ * configurations. This will be further reduced by IPvX hdr size.
+ */
+ dev->max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len;
+
netif_keep_dst(dev);
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
@@ -1231,81 +1069,75 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[])
}
static struct geneve_dev *geneve_find_dev(struct geneve_net *gn,
- __be16 dst_port,
- union geneve_addr *remote,
- u8 vni[],
+ const struct ip_tunnel_info *info,
bool *tun_on_same_port,
bool *tun_collect_md)
{
- struct geneve_dev *geneve, *t;
+ struct geneve_dev *geneve, *t = NULL;
*tun_on_same_port = false;
*tun_collect_md = false;
- t = NULL;
list_for_each_entry(geneve, &gn->geneve_list, next) {
- if (geneve->dst_port == dst_port) {
+ if (info->key.tp_dst == geneve->info.key.tp_dst) {
*tun_collect_md = geneve->collect_md;
*tun_on_same_port = true;
}
- if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
- !memcmp(remote, &geneve->remote, sizeof(geneve->remote)) &&
- dst_port == geneve->dst_port)
+ if (info->key.tun_id == geneve->info.key.tun_id &&
+ info->key.tp_dst == geneve->info.key.tp_dst &&
+ !memcmp(&info->key.u, &geneve->info.key.u, sizeof(info->key.u)))
t = geneve;
}
return t;
}
+static bool is_all_zero(const u8 *fp, size_t size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (fp[i])
+ return false;
+ return true;
+}
+
+static bool is_tnl_info_zero(const struct ip_tunnel_info *info)
+{
+ if (info->key.tun_id || info->key.tun_flags || info->key.tos ||
+ info->key.ttl || info->key.label || info->key.tp_src ||
+ !is_all_zero((const u8 *)&info->key.u, sizeof(info->key.u)))
+ return false;
+ else
+ return true;
+}
+
static int geneve_configure(struct net *net, struct net_device *dev,
- union geneve_addr *remote,
- __u32 vni, __u8 ttl, __u8 tos, __be32 label,
- __be16 dst_port, bool metadata, u32 flags)
+ const struct ip_tunnel_info *info,
+ bool metadata, bool ipv6_rx_csum)
{
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, encap_len;
- if (!remote)
- return -EINVAL;
- if (metadata &&
- (remote->sa.sa_family != AF_UNSPEC || vni || tos || ttl || label))
+ if (metadata && !is_tnl_info_zero(info))
return -EINVAL;
geneve->net = net;
geneve->dev = dev;
- geneve->vni[0] = (vni & 0x00ff0000) >> 16;
- geneve->vni[1] = (vni & 0x0000ff00) >> 8;
- geneve->vni[2] = vni & 0x000000ff;
-
- 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;
- if (label && remote->sa.sa_family != AF_INET6)
- return -EINVAL;
-
- geneve->remote = *remote;
-
- geneve->ttl = ttl;
- geneve->tos = tos;
- geneve->label = label;
- geneve->dst_port = dst_port;
- geneve->collect_md = metadata;
- geneve->flags = flags;
-
- t = geneve_find_dev(gn, dst_port, remote, geneve->vni,
- &tun_on_same_port, &tun_collect_md);
+ t = geneve_find_dev(gn, info, &tun_on_same_port, &tun_collect_md);
if (t)
return -EBUSY;
/* make enough headroom for basic scenario */
encap_len = GENEVE_BASE_HLEN + ETH_HLEN;
- if (remote->sa.sa_family == AF_INET)
+ if (ip_tunnel_info_af(info) == AF_INET) {
encap_len += sizeof(struct iphdr);
- else
+ dev->max_mtu -= sizeof(struct iphdr);
+ } else {
encap_len += sizeof(struct ipv6hdr);
+ dev->max_mtu -= sizeof(struct ipv6hdr);
+ }
dev->needed_headroom = encap_len + ETH_HLEN;
if (metadata) {
@@ -1316,7 +1148,10 @@ static int geneve_configure(struct net *net, struct net_device *dev,
return -EPERM;
}
- dst_cache_reset(&geneve->dst_cache);
+ dst_cache_reset(&geneve->info.dst_cache);
+ geneve->info = *info;
+ geneve->collect_md = metadata;
+ geneve->use_udp6_rx_checksums = ipv6_rx_csum;
err = register_netdevice(dev);
if (err)
@@ -1326,74 +1161,99 @@ static int geneve_configure(struct net *net, struct net_device *dev,
return 0;
}
+static void init_tnl_info(struct ip_tunnel_info *info, __u16 dst_port)
+{
+ memset(info, 0, sizeof(*info));
+ info->key.tp_dst = htons(dst_port);
+}
+
static int geneve_newlink(struct net *net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
- __be16 dst_port = htons(GENEVE_UDP_PORT);
- __u8 ttl = 0, tos = 0;
+ bool use_udp6_rx_checksums = false;
+ struct ip_tunnel_info info;
bool metadata = false;
- union geneve_addr remote = geneve_remote_unspec;
- __be32 label = 0;
- __u32 vni = 0;
- u32 flags = 0;
+
+ init_tnl_info(&info, GENEVE_UDP_PORT);
if (data[IFLA_GENEVE_REMOTE] && data[IFLA_GENEVE_REMOTE6])
return -EINVAL;
if (data[IFLA_GENEVE_REMOTE]) {
- remote.sa.sa_family = AF_INET;
- remote.sin.sin_addr.s_addr =
+ info.key.u.ipv4.dst =
nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+
+ if (IN_MULTICAST(ntohl(info.key.u.ipv4.dst))) {
+ netdev_dbg(dev, "multicast remote is unsupported\n");
+ return -EINVAL;
+ }
}
if (data[IFLA_GENEVE_REMOTE6]) {
- if (!IS_ENABLED(CONFIG_IPV6))
- return -EPFNOSUPPORT;
-
- remote.sa.sa_family = AF_INET6;
- remote.sin6.sin6_addr =
+ #if IS_ENABLED(CONFIG_IPV6)
+ info.mode = IP_TUNNEL_INFO_IPV6;
+ info.key.u.ipv6.dst =
nla_get_in6_addr(data[IFLA_GENEVE_REMOTE6]);
- if (ipv6_addr_type(&remote.sin6.sin6_addr) &
+ if (ipv6_addr_type(&info.key.u.ipv6.dst) &
IPV6_ADDR_LINKLOCAL) {
netdev_dbg(dev, "link-local remote is unsupported\n");
return -EINVAL;
}
+ if (ipv6_addr_is_multicast(&info.key.u.ipv6.dst)) {
+ netdev_dbg(dev, "multicast remote is unsupported\n");
+ return -EINVAL;
+ }
+ info.key.tun_flags |= TUNNEL_CSUM;
+ use_udp6_rx_checksums = true;
+#else
+ return -EPFNOSUPPORT;
+#endif
}
- if (data[IFLA_GENEVE_ID])
+ if (data[IFLA_GENEVE_ID]) {
+ __u32 vni;
+ __u8 tvni[3];
+
vni = nla_get_u32(data[IFLA_GENEVE_ID]);
+ tvni[0] = (vni & 0x00ff0000) >> 16;
+ tvni[1] = (vni & 0x0000ff00) >> 8;
+ tvni[2] = vni & 0x000000ff;
+ info.key.tun_id = vni_to_tunnel_id(tvni);
+ }
if (data[IFLA_GENEVE_TTL])
- ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
+ info.key.ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
if (data[IFLA_GENEVE_TOS])
- tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
+ info.key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
- if (data[IFLA_GENEVE_LABEL])
- label = nla_get_be32(data[IFLA_GENEVE_LABEL]) &
- IPV6_FLOWLABEL_MASK;
+ if (data[IFLA_GENEVE_LABEL]) {
+ info.key.label = nla_get_be32(data[IFLA_GENEVE_LABEL]) &
+ IPV6_FLOWLABEL_MASK;
+ if (info.key.label && (!(info.mode & IP_TUNNEL_INFO_IPV6)))
+ return -EINVAL;
+ }
if (data[IFLA_GENEVE_PORT])
- dst_port = nla_get_be16(data[IFLA_GENEVE_PORT]);
+ info.key.tp_dst = nla_get_be16(data[IFLA_GENEVE_PORT]);
if (data[IFLA_GENEVE_COLLECT_METADATA])
metadata = true;
if (data[IFLA_GENEVE_UDP_CSUM] &&
!nla_get_u8(data[IFLA_GENEVE_UDP_CSUM]))
- flags |= GENEVE_F_UDP_ZERO_CSUM_TX;
+ info.key.tun_flags |= TUNNEL_CSUM;
if (data[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] &&
nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
- flags |= GENEVE_F_UDP_ZERO_CSUM6_TX;
+ info.key.tun_flags &= ~TUNNEL_CSUM;
if (data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] &&
nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
- flags |= GENEVE_F_UDP_ZERO_CSUM6_RX;
+ use_udp6_rx_checksums = false;
- return geneve_configure(net, dev, &remote, vni, ttl, tos, label,
- dst_port, metadata, flags);
+ return geneve_configure(net, dev, &info, metadata, use_udp6_rx_checksums);
}
static void geneve_dellink(struct net_device *dev, struct list_head *head)
@@ -1422,45 +1282,52 @@ static size_t geneve_get_size(const struct net_device *dev)
static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
struct geneve_dev *geneve = netdev_priv(dev);
+ struct ip_tunnel_info *info = &geneve->info;
+ __u8 tmp_vni[3];
__u32 vni;
- vni = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+ tunnel_id_to_vni(info->key.tun_id, tmp_vni);
+ vni = (tmp_vni[0] << 16) | (tmp_vni[1] << 8) | tmp_vni[2];
if (nla_put_u32(skb, IFLA_GENEVE_ID, vni))
goto nla_put_failure;
- if (geneve->remote.sa.sa_family == AF_INET) {
+ if (ip_tunnel_info_af(info) == AF_INET) {
if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,
- geneve->remote.sin.sin_addr.s_addr))
+ info->key.u.ipv4.dst))
goto nla_put_failure;
+
+ if (nla_put_u8(skb, IFLA_GENEVE_UDP_CSUM,
+ !!(info->key.tun_flags & TUNNEL_CSUM)))
+ goto nla_put_failure;
+
#if IS_ENABLED(CONFIG_IPV6)
} else {
if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6,
- &geneve->remote.sin6.sin6_addr))
+ &info->key.u.ipv6.dst))
+ goto nla_put_failure;
+
+ if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
+ !(info->key.tun_flags & TUNNEL_CSUM)))
+ goto nla_put_failure;
+
+ if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
+ !geneve->use_udp6_rx_checksums))
goto nla_put_failure;
#endif
}
- if (nla_put_u8(skb, IFLA_GENEVE_TTL, geneve->ttl) ||
- nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos) ||
- nla_put_be32(skb, IFLA_GENEVE_LABEL, geneve->label))
+ if (nla_put_u8(skb, IFLA_GENEVE_TTL, info->key.ttl) ||
+ nla_put_u8(skb, IFLA_GENEVE_TOS, info->key.tos) ||
+ nla_put_be32(skb, IFLA_GENEVE_LABEL, info->key.label))
goto nla_put_failure;
- if (nla_put_be16(skb, IFLA_GENEVE_PORT, geneve->dst_port))
+ if (nla_put_be16(skb, IFLA_GENEVE_PORT, info->key.tp_dst))
goto nla_put_failure;
if (geneve->collect_md) {
if (nla_put_flag(skb, IFLA_GENEVE_COLLECT_METADATA))
goto nla_put_failure;
}
-
- if (nla_put_u8(skb, IFLA_GENEVE_UDP_CSUM,
- !(geneve->flags & GENEVE_F_UDP_ZERO_CSUM_TX)) ||
- nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
- !!(geneve->flags & GENEVE_F_UDP_ZERO_CSUM6_TX)) ||
- nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
- !!(geneve->flags & GENEVE_F_UDP_ZERO_CSUM6_RX)))
- goto nla_put_failure;
-
return 0;
nla_put_failure:
@@ -1484,6 +1351,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
u8 name_assign_type, u16 dst_port)
{
struct nlattr *tb[IFLA_MAX + 1];
+ struct ip_tunnel_info info;
struct net_device *dev;
LIST_HEAD(list_kill);
int err;
@@ -1494,9 +1362,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, &geneve_remote_unspec,
- 0, 0, 0, 0, htons(dst_port), true,
- GENEVE_F_UDP_ZERO_CSUM6_RX);
+ init_tnl_info(&info, dst_port);
+ err = geneve_configure(net, dev, &info, true, true);
if (err) {
free_netdev(dev);
return ERR_PTR(err);
@@ -1505,7 +1372,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
/* openvswitch users expect packet sizes to be unrestricted,
* so set the largest MTU we can.
*/
- err = __geneve_change_mtu(dev, IP_MAX_MTU, false);
+ err = geneve_change_mtu(dev, IP_MAX_MTU);
if (err)
goto err;
@@ -1514,8 +1381,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
goto err;
return dev;
-
- err:
+err:
geneve_dellink(dev, &list_kill);
unregister_netdevice_many(&list_kill);
return ERR_PTR(err);
@@ -1598,7 +1464,6 @@ static int __init geneve_init_module(void)
goto out3;
return 0;
-
out3:
unregister_netdevice_notifier(&geneve_notifier_block);
out2:
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 97e0cbca0a08..98f10c216521 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -77,7 +77,7 @@ struct gtp_dev {
struct hlist_head *addr_hash;
};
-static int gtp_net_id __read_mostly;
+static unsigned int gtp_net_id __read_mostly;
struct gtp_net {
struct list_head gtp_dev_list;
@@ -1094,14 +1094,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
return 0;
}
-static struct genl_family gtp_genl_family = {
- .id = GENL_ID_GENERATE,
- .name = "gtp",
- .version = 0,
- .hdrsize = 0,
- .maxattr = GTPA_MAX,
- .netnsok = true,
-};
+static struct genl_family gtp_genl_family;
static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
u32 type, struct pdp_ctx *pctx)
@@ -1297,6 +1290,17 @@ static const struct genl_ops gtp_genl_ops[] = {
},
};
+static struct genl_family gtp_genl_family __ro_after_init = {
+ .name = "gtp",
+ .version = 0,
+ .hdrsize = 0,
+ .maxattr = GTPA_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = gtp_genl_ops,
+ .n_ops = ARRAY_SIZE(gtp_genl_ops),
+};
+
static int __net_init gtp_net_init(struct net *net)
{
struct gtp_net *gn = net_generic(net, gtp_net_id);
@@ -1336,7 +1340,7 @@ static int __init gtp_init(void)
if (err < 0)
goto error_out;
- err = genl_register_family_with_ops(&gtp_genl_family, gtp_genl_ops);
+ err = genl_register_family(&gtp_genl_family);
if (err < 0)
goto unreg_rtnl_link;
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
index 95c0b45a68fb..f5a9728b89f3 100644
--- a/drivers/net/hippi/rrunner.c
+++ b/drivers/net/hippi/rrunner.c
@@ -68,7 +68,6 @@ static const struct net_device_ops rr_netdev_ops = {
.ndo_stop = rr_close,
.ndo_do_ioctl = rr_ioctl,
.ndo_start_xmit = rr_start_xmit,
- .ndo_change_mtu = hippi_change_mtu,
.ndo_set_mac_address = hippi_mac_addr,
};
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index f4fbcb5aa24a..3958adade7eb 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -606,8 +606,8 @@ struct nvsp_message {
} __packed;
-#define NETVSC_MTU 65536
-#define NETVSC_MTU_MIN 68
+#define NETVSC_MTU 65535
+#define NETVSC_MTU_MIN ETH_MIN_MTU
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 720b5fa9e625..5a1cc089acb7 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -410,8 +410,8 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_cnt =
net_device->send_buf_size / net_device->send_section_size;
- dev_info(&device->device, "Send section size: %d, Section count:%d\n",
- net_device->send_section_size, net_device->send_section_cnt);
+ netdev_dbg(ndev, "Send section size: %d, Section count:%d\n",
+ net_device->send_section_size, net_device->send_section_cnt);
/* Setup state for managing the send buffer. */
net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt,
@@ -578,7 +578,7 @@ void netvsc_device_remove(struct hv_device *device)
* At this point, no one should be accessing net_device
* except in here
*/
- dev_notice(&device->device, "net device safe to remove\n");
+ netdev_dbg(ndev, "net device safe to remove\n");
/* Now, we can close the channel safely */
vmbus_close(device->channel);
@@ -888,6 +888,13 @@ int netvsc_send(struct hv_device *device,
if (!net_device)
return -ENODEV;
+ /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
+ * here before the negotiation with the host is finished and
+ * send_section_map may not be allocated yet.
+ */
+ if (!net_device->send_section_map)
+ return -EAGAIN;
+
out_channel = net_device->chn_table[q_idx];
packet->send_buf_index = NETVSC_INVALID_INDEX;
@@ -1380,7 +1387,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
}
/* Channel is opened */
- pr_info("hv_netvsc channel opened successfully\n");
+ netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
/* If we're reopening the device we may have multiple queues, fill the
* chn_table with the default channel to use it before subchannels are
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c9140c3aeb67..c9414c054852 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -875,19 +875,12 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
struct netvsc_device *nvdev = ndevctx->nvdev;
struct hv_device *hdev = ndevctx->device_ctx;
struct netvsc_device_info device_info;
- int limit = ETH_DATA_LEN;
u32 num_chn;
int ret = 0;
if (ndevctx->start_remove || !nvdev || nvdev->destroy)
return -ENODEV;
- if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
- limit = NETVSC_MTU - ETH_HLEN;
-
- if (mtu < NETVSC_MTU_MIN || mtu > limit)
- return -EINVAL;
-
ret = netvsc_close(ndev);
if (ret)
goto out;
@@ -1406,6 +1399,13 @@ static int netvsc_probe(struct hv_device *dev,
netif_set_real_num_rx_queues(net, nvdev->num_chn);
netif_set_gso_max_size(net, NETVSC_GSO_MAX_SIZE);
+ /* MTU range: 68 - 1500 or 65521 */
+ net->min_mtu = NETVSC_MTU_MIN;
+ if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
+ net->max_mtu = NETVSC_MTU - ETH_HLEN;
+ else
+ net->max_mtu = ETH_DATA_LEN;
+
ret = register_netdev(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 9195d5da8485..8d90904e0e49 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1059,9 +1059,9 @@ int rndis_filter_device_add(struct hv_device *dev,
device_info->link_state = rndis_device->link_state;
- dev_info(&dev->device, "Device MAC %pM link state %s\n",
- rndis_device->hw_mac_adr,
- device_info->link_state ? "down" : "up");
+ netdev_dbg(net, "Device MAC %pM link state %s\n",
+ rndis_device->hw_mac_adr,
+ device_info->link_state ? "down" : "up");
if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
return 0;
diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c
index f355df7cf84a..3e4c8b21403c 100644
--- a/drivers/net/ieee802154/adf7242.c
+++ b/drivers/net/ieee802154/adf7242.c
@@ -873,7 +873,7 @@ static int adf7242_rx(struct adf7242_local *lp)
return 0;
}
-static struct ieee802154_ops adf7242_ops = {
+static const struct ieee802154_ops adf7242_ops = {
.owner = THIS_MODULE,
.xmit_sync = adf7242_xmit,
.ed = adf7242_ed,
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 9f10da60e02d..057025722e3d 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -990,7 +990,12 @@ at86rf23x_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
}
#define AT86RF2XX_MAX_ED_LEVELS 0xF
-static const s32 at86rf23x_ed_levels[AT86RF2XX_MAX_ED_LEVELS + 1] = {
+static const s32 at86rf233_ed_levels[AT86RF2XX_MAX_ED_LEVELS + 1] = {
+ -9400, -9200, -9000, -8800, -8600, -8400, -8200, -8000, -7800, -7600,
+ -7400, -7200, -7000, -6800, -6600, -6400,
+};
+
+static const s32 at86rf231_ed_levels[AT86RF2XX_MAX_ED_LEVELS + 1] = {
-9100, -8900, -8700, -8500, -8300, -8100, -7900, -7700, -7500, -7300,
-7100, -6900, -6700, -6500, -6300, -6100,
};
@@ -1343,7 +1348,7 @@ static struct at86rf2xx_chip_data at86rf233_data = {
.t_sleep_to_off = 1000,
.t_frame = 4096,
.t_p_ack = 545,
- .rssi_base_val = -91,
+ .rssi_base_val = -94,
.set_channel = at86rf23x_set_channel,
.set_txpower = at86rf23x_set_txpower,
};
@@ -1557,9 +1562,6 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) |
BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR);
- lp->hw->phy->supported.cca_ed_levels = at86rf23x_ed_levels;
- lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf23x_ed_levels);
-
lp->hw->phy->cca.mode = NL802154_CCA_ENERGY;
switch (part) {
@@ -1575,6 +1577,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->phy->symbol_duration = 16;
lp->hw->phy->supported.tx_powers = at86rf231_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers);
+ lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf231_ed_levels);
break;
case 7:
chip = "at86rf212";
@@ -1598,6 +1602,8 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->phy->symbol_duration = 16;
lp->hw->phy->supported.tx_powers = at86rf233_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers);
+ lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf233_ed_levels);
break;
default:
chip = "unknown";
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 1056ed142411..1253f864737a 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -58,6 +58,11 @@ struct atusb {
struct urb *tx_urb;
struct sk_buff *tx_skb;
uint8_t tx_ack_seq; /* current TX ACK sequence number */
+
+ /* Firmware variable */
+ unsigned char fw_ver_maj; /* Firmware major version number */
+ unsigned char fw_ver_min; /* Firmware minor version number */
+ unsigned char fw_hw_type; /* Firmware hardware type */
};
/* ----- USB commands without data ----------------------------------------- */
@@ -541,6 +546,21 @@ atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries
}
static int
+atusb_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
+{
+ struct atusb *atusb = hw->priv;
+ struct device *dev = &atusb->usb_dev->dev;
+
+ if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) {
+ dev_info(dev, "Automatic frame retransmission is only available from "
+ "firmware version 0.3. Please update if you want this feature.");
+ return -EINVAL;
+ }
+
+ return atusb_write_subreg(atusb, SR_MAX_FRAME_RETRIES, retries);
+}
+
+static int
atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
{
struct atusb *atusb = hw->priv;
@@ -567,7 +587,7 @@ atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
return 0;
}
-static struct ieee802154_ops atusb_ops = {
+static const struct ieee802154_ops atusb_ops = {
.owner = THIS_MODULE,
.xmit_async = atusb_xmit,
.ed = atusb_ed,
@@ -579,6 +599,7 @@ static struct ieee802154_ops atusb_ops = {
.set_cca_mode = atusb_set_cca_mode,
.set_cca_ed_level = atusb_set_cca_ed_level,
.set_csma_params = atusb_set_csma_params,
+ .set_frame_retries = atusb_set_frame_retries,
.set_promiscuous_mode = atusb_set_promiscuous_mode,
};
@@ -594,14 +615,19 @@ static int atusb_get_and_show_revision(struct atusb *atusb)
ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
buffer, 3, 1000);
- if (ret >= 0)
+ if (ret >= 0) {
+ atusb->fw_ver_maj = buffer[0];
+ atusb->fw_ver_min = buffer[1];
+ atusb->fw_hw_type = buffer[2];
+
dev_info(&usb_dev->dev,
"Firmware: major: %u, minor: %u, hardware type: %u\n",
- buffer[0], buffer[1], buffer[2]);
- if (buffer[0] == 0 && buffer[1] < 2) {
+ atusb->fw_ver_maj, atusb->fw_ver_min, atusb->fw_hw_type);
+ }
+ if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 2) {
dev_info(&usb_dev->dev,
- "Firmware version (%u.%u) is predates our first public release.",
- buffer[0], buffer[1]);
+ "Firmware version (%u.%u) predates our first public release.",
+ atusb->fw_ver_maj, atusb->fw_ver_min);
dev_info(&usb_dev->dev, "Please update to version 0.2 or newer");
}
@@ -669,6 +695,43 @@ fail:
return -ENODEV;
}
+static int atusb_set_extended_addr(struct atusb *atusb)
+{
+ struct usb_device *usb_dev = atusb->usb_dev;
+ unsigned char buffer[IEEE802154_EXTENDED_ADDR_LEN];
+ __le64 extended_addr;
+ u64 addr;
+ int ret;
+
+ /* Firmware versions before 0.3 do not support the EUI64_READ command.
+ * Just use a random address and be done */
+ if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) {
+ ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
+ return 0;
+ }
+
+ /* Firmware is new enough so we fetch the address from EEPROM */
+ ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
+ ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0,
+ buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000);
+ if (ret < 0)
+ dev_err(&usb_dev->dev, "failed to fetch extended address\n");
+
+ memcpy(&extended_addr, buffer, IEEE802154_EXTENDED_ADDR_LEN);
+ /* Check if read address is not empty and the unicast bit is set correctly */
+ if (!ieee802154_is_valid_extended_unicast_addr(extended_addr)) {
+ dev_info(&usb_dev->dev, "no permanent extended address found, random address set\n");
+ ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
+ } else {
+ atusb->hw->phy->perm_extended_addr = extended_addr;
+ addr = swab64((__force u64)atusb->hw->phy->perm_extended_addr);
+ dev_info(&usb_dev->dev, "Read permanent extended address %8phC from device\n",
+ &addr);
+ }
+
+ return ret;
+}
+
/* ----- Setup ------------------------------------------------------------- */
static int atusb_probe(struct usb_interface *interface,
@@ -707,7 +770,8 @@ static int atusb_probe(struct usb_interface *interface,
hw->parent = &usb_dev->dev;
hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
- IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS;
+ IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS |
+ IEEE802154_HW_FRAME_RETRIES;
hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL |
WPAN_PHY_FLAG_CCA_MODE;
@@ -728,13 +792,14 @@ static int atusb_probe(struct usb_interface *interface,
hw->phy->supported.tx_powers = atusb_powers;
hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
hw->phy->transmit_power = hw->phy->supported.tx_powers[0];
- ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
hw->phy->cca_ed_level = hw->phy->supported.cca_ed_levels[7];
atusb_command(atusb, ATUSB_RF_RESET, 0);
atusb_get_and_show_chip(atusb);
atusb_get_and_show_revision(atusb);
atusb_get_and_show_build(atusb);
+ atusb_set_extended_addr(atusb);
+
ret = atusb_get_and_clear_error(atusb);
if (ret) {
dev_err(&atusb->usb_dev->dev,
diff --git a/drivers/net/ieee802154/atusb.h b/drivers/net/ieee802154/atusb.h
index 0690edcad57b..b22bbaa77590 100644
--- a/drivers/net/ieee802154/atusb.h
+++ b/drivers/net/ieee802154/atusb.h
@@ -13,8 +13,8 @@
* Firmware: ben-wpan/atusb/fw/include/atusb/atusb.h
*/
-#ifndef _ATUSB_H
-#define _ATUSB_H
+#ifndef _ATUSB_H
+#define _ATUSB_H
#define ATUSB_VENDOR_ID 0x20b7 /* Qi Hardware*/
#define ATUSB_PRODUCT_ID 0x1540 /* 802.15.4, device 0 */
@@ -46,9 +46,12 @@ enum atusb_requests {
ATUSB_SPI_WRITE2_SYNC,
ATUSB_RX_MODE = 0x40, /* HardMAC group */
ATUSB_TX,
+ ATUSB_EUI64_WRITE = 0x50, /* Parameter in EEPROM grp */
+ ATUSB_EUI64_READ,
};
-/* Direction bRequest wValue wIndex wLength
+/*
+ * Direction bRequest wValue wIndex wLength
*
* ->host ATUSB_ID - - 3
* ->host ATUSB_BUILD - - #bytes
@@ -76,6 +79,8 @@ enum atusb_requests {
*
* host-> ATUSB_RX_MODE on - 0
* host-> ATUSB_TX flags ack_seq #bytes
+ * host-> ATUSB_EUI64_WRITE - - #bytes (8)
+ * ->host ATUSB_EUI64_READ - - #bytes (8)
*/
#define ATUSB_REQ_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index ec387efb61d0..0d673f7682ee 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -218,7 +218,7 @@ static int fakelb_probe(struct platform_device *pdev)
goto err_slave;
}
- dev_info(&pdev->dev, "added ieee802154 hardware\n");
+ dev_info(&pdev->dev, "added %i fake ieee802154 hardware devices\n", numlbs);
return 0;
err_slave:
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index 7e0732f5ea07..031093e1c25f 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -73,7 +73,6 @@ struct ipvl_dev {
DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE);
netdev_features_t sfeatures;
u32 msg_enable;
- u16 mtu_adj;
};
struct ipvl_addr {
@@ -98,7 +97,6 @@ struct ipvl_port {
struct work_struct wq;
struct sk_buff_head backlog;
int count;
- struct rcu_head rcu;
};
static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index dfbc4ef6d507..693ec5b66222 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -26,13 +26,13 @@ static struct nf_hook_ops ipvl_nfops[] __read_mostly = {
},
};
-static struct l3mdev_ops ipvl_l3mdev_ops __read_mostly = {
+static const struct l3mdev_ops ipvl_l3mdev_ops = {
.l3mdev_l3_rcv = ipvlan_l3_rcv,
};
static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
{
- ipvlan->dev->mtu = dev->mtu - ipvlan->mtu_adj;
+ ipvlan->dev->mtu = dev->mtu;
}
static int ipvlan_register_nf_hook(void)
@@ -128,7 +128,7 @@ static int ipvlan_port_create(struct net_device *dev)
return 0;
err:
- kfree_rcu(port, rcu);
+ kfree(port);
return err;
}
@@ -145,7 +145,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
netdev_rx_handler_unregister(dev);
cancel_work_sync(&port->wq);
__skb_queue_purge(&port->backlog);
- kfree_rcu(port, rcu);
+ kfree(port);
}
#define IPVLAN_FEATURES \
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index e8c3a8c32534..f293d33fb28f 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -1,5 +1,5 @@
/*********************************************************************
- *
+ *
* Filename: w83977af_ir.c
* Version: 1.0
* Description: FIR driver for the Winbond W83977AF Super I/O chip
@@ -8,37 +8,39 @@
* Created at: Wed Nov 4 11:46:16 1998
* Modified at: Fri Jan 28 12:10:59 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
- *
+ *
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1998-1999 Rebel.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
+ *
+ * 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.
- *
+ *
* Neither Paul VanderSpek nor Rebel.com admit liability nor provide
* warranty for any of this software. This material is provided "AS-IS"
* and at no charge.
- *
+ *
* If you find bugs in this file, its very likely that the same bug
* will also be in pc87108.c since the implementations are quite
* similar.
*
* Notice that all functions that needs to access the chip in _any_
- * way, must save BSR register on entry, and restore it on exit.
+ * way, must save BSR register on entry, and restore it on exit.
* It is _very_ important to follow this policy!
*
* __u8 bank;
- *
+ *
* bank = inb( iobase+BSR);
- *
+ *
* do_your_stuff_here();
*
* outb( bank, iobase+BSR);
*
********************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -63,7 +65,7 @@
#include "w83977af_ir.h"
#define CONFIG_USE_W977_PNP /* Currently needed */
-#define PIO_MAX_SPEED 115200
+#define PIO_MAX_SPEED 115200
static char *driver_name = "w83977af_ir";
static int qos_mtt_bits = 0x07; /* 1 ms or more */
@@ -83,14 +85,14 @@ static unsigned int efio = W977_EFIO_BASE;
static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
/* Some prototypes */
-static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
- unsigned int dma);
+static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
+ unsigned int dma);
static int w83977af_close(struct w83977af_ir *self);
static int w83977af_probe(int iobase, int irq, int dma);
-static int w83977af_dma_receive(struct w83977af_ir *self);
+static int w83977af_dma_receive(struct w83977af_ir *self);
static int w83977af_dma_receive_complete(struct w83977af_ir *self);
static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
- struct net_device *dev);
+ struct net_device *dev);
static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
static void w83977af_dma_write(struct w83977af_ir *self, int iobase);
static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed);
@@ -108,9 +110,9 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
*/
static int __init w83977af_init(void)
{
- int i;
+ int i;
- for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) {
+ for (i = 0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) {
if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
return 0;
}
@@ -127,7 +129,7 @@ static void __exit w83977af_cleanup(void)
{
int i;
- for (i=0; i < ARRAY_SIZE(dev_self); i++) {
+ for (i = 0; i < ARRAY_SIZE(dev_self); i++) {
if (dev_self[i])
w83977af_close(dev_self[i]);
}
@@ -150,13 +152,13 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
unsigned int dma)
{
struct net_device *dev;
- struct w83977af_ir *self;
+ struct w83977af_ir *self;
int err;
/* Lock the port that we need */
if (!request_region(iobase, CHIP_IO_EXTENT, driver_name)) {
- pr_debug("%s(), can't get iobase of 0x%03x\n",
- __func__ , iobase);
+ pr_debug("%s: can't get iobase of 0x%03x\n",
+ __func__, iobase);
return -ENODEV;
}
@@ -168,46 +170,44 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
* Allocate new instance of the driver
*/
dev = alloc_irdadev(sizeof(struct w83977af_ir));
- if (dev == NULL) {
- printk( KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
+ if (!dev) {
+ pr_err("IrDA: Can't allocate memory for IrDA control block!\n");
err = -ENOMEM;
goto err_out;
}
self = netdev_priv(dev);
spin_lock_init(&self->lock);
-
/* Initialize IO */
- self->io.fir_base = iobase;
- self->io.irq = irq;
- self->io.fir_ext = CHIP_IO_EXTENT;
- self->io.dma = dma;
- self->io.fifo_size = 32;
+ self->io.fir_base = iobase;
+ self->io.irq = irq;
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.dma = dma;
+ self->io.fifo_size = 32;
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
-
+
/* The only value we must override it the baudrate */
/* FIXME: The HP HDLS-1100 does not support 1152000! */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
- IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+ self->qos.baud_rate.bits = IR_9600 | IR_19200 | IR_38400 | IR_57600 |
+ IR_115200 | IR_576000 | IR_1152000 | (IR_4000000 << 8);
/* The HP HDLS-1100 needs 1 ms according to the specs */
self->qos.min_turn_time.bits = qos_mtt_bits;
irda_qos_bits_to_value(&self->qos);
-
+
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
- self->rx_buff.truesize = 14384;
+ self->rx_buff.truesize = 14384;
self->tx_buff.truesize = 4000;
-
+
/* Allocate memory if needed */
self->rx_buff.head =
dma_zalloc_coherent(NULL, self->rx_buff.truesize,
&self->rx_buff_dma, GFP_KERNEL);
- if (self->rx_buff.head == NULL) {
+ if (!self->rx_buff.head) {
err = -ENOMEM;
goto err_out1;
}
@@ -215,7 +215,7 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
self->tx_buff.head =
dma_zalloc_coherent(NULL, self->tx_buff.truesize,
&self->tx_buff_dma, GFP_KERNEL);
- if (self->tx_buff.head == NULL) {
+ if (!self->tx_buff.head) {
err = -ENOMEM;
goto err_out2;
}
@@ -230,7 +230,7 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
err = register_netdev(dev);
if (err) {
- net_err_ratelimited("%s(), register_netdevice() failed!\n",
+ net_err_ratelimited("%s:, register_netdevice() failed!\n",
__func__);
goto err_out3;
}
@@ -238,12 +238,12 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
/* Need to store self somewhere */
dev_self[i] = self;
-
+
return 0;
err_out3:
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
-err_out2:
+err_out2:
dma_free_coherent(NULL, self->rx_buff.truesize,
self->rx_buff.head, self->rx_buff_dma);
err_out1:
@@ -263,7 +263,7 @@ static int w83977af_close(struct w83977af_ir *self)
{
int iobase;
- iobase = self->io.fir_base;
+ iobase = self->io.fir_base;
#ifdef CONFIG_USE_W977_PNP
/* enter PnP configuration mode */
@@ -281,14 +281,13 @@ static int w83977af_close(struct w83977af_ir *self)
unregister_netdev(self->netdev);
/* Release the PORT that this driver is using */
- pr_debug("%s(), Releasing Region %03x\n",
- __func__ , self->io.fir_base);
+ pr_debug("%s: Releasing Region %03x\n", __func__, self->io.fir_base);
release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
-
+
if (self->rx_buff.head)
dma_free_coherent(NULL, self->rx_buff.truesize,
self->rx_buff.head, self->rx_buff_dma);
@@ -300,106 +299,106 @@ static int w83977af_close(struct w83977af_ir *self)
static int w83977af_probe(int iobase, int irq, int dma)
{
- int version;
+ int version;
int i;
-
- for (i=0; i < 2; i++) {
+
+ for (i = 0; i < 2; i++) {
#ifdef CONFIG_USE_W977_PNP
- /* Enter PnP configuration mode */
+ /* Enter PnP configuration mode */
w977_efm_enter(efbase[i]);
-
- w977_select_device(W977_DEVICE_IR, efbase[i]);
-
- /* Configure PnP port, IRQ, and DMA channel */
- w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]);
- w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
-
- w977_write_reg(0x70, irq, efbase[i]);
+
+ w977_select_device(W977_DEVICE_IR, efbase[i]);
+
+ /* Configure PnP port, IRQ, and DMA channel */
+ w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]);
+ w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
+
+ w977_write_reg(0x70, irq, efbase[i]);
#ifdef CONFIG_ARCH_NETWINDER
/* Netwinder uses 1 higher than Linux */
- w977_write_reg(0x74, dma+1, efbase[i]);
+ w977_write_reg(0x74, dma + 1, efbase[i]);
#else
- w977_write_reg(0x74, dma, efbase[i]);
+ w977_write_reg(0x74, dma, efbase[i]);
#endif /* CONFIG_ARCH_NETWINDER */
- w977_write_reg(0x75, 0x04, efbase[i]); /* Disable Tx DMA */
-
- /* Set append hardware CRC, enable IR bank selection */
- w977_write_reg(0xf0, APEDCRC|ENBNKSEL, efbase[i]);
-
- /* Activate device */
- w977_write_reg(0x30, 0x01, efbase[i]);
-
- w977_efm_exit(efbase[i]);
+ w977_write_reg(0x75, 0x04, efbase[i]);/* Disable Tx DMA */
+
+ /* Set append hardware CRC, enable IR bank selection */
+ w977_write_reg(0xf0, APEDCRC | ENBNKSEL, efbase[i]);
+
+ /* Activate device */
+ w977_write_reg(0x30, 0x01, efbase[i]);
+
+ w977_efm_exit(efbase[i]);
#endif /* CONFIG_USE_W977_PNP */
- /* Disable Advanced mode */
- switch_bank(iobase, SET2);
- outb(iobase+2, 0x00);
-
- /* Turn on UART (global) interrupts */
- switch_bank(iobase, SET0);
- outb(HCR_EN_IRQ, iobase+HCR);
-
- /* Switch to advanced mode */
- switch_bank(iobase, SET2);
- outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
-
- /* Set default IR-mode */
- switch_bank(iobase, SET0);
- outb(HCR_SIR, iobase+HCR);
-
- /* Read the Advanced IR ID */
- switch_bank(iobase, SET3);
- version = inb(iobase+AUID);
-
- /* Should be 0x1? */
- if (0x10 == (version & 0xf0)) {
- efio = efbase[i];
-
- /* Set FIFO size to 32 */
- switch_bank(iobase, SET2);
- outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);
-
- /* Set FIFO threshold to TX17, RX16 */
- switch_bank(iobase, SET0);
- outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|
- UFR_EN_FIFO,iobase+UFR);
-
- /* Receiver frame length */
- switch_bank(iobase, SET4);
- outb(2048 & 0xff, iobase+6);
- outb((2048 >> 8) & 0x1f, iobase+7);
-
- /*
- * Init HP HSDL-1100 transceiver.
- *
- * Set IRX_MSL since we have 2 * receive paths IRRX,
- * and IRRXH. Clear IRSL0D since we want IRSL0 * to
- * be a input pin used for IRRXH
+ /* Disable Advanced mode */
+ switch_bank(iobase, SET2);
+ outb(iobase + 2, 0x00);
+
+ /* Turn on UART (global) interrupts */
+ switch_bank(iobase, SET0);
+ outb(HCR_EN_IRQ, iobase + HCR);
+
+ /* Switch to advanced mode */
+ switch_bank(iobase, SET2);
+ outb(inb(iobase + ADCR1) | ADCR1_ADV_SL, iobase + ADCR1);
+
+ /* Set default IR-mode */
+ switch_bank(iobase, SET0);
+ outb(HCR_SIR, iobase + HCR);
+
+ /* Read the Advanced IR ID */
+ switch_bank(iobase, SET3);
+ version = inb(iobase + AUID);
+
+ /* Should be 0x1? */
+ if (0x10 == (version & 0xf0)) {
+ efio = efbase[i];
+
+ /* Set FIFO size to 32 */
+ switch_bank(iobase, SET2);
+ outb(ADCR2_RXFS32 | ADCR2_TXFS32, iobase + ADCR2);
+
+ /* Set FIFO threshold to TX17, RX16 */
+ switch_bank(iobase, SET0);
+ outb(UFR_RXTL | UFR_TXTL | UFR_TXF_RST | UFR_RXF_RST |
+ UFR_EN_FIFO, iobase + UFR);
+
+ /* Receiver frame length */
+ switch_bank(iobase, SET4);
+ outb(2048 & 0xff, iobase + 6);
+ outb((2048 >> 8) & 0x1f, iobase + 7);
+
+ /*
+ * Init HP HSDL-1100 transceiver.
+ *
+ * Set IRX_MSL since we have 2 * receive paths IRRX,
+ * and IRRXH. Clear IRSL0D since we want IRSL0 * to
+ * be a input pin used for IRRXH
*
- * IRRX pin 37 connected to receiver
+ * IRRX pin 37 connected to receiver
* IRTX pin 38 connected to transmitter
- * FIRRX pin 39 connected to receiver (IRSL0)
+ * FIRRX pin 39 connected to receiver (IRSL0)
* CIRRX pin 40 connected to pin 37
*/
switch_bank(iobase, SET7);
- outb(0x40, iobase+7);
-
+ outb(0x40, iobase + 7);
+
net_info_ratelimited("W83977AF (IR) driver loaded. Version: 0x%02x\n",
version);
-
+
return 0;
} else {
/* Try next extented function register address */
- pr_debug("%s(), Wrong chip version", __func__);
+ pr_debug("%s: Wrong chip version\n", __func__);
}
- }
+ }
return -1;
}
static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
{
int ir_mode = HCR_SIR;
- int iobase;
+ int iobase;
__u8 set;
iobase = self->io.fir_base;
@@ -408,66 +407,67 @@ static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
self->io.speed = speed;
/* Save current bank */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
/* Disable interrupts */
switch_bank(iobase, SET0);
- outb(0, iobase+ICR);
+ outb(0, iobase + ICR);
/* Select Set 2 */
switch_bank(iobase, SET2);
- outb(0x00, iobase+ABHL);
+ outb(0x00, iobase + ABHL);
switch (speed) {
- case 9600: outb(0x0c, iobase+ABLL); break;
- case 19200: outb(0x06, iobase+ABLL); break;
- case 38400: outb(0x03, iobase+ABLL); break;
- case 57600: outb(0x02, iobase+ABLL); break;
- case 115200: outb(0x01, iobase+ABLL); break;
+ case 9600: outb(0x0c, iobase + ABLL); break;
+ case 19200: outb(0x06, iobase + ABLL); break;
+ case 38400: outb(0x03, iobase + ABLL); break;
+ case 57600: outb(0x02, iobase + ABLL); break;
+ case 115200: outb(0x01, iobase + ABLL); break;
case 576000:
ir_mode = HCR_MIR_576;
- pr_debug("%s(), handling baud of 576000\n", __func__);
+ pr_debug("%s: handling baud of 576000\n", __func__);
break;
case 1152000:
ir_mode = HCR_MIR_1152;
- pr_debug("%s(), handling baud of 1152000\n", __func__);
+ pr_debug("%s: handling baud of 1152000\n", __func__);
break;
case 4000000:
ir_mode = HCR_FIR;
- pr_debug("%s(), handling baud of 4000000\n", __func__);
+ pr_debug("%s: handling baud of 4000000\n", __func__);
break;
default:
ir_mode = HCR_FIR;
- pr_debug("%s(), unknown baud rate of %d\n", __func__ , speed);
+ pr_debug("%s: unknown baud rate of %d\n", __func__, speed);
break;
}
/* Set speed mode */
switch_bank(iobase, SET0);
- outb(ir_mode, iobase+HCR);
+ outb(ir_mode, iobase + HCR);
/* set FIFO size to 32 */
switch_bank(iobase, SET2);
- outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);
-
+ outb(ADCR2_RXFS32 | ADCR2_TXFS32, iobase + ADCR2);
+
/* set FIFO threshold to TX17, RX16 */
switch_bank(iobase, SET0);
- outb(0x00, iobase+UFR); /* Reset */
- outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
- outb(0xa7, iobase+UFR);
+ outb(0x00, iobase + UFR); /* Reset */
+ outb(UFR_EN_FIFO, iobase + UFR); /* First we must enable FIFO */
+ outb(0xa7, iobase + UFR);
netif_wake_queue(self->netdev);
-
+
/* Enable some interrupts so we can receive frames */
switch_bank(iobase, SET0);
if (speed > PIO_MAX_SPEED) {
- outb(ICR_EFSFI, iobase+ICR);
+ outb(ICR_EFSFI, iobase + ICR);
w83977af_dma_receive(self);
- } else
- outb(ICR_ERBRI, iobase+ICR);
-
+ } else {
+ outb(ICR_ERBRI, iobase + ICR);
+ }
+
/* Restore SSR */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
}
/*
@@ -477,69 +477,68 @@ static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
*
*/
static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
- struct net_device *dev)
+ struct net_device *dev)
{
struct w83977af_ir *self;
__s32 speed;
int iobase;
__u8 set;
int mtt;
-
+
self = netdev_priv(dev);
iobase = self->io.fir_base;
- pr_debug("%s(%ld), skb->len=%d\n", __func__ , jiffies,
- (int)skb->len);
-
+ pr_debug("%s: %ld, skb->len=%d\n", __func__, jiffies, (int)skb->len);
+
/* Lock transmit buffer */
netif_stop_queue(dev);
-
+
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
- w83977af_change_speed(self, speed);
+ w83977af_change_speed(self, speed);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
- } else
- self->new_speed = speed;
+ }
+ self->new_speed = speed;
}
/* Save current set */
- set = inb(iobase+SSR);
-
+ set = inb(iobase + SSR);
+
/* Decide if we should use PIO or DMA transfer */
if (self->io.speed > PIO_MAX_SPEED) {
self->tx_buff.data = self->tx_buff.head;
skb_copy_from_linear_data(skb, self->tx_buff.data, skb->len);
self->tx_buff.len = skb->len;
-
+
mtt = irda_get_mtt(skb);
- pr_debug("%s(%ld), mtt=%d\n", __func__ , jiffies, mtt);
+ pr_debug("%s: %ld, mtt=%d\n", __func__, jiffies, mtt);
if (mtt > 1000)
- mdelay(mtt/1000);
+ mdelay(mtt / 1000);
else if (mtt)
- udelay(mtt);
+ udelay(mtt);
- /* Enable DMA interrupt */
- switch_bank(iobase, SET0);
- outb(ICR_EDMAI, iobase+ICR);
- w83977af_dma_write(self, iobase);
+ /* Enable DMA interrupt */
+ switch_bank(iobase, SET0);
+ outb(ICR_EDMAI, iobase + ICR);
+ w83977af_dma_write(self, iobase);
} else {
self->tx_buff.data = self->tx_buff.head;
- self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
-
+
/* Add interrupt on tx low level (will fire immediately) */
switch_bank(iobase, SET0);
- outb(ICR_ETXTHI, iobase+ICR);
+ outb(ICR_ETXTHI, iobase + ICR);
}
dev_kfree_skb(skb);
/* Restore set register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return NETDEV_TX_OK;
}
@@ -553,64 +552,64 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
{
__u8 set;
- pr_debug("%s(), len=%d\n", __func__ , self->tx_buff.len);
+
+ pr_debug("%s: len=%d\n", __func__, self->tx_buff.len);
/* Save current set */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
/* Disable DMA */
switch_bank(iobase, SET0);
- outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+ outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR);
- /* Choose transmit DMA channel */
+ /* Choose transmit DMA channel */
switch_bank(iobase, SET2);
- outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
+ outb(ADCR1_D_CHSW | /*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase + ADCR1);
irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
- DMA_MODE_WRITE);
+ DMA_MODE_WRITE);
self->io.direction = IO_XMIT;
-
+
/* Enable DMA */
- switch_bank(iobase, SET0);
- outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
+ switch_bank(iobase, SET0);
+ outb(inb(iobase + HCR) | HCR_EN_DMA | HCR_TX_WT, iobase + HCR);
/* Restore set register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
}
/*
* Function w83977af_pio_write (iobase, buf, len, fifo_size)
*
- *
+ *
*
*/
static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
{
int actual = 0;
__u8 set;
-
+
/* Save current bank */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
switch_bank(iobase, SET0);
- if (!(inb_p(iobase+USR) & USR_TSRE)) {
- pr_debug("%s(), warning, FIFO not empty yet!\n", __func__);
+ if (!(inb_p(iobase + USR) & USR_TSRE)) {
+ pr_debug("%s: warning, FIFO not empty yet!\n", __func__);
fifo_size -= 17;
- pr_debug("%s(), %d bytes left in tx fifo\n",
- __func__ , fifo_size);
+ pr_debug("%s: %d bytes left in tx fifo\n", __func__, fifo_size);
}
/* Fill FIFO with current frame */
while ((fifo_size-- > 0) && (actual < len)) {
/* Transmit next byte */
- outb(buf[actual++], iobase+TBR);
+ outb(buf[actual++], iobase + TBR);
}
-
- pr_debug("%s(), fifo_size %d ; %d sent of %d\n",
- __func__ , fifo_size, actual, len);
+
+ pr_debug("%s: fifo_size %d ; %d sent of %d\n",
+ __func__, fifo_size, actual, len);
/* Restore bank */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return actual;
}
@@ -620,39 +619,39 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
*
* The transfer of a frame in finished. So do the necessary things
*
- *
+ *
*/
static void w83977af_dma_xmit_complete(struct w83977af_ir *self)
{
int iobase;
__u8 set;
- pr_debug("%s(%ld)\n", __func__ , jiffies);
+ pr_debug("%s: %ld\n", __func__, jiffies);
- IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self, return;);
iobase = self->io.fir_base;
/* Save current set */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
/* Disable DMA */
switch_bank(iobase, SET0);
- outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
-
+ outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR);
+
/* Check for underrun! */
- if (inb(iobase+AUDR) & AUDR_UNDR) {
- pr_debug("%s(), Transmit underrun!\n", __func__);
-
+ if (inb(iobase + AUDR) & AUDR_UNDR) {
+ pr_debug("%s: Transmit underrun!\n", __func__);
+
self->netdev->stats.tx_errors++;
self->netdev->stats.tx_fifo_errors++;
/* Clear bit, by writing 1 to it */
- outb(AUDR_UNDR, iobase+AUDR);
- } else
+ outb(AUDR_UNDR, iobase + AUDR);
+ } else {
self->netdev->stats.tx_packets++;
+ }
-
if (self->new_speed) {
w83977af_change_speed(self, self->new_speed);
self->new_speed = 0;
@@ -661,9 +660,9 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self)
/* Unlock tx_buff and request another frame */
/* Tell the network layer, that we want more frames */
netif_wake_queue(self->netdev);
-
+
/* Restore set */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
}
/*
@@ -681,23 +680,23 @@ static int w83977af_dma_receive(struct w83977af_ir *self)
unsigned long flags;
__u8 hcr;
#endif
- IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self, return -1;);
pr_debug("%s\n", __func__);
- iobase= self->io.fir_base;
+ iobase = self->io.fir_base;
/* Save current set */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
/* Disable DMA */
switch_bank(iobase, SET0);
- outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+ outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR);
/* Choose DMA Rx, DMA Fairness, and Advanced mode */
switch_bank(iobase, SET2);
- outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
- iobase+ADCR1);
+ outb((inb(iobase + ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/ | ADCR1_ADV_SL,
+ iobase + ADCR1);
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
@@ -714,27 +713,27 @@ static int w83977af_dma_receive(struct w83977af_ir *self)
irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
DMA_MODE_READ);
#endif
- /*
- * Reset Rx FIFO. This will also flush the ST_FIFO, it's very
+ /*
+ * Reset Rx FIFO. This will also flush the ST_FIFO, it's very
* important that we don't reset the Tx FIFO since it might not
* be finished transmitting yet
*/
switch_bank(iobase, SET0);
- outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+ outb(UFR_RXTL | UFR_TXTL | UFR_RXF_RST | UFR_EN_FIFO, iobase + UFR);
self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
-
+
/* Enable DMA */
switch_bank(iobase, SET0);
#ifdef CONFIG_ARCH_NETWINDER
- hcr = inb(iobase+HCR);
- outb(hcr | HCR_EN_DMA, iobase+HCR);
+ hcr = inb(iobase + HCR);
+ outb(hcr | HCR_EN_DMA, iobase + HCR);
enable_dma(self->io.dma);
spin_unlock_irqrestore(&self->lock, flags);
-#else
- outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+#else
+ outb(inb(iobase + HCR) | HCR_EN_DMA, iobase + HCR);
#endif
/* Restore set */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return 0;
}
@@ -761,22 +760,22 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
iobase = self->io.fir_base;
/* Save current set */
- set = inb(iobase+SSR);
-
+ set = inb(iobase + SSR);
+
iobase = self->io.fir_base;
/* Read status FIFO */
switch_bank(iobase, SET5);
- while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) {
+ while ((status = inb(iobase + FS_FO)) & FS_FO_FSFDR) {
st_fifo->entries[st_fifo->tail].status = status;
-
- st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
- st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-
+
+ st_fifo->entries[st_fifo->tail].len = inb(iobase + RFLFL);
+ st_fifo->entries[st_fifo->tail].len |= inb(iobase + RFLFH) << 8;
+
st_fifo->tail++;
st_fifo->len++;
}
-
+
while (st_fifo->len) {
/* Get first entry */
status = st_fifo->entries[st_fifo->head].status;
@@ -792,53 +791,52 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
} else {
/* Skip frame */
self->netdev->stats.rx_errors++;
-
+
self->rx_buff.data += len;
-
+
if (status & FS_FO_MX_LEX)
self->netdev->stats.rx_length_errors++;
-
- if (status & FS_FO_PHY_ERR)
+
+ if (status & FS_FO_PHY_ERR)
self->netdev->stats.rx_frame_errors++;
-
- if (status & FS_FO_CRC_ERR)
+
+ if (status & FS_FO_CRC_ERR)
self->netdev->stats.rx_crc_errors++;
}
/* The errors below can be reported in both cases */
if (status & FS_FO_RX_OV)
self->netdev->stats.rx_fifo_errors++;
-
+
if (status & FS_FO_FSF_OV)
self->netdev->stats.rx_fifo_errors++;
-
+
} else {
/* Check if we have transferred all data to memory */
switch_bank(iobase, SET0);
- if (inb(iobase+USR) & USR_RDR) {
+ if (inb(iobase + USR) & USR_RDR)
udelay(80); /* Should be enough!? */
- }
-
- skb = dev_alloc_skb(len+1);
- if (skb == NULL) {
- printk(KERN_INFO
- "%s(), memory squeeze, dropping frame.\n", __func__);
+
+ skb = dev_alloc_skb(len + 1);
+ if (!skb) {
+ pr_info("%s: memory squeeze, dropping frame\n",
+ __func__);
/* Restore set register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return FALSE;
}
-
+
/* Align to 20 bytes */
- skb_reserve(skb, 1);
-
+ skb_reserve(skb, 1);
+
/* Copy frame without CRC */
if (self->io.speed < 4000000) {
- skb_put(skb, len-2);
+ skb_put(skb, len - 2);
skb_copy_to_linear_data(skb,
self->rx_buff.data,
len - 2);
} else {
- skb_put(skb, len-4);
+ skb_put(skb, len - 4);
skb_copy_to_linear_data(skb,
self->rx_buff.data,
len - 4);
@@ -847,7 +845,7 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
/* Move to next frame */
self->rx_buff.data += len;
self->netdev->stats.rx_packets++;
-
+
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
@@ -855,7 +853,7 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
}
}
/* Restore set register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return TRUE;
}
@@ -866,21 +864,21 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
* Receive all data in receiver FIFO
*
*/
-static void w83977af_pio_receive(struct w83977af_ir *self)
+static void w83977af_pio_receive(struct w83977af_ir *self)
{
__u8 byte = 0x00;
int iobase;
- IRDA_ASSERT(self != NULL, return;);
-
+ IRDA_ASSERT(self, return;);
+
iobase = self->io.fir_base;
-
+
/* Receive all characters in Rx FIFO */
do {
- byte = inb(iobase+RBR);
+ byte = inb(iobase + RBR);
async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff,
byte);
- } while (inb(iobase+USR) & USR_RDR); /* Data available */
+ } while (inb(iobase + USR) & USR_RDR); /* Data available */
}
/*
@@ -896,30 +894,30 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
__u8 set;
int iobase;
- pr_debug("%s(), isr=%#x\n", __func__ , isr);
-
+ pr_debug("%s: isr=%#x\n", __func__, isr);
+
iobase = self->io.fir_base;
/* Transmit FIFO low on data */
if (isr & ISR_TXTH_I) {
/* Write data left in transmit buffer */
- actual = w83977af_pio_write(self->io.fir_base,
- self->tx_buff.data,
- self->tx_buff.len,
+ actual = w83977af_pio_write(self->io.fir_base,
+ self->tx_buff.data,
+ self->tx_buff.len,
self->io.fifo_size);
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
-
+
self->io.direction = IO_XMIT;
/* Check if finished */
if (self->tx_buff.len > 0) {
new_icr |= ICR_ETXTHI;
} else {
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
switch_bank(iobase, SET0);
- outb(AUDR_SFEND, iobase+AUDR);
- outb(set, iobase+SSR);
+ outb(AUDR_SFEND, iobase + AUDR);
+ outb(set, iobase + SSR);
self->netdev->stats.tx_packets++;
@@ -929,10 +927,10 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
}
}
/* Check if transmission has completed */
- if (isr & ISR_TXEMP_I) {
+ if (isr & ISR_TXEMP_I) {
/* Check if we need to change the speed? */
if (self->new_speed) {
- pr_debug("%s(), Changing speed!\n", __func__);
+ pr_debug("%s: Changing speed!\n", __func__);
w83977af_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -965,12 +963,11 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
int iobase;
iobase = self->io.fir_base;
- set = inb(iobase+SSR);
-
+ set = inb(iobase + SSR);
+
/* End of frame detected in FIFO */
- if (isr & (ISR_FEND_I|ISR_FSF_I)) {
+ if (isr & (ISR_FEND_I | ISR_FSF_I)) {
if (w83977af_dma_receive_complete(self)) {
-
/* Wait for next status FIFO interrupt */
new_icr |= ICR_EFSFI;
} else {
@@ -978,11 +975,11 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
/* Set timer value, resolution 1 ms */
switch_bank(iobase, SET4);
- outb(0x01, iobase+TMRL); /* 1 ms */
- outb(0x00, iobase+TMRH);
+ outb(0x01, iobase + TMRL); /* 1 ms */
+ outb(0x00, iobase + TMRH);
/* Start timer */
- outb(IR_MSL_EN_TMR, iobase+IR_MSL);
+ outb(IR_MSL_EN_TMR, iobase + IR_MSL);
new_icr |= ICR_ETMRI;
}
@@ -991,11 +988,11 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
if (isr & ISR_TMR_I) {
/* Disable timer */
switch_bank(iobase, SET4);
- outb(0, iobase+IR_MSL);
+ outb(0, iobase + IR_MSL);
/* Clear timer event */
/* switch_bank(iobase, SET0); */
-/* outb(ASCR_CTE, iobase+ASCR); */
+/* outb(ASCR_CTE, iobase+ASCR); */
/* Check if this is a TX timer interrupt */
if (self->io.direction == IO_XMIT) {
@@ -1008,25 +1005,25 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
new_icr |= ICR_EFSFI;
}
- }
+ }
/* Finished with DMA */
if (isr & ISR_DMA_I) {
w83977af_dma_xmit_complete(self);
/* Check if there are more frames to be transmitted */
/* if (irda_device_txqueue_empty(self)) { */
-
- /* Prepare for receive
- *
+
+ /* Prepare for receive
+ *
* ** Netwinder Tx DMA likes that we do this anyway **
*/
w83977af_dma_receive(self);
new_icr = ICR_EFSFI;
- /* } */
+ /* } */
}
-
+
/* Restore set */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return new_icr;
}
@@ -1049,24 +1046,24 @@ static irqreturn_t w83977af_interrupt(int irq, void *dev_id)
iobase = self->io.fir_base;
/* Save current bank */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
switch_bank(iobase, SET0);
-
- icr = inb(iobase+ICR);
- isr = inb(iobase+ISR) & icr; /* Mask out the interesting ones */
- outb(0, iobase+ICR); /* Disable interrupts */
-
+ icr = inb(iobase + ICR);
+ isr = inb(iobase + ISR) & icr; /* Mask out the interesting ones */
+
+ outb(0, iobase + ICR); /* Disable interrupts */
+
if (isr) {
/* Dispatch interrupt handler for the current speed */
- if (self->io.speed > PIO_MAX_SPEED )
+ if (self->io.speed > PIO_MAX_SPEED)
icr = w83977af_fir_interrupt(self, isr);
else
icr = w83977af_sir_interrupt(self, isr);
}
- outb(icr, iobase+ICR); /* Restore (new) interrupts */
- outb(set, iobase+SSR); /* Restore bank register */
+ outb(icr, iobase + ICR); /* Restore (new) interrupts */
+ outb(set, iobase + SSR); /* Restore bank register */
return IRQ_RETVAL(isr);
}
@@ -1082,22 +1079,23 @@ static int w83977af_is_receiving(struct w83977af_ir *self)
int iobase;
__u8 set;
- IRDA_ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self, return FALSE;);
if (self->io.speed > 115200) {
iobase = self->io.fir_base;
/* Check if rx FIFO is not empty */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
switch_bank(iobase, SET2);
- if ((inb(iobase+RXFDTH) & 0x3f) != 0) {
+ if ((inb(iobase + RXFDTH) & 0x3f) != 0) {
/* We are receiving something */
status = TRUE;
}
- outb(set, iobase+SSR);
- } else
+ outb(set, iobase + SSR);
+ } else {
status = (self->rx_buff.state != OUTSIDE_FRAME);
-
+ }
+
return status;
}
@@ -1113,17 +1111,16 @@ static int w83977af_net_open(struct net_device *dev)
int iobase;
char hwname[32];
__u8 set;
-
-
- IRDA_ASSERT(dev != NULL, return -1;);
+
+ IRDA_ASSERT(dev, return -1;);
self = netdev_priv(dev);
-
- IRDA_ASSERT(self != NULL, return 0;);
-
+
+ IRDA_ASSERT(self, return 0;);
+
iobase = self->io.fir_base;
- if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name,
- (void *) dev)) {
+ if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name,
+ (void *)dev)) {
return -EAGAIN;
}
/*
@@ -1134,30 +1131,31 @@ static int w83977af_net_open(struct net_device *dev)
free_irq(self->io.irq, dev);
return -EAGAIN;
}
-
+
/* Save current set */
- set = inb(iobase+SSR);
+ set = inb(iobase + SSR);
- /* Enable some interrupts so we can receive frames again */
- switch_bank(iobase, SET0);
- if (self->io.speed > 115200) {
- outb(ICR_EFSFI, iobase+ICR);
- w83977af_dma_receive(self);
- } else
- outb(ICR_ERBRI, iobase+ICR);
+ /* Enable some interrupts so we can receive frames again */
+ switch_bank(iobase, SET0);
+ if (self->io.speed > 115200) {
+ outb(ICR_EFSFI, iobase + ICR);
+ w83977af_dma_receive(self);
+ } else {
+ outb(ICR_ERBRI, iobase + ICR);
+ }
/* Restore bank register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
/* Ready to play! */
netif_start_queue(dev);
-
+
/* Give self a hardware name */
sprintf(hwname, "w83977af @ 0x%03x", self->io.fir_base);
- /*
+ /*
* Open new IrLAP layer instance, now that everything should be
- * initialized properly
+ * initialized properly
*/
self->irlap = irlap_open(dev, &self->qos, hwname);
@@ -1176,17 +1174,17 @@ static int w83977af_net_close(struct net_device *dev)
int iobase;
__u8 set;
- IRDA_ASSERT(dev != NULL, return -1;);
-
+ IRDA_ASSERT(dev, return -1;);
+
self = netdev_priv(dev);
-
- IRDA_ASSERT(self != NULL, return 0;);
-
+
+ IRDA_ASSERT(self, return 0;);
+
iobase = self->io.fir_base;
/* Stop device */
netif_stop_queue(dev);
-
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
@@ -1195,17 +1193,17 @@ static int w83977af_net_close(struct net_device *dev)
disable_dma(self->io.dma);
/* Save current set */
- set = inb(iobase+SSR);
-
+ set = inb(iobase + SSR);
+
/* Disable interrupts */
switch_bank(iobase, SET0);
- outb(0, iobase+ICR);
+ outb(0, iobase + ICR);
free_irq(self->io.irq, dev);
free_dma(self->io.dma);
/* Restore bank register */
- outb(set, iobase+SSR);
+ outb(set, iobase + SSR);
return 0;
}
@@ -1218,19 +1216,19 @@ static int w83977af_net_close(struct net_device *dev)
*/
static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct if_irda_req *irq = (struct if_irda_req *) rq;
+ struct if_irda_req *irq = (struct if_irda_req *)rq;
struct w83977af_ir *self;
unsigned long flags;
int ret = 0;
- IRDA_ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev, return -1;);
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self, return -1;);
+
+ pr_debug("%s: %s, (cmd=0x%X)\n", __func__, dev->name, cmd);
- pr_debug("%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd);
-
spin_lock_irqsave(&self->lock, flags);
switch (cmd) {
@@ -1263,7 +1261,6 @@ MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
MODULE_LICENSE("GPL");
-
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Mimimum Turn Time");
module_param_array(io, int, NULL, 0);
@@ -1274,7 +1271,7 @@ MODULE_PARM_DESC(irq, "IRQ lines");
/*
* Function init_module (void)
*
- *
+ *
*
*/
module_init(w83977af_init);
@@ -1282,7 +1279,7 @@ module_init(w83977af_init);
/*
* Function cleanup_module (void)
*
- *
+ *
*
*/
module_exit(w83977af_cleanup);
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index d2e61e002926..f83cf6696820 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -1431,14 +1431,7 @@ static void clear_tx_sa(struct macsec_tx_sa *tx_sa)
macsec_txsa_put(tx_sa);
}
-static struct genl_family macsec_fam = {
- .id = GENL_ID_GENERATE,
- .name = MACSEC_GENL_NAME,
- .hdrsize = 0,
- .version = MACSEC_GENL_VERSION,
- .maxattr = MACSEC_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family macsec_fam;
static struct net_device *get_dev_from_nl(struct net *net,
struct nlattr **attrs)
@@ -2665,6 +2658,17 @@ static const struct genl_ops macsec_genl_ops[] = {
},
};
+static struct genl_family macsec_fam __ro_after_init = {
+ .name = MACSEC_GENL_NAME,
+ .hdrsize = 0,
+ .version = MACSEC_GENL_VERSION,
+ .maxattr = MACSEC_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = macsec_genl_ops,
+ .n_ops = ARRAY_SIZE(macsec_genl_ops),
+};
+
static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -2980,6 +2984,8 @@ static void macsec_free_netdev(struct net_device *dev)
static void macsec_setup(struct net_device *dev)
{
ether_setup(dev);
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
dev->netdev_ops = &macsec_netdev_ops;
dev->destructor = macsec_free_netdev;
@@ -3340,19 +3346,18 @@ static struct net *macsec_get_link_net(const struct net_device *dev)
static size_t macsec_get_size(const struct net_device *dev)
{
- return 0 +
- nla_total_size_64bit(8) + /* SCI */
- nla_total_size(1) + /* ICV_LEN */
- nla_total_size_64bit(8) + /* CIPHER_SUITE */
- nla_total_size(4) + /* WINDOW */
- nla_total_size(1) + /* ENCODING_SA */
- nla_total_size(1) + /* ENCRYPT */
- nla_total_size(1) + /* PROTECT */
- nla_total_size(1) + /* INC_SCI */
- nla_total_size(1) + /* ES */
- nla_total_size(1) + /* SCB */
- nla_total_size(1) + /* REPLAY_PROTECT */
- nla_total_size(1) + /* VALIDATION */
+ return nla_total_size_64bit(8) + /* IFLA_MACSEC_SCI */
+ nla_total_size(1) + /* IFLA_MACSEC_ICV_LEN */
+ nla_total_size_64bit(8) + /* IFLA_MACSEC_CIPHER_SUITE */
+ nla_total_size(4) + /* IFLA_MACSEC_WINDOW */
+ nla_total_size(1) + /* IFLA_MACSEC_ENCODING_SA */
+ nla_total_size(1) + /* IFLA_MACSEC_ENCRYPT */
+ nla_total_size(1) + /* IFLA_MACSEC_PROTECT */
+ nla_total_size(1) + /* IFLA_MACSEC_INC_SCI */
+ nla_total_size(1) + /* IFLA_MACSEC_ES */
+ nla_total_size(1) + /* IFLA_MACSEC_SCB */
+ nla_total_size(1) + /* IFLA_MACSEC_REPLAY_PROTECT */
+ nla_total_size(1) + /* IFLA_MACSEC_VALIDATION */
0;
}
@@ -3470,7 +3475,7 @@ static int __init macsec_init(void)
if (err)
goto notifier;
- err = genl_register_family_with_ops(&macsec_fam, macsec_genl_ops);
+ err = genl_register_family(&macsec_fam);
if (err)
goto rtnl;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 26d6f0bbe14b..20b3fdf282c5 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -43,7 +43,6 @@ struct macvlan_port {
struct net_device *dev;
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
struct list_head vlans;
- struct rcu_head rcu;
struct sk_buff_head bc_queue;
struct work_struct bc_work;
bool passthru;
@@ -179,20 +178,20 @@ static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
macvlan_hash_add(vlan);
}
-static int macvlan_addr_busy(const struct macvlan_port *port,
- const unsigned char *addr)
+static bool macvlan_addr_busy(const struct macvlan_port *port,
+ const unsigned char *addr)
{
/* Test to see if the specified multicast address is
* currently in use by the underlying device or
* another macvlan.
*/
if (ether_addr_equal_64bits(port->dev->dev_addr, addr))
- return 1;
+ return true;
if (macvlan_hash_lookup(port, addr))
- return 1;
+ return true;
- return 0;
+ return false;
}
@@ -400,8 +399,7 @@ static void macvlan_forward_source(struct sk_buff *skb,
hlist_for_each_entry_rcu(entry, h, hlist) {
if (ether_addr_equal_64bits(entry->addr, addr))
- if (entry->vlan->dev->flags & IFF_UP)
- macvlan_forward_source_one(skb, entry->vlan);
+ macvlan_forward_source_one(skb, entry->vlan);
}
}
@@ -778,7 +776,7 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
{
struct macvlan_dev *vlan = netdev_priv(dev);
- if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
+ if (vlan->lowerdev->mtu < new_mtu)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
@@ -1086,6 +1084,8 @@ void macvlan_common_setup(struct net_device *dev)
{
ether_setup(dev);
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
netif_keep_dst(dev);
dev->priv_flags |= IFF_UNICAST_FLT;
@@ -1150,7 +1150,7 @@ static void macvlan_port_destroy(struct net_device *dev)
cancel_work_sync(&port->bc_work);
__skb_queue_purge(&port->bc_queue);
- kfree_rcu(port, rcu);
+ kfree(port);
}
static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1299,6 +1299,10 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
else if (dev->mtu > lowerdev->mtu)
return -EINVAL;
+ /* MTU range: 68 - lowerdev->max_mtu */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = lowerdev->max_mtu;
+
if (!tb[IFLA_ADDRESS])
eth_hw_addr_random(dev);
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 7869b0651576..52a9d811be06 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -437,7 +437,7 @@ static int macvtap_get_minor(struct macvlan_dev *vlan)
if (retval >= 0) {
vlan->minor = retval;
} else if (retval == -ENOSPC) {
- printk(KERN_ERR "too many macvtap devices\n");
+ netdev_err(vlan->dev, "Too many macvtap devices\n");
retval = -EINVAL;
}
mutex_unlock(&minor_lock);
@@ -826,9 +826,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
if (iov_iter_count(iter) < vnet_hdr_len)
return -EINVAL;
- ret = virtio_net_hdr_from_skb(skb, &vnet_hdr,
- macvtap_is_little_endian(q));
- if (ret)
+ if (virtio_net_hdr_from_skb(skb, &vnet_hdr,
+ macvtap_is_little_endian(q)))
BUG();
if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index 993570b1e2ae..6d953c53eed6 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -135,6 +135,103 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
}
/**
+ * mii_ethtool_get_link_ksettings - get settings that are specified in @cmd
+ * @mii: MII interface
+ * @cmd: requested ethtool_link_ksettings
+ *
+ * The @cmd parameter is expected to have been cleared before calling
+ * mii_ethtool_get_link_ksettings().
+ *
+ * Returns 0 for success, negative on error.
+ */
+int mii_ethtool_get_link_ksettings(struct mii_if_info *mii,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct net_device *dev = mii->dev;
+ u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0;
+ u32 nego, supported, advertising, lp_advertising;
+
+ supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+ if (mii->supports_gmii)
+ supported |= SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
+
+ /* only supports twisted-pair */
+ cmd->base.port = PORT_MII;
+
+ /* this isn't fully supported at higher layers */
+ cmd->base.phy_address = mii->phy_id;
+ cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;
+
+ advertising = ADVERTISED_TP | ADVERTISED_MII;
+
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR);
+ if (mii->supports_gmii) {
+ ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+ stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
+ }
+ if (bmcr & BMCR_ANENABLE) {
+ advertising |= ADVERTISED_Autoneg;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+
+ advertising |= mii_get_an(mii, MII_ADVERTISE);
+ if (mii->supports_gmii)
+ advertising |= mii_ctrl1000_to_ethtool_adv_t(ctrl1000);
+
+ if (bmsr & BMSR_ANEGCOMPLETE) {
+ lp_advertising = mii_get_an(mii, MII_LPA);
+ lp_advertising |=
+ mii_stat1000_to_ethtool_lpa_t(stat1000);
+ } else {
+ lp_advertising = 0;
+ }
+
+ nego = advertising & lp_advertising;
+
+ if (nego & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half)) {
+ cmd->base.speed = SPEED_1000;
+ cmd->base.duplex = !!(nego & ADVERTISED_1000baseT_Full);
+ } else if (nego & (ADVERTISED_100baseT_Full |
+ ADVERTISED_100baseT_Half)) {
+ cmd->base.speed = SPEED_100;
+ cmd->base.duplex = !!(nego & ADVERTISED_100baseT_Full);
+ } else {
+ cmd->base.speed = SPEED_10;
+ cmd->base.duplex = !!(nego & ADVERTISED_10baseT_Full);
+ }
+ } else {
+ cmd->base.autoneg = AUTONEG_DISABLE;
+
+ cmd->base.speed = ((bmcr & BMCR_SPEED1000 &&
+ (bmcr & BMCR_SPEED100) == 0) ?
+ SPEED_1000 :
+ ((bmcr & BMCR_SPEED100) ?
+ SPEED_100 : SPEED_10));
+ cmd->base.duplex = (bmcr & BMCR_FULLDPLX) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+
+ lp_advertising = 0;
+ }
+
+ mii->full_duplex = cmd->base.duplex;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
+ lp_advertising);
+
+ /* ignore maxtxpkt, maxrxpkt for now */
+
+ return 0;
+}
+
+/**
* mii_ethtool_sset - set settings that are specified in @ecmd
* @mii: MII interface
* @ecmd: requested ethtool_cmd
@@ -227,6 +324,104 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
}
/**
+ * mii_ethtool_set_link_ksettings - set settings that are specified in @cmd
+ * @mii: MII interfaces
+ * @cmd: requested ethtool_link_ksettings
+ *
+ * Returns 0 for success, negative on error.
+ */
+int mii_ethtool_set_link_ksettings(struct mii_if_info *mii,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct net_device *dev = mii->dev;
+ u32 speed = cmd->base.speed;
+
+ if (speed != SPEED_10 &&
+ speed != SPEED_100 &&
+ speed != SPEED_1000)
+ return -EINVAL;
+ if (cmd->base.duplex != DUPLEX_HALF && cmd->base.duplex != DUPLEX_FULL)
+ return -EINVAL;
+ if (cmd->base.port != PORT_MII)
+ return -EINVAL;
+ if (cmd->base.phy_address != mii->phy_id)
+ return -EINVAL;
+ if (cmd->base.autoneg != AUTONEG_DISABLE &&
+ cmd->base.autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+ if ((speed == SPEED_1000) && (!mii->supports_gmii))
+ return -EINVAL;
+
+ /* ignore supported, maxtxpkt, maxrxpkt */
+
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
+ u32 bmcr, advert, tmp;
+ u32 advert2 = 0, tmp2 = 0;
+ u32 advertising;
+
+ ethtool_convert_link_mode_to_legacy_u32(
+ &advertising, cmd->link_modes.advertising);
+
+ if ((advertising & (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full)) == 0)
+ return -EINVAL;
+
+ /* advertise only what has been requested */
+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (mii->supports_gmii) {
+ advert2 = mii->mdio_read(dev, mii->phy_id,
+ MII_CTRL1000);
+ tmp2 = advert2 &
+ ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ }
+ tmp |= ethtool_adv_to_mii_adv_t(advertising);
+
+ if (mii->supports_gmii)
+ tmp2 |= ethtool_adv_to_mii_ctrl1000_t(advertising);
+ if (advert != tmp) {
+ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
+ mii->advertising = tmp;
+ }
+ if ((mii->supports_gmii) && (advert2 != tmp2))
+ mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
+
+ /* turn on autonegotiation, and force a renegotiate */
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+ mii->force_media = 0;
+ } else {
+ u32 bmcr, tmp;
+
+ /* turn off auto negotiation, set speed and duplexity */
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
+ BMCR_SPEED1000 | BMCR_FULLDPLX);
+ if (speed == SPEED_1000)
+ tmp |= BMCR_SPEED1000;
+ else if (speed == SPEED_100)
+ tmp |= BMCR_SPEED100;
+ if (cmd->base.duplex == DUPLEX_FULL) {
+ tmp |= BMCR_FULLDPLX;
+ mii->full_duplex = 1;
+ } else {
+ mii->full_duplex = 0;
+ }
+ if (bmcr != tmp)
+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
+
+ mii->force_media = 1;
+ }
+ return 0;
+}
+
+/**
* mii_check_gmii_support - check if the MII supports Gb interfaces
* @mii: the MII interface
*/
@@ -466,7 +661,9 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mii_link_ok);
EXPORT_SYMBOL(mii_nway_restart);
EXPORT_SYMBOL(mii_ethtool_gset);
+EXPORT_SYMBOL(mii_ethtool_get_link_ksettings);
EXPORT_SYMBOL(mii_ethtool_sset);
+EXPORT_SYMBOL(mii_ethtool_set_link_ksettings);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
EXPORT_SYMBOL(mii_check_gmii_support);
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index 7b7c70e2341e..2de7faee9b19 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -27,24 +27,6 @@ static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static int nlmon_is_valid_mtu(int new_mtu)
-{
- /* Note that in netlink we do not really have an upper limit. On
- * default, we use NLMSG_GOODSIZE. Here at least we should make
- * sure that it's at least the header size.
- */
- return new_mtu >= (int) sizeof(struct nlmsghdr);
-}
-
-static int nlmon_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (!nlmon_is_valid_mtu(new_mtu))
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
static int nlmon_dev_init(struct net_device *dev)
{
dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
@@ -124,7 +106,6 @@ static const struct net_device_ops nlmon_ops = {
.ndo_stop = nlmon_close,
.ndo_start_xmit = nlmon_xmit,
.ndo_get_stats64 = nlmon_get_stats64,
- .ndo_change_mtu = nlmon_change_mtu,
};
static void nlmon_setup(struct net_device *dev)
@@ -145,6 +126,7 @@ static void nlmon_setup(struct net_device *dev)
* expected in most cases.
*/
dev->mtu = NLMSG_GOODSIZE;
+ dev->min_mtu = sizeof(struct nlmsghdr);
}
static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[])
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index a9acf7156855..36877ba65516 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -433,6 +433,9 @@ static int ntb_netdev_probe(struct device *client_dev)
ndev->netdev_ops = &ntb_netdev_ops;
ndev->ethtool_ops = &ntb_ethtool_ops;
+ ndev->min_mtu = 0;
+ ndev->max_mtu = ETH_MAX_MTU;
+
dev->qp = ntb_transport_create_queue(ndev, client_dev,
&ntb_netdev_handlers);
if (!dev->qp) {
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 2651c8d8de2f..d361835b315d 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -15,6 +15,19 @@ if PHYLIB
config SWPHY
bool
+config LED_TRIGGER_PHY
+ bool "Support LED triggers for tracking link state"
+ depends on LEDS_TRIGGERS
+ ---help---
+ Adds support for a set of LED trigger events per-PHY. Link
+ state change will trigger the events, for consumption by an
+ LED class driver. There are triggers for each link speed currently
+ supported by the phy, and are of the form:
+ <mii bus id>:<phy>:<speed>
+
+ Where speed is in the form:
+ <Speed in megabits>Mbps or <Speed in gigabits>Gbps
+
comment "MDIO bus device drivers"
config MDIO_BCM_IPROC
@@ -204,7 +217,7 @@ config BROADCOM_PHY
select BCM_NET_PHYLIB
---help---
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
- BCM5481 and BCM5482 PHYs.
+ BCM5481, BCM54810 and BCM5482 PHYs.
config CICADA_PHY
tristate "Cicada PHYs"
@@ -264,6 +277,11 @@ config MARVELL_PHY
---help---
Currently has a driver for the 88E1011S
+config MESON_GXL_PHY
+ tristate "Amlogic Meson GXL Internal PHY"
+ ---help---
+ Currently has a driver for the Amlogic Meson GXL Internal PHY
+
config MICREL_PHY
tristate "Micrel PHYs"
---help---
@@ -277,7 +295,7 @@ config MICROCHIP_PHY
config MICROSEMI_PHY
tristate "Microsemi PHYs"
---help---
- Currently supports the VSC8531 and VSC8541 PHYs
+ Currently supports VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
config NATIONAL_PHY
tristate "National Semiconductor PHYs"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e58667d111e7..356859ac7c18 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -2,6 +2,7 @@
libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o
libphy-$(CONFIG_SWPHY) += swphy.o
+libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o
obj-$(CONFIG_PHYLIB) += libphy.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o
+obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 09b0b0aa8d68..e8ae50e1255e 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -21,6 +21,8 @@
#define PHY_ID_AQ1202 0x03a1b445
#define PHY_ID_AQ2104 0x03a1b460
#define PHY_ID_AQR105 0x03a1b4a2
+#define PHY_ID_AQR106 0x03a1b4d0
+#define PHY_ID_AQR107 0x03a1b4e0
#define PHY_ID_AQR405 0x03a1b4b0
#define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \
@@ -154,6 +156,30 @@ static struct phy_driver aquantia_driver[] = {
.read_status = aquantia_read_status,
},
{
+ .phy_id = PHY_ID_AQR106,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Aquantia AQR106",
+ .features = PHY_AQUANTIA_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .aneg_done = aquantia_aneg_done,
+ .config_aneg = aquantia_config_aneg,
+ .config_intr = aquantia_config_intr,
+ .ack_interrupt = aquantia_ack_interrupt,
+ .read_status = aquantia_read_status,
+},
+{
+ .phy_id = PHY_ID_AQR107,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Aquantia AQR107",
+ .features = PHY_AQUANTIA_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .aneg_done = aquantia_aneg_done,
+ .config_aneg = aquantia_config_aneg,
+ .config_intr = aquantia_config_intr,
+ .ack_interrupt = aquantia_ack_interrupt,
+ .read_status = aquantia_read_status,
+},
+{
.phy_id = PHY_ID_AQR405,
.phy_id_mask = 0xfffffff0,
.name = "Aquantia AQR405",
@@ -173,6 +199,8 @@ static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
{ PHY_ID_AQ1202, 0xfffffff0 },
{ PHY_ID_AQ2104, 0xfffffff0 },
{ PHY_ID_AQR105, 0xfffffff0 },
+ { PHY_ID_AQR106, 0xfffffff0 },
+ { PHY_ID_AQR107, 0xfffffff0 },
{ PHY_ID_AQR405, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index a52b560e428b..c1e52b9dc58d 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -63,6 +63,7 @@
#define ATH8030_PHY_ID 0x004dd076
#define ATH8031_PHY_ID 0x004dd074
#define ATH8035_PHY_ID 0x004dd072
+#define AT803X_PHY_ID_MASK 0xffffffef
MODULE_DESCRIPTION("Atheros 803x PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
@@ -398,7 +399,7 @@ static struct phy_driver at803x_driver[] = {
/* ATHEROS 8035 */
.phy_id = ATH8035_PHY_ID,
.name = "Atheros 8035 ethernet",
- .phy_id_mask = 0xffffffef,
+ .phy_id_mask = AT803X_PHY_ID_MASK,
.probe = at803x_probe,
.config_init = at803x_config_init,
.set_wol = at803x_set_wol,
@@ -415,7 +416,7 @@ static struct phy_driver at803x_driver[] = {
/* ATHEROS 8030 */
.phy_id = ATH8030_PHY_ID,
.name = "Atheros 8030 ethernet",
- .phy_id_mask = 0xffffffef,
+ .phy_id_mask = AT803X_PHY_ID_MASK,
.probe = at803x_probe,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
@@ -433,7 +434,7 @@ static struct phy_driver at803x_driver[] = {
/* ATHEROS 8031 */
.phy_id = ATH8031_PHY_ID,
.name = "Atheros 8031 ethernet",
- .phy_id_mask = 0xffffffef,
+ .phy_id_mask = AT803X_PHY_ID_MASK,
.probe = at803x_probe,
.config_init = at803x_config_init,
.set_wol = at803x_set_wol,
@@ -452,9 +453,9 @@ static struct phy_driver at803x_driver[] = {
module_phy_driver(at803x_driver);
static struct mdio_device_id __maybe_unused atheros_tbl[] = {
- { ATH8030_PHY_ID, 0xffffffef },
- { ATH8031_PHY_ID, 0xffffffef },
- { ATH8035_PHY_ID, 0xffffffef },
+ { ATH8030_PHY_ID, AT803X_PHY_ID_MASK },
+ { ATH8031_PHY_ID, AT803X_PHY_ID_MASK },
+ { ATH8035_PHY_ID, AT803X_PHY_ID_MASK },
{ }
};
diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c
index 49bbc6826883..3fe8cc5c177e 100644
--- a/drivers/net/phy/bcm-cygnus.c
+++ b/drivers/net/phy/bcm-cygnus.c
@@ -104,7 +104,7 @@ static int bcm_cygnus_config_init(struct phy_device *phydev)
return rc;
/* Advertise EEE */
- rc = bcm_phy_enable_eee(phydev);
+ rc = bcm_phy_set_eee(phydev, true);
if (rc)
return rc;
@@ -134,8 +134,7 @@ 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,
+ .features = PHY_GBIT_FEATURES,
.config_init = bcm_cygnus_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index df0416db0b88..ab9ad689617c 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -17,6 +17,7 @@
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/phy.h>
+#include <linux/ethtool.h>
#define MII_BCM_CHANNEL_WIDTH 0x2000
#define BCM_CL45VEN_EEE_ADV 0x3c
@@ -50,6 +51,23 @@ int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
}
EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
+int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
+{
+ /* The register must be written to both the Shadow Register Select and
+ * the Shadow Read Register Selector
+ */
+ phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
+ regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
+ return phy_read(phydev, MII_BCM54XX_AUX_CTL);
+}
+EXPORT_SYMBOL_GPL(bcm54xx_auxctl_read);
+
+int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+ return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
+}
+EXPORT_SYMBOL(bcm54xx_auxctl_write);
+
int bcm_phy_write_misc(struct phy_device *phydev,
u16 reg, u16 chl, u16 val)
{
@@ -178,7 +196,7 @@ int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
}
EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
-int bcm_phy_enable_eee(struct phy_device *phydev)
+int bcm_phy_set_eee(struct phy_device *phydev, bool enable)
{
int val;
@@ -188,7 +206,10 @@ int bcm_phy_enable_eee(struct phy_device *phydev)
if (val < 0)
return val;
- val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
+ if (enable)
+ val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
+ else
+ val &= ~(LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X);
phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
MDIO_MMD_AN, (u32)val);
@@ -199,14 +220,172 @@ int bcm_phy_enable_eee(struct phy_device *phydev)
if (val < 0)
return val;
- val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
+ if (enable)
+ val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
+ else
+ val &= ~(MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
MDIO_MMD_AN, (u32)val);
return 0;
}
-EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);
+EXPORT_SYMBOL_GPL(bcm_phy_set_eee);
+
+int bcm_phy_downshift_get(struct phy_device *phydev, u8 *count)
+{
+ int val;
+
+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ if (val < 0)
+ return val;
+
+ /* Check if wirespeed is enabled or not */
+ if (!(val & MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN)) {
+ *count = DOWNSHIFT_DEV_DISABLE;
+ return 0;
+ }
+
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR2);
+ if (val < 0)
+ return val;
+
+ /* Downgrade after one link attempt */
+ if (val & BCM54XX_SHD_SCR2_WSPD_RTRY_DIS) {
+ *count = 1;
+ } else {
+ /* Downgrade after configured retry count */
+ val >>= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT;
+ val &= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK;
+ *count = val + BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_downshift_get);
+
+int bcm_phy_downshift_set(struct phy_device *phydev, u8 count)
+{
+ int val = 0, ret = 0;
+
+ /* Range check the number given */
+ if (count - BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET >
+ BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK &&
+ count != DOWNSHIFT_DEV_DEFAULT_COUNT) {
+ return -ERANGE;
+ }
+
+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ if (val < 0)
+ return val;
+
+ /* Se the write enable bit */
+ val |= MII_BCM54XX_AUXCTL_MISC_WREN;
+
+ if (count == DOWNSHIFT_DEV_DISABLE) {
+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN;
+ return bcm54xx_auxctl_write(phydev,
+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ val);
+ } else {
+ val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN;
+ ret = bcm54xx_auxctl_write(phydev,
+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ val);
+ if (ret < 0)
+ return ret;
+ }
+
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR2);
+ val &= ~(BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK <<
+ BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT |
+ BCM54XX_SHD_SCR2_WSPD_RTRY_DIS);
+
+ switch (count) {
+ case 1:
+ val |= BCM54XX_SHD_SCR2_WSPD_RTRY_DIS;
+ break;
+ case DOWNSHIFT_DEV_DEFAULT_COUNT:
+ val |= 1 << BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT;
+ break;
+ default:
+ val |= (count - BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET) <<
+ BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT;
+ break;
+ }
+
+ return bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR2, val);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_downshift_set);
+
+struct bcm_phy_hw_stat {
+ const char *string;
+ u8 reg;
+ u8 shift;
+ u8 bits;
+};
+
+/* Counters freeze at either 0xffff or 0xff, better than nothing */
+static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
+ { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
+ { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
+ { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
+ { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
+ { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
+};
+
+int bcm_phy_get_sset_count(struct phy_device *phydev)
+{
+ return ARRAY_SIZE(bcm_phy_hw_stats);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count);
+
+void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
+ memcpy(data + i * ETH_GSTRING_LEN,
+ bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
+
+#ifndef UINT64_MAX
+#define UINT64_MAX (u64)(~((u64)0))
+#endif
+
+/* Caller is supposed to provide appropriate storage for the library code to
+ * access the shadow copy
+ */
+static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
+ unsigned int i)
+{
+ struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i];
+ int val;
+ u64 ret;
+
+ val = phy_read(phydev, stat.reg);
+ if (val < 0) {
+ ret = UINT64_MAX;
+ } else {
+ val >>= stat.shift;
+ val = val & ((1 << stat.bits) - 1);
+ shadow[i] += val;
+ ret = shadow[i];
+ }
+
+ return ret;
+}
+
+void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
+ struct ethtool_stats *stats, u64 *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
+ data[i] = bcm_phy_get_stat(phydev, shadow, i);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
MODULE_DESCRIPTION("Broadcom PHY Library");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h
index b2091c88b44d..7c73808cbbde 100644
--- a/drivers/net/phy/bcm-phy-lib.h
+++ b/drivers/net/phy/bcm-phy-lib.h
@@ -19,6 +19,9 @@
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 bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
+int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
+
int bcm_phy_write_misc(struct phy_device *phydev,
u16 reg, u16 chl, u16 value);
int bcm_phy_read_misc(struct phy_device *phydev,
@@ -33,5 +36,15 @@ 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);
+int bcm_phy_set_eee(struct phy_device *phydev, bool enable);
+
+int bcm_phy_downshift_get(struct phy_device *phydev, u8 *count);
+
+int bcm_phy_downshift_set(struct phy_device *phydev, u8 count);
+
+int bcm_phy_get_sset_count(struct phy_device *phydev);
+void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
+void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
+ struct ethtool_stats *stats, u64 *data);
+
#endif /* _LINUX_BCM_PHY_LIB_H */
diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 9636da0b6efc..264b085d796b 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -45,6 +45,10 @@
#define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3)
#define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0)
+struct bcm7xxx_phy_priv {
+ u64 *stats;
+};
+
static void r_rc_cal_reset(struct phy_device *phydev)
{
/* Reset R_CAL/RC_CAL Engine */
@@ -167,6 +171,7 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
{
u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
+ u8 count;
int ret = 0;
pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
@@ -199,7 +204,12 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
if (ret)
return ret;
- ret = bcm_phy_enable_eee(phydev);
+ ret = bcm_phy_downshift_get(phydev, &count);
+ if (ret)
+ return ret;
+
+ /* Only enable EEE if Wirespeed/downshift is disabled */
+ ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
if (ret)
return ret;
@@ -303,18 +313,91 @@ static int bcm7xxx_suspend(struct phy_device *phydev)
return 0;
}
+static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna,
+ void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ return bcm_phy_downshift_get(phydev, (u8 *)data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna,
+ const void *data)
+{
+ u8 count = *(u8 *)data;
+ int ret;
+
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ ret = bcm_phy_downshift_set(phydev, count);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (ret)
+ return ret;
+
+ /* Disable EEE advertisment since this prevents the PHY
+ * from successfully linking up, trigger auto-negotiation restart
+ * to let the MAC decide what to do.
+ */
+ ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
+ if (ret)
+ return ret;
+
+ return genphy_restart_aneg(phydev);
+}
+
+static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct bcm7xxx_phy_priv *priv = phydev->priv;
+
+ bcm_phy_get_stats(phydev, priv->stats, stats, data);
+}
+
+static int bcm7xxx_28nm_probe(struct phy_device *phydev)
+{
+ struct bcm7xxx_phy_priv *priv;
+
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ phydev->priv = priv;
+
+ priv->stats = devm_kcalloc(&phydev->mdio.dev,
+ bcm_phy_get_sset_count(phydev), sizeof(u64),
+ GFP_KERNEL);
+ if (!priv->stats)
+ return -ENOMEM;
+
+ return 0;
+}
+
#define BCM7XXX_28NM_GPHY(_oui, _name) \
{ \
.phy_id = (_oui), \
.phy_id_mask = 0xfffffff0, \
.name = _name, \
- .features = PHY_GBIT_FEATURES | \
- SUPPORTED_Pause | SUPPORTED_Asym_Pause, \
+ .features = PHY_GBIT_FEATURES, \
.flags = PHY_IS_INTERNAL, \
.config_init = bcm7xxx_28nm_config_init, \
.config_aneg = genphy_config_aneg, \
.read_status = genphy_read_status, \
.resume = bcm7xxx_28nm_resume, \
+ .get_tunable = bcm7xxx_28nm_get_tunable, \
+ .set_tunable = bcm7xxx_28nm_set_tunable, \
+ .get_sset_count = bcm_phy_get_sset_count, \
+ .get_strings = bcm_phy_get_strings, \
+ .get_stats = bcm7xxx_28nm_get_phy_stats, \
+ .probe = bcm7xxx_28nm_probe, \
}
#define BCM7XXX_40NM_EPHY(_oui, _name) \
@@ -322,8 +405,7 @@ static int bcm7xxx_suspend(struct phy_device *phydev)
.phy_id = (_oui), \
.phy_id_mask = 0xfffffff0, \
.name = _name, \
- .features = PHY_BASIC_FEATURES | \
- SUPPORTED_Pause | SUPPORTED_Asym_Pause, \
+ .features = PHY_BASIC_FEATURES, \
.flags = PHY_IS_INTERNAL, \
.config_init = bcm7xxx_config_init, \
.config_aneg = genphy_config_aneg, \
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 870327efccf7..4223e35490b0 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/brcmphy.h>
-
+#include <linux/of.h>
#define BRCM_PHY_MODEL(phydev) \
((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -30,9 +30,32 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
MODULE_AUTHOR("Maciej W. Rozycki");
MODULE_LICENSE("GPL");
-static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
+static int bcm54810_config(struct phy_device *phydev)
{
- return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
+ int rc, val;
+
+ val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
+ val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
+ rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
+ val);
+ if (rc < 0)
+ return rc;
+
+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
+ val |= MII_BCM54XX_AUXCTL_MISC_WREN;
+ rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ val);
+ if (rc < 0)
+ return rc;
+
+ val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
+ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
+ rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+ if (rc < 0)
+ return rc;
+
+ return 0;
}
/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
@@ -207,6 +230,12 @@ static int bcm54xx_config_init(struct phy_device *phydev)
(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
bcm54xx_adjust_rxrefclk(phydev);
+ if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
+ err = bcm54810_config(phydev);
+ if (err)
+ return err;
+ }
+
bcm54xx_phydsp_config(phydev);
return 0;
@@ -304,6 +333,7 @@ static int bcm5482_read_status(struct phy_device *phydev)
static int bcm5481_config_aneg(struct phy_device *phydev)
{
+ struct device_node *np = phydev->mdio.dev.of_node;
int ret;
/* Aneg firsly. */
@@ -334,6 +364,49 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
phy_write(phydev, 0x18, reg);
}
+ if (of_property_read_bool(np, "enet-phy-lane-swap")) {
+ /* Lane Swap - Undocumented register...magic! */
+ ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
+ 0x11B);
+ if (ret < 0)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int bcm54612e_config_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ /* First, auto-negotiate. */
+ ret = genphy_config_aneg(phydev);
+
+ /* Clear TX internal delay unless requested. */
+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
+ /* Disable TXD to GTXCLK clock delay (default set) */
+ /* Bit 9 is the only field in shadow register 00011 */
+ bcm_phy_write_shadow(phydev, 0x03, 0);
+ }
+
+ /* Clear RX internal delay unless requested. */
+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
+ u16 reg;
+
+ /* Errata: reads require filling in the write selector field */
+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
+ reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+ /* Disable RXD to RXC delay (default set) */
+ reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
+ /* Clear shadow selector field */
+ reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ MII_BCM54XX_AUXCTL_MISC_WREN | reg);
+ }
+
return ret;
}
@@ -452,8 +525,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5411,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5411",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -464,8 +536,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5421,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5421",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -476,8 +547,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5461,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5461",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -485,11 +555,21 @@ static struct phy_driver broadcom_drivers[] = {
.ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm_phy_config_intr,
}, {
+ .phy_id = PHY_ID_BCM54612E,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM54612E",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = bcm54612e_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
+}, {
.phy_id = PHY_ID_BCM54616S,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM54616S",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -500,8 +580,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5464,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5464",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -512,8 +591,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5481,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5481",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
@@ -521,11 +599,21 @@ static struct phy_driver broadcom_drivers[] = {
.ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm_phy_config_intr,
}, {
+ .phy_id = PHY_ID_BCM54810,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM54810",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = bcm5481_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
+}, {
.phy_id = PHY_ID_BCM5482,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5482",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm5482_config_init,
.config_aneg = genphy_config_aneg,
@@ -536,8 +624,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM50610,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM50610",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -548,8 +635,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM50610M,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM50610M",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -560,8 +646,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM57780,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM57780",
- .features = PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -572,8 +657,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCMAC131,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCMAC131",
- .features = PHY_BASIC_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = brcm_fet_config_init,
.config_aneg = genphy_config_aneg,
@@ -584,8 +668,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id = PHY_ID_BCM5241,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5241",
- .features = PHY_BASIC_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = brcm_fet_config_init,
.config_aneg = genphy_config_aneg,
@@ -600,9 +683,11 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
{ PHY_ID_BCM5411, 0xfffffff0 },
{ PHY_ID_BCM5421, 0xfffffff0 },
{ PHY_ID_BCM5461, 0xfffffff0 },
+ { PHY_ID_BCM54612E, 0xfffffff0 },
{ PHY_ID_BCM54616S, 0xfffffff0 },
{ PHY_ID_BCM5464, 0xfffffff0 },
{ PHY_ID_BCM5481, 0xfffffff0 },
+ { PHY_ID_BCM54810, 0xfffffff0 },
{ PHY_ID_BCM5482, 0xfffffff0 },
{ PHY_ID_BCM50610, 0xfffffff0 },
{ PHY_ID_BCM50610M, 0xfffffff0 },
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 7a240fce3a7e..e2460a57e4b1 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -375,7 +375,7 @@ static int periodic_output(struct dp83640_clock *clock,
/* ptp clock methods */
-static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int ptp_dp83640_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
struct dp83640_clock *clock =
container_of(ptp, struct dp83640_clock, caps);
@@ -384,13 +384,13 @@ static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
int neg_adj = 0;
u16 hi, lo;
- if (ppb < 0) {
+ if (scaled_ppm < 0) {
neg_adj = 1;
- ppb = -ppb;
+ scaled_ppm = -scaled_ppm;
}
- rate = ppb;
- rate <<= 26;
- rate = div_u64(rate, 1953125);
+ rate = scaled_ppm;
+ rate <<= 13;
+ rate = div_u64(rate, 15625);
hi = (rate >> 16) & PTP_RATE_HI_MASK;
if (neg_adj)
@@ -1035,7 +1035,7 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
clock->caps.n_per_out = N_PER_OUT;
clock->caps.n_pins = DP83640_N_PINS;
clock->caps.pps = 0;
- clock->caps.adjfreq = ptp_dp83640_adjfreq;
+ clock->caps.adjfine = ptp_dp83640_adjfine;
clock->caps.adjtime = ptp_dp83640_adjtime;
clock->caps.gettime64 = ptp_dp83640_gettime;
clock->caps.settime64 = ptp_dp83640_settime;
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 91177a4a32ad..1b639242f9e2 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -33,6 +33,7 @@
/* Extended Registers */
#define DP83867_RGMIICTL 0x0032
#define DP83867_RGMIIDCTL 0x0086
+#define DP83867_IO_MUX_CFG 0x0170
#define DP83867_SW_RESET BIT(15)
#define DP83867_SW_RESTART BIT(14)
@@ -62,10 +63,17 @@
/* RGMIIDCTL bits */
#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
+/* IO_MUX_CFG bits */
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f
+
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
+
struct dp83867_private {
int rx_id_delay;
int tx_id_delay;
int fifo_depth;
+ int io_impedance;
};
static int dp83867_ack_interrupt(struct phy_device *phydev)
@@ -111,6 +119,14 @@ static int dp83867_of_init(struct phy_device *phydev)
if (!of_node)
return -ENODEV;
+ dp83867->io_impedance = -EINVAL;
+
+ /* Optional configuration */
+ if (of_property_read_bool(of_node, "ti,max-output-impedance"))
+ dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
+ else if (of_property_read_bool(of_node, "ti,min-output-impedance"))
+ dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
+
ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
&dp83867->rx_id_delay);
if (ret)
@@ -184,6 +200,18 @@ static int dp83867_config_init(struct phy_device *phydev)
phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
DP83867_DEVADDR, delay);
+
+ if (dp83867->io_impedance >= 0) {
+ val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+ DP83867_DEVADDR);
+
+ val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+ val |= dp83867->io_impedance &
+ DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+
+ phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+ DP83867_DEVADDR, val);
+ }
}
return 0;
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index e5f251b91578..22b51f01a94a 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -225,8 +225,7 @@ static struct phy_driver icplus_driver[] = {
.phy_id = 0x02430d90,
.name = "ICPlus IP1001",
.phy_id_mask = 0x0ffffff0,
- .features = PHY_GBIT_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.config_init = &ip1001_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
@@ -236,8 +235,7 @@ static struct phy_driver icplus_driver[] = {
.phy_id = 0x02430c54,
.name = "ICPlus IP101A/G",
.phy_id_mask = 0x0ffffff0,
- .features = PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause,
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.ack_interrupt = ip101a_g_ack_interrupt,
.config_init = &ip101a_g_config_init,
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index c300ab5587b8..b1fd7bb0e4db 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -239,8 +239,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY11G_1_3,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.3",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = xway_gphy14_config_aneg,
@@ -254,8 +253,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY22F_1_3,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.3",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = xway_gphy14_config_aneg,
@@ -269,8 +267,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY11G_1_4,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.4",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = xway_gphy14_config_aneg,
@@ -284,8 +281,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY22F_1_4,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.4",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = xway_gphy14_config_aneg,
@@ -299,8 +295,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY11G_1_5,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = genphy_config_aneg,
@@ -314,8 +309,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY22F_1_5,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (PEF 7061) v1.5 / v1.6",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = genphy_config_aneg,
@@ -329,8 +323,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY11G_VR9,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY11G (xRX integrated)",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = genphy_config_aneg,
@@ -344,8 +337,7 @@ static struct phy_driver xway_gphy[] = {
.phy_id = PHY_ID_PHY22F_VR9,
.phy_id_mask = 0xffffffff,
.name = "Intel XWAY PHY22F (xRX integrated)",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = xway_gphy_config_init,
.config_aneg = genphy_config_aneg,
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index c2dcf02df202..e269262471a4 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -268,7 +268,7 @@ static int marvell_config_aneg(struct phy_device *phydev)
if (err < 0)
return err;
- err = marvell_set_polarity(phydev, phydev->mdix);
+ err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
@@ -311,7 +311,7 @@ static int m88e1111_config_aneg(struct phy_device *phydev)
*/
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
- err = marvell_set_polarity(phydev, phydev->mdix);
+ err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
@@ -361,7 +361,7 @@ static int m88e1111_config_aneg(struct phy_device *phydev)
static int marvell_of_reg_init(struct phy_device *phydev)
{
const __be32 *paddr;
- int len, i, saved_page, current_page, page_changed, ret;
+ int len, i, saved_page, current_page, ret;
if (!phydev->mdio.dev.of_node)
return 0;
@@ -374,7 +374,6 @@ static int marvell_of_reg_init(struct phy_device *phydev)
saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);
if (saved_page < 0)
return saved_page;
- page_changed = 0;
current_page = saved_page;
ret = 0;
@@ -388,7 +387,6 @@ static int marvell_of_reg_init(struct phy_device *phydev)
if (reg_page != current_page) {
current_page = reg_page;
- page_changed = 1;
ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
if (ret < 0)
goto err;
@@ -411,7 +409,7 @@ static int marvell_of_reg_init(struct phy_device *phydev)
}
err:
- if (page_changed) {
+ if (current_page != saved_page) {
i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);
if (ret == 0)
ret = i;
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index d0bed52c8d16..6a33646bdf05 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -21,7 +21,8 @@
struct mdio_mux_mmioreg_state {
void *mux_handle;
phys_addr_t phys;
- uint8_t mask;
+ unsigned int iosize;
+ unsigned int mask;
};
/*
@@ -47,17 +48,47 @@ static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
struct mdio_mux_mmioreg_state *s = data;
if (current_child ^ desired_child) {
- void __iomem *p = ioremap(s->phys, 1);
- uint8_t x, y;
-
+ void __iomem *p = ioremap(s->phys, s->iosize);
if (!p)
return -ENOMEM;
- x = ioread8(p);
- y = (x & ~s->mask) | desired_child;
- if (x != y) {
- iowrite8((x & ~s->mask) | desired_child, p);
- pr_debug("%s: %02x -> %02x\n", __func__, x, y);
+ switch (s->iosize) {
+ case sizeof(uint8_t): {
+ uint8_t x, y;
+
+ x = ioread8(p);
+ y = (x & ~s->mask) | desired_child;
+ if (x != y) {
+ iowrite8((x & ~s->mask) | desired_child, p);
+ pr_debug("%s: %02x -> %02x\n", __func__, x, y);
+ }
+
+ break;
+ }
+ case sizeof(uint16_t): {
+ uint16_t x, y;
+
+ x = ioread16(p);
+ y = (x & ~s->mask) | desired_child;
+ if (x != y) {
+ iowrite16((x & ~s->mask) | desired_child, p);
+ pr_debug("%s: %04x -> %04x\n", __func__, x, y);
+ }
+
+ break;
+ }
+ case sizeof(uint32_t): {
+ uint32_t x, y;
+
+ x = ioread32(p);
+ y = (x & ~s->mask) | desired_child;
+ if (x != y) {
+ iowrite32((x & ~s->mask) | desired_child, p);
+ pr_debug("%s: %08x -> %08x\n", __func__, x, y);
+ }
+
+ break;
+ }
}
iounmap(p);
@@ -88,8 +119,11 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
}
s->phys = res.start;
- if (resource_size(&res) != sizeof(uint8_t)) {
- dev_err(&pdev->dev, "only 8-bit registers are supported\n");
+ s->iosize = resource_size(&res);
+ if (s->iosize != sizeof(uint8_t) &&
+ s->iosize != sizeof(uint16_t) &&
+ s->iosize != sizeof(uint32_t)) {
+ dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n");
return -EINVAL;
}
@@ -98,8 +132,8 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "missing or invalid mux-mask property\n");
return -ENODEV;
}
- if (be32_to_cpup(iprop) > 255) {
- dev_err(&pdev->dev, "only 8-bit registers are supported\n");
+ if (be32_to_cpup(iprop) >= BIT(s->iosize * 8)) {
+ dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n");
return -EINVAL;
}
s->mask = be32_to_cpup(iprop);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 09deef4bed09..653d076eafe5 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,6 +38,9 @@
#include <asm/irq.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/mdio.h>
+
int mdiobus_register_device(struct mdio_device *mdiodev)
{
if (mdiodev->bus->mdio_map[mdiodev->addr])
@@ -461,6 +464,8 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
retval = bus->read(bus, addr, regnum);
mutex_unlock(&bus->mdio_lock);
+ trace_mdio_access(bus, 1, addr, regnum, retval, retval);
+
return retval;
}
EXPORT_SYMBOL(mdiobus_read_nested);
@@ -485,6 +490,8 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
retval = bus->read(bus, addr, regnum);
mutex_unlock(&bus->mdio_lock);
+ trace_mdio_access(bus, 1, addr, regnum, retval, retval);
+
return retval;
}
EXPORT_SYMBOL(mdiobus_read);
@@ -513,6 +520,8 @@ int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
err = bus->write(bus, addr, regnum, val);
mutex_unlock(&bus->mdio_lock);
+ trace_mdio_access(bus, 0, addr, regnum, val, err);
+
return err;
}
EXPORT_SYMBOL(mdiobus_write_nested);
@@ -538,6 +547,8 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
err = bus->write(bus, addr, regnum, val);
mutex_unlock(&bus->mdio_lock);
+ trace_mdio_access(bus, 0, addr, regnum, val, err);
+
return err;
}
EXPORT_SYMBOL(mdiobus_write);
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index 9c88e6749b9a..43c8fd46504b 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -144,7 +144,7 @@ int mdio_driver_register(struct mdio_driver *drv)
struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
int retval;
- pr_info("mdio_driver_register: %s\n", mdiodrv->driver.name);
+ pr_debug("mdio_driver_register: %s\n", mdiodrv->driver.name);
mdiodrv->driver.bus = &mdio_bus_type;
mdiodrv->driver.probe = mdio_probe;
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
new file mode 100644
index 000000000000..1ea69b7585d9
--- /dev/null
+++ b/drivers/net/phy/meson-gxl.c
@@ -0,0 +1,81 @@
+/*
+ * Amlogic Meson GXL Internal PHY Driver
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2016 BayLibre, SAS. All rights reserved.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+static int meson_gxl_config_init(struct phy_device *phydev)
+{
+ /* Enable Analog and DSP register Bank access by */
+ phy_write(phydev, 0x14, 0x0000);
+ phy_write(phydev, 0x14, 0x0400);
+ phy_write(phydev, 0x14, 0x0000);
+ phy_write(phydev, 0x14, 0x0400);
+
+ /* Write Analog register 23 */
+ phy_write(phydev, 0x17, 0x8E0D);
+ phy_write(phydev, 0x14, 0x4417);
+
+ /* Enable fractional PLL */
+ phy_write(phydev, 0x17, 0x0005);
+ phy_write(phydev, 0x14, 0x5C1B);
+
+ /* Program fraction FR_PLL_DIV1 */
+ phy_write(phydev, 0x17, 0x029A);
+ phy_write(phydev, 0x14, 0x5C1D);
+
+ /* Program fraction FR_PLL_DIV1 */
+ phy_write(phydev, 0x17, 0xAAAA);
+ phy_write(phydev, 0x14, 0x5C1C);
+
+ return 0;
+}
+
+static struct phy_driver meson_gxl_phy[] = {
+ {
+ .phy_id = 0x01814400,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Meson GXL Internal PHY",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_IS_INTERNAL,
+ .config_init = meson_gxl_config_init,
+ .config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
+ .read_status = genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ },
+};
+
+static struct mdio_device_id __maybe_unused meson_gxl_tbl[] = {
+ { 0x01814400, 0xfffffff0 },
+ { }
+};
+
+module_phy_driver(meson_gxl_phy);
+
+MODULE_DEVICE_TABLE(mdio, meson_gxl_tbl);
+
+MODULE_DESCRIPTION("Amlogic Meson GXL Internal PHY driver");
+MODULE_AUTHOR("Baoqi wang");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index ea92d524d5a8..9a77289109b7 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -790,7 +790,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KS8737,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KS8737",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ks8737_type,
.config_init = kszphy_config_init,
@@ -807,8 +807,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8021,
.phy_id_mask = 0x00ffffff,
.name = "Micrel KSZ8021 or KSZ8031",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8021_type,
.probe = kszphy_probe,
@@ -826,8 +825,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8031,
.phy_id_mask = 0x00ffffff,
.name = "Micrel KSZ8031",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8021_type,
.probe = kszphy_probe,
@@ -845,8 +843,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8041,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ8041",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8041_type,
.probe = kszphy_probe,
@@ -864,8 +861,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8041RNLI,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ8041RNLI",
- .features = PHY_BASIC_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8041_type,
.probe = kszphy_probe,
@@ -883,8 +879,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8051,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ8051",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8051_type,
.probe = kszphy_probe,
@@ -902,7 +897,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8001,
.name = "Micrel KSZ8001 or KS8721",
.phy_id_mask = 0x00fffffc,
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8041_type,
.probe = kszphy_probe,
@@ -920,7 +915,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8081,
.name = "Micrel KSZ8081 or KSZ8091",
.phy_id_mask = MICREL_PHY_ID_MASK,
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz8081_type,
.probe = kszphy_probe,
@@ -938,7 +933,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8061,
.name = "Micrel KSZ8061",
.phy_id_mask = MICREL_PHY_ID_MASK,
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
@@ -954,7 +949,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ9021,
.phy_id_mask = 0x000ffffe,
.name = "Micrel KSZ9021 Gigabit PHY",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz9021_type,
.config_init = ksz9021_config_init,
@@ -973,7 +968,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ9031,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ9031 Gigabit PHY",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz9021_type,
.config_init = ksz9031_config_init,
@@ -990,7 +985,6 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8873MLL,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ8873MLL Switch",
- .features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG,
.config_init = kszphy_config_init,
.config_aneg = ksz8873mll_config_aneg,
@@ -1004,7 +998,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ886X,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ886X Switch",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
index 7c00e508a101..324fbf6ad8ff 100644
--- a/drivers/net/phy/microchip.c
+++ b/drivers/net/phy/microchip.c
@@ -106,21 +106,54 @@ static int lan88xx_set_wol(struct phy_device *phydev,
return 0;
}
+static void lan88xx_set_mdix(struct phy_device *phydev)
+{
+ int buf;
+ int val;
+
+ switch (phydev->mdix_ctrl) {
+ case ETH_TP_MDI:
+ val = LAN88XX_EXT_MODE_CTRL_MDI_;
+ break;
+ case ETH_TP_MDI_X:
+ val = LAN88XX_EXT_MODE_CTRL_MDI_X_;
+ break;
+ case ETH_TP_MDI_AUTO:
+ val = LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_;
+ break;
+ default:
+ return;
+ }
+
+ 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_;
+ buf |= val;
+ phy_write(phydev, LAN88XX_EXT_MODE_CTRL, buf);
+ phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0);
+}
+
+static int lan88xx_config_aneg(struct phy_device *phydev)
+{
+ lan88xx_set_mdix(phydev);
+
+ return genphy_config_aneg(phydev);
+}
+
static struct phy_driver microchip_phy_driver[] = {
{
.phy_id = 0x0007c130,
.phy_id_mask = 0xfffffff0,
.name = "Microchip LAN88xx",
- .features = (PHY_GBIT_FEATURES |
- SUPPORTED_Pause | SUPPORTED_Asym_Pause),
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = lan88xx_probe,
.remove = lan88xx_remove,
.config_init = genphy_config_init,
- .config_aneg = genphy_config_aneg,
+ .config_aneg = lan88xx_config_aneg,
.read_status = genphy_read_status,
.ack_interrupt = lan88xx_phy_ack_interrupt,
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 77a6671d572e..e03ead81fffb 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -12,7 +12,6 @@
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/of.h>
-#include <dt-bindings/net/mscc-phy-vsc8531.h>
#include <linux/netdevice.h>
enum rgmii_rx_clock_delay {
@@ -28,6 +27,11 @@ enum rgmii_rx_clock_delay {
/* Microsemi VSC85xx PHY registers */
/* IEEE 802. Std Registers */
+#define MSCC_PHY_BYPASS_CONTROL 18
+#define DISABLE_HP_AUTO_MDIX_MASK 0x0080
+#define DISABLE_PAIR_SWAP_CORR_MASK 0x0020
+#define DISABLE_POLARITY_CORR_MASK 0x0010
+
#define MSCC_PHY_EXT_PHY_CNTL_1 23
#define MAC_IF_SELECTION_MASK 0x1800
#define MAC_IF_SELECTION_GMII 0
@@ -45,10 +49,25 @@ enum rgmii_rx_clock_delay {
#define EDGE_RATE_CNTL_POS 5
#define EDGE_RATE_CNTL_MASK 0x00E0
+#define MSCC_PHY_DEV_AUX_CNTL 28
+#define HP_AUTO_MDIX_X_OVER_IND_MASK 0x2000
+
#define MSCC_EXT_PAGE_ACCESS 31
#define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */
+#define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */
#define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */
+/* Extended Page 1 Registers */
+#define MSCC_PHY_EXT_MODE_CNTL 19
+#define FORCE_MDI_CROSSOVER_MASK 0x000C
+#define FORCE_MDI_CROSSOVER_MDIX 0x000C
+#define FORCE_MDI_CROSSOVER_MDI 0x0008
+
+#define MSCC_PHY_ACTIPHY_CNTL 20
+#define DOWNSHIFT_CNTL_MASK 0x001C
+#define DOWNSHIFT_EN 0x0010
+#define DOWNSHIFT_CNTL_POS 2
+
/* Extended Page 2 Registers */
#define MSCC_PHY_RGMII_CNTL 20
#define RGMII_RX_CLK_DELAY_MASK 0x0070
@@ -66,26 +85,36 @@ enum rgmii_rx_clock_delay {
#define SECURE_ON_PASSWD_LEN_4 0x4000
/* Microsemi PHY ID's */
+#define PHY_ID_VSC8530 0x00070560
#define PHY_ID_VSC8531 0x00070570
+#define PHY_ID_VSC8540 0x00070760
#define PHY_ID_VSC8541 0x00070770
-struct edge_rate_table {
- u16 vddmac;
- int slowdown[MSCC_SLOWDOWN_MAX];
-};
+#define MSCC_VDDMAC_1500 1500
+#define MSCC_VDDMAC_1800 1800
+#define MSCC_VDDMAC_2500 2500
+#define MSCC_VDDMAC_3300 3300
-struct edge_rate_table edge_table[MSCC_VDDMAC_MAX] = {
- {3300, { 0, -2, -4, -7, -10, -17, -29, -53} },
- {2500, { 0, -3, -6, -10, -14, -23, -37, -63} },
- {1800, { 0, -5, -9, -16, -23, -35, -52, -76} },
- {1500, { 0, -6, -14, -21, -29, -42, -58, -77} },
-};
+#define DOWNSHIFT_COUNT_MAX 5
struct vsc8531_private {
- u8 edge_slowdown;
+ int rate_magic;
+};
+
+#ifdef CONFIG_OF_MDIO
+struct vsc8531_edge_rate_table {
u16 vddmac;
+ u8 slowdown[8];
};
+static const struct vsc8531_edge_rate_table edge_table[] = {
+ {MSCC_VDDMAC_3300, { 0, 2, 4, 7, 10, 17, 29, 53} },
+ {MSCC_VDDMAC_2500, { 0, 3, 6, 10, 14, 23, 37, 63} },
+ {MSCC_VDDMAC_1800, { 0, 5, 9, 16, 23, 35, 52, 76} },
+ {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
+};
+#endif /* CONFIG_OF_MDIO */
+
static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
{
int rc;
@@ -94,6 +123,113 @@ static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
return rc;
}
+static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
+{
+ u16 reg_val;
+
+ reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
+ if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
+ *mdix = ETH_TP_MDI_X;
+ else
+ *mdix = ETH_TP_MDI;
+
+ return 0;
+}
+
+static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
+{
+ int rc;
+ u16 reg_val;
+
+ reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
+ if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) {
+ reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
+ DISABLE_POLARITY_CORR_MASK |
+ DISABLE_HP_AUTO_MDIX_MASK);
+ } else {
+ reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
+ DISABLE_POLARITY_CORR_MASK |
+ DISABLE_HP_AUTO_MDIX_MASK);
+ }
+ rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
+ if (rc != 0)
+ return rc;
+
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
+ if (rc != 0)
+ return rc;
+
+ reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL);
+ reg_val &= ~(FORCE_MDI_CROSSOVER_MASK);
+ if (mdix == ETH_TP_MDI)
+ reg_val |= FORCE_MDI_CROSSOVER_MDI;
+ else if (mdix == ETH_TP_MDI_X)
+ reg_val |= FORCE_MDI_CROSSOVER_MDIX;
+ rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val);
+ if (rc != 0)
+ return rc;
+
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
+ if (rc != 0)
+ return rc;
+
+ return genphy_restart_aneg(phydev);
+}
+
+static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
+{
+ int rc;
+ u16 reg_val;
+
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
+ if (rc != 0)
+ goto out;
+
+ reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
+ reg_val &= DOWNSHIFT_CNTL_MASK;
+ if (!(reg_val & DOWNSHIFT_EN))
+ *count = DOWNSHIFT_DEV_DISABLE;
+ else
+ *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
+
+out:
+ return rc;
+}
+
+static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
+{
+ int rc;
+ u16 reg_val;
+
+ if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
+ /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
+ count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
+ } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
+ phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
+ return -ERANGE;
+ } else if (count) {
+ /* Downshift count is either 2,3,4 or 5 */
+ count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
+ }
+
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
+ if (rc != 0)
+ goto out;
+
+ reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
+ reg_val &= ~(DOWNSHIFT_CNTL_MASK);
+ reg_val |= count;
+ rc = phy_write(phydev, MSCC_PHY_ACTIPHY_CNTL, reg_val);
+ if (rc != 0)
+ goto out;
+
+ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
+
+out:
+ return rc;
+}
+
static int vsc85xx_wol_set(struct phy_device *phydev,
struct ethtool_wolinfo *wol)
{
@@ -205,29 +341,43 @@ out_unlock:
mutex_unlock(&phydev->lock);
}
-static u8 edge_rate_magic_get(u16 vddmac,
- int slowdown)
+#ifdef CONFIG_OF_MDIO
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{
- int rc = (MSCC_SLOWDOWN_MAX - 1);
- u8 vdd;
u8 sd;
+ u16 vdd;
+ int rc, i, j;
+ struct device *dev = &phydev->mdio.dev;
+ struct device_node *of_node = dev->of_node;
+ u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
- for (vdd = 0; vdd < MSCC_VDDMAC_MAX; vdd++) {
- if (edge_table[vdd].vddmac == vddmac) {
- for (sd = 0; sd < MSCC_SLOWDOWN_MAX; sd++) {
- if (edge_table[vdd].slowdown[sd] <= slowdown) {
- rc = (MSCC_SLOWDOWN_MAX - sd - 1);
- break;
- }
- }
- }
- }
+ if (!of_node)
+ return -ENODEV;
- return rc;
+ rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd);
+ if (rc != 0)
+ vdd = MSCC_VDDMAC_3300;
+
+ rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd);
+ if (rc != 0)
+ sd = 0;
+
+ for (i = 0; i < ARRAY_SIZE(edge_table); i++)
+ if (edge_table[i].vddmac == vdd)
+ for (j = 0; j < sd_array_size; j++)
+ if (edge_table[i].slowdown[j] == sd)
+ return (sd_array_size - j - 1);
+
+ return -EINVAL;
}
+#else
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
+{
+ return 0;
+}
+#endif /* CONFIG_OF_MDIO */
-static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev,
- u8 edge_rate)
+static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
{
int rc;
u16 reg_val;
@@ -291,6 +441,7 @@ static int vsc85xx_default_config(struct phy_device *phydev)
int rc;
u16 reg_val;
+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
mutex_lock(&phydev->lock);
rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
if (rc != 0)
@@ -308,45 +459,33 @@ out_unlock:
return rc;
}
-#ifdef CONFIG_OF_MDIO
-static int vsc8531_of_init(struct phy_device *phydev)
+static int vsc85xx_get_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna, void *data)
{
- int rc;
- struct vsc8531_private *vsc8531 = phydev->priv;
- struct device *dev = &phydev->mdio.dev;
- struct device_node *of_node = dev->of_node;
-
- if (!of_node)
- return -ENODEV;
-
- rc = of_property_read_u16(of_node, "vsc8531,vddmac",
- &vsc8531->vddmac);
- if (rc == -EINVAL)
- vsc8531->vddmac = MSCC_VDDMAC_3300;
- rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown",
- &vsc8531->edge_slowdown);
- if (rc == -EINVAL)
- vsc8531->edge_slowdown = 0;
-
- rc = 0;
- return rc;
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ return vsc85xx_downshift_get(phydev, (u8 *)data);
+ default:
+ return -EINVAL;
+ }
}
-#else
-static int vsc8531_of_init(struct phy_device *phydev)
+
+static int vsc85xx_set_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna,
+ const void *data)
{
- return 0;
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ return vsc85xx_downshift_set(phydev, *(u8 *)data);
+ default:
+ return -EINVAL;
+ }
}
-#endif /* CONFIG_OF_MDIO */
static int vsc85xx_config_init(struct phy_device *phydev)
{
int rc;
struct vsc8531_private *vsc8531 = phydev->priv;
- u8 edge_rate;
-
- rc = vsc8531_of_init(phydev);
- if (rc)
- return rc;
rc = vsc85xx_default_config(phydev);
if (rc)
@@ -356,9 +495,7 @@ static int vsc85xx_config_init(struct phy_device *phydev)
if (rc)
return rc;
- edge_rate = edge_rate_magic_get(vsc8531->vddmac,
- -(int)vsc8531->edge_slowdown);
- rc = vsc85xx_edge_rate_cntl_set(phydev, edge_rate);
+ rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
if (rc)
return rc;
@@ -394,22 +531,72 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
return rc;
}
+static int vsc85xx_config_aneg(struct phy_device *phydev)
+{
+ int rc;
+
+ rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
+ if (rc < 0)
+ return rc;
+
+ return genphy_config_aneg(phydev);
+}
+
+static int vsc85xx_read_status(struct phy_device *phydev)
+{
+ int rc;
+
+ rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
+ if (rc < 0)
+ return rc;
+
+ return genphy_read_status(phydev);
+}
+
static int vsc85xx_probe(struct phy_device *phydev)
{
+ int rate_magic;
struct vsc8531_private *vsc8531;
+ rate_magic = vsc85xx_edge_rate_magic_get(phydev);
+ if (rate_magic < 0)
+ return rate_magic;
+
vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
if (!vsc8531)
return -ENOMEM;
phydev->priv = vsc8531;
+ vsc8531->rate_magic = rate_magic;
+
return 0;
}
/* Microsemi VSC85xx PHYs */
static struct phy_driver vsc85xx_driver[] = {
{
+ .phy_id = PHY_ID_VSC8530,
+ .name = "Microsemi FE VSC8530",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .soft_reset = &genphy_soft_reset,
+ .config_init = &vsc85xx_config_init,
+ .config_aneg = &vsc85xx_config_aneg,
+ .aneg_done = &genphy_aneg_done,
+ .read_status = &vsc85xx_read_status,
+ .ack_interrupt = &vsc85xx_ack_interrupt,
+ .config_intr = &vsc85xx_config_intr,
+ .suspend = &genphy_suspend,
+ .resume = &genphy_resume,
+ .probe = &vsc85xx_probe,
+ .set_wol = &vsc85xx_wol_set,
+ .get_wol = &vsc85xx_wol_get,
+ .get_tunable = &vsc85xx_get_tunable,
+ .set_tunable = &vsc85xx_set_tunable,
+},
+{
.phy_id = PHY_ID_VSC8531,
.name = "Microsemi VSC8531",
.phy_id_mask = 0xfffffff0,
@@ -417,16 +604,39 @@ static struct phy_driver vsc85xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.soft_reset = &genphy_soft_reset,
.config_init = &vsc85xx_config_init,
- .config_aneg = &genphy_config_aneg,
+ .config_aneg = &vsc85xx_config_aneg,
.aneg_done = &genphy_aneg_done,
- .read_status = &genphy_read_status,
+ .read_status = &vsc85xx_read_status,
.ack_interrupt = &vsc85xx_ack_interrupt,
.config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend,
.resume = &genphy_resume,
- .probe = &vsc85xx_probe,
- .set_wol = &vsc85xx_wol_set,
- .get_wol = &vsc85xx_wol_get,
+ .probe = &vsc85xx_probe,
+ .set_wol = &vsc85xx_wol_set,
+ .get_wol = &vsc85xx_wol_get,
+ .get_tunable = &vsc85xx_get_tunable,
+ .set_tunable = &vsc85xx_set_tunable,
+},
+{
+ .phy_id = PHY_ID_VSC8540,
+ .name = "Microsemi FE VSC8540 SyncE",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .soft_reset = &genphy_soft_reset,
+ .config_init = &vsc85xx_config_init,
+ .config_aneg = &vsc85xx_config_aneg,
+ .aneg_done = &genphy_aneg_done,
+ .read_status = &vsc85xx_read_status,
+ .ack_interrupt = &vsc85xx_ack_interrupt,
+ .config_intr = &vsc85xx_config_intr,
+ .suspend = &genphy_suspend,
+ .resume = &genphy_resume,
+ .probe = &vsc85xx_probe,
+ .set_wol = &vsc85xx_wol_set,
+ .get_wol = &vsc85xx_wol_get,
+ .get_tunable = &vsc85xx_get_tunable,
+ .set_tunable = &vsc85xx_set_tunable,
},
{
.phy_id = PHY_ID_VSC8541,
@@ -436,16 +646,18 @@ static struct phy_driver vsc85xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.soft_reset = &genphy_soft_reset,
.config_init = &vsc85xx_config_init,
- .config_aneg = &genphy_config_aneg,
+ .config_aneg = &vsc85xx_config_aneg,
.aneg_done = &genphy_aneg_done,
- .read_status = &genphy_read_status,
+ .read_status = &vsc85xx_read_status,
.ack_interrupt = &vsc85xx_ack_interrupt,
.config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend,
.resume = &genphy_resume,
- .probe = &vsc85xx_probe,
- .set_wol = &vsc85xx_wol_set,
- .get_wol = &vsc85xx_wol_get,
+ .probe = &vsc85xx_probe,
+ .set_wol = &vsc85xx_wol_set,
+ .get_wol = &vsc85xx_wol_get,
+ .get_tunable = &vsc85xx_get_tunable,
+ .set_tunable = &vsc85xx_set_tunable,
}
};
@@ -453,7 +665,9 @@ static struct phy_driver vsc85xx_driver[] = {
module_phy_driver(vsc85xx_driver);
static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+ { PHY_ID_VSC8530, 0xfffffff0, },
{ PHY_ID_VSC8531, 0xfffffff0, },
+ { PHY_ID_VSC8540, 0xfffffff0, },
{ PHY_ID_VSC8541, 0xfffffff0, },
{ }
};
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index 2a1b490bc587..2addf1d3f619 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -133,7 +133,7 @@ static struct phy_driver dp83865_driver[] = { {
.phy_id = DP83865_PHY_ID,
.phy_id_mask = 0xfffffff0,
.name = "NatSemi DP83865",
- .features = PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = ns_config_init,
.config_aneg = genphy_config_aneg,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f424b867f73e..25f93a98863b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -143,13 +143,14 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
* Returns > 0 on success or < 0 on error. 0 means that auto-negotiation
* is still pending.
*/
-static inline int phy_aneg_done(struct phy_device *phydev)
+int phy_aneg_done(struct phy_device *phydev)
{
if (phydev->drv->aneg_done)
return phydev->drv->aneg_done(phydev);
return genphy_aneg_done(phydev);
}
+EXPORT_SYMBOL(phy_aneg_done);
/* A structure for mapping a particular speed and duplex
* combination to a particular SUPPORTED and ADVERTISED value
@@ -261,6 +262,41 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
}
/**
+ * phy_supported_speeds - return all speeds currently supported by a phy device
+ * @phy: The phy device to return supported speeds of.
+ * @speeds: buffer to store supported speeds in.
+ * @size: size of speeds buffer.
+ *
+ * Description: Returns the number of supported speeds, and fills the speeds
+ * buffer with the supported speeds. If speeds buffer is too small to contain
+ * all currently supported speeds, will return as many speeds as can fit.
+ */
+unsigned int phy_supported_speeds(struct phy_device *phy,
+ unsigned int *speeds,
+ unsigned int size)
+{
+ unsigned int count = 0;
+ unsigned int idx = 0;
+
+ while (idx < MAX_NUM_SETTINGS && count < size) {
+ idx = phy_find_valid(idx, phy->supported);
+
+ if (!(settings[idx].setting & phy->supported))
+ break;
+
+ /* Assumes settings are grouped by speed */
+ if ((count == 0) ||
+ (speeds[count - 1] != settings[idx].speed)) {
+ speeds[count] = settings[idx].speed;
+ count++;
+ }
+ idx++;
+ }
+
+ return count;
+}
+
+/**
* phy_check_valid - check if there is a valid PHY setting which matches
* speed, duplex, and feature mask
* @speed: speed to match
@@ -353,7 +389,7 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
phydev->duplex = cmd->duplex;
- phydev->mdix = cmd->eth_tp_mdix_ctrl;
+ phydev->mdix_ctrl = cmd->eth_tp_mdix_ctrl;
/* Restart the PHY */
phy_start_aneg(phydev);
@@ -407,7 +443,7 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
phydev->duplex = duplex;
- phydev->mdix = cmd->base.eth_tp_mdix_ctrl;
+ phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
/* Restart the PHY */
phy_start_aneg(phydev);
@@ -433,7 +469,8 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
cmd->transceiver = phy_is_internal(phydev) ?
XCVR_INTERNAL : XCVR_EXTERNAL;
cmd->autoneg = phydev->autoneg;
- cmd->eth_tp_mdix_ctrl = phydev->mdix;
+ cmd->eth_tp_mdix_ctrl = phydev->mdix_ctrl;
+ cmd->eth_tp_mdix = phydev->mdix;
return 0;
}
@@ -460,7 +497,8 @@ int phy_ethtool_ksettings_get(struct phy_device *phydev,
cmd->base.phy_address = phydev->mdio.addr;
cmd->base.autoneg = phydev->autoneg;
- cmd->base.eth_tp_mdix_ctrl = phydev->mdix;
+ cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
+ cmd->base.eth_tp_mdix = phydev->mdix;
return 0;
}
@@ -664,7 +702,7 @@ static void phy_error(struct phy_device *phydev)
* @phy_dat: phy_device pointer
*
* Description: When a PHY interrupt occurs, the handler disables
- * interrupts, and schedules a work task to clear the interrupt.
+ * interrupts, and uses phy_change to handle the interrupt.
*/
static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
@@ -673,15 +711,10 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
if (PHY_HALTED == phydev->state)
return IRQ_NONE; /* It can't be ours. */
- /* The MDIO bus is not allowed to be written in interrupt
- * context, so we need to disable the irq here. A work
- * queue will write the PHY to disable and clear the
- * interrupt, and then reenable the irq line.
- */
disable_irq_nosync(irq);
atomic_inc(&phydev->irq_disable);
- queue_work(system_power_efficient_wq, &phydev->phy_queue);
+ phy_change(phydev);
return IRQ_HANDLED;
}
@@ -739,10 +772,9 @@ phy_err:
int phy_start_interrupts(struct phy_device *phydev)
{
atomic_set(&phydev->irq_disable, 0);
- if (request_irq(phydev->irq, phy_interrupt,
- IRQF_SHARED,
- "phy_interrupt",
- phydev) < 0) {
+ if (request_threaded_irq(phydev->irq, NULL, phy_interrupt,
+ IRQF_ONESHOT | IRQF_SHARED,
+ phydev_name(phydev), phydev) < 0) {
pr_warn("%s: Can't get IRQ %d (PHY)\n",
phydev->mdio.bus->name, phydev->irq);
phydev->irq = PHY_POLL;
@@ -766,12 +798,6 @@ int phy_stop_interrupts(struct phy_device *phydev)
free_irq(phydev->irq, phydev);
- /* Cannot call flush_scheduled_work() here as desired because
- * of rtnl_lock(), but we do not really care about what would
- * be done, except from enable_irq(), so cancel any work
- * possibly pending and take care of the matter below.
- */
- cancel_work_sync(&phydev->phy_queue);
/* If work indeed has been cancelled, disable_irq() will have
* been left unbalanced from phy_interrupt() and enable_irq()
* has to be called so that other devices on the line work.
@@ -784,14 +810,11 @@ int phy_stop_interrupts(struct phy_device *phydev)
EXPORT_SYMBOL(phy_stop_interrupts);
/**
- * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
- * @work: work_struct that describes the work to be done
+ * phy_change - Called by the phy_interrupt to handle PHY changes
+ * @phydev: phy_device struct that interrupted
*/
-void phy_change(struct work_struct *work)
+void phy_change(struct phy_device *phydev)
{
- struct phy_device *phydev =
- container_of(work, struct phy_device, phy_queue);
-
if (phy_interrupt_is_valid(phydev)) {
if (phydev->drv->did_interrupt &&
!phydev->drv->did_interrupt(phydev))
@@ -833,6 +856,18 @@ phy_err:
}
/**
+ * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
+ * @work: work_struct that describes the work to be done
+ */
+void phy_change_work(struct work_struct *work)
+{
+ struct phy_device *phydev =
+ container_of(work, struct phy_device, phy_queue);
+
+ phy_change(phydev);
+}
+
+/**
* phy_stop - Bring down the PHY link, and stop checking the status
* @phydev: target phy_device struct
*/
@@ -911,6 +946,12 @@ void phy_start(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_start);
+static void phy_adjust_link(struct phy_device *phydev)
+{
+ phydev->adjust_link(phydev->attached_dev);
+ phy_led_trigger_change_speed(phydev);
+}
+
/**
* phy_state_machine - Handle the state machine
* @work: work_struct that describes the work to be done
@@ -953,7 +994,7 @@ void phy_state_machine(struct work_struct *work)
if (!phydev->link) {
phydev->state = PHY_NOLINK;
netif_carrier_off(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
break;
}
@@ -966,7 +1007,7 @@ void phy_state_machine(struct work_struct *work)
if (err > 0) {
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
} else if (0 == phydev->link_timeout--)
needs_aneg = true;
@@ -993,7 +1034,7 @@ void phy_state_machine(struct work_struct *work)
}
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
}
break;
case PHY_FORCING:
@@ -1009,7 +1050,7 @@ void phy_state_machine(struct work_struct *work)
needs_aneg = true;
}
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
break;
case PHY_RUNNING:
/* Only register a CHANGE if we are polling and link changed
@@ -1038,7 +1079,7 @@ void phy_state_machine(struct work_struct *work)
netif_carrier_off(phydev->attached_dev);
}
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
if (phy_interrupt_is_valid(phydev))
err = phy_config_interrupt(phydev,
@@ -1048,7 +1089,7 @@ void phy_state_machine(struct work_struct *work)
if (phydev->link) {
phydev->link = 0;
netif_carrier_off(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
do_suspend = true;
}
break;
@@ -1072,7 +1113,7 @@ void phy_state_machine(struct work_struct *work)
} else {
phydev->state = PHY_NOLINK;
}
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
} else {
phydev->state = PHY_AN;
phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -1088,7 +1129,7 @@ void phy_state_machine(struct work_struct *work)
} else {
phydev->state = PHY_NOLINK;
}
- phydev->adjust_link(phydev->attached_dev);
+ phy_adjust_link(phydev);
}
break;
}
@@ -1116,6 +1157,15 @@ void phy_state_machine(struct work_struct *work)
PHY_STATE_TIME * HZ);
}
+/**
+ * phy_mac_interrupt - MAC says the link has changed
+ * @phydev: phy_device struct with changed link
+ * @new_link: Link is Up/Down.
+ *
+ * Description: The MAC layer is able indicate there has been a change
+ * in the PHY link status. Set the new link status, and trigger the
+ * state machine, work a work queue.
+ */
void phy_mac_interrupt(struct phy_device *phydev, int new_link)
{
phydev->link = new_link;
@@ -1348,6 +1398,9 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+ /* Mask prohibited EEE modes */
+ val &= ~phydev->eee_broken_modes;
+
phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, val);
return 0;
@@ -1393,3 +1446,14 @@ int phy_ethtool_set_link_ksettings(struct net_device *ndev,
return phy_ethtool_ksettings_set(phydev, cmd);
}
EXPORT_SYMBOL(phy_ethtool_set_link_ksettings);
+
+int phy_ethtool_nway_reset(struct net_device *ndev)
+{
+ struct phy_device *phydev = ndev->phydev;
+
+ if (!phydev)
+ return -ENODEV;
+
+ return genphy_restart_aneg(phydev);
+}
+EXPORT_SYMBOL(phy_ethtool_nway_reset);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c4ceb082e970..9c06f8028f0c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/phy_led_triggers.h>
#include <linux/mdio.h>
#include <linux/io.h>
#include <linux/uaccess.h>
@@ -234,6 +235,53 @@ int phy_register_fixup_for_id(const char *bus_id,
}
EXPORT_SYMBOL(phy_register_fixup_for_id);
+/**
+ * phy_unregister_fixup - remove a phy_fixup from the list
+ * @bus_id: A string matches fixup->bus_id (or PHY_ANY_ID) in phy_fixup_list
+ * @phy_uid: A phy id matches fixup->phy_id (or PHY_ANY_UID) in phy_fixup_list
+ * @phy_uid_mask: Applied to phy_uid and fixup->phy_uid before comparison
+ */
+int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask)
+{
+ struct list_head *pos, *n;
+ struct phy_fixup *fixup;
+ int ret;
+
+ ret = -ENODEV;
+
+ mutex_lock(&phy_fixup_lock);
+ list_for_each_safe(pos, n, &phy_fixup_list) {
+ fixup = list_entry(pos, struct phy_fixup, list);
+
+ if ((!strcmp(fixup->bus_id, bus_id)) &&
+ ((fixup->phy_uid & phy_uid_mask) ==
+ (phy_uid & phy_uid_mask))) {
+ list_del(&fixup->list);
+ kfree(fixup);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&phy_fixup_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(phy_unregister_fixup);
+
+/* Unregisters a fixup of any PHY with the UID in phy_uid */
+int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask)
+{
+ return phy_unregister_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask);
+}
+EXPORT_SYMBOL(phy_unregister_fixup_for_uid);
+
+/* Unregisters a fixup of the PHY with id string bus_id */
+int phy_unregister_fixup_for_id(const char *bus_id)
+{
+ return phy_unregister_fixup(bus_id, PHY_ANY_UID, 0xffffffff);
+}
+EXPORT_SYMBOL(phy_unregister_fixup_for_id);
+
/* Returns 1 if fixup matches phydev in bus_id and phy_uid.
* Fixups can be set to match any in one or more fields.
*/
@@ -347,7 +395,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
mutex_init(&dev->lock);
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
- INIT_WORK(&dev->phy_queue, phy_change);
+ INIT_WORK(&dev->phy_queue, phy_change_work);
/* Request the appropriate module unconditionally; don't
* bother trying to do so only if it isn't already loaded,
@@ -919,13 +967,15 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
*/
err = phy_init_hw(phydev);
if (err)
- phy_detach(phydev);
- else
- phy_resume(phydev);
+ goto error;
+
+ phy_resume(phydev);
+ phy_led_triggers_register(phydev);
return err;
error:
+ phy_detach(phydev);
put_device(d);
if (ndev_owner != bus->owner)
module_put(bus->owner);
@@ -987,6 +1037,8 @@ void phy_detach(struct phy_device *phydev)
phydev->attached_dev = NULL;
phy_suspend(phydev);
+ phy_led_triggers_unregister(phydev);
+
/* If the device had no specific driver before (i.e. - it
* was using the generic driver), we unbind the device
* from the generic driver so that there's a chance a
@@ -1126,6 +1178,43 @@ static int genphy_config_advert(struct phy_device *phydev)
}
/**
+ * genphy_config_eee_advert - disable unwanted eee mode advertisement
+ * @phydev: target phy_device struct
+ *
+ * Description: Writes MDIO_AN_EEE_ADV after disabling unsupported energy
+ * efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't
+ * changed, and 1 if it has changed.
+ */
+static int genphy_config_eee_advert(struct phy_device *phydev)
+{
+ u32 broken = phydev->eee_broken_modes;
+ u32 old_adv, adv;
+
+ /* Nothing to disable */
+ if (!broken)
+ return 0;
+
+ /* If the following call fails, we assume that EEE is not
+ * supported by the phy. If we read 0, EEE is not advertised
+ * In both case, we don't need to continue
+ */
+ adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN);
+ if (adv <= 0)
+ return 0;
+
+ old_adv = adv;
+ adv &= ~broken;
+
+ /* Advertising remains unchanged with the broken mask */
+ if (old_adv == adv)
+ return 0;
+
+ phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, adv);
+
+ return 1;
+}
+
+/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
* @phydev: target phy_device struct
*
@@ -1183,15 +1272,20 @@ EXPORT_SYMBOL(genphy_restart_aneg);
*/
int genphy_config_aneg(struct phy_device *phydev)
{
- int result;
+ int err, changed;
+
+ changed = genphy_config_eee_advert(phydev);
if (AUTONEG_ENABLE != phydev->autoneg)
return genphy_setup_forced(phydev);
- result = genphy_config_advert(phydev);
- if (result < 0) /* error */
- return result;
- if (result == 0) {
+ err = genphy_config_advert(phydev);
+ if (err < 0) /* error */
+ return err;
+
+ changed |= err;
+
+ if (changed == 0) {
/* Advertisement hasn't changed, but maybe aneg was never on to
* begin with? Or maybe phy was isolated?
*/
@@ -1201,16 +1295,16 @@ int genphy_config_aneg(struct phy_device *phydev)
return ctl;
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
- result = 1; /* do restart aneg */
+ changed = 1; /* do restart aneg */
}
/* Only restart aneg if we are advertising something different
* than we were before.
*/
- if (result > 0)
- result = genphy_restart_aneg(phydev);
+ if (changed > 0)
+ return genphy_restart_aneg(phydev);
- return result;
+ return 0;
}
EXPORT_SYMBOL(genphy_config_aneg);
@@ -1568,6 +1662,21 @@ static void of_set_phy_supported(struct phy_device *phydev)
__set_phy_supported(phydev, max_speed);
}
+static void of_set_phy_eee_broken(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ u32 broken;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (!of_property_read_u32(node, "eee-broken-modes", &broken))
+ phydev->eee_broken_modes = broken;
+}
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
@@ -1605,6 +1714,30 @@ static int phy_probe(struct device *dev)
of_set_phy_supported(phydev);
phydev->advertising = phydev->supported;
+ /* Get the EEE modes we want to prohibit. We will ask
+ * the PHY stop advertising these mode later on
+ */
+ of_set_phy_eee_broken(phydev);
+
+ /* The Pause Frame bits indicate that the PHY can support passing
+ * pause frames. During autonegotiation, the PHYs will determine if
+ * they should allow pause frames to pass. The MAC driver should then
+ * use that result to determine whether to enable flow control via
+ * pause frames.
+ *
+ * Normally, PHY drivers should not set the Pause bits, and instead
+ * allow phylib to do that. However, there may be some situations
+ * (e.g. hardware erratum) where the driver wants to set only one
+ * of these bits.
+ */
+ if (phydrv->features & (SUPPORTED_Pause | SUPPORTED_Asym_Pause)) {
+ phydev->supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ phydev->supported |= phydrv->features &
+ (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ } else {
+ phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ }
+
/* Set the state to READY by default */
phydev->state = PHY_READY;
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
new file mode 100644
index 000000000000..fa62bdf2f526
--- /dev/null
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -0,0 +1,134 @@
+/* Copyright (C) 2016 National Instruments Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/leds.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+static struct phy_led_trigger *phy_speed_to_led_trigger(struct phy_device *phy,
+ unsigned int speed)
+{
+ unsigned int i;
+
+ for (i = 0; i < phy->phy_num_led_triggers; i++) {
+ if (phy->phy_led_triggers[i].speed == speed)
+ return &phy->phy_led_triggers[i];
+ }
+ return NULL;
+}
+
+void phy_led_trigger_change_speed(struct phy_device *phy)
+{
+ struct phy_led_trigger *plt;
+
+ if (!phy->link)
+ goto out_change_speed;
+
+ if (phy->speed == 0)
+ return;
+
+ plt = phy_speed_to_led_trigger(phy, phy->speed);
+ if (!plt) {
+ netdev_alert(phy->attached_dev,
+ "No phy led trigger registered for speed(%d)\n",
+ phy->speed);
+ goto out_change_speed;
+ }
+
+ if (plt != phy->last_triggered) {
+ led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
+ led_trigger_event(&plt->trigger, LED_FULL);
+ phy->last_triggered = plt;
+ }
+ return;
+
+out_change_speed:
+ if (phy->last_triggered) {
+ led_trigger_event(&phy->last_triggered->trigger,
+ LED_OFF);
+ phy->last_triggered = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(phy_led_trigger_change_speed);
+
+static int phy_led_trigger_register(struct phy_device *phy,
+ struct phy_led_trigger *plt,
+ unsigned int speed)
+{
+ char name_suffix[PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE];
+
+ plt->speed = speed;
+
+ if (speed < SPEED_1000)
+ snprintf(name_suffix, sizeof(name_suffix), "%dMbps", speed);
+ else if (speed == SPEED_2500)
+ snprintf(name_suffix, sizeof(name_suffix), "2.5Gbps");
+ else
+ snprintf(name_suffix, sizeof(name_suffix), "%dGbps",
+ DIV_ROUND_CLOSEST(speed, 1000));
+
+ snprintf(plt->name, sizeof(plt->name), PHY_ID_FMT ":%s",
+ phy->mdio.bus->id, phy->mdio.addr, name_suffix);
+ plt->trigger.name = plt->name;
+
+ return led_trigger_register(&plt->trigger);
+}
+
+static void phy_led_trigger_unregister(struct phy_led_trigger *plt)
+{
+ led_trigger_unregister(&plt->trigger);
+}
+
+int phy_led_triggers_register(struct phy_device *phy)
+{
+ int i, err;
+ unsigned int speeds[50];
+
+ phy->phy_num_led_triggers = phy_supported_speeds(phy, speeds,
+ ARRAY_SIZE(speeds));
+ if (!phy->phy_num_led_triggers)
+ return 0;
+
+ phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev,
+ sizeof(struct phy_led_trigger) *
+ phy->phy_num_led_triggers,
+ GFP_KERNEL);
+ if (!phy->phy_led_triggers)
+ return -ENOMEM;
+
+ for (i = 0; i < phy->phy_num_led_triggers; i++) {
+ err = phy_led_trigger_register(phy, &phy->phy_led_triggers[i],
+ speeds[i]);
+ if (err)
+ goto out_unreg;
+ }
+
+ phy->last_triggered = NULL;
+ phy_led_trigger_change_speed(phy);
+
+ return 0;
+out_unreg:
+ while (i--)
+ phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+ devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
+ return err;
+}
+EXPORT_SYMBOL_GPL(phy_led_triggers_register);
+
+void phy_led_triggers_unregister(struct phy_device *phy)
+{
+ int i;
+
+ for (i = 0; i < phy->phy_num_led_triggers; i++)
+ phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+}
+EXPORT_SYMBOL_GPL(phy_led_triggers_unregister);
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index b62c4aaee40b..fb32eaf2255d 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -168,8 +168,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN83C185",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
@@ -191,8 +190,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN8187",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
@@ -214,8 +212,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN8700",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
@@ -237,8 +234,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN911x Internal PHY",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
@@ -259,8 +255,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN8710/LAN8720",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
@@ -282,8 +277,7 @@ static struct phy_driver smsc_phy_driver[] = {
.phy_id_mask = 0xfffffff0,
.name = "SMSC LAN8740",
- .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
.probe = smsc_phy_probe,
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 24b4a09468dd..f78ff0279648 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -69,6 +69,7 @@
#define PHY_ID_VSC8234 0x000fc620
#define PHY_ID_VSC8244 0x000fc6c0
#define PHY_ID_VSC8514 0x00070670
+#define PHY_ID_VSC8572 0x000704d0
#define PHY_ID_VSC8574 0x000704a0
#define PHY_ID_VSC8601 0x00070420
#define PHY_ID_VSC8662 0x00070660
@@ -166,6 +167,7 @@ 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_VSC8572 ||
phydev->drv->phy_id == PHY_ID_VSC8574 ||
phydev->drv->phy_id == PHY_ID_VSC8601) ?
MII_VSC8244_IMASK_MASK :
@@ -291,6 +293,17 @@ static struct phy_driver vsc82xx_driver[] = {
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
}, {
+ .phy_id = PHY_ID_VSC8572,
+ .name = "Vitesse VSC8572",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc824x_config_init,
+ .config_aneg = &vsc82x4_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+}, {
.phy_id = PHY_ID_VSC8574,
.name = "Vitesse VSC8574",
.phy_id_mask = 0x000ffff0,
@@ -355,6 +368,7 @@ static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
{ PHY_ID_VSC8234, 0x000ffff0 },
{ PHY_ID_VSC8244, 0x000fffc0 },
{ PHY_ID_VSC8514, 0x000ffff0 },
+ { PHY_ID_VSC8572, 0x000ffff0 },
{ PHY_ID_VSC8574, 0x000ffff0 },
{ PHY_ID_VSC8662, 0x000ffff0 },
{ PHY_ID_VSC8221, 0x000ffff0 },
diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c
index 9c4b41a4df7d..3c55ea357f35 100644
--- a/drivers/net/plip/plip.c
+++ b/drivers/net/plip/plip.c
@@ -270,7 +270,6 @@ static const struct net_device_ops plip_netdev_ops = {
.ndo_stop = plip_close,
.ndo_start_xmit = plip_tx_packet,
.ndo_do_ioctl = plip_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5489c0ec1d9a..3d3b1f4339ef 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -204,7 +204,7 @@ static atomic_t ppp_unit_count = ATOMIC_INIT(0);
static atomic_t channel_count = ATOMIC_INIT(0);
/* per-net private data for this module */
-static int ppp_net_id __read_mostly;
+static unsigned int ppp_net_id __read_mostly;
struct ppp_net {
/* units to ppp mapping */
struct idr units_idr;
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 4ddae8118c85..f017c72bb7fd 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -95,7 +95,7 @@ static const struct proto_ops pppoe_ops;
static const struct ppp_channel_ops pppoe_chan_ops;
/* per-net private data for this module */
-static int pppoe_net_id __read_mostly;
+static unsigned int pppoe_net_id __read_mostly;
struct pppoe_net {
/*
* we could use _single_ hash table for all
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index a31f4610b493..300bb1479b3a 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -466,17 +466,6 @@ static void rionet_set_msglevel(struct net_device *ndev, u32 value)
rnet->msg_enable = value;
}
-static int rionet_change_mtu(struct net_device *ndev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > RIONET_MAX_MTU)) {
- printk(KERN_ERR "%s: Invalid MTU size %d\n",
- ndev->name, new_mtu);
- return -EINVAL;
- }
- ndev->mtu = new_mtu;
- return 0;
-}
-
static const struct ethtool_ops rionet_ethtool_ops = {
.get_drvinfo = rionet_get_drvinfo,
.get_msglevel = rionet_get_msglevel,
@@ -488,7 +477,6 @@ static const struct net_device_ops rionet_netdev_ops = {
.ndo_open = rionet_open,
.ndo_stop = rionet_close,
.ndo_start_xmit = rionet_start_xmit,
- .ndo_change_mtu = rionet_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
@@ -525,6 +513,9 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
ndev->netdev_ops = &rionet_netdev_ops;
ndev->mtu = RIONET_MAX_MTU;
+ /* MTU range: 68 - 4082 */
+ ndev->min_mtu = ETH_MIN_MTU;
+ ndev->max_mtu = RIONET_MAX_MTU;
ndev->features = NETIF_F_LLTX;
SET_NETDEV_DEV(ndev, &mport->dev);
ndev->ethtool_ops = &rionet_ethtool_ops;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index aad0b59d41e3..8b8b53259783 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -141,7 +141,6 @@ static const struct net_device_ops sb1000_netdev_ops = {
.ndo_start_xmit = sb1000_start_xmit,
.ndo_do_ioctl = sb1000_dev_ioctl,
.ndo_stop = sb1000_close,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 9ed6d1c1ee45..7e933d8ff811 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -561,12 +561,7 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu)
{
struct slip *sl = netdev_priv(dev);
- if (new_mtu < 68 || new_mtu > 65534)
- return -EINVAL;
-
- if (new_mtu != dev->mtu)
- return sl_realloc_bufs(sl, new_mtu);
- return 0;
+ return sl_realloc_bufs(sl, new_mtu);
}
/* Netdevice get statistics request */
@@ -663,6 +658,10 @@ static void sl_setup(struct net_device *dev)
dev->addr_len = 0;
dev->tx_queue_len = 10;
+ /* MTU range: 68 - 65534 */
+ dev->min_mtu = 68;
+ dev->max_mtu = 65534;
+
/* New-style flags. */
dev->flags = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
}
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index a380649bf6b5..bdc58567d10e 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2150,13 +2150,7 @@ static struct rtnl_link_ops team_link_ops __read_mostly = {
* Generic netlink custom interface
***********************************/
-static struct genl_family team_nl_family = {
- .id = GENL_ID_GENERATE,
- .name = TEAM_GENL_NAME,
- .version = TEAM_GENL_VERSION,
- .maxattr = TEAM_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family team_nl_family;
static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = {
[TEAM_ATTR_UNSPEC] = { .type = NLA_UNSPEC, },
@@ -2746,6 +2740,18 @@ static const struct genl_multicast_group team_nl_mcgrps[] = {
{ .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, },
};
+static struct genl_family team_nl_family __ro_after_init = {
+ .name = TEAM_GENL_NAME,
+ .version = TEAM_GENL_VERSION,
+ .maxattr = TEAM_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = team_nl_ops,
+ .n_ops = ARRAY_SIZE(team_nl_ops),
+ .mcgrps = team_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(team_nl_mcgrps),
+};
+
static int team_nl_send_multicast(struct sk_buff *skb,
struct team *team, u32 portid)
{
@@ -2767,10 +2773,9 @@ static int team_nl_send_event_port_get(struct team *team,
port);
}
-static int team_nl_init(void)
+static int __init team_nl_init(void)
{
- return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops,
- team_nl_mcgrps);
+ return genl_register_family(&team_nl_family);
}
static void team_nl_fini(void)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index db6acecabeaa..a569e61bc1d9 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -878,13 +878,6 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
sk_filter(tfile->socket.sk, skb))
goto drop;
- /* Limit the number of packets queued by dividing txq length with the
- * number of queues.
- */
- if (skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues
- >= dev->tx_queue_len)
- goto drop;
-
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
goto drop;
@@ -925,18 +918,6 @@ static void tun_net_mclist(struct net_device *dev)
*/
}
-#define MIN_MTU 68
-#define MAX_MTU 65535
-
-static int
-tun_net_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU)
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static netdev_features_t tun_net_fix_features(struct net_device *dev,
netdev_features_t features)
{
@@ -1014,7 +995,6 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_open = tun_net_open,
.ndo_stop = tun_net_close,
.ndo_start_xmit = tun_net_xmit,
- .ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features,
.ndo_select_queue = tun_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1029,7 +1009,6 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_open = tun_net_open,
.ndo_stop = tun_net_close,
.ndo_start_xmit = tun_net_xmit,
- .ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features,
.ndo_set_rx_mode = tun_net_mclist,
.ndo_set_mac_address = eth_mac_addr,
@@ -1062,6 +1041,9 @@ static void tun_flow_uninit(struct tun_struct *tun)
tun_flow_flush(tun);
}
+#define MIN_MTU 68
+#define MAX_MTU 65535
+
/* Initialize net device. */
static void tun_net_init(struct net_device *dev)
{
@@ -1092,6 +1074,9 @@ static void tun_net_init(struct net_device *dev)
break;
}
+
+ dev->min_mtu = MIN_MTU;
+ dev->max_mtu = MAX_MTU - dev->hard_header_len;
}
/* Character device part */
@@ -1255,8 +1240,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
return -EFAULT;
}
- err = virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun));
- if (err) {
+ if (virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun))) {
this_cpu_inc(tun->pcpu_stats->rx_frame_errors);
kfree_skb(skb);
return -EINVAL;
@@ -1302,7 +1286,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb_probe_transport_header(skb, 0);
rxhash = skb_get_hash(skb);
+#ifndef CONFIG_4KSTACKS
+ local_bh_disable();
+ netif_receive_skb(skb);
+ local_bh_enable();
+#else
netif_rx_ni(skb);
+#endif
stats = get_cpu_ptr(tun->pcpu_stats);
u64_stats_update_begin(&stats->syncp);
@@ -1367,15 +1357,13 @@ static ssize_t tun_put_user(struct tun_struct *tun,
}
if (vnet_hdr_sz) {
- struct virtio_net_hdr gso = { 0 }; /* no info leak */
- int ret;
+ struct virtio_net_hdr gso;
if (iov_iter_count(iter) < vnet_hdr_sz)
return -EINVAL;
- ret = virtio_net_hdr_from_skb(skb, &gso,
- tun_is_little_endian(tun));
- if (ret) {
+ if (virtio_net_hdr_from_skb(skb, &gso,
+ tun_is_little_endian(tun))) {
struct skb_shared_info *sinfo = skb_shinfo(skb);
pr_err("unexpected GSO type: "
"0x%x, gso_size %d, hdr_len %d\n",
@@ -1991,7 +1979,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
int le;
int ret;
- if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
+ if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == SOCK_IOC_TYPE) {
if (copy_from_user(&ifr, argp, ifreq_len))
return -EFAULT;
} else {
@@ -2011,7 +1999,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
rtnl_lock();
tun = __tun_get(tfile);
- if (cmd == TUNSETIFF && !tun) {
+ if (cmd == TUNSETIFF) {
+ ret = -EEXIST;
+ if (tun)
+ goto unlock;
+
ifr.ifr_name[IFNAMSIZ-1] = '\0';
ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr);
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index cdde59089f72..3dd490f53e48 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -114,6 +114,11 @@ config USB_LAN78XX
help
This option adds support for Microchip LAN78XX based USB 2
& USB 3 10/100/1000 Ethernet adapters.
+ LAN7800 : USB 3 to 10/100/1000 Ethernet adapter
+ LAN7850 : USB 2 to 10/100/1000 Ethernet adapter
+ LAN7801 : USB 3 to 10/100/1000 Ethernet adapter (MAC only)
+
+ Proper PHY driver is required for LAN7801.
To compile this driver as a module, choose M here: the
module will be called lan78xx.
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index dc7b6392e75a..6c646e228833 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -1026,9 +1026,6 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu)
netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu);
- if (new_mtu <= 0 || ll_mtu > 16384)
- return -EINVAL;
-
if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
@@ -1081,6 +1078,7 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->netdev_ops = &ax88178_netdev_ops;
dev->net->ethtool_ops = &ax88178_ethtool_ops;
+ dev->net->max_mtu = 16384 - (dev->net->hard_header_len + 4);
/* Blink LEDS so users know driver saw dongle */
asix_sw_reset(dev, 0, 0);
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index 49a3bc107d05..6308386b09df 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -149,14 +149,6 @@ static const struct net_device_ops ax88172a_netdev_ops = {
.ndo_set_rx_mode = asix_set_multicast,
};
-static int ax88172a_nway_reset(struct net_device *net)
-{
- if (!net->phydev)
- return -ENODEV;
-
- return phy_start_aneg(net->phydev);
-}
-
static const struct ethtool_ops ax88172a_ethtool_ops = {
.get_drvinfo = asix_get_drvinfo,
.get_link = usbnet_get_link,
@@ -167,7 +159,7 @@ static const struct ethtool_ops ax88172a_ethtool_ops = {
.get_eeprom_len = asix_get_eeprom_len,
.get_eeprom = asix_get_eeprom,
.set_eeprom = asix_set_eeprom,
- .nway_reset = ax88172a_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 8a6675d92b98..a3a7db0702d8 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -907,9 +907,6 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu)
struct usbnet *dev = netdev_priv(net);
u16 tmp16;
- if (new_mtu <= 0 || new_mtu > 4088)
- return -EINVAL;
-
net->mtu = new_mtu;
dev->hard_mtu = net->mtu + net->hard_header_len;
@@ -1266,6 +1263,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->netdev_ops = &ax88179_netdev_ops;
dev->net->ethtool_ops = &ax88179_ethtool_ops;
dev->net->needed_headroom = 8;
+ dev->net->max_mtu = 4088;
/* Initialize MII structure */
dev->mii.dev = dev->net;
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index d9ca05d3ac8e..a1f2f6f1e614 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -761,7 +761,6 @@ static const struct net_device_ops catc_netdev_ops = {
.ndo_tx_timeout = catc_tx_timeout,
.ndo_set_rx_mode = catc_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index ff2270ead2e6..eb52de8205f0 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -276,21 +276,11 @@ static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -ENOIOCTLCMD;
}
-static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops usbpn_ops = {
.ndo_open = usbpn_open,
.ndo_stop = usbpn_close,
.ndo_start_xmit = usbpn_xmit,
.ndo_do_ioctl = usbpn_ioctl,
- .ndo_change_mtu = usbpn_set_mtu,
};
static void usbpn_setup(struct net_device *dev)
@@ -301,6 +291,8 @@ static void usbpn_setup(struct net_device *dev)
dev->type = ARPHRD_PHONET;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = PHONET_MAX_MTU;
+ dev->min_mtu = PHONET_MIN_MTU;
+ dev->max_mtu = PHONET_MAX_MTU;
dev->hard_header_len = 1;
dev->dev_addr[0] = PN_MEDIA_USB;
dev->addr_len = 1;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index dd623f674487..fe7b2886cb6b 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -711,6 +711,20 @@ static const struct usb_device_id products[] = {
.driver_info = 0,
},
+/* ThinkPad USB-C Dock (based on Realtek RTL8153) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
+/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
{
USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM,
@@ -718,6 +732,20 @@ static const struct usb_device_id products[] = {
.driver_info = 0,
},
+/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
+/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
{
USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index afbfc0f656f3..2d1a6f2e16ab 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -740,10 +740,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
int cdc_ncm_change_mtu(struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
- int maxmtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev);
-
- if (new_mtu <= 0 || new_mtu > maxmtu)
- return -EINVAL;
net->mtu = new_mtu;
cdc_ncm_set_dgram_size(dev, new_mtu + cdc_ncm_eth_hlen(dev));
@@ -913,6 +909,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
/* must handle MTU changes */
dev->net->netdev_ops = &cdc_ncm_netdev_ops;
+ dev->net->max_mtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev);
return 0;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 66b34ddbe216..338aed5da14d 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -982,7 +982,6 @@ static const struct net_device_ops kaweth_netdev_ops = {
.ndo_tx_timeout = kaweth_tx_timeout,
.ndo_set_rx_mode = kaweth_set_rx_mode,
.ndo_get_stats = kaweth_netdev_stats,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index f33460cec79f..08f8703e4d54 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -30,13 +30,17 @@
#include <linux/ipv6.h>
#include <linux/mdio.h>
#include <net/ip6_checksum.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.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.4"
+#define DRIVER_VERSION "1.0.6"
#define TX_TIMEOUT_JIFFIES (5 * HZ)
#define THROTTLE_JIFFIES (HZ / 8)
@@ -63,6 +67,7 @@
#define LAN78XX_USB_VENDOR_ID (0x0424)
#define LAN7800_USB_PRODUCT_ID (0x7800)
#define LAN7850_USB_PRODUCT_ID (0x7850)
+#define LAN7801_USB_PRODUCT_ID (0x7801)
#define LAN78XX_EEPROM_MAGIC (0x78A5)
#define LAN78XX_OTP_MAGIC (0x78F3)
@@ -89,6 +94,38 @@
/* statistic update interval (mSec) */
#define STAT_UPDATE_TIMER (1 * 1000)
+/* defines interrupts from interrupt EP */
+#define MAX_INT_EP (32)
+#define INT_EP_INTEP (31)
+#define INT_EP_OTP_WR_DONE (28)
+#define INT_EP_EEE_TX_LPI_START (26)
+#define INT_EP_EEE_TX_LPI_STOP (25)
+#define INT_EP_EEE_RX_LPI (24)
+#define INT_EP_MAC_RESET_TIMEOUT (23)
+#define INT_EP_RDFO (22)
+#define INT_EP_TXE (21)
+#define INT_EP_USB_STATUS (20)
+#define INT_EP_TX_DIS (19)
+#define INT_EP_RX_DIS (18)
+#define INT_EP_PHY (17)
+#define INT_EP_DP (16)
+#define INT_EP_MAC_ERR (15)
+#define INT_EP_TDFU (14)
+#define INT_EP_TDFO (13)
+#define INT_EP_UTX (12)
+#define INT_EP_GPIO_11 (11)
+#define INT_EP_GPIO_10 (10)
+#define INT_EP_GPIO_9 (9)
+#define INT_EP_GPIO_8 (8)
+#define INT_EP_GPIO_7 (7)
+#define INT_EP_GPIO_6 (6)
+#define INT_EP_GPIO_5 (5)
+#define INT_EP_GPIO_4 (4)
+#define INT_EP_GPIO_3 (3)
+#define INT_EP_GPIO_2 (2)
+#define INT_EP_GPIO_1 (1)
+#define INT_EP_GPIO_0 (0)
+
static const char lan78xx_gstrings[][ETH_GSTRING_LEN] = {
"RX FCS Errors",
"RX Alignment Errors",
@@ -296,6 +333,15 @@ struct statstage {
struct lan78xx_statstage64 curr_stat;
};
+struct irq_domain_data {
+ struct irq_domain *irqdomain;
+ unsigned int phyirq;
+ struct irq_chip *irqchip;
+ irq_flow_handler_t irq_handler;
+ u32 irqenable;
+ struct mutex irq_lock; /* for irq bus access */
+};
+
struct lan78xx_net {
struct net_device *net;
struct usb_device *udev;
@@ -345,14 +391,21 @@ struct lan78xx_net {
u32 chipid;
u32 chiprev;
struct mii_bus *mdiobus;
+ phy_interface_t interface;
int fc_autoneg;
u8 fc_request_control;
int delta;
struct statstage stats;
+
+ struct irq_domain_data domain_data;
};
+/* define external phy id */
+#define PHY_LAN8835 (0x0007C130)
+#define PHY_KSZ9031RNX (0x00221620)
+
/* use ethtool to change the level for any given device */
static int msg_level = -1;
module_param(msg_level, int, 0);
@@ -1092,15 +1145,10 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex,
static int lan78xx_link_reset(struct lan78xx_net *dev)
{
struct phy_device *phydev = dev->net->phydev;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ethtool_link_ksettings ecmd;
int ladv, radv, ret;
u32 buf;
- /* clear PHY interrupt status */
- ret = phy_read(phydev, LAN88XX_INT_STS);
- if (unlikely(ret < 0))
- return -EIO;
-
/* clear LAN78xx interrupt status */
ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_);
if (unlikely(ret < 0))
@@ -1120,18 +1168,14 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
if (unlikely(ret < 0))
return -EIO;
- phy_mac_interrupt(phydev, 0);
-
del_timer(&dev->stat_monitor);
} else if (phydev->link && !dev->link_on) {
dev->link_on = true;
- phy_ethtool_gset(phydev, &ecmd);
-
- ret = phy_read(phydev, LAN88XX_INT_STS);
+ phy_ethtool_ksettings_get(phydev, &ecmd);
if (dev->udev->speed == USB_SPEED_SUPER) {
- if (ethtool_cmd_speed(&ecmd) == 1000) {
+ if (ecmd.base.speed == 1000) {
/* disable U2 */
ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
buf &= ~USB_CFG1_DEV_U2_INIT_EN_;
@@ -1159,10 +1203,10 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
netif_dbg(dev, link, dev->net,
"speed: %u duplex: %d anadv: 0x%04x anlpa: 0x%04x",
- ethtool_cmd_speed(&ecmd), ecmd.duplex, ladv, radv);
+ ecmd.base.speed, ecmd.base.duplex, ladv, radv);
- ret = lan78xx_update_flowcontrol(dev, ecmd.duplex, ladv, radv);
- phy_mac_interrupt(phydev, 1);
+ ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv,
+ radv);
if (!timer_pending(&dev->stat_monitor)) {
dev->delta = 1;
@@ -1201,7 +1245,10 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb)
if (intdata & INT_ENP_PHY_INT) {
netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata);
- lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
+ lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
+
+ if (dev->domain_data.phyirq > 0)
+ generic_handle_irq(dev->domain_data.phyirq);
} else
netdev_warn(dev->net,
"unexpected interrupt: 0x%08x\n", intdata);
@@ -1406,11 +1453,6 @@ static u32 lan78xx_get_link(struct net_device *net)
return net->phydev->link;
}
-static int lan78xx_nway_reset(struct net_device *net)
-{
- return phy_start_aneg(net->phydev);
-}
-
static void lan78xx_get_drvinfo(struct net_device *net,
struct ethtool_drvinfo *info)
{
@@ -1435,88 +1477,26 @@ 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)
+static int lan78xx_get_link_ksettings(struct net_device *net,
+ struct ethtool_link_ksettings *cmd)
{
struct lan78xx_net *dev = netdev_priv(net);
struct phy_device *phydev = net->phydev;
int ret;
- int buf;
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
- ret = phy_ethtool_gset(phydev, cmd);
-
- buf = lan78xx_get_mdix_status(net);
-
- 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 == LAN88XX_EXT_MODE_CTRL_MDI_) {
- cmd->eth_tp_mdix = ETH_TP_MDI;
- cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
- } 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;
- }
+ ret = phy_ethtool_ksettings_get(phydev, cmd);
usb_autopm_put_interface(dev->intf);
return ret;
}
-static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int lan78xx_set_link_ksettings(struct net_device *net,
+ const struct ethtool_link_ksettings *cmd)
{
struct lan78xx_net *dev = netdev_priv(net);
struct phy_device *phydev = net->phydev;
@@ -1527,14 +1507,10 @@ static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
if (ret < 0)
return ret;
- if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) {
- lan78xx_set_mdix_status(net, cmd->eth_tp_mdix_ctrl);
- }
-
/* change speed & duplex */
- ret = phy_ethtool_sset(phydev, cmd);
+ ret = phy_ethtool_ksettings_set(phydev, cmd);
- if (!cmd->autoneg) {
+ if (!cmd->base.autoneg) {
/* force link down */
temp = phy_read(phydev, MII_BMCR);
phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK);
@@ -1552,9 +1528,9 @@ static void lan78xx_get_pause(struct net_device *net,
{
struct lan78xx_net *dev = netdev_priv(net);
struct phy_device *phydev = net->phydev;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ethtool_link_ksettings ecmd;
- phy_ethtool_gset(phydev, &ecmd);
+ phy_ethtool_ksettings_get(phydev, &ecmd);
pause->autoneg = dev->fc_autoneg;
@@ -1570,12 +1546,12 @@ static int lan78xx_set_pause(struct net_device *net,
{
struct lan78xx_net *dev = netdev_priv(net);
struct phy_device *phydev = net->phydev;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ethtool_link_ksettings ecmd;
int ret;
- phy_ethtool_gset(phydev, &ecmd);
+ phy_ethtool_ksettings_get(phydev, &ecmd);
- if (pause->autoneg && !ecmd.autoneg) {
+ if (pause->autoneg && !ecmd.base.autoneg) {
ret = -EINVAL;
goto exit;
}
@@ -1587,13 +1563,21 @@ static int lan78xx_set_pause(struct net_device *net,
if (pause->tx_pause)
dev->fc_request_control |= FLOW_CTRL_TX;
- if (ecmd.autoneg) {
+ if (ecmd.base.autoneg) {
u32 mii_adv;
+ u32 advertising;
- ecmd.advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+ ethtool_convert_link_mode_to_legacy_u32(
+ &advertising, ecmd.link_modes.advertising);
+
+ advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
- ecmd.advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
- phy_ethtool_sset(phydev, &ecmd);
+ advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
+
+ ethtool_convert_legacy_u32_to_link_mode(
+ ecmd.link_modes.advertising, advertising);
+
+ phy_ethtool_ksettings_set(phydev, &ecmd);
}
dev->fc_autoneg = pause->autoneg;
@@ -1605,12 +1589,10 @@ exit:
static const struct ethtool_ops lan78xx_ethtool_ops = {
.get_link = lan78xx_get_link,
- .nway_reset = lan78xx_nway_reset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_drvinfo = lan78xx_get_drvinfo,
.get_msglevel = lan78xx_get_msglevel,
.set_msglevel = lan78xx_set_msglevel,
- .get_settings = lan78xx_get_settings,
- .set_settings = lan78xx_set_settings,
.get_eeprom_len = lan78xx_ethtool_get_eeprom_len,
.get_eeprom = lan78xx_ethtool_get_eeprom,
.set_eeprom = lan78xx_ethtool_set_eeprom,
@@ -1623,6 +1605,8 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
.set_eee = lan78xx_set_eee,
.get_pauseparam = lan78xx_get_pause,
.set_pauseparam = lan78xx_set_pause,
+ .get_link_ksettings = lan78xx_get_link_ksettings,
+ .set_link_ksettings = lan78xx_set_link_ksettings,
};
static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -1719,6 +1703,7 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)
done:
mutex_unlock(&dev->phy_mutex);
usb_autopm_put_interface(dev->intf);
+
return ret;
}
@@ -1781,6 +1766,10 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev)
/* set to internal PHY id */
dev->mdiobus->phy_mask = ~(1 << 1);
break;
+ case ID_REV_CHIP_ID_7801_:
+ /* scan thru PHYAD[2..0] */
+ dev->mdiobus->phy_mask = ~(0xFF);
+ break;
}
ret = mdiobus_register(dev->mdiobus);
@@ -1834,6 +1823,168 @@ static void lan78xx_link_status_change(struct net_device *net)
}
}
+static int irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct irq_domain_data *data = d->host_data;
+
+ irq_set_chip_data(irq, data);
+ irq_set_chip_and_handler(irq, data->irqchip, data->irq_handler);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static void irq_unmap(struct irq_domain *d, unsigned int irq)
+{
+ irq_set_chip_and_handler(irq, NULL, NULL);
+ irq_set_chip_data(irq, NULL);
+}
+
+static const struct irq_domain_ops chip_domain_ops = {
+ .map = irq_map,
+ .unmap = irq_unmap,
+};
+
+static void lan78xx_irq_mask(struct irq_data *irqd)
+{
+ struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd);
+
+ data->irqenable &= ~BIT(irqd_to_hwirq(irqd));
+}
+
+static void lan78xx_irq_unmask(struct irq_data *irqd)
+{
+ struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd);
+
+ data->irqenable |= BIT(irqd_to_hwirq(irqd));
+}
+
+static void lan78xx_irq_bus_lock(struct irq_data *irqd)
+{
+ struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd);
+
+ mutex_lock(&data->irq_lock);
+}
+
+static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd)
+{
+ struct irq_domain_data *data = irq_data_get_irq_chip_data(irqd);
+ struct lan78xx_net *dev =
+ container_of(data, struct lan78xx_net, domain_data);
+ u32 buf;
+ int ret;
+
+ /* call register access here because irq_bus_lock & irq_bus_sync_unlock
+ * are only two callbacks executed in non-atomic contex.
+ */
+ ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ if (buf != data->irqenable)
+ ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
+
+ mutex_unlock(&data->irq_lock);
+}
+
+static struct irq_chip lan78xx_irqchip = {
+ .name = "lan78xx-irqs",
+ .irq_mask = lan78xx_irq_mask,
+ .irq_unmask = lan78xx_irq_unmask,
+ .irq_bus_lock = lan78xx_irq_bus_lock,
+ .irq_bus_sync_unlock = lan78xx_irq_bus_sync_unlock,
+};
+
+static int lan78xx_setup_irq_domain(struct lan78xx_net *dev)
+{
+ struct device_node *of_node;
+ struct irq_domain *irqdomain;
+ unsigned int irqmap = 0;
+ u32 buf;
+ int ret = 0;
+
+ of_node = dev->udev->dev.parent->of_node;
+
+ mutex_init(&dev->domain_data.irq_lock);
+
+ lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ dev->domain_data.irqenable = buf;
+
+ dev->domain_data.irqchip = &lan78xx_irqchip;
+ dev->domain_data.irq_handler = handle_simple_irq;
+
+ irqdomain = irq_domain_add_simple(of_node, MAX_INT_EP, 0,
+ &chip_domain_ops, &dev->domain_data);
+ if (irqdomain) {
+ /* create mapping for PHY interrupt */
+ irqmap = irq_create_mapping(irqdomain, INT_EP_PHY);
+ if (!irqmap) {
+ irq_domain_remove(irqdomain);
+
+ irqdomain = NULL;
+ ret = -EINVAL;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+ dev->domain_data.irqdomain = irqdomain;
+ dev->domain_data.phyirq = irqmap;
+
+ return ret;
+}
+
+static void lan78xx_remove_irq_domain(struct lan78xx_net *dev)
+{
+ if (dev->domain_data.phyirq > 0) {
+ irq_dispose_mapping(dev->domain_data.phyirq);
+
+ if (dev->domain_data.irqdomain)
+ irq_domain_remove(dev->domain_data.irqdomain);
+ }
+ dev->domain_data.phyirq = 0;
+ dev->domain_data.irqdomain = NULL;
+}
+
+static int lan8835_fixup(struct phy_device *phydev)
+{
+ int buf;
+ int ret;
+ struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
+
+ /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */
+ buf = phy_read_mmd_indirect(phydev, 0x8010, 3);
+ buf &= ~0x1800;
+ buf |= 0x0800;
+ phy_write_mmd_indirect(phydev, 0x8010, 3, buf);
+
+ /* RGMII MAC TXC Delay Enable */
+ ret = lan78xx_write_reg(dev, MAC_RGMII_ID,
+ MAC_RGMII_ID_TXC_DELAY_EN_);
+
+ /* RGMII TX DLL Tune Adjust */
+ ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+
+ dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
+
+ return 1;
+}
+
+static int ksz9031rnx_fixup(struct phy_device *phydev)
+{
+ struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
+
+ /* Micrel9301RNX PHY configuration */
+ /* RGMII Control Signal Pad Skew */
+ phy_write_mmd_indirect(phydev, 4, 2, 0x0077);
+ /* RGMII RX Data Pad Skew */
+ phy_write_mmd_indirect(phydev, 5, 2, 0x7777);
+ /* RGMII RX Clock Pad Skew */
+ phy_write_mmd_indirect(phydev, 8, 2, 0x1FF);
+
+ dev->interface = PHY_INTERFACE_MODE_RGMII_RXID;
+
+ return 1;
+}
+
static int lan78xx_phy_init(struct lan78xx_net *dev)
{
int ret;
@@ -1846,28 +1997,61 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
return -EIO;
}
- /* Enable PHY interrupts.
- * We handle our own interrupt
- */
- ret = phy_read(phydev, LAN88XX_INT_STS);
- ret = phy_write(phydev, LAN88XX_INT_MASK,
- LAN88XX_INT_MASK_MDINTPIN_EN_ |
- LAN88XX_INT_MASK_LINK_CHANGE_);
+ if ((dev->chipid == ID_REV_CHIP_ID_7800_) ||
+ (dev->chipid == ID_REV_CHIP_ID_7850_)) {
+ phydev->is_internal = true;
+ dev->interface = PHY_INTERFACE_MODE_GMII;
- phydev->irq = PHY_IGNORE_INTERRUPT;
+ } else if (dev->chipid == ID_REV_CHIP_ID_7801_) {
+ if (!phydev->drv) {
+ netdev_err(dev->net, "no PHY driver found\n");
+ return -EIO;
+ }
+
+ dev->interface = PHY_INTERFACE_MODE_RGMII;
+
+ /* external PHY fixup for KSZ9031RNX */
+ ret = phy_register_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0,
+ ksz9031rnx_fixup);
+ if (ret < 0) {
+ netdev_err(dev->net, "fail to register fixup\n");
+ return ret;
+ }
+ /* external PHY fixup for LAN8835 */
+ ret = phy_register_fixup_for_uid(PHY_LAN8835, 0xfffffff0,
+ lan8835_fixup);
+ if (ret < 0) {
+ netdev_err(dev->net, "fail to register fixup\n");
+ return ret;
+ }
+ /* add more external PHY fixup here if needed */
+
+ phydev->is_internal = false;
+ } else {
+ netdev_err(dev->net, "unknown ID found\n");
+ ret = -EIO;
+ goto error;
+ }
+
+ /* if phyirq is not set, use polling mode in phylib */
+ if (dev->domain_data.phyirq > 0)
+ phydev->irq = dev->domain_data.phyirq;
+ else
+ phydev->irq = 0;
+ netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq);
+
+ /* set to AUTOMDIX */
+ phydev->mdix = ETH_TP_MDI_AUTO;
ret = phy_connect_direct(dev->net, phydev,
lan78xx_link_status_change,
- PHY_INTERFACE_MODE_GMII);
+ dev->interface);
if (ret) {
netdev_err(dev->net, "can't attach PHY to %s\n",
dev->mdiobus->id);
return -EIO;
}
- /* set to AUTOMDIX */
- lan78xx_set_mdix_status(dev->net, ETH_TP_MDI_AUTO);
-
/* MAC doesn't support 1000T Half */
phydev->supported &= ~SUPPORTED_1000baseT_Half;
@@ -1886,6 +2070,12 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
return 0;
+
+error:
+ phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
+ phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
+
+ return ret;
}
static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size)
@@ -1970,11 +2160,6 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
int old_rx_urb_size = dev->rx_urb_size;
int ret;
- if (new_mtu > MAX_SINGLE_PACKET_SIZE)
- return -EINVAL;
-
- if (new_mtu <= 0)
- return -EINVAL;
/* no second zero-length packet read wanted after mtu-sized packets */
if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
@@ -2247,14 +2432,12 @@ static int lan78xx_reset(struct lan78xx_net *dev)
} while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_));
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
+ /* LAN7801 only has RGMII mode */
+ if (dev->chipid == ID_REV_CHIP_ID_7801_)
+ buf &= ~MAC_CR_GMII_EN_;
buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_;
ret = lan78xx_write_reg(dev, MAC_CR, buf);
- /* enable PHY interrupts */
- ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
- buf |= INT_ENP_PHY_INT;
- ret = lan78xx_write_reg(dev, INT_EP_CTL, buf);
-
ret = lan78xx_read_reg(dev, MAC_TX, &buf);
buf |= MAC_TX_TXEN_;
ret = lan78xx_write_reg(dev, MAC_TX, buf);
@@ -2378,8 +2561,12 @@ static int lan78xx_stop(struct net_device *net)
if (timer_pending(&dev->stat_monitor))
del_timer_sync(&dev->stat_monitor);
+ phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
+ phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
+
phy_stop(net->phydev);
phy_disconnect(net->phydev);
+
net->phydev = NULL;
clear_bit(EVENT_DEV_OPEN, &dev->flags);
@@ -2663,6 +2850,14 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
dev->net->hw_features = dev->net->features;
+ ret = lan78xx_setup_irq_domain(dev);
+ if (ret < 0) {
+ netdev_warn(dev->net,
+ "lan78xx_setup_irq_domain() failed : %d", ret);
+ kfree(pdata);
+ return ret;
+ }
+
/* Init all registers */
ret = lan78xx_reset(dev);
@@ -2679,6 +2874,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_irq_domain(dev);
+
lan78xx_remove_mdio(dev);
if (pdata) {
@@ -3378,6 +3575,9 @@ static int lan78xx_probe(struct usb_interface *intf,
if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len))
netdev->mtu = dev->hard_mtu - netdev->hard_header_len;
+ /* MTU range: 68 - 9000 */
+ netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;
+
dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0;
dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1;
dev->ep_intr = (intf->cur_altsetting)->endpoint + 2;
@@ -3789,6 +3989,10 @@ static const struct usb_device_id products[] = {
/* LAN7850 USB Gigabit Ethernet Device */
USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7850_USB_PRODUCT_ID),
},
+ {
+ /* LAN7801 USB Gigabit Ethernet Device */
+ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID),
+ },
{},
};
MODULE_DEVICE_TABLE(usb, products);
diff --git a/drivers/net/usb/lan78xx.h b/drivers/net/usb/lan78xx.h
index 40927906109a..25aa54611774 100644
--- a/drivers/net/usb/lan78xx.h
+++ b/drivers/net/usb/lan78xx.h
@@ -108,6 +108,7 @@
#define ID_REV_CHIP_REV_MASK_ (0x0000FFFF)
#define ID_REV_CHIP_ID_7800_ (0x7800)
#define ID_REV_CHIP_ID_7850_ (0x7850)
+#define ID_REV_CHIP_ID_7801_ (0x7801)
#define FPGA_REV (0x04)
#define FPGA_REV_MINOR_MASK_ (0x0000FF00)
@@ -550,6 +551,7 @@
#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)
@@ -787,6 +789,18 @@
#define PHY_DEV_ID_MODEL_MASK_ (0x0FC00000)
#define PHY_DEV_ID_OUI_MASK_ (0x003FFFFF)
+#define RGMII_TX_BYP_DLL (0x708)
+#define RGMII_TX_BYP_DLL_TX_TUNE_ADJ_MASK_ (0x000FC00)
+#define RGMII_TX_BYP_DLL_TX_TUNE_SEL_MASK_ (0x00003F0)
+#define RGMII_TX_BYP_DLL_TX_DLL_RESET_ (0x0000002)
+#define RGMII_TX_BYP_DLL_TX_DLL_BYPASS_ (0x0000001)
+
+#define RGMII_RX_BYP_DLL (0x70C)
+#define RGMII_RX_BYP_DLL_RX_TUNE_ADJ_MASK_ (0x000FC00)
+#define RGMII_RX_BYP_DLL_RX_TUNE_SEL_MASK_ (0x00003F0)
+#define RGMII_RX_BYP_DLL_RX_DLL_RESET_ (0x0000002)
+#define RGMII_RX_BYP_DLL_RX_DLL_BYPASS_ (0x0000001)
+
#define OTP_BASE_ADDR (0x00001000)
#define OTP_ADDR_RANGE_ (0x1FF)
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 1434e5dd5f9c..399f7ee57aea 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1273,7 +1273,6 @@ static const struct net_device_ops pegasus_netdev_ops = {
.ndo_set_rx_mode = pegasus_set_multicast,
.ndo_get_stats = pegasus_netdev_stats,
.ndo_tx_timeout = pegasus_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index efb84f092492..7dc61228c55b 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -4116,14 +4116,12 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
switch (tp->version) {
case RTL_VER_01:
case RTL_VER_02:
- return eth_change_mtu(dev, new_mtu);
+ dev->mtu = new_mtu;
+ return 0;
default:
break;
}
- if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU)
- return -EINVAL;
-
ret = usb_autopm_get_interface(tp->intf);
if (ret < 0)
return ret;
@@ -4313,6 +4311,18 @@ static int rtl8152_probe(struct usb_interface *intf,
netdev->ethtool_ops = &ops;
netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
+ /* MTU range: 68 - 1500 or 9194 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ switch (tp->version) {
+ case RTL_VER_01:
+ case RTL_VER_02:
+ netdev->max_mtu = ETH_DATA_LEN;
+ break;
+ default:
+ netdev->max_mtu = RTL8153_MAX_MTU;
+ break;
+ }
+
tp->mii.dev = netdev;
tp->mii.mdio_read = read_mii_word;
tp->mii.mdio_write = write_mii_word;
@@ -4413,8 +4423,12 @@ static struct usb_device_id rtl8152_table[] = {
{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
- {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)},
{REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)},
{}
};
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 7c72bfac89d0..93a1bda1c1e5 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -847,7 +847,6 @@ static const struct net_device_ops rtl8150_netdev_ops = {
.ndo_set_rx_mode = rtl8150_set_multicast,
.ndo_set_mac_address = rtl8150_set_mac_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index a251588762ec..12071f1582df 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -165,7 +165,6 @@ struct lsi_umts {
/* Forward definitions */
static void sierra_sync_timer(unsigned long syncdata);
-static int sierra_net_change_mtu(struct net_device *net, int new_mtu);
/* Our own net device operations structure */
static const struct net_device_ops sierra_net_device_ops = {
@@ -173,7 +172,7 @@ static const struct net_device_ops sierra_net_device_ops = {
.ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_change_mtu = sierra_net_change_mtu,
+ .ndo_change_mtu = usbnet_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -622,15 +621,6 @@ static const struct ethtool_ops sierra_net_ethtool_ops = {
.nway_reset = usbnet_nway_reset,
};
-/* MTU can not be more than 1500 bytes, enforce it. */
-static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
-{
- if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU)
- return -EINVAL;
-
- return usbnet_change_mtu(net, new_mtu);
-}
-
static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
{
int result = 0;
@@ -720,6 +710,7 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN;
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+ dev->net->max_mtu = SIERRA_NET_MAX_SUPPORTED_MTU;
/* Set up the netdev */
dev->net->flags |= IFF_NOARP;
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 9af9799935db..0b17b40d7a4f 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -925,9 +925,6 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
struct usbnet *dev = netdev_priv(netdev);
int ret;
- if (new_mtu > MAX_SINGLE_PACKET_SIZE)
- return -EINVAL;
-
ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
if (ret < 0) {
netdev_warn(dev->net, "Failed to set mac rx frame length\n");
@@ -1448,6 +1445,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->flags |= IFF_MULTICAST;
dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+ dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE;
return 0;
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d5071e364d40..3de65ea6531a 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -384,8 +384,6 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
int old_hard_mtu = dev->hard_mtu;
int old_rx_urb_size = dev->rx_urb_size;
- if (new_mtu <= 0)
- return -EINVAL;
// no second zero-length packet read wanted after mtu-sized packets
if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
@@ -1669,6 +1667,8 @@ 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;
+ net->min_mtu = 0;
+ net->max_mtu = ETH_MAX_MTU;
net->netdev_ops = &usbnet_netdev_ops;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index fbc853e64531..0520952aa096 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -23,9 +23,6 @@
#define DRV_NAME "veth"
#define DRV_VERSION "1.0"
-#define MIN_MTU 68 /* Min L3 MTU */
-#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
-
struct pcpu_vstats {
u64 packets;
u64 bytes;
@@ -216,17 +213,9 @@ static int veth_close(struct net_device *dev)
return 0;
}
-static int is_valid_veth_mtu(int new_mtu)
+static int is_valid_veth_mtu(int mtu)
{
- return new_mtu >= MIN_MTU && new_mtu <= MAX_MTU;
-}
-
-static int veth_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (!is_valid_veth_mtu(new_mtu))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
+ return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU;
}
static int veth_dev_init(struct net_device *dev)
@@ -300,7 +289,6 @@ static const struct net_device_ops veth_netdev_ops = {
.ndo_open = veth_open,
.ndo_stop = veth_close,
.ndo_start_xmit = veth_xmit,
- .ndo_change_mtu = veth_change_mtu,
.ndo_get_stats64 = veth_get_stats64,
.ndo_set_rx_mode = veth_set_multicast_list,
.ndo_set_mac_address = eth_mac_addr,
@@ -337,6 +325,7 @@ static void veth_setup(struct net_device *dev)
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_STAG_RX);
dev->destructor = veth_dev_free;
+ dev->max_mtu = ETH_MAX_MTU;
dev->hw_features = VETH_FEATURES;
dev->hw_enc_features = VETH_FEATURES;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cbf1c613c67a..b425fa1013af 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1428,17 +1428,6 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
.set_settings = virtnet_set_settings,
};
-#define MIN_MTU 68
-#define MAX_MTU 65535
-
-static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < MIN_MTU || new_mtu > MAX_MTU)
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops virtnet_netdev = {
.ndo_open = virtnet_open,
.ndo_stop = virtnet_close,
@@ -1446,7 +1435,6 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode,
- .ndo_change_mtu = virtnet_change_mtu,
.ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
@@ -1762,6 +1750,9 @@ static bool virtnet_validate_features(struct virtio_device *vdev)
return true;
}
+#define MIN_MTU ETH_MIN_MTU
+#define MAX_MTU ETH_MAX_MTU
+
static int virtnet_probe(struct virtio_device *vdev)
{
int i, err;
@@ -1835,6 +1826,10 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->vlan_features = dev->features;
+ /* MTU range: 68 - 65535 */
+ dev->min_mtu = MIN_MTU;
+ dev->max_mtu = MAX_MTU;
+
/* Configuration may specify what MAC to use. Otherwise random. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
virtio_cread_bytes(vdev,
@@ -1889,15 +1884,22 @@ static int virtnet_probe(struct virtio_device *vdev)
mtu = virtio_cread16(vdev,
offsetof(struct virtio_net_config,
mtu));
- if (virtnet_change_mtu(dev, mtu))
+ if (mtu < dev->min_mtu) {
__virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
+ } else {
+ dev->mtu = mtu;
+ dev->max_mtu = mtu;
+ }
}
if (vi->any_header_sg)
dev->needed_headroom = vi->hdr_len;
- /* Use single tx/rx queue pair as default */
- vi->curr_queue_pairs = 1;
+ /* Enable multiqueue by default */
+ if (num_online_cpus() >= max_queue_pairs)
+ vi->curr_queue_pairs = max_queue_pairs;
+ else
+ vi->curr_queue_pairs = num_online_cpus();
vi->max_queue_pairs = max_queue_pairs;
/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
@@ -1928,6 +1930,8 @@ static int virtnet_probe(struct virtio_device *vdev)
goto free_unregister_netdev;
}
+ virtnet_set_affinity(vi);
+
/* Assume link up if device can't report link status,
otherwise get link status from config. */
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ef83ae3b0a44..e34b1297c96a 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2972,9 +2972,6 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
int err = 0;
- if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU)
- return -EINVAL;
-
netdev->mtu = new_mtu;
/*
@@ -3431,6 +3428,10 @@ vmxnet3_probe_device(struct pci_dev *pdev,
vmxnet3_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
+ /* MTU range: 60 - 9000 */
+ netdev->min_mtu = VMXNET3_MIN_MTU;
+ netdev->max_mtu = VMXNET3_MAX_MTU;
+
INIT_WORK(&adapter->work, vmxnet3_reset_work);
set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 820de6a9ddde..3bca24651dc0 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -272,11 +272,6 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
if (IS_ERR(rt))
goto err;
- if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) {
- ip_rt_put(rt);
- goto err;
- }
-
skb_dst_drop(skb);
/* if dst.dev is loopback or the VRF device again this is locally
@@ -611,6 +606,10 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
struct dst_entry *dst = NULL;
struct rtable *rth;
+ /* don't divert multicast */
+ if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+ return skb;
+
rcu_read_lock();
rth = rcu_dereference(vrf->rth);
@@ -999,6 +998,9 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
skb->skb_iif = vrf_dev->ifindex;
IPCB(skb)->flags |= IPSKB_L3SLAVE;
+ if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+ goto out;
+
/* loopback traffic; do not push through packet taps again.
* Reset pkt_type for upper layers to process skb
*/
@@ -1162,8 +1164,19 @@ static int vrf_add_fib_rules(const struct net_device *dev)
if (err < 0)
goto ipv6_err;
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+ err = vrf_fib_rule(dev, RTNL_FAMILY_IPMR, true);
+ if (err < 0)
+ goto ipmr_err;
+#endif
+
return 0;
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+ipmr_err:
+ vrf_fib_rule(dev, AF_INET6, false);
+#endif
+
ipv6_err:
vrf_fib_rule(dev, AF_INET, false);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 2ba01ca02c9c..bb70dd5723b5 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -52,7 +52,7 @@ static bool log_ecn_error = true;
module_param(log_ecn_error, bool, 0644);
MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
-static int vxlan_net_id;
+static unsigned int vxlan_net_id;
static struct rtnl_link_ops vxlan_link_ops;
static const u8 all_zeros_mac[ETH_ALEN + 2];
@@ -1754,21 +1754,16 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
}
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
- + VXLAN_HLEN + iphdr_len
- + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
+ + VXLAN_HLEN + iphdr_len;
/* Need space for new headers (invalidates iph ptr) */
err = skb_cow_head(skb, min_headroom);
if (unlikely(err))
- goto out_free;
-
- skb = vlan_hwaccel_push_inside(skb);
- if (WARN_ON(!skb))
- return -ENOMEM;
+ return err;
err = iptunnel_handle_offloads(skb, type);
if (err)
- goto out_free;
+ return err;
vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = VXLAN_HF_VNI;
@@ -1792,19 +1787,16 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
if (vxflags & VXLAN_F_GPE) {
err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol);
if (err < 0)
- goto out_free;
+ return err;
inner_protocol = skb->protocol;
}
skb_set_inner_protocol(skb, inner_protocol);
return 0;
-
-out_free:
- kfree_skb(skb);
- return err;
}
-static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
+static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device *dev,
+ struct vxlan_sock *sock4,
struct sk_buff *skb, int oif, u8 tos,
__be32 daddr, __be32 *saddr,
struct dst_cache *dst_cache,
@@ -1814,6 +1806,9 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
struct rtable *rt = NULL;
struct flowi4 fl4;
+ if (!sock4)
+ return ERR_PTR(-EIO);
+
if (tos && !info)
use_cache = false;
if (use_cache) {
@@ -1831,16 +1826,27 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
fl4.saddr = *saddr;
rt = ip_route_output_key(vxlan->net, &fl4);
- if (!IS_ERR(rt)) {
+ if (likely(!IS_ERR(rt))) {
+ if (rt->dst.dev == dev) {
+ netdev_dbg(dev, "circular route to %pI4\n", &daddr);
+ ip_rt_put(rt);
+ return ERR_PTR(-ELOOP);
+ }
+
*saddr = fl4.saddr;
if (use_cache)
dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr);
+ } else {
+ netdev_dbg(dev, "no route to %pI4\n", &daddr);
+ return ERR_PTR(-ENETUNREACH);
}
return rt;
}
#if IS_ENABLED(CONFIG_IPV6)
static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
+ struct net_device *dev,
+ struct vxlan_sock *sock6,
struct sk_buff *skb, int oif, u8 tos,
__be32 label,
const struct in6_addr *daddr,
@@ -1848,7 +1854,6 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
struct dst_cache *dst_cache,
const struct ip_tunnel_info *info)
{
- struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct dst_entry *ndst;
struct flowi6 fl6;
@@ -1876,8 +1881,16 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
sock6->sock->sk,
&ndst, &fl6);
- if (err < 0)
- return ERR_PTR(err);
+ if (unlikely(err < 0)) {
+ netdev_dbg(dev, "no route to %pI6\n", daddr);
+ return ERR_PTR(-ENETUNREACH);
+ }
+
+ if (unlikely(ndst->dev == dev)) {
+ netdev_dbg(dev, "circular route to %pI6\n", daddr);
+ dst_release(ndst);
+ return ERR_PTR(-ELOOP);
+ }
*saddr = fl6.saddr;
if (use_cache)
@@ -1931,23 +1944,55 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
}
}
+static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
+ struct vxlan_dev *vxlan, union vxlan_addr *daddr,
+ __be32 dst_port, __be32 vni, struct dst_entry *dst,
+ u32 rt_flags)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+ /* IPv6 rt-flags are checked against RTF_LOCAL, but the value of
+ * RTF_LOCAL is equal to RTCF_LOCAL. So to keep code simple
+ * we can use RTCF_LOCAL which works for ipv4 and ipv6 route entry.
+ */
+ BUILD_BUG_ON(RTCF_LOCAL != RTF_LOCAL);
+#endif
+ /* Bypass encapsulation if the destination is local */
+ if (rt_flags & RTCF_LOCAL &&
+ !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+ struct vxlan_dev *dst_vxlan;
+
+ dst_release(dst);
+ dst_vxlan = vxlan_find_vni(vxlan->net, vni,
+ daddr->sa.sa_family, dst_port,
+ vxlan->flags);
+ if (!dst_vxlan) {
+ dev->stats.tx_errors++;
+ kfree_skb(skb);
+
+ return -ENOENT;
+ }
+ vxlan_encap_bypass(skb, vxlan, dst_vxlan);
+ return 1;
+ }
+
+ return 0;
+}
+
static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct vxlan_rdst *rdst, bool did_rsc)
{
struct dst_cache *dst_cache;
struct ip_tunnel_info *info;
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct sock *sk;
- struct rtable *rt = NULL;
- const struct iphdr *old_iph;
+ const struct iphdr *old_iph = ip_hdr(skb);
union vxlan_addr *dst;
union vxlan_addr remote_ip, local_ip;
union vxlan_addr *src;
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
__be16 src_port = 0, dst_port;
+ struct dst_entry *ndst = NULL;
__be32 vni, label;
- __be16 df = 0;
__u8 tos, ttl;
int err;
u32 flags = vxlan->flags;
@@ -1957,19 +2002,40 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
info = skb_tunnel_info(skb);
if (rdst) {
+ dst = &rdst->remote_ip;
+ if (vxlan_addr_any(dst)) {
+ if (did_rsc) {
+ /* short-circuited back to local bridge */
+ vxlan_encap_bypass(skb, vxlan, vxlan);
+ return;
+ }
+ goto drop;
+ }
+
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
vni = rdst->remote_vni;
- dst = &rdst->remote_ip;
src = &vxlan->cfg.saddr;
dst_cache = &rdst->dst_cache;
+ md->gbp = skb->mark;
+ ttl = vxlan->cfg.ttl;
+ if (!ttl && vxlan_addr_multicast(dst))
+ ttl = 1;
+
+ tos = vxlan->cfg.tos;
+ if (tos == 1)
+ tos = ip_tunnel_get_dsfield(old_iph, skb);
+
+ if (dst->sa.sa_family == AF_INET)
+ udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
+ else
+ udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
+ label = vxlan->cfg.label;
} else {
if (!info) {
WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
dev->name);
goto drop;
}
- dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
- vni = tunnel_id_to_key32(info->key.tun_id);
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;
@@ -1979,182 +2045,111 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
local_ip.sin6.sin6_addr = info->key.u.ipv6.src;
}
dst = &remote_ip;
+ dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
+ vni = tunnel_id_to_key32(info->key.tun_id);
src = &local_ip;
dst_cache = &info->dst_cache;
- }
-
- if (vxlan_addr_any(dst)) {
- if (did_rsc) {
- /* short-circuited back to local bridge */
- vxlan_encap_bypass(skb, vxlan, vxlan);
- return;
- }
- goto drop;
- }
-
- old_iph = ip_hdr(skb);
-
- ttl = vxlan->cfg.ttl;
- if (!ttl && vxlan_addr_multicast(dst))
- ttl = 1;
-
- tos = vxlan->cfg.tos;
- if (tos == 1)
- tos = ip_tunnel_get_dsfield(old_iph, skb);
-
- label = vxlan->cfg.label;
- src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
- vxlan->cfg.port_max, true);
-
- if (info) {
+ if (info->options_len)
+ md = ip_tunnel_info_opts(info);
ttl = info->key.ttl;
tos = info->key.tos;
label = info->key.label;
udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
-
- if (info->options_len)
- md = ip_tunnel_info_opts(info);
- } else {
- md->gbp = skb->mark;
}
+ src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+ vxlan->cfg.port_max, true);
if (dst->sa.sa_family == AF_INET) {
struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
+ struct rtable *rt;
+ __be16 df = 0;
- if (!sock4)
- goto drop;
- sk = sock4->sock->sk;
-
- rt = vxlan_get_route(vxlan, skb,
+ rt = vxlan_get_route(vxlan, dev, sock4, skb,
rdst ? rdst->remote_ifindex : 0, tos,
dst->sin.sin_addr.s_addr,
&src->sin.sin_addr.s_addr,
dst_cache, info);
if (IS_ERR(rt)) {
- netdev_dbg(dev, "no route to %pI4\n",
- &dst->sin.sin_addr.s_addr);
- dev->stats.tx_carrier_errors++;
+ err = PTR_ERR(rt);
goto tx_error;
}
- if (rt->dst.dev == dev) {
- netdev_dbg(dev, "circular route to %pI4\n",
- &dst->sin.sin_addr.s_addr);
- dev->stats.collisions++;
- goto rt_tx_error;
- }
-
/* Bypass encapsulation if the destination is local */
- if (!info && rt->rt_flags & RTCF_LOCAL &&
- !(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
- struct vxlan_dev *dst_vxlan;
-
- ip_rt_put(rt);
- dst_vxlan = vxlan_find_vni(vxlan->net, vni,
- dst->sa.sa_family, dst_port,
- vxlan->flags);
- if (!dst_vxlan)
- goto tx_error;
- vxlan_encap_bypass(skb, vxlan, dst_vxlan);
- return;
- }
-
- if (!info)
- udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
- else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
+ if (!info) {
+ err = encap_bypass_if_local(skb, dev, vxlan, dst,
+ dst_port, vni, &rt->dst,
+ rt->rt_flags);
+ if (err)
+ return;
+ } else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) {
df = htons(IP_DF);
+ }
+ ndst = &rt->dst;
tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
- err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr),
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
vni, md, flags, udp_sum);
if (err < 0)
- goto xmit_tx_error;
+ goto tx_error;
- udp_tunnel_xmit_skb(rt, sk, skb, src->sin.sin_addr.s_addr,
+ udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, src->sin.sin_addr.s_addr,
dst->sin.sin_addr.s_addr, tos, ttl, df,
src_port, dst_port, xnet, !udp_sum);
#if IS_ENABLED(CONFIG_IPV6)
} else {
struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
- struct dst_entry *ndst;
- u32 rt6i_flags;
- if (!sock6)
- goto drop;
- sk = sock6->sock->sk;
-
- ndst = vxlan6_get_route(vxlan, skb,
+ ndst = vxlan6_get_route(vxlan, dev, sock6, skb,
rdst ? rdst->remote_ifindex : 0, tos,
label, &dst->sin6.sin6_addr,
&src->sin6.sin6_addr,
dst_cache, info);
if (IS_ERR(ndst)) {
- netdev_dbg(dev, "no route to %pI6\n",
- &dst->sin6.sin6_addr);
- dev->stats.tx_carrier_errors++;
+ err = PTR_ERR(ndst);
+ ndst = NULL;
goto tx_error;
}
- if (ndst->dev == dev) {
- netdev_dbg(dev, "circular route to %pI6\n",
- &dst->sin6.sin6_addr);
- dst_release(ndst);
- dev->stats.collisions++;
- goto tx_error;
- }
+ if (!info) {
+ u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
- /* Bypass encapsulation if the destination is local */
- rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
- if (!info && rt6i_flags & RTF_LOCAL &&
- !(rt6i_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
- struct vxlan_dev *dst_vxlan;
-
- dst_release(ndst);
- dst_vxlan = vxlan_find_vni(vxlan->net, vni,
- dst->sa.sa_family, dst_port,
- vxlan->flags);
- if (!dst_vxlan)
- goto tx_error;
- vxlan_encap_bypass(skb, vxlan, dst_vxlan);
- return;
+ err = encap_bypass_if_local(skb, dev, vxlan, dst,
+ dst_port, vni, ndst,
+ rt6i_flags);
+ if (err)
+ return;
}
- if (!info)
- udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
-
tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
ttl = ttl ? : ip6_dst_hoplimit(ndst);
skb_scrub_packet(skb, xnet);
err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
vni, md, flags, udp_sum);
- if (err < 0) {
- dst_release(ndst);
- dev->stats.tx_errors++;
- return;
- }
- udp_tunnel6_xmit_skb(ndst, sk, skb, dev,
+ if (err < 0)
+ goto tx_error;
+
+ udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
&src->sin6.sin6_addr,
&dst->sin6.sin6_addr, tos, ttl,
label, src_port, dst_port, !udp_sum);
#endif
}
-
return;
drop:
dev->stats.tx_dropped++;
- goto tx_free;
+ dev_kfree_skb(skb);
+ return;
-xmit_tx_error:
- /* skb is already freed. */
- skb = NULL;
-rt_tx_error:
- ip_rt_put(rt);
tx_error:
+ if (err == -ELOOP)
+ dev->stats.collisions++;
+ else if (err == -ENETUNREACH)
+ dev->stats.tx_carrier_errors++;
+ dst_release(ndst);
dev->stats.tx_errors++;
-tx_free:
- dev_kfree_skb(skb);
+ kfree_skb(skb);
}
/* Transmit local packets over Vxlan
@@ -2394,43 +2389,31 @@ static void vxlan_set_multicast_list(struct net_device *dev)
{
}
-static int __vxlan_change_mtu(struct net_device *dev,
- struct net_device *lowerdev,
- struct vxlan_rdst *dst, int new_mtu, bool strict)
+static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
{
- int max_mtu = IP_MAX_MTU;
-
- if (lowerdev)
- max_mtu = lowerdev->mtu;
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_rdst *dst = &vxlan->default_dst;
+ struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
+ dst->remote_ifindex);
+ bool use_ipv6 = false;
if (dst->remote_ip.sa.sa_family == AF_INET6)
- max_mtu -= VXLAN6_HEADROOM;
- else
- max_mtu -= VXLAN_HEADROOM;
-
- if (new_mtu < 68)
- return -EINVAL;
+ use_ipv6 = true;
- if (new_mtu > max_mtu) {
- if (strict)
+ /* This check is different than dev->max_mtu, because it looks at
+ * the lowerdev->mtu, rather than the static dev->max_mtu
+ */
+ if (lowerdev) {
+ int max_mtu = lowerdev->mtu -
+ (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+ if (new_mtu > max_mtu)
return -EINVAL;
-
- new_mtu = max_mtu;
}
dev->mtu = new_mtu;
return 0;
}
-static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_rdst *dst = &vxlan->default_dst;
- struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
- dst->remote_ifindex);
- return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
-}
-
static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -2445,9 +2428,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
struct rtable *rt;
- if (!sock4)
- return -EINVAL;
- rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
+ rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
info->key.u.ipv4.dst,
&info->key.u.ipv4.src, NULL, info);
if (IS_ERR(rt))
@@ -2455,9 +2436,10 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
ip_rt_put(rt);
} else {
#if IS_ENABLED(CONFIG_IPV6)
+ struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
struct dst_entry *ndst;
- ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos,
+ ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, info->key.tos,
info->key.label, &info->key.u.ipv6.dst,
&info->key.u.ipv6.src, NULL, info);
if (IS_ERR(ndst))
@@ -2545,10 +2527,8 @@ static void vxlan_setup(struct net_device *dev)
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->vlan_features = dev->features;
- dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
- dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
netif_keep_dst(dev);
dev->priv_flags |= IFF_NO_QUEUE;
@@ -2821,6 +2801,10 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
vxlan_ether_setup(dev);
}
+ /* MTU range: 68 - 65535 */
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = ETH_MAX_MTU;
+
vxlan->net = src_net;
dst->remote_vni = conf->vni;
@@ -2864,7 +2848,8 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
#endif
if (!conf->mtu)
- dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+ dev->mtu = lowerdev->mtu -
+ (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
needed_headroom = lowerdev->hard_header_len;
} else if (vxlan_addr_multicast(&dst->remote_ip)) {
@@ -2873,9 +2858,20 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
}
if (conf->mtu) {
- err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
- if (err)
- return err;
+ int max_mtu = ETH_MAX_MTU;
+
+ if (lowerdev)
+ max_mtu = lowerdev->mtu;
+
+ max_mtu -= (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+
+ if (conf->mtu < dev->min_mtu || conf->mtu > dev->max_mtu)
+ return -EINVAL;
+
+ dev->mtu = conf->mtu;
+
+ if (conf->mtu > max_mtu)
+ dev->mtu = max_mtu;
}
if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 09a50751763b..2371e078afbb 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -302,7 +302,6 @@ static void c101_destroy_card(card_t *card)
static const struct net_device_ops c101_ops = {
.ndo_open = c101_open,
.ndo_stop = c101_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = c101_ioctl,
};
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index b87fe0a01c69..087eb266601f 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -432,7 +432,6 @@ module_exit(cosa_exit);
static const struct net_device_ops cosa_ops = {
.ndo_open = cosa_net_open,
.ndo_stop = cosa_net_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = cosa_net_ioctl,
.ndo_tx_timeout = cosa_net_timeout,
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 629225980463..7351e5440ed7 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -887,7 +887,6 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
static const struct net_device_ops dscc4_ops = {
.ndo_open = dscc4_open,
.ndo_stop = dscc4_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = dscc4_ioctl,
.ndo_tx_timeout = dscc4_tx_timeout,
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 3c9cbf908ec7..03696d35ee9c 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -2394,7 +2394,6 @@ fst_init_card(struct fst_card_info *card)
static const struct net_device_ops fst_ops = {
.ndo_open = fst_open,
.ndo_stop = fst_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = fst_ioctl,
.ndo_tx_timeout = fst_tx_timeout,
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 65647533b401..e38ce4da3efb 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -992,7 +992,6 @@ static const struct dev_pm_ops uhdlc_pm_ops = {
static const struct net_device_ops uhdlc_ops = {
.ndo_open = uhdlc_open,
.ndo_stop = uhdlc_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = uhdlc_ioctl,
};
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 9bd4aa8083ce..7221a53b8b14 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -46,14 +46,6 @@ static const char* version = "HDLC support module revision 1.22";
static struct hdlc_proto *first_proto;
-int hdlc_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *p, struct net_device *orig_dev)
{
@@ -237,6 +229,8 @@ static void hdlc_setup_dev(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->priv_flags = IFF_WAN_HDLC;
dev->mtu = HDLC_MAX_MTU;
+ dev->min_mtu = 68;
+ dev->max_mtu = HDLC_MAX_MTU;
dev->type = ARPHRD_RAWHDLC;
dev->hard_header_len = 16;
dev->addr_len = 0;
@@ -353,7 +347,6 @@ MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("HDLC support module");
MODULE_LICENSE("GPL v2");
-EXPORT_SYMBOL(hdlc_change_mtu);
EXPORT_SYMBOL(hdlc_start_xmit);
EXPORT_SYMBOL(hdlc_open);
EXPORT_SYMBOL(hdlc_close);
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index b6e0cfb095d3..eb915281197e 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -1053,7 +1053,6 @@ static void pvc_setup(struct net_device *dev)
static const struct net_device_ops pvc_ops = {
.ndo_open = pvc_open,
.ndo_stop = pvc_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = pvc_xmit,
.ndo_do_ioctl = pvc_ioctl,
};
@@ -1096,6 +1095,8 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
}
dev->netdev_ops = &pvc_ops;
dev->mtu = HDLC_MAX_MTU;
+ dev->min_mtu = 68;
+ dev->max_mtu = HDLC_MAX_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
dev->ml_priv = pvc;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index 3d741663fd67..dd6bb3364ad2 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -180,7 +180,6 @@ static int hostess_attach(struct net_device *dev, unsigned short encoding,
static const struct net_device_ops hostess_ops = {
.ndo_open = hostess_open,
.ndo_stop = hostess_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hostess_ioctl,
};
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index e7bbdb7af53a..6a505c26a3e7 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1321,7 +1321,6 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static const struct net_device_ops hss_hdlc_ops = {
.ndo_open = hss_hdlc_open,
.ndo_stop = hss_hdlc_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hss_hdlc_ioctl,
};
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 299140c04556..001b7796740d 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -808,7 +808,6 @@ static int lmc_attach(struct net_device *dev, unsigned short encoding,
static const struct net_device_ops lmc_ops = {
.ndo_open = lmc_open,
.ndo_stop = lmc_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = lmc_ioctl,
.ndo_tx_timeout = lmc_driver_timeout,
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 315bf09d6a20..c8f4517db3a0 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -330,7 +330,6 @@ static void n2_destroy_card(card_t *card)
static const struct net_device_ops n2_ops = {
.ndo_open = n2_open,
.ndo_stop = n2_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = n2_ioctl,
};
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index db363856e0b5..e1dd1ec18d64 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -291,7 +291,6 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
static const struct net_device_ops pc300_ops = {
.ndo_open = pc300_open,
.ndo_stop = pc300_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = pc300_ioctl,
};
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index e8455621390e..4e437c599e9a 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -270,7 +270,6 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
static const struct net_device_ops pci200_ops = {
.ndo_open = pci200_open,
.ndo_stop = pci200_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = pci200_ioctl,
};
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 3a421ca8a4d0..3f83be98d469 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -211,7 +211,6 @@ static const struct net_device_ops sbni_netdev_ops = {
.ndo_start_xmit = sbni_start_xmit,
.ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = sbni_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index 27860b4f5908..fbb5aa2c4d8f 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -174,7 +174,6 @@ static int sealevel_attach(struct net_device *dev, unsigned short encoding,
static const struct net_device_ops sealevel_ops = {
.ndo_open = sealevel_open,
.ndo_stop = sealevel_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = sealevel_ioctl,
};
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index a20d688d2595..0c7317520ed3 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -551,7 +551,6 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
static const struct net_device_ops wanxl_ops = {
.ndo_open = wanxl_open,
.ndo_stop = wanxl_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = wanxl_ioctl,
.ndo_get_stats = wanxl_get_stats,
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 1bc5e93d2a34..878b05d06fc7 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -124,9 +124,6 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
unsigned char *xbuff, *rbuff;
int len;
- if (newmtu > 65534)
- return -EINVAL;
-
len = 2 * newmtu;
xbuff = kmalloc(len + 4, GFP_ATOMIC);
rbuff = kmalloc(len + 4, GFP_ATOMIC);
@@ -751,6 +748,8 @@ static void x25_asy_setup(struct net_device *dev)
*/
dev->mtu = SL_MTU;
+ dev->min_mtu = 0;
+ dev->max_mtu = 65534;
dev->netdev_ops = &x25_asy_netdev_ops;
dev->watchdog_timeo = HZ*20;
dev->hard_header_len = 0;
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index bb74f4b9a02f..7f64e74d746b 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -395,25 +395,6 @@ drop:
static
-int i2400m_change_mtu(struct net_device *net_dev, int new_mtu)
-{
- int result;
- struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
- struct device *dev = i2400m_dev(i2400m);
-
- if (new_mtu >= I2400M_MAX_MTU) {
- dev_err(dev, "Cannot change MTU to %d (max is %d)\n",
- new_mtu, I2400M_MAX_MTU);
- result = -EINVAL;
- } else {
- net_dev->mtu = new_mtu;
- result = 0;
- }
- return result;
-}
-
-
-static
void i2400m_tx_timeout(struct net_device *net_dev)
{
/*
@@ -590,7 +571,6 @@ static const struct net_device_ops i2400m_netdev_ops = {
.ndo_stop = i2400m_stop,
.ndo_start_xmit = i2400m_hard_start_xmit,
.ndo_tx_timeout = i2400m_tx_timeout,
- .ndo_change_mtu = i2400m_change_mtu,
};
static void i2400m_get_drvinfo(struct net_device *net_dev,
@@ -621,6 +601,8 @@ void i2400m_netdev_setup(struct net_device *net_dev)
d_fnstart(3, NULL, "(net_dev %p)\n", net_dev);
ether_setup(net_dev);
net_dev->mtu = I2400M_MAX_MTU;
+ net_dev->min_mtu = 0;
+ net_dev->max_mtu = I2400M_MAX_MTU;
net_dev->tx_queue_len = I2400M_TX_QLEN;
net_dev->features =
NETIF_F_VLAN_CHALLENGED
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 8c8edaf1bba6..8f5a3f4a43f2 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -17,6 +17,19 @@ menuconfig WLAN
if WLAN
+config WIRELESS_WDS
+ bool "mac80211-based legacy WDS support" if EXPERT
+ help
+ This option enables the deprecated WDS support, the newer
+ mac80211-based 4-addr AP/client support supersedes it with
+ a much better feature set (HT, VHT, ...)
+
+ We plan to remove this option and code, so if you find
+ that you have to enable it, please let us know on the
+ linux-wireless@vger.kernel.org mailing list, so we can
+ help you migrate to 4-addr AP/client (or, if it's really
+ necessary, give up on our plan of removing it).
+
source "drivers/net/wireless/admtek/Kconfig"
source "drivers/net/wireless/ath/Kconfig"
source "drivers/net/wireless/atmel/Kconfig"
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index da7a7c8dafb2..f3f2784f6ebd 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -327,4 +327,10 @@ static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
}
#endif
+extern const char *ath_bus_type_strings[];
+static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
+{
+ return ath_bus_type_strings[bustype];
+}
+
#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 21ae8d663e67..749e381edd38 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -198,6 +198,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.name = "qca9984/qca9994 hw1.0",
.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
.otp_exe_param = 0x00000700,
.continuous_frag_desc = true,
.cck_rate_map_rev2 = true,
@@ -223,6 +224,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.name = "qca9888 hw2.0",
.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
.otp_exe_param = 0x00000700,
.continuous_frag_desc = true,
.channel_counters_freq_hz = 150000,
@@ -324,6 +326,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
+ [ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
@@ -1534,7 +1537,7 @@ static void ath10k_core_restart(struct work_struct *work)
switch (ar->state) {
case ATH10K_STATE_ON:
ar->state = ATH10K_STATE_RESTARTING;
- ath10k_hif_stop(ar);
+ ath10k_halt(ar);
ath10k_scan_finish(ar);
ieee80211_restart_hw(ar->hw);
break;
@@ -1560,6 +1563,15 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
+static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+{
+ struct ath10k *ar = container_of(work, struct ath10k,
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+ ar->hw_params.hw_ops->set_coverage_class(ar, -1);
+}
+
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
@@ -1846,7 +1858,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_wmi_detach;
}
- status = ath10k_htt_tx_alloc(&ar->htt);
+ status = ath10k_htt_tx_start(&ar->htt);
if (status) {
ath10k_err(ar, "failed to alloc htt tx: %d\n", status);
goto err_wmi_detach;
@@ -2041,7 +2053,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_hif_stop(ar);
- ath10k_htt_tx_free(&ar->htt);
+ ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
}
@@ -2342,6 +2354,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->register_work, ath10k_core_register_work);
INIT_WORK(&ar->restart_work, ath10k_core_restart);
+ INIT_WORK(&ar->set_coverage_class_work,
+ ath10k_core_set_coverage_class_work);
init_dummy_netdev(&ar->napi_dev);
@@ -2372,6 +2386,7 @@ void ath10k_core_destroy(struct ath10k *ar)
destroy_workqueue(ar->workqueue_aux);
ath10k_debug_destroy(ar);
+ ath10k_htt_tx_destroy(&ar->htt);
ath10k_wmi_free_host_mem(ar);
ath10k_mac_destroy(ar);
}
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 521f1c55c19e..09ff8b8a6441 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -337,6 +337,7 @@ struct ath10k_sta {
u32 nss;
u32 smps;
u16 peer_id;
+ struct rate_info txrate;
struct work_struct update_wk;
@@ -557,13 +558,18 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
- /* Older firmware with HTT delivers incorrect tx status for null func
- * frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
- * Also this workaround results in reporting of incorrect null func
- * status for 10.4. This flag is used to skip the workaround.
+ /* Unused flag and proven to be not working, enable this if you want
+ * to experiment sending NULL func data frames in HTT TX
*/
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,
+ /* Firmware allow other BSS mesh broadcast/multicast frames without
+ * creating monitor interface. Appropriate rxfilters are programmed for
+ * mesh vdev by firmware itself. This feature flags will be used for
+ * not creating monitor vdev while configuring mesh node.
+ */
+ ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16,
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
@@ -695,6 +701,21 @@ struct ath10k_fw_components {
struct ath10k_fw_file fw_file;
};
+struct ath10k_per_peer_tx_stats {
+ u32 succ_bytes;
+ u32 retry_bytes;
+ u32 failed_bytes;
+ u8 ratecode;
+ u8 flags;
+ u16 peer_id;
+ u16 succ_pkts;
+ u16 retry_pkts;
+ u16 failed_pkts;
+ u16 duration;
+ u32 reserved1;
+ u32 reserved2;
+};
+
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -714,6 +735,7 @@ struct ath10k {
u32 phy_capability;
u32 hw_min_tx_power;
u32 hw_max_tx_power;
+ u32 hw_eeprom_rd;
u32 ht_cap_info;
u32 vht_cap_info;
u32 num_rf_chains;
@@ -907,11 +929,25 @@ struct ath10k {
struct ath10k_thermal thermal;
struct ath10k_wow wow;
+ struct ath10k_per_peer_tx_stats peer_tx_stats;
/* NAPI */
struct net_device napi_dev;
struct napi_struct napi;
+ struct work_struct set_coverage_class_work;
+ /* protected by conf_mutex */
+ struct {
+ /* writing also protected by data_lock */
+ s16 coverage_class;
+
+ u32 reg_phyclk;
+ u32 reg_slottime_conf;
+ u32 reg_slottime_orig;
+ u32 reg_ack_cts_timeout_conf;
+ u32 reg_ack_cts_timeout_orig;
+ } fw_coverage;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index c458fa96a6d4..335512b11ca2 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -94,7 +94,19 @@ int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data);
+
+static inline u64 ath10k_debug_get_fw_dbglog_mask(struct ath10k *ar)
+{
+ return ar->debug.fw_dbglog_mask;
+}
+
+static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar)
+{
+ return ar->debug.fw_dbglog_level;
+}
+
#else
+
static inline int ath10k_debug_start(struct ath10k *ar)
{
return 0;
@@ -144,6 +156,16 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
return NULL;
}
+static inline u64 ath10k_debug_get_fw_dbglog_mask(struct ath10k *ar)
+{
+ return 0;
+}
+
+static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar)
+{
+ return 0;
+}
+
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index 9955fea0802a..fce6f8137d33 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
+
+ if (!arsta->txrate.legacy && !arsta->txrate.nss)
+ return;
+
+ if (arsta->txrate.legacy) {
+ sinfo->txrate.legacy = arsta->txrate.legacy;
+ } else {
+ sinfo->txrate.mcs = arsta->txrate.mcs;
+ sinfo->txrate.nss = arsta->txrate.nss;
+ sinfo->txrate.bw = arsta->txrate.bw;
+ }
+ sinfo->txrate.flags = arsta->txrate.flags;
+ sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE;
}
static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 130cd9502021..cd160b16db1e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
[HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] =
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
+ [HTT_10_4_T2H_MSG_TYPE_PEER_STATS] =
+ HTT_T2H_MSG_TYPE_PEER_STATS,
};
int ath10k_htt_connect(struct ath10k_htt *htt)
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 0d2ed09f202b..44b25cf00553 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type {
HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18,
/* 0x19 to 0x2f are reserved */
HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30,
+ HTT_10_4_T2H_MSG_TYPE_PEER_STATS = 0x31,
/* keep this last */
HTT_10_4_T2H_NUM_MSGS
};
@@ -453,6 +454,7 @@ enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
+ HTT_T2H_MSG_TYPE_PEER_STATS,
/* keep this last */
HTT_T2H_NUM_MSGS
};
@@ -1470,6 +1472,28 @@ struct htt_channel_change {
__le32 phymode;
} __packed;
+struct htt_per_peer_tx_stats_ind {
+ __le32 succ_bytes;
+ __le32 retry_bytes;
+ __le32 failed_bytes;
+ u8 ratecode;
+ u8 flags;
+ __le16 peer_id;
+ __le16 succ_pkts;
+ __le16 retry_pkts;
+ __le16 failed_pkts;
+ __le16 tx_duration;
+ __le32 reserved1;
+ __le32 reserved2;
+} __packed;
+
+struct htt_peer_tx_stats {
+ u8 num_ppdu;
+ u8 ppdu_len;
+ u8 version;
+ u8 payload[0];
+} __packed;
+
union htt_rx_pn_t {
/* WEP: 24-bit PN */
u32 pn24;
@@ -1521,6 +1545,7 @@ struct htt_resp {
struct htt_tx_fetch_confirm tx_fetch_confirm;
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
+ struct htt_peer_tx_stats peer_tx_stats;
};
} __packed;
@@ -1692,6 +1717,8 @@ struct ath10k_htt {
enum htt_tx_mode_switch_mode mode;
enum htt_q_depth_type type;
} tx_q_state;
+
+ bool tx_mem_allocated;
};
#define RX_HTT_HDR_STATUS_LEN 64
@@ -1754,7 +1781,9 @@ int ath10k_htt_connect(struct ath10k_htt *htt);
int ath10k_htt_init(struct ath10k *ar);
int ath10k_htt_setup(struct ath10k_htt *htt);
-int ath10k_htt_tx_alloc(struct ath10k_htt *htt);
+int ath10k_htt_tx_start(struct ath10k_htt *htt);
+void ath10k_htt_tx_stop(struct ath10k_htt *htt);
+void ath10k_htt_tx_destroy(struct ath10k_htt *htt);
void ath10k_htt_tx_free(struct ath10k_htt *htt);
int ath10k_htt_rx_alloc(struct ath10k_htt *htt);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 0b4c1562420f..86d082cf4eef 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1463,8 +1463,7 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
}
static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- bool chained)
+ struct sk_buff_head *amsdu)
{
struct sk_buff *first;
struct htt_rx_desc *rxd;
@@ -1475,9 +1474,6 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT);
- if (!chained)
- return;
-
/* FIXME: Current unchaining logic can only handle simple case of raw
* msdu chaining. If decapping is other than raw the chaining may be
* more complex and this isn't handled by the current code. Don't even
@@ -1555,7 +1551,11 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
num_msdus = skb_queue_len(&amsdu);
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
- ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
+
+ /* only for ret = 1 indicates chained msdus */
+ if (ret > 0)
+ ath10k_htt_rx_h_unchain(ar, &amsdu);
+
ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
@@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
+static inline bool is_valid_legacy_rate(u8 rate)
+{
+ static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12,
+ 18, 24, 36, 48, 54};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(legacy_rates); i++) {
+ if (rate == legacy_rates[i])
+ return true;
+ }
+
+ return false;
+}
+
+static void
+ath10k_update_per_peer_tx_stats(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ struct ath10k_per_peer_tx_stats *peer_stats)
+{
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ u8 rate = 0, sgi;
+ struct rate_info txrate;
+
+ lockdep_assert_held(&ar->data_lock);
+
+ txrate.flags = ATH10K_HW_PREAMBLE(peer_stats->ratecode);
+ txrate.bw = ATH10K_HW_BW(peer_stats->flags);
+ txrate.nss = ATH10K_HW_NSS(peer_stats->ratecode);
+ txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode);
+ sgi = ATH10K_HW_GI(peer_stats->flags);
+
+ if (((txrate.flags == WMI_RATE_PREAMBLE_HT) ||
+ (txrate.flags == WMI_RATE_PREAMBLE_VHT)) && txrate.mcs > 9) {
+ ath10k_warn(ar, "Invalid mcs %hhd peer stats", txrate.mcs);
+ return;
+ }
+
+ if (txrate.flags == WMI_RATE_PREAMBLE_CCK ||
+ txrate.flags == WMI_RATE_PREAMBLE_OFDM) {
+ rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode);
+
+ if (!is_valid_legacy_rate(rate)) {
+ ath10k_warn(ar, "Invalid legacy rate %hhd peer stats",
+ rate);
+ return;
+ }
+
+ /* This is hacky, FW sends CCK rate 5.5Mbps as 6 */
+ rate *= 10;
+ if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK)
+ rate = rate - 5;
+ arsta->txrate.legacy = rate * 10;
+ } else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
+ arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
+ arsta->txrate.mcs = txrate.mcs;
+ } else {
+ arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+ arsta->txrate.mcs = txrate.mcs;
+ }
+
+ if (sgi)
+ arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+ arsta->txrate.nss = txrate.nss;
+ arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
+}
+
+static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ struct htt_resp *resp = (struct htt_resp *)skb->data;
+ struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats;
+ struct htt_per_peer_tx_stats_ind *tx_stats;
+ struct ieee80211_sta *sta;
+ struct ath10k_peer *peer;
+ int peer_id, i;
+ u8 ppdu_len, num_ppdu;
+
+ num_ppdu = resp->peer_tx_stats.num_ppdu;
+ ppdu_len = resp->peer_tx_stats.ppdu_len * sizeof(__le32);
+
+ if (skb->len < sizeof(struct htt_resp_hdr) + num_ppdu * ppdu_len) {
+ ath10k_warn(ar, "Invalid peer stats buf length %d\n", skb->len);
+ return;
+ }
+
+ tx_stats = (struct htt_per_peer_tx_stats_ind *)
+ (resp->peer_tx_stats.payload);
+ peer_id = __le16_to_cpu(tx_stats->peer_id);
+
+ rcu_read_lock();
+ spin_lock_bh(&ar->data_lock);
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer) {
+ ath10k_warn(ar, "Invalid peer id %d peer stats buffer\n",
+ peer_id);
+ goto out;
+ }
+
+ sta = peer->sta;
+ for (i = 0; i < num_ppdu; i++) {
+ tx_stats = (struct htt_per_peer_tx_stats_ind *)
+ (resp->peer_tx_stats.payload + i * ppdu_len);
+
+ p_tx_stats->succ_bytes = __le32_to_cpu(tx_stats->succ_bytes);
+ p_tx_stats->retry_bytes = __le32_to_cpu(tx_stats->retry_bytes);
+ p_tx_stats->failed_bytes =
+ __le32_to_cpu(tx_stats->failed_bytes);
+ p_tx_stats->ratecode = tx_stats->ratecode;
+ p_tx_stats->flags = tx_stats->flags;
+ p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts);
+ p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts);
+ p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts);
+
+ ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats);
+ }
+
+out:
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+}
+
bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_htt *htt = &ar->htt;
@@ -2354,6 +2476,9 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND:
ath10k_htt_rx_tx_mode_switch_ind(ar, skb);
break;
+ case HTT_T2H_MSG_TYPE_PEER_STATS:
+ ath10k_htt_fetch_peer_stats(ar, skb);
+ break;
case HTT_T2H_MSG_TYPE_EN_STATS:
default:
ath10k_warn(ar, "htt event (%d) not handled\n",
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index ae5b33fe5ba8..27e49db4287a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -229,6 +229,32 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
idr_remove(&htt->pending_tx, msdu_id);
}
+static void ath10k_htt_tx_free_cont_txbuf(struct ath10k_htt *htt)
+{
+ struct ath10k *ar = htt->ar;
+ size_t size;
+
+ if (!htt->txbuf.vaddr)
+ return;
+
+ size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
+ dma_free_coherent(ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr);
+}
+
+static int ath10k_htt_tx_alloc_cont_txbuf(struct ath10k_htt *htt)
+{
+ struct ath10k *ar = htt->ar;
+ size_t size;
+
+ size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
+ htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size, &htt->txbuf.paddr,
+ GFP_KERNEL);
+ if (!htt->txbuf.vaddr)
+ return -ENOMEM;
+
+ return 0;
+}
+
static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt)
{
size_t size;
@@ -256,10 +282,8 @@ static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt)
htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
&htt->frag_desc.paddr,
GFP_KERNEL);
- if (!htt->frag_desc.vaddr) {
- ath10k_err(ar, "failed to alloc fragment desc memory\n");
+ if (!htt->frag_desc.vaddr)
return -ENOMEM;
- }
return 0;
}
@@ -310,25 +334,31 @@ static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt)
return 0;
}
-int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
+static void ath10k_htt_tx_free_txdone_fifo(struct ath10k_htt *htt)
{
- struct ath10k *ar = htt->ar;
- int ret, size;
+ WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
+ kfifo_free(&htt->txdone_fifo);
+}
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
- htt->max_num_pending_tx);
+static int ath10k_htt_tx_alloc_txdone_fifo(struct ath10k_htt *htt)
+{
+ int ret;
+ size_t size;
- spin_lock_init(&htt->tx_lock);
- idr_init(&htt->pending_tx);
+ size = roundup_pow_of_two(htt->max_num_pending_tx);
+ ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL);
+ return ret;
+}
- size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
- htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
- &htt->txbuf.paddr,
- GFP_KERNEL);
- if (!htt->txbuf.vaddr) {
- ath10k_err(ar, "failed to alloc tx buffer\n");
- ret = -ENOMEM;
- goto free_idr_pending_tx;
+static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
+{
+ struct ath10k *ar = htt->ar;
+ int ret;
+
+ ret = ath10k_htt_tx_alloc_cont_txbuf(htt);
+ if (ret) {
+ ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret);
+ return ret;
}
ret = ath10k_htt_tx_alloc_cont_frag_desc(htt);
@@ -343,8 +373,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
goto free_frag_desc;
}
- size = roundup_pow_of_two(htt->max_num_pending_tx);
- ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL);
+ ret = ath10k_htt_tx_alloc_txdone_fifo(htt);
if (ret) {
ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret);
goto free_txq;
@@ -359,10 +388,32 @@ free_frag_desc:
ath10k_htt_tx_free_cont_frag_desc(htt);
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);
+ ath10k_htt_tx_free_cont_txbuf(htt);
+
+ return ret;
+}
+
+int ath10k_htt_tx_start(struct ath10k_htt *htt)
+{
+ struct ath10k *ar = htt->ar;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
+ htt->max_num_pending_tx);
+
+ spin_lock_init(&htt->tx_lock);
+ idr_init(&htt->pending_tx);
+
+ if (htt->tx_mem_allocated)
+ return 0;
+
+ ret = ath10k_htt_tx_alloc_buf(htt);
+ if (ret)
+ goto free_idr_pending_tx;
+
+ htt->tx_mem_allocated = true;
+
+ return 0;
free_idr_pending_tx:
idr_destroy(&htt->pending_tx);
@@ -386,24 +437,28 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
return 0;
}
-void ath10k_htt_tx_free(struct ath10k_htt *htt)
+void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
{
- int size;
+ if (!htt->tx_mem_allocated)
+ return;
+
+ ath10k_htt_tx_free_cont_txbuf(htt);
+ ath10k_htt_tx_free_txq(htt);
+ ath10k_htt_tx_free_cont_frag_desc(htt);
+ ath10k_htt_tx_free_txdone_fifo(htt);
+ htt->tx_mem_allocated = false;
+}
+void ath10k_htt_tx_stop(struct ath10k_htt *htt)
+{
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
idr_destroy(&htt->pending_tx);
+}
- 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);
- }
-
- ath10k_htt_tx_free_txq(htt);
- ath10k_htt_tx_free_cont_frag_desc(htt);
- WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
- kfifo_free(&htt->txdone_fifo);
+void ath10k_htt_tx_free(struct ath10k_htt *htt)
+{
+ ath10k_htt_tx_stop(htt);
+ ath10k_htt_tx_destroy(htt);
}
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 675e75d66db2..33fb26833cd0 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -17,11 +17,14 @@
#include <linux/types.h>
#include "core.h"
#include "hw.h"
+#include "hif.h"
+#include "wmi-ops.h"
const struct ath10k_hw_regs qca988x_regs = {
.rtc_soc_base_address = 0x00004000,
.rtc_wmac_base_address = 0x00005000,
.soc_core_base_address = 0x00009000,
+ .wlan_mac_base_address = 0x00020000,
.ce_wrapper_base_address = 0x00057000,
.ce0_base_address = 0x00057400,
.ce1_base_address = 0x00057800,
@@ -48,6 +51,7 @@ const struct ath10k_hw_regs qca6174_regs = {
.rtc_soc_base_address = 0x00000800,
.rtc_wmac_base_address = 0x00001000,
.soc_core_base_address = 0x0003a000,
+ .wlan_mac_base_address = 0x00020000,
.ce_wrapper_base_address = 0x00034000,
.ce0_base_address = 0x00034400,
.ce1_base_address = 0x00034800,
@@ -74,6 +78,7 @@ const struct ath10k_hw_regs qca99x0_regs = {
.rtc_soc_base_address = 0x00080000,
.rtc_wmac_base_address = 0x00000000,
.soc_core_base_address = 0x00082000,
+ .wlan_mac_base_address = 0x00030000,
.ce_wrapper_base_address = 0x0004d000,
.ce0_base_address = 0x0004a000,
.ce1_base_address = 0x0004a400,
@@ -109,6 +114,7 @@ const struct ath10k_hw_regs qca99x0_regs = {
const struct ath10k_hw_regs qca4019_regs = {
.rtc_soc_base_address = 0x00080000,
.soc_core_base_address = 0x00082000,
+ .wlan_mac_base_address = 0x00030000,
.ce_wrapper_base_address = 0x0004d000,
.ce0_base_address = 0x0004a000,
.ce1_base_address = 0x0004a400,
@@ -220,7 +226,143 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
survey->time_busy = CCNT_TO_MSEC(ar, rcc);
}
+/* The firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
+ s16 value)
+{
+ u32 slottime_reg;
+ u32 slottime;
+ u32 timeout_reg;
+ u32 ack_timeout;
+ u32 cts_timeout;
+ u32 phyclk_reg;
+ u32 phyclk;
+ u64 fw_dbglog_mask;
+ u32 fw_dbglog_level;
+
+ mutex_lock(&ar->conf_mutex);
+
+ /* Only modify registers if the core is started. */
+ if ((ar->state != ATH10K_STATE_ON) &&
+ (ar->state != ATH10K_STATE_RESTARTED))
+ goto unlock;
+
+ /* Retrieve the current values of the two registers that need to be
+ * adjusted.
+ */
+ slottime_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
+ WAVE1_PCU_GBL_IFS_SLOT);
+ timeout_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
+ WAVE1_PCU_ACK_CTS_TIMEOUT);
+ phyclk_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
+ WAVE1_PHYCLK);
+ phyclk = MS(phyclk_reg, WAVE1_PHYCLK_USEC) + 1;
+
+ if (value < 0)
+ value = ar->fw_coverage.coverage_class;
+
+ /* Break out if the coverage class and registers have the expected
+ * value.
+ */
+ if (value == ar->fw_coverage.coverage_class &&
+ slottime_reg == ar->fw_coverage.reg_slottime_conf &&
+ timeout_reg == ar->fw_coverage.reg_ack_cts_timeout_conf &&
+ phyclk_reg == ar->fw_coverage.reg_phyclk)
+ goto unlock;
+
+ /* Store new initial register values from the firmware. */
+ if (slottime_reg != ar->fw_coverage.reg_slottime_conf)
+ ar->fw_coverage.reg_slottime_orig = slottime_reg;
+ if (timeout_reg != ar->fw_coverage.reg_ack_cts_timeout_conf)
+ ar->fw_coverage.reg_ack_cts_timeout_orig = timeout_reg;
+ ar->fw_coverage.reg_phyclk = phyclk_reg;
+
+ /* Calculat new value based on the (original) firmware calculation. */
+ slottime_reg = ar->fw_coverage.reg_slottime_orig;
+ timeout_reg = ar->fw_coverage.reg_ack_cts_timeout_orig;
+
+ /* Do some sanity checks on the slottime register. */
+ if (slottime_reg % phyclk) {
+ ath10k_warn(ar,
+ "failed to set coverage class: expected integer microsecond value in register\n");
+
+ goto store_regs;
+ }
+
+ slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT);
+ slottime = slottime / phyclk;
+ if (slottime != 9 && slottime != 20) {
+ ath10k_warn(ar,
+ "failed to set coverage class: expected slot time of 9 or 20us in HW register. It is %uus.\n",
+ slottime);
+
+ goto store_regs;
+ }
+
+ /* Recalculate the register values by adding the additional propagation
+ * delay (3us per coverage class).
+ */
+
+ slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT);
+ slottime += value * 3 * phyclk;
+ slottime = min_t(u32, slottime, WAVE1_PCU_GBL_IFS_SLOT_MAX);
+ slottime = SM(slottime, WAVE1_PCU_GBL_IFS_SLOT);
+ slottime_reg = (slottime_reg & ~WAVE1_PCU_GBL_IFS_SLOT_MASK) | slottime;
+
+ /* Update ack timeout (lower halfword). */
+ ack_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK);
+ ack_timeout += 3 * value * phyclk;
+ ack_timeout = min_t(u32, ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX);
+ ack_timeout = SM(ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK);
+
+ /* Update cts timeout (upper halfword). */
+ cts_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS);
+ cts_timeout += 3 * value * phyclk;
+ cts_timeout = min_t(u32, cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX);
+ cts_timeout = SM(cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS);
+
+ timeout_reg = ack_timeout | cts_timeout;
+
+ ath10k_hif_write32(ar,
+ WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_GBL_IFS_SLOT,
+ slottime_reg);
+ ath10k_hif_write32(ar,
+ WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_ACK_CTS_TIMEOUT,
+ timeout_reg);
+
+ /* Ensure we have a debug level of WARN set for the case that the
+ * coverage class is larger than 0. This is important as we need to
+ * set the registers again if the firmware does an internal reset and
+ * this way we will be notified of the event.
+ */
+ fw_dbglog_mask = ath10k_debug_get_fw_dbglog_mask(ar);
+ fw_dbglog_level = ath10k_debug_get_fw_dbglog_level(ar);
+
+ if (value > 0) {
+ if (fw_dbglog_level > ATH10K_DBGLOG_LEVEL_WARN)
+ fw_dbglog_level = ATH10K_DBGLOG_LEVEL_WARN;
+ fw_dbglog_mask = ~0;
+ }
+
+ ath10k_wmi_dbglog_cfg(ar, fw_dbglog_mask, fw_dbglog_level);
+
+store_regs:
+ /* After an error we will not retry setting the coverage class. */
+ spin_lock_bh(&ar->data_lock);
+ ar->fw_coverage.coverage_class = value;
+ spin_unlock_bh(&ar->data_lock);
+
+ ar->fw_coverage.reg_slottime_conf = slottime_reg;
+ ar->fw_coverage.reg_ack_cts_timeout_conf = timeout_reg;
+
+unlock:
+ mutex_unlock(&ar->conf_mutex);
+}
+
const struct ath10k_hw_ops qca988x_ops = {
+ .set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
};
static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 6038b7486f1d..883547f3347c 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -230,6 +230,7 @@ struct ath10k_hw_regs {
u32 rtc_soc_base_address;
u32 rtc_wmac_base_address;
u32 soc_core_base_address;
+ u32 wlan_mac_base_address;
u32 ce_wrapper_base_address;
u32 ce0_base_address;
u32 ce1_base_address;
@@ -418,6 +419,7 @@ struct htt_rx_desc;
/* Defines needed for Rx descriptor abstraction */
struct ath10k_hw_ops {
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
+ void (*set_coverage_class)(struct ath10k *ar, s16 value);
};
extern const struct ath10k_hw_ops qca988x_ops;
@@ -614,7 +616,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define WLAN_SI_BASE_ADDRESS 0x00010000
#define WLAN_GPIO_BASE_ADDRESS 0x00014000
#define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000
-#define WLAN_MAC_BASE_ADDRESS 0x00020000
+#define WLAN_MAC_BASE_ADDRESS ar->regs->wlan_mac_base_address
#define EFUSE_BASE_ADDRESS 0x00030000
#define FPGA_REG_BASE_ADDRESS 0x00039000
#define WLAN_UART2_BASE_ADDRESS 0x00054c00
@@ -814,4 +816,28 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
+/* Register definitions for first generation ath10k cards. These cards include
+ * a mac thich has a register allocation similar to ath9k and at least some
+ * registers including the ones relevant for modifying the coverage class are
+ * identical to the ath9k definitions.
+ * These registers are usually managed by the ath10k firmware. However by
+ * overriding them it is possible to support coverage class modifications.
+ */
+#define WAVE1_PCU_ACK_CTS_TIMEOUT 0x8014
+#define WAVE1_PCU_ACK_CTS_TIMEOUT_MAX 0x00003FFF
+#define WAVE1_PCU_ACK_CTS_TIMEOUT_ACK_MASK 0x00003FFF
+#define WAVE1_PCU_ACK_CTS_TIMEOUT_ACK_LSB 0
+#define WAVE1_PCU_ACK_CTS_TIMEOUT_CTS_MASK 0x3FFF0000
+#define WAVE1_PCU_ACK_CTS_TIMEOUT_CTS_LSB 16
+
+#define WAVE1_PCU_GBL_IFS_SLOT 0x1070
+#define WAVE1_PCU_GBL_IFS_SLOT_MASK 0x0000FFFF
+#define WAVE1_PCU_GBL_IFS_SLOT_MAX 0x0000FFFF
+#define WAVE1_PCU_GBL_IFS_SLOT_LSB 0
+#define WAVE1_PCU_GBL_IFS_SLOT_RESV0 0xFFFF0000
+
+#define WAVE1_PHYCLK 0x801C
+#define WAVE1_PHYCLK_USEC_MASK 0x0000007F
+#define WAVE1_PHYCLK_USEC_LSB 0
+
#endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 76297d69f1ed..aa545a1dbdc7 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -19,6 +19,7 @@
#include <net/mac80211.h>
#include <linux/etherdevice.h>
+#include <linux/acpi.h>
#include "hif.h"
#include "core.h"
@@ -1166,7 +1167,9 @@ 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_FW_FEATURE_ALLOWS_MESH_BCAST,
+ ar->running_fw->fw_file.fw_features) &&
+ (ar->filter_flags & FIF_OTHER_BSS)) ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
}
@@ -3179,7 +3182,8 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif,
ath10k_mac_vif_tx_unlock(arvif, pause_id);
break;
default:
- ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "received unknown tx pause action %d on vdev %i, ignoring\n",
action, arvif->vdev_id);
break;
}
@@ -3255,8 +3259,6 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
if (ar->htt.target_version_major < 3 &&
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
- ar->running_fw->fw_file.fw_features) &&
- !test_bit(ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
ar->running_fw->fw_file.fw_features))
return ATH10K_HW_TXRX_MGMT;
@@ -4449,7 +4451,6 @@ static int ath10k_start(struct ieee80211_hw *hw)
ar->state = ATH10K_STATE_ON;
break;
case ATH10K_STATE_RESTARTING:
- ath10k_halt(ar);
ar->state = ATH10K_STATE_RESTARTED;
break;
case ATH10K_STATE_ON:
@@ -4929,7 +4930,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
}
ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
+ spin_lock_bh(&ar->data_lock);
list_add(&arvif->list, &ar->arvifs);
+ spin_unlock_bh(&ar->data_lock);
/* It makes no sense to have firmware do keepalives. mac80211 already
* takes care of this with idle connection polling.
@@ -5080,7 +5083,9 @@ err_peer_delete:
err_vdev_delete:
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ spin_lock_bh(&ar->data_lock);
list_del(&arvif->list);
+ spin_unlock_bh(&ar->data_lock);
err:
if (arvif->beacon_buf) {
@@ -5126,7 +5131,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ spin_lock_bh(&ar->data_lock);
list_del(&arvif->list);
+ spin_unlock_bh(&ar->data_lock);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
@@ -5410,6 +5417,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
+static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value)
+{
+ struct ath10k *ar = hw->priv;
+
+ /* This function should never be called if setting the coverage class
+ * is not supported on this hardware.
+ */
+ if (!ar->hw_params.hw_ops->set_coverage_class) {
+ WARN_ON_ONCE(1);
+ return;
+ }
+ ar->hw_params.hw_ops->set_coverage_class(ar, value);
+}
+
static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
@@ -6956,40 +6977,28 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
ieee80211_queue_work(hw, &arsta->update_wk);
}
-static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- /*
- * FIXME: Return 0 for time being. Need to figure out whether FW
- * has the API to fetch 64-bit local TSF
- */
-
- return 0;
-}
-
-static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u64 tsf)
+static void ath10k_offset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, s64 tsf_offset)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
- u32 tsf_offset, vdev_param = ar->wmi.vdev_param->set_tsf;
+ u32 offset, vdev_param;
int ret;
- /* Workaround:
- *
- * Given tsf argument is entire TSF value, but firmware accepts
- * only TSF offset to current TSF.
- *
- * get_tsf function is used to get offset value, however since
- * ath10k_get_tsf is not implemented properly, it will return 0 always.
- * Luckily all the caller functions to set_tsf, as of now, also rely on
- * get_tsf function to get entire tsf value such get_tsf() + tsf_delta,
- * final tsf offset value to firmware will be arithmetically correct.
- */
- tsf_offset = tsf - ath10k_get_tsf(hw, vif);
+ if (tsf_offset < 0) {
+ vdev_param = ar->wmi.vdev_param->dec_tsf;
+ offset = -tsf_offset;
+ } else {
+ vdev_param = ar->wmi.vdev_param->inc_tsf;
+ offset = tsf_offset;
+ }
+
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
- vdev_param, tsf_offset);
+ vdev_param, offset);
+
if (ret && ret != -EOPNOTSUPP)
- ath10k_warn(ar, "failed to set tsf offset: %d\n", ret);
+ ath10k_warn(ar, "failed to set tsf offset %d cmd %d: %d\n",
+ offset, vdev_param, ret);
}
static int ath10k_ampdu_action(struct ieee80211_hw *hw,
@@ -7435,6 +7444,7 @@ static const struct ieee80211_ops ath10k_ops = {
.remove_interface = ath10k_remove_interface,
.configure_filter = ath10k_configure_filter,
.bss_info_changed = ath10k_bss_info_changed,
+ .set_coverage_class = ath10k_mac_op_set_coverage_class,
.hw_scan = ath10k_hw_scan,
.cancel_hw_scan = ath10k_cancel_hw_scan,
.set_key = ath10k_set_key,
@@ -7453,8 +7463,7 @@ static const struct ieee80211_ops ath10k_ops = {
.get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_mac_op_set_bitrate_mask,
.sta_rc_update = ath10k_sta_rc_update,
- .get_tsf = ath10k_get_tsf,
- .set_tsf = ath10k_set_tsf,
+ .offset_tsf = ath10k_offset_tsf,
.ampdu_action = ath10k_ampdu_action,
.get_et_sset_count = ath10k_debug_get_et_sset_count,
.get_et_stats = ath10k_debug_get_et_stats,
@@ -7789,6 +7798,109 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id)
return arvif_iter.arvif;
}
+#define WRD_METHOD "WRDD"
+#define WRDD_WIFI (0x07)
+
+static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
+{
+ union acpi_object *mcc_pkg;
+ union acpi_object *domain_type;
+ union acpi_object *mcc_value;
+ u32 i;
+
+ if (wrdd->type != ACPI_TYPE_PACKAGE ||
+ wrdd->package.count < 2 ||
+ wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
+ wrdd->package.elements[0].integer.value != 0) {
+ ath10k_warn(ar, "ignoring malformed/unsupported wrdd structure\n");
+ return 0;
+ }
+
+ for (i = 1; i < wrdd->package.count; ++i) {
+ mcc_pkg = &wrdd->package.elements[i];
+
+ if (mcc_pkg->type != ACPI_TYPE_PACKAGE)
+ continue;
+ if (mcc_pkg->package.count < 2)
+ continue;
+ if (mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
+ mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
+ continue;
+
+ domain_type = &mcc_pkg->package.elements[0];
+ if (domain_type->integer.value != WRDD_WIFI)
+ continue;
+
+ mcc_value = &mcc_pkg->package.elements[1];
+ return mcc_value->integer.value;
+ }
+ return 0;
+}
+
+static int ath10k_mac_get_wrdd_regulatory(struct ath10k *ar, u16 *rd)
+{
+ struct pci_dev __maybe_unused *pdev = to_pci_dev(ar->dev);
+ acpi_handle root_handle;
+ acpi_handle handle;
+ struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_status status;
+ u32 alpha2_code;
+ char alpha2[3];
+
+ root_handle = ACPI_HANDLE(&pdev->dev);
+ if (!root_handle)
+ return -EOPNOTSUPP;
+
+ status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
+ if (ACPI_FAILURE(status)) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "failed to get wrd method %d\n", status);
+ return -EIO;
+ }
+
+ status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
+ if (ACPI_FAILURE(status)) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "failed to call wrdc %d\n", status);
+ return -EIO;
+ }
+
+ alpha2_code = ath10k_mac_wrdd_get_mcc(ar, wrdd.pointer);
+ kfree(wrdd.pointer);
+ if (!alpha2_code)
+ return -EIO;
+
+ alpha2[0] = (alpha2_code >> 8) & 0xff;
+ alpha2[1] = (alpha2_code >> 0) & 0xff;
+ alpha2[2] = '\0';
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "regulatory hint from WRDD (alpha2-code): %s\n", alpha2);
+
+ *rd = ath_regd_find_country_by_name(alpha2);
+ if (*rd == 0xffff)
+ return -EIO;
+
+ *rd |= COUNTRY_ERD_FLAG;
+ return 0;
+}
+
+static int ath10k_mac_init_rd(struct ath10k *ar)
+{
+ int ret;
+ u16 rd;
+
+ ret = ath10k_mac_get_wrdd_regulatory(ar, &rd);
+ if (ret) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "fallback to eeprom programmed regulatory settings\n");
+ rd = ar->hw_eeprom_rd;
+ }
+
+ ar->ath_common.regulatory.current_rd = rd;
+ return 0;
+}
+
int ath10k_mac_register(struct ath10k *ar)
{
static const u32 cipher_suites[] = {
@@ -7881,6 +7993,8 @@ int ath10k_mac_register(struct ath10k *ar)
ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
+ ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
@@ -8012,6 +8126,16 @@ int ath10k_mac_register(struct ath10k *ar)
ar->running_fw->fw_file.fw_features))
ar->ops->wake_tx_queue = NULL;
+ ret = ath10k_mac_init_rd(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to derive regdom: %d\n", ret);
+ goto err_dfs_detector_exit;
+ }
+
+ /* Disable set_coverage_class for chipsets that do not support it. */
+ if (!ar->hw_params.hw_ops->set_coverage_class)
+ ar->ops->set_coverage_class = NULL;
+
ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
ath10k_reg_notifier);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 7d9b0da1b010..2ffc1fe4923b 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -338,7 +338,7 @@ static ssize_t write_file_spec_scan_ctl(struct file *file,
} else {
res = -EINVAL;
}
- } else if (strncmp("background", buf, 9) == 0) {
+ } else if (strncmp("background", buf, 10) == 0) {
res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
} else if (strncmp("manual", buf, 6) == 0) {
res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index c9a8bb1186f2..c7956e181f80 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -660,6 +660,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_conf)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
@@ -675,6 +678,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_enable)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
enable);
if (IS_ERR(skb))
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index e64f59300a7c..f304f6632c4f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1313,8 +1313,8 @@ ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
cmd->regd = __cpu_to_le32(rd);
cmd->regd_2ghz = __cpu_to_le32(rd2g);
cmd->regd_5ghz = __cpu_to_le32(rd5g);
- cmd->conform_limit_2ghz = __cpu_to_le32(rd2g);
- cmd->conform_limit_5ghz = __cpu_to_le32(rd5g);
+ cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
+ cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
return skb;
@@ -3136,6 +3136,76 @@ ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
return skb;
}
+static struct sk_buff *
+ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
+ const struct wmi_vdev_spectral_conf_arg *arg)
+{
+ struct wmi_vdev_spectral_conf_cmd *cmd;
+ struct sk_buff *skb;
+ struct wmi_tlv *tlv;
+ void *ptr;
+ size_t len;
+
+ len = sizeof(*tlv) + sizeof(*cmd);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ ptr = (void *)skb->data;
+ tlv = ptr;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+ cmd->scan_count = __cpu_to_le32(arg->scan_count);
+ cmd->scan_period = __cpu_to_le32(arg->scan_period);
+ cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+ cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
+ cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
+ cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
+ cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+ cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
+ cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
+ cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
+ cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
+ cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+ cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
+ cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
+ cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
+ cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
+ cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
+ cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
+
+ return skb;
+}
+
+static struct sk_buff *
+ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
+ u32 trigger, u32 enable)
+{
+ struct wmi_vdev_spectral_enable_cmd *cmd;
+ struct sk_buff *skb;
+ struct wmi_tlv *tlv;
+ void *ptr;
+ size_t len;
+
+ len = sizeof(*tlv) + sizeof(*cmd);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ ptr = (void *)skb->data;
+ tlv = ptr;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ cmd->vdev_id = __cpu_to_le32(vdev_id);
+ cmd->trigger_cmd = __cpu_to_le32(trigger);
+ cmd->enable_cmd = __cpu_to_le32(enable);
+
+ return skb;
+}
+
/****************/
/* TLV mappings */
/****************/
@@ -3464,7 +3534,6 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
- .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
};
static const struct wmi_ops wmi_tlv_ops = {
@@ -3542,6 +3611,8 @@ static const struct wmi_ops wmi_tlv_ops = {
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
.gen_echo = ath10k_wmi_tlv_op_gen_echo,
+ .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
+ .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
};
static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 54df425bb0fc..c893314a191f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -785,7 +785,6 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = {
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
- .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
};
/* 10.X WMI VDEV param map */
@@ -861,7 +860,6 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = {
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
- .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
};
static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
@@ -936,7 +934,6 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
- .set_tsf = WMI_10X_VDEV_PARAM_TSF_INCREMENT,
};
static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
@@ -1012,7 +1009,8 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
.meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC,
.rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
.bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
- .set_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
+ .inc_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
+ .dec_tsf = WMI_10_4_VDEV_PARAM_TSF_DECREMENT,
};
static struct wmi_pdev_param_map wmi_pdev_param_map = {
@@ -4489,7 +4487,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
if (!num_units)
return -ENOMEM;
- paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
+ paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL);
if (dma_mapping_error(ar->dev, paddr)) {
kfree(vaddr);
return -ENOMEM;
@@ -4676,7 +4674,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
ar->phy_capability = __le32_to_cpu(arg.phy_capab);
ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
- ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
+ ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
arg.service_map, arg.service_map_len);
@@ -4931,6 +4929,23 @@ exit:
return 0;
}
+static inline void ath10k_wmi_queue_set_coverage_class_work(struct ath10k *ar)
+{
+ if (ar->hw_params.hw_ops->set_coverage_class) {
+ spin_lock_bh(&ar->data_lock);
+
+ /* This call only ensures that the modified coverage class
+ * persists in case the firmware sets the registers back to
+ * their default value. So calling it is only necessary if the
+ * coverage class has a non-zero value.
+ */
+ if (ar->fw_coverage.coverage_class)
+ queue_work(ar->workqueue, &ar->set_coverage_class_work);
+
+ spin_unlock_bh(&ar->data_lock);
+ }
+}
+
static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@@ -4951,6 +4966,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
return;
case WMI_SCAN_EVENTID:
ath10k_wmi_event_scan(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_CHAN_INFO_EVENTID:
ath10k_wmi_event_chan_info(ar, skb);
@@ -4960,15 +4976,18 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_DEBUG_MESG_EVENTID:
ath10k_wmi_event_debug_mesg(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_UPDATE_STATS_EVENTID:
ath10k_wmi_event_update_stats(ar, skb);
break;
case WMI_VDEV_START_RESP_EVENTID:
ath10k_wmi_event_vdev_start_resp(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_VDEV_STOPPED_EVENTID:
ath10k_wmi_event_vdev_stopped(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_PEER_STA_KICKOUT_EVENTID:
ath10k_wmi_event_peer_sta_kickout(ar, skb);
@@ -4984,12 +5003,14 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_ROAM_EVENTID:
ath10k_wmi_event_roam(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_PROFILE_MATCH:
ath10k_wmi_event_profile_match(ar, skb);
break;
case WMI_DEBUG_PRINT_EVENTID:
ath10k_wmi_event_debug_print(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_PDEV_QVIT_EVENTID:
ath10k_wmi_event_pdev_qvit(ar, skb);
@@ -5038,6 +5059,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
return;
case WMI_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
@@ -5081,6 +5103,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
return;
case WMI_10X_SCAN_EVENTID:
ath10k_wmi_event_scan(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_CHAN_INFO_EVENTID:
ath10k_wmi_event_chan_info(ar, skb);
@@ -5090,15 +5113,18 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10X_DEBUG_MESG_EVENTID:
ath10k_wmi_event_debug_mesg(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_UPDATE_STATS_EVENTID:
ath10k_wmi_event_update_stats(ar, skb);
break;
case WMI_10X_VDEV_START_RESP_EVENTID:
ath10k_wmi_event_vdev_start_resp(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_VDEV_STOPPED_EVENTID:
ath10k_wmi_event_vdev_stopped(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_PEER_STA_KICKOUT_EVENTID:
ath10k_wmi_event_peer_sta_kickout(ar, skb);
@@ -5114,12 +5140,14 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10X_ROAM_EVENTID:
ath10k_wmi_event_roam(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_PROFILE_MATCH:
ath10k_wmi_event_profile_match(ar, skb);
break;
case WMI_10X_DEBUG_PRINT_EVENTID:
ath10k_wmi_event_debug_print(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_PDEV_QVIT_EVENTID:
ath10k_wmi_event_pdev_qvit(ar, skb);
@@ -5159,6 +5187,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
return;
case WMI_10X_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10X_PDEV_UTF_EVENTID:
/* ignore utf events */
@@ -5205,6 +5234,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
return;
case WMI_10_2_SCAN_EVENTID:
ath10k_wmi_event_scan(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_CHAN_INFO_EVENTID:
ath10k_wmi_event_chan_info(ar, skb);
@@ -5214,15 +5244,18 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_2_DEBUG_MESG_EVENTID:
ath10k_wmi_event_debug_mesg(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_UPDATE_STATS_EVENTID:
ath10k_wmi_event_update_stats(ar, skb);
break;
case WMI_10_2_VDEV_START_RESP_EVENTID:
ath10k_wmi_event_vdev_start_resp(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_VDEV_STOPPED_EVENTID:
ath10k_wmi_event_vdev_stopped(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_PEER_STA_KICKOUT_EVENTID:
ath10k_wmi_event_peer_sta_kickout(ar, skb);
@@ -5238,12 +5271,14 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_2_ROAM_EVENTID:
ath10k_wmi_event_roam(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_PROFILE_MATCH:
ath10k_wmi_event_profile_match(ar, skb);
break;
case WMI_10_2_DEBUG_PRINT_EVENTID:
ath10k_wmi_event_debug_print(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_PDEV_QVIT_EVENTID:
ath10k_wmi_event_pdev_qvit(ar, skb);
@@ -5274,15 +5309,18 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_2_VDEV_STANDBY_REQ_EVENTID:
ath10k_wmi_event_vdev_standby_req(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_VDEV_RESUME_REQ_EVENTID:
ath10k_wmi_event_vdev_resume_req(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_SERVICE_READY_EVENTID:
ath10k_wmi_event_service_ready(ar, skb);
return;
case WMI_10_2_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_2_PDEV_TEMPERATURE_EVENTID:
ath10k_wmi_event_temperature(ar, skb);
@@ -5345,12 +5383,14 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_4_DEBUG_MESG_EVENTID:
ath10k_wmi_event_debug_mesg(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_SERVICE_READY_EVENTID:
ath10k_wmi_event_service_ready(ar, skb);
return;
case WMI_10_4_SCAN_EVENTID:
ath10k_wmi_event_scan(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_CHAN_INFO_EVENTID:
ath10k_wmi_event_chan_info(ar, skb);
@@ -5360,12 +5400,14 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_4_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_PEER_STA_KICKOUT_EVENTID:
ath10k_wmi_event_peer_sta_kickout(ar, skb);
break;
case WMI_10_4_ROAM_EVENTID:
ath10k_wmi_event_roam(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_HOST_SWBA_EVENTID:
ath10k_wmi_event_host_swba(ar, skb);
@@ -5375,12 +5417,15 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
break;
case WMI_10_4_DEBUG_PRINT_EVENTID:
ath10k_wmi_event_debug_print(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_VDEV_START_RESP_EVENTID:
ath10k_wmi_event_vdev_start_resp(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_VDEV_STOPPED_EVENTID:
ath10k_wmi_event_vdev_stopped(ar, skb);
+ ath10k_wmi_queue_set_coverage_class_work(ar);
break;
case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
case WMI_10_4_PEER_RATECODE_LIST_EVENTID:
@@ -5397,6 +5442,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID:
ath10k_wmi_event_pdev_bss_chan_info(ar, skb);
break;
+ case WMI_10_4_PDEV_TPC_CONFIG_EVENTID:
+ ath10k_wmi_event_pdev_tpc_config(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
@@ -6096,6 +6144,7 @@ void ath10k_wmi_start_scan_init(struct ath10k *ar,
| WMI_SCAN_EVENT_COMPLETED
| WMI_SCAN_EVENT_BSS_CHANNEL
| WMI_SCAN_EVENT_FOREIGN_CHANNEL
+ | WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT
| WMI_SCAN_EVENT_DEQUEUED;
arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT;
arg->n_bssids = 1;
@@ -8153,6 +8202,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype,
.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
.gen_echo = ath10k_wmi_op_gen_echo,
+ .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
};
int ath10k_wmi_attach(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 1b243c899bef..5d3dff95b2e5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4603,9 +4603,17 @@ enum wmi_rate_preamble {
#define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3))
#define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3)
-#define ATH10K_HW_RATECODE(rate, nss, preamble) \
+#define ATH10K_HW_MCS_RATE(rate) ((rate) & 0xf)
+#define ATH10K_HW_LEGACY_RATE(rate) ((rate) & 0x3f)
+#define ATH10K_HW_BW(flags) (((flags) >> 3) & 0x3)
+#define ATH10K_HW_GI(flags) (((flags) >> 5) & 0x1)
+#define ATH10K_HW_RATECODE(rate, nss, preamble) \
(((preamble) << 6) | ((nss) << 4) | (rate))
+#define VHT_MCS_NUM 10
+#define VHT_BW_NUM 4
+#define VHT_NSS_NUM 4
+
/* Value to disable fixed rate setting */
#define WMI_FIXED_RATE_NONE (0xff)
@@ -4676,7 +4684,8 @@ struct wmi_vdev_param_map {
u32 meru_vc;
u32 rx_decap_type;
u32 bw_nss_ratemask;
- u32 set_tsf;
+ u32 inc_tsf;
+ u32 dec_tsf;
};
#define WMI_VDEV_PARAM_UNSUPPORTED 0
@@ -5009,6 +5018,11 @@ enum wmi_10_4_vdev_param {
WMI_10_4_VDEV_PARAM_STA_KICKOUT,
WMI_10_4_VDEV_PARAM_CAPABILITIES,
WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
+ WMI_10_4_VDEV_PARAM_RX_FILTER,
+ WMI_10_4_VDEV_PARAM_MGMT_TX_POWER,
+ WMI_10_4_VDEV_PARAM_ATF_SSID_SCHED_POLICY,
+ WMI_10_4_VDEV_PARAM_DISABLE_DYN_BW_RTS,
+ WMI_10_4_VDEV_PARAM_TSF_DECREMENT,
};
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4f8d9ed04f5e..d068df520e7a 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -66,7 +66,6 @@
#include <linux/seq_file.h>
#include <linux/list.h>
-#include <linux/vmalloc.h>
#include "debug.h"
#include "ath5k.h"
#include "reg.h"
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 76eb33679d4b..8ec66e74d06d 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -75,6 +75,8 @@ struct ath6kl_sdio {
#define CMD53_ARG_FIXED_ADDRESS 0
#define CMD53_ARG_INCR_ADDRESS 1
+static int ath6kl_sdio_config(struct ath6kl *ar);
+
static inline struct ath6kl_sdio *ath6kl_sdio_priv(struct ath6kl *ar)
{
return ar->hif_priv;
@@ -526,8 +528,15 @@ static int ath6kl_sdio_power_on(struct ath6kl *ar)
*/
msleep(10);
+ ret = ath6kl_sdio_config(ar);
+ if (ret) {
+ ath6kl_err("Failed to config sdio: %d\n", ret);
+ goto out;
+ }
+
ar_sdio->is_disabled = false;
+out:
return ret;
}
@@ -703,8 +712,10 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
* ath6kl_hif_rw_comp_handler() with status -ECANCELED so
* that the packet is properly freed?
*/
- if (s_req->busrequest)
+ if (s_req->busrequest) {
+ s_req->busrequest->scat_req = 0;
ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest);
+ }
kfree(s_req->virt_dma_buf);
kfree(s_req->sgentries);
kfree(s_req);
@@ -712,6 +723,8 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
spin_lock_bh(&ar_sdio->scat_lock);
}
spin_unlock_bh(&ar_sdio->scat_lock);
+
+ ar_sdio->scatter_enabled = false;
}
/* setup of HIF scatter resources */
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 3fd1cc98fd2f..84a6d12c3f8a 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -421,10 +421,6 @@ int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
switch ((le16_to_cpu(wh.frame_control)) &
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
- case 0:
- memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
- memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
- break;
case IEEE80211_FCTL_TODS:
memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
@@ -435,6 +431,10 @@ int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
break;
case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
break;
+ default:
+ memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
+ memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
+ break;
}
skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index bea6186f745a..2bd982c3a479 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -62,7 +62,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
return false;
}
-static struct ath_bus_ops ath_ahb_bus_ops = {
+static const struct ath_bus_ops ath_ahb_bus_ops = {
.ath_bus_type = ATH_AHB,
.read_cachesize = ath_ahb_read_cachesize,
.eeprom_read = ath_ahb_eeprom_read,
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 26fc8ecfe8c4..378d3458fddb 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -91,7 +91,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_RXBUF 512
#define ATH_TXBUF 512
#define ATH_TXBUF_RESERVE 5
-#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
#define ATH_TXMAXTRY 13
#define ATH_MAX_SW_RETRIES 30
@@ -145,7 +144,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 4095) < (_bawsz))
-#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
+#define ATH_AN_2_TID(_an, _tidno) ath_node_to_tid(_an, _tidno)
#define IS_HT_RATE(rate) (rate & 0x80)
#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
@@ -164,7 +163,6 @@ struct ath_txq {
spinlock_t axq_lock;
u32 axq_depth;
u32 axq_ampdu_depth;
- bool stopped;
bool axq_tx_inprogress;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
u8 txq_headidx;
@@ -232,7 +230,6 @@ struct ath_buf {
struct ath_atx_tid {
struct list_head list;
- struct sk_buff_head buf_q;
struct sk_buff_head retry_q;
struct ath_node *an;
struct ath_txq *txq;
@@ -247,13 +244,13 @@ struct ath_atx_tid {
s8 bar_index;
bool active;
bool clear_ps_filter;
+ bool has_queued;
};
struct ath_node {
struct ath_softc *sc;
struct ieee80211_sta *sta; /* station struct we're part of */
struct ieee80211_vif *vif; /* interface with which we're associated */
- struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
u16 maxampdu;
u8 mpdudensity;
@@ -276,7 +273,6 @@ struct ath_tx_control {
struct ath_node *an;
struct ieee80211_sta *sta;
u8 paprd;
- bool force_channel;
};
@@ -293,7 +289,6 @@ struct ath_tx {
struct ath_descdma txdma;
struct ath_txq *txq_map[IEEE80211_NUM_ACS];
struct ath_txq *uapsdq;
- u32 txq_max_pending[IEEE80211_NUM_ACS];
u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
};
@@ -421,6 +416,22 @@ struct ath_offchannel {
int duration;
};
+static inline struct ath_atx_tid *
+ath_node_to_tid(struct ath_node *an, u8 tidno)
+{
+ struct ieee80211_sta *sta = an->sta;
+ struct ieee80211_vif *vif = an->vif;
+ struct ieee80211_txq *txq;
+
+ BUG_ON(!vif);
+ if (sta)
+ txq = sta->txq[tidno % ARRAY_SIZE(sta->txq)];
+ else
+ txq = vif->txq;
+
+ return (struct ath_atx_tid *) txq->drv_priv;
+}
+
#define case_rtn_string(val) case val: return #val
#define ath_for_each_chanctx(_sc, _ctx) \
@@ -575,7 +586,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@@ -585,6 +595,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
u16 tids, int nframes,
enum ieee80211_frame_release_type reason,
bool more_data);
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
/********/
/* VIFs */
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 57e26a640477..929dd70f48eb 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1010,7 +1010,6 @@ static void ath_scan_send_probe(struct ath_softc *sc,
goto error;
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
- txctl.force_channel = true;
if (ath_tx_start(sc->hw, skb, &txctl))
goto error;
@@ -1133,7 +1132,6 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
txctl.sta = sta;
- txctl.force_channel = true;
if (ath_tx_start(sc->hw, skb, &txctl)) {
ieee80211_free_txskb(sc->hw, skb);
return false;
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index e2512d5bc0e1..eedf86b67cf5 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -528,6 +528,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
return 0;
+ if (!spec_priv->rfs_chan_spec_scan)
+ return 1;
+
/* Output buffers are full, no need to process anything
* since there is no space to put the result anyway
*/
@@ -1072,7 +1075,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = {
void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
{
- if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS)) {
+ if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) {
relay_close(spec_priv->rfs_chan_spec_scan);
spec_priv->rfs_chan_spec_scan = NULL;
}
@@ -1086,6 +1089,9 @@ void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
NULL);
+ if (!spec_priv->rfs_chan_spec_scan)
+ return;
+
debugfs_create_file("spectral_scan_ctl",
S_IRUSR | S_IWUSR,
debugfs_phy, spec_priv,
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index c56e40ff35e5..89a94dd5f2cb 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -600,7 +600,6 @@ static int read_file_xmit(struct seq_file *file, void *data)
PR("MPDUs XRetried: ", xretries);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued HW:", a_queued_hw);
- PR("AMPDUs Queued SW:", a_queued_sw);
PR("AMPDUs Completed:", a_completed);
PR("AMPDUs Retried: ", a_retries);
PR("AMPDUs XRetried: ", a_xretries);
@@ -629,8 +628,7 @@ static void print_queue(struct ath_softc *sc, struct ath_txq *txq,
seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
- seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
- seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
+ seq_printf(file, "%s: %3d\n", "pending", txq->pending_frames);
ath_txq_unlock(sc, txq);
}
@@ -1208,7 +1206,6 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
AMKSTR(d_tx_mpdu_xretries),
AMKSTR(d_tx_aggregates),
AMKSTR(d_tx_ampdus_queued_hw),
- AMKSTR(d_tx_ampdus_queued_sw),
AMKSTR(d_tx_ampdus_completed),
AMKSTR(d_tx_ampdu_retries),
AMKSTR(d_tx_ampdu_xretries),
@@ -1288,7 +1285,6 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
AWDATA(xretries);
AWDATA(a_aggr);
AWDATA(a_queued_hw);
- AWDATA(a_queued_sw);
AWDATA(a_completed);
AWDATA(a_retries);
AWDATA(a_xretries);
@@ -1346,14 +1342,6 @@ int ath9k_init_debug(struct ath_hw *ah)
read_file_xmit);
debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy,
read_file_queues);
- debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
- debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
- debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
- debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
read_file_misc);
debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cd68c5f0e751..a078cdd3170d 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -147,7 +147,6 @@ struct ath_interrupt_stats {
* @completed: Total MPDUs (non-aggr) completed
* @a_aggr: Total no. of aggregates queued
* @a_queued_hw: Total AMPDUs queued to hardware
- * @a_queued_sw: Total AMPDUs queued to software queues
* @a_completed: Total AMPDUs completed
* @a_retries: No. of AMPDUs retried (SW)
* @a_xretries: No. of AMPDUs dropped due to xretries
@@ -174,7 +173,6 @@ struct ath_tx_stats {
u32 xretries;
u32 a_aggr;
u32 a_queued_hw;
- u32 a_queued_sw;
u32 a_completed;
u32 a_retries;
u32 a_xretries;
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index b66cfa91364f..2a3a3c4671bc 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -52,8 +52,8 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
"TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
"BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+ tid = ath_node_to_tid(an, tidno);
txq = tid->txq;
ath_txq_lock(sc, txq);
if (tid->active) {
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index e1c338cb9cb5..de2d212f39ec 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -997,7 +997,8 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
err = usb_control_msg(hif_dev->udev,
usb_sndctrlpipe(hif_dev->udev, 0),
FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
- addr >> 8, 0, buf, transfer, HZ);
+ addr >> 8, 0, buf, transfer,
+ USB_MSG_TIMEOUT);
if (err < 0) {
kfree(buf);
return err;
@@ -1020,7 +1021,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
FIRMWARE_DOWNLOAD_COMP,
0x40 | USB_DIR_OUT,
- firm_offset >> 8, 0, NULL, 0, HZ);
+ firm_offset >> 8, 0, NULL, 0, USB_MSG_TIMEOUT);
if (err)
return -EIO;
@@ -1249,7 +1250,7 @@ static int send_eject_command(struct usb_interface *interface)
dev_info(&udev->dev, "Ejecting storage device...\n");
r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
- cmd, 31, NULL, 2000);
+ cmd, 31, NULL, 2 * USB_MSG_TIMEOUT);
kfree(cmd);
if (r)
return r;
@@ -1314,7 +1315,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev)
return;
ret = usb_interrupt_msg(udev, usb_sndintpipe(udev, USB_REG_OUT_PIPE),
- buf, 4, NULL, HZ);
+ buf, 4, NULL, USB_MSG_TIMEOUT);
if (ret)
dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 7c2ef7ecd98b..7846916aa01d 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -71,6 +71,8 @@ extern int htc_use_dev_fw;
#define USB_REG_IN_PIPE 3
#define USB_REG_OUT_PIPE 4
+#define USB_MSG_TIMEOUT 1000 /* (ms) */
+
#define HIF_USB_MAX_RXPIPES 2
#define HIF_USB_MAX_TXPIPES 4
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index fd85f996c554..8e6dae23669b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -244,8 +244,8 @@ int htc_connect_service(struct htc_target *target,
/* Find an available endpoint */
endpoint = get_next_avail_ep(target->endpoint);
if (!endpoint) {
- dev_err(target->dev, "Endpoint is not available for"
- "service %d\n", service_connreq->service_id);
+ dev_err(target->dev, "Endpoint is not available for service %d\n",
+ service_connreq->service_id);
return -EINVAL;
}
@@ -382,7 +382,7 @@ static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
break;
}
default:
- dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
+ dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
break;
}
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 14b13f07cd1f..a35f78be8dec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2792,7 +2792,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
WARN_ON(1);
}
- return val;
+ return !!val;
}
EXPORT_SYMBOL(ath9k_hw_gpio_get);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index cfa3fe82ade3..20794660d6ae 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -20,6 +20,8 @@
#include <linux/slab.h>
#include <linux/ath9k_platform.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
#include <linux/relay.h>
#include <net/ieee80211_radiotap.h>
@@ -358,7 +360,6 @@ static int ath9k_init_queues(struct ath_softc *sc)
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
sc->tx.txq_map[i]->mac80211_qnum = i;
- sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
}
return 0;
}
@@ -555,6 +556,42 @@ static int ath9k_init_platform(struct ath_softc *sc)
return 0;
}
+static int ath9k_of_init(struct ath_softc *sc)
+{
+ struct device_node *np = sc->dev->of_node;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ enum ath_bus_type bus_type = common->bus_ops->ath_bus_type;
+ const char *mac;
+ char eeprom_name[100];
+ int ret;
+
+ if (!of_device_is_available(np))
+ return 0;
+
+ ath_dbg(common, CONFIG, "parsing configuration from OF node\n");
+
+ if (of_property_read_bool(np, "qca,no-eeprom")) {
+ /* ath9k-eeprom-<bus>-<id>.bin */
+ scnprintf(eeprom_name, sizeof(eeprom_name),
+ "ath9k-eeprom-%s-%s.bin",
+ ath_bus_type_to_string(bus_type), dev_name(ah->dev));
+
+ ret = ath9k_eeprom_request(sc, eeprom_name);
+ if (ret)
+ return ret;
+ }
+
+ mac = of_get_mac_address(np);
+ if (mac)
+ ether_addr_copy(common->macaddr, mac);
+
+ ah->ah_flags &= ~AH_USE_EEPROM;
+ ah->ah_flags |= AH_NO_EEP_SWAP;
+
+ return 0;
+}
+
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
@@ -611,6 +648,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
if (ret)
return ret;
+ ret = ath9k_of_init(sc);
+ if (ret)
+ return ret;
+
if (ath9k_led_active_high != -1)
ah->config.led_active_high = ath9k_led_active_high == 1;
@@ -734,9 +775,11 @@ static const struct ieee80211_iface_limit if_limits[] = {
BIT(NL80211_IFTYPE_P2P_GO) },
};
+#ifdef CONFIG_WIRELESS_WDS
static const struct ieee80211_iface_limit wds_limits[] = {
{ .max = 2048, .types = BIT(NL80211_IFTYPE_WDS) },
};
+#endif
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
@@ -774,6 +817,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
BIT(NL80211_CHAN_WIDTH_40),
#endif
},
+#ifdef CONFIG_WIRELESS_WDS
{
.limits = wds_limits,
.n_limits = ARRAY_SIZE(wds_limits),
@@ -781,6 +825,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
.num_different_channels = 1,
.beacon_int_infra_match = true,
},
+#endif
};
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
@@ -851,7 +896,9 @@ 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) |
+#ifdef CONFIG_WIRELESS_WDS
BIT(NL80211_IFTYPE_WDS) |
+#endif
BIT(NL80211_IFTYPE_OCB);
if (ath9k_is_chanctx_enabled())
@@ -877,6 +924,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->txq_data_size = sizeof(struct ath_atx_tid);
hw->extra_tx_headroom = 4;
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e9f32b52fc8c..59e3bd0f4c20 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1902,9 +1902,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
bool flush = false;
int ret = 0;
struct ieee80211_sta *sta = params->sta;
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
u16 *ssn = &params->ssn;
+ struct ath_atx_tid *atid;
mutex_lock(&sc->mutex);
@@ -1937,9 +1939,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
ath9k_ps_restore(sc);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
- ath9k_ps_wakeup(sc);
- ath_tx_aggr_resume(sc, sta, tid);
- ath9k_ps_restore(sc);
+ atid = ath_node_to_tid(an, tid);
+ atid->baw_size = IEEE80211_MIN_AMPDU_BUF <<
+ sta->ht_cap.ampdu_factor;
break;
default:
ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
@@ -2701,4 +2703,5 @@ struct ieee80211_ops ath9k_ops = {
.sw_scan_start = ath9k_sw_scan_start,
.sw_scan_complete = ath9k_sw_scan_complete,
.get_txpower = ath9k_get_txpower,
+ .wake_tx_queue = ath9k_wake_tx_queue,
};
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 0dd454acf22a..aff473dfa10d 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -26,7 +26,6 @@ static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
- { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
#ifdef CONFIG_ATH9K_PCOEM
/* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */
@@ -37,7 +36,7 @@ static const struct pci_device_id ath_pci_id_table[] = {
.driver_data = ATH9K_PCI_LED_ACT_HI },
#endif
- { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
#ifdef CONFIG_ATH9K_PCOEM
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
@@ -85,7 +84,11 @@ static const struct pci_device_id ath_pci_id_table[] = {
0x10CF, /* Fujitsu */
0x1536),
.driver_data = ATH9K_PCI_D3_L1_WAR },
+#endif
+ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+
+#ifdef CONFIG_ATH9K_PCOEM
/* AR9285 card for Asus */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x002B,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 669734252664..fb4ba27d92b7 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -867,10 +867,21 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* can be dropped.
*/
if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
- ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
- if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime))
+ /*
+ * DFS and spectral are mutually exclusive
+ *
+ * Since some chips use PHYERR_RADAR as indication for both, we
+ * need to double check which feature is enabled to prevent
+ * feeding spectral or dfs-detector with wrong frames.
+ */
+ if (hw->conf.radar_enabled) {
+ ath9k_dfs_process_phyerr(sc, hdr, rx_stats,
+ rx_status->mactime);
+ } else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED &&
+ ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats,
+ rx_status->mactime)) {
RX_STAT_INC(rx_spectral);
-
+ }
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
index d38e50f96db7..568b1c6c2b2b 100644
--- a/drivers/net/wireless/ath/ath9k/rng.c
+++ b/drivers/net/wireless/ath/ath9k/rng.c
@@ -22,7 +22,7 @@
#include "ar9003_phy.h"
#define ATH9K_RNG_BUF_SIZE 320
-#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 320) >> 10) /* quality: 320/1024 */
+#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 10) >> 5) /* quality: 10/32 */
static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
{
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 52bfbb988611..486afa98a5b8 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -67,6 +67,8 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
struct sk_buff *skb);
+static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath_tx_control *txctl);
enum {
MCS_HT20,
@@ -137,6 +139,26 @@ static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
list_add_tail(&tid->list, list);
}
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv;
+ struct ath_txq *txq = tid->txq;
+
+ ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n",
+ queue->sta ? queue->sta->addr : queue->vif->addr,
+ tid->tidno);
+
+ ath_txq_lock(sc, txq);
+
+ tid->has_queued = true;
+ ath_tx_queue_tid(sc, txq, tid);
+ ath_txq_schedule(sc, txq);
+
+ ath_txq_unlock(sc, txq);
+}
+
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -164,7 +186,6 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_frame_info *fi = get_frame_info(skb);
int q = fi->txq;
@@ -175,14 +196,6 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
- if (txq->stopped &&
- txq->pending_frames < sc->tx.txq_max_pending[q]) {
- if (ath9k_is_chanctx_enabled())
- ieee80211_wake_queue(sc->hw, info->hw_queue);
- else
- ieee80211_wake_queue(sc->hw, q);
- txq->stopped = false;
- }
}
static struct ath_atx_tid *
@@ -192,9 +205,48 @@ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
return ATH_AN_2_TID(an, tidno);
}
+static struct sk_buff *
+ath_tid_pull(struct ath_atx_tid *tid)
+{
+ struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv);
+ struct ath_softc *sc = tid->an->sc;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_tx_control txctl = {
+ .txq = tid->txq,
+ .sta = tid->an->sta,
+ };
+ struct sk_buff *skb;
+ struct ath_frame_info *fi;
+ int q;
+
+ if (!tid->has_queued)
+ return NULL;
+
+ skb = ieee80211_tx_dequeue(hw, txq);
+ if (!skb) {
+ tid->has_queued = false;
+ return NULL;
+ }
+
+ if (ath_tx_prepare(hw, skb, &txctl)) {
+ ieee80211_free_txskb(hw, skb);
+ return NULL;
+ }
+
+ q = skb_get_queue_mapping(skb);
+ if (tid->txq == sc->tx.txq_map[q]) {
+ fi = get_frame_info(skb);
+ fi->txq = q;
+ ++tid->txq->pending_frames;
+ }
+
+ return skb;
+ }
+
+
static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
{
- return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q);
+ return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
}
static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
@@ -203,46 +255,11 @@ static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
skb = __skb_dequeue(&tid->retry_q);
if (!skb)
- skb = __skb_dequeue(&tid->buf_q);
+ skb = ath_tid_pull(tid);
return skb;
}
-/*
- * ath_tx_tid_change_state:
- * - clears a-mpdu flag of previous session
- * - force sequence number allocation to fix next BlockAck Window
- */
-static void
-ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
- struct ath_txq *txq = tid->txq;
- struct ieee80211_tx_info *tx_info;
- struct sk_buff *skb, *tskb;
- struct ath_buf *bf;
- struct ath_frame_info *fi;
-
- skb_queue_walk_safe(&tid->buf_q, skb, tskb) {
- fi = get_frame_info(skb);
- bf = fi->bf;
-
- tx_info = IEEE80211_SKB_CB(skb);
- tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
- if (bf)
- continue;
-
- bf = ath_tx_setup_buffer(sc, txq, tid, skb);
- if (!bf) {
- __skb_unlink(skb, &tid->buf_q);
- ath_txq_skb_done(sc, txq, skb);
- ieee80211_free_txskb(sc->hw, skb);
- continue;
- }
- }
-
-}
-
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->txq;
@@ -883,20 +900,16 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
static struct ath_buf *
ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid, struct sk_buff_head **q)
+ struct ath_atx_tid *tid)
{
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
- struct sk_buff *skb;
+ struct sk_buff *skb, *first_skb = NULL;
struct ath_buf *bf;
u16 seqno;
while (1) {
- *q = &tid->retry_q;
- if (skb_queue_empty(*q))
- *q = &tid->buf_q;
-
- skb = skb_peek(*q);
+ skb = ath_tid_dequeue(tid);
if (!skb)
break;
@@ -908,7 +921,6 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_state.stale = false;
if (!bf) {
- __skb_unlink(skb, *q);
ath_txq_skb_done(sc, txq, skb);
ieee80211_free_txskb(sc->hw, skb);
continue;
@@ -937,8 +949,20 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
seqno = bf->bf_state.seqno;
/* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno))
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+ __skb_queue_tail(&tid->retry_q, skb);
+
+ /* If there are other skbs in the retry q, they are
+ * probably within the BAW, so loop immediately to get
+ * one of them. Otherwise the queue can get stuck. */
+ if (!skb_queue_is_first(&tid->retry_q, skb) &&
+ !WARN_ON(skb == first_skb)) {
+ if(!first_skb) /* infinite loop prevention */
+ first_skb = skb;
+ continue;
+ }
break;
+ }
if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
struct ath_tx_status ts = {};
@@ -946,7 +970,6 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
- __skb_unlink(skb, *q);
ath_tx_update_baw(sc, tid, seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
continue;
@@ -958,11 +981,10 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
return NULL;
}
-static bool
+static int
ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid, struct list_head *bf_q,
- struct ath_buf *bf_first, struct sk_buff_head *tid_q,
- int *aggr_len)
+ struct ath_buf *bf_first)
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
struct ath_buf *bf = bf_first, *bf_prev = NULL;
@@ -972,12 +994,13 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
struct sk_buff *skb;
- bool closed = false;
+
bf = bf_first;
aggr_limit = ath_lookup_rate(sc, bf, tid);
- do {
+ while (bf)
+ {
skb = bf->bf_mpdu;
fi = get_frame_info(skb);
@@ -986,12 +1009,12 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (nframes) {
if (aggr_limit < al + bpad + al_delta ||
ath_lookup_legacy(bf) || nframes >= h_baw)
- break;
+ goto stop;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
!(tx_info->flags & IEEE80211_TX_CTL_AMPDU))
- break;
+ goto stop;
}
/* add padding for previous frame to aggregation length */
@@ -1013,20 +1036,18 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_addto_baw(sc, tid, bf);
bf->bf_state.ndelim = ndelim;
- __skb_unlink(skb, tid_q);
list_add_tail(&bf->list, bf_q);
if (bf_prev)
bf_prev->bf_next = bf;
bf_prev = bf;
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
- if (!bf) {
- closed = true;
- break;
- }
- } while (ath_tid_has_buffered(tid));
-
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
+ }
+ goto finish;
+stop:
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
+finish:
bf = bf_first;
bf->bf_lastbf = bf_prev;
@@ -1037,9 +1058,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
TX_STAT_INC(txq->axq_qnum, a_aggr);
}
- *aggr_len = al;
-
- return closed;
+ return al;
#undef PADBYTES
}
@@ -1416,18 +1435,15 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
static void
ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid, struct list_head *bf_q,
- struct ath_buf *bf_first, struct sk_buff_head *tid_q)
+ struct ath_buf *bf_first)
{
struct ath_buf *bf = bf_first, *bf_prev = NULL;
- struct sk_buff *skb;
int nframes = 0;
do {
struct ieee80211_tx_info *tx_info;
- skb = bf->bf_mpdu;
nframes++;
- __skb_unlink(skb, tid_q);
list_add_tail(&bf->list, bf_q);
if (bf_prev)
bf_prev->bf_next = bf;
@@ -1436,13 +1452,15 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
if (nframes >= 2)
break;
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
if (!bf)
break;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
break;
+ }
ath_set_rates(tid->an->vif, tid->an->sta, bf);
} while (1);
@@ -1453,34 +1471,33 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
{
struct ath_buf *bf;
struct ieee80211_tx_info *tx_info;
- struct sk_buff_head *tid_q;
struct list_head bf_q;
int aggr_len = 0;
- bool aggr, last = true;
+ bool aggr;
if (!ath_tid_has_buffered(tid))
return false;
INIT_LIST_HEAD(&bf_q);
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
if (!bf)
return false;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
- (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+ (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
*stop = true;
return false;
}
ath_set_rates(tid->an->vif, tid->an->sta, bf);
if (aggr)
- last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
- tid_q, &aggr_len);
+ aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf);
else
- ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
+ ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
if (list_empty(&bf_q))
return false;
@@ -1523,9 +1540,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
an->mpdudensity = density;
}
- /* force sequence number allocation for pending frames */
- ath_tx_tid_change_state(sc, txtid);
-
txtid->active = true;
*ssn = txtid->seq_start = txtid->seq_next;
txtid->bar_index = -1;
@@ -1550,7 +1564,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
ath_txq_lock(sc, txq);
txtid->active = false;
ath_tx_flush_tid(sc, txtid);
- ath_tx_tid_change_state(sc, txtid);
ath_txq_unlock_complete(sc, txq);
}
@@ -1560,14 +1573,12 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_txq *txq;
- bool buffered;
int tidno;
ath_dbg(common, XMIT, "%s called\n", __func__);
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+ tid = ath_node_to_tid(an, tidno);
txq = tid->txq;
ath_txq_lock(sc, txq);
@@ -1577,13 +1588,12 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
continue;
}
- buffered = ath_tid_has_buffered(tid);
+ if (!skb_queue_empty(&tid->retry_q))
+ ieee80211_sta_set_buffered(sta, tid->tidno, true);
list_del_init(&tid->list);
ath_txq_unlock(sc, txq);
-
- ieee80211_sta_set_buffered(sta, tidno, buffered);
}
}
@@ -1596,49 +1606,20 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ath_dbg(common, XMIT, "%s called\n", __func__);
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+ tid = ath_node_to_tid(an, tidno);
txq = tid->txq;
ath_txq_lock(sc, txq);
tid->clear_ps_filter = true;
-
if (ath_tid_has_buffered(tid)) {
ath_tx_queue_tid(sc, txq, tid);
ath_txq_schedule(sc, txq);
}
-
ath_txq_unlock_complete(sc, txq);
}
}
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tidno)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_atx_tid *tid;
- struct ath_node *an;
- struct ath_txq *txq;
-
- ath_dbg(common, XMIT, "%s called\n", __func__);
-
- an = (struct ath_node *)sta->drv_priv;
- tid = ATH_AN_2_TID(an, tidno);
- txq = tid->txq;
-
- ath_txq_lock(sc, txq);
-
- tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-
- if (ath_tid_has_buffered(tid)) {
- ath_tx_queue_tid(sc, txq, tid);
- ath_txq_schedule(sc, txq);
- }
-
- ath_txq_unlock_complete(sc, txq);
-}
-
void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u16 tids, int nframes,
@@ -1651,7 +1632,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info;
struct list_head bf_q;
struct ath_buf *bf_tail = NULL, *bf;
- struct sk_buff_head *tid_q;
int sent = 0;
int i;
@@ -1666,11 +1646,10 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
ath_txq_lock(sc, tid->txq);
while (nframes > 0) {
- bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
+ bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
if (!bf)
break;
- __skb_unlink(bf->bf_mpdu, tid_q);
list_add_tail(&bf->list, &bf_q);
ath_set_rates(tid->an->vif, tid->an->sta, bf);
if (bf_isampdu(bf)) {
@@ -1685,7 +1664,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
sent++;
TX_STAT_INC(txq->axq_qnum, a_queued_hw);
- if (an->sta && !ath_tid_has_buffered(tid))
+ if (an->sta && skb_queue_empty(&tid->retry_q))
ieee80211_sta_set_buffered(an->sta, i, false);
}
ath_txq_unlock_complete(sc, tid->txq);
@@ -1914,13 +1893,7 @@ bool ath_drain_all_txq(struct ath_softc *sc)
if (!ATH_TXQ_SETUP(sc, i))
continue;
- /*
- * The caller will resume queues with ieee80211_wake_queues.
- * Mark the queue as not stopped to prevent ath_tx_complete
- * from waking the queue too early.
- */
txq = &sc->tx.txq[i];
- txq->stopped = false;
ath_draintxq(sc, txq);
}
@@ -2319,16 +2292,14 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
struct ath_atx_tid *tid = NULL;
+ struct ath_node *an = NULL;
struct ath_buf *bf;
- bool queue, skip_uapsd = false, ps_resp;
+ bool ps_resp;
int q, ret;
if (vif)
avp = (void *)vif->drv_priv;
- if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
- txctl->force_channel = true;
-
ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE);
ret = ath_tx_prepare(hw, skb, txctl);
@@ -2343,63 +2314,18 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
q = skb_get_queue_mapping(skb);
- ath_txq_lock(sc, txq);
- if (txq == sc->tx.txq_map[q]) {
- fi->txq = q;
- if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
- !txq->stopped) {
- if (ath9k_is_chanctx_enabled())
- ieee80211_stop_queue(sc->hw, info->hw_queue);
- else
- ieee80211_stop_queue(sc->hw, q);
- txq->stopped = true;
- }
- }
-
- queue = ieee80211_is_data_present(hdr->frame_control);
-
- /* If chanctx, queue all null frames while NOA could be there */
- if (ath9k_is_chanctx_enabled() &&
- ieee80211_is_nullfunc(hdr->frame_control) &&
- !txctl->force_channel)
- queue = true;
-
- /* Force queueing of all frames that belong to a virtual interface on
- * a different channel context, to ensure that they are sent on the
- * correct channel.
- */
- if (((avp && avp->chanctx != sc->cur_chan) ||
- sc->cur_chan->stopped) && !txctl->force_channel) {
- if (!txctl->an)
- txctl->an = &avp->mcast_node;
- queue = true;
- skip_uapsd = true;
- }
-
- if (txctl->an && queue)
- tid = ath_get_skb_tid(sc, txctl->an, skb);
-
- if (!skip_uapsd && ps_resp) {
- ath_txq_unlock(sc, txq);
+ if (ps_resp)
txq = sc->tx.uapsdq;
- ath_txq_lock(sc, txq);
- } else if (txctl->an && queue) {
- WARN_ON(tid->txq != txctl->txq);
- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
- tid->clear_ps_filter = true;
-
- /*
- * Add this frame to software queue for scheduling later
- * for aggregation.
- */
- TX_STAT_INC(txq->axq_qnum, a_queued_sw);
- __skb_queue_tail(&tid->buf_q, skb);
- if (!txctl->an->sleeping)
- ath_tx_queue_tid(sc, txq, tid);
+ if (txctl->sta) {
+ an = (struct ath_node *) sta->drv_priv;
+ tid = ath_get_skb_tid(sc, an, skb);
+ }
- ath_txq_schedule(sc, txq);
- goto out;
+ ath_txq_lock(sc, txq);
+ if (txq == sc->tx.txq_map[q]) {
+ fi->txq = q;
+ ++txq->pending_frames;
}
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
@@ -2892,9 +2818,8 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
struct ath_atx_tid *tid;
int tidno, acno;
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS;
- tidno++, tid++) {
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+ tid = ath_node_to_tid(an, tidno);
tid->an = an;
tid->tidno = tidno;
tid->seq_start = tid->seq_next = 0;
@@ -2902,11 +2827,14 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->baw_head = tid->baw_tail = 0;
tid->active = false;
tid->clear_ps_filter = true;
- __skb_queue_head_init(&tid->buf_q);
+ tid->has_queued = false;
__skb_queue_head_init(&tid->retry_q);
INIT_LIST_HEAD(&tid->list);
acno = TID_TO_WME_AC(tidno);
tid->txq = sc->tx.txq_map[acno];
+
+ if (!an->sta)
+ break; /* just one multicast ath_atx_tid */
}
}
@@ -2916,9 +2844,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
struct ath_txq *txq;
int tidno;
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+ tid = ath_node_to_tid(an, tidno);
txq = tid->txq;
ath_txq_lock(sc, txq);
@@ -2930,6 +2857,9 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
tid->active = false;
ath_txq_unlock(sc, txq);
+
+ if (!an->sta)
+ break; /* just one multicast ath_atx_tid */
}
}
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index 338d72337604..89f4b0513946 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -90,3 +90,10 @@ void ath_printk(const char *level, const struct ath_common* common,
va_end(args);
}
EXPORT_SYMBOL(ath_printk);
+
+const char *ath_bus_type_strings[] = {
+ [ATH_PCI] = "pci",
+ [ATH_AHB] = "ahb",
+ [ATH_USB] = "usb",
+};
+EXPORT_SYMBOL(ath_bus_type_strings);
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index f8506037736f..43afa83a9f0c 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -449,7 +449,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
}
}
-static u16 ath_regd_find_country_by_name(char *alpha2)
+u16 ath_regd_find_country_by_name(char *alpha2)
{
unsigned int i;
@@ -460,6 +460,7 @@ static u16 ath_regd_find_country_by_name(char *alpha2)
return -1;
}
+EXPORT_SYMBOL(ath_regd_find_country_by_name);
static int __ath_reg_dyn_country(struct wiphy *wiphy,
struct ath_regulatory *reg,
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 565d3075f06e..5d80be213fac 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -251,6 +251,7 @@ enum CountryCode {
bool ath_is_world_regd(struct ath_regulatory *reg);
bool ath_is_49ghz_allowed(u16 redomain);
+u16 ath_regd_find_country_by_name(char *alpha2);
int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
void (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request));
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index d117240d9a73..6aa3ff4240a9 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -354,14 +354,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n",
__func__, wdev, wdev->iftype);
- mutex_lock(&wil->p2p_wdev_mutex);
- if (wil->scan_request) {
- wil_err(wil, "Already scanning\n");
- mutex_unlock(&wil->p2p_wdev_mutex);
- return -EAGAIN;
- }
- mutex_unlock(&wil->p2p_wdev_mutex);
-
/* check we are client side */
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -378,12 +370,24 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
return -EBUSY;
}
+ mutex_lock(&wil->mutex);
+
+ mutex_lock(&wil->p2p_wdev_mutex);
+ if (wil->scan_request || wil->p2p.discovery_started) {
+ wil_err(wil, "Already scanning\n");
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ rc = -EAGAIN;
+ goto out;
+ }
+ mutex_unlock(&wil->p2p_wdev_mutex);
+
/* social scan on P2P_DEVICE is handled as p2p search */
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
wil_p2p_is_social_scan(request)) {
if (!wil->p2p.p2p_dev_started) {
wil_err(wil, "P2P search requested on stopped P2P device\n");
- return -EIO;
+ rc = -EIO;
+ goto out;
}
wil->scan_request = request;
wil->radio_wdev = wdev;
@@ -392,7 +396,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
wil->radio_wdev = wil_to_wdev(wil);
wil->scan_request = NULL;
}
- return rc;
+ goto out;
}
(void)wil_p2p_stop_discovery(wil);
@@ -415,7 +419,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
if (rc) {
wil_err(wil, "set SSID for scan request failed: %d\n", rc);
- return rc;
+ goto out;
}
wil->scan_request = request;
@@ -448,7 +452,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
if (rc)
- goto out;
+ goto out_restore;
if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
cmd.cmd.discovery_mode = 1;
@@ -459,16 +463,45 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
-out:
+out_restore:
if (rc) {
del_timer_sync(&wil->scan_timer);
wil->radio_wdev = wil_to_wdev(wil);
wil->scan_request = NULL;
}
-
+out:
+ mutex_unlock(&wil->mutex);
return rc;
}
+static void wil_cfg80211_abort_scan(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
+
+ mutex_lock(&wil->mutex);
+ mutex_lock(&wil->p2p_wdev_mutex);
+
+ if (!wil->scan_request)
+ goto out;
+
+ if (wdev != wil->scan_request->wdev) {
+ wil_dbg_misc(wil, "abort scan was called on the wrong iface\n");
+ goto out;
+ }
+
+ if (wil->radio_wdev == wil->p2p_wdev)
+ wil_p2p_stop_radio_operations(wil);
+ else
+ wil_abort_scan(wil, true);
+
+out:
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ mutex_unlock(&wil->mutex);
+}
+
static void wil_print_crypto(struct wil6210_priv *wil,
struct cfg80211_crypto_settings *c)
{
@@ -674,6 +707,26 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
return rc;
}
+static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ int rc;
+
+ /* these parameters are explicitly not supported */
+ if (changed & (WIPHY_PARAM_RETRY_LONG |
+ WIPHY_PARAM_FRAG_THRESHOLD |
+ WIPHY_PARAM_RTS_THRESHOLD))
+ return -ENOTSUPP;
+
+ if (changed & WIPHY_PARAM_RETRY_SHORT) {
+ rc = wmi_set_mgmt_retry(wil, wiphy->retry_short);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params,
u64 *cookie)
@@ -940,16 +993,8 @@ static int wil_remain_on_channel(struct wiphy *wiphy,
wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n",
__func__, chan->center_freq, duration, wdev->iftype);
- rc = wil_p2p_listen(wil, duration, chan, cookie);
- if (rc)
- return rc;
-
- wil->radio_wdev = wdev;
-
- cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
- GFP_KERNEL);
-
- return 0;
+ rc = wil_p2p_listen(wil, wdev, duration, chan, cookie);
+ return rc;
}
static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
@@ -1419,17 +1464,49 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
wil_dbg_misc(wil, "%s: entered\n", __func__);
mutex_lock(&wil->mutex);
+ mutex_lock(&wil->p2p_wdev_mutex);
wil_p2p_stop_radio_operations(wil);
p2p->p2p_dev_started = 0;
+ mutex_unlock(&wil->p2p_wdev_mutex);
mutex_unlock(&wil->mutex);
}
+static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ enum wmi_ps_profile_type ps_profile;
+ int rc;
+
+ if (!test_bit(WMI_FW_CAPABILITY_PS_CONFIG, wil->fw_capabilities)) {
+ wil_err(wil, "set_power_mgmt not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ wil_dbg_misc(wil, "enabled=%d, timeout=%d\n",
+ enabled, timeout);
+
+ if (enabled)
+ ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
+ else
+ ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED;
+
+ rc = wmi_ps_dev_profile_cfg(wil, ps_profile);
+ if (rc)
+ wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc);
+
+ return rc;
+}
+
static struct cfg80211_ops wil_cfg80211_ops = {
.add_virtual_intf = wil_cfg80211_add_iface,
.del_virtual_intf = wil_cfg80211_del_iface,
.scan = wil_cfg80211_scan,
+ .abort_scan = wil_cfg80211_abort_scan,
.connect = wil_cfg80211_connect,
.disconnect = wil_cfg80211_disconnect,
+ .set_wiphy_params = wil_cfg80211_set_wiphy_params,
.change_virtual_intf = wil_cfg80211_change_iface,
.get_station = wil_cfg80211_get_station,
.dump_station = wil_cfg80211_dump_station,
@@ -1450,6 +1527,7 @@ static struct cfg80211_ops wil_cfg80211_ops = {
/* P2P device */
.start_p2p_device = wil_cfg80211_start_p2p_device,
.stop_p2p_device = wil_cfg80211_stop_p2p_device,
+ .set_power_mgmt = wil_cfg80211_set_power_mgmt,
};
static void wil_wiphy_init(struct wiphy *wiphy)
@@ -1466,7 +1544,8 @@ static void wil_wiphy_init(struct wiphy *wiphy)
BIT(NL80211_IFTYPE_MONITOR);
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
- WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
+ WIPHY_FLAG_PS_ON_BY_DEFAULT;
dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
__func__, wiphy->flags);
wiphy->probe_resp_offload =
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index e7130b54d1d8..e2e021bcaa03 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -24,6 +24,7 @@
#include "boot_loader.h"
#define WAIT_FOR_HALP_VOTE_MS 100
+#define WAIT_FOR_SCAN_ABORT_MS 1000
bool debug_fw; /* = false; */
module_param(debug_fw, bool, S_IRUGO);
@@ -213,7 +214,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
memset(&sta->stats, 0, sizeof(sta->stats));
}
-static bool wil_ap_is_connected(struct wil6210_priv *wil)
+static bool wil_is_connected(struct wil6210_priv *wil)
{
int i;
@@ -267,7 +268,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
wil_bcast_fini(wil);
- netif_tx_stop_all_queues(ndev);
+ wil_update_net_queues_bh(wil, NULL, true);
netif_carrier_off(ndev);
if (test_bit(wil_status_fwconnected, wil->status)) {
@@ -283,8 +284,12 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
- if (!wil_ap_is_connected(wil))
+ if (!wil_is_connected(wil)) {
+ wil_update_net_queues_bh(wil, NULL, true);
clear_bit(wil_status_fwconnected, wil->status);
+ } else {
+ wil_update_net_queues_bh(wil, NULL, false);
+ }
break;
default:
break;
@@ -384,18 +389,19 @@ static void wil_fw_error_worker(struct work_struct *work)
wil->last_fw_recovery = jiffies;
+ wil_info(wil, "fw error recovery requested (try %d)...\n",
+ wil->recovery_count);
+ if (!no_fw_recovery)
+ wil->recovery_state = fw_recovery_running;
+ if (wil_wait_for_recovery(wil) != 0)
+ return;
+
mutex_lock(&wil->mutex);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_MONITOR:
- wil_info(wil, "fw error recovery requested (try %d)...\n",
- wil->recovery_count);
- if (!no_fw_recovery)
- wil->recovery_state = fw_recovery_running;
- if (0 != wil_wait_for_recovery(wil))
- break;
-
+ /* silent recovery, upper layers will see disconnect */
__wil_down(wil);
__wil_up(wil);
break;
@@ -512,10 +518,13 @@ int wil_priv_init(struct wil6210_priv *wil)
INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
+ INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
INIT_LIST_HEAD(&wil->pending_wmi_ev);
INIT_LIST_HEAD(&wil->probe_client_pending);
spin_lock_init(&wil->wmi_ev_lock);
+ spin_lock_init(&wil->net_queue_lock);
+ wil->net_queue_stopped = 1;
init_waitqueue_head(&wil->wq);
wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
@@ -571,6 +580,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
cancel_work_sync(&wil->disconnect_worker);
cancel_work_sync(&wil->fw_error_worker);
cancel_work_sync(&wil->p2p.discovery_expired_work);
+ cancel_work_sync(&wil->p2p.delayed_listen_work);
mutex_lock(&wil->mutex);
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
mutex_unlock(&wil->mutex);
@@ -685,6 +695,19 @@ static int wil_target_reset(struct wil6210_priv *wil)
return 0;
}
+static void wil_collect_fw_info(struct wil6210_priv *wil)
+{
+ struct wiphy *wiphy = wil_to_wiphy(wil);
+ u8 retry_short;
+ int rc;
+
+ rc = wmi_get_mgmt_retry(wil, &retry_short);
+ if (!rc) {
+ wiphy->retry_short = retry_short;
+ wil_dbg_misc(wil, "FW retry_short: %d\n", retry_short);
+ }
+}
+
void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
{
le32_to_cpus(&r->base);
@@ -801,6 +824,34 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
return 0;
}
+void wil_abort_scan(struct wil6210_priv *wil, bool sync)
+{
+ int rc;
+ struct cfg80211_scan_info info = {
+ .aborted = true,
+ };
+
+ lockdep_assert_held(&wil->p2p_wdev_mutex);
+
+ if (!wil->scan_request)
+ return;
+
+ wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request);
+ del_timer_sync(&wil->scan_timer);
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ rc = wmi_abort_scan(wil);
+ if (!rc && sync)
+ wait_event_interruptible_timeout(wil->wq, !wil->scan_request,
+ msecs_to_jiffies(
+ WAIT_FOR_SCAN_ABORT_MS));
+
+ mutex_lock(&wil->p2p_wdev_mutex);
+ if (wil->scan_request) {
+ cfg80211_scan_done(wil->scan_request, &info);
+ wil->scan_request = NULL;
+ }
+}
+
/*
* We reset all the structures, and we reset the UMAC.
* After calling this routine, you're expected to reload
@@ -853,17 +904,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
mutex_unlock(&wil->wmi_mutex);
mutex_lock(&wil->p2p_wdev_mutex);
- if (wil->scan_request) {
- struct cfg80211_scan_info info = {
- .aborted = true,
- };
-
- wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
- wil->scan_request);
- del_timer_sync(&wil->scan_timer);
- cfg80211_scan_done(wil->scan_request, &info);
- wil->scan_request = NULL;
- }
+ wil_abort_scan(wil, false);
mutex_unlock(&wil->p2p_wdev_mutex);
wil_mask_irq(wil);
@@ -940,6 +981,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
return rc;
}
+ wil_collect_fw_info(wil);
+
if (wil->platform_ops.notify) {
rc = wil->platform_ops.notify(wil->platform_handle,
WIL_PLATFORM_EVT_FW_RDY);
@@ -1056,20 +1099,9 @@ int __wil_down(struct wil6210_priv *wil)
}
wil_enable_irq(wil);
- wil_p2p_stop_radio_operations(wil);
-
mutex_lock(&wil->p2p_wdev_mutex);
- if (wil->scan_request) {
- struct cfg80211_scan_info info = {
- .aborted = true,
- };
-
- wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
- wil->scan_request);
- del_timer_sync(&wil->scan_timer);
- cfg80211_scan_done(wil->scan_request, &info);
- wil->scan_request = NULL;
- }
+ wil_p2p_stop_radio_operations(wil);
+ wil_abort_scan(wil, false);
mutex_unlock(&wil->p2p_wdev_mutex);
wil_reset(wil, false);
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 61de5e9f8ef0..6676001dcbca 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -41,21 +41,6 @@ static int wil_stop(struct net_device *ndev)
return wil_down(wil);
}
-static int wil_change_mtu(struct net_device *ndev, int new_mtu)
-{
- struct wil6210_priv *wil = ndev_to_wil(ndev);
-
- if (new_mtu < 68 || new_mtu > mtu_max) {
- wil_err(wil, "invalid MTU %d\n", new_mtu);
- return -EINVAL;
- }
-
- wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu);
- ndev->mtu = new_mtu;
-
- return 0;
-}
-
static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
@@ -69,7 +54,6 @@ static const struct net_device_ops wil_netdev_ops = {
.ndo_start_xmit = wil_start_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = wil_change_mtu,
.ndo_do_ioctl = wil_do_ioctl,
};
@@ -126,6 +110,7 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
static void wil_dev_setup(struct net_device *dev)
{
ether_setup(dev);
+ dev->max_mtu = mtu_max;
dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
}
@@ -229,7 +214,7 @@ int wil_if_add(struct wil6210_priv *wil)
netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx,
WIL6210_NAPI_BUDGET);
- netif_tx_stop_all_queues(ndev);
+ wil_update_net_queues_bh(wil, NULL, true);
rc = register_netdev(ndev);
if (rc < 0) {
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c
index 4087785d3090..fbae99525e01 100644
--- a/drivers/net/wireless/ath/wil6210/p2p.c
+++ b/drivers/net/wireless/ath/wil6210/p2p.c
@@ -22,6 +22,43 @@
#define P2P_SEARCH_DURATION_MS 500
#define P2P_DEFAULT_BI 100
+static int wil_p2p_start_listen(struct wil6210_priv *wil)
+{
+ struct wil_p2p_info *p2p = &wil->p2p;
+ u8 channel = p2p->listen_chan.hw_value;
+ int rc;
+
+ lockdep_assert_held(&wil->mutex);
+
+ rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI);
+ if (rc) {
+ wil_err(wil, "wmi_p2p_cfg failed\n");
+ goto out;
+ }
+
+ rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
+ if (rc) {
+ wil_err(wil, "wmi_set_ssid failed\n");
+ goto out_stop;
+ }
+
+ rc = wmi_start_listen(wil);
+ if (rc) {
+ wil_err(wil, "wmi_start_listen failed\n");
+ goto out_stop;
+ }
+
+ INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired);
+ mod_timer(&p2p->discovery_timer,
+ jiffies + msecs_to_jiffies(p2p->listen_duration));
+out_stop:
+ if (rc)
+ wmi_stop_discovery(wil);
+
+out:
+ return rc;
+}
+
bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request)
{
return (request->n_channels == 1) &&
@@ -46,7 +83,7 @@ int wil_p2p_search(struct wil6210_priv *wil,
wil_dbg_misc(wil, "%s: channel %d\n",
__func__, P2P_DMG_SOCIAL_CHANNEL);
- mutex_lock(&wil->mutex);
+ lockdep_assert_held(&wil->mutex);
if (p2p->discovery_started) {
wil_err(wil, "%s: search failed. discovery already ongoing\n",
@@ -103,22 +140,19 @@ out_stop:
wmi_stop_discovery(wil);
out:
- mutex_unlock(&wil->mutex);
return rc;
}
-int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
- struct ieee80211_channel *chan, u64 *cookie)
+int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
+ unsigned int duration, struct ieee80211_channel *chan,
+ u64 *cookie)
{
struct wil_p2p_info *p2p = &wil->p2p;
- u8 channel = P2P_DMG_SOCIAL_CHANNEL;
int rc;
if (!chan)
return -EINVAL;
- channel = chan->hw_value;
-
wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration);
mutex_lock(&wil->mutex);
@@ -129,35 +163,30 @@ int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
goto out;
}
- rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI);
- if (rc) {
- wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__);
- goto out;
- }
-
- rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
- if (rc) {
- wil_err(wil, "%s: wmi_set_ssid failed\n", __func__);
- goto out_stop;
- }
+ memcpy(&p2p->listen_chan, chan, sizeof(*chan));
+ *cookie = ++p2p->cookie;
+ p2p->listen_duration = duration;
- rc = wmi_start_listen(wil);
- if (rc) {
- wil_err(wil, "%s: wmi_start_listen failed\n", __func__);
- goto out_stop;
+ mutex_lock(&wil->p2p_wdev_mutex);
+ if (wil->scan_request) {
+ wil_dbg_misc(wil, "Delaying p2p listen until scan done\n");
+ p2p->pending_listen_wdev = wdev;
+ p2p->discovery_started = 1;
+ rc = 0;
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ goto out;
}
+ mutex_unlock(&wil->p2p_wdev_mutex);
- memcpy(&p2p->listen_chan, chan, sizeof(*chan));
- *cookie = ++p2p->cookie;
+ rc = wil_p2p_start_listen(wil);
+ if (rc)
+ goto out;
p2p->discovery_started = 1;
- INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired);
- mod_timer(&p2p->discovery_timer,
- jiffies + msecs_to_jiffies(duration));
+ wil->radio_wdev = wdev;
-out_stop:
- if (rc)
- wmi_stop_discovery(wil);
+ cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
+ GFP_KERNEL);
out:
mutex_unlock(&wil->mutex);
@@ -170,9 +199,14 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
u8 started = p2p->discovery_started;
if (p2p->discovery_started) {
- del_timer_sync(&p2p->discovery_timer);
+ if (p2p->pending_listen_wdev) {
+ /* discovery not really started, only pending */
+ p2p->pending_listen_wdev = NULL;
+ } else {
+ del_timer_sync(&p2p->discovery_timer);
+ wmi_stop_discovery(wil);
+ }
p2p->discovery_started = 0;
- wmi_stop_discovery(wil);
}
return started;
@@ -257,13 +291,59 @@ void wil_p2p_search_expired(struct work_struct *work)
};
mutex_lock(&wil->p2p_wdev_mutex);
- cfg80211_scan_done(wil->scan_request, &info);
- wil->scan_request = NULL;
- wil->radio_wdev = wil->wdev;
+ if (wil->scan_request) {
+ cfg80211_scan_done(wil->scan_request, &info);
+ wil->scan_request = NULL;
+ wil->radio_wdev = wil->wdev;
+ }
mutex_unlock(&wil->p2p_wdev_mutex);
}
}
+void wil_p2p_delayed_listen_work(struct work_struct *work)
+{
+ struct wil_p2p_info *p2p = container_of(work,
+ struct wil_p2p_info, delayed_listen_work);
+ struct wil6210_priv *wil = container_of(p2p,
+ struct wil6210_priv, p2p);
+ int rc;
+
+ mutex_lock(&wil->mutex);
+
+ wil_dbg_misc(wil, "Checking delayed p2p listen\n");
+ if (!p2p->discovery_started || !p2p->pending_listen_wdev)
+ goto out;
+
+ mutex_lock(&wil->p2p_wdev_mutex);
+ if (wil->scan_request) {
+ /* another scan started, wait again... */
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ goto out;
+ }
+ mutex_unlock(&wil->p2p_wdev_mutex);
+
+ rc = wil_p2p_start_listen(wil);
+
+ mutex_lock(&wil->p2p_wdev_mutex);
+ if (rc) {
+ cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev,
+ p2p->cookie,
+ &p2p->listen_chan,
+ GFP_KERNEL);
+ wil->radio_wdev = wil->wdev;
+ } else {
+ cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie,
+ &p2p->listen_chan,
+ p2p->listen_duration, GFP_KERNEL);
+ wil->radio_wdev = p2p->pending_listen_wdev;
+ }
+ p2p->pending_listen_wdev = NULL;
+ mutex_unlock(&wil->p2p_wdev_mutex);
+
+out:
+ mutex_unlock(&wil->mutex);
+}
+
void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
{
struct wil_p2p_info *p2p = &wil->p2p;
@@ -272,8 +352,7 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
};
lockdep_assert_held(&wil->mutex);
-
- mutex_lock(&wil->p2p_wdev_mutex);
+ lockdep_assert_held(&wil->p2p_wdev_mutex);
if (wil->radio_wdev != wil->p2p_wdev)
goto out;
@@ -281,10 +360,8 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
if (!p2p->discovery_started) {
/* Regular scan on the p2p device */
if (wil->scan_request &&
- wil->scan_request->wdev == wil->p2p_wdev) {
- cfg80211_scan_done(wil->scan_request, &info);
- wil->scan_request = NULL;
- }
+ wil->scan_request->wdev == wil->p2p_wdev)
+ wil_abort_scan(wil, true);
goto out;
}
@@ -307,5 +384,4 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
out:
wil->radio_wdev = wil->wdev;
- mutex_unlock(&wil->p2p_wdev_mutex);
}
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index 5ca0307a3274..b9faae0278c9 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
struct pmc_ctx *pmc = &wil->pmc;
struct device *dev = wil_to_dev(wil);
struct wmi_pmc_cmd pmc_cmd = {0};
+ int last_cmd_err = -ENOMEM;
mutex_lock(&pmc->lock);
@@ -62,6 +63,29 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__);
goto no_release_err;
}
+ if ((num_descriptors <= 0) || (descriptor_size <= 0)) {
+ wil_err(wil,
+ "Invalid params num_descriptors(%d), descriptor_size(%d)\n",
+ num_descriptors, descriptor_size);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
+
+ if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) {
+ wil_err(wil,
+ "num_descriptors(%d) exceeds max ring size %d\n",
+ num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
+
+ if (num_descriptors > INT_MAX / descriptor_size) {
+ wil_err(wil,
+ "Overflow in num_descriptors(%d)*descriptor_size(%d)\n",
+ num_descriptors, descriptor_size);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
pmc->num_descriptors = num_descriptors;
pmc->descriptor_size = descriptor_size;
@@ -189,7 +213,7 @@ release_pmc_skb_list:
pmc->descriptors = NULL;
no_release_err:
- pmc->last_cmd_status = -ENOMEM;
+ pmc->last_cmd_status = last_cmd_err;
mutex_unlock(&pmc->lock);
}
@@ -295,7 +319,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
size_t retval = 0;
unsigned long long idx;
loff_t offset;
- size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+ size_t pmc_size;
mutex_lock(&pmc->lock);
@@ -306,6 +330,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
return -EPERM;
}
+ pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+
wil_dbg_misc(wil,
"%s: size %u, pos %lld\n",
__func__, (unsigned)count, *f_pos);
@@ -345,7 +371,18 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
loff_t newpos;
struct wil6210_priv *wil = filp->private_data;
struct pmc_ctx *pmc = &wil->pmc;
- size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+ size_t pmc_size;
+
+ mutex_lock(&pmc->lock);
+
+ if (!wil_is_pmc_allocated(pmc)) {
+ wil_err(wil, "error, pmc is not allocated!\n");
+ pmc->last_cmd_status = -EPERM;
+ mutex_unlock(&pmc->lock);
+ return -EPERM;
+ }
+
+ pmc_size = pmc->descriptor_size * pmc->num_descriptors;
switch (whence) {
case 0: /* SEEK_SET */
@@ -361,15 +398,21 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
break;
default: /* can't happen */
- return -EINVAL;
+ newpos = -EINVAL;
+ goto out;
}
- if (newpos < 0)
- return -EINVAL;
+ if (newpos < 0) {
+ newpos = -EINVAL;
+ goto out;
+ }
if (newpos > pmc_size)
newpos = pmc_size;
filp->f_pos = newpos;
+out:
+ mutex_unlock(&pmc->lock);
+
return newpos;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 4c38520d4dd2..4ac9ba04afed 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -88,6 +88,18 @@ static inline int wil_vring_wmark_high(struct vring *vring)
return vring->size/4;
}
+/* returns true if num avail descriptors is lower than wmark_low */
+static inline int wil_vring_avail_low(struct vring *vring)
+{
+ return wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring);
+}
+
+/* returns true if num avail descriptors is higher than wmark_high */
+static inline int wil_vring_avail_high(struct vring *vring)
+{
+ return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring);
+}
+
/* wil_val_in_range - check if value in [min,max) */
static inline bool wil_val_in_range(int val, int min, int max)
{
@@ -1780,6 +1792,89 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
return rc;
}
+/**
+ * Check status of tx vrings and stop/wake net queues if needed
+ *
+ * This function does one of two checks:
+ * In case check_stop is true, will check if net queues need to be stopped. If
+ * the conditions for stopping are met, netif_tx_stop_all_queues() is called.
+ * In case check_stop is false, will check if net queues need to be waked. If
+ * the conditions for waking are met, netif_tx_wake_all_queues() is called.
+ * vring is the vring which is currently being modified by either adding
+ * descriptors (tx) into it or removing descriptors (tx complete) from it. Can
+ * be null when irrelevant (e.g. connect/disconnect events).
+ *
+ * The implementation is to stop net queues if modified vring has low
+ * descriptor availability. Wake if all vrings are not in low descriptor
+ * availability and modified vring has high descriptor availability.
+ */
+static inline void __wil_update_net_queues(struct wil6210_priv *wil,
+ struct vring *vring,
+ bool check_stop)
+{
+ int i;
+
+ if (vring)
+ wil_dbg_txrx(wil, "vring %d, check_stop=%d, stopped=%d",
+ (int)(vring - wil->vring_tx), check_stop,
+ wil->net_queue_stopped);
+ else
+ wil_dbg_txrx(wil, "check_stop=%d, stopped=%d",
+ check_stop, wil->net_queue_stopped);
+
+ if (check_stop == wil->net_queue_stopped)
+ /* net queues already in desired state */
+ return;
+
+ if (check_stop) {
+ if (!vring || unlikely(wil_vring_avail_low(vring))) {
+ /* not enough room in the vring */
+ netif_tx_stop_all_queues(wil_to_ndev(wil));
+ wil->net_queue_stopped = true;
+ wil_dbg_txrx(wil, "netif_tx_stop called\n");
+ }
+ return;
+ }
+
+ /* check wake */
+ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
+ struct vring *cur_vring = &wil->vring_tx[i];
+ struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+
+ if (!cur_vring->va || !txdata->enabled || cur_vring == vring)
+ continue;
+
+ if (wil_vring_avail_low(cur_vring)) {
+ wil_dbg_txrx(wil, "vring %d full, can't wake\n",
+ (int)(cur_vring - wil->vring_tx));
+ return;
+ }
+ }
+
+ if (!vring || wil_vring_avail_high(vring)) {
+ /* enough room in the vring */
+ wil_dbg_txrx(wil, "calling netif_tx_wake\n");
+ netif_tx_wake_all_queues(wil_to_ndev(wil));
+ wil->net_queue_stopped = false;
+ }
+}
+
+void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring,
+ bool check_stop)
+{
+ spin_lock(&wil->net_queue_lock);
+ __wil_update_net_queues(wil, vring, check_stop);
+ spin_unlock(&wil->net_queue_lock);
+}
+
+void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring,
+ bool check_stop)
+{
+ spin_lock_bh(&wil->net_queue_lock);
+ __wil_update_net_queues(wil, vring, check_stop);
+ spin_unlock_bh(&wil->net_queue_lock);
+}
+
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
@@ -1822,14 +1917,10 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* set up vring entry */
rc = wil_tx_vring(wil, vring, skb);
- /* do we still have enough room in the vring? */
- if (unlikely(wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))) {
- netif_tx_stop_all_queues(wil_to_ndev(wil));
- wil_dbg_txrx(wil, "netif_tx_stop : ring full\n");
- }
-
switch (rc) {
case 0:
+ /* shall we stop net queues? */
+ wil_update_net_queues_bh(wil, vring, true);
/* statistics will be updated on the tx_complete */
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -1978,10 +2069,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
txdata->last_idle = get_cycles();
}
- if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring)) {
- wil_dbg_txrx(wil, "netif_tx_wake : ring not full\n");
- netif_tx_wake_all_queues(wil_to_ndev(wil));
- }
+ /* shall we wake net queues? */
+ if (done)
+ wil_update_net_queues(wil, vring, false);
return done;
}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index a949cd62bc4e..237e1666df2d 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -276,10 +276,11 @@ struct fw_map {
u32 to; /* linker address - to, exclusive */
u32 host; /* PCI/Host address - BAR0 + 0x880000 */
const char *name; /* for debugfs */
+ bool fw; /* true if FW mapping, false if UCODE mapping */
};
/* array size should be in sync with actual definition in the wmi.c */
-extern const struct fw_map fw_mapping[8];
+extern const struct fw_map fw_mapping[10];
/**
* mk_cidxtid - construct @cidxtid field
@@ -461,8 +462,11 @@ struct wil_p2p_info {
u8 discovery_started;
u8 p2p_dev_started;
u64 cookie;
+ struct wireless_dev *pending_listen_wdev;
+ unsigned int listen_duration;
struct timer_list discovery_timer; /* listen/search duration */
struct work_struct discovery_expired_work; /* listen/search expire */
+ struct work_struct delayed_listen_work; /* listen after scan done */
};
enum wil_sta_status {
@@ -624,6 +628,8 @@ struct wil6210_priv {
* - consumed in thread by wmi_event_worker
*/
spinlock_t wmi_ev_lock;
+ spinlock_t net_queue_lock; /* guarding stop/wake netif queue */
+ int net_queue_stopped; /* netif_tx_stop_all_queues invoked */
struct napi_struct napi_rx;
struct napi_struct napi_tx;
/* keep alive */
@@ -817,6 +823,10 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason);
int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason);
int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
+int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
+ enum wmi_ps_profile_type ps_profile);
+int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short);
+int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short);
int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl);
@@ -837,13 +847,15 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request);
void wil_p2p_discovery_timer_fn(ulong x);
int wil_p2p_search(struct wil6210_priv *wil,
struct cfg80211_scan_request *request);
-int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
- struct ieee80211_channel *chan, u64 *cookie);
+int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
+ unsigned int duration, struct ieee80211_channel *chan,
+ u64 *cookie);
u8 wil_p2p_stop_discovery(struct wil6210_priv *wil);
int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie);
void wil_p2p_listen_expired(struct work_struct *work);
void wil_p2p_search_expired(struct work_struct *work);
void wil_p2p_stop_radio_operations(struct wil6210_priv *wil);
+void wil_p2p_delayed_listen_work(struct work_struct *work);
/* WMI for P2P */
int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi);
@@ -869,6 +881,9 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
u8 chan, u8 hidden_ssid, u8 is_go);
int wmi_pcp_stop(struct wil6210_priv *wil);
int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
+int wmi_abort_scan(struct wil6210_priv *wil);
+void wil_abort_scan(struct wil6210_priv *wil, bool sync);
+
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
u16 reason_code, bool from_event);
void wil_probe_client_flush(struct wil6210_priv *wil);
@@ -886,6 +901,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size);
int wil_bcast_init(struct wil6210_priv *wil);
void wil_bcast_fini(struct wil6210_priv *wil);
+void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring,
+ bool should_stop);
+void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring,
+ bool check_stop);
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev);
int wil_tx_complete(struct wil6210_priv *wil, int ringid);
void wil6210_unmask_irq_tx(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
index b57d280946e0..d051eea47a54 100644
--- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
@@ -36,6 +36,9 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil,
for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) {
map = &fw_mapping[i];
+ if (!map->fw)
+ continue;
+
if (map->host < host_min)
host_min = map->host;
@@ -73,6 +76,9 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
map = &fw_mapping[i];
+ if (!map->fw)
+ continue;
+
data = (void * __force)wil->csr + HOSTADDR(map->host);
len = map->to - map->from;
offset = map->host - host_min;
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index fae4f1285d08..7585003bef67 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -84,19 +84,29 @@ MODULE_PARM_DESC(led_id,
* array size should be in sync with the declaration in the wil6210.h
*/
const struct fw_map fw_mapping[] = {
- {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */
- {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */
- {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
- {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
- {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
- {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
- {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf 512b */
- {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
- /*
- * 920000..930000 ucode code RAM
- * 930000..932000 ucode data RAM
- * 932000..949000 back-door debug data
+ /* FW code RAM 256k */
+ {0x000000, 0x040000, 0x8c0000, "fw_code", true},
+ /* FW data RAM 32k */
+ {0x800000, 0x808000, 0x900000, "fw_data", true},
+ /* periph data 128k */
+ {0x840000, 0x860000, 0x908000, "fw_peri", true},
+ /* various RGF 40k */
+ {0x880000, 0x88a000, 0x880000, "rgf", true},
+ /* AGC table 4k */
+ {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
+ /* Pcie_ext_rgf 4k */
+ {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
+ /* mac_ext_rgf 512b */
+ {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
+ /* upper area 548k */
+ {0x8c0000, 0x949000, 0x8c0000, "upper", true},
+ /* UCODE areas - accessible by debugfs blobs but not by
+ * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
*/
+ /* ucode code RAM 128k */
+ {0x000000, 0x020000, 0x920000, "uc_code", false},
+ /* ucode data RAM 16k */
+ {0x800000, 0x804000, 0x940000, "uc_data", false},
};
struct blink_on_off_time led_blink_time[] = {
@@ -108,7 +118,7 @@ struct blink_on_off_time led_blink_time[] = {
u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
/**
- * return AHB address for given firmware/ucode internal (linker) address
+ * return AHB address for given firmware internal (linker) address
* @x - internal address
* If address have no valid AHB mapping, return 0
*/
@@ -117,7 +127,8 @@ static u32 wmi_addr_remap(u32 x)
uint i;
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
- if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))
+ if (fw_mapping[i].fw &&
+ ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)))
return x + fw_mapping[i].host - fw_mapping[i].from;
}
@@ -427,18 +438,24 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
struct wmi_scan_complete_event *data = d;
+ int status = le32_to_cpu(data->status);
struct cfg80211_scan_info info = {
- .aborted = (data->status != WMI_SCAN_SUCCESS),
+ .aborted = ((status != WMI_SCAN_SUCCESS) &&
+ (status != WMI_SCAN_ABORT_REJECTED)),
};
- wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+ wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
wil->scan_request, info.aborted);
-
del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, &info);
wil->radio_wdev = wil->wdev;
wil->scan_request = NULL;
+ wake_up_interruptible(&wil->wq);
+ if (wil->p2p.pending_listen_wdev) {
+ wil_dbg_misc(wil, "Scheduling delayed listen\n");
+ schedule_work(&wil->p2p.delayed_listen_work);
+ }
} else {
wil_err(wil, "SCAN_COMPLETE while not scanning\n");
}
@@ -548,7 +565,6 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
if (rc) {
- netif_tx_stop_all_queues(ndev);
netif_carrier_off(ndev);
wil_err(wil,
"%s: cfg80211_connect_result with failure\n",
@@ -588,7 +604,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
wil->sta[evt->cid].status = wil_sta_connected;
set_bit(wil_status_fwconnected, wil->status);
- netif_tx_wake_all_queues(ndev);
+ wil_update_net_queues_bh(wil, NULL, false);
out:
if (rc)
@@ -1564,6 +1580,112 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
return rc;
}
+int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
+ enum wmi_ps_profile_type ps_profile)
+{
+ int rc;
+ struct wmi_ps_dev_profile_cfg_cmd cmd = {
+ .ps_profile = ps_profile,
+ };
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_ps_dev_profile_cfg_event evt;
+ } __packed reply;
+ u32 status;
+
+ wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
+
+ reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
+
+ rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
+ WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
+ 100);
+ if (rc)
+ return rc;
+
+ status = le32_to_cpu(reply.evt.status);
+
+ if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
+ wil_err(wil, "ps dev profile cfg failed with status %d\n",
+ status);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
+{
+ int rc;
+ struct wmi_set_mgmt_retry_limit_cmd cmd = {
+ .mgmt_retry_limit = retry_short,
+ };
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_set_mgmt_retry_limit_event evt;
+ } __packed reply;
+
+ wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
+
+ if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
+ return -ENOTSUPP;
+
+ reply.evt.status = WMI_FW_STATUS_FAILURE;
+
+ rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
+ WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
+ 100);
+ if (rc)
+ return rc;
+
+ if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
+ wil_err(wil, "set mgmt retry limit failed with status %d\n",
+ reply.evt.status);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
+{
+ int rc;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_get_mgmt_retry_limit_event evt;
+ } __packed reply;
+
+ wil_dbg_wmi(wil, "getting mgmt retry short\n");
+
+ if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
+ return -ENOTSUPP;
+
+ reply.evt.mgmt_retry_limit = 0;
+ rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
+ WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
+ 100);
+ if (rc)
+ return rc;
+
+ if (retry_short)
+ *retry_short = reply.evt.mgmt_retry_limit;
+
+ return 0;
+}
+
+int wmi_abort_scan(struct wil6210_priv *wil)
+{
+ int rc;
+
+ wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
+
+ rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
+ if (rc)
+ wil_err(wil, "Failed to abort scan (%d)\n", rc);
+
+ return rc;
+}
+
void wmi_event_flush(struct wil6210_priv *wil)
{
struct pending_wmi_event *evt, *t;
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index f430e8a80603..d93a4d490d24 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -35,6 +35,7 @@
#define WMI_MAC_LEN (6)
#define WMI_PROX_RANGE_NUM (3)
#define WMI_MAX_LOSS_DMG_BEACONS (20)
+#define MAX_NUM_OF_SECTORS (128)
/* Mailbox interface
* used for commands and events
@@ -51,8 +52,10 @@ enum wmi_mid {
* the host
*/
enum wmi_fw_capability {
- WMI_FW_CAPABILITY_FTM = 0,
- WMI_FW_CAPABILITY_PS_CONFIG = 1,
+ WMI_FW_CAPABILITY_FTM = 0,
+ WMI_FW_CAPABILITY_PS_CONFIG = 1,
+ WMI_FW_CAPABILITY_RF_SECTORS = 2,
+ WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3,
WMI_FW_CAPABILITY_MAX,
};
@@ -66,137 +69,149 @@ struct wmi_cmd_hdr {
/* List of Commands */
enum wmi_command_id {
- WMI_CONNECT_CMDID = 0x01,
- WMI_DISCONNECT_CMDID = 0x03,
- WMI_DISCONNECT_STA_CMDID = 0x04,
- WMI_START_SCAN_CMDID = 0x07,
- WMI_SET_BSS_FILTER_CMDID = 0x09,
- WMI_SET_PROBED_SSID_CMDID = 0x0A,
- WMI_SET_LISTEN_INT_CMDID = 0x0B,
- WMI_BCON_CTRL_CMDID = 0x0F,
- WMI_ADD_CIPHER_KEY_CMDID = 0x16,
- WMI_DELETE_CIPHER_KEY_CMDID = 0x17,
- WMI_PCP_CONF_CMDID = 0x18,
- WMI_SET_APPIE_CMDID = 0x3F,
- WMI_SET_WSC_STATUS_CMDID = 0x41,
- WMI_PXMT_RANGE_CFG_CMDID = 0x42,
- WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43,
- WMI_MEM_READ_CMDID = 0x800,
- WMI_MEM_WR_CMDID = 0x801,
- WMI_ECHO_CMDID = 0x803,
- WMI_DEEP_ECHO_CMDID = 0x804,
- WMI_CONFIG_MAC_CMDID = 0x805,
- WMI_CONFIG_PHY_DEBUG_CMDID = 0x806,
- WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808,
- WMI_PHY_GET_STATISTICS_CMDID = 0x809,
- WMI_FS_TUNE_CMDID = 0x80A,
- WMI_CORR_MEASURE_CMDID = 0x80B,
- WMI_READ_RSSI_CMDID = 0x80C,
- WMI_TEMP_SENSE_CMDID = 0x80E,
- WMI_DC_CALIB_CMDID = 0x80F,
- WMI_SEND_TONE_CMDID = 0x810,
- WMI_IQ_TX_CALIB_CMDID = 0x811,
- WMI_IQ_RX_CALIB_CMDID = 0x812,
- WMI_SET_UCODE_IDLE_CMDID = 0x813,
- WMI_SET_WORK_MODE_CMDID = 0x815,
- WMI_LO_LEAKAGE_CALIB_CMDID = 0x816,
- WMI_MARLON_R_READ_CMDID = 0x818,
- WMI_MARLON_R_WRITE_CMDID = 0x819,
- WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A,
- MAC_IO_STATIC_PARAMS_CMDID = 0x81B,
- MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C,
- WMI_SILENT_RSSI_CALIB_CMDID = 0x81D,
- WMI_RF_RX_TEST_CMDID = 0x81E,
- WMI_CFG_RX_CHAIN_CMDID = 0x820,
- WMI_VRING_CFG_CMDID = 0x821,
- WMI_BCAST_VRING_CFG_CMDID = 0x822,
- WMI_VRING_BA_EN_CMDID = 0x823,
- WMI_VRING_BA_DIS_CMDID = 0x824,
- WMI_RCP_ADDBA_RESP_CMDID = 0x825,
- WMI_RCP_DELBA_CMDID = 0x826,
- WMI_SET_SSID_CMDID = 0x827,
- WMI_GET_SSID_CMDID = 0x828,
- WMI_SET_PCP_CHANNEL_CMDID = 0x829,
- WMI_GET_PCP_CHANNEL_CMDID = 0x82A,
- WMI_SW_TX_REQ_CMDID = 0x82B,
- WMI_READ_MAC_RXQ_CMDID = 0x830,
- WMI_READ_MAC_TXQ_CMDID = 0x831,
- WMI_WRITE_MAC_RXQ_CMDID = 0x832,
- WMI_WRITE_MAC_TXQ_CMDID = 0x833,
- WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834,
- WMI_MLME_PUSH_CMDID = 0x835,
- WMI_BEAMFORMING_MGMT_CMDID = 0x836,
- WMI_BF_TXSS_MGMT_CMDID = 0x837,
- WMI_BF_SM_MGMT_CMDID = 0x838,
- WMI_BF_RXSS_MGMT_CMDID = 0x839,
- WMI_BF_TRIG_CMDID = 0x83A,
- WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842,
- WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843,
- WMI_SET_SECTORS_CMDID = 0x849,
- WMI_MAINTAIN_PAUSE_CMDID = 0x850,
- WMI_MAINTAIN_RESUME_CMDID = 0x851,
- WMI_RS_MGMT_CMDID = 0x852,
- WMI_RF_MGMT_CMDID = 0x853,
- WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854,
- WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855,
- WMI_OTP_READ_CMDID = 0x856,
- WMI_OTP_WRITE_CMDID = 0x857,
- WMI_LED_CFG_CMDID = 0x858,
+ WMI_CONNECT_CMDID = 0x01,
+ WMI_DISCONNECT_CMDID = 0x03,
+ WMI_DISCONNECT_STA_CMDID = 0x04,
+ WMI_START_SCAN_CMDID = 0x07,
+ WMI_SET_BSS_FILTER_CMDID = 0x09,
+ WMI_SET_PROBED_SSID_CMDID = 0x0A,
+ WMI_SET_LISTEN_INT_CMDID = 0x0B,
+ WMI_BCON_CTRL_CMDID = 0x0F,
+ WMI_ADD_CIPHER_KEY_CMDID = 0x16,
+ WMI_DELETE_CIPHER_KEY_CMDID = 0x17,
+ WMI_PCP_CONF_CMDID = 0x18,
+ WMI_SET_APPIE_CMDID = 0x3F,
+ WMI_SET_WSC_STATUS_CMDID = 0x41,
+ WMI_PXMT_RANGE_CFG_CMDID = 0x42,
+ WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43,
+ WMI_MEM_READ_CMDID = 0x800,
+ WMI_MEM_WR_CMDID = 0x801,
+ WMI_ECHO_CMDID = 0x803,
+ WMI_DEEP_ECHO_CMDID = 0x804,
+ WMI_CONFIG_MAC_CMDID = 0x805,
+ WMI_CONFIG_PHY_DEBUG_CMDID = 0x806,
+ WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808,
+ WMI_PHY_GET_STATISTICS_CMDID = 0x809,
+ WMI_FS_TUNE_CMDID = 0x80A,
+ WMI_CORR_MEASURE_CMDID = 0x80B,
+ WMI_READ_RSSI_CMDID = 0x80C,
+ WMI_TEMP_SENSE_CMDID = 0x80E,
+ WMI_DC_CALIB_CMDID = 0x80F,
+ WMI_SEND_TONE_CMDID = 0x810,
+ WMI_IQ_TX_CALIB_CMDID = 0x811,
+ WMI_IQ_RX_CALIB_CMDID = 0x812,
+ WMI_SET_UCODE_IDLE_CMDID = 0x813,
+ WMI_SET_WORK_MODE_CMDID = 0x815,
+ WMI_LO_LEAKAGE_CALIB_CMDID = 0x816,
+ WMI_MARLON_R_READ_CMDID = 0x818,
+ WMI_MARLON_R_WRITE_CMDID = 0x819,
+ WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A,
+ MAC_IO_STATIC_PARAMS_CMDID = 0x81B,
+ MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C,
+ WMI_SILENT_RSSI_CALIB_CMDID = 0x81D,
+ WMI_RF_RX_TEST_CMDID = 0x81E,
+ WMI_CFG_RX_CHAIN_CMDID = 0x820,
+ WMI_VRING_CFG_CMDID = 0x821,
+ WMI_BCAST_VRING_CFG_CMDID = 0x822,
+ WMI_VRING_BA_EN_CMDID = 0x823,
+ WMI_VRING_BA_DIS_CMDID = 0x824,
+ WMI_RCP_ADDBA_RESP_CMDID = 0x825,
+ WMI_RCP_DELBA_CMDID = 0x826,
+ WMI_SET_SSID_CMDID = 0x827,
+ WMI_GET_SSID_CMDID = 0x828,
+ WMI_SET_PCP_CHANNEL_CMDID = 0x829,
+ WMI_GET_PCP_CHANNEL_CMDID = 0x82A,
+ WMI_SW_TX_REQ_CMDID = 0x82B,
+ WMI_READ_MAC_RXQ_CMDID = 0x830,
+ WMI_READ_MAC_TXQ_CMDID = 0x831,
+ WMI_WRITE_MAC_RXQ_CMDID = 0x832,
+ WMI_WRITE_MAC_TXQ_CMDID = 0x833,
+ WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834,
+ WMI_MLME_PUSH_CMDID = 0x835,
+ WMI_BEAMFORMING_MGMT_CMDID = 0x836,
+ WMI_BF_TXSS_MGMT_CMDID = 0x837,
+ WMI_BF_SM_MGMT_CMDID = 0x838,
+ WMI_BF_RXSS_MGMT_CMDID = 0x839,
+ WMI_BF_TRIG_CMDID = 0x83A,
+ WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842,
+ WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843,
+ WMI_SET_SECTORS_CMDID = 0x849,
+ WMI_MAINTAIN_PAUSE_CMDID = 0x850,
+ WMI_MAINTAIN_RESUME_CMDID = 0x851,
+ WMI_RS_MGMT_CMDID = 0x852,
+ WMI_RF_MGMT_CMDID = 0x853,
+ WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854,
+ WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855,
+ WMI_OTP_READ_CMDID = 0x856,
+ WMI_OTP_WRITE_CMDID = 0x857,
+ WMI_LED_CFG_CMDID = 0x858,
/* Performance monitoring commands */
- WMI_BF_CTRL_CMDID = 0x862,
- WMI_NOTIFY_REQ_CMDID = 0x863,
- WMI_GET_STATUS_CMDID = 0x864,
- WMI_GET_RF_STATUS_CMDID = 0x866,
- WMI_GET_BASEBAND_TYPE_CMDID = 0x867,
- WMI_UNIT_TEST_CMDID = 0x900,
- WMI_HICCUP_CMDID = 0x901,
- WMI_FLASH_READ_CMDID = 0x902,
- WMI_FLASH_WRITE_CMDID = 0x903,
+ WMI_BF_CTRL_CMDID = 0x862,
+ WMI_NOTIFY_REQ_CMDID = 0x863,
+ WMI_GET_STATUS_CMDID = 0x864,
+ WMI_GET_RF_STATUS_CMDID = 0x866,
+ WMI_GET_BASEBAND_TYPE_CMDID = 0x867,
+ WMI_UNIT_TEST_CMDID = 0x900,
+ WMI_HICCUP_CMDID = 0x901,
+ WMI_FLASH_READ_CMDID = 0x902,
+ WMI_FLASH_WRITE_CMDID = 0x903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_CMDID = 0x904,
- WMI_TRAFFIC_RESUME_CMDID = 0x905,
+ WMI_TRAFFIC_DEFERRAL_CMDID = 0x904,
+ WMI_TRAFFIC_RESUME_CMDID = 0x905,
/* P2P */
- WMI_P2P_CFG_CMDID = 0x910,
- WMI_PORT_ALLOCATE_CMDID = 0x911,
- WMI_PORT_DELETE_CMDID = 0x912,
- WMI_POWER_MGMT_CFG_CMDID = 0x913,
- WMI_START_LISTEN_CMDID = 0x914,
- WMI_START_SEARCH_CMDID = 0x915,
- WMI_DISCOVERY_START_CMDID = 0x916,
- WMI_DISCOVERY_STOP_CMDID = 0x917,
- WMI_PCP_START_CMDID = 0x918,
- WMI_PCP_STOP_CMDID = 0x919,
- WMI_GET_PCP_FACTOR_CMDID = 0x91B,
+ WMI_P2P_CFG_CMDID = 0x910,
+ WMI_PORT_ALLOCATE_CMDID = 0x911,
+ WMI_PORT_DELETE_CMDID = 0x912,
+ WMI_POWER_MGMT_CFG_CMDID = 0x913,
+ WMI_START_LISTEN_CMDID = 0x914,
+ WMI_START_SEARCH_CMDID = 0x915,
+ WMI_DISCOVERY_START_CMDID = 0x916,
+ WMI_DISCOVERY_STOP_CMDID = 0x917,
+ WMI_PCP_START_CMDID = 0x918,
+ WMI_PCP_STOP_CMDID = 0x919,
+ WMI_GET_PCP_FACTOR_CMDID = 0x91B,
/* Power Save Configuration Commands */
- WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C,
+ WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C,
/* Not supported yet */
- WMI_PS_DEV_CFG_CMDID = 0x91D,
+ WMI_PS_DEV_CFG_CMDID = 0x91D,
/* Not supported yet */
- WMI_PS_DEV_CFG_READ_CMDID = 0x91E,
+ WMI_PS_DEV_CFG_READ_CMDID = 0x91E,
/* Per MAC Power Save Configuration commands
* Not supported yet
*/
- WMI_PS_MID_CFG_CMDID = 0x91F,
+ WMI_PS_MID_CFG_CMDID = 0x91F,
/* Not supported yet */
- WMI_PS_MID_CFG_READ_CMDID = 0x920,
- WMI_RS_CFG_CMDID = 0x921,
- WMI_GET_DETAILED_RS_RES_CMDID = 0x922,
- WMI_AOA_MEAS_CMDID = 0x923,
- WMI_TOF_SESSION_START_CMDID = 0x991,
- WMI_TOF_GET_CAPABILITIES_CMDID = 0x992,
- WMI_TOF_SET_LCR_CMDID = 0x993,
- WMI_TOF_SET_LCI_CMDID = 0x994,
- WMI_TOF_CHANNEL_INFO_CMDID = 0x995,
- WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
- WMI_ABORT_SCAN_CMDID = 0xF007,
- WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
- WMI_GET_PMK_CMDID = 0xF048,
- WMI_SET_PASSPHRASE_CMDID = 0xF049,
- WMI_SEND_ASSOC_RES_CMDID = 0xF04A,
- WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B,
- WMI_MAC_ADDR_REQ_CMDID = 0xF04D,
- WMI_FW_VER_CMDID = 0xF04E,
- WMI_PMC_CMDID = 0xF04F,
+ WMI_PS_MID_CFG_READ_CMDID = 0x920,
+ WMI_RS_CFG_CMDID = 0x921,
+ WMI_GET_DETAILED_RS_RES_CMDID = 0x922,
+ WMI_AOA_MEAS_CMDID = 0x923,
+ WMI_SET_MGMT_RETRY_LIMIT_CMDID = 0x930,
+ WMI_GET_MGMT_RETRY_LIMIT_CMDID = 0x931,
+ WMI_TOF_SESSION_START_CMDID = 0x991,
+ WMI_TOF_GET_CAPABILITIES_CMDID = 0x992,
+ WMI_TOF_SET_LCR_CMDID = 0x993,
+ WMI_TOF_SET_LCI_CMDID = 0x994,
+ WMI_TOF_CHANNEL_INFO_CMDID = 0x995,
+ WMI_TOF_SET_TX_RX_OFFSET_CMDID = 0x997,
+ WMI_TOF_GET_TX_RX_OFFSET_CMDID = 0x998,
+ WMI_GET_RF_SECTOR_PARAMS_CMDID = 0x9A0,
+ WMI_SET_RF_SECTOR_PARAMS_CMDID = 0x9A1,
+ WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID = 0x9A2,
+ WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID = 0x9A3,
+ WMI_SET_RF_SECTOR_ON_CMDID = 0x9A4,
+ WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5,
+ WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6,
+ WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7,
+ WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
+ WMI_ABORT_SCAN_CMDID = 0xF007,
+ WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
+ WMI_GET_PMK_CMDID = 0xF048,
+ WMI_SET_PASSPHRASE_CMDID = 0xF049,
+ WMI_SEND_ASSOC_RES_CMDID = 0xF04A,
+ WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B,
+ WMI_MAC_ADDR_REQ_CMDID = 0xF04D,
+ WMI_FW_VER_CMDID = 0xF04E,
+ WMI_PMC_CMDID = 0xF04F,
};
/* WMI_CONNECT_CMDID */
@@ -879,6 +894,14 @@ struct wmi_aoa_meas_cmd {
__le32 meas_rf_mask;
} __packed;
+/* WMI_SET_MGMT_RETRY_LIMIT_CMDID */
+struct wmi_set_mgmt_retry_limit_cmd {
+ /* MAC retransmit limit for mgmt frames */
+ u8 mgmt_retry_limit;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
enum wmi_tof_burst_duration {
WMI_TOF_BURST_DURATION_250_USEC = 2,
WMI_TOF_BURST_DURATION_500_USEC = 3,
@@ -942,6 +965,15 @@ struct wmi_tof_channel_info_cmd {
__le32 channel_info_report_request;
} __packed;
+/* WMI_TOF_SET_TX_RX_OFFSET_CMDID */
+struct wmi_tof_set_tx_rx_offset_cmd {
+ /* TX delay offset */
+ __le32 tx_offset;
+ /* RX delay offset */
+ __le32 rx_offset;
+ __le32 reserved[2];
+} __packed;
+
/* WMI Events
* List of Events (target to host)
*/
@@ -1035,12 +1067,24 @@ enum wmi_event_id {
WMI_RS_CFG_DONE_EVENTID = 0x1921,
WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922,
WMI_AOA_MEAS_EVENTID = 0x1923,
+ WMI_SET_MGMT_RETRY_LIMIT_EVENTID = 0x1930,
+ WMI_GET_MGMT_RETRY_LIMIT_EVENTID = 0x1931,
WMI_TOF_SESSION_END_EVENTID = 0x1991,
WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992,
WMI_TOF_SET_LCR_EVENTID = 0x1993,
WMI_TOF_SET_LCI_EVENTID = 0x1994,
WMI_TOF_FTM_PER_DEST_RES_EVENTID = 0x1995,
WMI_TOF_CHANNEL_INFO_EVENTID = 0x1996,
+ WMI_TOF_SET_TX_RX_OFFSET_EVENTID = 0x1997,
+ WMI_TOF_GET_TX_RX_OFFSET_EVENTID = 0x1998,
+ WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A0,
+ WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A1,
+ WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID = 0x19A2,
+ WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID = 0x19A3,
+ WMI_SET_RF_SECTOR_ON_DONE_EVENTID = 0x19A4,
+ WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5,
+ WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6,
+ WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7,
WMI_SET_CHANNEL_EVENTID = 0x9000,
WMI_ASSOC_REQ_EVENTID = 0x9001,
WMI_EAPOL_RX_EVENTID = 0x9002,
@@ -1166,6 +1210,7 @@ enum baseband_type {
BASEBAND_SPARROW_M_B0 = 0x05,
BASEBAND_SPARROW_M_C0 = 0x06,
BASEBAND_SPARROW_M_D0 = 0x07,
+ BASEBAND_TALYN_M_A0 = 0x08,
};
/* WMI_GET_BASEBAND_TYPE_EVENTID */
@@ -2070,6 +2115,22 @@ struct wmi_aoa_meas_event {
u8 meas_data[WMI_AOA_MAX_DATA_SIZE];
} __packed;
+/* WMI_SET_MGMT_RETRY_LIMIT_EVENTID */
+struct wmi_set_mgmt_retry_limit_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
+/* WMI_GET_MGMT_RETRY_LIMIT_EVENTID */
+struct wmi_get_mgmt_retry_limit_event {
+ /* MAC retransmit limit for mgmt frames */
+ u8 mgmt_retry_limit;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
/* WMI_TOF_GET_CAPABILITIES_EVENTID */
struct wmi_tof_get_capabilities_event {
u8 ftm_capability;
@@ -2184,4 +2245,283 @@ struct wmi_tof_channel_info_event {
u8 report[0];
} __packed;
+/* WMI_TOF_SET_TX_RX_OFFSET_EVENTID */
+struct wmi_tof_set_tx_rx_offset_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_TOF_GET_TX_RX_OFFSET_EVENTID */
+struct wmi_tof_get_tx_rx_offset_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ u8 reserved1[3];
+ /* TX delay offset */
+ __le32 tx_offset;
+ /* RX delay offset */
+ __le32 rx_offset;
+ __le32 reserved2[2];
+} __packed;
+
+/* Result status codes for WMI commands */
+enum wmi_rf_sector_status {
+ WMI_RF_SECTOR_STATUS_SUCCESS = 0x00,
+ WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR = 0x01,
+ WMI_RF_SECTOR_STATUS_BUSY_ERROR = 0x02,
+ WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR = 0x03,
+};
+
+/* Types of the RF sector (TX,RX) */
+enum wmi_rf_sector_type {
+ WMI_RF_SECTOR_TYPE_RX = 0x00,
+ WMI_RF_SECTOR_TYPE_TX = 0x01,
+};
+
+/* Content of RF Sector (six 32-bits registers) */
+struct wmi_rf_sector_info {
+ /* Phase values for RF Chains[15-0] (2bits per RF chain) */
+ __le32 psh_hi;
+ /* Phase values for RF Chains[31-16] (2bits per RF chain) */
+ __le32 psh_lo;
+ /* ETYPE Bit0 for all RF chains[31-0] - bit0 of Edge amplifier gain
+ * index
+ */
+ __le32 etype0;
+ /* ETYPE Bit1 for all RF chains[31-0] - bit1 of Edge amplifier gain
+ * index
+ */
+ __le32 etype1;
+ /* ETYPE Bit2 for all RF chains[31-0] - bit2 of Edge amplifier gain
+ * index
+ */
+ __le32 etype2;
+ /* D-Type values (3bits each) for 8 Distribution amplifiers + X16
+ * switch bits
+ */
+ __le32 dtype_swch_off;
+} __packed;
+
+#define WMI_INVALID_RF_SECTOR_INDEX (0xFFFF)
+#define WMI_MAX_RF_MODULES_NUM (8)
+
+/* WMI_GET_RF_SECTOR_PARAMS_CMD */
+struct wmi_get_rf_sector_params_cmd {
+ /* Sector number to be retrieved */
+ __le16 sector_idx;
+ /* enum wmi_rf_sector_type - type of requested RF sector */
+ u8 sector_type;
+ /* bitmask vector specifying destination RF modules */
+ u8 rf_modules_vec;
+} __packed;
+
+/* \WMI_GET_RF_SECTOR_PARAMS_DONE_EVENT */
+struct wmi_get_rf_sector_params_done_event {
+ /* result status of WMI_GET_RF_SECTOR_PARAMS_CMD (enum
+ * wmi_rf_sector_status)
+ */
+ u8 status;
+ /* align next field to U64 boundary */
+ u8 reserved[7];
+ /* TSF timestamp when RF sectors where retrieved */
+ __le64 tsf;
+ /* Content of RF sector retrieved from each RF module */
+ struct wmi_rf_sector_info sectors_info[WMI_MAX_RF_MODULES_NUM];
+} __packed;
+
+/* WMI_SET_RF_SECTOR_PARAMS_CMD */
+struct wmi_set_rf_sector_params_cmd {
+ /* Sector number to be retrieved */
+ __le16 sector_idx;
+ /* enum wmi_rf_sector_type - type of requested RF sector */
+ u8 sector_type;
+ /* bitmask vector specifying destination RF modules */
+ u8 rf_modules_vec;
+ /* Content of RF sector to be written to each RF module */
+ struct wmi_rf_sector_info sectors_info[WMI_MAX_RF_MODULES_NUM];
+} __packed;
+
+/* \WMI_SET_RF_SECTOR_PARAMS_DONE_EVENT */
+struct wmi_set_rf_sector_params_done_event {
+ /* result status of WMI_SET_RF_SECTOR_PARAMS_CMD (enum
+ * wmi_rf_sector_status)
+ */
+ u8 status;
+} __packed;
+
+/* WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD - Get RF sector index selected by
+ * TXSS/BRP for communication with specified CID
+ */
+struct wmi_get_selected_rf_sector_index_cmd {
+ /* Connection/Station ID in [0:7] range */
+ u8 cid;
+ /* type of requested RF sector (enum wmi_rf_sector_type) */
+ u8 sector_type;
+ /* align to U32 boundary */
+ u8 reserved[2];
+} __packed;
+
+/* \WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT - Returns retrieved RF sector
+ * index selected by TXSS/BRP for communication with specified CID
+ */
+struct wmi_get_selected_rf_sector_index_done_event {
+ /* Retrieved sector index selected in TXSS (for TX sector request) or
+ * BRP (for RX sector request)
+ */
+ __le16 sector_idx;
+ /* result status of WMI_GET_SELECTED_RF_SECTOR_INDEX_CMD (enum
+ * wmi_rf_sector_status)
+ */
+ u8 status;
+ /* align next field to U64 boundary */
+ u8 reserved[5];
+ /* TSF timestamp when result was retrieved */
+ __le64 tsf;
+} __packed;
+
+/* WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD - Force RF sector index for
+ * communication with specified CID. Assumes that TXSS/BRP is disabled by
+ * other command
+ */
+struct wmi_set_selected_rf_sector_index_cmd {
+ /* Connection/Station ID in [0:7] range */
+ u8 cid;
+ /* type of requested RF sector (enum wmi_rf_sector_type) */
+ u8 sector_type;
+ /* Forced sector index */
+ __le16 sector_idx;
+} __packed;
+
+/* \WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENT - Success/Fail status for
+ * WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD
+ */
+struct wmi_set_selected_rf_sector_index_done_event {
+ /* result status of WMI_SET_SELECTED_RF_SECTOR_INDEX_CMD (enum
+ * wmi_rf_sector_status)
+ */
+ u8 status;
+ /* align to U32 boundary */
+ u8 reserved[3];
+} __packed;
+
+/* WMI_SET_RF_SECTOR_ON_CMD - Activates specified sector for specified rf
+ * modules
+ */
+struct wmi_set_rf_sector_on_cmd {
+ /* Sector index to be activated */
+ __le16 sector_idx;
+ /* type of requested RF sector (enum wmi_rf_sector_type) */
+ u8 sector_type;
+ /* bitmask vector specifying destination RF modules */
+ u8 rf_modules_vec;
+} __packed;
+
+/* \WMI_SET_RF_SECTOR_ON_DONE_EVENT - Success/Fail status for
+ * WMI_SET_RF_SECTOR_ON_CMD
+ */
+struct wmi_set_rf_sector_on_done_event {
+ /* result status of WMI_SET_RF_SECTOR_ON_CMD (enum
+ * wmi_rf_sector_status)
+ */
+ u8 status;
+ /* align to U32 boundary */
+ u8 reserved[3];
+} __packed;
+
+enum wmi_sector_sweep_type {
+ WMI_SECTOR_SWEEP_TYPE_TXSS = 0x00,
+ WMI_SECTOR_SWEEP_TYPE_BCON = 0x01,
+ WMI_SECTOR_SWEEP_TYPE_TXSS_AND_BCON = 0x02,
+ WMI_SECTOR_SWEEP_TYPE_NUM = 0x03,
+};
+
+/* WMI_PRIO_TX_SECTORS_ORDER_CMDID
+ *
+ * Set the order of TX sectors in TXSS and/or Beacon(AP).
+ *
+ * Returned event:
+ * - WMI_PRIO_TX_SECTORS_ORDER_EVENTID
+ */
+struct wmi_prio_tx_sectors_order_cmd {
+ /* tx sectors order to be applied, 0xFF for end of array */
+ u8 tx_sectors_priority_array[MAX_NUM_OF_SECTORS];
+ /* enum wmi_sector_sweep_type, TXSS and/or Beacon */
+ u8 sector_sweep_type;
+ /* needed only for TXSS configuration */
+ u8 cid;
+ /* alignment to 32b */
+ u8 reserved[2];
+} __packed;
+
+/* completion status codes */
+enum wmi_prio_tx_sectors_cmd_status {
+ WMI_PRIO_TX_SECT_CMD_STATUS_SUCCESS = 0x00,
+ WMI_PRIO_TX_SECT_CMD_STATUS_BAD_PARAM = 0x01,
+ /* other error */
+ WMI_PRIO_TX_SECT_CMD_STATUS_ERROR = 0x02,
+};
+
+/* WMI_PRIO_TX_SECTORS_ORDER_EVENTID */
+struct wmi_prio_tx_sectors_order_event {
+ /* enum wmi_prio_tx_sectors_cmd_status */
+ u8 status;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
+struct wmi_prio_tx_sectors_num_cmd {
+ /* [0-128], 0 = No changes */
+ u8 beacon_number_of_sectors;
+ /* [0-128], 0 = No changes */
+ u8 txss_number_of_sectors;
+ /* [0-8] needed only for TXSS configuration */
+ u8 cid;
+} __packed;
+
+/* WMI_PRIO_TX_SECTORS_NUMBER_CMDID
+ *
+ * Set the number of active sectors in TXSS and/or Beacon.
+ *
+ * Returned event:
+ * - WMI_PRIO_TX_SECTORS_NUMBER_EVENTID
+ */
+struct wmi_prio_tx_sectors_number_cmd {
+ struct wmi_prio_tx_sectors_num_cmd active_sectors_num;
+ /* alignment to 32b */
+ u8 reserved;
+} __packed;
+
+/* WMI_PRIO_TX_SECTORS_NUMBER_EVENTID */
+struct wmi_prio_tx_sectors_number_event {
+ /* enum wmi_prio_tx_sectors_cmd_status */
+ u8 status;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
+/* WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID
+ *
+ * Set default sectors order and number (hard coded in board file)
+ * in TXSS and/or Beacon.
+ *
+ * Returned event:
+ * - WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID
+ */
+struct wmi_prio_tx_sectors_set_default_cfg_cmd {
+ /* enum wmi_sector_sweep_type, TXSS and/or Beacon */
+ u8 sector_sweep_type;
+ /* needed only for TXSS configuration */
+ u8 cid;
+ /* alignment to 32b */
+ u8 reserved[2];
+} __packed;
+
+/* WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID */
+struct wmi_prio_tx_sectors_set_default_cfg_event {
+ /* enum wmi_prio_tx_sectors_cmd_status */
+ u8 status;
+ /* alignment to 32b */
+ u8 reserved[3];
+} __packed;
+
#endif /* __WILOCITY_WMI_H__ */
diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c
index bf2e9a083c0c..eb92d5ab7a27 100644
--- a/drivers/net/wireless/atmel/atmel.c
+++ b/drivers/net/wireless/atmel/atmel.c
@@ -1295,14 +1295,6 @@ static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
return &priv->wstats;
}
-static int atmel_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > 2312))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static int atmel_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
@@ -1506,7 +1498,6 @@ static const struct file_operations atmel_proc_fops = {
static const struct net_device_ops atmel_netdev_ops = {
.ndo_open = atmel_open,
.ndo_stop = atmel_close,
- .ndo_change_mtu = atmel_change_mtu,
.ndo_set_mac_address = atmel_set_mac_address,
.ndo_start_xmit = start_tx,
.ndo_do_ioctl = atmel_ioctl,
@@ -1600,6 +1591,10 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
dev->irq = irq;
dev->base_addr = port;
+ /* MTU range: 68 - 2312 */
+ dev->min_mtu = 68;
+ dev->max_mtu = MAX_WIRELESS_BODY - ETH_FCS_LEN;
+
SET_NETDEV_DEV(dev, sys_dev);
if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) {
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 6e5d9095b195..52f3541ecbcf 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -5591,7 +5591,9 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT) |
BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
BIT(NL80211_IFTYPE_WDS) |
+#endif
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
index 83770d2ea057..e97ab2b91663 100644
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -3838,7 +3838,9 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
BIT(NL80211_IFTYPE_WDS) |
+#endif
BIT(NL80211_IFTYPE_ADHOC);
hw->queues = 1; /* FIXME: hardware has more queues */
hw->max_rates = 2;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
index 9e4b505ca593..d1568bed1ad1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
@@ -35,7 +35,8 @@ brcmfmac-objs += \
firmware.o \
feature.o \
btcoex.o \
- vendor.o
+ vendor.o \
+ pno.o
brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
bcdc.o
brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index 038a960c5104..384b1873e7e3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -326,6 +326,17 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
return 0;
}
+static int brcmf_proto_bcdc_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+ struct sk_buff *skb)
+{
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, ifidx);
+
+ if (!brcmf_fws_queue_skbs(drvr->fws))
+ return brcmf_proto_txdata(drvr, ifidx, 0, skb);
+
+ return brcmf_fws_process_skb(ifp, skb);
+}
+
static int
brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *pktbuf)
@@ -375,6 +386,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
+ drvr->proto->tx_queue_data = brcmf_proto_bcdc_tx_queue_data;
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 2b246545647a..e21f7600122b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -22,10 +22,12 @@
/* IDs of the 6 default common rings of msgbuf protocol */
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1
+#define BRCMF_H2D_MSGRING_FLOWRING_IDSTART 2
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2
#define BRCMF_D2H_MSGRING_TX_COMPLETE 3
#define BRCMF_D2H_MSGRING_RX_COMPLETE 4
+
#define BRCMF_NROF_H2D_COMMON_MSGRINGS 2
#define BRCMF_NROF_D2H_COMMON_MSGRINGS 3
#define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \
@@ -95,14 +97,18 @@ struct brcmf_bus_ops {
* @flowrings: commonrings which are dynamically created and destroyed for data.
* @rx_dataoffset: if set then all rx data has this this offset.
* @max_rxbufpost: maximum number of buffers to post for rx.
- * @nrof_flowrings: number of flowrings.
+ * @max_flowrings: maximum number of tx flow rings supported.
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
*/
struct brcmf_bus_msgbuf {
struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
struct brcmf_commonring **flowrings;
u32 rx_dataoffset;
u32 max_rxbufpost;
- u32 nrof_flowrings;
+ u16 max_flowrings;
+ u16 max_submissionrings;
+ u16 max_completionrings;
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 78d9966a3957..ccae3bbe7db2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -32,6 +32,7 @@
#include "fwil_types.h"
#include "p2p.h"
#include "btcoex.h"
+#include "pno.h"
#include "cfg80211.h"
#include "feature.h"
#include "fwil.h"
@@ -41,16 +42,6 @@
#include "common.h"
#define BRCMF_SCAN_IE_LEN_MAX 2048
-#define BRCMF_PNO_VERSION 2
-#define BRCMF_PNO_TIME 30
-#define BRCMF_PNO_REPEAT 4
-#define BRCMF_PNO_FREQ_EXPO_MAX 3
-#define BRCMF_PNO_MAX_PFN_COUNT 16
-#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
-#define BRCMF_PNO_HIDDEN_BIT 2
-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
-#define BRCMF_PNO_SCAN_COMPLETE 1
-#define BRCMF_PNO_SCAN_INCOMPLETE 0
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
#define WPA_OUI_TYPE 1
@@ -414,23 +405,24 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif,
enum nl80211_iftype new_type)
{
- int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
bool check_combos = false;
int ret = 0;
+ struct iface_combination_params params = {
+ .num_different_channels = 1,
+ };
- memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
if (pos == vif) {
- iftype_num[new_type]++;
+ params.iftype_num[new_type]++;
} else {
/* concurrent interfaces so need check combinations */
check_combos = true;
- iftype_num[pos->wdev.iftype]++;
+ params.iftype_num[pos->wdev.iftype]++;
}
if (check_combos)
- ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+ ret = cfg80211_check_combinations(cfg->wiphy, &params);
return ret;
}
@@ -438,15 +430,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype new_type)
{
- int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
+ struct iface_combination_params params = {
+ .num_different_channels = 1,
+ };
- memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
- iftype_num[pos->wdev.iftype]++;
+ params.iftype_num[pos->wdev.iftype]++;
- iftype_num[new_type]++;
- return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+ params.iftype_num[new_type]++;
+ return cfg80211_check_combinations(cfg->wiphy, &params);
}
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
@@ -766,12 +759,12 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
brcmf_scan_config_mpc(ifp, 1);
/*
- * e-scan can be initiated by scheduled scan
+ * e-scan can be initiated internally
* which takes precedence.
*/
- if (cfg->sched_escan) {
+ if (cfg->internal_escan) {
brcmf_dbg(SCAN, "scheduled scan completed\n");
- cfg->sched_escan = false;
+ cfg->internal_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
} else if (scan_request) {
@@ -1089,9 +1082,9 @@ exit:
}
static s32
-brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
- struct brcmf_if *ifp, struct cfg80211_scan_request *request)
+brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
{
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 err;
u32 passive_scan;
struct brcmf_scan_results *results;
@@ -1099,7 +1092,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
brcmf_dbg(SCAN, "Enter\n");
escan->ifp = ifp;
- escan->wiphy = wiphy;
+ escan->wiphy = cfg->wiphy;
escan->escan_state = WL_ESCAN_STATE_SCANNING;
passive_scan = cfg->active_scan ? 0 : 1;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
@@ -1179,7 +1172,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
if (err)
goto scan_out;
- err = brcmf_do_escan(cfg, wiphy, vif->ifp, request);
+ err = brcmf_do_escan(vif->ifp, request);
if (err)
goto scan_out;
} else {
@@ -3022,7 +3015,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
struct escan_info *escan = &cfg->escan_info;
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
- if (cfg->scan_request) {
+ if (cfg->internal_escan || cfg->scan_request) {
escan->escan_state = WL_ESCAN_STATE_IDLE;
brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
}
@@ -3045,7 +3038,7 @@ static void brcmf_escan_timeout(unsigned long data)
struct brcmf_cfg80211_info *cfg =
(struct brcmf_cfg80211_info *)data;
- if (cfg->scan_request) {
+ if (cfg->internal_escan || cfg->scan_request) {
brcmf_err("timer expired\n");
schedule_work(&cfg->escan_timeout_work);
}
@@ -3128,7 +3121,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
goto exit;
- if (!cfg->scan_request) {
+ if (!cfg->internal_escan && !cfg->scan_request) {
brcmf_dbg(SCAN, "result without cfg80211 request\n");
goto exit;
}
@@ -3174,7 +3167,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
goto exit;
- if (cfg->scan_request) {
+ if (cfg->internal_escan || cfg->scan_request) {
brcmf_inform_bss(cfg);
aborted = status != BRCMF_E_STATUS_SUCCESS;
brcmf_notify_escan_complete(cfg, ifp, aborted, false);
@@ -3199,6 +3192,95 @@ static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
brcmf_cfg80211_escan_timeout_worker);
}
+static struct cfg80211_scan_request *
+brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
+ struct cfg80211_scan_request *req;
+ size_t req_size;
+
+ req_size = sizeof(*req) +
+ n_netinfo * sizeof(req->channels[0]) +
+ n_netinfo * sizeof(*req->ssids);
+
+ req = kzalloc(req_size, GFP_KERNEL);
+ if (req) {
+ req->wiphy = wiphy;
+ req->ssids = (void *)(&req->channels[0]) +
+ n_netinfo * sizeof(req->channels[0]);
+ }
+ return req;
+}
+
+static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
+ u8 *ssid, u8 ssid_len, u8 channel)
+{
+ struct ieee80211_channel *chan;
+ enum nl80211_band band;
+ int freq;
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = NL80211_BAND_2GHZ;
+ else
+ band = NL80211_BAND_5GHZ;
+
+ freq = ieee80211_channel_to_frequency(channel, band);
+ if (!freq)
+ return -EINVAL;
+
+ chan = ieee80211_get_channel(req->wiphy, freq);
+ if (!chan)
+ return -EINVAL;
+
+ req->channels[req->n_channels++] = chan;
+ memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len);
+ req->ssids[req->n_ssids++].ssid_len = ssid_len;
+
+ return 0;
+}
+
+static int brcmf_start_internal_escan(struct brcmf_if *ifp,
+ struct cfg80211_scan_request *request)
+{
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ int err;
+
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ /* Abort any on-going scan */
+ brcmf_abort_scanning(cfg);
+ }
+
+ set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+ cfg->escan_info.run = brcmf_run_escan;
+ err = brcmf_do_escan(ifp, request);
+ if (err) {
+ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+ return err;
+ }
+ cfg->internal_escan = true;
+ return 0;
+}
+
+static struct brcmf_pno_net_info_le *
+brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
+{
+ struct brcmf_pno_scanresults_v2_le *pfn_v2;
+ struct brcmf_pno_net_info_le *netinfo;
+
+ switch (pfn_v1->version) {
+ default:
+ WARN_ON(1);
+ /* fall-thru */
+ case cpu_to_le32(1):
+ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);
+ break;
+ case cpu_to_le32(2):
+ pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
+ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
+ break;
+ }
+
+ return netinfo;
+}
+
/* PFN result doesn't have all the info which are required by the supplicant
* (For e.g IEs) Do a target Escan so that sched scan results are reported
* via wl_inform_single_bss in the required format. Escan does require the
@@ -3212,12 +3294,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
struct cfg80211_scan_request *request = NULL;
- struct cfg80211_ssid *ssid = NULL;
- struct ieee80211_channel *channel = NULL;
struct wiphy *wiphy = cfg_to_wiphy(cfg);
- int err = 0;
- int channel_req = 0;
- int band = 0;
+ int i, err = 0;
struct brcmf_pno_scanresults_le *pfn_result;
u32 result_count;
u32 status;
@@ -3243,254 +3321,86 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
*/
WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
- if (result_count > 0) {
- int i;
-
- request = kzalloc(sizeof(*request), GFP_KERNEL);
- ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
- channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
- if (!request || !ssid || !channel) {
- err = -ENOMEM;
- goto out_err;
- }
-
- request->wiphy = wiphy;
- data += sizeof(struct brcmf_pno_scanresults_le);
- netinfo_start = (struct brcmf_pno_net_info_le *)data;
-
- for (i = 0; i < result_count; i++) {
- netinfo = &netinfo_start[i];
- if (!netinfo) {
- brcmf_err("Invalid netinfo ptr. index: %d\n",
- i);
- err = -EINVAL;
- goto out_err;
- }
-
- brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
- netinfo->SSID, netinfo->channel);
- memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
- ssid[i].ssid_len = netinfo->SSID_len;
- request->n_ssids++;
-
- channel_req = netinfo->channel;
- if (channel_req <= CH_MAX_2G_CHANNEL)
- band = NL80211_BAND_2GHZ;
- else
- band = NL80211_BAND_5GHZ;
- channel[i].center_freq =
- ieee80211_channel_to_frequency(channel_req,
- band);
- channel[i].band = band;
- channel[i].flags |= IEEE80211_CHAN_NO_HT40;
- request->channels[i] = &channel[i];
- request->n_channels++;
- }
-
- /* assign parsed ssid array */
- if (request->n_ssids)
- request->ssids = &ssid[0];
-
- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
- /* Abort any on-going scan */
- brcmf_abort_scanning(cfg);
- }
-
- set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
- cfg->escan_info.run = brcmf_run_escan;
- err = brcmf_do_escan(cfg, wiphy, ifp, request);
- if (err) {
- clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
- goto out_err;
- }
- cfg->sched_escan = true;
- cfg->scan_request = request;
- } else {
+ if (!result_count) {
brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
goto out_err;
}
-
- kfree(ssid);
- kfree(channel);
- kfree(request);
- return 0;
-
-out_err:
- kfree(ssid);
- kfree(channel);
- kfree(request);
- cfg80211_sched_scan_stopped(wiphy);
- return err;
-}
-
-static int brcmf_dev_pno_clean(struct net_device *ndev)
-{
- int ret;
-
- /* Disable pfn */
- ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
- if (ret == 0) {
- /* clear pfn */
- ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
- NULL, 0);
- }
- if (ret < 0)
- brcmf_err("failed code %d\n", ret);
-
- return ret;
-}
-
-static int brcmf_dev_pno_config(struct brcmf_if *ifp,
- struct cfg80211_sched_scan_request *request)
-{
- struct brcmf_pno_param_le pfn_param;
- struct brcmf_pno_macaddr_le pfn_mac;
- s32 err;
- u8 *mac_mask;
- int i;
-
- memset(&pfn_param, 0, sizeof(pfn_param));
- pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
-
- /* set extra pno params */
- pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
- pfn_param.repeat = BRCMF_PNO_REPEAT;
- pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
-
- /* set up pno scan fr */
- pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
-
- err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
- sizeof(pfn_param));
- if (err) {
- brcmf_err("pfn_set failed, err=%d\n", err);
- return err;
+ request = brcmf_alloc_internal_escan_request(wiphy,
+ result_count);
+ if (!request) {
+ err = -ENOMEM;
+ goto out_err;
}
- /* Find out if mac randomization should be turned on */
- if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
- return 0;
+ data += sizeof(struct brcmf_pno_scanresults_le);
+ netinfo_start = brcmf_get_netinfo_array(pfn_result);
- pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
- pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
+ for (i = 0; i < result_count; i++) {
+ netinfo = &netinfo_start[i];
+ if (!netinfo) {
+ brcmf_err("Invalid netinfo ptr. index: %d\n",
+ i);
+ err = -EINVAL;
+ goto out_err;
+ }
- memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
- mac_mask = request->mac_addr_mask;
- for (i = 0; i < ETH_ALEN; i++) {
- pfn_mac.mac[i] &= mac_mask[i];
- pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
+ brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
+ netinfo->SSID, netinfo->channel);
+ err = brcmf_internal_escan_add_info(request,
+ netinfo->SSID,
+ netinfo->SSID_len,
+ netinfo->channel);
+ if (err)
+ goto out_err;
}
- /* Clear multi bit */
- pfn_mac.mac[0] &= 0xFE;
- /* Set locally administered */
- pfn_mac.mac[0] |= 0x02;
- err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
- sizeof(pfn_mac));
- if (err)
- brcmf_err("pfn_macaddr failed, err=%d\n", err);
+ err = brcmf_start_internal_escan(ifp, request);
+ if (!err)
+ goto free_req;
+out_err:
+ cfg80211_sched_scan_stopped(wiphy);
+free_req:
+ kfree(request);
return err;
}
static int
brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct net_device *ndev,
- struct cfg80211_sched_scan_request *request)
+ struct cfg80211_sched_scan_request *req)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
- struct brcmf_pno_net_param_le pfn;
- int i;
- int ret = 0;
brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
- request->n_match_sets, request->n_ssids);
- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
- brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
- return -EAGAIN;
- }
+ req->n_match_sets, req->n_ssids);
+
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
brcmf_err("Scanning suppressed: status (%lu)\n",
cfg->scan_status);
return -EAGAIN;
}
- if (!request->n_ssids || !request->n_match_sets) {
- brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
- request->n_ssids);
- return -EINVAL;
- }
-
- if (request->n_ssids > 0) {
- for (i = 0; i < request->n_ssids; i++) {
- /* Active scan req for ssids */
- brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
- request->ssids[i].ssid);
-
- /* match_set ssids is a supert set of n_ssid list,
- * so we need not add these set separately.
- */
- }
- }
-
- if (request->n_match_sets > 0) {
- /* clean up everything */
- ret = brcmf_dev_pno_clean(ndev);
- if (ret < 0) {
- brcmf_err("failed error=%d\n", ret);
- return ret;
- }
-
- /* configure pno */
- if (brcmf_dev_pno_config(ifp, request))
- return -EINVAL;
-
- /* configure each match set */
- for (i = 0; i < request->n_match_sets; i++) {
- struct cfg80211_ssid *ssid;
- u32 ssid_len;
-
- ssid = &request->match_sets[i].ssid;
- ssid_len = ssid->ssid_len;
-
- if (!ssid_len) {
- brcmf_err("skip broadcast ssid\n");
- continue;
- }
- pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
- pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
- pfn.wsec = cpu_to_le32(0);
- pfn.infra = cpu_to_le32(1);
- pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
- pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
- memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
- ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
- sizeof(pfn));
- brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
- ret == 0 ? "set" : "failed", ssid->ssid);
- }
- /* Enable the PNO */
- if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
- return -EINVAL;
- }
- } else {
+ if (req->n_match_sets <= 0) {
+ brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",
+ req->n_match_sets);
return -EINVAL;
}
- return 0;
+ return brcmf_pno_start_sched_scan(ifp, req);
}
static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
struct net_device *ndev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(SCAN, "enter\n");
- brcmf_dev_pno_clean(ndev);
- if (cfg->sched_escan)
- brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true);
+ brcmf_pno_clean(ifp);
+ if (cfg->internal_escan)
+ brcmf_notify_escan_complete(cfg, ifp, true, true);
return 0;
}
@@ -4578,8 +4488,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_configure_opensecurity(ifp);
}
- brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
-
/* Parameters shared by all radio interfaces */
if (!mbss) {
if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {
@@ -4708,6 +4616,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
WARN_ON(1);
}
+ brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
brcmf_net_setcarrier(ifp, true);
@@ -4764,6 +4673,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0)
brcmf_err("BRCMF_C_UP error %d\n", err);
+
+ brcmf_vif_clear_mgmt_ies(ifp->vif);
} else {
bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
bss_enable.enable = cpu_to_le32(0);
@@ -5506,7 +5417,8 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
u32 reason = e->reason;
struct station_info sinfo;
- brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
+ brcmf_dbg(CONN, "event %s (%u), reason %d\n",
+ brcmf_fweh_event_name(event), event, reason);
if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
ndev != cfg_to_ndev(cfg)) {
brcmf_dbg(CONN, "AP mode link down\n");
@@ -6424,6 +6336,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+ wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 8889832c17e0..0c9a7081fca9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl {
* @pub: common driver information.
* @channel: current channel.
* @active_scan: current scan mode.
- * @sched_escan: e-scan for scheduled scan support running.
+ * @internal_escan: indicates internally initiated e-scan is running.
* @ibss_starter: indicates this sta is ibss starter.
* @pwr_save: indicate whether dongle to support power save mode.
* @dongle_up: indicate whether dongle up or not.
@@ -303,7 +303,7 @@ struct brcmf_cfg80211_info {
struct brcmf_pub *pub;
u32 channel;
bool active_scan;
- bool sched_escan;
+ bool internal_escan;
bool ibss_starter;
bool pwr_save;
bool dongle_up;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 5eaac13e2317..9e6f60a0ec3e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -239,7 +239,13 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
if (eh->h_proto == htons(ETH_P_PAE))
atomic_inc(&ifp->pend_8021x_cnt);
- ret = brcmf_fws_process_skb(ifp, skb);
+ /* determine the priority */
+ if ((skb->priority == 0) || (skb->priority > 7))
+ skb->priority = cfg80211_classify8021d(skb, NULL);
+
+ ret = brcmf_proto_tx_queue_data(drvr, ifp->ifidx, skb);
+ if (ret < 0)
+ brcmf_txfinalize(ifp, skb, false);
done:
if (ret) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index 79c081fd560f..c79306b57532 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -69,7 +69,7 @@ static struct brcmf_fweh_event_name fweh_event_names[] = {
*
* @code: code to lookup.
*/
-static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
{
int i;
for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
@@ -79,7 +79,7 @@ static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
return "unknown";
}
#else
-static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
{
return "nodebug";
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index 26ff5a9648f3..5fba4b49f3b3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -287,6 +287,8 @@ struct brcmf_fweh_info {
void *data);
};
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code);
+
void brcmf_fweh_attach(struct brcmf_pub *drvr);
void brcmf_fweh_detach(struct brcmf_pub *drvr);
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index a4118c0ef6ca..9a1eb5ab6c4b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -131,6 +131,7 @@
#define BRCMF_TXBF_MU_BFR_CAP BIT(1)
#define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */
+#define BRCMF_NUMCHANNELS 64
#define BRCMF_PFN_MACADDR_CFG_VER 1
#define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
@@ -719,6 +720,21 @@ struct brcmf_pno_param_le {
};
/**
+ * struct brcmf_pno_config_le - PNO channel configuration.
+ *
+ * @reporttype: determines what is reported.
+ * @channel_num: number of channels specified in @channel_list.
+ * @channel_list: channels to use in PNO scan.
+ * @flags: reserved.
+ */
+struct brcmf_pno_config_le {
+ __le32 reporttype;
+ __le32 channel_num;
+ __le16 channel_list[BRCMF_NUMCHANNELS];
+ __le32 flags;
+};
+
+/**
* struct brcmf_pno_net_param_le - scan parameters per preferred network.
*
* @ssid: ssid name and its length.
@@ -769,6 +785,13 @@ struct brcmf_pno_scanresults_le {
__le32 count;
};
+struct brcmf_pno_scanresults_v2_le {
+ __le32 version;
+ __le32 status;
+ __le32 count;
+ __le32 scan_ch_bucket;
+};
+
/**
* struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization.
*
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index a190f535efc9..5f1a5929cb30 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -2100,16 +2100,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
int rc = 0;
brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
- /* determine the priority */
- if ((skb->priority == 0) || (skb->priority > 7))
- skb->priority = cfg80211_classify8021d(skb, NULL);
-
- if (fws->avoid_queueing) {
- rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
- if (rc < 0)
- brcmf_txfinalize(ifp, skb, false);
- return rc;
- }
/* set control buffer information */
skcb->if_flags = 0;
@@ -2442,6 +2432,11 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
kfree(fws);
}
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
+{
+ return !fws->avoid_queueing;
+}
+
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
{
if (!fws->creditmap_received)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
index ef0ad8597c8a..96df66073b2a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
@@ -20,6 +20,7 @@
int brcmf_fws_init(struct brcmf_pub *drvr);
void brcmf_fws_deinit(struct brcmf_pub *drvr);
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 2b9a2bc429d6..d2c834c3b2fc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -87,11 +87,6 @@ struct msgbuf_common_hdr {
__le32 request_id;
};
-struct msgbuf_buf_addr {
- __le32 low_addr;
- __le32 high_addr;
-};
-
struct msgbuf_ioctl_req_hdr {
struct msgbuf_common_hdr msg;
__le32 cmd;
@@ -227,7 +222,10 @@ struct brcmf_msgbuf {
struct brcmf_commonring **commonrings;
struct brcmf_commonring **flowrings;
dma_addr_t *flowring_dma_handle;
- u16 nrof_flowrings;
+
+ u16 max_flowrings;
+ u16 max_submissionrings;
+ u16 max_completionrings;
u16 rx_dataoffset;
u32 max_rxbufpost;
@@ -610,7 +608,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
create->msg.request_id = 0;
create->tid = brcmf_flowring_tid(msgbuf->flow, flowid);
create->flow_ring_id = cpu_to_le16(flowid +
- BRCMF_NROF_H2D_COMMON_MSGRINGS);
+ BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
memcpy(create->sa, work->sa, ETH_ALEN);
memcpy(create->da, work->da, ETH_ALEN);
address = (u64)msgbuf->flowring_dma_handle[flowid];
@@ -760,7 +758,7 @@ static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)
u32 flowid;
msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);
- for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) {
+ for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->max_flowrings) {
clear_bit(flowid, msgbuf->flow_map);
brcmf_msgbuf_txflow(msgbuf, flowid);
}
@@ -782,8 +780,8 @@ static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,
}
-static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
- u8 offset, struct sk_buff *skb)
+static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+ struct sk_buff *skb)
{
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
struct brcmf_flowring *flow = msgbuf->flow;
@@ -866,7 +864,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
tx_status = (struct msgbuf_tx_status *)buf;
idx = le32_to_cpu(tx_status->msg.request_id);
flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->tx_pktids, idx);
if (!skb)
@@ -1174,7 +1172,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf;
flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id);
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
status = le16_to_cpu(flowring_create_resp->compl_hdr.status);
if (status) {
@@ -1202,7 +1200,7 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf;
flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id);
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
status = le16_to_cpu(flowring_delete_resp->compl_hdr.status);
if (status) {
@@ -1307,7 +1305,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
brcmf_msgbuf_process_rx(msgbuf, buf);
for_each_set_bit(flowid, msgbuf->txstatus_done_map,
- msgbuf->nrof_flowrings) {
+ msgbuf->max_flowrings) {
clear_bit(flowid, msgbuf->txstatus_done_map);
commonring = msgbuf->flowrings[flowid];
qlen = brcmf_flowring_qlen(msgbuf->flow, flowid);
@@ -1349,7 +1347,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
delete->msg.request_id = 0;
delete->flow_ring_id = cpu_to_le16(flowid +
- BRCMF_NROF_H2D_COMMON_MSGRINGS);
+ BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
delete->reason = 0;
brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n",
@@ -1427,10 +1425,10 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
if_msgbuf = drvr->bus_if->msgbuf;
- if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
+ if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
brcmf_err("driver not configured for this many flowrings %d\n",
- if_msgbuf->nrof_flowrings);
- if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
+ if_msgbuf->max_flowrings);
+ if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
}
msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
@@ -1443,7 +1441,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
goto fail;
}
INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
- count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
+ count = BITS_TO_LONGS(if_msgbuf->max_flowrings);
count = count * sizeof(unsigned long);
msgbuf->flow_map = kzalloc(count, GFP_KERNEL);
if (!msgbuf->flow_map)
@@ -1467,7 +1465,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
drvr->proto->hdrpull = brcmf_msgbuf_hdrpull;
drvr->proto->query_dcmd = brcmf_msgbuf_query_dcmd;
drvr->proto->set_dcmd = brcmf_msgbuf_set_dcmd;
- drvr->proto->txdata = brcmf_msgbuf_txdata;
+ drvr->proto->tx_queue_data = brcmf_msgbuf_tx_queue_data;
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
@@ -1479,8 +1477,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
msgbuf->commonrings =
(struct brcmf_commonring **)if_msgbuf->commonrings;
msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
- msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings;
- msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings *
+ msgbuf->max_flowrings = if_msgbuf->max_flowrings;
+ msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings *
sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL);
if (!msgbuf->flowring_dma_handle)
goto fail;
@@ -1501,7 +1499,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
goto fail;
msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev,
- if_msgbuf->nrof_flowrings);
+ if_msgbuf->max_flowrings);
if (!msgbuf->flow)
goto fail;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
index ee6906a3c3f6..f93ba6be1ef8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
@@ -31,6 +31,10 @@
#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32
#define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48
+struct msgbuf_buf_addr {
+ __le32 low_addr;
+ __le32 high_addr;
+};
int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 3deba90c7eb5..048027f2085b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -135,7 +135,7 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_PCIE_MB_INT_D2H3_DB1)
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
-#define BRCMF_PCIE_MAX_SHARED_VERSION 5
+#define BRCMF_PCIE_MAX_SHARED_VERSION 6
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
@@ -166,17 +166,6 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_RING_MEM_SZ 16
#define BRCMF_RING_STATE_SZ 8
-#define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET 4
-#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
-#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
-#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
-#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20
-#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28
-#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36
-#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44
-#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0
-#define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52
-
#define BRCMF_DEF_MAX_RXBUFPOST 255
#define BRCMF_CONSOLE_BUFADDR_OFFSET 8
@@ -231,7 +220,9 @@ struct brcmf_pcie_shared_info {
struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
struct brcmf_pcie_ringbuf *flowrings;
u16 max_rxbufpost;
- u32 nrof_flowrings;
+ u16 max_flowrings;
+ u16 max_submissionrings;
+ u16 max_completionrings;
u32 rx_dataoffset;
u32 htod_mb_data_addr;
u32 dtoh_mb_data_addr;
@@ -241,6 +232,7 @@ struct brcmf_pcie_shared_info {
dma_addr_t scratch_dmahandle;
void *ringupd;
dma_addr_t ringupd_dmahandle;
+ u8 version;
};
struct brcmf_pcie_core_info {
@@ -284,6 +276,36 @@ struct brcmf_pcie_ringbuf {
u8 id;
};
+/**
+ * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info
+ *
+ * @ringmem: dongle memory pointer to ring memory location
+ * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers
+ * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers
+ * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers
+ * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers
+ * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers
+ * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers
+ * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers
+ * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers
+ * @max_flowrings: maximum number of tx flow rings supported.
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
+ */
+struct brcmf_pcie_dhi_ringinfo {
+ __le32 ringmem;
+ __le32 h2d_w_idx_ptr;
+ __le32 h2d_r_idx_ptr;
+ __le32 d2h_w_idx_ptr;
+ __le32 d2h_r_idx_ptr;
+ struct msgbuf_buf_addr h2d_w_idx_hostaddr;
+ struct msgbuf_buf_addr h2d_r_idx_hostaddr;
+ struct msgbuf_buf_addr d2h_w_idx_hostaddr;
+ struct msgbuf_buf_addr d2h_r_idx_hostaddr;
+ __le16 max_flowrings;
+ __le16 max_submissionrings;
+ __le16 max_completionrings;
+};
static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
@@ -1054,26 +1076,35 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
{
struct brcmf_pcie_ringbuf *ring;
struct brcmf_pcie_ringbuf *rings;
- u32 ring_addr;
u32 d2h_w_idx_ptr;
u32 d2h_r_idx_ptr;
u32 h2d_w_idx_ptr;
u32 h2d_r_idx_ptr;
- u32 addr;
u32 ring_mem_ptr;
u32 i;
u64 address;
u32 bufsz;
- u16 max_sub_queues;
u8 idx_offset;
-
- ring_addr = devinfo->shared.ring_info_addr;
- brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
- addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
- max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+ struct brcmf_pcie_dhi_ringinfo ringinfo;
+ u16 max_flowrings;
+ u16 max_submissionrings;
+ u16 max_completionrings;
+
+ memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr,
+ sizeof(ringinfo));
+ if (devinfo->shared.version >= 6) {
+ max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings);
+ max_flowrings = le16_to_cpu(ringinfo.max_flowrings);
+ max_completionrings = le16_to_cpu(ringinfo.max_completionrings);
+ } else {
+ max_submissionrings = le16_to_cpu(ringinfo.max_flowrings);
+ max_flowrings = max_submissionrings -
+ BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
+ }
if (devinfo->dma_idx_sz != 0) {
- bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
+ bufsz = (max_submissionrings + max_completionrings) *
devinfo->dma_idx_sz * 2;
devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
&devinfo->idxbuf_dmahandle,
@@ -1083,14 +1114,10 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
}
if (devinfo->dma_idx_sz == 0) {
- addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
- d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
- addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
- d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
- addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
- h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
- addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
- h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+ d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr);
+ d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr);
+ h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr);
+ h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr);
idx_offset = sizeof(u32);
devinfo->write_ptr = brcmf_pcie_write_tcm16;
devinfo->read_ptr = brcmf_pcie_read_tcm16;
@@ -1103,34 +1130,42 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
devinfo->read_ptr = brcmf_pcie_read_idx;
h2d_w_idx_ptr = 0;
- addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
address = (u64)devinfo->idxbuf_dmahandle;
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
-
- h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
- addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
- address += max_sub_queues * idx_offset;
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
-
- d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
- addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
- address += max_sub_queues * idx_offset;
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+ ringinfo.h2d_w_idx_hostaddr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+ ringinfo.h2d_w_idx_hostaddr.high_addr =
+ cpu_to_le32(address >> 32);
+
+ h2d_r_idx_ptr = h2d_w_idx_ptr +
+ max_submissionrings * idx_offset;
+ address += max_submissionrings * idx_offset;
+ ringinfo.h2d_r_idx_hostaddr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+ ringinfo.h2d_r_idx_hostaddr.high_addr =
+ cpu_to_le32(address >> 32);
+
+ d2h_w_idx_ptr = h2d_r_idx_ptr +
+ max_submissionrings * idx_offset;
+ address += max_submissionrings * idx_offset;
+ ringinfo.d2h_w_idx_hostaddr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+ ringinfo.d2h_w_idx_hostaddr.high_addr =
+ cpu_to_le32(address >> 32);
d2h_r_idx_ptr = d2h_w_idx_ptr +
- BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
- addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
- address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+ max_completionrings * idx_offset;
+ address += max_completionrings * idx_offset;
+ ringinfo.d2h_r_idx_hostaddr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+ ringinfo.d2h_r_idx_hostaddr.high_addr =
+ cpu_to_le32(address >> 32);
+
+ memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr,
+ &ringinfo, sizeof(ringinfo));
brcmf_dbg(PCIE, "Using host memory indices\n");
}
- addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
- ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+ ring_mem_ptr = le32_to_cpu(ringinfo.ringmem);
for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
@@ -1161,20 +1196,19 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
ring_mem_ptr += BRCMF_RING_MEM_SZ;
}
- devinfo->shared.nrof_flowrings =
- max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
- rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
- GFP_KERNEL);
+ devinfo->shared.max_flowrings = max_flowrings;
+ devinfo->shared.max_submissionrings = max_submissionrings;
+ devinfo->shared.max_completionrings = max_completionrings;
+ rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL);
if (!rings)
goto fail;
- brcmf_dbg(PCIE, "Nr of flowrings is %d\n",
- devinfo->shared.nrof_flowrings);
+ brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings);
- for (i = 0; i < devinfo->shared.nrof_flowrings; i++) {
+ for (i = 0; i < max_flowrings; i++) {
ring = &rings[i];
ring->devinfo = devinfo;
- ring->id = i + BRCMF_NROF_COMMON_MSGRINGS;
+ ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
brcmf_commonring_register_cb(&ring->commonring,
brcmf_pcie_ring_mb_ring_bell,
brcmf_pcie_ring_mb_update_rptr,
@@ -1357,17 +1391,16 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
{
struct brcmf_pcie_shared_info *shared;
u32 addr;
- u32 version;
shared = &devinfo->shared;
shared->tcm_base_address = sharedram_addr;
shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
- version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK;
- brcmf_dbg(PCIE, "PCIe protocol version %d\n", version);
- if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
- (version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
- brcmf_err("Unsupported PCIE version %d\n", version);
+ shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK);
+ brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);
+ if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
+ (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
+ brcmf_err("Unsupported PCIE version %d\n", shared->version);
return -EINVAL;
}
@@ -1661,18 +1694,18 @@ static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw,
bus->msgbuf->commonrings[i] =
&devinfo->shared.commonrings[i]->commonring;
- flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings),
+ flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings),
GFP_KERNEL);
if (!flowrings)
goto fail;
- for (i = 0; i < devinfo->shared.nrof_flowrings; i++)
+ for (i = 0; i < devinfo->shared.max_flowrings; i++)
flowrings[i] = &devinfo->shared.flowrings[i].commonring;
bus->msgbuf->flowrings = flowrings;
bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
- bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings;
+ bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings;
init_waitqueue_head(&devinfo->mbdata_resp_wait);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
new file mode 100644
index 000000000000..f273cab0da10
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2016 Broadcom
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+
+#include "core.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "cfg80211.h"
+#include "pno.h"
+
+#define BRCMF_PNO_VERSION 2
+#define BRCMF_PNO_REPEAT 4
+#define BRCMF_PNO_FREQ_EXPO_MAX 3
+#define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3
+#define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5
+#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
+#define BRCMF_PNO_REPORT_SEPARATELY_BIT 11
+#define BRCMF_PNO_SCAN_INCOMPLETE 0
+#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
+#define BRCMF_PNO_HIDDEN_BIT 2
+#define BRCMF_PNO_SCHED_SCAN_PERIOD 30
+
+static int brcmf_pno_channel_config(struct brcmf_if *ifp,
+ struct brcmf_pno_config_le *cfg)
+{
+ cfg->reporttype = 0;
+ cfg->flags = 0;
+
+ return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg));
+}
+
+static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
+ u32 mscan, u32 bestn)
+{
+ struct brcmf_pno_param_le pfn_param;
+ u16 flags;
+ u32 pfnmem;
+ s32 err;
+
+ memset(&pfn_param, 0, sizeof(pfn_param));
+ pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
+
+ /* set extra pno params */
+ flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
+ BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) |
+ BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
+ pfn_param.repeat = BRCMF_PNO_REPEAT;
+ pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
+
+ /* set up pno scan fr */
+ if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
+ brcmf_dbg(SCAN, "scan period too small, using minimum\n");
+ scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
+ }
+ pfn_param.scan_freq = cpu_to_le32(scan_freq);
+
+ if (mscan) {
+ pfnmem = bestn;
+
+ /* set bestn in firmware */
+ err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem);
+ if (err < 0) {
+ brcmf_err("failed to set pfnmem\n");
+ goto exit;
+ }
+ /* get max mscan which the firmware supports */
+ err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem);
+ if (err < 0) {
+ brcmf_err("failed to get pfnmem\n");
+ goto exit;
+ }
+ mscan = min_t(u32, mscan, pfnmem);
+ pfn_param.mscan = mscan;
+ pfn_param.bestn = bestn;
+ flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT);
+ brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn);
+ }
+
+ pfn_param.flags = cpu_to_le16(flags);
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
+ sizeof(pfn_param));
+ if (err)
+ brcmf_err("pfn_set failed, err=%d\n", err);
+
+exit:
+ return err;
+}
+
+static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
+ u8 *mac_mask)
+{
+ struct brcmf_pno_macaddr_le pfn_mac;
+ int err, i;
+
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+ pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
+
+ memcpy(pfn_mac.mac, mac_addr, ETH_ALEN);
+ for (i = 0; i < ETH_ALEN; i++) {
+ pfn_mac.mac[i] &= mac_mask[i];
+ pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
+ }
+ /* Clear multi bit */
+ pfn_mac.mac[0] &= 0xFE;
+ /* Set locally administered */
+ pfn_mac.mac[0] |= 0x02;
+
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
+ sizeof(pfn_mac));
+ if (err)
+ brcmf_err("pfn_macaddr failed, err=%d\n", err);
+
+ return err;
+}
+
+static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
+ bool active)
+{
+ struct brcmf_pno_net_param_le pfn;
+
+ pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
+ pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
+ pfn.wsec = cpu_to_le32(0);
+ pfn.infra = cpu_to_le32(1);
+ if (active)
+ pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
+ pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
+ memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
+ return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+}
+
+static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
+ struct cfg80211_sched_scan_request *req)
+{
+ int i;
+
+ if (!ssid || !req->ssids || !req->n_ssids)
+ return false;
+
+ for (i = 0; i < req->n_ssids; i++) {
+ if (ssid->ssid_len == req->ssids[i].ssid_len) {
+ if (!strncmp(ssid->ssid, req->ssids[i].ssid,
+ ssid->ssid_len))
+ return true;
+ }
+ }
+ return false;
+}
+
+int brcmf_pno_clean(struct brcmf_if *ifp)
+{
+ int ret;
+
+ /* Disable pfn */
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
+ if (ret == 0) {
+ /* clear pfn */
+ ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
+ }
+ if (ret < 0)
+ brcmf_err("failed code %d\n", ret);
+
+ return ret;
+}
+
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct brcmu_d11inf *d11inf;
+ struct brcmf_pno_config_le pno_cfg;
+ struct cfg80211_ssid *ssid;
+ u16 chan;
+ int i, ret;
+
+ /* clean up everything */
+ ret = brcmf_pno_clean(ifp);
+ if (ret < 0) {
+ brcmf_err("failed error=%d\n", ret);
+ return ret;
+ }
+
+ /* configure pno */
+ ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ /* configure random mac */
+ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+ ret = brcmf_pno_set_random(ifp, req->mac_addr,
+ req->mac_addr_mask);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* configure channels to use */
+ d11inf = &ifp->drvr->config->d11inf;
+ for (i = 0; i < req->n_channels; i++) {
+ chan = req->channels[i]->hw_value;
+ pno_cfg.channel_list[i] = cpu_to_le16(chan);
+ }
+ if (req->n_channels) {
+ pno_cfg.channel_num = cpu_to_le32(req->n_channels);
+ brcmf_pno_channel_config(ifp, &pno_cfg);
+ }
+
+ /* configure each match set */
+ for (i = 0; i < req->n_match_sets; i++) {
+ ssid = &req->match_sets[i].ssid;
+ if (!ssid->ssid_len) {
+ brcmf_err("skip broadcast ssid\n");
+ continue;
+ }
+
+ ret = brcmf_pno_add_ssid(ifp, ssid,
+ brcmf_is_ssid_active(ssid, req));
+ if (ret < 0)
+ brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
+ ret == 0 ? "set" : "failed", ssid->ssid);
+ }
+ /* Enable the PNO */
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+ if (ret < 0)
+ brcmf_err("PNO enable failed!! ret=%d\n", ret);
+
+ return ret;
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
new file mode 100644
index 000000000000..bae55b2af78c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Broadcom
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMF_PNO_H
+#define _BRCMF_PNO_H
+
+#define BRCMF_PNO_SCAN_COMPLETE 1
+#define BRCMF_PNO_MAX_PFN_COUNT 16
+#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10
+#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508
+
+/**
+ * brcmf_pno_clean - disable and clear pno in firmware.
+ *
+ * @ifp: interface object used.
+ */
+int brcmf_pno_clean(struct brcmf_if *ifp);
+
+/**
+ * brcmf_pno_start_sched_scan - initiate scheduled scan on device.
+ *
+ * @ifp: interface object used.
+ * @req: configuration parameters for scheduled scan.
+ */
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+ struct cfg80211_sched_scan_request *req);
+
+#endif /* _BRCMF_PNO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
index 26b68c367f57..d26ff219ef66 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
@@ -51,7 +51,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
drvr->bus_if->proto_type);
goto fail;
}
- if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
+ if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
(proto->configure_addr_mode == NULL) ||
(proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
index 57531f42190e..34b59feedeba 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
@@ -33,6 +33,8 @@ struct brcmf_proto {
void *buf, uint len);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
uint len);
+ int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
+ struct sk_buff *skb);
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *skb);
void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
@@ -74,6 +76,13 @@ static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
{
return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
}
+
+static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+ struct sk_buff *skb)
+{
+ return drvr->proto->tx_queue_data(drvr, ifidx, skb);
+}
+
static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
u8 offset, struct sk_buff *skb)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index b892dac70f4b..dfb0658713d9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -621,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c
index faf1ebe76068..b9672da24a9d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c
@@ -179,7 +179,7 @@ s16 qm_norm32(s32 op)
return u16extraSignBits;
}
-/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
+/* This table is log2(1+(i/32)) where i=[0:1:32], in q.15 format */
static const s16 log_table[] = {
0,
1455,
@@ -212,7 +212,8 @@ static const s16 log_table[] = {
29717,
30498,
31267,
- 32024
+ 32024,
+ 32768
};
#define LOG_TABLE_SIZE 32 /* log_table size */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index d0407d9ad782..f1fb8a3c7a32 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -36,6 +36,7 @@
#define BRCM_CC_4330_CHIP_ID 0x4330
#define BRCM_CC_4334_CHIP_ID 0x4334
#define BRCM_CC_43340_CHIP_ID 43340
+#define BRCM_CC_43341_CHIP_ID 43341
#define BRCM_CC_43362_CHIP_ID 43362
#define BRCM_CC_4335_CHIP_ID 0x4335
#define BRCM_CC_4339_CHIP_ID 0x4339
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 69b826d229c5..4b040451a9b8 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -2329,14 +2329,6 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
return 0;
}
-static int airo_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > 2400))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static LIST_HEAD(airo_devices);
static void add_airo_dev(struct airo_info *ai)
@@ -2656,7 +2648,6 @@ static const struct net_device_ops airo11_netdev_ops = {
.ndo_get_stats = airo_get_stats,
.ndo_set_mac_address = airo_set_mac_address,
.ndo_do_ioctl = airo_ioctl,
- .ndo_change_mtu = airo_change_mtu,
};
static void wifi_setup(struct net_device *dev)
@@ -2668,6 +2659,8 @@ static void wifi_setup(struct net_device *dev)
dev->type = ARPHRD_IEEE80211;
dev->hard_header_len = ETH_HLEN;
dev->mtu = AIRO_DEF_MTU;
+ dev->min_mtu = 68;
+ dev->max_mtu = MIC_MSGLEN_MAX;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 100;
@@ -2754,7 +2747,6 @@ static const struct net_device_ops airo_netdev_ops = {
.ndo_set_rx_mode = airo_set_multicast_list,
.ndo_set_mac_address = airo_set_mac_address,
.ndo_do_ioctl = airo_ioctl,
- .ndo_change_mtu = airo_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -2766,7 +2758,6 @@ static const struct net_device_ops mpi_netdev_ops = {
.ndo_set_rx_mode = airo_set_multicast_list,
.ndo_set_mac_address = airo_set_mac_address,
.ndo_do_ioctl = airo_ioctl,
- .ndo_change_mtu = airo_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -2822,6 +2813,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
dev->irq = irq;
dev->base_addr = port;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ dev->max_mtu = MIC_MSGLEN_MAX;
SET_NETDEV_DEV(dev, dmdev);
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index bfa542c8d6f1..64176090b196 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -6035,7 +6035,6 @@ static const struct net_device_ops ipw2100_netdev_ops = {
.ndo_open = ipw2100_open,
.ndo_stop = ipw2100_close,
.ndo_start_xmit = libipw_xmit,
- .ndo_change_mtu = libipw_change_mtu,
.ndo_tx_timeout = ipw2100_tx_timeout,
.ndo_set_mac_address = ipw2100_set_address,
.ndo_validate_addr = eth_validate_addr,
@@ -6071,6 +6070,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->wireless_data = &priv->wireless_data;
dev->watchdog_timeo = 3 * HZ;
dev->irq = 0;
+ dev->min_mtu = 68;
+ dev->max_mtu = LIBIPW_DATA_LEN;
/* NOTE: We don't use the wireless_handlers hook
* in dev as the system will start throwing WX requests
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index bfd68612a535..ef9af8a29cad 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11561,7 +11561,6 @@ static const struct net_device_ops ipw_prom_netdev_ops = {
.ndo_open = ipw_prom_open,
.ndo_stop = ipw_prom_stop,
.ndo_start_xmit = ipw_prom_hard_start_xmit,
- .ndo_change_mtu = libipw_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -11587,6 +11586,9 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;
+ priv->prom_net_dev->min_mtu = 68;
+ priv->prom_net_dev->max_mtu = LIBIPW_DATA_LEN;
+
priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev);
@@ -11619,7 +11621,6 @@ static const struct net_device_ops ipw_netdev_ops = {
.ndo_set_rx_mode = ipw_net_set_multicast_list,
.ndo_set_mac_address = ipw_net_set_mac_address,
.ndo_start_xmit = libipw_xmit,
- .ndo_change_mtu = libipw_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -11729,6 +11730,9 @@ static int ipw_pci_probe(struct pci_dev *pdev,
net_dev->wireless_handlers = &ipw_wx_handler_def;
net_dev->ethtool_ops = &ipw_ethtool_ops;
+ net_dev->min_mtu = 68;
+ net_dev->max_mtu = LIBIPW_DATA_LEN;
+
err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
if (err) {
IPW_ERROR("failed to create sysfs device attributes\n");
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h
index b0571618c2ed..b51355134e04 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw.h
+++ b/drivers/net/wireless/intel/ipw2x00/libipw.h
@@ -948,7 +948,6 @@ static inline int libipw_is_cck_rate(u8 rate)
/* libipw.c */
void free_libipw(struct net_device *dev, int monitor);
struct net_device *alloc_libipw(int sizeof_priv, int monitor);
-int libipw_change_mtu(struct net_device *dev, int new_mtu);
void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs);
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
index 60f28740f6af..2332075565f2 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
@@ -118,15 +118,6 @@ static void libipw_networks_initialize(struct libipw_device *ieee)
&ieee->network_free_list);
}
-int libipw_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-EXPORT_SYMBOL(libipw_change_mtu);
-
struct net_device *alloc_libipw(int sizeof_priv, int monitor)
{
struct libipw_device *ieee;
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index cef7f7d79cd9..1c1ec7bb9302 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -507,7 +507,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
memcpy(dst, hdr->addr3, ETH_ALEN);
memcpy(src, hdr->addr4, ETH_ALEN);
break;
- case 0:
+ default:
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index ceec5ca2b1ab..1ad0ec180d5d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -293,6 +293,7 @@ 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_STA_PM_NOTIF: firmware will send STA PM notification
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -342,6 +343,7 @@ 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_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index acc5cd53e4ba..b530fa47d68a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -474,4 +474,30 @@ struct iwl_mvm_internal_rxq_notif {
u8 data[];
} __packed;
+/**
+ * enum iwl_mvm_pm_event - type of station PM event
+ * @IWL_MVM_PM_EVENT_AWAKE: station woke up
+ * @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep
+ * @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger
+ * @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll
+ */
+enum iwl_mvm_pm_event {
+ IWL_MVM_PM_EVENT_AWAKE,
+ IWL_MVM_PM_EVENT_ASLEEP,
+ IWL_MVM_PM_EVENT_UAPSD,
+ IWL_MVM_PM_EVENT_PS_POLL,
+}; /* PEER_PM_NTFY_API_E_VER_1 */
+
+/**
+ * struct iwl_mvm_pm_state_notification - station PM state notification
+ * @sta_id: station ID of the station changing state
+ * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
+ */
+struct iwl_mvm_pm_state_notification {
+ u8 sta_id;
+ u8 type;
+ /* private: */
+ u16 reserved;
+} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
+
#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 6c8e3ca79323..3b5150e9975d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -179,7 +179,7 @@ enum iwl_sta_key_flag {
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
* @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
- * @STA_MODIFY_TX_RATE: unused
+ * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_trigger_acs
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
@@ -189,7 +189,7 @@ enum iwl_sta_key_flag {
enum iwl_sta_modify_flag {
STA_MODIFY_QUEUE_REMOVAL = BIT(0),
STA_MODIFY_TID_DISABLE_TX = BIT(1),
- STA_MODIFY_TX_RATE = BIT(2),
+ STA_MODIFY_UAPSD_ACS = BIT(2),
STA_MODIFY_ADD_BA_TID = BIT(3),
STA_MODIFY_REMOVE_BA_TID = BIT(4),
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
@@ -353,6 +353,8 @@ struct iwl_mvm_add_sta_cmd_v7 {
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station
* @rx_ba_window: aggregation window size
+ * @scd_queue_bank: queue bank in used. Each bank contains 32 queues. 0 means
+ * that the queues used by this station are in the first 32.
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
@@ -382,7 +384,8 @@ struct iwl_mvm_add_sta_cmd {
__le16 beamform_flags;
__le32 tfd_queue_msk;
__le16 rx_ba_window;
- __le16 reserved;
+ u8 scd_queue_bank;
+ u8 uapsd_trigger_acs;
} __packed; /* ADD_STA_CMD_API_S_VER_8 */
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 97633690f3d5..ae12badc0c2a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -332,6 +332,7 @@ enum iwl_data_path_subcmd_ids {
DQA_ENABLE_CMD = 0x0,
UPDATE_MU_GROUPS_CMD = 0x1,
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
+ STA_PM_NOTIF = 0xFD,
MU_GROUP_MGMT_NOTIF = 0xFE,
RX_QUEUES_NOTIFICATION = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index d89d0a1fd34e..2e8e3e8e30a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -70,49 +70,6 @@
#include "iwl-prph.h"
#include "iwl-csr.h"
-static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
- void *data, size_t datalen)
-{
- const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
- ssize_t bytes_read;
- ssize_t bytes_read_trans;
-
- if (offset < dump_ptrs->op_mode_len) {
- bytes_read = min_t(ssize_t, count,
- dump_ptrs->op_mode_len - offset);
- memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
- bytes_read);
- offset += bytes_read;
- count -= bytes_read;
-
- if (count == 0)
- return bytes_read;
- } else {
- bytes_read = 0;
- }
-
- if (!dump_ptrs->trans_ptr)
- return bytes_read;
-
- offset -= dump_ptrs->op_mode_len;
- bytes_read_trans = min_t(ssize_t, count,
- dump_ptrs->trans_ptr->len - offset);
- memcpy(buffer + bytes_read,
- (u8 *)dump_ptrs->trans_ptr->data + offset,
- bytes_read_trans);
-
- return bytes_read + bytes_read_trans;
-}
-
-static void iwl_mvm_free_coredump(void *data)
-{
- const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
-
- vfree(fw_error_dump->op_mode_ptr);
- vfree(fw_error_dump->trans_ptr);
- kfree(fw_error_dump);
-}
-
#define RADIO_REG_MAX_READ 0x2ad
static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm,
struct iwl_fw_error_dump_data **dump_data)
@@ -491,6 +448,43 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
return prph_len;
}
+/*
+ * alloc_sgtable - allocates scallerlist table in the given size,
+ * fills it with pages and returns it
+ * @size: the size (in bytes) of the table
+*/
+static struct scatterlist *alloc_sgtable(int size)
+{
+ int alloc_size, nents, i;
+ struct page *new_page;
+ struct scatterlist *iter;
+ struct scatterlist *table;
+
+ nents = DIV_ROUND_UP(size, PAGE_SIZE);
+ table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+ sg_init_table(table, nents);
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = alloc_page(GFP_KERNEL);
+ if (!new_page) {
+ /* release all previous allocated pages in the table */
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = sg_page(iter);
+ if (new_page)
+ __free_page(new_page);
+ }
+ return NULL;
+ }
+ alloc_size = min_t(int, size, PAGE_SIZE);
+ size -= PAGE_SIZE;
+ sg_set_page(iter, new_page, alloc_size, 0);
+ }
+ return table;
+}
+
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{
struct iwl_fw_error_dump_file *dump_file;
@@ -499,6 +493,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_mem *dump_mem;
struct iwl_fw_error_dump_trigger_desc *dump_trig;
struct iwl_mvm_dump_ptrs *fw_error_dump;
+ struct scatterlist *sg_dump_data;
u32 sram_len, sram_ofs;
struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem =
mvm->fw->dbg_mem_tlv;
@@ -815,8 +810,23 @@ dump_trans_data:
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
- dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
- GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
+ sg_dump_data = alloc_sgtable(file_len);
+ if (sg_dump_data) {
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->op_mode_ptr,
+ fw_error_dump->op_mode_len, 0);
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->trans_ptr->data,
+ fw_error_dump->trans_ptr->len,
+ fw_error_dump->op_mode_len);
+ dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
+ GFP_KERNEL);
+ }
+ vfree(fw_error_dump->op_mode_ptr);
+ vfree(fw_error_dump->trans_ptr);
+ kfree(fw_error_dump);
out:
iwl_mvm_free_fw_dump_desc(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 6b962d6b067a..4a0874e40731 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -499,23 +499,21 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;
+ /* If DQA is supported - queues will be enabled when needed */
+ if (iwl_mvm_is_dqa_supported(mvm))
+ return 0;
+
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
- if (!iwl_mvm_is_dqa_supported(mvm))
- iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_TX_FIFO_VO, 0,
- wdg_timeout);
+ iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
+ 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, vif->cab_queue,
IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
/* fall through */
default:
- /* If DQA is supported - queues will be enabled when needed */
- if (iwl_mvm_is_dqa_supported(mvm))
- break;
-
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
vif->hw_queue[ac],
@@ -899,9 +897,11 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
- for (i = 0; i < IEEE80211_NUM_ACS; i++)
- if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
- tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ if (!iwl_mvm_is_dqa_supported(mvm)) {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+ tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ }
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 1db1dc13e988..45122dafe922 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -445,6 +445,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
if (iwl_mvm_has_new_rx_api(mvm))
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF))
+ ieee80211_hw_set(hw, AP_LINK_PS);
if (mvm->trans->num_rx_queues > 1)
ieee80211_hw_set(hw, USES_RSS);
@@ -2097,6 +2099,22 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unbind;
+ /* enable the multicast queue, now that we have a station for it */
+ if (iwl_mvm_is_dqa_supported(mvm)) {
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ struct iwl_trans_txq_scd_cfg cfg = {
+ .fifo = IWL_MVM_TX_FIFO_MCAST,
+ .sta_id = mvmvif->bcast_sta.sta_id,
+ .tid = IWL_MAX_TID_COUNT,
+ .aggregate = false,
+ .frame_limit = IWL_FRAME_LIMIT,
+ };
+
+ iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
+ &cfg, wdg_timeout);
+ }
+
/* must be set before quota calculations */
mvmvif->ap_ibss_active = true;
@@ -2318,10 +2336,9 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
tids, more_data, true);
}
-static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta)
+static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2374,6 +2391,67 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
spin_unlock_bh(&mvmsta->lock);
}
+static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
+{
+ __iwl_mvm_mac_sta_notify(hw, cmd, sta);
+}
+
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm_pm_state_notification *notif = (void *)pkt->data;
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+ bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
+
+ if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
+ return;
+
+ rcu_read_lock();
+ sta = mvm->fw_id_to_mac_id[notif->sta_id];
+ if (WARN_ON(IS_ERR_OR_NULL(sta))) {
+ rcu_read_unlock();
+ return;
+ }
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (!mvmsta->vif ||
+ mvmsta->vif->type != NL80211_IFTYPE_AP) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (mvmsta->sleeping != sleeping) {
+ mvmsta->sleeping = sleeping;
+ __iwl_mvm_mac_sta_notify(mvm->hw,
+ sleeping ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE,
+ sta);
+ ieee80211_sta_ps_transition(sta, sleeping);
+ }
+
+ if (sleeping) {
+ switch (notif->type) {
+ case IWL_MVM_PM_EVENT_AWAKE:
+ case IWL_MVM_PM_EVENT_ASLEEP:
+ break;
+ case IWL_MVM_PM_EVENT_UAPSD:
+ ieee80211_sta_uapsd_trigger(sta, IEEE80211_NUM_TIDS);
+ break;
+ case IWL_MVM_PM_EVENT_PS_POLL:
+ ieee80211_sta_pspoll(sta);
+ break;
+ default:
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+}
+
static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index c60703e0c246..4a9cb76b7611 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1112,9 +1112,8 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
{
- /* Make sure DQA isn't allowed in driver until feature is complete */
- return false && fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
+ return fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
}
static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
@@ -1419,6 +1418,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4d35deb628bc..f14aada390c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -306,6 +306,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC),
RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC),
+ RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF,
+ iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC),
};
#undef RX_HANDLER
#undef RX_HANDLER_GRP
@@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
+ HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index fc771885e383..636c8b03e318 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -202,6 +202,20 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |=
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
+ add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);
+
+ if (sta->wme) {
+ add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
+
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
+ }
status = ADD_STA_SUCCESS;
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
@@ -875,12 +889,17 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
- if (ret)
+ if (ret) {
IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n",
queue, ret);
- else
- IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
- queue, tid);
+ return;
+ }
+
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[queue].txq_tid = tid;
+ spin_unlock_bh(&mvm->queue_info_lock);
+ IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
+ queue, tid);
}
static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
@@ -1010,6 +1029,7 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm,
local_bh_disable();
spin_lock(&mvmsta->lock);
skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx);
+ mvmsta->deferred_traffic_tid_map &= ~BIT(tid);
spin_unlock(&mvmsta->lock);
while ((skb = __skb_dequeue(&deferred_tx)))
@@ -1489,12 +1509,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
/* If DQA is supported - the queues can be disabled now */
- if (iwl_mvm_is_dqa_supported(mvm)) {
+ if (iwl_mvm_is_dqa_supported(mvm))
+ iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
+
+ /* If there is a TXQ still marked as reserved - free it */
+ if (iwl_mvm_is_dqa_supported(mvm) &&
+ mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
u8 reserved_txq = mvm_sta->reserved_queue;
enum iwl_mvm_queue_status *status;
- iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
-
/*
* If no traffic has gone through the reserved TXQ - it
* is still marked as IWL_MVM_QUEUE_RESERVED, and
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index e068d5355865..b45c7b9937c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -436,6 +436,7 @@ struct iwl_mvm_sta {
bool disable_tx;
bool tlc_amsdu;
+ bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
u8 avg_energy;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index ae95533e587d..b10e3633df1a 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1598,6 +1598,29 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
}
}
+static const char *queue_name(struct device *dev,
+ struct iwl_trans_pcie *trans_p, int i)
+{
+ if (trans_p->shared_vec_mask) {
+ int vec = trans_p->shared_vec_mask &
+ IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
+
+ if (i == 0)
+ return DRV_NAME ": shared IRQ";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i + vec);
+ }
+ if (i == 0)
+ return DRV_NAME ": default queue";
+
+ if (i == trans_p->alloc_vecs - 1)
+ return DRV_NAME ": exception";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i);
+}
+
static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
struct iwl_trans_pcie *trans_pcie)
{
@@ -1606,6 +1629,10 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
for (i = 0; i < trans_pcie->alloc_vecs; i++) {
int ret;
struct msix_entry *msix_entry;
+ const char *qname = queue_name(&pdev->dev, trans_pcie, i);
+
+ if (!qname)
+ return -ENOMEM;
msix_entry = &trans_pcie->msix_entries[i];
ret = devm_request_threaded_irq(&pdev->dev,
@@ -1615,7 +1642,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
iwl_pcie_irq_msix_handler :
iwl_pcie_irq_rx_msix_handler,
IRQF_SHARED,
- DRV_NAME,
+ qname,
msix_entry);
if (ret) {
IWL_ERR(trans_pcie->trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 5f840f16f40b..e44e5adc2b95 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -2196,7 +2196,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
memcpy(skb_put(csum_skb, tcp_hdrlen(skb)),
tcph, tcp_hdrlen(skb));
- skb_set_transport_header(csum_skb, 0);
+ skb_reset_transport_header(csum_skb);
csum_skb->csum_start =
(unsigned char *)tcp_hdr(csum_skb) -
csum_skb->head;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
index 599f30f22841..34dbddbf3f9b 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
@@ -855,7 +855,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
memcpy(dst, hdr->addr3, ETH_ALEN);
memcpy(src, hdr->addr4, ETH_ALEN);
break;
- case 0:
+ default:
memcpy(dst, hdr->addr1, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
break;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c
index 80d4228ba754..1a16b8cb366e 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_main.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_main.c
@@ -765,16 +765,6 @@ static void hostap_set_multicast_list(struct net_device *dev)
}
-static int prism2_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
-
static void prism2_tx_timeout(struct net_device *dev)
{
struct hostap_interface *iface;
@@ -813,7 +803,6 @@ static const struct net_device_ops hostap_netdev_ops = {
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
.ndo_set_rx_mode = hostap_set_multicast_list,
- .ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
};
@@ -826,7 +815,6 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
.ndo_set_rx_mode = hostap_set_multicast_list,
- .ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
};
@@ -839,7 +827,6 @@ static const struct net_device_ops hostap_master_ops = {
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
.ndo_set_rx_mode = hostap_set_multicast_list,
- .ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
};
@@ -851,6 +838,8 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
iface = netdev_priv(dev);
ether_setup(dev);
+ dev->min_mtu = PRISM2_MIN_MTU;
+ dev->max_mtu = PRISM2_MAX_MTU;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
/* kernel callbacks */
diff --git a/drivers/net/wireless/intersil/orinoco/main.c b/drivers/net/wireless/intersil/orinoco/main.c
index 7afe2004e930..9d96b7c928f7 100644
--- a/drivers/net/wireless/intersil/orinoco/main.c
+++ b/drivers/net/wireless/intersil/orinoco/main.c
@@ -322,9 +322,6 @@ int orinoco_change_mtu(struct net_device *dev, int new_mtu)
{
struct orinoco_private *priv = ndev_priv(dev);
- if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU))
- return -EINVAL;
-
/* MTU + encapsulation + header length */
if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
(priv->nicbuf_size - ETH_HLEN))
@@ -2288,6 +2285,9 @@ int orinoco_if_add(struct orinoco_private *priv,
dev->base_addr = base_addr;
dev->irq = irq;
+ dev->min_mtu = ORINOCO_MIN_MTU;
+ dev->max_mtu = ORINOCO_MAX_MTU;
+
SET_NETDEV_DEV(dev, priv->dev);
ret = register_netdev(dev);
if (ret)
diff --git a/drivers/net/wireless/intersil/p54/fwio.c b/drivers/net/wireless/intersil/p54/fwio.c
index 257a9eadd595..4ac6764f4897 100644
--- a/drivers/net/wireless/intersil/p54/fwio.c
+++ b/drivers/net/wireless/intersil/p54/fwio.c
@@ -488,7 +488,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
entry += sizeof(__le16);
chan->pa_points_per_curve = 8;
- memset(chan->curve_data, 0, sizeof(*chan->curve_data));
+ memset(chan->curve_data, 0, sizeof(chan->curve_data));
memcpy(chan->curve_data, entry,
sizeof(struct p54_pa_curve_data_sample) *
min((u8)8, curve_data->points_per_channel));
diff --git a/drivers/net/wireless/intersil/prism54/islpci_dev.c b/drivers/net/wireless/intersil/prism54/islpci_dev.c
index 84a42012aeae..325176d4d796 100644
--- a/drivers/net/wireless/intersil/prism54/islpci_dev.c
+++ b/drivers/net/wireless/intersil/prism54/islpci_dev.c
@@ -808,7 +808,6 @@ static const struct net_device_ops islpci_netdev_ops = {
.ndo_start_xmit = islpci_eth_transmit,
.ndo_tx_timeout = islpci_eth_tx_timeout,
.ndo_set_mac_address = prism54_set_mac_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index d3bad5779376..1620a5d2757d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -250,7 +250,7 @@ static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
cp->magic = 0;
}
-static int hwsim_net_id;
+static unsigned int hwsim_net_id;
static int hwsim_netgroup;
@@ -587,15 +587,8 @@ struct hwsim_radiotap_ack_hdr {
__le16 rt_chbitmask;
} __packed;
-/* MAC80211_HWSIM netlinf family */
-static struct genl_family hwsim_genl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = "MAC80211_HWSIM",
- .version = 1,
- .maxattr = HWSIM_ATTR_MAX,
- .netnsok = true,
-};
+/* MAC80211_HWSIM netlink family */
+static struct genl_family hwsim_genl_family;
enum hwsim_multicast_groups {
HWSIM_MCGRP_CONFIG,
@@ -2256,35 +2249,51 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
}
+#define HWSIM_COMMON_OPS \
+ .tx = mac80211_hwsim_tx, \
+ .start = mac80211_hwsim_start, \
+ .stop = mac80211_hwsim_stop, \
+ .add_interface = mac80211_hwsim_add_interface, \
+ .change_interface = mac80211_hwsim_change_interface, \
+ .remove_interface = mac80211_hwsim_remove_interface, \
+ .config = mac80211_hwsim_config, \
+ .configure_filter = mac80211_hwsim_configure_filter, \
+ .bss_info_changed = mac80211_hwsim_bss_info_changed, \
+ .sta_add = mac80211_hwsim_sta_add, \
+ .sta_remove = mac80211_hwsim_sta_remove, \
+ .sta_notify = mac80211_hwsim_sta_notify, \
+ .set_tim = mac80211_hwsim_set_tim, \
+ .conf_tx = mac80211_hwsim_conf_tx, \
+ .get_survey = mac80211_hwsim_get_survey, \
+ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \
+ .ampdu_action = mac80211_hwsim_ampdu_action, \
+ .flush = mac80211_hwsim_flush, \
+ .get_tsf = mac80211_hwsim_get_tsf, \
+ .set_tsf = mac80211_hwsim_set_tsf, \
+ .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \
+ .get_et_stats = mac80211_hwsim_get_et_stats, \
+ .get_et_strings = mac80211_hwsim_get_et_strings,
+
static const struct ieee80211_ops mac80211_hwsim_ops = {
- .tx = mac80211_hwsim_tx,
- .start = mac80211_hwsim_start,
- .stop = mac80211_hwsim_stop,
- .add_interface = mac80211_hwsim_add_interface,
- .change_interface = mac80211_hwsim_change_interface,
- .remove_interface = mac80211_hwsim_remove_interface,
- .config = mac80211_hwsim_config,
- .configure_filter = mac80211_hwsim_configure_filter,
- .bss_info_changed = mac80211_hwsim_bss_info_changed,
- .sta_add = mac80211_hwsim_sta_add,
- .sta_remove = mac80211_hwsim_sta_remove,
- .sta_notify = mac80211_hwsim_sta_notify,
- .set_tim = mac80211_hwsim_set_tim,
- .conf_tx = mac80211_hwsim_conf_tx,
- .get_survey = mac80211_hwsim_get_survey,
- CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
- .ampdu_action = mac80211_hwsim_ampdu_action,
+ HWSIM_COMMON_OPS
.sw_scan_start = mac80211_hwsim_sw_scan,
.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
- .flush = mac80211_hwsim_flush,
- .get_tsf = mac80211_hwsim_get_tsf,
- .set_tsf = mac80211_hwsim_set_tsf,
- .get_et_sset_count = mac80211_hwsim_get_et_sset_count,
- .get_et_stats = mac80211_hwsim_get_et_stats,
- .get_et_strings = mac80211_hwsim_get_et_strings,
};
-static struct ieee80211_ops mac80211_hwsim_mchan_ops;
+static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {
+ HWSIM_COMMON_OPS
+ .hw_scan = mac80211_hwsim_hw_scan,
+ .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan,
+ .sw_scan_start = NULL,
+ .sw_scan_complete = NULL,
+ .remain_on_channel = mac80211_hwsim_roc,
+ .cancel_remain_on_channel = mac80211_hwsim_croc,
+ .add_chanctx = mac80211_hwsim_add_chanctx,
+ .remove_chanctx = mac80211_hwsim_remove_chanctx,
+ .change_chanctx = mac80211_hwsim_change_chanctx,
+ .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx,
+ .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx,
+};
struct hwsim_new_radio_params {
unsigned int channels;
@@ -2791,7 +2800,6 @@ static void mac80211_hwsim_free(void)
static const struct net_device_ops hwsim_netdev_ops = {
.ndo_start_xmit = hwsim_mon_xmit,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -3236,6 +3244,18 @@ static const struct genl_ops hwsim_ops[] = {
},
};
+static struct genl_family hwsim_genl_family __ro_after_init = {
+ .name = "MAC80211_HWSIM",
+ .version = 1,
+ .maxattr = HWSIM_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = hwsim_ops,
+ .n_ops = ARRAY_SIZE(hwsim_ops),
+ .mcgrps = hwsim_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
+};
+
static void destroy_radio(struct work_struct *work)
{
struct mac80211_hwsim_data *data =
@@ -3283,15 +3303,13 @@ static struct notifier_block hwsim_netlink_notifier = {
.notifier_call = mac80211_hwsim_netlink_notify,
};
-static int hwsim_init_netlink(void)
+static int __init hwsim_init_netlink(void)
{
int rc;
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
- rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
- hwsim_ops,
- hwsim_mcgrps);
+ rc = genl_register_family(&hwsim_genl_family);
if (rc)
goto failure;
@@ -3360,21 +3378,6 @@ static int __init init_mac80211_hwsim(void)
if (channels < 1)
return -EINVAL;
- mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
- mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
- mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
- mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
- mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
- mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
- mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
- mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
- mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
- mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
- mac80211_hwsim_mchan_ops.assign_vif_chanctx =
- mac80211_hwsim_assign_vif_chanctx;
- mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
- mac80211_hwsim_unassign_vif_chanctx;
-
spin_lock_init(&hwsim_radio_lock);
err = register_pernet_device(&hwsim_net_ops);
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c
index 8541cbed786d..e3500203715c 100644
--- a/drivers/net/wireless/marvell/libertas/main.c
+++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -945,7 +945,6 @@ static const struct net_device_ops lbs_netdev_ops = {
.ndo_start_xmit = lbs_hard_start_xmit,
.ndo_set_mac_address = lbs_set_mac_address,
.ndo_set_rx_mode = lbs_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/wireless/marvell/mwifiex/README b/drivers/net/wireless/marvell/mwifiex/README
index 24e649b1eb24..588fcbe38374 100644
--- a/drivers/net/wireless/marvell/mwifiex/README
+++ b/drivers/net/wireless/marvell/mwifiex/README
@@ -180,6 +180,29 @@ regrdwr
echo "1 0xa060 0x12" > regrdwr : Write the MAC register
echo "1 0xa794 0x80000000" > regrdwr
: Write 0x80000000 to MAC register
+
+memrw
+ This command is used to read/write the firmware memory.
+
+ Usage:
+ 1) For reading firmware memory location.
+ echo r <address> 0 > /sys/kernel/debug/mwifiex/mlan0/memrw
+ cat /sys/kernel/debug/mwifiex/mlan0/memrw
+ 2) For writing value to firmware memory location.
+ echo w <address> [value] > /sys/kernel/debug/mwifiex/mlan0/memrw
+
+ where the parameters are,
+ <address>: memory address
+ [value]: value to be written
+
+ Examples:
+ echo r 0x4cf70 0 > /sys/kernel/debug/mwifiex/mlan0/memrw
+ cat /sys/kernel/debug/mwifiex/mlan0/memrw
+ : Read memory address 0x4cf70
+ iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000
+ echo w 0x8000a000 0xc0000000 > /sys/kernel/debug/mwifiex/mlan0/memrw
+ : Write 0xc0000000 to memory address 0x8000a000
+
rdeeprom
This command is used to read the EEPROM contents of the card.
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 16241d21727b..145cc4b5103b 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1203,6 +1203,12 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
priv->adapter->curr_iface_comb.p2p_intf--;
priv->adapter->curr_iface_comb.sta_intf++;
dev->ieee80211_ptr->iftype = type;
+ if (mwifiex_deinit_priv_params(priv))
+ return -1;
+ if (mwifiex_init_new_priv_params(priv, dev, type))
+ return -1;
+ if (mwifiex_sta_init_cmd(priv, false, false))
+ return -1;
break;
case NL80211_IFTYPE_ADHOC:
if (mwifiex_cfg80211_deinit_p2p(priv))
@@ -2137,6 +2143,16 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
if (mode == NL80211_IFTYPE_ADHOC) {
+ u16 enable = true;
+
+ /* set ibss coalescing_status */
+ ret = mwifiex_send_cmd(
+ priv,
+ HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+ HostCmd_ACT_GEN_SET, 0, &enable, true);
+ if (ret)
+ return ret;
+
/* "privacy" is set only for ad-hoc mode */
if (privacy) {
/*
@@ -3017,6 +3033,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->netdev = NULL;
memset(&priv->wdev, 0, sizeof(priv->wdev));
priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ destroy_workqueue(priv->dfs_cac_workqueue);
+ priv->dfs_cac_workqueue = NULL;
return ERR_PTR(-ENOMEM);
}
@@ -3071,8 +3089,10 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
- skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+ skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
+ skb_unlink(skb, &priv->bypass_txq);
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+ }
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
@@ -3971,13 +3991,11 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
struct mwifiex_ds_misc_cmd *hostcmd;
struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1];
- struct mwifiex_adapter *adapter;
struct sk_buff *skb;
int err;
if (!priv)
return -EINVAL;
- adapter = priv->adapter;
err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len,
mwifiex_tm_policy);
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 53477280f39c..25a7475702f7 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1118,13 +1118,14 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
void
mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
{
- if (!adapter->cmd_sent &&
+ if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) &&
!adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
mwifiex_dnld_sleep_confirm_cmd(adapter);
else
mwifiex_dbg(adapter, CMD,
- "cmd: Delay Sleep Confirm (%s%s%s)\n",
+ "cmd: Delay Sleep Confirm (%s%s%s%s)\n",
(adapter->cmd_sent) ? "D" : "",
+ atomic_read(&adapter->tx_hw_pending) ? "T" : "",
(adapter->curr_cmd) ? "C" : "",
(IS_CARD_RX_RCVD(adapter)) ? "R" : "");
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 4b1894b4757f..ea455948a68a 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -181,6 +181,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_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 176)
+#define TLV_TYPE_PS_PARAMS_IN_HS (PROPRIETARY_TLV_BASE_ID + 181)
#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)
@@ -218,6 +219,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15))
#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
+#define ISSUPP_ADHOC_ENABLED(FwCapInfo) (FwCapInfo & BIT(25))
#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
@@ -986,6 +988,15 @@ struct mwifiex_ps_param {
__le16 delay_to_ps;
};
+#define HS_DEF_WAKE_INTERVAL 100
+#define HS_DEF_INACTIVITY_TIMEOUT 50
+
+struct mwifiex_ps_param_in_hs {
+ struct mwifiex_ie_types_header header;
+ __le32 hs_wake_int;
+ __le32 hs_inact_timeout;
+};
+
#define BITMAP_AUTO_DS 0x01
#define BITMAP_STA_PS 0x10
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 82839d9f079f..b36cb3fef358 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -270,6 +270,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->adhoc_11n_enabled = false;
mwifiex_wmm_init(adapter);
+ atomic_set(&adapter->tx_hw_pending, 0);
sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
adapter->sleep_cfm->data;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2478ccd6f2d9..e5c3a8aa3929 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -308,6 +308,9 @@ process_start:
/* We have tried to wakeup the card already */
if (adapter->pm_wakeup_fw_try)
break;
+ if (adapter->ps_state == PS_STATE_PRE_SLEEP)
+ mwifiex_check_ps_cond(adapter);
+
if (adapter->ps_state != PS_STATE_AWAKE)
break;
if (adapter->tx_lock_flag) {
@@ -355,10 +358,8 @@ process_start:
/* Check if we need to confirm Sleep Request
received previously */
- if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
- if (!adapter->cmd_sent && !adapter->curr_cmd)
- mwifiex_check_ps_cond(adapter);
- }
+ if (adapter->ps_state == PS_STATE_PRE_SLEEP)
+ mwifiex_check_ps_cond(adapter);
/* * The ps_state may have been changed during processing of
* Sleep Request event.
@@ -517,12 +518,11 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
int ret;
char fmt[64];
- struct mwifiex_private *priv;
struct mwifiex_adapter *adapter = context;
struct mwifiex_fw_image fw;
- struct semaphore *sem = adapter->card_sem;
bool init_failed = false;
struct wireless_dev *wdev;
+ struct completion *fw_done = adapter->fw_done;
if (!firmware) {
mwifiex_dbg(adapter, ERROR,
@@ -575,8 +575,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
goto err_init_fw;
}
- priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
-
if (!adapter->wiphy) {
if (mwifiex_register_cfg80211(adapter)) {
mwifiex_dbg(adapter, ERROR,
@@ -669,7 +667,8 @@ done:
}
if (init_failed)
mwifiex_free_adapter(adapter);
- up(sem);
+ /* Tell all current and future waiters we're finished */
+ complete_all(fw_done);
return;
}
@@ -1364,7 +1363,7 @@ static void mwifiex_main_work_queue(struct work_struct *work)
* code is extracted from mwifiex_remove_card()
*/
static int
-mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
+mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
{
struct mwifiex_private *priv;
int i;
@@ -1372,8 +1371,9 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
if (!adapter)
goto exit_return;
- if (down_interruptible(sem))
- goto exit_sem_err;
+ wait_for_completion(adapter->fw_done);
+ /* Caller should ensure we aren't suspending while this happens */
+ reinit_completion(adapter->fw_done);
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
mwifiex_deauthenticate(priv, NULL);
@@ -1430,8 +1430,6 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
rtnl_unlock();
}
- up(sem);
-exit_sem_err:
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
exit_return:
return 0;
@@ -1441,21 +1439,18 @@ exit_return:
* code is extracted from mwifiex_add_card()
*/
static int
-mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
+mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct completion *fw_done,
struct mwifiex_if_ops *if_ops, u8 iface_type)
{
char fw_name[32];
struct pcie_service_card *card = adapter->card;
- if (down_interruptible(sem))
- goto exit_sem_err;
-
mwifiex_init_lock_list(adapter);
if (adapter->if_ops.up_dev)
adapter->if_ops.up_dev(adapter);
adapter->iface_type = iface_type;
- adapter->card_sem = sem;
+ adapter->fw_done = fw_done;
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
@@ -1506,7 +1501,8 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
}
strcpy(adapter->fw_name, fw_name);
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
- up(sem);
+
+ complete_all(adapter->fw_done);
return 0;
err_init_fw:
@@ -1526,8 +1522,7 @@ err_init_fw:
err_kmalloc:
mwifiex_terminate_workqueue(adapter);
adapter->surprise_removed = true;
- up(sem);
-exit_sem_err:
+ complete_all(adapter->fw_done);
mwifiex_dbg(adapter, INFO, "%s, error\n", __func__);
return -1;
@@ -1542,16 +1537,67 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
struct mwifiex_if_ops if_ops;
if (!prepare) {
- mwifiex_reinit_sw(adapter, adapter->card_sem, &if_ops,
+ mwifiex_reinit_sw(adapter, adapter->fw_done, &if_ops,
adapter->iface_type);
} else {
memcpy(&if_ops, &adapter->if_ops,
sizeof(struct mwifiex_if_ops));
- mwifiex_shutdown_sw(adapter, adapter->card_sem);
+ mwifiex_shutdown_sw(adapter);
}
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv)
+{
+ struct mwifiex_adapter *adapter = priv;
+
+ if (adapter->irq_wakeup >= 0) {
+ dev_dbg(adapter->dev, "%s: wake by wifi", __func__);
+ adapter->wake_by_wifi = true;
+ disable_irq_nosync(irq);
+ }
+
+ /* Notify PM core we are wakeup source */
+ pm_wakeup_event(adapter->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
+static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
+{
+ int ret;
+ struct device *dev = adapter->dev;
+
+ if (!dev->of_node)
+ return;
+
+ adapter->dt_node = dev->of_node;
+ adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0);
+ if (!adapter->irq_wakeup) {
+ dev_info(dev, "fail to parse irq_wakeup from device tree\n");
+ return;
+ }
+
+ ret = devm_request_irq(dev, adapter->irq_wakeup,
+ mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+ "wifi_wake", adapter);
+ if (ret) {
+ dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
+ adapter->irq_wakeup, ret);
+ goto err_exit;
+ }
+
+ disable_irq(adapter->irq_wakeup);
+ if (device_init_wakeup(dev, true)) {
+ dev_err(dev, "fail to init wakeup for mwifiex\n");
+ goto err_exit;
+ }
+ return;
+
+err_exit:
+ adapter->irq_wakeup = 0;
+}
+
/*
* This function adds the card.
*
@@ -1566,21 +1612,22 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
* - Add logical interfaces
*/
int
-mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops, u8 iface_type)
+mwifiex_add_card(void *card, struct completion *fw_done,
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev)
{
struct mwifiex_adapter *adapter;
- if (down_interruptible(sem))
- goto exit_sem_err;
-
if (mwifiex_register(card, if_ops, (void **)&adapter)) {
pr_err("%s: software init failed\n", __func__);
goto err_init_sw;
}
+ adapter->dev = dev;
+ mwifiex_probe_of(adapter);
+
adapter->iface_type = iface_type;
- adapter->card_sem = sem;
+ adapter->fw_done = fw_done;
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
@@ -1649,9 +1696,7 @@ err_kmalloc:
mwifiex_free_adapter(adapter);
err_init_sw:
- up(sem);
-exit_sem_err:
return -1;
}
EXPORT_SYMBOL_GPL(mwifiex_add_card);
@@ -1667,14 +1712,11 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card);
* - Unregister the device
* - Free the adapter structure
*/
-int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
+int mwifiex_remove_card(struct mwifiex_adapter *adapter)
{
struct mwifiex_private *priv = NULL;
int i;
- if (down_trylock(sem))
- goto exit_sem_err;
-
if (!adapter)
goto exit_remove;
@@ -1744,8 +1786,6 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
mwifiex_free_adapter(adapter);
exit_remove:
- up(sem);
-exit_sem_err:
return 0;
}
EXPORT_SYMBOL_GPL(mwifiex_remove_card);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 26df28f4bfb2..5c9bd944b6ea 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -20,6 +20,7 @@
#ifndef _MWIFIEX_MAIN_H_
#define _MWIFIEX_MAIN_H_
+#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -315,6 +316,7 @@ struct mwifiex_tid_tbl {
#define WMM_HIGHEST_PRIORITY 7
#define HIGH_PRIO_TID 7
#define LOW_PRIO_TID 0
+#define NO_PKT_PRIO_TID -1
#define MWIFIEX_WMM_DRV_DELAY_MAX 510
struct mwifiex_wmm_desc {
@@ -856,6 +858,7 @@ struct mwifiex_adapter {
atomic_t rx_pending;
atomic_t tx_pending;
atomic_t cmd_pending;
+ atomic_t tx_hw_pending;
struct workqueue_struct *workqueue;
struct work_struct main_work;
struct workqueue_struct *rx_workqueue;
@@ -983,7 +986,10 @@ struct mwifiex_adapter {
u32 usr_dot_11ac_mcs_support;
atomic_t pending_bridged_pkts;
- struct semaphore *card_sem;
+
+ /* For synchronizing FW initialization with device lifecycle. */
+ struct completion *fw_done;
+
bool ext_scan;
u8 fw_api_ver;
u8 key_api_major_ver, key_api_minor_ver;
@@ -1010,6 +1016,10 @@ struct mwifiex_adapter {
bool usb_mc_setup;
struct cfg80211_wowlan_nd_info *nd_info;
struct ieee80211_regdomain *regd;
+
+ /* Wake-on-WLAN (WoWLAN) */
+ int irq_wakeup;
+ bool wake_by_wifi;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1409,10 +1419,39 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
return false;
}
+/* Disable platform specific wakeup interrupt */
+static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter)
+{
+ if (adapter->irq_wakeup >= 0) {
+ disable_irq_wake(adapter->irq_wakeup);
+ disable_irq(adapter->irq_wakeup);
+ if (adapter->wake_by_wifi)
+ /* Undo our disable, since interrupt handler already
+ * did this.
+ */
+ enable_irq(adapter->irq_wakeup);
+
+ }
+}
+
+/* Enable platform specific wakeup interrupt */
+static inline void mwifiex_enable_wake(struct mwifiex_adapter *adapter)
+{
+ /* Enable platform specific wakeup interrupt */
+ if (adapter->irq_wakeup >= 0) {
+ adapter->wake_by_wifi = false;
+ enable_irq(adapter->irq_wakeup);
+ enable_irq_wake(adapter->irq_wakeup);
+ }
+}
+
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
-int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
+
+int mwifiex_add_card(void *card, struct completion *fw_done,
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev);
+int mwifiex_remove_card(struct mwifiex_adapter *adapter);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
int maxlen);
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 3c3c4f197da8..4db07da81d8d 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -35,7 +35,21 @@ static u8 user_rmmod;
static struct mwifiex_if_ops pcie_ops;
-static struct semaphore add_remove_card_sem;
+static const struct of_device_id mwifiex_pcie_of_match_table[] = {
+ { .compatible = "pci11ab,2b42" },
+ { .compatible = "pci1b4b,2b42" },
+ { }
+};
+
+static int mwifiex_pcie_probe_of(struct device *dev)
+{
+ if (!of_match_node(mwifiex_pcie_of_match_table, dev->of_node)) {
+ dev_err(dev, "required compatible string missing\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
static int
mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -101,23 +115,31 @@ static int mwifiex_pcie_suspend(struct device *dev)
{
struct mwifiex_adapter *adapter;
struct pcie_service_card *card;
- int hs_actived;
struct pci_dev *pdev = to_pci_dev(dev);
- if (pdev) {
- card = pci_get_drvdata(pdev);
- if (!card || !card->adapter) {
- pr_err("Card or adapter structure is not valid\n");
- return 0;
- }
- } else {
- pr_err("PCIE device is not specified\n");
+ card = pci_get_drvdata(pdev);
+
+ /* Might still be loading firmware */
+ wait_for_completion(&card->fw_done);
+
+ adapter = card->adapter;
+ if (!adapter) {
+ dev_err(dev, "adapter is not valid\n");
return 0;
}
- adapter = card->adapter;
+ mwifiex_enable_wake(adapter);
+
+ /* Enable the Host Sleep */
+ if (!mwifiex_enable_hs(adapter)) {
+ mwifiex_dbg(adapter, ERROR,
+ "cmd: failed to suspend\n");
+ adapter->hs_enabling = false;
+ mwifiex_disable_wake(adapter);
+ return -EFAULT;
+ }
- hs_actived = mwifiex_enable_hs(adapter);
+ flush_workqueue(adapter->workqueue);
/* Indicate device suspended */
adapter->is_suspended = true;
@@ -140,14 +162,10 @@ static int mwifiex_pcie_resume(struct device *dev)
struct pcie_service_card *card;
struct pci_dev *pdev = to_pci_dev(dev);
- if (pdev) {
- card = pci_get_drvdata(pdev);
- if (!card || !card->adapter) {
- pr_err("Card or adapter structure is not valid\n");
- return 0;
- }
- } else {
- pr_err("PCIE device is not specified\n");
+ card = pci_get_drvdata(pdev);
+
+ if (!card->adapter) {
+ dev_err(dev, "adapter structure is not valid\n");
return 0;
}
@@ -163,6 +181,7 @@ static int mwifiex_pcie_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_ASYNC_CMD);
+ mwifiex_disable_wake(adapter);
return 0;
}
@@ -178,14 +197,17 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pcie_service_card *card;
+ int ret;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
pdev->vendor, pdev->device, pdev->revision);
- card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
+ card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
+ init_completion(&card->fw_done);
+
card->dev = pdev;
if (ent->driver_data) {
@@ -199,8 +221,15 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
card->pcie.can_ext_scan = data->can_ext_scan;
}
- if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE)) {
+ /* device tree node parsing and platform specific configuration*/
+ if (pdev->dev.of_node) {
+ ret = mwifiex_pcie_probe_of(&pdev->dev);
+ if (ret)
+ return ret;
+ }
+
+ if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
+ MWIFIEX_PCIE, &pdev->dev)) {
pr_err("%s failed\n", __func__);
return -1;
}
@@ -218,19 +247,14 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
struct mwifiex_private *priv;
card = pci_get_drvdata(pdev);
- if (!card)
- return;
+
+ wait_for_completion(&card->fw_done);
adapter = card->adapter;
if (!adapter || !adapter->priv_num)
return;
if (user_rmmod && !adapter->mfg_mode) {
-#ifdef CONFIG_PM_SLEEP
- if (adapter->is_suspended)
- mwifiex_pcie_resume(&pdev->dev);
-#endif
-
mwifiex_deauthenticate_all(adapter);
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
@@ -240,7 +264,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
}
- mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+ mwifiex_remove_card(adapter);
}
static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
@@ -483,6 +507,7 @@ static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
}
}
+ atomic_set(&adapter->tx_hw_pending, 0);
return 0;
}
@@ -682,6 +707,7 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
card->tx_buf_list[i] = NULL;
}
+ atomic_set(&adapter->tx_hw_pending, 0);
return;
}
@@ -1119,6 +1145,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
-1);
else
mwifiex_write_data_complete(adapter, skb, 0, 0);
+ atomic_dec(&adapter->tx_hw_pending);
}
card->tx_buf_list[wrdoneidx] = NULL;
@@ -1211,6 +1238,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
card->tx_buf_list[wrindx] = skb;
+ atomic_inc(&adapter->tx_hw_pending);
if (reg->pfu_enabled) {
desc2 = card->txbd_ring[wrindx];
@@ -1288,6 +1316,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
done_unmap:
mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
card->tx_buf_list[wrindx] = NULL;
+ atomic_dec(&adapter->tx_hw_pending);
if (reg->pfu_enabled)
memset(desc2, 0, sizeof(*desc2));
else
@@ -1669,9 +1698,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
if (!adapter->curr_cmd) {
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
- mwifiex_process_sleep_confirm_resp(adapter, skb->data,
- skb->len);
- mwifiex_pcie_enable_host_int(adapter);
if (mwifiex_write_reg(adapter,
PCIE_CPU_INT_EVENT,
CPU_INTR_SLEEP_CFM_DONE)) {
@@ -1684,6 +1710,9 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
while (reg->sleep_cookie && (count++ < 10) &&
mwifiex_pcie_ok_to_access_hw(adapter))
usleep_range(50, 60);
+ mwifiex_pcie_enable_host_int(adapter);
+ mwifiex_process_sleep_confirm_resp(adapter, skb->data,
+ skb->len);
} else {
mwifiex_dbg(adapter, ERROR,
"There is no command but got cmdrsp\n");
@@ -2022,7 +2051,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
}
/* Wait for the command done interrupt */
- do {
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
&ireg_intr)) {
mwifiex_dbg(adapter, ERROR,
@@ -2034,8 +2063,18 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
ret = -1;
goto done;
}
- } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
- CPU_INTR_DOOR_BELL);
+ if (!(ireg_intr & CPU_INTR_DOOR_BELL))
+ break;
+ usleep_range(10, 20);
+ }
+ if (ireg_intr & CPU_INTR_DOOR_BELL) {
+ mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n",
+ __func__);
+ mwifiex_unmap_pci_memory(adapter, skb,
+ PCI_DMA_TODEVICE);
+ ret = -1;
+ goto done;
+ }
mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
@@ -2210,7 +2249,8 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
}
card = pci_get_drvdata(pdev);
- if (!card || !card->adapter) {
+
+ if (!card->adapter) {
pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
card ? card->adapter : NULL);
goto exit;
@@ -2322,6 +2362,8 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
ret = mwifiex_pcie_process_cmd_complete(adapter);
if (ret)
return ret;
+ if (adapter->hs_activated)
+ return ret;
}
if (card->msi_enable) {
@@ -2806,7 +2848,6 @@ err_req_region0:
err_set_dma_mask:
pci_disable_device(pdev);
err_enable_dev:
- pci_set_drvdata(pdev, NULL);
return ret;
}
@@ -2840,9 +2881,7 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
pci_disable_device(pdev);
pci_release_region(pdev, 2);
pci_release_region(pdev, 0);
- pci_set_drvdata(pdev, NULL);
}
- kfree(card);
}
static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
@@ -2962,11 +3001,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct pci_dev *pdev = card->dev;
/* save adapter pointer in card */
card->adapter = adapter;
- adapter->dev = &pdev->dev;
if (mwifiex_pcie_request_irq(adapter))
return -1;
@@ -2989,30 +3026,28 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct pci_dev *pdev;
+ struct pci_dev *pdev = card->dev;
int i;
- if (card) {
- pdev = card->dev;
- if (card->msix_enable) {
- for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
- synchronize_irq(card->msix_entries[i].vector);
+ if (card->msix_enable) {
+ for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
+ synchronize_irq(card->msix_entries[i].vector);
- for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
- free_irq(card->msix_entries[i].vector,
- &card->msix_ctx[i]);
+ for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
+ free_irq(card->msix_entries[i].vector,
+ &card->msix_ctx[i]);
- card->msix_enable = 0;
- pci_disable_msix(pdev);
- } else {
- mwifiex_dbg(adapter, INFO,
- "%s(): calling free_irq()\n", __func__);
- free_irq(card->dev->irq, &card->share_irq_ctx);
+ card->msix_enable = 0;
+ pci_disable_msix(pdev);
+ } else {
+ mwifiex_dbg(adapter, INFO,
+ "%s(): calling free_irq()\n", __func__);
+ free_irq(card->dev->irq, &card->share_irq_ctx);
- if (card->msi_enable)
- pci_disable_msi(pdev);
- }
+ if (card->msi_enable)
+ pci_disable_msi(pdev);
}
+ card->adapter = NULL;
}
/* This function initializes the PCI-E host memory space, WCB rings, etc.
@@ -3095,18 +3130,14 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
adapter->seq_num = 0;
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
- if (card) {
- if (reg->sleep_cookie)
- mwifiex_pcie_delete_sleep_cookie_buf(adapter);
-
- mwifiex_pcie_delete_cmdrsp_buf(adapter);
- mwifiex_pcie_delete_evtbd_ring(adapter);
- mwifiex_pcie_delete_rxbd_ring(adapter);
- mwifiex_pcie_delete_txbd_ring(adapter);
- card->cmdrsp_buf = NULL;
- }
+ if (reg->sleep_cookie)
+ mwifiex_pcie_delete_sleep_cookie_buf(adapter);
- return;
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+ mwifiex_pcie_delete_txbd_ring(adapter);
+ card->cmdrsp_buf = NULL;
}
static struct mwifiex_if_ops pcie_ops = {
@@ -3140,8 +3171,7 @@ static struct mwifiex_if_ops pcie_ops = {
/*
* This function initializes the PCIE driver module.
*
- * This initiates the semaphore and registers the device with
- * PCIE bus.
+ * This registers the device with PCIE bus.
*/
static int mwifiex_pcie_init_module(void)
{
@@ -3149,8 +3179,6 @@ static int mwifiex_pcie_init_module(void)
pr_debug("Marvell PCIe Driver\n");
- sema_init(&add_remove_card_sem, 1);
-
/* Clear the flag in case user removes the card. */
user_rmmod = 0;
@@ -3174,9 +3202,6 @@ static int mwifiex_pcie_init_module(void)
*/
static void mwifiex_pcie_cleanup_module(void)
{
- if (!down_interruptible(&add_remove_card_sem))
- up(&add_remove_card_sem);
-
/* Set the flag as user is removing this module. */
user_rmmod = 1;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index 46f99cae9399..ae3365d1c34e 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -22,6 +22,7 @@
#ifndef _MWIFIEX_PCIE_H
#define _MWIFIEX_PCIE_H
+#include <linux/completion.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@@ -345,6 +346,7 @@ struct pcie_service_card {
struct pci_dev *dev;
struct mwifiex_adapter *adapter;
struct mwifiex_pcie_device pcie;
+ struct completion fw_done;
u8 txbd_flush;
u32 txbd_wrptr;
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 97c9765b5bc6..181691684a08 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -827,7 +827,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
u32 num_probes;
u32 ssid_len;
u32 chan_idx;
- u32 chan_num;
u32 scan_type;
u16 scan_dur;
u8 channel;
@@ -1105,13 +1104,12 @@ mwifiex_config_scan(struct mwifiex_private *priv,
mwifiex_dbg(adapter, INFO,
"info: Scan: Scanning current channel only\n");
}
- chan_num = chan_idx;
} else {
mwifiex_dbg(adapter, INFO,
"info: Scan: Creating full region channel list\n");
- chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
- scan_chan_list,
- *filtered_scan);
+ mwifiex_scan_create_channel_list(priv, user_scan_in,
+ scan_chan_list,
+ *filtered_scan);
}
}
@@ -1671,6 +1669,10 @@ static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
}
done:
+ /* beacon_ie buffer was allocated in function
+ * mwifiex_fill_new_bss_desc(). Free it now.
+ */
+ kfree(bss_desc->beacon_buf);
kfree(bss_desc);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 8718950004f3..740d79cd91fa 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -49,8 +49,6 @@ static u8 user_rmmod;
static struct mwifiex_if_ops sdio_ops;
static unsigned long iface_work_flags;
-static struct semaphore add_remove_card_sem;
-
static struct memory_type_mapping generic_mem_type_map[] = {
{"DUMP", NULL, 0, 0xDD},
};
@@ -79,59 +77,18 @@ static const struct of_device_id mwifiex_sdio_of_match_table[] = {
{ }
};
-static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
-{
- struct mwifiex_plt_wake_cfg *cfg = priv;
-
- if (cfg->irq_wifi >= 0) {
- pr_info("%s: wake by wifi", __func__);
- cfg->wake_by_wifi = true;
- disable_irq_nosync(irq);
- }
-
- return IRQ_HANDLED;
-}
-
/* This function parse device tree node using mmc subnode devicetree API.
* The device node is saved in card->plt_of_node.
* if the device tree node exist and include interrupts attributes, this
* function will also request platform specific wakeup interrupt.
*/
-static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
+static int mwifiex_sdio_probe_of(struct device *dev)
{
- struct mwifiex_plt_wake_cfg *cfg;
- int ret;
-
if (!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
dev_err(dev, "required compatible string missing\n");
return -EINVAL;
}
- card->plt_of_node = dev->of_node;
- card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
- GFP_KERNEL);
- cfg = card->plt_wake_cfg;
- if (cfg && card->plt_of_node) {
- cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
- if (!cfg->irq_wifi) {
- dev_dbg(dev,
- "fail to parse irq_wifi from device tree\n");
- } else {
- ret = devm_request_irq(dev, cfg->irq_wifi,
- mwifiex_wake_irq_wifi,
- IRQF_TRIGGER_LOW,
- "wifi_wake", cfg);
- if (ret) {
- dev_dbg(dev,
- "Failed to request irq_wifi %d (%d)\n",
- cfg->irq_wifi, ret);
- card->plt_wake_cfg = NULL;
- return 0;
- }
- disable_irq(cfg->irq_wifi);
- }
- }
-
return 0;
}
@@ -152,10 +109,12 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
func->vendor, func->device, func->class, func->num);
- card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+ card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
+ init_completion(&card->fw_done);
+
card->func = func;
card->device_id = id;
@@ -185,20 +144,18 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
if (ret) {
dev_err(&func->dev, "failed to enable function\n");
- goto err_free;
+ return ret;
}
/* device tree node parsing and platform specific configuration*/
if (func->dev.of_node) {
- ret = mwifiex_sdio_probe_of(&func->dev, card);
- if (ret) {
- dev_err(&func->dev, "SDIO dt node parse failed\n");
+ ret = mwifiex_sdio_probe_of(&func->dev);
+ if (ret)
goto err_disable;
- }
}
- ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO);
+ ret = mwifiex_add_card(card, &card->fw_done, &sdio_ops,
+ MWIFIEX_SDIO, &func->dev);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
@@ -210,8 +167,6 @@ err_disable:
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
-err_free:
- kfree(card);
return ret;
}
@@ -231,17 +186,10 @@ static int mwifiex_sdio_resume(struct device *dev)
struct sdio_func *func = dev_to_sdio_func(dev);
struct sdio_mmc_card *card;
struct mwifiex_adapter *adapter;
- mmc_pm_flag_t pm_flag = 0;
- if (func) {
- pm_flag = sdio_get_host_pm_caps(func);
- card = sdio_get_drvdata(func);
- if (!card || !card->adapter) {
- pr_err("resume: invalid card or adapter\n");
- return 0;
- }
- } else {
- pr_err("resume: sdio_func is not specified\n");
+ card = sdio_get_drvdata(func);
+ if (!card || !card->adapter) {
+ dev_err(dev, "resume: invalid card or adapter\n");
return 0;
}
@@ -259,12 +207,7 @@ static int mwifiex_sdio_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_SYNC_CMD);
- /* Disable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- disable_irq_wake(card->plt_wake_cfg->irq_wifi);
- if (!card->plt_wake_cfg->wake_by_wifi)
- disable_irq(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_disable_wake(adapter);
return 0;
}
@@ -285,6 +228,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
if (!card)
return;
+ wait_for_completion(&card->fw_done);
+
adapter = card->adapter;
if (!adapter || !adapter->priv_num)
return;
@@ -292,9 +237,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
if (user_rmmod && !adapter->mfg_mode) {
- if (adapter->is_suspended)
- mwifiex_sdio_resume(adapter->dev);
-
mwifiex_deauthenticate_all(adapter);
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
@@ -302,7 +244,7 @@ mwifiex_sdio_remove(struct sdio_func *func)
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
}
- mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+ mwifiex_remove_card(adapter);
}
/*
@@ -323,40 +265,38 @@ static int mwifiex_sdio_suspend(struct device *dev)
mmc_pm_flag_t pm_flag = 0;
int ret = 0;
- if (func) {
- pm_flag = sdio_get_host_pm_caps(func);
- pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
- sdio_func_id(func), pm_flag);
- if (!(pm_flag & MMC_PM_KEEP_POWER)) {
- pr_err("%s: cannot remain alive while host is"
- " suspended\n", sdio_func_id(func));
- return -ENOSYS;
- }
+ pm_flag = sdio_get_host_pm_caps(func);
+ pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
+ sdio_func_id(func), pm_flag);
+ if (!(pm_flag & MMC_PM_KEEP_POWER)) {
+ dev_err(dev, "%s: cannot remain alive while host is"
+ " suspended\n", sdio_func_id(func));
+ return -ENOSYS;
+ }
- card = sdio_get_drvdata(func);
- if (!card || !card->adapter) {
- pr_err("suspend: invalid card or adapter\n");
- return 0;
- }
- } else {
- pr_err("suspend: sdio_func is not specified\n");
+ card = sdio_get_drvdata(func);
+ if (!card) {
+ dev_err(dev, "suspend: invalid card\n");
return 0;
}
- adapter = card->adapter;
+ /* Might still be loading firmware */
+ wait_for_completion(&card->fw_done);
- /* Enable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- card->plt_wake_cfg->wake_by_wifi = false;
- enable_irq(card->plt_wake_cfg->irq_wifi);
- enable_irq_wake(card->plt_wake_cfg->irq_wifi);
+ adapter = card->adapter;
+ if (!adapter) {
+ dev_err(dev, "adapter is not valid\n");
+ return 0;
}
+ mwifiex_enable_wake(adapter);
+
/* Enable the Host Sleep */
if (!mwifiex_enable_hs(adapter)) {
mwifiex_dbg(adapter, ERROR,
"cmd: failed to suspend\n");
adapter->hs_enabling = false;
+ mwifiex_disable_wake(adapter);
return -EFAULT;
}
@@ -1195,7 +1135,6 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
{
u32 total_pkt_len, pkt_len;
struct sk_buff *skb_deaggr;
- u32 pkt_type;
u16 blk_size;
u8 blk_num;
u8 *data;
@@ -1216,8 +1155,6 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
break;
}
pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
- pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
- 2));
if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
mwifiex_dbg(adapter, ERROR,
"%s: error in pkt_len,\t"
@@ -2066,6 +2003,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
struct sdio_mmc_card *card = adapter->card;
if (adapter->card) {
+ card->adapter = NULL;
sdio_claim_host(card->func);
sdio_disable_func(card->func);
sdio_release_host(card->func);
@@ -2098,9 +2036,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
return ret;
}
-
- adapter->dev = &func->dev;
-
strcpy(adapter->fw_name, card->firmware);
if (card->fw_dump_enh) {
adapter->mem_type_mapping_tbl = generic_mem_type_map;
@@ -2240,8 +2175,6 @@ static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter)
kfree(card->mpa_rx.len_arr);
kfree(card->mpa_tx.buf);
kfree(card->mpa_rx.buf);
- sdio_set_drvdata(card->func, NULL);
- kfree(card);
}
/*
@@ -2291,6 +2224,14 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
mwifiex_sdio_remove(func);
+ /*
+ * Normally, we would let the driver core take care of releasing these.
+ * But we're not letting the driver core handle this one. See above
+ * TODO.
+ */
+ sdio_set_drvdata(func, NULL);
+ devm_kfree(&func->dev, card);
+
/* power cycle the adapter */
sdio_claim_host(func);
mmc_hw_reset(func->card->host);
@@ -2767,14 +2708,11 @@ static struct mwifiex_if_ops sdio_ops = {
/*
* This function initializes the SDIO driver.
*
- * This initiates the semaphore and registers the device with
- * SDIO bus.
+ * This registers the device with SDIO bus.
*/
static int
mwifiex_sdio_init_module(void)
{
- sema_init(&add_remove_card_sem, 1);
-
/* Clear the flag in case user removes the card. */
user_rmmod = 0;
@@ -2793,9 +2731,6 @@ mwifiex_sdio_init_module(void)
static void
mwifiex_sdio_cleanup_module(void)
{
- if (!down_interruptible(&add_remove_card_sem))
- up(&add_remove_card_sem);
-
/* Set the flag as user is removing this module. */
user_rmmod = 1;
cancel_work_sync(&sdio_work);
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index db837f12c547..cdbf3a3ac7f9 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -21,6 +21,7 @@
#define _MWIFIEX_SDIO_H
+#include <linux/completion.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
@@ -154,11 +155,6 @@
a->mpa_rx.start_port = 0; \
} while (0)
-struct mwifiex_plt_wake_cfg {
- int irq_wifi;
- bool wake_by_wifi;
-};
-
/* data structure for SDIO MPA TX */
struct mwifiex_sdio_mpa_tx {
/* multiport tx aggregation buffer pointer */
@@ -242,9 +238,8 @@ struct mwifiex_sdio_card_reg {
struct sdio_mmc_card {
struct sdio_func *func;
struct mwifiex_adapter *adapter;
- struct device_node *plt_of_node;
- struct mwifiex_plt_wake_cfg *plt_wake_cfg;
+ struct completion fw_done;
const char *firmware;
const struct mwifiex_sdio_card_reg *reg;
u8 max_ports;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 2a162c33d271..125e448712dd 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -368,7 +368,10 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
{
struct mwifiex_adapter *adapter = priv->adapter;
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
+ u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
+ struct mwifiex_ps_param_in_hs *psparam_tlv = NULL;
bool hs_activate = false;
+ u16 size;
if (!hscfg_param)
/* New Activate command */
@@ -385,13 +388,14 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
memcpy(((u8 *) hs_cfg) +
sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
adapter->arp_filter, adapter->arp_filter_size);
- cmd->size = cpu_to_le16
- (adapter->arp_filter_size +
- sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
- + S_DS_GEN);
+ size = adapter->arp_filter_size +
+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
+ + S_DS_GEN;
+ tlv = (u8 *)hs_cfg
+ + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
+ + adapter->arp_filter_size;
} else {
- cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct
- host_cmd_ds_802_11_hs_cfg_enh));
+ size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
}
if (hs_activate) {
hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
@@ -401,12 +405,25 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
hs_cfg->params.hs_config.gap = hscfg_param->gap;
+
+ size += sizeof(struct mwifiex_ps_param_in_hs);
+ psparam_tlv = (struct mwifiex_ps_param_in_hs *)tlv;
+ psparam_tlv->header.type =
+ cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS);
+ psparam_tlv->header.len =
+ cpu_to_le16(sizeof(struct mwifiex_ps_param_in_hs)
+ - sizeof(struct mwifiex_ie_types_header));
+ psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL);
+ psparam_tlv->hs_inact_timeout =
+ cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT);
+
mwifiex_dbg(adapter, CMD,
"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
hs_cfg->params.hs_config.conditions,
hs_cfg->params.hs_config.gpio,
hs_cfg->params.hs_config.gap);
}
+ cmd->size = cpu_to_le16(size);
return 0;
}
@@ -1729,7 +1746,6 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
{
struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper;
struct mwifiex_ds_tdls_oper *oper = data_buf;
- struct mwifiex_sta_node *sta_ptr;
struct host_cmd_tlv_rates *tlv_rates;
struct mwifiex_ie_types_htcap *ht_capab;
struct mwifiex_ie_types_qos_info *wmm_qos_info;
@@ -1747,7 +1763,6 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
tdls_oper->reason = 0;
memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN);
- sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac);
pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper);
@@ -1885,6 +1900,24 @@ static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv,
return 0;
}
+/* This function check if the command is supported by firmware */
+static int mwifiex_is_cmd_supported(struct mwifiex_private *priv, u16 cmd_no)
+{
+ if (!ISSUPP_ADHOC_ENABLED(priv->adapter->fw_cap_info)) {
+ switch (cmd_no) {
+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+ case HostCmd_CMD_802_11_AD_HOC_START:
+ case HostCmd_CMD_802_11_AD_HOC_JOIN:
+ case HostCmd_CMD_802_11_AD_HOC_STOP:
+ return -EOPNOTSUPP;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
/*
* This function prepares the commands before sending them to the firmware.
*
@@ -1898,6 +1931,13 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
struct host_cmd_ds_command *cmd_ptr = cmd_buf;
int ret = 0;
+ if (mwifiex_is_cmd_supported(priv, cmd_no)) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "0x%x command not supported by firmware\n",
+ cmd_no);
+ return -EOPNOTSUPP;
+ }
+
/* Prepare command */
switch (cmd_no) {
case HostCmd_CMD_GET_HW_SPEC:
@@ -2191,7 +2231,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
{
struct mwifiex_adapter *adapter = priv->adapter;
int ret;
- u16 enable = true;
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
struct mwifiex_ds_auto_ds auto_ds;
enum state_11d_t state_11d;
@@ -2218,9 +2257,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
* The cal-data can be read from device tree and/or
* a configuration file and downloaded to firmware.
*/
- if (priv->adapter->iface_type == MWIFIEX_SDIO &&
- adapter->dev->of_node) {
- adapter->dt_node = adapter->dev->of_node;
+ if (adapter->dt_node) {
if (of_property_read_u32(adapter->dt_node,
"marvell,wakeup-pin",
&data) == 0) {
@@ -2228,19 +2265,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
adapter->hs_cfg.gpio = data;
}
- ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
- "marvell,caldata");
- if (ret)
- return -1;
+ mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
+ "marvell,caldata");
}
- if (adapter->cal_data) {
- ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
- HostCmd_ACT_GEN_SET, 0, NULL,
- true);
- if (ret)
- return -1;
- }
+ if (adapter->cal_data)
+ mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
+ HostCmd_ACT_GEN_SET, 0, NULL, true);
/* Read MAC address from HW */
ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
@@ -2312,16 +2343,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
if (ret)
return -1;
- if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
- /* set ibss coalescing_status */
- ret = mwifiex_send_cmd(
- priv,
- HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
- HostCmd_ACT_GEN_SET, 0, &enable, true);
- if (ret)
- return -1;
- }
-
memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
amsdu_aggr_ctrl.enable = true;
/* Send request to firmware */
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index a7e9f544f219..35d8636bdb91 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -404,7 +404,7 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
struct cfg80211_ap_settings *params)
{
const u8 *vendor_ie;
- struct ieee_types_header *wmm_ie;
+ const u8 *wmm_ie;
u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
@@ -412,9 +412,9 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
params->beacon.tail,
params->beacon.tail_len);
if (vendor_ie) {
- wmm_ie = (struct ieee_types_header *)vendor_ie;
- memcpy(&bss_cfg->wmm_info, wmm_ie + 1,
- sizeof(bss_cfg->wmm_info));
+ wmm_ie = vendor_ie;
+ memcpy(&bss_cfg->wmm_info, wmm_ie +
+ sizeof(struct ieee_types_header), *(wmm_ie + 1));
priv->wmm_enabled = 1;
} else {
memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 73eb0846db21..c563160b3b6b 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -24,7 +24,6 @@
static u8 user_rmmod;
static struct mwifiex_if_ops usb_ops;
-static struct semaphore add_remove_card_sem;
static struct usb_device_id mwifiex_usb_table[] = {
/* 8766 */
@@ -380,16 +379,17 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *epd;
int ret, i;
struct usb_card_rec *card;
- u16 id_vendor, id_product, bcd_device, bcd_usb;
+ u16 id_vendor, id_product, bcd_device;
- card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+ card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
+ init_completion(&card->fw_done);
+
id_vendor = le16_to_cpu(udev->descriptor.idVendor);
id_product = le16_to_cpu(udev->descriptor.idProduct);
bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
- bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB);
pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n",
id_vendor, id_product, bcd_device);
@@ -475,12 +475,11 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
- ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB);
+ ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
+ MWIFIEX_USB, &card->udev->dev);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
- kfree(card);
return ret;
}
@@ -503,17 +502,27 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
struct usb_tx_data_port *port;
int i, j;
- if (!card || !card->adapter) {
- pr_err("%s: card or card->adapter is NULL\n", __func__);
+ /* Might still be loading firmware */
+ wait_for_completion(&card->fw_done);
+
+ adapter = card->adapter;
+ if (!adapter) {
+ dev_err(&intf->dev, "card is not valid\n");
return 0;
}
- adapter = card->adapter;
if (unlikely(adapter->is_suspended))
mwifiex_dbg(adapter, WARN,
"Device already suspended\n");
- mwifiex_enable_hs(adapter);
+ /* Enable the Host Sleep */
+ if (!mwifiex_enable_hs(adapter)) {
+ mwifiex_dbg(adapter, ERROR,
+ "cmd: failed to suspend\n");
+ adapter->hs_enabling = false;
+ return -EFAULT;
+ }
+
/* 'is_suspended' flag indicates device is suspended.
* It must be set here before the usb_kill_urb() calls. Reason
@@ -559,8 +568,9 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
struct mwifiex_adapter *adapter;
int i;
- if (!card || !card->adapter) {
- pr_err("%s: card or card->adapter is NULL\n", __func__);
+ if (!card->adapter) {
+ dev_err(&intf->dev, "%s: card->adapter is NULL\n",
+ __func__);
return 0;
}
adapter = card->adapter;
@@ -602,21 +612,13 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
struct usb_card_rec *card = usb_get_intfdata(intf);
struct mwifiex_adapter *adapter;
- if (!card || !card->adapter) {
- pr_err("%s: card or card->adapter is NULL\n", __func__);
- return;
- }
+ wait_for_completion(&card->fw_done);
adapter = card->adapter;
- if (!adapter->priv_num)
+ if (!adapter || !adapter->priv_num)
return;
if (user_rmmod && !adapter->mfg_mode) {
-#ifdef CONFIG_PM
- if (adapter->is_suspended)
- mwifiex_usb_resume(intf);
-#endif
-
mwifiex_deauthenticate_all(adapter);
mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
@@ -628,13 +630,9 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
mwifiex_dbg(adapter, FATAL,
"%s: removing card\n", __func__);
- mwifiex_remove_card(adapter, &add_remove_card_sem);
+ mwifiex_remove_card(adapter);
- usb_set_intfdata(intf, NULL);
usb_put_dev(interface_to_usbdev(intf));
- kfree(card);
-
- return;
}
static struct usb_driver mwifiex_usb_driver = {
@@ -932,7 +930,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
card->adapter = adapter;
- adapter->dev = &card->udev->dev;
switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
case USB8997_PID_1:
@@ -1206,8 +1203,7 @@ static struct mwifiex_if_ops usb_ops = {
/* This function initializes the USB driver module.
*
- * This initiates the semaphore and registers the device with
- * USB bus.
+ * This registers the device with USB bus.
*/
static int mwifiex_usb_init_module(void)
{
@@ -1215,8 +1211,6 @@ static int mwifiex_usb_init_module(void)
pr_debug("Marvell USB8797 Driver\n");
- sema_init(&add_remove_card_sem, 1);
-
ret = usb_register(&mwifiex_usb_driver);
if (ret)
pr_err("Driver register failed!\n");
@@ -1236,9 +1230,6 @@ static int mwifiex_usb_init_module(void)
*/
static void mwifiex_usb_cleanup_module(void)
{
- if (!down_interruptible(&add_remove_card_sem))
- up(&add_remove_card_sem);
-
/* set the flag as user is removing this module */
user_rmmod = 1;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
index 30e8eb8c259d..e5f204ea018b 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.h
+++ b/drivers/net/wireless/marvell/mwifiex/usb.h
@@ -20,6 +20,7 @@
#ifndef _MWIFIEX_USB_H
#define _MWIFIEX_USB_H
+#include <linux/completion.h>
#include <linux/usb.h>
#define USB8XXX_VID 0x1286
@@ -75,6 +76,7 @@ struct usb_card_rec {
struct mwifiex_adapter *adapter;
struct usb_device *udev;
struct usb_interface *intf;
+ struct completion fw_done;
u8 rx_cmd_ep;
struct urb_context rx_cmd;
atomic_t rx_cmd_urb_pending;
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c
index 0eb246502e1d..28c2f6fae3e6 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -503,8 +503,10 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct sk_buff *skb, *tmp;
- skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
+ skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
+ skb_unlink(skb, &ra_list->skb_head);
mwifiex_write_data_complete(adapter, skb, 0, -1);
+ }
}
/*
@@ -600,11 +602,15 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
- skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
+ skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
+ skb_unlink(skb, &priv->tdls_txq);
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+ }
- skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+ skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
+ skb_unlink(skb, &priv->bypass_txq);
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+ }
atomic_set(&priv->adapter->bypass_tx_pending, 0);
idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
@@ -1099,6 +1105,7 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
&adapter->bss_prio_tbl[j].bss_prio_head,
list) {
+try_again:
priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
if (((priv_tmp->bss_mode != NL80211_IFTYPE_ADHOC) &&
@@ -1134,8 +1141,18 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
ra_list_spinlock,
flags_ra);
}
- }
+ if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) != 0) {
+ atomic_set(&priv_tmp->wmm.highest_queued_prio,
+ HIGH_PRIO_TID);
+ /* Iterate current private once more, since
+ * there still exist packets in data queue
+ */
+ goto try_again;
+ } else
+ atomic_set(&priv_tmp->wmm.highest_queued_prio,
+ NO_PKT_PRIO_TID);
+ }
}
return NULL;
@@ -1328,9 +1345,11 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
skb = skb_dequeue(&ptr->skb_head);
if (adapter->data_sent || adapter->tx_lock_flag) {
+ ptr->total_pkt_count--;
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
skb_queue_tail(&adapter->tx_data_q, skb);
+ atomic_dec(&priv->wmm.tx_pkts_queued);
atomic_inc(&adapter->tx_queued);
return;
}
@@ -1388,6 +1407,10 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
if (ret != -EBUSY) {
mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
+ ptr->total_pkt_count--;
+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
+ ra_list_flags);
}
}
diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c
index 44d46e25db80..a6e901766226 100644
--- a/drivers/net/wireless/mediatek/mt7601u/init.c
+++ b/drivers/net/wireless/mediatek/mt7601u/init.c
@@ -293,13 +293,13 @@ static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev)
ok = 0;
i = 200;
while (i--) {
- if ((mt76_rr(dev, 0x0430) & 0x00ff0000) ||
- (mt76_rr(dev, 0x0a30) & 0xffffffff) ||
- (mt76_rr(dev, 0x0a34) & 0xffffffff))
- ok++;
- if (ok > 6)
- break;
-
+ if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
+ !mt76_rr(dev, 0x0a30) &&
+ !mt76_rr(dev, 0x0a34)) {
+ if (ok++ > 5)
+ break;
+ continue;
+ }
msleep(1);
}
diff --git a/drivers/net/wireless/mediatek/mt7601u/regs.h b/drivers/net/wireless/mediatek/mt7601u/regs.h
index 27a429d90cec..2a8837002f00 100644
--- a/drivers/net/wireless/mediatek/mt7601u/regs.h
+++ b/drivers/net/wireless/mediatek/mt7601u/regs.h
@@ -192,6 +192,9 @@
#define MT_BCN_OFFSET_BASE 0x041c
#define MT_BCN_OFFSET(_n) (MT_BCN_OFFSET_BASE + ((_n) << 2))
+#define MT_RXQ_STA 0x0430
+#define MT_TXQ_STA 0x0434
+
#define MT_RF_CSR_CFG 0x0500
#define MT_RF_CSR_CFG_DATA GENMASK(7, 0)
#define MT_RF_CSR_CFG_REG_ID GENMASK(13, 8)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
index 155f343981fe..085c5b423bdf 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
@@ -1459,10 +1459,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
index 2553cdd74066..9832fd50c793 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
@@ -1585,10 +1585,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index 2d64611de300..cd3ab5a9e98d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -1349,10 +1349,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index bf3f0a39908c..4fb79e05078f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1621,7 +1621,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
* => Protect all HT40 transmissions.
*/
mm20_mode = gf20_mode = 0;
- mm40_mode = gf40_mode = 2;
+ mm40_mode = gf40_mode = 1;
break;
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
@@ -1644,7 +1644,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
* Legacy STAs are present
* => Protect all HT transmissions.
*/
- mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;
+ mm20_mode = mm40_mode = gf20_mode = gf40_mode = 1;
/*
* If erp protection is needed we have to protect HT
@@ -1660,7 +1660,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
/* check for STAs not supporting greenfield mode */
if (any_sta_nongf)
- gf20_mode = gf40_mode = 2;
+ gf20_mode = gf40_mode = 1;
/* Update HT protection config */
rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
@@ -1691,8 +1691,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
- !!erp->short_preamble);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
!!erp->short_preamble);
rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
@@ -1707,7 +1705,7 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
if (changed & BSS_CHANGED_BASIC_RATES) {
rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
- erp->basic_rates);
+ 0xff0 | erp->basic_rates);
rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
}
@@ -4672,11 +4670,14 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
0x00000000);
}
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392) ||
- rt2x00_rt(rt2x00dev, RT5592)) {
+ rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+ } else if (rt2x00_rt(rt2x00dev, RT5592)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
} else {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -4735,9 +4736,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 1);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 1);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 0);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
@@ -4770,9 +4771,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
@@ -4783,9 +4784,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
@@ -4796,9 +4797,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
@@ -4809,9 +4810,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
@@ -6756,7 +6757,6 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
@@ -6919,10 +6919,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
if (word == 0xffff) {
@@ -7464,7 +7461,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
char *default_power1;
char *default_power2;
char *default_power3;
- unsigned int i;
+ unsigned int i, tx_chains, rx_chains;
u32 reg;
/*
@@ -7475,7 +7472,6 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all hw fields.
*/
- ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_HT_CCK_RATES);
ieee80211_hw_set(rt2x00dev->hw, REPORTS_TX_ACK_STATUS);
ieee80211_hw_set(rt2x00dev->hw, AMPDU_AGGREGATION);
ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
@@ -7589,21 +7585,24 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40;
- if (rt2x00dev->default_ant.tx_chain_num >= 2)
+ tx_chains = rt2x00dev->default_ant.tx_chain_num;
+ rx_chains = rt2x00dev->default_ant.rx_chain_num;
+
+ if (tx_chains >= 2)
spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
- spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num <<
- IEEE80211_HT_CAP_RX_STBC_SHIFT;
+ spec->ht.cap |= rx_chains << IEEE80211_HT_CAP_RX_STBC_SHIFT;
spec->ht.ampdu_factor = 3;
spec->ht.ampdu_density = 4;
- spec->ht.mcs.tx_params =
- IEEE80211_HT_MCS_TX_DEFINED |
- IEEE80211_HT_MCS_TX_RX_DIFF |
- ((rt2x00dev->default_ant.tx_chain_num - 1) <<
- IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+ spec->ht.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ if (tx_chains != rx_chains) {
+ spec->ht.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+ spec->ht.mcs.tx_params |=
+ (tx_chains - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+ }
- switch (rt2x00dev->default_ant.rx_chain_num) {
+ switch (rx_chains) {
case 3:
spec->ht.mcs.rx_mask[2] = 0xff;
case 2:
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 4b0bb6b4f6f1..9f61293f1a56 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -341,8 +341,6 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
- rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
-
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
USB_MODE_RESET, REGISTER_TIMEOUT);
@@ -353,12 +351,11 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
- u32 reg;
+ u32 reg = 0;
if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
return -EIO;
- rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index f68d492129c6..aa3d4ceef4ad 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1403,6 +1403,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
*/
u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif);
+void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr);
/*
* Interrupt context handlers.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 4e0c5653054b..eb7b71443657 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -26,6 +26,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
@@ -931,6 +933,21 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
}
+void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
+{
+ const char *mac_addr;
+
+ mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
+ if (mac_addr)
+ ether_addr_copy(eeprom_mac_addr, mac_addr);
+
+ if (!is_valid_ether_addr(eeprom_mac_addr)) {
+ eth_random_addr(eeprom_mac_addr);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", eeprom_mac_addr);
+ }
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_set_mac_address);
+
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
struct hw_mode_spec *spec)
{
@@ -1362,11 +1379,13 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
if (rt2x00dev->bcn->limit > 0)
rt2x00dev->hw->wiphy->interface_modes |=
BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
- BIT(NL80211_IFTYPE_WDS);
+#ifdef CONFIG_WIRELESS_WDS
+ BIT(NL80211_IFTYPE_WDS) |
+#endif
+ BIT(NL80211_IFTYPE_AP);
rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -1422,7 +1441,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
cancel_work_sync(&rt2x00dev->intf_work);
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
cancel_work_sync(&rt2x00dev->sleep_work);
-#ifdef CONFIG_RT2X00_LIB_USB
+#if IS_ENABLED(CONFIG_RT2X00_LIB_USB)
if (rt2x00_is_usb(rt2x00dev)) {
usb_kill_anchored_urbs(rt2x00dev->anchor);
hrtimer_cancel(&rt2x00dev->txstatus_timer);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index 03013eb2f642..5306a3b2622d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -2413,10 +2413,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
index c1397a6d3cee..1a29c4d205a5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
@@ -1766,10 +1766,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 0881ba8535f4..4fdc7223c894 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -272,7 +272,6 @@ static const struct net_device_ops ray_netdev_ops = {
.ndo_set_config = ray_dev_config,
.ndo_get_stats = ray_get_stats,
.ndo_set_rx_mode = set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 08d587a342d3..df551b2b56eb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1337,10 +1337,11 @@ struct rtl8xxxu_fileops {
u32 ramask, int sgi);
void (*report_connect) (struct rtl8xxxu_priv *priv,
u8 macid, bool connect);
- void (*fill_txdesc) (struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
+ void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
int writeN_block_size;
int rx_agg_buf_size;
char tx_desc_size;
@@ -1434,14 +1435,16 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
int rtl8xxxu_gen2_channel_to_group(int channel);
bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv,
int result[][8], int c1, int c2);
-void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
-void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
+void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
+void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
extern struct rtl8xxxu_fileops rtl8192cu_fops;
extern struct rtl8xxxu_fileops rtl8192eu_fops;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index a793fedc3654..a1178c5d6ad8 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -1556,7 +1556,7 @@ exit:
return ret;
}
-void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
+static void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index a5e6ec2152bf..3a86675020a2 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -4372,6 +4372,13 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
u8 macid, bool connect)
{
+#ifdef RTL8XXXU_GEN2_REPORT_CONNECT
+ /*
+ * Barry Day reports this causes issues with 8192eu and 8723bu
+ * devices reconnecting. The reason for this is unclear, but
+ * until it is better understood, leave the code in place but
+ * disabled, so it is not lost.
+ */
struct h2c_cmd h2c;
memset(&h2c, 0, sizeof(struct h2c_cmd));
@@ -4383,6 +4390,7 @@ void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
h2c.media_status_rpt.parm &= ~BIT(0);
rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
+#endif
}
void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
@@ -4759,13 +4767,28 @@ static void rtl8xxxu_dump_action(struct device *dev,
* This format is used on 8188cu/8192cu/8723au
*/
void
-rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable)
+rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable, u32 rts_rate)
{
+ struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u32 rate;
+ u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
+ if (rate_flags & IEEE80211_TX_RC_MCS &&
+ !ieee80211_is_mgmt(hdr->frame_control))
+ rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
+ else
+ rate = tx_rate->hw_value;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+ dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
+ __func__, rate, cpu_to_le16(tx_desc->pkt_size));
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc->txdw5 = cpu_to_le32(rate);
@@ -4796,15 +4819,16 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
if (sgi)
tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI);
- 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 <<
- TXDESC32_RTS_RATE_SHIFT);
+ /*
+ * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
+ */
+ tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
+ } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
}
@@ -4813,16 +4837,31 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
* This format is used on 8192eu/8723bu
*/
void
-rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable)
+rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
+ bool short_preamble, bool ampdu_enable, u32 rts_rate)
{
+ struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
struct rtl8xxxu_txdesc40 *tx_desc40;
+ u32 rate;
+ u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32;
+ if (rate_flags & IEEE80211_TX_RC_MCS &&
+ !ieee80211_is_mgmt(hdr->frame_control))
+ rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
+ else
+ rate = tx_rate->hw_value;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+ dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
+ __func__, rate, cpu_to_le16(tx_desc40->pkt_size));
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc40->txdw4 = cpu_to_le32(rate);
@@ -4849,15 +4888,19 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr,
if (short_preamble)
tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE);
- if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
- /*
- * Use RTS rate 24M - does the mac80211 tell
- * us which to use?
- */
- tx_desc40->txdw4 |= cpu_to_le32(DESC_RATE_24M <<
- TXDESC40_RTS_RATE_SHIFT);
+ tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT);
+ /*
+ * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
+ */
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE);
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE);
+ } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ /*
+ * For some reason the vendor driver doesn't set
+ * TXDESC40_HW_RTS_ENABLE for CTS to SELF
+ */
+ tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_CTS_SELF_ENABLE);
}
}
@@ -4867,14 +4910,13 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
{
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_txdesc32 *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;
+ u32 queue, rts_rate;
u16 pktlen = skb->len;
u16 seq_number;
u16 rate_flag = tx_info->control.rates[0].flags;
@@ -4901,10 +4943,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
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);
@@ -4958,12 +4996,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
}
}
- if (rate_flag & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rate_flag & IEEE80211_TX_RC_SHORT_GI ||
(ieee80211_is_data_qos(hdr->frame_control) &&
sta && sta->ht_cap.cap &
@@ -4974,10 +5006,17 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
(sta && vif && vif->bss_conf.use_short_preamble))
short_preamble = true;
+ if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS)
+ rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ else
+ rts_rate = 0;
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
- priv->fops->fill_txdesc(hdr, tx_desc, rate, rate_flag,
- sgi, short_preamble, ampdu_enable);
+ priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
+ ampdu_enable, rts_rate);
rtl8xxxu_calc_tx_desc_csum(tx_desc);
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 264466f59c57..4ac928bf1f8e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc);
static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
{
+ struct ieee80211_hw *hw = rtlpriv->hw;
+
rtlpriv->ra.is_special_data = true;
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
rtlpriv, 1);
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
+ rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
@@ -1381,8 +1382,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
if (is_tx) {
rtlpriv->ra.is_special_data = true;
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
+ rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 8e7f23c11680..2caa4ad04dba 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
} else {
mstatus = RT_MEDIA_DISCONNECT;
- if (mac->link_state == MAC80211_LINKED) {
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
- }
+ if (mac->link_state == MAC80211_LINKED)
+ rtl_lps_leave(hw);
if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
mac->link_state = MAC80211_NOLINK;
@@ -1431,8 +1429,7 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
}
if (mac->link_state == MAC80211_LINKED) {
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
+ rtl_lps_leave(hw);
mac->link_state = MAC80211_LINKED_SCANNING;
} else {
rtl_ips_nic_on(hw);
@@ -1832,7 +1829,7 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pskb = __skb_dequeue(&ring->queue);
- kfree_skb(pskb);
+ dev_kfree_skb_irq(pskb);
/*this is wrong, fill_tx_cmddesc needs update*/
pdesc = &ring->desc[0];
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 0dfa9eac3926..8bfe020edd3a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
@@ -663,11 +659,9 @@ tx_status_ok:
}
if (((rtlpriv->link_info.num_rx_inperiod +
- rtlpriv->link_info.num_tx_inperiod) > 8) ||
- (rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
- }
+ rtlpriv->link_info.num_tx_inperiod) > 8) ||
+ (rtlpriv->link_info.num_rx_inperiod > 2))
+ rtl_lps_leave(hw);
}
static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -918,10 +912,8 @@ new_trx_end:
}
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
- (rtlpriv->link_info.num_rx_inperiod > 2)) {
- rtlpriv->enter_ps = false;
- schedule_work(&rtlpriv->works.lps_change_work);
- }
+ (rtlpriv->link_info.num_rx_inperiod > 2))
+ rtl_lps_leave(hw);
skb = new_skb;
no_new:
if (rtlpriv->use_new_trx_flow) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index b951ebac15ea..578b1d900bfb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index 18d979affc18..d0ffc4d508cf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
}
}
-/*Enter the leisure power save mode.*/
-void rtl_lps_enter(struct ieee80211_hw *hw)
+/* Interrupt safe routine to enter the leisure power save mode.*/
+static void rtl_lps_enter_core(struct ieee80211_hw *hw)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -444,10 +444,9 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
}
-EXPORT_SYMBOL(rtl_lps_enter);
-/*Leave the leisure power save mode.*/
-void rtl_lps_leave(struct ieee80211_hw *hw)
+/* Interrupt safe routine to leave the leisure power save mode.*/
+static void rtl_lps_leave_core(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -477,7 +476,6 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
}
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
}
-EXPORT_SYMBOL(rtl_lps_leave);
/* For sw LPS*/
void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
@@ -670,12 +668,34 @@ void rtl_lps_change_work_callback(struct work_struct *work)
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->enter_ps)
- rtl_lps_enter(hw);
+ rtl_lps_enter_core(hw);
else
- rtl_lps_leave(hw);
+ rtl_lps_leave_core(hw);
}
EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
+void rtl_lps_enter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (!in_interrupt())
+ return rtl_lps_enter_core(hw);
+ rtlpriv->enter_ps = true;
+ schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_enter);
+
+void rtl_lps_leave(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (!in_interrupt())
+ return rtl_lps_leave_core(hw);
+ rtlpriv->enter_ps = false;
+ schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_leave);
+
void rtl_swlps_wq_callback(void *data)
{
struct rtl_works *rtlworks = container_of_dwork_rtl(data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
index 071ccee69eae..0fd2bac14db6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
index 21bd4a5337ab..b884c30c7b37 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
index 1850fde881b5..d38dbca3c19e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
index f05c2c674165..6ea7fd7bb527 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
index 316be5ff69ca..bdc132bef822 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
index 6a72d0c8afa0..441604ff5858 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
index 864806c19ca7..c5fa14bda387 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
index 918b1d129e77..889bd1301154 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
index 27e3d5f9ca34..94dd25cf1ca8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
index 202412577bf0..d11261e05a2e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
index 690a7a1675e2..b90aaf128072 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
index 09898cf2e07a..2c8205e46be4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
index 38ba707015f5..9761d0ca31b0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index a47be73a0980..4483d40ecad1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
index 98a086822aac..877f138a0cb9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
index 24e483ba3fa4..833193b751f7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
index c5761066d383..f6edb9cd9b67 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
index 46d0d945f283..d1b6a8fe7b6a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
index dadc02b5de0b..93f3bc0197b4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
index dc8460c0b32f..1bb7ed35812d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
index a9c406f33d0a..7cae6350437c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
index ebd72cae10b6..22c5e6f51331 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index 8b6e37ce3f66..691ddef1ae28 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
index d2367a5d0cf5..9a1c89cbbda1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
index 752f943a84ae..98b06d48a2dd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
index 8b79161f71be..51e4e07396a6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index 781af1b99eb5..2ab4a00246cc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
index 607304586c03..66291fc341e7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
index 74a479ac323d..316fe9990b6d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
index c16209a336ea..00fc0685317a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
index fafa6bac2a3f..ce71433792e3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
index ae8f055483fa..5c7da0cfc684 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
index 67588083e6cc..932f056f7ef8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
index 8514ab652520..c6240813ff7b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
index 0f372278b7af..551deb8afb6f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index 68ca734853c1..cf212f694db5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
index 20a49ec8459b..8573b7e257d9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
index 4b2976465905..f35f435c094e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
index 42b068660483..a422c4db1a41 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
index 8b81465c629b..8185886daa8e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
index ec2ea56f7933..5e3183024aa0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
index 6f987de5b441..07aec0b20cc9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index f953320f0e23..b84e13ac6ead 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
index a1310abd0d54..4ea2cb225580 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
index 7903c154de00..b3ac981d88c6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
index 4b020e9e30b1..851bf53d246c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 95880fe4106e..1ea878fa7901 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index fd8051dcd98a..df88e39301c2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
index 0a443ed17cf4..cb7b9b727e3a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
index 7c1db7e7572d..ac6d554b67c8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
index f2d318ceeb28..5d346ec366ce 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
index 8de29cc3ced0..17f6903c14bb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
index 8a38daa316cb..6b435236a28e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
index d91f8bbfe7a0..fcb14c5db172 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
index 1bc7b1a96d4a..24b03b9999be 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
index 811ba57eb9bb..c22b8a215c87 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
index a29df30c3025..9874519704d3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
index 2a1edfd21b96..424f54babd03 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
index 8115bf4ac683..58b56b523dbe 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
index 315a298bab06..b354b95936e2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
index 2f479d397644..9dc9e915513e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
index 7303d12c266f..c650a8dcdb26 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index 1ebfee18882f..2d65e4095292 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
index 0e6035b8fd86..fd7d036e9abc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
index 8ea6f528dfa6..4badb183cf35 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
index 8b724a86117a..7fefc483ec28 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index e998e98d74cb..5fb37564957c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
index 194d99f8bacf..9bb6cc648590 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
index 41466f957cdc..b5ba0554a0cd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
index 9bae5a92e30f..2c073a77b194 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
index de6ac796c74d..3af07efed73a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
index 331b1584a1a2..32f9207b5cf5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
index b1e44b86e8ed..5827aa32cef0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
index 52e4430edb54..26e06b2837c3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
index 4cacee10f31e..86bce1be83ce 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
index 9849cb988186..870007801f6b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
index 2182dbeb5f32..90e265d9ffc6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
index 4bb75581ab38..fcb9216af82d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
index 8acf4765a7a6..7a3b6b623872 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
index e13043479b71..5d445c2afcf3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
index 34e88a3f6abe..bd2fa7735866 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
index 8a29eb94ab17..e9ba283d05ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index 3e1eaeac4fdc..998cefbd7e89 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
index 2eb88862ebe4..af449d6714e6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
index f1a73f75127e..162578f05c85 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
index 2feb73b71a4f..aa3c7687d226 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
@@ -6,10 +6,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
index d53bbf6bef81..9a5a11399221 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
index 5a13f17e3b41..728589138072 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
index 57111052e86b..a113780af08a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
index 9d1fe25db953..2e668fcfc5c2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
index bcd64a22acc0..45719fdcb067 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
index c7be9342136c..77c10047cb20 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 32aa5c1d070a..0a508649903d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h
index 685273ca9561..a6d43d2ecd36 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.h
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.h
@@ -11,10 +11,6 @@
* 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 LICENSE.
*
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index dbb23899ddcb..dadaa73ab49d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -194,6 +194,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
void rsi_mac80211_detach(struct rsi_hw *adapter)
{
struct ieee80211_hw *hw = adapter->hw;
+ enum nl80211_band band;
if (hw) {
ieee80211_stop_queues(hw);
@@ -201,7 +202,17 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
ieee80211_free_hw(hw);
}
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ struct ieee80211_supported_band *sband =
+ &adapter->sbands[band];
+
+ kfree(sband->channels);
+ }
+
+#ifdef CONFIG_RSI_DEBUGFS
rsi_remove_dbgfs(adapter);
+ kfree(adapter->dfsentry);
+#endif
}
EXPORT_SYMBOL_GPL(rsi_mac80211_detach);
@@ -264,6 +275,8 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw)
common->iface_down = false;
mutex_unlock(&common->mutex);
+ rsi_send_rx_filter_frame(common, 0);
+
return 0;
}
@@ -304,7 +317,9 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
if (!adapter->sc_nvifs) {
++adapter->sc_nvifs;
adapter->vifs[0] = vif;
- ret = rsi_set_vap_capabilities(common, STA_OPMODE);
+ ret = rsi_set_vap_capabilities(common,
+ STA_OPMODE,
+ VAP_ADD);
}
break;
default:
@@ -332,8 +347,10 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
struct rsi_common *common = adapter->priv;
mutex_lock(&common->mutex);
- if (vif->type == NL80211_IFTYPE_STATION)
+ if (vif->type == NL80211_IFTYPE_STATION) {
adapter->sc_nvifs--;
+ rsi_set_vap_capabilities(common, STA_OPMODE, VAP_DELETE);
+ }
if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
adapter->vifs[0] = NULL;
@@ -373,7 +390,7 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
status = rsi_band_check(common);
if (!status)
- status = rsi_set_channel(adapter->priv, channel);
+ status = rsi_set_channel(adapter->priv, curchan);
if (bss->assoc) {
if (common->hw_data_qs_blocked &&
@@ -394,6 +411,34 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
}
/**
+ * rsi_config_power() - This function configures tx power to device
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_config_power(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (adapter->sc_nvifs <= 0) {
+ rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+ return -EINVAL;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Set tx power: %d dBM\n", __func__, conf->power_level);
+
+ if (conf->power_level == common->tx_power)
+ return 0;
+
+ common->tx_power = conf->power_level;
+
+ return rsi_send_radio_params_update(common);
+}
+
+/**
* rsi_mac80211_config() - This function is a handler for configuration
* requests. The stack calls this function to
* change hardware configuration, e.g., channel.
@@ -414,6 +459,12 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
status = rsi_channel_change(hw);
+ /* tx power */
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__);
+ status = rsi_config_power(hw);
+ }
+
mutex_unlock(&common->mutex);
return status;
@@ -456,11 +507,19 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ u16 rx_filter_word = 0;
mutex_lock(&common->mutex);
if (changed & BSS_CHANGED_ASSOC) {
rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",
__func__, bss_conf->assoc);
+ if (bss_conf->assoc) {
+ /* Send the RX filter frame */
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+ ALLOW_CTRL_ASSOC_PEER |
+ ALLOW_MGMT_ASSOC_PEER);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ }
rsi_inform_bss_status(common,
bss_conf->assoc,
bss_conf->bssid,
@@ -998,6 +1057,7 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
struct rsi_common *common = adapter->priv;
mutex_lock(&common->mutex);
+
/* Resetting all the fields to default values */
common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
@@ -1007,9 +1067,114 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
common->vif_info[0].seq_start = 0;
common->secinfo.ptk_cipher = 0;
common->secinfo.gtk_cipher = 0;
+
+ rsi_send_rx_filter_frame(common, 0);
+
mutex_unlock(&common->mutex);
+
+ return 0;
+}
+/**
+ * rsi_mac80211_set_antenna() - This function is used to configure
+ * tx and rx antennas.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, Negative error code on failure.
+ */
+static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
+ u32 tx_ant, u32 rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u8 antenna = 0;
+
+ if (tx_ant > 1 || rx_ant > 1) {
+ rsi_dbg(ERR_ZONE,
+ "Invalid antenna selection (tx: %d, rx:%d)\n",
+ tx_ant, rx_ant);
+ rsi_dbg(ERR_ZONE,
+ "Use 0 for int_ant, 1 for ext_ant\n");
+ return -EINVAL;
+ }
+
+ rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n",
+ __func__, tx_ant, rx_ant);
+
+ mutex_lock(&common->mutex);
+
+ antenna = tx_ant ? ANTENNA_SEL_UFL : ANTENNA_SEL_INT;
+ if (common->ant_in_use != antenna)
+ if (rsi_set_antenna(common, antenna))
+ goto fail_set_antenna;
+
+ rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n",
+ tx_ant ? "UFL" : "INT");
+
+ common->ant_in_use = antenna;
+
+ mutex_unlock(&common->mutex);
+
return 0;
+
+fail_set_antenna:
+ rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__);
+ mutex_unlock(&common->mutex);
+ return -EINVAL;
+}
+
+/**
+ * rsi_mac80211_get_antenna() - This function is used to configure
+ * tx and rx antennas.
+ *
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw,
+ u32 *tx_ant, u32 *rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ mutex_lock(&common->mutex);
+
+ *tx_ant = (common->ant_in_use == ANTENNA_SEL_UFL) ? 1 : 0;
+ *rx_ant = 0;
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+static void rsi_reg_notify(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct rsi_hw * adapter = hw->priv;
+ int i;
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ if (ch->flags & IEEE80211_CHAN_RADAR)
+ ch->flags |= IEEE80211_CHAN_NO_IR;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "country = %s dfs_region = %d\n",
+ request->alpha2, request->dfs_region);
+ adapter->dfs_region = request->dfs_region;
}
static struct ieee80211_ops mac80211_ops = {
@@ -1028,6 +1193,8 @@ static struct ieee80211_ops mac80211_ops = {
.ampdu_action = rsi_mac80211_ampdu_action,
.sta_add = rsi_mac80211_sta_add,
.sta_remove = rsi_mac80211_sta_remove,
+ .set_antenna = rsi_mac80211_set_antenna,
+ .get_antenna = rsi_mac80211_get_antenna,
};
/**
@@ -1092,6 +1259,8 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->bands[NL80211_BAND_5GHZ] =
&adapter->sbands[NL80211_BAND_5GHZ];
+ wiphy->reg_notifier = rsi_reg_notify;
+
status = ieee80211_register_hw(hw);
if (status)
return status;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 35c14cc3f0d2..fac87c06357b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -617,7 +617,9 @@ static int rsi_program_bb_rf(struct rsi_common *common)
*
* Return: 0 on success, corresponding negative error code on failure.
*/
-int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
+int rsi_set_vap_capabilities(struct rsi_common *common,
+ enum opmode mode,
+ u8 vap_status)
{
struct sk_buff *skb = NULL;
struct rsi_vap_caps *vap_caps;
@@ -642,6 +644,7 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
FRAME_DESC_SZ) |
(RSI_WIFI_MGMT_Q << 12));
vap_caps->desc_word[1] = cpu_to_le16(VAP_CAPABILITIES);
+ vap_caps->desc_word[2] = cpu_to_le16(vap_status << 8);
vap_caps->desc_word[4] = cpu_to_le16(mode |
(common->channel_width << 8));
vap_caps->desc_word[7] = cpu_to_le16((vap_id << 8) |
@@ -910,7 +913,8 @@ int rsi_band_check(struct rsi_common *common)
*
* Return: 0 on success, corresponding error code on failure.
*/
-int rsi_set_channel(struct rsi_common *common, u16 channel)
+int rsi_set_channel(struct rsi_common *common,
+ struct ieee80211_channel *channel)
{
struct sk_buff *skb = NULL;
struct rsi_mac_frame *mgmt_frame;
@@ -925,24 +929,76 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
return -ENOMEM;
}
+ if (!channel) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
memset(skb->data, 0, FRAME_DESC_SZ);
mgmt_frame = (struct rsi_mac_frame *)skb->data;
mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);
- mgmt_frame->desc_word[4] = cpu_to_le16(channel);
+ mgmt_frame->desc_word[4] = cpu_to_le16(channel->hw_value);
+
+ mgmt_frame->desc_word[4] |=
+ cpu_to_le16(((char)(channel->max_antenna_gain)) << 8);
+ mgmt_frame->desc_word[5] =
+ cpu_to_le16((char)(channel->max_antenna_gain));
mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET |
BBP_REG_WRITE |
(RSI_RF_TYPE << 4));
- mgmt_frame->desc_word[5] = cpu_to_le16(0x01);
- mgmt_frame->desc_word[6] = cpu_to_le16(0x12);
+ if (!(channel->flags & IEEE80211_CHAN_NO_IR) &&
+ !(channel->flags & IEEE80211_CHAN_RADAR)) {
+ if (common->tx_power < channel->max_power)
+ mgmt_frame->desc_word[6] = cpu_to_le16(common->tx_power);
+ else
+ mgmt_frame->desc_word[6] = cpu_to_le16(channel->max_power);
+ }
+ mgmt_frame->desc_word[7] = cpu_to_le16(common->priv->dfs_region);
if (common->channel_width == BW_40MHZ)
mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);
- common->channel = channel;
+ common->channel = channel->hw_value;
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_radio_params_update() - This function sends the radio
+ * parameters update to device
+ * @common: Pointer to the driver private structure.
+ * @channel: Channel value to be set.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_radio_params_update(struct rsi_common *common)
+{
+ struct rsi_mac_frame *cmd_frame;
+ struct sk_buff *skb = NULL;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending Radio Params update frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ cmd_frame = (struct rsi_mac_frame *)skb->data;
+
+ cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ cmd_frame->desc_word[1] = cpu_to_le16(RADIO_PARAMS_UPDATE);
+ cmd_frame->desc_word[3] = cpu_to_le16(BIT(0));
+
+ cmd_frame->desc_word[3] |= cpu_to_le16(common->tx_power << 8);
skb_put(skb, FRAME_DESC_SZ);
@@ -1240,6 +1296,72 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
}
+/**
+ * rsi_send_rx_filter_frame() - Sends a frame to filter the RX packets
+ *
+ * @common: Pointer to the driver private structure.
+ * @rx_filter_word: Flags of filter packets
+ *
+ * @Return: 0 on success, -1 on failure.
+ */
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
+{
+ struct rsi_mac_frame *cmd_frame;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "Sending RX filter frame\n");
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ cmd_frame = (struct rsi_mac_frame *)skb->data;
+
+ cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ cmd_frame->desc_word[1] = cpu_to_le16(SET_RX_FILTER);
+ cmd_frame->desc_word[4] = cpu_to_le16(rx_filter_word);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_set_antenna() - This fuction send antenna configuration request
+ * to device
+ *
+ * @common: Pointer to the driver private structure.
+ * @antenna: bitmap for tx antenna selection
+ *
+ * Return: 0 on Success, negative error code on failure
+ */
+int rsi_set_antenna(struct rsi_common *common, u8 antenna)
+{
+ struct rsi_mac_frame *cmd_frame;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ cmd_frame = (struct rsi_mac_frame *)skb->data;
+
+ cmd_frame->desc_word[1] = cpu_to_le16(ANT_SEL_FRAME);
+ cmd_frame->desc_word[3] = cpu_to_le16(antenna & 0x00ff);
+ cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index dcd095787166..1d5904bc2c74 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -204,6 +204,9 @@ struct rsi_common {
struct cqm_info cqm_info;
bool hw_data_qs_blocked;
+
+ int tx_power;
+ u8 ant_in_use;
};
struct rsi_hw {
@@ -220,6 +223,7 @@ struct rsi_hw {
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
+ u8 dfs_region;
void *rsi_dev;
int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 3741173fd3ac..dfbf7a50269b 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -140,11 +140,30 @@
#define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\
FIF_BCN_PRBRESP_PROMISC)
+
+#define ANTENNA_SEL_INT 0x02 /* RF_OUT_2 / Integerated */
+#define ANTENNA_SEL_UFL 0x03 /* RF_OUT_1 / U.FL */
+
+/* Rx filter word definitions */
+#define PROMISCOUS_MODE BIT(0)
+#define ALLOW_DATA_ASSOC_PEER BIT(1)
+#define ALLOW_MGMT_ASSOC_PEER BIT(2)
+#define ALLOW_CTRL_ASSOC_PEER BIT(3)
+#define DISALLOW_BEACONS BIT(4)
+#define ALLOW_CONN_PEER_MGMT_WHILE_BUF_FULL BIT(5)
+#define DISALLOW_BROADCAST_DATA BIT(6)
+
enum opmode {
STA_OPMODE = 1,
AP_OPMODE = 2
};
+enum vap_status {
+ VAP_ADD = 1,
+ VAP_DELETE = 2,
+ VAP_UPDATE = 3
+};
+
extern struct ieee80211_rate rsi_rates[12];
extern const u16 rsi_mcsrates[8];
@@ -184,7 +203,9 @@ enum cmd_frame_type {
BG_SCAN_PARAMS,
BG_SCAN_PROBE_REQ,
CW_MODE_REQ,
- PER_CMD_PKT
+ PER_CMD_PKT,
+ ANT_SEL_FRAME = 0x20,
+ RADIO_PARAMS_UPDATE = 0x29
};
struct rsi_mac_frame {
@@ -287,12 +308,14 @@ static inline u8 rsi_get_channel(u8 *addr)
}
int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
-int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode);
+int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
+ u8 vap_status);
int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
u16 ssn, u8 buf_size, u8 event);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
u8 key_type, u8 key_id, u32 cipher);
-int rsi_set_channel(struct rsi_common *common, u16 chno);
+int rsi_set_channel(struct rsi_common *common,
+ struct ieee80211_channel *channel);
int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
void rsi_inform_bss_status(struct rsi_common *common, u8 status,
const u8 *bssid, u8 qos_enable, u16 aid);
@@ -306,4 +329,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_band_check(struct rsi_common *common);
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
+int rsi_send_radio_params_update(struct rsi_common *common);
+int rsi_set_antenna(struct rsi_common *common, u8 antenna);
#endif
diff --git a/drivers/net/wireless/st/cw1200/wsm.c b/drivers/net/wireless/st/cw1200/wsm.c
index 680d60eabc75..be4c22e0d902 100644
--- a/drivers/net/wireless/st/cw1200/wsm.c
+++ b/drivers/net/wireless/st/cw1200/wsm.c
@@ -379,7 +379,6 @@ static int wsm_multi_tx_confirm(struct cw1200_common *priv,
{
int ret;
int count;
- int i;
count = WSM_GET32(buf);
if (WARN_ON(count <= 0))
@@ -395,11 +394,10 @@ static int wsm_multi_tx_confirm(struct cw1200_common *priv,
}
cw1200_debug_txed_multi(priv, count);
- for (i = 0; i < count; ++i) {
+ do {
ret = wsm_tx_confirm(priv, buf, link_id);
- if (ret)
- return ret;
- }
+ } while (!ret && --count);
+
return ret;
underflow:
@@ -1807,16 +1805,18 @@ static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size)
{
size_t pos = buf->data - buf->begin;
size_t size = pos + extra_size;
+ u8 *tmp;
size = round_up(size, FWLOAD_BLOCK_SIZE);
- buf->begin = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA);
- if (buf->begin) {
- buf->data = &buf->begin[pos];
- buf->end = &buf->begin[size];
- return 0;
- } else {
- buf->end = buf->data = buf->begin;
+ tmp = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA);
+ if (!tmp) {
+ wsm_buf_deinit(buf);
return -ENOMEM;
}
+
+ buf->begin = tmp;
+ buf->data = &buf->begin[pos];
+ buf->end = &buf->begin[size];
+ return 0;
}
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index b36ce185c9f2..86fa0fc69084 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -218,5 +218,33 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
if (vector & FW_LOGGER_INDICATION)
wlcore_event_fw_logger(wl);
+ if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) {
+ struct wl12xx_vif *wlvif;
+ struct ieee80211_vif *vif;
+ struct ieee80211_sta *sta;
+ u8 link_id = mbox->rx_ba_link_id;
+ u8 win_size = mbox->rx_ba_win_size;
+ const u8 *addr;
+
+ wlvif = wl->links[link_id].wlvif;
+ vif = wl12xx_wlvif_to_vif(wlvif);
+
+ /* Update RX aggregation window size and call
+ * MAC routine to stop active RX aggregations for this link
+ */
+ if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+ addr = vif->bss_conf.bssid;
+ else
+ addr = wl->links[link_id].addr;
+
+ sta = ieee80211_find_sta(vif, addr);
+ if (sta) {
+ sta->max_rx_aggregation_subframes = win_size;
+ ieee80211_stop_rx_ba_session(vif,
+ wl->links[link_id].ba_bitmap,
+ addr);
+ }
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index ce8ea9c04052..4af297fbb529 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -38,6 +38,7 @@ enum {
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18),
DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20),
+ RX_BA_WIN_SIZE_CHANGE_EVENT_ID = BIT(21),
SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
TIME_SYNC_EVENT_ID = BIT(24),
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 06d6943b257c..5bdf7a03e3dd 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1041,7 +1041,8 @@ static int wl18xx_boot(struct wl1271 *wl)
SMART_CONFIG_SYNC_EVENT_ID |
SMART_CONFIG_DECODE_EVENT_ID |
TIME_SYNC_EVENT_ID |
- FW_LOGGER_INDICATION;
+ FW_LOGGER_INDICATION |
+ RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index 26cc23f32241..a4859993db3c 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -1419,7 +1419,8 @@ out:
/* setup BA session receiver setting in the FW. */
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
- u16 ssn, bool enable, u8 peer_hlid)
+ u16 ssn, bool enable, u8 peer_hlid,
+ u8 win_size)
{
struct wl1271_acx_ba_receiver_setup *acx;
int ret;
@@ -1435,7 +1436,7 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
acx->hlid = peer_hlid;
acx->tid = tid_index;
acx->enable = enable;
- acx->win_size = wl->conf.ht.rx_ba_win_size;
+ acx->win_size = win_size;
acx->ssn = ssn;
ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx,
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 6321ed472891..f46d7fdf9a00 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -1113,7 +1113,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
- u16 ssn, bool enable, u8 peer_hlid);
+ u16 ssn, bool enable, u8 peer_hlid,
+ u8 win_size);
int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u64 *mactime);
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 471521a0db7b..e536aa01b937 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5285,7 +5285,9 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
}
ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
- hlid);
+ hlid,
+ params->buf_size);
+
if (!ret) {
*ba_bitmap |= BIT(tid);
wl->ba_rx_session_count++;
@@ -5306,7 +5308,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
}
ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
- hlid);
+ hlid, 0);
if (!ret) {
*ba_bitmap &= ~BIT(tid);
wl->ba_rx_session_count--;
@@ -6086,6 +6088,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
ieee80211_hw_set(wl->hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(wl->hw, SIGNAL_DBM);
ieee80211_hw_set(wl->hw, SUPPORTS_PS);
+ ieee80211_hw_set(wl->hw, SUPPORTS_TX_FRAG);
wl->hw->wiphy->cipher_suites = cipher_suites;
wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
@@ -6120,6 +6123,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
WIPHY_FLAG_SUPPORTS_SCHED_SCAN |
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+ wl->hw->wiphy->features |= NL80211_FEATURE_AP_SCAN;
+
/* make sure all our channels fit in the scanned_ch bitmask */
BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
ARRAY_SIZE(wl1271_channels_5ghz) >
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 932f3f81e8cf..d9d29ab88184 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1853,7 +1853,6 @@ static const struct net_device_ops wl3501_netdev_ops = {
.ndo_stop = wl3501_close,
.ndo_start_xmit = wl3501_hard_start_xmit,
.ndo_tx_timeout = wl3501_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c
index dea049b2556f..de7ff395977a 100644
--- a/drivers/net/wireless/zydas/zd1201.c
+++ b/drivers/net/wireless/zydas/zd1201.c
@@ -1724,7 +1724,6 @@ static const struct net_device_ops zd1201_netdev_ops = {
.ndo_tx_timeout = zd1201_tx_timeout,
.ndo_set_rx_mode = zd1201_set_multicast,
.ndo_set_mac_address = zd1201_set_mac_address,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 74dc2bf71428..e30ffd29b7e9 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -302,7 +302,7 @@ static int xenvif_close(struct net_device *dev)
static int xenvif_change_mtu(struct net_device *dev, int mtu)
{
struct xenvif *vif = netdev_priv(dev);
- int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN;
+ int max = vif->can_sg ? ETH_MAX_MTU - VLAN_ETH_HLEN : ETH_DATA_LEN;
if (mtu > max)
return -EINVAL;
@@ -471,6 +471,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN;
+
/*
* Initialise a dummy MAC address. We choose the numerically
* largest non-broadcast address to prevent the address getting
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 8674e188b697..55a4488633e4 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -889,16 +889,16 @@ static int connect_ctrl_ring(struct backend_info *be)
unsigned int evtchn;
int err;
- err = xenbus_gather(XBT_NIL, dev->otherend,
- "ctrl-ring-ref", "%u", &val, NULL);
- if (err)
+ err = xenbus_scanf(XBT_NIL, dev->otherend,
+ "ctrl-ring-ref", "%u", &val);
+ if (err < 0)
goto done; /* The frontend does not have a control ring */
ring_ref = val;
- err = xenbus_gather(XBT_NIL, dev->otherend,
- "event-channel-ctrl", "%u", &val, NULL);
- if (err) {
+ err = xenbus_scanf(XBT_NIL, dev->otherend,
+ "event-channel-ctrl", "%u", &val);
+ if (err < 0) {
xenbus_dev_fatal(dev, err,
"reading %s/event-channel-ctrl",
dev->otherend);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index bf2744e1e3db..e085c8c31cfe 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1329,6 +1329,8 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
netdev->features |= netdev->hw_features;
netdev->ethtool_ops = &xennet_ethtool_ops;
+ netdev->min_mtu = 0;
+ netdev->max_mtu = XEN_NETIF_MAX_TX_SIZE;
SET_NETDEV_DEV(netdev, &dev->dev);
np->netdev = netdev;
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index 124c2432ac9c..59e750183b7f 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -28,7 +28,7 @@ config BLK_DEV_PMEM
non-standard OEM-specific E820 memory type (type-12, see
CONFIG_X86_PMEM_LEGACY), or it is manually specified by the
'memmap=nn[KMG]!ss[KMG]' kernel command line (see
- Documentation/kernel-parameters.txt). This driver converts
+ Documentation/admin-guide/kernel-parameters.rst). This driver converts
these persistent memory ranges into block devices that are
capable of DAX (direct-access) file system mappings. See
Documentation/nvdimm/nvdimm.txt for more details.
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
index f7d37a62f874..90745a616df7 100644
--- a/drivers/nvme/host/Kconfig
+++ b/drivers/nvme/host/Kconfig
@@ -43,3 +43,20 @@ config NVME_RDMA
from https://github.com/linux-nvme/nvme-cli.
If unsure, say N.
+
+config NVME_FC
+ tristate "NVM Express over Fabrics FC host driver"
+ depends on BLOCK
+ depends on HAS_DMA
+ select NVME_CORE
+ select NVME_FABRICS
+ select SG_POOL
+ help
+ This provides support for the NVMe over Fabrics protocol using
+ the FC transport. This allows you to use remote block devices
+ exported using the NVMe protocol set.
+
+ To configure a NVMe over Fabrics controller use the nvme-cli tool
+ from https://github.com/linux-nvme/nvme-cli.
+
+ If unsure, say N.
diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
index 47abcec23514..f1a7d945fbb6 100644
--- a/drivers/nvme/host/Makefile
+++ b/drivers/nvme/host/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_NVME_CORE) += nvme-core.o
obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
obj-$(CONFIG_NVME_FABRICS) += nvme-fabrics.o
obj-$(CONFIG_NVME_RDMA) += nvme-rdma.o
+obj-$(CONFIG_NVME_FC) += nvme-fc.o
nvme-core-y := core.o
nvme-core-$(CONFIG_BLK_DEV_NVME_SCSI) += scsi.o
@@ -12,3 +13,5 @@ nvme-y += pci.o
nvme-fabrics-y += fabrics.o
nvme-rdma-y += rdma.o
+
+nvme-fc-y += fc.o
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 79e679d12f3b..35b3fee5a453 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -201,13 +201,7 @@ fail:
void nvme_requeue_req(struct request *req)
{
- unsigned long flags;
-
- 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);
+ blk_mq_requeue_request(req, !blk_mq_queue_stopped(req->q));
}
EXPORT_SYMBOL_GPL(nvme_requeue_req);
@@ -227,8 +221,7 @@ struct request *nvme_alloc_request(struct request_queue *q,
req->cmd_type = REQ_TYPE_DRV_PRIV;
req->cmd_flags |= REQ_FAILFAST_DRIVER;
- req->cmd = (unsigned char *)cmd;
- req->cmd_len = sizeof(struct nvme_command);
+ nvme_req(req)->cmd = cmd;
return req;
}
@@ -246,8 +239,6 @@ static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
struct nvme_command *cmnd)
{
struct nvme_dsm_range *range;
- struct page *page;
- int offset;
unsigned int nr_bytes = blk_rq_bytes(req);
range = kmalloc(sizeof(*range), GFP_ATOMIC);
@@ -264,19 +255,27 @@ static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
cmnd->dsm.nr = 0;
cmnd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD);
- req->completion_data = range;
- page = virt_to_page(range);
- offset = offset_in_page(range);
- blk_add_request_payload(req, page, offset, sizeof(*range));
+ req->special_vec.bv_page = virt_to_page(range);
+ req->special_vec.bv_offset = offset_in_page(range);
+ req->special_vec.bv_len = sizeof(*range);
+ req->rq_flags |= RQF_SPECIAL_PAYLOAD;
- /*
- * we set __data_len back to the size of the area to be discarded
- * on disk. This allows us to report completion on the full amount
- * of blocks described by the request.
- */
- req->__data_len = nr_bytes;
+ return BLK_MQ_RQ_QUEUE_OK;
+}
- return 0;
+static inline void nvme_setup_write_zeroes(struct nvme_ns *ns,
+ struct request *req, struct nvme_command *cmnd)
+{
+ struct nvme_write_zeroes_cmd *write_zeroes = &cmnd->write_zeroes;
+
+ memset(cmnd, 0, sizeof(*cmnd));
+ write_zeroes->opcode = nvme_cmd_write_zeroes;
+ write_zeroes->nsid = cpu_to_le32(ns->ns_id);
+ write_zeroes->slba =
+ cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
+ write_zeroes->length =
+ cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
+ write_zeroes->control = 0;
}
static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
@@ -295,7 +294,6 @@ static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
memset(cmnd, 0, sizeof(*cmnd));
cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read);
- cmnd->rw.command_id = req->tag;
cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
@@ -324,17 +322,21 @@ static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
struct nvme_command *cmd)
{
- int ret = 0;
+ int ret = BLK_MQ_RQ_QUEUE_OK;
if (req->cmd_type == REQ_TYPE_DRV_PRIV)
- memcpy(cmd, req->cmd, sizeof(*cmd));
+ memcpy(cmd, nvme_req(req)->cmd, sizeof(*cmd));
else if (req_op(req) == REQ_OP_FLUSH)
nvme_setup_flush(ns, cmd);
else if (req_op(req) == REQ_OP_DISCARD)
ret = nvme_setup_discard(ns, req, cmd);
+ else if (req_op(req) == REQ_OP_WRITE_ZEROES)
+ nvme_setup_write_zeroes(ns, req, cmd);
else
nvme_setup_rw(ns, req, cmd);
+ cmd->common.command_id = req->tag;
+
return ret;
}
EXPORT_SYMBOL_GPL(nvme_setup_cmd);
@@ -344,7 +346,7 @@ EXPORT_SYMBOL_GPL(nvme_setup_cmd);
* if the result is positive, it's an NVM Express status code
*/
int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
- struct nvme_completion *cqe, void *buffer, unsigned bufflen,
+ union nvme_result *result, void *buffer, unsigned bufflen,
unsigned timeout, int qid, int at_head, int flags)
{
struct request *req;
@@ -355,7 +357,6 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
return PTR_ERR(req);
req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
- req->special = cqe;
if (buffer && bufflen) {
ret = blk_rq_map_kern(q, req, buffer, bufflen, GFP_KERNEL);
@@ -364,6 +365,8 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
}
blk_execute_rq(req->q, NULL, req, at_head);
+ if (result)
+ *result = nvme_req(req)->result;
ret = req->errors;
out:
blk_mq_free_request(req);
@@ -385,7 +388,6 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
u32 *result, unsigned timeout)
{
bool write = nvme_is_write(cmd);
- struct nvme_completion cqe;
struct nvme_ns *ns = q->queuedata;
struct gendisk *disk = ns ? ns->disk : NULL;
struct request *req;
@@ -398,7 +400,6 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
return PTR_ERR(req);
req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
- req->special = &cqe;
if (ubuffer && bufflen) {
ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
@@ -453,7 +454,7 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
blk_execute_rq(req->q, disk, req, 0);
ret = req->errors;
if (result)
- *result = le32_to_cpu(cqe.result);
+ *result = le32_to_cpu(nvme_req(req)->result.u32);
if (meta && !ret && !write) {
if (copy_to_user(meta_buffer, meta, meta_len))
ret = -EFAULT;
@@ -602,7 +603,7 @@ int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
void *buffer, size_t buflen, u32 *result)
{
struct nvme_command c;
- struct nvme_completion cqe;
+ union nvme_result res;
int ret;
memset(&c, 0, sizeof(c));
@@ -610,10 +611,10 @@ int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
c.features.nsid = cpu_to_le32(nsid);
c.features.fid = cpu_to_le32(fid);
- ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, buffer, buflen, 0,
+ ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res, buffer, buflen, 0,
NVME_QID_ANY, 0, 0);
if (ret >= 0 && result)
- *result = le32_to_cpu(cqe.result);
+ *result = le32_to_cpu(res.u32);
return ret;
}
@@ -621,7 +622,7 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
void *buffer, size_t buflen, u32 *result)
{
struct nvme_command c;
- struct nvme_completion cqe;
+ union nvme_result res;
int ret;
memset(&c, 0, sizeof(c));
@@ -629,10 +630,10 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
c.features.fid = cpu_to_le32(fid);
c.features.dword11 = cpu_to_le32(dword11);
- ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe,
+ ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res,
buffer, buflen, 0, NVME_QID_ANY, 0, 0);
if (ret >= 0 && result)
- *result = le32_to_cpu(cqe.result);
+ *result = le32_to_cpu(res.u32);
return ret;
}
@@ -951,6 +952,10 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
if (ns->ctrl->oncs & NVME_CTRL_ONCS_DSM)
nvme_config_discard(ns);
+ if (ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES)
+ blk_queue_max_write_zeroes_sectors(ns->queue,
+ ((u32)(USHRT_MAX + 1) * bs) >> 9);
+
blk_mq_unfreeze_queue(disk->queue);
}
@@ -1683,27 +1688,24 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
if (nvme_revalidate_ns(ns, &id))
goto out_free_queue;
- if (nvme_nvm_ns_supported(ns, id)) {
- if (nvme_nvm_register(ns, disk_name, node,
- &nvme_ns_attr_group)) {
- dev_warn(ctrl->dev, "%s: LightNVM init failure\n",
- __func__);
- goto out_free_id;
- }
- } else {
- disk = alloc_disk_node(0, node);
- if (!disk)
- goto out_free_id;
+ if (nvme_nvm_ns_supported(ns, id) &&
+ nvme_nvm_register(ns, disk_name, node)) {
+ dev_warn(ctrl->dev, "%s: LightNVM init failure\n", __func__);
+ goto out_free_id;
+ }
- disk->fops = &nvme_fops;
- disk->private_data = ns;
- disk->queue = ns->queue;
- disk->flags = GENHD_FL_EXT_DEVT;
- memcpy(disk->disk_name, disk_name, DISK_NAME_LEN);
- ns->disk = disk;
+ disk = alloc_disk_node(0, node);
+ if (!disk)
+ goto out_free_id;
- __nvme_revalidate_disk(disk, id);
- }
+ disk->fops = &nvme_fops;
+ disk->private_data = ns;
+ disk->queue = ns->queue;
+ disk->flags = GENHD_FL_EXT_DEVT;
+ memcpy(disk->disk_name, disk_name, DISK_NAME_LEN);
+ ns->disk = disk;
+
+ __nvme_revalidate_disk(disk, id);
mutex_lock(&ctrl->namespaces_mutex);
list_add_tail(&ns->list, &ctrl->namespaces);
@@ -1713,14 +1715,14 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
kfree(id);
- if (ns->ndev)
- return;
-
device_add_disk(ctrl->device, ns->disk);
if (sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
&nvme_ns_attr_group))
pr_warn("%s: failed to create sysfs group for identification\n",
ns->disk->disk_name);
+ if (ns->ndev && nvme_nvm_register_sysfs(ns))
+ pr_warn("%s: failed to register lightnvm sysfs group for identification\n",
+ ns->disk->disk_name);
return;
out_free_id:
kfree(id);
@@ -1742,6 +1744,8 @@ static void nvme_ns_remove(struct nvme_ns *ns)
blk_integrity_unregister(ns->disk);
sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
&nvme_ns_attr_group);
+ if (ns->ndev)
+ nvme_nvm_unregister_sysfs(ns);
del_gendisk(ns->disk);
blk_mq_abort_requeue_list(ns->queue);
blk_cleanup_queue(ns->queue);
@@ -1905,18 +1909,25 @@ static void nvme_async_event_work(struct work_struct *work)
spin_unlock_irq(&ctrl->lock);
}
-void nvme_complete_async_event(struct nvme_ctrl *ctrl,
- struct nvme_completion *cqe)
+void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
+ union nvme_result *res)
{
- u16 status = le16_to_cpu(cqe->status) >> 1;
- u32 result = le32_to_cpu(cqe->result);
+ u32 result = le32_to_cpu(res->u32);
+ bool done = true;
- if (status == NVME_SC_SUCCESS || status == NVME_SC_ABORT_REQ) {
+ switch (le16_to_cpu(status) >> 1) {
+ case NVME_SC_SUCCESS:
+ done = false;
+ /*FALLTHRU*/
+ case NVME_SC_ABORT_REQ:
++ctrl->event_limit;
schedule_work(&ctrl->async_event_work);
+ break;
+ default:
+ break;
}
- if (status != NVME_SC_SUCCESS)
+ if (done)
return;
switch (result & 0xff07) {
@@ -2078,14 +2089,8 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl)
struct nvme_ns *ns;
mutex_lock(&ctrl->namespaces_mutex);
- list_for_each_entry(ns, &ctrl->namespaces, list) {
- spin_lock_irq(ns->queue->queue_lock);
- queue_flag_set(QUEUE_FLAG_STOPPED, ns->queue);
- spin_unlock_irq(ns->queue->queue_lock);
-
- blk_mq_cancel_requeue_work(ns->queue);
- blk_mq_stop_hw_queues(ns->queue);
- }
+ list_for_each_entry(ns, &ctrl->namespaces, list)
+ blk_mq_quiesce_queue(ns->queue);
mutex_unlock(&ctrl->namespaces_mutex);
}
EXPORT_SYMBOL_GPL(nvme_stop_queues);
@@ -2096,7 +2101,6 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
mutex_lock(&ctrl->namespaces_mutex);
list_for_each_entry(ns, &ctrl->namespaces, list) {
- queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, ns->queue);
blk_mq_start_stopped_hw_queues(ns->queue, true);
blk_mq_kick_requeue_list(ns->queue);
}
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 5a3f008d3480..916d13608059 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -161,7 +161,7 @@ EXPORT_SYMBOL_GPL(nvmf_get_subsysnqn);
int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
{
struct nvme_command cmd;
- struct nvme_completion cqe;
+ union nvme_result res;
int ret;
memset(&cmd, 0, sizeof(cmd));
@@ -169,11 +169,11 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
cmd.prop_get.fctype = nvme_fabrics_type_property_get;
cmd.prop_get.offset = cpu_to_le32(off);
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &cqe, NULL, 0, 0,
+ ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
NVME_QID_ANY, 0, 0);
if (ret >= 0)
- *val = le64_to_cpu(cqe.result64);
+ *val = le64_to_cpu(res.u64);
if (unlikely(ret != 0))
dev_err(ctrl->device,
"Property Get error: %d, offset %#x\n",
@@ -207,7 +207,7 @@ EXPORT_SYMBOL_GPL(nvmf_reg_read32);
int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
{
struct nvme_command cmd;
- struct nvme_completion cqe;
+ union nvme_result res;
int ret;
memset(&cmd, 0, sizeof(cmd));
@@ -216,11 +216,11 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
cmd.prop_get.attrib = 1;
cmd.prop_get.offset = cpu_to_le32(off);
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &cqe, NULL, 0, 0,
+ ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
NVME_QID_ANY, 0, 0);
if (ret >= 0)
- *val = le64_to_cpu(cqe.result64);
+ *val = le64_to_cpu(res.u64);
if (unlikely(ret != 0))
dev_err(ctrl->device,
"Property Get error: %d, offset %#x\n",
@@ -368,7 +368,7 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
{
struct nvme_command cmd;
- struct nvme_completion cqe;
+ union nvme_result res;
struct nvmf_connect_data *data;
int ret;
@@ -400,16 +400,16 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
- ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &cqe,
+ ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res,
data, sizeof(*data), 0, NVME_QID_ANY, 1,
BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
if (ret) {
- nvmf_log_connect_error(ctrl, ret, le32_to_cpu(cqe.result),
+ nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
&cmd, data);
goto out_free_data;
}
- ctrl->cntlid = le16_to_cpu(cqe.result16);
+ ctrl->cntlid = le16_to_cpu(res.u16);
out_free_data:
kfree(data);
@@ -441,7 +441,7 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
{
struct nvme_command cmd;
struct nvmf_connect_data *data;
- struct nvme_completion cqe;
+ union nvme_result res;
int ret;
memset(&cmd, 0, sizeof(cmd));
@@ -459,11 +459,11 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
- ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &cqe,
+ ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res,
data, sizeof(*data), 0, qid, 1,
BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
if (ret) {
- nvmf_log_connect_error(ctrl, ret, le32_to_cpu(cqe.result),
+ nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
&cmd, data);
}
kfree(data);
@@ -576,7 +576,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
nqnlen = strlen(opts->subsysnqn);
if (nqnlen >= NVMF_NQN_SIZE) {
pr_err("%s needs to be < %d bytes\n",
- opts->subsysnqn, NVMF_NQN_SIZE);
+ opts->subsysnqn, NVMF_NQN_SIZE);
ret = -EINVAL;
goto out;
}
@@ -666,10 +666,12 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
if (nqnlen >= NVMF_NQN_SIZE) {
pr_err("%s needs to be < %d bytes\n",
p, NVMF_NQN_SIZE);
+ kfree(p);
ret = -EINVAL;
goto out;
}
opts->host = nvmf_host_add(p);
+ kfree(p);
if (!opts->host) {
ret = -ENOMEM;
goto out;
@@ -825,8 +827,7 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
out_unlock:
mutex_unlock(&nvmf_transports_mutex);
out_free_opts:
- nvmf_host_put(opts->host);
- kfree(opts);
+ nvmf_free_options(opts);
return ERR_PTR(ret);
}
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
new file mode 100644
index 000000000000..771e2e761872
--- /dev/null
+++ b/drivers/nvme/host/fc.c
@@ -0,0 +1,2586 @@
+/*
+ * Copyright (c) 2016 Avago Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO
+ * THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
+ * See the GNU General Public License for more details, a copy of which
+ * can be found in the file COPYING included with this package
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <uapi/scsi/fc/fc_fs.h>
+#include <uapi/scsi/fc/fc_els.h>
+
+#include "nvme.h"
+#include "fabrics.h"
+#include <linux/nvme-fc-driver.h>
+#include <linux/nvme-fc.h>
+
+
+/* *************************** Data Structures/Defines ****************** */
+
+
+/*
+ * We handle AEN commands ourselves and don't even let the
+ * block layer know about them.
+ */
+#define NVME_FC_NR_AEN_COMMANDS 1
+#define NVME_FC_AQ_BLKMQ_DEPTH \
+ (NVMF_AQ_DEPTH - NVME_FC_NR_AEN_COMMANDS)
+#define AEN_CMDID_BASE (NVME_FC_AQ_BLKMQ_DEPTH + 1)
+
+enum nvme_fc_queue_flags {
+ NVME_FC_Q_CONNECTED = (1 << 0),
+};
+
+#define NVMEFC_QUEUE_DELAY 3 /* ms units */
+
+struct nvme_fc_queue {
+ struct nvme_fc_ctrl *ctrl;
+ struct device *dev;
+ struct blk_mq_hw_ctx *hctx;
+ void *lldd_handle;
+ int queue_size;
+ size_t cmnd_capsule_len;
+ u32 qnum;
+ u32 rqcnt;
+ u32 seqno;
+
+ u64 connection_id;
+ atomic_t csn;
+
+ unsigned long flags;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+struct nvmefc_ls_req_op {
+ struct nvmefc_ls_req ls_req;
+
+ struct nvme_fc_ctrl *ctrl;
+ struct nvme_fc_queue *queue;
+ struct request *rq;
+
+ int ls_error;
+ struct completion ls_done;
+ struct list_head lsreq_list; /* ctrl->ls_req_list */
+ bool req_queued;
+};
+
+enum nvme_fcpop_state {
+ FCPOP_STATE_UNINIT = 0,
+ FCPOP_STATE_IDLE = 1,
+ FCPOP_STATE_ACTIVE = 2,
+ FCPOP_STATE_ABORTED = 3,
+};
+
+struct nvme_fc_fcp_op {
+ struct nvme_request nreq; /*
+ * nvme/host/core.c
+ * requires this to be
+ * the 1st element in the
+ * private structure
+ * associated with the
+ * request.
+ */
+ struct nvmefc_fcp_req fcp_req;
+
+ struct nvme_fc_ctrl *ctrl;
+ struct nvme_fc_queue *queue;
+ struct request *rq;
+
+ atomic_t state;
+ u32 rqno;
+ u32 nents;
+
+ struct nvme_fc_cmd_iu cmd_iu;
+ struct nvme_fc_ersp_iu rsp_iu;
+};
+
+struct nvme_fc_lport {
+ struct nvme_fc_local_port localport;
+
+ struct ida endp_cnt;
+ struct list_head port_list; /* nvme_fc_port_list */
+ struct list_head endp_list;
+ struct device *dev; /* physical device for dma */
+ struct nvme_fc_port_template *ops;
+ struct kref ref;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+struct nvme_fc_rport {
+ struct nvme_fc_remote_port remoteport;
+
+ struct list_head endp_list; /* for lport->endp_list */
+ struct list_head ctrl_list;
+ spinlock_t lock;
+ struct kref ref;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+enum nvme_fcctrl_state {
+ FCCTRL_INIT = 0,
+ FCCTRL_ACTIVE = 1,
+};
+
+struct nvme_fc_ctrl {
+ spinlock_t lock;
+ struct nvme_fc_queue *queues;
+ u32 queue_count;
+
+ struct device *dev;
+ struct nvme_fc_lport *lport;
+ struct nvme_fc_rport *rport;
+ u32 cnum;
+
+ u64 association_id;
+
+ u64 cap;
+
+ struct list_head ctrl_list; /* rport->ctrl_list */
+ struct list_head ls_req_list;
+
+ struct blk_mq_tag_set admin_tag_set;
+ struct blk_mq_tag_set tag_set;
+
+ struct work_struct delete_work;
+ struct kref ref;
+ int state;
+
+ struct nvme_fc_fcp_op aen_ops[NVME_FC_NR_AEN_COMMANDS];
+
+ struct nvme_ctrl ctrl;
+};
+
+static inline struct nvme_fc_ctrl *
+to_fc_ctrl(struct nvme_ctrl *ctrl)
+{
+ return container_of(ctrl, struct nvme_fc_ctrl, ctrl);
+}
+
+static inline struct nvme_fc_lport *
+localport_to_lport(struct nvme_fc_local_port *portptr)
+{
+ return container_of(portptr, struct nvme_fc_lport, localport);
+}
+
+static inline struct nvme_fc_rport *
+remoteport_to_rport(struct nvme_fc_remote_port *portptr)
+{
+ return container_of(portptr, struct nvme_fc_rport, remoteport);
+}
+
+static inline struct nvmefc_ls_req_op *
+ls_req_to_lsop(struct nvmefc_ls_req *lsreq)
+{
+ return container_of(lsreq, struct nvmefc_ls_req_op, ls_req);
+}
+
+static inline struct nvme_fc_fcp_op *
+fcp_req_to_fcp_op(struct nvmefc_fcp_req *fcpreq)
+{
+ return container_of(fcpreq, struct nvme_fc_fcp_op, fcp_req);
+}
+
+
+
+/* *************************** Globals **************************** */
+
+
+static DEFINE_SPINLOCK(nvme_fc_lock);
+
+static LIST_HEAD(nvme_fc_lport_list);
+static DEFINE_IDA(nvme_fc_local_port_cnt);
+static DEFINE_IDA(nvme_fc_ctrl_cnt);
+
+static struct workqueue_struct *nvme_fc_wq;
+
+
+
+/* *********************** FC-NVME Port Management ************************ */
+
+static int __nvme_fc_del_ctrl(struct nvme_fc_ctrl *);
+static void __nvme_fc_delete_hw_queue(struct nvme_fc_ctrl *,
+ struct nvme_fc_queue *, unsigned int);
+
+
+/**
+ * nvme_fc_register_localport - transport entry point called by an
+ * LLDD to register the existence of a NVME
+ * host FC port.
+ * @pinfo: pointer to information about the port to be registered
+ * @template: LLDD entrypoints and operational parameters for the port
+ * @dev: physical hardware device node port corresponds to. Will be
+ * used for DMA mappings
+ * @lport_p: pointer to a local port pointer. Upon success, the routine
+ * will allocate a nvme_fc_local_port structure and place its
+ * address in the local port pointer. Upon failure, local port
+ * pointer will be set to 0.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
+ struct nvme_fc_port_template *template,
+ struct device *dev,
+ struct nvme_fc_local_port **portptr)
+{
+ struct nvme_fc_lport *newrec;
+ unsigned long flags;
+ int ret, idx;
+
+ if (!template->localport_delete || !template->remoteport_delete ||
+ !template->ls_req || !template->fcp_io ||
+ !template->ls_abort || !template->fcp_abort ||
+ !template->max_hw_queues || !template->max_sgl_segments ||
+ !template->max_dif_sgl_segments || !template->dma_boundary) {
+ ret = -EINVAL;
+ goto out_reghost_failed;
+ }
+
+ newrec = kmalloc((sizeof(*newrec) + template->local_priv_sz),
+ GFP_KERNEL);
+ if (!newrec) {
+ ret = -ENOMEM;
+ goto out_reghost_failed;
+ }
+
+ idx = ida_simple_get(&nvme_fc_local_port_cnt, 0, 0, GFP_KERNEL);
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out_fail_kfree;
+ }
+
+ if (!get_device(dev) && dev) {
+ ret = -ENODEV;
+ goto out_ida_put;
+ }
+
+ INIT_LIST_HEAD(&newrec->port_list);
+ INIT_LIST_HEAD(&newrec->endp_list);
+ kref_init(&newrec->ref);
+ newrec->ops = template;
+ newrec->dev = dev;
+ ida_init(&newrec->endp_cnt);
+ newrec->localport.private = &newrec[1];
+ newrec->localport.node_name = pinfo->node_name;
+ newrec->localport.port_name = pinfo->port_name;
+ newrec->localport.port_role = pinfo->port_role;
+ newrec->localport.port_id = pinfo->port_id;
+ newrec->localport.port_state = FC_OBJSTATE_ONLINE;
+ newrec->localport.port_num = idx;
+
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_add_tail(&newrec->port_list, &nvme_fc_lport_list);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ if (dev)
+ dma_set_seg_boundary(dev, template->dma_boundary);
+
+ *portptr = &newrec->localport;
+ return 0;
+
+out_ida_put:
+ ida_simple_remove(&nvme_fc_local_port_cnt, idx);
+out_fail_kfree:
+ kfree(newrec);
+out_reghost_failed:
+ *portptr = NULL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nvme_fc_register_localport);
+
+static void
+nvme_fc_free_lport(struct kref *ref)
+{
+ struct nvme_fc_lport *lport =
+ container_of(ref, struct nvme_fc_lport, ref);
+ unsigned long flags;
+
+ WARN_ON(lport->localport.port_state != FC_OBJSTATE_DELETED);
+ WARN_ON(!list_empty(&lport->endp_list));
+
+ /* remove from transport list */
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_del(&lport->port_list);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ /* let the LLDD know we've finished tearing it down */
+ lport->ops->localport_delete(&lport->localport);
+
+ ida_simple_remove(&nvme_fc_local_port_cnt, lport->localport.port_num);
+ ida_destroy(&lport->endp_cnt);
+
+ put_device(lport->dev);
+
+ kfree(lport);
+}
+
+static void
+nvme_fc_lport_put(struct nvme_fc_lport *lport)
+{
+ kref_put(&lport->ref, nvme_fc_free_lport);
+}
+
+static int
+nvme_fc_lport_get(struct nvme_fc_lport *lport)
+{
+ return kref_get_unless_zero(&lport->ref);
+}
+
+/**
+ * nvme_fc_unregister_localport - transport entry point called by an
+ * LLDD to deregister/remove a previously
+ * registered a NVME host FC port.
+ * @localport: pointer to the (registered) local port that is to be
+ * deregistered.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvme_fc_unregister_localport(struct nvme_fc_local_port *portptr)
+{
+ struct nvme_fc_lport *lport = localport_to_lport(portptr);
+ unsigned long flags;
+
+ if (!portptr)
+ return -EINVAL;
+
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+
+ if (portptr->port_state != FC_OBJSTATE_ONLINE) {
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+ return -EINVAL;
+ }
+ portptr->port_state = FC_OBJSTATE_DELETED;
+
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ nvme_fc_lport_put(lport);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_fc_unregister_localport);
+
+/**
+ * nvme_fc_register_remoteport - transport entry point called by an
+ * LLDD to register the existence of a NVME
+ * subsystem FC port on its fabric.
+ * @localport: pointer to the (registered) local port that the remote
+ * subsystem port is connected to.
+ * @pinfo: pointer to information about the port to be registered
+ * @rport_p: pointer to a remote port pointer. Upon success, the routine
+ * will allocate a nvme_fc_remote_port structure and place its
+ * address in the remote port pointer. Upon failure, remote port
+ * pointer will be set to 0.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvme_fc_register_remoteport(struct nvme_fc_local_port *localport,
+ struct nvme_fc_port_info *pinfo,
+ struct nvme_fc_remote_port **portptr)
+{
+ struct nvme_fc_lport *lport = localport_to_lport(localport);
+ struct nvme_fc_rport *newrec;
+ unsigned long flags;
+ int ret, idx;
+
+ newrec = kmalloc((sizeof(*newrec) + lport->ops->remote_priv_sz),
+ GFP_KERNEL);
+ if (!newrec) {
+ ret = -ENOMEM;
+ goto out_reghost_failed;
+ }
+
+ if (!nvme_fc_lport_get(lport)) {
+ ret = -ESHUTDOWN;
+ goto out_kfree_rport;
+ }
+
+ idx = ida_simple_get(&lport->endp_cnt, 0, 0, GFP_KERNEL);
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out_lport_put;
+ }
+
+ INIT_LIST_HEAD(&newrec->endp_list);
+ INIT_LIST_HEAD(&newrec->ctrl_list);
+ kref_init(&newrec->ref);
+ spin_lock_init(&newrec->lock);
+ newrec->remoteport.localport = &lport->localport;
+ newrec->remoteport.private = &newrec[1];
+ newrec->remoteport.port_role = pinfo->port_role;
+ newrec->remoteport.node_name = pinfo->node_name;
+ newrec->remoteport.port_name = pinfo->port_name;
+ newrec->remoteport.port_id = pinfo->port_id;
+ newrec->remoteport.port_state = FC_OBJSTATE_ONLINE;
+ newrec->remoteport.port_num = idx;
+
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_add_tail(&newrec->endp_list, &lport->endp_list);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ *portptr = &newrec->remoteport;
+ return 0;
+
+out_lport_put:
+ nvme_fc_lport_put(lport);
+out_kfree_rport:
+ kfree(newrec);
+out_reghost_failed:
+ *portptr = NULL;
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(nvme_fc_register_remoteport);
+
+static void
+nvme_fc_free_rport(struct kref *ref)
+{
+ struct nvme_fc_rport *rport =
+ container_of(ref, struct nvme_fc_rport, ref);
+ struct nvme_fc_lport *lport =
+ localport_to_lport(rport->remoteport.localport);
+ unsigned long flags;
+
+ WARN_ON(rport->remoteport.port_state != FC_OBJSTATE_DELETED);
+ WARN_ON(!list_empty(&rport->ctrl_list));
+
+ /* remove from lport list */
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_del(&rport->endp_list);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ /* let the LLDD know we've finished tearing it down */
+ lport->ops->remoteport_delete(&rport->remoteport);
+
+ ida_simple_remove(&lport->endp_cnt, rport->remoteport.port_num);
+
+ kfree(rport);
+
+ nvme_fc_lport_put(lport);
+}
+
+static void
+nvme_fc_rport_put(struct nvme_fc_rport *rport)
+{
+ kref_put(&rport->ref, nvme_fc_free_rport);
+}
+
+static int
+nvme_fc_rport_get(struct nvme_fc_rport *rport)
+{
+ return kref_get_unless_zero(&rport->ref);
+}
+
+/**
+ * nvme_fc_unregister_remoteport - transport entry point called by an
+ * LLDD to deregister/remove a previously
+ * registered a NVME subsystem FC port.
+ * @remoteport: pointer to the (registered) remote port that is to be
+ * deregistered.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvme_fc_unregister_remoteport(struct nvme_fc_remote_port *portptr)
+{
+ struct nvme_fc_rport *rport = remoteport_to_rport(portptr);
+ struct nvme_fc_ctrl *ctrl;
+ unsigned long flags;
+
+ if (!portptr)
+ return -EINVAL;
+
+ spin_lock_irqsave(&rport->lock, flags);
+
+ if (portptr->port_state != FC_OBJSTATE_ONLINE) {
+ spin_unlock_irqrestore(&rport->lock, flags);
+ return -EINVAL;
+ }
+ portptr->port_state = FC_OBJSTATE_DELETED;
+
+ /* tear down all associations to the remote port */
+ list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list)
+ __nvme_fc_del_ctrl(ctrl);
+
+ spin_unlock_irqrestore(&rport->lock, flags);
+
+ nvme_fc_rport_put(rport);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_fc_unregister_remoteport);
+
+
+/* *********************** FC-NVME DMA Handling **************************** */
+
+/*
+ * The fcloop device passes in a NULL device pointer. Real LLD's will
+ * pass in a valid device pointer. If NULL is passed to the dma mapping
+ * routines, depending on the platform, it may or may not succeed, and
+ * may crash.
+ *
+ * As such:
+ * Wrapper all the dma routines and check the dev pointer.
+ *
+ * If simple mappings (return just a dma address, we'll noop them,
+ * returning a dma address of 0.
+ *
+ * On more complex mappings (dma_map_sg), a pseudo routine fills
+ * in the scatter list, setting all dma addresses to 0.
+ */
+
+static inline dma_addr_t
+fc_dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ return dev ? dma_map_single(dev, ptr, size, dir) : (dma_addr_t)0L;
+}
+
+static inline int
+fc_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return dev ? dma_mapping_error(dev, dma_addr) : 0;
+}
+
+static inline void
+fc_dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_unmap_single(dev, addr, size, dir);
+}
+
+static inline void
+fc_dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_sync_single_for_cpu(dev, addr, size, dir);
+}
+
+static inline void
+fc_dma_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_sync_single_for_device(dev, addr, size, dir);
+}
+
+/* pseudo dma_map_sg call */
+static int
+fc_map_sg(struct scatterlist *sg, int nents)
+{
+ struct scatterlist *s;
+ int i;
+
+ WARN_ON(nents == 0 || sg[0].length == 0);
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = 0L;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ s->dma_length = s->length;
+#endif
+ }
+ return nents;
+}
+
+static inline int
+fc_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ return dev ? dma_map_sg(dev, sg, nents, dir) : fc_map_sg(sg, nents);
+}
+
+static inline void
+fc_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_unmap_sg(dev, sg, nents, dir);
+}
+
+
+/* *********************** FC-NVME LS Handling **************************** */
+
+static void nvme_fc_ctrl_put(struct nvme_fc_ctrl *);
+static int nvme_fc_ctrl_get(struct nvme_fc_ctrl *);
+
+
+static void
+__nvme_fc_finish_ls_req(struct nvme_fc_ctrl *ctrl,
+ struct nvmefc_ls_req_op *lsop)
+{
+ struct nvmefc_ls_req *lsreq = &lsop->ls_req;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+
+ if (!lsop->req_queued) {
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ return;
+ }
+
+ list_del(&lsop->lsreq_list);
+
+ lsop->req_queued = false;
+
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+
+ fc_dma_unmap_single(ctrl->dev, lsreq->rqstdma,
+ (lsreq->rqstlen + lsreq->rsplen),
+ DMA_BIDIRECTIONAL);
+
+ nvme_fc_ctrl_put(ctrl);
+}
+
+static int
+__nvme_fc_send_ls_req(struct nvme_fc_ctrl *ctrl,
+ struct nvmefc_ls_req_op *lsop,
+ void (*done)(struct nvmefc_ls_req *req, int status))
+{
+ struct nvmefc_ls_req *lsreq = &lsop->ls_req;
+ unsigned long flags;
+ int ret;
+
+ if (!nvme_fc_ctrl_get(ctrl))
+ return -ESHUTDOWN;
+
+ lsreq->done = done;
+ lsop->ctrl = ctrl;
+ lsop->req_queued = false;
+ INIT_LIST_HEAD(&lsop->lsreq_list);
+ init_completion(&lsop->ls_done);
+
+ lsreq->rqstdma = fc_dma_map_single(ctrl->dev, lsreq->rqstaddr,
+ lsreq->rqstlen + lsreq->rsplen,
+ DMA_BIDIRECTIONAL);
+ if (fc_dma_mapping_error(ctrl->dev, lsreq->rqstdma)) {
+ nvme_fc_ctrl_put(ctrl);
+ dev_err(ctrl->dev,
+ "els request command failed EFAULT.\n");
+ return -EFAULT;
+ }
+ lsreq->rspdma = lsreq->rqstdma + lsreq->rqstlen;
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+
+ list_add_tail(&lsop->lsreq_list, &ctrl->ls_req_list);
+
+ lsop->req_queued = true;
+
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+
+ ret = ctrl->lport->ops->ls_req(&ctrl->lport->localport,
+ &ctrl->rport->remoteport, lsreq);
+ if (ret)
+ lsop->ls_error = ret;
+
+ return ret;
+}
+
+static void
+nvme_fc_send_ls_req_done(struct nvmefc_ls_req *lsreq, int status)
+{
+ struct nvmefc_ls_req_op *lsop = ls_req_to_lsop(lsreq);
+
+ lsop->ls_error = status;
+ complete(&lsop->ls_done);
+}
+
+static int
+nvme_fc_send_ls_req(struct nvme_fc_ctrl *ctrl, struct nvmefc_ls_req_op *lsop)
+{
+ struct nvmefc_ls_req *lsreq = &lsop->ls_req;
+ struct fcnvme_ls_rjt *rjt = lsreq->rspaddr;
+ int ret;
+
+ ret = __nvme_fc_send_ls_req(ctrl, lsop, nvme_fc_send_ls_req_done);
+
+ if (!ret)
+ /*
+ * No timeout/not interruptible as we need the struct
+ * to exist until the lldd calls us back. Thus mandate
+ * wait until driver calls back. lldd responsible for
+ * the timeout action
+ */
+ wait_for_completion(&lsop->ls_done);
+
+ __nvme_fc_finish_ls_req(ctrl, lsop);
+
+ if (ret) {
+ dev_err(ctrl->dev,
+ "ls request command failed (%d).\n", ret);
+ return ret;
+ }
+
+ /* ACC or RJT payload ? */
+ if (rjt->w0.ls_cmd == FCNVME_LS_RJT)
+ return -ENXIO;
+
+ return 0;
+}
+
+static void
+nvme_fc_send_ls_req_async(struct nvme_fc_ctrl *ctrl,
+ struct nvmefc_ls_req_op *lsop,
+ void (*done)(struct nvmefc_ls_req *req, int status))
+{
+ int ret;
+
+ ret = __nvme_fc_send_ls_req(ctrl, lsop, done);
+
+ /* don't wait for completion */
+
+ if (ret)
+ done(&lsop->ls_req, ret);
+}
+
+/* Validation Error indexes into the string table below */
+enum {
+ VERR_NO_ERROR = 0,
+ VERR_LSACC = 1,
+ VERR_LSDESC_RQST = 2,
+ VERR_LSDESC_RQST_LEN = 3,
+ VERR_ASSOC_ID = 4,
+ VERR_ASSOC_ID_LEN = 5,
+ VERR_CONN_ID = 6,
+ VERR_CONN_ID_LEN = 7,
+ VERR_CR_ASSOC = 8,
+ VERR_CR_ASSOC_ACC_LEN = 9,
+ VERR_CR_CONN = 10,
+ VERR_CR_CONN_ACC_LEN = 11,
+ VERR_DISCONN = 12,
+ VERR_DISCONN_ACC_LEN = 13,
+};
+
+static char *validation_errors[] = {
+ "OK",
+ "Not LS_ACC",
+ "Not LSDESC_RQST",
+ "Bad LSDESC_RQST Length",
+ "Not Association ID",
+ "Bad Association ID Length",
+ "Not Connection ID",
+ "Bad Connection ID Length",
+ "Not CR_ASSOC Rqst",
+ "Bad CR_ASSOC ACC Length",
+ "Not CR_CONN Rqst",
+ "Bad CR_CONN ACC Length",
+ "Not Disconnect Rqst",
+ "Bad Disconnect ACC Length",
+};
+
+static int
+nvme_fc_connect_admin_queue(struct nvme_fc_ctrl *ctrl,
+ struct nvme_fc_queue *queue, u16 qsize, u16 ersp_ratio)
+{
+ struct nvmefc_ls_req_op *lsop;
+ struct nvmefc_ls_req *lsreq;
+ struct fcnvme_ls_cr_assoc_rqst *assoc_rqst;
+ struct fcnvme_ls_cr_assoc_acc *assoc_acc;
+ int ret, fcret = 0;
+
+ lsop = kzalloc((sizeof(*lsop) +
+ ctrl->lport->ops->lsrqst_priv_sz +
+ sizeof(*assoc_rqst) + sizeof(*assoc_acc)), GFP_KERNEL);
+ if (!lsop) {
+ ret = -ENOMEM;
+ goto out_no_memory;
+ }
+ lsreq = &lsop->ls_req;
+
+ lsreq->private = (void *)&lsop[1];
+ assoc_rqst = (struct fcnvme_ls_cr_assoc_rqst *)
+ (lsreq->private + ctrl->lport->ops->lsrqst_priv_sz);
+ assoc_acc = (struct fcnvme_ls_cr_assoc_acc *)&assoc_rqst[1];
+
+ assoc_rqst->w0.ls_cmd = FCNVME_LS_CREATE_ASSOCIATION;
+ assoc_rqst->desc_list_len =
+ cpu_to_be32(sizeof(struct fcnvme_lsdesc_cr_assoc_cmd));
+
+ assoc_rqst->assoc_cmd.desc_tag =
+ cpu_to_be32(FCNVME_LSDESC_CREATE_ASSOC_CMD);
+ assoc_rqst->assoc_cmd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_cr_assoc_cmd));
+
+ assoc_rqst->assoc_cmd.ersp_ratio = cpu_to_be16(ersp_ratio);
+ assoc_rqst->assoc_cmd.sqsize = cpu_to_be16(qsize);
+ /* Linux supports only Dynamic controllers */
+ assoc_rqst->assoc_cmd.cntlid = cpu_to_be16(0xffff);
+ memcpy(&assoc_rqst->assoc_cmd.hostid, &ctrl->ctrl.opts->host->id,
+ min_t(size_t, FCNVME_ASSOC_HOSTID_LEN, sizeof(uuid_be)));
+ strncpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn,
+ min(FCNVME_ASSOC_HOSTNQN_LEN, NVMF_NQN_SIZE));
+ strncpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn,
+ min(FCNVME_ASSOC_SUBNQN_LEN, NVMF_NQN_SIZE));
+
+ lsop->queue = queue;
+ lsreq->rqstaddr = assoc_rqst;
+ lsreq->rqstlen = sizeof(*assoc_rqst);
+ lsreq->rspaddr = assoc_acc;
+ lsreq->rsplen = sizeof(*assoc_acc);
+ lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+
+ ret = nvme_fc_send_ls_req(ctrl, lsop);
+ if (ret)
+ goto out_free_buffer;
+
+ /* process connect LS completion */
+
+ /* validate the ACC response */
+ if (assoc_acc->hdr.w0.ls_cmd != FCNVME_LS_ACC)
+ fcret = VERR_LSACC;
+ if (assoc_acc->hdr.desc_list_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_cr_assoc_acc)))
+ fcret = VERR_CR_ASSOC_ACC_LEN;
+ if (assoc_acc->hdr.rqst.desc_tag != cpu_to_be32(FCNVME_LSDESC_RQST))
+ fcret = VERR_LSDESC_RQST;
+ else if (assoc_acc->hdr.rqst.desc_len !=
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst)))
+ fcret = VERR_LSDESC_RQST_LEN;
+ else if (assoc_acc->hdr.rqst.w0.ls_cmd != FCNVME_LS_CREATE_ASSOCIATION)
+ fcret = VERR_CR_ASSOC;
+ else if (assoc_acc->associd.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
+ fcret = VERR_ASSOC_ID;
+ else if (assoc_acc->associd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id)))
+ fcret = VERR_ASSOC_ID_LEN;
+ else if (assoc_acc->connectid.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_CONN_ID))
+ fcret = VERR_CONN_ID;
+ else if (assoc_acc->connectid.desc_len !=
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_conn_id)))
+ fcret = VERR_CONN_ID_LEN;
+
+ if (fcret) {
+ ret = -EBADF;
+ dev_err(ctrl->dev,
+ "q %d connect failed: %s\n",
+ queue->qnum, validation_errors[fcret]);
+ } else {
+ ctrl->association_id =
+ be64_to_cpu(assoc_acc->associd.association_id);
+ queue->connection_id =
+ be64_to_cpu(assoc_acc->connectid.connection_id);
+ set_bit(NVME_FC_Q_CONNECTED, &queue->flags);
+ }
+
+out_free_buffer:
+ kfree(lsop);
+out_no_memory:
+ if (ret)
+ dev_err(ctrl->dev,
+ "queue %d connect admin queue failed (%d).\n",
+ queue->qnum, ret);
+ return ret;
+}
+
+static int
+nvme_fc_connect_queue(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
+ u16 qsize, u16 ersp_ratio)
+{
+ struct nvmefc_ls_req_op *lsop;
+ struct nvmefc_ls_req *lsreq;
+ struct fcnvme_ls_cr_conn_rqst *conn_rqst;
+ struct fcnvme_ls_cr_conn_acc *conn_acc;
+ int ret, fcret = 0;
+
+ lsop = kzalloc((sizeof(*lsop) +
+ ctrl->lport->ops->lsrqst_priv_sz +
+ sizeof(*conn_rqst) + sizeof(*conn_acc)), GFP_KERNEL);
+ if (!lsop) {
+ ret = -ENOMEM;
+ goto out_no_memory;
+ }
+ lsreq = &lsop->ls_req;
+
+ lsreq->private = (void *)&lsop[1];
+ conn_rqst = (struct fcnvme_ls_cr_conn_rqst *)
+ (lsreq->private + ctrl->lport->ops->lsrqst_priv_sz);
+ conn_acc = (struct fcnvme_ls_cr_conn_acc *)&conn_rqst[1];
+
+ conn_rqst->w0.ls_cmd = FCNVME_LS_CREATE_CONNECTION;
+ conn_rqst->desc_list_len = cpu_to_be32(
+ sizeof(struct fcnvme_lsdesc_assoc_id) +
+ sizeof(struct fcnvme_lsdesc_cr_conn_cmd));
+
+ conn_rqst->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
+ conn_rqst->associd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id));
+ conn_rqst->associd.association_id = cpu_to_be64(ctrl->association_id);
+ conn_rqst->connect_cmd.desc_tag =
+ cpu_to_be32(FCNVME_LSDESC_CREATE_CONN_CMD);
+ conn_rqst->connect_cmd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_cr_conn_cmd));
+ conn_rqst->connect_cmd.ersp_ratio = cpu_to_be16(ersp_ratio);
+ conn_rqst->connect_cmd.qid = cpu_to_be16(queue->qnum);
+ conn_rqst->connect_cmd.sqsize = cpu_to_be16(qsize);
+
+ lsop->queue = queue;
+ lsreq->rqstaddr = conn_rqst;
+ lsreq->rqstlen = sizeof(*conn_rqst);
+ lsreq->rspaddr = conn_acc;
+ lsreq->rsplen = sizeof(*conn_acc);
+ lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+
+ ret = nvme_fc_send_ls_req(ctrl, lsop);
+ if (ret)
+ goto out_free_buffer;
+
+ /* process connect LS completion */
+
+ /* validate the ACC response */
+ if (conn_acc->hdr.w0.ls_cmd != FCNVME_LS_ACC)
+ fcret = VERR_LSACC;
+ if (conn_acc->hdr.desc_list_len !=
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_cr_conn_acc)))
+ fcret = VERR_CR_CONN_ACC_LEN;
+ if (conn_acc->hdr.rqst.desc_tag != cpu_to_be32(FCNVME_LSDESC_RQST))
+ fcret = VERR_LSDESC_RQST;
+ else if (conn_acc->hdr.rqst.desc_len !=
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst)))
+ fcret = VERR_LSDESC_RQST_LEN;
+ else if (conn_acc->hdr.rqst.w0.ls_cmd != FCNVME_LS_CREATE_CONNECTION)
+ fcret = VERR_CR_CONN;
+ else if (conn_acc->connectid.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_CONN_ID))
+ fcret = VERR_CONN_ID;
+ else if (conn_acc->connectid.desc_len !=
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_conn_id)))
+ fcret = VERR_CONN_ID_LEN;
+
+ if (fcret) {
+ ret = -EBADF;
+ dev_err(ctrl->dev,
+ "q %d connect failed: %s\n",
+ queue->qnum, validation_errors[fcret]);
+ } else {
+ queue->connection_id =
+ be64_to_cpu(conn_acc->connectid.connection_id);
+ set_bit(NVME_FC_Q_CONNECTED, &queue->flags);
+ }
+
+out_free_buffer:
+ kfree(lsop);
+out_no_memory:
+ if (ret)
+ dev_err(ctrl->dev,
+ "queue %d connect command failed (%d).\n",
+ queue->qnum, ret);
+ return ret;
+}
+
+static void
+nvme_fc_disconnect_assoc_done(struct nvmefc_ls_req *lsreq, int status)
+{
+ struct nvmefc_ls_req_op *lsop = ls_req_to_lsop(lsreq);
+ struct nvme_fc_ctrl *ctrl = lsop->ctrl;
+
+ __nvme_fc_finish_ls_req(ctrl, lsop);
+
+ if (status)
+ dev_err(ctrl->dev,
+ "disconnect assoc ls request command failed (%d).\n",
+ status);
+
+ /* fc-nvme iniator doesn't care about success or failure of cmd */
+
+ kfree(lsop);
+}
+
+/*
+ * This routine sends a FC-NVME LS to disconnect (aka terminate)
+ * the FC-NVME Association. Terminating the association also
+ * terminates the FC-NVME connections (per queue, both admin and io
+ * queues) that are part of the association. E.g. things are torn
+ * down, and the related FC-NVME Association ID and Connection IDs
+ * become invalid.
+ *
+ * The behavior of the fc-nvme initiator is such that it's
+ * understanding of the association and connections will implicitly
+ * be torn down. The action is implicit as it may be due to a loss of
+ * connectivity with the fc-nvme target, so you may never get a
+ * response even if you tried. As such, the action of this routine
+ * is to asynchronously send the LS, ignore any results of the LS, and
+ * continue on with terminating the association. If the fc-nvme target
+ * is present and receives the LS, it too can tear down.
+ */
+static void
+nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
+{
+ struct fcnvme_ls_disconnect_rqst *discon_rqst;
+ struct fcnvme_ls_disconnect_acc *discon_acc;
+ struct nvmefc_ls_req_op *lsop;
+ struct nvmefc_ls_req *lsreq;
+
+ lsop = kzalloc((sizeof(*lsop) +
+ ctrl->lport->ops->lsrqst_priv_sz +
+ sizeof(*discon_rqst) + sizeof(*discon_acc)),
+ GFP_KERNEL);
+ if (!lsop)
+ /* couldn't sent it... too bad */
+ return;
+
+ lsreq = &lsop->ls_req;
+
+ lsreq->private = (void *)&lsop[1];
+ discon_rqst = (struct fcnvme_ls_disconnect_rqst *)
+ (lsreq->private + ctrl->lport->ops->lsrqst_priv_sz);
+ discon_acc = (struct fcnvme_ls_disconnect_acc *)&discon_rqst[1];
+
+ discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT;
+ discon_rqst->desc_list_len = cpu_to_be32(
+ sizeof(struct fcnvme_lsdesc_assoc_id) +
+ sizeof(struct fcnvme_lsdesc_disconn_cmd));
+
+ discon_rqst->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
+ discon_rqst->associd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id));
+
+ discon_rqst->associd.association_id = cpu_to_be64(ctrl->association_id);
+
+ discon_rqst->discon_cmd.desc_tag = cpu_to_be32(
+ FCNVME_LSDESC_DISCONN_CMD);
+ discon_rqst->discon_cmd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_disconn_cmd));
+ discon_rqst->discon_cmd.scope = FCNVME_DISCONN_ASSOCIATION;
+ discon_rqst->discon_cmd.id = cpu_to_be64(ctrl->association_id);
+
+ lsreq->rqstaddr = discon_rqst;
+ lsreq->rqstlen = sizeof(*discon_rqst);
+ lsreq->rspaddr = discon_acc;
+ lsreq->rsplen = sizeof(*discon_acc);
+ lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+
+ nvme_fc_send_ls_req_async(ctrl, lsop, nvme_fc_disconnect_assoc_done);
+
+ /* only meaningful part to terminating the association */
+ ctrl->association_id = 0;
+}
+
+
+/* *********************** NVME Ctrl Routines **************************** */
+
+
+static int
+nvme_fc_reinit_request(void *data, struct request *rq)
+{
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
+
+ memset(cmdiu, 0, sizeof(*cmdiu));
+ cmdiu->scsi_id = NVME_CMD_SCSI_ID;
+ cmdiu->fc_id = NVME_CMD_FC_ID;
+ cmdiu->iu_len = cpu_to_be16(sizeof(*cmdiu) / sizeof(u32));
+ memset(&op->rsp_iu, 0, sizeof(op->rsp_iu));
+
+ return 0;
+}
+
+static void
+__nvme_fc_exit_request(struct nvme_fc_ctrl *ctrl,
+ struct nvme_fc_fcp_op *op)
+{
+ fc_dma_unmap_single(ctrl->lport->dev, op->fcp_req.rspdma,
+ sizeof(op->rsp_iu), DMA_FROM_DEVICE);
+ fc_dma_unmap_single(ctrl->lport->dev, op->fcp_req.cmddma,
+ sizeof(op->cmd_iu), DMA_TO_DEVICE);
+
+ atomic_set(&op->state, FCPOP_STATE_UNINIT);
+}
+
+static void
+nvme_fc_exit_request(void *data, struct request *rq,
+ unsigned int hctx_idx, unsigned int rq_idx)
+{
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+
+ return __nvme_fc_exit_request(data, op);
+}
+
+static void
+nvme_fc_exit_aen_ops(struct nvme_fc_ctrl *ctrl)
+{
+ struct nvme_fc_fcp_op *aen_op = ctrl->aen_ops;
+ int i;
+
+ for (i = 0; i < NVME_FC_NR_AEN_COMMANDS; i++, aen_op++) {
+ if (atomic_read(&aen_op->state) == FCPOP_STATE_UNINIT)
+ continue;
+ __nvme_fc_exit_request(ctrl, aen_op);
+ nvme_fc_ctrl_put(ctrl);
+ }
+}
+
+void
+nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
+{
+ struct nvme_fc_fcp_op *op = fcp_req_to_fcp_op(req);
+ struct request *rq = op->rq;
+ struct nvmefc_fcp_req *freq = &op->fcp_req;
+ struct nvme_fc_ctrl *ctrl = op->ctrl;
+ struct nvme_fc_queue *queue = op->queue;
+ struct nvme_completion *cqe = &op->rsp_iu.cqe;
+ u16 status;
+
+ /*
+ * WARNING:
+ * The current linux implementation of a nvme controller
+ * allocates a single tag set for all io queues and sizes
+ * the io queues to fully hold all possible tags. Thus, the
+ * implementation does not reference or care about the sqhd
+ * value as it never needs to use the sqhd/sqtail pointers
+ * for submission pacing.
+ *
+ * This affects the FC-NVME implementation in two ways:
+ * 1) As the value doesn't matter, we don't need to waste
+ * cycles extracting it from ERSPs and stamping it in the
+ * cases where the transport fabricates CQEs on successful
+ * completions.
+ * 2) The FC-NVME implementation requires that delivery of
+ * ERSP completions are to go back to the nvme layer in order
+ * relative to the rsn, such that the sqhd value will always
+ * be "in order" for the nvme layer. As the nvme layer in
+ * linux doesn't care about sqhd, there's no need to return
+ * them in order.
+ *
+ * Additionally:
+ * As the core nvme layer in linux currently does not look at
+ * every field in the cqe - in cases where the FC transport must
+ * fabricate a CQE, the following fields will not be set as they
+ * are not referenced:
+ * cqe.sqid, cqe.sqhd, cqe.command_id
+ */
+
+ fc_dma_sync_single_for_cpu(ctrl->lport->dev, op->fcp_req.rspdma,
+ sizeof(op->rsp_iu), DMA_FROM_DEVICE);
+
+ if (atomic_read(&op->state) == FCPOP_STATE_ABORTED)
+ status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+ else
+ status = freq->status;
+
+ /*
+ * For the linux implementation, if we have an unsuccesful
+ * status, they blk-mq layer can typically be called with the
+ * non-zero status and the content of the cqe isn't important.
+ */
+ if (status)
+ goto done;
+
+ /*
+ * command completed successfully relative to the wire
+ * protocol. However, validate anything received and
+ * extract the status and result from the cqe (create it
+ * where necessary).
+ */
+
+ switch (freq->rcv_rsplen) {
+
+ case 0:
+ case NVME_FC_SIZEOF_ZEROS_RSP:
+ /*
+ * No response payload or 12 bytes of payload (which
+ * should all be zeros) are considered successful and
+ * no payload in the CQE by the transport.
+ */
+ if (freq->transferred_length !=
+ be32_to_cpu(op->cmd_iu.data_len)) {
+ status = -EIO;
+ goto done;
+ }
+ op->nreq.result.u64 = 0;
+ break;
+
+ case sizeof(struct nvme_fc_ersp_iu):
+ /*
+ * The ERSP IU contains a full completion with CQE.
+ * Validate ERSP IU and look at cqe.
+ */
+ if (unlikely(be16_to_cpu(op->rsp_iu.iu_len) !=
+ (freq->rcv_rsplen / 4) ||
+ be32_to_cpu(op->rsp_iu.xfrd_len) !=
+ freq->transferred_length ||
+ op->rqno != le16_to_cpu(cqe->command_id))) {
+ status = -EIO;
+ goto done;
+ }
+ op->nreq.result = cqe->result;
+ status = le16_to_cpu(cqe->status) >> 1;
+ break;
+
+ default:
+ status = -EIO;
+ goto done;
+ }
+
+done:
+ if (!queue->qnum && op->rqno >= AEN_CMDID_BASE) {
+ nvme_complete_async_event(&queue->ctrl->ctrl, status,
+ &op->nreq.result);
+ nvme_fc_ctrl_put(ctrl);
+ return;
+ }
+
+ blk_mq_complete_request(rq, status);
+}
+
+static int
+__nvme_fc_init_request(struct nvme_fc_ctrl *ctrl,
+ struct nvme_fc_queue *queue, struct nvme_fc_fcp_op *op,
+ struct request *rq, u32 rqno)
+{
+ struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
+ int ret = 0;
+
+ memset(op, 0, sizeof(*op));
+ op->fcp_req.cmdaddr = &op->cmd_iu;
+ op->fcp_req.cmdlen = sizeof(op->cmd_iu);
+ op->fcp_req.rspaddr = &op->rsp_iu;
+ op->fcp_req.rsplen = sizeof(op->rsp_iu);
+ op->fcp_req.done = nvme_fc_fcpio_done;
+ op->fcp_req.first_sgl = (struct scatterlist *)&op[1];
+ op->fcp_req.private = &op->fcp_req.first_sgl[SG_CHUNK_SIZE];
+ op->ctrl = ctrl;
+ op->queue = queue;
+ op->rq = rq;
+ op->rqno = rqno;
+
+ cmdiu->scsi_id = NVME_CMD_SCSI_ID;
+ cmdiu->fc_id = NVME_CMD_FC_ID;
+ cmdiu->iu_len = cpu_to_be16(sizeof(*cmdiu) / sizeof(u32));
+
+ op->fcp_req.cmddma = fc_dma_map_single(ctrl->lport->dev,
+ &op->cmd_iu, sizeof(op->cmd_iu), DMA_TO_DEVICE);
+ if (fc_dma_mapping_error(ctrl->lport->dev, op->fcp_req.cmddma)) {
+ dev_err(ctrl->dev,
+ "FCP Op failed - cmdiu dma mapping failed.\n");
+ ret = EFAULT;
+ goto out_on_error;
+ }
+
+ op->fcp_req.rspdma = fc_dma_map_single(ctrl->lport->dev,
+ &op->rsp_iu, sizeof(op->rsp_iu),
+ DMA_FROM_DEVICE);
+ if (fc_dma_mapping_error(ctrl->lport->dev, op->fcp_req.rspdma)) {
+ dev_err(ctrl->dev,
+ "FCP Op failed - rspiu dma mapping failed.\n");
+ ret = EFAULT;
+ }
+
+ atomic_set(&op->state, FCPOP_STATE_IDLE);
+out_on_error:
+ return ret;
+}
+
+static int
+nvme_fc_init_request(void *data, struct request *rq,
+ unsigned int hctx_idx, unsigned int rq_idx,
+ unsigned int numa_node)
+{
+ struct nvme_fc_ctrl *ctrl = data;
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_queue *queue = &ctrl->queues[hctx_idx+1];
+
+ return __nvme_fc_init_request(ctrl, queue, op, rq, queue->rqcnt++);
+}
+
+static int
+nvme_fc_init_admin_request(void *data, struct request *rq,
+ unsigned int hctx_idx, unsigned int rq_idx,
+ unsigned int numa_node)
+{
+ struct nvme_fc_ctrl *ctrl = data;
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_queue *queue = &ctrl->queues[0];
+
+ return __nvme_fc_init_request(ctrl, queue, op, rq, queue->rqcnt++);
+}
+
+static int
+nvme_fc_init_aen_ops(struct nvme_fc_ctrl *ctrl)
+{
+ struct nvme_fc_fcp_op *aen_op;
+ struct nvme_fc_cmd_iu *cmdiu;
+ struct nvme_command *sqe;
+ int i, ret;
+
+ aen_op = ctrl->aen_ops;
+ for (i = 0; i < NVME_FC_NR_AEN_COMMANDS; i++, aen_op++) {
+ cmdiu = &aen_op->cmd_iu;
+ sqe = &cmdiu->sqe;
+ ret = __nvme_fc_init_request(ctrl, &ctrl->queues[0],
+ aen_op, (struct request *)NULL,
+ (AEN_CMDID_BASE + i));
+ if (ret)
+ return ret;
+
+ memset(sqe, 0, sizeof(*sqe));
+ sqe->common.opcode = nvme_admin_async_event;
+ sqe->common.command_id = AEN_CMDID_BASE + i;
+ }
+ return 0;
+}
+
+
+static inline void
+__nvme_fc_init_hctx(struct blk_mq_hw_ctx *hctx, struct nvme_fc_ctrl *ctrl,
+ unsigned int qidx)
+{
+ struct nvme_fc_queue *queue = &ctrl->queues[qidx];
+
+ hctx->driver_data = queue;
+ queue->hctx = hctx;
+}
+
+static int
+nvme_fc_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
+ unsigned int hctx_idx)
+{
+ struct nvme_fc_ctrl *ctrl = data;
+
+ __nvme_fc_init_hctx(hctx, ctrl, hctx_idx + 1);
+
+ return 0;
+}
+
+static int
+nvme_fc_init_admin_hctx(struct blk_mq_hw_ctx *hctx, void *data,
+ unsigned int hctx_idx)
+{
+ struct nvme_fc_ctrl *ctrl = data;
+
+ __nvme_fc_init_hctx(hctx, ctrl, hctx_idx);
+
+ return 0;
+}
+
+static void
+nvme_fc_init_queue(struct nvme_fc_ctrl *ctrl, int idx, size_t queue_size)
+{
+ struct nvme_fc_queue *queue;
+
+ queue = &ctrl->queues[idx];
+ memset(queue, 0, sizeof(*queue));
+ queue->ctrl = ctrl;
+ queue->qnum = idx;
+ atomic_set(&queue->csn, 1);
+ queue->dev = ctrl->dev;
+
+ if (idx > 0)
+ queue->cmnd_capsule_len = ctrl->ctrl.ioccsz * 16;
+ else
+ queue->cmnd_capsule_len = sizeof(struct nvme_command);
+
+ queue->queue_size = queue_size;
+
+ /*
+ * Considered whether we should allocate buffers for all SQEs
+ * and CQEs and dma map them - mapping their respective entries
+ * into the request structures (kernel vm addr and dma address)
+ * thus the driver could use the buffers/mappings directly.
+ * It only makes sense if the LLDD would use them for its
+ * messaging api. It's very unlikely most adapter api's would use
+ * a native NVME sqe/cqe. More reasonable if FC-NVME IU payload
+ * structures were used instead.
+ */
+}
+
+/*
+ * This routine terminates a queue at the transport level.
+ * The transport has already ensured that all outstanding ios on
+ * the queue have been terminated.
+ * The transport will send a Disconnect LS request to terminate
+ * the queue's connection. Termination of the admin queue will also
+ * terminate the association at the target.
+ */
+static void
+nvme_fc_free_queue(struct nvme_fc_queue *queue)
+{
+ if (!test_and_clear_bit(NVME_FC_Q_CONNECTED, &queue->flags))
+ return;
+
+ /*
+ * Current implementation never disconnects a single queue.
+ * It always terminates a whole association. So there is never
+ * a disconnect(queue) LS sent to the target.
+ */
+
+ queue->connection_id = 0;
+ clear_bit(NVME_FC_Q_CONNECTED, &queue->flags);
+}
+
+static void
+__nvme_fc_delete_hw_queue(struct nvme_fc_ctrl *ctrl,
+ struct nvme_fc_queue *queue, unsigned int qidx)
+{
+ if (ctrl->lport->ops->delete_queue)
+ ctrl->lport->ops->delete_queue(&ctrl->lport->localport, qidx,
+ queue->lldd_handle);
+ queue->lldd_handle = NULL;
+}
+
+static void
+nvme_fc_destroy_admin_queue(struct nvme_fc_ctrl *ctrl)
+{
+ __nvme_fc_delete_hw_queue(ctrl, &ctrl->queues[0], 0);
+ blk_cleanup_queue(ctrl->ctrl.admin_q);
+ blk_mq_free_tag_set(&ctrl->admin_tag_set);
+ nvme_fc_free_queue(&ctrl->queues[0]);
+}
+
+static void
+nvme_fc_free_io_queues(struct nvme_fc_ctrl *ctrl)
+{
+ int i;
+
+ for (i = 1; i < ctrl->queue_count; i++)
+ nvme_fc_free_queue(&ctrl->queues[i]);
+}
+
+static int
+__nvme_fc_create_hw_queue(struct nvme_fc_ctrl *ctrl,
+ struct nvme_fc_queue *queue, unsigned int qidx, u16 qsize)
+{
+ int ret = 0;
+
+ queue->lldd_handle = NULL;
+ if (ctrl->lport->ops->create_queue)
+ ret = ctrl->lport->ops->create_queue(&ctrl->lport->localport,
+ qidx, qsize, &queue->lldd_handle);
+
+ return ret;
+}
+
+static void
+nvme_fc_delete_hw_io_queues(struct nvme_fc_ctrl *ctrl)
+{
+ struct nvme_fc_queue *queue = &ctrl->queues[ctrl->queue_count - 1];
+ int i;
+
+ for (i = ctrl->queue_count - 1; i >= 1; i--, queue--)
+ __nvme_fc_delete_hw_queue(ctrl, queue, i);
+}
+
+static int
+nvme_fc_create_hw_io_queues(struct nvme_fc_ctrl *ctrl, u16 qsize)
+{
+ struct nvme_fc_queue *queue = &ctrl->queues[1];
+ int i, j, ret;
+
+ for (i = 1; i < ctrl->queue_count; i++, queue++) {
+ ret = __nvme_fc_create_hw_queue(ctrl, queue, i, qsize);
+ if (ret) {
+ for (j = i-1; j >= 0; j--)
+ __nvme_fc_delete_hw_queue(ctrl,
+ &ctrl->queues[j], j);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int
+nvme_fc_connect_io_queues(struct nvme_fc_ctrl *ctrl, u16 qsize)
+{
+ int i, ret = 0;
+
+ for (i = 1; i < ctrl->queue_count; i++) {
+ ret = nvme_fc_connect_queue(ctrl, &ctrl->queues[i], qsize,
+ (qsize / 5));
+ if (ret)
+ break;
+ ret = nvmf_connect_io_queue(&ctrl->ctrl, i);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static void
+nvme_fc_init_io_queues(struct nvme_fc_ctrl *ctrl)
+{
+ int i;
+
+ for (i = 1; i < ctrl->queue_count; i++)
+ nvme_fc_init_queue(ctrl, i, ctrl->ctrl.sqsize);
+}
+
+static void
+nvme_fc_ctrl_free(struct kref *ref)
+{
+ struct nvme_fc_ctrl *ctrl =
+ container_of(ref, struct nvme_fc_ctrl, ref);
+ unsigned long flags;
+
+ if (ctrl->state != FCCTRL_INIT) {
+ /* remove from rport list */
+ spin_lock_irqsave(&ctrl->rport->lock, flags);
+ list_del(&ctrl->ctrl_list);
+ spin_unlock_irqrestore(&ctrl->rport->lock, flags);
+ }
+
+ put_device(ctrl->dev);
+ nvme_fc_rport_put(ctrl->rport);
+
+ kfree(ctrl->queues);
+ ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum);
+ nvmf_free_options(ctrl->ctrl.opts);
+ kfree(ctrl);
+}
+
+static void
+nvme_fc_ctrl_put(struct nvme_fc_ctrl *ctrl)
+{
+ kref_put(&ctrl->ref, nvme_fc_ctrl_free);
+}
+
+static int
+nvme_fc_ctrl_get(struct nvme_fc_ctrl *ctrl)
+{
+ return kref_get_unless_zero(&ctrl->ref);
+}
+
+/*
+ * All accesses from nvme core layer done - can now free the
+ * controller. Called after last nvme_put_ctrl() call
+ */
+static void
+nvme_fc_free_nvme_ctrl(struct nvme_ctrl *nctrl)
+{
+ struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+
+ WARN_ON(nctrl != &ctrl->ctrl);
+
+ /*
+ * Tear down the association, which will generate link
+ * traffic to terminate connections
+ */
+
+ if (ctrl->state != FCCTRL_INIT) {
+ /* send a Disconnect(association) LS to fc-nvme target */
+ nvme_fc_xmt_disconnect_assoc(ctrl);
+
+ if (ctrl->ctrl.tagset) {
+ blk_cleanup_queue(ctrl->ctrl.connect_q);
+ blk_mq_free_tag_set(&ctrl->tag_set);
+ nvme_fc_delete_hw_io_queues(ctrl);
+ nvme_fc_free_io_queues(ctrl);
+ }
+
+ nvme_fc_exit_aen_ops(ctrl);
+
+ nvme_fc_destroy_admin_queue(ctrl);
+ }
+
+ nvme_fc_ctrl_put(ctrl);
+}
+
+
+static int
+__nvme_fc_abort_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_fcp_op *op)
+{
+ int state;
+
+ state = atomic_xchg(&op->state, FCPOP_STATE_ABORTED);
+ if (state != FCPOP_STATE_ACTIVE) {
+ atomic_set(&op->state, state);
+ return -ECANCELED; /* fail */
+ }
+
+ ctrl->lport->ops->fcp_abort(&ctrl->lport->localport,
+ &ctrl->rport->remoteport,
+ op->queue->lldd_handle,
+ &op->fcp_req);
+
+ return 0;
+}
+
+enum blk_eh_timer_return
+nvme_fc_timeout(struct request *rq, bool reserved)
+{
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_ctrl *ctrl = op->ctrl;
+ int ret;
+
+ if (reserved)
+ return BLK_EH_RESET_TIMER;
+
+ ret = __nvme_fc_abort_op(ctrl, op);
+ if (ret)
+ /* io wasn't active to abort consider it done */
+ return BLK_EH_HANDLED;
+
+ /*
+ * TODO: force a controller reset
+ * when that happens, queues will be torn down and outstanding
+ * ios will be terminated, and the above abort, on a single io
+ * will no longer be needed.
+ */
+
+ return BLK_EH_HANDLED;
+}
+
+static int
+nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
+ struct nvme_fc_fcp_op *op)
+{
+ struct nvmefc_fcp_req *freq = &op->fcp_req;
+ u32 map_len = nvme_map_len(rq);
+ enum dma_data_direction dir;
+ int ret;
+
+ freq->sg_cnt = 0;
+
+ if (!map_len)
+ return 0;
+
+ freq->sg_table.sgl = freq->first_sgl;
+ ret = sg_alloc_table_chained(&freq->sg_table, rq->nr_phys_segments,
+ freq->sg_table.sgl);
+ if (ret)
+ return -ENOMEM;
+
+ op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
+ WARN_ON(op->nents > rq->nr_phys_segments);
+ dir = (rq_data_dir(rq) == WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
+ op->nents, dir);
+ if (unlikely(freq->sg_cnt <= 0)) {
+ sg_free_table_chained(&freq->sg_table, true);
+ freq->sg_cnt = 0;
+ return -EFAULT;
+ }
+
+ /*
+ * TODO: blk_integrity_rq(rq) for DIF
+ */
+ return 0;
+}
+
+static void
+nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
+ struct nvme_fc_fcp_op *op)
+{
+ struct nvmefc_fcp_req *freq = &op->fcp_req;
+
+ if (!freq->sg_cnt)
+ return;
+
+ fc_dma_unmap_sg(ctrl->lport->dev, freq->sg_table.sgl, op->nents,
+ ((rq_data_dir(rq) == WRITE) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE));
+
+ nvme_cleanup_cmd(rq);
+
+ sg_free_table_chained(&freq->sg_table, true);
+
+ freq->sg_cnt = 0;
+}
+
+/*
+ * In FC, the queue is a logical thing. At transport connect, the target
+ * creates its "queue" and returns a handle that is to be given to the
+ * target whenever it posts something to the corresponding SQ. When an
+ * SQE is sent on a SQ, FC effectively considers the SQE, or rather the
+ * command contained within the SQE, an io, and assigns a FC exchange
+ * to it. The SQE and the associated SQ handle are sent in the initial
+ * CMD IU sents on the exchange. All transfers relative to the io occur
+ * as part of the exchange. The CQE is the last thing for the io,
+ * which is transferred (explicitly or implicitly) with the RSP IU
+ * sent on the exchange. After the CQE is received, the FC exchange is
+ * terminaed and the Exchange may be used on a different io.
+ *
+ * The transport to LLDD api has the transport making a request for a
+ * new fcp io request to the LLDD. The LLDD then allocates a FC exchange
+ * resource and transfers the command. The LLDD will then process all
+ * steps to complete the io. Upon completion, the transport done routine
+ * is called.
+ *
+ * So - while the operation is outstanding to the LLDD, there is a link
+ * level FC exchange resource that is also outstanding. This must be
+ * considered in all cleanup operations.
+ */
+static int
+nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
+ struct nvme_fc_fcp_op *op, u32 data_len,
+ enum nvmefc_fcp_datadir io_dir)
+{
+ struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
+ struct nvme_command *sqe = &cmdiu->sqe;
+ u32 csn;
+ int ret;
+
+ if (!nvme_fc_ctrl_get(ctrl))
+ return BLK_MQ_RQ_QUEUE_ERROR;
+
+ /* format the FC-NVME CMD IU and fcp_req */
+ cmdiu->connection_id = cpu_to_be64(queue->connection_id);
+ csn = atomic_inc_return(&queue->csn);
+ cmdiu->csn = cpu_to_be32(csn);
+ cmdiu->data_len = cpu_to_be32(data_len);
+ switch (io_dir) {
+ case NVMEFC_FCP_WRITE:
+ cmdiu->flags = FCNVME_CMD_FLAGS_WRITE;
+ break;
+ case NVMEFC_FCP_READ:
+ cmdiu->flags = FCNVME_CMD_FLAGS_READ;
+ break;
+ case NVMEFC_FCP_NODATA:
+ cmdiu->flags = 0;
+ break;
+ }
+ op->fcp_req.payload_length = data_len;
+ op->fcp_req.io_dir = io_dir;
+ op->fcp_req.transferred_length = 0;
+ op->fcp_req.rcv_rsplen = 0;
+ op->fcp_req.status = 0;
+ op->fcp_req.sqid = cpu_to_le16(queue->qnum);
+
+ /*
+ * validate per fabric rules, set fields mandated by fabric spec
+ * as well as those by FC-NVME spec.
+ */
+ WARN_ON_ONCE(sqe->common.metadata);
+ WARN_ON_ONCE(sqe->common.dptr.prp1);
+ WARN_ON_ONCE(sqe->common.dptr.prp2);
+ sqe->common.flags |= NVME_CMD_SGL_METABUF;
+
+ /*
+ * format SQE DPTR field per FC-NVME rules
+ * type=data block descr; subtype=offset;
+ * offset is currently 0.
+ */
+ sqe->rw.dptr.sgl.type = NVME_SGL_FMT_OFFSET;
+ sqe->rw.dptr.sgl.length = cpu_to_le32(data_len);
+ sqe->rw.dptr.sgl.addr = 0;
+
+ /* odd that we set the command_id - should come from nvme-fabrics */
+ WARN_ON_ONCE(sqe->common.command_id != cpu_to_le16(op->rqno));
+
+ if (op->rq) { /* skipped on aens */
+ ret = nvme_fc_map_data(ctrl, op->rq, op);
+ if (ret < 0) {
+ dev_err(queue->ctrl->ctrl.device,
+ "Failed to map data (%d)\n", ret);
+ nvme_cleanup_cmd(op->rq);
+ nvme_fc_ctrl_put(ctrl);
+ return (ret == -ENOMEM || ret == -EAGAIN) ?
+ BLK_MQ_RQ_QUEUE_BUSY : BLK_MQ_RQ_QUEUE_ERROR;
+ }
+ }
+
+ fc_dma_sync_single_for_device(ctrl->lport->dev, op->fcp_req.cmddma,
+ sizeof(op->cmd_iu), DMA_TO_DEVICE);
+
+ atomic_set(&op->state, FCPOP_STATE_ACTIVE);
+
+ if (op->rq)
+ blk_mq_start_request(op->rq);
+
+ ret = ctrl->lport->ops->fcp_io(&ctrl->lport->localport,
+ &ctrl->rport->remoteport,
+ queue->lldd_handle, &op->fcp_req);
+
+ if (ret) {
+ dev_err(ctrl->dev,
+ "Send nvme command failed - lldd returned %d.\n", ret);
+
+ if (op->rq) { /* normal request */
+ nvme_fc_unmap_data(ctrl, op->rq, op);
+ nvme_cleanup_cmd(op->rq);
+ }
+ /* else - aen. no cleanup needed */
+
+ nvme_fc_ctrl_put(ctrl);
+
+ if (ret != -EBUSY)
+ return BLK_MQ_RQ_QUEUE_ERROR;
+
+ if (op->rq) {
+ blk_mq_stop_hw_queues(op->rq->q);
+ blk_mq_delay_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
+ }
+ return BLK_MQ_RQ_QUEUE_BUSY;
+ }
+
+ return BLK_MQ_RQ_QUEUE_OK;
+}
+
+static int
+nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *bd)
+{
+ struct nvme_ns *ns = hctx->queue->queuedata;
+ struct nvme_fc_queue *queue = hctx->driver_data;
+ struct nvme_fc_ctrl *ctrl = queue->ctrl;
+ struct request *rq = bd->rq;
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
+ struct nvme_command *sqe = &cmdiu->sqe;
+ enum nvmefc_fcp_datadir io_dir;
+ u32 data_len;
+ int ret;
+
+ ret = nvme_setup_cmd(ns, rq, sqe);
+ if (ret)
+ return ret;
+
+ data_len = nvme_map_len(rq);
+ if (data_len)
+ io_dir = ((rq_data_dir(rq) == WRITE) ?
+ NVMEFC_FCP_WRITE : NVMEFC_FCP_READ);
+ else
+ io_dir = NVMEFC_FCP_NODATA;
+
+ return nvme_fc_start_fcp_op(ctrl, queue, op, data_len, io_dir);
+}
+
+static struct blk_mq_tags *
+nvme_fc_tagset(struct nvme_fc_queue *queue)
+{
+ if (queue->qnum == 0)
+ return queue->ctrl->admin_tag_set.tags[queue->qnum];
+
+ return queue->ctrl->tag_set.tags[queue->qnum - 1];
+}
+
+static int
+nvme_fc_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
+
+{
+ struct nvme_fc_queue *queue = hctx->driver_data;
+ struct nvme_fc_ctrl *ctrl = queue->ctrl;
+ struct request *req;
+ struct nvme_fc_fcp_op *op;
+
+ req = blk_mq_tag_to_rq(nvme_fc_tagset(queue), tag);
+ if (!req) {
+ dev_err(queue->ctrl->ctrl.device,
+ "tag 0x%x on QNum %#x not found\n",
+ tag, queue->qnum);
+ return 0;
+ }
+
+ op = blk_mq_rq_to_pdu(req);
+
+ if ((atomic_read(&op->state) == FCPOP_STATE_ACTIVE) &&
+ (ctrl->lport->ops->poll_queue))
+ ctrl->lport->ops->poll_queue(&ctrl->lport->localport,
+ queue->lldd_handle);
+
+ return ((atomic_read(&op->state) != FCPOP_STATE_ACTIVE));
+}
+
+static void
+nvme_fc_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
+{
+ struct nvme_fc_ctrl *ctrl = to_fc_ctrl(arg);
+ struct nvme_fc_fcp_op *aen_op;
+ int ret;
+
+ if (aer_idx > NVME_FC_NR_AEN_COMMANDS)
+ return;
+
+ aen_op = &ctrl->aen_ops[aer_idx];
+
+ ret = nvme_fc_start_fcp_op(ctrl, aen_op->queue, aen_op, 0,
+ NVMEFC_FCP_NODATA);
+ if (ret)
+ dev_err(ctrl->ctrl.device,
+ "failed async event work [%d]\n", aer_idx);
+}
+
+static void
+nvme_fc_complete_rq(struct request *rq)
+{
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
+ struct nvme_fc_ctrl *ctrl = op->ctrl;
+ int error = 0, state;
+
+ state = atomic_xchg(&op->state, FCPOP_STATE_IDLE);
+
+ nvme_cleanup_cmd(rq);
+
+ nvme_fc_unmap_data(ctrl, rq, op);
+
+ if (unlikely(rq->errors)) {
+ if (nvme_req_needs_retry(rq, rq->errors)) {
+ nvme_requeue_req(rq);
+ return;
+ }
+
+ if (rq->cmd_type == REQ_TYPE_DRV_PRIV)
+ error = rq->errors;
+ else
+ error = nvme_error_status(rq->errors);
+ }
+
+ nvme_fc_ctrl_put(ctrl);
+
+ blk_mq_end_request(rq, error);
+}
+
+static struct blk_mq_ops nvme_fc_mq_ops = {
+ .queue_rq = nvme_fc_queue_rq,
+ .complete = nvme_fc_complete_rq,
+ .init_request = nvme_fc_init_request,
+ .exit_request = nvme_fc_exit_request,
+ .reinit_request = nvme_fc_reinit_request,
+ .init_hctx = nvme_fc_init_hctx,
+ .poll = nvme_fc_poll,
+ .timeout = nvme_fc_timeout,
+};
+
+static struct blk_mq_ops nvme_fc_admin_mq_ops = {
+ .queue_rq = nvme_fc_queue_rq,
+ .complete = nvme_fc_complete_rq,
+ .init_request = nvme_fc_init_admin_request,
+ .exit_request = nvme_fc_exit_request,
+ .reinit_request = nvme_fc_reinit_request,
+ .init_hctx = nvme_fc_init_admin_hctx,
+ .timeout = nvme_fc_timeout,
+};
+
+static int
+nvme_fc_configure_admin_queue(struct nvme_fc_ctrl *ctrl)
+{
+ u32 segs;
+ int error;
+
+ nvme_fc_init_queue(ctrl, 0, NVME_FC_AQ_BLKMQ_DEPTH);
+
+ error = nvme_fc_connect_admin_queue(ctrl, &ctrl->queues[0],
+ NVME_FC_AQ_BLKMQ_DEPTH,
+ (NVME_FC_AQ_BLKMQ_DEPTH / 4));
+ if (error)
+ return error;
+
+ memset(&ctrl->admin_tag_set, 0, sizeof(ctrl->admin_tag_set));
+ ctrl->admin_tag_set.ops = &nvme_fc_admin_mq_ops;
+ ctrl->admin_tag_set.queue_depth = NVME_FC_AQ_BLKMQ_DEPTH;
+ ctrl->admin_tag_set.reserved_tags = 2; /* fabric connect + Keep-Alive */
+ ctrl->admin_tag_set.numa_node = NUMA_NO_NODE;
+ ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_fc_fcp_op) +
+ (SG_CHUNK_SIZE *
+ sizeof(struct scatterlist)) +
+ ctrl->lport->ops->fcprqst_priv_sz;
+ ctrl->admin_tag_set.driver_data = ctrl;
+ ctrl->admin_tag_set.nr_hw_queues = 1;
+ ctrl->admin_tag_set.timeout = ADMIN_TIMEOUT;
+
+ error = blk_mq_alloc_tag_set(&ctrl->admin_tag_set);
+ if (error)
+ goto out_free_queue;
+
+ ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set);
+ if (IS_ERR(ctrl->ctrl.admin_q)) {
+ error = PTR_ERR(ctrl->ctrl.admin_q);
+ goto out_free_tagset;
+ }
+
+ error = __nvme_fc_create_hw_queue(ctrl, &ctrl->queues[0], 0,
+ NVME_FC_AQ_BLKMQ_DEPTH);
+ if (error)
+ goto out_cleanup_queue;
+
+ error = nvmf_connect_admin_queue(&ctrl->ctrl);
+ if (error)
+ goto out_delete_hw_queue;
+
+ error = nvmf_reg_read64(&ctrl->ctrl, NVME_REG_CAP, &ctrl->cap);
+ if (error) {
+ dev_err(ctrl->ctrl.device,
+ "prop_get NVME_REG_CAP failed\n");
+ goto out_delete_hw_queue;
+ }
+
+ ctrl->ctrl.sqsize =
+ min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize);
+
+ error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
+ if (error)
+ goto out_delete_hw_queue;
+
+ segs = min_t(u32, NVME_FC_MAX_SEGMENTS,
+ ctrl->lport->ops->max_sgl_segments);
+ ctrl->ctrl.max_hw_sectors = (segs - 1) << (PAGE_SHIFT - 9);
+
+ error = nvme_init_identify(&ctrl->ctrl);
+ if (error)
+ goto out_delete_hw_queue;
+
+ nvme_start_keep_alive(&ctrl->ctrl);
+
+ return 0;
+
+out_delete_hw_queue:
+ __nvme_fc_delete_hw_queue(ctrl, &ctrl->queues[0], 0);
+out_cleanup_queue:
+ blk_cleanup_queue(ctrl->ctrl.admin_q);
+out_free_tagset:
+ blk_mq_free_tag_set(&ctrl->admin_tag_set);
+out_free_queue:
+ nvme_fc_free_queue(&ctrl->queues[0]);
+ return error;
+}
+
+/*
+ * This routine is used by the transport when it needs to find active
+ * io on a queue that is to be terminated. The transport uses
+ * blk_mq_tagset_busy_itr() to find the busy requests, which then invoke
+ * this routine to kill them on a 1 by 1 basis.
+ *
+ * As FC allocates FC exchange for each io, the transport must contact
+ * the LLDD to terminate the exchange, thus releasing the FC exchange.
+ * After terminating the exchange the LLDD will call the transport's
+ * normal io done path for the request, but it will have an aborted
+ * status. The done path will return the io request back to the block
+ * layer with an error status.
+ */
+static void
+nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
+{
+ struct nvme_ctrl *nctrl = data;
+ struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+ struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
+int status;
+
+ if (!blk_mq_request_started(req))
+ return;
+
+ /* this performs an ABTS-LS on the FC exchange for the io */
+ status = __nvme_fc_abort_op(ctrl, op);
+ /*
+ * if __nvme_fc_abort_op failed: io wasn't active to abort
+ * consider it done. Assume completion path already completing
+ * in parallel
+ */
+ if (status)
+ /* io wasn't active to abort consider it done */
+ /* assume completion path already completing in parallel */
+ return;
+}
+
+
+/*
+ * This routine stops operation of the controller. Admin and IO queues
+ * are stopped, outstanding ios on them terminated, and the nvme ctrl
+ * is shutdown.
+ */
+static void
+nvme_fc_shutdown_ctrl(struct nvme_fc_ctrl *ctrl)
+{
+ /*
+ * If io queues are present, stop them and terminate all outstanding
+ * ios on them. As FC allocates FC exchange for each io, the
+ * transport must contact the LLDD to terminate the exchange,
+ * thus releasing the FC exchange. We use blk_mq_tagset_busy_itr()
+ * to tell us what io's are busy and invoke a transport routine
+ * to kill them with the LLDD. After terminating the exchange
+ * the LLDD will call the transport's normal io done path, but it
+ * will have an aborted status. The done path will return the
+ * io requests back to the block layer as part of normal completions
+ * (but with error status).
+ */
+ if (ctrl->queue_count > 1) {
+ nvme_stop_queues(&ctrl->ctrl);
+ blk_mq_tagset_busy_iter(&ctrl->tag_set,
+ nvme_fc_terminate_exchange, &ctrl->ctrl);
+ }
+
+ if (ctrl->ctrl.state == NVME_CTRL_LIVE)
+ nvme_shutdown_ctrl(&ctrl->ctrl);
+
+ /*
+ * now clean up the admin queue. Same thing as above.
+ * use blk_mq_tagset_busy_itr() and the transport routine to
+ * terminate the exchanges.
+ */
+ blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
+ blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
+ nvme_fc_terminate_exchange, &ctrl->ctrl);
+}
+
+/*
+ * Called to teardown an association.
+ * May be called with association fully in place or partially in place.
+ */
+static void
+__nvme_fc_remove_ctrl(struct nvme_fc_ctrl *ctrl)
+{
+ nvme_stop_keep_alive(&ctrl->ctrl);
+
+ /* stop and terminate ios on admin and io queues */
+ nvme_fc_shutdown_ctrl(ctrl);
+
+ /*
+ * tear down the controller
+ * This will result in the last reference on the nvme ctrl to
+ * expire, calling the transport nvme_fc_free_nvme_ctrl() callback.
+ * From there, the transport will tear down it's logical queues and
+ * association.
+ */
+ nvme_uninit_ctrl(&ctrl->ctrl);
+
+ nvme_put_ctrl(&ctrl->ctrl);
+}
+
+static void
+nvme_fc_del_ctrl_work(struct work_struct *work)
+{
+ struct nvme_fc_ctrl *ctrl =
+ container_of(work, struct nvme_fc_ctrl, delete_work);
+
+ __nvme_fc_remove_ctrl(ctrl);
+}
+
+static int
+__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
+{
+ if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
+ return -EBUSY;
+
+ if (!queue_work(nvme_fc_wq, &ctrl->delete_work))
+ return -EBUSY;
+
+ return 0;
+}
+
+/*
+ * Request from nvme core layer to delete the controller
+ */
+static int
+nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
+{
+ struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+ struct nvme_fc_rport *rport = ctrl->rport;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&rport->lock, flags);
+ ret = __nvme_fc_del_ctrl(ctrl);
+ spin_unlock_irqrestore(&rport->lock, flags);
+ if (ret)
+ return ret;
+
+ flush_work(&ctrl->delete_work);
+
+ return 0;
+}
+
+static int
+nvme_fc_reset_nvme_ctrl(struct nvme_ctrl *nctrl)
+{
+ return -EIO;
+}
+
+static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
+ .name = "fc",
+ .module = THIS_MODULE,
+ .is_fabrics = true,
+ .reg_read32 = nvmf_reg_read32,
+ .reg_read64 = nvmf_reg_read64,
+ .reg_write32 = nvmf_reg_write32,
+ .reset_ctrl = nvme_fc_reset_nvme_ctrl,
+ .free_ctrl = nvme_fc_free_nvme_ctrl,
+ .submit_async_event = nvme_fc_submit_async_event,
+ .delete_ctrl = nvme_fc_del_nvme_ctrl,
+ .get_subsysnqn = nvmf_get_subsysnqn,
+ .get_address = nvmf_get_address,
+};
+
+static int
+nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
+{
+ struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
+ int ret;
+
+ ret = nvme_set_queue_count(&ctrl->ctrl, &opts->nr_io_queues);
+ if (ret) {
+ dev_info(ctrl->ctrl.device,
+ "set_queue_count failed: %d\n", ret);
+ return ret;
+ }
+
+ ctrl->queue_count = opts->nr_io_queues + 1;
+ if (!opts->nr_io_queues)
+ return 0;
+
+ dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n",
+ opts->nr_io_queues);
+
+ nvme_fc_init_io_queues(ctrl);
+
+ memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
+ ctrl->tag_set.ops = &nvme_fc_mq_ops;
+ ctrl->tag_set.queue_depth = ctrl->ctrl.opts->queue_size;
+ ctrl->tag_set.reserved_tags = 1; /* fabric connect */
+ ctrl->tag_set.numa_node = NUMA_NO_NODE;
+ ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+ ctrl->tag_set.cmd_size = sizeof(struct nvme_fc_fcp_op) +
+ (SG_CHUNK_SIZE *
+ sizeof(struct scatterlist)) +
+ ctrl->lport->ops->fcprqst_priv_sz;
+ ctrl->tag_set.driver_data = ctrl;
+ ctrl->tag_set.nr_hw_queues = ctrl->queue_count - 1;
+ ctrl->tag_set.timeout = NVME_IO_TIMEOUT;
+
+ ret = blk_mq_alloc_tag_set(&ctrl->tag_set);
+ if (ret)
+ return ret;
+
+ ctrl->ctrl.tagset = &ctrl->tag_set;
+
+ ctrl->ctrl.connect_q = blk_mq_init_queue(&ctrl->tag_set);
+ if (IS_ERR(ctrl->ctrl.connect_q)) {
+ ret = PTR_ERR(ctrl->ctrl.connect_q);
+ goto out_free_tag_set;
+ }
+
+ ret = nvme_fc_create_hw_io_queues(ctrl, ctrl->ctrl.opts->queue_size);
+ if (ret)
+ goto out_cleanup_blk_queue;
+
+ ret = nvme_fc_connect_io_queues(ctrl, ctrl->ctrl.opts->queue_size);
+ if (ret)
+ goto out_delete_hw_queues;
+
+ return 0;
+
+out_delete_hw_queues:
+ nvme_fc_delete_hw_io_queues(ctrl);
+out_cleanup_blk_queue:
+ nvme_stop_keep_alive(&ctrl->ctrl);
+ blk_cleanup_queue(ctrl->ctrl.connect_q);
+out_free_tag_set:
+ blk_mq_free_tag_set(&ctrl->tag_set);
+ nvme_fc_free_io_queues(ctrl);
+
+ /* force put free routine to ignore io queues */
+ ctrl->ctrl.tagset = NULL;
+
+ return ret;
+}
+
+
+static struct nvme_ctrl *
+__nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
+ struct nvme_fc_lport *lport, struct nvme_fc_rport *rport)
+{
+ struct nvme_fc_ctrl *ctrl;
+ unsigned long flags;
+ int ret, idx;
+ bool changed;
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl) {
+ ret = -ENOMEM;
+ goto out_fail;
+ }
+
+ idx = ida_simple_get(&nvme_fc_ctrl_cnt, 0, 0, GFP_KERNEL);
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out_free_ctrl;
+ }
+
+ ctrl->ctrl.opts = opts;
+ INIT_LIST_HEAD(&ctrl->ctrl_list);
+ INIT_LIST_HEAD(&ctrl->ls_req_list);
+ ctrl->lport = lport;
+ ctrl->rport = rport;
+ ctrl->dev = lport->dev;
+ ctrl->state = FCCTRL_INIT;
+ ctrl->cnum = idx;
+
+ ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_fc_ctrl_ops, 0);
+ if (ret)
+ goto out_free_ida;
+
+ get_device(ctrl->dev);
+ kref_init(&ctrl->ref);
+
+ INIT_WORK(&ctrl->delete_work, nvme_fc_del_ctrl_work);
+ spin_lock_init(&ctrl->lock);
+
+ /* io queue count */
+ ctrl->queue_count = min_t(unsigned int,
+ opts->nr_io_queues,
+ lport->ops->max_hw_queues);
+ opts->nr_io_queues = ctrl->queue_count; /* so opts has valid value */
+ ctrl->queue_count++; /* +1 for admin queue */
+
+ ctrl->ctrl.sqsize = opts->queue_size - 1;
+ ctrl->ctrl.kato = opts->kato;
+
+ ret = -ENOMEM;
+ ctrl->queues = kcalloc(ctrl->queue_count, sizeof(struct nvme_fc_queue),
+ GFP_KERNEL);
+ if (!ctrl->queues)
+ goto out_uninit_ctrl;
+
+ ret = nvme_fc_configure_admin_queue(ctrl);
+ if (ret)
+ goto out_uninit_ctrl;
+
+ /* sanity checks */
+
+ /* FC-NVME supports 64-byte SQE only */
+ if (ctrl->ctrl.ioccsz != 4) {
+ dev_err(ctrl->ctrl.device, "ioccsz %d is not supported!\n",
+ ctrl->ctrl.ioccsz);
+ goto out_remove_admin_queue;
+ }
+ /* FC-NVME supports 16-byte CQE only */
+ if (ctrl->ctrl.iorcsz != 1) {
+ dev_err(ctrl->ctrl.device, "iorcsz %d is not supported!\n",
+ ctrl->ctrl.iorcsz);
+ goto out_remove_admin_queue;
+ }
+ /* FC-NVME does not have other data in the capsule */
+ if (ctrl->ctrl.icdoff) {
+ dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n",
+ ctrl->ctrl.icdoff);
+ goto out_remove_admin_queue;
+ }
+
+ /* FC-NVME supports normal SGL Data Block Descriptors */
+
+ if (opts->queue_size > ctrl->ctrl.maxcmd) {
+ /* warn if maxcmd is lower than queue_size */
+ dev_warn(ctrl->ctrl.device,
+ "queue_size %zu > ctrl maxcmd %u, reducing "
+ "to queue_size\n",
+ opts->queue_size, ctrl->ctrl.maxcmd);
+ opts->queue_size = ctrl->ctrl.maxcmd;
+ }
+
+ ret = nvme_fc_init_aen_ops(ctrl);
+ if (ret)
+ goto out_exit_aen_ops;
+
+ if (ctrl->queue_count > 1) {
+ ret = nvme_fc_create_io_queues(ctrl);
+ if (ret)
+ goto out_exit_aen_ops;
+ }
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+ ctrl->state = FCCTRL_ACTIVE;
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+
+ changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
+ WARN_ON_ONCE(!changed);
+
+ dev_info(ctrl->ctrl.device,
+ "NVME-FC{%d}: new ctrl: NQN \"%s\" (%p)\n",
+ ctrl->cnum, ctrl->ctrl.opts->subsysnqn, &ctrl);
+
+ kref_get(&ctrl->ctrl.kref);
+
+ spin_lock_irqsave(&rport->lock, flags);
+ list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list);
+ spin_unlock_irqrestore(&rport->lock, flags);
+
+ if (opts->nr_io_queues) {
+ nvme_queue_scan(&ctrl->ctrl);
+ nvme_queue_async_events(&ctrl->ctrl);
+ }
+
+ return &ctrl->ctrl;
+
+out_exit_aen_ops:
+ nvme_fc_exit_aen_ops(ctrl);
+out_remove_admin_queue:
+ /* send a Disconnect(association) LS to fc-nvme target */
+ nvme_fc_xmt_disconnect_assoc(ctrl);
+ nvme_stop_keep_alive(&ctrl->ctrl);
+ nvme_fc_destroy_admin_queue(ctrl);
+out_uninit_ctrl:
+ nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_put_ctrl(&ctrl->ctrl);
+ if (ret > 0)
+ ret = -EIO;
+ /* exit via here will follow ctlr ref point callbacks to free */
+ return ERR_PTR(ret);
+
+out_free_ida:
+ ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum);
+out_free_ctrl:
+ kfree(ctrl);
+out_fail:
+ nvme_fc_rport_put(rport);
+ /* exit via here doesn't follow ctlr ref points */
+ return ERR_PTR(ret);
+}
+
+enum {
+ FCT_TRADDR_ERR = 0,
+ FCT_TRADDR_WWNN = 1 << 0,
+ FCT_TRADDR_WWPN = 1 << 1,
+};
+
+struct nvmet_fc_traddr {
+ u64 nn;
+ u64 pn;
+};
+
+static const match_table_t traddr_opt_tokens = {
+ { FCT_TRADDR_WWNN, "nn-%s" },
+ { FCT_TRADDR_WWPN, "pn-%s" },
+ { FCT_TRADDR_ERR, NULL }
+};
+
+static int
+nvme_fc_parse_address(struct nvmet_fc_traddr *traddr, char *buf)
+{
+ substring_t args[MAX_OPT_ARGS];
+ char *options, *o, *p;
+ int token, ret = 0;
+ u64 token64;
+
+ options = o = kstrdup(buf, GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ while ((p = strsep(&o, ":\n")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, traddr_opt_tokens, args);
+ switch (token) {
+ case FCT_TRADDR_WWNN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ traddr->nn = token64;
+ break;
+ case FCT_TRADDR_WWPN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ traddr->pn = token64;
+ break;
+ default:
+ pr_warn("unknown traddr token or missing value '%s'\n",
+ p);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+out:
+ kfree(options);
+ return ret;
+}
+
+static struct nvme_ctrl *
+nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
+{
+ struct nvme_fc_lport *lport;
+ struct nvme_fc_rport *rport;
+ struct nvmet_fc_traddr laddr = { 0L, 0L };
+ struct nvmet_fc_traddr raddr = { 0L, 0L };
+ unsigned long flags;
+ int ret;
+
+ ret = nvme_fc_parse_address(&raddr, opts->traddr);
+ if (ret || !raddr.nn || !raddr.pn)
+ return ERR_PTR(-EINVAL);
+
+ ret = nvme_fc_parse_address(&laddr, opts->host_traddr);
+ if (ret || !laddr.nn || !laddr.pn)
+ return ERR_PTR(-EINVAL);
+
+ /* find the host and remote ports to connect together */
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
+ if (lport->localport.node_name != laddr.nn ||
+ lport->localport.port_name != laddr.pn)
+ continue;
+
+ list_for_each_entry(rport, &lport->endp_list, endp_list) {
+ if (rport->remoteport.node_name != raddr.nn ||
+ rport->remoteport.port_name != raddr.pn)
+ continue;
+
+ /* if fail to get reference fall through. Will error */
+ if (!nvme_fc_rport_get(rport))
+ break;
+
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ return __nvme_fc_create_ctrl(dev, opts, lport, rport);
+ }
+ }
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ return ERR_PTR(-ENOENT);
+}
+
+
+static struct nvmf_transport_ops nvme_fc_transport = {
+ .name = "fc",
+ .required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR,
+ .allowed_opts = NVMF_OPT_RECONNECT_DELAY,
+ .create_ctrl = nvme_fc_create_ctrl,
+};
+
+static int __init nvme_fc_init_module(void)
+{
+ nvme_fc_wq = create_workqueue("nvme_fc_wq");
+ if (!nvme_fc_wq)
+ return -ENOMEM;
+
+ nvmf_register_transport(&nvme_fc_transport);
+ return 0;
+}
+
+static void __exit nvme_fc_exit_module(void)
+{
+ /* sanity check - all lports should be removed */
+ if (!list_empty(&nvme_fc_lport_list))
+ pr_warn("%s: localport list not empty\n", __func__);
+
+ nvmf_unregister_transport(&nvme_fc_transport);
+
+ destroy_workqueue(nvme_fc_wq);
+
+ ida_destroy(&nvme_fc_local_port_cnt);
+ ida_destroy(&nvme_fc_ctrl_cnt);
+}
+
+module_init(nvme_fc_init_module);
+module_exit(nvme_fc_exit_module);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 5daf2f4be0cd..588d4a34c083 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -146,14 +146,6 @@ struct nvme_nvm_command {
};
};
-struct nvme_nvm_completion {
- __le64 result; /* Used by LightNVM to return ppa completions */
- __le16 sq_head; /* how much of this queue may be reclaimed */
- __le16 sq_id; /* submission queue that generated this entry */
- __u16 command_id; /* of the command which completed */
- __le16 status; /* did the command fail, and if so, why? */
-};
-
#define NVME_NVM_LP_MLC_PAIRS 886
struct nvme_nvm_lp_mlc {
__le16 num_pairs;
@@ -360,6 +352,7 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
while (nlb) {
u32 cmd_nlb = min(nlb_pr_rq, nlb);
+ u64 elba = slba + cmd_nlb;
c.l2p.slba = cpu_to_le64(cmd_slba);
c.l2p.nlb = cpu_to_le32(cmd_nlb);
@@ -373,6 +366,14 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
goto out;
}
+ if (unlikely(elba > nvmdev->total_secs)) {
+ pr_err("nvm: L2P data from device is out of bounds!\n");
+ return -EINVAL;
+ }
+
+ /* Transform physical address to target address space */
+ nvmdev->mt->part_to_tgt(nvmdev, entries, cmd_nlb);
+
if (update_l2p(cmd_slba, cmd_nlb, entries, priv)) {
ret = -EINTR;
goto out;
@@ -391,11 +392,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
u8 *blks)
{
struct request_queue *q = nvmdev->q;
+ struct nvm_geo *geo = &nvmdev->geo;
struct nvme_ns *ns = q->queuedata;
struct nvme_ctrl *ctrl = ns->ctrl;
struct nvme_nvm_command c = {};
struct nvme_nvm_bb_tbl *bb_tbl;
- int nr_blks = nvmdev->blks_per_lun * nvmdev->plane_mode;
+ int nr_blks = geo->blks_per_lun * geo->plane_mode;
int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
int ret = 0;
@@ -436,7 +438,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
goto out;
}
- memcpy(blks, bb_tbl->blk, nvmdev->blks_per_lun * nvmdev->plane_mode);
+ memcpy(blks, bb_tbl->blk, geo->blks_per_lun * geo->plane_mode);
out:
kfree(bb_tbl);
return ret;
@@ -481,14 +483,11 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd,
static void nvme_nvm_end_io(struct request *rq, int error)
{
struct nvm_rq *rqd = rq->end_io_data;
- struct nvme_nvm_completion *cqe = rq->special;
-
- if (cqe)
- rqd->ppa_status = le64_to_cpu(cqe->result);
+ rqd->ppa_status = nvme_req(rq)->result.u64;
nvm_end_io(rqd, error);
- kfree(rq->cmd);
+ kfree(nvme_req(rq)->cmd);
blk_mq_free_request(rq);
}
@@ -500,20 +499,18 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
struct bio *bio = rqd->bio;
struct nvme_nvm_command *cmd;
- rq = blk_mq_alloc_request(q, bio_data_dir(bio), 0);
- if (IS_ERR(rq))
+ cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL);
+ if (!cmd)
return -ENOMEM;
- cmd = kzalloc(sizeof(struct nvme_nvm_command) +
- sizeof(struct nvme_nvm_completion), GFP_KERNEL);
- if (!cmd) {
- blk_mq_free_request(rq);
+ rq = nvme_alloc_request(q, (struct nvme_command *)cmd, 0, NVME_QID_ANY);
+ if (IS_ERR(rq)) {
+ kfree(cmd);
return -ENOMEM;
}
+ rq->cmd_flags &= ~REQ_FAILFAST_DRIVER;
- 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);
@@ -522,10 +519,6 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
nvme_nvm_rqtocmd(rq, rqd, ns, cmd);
- rq->cmd = (unsigned char *)cmd;
- rq->cmd_len = sizeof(struct nvme_nvm_command);
- rq->special = cmd + 1;
-
rq->end_io_data = rqd;
blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_io);
@@ -543,6 +536,7 @@ static int nvme_nvm_erase_block(struct nvm_dev *dev, struct nvm_rq *rqd)
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_ppas - 1);
+ c.erase.control = cpu_to_le16(rqd->flags);
return nvme_submit_sync_cmd(q, (struct nvme_command *)&c, NULL, 0);
}
@@ -592,12 +586,10 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
.max_phys_sect = 64,
};
-int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node,
- const struct attribute_group *attrs)
+int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
{
struct request_queue *q = ns->queue;
struct nvm_dev *dev;
- int ret;
dev = nvm_alloc_dev(node);
if (!dev)
@@ -606,18 +598,10 @@ int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node,
dev->q = q;
memcpy(dev->name, disk_name, DISK_NAME_LEN);
dev->ops = &nvme_nvm_dev_ops;
- dev->parent_dev = ns->ctrl->device;
dev->private_data = ns;
ns->ndev = dev;
- ret = nvm_register(dev);
-
- ns->lba_shift = ilog2(dev->sec_size);
-
- if (sysfs_create_group(&dev->dev.kobj, attrs))
- pr_warn("%s: failed to create sysfs group for identification\n",
- disk_name);
- return ret;
+ return nvm_register(dev);
}
void nvme_nvm_unregister(struct nvme_ns *ns)
@@ -625,6 +609,167 @@ void nvme_nvm_unregister(struct nvme_ns *ns)
nvm_unregister(ns->ndev);
}
+static ssize_t nvm_dev_attr_show(struct device *dev,
+ struct device_attribute *dattr, char *page)
+{
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+ struct nvm_dev *ndev = ns->ndev;
+ struct nvm_id *id;
+ struct nvm_id_group *grp;
+ struct attribute *attr;
+
+ if (!ndev)
+ return 0;
+
+ id = &ndev->identity;
+ grp = &id->groups[0];
+ attr = &dattr->attr;
+
+ if (strcmp(attr->name, "version") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
+ } else if (strcmp(attr->name, "vendor_opcode") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
+ } else if (strcmp(attr->name, "capabilities") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
+ } else if (strcmp(attr->name, "device_mode") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
+ } else if (strcmp(attr->name, "media_manager") == 0) {
+ if (!ndev->mt)
+ return scnprintf(page, PAGE_SIZE, "%s\n", "none");
+ return scnprintf(page, PAGE_SIZE, "%s\n", ndev->mt->name);
+ } else if (strcmp(attr->name, "ppa_format") == 0) {
+ return scnprintf(page, PAGE_SIZE,
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ id->ppaf.ch_offset, id->ppaf.ch_len,
+ id->ppaf.lun_offset, id->ppaf.lun_len,
+ id->ppaf.pln_offset, id->ppaf.pln_len,
+ id->ppaf.blk_offset, id->ppaf.blk_len,
+ id->ppaf.pg_offset, id->ppaf.pg_len,
+ id->ppaf.sect_offset, id->ppaf.sect_len);
+ } else if (strcmp(attr->name, "media_type") == 0) { /* u8 */
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->mtype);
+ } else if (strcmp(attr->name, "flash_media_type") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->fmtype);
+ } else if (strcmp(attr->name, "num_channels") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_ch);
+ } else if (strcmp(attr->name, "num_luns") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_lun);
+ } else if (strcmp(attr->name, "num_planes") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pln);
+ } else if (strcmp(attr->name, "num_blocks") == 0) { /* u16 */
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_blk);
+ } else if (strcmp(attr->name, "num_pages") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pg);
+ } else if (strcmp(attr->name, "page_size") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->fpg_sz);
+ } else if (strcmp(attr->name, "hw_sector_size") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->csecs);
+ } else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->sos);
+ } else if (strcmp(attr->name, "read_typ") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdt);
+ } else if (strcmp(attr->name, "read_max") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdm);
+ } else if (strcmp(attr->name, "prog_typ") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprt);
+ } else if (strcmp(attr->name, "prog_max") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprm);
+ } else if (strcmp(attr->name, "erase_typ") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbet);
+ } else if (strcmp(attr->name, "erase_max") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbem);
+ } else if (strcmp(attr->name, "multiplane_modes") == 0) {
+ return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mpos);
+ } else if (strcmp(attr->name, "media_capabilities") == 0) {
+ return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mccap);
+ } else if (strcmp(attr->name, "max_phys_secs") == 0) {
+ return scnprintf(page, PAGE_SIZE, "%u\n",
+ ndev->ops->max_phys_sect);
+ } else {
+ return scnprintf(page,
+ PAGE_SIZE,
+ "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
+ attr->name);
+ }
+}
+
+#define NVM_DEV_ATTR_RO(_name) \
+ DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
+
+static NVM_DEV_ATTR_RO(version);
+static NVM_DEV_ATTR_RO(vendor_opcode);
+static NVM_DEV_ATTR_RO(capabilities);
+static NVM_DEV_ATTR_RO(device_mode);
+static NVM_DEV_ATTR_RO(ppa_format);
+static NVM_DEV_ATTR_RO(media_manager);
+
+static NVM_DEV_ATTR_RO(media_type);
+static NVM_DEV_ATTR_RO(flash_media_type);
+static NVM_DEV_ATTR_RO(num_channels);
+static NVM_DEV_ATTR_RO(num_luns);
+static NVM_DEV_ATTR_RO(num_planes);
+static NVM_DEV_ATTR_RO(num_blocks);
+static NVM_DEV_ATTR_RO(num_pages);
+static NVM_DEV_ATTR_RO(page_size);
+static NVM_DEV_ATTR_RO(hw_sector_size);
+static NVM_DEV_ATTR_RO(oob_sector_size);
+static NVM_DEV_ATTR_RO(read_typ);
+static NVM_DEV_ATTR_RO(read_max);
+static NVM_DEV_ATTR_RO(prog_typ);
+static NVM_DEV_ATTR_RO(prog_max);
+static NVM_DEV_ATTR_RO(erase_typ);
+static NVM_DEV_ATTR_RO(erase_max);
+static NVM_DEV_ATTR_RO(multiplane_modes);
+static NVM_DEV_ATTR_RO(media_capabilities);
+static NVM_DEV_ATTR_RO(max_phys_secs);
+
+static struct attribute *nvm_dev_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_vendor_opcode.attr,
+ &dev_attr_capabilities.attr,
+ &dev_attr_device_mode.attr,
+ &dev_attr_media_manager.attr,
+
+ &dev_attr_ppa_format.attr,
+ &dev_attr_media_type.attr,
+ &dev_attr_flash_media_type.attr,
+ &dev_attr_num_channels.attr,
+ &dev_attr_num_luns.attr,
+ &dev_attr_num_planes.attr,
+ &dev_attr_num_blocks.attr,
+ &dev_attr_num_pages.attr,
+ &dev_attr_page_size.attr,
+ &dev_attr_hw_sector_size.attr,
+ &dev_attr_oob_sector_size.attr,
+ &dev_attr_read_typ.attr,
+ &dev_attr_read_max.attr,
+ &dev_attr_prog_typ.attr,
+ &dev_attr_prog_max.attr,
+ &dev_attr_erase_typ.attr,
+ &dev_attr_erase_max.attr,
+ &dev_attr_multiplane_modes.attr,
+ &dev_attr_media_capabilities.attr,
+ &dev_attr_max_phys_secs.attr,
+ NULL,
+};
+
+static const struct attribute_group nvm_dev_attr_group = {
+ .name = "lightnvm",
+ .attrs = nvm_dev_attrs,
+};
+
+int nvme_nvm_register_sysfs(struct nvme_ns *ns)
+{
+ return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+ &nvm_dev_attr_group);
+}
+
+void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
+{
+ sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+ &nvm_dev_attr_group);
+}
+
/* move to shared place when used in multiple places. */
#define PCI_VENDOR_ID_CNEX 0x1d1d
#define PCI_DEVICE_ID_CNEX_WL 0x2807
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index d47f5a5d18c7..bd5321441d12 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -79,6 +79,20 @@ enum nvme_quirks {
NVME_QUIRK_DELAY_BEFORE_CHK_RDY = (1 << 3),
};
+/*
+ * Common request structure for NVMe passthrough. All drivers must have
+ * this structure as the first member of their request-private data.
+ */
+struct nvme_request {
+ struct nvme_command *cmd;
+ union nvme_result result;
+};
+
+static inline struct nvme_request *nvme_req(struct request *req)
+{
+ return blk_mq_rq_to_pdu(req);
+}
+
/* The below value is the specific amount of delay needed before checking
* readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the
* NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was
@@ -222,8 +236,10 @@ static inline unsigned nvme_map_len(struct request *rq)
static inline void nvme_cleanup_cmd(struct request *req)
{
- if (req_op(req) == REQ_OP_DISCARD)
- kfree(req->completion_data);
+ if (req->rq_flags & RQF_SPECIAL_PAYLOAD) {
+ kfree(page_address(req->special_vec.bv_page) +
+ req->special_vec.bv_offset);
+ }
}
static inline int nvme_error_status(u16 status)
@@ -261,8 +277,8 @@ void nvme_queue_scan(struct nvme_ctrl *ctrl);
void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
#define NVME_NR_AERS 1
-void nvme_complete_async_event(struct nvme_ctrl *ctrl,
- struct nvme_completion *cqe);
+void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
+ union nvme_result *res);
void nvme_queue_async_events(struct nvme_ctrl *ctrl);
void nvme_stop_queues(struct nvme_ctrl *ctrl);
@@ -278,7 +294,7 @@ int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
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,
- struct nvme_completion *cqe, void *buffer, unsigned bufflen,
+ union nvme_result *result, void *buffer, unsigned bufflen,
unsigned timeout, int qid, int at_head, int flags);
int nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
void __user *ubuffer, unsigned bufflen, u32 *result,
@@ -307,36 +323,33 @@ int nvme_sg_get_version_num(int __user *ip);
#ifdef CONFIG_NVM
int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id);
-int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node,
- const struct attribute_group *attrs);
+int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node);
void nvme_nvm_unregister(struct nvme_ns *ns);
-
-static inline struct nvme_ns *nvme_get_ns_from_dev(struct device *dev)
-{
- if (dev->type->devnode)
- return dev_to_disk(dev)->private_data;
-
- return (container_of(dev, struct nvm_dev, dev))->private_data;
-}
+int nvme_nvm_register_sysfs(struct nvme_ns *ns);
+void nvme_nvm_unregister_sysfs(struct nvme_ns *ns);
#else
static inline int nvme_nvm_register(struct nvme_ns *ns, char *disk_name,
- int node,
- const struct attribute_group *attrs)
+ int node)
{
return 0;
}
static inline void nvme_nvm_unregister(struct nvme_ns *ns) {};
-
+static inline int nvme_nvm_register_sysfs(struct nvme_ns *ns)
+{
+ return 0;
+}
+static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {};
static inline int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id)
{
return 0;
}
+#endif /* CONFIG_NVM */
+
static inline struct nvme_ns *nvme_get_ns_from_dev(struct device *dev)
{
return dev_to_disk(dev)->private_data;
}
-#endif /* CONFIG_NVM */
int __init nvme_core_init(void);
void nvme_core_exit(void);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5e52034ab010..3ba38f4d774d 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -141,6 +141,7 @@ struct nvme_queue {
* allocated to store the PRP list.
*/
struct nvme_iod {
+ struct nvme_request req;
struct nvme_queue *nvmeq;
int aborted;
int npages; /* In the PRP list. 0 means small pool in use */
@@ -302,14 +303,14 @@ static void __nvme_submit_cmd(struct nvme_queue *nvmeq,
static __le64 **iod_list(struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
- return (__le64 **)(iod->sg + req->nr_phys_segments);
+ return (__le64 **)(iod->sg + blk_rq_nr_phys_segments(req));
}
static int nvme_init_iod(struct request *rq, unsigned size,
struct nvme_dev *dev)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(rq);
- int nseg = rq->nr_phys_segments;
+ int nseg = blk_rq_nr_phys_segments(rq);
if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) {
iod->sg = kmalloc(nvme_iod_alloc_size(dev, size, nseg), GFP_ATOMIC);
@@ -324,11 +325,11 @@ static int nvme_init_iod(struct request *rq, unsigned size,
iod->nents = 0;
iod->length = size;
- if (!(rq->cmd_flags & REQ_DONTPREP)) {
+ if (!(rq->rq_flags & RQF_DONTPREP)) {
rq->retries = 0;
- rq->cmd_flags |= REQ_DONTPREP;
+ rq->rq_flags |= RQF_DONTPREP;
}
- return 0;
+ return BLK_MQ_RQ_QUEUE_OK;
}
static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
@@ -339,8 +340,6 @@ static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
__le64 **list = iod_list(req);
dma_addr_t prp_dma = iod->first_dma;
- nvme_cleanup_cmd(req);
-
if (iod->npages == 0)
dma_pool_free(dev->prp_small_pool, list[0], prp_dma);
for (i = 0; i < iod->npages; i++) {
@@ -510,7 +509,7 @@ static int nvme_map_data(struct nvme_dev *dev, struct request *req,
DMA_TO_DEVICE : DMA_FROM_DEVICE;
int ret = BLK_MQ_RQ_QUEUE_ERROR;
- sg_init_table(iod->sg, req->nr_phys_segments);
+ sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
iod->nents = blk_rq_map_sg(q, req, iod->sg);
if (!iod->nents)
goto out;
@@ -566,6 +565,7 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
}
}
+ nvme_cleanup_cmd(req);
nvme_free_iod(dev, req);
}
@@ -596,22 +596,21 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
}
}
- map_len = nvme_map_len(req);
- ret = nvme_init_iod(req, map_len, dev);
- if (ret)
+ ret = nvme_setup_cmd(ns, req, &cmnd);
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
return ret;
- ret = nvme_setup_cmd(ns, req, &cmnd);
- if (ret)
- goto out;
+ map_len = nvme_map_len(req);
+ ret = nvme_init_iod(req, map_len, dev);
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
+ goto out_free_cmd;
- if (req->nr_phys_segments)
+ if (blk_rq_nr_phys_segments(req))
ret = nvme_map_data(dev, req, map_len, &cmnd);
- if (ret)
- goto out;
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
+ goto out_cleanup_iod;
- cmnd.common.command_id = req->tag;
blk_mq_start_request(req);
spin_lock_irq(&nvmeq->q_lock);
@@ -621,14 +620,16 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
else
ret = BLK_MQ_RQ_QUEUE_ERROR;
spin_unlock_irq(&nvmeq->q_lock);
- goto out;
+ goto out_cleanup_iod;
}
__nvme_submit_cmd(nvmeq, &cmnd);
nvme_process_cq(nvmeq);
spin_unlock_irq(&nvmeq->q_lock);
return BLK_MQ_RQ_QUEUE_OK;
-out:
+out_cleanup_iod:
nvme_free_iod(dev, req);
+out_free_cmd:
+ nvme_cleanup_cmd(req);
return ret;
}
@@ -703,13 +704,13 @@ static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag)
*/
if (unlikely(nvmeq->qid == 0 &&
cqe.command_id >= NVME_AQ_BLKMQ_DEPTH)) {
- nvme_complete_async_event(&nvmeq->dev->ctrl, &cqe);
+ nvme_complete_async_event(&nvmeq->dev->ctrl,
+ cqe.status, &cqe.result);
continue;
}
req = blk_mq_tag_to_rq(*nvmeq->tags, cqe.command_id);
- if (req->cmd_type == REQ_TYPE_DRV_PRIV && req->special)
- memcpy(req->special, &cqe, sizeof(cqe));
+ nvme_req(req)->result = cqe.result;
blk_mq_complete_request(req, le16_to_cpu(cqe.status) >> 1);
}
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 3d25add36d91..f42ab70ffa38 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -28,7 +28,6 @@
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
-#include <rdma/ib_cm.h>
#include <linux/nvme-rdma.h>
#include "nvme.h"
@@ -66,6 +65,7 @@ struct nvme_rdma_qe {
struct nvme_rdma_queue;
struct nvme_rdma_request {
+ struct nvme_request req;
struct ib_mr *mr;
struct nvme_rdma_qe sqe;
struct ib_sge sge[1 + NVME_RDMA_MAX_INLINE_SEGMENTS];
@@ -241,7 +241,9 @@ out_free_ring:
static void nvme_rdma_qp_event(struct ib_event *event, void *context)
{
- pr_debug("QP event %d\n", event->event);
+ pr_debug("QP event %s (%d)\n",
+ ib_event_msg(event->event), event->event);
+
}
static int nvme_rdma_wait_for_cm(struct nvme_rdma_queue *queue)
@@ -963,8 +965,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
struct nvme_rdma_device *dev = queue->device;
struct ib_device *ibdev = dev->dev;
- int nents, count;
- int ret;
+ int count, ret;
req->num_sge = 1;
req->inline_data = false;
@@ -976,16 +977,14 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
return nvme_rdma_set_sg_null(c);
req->sg_table.sgl = req->first_sgl;
- ret = sg_alloc_table_chained(&req->sg_table, rq->nr_phys_segments,
- req->sg_table.sgl);
+ ret = sg_alloc_table_chained(&req->sg_table,
+ blk_rq_nr_phys_segments(rq), req->sg_table.sgl);
if (ret)
return -ENOMEM;
- nents = blk_rq_map_sg(rq->q, rq, req->sg_table.sgl);
- BUG_ON(nents > rq->nr_phys_segments);
- req->nents = nents;
+ req->nents = blk_rq_map_sg(rq->q, rq, req->sg_table.sgl);
- count = ib_dma_map_sg(ibdev, req->sg_table.sgl, nents,
+ count = ib_dma_map_sg(ibdev, req->sg_table.sgl, req->nents,
rq_data_dir(rq) == WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (unlikely(count <= 0)) {
sg_free_table_chained(&req->sg_table, true);
@@ -1130,13 +1129,10 @@ static void nvme_rdma_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
struct nvme_completion *cqe, struct ib_wc *wc, int tag)
{
- u16 status = le16_to_cpu(cqe->status);
struct request *rq;
struct nvme_rdma_request *req;
int ret = 0;
- status >>= 1;
-
rq = blk_mq_tag_to_rq(nvme_rdma_tagset(queue), cqe->command_id);
if (!rq) {
dev_err(queue->ctrl->ctrl.device,
@@ -1147,9 +1143,6 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
}
req = blk_mq_rq_to_pdu(rq);
- if (rq->cmd_type == REQ_TYPE_DRV_PRIV && rq->special)
- memcpy(rq->special, cqe, sizeof(*cqe));
-
if (rq->tag == tag)
ret = 1;
@@ -1157,8 +1150,8 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
wc->ex.invalidate_rkey == req->mr->rkey)
req->mr->need_inval = false;
- blk_mq_complete_request(rq, status);
-
+ req->req.result = cqe->result;
+ blk_mq_complete_request(rq, le16_to_cpu(cqe->status) >> 1);
return ret;
}
@@ -1186,7 +1179,8 @@ static int __nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc, int tag)
*/
if (unlikely(nvme_rdma_queue_idx(queue) == 0 &&
cqe->command_id >= NVME_RDMA_AQ_BLKMQ_DEPTH))
- nvme_complete_async_event(&queue->ctrl->ctrl, cqe);
+ nvme_complete_async_event(&queue->ctrl->ctrl, cqe->status,
+ &cqe->result);
else
ret = nvme_rdma_process_nvme_rsp(queue, cqe, wc, tag);
ib_dma_sync_single_for_device(ibdev, qe->dma, len, DMA_FROM_DEVICE);
@@ -1433,10 +1427,9 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
sizeof(struct nvme_command), DMA_TO_DEVICE);
ret = nvme_setup_cmd(ns, rq, c);
- if (ret)
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
return ret;
- c->common.command_id = rq->tag;
blk_mq_start_request(rq);
map_len = nvme_map_len(rq);
@@ -1944,6 +1937,14 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
opts->queue_size = ctrl->ctrl.maxcmd;
}
+ if (opts->queue_size > ctrl->ctrl.sqsize + 1) {
+ /* warn if sqsize is lower than queue_size */
+ dev_warn(ctrl->ctrl.device,
+ "queue_size %zu > ctrl sqsize %u, clamping down\n",
+ opts->queue_size, ctrl->ctrl.sqsize + 1);
+ opts->queue_size = ctrl->ctrl.sqsize + 1;
+ }
+
if (opts->nr_io_queues) {
ret = nvme_rdma_create_io_queues(ctrl);
if (ret)
diff --git a/drivers/nvme/host/scsi.c b/drivers/nvme/host/scsi.c
index 3eaa4d27801e..b71e95044b43 100644
--- a/drivers/nvme/host/scsi.c
+++ b/drivers/nvme/host/scsi.c
@@ -1280,10 +1280,6 @@ static inline void nvme_trans_modesel_get_bd_len(u8 *parm_list, u8 cdb10,
static void nvme_trans_modesel_save_bd(struct nvme_ns *ns, u8 *parm_list,
u16 idx, u16 bd_len, u8 llbaa)
{
- u16 bd_num;
-
- bd_num = bd_len / ((llbaa == 0) ?
- SHORT_DESC_BLOCK : LONG_DESC_BLOCK);
/* Store block descriptor info if a FORMAT UNIT comes later */
/* TODO Saving 1st BD info; what to do if multiple BD received? */
if (llbaa == 0) {
@@ -1528,7 +1524,7 @@ static int nvme_trans_fmt_send_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
int nvme_sc;
struct nvme_id_ns *id_ns;
u8 i;
- u8 flbas, nlbaf;
+ u8 nlbaf;
u8 selected_lbaf = 0xFF;
u32 cdw10 = 0;
struct nvme_command c;
@@ -1539,7 +1535,6 @@ static int nvme_trans_fmt_send_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
if (res)
return res;
- flbas = (id_ns->flbas) & 0x0F;
nlbaf = id_ns->nlbaf;
for (i = 0; i < nlbaf; i++) {
@@ -2168,12 +2163,10 @@ static int nvme_trans_synchronize_cache(struct nvme_ns *ns,
static int nvme_trans_start_stop(struct nvme_ns *ns, struct sg_io_hdr *hdr,
u8 *cmd)
{
- u8 immed, pcmod, no_flush, start;
+ u8 immed, no_flush;
immed = cmd[1] & 0x01;
- pcmod = cmd[3] & 0x0f;
no_flush = cmd[4] & 0x04;
- start = cmd[4] & 0x01;
if (immed != 0) {
return nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig
index 3a5b9d0576cb..03e4ab65fe77 100644
--- a/drivers/nvme/target/Kconfig
+++ b/drivers/nvme/target/Kconfig
@@ -34,3 +34,27 @@ config NVME_TARGET_RDMA
devices over RDMA.
If unsure, say N.
+
+config NVME_TARGET_FC
+ tristate "NVMe over Fabrics FC target driver"
+ depends on NVME_TARGET
+ depends on HAS_DMA
+ help
+ This enables the NVMe FC target support, which allows exporting NVMe
+ devices over FC.
+
+ If unsure, say N.
+
+config NVME_TARGET_FCLOOP
+ tristate "NVMe over Fabrics FC Transport Loopback Test driver"
+ depends on NVME_TARGET
+ select NVME_CORE
+ select NVME_FABRICS
+ select SG_POOL
+ depends on NVME_FC
+ depends on NVME_TARGET_FC
+ help
+ This enables the NVMe FC loopback test support, which can be useful
+ to test NVMe-FC transport interfaces.
+
+ If unsure, say N.
diff --git a/drivers/nvme/target/Makefile b/drivers/nvme/target/Makefile
index b7a06232c9da..fecc14f535b2 100644
--- a/drivers/nvme/target/Makefile
+++ b/drivers/nvme/target/Makefile
@@ -2,8 +2,12 @@
obj-$(CONFIG_NVME_TARGET) += nvmet.o
obj-$(CONFIG_NVME_TARGET_LOOP) += nvme-loop.o
obj-$(CONFIG_NVME_TARGET_RDMA) += nvmet-rdma.o
+obj-$(CONFIG_NVME_TARGET_FC) += nvmet-fc.o
+obj-$(CONFIG_NVME_TARGET_FCLOOP) += nvme-fcloop.o
nvmet-y += core.o configfs.o admin-cmd.o io-cmd.o fabrics-cmd.o \
discovery.o
nvme-loop-y += loop.o
nvmet-rdma-y += rdma.o
+nvmet-fc-y += fc.o
+nvme-fcloop-y += fcloop.o
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 6fe4c48a21e4..ec1ad2aa0a4c 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -237,7 +237,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->maxcmd = cpu_to_le16(NVMET_MAX_CMD);
id->nn = cpu_to_le32(ctrl->subsys->max_nsid);
- id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM);
+ id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM |
+ NVME_CTRL_ONCS_WRITE_ZEROES);
/* XXX: don't report vwc if the underlying device is write through */
id->vwc = NVME_CTRL_VWC_PRESENT;
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index af5e2dc4a3d5..d0f60c36d576 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -37,6 +37,8 @@ static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
return sprintf(page, "ipv6\n");
case NVMF_ADDR_FAMILY_IB:
return sprintf(page, "ib\n");
+ case NVMF_ADDR_FAMILY_FC:
+ return sprintf(page, "fc\n");
default:
return sprintf(page, "\n");
}
@@ -59,6 +61,8 @@ static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP6;
} else if (sysfs_streq(page, "ib")) {
port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IB;
+ } else if (sysfs_streq(page, "fc")) {
+ port->disc_addr.adrfam = NVMF_ADDR_FAMILY_FC;
} else {
pr_err("Invalid value '%s' for adrfam\n", page);
return -EINVAL;
@@ -209,6 +213,8 @@ static ssize_t nvmet_addr_trtype_show(struct config_item *item,
return sprintf(page, "rdma\n");
case NVMF_TRTYPE_LOOP:
return sprintf(page, "loop\n");
+ case NVMF_TRTYPE_FC:
+ return sprintf(page, "fc\n");
default:
return sprintf(page, "\n");
}
@@ -229,6 +235,12 @@ static void nvmet_port_init_tsas_loop(struct nvmet_port *port)
memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
}
+static void nvmet_port_init_tsas_fc(struct nvmet_port *port)
+{
+ port->disc_addr.trtype = NVMF_TRTYPE_FC;
+ memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
+}
+
static ssize_t nvmet_addr_trtype_store(struct config_item *item,
const char *page, size_t count)
{
@@ -244,6 +256,8 @@ static ssize_t nvmet_addr_trtype_store(struct config_item *item,
nvmet_port_init_tsas_rdma(port);
} else if (sysfs_streq(page, "loop")) {
nvmet_port_init_tsas_loop(port);
+ } else if (sysfs_streq(page, "fc")) {
+ nvmet_port_init_tsas_fc(port);
} else {
pr_err("Invalid value '%s' for trtype\n", page);
return -EINVAL;
@@ -271,7 +285,7 @@ static ssize_t nvmet_ns_device_path_store(struct config_item *item,
mutex_lock(&subsys->lock);
ret = -EBUSY;
- if (nvmet_ns_enabled(ns))
+ if (ns->enabled)
goto out_unlock;
kfree(ns->device_path);
@@ -307,7 +321,7 @@ static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
int ret = 0;
mutex_lock(&subsys->lock);
- if (nvmet_ns_enabled(ns)) {
+ if (ns->enabled) {
ret = -EBUSY;
goto out_unlock;
}
@@ -339,7 +353,7 @@ CONFIGFS_ATTR(nvmet_ns_, device_nguid);
static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d\n", nvmet_ns_enabled(to_nvmet_ns(item)));
+ return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled);
}
static ssize_t nvmet_ns_enable_store(struct config_item *item,
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index a21437a33adb..b1d66ed655c9 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -264,7 +264,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
int ret = 0;
mutex_lock(&subsys->lock);
- if (!list_empty(&ns->dev_link))
+ if (ns->enabled)
goto out_unlock;
ns->bdev = blkdev_get_by_path(ns->device_path, FMODE_READ | FMODE_WRITE,
@@ -309,6 +309,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, 0, 0);
+ ns->enabled = true;
ret = 0;
out_unlock:
mutex_unlock(&subsys->lock);
@@ -325,11 +326,11 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
struct nvmet_ctrl *ctrl;
mutex_lock(&subsys->lock);
- if (list_empty(&ns->dev_link)) {
- mutex_unlock(&subsys->lock);
- return;
- }
- list_del_init(&ns->dev_link);
+ if (!ns->enabled)
+ goto out_unlock;
+
+ ns->enabled = false;
+ list_del_rcu(&ns->dev_link);
mutex_unlock(&subsys->lock);
/*
@@ -351,6 +352,7 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
if (ns->bdev)
blkdev_put(ns->bdev, FMODE_WRITE|FMODE_READ);
+out_unlock:
mutex_unlock(&subsys->lock);
}
@@ -617,7 +619,7 @@ u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
if (!subsys) {
pr_warn("connect request for invalid subsystem %s!\n",
subsysnqn);
- req->rsp->result = IPO_IATTR_CONNECT_DATA(subsysnqn);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn);
return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
}
@@ -638,7 +640,7 @@ u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
pr_warn("could not find controller %d for subsys %s / host %s\n",
cntlid, subsysnqn, hostnqn);
- req->rsp->result = IPO_IATTR_CONNECT_DATA(cntlid);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid);
status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
out:
@@ -700,7 +702,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
if (!subsys) {
pr_warn("connect request for invalid subsystem %s!\n",
subsysnqn);
- req->rsp->result = IPO_IATTR_CONNECT_DATA(subsysnqn);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn);
goto out;
}
@@ -709,7 +711,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
if (!nvmet_host_allowed(req, subsys, hostnqn)) {
pr_info("connect by host %s for subsystem %s not allowed\n",
hostnqn, subsysnqn);
- req->rsp->result = IPO_IATTR_CONNECT_DATA(hostnqn);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(hostnqn);
up_read(&nvmet_config_sem);
goto out_put_subsystem;
}
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index 9a97ae67e656..f4088198cd0d 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -69,7 +69,7 @@ static void nvmet_execute_prop_get(struct nvmet_req *req)
}
}
- req->rsp->result64 = cpu_to_le64(val);
+ req->rsp->result.u64 = cpu_to_le64(val);
nvmet_req_complete(req, status);
}
@@ -125,7 +125,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
d = kmap(sg_page(req->sg)) + req->sg->offset;
/* zero out initial completion result, assign values as needed */
- req->rsp->result = 0;
+ req->rsp->result.u32 = 0;
if (c->recfmt != 0) {
pr_warn("invalid connect version (%d).\n",
@@ -138,7 +138,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
pr_warn("connect attempt for invalid controller ID %#x\n",
d->cntlid);
status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
- req->rsp->result = IPO_IATTR_CONNECT_DATA(cntlid);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid);
goto out;
}
@@ -155,7 +155,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
pr_info("creating controller %d for NQN %s.\n",
ctrl->cntlid, ctrl->hostnqn);
- req->rsp->result16 = cpu_to_le16(ctrl->cntlid);
+ req->rsp->result.u16 = cpu_to_le16(ctrl->cntlid);
out:
kunmap(sg_page(req->sg));
@@ -173,7 +173,7 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
d = kmap(sg_page(req->sg)) + req->sg->offset;
/* zero out initial completion result, assign values as needed */
- req->rsp->result = 0;
+ req->rsp->result.u32 = 0;
if (c->recfmt != 0) {
pr_warn("invalid connect version (%d).\n",
@@ -191,14 +191,14 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
if (unlikely(qid > ctrl->subsys->max_qid)) {
pr_warn("invalid queue id (%d)\n", qid);
status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
- req->rsp->result = IPO_IATTR_CONNECT_SQE(qid);
+ req->rsp->result.u32 = IPO_IATTR_CONNECT_SQE(qid);
goto out_ctrl_put;
}
status = nvmet_install_queue(ctrl, req);
if (status) {
/* pass back cntlid that had the issue of installing queue */
- req->rsp->result16 = cpu_to_le16(ctrl->cntlid);
+ req->rsp->result.u16 = cpu_to_le16(ctrl->cntlid);
goto out_ctrl_put;
}
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
new file mode 100644
index 000000000000..173e842f19c9
--- /dev/null
+++ b/drivers/nvme/target/fc.c
@@ -0,0 +1,2288 @@
+/*
+ * Copyright (c) 2016 Avago Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO
+ * THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
+ * See the GNU General Public License for more details, a copy of which
+ * can be found in the file COPYING included with this package
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blk-mq.h>
+#include <linux/parser.h>
+#include <linux/random.h>
+#include <uapi/scsi/fc/fc_fs.h>
+#include <uapi/scsi/fc/fc_els.h>
+
+#include "nvmet.h"
+#include <linux/nvme-fc-driver.h>
+#include <linux/nvme-fc.h>
+
+
+/* *************************** Data Structures/Defines ****************** */
+
+
+#define NVMET_LS_CTX_COUNT 4
+
+/* for this implementation, assume small single frame rqst/rsp */
+#define NVME_FC_MAX_LS_BUFFER_SIZE 2048
+
+struct nvmet_fc_tgtport;
+struct nvmet_fc_tgt_assoc;
+
+struct nvmet_fc_ls_iod {
+ struct nvmefc_tgt_ls_req *lsreq;
+ struct nvmefc_tgt_fcp_req *fcpreq; /* only if RS */
+
+ struct list_head ls_list; /* tgtport->ls_list */
+
+ struct nvmet_fc_tgtport *tgtport;
+ struct nvmet_fc_tgt_assoc *assoc;
+
+ u8 *rqstbuf;
+ u8 *rspbuf;
+ u16 rqstdatalen;
+ dma_addr_t rspdma;
+
+ struct scatterlist sg[2];
+
+ struct work_struct work;
+} __aligned(sizeof(unsigned long long));
+
+#define NVMET_FC_MAX_KB_PER_XFR 256
+
+enum nvmet_fcp_datadir {
+ NVMET_FCP_NODATA,
+ NVMET_FCP_WRITE,
+ NVMET_FCP_READ,
+ NVMET_FCP_ABORTED,
+};
+
+struct nvmet_fc_fcp_iod {
+ struct nvmefc_tgt_fcp_req *fcpreq;
+
+ struct nvme_fc_cmd_iu cmdiubuf;
+ struct nvme_fc_ersp_iu rspiubuf;
+ dma_addr_t rspdma;
+ struct scatterlist *data_sg;
+ struct scatterlist *next_sg;
+ int data_sg_cnt;
+ u32 next_sg_offset;
+ u32 total_length;
+ u32 offset;
+ enum nvmet_fcp_datadir io_dir;
+ bool active;
+ bool abort;
+ spinlock_t flock;
+
+ struct nvmet_req req;
+ struct work_struct work;
+
+ struct nvmet_fc_tgtport *tgtport;
+ struct nvmet_fc_tgt_queue *queue;
+
+ struct list_head fcp_list; /* tgtport->fcp_list */
+};
+
+struct nvmet_fc_tgtport {
+
+ struct nvmet_fc_target_port fc_target_port;
+
+ struct list_head tgt_list; /* nvmet_fc_target_list */
+ struct device *dev; /* dev for dma mapping */
+ struct nvmet_fc_target_template *ops;
+
+ struct nvmet_fc_ls_iod *iod;
+ spinlock_t lock;
+ struct list_head ls_list;
+ struct list_head ls_busylist;
+ struct list_head assoc_list;
+ struct ida assoc_cnt;
+ struct nvmet_port *port;
+ struct kref ref;
+};
+
+struct nvmet_fc_tgt_queue {
+ bool ninetypercent;
+ u16 qid;
+ u16 sqsize;
+ u16 ersp_ratio;
+ u16 sqhd;
+ int cpu;
+ atomic_t connected;
+ atomic_t sqtail;
+ atomic_t zrspcnt;
+ atomic_t rsn;
+ spinlock_t qlock;
+ struct nvmet_port *port;
+ struct nvmet_cq nvme_cq;
+ struct nvmet_sq nvme_sq;
+ struct nvmet_fc_tgt_assoc *assoc;
+ struct nvmet_fc_fcp_iod *fod; /* array of fcp_iods */
+ struct list_head fod_list;
+ struct workqueue_struct *work_q;
+ struct kref ref;
+} __aligned(sizeof(unsigned long long));
+
+struct nvmet_fc_tgt_assoc {
+ u64 association_id;
+ u32 a_id;
+ struct nvmet_fc_tgtport *tgtport;
+ struct list_head a_list;
+ struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES];
+ struct kref ref;
+};
+
+
+static inline int
+nvmet_fc_iodnum(struct nvmet_fc_ls_iod *iodptr)
+{
+ return (iodptr - iodptr->tgtport->iod);
+}
+
+static inline int
+nvmet_fc_fodnum(struct nvmet_fc_fcp_iod *fodptr)
+{
+ return (fodptr - fodptr->queue->fod);
+}
+
+
+/*
+ * Association and Connection IDs:
+ *
+ * Association ID will have random number in upper 6 bytes and zero
+ * in lower 2 bytes
+ *
+ * Connection IDs will be Association ID with QID or'd in lower 2 bytes
+ *
+ * note: Association ID = Connection ID for queue 0
+ */
+#define BYTES_FOR_QID sizeof(u16)
+#define BYTES_FOR_QID_SHIFT (BYTES_FOR_QID * 8)
+#define NVMET_FC_QUEUEID_MASK ((u64)((1 << BYTES_FOR_QID_SHIFT) - 1))
+
+static inline u64
+nvmet_fc_makeconnid(struct nvmet_fc_tgt_assoc *assoc, u16 qid)
+{
+ return (assoc->association_id | qid);
+}
+
+static inline u64
+nvmet_fc_getassociationid(u64 connectionid)
+{
+ return connectionid & ~NVMET_FC_QUEUEID_MASK;
+}
+
+static inline u16
+nvmet_fc_getqueueid(u64 connectionid)
+{
+ return (u16)(connectionid & NVMET_FC_QUEUEID_MASK);
+}
+
+static inline struct nvmet_fc_tgtport *
+targetport_to_tgtport(struct nvmet_fc_target_port *targetport)
+{
+ return container_of(targetport, struct nvmet_fc_tgtport,
+ fc_target_port);
+}
+
+static inline struct nvmet_fc_fcp_iod *
+nvmet_req_to_fod(struct nvmet_req *nvme_req)
+{
+ return container_of(nvme_req, struct nvmet_fc_fcp_iod, req);
+}
+
+
+/* *************************** Globals **************************** */
+
+
+static DEFINE_SPINLOCK(nvmet_fc_tgtlock);
+
+static LIST_HEAD(nvmet_fc_target_list);
+static DEFINE_IDA(nvmet_fc_tgtport_cnt);
+
+
+static void nvmet_fc_handle_ls_rqst_work(struct work_struct *work);
+static void nvmet_fc_handle_fcp_rqst_work(struct work_struct *work);
+static void nvmet_fc_tgt_a_put(struct nvmet_fc_tgt_assoc *assoc);
+static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc);
+static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue);
+static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue);
+static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport);
+static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport);
+
+
+/* *********************** FC-NVME DMA Handling **************************** */
+
+/*
+ * The fcloop device passes in a NULL device pointer. Real LLD's will
+ * pass in a valid device pointer. If NULL is passed to the dma mapping
+ * routines, depending on the platform, it may or may not succeed, and
+ * may crash.
+ *
+ * As such:
+ * Wrapper all the dma routines and check the dev pointer.
+ *
+ * If simple mappings (return just a dma address, we'll noop them,
+ * returning a dma address of 0.
+ *
+ * On more complex mappings (dma_map_sg), a pseudo routine fills
+ * in the scatter list, setting all dma addresses to 0.
+ */
+
+static inline dma_addr_t
+fc_dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ return dev ? dma_map_single(dev, ptr, size, dir) : (dma_addr_t)0L;
+}
+
+static inline int
+fc_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return dev ? dma_mapping_error(dev, dma_addr) : 0;
+}
+
+static inline void
+fc_dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_unmap_single(dev, addr, size, dir);
+}
+
+static inline void
+fc_dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_sync_single_for_cpu(dev, addr, size, dir);
+}
+
+static inline void
+fc_dma_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_sync_single_for_device(dev, addr, size, dir);
+}
+
+/* pseudo dma_map_sg call */
+static int
+fc_map_sg(struct scatterlist *sg, int nents)
+{
+ struct scatterlist *s;
+ int i;
+
+ WARN_ON(nents == 0 || sg[0].length == 0);
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = 0L;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ s->dma_length = s->length;
+#endif
+ }
+ return nents;
+}
+
+static inline int
+fc_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ return dev ? dma_map_sg(dev, sg, nents, dir) : fc_map_sg(sg, nents);
+}
+
+static inline void
+fc_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ if (dev)
+ dma_unmap_sg(dev, sg, nents, dir);
+}
+
+
+/* *********************** FC-NVME Port Management ************************ */
+
+
+static int
+nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
+{
+ struct nvmet_fc_ls_iod *iod;
+ int i;
+
+ iod = kcalloc(NVMET_LS_CTX_COUNT, sizeof(struct nvmet_fc_ls_iod),
+ GFP_KERNEL);
+ if (!iod)
+ return -ENOMEM;
+
+ tgtport->iod = iod;
+
+ for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
+ INIT_WORK(&iod->work, nvmet_fc_handle_ls_rqst_work);
+ iod->tgtport = tgtport;
+ list_add_tail(&iod->ls_list, &tgtport->ls_list);
+
+ iod->rqstbuf = kcalloc(2, NVME_FC_MAX_LS_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!iod->rqstbuf)
+ goto out_fail;
+
+ iod->rspbuf = iod->rqstbuf + NVME_FC_MAX_LS_BUFFER_SIZE;
+
+ iod->rspdma = fc_dma_map_single(tgtport->dev, iod->rspbuf,
+ NVME_FC_MAX_LS_BUFFER_SIZE,
+ DMA_TO_DEVICE);
+ if (fc_dma_mapping_error(tgtport->dev, iod->rspdma))
+ goto out_fail;
+ }
+
+ return 0;
+
+out_fail:
+ kfree(iod->rqstbuf);
+ list_del(&iod->ls_list);
+ for (iod--, i--; i >= 0; iod--, i--) {
+ fc_dma_unmap_single(tgtport->dev, iod->rspdma,
+ NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
+ kfree(iod->rqstbuf);
+ list_del(&iod->ls_list);
+ }
+
+ kfree(iod);
+
+ return -EFAULT;
+}
+
+static void
+nvmet_fc_free_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
+{
+ struct nvmet_fc_ls_iod *iod = tgtport->iod;
+ int i;
+
+ for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
+ fc_dma_unmap_single(tgtport->dev,
+ iod->rspdma, NVME_FC_MAX_LS_BUFFER_SIZE,
+ DMA_TO_DEVICE);
+ kfree(iod->rqstbuf);
+ list_del(&iod->ls_list);
+ }
+ kfree(tgtport->iod);
+}
+
+static struct nvmet_fc_ls_iod *
+nvmet_fc_alloc_ls_iod(struct nvmet_fc_tgtport *tgtport)
+{
+ static struct nvmet_fc_ls_iod *iod;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ iod = list_first_entry_or_null(&tgtport->ls_list,
+ struct nvmet_fc_ls_iod, ls_list);
+ if (iod)
+ list_move_tail(&iod->ls_list, &tgtport->ls_busylist);
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ return iod;
+}
+
+
+static void
+nvmet_fc_free_ls_iod(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_move(&iod->ls_list, &tgtport->ls_list);
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+}
+
+static void
+nvmet_fc_prep_fcp_iodlist(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_tgt_queue *queue)
+{
+ struct nvmet_fc_fcp_iod *fod = queue->fod;
+ int i;
+
+ for (i = 0; i < queue->sqsize; fod++, i++) {
+ INIT_WORK(&fod->work, nvmet_fc_handle_fcp_rqst_work);
+ fod->tgtport = tgtport;
+ fod->queue = queue;
+ fod->active = false;
+ list_add_tail(&fod->fcp_list, &queue->fod_list);
+ spin_lock_init(&fod->flock);
+
+ fod->rspdma = fc_dma_map_single(tgtport->dev, &fod->rspiubuf,
+ sizeof(fod->rspiubuf), DMA_TO_DEVICE);
+ if (fc_dma_mapping_error(tgtport->dev, fod->rspdma)) {
+ list_del(&fod->fcp_list);
+ for (fod--, i--; i >= 0; fod--, i--) {
+ fc_dma_unmap_single(tgtport->dev, fod->rspdma,
+ sizeof(fod->rspiubuf),
+ DMA_TO_DEVICE);
+ fod->rspdma = 0L;
+ list_del(&fod->fcp_list);
+ }
+
+ return;
+ }
+ }
+}
+
+static void
+nvmet_fc_destroy_fcp_iodlist(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_tgt_queue *queue)
+{
+ struct nvmet_fc_fcp_iod *fod = queue->fod;
+ int i;
+
+ for (i = 0; i < queue->sqsize; fod++, i++) {
+ if (fod->rspdma)
+ fc_dma_unmap_single(tgtport->dev, fod->rspdma,
+ sizeof(fod->rspiubuf), DMA_TO_DEVICE);
+ }
+}
+
+static struct nvmet_fc_fcp_iod *
+nvmet_fc_alloc_fcp_iod(struct nvmet_fc_tgt_queue *queue)
+{
+ static struct nvmet_fc_fcp_iod *fod;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->qlock, flags);
+ fod = list_first_entry_or_null(&queue->fod_list,
+ struct nvmet_fc_fcp_iod, fcp_list);
+ if (fod) {
+ list_del(&fod->fcp_list);
+ fod->active = true;
+ fod->abort = false;
+ /*
+ * no queue reference is taken, as it was taken by the
+ * queue lookup just prior to the allocation. The iod
+ * will "inherit" that reference.
+ */
+ }
+ spin_unlock_irqrestore(&queue->qlock, flags);
+ return fod;
+}
+
+
+static void
+nvmet_fc_free_fcp_iod(struct nvmet_fc_tgt_queue *queue,
+ struct nvmet_fc_fcp_iod *fod)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->qlock, flags);
+ list_add_tail(&fod->fcp_list, &fod->queue->fod_list);
+ fod->active = false;
+ spin_unlock_irqrestore(&queue->qlock, flags);
+
+ /*
+ * release the reference taken at queue lookup and fod allocation
+ */
+ nvmet_fc_tgt_q_put(queue);
+}
+
+static int
+nvmet_fc_queue_to_cpu(struct nvmet_fc_tgtport *tgtport, int qid)
+{
+ int cpu, idx, cnt;
+
+ if (!(tgtport->ops->target_features &
+ NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED) ||
+ tgtport->ops->max_hw_queues == 1)
+ return WORK_CPU_UNBOUND;
+
+ /* Simple cpu selection based on qid modulo active cpu count */
+ idx = !qid ? 0 : (qid - 1) % num_active_cpus();
+
+ /* find the n'th active cpu */
+ for (cpu = 0, cnt = 0; ; ) {
+ if (cpu_active(cpu)) {
+ if (cnt == idx)
+ break;
+ cnt++;
+ }
+ cpu = (cpu + 1) % num_possible_cpus();
+ }
+
+ return cpu;
+}
+
+static struct nvmet_fc_tgt_queue *
+nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc,
+ u16 qid, u16 sqsize)
+{
+ struct nvmet_fc_tgt_queue *queue;
+ unsigned long flags;
+ int ret;
+
+ if (qid >= NVMET_NR_QUEUES)
+ return NULL;
+
+ queue = kzalloc((sizeof(*queue) +
+ (sizeof(struct nvmet_fc_fcp_iod) * sqsize)),
+ GFP_KERNEL);
+ if (!queue)
+ return NULL;
+
+ if (!nvmet_fc_tgt_a_get(assoc))
+ goto out_free_queue;
+
+ queue->work_q = alloc_workqueue("ntfc%d.%d.%d", 0, 0,
+ assoc->tgtport->fc_target_port.port_num,
+ assoc->a_id, qid);
+ if (!queue->work_q)
+ goto out_a_put;
+
+ queue->fod = (struct nvmet_fc_fcp_iod *)&queue[1];
+ queue->qid = qid;
+ queue->sqsize = sqsize;
+ queue->assoc = assoc;
+ queue->port = assoc->tgtport->port;
+ queue->cpu = nvmet_fc_queue_to_cpu(assoc->tgtport, qid);
+ INIT_LIST_HEAD(&queue->fod_list);
+ atomic_set(&queue->connected, 0);
+ atomic_set(&queue->sqtail, 0);
+ atomic_set(&queue->rsn, 1);
+ atomic_set(&queue->zrspcnt, 0);
+ spin_lock_init(&queue->qlock);
+ kref_init(&queue->ref);
+
+ nvmet_fc_prep_fcp_iodlist(assoc->tgtport, queue);
+
+ ret = nvmet_sq_init(&queue->nvme_sq);
+ if (ret)
+ goto out_fail_iodlist;
+
+ WARN_ON(assoc->queues[qid]);
+ spin_lock_irqsave(&assoc->tgtport->lock, flags);
+ assoc->queues[qid] = queue;
+ spin_unlock_irqrestore(&assoc->tgtport->lock, flags);
+
+ return queue;
+
+out_fail_iodlist:
+ nvmet_fc_destroy_fcp_iodlist(assoc->tgtport, queue);
+ destroy_workqueue(queue->work_q);
+out_a_put:
+ nvmet_fc_tgt_a_put(assoc);
+out_free_queue:
+ kfree(queue);
+ return NULL;
+}
+
+
+static void
+nvmet_fc_tgt_queue_free(struct kref *ref)
+{
+ struct nvmet_fc_tgt_queue *queue =
+ container_of(ref, struct nvmet_fc_tgt_queue, ref);
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->assoc->tgtport->lock, flags);
+ queue->assoc->queues[queue->qid] = NULL;
+ spin_unlock_irqrestore(&queue->assoc->tgtport->lock, flags);
+
+ nvmet_fc_destroy_fcp_iodlist(queue->assoc->tgtport, queue);
+
+ nvmet_fc_tgt_a_put(queue->assoc);
+
+ destroy_workqueue(queue->work_q);
+
+ kfree(queue);
+}
+
+static void
+nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue)
+{
+ kref_put(&queue->ref, nvmet_fc_tgt_queue_free);
+}
+
+static int
+nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue)
+{
+ return kref_get_unless_zero(&queue->ref);
+}
+
+
+static void
+nvmet_fc_abort_op(struct nvmet_fc_tgtport *tgtport,
+ struct nvmefc_tgt_fcp_req *fcpreq)
+{
+ int ret;
+
+ fcpreq->op = NVMET_FCOP_ABORT;
+ fcpreq->offset = 0;
+ fcpreq->timeout = 0;
+ fcpreq->transfer_length = 0;
+ fcpreq->transferred_length = 0;
+ fcpreq->fcp_error = 0;
+ fcpreq->sg_cnt = 0;
+
+ ret = tgtport->ops->fcp_op(&tgtport->fc_target_port, fcpreq);
+ if (ret)
+ /* should never reach here !! */
+ WARN_ON(1);
+}
+
+
+static void
+nvmet_fc_delete_target_queue(struct nvmet_fc_tgt_queue *queue)
+{
+ struct nvmet_fc_fcp_iod *fod = queue->fod;
+ unsigned long flags;
+ int i;
+ bool disconnect;
+
+ disconnect = atomic_xchg(&queue->connected, 0);
+
+ spin_lock_irqsave(&queue->qlock, flags);
+ /* about outstanding io's */
+ for (i = 0; i < queue->sqsize; fod++, i++) {
+ if (fod->active) {
+ spin_lock(&fod->flock);
+ fod->abort = true;
+ spin_unlock(&fod->flock);
+ }
+ }
+ spin_unlock_irqrestore(&queue->qlock, flags);
+
+ flush_workqueue(queue->work_q);
+
+ if (disconnect)
+ nvmet_sq_destroy(&queue->nvme_sq);
+
+ nvmet_fc_tgt_q_put(queue);
+}
+
+static struct nvmet_fc_tgt_queue *
+nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport,
+ u64 connection_id)
+{
+ struct nvmet_fc_tgt_assoc *assoc;
+ struct nvmet_fc_tgt_queue *queue;
+ u64 association_id = nvmet_fc_getassociationid(connection_id);
+ u16 qid = nvmet_fc_getqueueid(connection_id);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
+ if (association_id == assoc->association_id) {
+ queue = assoc->queues[qid];
+ if (queue &&
+ (!atomic_read(&queue->connected) ||
+ !nvmet_fc_tgt_q_get(queue)))
+ queue = NULL;
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ return queue;
+ }
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ return NULL;
+}
+
+static struct nvmet_fc_tgt_assoc *
+nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport)
+{
+ struct nvmet_fc_tgt_assoc *assoc, *tmpassoc;
+ unsigned long flags;
+ u64 ran;
+ int idx;
+ bool needrandom = true;
+
+ assoc = kzalloc(sizeof(*assoc), GFP_KERNEL);
+ if (!assoc)
+ return NULL;
+
+ idx = ida_simple_get(&tgtport->assoc_cnt, 0, 0, GFP_KERNEL);
+ if (idx < 0)
+ goto out_free_assoc;
+
+ if (!nvmet_fc_tgtport_get(tgtport))
+ goto out_ida_put;
+
+ assoc->tgtport = tgtport;
+ assoc->a_id = idx;
+ INIT_LIST_HEAD(&assoc->a_list);
+ kref_init(&assoc->ref);
+
+ while (needrandom) {
+ get_random_bytes(&ran, sizeof(ran) - BYTES_FOR_QID);
+ ran = ran << BYTES_FOR_QID_SHIFT;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ needrandom = false;
+ list_for_each_entry(tmpassoc, &tgtport->assoc_list, a_list)
+ if (ran == tmpassoc->association_id) {
+ needrandom = true;
+ break;
+ }
+ if (!needrandom) {
+ assoc->association_id = ran;
+ list_add_tail(&assoc->a_list, &tgtport->assoc_list);
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ }
+
+ return assoc;
+
+out_ida_put:
+ ida_simple_remove(&tgtport->assoc_cnt, idx);
+out_free_assoc:
+ kfree(assoc);
+ return NULL;
+}
+
+static void
+nvmet_fc_target_assoc_free(struct kref *ref)
+{
+ struct nvmet_fc_tgt_assoc *assoc =
+ container_of(ref, struct nvmet_fc_tgt_assoc, ref);
+ struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_del(&assoc->a_list);
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ ida_simple_remove(&tgtport->assoc_cnt, assoc->a_id);
+ kfree(assoc);
+ nvmet_fc_tgtport_put(tgtport);
+}
+
+static void
+nvmet_fc_tgt_a_put(struct nvmet_fc_tgt_assoc *assoc)
+{
+ kref_put(&assoc->ref, nvmet_fc_target_assoc_free);
+}
+
+static int
+nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc)
+{
+ return kref_get_unless_zero(&assoc->ref);
+}
+
+static void
+nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc)
+{
+ struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
+ struct nvmet_fc_tgt_queue *queue;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ for (i = NVMET_NR_QUEUES - 1; i >= 0; i--) {
+ queue = assoc->queues[i];
+ if (queue) {
+ if (!nvmet_fc_tgt_q_get(queue))
+ continue;
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ nvmet_fc_delete_target_queue(queue);
+ nvmet_fc_tgt_q_put(queue);
+ spin_lock_irqsave(&tgtport->lock, flags);
+ }
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+
+ nvmet_fc_tgt_a_put(assoc);
+}
+
+static struct nvmet_fc_tgt_assoc *
+nvmet_fc_find_target_assoc(struct nvmet_fc_tgtport *tgtport,
+ u64 association_id)
+{
+ struct nvmet_fc_tgt_assoc *assoc;
+ struct nvmet_fc_tgt_assoc *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
+ if (association_id == assoc->association_id) {
+ ret = assoc;
+ nvmet_fc_tgt_a_get(assoc);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+
+ return ret;
+}
+
+
+/**
+ * nvme_fc_register_targetport - transport entry point called by an
+ * LLDD to register the existence of a local
+ * NVME subystem FC port.
+ * @pinfo: pointer to information about the port to be registered
+ * @template: LLDD entrypoints and operational parameters for the port
+ * @dev: physical hardware device node port corresponds to. Will be
+ * used for DMA mappings
+ * @portptr: pointer to a local port pointer. Upon success, the routine
+ * will allocate a nvme_fc_local_port structure and place its
+ * address in the local port pointer. Upon failure, local port
+ * pointer will be set to NULL.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo,
+ struct nvmet_fc_target_template *template,
+ struct device *dev,
+ struct nvmet_fc_target_port **portptr)
+{
+ struct nvmet_fc_tgtport *newrec;
+ unsigned long flags;
+ int ret, idx;
+
+ if (!template->xmt_ls_rsp || !template->fcp_op ||
+ !template->targetport_delete ||
+ !template->max_hw_queues || !template->max_sgl_segments ||
+ !template->max_dif_sgl_segments || !template->dma_boundary) {
+ ret = -EINVAL;
+ goto out_regtgt_failed;
+ }
+
+ newrec = kzalloc((sizeof(*newrec) + template->target_priv_sz),
+ GFP_KERNEL);
+ if (!newrec) {
+ ret = -ENOMEM;
+ goto out_regtgt_failed;
+ }
+
+ idx = ida_simple_get(&nvmet_fc_tgtport_cnt, 0, 0, GFP_KERNEL);
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out_fail_kfree;
+ }
+
+ if (!get_device(dev) && dev) {
+ ret = -ENODEV;
+ goto out_ida_put;
+ }
+
+ newrec->fc_target_port.node_name = pinfo->node_name;
+ newrec->fc_target_port.port_name = pinfo->port_name;
+ newrec->fc_target_port.private = &newrec[1];
+ newrec->fc_target_port.port_id = pinfo->port_id;
+ newrec->fc_target_port.port_num = idx;
+ INIT_LIST_HEAD(&newrec->tgt_list);
+ newrec->dev = dev;
+ newrec->ops = template;
+ spin_lock_init(&newrec->lock);
+ INIT_LIST_HEAD(&newrec->ls_list);
+ INIT_LIST_HEAD(&newrec->ls_busylist);
+ INIT_LIST_HEAD(&newrec->assoc_list);
+ kref_init(&newrec->ref);
+ ida_init(&newrec->assoc_cnt);
+
+ ret = nvmet_fc_alloc_ls_iodlist(newrec);
+ if (ret) {
+ ret = -ENOMEM;
+ goto out_free_newrec;
+ }
+
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ list_add_tail(&newrec->tgt_list, &nvmet_fc_target_list);
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+
+ *portptr = &newrec->fc_target_port;
+ return 0;
+
+out_free_newrec:
+ put_device(dev);
+out_ida_put:
+ ida_simple_remove(&nvmet_fc_tgtport_cnt, idx);
+out_fail_kfree:
+ kfree(newrec);
+out_regtgt_failed:
+ *portptr = NULL;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nvmet_fc_register_targetport);
+
+
+static void
+nvmet_fc_free_tgtport(struct kref *ref)
+{
+ struct nvmet_fc_tgtport *tgtport =
+ container_of(ref, struct nvmet_fc_tgtport, ref);
+ struct device *dev = tgtport->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ list_del(&tgtport->tgt_list);
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+
+ nvmet_fc_free_ls_iodlist(tgtport);
+
+ /* let the LLDD know we've finished tearing it down */
+ tgtport->ops->targetport_delete(&tgtport->fc_target_port);
+
+ ida_simple_remove(&nvmet_fc_tgtport_cnt,
+ tgtport->fc_target_port.port_num);
+
+ ida_destroy(&tgtport->assoc_cnt);
+
+ kfree(tgtport);
+
+ put_device(dev);
+}
+
+static void
+nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport)
+{
+ kref_put(&tgtport->ref, nvmet_fc_free_tgtport);
+}
+
+static int
+nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport)
+{
+ return kref_get_unless_zero(&tgtport->ref);
+}
+
+static void
+__nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport)
+{
+ struct nvmet_fc_tgt_assoc *assoc, *next;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_for_each_entry_safe(assoc, next,
+ &tgtport->assoc_list, a_list) {
+ if (!nvmet_fc_tgt_a_get(assoc))
+ continue;
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+ nvmet_fc_delete_target_assoc(assoc);
+ nvmet_fc_tgt_a_put(assoc);
+ spin_lock_irqsave(&tgtport->lock, flags);
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+}
+
+/*
+ * nvmet layer has called to terminate an association
+ */
+static void
+nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl)
+{
+ struct nvmet_fc_tgtport *tgtport, *next;
+ struct nvmet_fc_tgt_assoc *assoc;
+ struct nvmet_fc_tgt_queue *queue;
+ unsigned long flags;
+ bool found_ctrl = false;
+
+ /* this is a bit ugly, but don't want to make locks layered */
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ list_for_each_entry_safe(tgtport, next, &nvmet_fc_target_list,
+ tgt_list) {
+ if (!nvmet_fc_tgtport_get(tgtport))
+ continue;
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+
+ spin_lock_irqsave(&tgtport->lock, flags);
+ list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
+ queue = assoc->queues[0];
+ if (queue && queue->nvme_sq.ctrl == ctrl) {
+ if (nvmet_fc_tgt_a_get(assoc))
+ found_ctrl = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+
+ nvmet_fc_tgtport_put(tgtport);
+
+ if (found_ctrl) {
+ nvmet_fc_delete_target_assoc(assoc);
+ nvmet_fc_tgt_a_put(assoc);
+ return;
+ }
+
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ }
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+}
+
+/**
+ * nvme_fc_unregister_targetport - transport entry point called by an
+ * LLDD to deregister/remove a previously
+ * registered a local NVME subsystem FC port.
+ * @tgtport: pointer to the (registered) target port that is to be
+ * deregistered.
+ *
+ * Returns:
+ * a completion status. Must be 0 upon success; a negative errno
+ * (ex: -ENXIO) upon failure.
+ */
+int
+nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *target_port)
+{
+ struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
+
+ /* terminate any outstanding associations */
+ __nvmet_fc_free_assocs(tgtport);
+
+ nvmet_fc_tgtport_put(tgtport);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmet_fc_unregister_targetport);
+
+
+/* *********************** FC-NVME LS Handling **************************** */
+
+
+static void
+nvmet_fc_format_rsp_hdr(void *buf, u8 ls_cmd, u32 desc_len, u8 rqst_ls_cmd)
+{
+ struct fcnvme_ls_acc_hdr *acc = buf;
+
+ acc->w0.ls_cmd = ls_cmd;
+ acc->desc_list_len = desc_len;
+ acc->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST);
+ acc->rqst.desc_len =
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst));
+ acc->rqst.w0.ls_cmd = rqst_ls_cmd;
+}
+
+static int
+nvmet_fc_format_rjt(void *buf, u16 buflen, u8 ls_cmd,
+ u8 reason, u8 explanation, u8 vendor)
+{
+ struct fcnvme_ls_rjt *rjt = buf;
+
+ nvmet_fc_format_rsp_hdr(buf, FCNVME_LSDESC_RQST,
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)),
+ ls_cmd);
+ rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT);
+ rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt));
+ rjt->rjt.reason_code = reason;
+ rjt->rjt.reason_explanation = explanation;
+ rjt->rjt.vendor = vendor;
+
+ return sizeof(struct fcnvme_ls_rjt);
+}
+
+/* Validation Error indexes into the string table below */
+enum {
+ VERR_NO_ERROR = 0,
+ VERR_CR_ASSOC_LEN = 1,
+ VERR_CR_ASSOC_RQST_LEN = 2,
+ VERR_CR_ASSOC_CMD = 3,
+ VERR_CR_ASSOC_CMD_LEN = 4,
+ VERR_ERSP_RATIO = 5,
+ VERR_ASSOC_ALLOC_FAIL = 6,
+ VERR_QUEUE_ALLOC_FAIL = 7,
+ VERR_CR_CONN_LEN = 8,
+ VERR_CR_CONN_RQST_LEN = 9,
+ VERR_ASSOC_ID = 10,
+ VERR_ASSOC_ID_LEN = 11,
+ VERR_NO_ASSOC = 12,
+ VERR_CONN_ID = 13,
+ VERR_CONN_ID_LEN = 14,
+ VERR_NO_CONN = 15,
+ VERR_CR_CONN_CMD = 16,
+ VERR_CR_CONN_CMD_LEN = 17,
+ VERR_DISCONN_LEN = 18,
+ VERR_DISCONN_RQST_LEN = 19,
+ VERR_DISCONN_CMD = 20,
+ VERR_DISCONN_CMD_LEN = 21,
+ VERR_DISCONN_SCOPE = 22,
+ VERR_RS_LEN = 23,
+ VERR_RS_RQST_LEN = 24,
+ VERR_RS_CMD = 25,
+ VERR_RS_CMD_LEN = 26,
+ VERR_RS_RCTL = 27,
+ VERR_RS_RO = 28,
+};
+
+static char *validation_errors[] = {
+ "OK",
+ "Bad CR_ASSOC Length",
+ "Bad CR_ASSOC Rqst Length",
+ "Not CR_ASSOC Cmd",
+ "Bad CR_ASSOC Cmd Length",
+ "Bad Ersp Ratio",
+ "Association Allocation Failed",
+ "Queue Allocation Failed",
+ "Bad CR_CONN Length",
+ "Bad CR_CONN Rqst Length",
+ "Not Association ID",
+ "Bad Association ID Length",
+ "No Association",
+ "Not Connection ID",
+ "Bad Connection ID Length",
+ "No Connection",
+ "Not CR_CONN Cmd",
+ "Bad CR_CONN Cmd Length",
+ "Bad DISCONN Length",
+ "Bad DISCONN Rqst Length",
+ "Not DISCONN Cmd",
+ "Bad DISCONN Cmd Length",
+ "Bad Disconnect Scope",
+ "Bad RS Length",
+ "Bad RS Rqst Length",
+ "Not RS Cmd",
+ "Bad RS Cmd Length",
+ "Bad RS R_CTL",
+ "Bad RS Relative Offset",
+};
+
+static void
+nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ struct fcnvme_ls_cr_assoc_rqst *rqst =
+ (struct fcnvme_ls_cr_assoc_rqst *)iod->rqstbuf;
+ struct fcnvme_ls_cr_assoc_acc *acc =
+ (struct fcnvme_ls_cr_assoc_acc *)iod->rspbuf;
+ struct nvmet_fc_tgt_queue *queue;
+ int ret = 0;
+
+ memset(acc, 0, sizeof(*acc));
+
+ if (iod->rqstdatalen < sizeof(struct fcnvme_ls_cr_assoc_rqst))
+ ret = VERR_CR_ASSOC_LEN;
+ else if (rqst->desc_list_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_cr_assoc_rqst)))
+ ret = VERR_CR_ASSOC_RQST_LEN;
+ else if (rqst->assoc_cmd.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_CREATE_ASSOC_CMD))
+ ret = VERR_CR_ASSOC_CMD;
+ else if (rqst->assoc_cmd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_cr_assoc_cmd)))
+ ret = VERR_CR_ASSOC_CMD_LEN;
+ else if (!rqst->assoc_cmd.ersp_ratio ||
+ (be16_to_cpu(rqst->assoc_cmd.ersp_ratio) >=
+ be16_to_cpu(rqst->assoc_cmd.sqsize)))
+ ret = VERR_ERSP_RATIO;
+
+ else {
+ /* new association w/ admin queue */
+ iod->assoc = nvmet_fc_alloc_target_assoc(tgtport);
+ if (!iod->assoc)
+ ret = VERR_ASSOC_ALLOC_FAIL;
+ else {
+ queue = nvmet_fc_alloc_target_queue(iod->assoc, 0,
+ be16_to_cpu(rqst->assoc_cmd.sqsize));
+ if (!queue)
+ ret = VERR_QUEUE_ALLOC_FAIL;
+ }
+ }
+
+ if (ret) {
+ dev_err(tgtport->dev,
+ "Create Association LS failed: %s\n",
+ validation_errors[ret]);
+ iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
+ NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
+ ELS_RJT_LOGIC,
+ ELS_EXPL_NONE, 0);
+ return;
+ }
+
+ queue->ersp_ratio = be16_to_cpu(rqst->assoc_cmd.ersp_ratio);
+ atomic_set(&queue->connected, 1);
+ queue->sqhd = 0; /* best place to init value */
+
+ /* format a response */
+
+ iod->lsreq->rsplen = sizeof(*acc);
+
+ nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_cr_assoc_acc)),
+ FCNVME_LS_CREATE_ASSOCIATION);
+ acc->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
+ acc->associd.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id));
+ acc->associd.association_id =
+ cpu_to_be64(nvmet_fc_makeconnid(iod->assoc, 0));
+ acc->connectid.desc_tag = cpu_to_be32(FCNVME_LSDESC_CONN_ID);
+ acc->connectid.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_conn_id));
+ acc->connectid.connection_id = acc->associd.association_id;
+}
+
+static void
+nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ struct fcnvme_ls_cr_conn_rqst *rqst =
+ (struct fcnvme_ls_cr_conn_rqst *)iod->rqstbuf;
+ struct fcnvme_ls_cr_conn_acc *acc =
+ (struct fcnvme_ls_cr_conn_acc *)iod->rspbuf;
+ struct nvmet_fc_tgt_queue *queue;
+ int ret = 0;
+
+ memset(acc, 0, sizeof(*acc));
+
+ if (iod->rqstdatalen < sizeof(struct fcnvme_ls_cr_conn_rqst))
+ ret = VERR_CR_CONN_LEN;
+ else if (rqst->desc_list_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_cr_conn_rqst)))
+ ret = VERR_CR_CONN_RQST_LEN;
+ else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
+ ret = VERR_ASSOC_ID;
+ else if (rqst->associd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id)))
+ ret = VERR_ASSOC_ID_LEN;
+ else if (rqst->connect_cmd.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_CREATE_CONN_CMD))
+ ret = VERR_CR_CONN_CMD;
+ else if (rqst->connect_cmd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_cr_conn_cmd)))
+ ret = VERR_CR_CONN_CMD_LEN;
+ else if (!rqst->connect_cmd.ersp_ratio ||
+ (be16_to_cpu(rqst->connect_cmd.ersp_ratio) >=
+ be16_to_cpu(rqst->connect_cmd.sqsize)))
+ ret = VERR_ERSP_RATIO;
+
+ else {
+ /* new io queue */
+ iod->assoc = nvmet_fc_find_target_assoc(tgtport,
+ be64_to_cpu(rqst->associd.association_id));
+ if (!iod->assoc)
+ ret = VERR_NO_ASSOC;
+ else {
+ queue = nvmet_fc_alloc_target_queue(iod->assoc,
+ be16_to_cpu(rqst->connect_cmd.qid),
+ be16_to_cpu(rqst->connect_cmd.sqsize));
+ if (!queue)
+ ret = VERR_QUEUE_ALLOC_FAIL;
+
+ /* release get taken in nvmet_fc_find_target_assoc */
+ nvmet_fc_tgt_a_put(iod->assoc);
+ }
+ }
+
+ if (ret) {
+ dev_err(tgtport->dev,
+ "Create Connection LS failed: %s\n",
+ validation_errors[ret]);
+ iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
+ NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
+ (ret == VERR_NO_ASSOC) ?
+ ELS_RJT_PROT : ELS_RJT_LOGIC,
+ ELS_EXPL_NONE, 0);
+ return;
+ }
+
+ queue->ersp_ratio = be16_to_cpu(rqst->connect_cmd.ersp_ratio);
+ atomic_set(&queue->connected, 1);
+ queue->sqhd = 0; /* best place to init value */
+
+ /* format a response */
+
+ iod->lsreq->rsplen = sizeof(*acc);
+
+ nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
+ fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_cr_conn_acc)),
+ FCNVME_LS_CREATE_CONNECTION);
+ acc->connectid.desc_tag = cpu_to_be32(FCNVME_LSDESC_CONN_ID);
+ acc->connectid.desc_len =
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_conn_id));
+ acc->connectid.connection_id =
+ cpu_to_be64(nvmet_fc_makeconnid(iod->assoc,
+ be16_to_cpu(rqst->connect_cmd.qid)));
+}
+
+static void
+nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ struct fcnvme_ls_disconnect_rqst *rqst =
+ (struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf;
+ struct fcnvme_ls_disconnect_acc *acc =
+ (struct fcnvme_ls_disconnect_acc *)iod->rspbuf;
+ struct nvmet_fc_tgt_queue *queue;
+ struct nvmet_fc_tgt_assoc *assoc;
+ int ret = 0;
+ bool del_assoc = false;
+
+ memset(acc, 0, sizeof(*acc));
+
+ if (iod->rqstdatalen < sizeof(struct fcnvme_ls_disconnect_rqst))
+ ret = VERR_DISCONN_LEN;
+ else if (rqst->desc_list_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_disconnect_rqst)))
+ ret = VERR_DISCONN_RQST_LEN;
+ else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
+ ret = VERR_ASSOC_ID;
+ else if (rqst->associd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_assoc_id)))
+ ret = VERR_ASSOC_ID_LEN;
+ else if (rqst->discon_cmd.desc_tag !=
+ cpu_to_be32(FCNVME_LSDESC_DISCONN_CMD))
+ ret = VERR_DISCONN_CMD;
+ else if (rqst->discon_cmd.desc_len !=
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_lsdesc_disconn_cmd)))
+ ret = VERR_DISCONN_CMD_LEN;
+ else if ((rqst->discon_cmd.scope != FCNVME_DISCONN_ASSOCIATION) &&
+ (rqst->discon_cmd.scope != FCNVME_DISCONN_CONNECTION))
+ ret = VERR_DISCONN_SCOPE;
+ else {
+ /* match an active association */
+ assoc = nvmet_fc_find_target_assoc(tgtport,
+ be64_to_cpu(rqst->associd.association_id));
+ iod->assoc = assoc;
+ if (!assoc)
+ ret = VERR_NO_ASSOC;
+ }
+
+ if (ret) {
+ dev_err(tgtport->dev,
+ "Disconnect LS failed: %s\n",
+ validation_errors[ret]);
+ iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
+ NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
+ (ret == 8) ? ELS_RJT_PROT : ELS_RJT_LOGIC,
+ ELS_EXPL_NONE, 0);
+ return;
+ }
+
+ /* format a response */
+
+ iod->lsreq->rsplen = sizeof(*acc);
+
+ nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
+ fcnvme_lsdesc_len(
+ sizeof(struct fcnvme_ls_disconnect_acc)),
+ FCNVME_LS_DISCONNECT);
+
+
+ if (rqst->discon_cmd.scope == FCNVME_DISCONN_CONNECTION) {
+ queue = nvmet_fc_find_target_queue(tgtport,
+ be64_to_cpu(rqst->discon_cmd.id));
+ if (queue) {
+ int qid = queue->qid;
+
+ nvmet_fc_delete_target_queue(queue);
+
+ /* release the get taken by find_target_queue */
+ nvmet_fc_tgt_q_put(queue);
+
+ /* tear association down if io queue terminated */
+ if (!qid)
+ del_assoc = true;
+ }
+ }
+
+ /* release get taken in nvmet_fc_find_target_assoc */
+ nvmet_fc_tgt_a_put(iod->assoc);
+
+ if (del_assoc)
+ nvmet_fc_delete_target_assoc(iod->assoc);
+}
+
+
+/* *********************** NVME Ctrl Routines **************************** */
+
+
+static void nvmet_fc_fcp_nvme_cmd_done(struct nvmet_req *nvme_req);
+
+static struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops;
+
+static void
+nvmet_fc_xmt_ls_rsp_done(struct nvmefc_tgt_ls_req *lsreq)
+{
+ struct nvmet_fc_ls_iod *iod = lsreq->nvmet_fc_private;
+ struct nvmet_fc_tgtport *tgtport = iod->tgtport;
+
+ fc_dma_sync_single_for_cpu(tgtport->dev, iod->rspdma,
+ NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
+ nvmet_fc_free_ls_iod(tgtport, iod);
+ nvmet_fc_tgtport_put(tgtport);
+}
+
+static void
+nvmet_fc_xmt_ls_rsp(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ int ret;
+
+ fc_dma_sync_single_for_device(tgtport->dev, iod->rspdma,
+ NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
+
+ ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsreq);
+ if (ret)
+ nvmet_fc_xmt_ls_rsp_done(iod->lsreq);
+}
+
+/*
+ * Actual processing routine for received FC-NVME LS Requests from the LLD
+ */
+static void
+nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_ls_iod *iod)
+{
+ struct fcnvme_ls_rqst_w0 *w0 =
+ (struct fcnvme_ls_rqst_w0 *)iod->rqstbuf;
+
+ iod->lsreq->nvmet_fc_private = iod;
+ iod->lsreq->rspbuf = iod->rspbuf;
+ iod->lsreq->rspdma = iod->rspdma;
+ iod->lsreq->done = nvmet_fc_xmt_ls_rsp_done;
+ /* Be preventative. handlers will later set to valid length */
+ iod->lsreq->rsplen = 0;
+
+ iod->assoc = NULL;
+
+ /*
+ * handlers:
+ * parse request input, execute the request, and format the
+ * LS response
+ */
+ switch (w0->ls_cmd) {
+ case FCNVME_LS_CREATE_ASSOCIATION:
+ /* Creates Association and initial Admin Queue/Connection */
+ nvmet_fc_ls_create_association(tgtport, iod);
+ break;
+ case FCNVME_LS_CREATE_CONNECTION:
+ /* Creates an IO Queue/Connection */
+ nvmet_fc_ls_create_connection(tgtport, iod);
+ break;
+ case FCNVME_LS_DISCONNECT:
+ /* Terminate a Queue/Connection or the Association */
+ nvmet_fc_ls_disconnect(tgtport, iod);
+ break;
+ default:
+ iod->lsreq->rsplen = nvmet_fc_format_rjt(iod->rspbuf,
+ NVME_FC_MAX_LS_BUFFER_SIZE, w0->ls_cmd,
+ ELS_RJT_INVAL, ELS_EXPL_NONE, 0);
+ }
+
+ nvmet_fc_xmt_ls_rsp(tgtport, iod);
+}
+
+/*
+ * Actual processing routine for received FC-NVME LS Requests from the LLD
+ */
+static void
+nvmet_fc_handle_ls_rqst_work(struct work_struct *work)
+{
+ struct nvmet_fc_ls_iod *iod =
+ container_of(work, struct nvmet_fc_ls_iod, work);
+ struct nvmet_fc_tgtport *tgtport = iod->tgtport;
+
+ nvmet_fc_handle_ls_rqst(tgtport, iod);
+}
+
+
+/**
+ * nvmet_fc_rcv_ls_req - transport entry point called by an LLDD
+ * upon the reception of a NVME LS request.
+ *
+ * The nvmet-fc layer will copy payload to an internal structure for
+ * processing. As such, upon completion of the routine, the LLDD may
+ * immediately free/reuse the LS request buffer passed in the call.
+ *
+ * If this routine returns error, the LLDD should abort the exchange.
+ *
+ * @tgtport: pointer to the (registered) target port the LS was
+ * received on.
+ * @lsreq: pointer to a lsreq request structure to be used to reference
+ * the exchange corresponding to the LS.
+ * @lsreqbuf: pointer to the buffer containing the LS Request
+ * @lsreqbuf_len: length, in bytes, of the received LS request
+ */
+int
+nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port,
+ struct nvmefc_tgt_ls_req *lsreq,
+ void *lsreqbuf, u32 lsreqbuf_len)
+{
+ struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
+ struct nvmet_fc_ls_iod *iod;
+
+ if (lsreqbuf_len > NVME_FC_MAX_LS_BUFFER_SIZE)
+ return -E2BIG;
+
+ if (!nvmet_fc_tgtport_get(tgtport))
+ return -ESHUTDOWN;
+
+ iod = nvmet_fc_alloc_ls_iod(tgtport);
+ if (!iod) {
+ nvmet_fc_tgtport_put(tgtport);
+ return -ENOENT;
+ }
+
+ iod->lsreq = lsreq;
+ iod->fcpreq = NULL;
+ memcpy(iod->rqstbuf, lsreqbuf, lsreqbuf_len);
+ iod->rqstdatalen = lsreqbuf_len;
+
+ schedule_work(&iod->work);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmet_fc_rcv_ls_req);
+
+
+/*
+ * **********************
+ * Start of FCP handling
+ * **********************
+ */
+
+static int
+nvmet_fc_alloc_tgt_pgs(struct nvmet_fc_fcp_iod *fod)
+{
+ struct scatterlist *sg;
+ struct page *page;
+ unsigned int nent;
+ u32 page_len, length;
+ int i = 0;
+
+ length = fod->total_length;
+ nent = DIV_ROUND_UP(length, PAGE_SIZE);
+ sg = kmalloc_array(nent, sizeof(struct scatterlist), GFP_KERNEL);
+ if (!sg)
+ goto out;
+
+ sg_init_table(sg, nent);
+
+ while (length) {
+ page_len = min_t(u32, length, PAGE_SIZE);
+
+ page = alloc_page(GFP_KERNEL);
+ if (!page)
+ goto out_free_pages;
+
+ sg_set_page(&sg[i], page, page_len, 0);
+ length -= page_len;
+ i++;
+ }
+
+ fod->data_sg = sg;
+ fod->data_sg_cnt = nent;
+ fod->data_sg_cnt = fc_dma_map_sg(fod->tgtport->dev, sg, nent,
+ ((fod->io_dir == NVMET_FCP_WRITE) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE));
+ /* note: write from initiator perspective */
+
+ return 0;
+
+out_free_pages:
+ while (i > 0) {
+ i--;
+ __free_page(sg_page(&sg[i]));
+ }
+ kfree(sg);
+ fod->data_sg = NULL;
+ fod->data_sg_cnt = 0;
+out:
+ return NVME_SC_INTERNAL;
+}
+
+static void
+nvmet_fc_free_tgt_pgs(struct nvmet_fc_fcp_iod *fod)
+{
+ struct scatterlist *sg;
+ int count;
+
+ if (!fod->data_sg || !fod->data_sg_cnt)
+ return;
+
+ fc_dma_unmap_sg(fod->tgtport->dev, fod->data_sg, fod->data_sg_cnt,
+ ((fod->io_dir == NVMET_FCP_WRITE) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE));
+ for_each_sg(fod->data_sg, sg, fod->data_sg_cnt, count)
+ __free_page(sg_page(sg));
+ kfree(fod->data_sg);
+}
+
+
+static bool
+queue_90percent_full(struct nvmet_fc_tgt_queue *q, u32 sqhd)
+{
+ u32 sqtail, used;
+
+ /* egad, this is ugly. And sqtail is just a best guess */
+ sqtail = atomic_read(&q->sqtail) % q->sqsize;
+
+ used = (sqtail < sqhd) ? (sqtail + q->sqsize - sqhd) : (sqtail - sqhd);
+ return ((used * 10) >= (((u32)(q->sqsize - 1) * 9)));
+}
+
+/*
+ * Prep RSP payload.
+ * May be a NVMET_FCOP_RSP or NVMET_FCOP_READDATA_RSP op
+ */
+static void
+nvmet_fc_prep_fcp_rsp(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_fcp_iod *fod)
+{
+ struct nvme_fc_ersp_iu *ersp = &fod->rspiubuf;
+ struct nvme_common_command *sqe = &fod->cmdiubuf.sqe.common;
+ struct nvme_completion *cqe = &ersp->cqe;
+ u32 *cqewd = (u32 *)cqe;
+ bool send_ersp = false;
+ u32 rsn, rspcnt, xfr_length;
+
+ if (fod->fcpreq->op == NVMET_FCOP_READDATA_RSP)
+ xfr_length = fod->total_length;
+ else
+ xfr_length = fod->offset;
+
+ /*
+ * check to see if we can send a 0's rsp.
+ * Note: to send a 0's response, the NVME-FC host transport will
+ * recreate the CQE. The host transport knows: sq id, SQHD (last
+ * seen in an ersp), and command_id. Thus it will create a
+ * zero-filled CQE with those known fields filled in. Transport
+ * must send an ersp for any condition where the cqe won't match
+ * this.
+ *
+ * Here are the FC-NVME mandated cases where we must send an ersp:
+ * every N responses, where N=ersp_ratio
+ * force fabric commands to send ersp's (not in FC-NVME but good
+ * practice)
+ * normal cmds: any time status is non-zero, or status is zero
+ * but words 0 or 1 are non-zero.
+ * the SQ is 90% or more full
+ * the cmd is a fused command
+ * transferred data length not equal to cmd iu length
+ */
+ rspcnt = atomic_inc_return(&fod->queue->zrspcnt);
+ if (!(rspcnt % fod->queue->ersp_ratio) ||
+ sqe->opcode == nvme_fabrics_command ||
+ xfr_length != fod->total_length ||
+ (le16_to_cpu(cqe->status) & 0xFFFE) || cqewd[0] || cqewd[1] ||
+ (sqe->flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND)) ||
+ queue_90percent_full(fod->queue, cqe->sq_head))
+ send_ersp = true;
+
+ /* re-set the fields */
+ fod->fcpreq->rspaddr = ersp;
+ fod->fcpreq->rspdma = fod->rspdma;
+
+ if (!send_ersp) {
+ memset(ersp, 0, NVME_FC_SIZEOF_ZEROS_RSP);
+ fod->fcpreq->rsplen = NVME_FC_SIZEOF_ZEROS_RSP;
+ } else {
+ ersp->iu_len = cpu_to_be16(sizeof(*ersp)/sizeof(u32));
+ rsn = atomic_inc_return(&fod->queue->rsn);
+ ersp->rsn = cpu_to_be32(rsn);
+ ersp->xfrd_len = cpu_to_be32(xfr_length);
+ fod->fcpreq->rsplen = sizeof(*ersp);
+ }
+
+ fc_dma_sync_single_for_device(tgtport->dev, fod->rspdma,
+ sizeof(fod->rspiubuf), DMA_TO_DEVICE);
+}
+
+static void nvmet_fc_xmt_fcp_op_done(struct nvmefc_tgt_fcp_req *fcpreq);
+
+static void
+nvmet_fc_xmt_fcp_rsp(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_fcp_iod *fod)
+{
+ int ret;
+
+ fod->fcpreq->op = NVMET_FCOP_RSP;
+ fod->fcpreq->timeout = 0;
+
+ nvmet_fc_prep_fcp_rsp(tgtport, fod);
+
+ ret = tgtport->ops->fcp_op(&tgtport->fc_target_port, fod->fcpreq);
+ if (ret)
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+}
+
+static void
+nvmet_fc_transfer_fcp_data(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_fcp_iod *fod, u8 op)
+{
+ struct nvmefc_tgt_fcp_req *fcpreq = fod->fcpreq;
+ struct scatterlist *sg, *datasg;
+ u32 tlen, sg_off;
+ int ret;
+
+ fcpreq->op = op;
+ fcpreq->offset = fod->offset;
+ fcpreq->timeout = NVME_FC_TGTOP_TIMEOUT_SEC;
+ tlen = min_t(u32, (NVMET_FC_MAX_KB_PER_XFR * 1024),
+ (fod->total_length - fod->offset));
+ tlen = min_t(u32, tlen, NVME_FC_MAX_SEGMENTS * PAGE_SIZE);
+ tlen = min_t(u32, tlen, fod->tgtport->ops->max_sgl_segments
+ * PAGE_SIZE);
+ fcpreq->transfer_length = tlen;
+ fcpreq->transferred_length = 0;
+ fcpreq->fcp_error = 0;
+ fcpreq->rsplen = 0;
+
+ fcpreq->sg_cnt = 0;
+
+ datasg = fod->next_sg;
+ sg_off = fod->next_sg_offset;
+
+ for (sg = fcpreq->sg ; tlen; sg++) {
+ *sg = *datasg;
+ if (sg_off) {
+ sg->offset += sg_off;
+ sg->length -= sg_off;
+ sg->dma_address += sg_off;
+ sg_off = 0;
+ }
+ if (tlen < sg->length) {
+ sg->length = tlen;
+ fod->next_sg = datasg;
+ fod->next_sg_offset += tlen;
+ } else if (tlen == sg->length) {
+ fod->next_sg_offset = 0;
+ fod->next_sg = sg_next(datasg);
+ } else {
+ fod->next_sg_offset = 0;
+ datasg = sg_next(datasg);
+ }
+ tlen -= sg->length;
+ fcpreq->sg_cnt++;
+ }
+
+ /*
+ * If the last READDATA request: check if LLDD supports
+ * combined xfr with response.
+ */
+ if ((op == NVMET_FCOP_READDATA) &&
+ ((fod->offset + fcpreq->transfer_length) == fod->total_length) &&
+ (tgtport->ops->target_features & NVMET_FCTGTFEAT_READDATA_RSP)) {
+ fcpreq->op = NVMET_FCOP_READDATA_RSP;
+ nvmet_fc_prep_fcp_rsp(tgtport, fod);
+ }
+
+ ret = tgtport->ops->fcp_op(&tgtport->fc_target_port, fod->fcpreq);
+ if (ret) {
+ /*
+ * should be ok to set w/o lock as its in the thread of
+ * execution (not an async timer routine) and doesn't
+ * contend with any clearing action
+ */
+ fod->abort = true;
+
+ if (op == NVMET_FCOP_WRITEDATA)
+ nvmet_req_complete(&fod->req,
+ NVME_SC_FC_TRANSPORT_ERROR);
+ else /* NVMET_FCOP_READDATA or NVMET_FCOP_READDATA_RSP */ {
+ fcpreq->fcp_error = ret;
+ fcpreq->transferred_length = 0;
+ nvmet_fc_xmt_fcp_op_done(fod->fcpreq);
+ }
+ }
+}
+
+static void
+nvmet_fc_xmt_fcp_op_done(struct nvmefc_tgt_fcp_req *fcpreq)
+{
+ struct nvmet_fc_fcp_iod *fod = fcpreq->nvmet_fc_private;
+ struct nvmet_fc_tgtport *tgtport = fod->tgtport;
+ unsigned long flags;
+ bool abort;
+
+ spin_lock_irqsave(&fod->flock, flags);
+ abort = fod->abort;
+ spin_unlock_irqrestore(&fod->flock, flags);
+
+ /* if in the middle of an io and we need to tear down */
+ if (abort && fcpreq->op != NVMET_FCOP_ABORT) {
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+
+ if (fcpreq->fcp_error || abort)
+ nvmet_req_complete(&fod->req, fcpreq->fcp_error);
+
+ return;
+ }
+
+ switch (fcpreq->op) {
+
+ case NVMET_FCOP_WRITEDATA:
+ if (abort || fcpreq->fcp_error ||
+ fcpreq->transferred_length != fcpreq->transfer_length) {
+ nvmet_req_complete(&fod->req,
+ NVME_SC_FC_TRANSPORT_ERROR);
+ return;
+ }
+
+ fod->offset += fcpreq->transferred_length;
+ if (fod->offset != fod->total_length) {
+ /* transfer the next chunk */
+ nvmet_fc_transfer_fcp_data(tgtport, fod,
+ NVMET_FCOP_WRITEDATA);
+ return;
+ }
+
+ /* data transfer complete, resume with nvmet layer */
+
+ fod->req.execute(&fod->req);
+
+ break;
+
+ case NVMET_FCOP_READDATA:
+ case NVMET_FCOP_READDATA_RSP:
+ if (abort || fcpreq->fcp_error ||
+ fcpreq->transferred_length != fcpreq->transfer_length) {
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+ return;
+ }
+
+ /* success */
+
+ if (fcpreq->op == NVMET_FCOP_READDATA_RSP) {
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+ fc_dma_sync_single_for_cpu(tgtport->dev, fod->rspdma,
+ sizeof(fod->rspiubuf), DMA_TO_DEVICE);
+ nvmet_fc_free_fcp_iod(fod->queue, fod);
+ return;
+ }
+
+ fod->offset += fcpreq->transferred_length;
+ if (fod->offset != fod->total_length) {
+ /* transfer the next chunk */
+ nvmet_fc_transfer_fcp_data(tgtport, fod,
+ NVMET_FCOP_READDATA);
+ return;
+ }
+
+ /* data transfer complete, send response */
+
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+
+ nvmet_fc_xmt_fcp_rsp(tgtport, fod);
+
+ break;
+
+ case NVMET_FCOP_RSP:
+ case NVMET_FCOP_ABORT:
+ fc_dma_sync_single_for_cpu(tgtport->dev, fod->rspdma,
+ sizeof(fod->rspiubuf), DMA_TO_DEVICE);
+ nvmet_fc_free_fcp_iod(fod->queue, fod);
+ break;
+
+ default:
+ nvmet_fc_free_tgt_pgs(fod);
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+ break;
+ }
+}
+
+/*
+ * actual completion handler after execution by the nvmet layer
+ */
+static void
+__nvmet_fc_fcp_nvme_cmd_done(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_fcp_iod *fod, int status)
+{
+ struct nvme_common_command *sqe = &fod->cmdiubuf.sqe.common;
+ struct nvme_completion *cqe = &fod->rspiubuf.cqe;
+ unsigned long flags;
+ bool abort;
+
+ spin_lock_irqsave(&fod->flock, flags);
+ abort = fod->abort;
+ spin_unlock_irqrestore(&fod->flock, flags);
+
+ /* if we have a CQE, snoop the last sq_head value */
+ if (!status)
+ fod->queue->sqhd = cqe->sq_head;
+
+ if (abort) {
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+ return;
+ }
+
+ /* if an error handling the cmd post initial parsing */
+ if (status) {
+ /* fudge up a failed CQE status for our transport error */
+ memset(cqe, 0, sizeof(*cqe));
+ cqe->sq_head = fod->queue->sqhd; /* echo last cqe sqhd */
+ cqe->sq_id = cpu_to_le16(fod->queue->qid);
+ cqe->command_id = sqe->command_id;
+ cqe->status = cpu_to_le16(status);
+ } else {
+
+ /*
+ * try to push the data even if the SQE status is non-zero.
+ * There may be a status where data still was intended to
+ * be moved
+ */
+ if ((fod->io_dir == NVMET_FCP_READ) && (fod->data_sg_cnt)) {
+ /* push the data over before sending rsp */
+ nvmet_fc_transfer_fcp_data(tgtport, fod,
+ NVMET_FCOP_READDATA);
+ return;
+ }
+
+ /* writes & no data - fall thru */
+ }
+
+ /* data no longer needed */
+ nvmet_fc_free_tgt_pgs(fod);
+
+ nvmet_fc_xmt_fcp_rsp(tgtport, fod);
+}
+
+
+static void
+nvmet_fc_fcp_nvme_cmd_done(struct nvmet_req *nvme_req)
+{
+ struct nvmet_fc_fcp_iod *fod = nvmet_req_to_fod(nvme_req);
+ struct nvmet_fc_tgtport *tgtport = fod->tgtport;
+
+ __nvmet_fc_fcp_nvme_cmd_done(tgtport, fod, 0);
+}
+
+
+/*
+ * Actual processing routine for received FC-NVME LS Requests from the LLD
+ */
+void
+nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
+ struct nvmet_fc_fcp_iod *fod)
+{
+ struct nvme_fc_cmd_iu *cmdiu = &fod->cmdiubuf;
+ int ret;
+
+ /*
+ * Fused commands are currently not supported in the linux
+ * implementation.
+ *
+ * As such, the implementation of the FC transport does not
+ * look at the fused commands and order delivery to the upper
+ * layer until we have both based on csn.
+ */
+
+ fod->fcpreq->done = nvmet_fc_xmt_fcp_op_done;
+
+ fod->total_length = be32_to_cpu(cmdiu->data_len);
+ if (cmdiu->flags & FCNVME_CMD_FLAGS_WRITE) {
+ fod->io_dir = NVMET_FCP_WRITE;
+ if (!nvme_is_write(&cmdiu->sqe))
+ goto transport_error;
+ } else if (cmdiu->flags & FCNVME_CMD_FLAGS_READ) {
+ fod->io_dir = NVMET_FCP_READ;
+ if (nvme_is_write(&cmdiu->sqe))
+ goto transport_error;
+ } else {
+ fod->io_dir = NVMET_FCP_NODATA;
+ if (fod->total_length)
+ goto transport_error;
+ }
+
+ fod->req.cmd = &fod->cmdiubuf.sqe;
+ fod->req.rsp = &fod->rspiubuf.cqe;
+ fod->req.port = fod->queue->port;
+
+ /* ensure nvmet handlers will set cmd handler callback */
+ fod->req.execute = NULL;
+
+ /* clear any response payload */
+ memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
+
+ ret = nvmet_req_init(&fod->req,
+ &fod->queue->nvme_cq,
+ &fod->queue->nvme_sq,
+ &nvmet_fc_tgt_fcp_ops);
+ if (!ret) { /* bad SQE content */
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+ return;
+ }
+
+ /* keep a running counter of tail position */
+ atomic_inc(&fod->queue->sqtail);
+
+ fod->data_sg = NULL;
+ fod->data_sg_cnt = 0;
+ if (fod->total_length) {
+ ret = nvmet_fc_alloc_tgt_pgs(fod);
+ if (ret) {
+ nvmet_req_complete(&fod->req, ret);
+ return;
+ }
+ }
+ fod->req.sg = fod->data_sg;
+ fod->req.sg_cnt = fod->data_sg_cnt;
+ fod->offset = 0;
+ fod->next_sg = fod->data_sg;
+ fod->next_sg_offset = 0;
+
+ if (fod->io_dir == NVMET_FCP_WRITE) {
+ /* pull the data over before invoking nvmet layer */
+ nvmet_fc_transfer_fcp_data(tgtport, fod, NVMET_FCOP_WRITEDATA);
+ return;
+ }
+
+ /*
+ * Reads or no data:
+ *
+ * can invoke the nvmet_layer now. If read data, cmd completion will
+ * push the data
+ */
+
+ fod->req.execute(&fod->req);
+
+ return;
+
+transport_error:
+ nvmet_fc_abort_op(tgtport, fod->fcpreq);
+}
+
+/*
+ * Actual processing routine for received FC-NVME LS Requests from the LLD
+ */
+static void
+nvmet_fc_handle_fcp_rqst_work(struct work_struct *work)
+{
+ struct nvmet_fc_fcp_iod *fod =
+ container_of(work, struct nvmet_fc_fcp_iod, work);
+ struct nvmet_fc_tgtport *tgtport = fod->tgtport;
+
+ nvmet_fc_handle_fcp_rqst(tgtport, fod);
+}
+
+/**
+ * nvmet_fc_rcv_fcp_req - transport entry point called by an LLDD
+ * upon the reception of a NVME FCP CMD IU.
+ *
+ * Pass a FC-NVME FCP CMD IU received from the FC link to the nvmet-fc
+ * layer for processing.
+ *
+ * The nvmet-fc layer will copy cmd payload to an internal structure for
+ * processing. As such, upon completion of the routine, the LLDD may
+ * immediately free/reuse the CMD IU buffer passed in the call.
+ *
+ * If this routine returns error, the lldd should abort the exchange.
+ *
+ * @target_port: pointer to the (registered) target port the FCP CMD IU
+ * was receive on.
+ * @fcpreq: pointer to a fcpreq request structure to be used to reference
+ * the exchange corresponding to the FCP Exchange.
+ * @cmdiubuf: pointer to the buffer containing the FCP CMD IU
+ * @cmdiubuf_len: length, in bytes, of the received FCP CMD IU
+ */
+int
+nvmet_fc_rcv_fcp_req(struct nvmet_fc_target_port *target_port,
+ struct nvmefc_tgt_fcp_req *fcpreq,
+ void *cmdiubuf, u32 cmdiubuf_len)
+{
+ struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
+ struct nvme_fc_cmd_iu *cmdiu = cmdiubuf;
+ struct nvmet_fc_tgt_queue *queue;
+ struct nvmet_fc_fcp_iod *fod;
+
+ /* validate iu, so the connection id can be used to find the queue */
+ if ((cmdiubuf_len != sizeof(*cmdiu)) ||
+ (cmdiu->scsi_id != NVME_CMD_SCSI_ID) ||
+ (cmdiu->fc_id != NVME_CMD_FC_ID) ||
+ (be16_to_cpu(cmdiu->iu_len) != (sizeof(*cmdiu)/4)))
+ return -EIO;
+
+
+ queue = nvmet_fc_find_target_queue(tgtport,
+ be64_to_cpu(cmdiu->connection_id));
+ if (!queue)
+ return -ENOTCONN;
+
+ /*
+ * note: reference taken by find_target_queue
+ * After successful fod allocation, the fod will inherit the
+ * ownership of that reference and will remove the reference
+ * when the fod is freed.
+ */
+
+ fod = nvmet_fc_alloc_fcp_iod(queue);
+ if (!fod) {
+ /* release the queue lookup reference */
+ nvmet_fc_tgt_q_put(queue);
+ return -ENOENT;
+ }
+
+ fcpreq->nvmet_fc_private = fod;
+ fod->fcpreq = fcpreq;
+ /*
+ * put all admin cmds on hw queue id 0. All io commands go to
+ * the respective hw queue based on a modulo basis
+ */
+ fcpreq->hwqid = queue->qid ?
+ ((queue->qid - 1) % tgtport->ops->max_hw_queues) : 0;
+ memcpy(&fod->cmdiubuf, cmdiubuf, cmdiubuf_len);
+
+ queue_work_on(queue->cpu, queue->work_q, &fod->work);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_req);
+
+enum {
+ FCT_TRADDR_ERR = 0,
+ FCT_TRADDR_WWNN = 1 << 0,
+ FCT_TRADDR_WWPN = 1 << 1,
+};
+
+struct nvmet_fc_traddr {
+ u64 nn;
+ u64 pn;
+};
+
+static const match_table_t traddr_opt_tokens = {
+ { FCT_TRADDR_WWNN, "nn-%s" },
+ { FCT_TRADDR_WWPN, "pn-%s" },
+ { FCT_TRADDR_ERR, NULL }
+};
+
+static int
+nvmet_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf)
+{
+ substring_t args[MAX_OPT_ARGS];
+ char *options, *o, *p;
+ int token, ret = 0;
+ u64 token64;
+
+ options = o = kstrdup(buf, GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ while ((p = strsep(&o, ",\n")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, traddr_opt_tokens, args);
+ switch (token) {
+ case FCT_TRADDR_WWNN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ traddr->nn = token64;
+ break;
+ case FCT_TRADDR_WWPN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ traddr->pn = token64;
+ break;
+ default:
+ pr_warn("unknown traddr token or missing value '%s'\n",
+ p);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+out:
+ kfree(options);
+ return ret;
+}
+
+static int
+nvmet_fc_add_port(struct nvmet_port *port)
+{
+ struct nvmet_fc_tgtport *tgtport;
+ struct nvmet_fc_traddr traddr = { 0L, 0L };
+ unsigned long flags;
+ int ret;
+
+ /* validate the address info */
+ if ((port->disc_addr.trtype != NVMF_TRTYPE_FC) ||
+ (port->disc_addr.adrfam != NVMF_ADDR_FAMILY_FC))
+ return -EINVAL;
+
+ /* map the traddr address info to a target port */
+
+ ret = nvmet_fc_parse_traddr(&traddr, port->disc_addr.traddr);
+ if (ret)
+ return ret;
+
+ ret = -ENXIO;
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ list_for_each_entry(tgtport, &nvmet_fc_target_list, tgt_list) {
+ if ((tgtport->fc_target_port.node_name == traddr.nn) &&
+ (tgtport->fc_target_port.port_name == traddr.pn)) {
+ /* a FC port can only be 1 nvmet port id */
+ if (!tgtport->port) {
+ tgtport->port = port;
+ port->priv = tgtport;
+ ret = 0;
+ } else
+ ret = -EALREADY;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+ return ret;
+}
+
+static void
+nvmet_fc_remove_port(struct nvmet_port *port)
+{
+ struct nvmet_fc_tgtport *tgtport = port->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
+ if (tgtport->port == port) {
+ nvmet_fc_tgtport_put(tgtport);
+ tgtport->port = NULL;
+ }
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+}
+
+static struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
+ .owner = THIS_MODULE,
+ .type = NVMF_TRTYPE_FC,
+ .msdbd = 1,
+ .add_port = nvmet_fc_add_port,
+ .remove_port = nvmet_fc_remove_port,
+ .queue_response = nvmet_fc_fcp_nvme_cmd_done,
+ .delete_ctrl = nvmet_fc_delete_ctrl,
+};
+
+static int __init nvmet_fc_init_module(void)
+{
+ return nvmet_register_transport(&nvmet_fc_tgt_fcp_ops);
+}
+
+static void __exit nvmet_fc_exit_module(void)
+{
+ /* sanity check - all lports should be removed */
+ if (!list_empty(&nvmet_fc_target_list))
+ pr_warn("%s: targetport list not empty\n", __func__);
+
+ nvmet_unregister_transport(&nvmet_fc_tgt_fcp_ops);
+
+ ida_destroy(&nvmet_fc_tgtport_cnt);
+}
+
+module_init(nvmet_fc_init_module);
+module_exit(nvmet_fc_exit_module);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
new file mode 100644
index 000000000000..bcb8ebeb01c5
--- /dev/null
+++ b/drivers/nvme/target/fcloop.c
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (c) 2016 Avago Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO
+ * THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
+ * See the GNU General Public License for more details, a copy of which
+ * can be found in the file COPYING included with this package
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <uapi/scsi/fc/fc_fs.h>
+
+#include "../host/nvme.h"
+#include "../target/nvmet.h"
+#include <linux/nvme-fc-driver.h>
+#include <linux/nvme-fc.h>
+
+
+enum {
+ NVMF_OPT_ERR = 0,
+ NVMF_OPT_WWNN = 1 << 0,
+ NVMF_OPT_WWPN = 1 << 1,
+ NVMF_OPT_ROLES = 1 << 2,
+ NVMF_OPT_FCADDR = 1 << 3,
+ NVMF_OPT_LPWWNN = 1 << 4,
+ NVMF_OPT_LPWWPN = 1 << 5,
+};
+
+struct fcloop_ctrl_options {
+ int mask;
+ u64 wwnn;
+ u64 wwpn;
+ u32 roles;
+ u32 fcaddr;
+ u64 lpwwnn;
+ u64 lpwwpn;
+};
+
+static const match_table_t opt_tokens = {
+ { NVMF_OPT_WWNN, "wwnn=%s" },
+ { NVMF_OPT_WWPN, "wwpn=%s" },
+ { NVMF_OPT_ROLES, "roles=%d" },
+ { NVMF_OPT_FCADDR, "fcaddr=%x" },
+ { NVMF_OPT_LPWWNN, "lpwwnn=%s" },
+ { NVMF_OPT_LPWWPN, "lpwwpn=%s" },
+ { NVMF_OPT_ERR, NULL }
+};
+
+static int
+fcloop_parse_options(struct fcloop_ctrl_options *opts,
+ const char *buf)
+{
+ substring_t args[MAX_OPT_ARGS];
+ char *options, *o, *p;
+ int token, ret = 0;
+ u64 token64;
+
+ options = o = kstrdup(buf, GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ while ((p = strsep(&o, ",\n")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, opt_tokens, args);
+ opts->mask |= token;
+ switch (token) {
+ case NVMF_OPT_WWNN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->wwnn = token64;
+ break;
+ case NVMF_OPT_WWPN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->wwpn = token64;
+ break;
+ case NVMF_OPT_ROLES:
+ if (match_int(args, &token)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->roles = token;
+ break;
+ case NVMF_OPT_FCADDR:
+ if (match_hex(args, &token)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->fcaddr = token;
+ break;
+ case NVMF_OPT_LPWWNN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->lpwwnn = token64;
+ break;
+ case NVMF_OPT_LPWWPN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ opts->lpwwpn = token64;
+ break;
+ default:
+ pr_warn("unknown parameter or missing value '%s'\n", p);
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ }
+
+out_free_options:
+ kfree(options);
+ return ret;
+}
+
+
+static int
+fcloop_parse_nm_options(struct device *dev, u64 *nname, u64 *pname,
+ const char *buf)
+{
+ substring_t args[MAX_OPT_ARGS];
+ char *options, *o, *p;
+ int token, ret = 0;
+ u64 token64;
+
+ *nname = -1;
+ *pname = -1;
+
+ options = o = kstrdup(buf, GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ while ((p = strsep(&o, ",\n")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, opt_tokens, args);
+ switch (token) {
+ case NVMF_OPT_WWNN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ *nname = token64;
+ break;
+ case NVMF_OPT_WWPN:
+ if (match_u64(args, &token64)) {
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ *pname = token64;
+ break;
+ default:
+ pr_warn("unknown parameter or missing value '%s'\n", p);
+ ret = -EINVAL;
+ goto out_free_options;
+ }
+ }
+
+out_free_options:
+ kfree(options);
+
+ if (!ret) {
+ if (*nname == -1)
+ return -EINVAL;
+ if (*pname == -1)
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+#define LPORT_OPTS (NVMF_OPT_WWNN | NVMF_OPT_WWPN)
+
+#define RPORT_OPTS (NVMF_OPT_WWNN | NVMF_OPT_WWPN | \
+ NVMF_OPT_LPWWNN | NVMF_OPT_LPWWPN)
+
+#define TGTPORT_OPTS (NVMF_OPT_WWNN | NVMF_OPT_WWPN)
+
+#define ALL_OPTS (NVMF_OPT_WWNN | NVMF_OPT_WWPN | NVMF_OPT_ROLES | \
+ NVMF_OPT_FCADDR | NVMF_OPT_LPWWNN | NVMF_OPT_LPWWPN)
+
+
+static DEFINE_SPINLOCK(fcloop_lock);
+static LIST_HEAD(fcloop_lports);
+static LIST_HEAD(fcloop_nports);
+
+struct fcloop_lport {
+ struct nvme_fc_local_port *localport;
+ struct list_head lport_list;
+ struct completion unreg_done;
+};
+
+struct fcloop_rport {
+ struct nvme_fc_remote_port *remoteport;
+ struct nvmet_fc_target_port *targetport;
+ struct fcloop_nport *nport;
+ struct fcloop_lport *lport;
+};
+
+struct fcloop_tport {
+ struct nvmet_fc_target_port *targetport;
+ struct nvme_fc_remote_port *remoteport;
+ struct fcloop_nport *nport;
+ struct fcloop_lport *lport;
+};
+
+struct fcloop_nport {
+ struct fcloop_rport *rport;
+ struct fcloop_tport *tport;
+ struct fcloop_lport *lport;
+ struct list_head nport_list;
+ struct kref ref;
+ struct completion rport_unreg_done;
+ struct completion tport_unreg_done;
+ u64 node_name;
+ u64 port_name;
+ u32 port_role;
+ u32 port_id;
+};
+
+struct fcloop_lsreq {
+ struct fcloop_tport *tport;
+ struct nvmefc_ls_req *lsreq;
+ struct work_struct work;
+ struct nvmefc_tgt_ls_req tgt_ls_req;
+ int status;
+};
+
+struct fcloop_fcpreq {
+ struct fcloop_tport *tport;
+ struct nvmefc_fcp_req *fcpreq;
+ u16 status;
+ struct work_struct work;
+ struct nvmefc_tgt_fcp_req tgt_fcp_req;
+};
+
+
+static inline struct fcloop_lsreq *
+tgt_ls_req_to_lsreq(struct nvmefc_tgt_ls_req *tgt_lsreq)
+{
+ return container_of(tgt_lsreq, struct fcloop_lsreq, tgt_ls_req);
+}
+
+static inline struct fcloop_fcpreq *
+tgt_fcp_req_to_fcpreq(struct nvmefc_tgt_fcp_req *tgt_fcpreq)
+{
+ return container_of(tgt_fcpreq, struct fcloop_fcpreq, tgt_fcp_req);
+}
+
+
+static int
+fcloop_create_queue(struct nvme_fc_local_port *localport,
+ unsigned int qidx, u16 qsize,
+ void **handle)
+{
+ *handle = localport;
+ return 0;
+}
+
+static void
+fcloop_delete_queue(struct nvme_fc_local_port *localport,
+ unsigned int idx, void *handle)
+{
+}
+
+
+/*
+ * Transmit of LS RSP done (e.g. buffers all set). call back up
+ * initiator "done" flows.
+ */
+static void
+fcloop_tgt_lsrqst_done_work(struct work_struct *work)
+{
+ struct fcloop_lsreq *tls_req =
+ container_of(work, struct fcloop_lsreq, work);
+ struct fcloop_tport *tport = tls_req->tport;
+ struct nvmefc_ls_req *lsreq = tls_req->lsreq;
+
+ if (tport->remoteport)
+ lsreq->done(lsreq, tls_req->status);
+}
+
+static int
+fcloop_ls_req(struct nvme_fc_local_port *localport,
+ struct nvme_fc_remote_port *remoteport,
+ struct nvmefc_ls_req *lsreq)
+{
+ struct fcloop_lsreq *tls_req = lsreq->private;
+ struct fcloop_rport *rport = remoteport->private;
+ int ret = 0;
+
+ tls_req->lsreq = lsreq;
+ INIT_WORK(&tls_req->work, fcloop_tgt_lsrqst_done_work);
+
+ if (!rport->targetport) {
+ tls_req->status = -ECONNREFUSED;
+ schedule_work(&tls_req->work);
+ return ret;
+ }
+
+ tls_req->status = 0;
+ tls_req->tport = rport->targetport->private;
+ ret = nvmet_fc_rcv_ls_req(rport->targetport, &tls_req->tgt_ls_req,
+ lsreq->rqstaddr, lsreq->rqstlen);
+
+ return ret;
+}
+
+static int
+fcloop_xmt_ls_rsp(struct nvmet_fc_target_port *tport,
+ struct nvmefc_tgt_ls_req *tgt_lsreq)
+{
+ struct fcloop_lsreq *tls_req = tgt_ls_req_to_lsreq(tgt_lsreq);
+ struct nvmefc_ls_req *lsreq = tls_req->lsreq;
+
+ memcpy(lsreq->rspaddr, tgt_lsreq->rspbuf,
+ ((lsreq->rsplen < tgt_lsreq->rsplen) ?
+ lsreq->rsplen : tgt_lsreq->rsplen));
+ tgt_lsreq->done(tgt_lsreq);
+
+ schedule_work(&tls_req->work);
+
+ return 0;
+}
+
+/*
+ * FCP IO operation done. call back up initiator "done" flows.
+ */
+static void
+fcloop_tgt_fcprqst_done_work(struct work_struct *work)
+{
+ struct fcloop_fcpreq *tfcp_req =
+ container_of(work, struct fcloop_fcpreq, work);
+ struct fcloop_tport *tport = tfcp_req->tport;
+ struct nvmefc_fcp_req *fcpreq = tfcp_req->fcpreq;
+
+ if (tport->remoteport) {
+ fcpreq->status = tfcp_req->status;
+ fcpreq->done(fcpreq);
+ }
+}
+
+
+static int
+fcloop_fcp_req(struct nvme_fc_local_port *localport,
+ struct nvme_fc_remote_port *remoteport,
+ void *hw_queue_handle,
+ struct nvmefc_fcp_req *fcpreq)
+{
+ struct fcloop_fcpreq *tfcp_req = fcpreq->private;
+ struct fcloop_rport *rport = remoteport->private;
+ int ret = 0;
+
+ INIT_WORK(&tfcp_req->work, fcloop_tgt_fcprqst_done_work);
+
+ if (!rport->targetport) {
+ tfcp_req->status = NVME_SC_FC_TRANSPORT_ERROR;
+ schedule_work(&tfcp_req->work);
+ return ret;
+ }
+
+ tfcp_req->fcpreq = fcpreq;
+ tfcp_req->tport = rport->targetport->private;
+
+ ret = nvmet_fc_rcv_fcp_req(rport->targetport, &tfcp_req->tgt_fcp_req,
+ fcpreq->cmdaddr, fcpreq->cmdlen);
+
+ return ret;
+}
+
+static void
+fcloop_fcp_copy_data(u8 op, struct scatterlist *data_sg,
+ struct scatterlist *io_sg, u32 offset, u32 length)
+{
+ void *data_p, *io_p;
+ u32 data_len, io_len, tlen;
+
+ io_p = sg_virt(io_sg);
+ io_len = io_sg->length;
+
+ for ( ; offset; ) {
+ tlen = min_t(u32, offset, io_len);
+ offset -= tlen;
+ io_len -= tlen;
+ if (!io_len) {
+ io_sg = sg_next(io_sg);
+ io_p = sg_virt(io_sg);
+ io_len = io_sg->length;
+ } else
+ io_p += tlen;
+ }
+
+ data_p = sg_virt(data_sg);
+ data_len = data_sg->length;
+
+ for ( ; length; ) {
+ tlen = min_t(u32, io_len, data_len);
+ tlen = min_t(u32, tlen, length);
+
+ if (op == NVMET_FCOP_WRITEDATA)
+ memcpy(data_p, io_p, tlen);
+ else
+ memcpy(io_p, data_p, tlen);
+
+ length -= tlen;
+
+ io_len -= tlen;
+ if ((!io_len) && (length)) {
+ io_sg = sg_next(io_sg);
+ io_p = sg_virt(io_sg);
+ io_len = io_sg->length;
+ } else
+ io_p += tlen;
+
+ data_len -= tlen;
+ if ((!data_len) && (length)) {
+ data_sg = sg_next(data_sg);
+ data_p = sg_virt(data_sg);
+ data_len = data_sg->length;
+ } else
+ data_p += tlen;
+ }
+}
+
+static int
+fcloop_fcp_op(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_tgt_fcp_req *tgt_fcpreq)
+{
+ struct fcloop_fcpreq *tfcp_req = tgt_fcp_req_to_fcpreq(tgt_fcpreq);
+ struct nvmefc_fcp_req *fcpreq = tfcp_req->fcpreq;
+ u32 rsplen = 0, xfrlen = 0;
+ int fcp_err = 0;
+ u8 op = tgt_fcpreq->op;
+
+ switch (op) {
+ case NVMET_FCOP_WRITEDATA:
+ xfrlen = tgt_fcpreq->transfer_length;
+ fcloop_fcp_copy_data(op, tgt_fcpreq->sg, fcpreq->first_sgl,
+ tgt_fcpreq->offset, xfrlen);
+ fcpreq->transferred_length += xfrlen;
+ break;
+
+ case NVMET_FCOP_READDATA:
+ case NVMET_FCOP_READDATA_RSP:
+ xfrlen = tgt_fcpreq->transfer_length;
+ fcloop_fcp_copy_data(op, tgt_fcpreq->sg, fcpreq->first_sgl,
+ tgt_fcpreq->offset, xfrlen);
+ fcpreq->transferred_length += xfrlen;
+ if (op == NVMET_FCOP_READDATA)
+ break;
+
+ /* Fall-Thru to RSP handling */
+
+ case NVMET_FCOP_RSP:
+ rsplen = ((fcpreq->rsplen < tgt_fcpreq->rsplen) ?
+ fcpreq->rsplen : tgt_fcpreq->rsplen);
+ memcpy(fcpreq->rspaddr, tgt_fcpreq->rspaddr, rsplen);
+ if (rsplen < tgt_fcpreq->rsplen)
+ fcp_err = -E2BIG;
+ fcpreq->rcv_rsplen = rsplen;
+ fcpreq->status = 0;
+ tfcp_req->status = 0;
+ break;
+
+ case NVMET_FCOP_ABORT:
+ tfcp_req->status = NVME_SC_FC_TRANSPORT_ABORTED;
+ break;
+
+ default:
+ fcp_err = -EINVAL;
+ break;
+ }
+
+ tgt_fcpreq->transferred_length = xfrlen;
+ tgt_fcpreq->fcp_error = fcp_err;
+ tgt_fcpreq->done(tgt_fcpreq);
+
+ if ((!fcp_err) && (op == NVMET_FCOP_RSP ||
+ op == NVMET_FCOP_READDATA_RSP ||
+ op == NVMET_FCOP_ABORT))
+ schedule_work(&tfcp_req->work);
+
+ return 0;
+}
+
+static void
+fcloop_ls_abort(struct nvme_fc_local_port *localport,
+ struct nvme_fc_remote_port *remoteport,
+ struct nvmefc_ls_req *lsreq)
+{
+}
+
+static void
+fcloop_fcp_abort(struct nvme_fc_local_port *localport,
+ struct nvme_fc_remote_port *remoteport,
+ void *hw_queue_handle,
+ struct nvmefc_fcp_req *fcpreq)
+{
+}
+
+static void
+fcloop_localport_delete(struct nvme_fc_local_port *localport)
+{
+ struct fcloop_lport *lport = localport->private;
+
+ /* release any threads waiting for the unreg to complete */
+ complete(&lport->unreg_done);
+}
+
+static void
+fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
+{
+ struct fcloop_rport *rport = remoteport->private;
+
+ /* release any threads waiting for the unreg to complete */
+ complete(&rport->nport->rport_unreg_done);
+}
+
+static void
+fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
+{
+ struct fcloop_tport *tport = targetport->private;
+
+ /* release any threads waiting for the unreg to complete */
+ complete(&tport->nport->tport_unreg_done);
+}
+
+#define FCLOOP_HW_QUEUES 4
+#define FCLOOP_SGL_SEGS 256
+#define FCLOOP_DMABOUND_4G 0xFFFFFFFF
+
+struct nvme_fc_port_template fctemplate = {
+ .localport_delete = fcloop_localport_delete,
+ .remoteport_delete = fcloop_remoteport_delete,
+ .create_queue = fcloop_create_queue,
+ .delete_queue = fcloop_delete_queue,
+ .ls_req = fcloop_ls_req,
+ .fcp_io = fcloop_fcp_req,
+ .ls_abort = fcloop_ls_abort,
+ .fcp_abort = fcloop_fcp_abort,
+ .max_hw_queues = FCLOOP_HW_QUEUES,
+ .max_sgl_segments = FCLOOP_SGL_SEGS,
+ .max_dif_sgl_segments = FCLOOP_SGL_SEGS,
+ .dma_boundary = FCLOOP_DMABOUND_4G,
+ /* sizes of additional private data for data structures */
+ .local_priv_sz = sizeof(struct fcloop_lport),
+ .remote_priv_sz = sizeof(struct fcloop_rport),
+ .lsrqst_priv_sz = sizeof(struct fcloop_lsreq),
+ .fcprqst_priv_sz = sizeof(struct fcloop_fcpreq),
+};
+
+struct nvmet_fc_target_template tgttemplate = {
+ .targetport_delete = fcloop_targetport_delete,
+ .xmt_ls_rsp = fcloop_xmt_ls_rsp,
+ .fcp_op = fcloop_fcp_op,
+ .max_hw_queues = FCLOOP_HW_QUEUES,
+ .max_sgl_segments = FCLOOP_SGL_SEGS,
+ .max_dif_sgl_segments = FCLOOP_SGL_SEGS,
+ .dma_boundary = FCLOOP_DMABOUND_4G,
+ /* optional features */
+ .target_features = NVMET_FCTGTFEAT_READDATA_RSP |
+ NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED,
+ /* sizes of additional private data for data structures */
+ .target_priv_sz = sizeof(struct fcloop_tport),
+};
+
+static ssize_t
+fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct nvme_fc_port_info pinfo;
+ struct fcloop_ctrl_options *opts;
+ struct nvme_fc_local_port *localport;
+ struct fcloop_lport *lport;
+ int ret;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return -ENOMEM;
+
+ ret = fcloop_parse_options(opts, buf);
+ if (ret)
+ goto out_free_opts;
+
+ /* everything there ? */
+ if ((opts->mask & LPORT_OPTS) != LPORT_OPTS) {
+ ret = -EINVAL;
+ goto out_free_opts;
+ }
+
+ pinfo.node_name = opts->wwnn;
+ pinfo.port_name = opts->wwpn;
+ pinfo.port_role = opts->roles;
+ pinfo.port_id = opts->fcaddr;
+
+ ret = nvme_fc_register_localport(&pinfo, &fctemplate, NULL, &localport);
+ if (!ret) {
+ unsigned long flags;
+
+ /* success */
+ lport = localport->private;
+ lport->localport = localport;
+ INIT_LIST_HEAD(&lport->lport_list);
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+ list_add_tail(&lport->lport_list, &fcloop_lports);
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ /* mark all of the input buffer consumed */
+ ret = count;
+ }
+
+out_free_opts:
+ kfree(opts);
+ return ret ? ret : count;
+}
+
+
+static void
+__unlink_local_port(struct fcloop_lport *lport)
+{
+ list_del(&lport->lport_list);
+}
+
+static int
+__wait_localport_unreg(struct fcloop_lport *lport)
+{
+ int ret;
+
+ init_completion(&lport->unreg_done);
+
+ ret = nvme_fc_unregister_localport(lport->localport);
+
+ wait_for_completion(&lport->unreg_done);
+
+ return ret;
+}
+
+
+static ssize_t
+fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcloop_lport *tlport, *lport = NULL;
+ u64 nodename, portname;
+ unsigned long flags;
+ int ret;
+
+ ret = fcloop_parse_nm_options(dev, &nodename, &portname, buf);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+
+ list_for_each_entry(tlport, &fcloop_lports, lport_list) {
+ if (tlport->localport->node_name == nodename &&
+ tlport->localport->port_name == portname) {
+ lport = tlport;
+ __unlink_local_port(lport);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ if (!lport)
+ return -ENOENT;
+
+ ret = __wait_localport_unreg(lport);
+
+ return ret ? ret : count;
+}
+
+static void
+fcloop_nport_free(struct kref *ref)
+{
+ struct fcloop_nport *nport =
+ container_of(ref, struct fcloop_nport, ref);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+ list_del(&nport->nport_list);
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ kfree(nport);
+}
+
+static void
+fcloop_nport_put(struct fcloop_nport *nport)
+{
+ kref_put(&nport->ref, fcloop_nport_free);
+}
+
+static int
+fcloop_nport_get(struct fcloop_nport *nport)
+{
+ return kref_get_unless_zero(&nport->ref);
+}
+
+static struct fcloop_nport *
+fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
+{
+ struct fcloop_nport *newnport, *nport = NULL;
+ struct fcloop_lport *tmplport, *lport = NULL;
+ struct fcloop_ctrl_options *opts;
+ unsigned long flags;
+ u32 opts_mask = (remoteport) ? RPORT_OPTS : TGTPORT_OPTS;
+ int ret;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return NULL;
+
+ ret = fcloop_parse_options(opts, buf);
+ if (ret)
+ goto out_free_opts;
+
+ /* everything there ? */
+ if ((opts->mask & opts_mask) != opts_mask) {
+ ret = -EINVAL;
+ goto out_free_opts;
+ }
+
+ newnport = kzalloc(sizeof(*newnport), GFP_KERNEL);
+ if (!newnport)
+ goto out_free_opts;
+
+ INIT_LIST_HEAD(&newnport->nport_list);
+ newnport->node_name = opts->wwnn;
+ newnport->port_name = opts->wwpn;
+ if (opts->mask & NVMF_OPT_ROLES)
+ newnport->port_role = opts->roles;
+ if (opts->mask & NVMF_OPT_FCADDR)
+ newnport->port_id = opts->fcaddr;
+ kref_init(&newnport->ref);
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+
+ list_for_each_entry(tmplport, &fcloop_lports, lport_list) {
+ if (tmplport->localport->node_name == opts->wwnn &&
+ tmplport->localport->port_name == opts->wwpn)
+ goto out_invalid_opts;
+
+ if (tmplport->localport->node_name == opts->lpwwnn &&
+ tmplport->localport->port_name == opts->lpwwpn)
+ lport = tmplport;
+ }
+
+ if (remoteport) {
+ if (!lport)
+ goto out_invalid_opts;
+ newnport->lport = lport;
+ }
+
+ list_for_each_entry(nport, &fcloop_nports, nport_list) {
+ if (nport->node_name == opts->wwnn &&
+ nport->port_name == opts->wwpn) {
+ if ((remoteport && nport->rport) ||
+ (!remoteport && nport->tport)) {
+ nport = NULL;
+ goto out_invalid_opts;
+ }
+
+ fcloop_nport_get(nport);
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ if (remoteport)
+ nport->lport = lport;
+ if (opts->mask & NVMF_OPT_ROLES)
+ nport->port_role = opts->roles;
+ if (opts->mask & NVMF_OPT_FCADDR)
+ nport->port_id = opts->fcaddr;
+ goto out_free_newnport;
+ }
+ }
+
+ list_add_tail(&newnport->nport_list, &fcloop_nports);
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ kfree(opts);
+ return newnport;
+
+out_invalid_opts:
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+out_free_newnport:
+ kfree(newnport);
+out_free_opts:
+ kfree(opts);
+ return nport;
+}
+
+static ssize_t
+fcloop_create_remote_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct nvme_fc_remote_port *remoteport;
+ struct fcloop_nport *nport;
+ struct fcloop_rport *rport;
+ struct nvme_fc_port_info pinfo;
+ int ret;
+
+ nport = fcloop_alloc_nport(buf, count, true);
+ if (!nport)
+ return -EIO;
+
+ pinfo.node_name = nport->node_name;
+ pinfo.port_name = nport->port_name;
+ pinfo.port_role = nport->port_role;
+ pinfo.port_id = nport->port_id;
+
+ ret = nvme_fc_register_remoteport(nport->lport->localport,
+ &pinfo, &remoteport);
+ if (ret || !remoteport) {
+ fcloop_nport_put(nport);
+ return ret;
+ }
+
+ /* success */
+ rport = remoteport->private;
+ rport->remoteport = remoteport;
+ rport->targetport = (nport->tport) ? nport->tport->targetport : NULL;
+ if (nport->tport) {
+ nport->tport->remoteport = remoteport;
+ nport->tport->lport = nport->lport;
+ }
+ rport->nport = nport;
+ rport->lport = nport->lport;
+ nport->rport = rport;
+
+ return ret ? ret : count;
+}
+
+
+static struct fcloop_rport *
+__unlink_remote_port(struct fcloop_nport *nport)
+{
+ struct fcloop_rport *rport = nport->rport;
+
+ if (rport && nport->tport)
+ nport->tport->remoteport = NULL;
+ nport->rport = NULL;
+
+ return rport;
+}
+
+static int
+__wait_remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
+{
+ int ret;
+
+ if (!rport)
+ return -EALREADY;
+
+ init_completion(&nport->rport_unreg_done);
+
+ ret = nvme_fc_unregister_remoteport(rport->remoteport);
+ if (ret)
+ return ret;
+
+ wait_for_completion(&nport->rport_unreg_done);
+
+ fcloop_nport_put(nport);
+
+ return ret;
+}
+
+static ssize_t
+fcloop_delete_remote_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcloop_nport *nport = NULL, *tmpport;
+ static struct fcloop_rport *rport;
+ u64 nodename, portname;
+ unsigned long flags;
+ int ret;
+
+ ret = fcloop_parse_nm_options(dev, &nodename, &portname, buf);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+
+ list_for_each_entry(tmpport, &fcloop_nports, nport_list) {
+ if (tmpport->node_name == nodename &&
+ tmpport->port_name == portname && tmpport->rport) {
+ nport = tmpport;
+ rport = __unlink_remote_port(nport);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ if (!nport)
+ return -ENOENT;
+
+ ret = __wait_remoteport_unreg(nport, rport);
+
+ return ret ? ret : count;
+}
+
+static ssize_t
+fcloop_create_target_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct nvmet_fc_target_port *targetport;
+ struct fcloop_nport *nport;
+ struct fcloop_tport *tport;
+ struct nvmet_fc_port_info tinfo;
+ int ret;
+
+ nport = fcloop_alloc_nport(buf, count, false);
+ if (!nport)
+ return -EIO;
+
+ tinfo.node_name = nport->node_name;
+ tinfo.port_name = nport->port_name;
+ tinfo.port_id = nport->port_id;
+
+ ret = nvmet_fc_register_targetport(&tinfo, &tgttemplate, NULL,
+ &targetport);
+ if (ret) {
+ fcloop_nport_put(nport);
+ return ret;
+ }
+
+ /* success */
+ tport = targetport->private;
+ tport->targetport = targetport;
+ tport->remoteport = (nport->rport) ? nport->rport->remoteport : NULL;
+ if (nport->rport)
+ nport->rport->targetport = targetport;
+ tport->nport = nport;
+ tport->lport = nport->lport;
+ nport->tport = tport;
+
+ return ret ? ret : count;
+}
+
+
+static struct fcloop_tport *
+__unlink_target_port(struct fcloop_nport *nport)
+{
+ struct fcloop_tport *tport = nport->tport;
+
+ if (tport && nport->rport)
+ nport->rport->targetport = NULL;
+ nport->tport = NULL;
+
+ return tport;
+}
+
+static int
+__wait_targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
+{
+ int ret;
+
+ if (!tport)
+ return -EALREADY;
+
+ init_completion(&nport->tport_unreg_done);
+
+ ret = nvmet_fc_unregister_targetport(tport->targetport);
+ if (ret)
+ return ret;
+
+ wait_for_completion(&nport->tport_unreg_done);
+
+ fcloop_nport_put(nport);
+
+ return ret;
+}
+
+static ssize_t
+fcloop_delete_target_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcloop_nport *nport = NULL, *tmpport;
+ struct fcloop_tport *tport;
+ u64 nodename, portname;
+ unsigned long flags;
+ int ret;
+
+ ret = fcloop_parse_nm_options(dev, &nodename, &portname, buf);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+
+ list_for_each_entry(tmpport, &fcloop_nports, nport_list) {
+ if (tmpport->node_name == nodename &&
+ tmpport->port_name == portname && tmpport->tport) {
+ nport = tmpport;
+ tport = __unlink_target_port(nport);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ if (!nport)
+ return -ENOENT;
+
+ ret = __wait_targetport_unreg(nport, tport);
+
+ return ret ? ret : count;
+}
+
+
+static DEVICE_ATTR(add_local_port, 0200, NULL, fcloop_create_local_port);
+static DEVICE_ATTR(del_local_port, 0200, NULL, fcloop_delete_local_port);
+static DEVICE_ATTR(add_remote_port, 0200, NULL, fcloop_create_remote_port);
+static DEVICE_ATTR(del_remote_port, 0200, NULL, fcloop_delete_remote_port);
+static DEVICE_ATTR(add_target_port, 0200, NULL, fcloop_create_target_port);
+static DEVICE_ATTR(del_target_port, 0200, NULL, fcloop_delete_target_port);
+
+static struct attribute *fcloop_dev_attrs[] = {
+ &dev_attr_add_local_port.attr,
+ &dev_attr_del_local_port.attr,
+ &dev_attr_add_remote_port.attr,
+ &dev_attr_del_remote_port.attr,
+ &dev_attr_add_target_port.attr,
+ &dev_attr_del_target_port.attr,
+ NULL
+};
+
+static struct attribute_group fclopp_dev_attrs_group = {
+ .attrs = fcloop_dev_attrs,
+};
+
+static const struct attribute_group *fcloop_dev_attr_groups[] = {
+ &fclopp_dev_attrs_group,
+ NULL,
+};
+
+static struct class *fcloop_class;
+static struct device *fcloop_device;
+
+
+static int __init fcloop_init(void)
+{
+ int ret;
+
+ fcloop_class = class_create(THIS_MODULE, "fcloop");
+ if (IS_ERR(fcloop_class)) {
+ pr_err("couldn't register class fcloop\n");
+ ret = PTR_ERR(fcloop_class);
+ return ret;
+ }
+
+ fcloop_device = device_create_with_groups(
+ fcloop_class, NULL, MKDEV(0, 0), NULL,
+ fcloop_dev_attr_groups, "ctl");
+ if (IS_ERR(fcloop_device)) {
+ pr_err("couldn't create ctl device!\n");
+ ret = PTR_ERR(fcloop_device);
+ goto out_destroy_class;
+ }
+
+ get_device(fcloop_device);
+
+ return 0;
+
+out_destroy_class:
+ class_destroy(fcloop_class);
+ return ret;
+}
+
+static void __exit fcloop_exit(void)
+{
+ struct fcloop_lport *lport;
+ struct fcloop_nport *nport;
+ struct fcloop_tport *tport;
+ struct fcloop_rport *rport;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+
+ for (;;) {
+ nport = list_first_entry_or_null(&fcloop_nports,
+ typeof(*nport), nport_list);
+ if (!nport)
+ break;
+
+ tport = __unlink_target_port(nport);
+ rport = __unlink_remote_port(nport);
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ ret = __wait_targetport_unreg(nport, tport);
+ if (ret)
+ pr_warn("%s: Failed deleting target port\n", __func__);
+
+ ret = __wait_remoteport_unreg(nport, rport);
+ if (ret)
+ pr_warn("%s: Failed deleting remote port\n", __func__);
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+ }
+
+ for (;;) {
+ lport = list_first_entry_or_null(&fcloop_lports,
+ typeof(*lport), lport_list);
+ if (!lport)
+ break;
+
+ __unlink_local_port(lport);
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ ret = __wait_localport_unreg(lport);
+ if (ret)
+ pr_warn("%s: Failed deleting local port\n", __func__);
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ put_device(fcloop_device);
+
+ device_destroy(fcloop_class, MKDEV(0, 0));
+ class_destroy(fcloop_class);
+}
+
+module_init(fcloop_init);
+module_exit(fcloop_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvme/target/io-cmd.c b/drivers/nvme/target/io-cmd.c
index 4a96c2049b7b..4195115c7e54 100644
--- a/drivers/nvme/target/io-cmd.c
+++ b/drivers/nvme/target/io-cmd.c
@@ -37,9 +37,7 @@ static void nvmet_inline_bio_init(struct nvmet_req *req)
{
struct bio *bio = &req->inline_bio;
- bio_init(bio);
- bio->bi_max_vecs = NVMET_MAX_INLINE_BIOVEC;
- bio->bi_io_vec = req->inline_bvec;
+ bio_init(bio, req->inline_bvec, NVMET_MAX_INLINE_BIOVEC);
}
static void nvmet_execute_rw(struct nvmet_req *req)
@@ -58,7 +56,7 @@ static void nvmet_execute_rw(struct nvmet_req *req)
if (req->cmd->rw.opcode == nvme_cmd_write) {
op = REQ_OP_WRITE;
- op_flags = WRITE_ODIRECT;
+ op_flags = REQ_SYNC | REQ_IDLE;
if (req->cmd->rw.control & cpu_to_le16(NVME_RW_FUA))
op_flags |= REQ_FUA;
} else {
@@ -96,7 +94,7 @@ static void nvmet_execute_rw(struct nvmet_req *req)
cookie = submit_bio(bio);
- blk_poll(bdev_get_queue(req->ns->bdev), cookie);
+ blk_mq_poll(bdev_get_queue(req->ns->bdev), cookie);
}
static void nvmet_execute_flush(struct nvmet_req *req)
@@ -109,7 +107,7 @@ static void nvmet_execute_flush(struct nvmet_req *req)
bio->bi_bdev = req->ns->bdev;
bio->bi_private = req;
bio->bi_end_io = nvmet_bio_done;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
submit_bio(bio);
}
@@ -172,6 +170,32 @@ static void nvmet_execute_dsm(struct nvmet_req *req)
}
}
+static void nvmet_execute_write_zeroes(struct nvmet_req *req)
+{
+ struct nvme_write_zeroes_cmd *write_zeroes = &req->cmd->write_zeroes;
+ struct bio *bio = NULL;
+ u16 status = NVME_SC_SUCCESS;
+ sector_t sector;
+ sector_t nr_sector;
+
+ sector = le64_to_cpu(write_zeroes->slba) <<
+ (req->ns->blksize_shift - 9);
+ nr_sector = (((sector_t)le32_to_cpu(write_zeroes->length)) <<
+ (req->ns->blksize_shift - 9)) + 1;
+
+ if (__blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
+ GFP_KERNEL, &bio, true))
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+
+ if (bio) {
+ bio->bi_private = req;
+ bio->bi_end_io = nvmet_bio_done;
+ submit_bio(bio);
+ } else {
+ nvmet_req_complete(req, status);
+ }
+}
+
int nvmet_parse_io_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
@@ -209,6 +233,9 @@ int nvmet_parse_io_cmd(struct nvmet_req *req)
req->data_len = le32_to_cpu(cmd->dsm.nr + 1) *
sizeof(struct nvme_dsm_range);
return 0;
+ case nvme_cmd_write_zeroes:
+ req->execute = nvmet_execute_write_zeroes;
+ return 0;
default:
pr_err("nvmet: unhandled cmd %d\n", cmd->common.opcode);
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index d5df77d686b2..9aaa70071ae5 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -36,6 +36,7 @@
(NVME_LOOP_AQ_DEPTH - NVME_LOOP_NR_AEN_COMMANDS)
struct nvme_loop_iod {
+ struct nvme_request nvme_req;
struct nvme_command cmd;
struct nvme_completion rsp;
struct nvmet_req req;
@@ -112,10 +113,10 @@ static void nvme_loop_complete_rq(struct request *req)
blk_mq_end_request(req, error);
}
-static void nvme_loop_queue_response(struct nvmet_req *nvme_req)
+static void nvme_loop_queue_response(struct nvmet_req *req)
{
struct nvme_loop_iod *iod =
- container_of(nvme_req, struct nvme_loop_iod, req);
+ container_of(req, struct nvme_loop_iod, req);
struct nvme_completion *cqe = &iod->rsp;
/*
@@ -126,13 +127,13 @@ static void nvme_loop_queue_response(struct nvmet_req *nvme_req)
*/
if (unlikely(nvme_loop_queue_idx(iod->queue) == 0 &&
cqe->command_id >= NVME_LOOP_AQ_BLKMQ_DEPTH)) {
- nvme_complete_async_event(&iod->queue->ctrl->ctrl, cqe);
+ nvme_complete_async_event(&iod->queue->ctrl->ctrl, cqe->status,
+ &cqe->result);
} else {
- struct request *req = blk_mq_rq_from_pdu(iod);
+ struct request *rq = blk_mq_rq_from_pdu(iod);
- if (req->cmd_type == REQ_TYPE_DRV_PRIV && req->special)
- memcpy(req->special, cqe, sizeof(*cqe));
- blk_mq_complete_request(req, le16_to_cpu(cqe->status) >> 1);
+ iod->nvme_req.result = cqe->result;
+ blk_mq_complete_request(rq, le16_to_cpu(cqe->status) >> 1);
}
}
@@ -168,7 +169,7 @@ static int nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
int ret;
ret = nvme_setup_cmd(ns, req, &iod->cmd);
- if (ret)
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
return ret;
iod->cmd.common.flags |= NVME_CMD_SGL_METABUF;
@@ -178,26 +179,25 @@ static int nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
nvme_cleanup_cmd(req);
blk_mq_start_request(req);
nvme_loop_queue_response(&iod->req);
- return 0;
+ return BLK_MQ_RQ_QUEUE_OK;
}
if (blk_rq_bytes(req)) {
iod->sg_table.sgl = iod->first_sgl;
ret = sg_alloc_table_chained(&iod->sg_table,
- req->nr_phys_segments, iod->sg_table.sgl);
+ blk_rq_nr_phys_segments(req),
+ iod->sg_table.sgl);
if (ret)
return BLK_MQ_RQ_QUEUE_BUSY;
iod->req.sg = iod->sg_table.sgl;
iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
- BUG_ON(iod->req.sg_cnt > req->nr_phys_segments);
}
- iod->cmd.common.command_id = req->tag;
blk_mq_start_request(req);
schedule_work(&iod->work);
- return 0;
+ return BLK_MQ_RQ_QUEUE_OK;
}
static void nvme_loop_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 76b6eedccaf9..23d5eb1c944f 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -47,6 +47,7 @@ struct nvmet_ns {
loff_t size;
u8 nguid[16];
+ bool enabled;
struct nvmet_subsys *subsys;
const char *device_path;
@@ -61,11 +62,6 @@ static inline struct nvmet_ns *to_nvmet_ns(struct config_item *item)
return container_of(to_config_group(item), struct nvmet_ns, group);
}
-static inline bool nvmet_ns_enabled(struct nvmet_ns *ns)
-{
- return !list_empty_careful(&ns->dev_link);
-}
-
struct nvmet_cq {
u16 qid;
u16 size;
@@ -238,7 +234,7 @@ static inline void nvmet_set_status(struct nvmet_req *req, u16 status)
static inline void nvmet_set_result(struct nvmet_req *req, u32 result)
{
- req->rsp->result = cpu_to_le32(result);
+ req->rsp->result.u32 = cpu_to_le32(result);
}
/*
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 005ef5d17a19..3fbcdb7a583c 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -1045,8 +1045,10 @@ nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev,
}
ret = nvmet_sq_init(&queue->nvme_sq);
- if (ret)
+ if (ret) {
+ ret = NVME_RDMA_CM_NO_RSC;
goto out_free_queue;
+ }
ret = nvmet_rdma_parse_cm_connect_req(&event->param.conn, queue);
if (ret)
@@ -1116,6 +1118,7 @@ out_destroy_sq:
out_free_queue:
kfree(queue);
out_reject:
+ pr_debug("rejecting connect request with status code %d\n", ret);
nvmet_rdma_cm_reject(cm_id, ret);
return NULL;
}
@@ -1129,7 +1132,8 @@ static void nvmet_rdma_qp_event(struct ib_event *event, void *priv)
rdma_notify(queue->cm_id, event->event);
break;
default:
- pr_err("received unrecognized IB QP event %d\n", event->event);
+ pr_err("received IB QP event: %s (%d)\n",
+ ib_event_msg(event->event), event->event);
break;
}
}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index c89d5d231a0e..c9b5cac03b36 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1015,6 +1015,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *reg, *endp;
int l;
+ bool hotpluggable;
/* We are scanning "memory" nodes only */
if (type == NULL) {
@@ -1034,6 +1035,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
return 0;
endp = reg + (l / sizeof(__be32));
+ hotpluggable = of_get_flat_dt_prop(node, "hotpluggable", NULL);
pr_debug("memory scan node %s, reg size %d,\n", uname, l);
@@ -1049,6 +1051,13 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
(unsigned long long)size);
early_init_dt_add_memory_arch(base, size);
+
+ if (!hotpluggable)
+ continue;
+
+ if (early_init_dt_mark_hotplug_memory_arch(base, size))
+ pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
+ base, base + size);
}
return 0;
@@ -1146,6 +1155,11 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
memblock_add(base, size);
}
+int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size)
+{
+ return memblock_mark_hotplug(base, size);
+}
+
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
phys_addr_t size, bool nomap)
{
@@ -1168,6 +1182,11 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
WARN_ON(1);
}
+int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size)
+{
+ return -ENOSYS;
+}
+
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
phys_addr_t size, bool nomap)
{
diff --git a/drivers/oprofile/nmi_timer_int.c b/drivers/oprofile/nmi_timer_int.c
index 9559829fb234..e65a576e4032 100644
--- a/drivers/oprofile/nmi_timer_int.c
+++ b/drivers/oprofile/nmi_timer_int.c
@@ -59,25 +59,16 @@ static void nmi_timer_stop_cpu(int cpu)
perf_event_disable(event);
}
-static int nmi_timer_cpu_notifier(struct notifier_block *b, unsigned long action,
- void *data)
+static int nmi_timer_cpu_online(unsigned int cpu)
{
- int cpu = (unsigned long)data;
- switch (action) {
- case CPU_DOWN_FAILED:
- case CPU_ONLINE:
- nmi_timer_start_cpu(cpu);
- break;
- case CPU_DOWN_PREPARE:
- nmi_timer_stop_cpu(cpu);
- break;
- }
- return NOTIFY_DONE;
+ nmi_timer_start_cpu(cpu);
+ return 0;
+}
+static int nmi_timer_cpu_predown(unsigned int cpu)
+{
+ nmi_timer_stop_cpu(cpu);
+ return 0;
}
-
-static struct notifier_block nmi_timer_cpu_nb = {
- .notifier_call = nmi_timer_cpu_notifier
-};
static int nmi_timer_start(void)
{
@@ -103,13 +94,14 @@ static void nmi_timer_stop(void)
put_online_cpus();
}
+static enum cpuhp_state hp_online;
+
static void nmi_timer_shutdown(void)
{
struct perf_event *event;
int cpu;
- cpu_notifier_register_begin();
- __unregister_cpu_notifier(&nmi_timer_cpu_nb);
+ cpuhp_remove_state(hp_online);
for_each_possible_cpu(cpu) {
event = per_cpu(nmi_timer_events, cpu);
if (!event)
@@ -118,13 +110,11 @@ static void nmi_timer_shutdown(void)
per_cpu(nmi_timer_events, cpu) = NULL;
perf_event_release_kernel(event);
}
-
- cpu_notifier_register_done();
}
static int nmi_timer_setup(void)
{
- int cpu, err;
+ int err;
u64 period;
/* clock cycles per tick: */
@@ -132,24 +122,14 @@ static int nmi_timer_setup(void)
do_div(period, HZ);
nmi_timer_attr.sample_period = period;
- cpu_notifier_register_begin();
- err = __register_cpu_notifier(&nmi_timer_cpu_nb);
- if (err)
- goto out;
-
- /* can't attach events to offline cpus: */
- for_each_online_cpu(cpu) {
- err = nmi_timer_start_cpu(cpu);
- if (err) {
- cpu_notifier_register_done();
- nmi_timer_shutdown();
- return err;
- }
+ err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "oprofile/nmi:online",
+ nmi_timer_cpu_online, nmi_timer_cpu_predown);
+ if (err < 0) {
+ nmi_timer_shutdown();
+ return err;
}
-
-out:
- cpu_notifier_register_done();
- return err;
+ hp_online = err;
+ return 0;
}
int __init op_nmi_timer_init(struct oprofile_operations *ops)
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
index a6456b578269..1f38d0836751 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/host/pci-xgene-msi.c
@@ -360,16 +360,16 @@ static void xgene_msi_isr(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
+static enum cpuhp_state pci_xgene_online;
+
static int xgene_msi_remove(struct platform_device *pdev)
{
- int virq, i;
struct xgene_msi *msi = platform_get_drvdata(pdev);
- for (i = 0; i < NR_HW_IRQS; i++) {
- virq = msi->msi_groups[i].gic_irq;
- if (virq != 0)
- irq_set_chained_handler_and_data(virq, NULL, NULL);
- }
+ if (pci_xgene_online)
+ cpuhp_remove_state(pci_xgene_online);
+ cpuhp_remove_state(CPUHP_PCI_XGENE_DEAD);
+
kfree(msi->msi_groups);
kfree(msi->bitmap);
@@ -427,7 +427,7 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
return 0;
}
-static void xgene_msi_hwirq_free(unsigned int cpu)
+static int xgene_msi_hwirq_free(unsigned int cpu)
{
struct xgene_msi *msi = &xgene_msi_ctrl;
struct xgene_msi_group *msi_group;
@@ -441,33 +441,9 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
NULL);
}
+ return 0;
}
-static int xgene_msi_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- xgene_msi_hwirq_alloc(cpu);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- xgene_msi_hwirq_free(cpu);
- break;
- default:
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block xgene_msi_cpu_notifier = {
- .notifier_call = xgene_msi_cpu_callback,
-};
-
static const struct of_device_id xgene_msi_match_table[] = {
{.compatible = "apm,xgene1-msi"},
{},
@@ -478,7 +454,6 @@ static int xgene_msi_probe(struct platform_device *pdev)
struct resource *res;
int rc, irq_index;
struct xgene_msi *xgene_msi;
- unsigned int cpu;
int virt_msir;
u32 msi_val, msi_idx;
@@ -540,28 +515,22 @@ static int xgene_msi_probe(struct platform_device *pdev)
}
}
- cpu_notifier_register_begin();
-
- for_each_online_cpu(cpu)
- if (xgene_msi_hwirq_alloc(cpu)) {
- dev_err(&pdev->dev, "failed to register MSI handlers\n");
- cpu_notifier_register_done();
- goto error;
- }
-
- rc = __register_hotcpu_notifier(&xgene_msi_cpu_notifier);
- if (rc) {
- dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
- cpu_notifier_register_done();
- goto error;
- }
-
- cpu_notifier_register_done();
+ rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online",
+ xgene_msi_hwirq_alloc, NULL);
+ if (rc)
+ goto err_cpuhp;
+ pci_xgene_online = rc;
+ rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL,
+ xgene_msi_hwirq_free);
+ if (rc)
+ goto err_cpuhp;
dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");
return 0;
+err_cpuhp:
+ dev_err(&pdev->dev, "failed to add CPU MSI notifier\n");
error:
xgene_msi_remove(pdev);
return rc;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ad70507cfb56..dd27f73a45fc 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -551,14 +551,14 @@ error_attrs:
}
static struct msi_desc *
-msi_setup_entry(struct pci_dev *dev, int nvec, bool affinity)
+msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd)
{
struct cpumask *masks = NULL;
struct msi_desc *entry;
u16 control;
- if (affinity) {
- masks = irq_create_affinity_masks(dev->irq_affinity, nvec);
+ if (affd) {
+ masks = irq_create_affinity_masks(nvec, affd);
if (!masks)
pr_err("Unable to allocate affinity masks, ignoring\n");
}
@@ -618,7 +618,8 @@ static int msi_verify_entries(struct pci_dev *dev)
* an error, and a positive return value indicates the number of interrupts
* which could have been allocated.
*/
-static int msi_capability_init(struct pci_dev *dev, int nvec, bool affinity)
+static int msi_capability_init(struct pci_dev *dev, int nvec,
+ const struct irq_affinity *affd)
{
struct msi_desc *entry;
int ret;
@@ -626,7 +627,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, bool affinity)
pci_msi_set_enable(dev, 0); /* Disable MSI during set up */
- entry = msi_setup_entry(dev, nvec, affinity);
+ entry = msi_setup_entry(dev, nvec, affd);
if (!entry)
return -ENOMEM;
@@ -690,14 +691,14 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)
static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
struct msix_entry *entries, int nvec,
- bool affinity)
+ const struct irq_affinity *affd)
{
struct cpumask *curmsk, *masks = NULL;
struct msi_desc *entry;
int ret, i;
- if (affinity) {
- masks = irq_create_affinity_masks(dev->irq_affinity, nvec);
+ if (affd) {
+ masks = irq_create_affinity_masks(nvec, affd);
if (!masks)
pr_err("Unable to allocate affinity masks, ignoring\n");
}
@@ -753,14 +754,14 @@ static void msix_program_entries(struct pci_dev *dev,
* @dev: pointer to the pci_dev data structure of MSI-X device function
* @entries: pointer to an array of struct msix_entry entries
* @nvec: number of @entries
- * @affinity: flag to indicate cpu irq affinity mask should be set
+ * @affd: Optional pointer to enable automatic affinity assignement
*
* Setup the MSI-X capability structure of device function with a
* single MSI-X irq. A return of zero indicates the successful setup of
* requested MSI-X entries with allocated irqs or non-zero for otherwise.
**/
static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
- int nvec, bool affinity)
+ int nvec, const struct irq_affinity *affd)
{
int ret;
u16 control;
@@ -775,7 +776,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
if (!base)
return -ENOMEM;
- ret = msix_setup_entries(dev, base, entries, nvec, affinity);
+ ret = msix_setup_entries(dev, base, entries, nvec, affd);
if (ret)
return ret;
@@ -956,7 +957,7 @@ int pci_msix_vec_count(struct pci_dev *dev)
EXPORT_SYMBOL(pci_msix_vec_count);
static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
- int nvec, bool affinity)
+ int nvec, const struct irq_affinity *affd)
{
int nr_entries;
int i, j;
@@ -988,7 +989,7 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");
return -EINVAL;
}
- return msix_capability_init(dev, entries, nvec, affinity);
+ return msix_capability_init(dev, entries, nvec, affd);
}
/**
@@ -1008,7 +1009,7 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
**/
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
{
- return __pci_enable_msix(dev, entries, nvec, false);
+ return __pci_enable_msix(dev, entries, nvec, NULL);
}
EXPORT_SYMBOL(pci_enable_msix);
@@ -1059,9 +1060,8 @@ int pci_msi_enabled(void)
EXPORT_SYMBOL(pci_msi_enabled);
static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
- unsigned int flags)
+ const struct irq_affinity *affd)
{
- bool affinity = flags & PCI_IRQ_AFFINITY;
int nvec;
int rc;
@@ -1090,14 +1090,13 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
nvec = maxvec;
for (;;) {
- if (affinity) {
- nvec = irq_calc_affinity_vectors(dev->irq_affinity,
- nvec);
+ if (affd) {
+ nvec = irq_calc_affinity_vectors(nvec, affd);
if (nvec < minvec)
return -ENOSPC;
}
- rc = msi_capability_init(dev, nvec, affinity);
+ rc = msi_capability_init(dev, nvec, affd);
if (rc == 0)
return nvec;
@@ -1124,29 +1123,27 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
**/
int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
{
- return __pci_enable_msi_range(dev, minvec, maxvec, 0);
+ return __pci_enable_msi_range(dev, minvec, maxvec, NULL);
}
EXPORT_SYMBOL(pci_enable_msi_range);
static int __pci_enable_msix_range(struct pci_dev *dev,
- struct msix_entry *entries, int minvec, int maxvec,
- unsigned int flags)
+ struct msix_entry *entries, int minvec,
+ int maxvec, const struct irq_affinity *affd)
{
- bool affinity = flags & PCI_IRQ_AFFINITY;
int rc, nvec = maxvec;
if (maxvec < minvec)
return -ERANGE;
for (;;) {
- if (affinity) {
- nvec = irq_calc_affinity_vectors(dev->irq_affinity,
- nvec);
+ if (affd) {
+ nvec = irq_calc_affinity_vectors(nvec, affd);
if (nvec < minvec)
return -ENOSPC;
}
- rc = __pci_enable_msix(dev, entries, nvec, affinity);
+ rc = __pci_enable_msix(dev, entries, nvec, affd);
if (rc == 0)
return nvec;
@@ -1177,16 +1174,17 @@ static int __pci_enable_msix_range(struct pci_dev *dev,
int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
int minvec, int maxvec)
{
- return __pci_enable_msix_range(dev, entries, minvec, maxvec, 0);
+ return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL);
}
EXPORT_SYMBOL(pci_enable_msix_range);
/**
- * pci_alloc_irq_vectors - allocate multiple IRQs for a device
+ * pci_alloc_irq_vectors_affinity - allocate multiple IRQs for a device
* @dev: PCI device to operate on
* @min_vecs: minimum number of vectors required (must be >= 1)
* @max_vecs: maximum (desired) number of vectors
* @flags: flags or quirks for the allocation
+ * @affd: optional description of the affinity requirements
*
* Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI
* vectors if available, and fall back to a single legacy vector
@@ -1198,20 +1196,30 @@ EXPORT_SYMBOL(pci_enable_msix_range);
* To get the Linux IRQ number used for a vector that can be passed to
* request_irq() use the pci_irq_vector() helper.
*/
-int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
- unsigned int max_vecs, unsigned int flags)
+int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
+ unsigned int max_vecs, unsigned int flags,
+ const struct irq_affinity *affd)
{
+ static const struct irq_affinity msi_default_affd;
int vecs = -ENOSPC;
+ if (flags & PCI_IRQ_AFFINITY) {
+ if (!affd)
+ affd = &msi_default_affd;
+ } else {
+ if (WARN_ON(affd))
+ affd = NULL;
+ }
+
if (flags & PCI_IRQ_MSIX) {
vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
- flags);
+ affd);
if (vecs > 0)
return vecs;
}
if (flags & PCI_IRQ_MSI) {
- vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, flags);
+ vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
if (vecs > 0)
return vecs;
}
@@ -1224,7 +1232,7 @@ int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
return vecs;
}
-EXPORT_SYMBOL(pci_alloc_irq_vectors);
+EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
/**
* pci_free_irq_vectors - free previously allocated IRQs for a device
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index eb126b98ed8a..e50bbf826188 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -296,10 +296,11 @@ static int __init is_alive(u_short sock)
return 0;
}
-static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
- unsigned int ioaddr)
+static int add_pcc_socket(ulong base, int irq, ulong mapaddr,
+ unsigned int ioaddr)
{
pcc_socket_t *t = &socket[pcc_sockets];
+ int err;
/* add sockets */
t->ioaddr = ioaddr;
@@ -328,11 +329,16 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
t->socket.irq_mask = 0;
t->socket.pci_irq = 2 + pcc_sockets; /* XXX */
- request_irq(irq, pcc_interrupt, 0, "m32r-pcc", pcc_interrupt);
+ err = request_irq(irq, pcc_interrupt, 0, "m32r-pcc", pcc_interrupt);
+ if (err) {
+ if (t->base > 0)
+ release_region(t->base, 0x20);
+ return err;
+ }
pcc_sockets++;
- return;
+ return 0;
}
@@ -683,26 +689,29 @@ static int __init init_m32r_pcc(void)
return ret;
ret = platform_device_register(&pcc_device);
- if (ret){
- platform_driver_unregister(&pcc_driver);
- return ret;
- }
+ if (ret)
+ goto unreg_driv;
printk(KERN_INFO "m32r PCC probe:\n");
pcc_sockets = 0;
- add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE, 0x1000);
+ ret = add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE,
+ 0x1000);
+ if (ret)
+ goto unreg_dev;
#ifdef CONFIG_M32RPCC_SLOT2
- add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE, 0x2000);
+ ret = add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE,
+ 0x2000);
+ if (ret)
+ goto unreg_dev;
#endif
if (pcc_sockets == 0) {
printk("socket is not found.\n");
- platform_device_unregister(&pcc_device);
- platform_driver_unregister(&pcc_driver);
- return -ENODEV;
+ ret = -ENODEV;
+ goto unreg_dev;
}
/* Set up interrupt handler(s) */
@@ -728,6 +737,12 @@ static int __init init_m32r_pcc(void)
}
return 0;
+
+unreg_dev:
+ platform_device_unregister(&pcc_device);
+unreg_driv:
+ platform_driver_unregister(&pcc_driver);
+ return ret;
} /* init_m32r_pcc */
static void __exit exit_m32r_pcc(void)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0e75d94972ba..54044a8ecbd7 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -93,6 +93,15 @@ config PINCTRL_AMD
Requires ACPI/FDT device enumeration code to set up a platform
device.
+config PINCTRL_DA850_PUPD
+ tristate "TI DA850/OMAP-L138/AM18XX pullup/pulldown groups"
+ depends on OF && (ARCH_DAVINCI_DA850 || COMPILE_TEST)
+ select PINCONF
+ select GENERIC_PINCONF
+ help
+ Driver for TI DA850/OMAP-L138/AM18XX pinconf. Used to control
+ pullup/pulldown pin groups.
+
config PINCTRL_DIGICOLOR
bool
depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST)
@@ -164,6 +173,21 @@ config PINCTRL_SIRF
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
+config PINCTRL_SX150X
+ bool "Semtech SX150x I2C GPIO expander pinctrl driver"
+ depends on GPIOLIB && I2C=y
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+ select GPIOLIB_IRQCHIP
+ select REGMAP
+ help
+ Say yes here to provide support for Semtech SX150x-series I2C
+ GPIO expanders as pinctrl module.
+ Compatible models include:
+ - 8 bits: sx1508q, sx1502q
+ - 16 bits: sx1509q, sx1506q
+
config PINCTRL_PISTACHIO
def_bool y if MACH_PISTACHIO
depends on GPIOLIB
@@ -209,7 +233,7 @@ config PINCTRL_COH901
config PINCTRL_MAX77620
tristate "MAX77620/MAX20024 Pincontrol support"
- depends on MFD_MAX77620
+ depends on MFD_MAX77620 && OF
select PINMUX
select GENERIC_PINCONF
help
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 11bad373dfe0..25d50a86981d 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,6 +14,7 @@ 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_DA850_PUPD) += pinctrl-da850-pupd.o
obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
+obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index 63246770bd74..8968dd7aebed 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -20,6 +20,7 @@ config PINCTRL_BCM2835
bool
select PINMUX
select PINCONF
+ select GPIOLIB_IRQCHIP
config PINCTRL_IPROC_GPIO
bool "Broadcom iProc GPIO (with PINCONF) driver"
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index fa77165fab2c..1bb38d0493eb 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -24,11 +24,9 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
-#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
-#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of.h>
@@ -47,6 +45,7 @@
#define MODULE_NAME "pinctrl-bcm2835"
#define BCM2835_NUM_GPIOS 54
#define BCM2835_NUM_BANKS 2
+#define BCM2835_NUM_IRQS 3
#define BCM2835_PIN_BITMAP_SZ \
DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
@@ -86,31 +85,23 @@ enum bcm2835_pinconf_pull {
#define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
#define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
-struct bcm2835_gpio_irqdata {
- struct bcm2835_pinctrl *pc;
- int bank;
-};
-
struct bcm2835_pinctrl {
struct device *dev;
void __iomem *base;
- int irq[BCM2835_NUM_BANKS];
+ int irq[BCM2835_NUM_IRQS];
/* note: locking assumes each bank will have its own unsigned long */
unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
unsigned int irq_type[BCM2835_NUM_GPIOS];
struct pinctrl_dev *pctl_dev;
- struct irq_domain *irq_domain;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
- struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_BANKS];
+ int irq_group[BCM2835_NUM_IRQS];
spinlock_t irq_lock[BCM2835_NUM_BANKS];
};
-static struct lock_class_key gpio_lock_class;
-
/* pins are just named GPIO0..GPIO53 */
#define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
@@ -368,13 +359,6 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
return pinctrl_gpio_direction_output(chip->base + offset);
}
-static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
-
- return irq_linear_revmap(pc->irq_domain, offset);
-}
-
static struct gpio_chip bcm2835_gpio_chip = {
.label = MODULE_NAME,
.owner = THIS_MODULE,
@@ -385,31 +369,67 @@ static struct gpio_chip bcm2835_gpio_chip = {
.get_direction = bcm2835_gpio_get_direction,
.get = bcm2835_gpio_get,
.set = bcm2835_gpio_set,
- .to_irq = bcm2835_gpio_to_irq,
.base = -1,
.ngpio = BCM2835_NUM_GPIOS,
.can_sleep = false,
};
-static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
+static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
+ unsigned int bank, u32 mask)
{
- struct bcm2835_gpio_irqdata *irqdata = dev_id;
- struct bcm2835_pinctrl *pc = irqdata->pc;
- int bank = irqdata->bank;
unsigned long events;
unsigned offset;
unsigned gpio;
unsigned int type;
events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+ events &= mask;
events &= pc->enabled_irq_map[bank];
for_each_set_bit(offset, &events, 32) {
gpio = (32 * bank) + offset;
+ /* FIXME: no clue why the code looks up the type here */
type = pc->irq_type[gpio];
- generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
+ generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
+ gpio));
}
- return events ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
+{
+ struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+ struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+ struct irq_chip *host_chip = irq_desc_get_chip(desc);
+ int irq = irq_desc_get_irq(desc);
+ int group;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pc->irq); i++) {
+ if (pc->irq[i] == irq) {
+ group = pc->irq_group[i];
+ break;
+ }
+ }
+ /* This should not happen, every IRQ has a bank */
+ if (i == ARRAY_SIZE(pc->irq))
+ BUG();
+
+ chained_irq_enter(host_chip, desc);
+
+ switch (group) {
+ case 0: /* IRQ0 covers GPIOs 0-27 */
+ bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
+ break;
+ case 1: /* IRQ1 covers GPIOs 28-45 */
+ bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
+ bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
+ break;
+ case 2: /* IRQ2 covers GPIOs 46-53 */
+ bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
+ break;
+ }
+
+ chained_irq_exit(host_chip, desc);
}
static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
@@ -455,7 +475,8 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
static void bcm2835_gpio_irq_enable(struct irq_data *data)
{
- struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+ struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
unsigned gpio = irqd_to_hwirq(data);
unsigned offset = GPIO_REG_SHIFT(gpio);
unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -469,7 +490,8 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
static void bcm2835_gpio_irq_disable(struct irq_data *data)
{
- struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+ struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
unsigned gpio = irqd_to_hwirq(data);
unsigned offset = GPIO_REG_SHIFT(gpio);
unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -575,7 +597,8 @@ static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
- struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+ struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
unsigned gpio = irqd_to_hwirq(data);
unsigned offset = GPIO_REG_SHIFT(gpio);
unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -601,7 +624,8 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
static void bcm2835_gpio_irq_ack(struct irq_data *data)
{
- struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+ struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
unsigned gpio = irqd_to_hwirq(data);
bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
@@ -644,10 +668,11 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
unsigned offset)
{
struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ struct gpio_chip *chip = &pc->gpio_chip;
enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
const char *fname = bcm2835_functions[fsel];
int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
- int irq = irq_find_mapping(pc->irq_domain, offset);
+ int irq = irq_find_mapping(chip->irqdomain, offset);
seq_printf(s, "function %s in %s; irq %d (%s)",
fname, value ? "hi" : "lo",
@@ -821,6 +846,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = {
.dt_free_map = bcm2835_pctl_dt_free_map,
};
+static int bcm2835_pmx_free(struct pinctrl_dev *pctldev,
+ unsigned offset)
+{
+ struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable by setting to GPIO_IN */
+ bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
+ return 0;
+}
+
static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev)
{
return BCM2835_FSEL_COUNT;
@@ -880,6 +915,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
}
static const struct pinmux_ops bcm2835_pmx_ops = {
+ .free = bcm2835_pmx_free,
.get_functions_count = bcm2835_pmx_get_functions_count,
.get_function_name = bcm2835_pmx_get_function_name,
.get_function_groups = bcm2835_pmx_get_function_groups,
@@ -917,12 +953,14 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
bcm2835_gpio_wr(pc, GPPUD, arg & 3);
/*
- * Docs say to wait 150 cycles, but not of what. We assume a
- * 1 MHz clock here, which is pretty slow...
+ * BCM2835 datasheet say to wait 150 cycles, but not of what.
+ * But the VideoCore firmware delay for this operation
+ * based nearly on the same amount of VPU cycles and this clock
+ * runs at 250 MHz.
*/
- udelay(150);
+ udelay(1);
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
- udelay(150);
+ udelay(1);
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
} /* for each config */
@@ -980,26 +1018,9 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
pc->gpio_chip.parent = dev;
pc->gpio_chip.of_node = np;
- pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
- &irq_domain_simple_ops, NULL);
- if (!pc->irq_domain) {
- dev_err(dev, "could not create IRQ domain\n");
- return -ENOMEM;
- }
-
- for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
- int irq = irq_create_mapping(pc->irq_domain, i);
- irq_set_lockdep_class(irq, &gpio_lock_class);
- irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
- handle_level_irq);
- irq_set_chip_data(irq, pc);
- }
-
for (i = 0; i < BCM2835_NUM_BANKS; i++) {
unsigned long events;
unsigned offset;
- int len;
- char *name;
/* clear event detection flags */
bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
@@ -1014,24 +1035,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
for_each_set_bit(offset, &events, 32)
bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
- pc->irq[i] = irq_of_parse_and_map(np, i);
- pc->irq_data[i].pc = pc;
- pc->irq_data[i].bank = i;
spin_lock_init(&pc->irq_lock[i]);
-
- len = strlen(dev_name(pc->dev)) + 16;
- name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
- if (!name)
- return -ENOMEM;
- snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
-
- err = devm_request_irq(dev, pc->irq[i],
- bcm2835_gpio_irq_handler, IRQF_SHARED,
- name, &pc->irq_data[i]);
- if (err) {
- dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
- return err;
- }
}
err = gpiochip_add_data(&pc->gpio_chip, pc);
@@ -1040,6 +1044,29 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
return err;
}
+ err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
+ 0, handle_level_irq, IRQ_TYPE_NONE);
+ if (err) {
+ dev_info(dev, "could not add irqchip\n");
+ return err;
+ }
+
+ for (i = 0; i < BCM2835_NUM_IRQS; i++) {
+ pc->irq[i] = irq_of_parse_and_map(np, i);
+ pc->irq_group[i] = i;
+ /*
+ * Use the same handler for all groups: this is necessary
+ * since we use one gpiochip to cover all lines - the
+ * irq handler then needs to figure out which group and
+ * bank that was firing the IRQ and look up the per-group
+ * and bank data.
+ */
+ gpiochip_set_chained_irqchip(&pc->gpio_chip,
+ &bcm2835_gpio_irq_chip,
+ pc->irq[i],
+ bcm2835_gpio_irq_handler);
+ }
+
pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
if (IS_ERR(pc->pctl_dev)) {
gpiochip_remove(&pc->gpio_chip);
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 54dad89fc9bf..260908480075 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -253,3 +253,147 @@ err:
pinctrl_dt_free_maps(p);
return ret;
}
+
+/*
+ * For pinctrl binding, typically #pinctrl-cells is for the pin controller
+ * device, so either parent or grandparent. See pinctrl-bindings.txt.
+ */
+static int pinctrl_find_cells_size(const struct device_node *np)
+{
+ const char *cells_name = "#pinctrl-cells";
+ int cells_size, error;
+
+ error = of_property_read_u32(np->parent, cells_name, &cells_size);
+ if (error) {
+ error = of_property_read_u32(np->parent->parent,
+ cells_name, &cells_size);
+ if (error)
+ return -ENOENT;
+ }
+
+ return cells_size;
+}
+
+/**
+ * pinctrl_get_list_and_count - Gets the list and it's cell size and number
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ * @list: pointer for the list found
+ * @cells_size: pointer for the cell size found
+ * @nr_elements: pointer for the number of elements found
+ *
+ * Typically np is a single pinctrl entry containing the list.
+ */
+static int pinctrl_get_list_and_count(const struct device_node *np,
+ const char *list_name,
+ const __be32 **list,
+ int *cells_size,
+ int *nr_elements)
+{
+ int size;
+
+ *cells_size = 0;
+ *nr_elements = 0;
+
+ *list = of_get_property(np, list_name, &size);
+ if (!*list)
+ return -ENOENT;
+
+ *cells_size = pinctrl_find_cells_size(np);
+ if (*cells_size < 0)
+ return -ENOENT;
+
+ /* First element is always the index within the pinctrl device */
+ *nr_elements = (size / sizeof(**list)) / (*cells_size + 1);
+
+ return 0;
+}
+
+/**
+ * pinctrl_count_index_with_args - Count number of elements in a pinctrl entry
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ *
+ * Counts the number of elements in a pinctrl array consisting of an index
+ * within the controller and a number of u32 entries specified for each
+ * entry. Note that device_node is always for the parent pin controller device.
+ */
+int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name)
+{
+ const __be32 *list;
+ int size, nr_cells, error;
+
+ error = pinctrl_get_list_and_count(np, list_name, &list,
+ &nr_cells, &size);
+ if (error)
+ return error;
+
+ return size;
+}
+EXPORT_SYMBOL_GPL(pinctrl_count_index_with_args);
+
+/**
+ * pinctrl_copy_args - Populates of_phandle_args based on index
+ * @np: pointer to device node with the property
+ * @list: pointer to a list with the elements
+ * @index: entry within the list of elements
+ * @nr_cells: number of cells in the list
+ * @nr_elem: number of elements for each entry in the list
+ * @out_args: returned values
+ *
+ * Populates the of_phandle_args based on the index in the list.
+ */
+static int pinctrl_copy_args(const struct device_node *np,
+ const __be32 *list,
+ int index, int nr_cells, int nr_elem,
+ struct of_phandle_args *out_args)
+{
+ int i;
+
+ memset(out_args, 0, sizeof(*out_args));
+ out_args->np = (struct device_node *)np;
+ out_args->args_count = nr_cells + 1;
+
+ if (index >= nr_elem)
+ return -EINVAL;
+
+ list += index * (nr_cells + 1);
+
+ for (i = 0; i < nr_cells + 1; i++)
+ out_args->args[i] = be32_to_cpup(list++);
+
+ return 0;
+}
+
+/**
+ * pinctrl_parse_index_with_args - Find a node pointed by index in a list
+ * @np: pointer to device node with the property
+ * @list_name: property that contains the list
+ * @index: index within the list
+ * @out_arts: entries in the list pointed by index
+ *
+ * Finds the selected element in a pinctrl array consisting of an index
+ * within the controller and a number of u32 entries specified for each
+ * entry. Note that device_node is always for the parent pin controller device.
+ */
+int pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args)
+{
+ const __be32 *list;
+ int nr_elem, nr_cells, error;
+
+ error = pinctrl_get_list_and_count(np, list_name, &list,
+ &nr_cells, &nr_elem);
+ if (error || !nr_cells)
+ return error;
+
+ error = pinctrl_copy_args(np, list, index, nr_cells, nr_elem,
+ out_args);
+ if (error)
+ return error;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pinctrl_parse_index_with_args);
diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h
index 760bc4960f58..c2d1a5505850 100644
--- a/drivers/pinctrl/devicetree.h
+++ b/drivers/pinctrl/devicetree.h
@@ -16,11 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+struct of_phandle_args;
+
#ifdef CONFIG_OF
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
+int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name);
+
+int pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args);
+
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
@@ -32,4 +41,18 @@ static inline void pinctrl_dt_free_maps(struct pinctrl *p)
{
}
+static inline int pinctrl_count_index_with_args(const struct device_node *np,
+ const char *list_name)
+{
+ return -ENODEV;
+}
+
+static inline int
+pinctrl_parse_index_with_args(const struct device_node *np,
+ const char *list_name, int index,
+ struct of_phandle_args *out_args)
+{
+ return -ENODEV;
+}
+
#endif
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 79c4e14a5a75..5ef7e875b50e 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -778,10 +778,10 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
- imx_pinctrl_desc->pctlops = &imx_pctrl_ops,
- imx_pinctrl_desc->pmxops = &imx_pmx_ops,
- imx_pinctrl_desc->confops = &imx_pinconf_ops,
- imx_pinctrl_desc->owner = THIS_MODULE,
+ imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
+ imx_pinctrl_desc->pmxops = &imx_pmx_ops;
+ imx_pinctrl_desc->confops = &imx_pinconf_ops;
+ imx_pinctrl_desc->owner = THIS_MODULE;
ret = imx_pinctrl_probe_dt(pdev, info);
if (ret) {
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 71bbeb9321ba..37300634b7d2 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1703,7 +1703,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
if (irq_rc && irq_rc->start) {
byt_gpio_irq_init_hw(vg);
ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
+ handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add irqchip\n");
goto fail;
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index c43b1e9a06af..5e66860a5e67 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -762,7 +762,7 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
seq_printf(s, "mode %d ", mode);
}
- seq_printf(s, "ctrl0 0x%08x ctrl1 0x%08x", ctrl0, ctrl1);
+ seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1);
if (locked)
seq_puts(s, " [LOCKED]");
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 01443762e570..1e139672f1af 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -911,7 +911,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
}
ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
+ handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "failed to add irqchip\n");
goto fail;
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 7826c7f0cb7c..b21896126f76 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -814,10 +814,51 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
+static int mrfld_config_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+
+ ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ ret = mrfld_config_get(pctldev, pins[0], config);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mrfld_config_group_set(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int i, ret;
+
+ ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = mrfld_config_set(pctldev, pins[i], configs, num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct pinconf_ops mrfld_pinconf_ops = {
.is_generic = true,
.pin_config_get = mrfld_config_get,
.pin_config_set = mrfld_config_set,
+ .pin_config_group_get = mrfld_config_group_get,
+ .pin_config_group_set = mrfld_config_group_set,
};
static const struct pinctrl_desc mrfld_pinctrl_desc = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
index 6eccb85c02cd..afcede7e2222 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
@@ -64,8 +64,4 @@ static struct platform_driver mtk_pinctrl_driver = {
},
};
-static int __init mtk_pinctrl_init(void)
-{
- return platform_driver_register(&mtk_pinctrl_driver);
-}
-device_initcall(mtk_pinctrl_init);
+builtin_platform_driver(mtk_pinctrl_driver);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
index 13e5b68bfe1b..9b018fdbeb51 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
@@ -201,7 +201,7 @@ static const struct mtk_desc_pin mtk_pins_mt8173[] = {
MTK_PIN(
PINCTRL_PIN(16, "IDDIG"),
NULL, "mt8173",
- MTK_EINT_FUNCTION(0, 16),
+ MTK_EINT_FUNCTION(1, 16),
MTK_FUNCTION(0, "GPIO16"),
MTK_FUNCTION(1, "IDDIG"),
MTK_FUNCTION(2, "CMFLASH"),
diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
index 24434f139947..27c5b5126008 100644
--- a/drivers/pinctrl/meson/Makefile
+++ b/drivers/pinctrl/meson/Makefile
@@ -1,2 +1,3 @@
-obj-y += pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o
+obj-y += pinctrl-meson8.o pinctrl-meson8b.o
+obj-y += pinctrl-meson-gxbb.o pinctrl-meson-gxl.o
obj-y += pinctrl-meson.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
new file mode 100644
index 000000000000..25694f7094c7
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
@@ -0,0 +1,589 @@
+/*
+ * Pin controller and GPIO driver for Amlogic Meson GXL.
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dt-bindings/gpio/meson-gxl-gpio.h>
+#include "pinctrl-meson.h"
+
+#define EE_OFF 10
+
+static const struct pinctrl_pin_desc meson_gxl_periphs_pins[] = {
+ MESON_PIN(GPIOZ_0, EE_OFF),
+ MESON_PIN(GPIOZ_1, EE_OFF),
+ MESON_PIN(GPIOZ_2, EE_OFF),
+ MESON_PIN(GPIOZ_3, EE_OFF),
+ MESON_PIN(GPIOZ_4, EE_OFF),
+ MESON_PIN(GPIOZ_5, EE_OFF),
+ MESON_PIN(GPIOZ_6, EE_OFF),
+ MESON_PIN(GPIOZ_7, EE_OFF),
+ MESON_PIN(GPIOZ_8, EE_OFF),
+ MESON_PIN(GPIOZ_9, EE_OFF),
+ MESON_PIN(GPIOZ_10, EE_OFF),
+ MESON_PIN(GPIOZ_11, EE_OFF),
+ MESON_PIN(GPIOZ_12, EE_OFF),
+ MESON_PIN(GPIOZ_13, EE_OFF),
+ MESON_PIN(GPIOZ_14, EE_OFF),
+ MESON_PIN(GPIOZ_15, EE_OFF),
+
+ MESON_PIN(GPIOH_0, EE_OFF),
+ MESON_PIN(GPIOH_1, EE_OFF),
+ MESON_PIN(GPIOH_2, EE_OFF),
+ MESON_PIN(GPIOH_3, EE_OFF),
+ MESON_PIN(GPIOH_4, EE_OFF),
+ MESON_PIN(GPIOH_5, EE_OFF),
+ MESON_PIN(GPIOH_6, EE_OFF),
+ MESON_PIN(GPIOH_7, EE_OFF),
+ MESON_PIN(GPIOH_8, EE_OFF),
+ MESON_PIN(GPIOH_9, EE_OFF),
+
+ MESON_PIN(BOOT_0, EE_OFF),
+ MESON_PIN(BOOT_1, EE_OFF),
+ MESON_PIN(BOOT_2, EE_OFF),
+ MESON_PIN(BOOT_3, EE_OFF),
+ MESON_PIN(BOOT_4, EE_OFF),
+ MESON_PIN(BOOT_5, EE_OFF),
+ MESON_PIN(BOOT_6, EE_OFF),
+ MESON_PIN(BOOT_7, EE_OFF),
+ MESON_PIN(BOOT_8, EE_OFF),
+ MESON_PIN(BOOT_9, EE_OFF),
+ MESON_PIN(BOOT_10, EE_OFF),
+ MESON_PIN(BOOT_11, EE_OFF),
+ MESON_PIN(BOOT_12, EE_OFF),
+ MESON_PIN(BOOT_13, EE_OFF),
+ MESON_PIN(BOOT_14, EE_OFF),
+ MESON_PIN(BOOT_15, EE_OFF),
+
+ MESON_PIN(CARD_0, EE_OFF),
+ MESON_PIN(CARD_1, EE_OFF),
+ MESON_PIN(CARD_2, EE_OFF),
+ MESON_PIN(CARD_3, EE_OFF),
+ MESON_PIN(CARD_4, EE_OFF),
+ MESON_PIN(CARD_5, EE_OFF),
+ MESON_PIN(CARD_6, EE_OFF),
+
+ MESON_PIN(GPIODV_0, EE_OFF),
+ MESON_PIN(GPIODV_1, EE_OFF),
+ MESON_PIN(GPIODV_2, EE_OFF),
+ MESON_PIN(GPIODV_3, EE_OFF),
+ MESON_PIN(GPIODV_4, EE_OFF),
+ MESON_PIN(GPIODV_5, EE_OFF),
+ MESON_PIN(GPIODV_6, EE_OFF),
+ MESON_PIN(GPIODV_7, EE_OFF),
+ MESON_PIN(GPIODV_8, EE_OFF),
+ MESON_PIN(GPIODV_9, EE_OFF),
+ MESON_PIN(GPIODV_10, EE_OFF),
+ MESON_PIN(GPIODV_11, EE_OFF),
+ MESON_PIN(GPIODV_12, EE_OFF),
+ MESON_PIN(GPIODV_13, EE_OFF),
+ MESON_PIN(GPIODV_14, EE_OFF),
+ MESON_PIN(GPIODV_15, EE_OFF),
+ MESON_PIN(GPIODV_16, EE_OFF),
+ MESON_PIN(GPIODV_17, EE_OFF),
+ MESON_PIN(GPIODV_19, EE_OFF),
+ MESON_PIN(GPIODV_20, EE_OFF),
+ MESON_PIN(GPIODV_21, EE_OFF),
+ MESON_PIN(GPIODV_22, EE_OFF),
+ MESON_PIN(GPIODV_23, EE_OFF),
+ MESON_PIN(GPIODV_24, EE_OFF),
+ MESON_PIN(GPIODV_25, EE_OFF),
+ MESON_PIN(GPIODV_26, EE_OFF),
+ MESON_PIN(GPIODV_27, EE_OFF),
+ MESON_PIN(GPIODV_28, EE_OFF),
+ MESON_PIN(GPIODV_29, EE_OFF),
+
+ MESON_PIN(GPIOX_0, EE_OFF),
+ MESON_PIN(GPIOX_1, EE_OFF),
+ MESON_PIN(GPIOX_2, EE_OFF),
+ MESON_PIN(GPIOX_3, EE_OFF),
+ MESON_PIN(GPIOX_4, EE_OFF),
+ MESON_PIN(GPIOX_5, EE_OFF),
+ MESON_PIN(GPIOX_6, EE_OFF),
+ MESON_PIN(GPIOX_7, EE_OFF),
+ MESON_PIN(GPIOX_8, EE_OFF),
+ MESON_PIN(GPIOX_9, EE_OFF),
+ MESON_PIN(GPIOX_10, EE_OFF),
+ MESON_PIN(GPIOX_11, EE_OFF),
+ MESON_PIN(GPIOX_12, EE_OFF),
+ MESON_PIN(GPIOX_13, EE_OFF),
+ MESON_PIN(GPIOX_14, EE_OFF),
+ MESON_PIN(GPIOX_15, EE_OFF),
+ MESON_PIN(GPIOX_16, EE_OFF),
+ MESON_PIN(GPIOX_17, EE_OFF),
+ MESON_PIN(GPIOX_18, EE_OFF),
+
+ MESON_PIN(GPIOCLK_0, EE_OFF),
+ MESON_PIN(GPIOCLK_1, EE_OFF),
+
+ MESON_PIN(GPIO_TEST_N, EE_OFF),
+};
+
+static const unsigned int emmc_nand_d07_pins[] = {
+ PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
+ PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF),
+ PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF),
+};
+static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) };
+static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) };
+static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) };
+
+static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) };
+static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) };
+static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) };
+static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
+static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
+static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
+
+static const unsigned int sdio_d0_pins[] = { PIN(GPIOX_0, EE_OFF) };
+static const unsigned int sdio_d1_pins[] = { PIN(GPIOX_1, EE_OFF) };
+static const unsigned int sdio_d2_pins[] = { PIN(GPIOX_2, EE_OFF) };
+static const unsigned int sdio_d3_pins[] = { PIN(GPIOX_3, EE_OFF) };
+static const unsigned int sdio_cmd_pins[] = { PIN(GPIOX_4, EE_OFF) };
+static const unsigned int sdio_clk_pins[] = { PIN(GPIOX_5, EE_OFF) };
+static const unsigned int sdio_irq_pins[] = { PIN(GPIOX_7, EE_OFF) };
+
+static const unsigned int nand_ce0_pins[] = { PIN(BOOT_8, EE_OFF) };
+static const unsigned int nand_ce1_pins[] = { PIN(BOOT_9, EE_OFF) };
+static const unsigned int nand_rb0_pins[] = { PIN(BOOT_10, EE_OFF) };
+static const unsigned int nand_ale_pins[] = { PIN(BOOT_11, EE_OFF) };
+static const unsigned int nand_cle_pins[] = { PIN(BOOT_12, EE_OFF) };
+static const unsigned int nand_wen_clk_pins[] = { PIN(BOOT_13, EE_OFF) };
+static const unsigned int nand_ren_wr_pins[] = { PIN(BOOT_14, EE_OFF) };
+static const unsigned int nand_dqs_pins[] = { PIN(BOOT_15, EE_OFF) };
+
+static const unsigned int uart_tx_a_pins[] = { PIN(GPIOX_12, EE_OFF) };
+static const unsigned int uart_rx_a_pins[] = { PIN(GPIOX_13, EE_OFF) };
+static const unsigned int uart_cts_a_pins[] = { PIN(GPIOX_14, EE_OFF) };
+static const unsigned int uart_rts_a_pins[] = { PIN(GPIOX_15, EE_OFF) };
+
+static const unsigned int uart_tx_b_pins[] = { PIN(GPIODV_24, EE_OFF) };
+static const unsigned int uart_rx_b_pins[] = { PIN(GPIODV_25, EE_OFF) };
+
+static const unsigned int uart_tx_c_pins[] = { PIN(GPIOX_8, EE_OFF) };
+static const unsigned int uart_rx_c_pins[] = { PIN(GPIOX_9, EE_OFF) };
+
+static const unsigned int i2c_sck_a_pins[] = { PIN(GPIODV_25, EE_OFF) };
+static const unsigned int i2c_sda_a_pins[] = { PIN(GPIODV_24, EE_OFF) };
+
+static const unsigned int i2c_sck_b_pins[] = { PIN(GPIODV_27, EE_OFF) };
+static const unsigned int i2c_sda_b_pins[] = { PIN(GPIODV_26, EE_OFF) };
+
+static const unsigned int i2c_sck_c_pins[] = { PIN(GPIODV_29, EE_OFF) };
+static const unsigned int i2c_sda_c_pins[] = { PIN(GPIODV_28, EE_OFF) };
+
+static const unsigned int eth_mdio_pins[] = { PIN(GPIOZ_0, EE_OFF) };
+static const unsigned int eth_mdc_pins[] = { PIN(GPIOZ_1, EE_OFF) };
+static const unsigned int eth_clk_rx_clk_pins[] = { PIN(GPIOZ_2, EE_OFF) };
+static const unsigned int eth_rx_dv_pins[] = { PIN(GPIOZ_3, EE_OFF) };
+static const unsigned int eth_rxd0_pins[] = { PIN(GPIOZ_4, EE_OFF) };
+static const unsigned int eth_rxd1_pins[] = { PIN(GPIOZ_5, EE_OFF) };
+static const unsigned int eth_rxd2_pins[] = { PIN(GPIOZ_6, EE_OFF) };
+static const unsigned int eth_rxd3_pins[] = { PIN(GPIOZ_7, EE_OFF) };
+static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) };
+static const unsigned int eth_tx_en_pins[] = { PIN(GPIOZ_9, EE_OFF) };
+static const unsigned int eth_txd0_pins[] = { PIN(GPIOZ_10, EE_OFF) };
+static const unsigned int eth_txd1_pins[] = { PIN(GPIOZ_11, EE_OFF) };
+static const unsigned int eth_txd2_pins[] = { PIN(GPIOZ_12, EE_OFF) };
+static const unsigned int eth_txd3_pins[] = { PIN(GPIOZ_13, EE_OFF) };
+
+static const unsigned int pwm_e_pins[] = { PIN(GPIOX_16, EE_OFF) };
+
+static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = {
+ MESON_PIN(GPIOAO_0, 0),
+ MESON_PIN(GPIOAO_1, 0),
+ MESON_PIN(GPIOAO_2, 0),
+ MESON_PIN(GPIOAO_3, 0),
+ MESON_PIN(GPIOAO_4, 0),
+ MESON_PIN(GPIOAO_5, 0),
+ MESON_PIN(GPIOAO_6, 0),
+ MESON_PIN(GPIOAO_7, 0),
+ MESON_PIN(GPIOAO_8, 0),
+ MESON_PIN(GPIOAO_9, 0),
+};
+
+static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, 0) };
+static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) };
+static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_1, 0),
+ PIN(GPIOAO_5, 0) };
+static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
+
+static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
+
+static struct meson_pmx_group meson_gxl_periphs_groups[] = {
+ GPIO_GROUP(GPIOZ_0, EE_OFF),
+ GPIO_GROUP(GPIOZ_1, EE_OFF),
+ GPIO_GROUP(GPIOZ_2, EE_OFF),
+ GPIO_GROUP(GPIOZ_3, EE_OFF),
+ GPIO_GROUP(GPIOZ_4, EE_OFF),
+ GPIO_GROUP(GPIOZ_5, EE_OFF),
+ GPIO_GROUP(GPIOZ_6, EE_OFF),
+ GPIO_GROUP(GPIOZ_7, EE_OFF),
+ GPIO_GROUP(GPIOZ_8, EE_OFF),
+ GPIO_GROUP(GPIOZ_9, EE_OFF),
+ GPIO_GROUP(GPIOZ_10, EE_OFF),
+ GPIO_GROUP(GPIOZ_11, EE_OFF),
+ GPIO_GROUP(GPIOZ_12, EE_OFF),
+ GPIO_GROUP(GPIOZ_13, EE_OFF),
+ GPIO_GROUP(GPIOZ_14, EE_OFF),
+ GPIO_GROUP(GPIOZ_15, EE_OFF),
+
+ GPIO_GROUP(GPIOH_0, EE_OFF),
+ GPIO_GROUP(GPIOH_1, EE_OFF),
+ GPIO_GROUP(GPIOH_2, EE_OFF),
+ GPIO_GROUP(GPIOH_3, EE_OFF),
+ GPIO_GROUP(GPIOH_4, EE_OFF),
+ GPIO_GROUP(GPIOH_5, EE_OFF),
+ GPIO_GROUP(GPIOH_6, EE_OFF),
+ GPIO_GROUP(GPIOH_7, EE_OFF),
+ GPIO_GROUP(GPIOH_8, EE_OFF),
+ GPIO_GROUP(GPIOH_9, EE_OFF),
+
+ GPIO_GROUP(BOOT_0, EE_OFF),
+ GPIO_GROUP(BOOT_1, EE_OFF),
+ GPIO_GROUP(BOOT_2, EE_OFF),
+ GPIO_GROUP(BOOT_3, EE_OFF),
+ GPIO_GROUP(BOOT_4, EE_OFF),
+ GPIO_GROUP(BOOT_5, EE_OFF),
+ GPIO_GROUP(BOOT_6, EE_OFF),
+ GPIO_GROUP(BOOT_7, EE_OFF),
+ GPIO_GROUP(BOOT_8, EE_OFF),
+ GPIO_GROUP(BOOT_9, EE_OFF),
+ GPIO_GROUP(BOOT_10, EE_OFF),
+ GPIO_GROUP(BOOT_11, EE_OFF),
+ GPIO_GROUP(BOOT_12, EE_OFF),
+ GPIO_GROUP(BOOT_13, EE_OFF),
+ GPIO_GROUP(BOOT_14, EE_OFF),
+ GPIO_GROUP(BOOT_15, EE_OFF),
+
+ GPIO_GROUP(CARD_0, EE_OFF),
+ GPIO_GROUP(CARD_1, EE_OFF),
+ GPIO_GROUP(CARD_2, EE_OFF),
+ GPIO_GROUP(CARD_3, EE_OFF),
+ GPIO_GROUP(CARD_4, EE_OFF),
+ GPIO_GROUP(CARD_5, EE_OFF),
+ GPIO_GROUP(CARD_6, EE_OFF),
+
+ GPIO_GROUP(GPIODV_0, EE_OFF),
+ GPIO_GROUP(GPIODV_1, EE_OFF),
+ GPIO_GROUP(GPIODV_2, EE_OFF),
+ GPIO_GROUP(GPIODV_3, EE_OFF),
+ GPIO_GROUP(GPIODV_4, EE_OFF),
+ GPIO_GROUP(GPIODV_5, EE_OFF),
+ GPIO_GROUP(GPIODV_6, EE_OFF),
+ GPIO_GROUP(GPIODV_7, EE_OFF),
+ GPIO_GROUP(GPIODV_8, EE_OFF),
+ GPIO_GROUP(GPIODV_9, EE_OFF),
+ GPIO_GROUP(GPIODV_10, EE_OFF),
+ GPIO_GROUP(GPIODV_11, EE_OFF),
+ GPIO_GROUP(GPIODV_12, EE_OFF),
+ GPIO_GROUP(GPIODV_13, EE_OFF),
+ GPIO_GROUP(GPIODV_14, EE_OFF),
+ GPIO_GROUP(GPIODV_15, EE_OFF),
+ GPIO_GROUP(GPIODV_16, EE_OFF),
+ GPIO_GROUP(GPIODV_17, EE_OFF),
+ GPIO_GROUP(GPIODV_19, EE_OFF),
+ GPIO_GROUP(GPIODV_20, EE_OFF),
+ GPIO_GROUP(GPIODV_21, EE_OFF),
+ GPIO_GROUP(GPIODV_22, EE_OFF),
+ GPIO_GROUP(GPIODV_23, EE_OFF),
+ GPIO_GROUP(GPIODV_24, EE_OFF),
+ GPIO_GROUP(GPIODV_25, EE_OFF),
+ GPIO_GROUP(GPIODV_26, EE_OFF),
+ GPIO_GROUP(GPIODV_27, EE_OFF),
+ GPIO_GROUP(GPIODV_28, EE_OFF),
+ GPIO_GROUP(GPIODV_29, EE_OFF),
+
+ GPIO_GROUP(GPIOX_0, EE_OFF),
+ GPIO_GROUP(GPIOX_1, EE_OFF),
+ GPIO_GROUP(GPIOX_2, EE_OFF),
+ GPIO_GROUP(GPIOX_3, EE_OFF),
+ GPIO_GROUP(GPIOX_4, EE_OFF),
+ GPIO_GROUP(GPIOX_5, EE_OFF),
+ GPIO_GROUP(GPIOX_6, EE_OFF),
+ GPIO_GROUP(GPIOX_7, EE_OFF),
+ GPIO_GROUP(GPIOX_8, EE_OFF),
+ GPIO_GROUP(GPIOX_9, EE_OFF),
+ GPIO_GROUP(GPIOX_10, EE_OFF),
+ GPIO_GROUP(GPIOX_11, EE_OFF),
+ GPIO_GROUP(GPIOX_12, EE_OFF),
+ GPIO_GROUP(GPIOX_13, EE_OFF),
+ GPIO_GROUP(GPIOX_14, EE_OFF),
+ GPIO_GROUP(GPIOX_15, EE_OFF),
+ GPIO_GROUP(GPIOX_16, EE_OFF),
+ GPIO_GROUP(GPIOX_17, EE_OFF),
+ GPIO_GROUP(GPIOX_18, EE_OFF),
+
+ GPIO_GROUP(GPIOCLK_0, EE_OFF),
+ GPIO_GROUP(GPIOCLK_1, EE_OFF),
+
+ GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+
+ /* Bank X */
+ GROUP(sdio_d0, 5, 31),
+ GROUP(sdio_d1, 5, 30),
+ GROUP(sdio_d2, 5, 29),
+ GROUP(sdio_d3, 5, 28),
+ GROUP(sdio_cmd, 5, 27),
+ GROUP(sdio_clk, 5, 26),
+ GROUP(sdio_irq, 5, 24),
+ GROUP(uart_tx_a, 5, 19),
+ GROUP(uart_rx_a, 5, 18),
+ GROUP(uart_cts_a, 5, 17),
+ GROUP(uart_rts_a, 5, 16),
+ GROUP(uart_tx_c, 5, 13),
+ GROUP(uart_rx_c, 5, 12),
+ GROUP(pwm_e, 5, 15),
+
+ /* Bank Z */
+ GROUP(eth_mdio, 4, 22),
+ GROUP(eth_mdc, 4, 23),
+ GROUP(eth_clk_rx_clk, 4, 21),
+ GROUP(eth_rx_dv, 4, 20),
+ GROUP(eth_rxd0, 4, 19),
+ GROUP(eth_rxd1, 4, 18),
+ GROUP(eth_rxd2, 4, 17),
+ GROUP(eth_rxd3, 4, 16),
+ GROUP(eth_rgmii_tx_clk, 4, 15),
+ GROUP(eth_tx_en, 4, 14),
+ GROUP(eth_txd0, 4, 13),
+ GROUP(eth_txd1, 4, 12),
+ GROUP(eth_txd2, 4, 11),
+ GROUP(eth_txd3, 4, 10),
+
+ /* Bank DV */
+ GROUP(uart_tx_b, 2, 16),
+ GROUP(uart_rx_b, 2, 15),
+ GROUP(i2c_sck_a, 1, 15),
+ GROUP(i2c_sda_a, 1, 14),
+ GROUP(i2c_sck_b, 1, 13),
+ GROUP(i2c_sda_b, 1, 12),
+ GROUP(i2c_sck_c, 1, 11),
+ GROUP(i2c_sda_c, 1, 10),
+
+ /* Bank BOOT */
+ GROUP(emmc_nand_d07, 7, 31),
+ GROUP(emmc_clk, 7, 30),
+ GROUP(emmc_cmd, 7, 29),
+ GROUP(emmc_ds, 7, 28),
+ GROUP(nand_ce0, 7, 7),
+ GROUP(nand_ce1, 7, 6),
+ GROUP(nand_rb0, 7, 5),
+ GROUP(nand_ale, 7, 4),
+ GROUP(nand_cle, 7, 3),
+ GROUP(nand_wen_clk, 7, 2),
+ GROUP(nand_ren_wr, 7, 1),
+ GROUP(nand_dqs, 7, 0),
+
+ /* Bank CARD */
+ GROUP(sdcard_d1, 6, 5),
+ GROUP(sdcard_d0, 6, 4),
+ GROUP(sdcard_d3, 6, 1),
+ GROUP(sdcard_d2, 6, 0),
+ GROUP(sdcard_cmd, 6, 2),
+ GROUP(sdcard_clk, 6, 3),
+};
+
+static struct meson_pmx_group meson_gxl_aobus_groups[] = {
+ GPIO_GROUP(GPIOAO_0, 0),
+ GPIO_GROUP(GPIOAO_1, 0),
+ GPIO_GROUP(GPIOAO_2, 0),
+ GPIO_GROUP(GPIOAO_3, 0),
+ GPIO_GROUP(GPIOAO_4, 0),
+ GPIO_GROUP(GPIOAO_5, 0),
+ GPIO_GROUP(GPIOAO_6, 0),
+ GPIO_GROUP(GPIOAO_7, 0),
+ GPIO_GROUP(GPIOAO_8, 0),
+ GPIO_GROUP(GPIOAO_9, 0),
+
+ /* bank AO */
+ GROUP(uart_tx_ao_b, 0, 26),
+ GROUP(uart_rx_ao_b, 0, 25),
+ GROUP(uart_tx_ao_a, 0, 12),
+ GROUP(uart_rx_ao_a, 0, 11),
+ GROUP(uart_cts_ao_a, 0, 10),
+ GROUP(uart_rts_ao_a, 0, 9),
+ GROUP(uart_cts_ao_b, 0, 8),
+ GROUP(uart_rts_ao_b, 0, 7),
+ GROUP(remote_input_ao, 0, 0),
+};
+
+static const char * const gpio_periphs_groups[] = {
+ "GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4",
+ "GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9",
+ "GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14",
+ "GPIOZ_15",
+
+ "GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3", "GPIOH_4",
+ "GPIOH_5", "GPIOH_6", "GPIOH_7", "GPIOH_8", "GPIOH_9",
+
+ "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+ "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+ "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+ "BOOT_15",
+
+ "CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4",
+ "CARD_5", "CARD_6",
+
+ "GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4",
+ "GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9",
+ "GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14",
+ "GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19",
+ "GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24",
+ "GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29",
+
+ "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+ "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+ "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+ "GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18",
+
+ "GPIO_TEST_N",
+};
+
+static const char * const emmc_groups[] = {
+ "emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds",
+};
+
+static const char * const sdcard_groups[] = {
+ "sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3",
+ "sdcard_cmd", "sdcard_clk",
+};
+
+static const char * const sdio_groups[] = {
+ "sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3",
+ "sdio_cmd", "sdio_clk", "sdio_irq",
+};
+
+static const char * const nand_groups[] = {
+ "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", "nand_cle",
+ "nand_wen_clk", "nand_ren_wr", "nand_dqs",
+};
+
+static const char * const uart_a_groups[] = {
+ "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
+};
+
+static const char * const uart_b_groups[] = {
+ "uart_tx_b", "uart_rx_b",
+};
+
+static const char * const uart_c_groups[] = {
+ "uart_tx_c", "uart_rx_c",
+};
+
+static const char * const i2c_a_groups[] = {
+ "i2c_sck_a", "i2c_sda_a",
+};
+
+static const char * const i2c_b_groups[] = {
+ "i2c_sck_b", "i2c_sda_b",
+};
+
+static const char * const i2c_c_groups[] = {
+ "i2c_sck_c", "i2c_sda_c",
+};
+
+static const char * const eth_groups[] = {
+ "eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv",
+ "eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3",
+ "eth_rgmii_tx_clk", "eth_tx_en",
+ "eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
+};
+
+static const char * const pwm_e_groups[] = {
+ "pwm_e",
+};
+
+static const char * const gpio_aobus_groups[] = {
+ "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
+ "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+};
+
+static const char * const uart_ao_groups[] = {
+ "uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a",
+};
+
+static const char * const uart_ao_b_groups[] = {
+ "uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b",
+};
+
+static const char * const remote_input_ao_groups[] = {
+ "remote_input_ao",
+};
+
+static struct meson_pmx_func meson_gxl_periphs_functions[] = {
+ FUNCTION(gpio_periphs),
+ FUNCTION(emmc),
+ FUNCTION(sdcard),
+ FUNCTION(sdio),
+ FUNCTION(nand),
+ FUNCTION(uart_a),
+ FUNCTION(uart_b),
+ FUNCTION(uart_c),
+ FUNCTION(i2c_a),
+ FUNCTION(i2c_b),
+ FUNCTION(i2c_c),
+ FUNCTION(eth),
+ FUNCTION(pwm_e),
+};
+
+static struct meson_pmx_func meson_gxl_aobus_functions[] = {
+ FUNCTION(gpio_aobus),
+ FUNCTION(uart_ao),
+ FUNCTION(uart_ao_b),
+ FUNCTION(remote_input_ao),
+};
+
+static struct meson_bank meson_gxl_periphs_banks[] = {
+ /* name first last pullen pull dir out in */
+ BANK("X", PIN(GPIOX_0, EE_OFF), PIN(GPIOX_18, EE_OFF), 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
+ BANK("DV", PIN(GPIODV_0, EE_OFF), PIN(GPIODV_29, EE_OFF), 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
+ BANK("H", PIN(GPIOH_0, EE_OFF), PIN(GPIOH_9, EE_OFF), 1, 20, 1, 20, 3, 20, 4, 20, 5, 20),
+ BANK("Z", PIN(GPIOZ_0, EE_OFF), PIN(GPIOZ_15, EE_OFF), 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
+ BANK("CARD", PIN(CARD_0, EE_OFF), PIN(CARD_6, EE_OFF), 2, 20, 2, 20, 6, 20, 7, 20, 8, 20),
+ BANK("BOOT", PIN(BOOT_0, EE_OFF), PIN(BOOT_15, EE_OFF), 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
+ BANK("CLK", PIN(GPIOCLK_0, EE_OFF), PIN(GPIOCLK_1, EE_OFF), 3, 28, 3, 28, 9, 28, 10, 28, 11, 28),
+};
+
+static struct meson_bank meson_gxl_aobus_banks[] = {
+ /* name first last pullen pull dir out in */
+ BANK("AO", PIN(GPIOAO_0, 0), PIN(GPIOAO_9, 0), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
+};
+
+struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = {
+ .name = "periphs-banks",
+ .pin_base = 10,
+ .pins = meson_gxl_periphs_pins,
+ .groups = meson_gxl_periphs_groups,
+ .funcs = meson_gxl_periphs_functions,
+ .banks = meson_gxl_periphs_banks,
+ .num_pins = ARRAY_SIZE(meson_gxl_periphs_pins),
+ .num_groups = ARRAY_SIZE(meson_gxl_periphs_groups),
+ .num_funcs = ARRAY_SIZE(meson_gxl_periphs_functions),
+ .num_banks = ARRAY_SIZE(meson_gxl_periphs_banks),
+};
+
+struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data = {
+ .name = "aobus-banks",
+ .pin_base = 0,
+ .pins = meson_gxl_aobus_pins,
+ .groups = meson_gxl_aobus_groups,
+ .funcs = meson_gxl_aobus_functions,
+ .banks = meson_gxl_aobus_banks,
+ .num_pins = ARRAY_SIZE(meson_gxl_aobus_pins),
+ .num_groups = ARRAY_SIZE(meson_gxl_aobus_groups),
+ .num_funcs = ARRAY_SIZE(meson_gxl_aobus_functions),
+ .num_banks = ARRAY_SIZE(meson_gxl_aobus_banks),
+};
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 57122eda155a..a579126832af 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -524,6 +524,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
.compatible = "amlogic,meson-gxbb-aobus-pinctrl",
.data = &meson_gxbb_aobus_pinctrl_data,
},
+ {
+ .compatible = "amlogic,meson-gxl-periphs-pinctrl",
+ .data = &meson_gxl_periphs_pinctrl_data,
+ },
+ {
+ .compatible = "amlogic,meson-gxl-aobus-pinctrl",
+ .data = &meson_gxl_aobus_pinctrl_data,
+ },
{ },
};
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index 98b5080650c1..1aa871d5431e 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -169,3 +169,5 @@ extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data;
extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data;
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
index 8392083514fb..af4814479eb0 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
@@ -379,13 +379,24 @@ static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 };
static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
/* Basic pins of the MMC/SD card 0 interface */
-static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
- DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
- DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, /* MC0_CMDDIR */
+ DB8500_PIN_AC1, /* MC0_DAT0DIR */
+ DB8500_PIN_AB4, /* MC0_DAT2DIR */
+ DB8500_PIN_AA3, /* MC0_FBCLK */
+ DB8500_PIN_AA4, /* MC0_CLK */
+ DB8500_PIN_AB2, /* MC0_CMD */
+ DB8500_PIN_Y4, /* MC0_DAT0 */
+ DB8500_PIN_Y2, /* MC0_DAT1 */
+ DB8500_PIN_AA2, /* MC0_DAT2 */
+ DB8500_PIN_AA1 /* MC0_DAT3 */
+};
/* Often only 4 bits are used, then these are not needed (only used for MMC) */
-static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
- DB8500_PIN_V3, DB8500_PIN_V2};
-static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 };
+static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, /* MC0_DAT4 */
+ DB8500_PIN_W3, /* MC0_DAT5 */
+ DB8500_PIN_V3, /* MC0_DAT6 */
+ DB8500_PIN_V2 /* MC0_DAT7 */
+};
+static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 }; /* MC0_DAT31DIR */
/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 };
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 5020ae534479..ce3335accb5b 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -381,7 +381,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
if (ret < 0)
goto exit;
- for_each_child_of_node(np_config, np) {
+ for_each_available_child_of_node(np_config, np) {
ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
&reserved_maps, num_maps, type);
if (ret < 0)
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 9f0904185909..569bc28cb909 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -56,6 +56,9 @@ static int gpio_banks;
#define DRIVE_STRENGTH_SHIFT 5
#define DRIVE_STRENGTH_MASK 0x3
#define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT)
+#define OUTPUT (1 << 7)
+#define OUTPUT_VAL_SHIFT 8
+#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
@@ -375,6 +378,19 @@ static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
}
+static bool at91_mux_get_output(void __iomem *pio, unsigned int pin, bool *val)
+{
+ *val = (readl_relaxed(pio + PIO_ODSR) >> pin) & 0x1;
+ return (readl_relaxed(pio + PIO_OSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_output(void __iomem *pio, unsigned int mask,
+ bool is_on, bool val)
+{
+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+ writel_relaxed(mask, pio + (is_on ? PIO_OER : PIO_ODR));
+}
+
static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
{
return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
@@ -848,6 +864,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
void __iomem *pio;
unsigned pin;
int div;
+ bool out;
*config = 0;
dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id);
@@ -875,6 +892,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
if (info->ops->get_drivestrength)
*config |= (info->ops->get_drivestrength(pio, pin)
<< DRIVE_STRENGTH_SHIFT);
+ if (at91_mux_get_output(pio, pin, &out))
+ *config |= OUTPUT | (out << OUTPUT_VAL_SHIFT);
return 0;
}
@@ -907,6 +926,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
if (config & PULL_UP && config & PULL_DOWN)
return -EINVAL;
+ at91_mux_set_output(pio, mask, config & OUTPUT,
+ (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT);
at91_mux_set_pullup(pio, mask, config & PULL_UP);
at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
if (info->ops->set_deglitch)
diff --git a/drivers/pinctrl/pinctrl-da850-pupd.c b/drivers/pinctrl/pinctrl-da850-pupd.c
new file mode 100644
index 000000000000..b36a90a3f3e4
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-da850-pupd.c
@@ -0,0 +1,210 @@
+/*
+ * Pinconf driver for TI DA850/OMAP-L138/AM18XX pullup/pulldown groups
+ *
+ * Copyright (C) 2016 David Lechner
+ *
+ * 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/bitops.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#define DA850_PUPD_ENA 0x00
+#define DA850_PUPD_SEL 0x04
+
+struct da850_pupd_data {
+ void __iomem *base;
+ struct pinctrl_desc desc;
+ struct pinctrl_dev *pinctrl;
+};
+
+static const char * const da850_pupd_group_names[] = {
+ "cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7",
+ "cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15",
+ "cp16", "cp17", "cp18", "cp19", "cp20", "cp21", "cp22", "cp23",
+ "cp24", "cp25", "cp26", "cp27", "cp28", "cp29", "cp30", "cp31",
+};
+
+static int da850_pupd_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(da850_pupd_group_names);
+}
+
+static const char *da850_pupd_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ return da850_pupd_group_names[selector];
+}
+
+static int da850_pupd_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ *num_pins = 0;
+
+ return 0;
+}
+
+static const struct pinctrl_ops da850_pupd_pctlops = {
+ .get_groups_count = da850_pupd_get_groups_count,
+ .get_group_name = da850_pupd_get_group_name,
+ .get_group_pins = da850_pupd_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int da850_pupd_pin_config_group_get(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *config)
+{
+ struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ u32 val;
+ u16 arg;
+
+ val = readl(data->base + DA850_PUPD_ENA);
+ arg = !!(~val & BIT(selector));
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (arg) {
+ /* bias is disabled */
+ arg = 0;
+ break;
+ }
+ val = readl(data->base + DA850_PUPD_SEL);
+ if (param == PIN_CONFIG_BIAS_PULL_DOWN)
+ val = ~val;
+ arg = !!(val & BIT(selector));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
+ u32 ena, sel;
+ enum pin_config_param param;
+ u16 arg;
+ int i;
+
+ ena = readl(data->base + DA850_PUPD_ENA);
+ sel = readl(data->base + DA850_PUPD_SEL);
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ ena &= ~BIT(selector);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ena |= BIT(selector);
+ sel |= BIT(selector);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ena |= BIT(selector);
+ sel &= ~BIT(selector);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ writel(sel, data->base + DA850_PUPD_SEL);
+ writel(ena, data->base + DA850_PUPD_ENA);
+
+ return 0;
+}
+
+static const struct pinconf_ops da850_pupd_confops = {
+ .is_generic = true,
+ .pin_config_group_get = da850_pupd_pin_config_group_get,
+ .pin_config_group_set = da850_pupd_pin_config_group_set,
+};
+
+static int da850_pupd_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct da850_pupd_data *data;
+ struct resource *res;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->base)) {
+ dev_err(dev, "Could not map resource\n");
+ return PTR_ERR(data->base);
+ }
+
+ data->desc.name = dev_name(dev);
+ data->desc.pctlops = &da850_pupd_pctlops;
+ data->desc.confops = &da850_pupd_confops;
+ data->desc.owner = THIS_MODULE;
+
+ data->pinctrl = devm_pinctrl_register(dev, &data->desc, data);
+ if (IS_ERR(data->pinctrl)) {
+ dev_err(dev, "Failed to register pinctrl\n");
+ return PTR_ERR(data->pinctrl);
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int da850_pupd_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id da850_pupd_of_match[] = {
+ { .compatible = "ti,da850-pupd" },
+ { }
+};
+
+static struct platform_driver da850_pupd_driver = {
+ .driver = {
+ .name = "ti-da850-pupd",
+ .of_match_table = da850_pupd_of_match,
+ },
+ .probe = da850_pupd_probe,
+ .remove = da850_pupd_remove,
+};
+module_platform_driver(da850_pupd_driver);
+
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_DESCRIPTION("TI DA850/OMAP-L138/AM18XX pullup/pulldown configuration");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
index 917a7d2535d7..494ec9a7573a 100644
--- a/drivers/pinctrl/pinctrl-oxnas.c
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -37,15 +37,24 @@
#define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK)
-/* Regmap Offsets */
-#define PINMUX_PRIMARY_SEL0 0x0c
-#define PINMUX_SECONDARY_SEL0 0x14
-#define PINMUX_TERTIARY_SEL0 0x8c
-#define PINMUX_PRIMARY_SEL1 0x10
-#define PINMUX_SECONDARY_SEL1 0x18
-#define PINMUX_TERTIARY_SEL1 0x90
-#define PINMUX_PULLUP_CTRL0 0xac
-#define PINMUX_PULLUP_CTRL1 0xb0
+/* OX810 Regmap Offsets */
+#define PINMUX_810_PRIMARY_SEL0 0x0c
+#define PINMUX_810_SECONDARY_SEL0 0x14
+#define PINMUX_810_TERTIARY_SEL0 0x8c
+#define PINMUX_810_PRIMARY_SEL1 0x10
+#define PINMUX_810_SECONDARY_SEL1 0x18
+#define PINMUX_810_TERTIARY_SEL1 0x90
+#define PINMUX_810_PULLUP_CTRL0 0xac
+#define PINMUX_810_PULLUP_CTRL1 0xb0
+
+/* OX820 Regmap Offsets */
+#define PINMUX_820_BANK_OFFSET 0x100000
+#define PINMUX_820_SECONDARY_SEL 0x14
+#define PINMUX_820_TERTIARY_SEL 0x8c
+#define PINMUX_820_QUATERNARY_SEL 0x94
+#define PINMUX_820_DEBUG_SEL 0x9c
+#define PINMUX_820_ALTERNATIVE_SEL 0xa4
+#define PINMUX_820_PULLUP_CTRL 0xac
/* GPIO Registers */
#define INPUT_VALUE 0x00
@@ -87,8 +96,6 @@ struct oxnas_pinctrl {
struct regmap *regmap;
struct device *dev;
struct pinctrl_dev *pctldev;
- const struct pinctrl_pin_desc *pins;
- unsigned int npins;
const struct oxnas_function *functions;
unsigned int nfunctions;
const struct oxnas_pin_group *groups;
@@ -97,7 +104,50 @@ struct oxnas_pinctrl {
unsigned int nbanks;
};
-static const struct pinctrl_pin_desc oxnas_pins[] = {
+struct oxnas_pinctrl_data {
+ struct pinctrl_desc *desc;
+ struct oxnas_pinctrl *pctl;
+};
+
+static const struct pinctrl_pin_desc oxnas_ox810se_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+};
+
+static const struct pinctrl_pin_desc oxnas_ox820_pins[] = {
PINCTRL_PIN(0, "gpio0"),
PINCTRL_PIN(1, "gpio1"),
PINCTRL_PIN(2, "gpio2"),
@@ -133,9 +183,24 @@ static const struct pinctrl_pin_desc oxnas_pins[] = {
PINCTRL_PIN(32, "gpio32"),
PINCTRL_PIN(33, "gpio33"),
PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
};
-static const char * const oxnas_fct0_group[] = {
+static const char * const oxnas_ox810se_fct0_group[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7",
"gpio8", "gpio9", "gpio10", "gpio11",
@@ -147,7 +212,7 @@ static const char * const oxnas_fct0_group[] = {
"gpio32", "gpio33", "gpio34"
};
-static const char * const oxnas_fct3_group[] = {
+static const char * const oxnas_ox810se_fct3_group[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7",
"gpio8", "gpio9",
@@ -158,6 +223,40 @@ static const char * const oxnas_fct3_group[] = {
"gpio34"
};
+static const char * const oxnas_ox820_fct0_group[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15",
+ "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio28", "gpio29", "gpio30", "gpio31",
+ "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39",
+ "gpio40", "gpio41", "gpio42", "gpio43",
+ "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49"
+};
+
+static const char * const oxnas_ox820_fct1_group[] = {
+ "gpio3", "gpio4",
+ "gpio12", "gpio13", "gpio14", "gpio15",
+ "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24"
+};
+
+static const char * const oxnas_ox820_fct4_group[] = {
+ "gpio5", "gpio6", "gpio7", "gpio8",
+ "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio40", "gpio41", "gpio42", "gpio43"
+};
+
+static const char * const oxnas_ox820_fct5_group[] = {
+ "gpio28", "gpio29", "gpio30", "gpio31"
+};
+
#define FUNCTION(_name, _gr) \
{ \
.name = #_name, \
@@ -165,9 +264,16 @@ static const char * const oxnas_fct3_group[] = {
.ngroups = ARRAY_SIZE(oxnas_##_gr##_group), \
}
-static const struct oxnas_function oxnas_functions[] = {
- FUNCTION(gpio, fct0),
- FUNCTION(fct3, fct3),
+static const struct oxnas_function oxnas_ox810se_functions[] = {
+ FUNCTION(gpio, ox810se_fct0),
+ FUNCTION(fct3, ox810se_fct3),
+};
+
+static const struct oxnas_function oxnas_ox820_functions[] = {
+ FUNCTION(gpio, ox820_fct0),
+ FUNCTION(fct1, ox820_fct1),
+ FUNCTION(fct4, ox820_fct4),
+ FUNCTION(fct5, ox820_fct5),
};
#define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \
@@ -185,7 +291,7 @@ static const struct oxnas_function oxnas_functions[] = {
.fct = _fct, \
}
-static const struct oxnas_pin_group oxnas_groups[] = {
+static const struct oxnas_pin_group oxnas_ox810se_groups[] = {
OXNAS_PINCTRL_GROUP(0, gpio0,
OXNAS_PINCTRL_FUNCTION(gpio, 0),
OXNAS_PINCTRL_FUNCTION(fct3, 3)),
@@ -282,6 +388,140 @@ static const struct oxnas_pin_group oxnas_groups[] = {
OXNAS_PINCTRL_FUNCTION(fct3, 3)),
};
+static const struct oxnas_pin_group oxnas_ox820_groups[] = {
+ OXNAS_PINCTRL_GROUP(0, gpio0,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(1, gpio1,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(2, gpio2,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(3, gpio3,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(4, gpio4,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(5, gpio5,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(6, gpio6,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(7, gpio7,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(8, gpio8,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(9, gpio9,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(10, gpio10,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(11, gpio11,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(12, gpio12,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(13, gpio13,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(14, gpio14,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(15, gpio15,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(16, gpio16,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(17, gpio17,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(18, gpio18,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(19, gpio19,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(20, gpio20,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(21, gpio21,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(22, gpio22,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(23, gpio23,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(24, gpio24,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1),
+ OXNAS_PINCTRL_FUNCTION(fct4, 5)),
+ OXNAS_PINCTRL_GROUP(25, gpio25,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(26, gpio26,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(27, gpio27,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(28, gpio28,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(29, gpio29,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(30, gpio30,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(31, gpio31,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(32, gpio32,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(33, gpio33,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(34, gpio34,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(35, gpio35,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(36, gpio36,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(37, gpio37,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(38, gpio38,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(39, gpio39,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(40, gpio40,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(41, gpio41,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(42, gpio42,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(43, gpio43,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(44, gpio44,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(45, gpio45,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(46, gpio46,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(47, gpio47,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(48, gpio48,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(49, gpio49,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+};
+
static inline struct oxnas_gpio_bank *pctl_to_bank(struct oxnas_pinctrl *pctl,
unsigned int pin)
{
@@ -352,8 +592,8 @@ static int oxnas_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
- unsigned int func, unsigned int group)
+static int oxnas_ox810se_pinmux_enable(struct pinctrl_dev *pctldev,
+ unsigned int func, unsigned int group)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
const struct oxnas_pin_group *pg = &pctl->groups[group];
@@ -371,22 +611,22 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_PRIMARY_SEL1 :
- PINMUX_PRIMARY_SEL0),
+ PINMUX_810_PRIMARY_SEL1 :
+ PINMUX_810_PRIMARY_SEL0),
mask,
(functions->fct == 1 ?
mask : 0));
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_SECONDARY_SEL1 :
- PINMUX_SECONDARY_SEL0),
+ PINMUX_810_SECONDARY_SEL1 :
+ PINMUX_810_SECONDARY_SEL0),
mask,
(functions->fct == 2 ?
mask : 0));
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_TERTIARY_SEL1 :
- PINMUX_TERTIARY_SEL0),
+ PINMUX_810_TERTIARY_SEL1 :
+ PINMUX_810_TERTIARY_SEL0),
mask,
(functions->fct == 3 ?
mask : 0));
@@ -402,9 +642,64 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
}
-static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned int offset)
+static int oxnas_ox820_pinmux_enable(struct pinctrl_dev *pctldev,
+ unsigned int func, unsigned int group)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct oxnas_pin_group *pg = &pctl->groups[group];
+ const struct oxnas_function *pf = &pctl->functions[func];
+ const char *fname = pf->name;
+ struct oxnas_desc_function *functions = pg->functions;
+ unsigned int offset = (pg->bank ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(pg->pin);
+
+ while (functions->name) {
+ if (!strcmp(functions->name, fname)) {
+ dev_dbg(pctl->dev,
+ "setting function %s bank %d pin %d fct %d mask %x\n",
+ fname, pg->bank, pg->pin,
+ functions->fct, mask);
+
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_SECONDARY_SEL,
+ mask,
+ (functions->fct == 1 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_TERTIARY_SEL,
+ mask,
+ (functions->fct == 2 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_QUATERNARY_SEL,
+ mask,
+ (functions->fct == 3 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_DEBUG_SEL,
+ mask,
+ (functions->fct == 4 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_ALTERNATIVE_SEL,
+ mask,
+ (functions->fct == 5 ?
+ mask : 0));
+
+ return 0;
+ }
+
+ functions++;
+ }
+
+ dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func);
+
+ return -EINVAL;
+}
+
+static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc);
@@ -415,18 +710,49 @@ static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_PRIMARY_SEL1 :
- PINMUX_PRIMARY_SEL0),
+ PINMUX_810_PRIMARY_SEL1 :
+ PINMUX_810_PRIMARY_SEL0),
mask, 0);
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_SECONDARY_SEL1 :
- PINMUX_SECONDARY_SEL0),
+ PINMUX_810_SECONDARY_SEL1 :
+ PINMUX_810_SECONDARY_SEL0),
mask, 0);
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_TERTIARY_SEL1 :
- PINMUX_TERTIARY_SEL0),
+ PINMUX_810_TERTIARY_SEL1 :
+ PINMUX_810_TERTIARY_SEL0),
+ mask, 0);
+
+ return 0;
+}
+
+static int oxnas_ox820_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(offset - bank->gpio_chip.base);
+
+ dev_dbg(pctl->dev, "requesting gpio %d in bank %d (id %d) with mask 0x%x\n",
+ offset, bank->gpio_chip.base, bank->id, mask);
+
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_SECONDARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_TERTIARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_QUATERNARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_DEBUG_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_ALTERNATIVE_SEL,
mask, 0);
return 0;
@@ -498,17 +824,26 @@ static int oxnas_gpio_set_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static const struct pinmux_ops oxnas_pinmux_ops = {
+static const struct pinmux_ops oxnas_ox810se_pinmux_ops = {
.get_functions_count = oxnas_pinmux_get_functions_count,
.get_function_name = oxnas_pinmux_get_function_name,
.get_function_groups = oxnas_pinmux_get_function_groups,
- .set_mux = oxnas_pinmux_enable,
- .gpio_request_enable = oxnas_gpio_request_enable,
+ .set_mux = oxnas_ox810se_pinmux_enable,
+ .gpio_request_enable = oxnas_ox810se_gpio_request_enable,
.gpio_set_direction = oxnas_gpio_set_direction,
};
-static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *config)
+static const struct pinmux_ops oxnas_ox820_pinmux_ops = {
+ .get_functions_count = oxnas_pinmux_get_functions_count,
+ .get_function_name = oxnas_pinmux_get_function_name,
+ .get_function_groups = oxnas_pinmux_get_function_groups,
+ .set_mux = oxnas_ox820_pinmux_enable,
+ .gpio_request_enable = oxnas_ox820_gpio_request_enable,
+ .gpio_set_direction = oxnas_gpio_set_direction,
+};
+
+static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
@@ -521,8 +856,38 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
case PIN_CONFIG_BIAS_PULL_UP:
ret = regmap_read(pctl->regmap,
(bank->id ?
- PINMUX_PULLUP_CTRL1 :
- PINMUX_PULLUP_CTRL0),
+ PINMUX_810_PULLUP_CTRL1 :
+ PINMUX_810_PULLUP_CTRL0),
+ &arg);
+ if (ret)
+ return ret;
+
+ arg = !!(arg & mask);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int oxnas_ox820_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+ unsigned int param = pinconf_to_config_param(*config);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(pin - bank->gpio_chip.base);
+ int ret;
+ u32 arg;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = regmap_read(pctl->regmap,
+ bank_offset + PINMUX_820_PULLUP_CTRL,
&arg);
if (ret)
return ret;
@@ -538,8 +903,9 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
-static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *configs, unsigned int num_configs)
+static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
@@ -561,8 +927,8 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
dev_dbg(pctl->dev, " pullup\n");
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_PULLUP_CTRL1 :
- PINMUX_PULLUP_CTRL0),
+ PINMUX_810_PULLUP_CTRL1 :
+ PINMUX_810_PULLUP_CTRL0),
mask, mask);
break;
default:
@@ -575,18 +941,53 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
-static const struct pinconf_ops oxnas_pinconf_ops = {
- .pin_config_get = oxnas_pinconf_get,
- .pin_config_set = oxnas_pinconf_set,
+static int oxnas_ox820_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ unsigned int param;
+ u32 arg;
+ unsigned int i;
+ u32 offset = pin - bank->gpio_chip.base;
+ u32 mask = BIT(offset);
+
+ dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n",
+ pin, bank->gpio_chip.base, mask);
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ dev_dbg(pctl->dev, " pullup\n");
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_PULLUP_CTRL,
+ mask, mask);
+ break;
+ default:
+ dev_err(pctl->dev, "Property %u not supported\n",
+ param);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops oxnas_ox810se_pinconf_ops = {
+ .pin_config_get = oxnas_ox810se_pinconf_get,
+ .pin_config_set = oxnas_ox810se_pinconf_set,
.is_generic = true,
};
-static struct pinctrl_desc oxnas_pinctrl_desc = {
- .name = "oxnas-pinctrl",
- .pctlops = &oxnas_pinctrl_ops,
- .pmxops = &oxnas_pinmux_ops,
- .confops = &oxnas_pinconf_ops,
- .owner = THIS_MODULE,
+static const struct pinconf_ops oxnas_ox820_pinconf_ops = {
+ .pin_config_get = oxnas_ox820_pinconf_get,
+ .pin_config_set = oxnas_ox820_pinconf_set,
+ .is_generic = true,
};
static void oxnas_gpio_irq_ack(struct irq_data *data)
@@ -699,10 +1100,78 @@ static struct oxnas_gpio_bank oxnas_gpio_banks[] = {
GPIO_BANK(1),
};
+static struct oxnas_pinctrl ox810se_pinctrl = {
+ .functions = oxnas_ox810se_functions,
+ .nfunctions = ARRAY_SIZE(oxnas_ox810se_functions),
+ .groups = oxnas_ox810se_groups,
+ .ngroups = ARRAY_SIZE(oxnas_ox810se_groups),
+ .gpio_banks = oxnas_gpio_banks,
+ .nbanks = ARRAY_SIZE(oxnas_gpio_banks),
+};
+
+static struct pinctrl_desc oxnas_ox810se_pinctrl_desc = {
+ .name = "oxnas-pinctrl",
+ .pins = oxnas_ox810se_pins,
+ .npins = ARRAY_SIZE(oxnas_ox810se_pins),
+ .pctlops = &oxnas_pinctrl_ops,
+ .pmxops = &oxnas_ox810se_pinmux_ops,
+ .confops = &oxnas_ox810se_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static struct oxnas_pinctrl ox820_pinctrl = {
+ .functions = oxnas_ox820_functions,
+ .nfunctions = ARRAY_SIZE(oxnas_ox820_functions),
+ .groups = oxnas_ox820_groups,
+ .ngroups = ARRAY_SIZE(oxnas_ox820_groups),
+ .gpio_banks = oxnas_gpio_banks,
+ .nbanks = ARRAY_SIZE(oxnas_gpio_banks),
+};
+
+static struct pinctrl_desc oxnas_ox820_pinctrl_desc = {
+ .name = "oxnas-pinctrl",
+ .pins = oxnas_ox820_pins,
+ .npins = ARRAY_SIZE(oxnas_ox820_pins),
+ .pctlops = &oxnas_pinctrl_ops,
+ .pmxops = &oxnas_ox820_pinmux_ops,
+ .confops = &oxnas_ox820_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static struct oxnas_pinctrl_data oxnas_ox810se_pinctrl_data = {
+ .desc = &oxnas_ox810se_pinctrl_desc,
+ .pctl = &ox810se_pinctrl,
+};
+
+static struct oxnas_pinctrl_data oxnas_ox820_pinctrl_data = {
+ .desc = &oxnas_ox820_pinctrl_desc,
+ .pctl = &ox820_pinctrl,
+};
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+ { .compatible = "oxsemi,ox810se-pinctrl",
+ .data = &oxnas_ox810se_pinctrl_data
+ },
+ { .compatible = "oxsemi,ox820-pinctrl",
+ .data = &oxnas_ox820_pinctrl_data,
+ },
+ { },
+};
+
static int oxnas_pinctrl_probe(struct platform_device *pdev)
{
+ const struct of_device_id *id;
+ const struct oxnas_pinctrl_data *data;
struct oxnas_pinctrl *pctl;
+ id = of_match_node(oxnas_pinctrl_of_match, pdev->dev.of_node);
+ if (!id)
+ return -ENODEV;
+
+ data = id->data;
+ if (!data || !data->pctl || !data->desc)
+ return -EINVAL;
+
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
return -ENOMEM;
@@ -716,20 +1185,14 @@ static int oxnas_pinctrl_probe(struct platform_device *pdev)
return -ENODEV;
}
- pctl->pins = oxnas_pins;
- pctl->npins = ARRAY_SIZE(oxnas_pins);
- pctl->functions = oxnas_functions;
- pctl->nfunctions = ARRAY_SIZE(oxnas_functions);
- pctl->groups = oxnas_groups;
- pctl->ngroups = ARRAY_SIZE(oxnas_groups);
- pctl->gpio_banks = oxnas_gpio_banks;
- pctl->nbanks = ARRAY_SIZE(oxnas_gpio_banks);
-
- oxnas_pinctrl_desc.pins = pctl->pins;
- oxnas_pinctrl_desc.npins = pctl->npins;
+ pctl->functions = data->pctl->functions;
+ pctl->nfunctions = data->pctl->nfunctions;
+ pctl->groups = data->pctl->groups;
+ pctl->ngroups = data->pctl->ngroups;
+ pctl->gpio_banks = data->pctl->gpio_banks;
+ pctl->nbanks = data->pctl->nbanks;
- pctl->pctldev = pinctrl_register(&oxnas_pinctrl_desc,
- &pdev->dev, pctl);
+ pctl->pctldev = pinctrl_register(data->desc, &pdev->dev, pctl);
if (IS_ERR(pctl->pctldev)) {
dev_err(&pdev->dev, "Failed to register pinctrl device\n");
return PTR_ERR(pctl->pctldev);
@@ -805,11 +1268,6 @@ static int oxnas_gpio_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id oxnas_pinctrl_of_match[] = {
- { .compatible = "oxsemi,ox810se-pinctrl", },
- { },
-};
-
static struct platform_driver oxnas_pinctrl_driver = {
.driver = {
.name = "oxnas-pinctrl",
@@ -821,6 +1279,7 @@ static struct platform_driver oxnas_pinctrl_driver = {
static const struct of_device_id oxnas_gpio_of_match[] = {
{ .compatible = "oxsemi,ox810se-gpio", },
+ { .compatible = "oxsemi,ox820-gpio", },
{ },
};
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 49bf7dcb7ed8..08765f58253c 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -59,6 +59,7 @@
#define GPIO_LS_SYNC 0x60
enum rockchip_pinctrl_type {
+ RK1108,
RK2928,
RK3066B,
RK3188,
@@ -624,6 +625,65 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
return ret;
}
+#define RK1108_PULL_PMU_OFFSET 0x10
+#define RK1108_PULL_OFFSET 0x110
+#define RK1108_PULL_PINS_PER_REG 8
+#define RK1108_PULL_BITS_PER_PIN 2
+#define RK1108_PULL_BANK_STRIDE 16
+
+static void rk1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ *regmap = info->regmap_pmu;
+ *reg = RK1108_PULL_PMU_OFFSET;
+ } else {
+ *reg = RK1108_PULL_OFFSET;
+ *regmap = info->regmap_base;
+ /* correct the offset, as we're starting with the 2nd bank */
+ *reg -= 0x10;
+ *reg += bank->bank_num * RK1108_PULL_BANK_STRIDE;
+ }
+
+ *reg += ((pin_num / RK1108_PULL_PINS_PER_REG) * 4);
+ *bit = (pin_num % RK1108_PULL_PINS_PER_REG);
+ *bit *= RK1108_PULL_BITS_PER_PIN;
+}
+
+#define RK1108_DRV_PMU_OFFSET 0x20
+#define RK1108_DRV_GRF_OFFSET 0x210
+#define RK1108_DRV_BITS_PER_PIN 2
+#define RK1108_DRV_PINS_PER_REG 8
+#define RK1108_DRV_BANK_STRIDE 16
+
+static void rk1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ *regmap = info->regmap_pmu;
+ *reg = RK1108_DRV_PMU_OFFSET;
+ } else {
+ *regmap = info->regmap_base;
+ *reg = RK1108_DRV_GRF_OFFSET;
+
+ /* correct the offset, as we're starting with the 2nd bank */
+ *reg -= 0x10;
+ *reg += bank->bank_num * RK1108_DRV_BANK_STRIDE;
+ }
+
+ *reg += ((pin_num / RK1108_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RK1108_DRV_PINS_PER_REG;
+ *bit *= RK1108_DRV_BITS_PER_PIN;
+}
+
#define RK2928_PULL_OFFSET 0x118
#define RK2928_PULL_PINS_PER_REG 16
#define RK2928_PULL_BANK_STRIDE 8
@@ -1123,6 +1183,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
return !(data & BIT(bit))
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE;
+ case RK1108:
case RK3188:
case RK3288:
case RK3368:
@@ -1169,6 +1230,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
spin_unlock_irqrestore(&bank->slock, flags);
break;
+ case RK1108:
case RK3188:
case RK3288:
case RK3368:
@@ -1358,6 +1420,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
pull == PIN_CONFIG_BIAS_DISABLE);
case RK3066B:
return pull ? false : true;
+ case RK1108:
case RK3188:
case RK3288:
case RK3368:
@@ -2455,6 +2518,27 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
return 0;
}
+static struct rockchip_pin_bank rk1108_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+ IOMUX_SOURCE_PMU,
+ IOMUX_SOURCE_PMU,
+ IOMUX_SOURCE_PMU),
+ PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
+};
+
+static struct rockchip_pin_ctrl rk1108_pin_ctrl = {
+ .pin_banks = rk1108_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk1108_pin_banks),
+ .label = "RK1108-GPIO",
+ .type = RK1108,
+ .grf_mux_offset = 0x10,
+ .pmu_mux_offset = 0x0,
+ .pull_calc_reg = rk1108_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk1108_calc_drv_reg_and_bit,
+};
+
static struct rockchip_pin_bank rk2928_pin_banks[] = {
PIN_BANK(0, 32, "gpio0"),
PIN_BANK(1, 32, "gpio1"),
@@ -2684,6 +2768,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
};
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
+ { .compatible = "rockchip,rk1108-pinctrl",
+ .data = (void *)&rk1108_pin_ctrl },
{ .compatible = "rockchip,rk2928-pinctrl",
.data = (void *)&rk2928_pin_ctrl },
{ .compatible = "rockchip,rk3036-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index bfdf720db270..a5a0392ab817 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -31,12 +31,10 @@
#include <linux/platform_data/pinctrl-single.h>
#include "core.h"
+#include "devicetree.h"
#include "pinconf.h"
#define DRIVER_NAME "pinctrl-single"
-#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
-#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
-#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3)
#define PCS_OFF_DISABLED ~0U
/**
@@ -142,20 +140,6 @@ struct pcs_data {
};
/**
- * struct pcs_name - register name for a pin
- * @name: name of the pinctrl register
- *
- * REVISIT: We may want to make names optional in the pinctrl
- * framework as some drivers may not care about pin names to
- * avoid kernel bloat. The pin names can be deciphered by user
- * space tools using debugfs based on the register address and
- * SoC packaging information.
- */
-struct pcs_name {
- char name[PCS_REG_NAME_LEN];
-};
-
-/**
* struct pcs_soc_data - SoC specific settings
* @flags: initial SoC specific PCS_FEAT_xxx values
* @irq: optional interrupt for the controller
@@ -177,8 +161,11 @@ struct pcs_soc_data {
* @base: virtual address of the controller
* @size: size of the ioremapped area
* @dev: device entry
+ * @np: device tree node
* @pctl: pin controller device
* @flags: mask of PCS_FEAT_xxx values
+ * @missing_nr_pinctrl_cells: for legacy binding, may go away
+ * @socdata: soc specific data
* @lock: spinlock for register access
* @mutex: mutex protecting the lists
* @width: bits per mux register
@@ -186,8 +173,8 @@ struct pcs_soc_data {
* @fshift: function register shift
* @foff: value to turn mux off
* @fmax: max number of functions in fmask
- * @bits_per_pin:number of bits per pin
- * @names: array of register names for pins
+ * @bits_per_mux: number of bits per mux
+ * @bits_per_pin: number of bits per pin
* @pins: physical pins on the SoC
* @pgtree: pingroup index radix tree
* @ftree: function index radix tree
@@ -208,11 +195,13 @@ struct pcs_device {
void __iomem *base;
unsigned size;
struct device *dev;
+ struct device_node *np;
struct pinctrl_dev *pctl;
unsigned flags;
#define PCS_QUIRK_SHARED_IRQ (1 << 2)
#define PCS_FEAT_IRQ (1 << 1)
#define PCS_FEAT_PINCONF (1 << 0)
+ struct property *missing_nr_pinctrl_cells;
struct pcs_soc_data socdata;
raw_spinlock_t lock;
struct mutex mutex;
@@ -223,7 +212,6 @@ struct pcs_device {
unsigned fmax;
bool bits_per_mux;
unsigned bits_per_pin;
- struct pcs_name *names;
struct pcs_data pins;
struct radix_tree_root pgtree;
struct radix_tree_root ftree;
@@ -354,13 +342,17 @@ static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
{
struct pcs_device *pcs;
unsigned val, mux_bytes;
+ unsigned long offset;
+ size_t pa;
pcs = pinctrl_dev_get_drvdata(pctldev);
mux_bytes = pcs->width / BITS_PER_BYTE;
- val = pcs->read(pcs->base + pin * mux_bytes);
+ offset = pin * mux_bytes;
+ val = pcs->read(pcs->base + offset);
+ pa = pcs->res->start + offset;
- seq_printf(s, "%08x %s " , val, DRIVER_NAME);
+ seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
}
static void pcs_dt_free_map(struct pinctrl_dev *pctldev,
@@ -763,7 +755,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
{
struct pcs_soc_data *pcs_soc = &pcs->socdata;
struct pinctrl_pin_desc *pin;
- struct pcs_name *pn;
int i;
i = pcs->pins.cur;
@@ -786,10 +777,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
}
pin = &pcs->pins.pa[i];
- pn = &pcs->names[i];
- sprintf(pn->name, "%lx.%u",
- (unsigned long)pcs->res->start + offset, pin_pos);
- pin->name = pn->name;
pin->number = i;
pcs->pins.cur++;
@@ -827,12 +814,6 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
if (!pcs->pins.pa)
return -ENOMEM;
- pcs->names = devm_kzalloc(pcs->dev,
- sizeof(struct pcs_name) * nr_pins,
- GFP_KERNEL);
- if (!pcs->names)
- return -ENOMEM;
-
pcs->desc.pins = pcs->pins.pa;
pcs->desc.npins = nr_pins;
@@ -1146,21 +1127,17 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
unsigned *num_maps,
const char **pgnames)
{
+ const char *name = "pinctrl-single,pins";
struct pcs_func_vals *vals;
- const __be32 *mux;
- int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
+ int rows, *pins, found = 0, res = -ENOMEM, i;
struct pcs_function *function;
- mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
- if ((!mux) || (size < sizeof(*mux) * 2)) {
- dev_err(pcs->dev, "bad data for mux %s\n",
- np->name);
+ rows = pinctrl_count_index_with_args(np, name);
+ if (rows <= 0) {
+ dev_err(pcs->dev, "Ivalid number of rows: %d\n", rows);
return -EINVAL;
}
- size /= sizeof(*mux); /* Number of elements in array */
- rows = size / 2;
-
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
if (!vals)
return -ENOMEM;
@@ -1169,14 +1146,28 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
if (!pins)
goto free_vals;
- while (index < size) {
- unsigned offset, val;
+ for (i = 0; i < rows; i++) {
+ struct of_phandle_args pinctrl_spec;
+ unsigned int offset;
int pin;
- offset = be32_to_cpup(mux + index++);
- val = be32_to_cpup(mux + index++);
+ res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
+ if (res)
+ return res;
+
+ if (pinctrl_spec.args_count < 2) {
+ dev_err(pcs->dev, "invalid args_count for spec: %i\n",
+ pinctrl_spec.args_count);
+ break;
+ }
+
+ /* Index plus one value cell */
+ offset = pinctrl_spec.args[0];
vals[found].reg = pcs->base + offset;
- vals[found].val = val;
+ vals[found].val = pinctrl_spec.args[1];
+
+ dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n",
+ pinctrl_spec.np->name, offset, pinctrl_spec.args[1]);
pin = pcs_get_pin_by_offset(pcs, offset);
if (pin < 0) {
@@ -1190,8 +1181,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
pgnames[0] = np->name;
function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
- if (!function)
+ if (!function) {
+ res = -ENOMEM;
goto free_pins;
+ }
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
if (res < 0)
@@ -1226,36 +1219,24 @@ free_vals:
return res;
}
-#define PARAMS_FOR_BITS_PER_MUX 3
-
static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
struct device_node *np,
struct pinctrl_map **map,
unsigned *num_maps,
const char **pgnames)
{
+ const char *name = "pinctrl-single,bits";
struct pcs_func_vals *vals;
- const __be32 *mux;
- int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
+ int rows, *pins, found = 0, res = -ENOMEM, i;
int npins_in_row;
struct pcs_function *function;
- mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
-
- if (!mux) {
- dev_err(pcs->dev, "no valid property for %s\n", np->name);
- return -EINVAL;
- }
-
- if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) {
- dev_err(pcs->dev, "bad data for %s\n", np->name);
+ rows = pinctrl_count_index_with_args(np, name);
+ if (rows <= 0) {
+ dev_err(pcs->dev, "Invalid number of rows: %d\n", rows);
return -EINVAL;
}
- /* Number of elements in array */
- size /= sizeof(*mux);
-
- rows = size / PARAMS_FOR_BITS_PER_MUX;
npins_in_row = pcs->width / pcs->bits_per_pin;
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
@@ -1268,15 +1249,30 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
if (!pins)
goto free_vals;
- while (index < size) {
+ for (i = 0; i < rows; i++) {
+ struct of_phandle_args pinctrl_spec;
unsigned offset, val;
unsigned mask, bit_pos, val_pos, mask_pos, submask;
unsigned pin_num_from_lsb;
int pin;
- offset = be32_to_cpup(mux + index++);
- val = be32_to_cpup(mux + index++);
- mask = be32_to_cpup(mux + index++);
+ res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
+ if (res)
+ return res;
+
+ if (pinctrl_spec.args_count < 3) {
+ dev_err(pcs->dev, "invalid args_count for spec: %i\n",
+ pinctrl_spec.args_count);
+ break;
+ }
+
+ /* Index plus two value cells */
+ offset = pinctrl_spec.args[0];
+ val = pinctrl_spec.args[1];
+ mask = pinctrl_spec.args[2];
+
+ dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n",
+ pinctrl_spec.np->name, offset, val, mask);
/* Parse pins in each row from LSB */
while (mask) {
@@ -1319,8 +1315,10 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
pgnames[0] = np->name;
function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
- if (!function)
+ if (!function) {
+ res = -ENOMEM;
goto free_pins;
+ }
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
if (res < 0)
@@ -1494,17 +1492,12 @@ static void pcs_free_resources(struct pcs_device *pcs)
pinctrl_unregister(pcs->pctl);
pcs_free_funcs(pcs);
pcs_free_pingroups(pcs);
+#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
+ if (pcs->missing_nr_pinctrl_cells)
+ of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells);
+#endif
}
-#define PCS_GET_PROP_U32(name, reg, err) \
- do { \
- ret = of_property_read_u32(np, name, reg); \
- if (ret) { \
- dev_err(pcs->dev, err); \
- return ret; \
- } \
- } while (0);
-
static const struct of_device_id pcs_of_match[];
static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
@@ -1820,6 +1813,55 @@ static int pinctrl_single_resume(struct platform_device *pdev)
}
#endif
+/**
+ * pcs_quirk_missing_pinctrl_cells - handle legacy binding
+ * @pcs: pinctrl driver instance
+ * @np: device tree node
+ * @cells: number of cells
+ *
+ * Handle legacy binding with no #pinctrl-cells. This should be
+ * always two pinctrl-single,bit-per-mux and one for others.
+ * At some point we may want to consider removing this.
+ */
+static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs,
+ struct device_node *np,
+ int cells)
+{
+ struct property *p;
+ const char *name = "#pinctrl-cells";
+ int error;
+ u32 val;
+
+ error = of_property_read_u32(np, name, &val);
+ if (!error)
+ return 0;
+
+ dev_warn(pcs->dev, "please update dts to use %s = <%i>\n",
+ name, cells);
+
+ p = devm_kzalloc(pcs->dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->length = sizeof(__be32);
+ p->value = devm_kzalloc(pcs->dev, sizeof(__be32), GFP_KERNEL);
+ if (!p->value)
+ return -ENOMEM;
+ *(__be32 *)p->value = cpu_to_be32(cells);
+
+ p->name = devm_kstrdup(pcs->dev, name, GFP_KERNEL);
+ if (!p->name)
+ return -ENOMEM;
+
+ pcs->missing_nr_pinctrl_cells = p;
+
+#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
+ error = of_add_property(np, pcs->missing_nr_pinctrl_cells);
+#endif
+
+ return error;
+}
+
static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1840,6 +1882,7 @@ static int pcs_probe(struct platform_device *pdev)
return -ENOMEM;
}
pcs->dev = &pdev->dev;
+ pcs->np = np;
raw_spin_lock_init(&pcs->lock);
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
@@ -1849,8 +1892,13 @@ static int pcs_probe(struct platform_device *pdev)
pcs->flags = soc->flags;
memcpy(&pcs->socdata, soc, sizeof(*soc));
- PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
- "register width not specified\n");
+ ret = of_property_read_u32(np, "pinctrl-single,register-width",
+ &pcs->width);
+ if (ret) {
+ dev_err(pcs->dev, "register width not specified\n");
+
+ return ret;
+ }
ret = of_property_read_u32(np, "pinctrl-single,function-mask",
&pcs->fmask);
@@ -1871,6 +1919,13 @@ static int pcs_probe(struct platform_device *pdev)
pcs->bits_per_mux = of_property_read_bool(np,
"pinctrl-single,bit-per-mux");
+ ret = pcs_quirk_missing_pinctrl_cells(pcs, np,
+ pcs->bits_per_mux ? 2 : 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to patch #pinctrl-cells\n");
+
+ return ret;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index b7bb37167969..676efcc032d2 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -1006,7 +1006,7 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev,
function = st_pctl_get_pin_function(pc, offset);
if (function)
- snprintf(f, 10, "Alt Fn %d", function);
+ snprintf(f, 10, "Alt Fn %u", function);
else
snprintf(f, 5, "GPIO");
@@ -1181,7 +1181,7 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
if (!strcmp(pp->name, "name"))
continue;
- if (pp && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) {
+ if (pp->length / sizeof(__be32) >= OF_GPIO_ARGS_MIN) {
npins++;
} else {
pr_warn("Invalid st,pins in %s node\n", np->name);
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
new file mode 100644
index 000000000000..29fb7403d24e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -0,0 +1,1275 @@
+/*
+ * Copyright (c) 2016, BayLibre, SAS. All rights reserved.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * Driver for Semtech SX150X I2C GPIO Expanders
+ * The handling of the 4-bit chips (SX1501/SX1504/SX1507) is untested.
+ *
+ * Author: Gregory Bean <gbean@codeaurora.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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/regmap.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/gpio/driver.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+/* The chip models of sx150x */
+enum {
+ SX150X_123 = 0,
+ SX150X_456,
+ SX150X_789,
+};
+enum {
+ SX150X_789_REG_MISC_AUTOCLEAR_OFF = 1 << 0,
+ SX150X_MAX_REGISTER = 0xad,
+ SX150X_IRQ_TYPE_EDGE_RISING = 0x1,
+ SX150X_IRQ_TYPE_EDGE_FALLING = 0x2,
+ SX150X_789_RESET_KEY1 = 0x12,
+ SX150X_789_RESET_KEY2 = 0x34,
+};
+
+struct sx150x_123_pri {
+ u8 reg_pld_mode;
+ u8 reg_pld_table0;
+ u8 reg_pld_table1;
+ u8 reg_pld_table2;
+ u8 reg_pld_table3;
+ u8 reg_pld_table4;
+ u8 reg_advanced;
+};
+
+struct sx150x_456_pri {
+ u8 reg_pld_mode;
+ u8 reg_pld_table0;
+ u8 reg_pld_table1;
+ u8 reg_pld_table2;
+ u8 reg_pld_table3;
+ u8 reg_pld_table4;
+ u8 reg_advanced;
+};
+
+struct sx150x_789_pri {
+ u8 reg_drain;
+ u8 reg_polarity;
+ u8 reg_clock;
+ u8 reg_misc;
+ u8 reg_reset;
+ u8 ngpios;
+};
+
+struct sx150x_device_data {
+ u8 model;
+ u8 reg_pullup;
+ u8 reg_pulldn;
+ u8 reg_dir;
+ u8 reg_data;
+ u8 reg_irq_mask;
+ u8 reg_irq_src;
+ u8 reg_sense;
+ u8 ngpios;
+ union {
+ struct sx150x_123_pri x123;
+ struct sx150x_456_pri x456;
+ struct sx150x_789_pri x789;
+ } pri;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+};
+
+struct sx150x_pinctrl {
+ struct device *dev;
+ struct i2c_client *client;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc pinctrl_desc;
+ struct gpio_chip gpio;
+ struct irq_chip irq_chip;
+ struct regmap *regmap;
+ struct {
+ u32 sense;
+ u32 masked;
+ } irq;
+ struct mutex lock;
+ const struct sx150x_device_data *data;
+};
+
+static const struct pinctrl_pin_desc sx150x_4_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "oscio"),
+};
+
+static const struct pinctrl_pin_desc sx150x_8_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "oscio"),
+};
+
+static const struct pinctrl_pin_desc sx150x_16_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "oscio"),
+};
+
+static const struct sx150x_device_data sx1501q_device_data = {
+ .model = SX150X_123,
+ .reg_pullup = 0x02,
+ .reg_pulldn = 0x03,
+ .reg_dir = 0x01,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x05,
+ .reg_irq_src = 0x08,
+ .reg_sense = 0x07,
+ .pri.x123 = {
+ .reg_pld_mode = 0x10,
+ .reg_pld_table0 = 0x11,
+ .reg_pld_table2 = 0x13,
+ .reg_advanced = 0xad,
+ },
+ .ngpios = 4,
+ .pins = sx150x_4_pins,
+ .npins = 4, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1502q_device_data = {
+ .model = SX150X_123,
+ .reg_pullup = 0x02,
+ .reg_pulldn = 0x03,
+ .reg_dir = 0x01,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x05,
+ .reg_irq_src = 0x08,
+ .reg_sense = 0x06,
+ .pri.x123 = {
+ .reg_pld_mode = 0x10,
+ .reg_pld_table0 = 0x11,
+ .reg_pld_table1 = 0x12,
+ .reg_pld_table2 = 0x13,
+ .reg_pld_table3 = 0x14,
+ .reg_pld_table4 = 0x15,
+ .reg_advanced = 0xad,
+ },
+ .ngpios = 8,
+ .pins = sx150x_8_pins,
+ .npins = 8, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1503q_device_data = {
+ .model = SX150X_123,
+ .reg_pullup = 0x04,
+ .reg_pulldn = 0x06,
+ .reg_dir = 0x02,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x08,
+ .reg_irq_src = 0x0e,
+ .reg_sense = 0x0a,
+ .pri.x123 = {
+ .reg_pld_mode = 0x20,
+ .reg_pld_table0 = 0x22,
+ .reg_pld_table1 = 0x24,
+ .reg_pld_table2 = 0x26,
+ .reg_pld_table3 = 0x28,
+ .reg_pld_table4 = 0x2a,
+ .reg_advanced = 0xad,
+ },
+ .ngpios = 16,
+ .pins = sx150x_16_pins,
+ .npins = 16, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1504q_device_data = {
+ .model = SX150X_456,
+ .reg_pullup = 0x02,
+ .reg_pulldn = 0x03,
+ .reg_dir = 0x01,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x05,
+ .reg_irq_src = 0x08,
+ .reg_sense = 0x07,
+ .pri.x456 = {
+ .reg_pld_mode = 0x10,
+ .reg_pld_table0 = 0x11,
+ .reg_pld_table2 = 0x13,
+ },
+ .ngpios = 4,
+ .pins = sx150x_4_pins,
+ .npins = 4, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1505q_device_data = {
+ .model = SX150X_456,
+ .reg_pullup = 0x02,
+ .reg_pulldn = 0x03,
+ .reg_dir = 0x01,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x05,
+ .reg_irq_src = 0x08,
+ .reg_sense = 0x06,
+ .pri.x456 = {
+ .reg_pld_mode = 0x10,
+ .reg_pld_table0 = 0x11,
+ .reg_pld_table1 = 0x12,
+ .reg_pld_table2 = 0x13,
+ .reg_pld_table3 = 0x14,
+ .reg_pld_table4 = 0x15,
+ },
+ .ngpios = 8,
+ .pins = sx150x_8_pins,
+ .npins = 8, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1506q_device_data = {
+ .model = SX150X_456,
+ .reg_pullup = 0x04,
+ .reg_pulldn = 0x06,
+ .reg_dir = 0x02,
+ .reg_data = 0x00,
+ .reg_irq_mask = 0x08,
+ .reg_irq_src = 0x0e,
+ .reg_sense = 0x0a,
+ .pri.x456 = {
+ .reg_pld_mode = 0x20,
+ .reg_pld_table0 = 0x22,
+ .reg_pld_table1 = 0x24,
+ .reg_pld_table2 = 0x26,
+ .reg_pld_table3 = 0x28,
+ .reg_pld_table4 = 0x2a,
+ .reg_advanced = 0xad,
+ },
+ .ngpios = 16,
+ .pins = sx150x_16_pins,
+ .npins = 16, /* oscio not available */
+};
+
+static const struct sx150x_device_data sx1507q_device_data = {
+ .model = SX150X_789,
+ .reg_pullup = 0x03,
+ .reg_pulldn = 0x04,
+ .reg_dir = 0x07,
+ .reg_data = 0x08,
+ .reg_irq_mask = 0x09,
+ .reg_irq_src = 0x0b,
+ .reg_sense = 0x0a,
+ .pri.x789 = {
+ .reg_drain = 0x05,
+ .reg_polarity = 0x06,
+ .reg_clock = 0x0d,
+ .reg_misc = 0x0e,
+ .reg_reset = 0x7d,
+ },
+ .ngpios = 4,
+ .pins = sx150x_4_pins,
+ .npins = ARRAY_SIZE(sx150x_4_pins),
+};
+
+static const struct sx150x_device_data sx1508q_device_data = {
+ .model = SX150X_789,
+ .reg_pullup = 0x03,
+ .reg_pulldn = 0x04,
+ .reg_dir = 0x07,
+ .reg_data = 0x08,
+ .reg_irq_mask = 0x09,
+ .reg_irq_src = 0x0c,
+ .reg_sense = 0x0a,
+ .pri.x789 = {
+ .reg_drain = 0x05,
+ .reg_polarity = 0x06,
+ .reg_clock = 0x0f,
+ .reg_misc = 0x10,
+ .reg_reset = 0x7d,
+ },
+ .ngpios = 8,
+ .pins = sx150x_8_pins,
+ .npins = ARRAY_SIZE(sx150x_8_pins),
+};
+
+static const struct sx150x_device_data sx1509q_device_data = {
+ .model = SX150X_789,
+ .reg_pullup = 0x06,
+ .reg_pulldn = 0x08,
+ .reg_dir = 0x0e,
+ .reg_data = 0x10,
+ .reg_irq_mask = 0x12,
+ .reg_irq_src = 0x18,
+ .reg_sense = 0x14,
+ .pri.x789 = {
+ .reg_drain = 0x0a,
+ .reg_polarity = 0x0c,
+ .reg_clock = 0x1e,
+ .reg_misc = 0x1f,
+ .reg_reset = 0x7d,
+ },
+ .ngpios = 16,
+ .pins = sx150x_16_pins,
+ .npins = ARRAY_SIZE(sx150x_16_pins),
+};
+
+static int sx150x_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ return 0;
+}
+
+static const char *sx150x_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int group)
+{
+ return NULL;
+}
+
+static int sx150x_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ return -ENOTSUPP;
+}
+
+static const struct pinctrl_ops sx150x_pinctrl_ops = {
+ .get_groups_count = sx150x_pinctrl_get_groups_count,
+ .get_group_name = sx150x_pinctrl_get_group_name,
+ .get_group_pins = sx150x_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static bool sx150x_pin_is_oscio(struct sx150x_pinctrl *pctl, unsigned int pin)
+{
+ if (pin >= pctl->data->npins)
+ return false;
+
+ /* OSCIO pin is only present in 789 devices */
+ if (pctl->data->model != SX150X_789)
+ return false;
+
+ return !strcmp(pctl->data->pins[pin].name, "oscio");
+}
+
+static int sx150x_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+ unsigned int value;
+ int ret;
+
+ if (sx150x_pin_is_oscio(pctl, offset))
+ return false;
+
+ ret = regmap_read(pctl->regmap, pctl->data->reg_dir, &value);
+ if (ret < 0)
+ return ret;
+
+ return !!(value & BIT(offset));
+}
+
+static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+ unsigned int value;
+ int ret;
+
+ if (sx150x_pin_is_oscio(pctl, offset))
+ return -EINVAL;
+
+ ret = regmap_read(pctl->regmap, pctl->data->reg_data, &value);
+ if (ret < 0)
+ return ret;
+
+ return !!(value & BIT(offset));
+}
+
+static int sx150x_gpio_set_single_ended(struct gpio_chip *chip,
+ unsigned int offset,
+ enum single_ended_mode mode)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+ int ret;
+
+ switch (mode) {
+ case LINE_MODE_PUSH_PULL:
+ if (pctl->data->model != SX150X_789 ||
+ sx150x_pin_is_oscio(pctl, offset))
+ return 0;
+
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->pri.x789.reg_drain,
+ BIT(offset), 0);
+ break;
+
+ case LINE_MODE_OPEN_DRAIN:
+ if (pctl->data->model != SX150X_789 ||
+ sx150x_pin_is_oscio(pctl, offset))
+ return -ENOTSUPP;
+
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->pri.x789.reg_drain,
+ BIT(offset), BIT(offset));
+ break;
+ default:
+ ret = -ENOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset,
+ int value)
+{
+ return regmap_write_bits(pctl->regmap, pctl->data->reg_data,
+ BIT(offset), value ? BIT(offset) : 0);
+}
+
+static int sx150x_gpio_oscio_set(struct sx150x_pinctrl *pctl,
+ int value)
+{
+ return regmap_write(pctl->regmap,
+ pctl->data->pri.x789.reg_clock,
+ (value ? 0x1f : 0x10));
+}
+
+static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+
+ if (sx150x_pin_is_oscio(pctl, offset))
+ sx150x_gpio_oscio_set(pctl, value);
+ else
+ __sx150x_gpio_set(pctl, offset, value);
+
+}
+
+static void sx150x_gpio_set_multiple(struct gpio_chip *chip,
+ unsigned long *mask,
+ unsigned long *bits)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+
+ regmap_write_bits(pctl->regmap, pctl->data->reg_data, *mask, *bits);
+}
+
+static int sx150x_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+
+ if (sx150x_pin_is_oscio(pctl, offset))
+ return -EINVAL;
+
+ return regmap_write_bits(pctl->regmap,
+ pctl->data->reg_dir,
+ BIT(offset), BIT(offset));
+}
+
+static int sx150x_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
+ int ret;
+
+ if (sx150x_pin_is_oscio(pctl, offset))
+ return sx150x_gpio_oscio_set(pctl, value);
+
+ ret = __sx150x_gpio_set(pctl, offset, value);
+ if (ret < 0)
+ return ret;
+
+ return regmap_write_bits(pctl->regmap,
+ pctl->data->reg_dir,
+ BIT(offset), 0);
+}
+
+static void sx150x_irq_mask(struct irq_data *d)
+{
+ struct sx150x_pinctrl *pctl =
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ unsigned int n = d->hwirq;
+
+ pctl->irq.masked |= BIT(n);
+}
+
+static void sx150x_irq_unmask(struct irq_data *d)
+{
+ struct sx150x_pinctrl *pctl =
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ unsigned int n = d->hwirq;
+
+ pctl->irq.masked &= ~BIT(n);
+}
+
+static void sx150x_irq_set_sense(struct sx150x_pinctrl *pctl,
+ unsigned int line, unsigned int sense)
+{
+ /*
+ * Every interrupt line is represented by two bits shifted
+ * proportionally to the line number
+ */
+ const unsigned int n = line * 2;
+ const unsigned int mask = ~((SX150X_IRQ_TYPE_EDGE_RISING |
+ SX150X_IRQ_TYPE_EDGE_FALLING) << n);
+
+ pctl->irq.sense &= mask;
+ pctl->irq.sense |= sense << n;
+}
+
+static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ struct sx150x_pinctrl *pctl =
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ unsigned int n, val = 0;
+
+ if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+ return -EINVAL;
+
+ n = d->hwirq;
+
+ if (flow_type & IRQ_TYPE_EDGE_RISING)
+ val |= SX150X_IRQ_TYPE_EDGE_RISING;
+ if (flow_type & IRQ_TYPE_EDGE_FALLING)
+ val |= SX150X_IRQ_TYPE_EDGE_FALLING;
+
+ sx150x_irq_set_sense(pctl, n, val);
+ return 0;
+}
+
+static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
+{
+ struct sx150x_pinctrl *pctl = (struct sx150x_pinctrl *)dev_id;
+ unsigned long n, status;
+ unsigned int val;
+ int err;
+
+ err = regmap_read(pctl->regmap, pctl->data->reg_irq_src, &val);
+ if (err < 0)
+ return IRQ_NONE;
+
+ err = regmap_write(pctl->regmap, pctl->data->reg_irq_src, val);
+ if (err < 0)
+ return IRQ_NONE;
+
+ status = val;
+ for_each_set_bit(n, &status, pctl->data->ngpios)
+ handle_nested_irq(irq_find_mapping(pctl->gpio.irqdomain, n));
+
+ return IRQ_HANDLED;
+}
+
+static void sx150x_irq_bus_lock(struct irq_data *d)
+{
+ struct sx150x_pinctrl *pctl =
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+
+ mutex_lock(&pctl->lock);
+}
+
+static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct sx150x_pinctrl *pctl =
+ gpiochip_get_data(irq_data_get_irq_chip_data(d));
+
+ regmap_write(pctl->regmap, pctl->data->reg_irq_mask, pctl->irq.masked);
+ regmap_write(pctl->regmap, pctl->data->reg_sense, pctl->irq.sense);
+ mutex_unlock(&pctl->lock);
+}
+
+static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config)
+{
+ struct sx150x_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int param = pinconf_to_config_param(*config);
+ int ret;
+ u32 arg;
+ unsigned int data;
+
+ if (sx150x_pin_is_oscio(pctl, pin)) {
+ switch (param) {
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ case PIN_CONFIG_OUTPUT:
+ ret = regmap_read(pctl->regmap,
+ pctl->data->pri.x789.reg_clock,
+ &data);
+ if (ret < 0)
+ return ret;
+
+ if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
+ arg = (data & 0x1f) ? 1 : 0;
+ else {
+ if ((data & 0x1f) == 0x1f)
+ arg = 1;
+ else if ((data & 0x1f) == 0x10)
+ arg = 0;
+ else
+ return -EINVAL;
+ }
+
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ goto out;
+ }
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ret = regmap_read(pctl->regmap,
+ pctl->data->reg_pulldn,
+ &data);
+ data &= BIT(pin);
+
+ if (ret < 0)
+ return ret;
+
+ if (!ret)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = regmap_read(pctl->regmap,
+ pctl->data->reg_pullup,
+ &data);
+ data &= BIT(pin);
+
+ if (ret < 0)
+ return ret;
+
+ if (!ret)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (pctl->data->model != SX150X_789)
+ return -ENOTSUPP;
+
+ ret = regmap_read(pctl->regmap,
+ pctl->data->pri.x789.reg_drain,
+ &data);
+ data &= BIT(pin);
+
+ if (ret < 0)
+ return ret;
+
+ if (!data)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (pctl->data->model != SX150X_789)
+ arg = true;
+ else {
+ ret = regmap_read(pctl->regmap,
+ pctl->data->pri.x789.reg_drain,
+ &data);
+ data &= BIT(pin);
+
+ if (ret < 0)
+ return ret;
+
+ if (data)
+ return -EINVAL;
+
+ arg = 1;
+ }
+ break;
+
+ case PIN_CONFIG_OUTPUT:
+ ret = sx150x_gpio_get_direction(&pctl->gpio, pin);
+ if (ret < 0)
+ return ret;
+
+ if (ret)
+ return -EINVAL;
+
+ ret = sx150x_gpio_get(&pctl->gpio, pin);
+ if (ret < 0)
+ return ret;
+
+ arg = ret;
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+out:
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct sx150x_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param;
+ u32 arg;
+ int i;
+ int ret;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ if (sx150x_pin_is_oscio(pctl, pin)) {
+ if (param == PIN_CONFIG_OUTPUT) {
+ ret = sx150x_gpio_direction_output(&pctl->gpio,
+ pin, arg);
+ if (ret < 0)
+ return ret;
+
+ continue;
+ } else
+ return -ENOTSUPP;
+ }
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+ case PIN_CONFIG_BIAS_DISABLE:
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->reg_pulldn,
+ BIT(pin), 0);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->reg_pullup,
+ BIT(pin), 0);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->reg_pullup,
+ BIT(pin), BIT(pin));
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ret = regmap_write_bits(pctl->regmap,
+ pctl->data->reg_pulldn,
+ BIT(pin), BIT(pin));
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ ret = sx150x_gpio_set_single_ended(&pctl->gpio,
+ pin, LINE_MODE_OPEN_DRAIN);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ ret = sx150x_gpio_set_single_ended(&pctl->gpio,
+ pin, LINE_MODE_PUSH_PULL);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case PIN_CONFIG_OUTPUT:
+ ret = sx150x_gpio_direction_output(&pctl->gpio,
+ pin, arg);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+ } /* for each config */
+
+ return 0;
+}
+
+static const struct pinconf_ops sx150x_pinconf_ops = {
+ .pin_config_get = sx150x_pinconf_get,
+ .pin_config_set = sx150x_pinconf_set,
+ .is_generic = true,
+};
+
+static const struct i2c_device_id sx150x_id[] = {
+ {"sx1501q", (kernel_ulong_t) &sx1501q_device_data },
+ {"sx1502q", (kernel_ulong_t) &sx1502q_device_data },
+ {"sx1503q", (kernel_ulong_t) &sx1503q_device_data },
+ {"sx1504q", (kernel_ulong_t) &sx1504q_device_data },
+ {"sx1505q", (kernel_ulong_t) &sx1505q_device_data },
+ {"sx1506q", (kernel_ulong_t) &sx1506q_device_data },
+ {"sx1507q", (kernel_ulong_t) &sx1507q_device_data },
+ {"sx1508q", (kernel_ulong_t) &sx1508q_device_data },
+ {"sx1509q", (kernel_ulong_t) &sx1509q_device_data },
+ {}
+};
+
+static const struct of_device_id sx150x_of_match[] = {
+ { .compatible = "semtech,sx1501q", .data = &sx1501q_device_data },
+ { .compatible = "semtech,sx1502q", .data = &sx1502q_device_data },
+ { .compatible = "semtech,sx1503q", .data = &sx1503q_device_data },
+ { .compatible = "semtech,sx1504q", .data = &sx1504q_device_data },
+ { .compatible = "semtech,sx1505q", .data = &sx1505q_device_data },
+ { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data },
+ { .compatible = "semtech,sx1507q", .data = &sx1507q_device_data },
+ { .compatible = "semtech,sx1508q", .data = &sx1508q_device_data },
+ { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data },
+ {},
+};
+
+static int sx150x_reset(struct sx150x_pinctrl *pctl)
+{
+ int err;
+
+ err = i2c_smbus_write_byte_data(pctl->client,
+ pctl->data->pri.x789.reg_reset,
+ SX150X_789_RESET_KEY1);
+ if (err < 0)
+ return err;
+
+ err = i2c_smbus_write_byte_data(pctl->client,
+ pctl->data->pri.x789.reg_reset,
+ SX150X_789_RESET_KEY2);
+ return err;
+}
+
+static int sx150x_init_misc(struct sx150x_pinctrl *pctl)
+{
+ u8 reg, value;
+
+ switch (pctl->data->model) {
+ case SX150X_789:
+ reg = pctl->data->pri.x789.reg_misc;
+ value = SX150X_789_REG_MISC_AUTOCLEAR_OFF;
+ break;
+ case SX150X_456:
+ reg = pctl->data->pri.x456.reg_advanced;
+ value = 0x00;
+
+ /*
+ * Only SX1506 has RegAdvanced, SX1504/5 are expected
+ * to initialize this offset to zero
+ */
+ if (!reg)
+ return 0;
+ break;
+ case SX150X_123:
+ reg = pctl->data->pri.x123.reg_advanced;
+ value = 0x00;
+ break;
+ default:
+ WARN(1, "Unknown chip model %d\n", pctl->data->model);
+ return -EINVAL;
+ }
+
+ return regmap_write(pctl->regmap, reg, value);
+}
+
+static int sx150x_init_hw(struct sx150x_pinctrl *pctl)
+{
+ const u8 reg[] = {
+ [SX150X_789] = pctl->data->pri.x789.reg_polarity,
+ [SX150X_456] = pctl->data->pri.x456.reg_pld_mode,
+ [SX150X_123] = pctl->data->pri.x123.reg_pld_mode,
+ };
+ int err;
+
+ if (pctl->data->model == SX150X_789 &&
+ of_property_read_bool(pctl->dev->of_node, "semtech,probe-reset")) {
+ err = sx150x_reset(pctl);
+ if (err < 0)
+ return err;
+ }
+
+ err = sx150x_init_misc(pctl);
+ if (err < 0)
+ return err;
+
+ /* Set all pins to work in normal mode */
+ return regmap_write(pctl->regmap, reg[pctl->data->model], 0);
+}
+
+static int sx150x_regmap_reg_width(struct sx150x_pinctrl *pctl,
+ unsigned int reg)
+{
+ const struct sx150x_device_data *data = pctl->data;
+
+ if (reg == data->reg_sense) {
+ /*
+ * RegSense packs two bits of configuration per GPIO,
+ * so we'd need to read twice as many bits as there
+ * are GPIO in our chip
+ */
+ return 2 * data->ngpios;
+ } else if ((data->model == SX150X_789 &&
+ (reg == data->pri.x789.reg_misc ||
+ reg == data->pri.x789.reg_clock ||
+ reg == data->pri.x789.reg_reset))
+ ||
+ (data->model == SX150X_123 &&
+ reg == data->pri.x123.reg_advanced)
+ ||
+ (data->model == SX150X_456 &&
+ data->pri.x456.reg_advanced &&
+ reg == data->pri.x456.reg_advanced)) {
+ return 8;
+ } else {
+ return data->ngpios;
+ }
+}
+
+static unsigned int sx150x_maybe_swizzle(struct sx150x_pinctrl *pctl,
+ unsigned int reg, unsigned int val)
+{
+ unsigned int a, b;
+ const struct sx150x_device_data *data = pctl->data;
+
+ /*
+ * Whereas SX1509 presents RegSense in a simple layout as such:
+ * reg [ f f e e d d c c ]
+ * reg + 1 [ b b a a 9 9 8 8 ]
+ * reg + 2 [ 7 7 6 6 5 5 4 4 ]
+ * reg + 3 [ 3 3 2 2 1 1 0 0 ]
+ *
+ * SX1503 and SX1506 deviate from that data layout, instead storing
+ * their contents as follows:
+ *
+ * reg [ f f e e d d c c ]
+ * reg + 1 [ 7 7 6 6 5 5 4 4 ]
+ * reg + 2 [ b b a a 9 9 8 8 ]
+ * reg + 3 [ 3 3 2 2 1 1 0 0 ]
+ *
+ * so, taking that into account, we swap two
+ * inner bytes of a 4-byte result
+ */
+
+ if (reg == data->reg_sense &&
+ data->ngpios == 16 &&
+ (data->model == SX150X_123 ||
+ data->model == SX150X_456)) {
+ a = val & 0x00ff0000;
+ b = val & 0x0000ff00;
+
+ val &= 0xff0000ff;
+ val |= b << 8;
+ val |= a >> 8;
+ }
+
+ return val;
+}
+
+/*
+ * In order to mask the differences between 16 and 8 bit expander
+ * devices we set up a sligthly ficticious regmap that pretends to be
+ * a set of 32-bit (to accomodate RegSenseLow/RegSenseHigh
+ * pair/quartet) registers and transparently reconstructs those
+ * registers via multiple I2C/SMBus reads
+ *
+ * This way the rest of the driver code, interfacing with the chip via
+ * regmap API, can work assuming that each GPIO pin is represented by
+ * a group of bits at an offset proportional to GPIO number within a
+ * given register.
+ */
+static int sx150x_regmap_reg_read(void *context, unsigned int reg,
+ unsigned int *result)
+{
+ int ret, n;
+ struct sx150x_pinctrl *pctl = context;
+ struct i2c_client *i2c = pctl->client;
+ const int width = sx150x_regmap_reg_width(pctl, reg);
+ unsigned int idx, val;
+
+ /*
+ * There are four potential cases covered by this function:
+ *
+ * 1) 8-pin chip, single configuration bit register
+ *
+ * This is trivial the code below just needs to read:
+ * reg [ 7 6 5 4 3 2 1 0 ]
+ *
+ * 2) 8-pin chip, double configuration bit register (RegSense)
+ *
+ * The read will be done as follows:
+ * reg [ 7 7 6 6 5 5 4 4 ]
+ * reg + 1 [ 3 3 2 2 1 1 0 0 ]
+ *
+ * 3) 16-pin chip, single configuration bit register
+ *
+ * The read will be done as follows:
+ * reg [ f e d c b a 9 8 ]
+ * reg + 1 [ 7 6 5 4 3 2 1 0 ]
+ *
+ * 4) 16-pin chip, double configuration bit register (RegSense)
+ *
+ * The read will be done as follows:
+ * reg [ f f e e d d c c ]
+ * reg + 1 [ b b a a 9 9 8 8 ]
+ * reg + 2 [ 7 7 6 6 5 5 4 4 ]
+ * reg + 3 [ 3 3 2 2 1 1 0 0 ]
+ */
+
+ for (n = width, val = 0, idx = reg; n > 0; n -= 8, idx++) {
+ val <<= 8;
+
+ ret = i2c_smbus_read_byte_data(i2c, idx);
+ if (ret < 0)
+ return ret;
+
+ val |= ret;
+ }
+
+ *result = sx150x_maybe_swizzle(pctl, reg, val);
+
+ return 0;
+}
+
+static int sx150x_regmap_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ int ret, n;
+ struct sx150x_pinctrl *pctl = context;
+ struct i2c_client *i2c = pctl->client;
+ const int width = sx150x_regmap_reg_width(pctl, reg);
+
+ val = sx150x_maybe_swizzle(pctl, reg, val);
+
+ n = (width - 1) & ~7;
+ do {
+ const u8 byte = (val >> n) & 0xff;
+
+ ret = i2c_smbus_write_byte_data(i2c, reg, byte);
+ if (ret < 0)
+ return ret;
+
+ reg++;
+ n -= 8;
+ } while (n >= 0);
+
+ return 0;
+}
+
+static bool sx150x_reg_volatile(struct device *dev, unsigned int reg)
+{
+ struct sx150x_pinctrl *pctl = i2c_get_clientdata(to_i2c_client(dev));
+
+ return reg == pctl->data->reg_irq_src || reg == pctl->data->reg_data;
+}
+
+const struct regmap_config sx150x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_read = sx150x_regmap_reg_read,
+ .reg_write = sx150x_regmap_reg_write,
+
+ .max_register = SX150X_MAX_REGISTER,
+ .volatile_reg = sx150x_reg_volatile,
+};
+
+static int sx150x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+ struct device *dev = &client->dev;
+ struct sx150x_pinctrl *pctl;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, i2c_funcs))
+ return -ENOSYS;
+
+ pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, pctl);
+
+ pctl->dev = dev;
+ pctl->client = client;
+
+ if (dev->of_node)
+ pctl->data = of_device_get_match_data(dev);
+ else
+ pctl->data = (struct sx150x_device_data *)id->driver_data;
+
+ if (!pctl->data)
+ return -EINVAL;
+
+ pctl->regmap = devm_regmap_init(dev, NULL, pctl,
+ &sx150x_regmap_config);
+ if (IS_ERR(pctl->regmap)) {
+ ret = PTR_ERR(pctl->regmap);
+ dev_err(dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ mutex_init(&pctl->lock);
+
+ ret = sx150x_init_hw(pctl);
+ if (ret)
+ return ret;
+
+ /* Register GPIO controller */
+ pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL);
+ pctl->gpio.base = -1;
+ pctl->gpio.ngpio = pctl->data->npins;
+ pctl->gpio.get_direction = sx150x_gpio_get_direction;
+ pctl->gpio.direction_input = sx150x_gpio_direction_input;
+ pctl->gpio.direction_output = sx150x_gpio_direction_output;
+ pctl->gpio.get = sx150x_gpio_get;
+ pctl->gpio.set = sx150x_gpio_set;
+ pctl->gpio.set_single_ended = sx150x_gpio_set_single_ended;
+ pctl->gpio.parent = dev;
+#ifdef CONFIG_OF_GPIO
+ pctl->gpio.of_node = dev->of_node;
+#endif
+ pctl->gpio.can_sleep = true;
+ /*
+ * Setting multiple pins is not safe when all pins are not
+ * handled by the same regmap register. The oscio pin (present
+ * on the SX150X_789 chips) lives in its own register, so
+ * would require locking that is not in place at this time.
+ */
+ if (pctl->data->model != SX150X_789)
+ pctl->gpio.set_multiple = sx150x_gpio_set_multiple;
+
+ ret = devm_gpiochip_add_data(dev, &pctl->gpio, pctl);
+ if (ret)
+ return ret;
+
+ /* Add Interrupt support if an irq is specified */
+ if (client->irq > 0) {
+ pctl->irq_chip.name = devm_kstrdup(dev, client->name,
+ GFP_KERNEL);
+ pctl->irq_chip.irq_mask = sx150x_irq_mask;
+ pctl->irq_chip.irq_unmask = sx150x_irq_unmask;
+ pctl->irq_chip.irq_set_type = sx150x_irq_set_type;
+ pctl->irq_chip.irq_bus_lock = sx150x_irq_bus_lock;
+ pctl->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
+
+ pctl->irq.masked = ~0;
+ pctl->irq.sense = 0;
+
+ /*
+ * Because sx150x_irq_threaded_fn invokes all of the
+ * nested interrrupt handlers via handle_nested_irq,
+ * any "handler" passed to gpiochip_irqchip_add()
+ * below is going to be ignored, so the choice of the
+ * function does not matter that much.
+ *
+ * We set it to handle_bad_irq to avoid confusion,
+ * plus it will be instantly noticeable if it is ever
+ * called (should not happen)
+ */
+ ret = gpiochip_irqchip_add_nested(&pctl->gpio,
+ &pctl->irq_chip, 0,
+ handle_bad_irq, IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(dev, "could not connect irqchip to gpiochip\n");
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ sx150x_irq_thread_fn,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING,
+ pctl->irq_chip.name, pctl);
+ if (ret < 0)
+ return ret;
+
+ gpiochip_set_nested_irqchip(&pctl->gpio,
+ &pctl->irq_chip,
+ client->irq);
+ }
+
+ /* Pinctrl_desc */
+ pctl->pinctrl_desc.name = "sx150x-pinctrl";
+ pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops;
+ pctl->pinctrl_desc.confops = &sx150x_pinconf_ops;
+ pctl->pinctrl_desc.pins = pctl->data->pins;
+ pctl->pinctrl_desc.npins = pctl->data->npins;
+ pctl->pinctrl_desc.owner = THIS_MODULE;
+
+ pctl->pctldev = pinctrl_register(&pctl->pinctrl_desc, dev, pctl);
+ if (IS_ERR(pctl->pctldev)) {
+ dev_err(dev, "Failed to register pinctrl device\n");
+ return PTR_ERR(pctl->pctldev);
+ }
+
+ return 0;
+}
+
+static struct i2c_driver sx150x_driver = {
+ .driver = {
+ .name = "sx150x-pinctrl",
+ .of_match_table = of_match_ptr(sx150x_of_match),
+ },
+ .probe = sx150x_probe,
+ .id_table = sx150x_id,
+};
+
+static int __init sx150x_init(void)
+{
+ return i2c_add_driver(&sx150x_driver);
+}
+subsys_initcall(sx150x_init);
diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c
index e0ecffcbe11f..b51a46dfdcc3 100644
--- a/drivers/pinctrl/pinctrl-zynq.c
+++ b/drivers/pinctrl/pinctrl-zynq.c
@@ -247,6 +247,8 @@ static const unsigned int smc0_nor_addr25_pins[] = {1};
static const unsigned int smc0_nand_pins[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 16, 17, 18, 19, 20,
21, 22, 23};
+static const unsigned int smc0_nand8_pins[] = {0, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14};
/* Note: CAN MIO clock inputs are modeled in the clock framework */
static const unsigned int can0_0_pins[] = {10, 11};
static const unsigned int can0_1_pins[] = {14, 15};
@@ -445,6 +447,7 @@ static const struct zynq_pctrl_group zynq_pctrl_groups[] = {
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_cs1),
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_addr25),
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand),
+ DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand8),
DEFINE_ZYNQ_PINCTRL_GRP(can0_0),
DEFINE_ZYNQ_PINCTRL_GRP(can0_1),
DEFINE_ZYNQ_PINCTRL_GRP(can0_2),
@@ -709,7 +712,8 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp",
static const char * const smc0_nor_groups[] = {"smc0_nor_grp"};
static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"};
static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"};
-static const char * const smc0_nand_groups[] = {"smc0_nand_grp"};
+static const char * const smc0_nand_groups[] = {"smc0_nand_grp",
+ "smc0_nand8_grp"};
static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp",
"can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp",
"can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp",
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 93ef268d5ccd..3ebdc01f53c0 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -79,6 +79,15 @@ config PINCTRL_MSM8916
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found on the Qualcomm 8916 platform.
+config PINCTRL_MSM8994
+ tristate "Qualcomm 8994 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8994 platform. The
+ Qualcomm 8992 platform is also supported by this driver.
+
config PINCTRL_MSM8996
tristate "Qualcomm MSM8996 pin controller driver"
depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 8319e11cecb5..ab47764dbc5c 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
+obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o
obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c
new file mode 100644
index 000000000000..8e16d9ae0c39
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (c) 2016, 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname) \
+ [MSM_MUX_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ MSM_MUX_gpio, \
+ MSM_MUX_##f1, \
+ MSM_MUX_##f2, \
+ MSM_MUX_##f3, \
+ MSM_MUX_##f4, \
+ MSM_MUX_##f5, \
+ MSM_MUX_##f6, \
+ MSM_MUX_##f7, \
+ MSM_MUX_##f8, \
+ MSM_MUX_##f9, \
+ MSM_MUX_##f10, \
+ MSM_MUX_##f11 \
+ }, \
+ .nfuncs = 12, \
+ .ctl_reg = 0x1000 + 0x10 * id, \
+ .io_reg = 0x1004 + 0x10 * id, \
+ .intr_cfg_reg = 0x1008 + 0x10 * id, \
+ .intr_status_reg = 0x100c + 0x10 * id, \
+ .intr_target_reg = 0x1008 + 0x10 * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 4, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_target_kpss_val = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc msm8994_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, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "SDC1_RCLK"),
+ PINCTRL_PIN(147, "SDC1_CLK"),
+ PINCTRL_PIN(148, "SDC1_CMD"),
+ PINCTRL_PIN(149, "SDC1_DATA"),
+ PINCTRL_PIN(150, "SDC2_CLK"),
+ PINCTRL_PIN(151, "SDC2_CMD"),
+ PINCTRL_PIN(152, "SDC2_DATA"),
+ PINCTRL_PIN(153, "SDC3_CLK"),
+ PINCTRL_PIN(154, "SDC3_CMD"),
+ PINCTRL_PIN(155, "SDC3_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+
+static const unsigned int sdc1_rclk_pins[] = { 146 };
+static const unsigned int sdc1_clk_pins[] = { 147 };
+static const unsigned int sdc1_cmd_pins[] = { 148 };
+static const unsigned int sdc1_data_pins[] = { 149 };
+static const unsigned int sdc2_clk_pins[] = { 150 };
+static const unsigned int sdc2_cmd_pins[] = { 151 };
+static const unsigned int sdc2_data_pins[] = { 152 };
+static const unsigned int sdc3_clk_pins[] = { 153 };
+static const unsigned int sdc3_cmd_pins[] = { 154 };
+static const unsigned int sdc3_data_pins[] = { 155 };
+
+enum msm8994_functions {
+ MSM_MUX_audio_ref_clk,
+ MSM_MUX_blsp_i2c1,
+ MSM_MUX_blsp_i2c2,
+ MSM_MUX_blsp_i2c3,
+ MSM_MUX_blsp_i2c4,
+ MSM_MUX_blsp_i2c5,
+ MSM_MUX_blsp_i2c6,
+ MSM_MUX_blsp_i2c7,
+ MSM_MUX_blsp_i2c8,
+ MSM_MUX_blsp_i2c9,
+ MSM_MUX_blsp_i2c10,
+ MSM_MUX_blsp_i2c11,
+ MSM_MUX_blsp_i2c12,
+ MSM_MUX_blsp_spi1,
+ MSM_MUX_blsp_spi1_cs1,
+ MSM_MUX_blsp_spi1_cs2,
+ MSM_MUX_blsp_spi1_cs3,
+ MSM_MUX_blsp_spi2,
+ MSM_MUX_blsp_spi2_cs1,
+ MSM_MUX_blsp_spi2_cs2,
+ MSM_MUX_blsp_spi2_cs3,
+ MSM_MUX_blsp_spi3,
+ MSM_MUX_blsp_spi4,
+ MSM_MUX_blsp_spi5,
+ MSM_MUX_blsp_spi6,
+ MSM_MUX_blsp_spi7,
+ MSM_MUX_blsp_spi8,
+ MSM_MUX_blsp_spi9,
+ MSM_MUX_blsp_spi10,
+ MSM_MUX_blsp_spi10_cs1,
+ MSM_MUX_blsp_spi10_cs2,
+ MSM_MUX_blsp_spi10_cs3,
+ MSM_MUX_blsp_spi11,
+ MSM_MUX_blsp_spi12,
+ MSM_MUX_blsp_uart1,
+ MSM_MUX_blsp_uart2,
+ MSM_MUX_blsp_uart3,
+ MSM_MUX_blsp_uart4,
+ MSM_MUX_blsp_uart5,
+ MSM_MUX_blsp_uart6,
+ MSM_MUX_blsp_uart7,
+ MSM_MUX_blsp_uart8,
+ MSM_MUX_blsp_uart9,
+ MSM_MUX_blsp_uart10,
+ MSM_MUX_blsp_uart11,
+ MSM_MUX_blsp_uart12,
+ MSM_MUX_blsp_uim1,
+ MSM_MUX_blsp_uim2,
+ MSM_MUX_blsp_uim3,
+ MSM_MUX_blsp_uim4,
+ MSM_MUX_blsp_uim5,
+ MSM_MUX_blsp_uim6,
+ MSM_MUX_blsp_uim7,
+ MSM_MUX_blsp_uim8,
+ MSM_MUX_blsp_uim9,
+ MSM_MUX_blsp_uim10,
+ MSM_MUX_blsp_uim11,
+ MSM_MUX_blsp_uim12,
+ MSM_MUX_blsp11_i2c_scl_b,
+ MSM_MUX_blsp11_i2c_sda_b,
+ MSM_MUX_blsp11_uart_rx_b,
+ MSM_MUX_blsp11_uart_tx_b,
+ MSM_MUX_cam_mclk0,
+ MSM_MUX_cam_mclk1,
+ MSM_MUX_cam_mclk2,
+ MSM_MUX_cam_mclk3,
+ MSM_MUX_cci_async_in0,
+ MSM_MUX_cci_async_in1,
+ MSM_MUX_cci_async_in2,
+ MSM_MUX_cci_i2c0,
+ MSM_MUX_cci_i2c1,
+ MSM_MUX_cci_timer0,
+ MSM_MUX_cci_timer1,
+ MSM_MUX_cci_timer2,
+ MSM_MUX_cci_timer3,
+ MSM_MUX_cci_timer4,
+ MSM_MUX_gcc_gp1_clk_a,
+ MSM_MUX_gcc_gp1_clk_b,
+ MSM_MUX_gcc_gp2_clk_a,
+ MSM_MUX_gcc_gp2_clk_b,
+ MSM_MUX_gcc_gp3_clk_a,
+ MSM_MUX_gcc_gp3_clk_b,
+ MSM_MUX_gp_mn,
+ MSM_MUX_gp_pdm0,
+ MSM_MUX_gp_pdm1,
+ MSM_MUX_gp_pdm2,
+ MSM_MUX_gp0_clk,
+ MSM_MUX_gp1_clk,
+ MSM_MUX_gps_tx,
+ MSM_MUX_gsm_tx,
+ MSM_MUX_hdmi_cec,
+ MSM_MUX_hdmi_ddc,
+ MSM_MUX_hdmi_hpd,
+ MSM_MUX_hdmi_rcv,
+ MSM_MUX_mdp_vsync,
+ MSM_MUX_mss_lte,
+ MSM_MUX_nav_pps,
+ MSM_MUX_nav_tsync,
+ MSM_MUX_qdss_cti_trig_in_a,
+ MSM_MUX_qdss_cti_trig_in_b,
+ MSM_MUX_qdss_cti_trig_in_c,
+ MSM_MUX_qdss_cti_trig_in_d,
+ MSM_MUX_qdss_cti_trig_out_a,
+ MSM_MUX_qdss_cti_trig_out_b,
+ MSM_MUX_qdss_cti_trig_out_c,
+ MSM_MUX_qdss_cti_trig_out_d,
+ MSM_MUX_qdss_traceclk_a,
+ MSM_MUX_qdss_traceclk_b,
+ MSM_MUX_qdss_tracectl_a,
+ MSM_MUX_qdss_tracectl_b,
+ MSM_MUX_qdss_tracedata_a,
+ MSM_MUX_qdss_tracedata_b,
+ MSM_MUX_qua_mi2s,
+ MSM_MUX_pci_e0,
+ MSM_MUX_pci_e1,
+ MSM_MUX_pri_mi2s,
+ MSM_MUX_sdc4,
+ MSM_MUX_sec_mi2s,
+ MSM_MUX_slimbus,
+ MSM_MUX_spkr_i2s,
+ MSM_MUX_ter_mi2s,
+ MSM_MUX_tsif1,
+ MSM_MUX_tsif2,
+ MSM_MUX_uim1,
+ MSM_MUX_uim2,
+ MSM_MUX_uim3,
+ MSM_MUX_uim4,
+ MSM_MUX_uim_batt_alarm,
+ MSM_MUX_gpio,
+ MSM_MUX_NA,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145",
+};
+
+static const char * const blsp_spi1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_uart1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio0", "gpio1"
+};
+static const char * const hdmi_rcv_groups[] = {
+ "gpio0"
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio2", "gpio3"
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_uim2_groups[] = {
+ "gpio4", "gpio5"
+};
+static const char * const qdss_cti_trig_out_b_groups[] = {
+ "gpio4",
+};
+static const char * const qdss_cti_trig_in_b_groups[] = {
+ "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7"
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11"
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11"
+};
+static const char * const blsp_uim3_groups[] = {
+ "gpio8", "gpio9"
+};
+static const char * const blsp_spi1_cs1_groups[] = {
+ "gpio8"
+};
+static const char * const blsp_spi1_cs2_groups[] = {
+ "gpio9", "gpio11"
+};
+static const char * const mdp_vsync_groups[] = {
+ "gpio10", "gpio11", "gpio12"
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio10", "gpio11"
+};
+static const char * const blsp_spi1_cs3_groups[] = {
+ "gpio10"
+};
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18",
+ "gpio19", "gpio21", "gpio22", "gpio23", "gpio25", "gpio26",
+ "gpio57", "gpio58", "gpio92", "gpio93",
+};
+static const char * const cam_mclk0_groups[] = {
+ "gpio13"
+};
+static const char * const cam_mclk1_groups[] = {
+ "gpio14"
+};
+static const char * const cam_mclk2_groups[] = {
+ "gpio15"
+};
+static const char * const cam_mclk3_groups[] = {
+ "gpio16"
+};
+static const char * const cci_i2c0_groups[] = {
+ "gpio17", "gpio18"
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20"
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20"
+};
+static const char * const blsp_uim4_groups[] = {
+ "gpio17", "gpio18"
+};
+static const char * const cci_i2c1_groups[] = {
+ "gpio19", "gpio20"
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio19", "gpio20"
+};
+static const char * const cci_timer0_groups[] = {
+ "gpio21"
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio21", "gpio22", "gpio23", "gpio24"
+};
+static const char * const blsp_uart5_groups[] = {
+ "gpio21", "gpio22", "gpio23", "gpio24"
+};
+static const char * const blsp_uim5_groups[] = {
+ "gpio21", "gpio22"
+};
+static const char * const cci_timer1_groups[] = {
+ "gpio22"
+};
+static const char * const cci_timer2_groups[] = {
+ "gpio23"
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio23", "gpio24"
+};
+static const char * const cci_timer3_groups[] = {
+ "gpio24"
+};
+static const char * const cci_async_in1_groups[] = {
+ "gpio24"
+};
+static const char * const cci_timer4_groups[] = {
+ "gpio25"
+};
+static const char * const cci_async_in2_groups[] = {
+ "gpio25"
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28"
+};
+static const char * const blsp_uart6_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28"
+};
+static const char * const blsp_uim6_groups[] = {
+ "gpio25", "gpio26"
+};
+static const char * const cci_async_in0_groups[] = {
+ "gpio26"
+};
+static const char * const gp0_clk_groups[] = {
+ "gpio26"
+};
+static const char * const gp1_clk_groups[] = {
+ "gpio27", "gpio57", "gpio78"
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio27", "gpio28"
+};
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio27",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio28",
+};
+static const char * const gp_mn_groups[] = {
+ "gpio29"
+};
+static const char * const hdmi_cec_groups[] = {
+ "gpio31"
+};
+static const char * const hdmi_ddc_groups[] = {
+ "gpio32", "gpio33"
+};
+static const char * const hdmi_hpd_groups[] = {
+ "gpio34"
+};
+static const char * const uim3_groups[] = {
+ "gpio35", "gpio36", "gpio37", "gpio38"
+};
+static const char * const pci_e1_groups[] = {
+ "gpio35", "gpio36",
+};
+static const char * const blsp_spi7_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44"
+};
+static const char * const blsp_uart7_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44"
+};
+static const char * const blsp_uim7_groups[] = {
+ "gpio41", "gpio42"
+};
+static const char * const qdss_cti_trig_out_c_groups[] = {
+ "gpio41",
+};
+static const char * const qdss_cti_trig_in_c_groups[] = {
+ "gpio42",
+};
+static const char * const blsp_i2c7_groups[] = {
+ "gpio43", "gpio44"
+};
+static const char * const blsp_spi8_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48"
+};
+static const char * const blsp_uart8_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48"
+};
+static const char * const blsp_uim8_groups[] = {
+ "gpio45", "gpio46"
+};
+static const char * const blsp_i2c8_groups[] = {
+ "gpio47", "gpio48"
+};
+static const char * const blsp_spi10_cs1_groups[] = {
+ "gpio47", "gpio67"
+};
+static const char * const blsp_spi10_cs2_groups[] = {
+ "gpio48", "gpio68"
+};
+static const char * const uim2_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_spi9_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_uart9_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_uim9_groups[] = {
+ "gpio49", "gpio50"
+};
+static const char * const blsp_i2c9_groups[] = {
+ "gpio51", "gpio52"
+};
+static const char * const pci_e0_groups[] = {
+ "gpio53", "gpio54",
+};
+static const char * const uim4_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_spi10_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_uart10_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_uim10_groups[] = {
+ "gpio53", "gpio54"
+};
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio53", "gpio54", "gpio63", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio74", "gpio75", "gpio76",
+ "gpio77", "gpio85", "gpio86", "gpio87", "gpio89",
+ "gpio90"
+};
+static const char * const gp_pdm0_groups[] = {
+ "gpio54", "gpio95"
+};
+static const char * const blsp_i2c10_groups[] = {
+ "gpio55", "gpio56"
+};
+static const char * const qdss_cti_trig_in_a_groups[] = {
+ "gpio55",
+};
+static const char * const qdss_cti_trig_out_a_groups[] = {
+ "gpio56",
+};
+static const char * const qua_mi2s_groups[] = {
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+ "gpio57"
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+ "gpio58"
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+ "gpio59"
+};
+static const char * const blsp_spi2_cs1_groups[] = {
+ "gpio62"
+};
+static const char * const blsp_spi2_cs2_groups[] = {
+ "gpio63"
+};
+static const char * const gp_pdm2_groups[] = {
+ "gpio63", "gpio79"
+};
+static const char * const pri_mi2s_groups[] = {
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const blsp_spi2_cs3_groups[] = {
+ "gpio66"
+};
+static const char * const spkr_i2s_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72"
+};
+static const char * const audio_ref_clk_groups[] = {
+ "gpio69"
+};
+static const char * const slimbus_groups[] = {
+ "gpio70", "gpio71"
+};
+static const char * const ter_mi2s_groups[] = {
+ "gpio73", "gpio74", "gpio75", "gpio76", "gpio77"
+};
+static const char * const gp_pdm1_groups[] = {
+ "gpio74", "gpio86"
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+ "gpio78"
+};
+static const char * const blsp_spi11_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84"
+};
+static const char * const blsp_uart11_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84"
+};
+static const char * const blsp_uim11_groups[] = {
+ "gpio81", "gpio82"
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+ "gpio81"
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+ "gpio82"
+};
+static const char * const blsp_i2c11_groups[] = {
+ "gpio83", "gpio84"
+};
+static const char * const blsp_uart12_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88"
+};
+static const char * const blsp_uim12_groups[] = {
+ "gpio85", "gpio86"
+};
+static const char * const blsp_i2c12_groups[] = {
+ "gpio87", "gpio88"
+};
+static const char * const blsp_spi12_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88"
+};
+static const char * const tsif1_groups[] = {
+ "gpio89", "gpio90", "gpio91", "gpio110", "gpio111"
+};
+static const char * const blsp_spi10_cs3_groups[] = {
+ "gpio90"
+};
+static const char * const sdc4_groups[] = {
+ "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
+};
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio91",
+};
+static const char * const tsif2_groups[] = {
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
+};
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio94",
+};
+static const char * const qdss_cti_trig_out_d_groups[] = {
+ "gpio95",
+};
+static const char * const qdss_cti_trig_in_d_groups[] = {
+ "gpio96",
+};
+static const char * const uim1_groups[] = {
+ "gpio97", "gpio98", "gpio99", "gpio100"
+};
+static const char * const uim_batt_alarm_groups[] = {
+ "gpio101"
+};
+static const char * const blsp11_uart_tx_b_groups[] = {
+ "gpio111"
+};
+static const char * const blsp11_uart_rx_b_groups[] = {
+ "gpio112"
+};
+static const char * const blsp11_i2c_sda_b_groups[] = {
+ "gpio113"
+};
+static const char * const blsp11_i2c_scl_b_groups[] = {
+ "gpio114"
+};
+static const char * const gsm_tx_groups[] = {
+ "gpio126", "gpio131", "gpio132", "gpio133"
+};
+static const char * const nav_tsync_groups[] = {
+ "gpio127"
+};
+static const char * const nav_pps_groups[] = {
+ "gpio127"
+};
+static const char * const gps_tx_groups[] = {
+ "gpio130"
+};
+static const char * const mss_lte_groups[] = {
+ "gpio134", "gpio135"
+};
+
+static const struct msm_function msm8994_functions[] = {
+ FUNCTION(audio_ref_clk),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(blsp_i2c8),
+ FUNCTION(blsp_i2c9),
+ FUNCTION(blsp_i2c10),
+ FUNCTION(blsp_i2c11),
+ FUNCTION(blsp_i2c12),
+ FUNCTION(blsp_spi1),
+ FUNCTION(blsp_spi1_cs1),
+ FUNCTION(blsp_spi1_cs2),
+ FUNCTION(blsp_spi1_cs3),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_spi2_cs1),
+ FUNCTION(blsp_spi2_cs2),
+ FUNCTION(blsp_spi2_cs3),
+ FUNCTION(blsp_spi3),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_spi7),
+ FUNCTION(blsp_spi8),
+ FUNCTION(blsp_spi9),
+ FUNCTION(blsp_spi10),
+ FUNCTION(blsp_spi10_cs1),
+ FUNCTION(blsp_spi10_cs2),
+ FUNCTION(blsp_spi10_cs3),
+ FUNCTION(blsp_spi11),
+ FUNCTION(blsp_spi12),
+ FUNCTION(blsp_uart1),
+ FUNCTION(blsp_uart2),
+ FUNCTION(blsp_uart3),
+ FUNCTION(blsp_uart4),
+ FUNCTION(blsp_uart5),
+ FUNCTION(blsp_uart6),
+ FUNCTION(blsp_uart7),
+ FUNCTION(blsp_uart8),
+ FUNCTION(blsp_uart9),
+ FUNCTION(blsp_uart10),
+ FUNCTION(blsp_uart11),
+ FUNCTION(blsp_uart12),
+ FUNCTION(blsp_uim1),
+ FUNCTION(blsp_uim2),
+ FUNCTION(blsp_uim3),
+ FUNCTION(blsp_uim4),
+ FUNCTION(blsp_uim5),
+ FUNCTION(blsp_uim6),
+ FUNCTION(blsp_uim7),
+ FUNCTION(blsp_uim8),
+ FUNCTION(blsp_uim9),
+ FUNCTION(blsp_uim10),
+ FUNCTION(blsp_uim11),
+ FUNCTION(blsp_uim12),
+ FUNCTION(blsp11_i2c_scl_b),
+ FUNCTION(blsp11_i2c_sda_b),
+ FUNCTION(blsp11_uart_rx_b),
+ FUNCTION(blsp11_uart_tx_b),
+ FUNCTION(cam_mclk0),
+ FUNCTION(cam_mclk1),
+ FUNCTION(cam_mclk2),
+ FUNCTION(cam_mclk3),
+ FUNCTION(cci_async_in0),
+ FUNCTION(cci_async_in1),
+ FUNCTION(cci_async_in2),
+ FUNCTION(cci_i2c0),
+ FUNCTION(cci_i2c1),
+ FUNCTION(cci_timer0),
+ FUNCTION(cci_timer1),
+ FUNCTION(cci_timer2),
+ FUNCTION(cci_timer3),
+ FUNCTION(cci_timer4),
+ FUNCTION(gcc_gp1_clk_a),
+ FUNCTION(gcc_gp1_clk_b),
+ FUNCTION(gcc_gp2_clk_a),
+ FUNCTION(gcc_gp2_clk_b),
+ FUNCTION(gcc_gp3_clk_a),
+ FUNCTION(gcc_gp3_clk_b),
+ FUNCTION(gp_mn),
+ FUNCTION(gp_pdm0),
+ FUNCTION(gp_pdm1),
+ FUNCTION(gp_pdm2),
+ FUNCTION(gp0_clk),
+ FUNCTION(gp1_clk),
+ FUNCTION(gps_tx),
+ FUNCTION(gsm_tx),
+ FUNCTION(hdmi_cec),
+ FUNCTION(hdmi_ddc),
+ FUNCTION(hdmi_hpd),
+ FUNCTION(hdmi_rcv),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mss_lte),
+ FUNCTION(nav_pps),
+ FUNCTION(nav_tsync),
+ FUNCTION(qdss_cti_trig_in_a),
+ FUNCTION(qdss_cti_trig_in_b),
+ FUNCTION(qdss_cti_trig_in_c),
+ FUNCTION(qdss_cti_trig_in_d),
+ FUNCTION(qdss_cti_trig_out_a),
+ FUNCTION(qdss_cti_trig_out_b),
+ FUNCTION(qdss_cti_trig_out_c),
+ FUNCTION(qdss_cti_trig_out_d),
+ FUNCTION(qdss_traceclk_a),
+ FUNCTION(qdss_traceclk_b),
+ FUNCTION(qdss_tracectl_a),
+ FUNCTION(qdss_tracectl_b),
+ FUNCTION(qdss_tracedata_a),
+ FUNCTION(qdss_tracedata_b),
+ FUNCTION(qua_mi2s),
+ FUNCTION(pci_e0),
+ FUNCTION(pci_e1),
+ FUNCTION(pri_mi2s),
+ FUNCTION(sdc4),
+ FUNCTION(sec_mi2s),
+ FUNCTION(slimbus),
+ FUNCTION(spkr_i2s),
+ FUNCTION(ter_mi2s),
+ FUNCTION(tsif1),
+ FUNCTION(tsif2),
+ FUNCTION(uim_batt_alarm),
+ FUNCTION(uim1),
+ FUNCTION(uim2),
+ FUNCTION(uim3),
+ FUNCTION(uim4),
+ FUNCTION(gpio),
+};
+
+static const struct msm_pingroup msm8994_groups[] = {
+ PINGROUP(0, blsp_spi1, blsp_uart1, blsp_uim1, hdmi_rcv, NA, NA, NA,
+ NA, NA, NA, NA),
+ PINGROUP(1, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_out_b,
+ NA, NA, NA, NA, NA, NA),
+ PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_in_b,
+ NA, NA, NA, NA, NA, NA),
+ PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(8, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA,
+ NA, NA, NA, NA, NA),
+ PINGROUP(9, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA,
+ NA, NA, NA, NA, NA),
+ PINGROUP(10, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
+ blsp_spi1_cs3, NA, NA, NA, NA, NA, NA),
+ PINGROUP(11, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
+ blsp_spi1_cs2, NA, NA, NA, NA, NA, NA),
+ PINGROUP(12, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(13, cam_mclk0, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(14, cam_mclk1, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(15, cam_mclk2, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(16, cam_mclk3, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(17, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+ qdss_tracedata_b, NA, NA, NA, NA, NA),
+ PINGROUP(18, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+ qdss_tracedata_b, NA, NA, NA, NA, NA),
+ PINGROUP(19, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA,
+ qdss_tracedata_b, NA, NA, NA, NA, NA),
+ PINGROUP(20, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA,
+ NA, NA, NA, NA),
+ PINGROUP(21, cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA,
+ qdss_tracedata_b, NA, NA, NA, NA, NA),
+ PINGROUP(22, cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA,
+ qdss_tracedata_b, NA, NA, NA, NA, NA),
+ PINGROUP(23, cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA,
+ qdss_tracedata_b, NA, NA, NA, NA),
+ PINGROUP(24, cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5,
+ blsp_i2c5, NA, NA, NA, NA, NA, NA),
+ PINGROUP(25, cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6,
+ blsp_uim6, NA, NA, qdss_tracedata_b, NA, NA, NA),
+ PINGROUP(26, cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, gp0_clk,
+ NA, qdss_tracedata_b, NA, NA, NA, NA),
+ PINGROUP(27, blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk,
+ qdss_tracectl_a, NA, NA, NA, NA, NA, NA),
+ PINGROUP(28, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_a, NA,
+ NA, NA, NA, NA, NA, NA),
+ PINGROUP(29, gp_mn, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(31, hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(32, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(33, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(34, hdmi_hpd, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(35, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(36, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(37, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(38, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_out_c,
+ NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(42, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_in_c, NA,
+ NA, NA, NA, NA, NA, NA),
+ PINGROUP(43, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(44, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(45, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(46, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(47, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA,
+ NA, NA, NA, NA, NA),
+ PINGROUP(48, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA,
+ NA, NA, NA, NA, NA),
+ PINGROUP(49, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(50, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(51, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(52, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(53, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, NA,
+ NA, qdss_tracedata_a, NA, NA, NA),
+ PINGROUP(54, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10,
+ gp_pdm0, NA, NA, qdss_tracedata_a, NA, NA),
+ PINGROUP(55, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA,
+ qdss_cti_trig_in_a, NA, NA, NA),
+ PINGROUP(56, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA,
+ qdss_cti_trig_out_a, NA, NA, NA, NA),
+ PINGROUP(57, qua_mi2s, gcc_gp1_clk_a, NA, NA, qdss_tracedata_b, NA, NA,
+ NA, NA, NA, NA),
+ PINGROUP(58, qua_mi2s, gcc_gp2_clk_a, NA, NA, qdss_tracedata_b, NA, NA,
+ NA, NA, NA, NA),
+ PINGROUP(59, qua_mi2s, gcc_gp3_clk_a, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(60, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(61, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(62, qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(63, qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA, NA,
+ qdss_tracedata_a, NA, NA),
+ PINGROUP(64, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(65, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(66, pri_mi2s, blsp_spi2_cs3, NA, NA, NA, qdss_tracedata_a,
+ NA, NA, NA, NA, NA),
+ PINGROUP(67, pri_mi2s, blsp_spi10_cs1, NA, NA, NA, qdss_tracedata_a,
+ NA, NA, NA, NA, NA),
+ PINGROUP(68, pri_mi2s, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(69, spkr_i2s, audio_ref_clk, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(70, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(71, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, ter_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, ter_mi2s, gp_pdm1, NA, NA, NA, qdss_tracedata_a, NA, NA,
+ NA, NA, NA),
+ PINGROUP(75, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(76, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(77, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(78, sec_mi2s, gcc_gp1_clk_b, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(79, sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(81, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
+ gcc_gp2_clk_b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
+ gcc_gp3_clk_b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(83, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(84, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(85, blsp_spi12, blsp_uart12, blsp_uim12, NA, NA,
+ qdss_tracedata_a, NA, NA, NA, NA, NA),
+ PINGROUP(86, blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA,
+ qdss_tracedata_a, NA, NA, NA, NA, NA),
+ PINGROUP(87, blsp_spi12, blsp_uart12, blsp_i2c12, NA,
+ qdss_tracedata_a, NA, NA, NA, NA, NA, NA),
+ PINGROUP(88, blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(89, tsif1, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(90, tsif1, blsp_spi10_cs3, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA, NA, NA),
+ PINGROUP(91, tsif1, sdc4, NA, NA, NA, NA, qdss_traceclk_b, NA, NA, NA,
+ NA),
+ PINGROUP(92, tsif2, sdc4, NA, NA, qdss_tracedata_b, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(93, tsif2, sdc4, NA, NA, NA, NA, qdss_tracedata_b, NA, NA,
+ NA, NA),
+ PINGROUP(94, tsif2, sdc4, NA, NA, NA, NA, qdss_tracectl_b, NA, NA, NA,
+ NA),
+ PINGROUP(95, tsif2, sdc4, gp_pdm0, NA, NA, NA, qdss_cti_trig_out_d,
+ NA, NA, NA, NA),
+ PINGROUP(96, tsif2, sdc4, qdss_cti_trig_in_d, NA, NA, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(97, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(99, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, tsif1, blsp11_uart_tx_b, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(112, blsp11_uart_rx_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(113, blsp11_i2c_sda_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(114, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(115, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(118, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(121, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(122, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(123, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(126, NA, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(127, NA, nav_tsync, nav_pps, NA, NA, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(130, gps_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(131, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(132, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(133, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(134, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(135, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(137, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(138, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(139, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(140, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(141, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(142, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(143, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(144, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(145, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ SDC_PINGROUP(sdc1_rclk, 0x2044, 15, 0),
+ SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6),
+ SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3),
+ SDC_PINGROUP(sdc1_data, 0x2044, 9, 0),
+ SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6),
+ SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3),
+ SDC_PINGROUP(sdc2_data, 0x2048, 9, 0),
+ SDC_PINGROUP(sdc3_clk, 0x206c, 14, 6),
+ SDC_PINGROUP(sdc3_cmd, 0x206c, 11, 3),
+ SDC_PINGROUP(sdc3_data, 0x206c, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 146
+
+static const struct msm_pinctrl_soc_data msm8994_pinctrl = {
+ .pins = msm8994_pins,
+ .npins = ARRAY_SIZE(msm8994_pins),
+ .functions = msm8994_functions,
+ .nfunctions = ARRAY_SIZE(msm8994_functions),
+ .groups = msm8994_groups,
+ .ngroups = ARRAY_SIZE(msm8994_groups),
+ .ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int msm8994_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &msm8994_pinctrl);
+}
+
+static const struct of_device_id msm8994_pinctrl_of_match[] = {
+ { .compatible = "qcom,msm8992-pinctrl", },
+ { .compatible = "qcom,msm8994-pinctrl", },
+ { }
+};
+
+static struct platform_driver msm8994_pinctrl_driver = {
+ .driver = {
+ .name = "msm8994-pinctrl",
+ .of_match_table = msm8994_pinctrl_of_match,
+ },
+ .probe = msm8994_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init msm8994_pinctrl_init(void)
+{
+ return platform_driver_register(&msm8994_pinctrl_driver);
+}
+arch_initcall(msm8994_pinctrl_init);
+
+static void __exit msm8994_pinctrl_exit(void)
+{
+ platform_driver_unregister(&msm8994_pinctrl_driver);
+}
+module_exit(msm8994_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm MSM8994 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8994_pinctrl_of_match);
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index d32fa2b5ff82..12f7d1eb65bc 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -61,16 +61,15 @@ static void exynos_irq_mask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
spin_lock_irqsave(&bank->slock, flags);
- mask = readl(d->virt_base + reg_mask);
+ mask = readl(bank->eint_base + reg_mask);
mask |= 1 << irqd->hwirq;
- writel(mask, d->virt_base + reg_mask);
+ writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
}
@@ -80,10 +79,9 @@ static void exynos_irq_ack(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
- writel(1 << irqd->hwirq, d->virt_base + reg_pend);
+ writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
}
static void exynos_irq_unmask(struct irq_data *irqd)
@@ -91,7 +89,6 @@ static void exynos_irq_unmask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
@@ -109,9 +106,9 @@ static void exynos_irq_unmask(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
- mask = readl(d->virt_base + reg_mask);
+ mask = readl(bank->eint_base + reg_mask);
mask &= ~(1 << irqd->hwirq);
- writel(mask, d->virt_base + reg_mask);
+ writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
}
@@ -121,7 +118,6 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned int con, trig_type;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
@@ -152,10 +148,10 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
else
irq_set_handler_locked(irqd, handle_level_irq);
- con = readl(d->virt_base + reg_con);
+ con = readl(bank->eint_base + reg_con);
con &= ~(EXYNOS_EINT_CON_MASK << shift);
con |= trig_type << shift;
- writel(con, d->virt_base + reg_con);
+ writel(con, bank->eint_base + reg_con);
return 0;
}
@@ -166,7 +162,6 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
const struct samsung_pin_bank_type *bank_type = bank->type;
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long flags;
@@ -188,10 +183,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
- con = readl(d->virt_base + reg_con);
+ con = readl(bank->eint_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
- writel(con, d->virt_base + reg_con);
+ writel(con, bank->eint_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
@@ -206,7 +201,6 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
const struct samsung_pin_bank_type *bank_type = bank->type;
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long flags;
@@ -221,10 +215,10 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
- con = readl(d->virt_base + reg_con);
+ con = readl(bank->eint_base + reg_con);
con &= ~(mask << shift);
con |= FUNC_INPUT << shift;
- writel(con, d->virt_base + reg_con);
+ writel(con, bank->eint_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
@@ -274,7 +268,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
struct samsung_pin_bank *bank = d->pin_banks;
unsigned int svc, group, pin, virq;
- svc = readl(d->virt_base + EXYNOS_SVC_OFFSET);
+ svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
group = EXYNOS_SVC_GROUP(svc);
pin = svc & EXYNOS_SVC_NUM_MASK;
@@ -452,7 +446,6 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
- struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
unsigned long pend;
unsigned long mask;
int i;
@@ -461,9 +454,9 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
for (i = 0; i < eintd->nr_banks; ++i) {
struct samsung_pin_bank *b = eintd->banks[i];
- pend = readl(d->virt_base + b->irq_chip->eint_pend
+ pend = readl(b->eint_base + b->irq_chip->eint_pend
+ b->eint_offset);
- mask = readl(d->virt_base + b->irq_chip->eint_mask
+ mask = readl(b->eint_base + b->irq_chip->eint_mask
+ b->eint_offset);
exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
}
@@ -581,7 +574,7 @@ static void exynos_pinctrl_suspend_bank(
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
- void __iomem *regs = drvdata->virt_base;
+ void __iomem *regs = bank->eint_base;
save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+ bank->eint_offset);
@@ -610,7 +603,7 @@ static void exynos_pinctrl_resume_bank(
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
- void __iomem *regs = drvdata->virt_base;
+ void __iomem *regs = bank->eint_base;
pr_debug("%s: con %#010x => %#010x\n", bank->name,
readl(regs + EXYNOS_GPIO_ECON_OFFSET
@@ -1346,6 +1339,11 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
+ EXYNOS_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
+ EXYNOS_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
+ EXYNOS_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
+ EXYNOS_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
+ EXYNOS_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
};
/* pin banks of exynos5433 pin-controller - AUD */
@@ -1427,6 +1425,7 @@ const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
+ .nr_ext_resources = 1,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos5433_pin_banks1,
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 0f0f7cedb2dc..5821525a2c84 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -79,6 +79,17 @@
.name = id \
}
+#define EXYNOS_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx) \
+ { \
+ .type = &bank_type_alive, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_offset = offs, \
+ .name = id, \
+ .pctl_res_idx = pctl_idx, \
+ } \
+
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
index 3d92f827da7a..b82a003546ae 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
@@ -151,7 +151,7 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
u32 val;
/* Make sure that pin is configured as interrupt */
- reg = d->virt_base + bank->pctl_offset;
+ reg = bank->pctl_base + bank->pctl_offset;
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
@@ -184,7 +184,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
s3c24xx_eint_set_handler(data, type);
/* Set up interrupt trigger */
- reg = d->virt_base + EINT_REG(index);
+ reg = bank->eint_base + EINT_REG(index);
shift = EINT_OFFS(index);
val = readl(reg);
@@ -259,32 +259,29 @@ static void s3c2410_demux_eint0_3(struct irq_desc *desc)
static void s3c2412_eint0_3_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long bitval = 1UL << data->hwirq;
- writel(bitval, d->virt_base + EINTPEND_REG);
+ writel(bitval, bank->eint_base + EINTPEND_REG);
}
static void s3c2412_eint0_3_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
- mask = readl(d->virt_base + EINTMASK_REG);
+ mask = readl(bank->eint_base + EINTMASK_REG);
mask |= (1UL << data->hwirq);
- writel(mask, d->virt_base + EINTMASK_REG);
+ writel(mask, bank->eint_base + EINTMASK_REG);
}
static void s3c2412_eint0_3_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
- mask = readl(d->virt_base + EINTMASK_REG);
+ mask = readl(bank->eint_base + EINTMASK_REG);
mask &= ~(1UL << data->hwirq);
- writel(mask, d->virt_base + EINTMASK_REG);
+ writel(mask, bank->eint_base + EINTMASK_REG);
}
static struct irq_chip s3c2412_eint0_3_chip = {
@@ -319,34 +316,31 @@ static void s3c2412_demux_eint0_3(struct irq_desc *desc)
static void s3c24xx_eint_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
- writel(1UL << index, d->virt_base + EINTPEND_REG);
+ writel(1UL << index, bank->eint_base + EINTPEND_REG);
}
static void s3c24xx_eint_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
- mask = readl(d->virt_base + EINTMASK_REG);
+ mask = readl(bank->eint_base + EINTMASK_REG);
mask |= (1UL << index);
- writel(mask, d->virt_base + EINTMASK_REG);
+ writel(mask, bank->eint_base + EINTMASK_REG);
}
static void s3c24xx_eint_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
- mask = readl(d->virt_base + EINTMASK_REG);
+ mask = readl(bank->eint_base + EINTMASK_REG);
mask &= ~(1UL << index);
- writel(mask, d->virt_base + EINTMASK_REG);
+ writel(mask, bank->eint_base + EINTMASK_REG);
}
static struct irq_chip s3c24xx_eint_chip = {
@@ -362,13 +356,14 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
{
struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
- struct samsung_pinctrl_drv_data *d = data->drvdata;
+ struct irq_data *irqd = irq_desc_get_irq_data(desc);
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned int pend, mask;
chained_irq_enter(chip, desc);
- pend = readl(d->virt_base + EINTPEND_REG);
- mask = readl(d->virt_base + EINTMASK_REG);
+ pend = readl(bank->eint_base + EINTPEND_REG);
+ mask = readl(bank->eint_base + EINTMASK_REG);
pend &= ~mask;
pend &= range;
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index 43407ab248f5..4c632812ccff 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -280,7 +280,7 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
u32 val;
/* Make sure that pin is configured as interrupt */
- reg = d->virt_base + bank->pctl_offset;
+ reg = bank->pctl_base + bank->pctl_offset;
shift = pin;
if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
/* 4-bit bank type with 2 con regs */
@@ -308,9 +308,8 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
- void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
+ void __iomem *reg = bank->eint_base + EINTMASK_REG(bank->eint_offset);
u32 val;
val = readl(reg);
@@ -334,9 +333,8 @@ static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
- void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
+ void __iomem *reg = bank->eint_base + EINTPEND_REG(bank->eint_offset);
writel(1 << index, reg);
}
@@ -359,7 +357,7 @@ static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */
- reg = d->virt_base + EINTCON_REG(bank->eint_offset);
+ reg = bank->eint_base + EINTCON_REG(bank->eint_offset);
shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
@@ -411,7 +409,8 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
- struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+ struct irq_data *irqd = irq_desc_get_irq_data(desc);
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
chained_irq_enter(chip, desc);
@@ -421,7 +420,7 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
unsigned int pin;
unsigned int virq;
- svc = readl(drvdata->virt_base + SERVICE_REG);
+ svc = readl(bank->eint_base + SERVICE_REG);
group = SVC_GROUP(svc);
pin = svc & SVC_NUM_MASK;
@@ -518,15 +517,15 @@ static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
{
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+ struct samsung_pin_bank *bank = ddata->bank;
u32 val;
- val = readl(d->virt_base + EINT0MASK_REG);
+ val = readl(bank->eint_base + EINT0MASK_REG);
if (mask)
val |= 1 << ddata->eints[irqd->hwirq];
else
val &= ~(1 << ddata->eints[irqd->hwirq]);
- writel(val, d->virt_base + EINT0MASK_REG);
+ writel(val, bank->eint_base + EINT0MASK_REG);
}
static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
@@ -543,10 +542,10 @@ static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
{
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+ struct samsung_pin_bank *bank = ddata->bank;
writel(1 << ddata->eints[irqd->hwirq],
- d->virt_base + EINT0PEND_REG);
+ bank->eint_base + EINT0PEND_REG);
}
static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
@@ -554,7 +553,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank *bank = ddata->bank;
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
void __iomem *reg;
int trigger;
u8 shift;
@@ -569,7 +568,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */
- reg = d->virt_base + EINT0CON0_REG;
+ reg = bank->eint_base + EINT0CON0_REG;
shift = ddata->eints[irqd->hwirq];
if (shift >= EINT_MAX_PER_REG) {
reg += 4;
@@ -601,14 +600,19 @@ static struct irq_chip s3c64xx_eint0_irq_chip = {
static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irq_data *irqd = irq_desc_get_irq_data(desc);
+ struct s3c64xx_eint0_domain_data *ddata =
+ irq_data_get_irq_chip_data(irqd);
+ struct samsung_pin_bank *bank = ddata->bank;
+
struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
- struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+
unsigned int pend, mask;
chained_irq_enter(chip, desc);
- pend = readl(drvdata->virt_base + EINT0PEND_REG);
- mask = readl(drvdata->virt_base + EINT0MASK_REG);
+ pend = readl(bank->eint_base + EINT0PEND_REG);
+ mask = readl(bank->eint_base + EINT0MASK_REG);
pend = pend & range & ~mask;
pend &= range;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 620727fabe64..41e62391c33c 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -33,6 +33,9 @@
#include "../core.h"
#include "pinctrl-samsung.h"
+/* maximum number of the memory resources */
+#define SAMSUNG_PINCTRL_NUM_RESOURCES 2
+
/* list of all possible config options supported */
static struct pin_config {
const char *property;
@@ -345,7 +348,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
((b->pin_base + b->nr_pins - 1) < pin))
b++;
- *reg = drvdata->virt_base + b->pctl_offset;
+ *reg = b->pctl_base + b->pctl_offset;
*offset = pin - b->pin_base;
if (bank)
*bank = b;
@@ -526,7 +529,7 @@ static void samsung_gpio_set_value(struct gpio_chip *gc,
void __iomem *reg;
u32 data;
- reg = bank->drvdata->virt_base + bank->pctl_offset;
+ reg = bank->pctl_base + bank->pctl_offset;
data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
data &= ~(1 << offset);
@@ -554,7 +557,7 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
const struct samsung_pin_bank_type *type = bank->type;
- reg = bank->drvdata->virt_base + bank->pctl_offset;
+ reg = bank->pctl_base + bank->pctl_offset;
data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
data >>= offset;
@@ -581,8 +584,8 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc,
type = bank->type;
drvdata = bank->drvdata;
- reg = drvdata->virt_base + bank->pctl_offset +
- type->reg_offset[PINCFG_TYPE_FUNC];
+ reg = bank->pctl_base + bank->pctl_offset
+ + type->reg_offset[PINCFG_TYPE_FUNC];
mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
shift = offset * type->fld_width[PINCFG_TYPE_FUNC];
@@ -979,6 +982,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
const struct samsung_pin_bank_data *bdata;
const struct samsung_pin_ctrl *ctrl;
struct samsung_pin_bank *bank;
+ struct resource *res;
+ void __iomem *virt_base[SAMSUNG_PINCTRL_NUM_RESOURCES];
int i;
id = of_alias_get_id(node, "pinctrl");
@@ -997,6 +1002,17 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
if (!d->pin_banks)
return ERR_PTR(-ENOMEM);
+ if (ctrl->nr_ext_resources + 1 > SAMSUNG_PINCTRL_NUM_RESOURCES)
+ return ERR_PTR(-EINVAL);
+
+ for (i = 0; i < ctrl->nr_ext_resources + 1; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ virt_base[i] = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (IS_ERR(virt_base[i]))
+ return ERR_PTR(-EIO);
+ }
+
bank = d->pin_banks;
bdata = ctrl->pin_banks;
for (i = 0; i < ctrl->nr_banks; ++i, ++bdata, ++bank) {
@@ -1013,6 +1029,9 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
bank->drvdata = d;
bank->pin_base = d->nr_pins;
d->nr_pins += bank->nr_pins;
+
+ bank->eint_base = virt_base[0];
+ bank->pctl_base = virt_base[bdata->pctl_res_idx];
}
for_each_child_of_node(node, np) {
@@ -1052,11 +1071,6 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
}
drvdata->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(drvdata->virt_base))
- return PTR_ERR(drvdata->virt_base);
-
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res)
drvdata->irq = res->start;
@@ -1094,12 +1108,11 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
static void samsung_pinctrl_suspend_dev(
struct samsung_pinctrl_drv_data *drvdata)
{
- void __iomem *virt_base = drvdata->virt_base;
int i;
for (i = 0; i < drvdata->nr_banks; i++) {
struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
- void __iomem *reg = virt_base + bank->pctl_offset;
+ void __iomem *reg = bank->pctl_base + bank->pctl_offset;
const u8 *offs = bank->type->reg_offset;
const u8 *widths = bank->type->fld_width;
enum pincfg_type type;
@@ -1140,7 +1153,6 @@ static void samsung_pinctrl_suspend_dev(
*/
static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
{
- void __iomem *virt_base = drvdata->virt_base;
int i;
if (drvdata->resume)
@@ -1148,7 +1160,7 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
for (i = 0; i < drvdata->nr_banks; i++) {
struct samsung_pin_bank *bank = &drvdata->pin_banks[i];
- void __iomem *reg = virt_base + bank->pctl_offset;
+ void __iomem *reg = bank->pctl_base + bank->pctl_offset;
const u8 *offs = bank->type->reg_offset;
const u8 *widths = bank->type->fld_width;
enum pincfg_type type;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index cd31bfaf62cb..043cb6c11180 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -116,6 +116,7 @@ struct samsung_pin_bank_type {
* struct samsung_pin_bank_data: represent a controller pin-bank (init data).
* @type: type of the bank (register offsets and bitfield widths)
* @pctl_offset: starting offset of the pin-bank registers.
+ * @pctl_res_idx: index of base address for pin-bank registers.
* @nr_pins: number of pins included in this bank.
* @eint_func: function to set in CON register to configure pin as EINT.
* @eint_type: type of the external interrupt supported by the bank.
@@ -126,6 +127,7 @@ struct samsung_pin_bank_type {
struct samsung_pin_bank_data {
const struct samsung_pin_bank_type *type;
u32 pctl_offset;
+ u8 pctl_res_idx;
u8 nr_pins;
u8 eint_func;
enum eint_type eint_type;
@@ -137,8 +139,10 @@ struct samsung_pin_bank_data {
/**
* struct samsung_pin_bank: represent a controller pin-bank.
* @type: type of the bank (register offsets and bitfield widths)
+ * @pctl_base: base address of the pin-bank registers
* @pctl_offset: starting offset of the pin-bank registers.
* @nr_pins: number of pins included in this bank.
+ * @eint_base: base address of the pin-bank EINT registers.
* @eint_func: function to set in CON register to configure pin as EINT.
* @eint_type: type of the external interrupt supported by the bank.
* @eint_mask: bit mask of pins which support EINT function.
@@ -157,8 +161,10 @@ struct samsung_pin_bank_data {
*/
struct samsung_pin_bank {
const struct samsung_pin_bank_type *type;
+ void __iomem *pctl_base;
u32 pctl_offset;
u8 nr_pins;
+ void __iomem *eint_base;
u8 eint_func;
enum eint_type eint_type;
u32 eint_mask;
@@ -182,6 +188,7 @@ struct samsung_pin_bank {
* struct samsung_pin_ctrl: represent a pin controller.
* @pin_banks: list of pin banks included in this controller.
* @nr_banks: number of pin banks.
+ * @nr_ext_resources: number of the extra base address for pin banks.
* @eint_gpio_init: platform specific callback to setup the external gpio
* interrupts for the controller.
* @eint_wkup_init: platform specific callback to setup the external wakeup
@@ -190,6 +197,7 @@ struct samsung_pin_bank {
struct samsung_pin_ctrl {
const struct samsung_pin_bank_data *pin_banks;
u32 nr_banks;
+ int nr_ext_resources;
int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
@@ -200,7 +208,6 @@ struct samsung_pin_ctrl {
/**
* struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
* @node: global list node
- * @virt_base: register base address of the controller.
* @dev: device instance representing the controller.
* @irq: interrpt number used by the controller to notify gpio interrupts.
* @ctrl: pin controller instance managed by the driver.
@@ -215,7 +222,6 @@ struct samsung_pin_ctrl {
*/
struct samsung_pinctrl_drv_data {
struct list_head node;
- void __iomem *virt_base;
struct device *dev;
int irq;
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index f3a8897d4e8f..cf80ce1dd7ce 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -389,6 +389,21 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
return 0;
}
+const struct sh_pfc_bias_info *
+sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info,
+ unsigned int num, unsigned int pin)
+{
+ unsigned int i;
+
+ for (i = 0; i < num; i++)
+ if (info[i].pin == pin)
+ return &info[i];
+
+ WARN_ONCE(1, "Pin %u is not in bias info list\n", pin);
+
+ return NULL;
+}
+
static int sh_pfc_init_ranges(struct sh_pfc *pfc)
{
struct sh_pfc_pin_range *range;
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index 0bbdea5849f4..6d598dd63720 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -33,4 +33,8 @@ void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width,
int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);
+const struct sh_pfc_bias_info *
+sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info,
+ unsigned int num, unsigned int pin);
+
#endif /* __SH_PFC_CORE_H__ */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index 18ef7042b3d1..c3af9ebee4af 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include "core.h"
#include "sh_pfc.h"
#define PORT_GP_PUP_1(bank, pin, fn, sfx) \
@@ -2918,183 +2919,182 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
#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 const struct sh_pfc_bias_info bias_info[] = {
+ { 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)
{
+ const struct sh_pfc_bias_info *info;
void __iomem *addr;
- if (WARN_ON_ONCE(!pullups[pin].reg))
+ info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin);
+ if (!info)
return PIN_CONFIG_BIAS_DISABLE;
- addr = pfc->windows->virt + pullups[pin].reg;
+ addr = pfc->windows->virt + info->reg;
- if (ioread32(addr) & BIT(pullups[pin].bit))
+ if (ioread32(addr) & BIT(info->bit))
return PIN_CONFIG_BIAS_PULL_UP;
else
return PIN_CONFIG_BIAS_DISABLE;
@@ -3103,15 +3103,17 @@ static unsigned int r8a7778_pinmux_get_bias(struct sh_pfc *pfc,
static void r8a7778_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
unsigned int bias)
{
+ const struct sh_pfc_bias_info *info;
void __iomem *addr;
u32 value;
u32 bit;
- if (WARN_ON_ONCE(!pullups[pin].reg))
+ info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin);
+ if (!info)
return;
- addr = pfc->windows->virt + pullups[pin].reg;
- bit = BIT(pullups[pin].bit);
+ addr = pfc->windows->virt + info->reg;
+ bit = BIT(info->bit);
value = ioread32(addr) & ~bit;
if (bias == PIN_CONFIG_BIAS_PULL_UP)
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
index 2e8cc2adbed7..135ed5cbeb44 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -523,6 +523,22 @@ MOD_SEL0_2_1 MOD_SEL1_2 \
MOD_SEL1_1 \
MOD_SEL1_0 MOD_SEL2_0
+/*
+ * These pins are not able to be muxed but have other properties
+ * that can be set, such as drive-strength or pull-up/pull-down enable.
+ */
+#define PINMUX_STATIC \
+ FM(QSPI0_SPCLK) FM(QSPI0_SSL) FM(QSPI0_MOSI_IO0) FM(QSPI0_MISO_IO1) \
+ FM(QSPI0_IO2) FM(QSPI0_IO3) \
+ FM(QSPI1_SPCLK) FM(QSPI1_SSL) FM(QSPI1_MOSI_IO0) FM(QSPI1_MISO_IO1) \
+ FM(QSPI1_IO2) FM(QSPI1_IO3) \
+ FM(RPC_INT) FM(RPC_WP) FM(RPC_RESET) \
+ FM(AVB_TX_CTL) FM(AVB_TXC) FM(AVB_TD0) FM(AVB_TD1) FM(AVB_TD2) FM(AVB_TD3) \
+ FM(AVB_RX_CTL) FM(AVB_RXC) FM(AVB_RD0) FM(AVB_RD1) FM(AVB_RD2) FM(AVB_RD3) \
+ FM(AVB_TXCREFCLK) FM(AVB_MDIO) \
+ FM(CLKOUT) FM(PRESETOUT) \
+ FM(DU_DOTCLKIN0) FM(DU_DOTCLKIN1) FM(DU_DOTCLKIN2) FM(DU_DOTCLKIN3) \
+ FM(TMS) FM(TDO) FM(ASEBRK) FM(MLB_REF)
enum {
PINMUX_RESERVED = 0,
@@ -548,6 +564,7 @@ enum {
PINMUX_GPSR
PINMUX_IPSR
PINMUX_MOD_SELS
+ PINMUX_STATIC
PINMUX_MARK_END,
#undef F_
#undef FM
@@ -1412,10 +1429,78 @@ static const u16 pinmux_data[] = {
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_GPSR(IP17_7_4, TPU0TO3),
+
+/*
+ * Static pins can not be muxed between different functions but
+ * still needs a mark entry in the pinmux list. Add each static
+ * pin to the list without an associated function. The sh-pfc
+ * core will do the right thing and skip trying to mux then pin
+ * while still applying configuration to it
+ */
+#define FM(x) PINMUX_DATA(x##_MARK, 0),
+ PINMUX_STATIC
+#undef FM
};
+/*
+ * R8A7795 has 8 banks with 32 PGIOS in each => 256 GPIOs.
+ * Physical layout rows: A - AW, cols: 1 - 39.
+ */
+#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
+#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300)
+#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
+
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
+
+ /*
+ * Pins not associated with a GPIO port.
+ *
+ * The pin positions are different between different r8a7795
+ * packages, all that is needed for the pfc driver is a unique
+ * number for each pin. To this end use the pin layout from
+ * R-Car H3SiP to calculate a unique number for each pin.
+ */
+ SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('F', 1, CLKOUT, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST#, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 7, DU_DOTCLKIN2, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN3, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
+ SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -1563,11 +1648,33 @@ 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),
+ /* AVB_MDC, AVB_MDIO */
+ RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9),
};
static const unsigned int avb_mdc_mux[] = {
- AVB_MDC_MARK,
+ AVB_MDC_MARK, AVB_MDIO_MARK,
+};
+static const unsigned int avb_mii_pins[] = {
+ /*
+ * AVB_TX_CTL, AVB_TXC, AVB_TD0,
+ * AVB_TD1, AVB_TD2, AVB_TD3,
+ * AVB_RX_CTL, AVB_RXC, AVB_RD0,
+ * AVB_RD1, AVB_RD2, AVB_RD3,
+ * AVB_TXCREFCLK
+ */
+ PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18),
+ PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17),
+ PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13),
+ PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14),
+ PIN_NUMBER('A', 12),
+
+};
+static const unsigned int avb_mii_mux[] = {
+ AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
+ AVB_TD1_MARK, AVB_TD2_MARK, AVB_TD3_MARK,
+ AVB_RX_CTL_MARK, AVB_RXC_MARK, AVB_RD0_MARK,
+ AVB_RD1_MARK, AVB_RD2_MARK, AVB_RD3_MARK,
+ AVB_TXCREFCLK_MARK,
};
static const unsigned int avb_avtp_pps_pins[] = {
/* AVB_AVTP_PPS */
@@ -3613,6 +3720,55 @@ static const unsigned int usb2_mux[] = {
USB2_PWEN_MARK, USB2_OVC_MARK,
};
+/* - QSPI0 ------------------------------------------------------------------ */
+static const unsigned int qspi0_ctrl_pins[] = {
+ /* QSPI0_SPCLK, QSPI0_SSL */
+ PIN_NUMBER('W', 3), PIN_NUMBER('Y', 3),
+};
+static const unsigned int qspi0_ctrl_mux[] = {
+ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
+};
+static const unsigned int qspi0_data2_pins[] = {
+ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
+ PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4),
+};
+static const unsigned int qspi0_data2_mux[] = {
+ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+};
+static const unsigned int qspi0_data4_pins[] = {
+ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1, QSPI0_IO2, QSPI0_IO3 */
+ PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4),
+ PIN_NUMBER('Y', 6), PIN_A_NUMBER('B', 6),
+};
+static const unsigned int qspi0_data4_mux[] = {
+ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+ QSPI0_IO2_MARK, QSPI0_IO3_MARK,
+};
+/* - QSPI1 ------------------------------------------------------------------ */
+static const unsigned int qspi1_ctrl_pins[] = {
+ /* QSPI1_SPCLK, QSPI1_SSL */
+ PIN_NUMBER('V', 3), PIN_NUMBER('V', 5),
+};
+static const unsigned int qspi1_ctrl_mux[] = {
+ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
+};
+static const unsigned int qspi1_data2_pins[] = {
+ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
+ PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5),
+};
+static const unsigned int qspi1_data2_mux[] = {
+ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+};
+static const unsigned int qspi1_data4_pins[] = {
+ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1, QSPI1_IO2, QSPI1_IO3 */
+ PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5),
+ PIN_A_NUMBER('E', 4), PIN_A_NUMBER('C', 3),
+};
+static const unsigned int qspi1_data4_mux[] = {
+ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+ QSPI1_IO2_MARK, QSPI1_IO3_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),
@@ -3635,6 +3791,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(avb_magic),
SH_PFC_PIN_GROUP(avb_phy_int),
SH_PFC_PIN_GROUP(avb_mdc),
+ SH_PFC_PIN_GROUP(avb_mii),
SH_PFC_PIN_GROUP(avb_avtp_pps),
SH_PFC_PIN_GROUP(avb_avtp_match_a),
SH_PFC_PIN_GROUP(avb_avtp_capture_a),
@@ -3912,6 +4069,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
SH_PFC_PIN_GROUP(usb2),
+ SH_PFC_PIN_GROUP(qspi0_ctrl),
+ SH_PFC_PIN_GROUP(qspi0_data2),
+ SH_PFC_PIN_GROUP(qspi0_data4),
+ SH_PFC_PIN_GROUP(qspi1_ctrl),
+ SH_PFC_PIN_GROUP(qspi1_data2),
+ SH_PFC_PIN_GROUP(qspi1_data4),
};
static const char * const audio_clk_groups[] = {
@@ -3939,6 +4102,7 @@ static const char * const avb_groups[] = {
"avb_magic",
"avb_phy_int",
"avb_mdc",
+ "avb_mii",
"avb_avtp_pps",
"avb_avtp_match_a",
"avb_avtp_capture_a",
@@ -4356,6 +4520,18 @@ static const char * const usb2_groups[] = {
"usb2",
};
+static const char * const qspi0_groups[] = {
+ "qspi0_ctrl",
+ "qspi0_data2",
+ "qspi0_data4",
+};
+
+static const char * const qspi1_groups[] = {
+ "qspi1_ctrl",
+ "qspi1_data2",
+ "qspi1_data4",
+};
+
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
SH_PFC_FUNCTION(avb),
@@ -4405,6 +4581,8 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb2),
+ SH_PFC_FUNCTION(qspi0),
+ SH_PFC_FUNCTION(qspi1),
};
static const struct pinmux_cfg_reg pinmux_config_regs[] = {
@@ -4962,10 +5140,45 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
};
static const struct pinmux_drive_reg pinmux_drive_regs[] = {
+ { PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) {
+ { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */
+ { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */
+ { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */
+ { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */
+ { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */
+ { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */
+ { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */
+ { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */
+ } },
+ { PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) {
+ { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */
+ { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */
+ { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */
+ { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */
+ { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */
+ { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */
+ { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */
+ { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */
+ } },
+ { PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) {
+ { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */
+ { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */
+ { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */
+ { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */
+ { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */
+ { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */
+ { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */
+ { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */
+ } },
{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
- { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
- { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
- { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
+ { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */
+ { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */
+ { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */
+ { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */
+ { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */
+ { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
+ { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
} },
{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
{ RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */
@@ -5008,6 +5221,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(1, 19), 0, 3 }, /* A19 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) {
+ { PIN_NUMBER('F', 1), 28, 3 }, /* CLKOUT */
{ RCAR_GP_PIN(1, 20), 24, 3 }, /* CS0 */
{ RCAR_GP_PIN(1, 21), 20, 3 }, /* CS1_A26 */
{ RCAR_GP_PIN(1, 22), 16, 3 }, /* BS */
@@ -5018,6 +5232,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
} },
{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
{ RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */
+ { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */
{ RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */
{ RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */
{ RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */
@@ -5036,20 +5251,30 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
- { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
- { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
- { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
- { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
- { RCAR_GP_PIN(7, 2), 12, 3 }, /* HDMI0_CEC */
- { RCAR_GP_PIN(7, 3), 8, 3 }, /* HDMI1_CEC */
+ { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
+ { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
+ { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
+ { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 2), 12, 3 }, /* HDMI0_CEC */
+ { RCAR_GP_PIN(7, 3), 8, 3 }, /* HDMI1_CEC */
+ { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */
+ { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */
+ } },
+ { PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
+ { PIN_A_NUMBER('R', 7), 28, 2 }, /* DU_DOTCLKIN2 */
+ { PIN_A_NUMBER('R', 8), 24, 2 }, /* DU_DOTCLKIN3 */
+ { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST# */
+ { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */
} },
{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
- { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
- { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
- { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
- { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
- { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
- { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
+ { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */
+ { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */
+ { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
+ { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
{ RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */
@@ -5118,6 +5343,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */
{ RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */
{ RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */
+ { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */
{ RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
@@ -5188,206 +5414,206 @@ static int r8a7795_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *poc
#define PU5 0x14
#define PU6 0x18
-static const struct {
- u16 reg : 11;
- u16 bit : 5;
-} pullups[] = {
- [RCAR_GP_PIN(2, 11)] = { PU0, 31 }, /* AVB_PHY_INT */
- [RCAR_GP_PIN(2, 10)] = { PU0, 30 }, /* AVB_MAGIC */
- [RCAR_GP_PIN(2, 9)] = { PU0, 29 }, /* AVB_MDC */
-
- [RCAR_GP_PIN(1, 19)] = { PU1, 31 }, /* A19 */
- [RCAR_GP_PIN(1, 18)] = { PU1, 30 }, /* A18 */
- [RCAR_GP_PIN(1, 17)] = { PU1, 29 }, /* A17 */
- [RCAR_GP_PIN(1, 16)] = { PU1, 28 }, /* A16 */
- [RCAR_GP_PIN(1, 15)] = { PU1, 27 }, /* A15 */
- [RCAR_GP_PIN(1, 14)] = { PU1, 26 }, /* A14 */
- [RCAR_GP_PIN(1, 13)] = { PU1, 25 }, /* A13 */
- [RCAR_GP_PIN(1, 12)] = { PU1, 24 }, /* A12 */
- [RCAR_GP_PIN(1, 11)] = { PU1, 23 }, /* A11 */
- [RCAR_GP_PIN(1, 10)] = { PU1, 22 }, /* A10 */
- [RCAR_GP_PIN(1, 9)] = { PU1, 21 }, /* A9 */
- [RCAR_GP_PIN(1, 8)] = { PU1, 20 }, /* A8 */
- [RCAR_GP_PIN(1, 7)] = { PU1, 19 }, /* A7 */
- [RCAR_GP_PIN(1, 6)] = { PU1, 18 }, /* A6 */
- [RCAR_GP_PIN(1, 5)] = { PU1, 17 }, /* A5 */
- [RCAR_GP_PIN(1, 4)] = { PU1, 16 }, /* A4 */
- [RCAR_GP_PIN(1, 3)] = { PU1, 15 }, /* A3 */
- [RCAR_GP_PIN(1, 2)] = { PU1, 14 }, /* A2 */
- [RCAR_GP_PIN(1, 1)] = { PU1, 13 }, /* A1 */
- [RCAR_GP_PIN(1, 0)] = { PU1, 12 }, /* A0 */
- [RCAR_GP_PIN(2, 8)] = { PU1, 11 }, /* PWM2_A */
- [RCAR_GP_PIN(2, 7)] = { PU1, 10 }, /* PWM1_A */
- [RCAR_GP_PIN(2, 6)] = { PU1, 9 }, /* PWM0 */
- [RCAR_GP_PIN(2, 5)] = { PU1, 8 }, /* IRQ5 */
- [RCAR_GP_PIN(2, 4)] = { PU1, 7 }, /* IRQ4 */
- [RCAR_GP_PIN(2, 3)] = { PU1, 6 }, /* IRQ3 */
- [RCAR_GP_PIN(2, 2)] = { PU1, 5 }, /* IRQ2 */
- [RCAR_GP_PIN(2, 1)] = { PU1, 4 }, /* IRQ1 */
- [RCAR_GP_PIN(2, 0)] = { PU1, 3 }, /* IRQ0 */
- [RCAR_GP_PIN(2, 14)] = { PU1, 2 }, /* AVB_AVTP_CAPTURE_A */
- [RCAR_GP_PIN(2, 13)] = { PU1, 1 }, /* AVB_AVTP_MATCH_A */
- [RCAR_GP_PIN(2, 12)] = { PU1, 0 }, /* AVB_LINK */
-
- [RCAR_GP_PIN(7, 3)] = { PU2, 29 }, /* HDMI1_CEC */
- [RCAR_GP_PIN(7, 2)] = { PU2, 28 }, /* HDMI0_CEC */
- [RCAR_GP_PIN(7, 1)] = { PU2, 27 }, /* AVS2 */
- [RCAR_GP_PIN(7, 0)] = { PU2, 26 }, /* AVS1 */
- [RCAR_GP_PIN(0, 15)] = { PU2, 25 }, /* D15 */
- [RCAR_GP_PIN(0, 14)] = { PU2, 24 }, /* D14 */
- [RCAR_GP_PIN(0, 13)] = { PU2, 23 }, /* D13 */
- [RCAR_GP_PIN(0, 12)] = { PU2, 22 }, /* D12 */
- [RCAR_GP_PIN(0, 11)] = { PU2, 21 }, /* D11 */
- [RCAR_GP_PIN(0, 10)] = { PU2, 20 }, /* D10 */
- [RCAR_GP_PIN(0, 9)] = { PU2, 19 }, /* D9 */
- [RCAR_GP_PIN(0, 8)] = { PU2, 18 }, /* D8 */
- [RCAR_GP_PIN(0, 7)] = { PU2, 17 }, /* D7 */
- [RCAR_GP_PIN(0, 6)] = { PU2, 16 }, /* D6 */
- [RCAR_GP_PIN(0, 5)] = { PU2, 15 }, /* D5 */
- [RCAR_GP_PIN(0, 4)] = { PU2, 14 }, /* D4 */
- [RCAR_GP_PIN(0, 3)] = { PU2, 13 }, /* D3 */
- [RCAR_GP_PIN(0, 2)] = { PU2, 12 }, /* D2 */
- [RCAR_GP_PIN(0, 1)] = { PU2, 11 }, /* D1 */
- [RCAR_GP_PIN(0, 0)] = { PU2, 10 }, /* D0 */
- [RCAR_GP_PIN(1, 27)] = { PU2, 8 }, /* EX_WAIT0_A */
- [RCAR_GP_PIN(1, 26)] = { PU2, 7 }, /* WE1_N */
- [RCAR_GP_PIN(1, 25)] = { PU2, 6 }, /* WE0_N */
- [RCAR_GP_PIN(1, 24)] = { PU2, 5 }, /* RD_WR_N */
- [RCAR_GP_PIN(1, 23)] = { PU2, 4 }, /* RD_N */
- [RCAR_GP_PIN(1, 22)] = { PU2, 3 }, /* BS_N */
- [RCAR_GP_PIN(1, 21)] = { PU2, 2 }, /* CS1_N_A26 */
- [RCAR_GP_PIN(1, 20)] = { PU2, 1 }, /* CS0_N */
-
- [RCAR_GP_PIN(4, 9)] = { PU3, 31 }, /* SD3_DAT0 */
- [RCAR_GP_PIN(4, 8)] = { PU3, 30 }, /* SD3_CMD */
- [RCAR_GP_PIN(4, 7)] = { PU3, 29 }, /* SD3_CLK */
- [RCAR_GP_PIN(4, 6)] = { PU3, 28 }, /* SD2_DS */
- [RCAR_GP_PIN(4, 5)] = { PU3, 27 }, /* SD2_DAT3 */
- [RCAR_GP_PIN(4, 4)] = { PU3, 26 }, /* SD2_DAT2 */
- [RCAR_GP_PIN(4, 3)] = { PU3, 25 }, /* SD2_DAT1 */
- [RCAR_GP_PIN(4, 2)] = { PU3, 24 }, /* SD2_DAT0 */
- [RCAR_GP_PIN(4, 1)] = { PU3, 23 }, /* SD2_CMD */
- [RCAR_GP_PIN(4, 0)] = { PU3, 22 }, /* SD2_CLK */
- [RCAR_GP_PIN(3, 11)] = { PU3, 21 }, /* SD1_DAT3 */
- [RCAR_GP_PIN(3, 10)] = { PU3, 20 }, /* SD1_DAT2 */
- [RCAR_GP_PIN(3, 9)] = { PU3, 19 }, /* SD1_DAT1 */
- [RCAR_GP_PIN(3, 8)] = { PU3, 18 }, /* SD1_DAT0 */
- [RCAR_GP_PIN(3, 7)] = { PU3, 17 }, /* SD1_CMD */
- [RCAR_GP_PIN(3, 6)] = { PU3, 16 }, /* SD1_CLK */
- [RCAR_GP_PIN(3, 5)] = { PU3, 15 }, /* SD0_DAT3 */
- [RCAR_GP_PIN(3, 4)] = { PU3, 14 }, /* SD0_DAT2 */
- [RCAR_GP_PIN(3, 3)] = { PU3, 13 }, /* SD0_DAT1 */
- [RCAR_GP_PIN(3, 2)] = { PU3, 12 }, /* SD0_DAT0 */
- [RCAR_GP_PIN(3, 1)] = { PU3, 11 }, /* SD0_CMD */
- [RCAR_GP_PIN(3, 0)] = { PU3, 10 }, /* SD0_CLK */
-
- [RCAR_GP_PIN(5, 19)] = { PU4, 31 }, /* MSIOF0_SS1 */
- [RCAR_GP_PIN(5, 18)] = { PU4, 30 }, /* MSIOF0_SYNC */
- [RCAR_GP_PIN(5, 17)] = { PU4, 29 }, /* MSIOF0_SCK */
- [RCAR_GP_PIN(5, 16)] = { PU4, 28 }, /* HRTS0_N */
- [RCAR_GP_PIN(5, 15)] = { PU4, 27 }, /* HCTS0_N */
- [RCAR_GP_PIN(5, 14)] = { PU4, 26 }, /* HTX0 */
- [RCAR_GP_PIN(5, 13)] = { PU4, 25 }, /* HRX0 */
- [RCAR_GP_PIN(5, 12)] = { PU4, 24 }, /* HSCK0 */
- [RCAR_GP_PIN(5, 11)] = { PU4, 23 }, /* RX2_A */
- [RCAR_GP_PIN(5, 10)] = { PU4, 22 }, /* TX2_A */
- [RCAR_GP_PIN(5, 9)] = { PU4, 21 }, /* SCK2 */
- [RCAR_GP_PIN(5, 8)] = { PU4, 20 }, /* RTS1_N_TANS */
- [RCAR_GP_PIN(5, 7)] = { PU4, 19 }, /* CTS1_N */
- [RCAR_GP_PIN(5, 6)] = { PU4, 18 }, /* TX1_A */
- [RCAR_GP_PIN(5, 5)] = { PU4, 17 }, /* RX1_A */
- [RCAR_GP_PIN(5, 4)] = { PU4, 16 }, /* RTS0_N_TANS */
- [RCAR_GP_PIN(5, 3)] = { PU4, 15 }, /* CTS0_N */
- [RCAR_GP_PIN(5, 2)] = { PU4, 14 }, /* TX0 */
- [RCAR_GP_PIN(5, 1)] = { PU4, 13 }, /* RX0 */
- [RCAR_GP_PIN(5, 0)] = { PU4, 12 }, /* SCK0 */
- [RCAR_GP_PIN(3, 15)] = { PU4, 11 }, /* SD1_WP */
- [RCAR_GP_PIN(3, 14)] = { PU4, 10 }, /* SD1_CD */
- [RCAR_GP_PIN(3, 13)] = { PU4, 9 }, /* SD0_WP */
- [RCAR_GP_PIN(3, 12)] = { PU4, 8 }, /* SD0_CD */
- [RCAR_GP_PIN(4, 17)] = { PU4, 7 }, /* SD3_DS */
- [RCAR_GP_PIN(4, 16)] = { PU4, 6 }, /* SD3_DAT7 */
- [RCAR_GP_PIN(4, 15)] = { PU4, 5 }, /* SD3_DAT6 */
- [RCAR_GP_PIN(4, 14)] = { PU4, 4 }, /* SD3_DAT5 */
- [RCAR_GP_PIN(4, 13)] = { PU4, 3 }, /* SD3_DAT4 */
- [RCAR_GP_PIN(4, 12)] = { PU4, 2 }, /* SD3_DAT3 */
- [RCAR_GP_PIN(4, 11)] = { PU4, 1 }, /* SD3_DAT2 */
- [RCAR_GP_PIN(4, 10)] = { PU4, 0 }, /* SD3_DAT1 */
-
- [RCAR_GP_PIN(6, 24)] = { PU5, 31 }, /* USB0_PWEN */
- [RCAR_GP_PIN(6, 23)] = { PU5, 30 }, /* AUDIO_CLKB_B */
- [RCAR_GP_PIN(6, 22)] = { PU5, 29 }, /* AUDIO_CLKA_A */
- [RCAR_GP_PIN(6, 21)] = { PU5, 28 }, /* SSI_SDATA9_A */
- [RCAR_GP_PIN(6, 20)] = { PU5, 27 }, /* SSI_SDATA8 */
- [RCAR_GP_PIN(6, 19)] = { PU5, 26 }, /* SSI_SDATA7 */
- [RCAR_GP_PIN(6, 18)] = { PU5, 25 }, /* SSI_WS78 */
- [RCAR_GP_PIN(6, 17)] = { PU5, 24 }, /* SSI_SCK78 */
- [RCAR_GP_PIN(6, 16)] = { PU5, 23 }, /* SSI_SDATA6 */
- [RCAR_GP_PIN(6, 15)] = { PU5, 22 }, /* SSI_WS6 */
- [RCAR_GP_PIN(6, 14)] = { PU5, 21 }, /* SSI_SCK6 */
- [RCAR_GP_PIN(6, 13)] = { PU5, 20 }, /* SSI_SDATA5 */
- [RCAR_GP_PIN(6, 12)] = { PU5, 19 }, /* SSI_WS5 */
- [RCAR_GP_PIN(6, 11)] = { PU5, 18 }, /* SSI_SCK5 */
- [RCAR_GP_PIN(6, 10)] = { PU5, 17 }, /* SSI_SDATA4 */
- [RCAR_GP_PIN(6, 9)] = { PU5, 16 }, /* SSI_WS4 */
- [RCAR_GP_PIN(6, 8)] = { PU5, 15 }, /* SSI_SCK4 */
- [RCAR_GP_PIN(6, 7)] = { PU5, 14 }, /* SSI_SDATA3 */
- [RCAR_GP_PIN(6, 6)] = { PU5, 13 }, /* SSI_WS34 */
- [RCAR_GP_PIN(6, 5)] = { PU5, 12 }, /* SSI_SCK34 */
- [RCAR_GP_PIN(6, 4)] = { PU5, 11 }, /* SSI_SDATA2_A */
- [RCAR_GP_PIN(6, 3)] = { PU5, 10 }, /* SSI_SDATA1_A */
- [RCAR_GP_PIN(6, 2)] = { PU5, 9 }, /* SSI_SDATA0 */
- [RCAR_GP_PIN(6, 1)] = { PU5, 8 }, /* SSI_WS01239 */
- [RCAR_GP_PIN(6, 0)] = { PU5, 7 }, /* SSI_SCK01239 */
- [RCAR_GP_PIN(5, 25)] = { PU5, 5 }, /* MLB_DAT */
- [RCAR_GP_PIN(5, 24)] = { PU5, 4 }, /* MLB_SIG */
- [RCAR_GP_PIN(5, 23)] = { PU5, 3 }, /* MLB_CLK */
- [RCAR_GP_PIN(5, 22)] = { PU5, 2 }, /* MSIOF0_RXD */
- [RCAR_GP_PIN(5, 21)] = { PU5, 1 }, /* MSIOF0_SS2 */
- [RCAR_GP_PIN(5, 20)] = { PU5, 0 }, /* MSIOF0_TXD */
-
- [RCAR_GP_PIN(6, 31)] = { PU6, 6 }, /* USB31_OVC */
- [RCAR_GP_PIN(6, 30)] = { PU6, 5 }, /* USB31_PWEN */
- [RCAR_GP_PIN(6, 29)] = { PU6, 4 }, /* USB30_OVC */
- [RCAR_GP_PIN(6, 28)] = { PU6, 3 }, /* USB30_PWEN */
- [RCAR_GP_PIN(6, 27)] = { PU6, 2 }, /* USB1_OVC */
- [RCAR_GP_PIN(6, 26)] = { PU6, 1 }, /* USB1_PWEN */
- [RCAR_GP_PIN(6, 25)] = { PU6, 0 }, /* USB0_OVC */
+static const struct sh_pfc_bias_info bias_info[] = {
+ { RCAR_GP_PIN(2, 11), PU0, 31 }, /* AVB_PHY_INT */
+ { RCAR_GP_PIN(2, 10), PU0, 30 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 9), PU0, 29 }, /* AVB_MDC */
+
+ { RCAR_GP_PIN(1, 19), PU1, 31 }, /* A19 */
+ { RCAR_GP_PIN(1, 18), PU1, 30 }, /* A18 */
+ { RCAR_GP_PIN(1, 17), PU1, 29 }, /* A17 */
+ { RCAR_GP_PIN(1, 16), PU1, 28 }, /* A16 */
+ { RCAR_GP_PIN(1, 15), PU1, 27 }, /* A15 */
+ { RCAR_GP_PIN(1, 14), PU1, 26 }, /* A14 */
+ { RCAR_GP_PIN(1, 13), PU1, 25 }, /* A13 */
+ { RCAR_GP_PIN(1, 12), PU1, 24 }, /* A12 */
+ { RCAR_GP_PIN(1, 11), PU1, 23 }, /* A11 */
+ { RCAR_GP_PIN(1, 10), PU1, 22 }, /* A10 */
+ { RCAR_GP_PIN(1, 9), PU1, 21 }, /* A9 */
+ { RCAR_GP_PIN(1, 8), PU1, 20 }, /* A8 */
+ { RCAR_GP_PIN(1, 7), PU1, 19 }, /* A7 */
+ { RCAR_GP_PIN(1, 6), PU1, 18 }, /* A6 */
+ { RCAR_GP_PIN(1, 5), PU1, 17 }, /* A5 */
+ { RCAR_GP_PIN(1, 4), PU1, 16 }, /* A4 */
+ { RCAR_GP_PIN(1, 3), PU1, 15 }, /* A3 */
+ { RCAR_GP_PIN(1, 2), PU1, 14 }, /* A2 */
+ { RCAR_GP_PIN(1, 1), PU1, 13 }, /* A1 */
+ { RCAR_GP_PIN(1, 0), PU1, 12 }, /* A0 */
+ { RCAR_GP_PIN(2, 8), PU1, 11 }, /* PWM2_A */
+ { RCAR_GP_PIN(2, 7), PU1, 10 }, /* PWM1_A */
+ { RCAR_GP_PIN(2, 6), PU1, 9 }, /* PWM0 */
+ { RCAR_GP_PIN(2, 5), PU1, 8 }, /* IRQ5 */
+ { RCAR_GP_PIN(2, 4), PU1, 7 }, /* IRQ4 */
+ { RCAR_GP_PIN(2, 3), PU1, 6 }, /* IRQ3 */
+ { RCAR_GP_PIN(2, 2), PU1, 5 }, /* IRQ2 */
+ { RCAR_GP_PIN(2, 1), PU1, 4 }, /* IRQ1 */
+ { RCAR_GP_PIN(2, 0), PU1, 3 }, /* IRQ0 */
+ { RCAR_GP_PIN(2, 14), PU1, 2 }, /* AVB_AVTP_CAPTURE_A */
+ { RCAR_GP_PIN(2, 13), PU1, 1 }, /* AVB_AVTP_MATCH_A */
+ { RCAR_GP_PIN(2, 12), PU1, 0 }, /* AVB_LINK */
+
+ { RCAR_GP_PIN(7, 3), PU2, 29 }, /* HDMI1_CEC */
+ { RCAR_GP_PIN(7, 2), PU2, 28 }, /* HDMI0_CEC */
+ { RCAR_GP_PIN(7, 1), PU2, 27 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 0), PU2, 26 }, /* AVS1 */
+ { RCAR_GP_PIN(0, 15), PU2, 25 }, /* D15 */
+ { RCAR_GP_PIN(0, 14), PU2, 24 }, /* D14 */
+ { RCAR_GP_PIN(0, 13), PU2, 23 }, /* D13 */
+ { RCAR_GP_PIN(0, 12), PU2, 22 }, /* D12 */
+ { RCAR_GP_PIN(0, 11), PU2, 21 }, /* D11 */
+ { RCAR_GP_PIN(0, 10), PU2, 20 }, /* D10 */
+ { RCAR_GP_PIN(0, 9), PU2, 19 }, /* D9 */
+ { RCAR_GP_PIN(0, 8), PU2, 18 }, /* D8 */
+ { RCAR_GP_PIN(0, 7), PU2, 17 }, /* D7 */
+ { RCAR_GP_PIN(0, 6), PU2, 16 }, /* D6 */
+ { RCAR_GP_PIN(0, 5), PU2, 15 }, /* D5 */
+ { RCAR_GP_PIN(0, 4), PU2, 14 }, /* D4 */
+ { RCAR_GP_PIN(0, 3), PU2, 13 }, /* D3 */
+ { RCAR_GP_PIN(0, 2), PU2, 12 }, /* D2 */
+ { RCAR_GP_PIN(0, 1), PU2, 11 }, /* D1 */
+ { RCAR_GP_PIN(0, 0), PU2, 10 }, /* D0 */
+ { RCAR_GP_PIN(1, 27), PU2, 8 }, /* EX_WAIT0_A */
+ { RCAR_GP_PIN(1, 26), PU2, 7 }, /* WE1_N */
+ { RCAR_GP_PIN(1, 25), PU2, 6 }, /* WE0_N */
+ { RCAR_GP_PIN(1, 24), PU2, 5 }, /* RD_WR_N */
+ { RCAR_GP_PIN(1, 23), PU2, 4 }, /* RD_N */
+ { RCAR_GP_PIN(1, 22), PU2, 3 }, /* BS_N */
+ { RCAR_GP_PIN(1, 21), PU2, 2 }, /* CS1_N_A26 */
+ { RCAR_GP_PIN(1, 20), PU2, 1 }, /* CS0_N */
+
+ { RCAR_GP_PIN(4, 9), PU3, 31 }, /* SD3_DAT0 */
+ { RCAR_GP_PIN(4, 8), PU3, 30 }, /* SD3_CMD */
+ { RCAR_GP_PIN(4, 7), PU3, 29 }, /* SD3_CLK */
+ { RCAR_GP_PIN(4, 6), PU3, 28 }, /* SD2_DS */
+ { RCAR_GP_PIN(4, 5), PU3, 27 }, /* SD2_DAT3 */
+ { RCAR_GP_PIN(4, 4), PU3, 26 }, /* SD2_DAT2 */
+ { RCAR_GP_PIN(4, 3), PU3, 25 }, /* SD2_DAT1 */
+ { RCAR_GP_PIN(4, 2), PU3, 24 }, /* SD2_DAT0 */
+ { RCAR_GP_PIN(4, 1), PU3, 23 }, /* SD2_CMD */
+ { RCAR_GP_PIN(4, 0), PU3, 22 }, /* SD2_CLK */
+ { RCAR_GP_PIN(3, 11), PU3, 21 }, /* SD1_DAT3 */
+ { RCAR_GP_PIN(3, 10), PU3, 20 }, /* SD1_DAT2 */
+ { RCAR_GP_PIN(3, 9), PU3, 19 }, /* SD1_DAT1 */
+ { RCAR_GP_PIN(3, 8), PU3, 18 }, /* SD1_DAT0 */
+ { RCAR_GP_PIN(3, 7), PU3, 17 }, /* SD1_CMD */
+ { RCAR_GP_PIN(3, 6), PU3, 16 }, /* SD1_CLK */
+ { RCAR_GP_PIN(3, 5), PU3, 15 }, /* SD0_DAT3 */
+ { RCAR_GP_PIN(3, 4), PU3, 14 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 3), PU3, 13 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 2), PU3, 12 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 1), PU3, 11 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 0), PU3, 10 }, /* SD0_CLK */
+
+ { RCAR_GP_PIN(5, 19), PU4, 31 }, /* MSIOF0_SS1 */
+ { RCAR_GP_PIN(5, 18), PU4, 30 }, /* MSIOF0_SYNC */
+ { RCAR_GP_PIN(5, 17), PU4, 29 }, /* MSIOF0_SCK */
+ { RCAR_GP_PIN(5, 16), PU4, 28 }, /* HRTS0_N */
+ { RCAR_GP_PIN(5, 15), PU4, 27 }, /* HCTS0_N */
+ { RCAR_GP_PIN(5, 14), PU4, 26 }, /* HTX0 */
+ { RCAR_GP_PIN(5, 13), PU4, 25 }, /* HRX0 */
+ { RCAR_GP_PIN(5, 12), PU4, 24 }, /* HSCK0 */
+ { RCAR_GP_PIN(5, 11), PU4, 23 }, /* RX2_A */
+ { RCAR_GP_PIN(5, 10), PU4, 22 }, /* TX2_A */
+ { RCAR_GP_PIN(5, 9), PU4, 21 }, /* SCK2 */
+ { RCAR_GP_PIN(5, 8), PU4, 20 }, /* RTS1_N_TANS */
+ { RCAR_GP_PIN(5, 7), PU4, 19 }, /* CTS1_N */
+ { RCAR_GP_PIN(5, 6), PU4, 18 }, /* TX1_A */
+ { RCAR_GP_PIN(5, 5), PU4, 17 }, /* RX1_A */
+ { RCAR_GP_PIN(5, 4), PU4, 16 }, /* RTS0_N_TANS */
+ { RCAR_GP_PIN(5, 3), PU4, 15 }, /* CTS0_N */
+ { RCAR_GP_PIN(5, 2), PU4, 14 }, /* TX0 */
+ { RCAR_GP_PIN(5, 1), PU4, 13 }, /* RX0 */
+ { RCAR_GP_PIN(5, 0), PU4, 12 }, /* SCK0 */
+ { RCAR_GP_PIN(3, 15), PU4, 11 }, /* SD1_WP */
+ { RCAR_GP_PIN(3, 14), PU4, 10 }, /* SD1_CD */
+ { RCAR_GP_PIN(3, 13), PU4, 9 }, /* SD0_WP */
+ { RCAR_GP_PIN(3, 12), PU4, 8 }, /* SD0_CD */
+ { RCAR_GP_PIN(4, 17), PU4, 7 }, /* SD3_DS */
+ { RCAR_GP_PIN(4, 16), PU4, 6 }, /* SD3_DAT7 */
+ { RCAR_GP_PIN(4, 15), PU4, 5 }, /* SD3_DAT6 */
+ { RCAR_GP_PIN(4, 14), PU4, 4 }, /* SD3_DAT5 */
+ { RCAR_GP_PIN(4, 13), PU4, 3 }, /* SD3_DAT4 */
+ { RCAR_GP_PIN(4, 12), PU4, 2 }, /* SD3_DAT3 */
+ { RCAR_GP_PIN(4, 11), PU4, 1 }, /* SD3_DAT2 */
+ { RCAR_GP_PIN(4, 10), PU4, 0 }, /* SD3_DAT1 */
+
+ { RCAR_GP_PIN(6, 24), PU5, 31 }, /* USB0_PWEN */
+ { RCAR_GP_PIN(6, 23), PU5, 30 }, /* AUDIO_CLKB_B */
+ { RCAR_GP_PIN(6, 22), PU5, 29 }, /* AUDIO_CLKA_A */
+ { RCAR_GP_PIN(6, 21), PU5, 28 }, /* SSI_SDATA9_A */
+ { RCAR_GP_PIN(6, 20), PU5, 27 }, /* SSI_SDATA8 */
+ { RCAR_GP_PIN(6, 19), PU5, 26 }, /* SSI_SDATA7 */
+ { RCAR_GP_PIN(6, 18), PU5, 25 }, /* SSI_WS78 */
+ { RCAR_GP_PIN(6, 17), PU5, 24 }, /* SSI_SCK78 */
+ { RCAR_GP_PIN(6, 16), PU5, 23 }, /* SSI_SDATA6 */
+ { RCAR_GP_PIN(6, 15), PU5, 22 }, /* SSI_WS6 */
+ { RCAR_GP_PIN(6, 14), PU5, 21 }, /* SSI_SCK6 */
+ { RCAR_GP_PIN(6, 13), PU5, 20 }, /* SSI_SDATA5 */
+ { RCAR_GP_PIN(6, 12), PU5, 19 }, /* SSI_WS5 */
+ { RCAR_GP_PIN(6, 11), PU5, 18 }, /* SSI_SCK5 */
+ { RCAR_GP_PIN(6, 10), PU5, 17 }, /* SSI_SDATA4 */
+ { RCAR_GP_PIN(6, 9), PU5, 16 }, /* SSI_WS4 */
+ { RCAR_GP_PIN(6, 8), PU5, 15 }, /* SSI_SCK4 */
+ { RCAR_GP_PIN(6, 7), PU5, 14 }, /* SSI_SDATA3 */
+ { RCAR_GP_PIN(6, 6), PU5, 13 }, /* SSI_WS34 */
+ { RCAR_GP_PIN(6, 5), PU5, 12 }, /* SSI_SCK34 */
+ { RCAR_GP_PIN(6, 4), PU5, 11 }, /* SSI_SDATA2_A */
+ { RCAR_GP_PIN(6, 3), PU5, 10 }, /* SSI_SDATA1_A */
+ { RCAR_GP_PIN(6, 2), PU5, 9 }, /* SSI_SDATA0 */
+ { RCAR_GP_PIN(6, 1), PU5, 8 }, /* SSI_WS01239 */
+ { RCAR_GP_PIN(6, 0), PU5, 7 }, /* SSI_SCK01239 */
+ { RCAR_GP_PIN(5, 25), PU5, 5 }, /* MLB_DAT */
+ { RCAR_GP_PIN(5, 24), PU5, 4 }, /* MLB_SIG */
+ { RCAR_GP_PIN(5, 23), PU5, 3 }, /* MLB_CLK */
+ { RCAR_GP_PIN(5, 22), PU5, 2 }, /* MSIOF0_RXD */
+ { RCAR_GP_PIN(5, 21), PU5, 1 }, /* MSIOF0_SS2 */
+ { RCAR_GP_PIN(5, 20), PU5, 0 }, /* MSIOF0_TXD */
+
+ { RCAR_GP_PIN(6, 31), PU6, 6 }, /* USB31_OVC */
+ { RCAR_GP_PIN(6, 30), PU6, 5 }, /* USB31_PWEN */
+ { RCAR_GP_PIN(6, 29), PU6, 4 }, /* USB30_OVC */
+ { RCAR_GP_PIN(6, 28), PU6, 3 }, /* USB30_PWEN */
+ { RCAR_GP_PIN(6, 27), PU6, 2 }, /* USB1_OVC */
+ { RCAR_GP_PIN(6, 26), PU6, 1 }, /* USB1_PWEN */
+ { RCAR_GP_PIN(6, 25), PU6, 0 }, /* USB0_OVC */
};
static unsigned int r8a7795_pinmux_get_bias(struct sh_pfc *pfc,
unsigned int pin)
{
+ const struct sh_pfc_bias_info *info;
u32 reg;
u32 bit;
- if (WARN_ON_ONCE(!pullups[pin].reg))
+ info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin);
+ if (!info)
return PIN_CONFIG_BIAS_DISABLE;
- reg = pullups[pin].reg;
- bit = BIT(pullups[pin].bit);
+ reg = info->reg;
+ bit = BIT(info->bit);
- if (sh_pfc_read_reg(pfc, PUEN + reg, 32) & bit) {
- if (sh_pfc_read_reg(pfc, PUD + reg, 32) & bit)
- return PIN_CONFIG_BIAS_PULL_UP;
- else
- return PIN_CONFIG_BIAS_PULL_DOWN;
- } else
+ if (!(sh_pfc_read_reg(pfc, PUEN + reg, 32) & bit))
return PIN_CONFIG_BIAS_DISABLE;
+ else if (sh_pfc_read_reg(pfc, PUD + reg, 32) & bit)
+ return PIN_CONFIG_BIAS_PULL_UP;
+ else
+ return PIN_CONFIG_BIAS_PULL_DOWN;
}
static void r8a7795_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
unsigned int bias)
{
+ const struct sh_pfc_bias_info *info;
u32 enable, updown;
u32 reg;
u32 bit;
- if (WARN_ON_ONCE(!pullups[pin].reg))
+ info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin);
+ if (!info)
return;
- reg = pullups[pin].reg;
- bit = BIT(pullups[pin].bit);
+ reg = info->reg;
+ bit = BIT(info->bit);
enable = sh_pfc_read_reg(pfc, PUEN + reg, 32) & ~bit;
if (bias != PIN_CONFIG_BIAS_DISABLE)
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
index dc9b671ccf2e..7e16545a2c3c 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
@@ -122,22 +122,22 @@
#define GPSR3_0 F_(SD0_CLK, IP7_19_16)
/* GPSR4 */
-#define GPSR4_17 F_(SD3_DS, IP11_11_8)
-#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_17 F_(SD3_DS, IP11_7_4)
+#define GPSR4_16 F_(SD3_DAT7, IP11_3_0)
+#define GPSR4_15 F_(SD3_DAT6, IP10_31_28)
+#define GPSR4_14 F_(SD3_DAT5, IP10_27_24)
+#define GPSR4_13 F_(SD3_DAT4, IP10_23_20)
#define GPSR4_12 F_(SD3_DAT3, IP10_19_16)
#define GPSR4_11 F_(SD3_DAT2, IP10_15_12)
#define GPSR4_10 F_(SD3_DAT1, IP10_11_8)
#define GPSR4_9 F_(SD3_DAT0, IP10_7_4)
#define GPSR4_8 F_(SD3_CMD, IP10_3_0)
#define GPSR4_7 F_(SD3_CLK, IP9_31_28)
-#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_6 F_(SD2_DS, IP9_27_24)
+#define GPSR4_5 F_(SD2_DAT3, IP9_23_20)
+#define GPSR4_4 F_(SD2_DAT2, IP9_19_16)
+#define GPSR4_3 F_(SD2_DAT1, IP9_15_12)
+#define GPSR4_2 F_(SD2_DAT0, IP9_11_8)
#define GPSR4_1 F_(SD2_CMD, IP9_7_4)
#define GPSR4_0 F_(SD2_CLK, IP9_3_0)
@@ -1490,6 +1490,418 @@ static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
};
+/* - 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,
+};
+
+/* - DRIF0 --------------------------------------------------------------- */
+static const unsigned int drif0_ctrl_a_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9),
+};
+static const unsigned int drif0_ctrl_a_mux[] = {
+ RIF0_CLK_A_MARK, RIF0_SYNC_A_MARK,
+};
+static const unsigned int drif0_data0_a_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int drif0_data0_a_mux[] = {
+ RIF0_D0_A_MARK,
+};
+static const unsigned int drif0_data1_a_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 7),
+};
+static const unsigned int drif0_data1_a_mux[] = {
+ RIF0_D1_A_MARK,
+};
+static const unsigned int drif0_ctrl_b_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4),
+};
+static const unsigned int drif0_ctrl_b_mux[] = {
+ RIF0_CLK_B_MARK, RIF0_SYNC_B_MARK,
+};
+static const unsigned int drif0_data0_b_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(5, 1),
+};
+static const unsigned int drif0_data0_b_mux[] = {
+ RIF0_D0_B_MARK,
+};
+static const unsigned int drif0_data1_b_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(5, 2),
+};
+static const unsigned int drif0_data1_b_mux[] = {
+ RIF0_D1_B_MARK,
+};
+static const unsigned int drif0_ctrl_c_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 15),
+};
+static const unsigned int drif0_ctrl_c_mux[] = {
+ RIF0_CLK_C_MARK, RIF0_SYNC_C_MARK,
+};
+static const unsigned int drif0_data0_c_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(5, 13),
+};
+static const unsigned int drif0_data0_c_mux[] = {
+ RIF0_D0_C_MARK,
+};
+static const unsigned int drif0_data1_c_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(5, 14),
+};
+static const unsigned int drif0_data1_c_mux[] = {
+ RIF0_D1_C_MARK,
+};
+/* - DRIF1 --------------------------------------------------------------- */
+static const unsigned int drif1_ctrl_a_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18),
+};
+static const unsigned int drif1_ctrl_a_mux[] = {
+ RIF1_CLK_A_MARK, RIF1_SYNC_A_MARK,
+};
+static const unsigned int drif1_data0_a_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 19),
+};
+static const unsigned int drif1_data0_a_mux[] = {
+ RIF1_D0_A_MARK,
+};
+static const unsigned int drif1_data1_a_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 20),
+};
+static const unsigned int drif1_data1_a_mux[] = {
+ RIF1_D1_A_MARK,
+};
+static const unsigned int drif1_ctrl_b_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 3),
+};
+static const unsigned int drif1_ctrl_b_mux[] = {
+ RIF1_CLK_B_MARK, RIF1_SYNC_B_MARK,
+};
+static const unsigned int drif1_data0_b_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(5, 7),
+};
+static const unsigned int drif1_data0_b_mux[] = {
+ RIF1_D0_B_MARK,
+};
+static const unsigned int drif1_data1_b_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(5, 8),
+};
+static const unsigned int drif1_data1_b_mux[] = {
+ RIF1_D1_B_MARK,
+};
+static const unsigned int drif1_ctrl_c_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 11),
+};
+static const unsigned int drif1_ctrl_c_mux[] = {
+ RIF1_CLK_C_MARK, RIF1_SYNC_C_MARK,
+};
+static const unsigned int drif1_data0_c_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(5, 6),
+};
+static const unsigned int drif1_data0_c_mux[] = {
+ RIF1_D0_C_MARK,
+};
+static const unsigned int drif1_data1_c_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(5, 10),
+};
+static const unsigned int drif1_data1_c_mux[] = {
+ RIF1_D1_C_MARK,
+};
+/* - DRIF2 --------------------------------------------------------------- */
+static const unsigned int drif2_ctrl_a_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9),
+};
+static const unsigned int drif2_ctrl_a_mux[] = {
+ RIF2_CLK_A_MARK, RIF2_SYNC_A_MARK,
+};
+static const unsigned int drif2_data0_a_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 7),
+};
+static const unsigned int drif2_data0_a_mux[] = {
+ RIF2_D0_A_MARK,
+};
+static const unsigned int drif2_data1_a_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int drif2_data1_a_mux[] = {
+ RIF2_D1_A_MARK,
+};
+static const unsigned int drif2_ctrl_b_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27),
+};
+static const unsigned int drif2_ctrl_b_mux[] = {
+ RIF2_CLK_B_MARK, RIF2_SYNC_B_MARK,
+};
+static const unsigned int drif2_data0_b_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int drif2_data0_b_mux[] = {
+ RIF2_D0_B_MARK,
+};
+static const unsigned int drif2_data1_b_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int drif2_data1_b_mux[] = {
+ RIF2_D1_B_MARK,
+};
+/* - DRIF3 --------------------------------------------------------------- */
+static const unsigned int drif3_ctrl_a_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18),
+};
+static const unsigned int drif3_ctrl_a_mux[] = {
+ RIF3_CLK_A_MARK, RIF3_SYNC_A_MARK,
+};
+static const unsigned int drif3_data0_a_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 19),
+};
+static const unsigned int drif3_data0_a_mux[] = {
+ RIF3_D0_A_MARK,
+};
+static const unsigned int drif3_data1_a_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 20),
+};
+static const unsigned int drif3_data1_a_mux[] = {
+ RIF3_D1_A_MARK,
+};
+static const unsigned int drif3_ctrl_b_pins[] = {
+ /* CLK, SYNC */
+ RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25),
+};
+static const unsigned int drif3_ctrl_b_mux[] = {
+ RIF3_CLK_B_MARK, RIF3_SYNC_B_MARK,
+};
+static const unsigned int drif3_data0_b_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int drif3_data0_b_mux[] = {
+ RIF3_D0_B_MARK,
+};
+static const unsigned int drif3_data1_b_pins[] = {
+ /* D1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int drif3_data1_b_mux[] = {
+ RIF3_D1_B_MARK,
+};
+
+/* - DU --------------------------------------------------------------------- */
+static const unsigned int du_rgb666_pins[] = {
+ /* R[7:2], G[7:2], B[7:2] */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13),
+ RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10),
+ RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13),
+ RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 19), RCAR_GP_PIN(1, 18),
+ RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 5),
+ RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 2),
+};
+static const unsigned int du_rgb666_mux[] = {
+ DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK,
+ DU_DR3_MARK, DU_DR2_MARK,
+ DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK,
+ DU_DG3_MARK, DU_DG2_MARK,
+ DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK,
+ DU_DB3_MARK, DU_DB2_MARK,
+};
+static const unsigned int du_rgb888_pins[] = {
+ /* R[7:0], G[7:0], B[7:0] */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13),
+ RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10),
+ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8),
+ RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13),
+ RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 19), RCAR_GP_PIN(1, 18),
+ RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 16),
+ RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 5),
+ RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 2),
+ RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 0),
+};
+static const unsigned int du_rgb888_mux[] = {
+ DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK,
+ DU_DR3_MARK, DU_DR2_MARK, DU_DR1_MARK, DU_DR0_MARK,
+ DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK,
+ DU_DG3_MARK, DU_DG2_MARK, DU_DG1_MARK, DU_DG0_MARK,
+ DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK,
+ DU_DB3_MARK, DU_DB2_MARK, DU_DB1_MARK, DU_DB0_MARK,
+};
+static const unsigned int du_clk_out_0_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(1, 27),
+};
+static const unsigned int du_clk_out_0_mux[] = {
+ DU_DOTCLKOUT0_MARK
+};
+static const unsigned int du_clk_out_1_pins[] = {
+ /* CLKOUT */
+ RCAR_GP_PIN(2, 3),
+};
+static const unsigned int du_clk_out_1_mux[] = {
+ DU_DOTCLKOUT1_MARK
+};
+static const unsigned int du_sync_pins[] = {
+ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
+ RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 4),
+};
+static const unsigned int du_sync_mux[] = {
+ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK
+};
+static const unsigned int du_oddf_pins[] = {
+ /* EXDISP/EXODDF/EXCDE */
+ RCAR_GP_PIN(2, 2),
+};
+static const unsigned int du_oddf_mux[] = {
+ DU_EXODDF_DU_ODDF_DISP_CDE_MARK,
+};
+static const unsigned int du_cde_pins[] = {
+ /* CDE */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int du_cde_mux[] = {
+ DU_CDE_MARK,
+};
+static const unsigned int du_disp_pins[] = {
+ /* DISP */
+ RCAR_GP_PIN(2, 1),
+};
+static const unsigned int du_disp_mux[] = {
+ DU_DISP_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 */
@@ -1912,6 +2324,60 @@ static const unsigned int sdhi3_ds_mux[] = {
};
static const struct sh_pfc_pin_group pinmux_groups[] = {
+ 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(drif0_ctrl_a),
+ SH_PFC_PIN_GROUP(drif0_data0_a),
+ SH_PFC_PIN_GROUP(drif0_data1_a),
+ SH_PFC_PIN_GROUP(drif0_ctrl_b),
+ SH_PFC_PIN_GROUP(drif0_data0_b),
+ SH_PFC_PIN_GROUP(drif0_data1_b),
+ SH_PFC_PIN_GROUP(drif0_ctrl_c),
+ SH_PFC_PIN_GROUP(drif0_data0_c),
+ SH_PFC_PIN_GROUP(drif0_data1_c),
+ SH_PFC_PIN_GROUP(drif1_ctrl_a),
+ SH_PFC_PIN_GROUP(drif1_data0_a),
+ SH_PFC_PIN_GROUP(drif1_data1_a),
+ SH_PFC_PIN_GROUP(drif1_ctrl_b),
+ SH_PFC_PIN_GROUP(drif1_data0_b),
+ SH_PFC_PIN_GROUP(drif1_data1_b),
+ SH_PFC_PIN_GROUP(drif1_ctrl_c),
+ SH_PFC_PIN_GROUP(drif1_data0_c),
+ SH_PFC_PIN_GROUP(drif1_data1_c),
+ SH_PFC_PIN_GROUP(drif2_ctrl_a),
+ SH_PFC_PIN_GROUP(drif2_data0_a),
+ SH_PFC_PIN_GROUP(drif2_data1_a),
+ SH_PFC_PIN_GROUP(drif2_ctrl_b),
+ SH_PFC_PIN_GROUP(drif2_data0_b),
+ SH_PFC_PIN_GROUP(drif2_data1_b),
+ SH_PFC_PIN_GROUP(drif3_ctrl_a),
+ SH_PFC_PIN_GROUP(drif3_data0_a),
+ SH_PFC_PIN_GROUP(drif3_data1_a),
+ SH_PFC_PIN_GROUP(drif3_ctrl_b),
+ SH_PFC_PIN_GROUP(drif3_data0_b),
+ SH_PFC_PIN_GROUP(drif3_data1_b),
+ SH_PFC_PIN_GROUP(du_rgb666),
+ SH_PFC_PIN_GROUP(du_rgb888),
+ SH_PFC_PIN_GROUP(du_clk_out_0),
+ SH_PFC_PIN_GROUP(du_clk_out_1),
+ SH_PFC_PIN_GROUP(du_sync),
+ SH_PFC_PIN_GROUP(du_oddf),
+ SH_PFC_PIN_GROUP(du_cde),
+ SH_PFC_PIN_GROUP(du_disp),
+ 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),
@@ -1969,6 +2435,87 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(sdhi3_ds),
};
+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 drif0_groups[] = {
+ "drif0_ctrl_a",
+ "drif0_data0_a",
+ "drif0_data1_a",
+ "drif0_ctrl_b",
+ "drif0_data0_b",
+ "drif0_data1_b",
+ "drif0_ctrl_c",
+ "drif0_data0_c",
+ "drif0_data1_c",
+};
+
+static const char * const drif1_groups[] = {
+ "drif1_ctrl_a",
+ "drif1_data0_a",
+ "drif1_data1_a",
+ "drif1_ctrl_b",
+ "drif1_data0_b",
+ "drif1_data1_b",
+ "drif1_ctrl_c",
+ "drif1_data0_c",
+ "drif1_data1_c",
+};
+
+static const char * const drif2_groups[] = {
+ "drif2_ctrl_a",
+ "drif2_data0_a",
+ "drif2_data1_a",
+ "drif2_ctrl_b",
+ "drif2_data0_b",
+ "drif2_data1_b",
+};
+
+static const char * const drif3_groups[] = {
+ "drif3_ctrl_a",
+ "drif3_data0_a",
+ "drif3_data1_a",
+ "drif3_ctrl_b",
+ "drif3_data0_b",
+ "drif3_data1_b",
+};
+
+static const char * const du_groups[] = {
+ "du_rgb666",
+ "du_rgb888",
+ "du_clk_out_0",
+ "du_clk_out_1",
+ "du_sync",
+ "du_oddf",
+ "du_cde",
+ "du_disp",
+};
+
+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",
@@ -2058,6 +2605,15 @@ static const char * const sdhi3_groups[] = {
};
static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(avb),
+ SH_PFC_FUNCTION(drif0),
+ SH_PFC_FUNCTION(drif1),
+ SH_PFC_FUNCTION(drif2),
+ SH_PFC_FUNCTION(drif3),
+ SH_PFC_FUNCTION(du),
+ SH_PFC_FUNCTION(i2c1),
+ SH_PFC_FUNCTION(i2c2),
+ SH_PFC_FUNCTION(i2c6),
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
SH_PFC_FUNCTION(scif2),
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index c5772584594c..fcacfa73ef6e 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -570,7 +570,8 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- return true;
+ return pin->configs &
+ (SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN);
case PIN_CONFIG_BIAS_PULL_UP:
return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 2345421103db..e42cc7a8d10e 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -189,6 +189,12 @@ struct sh_pfc_window {
unsigned long size;
};
+struct sh_pfc_bias_info {
+ u16 pin;
+ u16 reg : 11;
+ u16 bit : 5;
+};
+
struct sh_pfc_pin_range;
struct sh_pfc {
@@ -540,6 +546,14 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
.configs = SH_PFC_PIN_CFG_NO_GPIO, \
}
+/* SH_PFC_PIN_NAMED_CFG - Expand to a sh_pfc_pin entry with the given name */
+#define SH_PFC_PIN_NAMED_CFG(row, col, _name, cfgs) \
+ { \
+ .pin = PIN_NUMBER(row, col), \
+ .name = __stringify(PIN_##_name), \
+ .configs = SH_PFC_PIN_CFG_NO_GPIO | cfgs, \
+ }
+
/* PINMUX_DATA_ALL - Expand to a list of PORT_name_DATA, PORT_name_FN0,
* PORT_name_OUT, PORT_name_IN marks
*/
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c
index e9b15dc0654b..990b867b9625 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32f429.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32f429.c
@@ -1584,8 +1584,4 @@ static struct platform_driver stm32f429_pinctrl_driver = {
},
};
-static int __init stm32f429_pinctrl_init(void)
-{
- return platform_driver_register(&stm32f429_pinctrl_driver);
-}
-device_initcall(stm32f429_pinctrl_init);
+builtin_platform_driver(stm32f429_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-gr8.c b/drivers/pinctrl/sunxi/pinctrl-gr8.c
index 2904d2b7378b..2f232c3a0579 100644
--- a/drivers/pinctrl/sunxi/pinctrl-gr8.c
+++ b/drivers/pinctrl/sunxi/pinctrl-gr8.c
@@ -12,7 +12,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -525,7 +525,6 @@ static const struct of_device_id sun5i_gr8_pinctrl_match[] = {
{ .compatible = "nextthing,gr8-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun5i_gr8_pinctrl_match);
static struct platform_driver sun5i_gr8_pinctrl_driver = {
.probe = sun5i_gr8_pinctrl_probe,
@@ -534,8 +533,4 @@ static struct platform_driver sun5i_gr8_pinctrl_driver = {
.of_match_table = sun5i_gr8_pinctrl_match,
},
};
-module_platform_driver(sun5i_gr8_pinctrl_driver);
-
-MODULE_AUTHOR("Mylene Josserand <mylene.josserand@free-electrons.com");
-MODULE_DESCRIPTION("NextThing GR8 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun5i_gr8_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
index 862a096c5dba..fb30b86a97ee 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -1035,7 +1035,6 @@ static const struct of_device_id sun4i_a10_pinctrl_match[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun4i_a10_pinctrl_match);
static struct platform_driver sun4i_a10_pinctrl_driver = {
.probe = sun4i_a10_pinctrl_probe,
@@ -1044,8 +1043,4 @@ static struct platform_driver sun4i_a10_pinctrl_driver = {
.of_match_table = sun4i_a10_pinctrl_match,
},
};
-module_platform_driver(sun4i_a10_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A10 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun4i_a10_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
index f9a3f8f446f7..a5b57fdff9e1 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -674,7 +674,6 @@ static const struct of_device_id sun5i_a10s_pinctrl_match[] = {
{ .compatible = "allwinner,sun5i-a10s-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun5i_a10s_pinctrl_match);
static struct platform_driver sun5i_a10s_pinctrl_driver = {
.probe = sun5i_a10s_pinctrl_probe,
@@ -683,8 +682,4 @@ static struct platform_driver sun5i_a10s_pinctrl_driver = {
.of_match_table = sun5i_a10s_pinctrl_match,
},
};
-module_platform_driver(sun5i_a10s_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A10s pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun5i_a10s_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
index 2bb07b38834f..8575f3f6d3dd 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -392,7 +392,6 @@ static const struct of_device_id sun5i_a13_pinctrl_match[] = {
{ .compatible = "allwinner,sun5i-a13-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun5i_a13_pinctrl_match);
static struct platform_driver sun5i_a13_pinctrl_driver = {
.probe = sun5i_a13_pinctrl_probe,
@@ -401,8 +400,4 @@ static struct platform_driver sun5i_a13_pinctrl_driver = {
.of_match_table = sun5i_a13_pinctrl_match,
},
};
-module_platform_driver(sun5i_a13_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A13 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun5i_a13_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
index d4bc4f0e8be0..a22bd88a1f03 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
@@ -12,7 +12,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -136,7 +136,6 @@ static const struct of_device_id sun6i_a31_r_pinctrl_match[] = {
{ .compatible = "allwinner,sun6i-a31-r-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun6i_a31_r_pinctrl_match);
static struct platform_driver sun6i_a31_r_pinctrl_driver = {
.probe = sun6i_a31_r_pinctrl_probe,
@@ -145,9 +144,4 @@ static struct platform_driver sun6i_a31_r_pinctrl_driver = {
.of_match_table = sun6i_a31_r_pinctrl_match,
},
};
-module_platform_driver(sun6i_a31_r_pinctrl_driver);
-
-MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com");
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A31 R_PIO pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun6i_a31_r_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
index a70b52957e24..9e58926bef37 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -934,7 +934,6 @@ static const struct of_device_id sun6i_a31_pinctrl_match[] = {
{ .compatible = "allwinner,sun6i-a31-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun6i_a31_pinctrl_match);
static struct platform_driver sun6i_a31_pinctrl_driver = {
.probe = sun6i_a31_pinctrl_probe,
@@ -943,8 +942,4 @@ static struct platform_driver sun6i_a31_pinctrl_driver = {
.of_match_table = sun6i_a31_pinctrl_match,
},
};
-module_platform_driver(sun6i_a31_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A31 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun6i_a31_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c
index e570d5c93ecc..231a746a5356 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c
@@ -11,7 +11,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -798,7 +798,6 @@ static const struct of_device_id sun6i_a31s_pinctrl_match[] = {
{ .compatible = "allwinner,sun6i-a31s-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun6i_a31s_pinctrl_match);
static struct platform_driver sun6i_a31s_pinctrl_driver = {
.probe = sun6i_a31s_pinctrl_probe,
@@ -807,8 +806,4 @@ static struct platform_driver sun6i_a31s_pinctrl_driver = {
.of_match_table = sun6i_a31s_pinctrl_match,
},
};
-module_platform_driver(sun6i_a31s_pinctrl_driver);
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Allwinner A31s pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun6i_a31s_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
index 435ad30f45db..b6f4c68ffb39 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -1045,7 +1045,6 @@ static const struct of_device_id sun7i_a20_pinctrl_match[] = {
{ .compatible = "allwinner,sun7i-a20-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun7i_a20_pinctrl_match);
static struct platform_driver sun7i_a20_pinctrl_driver = {
.probe = sun7i_a20_pinctrl_probe,
@@ -1054,8 +1053,4 @@ static struct platform_driver sun7i_a20_pinctrl_driver = {
.of_match_table = sun7i_a20_pinctrl_match,
},
};
-module_platform_driver(sun7i_a20_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A20 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun7i_a20_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
index 056287635873..2292e05a397b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
@@ -15,7 +15,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -123,7 +123,6 @@ static const struct of_device_id sun8i_a23_r_pinctrl_match[] = {
{ .compatible = "allwinner,sun8i-a23-r-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match);
static struct platform_driver sun8i_a23_r_pinctrl_driver = {
.probe = sun8i_a23_r_pinctrl_probe,
@@ -132,10 +131,4 @@ static struct platform_driver sun8i_a23_r_pinctrl_driver = {
.of_match_table = sun8i_a23_r_pinctrl_match,
},
};
-module_platform_driver(sun8i_a23_r_pinctrl_driver);
-
-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com");
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A23 R_PIO pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun8i_a23_r_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
index f9d661e5c14a..721b6935baf3 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
@@ -14,7 +14,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -575,7 +575,6 @@ static const struct of_device_id sun8i_a23_pinctrl_match[] = {
{ .compatible = "allwinner,sun8i-a23-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match);
static struct platform_driver sun8i_a23_pinctrl_driver = {
.probe = sun8i_a23_pinctrl_probe,
@@ -584,9 +583,4 @@ static struct platform_driver sun8i_a23_pinctrl_driver = {
.of_match_table = sun8i_a23_pinctrl_match,
},
};
-module_platform_driver(sun8i_a23_pinctrl_driver);
-
-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A23 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun8i_a23_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
index 3131cac2b76f..ef1e0bef4099 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
@@ -12,7 +12,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -498,7 +498,6 @@ static const struct of_device_id sun8i_a33_pinctrl_match[] = {
{ .compatible = "allwinner,sun8i-a33-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun8i_a33_pinctrl_match);
static struct platform_driver sun8i_a33_pinctrl_driver = {
.probe = sun8i_a33_pinctrl_probe,
@@ -507,8 +506,4 @@ static struct platform_driver sun8i_a33_pinctrl_driver = {
.of_match_table = sun8i_a33_pinctrl_match,
},
};
-module_platform_driver(sun8i_a33_pinctrl_driver);
-
-MODULE_AUTHOR("Vishnu Patekar <vishnupatekar0510@gmail.com>");
-MODULE_DESCRIPTION("Allwinner a33 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun8i_a33_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
index 90b973e15982..9aec1d2232dd 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -12,7 +12,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -587,7 +587,6 @@ 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,
@@ -596,8 +595,4 @@ static struct platform_driver sun8i_a83t_pinctrl_driver = {
.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");
+builtin_platform_driver(sun8i_a83t_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c
index 1b580ba76453..bc14e954d7a2 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c
@@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -733,7 +733,6 @@ static const struct of_device_id sun9i_a80_pinctrl_match[] = {
{ .compatible = "allwinner,sun9i-a80-pinctrl", },
{}
};
-MODULE_DEVICE_TABLE(of, sun9i_a80_pinctrl_match);
static struct platform_driver sun9i_a80_pinctrl_driver = {
.probe = sun9i_a80_pinctrl_probe,
@@ -742,8 +741,4 @@ static struct platform_driver sun9i_a80_pinctrl_driver = {
.of_match_table = sun9i_a80_pinctrl_match,
},
};
-module_platform_driver(sun9i_a80_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A80 pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun9i_a80_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 0facbea5f465..0eb51e33cb1b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -28,6 +28,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
#include "../core.h"
#include "pinctrl-sunxi.h"
@@ -145,6 +147,171 @@ static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
return 0;
}
+static bool sunxi_pctrl_has_bias_prop(struct device_node *node)
+{
+ return of_find_property(node, "bias-pull-up", NULL) ||
+ of_find_property(node, "bias-pull-down", NULL) ||
+ of_find_property(node, "bias-disable", NULL) ||
+ of_find_property(node, "allwinner,pull", NULL);
+}
+
+static bool sunxi_pctrl_has_drive_prop(struct device_node *node)
+{
+ return of_find_property(node, "drive-strength", NULL) ||
+ of_find_property(node, "allwinner,drive", NULL);
+}
+
+static int sunxi_pctrl_parse_bias_prop(struct device_node *node)
+{
+ u32 val;
+
+ /* Try the new style binding */
+ if (of_find_property(node, "bias-pull-up", NULL))
+ return PIN_CONFIG_BIAS_PULL_UP;
+
+ if (of_find_property(node, "bias-pull-down", NULL))
+ return PIN_CONFIG_BIAS_PULL_DOWN;
+
+ if (of_find_property(node, "bias-disable", NULL))
+ return PIN_CONFIG_BIAS_DISABLE;
+
+ /* And fall back to the old binding */
+ if (of_property_read_u32(node, "allwinner,pull", &val))
+ return -EINVAL;
+
+ switch (val) {
+ case SUN4I_PINCTRL_NO_PULL:
+ return PIN_CONFIG_BIAS_DISABLE;
+ case SUN4I_PINCTRL_PULL_UP:
+ return PIN_CONFIG_BIAS_PULL_UP;
+ case SUN4I_PINCTRL_PULL_DOWN:
+ return PIN_CONFIG_BIAS_PULL_DOWN;
+ }
+
+ return -EINVAL;
+}
+
+static int sunxi_pctrl_parse_drive_prop(struct device_node *node)
+{
+ u32 val;
+
+ /* Try the new style binding */
+ if (!of_property_read_u32(node, "drive-strength", &val)) {
+ /* We can't go below 10mA ... */
+ if (val < 10)
+ return -EINVAL;
+
+ /* ... and only up to 40 mA ... */
+ if (val > 40)
+ val = 40;
+
+ /* by steps of 10 mA */
+ return rounddown(val, 10);
+ }
+
+ /* And then fall back to the old binding */
+ if (of_property_read_u32(node, "allwinner,drive", &val))
+ return -EINVAL;
+
+ return (val + 1) * 10;
+}
+
+static const char *sunxi_pctrl_parse_function_prop(struct device_node *node)
+{
+ const char *function;
+ int ret;
+
+ /* Try the generic binding */
+ ret = of_property_read_string(node, "function", &function);
+ if (!ret)
+ return function;
+
+ /* And fall back to our legacy one */
+ ret = of_property_read_string(node, "allwinner,function", &function);
+ if (!ret)
+ return function;
+
+ return NULL;
+}
+
+static const char *sunxi_pctrl_find_pins_prop(struct device_node *node,
+ int *npins)
+{
+ int count;
+
+ /* Try the generic binding */
+ count = of_property_count_strings(node, "pins");
+ if (count > 0) {
+ *npins = count;
+ return "pins";
+ }
+
+ /* And fall back to our legacy one */
+ count = of_property_count_strings(node, "allwinner,pins");
+ if (count > 0) {
+ *npins = count;
+ return "allwinner,pins";
+ }
+
+ return NULL;
+}
+
+static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
+ unsigned int *len)
+{
+ unsigned long *pinconfig;
+ unsigned int configlen = 0, idx = 0;
+ int ret;
+
+ if (sunxi_pctrl_has_drive_prop(node))
+ configlen++;
+ if (sunxi_pctrl_has_bias_prop(node))
+ configlen++;
+
+ /*
+ * If we don't have any configuration, bail out
+ */
+ if (!configlen)
+ return NULL;
+
+ pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
+ if (!pinconfig)
+ return ERR_PTR(-ENOMEM);
+
+ if (sunxi_pctrl_has_drive_prop(node)) {
+ int drive = sunxi_pctrl_parse_drive_prop(node);
+ if (drive < 0) {
+ ret = drive;
+ goto err_free;
+ }
+
+ pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
+ drive);
+ }
+
+ if (sunxi_pctrl_has_bias_prop(node)) {
+ int pull = sunxi_pctrl_parse_bias_prop(node);
+ int arg = 0;
+ if (pull < 0) {
+ ret = pull;
+ goto err_free;
+ }
+
+ if (pull != PIN_CONFIG_BIAS_DISABLE)
+ arg = 1; /* hardware uses weak pull resistors */
+
+ pinconfig[idx++] = pinconf_to_config_packed(pull, arg);
+ }
+
+
+ *len = configlen;
+ return pinconfig;
+
+err_free:
+ kfree(pinconfig);
+ return ERR_PTR(ret);
+}
+
static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *node,
struct pinctrl_map **map,
@@ -153,38 +320,48 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
unsigned long *pinconfig;
struct property *prop;
- const char *function;
+ const char *function, *pin_prop;
const char *group;
- int ret, nmaps, i = 0;
- u32 val;
+ int ret, npins, nmaps, configlen = 0, i = 0;
*map = NULL;
*num_maps = 0;
- ret = of_property_read_string(node, "allwinner,function", &function);
- if (ret) {
- dev_err(pctl->dev,
- "missing allwinner,function property in node %s\n",
+ function = sunxi_pctrl_parse_function_prop(node);
+ if (!function) {
+ dev_err(pctl->dev, "missing function property in node %s\n",
node->name);
return -EINVAL;
}
- nmaps = of_property_count_strings(node, "allwinner,pins") * 2;
- if (nmaps < 0) {
- dev_err(pctl->dev,
- "missing allwinner,pins property in node %s\n",
+ pin_prop = sunxi_pctrl_find_pins_prop(node, &npins);
+ if (!pin_prop) {
+ dev_err(pctl->dev, "missing pins property in node %s\n",
node->name);
return -EINVAL;
}
+ /*
+ * We have two maps for each pin: one for the function, one
+ * for the configuration (bias, strength, etc).
+ *
+ * We might be slightly overshooting, since we might not have
+ * any configuration.
+ */
+ nmaps = npins * 2;
*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
- of_property_for_each_string(node, "allwinner,pins", prop, group) {
+ pinconfig = sunxi_pctrl_build_pin_config(node, &configlen);
+ if (IS_ERR(pinconfig)) {
+ ret = PTR_ERR(pinconfig);
+ goto err_free_map;
+ }
+
+ of_property_for_each_string(node, pin_prop, prop, group) {
struct sunxi_pinctrl_group *grp =
sunxi_pinctrl_find_group_by_name(pctl, group);
- int j = 0, configlen = 0;
if (!grp) {
dev_err(pctl->dev, "unknown pin %s", group);
@@ -205,45 +382,31 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
i++;
- (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
- (*map)[i].data.configs.group_or_pin = group;
-
- if (of_find_property(node, "allwinner,drive", NULL))
- configlen++;
- if (of_find_property(node, "allwinner,pull", NULL))
- configlen++;
-
- pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
- if (!pinconfig) {
- kfree(*map);
- return -ENOMEM;
+ if (pinconfig) {
+ (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)[i].data.configs.group_or_pin = group;
+ (*map)[i].data.configs.configs = pinconfig;
+ (*map)[i].data.configs.num_configs = configlen;
+ i++;
}
-
- if (!of_property_read_u32(node, "allwinner,drive", &val)) {
- u16 strength = (val + 1) * 10;
- pinconfig[j++] =
- pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
- strength);
- }
-
- if (!of_property_read_u32(node, "allwinner,pull", &val)) {
- enum pin_config_param pull = PIN_CONFIG_END;
- if (val == 1)
- pull = PIN_CONFIG_BIAS_PULL_UP;
- else if (val == 2)
- pull = PIN_CONFIG_BIAS_PULL_DOWN;
- pinconfig[j++] = pinconf_to_config_packed(pull, 0);
- }
-
- (*map)[i].data.configs.configs = pinconfig;
- (*map)[i].data.configs.num_configs = configlen;
-
- i++;
}
- *num_maps = nmaps;
+ *num_maps = i;
+
+ /*
+ * We know have the number of maps we need, we can resize our
+ * map array
+ */
+ *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
return 0;
+
+err_free_map:
+ kfree(*map);
+ *map = NULL;
+ return ret;
}
static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
@@ -252,9 +415,17 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
{
int i;
- for (i = 0; i < num_maps; i++) {
- if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
- kfree(map[i].data.configs.configs);
+ /* pin config is never in the first map */
+ for (i = 1; i < num_maps; i++) {
+ if (map[i].type != PIN_MAP_TYPE_CONFIGS_GROUP)
+ continue;
+
+ /*
+ * All the maps share the same pin config,
+ * free only the first one we find.
+ */
+ kfree(map[i].data.configs.configs);
+ break;
}
kfree(map);
@@ -268,15 +439,91 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
.get_group_pins = sunxi_pctrl_get_group_pins,
};
+static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
+ u32 *offset, u32 *shift, u32 *mask)
+{
+ switch (param) {
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ *offset = sunxi_dlevel_reg(pin);
+ *shift = sunxi_dlevel_offset(pin);
+ *mask = DLEVEL_PINS_MASK;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_DISABLE:
+ *offset = sunxi_pull_reg(pin);
+ *shift = sunxi_pull_offset(pin);
+ *mask = PULL_PINS_MASK;
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config)
+{
+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ u32 offset, shift, mask, val;
+ u16 arg;
+ int ret;
+
+ pin -= pctl->desc->pin_base;
+
+ ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+ if (ret < 0)
+ return ret;
+
+ val = (readl(pctl->membase + offset) >> shift) & mask;
+
+ switch (pinconf_to_config_param(*config)) {
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ arg = (val + 1) * 10;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (val != SUN4I_PINCTRL_PULL_UP)
+ return -EINVAL;
+ arg = 1; /* hardware is weak pull-up */
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (val != SUN4I_PINCTRL_PULL_DOWN)
+ return -EINVAL;
+ arg = 1; /* hardware is weak pull-down */
+ break;
+
+ case PIN_CONFIG_BIAS_DISABLE:
+ if (val != SUN4I_PINCTRL_NO_PULL)
+ return -EINVAL;
+ arg = 0;
+ break;
+
+ default:
+ /* sunxi_pconf_reg should catch anything unsupported */
+ WARN_ON(1);
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev,
unsigned group,
unsigned long *config)
{
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct sunxi_pinctrl_group *g = &pctl->groups[group];
- *config = pctl->groups[group].config;
-
- return 0;
+ /* We only support 1 pin per group. Chain it to the pin callback */
+ return sunxi_pconf_get(pctldev, g->pin, config);
}
static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
@@ -286,23 +533,27 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
{
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct sunxi_pinctrl_group *g = &pctl->groups[group];
- unsigned long flags;
unsigned pin = g->pin - pctl->desc->pin_base;
- u32 val, mask;
- u16 strength;
- u8 dlevel;
int i;
- spin_lock_irqsave(&pctl->lock, flags);
-
for (i = 0; i < num_configs; i++) {
- switch (pinconf_to_config_param(configs[i])) {
+ enum pin_config_param param;
+ unsigned long flags;
+ u32 offset, shift, mask, reg;
+ u16 arg, val;
+ int ret;
+
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+ if (ret < 0)
+ return ret;
+
+ switch (param) {
case PIN_CONFIG_DRIVE_STRENGTH:
- strength = pinconf_to_config_argument(configs[i]);
- if (strength > 40) {
- spin_unlock_irqrestore(&pctl->lock, flags);
+ if (arg < 10 || arg > 40)
return -EINVAL;
- }
/*
* We convert from mA to what the register expects:
* 0: 10mA
@@ -310,38 +561,40 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
* 2: 30mA
* 3: 40mA
*/
- dlevel = strength / 10 - 1;
- val = readl(pctl->membase + sunxi_dlevel_reg(pin));
- mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(pin);
- writel((val & ~mask)
- | dlevel << sunxi_dlevel_offset(pin),
- pctl->membase + sunxi_dlevel_reg(pin));
+ val = arg / 10 - 1;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ val = 0;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- val = readl(pctl->membase + sunxi_pull_reg(pin));
- mask = PULL_PINS_MASK << sunxi_pull_offset(pin);
- writel((val & ~mask) | 1 << sunxi_pull_offset(pin),
- pctl->membase + sunxi_pull_reg(pin));
+ if (arg == 0)
+ return -EINVAL;
+ val = 1;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- val = readl(pctl->membase + sunxi_pull_reg(pin));
- mask = PULL_PINS_MASK << sunxi_pull_offset(pin);
- writel((val & ~mask) | 2 << sunxi_pull_offset(pin),
- pctl->membase + sunxi_pull_reg(pin));
+ if (arg == 0)
+ return -EINVAL;
+ val = 2;
break;
default:
- break;
+ /* sunxi_pconf_reg should catch anything unsupported */
+ WARN_ON(1);
+ return -ENOTSUPP;
}
- /* cache the config value */
- g->config = configs[i];
- } /* for each config */
- spin_unlock_irqrestore(&pctl->lock, flags);
+ spin_lock_irqsave(&pctl->lock, flags);
+ reg = readl(pctl->membase + offset);
+ reg &= ~(mask << shift);
+ writel(reg | val << shift, pctl->membase + offset);
+ spin_unlock_irqrestore(&pctl->lock, flags);
+ } /* for each config */
return 0;
}
static const struct pinconf_ops sunxi_pconf_ops = {
+ .is_generic = true,
+ .pin_config_get = sunxi_pconf_get,
.pin_config_group_get = sunxi_pconf_group_get,
.pin_config_group_set = sunxi_pconf_group_set,
};
@@ -870,6 +1123,91 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
return 0;
}
+static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff)
+{
+ unsigned long clock = clk_get_rate(clk);
+ unsigned int best_diff, best_div;
+ int i;
+
+ best_diff = abs(freq - clock);
+ best_div = 0;
+
+ for (i = 1; i < 8; i++) {
+ int cur_diff = abs(freq - (clock >> i));
+
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ best_div = i;
+ }
+ }
+
+ *diff = best_diff;
+ return best_div;
+}
+
+static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
+ struct device_node *node)
+{
+ unsigned int hosc_diff, losc_diff;
+ unsigned int hosc_div, losc_div;
+ struct clk *hosc, *losc;
+ u8 div, src;
+ int i, ret;
+
+ /* Deal with old DTs that didn't have the oscillators */
+ if (of_count_phandle_with_args(node, "clocks", "#clock-cells") != 3)
+ return 0;
+
+ /* If we don't have any setup, bail out */
+ if (!of_find_property(node, "input-debounce", NULL))
+ return 0;
+
+ losc = devm_clk_get(pctl->dev, "losc");
+ if (IS_ERR(losc))
+ return PTR_ERR(losc);
+
+ hosc = devm_clk_get(pctl->dev, "hosc");
+ if (IS_ERR(hosc))
+ return PTR_ERR(hosc);
+
+ for (i = 0; i < pctl->desc->irq_banks; i++) {
+ unsigned long debounce_freq;
+ u32 debounce;
+
+ ret = of_property_read_u32_index(node, "input-debounce",
+ i, &debounce);
+ if (ret)
+ return ret;
+
+ if (!debounce)
+ continue;
+
+ debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC, debounce);
+ losc_div = sunxi_pinctrl_get_debounce_div(losc,
+ debounce_freq,
+ &losc_diff);
+
+ hosc_div = sunxi_pinctrl_get_debounce_div(hosc,
+ debounce_freq,
+ &hosc_diff);
+
+ if (hosc_diff < losc_diff) {
+ div = hosc_div;
+ src = 1;
+ } else {
+ div = losc_div;
+ src = 0;
+ }
+
+ writel(src | div << 4,
+ pctl->membase +
+ sunxi_irq_debounce_reg_from_bank(i,
+ pctl->desc->irq_bank_base));
+ }
+
+ return 0;
+}
+
int sunxi_pinctrl_init(struct platform_device *pdev,
const struct sunxi_pinctrl_desc *desc)
{
@@ -1032,6 +1370,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
pctl);
}
+ sunxi_pinctrl_setup_debounce(pctl, node);
+
dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
return 0;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 0afce1ab12d0..f78a44a03189 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -69,6 +69,8 @@
#define IRQ_STATUS_IRQ_BITS 1
#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
+#define IRQ_DEBOUNCE_REG 0x218
+
#define IRQ_MEM_SIZE 0x20
#define IRQ_EDGE_RISING 0x00
@@ -109,7 +111,6 @@ struct sunxi_pinctrl_function {
struct sunxi_pinctrl_group {
const char *name;
- unsigned long config;
unsigned pin;
};
@@ -266,6 +267,11 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
return irq_num * IRQ_CTRL_IRQ_BITS;
}
+static inline u32 sunxi_irq_debounce_reg_from_bank(u8 bank, unsigned bank_base)
+{
+ return IRQ_DEBOUNCE_REG + (bank_base + bank) * IRQ_MEM_SIZE;
+}
+
static inline u32 sunxi_irq_status_reg_from_bank(u8 bank, unsigned bank_base)
{
return IRQ_STATUS_REG + (bank_base + bank) * IRQ_MEM_SIZE;
diff --git a/drivers/pinctrl/vt8500/pinctrl-vt8500.c b/drivers/pinctrl/vt8500/pinctrl-vt8500.c
index ca946b3dbdb4..767f340d6b11 100644
--- a/drivers/pinctrl/vt8500/pinctrl-vt8500.c
+++ b/drivers/pinctrl/vt8500/pinctrl-vt8500.c
@@ -14,7 +14,7 @@
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -473,11 +473,6 @@ static int vt8500_pinctrl_probe(struct platform_device *pdev)
return wmt_pinctrl_probe(pdev, data);
}
-static int vt8500_pinctrl_remove(struct platform_device *pdev)
-{
- return wmt_pinctrl_remove(pdev);
-}
-
static const struct of_device_id wmt_pinctrl_of_match[] = {
{ .compatible = "via,vt8500-pinctrl" },
{ /* sentinel */ },
@@ -485,16 +480,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = {
static struct platform_driver wmt_pinctrl_driver = {
.probe = vt8500_pinctrl_probe,
- .remove = vt8500_pinctrl_remove,
.driver = {
.name = "pinctrl-vt8500",
.of_match_table = wmt_pinctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(wmt_pinctrl_driver);
-
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_DESCRIPTION("VIA VT8500 Pincontrol driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
+builtin_platform_driver(wmt_pinctrl_driver);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8505.c b/drivers/pinctrl/vt8500/pinctrl-wm8505.c
index 626fc7ec0174..a56fdbd87e42 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8505.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8505.c
@@ -14,7 +14,7 @@
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -504,11 +504,6 @@ static int wm8505_pinctrl_probe(struct platform_device *pdev)
return wmt_pinctrl_probe(pdev, data);
}
-static int wm8505_pinctrl_remove(struct platform_device *pdev)
-{
- return wmt_pinctrl_remove(pdev);
-}
-
static const struct of_device_id wmt_pinctrl_of_match[] = {
{ .compatible = "wm,wm8505-pinctrl" },
{ /* sentinel */ },
@@ -516,16 +511,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = {
static struct platform_driver wmt_pinctrl_driver = {
.probe = wm8505_pinctrl_probe,
- .remove = wm8505_pinctrl_remove,
.driver = {
.name = "pinctrl-wm8505",
.of_match_table = wmt_pinctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(wmt_pinctrl_driver);
-
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_DESCRIPTION("Wondermedia WM8505 Pincontrol driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
+builtin_platform_driver(wmt_pinctrl_driver);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8650.c b/drivers/pinctrl/vt8500/pinctrl-wm8650.c
index 8953aba8bfc2..270dd491f5a1 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8650.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8650.c
@@ -14,7 +14,7 @@
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -342,11 +342,6 @@ static int wm8650_pinctrl_probe(struct platform_device *pdev)
return wmt_pinctrl_probe(pdev, data);
}
-static int wm8650_pinctrl_remove(struct platform_device *pdev)
-{
- return wmt_pinctrl_remove(pdev);
-}
-
static const struct of_device_id wmt_pinctrl_of_match[] = {
{ .compatible = "wm,wm8650-pinctrl" },
{ /* sentinel */ },
@@ -354,16 +349,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = {
static struct platform_driver wmt_pinctrl_driver = {
.probe = wm8650_pinctrl_probe,
- .remove = wm8650_pinctrl_remove,
.driver = {
.name = "pinctrl-wm8650",
.of_match_table = wmt_pinctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(wmt_pinctrl_driver);
-
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_DESCRIPTION("Wondermedia WM8650 Pincontrol driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
+builtin_platform_driver(wmt_pinctrl_driver);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8750.c b/drivers/pinctrl/vt8500/pinctrl-wm8750.c
index c79053d430db..74f7b3a18f3a 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8750.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8750.c
@@ -14,7 +14,7 @@
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -381,11 +381,6 @@ static int wm8750_pinctrl_probe(struct platform_device *pdev)
return wmt_pinctrl_probe(pdev, data);
}
-static int wm8750_pinctrl_remove(struct platform_device *pdev)
-{
- return wmt_pinctrl_remove(pdev);
-}
-
static const struct of_device_id wmt_pinctrl_of_match[] = {
{ .compatible = "wm,wm8750-pinctrl" },
{ /* sentinel */ },
@@ -393,16 +388,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = {
static struct platform_driver wmt_pinctrl_driver = {
.probe = wm8750_pinctrl_probe,
- .remove = wm8750_pinctrl_remove,
.driver = {
.name = "pinctrl-wm8750",
.of_match_table = wmt_pinctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(wmt_pinctrl_driver);
-
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_DESCRIPTION("Wondermedia WM8750 Pincontrol driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
+builtin_platform_driver(wmt_pinctrl_driver);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8850.c b/drivers/pinctrl/vt8500/pinctrl-wm8850.c
index f232b163c735..45792aa7a06e 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8850.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8850.c
@@ -14,7 +14,7 @@
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -360,11 +360,6 @@ static int wm8850_pinctrl_probe(struct platform_device *pdev)
return wmt_pinctrl_probe(pdev, data);
}
-static int wm8850_pinctrl_remove(struct platform_device *pdev)
-{
- return wmt_pinctrl_remove(pdev);
-}
-
static const struct of_device_id wmt_pinctrl_of_match[] = {
{ .compatible = "wm,wm8850-pinctrl" },
{ /* sentinel */ },
@@ -372,16 +367,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = {
static struct platform_driver wmt_pinctrl_driver = {
.probe = wm8850_pinctrl_probe,
- .remove = wm8850_pinctrl_remove,
.driver = {
.name = "pinctrl-wm8850",
.of_match_table = wmt_pinctrl_of_match,
+ .suppress_bind_attrs = true,
},
};
-
-module_platform_driver(wmt_pinctrl_driver);
-
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_DESCRIPTION("Wondermedia WM8850 Pincontrol driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
+builtin_platform_driver(wmt_pinctrl_driver);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index cbc638631678..270ca2a47a8c 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -18,7 +18,6 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
-#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
@@ -608,12 +607,3 @@ fail_range:
gpiochip_remove(&data->gpio_chip);
return err;
}
-
-int wmt_pinctrl_remove(struct platform_device *pdev)
-{
- struct wmt_pinctrl_data *data = platform_get_drvdata(pdev);
-
- gpiochip_remove(&data->gpio_chip);
-
- return 0;
-}
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.h b/drivers/pinctrl/vt8500/pinctrl-wmt.h
index 41f5f2deb5d6..885613396fe7 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.h
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.h
@@ -76,4 +76,3 @@ struct wmt_pinctrl_data {
int wmt_pinctrl_probe(struct platform_device *pdev,
struct wmt_pinctrl_data *data);
-int wmt_pinctrl_remove(struct platform_device *pdev);
diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c
index 01b6d3f9b8fb..56bce1908be2 100644
--- a/drivers/power/avs/rockchip-io-domain.c
+++ b/drivers/power/avs/rockchip-io-domain.c
@@ -143,7 +143,7 @@ static int rockchip_iodomain_notify(struct notifier_block *nb,
if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
return NOTIFY_BAD;
- dev_info(supply->iod->dev, "Setting to %d done\n", uV);
+ dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
return NOTIFY_OK;
}
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 243b233ff31b..9a25110c4a46 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -189,14 +189,13 @@ struct rapl_package {
unsigned int time_unit;
struct rapl_domain *domains; /* array of domains, sized at runtime */
struct powercap_zone *power_zone; /* keep track of parent zone */
- int nr_cpus; /* active cpus on the package, topology info is lost during
- * cpu hotplug. so we have to track ourselves.
- */
unsigned long power_limit_irq; /* keep track of package power limit
* notify interrupt enable status.
*/
struct list_head plist;
int lead_cpu; /* one active cpu per package for access */
+ /* Track active cpus */
+ struct cpumask cpumask;
};
struct rapl_defaults {
@@ -275,18 +274,6 @@ static struct rapl_package *find_package_by_id(int id)
return NULL;
}
-/* caller must hold cpu hotplug lock */
-static void rapl_cleanup_data(void)
-{
- struct rapl_package *p, *tmp;
-
- list_for_each_entry_safe(p, tmp, &rapl_packages, plist) {
- kfree(p->domains);
- list_del(&p->plist);
- kfree(p);
- }
-}
-
static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw)
{
struct rapl_domain *rd;
@@ -442,6 +429,7 @@ static int contraint_to_pl(struct rapl_domain *rd, int cid)
return i;
}
}
+ pr_err("Cannot find matching power limit for constraint %d\n", cid);
return -EINVAL;
}
@@ -457,6 +445,10 @@ static int set_power_limit(struct powercap_zone *power_zone, int cid,
get_online_cpus();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
+ if (id < 0) {
+ ret = id;
+ goto set_exit;
+ }
rp = rd->rp;
@@ -496,6 +488,11 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
get_online_cpus();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
+ if (id < 0) {
+ ret = id;
+ goto get_exit;
+ }
+
switch (rd->rpl[id].prim_id) {
case PL1_ENABLE:
prim = POWER_LIMIT1;
@@ -512,6 +509,7 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
else
*data = val;
+get_exit:
put_online_cpus();
return ret;
@@ -527,6 +525,10 @@ static int set_time_window(struct powercap_zone *power_zone, int cid,
get_online_cpus();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
+ if (id < 0) {
+ ret = id;
+ goto set_time_exit;
+ }
switch (rd->rpl[id].prim_id) {
case PL1_ENABLE:
@@ -538,6 +540,8 @@ static int set_time_window(struct powercap_zone *power_zone, int cid,
default:
ret = -EINVAL;
}
+
+set_time_exit:
put_online_cpus();
return ret;
}
@@ -552,6 +556,10 @@ static int get_time_window(struct powercap_zone *power_zone, int cid, u64 *data)
get_online_cpus();
rd = power_zone_to_rapl_domain(power_zone);
id = contraint_to_pl(rd, cid);
+ if (id < 0) {
+ ret = id;
+ goto get_time_exit;
+ }
switch (rd->rpl[id].prim_id) {
case PL1_ENABLE:
@@ -566,6 +574,8 @@ static int get_time_window(struct powercap_zone *power_zone, int cid, u64 *data)
}
if (!ret)
*data = val;
+
+get_time_exit:
put_online_cpus();
return ret;
@@ -707,7 +717,7 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
case ENERGY_UNIT:
scale = ENERGY_UNIT_SCALE;
/* per domain unit takes precedence */
- if (rd && rd->domain_energy_unit)
+ if (rd->domain_energy_unit)
units = rd->domain_energy_unit;
else
units = rp->energy_unit;
@@ -976,10 +986,20 @@ static void package_power_limit_irq_save(struct rapl_package *rp)
smp_call_function_single(rp->lead_cpu, power_limit_irq_save_cpu, rp, 1);
}
-static void power_limit_irq_restore_cpu(void *info)
+/*
+ * Restore per package power limit interrupt enable state. Called from cpu
+ * hotplug code on package removal.
+ */
+static void package_power_limit_irq_restore(struct rapl_package *rp)
{
- u32 l, h = 0;
- struct rapl_package *rp = (struct rapl_package *)info;
+ u32 l, h;
+
+ if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
+ return;
+
+ /* irq enable state not saved, nothing to restore */
+ if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
+ return;
rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
@@ -991,19 +1011,6 @@ static void power_limit_irq_restore_cpu(void *info)
wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
}
-/* restore per package power limit interrupt enable state */
-static void package_power_limit_irq_restore(struct rapl_package *rp)
-{
- if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
- return;
-
- /* irq enable state not saved, nothing to restore */
- if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
- return;
-
- smp_call_function_single(rp->lead_cpu, power_limit_irq_restore_cpu, rp, 1);
-}
-
static void set_floor_freq_default(struct rapl_domain *rd, bool mode)
{
int nr_powerlimit = find_nr_power_limit(rd);
@@ -1160,84 +1167,49 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server),
+ RAPL_CPU(INTEL_FAM6_XEON_PHI_KNM, rapl_defaults_hsw_server),
{}
};
MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
-/* read once for all raw primitive data for all packages, domains */
-static void rapl_update_domain_data(void)
+/* Read once for all raw primitive data for domains */
+static void rapl_update_domain_data(struct rapl_package *rp)
{
int dmn, prim;
u64 val;
- struct rapl_package *rp;
- list_for_each_entry(rp, &rapl_packages, plist) {
- for (dmn = 0; dmn < rp->nr_domains; dmn++) {
- pr_debug("update package %d domain %s data\n", rp->id,
- rp->domains[dmn].name);
- /* exclude non-raw primitives */
- for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++)
- if (!rapl_read_data_raw(&rp->domains[dmn], prim,
- rpi[prim].unit,
- &val))
- rp->domains[dmn].rdd.primitives[prim] =
- val;
+ for (dmn = 0; dmn < rp->nr_domains; dmn++) {
+ pr_debug("update package %d domain %s data\n", rp->id,
+ rp->domains[dmn].name);
+ /* exclude non-raw primitives */
+ for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) {
+ if (!rapl_read_data_raw(&rp->domains[dmn], prim,
+ rpi[prim].unit, &val))
+ rp->domains[dmn].rdd.primitives[prim] = val;
}
}
}
-static int rapl_unregister_powercap(void)
+static void rapl_unregister_powercap(void)
{
- struct rapl_package *rp;
- struct rapl_domain *rd, *rd_package = NULL;
-
- /* unregister all active rapl packages from the powercap layer,
- * hotplug lock held
- */
- list_for_each_entry(rp, &rapl_packages, plist) {
- package_power_limit_irq_restore(rp);
-
- for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
- rd++) {
- pr_debug("remove package, undo power limit on %d: %s\n",
- rp->id, rd->name);
- rapl_write_data_raw(rd, PL1_ENABLE, 0);
- rapl_write_data_raw(rd, PL1_CLAMP, 0);
- if (find_nr_power_limit(rd) > 1) {
- rapl_write_data_raw(rd, PL2_ENABLE, 0);
- rapl_write_data_raw(rd, PL2_CLAMP, 0);
- }
- if (rd->id == RAPL_DOMAIN_PACKAGE) {
- rd_package = rd;
- continue;
- }
- powercap_unregister_zone(control_type, &rd->power_zone);
- }
- /* do the package zone last */
- if (rd_package)
- powercap_unregister_zone(control_type,
- &rd_package->power_zone);
- }
-
if (platform_rapl_domain) {
powercap_unregister_zone(control_type,
&platform_rapl_domain->power_zone);
kfree(platform_rapl_domain);
}
-
powercap_unregister_control_type(control_type);
-
- return 0;
}
static int rapl_package_register_powercap(struct rapl_package *rp)
{
struct rapl_domain *rd;
- int ret = 0;
char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/
struct powercap_zone *power_zone = NULL;
- int nr_pl;
+ int nr_pl, ret;;
+
+ /* Update the domain data of the new package */
+ rapl_update_domain_data(rp);
/* first we register package domain as the parent zone*/
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
@@ -1257,8 +1229,7 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
if (IS_ERR(power_zone)) {
pr_debug("failed to register package, %d\n",
rp->id);
- ret = PTR_ERR(power_zone);
- goto exit_package;
+ return PTR_ERR(power_zone);
}
/* track parent zone in per package/socket data */
rp->power_zone = power_zone;
@@ -1268,8 +1239,7 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
}
if (!power_zone) {
pr_err("no package domain found, unknown topology!\n");
- ret = -ENODEV;
- goto exit_package;
+ return -ENODEV;
}
/* now register domains as children of the socket/package*/
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
@@ -1290,11 +1260,11 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
goto err_cleanup;
}
}
+ return 0;
-exit_package:
- return ret;
err_cleanup:
- /* clean up previously initialized domains within the package if we
+ /*
+ * Clean up previously initialized domains within the package if we
* failed after the first domain setup.
*/
while (--rd >= rp->domains) {
@@ -1305,7 +1275,7 @@ err_cleanup:
return ret;
}
-static int rapl_register_psys(void)
+static int __init rapl_register_psys(void)
{
struct rapl_domain *rd;
struct powercap_zone *power_zone;
@@ -1346,40 +1316,14 @@ static int rapl_register_psys(void)
return 0;
}
-static int rapl_register_powercap(void)
+static int __init rapl_register_powercap(void)
{
- struct rapl_domain *rd;
- struct rapl_package *rp;
- int ret = 0;
-
control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
if (IS_ERR(control_type)) {
pr_debug("failed to register powercap control_type.\n");
return PTR_ERR(control_type);
}
- /* read the initial data */
- rapl_update_domain_data();
- list_for_each_entry(rp, &rapl_packages, plist)
- if (rapl_package_register_powercap(rp))
- goto err_cleanup_package;
-
- /* Don't bail out if PSys is not supported */
- rapl_register_psys();
-
- return ret;
-
-err_cleanup_package:
- /* clean up previously initialized packages */
- list_for_each_entry_continue_reverse(rp, &rapl_packages, plist) {
- for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
- rd++) {
- pr_debug("unregister zone/package %d, %s domain\n",
- rp->id, rd->name);
- powercap_unregister_zone(control_type, &rd->power_zone);
- }
- }
-
- return ret;
+ return 0;
}
static int rapl_check_domain(int cpu, int domain)
@@ -1452,9 +1396,8 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
*/
static int rapl_detect_domains(struct rapl_package *rp, int cpu)
{
- int i;
- int ret = 0;
struct rapl_domain *rd;
+ int i;
for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
/* use physical package id to read counters */
@@ -1466,84 +1409,20 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
if (!rp->nr_domains) {
pr_debug("no valid rapl domains found in package %d\n", rp->id);
- ret = -ENODEV;
- goto done;
+ return -ENODEV;
}
pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id);
rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
GFP_KERNEL);
- if (!rp->domains) {
- ret = -ENOMEM;
- goto done;
- }
+ if (!rp->domains)
+ return -ENOMEM;
+
rapl_init_domains(rp);
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
rapl_detect_powerlimit(rd);
-
-
-done:
- return ret;
-}
-
-static bool is_package_new(int package)
-{
- struct rapl_package *rp;
-
- /* caller prevents cpu hotplug, there will be no new packages added
- * or deleted while traversing the package list, no need for locking.
- */
- list_for_each_entry(rp, &rapl_packages, plist)
- if (package == rp->id)
- return false;
-
- return true;
-}
-
-/* RAPL interface can be made of a two-level hierarchy: package level and domain
- * level. We first detect the number of packages then domains of each package.
- * We have to consider the possiblity of CPU online/offline due to hotplug and
- * other scenarios.
- */
-static int rapl_detect_topology(void)
-{
- int i;
- int phy_package_id;
- struct rapl_package *new_package, *rp;
-
- for_each_online_cpu(i) {
- phy_package_id = topology_physical_package_id(i);
- if (is_package_new(phy_package_id)) {
- new_package = kzalloc(sizeof(*rp), GFP_KERNEL);
- if (!new_package) {
- rapl_cleanup_data();
- return -ENOMEM;
- }
- /* add the new package to the list */
- new_package->id = phy_package_id;
- new_package->nr_cpus = 1;
- /* use the first active cpu of the package to access */
- new_package->lead_cpu = i;
- /* check if the package contains valid domains */
- if (rapl_detect_domains(new_package, i) ||
- rapl_defaults->check_unit(new_package, i)) {
- kfree(new_package->domains);
- kfree(new_package);
- /* free up the packages already initialized */
- rapl_cleanup_data();
- return -ENODEV;
- }
- INIT_LIST_HEAD(&new_package->plist);
- list_add(&new_package->plist, &rapl_packages);
- } else {
- rp = find_package_by_id(phy_package_id);
- if (rp)
- ++rp->nr_cpus;
- }
- }
-
return 0;
}
@@ -1552,12 +1431,21 @@ static void rapl_remove_package(struct rapl_package *rp)
{
struct rapl_domain *rd, *rd_package = NULL;
+ package_power_limit_irq_restore(rp);
+
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+ rapl_write_data_raw(rd, PL1_ENABLE, 0);
+ rapl_write_data_raw(rd, PL1_CLAMP, 0);
+ if (find_nr_power_limit(rd) > 1) {
+ rapl_write_data_raw(rd, PL2_ENABLE, 0);
+ rapl_write_data_raw(rd, PL2_CLAMP, 0);
+ }
if (rd->id == RAPL_DOMAIN_PACKAGE) {
rd_package = rd;
continue;
}
- pr_debug("remove package %d, %s domain\n", rp->id, rd->name);
+ pr_debug("remove package, undo power limit on %d: %s\n",
+ rp->id, rd->name);
powercap_unregister_zone(control_type, &rd->power_zone);
}
/* do parent zone last */
@@ -1567,20 +1455,17 @@ static void rapl_remove_package(struct rapl_package *rp)
}
/* called from CPU hotplug notifier, hotplug lock held */
-static int rapl_add_package(int cpu)
+static struct rapl_package *rapl_add_package(int cpu, int pkgid)
{
- int ret = 0;
- int phy_package_id;
struct rapl_package *rp;
+ int ret;
- phy_package_id = topology_physical_package_id(cpu);
rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
if (!rp)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
/* add the new package to the list */
- rp->id = phy_package_id;
- rp->nr_cpus = 1;
+ rp->id = pkgid;
rp->lead_cpu = cpu;
/* check if the package contains valid domains */
@@ -1589,17 +1474,17 @@ static int rapl_add_package(int cpu)
ret = -ENODEV;
goto err_free_package;
}
- if (!rapl_package_register_powercap(rp)) {
+ ret = rapl_package_register_powercap(rp);
+ if (!ret) {
INIT_LIST_HEAD(&rp->plist);
list_add(&rp->plist, &rapl_packages);
- return ret;
+ return rp;
}
err_free_package:
kfree(rp->domains);
kfree(rp);
-
- return ret;
+ return ERR_PTR(ret);
}
/* Handles CPU hotplug on multi-socket systems.
@@ -1609,55 +1494,46 @@ err_free_package:
* associated domains. Cooling devices are handled accordingly at
* per-domain level.
*/
-static int rapl_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static int rapl_cpu_online(unsigned int cpu)
{
- unsigned long cpu = (unsigned long)hcpu;
- int phy_package_id;
+ int pkgid = topology_physical_package_id(cpu);
struct rapl_package *rp;
- int lead_cpu;
- phy_package_id = topology_physical_package_id(cpu);
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- rp = find_package_by_id(phy_package_id);
- if (rp)
- ++rp->nr_cpus;
- else
- rapl_add_package(cpu);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- rp = find_package_by_id(phy_package_id);
- if (!rp)
- break;
- if (--rp->nr_cpus == 0)
- rapl_remove_package(rp);
- else if (cpu == rp->lead_cpu) {
- /* choose another active cpu in the package */
- lead_cpu = cpumask_any_but(topology_core_cpumask(cpu), cpu);
- if (lead_cpu < nr_cpu_ids)
- rp->lead_cpu = lead_cpu;
- else /* should never go here */
- pr_err("no active cpu available for package %d\n",
- phy_package_id);
- }
+ rp = find_package_by_id(pkgid);
+ if (!rp) {
+ rp = rapl_add_package(cpu, pkgid);
+ if (IS_ERR(rp))
+ return PTR_ERR(rp);
}
+ cpumask_set_cpu(cpu, &rp->cpumask);
+ return 0;
+}
+
+static int rapl_cpu_down_prep(unsigned int cpu)
+{
+ int pkgid = topology_physical_package_id(cpu);
+ struct rapl_package *rp;
+ int lead_cpu;
+
+ rp = find_package_by_id(pkgid);
+ if (!rp)
+ return 0;
- return NOTIFY_OK;
+ cpumask_clear_cpu(cpu, &rp->cpumask);
+ lead_cpu = cpumask_first(&rp->cpumask);
+ if (lead_cpu >= nr_cpu_ids)
+ rapl_remove_package(rp);
+ else if (rp->lead_cpu == cpu)
+ rp->lead_cpu = lead_cpu;
+ return 0;
}
-static struct notifier_block rapl_cpu_notifier = {
- .notifier_call = rapl_cpu_callback,
-};
+static enum cpuhp_state pcap_rapl_online;
static int __init rapl_init(void)
{
- int ret = 0;
const struct x86_cpu_id *id;
+ int ret;
id = x86_match_cpu(rapl_ids);
if (!id) {
@@ -1669,36 +1545,29 @@ static int __init rapl_init(void)
rapl_defaults = (struct rapl_defaults *)id->driver_data;
- cpu_notifier_register_begin();
-
- /* prevent CPU hotplug during detection */
- get_online_cpus();
- ret = rapl_detect_topology();
+ ret = rapl_register_powercap();
if (ret)
- goto done;
+ return ret;
- if (rapl_register_powercap()) {
- rapl_cleanup_data();
- ret = -ENODEV;
- goto done;
- }
- __register_hotcpu_notifier(&rapl_cpu_notifier);
-done:
- put_online_cpus();
- cpu_notifier_register_done();
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
+ rapl_cpu_online, rapl_cpu_down_prep);
+ if (ret < 0)
+ goto err_unreg;
+ pcap_rapl_online = ret;
+
+ /* Don't bail out if PSys is not supported */
+ rapl_register_psys();
+ return 0;
+err_unreg:
+ rapl_unregister_powercap();
return ret;
}
static void __exit rapl_exit(void)
{
- cpu_notifier_register_begin();
- get_online_cpus();
- __unregister_hotcpu_notifier(&rapl_cpu_notifier);
+ cpuhp_remove_state(pcap_rapl_online);
rapl_unregister_powercap();
- rapl_cleanup_data();
- put_online_cpus();
- cpu_notifier_register_done();
}
module_init(rapl_init);
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index ee3de3421f2d..bdce33291161 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -6,7 +6,7 @@ menu "PTP clock support"
config PTP_1588_CLOCK
tristate "PTP clock support"
- depends on NET
+ depends on NET && POSIX_TIMERS
select PPS
select NET_PTP_CLASSIFY
help
@@ -28,7 +28,7 @@ config PTP_1588_CLOCK
config PTP_1588_CLOCK_GIANFAR
tristate "Freescale eTSEC as PTP clock"
depends on GIANFAR
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
default y
help
This driver adds support for using the eTSEC as a PTP
@@ -42,7 +42,7 @@ config PTP_1588_CLOCK_GIANFAR
config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock"
depends on IXP4XX_ETH
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
default y
help
This driver adds support for using the IXP46X as a PTP
@@ -60,7 +60,7 @@ config DP83640_PHY
tristate "Driver for the National Semiconductor DP83640 PHYTER"
depends on NETWORK_PHY_TIMESTAMPING
depends on PHYLIB
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
---help---
Supports the DP83640 PHYTER with IEEE 1588 features.
@@ -76,7 +76,7 @@ config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
depends on X86_32 || COMPILE_TEST
depends on HAS_IOMEM && NET
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
help
This driver adds support for using the PCH EG20T as a PTP
clock. The hardware supports time stamping of PTP packets
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 86280b7e41f3..9c13381b6966 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -153,7 +153,10 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx)
s32 ppb = scaled_ppm_to_ppb(tx->freq);
if (ppb > ops->max_adj || ppb < -ops->max_adj)
return -ERANGE;
- err = ops->adjfreq(ops, ppb);
+ if (ops->adjfine)
+ err = ops->adjfine(ops, tx->freq);
+ else
+ err = ops->adjfreq(ops, ppb);
ptp->dialed_frequency = tx->freq;
} else if (tx->modes == 0) {
tx->freq = ptp->dialed_frequency;
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 302e626fe6b0..53d43954a974 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -28,7 +28,7 @@ static ssize_t clock_name_show(struct device *dev,
struct ptp_clock *ptp = dev_get_drvdata(dev);
return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
}
-static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL);
+static DEVICE_ATTR_RO(clock_name);
#define PTP_SHOW_INT(name, var) \
static ssize_t var##_show(struct device *dev, \
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d3fc08..14294692beb9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -104,7 +104,7 @@ obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
-obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index f7c88ff90c43..302b57cb89c6 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -130,6 +130,7 @@ static const struct regulator_desc arizona_ldo1_hc = {
.uV_step = 50000,
.n_voltages = 8,
.enable_time = 1500,
+ .ramp_delay = 24000,
.owner = THIS_MODULE,
};
@@ -153,6 +154,7 @@ static const struct regulator_desc arizona_ldo1 = {
.uV_step = 25000,
.n_voltages = 13,
.enable_time = 500,
+ .ramp_delay = 24000,
.owner = THIS_MODULE,
};
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 54382ef902c6..e6a512ebeae2 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -337,10 +337,18 @@ static const struct regulator_desc axp809_regulators[] = {
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
- AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+ /*
+ * Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints
+ */
+ AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
- AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+ /*
+ * Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints
+ */
+ AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 5c1519b229e0..04baac9a165b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -204,7 +204,7 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
if (!regnode) {
- dev_dbg(dev, "Looking up %s property in node %s failed",
+ dev_dbg(dev, "Looking up %s property in node %s failed\n",
prop_name, dev->of_node->full_name);
return NULL;
}
@@ -293,7 +293,8 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
}
/* operating mode constraint check */
-static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
+static int regulator_mode_constrain(struct regulator_dev *rdev,
+ unsigned int *mode)
{
switch (*mode) {
case REGULATOR_MODE_FAST:
@@ -3359,6 +3360,39 @@ unsigned int regulator_get_mode(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_get_mode);
+static int _regulator_get_error_flags(struct regulator_dev *rdev,
+ unsigned int *flags)
+{
+ int ret;
+
+ mutex_lock(&rdev->mutex);
+
+ /* sanity check */
+ if (!rdev->desc->ops->get_error_flags) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = rdev->desc->ops->get_error_flags(rdev, flags);
+out:
+ mutex_unlock(&rdev->mutex);
+ return ret;
+}
+
+/**
+ * regulator_get_error_flags - get regulator error information
+ * @regulator: regulator source
+ * @flags: pointer to store error flags
+ *
+ * Get the current regulator error information.
+ */
+int regulator_get_error_flags(struct regulator *regulator,
+ unsigned int *flags)
+{
+ return _regulator_get_error_flags(regulator->rdev, flags);
+}
+EXPORT_SYMBOL_GPL(regulator_get_error_flags);
+
/**
* regulator_set_load - set regulator load
* @regulator: regulator source
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 988a7472c2ab..a43b0e8a438d 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -30,6 +30,9 @@
#include <linux/of_gpio.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
+#include <linux/acpi.h>
+#include <linux/property.h>
+#include <linux/gpio/consumer.h>
struct fixed_voltage_data {
struct regulator_desc desc;
@@ -94,6 +97,44 @@ of_get_fixed_voltage_config(struct device *dev,
return config;
}
+/**
+ * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
+ *
+ * Populates fixed_voltage_config structure by extracting data through ACPI
+ * interface, returns a pointer to the populated structure of NULL if memory
+ * alloc fails.
+ */
+static struct fixed_voltage_config *
+acpi_get_fixed_voltage_config(struct device *dev,
+ const struct regulator_desc *desc)
+{
+ struct fixed_voltage_config *config;
+ const char *supply_name;
+ struct gpio_desc *gpiod;
+ int ret;
+
+ config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return ERR_PTR(-ENOMEM);
+
+ ret = device_property_read_string(dev, "supply-name", &supply_name);
+ if (!ret)
+ config->supply_name = supply_name;
+
+ gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
+ if (IS_ERR(gpiod))
+ return ERR_PTR(-ENODEV);
+
+ config->gpio = desc_to_gpio(gpiod);
+ config->enable_high = device_property_read_bool(dev,
+ "enable-active-high");
+ gpiod_put(gpiod);
+
+ return config;
+}
+
static struct regulator_ops fixed_voltage_ops = {
};
@@ -114,6 +155,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
&drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
+ } else if (ACPI_HANDLE(&pdev->dev)) {
+ config = acpi_get_fixed_voltage_config(&pdev->dev,
+ &drvdata->desc);
+ if (IS_ERR(config))
+ return PTR_ERR(config);
} else {
config = dev_get_platdata(&pdev->dev);
}
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 83e89e5d4752..0fce06acfaec 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -162,8 +162,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
- if (config->enable_gpio == -EPROBE_DEFER)
- return ERR_PTR(-EPROBE_DEFER);
+ if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT)
+ return ERR_PTR(config->enable_gpio);
/* Fetch GPIOs. - optional property*/
ret = of_gpio_count(np);
@@ -190,8 +190,11 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
for (i = 0; i < config->nr_gpios; i++) {
gpio = of_get_named_gpio(np, "gpios", i);
- if (gpio < 0)
+ if (gpio < 0) {
+ if (gpio != -ENOENT)
+ return ERR_PTR(gpio);
break;
+ }
config->gpios[i].gpio = gpio;
if (proplen > 0) {
of_property_read_u32_index(np, "gpios-states",
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index bcf38fd5106a..379cdacc05d8 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -454,13 +454,17 @@ EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
{
unsigned int val;
+ unsigned int val_on = rdev->desc->bypass_val_on;
int ret;
ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
if (ret != 0)
return ret;
- *enable = (val & rdev->desc->bypass_mask) == rdev->desc->bypass_val_on;
+ if (!val_on)
+ val_on = rdev->desc->bypass_mask;
+
+ *enable = (val & rdev->desc->bypass_mask) == val_on;
return 0;
}
diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c
index e504b9148226..70e3df653381 100644
--- a/drivers/regulator/lp873x-regulator.c
+++ b/drivers/regulator/lp873x-regulator.c
@@ -24,6 +24,7 @@
[_id] = { \
.desc = { \
.name = _name, \
+ .supply_name = _of "-in", \
.id = _id, \
.of_match = of_match_ptr(_of), \
.regulators_node = of_match_ptr("regulators"),\
diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c
index a1b49a6d538f..d088a7c79e60 100644
--- a/drivers/regulator/max77620-regulator.c
+++ b/drivers/regulator/max77620-regulator.c
@@ -73,7 +73,6 @@ struct max77620_regulator_info {
};
struct max77620_regulator_pdata {
- struct regulator_init_data *reg_idata;
int active_fps_src;
int active_fps_pd_slot;
int active_fps_pu_slot;
@@ -81,6 +80,7 @@ struct max77620_regulator_pdata {
int suspend_fps_pd_slot;
int suspend_fps_pu_slot;
int current_mode;
+ int power_ok;
int ramp_rate_setting;
};
@@ -351,11 +351,48 @@ static int max77620_set_slew_rate(struct max77620_regulator *pmic, int id,
return 0;
}
+static int max77620_config_power_ok(struct max77620_regulator *pmic, int id)
+{
+ struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ struct max77620_chip *chip = dev_get_drvdata(pmic->dev->parent);
+ u8 val, mask;
+ int ret;
+
+ switch (chip->chip_id) {
+ case MAX20024:
+ if (rpdata->power_ok >= 0) {
+ if (rinfo->type == MAX77620_REGULATOR_TYPE_SD)
+ mask = MAX20024_SD_CFG1_MPOK_MASK;
+ else
+ mask = MAX20024_LDO_CFG2_MPOK_MASK;
+
+ val = rpdata->power_ok ? mask : 0;
+
+ ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
+ mask, val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
+ rinfo->cfg_addr, ret);
+ return ret;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int max77620_init_pmic(struct max77620_regulator *pmic, int id)
{
struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
int ret;
+ max77620_config_power_ok(pmic, id);
+
/* Update power mode */
ret = max77620_regulator_get_power_mode(pmic, id);
if (ret < 0)
@@ -595,6 +632,12 @@ static int max77620_of_parse_cb(struct device_node *np,
np, "maxim,suspend-fps-power-down-slot", &pval);
rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1;
+ ret = of_property_read_u32(np, "maxim,power-ok-control", &pval);
+ if (!ret)
+ rpdata->power_ok = pval;
+ else
+ rpdata->power_ok = -1;
+
ret = of_property_read_u32(np, "maxim,ramp-rate-setting", &pval);
rpdata->ramp_rate_setting = (!ret) ? pval : 0;
@@ -807,6 +850,8 @@ static int max77620_regulator_resume(struct device *dev)
for (id = 0; id < MAX77620_NUM_REGS; id++) {
reg_pdata = &pmic->reg_pdata[id];
+ max77620_config_power_ok(pmic, id);
+
max77620_regulator_set_fps_slots(pmic, id, false);
if (reg_pdata->active_fps_src < 0)
continue;
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
index 7d2ae3e9e942..342f5da79975 100644
--- a/drivers/regulator/stw481x-vmmc.c
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -47,7 +47,8 @@ static struct regulator_desc vmmc_regulator = {
.volt_table = stw481x_vmmc_voltages,
.enable_time = 200, /* FIXME: look this up */
.enable_reg = STW_CONF1,
- .enable_mask = STW_CONF1_PDN_VMMC,
+ .enable_mask = STW_CONF1_PDN_VMMC | STW_CONF1_MMC_LS_STATUS,
+ .enable_val = STW_CONF1_PDN_VMMC,
.vsel_reg = STW_CONF1,
.vsel_mask = STW_CONF1_VMMC_MASK,
};
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index dad0bac09ecf..c179a3a221af 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -375,7 +375,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data(
struct device_node *np = pdev->dev.parent->of_node;
struct device_node *regulators;
struct of_regulator_match *matches;
- static struct regulator_init_data *reg_data;
+ struct regulator_init_data *reg_data;
int idx = 0, count, ret;
tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board),
diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c
index 33f389d583ef..ecb0371780af 100644
--- a/drivers/regulator/tps65086-regulator.c
+++ b/drivers/regulator/tps65086-regulator.c
@@ -71,7 +71,7 @@ struct tps65086_regulator {
unsigned int decay_mask;
};
-static const struct regulator_linear_range tps65086_buck126_10mv_ranges[] = {
+static const struct regulator_linear_range tps65086_10mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),
};
@@ -82,7 +82,7 @@ static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),
};
-static const struct regulator_linear_range tps65086_buck345_ranges[] = {
+static const struct regulator_linear_range tps65086_buck345_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),
};
@@ -125,27 +125,27 @@ static int tps65086_of_parse_cb(struct device_node *dev,
static struct tps65086_regulator regulators[] = {
TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),
- tps65086_buck126_10mv_ranges, TPS65086_BUCK1CTRL,
+ tps65086_10mv_ranges, TPS65086_BUCK1CTRL,
BIT(0)),
TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),
- tps65086_buck126_10mv_ranges, TPS65086_BUCK2CTRL,
+ tps65086_10mv_ranges, TPS65086_BUCK2CTRL,
BIT(0)),
TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),
- tps65086_buck345_ranges, TPS65086_BUCK3DECAY,
+ tps65086_10mv_ranges, TPS65086_BUCK3DECAY,
BIT(0)),
TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,
BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),
- tps65086_buck345_ranges, TPS65086_BUCK4VID,
+ tps65086_10mv_ranges, TPS65086_BUCK4VID,
BIT(0)),
TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,
BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),
- tps65086_buck345_ranges, TPS65086_BUCK5CTRL,
+ tps65086_10mv_ranges, TPS65086_BUCK5CTRL,
BIT(0)),
TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,
BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),
- tps65086_buck126_10mv_ranges, TPS65086_BUCK6CTRL,
+ tps65086_10mv_ranges, TPS65086_BUCK6CTRL,
BIT(0)),
TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,
VDOA1_VID_MASK, TPS65086_LDOA1CTRL, BIT(0),
@@ -162,18 +162,6 @@ static struct tps65086_regulator regulators[] = {
TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),
};
-static inline bool has_25mv_mode(int id)
-{
- switch (id) {
- case BUCK1:
- case BUCK2:
- case BUCK6:
- return true;
- default:
- return false;
- }
-}
-
static int tps65086_of_parse_cb(struct device_node *dev,
const struct regulator_desc *desc,
struct regulator_config *config)
@@ -181,12 +169,27 @@ static int tps65086_of_parse_cb(struct device_node *dev,
int ret;
/* Check for 25mV step mode */
- if (has_25mv_mode(desc->id) &&
- of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
- regulators[desc->id].desc.linear_ranges =
+ if (of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
+ switch (desc->id) {
+ case BUCK1:
+ case BUCK2:
+ case BUCK6:
+ regulators[desc->id].desc.linear_ranges =
tps65086_buck126_25mv_ranges;
- regulators[desc->id].desc.n_linear_ranges =
+ regulators[desc->id].desc.n_linear_ranges =
ARRAY_SIZE(tps65086_buck126_25mv_ranges);
+ break;
+ case BUCK3:
+ case BUCK4:
+ case BUCK5:
+ regulators[desc->id].desc.linear_ranges =
+ tps65086_buck345_25mv_ranges;
+ regulators[desc->id].desc.n_linear_ranges =
+ ARRAY_SIZE(tps65086_buck345_25mv_ranges);
+ break;
+ default:
+ dev_warn(config->dev, "25mV step mode only valid for BUCK regulators\n");
+ }
}
/* Check for decay mode */
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 210681d6b743..6c9ec84121bd 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -24,7 +24,7 @@
#include <linux/delay.h>
/*
- * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a
+ * The TWL4030/TW5030/TPS659x0 family chips include power management, a
* USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions
* include an audio codec, battery charger, and more voltage regulators.
* These chips are often used in OMAP-based systems.
@@ -48,25 +48,12 @@ struct twlreg_info {
/* State REMAP default configuration */
u8 remap;
- /* chip constraints on regulator behavior */
- u16 min_mV;
- u16 max_mV;
-
- u8 flags;
-
/* used by regulator core */
struct regulator_desc desc;
/* chip specific features */
unsigned long features;
- /*
- * optional override functions for voltage set/get
- * these are currently only used for SMPS regulators
- */
- int (*get_voltage)(void *data);
- int (*set_voltage)(void *data, int target_uV);
-
/* data passed from board for external get/set voltage */
void *data;
};
@@ -88,33 +75,6 @@ struct twlreg_info {
#define VREG_STATE 2
#define VREG_VOLTAGE 3
#define VREG_VOLTAGE_SMPS 4
-/* TWL6030 Misc register offsets */
-#define VREG_BC_ALL 1
-#define VREG_BC_REF 2
-#define VREG_BC_PROC 3
-#define VREG_BC_CLK_RST 4
-
-/* TWL6030 LDO register values for CFG_STATE */
-#define TWL6030_CFG_STATE_OFF 0x00
-#define TWL6030_CFG_STATE_ON 0x01
-#define TWL6030_CFG_STATE_OFF2 0x02
-#define TWL6030_CFG_STATE_SLEEP 0x03
-#define TWL6030_CFG_STATE_GRP_SHIFT 5
-#define TWL6030_CFG_STATE_APP_SHIFT 2
-#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
-#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
- TWL6030_CFG_STATE_APP_SHIFT)
-
-/* Flags for SMPS Voltage reading */
-#define SMPS_OFFSET_EN BIT(0)
-#define SMPS_EXTENDED_EN BIT(1)
-
-/* twl6032 SMPS EPROM values */
-#define TWL6030_SMPS_OFFSET 0xB0
-#define TWL6030_SMPS_MULT 0xB3
-#define SMPS_MULTOFFSET_SMPS4 BIT(0)
-#define SMPS_MULTOFFSET_VIO BIT(1)
-#define SMPS_MULTOFFSET_SMPS3 BIT(6)
static inline int
twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
@@ -168,26 +128,6 @@ static int twl4030reg_is_enabled(struct regulator_dev *rdev)
return state & P1_GRP_4030;
}
-static int twl6030reg_is_enabled(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int grp = 0, val;
-
- if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) {
- grp = twlreg_grp(rdev);
- if (grp < 0)
- return grp;
- grp &= P1_GRP_6030;
- } else {
- grp = 1;
- }
-
- val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
- val = TWL6030_CFG_STATE_APP(val);
-
- return grp && (val == TWL6030_CFG_STATE_ON);
-}
-
#define PB_I2C_BUSY BIT(0)
#define PB_I2C_BWEN BIT(1)
@@ -273,23 +213,6 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
return ret;
}
-static int twl6030reg_enable(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int grp = 0;
- int ret;
-
- if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
- grp = twlreg_grp(rdev);
- if (grp < 0)
- return grp;
-
- ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
- grp << TWL6030_CFG_STATE_GRP_SHIFT |
- TWL6030_CFG_STATE_ON);
- return ret;
-}
-
static int twl4030reg_disable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
@@ -307,23 +230,6 @@ static int twl4030reg_disable(struct regulator_dev *rdev)
return ret;
}
-static int twl6030reg_disable(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int grp = 0;
- int ret;
-
- if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
- grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
-
- /* For 6030, set the off state for all grps enabled */
- ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
- (grp) << TWL6030_CFG_STATE_GRP_SHIFT |
- TWL6030_CFG_STATE_OFF);
-
- return ret;
-}
-
static int twl4030reg_get_status(struct regulator_dev *rdev)
{
int state = twlreg_grp(rdev);
@@ -340,33 +246,6 @@ static int twl4030reg_get_status(struct regulator_dev *rdev)
: REGULATOR_STATUS_STANDBY;
}
-static int twl6030reg_get_status(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int val;
-
- val = twlreg_grp(rdev);
- if (val < 0)
- return val;
-
- val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
-
- switch (TWL6030_CFG_STATE_APP(val)) {
- case TWL6030_CFG_STATE_ON:
- return REGULATOR_STATUS_NORMAL;
-
- case TWL6030_CFG_STATE_SLEEP:
- return REGULATOR_STATUS_STANDBY;
-
- case TWL6030_CFG_STATE_OFF:
- case TWL6030_CFG_STATE_OFF2:
- default:
- break;
- }
-
- return REGULATOR_STATUS_OFF;
-}
-
static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
@@ -399,36 +278,6 @@ static inline unsigned int twl4030reg_map_mode(unsigned int mode)
}
}
-static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int grp = 0;
- int val;
-
- if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
- grp = twlreg_grp(rdev);
-
- if (grp < 0)
- return grp;
-
- /* Compose the state register settings */
- val = grp << TWL6030_CFG_STATE_GRP_SHIFT;
- /* We can only set the mode through state machine commands... */
- switch (mode) {
- case REGULATOR_MODE_NORMAL:
- val |= TWL6030_CFG_STATE_ON;
- break;
- case REGULATOR_MODE_STANDBY:
- val |= TWL6030_CFG_STATE_SLEEP;
- break;
-
- default:
- return -EINVAL;
- }
-
- return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val);
-}
-
/*----------------------------------------------------------------------*/
/*
@@ -565,12 +414,7 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
- if (info->set_voltage) {
- return info->set_voltage(info->data, min_uV);
- } else {
- twlreg_write(info, TWL_MODULE_PM_RECEIVER,
- VREG_VOLTAGE_SMPS_4030, vsel);
- }
+ twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, vsel);
return 0;
}
@@ -580,9 +424,6 @@ static int twl4030smps_get_voltage(struct regulator_dev *rdev)
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel;
- if (info->get_voltage)
- return info->get_voltage(info->data);
-
vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
VREG_VOLTAGE_SMPS_4030);
@@ -594,85 +435,6 @@ static struct regulator_ops twl4030smps_ops = {
.get_voltage = twl4030smps_get_voltage,
};
-static int twl6030coresmps_set_voltage(struct regulator_dev *rdev, int min_uV,
- int max_uV, unsigned *selector)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- if (info->set_voltage)
- return info->set_voltage(info->data, min_uV);
-
- return -ENODEV;
-}
-
-static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- if (info->get_voltage)
- return info->get_voltage(info->data);
-
- return -ENODEV;
-}
-
-static struct regulator_ops twl6030coresmps_ops = {
- .set_voltage = twl6030coresmps_set_voltage,
- .get_voltage = twl6030coresmps_get_voltage,
-};
-
-static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- switch (sel) {
- case 0:
- return 0;
- case 1 ... 24:
- /* Linear mapping from 00000001 to 00011000:
- * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
- */
- return (info->min_mV + 100 * (sel - 1)) * 1000;
- case 25 ... 30:
- return -EINVAL;
- case 31:
- return 2750000;
- default:
- return -EINVAL;
- }
-}
-
-static int
-twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
- selector);
-}
-
-static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
-
- return vsel;
-}
-
-static struct regulator_ops twl6030ldo_ops = {
- .list_voltage = twl6030ldo_list_voltage,
-
- .set_voltage_sel = twl6030ldo_set_voltage_sel,
- .get_voltage_sel = twl6030ldo_get_voltage_sel,
-
- .enable = twl6030reg_enable,
- .disable = twl6030reg_disable,
- .is_enabled = twl6030reg_is_enabled,
-
- .set_mode = twl6030reg_set_mode,
-
- .get_status = twl6030reg_get_status,
-};
-
/*----------------------------------------------------------------------*/
static struct regulator_ops twl4030fixed_ops = {
@@ -687,226 +449,8 @@ static struct regulator_ops twl4030fixed_ops = {
.get_status = twl4030reg_get_status,
};
-static struct regulator_ops twl6030fixed_ops = {
- .list_voltage = regulator_list_voltage_linear,
-
- .enable = twl6030reg_enable,
- .disable = twl6030reg_disable,
- .is_enabled = twl6030reg_is_enabled,
-
- .set_mode = twl6030reg_set_mode,
-
- .get_status = twl6030reg_get_status,
-};
-
-/*
- * SMPS status and control
- */
-
-static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- int voltage = 0;
-
- switch (info->flags) {
- case SMPS_OFFSET_EN:
- voltage = 100000;
- /* fall through */
- case 0:
- switch (index) {
- case 0:
- voltage = 0;
- break;
- case 58:
- voltage = 1350 * 1000;
- break;
- case 59:
- voltage = 1500 * 1000;
- break;
- case 60:
- voltage = 1800 * 1000;
- break;
- case 61:
- voltage = 1900 * 1000;
- break;
- case 62:
- voltage = 2100 * 1000;
- break;
- default:
- voltage += (600000 + (12500 * (index - 1)));
- }
- break;
- case SMPS_EXTENDED_EN:
- switch (index) {
- case 0:
- voltage = 0;
- break;
- case 58:
- voltage = 2084 * 1000;
- break;
- case 59:
- voltage = 2315 * 1000;
- break;
- case 60:
- voltage = 2778 * 1000;
- break;
- case 61:
- voltage = 2932 * 1000;
- break;
- case 62:
- voltage = 3241 * 1000;
- break;
- default:
- voltage = (1852000 + (38600 * (index - 1)));
- }
- break;
- case SMPS_OFFSET_EN | SMPS_EXTENDED_EN:
- switch (index) {
- case 0:
- voltage = 0;
- break;
- case 58:
- voltage = 4167 * 1000;
- break;
- case 59:
- voltage = 2315 * 1000;
- break;
- case 60:
- voltage = 2778 * 1000;
- break;
- case 61:
- voltage = 2932 * 1000;
- break;
- case 62:
- voltage = 3241 * 1000;
- break;
- default:
- voltage = (2161000 + (38600 * (index - 1)));
- }
- break;
- }
-
- return voltage;
-}
-
-static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV,
- int max_uV)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
- int vsel = 0;
-
- switch (info->flags) {
- case 0:
- if (min_uV == 0)
- vsel = 0;
- else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
- vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
- vsel++;
- }
- /* Values 1..57 for vsel are linear and can be calculated
- * values 58..62 are non linear.
- */
- else if ((min_uV > 1900000) && (min_uV <= 2100000))
- vsel = 62;
- else if ((min_uV > 1800000) && (min_uV <= 1900000))
- vsel = 61;
- else if ((min_uV > 1500000) && (min_uV <= 1800000))
- vsel = 60;
- else if ((min_uV > 1350000) && (min_uV <= 1500000))
- vsel = 59;
- else if ((min_uV > 1300000) && (min_uV <= 1350000))
- vsel = 58;
- else
- return -EINVAL;
- break;
- case SMPS_OFFSET_EN:
- if (min_uV == 0)
- vsel = 0;
- else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
- vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
- vsel++;
- }
- /* Values 1..57 for vsel are linear and can be calculated
- * values 58..62 are non linear.
- */
- else if ((min_uV > 1900000) && (min_uV <= 2100000))
- vsel = 62;
- else if ((min_uV > 1800000) && (min_uV <= 1900000))
- vsel = 61;
- else if ((min_uV > 1350000) && (min_uV <= 1800000))
- vsel = 60;
- else if ((min_uV > 1350000) && (min_uV <= 1500000))
- vsel = 59;
- else if ((min_uV > 1300000) && (min_uV <= 1350000))
- vsel = 58;
- else
- return -EINVAL;
- break;
- case SMPS_EXTENDED_EN:
- if (min_uV == 0) {
- vsel = 0;
- } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
- vsel = DIV_ROUND_UP(min_uV - 1852000, 38600);
- vsel++;
- }
- break;
- case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
- if (min_uV == 0) {
- vsel = 0;
- } else if ((min_uV >= 2161000) && (min_uV <= 4321000)) {
- vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
- vsel++;
- }
- break;
- }
-
- return vsel;
-}
-
-static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev,
- unsigned int selector)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
- selector);
-}
-
-static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
-}
-
-static struct regulator_ops twlsmps_ops = {
- .list_voltage = twl6030smps_list_voltage,
- .map_voltage = twl6030smps_map_voltage,
-
- .set_voltage_sel = twl6030smps_set_voltage_sel,
- .get_voltage_sel = twl6030smps_get_voltage_sel,
-
- .enable = twl6030reg_enable,
- .disable = twl6030reg_disable,
- .is_enabled = twl6030reg_is_enabled,
-
- .set_mode = twl6030reg_set_mode,
-
- .get_status = twl6030reg_get_status,
-};
-
/*----------------------------------------------------------------------*/
-#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
- remap_conf) \
- TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
- remap_conf, TWL4030, twl4030fixed_ops, \
- twl4030reg_map_mode)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
- TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
- 0x0, TWL6030, twl6030fixed_ops, NULL)
-
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
static const struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \
@@ -942,79 +486,22 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
}, \
}
-#define TWL6030_ADJUSTABLE_SMPS(label) \
-static const struct twlreg_info TWL6030_INFO_##label = { \
- .desc = { \
- .name = #label, \
- .id = TWL6030_REG_##label, \
- .ops = &twl6030coresmps_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- }, \
- }
-
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
-static const struct twlreg_info TWL6030_INFO_##label = { \
- .base = offset, \
- .min_mV = min_mVolts, \
- .max_mV = max_mVolts, \
- .desc = { \
- .name = #label, \
- .id = TWL6030_REG_##label, \
- .n_voltages = 32, \
- .ops = &twl6030ldo_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- }, \
- }
-
-#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
-static const struct twlreg_info TWL6032_INFO_##label = { \
- .base = offset, \
- .min_mV = min_mVolts, \
- .max_mV = max_mVolts, \
- .desc = { \
- .name = #label, \
- .id = TWL6032_REG_##label, \
- .n_voltages = 32, \
- .ops = &twl6030ldo_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- }, \
- }
-
-#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
- family, operations, map_mode) \
+#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+ remap_conf) \
static const struct twlreg_info TWLFIXED_INFO_##label = { \
.base = offset, \
.id = num, \
- .min_mV = mVolts, \
.remap = remap_conf, \
.desc = { \
.name = #label, \
- .id = family##_REG_##label, \
+ .id = TWL4030##_REG_##label, \
.n_voltages = 1, \
- .ops = &operations, \
+ .ops = &twl4030fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = mVolts * 1000, \
.enable_time = turnon_delay, \
- .of_map_mode = map_mode, \
- }, \
- }
-
-#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
-static const struct twlreg_info TWLSMPS_INFO_##label = { \
- .base = offset, \
- .min_mV = 600, \
- .max_mV = 2100, \
- .desc = { \
- .name = #label, \
- .id = TWL6032_REG_##label, \
- .n_voltages = 63, \
- .ops = &twlsmps_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
+ .of_map_mode = twl4030reg_map_mode, \
}, \
}
@@ -1038,60 +525,11 @@ TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08);
TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08);
TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08);
/* VUSBCP is managed *only* by the USB subchip */
-/* 6030 REG with base as PMC Slave Misc : 0x0030 */
-/* Turnon-delay and remap configuration values for 6030 are not
- verified since the specification is not public */
-TWL6030_ADJUSTABLE_SMPS(VDD1);
-TWL6030_ADJUSTABLE_SMPS(VDD2);
-TWL6030_ADJUSTABLE_SMPS(VDD3);
-TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300);
-TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300);
-TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300);
-TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300);
-TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300);
-TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300);
-/* 6025 are renamed compared to 6030 versions */
-TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
-TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08);
TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08);
-TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
-TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
-TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
-TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
-TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
-TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
-TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34);
-TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10);
-TWL6032_ADJUSTABLE_SMPS(VIO, 0x16);
-
-static u8 twl_get_smps_offset(void)
-{
- u8 value;
-
- twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
- TWL6030_SMPS_OFFSET);
- return value;
-}
-
-static u8 twl_get_smps_mult(void)
-{
- u8 value;
-
- twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
- TWL6030_SMPS_MULT);
- return value;
-}
#define TWL_OF_MATCH(comp, family, label) \
{ \
@@ -1121,81 +559,37 @@ static const struct of_device_id twl_of_match[] = {
TWL4030_OF_MATCH("ti,twl4030-vio", VIO),
TWL4030_OF_MATCH("ti,twl4030-vdd1", VDD1),
TWL4030_OF_MATCH("ti,twl4030-vdd2", VDD2),
- TWL6030_OF_MATCH("ti,twl6030-vdd1", VDD1),
- TWL6030_OF_MATCH("ti,twl6030-vdd2", VDD2),
- TWL6030_OF_MATCH("ti,twl6030-vdd3", VDD3),
- TWL6030_OF_MATCH("ti,twl6030-vaux1", VAUX1_6030),
- TWL6030_OF_MATCH("ti,twl6030-vaux2", VAUX2_6030),
- TWL6030_OF_MATCH("ti,twl6030-vaux3", VAUX3_6030),
- TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
- TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
- TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
- TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2),
- TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4),
- TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3),
- TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5),
- TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1),
- TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7),
- TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6),
- TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN),
- TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB),
TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1),
TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),
TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8),
TWLFIXED_OF_MATCH("ti,twl4030-vusb3v1", VUSB3V1),
- TWLFIXED_OF_MATCH("ti,twl6030-vana", VANA),
- TWLFIXED_OF_MATCH("ti,twl6030-vcxio", VCXIO),
- TWLFIXED_OF_MATCH("ti,twl6030-vdac", VDAC),
- TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
- TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
- TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
- TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3),
- TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4),
- TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
{},
};
MODULE_DEVICE_TABLE(of, twl_of_match);
static int twlreg_probe(struct platform_device *pdev)
{
- int i, id;
+ int id;
struct twlreg_info *info;
const struct twlreg_info *template;
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
- struct twl_regulator_driver_data *drvdata;
const struct of_device_id *match;
struct regulator_config config = { };
match = of_match_device(twl_of_match, &pdev->dev);
- if (match) {
- template = match->data;
- id = template->desc.id;
- initdata = of_get_regulator_init_data(&pdev->dev,
- pdev->dev.of_node,
- &template->desc);
- drvdata = NULL;
- } else {
- id = pdev->id;
- initdata = dev_get_platdata(&pdev->dev);
- for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
- template = twl_of_match[i].data;
- if (template && template->desc.id == id)
- break;
- }
- if (i == ARRAY_SIZE(twl_of_match))
- return -ENODEV;
-
- drvdata = initdata->driver_data;
- if (!drvdata)
- return -EINVAL;
- }
+ if (!match)
+ return -ENODEV;
+ template = match->data;
if (!template)
return -ENODEV;
+ id = template->desc.id;
+ initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+ &template->desc);
if (!initdata)
return -EINVAL;
@@ -1203,14 +597,6 @@ static int twlreg_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
- if (drvdata) {
- /* copy the driver data into regulator data */
- info->features = drvdata->features;
- info->data = drvdata->data;
- info->set_voltage = drvdata->set_voltage;
- info->get_voltage = drvdata->get_voltage;
- }
-
/* Constrain board-specific capabilities according to what
* this driver and the chip itself can actually do.
*/
@@ -1233,27 +619,6 @@ static int twlreg_probe(struct platform_device *pdev)
break;
}
- switch (id) {
- case TWL6032_REG_SMPS3:
- if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
- info->flags |= SMPS_EXTENDED_EN;
- if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
- info->flags |= SMPS_OFFSET_EN;
- break;
- case TWL6032_REG_SMPS4:
- if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
- info->flags |= SMPS_EXTENDED_EN;
- if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
- info->flags |= SMPS_OFFSET_EN;
- break;
- case TWL6032_REG_VIO:
- if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
- info->flags |= SMPS_EXTENDED_EN;
- if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
- info->flags |= SMPS_OFFSET_EN;
- break;
- }
-
config.dev = &pdev->dev;
config.init_data = initdata;
config.driver_data = info;
@@ -1267,9 +632,7 @@ static int twlreg_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, rdev);
- if (twl_class_is_4030())
- twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
- info->remap);
+ twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap);
/* NOTE: many regulators support short-circuit IRQs (presentable
* as REGULATOR_OVER_CURRENT notifications?) configured via:
@@ -1282,7 +645,7 @@ static int twlreg_probe(struct platform_device *pdev)
return 0;
}
-MODULE_ALIAS("platform:twl_reg");
+MODULE_ALIAS("platform:twl4030_reg");
static struct platform_driver twlreg_driver = {
.probe = twlreg_probe,
@@ -1290,7 +653,7 @@ static struct platform_driver twlreg_driver = {
* "twl_regulator.12" (and friends) to "twl_regulator.1".
*/
.driver = {
- .name = "twl_reg",
+ .name = "twl4030_reg",
.of_match_table = of_match_ptr(twl_of_match),
},
};
@@ -1307,5 +670,5 @@ static void __exit twlreg_exit(void)
}
module_exit(twlreg_exit)
-MODULE_DESCRIPTION("TWL regulator driver");
+MODULE_DESCRIPTION("TWL4030 regulator driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
new file mode 100644
index 000000000000..4864b9d742c0
--- /dev/null
+++ b/drivers/regulator/twl6030-regulator.c
@@ -0,0 +1,793 @@
+/*
+ * Split TWL6030 logic from twl-regulator.c:
+ * Copyright (C) 2008 David Brownell
+ *
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/i2c/twl.h>
+#include <linux/delay.h>
+
+struct twlreg_info {
+ /* start of regulator's PM_RECEIVER control register bank */
+ u8 base;
+
+ /* twl resource ID, for resource control state machine */
+ u8 id;
+
+ /* chip constraints on regulator behavior */
+ u16 min_mV;
+
+ u8 flags;
+
+ /* used by regulator core */
+ struct regulator_desc desc;
+
+ /* chip specific features */
+ unsigned long features;
+
+ /* data passed from board for external get/set voltage */
+ void *data;
+};
+
+
+/* LDO control registers ... offset is from the base of its register bank.
+ * The first three registers of all power resource banks help hardware to
+ * manage the various resource groups.
+ */
+/* Common offset in TWL4030/6030 */
+#define VREG_GRP 0
+/* TWL6030 register offsets */
+#define VREG_TRANS 1
+#define VREG_STATE 2
+#define VREG_VOLTAGE 3
+#define VREG_VOLTAGE_SMPS 4
+/* TWL6030 Misc register offsets */
+#define VREG_BC_ALL 1
+#define VREG_BC_REF 2
+#define VREG_BC_PROC 3
+#define VREG_BC_CLK_RST 4
+
+/* TWL6030 LDO register values for CFG_STATE */
+#define TWL6030_CFG_STATE_OFF 0x00
+#define TWL6030_CFG_STATE_ON 0x01
+#define TWL6030_CFG_STATE_OFF2 0x02
+#define TWL6030_CFG_STATE_SLEEP 0x03
+#define TWL6030_CFG_STATE_GRP_SHIFT 5
+#define TWL6030_CFG_STATE_APP_SHIFT 2
+#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
+#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
+ TWL6030_CFG_STATE_APP_SHIFT)
+
+/* Flags for SMPS Voltage reading */
+#define SMPS_OFFSET_EN BIT(0)
+#define SMPS_EXTENDED_EN BIT(1)
+
+/* twl6032 SMPS EPROM values */
+#define TWL6030_SMPS_OFFSET 0xB0
+#define TWL6030_SMPS_MULT 0xB3
+#define SMPS_MULTOFFSET_SMPS4 BIT(0)
+#define SMPS_MULTOFFSET_VIO BIT(1)
+#define SMPS_MULTOFFSET_SMPS3 BIT(6)
+
+static inline int
+twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
+{
+ u8 value;
+ int status;
+
+ status = twl_i2c_read_u8(slave_subgp,
+ &value, info->base + offset);
+ return (status < 0) ? status : value;
+}
+
+static inline int
+twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset,
+ u8 value)
+{
+ return twl_i2c_write_u8(slave_subgp,
+ value, info->base + offset);
+}
+
+/* generic power resource operations, which work on all regulators */
+static int twlreg_grp(struct regulator_dev *rdev)
+{
+ return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER,
+ VREG_GRP);
+}
+
+/*
+ * Enable/disable regulators by joining/leaving the P1 (processor) group.
+ * We assume nobody else is updating the DEV_GRP registers.
+ */
+/* definition for 6030 family */
+#define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */
+#define P2_GRP_6030 BIT(1) /* "peripherals" */
+#define P1_GRP_6030 BIT(0) /* CPU/Linux */
+
+static int twl6030reg_is_enabled(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int grp = 0, val;
+
+ if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) {
+ grp = twlreg_grp(rdev);
+ if (grp < 0)
+ return grp;
+ grp &= P1_GRP_6030;
+ } else {
+ grp = 1;
+ }
+
+ val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+ val = TWL6030_CFG_STATE_APP(val);
+
+ return grp && (val == TWL6030_CFG_STATE_ON);
+}
+
+#define PB_I2C_BUSY BIT(0)
+#define PB_I2C_BWEN BIT(1)
+
+
+static int twl6030reg_enable(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int grp = 0;
+ int ret;
+
+ if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
+ grp = twlreg_grp(rdev);
+ if (grp < 0)
+ return grp;
+
+ ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ grp << TWL6030_CFG_STATE_GRP_SHIFT |
+ TWL6030_CFG_STATE_ON);
+ return ret;
+}
+
+static int twl6030reg_disable(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int grp = 0;
+ int ret;
+
+ if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
+ grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
+
+ /* For 6030, set the off state for all grps enabled */
+ ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ (grp) << TWL6030_CFG_STATE_GRP_SHIFT |
+ TWL6030_CFG_STATE_OFF);
+
+ return ret;
+}
+
+static int twl6030reg_get_status(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int val;
+
+ val = twlreg_grp(rdev);
+ if (val < 0)
+ return val;
+
+ val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+
+ switch (TWL6030_CFG_STATE_APP(val)) {
+ case TWL6030_CFG_STATE_ON:
+ return REGULATOR_STATUS_NORMAL;
+
+ case TWL6030_CFG_STATE_SLEEP:
+ return REGULATOR_STATUS_STANDBY;
+
+ case TWL6030_CFG_STATE_OFF:
+ case TWL6030_CFG_STATE_OFF2:
+ default:
+ break;
+ }
+
+ return REGULATOR_STATUS_OFF;
+}
+
+static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int grp = 0;
+ int val;
+
+ if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
+ grp = twlreg_grp(rdev);
+
+ if (grp < 0)
+ return grp;
+
+ /* Compose the state register settings */
+ val = grp << TWL6030_CFG_STATE_GRP_SHIFT;
+ /* We can only set the mode through state machine commands... */
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val |= TWL6030_CFG_STATE_ON;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val |= TWL6030_CFG_STATE_SLEEP;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val);
+}
+
+static int twl6030coresmps_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ return -ENODEV;
+}
+
+static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
+{
+ return -ENODEV;
+}
+
+static struct regulator_ops twl6030coresmps_ops = {
+ .set_voltage = twl6030coresmps_set_voltage,
+ .get_voltage = twl6030coresmps_get_voltage,
+};
+
+static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ switch (sel) {
+ case 0:
+ return 0;
+ case 1 ... 24:
+ /* Linear mapping from 00000001 to 00011000:
+ * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
+ */
+ return (info->min_mV + 100 * (sel - 1)) * 1000;
+ case 25 ... 30:
+ return -EINVAL;
+ case 31:
+ return 2750000;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int
+twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
+ selector);
+}
+
+static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
+
+ return vsel;
+}
+
+static struct regulator_ops twl6030ldo_ops = {
+ .list_voltage = twl6030ldo_list_voltage,
+
+ .set_voltage_sel = twl6030ldo_set_voltage_sel,
+ .get_voltage_sel = twl6030ldo_get_voltage_sel,
+
+ .enable = twl6030reg_enable,
+ .disable = twl6030reg_disable,
+ .is_enabled = twl6030reg_is_enabled,
+
+ .set_mode = twl6030reg_set_mode,
+
+ .get_status = twl6030reg_get_status,
+};
+
+static struct regulator_ops twl6030fixed_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+
+ .enable = twl6030reg_enable,
+ .disable = twl6030reg_disable,
+ .is_enabled = twl6030reg_is_enabled,
+
+ .set_mode = twl6030reg_set_mode,
+
+ .get_status = twl6030reg_get_status,
+};
+
+/*
+ * SMPS status and control
+ */
+
+static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ int voltage = 0;
+
+ switch (info->flags) {
+ case SMPS_OFFSET_EN:
+ voltage = 100000;
+ /* fall through */
+ case 0:
+ switch (index) {
+ case 0:
+ voltage = 0;
+ break;
+ case 58:
+ voltage = 1350 * 1000;
+ break;
+ case 59:
+ voltage = 1500 * 1000;
+ break;
+ case 60:
+ voltage = 1800 * 1000;
+ break;
+ case 61:
+ voltage = 1900 * 1000;
+ break;
+ case 62:
+ voltage = 2100 * 1000;
+ break;
+ default:
+ voltage += (600000 + (12500 * (index - 1)));
+ }
+ break;
+ case SMPS_EXTENDED_EN:
+ switch (index) {
+ case 0:
+ voltage = 0;
+ break;
+ case 58:
+ voltage = 2084 * 1000;
+ break;
+ case 59:
+ voltage = 2315 * 1000;
+ break;
+ case 60:
+ voltage = 2778 * 1000;
+ break;
+ case 61:
+ voltage = 2932 * 1000;
+ break;
+ case 62:
+ voltage = 3241 * 1000;
+ break;
+ default:
+ voltage = (1852000 + (38600 * (index - 1)));
+ }
+ break;
+ case SMPS_OFFSET_EN | SMPS_EXTENDED_EN:
+ switch (index) {
+ case 0:
+ voltage = 0;
+ break;
+ case 58:
+ voltage = 4167 * 1000;
+ break;
+ case 59:
+ voltage = 2315 * 1000;
+ break;
+ case 60:
+ voltage = 2778 * 1000;
+ break;
+ case 61:
+ voltage = 2932 * 1000;
+ break;
+ case 62:
+ voltage = 3241 * 1000;
+ break;
+ default:
+ voltage = (2161000 + (38600 * (index - 1)));
+ }
+ break;
+ }
+
+ return voltage;
+}
+
+static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+ int vsel = 0;
+
+ switch (info->flags) {
+ case 0:
+ if (min_uV == 0)
+ vsel = 0;
+ else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
+ vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
+ vsel++;
+ }
+ /* Values 1..57 for vsel are linear and can be calculated
+ * values 58..62 are non linear.
+ */
+ else if ((min_uV > 1900000) && (min_uV <= 2100000))
+ vsel = 62;
+ else if ((min_uV > 1800000) && (min_uV <= 1900000))
+ vsel = 61;
+ else if ((min_uV > 1500000) && (min_uV <= 1800000))
+ vsel = 60;
+ else if ((min_uV > 1350000) && (min_uV <= 1500000))
+ vsel = 59;
+ else if ((min_uV > 1300000) && (min_uV <= 1350000))
+ vsel = 58;
+ else
+ return -EINVAL;
+ break;
+ case SMPS_OFFSET_EN:
+ if (min_uV == 0)
+ vsel = 0;
+ else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
+ vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
+ vsel++;
+ }
+ /* Values 1..57 for vsel are linear and can be calculated
+ * values 58..62 are non linear.
+ */
+ else if ((min_uV > 1900000) && (min_uV <= 2100000))
+ vsel = 62;
+ else if ((min_uV > 1800000) && (min_uV <= 1900000))
+ vsel = 61;
+ else if ((min_uV > 1350000) && (min_uV <= 1800000))
+ vsel = 60;
+ else if ((min_uV > 1350000) && (min_uV <= 1500000))
+ vsel = 59;
+ else if ((min_uV > 1300000) && (min_uV <= 1350000))
+ vsel = 58;
+ else
+ return -EINVAL;
+ break;
+ case SMPS_EXTENDED_EN:
+ if (min_uV == 0) {
+ vsel = 0;
+ } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
+ vsel = DIV_ROUND_UP(min_uV - 1852000, 38600);
+ vsel++;
+ }
+ break;
+ case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
+ if (min_uV == 0) {
+ vsel = 0;
+ } else if ((min_uV >= 2161000) && (min_uV <= 4321000)) {
+ vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
+ vsel++;
+ }
+ break;
+ }
+
+ return vsel;
+}
+
+static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
+ selector);
+}
+
+static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
+}
+
+static struct regulator_ops twlsmps_ops = {
+ .list_voltage = twl6030smps_list_voltage,
+ .map_voltage = twl6030smps_map_voltage,
+
+ .set_voltage_sel = twl6030smps_set_voltage_sel,
+ .get_voltage_sel = twl6030smps_get_voltage_sel,
+
+ .enable = twl6030reg_enable,
+ .disable = twl6030reg_disable,
+ .is_enabled = twl6030reg_is_enabled,
+
+ .set_mode = twl6030reg_set_mode,
+
+ .get_status = twl6030reg_get_status,
+};
+
+/*----------------------------------------------------------------------*/
+
+#define TWL6030_ADJUSTABLE_SMPS(label) \
+static const struct twlreg_info TWL6030_INFO_##label = { \
+ .desc = { \
+ .name = #label, \
+ .id = TWL6030_REG_##label, \
+ .ops = &twl6030coresmps_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
+ }
+
+#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+static const struct twlreg_info TWL6030_INFO_##label = { \
+ .base = offset, \
+ .min_mV = min_mVolts, \
+ .desc = { \
+ .name = #label, \
+ .id = TWL6030_REG_##label, \
+ .n_voltages = 32, \
+ .ops = &twl6030ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
+ }
+
+#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+static const struct twlreg_info TWL6032_INFO_##label = { \
+ .base = offset, \
+ .min_mV = min_mVolts, \
+ .desc = { \
+ .name = #label, \
+ .id = TWL6032_REG_##label, \
+ .n_voltages = 32, \
+ .ops = &twl6030ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
+ }
+
+#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
+static const struct twlreg_info TWLFIXED_INFO_##label = { \
+ .base = offset, \
+ .id = 0, \
+ .min_mV = mVolts, \
+ .desc = { \
+ .name = #label, \
+ .id = TWL6030##_REG_##label, \
+ .n_voltages = 1, \
+ .ops = &twl6030fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = mVolts * 1000, \
+ .enable_time = turnon_delay, \
+ .of_map_mode = NULL, \
+ }, \
+ }
+
+#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
+static const struct twlreg_info TWLSMPS_INFO_##label = { \
+ .base = offset, \
+ .min_mV = 600, \
+ .desc = { \
+ .name = #label, \
+ .id = TWL6032_REG_##label, \
+ .n_voltages = 63, \
+ .ops = &twlsmps_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
+ }
+
+/* VUSBCP is managed *only* by the USB subchip */
+/* 6030 REG with base as PMC Slave Misc : 0x0030 */
+/* Turnon-delay and remap configuration values for 6030 are not
+ verified since the specification is not public */
+TWL6030_ADJUSTABLE_SMPS(VDD1);
+TWL6030_ADJUSTABLE_SMPS(VDD2);
+TWL6030_ADJUSTABLE_SMPS(VDD3);
+TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000);
+TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000);
+TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000);
+TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000);
+TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000);
+TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000);
+/* 6025 are renamed compared to 6030 versions */
+TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000);
+TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000);
+TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000);
+TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
+TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
+TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
+TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
+TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
+TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
+TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34);
+TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10);
+TWL6032_ADJUSTABLE_SMPS(VIO, 0x16);
+
+static u8 twl_get_smps_offset(void)
+{
+ u8 value;
+
+ twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
+ TWL6030_SMPS_OFFSET);
+ return value;
+}
+
+static u8 twl_get_smps_mult(void)
+{
+ u8 value;
+
+ twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
+ TWL6030_SMPS_MULT);
+ return value;
+}
+
+#define TWL_OF_MATCH(comp, family, label) \
+ { \
+ .compatible = comp, \
+ .data = &family##_INFO_##label, \
+ }
+
+#define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
+#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
+#define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
+#define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
+
+static const struct of_device_id twl_of_match[] = {
+ TWL6030_OF_MATCH("ti,twl6030-vdd1", VDD1),
+ TWL6030_OF_MATCH("ti,twl6030-vdd2", VDD2),
+ TWL6030_OF_MATCH("ti,twl6030-vdd3", VDD3),
+ TWL6030_OF_MATCH("ti,twl6030-vaux1", VAUX1_6030),
+ TWL6030_OF_MATCH("ti,twl6030-vaux2", VAUX2_6030),
+ TWL6030_OF_MATCH("ti,twl6030-vaux3", VAUX3_6030),
+ TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
+ TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
+ TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
+ TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2),
+ TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4),
+ TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3),
+ TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5),
+ TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1),
+ TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7),
+ TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6),
+ TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN),
+ TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB),
+ TWLFIXED_OF_MATCH("ti,twl6030-vana", VANA),
+ TWLFIXED_OF_MATCH("ti,twl6030-vcxio", VCXIO),
+ TWLFIXED_OF_MATCH("ti,twl6030-vdac", VDAC),
+ TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
+ TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
+ TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
+ TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3),
+ TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4),
+ TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
+ {},
+};
+MODULE_DEVICE_TABLE(of, twl_of_match);
+
+static int twlreg_probe(struct platform_device *pdev)
+{
+ int id;
+ struct twlreg_info *info;
+ const struct twlreg_info *template;
+ struct regulator_init_data *initdata;
+ struct regulation_constraints *c;
+ struct regulator_dev *rdev;
+ const struct of_device_id *match;
+ struct regulator_config config = { };
+
+ match = of_match_device(twl_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ template = match->data;
+ if (!template)
+ return -ENODEV;
+
+ id = template->desc.id;
+ initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+ &template->desc);
+ if (!initdata)
+ return -EINVAL;
+
+ info = devm_kmemdup(&pdev->dev, template, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ /* Constrain board-specific capabilities according to what
+ * this driver and the chip itself can actually do.
+ */
+ c = &initdata->constraints;
+ c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
+ c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS;
+
+ switch (id) {
+ case TWL6032_REG_SMPS3:
+ if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
+ info->flags |= SMPS_EXTENDED_EN;
+ if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
+ info->flags |= SMPS_OFFSET_EN;
+ break;
+ case TWL6032_REG_SMPS4:
+ if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
+ info->flags |= SMPS_EXTENDED_EN;
+ if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
+ info->flags |= SMPS_OFFSET_EN;
+ break;
+ case TWL6032_REG_VIO:
+ if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
+ info->flags |= SMPS_EXTENDED_EN;
+ if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
+ info->flags |= SMPS_OFFSET_EN;
+ break;
+ }
+
+ config.dev = &pdev->dev;
+ config.init_data = initdata;
+ config.driver_data = info;
+ config.of_node = pdev->dev.of_node;
+
+ rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "can't register %s, %ld\n",
+ info->desc.name, PTR_ERR(rdev));
+ return PTR_ERR(rdev);
+ }
+ platform_set_drvdata(pdev, rdev);
+
+ /* NOTE: many regulators support short-circuit IRQs (presentable
+ * as REGULATOR_OVER_CURRENT notifications?) configured via:
+ * - SC_CONFIG
+ * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
+ * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
+ * - IT_CONFIG
+ */
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:twl6030_reg");
+
+static struct platform_driver twlreg_driver = {
+ .probe = twlreg_probe,
+ /* NOTE: short name, to work around driver model truncation of
+ * "twl_regulator.12" (and friends) to "twl_regulator.1".
+ */
+ .driver = {
+ .name = "twl6030_reg",
+ .of_match_table = of_match_ptr(twl_of_match),
+ },
+};
+
+static int __init twlreg_init(void)
+{
+ return platform_driver_register(&twlreg_driver);
+}
+subsys_initcall(twlreg_init);
+
+static void __exit twlreg_exit(void)
+{
+ platform_driver_unregister(&twlreg_driver);
+}
+module_exit(twlreg_exit)
+
+MODULE_DESCRIPTION("TWL6030 regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f396bfef5d42..8f9cf0bc571c 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -1,20 +1,21 @@
menu "Remoteproc drivers"
-# REMOTEPROC gets selected by whoever wants it
config REMOTEPROC
- tristate
+ tristate "Support for Remote Processor subsystem"
depends on HAS_DMA
select CRC32
select FW_LOADER
select VIRTIO
select VIRTUALIZATION
+if REMOTEPROC
+
config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
depends on HAS_DMA
depends on ARCH_OMAP4 || SOC_OMAP5
depends on OMAP_IOMMU
- select REMOTEPROC
+ depends on REMOTEPROC
select MAILBOX
select OMAP2PLUS_MBOX
select RPMSG_VIRTIO
@@ -31,20 +32,10 @@ config OMAP_REMOTEPROC
It's safe to say n here if you're not interested in multimedia
offloading or just want a bare minimum kernel.
-config STE_MODEM_RPROC
- tristate "STE-Modem remoteproc support"
- depends on HAS_DMA
- select REMOTEPROC
- default n
- help
- Say y or m here to support STE-Modem shared memory driver.
- This can be either built-in or a loadable module.
- If unsure say N.
-
config WKUP_M3_RPROC
tristate "AMx3xx Wakeup M3 remoteproc support"
depends on SOC_AM33XX || SOC_AM43XX
- select REMOTEPROC
+ depends on REMOTEPROC
help
Say y here to support Wakeup M3 remote processor on TI AM33xx
and AM43xx family of SoCs.
@@ -57,8 +48,8 @@ config WKUP_M3_RPROC
config DA8XX_REMOTEPROC
tristate "DA8xx/OMAP-L13x remoteproc support"
depends on ARCH_DAVINCI_DA8XX
+ depends on REMOTEPROC
select CMA if MMU
- select REMOTEPROC
select RPMSG_VIRTIO
help
Say y here to support DA8xx/OMAP-L13x remote processors via the
@@ -77,6 +68,18 @@ config DA8XX_REMOTEPROC
It's safe to say n here if you're not interested in multimedia
offloading.
+config QCOM_ADSP_PIL
+ tristate "Qualcomm ADSP Peripheral Image Loader"
+ depends on OF && ARCH_QCOM
+ depends on REMOTEPROC
+ depends on QCOM_SMEM
+ select MFD_SYSCON
+ select QCOM_MDT_LOADER
+ select QCOM_SCM
+ help
+ Say y here to support the TrustZone based Peripherial Image Loader
+ for the Qualcomm ADSP remote processors.
+
config QCOM_MDT_LOADER
tristate
@@ -84,25 +87,22 @@ config QCOM_Q6V5_PIL
tristate "Qualcomm Hexagon V5 Peripherial Image Loader"
depends on OF && ARCH_QCOM
depends on QCOM_SMEM
+ depends on REMOTEPROC
select MFD_SYSCON
select QCOM_MDT_LOADER
- select REMOTEPROC
+ select QCOM_SCM
help
Say y here to support the Qualcomm Peripherial Image Loader for the
Hexagon V5 based remote processors.
-config QCOM_WCNSS_IRIS
- tristate
- depends on OF && ARCH_QCOM
-
config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
+ depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
depends on QCOM_SMEM
+ depends on REMOTEPROC
select QCOM_MDT_LOADER
select QCOM_SCM
- select QCOM_WCNSS_IRIS
- select REMOTEPROC
help
Say y here to support the Peripheral Image Loader for the Qualcomm
Wireless Connectivity Subsystem.
@@ -110,10 +110,16 @@ config QCOM_WCNSS_PIL
config ST_REMOTEPROC
tristate "ST remoteproc support"
depends on ARCH_STI
- select REMOTEPROC
+ depends on REMOTEPROC
help
Say y here to support ST's adjunct processors via the remote
processor framework.
This can be either built-in or a loadable module.
+config ST_SLIM_REMOTEPROC
+ tristate
+ depends on REMOTEPROC
+
+endif # REMOTEPROC
+
endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 6dfb62ed643f..0938ea3c41ba 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,14 +5,17 @@
obj-$(CONFIG_REMOTEPROC) += remoteproc.o
remoteproc-y := remoteproc_core.o
remoteproc-y += remoteproc_debugfs.o
+remoteproc-y += remoteproc_sysfs.o
remoteproc-y += remoteproc_virtio.o
remoteproc-y += remoteproc_elf_loader.o
obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
-obj-$(CONFIG_STE_MODEM_RPROC) += ste_modem_rproc.o
obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o
obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
+obj-$(CONFIG_QCOM_ADSP_PIL) += qcom_adsp_pil.o
obj-$(CONFIG_QCOM_MDT_LOADER) += qcom_mdt_loader.o
obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o
-obj-$(CONFIG_QCOM_WCNSS_IRIS) += qcom_wcnss_iris.o
-obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss.o
+obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o
+qcom_wcnss_pil-y += qcom_wcnss.o
+qcom_wcnss_pil-y += qcom_wcnss_iris.o
obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o
+obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o
diff --git a/drivers/remoteproc/qcom_adsp_pil.c b/drivers/remoteproc/qcom_adsp_pil.c
new file mode 100644
index 000000000000..43a4ed2f346c
--- /dev/null
+++ b/drivers/remoteproc/qcom_adsp_pil.c
@@ -0,0 +1,428 @@
+/*
+ * Qualcomm ADSP Peripheral Image Loader for MSM8974 and MSM8996
+ *
+ * Copyright (C) 2016 Linaro Ltd
+ * Copyright (C) 2014 Sony Mobile Communications AB
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/qcom_scm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/remoteproc.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/smem_state.h>
+
+#include "qcom_mdt_loader.h"
+#include "remoteproc_internal.h"
+
+#define ADSP_CRASH_REASON_SMEM 423
+#define ADSP_FIRMWARE_NAME "adsp.mdt"
+#define ADSP_PAS_ID 1
+
+struct qcom_adsp {
+ struct device *dev;
+ struct rproc *rproc;
+
+ int wdog_irq;
+ int fatal_irq;
+ int ready_irq;
+ int handover_irq;
+ int stop_ack_irq;
+
+ struct qcom_smem_state *state;
+ unsigned stop_bit;
+
+ struct clk *xo;
+
+ struct regulator *cx_supply;
+
+ struct completion start_done;
+ struct completion stop_done;
+
+ phys_addr_t mem_phys;
+ phys_addr_t mem_reloc;
+ void *mem_region;
+ size_t mem_size;
+};
+
+static int adsp_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+ phys_addr_t fw_addr;
+ size_t fw_size;
+ bool relocate;
+ int ret;
+
+ ret = qcom_scm_pas_init_image(ADSP_PAS_ID, fw->data, fw->size);
+ if (ret) {
+ dev_err(&rproc->dev, "invalid firmware metadata\n");
+ return ret;
+ }
+
+ ret = qcom_mdt_parse(fw, &fw_addr, &fw_size, &relocate);
+ if (ret) {
+ dev_err(&rproc->dev, "failed to parse mdt header\n");
+ return ret;
+ }
+
+ if (relocate) {
+ adsp->mem_reloc = fw_addr;
+
+ ret = qcom_scm_pas_mem_setup(ADSP_PAS_ID, adsp->mem_phys, fw_size);
+ if (ret) {
+ dev_err(&rproc->dev, "unable to setup memory for image\n");
+ return ret;
+ }
+ }
+
+ return qcom_mdt_load(rproc, fw, rproc->firmware);
+}
+
+static const struct rproc_fw_ops adsp_fw_ops = {
+ .find_rsc_table = qcom_mdt_find_rsc_table,
+ .load = adsp_load,
+};
+
+static int adsp_start(struct rproc *rproc)
+{
+ struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+ int ret;
+
+ ret = clk_prepare_enable(adsp->xo);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(adsp->cx_supply);
+ if (ret)
+ goto disable_clocks;
+
+ ret = qcom_scm_pas_auth_and_reset(ADSP_PAS_ID);
+ if (ret) {
+ dev_err(adsp->dev,
+ "failed to authenticate image and release reset\n");
+ goto disable_regulators;
+ }
+
+ ret = wait_for_completion_timeout(&adsp->start_done,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(adsp->dev, "start timed out\n");
+ qcom_scm_pas_shutdown(ADSP_PAS_ID);
+ ret = -ETIMEDOUT;
+ goto disable_regulators;
+ }
+
+ ret = 0;
+
+disable_regulators:
+ regulator_disable(adsp->cx_supply);
+disable_clocks:
+ clk_disable_unprepare(adsp->xo);
+
+ return ret;
+}
+
+static int adsp_stop(struct rproc *rproc)
+{
+ struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+ int ret;
+
+ qcom_smem_state_update_bits(adsp->state,
+ BIT(adsp->stop_bit),
+ BIT(adsp->stop_bit));
+
+ ret = wait_for_completion_timeout(&adsp->stop_done,
+ msecs_to_jiffies(5000));
+ if (ret == 0)
+ dev_err(adsp->dev, "timed out on wait\n");
+
+ qcom_smem_state_update_bits(adsp->state,
+ BIT(adsp->stop_bit),
+ 0);
+
+ ret = qcom_scm_pas_shutdown(ADSP_PAS_ID);
+ if (ret)
+ dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
+
+ return ret;
+}
+
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+{
+ struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+ int offset;
+
+ offset = da - adsp->mem_reloc;
+ if (offset < 0 || offset + len > adsp->mem_size)
+ return NULL;
+
+ return adsp->mem_region + offset;
+}
+
+static const struct rproc_ops adsp_ops = {
+ .start = adsp_start,
+ .stop = adsp_stop,
+ .da_to_va = adsp_da_to_va,
+};
+
+static irqreturn_t adsp_wdog_interrupt(int irq, void *dev)
+{
+ struct qcom_adsp *adsp = dev;
+
+ rproc_report_crash(adsp->rproc, RPROC_WATCHDOG);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t adsp_fatal_interrupt(int irq, void *dev)
+{
+ struct qcom_adsp *adsp = dev;
+ size_t len;
+ char *msg;
+
+ msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, ADSP_CRASH_REASON_SMEM, &len);
+ if (!IS_ERR(msg) && len > 0 && msg[0])
+ dev_err(adsp->dev, "fatal error received: %s\n", msg);
+
+ rproc_report_crash(adsp->rproc, RPROC_FATAL_ERROR);
+
+ if (!IS_ERR(msg))
+ msg[0] = '\0';
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t adsp_ready_interrupt(int irq, void *dev)
+{
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t adsp_handover_interrupt(int irq, void *dev)
+{
+ struct qcom_adsp *adsp = dev;
+
+ complete(&adsp->start_done);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t adsp_stop_ack_interrupt(int irq, void *dev)
+{
+ struct qcom_adsp *adsp = dev;
+
+ complete(&adsp->stop_done);
+
+ return IRQ_HANDLED;
+}
+
+static int adsp_init_clock(struct qcom_adsp *adsp)
+{
+ int ret;
+
+ adsp->xo = devm_clk_get(adsp->dev, "xo");
+ if (IS_ERR(adsp->xo)) {
+ ret = PTR_ERR(adsp->xo);
+ if (ret != -EPROBE_DEFER)
+ dev_err(adsp->dev, "failed to get xo clock");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int adsp_init_regulator(struct qcom_adsp *adsp)
+{
+ adsp->cx_supply = devm_regulator_get(adsp->dev, "cx");
+ if (IS_ERR(adsp->cx_supply))
+ return PTR_ERR(adsp->cx_supply);
+
+ regulator_set_load(adsp->cx_supply, 100000);
+
+ return 0;
+}
+
+static int adsp_request_irq(struct qcom_adsp *adsp,
+ struct platform_device *pdev,
+ const char *name,
+ irq_handler_t thread_fn)
+{
+ int ret;
+
+ ret = platform_get_irq_byname(pdev, name);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "no %s IRQ defined\n", name);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, ret,
+ NULL, thread_fn,
+ IRQF_ONESHOT,
+ "adsp", adsp);
+ if (ret)
+ dev_err(&pdev->dev, "request %s IRQ failed\n", name);
+
+ return ret;
+}
+
+static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
+{
+ struct device_node *node;
+ struct resource r;
+ int ret;
+
+ node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
+ if (!node) {
+ dev_err(adsp->dev, "no memory-region specified\n");
+ return -EINVAL;
+ }
+
+ ret = of_address_to_resource(node, 0, &r);
+ if (ret)
+ return ret;
+
+ adsp->mem_phys = adsp->mem_reloc = r.start;
+ adsp->mem_size = resource_size(&r);
+ adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
+ if (!adsp->mem_region) {
+ dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
+ &r.start, adsp->mem_size);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int adsp_probe(struct platform_device *pdev)
+{
+ struct qcom_adsp *adsp;
+ struct rproc *rproc;
+ int ret;
+
+ if (!qcom_scm_is_available())
+ return -EPROBE_DEFER;
+
+ if (!qcom_scm_pas_supported(ADSP_PAS_ID)) {
+ dev_err(&pdev->dev, "PAS is not available for ADSP\n");
+ return -ENXIO;
+ }
+
+ rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
+ ADSP_FIRMWARE_NAME, sizeof(*adsp));
+ if (!rproc) {
+ dev_err(&pdev->dev, "unable to allocate remoteproc\n");
+ return -ENOMEM;
+ }
+
+ rproc->fw_ops = &adsp_fw_ops;
+
+ adsp = (struct qcom_adsp *)rproc->priv;
+ adsp->dev = &pdev->dev;
+ adsp->rproc = rproc;
+ platform_set_drvdata(pdev, adsp);
+
+ init_completion(&adsp->start_done);
+ init_completion(&adsp->stop_done);
+
+ ret = adsp_alloc_memory_region(adsp);
+ if (ret)
+ goto free_rproc;
+
+ ret = adsp_init_clock(adsp);
+ if (ret)
+ goto free_rproc;
+
+ ret = adsp_init_regulator(adsp);
+ if (ret)
+ goto free_rproc;
+
+ ret = adsp_request_irq(adsp, pdev, "wdog", adsp_wdog_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+ adsp->wdog_irq = ret;
+
+ ret = adsp_request_irq(adsp, pdev, "fatal", adsp_fatal_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+ adsp->fatal_irq = ret;
+
+ ret = adsp_request_irq(adsp, pdev, "ready", adsp_ready_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+ adsp->ready_irq = ret;
+
+ ret = adsp_request_irq(adsp, pdev, "handover", adsp_handover_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+ adsp->handover_irq = ret;
+
+ ret = adsp_request_irq(adsp, pdev, "stop-ack", adsp_stop_ack_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+ adsp->stop_ack_irq = ret;
+
+ adsp->state = qcom_smem_state_get(&pdev->dev, "stop",
+ &adsp->stop_bit);
+ if (IS_ERR(adsp->state)) {
+ ret = PTR_ERR(adsp->state);
+ goto free_rproc;
+ }
+
+ ret = rproc_add(rproc);
+ if (ret)
+ goto free_rproc;
+
+ return 0;
+
+free_rproc:
+ rproc_free(rproc);
+
+ return ret;
+}
+
+static int adsp_remove(struct platform_device *pdev)
+{
+ struct qcom_adsp *adsp = platform_get_drvdata(pdev);
+
+ qcom_smem_state_put(adsp->state);
+ rproc_del(adsp->rproc);
+ rproc_free(adsp->rproc);
+
+ return 0;
+}
+
+static const struct of_device_id adsp_of_match[] = {
+ { .compatible = "qcom,msm8974-adsp-pil" },
+ { .compatible = "qcom,msm8996-adsp-pil" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adsp_of_match);
+
+static struct platform_driver adsp_driver = {
+ .probe = adsp_probe,
+ .remove = adsp_remove,
+ .driver = {
+ .name = "qcom_adsp_pil",
+ .of_match_table = adsp_of_match,
+ },
+};
+
+module_platform_driver(adsp_driver);
+MODULE_DESCRIPTION("Qualcomm MSM8974/MSM8996 ADSP Peripherial Image Loader");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_mdt_loader.c b/drivers/remoteproc/qcom_mdt_loader.c
index 114e8e4cef67..2ff18cd6c096 100644
--- a/drivers/remoteproc/qcom_mdt_loader.c
+++ b/drivers/remoteproc/qcom_mdt_loader.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/remoteproc.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include "remoteproc_internal.h"
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index 2e0caaaa766a..b08989b48df7 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -894,6 +894,7 @@ static const struct of_device_id q6v5_of_match[] = {
{ .compatible = "qcom,q6v5-pil", },
{ },
};
+MODULE_DEVICE_TABLE(of, q6v5_of_match);
static struct platform_driver q6v5_driver = {
.probe = q6v5_probe,
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index f5cedeaafba1..ebd61f5d18bb 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -30,6 +30,7 @@
#include <linux/remoteproc.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
+#include <linux/rpmsg/qcom_smd.h>
#include "qcom_mdt_loader.h"
#include "remoteproc_internal.h"
@@ -94,6 +95,10 @@ struct qcom_wcnss {
phys_addr_t mem_reloc;
void *mem_region;
size_t mem_size;
+
+ struct device_node *smd_node;
+ struct qcom_smd_edge *smd_edge;
+ struct rproc_subdev smd_subdev;
};
static const struct wcnss_data riva_data = {
@@ -143,7 +148,6 @@ void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss,
mutex_unlock(&wcnss->iris_lock);
}
-EXPORT_SYMBOL_GPL(qcom_wcnss_assign_iris);
static int wcnss_load(struct rproc *rproc, const struct firmware *fw)
{
@@ -396,6 +400,23 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev)
return IRQ_HANDLED;
}
+static int wcnss_smd_probe(struct rproc_subdev *subdev)
+{
+ struct qcom_wcnss *wcnss = container_of(subdev, struct qcom_wcnss, smd_subdev);
+
+ wcnss->smd_edge = qcom_smd_register_edge(wcnss->dev, wcnss->smd_node);
+
+ return IS_ERR(wcnss->smd_edge) ? PTR_ERR(wcnss->smd_edge) : 0;
+}
+
+static void wcnss_smd_remove(struct rproc_subdev *subdev)
+{
+ struct qcom_wcnss *wcnss = container_of(subdev, struct qcom_wcnss, smd_subdev);
+
+ qcom_smd_unregister_edge(wcnss->smd_edge);
+ wcnss->smd_edge = NULL;
+}
+
static int wcnss_init_regulators(struct qcom_wcnss *wcnss,
const struct wcnss_vreg_info *info,
int num_vregs)
@@ -578,6 +599,10 @@ static int wcnss_probe(struct platform_device *pdev)
}
}
+ wcnss->smd_node = of_get_child_by_name(pdev->dev.of_node, "smd-edge");
+ if (wcnss->smd_node)
+ rproc_add_subdev(rproc, &wcnss->smd_subdev, wcnss_smd_probe, wcnss_smd_remove);
+
ret = rproc_add(rproc);
if (ret)
goto free_rproc;
@@ -596,6 +621,7 @@ static int wcnss_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev);
+ of_node_put(wcnss->smd_node);
qcom_smem_state_put(wcnss->state);
rproc_del(wcnss->rproc);
rproc_free(wcnss->rproc);
@@ -609,6 +635,7 @@ static const struct of_device_id wcnss_of_match[] = {
{ .compatible = "qcom,pronto-v2-pil", &pronto_v2_data },
{ },
};
+MODULE_DEVICE_TABLE(of, wcnss_of_match);
static struct platform_driver wcnss_driver = {
.probe = wcnss_probe,
@@ -619,6 +646,28 @@ static struct platform_driver wcnss_driver = {
},
};
-module_platform_driver(wcnss_driver);
+static int __init wcnss_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&wcnss_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&qcom_iris_driver);
+ if (ret)
+ platform_driver_unregister(&wcnss_driver);
+
+ return ret;
+}
+module_init(wcnss_init);
+
+static void __exit wcnss_exit(void)
+{
+ platform_driver_unregister(&qcom_iris_driver);
+ platform_driver_unregister(&wcnss_driver);
+}
+module_exit(wcnss_exit);
+
MODULE_DESCRIPTION("Qualcomm Peripherial Image Loader for Wireless Subsystem");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_wcnss.h b/drivers/remoteproc/qcom_wcnss.h
index 9dc4a9fe41e1..25fb7f62a457 100644
--- a/drivers/remoteproc/qcom_wcnss.h
+++ b/drivers/remoteproc/qcom_wcnss.h
@@ -4,6 +4,8 @@
struct qcom_iris;
struct qcom_wcnss;
+extern struct platform_driver qcom_iris_driver;
+
struct wcnss_vreg_info {
const char * const name;
int min_voltage;
diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c
index f0ca24a8dd0b..e842be58e8c7 100644
--- a/drivers/remoteproc/qcom_wcnss_iris.c
+++ b/drivers/remoteproc/qcom_wcnss_iris.c
@@ -94,14 +94,12 @@ disable_regulators:
return ret;
}
-EXPORT_SYMBOL_GPL(qcom_iris_enable);
void qcom_iris_disable(struct qcom_iris *iris)
{
clk_disable_unprepare(iris->xo_clk);
regulator_bulk_disable(iris->num_vregs, iris->vregs);
}
-EXPORT_SYMBOL_GPL(qcom_iris_disable);
static int qcom_iris_probe(struct platform_device *pdev)
{
@@ -173,8 +171,9 @@ static const struct of_device_id iris_of_match[] = {
{ .compatible = "qcom,wcn3680", .data = &wcn3680_data },
{}
};
+MODULE_DEVICE_TABLE(of, iris_of_match);
-static struct platform_driver wcnss_driver = {
+struct platform_driver qcom_iris_driver = {
.probe = qcom_iris_probe,
.remove = qcom_iris_remove,
.driver = {
@@ -182,7 +181,3 @@ static struct platform_driver wcnss_driver = {
.of_match_table = iris_of_match,
},
};
-
-module_platform_driver(wcnss_driver);
-MODULE_DESCRIPTION("Qualcomm Wireless Subsystem Iris driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index c6bfb3496684..9a507e77eced 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -236,6 +236,10 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
}
notifyid = ret;
+ /* Potentially bump max_notifyid */
+ if (notifyid > rproc->max_notifyid)
+ rproc->max_notifyid = notifyid;
+
dev_dbg(dev, "vring%d: va %p dma %pad size 0x%x idr %d\n",
i, va, &dma, size, notifyid);
@@ -296,6 +300,20 @@ void rproc_free_vring(struct rproc_vring *rvring)
rsc->vring[idx].notifyid = -1;
}
+static int rproc_vdev_do_probe(struct rproc_subdev *subdev)
+{
+ struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
+
+ return rproc_add_virtio_dev(rvdev, rvdev->id);
+}
+
+static void rproc_vdev_do_remove(struct rproc_subdev *subdev)
+{
+ struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
+
+ rproc_remove_virtio_dev(rvdev);
+}
+
/**
* rproc_handle_vdev() - handle a vdev fw resource
* @rproc: the remote processor
@@ -356,6 +374,9 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
if (!rvdev)
return -ENOMEM;
+ kref_init(&rvdev->refcount);
+
+ rvdev->id = rsc->id;
rvdev->rproc = rproc;
/* parse the vrings */
@@ -368,22 +389,51 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
/* remember the resource offset*/
rvdev->rsc_offset = offset;
+ /* allocate the vring resources */
+ for (i = 0; i < rsc->num_of_vrings; i++) {
+ ret = rproc_alloc_vring(rvdev, i);
+ if (ret)
+ goto unwind_vring_allocations;
+ }
+
+ /* track the rvdevs list reference */
+ kref_get(&rvdev->refcount);
+
list_add_tail(&rvdev->node, &rproc->rvdevs);
- /* it is now safe to add the virtio device */
- ret = rproc_add_virtio_dev(rvdev, rsc->id);
- if (ret)
- goto remove_rvdev;
+ rproc_add_subdev(rproc, &rvdev->subdev,
+ rproc_vdev_do_probe, rproc_vdev_do_remove);
return 0;
-remove_rvdev:
- list_del(&rvdev->node);
+unwind_vring_allocations:
+ for (i--; i >= 0; i--)
+ rproc_free_vring(&rvdev->vring[i]);
free_rvdev:
kfree(rvdev);
return ret;
}
+void rproc_vdev_release(struct kref *ref)
+{
+ struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
+ struct rproc_vring *rvring;
+ struct rproc *rproc = rvdev->rproc;
+ int id;
+
+ for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
+ rvring = &rvdev->vring[id];
+ if (!rvring->va)
+ continue;
+
+ rproc_free_vring(rvring);
+ }
+
+ rproc_remove_subdev(rproc, &rvdev->subdev);
+ list_del(&rvdev->node);
+ kfree(rvdev);
+}
+
/**
* rproc_handle_trace() - handle a shared trace buffer resource
* @rproc: the remote processor
@@ -673,15 +723,6 @@ free_carv:
return ret;
}
-static int rproc_count_vrings(struct rproc *rproc, struct fw_rsc_vdev *rsc,
- int offset, int avail)
-{
- /* Summarize the number of notification IDs */
- rproc->max_notifyid += rsc->num_of_vrings;
-
- return 0;
-}
-
/*
* A lookup table for resource handlers. The indices are defined in
* enum fw_resource_type.
@@ -690,10 +731,6 @@ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
[RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
[RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
[RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
- [RSC_VDEV] = (rproc_handle_resource_t)rproc_count_vrings,
-};
-
-static rproc_handle_resource_t rproc_vdev_handler[RSC_LAST] = {
[RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev,
};
@@ -736,6 +773,34 @@ static int rproc_handle_resources(struct rproc *rproc, int len,
return ret;
}
+static int rproc_probe_subdevices(struct rproc *rproc)
+{
+ struct rproc_subdev *subdev;
+ int ret;
+
+ list_for_each_entry(subdev, &rproc->subdevs, node) {
+ ret = subdev->probe(subdev);
+ if (ret)
+ goto unroll_registration;
+ }
+
+ return 0;
+
+unroll_registration:
+ list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node)
+ subdev->remove(subdev);
+
+ return ret;
+}
+
+static void rproc_remove_subdevices(struct rproc *rproc)
+{
+ struct rproc_subdev *subdev;
+
+ list_for_each_entry(subdev, &rproc->subdevs, node)
+ subdev->remove(subdev);
+}
+
/**
* rproc_resource_cleanup() - clean up and free all acquired resources
* @rproc: rproc handle
@@ -782,7 +847,7 @@ static void rproc_resource_cleanup(struct rproc *rproc)
/* clean up remote vdev entries */
list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
- rproc_remove_virtio_dev(rvdev);
+ kref_put(&rvdev->refcount, rproc_vdev_release);
}
/*
@@ -824,25 +889,16 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
/*
* Create a copy of the resource table. When a virtio device starts
* and calls vring_new_virtqueue() the address of the allocated vring
- * will be stored in the cached_table. Before the device is started,
- * cached_table will be copied into device memory.
+ * will be stored in the table_ptr. Before the device is started,
+ * table_ptr will be copied into device memory.
*/
- rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL);
- if (!rproc->cached_table)
+ rproc->table_ptr = kmemdup(table, tablesz, GFP_KERNEL);
+ if (!rproc->table_ptr)
goto clean_up;
- rproc->table_ptr = rproc->cached_table;
-
/* reset max_notifyid */
rproc->max_notifyid = -1;
- /* look for virtio devices and register them */
- ret = rproc_handle_resources(rproc, tablesz, rproc_vdev_handler);
- if (ret) {
- dev_err(dev, "Failed to handle vdev resources: %d\n", ret);
- goto clean_up;
- }
-
/* handle fw resources which are required to boot rproc */
ret = rproc_handle_resources(rproc, tablesz, rproc_loading_handlers);
if (ret) {
@@ -858,18 +914,16 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
}
/*
- * The starting device has been given the rproc->cached_table as the
+ * The starting device has been given the rproc->table_ptr as the
* resource table. The address of the vring along with the other
- * allocated resources (carveouts etc) is stored in cached_table.
+ * allocated resources (carveouts etc) is stored in table_ptr.
* In order to pass this information to the remote device we must copy
* this information to device memory. We also update the table_ptr so
* that any subsequent changes will be applied to the loaded version.
*/
loaded_table = rproc_find_loaded_rsc_table(rproc, fw);
- if (loaded_table) {
- memcpy(loaded_table, rproc->cached_table, tablesz);
- rproc->table_ptr = loaded_table;
- }
+ if (loaded_table)
+ memcpy(loaded_table, rproc->table_ptr, tablesz);
/* power up the remote processor */
ret = rproc->ops->start(rproc);
@@ -878,17 +932,26 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
goto clean_up_resources;
}
+ /* probe any subdevices for the remote processor */
+ ret = rproc_probe_subdevices(rproc);
+ if (ret) {
+ dev_err(dev, "failed to probe subdevices for %s: %d\n",
+ rproc->name, ret);
+ goto stop_rproc;
+ }
+
rproc->state = RPROC_RUNNING;
dev_info(dev, "remote processor %s is now up\n", rproc->name);
return 0;
+stop_rproc:
+ rproc->ops->stop(rproc);
clean_up_resources:
rproc_resource_cleanup(rproc);
clean_up:
- kfree(rproc->cached_table);
- rproc->cached_table = NULL;
+ kfree(rproc->table_ptr);
rproc->table_ptr = NULL;
rproc_disable_iommu(rproc);
@@ -909,7 +972,7 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
/* if rproc is marked always-on, request it to boot */
if (rproc->auto_boot)
- rproc_boot_nowait(rproc);
+ rproc_boot(rproc);
release_firmware(fw);
/* allow rproc_del() contexts, if any, to proceed */
@@ -1007,7 +1070,6 @@ static void rproc_crash_handler_work(struct work_struct *work)
/**
* __rproc_boot() - boot a remote processor
* @rproc: handle of a remote processor
- * @wait: wait for rproc registration completion
*
* Boot a remote processor (i.e. load its firmware, power it on, ...).
*
@@ -1016,7 +1078,7 @@ static void rproc_crash_handler_work(struct work_struct *work)
*
* Returns 0 on success, and an appropriate error value otherwise.
*/
-static int __rproc_boot(struct rproc *rproc, bool wait)
+static int __rproc_boot(struct rproc *rproc)
{
const struct firmware *firmware_p;
struct device *dev;
@@ -1050,10 +1112,6 @@ static int __rproc_boot(struct rproc *rproc, bool wait)
goto downref_rproc;
}
- /* if rproc virtio is not yet configured, wait */
- if (wait)
- wait_for_completion(&rproc->firmware_loading_complete);
-
ret = rproc_fw_boot(rproc, firmware_p);
release_firmware(firmware_p);
@@ -1072,22 +1130,11 @@ unlock_mutex:
*/
int rproc_boot(struct rproc *rproc)
{
- return __rproc_boot(rproc, true);
+ return __rproc_boot(rproc);
}
EXPORT_SYMBOL(rproc_boot);
/**
- * rproc_boot_nowait() - boot a remote processor
- * @rproc: handle of a remote processor
- *
- * Same as rproc_boot() but don't wait for rproc registration completion
- */
-int rproc_boot_nowait(struct rproc *rproc)
-{
- return __rproc_boot(rproc, false);
-}
-
-/**
* rproc_shutdown() - power off the remote processor
* @rproc: the remote processor
*
@@ -1121,6 +1168,9 @@ void rproc_shutdown(struct rproc *rproc)
if (!atomic_dec_and_test(&rproc->power))
goto out;
+ /* remove any subdevices for the remote processor */
+ rproc_remove_subdevices(rproc);
+
/* power off the remote processor */
ret = rproc->ops->stop(rproc);
if (ret) {
@@ -1135,8 +1185,7 @@ void rproc_shutdown(struct rproc *rproc)
rproc_disable_iommu(rproc);
/* Free the copy of the resource table */
- kfree(rproc->cached_table);
- rproc->cached_table = NULL;
+ kfree(rproc->table_ptr);
rproc->table_ptr = NULL;
/* if in crash state, unlock crash handler */
@@ -1233,9 +1282,6 @@ int rproc_add(struct rproc *rproc)
dev_info(dev, "%s is available\n", rproc->name);
- dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n");
- dev_info(dev, "THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.\n");
-
/* create debugfs entries */
rproc_create_debug_dir(rproc);
ret = rproc_add_virtio_devices(rproc);
@@ -1273,6 +1319,7 @@ static void rproc_type_release(struct device *dev)
if (rproc->index >= 0)
ida_simple_remove(&rproc_dev_index, rproc->index);
+ kfree(rproc->firmware);
kfree(rproc);
}
@@ -1310,31 +1357,31 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
{
struct rproc *rproc;
char *p, *template = "rproc-%s-fw";
- int name_len = 0;
+ int name_len;
if (!dev || !name || !ops)
return NULL;
- if (!firmware)
+ if (!firmware) {
/*
- * Make room for default firmware name (minus %s plus '\0').
* If the caller didn't pass in a firmware name then
- * construct a default name. We're already glomming 'len'
- * bytes onto the end of the struct rproc allocation, so do
- * a few more for the default firmware name (but only if
- * the caller doesn't pass one).
+ * construct a default name.
*/
name_len = strlen(name) + strlen(template) - 2 + 1;
-
- rproc = kzalloc(sizeof(*rproc) + len + name_len, GFP_KERNEL);
- if (!rproc)
- return NULL;
-
- if (!firmware) {
- p = (char *)rproc + sizeof(struct rproc) + len;
+ p = kmalloc(name_len, GFP_KERNEL);
+ if (!p)
+ return NULL;
snprintf(p, name_len, template, name);
} else {
- p = (char *)firmware;
+ p = kstrdup(firmware, GFP_KERNEL);
+ if (!p)
+ return NULL;
+ }
+
+ rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL);
+ if (!rproc) {
+ kfree(p);
+ return NULL;
}
rproc->firmware = p;
@@ -1346,6 +1393,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
device_initialize(&rproc->dev);
rproc->dev.parent = dev;
rproc->dev.type = &rproc_type;
+ rproc->dev.class = &rproc_class;
/* Assign a unique device index and name */
rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL);
@@ -1370,6 +1418,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
INIT_LIST_HEAD(&rproc->mappings);
INIT_LIST_HEAD(&rproc->traces);
INIT_LIST_HEAD(&rproc->rvdevs);
+ INIT_LIST_HEAD(&rproc->subdevs);
INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work);
init_completion(&rproc->crash_comp);
@@ -1428,8 +1477,6 @@ EXPORT_SYMBOL(rproc_put);
*/
int rproc_del(struct rproc *rproc)
{
- struct rproc_vdev *rvdev, *tmp;
-
if (!rproc)
return -EINVAL;
@@ -1441,10 +1488,6 @@ int rproc_del(struct rproc *rproc)
if (rproc->auto_boot)
rproc_shutdown(rproc);
- /* clean up remote vdev entries */
- list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node)
- rproc_remove_virtio_dev(rvdev);
-
/* the rproc is downref'ed as soon as it's removed from the klist */
mutex_lock(&rproc_list_mutex);
list_del(&rproc->node);
@@ -1457,6 +1500,36 @@ int rproc_del(struct rproc *rproc)
EXPORT_SYMBOL(rproc_del);
/**
+ * rproc_add_subdev() - add a subdevice to a remoteproc
+ * @rproc: rproc handle to add the subdevice to
+ * @subdev: subdev handle to register
+ * @probe: function to call when the rproc boots
+ * @remove: function to call when the rproc shuts down
+ */
+void rproc_add_subdev(struct rproc *rproc,
+ struct rproc_subdev *subdev,
+ int (*probe)(struct rproc_subdev *subdev),
+ void (*remove)(struct rproc_subdev *subdev))
+{
+ subdev->probe = probe;
+ subdev->remove = remove;
+
+ list_add_tail(&subdev->node, &rproc->subdevs);
+}
+EXPORT_SYMBOL(rproc_add_subdev);
+
+/**
+ * rproc_remove_subdev() - remove a subdevice from a remoteproc
+ * @rproc: rproc handle to remove the subdevice from
+ * @subdev: subdev handle, previously registered with rproc_add_subdev()
+ */
+void rproc_remove_subdev(struct rproc *rproc, struct rproc_subdev *subdev)
+{
+ list_del(&subdev->node);
+}
+EXPORT_SYMBOL(rproc_remove_subdev);
+
+/**
* rproc_report_crash() - rproc crash reporter function
* @rproc: remote processor
* @type: crash type
@@ -1484,6 +1557,7 @@ EXPORT_SYMBOL(rproc_report_crash);
static int __init remoteproc_init(void)
{
+ rproc_init_sysfs();
rproc_init_debugfs();
return 0;
@@ -1495,6 +1569,7 @@ static void __exit remoteproc_exit(void)
ida_destroy(&rproc_dev_index);
rproc_exit_debugfs();
+ rproc_exit_sysfs();
}
module_exit(remoteproc_exit);
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
index 374797206c79..1c122e230cec 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -59,75 +59,6 @@ static const struct file_operations trace_rproc_ops = {
.llseek = generic_file_llseek,
};
-/*
- * A state-to-string lookup table, for exposing a human readable state
- * via debugfs. Always keep in sync with enum rproc_state
- */
-static const char * const rproc_state_string[] = {
- "offline",
- "suspended",
- "running",
- "crashed",
- "invalid",
-};
-
-/* expose the state of the remote processor via debugfs */
-static ssize_t rproc_state_read(struct file *filp, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct rproc *rproc = filp->private_data;
- unsigned int state;
- char buf[30];
- int i;
-
- state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
-
- i = scnprintf(buf, 30, "%.28s (%d)\n", rproc_state_string[state],
- rproc->state);
-
- return simple_read_from_buffer(userbuf, count, ppos, buf, i);
-}
-
-static ssize_t rproc_state_write(struct file *filp, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct rproc *rproc = filp->private_data;
- char buf[10];
- int ret;
-
- if (count > sizeof(buf) || count <= 0)
- return -EINVAL;
-
- ret = copy_from_user(buf, userbuf, count);
- if (ret)
- return -EFAULT;
-
- if (buf[count - 1] == '\n')
- buf[count - 1] = '\0';
-
- if (!strncmp(buf, "start", count)) {
- ret = rproc_boot(rproc);
- if (ret) {
- dev_err(&rproc->dev, "Boot failed: %d\n", ret);
- return ret;
- }
- } else if (!strncmp(buf, "stop", count)) {
- rproc_shutdown(rproc);
- } else {
- dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
- return -EINVAL;
- }
-
- return count;
-}
-
-static const struct file_operations rproc_state_ops = {
- .read = rproc_state_read,
- .write = rproc_state_write,
- .open = simple_open,
- .llseek = generic_file_llseek,
-};
-
/* expose the name of the remote processor via debugfs */
static ssize_t rproc_name_read(struct file *filp, char __user *userbuf,
size_t count, loff_t *ppos)
@@ -265,8 +196,6 @@ void rproc_create_debug_dir(struct rproc *rproc)
debugfs_create_file("name", 0400, rproc->dbg_dir,
rproc, &rproc_name_ops);
- debugfs_create_file("state", 0400, rproc->dbg_dir,
- rproc, &rproc_state_ops);
debugfs_create_file("recovery", 0400, rproc->dbg_dir,
rproc, &rproc_recovery_ops);
}
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 4cf93ca2816e..1e9e5b3f021c 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -49,6 +49,7 @@ struct rproc_fw_ops {
void rproc_release(struct kref *kref);
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
int rproc_boot_nowait(struct rproc *rproc);
+void rproc_vdev_release(struct kref *ref);
/* from remoteproc_virtio.c */
int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
@@ -63,6 +64,11 @@ void rproc_create_debug_dir(struct rproc *rproc);
void rproc_init_debugfs(void);
void rproc_exit_debugfs(void);
+/* from remoteproc_sysfs.c */
+extern struct class rproc_class;
+int rproc_init_sysfs(void);
+void rproc_exit_sysfs(void);
+
void rproc_free_vring(struct rproc_vring *rvring);
int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
diff --git a/drivers/remoteproc/remoteproc_sysfs.c b/drivers/remoteproc/remoteproc_sysfs.c
new file mode 100644
index 000000000000..bc5b0e00efb1
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -0,0 +1,151 @@
+/*
+ * Remote Processor Framework
+ *
+ * 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/remoteproc.h>
+
+#include "remoteproc_internal.h"
+
+#define to_rproc(d) container_of(d, struct rproc, dev)
+
+/* Expose the loaded / running firmware name via sysfs */
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct rproc *rproc = to_rproc(dev);
+
+ return sprintf(buf, "%s\n", rproc->firmware);
+}
+
+/* Change firmware name via sysfs */
+static ssize_t firmware_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rproc *rproc = to_rproc(dev);
+ char *p;
+ int err, len = count;
+
+ err = mutex_lock_interruptible(&rproc->lock);
+ if (err) {
+ dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, err);
+ return -EINVAL;
+ }
+
+ if (rproc->state != RPROC_OFFLINE) {
+ dev_err(dev, "can't change firmware while running\n");
+ err = -EBUSY;
+ goto out;
+ }
+
+ len = strcspn(buf, "\n");
+
+ p = kstrndup(buf, len, GFP_KERNEL);
+ if (!p) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ kfree(rproc->firmware);
+ rproc->firmware = p;
+out:
+ mutex_unlock(&rproc->lock);
+
+ return err ? err : count;
+}
+static DEVICE_ATTR_RW(firmware);
+
+/*
+ * A state-to-string lookup table, for exposing a human readable state
+ * via sysfs. Always keep in sync with enum rproc_state
+ */
+static const char * const rproc_state_string[] = {
+ [RPROC_OFFLINE] = "offline",
+ [RPROC_SUSPENDED] = "suspended",
+ [RPROC_RUNNING] = "running",
+ [RPROC_CRASHED] = "crashed",
+ [RPROC_LAST] = "invalid",
+};
+
+/* Expose the state of the remote processor via sysfs */
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct rproc *rproc = to_rproc(dev);
+ unsigned int state;
+
+ state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
+ return sprintf(buf, "%s\n", rproc_state_string[state]);
+}
+
+/* Change remote processor state via sysfs */
+static ssize_t state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rproc *rproc = to_rproc(dev);
+ int ret = 0;
+
+ if (sysfs_streq(buf, "start")) {
+ if (rproc->state == RPROC_RUNNING)
+ return -EBUSY;
+
+ ret = rproc_boot(rproc);
+ if (ret)
+ dev_err(&rproc->dev, "Boot failed: %d\n", ret);
+ } else if (sysfs_streq(buf, "stop")) {
+ if (rproc->state != RPROC_RUNNING)
+ return -EINVAL;
+
+ rproc_shutdown(rproc);
+ } else {
+ dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
+ ret = -EINVAL;
+ }
+ return ret ? ret : count;
+}
+static DEVICE_ATTR_RW(state);
+
+static struct attribute *rproc_attrs[] = {
+ &dev_attr_firmware.attr,
+ &dev_attr_state.attr,
+ NULL
+};
+
+static const struct attribute_group rproc_devgroup = {
+ .attrs = rproc_attrs
+};
+
+static const struct attribute_group *rproc_devgroups[] = {
+ &rproc_devgroup,
+ NULL
+};
+
+struct class rproc_class = {
+ .name = "remoteproc",
+ .dev_groups = rproc_devgroups,
+};
+
+int __init rproc_init_sysfs(void)
+{
+ /* create remoteproc device class for sysfs */
+ int err = class_register(&rproc_class);
+
+ if (err)
+ pr_err("remoteproc: unable to register class\n");
+ return err;
+}
+
+void __exit rproc_exit_sysfs(void)
+{
+ class_unregister(&rproc_class);
+}
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 01870a16d6d2..364411fb7734 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -79,7 +79,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
struct rproc_vring *rvring;
struct virtqueue *vq;
void *addr;
- int len, size, ret;
+ int len, size;
/* we're temporarily limited to two virtqueues per rvdev */
if (id >= ARRAY_SIZE(rvdev->vring))
@@ -88,10 +88,6 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
if (!name)
return NULL;
- ret = rproc_alloc_vring(rvdev, id);
- if (ret)
- return ERR_PTR(ret);
-
rvring = &rvdev->vring[id];
addr = rvring->va;
len = rvring->len;
@@ -130,7 +126,6 @@ static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
rvring = vq->priv;
rvring->vq = NULL;
vring_del_virtqueue(vq);
- rproc_free_vring(rvring);
}
}
@@ -282,14 +277,13 @@ static const struct virtio_config_ops rproc_virtio_config_ops = {
* Never call this function directly; it will be called by the driver
* core when needed.
*/
-static void rproc_vdev_release(struct device *dev)
+static void rproc_virtio_dev_release(struct device *dev)
{
struct virtio_device *vdev = dev_to_virtio(dev);
struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
struct rproc *rproc = vdev_to_rproc(vdev);
- list_del(&rvdev->node);
- kfree(rvdev);
+ kref_put(&rvdev->refcount, rproc_vdev_release);
put_device(&rproc->dev);
}
@@ -313,7 +307,7 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
vdev->id.device = id,
vdev->config = &rproc_virtio_config_ops,
vdev->dev.parent = dev;
- vdev->dev.release = rproc_vdev_release;
+ vdev->dev.release = rproc_virtio_dev_release;
/*
* We're indirectly making a non-temporary copy of the rproc pointer
@@ -325,6 +319,9 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
*/
get_device(&rproc->dev);
+ /* Reference the vdev and vring allocations */
+ kref_get(&rvdev->refcount);
+
ret = register_virtio_device(vdev);
if (ret) {
put_device(&rproc->dev);
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index ae8963fcc8c8..da4e152e9733 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -245,8 +245,10 @@ static int st_rproc_probe(struct platform_device *pdev)
goto free_rproc;
enabled = st_rproc_state(pdev);
- if (enabled < 0)
+ if (enabled < 0) {
+ ret = enabled;
goto free_rproc;
+ }
if (enabled) {
atomic_inc(&rproc->power);
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
new file mode 100644
index 000000000000..507716c8721f
--- /dev/null
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -0,0 +1,364 @@
+/*
+ * SLIM core rproc driver
+ *
+ * Copyright (C) 2016 STMicroelectronics
+ *
+ * Author: Peter Griffin <peter.griffin@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/clk.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/remoteproc/st_slim_rproc.h>
+#include "remoteproc_internal.h"
+
+/* SLIM core registers */
+#define SLIM_ID_OFST 0x0
+#define SLIM_VER_OFST 0x4
+
+#define SLIM_EN_OFST 0x8
+#define SLIM_EN_RUN BIT(0)
+
+#define SLIM_CLK_GATE_OFST 0xC
+#define SLIM_CLK_GATE_DIS BIT(0)
+#define SLIM_CLK_GATE_RESET BIT(2)
+
+#define SLIM_SLIM_PC_OFST 0x20
+
+/* DMEM registers */
+#define SLIM_REV_ID_OFST 0x0
+#define SLIM_REV_ID_MIN_MASK GENMASK(15, 8)
+#define SLIM_REV_ID_MIN(id) ((id & SLIM_REV_ID_MIN_MASK) >> 8)
+#define SLIM_REV_ID_MAJ_MASK GENMASK(23, 16)
+#define SLIM_REV_ID_MAJ(id) ((id & SLIM_REV_ID_MAJ_MASK) >> 16)
+
+
+/* peripherals registers */
+#define SLIM_STBUS_SYNC_OFST 0xF88
+#define SLIM_STBUS_SYNC_DIS BIT(0)
+
+#define SLIM_INT_SET_OFST 0xFD4
+#define SLIM_INT_CLR_OFST 0xFD8
+#define SLIM_INT_MASK_OFST 0xFDC
+
+#define SLIM_CMD_CLR_OFST 0xFC8
+#define SLIM_CMD_MASK_OFST 0xFCC
+
+static const char *mem_names[ST_SLIM_MEM_MAX] = {
+ [ST_SLIM_DMEM] = "dmem",
+ [ST_SLIM_IMEM] = "imem",
+};
+
+static int slim_clk_get(struct st_slim_rproc *slim_rproc, struct device *dev)
+{
+ int clk, err;
+
+ for (clk = 0; clk < ST_SLIM_MAX_CLK; clk++) {
+ slim_rproc->clks[clk] = of_clk_get(dev->of_node, clk);
+ if (IS_ERR(slim_rproc->clks[clk])) {
+ err = PTR_ERR(slim_rproc->clks[clk]);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ slim_rproc->clks[clk] = NULL;
+ break;
+ }
+ }
+
+ return 0;
+
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(slim_rproc->clks[clk]);
+
+ return err;
+}
+
+static void slim_clk_disable(struct st_slim_rproc *slim_rproc)
+{
+ int clk;
+
+ for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++)
+ clk_disable_unprepare(slim_rproc->clks[clk]);
+}
+
+static int slim_clk_enable(struct st_slim_rproc *slim_rproc)
+{
+ int clk, ret;
+
+ for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++) {
+ ret = clk_prepare_enable(slim_rproc->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ return 0;
+
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(slim_rproc->clks[clk]);
+
+ return ret;
+}
+
+/*
+ * Remoteproc slim specific device handlers
+ */
+static int slim_rproc_start(struct rproc *rproc)
+{
+ struct device *dev = &rproc->dev;
+ struct st_slim_rproc *slim_rproc = rproc->priv;
+ unsigned long hw_id, hw_ver, fw_rev;
+ u32 val;
+
+ /* disable CPU pipeline clock & reset CPU pipeline */
+ val = SLIM_CLK_GATE_DIS | SLIM_CLK_GATE_RESET;
+ writel(val, slim_rproc->slimcore + SLIM_CLK_GATE_OFST);
+
+ /* disable SLIM core STBus sync */
+ writel(SLIM_STBUS_SYNC_DIS, slim_rproc->peri + SLIM_STBUS_SYNC_OFST);
+
+ /* enable cpu pipeline clock */
+ writel(!SLIM_CLK_GATE_DIS,
+ slim_rproc->slimcore + SLIM_CLK_GATE_OFST);
+
+ /* clear int & cmd mailbox */
+ writel(~0U, slim_rproc->peri + SLIM_INT_CLR_OFST);
+ writel(~0U, slim_rproc->peri + SLIM_CMD_CLR_OFST);
+
+ /* enable all channels cmd & int */
+ writel(~0U, slim_rproc->peri + SLIM_INT_MASK_OFST);
+ writel(~0U, slim_rproc->peri + SLIM_CMD_MASK_OFST);
+
+ /* enable cpu */
+ writel(SLIM_EN_RUN, slim_rproc->slimcore + SLIM_EN_OFST);
+
+ hw_id = readl_relaxed(slim_rproc->slimcore + SLIM_ID_OFST);
+ hw_ver = readl_relaxed(slim_rproc->slimcore + SLIM_VER_OFST);
+
+ fw_rev = readl(slim_rproc->mem[ST_SLIM_DMEM].cpu_addr +
+ SLIM_REV_ID_OFST);
+
+ dev_info(dev, "fw rev:%ld.%ld on SLIM %ld.%ld\n",
+ SLIM_REV_ID_MAJ(fw_rev), SLIM_REV_ID_MIN(fw_rev),
+ hw_id, hw_ver);
+
+ return 0;
+}
+
+static int slim_rproc_stop(struct rproc *rproc)
+{
+ struct st_slim_rproc *slim_rproc = rproc->priv;
+ u32 val;
+
+ /* mask all (cmd & int) channels */
+ writel(0UL, slim_rproc->peri + SLIM_INT_MASK_OFST);
+ writel(0UL, slim_rproc->peri + SLIM_CMD_MASK_OFST);
+
+ /* disable cpu pipeline clock */
+ writel(SLIM_CLK_GATE_DIS, slim_rproc->slimcore + SLIM_CLK_GATE_OFST);
+
+ writel(!SLIM_EN_RUN, slim_rproc->slimcore + SLIM_EN_OFST);
+
+ val = readl(slim_rproc->slimcore + SLIM_EN_OFST);
+ if (val & SLIM_EN_RUN)
+ dev_warn(&rproc->dev, "Failed to disable SLIM");
+
+ dev_dbg(&rproc->dev, "slim stopped\n");
+
+ return 0;
+}
+
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+{
+ struct st_slim_rproc *slim_rproc = rproc->priv;
+ void *va = NULL;
+ int i;
+
+ for (i = 0; i < ST_SLIM_MEM_MAX; i++) {
+ if (da != slim_rproc->mem[i].bus_addr)
+ continue;
+
+ if (len <= slim_rproc->mem[i].size) {
+ /* __force to make sparse happy with type conversion */
+ va = (__force void *)slim_rproc->mem[i].cpu_addr;
+ break;
+ }
+ }
+
+ dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
+
+ return va;
+}
+
+static struct rproc_ops slim_rproc_ops = {
+ .start = slim_rproc_start,
+ .stop = slim_rproc_stop,
+ .da_to_va = slim_rproc_da_to_va,
+};
+
+/*
+ * Firmware handler operations: sanity, boot address, load ...
+ */
+
+static struct resource_table empty_rsc_tbl = {
+ .ver = 1,
+ .num = 0,
+};
+
+static struct resource_table *slim_rproc_find_rsc_table(struct rproc *rproc,
+ const struct firmware *fw,
+ int *tablesz)
+{
+ *tablesz = sizeof(empty_rsc_tbl);
+ return &empty_rsc_tbl;
+}
+
+static struct rproc_fw_ops slim_rproc_fw_ops = {
+ .find_rsc_table = slim_rproc_find_rsc_table,
+};
+
+/**
+ * st_slim_rproc_alloc() - allocate and initialise slim rproc
+ * @pdev: Pointer to the platform_device struct
+ * @fw_name: Name of firmware for rproc to use
+ *
+ * Function for allocating and initialising a slim rproc for use by
+ * device drivers whose IP is based around the SLIM core. It
+ * obtains and enables any clocks required by the SLIM core and also
+ * ioremaps the various IO.
+ *
+ * Returns st_slim_rproc pointer or PTR_ERR() on error.
+ */
+
+struct st_slim_rproc *st_slim_rproc_alloc(struct platform_device *pdev,
+ char *fw_name)
+{
+ struct device *dev = &pdev->dev;
+ struct st_slim_rproc *slim_rproc;
+ struct device_node *np = dev->of_node;
+ struct rproc *rproc;
+ struct resource *res;
+ int err, i;
+ const struct rproc_fw_ops *elf_ops;
+
+ if (!fw_name)
+ return ERR_PTR(-EINVAL);
+
+ if (!of_device_is_compatible(np, "st,slim-rproc"))
+ return ERR_PTR(-EINVAL);
+
+ rproc = rproc_alloc(dev, np->name, &slim_rproc_ops,
+ fw_name, sizeof(*slim_rproc));
+ if (!rproc)
+ return ERR_PTR(-ENOMEM);
+
+ rproc->has_iommu = false;
+
+ slim_rproc = rproc->priv;
+ slim_rproc->rproc = rproc;
+
+ elf_ops = rproc->fw_ops;
+ /* Use some generic elf ops */
+ slim_rproc_fw_ops.load = elf_ops->load;
+ slim_rproc_fw_ops.sanity_check = elf_ops->sanity_check;
+
+ rproc->fw_ops = &slim_rproc_fw_ops;
+
+ /* get imem and dmem */
+ for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ mem_names[i]);
+
+ slim_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(slim_rproc->mem[i].cpu_addr)) {
+ dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+ err = PTR_ERR(slim_rproc->mem[i].cpu_addr);
+ goto err;
+ }
+ slim_rproc->mem[i].bus_addr = res->start;
+ slim_rproc->mem[i].size = resource_size(res);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
+ slim_rproc->slimcore = devm_ioremap_resource(dev, res);
+ if (IS_ERR(slim_rproc->slimcore)) {
+ dev_err(&pdev->dev, "failed to ioremap slimcore IO\n");
+ err = PTR_ERR(slim_rproc->slimcore);
+ goto err;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
+ slim_rproc->peri = devm_ioremap_resource(dev, res);
+ if (IS_ERR(slim_rproc->peri)) {
+ dev_err(&pdev->dev, "failed to ioremap peripherals IO\n");
+ err = PTR_ERR(slim_rproc->peri);
+ goto err;
+ }
+
+ err = slim_clk_get(slim_rproc, dev);
+ if (err)
+ goto err;
+
+ err = slim_clk_enable(slim_rproc);
+ if (err) {
+ dev_err(dev, "Failed to enable clocks\n");
+ goto err_clk_put;
+ }
+
+ /* Register as a remoteproc device */
+ err = rproc_add(rproc);
+ if (err) {
+ dev_err(dev, "registration of slim remoteproc failed\n");
+ goto err_clk_dis;
+ }
+
+ return slim_rproc;
+
+err_clk_dis:
+ slim_clk_disable(slim_rproc);
+err_clk_put:
+ for (i = 0; i < ST_SLIM_MAX_CLK && slim_rproc->clks[i]; i++)
+ clk_put(slim_rproc->clks[i]);
+err:
+ rproc_free(rproc);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(st_slim_rproc_alloc);
+
+/**
+ * st_slim_rproc_put() - put slim rproc resources
+ * @slim_rproc: Pointer to the st_slim_rproc struct
+ *
+ * Function for calling respective _put() functions on slim_rproc resources.
+ *
+ */
+void st_slim_rproc_put(struct st_slim_rproc *slim_rproc)
+{
+ int clk;
+
+ if (!slim_rproc)
+ return;
+
+ slim_clk_disable(slim_rproc);
+
+ for (clk = 0; clk < ST_SLIM_MAX_CLK && slim_rproc->clks[clk]; clk++)
+ clk_put(slim_rproc->clks[clk]);
+
+ rproc_del(slim_rproc->rproc);
+ rproc_free(slim_rproc->rproc);
+}
+EXPORT_SYMBOL(st_slim_rproc_put);
+
+MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
+MODULE_DESCRIPTION("STMicroelectronics SLIM core rproc driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/ste_modem_rproc.c b/drivers/remoteproc/ste_modem_rproc.c
deleted file mode 100644
index 03d69a9a3c5b..000000000000
--- a/drivers/remoteproc/ste_modem_rproc.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2012
- * Author: Sjur Brændeland <sjur.brandeland@stericsson.com>
- * License terms: GNU General Public License (GPL), version 2
- */
-
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/remoteproc.h>
-#include <linux/ste_modem_shm.h>
-#include "remoteproc_internal.h"
-
-#define SPROC_FW_SIZE (50 * 4096)
-#define SPROC_MAX_TOC_ENTRIES 32
-#define SPROC_MAX_NOTIFY_ID 14
-#define SPROC_RESOURCE_NAME "rsc-table"
-#define SPROC_MODEM_NAME "ste-modem"
-#define SPROC_MODEM_FIRMWARE SPROC_MODEM_NAME "-fw.bin"
-
-#define sproc_dbg(sproc, fmt, ...) \
- dev_dbg(&sproc->mdev->pdev.dev, fmt, ##__VA_ARGS__)
-#define sproc_err(sproc, fmt, ...) \
- dev_err(&sproc->mdev->pdev.dev, fmt, ##__VA_ARGS__)
-
-/* STE-modem control structure */
-struct sproc {
- struct rproc *rproc;
- struct ste_modem_device *mdev;
- int error;
- void *fw_addr;
- size_t fw_size;
- dma_addr_t fw_dma_addr;
-};
-
-/* STE-Modem firmware entry */
-struct ste_toc_entry {
- __le32 start;
- __le32 size;
- __le32 flags;
- __le32 entry_point;
- __le32 load_addr;
- char name[12];
-};
-
-/*
- * The Table Of Content is located at the start of the firmware image and
- * at offset zero in the shared memory region. The resource table typically
- * contains the initial boot image (boot strap) and other information elements
- * such as remoteproc resource table. Each entry is identified by a unique
- * name.
- */
-struct ste_toc {
- struct ste_toc_entry table[SPROC_MAX_TOC_ENTRIES];
-};
-
-/* Loads the firmware to shared memory. */
-static int sproc_load_segments(struct rproc *rproc, const struct firmware *fw)
-{
- struct sproc *sproc = rproc->priv;
-
- memcpy(sproc->fw_addr, fw->data, fw->size);
-
- return 0;
-}
-
-/* Find the entry for resource table in the Table of Content */
-static const struct ste_toc_entry *sproc_find_rsc_entry(const void *data)
-{
- int i;
- const struct ste_toc *toc = data;
-
- /* Search the table for the resource table */
- for (i = 0; i < SPROC_MAX_TOC_ENTRIES &&
- toc->table[i].start != 0xffffffff; i++) {
- if (!strncmp(toc->table[i].name, SPROC_RESOURCE_NAME,
- sizeof(toc->table[i].name)))
- return &toc->table[i];
- }
-
- return NULL;
-}
-
-/* Find the resource table inside the remote processor's firmware. */
-static struct resource_table *
-sproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
- int *tablesz)
-{
- struct sproc *sproc = rproc->priv;
- struct resource_table *table;
- const struct ste_toc_entry *entry;
-
- if (!fw)
- return NULL;
-
- entry = sproc_find_rsc_entry(fw->data);
- if (!entry) {
- sproc_err(sproc, "resource table not found in fw\n");
- return NULL;
- }
-
- table = (void *)(fw->data + entry->start);
-
- /* sanity check size and offset of resource table */
- if (entry->start > SPROC_FW_SIZE ||
- entry->size > SPROC_FW_SIZE ||
- fw->size > SPROC_FW_SIZE ||
- entry->start + entry->size > fw->size ||
- sizeof(struct resource_table) > entry->size) {
- sproc_err(sproc, "bad size of fw or resource table\n");
- return NULL;
- }
-
- /* we don't support any version beyond the first */
- if (table->ver != 1) {
- sproc_err(sproc, "unsupported fw ver: %d\n", table->ver);
- return NULL;
- }
-
- /* make sure reserved bytes are zeroes */
- if (table->reserved[0] || table->reserved[1]) {
- sproc_err(sproc, "non zero reserved bytes\n");
- return NULL;
- }
-
- /* make sure the offsets array isn't truncated */
- if (table->num > SPROC_MAX_TOC_ENTRIES ||
- table->num * sizeof(table->offset[0]) +
- sizeof(struct resource_table) > entry->size) {
- sproc_err(sproc, "resource table incomplete\n");
- return NULL;
- }
-
- /* If the fw size has grown, release the previous fw allocation */
- if (SPROC_FW_SIZE < fw->size) {
- sproc_err(sproc, "Insufficient space for fw (%d < %zd)\n",
- SPROC_FW_SIZE, fw->size);
- return NULL;
- }
-
- sproc->fw_size = fw->size;
- *tablesz = entry->size;
-
- return table;
-}
-
-/* Find the resource table inside the remote processor's firmware. */
-static struct resource_table *
-sproc_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw)
-{
- struct sproc *sproc = rproc->priv;
- const struct ste_toc_entry *entry;
-
- if (!fw || !sproc->fw_addr)
- return NULL;
-
- entry = sproc_find_rsc_entry(sproc->fw_addr);
- if (!entry) {
- sproc_err(sproc, "resource table not found in fw\n");
- return NULL;
- }
-
- return sproc->fw_addr + entry->start;
-}
-
-/* STE modem firmware handler operations */
-static const struct rproc_fw_ops sproc_fw_ops = {
- .load = sproc_load_segments,
- .find_rsc_table = sproc_find_rsc_table,
- .find_loaded_rsc_table = sproc_find_loaded_rsc_table,
-};
-
-/* Kick the modem with specified notification id */
-static void sproc_kick(struct rproc *rproc, int vqid)
-{
- struct sproc *sproc = rproc->priv;
-
- sproc_dbg(sproc, "kick vqid:%d\n", vqid);
-
- /*
- * We need different notification IDs for RX and TX so add
- * an offset on TX notification IDs.
- */
- sproc->mdev->ops.kick(sproc->mdev, vqid + SPROC_MAX_NOTIFY_ID);
-}
-
-/* Received a kick from a modem, kick the virtqueue */
-static void sproc_kick_callback(struct ste_modem_device *mdev, int vqid)
-{
- struct sproc *sproc = mdev->drv_data;
-
- if (rproc_vq_interrupt(sproc->rproc, vqid) == IRQ_NONE)
- sproc_dbg(sproc, "no message was found in vqid %d\n", vqid);
-}
-
-static struct ste_modem_dev_cb sproc_dev_cb = {
- .kick = sproc_kick_callback,
-};
-
-/* Start the STE modem */
-static int sproc_start(struct rproc *rproc)
-{
- struct sproc *sproc = rproc->priv;
- int i, err;
-
- sproc_dbg(sproc, "start ste-modem\n");
-
- /* Sanity test the max_notifyid */
- if (rproc->max_notifyid > SPROC_MAX_NOTIFY_ID) {
- sproc_err(sproc, "Notification IDs too high:%d\n",
- rproc->max_notifyid);
- return -EINVAL;
- }
-
- /* Subscribe to notifications */
- for (i = 0; i <= rproc->max_notifyid; i++) {
- err = sproc->mdev->ops.kick_subscribe(sproc->mdev, i);
- if (err) {
- sproc_err(sproc,
- "subscription of kicks failed:%d\n", err);
- return err;
- }
- }
-
- /* Request modem start-up*/
- return sproc->mdev->ops.power(sproc->mdev, true);
-}
-
-/* Stop the STE modem */
-static int sproc_stop(struct rproc *rproc)
-{
- struct sproc *sproc = rproc->priv;
-
- sproc_dbg(sproc, "stop ste-modem\n");
-
- return sproc->mdev->ops.power(sproc->mdev, false);
-}
-
-static struct rproc_ops sproc_ops = {
- .start = sproc_start,
- .stop = sproc_stop,
- .kick = sproc_kick,
-};
-
-/* STE modem device is unregistered */
-static int sproc_drv_remove(struct platform_device *pdev)
-{
- struct ste_modem_device *mdev =
- container_of(pdev, struct ste_modem_device, pdev);
- struct sproc *sproc = mdev->drv_data;
-
- sproc_dbg(sproc, "remove ste-modem\n");
-
- /* Reset device callback functions */
- sproc->mdev->ops.setup(sproc->mdev, NULL);
-
- /* Unregister as remoteproc device */
- rproc_del(sproc->rproc);
- dma_free_coherent(sproc->rproc->dev.parent, SPROC_FW_SIZE,
- sproc->fw_addr, sproc->fw_dma_addr);
- rproc_free(sproc->rproc);
-
- mdev->drv_data = NULL;
-
- return 0;
-}
-
-/* Handle probe of a modem device */
-static int sproc_probe(struct platform_device *pdev)
-{
- struct ste_modem_device *mdev =
- container_of(pdev, struct ste_modem_device, pdev);
- struct sproc *sproc;
- struct rproc *rproc;
- int err;
-
- dev_dbg(&mdev->pdev.dev, "probe ste-modem\n");
-
- if (!mdev->ops.setup || !mdev->ops.kick || !mdev->ops.kick_subscribe ||
- !mdev->ops.power) {
- dev_err(&mdev->pdev.dev, "invalid mdev ops\n");
- return -EINVAL;
- }
-
- rproc = rproc_alloc(&mdev->pdev.dev, mdev->pdev.name, &sproc_ops,
- SPROC_MODEM_FIRMWARE, sizeof(*sproc));
- if (!rproc)
- return -ENOMEM;
-
- sproc = rproc->priv;
- sproc->mdev = mdev;
- sproc->rproc = rproc;
- rproc->has_iommu = false;
- mdev->drv_data = sproc;
-
- /* Provide callback functions to modem device */
- sproc->mdev->ops.setup(sproc->mdev, &sproc_dev_cb);
-
- /* Set the STE-modem specific firmware handler */
- rproc->fw_ops = &sproc_fw_ops;
-
- /*
- * STE-modem requires the firmware to be located
- * at the start of the shared memory region. So we need to
- * reserve space for firmware at the start.
- */
- sproc->fw_addr = dma_alloc_coherent(rproc->dev.parent, SPROC_FW_SIZE,
- &sproc->fw_dma_addr,
- GFP_KERNEL);
- if (!sproc->fw_addr) {
- sproc_err(sproc, "Cannot allocate memory for fw\n");
- err = -ENOMEM;
- goto free_rproc;
- }
-
- /* Register as a remoteproc device */
- err = rproc_add(rproc);
- if (err)
- goto free_mem;
-
- return 0;
-
-free_mem:
- dma_free_coherent(rproc->dev.parent, SPROC_FW_SIZE,
- sproc->fw_addr, sproc->fw_dma_addr);
-free_rproc:
- /* Reset device data upon error */
- mdev->drv_data = NULL;
- rproc_free(rproc);
- return err;
-}
-
-static struct platform_driver sproc_driver = {
- .driver = {
- .name = SPROC_MODEM_NAME,
- },
- .probe = sproc_probe,
- .remove = sproc_drv_remove,
-};
-
-module_platform_driver(sproc_driver);
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("STE Modem driver using the Remote Processor Framework");
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 06fef2b4c814..0fae48116a0d 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -25,6 +25,7 @@
#include <linux/soc/qcom/smem.h>
#include <linux/wait.h>
#include <linux/rpmsg.h>
+#include <linux/rpmsg/qcom_smd.h>
#include "rpmsg_internal.h"
@@ -739,7 +740,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
while (qcom_smd_get_tx_avail(channel) < tlen) {
if (!wait) {
- ret = -ENOMEM;
+ ret = -EAGAIN;
goto out;
}
@@ -820,20 +821,13 @@ qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name)
struct qcom_smd_channel *channel;
struct qcom_smd_channel *ret = NULL;
unsigned long flags;
- unsigned state;
spin_lock_irqsave(&edge->channels_lock, flags);
list_for_each_entry(channel, &edge->channels, list) {
- if (strcmp(channel->name, name))
- continue;
-
- state = GET_RX_CHANNEL_INFO(channel, state);
- if (state != SMD_CHANNEL_OPENING &&
- state != SMD_CHANNEL_OPENED)
- continue;
-
- ret = channel;
- break;
+ if (!strcmp(channel->name, name)) {
+ ret = channel;
+ break;
+ }
}
spin_unlock_irqrestore(&edge->channels_lock, flags);
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index b6ea9ffa7381..a79cb5a9e5f2 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -71,6 +71,9 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
rpmsg_rx_cb_t cb, void *priv,
struct rpmsg_channel_info chinfo)
{
+ if (WARN_ON(!rpdev))
+ return ERR_PTR(-EINVAL);
+
return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
}
EXPORT_SYMBOL(rpmsg_create_ept);
@@ -80,11 +83,13 @@ EXPORT_SYMBOL(rpmsg_create_ept);
* @ept: endpoing to destroy
*
* Should be used by drivers to destroy an rpmsg endpoint previously
- * created with rpmsg_create_ept().
+ * created with rpmsg_create_ept(). As with other types of "free" NULL
+ * is a valid parameter.
*/
void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
{
- ept->ops->destroy_ept(ept);
+ if (ept)
+ ept->ops->destroy_ept(ept);
}
EXPORT_SYMBOL(rpmsg_destroy_ept);
@@ -108,6 +113,11 @@ EXPORT_SYMBOL(rpmsg_destroy_ept);
*/
int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->send)
+ return -ENXIO;
+
return ept->ops->send(ept, data, len);
}
EXPORT_SYMBOL(rpmsg_send);
@@ -132,6 +142,11 @@ EXPORT_SYMBOL(rpmsg_send);
*/
int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->sendto)
+ return -ENXIO;
+
return ept->ops->sendto(ept, data, len, dst);
}
EXPORT_SYMBOL(rpmsg_sendto);
@@ -159,6 +174,11 @@ EXPORT_SYMBOL(rpmsg_sendto);
int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
void *data, int len)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->send_offchannel)
+ return -ENXIO;
+
return ept->ops->send_offchannel(ept, src, dst, data, len);
}
EXPORT_SYMBOL(rpmsg_send_offchannel);
@@ -182,6 +202,11 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
*/
int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->trysend)
+ return -ENXIO;
+
return ept->ops->trysend(ept, data, len);
}
EXPORT_SYMBOL(rpmsg_trysend);
@@ -205,6 +230,11 @@ EXPORT_SYMBOL(rpmsg_trysend);
*/
int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->trysendto)
+ return -ENXIO;
+
return ept->ops->trysendto(ept, data, len, dst);
}
EXPORT_SYMBOL(rpmsg_trysendto);
@@ -231,6 +261,11 @@ EXPORT_SYMBOL(rpmsg_trysendto);
int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
void *data, int len)
{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->trysend_offchannel)
+ return -ENXIO;
+
return ept->ops->trysend_offchannel(ept, src, dst, data, len);
}
EXPORT_SYMBOL(rpmsg_trysend_offchannel);
@@ -315,6 +350,9 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
const struct rpmsg_device_id *ids = rpdrv->id_table;
unsigned int i;
+ if (rpdev->driver_override)
+ return !strcmp(rpdev->driver_override, drv->name);
+
if (ids)
for (i = 0; ids[i].name[0]; i++)
if (rpmsg_id_match(rpdev, &ids[i]))
@@ -344,27 +382,30 @@ static int rpmsg_dev_probe(struct device *dev)
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
struct rpmsg_channel_info chinfo = {};
- struct rpmsg_endpoint *ept;
+ struct rpmsg_endpoint *ept = NULL;
int err;
- strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
- chinfo.src = rpdev->src;
- chinfo.dst = RPMSG_ADDR_ANY;
+ if (rpdrv->callback) {
+ strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
+ chinfo.src = rpdev->src;
+ chinfo.dst = RPMSG_ADDR_ANY;
- ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo);
- if (!ept) {
- dev_err(dev, "failed to create endpoint\n");
- err = -ENOMEM;
- goto out;
- }
+ ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo);
+ if (!ept) {
+ dev_err(dev, "failed to create endpoint\n");
+ err = -ENOMEM;
+ goto out;
+ }
- rpdev->ept = ept;
- rpdev->src = ept->addr;
+ rpdev->ept = ept;
+ rpdev->src = ept->addr;
+ }
err = rpdrv->probe(rpdev);
if (err) {
dev_err(dev, "%s: failed: %d\n", __func__, err);
- rpmsg_destroy_ept(ept);
+ if (ept)
+ rpmsg_destroy_ept(ept);
goto out;
}
@@ -385,7 +426,8 @@ static int rpmsg_dev_remove(struct device *dev)
rpdrv->remove(rpdev);
- rpmsg_destroy_ept(rpdev->ept);
+ if (rpdev->ept)
+ rpmsg_destroy_ept(rpdev->ept);
return err;
}
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 7030d7cd3861..38aa8e1906c2 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -191,6 +191,13 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
+ /*
+ * If pm_trace abused the RTC for storage, set the timespec to 0,
+ * which tells the caller that this RTC value is unusable.
+ */
+ if (!pm_trace_rtc_valid())
+ return -EIO;
+
/* REVISIT: if the clock has a "century" register, use
* that instead of the heuristic in mc146818_get_time().
* That'll make Y3K compatility (year > 2070) easy!
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index ad17fc5883f6..ac65f12bcd43 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1032,9 +1032,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
struct ctcm_priv *priv;
int max_bufsize;
- if (new_mtu < 576 || new_mtu > 65527)
- return -EINVAL;
-
priv = dev->ml_priv;
max_bufsize = priv->channel[CTCM_READ]->max_bufsize;
@@ -1123,6 +1120,8 @@ void static ctcm_dev_setup(struct net_device *dev)
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 100;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ dev->min_mtu = 576;
+ dev->max_mtu = 65527;
}
/*
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 251db0a02e73..211b31d9f157 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1888,7 +1888,7 @@ lcs_stop_device(struct net_device *dev)
rc = lcs_stopcard(card);
if (rc)
dev_err(&card->dev->dev,
- " Shutting down the LCS device failed\n ");
+ " Shutting down the LCS device failed\n");
return rc;
}
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index b0e8ffdf864b..2981024a2438 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -302,8 +302,7 @@ static char *netiucv_printuser(struct iucv_connection *conn)
if (memcmp(conn->userdata, iucvMagic_ebcdic, 16)) {
tmp_uid[8] = '\0';
tmp_udat[16] = '\0';
- memcpy(tmp_uid, conn->userid, 8);
- memcpy(tmp_uid, netiucv_printname(tmp_uid, 8), 8);
+ memcpy(tmp_uid, netiucv_printname(conn->userid, 8), 8);
memcpy(tmp_udat, conn->userdata, 16);
EBCASC(tmp_udat, 16);
memcpy(tmp_udat, netiucv_printname(tmp_udat, 16), 16);
@@ -1429,27 +1428,6 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
return &priv->stats;
}
-/**
- * netiucv_change_mtu
- * @dev: Pointer to interface struct.
- * @new_mtu: The new MTU to use for this interface.
- *
- * Sets MTU of an interface.
- *
- * Returns 0 on success, -EINVAL if MTU is out of valid range.
- * (valid range is 576 .. NETIUCV_MTU_MAX).
- */
-static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
-{
- IUCV_DBF_TEXT(trace, 3, __func__);
- if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
- IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
- return -EINVAL;
- }
- dev->mtu = new_mtu;
- return 0;
-}
-
/*
* attributes in sysfs
*/
@@ -1564,21 +1542,21 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
{
struct netiucv_priv *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->conn->netdev;
- char *e;
- int bs1;
+ unsigned int bs1;
+ int rc;
IUCV_DBF_TEXT(trace, 3, __func__);
if (count >= 39)
return -EINVAL;
- bs1 = simple_strtoul(buf, &e, 0);
+ rc = kstrtouint(buf, 0, &bs1);
- if (e && (!isspace(*e))) {
- IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %02x\n",
- *e);
+ if (rc == -EINVAL) {
+ IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %s\n",
+ buf);
return -EINVAL;
}
- if (bs1 > NETIUCV_BUFSIZE_MAX) {
+ if ((rc == -ERANGE) || (bs1 > NETIUCV_BUFSIZE_MAX)) {
IUCV_DBF_TEXT_(setup, 2,
"buffer_write: buffer size %d too large\n",
bs1);
@@ -1987,12 +1965,13 @@ static const struct net_device_ops netiucv_netdev_ops = {
.ndo_stop = netiucv_close,
.ndo_get_stats = netiucv_stats,
.ndo_start_xmit = netiucv_tx,
- .ndo_change_mtu = netiucv_change_mtu,
};
static void netiucv_setup_netdevice(struct net_device *dev)
{
dev->mtu = NETIUCV_MTU_DEFAULT;
+ dev->min_mtu = 576;
+ dev->max_mtu = NETIUCV_MTU_MAX;
dev->destructor = netiucv_free_netdevice;
dev->hard_header_len = NETIUCV_HDRLEN;
dev->addr_len = 0;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 20cf29613043..e33558313834 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -4202,10 +4202,6 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu)
sprintf(dbf_text, "%8x", new_mtu);
QETH_CARD_TEXT(card, 4, dbf_text);
- if (new_mtu < 64)
- return -EINVAL;
- if (new_mtu > 65535)
- return -EINVAL;
if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
(!qeth_mtu_is_valid(card, new_mtu)))
return -EINVAL;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index bb27058fa9f0..9c921c2833f1 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1107,6 +1107,8 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->dev->ml_priv = card;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
card->dev->mtu = card->info.initial_mtu;
+ card->dev->min_mtu = 64;
+ card->dev->max_mtu = ETH_MAX_MTU;
card->dev->netdev_ops = &qeth_l2_netdev_ops;
card->dev->ethtool_ops =
(card->info.type != QETH_CARD_TYPE_OSN) ?
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 272d9e7419be..ac37d050e765 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3140,6 +3140,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->ml_priv = card;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
card->dev->mtu = card->info.initial_mtu;
+ card->dev->min_mtu = 64;
+ card->dev->max_mtu = ETH_MAX_MTU;
card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 38d938d7fe67..1520596f54a6 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -173,6 +173,7 @@ hv_storvsc-y := storvsc_drv.o
sd_mod-objs := sd.o
sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
+sd_mod-$(CONFIG_BLK_DEV_ZONED) += sd_zbc.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 0039bebaa9e2..4655a9f9dcea 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -85,6 +85,7 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *);
static const struct cxgb4_uld_info cxgb4i_uld_info = {
.name = DRV_MODULE_NAME,
.nrxq = MAX_ULD_QSETS,
+ .ntxq = MAX_ULD_QSETS,
.rxq_size = 1024,
.lro = false,
.add = t4_uld_add,
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7bb20684e9fa..db03c49e2350 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -154,7 +154,8 @@ static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
return scsi_execute_req_flags(sdev, cdb, DMA_FROM_DEVICE,
buff, bufflen, sshdr,
ALUA_FAILOVER_TIMEOUT * HZ,
- ALUA_FAILOVER_RETRIES, NULL, req_flags);
+ ALUA_FAILOVER_RETRIES, NULL,
+ req_flags, 0);
}
/*
@@ -187,7 +188,8 @@ static int submit_stpg(struct scsi_device *sdev, int group_id,
return scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE,
stpg_data, stpg_len,
sshdr, ALUA_FAILOVER_TIMEOUT * HZ,
- ALUA_FAILOVER_RETRIES, NULL, req_flags);
+ ALUA_FAILOVER_RETRIES, NULL,
+ req_flags, 0);
}
static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size,
@@ -1066,7 +1068,7 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
state != SCSI_ACCESS_STATE_ACTIVE &&
state != SCSI_ACCESS_STATE_LBA) {
ret = BLKPREP_KILL;
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
}
return ret;
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 375d81850f15..5b80746980b8 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -452,7 +452,7 @@ static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
if (h->lun_state != CLARIION_LUN_OWNED) {
ret = BLKPREP_KILL;
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
}
return ret;
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 9406d5f4a3d3..308e87195dc1 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -266,7 +266,7 @@ static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
if (h->path_state != HP_SW_PATH_ACTIVE) {
ret = BLKPREP_KILL;
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
}
return ret;
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 06fbd0b0c68a..00d9c326158e 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -724,7 +724,7 @@ static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
if (h->state != RDAC_STATE_ACTIVE) {
ret = BLKPREP_KILL;
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
}
return ret;
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 2f2a9910e30e..ef99f62831fb 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -1595,7 +1595,7 @@ static int _init_blk_request(struct osd_request *or,
}
or->request = req;
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
req->timeout = or->timeout;
req->retries = or->retries;
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 5033223f6287..a2960f5d98ec 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -368,7 +368,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
return DRIVER_ERROR << 24;
blk_rq_set_block_pc(req);
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
SRpnt->bio = NULL;
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 68a5c347fae9..845affa112f7 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -1368,13 +1368,8 @@ static struct genl_multicast_group pmcraid_mcgrps[] = {
{ .name = "events", /* not really used - see ID discussion below */ },
};
-static struct genl_family pmcraid_event_family = {
- /*
- * Due to prior multicast group abuse (the code having assumed that
- * the family ID can be used as a multicast group ID) we need to
- * statically allocate a family (and thus group) ID.
- */
- .id = GENL_ID_PMCRAID,
+static struct genl_family pmcraid_event_family __ro_after_init = {
+ .module = THIS_MODULE,
.name = "pmcraid",
.version = 1,
.maxattr = PMCRAID_AEN_ATTR_MAX,
@@ -1389,7 +1384,7 @@ static struct genl_family pmcraid_event_family = {
* 0 if the pmcraid_event_family is successfully registered
* with netlink generic, non-zero otherwise
*/
-static int pmcraid_netlink_init(void)
+static int __init pmcraid_netlink_init(void)
{
int result;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1deb6adc411f..75455d4dab68 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -621,6 +621,9 @@ int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
wmb();
}
+ if (sdev->request_queue)
+ blk_set_queue_depth(sdev->request_queue, depth);
+
return sdev->queue_depth;
}
EXPORT_SYMBOL(scsi_change_queue_depth);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 106a6adbd6f1..996e134d79fa 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1988,7 +1988,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
req->cmd_len = COMMAND_SIZE(req->cmd[0]);
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
req->timeout = 10 * HZ;
req->retries = 5;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 2cca9cffc63f..9a8ccff1121f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -86,10 +86,8 @@ scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
- struct request_queue *q = cmd->request->q;
- blk_mq_requeue_request(cmd->request);
- blk_mq_kick_requeue_list(q);
+ blk_mq_requeue_request(cmd->request, true);
put_device(&sdev->sdev_gendev);
}
@@ -163,26 +161,11 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
__scsi_queue_insert(cmd, reason, 1);
}
-/**
- * scsi_execute - insert request and wait for the result
- * @sdev: scsi device
- * @cmd: scsi command
- * @data_direction: data direction
- * @buffer: data buffer
- * @bufflen: len of buffer
- * @sense: optional sense buffer
- * @timeout: request timeout in seconds
- * @retries: number of times to retry request
- * @flags: or into request flags;
- * @resid: optional residual length
- *
- * returns the req->errors value which is the scsi_cmnd result
- * field.
- */
-int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+
+static int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen,
unsigned char *sense, int timeout, int retries, u64 flags,
- int *resid)
+ req_flags_t rq_flags, int *resid)
{
struct request *req;
int write = (data_direction == DMA_TO_DEVICE);
@@ -203,7 +186,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
req->sense_len = 0;
req->retries = retries;
req->timeout = timeout;
- req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT;
+ req->cmd_flags |= flags;
+ req->rq_flags |= rq_flags | RQF_QUIET | RQF_PREEMPT;
/*
* head injection *required* here otherwise quiesce won't work
@@ -227,12 +211,37 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
return ret;
}
+
+/**
+ * scsi_execute - insert request and wait for the result
+ * @sdev: scsi device
+ * @cmd: scsi command
+ * @data_direction: data direction
+ * @buffer: data buffer
+ * @bufflen: len of buffer
+ * @sense: optional sense buffer
+ * @timeout: request timeout in seconds
+ * @retries: number of times to retry request
+ * @flags: or into request flags;
+ * @resid: optional residual length
+ *
+ * returns the req->errors value which is the scsi_cmnd result
+ * field.
+ */
+int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ unsigned char *sense, int timeout, int retries, u64 flags,
+ int *resid)
+{
+ return __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense,
+ timeout, retries, flags, 0, resid);
+}
EXPORT_SYMBOL(scsi_execute);
int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen,
struct scsi_sense_hdr *sshdr, int timeout, int retries,
- int *resid, u64 flags)
+ int *resid, u64 flags, req_flags_t rq_flags)
{
char *sense = NULL;
int result;
@@ -242,8 +251,8 @@ int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
if (!sense)
return DRIVER_ERROR << 24;
}
- result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
- sense, timeout, retries, flags, resid);
+ result = __scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
+ sense, timeout, retries, flags, rq_flags, resid);
if (sshdr)
scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
@@ -813,7 +822,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
*/
if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d))
;
- else if (!(req->cmd_flags & REQ_QUIET))
+ else if (!(req->rq_flags & RQF_QUIET))
scsi_print_sense(cmd);
result = 0;
/* BLOCK_PC may have set error */
@@ -943,7 +952,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
switch (action) {
case ACTION_FAIL:
/* Give up and fail the remainder of the request */
- if (!(req->cmd_flags & REQ_QUIET)) {
+ if (!(req->rq_flags & RQF_QUIET)) {
static DEFINE_RATELIMIT_STATE(_rs,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
@@ -972,7 +981,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
* A new command will be prepared and issued.
*/
if (q->mq_ops) {
- cmd->request->cmd_flags &= ~REQ_DONTPREP;
+ cmd->request->rq_flags &= ~RQF_DONTPREP;
scsi_mq_uninit_cmd(cmd);
scsi_mq_requeue_cmd(cmd);
} else {
@@ -998,8 +1007,8 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb)
/*
* If sg table allocation fails, requeue request later.
*/
- if (unlikely(sg_alloc_table_chained(&sdb->table, req->nr_phys_segments,
- sdb->table.sgl)))
+ if (unlikely(sg_alloc_table_chained(&sdb->table,
+ blk_rq_nr_phys_segments(req), sdb->table.sgl)))
return BLKPREP_DEFER;
/*
@@ -1031,7 +1040,7 @@ int scsi_init_io(struct scsi_cmnd *cmd)
bool is_mq = (rq->mq_ctx != NULL);
int error;
- BUG_ON(!rq->nr_phys_segments);
+ BUG_ON(!blk_rq_nr_phys_segments(rq));
error = scsi_init_sgtable(rq, &cmd->sdb);
if (error)
@@ -1234,7 +1243,7 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
/*
* If the devices is blocked we defer normal commands.
*/
- if (!(req->cmd_flags & REQ_PREEMPT))
+ if (!(req->rq_flags & RQF_PREEMPT))
ret = BLKPREP_DEFER;
break;
default:
@@ -1243,7 +1252,7 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
* special commands. In particular any user initiated
* command is not allowed.
*/
- if (!(req->cmd_flags & REQ_PREEMPT))
+ if (!(req->rq_flags & RQF_PREEMPT))
ret = BLKPREP_KILL;
break;
}
@@ -1279,7 +1288,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret)
blk_delay_queue(q, SCSI_QUEUE_DELAY);
break;
default:
- req->cmd_flags |= REQ_DONTPREP;
+ req->rq_flags |= RQF_DONTPREP;
}
return ret;
@@ -1736,7 +1745,7 @@ static void scsi_request_fn(struct request_queue *q)
* we add the dev to the starved list so it eventually gets
* a run when a tag is freed.
*/
- if (blk_queue_tagged(q) && !(req->cmd_flags & REQ_QUEUED)) {
+ if (blk_queue_tagged(q) && !(req->rq_flags & RQF_QUEUED)) {
spin_lock_irq(shost->host_lock);
if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry,
@@ -1801,7 +1810,7 @@ static inline int prep_to_mq(int ret)
{
switch (ret) {
case BLKPREP_OK:
- return 0;
+ return BLK_MQ_RQ_QUEUE_OK;
case BLKPREP_DEFER:
return BLK_MQ_RQ_QUEUE_BUSY;
default:
@@ -1888,7 +1897,7 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
int reason;
ret = prep_to_mq(scsi_prep_state_check(sdev, req));
- if (ret)
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
goto out;
ret = BLK_MQ_RQ_QUEUE_BUSY;
@@ -1903,11 +1912,11 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
goto out_dec_target_busy;
- if (!(req->cmd_flags & REQ_DONTPREP)) {
+ if (!(req->rq_flags & RQF_DONTPREP)) {
ret = prep_to_mq(scsi_mq_prep_fn(req));
- if (ret)
+ if (ret != BLK_MQ_RQ_QUEUE_OK)
goto out_dec_host_busy;
- req->cmd_flags |= REQ_DONTPREP;
+ req->rq_flags |= RQF_DONTPREP;
} else {
blk_mq_start_request(req);
}
@@ -1941,7 +1950,6 @@ out_put_device:
out:
switch (ret) {
case BLK_MQ_RQ_QUEUE_BUSY:
- blk_mq_stop_hw_queue(hctx);
if (atomic_read(&sdev->device_busy) == 0 &&
!scsi_device_blocked(sdev))
blk_mq_delay_queue(hctx, SCSI_QUEUE_DELAY);
@@ -1952,7 +1960,7 @@ out:
* we hit an error, as we will never see this command
* again.
*/
- if (req->cmd_flags & REQ_DONTPREP)
+ if (req->rq_flags & RQF_DONTPREP)
scsi_mq_uninit_cmd(cmd);
break;
default:
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 51e56296f465..079c2d9759fb 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -93,6 +93,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR);
MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC);
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
#define SD_MINORS 16
@@ -163,7 +164,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
static const char temp[] = "temporary ";
int len;
- if (sdp->type != TYPE_DISK)
+ if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
/* no cache control on RBC devices; theoretically they
* can do it, but there's probably so many exceptions
* it's not worth the risk */
@@ -262,7 +263,7 @@ allow_restart_store(struct device *dev, struct device_attribute *attr,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (sdp->type != TYPE_DISK)
+ if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
return -EINVAL;
sdp->allow_restart = simple_strtoul(buf, NULL, 10);
@@ -392,6 +393,11 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
+ if (sd_is_zoned(sdkp)) {
+ sd_config_discard(sdkp, SD_LBP_DISABLE);
+ return count;
+ }
+
if (sdp->type != TYPE_DISK)
return -EINVAL;
@@ -459,7 +465,7 @@ max_write_same_blocks_store(struct device *dev, struct device_attribute *attr,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (sdp->type != TYPE_DISK)
+ if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
return -EINVAL;
err = kstrtoul(buf, 10, &max);
@@ -710,7 +716,6 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
sector_t sector = blk_rq_pos(rq);
unsigned int nr_sectors = blk_rq_sectors(rq);
- unsigned int nr_bytes = blk_rq_bytes(rq);
unsigned int len;
int ret;
char *buf;
@@ -766,24 +771,19 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
goto out;
}
- rq->completion_data = page;
rq->timeout = SD_TIMEOUT;
cmd->transfersize = len;
cmd->allowed = SD_MAX_RETRIES;
- /*
- * Initially __data_len is set to the amount of data that needs to be
- * transferred to the target. This amount depends on whether WRITE SAME
- * or UNMAP is being used. After the scatterlist has been mapped by
- * scsi_init_io() we set __data_len to the size of the area to be
- * discarded on disk. This allows us to report completion on the full
- * amount of blocks described by the request.
- */
- blk_add_request_payload(rq, page, 0, len);
- ret = scsi_init_io(cmd);
- rq->__data_len = nr_bytes;
+ rq->special_vec.bv_page = page;
+ rq->special_vec.bv_offset = 0;
+ rq->special_vec.bv_len = len;
+
+ rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
+ rq->resid_len = len;
+ ret = scsi_init_io(cmd);
out:
if (ret != BLKPREP_OK)
__free_page(page);
@@ -844,6 +844,12 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
+ if (sd_is_zoned(sdkp)) {
+ ret = sd_zbc_setup_write_cmnd(cmd);
+ if (ret != BLKPREP_OK)
+ return ret;
+ }
+
sector >>= ilog2(sdp->sector_size) - 9;
nr_sectors >>= ilog2(sdp->sector_size) - 9;
@@ -901,19 +907,25 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
struct request *rq = SCpnt->request;
struct scsi_device *sdp = SCpnt->device;
struct gendisk *disk = rq->rq_disk;
- struct scsi_disk *sdkp;
+ struct scsi_disk *sdkp = scsi_disk(disk);
sector_t block = blk_rq_pos(rq);
sector_t threshold;
unsigned int this_count = blk_rq_sectors(rq);
unsigned int dif, dix;
+ bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE;
int ret;
unsigned char protect;
+ if (zoned_write) {
+ ret = sd_zbc_setup_write_cmnd(SCpnt);
+ if (ret != BLKPREP_OK)
+ return ret;
+ }
+
ret = scsi_init_io(SCpnt);
if (ret != BLKPREP_OK)
goto out;
SCpnt = rq->special;
- sdkp = scsi_disk(disk);
/* from here on until we're complete, any goto out
* is used for a killable error condition */
@@ -1013,8 +1025,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
} else if (rq_data_dir(rq) == READ) {
SCpnt->cmnd[0] = READ_6;
} else {
- scmd_printk(KERN_ERR, SCpnt, "Unknown command %llu,%llx\n",
- req_op(rq), (unsigned long long) rq->cmd_flags);
+ scmd_printk(KERN_ERR, SCpnt, "Unknown command %d\n", req_op(rq));
goto out;
}
@@ -1132,6 +1143,9 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
*/
ret = BLKPREP_OK;
out:
+ if (zoned_write && ret != BLKPREP_OK)
+ sd_zbc_cancel_write_cmnd(SCpnt);
+
return ret;
}
@@ -1149,6 +1163,10 @@ static int sd_init_command(struct scsi_cmnd *cmd)
case REQ_OP_READ:
case REQ_OP_WRITE:
return sd_setup_read_write_cmnd(cmd);
+ case REQ_OP_ZONE_REPORT:
+ return sd_zbc_setup_report_cmnd(cmd);
+ case REQ_OP_ZONE_RESET:
+ return sd_zbc_setup_reset_cmnd(cmd);
default:
BUG();
}
@@ -1158,8 +1176,8 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
{
struct request *rq = SCpnt->request;
- if (req_op(rq) == REQ_OP_DISCARD)
- __free_page(rq->completion_data);
+ if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+ __free_page(rq->special_vec.bv_page);
if (SCpnt->cmnd != rq->cmd) {
mempool_free(SCpnt->cmnd, sd_cdb_pool);
@@ -1495,7 +1513,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
*/
res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
&sshdr, timeout, SD_MAX_RETRIES,
- NULL, REQ_PM);
+ NULL, 0, RQF_PM);
if (res == 0)
break;
}
@@ -1780,7 +1798,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)
unsigned char op = SCpnt->cmnd[0];
unsigned char unmap = SCpnt->cmnd[1] & 8;
- if (req_op(req) == REQ_OP_DISCARD || req_op(req) == REQ_OP_WRITE_SAME) {
+ switch (req_op(req)) {
+ case REQ_OP_DISCARD:
+ case REQ_OP_WRITE_SAME:
+ case REQ_OP_ZONE_RESET:
if (!result) {
good_bytes = blk_rq_bytes(req);
scsi_set_resid(SCpnt, 0);
@@ -1788,6 +1809,17 @@ static int sd_done(struct scsi_cmnd *SCpnt)
good_bytes = 0;
scsi_set_resid(SCpnt, blk_rq_bytes(req));
}
+ break;
+ case REQ_OP_ZONE_REPORT:
+ if (!result) {
+ good_bytes = scsi_bufflen(SCpnt)
+ - scsi_get_resid(SCpnt);
+ scsi_set_resid(SCpnt, 0);
+ } else {
+ good_bytes = 0;
+ scsi_set_resid(SCpnt, blk_rq_bytes(req));
+ }
+ break;
}
if (result) {
@@ -1840,7 +1872,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
good_bytes = 0;
req->__data_len = blk_rq_bytes(req);
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
}
}
}
@@ -1848,7 +1880,11 @@ static int sd_done(struct scsi_cmnd *SCpnt)
default:
break;
}
+
out:
+ if (sd_is_zoned(sdkp))
+ sd_zbc_complete(SCpnt, good_bytes, &sshdr);
+
SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
"sd_done: completed %d of %d bytes\n",
good_bytes, scsi_bufflen(SCpnt)));
@@ -1983,7 +2019,6 @@ sd_spinup_disk(struct scsi_disk *sdkp)
}
}
-
/*
* Determine whether disk supports Data Integrity Field.
*/
@@ -2133,6 +2168,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
/* Logical blocks per physical block exponent */
sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size;
+ /* RC basis */
+ sdkp->rc_basis = (buffer[12] >> 4) & 0x3;
+
/* Lowest aligned logical block */
alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
blk_queue_alignment_offset(sdp->request_queue, alignment);
@@ -2242,7 +2280,6 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
{
int sector_size;
struct scsi_device *sdp = sdkp->device;
- sector_t old_capacity = sdkp->capacity;
if (sd_try_rc16_first(sdp)) {
sector_size = read_capacity_16(sdkp, sdp, buffer);
@@ -2323,35 +2360,44 @@ got_data:
sector_size = 512;
}
blk_queue_logical_block_size(sdp->request_queue, sector_size);
+ blk_queue_physical_block_size(sdp->request_queue,
+ sdkp->physical_block_size);
+ sdkp->device->sector_size = sector_size;
- {
- char cap_str_2[10], cap_str_10[10];
+ if (sdkp->capacity > 0xffffffff)
+ sdp->use_16_for_rw = 1;
- string_get_size(sdkp->capacity, sector_size,
- STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
- string_get_size(sdkp->capacity, sector_size,
- STRING_UNITS_10, cap_str_10,
- sizeof(cap_str_10));
+}
- if (sdkp->first_scan || old_capacity != sdkp->capacity) {
- sd_printk(KERN_NOTICE, sdkp,
- "%llu %d-byte logical blocks: (%s/%s)\n",
- (unsigned long long)sdkp->capacity,
- sector_size, cap_str_10, cap_str_2);
+/*
+ * Print disk capacity
+ */
+static void
+sd_print_capacity(struct scsi_disk *sdkp,
+ sector_t old_capacity)
+{
+ int sector_size = sdkp->device->sector_size;
+ char cap_str_2[10], cap_str_10[10];
- if (sdkp->physical_block_size != sector_size)
- sd_printk(KERN_NOTICE, sdkp,
- "%u-byte physical blocks\n",
- sdkp->physical_block_size);
- }
- }
+ string_get_size(sdkp->capacity, sector_size,
+ STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
+ string_get_size(sdkp->capacity, sector_size,
+ STRING_UNITS_10, cap_str_10,
+ sizeof(cap_str_10));
- if (sdkp->capacity > 0xffffffff)
- sdp->use_16_for_rw = 1;
+ if (sdkp->first_scan || old_capacity != sdkp->capacity) {
+ sd_printk(KERN_NOTICE, sdkp,
+ "%llu %d-byte logical blocks: (%s/%s)\n",
+ (unsigned long long)sdkp->capacity,
+ sector_size, cap_str_10, cap_str_2);
- blk_queue_physical_block_size(sdp->request_queue,
- sdkp->physical_block_size);
- sdkp->device->sector_size = sector_size;
+ if (sdkp->physical_block_size != sector_size)
+ sd_printk(KERN_NOTICE, sdkp,
+ "%u-byte physical blocks\n",
+ sdkp->physical_block_size);
+
+ sd_zbc_print_zones(sdkp);
+ }
}
/* called with buffer of length 512 */
@@ -2613,7 +2659,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
- if (sdp->type != TYPE_DISK)
+ if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
return;
if (sdkp->protection_type == 0)
@@ -2720,6 +2766,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
*/
static void sd_read_block_characteristics(struct scsi_disk *sdkp)
{
+ struct request_queue *q = sdkp->disk->queue;
unsigned char *buffer;
u16 rot;
const int vpd_len = 64;
@@ -2734,10 +2781,21 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
rot = get_unaligned_be16(&buffer[4]);
if (rot == 1) {
- queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue);
- queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, sdkp->disk->queue);
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+ queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
}
+ sdkp->zoned = (buffer[8] >> 4) & 3;
+ if (sdkp->zoned == 1)
+ q->limits.zoned = BLK_ZONED_HA;
+ else if (sdkp->device->type == TYPE_ZBC)
+ q->limits.zoned = BLK_ZONED_HM;
+ else
+ q->limits.zoned = BLK_ZONED_NONE;
+ if (blk_queue_is_zoned(q) && sdkp->first_scan)
+ sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
+ q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
+
out:
kfree(buffer);
}
@@ -2809,6 +2867,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
struct request_queue *q = sdkp->disk->queue;
+ sector_t old_capacity = sdkp->capacity;
unsigned char *buffer;
unsigned int dev_max, rw_max;
@@ -2842,8 +2901,11 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_block_provisioning(sdkp);
sd_read_block_limits(sdkp);
sd_read_block_characteristics(sdkp);
+ sd_zbc_read_zones(sdkp, buffer);
}
+ sd_print_capacity(sdkp, old_capacity);
+
sd_read_write_protect_flag(sdkp, buffer);
sd_read_cache_type(sdkp, buffer);
sd_read_app_tag_own(sdkp, buffer);
@@ -3041,9 +3103,16 @@ static int sd_probe(struct device *dev)
scsi_autopm_get_device(sdp);
error = -ENODEV;
- if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
+ if (sdp->type != TYPE_DISK &&
+ sdp->type != TYPE_ZBC &&
+ sdp->type != TYPE_MOD &&
+ sdp->type != TYPE_RBC)
goto out;
+#ifndef CONFIG_BLK_DEV_ZONED
+ if (sdp->type == TYPE_ZBC)
+ goto out;
+#endif
SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp,
"sd_probe\n"));
@@ -3147,6 +3216,8 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk);
sd_shutdown(dev);
+ sd_zbc_remove(sdkp);
+
blk_register_region(devt, SD_MINORS, NULL,
sd_default_probe, NULL, NULL);
@@ -3200,7 +3271,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
return -ENODEV;
res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
+ SD_TIMEOUT, SD_MAX_RETRIES, NULL, 0, RQF_PM);
if (res) {
sd_print_result(sdkp, "Start/Stop Unit failed", res);
if (driver_byte(res) & DRIVER_SENSE)
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index c8d986368da9..4dac35e96a75 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -64,6 +64,15 @@ struct scsi_disk {
struct scsi_device *device;
struct device dev;
struct gendisk *disk;
+#ifdef CONFIG_BLK_DEV_ZONED
+ unsigned int nr_zones;
+ unsigned int zone_blocks;
+ unsigned int zone_shift;
+ unsigned long *zones_wlock;
+ unsigned int zones_optimal_open;
+ unsigned int zones_optimal_nonseq;
+ unsigned int zones_max_open;
+#endif
atomic_t openers;
sector_t capacity; /* size in logical blocks */
u32 max_xfer_blocks;
@@ -94,6 +103,9 @@ struct scsi_disk {
unsigned lbpvpd : 1;
unsigned ws10 : 1;
unsigned ws16 : 1;
+ unsigned rc_basis: 2;
+ unsigned zoned: 2;
+ unsigned urswrz : 1;
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
@@ -156,6 +168,11 @@ static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t b
return blocks * sdev->sector_size;
}
+static inline sector_t sectors_to_logical(struct scsi_device *sdev, sector_t sector)
+{
+ return sector >> (ilog2(sdev->sector_size) - 9);
+}
+
/*
* Look up the DIX operation based on whether the command is read or
* write and whether dix and dif are enabled.
@@ -239,4 +256,57 @@ static inline void sd_dif_complete(struct scsi_cmnd *cmd, unsigned int a)
#endif /* CONFIG_BLK_DEV_INTEGRITY */
+static inline int sd_is_zoned(struct scsi_disk *sdkp)
+{
+ return sdkp->zoned == 1 || sdkp->device->type == TYPE_ZBC;
+}
+
+#ifdef CONFIG_BLK_DEV_ZONED
+
+extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
+extern void sd_zbc_remove(struct scsi_disk *sdkp);
+extern void sd_zbc_print_zones(struct scsi_disk *sdkp);
+extern int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd);
+extern void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd);
+extern int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd);
+extern int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd);
+extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
+ struct scsi_sense_hdr *sshdr);
+
+#else /* CONFIG_BLK_DEV_ZONED */
+
+static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
+ unsigned char *buf)
+{
+ return 0;
+}
+
+static inline void sd_zbc_remove(struct scsi_disk *sdkp) {}
+
+static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {}
+
+static inline int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd)
+{
+ /* Let the drive fail requests */
+ return BLKPREP_OK;
+}
+
+static inline void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd) {}
+
+static inline int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd)
+{
+ return BLKPREP_INVALID;
+}
+
+static inline int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
+{
+ return BLKPREP_INVALID;
+}
+
+static inline void sd_zbc_complete(struct scsi_cmnd *cmd,
+ unsigned int good_bytes,
+ struct scsi_sense_hdr *sshdr) {}
+
+#endif /* CONFIG_BLK_DEV_ZONED */
+
#endif /* _SCSI_DISK_H */
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
new file mode 100644
index 000000000000..92620c8ea8ad
--- /dev/null
+++ b/drivers/scsi/sd_zbc.c
@@ -0,0 +1,648 @@
+/*
+ * SCSI Zoned Block commands
+ *
+ * Copyright (C) 2014-2015 SUSE Linux GmbH
+ * Written by: Hannes Reinecke <hare@suse.de>
+ * Modified by: Damien Le Moal <damien.lemoal@hgst.com>
+ * Modified by: Shaun Tancheff <shaun.tancheff@seagate.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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include <linux/blkdev.h>
+
+#include <asm/unaligned.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+
+#include "sd.h"
+#include "scsi_priv.h"
+
+enum zbc_zone_type {
+ ZBC_ZONE_TYPE_CONV = 0x1,
+ ZBC_ZONE_TYPE_SEQWRITE_REQ,
+ ZBC_ZONE_TYPE_SEQWRITE_PREF,
+ ZBC_ZONE_TYPE_RESERVED,
+};
+
+enum zbc_zone_cond {
+ ZBC_ZONE_COND_NO_WP,
+ ZBC_ZONE_COND_EMPTY,
+ ZBC_ZONE_COND_IMP_OPEN,
+ ZBC_ZONE_COND_EXP_OPEN,
+ ZBC_ZONE_COND_CLOSED,
+ ZBC_ZONE_COND_READONLY = 0xd,
+ ZBC_ZONE_COND_FULL,
+ ZBC_ZONE_COND_OFFLINE,
+};
+
+/**
+ * Convert a zone descriptor to a zone struct.
+ */
+static void sd_zbc_parse_report(struct scsi_disk *sdkp,
+ u8 *buf,
+ struct blk_zone *zone)
+{
+ struct scsi_device *sdp = sdkp->device;
+
+ memset(zone, 0, sizeof(struct blk_zone));
+
+ zone->type = buf[0] & 0x0f;
+ zone->cond = (buf[1] >> 4) & 0xf;
+ if (buf[1] & 0x01)
+ zone->reset = 1;
+ if (buf[1] & 0x02)
+ zone->non_seq = 1;
+
+ zone->len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8]));
+ zone->start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16]));
+ zone->wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24]));
+ if (zone->type != ZBC_ZONE_TYPE_CONV &&
+ zone->cond == ZBC_ZONE_COND_FULL)
+ zone->wp = zone->start + zone->len;
+}
+
+/**
+ * Issue a REPORT ZONES scsi command.
+ */
+static int sd_zbc_report_zones(struct scsi_disk *sdkp, unsigned char *buf,
+ unsigned int buflen, sector_t lba)
+{
+ struct scsi_device *sdp = sdkp->device;
+ const int timeout = sdp->request_queue->rq_timeout;
+ struct scsi_sense_hdr sshdr;
+ unsigned char cmd[16];
+ unsigned int rep_len;
+ int result;
+
+ memset(cmd, 0, 16);
+ cmd[0] = ZBC_IN;
+ cmd[1] = ZI_REPORT_ZONES;
+ put_unaligned_be64(lba, &cmd[2]);
+ put_unaligned_be32(buflen, &cmd[10]);
+ memset(buf, 0, buflen);
+
+ result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ buf, buflen, &sshdr,
+ timeout, SD_MAX_RETRIES, NULL);
+ if (result) {
+ sd_printk(KERN_ERR, sdkp,
+ "REPORT ZONES lba %llu failed with %d/%d\n",
+ (unsigned long long)lba,
+ host_byte(result), driver_byte(result));
+ return -EIO;
+ }
+
+ rep_len = get_unaligned_be32(&buf[0]);
+ if (rep_len < 64) {
+ sd_printk(KERN_ERR, sdkp,
+ "REPORT ZONES report invalid length %u\n",
+ rep_len);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd)
+{
+ struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ sector_t lba, sector = blk_rq_pos(rq);
+ unsigned int nr_bytes = blk_rq_bytes(rq);
+ int ret;
+
+ WARN_ON(nr_bytes == 0);
+
+ if (!sd_is_zoned(sdkp))
+ /* Not a zoned device */
+ return BLKPREP_KILL;
+
+ ret = scsi_init_io(cmd);
+ if (ret != BLKPREP_OK)
+ return ret;
+
+ cmd->cmd_len = 16;
+ memset(cmd->cmnd, 0, cmd->cmd_len);
+ cmd->cmnd[0] = ZBC_IN;
+ cmd->cmnd[1] = ZI_REPORT_ZONES;
+ lba = sectors_to_logical(sdkp->device, sector);
+ put_unaligned_be64(lba, &cmd->cmnd[2]);
+ put_unaligned_be32(nr_bytes, &cmd->cmnd[10]);
+ /* Do partial report for speeding things up */
+ cmd->cmnd[14] = ZBC_REPORT_ZONE_PARTIAL;
+
+ cmd->sc_data_direction = DMA_FROM_DEVICE;
+ cmd->sdb.length = nr_bytes;
+ cmd->transfersize = sdkp->device->sector_size;
+ cmd->allowed = 0;
+
+ /*
+ * Report may return less bytes than requested. Make sure
+ * to report completion on the entire initial request.
+ */
+ rq->__data_len = nr_bytes;
+
+ return BLKPREP_OK;
+}
+
+static void sd_zbc_report_zones_complete(struct scsi_cmnd *scmd,
+ unsigned int good_bytes)
+{
+ struct request *rq = scmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ struct sg_mapping_iter miter;
+ struct blk_zone_report_hdr hdr;
+ struct blk_zone zone;
+ unsigned int offset, bytes = 0;
+ unsigned long flags;
+ u8 *buf;
+
+ if (good_bytes < 64)
+ return;
+
+ memset(&hdr, 0, sizeof(struct blk_zone_report_hdr));
+
+ sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
+ SG_MITER_TO_SG | SG_MITER_ATOMIC);
+
+ local_irq_save(flags);
+ while (sg_miter_next(&miter) && bytes < good_bytes) {
+
+ buf = miter.addr;
+ offset = 0;
+
+ if (bytes == 0) {
+ /* Set the report header */
+ hdr.nr_zones = min_t(unsigned int,
+ (good_bytes - 64) / 64,
+ get_unaligned_be32(&buf[0]) / 64);
+ memcpy(buf, &hdr, sizeof(struct blk_zone_report_hdr));
+ offset += 64;
+ bytes += 64;
+ }
+
+ /* Parse zone descriptors */
+ while (offset < miter.length && hdr.nr_zones) {
+ WARN_ON(offset > miter.length);
+ buf = miter.addr + offset;
+ sd_zbc_parse_report(sdkp, buf, &zone);
+ memcpy(buf, &zone, sizeof(struct blk_zone));
+ offset += 64;
+ bytes += 64;
+ hdr.nr_zones--;
+ }
+
+ if (!hdr.nr_zones)
+ break;
+
+ }
+ sg_miter_stop(&miter);
+ local_irq_restore(flags);
+}
+
+static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp)
+{
+ return logical_to_sectors(sdkp->device, sdkp->zone_blocks);
+}
+
+static inline unsigned int sd_zbc_zone_no(struct scsi_disk *sdkp,
+ sector_t sector)
+{
+ return sectors_to_logical(sdkp->device, sector) >> sdkp->zone_shift;
+}
+
+int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
+{
+ struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ sector_t sector = blk_rq_pos(rq);
+ sector_t block = sectors_to_logical(sdkp->device, sector);
+ unsigned int zno = block >> sdkp->zone_shift;
+
+ if (!sd_is_zoned(sdkp))
+ /* Not a zoned device */
+ return BLKPREP_KILL;
+
+ if (sdkp->device->changed)
+ return BLKPREP_KILL;
+
+ if (sector & (sd_zbc_zone_sectors(sdkp) - 1))
+ /* Unaligned request */
+ return BLKPREP_KILL;
+
+ /* Do not allow concurrent reset and writes */
+ if (sdkp->zones_wlock &&
+ test_and_set_bit(zno, sdkp->zones_wlock))
+ return BLKPREP_DEFER;
+
+ cmd->cmd_len = 16;
+ memset(cmd->cmnd, 0, cmd->cmd_len);
+ cmd->cmnd[0] = ZBC_OUT;
+ cmd->cmnd[1] = ZO_RESET_WRITE_POINTER;
+ put_unaligned_be64(block, &cmd->cmnd[2]);
+
+ rq->timeout = SD_TIMEOUT;
+ cmd->sc_data_direction = DMA_NONE;
+ cmd->transfersize = 0;
+ cmd->allowed = 0;
+
+ return BLKPREP_OK;
+}
+
+int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd)
+{
+ struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ sector_t sector = blk_rq_pos(rq);
+ sector_t zone_sectors = sd_zbc_zone_sectors(sdkp);
+ unsigned int zno = sd_zbc_zone_no(sdkp, sector);
+
+ /*
+ * Note: Checks of the alignment of the write command on
+ * logical blocks is done in sd.c
+ */
+
+ /* Do not allow zone boundaries crossing on host-managed drives */
+ if (blk_queue_zoned_model(sdkp->disk->queue) == BLK_ZONED_HM &&
+ (sector & (zone_sectors - 1)) + blk_rq_sectors(rq) > zone_sectors)
+ return BLKPREP_KILL;
+
+ /*
+ * Do not issue more than one write at a time per
+ * zone. This solves write ordering problems due to
+ * the unlocking of the request queue in the dispatch
+ * path in the non scsi-mq case. For scsi-mq, this
+ * also avoids potential write reordering when multiple
+ * threads running on different CPUs write to the same
+ * zone (with a synchronized sequential pattern).
+ */
+ if (sdkp->zones_wlock &&
+ test_and_set_bit(zno, sdkp->zones_wlock))
+ return BLKPREP_DEFER;
+
+ return BLKPREP_OK;
+}
+
+static void sd_zbc_unlock_zone(struct request *rq)
+{
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+
+ if (sdkp->zones_wlock) {
+ unsigned int zno = sd_zbc_zone_no(sdkp, blk_rq_pos(rq));
+ WARN_ON_ONCE(!test_bit(zno, sdkp->zones_wlock));
+ clear_bit_unlock(zno, sdkp->zones_wlock);
+ smp_mb__after_atomic();
+ }
+}
+
+void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd)
+{
+ sd_zbc_unlock_zone(cmd->request);
+}
+
+void sd_zbc_complete(struct scsi_cmnd *cmd,
+ unsigned int good_bytes,
+ struct scsi_sense_hdr *sshdr)
+{
+ int result = cmd->result;
+ struct request *rq = cmd->request;
+
+ switch (req_op(rq)) {
+ case REQ_OP_WRITE:
+ case REQ_OP_WRITE_SAME:
+ case REQ_OP_ZONE_RESET:
+
+ /* Unlock the zone */
+ sd_zbc_unlock_zone(rq);
+
+ if (!result ||
+ sshdr->sense_key != ILLEGAL_REQUEST)
+ break;
+
+ switch (sshdr->asc) {
+ case 0x24:
+ /*
+ * INVALID FIELD IN CDB error: For a zone reset,
+ * this means that a reset of a conventional
+ * zone was attempted. Nothing to worry about in
+ * this case, so be quiet about the error.
+ */
+ if (req_op(rq) == REQ_OP_ZONE_RESET)
+ rq->rq_flags |= RQF_QUIET;
+ break;
+ case 0x21:
+ /*
+ * INVALID ADDRESS FOR WRITE error: It is unlikely that
+ * retrying write requests failed with any kind of
+ * alignement error will result in success. So don't.
+ */
+ cmd->allowed = 0;
+ break;
+ }
+
+ break;
+
+ case REQ_OP_ZONE_REPORT:
+
+ if (!result)
+ sd_zbc_report_zones_complete(cmd, good_bytes);
+ break;
+
+ }
+}
+
+/**
+ * Read zoned block device characteristics (VPD page B6).
+ */
+static int sd_zbc_read_zoned_characteristics(struct scsi_disk *sdkp,
+ unsigned char *buf)
+{
+
+ if (scsi_get_vpd_page(sdkp->device, 0xb6, buf, 64)) {
+ sd_printk(KERN_NOTICE, sdkp,
+ "Unconstrained-read check failed\n");
+ return -ENODEV;
+ }
+
+ if (sdkp->device->type != TYPE_ZBC) {
+ /* Host-aware */
+ sdkp->urswrz = 1;
+ sdkp->zones_optimal_open = get_unaligned_be64(&buf[8]);
+ sdkp->zones_optimal_nonseq = get_unaligned_be64(&buf[12]);
+ sdkp->zones_max_open = 0;
+ } else {
+ /* Host-managed */
+ sdkp->urswrz = buf[4] & 1;
+ sdkp->zones_optimal_open = 0;
+ sdkp->zones_optimal_nonseq = 0;
+ sdkp->zones_max_open = get_unaligned_be64(&buf[16]);
+ }
+
+ return 0;
+}
+
+/**
+ * Check reported capacity.
+ */
+static int sd_zbc_check_capacity(struct scsi_disk *sdkp,
+ unsigned char *buf)
+{
+ sector_t lba;
+ int ret;
+
+ if (sdkp->rc_basis != 0)
+ return 0;
+
+ /* Do a report zone to get the maximum LBA to check capacity */
+ ret = sd_zbc_report_zones(sdkp, buf, SD_BUF_SIZE, 0);
+ if (ret)
+ return ret;
+
+ /* The max_lba field is the capacity of this device */
+ lba = get_unaligned_be64(&buf[8]);
+ if (lba + 1 == sdkp->capacity)
+ return 0;
+
+ if (sdkp->first_scan)
+ sd_printk(KERN_WARNING, sdkp,
+ "Changing capacity from %llu to max LBA+1 %llu\n",
+ (unsigned long long)sdkp->capacity,
+ (unsigned long long)lba + 1);
+ sdkp->capacity = lba + 1;
+
+ return 0;
+}
+
+#define SD_ZBC_BUF_SIZE 131072
+
+static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
+{
+ u64 zone_blocks;
+ sector_t block = 0;
+ unsigned char *buf;
+ unsigned char *rec;
+ unsigned int buf_len;
+ unsigned int list_length;
+ int ret;
+ u8 same;
+
+ sdkp->zone_blocks = 0;
+
+ /* Get a buffer */
+ buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Do a report zone to get the same field */
+ ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0);
+ if (ret) {
+ zone_blocks = 0;
+ goto out;
+ }
+
+ same = buf[4] & 0x0f;
+ if (same > 0) {
+ rec = &buf[64];
+ zone_blocks = get_unaligned_be64(&rec[8]);
+ goto out;
+ }
+
+ /*
+ * Check the size of all zones: all zones must be of
+ * equal size, except the last zone which can be smaller
+ * than other zones.
+ */
+ do {
+
+ /* Parse REPORT ZONES header */
+ list_length = get_unaligned_be32(&buf[0]) + 64;
+ rec = buf + 64;
+ if (list_length < SD_ZBC_BUF_SIZE)
+ buf_len = list_length;
+ else
+ buf_len = SD_ZBC_BUF_SIZE;
+
+ /* Parse zone descriptors */
+ while (rec < buf + buf_len) {
+ zone_blocks = get_unaligned_be64(&rec[8]);
+ if (sdkp->zone_blocks == 0) {
+ sdkp->zone_blocks = zone_blocks;
+ } else if (zone_blocks != sdkp->zone_blocks &&
+ (block + zone_blocks < sdkp->capacity
+ || zone_blocks > sdkp->zone_blocks)) {
+ zone_blocks = 0;
+ goto out;
+ }
+ block += zone_blocks;
+ rec += 64;
+ }
+
+ if (block < sdkp->capacity) {
+ ret = sd_zbc_report_zones(sdkp, buf,
+ SD_ZBC_BUF_SIZE, block);
+ if (ret)
+ return ret;
+ }
+
+ } while (block < sdkp->capacity);
+
+ zone_blocks = sdkp->zone_blocks;
+
+out:
+ kfree(buf);
+
+ if (!zone_blocks) {
+ if (sdkp->first_scan)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Devices with non constant zone "
+ "size are not supported\n");
+ return -ENODEV;
+ }
+
+ if (!is_power_of_2(zone_blocks)) {
+ if (sdkp->first_scan)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Devices with non power of 2 zone "
+ "size are not supported\n");
+ return -ENODEV;
+ }
+
+ if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
+ if (sdkp->first_scan)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Zone size too large\n");
+ return -ENODEV;
+ }
+
+ sdkp->zone_blocks = zone_blocks;
+
+ return 0;
+}
+
+static int sd_zbc_setup(struct scsi_disk *sdkp)
+{
+
+ /* chunk_sectors indicates the zone size */
+ blk_queue_chunk_sectors(sdkp->disk->queue,
+ logical_to_sectors(sdkp->device, sdkp->zone_blocks));
+ sdkp->zone_shift = ilog2(sdkp->zone_blocks);
+ sdkp->nr_zones = sdkp->capacity >> sdkp->zone_shift;
+ if (sdkp->capacity & (sdkp->zone_blocks - 1))
+ sdkp->nr_zones++;
+
+ if (!sdkp->zones_wlock) {
+ sdkp->zones_wlock = kcalloc(BITS_TO_LONGS(sdkp->nr_zones),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!sdkp->zones_wlock)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int sd_zbc_read_zones(struct scsi_disk *sdkp,
+ unsigned char *buf)
+{
+ sector_t capacity;
+ int ret = 0;
+
+ if (!sd_is_zoned(sdkp))
+ /*
+ * Device managed or normal SCSI disk,
+ * no special handling required
+ */
+ return 0;
+
+
+ /* Get zoned block device characteristics */
+ ret = sd_zbc_read_zoned_characteristics(sdkp, buf);
+ if (ret)
+ goto err;
+
+ /*
+ * Check for unconstrained reads: host-managed devices with
+ * constrained reads (drives failing read after write pointer)
+ * are not supported.
+ */
+ if (!sdkp->urswrz) {
+ if (sdkp->first_scan)
+ sd_printk(KERN_NOTICE, sdkp,
+ "constrained reads devices are not supported\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ /* Check capacity */
+ ret = sd_zbc_check_capacity(sdkp, buf);
+ if (ret)
+ goto err;
+ capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
+
+ /*
+ * Check zone size: only devices with a constant zone size (except
+ * an eventual last runt zone) that is a power of 2 are supported.
+ */
+ ret = sd_zbc_check_zone_size(sdkp);
+ if (ret)
+ goto err;
+
+ /* The drive satisfies the kernel restrictions: set it up */
+ ret = sd_zbc_setup(sdkp);
+ if (ret)
+ goto err;
+
+ /* READ16/WRITE16 is mandatory for ZBC disks */
+ sdkp->device->use_16_for_rw = 1;
+ sdkp->device->use_10_for_rw = 0;
+
+ return 0;
+
+err:
+ sdkp->capacity = 0;
+
+ return ret;
+}
+
+void sd_zbc_remove(struct scsi_disk *sdkp)
+{
+ kfree(sdkp->zones_wlock);
+ sdkp->zones_wlock = NULL;
+}
+
+void sd_zbc_print_zones(struct scsi_disk *sdkp)
+{
+ if (!sd_is_zoned(sdkp) || !sdkp->capacity)
+ return;
+
+ if (sdkp->capacity & (sdkp->zone_blocks - 1))
+ sd_printk(KERN_NOTICE, sdkp,
+ "%u zones of %u logical blocks + 1 runt zone\n",
+ sdkp->nr_zones - 1,
+ sdkp->zone_blocks);
+ else
+ sd_printk(KERN_NOTICE, sdkp,
+ "%u zones of %u logical blocks\n",
+ sdkp->nr_zones,
+ sdkp->zone_blocks);
+}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 618422ea3a41..605887d5ee57 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -546,7 +546,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
return DRIVER_ERROR << 24;
blk_rq_set_block_pc(req);
- req->cmd_flags |= REQ_QUIET;
+ req->rq_flags |= RQF_QUIET;
mdata->null_mapped = 1;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 05c745663c10..cf549871c1ee 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5590,7 +5590,7 @@ ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp)
ret = scsi_execute_req_flags(sdp, cmd, DMA_FROM_DEVICE, buffer,
SCSI_SENSE_BUFFERSIZE, NULL,
- msecs_to_jiffies(1000), 3, NULL, REQ_PM);
+ msecs_to_jiffies(1000), 3, NULL, 0, RQF_PM);
if (ret)
pr_err("%s: failed with err %d\n", __func__, ret);
@@ -5652,11 +5652,11 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
/*
* Current function would be generally called from the power management
- * callbacks hence set the REQ_PM flag so that it doesn't resume the
+ * callbacks hence set the RQF_PM flag so that it doesn't resume the
* already suspended childs.
*/
ret = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
- START_STOP_TIMEOUT, 0, NULL, REQ_PM);
+ START_STOP_TIMEOUT, 0, NULL, 0, RQF_PM);
if (ret) {
sdev_printk(KERN_WARNING, sdp,
"START_STOP failed for power mode: %d, result %x\n",
diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
index e7899624aa0b..35bbe288ddb4 100644
--- a/drivers/sh/intc/virq.c
+++ b/drivers/sh/intc/virq.c
@@ -254,7 +254,7 @@ restart:
radix_tree_tag_clear(&d->tree, entry->enum_id,
INTC_TAG_VIRQ_NEEDS_ALLOC);
- radix_tree_replace_slot((void **)entries[i],
+ radix_tree_replace_slot(&d->tree, (void **)entries[i],
&intc_irq_xlate[irq]);
}
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index e6e90e80519a..f31bceb69c0d 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,8 +1,7 @@
menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/bcm/Kconfig"
-source "drivers/soc/fsl/qbman/Kconfig"
-source "drivers/soc/fsl/qe/Kconfig"
+source "drivers/soc/fsl/Kconfig"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 000000000000..7a9fb9baa66d
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,18 @@
+#
+# Freescale SOC drivers
+#
+
+source "drivers/soc/fsl/qbman/Kconfig"
+source "drivers/soc/fsl/qe/Kconfig"
+
+config FSL_GUTS
+ bool
+ select SOC_BUS
+ help
+ The global utilities block controls power management, I/O device
+ enabling, power-onreset(POR) configuration monitoring, alternate
+ function selection for multiplexed signals,and clock control.
+ This driver is to manage and access global utilities block.
+ Initially only reading SVR and registering soc device are supported.
+ Other guts accesses, such as reading RCW, should eventually be moved
+ into this driver as well.
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 75e1f5334821..44b3bebef24a 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_FSL_DPAA) += qbman/
obj-$(CONFIG_QUICC_ENGINE) += qe/
obj-$(CONFIG_CPM) += qe/
+obj-$(CONFIG_FSL_GUTS) += guts.o
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
new file mode 100644
index 000000000000..6af7a11f09a5
--- /dev/null
+++ b/drivers/soc/fsl/guts.c
@@ -0,0 +1,239 @@
+/*
+ * Freescale QorIQ Platforms GUTS Driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_fdt.h>
+#include <linux/sys_soc.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/fsl/guts.h>
+
+struct guts {
+ struct ccsr_guts __iomem *regs;
+ bool little_endian;
+};
+
+struct fsl_soc_die_attr {
+ char *die;
+ u32 svr;
+ u32 mask;
+};
+
+static struct guts *guts;
+static struct soc_device_attribute soc_dev_attr;
+static struct soc_device *soc_dev;
+
+
+/* SoC die attribute definition for QorIQ platform */
+static const struct fsl_soc_die_attr fsl_soc_die[] = {
+ /*
+ * Power Architecture-based SoCs T Series
+ */
+
+ /* Die: T4240, SoC: T4240/T4160/T4080 */
+ { .die = "T4240",
+ .svr = 0x82400000,
+ .mask = 0xfff00000,
+ },
+ /* Die: T1040, SoC: T1040/T1020/T1042/T1022 */
+ { .die = "T1040",
+ .svr = 0x85200000,
+ .mask = 0xfff00000,
+ },
+ /* Die: T2080, SoC: T2080/T2081 */
+ { .die = "T2080",
+ .svr = 0x85300000,
+ .mask = 0xfff00000,
+ },
+ /* Die: T1024, SoC: T1024/T1014/T1023/T1013 */
+ { .die = "T1024",
+ .svr = 0x85400000,
+ .mask = 0xfff00000,
+ },
+
+ /*
+ * ARM-based SoCs LS Series
+ */
+
+ /* Die: LS1043A, SoC: LS1043A/LS1023A */
+ { .die = "LS1043A",
+ .svr = 0x87920000,
+ .mask = 0xffff0000,
+ },
+ /* Die: LS2080A, SoC: LS2080A/LS2040A/LS2085A */
+ { .die = "LS2080A",
+ .svr = 0x87010000,
+ .mask = 0xff3f0000,
+ },
+ /* Die: LS1088A, SoC: LS1088A/LS1048A/LS1084A/LS1044A */
+ { .die = "LS1088A",
+ .svr = 0x87030000,
+ .mask = 0xff3f0000,
+ },
+ /* Die: LS1012A, SoC: LS1012A */
+ { .die = "LS1012A",
+ .svr = 0x87040000,
+ .mask = 0xffff0000,
+ },
+ /* Die: LS1046A, SoC: LS1046A/LS1026A */
+ { .die = "LS1046A",
+ .svr = 0x87070000,
+ .mask = 0xffff0000,
+ },
+ /* Die: LS2088A, SoC: LS2088A/LS2048A/LS2084A/LS2044A */
+ { .die = "LS2088A",
+ .svr = 0x87090000,
+ .mask = 0xff3f0000,
+ },
+ /* Die: LS1021A, SoC: LS1021A/LS1020A/LS1022A */
+ { .die = "LS1021A",
+ .svr = 0x87000000,
+ .mask = 0xfff70000,
+ },
+ { },
+};
+
+static const struct fsl_soc_die_attr *fsl_soc_die_match(
+ u32 svr, const struct fsl_soc_die_attr *matches)
+{
+ while (matches->svr) {
+ if (matches->svr == (svr & matches->mask))
+ return matches;
+ matches++;
+ };
+ return NULL;
+}
+
+u32 fsl_guts_get_svr(void)
+{
+ u32 svr = 0;
+
+ if (!guts || !guts->regs)
+ return svr;
+
+ if (guts->little_endian)
+ svr = ioread32(&guts->regs->svr);
+ else
+ svr = ioread32be(&guts->regs->svr);
+
+ return svr;
+}
+EXPORT_SYMBOL(fsl_guts_get_svr);
+
+static int fsl_guts_probe(struct platform_device *pdev)
+{
+ struct device_node *root, *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ const struct fsl_soc_die_attr *soc_die;
+ const char *machine;
+ u32 svr;
+
+ /* Initialize guts */
+ guts = devm_kzalloc(dev, sizeof(*guts), GFP_KERNEL);
+ if (!guts)
+ return -ENOMEM;
+
+ guts->little_endian = of_property_read_bool(np, "little-endian");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ guts->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(guts->regs))
+ return PTR_ERR(guts->regs);
+
+ /* Register soc device */
+ root = of_find_node_by_path("/");
+ if (of_property_read_string(root, "model", &machine))
+ of_property_read_string_index(root, "compatible", 0, &machine);
+ of_node_put(root);
+ if (machine)
+ soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
+
+ svr = fsl_guts_get_svr();
+ soc_die = fsl_soc_die_match(svr, fsl_soc_die);
+ if (soc_die) {
+ soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL,
+ "QorIQ %s", soc_die->die);
+ } else {
+ soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, "QorIQ");
+ }
+ soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL,
+ "svr:0x%08x", svr);
+ soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d",
+ (svr >> 4) & 0xf, svr & 0xf);
+
+ soc_dev = soc_device_register(&soc_dev_attr);
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ pr_info("Machine: %s\n", soc_dev_attr.machine);
+ pr_info("SoC family: %s\n", soc_dev_attr.family);
+ pr_info("SoC ID: %s, Revision: %s\n",
+ soc_dev_attr.soc_id, soc_dev_attr.revision);
+ return 0;
+}
+
+static int fsl_guts_remove(struct platform_device *dev)
+{
+ soc_device_unregister(soc_dev);
+ return 0;
+}
+
+/*
+ * Table for matching compatible strings, for device tree
+ * guts node, for Freescale QorIQ SOCs.
+ */
+static const struct of_device_id fsl_guts_of_match[] = {
+ { .compatible = "fsl,qoriq-device-config-1.0", },
+ { .compatible = "fsl,qoriq-device-config-2.0", },
+ { .compatible = "fsl,p1010-guts", },
+ { .compatible = "fsl,p1020-guts", },
+ { .compatible = "fsl,p1021-guts", },
+ { .compatible = "fsl,p1022-guts", },
+ { .compatible = "fsl,p1023-guts", },
+ { .compatible = "fsl,p2020-guts", },
+ { .compatible = "fsl,bsc9131-guts", },
+ { .compatible = "fsl,bsc9132-guts", },
+ { .compatible = "fsl,mpc8536-guts", },
+ { .compatible = "fsl,mpc8544-guts", },
+ { .compatible = "fsl,mpc8548-guts", },
+ { .compatible = "fsl,mpc8568-guts", },
+ { .compatible = "fsl,mpc8569-guts", },
+ { .compatible = "fsl,mpc8572-guts", },
+ { .compatible = "fsl,ls1021a-dcfg", },
+ { .compatible = "fsl,ls1043a-dcfg", },
+ { .compatible = "fsl,ls2080a-dcfg", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
+
+static struct platform_driver fsl_guts_driver = {
+ .driver = {
+ .name = "fsl-guts",
+ .of_match_table = fsl_guts_of_match,
+ },
+ .probe = fsl_guts_probe,
+ .remove = fsl_guts_remove,
+};
+
+static int __init fsl_guts_init(void)
+{
+ return platform_driver_register(&fsl_guts_driver);
+}
+core_initcall(fsl_guts_init);
+
+static void __exit fsl_guts_exit(void)
+{
+ platform_driver_unregister(&fsl_guts_driver);
+}
+module_exit(fsl_guts_exit);
diff --git a/drivers/soc/fsl/qbman/bman_portal.c b/drivers/soc/fsl/qbman/bman_portal.c
index 6579cc18811a..986f64690e6e 100644
--- a/drivers/soc/fsl/qbman/bman_portal.c
+++ b/drivers/soc/fsl/qbman/bman_portal.c
@@ -53,58 +53,38 @@ static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg)
return p;
}
-static void bman_offline_cpu(unsigned int cpu)
+static int bman_offline_cpu(unsigned int cpu)
{
struct bman_portal *p = affine_bportals[cpu];
const struct bm_portal_config *pcfg;
if (!p)
- return;
+ return 0;
pcfg = bman_get_bm_portal_config(p);
if (!pcfg)
- return;
+ return 0;
irq_set_affinity(pcfg->irq, cpumask_of(0));
+ return 0;
}
-static void bman_online_cpu(unsigned int cpu)
+static int bman_online_cpu(unsigned int cpu)
{
struct bman_portal *p = affine_bportals[cpu];
const struct bm_portal_config *pcfg;
if (!p)
- return;
+ return 0;
pcfg = bman_get_bm_portal_config(p);
if (!pcfg)
- return;
+ return 0;
irq_set_affinity(pcfg->irq, cpumask_of(cpu));
+ return 0;
}
-static int bman_hotplug_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- bman_online_cpu(cpu);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- bman_offline_cpu(cpu);
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block bman_hotplug_cpu_notifier = {
- .notifier_call = bman_hotplug_cpu_callback,
-};
-
static int bman_portal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -210,8 +190,14 @@ static int __init bman_portal_driver_register(struct platform_driver *drv)
if (ret < 0)
return ret;
- register_hotcpu_notifier(&bman_hotplug_cpu_notifier);
-
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "soc/qbman_portal:online",
+ bman_online_cpu, bman_offline_cpu);
+ if (ret < 0) {
+ pr_err("bman: failed to register hotplug callbacks.\n");
+ platform_driver_unregister(drv);
+ return ret;
+ }
return 0;
}
diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c
index 148614388fca..d068e4820f49 100644
--- a/drivers/soc/fsl/qbman/qman_portal.c
+++ b/drivers/soc/fsl/qbman/qman_portal.c
@@ -179,7 +179,7 @@ static void qman_portal_update_sdest(const struct qm_portal_config *pcfg,
qman_set_sdest(pcfg->channel, cpu);
}
-static void qman_offline_cpu(unsigned int cpu)
+static int qman_offline_cpu(unsigned int cpu)
{
struct qman_portal *p;
const struct qm_portal_config *pcfg;
@@ -192,9 +192,10 @@ static void qman_offline_cpu(unsigned int cpu)
qman_portal_update_sdest(pcfg, 0);
}
}
+ return 0;
}
-static void qman_online_cpu(unsigned int cpu)
+static int qman_online_cpu(unsigned int cpu)
{
struct qman_portal *p;
const struct qm_portal_config *pcfg;
@@ -207,31 +208,9 @@ static void qman_online_cpu(unsigned int cpu)
qman_portal_update_sdest(pcfg, cpu);
}
}
+ return 0;
}
-static int qman_hotplug_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- qman_online_cpu(cpu);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- qman_offline_cpu(cpu);
- default:
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block qman_hotplug_cpu_notifier = {
- .notifier_call = qman_hotplug_cpu_callback,
-};
-
static int qman_portal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -346,8 +325,14 @@ static int __init qman_portal_driver_register(struct platform_driver *drv)
if (ret < 0)
return ret;
- register_hotcpu_notifier(&qman_hotplug_cpu_notifier);
-
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "soc/qman_portal:online",
+ qman_online_cpu, qman_offline_cpu);
+ if (ret < 0) {
+ pr_err("qman: failed to register hotplug callbacks.\n");
+ platform_driver_unregister(drv);
+ return ret;
+ }
return 0;
}
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 623039c3514c..86cc78cd1962 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -1,3 +1,8 @@
+obj-$(CONFIG_ARCH_RCAR_GEN1) += rcar-rst.o
+obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o
+obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o
+obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o
+
obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o
obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o
obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
new file mode 100644
index 000000000000..a6d1c26d3167
--- /dev/null
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -0,0 +1,92 @@
+/*
+ * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver
+ *
+ * Copyright (C) 2016 Glider bvba
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+struct rst_config {
+ unsigned int modemr; /* Mode Monitoring Register Offset */
+};
+
+static const struct rst_config rcar_rst_gen1 __initconst = {
+ .modemr = 0x20,
+};
+
+static const struct rst_config rcar_rst_gen2 __initconst = {
+ .modemr = 0x60,
+};
+
+static const struct of_device_id rcar_rst_matches[] __initconst = {
+ /* RZ/G is handled like R-Car Gen2 */
+ { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
+ /* R-Car Gen1 */
+ { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
+ { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
+ /* R-Car Gen2 */
+ { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 },
+ /* R-Car Gen3 is handled like R-Car Gen2 */
+ { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 },
+ { /* sentinel */ }
+};
+
+static void __iomem *rcar_rst_base __initdata;
+static u32 saved_mode __initdata;
+
+static int __init rcar_rst_init(void)
+{
+ const struct of_device_id *match;
+ const struct rst_config *cfg;
+ struct device_node *np;
+ void __iomem *base;
+ int error = 0;
+
+ np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match);
+ if (!np)
+ return -ENODEV;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("%s: Cannot map regs\n", np->full_name);
+ error = -ENOMEM;
+ goto out_put;
+ }
+
+ rcar_rst_base = base;
+ cfg = match->data;
+ saved_mode = ioread32(base + cfg->modemr);
+
+ pr_debug("%s: MODE = 0x%08x\n", np->full_name, saved_mode);
+
+out_put:
+ of_node_put(np);
+ return error;
+}
+
+int __init rcar_rst_read_mode_pins(u32 *mode)
+{
+ int error;
+
+ if (!rcar_rst_base) {
+ error = rcar_rst_init();
+ if (error)
+ return error;
+ }
+
+ *mode = saved_mode;
+ return 0;
+}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 0f28c08fcb3c..77b551da5728 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -909,6 +909,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
if (err) {
ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
err);
+ goto out_free;
} else {
ssb_dbg("Using SPROM revision %d provided by platform\n",
sprom->revision);
diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h
index f8be0e2f7bf7..8ca1e9d0cfe2 100644
--- a/drivers/staging/lustre/include/linux/lnet/types.h
+++ b/drivers/staging/lustre/include/linux/lnet/types.h
@@ -34,6 +34,7 @@
#define __LNET_TYPES_H__
#include <linux/types.h>
+#include <linux/bvec.h>
/** \addtogroup lnet
* @{
diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
index 50c0152ba022..76a6836cdf70 100644
--- a/drivers/staging/lustre/lustre/llite/rw.c
+++ b/drivers/staging/lustre/lustre/llite/rw.c
@@ -47,6 +47,7 @@
#include <linux/pagemap.h>
/* current_is_kswapd() */
#include <linux/swap.h>
+#include <linux/bvec.h>
#define DEBUG_SUBSYSTEM S_LLITE
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index d02e3e31ed29..8130dfe89745 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -259,17 +259,6 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu)
#endif
int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes;
- /*
- * Limit the MTU to make sure the ethernet packets are between
- * 64 bytes and 65535 bytes.
- */
- if ((new_mtu + mtu_overhead < VLAN_ETH_ZLEN) ||
- (new_mtu + mtu_overhead > OCTEON_MAX_MTU)) {
- pr_err("MTU must be between %d and %d.\n",
- VLAN_ETH_ZLEN - mtu_overhead,
- OCTEON_MAX_MTU - mtu_overhead);
- return -EINVAL;
- }
dev->mtu = new_mtu;
if ((interface < 2) &&
@@ -457,7 +446,7 @@ int cvm_oct_common_init(struct net_device *dev)
dev->ethtool_ops = &cvm_oct_ethtool_ops;
cvm_oct_set_mac_filter(dev);
- dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
+ dev_set_mtu(dev, dev->mtu);
/*
* Zero out stats for port so we won't mistakenly show
@@ -685,6 +674,11 @@ static int cvm_oct_probe(struct platform_device *pdev)
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos;
struct device_node *pip;
+ int mtu_overhead = ETH_HLEN + ETH_FCS_LEN;
+
+#if IS_ENABLED(CONFIG_VLAN_8021Q)
+ mtu_overhead += VLAN_HLEN;
+#endif
octeon_mdiobus_force_mod_depencency();
@@ -783,6 +777,8 @@ static int cvm_oct_probe(struct platform_device *pdev)
strcpy(dev->name, "pow%d");
for (qos = 0; qos < 16; qos++)
skb_queue_head_init(&priv->tx_free_list[qos]);
+ dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead;
+ dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead;
if (register_netdev(dev) < 0) {
pr_err("Failed to register ethernet device for POW\n");
@@ -836,6 +832,8 @@ static int cvm_oct_probe(struct platform_device *pdev)
for (qos = 0; qos < cvmx_pko_get_num_queues(port);
qos++)
cvmx_fau_atomic_write32(priv->fau + qos * 4, 0);
+ dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead;
+ dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead;
switch (priv->imode) {
/* These types don't support ports to IPD/PKO */
diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c
index d976e5e18d50..c9c9821cfc32 100644
--- a/drivers/staging/rtl8188eu/os_dep/mon.c
+++ b/drivers/staging/rtl8188eu/os_dep/mon.c
@@ -145,7 +145,6 @@ static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
static const struct net_device_ops mon_netdev_ops = {
.ndo_start_xmit = mon_xmit,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 4c30eea45f89..5f53fbd565ef 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2545,7 +2545,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_set_rx_mode = _rtl92e_set_multicast,
.ndo_set_mac_address = _rtl92e_set_mac_adr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_start_xmit = rtllib_xmit,
};
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 457eeb5f5239..fdb03dccb449 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -4930,7 +4930,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_set_rx_mode = r8192_set_multicast,
.ndo_set_mac_address = r8192_set_mac_adr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_start_xmit = ieee80211_xmit,
};
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 062307ad7fed..2802b900f8ee 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -2880,7 +2880,6 @@ static const struct net_device_ops slic_netdev_ops = {
.ndo_get_stats = slic_get_stats,
.ndo_set_rx_mode = slic_mcast_set_list,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static u32 slic_card_locate(struct adapter *adapter)
diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h
index cba4433bcd51..9081b3f8779c 100644
--- a/drivers/staging/unisys/include/iochannel.h
+++ b/drivers/staging/unisys/include/iochannel.h
@@ -113,12 +113,10 @@ enum net_types {
};
-#define ETH_HEADER_SIZE 14 /* size of ethernet header */
-
#define ETH_MIN_DATA_SIZE 46 /* minimum eth data size */
-#define ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE)
+#define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE)
-#define ETH_MAX_MTU 16384 /* maximum data size */
+#define VISOR_ETH_MAX_MTU 16384 /* maximum data size */
#ifndef MAX_MACADDR_LEN
#define MAX_MACADDR_LEN 6 /* number of bytes in MAC address */
@@ -288,7 +286,7 @@ 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 */
- char ethhdr[ETH_HEADER_SIZE]; /* the ethernet header */
+ char ethhdr[ETH_HLEN]; /* the ethernet header */
struct {
/* these are needed for csum at uisnic end */
u8 valid; /* 1 = struct is valid - else ignore */
@@ -323,7 +321,7 @@ struct net_pkt_xmtdone {
*/
#define RCVPOST_BUF_SIZE 4032
#define MAX_NET_RCV_CHAIN \
- ((ETH_MAX_MTU + ETH_HEADER_SIZE + RCVPOST_BUF_SIZE - 1) \
+ ((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \
/ RCVPOST_BUF_SIZE)
struct net_pkt_rcvpost {
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 136700756485..f8a584bf4a77 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -791,7 +791,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
* pointing to
*/
firstfraglen = skb->len - skb->data_len;
- if (firstfraglen < ETH_HEADER_SIZE) {
+ if (firstfraglen < ETH_HLEN) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
dev_err(&netdev->dev,
@@ -864,7 +864,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
/* copy ethernet header from first frag into ocmdrsp
* - everything else will be pass in frags & DMA'ed
*/
- memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HEADER_SIZE);
+ memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HLEN);
/* copy frags info - from skb->data we need to only provide access
* beyond eth header
*/
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 5dd430f8f921..d84dffb894f4 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -47,7 +47,7 @@ static const char driver_name[] = "vme_user";
static int bus[VME_USER_BUS_MAX];
static unsigned int bus_num;
-/* Currently Documentation/devices.txt defines the following for VME:
+/* Currently Documentation/admin-guide/devices.rst defines the following for VME:
*
* 221 char VME bus
* 0 = /dev/bus/vme/m0 First master image
diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c
index 242f82f4d24f..f328d75de0d1 100644
--- a/drivers/staging/wilc1000/linux_mon.c
+++ b/drivers/staging/wilc1000/linux_mon.c
@@ -111,7 +111,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size)
}
skb->dev = wilc_wfi_mon;
- skb_set_mac_header(skb, 0);
+ skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_802_2);
@@ -215,7 +215,7 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
cb_hdr->tx_flags = 0x0004;
skb2->dev = wilc_wfi_mon;
- skb_set_mac_header(skb2, 0);
+ skb_reset_mac_header(skb2);
skb2->ip_summed = CHECKSUM_UNNECESSARY;
skb2->pkt_type = PACKET_OTHERHOST;
skb2->protocol = htons(ETH_P_802_2);
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 825a63a7c0e3..4762d38a720e 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -669,18 +669,6 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr)
return result;
}
-static int wlan_change_mtu(struct net_device *dev, int new_mtu)
-{
- /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap)
- and another 8 for wep. */
- if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8)))
- return -EINVAL;
-
- dev->mtu = new_mtu;
-
- return 0;
-}
-
static const struct net_device_ops p80211_netdev_ops = {
.ndo_init = p80211knetdev_init,
.ndo_open = p80211knetdev_open,
@@ -690,7 +678,6 @@ static const struct net_device_ops p80211_netdev_ops = {
.ndo_do_ioctl = p80211knetdev_do_ioctl,
.ndo_set_mac_address = p80211knetdev_set_mac_address,
.ndo_tx_timeout = p80211knetdev_tx_timeout,
- .ndo_change_mtu = wlan_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -756,6 +743,11 @@ int wlan_setup(struct wlandevice *wlandev, struct device *physdev)
wdev->wiphy = wiphy;
wdev->iftype = NL80211_IFTYPE_STATION;
netdev->ieee80211_ptr = wdev;
+ netdev->min_mtu = 68;
+ /* 2312 is max 802.11 payload, 20 is overhead,
+ * (ether + llc + snap) and another 8 for wep.
+ */
+ netdev->max_mtu = (2312 - 20 - 8);
netif_stop_queue(netdev);
netif_carrier_off(netdev);
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c
index ad26b9372f10..96eedfc49c94 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_main.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c
@@ -653,6 +653,7 @@ static struct iscsit_transport cxgbit_transport = {
static struct cxgb4_uld_info cxgbit_uld_info = {
.name = DRV_NAME,
.nrxq = MAX_ULD_QSETS,
+ .ntxq = MAX_ULD_QSETS,
.rxq_size = 1024,
.lro = true,
.add = cxgbit_uld_add,
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 372d744315f3..d316ed537d59 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -388,7 +388,7 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
bio = bio_alloc(GFP_KERNEL, 0);
bio->bi_end_io = iblock_end_io_flush;
bio->bi_bdev = ib_dev->ibd_bd;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
if (!immed)
bio->bi_private = cmd;
submit_bio(bio);
@@ -686,15 +686,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
struct request_queue *q = bdev_get_queue(ib_dev->ibd_bd);
/*
- * Force writethrough using WRITE_FUA if a volatile write cache
+ * Force writethrough using REQ_FUA if a volatile write cache
* is not enabled, or if initiator set the Force Unit Access bit.
*/
op = REQ_OP_WRITE;
if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) {
if (cmd->se_cmd_flags & SCF_FUA)
- op_flags = WRITE_FUA;
+ op_flags = REQ_FUA;
else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags))
- op_flags = WRITE_FUA;
+ op_flags = REQ_FUA;
}
} else {
op = REQ_OP_READ;
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 9125d9358dea..04d7aa7390d0 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -935,13 +935,9 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
rc = bio_add_pc_page(pdv->pdv_sd->request_queue,
bio, page, bytes, off);
- if (rc != bytes)
- goto fail;
-
pr_debug("PSCSI: bio->bi_vcnt: %d nr_vecs: %d\n",
- bio->bi_vcnt, nr_vecs);
-
- if (bio->bi_vcnt > nr_vecs) {
+ bio_segments(bio), nr_vecs);
+ if (rc != bytes) {
pr_debug("PSCSI: Reached bio->bi_vcnt max:"
" %d i: %d bio: %p, allocating another"
" bio\n", bio->bi_vcnt, i, bio);
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 47562509b489..2b3c8564ace8 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -147,8 +147,8 @@ static const struct genl_multicast_group tcmu_mcgrps[] = {
};
/* Our generic netlink family */
-static struct genl_family tcmu_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family tcmu_genl_family __ro_after_init = {
+ .module = THIS_MODULE,
.hdrsize = 0,
.name = "TCM-USER",
.version = 1,
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index a13541bdc726..c2c056cc7ea5 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -177,8 +177,10 @@ config THERMAL_EMULATION
config HISI_THERMAL
tristate "Hisilicon thermal driver"
- depends on (ARCH_HISI && CPU_THERMAL && OF) || COMPILE_TEST
+ depends on ARCH_HISI || COMPILE_TEST
depends on HAS_IOMEM
+ depends on OF
+ default y
help
Enable this to plug hisilicon's thermal sensor driver into the Linux
thermal framework. cpufreq is used as the cooling device to throttle
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c92eb22a41ff..6a3d7b573036 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,7 +3,8 @@
#
obj-$(CONFIG_THERMAL) += thermal_sys.o
-thermal_sys-y += thermal_core.o
+thermal_sys-y += thermal_core.o thermal_sysfs.o \
+ thermal_helpers.o
# interface to/from other layers providing sensors
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index e776cea80cfc..f491faf16592 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -512,6 +512,7 @@ static const struct of_device_id db8500_thermal_match[] = {
{ .compatible = "stericsson,db8500-thermal" },
{},
};
+MODULE_DEVICE_TABLE(of, db8500_thermal_match);
#endif
static struct platform_driver db8500_thermal_driver = {
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
index 81631b110e17..5a737fd5f1aa 100644
--- a/drivers/thermal/devfreq_cooling.c
+++ b/drivers/thermal/devfreq_cooling.c
@@ -238,7 +238,7 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
return 0;
}
- return dfc->power_ops->get_static_power(voltage);
+ return dfc->power_ops->get_static_power(df, voltage);
}
/**
@@ -262,7 +262,8 @@ get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,
struct devfreq_cooling_power *dfc_power = dfc->power_ops;
if (dfc_power->get_dynamic_power)
- return dfc_power->get_dynamic_power(freq, voltage);
+ return dfc_power->get_dynamic_power(dfc->devfreq, freq,
+ voltage);
freq_mhz = freq / 1000000;
power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage;
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
index 5836e5554433..9413c4abf0b9 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
@@ -96,7 +96,7 @@ static ssize_t current_uuid_store(struct device *dev,
return -EINVAL;
}
-static DEVICE_ATTR(current_uuid, 0644, current_uuid_show, current_uuid_store);
+static DEVICE_ATTR_RW(current_uuid);
static DEVICE_ATTR_RO(available_uuids);
static struct attribute *uuid_attrs[] = {
&dev_attr_available_uuids.attr,
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c
index 19bf2028e508..2b49e8d0fe9e 100644
--- a/drivers/thermal/intel_pch_thermal.c
+++ b/drivers/thermal/intel_pch_thermal.c
@@ -29,6 +29,7 @@
#define PCH_THERMAL_DID_HSW_2 0x8C24 /* Haswell PCH */
#define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */
#define PCH_THERMAL_DID_SKL 0x9D31 /* Skylake PCH */
+#define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */
/* Wildcat Point-LP PCH Thermal registers */
#define WPT_TEMP 0x0000 /* Temperature */
@@ -273,37 +274,44 @@ static struct thermal_zone_device_ops tzd_ops = {
.get_trip_temp = pch_get_trip_temp,
};
+enum board_ids {
+ board_hsw,
+ board_wpt,
+ board_skl,
+};
+
+static const struct board_info {
+ const char *name;
+ const struct pch_dev_ops *ops;
+} board_info[] = {
+ [board_hsw] = {
+ .name = "pch_haswell",
+ .ops = &pch_dev_ops_wpt,
+ },
+ [board_wpt] = {
+ .name = "pch_wildcat_point",
+ .ops = &pch_dev_ops_wpt,
+ },
+ [board_skl] = {
+ .name = "pch_skylake",
+ .ops = &pch_dev_ops_wpt,
+ },
+};
static int intel_pch_thermal_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
+ enum board_ids board_id = id->driver_data;
+ const struct board_info *bi = &board_info[board_id];
struct pch_thermal_device *ptd;
int err;
int nr_trips;
- char *dev_name;
ptd = devm_kzalloc(&pdev->dev, sizeof(*ptd), GFP_KERNEL);
if (!ptd)
return -ENOMEM;
- switch (pdev->device) {
- case PCH_THERMAL_DID_WPT:
- ptd->ops = &pch_dev_ops_wpt;
- dev_name = "pch_wildcat_point";
- break;
- case PCH_THERMAL_DID_SKL:
- ptd->ops = &pch_dev_ops_wpt;
- dev_name = "pch_skylake";
- break;
- case PCH_THERMAL_DID_HSW_1:
- case PCH_THERMAL_DID_HSW_2:
- ptd->ops = &pch_dev_ops_wpt;
- dev_name = "pch_haswell";
- break;
- default:
- dev_err(&pdev->dev, "unknown pch thermal device\n");
- return -ENODEV;
- }
+ ptd->ops = bi->ops;
pci_set_drvdata(pdev, ptd);
ptd->pdev = pdev;
@@ -331,11 +339,11 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev,
if (err)
goto error_cleanup;
- ptd->tzd = thermal_zone_device_register(dev_name, nr_trips, 0, ptd,
+ ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd,
&tzd_ops, NULL, 0, 0);
if (IS_ERR(ptd->tzd)) {
dev_err(&pdev->dev, "Failed to register thermal zone %s\n",
- dev_name);
+ bi->name);
err = PTR_ERR(ptd->tzd);
goto error_cleanup;
}
@@ -380,10 +388,16 @@ static int intel_pch_thermal_resume(struct device *device)
}
static struct pci_device_id intel_pch_thermal_id[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1),
+ .driver_data = board_hsw, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2),
+ .driver_data = board_hsw, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT),
+ .driver_data = board_wpt, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL),
+ .driver_data = board_skl, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H),
+ .driver_data = board_skl, },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c
index afada655f861..df64692e9e64 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel_powerclamp.c
@@ -43,7 +43,6 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/kthread.h>
-#include <linux/freezer.h>
#include <linux/cpu.h>
#include <linux/thermal.h>
#include <linux/slab.h>
@@ -56,7 +55,6 @@
#include <asm/msr.h>
#include <asm/mwait.h>
#include <asm/cpu_device_id.h>
-#include <asm/idle.h>
#include <asm/hardirq.h>
#define MAX_TARGET_RATIO (50U)
@@ -86,11 +84,26 @@ static unsigned int control_cpu; /* The cpu assigned to collect stat and update
*/
static bool clamping;
+static const struct sched_param sparam = {
+ .sched_priority = MAX_USER_RT_PRIO / 2,
+};
+struct powerclamp_worker_data {
+ struct kthread_worker *worker;
+ struct kthread_work balancing_work;
+ struct kthread_delayed_work idle_injection_work;
+ unsigned int cpu;
+ unsigned int count;
+ unsigned int guard;
+ unsigned int window_size_now;
+ unsigned int target_ratio;
+ unsigned int duration_jiffies;
+ bool clamping;
+};
-static struct task_struct * __percpu *powerclamp_thread;
+static struct powerclamp_worker_data * __percpu worker_data;
static struct thermal_cooling_device *cooling_dev;
static unsigned long *cpu_clamping_mask; /* bit map for tracking per cpu
- * clamping thread
+ * clamping kthread worker
*/
static unsigned int duration;
@@ -262,11 +275,6 @@ static u64 pkg_state_counter(void)
return count;
}
-static void noop_timer(unsigned long foo)
-{
- /* empty... just the fact that we get the interrupt wakes us up */
-}
-
static unsigned int get_compensation(int ratio)
{
unsigned int comp = 0;
@@ -368,103 +376,79 @@ static bool powerclamp_adjust_controls(unsigned int target_ratio,
return set_target_ratio + guard <= current_ratio;
}
-static int clamp_thread(void *arg)
+static void clamp_balancing_func(struct kthread_work *work)
{
- int cpunr = (unsigned long)arg;
- DEFINE_TIMER(wakeup_timer, noop_timer, 0, 0);
- static const struct sched_param param = {
- .sched_priority = MAX_USER_RT_PRIO/2,
- };
- unsigned int count = 0;
- unsigned int target_ratio;
+ struct powerclamp_worker_data *w_data;
+ int sleeptime;
+ unsigned long target_jiffies;
+ unsigned int compensated_ratio;
+ int interval; /* jiffies to sleep for each attempt */
- set_bit(cpunr, cpu_clamping_mask);
- set_freezable();
- init_timer_on_stack(&wakeup_timer);
- sched_setscheduler(current, SCHED_FIFO, &param);
-
- while (true == clamping && !kthread_should_stop() &&
- cpu_online(cpunr)) {
- int sleeptime;
- unsigned long target_jiffies;
- unsigned int guard;
- unsigned int compensated_ratio;
- int interval; /* jiffies to sleep for each attempt */
- unsigned int duration_jiffies = msecs_to_jiffies(duration);
- unsigned int window_size_now;
-
- try_to_freeze();
- /*
- * make sure user selected ratio does not take effect until
- * the next round. adjust target_ratio if user has changed
- * target such that we can converge quickly.
- */
- target_ratio = set_target_ratio;
- guard = 1 + target_ratio/20;
- window_size_now = window_size;
- count++;
-
- /*
- * systems may have different ability to enter package level
- * c-states, thus we need to compensate the injected idle ratio
- * to achieve the actual target reported by the HW.
- */
- compensated_ratio = target_ratio +
- get_compensation(target_ratio);
- if (compensated_ratio <= 0)
- compensated_ratio = 1;
- interval = duration_jiffies * 100 / compensated_ratio;
-
- /* align idle time */
- target_jiffies = roundup(jiffies, interval);
- sleeptime = target_jiffies - jiffies;
- if (sleeptime <= 0)
- sleeptime = 1;
- schedule_timeout_interruptible(sleeptime);
- /*
- * only elected controlling cpu can collect stats and update
- * control parameters.
- */
- if (cpunr == control_cpu && !(count%window_size_now)) {
- should_skip =
- powerclamp_adjust_controls(target_ratio,
- guard, window_size_now);
- smp_mb();
- }
+ w_data = container_of(work, struct powerclamp_worker_data,
+ balancing_work);
- if (should_skip)
- continue;
-
- target_jiffies = jiffies + duration_jiffies;
- mod_timer(&wakeup_timer, target_jiffies);
- if (unlikely(local_softirq_pending()))
- continue;
- /*
- * stop tick sched during idle time, interrupts are still
- * allowed. thus jiffies are updated properly.
- */
- preempt_disable();
- /* mwait until target jiffies is reached */
- while (time_before(jiffies, target_jiffies)) {
- unsigned long ecx = 1;
- unsigned long eax = target_mwait;
-
- /*
- * REVISIT: may call enter_idle() to notify drivers who
- * can save power during cpu idle. same for exit_idle()
- */
- local_touch_nmi();
- stop_critical_timings();
- mwait_idle_with_hints(eax, ecx);
- start_critical_timings();
- atomic_inc(&idle_wakeup_counter);
- }
- preempt_enable();
+ /*
+ * make sure user selected ratio does not take effect until
+ * the next round. adjust target_ratio if user has changed
+ * target such that we can converge quickly.
+ */
+ w_data->target_ratio = READ_ONCE(set_target_ratio);
+ w_data->guard = 1 + w_data->target_ratio / 20;
+ w_data->window_size_now = window_size;
+ w_data->duration_jiffies = msecs_to_jiffies(duration);
+ w_data->count++;
+
+ /*
+ * systems may have different ability to enter package level
+ * c-states, thus we need to compensate the injected idle ratio
+ * to achieve the actual target reported by the HW.
+ */
+ compensated_ratio = w_data->target_ratio +
+ get_compensation(w_data->target_ratio);
+ if (compensated_ratio <= 0)
+ compensated_ratio = 1;
+ interval = w_data->duration_jiffies * 100 / compensated_ratio;
+
+ /* align idle time */
+ target_jiffies = roundup(jiffies, interval);
+ sleeptime = target_jiffies - jiffies;
+ if (sleeptime <= 0)
+ sleeptime = 1;
+
+ if (clamping && w_data->clamping && cpu_online(w_data->cpu))
+ kthread_queue_delayed_work(w_data->worker,
+ &w_data->idle_injection_work,
+ sleeptime);
+}
+
+static void clamp_idle_injection_func(struct kthread_work *work)
+{
+ struct powerclamp_worker_data *w_data;
+
+ w_data = container_of(work, struct powerclamp_worker_data,
+ idle_injection_work.work);
+
+ /*
+ * only elected controlling cpu can collect stats and update
+ * control parameters.
+ */
+ if (w_data->cpu == control_cpu &&
+ !(w_data->count % w_data->window_size_now)) {
+ should_skip =
+ powerclamp_adjust_controls(w_data->target_ratio,
+ w_data->guard,
+ w_data->window_size_now);
+ smp_mb();
}
- del_timer_sync(&wakeup_timer);
- clear_bit(cpunr, cpu_clamping_mask);
- return 0;
+ if (should_skip)
+ goto balance;
+
+ play_idle(jiffies_to_msecs(w_data->duration_jiffies));
+
+balance:
+ if (clamping && w_data->clamping && cpu_online(w_data->cpu))
+ kthread_queue_work(w_data->worker, &w_data->balancing_work);
}
/*
@@ -508,10 +492,60 @@ static void poll_pkg_cstate(struct work_struct *dummy)
schedule_delayed_work(&poll_pkg_cstate_work, HZ);
}
+static void start_power_clamp_worker(unsigned long cpu)
+{
+ struct powerclamp_worker_data *w_data = per_cpu_ptr(worker_data, cpu);
+ struct kthread_worker *worker;
+
+ worker = kthread_create_worker_on_cpu(cpu, 0, "kidle_inject/%ld", cpu);
+ if (IS_ERR(worker))
+ return;
+
+ w_data->worker = worker;
+ w_data->count = 0;
+ w_data->cpu = cpu;
+ w_data->clamping = true;
+ set_bit(cpu, cpu_clamping_mask);
+ sched_setscheduler(worker->task, SCHED_FIFO, &sparam);
+ kthread_init_work(&w_data->balancing_work, clamp_balancing_func);
+ kthread_init_delayed_work(&w_data->idle_injection_work,
+ clamp_idle_injection_func);
+ kthread_queue_work(w_data->worker, &w_data->balancing_work);
+}
+
+static void stop_power_clamp_worker(unsigned long cpu)
+{
+ struct powerclamp_worker_data *w_data = per_cpu_ptr(worker_data, cpu);
+
+ if (!w_data->worker)
+ return;
+
+ w_data->clamping = false;
+ /*
+ * Make sure that all works that get queued after this point see
+ * the clamping disabled. The counter part is not needed because
+ * there is an implicit memory barrier when the queued work
+ * is proceed.
+ */
+ smp_wmb();
+ kthread_cancel_work_sync(&w_data->balancing_work);
+ kthread_cancel_delayed_work_sync(&w_data->idle_injection_work);
+ /*
+ * The balancing work still might be queued here because
+ * the handling of the "clapming" variable, cancel, and queue
+ * operations are not synchronized via a lock. But it is not
+ * a big deal. The balancing work is fast and destroy kthread
+ * will wait for it.
+ */
+ clear_bit(w_data->cpu, cpu_clamping_mask);
+ kthread_destroy_worker(w_data->worker);
+
+ w_data->worker = NULL;
+}
+
static int start_power_clamp(void)
{
unsigned long cpu;
- struct task_struct *thread;
set_target_ratio = clamp(set_target_ratio, 0U, MAX_TARGET_RATIO - 1);
/* prevent cpu hotplug */
@@ -525,22 +559,9 @@ static int start_power_clamp(void)
clamping = true;
schedule_delayed_work(&poll_pkg_cstate_work, 0);
- /* start one thread per online cpu */
+ /* start one kthread worker per online cpu */
for_each_online_cpu(cpu) {
- struct task_struct **p =
- per_cpu_ptr(powerclamp_thread, cpu);
-
- thread = kthread_create_on_node(clamp_thread,
- (void *) cpu,
- cpu_to_node(cpu),
- "kidle_inject/%ld", cpu);
- /* bind to cpu here */
- if (likely(!IS_ERR(thread))) {
- kthread_bind(thread, cpu);
- wake_up_process(thread);
- *p = thread;
- }
-
+ start_power_clamp_worker(cpu);
}
put_online_cpus();
@@ -550,71 +571,49 @@ static int start_power_clamp(void)
static void end_power_clamp(void)
{
int i;
- struct task_struct *thread;
- clamping = false;
/*
- * make clamping visible to other cpus and give per cpu clamping threads
- * sometime to exit, or gets killed later.
+ * Block requeuing in all the kthread workers. They will flush and
+ * stop faster.
*/
- smp_mb();
- msleep(20);
+ clamping = false;
if (bitmap_weight(cpu_clamping_mask, num_possible_cpus())) {
for_each_set_bit(i, cpu_clamping_mask, num_possible_cpus()) {
- pr_debug("clamping thread for cpu %d alive, kill\n", i);
- thread = *per_cpu_ptr(powerclamp_thread, i);
- kthread_stop(thread);
+ pr_debug("clamping worker for cpu %d alive, destroy\n",
+ i);
+ stop_power_clamp_worker(i);
}
}
}
-static int powerclamp_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static int powerclamp_cpu_online(unsigned int cpu)
{
- unsigned long cpu = (unsigned long)hcpu;
- struct task_struct *thread;
- struct task_struct **percpu_thread =
- per_cpu_ptr(powerclamp_thread, cpu);
-
- if (false == clamping)
- goto exit_ok;
-
- switch (action) {
- case CPU_ONLINE:
- thread = kthread_create_on_node(clamp_thread,
- (void *) cpu,
- cpu_to_node(cpu),
- "kidle_inject/%lu", cpu);
- if (likely(!IS_ERR(thread))) {
- kthread_bind(thread, cpu);
- wake_up_process(thread);
- *percpu_thread = thread;
- }
- /* prefer BSP as controlling CPU */
- if (cpu == 0) {
- control_cpu = 0;
- smp_mb();
- }
- break;
- case CPU_DEAD:
- if (test_bit(cpu, cpu_clamping_mask)) {
- pr_err("cpu %lu dead but powerclamping thread is not\n",
- cpu);
- kthread_stop(*percpu_thread);
- }
- if (cpu == control_cpu) {
- control_cpu = smp_processor_id();
- smp_mb();
- }
+ if (clamping == false)
+ return 0;
+ start_power_clamp_worker(cpu);
+ /* prefer BSP as controlling CPU */
+ if (cpu == 0) {
+ control_cpu = 0;
+ smp_mb();
}
-
-exit_ok:
- return NOTIFY_OK;
+ return 0;
}
-static struct notifier_block powerclamp_cpu_notifier = {
- .notifier_call = powerclamp_cpu_callback,
-};
+static int powerclamp_cpu_predown(unsigned int cpu)
+{
+ if (clamping == false)
+ return 0;
+
+ stop_power_clamp_worker(cpu);
+ if (cpu != control_cpu)
+ return 0;
+
+ control_cpu = cpumask_first(cpu_online_mask);
+ if (control_cpu == cpu)
+ control_cpu = cpumask_next(cpu, cpu_online_mask);
+ smp_mb();
+ return 0;
+}
static int powerclamp_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
@@ -742,6 +741,8 @@ file_error:
debugfs_remove_recursive(debug_dir);
}
+static enum cpuhp_state hp_state;
+
static int __init powerclamp_init(void)
{
int retval;
@@ -759,10 +760,17 @@ static int __init powerclamp_init(void)
/* set default limit, maybe adjusted during runtime based on feedback */
window_size = 2;
- register_hotcpu_notifier(&powerclamp_cpu_notifier);
+ retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "thermal/intel_powerclamp:online",
+ powerclamp_cpu_online,
+ powerclamp_cpu_predown);
+ if (retval < 0)
+ goto exit_free;
+
+ hp_state = retval;
- powerclamp_thread = alloc_percpu(struct task_struct *);
- if (!powerclamp_thread) {
+ worker_data = alloc_percpu(struct powerclamp_worker_data);
+ if (!worker_data) {
retval = -ENOMEM;
goto exit_unregister;
}
@@ -782,9 +790,9 @@ static int __init powerclamp_init(void)
return 0;
exit_free_thread:
- free_percpu(powerclamp_thread);
+ free_percpu(worker_data);
exit_unregister:
- unregister_hotcpu_notifier(&powerclamp_cpu_notifier);
+ cpuhp_remove_state_nocalls(hp_state);
exit_free:
kfree(cpu_clamping_mask);
return retval;
@@ -793,9 +801,9 @@ module_init(powerclamp_init);
static void __exit powerclamp_exit(void)
{
- unregister_hotcpu_notifier(&powerclamp_cpu_notifier);
end_power_clamp();
- free_percpu(powerclamp_thread);
+ cpuhp_remove_state_nocalls(hp_state);
+ free_percpu(worker_data);
thermal_cooling_device_unregister(cooling_dev);
kfree(cpu_clamping_mask);
diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c
index 83905ff46e40..e9a1fe342760 100644
--- a/drivers/thermal/max77620_thermal.c
+++ b/drivers/thermal/max77620_thermal.c
@@ -149,6 +149,7 @@ static struct platform_device_id max77620_thermal_devtype[] = {
{ .name = "max77620-thermal", },
{},
};
+MODULE_DEVICE_TABLE(platform, max77620_thermal_devtype);
static struct platform_driver max77620_thermal_driver = {
.driver = {
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c
index 819c6d5d7aa7..f50241962ad2 100644
--- a/drivers/thermal/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom-spmi-temp-alarm.c
@@ -200,7 +200,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
struct qpnp_tm_chip *chip;
struct device_node *node;
u8 type, subtype;
- u32 res[2];
+ u32 res;
int ret, irq;
node = pdev->dev.of_node;
@@ -215,7 +215,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
if (!chip->map)
return -ENXIO;
- ret = of_property_read_u32_array(node, "reg", res, 2);
+ ret = of_property_read_u32(node, "reg", &res);
if (ret < 0)
return ret;
@@ -228,7 +228,7 @@ static int qpnp_tm_probe(struct platform_device *pdev)
if (PTR_ERR(chip->adc) == -EPROBE_DEFER)
return PTR_ERR(chip->adc);
- chip->base = res[0];
+ chip->base = res;
ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type);
if (ret < 0) {
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index e227a9f0acf7..b811b0fb61b1 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -524,11 +524,6 @@ static void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs,
regs + TSADCV2_AUTO_PERIOD_HT);
writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
-
- if (IS_ERR(grf)) {
- pr_warn("%s: Missing rockchip,grf property\n", __func__);
- return;
- }
}
/**
@@ -971,6 +966,8 @@ static int rockchip_configure_from_dt(struct device *dev,
* need this property.
*/
thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+ if (IS_ERR(thermal->grf))
+ dev_warn(dev, "Missing rockchip,grf property\n");
return 0;
}
diff --git a/drivers/thermal/tango_thermal.c b/drivers/thermal/tango_thermal.c
index 201304aeafeb..4e67795cb6ce 100644
--- a/drivers/thermal/tango_thermal.c
+++ b/drivers/thermal/tango_thermal.c
@@ -107,6 +107,7 @@ static const struct of_device_id tango_sensor_ids[] = {
},
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, tango_sensor_ids);
static struct platform_driver tango_thermal_driver = {
.probe = tango_thermal_probe,
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 226b0b4aced6..641faab6e24b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -5,22 +5,9 @@
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; 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.
- *
- * 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
@@ -64,6 +51,13 @@ static atomic_t in_suspend;
static struct thermal_governor *def_governor;
+/*
+ * Governor section: set of functions to handle thermal governors
+ *
+ * Functions to help in the life cycle of thermal governors within
+ * the thermal core and by the thermal governor code.
+ */
+
static struct thermal_governor *__find_governor(const char *name)
{
struct thermal_governor *pos;
@@ -142,11 +136,16 @@ int thermal_register_governor(struct thermal_governor *governor)
mutex_lock(&thermal_governor_lock);
err = -EBUSY;
- if (__find_governor(governor->name) == NULL) {
+ if (!__find_governor(governor->name)) {
+ bool match_default;
+
err = 0;
list_add(&governor->governor_list, &thermal_governor_list);
- if (!def_governor && !strncmp(governor->name,
- DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH))
+ match_default = !strncmp(governor->name,
+ DEFAULT_THERMAL_GOVERNOR,
+ THERMAL_NAME_LENGTH);
+
+ if (!def_governor && match_default)
def_governor = governor;
}
@@ -188,14 +187,14 @@ void thermal_unregister_governor(struct thermal_governor *governor)
mutex_lock(&thermal_governor_lock);
- if (__find_governor(governor->name) == NULL)
+ if (!__find_governor(governor->name))
goto exit;
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node) {
if (!strncasecmp(pos->governor->name, governor->name,
- THERMAL_NAME_LENGTH))
+ THERMAL_NAME_LENGTH))
thermal_set_governor(pos, NULL);
}
@@ -203,195 +202,92 @@ void thermal_unregister_governor(struct thermal_governor *governor)
list_del(&governor->governor_list);
exit:
mutex_unlock(&thermal_governor_lock);
- return;
}
-static int get_idr(struct idr *idr, struct mutex *lock, int *id)
+int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
+ char *policy)
{
- int ret;
-
- if (lock)
- mutex_lock(lock);
- ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
- if (lock)
- mutex_unlock(lock);
- if (unlikely(ret < 0))
- return ret;
- *id = ret;
- return 0;
-}
-
-static void release_idr(struct idr *idr, struct mutex *lock, int id)
-{
- if (lock)
- mutex_lock(lock);
- idr_remove(idr, id);
- if (lock)
- mutex_unlock(lock);
-}
-
-int get_tz_trend(struct thermal_zone_device *tz, int trip)
-{
- enum thermal_trend trend;
-
- if (tz->emul_temperature || !tz->ops->get_trend ||
- tz->ops->get_trend(tz, trip, &trend)) {
- if (tz->temperature > tz->last_temperature)
- trend = THERMAL_TREND_RAISING;
- else if (tz->temperature < tz->last_temperature)
- trend = THERMAL_TREND_DROPPING;
- else
- trend = THERMAL_TREND_STABLE;
- }
-
- return trend;
-}
-EXPORT_SYMBOL(get_tz_trend);
-
-struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int trip)
-{
- struct thermal_instance *pos = NULL;
- struct thermal_instance *target_instance = NULL;
+ struct thermal_governor *gov;
+ int ret = -EINVAL;
+ mutex_lock(&thermal_governor_lock);
mutex_lock(&tz->lock);
- mutex_lock(&cdev->lock);
- list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
- target_instance = pos;
- break;
- }
- }
+ gov = __find_governor(strim(policy));
+ if (!gov)
+ goto exit;
- mutex_unlock(&cdev->lock);
- mutex_unlock(&tz->lock);
+ ret = thermal_set_governor(tz, gov);
- return target_instance;
-}
-EXPORT_SYMBOL(get_thermal_instance);
+exit:
+ mutex_unlock(&tz->lock);
+ mutex_unlock(&thermal_governor_lock);
-static void print_bind_err_msg(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int ret)
-{
- dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
- tz->type, cdev->type, ret);
+ return ret;
}
-static void __bind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev,
- unsigned long *limits,
- unsigned int weight)
+int thermal_build_list_of_policies(char *buf)
{
- int i, ret;
+ struct thermal_governor *pos;
+ ssize_t count = 0;
+ ssize_t size = PAGE_SIZE;
- for (i = 0; i < tz->trips; i++) {
- if (mask & (1 << i)) {
- unsigned long upper, lower;
+ mutex_lock(&thermal_governor_lock);
- upper = THERMAL_NO_LIMIT;
- lower = THERMAL_NO_LIMIT;
- if (limits) {
- lower = limits[i * 2];
- upper = limits[i * 2 + 1];
- }
- ret = thermal_zone_bind_cooling_device(tz, i, cdev,
- upper, lower,
- weight);
- if (ret)
- print_bind_err_msg(tz, cdev, ret);
- }
+ list_for_each_entry(pos, &thermal_governor_list, governor_list) {
+ size = PAGE_SIZE - count;
+ count += scnprintf(buf + count, size, "%s ", pos->name);
}
-}
+ count += scnprintf(buf + count, size, "\n");
-static void __unbind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev)
-{
- int i;
+ mutex_unlock(&thermal_governor_lock);
- for (i = 0; i < tz->trips; i++)
- if (mask & (1 << i))
- thermal_zone_unbind_cooling_device(tz, i, cdev);
+ return count;
}
-static void bind_cdev(struct thermal_cooling_device *cdev)
+static int __init thermal_register_governors(void)
{
- int i, ret;
- const struct thermal_zone_params *tzp;
- struct thermal_zone_device *pos = NULL;
-
- mutex_lock(&thermal_list_lock);
+ int result;
- list_for_each_entry(pos, &thermal_tz_list, node) {
- if (!pos->tzp && !pos->ops->bind)
- continue;
+ result = thermal_gov_step_wise_register();
+ if (result)
+ return result;
- if (pos->ops->bind) {
- ret = pos->ops->bind(pos, cdev);
- if (ret)
- print_bind_err_msg(pos, cdev, ret);
- continue;
- }
+ result = thermal_gov_fair_share_register();
+ if (result)
+ return result;
- tzp = pos->tzp;
- if (!tzp || !tzp->tbp)
- continue;
+ result = thermal_gov_bang_bang_register();
+ if (result)
+ return result;
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(pos, cdev))
- continue;
- tzp->tbp[i].cdev = cdev;
- __bind(pos, tzp->tbp[i].trip_mask, cdev,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
+ result = thermal_gov_user_space_register();
+ if (result)
+ return result;
- mutex_unlock(&thermal_list_lock);
+ return thermal_gov_power_allocator_register();
}
-static void bind_tz(struct thermal_zone_device *tz)
+static void thermal_unregister_governors(void)
{
- int i, ret;
- struct thermal_cooling_device *pos = NULL;
- const struct thermal_zone_params *tzp = tz->tzp;
-
- if (!tzp && !tz->ops->bind)
- return;
-
- mutex_lock(&thermal_list_lock);
-
- /* If there is ops->bind, try to use ops->bind */
- if (tz->ops->bind) {
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- ret = tz->ops->bind(tz, pos);
- if (ret)
- print_bind_err_msg(tz, pos, ret);
- }
- goto exit;
- }
-
- if (!tzp || !tzp->tbp)
- goto exit;
-
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(tz, pos))
- continue;
- tzp->tbp[i].cdev = pos;
- __bind(tz, tzp->tbp[i].trip_mask, pos,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
-exit:
- mutex_unlock(&thermal_list_lock);
+ thermal_gov_step_wise_unregister();
+ thermal_gov_fair_share_unregister();
+ thermal_gov_bang_bang_unregister();
+ thermal_gov_user_space_unregister();
+ thermal_gov_power_allocator_unregister();
}
+/*
+ * Zone update section: main control loop applied to each zone while monitoring
+ *
+ * in polling mode. The monitoring is done using a workqueue.
+ * Same update may be done on a zone by calling thermal_zone_device_update().
+ *
+ * An update means:
+ * - Non-critical trips will invoke the governor responsible for that zone;
+ * - Hot trips will produce a notification to userspace;
+ * - Critical trip point will cause a system shutdown.
+ */
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
int delay)
{
@@ -420,14 +316,15 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
}
static void handle_non_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip,
+ enum thermal_trip_type trip_type)
{
tz->governor ? tz->governor->throttle(tz, trip) :
def_governor->throttle(tz, trip);
}
static void handle_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip, enum thermal_trip_type trip_type)
{
int trip_temp;
@@ -471,105 +368,6 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
monitor_thermal_zone(tz);
}
-/**
- * thermal_zone_get_temp() - returns the temperature of a thermal zone
- * @tz: a valid pointer to a struct thermal_zone_device
- * @temp: a valid pointer to where to store the resulting temperature.
- *
- * When a valid thermal zone reference is passed, it will fetch its
- * temperature and fill @temp.
- *
- * Return: On success returns 0, an error code otherwise
- */
-int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
-{
- int ret = -EINVAL;
- int count;
- int crit_temp = INT_MAX;
- enum thermal_trip_type type;
-
- if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
- goto exit;
-
- mutex_lock(&tz->lock);
-
- ret = tz->ops->get_temp(tz, temp);
-
- if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
- for (count = 0; count < tz->trips; count++) {
- ret = tz->ops->get_trip_type(tz, count, &type);
- if (!ret && type == THERMAL_TRIP_CRITICAL) {
- ret = tz->ops->get_trip_temp(tz, count,
- &crit_temp);
- break;
- }
- }
-
- /*
- * Only allow emulating a temperature when the real temperature
- * is below the critical temperature so that the emulation code
- * cannot hide critical conditions.
- */
- if (!ret && *temp < crit_temp)
- *temp = tz->emul_temperature;
- }
-
- mutex_unlock(&tz->lock);
-exit:
- return ret;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
-
-void thermal_zone_set_trips(struct thermal_zone_device *tz)
-{
- int low = -INT_MAX;
- int high = INT_MAX;
- int trip_temp, hysteresis;
- int i, ret;
-
- mutex_lock(&tz->lock);
-
- if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
- goto exit;
-
- for (i = 0; i < tz->trips; i++) {
- int trip_low;
-
- tz->ops->get_trip_temp(tz, i, &trip_temp);
- tz->ops->get_trip_hyst(tz, i, &hysteresis);
-
- trip_low = trip_temp - hysteresis;
-
- if (trip_low < tz->temperature && trip_low > low)
- low = trip_low;
-
- if (trip_temp > tz->temperature && trip_temp < high)
- high = trip_temp;
- }
-
- /* No need to change trip points */
- if (tz->prev_low_trip == low && tz->prev_high_trip == high)
- goto exit;
-
- tz->prev_low_trip = low;
- tz->prev_high_trip = high;
-
- dev_dbg(&tz->device,
- "new temperature boundaries: %d < x < %d\n", low, high);
-
- /*
- * Set a temperature window. When this window is left the driver
- * must inform the thermal core via thermal_zone_device_update.
- */
- ret = tz->ops->set_trips(tz, low, high);
- if (ret)
- dev_err(&tz->device, "Failed to set trips: %d\n", ret);
-
-exit:
- mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
-
static void update_temperature(struct thermal_zone_device *tz)
{
int temp, ret;
@@ -629,6 +427,24 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
+/**
+ * thermal_notify_framework - Sensor drivers use this API to notify framework
+ * @tz: thermal zone device
+ * @trip: indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
+ */
+void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
+{
+ handle_thermal_trip(tz, trip);
+}
+EXPORT_SYMBOL_GPL(thermal_notify_framework);
+
static void thermal_zone_device_check(struct work_struct *work)
{
struct thermal_zone_device *tz = container_of(work, struct
@@ -637,445 +453,12 @@ static void thermal_zone_device_check(struct work_struct *work)
thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
}
-/* sys I/F for thermal zone */
-
-#define to_thermal_zone(_dev) \
- container_of(_dev, struct thermal_zone_device, device)
-
-static ssize_t
-type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->type);
-}
-
-static ssize_t
-temp_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int temperature, ret;
-
- ret = thermal_zone_get_temp(tz, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_device_mode mode;
- int result;
-
- if (!tz->ops->get_mode)
- return -EPERM;
-
- result = tz->ops->get_mode(tz, &mode);
- if (result)
- return result;
-
- return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
- : "disabled");
-}
-
-static ssize_t
-mode_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int result;
-
- if (!tz->ops->set_mode)
- return -EPERM;
-
- if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
- else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
- else
- result = -EINVAL;
-
- if (result)
- return result;
-
- return count;
-}
-
-static ssize_t
-trip_point_type_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_trip_type type;
- int trip, result;
-
- if (!tz->ops->get_trip_type)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
- return -EINVAL;
-
- result = tz->ops->get_trip_type(tz, trip, &type);
- if (result)
- return result;
-
- switch (type) {
- case THERMAL_TRIP_CRITICAL:
- return sprintf(buf, "critical\n");
- case THERMAL_TRIP_HOT:
- return sprintf(buf, "hot\n");
- case THERMAL_TRIP_PASSIVE:
- return sprintf(buf, "passive\n");
- case THERMAL_TRIP_ACTIVE:
- return sprintf(buf, "active\n");
- default:
- return sprintf(buf, "unknown\n");
- }
-}
-
-static ssize_t
-trip_point_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_temp)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- ret = tz->ops->set_trip_temp(tz, trip, temperature);
- if (ret)
- return ret;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-trip_point_temp_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_temp)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
- return -EINVAL;
-
- ret = tz->ops->get_trip_temp(tz, trip, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_hyst)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- /*
- * We are not doing any check on the 'temperature' value
- * here. The driver implementing 'set_trip_hyst' has to
- * take care of this.
- */
- ret = tz->ops->set_trip_hyst(tz, trip, temperature);
-
- if (!ret)
- thermal_zone_set_trips(tz);
-
- return ret ? ret : count;
-}
-
-static ssize_t
-trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_hyst)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
- return -EINVAL;
-
- ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
-
- return ret ? ret : sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-passive_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_cooling_device *cdev = NULL;
- int state;
-
- if (!sscanf(buf, "%d\n", &state))
- return -EINVAL;
-
- /* sanity check: values below 1000 millicelcius don't make sense
- * and can cause the system to go into a thermal heart attack
- */
- if (state && state < 1000)
- return -EINVAL;
-
- if (state && !tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_bind_cooling_device(tz,
- THERMAL_TRIPS_NONE, cdev,
- THERMAL_NO_LIMIT,
- THERMAL_NO_LIMIT,
- THERMAL_WEIGHT_DEFAULT);
- }
- mutex_unlock(&thermal_list_lock);
- if (!tz->passive_delay)
- tz->passive_delay = 1000;
- } else if (!state && tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_unbind_cooling_device(tz,
- THERMAL_TRIPS_NONE,
- cdev);
- }
- mutex_unlock(&thermal_list_lock);
- tz->passive_delay = 0;
- }
-
- tz->forced_passive = state;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-passive_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%d\n", tz->forced_passive);
-}
-
-static ssize_t
-policy_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int ret = -EINVAL;
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_governor *gov;
- char name[THERMAL_NAME_LENGTH];
-
- snprintf(name, sizeof(name), "%s", buf);
-
- mutex_lock(&thermal_governor_lock);
- mutex_lock(&tz->lock);
-
- gov = __find_governor(strim(name));
- if (!gov)
- goto exit;
-
- ret = thermal_set_governor(tz, gov);
- if (!ret)
- ret = count;
-
-exit:
- mutex_unlock(&tz->lock);
- mutex_unlock(&thermal_governor_lock);
- return ret;
-}
-
-static ssize_t
-policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->governor->name);
-}
-
-static ssize_t
-available_policies_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct thermal_governor *pos;
- ssize_t count = 0;
- ssize_t size = PAGE_SIZE;
-
- mutex_lock(&thermal_governor_lock);
-
- list_for_each_entry(pos, &thermal_governor_list, governor_list) {
- size = PAGE_SIZE - count;
- count += scnprintf(buf + count, size, "%s ", pos->name);
- }
- count += scnprintf(buf + count, size, "\n");
-
- mutex_unlock(&thermal_governor_lock);
-
- return count;
-}
-
-static ssize_t
-emul_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int ret = 0;
- int temperature;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- if (!tz->ops->set_emul_temp) {
- mutex_lock(&tz->lock);
- tz->emul_temperature = temperature;
- mutex_unlock(&tz->lock);
- } else {
- ret = tz->ops->set_emul_temp(tz, temperature);
- }
-
- if (!ret)
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return ret ? ret : count;
-}
-static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
-
-static ssize_t
-sustainable_power_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- if (tz->tzp)
- return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
- else
- return -EIO;
-}
-
-static ssize_t
-sustainable_power_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- u32 sustainable_power;
-
- if (!tz->tzp)
- return -EIO;
-
- if (kstrtou32(buf, 10, &sustainable_power))
- return -EINVAL;
-
- tz->tzp->sustainable_power = sustainable_power;
-
- return count;
-}
-static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
- sustainable_power_store);
-
-#define create_s32_tzp_attr(name) \
- static ssize_t \
- name##_show(struct device *dev, struct device_attribute *devattr, \
- char *buf) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- \
- if (tz->tzp) \
- return sprintf(buf, "%d\n", tz->tzp->name); \
- else \
- return -EIO; \
- } \
- \
- static ssize_t \
- name##_store(struct device *dev, struct device_attribute *devattr, \
- const char *buf, size_t count) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- s32 value; \
- \
- if (!tz->tzp) \
- return -EIO; \
- \
- if (kstrtos32(buf, 10, &value)) \
- return -EINVAL; \
- \
- tz->tzp->name = value; \
- \
- return count; \
- } \
- static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
-
-create_s32_tzp_attr(k_po);
-create_s32_tzp_attr(k_pu);
-create_s32_tzp_attr(k_i);
-create_s32_tzp_attr(k_d);
-create_s32_tzp_attr(integral_cutoff);
-create_s32_tzp_attr(slope);
-create_s32_tzp_attr(offset);
-#undef create_s32_tzp_attr
-
-static struct device_attribute *dev_tzp_attrs[] = {
- &dev_attr_sustainable_power,
- &dev_attr_k_po,
- &dev_attr_k_pu,
- &dev_attr_k_i,
- &dev_attr_k_d,
- &dev_attr_integral_cutoff,
- &dev_attr_slope,
- &dev_attr_offset,
-};
-
-static int create_tzp_attrs(struct device *dev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dev_tzp_attrs); i++) {
- int ret;
- struct device_attribute *dev_attr = dev_tzp_attrs[i];
-
- ret = device_create_file(dev, dev_attr);
- if (ret)
- return ret;
- }
-
- return 0;
-}
+/*
+ * Power actor section: interface to power actors to estimate power
+ *
+ * Set of functions used to interact to cooling devices that know
+ * how to estimate their devices power consumption.
+ */
/**
* power_actor_get_max_power() - get the maximum power that a cdev can consume
@@ -1127,12 +510,13 @@ int power_actor_get_min_power(struct thermal_cooling_device *cdev,
}
/**
- * power_actor_set_power() - limit the maximum power that a cooling device can consume
+ * power_actor_set_power() - limit the maximum power a cooling device consumes
* @cdev: pointer to &thermal_cooling_device
* @instance: thermal instance to update
* @power: the power in milliwatts
*
- * Set the cooling device to consume at most @power milliwatts.
+ * Set the cooling device to consume at most @power milliwatts. The limit is
+ * expected to be a cap at the maximum power consumption.
*
* Return: 0 on success, -EINVAL if the cooling device does not
* implement the power actor API or -E* for other failures.
@@ -1159,143 +543,75 @@ int power_actor_set_power(struct thermal_cooling_device *cdev,
return 0;
}
-static DEVICE_ATTR(type, 0444, type_show, NULL);
-static DEVICE_ATTR(temp, 0444, temp_show, NULL);
-static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
-static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
-static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
-static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
-
-/* sys I/F for cooling device */
-#define to_cooling_device(_dev) \
- container_of(_dev, struct thermal_cooling_device, device)
-
-static ssize_t
-thermal_cooling_device_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ struct thermal_cooling_device *cdev = NULL;
+
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
- return sprintf(buf, "%s\n", cdev->type);
+ /* re binding the exception matching the type pattern */
+ thermal_zone_bind_cooling_device(tz, THERMAL_TRIPS_NONE, cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ }
+ mutex_unlock(&thermal_list_lock);
}
-static ssize_t
-thermal_cooling_device_max_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int ret;
+ struct thermal_cooling_device *cdev = NULL;
- ret = cdev->ops->get_max_state(cdev, &state);
- if (ret)
- return ret;
- return sprintf(buf, "%ld\n", state);
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
+ /* unbinding the exception matching the type pattern */
+ thermal_zone_unbind_cooling_device(tz, THERMAL_TRIPS_NONE,
+ cdev);
+ }
+ mutex_unlock(&thermal_list_lock);
}
-static ssize_t
-thermal_cooling_device_cur_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+/*
+ * Device management section: cooling devices, zones devices, and binding
+ *
+ * Set of functions provided by the thermal core for:
+ * - cooling devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ * - thermal zone devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ */
+static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
int ret;
- ret = cdev->ops->get_cur_state(cdev, &state);
- if (ret)
+ if (lock)
+ mutex_lock(lock);
+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ if (lock)
+ mutex_unlock(lock);
+ if (unlikely(ret < 0))
return ret;
- return sprintf(buf, "%ld\n", state);
-}
-
-static ssize_t
-thermal_cooling_device_cur_state_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int result;
-
- if (!sscanf(buf, "%ld\n", &state))
- return -EINVAL;
-
- if ((long)state < 0)
- return -EINVAL;
-
- result = cdev->ops->set_cur_state(cdev, state);
- if (result)
- return result;
- return count;
-}
-
-static struct device_attribute dev_attr_cdev_type =
-__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
-static DEVICE_ATTR(max_state, 0444,
- thermal_cooling_device_max_state_show, NULL);
-static DEVICE_ATTR(cur_state, 0644,
- thermal_cooling_device_cur_state_show,
- thermal_cooling_device_cur_state_store);
-
-static ssize_t
-thermal_cooling_device_trip_point_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance =
- container_of(attr, struct thermal_instance, attr);
-
- if (instance->trip == THERMAL_TRIPS_NONE)
- return sprintf(buf, "-1\n");
- else
- return sprintf(buf, "%d\n", instance->trip);
-}
-
-static struct attribute *cooling_device_attrs[] = {
- &dev_attr_cdev_type.attr,
- &dev_attr_max_state.attr,
- &dev_attr_cur_state.attr,
- NULL,
-};
-
-static const struct attribute_group cooling_device_attr_group = {
- .attrs = cooling_device_attrs,
-};
-
-static const struct attribute_group *cooling_device_attr_groups[] = {
- &cooling_device_attr_group,
- NULL,
-};
-
-static ssize_t
-thermal_cooling_device_weight_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
-
- return sprintf(buf, "%d\n", instance->weight);
+ *id = ret;
+ return 0;
}
-static ssize_t
-thermal_cooling_device_weight_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static void release_idr(struct idr *idr, struct mutex *lock, int id)
{
- struct thermal_instance *instance;
- int ret, weight;
-
- ret = kstrtoint(buf, 0, &weight);
- if (ret)
- return ret;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
- instance->weight = weight;
-
- return count;
+ if (lock)
+ mutex_lock(lock);
+ idr_remove(idr, id);
+ if (lock)
+ mutex_unlock(lock);
}
-/* Device management */
/**
* thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone
@@ -1358,8 +674,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
if (lower > upper || upper > max_state)
return -EINVAL;
- dev =
- kzalloc(sizeof(struct thermal_instance), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->tz = tz;
@@ -1402,10 +717,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
- result = -EEXIST;
- break;
- }
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+ result = -EEXIST;
+ break;
+ }
if (!result) {
list_add_tail(&dev->tz_node, &tz->thermal_instances);
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
@@ -1485,8 +800,8 @@ static void thermal_release(struct device *dev)
sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev);
kfree(tz);
- } else if(!strncmp(dev_name(dev), "cooling_device",
- sizeof("cooling_device") - 1)){
+ } else if (!strncmp(dev_name(dev), "cooling_device",
+ sizeof("cooling_device") - 1)) {
cdev = to_cooling_device(dev);
kfree(cdev);
}
@@ -1497,6 +812,78 @@ static struct class thermal_class = {
.dev_release = thermal_release,
};
+static inline
+void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret)
+{
+ dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+ tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev,
+ unsigned long *limits,
+ unsigned int weight)
+{
+ int i, ret;
+
+ for (i = 0; i < tz->trips; i++) {
+ if (mask & (1 << i)) {
+ unsigned long upper, lower;
+
+ upper = THERMAL_NO_LIMIT;
+ lower = THERMAL_NO_LIMIT;
+ if (limits) {
+ lower = limits[i * 2];
+ upper = limits[i * 2 + 1];
+ }
+ ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+ upper, lower,
+ weight);
+ if (ret)
+ print_bind_err_msg(tz, cdev, ret);
+ }
+ }
+}
+
+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+ int i, ret;
+ const struct thermal_zone_params *tzp;
+ struct thermal_zone_device *pos = NULL;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!pos->tzp && !pos->ops->bind)
+ continue;
+
+ if (pos->ops->bind) {
+ ret = pos->ops->bind(pos, cdev);
+ if (ret)
+ print_bind_err_msg(pos, cdev, ret);
+ continue;
+ }
+
+ tzp = pos->tzp;
+ if (!tzp || !tzp->tbp)
+ continue;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(pos, cdev))
+ continue;
+ tzp->tbp[i].cdev = cdev;
+ __bind(pos, tzp->tbp[i].trip_mask, cdev,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
+ }
+ }
+
+ mutex_unlock(&thermal_list_lock);
+}
+
/**
* __thermal_cooling_device_register() - register a new thermal cooling device
* @np: a pointer to a device tree node.
@@ -1529,7 +916,7 @@ __thermal_cooling_device_register(struct device_node *np,
!ops->set_cur_state)
return ERR_PTR(-EINVAL);
- cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return ERR_PTR(-ENOMEM);
@@ -1546,7 +933,7 @@ __thermal_cooling_device_register(struct device_node *np,
cdev->ops = ops;
cdev->updated = false;
cdev->device.class = &thermal_class;
- cdev->device.groups = cooling_device_attr_groups;
+ thermal_cooling_device_setup_sysfs(cdev);
cdev->devdata = devdata;
dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
result = device_register(&cdev->device);
@@ -1619,12 +1006,22 @@ thermal_of_cooling_device_register(struct device_node *np,
}
EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
/**
- * thermal_cooling_device_unregister - removes the registered thermal cooling device
+ * thermal_cooling_device_unregister - removes a thermal cooling device
* @cdev: the thermal cooling device to remove.
*
- * thermal_cooling_device_unregister() must be called when the device is no
- * longer needed.
+ * thermal_cooling_device_unregister() must be called when a registered
+ * thermal cooling device is no longer needed.
*/
void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
{
@@ -1638,8 +1035,8 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_cdev_list, node)
- if (pos == cdev)
- break;
+ if (pos == cdev)
+ break;
if (pos != cdev) {
/* thermal cooling device not found */
mutex_unlock(&thermal_list_lock);
@@ -1668,171 +1065,49 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
mutex_unlock(&thermal_list_lock);
- if (cdev->type[0])
- device_remove_file(&cdev->device, &dev_attr_cdev_type);
- device_remove_file(&cdev->device, &dev_attr_max_state);
- device_remove_file(&cdev->device, &dev_attr_cur_state);
-
release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
device_unregister(&cdev->device);
- return;
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
-void thermal_cdev_update(struct thermal_cooling_device *cdev)
+static void bind_tz(struct thermal_zone_device *tz)
{
- struct thermal_instance *instance;
- unsigned long target = 0;
+ int i, ret;
+ struct thermal_cooling_device *pos = NULL;
+ const struct thermal_zone_params *tzp = tz->tzp;
- mutex_lock(&cdev->lock);
- /* cooling device is updated*/
- if (cdev->updated) {
- mutex_unlock(&cdev->lock);
+ if (!tzp && !tz->ops->bind)
return;
- }
-
- /* Make sure cdev enters the deepest cooling state */
- list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
- dev_dbg(&cdev->device, "zone%d->target=%lu\n",
- instance->tz->id, instance->target);
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- if (instance->target > target)
- target = instance->target;
- }
- cdev->ops->set_cur_state(cdev, target);
- cdev->updated = true;
- mutex_unlock(&cdev->lock);
- trace_cdev_update(cdev, target);
- dev_dbg(&cdev->device, "set to state %lu\n", target);
-}
-EXPORT_SYMBOL(thermal_cdev_update);
-/**
- * thermal_notify_framework - Sensor drivers use this API to notify framework
- * @tz: thermal zone device
- * @trip: indicates which trip point has been crossed
- *
- * This function handles the trip events from sensor drivers. It starts
- * throttling the cooling devices according to the policy configured.
- * For CRITICAL and HOT trip points, this notifies the respective drivers,
- * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
- * The throttling policy is based on the configured platform data; if no
- * platform data is provided, this uses the step_wise throttling policy.
- */
-void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
-{
- handle_thermal_trip(tz, trip);
-}
-EXPORT_SYMBOL_GPL(thermal_notify_framework);
-
-/**
- * create_trip_attrs() - create attributes for trip points
- * @tz: the thermal zone device
- * @mask: Writeable trip point bitmap.
- *
- * helper function to instantiate sysfs entries for every trip
- * point and its properties of a struct thermal_zone_device.
- *
- * Return: 0 on success, the proper error value otherwise.
- */
-static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
-{
- int indx;
- int size = sizeof(struct thermal_attr) * tz->trips;
-
- tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_type_attrs)
- return -ENOMEM;
-
- tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_temp_attrs) {
- kfree(tz->trip_type_attrs);
- return -ENOMEM;
- }
+ mutex_lock(&thermal_list_lock);
- if (tz->ops->get_trip_hyst) {
- tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_hyst_attrs) {
- kfree(tz->trip_type_attrs);
- kfree(tz->trip_temp_attrs);
- return -ENOMEM;
+ /* If there is ops->bind, try to use ops->bind */
+ if (tz->ops->bind) {
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ ret = tz->ops->bind(tz, pos);
+ if (ret)
+ print_bind_err_msg(tz, pos, ret);
}
+ goto exit;
}
+ if (!tzp || !tzp->tbp)
+ goto exit;
- for (indx = 0; indx < tz->trips; indx++) {
- /* create trip type attribute */
- snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_type", indx);
-
- sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
- tz->trip_type_attrs[indx].attr.attr.name =
- tz->trip_type_attrs[indx].name;
- tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
-
- device_create_file(&tz->device,
- &tz->trip_type_attrs[indx].attr);
-
- /* create trip temp attribute */
- snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_temp", indx);
-
- sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
- tz->trip_temp_attrs[indx].attr.attr.name =
- tz->trip_temp_attrs[indx].name;
- tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
- if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
- mask & (1 << indx)) {
- tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_temp_attrs[indx].attr.store =
- trip_point_temp_store;
- }
-
- device_create_file(&tz->device,
- &tz->trip_temp_attrs[indx].attr);
-
- /* create Optional trip hyst attribute */
- if (!tz->ops->get_trip_hyst)
- continue;
- snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_hyst", indx);
-
- sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
- tz->trip_hyst_attrs[indx].attr.attr.name =
- tz->trip_hyst_attrs[indx].name;
- tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
- if (tz->ops->set_trip_hyst) {
- tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_hyst_attrs[indx].attr.store =
- trip_point_hyst_store;
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(tz, pos))
+ continue;
+ tzp->tbp[i].cdev = pos;
+ __bind(tz, tzp->tbp[i].trip_mask, pos,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
}
-
- device_create_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
- }
- return 0;
-}
-
-static void remove_trip_attrs(struct thermal_zone_device *tz)
-{
- int indx;
-
- for (indx = 0; indx < tz->trips; indx++) {
- device_remove_file(&tz->device,
- &tz->trip_type_attrs[indx].attr);
- device_remove_file(&tz->device,
- &tz->trip_temp_attrs[indx].attr);
- if (tz->ops->get_trip_hyst)
- device_remove_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
}
- kfree(tz->trip_type_attrs);
- kfree(tz->trip_temp_attrs);
- kfree(tz->trip_hyst_attrs);
+exit:
+ mutex_unlock(&thermal_list_lock);
}
/**
@@ -1859,20 +1134,22 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
* in case of error, an ERR_PTR. Caller must check return value with
* IS_ERR*() helpers.
*/
-struct thermal_zone_device *thermal_zone_device_register(const char *type,
- int trips, int mask, void *devdata,
- struct thermal_zone_device_ops *ops,
- struct thermal_zone_params *tzp,
- int passive_delay, int polling_delay)
+struct thermal_zone_device *
+thermal_zone_device_register(const char *type, int trips, int mask,
+ void *devdata, struct thermal_zone_device_ops *ops,
+ struct thermal_zone_params *tzp, int passive_delay,
+ int polling_delay)
{
struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
int trip_temp;
int result;
int count;
- int passive = 0;
struct thermal_governor *governor;
+ if (!type || strlen(type) == 0)
+ return ERR_PTR(-EINVAL);
+
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
return ERR_PTR(-EINVAL);
@@ -1885,7 +1162,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
return ERR_PTR(-EINVAL);
- tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
+ tz = kzalloc(sizeof(*tz), GFP_KERNEL);
if (!tz)
return ERR_PTR(-ENOMEM);
@@ -1898,7 +1175,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
return ERR_PTR(result);
}
- strlcpy(tz->type, type ? : "", sizeof(tz->type));
+ strlcpy(tz->type, type, sizeof(tz->type));
tz->ops = ops;
tz->tzp = tzp;
tz->device.class = &thermal_class;
@@ -1906,6 +1183,13 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
tz->trips = trips;
tz->passive_delay = passive_delay;
tz->polling_delay = polling_delay;
+
+ /* sys I/F */
+ /* Add nodes that are always present via .groups */
+ result = thermal_zone_create_device_groups(tz, mask);
+ if (result)
+ goto unregister;
+
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);
@@ -1917,32 +1201,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
return ERR_PTR(result);
}
- /* sys I/F */
- if (type) {
- result = device_create_file(&tz->device, &dev_attr_type);
- if (result)
- goto unregister;
- }
-
- result = device_create_file(&tz->device, &dev_attr_temp);
- if (result)
- goto unregister;
-
- if (ops->get_mode) {
- result = device_create_file(&tz->device, &dev_attr_mode);
- if (result)
- goto unregister;
- }
-
- result = create_trip_attrs(tz, mask);
- if (result)
- goto unregister;
-
for (count = 0; count < trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type))
set_bit(count, &tz->trips_disabled);
- if (trip_type == THERMAL_TRIP_PASSIVE)
- passive = 1;
if (tz->ops->get_trip_temp(tz, count, &trip_temp))
set_bit(count, &tz->trips_disabled);
/* Check for bogus trip points */
@@ -1950,33 +1211,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
set_bit(count, &tz->trips_disabled);
}
- if (!passive) {
- result = device_create_file(&tz->device, &dev_attr_passive);
- if (result)
- goto unregister;
- }
-
- if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
- result = device_create_file(&tz->device, &dev_attr_emul_temp);
- if (result)
- goto unregister;
- }
-
- /* Create policy attribute */
- result = device_create_file(&tz->device, &dev_attr_policy);
- if (result)
- goto unregister;
-
- /* Add thermal zone params */
- result = create_tzp_attrs(&tz->device);
- if (result)
- goto unregister;
-
- /* Create available_policies attribute */
- result = device_create_file(&tz->device, &dev_attr_available_policies);
- if (result)
- goto unregister;
-
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);
@@ -2006,7 +1240,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
/* Bind cooling devices for this zone */
bind_tz(tz);
- INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+ INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
thermal_zone_device_reset(tz);
/* Update the new thermal zone and mark it as already updated. */
@@ -2040,8 +1274,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
- if (pos == tz)
- break;
+ if (pos == tz)
+ break;
if (pos != tz) {
/* thermal zone device not found */
mutex_unlock(&thermal_list_lock);
@@ -2071,14 +1305,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
thermal_zone_device_set_polling(tz, 0);
- if (tz->type[0])
- device_remove_file(&tz->device, &dev_attr_type);
- device_remove_file(&tz->device, &dev_attr_temp);
- if (tz->ops->get_mode)
- device_remove_file(&tz->device, &dev_attr_mode);
- device_remove_file(&tz->device, &dev_attr_policy);
- device_remove_file(&tz->device, &dev_attr_available_policies);
- remove_trip_attrs(tz);
+ kfree(tz->trip_type_attrs);
+ kfree(tz->trip_temp_attrs);
+ kfree(tz->trip_hyst_attrs);
+ kfree(tz->trips_attribute_group.attrs);
thermal_set_governor(tz, NULL);
thermal_remove_hwmon_sysfs(tz);
@@ -2086,7 +1316,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
idr_destroy(&tz->idr);
mutex_destroy(&tz->lock);
device_unregister(&tz->device);
- return;
+ kfree(tz->device.groups);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
@@ -2128,43 +1358,13 @@ exit:
}
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
-/**
- * thermal_zone_get_slope - return the slope attribute of the thermal zone
- * @tz: thermal zone device with the slope attribute
- *
- * Return: If the thermal zone device has a slope attribute, return it, else
- * return 1.
- */
-int thermal_zone_get_slope(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->slope;
- return 1;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
-
-/**
- * thermal_zone_get_offset - return the offset attribute of the thermal zone
- * @tz: thermal zone device with the offset attribute
- *
- * Return: If the thermal zone device has a offset attribute, return it, else
- * return 0.
- */
-int thermal_zone_get_offset(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->offset;
- return 0;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
-
#ifdef CONFIG_NET
static const struct genl_multicast_group thermal_event_mcgrps[] = {
{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
};
-static struct genl_family thermal_event_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family thermal_event_genl_family __ro_after_init = {
+ .module = THIS_MODULE,
.name = THERMAL_GENL_FAMILY_NAME,
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
@@ -2173,7 +1373,7 @@ static struct genl_family thermal_event_genl_family = {
};
int thermal_generate_netlink_event(struct thermal_zone_device *tz,
- enum events event)
+ enum events event)
{
struct sk_buff *skb;
struct nlattr *attr;
@@ -2235,7 +1435,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
}
EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
-static int genetlink_init(void)
+static int __init genetlink_init(void)
{
return genl_register_family(&thermal_event_genl_family);
}
@@ -2249,40 +1449,8 @@ static inline int genetlink_init(void) { return 0; }
static inline void genetlink_exit(void) {}
#endif /* !CONFIG_NET */
-static int __init thermal_register_governors(void)
-{
- int result;
-
- result = thermal_gov_step_wise_register();
- if (result)
- return result;
-
- result = thermal_gov_fair_share_register();
- if (result)
- return result;
-
- result = thermal_gov_bang_bang_register();
- if (result)
- return result;
-
- result = thermal_gov_user_space_register();
- if (result)
- return result;
-
- return thermal_gov_power_allocator_register();
-}
-
-static void thermal_unregister_governors(void)
-{
- thermal_gov_step_wise_unregister();
- thermal_gov_fair_share_unregister();
- thermal_gov_bang_bang_unregister();
- thermal_gov_user_space_unregister();
- thermal_gov_power_allocator_unregister();
-}
-
static int thermal_pm_notify(struct notifier_block *nb,
- unsigned long mode, void *_unused)
+ unsigned long mode, void *_unused)
{
struct thermal_zone_device *tz;
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 749d41abfbab..2412b3759e16 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -54,8 +54,34 @@ struct thermal_instance {
unsigned int weight; /* The weight of the cooling device */
};
+#define to_thermal_zone(_dev) \
+ container_of(_dev, struct thermal_zone_device, device)
+
+#define to_cooling_device(_dev) \
+ container_of(_dev, struct thermal_cooling_device, device)
+
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
+void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
+ const char *, size_t);
+void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
+ const char *, size_t);
+int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
+int thermal_build_list_of_policies(char *buf);
+
+/* sysfs I/F */
+int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
+void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
+/* used only at binding time */
+ssize_t
+thermal_cooling_device_trip_point_show(struct device *,
+ struct device_attribute *, char *);
+ssize_t thermal_cooling_device_weight_show(struct device *,
+ struct device_attribute *, char *);
+
+ssize_t thermal_cooling_device_weight_store(struct device *,
+ struct device_attribute *,
+ const char *, size_t);
#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c
new file mode 100644
index 000000000000..8cdf75adcce1
--- /dev/null
+++ b/drivers/thermal/thermal_helpers.c
@@ -0,0 +1,226 @@
+/*
+ * thermal_helpers.c - helper functions to handle thermal devices
+ *
+ * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
+ *
+ * Highly based on original thermal_core.c
+ * Copyright (C) 2008 Intel Corp
+ * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
+ * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <trace/events/thermal.h>
+
+#include "thermal_core.h"
+
+int get_tz_trend(struct thermal_zone_device *tz, int trip)
+{
+ enum thermal_trend trend;
+
+ if (tz->emul_temperature || !tz->ops->get_trend ||
+ tz->ops->get_trend(tz, trip, &trend)) {
+ if (tz->temperature > tz->last_temperature)
+ trend = THERMAL_TREND_RAISING;
+ else if (tz->temperature < tz->last_temperature)
+ trend = THERMAL_TREND_DROPPING;
+ else
+ trend = THERMAL_TREND_STABLE;
+ }
+
+ return trend;
+}
+EXPORT_SYMBOL(get_tz_trend);
+
+struct thermal_instance *
+get_thermal_instance(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int trip)
+{
+ struct thermal_instance *pos = NULL;
+ struct thermal_instance *target_instance = NULL;
+
+ mutex_lock(&tz->lock);
+ mutex_lock(&cdev->lock);
+
+ list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+ target_instance = pos;
+ break;
+ }
+ }
+
+ mutex_unlock(&cdev->lock);
+ mutex_unlock(&tz->lock);
+
+ return target_instance;
+}
+EXPORT_SYMBOL(get_thermal_instance);
+
+/**
+ * thermal_zone_get_temp() - returns the temperature of a thermal zone
+ * @tz: a valid pointer to a struct thermal_zone_device
+ * @temp: a valid pointer to where to store the resulting temperature.
+ *
+ * When a valid thermal zone reference is passed, it will fetch its
+ * temperature and fill @temp.
+ *
+ * Return: On success returns 0, an error code otherwise
+ */
+int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ int ret = -EINVAL;
+ int count;
+ int crit_temp = INT_MAX;
+ enum thermal_trip_type type;
+
+ if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+ goto exit;
+
+ mutex_lock(&tz->lock);
+
+ ret = tz->ops->get_temp(tz, temp);
+
+ if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
+ for (count = 0; count < tz->trips; count++) {
+ ret = tz->ops->get_trip_type(tz, count, &type);
+ if (!ret && type == THERMAL_TRIP_CRITICAL) {
+ ret = tz->ops->get_trip_temp(tz, count,
+ &crit_temp);
+ break;
+ }
+ }
+
+ /*
+ * Only allow emulating a temperature when the real temperature
+ * is below the critical temperature so that the emulation code
+ * cannot hide critical conditions.
+ */
+ if (!ret && *temp < crit_temp)
+ *temp = tz->emul_temperature;
+ }
+
+ mutex_unlock(&tz->lock);
+exit:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+
+void thermal_zone_set_trips(struct thermal_zone_device *tz)
+{
+ int low = -INT_MAX;
+ int high = INT_MAX;
+ int trip_temp, hysteresis;
+ int i, ret;
+
+ mutex_lock(&tz->lock);
+
+ if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
+ goto exit;
+
+ for (i = 0; i < tz->trips; i++) {
+ int trip_low;
+
+ tz->ops->get_trip_temp(tz, i, &trip_temp);
+ tz->ops->get_trip_hyst(tz, i, &hysteresis);
+
+ trip_low = trip_temp - hysteresis;
+
+ if (trip_low < tz->temperature && trip_low > low)
+ low = trip_low;
+
+ if (trip_temp > tz->temperature && trip_temp < high)
+ high = trip_temp;
+ }
+
+ /* No need to change trip points */
+ if (tz->prev_low_trip == low && tz->prev_high_trip == high)
+ goto exit;
+
+ tz->prev_low_trip = low;
+ tz->prev_high_trip = high;
+
+ dev_dbg(&tz->device,
+ "new temperature boundaries: %d < x < %d\n", low, high);
+
+ /*
+ * Set a temperature window. When this window is left the driver
+ * must inform the thermal core via thermal_zone_device_update.
+ */
+ ret = tz->ops->set_trips(tz, low, high);
+ if (ret)
+ dev_err(&tz->device, "Failed to set trips: %d\n", ret);
+
+exit:
+ mutex_unlock(&tz->lock);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
+
+void thermal_cdev_update(struct thermal_cooling_device *cdev)
+{
+ struct thermal_instance *instance;
+ unsigned long target = 0;
+
+ mutex_lock(&cdev->lock);
+ /* cooling device is updated*/
+ if (cdev->updated) {
+ mutex_unlock(&cdev->lock);
+ return;
+ }
+
+ /* Make sure cdev enters the deepest cooling state */
+ list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
+ dev_dbg(&cdev->device, "zone%d->target=%lu\n",
+ instance->tz->id, instance->target);
+ if (instance->target == THERMAL_NO_TARGET)
+ continue;
+ if (instance->target > target)
+ target = instance->target;
+ }
+ cdev->ops->set_cur_state(cdev, target);
+ cdev->updated = true;
+ mutex_unlock(&cdev->lock);
+ trace_cdev_update(cdev, target);
+ dev_dbg(&cdev->device, "set to state %lu\n", target);
+}
+EXPORT_SYMBOL(thermal_cdev_update);
+
+/**
+ * thermal_zone_get_slope - return the slope attribute of the thermal zone
+ * @tz: thermal zone device with the slope attribute
+ *
+ * Return: If the thermal zone device has a slope attribute, return it, else
+ * return 1.
+ */
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+ if (tz && tz->tzp)
+ return tz->tzp->slope;
+ return 1;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+/**
+ * thermal_zone_get_offset - return the offset attribute of the thermal zone
+ * @tz: thermal zone device with the offset attribute
+ *
+ * Return: If the thermal zone device has a offset attribute, return it, else
+ * return 0.
+ */
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+ if (tz && tz->tzp)
+ return tz->tzp->offset;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index c41c7742903a..541af5946203 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -64,7 +64,7 @@ name_show(struct device *dev, struct device_attribute *attr, char *buf)
struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", hwmon->type);
}
-static DEVICE_ATTR(name, 0444, name_show, NULL);
+static DEVICE_ATTR_RO(name);
static ssize_t
temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -98,7 +98,7 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
int temperature;
int ret;
- ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+ ret = tz->ops->get_crit_temp(tz, &temperature);
if (ret)
return ret;
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
new file mode 100644
index 000000000000..a694de907a26
--- /dev/null
+++ b/drivers/thermal/thermal_sysfs.c
@@ -0,0 +1,771 @@
+/*
+ * thermal.c - sysfs interface of thermal devices
+ *
+ * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
+ *
+ * Highly based on original thermal_core.c
+ * Copyright (C) 2008 Intel Corp
+ * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
+ * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "thermal_core.h"
+
+/* sys I/F for thermal zone */
+
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%s\n", tz->type);
+}
+
+static ssize_t
+temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int temperature, ret;
+
+ ret = thermal_zone_get_temp(tz, &temperature);
+
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ enum thermal_device_mode mode;
+ int result;
+
+ if (!tz->ops->get_mode)
+ return -EPERM;
+
+ result = tz->ops->get_mode(tz, &mode);
+ if (result)
+ return result;
+
+ return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
+ : "disabled");
+}
+
+static ssize_t
+mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int result;
+
+ if (!tz->ops->set_mode)
+ return -EPERM;
+
+ if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
+ result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
+ else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
+ result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
+ else
+ result = -EINVAL;
+
+ if (result)
+ return result;
+
+ return count;
+}
+
+static ssize_t
+trip_point_type_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ enum thermal_trip_type type;
+ int trip, result;
+
+ if (!tz->ops->get_trip_type)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
+ return -EINVAL;
+
+ result = tz->ops->get_trip_type(tz, trip, &type);
+ if (result)
+ return result;
+
+ switch (type) {
+ case THERMAL_TRIP_CRITICAL:
+ return sprintf(buf, "critical\n");
+ case THERMAL_TRIP_HOT:
+ return sprintf(buf, "hot\n");
+ case THERMAL_TRIP_PASSIVE:
+ return sprintf(buf, "passive\n");
+ case THERMAL_TRIP_ACTIVE:
+ return sprintf(buf, "active\n");
+ default:
+ return sprintf(buf, "unknown\n");
+ }
+}
+
+static ssize_t
+trip_point_temp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->set_trip_temp)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ ret = tz->ops->set_trip_temp(tz, trip, temperature);
+ if (ret)
+ return ret;
+
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->get_trip_temp)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
+ return -EINVAL;
+
+ ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->set_trip_hyst)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ /*
+ * We are not doing any check on the 'temperature' value
+ * here. The driver implementing 'set_trip_hyst' has to
+ * take care of this.
+ */
+ ret = tz->ops->set_trip_hyst(tz, trip, temperature);
+
+ if (!ret)
+ thermal_zone_set_trips(tz);
+
+ return ret ? ret : count;
+}
+
+static ssize_t
+trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->get_trip_hyst)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
+ return -EINVAL;
+
+ ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+
+ return ret ? ret : sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+passive_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int state;
+
+ if (sscanf(buf, "%d\n", &state) != 1)
+ return -EINVAL;
+
+ /* sanity check: values below 1000 millicelcius don't make sense
+ * and can cause the system to go into a thermal heart attack
+ */
+ if (state && state < 1000)
+ return -EINVAL;
+
+ if (state && !tz->forced_passive) {
+ if (!tz->passive_delay)
+ tz->passive_delay = 1000;
+ thermal_zone_device_rebind_exception(tz, "Processor",
+ sizeof("Processor"));
+ } else if (!state && tz->forced_passive) {
+ tz->passive_delay = 0;
+ thermal_zone_device_unbind_exception(tz, "Processor",
+ sizeof("Processor"));
+ }
+
+ tz->forced_passive = state;
+
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+passive_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%d\n", tz->forced_passive);
+}
+
+static ssize_t
+policy_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ char name[THERMAL_NAME_LENGTH];
+ int ret;
+
+ snprintf(name, sizeof(name), "%s", buf);
+
+ ret = thermal_zone_device_set_policy(tz, name);
+ if (!ret)
+ ret = count;
+
+ return ret;
+}
+
+static ssize_t
+policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%s\n", tz->governor->name);
+}
+
+static ssize_t
+available_policies_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return thermal_build_list_of_policies(buf);
+}
+
+#if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
+static ssize_t
+emul_temp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int ret = 0;
+ int temperature;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ if (!tz->ops->set_emul_temp) {
+ mutex_lock(&tz->lock);
+ tz->emul_temperature = temperature;
+ mutex_unlock(&tz->lock);
+ } else {
+ ret = tz->ops->set_emul_temp(tz, temperature);
+ }
+
+ if (!ret)
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return ret ? ret : count;
+}
+static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
+#endif
+
+static ssize_t
+sustainable_power_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ if (tz->tzp)
+ return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
+ else
+ return -EIO;
+}
+
+static ssize_t
+sustainable_power_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ u32 sustainable_power;
+
+ if (!tz->tzp)
+ return -EIO;
+
+ if (kstrtou32(buf, 10, &sustainable_power))
+ return -EINVAL;
+
+ tz->tzp->sustainable_power = sustainable_power;
+
+ return count;
+}
+
+#define create_s32_tzp_attr(name) \
+ static ssize_t \
+ name##_show(struct device *dev, struct device_attribute *devattr, \
+ char *buf) \
+ { \
+ struct thermal_zone_device *tz = to_thermal_zone(dev); \
+ \
+ if (tz->tzp) \
+ return sprintf(buf, "%d\n", tz->tzp->name); \
+ else \
+ return -EIO; \
+ } \
+ \
+ static ssize_t \
+ name##_store(struct device *dev, struct device_attribute *devattr, \
+ const char *buf, size_t count) \
+ { \
+ struct thermal_zone_device *tz = to_thermal_zone(dev); \
+ s32 value; \
+ \
+ if (!tz->tzp) \
+ return -EIO; \
+ \
+ if (kstrtos32(buf, 10, &value)) \
+ return -EINVAL; \
+ \
+ tz->tzp->name = value; \
+ \
+ return count; \
+ } \
+ static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
+
+create_s32_tzp_attr(k_po);
+create_s32_tzp_attr(k_pu);
+create_s32_tzp_attr(k_i);
+create_s32_tzp_attr(k_d);
+create_s32_tzp_attr(integral_cutoff);
+create_s32_tzp_attr(slope);
+create_s32_tzp_attr(offset);
+#undef create_s32_tzp_attr
+
+/*
+ * These are thermal zone device attributes that will always be present.
+ * All the attributes created for tzp (create_s32_tzp_attr) also are always
+ * present on the sysfs interface.
+ */
+static DEVICE_ATTR(type, 0444, type_show, NULL);
+static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
+static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
+static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
+ sustainable_power_store);
+
+/* These thermal zone device attributes are created based on conditions */
+static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
+static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+
+/* These attributes are unconditionally added to a thermal zone */
+static struct attribute *thermal_zone_dev_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_temp.attr,
+#if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
+ &dev_attr_emul_temp.attr,
+#endif
+ &dev_attr_policy.attr,
+ &dev_attr_available_policies.attr,
+ &dev_attr_sustainable_power.attr,
+ &dev_attr_k_po.attr,
+ &dev_attr_k_pu.attr,
+ &dev_attr_k_i.attr,
+ &dev_attr_k_d.attr,
+ &dev_attr_integral_cutoff.attr,
+ &dev_attr_slope.attr,
+ &dev_attr_offset.attr,
+ NULL,
+};
+
+static struct attribute_group thermal_zone_attribute_group = {
+ .attrs = thermal_zone_dev_attrs,
+};
+
+/* We expose mode only if .get_mode is present */
+static struct attribute *thermal_zone_mode_attrs[] = {
+ &dev_attr_mode.attr,
+ NULL,
+};
+
+static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int attrno)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct thermal_zone_device *tz;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ if (tz->ops->get_mode)
+ return attr->mode;
+
+ return 0;
+}
+
+static struct attribute_group thermal_zone_mode_attribute_group = {
+ .attrs = thermal_zone_mode_attrs,
+ .is_visible = thermal_zone_mode_is_visible,
+};
+
+/* We expose passive only if passive trips are present */
+static struct attribute *thermal_zone_passive_attrs[] = {
+ &dev_attr_passive.attr,
+ NULL,
+};
+
+static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int attrno)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct thermal_zone_device *tz;
+ enum thermal_trip_type trip_type;
+ int count, passive = 0;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ for (count = 0; count < tz->trips && !passive; count++) {
+ tz->ops->get_trip_type(tz, count, &trip_type);
+
+ if (trip_type == THERMAL_TRIP_PASSIVE)
+ passive = 1;
+ }
+
+ if (!passive)
+ return attr->mode;
+
+ return 0;
+}
+
+static struct attribute_group thermal_zone_passive_attribute_group = {
+ .attrs = thermal_zone_passive_attrs,
+ .is_visible = thermal_zone_passive_is_visible,
+};
+
+static const struct attribute_group *thermal_zone_attribute_groups[] = {
+ &thermal_zone_attribute_group,
+ &thermal_zone_mode_attribute_group,
+ &thermal_zone_passive_attribute_group,
+ /* This is not NULL terminated as we create the group dynamically */
+};
+
+/**
+ * create_trip_attrs() - create attributes for trip points
+ * @tz: the thermal zone device
+ * @mask: Writeable trip point bitmap.
+ *
+ * helper function to instantiate sysfs entries for every trip
+ * point and its properties of a struct thermal_zone_device.
+ *
+ * Return: 0 on success, the proper error value otherwise.
+ */
+static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
+{
+ struct attribute **attrs;
+ int indx;
+
+ /* This function works only for zones with at least one trip */
+ if (tz->trips <= 0)
+ return -EINVAL;
+
+ tz->trip_type_attrs = kcalloc(tz->trips, sizeof(*tz->trip_type_attrs),
+ GFP_KERNEL);
+ if (!tz->trip_type_attrs)
+ return -ENOMEM;
+
+ tz->trip_temp_attrs = kcalloc(tz->trips, sizeof(*tz->trip_temp_attrs),
+ GFP_KERNEL);
+ if (!tz->trip_temp_attrs) {
+ kfree(tz->trip_type_attrs);
+ return -ENOMEM;
+ }
+
+ if (tz->ops->get_trip_hyst) {
+ tz->trip_hyst_attrs = kcalloc(tz->trips,
+ sizeof(*tz->trip_hyst_attrs),
+ GFP_KERNEL);
+ if (!tz->trip_hyst_attrs) {
+ kfree(tz->trip_type_attrs);
+ kfree(tz->trip_temp_attrs);
+ return -ENOMEM;
+ }
+ }
+
+ attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
+ if (!attrs) {
+ kfree(tz->trip_type_attrs);
+ kfree(tz->trip_temp_attrs);
+ if (tz->ops->get_trip_hyst)
+ kfree(tz->trip_hyst_attrs);
+ return -ENOMEM;
+ }
+
+ for (indx = 0; indx < tz->trips; indx++) {
+ /* create trip type attribute */
+ snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_type", indx);
+
+ sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
+ tz->trip_type_attrs[indx].attr.attr.name =
+ tz->trip_type_attrs[indx].name;
+ tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
+ tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
+ attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
+
+ /* create trip temp attribute */
+ snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_temp", indx);
+
+ sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
+ tz->trip_temp_attrs[indx].attr.attr.name =
+ tz->trip_temp_attrs[indx].name;
+ tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
+ tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
+ if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
+ mask & (1 << indx)) {
+ tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
+ tz->trip_temp_attrs[indx].attr.store =
+ trip_point_temp_store;
+ }
+ attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
+
+ /* create Optional trip hyst attribute */
+ if (!tz->ops->get_trip_hyst)
+ continue;
+ snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_hyst", indx);
+
+ sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
+ tz->trip_hyst_attrs[indx].attr.attr.name =
+ tz->trip_hyst_attrs[indx].name;
+ tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
+ tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
+ if (tz->ops->set_trip_hyst) {
+ tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
+ tz->trip_hyst_attrs[indx].attr.store =
+ trip_point_hyst_store;
+ }
+ attrs[indx + tz->trips * 2] =
+ &tz->trip_hyst_attrs[indx].attr.attr;
+ }
+ attrs[tz->trips * 3] = NULL;
+
+ tz->trips_attribute_group.attrs = attrs;
+
+ return 0;
+}
+
+int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
+ int mask)
+{
+ const struct attribute_group **groups;
+ int i, size, result;
+
+ /* we need one extra for trips and the NULL to terminate the array */
+ size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
+ /* This also takes care of API requirement to be NULL terminated */
+ groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
+ if (!groups)
+ return -ENOMEM;
+
+ for (i = 0; i < size - 2; i++)
+ groups[i] = thermal_zone_attribute_groups[i];
+
+ if (tz->trips) {
+ result = create_trip_attrs(tz, mask);
+ if (result) {
+ kfree(groups);
+
+ return result;
+ }
+
+ groups[size - 2] = &tz->trips_attribute_group;
+ }
+
+ tz->device.groups = groups;
+
+ return 0;
+}
+
+/* sys I/F for cooling device */
+static ssize_t
+thermal_cooling_device_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+ return sprintf(buf, "%s\n", cdev->type);
+}
+
+static ssize_t
+thermal_cooling_device_max_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int ret;
+
+ ret = cdev->ops->get_max_state(cdev, &state);
+ if (ret)
+ return ret;
+ return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+thermal_cooling_device_cur_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int ret;
+
+ ret = cdev->ops->get_cur_state(cdev, &state);
+ if (ret)
+ return ret;
+ return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+thermal_cooling_device_cur_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int result;
+
+ if (sscanf(buf, "%ld\n", &state) != 1)
+ return -EINVAL;
+
+ if ((long)state < 0)
+ return -EINVAL;
+
+ result = cdev->ops->set_cur_state(cdev, state);
+ if (result)
+ return result;
+ return count;
+}
+
+static struct device_attribute dev_attr_cdev_type =
+__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
+static DEVICE_ATTR(max_state, 0444,
+ thermal_cooling_device_max_state_show, NULL);
+static DEVICE_ATTR(cur_state, 0644,
+ thermal_cooling_device_cur_state_show,
+ thermal_cooling_device_cur_state_store);
+
+static struct attribute *cooling_device_attrs[] = {
+ &dev_attr_cdev_type.attr,
+ &dev_attr_max_state.attr,
+ &dev_attr_cur_state.attr,
+ NULL,
+};
+
+static const struct attribute_group cooling_device_attr_group = {
+ .attrs = cooling_device_attrs,
+};
+
+static const struct attribute_group *cooling_device_attr_groups[] = {
+ &cooling_device_attr_group,
+ NULL,
+};
+
+void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
+{
+ cdev->device.groups = cooling_device_attr_groups;
+}
+
+/* these helper will be used only at the time of bindig */
+ssize_t
+thermal_cooling_device_trip_point_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_instance *instance;
+
+ instance =
+ container_of(attr, struct thermal_instance, attr);
+
+ if (instance->trip == THERMAL_TRIPS_NONE)
+ return sprintf(buf, "-1\n");
+ else
+ return sprintf(buf, "%d\n", instance->trip);
+}
+
+ssize_t
+thermal_cooling_device_weight_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_instance *instance;
+
+ instance = container_of(attr, struct thermal_instance, weight_attr);
+
+ return sprintf(buf, "%d\n", instance->weight);
+}
+
+ssize_t
+thermal_cooling_device_weight_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_instance *instance;
+ int ret, weight;
+
+ ret = kstrtoint(buf, 0, &weight);
+ if (ret)
+ return ret;
+
+ instance = container_of(attr, struct thermal_instance, weight_attr);
+ instance->weight = weight;
+
+ return count;
+}
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index 06ea9766a70a..ba9c302454fb 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1298,7 +1298,7 @@ int ti_bandgap_probe(struct platform_device *pdev)
if (IS_ERR(bgp->div_clk)) {
dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n");
ret = PTR_ERR(bgp->div_clk);
- goto free_irqs;
+ goto put_fclock;
}
for (i = 0; i < bgp->conf->sensor_count; i++) {
@@ -1430,8 +1430,9 @@ disable_clk:
if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
clk_disable_unprepare(bgp->fclock);
put_clks:
- clk_put(bgp->fclock);
clk_put(bgp->div_clk);
+put_fclock:
+ clk_put(bgp->fclock);
free_irqs:
if (TI_BANDGAP_HAS(bgp, TSHUT)) {
free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 95f4c1bcdb4c..d93eee2f101b 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -54,37 +54,33 @@ MODULE_PARM_DESC(notify_delay_ms,
* is some wrong values returned by cpuid for number of thresholds.
*/
#define MAX_NUMBER_OF_TRIPS 2
-/* Limit number of package temp zones */
-#define MAX_PKG_TEMP_ZONE_IDS 256
-
-struct phy_dev_entry {
- struct list_head list;
- u16 phys_proc_id;
- u16 first_cpu;
- u32 tj_max;
- int ref_cnt;
- u32 start_pkg_therm_low;
- u32 start_pkg_therm_high;
- struct thermal_zone_device *tzone;
+
+struct pkg_device {
+ int cpu;
+ bool work_scheduled;
+ u32 tj_max;
+ u32 msr_pkg_therm_low;
+ u32 msr_pkg_therm_high;
+ struct delayed_work work;
+ struct thermal_zone_device *tzone;
+ struct cpumask cpumask;
};
static struct thermal_zone_params pkg_temp_tz_params = {
.no_hwmon = true,
};
-/* List maintaining number of package instances */
-static LIST_HEAD(phy_dev_list);
-static DEFINE_MUTEX(phy_dev_list_mutex);
-
-/* Interrupt to work function schedule queue */
-static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work);
+/* Keep track of how many package pointers we allocated in init() */
+static int max_packages __read_mostly;
+/* Array of package pointers */
+static struct pkg_device **packages;
+/* Serializes interrupt notification, work and hotplug */
+static DEFINE_SPINLOCK(pkg_temp_lock);
+/* Protects zone operation in the work function against hotplug removal */
+static DEFINE_MUTEX(thermal_zone_mutex);
-/* To track if the work is already scheduled on a package */
-static u8 *pkg_work_scheduled;
-
-/* Spin lock to prevent races with pkg_work_scheduled */
-static spinlock_t pkg_work_lock;
-static u16 max_phy_id;
+/* The dynamically assigned cpu hotplug state for module_exit() */
+static enum cpuhp_state pkg_thermal_hp_state __read_mostly;
/* Debug counters to show using debugfs */
static struct dentry *debugfs;
@@ -116,22 +112,20 @@ err_out:
return -ENOENT;
}
-static struct phy_dev_entry
- *pkg_temp_thermal_get_phy_entry(unsigned int cpu)
+/*
+ * Protection:
+ *
+ * - cpu hotplug: Read serialized by cpu hotplug lock
+ * Write must hold pkg_temp_lock
+ *
+ * - Other callsites: Must hold pkg_temp_lock
+ */
+static struct pkg_device *pkg_temp_thermal_get_dev(unsigned int cpu)
{
- u16 phys_proc_id = topology_physical_package_id(cpu);
- struct phy_dev_entry *phy_ptr;
-
- mutex_lock(&phy_dev_list_mutex);
-
- list_for_each_entry(phy_ptr, &phy_dev_list, list)
- if (phy_ptr->phys_proc_id == phys_proc_id) {
- mutex_unlock(&phy_dev_list_mutex);
- return phy_ptr;
- }
-
- mutex_unlock(&phy_dev_list_mutex);
+ int pkgid = topology_logical_package_id(cpu);
+ if (pkgid >= 0 && pkgid < max_packages)
+ return packages[pkgid];
return NULL;
}
@@ -141,61 +135,44 @@ static struct phy_dev_entry
*/
static int get_tj_max(int cpu, u32 *tj_max)
{
- u32 eax, edx;
- u32 val;
+ u32 eax, edx, val;
int err;
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err)
- goto err_ret;
- else {
- val = (eax >> 16) & 0xff;
- if (val)
- *tj_max = val * 1000;
- else {
- err = -EINVAL;
- goto err_ret;
- }
- }
+ return err;
- return 0;
-err_ret:
- *tj_max = 0;
- return err;
+ val = (eax >> 16) & 0xff;
+ *tj_max = val * 1000;
+
+ return val ? 0 : -EINVAL;
}
static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
{
+ struct pkg_device *pkgdev = tzd->devdata;
u32 eax, edx;
- struct phy_dev_entry *phy_dev_entry;
- phy_dev_entry = tzd->devdata;
- rdmsr_on_cpu(phy_dev_entry->first_cpu, MSR_IA32_PACKAGE_THERM_STATUS,
- &eax, &edx);
+ rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_STATUS, &eax, &edx);
if (eax & 0x80000000) {
- *temp = phy_dev_entry->tj_max -
- ((eax >> 16) & 0x7f) * 1000;
+ *temp = pkgdev->tj_max - ((eax >> 16) & 0x7f) * 1000;
pr_debug("sys_get_curr_temp %d\n", *temp);
return 0;
}
-
return -EINVAL;
}
static int sys_get_trip_temp(struct thermal_zone_device *tzd,
- int trip, int *temp)
+ int trip, int *temp)
{
- u32 eax, edx;
- struct phy_dev_entry *phy_dev_entry;
- u32 mask, shift;
+ struct pkg_device *pkgdev = tzd->devdata;
unsigned long thres_reg_value;
+ u32 mask, shift, eax, edx;
int ret;
if (trip >= MAX_NUMBER_OF_TRIPS)
return -EINVAL;
- phy_dev_entry = tzd->devdata;
-
if (trip) {
mask = THERM_MASK_THRESHOLD1;
shift = THERM_SHIFT_THRESHOLD1;
@@ -204,14 +181,14 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
shift = THERM_SHIFT_THRESHOLD0;
}
- ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
- MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+ ret = rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+ &eax, &edx);
if (ret < 0)
- return -EINVAL;
+ return ret;
thres_reg_value = (eax & mask) >> shift;
if (thres_reg_value)
- *temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
+ *temp = pkgdev->tj_max - thres_reg_value * 1000;
else
*temp = 0;
pr_debug("sys_get_trip_temp %d\n", *temp);
@@ -219,24 +196,20 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
return 0;
}
-static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
- int temp)
+static int
+sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
{
- u32 l, h;
- struct phy_dev_entry *phy_dev_entry;
- u32 mask, shift, intr;
+ struct pkg_device *pkgdev = tzd->devdata;
+ u32 l, h, mask, shift, intr;
int ret;
- phy_dev_entry = tzd->devdata;
-
- if (trip >= MAX_NUMBER_OF_TRIPS || temp >= phy_dev_entry->tj_max)
+ if (trip >= MAX_NUMBER_OF_TRIPS || temp >= pkgdev->tj_max)
return -EINVAL;
- ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
- MSR_IA32_PACKAGE_THERM_INTERRUPT,
- &l, &h);
+ ret = rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+ &l, &h);
if (ret < 0)
- return -EINVAL;
+ return ret;
if (trip) {
mask = THERM_MASK_THRESHOLD1;
@@ -252,24 +225,20 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
* When users space sets a trip temperature == 0, which is indication
* that, it is no longer interested in receiving notifications.
*/
- if (!temp)
+ if (!temp) {
l &= ~intr;
- else {
- l |= (phy_dev_entry->tj_max - temp)/1000 << shift;
+ } else {
+ l |= (pkgdev->tj_max - temp)/1000 << shift;
l |= intr;
}
- return wrmsr_on_cpu(phy_dev_entry->first_cpu,
- MSR_IA32_PACKAGE_THERM_INTERRUPT,
- l, h);
+ return wrmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
}
-static int sys_get_trip_type(struct thermal_zone_device *thermal,
- int trip, enum thermal_trip_type *type)
+static int sys_get_trip_type(struct thermal_zone_device *thermal, int trip,
+ enum thermal_trip_type *type)
{
-
*type = THERMAL_TRIP_PASSIVE;
-
return 0;
}
@@ -281,7 +250,7 @@ static struct thermal_zone_device_ops tzone_ops = {
.set_trip_temp = sys_set_trip_temp,
};
-static bool pkg_temp_thermal_platform_thermal_rate_control(void)
+static bool pkg_thermal_rate_control(void)
{
return true;
}
@@ -289,8 +258,8 @@ static bool pkg_temp_thermal_platform_thermal_rate_control(void)
/* Enable threshold interrupt on local package/cpu */
static inline void enable_pkg_thres_interrupt(void)
{
- u32 l, h;
u8 thres_0, thres_1;
+ u32 l, h;
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
/* only enable/disable if it had valid threshold value */
@@ -307,271 +276,232 @@ static inline void enable_pkg_thres_interrupt(void)
static inline void disable_pkg_thres_interrupt(void)
{
u32 l, h;
+
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
- wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
- l & (~THERM_INT_THRESHOLD0_ENABLE) &
- (~THERM_INT_THRESHOLD1_ENABLE), h);
+
+ l &= ~(THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
+ wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
}
static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
{
- __u64 msr_val;
+ struct thermal_zone_device *tzone = NULL;
int cpu = smp_processor_id();
- int phy_id = topology_physical_package_id(cpu);
- struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
- bool notify = false;
- unsigned long flags;
-
- if (!phdev)
- return;
+ struct pkg_device *pkgdev;
+ u64 msr_val, wr_val;
- spin_lock_irqsave(&pkg_work_lock, flags);
+ mutex_lock(&thermal_zone_mutex);
+ spin_lock_irq(&pkg_temp_lock);
++pkg_work_cnt;
- if (unlikely(phy_id > max_phy_id)) {
- spin_unlock_irqrestore(&pkg_work_lock, flags);
+
+ pkgdev = pkg_temp_thermal_get_dev(cpu);
+ if (!pkgdev) {
+ spin_unlock_irq(&pkg_temp_lock);
+ mutex_unlock(&thermal_zone_mutex);
return;
}
- pkg_work_scheduled[phy_id] = 0;
- spin_unlock_irqrestore(&pkg_work_lock, flags);
+ pkgdev->work_scheduled = false;
- enable_pkg_thres_interrupt();
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
- if (msr_val & THERM_LOG_THRESHOLD0) {
- wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
- msr_val & ~THERM_LOG_THRESHOLD0);
- notify = true;
- }
- if (msr_val & THERM_LOG_THRESHOLD1) {
- wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
- msr_val & ~THERM_LOG_THRESHOLD1);
- notify = true;
- }
- if (notify) {
- pr_debug("thermal_zone_device_update\n");
- thermal_zone_device_update(phdev->tzone,
- THERMAL_EVENT_UNSPECIFIED);
+ wr_val = msr_val & ~(THERM_LOG_THRESHOLD0 | THERM_LOG_THRESHOLD1);
+ if (wr_val != msr_val) {
+ wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, wr_val);
+ tzone = pkgdev->tzone;
}
+
+ enable_pkg_thres_interrupt();
+ spin_unlock_irq(&pkg_temp_lock);
+
+ /*
+ * If tzone is not NULL, then thermal_zone_mutex will prevent the
+ * concurrent removal in the cpu offline callback.
+ */
+ if (tzone)
+ thermal_zone_device_update(tzone, THERMAL_EVENT_UNSPECIFIED);
+
+ mutex_unlock(&thermal_zone_mutex);
}
-static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
+static void pkg_thermal_schedule_work(int cpu, struct delayed_work *work)
+{
+ unsigned long ms = msecs_to_jiffies(notify_delay_ms);
+
+ schedule_delayed_work_on(cpu, work, ms);
+}
+
+static int pkg_thermal_notify(u64 msr_val)
{
- unsigned long flags;
int cpu = smp_processor_id();
- int phy_id = topology_physical_package_id(cpu);
+ struct pkg_device *pkgdev;
+ unsigned long flags;
- /*
- * When a package is in interrupted state, all CPU's in that package
- * are in the same interrupt state. So scheduling on any one CPU in
- * the package is enough and simply return for others.
- */
- spin_lock_irqsave(&pkg_work_lock, flags);
+ spin_lock_irqsave(&pkg_temp_lock, flags);
++pkg_interrupt_cnt;
- if (unlikely(phy_id > max_phy_id) || unlikely(!pkg_work_scheduled) ||
- pkg_work_scheduled[phy_id]) {
- disable_pkg_thres_interrupt();
- spin_unlock_irqrestore(&pkg_work_lock, flags);
- return -EINVAL;
- }
- pkg_work_scheduled[phy_id] = 1;
- spin_unlock_irqrestore(&pkg_work_lock, flags);
disable_pkg_thres_interrupt();
- schedule_delayed_work_on(cpu,
- &per_cpu(pkg_temp_thermal_threshold_work, cpu),
- msecs_to_jiffies(notify_delay_ms));
- return 0;
-}
-static int find_siblings_cpu(int cpu)
-{
- int i;
- int id = topology_physical_package_id(cpu);
-
- for_each_online_cpu(i)
- if (i != cpu && topology_physical_package_id(i) == id)
- return i;
+ /* Work is per package, so scheduling it once is enough. */
+ pkgdev = pkg_temp_thermal_get_dev(cpu);
+ if (pkgdev && !pkgdev->work_scheduled) {
+ pkgdev->work_scheduled = true;
+ pkg_thermal_schedule_work(pkgdev->cpu, &pkgdev->work);
+ }
+ spin_unlock_irqrestore(&pkg_temp_lock, flags);
return 0;
}
static int pkg_temp_thermal_device_add(unsigned int cpu)
{
- int err;
- u32 tj_max;
- struct phy_dev_entry *phy_dev_entry;
- int thres_count;
- u32 eax, ebx, ecx, edx;
- u8 *temp;
- unsigned long flags;
+ int pkgid = topology_logical_package_id(cpu);
+ u32 tj_max, eax, ebx, ecx, edx;
+ struct pkg_device *pkgdev;
+ int thres_count, err;
+
+ if (pkgid >= max_packages)
+ return -ENOMEM;
cpuid(6, &eax, &ebx, &ecx, &edx);
thres_count = ebx & 0x07;
if (!thres_count)
return -ENODEV;
- if (topology_physical_package_id(cpu) > MAX_PKG_TEMP_ZONE_IDS)
- return -ENODEV;
-
thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
err = get_tj_max(cpu, &tj_max);
if (err)
- goto err_ret;
-
- mutex_lock(&phy_dev_list_mutex);
+ return err;
- phy_dev_entry = kzalloc(sizeof(*phy_dev_entry), GFP_KERNEL);
- if (!phy_dev_entry) {
- err = -ENOMEM;
- goto err_ret_unlock;
- }
+ pkgdev = kzalloc(sizeof(*pkgdev), GFP_KERNEL);
+ if (!pkgdev)
+ return -ENOMEM;
- spin_lock_irqsave(&pkg_work_lock, flags);
- if (topology_physical_package_id(cpu) > max_phy_id)
- max_phy_id = topology_physical_package_id(cpu);
- temp = krealloc(pkg_work_scheduled,
- (max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
- if (!temp) {
- spin_unlock_irqrestore(&pkg_work_lock, flags);
- err = -ENOMEM;
- goto err_ret_free;
- }
- pkg_work_scheduled = temp;
- pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
- spin_unlock_irqrestore(&pkg_work_lock, flags);
-
- phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
- phy_dev_entry->first_cpu = cpu;
- phy_dev_entry->tj_max = tj_max;
- phy_dev_entry->ref_cnt = 1;
- phy_dev_entry->tzone = thermal_zone_device_register("x86_pkg_temp",
+ INIT_DELAYED_WORK(&pkgdev->work, pkg_temp_thermal_threshold_work_fn);
+ pkgdev->cpu = cpu;
+ pkgdev->tj_max = tj_max;
+ pkgdev->tzone = thermal_zone_device_register("x86_pkg_temp",
thres_count,
- (thres_count == MAX_NUMBER_OF_TRIPS) ?
- 0x03 : 0x01,
- phy_dev_entry, &tzone_ops, &pkg_temp_tz_params, 0, 0);
- if (IS_ERR(phy_dev_entry->tzone)) {
- err = PTR_ERR(phy_dev_entry->tzone);
- goto err_ret_free;
+ (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
+ pkgdev, &tzone_ops, &pkg_temp_tz_params, 0, 0);
+ if (IS_ERR(pkgdev->tzone)) {
+ err = PTR_ERR(pkgdev->tzone);
+ kfree(pkgdev);
+ return err;
}
/* Store MSR value for package thermal interrupt, to restore at exit */
- rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
- &phy_dev_entry->start_pkg_therm_low,
- &phy_dev_entry->start_pkg_therm_high);
-
- list_add_tail(&phy_dev_entry->list, &phy_dev_list);
- pr_debug("pkg_temp_thermal_device_add :phy_id %d cpu %d\n",
- phy_dev_entry->phys_proc_id, cpu);
-
- mutex_unlock(&phy_dev_list_mutex);
+ rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, pkgdev->msr_pkg_therm_low,
+ pkgdev->msr_pkg_therm_high);
+ cpumask_set_cpu(cpu, &pkgdev->cpumask);
+ spin_lock_irq(&pkg_temp_lock);
+ packages[pkgid] = pkgdev;
+ spin_unlock_irq(&pkg_temp_lock);
return 0;
-
-err_ret_free:
- kfree(phy_dev_entry);
-err_ret_unlock:
- mutex_unlock(&phy_dev_list_mutex);
-
-err_ret:
- return err;
}
-static int pkg_temp_thermal_device_remove(unsigned int cpu)
+static int pkg_thermal_cpu_offline(unsigned int cpu)
{
- struct phy_dev_entry *n;
- u16 phys_proc_id = topology_physical_package_id(cpu);
- struct phy_dev_entry *phdev =
- pkg_temp_thermal_get_phy_entry(cpu);
+ struct pkg_device *pkgdev = pkg_temp_thermal_get_dev(cpu);
+ bool lastcpu, was_target;
+ int target;
- if (!phdev)
- return -ENODEV;
+ if (!pkgdev)
+ return 0;
- mutex_lock(&phy_dev_list_mutex);
- /* If we are loosing the first cpu for this package, we need change */
- if (phdev->first_cpu == cpu) {
- phdev->first_cpu = find_siblings_cpu(cpu);
- pr_debug("thermal_device_remove: first cpu switched %d\n",
- phdev->first_cpu);
+ target = cpumask_any_but(&pkgdev->cpumask, cpu);
+ cpumask_clear_cpu(cpu, &pkgdev->cpumask);
+ lastcpu = target >= nr_cpu_ids;
+ /*
+ * Remove the sysfs files, if this is the last cpu in the package
+ * before doing further cleanups.
+ */
+ if (lastcpu) {
+ struct thermal_zone_device *tzone = pkgdev->tzone;
+
+ /*
+ * We must protect against a work function calling
+ * thermal_zone_update, after/while unregister. We null out
+ * the pointer under the zone mutex, so the worker function
+ * won't try to call.
+ */
+ mutex_lock(&thermal_zone_mutex);
+ pkgdev->tzone = NULL;
+ mutex_unlock(&thermal_zone_mutex);
+
+ thermal_zone_device_unregister(tzone);
}
+
+ /* Protect against work and interrupts */
+ spin_lock_irq(&pkg_temp_lock);
+
/*
- * It is possible that no siblings left as this was the last cpu
- * going offline. We don't need to worry about this assignment
- * as the phydev entry will be removed in this case and
- * thermal zone is removed.
- */
- --phdev->ref_cnt;
- pr_debug("thermal_device_remove: pkg: %d cpu %d ref_cnt %d\n",
- phys_proc_id, cpu, phdev->ref_cnt);
- if (!phdev->ref_cnt)
- list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
- if (phdev->phys_proc_id == phys_proc_id) {
- thermal_zone_device_unregister(phdev->tzone);
- list_del(&phdev->list);
- kfree(phdev);
- break;
- }
- }
- mutex_unlock(&phy_dev_list_mutex);
+ * Check whether this cpu was the current target and store the new
+ * one. When we drop the lock, then the interrupt notify function
+ * will see the new target.
+ */
+ was_target = pkgdev->cpu == cpu;
+ pkgdev->cpu = target;
- return 0;
-}
+ /*
+ * If this is the last CPU in the package remove the package
+ * reference from the array and restore the interrupt MSR. When we
+ * drop the lock neither the interrupt notify function nor the
+ * worker will see the package anymore.
+ */
+ if (lastcpu) {
+ packages[topology_logical_package_id(cpu)] = NULL;
+ /* After this point nothing touches the MSR anymore. */
+ wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
+ pkgdev->msr_pkg_therm_low, pkgdev->msr_pkg_therm_high);
+ }
-static int get_core_online(unsigned int cpu)
-{
- struct cpuinfo_x86 *c = &cpu_data(cpu);
- struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
-
- /* Check if there is already an instance for this package */
- if (!phdev) {
- if (!cpu_has(c, X86_FEATURE_DTHERM) ||
- !cpu_has(c, X86_FEATURE_PTS))
- return -ENODEV;
- if (pkg_temp_thermal_device_add(cpu))
- return -ENODEV;
- } else {
- mutex_lock(&phy_dev_list_mutex);
- ++phdev->ref_cnt;
- pr_debug("get_core_online: cpu %d ref_cnt %d\n",
- cpu, phdev->ref_cnt);
- mutex_unlock(&phy_dev_list_mutex);
+ /*
+ * Check whether there is work scheduled and whether the work is
+ * targeted at the outgoing CPU.
+ */
+ if (pkgdev->work_scheduled && was_target) {
+ /*
+ * To cancel the work we need to drop the lock, otherwise
+ * we might deadlock if the work needs to be flushed.
+ */
+ spin_unlock_irq(&pkg_temp_lock);
+ cancel_delayed_work_sync(&pkgdev->work);
+ spin_lock_irq(&pkg_temp_lock);
+ /*
+ * If this is not the last cpu in the package and the work
+ * did not run after we dropped the lock above, then we
+ * need to reschedule the work, otherwise the interrupt
+ * stays disabled forever.
+ */
+ if (!lastcpu && pkgdev->work_scheduled)
+ pkg_thermal_schedule_work(target, &pkgdev->work);
}
- INIT_DELAYED_WORK(&per_cpu(pkg_temp_thermal_threshold_work, cpu),
- pkg_temp_thermal_threshold_work_fn);
- pr_debug("get_core_online: cpu %d successful\n", cpu);
+ spin_unlock_irq(&pkg_temp_lock);
+ /* Final cleanup if this is the last cpu */
+ if (lastcpu)
+ kfree(pkgdev);
return 0;
}
-static void put_core_offline(unsigned int cpu)
+static int pkg_thermal_cpu_online(unsigned int cpu)
{
- if (!pkg_temp_thermal_device_remove(cpu))
- cancel_delayed_work_sync(
- &per_cpu(pkg_temp_thermal_threshold_work, cpu));
+ struct pkg_device *pkgdev = pkg_temp_thermal_get_dev(cpu);
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
- pr_debug("put_core_offline: cpu %d\n", cpu);
-}
+ /* Paranoia check */
+ if (!cpu_has(c, X86_FEATURE_DTHERM) || !cpu_has(c, X86_FEATURE_PTS))
+ return -ENODEV;
-static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long) hcpu;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- case CPU_DOWN_FAILED:
- get_core_online(cpu);
- break;
- case CPU_DOWN_PREPARE:
- put_core_offline(cpu);
- break;
+ /* If the package exists, nothing to do */
+ if (pkgdev) {
+ cpumask_set_cpu(cpu, &pkgdev->cpumask);
+ return 0;
}
- return NOTIFY_OK;
+ return pkg_temp_thermal_device_add(cpu);
}
-static struct notifier_block pkg_temp_thermal_notifier __refdata = {
- .notifier_call = pkg_temp_thermal_cpu_callback,
-};
-
static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = {
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_PTS },
{}
@@ -580,71 +510,46 @@ MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids);
static int __init pkg_temp_thermal_init(void)
{
- int i;
+ int ret;
if (!x86_match_cpu(pkg_temp_thermal_ids))
return -ENODEV;
- spin_lock_init(&pkg_work_lock);
- platform_thermal_package_notify =
- pkg_temp_thermal_platform_thermal_notify;
- platform_thermal_package_rate_control =
- pkg_temp_thermal_platform_thermal_rate_control;
+ max_packages = topology_max_packages();
+ packages = kzalloc(max_packages * sizeof(struct pkg_device *), GFP_KERNEL);
+ if (!packages)
+ return -ENOMEM;
- cpu_notifier_register_begin();
- for_each_online_cpu(i)
- if (get_core_online(i))
- goto err_ret;
- __register_hotcpu_notifier(&pkg_temp_thermal_notifier);
- cpu_notifier_register_done();
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "thermal/x86_pkg:online",
+ pkg_thermal_cpu_online, pkg_thermal_cpu_offline);
+ if (ret < 0)
+ goto err;
- pkg_temp_debugfs_init(); /* Don't care if fails */
+ /* Store the state for module exit */
+ pkg_thermal_hp_state = ret;
- return 0;
+ platform_thermal_package_notify = pkg_thermal_notify;
+ platform_thermal_package_rate_control = pkg_thermal_rate_control;
-err_ret:
- for_each_online_cpu(i)
- put_core_offline(i);
- cpu_notifier_register_done();
- kfree(pkg_work_scheduled);
- platform_thermal_package_notify = NULL;
- platform_thermal_package_rate_control = NULL;
+ /* Don't care if it fails */
+ pkg_temp_debugfs_init();
+ return 0;
- return -ENODEV;
+err:
+ kfree(packages);
+ return ret;
}
+module_init(pkg_temp_thermal_init)
static void __exit pkg_temp_thermal_exit(void)
{
- struct phy_dev_entry *phdev, *n;
- int i;
-
- cpu_notifier_register_begin();
- __unregister_hotcpu_notifier(&pkg_temp_thermal_notifier);
- mutex_lock(&phy_dev_list_mutex);
- list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
- /* Retore old MSR value for package thermal interrupt */
- wrmsr_on_cpu(phdev->first_cpu,
- MSR_IA32_PACKAGE_THERM_INTERRUPT,
- phdev->start_pkg_therm_low,
- phdev->start_pkg_therm_high);
- thermal_zone_device_unregister(phdev->tzone);
- list_del(&phdev->list);
- kfree(phdev);
- }
- mutex_unlock(&phy_dev_list_mutex);
platform_thermal_package_notify = NULL;
platform_thermal_package_rate_control = NULL;
- for_each_online_cpu(i)
- cancel_delayed_work_sync(
- &per_cpu(pkg_temp_thermal_threshold_work, i));
- cpu_notifier_register_done();
-
- kfree(pkg_work_scheduled);
+ cpuhp_remove_state(pkg_thermal_hp_state);
debugfs_remove_recursive(debugfs);
+ kfree(packages);
}
-
-module_init(pkg_temp_thermal_init)
module_exit(pkg_temp_thermal_exit)
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
index c121acc15bfe..d35db16aa43f 100644
--- a/drivers/thunderbolt/Kconfig
+++ b/drivers/thunderbolt/Kconfig
@@ -1,6 +1,8 @@
menuconfig THUNDERBOLT
tristate "Thunderbolt support for Apple devices"
depends on PCI
+ depends on X86 || COMPILE_TEST
+ select APPLE_PROPERTIES if EFI_STUB && X86
select CRC32
help
Cactus Ridge Thunderbolt Controller driver
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 2b9602c2c355..6392990c984d 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -5,6 +5,7 @@
*/
#include <linux/crc32.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include "tb.h"
@@ -360,6 +361,40 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
}
/**
+ * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
+ */
+static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
+{
+ struct device *dev = &sw->tb->nhi->pdev->dev;
+ int len, res;
+
+ len = device_property_read_u8_array(dev, "ThunderboltDROM", NULL, 0);
+ if (len < 0 || len < sizeof(struct tb_drom_header))
+ return -EINVAL;
+
+ sw->drom = kmalloc(len, GFP_KERNEL);
+ if (!sw->drom)
+ return -ENOMEM;
+
+ res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom,
+ len);
+ if (res)
+ goto err;
+
+ *size = ((struct tb_drom_header *)sw->drom)->data_len +
+ TB_DROM_DATA_START;
+ if (*size > len)
+ goto err;
+
+ return 0;
+
+err:
+ kfree(sw->drom);
+ sw->drom = NULL;
+ return -EINVAL;
+}
+
+/**
* tb_drom_read - copy drom to sw->drom and parse it
*/
int tb_drom_read(struct tb_switch *sw)
@@ -374,6 +409,13 @@ int tb_drom_read(struct tb_switch *sw)
if (tb_route(sw) == 0) {
/*
+ * Apple's NHI EFI driver supplies a DROM for the root switch
+ * in a device property. Use it if available.
+ */
+ if (tb_drom_copy_efi(sw, &size) == 0)
+ goto parse;
+
+ /*
* The root switch contains only a dummy drom (header only,
* no entries). Hardcode the configuration here.
*/
@@ -418,6 +460,7 @@ int tb_drom_read(struct tb_switch *sw)
if (res)
goto err;
+parse:
header = (void *) sw->drom;
if (header->data_len + TB_DROM_DATA_START != size) {
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 9840fdecb73b..c6f30b1695a9 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -460,7 +460,7 @@ int tb_switch_resume(struct tb_switch *sw)
tb_sw_warn(sw, "uid read failed\n");
return err;
}
- if (sw->uid != uid) {
+ if (sw != sw->tb->root_switch && sw->uid != uid) {
tb_sw_info(sw,
"changed while suspended (uid %#llx -> %#llx)\n",
sw->uid, uid);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 54cab59e20ed..f3932baed07d 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2711,15 +2711,6 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
return;
}
-static int gsm_change_mtu(struct net_device *net, int new_mtu)
-{
- struct gsm_mux_net *mux_net = netdev_priv(net);
- if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
- return -EINVAL;
- net->mtu = new_mtu;
- return 0;
-}
-
static void gsm_mux_net_init(struct net_device *net)
{
static const struct net_device_ops gsm_netdev_ops = {
@@ -2728,7 +2719,6 @@ static void gsm_mux_net_init(struct net_device *net)
.ndo_start_xmit = gsm_mux_net_start_xmit,
.ndo_tx_timeout = gsm_mux_net_tx_timeout,
.ndo_get_stats = gsm_mux_net_get_stats,
- .ndo_change_mtu = gsm_change_mtu,
};
net->netdev_ops = &gsm_netdev_ops;
@@ -2787,6 +2777,8 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
return -ENOMEM;
}
net->mtu = dlci->gsm->mtu;
+ net->min_mtu = 8;
+ net->max_mtu = dlci->gsm->mtu;
mux_net = netdev_priv(net);
mux_net->dlci = dlci;
kref_init(&mux_net->ref);
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 315c84979b18..6450a38cb1aa 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -28,7 +28,6 @@ static char *serial_version = "$Revision: 1.25 $";
#include <linux/bitops.h>
#include <linux/seq_file.h>
#include <linux/delay.h>
-#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -4098,7 +4097,7 @@ static void show_serial_version(void)
&serial_version[11]); /* "$Revision: x.yy" */
}
-/* rs_init inits the driver at boot (using the module_init chain) */
+/* rs_init inits the driver at boot (using the initcall chain) */
static const struct tty_operations rs_ops = {
.open = rs_open,
@@ -4247,5 +4246,4 @@ static int __init rs_init(void)
}
/* this makes sure that rs_init is called during kernel boot */
-
-module_init(rs_init);
+device_initcall(rs_init);
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index c13e27ecb0b7..415885c56435 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -7973,7 +7973,6 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
static const struct net_device_ops hdlcdev_ops = {
.ndo_open = hdlcdev_open,
.ndo_stop = hdlcdev_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hdlcdev_ioctl,
.ndo_tx_timeout = hdlcdev_tx_timeout,
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 7aca2d4670e4..8267bcf2405e 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -1768,7 +1768,6 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
static const struct net_device_ops hdlcdev_ops = {
.ndo_open = hdlcdev_open,
.ndo_stop = hdlcdev_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hdlcdev_ioctl,
.ndo_tx_timeout = hdlcdev_tx_timeout,
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index dec156586de1..d66620f7eaa3 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -1887,7 +1887,6 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
static const struct net_device_ops hdlcdev_ops = {
.ndo_open = hdlcdev_open,
.ndo_stop = hdlcdev_close,
- .ndo_change_mtu = hdlc_change_mtu,
.ndo_start_xmit = hdlc_start_xmit,
.ndo_do_ioctl = hdlcdev_ioctl,
.ndo_tx_timeout = hdlcdev_tx_timeout,
diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
index 0473d619d5bf..b4058f0000e4 100644
--- a/drivers/usb/gadget/function/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
@@ -261,19 +261,10 @@ out:
return NETDEV_TX_OK;
}
-static int pn_net_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops pn_netdev_ops = {
.ndo_open = pn_net_open,
.ndo_stop = pn_net_close,
.ndo_start_xmit = pn_net_xmit,
- .ndo_change_mtu = pn_net_mtu,
};
static void pn_net_setup(struct net_device *dev)
@@ -282,6 +273,8 @@ static void pn_net_setup(struct net_device *dev)
dev->type = ARPHRD_PHONET;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = PHONET_DEV_MTU;
+ dev->min_mtu = PHONET_MIN_MTU;
+ dev->max_mtu = PHONET_MAX_MTU;
dev->hard_header_len = 1;
dev->dev_addr[0] = PN_MEDIA_USB;
dev->addr_len = 1;
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 5d1bd13a56c1..84a1709e0784 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -142,15 +142,6 @@ static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-static int ueth_change_mtu(struct net_device *net, int new_mtu)
-{
- if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN)
- return -ERANGE;
- net->mtu = new_mtu;
-
- return 0;
-}
-
static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
{
struct eth_dev *dev = netdev_priv(net);
@@ -729,7 +720,6 @@ static const struct net_device_ops eth_netdev_ops = {
.ndo_open = eth_open,
.ndo_stop = eth_stop,
.ndo_start_xmit = eth_start_xmit,
- .ndo_change_mtu = ueth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -792,6 +782,10 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
net->ethtool_ops = &ops;
+ /* MTU range: 14 - 15412 */
+ net->min_mtu = ETH_HLEN;
+ net->max_mtu = GETHER_MAX_ETH_FRAME_LEN;
+
dev->gadget = g;
SET_NETDEV_DEV(net, &g->dev);
SET_NETDEV_DEVTYPE(net, &gadget_type);
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index da6e2ce77495..23eced02aaf6 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -48,4 +48,5 @@ menuconfig VFIO_NOIOMMU
source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
+source "drivers/vfio/mdev/Kconfig"
source "virt/lib/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 7b8a31f63fea..4a23c13b6be4 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
obj-$(CONFIG_VFIO_PCI) += pci/
obj-$(CONFIG_VFIO_PLATFORM) += platform/
+obj-$(CONFIG_VFIO_MDEV) += mdev/
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig
new file mode 100644
index 000000000000..14fdb106a827
--- /dev/null
+++ b/drivers/vfio/mdev/Kconfig
@@ -0,0 +1,17 @@
+
+config VFIO_MDEV
+ tristate "Mediated device driver framework"
+ depends on VFIO
+ default n
+ help
+ Provides a framework to virtualize devices.
+ See Documentation/vfio-mediated-device.txt for more details.
+
+ If you don't know what do here, say N.
+
+config VFIO_MDEV_DEVICE
+ tristate "VFIO driver for Mediated devices"
+ depends on VFIO && VFIO_MDEV
+ default n
+ help
+ VFIO based driver for Mediated devices.
diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile
new file mode 100644
index 000000000000..fa2d5ea466ee
--- /dev/null
+++ b/drivers/vfio/mdev/Makefile
@@ -0,0 +1,5 @@
+
+mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o
+
+obj-$(CONFIG_VFIO_MDEV) += mdev.o
+obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
new file mode 100644
index 000000000000..be1ee89ee917
--- /dev/null
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -0,0 +1,385 @@
+/*
+ * Mediated device Core Driver
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <linux/sysfs.h>
+#include <linux/mdev.h>
+
+#include "mdev_private.h"
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_AUTHOR "NVIDIA Corporation"
+#define DRIVER_DESC "Mediated device Core Driver"
+
+static LIST_HEAD(parent_list);
+static DEFINE_MUTEX(parent_list_lock);
+static struct class_compat *mdev_bus_compat_class;
+
+static int _find_mdev_device(struct device *dev, void *data)
+{
+ struct mdev_device *mdev;
+
+ if (!dev_is_mdev(dev))
+ return 0;
+
+ mdev = to_mdev_device(dev);
+
+ if (uuid_le_cmp(mdev->uuid, *(uuid_le *)data) == 0)
+ return 1;
+
+ return 0;
+}
+
+static bool mdev_device_exist(struct parent_device *parent, uuid_le uuid)
+{
+ struct device *dev;
+
+ dev = device_find_child(parent->dev, &uuid, _find_mdev_device);
+ if (dev) {
+ put_device(dev);
+ return true;
+ }
+
+ return false;
+}
+
+/* Should be called holding parent_list_lock */
+static struct parent_device *__find_parent_device(struct device *dev)
+{
+ struct parent_device *parent;
+
+ list_for_each_entry(parent, &parent_list, next) {
+ if (parent->dev == dev)
+ return parent;
+ }
+ return NULL;
+}
+
+static void mdev_release_parent(struct kref *kref)
+{
+ struct parent_device *parent = container_of(kref, struct parent_device,
+ ref);
+ struct device *dev = parent->dev;
+
+ kfree(parent);
+ put_device(dev);
+}
+
+static
+inline struct parent_device *mdev_get_parent(struct parent_device *parent)
+{
+ if (parent)
+ kref_get(&parent->ref);
+
+ return parent;
+}
+
+static inline void mdev_put_parent(struct parent_device *parent)
+{
+ if (parent)
+ kref_put(&parent->ref, mdev_release_parent);
+}
+
+static int mdev_device_create_ops(struct kobject *kobj,
+ struct mdev_device *mdev)
+{
+ struct parent_device *parent = mdev->parent;
+ int ret;
+
+ ret = parent->ops->create(kobj, mdev);
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_groups(&mdev->dev.kobj,
+ parent->ops->mdev_attr_groups);
+ if (ret)
+ parent->ops->remove(mdev);
+
+ return ret;
+}
+
+/*
+ * mdev_device_remove_ops gets called from sysfs's 'remove' and when parent
+ * device is being unregistered from mdev device framework.
+ * - 'force_remove' is set to 'false' when called from sysfs's 'remove' which
+ * indicates that if the mdev device is active, used by VMM or userspace
+ * application, vendor driver could return error then don't remove the device.
+ * - 'force_remove' is set to 'true' when called from mdev_unregister_device()
+ * which indicate that parent device is being removed from mdev device
+ * framework so remove mdev device forcefully.
+ */
+static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove)
+{
+ struct parent_device *parent = mdev->parent;
+ int ret;
+
+ /*
+ * Vendor driver can return error if VMM or userspace application is
+ * using this mdev device.
+ */
+ ret = parent->ops->remove(mdev);
+ if (ret && !force_remove)
+ return -EBUSY;
+
+ sysfs_remove_groups(&mdev->dev.kobj, parent->ops->mdev_attr_groups);
+ return 0;
+}
+
+static int mdev_device_remove_cb(struct device *dev, void *data)
+{
+ if (!dev_is_mdev(dev))
+ return 0;
+
+ return mdev_device_remove(dev, data ? *(bool *)data : true);
+}
+
+/*
+ * mdev_register_device : Register a device
+ * @dev: device structure representing parent device.
+ * @ops: Parent device operation structure to be registered.
+ *
+ * Add device to list of registered parent devices.
+ * Returns a negative value on error, otherwise 0.
+ */
+int mdev_register_device(struct device *dev, const struct parent_ops *ops)
+{
+ int ret;
+ struct parent_device *parent;
+
+ /* check for mandatory ops */
+ if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups)
+ return -EINVAL;
+
+ dev = get_device(dev);
+ if (!dev)
+ return -EINVAL;
+
+ mutex_lock(&parent_list_lock);
+
+ /* Check for duplicate */
+ parent = __find_parent_device(dev);
+ if (parent) {
+ ret = -EEXIST;
+ goto add_dev_err;
+ }
+
+ parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+ if (!parent) {
+ ret = -ENOMEM;
+ goto add_dev_err;
+ }
+
+ kref_init(&parent->ref);
+ mutex_init(&parent->lock);
+
+ parent->dev = dev;
+ parent->ops = ops;
+
+ if (!mdev_bus_compat_class) {
+ mdev_bus_compat_class = class_compat_register("mdev_bus");
+ if (!mdev_bus_compat_class) {
+ ret = -ENOMEM;
+ goto add_dev_err;
+ }
+ }
+
+ ret = parent_create_sysfs_files(parent);
+ if (ret)
+ goto add_dev_err;
+
+ ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL);
+ if (ret)
+ dev_warn(dev, "Failed to create compatibility class link\n");
+
+ list_add(&parent->next, &parent_list);
+ mutex_unlock(&parent_list_lock);
+
+ dev_info(dev, "MDEV: Registered\n");
+ return 0;
+
+add_dev_err:
+ mutex_unlock(&parent_list_lock);
+ if (parent)
+ mdev_put_parent(parent);
+ else
+ put_device(dev);
+ return ret;
+}
+EXPORT_SYMBOL(mdev_register_device);
+
+/*
+ * mdev_unregister_device : Unregister a parent device
+ * @dev: device structure representing parent device.
+ *
+ * Remove device from list of registered parent devices. Give a chance to free
+ * existing mediated devices for given device.
+ */
+
+void mdev_unregister_device(struct device *dev)
+{
+ struct parent_device *parent;
+ bool force_remove = true;
+
+ mutex_lock(&parent_list_lock);
+ parent = __find_parent_device(dev);
+
+ if (!parent) {
+ mutex_unlock(&parent_list_lock);
+ return;
+ }
+ dev_info(dev, "MDEV: Unregistering\n");
+
+ list_del(&parent->next);
+ class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
+
+ device_for_each_child(dev, (void *)&force_remove,
+ mdev_device_remove_cb);
+
+ parent_remove_sysfs_files(parent);
+
+ mutex_unlock(&parent_list_lock);
+ mdev_put_parent(parent);
+}
+EXPORT_SYMBOL(mdev_unregister_device);
+
+static void mdev_device_release(struct device *dev)
+{
+ struct mdev_device *mdev = to_mdev_device(dev);
+
+ dev_dbg(&mdev->dev, "MDEV: destroying\n");
+ kfree(mdev);
+}
+
+int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
+{
+ int ret;
+ struct mdev_device *mdev;
+ struct parent_device *parent;
+ struct mdev_type *type = to_mdev_type(kobj);
+
+ parent = mdev_get_parent(type->parent);
+ if (!parent)
+ return -EINVAL;
+
+ mutex_lock(&parent->lock);
+
+ /* Check for duplicate */
+ if (mdev_device_exist(parent, uuid)) {
+ ret = -EEXIST;
+ goto create_err;
+ }
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev) {
+ ret = -ENOMEM;
+ goto create_err;
+ }
+
+ memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
+ mdev->parent = parent;
+ kref_init(&mdev->ref);
+
+ mdev->dev.parent = dev;
+ mdev->dev.bus = &mdev_bus_type;
+ mdev->dev.release = mdev_device_release;
+ dev_set_name(&mdev->dev, "%pUl", uuid.b);
+
+ ret = device_register(&mdev->dev);
+ if (ret) {
+ put_device(&mdev->dev);
+ goto create_err;
+ }
+
+ ret = mdev_device_create_ops(kobj, mdev);
+ if (ret)
+ goto create_failed;
+
+ ret = mdev_create_sysfs_files(&mdev->dev, type);
+ if (ret) {
+ mdev_device_remove_ops(mdev, true);
+ goto create_failed;
+ }
+
+ mdev->type_kobj = kobj;
+ dev_dbg(&mdev->dev, "MDEV: created\n");
+
+ mutex_unlock(&parent->lock);
+ return ret;
+
+create_failed:
+ device_unregister(&mdev->dev);
+
+create_err:
+ mutex_unlock(&parent->lock);
+ mdev_put_parent(parent);
+ return ret;
+}
+
+int mdev_device_remove(struct device *dev, bool force_remove)
+{
+ struct mdev_device *mdev;
+ struct parent_device *parent;
+ struct mdev_type *type;
+ int ret;
+
+ mdev = to_mdev_device(dev);
+ type = to_mdev_type(mdev->type_kobj);
+ parent = mdev->parent;
+ mutex_lock(&parent->lock);
+
+ ret = mdev_device_remove_ops(mdev, force_remove);
+ if (ret) {
+ mutex_unlock(&parent->lock);
+ return ret;
+ }
+
+ mdev_remove_sysfs_files(dev, type);
+ device_unregister(dev);
+ mutex_unlock(&parent->lock);
+ mdev_put_parent(parent);
+ return ret;
+}
+
+static int __init mdev_init(void)
+{
+ int ret;
+
+ ret = mdev_bus_register();
+
+ /*
+ * Attempt to load known vfio_mdev. This gives us a working environment
+ * without the user needing to explicitly load vfio_mdev driver.
+ */
+ if (!ret)
+ request_module_nowait("vfio_mdev");
+
+ return ret;
+}
+
+static void __exit mdev_exit(void)
+{
+ if (mdev_bus_compat_class)
+ class_compat_unregister(mdev_bus_compat_class);
+
+ mdev_bus_unregister();
+}
+
+module_init(mdev_init)
+module_exit(mdev_exit)
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
new file mode 100644
index 000000000000..6f0391f6f9b6
--- /dev/null
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -0,0 +1,119 @@
+/*
+ * MDEV driver
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/device.h>
+#include <linux/iommu.h>
+#include <linux/mdev.h>
+
+#include "mdev_private.h"
+
+static int mdev_attach_iommu(struct mdev_device *mdev)
+{
+ int ret;
+ struct iommu_group *group;
+
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ ret = iommu_group_add_device(group, &mdev->dev);
+ if (!ret)
+ dev_info(&mdev->dev, "MDEV: group_id = %d\n",
+ iommu_group_id(group));
+
+ iommu_group_put(group);
+ return ret;
+}
+
+static void mdev_detach_iommu(struct mdev_device *mdev)
+{
+ iommu_group_remove_device(&mdev->dev);
+ dev_info(&mdev->dev, "MDEV: detaching iommu\n");
+}
+
+static int mdev_probe(struct device *dev)
+{
+ struct mdev_driver *drv = to_mdev_driver(dev->driver);
+ struct mdev_device *mdev = to_mdev_device(dev);
+ int ret;
+
+ ret = mdev_attach_iommu(mdev);
+ if (ret)
+ return ret;
+
+ if (drv && drv->probe) {
+ ret = drv->probe(dev);
+ if (ret)
+ mdev_detach_iommu(mdev);
+ }
+
+ return ret;
+}
+
+static int mdev_remove(struct device *dev)
+{
+ struct mdev_driver *drv = to_mdev_driver(dev->driver);
+ struct mdev_device *mdev = to_mdev_device(dev);
+
+ if (drv && drv->remove)
+ drv->remove(dev);
+
+ mdev_detach_iommu(mdev);
+
+ return 0;
+}
+
+struct bus_type mdev_bus_type = {
+ .name = "mdev",
+ .probe = mdev_probe,
+ .remove = mdev_remove,
+};
+EXPORT_SYMBOL_GPL(mdev_bus_type);
+
+/**
+ * mdev_register_driver - register a new MDEV driver
+ * @drv: the driver to register
+ * @owner: module owner of driver to be registered
+ *
+ * Returns a negative value on error, otherwise 0.
+ **/
+int mdev_register_driver(struct mdev_driver *drv, struct module *owner)
+{
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &mdev_bus_type;
+ drv->driver.owner = owner;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(mdev_register_driver);
+
+/*
+ * mdev_unregister_driver - unregister MDEV driver
+ * @drv: the driver to unregister
+ */
+void mdev_unregister_driver(struct mdev_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(mdev_unregister_driver);
+
+int mdev_bus_register(void)
+{
+ return bus_register(&mdev_bus_type);
+}
+
+void mdev_bus_unregister(void)
+{
+ bus_unregister(&mdev_bus_type);
+}
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
new file mode 100644
index 000000000000..d35097cbf3d7
--- /dev/null
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -0,0 +1,41 @@
+/*
+ * Mediated device interal definitions
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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.
+ */
+
+#ifndef MDEV_PRIVATE_H
+#define MDEV_PRIVATE_H
+
+int mdev_bus_register(void);
+void mdev_bus_unregister(void);
+
+struct mdev_type {
+ struct kobject kobj;
+ struct kobject *devices_kobj;
+ struct parent_device *parent;
+ struct list_head next;
+ struct attribute_group *group;
+};
+
+#define to_mdev_type_attr(_attr) \
+ container_of(_attr, struct mdev_type_attribute, attr)
+#define to_mdev_type(_kobj) \
+ container_of(_kobj, struct mdev_type, kobj)
+
+int parent_create_sysfs_files(struct parent_device *parent);
+void parent_remove_sysfs_files(struct parent_device *parent);
+
+int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type);
+void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);
+
+int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid);
+int mdev_device_remove(struct device *dev, bool force_remove);
+
+#endif /* MDEV_PRIVATE_H */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
new file mode 100644
index 000000000000..1a53deb2ee10
--- /dev/null
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -0,0 +1,286 @@
+/*
+ * File attributes for Mediated devices
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <linux/mdev.h>
+
+#include "mdev_private.h"
+
+/* Static functions */
+
+static ssize_t mdev_type_attr_show(struct kobject *kobj,
+ struct attribute *__attr, char *buf)
+{
+ struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
+ struct mdev_type *type = to_mdev_type(kobj);
+ ssize_t ret = -EIO;
+
+ if (attr->show)
+ ret = attr->show(kobj, type->parent->dev, buf);
+ return ret;
+}
+
+static ssize_t mdev_type_attr_store(struct kobject *kobj,
+ struct attribute *__attr,
+ const char *buf, size_t count)
+{
+ struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
+ struct mdev_type *type = to_mdev_type(kobj);
+ ssize_t ret = -EIO;
+
+ if (attr->store)
+ ret = attr->store(&type->kobj, type->parent->dev, buf, count);
+ return ret;
+}
+
+static const struct sysfs_ops mdev_type_sysfs_ops = {
+ .show = mdev_type_attr_show,
+ .store = mdev_type_attr_store,
+};
+
+static ssize_t create_store(struct kobject *kobj, struct device *dev,
+ const char *buf, size_t count)
+{
+ char *str;
+ uuid_le uuid;
+ int ret;
+
+ if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1))
+ return -EINVAL;
+
+ str = kstrndup(buf, count, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+
+ ret = uuid_le_to_bin(str, &uuid);
+ kfree(str);
+ if (ret)
+ return ret;
+
+ ret = mdev_device_create(kobj, dev, uuid);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+MDEV_TYPE_ATTR_WO(create);
+
+static void mdev_type_release(struct kobject *kobj)
+{
+ struct mdev_type *type = to_mdev_type(kobj);
+
+ pr_debug("Releasing group %s\n", kobj->name);
+ kfree(type);
+}
+
+static struct kobj_type mdev_type_ktype = {
+ .sysfs_ops = &mdev_type_sysfs_ops,
+ .release = mdev_type_release,
+};
+
+struct mdev_type *add_mdev_supported_type(struct parent_device *parent,
+ struct attribute_group *group)
+{
+ struct mdev_type *type;
+ int ret;
+
+ if (!group->name) {
+ pr_err("%s: Type name empty!\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ type = kzalloc(sizeof(*type), GFP_KERNEL);
+ if (!type)
+ return ERR_PTR(-ENOMEM);
+
+ type->kobj.kset = parent->mdev_types_kset;
+
+ ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
+ "%s-%s", dev_driver_string(parent->dev),
+ group->name);
+ if (ret) {
+ kfree(type);
+ return ERR_PTR(ret);
+ }
+
+ ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
+ if (ret)
+ goto attr_create_failed;
+
+ type->devices_kobj = kobject_create_and_add("devices", &type->kobj);
+ if (!type->devices_kobj) {
+ ret = -ENOMEM;
+ goto attr_devices_failed;
+ }
+
+ ret = sysfs_create_files(&type->kobj,
+ (const struct attribute **)group->attrs);
+ if (ret) {
+ ret = -ENOMEM;
+ goto attrs_failed;
+ }
+
+ type->group = group;
+ type->parent = parent;
+ return type;
+
+attrs_failed:
+ kobject_put(type->devices_kobj);
+attr_devices_failed:
+ sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
+attr_create_failed:
+ kobject_del(&type->kobj);
+ kobject_put(&type->kobj);
+ return ERR_PTR(ret);
+}
+
+static void remove_mdev_supported_type(struct mdev_type *type)
+{
+ sysfs_remove_files(&type->kobj,
+ (const struct attribute **)type->group->attrs);
+ kobject_put(type->devices_kobj);
+ sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
+ kobject_del(&type->kobj);
+ kobject_put(&type->kobj);
+}
+
+static int add_mdev_supported_type_groups(struct parent_device *parent)
+{
+ int i;
+
+ for (i = 0; parent->ops->supported_type_groups[i]; i++) {
+ struct mdev_type *type;
+
+ type = add_mdev_supported_type(parent,
+ parent->ops->supported_type_groups[i]);
+ if (IS_ERR(type)) {
+ struct mdev_type *ltype, *tmp;
+
+ list_for_each_entry_safe(ltype, tmp, &parent->type_list,
+ next) {
+ list_del(&ltype->next);
+ remove_mdev_supported_type(ltype);
+ }
+ return PTR_ERR(type);
+ }
+ list_add(&type->next, &parent->type_list);
+ }
+ return 0;
+}
+
+/* mdev sysfs functions */
+void parent_remove_sysfs_files(struct parent_device *parent)
+{
+ struct mdev_type *type, *tmp;
+
+ list_for_each_entry_safe(type, tmp, &parent->type_list, next) {
+ list_del(&type->next);
+ remove_mdev_supported_type(type);
+ }
+
+ sysfs_remove_groups(&parent->dev->kobj, parent->ops->dev_attr_groups);
+ kset_unregister(parent->mdev_types_kset);
+}
+
+int parent_create_sysfs_files(struct parent_device *parent)
+{
+ int ret;
+
+ parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
+ NULL, &parent->dev->kobj);
+
+ if (!parent->mdev_types_kset)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&parent->type_list);
+
+ ret = sysfs_create_groups(&parent->dev->kobj,
+ parent->ops->dev_attr_groups);
+ if (ret)
+ goto create_err;
+
+ ret = add_mdev_supported_type_groups(parent);
+ if (ret)
+ sysfs_remove_groups(&parent->dev->kobj,
+ parent->ops->dev_attr_groups);
+ else
+ return ret;
+
+create_err:
+ kset_unregister(parent->mdev_types_kset);
+ return ret;
+}
+
+static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val) < 0)
+ return -EINVAL;
+
+ if (val && device_remove_file_self(dev, attr)) {
+ int ret;
+
+ ret = mdev_device_remove(dev, false);
+ if (ret) {
+ device_create_file(dev, attr);
+ return ret;
+ }
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR_WO(remove);
+
+static const struct attribute *mdev_device_attrs[] = {
+ &dev_attr_remove.attr,
+ NULL,
+};
+
+int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type)
+{
+ int ret;
+
+ ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev));
+ if (ret)
+ goto device_link_failed;
+
+ ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type");
+ if (ret)
+ goto type_link_failed;
+
+ return ret;
+
+type_link_failed:
+ sysfs_remove_link(type->devices_kobj, dev_name(dev));
+device_link_failed:
+ sysfs_remove_files(&dev->kobj, mdev_device_attrs);
+ return ret;
+}
+
+void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type)
+{
+ sysfs_remove_link(&dev->kobj, "mdev_type");
+ sysfs_remove_link(type->devices_kobj, dev_name(dev));
+ sysfs_remove_files(&dev->kobj, mdev_device_attrs);
+}
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
new file mode 100644
index 000000000000..ffc36758cb84
--- /dev/null
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -0,0 +1,148 @@
+/*
+ * VFIO based driver for Mediated device
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/mdev.h>
+
+#include "mdev_private.h"
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_AUTHOR "NVIDIA Corporation"
+#define DRIVER_DESC "VFIO based driver for Mediated device"
+
+static int vfio_mdev_open(void *device_data)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+ int ret;
+
+ if (unlikely(!parent->ops->open))
+ return -EINVAL;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ ret = parent->ops->open(mdev);
+ if (ret)
+ module_put(THIS_MODULE);
+
+ return ret;
+}
+
+static void vfio_mdev_release(void *device_data)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+
+ if (likely(parent->ops->release))
+ parent->ops->release(mdev);
+
+ module_put(THIS_MODULE);
+}
+
+static long vfio_mdev_unlocked_ioctl(void *device_data,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+
+ if (unlikely(!parent->ops->ioctl))
+ return -EINVAL;
+
+ return parent->ops->ioctl(mdev, cmd, arg);
+}
+
+static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+
+ if (unlikely(!parent->ops->read))
+ return -EINVAL;
+
+ return parent->ops->read(mdev, buf, count, ppos);
+}
+
+static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+
+ if (unlikely(!parent->ops->write))
+ return -EINVAL;
+
+ return parent->ops->write(mdev, buf, count, ppos);
+}
+
+static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)
+{
+ struct mdev_device *mdev = device_data;
+ struct parent_device *parent = mdev->parent;
+
+ if (unlikely(!parent->ops->mmap))
+ return -EINVAL;
+
+ return parent->ops->mmap(mdev, vma);
+}
+
+static const struct vfio_device_ops vfio_mdev_dev_ops = {
+ .name = "vfio-mdev",
+ .open = vfio_mdev_open,
+ .release = vfio_mdev_release,
+ .ioctl = vfio_mdev_unlocked_ioctl,
+ .read = vfio_mdev_read,
+ .write = vfio_mdev_write,
+ .mmap = vfio_mdev_mmap,
+};
+
+int vfio_mdev_probe(struct device *dev)
+{
+ struct mdev_device *mdev = to_mdev_device(dev);
+
+ return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev);
+}
+
+void vfio_mdev_remove(struct device *dev)
+{
+ vfio_del_group_dev(dev);
+}
+
+struct mdev_driver vfio_mdev_driver = {
+ .name = "vfio_mdev",
+ .probe = vfio_mdev_probe,
+ .remove = vfio_mdev_remove,
+};
+
+static int __init vfio_mdev_init(void)
+{
+ return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE);
+}
+
+static void __exit vfio_mdev_exit(void)
+{
+ mdev_unregister_driver(&vfio_mdev_driver);
+}
+
+module_init(vfio_mdev_init)
+module_exit(vfio_mdev_exit)
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 031bc08d000d..dcd7c2a99618 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -558,10 +558,9 @@ static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev,
struct vfio_info_cap *caps)
{
- struct vfio_info_cap_header *header;
struct vfio_region_info_cap_sparse_mmap *sparse;
size_t end, size;
- int nr_areas = 2, i = 0;
+ int nr_areas = 2, i = 0, ret;
end = pci_resource_len(vdev->pdev, vdev->msix_bar);
@@ -572,13 +571,10 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev,
size = sizeof(*sparse) + (nr_areas * sizeof(*sparse->areas));
- header = vfio_info_cap_add(caps, size,
- VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1);
- if (IS_ERR(header))
- return PTR_ERR(header);
+ sparse = kzalloc(size, GFP_KERNEL);
+ if (!sparse)
+ return -ENOMEM;
- sparse = container_of(header,
- struct vfio_region_info_cap_sparse_mmap, header);
sparse->nr_areas = nr_areas;
if (vdev->msix_offset & PAGE_MASK) {
@@ -594,26 +590,11 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev,
i++;
}
- return 0;
-}
-
-static int region_type_cap(struct vfio_pci_device *vdev,
- struct vfio_info_cap *caps,
- unsigned int type, unsigned int subtype)
-{
- struct vfio_info_cap_header *header;
- struct vfio_region_info_cap_type *cap;
-
- header = vfio_info_cap_add(caps, sizeof(*cap),
- VFIO_REGION_INFO_CAP_TYPE, 1);
- if (IS_ERR(header))
- return PTR_ERR(header);
-
- cap = container_of(header, struct vfio_region_info_cap_type, header);
- cap->type = type;
- cap->subtype = subtype;
+ ret = vfio_info_add_capability(caps, VFIO_REGION_INFO_CAP_SPARSE_MMAP,
+ sparse);
+ kfree(sparse);
- return 0;
+ return ret;
}
int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
@@ -752,6 +733,9 @@ static long vfio_pci_ioctl(void *device_data,
break;
default:
+ {
+ struct vfio_region_info_cap_type cap_type;
+
if (info.index >=
VFIO_PCI_NUM_REGIONS + vdev->num_regions)
return -EINVAL;
@@ -762,11 +746,16 @@ static long vfio_pci_ioctl(void *device_data,
info.size = vdev->region[i].size;
info.flags = vdev->region[i].flags;
- ret = region_type_cap(vdev, &caps,
- vdev->region[i].type,
- vdev->region[i].subtype);
+ cap_type.type = vdev->region[i].type;
+ cap_type.subtype = vdev->region[i].subtype;
+
+ ret = vfio_info_add_capability(&caps,
+ VFIO_REGION_INFO_CAP_TYPE,
+ &cap_type);
if (ret)
return ret;
+
+ }
}
if (caps.size) {
@@ -829,45 +818,25 @@ static long vfio_pci_ioctl(void *device_data,
} else if (cmd == VFIO_DEVICE_SET_IRQS) {
struct vfio_irq_set hdr;
- size_t size;
u8 *data = NULL;
int max, ret = 0;
+ size_t data_size = 0;
minsz = offsetofend(struct vfio_irq_set, count);
if (copy_from_user(&hdr, (void __user *)arg, minsz))
return -EFAULT;
- if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS ||
- hdr.count >= (U32_MAX - hdr.start) ||
- hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
- VFIO_IRQ_SET_ACTION_TYPE_MASK))
- return -EINVAL;
-
max = vfio_pci_get_irq_count(vdev, hdr.index);
- if (hdr.start >= max || hdr.start + hdr.count > max)
- return -EINVAL;
- switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
- case VFIO_IRQ_SET_DATA_NONE:
- size = 0;
- break;
- case VFIO_IRQ_SET_DATA_BOOL:
- size = sizeof(uint8_t);
- break;
- case VFIO_IRQ_SET_DATA_EVENTFD:
- size = sizeof(int32_t);
- break;
- default:
- return -EINVAL;
- }
-
- if (size) {
- if (hdr.argsz - minsz < hdr.count * size)
- return -EINVAL;
+ ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
+ VFIO_PCI_NUM_IRQS, &data_size);
+ if (ret)
+ return ret;
+ if (data_size) {
data = memdup_user((void __user *)(arg + minsz),
- hdr.count * size);
+ data_size);
if (IS_ERR(data))
return PTR_ERR(data);
}
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 65d4a3015542..e4220ca8ca27 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -152,7 +152,7 @@ static int vfio_user_config_read(struct pci_dev *pdev, int offset,
*val = cpu_to_le32(tmp_val);
- return pcibios_err_to_errno(ret);
+ return ret;
}
static int vfio_user_config_write(struct pci_dev *pdev, int offset,
@@ -173,7 +173,7 @@ static int vfio_user_config_write(struct pci_dev *pdev, int offset,
break;
}
- return pcibios_err_to_errno(ret);
+ return ret;
}
static int vfio_default_config_read(struct vfio_pci_device *vdev, int pos,
@@ -257,7 +257,7 @@ static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos,
ret = vfio_user_config_read(vdev->pdev, pos, val, count);
if (ret)
- return pcibios_err_to_errno(ret);
+ return ret;
if (pos >= PCI_CFG_SPACE_SIZE) { /* Extended cap header mangling */
if (offset < 4)
@@ -295,7 +295,7 @@ static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
ret = vfio_user_config_read(vdev->pdev, pos, val, count);
if (ret)
- return pcibios_err_to_errno(ret);
+ return ret;
return count;
}
@@ -1089,7 +1089,7 @@ static int vfio_msi_config_write(struct vfio_pci_device *vdev, int pos,
start + PCI_MSI_FLAGS,
flags);
if (ret)
- return pcibios_err_to_errno(ret);
+ return ret;
}
return count;
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index d78142830754..4c27f4be3c3d 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -364,36 +364,21 @@ static long vfio_platform_ioctl(void *device_data,
struct vfio_irq_set hdr;
u8 *data = NULL;
int ret = 0;
+ size_t data_size = 0;
minsz = offsetofend(struct vfio_irq_set, count);
if (copy_from_user(&hdr, (void __user *)arg, minsz))
return -EFAULT;
- if (hdr.argsz < minsz)
- return -EINVAL;
-
- if (hdr.index >= vdev->num_irqs)
- return -EINVAL;
-
- if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
- VFIO_IRQ_SET_ACTION_TYPE_MASK))
- return -EINVAL;
-
- if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
- size_t size;
-
- if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
- size = sizeof(uint8_t);
- else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
- size = sizeof(int32_t);
- else
- return -EINVAL;
-
- if (hdr.argsz - minsz < size)
- return -EINVAL;
+ ret = vfio_set_irqs_validate_and_prepare(&hdr, vdev->num_irqs,
+ vdev->num_irqs, &data_size);
+ if (ret)
+ return ret;
- data = memdup_user((void __user *)(arg + minsz), size);
+ if (data_size) {
+ data = memdup_user((void __user *)(arg + minsz),
+ data_size);
if (IS_ERR(data))
return PTR_ERR(data);
}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index d1d70e0b011b..9901c4671e2f 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -86,6 +86,8 @@ struct vfio_group {
struct mutex unbound_lock;
atomic_t opened;
bool noiommu;
+ struct kvm *kvm;
+ struct blocking_notifier_head notifier;
};
struct vfio_device {
@@ -339,6 +341,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
#ifdef CONFIG_VFIO_NOIOMMU
group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu);
#endif
+ BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier);
group->nb.notifier_call = vfio_iommu_group_notifier;
@@ -480,6 +483,21 @@ static struct vfio_group *vfio_group_get_from_minor(int minor)
return group;
}
+static struct vfio_group *vfio_group_get_from_dev(struct device *dev)
+{
+ struct iommu_group *iommu_group;
+ struct vfio_group *group;
+
+ iommu_group = iommu_group_get(dev);
+ if (!iommu_group)
+ return NULL;
+
+ group = vfio_group_get_from_iommu(iommu_group);
+ iommu_group_put(iommu_group);
+
+ return group;
+}
+
/**
* Device objects - create, release, get, put, search
*/
@@ -811,16 +829,10 @@ EXPORT_SYMBOL_GPL(vfio_add_group_dev);
*/
struct vfio_device *vfio_device_get_from_dev(struct device *dev)
{
- struct iommu_group *iommu_group;
struct vfio_group *group;
struct vfio_device *device;
- iommu_group = iommu_group_get(dev);
- if (!iommu_group)
- return NULL;
-
- group = vfio_group_get_from_iommu(iommu_group);
- iommu_group_put(iommu_group);
+ group = vfio_group_get_from_dev(dev);
if (!group)
return NULL;
@@ -1376,6 +1388,23 @@ static bool vfio_group_viable(struct vfio_group *group)
group, vfio_dev_viable) == 0);
}
+static int vfio_group_add_container_user(struct vfio_group *group)
+{
+ if (!atomic_inc_not_zero(&group->container_users))
+ return -EINVAL;
+
+ if (group->noiommu) {
+ atomic_dec(&group->container_users);
+ return -EPERM;
+ }
+ if (!group->container->iommu_driver || !vfio_group_viable(group)) {
+ atomic_dec(&group->container_users);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct file_operations vfio_device_fops;
static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
@@ -1555,6 +1584,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
filep->private_data = NULL;
+ /* Any user didn't unregister? */
+ WARN_ON(group->notifier.head);
+
vfio_group_try_dissolve_container(group);
atomic_dec(&group->opened);
@@ -1685,23 +1717,14 @@ static const struct file_operations vfio_device_fops = {
struct vfio_group *vfio_group_get_external_user(struct file *filep)
{
struct vfio_group *group = filep->private_data;
+ int ret;
if (filep->f_op != &vfio_group_fops)
return ERR_PTR(-EINVAL);
- 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);
- return ERR_PTR(-EINVAL);
- }
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ return ERR_PTR(ret);
vfio_group_get(group);
@@ -1763,7 +1786,7 @@ struct vfio_info_cap_header *vfio_info_cap_add(struct vfio_info_cap *caps,
header->version = version;
/* Add to the end of the capability chain */
- for (tmp = caps->buf; tmp->next; tmp = (void *)tmp + tmp->next)
+ for (tmp = buf; tmp->next; tmp = buf + tmp->next)
; /* nothing */
tmp->next = caps->size;
@@ -1776,11 +1799,403 @@ EXPORT_SYMBOL_GPL(vfio_info_cap_add);
void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset)
{
struct vfio_info_cap_header *tmp;
+ void *buf = (void *)caps->buf;
- for (tmp = caps->buf; tmp->next; tmp = (void *)tmp + tmp->next - offset)
+ for (tmp = buf; tmp->next; tmp = buf + tmp->next - offset)
tmp->next += offset;
}
-EXPORT_SYMBOL_GPL(vfio_info_cap_shift);
+EXPORT_SYMBOL(vfio_info_cap_shift);
+
+static int sparse_mmap_cap(struct vfio_info_cap *caps, void *cap_type)
+{
+ struct vfio_info_cap_header *header;
+ struct vfio_region_info_cap_sparse_mmap *sparse_cap, *sparse = cap_type;
+ size_t size;
+
+ size = sizeof(*sparse) + sparse->nr_areas * sizeof(*sparse->areas);
+ header = vfio_info_cap_add(caps, size,
+ VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1);
+ if (IS_ERR(header))
+ return PTR_ERR(header);
+
+ sparse_cap = container_of(header,
+ struct vfio_region_info_cap_sparse_mmap, header);
+ sparse_cap->nr_areas = sparse->nr_areas;
+ memcpy(sparse_cap->areas, sparse->areas,
+ sparse->nr_areas * sizeof(*sparse->areas));
+ return 0;
+}
+
+static int region_type_cap(struct vfio_info_cap *caps, void *cap_type)
+{
+ struct vfio_info_cap_header *header;
+ struct vfio_region_info_cap_type *type_cap, *cap = cap_type;
+
+ header = vfio_info_cap_add(caps, sizeof(*cap),
+ VFIO_REGION_INFO_CAP_TYPE, 1);
+ if (IS_ERR(header))
+ return PTR_ERR(header);
+
+ type_cap = container_of(header, struct vfio_region_info_cap_type,
+ header);
+ type_cap->type = cap->type;
+ type_cap->subtype = cap->subtype;
+ return 0;
+}
+
+int vfio_info_add_capability(struct vfio_info_cap *caps, int cap_type_id,
+ void *cap_type)
+{
+ int ret = -EINVAL;
+
+ if (!cap_type)
+ return 0;
+
+ switch (cap_type_id) {
+ case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
+ ret = sparse_mmap_cap(caps, cap_type);
+ break;
+
+ case VFIO_REGION_INFO_CAP_TYPE:
+ ret = region_type_cap(caps, cap_type);
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(vfio_info_add_capability);
+
+int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
+ int max_irq_type, size_t *data_size)
+{
+ unsigned long minsz;
+ size_t size;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+
+ if ((hdr->argsz < minsz) || (hdr->index >= max_irq_type) ||
+ (hdr->count >= (U32_MAX - hdr->start)) ||
+ (hdr->flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+ VFIO_IRQ_SET_ACTION_TYPE_MASK)))
+ return -EINVAL;
+
+ if (data_size)
+ *data_size = 0;
+
+ if (hdr->start >= num_irqs || hdr->start + hdr->count > num_irqs)
+ return -EINVAL;
+
+ switch (hdr->flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
+ case VFIO_IRQ_SET_DATA_NONE:
+ size = 0;
+ break;
+ case VFIO_IRQ_SET_DATA_BOOL:
+ size = sizeof(uint8_t);
+ break;
+ case VFIO_IRQ_SET_DATA_EVENTFD:
+ size = sizeof(int32_t);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (size) {
+ if (hdr->argsz - minsz < hdr->count * size)
+ return -EINVAL;
+
+ if (!data_size)
+ return -EINVAL;
+
+ *data_size = hdr->count * size;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(vfio_set_irqs_validate_and_prepare);
+
+/*
+ * Pin a set of guest PFNs and return their associated host PFNs for local
+ * domain only.
+ * @dev [in] : device
+ * @user_pfn [in]: array of user/guest PFNs to be unpinned.
+ * @npage [in] : count of elements in user_pfn array. This count should not
+ * be greater VFIO_PIN_PAGES_MAX_ENTRIES.
+ * @prot [in] : protection flags
+ * @phys_pfn[out]: array of host PFNs
+ * Return error or number of pages pinned.
+ */
+int vfio_pin_pages(struct device *dev, unsigned long *user_pfn, int npage,
+ int prot, unsigned long *phys_pfn)
+{
+ struct vfio_container *container;
+ struct vfio_group *group;
+ struct vfio_iommu_driver *driver;
+ int ret;
+
+ if (!dev || !user_pfn || !phys_pfn || !npage)
+ return -EINVAL;
+
+ if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
+ return -E2BIG;
+
+ group = vfio_group_get_from_dev(dev);
+ if (!group)
+ return -ENODEV;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ goto err_pin_pages;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ driver = container->iommu_driver;
+ if (likely(driver && driver->ops->pin_pages))
+ ret = driver->ops->pin_pages(container->iommu_data, user_pfn,
+ npage, prot, phys_pfn);
+ else
+ ret = -ENOTTY;
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+err_pin_pages:
+ vfio_group_put(group);
+ return ret;
+}
+EXPORT_SYMBOL(vfio_pin_pages);
+
+/*
+ * Unpin set of host PFNs for local domain only.
+ * @dev [in] : device
+ * @user_pfn [in]: array of user/guest PFNs to be unpinned. Number of user/guest
+ * PFNs should not be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
+ * @npage [in] : count of elements in user_pfn array. This count should not
+ * be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
+ * Return error or number of pages unpinned.
+ */
+int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, int npage)
+{
+ struct vfio_container *container;
+ struct vfio_group *group;
+ struct vfio_iommu_driver *driver;
+ int ret;
+
+ if (!dev || !user_pfn || !npage)
+ return -EINVAL;
+
+ if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
+ return -E2BIG;
+
+ group = vfio_group_get_from_dev(dev);
+ if (!group)
+ return -ENODEV;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ goto err_unpin_pages;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ driver = container->iommu_driver;
+ if (likely(driver && driver->ops->unpin_pages))
+ ret = driver->ops->unpin_pages(container->iommu_data, user_pfn,
+ npage);
+ else
+ ret = -ENOTTY;
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+err_unpin_pages:
+ vfio_group_put(group);
+ return ret;
+}
+EXPORT_SYMBOL(vfio_unpin_pages);
+
+static int vfio_register_iommu_notifier(struct vfio_group *group,
+ unsigned long *events,
+ struct notifier_block *nb)
+{
+ struct vfio_container *container;
+ struct vfio_iommu_driver *driver;
+ int ret;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ return -EINVAL;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ driver = container->iommu_driver;
+ if (likely(driver && driver->ops->register_notifier))
+ ret = driver->ops->register_notifier(container->iommu_data,
+ events, nb);
+ else
+ ret = -ENOTTY;
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+ return ret;
+}
+
+static int vfio_unregister_iommu_notifier(struct vfio_group *group,
+ struct notifier_block *nb)
+{
+ struct vfio_container *container;
+ struct vfio_iommu_driver *driver;
+ int ret;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ return -EINVAL;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ driver = container->iommu_driver;
+ if (likely(driver && driver->ops->unregister_notifier))
+ ret = driver->ops->unregister_notifier(container->iommu_data,
+ nb);
+ else
+ ret = -ENOTTY;
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+ return ret;
+}
+
+void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
+{
+ group->kvm = kvm;
+ blocking_notifier_call_chain(&group->notifier,
+ VFIO_GROUP_NOTIFY_SET_KVM, kvm);
+}
+EXPORT_SYMBOL_GPL(vfio_group_set_kvm);
+
+static int vfio_register_group_notifier(struct vfio_group *group,
+ unsigned long *events,
+ struct notifier_block *nb)
+{
+ struct vfio_container *container;
+ int ret;
+ bool set_kvm = false;
+
+ if (*events & VFIO_GROUP_NOTIFY_SET_KVM)
+ set_kvm = true;
+
+ /* clear known events */
+ *events &= ~VFIO_GROUP_NOTIFY_SET_KVM;
+
+ /* refuse to continue if still events remaining */
+ if (*events)
+ return -EINVAL;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ return -EINVAL;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ ret = blocking_notifier_chain_register(&group->notifier, nb);
+
+ /*
+ * The attaching of kvm and vfio_group might already happen, so
+ * here we replay once upon registration.
+ */
+ if (!ret && set_kvm && group->kvm)
+ blocking_notifier_call_chain(&group->notifier,
+ VFIO_GROUP_NOTIFY_SET_KVM, group->kvm);
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+ return ret;
+}
+
+static int vfio_unregister_group_notifier(struct vfio_group *group,
+ struct notifier_block *nb)
+{
+ struct vfio_container *container;
+ int ret;
+
+ ret = vfio_group_add_container_user(group);
+ if (ret)
+ return -EINVAL;
+
+ container = group->container;
+ down_read(&container->group_lock);
+
+ ret = blocking_notifier_chain_unregister(&group->notifier, nb);
+
+ up_read(&container->group_lock);
+ vfio_group_try_dissolve_container(group);
+
+ return ret;
+}
+
+int vfio_register_notifier(struct device *dev, enum vfio_notify_type type,
+ unsigned long *events, struct notifier_block *nb)
+{
+ struct vfio_group *group;
+ int ret;
+
+ if (!dev || !nb || !events || (*events == 0))
+ return -EINVAL;
+
+ group = vfio_group_get_from_dev(dev);
+ if (!group)
+ return -ENODEV;
+
+ switch (type) {
+ case VFIO_IOMMU_NOTIFY:
+ ret = vfio_register_iommu_notifier(group, events, nb);
+ break;
+ case VFIO_GROUP_NOTIFY:
+ ret = vfio_register_group_notifier(group, events, nb);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ vfio_group_put(group);
+ return ret;
+}
+EXPORT_SYMBOL(vfio_register_notifier);
+
+int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type,
+ struct notifier_block *nb)
+{
+ struct vfio_group *group;
+ int ret;
+
+ if (!dev || !nb)
+ return -EINVAL;
+
+ group = vfio_group_get_from_dev(dev);
+ if (!group)
+ return -ENODEV;
+
+ switch (type) {
+ case VFIO_IOMMU_NOTIFY:
+ ret = vfio_unregister_iommu_notifier(group, nb);
+ break;
+ case VFIO_GROUP_NOTIFY:
+ ret = vfio_unregister_group_notifier(group, nb);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ vfio_group_put(group);
+ return ret;
+}
+EXPORT_SYMBOL(vfio_unregister_notifier);
/**
* Module/class support
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 2ba19424e4a1..9815e45c23c4 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -36,6 +36,9 @@
#include <linux/uaccess.h>
#include <linux/vfio.h>
#include <linux/workqueue.h>
+#include <linux/pid_namespace.h>
+#include <linux/mdev.h>
+#include <linux/notifier.h>
#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
@@ -55,8 +58,10 @@ MODULE_PARM_DESC(disable_hugepages,
struct vfio_iommu {
struct list_head domain_list;
+ struct vfio_domain *external_domain; /* domain for external user */
struct mutex lock;
struct rb_root dma_list;
+ struct blocking_notifier_head notifier;
bool v2;
bool nesting;
};
@@ -75,6 +80,9 @@ struct vfio_dma {
unsigned long vaddr; /* Process virtual addr */
size_t size; /* Map size (bytes) */
int prot; /* IOMMU_READ/WRITE */
+ bool iommu_mapped;
+ struct task_struct *task;
+ struct rb_root pfn_list; /* Ex-user pinned pfn list */
};
struct vfio_group {
@@ -83,6 +91,21 @@ struct vfio_group {
};
/*
+ * Guest RAM pinning working set or DMA target
+ */
+struct vfio_pfn {
+ struct rb_node node;
+ dma_addr_t iova; /* Device address */
+ unsigned long pfn; /* Host pfn */
+ atomic_t ref_count;
+};
+
+#define IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu) \
+ (!list_empty(&iommu->domain_list))
+
+static int put_pfn(unsigned long pfn, int prot);
+
+/*
* This code handles mapping and unmapping of user data buffers
* into DMA'ble space using the IOMMU
*/
@@ -130,6 +153,97 @@ static void vfio_unlink_dma(struct vfio_iommu *iommu, struct vfio_dma *old)
rb_erase(&old->node, &iommu->dma_list);
}
+/*
+ * Helper Functions for host iova-pfn list
+ */
+static struct vfio_pfn *vfio_find_vpfn(struct vfio_dma *dma, dma_addr_t iova)
+{
+ struct vfio_pfn *vpfn;
+ struct rb_node *node = dma->pfn_list.rb_node;
+
+ while (node) {
+ vpfn = rb_entry(node, struct vfio_pfn, node);
+
+ if (iova < vpfn->iova)
+ node = node->rb_left;
+ else if (iova > vpfn->iova)
+ node = node->rb_right;
+ else
+ return vpfn;
+ }
+ return NULL;
+}
+
+static void vfio_link_pfn(struct vfio_dma *dma,
+ struct vfio_pfn *new)
+{
+ struct rb_node **link, *parent = NULL;
+ struct vfio_pfn *vpfn;
+
+ link = &dma->pfn_list.rb_node;
+ while (*link) {
+ parent = *link;
+ vpfn = rb_entry(parent, struct vfio_pfn, node);
+
+ if (new->iova < vpfn->iova)
+ link = &(*link)->rb_left;
+ else
+ link = &(*link)->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, link);
+ rb_insert_color(&new->node, &dma->pfn_list);
+}
+
+static void vfio_unlink_pfn(struct vfio_dma *dma, struct vfio_pfn *old)
+{
+ rb_erase(&old->node, &dma->pfn_list);
+}
+
+static int vfio_add_to_pfn_list(struct vfio_dma *dma, dma_addr_t iova,
+ unsigned long pfn)
+{
+ struct vfio_pfn *vpfn;
+
+ vpfn = kzalloc(sizeof(*vpfn), GFP_KERNEL);
+ if (!vpfn)
+ return -ENOMEM;
+
+ vpfn->iova = iova;
+ vpfn->pfn = pfn;
+ atomic_set(&vpfn->ref_count, 1);
+ vfio_link_pfn(dma, vpfn);
+ return 0;
+}
+
+static void vfio_remove_from_pfn_list(struct vfio_dma *dma,
+ struct vfio_pfn *vpfn)
+{
+ vfio_unlink_pfn(dma, vpfn);
+ kfree(vpfn);
+}
+
+static struct vfio_pfn *vfio_iova_get_vfio_pfn(struct vfio_dma *dma,
+ unsigned long iova)
+{
+ struct vfio_pfn *vpfn = vfio_find_vpfn(dma, iova);
+
+ if (vpfn)
+ atomic_inc(&vpfn->ref_count);
+ return vpfn;
+}
+
+static int vfio_iova_put_vfio_pfn(struct vfio_dma *dma, struct vfio_pfn *vpfn)
+{
+ int ret = 0;
+
+ if (atomic_dec_and_test(&vpfn->ref_count)) {
+ ret = put_pfn(vpfn->pfn, dma->prot);
+ vfio_remove_from_pfn_list(dma, vpfn);
+ }
+ return ret;
+}
+
struct vwork {
struct mm_struct *mm;
long npage;
@@ -150,17 +264,22 @@ static void vfio_lock_acct_bg(struct work_struct *work)
kfree(vwork);
}
-static void vfio_lock_acct(long npage)
+static void vfio_lock_acct(struct task_struct *task, long npage)
{
struct vwork *vwork;
struct mm_struct *mm;
- if (!current->mm || !npage)
+ if (!npage)
+ return;
+
+ mm = get_task_mm(task);
+ if (!mm)
return; /* process exited or nothing to do */
- if (down_write_trylock(&current->mm->mmap_sem)) {
- current->mm->locked_vm += npage;
- up_write(&current->mm->mmap_sem);
+ if (down_write_trylock(&mm->mmap_sem)) {
+ mm->locked_vm += npage;
+ up_write(&mm->mmap_sem);
+ mmput(mm);
return;
}
@@ -170,11 +289,8 @@ static void vfio_lock_acct(long npage)
* wouldn't need this silliness
*/
vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
- if (!vwork)
- return;
- mm = get_task_mm(current);
- if (!mm) {
- kfree(vwork);
+ if (!vwork) {
+ mmput(mm);
return;
}
INIT_WORK(&vwork->work, vfio_lock_acct_bg);
@@ -228,20 +344,36 @@ static int put_pfn(unsigned long pfn, int prot)
return 0;
}
-static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn)
+static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
+ int prot, unsigned long *pfn)
{
struct page *page[1];
struct vm_area_struct *vma;
- int ret = -EFAULT;
+ int ret;
+
+ if (mm == current->mm) {
+ ret = get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE),
+ page);
+ } else {
+ unsigned int flags = 0;
+
+ if (prot & IOMMU_WRITE)
+ flags |= FOLL_WRITE;
+
+ down_read(&mm->mmap_sem);
+ ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page,
+ NULL);
+ up_read(&mm->mmap_sem);
+ }
- if (get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE), page) == 1) {
+ if (ret == 1) {
*pfn = page_to_pfn(page[0]);
return 0;
}
- down_read(&current->mm->mmap_sem);
+ down_read(&mm->mmap_sem);
- vma = find_vma_intersection(current->mm, vaddr, vaddr + 1);
+ vma = find_vma_intersection(mm, vaddr, vaddr + 1);
if (vma && vma->vm_flags & VM_PFNMAP) {
*pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
@@ -249,8 +381,7 @@ static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn)
ret = 0;
}
- up_read(&current->mm->mmap_sem);
-
+ up_read(&mm->mmap_sem);
return ret;
}
@@ -259,88 +390,299 @@ static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn)
* the iommu can only map chunks of consecutive pfns anyway, so get the
* first page and all consecutive pages with the same locking.
*/
-static long vfio_pin_pages(unsigned long vaddr, long npage,
- int prot, unsigned long *pfn_base)
+static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
+ long npage, unsigned long *pfn_base)
{
- unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
- bool lock_cap = capable(CAP_IPC_LOCK);
- long ret, i;
+ unsigned long limit;
+ bool lock_cap = ns_capable(task_active_pid_ns(dma->task)->user_ns,
+ CAP_IPC_LOCK);
+ struct mm_struct *mm;
+ long ret, i = 0, lock_acct = 0;
bool rsvd;
+ dma_addr_t iova = vaddr - dma->vaddr + dma->iova;
- if (!current->mm)
+ mm = get_task_mm(dma->task);
+ if (!mm)
return -ENODEV;
- ret = vaddr_get_pfn(vaddr, prot, pfn_base);
+ ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
if (ret)
- return ret;
+ goto pin_pg_remote_exit;
rsvd = is_invalid_reserved_pfn(*pfn_base);
+ limit = task_rlimit(dma->task, RLIMIT_MEMLOCK) >> PAGE_SHIFT;
- if (!rsvd && !lock_cap && current->mm->locked_vm + 1 > limit) {
- put_pfn(*pfn_base, prot);
- pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
- limit << PAGE_SHIFT);
- return -ENOMEM;
+ /*
+ * Reserved pages aren't counted against the user, externally pinned
+ * pages are already counted against the user.
+ */
+ if (!rsvd && !vfio_find_vpfn(dma, iova)) {
+ if (!lock_cap && mm->locked_vm + 1 > limit) {
+ put_pfn(*pfn_base, dma->prot);
+ pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
+ limit << PAGE_SHIFT);
+ ret = -ENOMEM;
+ goto pin_pg_remote_exit;
+ }
+ lock_acct++;
}
- if (unlikely(disable_hugepages)) {
- if (!rsvd)
- vfio_lock_acct(1);
- return 1;
- }
+ i++;
+ if (likely(!disable_hugepages)) {
+ /* Lock all the consecutive pages from pfn_base */
+ for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; i < npage;
+ i++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) {
+ unsigned long pfn = 0;
- /* Lock all the consecutive pages from pfn_base */
- for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
- unsigned long pfn = 0;
+ ret = vaddr_get_pfn(mm, vaddr, dma->prot, &pfn);
+ if (ret)
+ break;
- ret = vaddr_get_pfn(vaddr, prot, &pfn);
- if (ret)
- break;
+ if (pfn != *pfn_base + i ||
+ rsvd != is_invalid_reserved_pfn(pfn)) {
+ put_pfn(pfn, dma->prot);
+ break;
+ }
- if (pfn != *pfn_base + i ||
- rsvd != is_invalid_reserved_pfn(pfn)) {
- put_pfn(pfn, prot);
- break;
+ if (!rsvd && !vfio_find_vpfn(dma, iova)) {
+ if (!lock_cap &&
+ mm->locked_vm + lock_acct + 1 > limit) {
+ put_pfn(pfn, dma->prot);
+ pr_warn("%s: RLIMIT_MEMLOCK (%ld) "
+ "exceeded\n", __func__,
+ limit << PAGE_SHIFT);
+ break;
+ }
+ lock_acct++;
+ }
}
+ }
- if (!rsvd && !lock_cap &&
- current->mm->locked_vm + i + 1 > limit) {
- put_pfn(pfn, prot);
- pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
- __func__, limit << PAGE_SHIFT);
- break;
+ vfio_lock_acct(dma->task, lock_acct);
+ ret = i;
+
+pin_pg_remote_exit:
+ mmput(mm);
+ return ret;
+}
+
+static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
+ unsigned long pfn, long npage,
+ bool do_accounting)
+{
+ long unlocked = 0, locked = 0;
+ long i;
+
+ for (i = 0; i < npage; i++) {
+ if (put_pfn(pfn++, dma->prot)) {
+ unlocked++;
+ if (vfio_find_vpfn(dma, iova + (i << PAGE_SHIFT)))
+ locked++;
}
}
- if (!rsvd)
- vfio_lock_acct(i);
+ if (do_accounting)
+ vfio_lock_acct(dma->task, locked - unlocked);
- return i;
+ return unlocked;
}
-static long vfio_unpin_pages(unsigned long pfn, long npage,
- int prot, bool do_accounting)
+static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
+ unsigned long *pfn_base, bool do_accounting)
{
- unsigned long unlocked = 0;
- long i;
+ unsigned long limit;
+ bool lock_cap = ns_capable(task_active_pid_ns(dma->task)->user_ns,
+ CAP_IPC_LOCK);
+ struct mm_struct *mm;
+ int ret;
+ bool rsvd;
- for (i = 0; i < npage; i++)
- unlocked += put_pfn(pfn++, prot);
+ mm = get_task_mm(dma->task);
+ if (!mm)
+ return -ENODEV;
+
+ ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
+ if (ret)
+ goto pin_page_exit;
+
+ rsvd = is_invalid_reserved_pfn(*pfn_base);
+ limit = task_rlimit(dma->task, RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+ if (!rsvd && !lock_cap && mm->locked_vm + 1 > limit) {
+ put_pfn(*pfn_base, dma->prot);
+ pr_warn("%s: Task %s (%d) RLIMIT_MEMLOCK (%ld) exceeded\n",
+ __func__, dma->task->comm, task_pid_nr(dma->task),
+ limit << PAGE_SHIFT);
+ ret = -ENOMEM;
+ goto pin_page_exit;
+ }
+
+ if (!rsvd && do_accounting)
+ vfio_lock_acct(dma->task, 1);
+ ret = 1;
+
+pin_page_exit:
+ mmput(mm);
+ return ret;
+}
+
+static int vfio_unpin_page_external(struct vfio_dma *dma, dma_addr_t iova,
+ bool do_accounting)
+{
+ int unlocked;
+ struct vfio_pfn *vpfn = vfio_find_vpfn(dma, iova);
+
+ if (!vpfn)
+ return 0;
+
+ unlocked = vfio_iova_put_vfio_pfn(dma, vpfn);
if (do_accounting)
- vfio_lock_acct(-unlocked);
+ vfio_lock_acct(dma->task, -unlocked);
return unlocked;
}
-static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
+static int vfio_iommu_type1_pin_pages(void *iommu_data,
+ unsigned long *user_pfn,
+ int npage, int prot,
+ unsigned long *phys_pfn)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ int i, j, ret;
+ unsigned long remote_vaddr;
+ struct vfio_dma *dma;
+ bool do_accounting;
+
+ if (!iommu || !user_pfn || !phys_pfn)
+ return -EINVAL;
+
+ /* Supported for v2 version only */
+ if (!iommu->v2)
+ return -EACCES;
+
+ mutex_lock(&iommu->lock);
+
+ /* Fail if notifier list is empty */
+ if ((!iommu->external_domain) || (!iommu->notifier.head)) {
+ ret = -EINVAL;
+ goto pin_done;
+ }
+
+ /*
+ * If iommu capable domain exist in the container then all pages are
+ * already pinned and accounted. Accouting should be done if there is no
+ * iommu capable domain in the container.
+ */
+ do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu);
+
+ for (i = 0; i < npage; i++) {
+ dma_addr_t iova;
+ struct vfio_pfn *vpfn;
+
+ iova = user_pfn[i] << PAGE_SHIFT;
+ dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
+ if (!dma) {
+ ret = -EINVAL;
+ goto pin_unwind;
+ }
+
+ if ((dma->prot & prot) != prot) {
+ ret = -EPERM;
+ goto pin_unwind;
+ }
+
+ vpfn = vfio_iova_get_vfio_pfn(dma, iova);
+ if (vpfn) {
+ phys_pfn[i] = vpfn->pfn;
+ continue;
+ }
+
+ remote_vaddr = dma->vaddr + iova - dma->iova;
+ ret = vfio_pin_page_external(dma, remote_vaddr, &phys_pfn[i],
+ do_accounting);
+ if (ret <= 0) {
+ WARN_ON(!ret);
+ goto pin_unwind;
+ }
+
+ ret = vfio_add_to_pfn_list(dma, iova, phys_pfn[i]);
+ if (ret) {
+ vfio_unpin_page_external(dma, iova, do_accounting);
+ goto pin_unwind;
+ }
+ }
+
+ ret = i;
+ goto pin_done;
+
+pin_unwind:
+ phys_pfn[i] = 0;
+ for (j = 0; j < i; j++) {
+ dma_addr_t iova;
+
+ iova = user_pfn[j] << PAGE_SHIFT;
+ dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
+ vfio_unpin_page_external(dma, iova, do_accounting);
+ phys_pfn[j] = 0;
+ }
+pin_done:
+ mutex_unlock(&iommu->lock);
+ return ret;
+}
+
+static int vfio_iommu_type1_unpin_pages(void *iommu_data,
+ unsigned long *user_pfn,
+ int npage)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ bool do_accounting;
+ int i;
+
+ if (!iommu || !user_pfn)
+ return -EINVAL;
+
+ /* Supported for v2 version only */
+ if (!iommu->v2)
+ return -EACCES;
+
+ mutex_lock(&iommu->lock);
+
+ if (!iommu->external_domain) {
+ mutex_unlock(&iommu->lock);
+ return -EINVAL;
+ }
+
+ do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu);
+ for (i = 0; i < npage; i++) {
+ struct vfio_dma *dma;
+ dma_addr_t iova;
+
+ iova = user_pfn[i] << PAGE_SHIFT;
+ dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
+ if (!dma)
+ goto unpin_exit;
+ vfio_unpin_page_external(dma, iova, do_accounting);
+ }
+
+unpin_exit:
+ mutex_unlock(&iommu->lock);
+ return i > npage ? npage : (i > 0 ? i : -EINVAL);
+}
+
+static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
+ bool do_accounting)
{
dma_addr_t iova = dma->iova, end = dma->iova + dma->size;
struct vfio_domain *domain, *d;
long unlocked = 0;
if (!dma->size)
- return;
+ return 0;
+
+ if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu))
+ return 0;
+
/*
* We use the IOMMU to track the physical addresses, otherwise we'd
* need a much more complicated tracking system. Unfortunately that
@@ -382,21 +724,28 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
if (WARN_ON(!unmapped))
break;
- unlocked += vfio_unpin_pages(phys >> PAGE_SHIFT,
- unmapped >> PAGE_SHIFT,
- dma->prot, false);
+ unlocked += vfio_unpin_pages_remote(dma, iova,
+ phys >> PAGE_SHIFT,
+ unmapped >> PAGE_SHIFT,
+ false);
iova += unmapped;
cond_resched();
}
- vfio_lock_acct(-unlocked);
+ dma->iommu_mapped = false;
+ if (do_accounting) {
+ vfio_lock_acct(dma->task, -unlocked);
+ return 0;
+ }
+ return unlocked;
}
static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
{
- vfio_unmap_unpin(iommu, dma);
+ vfio_unmap_unpin(iommu, dma, true);
vfio_unlink_dma(iommu, dma);
+ put_task_struct(dma->task);
kfree(dma);
}
@@ -430,9 +779,9 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
struct vfio_iommu_type1_dma_unmap *unmap)
{
uint64_t mask;
- struct vfio_dma *dma;
+ struct vfio_dma *dma, *dma_last = NULL;
size_t unmapped = 0;
- int ret = 0;
+ int ret = 0, retries = 0;
mask = ((uint64_t)1 << __ffs(vfio_pgsize_bitmap(iommu))) - 1;
@@ -442,7 +791,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
return -EINVAL;
WARN_ON(mask & PAGE_MASK);
-
+again:
mutex_lock(&iommu->lock);
/*
@@ -477,7 +826,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
* mappings within the range.
*/
if (iommu->v2) {
- dma = vfio_find_dma(iommu, unmap->iova, 0);
+ dma = vfio_find_dma(iommu, unmap->iova, 1);
if (dma && dma->iova != unmap->iova) {
ret = -EINVAL;
goto unlock;
@@ -492,6 +841,38 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
if (!iommu->v2 && unmap->iova > dma->iova)
break;
+ /*
+ * Task with same address space who mapped this iova range is
+ * allowed to unmap the iova range.
+ */
+ if (dma->task->mm != current->mm)
+ break;
+
+ if (!RB_EMPTY_ROOT(&dma->pfn_list)) {
+ struct vfio_iommu_type1_dma_unmap nb_unmap;
+
+ if (dma_last == dma) {
+ BUG_ON(++retries > 10);
+ } else {
+ dma_last = dma;
+ retries = 0;
+ }
+
+ nb_unmap.iova = dma->iova;
+ nb_unmap.size = dma->size;
+
+ /*
+ * Notify anyone (mdev vendor drivers) to invalidate and
+ * unmap iovas within the range we're about to unmap.
+ * Vendor drivers MUST unpin pages in response to an
+ * invalidation.
+ */
+ mutex_unlock(&iommu->lock);
+ blocking_notifier_call_chain(&iommu->notifier,
+ VFIO_IOMMU_NOTIFY_DMA_UNMAP,
+ &nb_unmap);
+ goto again;
+ }
unmapped += dma->size;
vfio_remove_dma(iommu, dma);
}
@@ -558,17 +939,56 @@ unwind:
return ret;
}
+static int vfio_pin_map_dma(struct vfio_iommu *iommu, struct vfio_dma *dma,
+ size_t map_size)
+{
+ dma_addr_t iova = dma->iova;
+ unsigned long vaddr = dma->vaddr;
+ size_t size = map_size;
+ long npage;
+ unsigned long pfn;
+ int ret = 0;
+
+ while (size) {
+ /* Pin a contiguous chunk of memory */
+ npage = vfio_pin_pages_remote(dma, vaddr + dma->size,
+ size >> PAGE_SHIFT, &pfn);
+ if (npage <= 0) {
+ WARN_ON(!npage);
+ ret = (int)npage;
+ break;
+ }
+
+ /* Map it! */
+ ret = vfio_iommu_map(iommu, iova + dma->size, pfn, npage,
+ dma->prot);
+ if (ret) {
+ vfio_unpin_pages_remote(dma, iova + dma->size, pfn,
+ npage, true);
+ break;
+ }
+
+ size -= npage << PAGE_SHIFT;
+ dma->size += npage << PAGE_SHIFT;
+ }
+
+ dma->iommu_mapped = true;
+
+ if (ret)
+ vfio_remove_dma(iommu, dma);
+
+ return ret;
+}
+
static int vfio_dma_do_map(struct vfio_iommu *iommu,
struct vfio_iommu_type1_dma_map *map)
{
dma_addr_t iova = map->iova;
unsigned long vaddr = map->vaddr;
size_t size = map->size;
- long npage;
int ret = 0, prot = 0;
uint64_t mask;
struct vfio_dma *dma;
- unsigned long pfn;
/* Verify that none of our __u64 fields overflow */
if (map->size != size || map->vaddr != vaddr || map->iova != iova)
@@ -594,47 +1014,33 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
mutex_lock(&iommu->lock);
if (vfio_find_dma(iommu, iova, size)) {
- mutex_unlock(&iommu->lock);
- return -EEXIST;
+ ret = -EEXIST;
+ goto out_unlock;
}
dma = kzalloc(sizeof(*dma), GFP_KERNEL);
if (!dma) {
- mutex_unlock(&iommu->lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_unlock;
}
dma->iova = iova;
dma->vaddr = vaddr;
dma->prot = prot;
+ get_task_struct(current);
+ dma->task = current;
+ dma->pfn_list = RB_ROOT;
/* Insert zero-sized and grow as we map chunks of it */
vfio_link_dma(iommu, dma);
- while (size) {
- /* Pin a contiguous chunk of memory */
- npage = vfio_pin_pages(vaddr + dma->size,
- size >> PAGE_SHIFT, prot, &pfn);
- if (npage <= 0) {
- WARN_ON(!npage);
- ret = (int)npage;
- break;
- }
-
- /* Map it! */
- ret = vfio_iommu_map(iommu, iova + dma->size, pfn, npage, prot);
- if (ret) {
- vfio_unpin_pages(pfn, npage, prot, true);
- break;
- }
-
- size -= npage << PAGE_SHIFT;
- dma->size += npage << PAGE_SHIFT;
- }
-
- if (ret)
- vfio_remove_dma(iommu, dma);
+ /* Don't pin and map if container doesn't contain IOMMU capable domain*/
+ if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu))
+ dma->size = size;
+ else
+ ret = vfio_pin_map_dma(iommu, dma, size);
+out_unlock:
mutex_unlock(&iommu->lock);
return ret;
}
@@ -662,10 +1068,6 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
n = rb_first(&iommu->dma_list);
- /* If there's not a domain, there better not be any mappings */
- if (WARN_ON(n && !d))
- return -EINVAL;
-
for (; n; n = rb_next(n)) {
struct vfio_dma *dma;
dma_addr_t iova;
@@ -674,21 +1076,49 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
iova = dma->iova;
while (iova < dma->iova + dma->size) {
- phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
+ phys_addr_t phys;
size_t size;
- if (WARN_ON(!phys)) {
- iova += PAGE_SIZE;
- continue;
+ if (dma->iommu_mapped) {
+ phys_addr_t p;
+ dma_addr_t i;
+
+ phys = iommu_iova_to_phys(d->domain, iova);
+
+ if (WARN_ON(!phys)) {
+ iova += PAGE_SIZE;
+ continue;
+ }
+
+ size = PAGE_SIZE;
+ p = phys + size;
+ i = iova + size;
+ while (i < dma->iova + dma->size &&
+ p == iommu_iova_to_phys(d->domain, i)) {
+ size += PAGE_SIZE;
+ p += PAGE_SIZE;
+ i += PAGE_SIZE;
+ }
+ } else {
+ unsigned long pfn;
+ unsigned long vaddr = dma->vaddr +
+ (iova - dma->iova);
+ size_t n = dma->iova + dma->size - iova;
+ long npage;
+
+ npage = vfio_pin_pages_remote(dma, vaddr,
+ n >> PAGE_SHIFT,
+ &pfn);
+ if (npage <= 0) {
+ WARN_ON(!npage);
+ ret = (int)npage;
+ return ret;
+ }
+
+ phys = pfn << PAGE_SHIFT;
+ size = npage << PAGE_SHIFT;
}
- size = PAGE_SIZE;
-
- while (iova + size < dma->iova + dma->size &&
- phys + size == iommu_iova_to_phys(d->domain,
- iova + size))
- size += PAGE_SIZE;
-
ret = iommu_map(domain->domain, iova, phys,
size, dma->prot | domain->prot);
if (ret)
@@ -696,8 +1126,8 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
iova += size;
}
+ dma->iommu_mapped = true;
}
-
return 0;
}
@@ -734,22 +1164,39 @@ static void vfio_test_domain_fgsp(struct vfio_domain *domain)
__free_pages(pages, order);
}
+static struct vfio_group *find_iommu_group(struct vfio_domain *domain,
+ struct iommu_group *iommu_group)
+{
+ struct vfio_group *g;
+
+ list_for_each_entry(g, &domain->group_list, next) {
+ if (g->iommu_group == iommu_group)
+ return g;
+ }
+
+ return NULL;
+}
+
static int vfio_iommu_type1_attach_group(void *iommu_data,
struct iommu_group *iommu_group)
{
struct vfio_iommu *iommu = iommu_data;
- struct vfio_group *group, *g;
+ struct vfio_group *group;
struct vfio_domain *domain, *d;
- struct bus_type *bus = NULL;
+ struct bus_type *bus = NULL, *mdev_bus;
int ret;
mutex_lock(&iommu->lock);
list_for_each_entry(d, &iommu->domain_list, next) {
- list_for_each_entry(g, &d->group_list, next) {
- if (g->iommu_group != iommu_group)
- continue;
+ if (find_iommu_group(d, iommu_group)) {
+ mutex_unlock(&iommu->lock);
+ return -EINVAL;
+ }
+ }
+ if (iommu->external_domain) {
+ if (find_iommu_group(iommu->external_domain, iommu_group)) {
mutex_unlock(&iommu->lock);
return -EINVAL;
}
@@ -769,6 +1216,25 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
if (ret)
goto out_free;
+ mdev_bus = symbol_get(mdev_bus_type);
+
+ if (mdev_bus) {
+ if ((bus == mdev_bus) && !iommu_present(bus)) {
+ symbol_put(mdev_bus_type);
+ if (!iommu->external_domain) {
+ INIT_LIST_HEAD(&domain->group_list);
+ iommu->external_domain = domain;
+ } else
+ kfree(domain);
+
+ list_add(&group->next,
+ &iommu->external_domain->group_list);
+ mutex_unlock(&iommu->lock);
+ return 0;
+ }
+ symbol_put(mdev_bus_type);
+ }
+
domain->domain = iommu_domain_alloc(bus);
if (!domain->domain) {
ret = -EIO;
@@ -859,6 +1325,46 @@ static void vfio_iommu_unmap_unpin_all(struct vfio_iommu *iommu)
vfio_remove_dma(iommu, rb_entry(node, struct vfio_dma, node));
}
+static void vfio_iommu_unmap_unpin_reaccount(struct vfio_iommu *iommu)
+{
+ struct rb_node *n, *p;
+
+ n = rb_first(&iommu->dma_list);
+ for (; n; n = rb_next(n)) {
+ struct vfio_dma *dma;
+ long locked = 0, unlocked = 0;
+
+ dma = rb_entry(n, struct vfio_dma, node);
+ unlocked += vfio_unmap_unpin(iommu, dma, false);
+ p = rb_first(&dma->pfn_list);
+ for (; p; p = rb_next(p)) {
+ struct vfio_pfn *vpfn = rb_entry(p, struct vfio_pfn,
+ node);
+
+ if (!is_invalid_reserved_pfn(vpfn->pfn))
+ locked++;
+ }
+ vfio_lock_acct(dma->task, locked - unlocked);
+ }
+}
+
+static void vfio_sanity_check_pfn_list(struct vfio_iommu *iommu)
+{
+ struct rb_node *n;
+
+ n = rb_first(&iommu->dma_list);
+ for (; n; n = rb_next(n)) {
+ struct vfio_dma *dma;
+
+ dma = rb_entry(n, struct vfio_dma, node);
+
+ if (WARN_ON(!RB_EMPTY_ROOT(&dma->pfn_list)))
+ break;
+ }
+ /* mdev vendor driver must unregister notifier */
+ WARN_ON(iommu->notifier.head);
+}
+
static void vfio_iommu_type1_detach_group(void *iommu_data,
struct iommu_group *iommu_group)
{
@@ -868,31 +1374,55 @@ static void vfio_iommu_type1_detach_group(void *iommu_data,
mutex_lock(&iommu->lock);
- list_for_each_entry(domain, &iommu->domain_list, next) {
- list_for_each_entry(group, &domain->group_list, next) {
- if (group->iommu_group != iommu_group)
- continue;
-
- iommu_detach_group(domain->domain, iommu_group);
+ if (iommu->external_domain) {
+ group = find_iommu_group(iommu->external_domain, iommu_group);
+ if (group) {
list_del(&group->next);
kfree(group);
- /*
- * Group ownership provides privilege, if the group
- * list is empty, the domain goes away. If it's the
- * last domain, then all the mappings go away too.
- */
- if (list_empty(&domain->group_list)) {
- if (list_is_singular(&iommu->domain_list))
+
+ if (list_empty(&iommu->external_domain->group_list)) {
+ vfio_sanity_check_pfn_list(iommu);
+
+ if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu))
vfio_iommu_unmap_unpin_all(iommu);
- iommu_domain_free(domain->domain);
- list_del(&domain->next);
- kfree(domain);
+
+ kfree(iommu->external_domain);
+ iommu->external_domain = NULL;
+ }
+ goto detach_group_done;
+ }
+ }
+
+ list_for_each_entry(domain, &iommu->domain_list, next) {
+ group = find_iommu_group(domain, iommu_group);
+ if (!group)
+ continue;
+
+ iommu_detach_group(domain->domain, iommu_group);
+ list_del(&group->next);
+ kfree(group);
+ /*
+ * Group ownership provides privilege, if the group list is
+ * empty, the domain goes away. If it's the last domain with
+ * iommu and external domain doesn't exist, then all the
+ * mappings go away too. If it's the last domain with iommu and
+ * external domain exist, update accounting
+ */
+ if (list_empty(&domain->group_list)) {
+ if (list_is_singular(&iommu->domain_list)) {
+ if (!iommu->external_domain)
+ vfio_iommu_unmap_unpin_all(iommu);
+ else
+ vfio_iommu_unmap_unpin_reaccount(iommu);
}
- goto done;
+ iommu_domain_free(domain->domain);
+ list_del(&domain->next);
+ kfree(domain);
}
+ break;
}
-done:
+detach_group_done:
mutex_unlock(&iommu->lock);
}
@@ -920,31 +1450,46 @@ static void *vfio_iommu_type1_open(unsigned long arg)
INIT_LIST_HEAD(&iommu->domain_list);
iommu->dma_list = RB_ROOT;
mutex_init(&iommu->lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier);
return iommu;
}
+static void vfio_release_domain(struct vfio_domain *domain, bool external)
+{
+ struct vfio_group *group, *group_tmp;
+
+ list_for_each_entry_safe(group, group_tmp,
+ &domain->group_list, next) {
+ if (!external)
+ iommu_detach_group(domain->domain, group->iommu_group);
+ list_del(&group->next);
+ kfree(group);
+ }
+
+ if (!external)
+ iommu_domain_free(domain->domain);
+}
+
static void vfio_iommu_type1_release(void *iommu_data)
{
struct vfio_iommu *iommu = iommu_data;
struct vfio_domain *domain, *domain_tmp;
- struct vfio_group *group, *group_tmp;
+
+ if (iommu->external_domain) {
+ vfio_release_domain(iommu->external_domain, true);
+ vfio_sanity_check_pfn_list(iommu);
+ kfree(iommu->external_domain);
+ }
vfio_iommu_unmap_unpin_all(iommu);
list_for_each_entry_safe(domain, domain_tmp,
&iommu->domain_list, next) {
- list_for_each_entry_safe(group, group_tmp,
- &domain->group_list, next) {
- iommu_detach_group(domain->domain, group->iommu_group);
- list_del(&group->next);
- kfree(group);
- }
- iommu_domain_free(domain->domain);
+ vfio_release_domain(domain, false);
list_del(&domain->next);
kfree(domain);
}
-
kfree(iommu);
}
@@ -1040,14 +1585,42 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
return -ENOTTY;
}
+static int vfio_iommu_type1_register_notifier(void *iommu_data,
+ unsigned long *events,
+ struct notifier_block *nb)
+{
+ struct vfio_iommu *iommu = iommu_data;
+
+ /* clear known events */
+ *events &= ~VFIO_IOMMU_NOTIFY_DMA_UNMAP;
+
+ /* refuse to register if still events remaining */
+ if (*events)
+ return -EINVAL;
+
+ return blocking_notifier_chain_register(&iommu->notifier, nb);
+}
+
+static int vfio_iommu_type1_unregister_notifier(void *iommu_data,
+ struct notifier_block *nb)
+{
+ struct vfio_iommu *iommu = iommu_data;
+
+ return blocking_notifier_chain_unregister(&iommu->notifier, nb);
+}
+
static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = {
- .name = "vfio-iommu-type1",
- .owner = THIS_MODULE,
- .open = vfio_iommu_type1_open,
- .release = vfio_iommu_type1_release,
- .ioctl = vfio_iommu_type1_ioctl,
- .attach_group = vfio_iommu_type1_attach_group,
- .detach_group = vfio_iommu_type1_detach_group,
+ .name = "vfio-iommu-type1",
+ .owner = THIS_MODULE,
+ .open = vfio_iommu_type1_open,
+ .release = vfio_iommu_type1_release,
+ .ioctl = vfio_iommu_type1_ioctl,
+ .attach_group = vfio_iommu_type1_attach_group,
+ .detach_group = vfio_iommu_type1_detach_group,
+ .pin_pages = vfio_iommu_type1_pin_pages,
+ .unpin_pages = vfio_iommu_type1_unpin_pages,
+ .register_notifier = vfio_iommu_type1_register_notifier,
+ .unregister_notifier = vfio_iommu_type1_unregister_notifier,
};
static int __init vfio_iommu_type1_init(void)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 5dc128a8da83..5dc34653274a 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -342,7 +342,7 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
endtime = busy_clock() + vq->busyloop_timeout;
while (vhost_can_busy_poll(vq->dev, endtime) &&
vhost_vq_avail_empty(vq->dev, vq))
- cpu_relax_lowlatency();
+ cpu_relax();
preempt_enable();
r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
out_num, in_num, NULL, NULL);
@@ -533,7 +533,7 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk)
while (vhost_can_busy_poll(&net->dev, endtime) &&
!sk_has_rx_data(sk) &&
vhost_vq_avail_empty(&net->dev, vq))
- cpu_relax_lowlatency();
+ cpu_relax();
preempt_enable();
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c6f2d89c0e97..266354390c8f 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -261,8 +261,8 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
/* We can only add the work to the list after we're
* sure it was not in the list.
+ * test_and_set_bit() implies a memory barrier.
*/
- smp_mb();
llist_add(&work->node, &dev->work_list);
wake_up_process(dev->worker);
}
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index a504e2e003da..e6b70966c19d 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -195,7 +195,6 @@ static int
vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
{
struct vhost_vsock *vsock;
- struct vhost_virtqueue *vq;
int len = pkt->len;
/* Find the vhost_vsock according to guest context id */
@@ -205,8 +204,6 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
return -ENODEV;
}
- vq = &vsock->vqs[VSOCK_VQ_RX];
-
if (pkt->reply)
atomic_inc(&vsock->queued_replies);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e299149..c3f1fb9ee820 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -9,7 +9,7 @@ config VGA_CONSOLE
depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && \
!SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \
(!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \
- !ARM64 && !ARC && !MICROBLAZE
+ !ARM64 && !ARC && !MICROBLAZE && !OPENRISC
default y
help
Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 37a37c4d04cb..8c4dc1e1f94f 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -118,6 +118,31 @@ static inline bool fb_base_is_valid(void)
return false;
}
+#define efifb_attr_decl(name, fmt) \
+static ssize_t name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, fmt "\n", (screen_info.lfb_##name)); \
+} \
+static DEVICE_ATTR_RO(name)
+
+efifb_attr_decl(base, "0x%x");
+efifb_attr_decl(linelength, "%u");
+efifb_attr_decl(height, "%u");
+efifb_attr_decl(width, "%u");
+efifb_attr_decl(depth, "%u");
+
+static struct attribute *efifb_attrs[] = {
+ &dev_attr_base.attr,
+ &dev_attr_linelength.attr,
+ &dev_attr_width.attr,
+ &dev_attr_height.attr,
+ &dev_attr_depth.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(efifb);
+
static int efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@@ -205,14 +230,13 @@ static int efifb_probe(struct platform_device *dev)
} else {
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
- printk(KERN_WARNING
- "efifb: cannot reserve video memory at 0x%lx\n",
+ pr_warn("efifb: cannot reserve video memory at 0x%lx\n",
efifb_fix.smem_start);
}
info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
if (!info) {
- printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
+ pr_err("efifb: cannot allocate framebuffer\n");
err = -ENOMEM;
goto err_release_mem;
}
@@ -230,16 +254,15 @@ static int efifb_probe(struct platform_device *dev)
info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
if (!info->screen_base) {
- printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
- "0x%x @ 0x%lx\n",
+ pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
efifb_fix.smem_len, efifb_fix.smem_start);
err = -EIO;
goto err_release_fb;
}
- printk(KERN_INFO "efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
+ pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
efifb_fix.smem_start, size_remap/1024, size_total/1024);
- printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
efifb_defined.xres, efifb_defined.yres,
efifb_defined.bits_per_pixel, efifb_fix.line_length,
screen_info.pages);
@@ -247,7 +270,7 @@ static int efifb_probe(struct platform_device *dev)
efifb_defined.xres_virtual = efifb_defined.xres;
efifb_defined.yres_virtual = efifb_fix.smem_len /
efifb_fix.line_length;
- printk(KERN_INFO "efifb: scrolling: redraw\n");
+ pr_info("efifb: scrolling: redraw\n");
efifb_defined.yres_virtual = efifb_defined.yres;
/* some dummy values for timing to make fbset happy */
@@ -265,7 +288,7 @@ static int efifb_probe(struct platform_device *dev)
efifb_defined.transp.offset = screen_info.rsvd_pos;
efifb_defined.transp.length = screen_info.rsvd_size;
- printk(KERN_INFO "efifb: %s: "
+ pr_info("efifb: %s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
"Truecolor",
screen_info.rsvd_size,
@@ -285,12 +308,19 @@ static int efifb_probe(struct platform_device *dev)
info->fix = efifb_fix;
info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
- if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
- printk(KERN_ERR "efifb: cannot allocate colormap\n");
+ err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
+ if (err) {
+ pr_err("efifb: cannot add sysfs attrs\n");
goto err_unmap;
}
- if ((err = register_framebuffer(info)) < 0) {
- printk(KERN_ERR "efifb: cannot register framebuffer\n");
+ err = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (err < 0) {
+ pr_err("efifb: cannot allocate colormap\n");
+ goto err_groups;
+ }
+ err = register_framebuffer(info);
+ if (err < 0) {
+ pr_err("efifb: cannot register framebuffer\n");
goto err_fb_dealoc;
}
fb_info(info, "%s frame buffer device\n", info->fix.id);
@@ -298,6 +328,8 @@ static int efifb_probe(struct platform_device *dev)
err_fb_dealoc:
fb_dealloc_cmap(&info->cmap);
+err_groups:
+ sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
err_unmap:
iounmap(info->screen_base);
err_release_fb:
@@ -313,6 +345,7 @@ static int efifb_remove(struct platform_device *pdev)
struct fb_info *info = platform_get_drvdata(pdev);
unregister_framebuffer(info);
+ sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
framebuffer_release(info);
return 0;
diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c
index f948baa16d82..e219a0a22077 100644
--- a/drivers/video/fbdev/skeletonfb.c
+++ b/drivers/video/fbdev/skeletonfb.c
@@ -836,7 +836,7 @@ static void xxxfb_remove(struct pci_dev *dev)
* @dev: PCI device
* @msg: the suspend event code.
*
- * See Documentation/power/devices.txt for more information
+ * See Documentation/power/admin-guide/devices.rst for more information
*/
static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
{
@@ -851,7 +851,7 @@ static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
* xxxfb_resume - Optional but recommended function. Resume the device.
* @dev: PCI device
*
- * See Documentation/power/devices.txt for more information
+ * See Documentation/power/admin-guide/devices.rst for more information
*/
static int xxxfb_resume(struct pci_dev *dev)
{
@@ -915,7 +915,7 @@ static void __exit xxxfb_exit(void)
* @dev: platform device
* @msg: the suspend event code.
*
- * See Documentation/power/devices.txt for more information
+ * See Documentation/power/admin-guide/devices.rst for more information
*/
static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
{
@@ -930,7 +930,7 @@ static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
* xxxfb_resume - Optional but recommended function. Resume the device.
* @dev: platform device
*
- * See Documentation/power/devices.txt for more information
+ * See Documentation/power/admin-guide/devices.rst for more information
*/
static int xxxfb_resume(struct platform_dev *dev)
{
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 162689227a23..1cf907ecded4 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -533,6 +533,10 @@ hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)
return "4:3";
case HDMI_PICTURE_ASPECT_16_9:
return "16:9";
+ case HDMI_PICTURE_ASPECT_64_27:
+ return "64:27";
+ case HDMI_PICTURE_ASPECT_256_135:
+ return "256:135";
case HDMI_PICTURE_ASPECT_RESERVED:
return "Reserved";
}
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
index 8a1076beecd3..32b0a7543433 100644
--- a/drivers/video/of_display_timing.c
+++ b/drivers/video/of_display_timing.c
@@ -88,6 +88,15 @@ static int of_parse_display_timing(const struct device_node *np,
dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ if (!of_property_read_u32(np, "syncclk-active", &val))
+ dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE :
+ DISPLAY_FLAGS_SYNC_NEGEDGE;
+ else if (dt->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE))
+ dt->flags |= dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
+ DISPLAY_FLAGS_SYNC_POSEDGE :
+ DISPLAY_FLAGS_SYNC_NEGEDGE;
+
if (of_property_read_bool(np, "interlaced"))
dt->flags |= DISPLAY_FLAGS_INTERLACED;
if (of_property_read_bool(np, "doublescan"))
@@ -110,7 +119,7 @@ static int of_parse_display_timing(const struct device_node *np,
* @name: name of the timing node
* @dt: display_timing struct to fill
**/
-int of_get_display_timing(struct device_node *np, const char *name,
+int of_get_display_timing(const struct device_node *np, const char *name,
struct display_timing *dt)
{
struct device_node *timing_np;
@@ -133,7 +142,7 @@ EXPORT_SYMBOL_GPL(of_get_display_timing);
* of_get_display_timings - parse all display_timing entries from a device_node
* @np: device_node with the subnodes
**/
-struct display_timings *of_get_display_timings(struct device_node *np)
+struct display_timings *of_get_display_timings(const struct device_node *np)
{
struct device_node *timings_np;
struct device_node *entry;
@@ -249,7 +258,7 @@ EXPORT_SYMBOL_GPL(of_get_display_timings);
* of_display_timings_exist - check if a display-timings node is provided
* @np: device_node with the timing
**/
-int of_display_timings_exist(struct device_node *np)
+int of_display_timings_exist(const struct device_node *np)
{
struct device_node *timings_np;
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 77590320d44c..623f72334fa5 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -75,7 +75,7 @@ config VIRTIO_MMIO_CMDLINE_DEVICES
Allow virtio-mmio devices instantiation via the kernel command line
or module parameters. Be aware that using incorrect parameters (base
address in particular) can crash your system - you have been warned.
- See Documentation/kernel-parameters.txt for details.
+ See Documentation/admin-guide/kernel-parameters.rst for details.
If unsure, say 'N'.
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index b55981f88a08..529182d7d8a7 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -374,7 +374,7 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
}
-static void octeon_wdt_disable_interrupt(int cpu)
+static int octeon_wdt_cpu_pre_down(unsigned int cpu)
{
unsigned int core;
unsigned int irq;
@@ -392,9 +392,10 @@ static void octeon_wdt_disable_interrupt(int cpu)
cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
free_irq(irq, octeon_wdt_poke_irq);
+ return 0;
}
-static void octeon_wdt_setup_interrupt(int cpu)
+static int octeon_wdt_cpu_online(unsigned int cpu)
{
unsigned int core;
unsigned int irq;
@@ -424,25 +425,8 @@ static void octeon_wdt_setup_interrupt(int cpu)
ciu_wdog.s.len = timeout_cnt;
ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
-}
-static int octeon_wdt_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_DOWN_PREPARE:
- octeon_wdt_disable_interrupt(cpu);
- break;
- case CPU_ONLINE:
- case CPU_DOWN_FAILED:
- octeon_wdt_setup_interrupt(cpu);
- break;
- default:
- break;
- }
- return NOTIFY_OK;
+ return 0;
}
static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
@@ -531,10 +515,6 @@ static int octeon_wdt_stop(struct watchdog_device *wdog)
return 0;
}
-static struct notifier_block octeon_wdt_cpu_notifier = {
- .notifier_call = octeon_wdt_cpu_callback,
-};
-
static const struct watchdog_info octeon_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.identity = "OCTEON",
@@ -553,6 +533,7 @@ static struct watchdog_device octeon_wdt = {
.ops = &octeon_wdt_ops,
};
+static enum cpuhp_state octeon_wdt_online;
/**
* Module/ driver initialization.
*
@@ -562,7 +543,6 @@ static int __init octeon_wdt_init(void)
{
int i;
int ret;
- int cpu;
u64 *ptr;
/*
@@ -610,14 +590,16 @@ static int __init octeon_wdt_init(void)
cpumask_clear(&irq_enabled_cpus);
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- octeon_wdt_setup_interrupt(cpu);
-
- __register_hotcpu_notifier(&octeon_wdt_cpu_notifier);
- cpu_notifier_register_done();
-
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
+ octeon_wdt_cpu_online, octeon_wdt_cpu_pre_down);
+ if (ret < 0)
+ goto err;
+ octeon_wdt_online = ret;
return 0;
+err:
+ cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0);
+ watchdog_unregister_device(&octeon_wdt);
+ return ret;
}
/**
@@ -625,22 +607,8 @@ static int __init octeon_wdt_init(void)
*/
static void __exit octeon_wdt_cleanup(void)
{
- int cpu;
-
watchdog_unregister_device(&octeon_wdt);
-
- cpu_notifier_register_begin();
- __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier);
-
- for_each_online_cpu(cpu) {
- int core = cpu2core(cpu);
- /* Disable the watchdog */
- cvmx_write_csr(CVMX_CIU_WDOGX(core), 0);
- /* Free the interrupt handler */
- free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq);
- }
-
- cpu_notifier_register_done();
+ cpuhp_remove_state(octeon_wdt_online);
/*
* Disable the boot-bus memory, the code it points to is soon
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 9ecfcdcdd6d6..adc19ce3cc66 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -37,7 +37,6 @@
#include <asm/desc.h>
#include <asm/ptrace.h>
#include <asm/irq.h>
-#include <asm/idle.h>
#include <asm/io_apic.h>
#include <asm/i8259.h>
#include <asm/xen/pci.h>
@@ -1256,7 +1255,6 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
irq_enter();
#ifdef CONFIG_X86
- exit_idle();
inc_irq_stat(irq_hv_callback_count);
#endif
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 6181ad79e1a5..5ca1fb0043f6 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -34,6 +34,7 @@
#include <linux/idr.h>
#include <linux/sched.h>
#include <linux/uio.h>
+#include <linux/bvec.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 4c09d93d9569..b2f82cf6bf86 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -170,8 +170,8 @@ config BINFMT_MISC
You can do other nice things, too. Read the file
<file:Documentation/binfmt_misc.txt> to learn how to use this
- feature, <file:Documentation/java.txt> for information about how
- to include Java support. and <file:Documentation/mono.txt> for
+ feature, <file:Documentation/admin-guide/java.rst> for information about how
+ to include Java support. and <file:Documentation/admin-guide/mono.rst> for
information about how to include Mono-based .NET support.
To use binfmt_misc, you will need to mount it:
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 2472af2798c7..e6c1bd443806 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2204,7 +2204,9 @@ static int elf_core_dump(struct coredump_params *cprm)
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
- vma_filesz = kmalloc_array(segs - 1, sizeof(*vma_filesz), GFP_KERNEL);
+ if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz))
+ goto end_coredump;
+ vma_filesz = vmalloc((segs - 1) * sizeof(*vma_filesz));
if (!vma_filesz)
goto end_coredump;
@@ -2311,7 +2313,7 @@ end_coredump:
cleanup:
free_note_info(&info);
kfree(shdr4extnum);
- kfree(vma_filesz);
+ vfree(vma_filesz);
kfree(phdr4note);
kfree(elf);
out:
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 05b553368bb4..95acbd2ebc5d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -30,6 +30,7 @@
#include <linux/cleancache.h>
#include <linux/dax.h>
#include <linux/badblocks.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/falloc.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -175,17 +176,273 @@ static struct inode *bdev_file_inode(struct file *file)
return file->f_mapping->host;
}
+static unsigned int dio_bio_write_op(struct kiocb *iocb)
+{
+ unsigned int op = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE;
+
+ /* avoid the need for a I/O completion work item */
+ if (iocb->ki_flags & IOCB_DSYNC)
+ op |= REQ_FUA;
+ return op;
+}
+
+#define DIO_INLINE_BIO_VECS 4
+
+static void blkdev_bio_end_io_simple(struct bio *bio)
+{
+ struct task_struct *waiter = bio->bi_private;
+
+ WRITE_ONCE(bio->bi_private, NULL);
+ wake_up_process(waiter);
+}
+
static ssize_t
-blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+__blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
+ int nr_pages)
+{
+ struct file *file = iocb->ki_filp;
+ struct block_device *bdev = I_BDEV(bdev_file_inode(file));
+ struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs, *bvec;
+ loff_t pos = iocb->ki_pos;
+ bool should_dirty = false;
+ struct bio bio;
+ ssize_t ret;
+ blk_qc_t qc;
+ int i;
+
+ if ((pos | iov_iter_alignment(iter)) &
+ (bdev_logical_block_size(bdev) - 1))
+ return -EINVAL;
+
+ if (nr_pages <= DIO_INLINE_BIO_VECS)
+ vecs = inline_vecs;
+ else {
+ vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL);
+ if (!vecs)
+ return -ENOMEM;
+ }
+
+ bio_init(&bio, vecs, nr_pages);
+ bio.bi_bdev = bdev;
+ bio.bi_iter.bi_sector = pos >> 9;
+ bio.bi_private = current;
+ bio.bi_end_io = blkdev_bio_end_io_simple;
+
+ ret = bio_iov_iter_get_pages(&bio, iter);
+ if (unlikely(ret))
+ return ret;
+ ret = bio.bi_iter.bi_size;
+
+ if (iov_iter_rw(iter) == READ) {
+ bio.bi_opf = REQ_OP_READ;
+ if (iter_is_iovec(iter))
+ should_dirty = true;
+ } else {
+ bio.bi_opf = dio_bio_write_op(iocb);
+ task_io_account_write(ret);
+ }
+
+ qc = submit_bio(&bio);
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (!READ_ONCE(bio.bi_private))
+ break;
+ if (!(iocb->ki_flags & IOCB_HIPRI) ||
+ !blk_mq_poll(bdev_get_queue(bdev), qc))
+ io_schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+
+ bio_for_each_segment_all(bvec, &bio, i) {
+ if (should_dirty && !PageCompound(bvec->bv_page))
+ set_page_dirty_lock(bvec->bv_page);
+ put_page(bvec->bv_page);
+ }
+
+ if (vecs != inline_vecs)
+ kfree(vecs);
+
+ if (unlikely(bio.bi_error))
+ return bio.bi_error;
+ iocb->ki_pos += ret;
+ return ret;
+}
+
+struct blkdev_dio {
+ union {
+ struct kiocb *iocb;
+ struct task_struct *waiter;
+ };
+ size_t size;
+ atomic_t ref;
+ bool multi_bio : 1;
+ bool should_dirty : 1;
+ bool is_sync : 1;
+ struct bio bio;
+};
+
+static struct bio_set *blkdev_dio_pool __read_mostly;
+
+static void blkdev_bio_end_io(struct bio *bio)
+{
+ struct blkdev_dio *dio = bio->bi_private;
+ bool should_dirty = dio->should_dirty;
+
+ if (dio->multi_bio && !atomic_dec_and_test(&dio->ref)) {
+ if (bio->bi_error && !dio->bio.bi_error)
+ dio->bio.bi_error = bio->bi_error;
+ } else {
+ if (!dio->is_sync) {
+ struct kiocb *iocb = dio->iocb;
+ ssize_t ret = dio->bio.bi_error;
+
+ if (likely(!ret)) {
+ ret = dio->size;
+ iocb->ki_pos += ret;
+ }
+
+ dio->iocb->ki_complete(iocb, ret, 0);
+ bio_put(&dio->bio);
+ } else {
+ struct task_struct *waiter = dio->waiter;
+
+ WRITE_ONCE(dio->waiter, NULL);
+ wake_up_process(waiter);
+ }
+ }
+
+ if (should_dirty) {
+ bio_check_pages_dirty(bio);
+ } else {
+ struct bio_vec *bvec;
+ int i;
+
+ bio_for_each_segment_all(bvec, bio, i)
+ put_page(bvec->bv_page);
+ bio_put(bio);
+ }
+}
+
+static ssize_t
+__blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
{
struct file *file = iocb->ki_filp;
struct inode *inode = bdev_file_inode(file);
+ struct block_device *bdev = I_BDEV(inode);
+ struct blkdev_dio *dio;
+ struct bio *bio;
+ bool is_read = (iov_iter_rw(iter) == READ);
+ loff_t pos = iocb->ki_pos;
+ blk_qc_t qc = BLK_QC_T_NONE;
+ int ret;
+
+ if ((pos | iov_iter_alignment(iter)) &
+ (bdev_logical_block_size(bdev) - 1))
+ return -EINVAL;
+
+ bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, blkdev_dio_pool);
+ bio_get(bio); /* extra ref for the completion handler */
+
+ dio = container_of(bio, struct blkdev_dio, bio);
+ dio->is_sync = is_sync_kiocb(iocb);
+ if (dio->is_sync)
+ dio->waiter = current;
+ else
+ dio->iocb = iocb;
+
+ dio->size = 0;
+ dio->multi_bio = false;
+ dio->should_dirty = is_read && (iter->type == ITER_IOVEC);
+
+ for (;;) {
+ bio->bi_bdev = bdev;
+ bio->bi_iter.bi_sector = pos >> 9;
+ bio->bi_private = dio;
+ bio->bi_end_io = blkdev_bio_end_io;
+
+ ret = bio_iov_iter_get_pages(bio, iter);
+ if (unlikely(ret)) {
+ bio->bi_error = ret;
+ bio_endio(bio);
+ break;
+ }
+
+ if (is_read) {
+ bio->bi_opf = REQ_OP_READ;
+ if (dio->should_dirty)
+ bio_set_pages_dirty(bio);
+ } else {
+ bio->bi_opf = dio_bio_write_op(iocb);
+ task_io_account_write(bio->bi_iter.bi_size);
+ }
+
+ dio->size += bio->bi_iter.bi_size;
+ pos += bio->bi_iter.bi_size;
+
+ nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES);
+ if (!nr_pages) {
+ qc = submit_bio(bio);
+ break;
+ }
+
+ if (!dio->multi_bio) {
+ dio->multi_bio = true;
+ atomic_set(&dio->ref, 2);
+ } else {
+ atomic_inc(&dio->ref);
+ }
- return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter,
- blkdev_get_block, NULL, NULL,
- DIO_SKIP_DIO_COUNT);
+ submit_bio(bio);
+ bio = bio_alloc(GFP_KERNEL, nr_pages);
+ }
+
+ if (!dio->is_sync)
+ return -EIOCBQUEUED;
+
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (!READ_ONCE(dio->waiter))
+ break;
+
+ if (!(iocb->ki_flags & IOCB_HIPRI) ||
+ !blk_mq_poll(bdev_get_queue(bdev), qc))
+ io_schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+
+ ret = dio->bio.bi_error;
+ if (likely(!ret)) {
+ ret = dio->size;
+ iocb->ki_pos += ret;
+ }
+
+ bio_put(&dio->bio);
+ return ret;
}
+static ssize_t
+blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+{
+ int nr_pages;
+
+ nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES + 1);
+ if (!nr_pages)
+ return 0;
+ if (is_sync_kiocb(iocb) && nr_pages <= BIO_MAX_PAGES)
+ return __blkdev_direct_IO_simple(iocb, iter, nr_pages);
+
+ return __blkdev_direct_IO(iocb, iter, min(nr_pages, BIO_MAX_PAGES));
+}
+
+static __init int blkdev_init(void)
+{
+ blkdev_dio_pool = bioset_create(4, offsetof(struct blkdev_dio, bio));
+ if (!blkdev_dio_pool)
+ return -ENOMEM;
+ return 0;
+}
+module_init(blkdev_init);
+
int __sync_blockdev(struct block_device *bdev, int wait)
{
if (!bdev)
@@ -1950,6 +2207,7 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
spin_lock(&blockdev_superblock->s_inode_list_lock);
list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
struct address_space *mapping = inode->i_mapping;
+ struct block_device *bdev;
spin_lock(&inode->i_lock);
if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) ||
@@ -1970,8 +2228,12 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
*/
iput(old_inode);
old_inode = inode;
+ bdev = I_BDEV(inode);
- func(I_BDEV(inode), arg);
+ mutex_lock(&bdev->bd_mutex);
+ if (bdev->bd_openers)
+ func(bdev, arg);
+ mutex_unlock(&bdev->bd_mutex);
spin_lock(&blockdev_superblock->s_inode_list_lock);
}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3a57f99d96aa..fe10afd51e02 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -930,7 +930,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
atomic_inc(&fs_info->nr_async_submits);
- if (bio->bi_opf & REQ_SYNC)
+ if (op_is_sync(bio->bi_opf))
btrfs_set_work_high_priority(&async->work);
btrfs_queue_work(fs_info->workers, &async->work);
@@ -3485,9 +3485,9 @@ static int write_dev_supers(struct btrfs_device *device,
* to go down lazy.
*/
if (i == 0)
- ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_FUA, bh);
+ ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh);
else
- ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh);
+ ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh);
if (ret)
errors++;
}
@@ -3551,7 +3551,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
bio->bi_end_io = btrfs_end_empty_barrier;
bio->bi_bdev = device->bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
init_completion(&device->flush_wait);
bio->bi_private = &device->flush_wait;
device->flush_bio = bio;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 8ed05d95584a..1e67723c27a1 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -127,7 +127,7 @@ struct extent_page_data {
*/
unsigned int extent_locked:1;
- /* tells the submit_bio code to use a WRITE_SYNC */
+ /* tells the submit_bio code to use REQ_SYNC */
unsigned int sync_io:1;
};
@@ -2047,7 +2047,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
return -EIO;
}
bio->bi_bdev = dev->bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC);
+ bio->bi_opf = REQ_OP_WRITE | REQ_SYNC;
bio_add_page(bio, page, length, pg_offset);
if (btrfsic_submit_bio_wait(bio)) {
@@ -2388,7 +2388,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
struct inode *inode = page->mapping->host;
struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
struct bio *bio;
- int read_mode;
+ int read_mode = 0;
int ret;
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
@@ -2404,9 +2404,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
}
if (failed_bio->bi_vcnt > 1)
- read_mode = READ_SYNC | REQ_FAILFAST_DEV;
- else
- read_mode = READ_SYNC;
+ read_mode |= REQ_FAILFAST_DEV;
phy_offset >>= inode->i_sb->s_blocksize_bits;
bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page,
@@ -3484,7 +3482,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
unsigned long nr_written = 0;
if (wbc->sync_mode == WB_SYNC_ALL)
- write_flags = WRITE_SYNC;
+ write_flags = REQ_SYNC;
trace___extent_writepage(page, inode, wbc);
@@ -3729,7 +3727,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
unsigned long i, num_pages;
unsigned long bio_flags = 0;
unsigned long start, end;
- int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META;
+ int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META;
int ret = 0;
clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
@@ -4076,7 +4074,7 @@ static void flush_epd_write_bio(struct extent_page_data *epd)
int ret;
bio_set_op_attrs(epd->bio, REQ_OP_WRITE,
- epd->sync_io ? WRITE_SYNC : 0);
+ epd->sync_io ? REQ_SYNC : 0);
ret = submit_one_bio(epd->bio, 0, epd->bio_flags);
BUG_ON(ret < 0); /* -ENOMEM */
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8e3a5a266917..a4c879671b9d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7917,7 +7917,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
struct io_failure_record *failrec;
struct bio *bio;
int isector;
- int read_mode;
+ int read_mode = 0;
int ret;
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
@@ -7936,9 +7936,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
if ((failed_bio->bi_vcnt > 1)
|| (failed_bio->bi_io_vec->bv_len
> BTRFS_I(inode)->root->sectorsize))
- read_mode = READ_SYNC | REQ_FAILFAST_DEV;
- else
- read_mode = READ_SYNC;
+ read_mode |= REQ_FAILFAST_DEV;
isector = start - btrfs_io_bio(failed_bio)->logical;
isector >>= inode->i_sb->s_blocksize_bits;
@@ -8427,7 +8425,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
if (!bio)
return -ENOMEM;
- bio_set_op_attrs(bio, bio_op(orig_bio), bio_flags(orig_bio));
+ bio->bi_opf = orig_bio->bi_opf;
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
@@ -8465,8 +8463,7 @@ next_block:
start_sector, GFP_NOFS);
if (!bio)
goto out_err;
- bio_set_op_attrs(bio, bio_op(orig_bio),
- bio_flags(orig_bio));
+ bio->bi_opf = orig_bio->bi_opf;
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index fffb9ab8526e..ff3078234d94 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -4440,7 +4440,7 @@ static int write_page_nocow(struct scrub_ctx *sctx,
bio->bi_iter.bi_size = 0;
bio->bi_iter.bi_sector = physical_for_dev_replace >> 9;
bio->bi_bdev = dev->bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC);
+ bio->bi_opf = REQ_OP_WRITE | REQ_SYNC;
ret = bio_add_page(bio, page, PAGE_SIZE, 0);
if (ret != PAGE_SIZE) {
leave_with_eio:
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 74ed5aae6cea..180f910339f4 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -202,27 +202,31 @@ static struct ratelimit_state printk_limits[] = {
void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
{
struct super_block *sb = fs_info->sb;
- char lvl[4];
+ char lvl[PRINTK_MAX_SINGLE_HEADER_LEN + 1];
struct va_format vaf;
va_list args;
- const char *type = logtypes[4];
+ const char *type = NULL;
int kern_level;
struct ratelimit_state *ratelimit;
va_start(args, fmt);
- kern_level = printk_get_level(fmt);
- if (kern_level) {
+ while ((kern_level = printk_get_level(fmt)) != 0) {
size_t size = printk_skip_level(fmt) - fmt;
- memcpy(lvl, fmt, size);
- lvl[size] = '\0';
+
+ if (kern_level >= '0' && kern_level <= '7') {
+ memcpy(lvl, fmt, size);
+ lvl[size] = '\0';
+ type = logtypes[kern_level - '0'];
+ ratelimit = &printk_limits[kern_level - '0'];
+ }
fmt += size;
- type = logtypes[kern_level - '0'];
- ratelimit = &printk_limits[kern_level - '0'];
- } else {
+ }
+
+ if (!type) {
*lvl = '\0';
- /* Default to debug output */
- ratelimit = &printk_limits[7];
+ type = logtypes[4];
+ ratelimit = &printk_limits[4];
}
vaf.fmt = fmt;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 71a60cc01451..0d7d635d8bfb 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6023,7 +6023,7 @@ static void btrfs_end_bio(struct bio *bio)
else
btrfs_dev_stat_inc(dev,
BTRFS_DEV_STAT_READ_ERRS);
- if ((bio->bi_opf & WRITE_FLUSH) == WRITE_FLUSH)
+ if (bio->bi_opf & REQ_PREFLUSH)
btrfs_dev_stat_inc(dev,
BTRFS_DEV_STAT_FLUSH_ERRS);
btrfs_dev_stat_print_on_error(dev);
@@ -6100,7 +6100,7 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root,
bio->bi_next = NULL;
spin_lock(&device->io_lock);
- if (bio->bi_opf & REQ_SYNC)
+ if (op_is_sync(bio->bi_opf))
pending_bios = &device->pending_sync_bios;
else
pending_bios = &device->pending_bios;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 09ed29c67848..f137ffe6654c 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -62,7 +62,7 @@ struct btrfs_device {
int running_pending;
/* regular prio bios */
struct btrfs_pending_bios pending_bios;
- /* WRITE_SYNC bios */
+ /* sync bios */
struct btrfs_pending_bios pending_sync_bios;
struct block_device *bdev;
diff --git a/fs/buffer.c b/fs/buffer.c
index b205a629001d..a3bfd57c2697 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -753,7 +753,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
* still in flight on potentially older
* contents.
*/
- write_dirty_buffer(bh, WRITE_SYNC);
+ write_dirty_buffer(bh, REQ_SYNC);
/*
* Kick off IO for the previous mapping. Note
@@ -1684,7 +1684,7 @@ static struct buffer_head *create_page_buffers(struct page *page, struct inode *
* prevents this contention from occurring.
*
* If block_write_full_page() is called with wbc->sync_mode ==
- * WB_SYNC_ALL, the writes are posted using WRITE_SYNC; this
+ * WB_SYNC_ALL, the writes are posted using REQ_SYNC; this
* causes the writes to be flagged as synchronous writes.
*/
int __block_write_full_page(struct inode *inode, struct page *page,
@@ -1697,7 +1697,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
struct buffer_head *bh, *head;
unsigned int blocksize, bbits;
int nr_underway = 0;
- int write_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0);
+ int write_flags = wbc_to_write_flags(wbc);
head = create_page_buffers(page, inode,
(1 << BH_Dirty)|(1 << BH_Uptodate));
@@ -3118,7 +3118,7 @@ EXPORT_SYMBOL(submit_bh);
/**
* ll_rw_block: low-level access to block devices (DEPRECATED)
* @op: whether to %READ or %WRITE
- * @op_flags: rq_flag_bits
+ * @op_flags: req_flag_bits
* @nr: number of &struct buffer_heads in the array
* @bhs: array of pointers to &struct buffer_head
*
@@ -3210,7 +3210,7 @@ EXPORT_SYMBOL(__sync_dirty_buffer);
int sync_dirty_buffer(struct buffer_head *bh)
{
- return __sync_dirty_buffer(bh, WRITE_SYNC);
+ return __sync_dirty_buffer(bh, REQ_SYNC);
}
EXPORT_SYMBOL(sync_dirty_buffer);
@@ -3403,7 +3403,7 @@ void free_buffer_head(struct buffer_head *bh)
}
EXPORT_SYMBOL(free_buffer_head);
-static void buffer_exit_cpu(int cpu)
+static int buffer_exit_cpu_dead(unsigned int cpu)
{
int i;
struct bh_lru *b = &per_cpu(bh_lrus, cpu);
@@ -3414,14 +3414,7 @@ static void buffer_exit_cpu(int cpu)
}
this_cpu_add(bh_accounting.nr, per_cpu(bh_accounting, cpu).nr);
per_cpu(bh_accounting, cpu).nr = 0;
-}
-
-static int buffer_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
- buffer_exit_cpu((unsigned long)hcpu);
- return NOTIFY_OK;
+ return 0;
}
/**
@@ -3471,6 +3464,7 @@ EXPORT_SYMBOL(bh_submit_read);
void __init buffer_init(void)
{
unsigned long nrpages;
+ int ret;
bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0,
@@ -3483,5 +3477,7 @@ void __init buffer_init(void)
*/
nrpages = (nr_free_buffer_pages() * 10) / 100;
max_buffer_heads = nrpages * (PAGE_SIZE / sizeof(struct buffer_head));
- hotcpu_notifier(buffer_cpu_notify, 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_FS_BUFF_DEAD, "fs/buffer:dead",
+ NULL, buffer_exit_cpu_dead);
+ WARN_ON(ret < 0);
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4547aeddd12b..f7563c88c917 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -41,6 +41,7 @@
#include <keys/user-type.h>
#include <net/ipv6.h>
#include <linux/parser.h>
+#include <linux/bvec.h>
#include "cifspdu.h"
#include "cifsglob.h"
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 206a597b2293..5f02edc819af 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/tcp.h>
+#include <linux/bvec.h>
#include <linux/highmem.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
diff --git a/fs/dax.c b/fs/dax.c
index 014defd2e744..6916ed37d463 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -342,7 +342,7 @@ static inline void *lock_slot(struct address_space *mapping, void **slot)
radix_tree_deref_slot_protected(slot, &mapping->tree_lock);
entry |= RADIX_DAX_ENTRY_LOCK;
- radix_tree_replace_slot(slot, (void *)entry);
+ radix_tree_replace_slot(&mapping->page_tree, slot, (void *)entry);
return (void *)entry;
}
@@ -356,7 +356,7 @@ static inline void *unlock_slot(struct address_space *mapping, void **slot)
radix_tree_deref_slot_protected(slot, &mapping->tree_lock);
entry &= ~(unsigned long)RADIX_DAX_ENTRY_LOCK;
- radix_tree_replace_slot(slot, (void *)entry);
+ radix_tree_replace_slot(&mapping->page_tree, slot, (void *)entry);
return (void *)entry;
}
@@ -643,12 +643,14 @@ static void *dax_insert_mapping_entry(struct address_space *mapping,
}
mapping->nrexceptional++;
} else {
+ struct radix_tree_node *node;
void **slot;
void *ret;
- ret = __radix_tree_lookup(page_tree, index, NULL, &slot);
+ ret = __radix_tree_lookup(page_tree, index, &node, &slot);
WARN_ON_ONCE(ret != entry);
- radix_tree_replace_slot(slot, new_entry);
+ __radix_tree_replace(page_tree, node, slot,
+ new_entry, NULL, NULL);
}
if (vmf->flags & FAULT_FLAG_WRITE)
radix_tree_tag_set(page_tree, index, PAGECACHE_TAG_DIRTY);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index fb9aa16a7727..835e23a4ee4b 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -457,7 +457,7 @@ static struct bio *dio_await_one(struct dio *dio)
dio->waiter = current;
spin_unlock_irqrestore(&dio->bio_lock, flags);
if (!(dio->iocb->ki_flags & IOCB_HIPRI) ||
- !blk_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie))
+ !blk_mq_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie))
io_schedule();
/* wake up sets us TASK_RUNNING */
spin_lock_irqsave(&dio->bio_lock, flags);
@@ -1209,7 +1209,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
dio->inode = inode;
if (iov_iter_rw(iter) == WRITE) {
dio->op = REQ_OP_WRITE;
- dio->op_flags = WRITE_ODIRECT;
+ dio->op_flags = REQ_SYNC | REQ_IDLE;
} else {
dio->op = REQ_OP_READ;
}
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
index 1e6e227134d7..0643ae44f342 100644
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@ -16,11 +16,7 @@
static uint32_t dlm_nl_seqnum;
static uint32_t listener_nlportid;
-static struct genl_family family = {
- .id = GENL_ID_GENERATE,
- .name = DLM_GENL_NAME,
- .version = DLM_GENL_VERSION,
-};
+static struct genl_family family;
static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
{
@@ -76,9 +72,17 @@ static struct genl_ops dlm_nl_ops[] = {
},
};
+static struct genl_family family __ro_after_init = {
+ .name = DLM_GENL_NAME,
+ .version = DLM_GENL_VERSION,
+ .ops = dlm_nl_ops,
+ .n_ops = ARRAY_SIZE(dlm_nl_ops),
+ .module = THIS_MODULE,
+};
+
int __init dlm_netlink_init(void)
{
- return genl_register_family_with_ops(&family, dlm_nl_ops);
+ return genl_register_family(&family);
}
void dlm_netlink_exit(void)
diff --git a/fs/exec.c b/fs/exec.c
index 4e497b9ee71e..923c57d96899 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1169,8 +1169,10 @@ no_thread_group:
/* we have changed execution domain */
tsk->exit_signal = SIGCHLD;
+#ifdef CONFIG_POSIX_TIMERS
exit_itimers(sig);
flush_itimer_signals();
+#endif
if (atomic_read(&oldsighand->count) != 1) {
struct sighand_struct *newsighand;
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
index d89754ef1aab..eb9835638680 100644
--- a/fs/ext4/mmp.c
+++ b/fs/ext4/mmp.c
@@ -35,7 +35,7 @@ static void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp)
}
/*
- * Write the MMP block using WRITE_SYNC to try to get the block on-disk
+ * Write the MMP block using REQ_SYNC to try to get the block on-disk
* faster.
*/
static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
@@ -52,7 +52,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
lock_buffer(bh);
bh->b_end_io = end_buffer_write_sync;
get_bh(bh);
- submit_bh(REQ_OP_WRITE, WRITE_SYNC | REQ_META | REQ_PRIO, bh);
+ submit_bh(REQ_OP_WRITE, REQ_SYNC | REQ_META | REQ_PRIO, bh);
wait_on_buffer(bh);
sb_end_write(sb);
if (unlikely(!buffer_uptodate(bh)))
@@ -88,7 +88,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
get_bh(*bh);
lock_buffer(*bh);
(*bh)->b_end_io = end_buffer_read_sync;
- submit_bh(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, *bh);
+ submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, *bh);
wait_on_buffer(*bh);
if (!buffer_uptodate(*bh)) {
ret = -EIO;
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 0094923e5ebf..e0b3b54cdef3 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -340,7 +340,7 @@ void ext4_io_submit(struct ext4_io_submit *io)
if (bio) {
int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ?
- WRITE_SYNC : 0;
+ REQ_SYNC : 0;
bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags);
submit_bio(io->io_bio);
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 52b0530c5d65..caa4147cda47 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4569,7 +4569,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
unlock_buffer(sbh);
if (sync) {
error = __sync_dirty_buffer(sbh,
- test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC);
+ test_opt(sb, BARRIER) ? REQ_FUA : REQ_SYNC);
if (error)
return error;
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 7e9b504bd8b2..d935c06a84f0 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -65,7 +65,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
.sbi = sbi,
.type = META,
.op = REQ_OP_READ,
- .op_flags = READ_SYNC | REQ_META | REQ_PRIO,
+ .op_flags = REQ_META | REQ_PRIO,
.old_blkaddr = index,
.new_blkaddr = index,
.encrypted_page = NULL,
@@ -160,7 +160,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
.sbi = sbi,
.type = META,
.op = REQ_OP_READ,
- .op_flags = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : REQ_RAHEAD,
+ .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
.encrypted_page = NULL,
};
struct blk_plug plug;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9ae194fd2fdb..9e5561fa4cb6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -198,11 +198,9 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
if (type >= META_FLUSH) {
io->fio.type = META_FLUSH;
io->fio.op = REQ_OP_WRITE;
- if (test_opt(sbi, NOBARRIER))
- io->fio.op_flags = WRITE_FLUSH | REQ_META | REQ_PRIO;
- else
- io->fio.op_flags = WRITE_FLUSH_FUA | REQ_META |
- REQ_PRIO;
+ io->fio.op_flags = REQ_PREFLUSH | REQ_META | REQ_PRIO;
+ if (!test_opt(sbi, NOBARRIER))
+ io->fio.op_flags |= REQ_FUA;
}
__submit_merged_bio(io);
out:
@@ -483,7 +481,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
return page;
f2fs_put_page(page, 0);
- page = get_read_data_page(inode, index, READ_SYNC, false);
+ page = get_read_data_page(inode, index, 0, false);
if (IS_ERR(page))
return page;
@@ -509,7 +507,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index,
struct address_space *mapping = inode->i_mapping;
struct page *page;
repeat:
- page = get_read_data_page(inode, index, READ_SYNC, for_write);
+ page = get_read_data_page(inode, index, 0, for_write);
if (IS_ERR(page))
return page;
@@ -1251,7 +1249,7 @@ static int f2fs_write_data_page(struct page *page,
.sbi = sbi,
.type = DATA,
.op = REQ_OP_WRITE,
- .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
+ .op_flags = wbc_to_write_flags(wbc),
.page = page,
.encrypted_page = NULL,
};
@@ -1663,7 +1661,7 @@ repeat:
err = PTR_ERR(bio);
goto fail;
}
- bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC);
+ bio->bi_opf = REQ_OP_READ;
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
bio_put(bio);
err = -EFAULT;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9e8de18a168a..2cf4f7f09e32 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -688,7 +688,7 @@ struct f2fs_io_info {
struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
int op; /* contains REQ_OP_ */
- int op_flags; /* rq_flag_bits */
+ int op_flags; /* req_flag_bits */
block_t new_blkaddr; /* new block address to be written */
block_t old_blkaddr; /* old block address before Cow */
struct page *page; /* page to be written */
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6f14ee923acd..fcca12b97a2a 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -550,7 +550,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
.sbi = F2FS_I_SB(inode),
.type = DATA,
.op = REQ_OP_READ,
- .op_flags = READ_SYNC,
+ .op_flags = 0,
.encrypted_page = NULL,
};
struct dnode_of_data dn;
@@ -625,7 +625,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
fio.op = REQ_OP_WRITE;
- fio.op_flags = WRITE_SYNC;
+ fio.op_flags = REQ_SYNC;
fio.new_blkaddr = newaddr;
f2fs_submit_page_mbio(&fio);
@@ -663,7 +663,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
.sbi = F2FS_I_SB(inode),
.type = DATA,
.op = REQ_OP_WRITE,
- .op_flags = WRITE_SYNC,
+ .op_flags = REQ_SYNC,
.page = page,
.encrypted_page = NULL,
};
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 5f1a67f756af..2e7f54c191b4 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -111,7 +111,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
.sbi = F2FS_I_SB(dn->inode),
.type = DATA,
.op = REQ_OP_WRITE,
- .op_flags = WRITE_SYNC | REQ_PRIO,
+ .op_flags = REQ_SYNC | REQ_PRIO,
.page = page,
.encrypted_page = NULL,
};
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 01177ecdeab8..d1e29deb4598 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1134,7 +1134,7 @@ repeat:
if (!page)
return ERR_PTR(-ENOMEM);
- err = read_node_page(page, READ_SYNC);
+ err = read_node_page(page, 0);
if (err < 0) {
f2fs_put_page(page, 1);
return ERR_PTR(err);
@@ -1570,7 +1570,7 @@ static int f2fs_write_node_page(struct page *page,
.sbi = sbi,
.type = NODE,
.op = REQ_OP_WRITE,
- .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
+ .op_flags = wbc_to_write_flags(wbc),
.page = page,
.encrypted_page = NULL,
};
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index fc886f008449..f1b4a1775ebe 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -259,7 +259,7 @@ static int __commit_inmem_pages(struct inode *inode,
.sbi = sbi,
.type = DATA,
.op = REQ_OP_WRITE,
- .op_flags = WRITE_SYNC | REQ_PRIO,
+ .op_flags = REQ_SYNC | REQ_PRIO,
.encrypted_page = NULL,
};
bool submit_bio = false;
@@ -420,7 +420,7 @@ repeat:
fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list);
bio->bi_bdev = sbi->sb->s_bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
ret = submit_bio_wait(bio);
llist_for_each_entry_safe(cmd, next,
@@ -454,7 +454,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi)
atomic_inc(&fcc->submit_flush);
bio->bi_bdev = sbi->sb->s_bdev;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
ret = submit_bio_wait(bio);
atomic_dec(&fcc->submit_flush);
bio_put(bio);
@@ -1515,7 +1515,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
.sbi = sbi,
.type = META,
.op = REQ_OP_WRITE,
- .op_flags = WRITE_SYNC | REQ_META | REQ_PRIO,
+ .op_flags = REQ_SYNC | REQ_META | REQ_PRIO,
.old_blkaddr = page->index,
.new_blkaddr = page->index,
.page = page,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 6132b4ce4e4c..2cac6bb86080 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1238,7 +1238,7 @@ static int __f2fs_commit_super(struct buffer_head *bh,
unlock_buffer(bh);
/* it's rare case, we can do fua all the time */
- return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA);
+ return __sync_dirty_buffer(bh, REQ_PREFLUSH | REQ_FUA);
}
static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi,
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 05713a5da083..ef600591d96f 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1769,15 +1769,13 @@ static long wb_writeback(struct bdi_writeback *wb,
* become available for writeback. Otherwise
* we'll just busyloop.
*/
- if (!list_empty(&wb->b_more_io)) {
- trace_writeback_wait(wb, work);
- inode = wb_inode(wb->b_more_io.prev);
- spin_lock(&inode->i_lock);
- spin_unlock(&wb->list_lock);
- /* This function drops i_lock... */
- inode_sleep_on_writeback(inode);
- spin_lock(&wb->list_lock);
- }
+ trace_writeback_wait(wb, work);
+ inode = wb_inode(wb->b_more_io.prev);
+ spin_lock(&inode->i_lock);
+ spin_unlock(&wb->list_lock);
+ /* This function drops i_lock... */
+ inode_sleep_on_writeback(inode);
+ spin_lock(&wb->list_lock);
}
spin_unlock(&wb->list_lock);
blk_finish_plug(&plug);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 3cdde5f5d399..79113219be5f 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -62,6 +62,7 @@
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <linux/vmalloc.h>
+#include <linux/bio.h>
#include "gfs2.h"
#include "incore.h"
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index e58ccef09c91..27c00a16def0 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -657,7 +657,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
struct gfs2_log_header *lh;
unsigned int tail;
u32 hash;
- int op_flags = WRITE_FLUSH_FUA | REQ_META;
+ int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META;
struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
lh = page_address(page);
@@ -682,7 +682,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
gfs2_ordered_wait(sdp);
log_flush_wait(sdp);
- op_flags = WRITE_SYNC | REQ_META | REQ_PRIO;
+ op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
}
sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 49d5a1b61b06..b1f9144b42c7 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -231,7 +231,7 @@ static void gfs2_end_log_write(struct bio *bio)
* gfs2_log_flush_bio - Submit any pending log bio
* @sdp: The superblock
* @op: REQ_OP
- * @op_flags: rq_flag_bits
+ * @op_flags: req_flag_bits
*
* Submit any pending part-built or full bio to the block device. If
* there is no pending bio, then this is a no-op.
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 373639a59782..49db8ef13fdf 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -37,8 +37,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
{
struct buffer_head *bh, *head;
int nr_underway = 0;
- int write_flags = REQ_META | REQ_PRIO |
- (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0);
+ int write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc);
BUG_ON(!PageLocked(page));
BUG_ON(!page_has_buffers(page));
@@ -285,7 +284,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
}
}
- gfs2_submit_bhs(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, bhs, num);
+ gfs2_submit_bhs(REQ_OP_READ, REQ_META | REQ_PRIO, bhs, num);
if (!(flags & DIO_WAIT))
return 0;
@@ -453,7 +452,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
if (buffer_uptodate(first_bh))
goto out;
if (!buffer_locked(first_bh))
- ll_rw_block(REQ_OP_READ, READ_SYNC | REQ_META, 1, &first_bh);
+ ll_rw_block(REQ_OP_READ, REQ_META, 1, &first_bh);
dblock++;
extlen--;
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index ff72ac6439c8..a34308df927f 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -246,7 +246,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
bio->bi_end_io = end_bio_io_page;
bio->bi_private = page;
- bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC | REQ_META);
+ bio_set_op_attrs(bio, REQ_OP_READ, REQ_META);
submit_bio(bio);
wait_on_page_locked(page);
bio_put(bio);
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 11854dd84572..67aedf4c2e7c 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -221,7 +221,7 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
error2 = hfsplus_submit_bio(sb,
sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
sbi->s_vhdr_buf, NULL, REQ_OP_WRITE,
- WRITE_SYNC);
+ REQ_SYNC);
if (!error)
error = error2;
if (!write_backup)
@@ -230,7 +230,7 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
error2 = hfsplus_submit_bio(sb,
sbi->part_start + sbi->sect_count - 2,
sbi->s_backup_vhdr_buf, NULL, REQ_OP_WRITE,
- WRITE_SYNC);
+ REQ_SYNC);
if (!error)
error2 = error;
out:
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 44af14b2e916..9bb2fe35799d 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/bio.h>
#include <linux/vmalloc.h>
#include <linux/zlib.h>
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 684996c8a3a4..4055f51617ef 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -186,7 +186,7 @@ __flush_batch(journal_t *journal, int *batch_count)
blk_start_plug(&plug);
for (i = 0; i < *batch_count; i++)
- write_dirty_buffer(journal->j_chkpt_bhs[i], WRITE_SYNC);
+ write_dirty_buffer(journal->j_chkpt_bhs[i], REQ_SYNC);
blk_finish_plug(&plug);
for (i = 0; i < *batch_count; i++) {
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 31f8ca046639..8c514367ba5a 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -155,9 +155,10 @@ static int journal_submit_commit_record(journal_t *journal,
if (journal->j_flags & JBD2_BARRIER &&
!jbd2_has_feature_async_commit(journal))
- ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC | WRITE_FLUSH_FUA, bh);
+ ret = submit_bh(REQ_OP_WRITE,
+ REQ_SYNC | REQ_PREFLUSH | REQ_FUA, bh);
else
- ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh);
+ ret = submit_bh(REQ_OP_WRITE, REQ_SYNC, bh);
*cbh = bh;
return ret;
@@ -402,7 +403,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
jbd2_journal_update_sb_log_tail(journal,
journal->j_tail_sequence,
journal->j_tail,
- WRITE_SYNC);
+ REQ_SYNC);
mutex_unlock(&journal->j_checkpoint_mutex);
} else {
jbd_debug(3, "superblock not updated\n");
@@ -717,7 +718,7 @@ start_journal_io:
clear_buffer_dirty(bh);
set_buffer_uptodate(bh);
bh->b_end_io = journal_end_buffer_io_sync;
- submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh);
+ submit_bh(REQ_OP_WRITE, REQ_SYNC, bh);
}
cond_resched();
stats.run.rs_blocks_logged += bufs;
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 927da4956a89..8ed971eeab44 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -913,7 +913,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
* space and if we lose sb update during power failure we'd replay
* old transaction with possibly newly overwritten data.
*/
- ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA);
+ ret = jbd2_journal_update_sb_log_tail(journal, tid, block, REQ_FUA);
if (ret)
goto out;
@@ -1306,7 +1306,7 @@ static int journal_reset(journal_t *journal)
/* Lock here to make assertions happy... */
mutex_lock(&journal->j_checkpoint_mutex);
/*
- * Update log tail information. We use WRITE_FUA since new
+ * Update log tail information. We use REQ_FUA since new
* transaction will start reusing journal space and so we
* must make sure information about current log tail is on
* disk before that.
@@ -1314,7 +1314,7 @@ static int journal_reset(journal_t *journal)
jbd2_journal_update_sb_log_tail(journal,
journal->j_tail_sequence,
journal->j_tail,
- WRITE_FUA);
+ REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex);
}
return jbd2_journal_start_thread(journal);
@@ -1454,7 +1454,7 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
sb->s_errno = cpu_to_be32(journal->j_errno);
read_unlock(&journal->j_state_lock);
- jbd2_write_superblock(journal, WRITE_FUA);
+ jbd2_write_superblock(journal, REQ_FUA);
}
EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
@@ -1720,7 +1720,8 @@ int jbd2_journal_destroy(journal_t *journal)
++journal->j_transaction_sequence;
write_unlock(&journal->j_state_lock);
- jbd2_mark_journal_empty(journal, WRITE_FLUSH_FUA);
+ jbd2_mark_journal_empty(journal,
+ REQ_PREFLUSH | REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex);
} else
err = -EIO;
@@ -1979,7 +1980,7 @@ int jbd2_journal_flush(journal_t *journal)
* the magic code for a fully-recovered superblock. Any future
* commits of data to the journal will restore the current
* s_start value. */
- jbd2_mark_journal_empty(journal, WRITE_FUA);
+ jbd2_mark_journal_empty(journal, REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex);
write_lock(&journal->j_state_lock);
J_ASSERT(!journal->j_running_transaction);
@@ -2025,7 +2026,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
if (write) {
/* Lock to make assertions happy... */
mutex_lock(&journal->j_checkpoint_mutex);
- jbd2_mark_journal_empty(journal, WRITE_FUA);
+ jbd2_mark_journal_empty(journal, REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex);
}
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 91171dc352cb..cfc38b552118 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -648,7 +648,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(descriptor);
BUFFER_TRACE(descriptor, "write");
set_buffer_dirty(descriptor);
- write_dirty_buffer(descriptor, WRITE_SYNC);
+ write_dirty_buffer(descriptor, REQ_SYNC);
}
#endif
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index a21ea8b3e5fa..bb1da1feafeb 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -2002,7 +2002,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
bio->bi_end_io = lbmIODone;
bio->bi_private = bp;
- bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC);
+ bio->bi_opf = REQ_OP_READ;
/*check if journaling to disk has been disabled*/
if (log->no_integrity) {
bio->bi_iter.bi_size = 0;
@@ -2146,7 +2146,7 @@ static void lbmStartIO(struct lbuf * bp)
bio->bi_end_io = lbmIODone;
bio->bi_private = bp;
- bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC);
+ bio->bi_opf = REQ_OP_WRITE | REQ_SYNC;
/* check if journaling to disk has been disabled */
if (log->no_integrity) {
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h
index 5426189406c1..fb8cac88251a 100644
--- a/fs/lockd/netns.h
+++ b/fs/lockd/netns.h
@@ -15,6 +15,6 @@ struct lockd_net {
struct list_head nsm_handles;
};
-extern int lockd_net_id;
+extern unsigned int lockd_net_id;
#endif
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index fc4084ef4736..1c13dd80744f 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -57,7 +57,7 @@ static struct task_struct *nlmsvc_task;
static struct svc_rqst *nlmsvc_rqst;
unsigned long nlmsvc_timeout;
-int lockd_net_id;
+unsigned int lockd_net_id;
/*
* These can be set at insmod time (useful for NFS as root filesystem),
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index a8329cc47dec..9bfa0151d7c9 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -19,16 +19,10 @@ static int sync_request(struct page *page, struct block_device *bdev, int op)
struct bio bio;
struct bio_vec bio_vec;
- bio_init(&bio);
- bio.bi_max_vecs = 1;
- bio.bi_io_vec = &bio_vec;
- bio_vec.bv_page = page;
- bio_vec.bv_len = PAGE_SIZE;
- bio_vec.bv_offset = 0;
- bio.bi_vcnt = 1;
+ bio_init(&bio, &bio_vec, 1);
bio.bi_bdev = bdev;
+ bio_add_page(&bio, page, PAGE_SIZE, 0);
bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9);
- bio.bi_iter.bi_size = PAGE_SIZE;
bio_set_op_attrs(&bio, op, 0);
return submit_bio_wait(&bio);
@@ -77,56 +71,45 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
{
struct logfs_super *super = logfs_super(sb);
struct address_space *mapping = super->s_mapping_inode->i_mapping;
- struct bio *bio;
+ struct bio *bio = NULL;
struct page *page;
unsigned int max_pages;
- int i;
+ int i, ret;
max_pages = min_t(size_t, nr_pages, BIO_MAX_PAGES);
- bio = bio_alloc(GFP_NOFS, max_pages);
- BUG_ON(!bio);
-
for (i = 0; i < nr_pages; i++) {
- if (i >= max_pages) {
- /* Block layer cannot split bios :( */
- bio->bi_vcnt = i;
- bio->bi_iter.bi_size = i * PAGE_SIZE;
+ if (!bio) {
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio);
+
bio->bi_bdev = super->s_bdev;
bio->bi_iter.bi_sector = ofs >> 9;
bio->bi_private = sb;
bio->bi_end_io = writeseg_end_io;
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
- atomic_inc(&super->s_pending_writes);
- submit_bio(bio);
-
- ofs += i * PAGE_SIZE;
- index += i;
- nr_pages -= i;
- i = 0;
-
- bio = bio_alloc(GFP_NOFS, max_pages);
- BUG_ON(!bio);
}
page = find_lock_page(mapping, index + i);
BUG_ON(!page);
- bio->bi_io_vec[i].bv_page = page;
- bio->bi_io_vec[i].bv_len = PAGE_SIZE;
- bio->bi_io_vec[i].bv_offset = 0;
+ ret = bio_add_page(bio, page, PAGE_SIZE, 0);
BUG_ON(PageWriteback(page));
set_page_writeback(page);
unlock_page(page);
+
+ if (!ret) {
+ /* Block layer cannot split bios :( */
+ ofs += bio->bi_iter.bi_size;
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(bio);
+ bio = NULL;
+ }
+ }
+
+ if (bio) {
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(bio);
}
- bio->bi_vcnt = nr_pages;
- bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;
- bio->bi_bdev = super->s_bdev;
- bio->bi_iter.bi_sector = ofs >> 9;
- bio->bi_private = sb;
- bio->bi_end_io = writeseg_end_io;
- bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
- atomic_inc(&super->s_pending_writes);
- submit_bio(bio);
return 0;
}
@@ -160,7 +143,6 @@ static void erase_end_io(struct bio *bio)
struct logfs_super *super = logfs_super(sb);
BUG_ON(bio->bi_error); /* FIXME: Retry io or write elsewhere */
- BUG_ON(bio->bi_vcnt == 0);
bio_put(bio);
if (atomic_dec_and_test(&super->s_pending_writes))
wake_up(&wq);
@@ -170,49 +152,35 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
size_t nr_pages)
{
struct logfs_super *super = logfs_super(sb);
- struct bio *bio;
+ struct bio *bio = NULL;
unsigned int max_pages;
- int i;
+ int i, ret;
max_pages = min_t(size_t, nr_pages, BIO_MAX_PAGES);
- bio = bio_alloc(GFP_NOFS, max_pages);
- BUG_ON(!bio);
-
for (i = 0; i < nr_pages; i++) {
- if (i >= max_pages) {
- /* Block layer cannot split bios :( */
- bio->bi_vcnt = i;
- bio->bi_iter.bi_size = i * PAGE_SIZE;
+ if (!bio) {
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio);
+
bio->bi_bdev = super->s_bdev;
bio->bi_iter.bi_sector = ofs >> 9;
bio->bi_private = sb;
bio->bi_end_io = erase_end_io;
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+ }
+ ret = bio_add_page(bio, super->s_erase_page, PAGE_SIZE, 0);
+ if (!ret) {
+ /* Block layer cannot split bios :( */
+ ofs += bio->bi_iter.bi_size;
atomic_inc(&super->s_pending_writes);
submit_bio(bio);
-
- ofs += i * PAGE_SIZE;
- index += i;
- nr_pages -= i;
- i = 0;
-
- bio = bio_alloc(GFP_NOFS, max_pages);
- BUG_ON(!bio);
}
- bio->bi_io_vec[i].bv_page = super->s_erase_page;
- bio->bi_io_vec[i].bv_len = PAGE_SIZE;
- bio->bi_io_vec[i].bv_offset = 0;
}
- bio->bi_vcnt = nr_pages;
- bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;
- bio->bi_bdev = super->s_bdev;
- bio->bi_iter.bi_sector = ofs >> 9;
- bio->bi_private = sb;
- bio->bi_end_io = erase_end_io;
- bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
- atomic_inc(&super->s_pending_writes);
- submit_bio(bio);
+ if (bio) {
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(bio);
+ }
return 0;
}
diff --git a/fs/mpage.c b/fs/mpage.c
index d2413af0823a..98fc11aa7e0b 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -489,7 +489,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
struct buffer_head map_bh;
loff_t i_size = i_size_read(inode);
int ret = 0;
- int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0);
+ int op_flags = wbc_to_write_flags(wbc);
if (page_has_buffers(page)) {
struct buffer_head *head = page_buffers(page);
@@ -705,7 +705,7 @@ mpage_writepages(struct address_space *mapping,
ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd);
if (mpd.bio) {
int op_flags = (wbc->sync_mode == WB_SYNC_ALL ?
- WRITE_SYNC : 0);
+ REQ_SYNC : 0);
mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio);
}
}
@@ -726,7 +726,7 @@ int mpage_writepage(struct page *page, get_block_t get_block,
int ret = __mpage_writepage(page, wbc, &mpd);
if (mpd.bio) {
int op_flags = (wbc->sync_mode == WB_SYNC_ALL ?
- WRITE_SYNC : 0);
+ REQ_SYNC : 0);
mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio);
}
return ret;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bf4ec5ecc97e..ce42dd00e4ee 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2015,7 +2015,7 @@ static void nfsiod_stop(void)
destroy_workqueue(wq);
}
-int nfs_net_id;
+unsigned int nfs_net_id;
EXPORT_SYMBOL_GPL(nfs_net_id);
static int nfs_net_init(struct net *net)
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h
index fbce0d885d4c..5fbd2bde91ba 100644
--- a/fs/nfs/netns.h
+++ b/fs/nfs/netns.h
@@ -35,6 +35,6 @@ struct nfs_net {
#endif
};
-extern int nfs_net_id;
+extern unsigned int nfs_net_id;
#endif
diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c
index fd8c9a5bcac4..420d3a0ab258 100644
--- a/fs/nfs_common/grace.c
+++ b/fs/nfs_common/grace.c
@@ -9,7 +9,7 @@
#include <net/netns/generic.h>
#include <linux/fs.h>
-static int grace_net_id;
+static unsigned int grace_net_id;
static DEFINE_SPINLOCK(grace_lock);
/**
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index ee36efd5aece..3714231a9d0f 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -124,5 +124,5 @@ struct nfsd_net {
/* Simple check to find out if a given net was properly initialized */
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
-extern int nfsd_net_id;
+extern unsigned int nfsd_net_id;
#endif /* __NFSD_NETNS_H__ */
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 36b2af931e06..2857e46d5cc5 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1201,7 +1201,7 @@ static int create_proc_exports_entry(void)
}
#endif
-int nfsd_net_id;
+unsigned int nfsd_net_id;
static __net_init int nfsd_init_net(struct net *net)
{
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index c95d369e90aa..12eeae62a2b1 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -189,7 +189,7 @@ static int nilfs_sync_super(struct super_block *sb, int flag)
set_buffer_dirty(nilfs->ns_sbh[0]);
if (nilfs_test_opt(nilfs, BARRIER)) {
err = __sync_dirty_buffer(nilfs->ns_sbh[0],
- WRITE_SYNC | WRITE_FLUSH_FUA);
+ REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
} else {
err = sync_dirty_buffer(nilfs->ns_sbh[0]);
}
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 8718af895eab..8c9fb29c6673 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -118,7 +118,7 @@ again:
return ret;
}
-static int open_related_ns(struct ns_common *ns,
+int open_related_ns(struct ns_common *ns,
struct ns_common *(*get_ns)(struct ns_common *ns))
{
struct path path = {};
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index fe251f187ff8..d0cf6fee5c77 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -29,6 +29,7 @@
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/bit_spinlock.h>
+#include <linux/bio.h>
#include "aops.h"
#include "attrib.h"
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 761f12f7f3ef..353379ff6057 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -27,6 +27,7 @@
#include <linux/buffer_head.h>
#include <linux/bitops.h>
#include <linux/log2.h>
+#include <linux/bio.h>
#include "attrib.h"
#include "aops.h"
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index d3c009626032..b6f402194f02 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -23,6 +23,7 @@
#include <linux/buffer_head.h>
#include <linux/slab.h>
#include <linux/swap.h>
+#include <linux/bio.h>
#include "attrib.h"
#include "aops.h"
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index c5c5b9748ea3..9a88984f9f6f 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -1950,8 +1950,7 @@ static void ocfs2_write_end_inline(struct inode *inode, loff_t pos,
}
int ocfs2_write_end_nolock(struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
+ loff_t pos, unsigned len, unsigned copied, void *fsdata)
{
int i, ret;
unsigned from, to, start = pos & (PAGE_SIZE - 1);
@@ -2064,7 +2063,7 @@ static int ocfs2_write_end(struct file *file, struct address_space *mapping,
int ret;
struct inode *inode = mapping->host;
- ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
+ ret = ocfs2_write_end_nolock(mapping, pos, len, copied, fsdata);
up_write(&OCFS2_I(inode)->ip_alloc_sem);
ocfs2_inode_unlock(inode, 1);
@@ -2241,7 +2240,7 @@ static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock,
dwc->dw_zero_count++;
}
- ret = ocfs2_write_end_nolock(inode->i_mapping, pos, len, len, NULL, wc);
+ ret = ocfs2_write_end_nolock(inode->i_mapping, pos, len, len, wc);
BUG_ON(ret != len);
ret = 0;
unlock:
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index b1c9f28a57b1..8614ff069d99 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -44,8 +44,7 @@ int walk_page_buffers( handle_t *handle,
struct buffer_head *bh));
int ocfs2_write_end_nolock(struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata);
+ loff_t pos, unsigned len, unsigned copied, void *fsdata);
typedef enum {
OCFS2_WRITE_BUFFER = 0,
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index 8f040f88ade4..d9ebe11c8990 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -26,6 +26,7 @@
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/highmem.h>
+#include <linux/bio.h>
#include <cluster/masklog.h>
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 636abcbd4650..96a155ab5059 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -627,7 +627,7 @@ static int o2hb_issue_node_write(struct o2hb_region *reg,
slot = o2nm_this_node();
bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1, REQ_OP_WRITE,
- WRITE_SYNC);
+ REQ_SYNC);
if (IS_ERR(bio)) {
status = PTR_ERR(bio);
mlog_errno(status);
@@ -741,7 +741,7 @@ static inline void o2hb_prepare_block(struct o2hb_region *reg,
hb_block = (struct o2hb_disk_heartbeat_block *)slot->ds_raw_block;
memset(hb_block, 0, reg->hr_block_bytes);
/* TODO: time stuff */
- cputime = CURRENT_TIME.tv_sec;
+ cputime = ktime_get_real_seconds();
if (!cputime)
cputime = 1;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 3f828a187049..a464c8088170 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1609,8 +1609,6 @@ way_up_top:
__dlm_insert_mle(dlm, mle);
response = DLM_MASTER_RESP_NO;
} else {
- // mlog(0, "mle was found\n");
- set_maybe = 1;
spin_lock(&tmpmle->spinlock);
if (tmpmle->master == dlm->node_num) {
mlog(ML_ERROR, "no lockres, but an mle with this node as master!\n");
@@ -1625,8 +1623,7 @@ way_up_top:
response = DLM_MASTER_RESP_NO;
} else
response = DLM_MASTER_RESP_MAYBE;
- if (set_maybe)
- set_bit(request->node_idx, tmpmle->maybe_map);
+ set_bit(request->node_idx, tmpmle->maybe_map);
spin_unlock(&tmpmle->spinlock);
}
spin_unlock(&dlm->master_lock);
@@ -1644,12 +1641,6 @@ send_response:
* dlm_assert_master_worker() isn't called, we drop it here.
*/
if (dispatch_assert) {
- if (response != DLM_MASTER_RESP_YES)
- mlog(ML_ERROR, "invalid response %d\n", response);
- if (!res) {
- mlog(ML_ERROR, "bad lockres while trying to assert!\n");
- BUG();
- }
mlog(0, "%u is the owner of %.*s, cleaning everyone else\n",
dlm->node_num, res->lockname.len, res->lockname.name);
spin_lock(&res->spinlock);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index dd5cb8bcefd1..74407c6dd592 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -2966,8 +2966,6 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
spin_unlock(&dlm->spinlock);
dlm_kick_recovery_thread(dlm);
break;
- default:
- BUG();
}
mlog(0, "%s: recovery done, reco master was %u, dead now %u, master now %u\n",
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index c56a7679df93..382401d3e88f 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -703,7 +703,7 @@ static int ocfs2_remove_inode(struct inode *inode,
goto bail_commit;
}
- di->i_dtime = cpu_to_le64(CURRENT_TIME.tv_sec);
+ di->i_dtime = cpu_to_le64(ktime_get_real_seconds());
di->i_flags &= cpu_to_le32(~(OCFS2_VALID_FL | OCFS2_ORPHANED_FL));
ocfs2_journal_dirty(handle, di_bh);
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index a244f14c6b87..d5e5fa7f0743 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -1947,7 +1947,7 @@ static void ocfs2_queue_orphan_scan(struct ocfs2_super *osb)
*/
seqno++;
os->os_count++;
- os->os_scantime = CURRENT_TIME;
+ os->os_scantime = ktime_get_seconds();
unlock:
ocfs2_orphan_scan_unlock(osb, seqno);
out:
@@ -2004,7 +2004,7 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
struct ocfs2_orphan_scan *os;
os = &osb->osb_orphan_scan;
- os->os_scantime = CURRENT_TIME;
+ os->os_scantime = ktime_get_seconds();
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
else {
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 71545ad4628c..429088786e93 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -120,8 +120,7 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
ret = VM_FAULT_NOPAGE;
goto out;
}
- ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
- fsdata);
+ ret = ocfs2_write_end_nolock(mapping, pos, len, len, fsdata);
BUG_ON(ret != len);
ret = VM_FAULT_LOCKED;
out:
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 8d887c75765c..3b0a10d9b36f 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -516,6 +516,7 @@ static int __ocfs2_mknod_locked(struct inode *dir,
struct ocfs2_extent_list *fel;
u16 feat;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct timespec64 ts;
*new_fe_bh = NULL;
@@ -564,10 +565,11 @@ static int __ocfs2_mknod_locked(struct inode *dir,
fe->i_last_eb_blk = 0;
strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
fe->i_flags |= cpu_to_le32(OCFS2_VALID_FL);
+ ktime_get_real_ts64(&ts);
fe->i_atime = fe->i_ctime = fe->i_mtime =
- cpu_to_le64(CURRENT_TIME.tv_sec);
+ cpu_to_le64(ts.tv_sec);
fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec =
- cpu_to_le32(CURRENT_TIME.tv_nsec);
+ cpu_to_le32(ts.tv_nsec);
fe->i_dtime = 0;
/*
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index e63af7ddfe68..7e5958b0be6b 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -224,7 +224,7 @@ struct ocfs2_orphan_scan {
struct ocfs2_super *os_osb;
struct ocfs2_lock_res os_lockres; /* lock to synchronize scans */
struct delayed_work os_orphan_scan_work;
- struct timespec os_scantime; /* time this node ran the scan */
+ time64_t os_scantime; /* time this node ran the scan */
u32 os_count; /* tracks node specific scans */
u32 os_seqno; /* tracks cluster wide scans */
atomic_t os_state; /* ACTIVE or INACTIVE */
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 19238512a324..738b4ea8e990 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -478,7 +478,6 @@ again:
if (ret) {
mlog_errno(ret);
ocfs2_unlock_refcount_tree(osb, tree, rw);
- ocfs2_refcount_tree_put(tree);
goto out;
}
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index f56fe39fab04..c894d945b084 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -337,7 +337,7 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len)
out += snprintf(buf + out, len - out, "Disabled\n");
else
out += snprintf(buf + out, len - out, "%lu seconds ago\n",
- (get_seconds() - os->os_scantime.tv_sec));
+ (unsigned long)(ktime_get_seconds() - os->os_scantime));
out += snprintf(buf + out, len - out, "%10s => %3s %10s\n",
"Slots", "Num", "RecoGen");
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index ef3b4eb54cf2..551bc74ed2b8 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -8,6 +8,7 @@
* Linux VFS inode operations.
*/
+#include <linux/bvec.h>
#include "protocol.h"
#include "orangefs-kernel.h"
#include "orangefs-bufmap.h"
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 81818adb8e9e..51a4213afa2e 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -245,7 +245,7 @@ void render_sigset_t(struct seq_file *m, const char *header,
if (sigismember(set, i+2)) x |= 2;
if (sigismember(set, i+3)) x |= 4;
if (sigismember(set, i+4)) x |= 8;
- seq_printf(m, "%x", x);
+ seq_putc(m, hex_asc[x]);
} while (i >= 4);
seq_putc(m, '\n');
@@ -342,10 +342,11 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p)
static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
{
+ seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
#ifdef CONFIG_SECCOMP
- seq_put_decimal_ull(m, "Seccomp:\t", p->seccomp.mode);
- seq_putc(m, '\n');
+ seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
#endif
+ seq_putc(m, '\n');
}
static inline void task_context_switch_counts(struct seq_file *m,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ca651ac00660..9b99df4893a4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -104,9 +104,12 @@
* in /proc for a task before it execs a suid executable.
*/
+static u8 nlink_tid;
+static u8 nlink_tgid;
+
struct pid_entry {
const char *name;
- int len;
+ unsigned int len;
umode_t mode;
const struct inode_operations *iop;
const struct file_operations *fop;
@@ -139,13 +142,13 @@ struct pid_entry {
* Count the number of hardlinks for the pid_entry table, excluding the .
* and .. links.
*/
-static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
+static unsigned int __init pid_entry_nlink(const struct pid_entry *entries,
unsigned int n)
{
unsigned int i;
unsigned int count;
- count = 0;
+ count = 2;
for (i = 0; i < n; ++i) {
if (S_ISDIR(entries[i].mode))
++count;
@@ -1967,7 +1970,7 @@ out:
struct map_files_info {
fmode_t mode;
- unsigned long len;
+ unsigned int len;
unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
};
@@ -2412,14 +2415,14 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
* Yes, it does not scale. And it should not. Don't add
* new entries into /proc/<tgid>/ without very good reasons.
*/
- last = &ents[nents - 1];
- for (p = ents; p <= last; p++) {
+ last = &ents[nents];
+ for (p = ents; p < last; p++) {
if (p->len != dentry->d_name.len)
continue;
if (!memcmp(dentry->d_name.name, p->name, p->len))
break;
}
- if (p > last)
+ if (p >= last)
goto out;
error = proc_pident_instantiate(dir, dentry, task, p);
@@ -2444,7 +2447,7 @@ static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
if (ctx->pos >= nents + 2)
goto out;
- for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) {
+ for (p = ents + (ctx->pos - 2); p < ents + nents; p++) {
if (!proc_fill_cache(file, ctx, p->name, p->len,
proc_pident_instantiate, task, p))
break;
@@ -3068,8 +3071,7 @@ static int proc_pid_instantiate(struct inode *dir,
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
- set_nlink(inode, 2 + pid_entry_count_dirs(tgid_base_stuff,
- ARRAY_SIZE(tgid_base_stuff)));
+ set_nlink(inode, nlink_tgid);
d_set_d_op(dentry, &pid_dentry_operations);
@@ -3361,8 +3363,7 @@ static int proc_task_instantiate(struct inode *dir,
inode->i_fop = &proc_tid_base_operations;
inode->i_flags|=S_IMMUTABLE;
- set_nlink(inode, 2 + pid_entry_count_dirs(tid_base_stuff,
- ARRAY_SIZE(tid_base_stuff)));
+ set_nlink(inode, nlink_tid);
d_set_d_op(dentry, &pid_dentry_operations);
@@ -3552,3 +3553,9 @@ static const struct file_operations proc_task_operations = {
.iterate_shared = proc_task_readdir,
.llseek = generic_file_llseek,
};
+
+void __init set_proc_pid_nlink(void)
+{
+ nlink_tid = pid_entry_nlink(tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
+ nlink_tgid = pid_entry_nlink(tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
+}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e69ebe648a34..783bc19644d1 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -138,6 +138,16 @@ static void unuse_pde(struct proc_dir_entry *pde)
/* pde is locked */
static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
{
+ /*
+ * close() (proc_reg_release()) can't delete an entry and proceed:
+ * ->release hook needs to be available at the right moment.
+ *
+ * rmmod (remove_proc_entry() et al) can't delete an entry and proceed:
+ * "struct file" needs to be available at the right moment.
+ *
+ * Therefore, first process to enter this function does ->release() and
+ * signals its completion to the other process which does nothing.
+ */
if (pdeo->closing) {
/* somebody else is doing that, just wait */
DECLARE_COMPLETION_ONSTACK(c);
@@ -147,12 +157,13 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
spin_lock(&pde->pde_unload_lock);
} else {
struct file *file;
- pdeo->closing = 1;
+ pdeo->closing = true;
spin_unlock(&pde->pde_unload_lock);
file = pdeo->file;
pde->proc_fops->release(file_inode(file), file);
spin_lock(&pde->pde_unload_lock);
- list_del_init(&pdeo->lh);
+ /* After ->release. */
+ list_del(&pdeo->lh);
if (pdeo->c)
complete(pdeo->c);
kfree(pdeo);
@@ -167,6 +178,8 @@ void proc_entry_rundown(struct proc_dir_entry *de)
if (atomic_add_return(BIAS, &de->in_use) != BIAS)
wait_for_completion(&c);
+ /* ->pde_openers list can't grow from now on. */
+
spin_lock(&de->pde_unload_lock);
while (!list_empty(&de->pde_openers)) {
struct pde_opener *pdeo;
@@ -312,16 +325,17 @@ static int proc_reg_open(struct inode *inode, struct file *file)
struct pde_opener *pdeo;
/*
- * What for, you ask? Well, we can have open, rmmod, remove_proc_entry
- * sequence. ->release won't be called because ->proc_fops will be
- * cleared. Depending on complexity of ->release, consequences vary.
+ * Ensure that
+ * 1) PDE's ->release hook will be called no matter what
+ * either normally by close()/->release, or forcefully by
+ * rmmod/remove_proc_entry.
+ *
+ * 2) rmmod isn't blocked by opening file in /proc and sitting on
+ * the descriptor (including "rmmod foo </proc/foo" scenario).
*
- * We can't wait for mercy when close will be done for real, it's
- * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release
- * by hand in remove_proc_entry(). For this, save opener's credentials
- * for later.
+ * Save every "struct file" with custom ->release hook.
*/
- pdeo = kzalloc(sizeof(struct pde_opener), GFP_KERNEL);
+ pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL);
if (!pdeo)
return -ENOMEM;
@@ -338,7 +352,8 @@ static int proc_reg_open(struct inode *inode, struct file *file)
if (rv == 0 && release) {
/* To know what to release. */
pdeo->file = file;
- /* Strictly for "too late" ->release in proc_reg_release(). */
+ pdeo->closing = false;
+ pdeo->c = NULL;
spin_lock(&pde->pde_unload_lock);
list_add(&pdeo->lh, &pde->pde_openers);
spin_unlock(&pde->pde_unload_lock);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 5378441ec1b7..bbba5d22aada 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -203,7 +203,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name);
struct pde_opener {
struct file *file;
struct list_head lh;
- int closing;
+ bool closing;
struct completion *c;
};
extern const struct inode_operations proc_link_inode_operations;
@@ -211,6 +211,7 @@ extern const struct inode_operations proc_link_inode_operations;
extern const struct inode_operations proc_pid_link_inode_operations;
extern void proc_init_inodecache(void);
+void set_proc_pid_nlink(void);
extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
extern int proc_fill_super(struct super_block *, void *data, int flags);
extern void proc_entry_rundown(struct proc_dir_entry *);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 8d3e484055a6..4bd0373576b5 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -122,6 +122,7 @@ void __init proc_root_init(void)
int err;
proc_init_inodecache();
+ set_proc_pid_nlink();
err = register_filesystem(&proc_fs_type);
if (err)
return;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 35b92d81692f..958f32545064 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1588,6 +1588,7 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
} while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap_unlock(orig_pte, ptl);
+ cond_resched();
return 0;
}
#ifdef CONFIG_HUGETLB_PAGE
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index be40813eff52..b42e5bd6d8ff 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -86,4 +86,4 @@ config PSTORE_RAM
Note that for historical reasons, the module will be named
"ramoops.ko".
- For more information, see Documentation/ramoops.txt.
+ For more information, see Documentation/admin-guide/ramoops.rst.
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c
index d4887705bb61..899d0ba0bd6c 100644
--- a/fs/pstore/ftrace.c
+++ b/fs/pstore/ftrace.c
@@ -27,6 +27,9 @@
#include <asm/barrier.h>
#include "internal.h"
+/* This doesn't need to be atomic: speed is chosen over correctness here. */
+static u64 pstore_ftrace_stamp;
+
static void notrace pstore_ftrace_call(unsigned long ip,
unsigned long parent_ip,
struct ftrace_ops *op,
@@ -42,6 +45,7 @@ static void notrace pstore_ftrace_call(unsigned long ip,
rec.ip = ip;
rec.parent_ip = parent_ip;
+ pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec,
0, sizeof(rec), psinfo);
@@ -71,10 +75,13 @@ static ssize_t pstore_ftrace_knob_write(struct file *f, const char __user *buf,
if (!on ^ pstore_ftrace_enabled)
goto out;
- if (on)
+ if (on) {
+ ftrace_ops_set_global_filter(&pstore_ftrace_ops);
ret = register_ftrace_function(&pstore_ftrace_ops);
- else
+ } else {
ret = unregister_ftrace_function(&pstore_ftrace_ops);
+ }
+
if (ret) {
pr_err("%s: unable to %sregister ftrace ops: %zd\n",
__func__, on ? "" : "un", ret);
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 1781dc50762e..57c0646479f5 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -107,9 +107,11 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
struct pstore_ftrace_seq_data *data = v;
struct pstore_ftrace_record *rec = (void *)(ps->data + data->off);
- seq_printf(s, "%d %08lx %08lx %pf <- %pF\n",
- pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip,
- (void *)rec->ip, (void *)rec->parent_ip);
+ seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %pf <- %pF\n",
+ pstore_ftrace_decode_cpu(rec),
+ pstore_ftrace_read_timestamp(rec),
+ rec->ip, rec->parent_ip, (void *)rec->ip,
+ (void *)rec->parent_ip);
return 0;
}
@@ -197,11 +199,14 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
if (err)
return err;
- if (p->psi->erase)
+ if (p->psi->erase) {
+ mutex_lock(&p->psi->read_mutex);
p->psi->erase(p->type, p->id, p->count,
d_inode(dentry)->i_ctime, p->psi);
- else
+ mutex_unlock(&p->psi->read_mutex);
+ } else {
return -EPERM;
+ }
return simple_unlink(dir, dentry);
}
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index e38a22b31282..da416e6591c9 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -5,40 +5,6 @@
#include <linux/time.h>
#include <linux/pstore.h>
-#if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB)
-#define PSTORE_CPU_IN_IP 0x1
-#elif NR_CPUS <= 4 && defined(CONFIG_ARM)
-#define PSTORE_CPU_IN_IP 0x3
-#endif
-
-struct pstore_ftrace_record {
- unsigned long ip;
- unsigned long parent_ip;
-#ifndef PSTORE_CPU_IN_IP
- unsigned int cpu;
-#endif
-};
-
-static inline void
-pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
-{
-#ifndef PSTORE_CPU_IN_IP
- rec->cpu = cpu;
-#else
- rec->ip |= cpu;
-#endif
-}
-
-static inline unsigned int
-pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
-{
-#ifndef PSTORE_CPU_IN_IP
- return rec->cpu;
-#else
- return rec->ip & PSTORE_CPU_IN_IP;
-#endif
-}
-
#ifdef CONFIG_PSTORE_FTRACE
extern void pstore_register_ftrace(void);
extern void pstore_unregister_ftrace(void);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 14984d902a99..729677e18e36 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -493,6 +493,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
if (!is_locked) {
pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
, in_nmi() ? "NMI" : why);
+ return;
}
} else {
spin_lock_irqsave(&psinfo->buf_lock, flags);
@@ -584,8 +585,8 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
} else {
spin_lock_irqsave(&psinfo->buf_lock, flags);
}
- memcpy(psinfo->buf, s, c);
- psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, 0, c, psinfo);
+ psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
+ s, 0, c, psinfo);
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
s += c;
c = e - s;
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 6ad831b9d1b8..27c059e1760a 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -85,10 +85,10 @@ MODULE_PARM_DESC(ramoops_ecc,
"bytes ECC)");
struct ramoops_context {
- struct persistent_ram_zone **przs;
- struct persistent_ram_zone *cprz;
- struct persistent_ram_zone *fprz;
- struct persistent_ram_zone *mprz;
+ struct persistent_ram_zone **dprzs; /* Oops dump zones */
+ struct persistent_ram_zone *cprz; /* Console zone */
+ struct persistent_ram_zone **fprzs; /* Ftrace zones */
+ struct persistent_ram_zone *mprz; /* PMSG zone */
phys_addr_t phys_addr;
unsigned long size;
unsigned int memtype;
@@ -97,12 +97,14 @@ struct ramoops_context {
size_t ftrace_size;
size_t pmsg_size;
int dump_oops;
+ u32 flags;
struct persistent_ram_ecc_info ecc_info;
unsigned int max_dump_cnt;
unsigned int dump_write_cnt;
/* _read_cnt need clear on ramoops_pstore_open */
unsigned int dump_read_cnt;
unsigned int console_read_cnt;
+ unsigned int max_ftrace_cnt;
unsigned int ftrace_read_cnt;
unsigned int pmsg_read_cnt;
struct pstore_info pstore;
@@ -180,16 +182,69 @@ static bool prz_ok(struct persistent_ram_zone *prz)
persistent_ram_ecc_string(prz, NULL, 0));
}
+static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest,
+ struct persistent_ram_zone *src)
+{
+ size_t dest_size, src_size, total, dest_off, src_off;
+ size_t dest_idx = 0, src_idx = 0, merged_idx = 0;
+ void *merged_buf;
+ struct pstore_ftrace_record *drec, *srec, *mrec;
+ size_t record_size = sizeof(struct pstore_ftrace_record);
+
+ dest_off = dest->old_log_size % record_size;
+ dest_size = dest->old_log_size - dest_off;
+
+ src_off = src->old_log_size % record_size;
+ src_size = src->old_log_size - src_off;
+
+ total = dest_size + src_size;
+ merged_buf = kmalloc(total, GFP_KERNEL);
+ if (!merged_buf)
+ return -ENOMEM;
+
+ drec = (struct pstore_ftrace_record *)(dest->old_log + dest_off);
+ srec = (struct pstore_ftrace_record *)(src->old_log + src_off);
+ mrec = (struct pstore_ftrace_record *)(merged_buf);
+
+ while (dest_size > 0 && src_size > 0) {
+ if (pstore_ftrace_read_timestamp(&drec[dest_idx]) <
+ pstore_ftrace_read_timestamp(&srec[src_idx])) {
+ mrec[merged_idx++] = drec[dest_idx++];
+ dest_size -= record_size;
+ } else {
+ mrec[merged_idx++] = srec[src_idx++];
+ src_size -= record_size;
+ }
+ }
+
+ while (dest_size > 0) {
+ mrec[merged_idx++] = drec[dest_idx++];
+ dest_size -= record_size;
+ }
+
+ while (src_size > 0) {
+ mrec[merged_idx++] = srec[src_idx++];
+ src_size -= record_size;
+ }
+
+ kfree(dest->old_log);
+ dest->old_log = merged_buf;
+ dest->old_log_size = total;
+
+ return 0;
+}
+
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
int *count, struct timespec *time,
char **buf, bool *compressed,
ssize_t *ecc_notice_size,
struct pstore_info *psi)
{
- ssize_t size;
+ ssize_t size = 0;
struct ramoops_context *cxt = psi->data;
struct persistent_ram_zone *prz = NULL;
int header_length = 0;
+ bool free_prz = false;
/* Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but
* PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have
@@ -201,7 +256,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
/* Find the next valid persistent_ram_zone for DMESG */
while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) {
- prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
+ prz = ramoops_get_next_prz(cxt->dprzs, &cxt->dump_read_cnt,
cxt->max_dump_cnt, id, type,
PSTORE_TYPE_DMESG, 1);
if (!prz_ok(prz))
@@ -219,14 +274,56 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
if (!prz_ok(prz))
prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt,
1, id, type, PSTORE_TYPE_CONSOLE, 0);
- if (!prz_ok(prz))
- prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt,
- 1, id, type, PSTORE_TYPE_FTRACE, 0);
+
if (!prz_ok(prz))
prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt,
1, id, type, PSTORE_TYPE_PMSG, 0);
- if (!prz_ok(prz))
- return 0;
+
+ /* ftrace is last since it may want to dynamically allocate memory. */
+ if (!prz_ok(prz)) {
+ if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) {
+ prz = ramoops_get_next_prz(cxt->fprzs,
+ &cxt->ftrace_read_cnt, 1, id, type,
+ PSTORE_TYPE_FTRACE, 0);
+ } else {
+ /*
+ * Build a new dummy record which combines all the
+ * per-cpu records including metadata and ecc info.
+ */
+ struct persistent_ram_zone *tmp_prz, *prz_next;
+
+ tmp_prz = kzalloc(sizeof(struct persistent_ram_zone),
+ GFP_KERNEL);
+ if (!tmp_prz)
+ return -ENOMEM;
+ free_prz = true;
+
+ while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) {
+ prz_next = ramoops_get_next_prz(cxt->fprzs,
+ &cxt->ftrace_read_cnt,
+ cxt->max_ftrace_cnt, id,
+ type, PSTORE_TYPE_FTRACE, 0);
+
+ if (!prz_ok(prz_next))
+ continue;
+
+ tmp_prz->ecc_info = prz_next->ecc_info;
+ tmp_prz->corrected_bytes +=
+ prz_next->corrected_bytes;
+ tmp_prz->bad_blocks += prz_next->bad_blocks;
+ size = ftrace_log_combine(tmp_prz, prz_next);
+ if (size)
+ goto out;
+ }
+ *id = 0;
+ prz = tmp_prz;
+ }
+ }
+
+ if (!prz_ok(prz)) {
+ size = 0;
+ goto out;
+ }
size = persistent_ram_old_size(prz) - header_length;
@@ -234,12 +331,21 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
*ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
*buf = kmalloc(size + *ecc_notice_size + 1, GFP_KERNEL);
- if (*buf == NULL)
- return -ENOMEM;
+ if (*buf == NULL) {
+ size = -ENOMEM;
+ goto out;
+ }
memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size);
+
persistent_ram_ecc_string(prz, *buf + size, *ecc_notice_size + 1);
+out:
+ if (free_prz) {
+ kfree(prz->old_log);
+ kfree(prz);
+ }
+
return size;
}
@@ -283,15 +389,23 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
persistent_ram_write(cxt->cprz, buf, size);
return 0;
} else if (type == PSTORE_TYPE_FTRACE) {
- if (!cxt->fprz)
+ int zonenum;
+
+ if (!cxt->fprzs)
return -ENOMEM;
- persistent_ram_write(cxt->fprz, buf, size);
+ /*
+ * Choose zone by if we're using per-cpu buffers.
+ */
+ if (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
+ zonenum = smp_processor_id();
+ else
+ zonenum = 0;
+
+ persistent_ram_write(cxt->fprzs[zonenum], buf, size);
return 0;
} else if (type == PSTORE_TYPE_PMSG) {
- if (!cxt->mprz)
- return -ENOMEM;
- persistent_ram_write(cxt->mprz, buf, size);
- return 0;
+ pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__);
+ return -EINVAL;
}
if (type != PSTORE_TYPE_DMESG)
@@ -316,10 +430,10 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
if (part != 1)
return -ENOSPC;
- if (!cxt->przs)
+ if (!cxt->dprzs)
return -ENOSPC;
- prz = cxt->przs[cxt->dump_write_cnt];
+ prz = cxt->dprzs[cxt->dump_write_cnt];
hlen = ramoops_write_kmsg_hdr(prz, compressed);
if (size + hlen > prz->buffer_size)
@@ -359,13 +473,15 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
case PSTORE_TYPE_DMESG:
if (id >= cxt->max_dump_cnt)
return -EINVAL;
- prz = cxt->przs[id];
+ prz = cxt->dprzs[id];
break;
case PSTORE_TYPE_CONSOLE:
prz = cxt->cprz;
break;
case PSTORE_TYPE_FTRACE:
- prz = cxt->fprz;
+ if (id >= cxt->max_ftrace_cnt)
+ return -EINVAL;
+ prz = cxt->fprzs[id];
break;
case PSTORE_TYPE_PMSG:
prz = cxt->mprz;
@@ -396,68 +512,113 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
{
int i;
- if (!cxt->przs)
- return;
+ /* Free dump PRZs */
+ if (cxt->dprzs) {
+ for (i = 0; i < cxt->max_dump_cnt; i++)
+ persistent_ram_free(cxt->dprzs[i]);
- for (i = 0; i < cxt->max_dump_cnt; i++)
- persistent_ram_free(cxt->przs[i]);
+ kfree(cxt->dprzs);
+ cxt->max_dump_cnt = 0;
+ }
- kfree(cxt->przs);
- cxt->max_dump_cnt = 0;
+ /* Free ftrace PRZs */
+ if (cxt->fprzs) {
+ for (i = 0; i < cxt->max_ftrace_cnt; i++)
+ persistent_ram_free(cxt->fprzs[i]);
+ kfree(cxt->fprzs);
+ cxt->max_ftrace_cnt = 0;
+ }
}
-static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
- phys_addr_t *paddr, size_t dump_mem_sz)
+static int ramoops_init_przs(const char *name,
+ struct device *dev, struct ramoops_context *cxt,
+ struct persistent_ram_zone ***przs,
+ phys_addr_t *paddr, size_t mem_sz,
+ ssize_t record_size,
+ unsigned int *cnt, u32 sig, u32 flags)
{
int err = -ENOMEM;
int i;
+ size_t zone_sz;
+ struct persistent_ram_zone **prz_ar;
- if (!cxt->record_size)
+ /* Allocate nothing for 0 mem_sz or 0 record_size. */
+ if (mem_sz == 0 || record_size == 0) {
+ *cnt = 0;
return 0;
+ }
- if (*paddr + dump_mem_sz - cxt->phys_addr > cxt->size) {
- dev_err(dev, "no room for dumps\n");
- return -ENOMEM;
+ /*
+ * If we have a negative record size, calculate it based on
+ * mem_sz / *cnt. If we have a positive record size, calculate
+ * cnt from mem_sz / record_size.
+ */
+ if (record_size < 0) {
+ if (*cnt == 0)
+ return 0;
+ record_size = mem_sz / *cnt;
+ if (record_size == 0) {
+ dev_err(dev, "%s record size == 0 (%zu / %u)\n",
+ name, mem_sz, *cnt);
+ goto fail;
+ }
+ } else {
+ *cnt = mem_sz / record_size;
+ if (*cnt == 0) {
+ dev_err(dev, "%s record count == 0 (%zu / %zu)\n",
+ name, mem_sz, record_size);
+ goto fail;
+ }
}
- cxt->max_dump_cnt = dump_mem_sz / cxt->record_size;
- if (!cxt->max_dump_cnt)
- return -ENOMEM;
+ if (*paddr + mem_sz - cxt->phys_addr > cxt->size) {
+ dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
+ name,
+ mem_sz, (unsigned long long)*paddr,
+ cxt->size, (unsigned long long)cxt->phys_addr);
+ goto fail;
+ }
- cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt,
- GFP_KERNEL);
- if (!cxt->przs) {
- dev_err(dev, "failed to initialize a prz array for dumps\n");
- goto fail_mem;
+ zone_sz = mem_sz / *cnt;
+ if (!zone_sz) {
+ dev_err(dev, "%s zone size == 0\n", name);
+ goto fail;
}
- for (i = 0; i < cxt->max_dump_cnt; i++) {
- cxt->przs[i] = persistent_ram_new(*paddr, cxt->record_size, 0,
+ prz_ar = kcalloc(*cnt, sizeof(**przs), GFP_KERNEL);
+ if (!prz_ar)
+ goto fail;
+
+ for (i = 0; i < *cnt; i++) {
+ prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig,
&cxt->ecc_info,
- cxt->memtype);
- if (IS_ERR(cxt->przs[i])) {
- err = PTR_ERR(cxt->przs[i]);
- dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
- cxt->record_size, (unsigned long long)*paddr, err);
+ cxt->memtype, flags);
+ if (IS_ERR(prz_ar[i])) {
+ err = PTR_ERR(prz_ar[i]);
+ dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
+ name, record_size,
+ (unsigned long long)*paddr, err);
while (i > 0) {
i--;
- persistent_ram_free(cxt->przs[i]);
+ persistent_ram_free(prz_ar[i]);
}
- goto fail_prz;
+ kfree(prz_ar);
+ goto fail;
}
- *paddr += cxt->record_size;
+ *paddr += zone_sz;
}
+ *przs = prz_ar;
return 0;
-fail_prz:
- kfree(cxt->przs);
-fail_mem:
- cxt->max_dump_cnt = 0;
+
+fail:
+ *cnt = 0;
return err;
}
-static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
+static int ramoops_init_prz(const char *name,
+ struct device *dev, struct ramoops_context *cxt,
struct persistent_ram_zone **prz,
phys_addr_t *paddr, size_t sz, u32 sig)
{
@@ -465,18 +626,19 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
return 0;
if (*paddr + sz - cxt->phys_addr > cxt->size) {
- dev_err(dev, "no room for mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
- sz, (unsigned long long)*paddr,
+ dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
+ name, sz, (unsigned long long)*paddr,
cxt->size, (unsigned long long)cxt->phys_addr);
return -ENOMEM;
}
- *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype);
+ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
+ cxt->memtype, 0);
if (IS_ERR(*prz)) {
int err = PTR_ERR(*prz);
- dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
- sz, (unsigned long long)*paddr, err);
+ dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
+ name, sz, (unsigned long long)*paddr, err);
return err;
}
@@ -543,6 +705,7 @@ static int ramoops_parse_dt(struct platform_device *pdev,
parse_size("ftrace-size", pdata->ftrace_size);
parse_size("pmsg-size", pdata->pmsg_size);
parse_size("ecc-size", pdata->ecc_info.ecc_size);
+ parse_size("flags", pdata->flags);
#undef parse_size
@@ -561,6 +724,7 @@ static int ramoops_probe(struct platform_device *pdev)
if (dev_of_node(dev) && !pdata) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
+ pr_err("cannot allocate platform data buffer\n");
err = -ENOMEM;
goto fail_out;
}
@@ -570,11 +734,20 @@ static int ramoops_probe(struct platform_device *pdev)
goto fail_out;
}
- /* Only a single ramoops area allowed at a time, so fail extra
+ /*
+ * Only a single ramoops area allowed at a time, so fail extra
* probes.
*/
- if (cxt->max_dump_cnt)
+ if (cxt->max_dump_cnt) {
+ pr_err("already initialized\n");
goto fail_out;
+ }
+
+ /* Make sure we didn't get bogus platform data pointer. */
+ if (!pdata) {
+ pr_err("NULL platform data\n");
+ goto fail_out;
+ }
if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size &&
!pdata->ftrace_size && !pdata->pmsg_size)) {
@@ -600,27 +773,37 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->ftrace_size = pdata->ftrace_size;
cxt->pmsg_size = pdata->pmsg_size;
cxt->dump_oops = pdata->dump_oops;
+ cxt->flags = pdata->flags;
cxt->ecc_info = pdata->ecc_info;
paddr = cxt->phys_addr;
dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
- cxt->pmsg_size;
- err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz);
+ err = ramoops_init_przs("dump", dev, cxt, &cxt->dprzs, &paddr,
+ dump_mem_sz, cxt->record_size,
+ &cxt->max_dump_cnt, 0, 0);
if (err)
goto fail_out;
- err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr,
+ err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr,
cxt->console_size, 0);
if (err)
goto fail_init_cprz;
- err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
- LINUX_VERSION_CODE);
+ cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
+ ? nr_cpu_ids
+ : 1;
+ err = ramoops_init_przs("ftrace", dev, cxt, &cxt->fprzs, &paddr,
+ cxt->ftrace_size, -1,
+ &cxt->max_ftrace_cnt, LINUX_VERSION_CODE,
+ (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
+ ? PRZ_FLAG_NO_LOCK : 0);
if (err)
goto fail_init_fprz;
- err = ramoops_init_prz(dev, cxt, &cxt->mprz, &paddr, cxt->pmsg_size, 0);
+ err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
+ cxt->pmsg_size, 0);
if (err)
goto fail_init_mprz;
@@ -680,7 +863,6 @@ fail_clear:
cxt->pstore.bufsize = 0;
persistent_ram_free(cxt->mprz);
fail_init_mprz:
- persistent_ram_free(cxt->fprz);
fail_init_fprz:
persistent_ram_free(cxt->cprz);
fail_init_cprz:
@@ -699,7 +881,6 @@ static int ramoops_remove(struct platform_device *pdev)
cxt->pstore.bufsize = 0;
persistent_ram_free(cxt->mprz);
- persistent_ram_free(cxt->fprz);
persistent_ram_free(cxt->cprz);
ramoops_free_przs(cxt);
@@ -741,6 +922,8 @@ static void ramoops_register_dummy(void)
dummy_data->ftrace_size = ramoops_ftrace_size;
dummy_data->pmsg_size = ramoops_pmsg_size;
dummy_data->dump_oops = dump_oops;
+ dummy_data->flags = RAMOOPS_FLAG_FTRACE_PER_CPU;
+
/*
* For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
* (using 1 byte for ECC isn't much of use anyway).
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 3975deec02f8..a857338b7dab 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -48,16 +48,15 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
return atomic_read(&prz->buffer->start);
}
-static DEFINE_RAW_SPINLOCK(buffer_lock);
-
/* increase and wrap the start pointer, returning the old value */
static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
{
int old;
int new;
- unsigned long flags;
+ unsigned long flags = 0;
- raw_spin_lock_irqsave(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
old = atomic_read(&prz->buffer->start);
new = old + a;
@@ -65,7 +64,8 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
new -= prz->buffer_size;
atomic_set(&prz->buffer->start, new);
- raw_spin_unlock_irqrestore(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
return old;
}
@@ -75,9 +75,10 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
{
size_t old;
size_t new;
- unsigned long flags;
+ unsigned long flags = 0;
- raw_spin_lock_irqsave(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
old = atomic_read(&prz->buffer->size);
if (old == prz->buffer_size)
@@ -89,7 +90,8 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
atomic_set(&prz->buffer->size, new);
exit:
- raw_spin_unlock_irqrestore(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
}
static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
@@ -465,7 +467,8 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
}
static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
- struct persistent_ram_ecc_info *ecc_info)
+ struct persistent_ram_ecc_info *ecc_info,
+ unsigned long flags)
{
int ret;
@@ -493,6 +496,8 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
prz->buffer->sig = sig;
persistent_ram_zap(prz);
+ prz->buffer_lock = __RAW_SPIN_LOCK_UNLOCKED(buffer_lock);
+ prz->flags = flags;
return 0;
}
@@ -517,7 +522,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
- unsigned int memtype)
+ unsigned int memtype, u32 flags)
{
struct persistent_ram_zone *prz;
int ret = -ENOMEM;
@@ -532,7 +537,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
if (ret)
goto err;
- ret = persistent_ram_post_init(prz, sig, ecc_info);
+ ret = persistent_ram_post_init(prz, sig, ecc_info, flags);
if (ret)
goto err;
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
index 8b252673d454..e99b1a72d9a7 100644
--- a/fs/quota/netlink.c
+++ b/fs/quota/netlink.c
@@ -12,14 +12,8 @@ static const struct genl_multicast_group quota_mcgrps[] = {
};
/* Netlink family structure for quota */
-static struct genl_family quota_genl_family = {
- /*
- * Needed due to multicast group ID abuse - old code assumed
- * the family ID was also a valid multicast group ID (which
- * isn't true) and userspace might thus rely on it. Assign a
- * static ID for this group to make dealing with that easier.
- */
- .id = GENL_ID_VFS_DQUOT,
+static struct genl_family quota_genl_family __ro_after_init = {
+ .module = THIS_MODULE,
.hdrsize = 0,
.name = "VFS_DQUOT",
.version = 1,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 58b2dedb2a3a..cfeae9b0a2b7 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -19,6 +19,7 @@
#include <linux/quotaops.h>
#include <linux/swap.h>
#include <linux/uio.h>
+#include <linux/bio.h>
int reiserfs_commit_write(struct file *f, struct page *page,
unsigned from, unsigned to);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index bc2dde2423c2..aa40c242f1db 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1111,7 +1111,8 @@ static int flush_commit_list(struct super_block *s,
mark_buffer_dirty(jl->j_commit_bh) ;
depth = reiserfs_write_unlock_nested(s);
if (reiserfs_barrier_flush(s))
- __sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA);
+ __sync_dirty_buffer(jl->j_commit_bh,
+ REQ_PREFLUSH | REQ_FUA);
else
sync_dirty_buffer(jl->j_commit_bh);
reiserfs_write_lock_nested(s, depth);
@@ -1269,7 +1270,8 @@ static int _update_journal_header_block(struct super_block *sb,
depth = reiserfs_write_unlock_nested(sb);
if (reiserfs_barrier_flush(sb))
- __sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA);
+ __sync_dirty_buffer(journal->j_header_bh,
+ REQ_PREFLUSH | REQ_FUA);
else
sync_dirty_buffer(journal->j_header_bh);
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index a97e352d05d3..0037aea97d39 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -11,6 +11,7 @@
#include <linux/time.h>
#include <linux/string.h>
#include <linux/pagemap.h>
+#include <linux/bio.h>
#include "reiserfs.h"
#include <linux/buffer_head.h>
#include <linux/quotaops.h>
diff --git a/fs/splice.c b/fs/splice.c
index 5a7750bd2eea..8ed7c9d8c0fb 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -17,6 +17,7 @@
* Copyright (C) 2006 Ingo Molnar <mingo@elte.hu>
*
*/
+#include <linux/bvec.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/pagemap.h>
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index ce62a380314f..2751476e6b6e 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
+#include <linux/bio.h>
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index aaec13c95253..2d0e028067eb 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -30,6 +30,7 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/bio.h>
#include "udf_i.h"
#include "udf_sb.h"
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 988d5352bdb8..7aa48bd7cbaf 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/string.h>
+#include <linux/bio.h>
struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index aad46401ede5..0f3db71753aa 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -38,6 +38,7 @@
#include <linux/crc-itu-t.h>
#include <linux/mpage.h>
#include <linux/uio.h>
+#include <linux/bio.h>
#include "udf_i.h"
#include "udf_sb.h"
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 67e085d591d8..b035af54f538 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -15,6 +15,7 @@
#include <linux/buffer_head.h>
#include <linux/capability.h>
#include <linux/bitops.h>
+#include <linux/bio.h>
#include <asm/byteorder.h>
#include "ufs_fs.h"
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 3e57a56cf829..6be5204a06d3 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -495,8 +495,8 @@ xfs_submit_ioend(
ioend->io_bio->bi_private = ioend;
ioend->io_bio->bi_end_io = xfs_end_bio;
- bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE,
- (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0);
+ ioend->io_bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
+
/*
* If we are failing the IO now, just mark the ioend with an
* error and finish it. This will run IO completion immediately
@@ -567,8 +567,7 @@ xfs_chain_bio(
bio_chain(ioend->io_bio, new);
bio_get(ioend->io_bio); /* for xfs_destroy_ioend */
- bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE,
- (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0);
+ ioend->io_bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
submit_bio(ioend->io_bio);
ioend->io_bio = new;
}
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index b5b9bffe3520..33c435f3316c 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1304,7 +1304,7 @@ _xfs_buf_ioapply(
if (bp->b_flags & XBF_WRITE) {
op = REQ_OP_WRITE;
if (bp->b_flags & XBF_SYNCIO)
- op_flags = WRITE_SYNC;
+ op_flags = REQ_SYNC;
if (bp->b_flags & XBF_FUA)
op_flags |= REQ_FUA;
if (bp->b_flags & XBF_FLUSH)
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index f3db11c24654..c1ba00fc4888 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -249,6 +249,7 @@ extern int acpi_processor_register_performance(struct acpi_processor_performance
*performance, unsigned int cpu);
extern void acpi_processor_unregister_performance(unsigned int cpu);
+int acpi_processor_pstate_control(void);
/* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */
int acpi_processor_notify_smm(struct module *calling_module);
@@ -294,7 +295,7 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
#ifdef CONFIG_CPU_FREQ
void acpi_processor_ppc_init(void);
void acpi_processor_ppc_exit(void);
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
+void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit);
#else
static inline void acpi_processor_ppc_init(void)
diff --git a/include/asm-generic/cputime_jiffies.h b/include/asm-generic/cputime_jiffies.h
index fe386fc6e85e..6bb8cd45f53b 100644
--- a/include/asm-generic/cputime_jiffies.h
+++ b/include/asm-generic/cputime_jiffies.h
@@ -7,7 +7,6 @@ typedef unsigned long __nocast cputime_t;
#define cputime_one_jiffy jiffies_to_cputime(1)
#define cputime_to_jiffies(__ct) (__force unsigned long)(__ct)
-#define cputime_to_scaled(__ct) (__ct)
#define jiffies_to_cputime(__hz) (__force cputime_t)(__hz)
typedef u64 __nocast cputime64_t;
diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h
index a84e28e0c634..4e3b18e559b1 100644
--- a/include/asm-generic/cputime_nsecs.h
+++ b/include/asm-generic/cputime_nsecs.h
@@ -34,7 +34,6 @@ typedef u64 __nocast cputime64_t;
*/
#define cputime_to_jiffies(__ct) \
cputime_div(__ct, NSEC_PER_SEC / HZ)
-#define cputime_to_scaled(__ct) (__ct)
#define jiffies_to_cputime(__jif) \
(__force cputime_t)((__jif) * (NSEC_PER_SEC / HZ))
#define cputime64_to_jiffies64(__ct) \
diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h
deleted file mode 100644
index c54829d3de37..000000000000
--- a/include/asm-generic/mutex-dec.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * include/asm-generic/mutex-dec.h
- *
- * Generic implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- */
-#ifndef _ASM_GENERIC_MUTEX_DEC_H
-#define _ASM_GENERIC_MUTEX_DEC_H
-
-/**
- * __mutex_fastpath_lock - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_dec_return_acquire(count) < 0))
- fail_fn(count);
-}
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(atomic_dec_return_acquire(count) < 0))
- return -1;
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - try to promote the count from 0 to 1
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, then the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_inc_return_release(count) <= 0))
- fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- *
- * If the architecture has no effective trylock variant, it should call the
- * <fail_fn> spinlock-based trylock variant unconditionally.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- if (likely(atomic_read(count) == 1 && atomic_cmpxchg_acquire(count, 1, 0) == 1))
- return 1;
- return 0;
-}
-
-#endif
diff --git a/include/asm-generic/mutex-null.h b/include/asm-generic/mutex-null.h
deleted file mode 100644
index 61069ed334e2..000000000000
--- a/include/asm-generic/mutex-null.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-generic/mutex-null.h
- *
- * Generic implementation of the mutex fastpath, based on NOP :-)
- *
- * This is used by the mutex-debugging infrastructure, but it can also
- * be used by architectures that (for whatever reason) want to use the
- * spinlock based slowpath.
- */
-#ifndef _ASM_GENERIC_MUTEX_NULL_H
-#define _ASM_GENERIC_MUTEX_NULL_H
-
-#define __mutex_fastpath_lock(count, fail_fn) fail_fn(count)
-#define __mutex_fastpath_lock_retval(count) (-1)
-#define __mutex_fastpath_unlock(count, fail_fn) fail_fn(count)
-#define __mutex_fastpath_trylock(count, fail_fn) fail_fn(count)
-#define __mutex_slowpath_needs_to_unlock() 1
-
-#endif
diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h
deleted file mode 100644
index 3269ec4e195f..000000000000
--- a/include/asm-generic/mutex-xchg.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * include/asm-generic/mutex-xchg.h
- *
- * Generic implementation of the mutex fastpath, based on xchg().
- *
- * NOTE: An xchg based implementation might be less optimal than an atomic
- * decrement/increment based implementation. If your architecture
- * has a reasonable atomic dec/inc then you should probably use
- * asm-generic/mutex-dec.h instead, or you could open-code an
- * optimized version in asm/mutex.h.
- */
-#ifndef _ASM_GENERIC_MUTEX_XCHG_H
-#define _ASM_GENERIC_MUTEX_XCHG_H
-
-/**
- * __mutex_fastpath_lock - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if it
- * wasn't 1 originally. This function MUST leave the value lower than 1
- * even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_xchg(count, 0) != 1))
- /*
- * We failed to acquire the lock, so mark it contended
- * to ensure that any waiting tasks are woken up by the
- * unlock slow path.
- */
- if (likely(atomic_xchg_acquire(count, -1) != 1))
- fail_fn(count);
-}
-
-/**
- * __mutex_fastpath_lock_retval - try to take the lock by moving the count
- * from 1 to a 0 value
- * @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
- if (unlikely(atomic_xchg_acquire(count, 0) != 1))
- if (likely(atomic_xchg(count, -1) != 1))
- return -1;
- return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1
- * @count: pointer of type atomic_t
- * @fail_fn: function to call if the original value was not 0
- *
- * try to promote the mutex from 0 to 1. if it wasn't 0, call <function>
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than one.
- * If the implementation sets it to a value of lower than one, the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- if (unlikely(atomic_xchg_release(count, 1) != 0))
- fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock() 0
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- * @count: pointer of type atomic_t
- * @fail_fn: spinlock based trylock implementation
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- *
- * If the architecture has no effective trylock variant, it should call the
- * <fail_fn> spinlock-based trylock variant unconditionally.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- int prev;
-
- if (atomic_read(count) != 1)
- return 0;
-
- prev = atomic_xchg_acquire(count, 0);
- if (unlikely(prev < 0)) {
- /*
- * The lock was marked contended so we must restore that
- * state. If while doing so we get back a prev value of 1
- * then we just own it.
- *
- * [ In the rare case of the mutex going to 1, to 0, to -1
- * and then back to 0 in this few-instructions window,
- * this has the potential to trigger the slowpath for the
- * owner's unlock path needlessly, but that's not a problem
- * in practice. ]
- */
- prev = atomic_xchg_acquire(count, prev);
- if (prev < 0)
- prev = 0;
- }
-
- return prev;
-}
-
-#endif
diff --git a/include/asm-generic/mutex.h b/include/asm-generic/mutex.h
deleted file mode 100644
index fe91ab502793..000000000000
--- a/include/asm-generic/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_GENERIC_MUTEX_H
-#define __ASM_GENERIC_MUTEX_H
-/*
- * Pull in the generic implementation for the mutex fastpath,
- * which is a reasonable default on many architectures.
- */
-
-#include <asm-generic/mutex-dec.h>
-#endif /* __ASM_GENERIC_MUTEX_H */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index c4f8fd2fd384..18af2bcefe6a 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -558,10 +558,9 @@ static inline int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
* track_pfn_insert is called when a _new_ single pfn is established
* by vm_insert_pfn().
*/
-static inline int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
- pfn_t pfn)
+static inline void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
+ pfn_t pfn)
{
- return 0;
}
/*
@@ -593,8 +592,8 @@ static inline void untrack_pfn_moved(struct vm_area_struct *vma)
extern int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
unsigned long pfn, unsigned long addr,
unsigned long size);
-extern int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
- pfn_t pfn);
+extern void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
+ pfn_t pfn);
extern int track_pfn_copy(struct vm_area_struct *vma);
extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
unsigned long size);
@@ -653,18 +652,9 @@ static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
}
#endif
-#ifndef pmd_move_must_withdraw
-static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl,
- spinlock_t *old_pmd_ptl)
-{
- /*
- * With split pmd lock we also need to move preallocated
- * PTE page table if new_pmd is on different PMD page table.
- */
- return new_pmd_ptl != old_pmd_ptl;
-}
+#ifndef arch_needs_pgtable_deposit
+#define arch_needs_pgtable_deposit() (false)
#endif
-
/*
* This function is meant to be used by sites walking pagetables with
* the mmap_sem hold in read mode to protect against MADV_DONTNEED and
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index c6d667187608..7eed8cf3130a 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -107,11 +107,6 @@ struct mmu_gather {
struct mmu_gather_batch local;
struct page *__pages[MMU_GATHER_BUNDLE];
unsigned int batch_count;
- /*
- * __tlb_adjust_range will track the new addr here,
- * that that we can adjust the range after the flush
- */
- unsigned long addr;
int page_size;
};
@@ -125,16 +120,11 @@ extern bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page,
int page_size);
static inline void __tlb_adjust_range(struct mmu_gather *tlb,
- unsigned long address)
+ unsigned long address,
+ unsigned int range_size)
{
tlb->start = min(tlb->start, address);
- tlb->end = max(tlb->end, address + PAGE_SIZE);
- /*
- * Track the last address with which we adjusted the range. This
- * will be used later to adjust again after a mmu_flush due to
- * failed __tlb_remove_page
- */
- tlb->addr = address;
+ tlb->end = max(tlb->end, address + range_size);
}
static inline void __tlb_reset_range(struct mmu_gather *tlb)
@@ -150,15 +140,11 @@ static inline void __tlb_reset_range(struct mmu_gather *tlb)
static inline void tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, int page_size)
{
- if (__tlb_remove_page_size(tlb, page, page_size)) {
+ if (__tlb_remove_page_size(tlb, page, page_size))
tlb_flush_mmu(tlb);
- tlb->page_size = page_size;
- __tlb_adjust_range(tlb, tlb->addr);
- __tlb_remove_page_size(tlb, page, page_size);
- }
}
-static bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
{
return __tlb_remove_page_size(tlb, page, PAGE_SIZE);
}
@@ -172,14 +158,21 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
return tlb_remove_page_size(tlb, page, PAGE_SIZE);
}
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb, struct page *page)
+#ifndef tlb_remove_check_page_size_change
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+ unsigned int page_size)
{
- /* active->nr should be zero when we call this */
- VM_BUG_ON_PAGE(tlb->active->nr, page);
- tlb->page_size = PAGE_SIZE;
- __tlb_adjust_range(tlb, tlb->addr);
- return __tlb_remove_page(tlb, page);
+ /*
+ * We don't care about page size change, just update
+ * mmu_gather page size here so that debug checks
+ * doesn't throw false warning.
+ */
+#ifdef CONFIG_DEBUG_VM
+ tlb->page_size = page_size;
+#endif
}
+#endif
/*
* In the case of tlb vma handling, we can optimise these away in the
@@ -215,10 +208,16 @@ static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb, struct page *pa
*/
#define tlb_remove_tlb_entry(tlb, ptep, address) \
do { \
- __tlb_adjust_range(tlb, address); \
+ __tlb_adjust_range(tlb, address, PAGE_SIZE); \
__tlb_remove_tlb_entry(tlb, ptep, address); \
} while (0)
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ do { \
+ __tlb_adjust_range(tlb, address, huge_page_size(h)); \
+ __tlb_remove_tlb_entry(tlb, ptep, address); \
+ } while (0)
+
/**
* tlb_remove_pmd_tlb_entry - remember a pmd mapping for later tlb invalidation
* This is a nop so far, because only x86 needs it.
@@ -227,29 +226,47 @@ static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb, struct page *pa
#define __tlb_remove_pmd_tlb_entry(tlb, pmdp, address) do {} while (0)
#endif
-#define tlb_remove_pmd_tlb_entry(tlb, pmdp, address) \
- do { \
- __tlb_adjust_range(tlb, address); \
- __tlb_remove_pmd_tlb_entry(tlb, pmdp, address); \
+#define tlb_remove_pmd_tlb_entry(tlb, pmdp, address) \
+ do { \
+ __tlb_adjust_range(tlb, address, HPAGE_PMD_SIZE); \
+ __tlb_remove_pmd_tlb_entry(tlb, pmdp, address); \
} while (0)
+/*
+ * For things like page tables caches (ie caching addresses "inside" the
+ * page tables, like x86 does), for legacy reasons, flushing an
+ * individual page had better flush the page table caches behind it. This
+ * is definitely how x86 works, for example. And if you have an
+ * architected non-legacy page table cache (which I'm not aware of
+ * anybody actually doing), you're going to have some architecturally
+ * explicit flushing for that, likely *separate* from a regular TLB entry
+ * flush, and thus you'd need more than just some range expansion..
+ *
+ * So if we ever find an architecture
+ * that would want something that odd, I think it is up to that
+ * architecture to do its own odd thing, not cause pain for others
+ * http://lkml.kernel.org/r/CA+55aFzBggoXtNXQeng5d_mRoDnaMBE5Y+URs+PHR67nUpMtaw@mail.gmail.com
+ *
+ * For now w.r.t page table cache, mark the range_size as PAGE_SIZE
+ */
+
#define pte_free_tlb(tlb, ptep, address) \
do { \
- __tlb_adjust_range(tlb, address); \
+ __tlb_adjust_range(tlb, address, PAGE_SIZE); \
__pte_free_tlb(tlb, ptep, address); \
} while (0)
#ifndef __ARCH_HAS_4LEVEL_HACK
#define pud_free_tlb(tlb, pudp, address) \
do { \
- __tlb_adjust_range(tlb, address); \
+ __tlb_adjust_range(tlb, address, PAGE_SIZE); \
__pud_free_tlb(tlb, pudp, address); \
} while (0)
#endif
#define pmd_free_tlb(tlb, pmdp, address) \
do { \
- __tlb_adjust_range(tlb, address); \
+ __tlb_adjust_range(tlb, address, PAGE_SIZE); \
__pmd_free_tlb(tlb, pmdp, address); \
} while (0)
diff --git a/include/drm/bridge/mhl.h b/include/drm/bridge/mhl.h
new file mode 100644
index 000000000000..3629b2734db6
--- /dev/null
+++ b/include/drm/bridge/mhl.h
@@ -0,0 +1,291 @@
+/*
+ * Defines for Mobile High-Definition Link (MHL) interface
+ *
+ * Copyright (C) 2015, Samsung Electronics, Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * Based on MHL driver for Android devices.
+ * Copyright (C) 2013-2014 Silicon Image, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MHL_H__
+#define __MHL_H__
+
+/* Device Capabilities Registers */
+enum {
+ MHL_DCAP_DEV_STATE,
+ MHL_DCAP_MHL_VERSION,
+ MHL_DCAP_CAT,
+ MHL_DCAP_ADOPTER_ID_H,
+ MHL_DCAP_ADOPTER_ID_L,
+ MHL_DCAP_VID_LINK_MODE,
+ MHL_DCAP_AUD_LINK_MODE,
+ MHL_DCAP_VIDEO_TYPE,
+ MHL_DCAP_LOG_DEV_MAP,
+ MHL_DCAP_BANDWIDTH,
+ MHL_DCAP_FEATURE_FLAG,
+ MHL_DCAP_DEVICE_ID_H,
+ MHL_DCAP_DEVICE_ID_L,
+ MHL_DCAP_SCRATCHPAD_SIZE,
+ MHL_DCAP_INT_STAT_SIZE,
+ MHL_DCAP_RESERVED,
+ MHL_DCAP_SIZE
+};
+
+#define MHL_DCAP_CAT_SINK 0x01
+#define MHL_DCAP_CAT_SOURCE 0x02
+#define MHL_DCAP_CAT_POWER 0x10
+#define MHL_DCAP_CAT_PLIM(x) ((x) << 5)
+
+#define MHL_DCAP_VID_LINK_RGB444 0x01
+#define MHL_DCAP_VID_LINK_YCBCR444 0x02
+#define MHL_DCAP_VID_LINK_YCBCR422 0x04
+#define MHL_DCAP_VID_LINK_PPIXEL 0x08
+#define MHL_DCAP_VID_LINK_ISLANDS 0x10
+#define MHL_DCAP_VID_LINK_VGA 0x20
+#define MHL_DCAP_VID_LINK_16BPP 0x40
+
+#define MHL_DCAP_AUD_LINK_2CH 0x01
+#define MHL_DCAP_AUD_LINK_8CH 0x02
+
+#define MHL_DCAP_VT_GRAPHICS 0x00
+#define MHL_DCAP_VT_PHOTO 0x02
+#define MHL_DCAP_VT_CINEMA 0x04
+#define MHL_DCAP_VT_GAMES 0x08
+#define MHL_DCAP_SUPP_VT 0x80
+
+#define MHL_DCAP_LD_DISPLAY 0x01
+#define MHL_DCAP_LD_VIDEO 0x02
+#define MHL_DCAP_LD_AUDIO 0x04
+#define MHL_DCAP_LD_MEDIA 0x08
+#define MHL_DCAP_LD_TUNER 0x10
+#define MHL_DCAP_LD_RECORD 0x20
+#define MHL_DCAP_LD_SPEAKER 0x40
+#define MHL_DCAP_LD_GUI 0x80
+#define MHL_DCAP_LD_ALL 0xFF
+
+#define MHL_DCAP_FEATURE_RCP_SUPPORT 0x01
+#define MHL_DCAP_FEATURE_RAP_SUPPORT 0x02
+#define MHL_DCAP_FEATURE_SP_SUPPORT 0x04
+#define MHL_DCAP_FEATURE_UCP_SEND_SUPPOR 0x08
+#define MHL_DCAP_FEATURE_UCP_RECV_SUPPORT 0x10
+#define MHL_DCAP_FEATURE_RBP_SUPPORT 0x40
+
+/* Extended Device Capabilities Registers */
+enum {
+ MHL_XDC_ECBUS_SPEEDS,
+ MHL_XDC_TMDS_SPEEDS,
+ MHL_XDC_ECBUS_ROLES,
+ MHL_XDC_LOG_DEV_MAPX,
+ MHL_XDC_SIZE
+};
+
+#define MHL_XDC_ECBUS_S_075 0x01
+#define MHL_XDC_ECBUS_S_8BIT 0x02
+#define MHL_XDC_ECBUS_S_12BIT 0x04
+#define MHL_XDC_ECBUS_D_150 0x10
+#define MHL_XDC_ECBUS_D_8BIT 0x20
+
+#define MHL_XDC_TMDS_000 0x00
+#define MHL_XDC_TMDS_150 0x01
+#define MHL_XDC_TMDS_300 0x02
+#define MHL_XDC_TMDS_600 0x04
+
+/* MHL_XDC_ECBUS_ROLES flags */
+#define MHL_XDC_DEV_HOST 0x01
+#define MHL_XDC_DEV_DEVICE 0x02
+#define MHL_XDC_DEV_CHARGER 0x04
+#define MHL_XDC_HID_HOST 0x08
+#define MHL_XDC_HID_DEVICE 0x10
+
+/* MHL_XDC_LOG_DEV_MAPX flags */
+#define MHL_XDC_LD_PHONE 0x01
+
+/* Device Status Registers */
+enum {
+ MHL_DST_CONNECTED_RDY,
+ MHL_DST_LINK_MODE,
+ MHL_DST_VERSION,
+ MHL_DST_SIZE
+};
+
+/* Offset of DEVSTAT registers */
+#define MHL_DST_OFFSET 0x30
+#define MHL_DST_REG(name) (MHL_DST_OFFSET + MHL_DST_##name)
+
+#define MHL_DST_CONN_DCAP_RDY 0x01
+#define MHL_DST_CONN_XDEVCAPP_SUPP 0x02
+#define MHL_DST_CONN_POW_STAT 0x04
+#define MHL_DST_CONN_PLIM_STAT_MASK 0x38
+
+#define MHL_DST_LM_CLK_MODE_MASK 0x07
+#define MHL_DST_LM_CLK_MODE_PACKED_PIXEL 0x02
+#define MHL_DST_LM_CLK_MODE_NORMAL 0x03
+#define MHL_DST_LM_PATH_EN_MASK 0x08
+#define MHL_DST_LM_PATH_ENABLED 0x08
+#define MHL_DST_LM_PATH_DISABLED 0x00
+#define MHL_DST_LM_MUTED_MASK 0x10
+
+/* Extended Device Status Registers */
+enum {
+ MHL_XDS_CURR_ECBUS_MODE,
+ MHL_XDS_AVLINK_MODE_STATUS,
+ MHL_XDS_AVLINK_MODE_CONTROL,
+ MHL_XDS_MULTI_SINK_STATUS,
+ MHL_XDS_SIZE
+};
+
+/* Offset of XDEVSTAT registers */
+#define MHL_XDS_OFFSET 0x90
+#define MHL_XDS_REG(name) (MHL_XDS_OFFSET + MHL_XDS_##name)
+
+/* MHL_XDS_REG_CURR_ECBUS_MODE flags */
+#define MHL_XDS_SLOT_MODE_8BIT 0x00
+#define MHL_XDS_SLOT_MODE_6BIT 0x01
+#define MHL_XDS_ECBUS_S 0x04
+#define MHL_XDS_ECBUS_D 0x08
+
+#define MHL_XDS_LINK_CLOCK_75MHZ 0x00
+#define MHL_XDS_LINK_CLOCK_150MHZ 0x10
+#define MHL_XDS_LINK_CLOCK_300MHZ 0x20
+#define MHL_XDS_LINK_CLOCK_600MHZ 0x30
+
+#define MHL_XDS_LINK_STATUS_NO_SIGNAL 0x00
+#define MHL_XDS_LINK_STATUS_CRU_LOCKED 0x01
+#define MHL_XDS_LINK_STATUS_TMDS_NORMAL 0x02
+#define MHL_XDS_LINK_STATUS_TMDS_RESERVED 0x03
+
+#define MHL_XDS_LINK_RATE_1_5_GBPS 0x00
+#define MHL_XDS_LINK_RATE_3_0_GBPS 0x01
+#define MHL_XDS_LINK_RATE_6_0_GBPS 0x02
+#define MHL_XDS_ATT_CAPABLE 0x08
+
+#define MHL_XDS_SINK_STATUS_1_HPD_LOW 0x00
+#define MHL_XDS_SINK_STATUS_1_HPD_HIGH 0x01
+#define MHL_XDS_SINK_STATUS_2_HPD_LOW 0x00
+#define MHL_XDS_SINK_STATUS_2_HPD_HIGH 0x04
+#define MHL_XDS_SINK_STATUS_3_HPD_LOW 0x00
+#define MHL_XDS_SINK_STATUS_3_HPD_HIGH 0x10
+#define MHL_XDS_SINK_STATUS_4_HPD_LOW 0x00
+#define MHL_XDS_SINK_STATUS_4_HPD_HIGH 0x40
+
+/* Interrupt Registers */
+enum {
+ MHL_INT_RCHANGE,
+ MHL_INT_DCHANGE,
+ MHL_INT_SIZE
+};
+
+/* Offset of DEVSTAT registers */
+#define MHL_INT_OFFSET 0x20
+#define MHL_INT_REG(name) (MHL_INT_OFFSET + MHL_INT_##name)
+
+#define MHL_INT_RC_DCAP_CHG 0x01
+#define MHL_INT_RC_DSCR_CHG 0x02
+#define MHL_INT_RC_REQ_WRT 0x04
+#define MHL_INT_RC_GRT_WRT 0x08
+#define MHL_INT_RC_3D_REQ 0x10
+#define MHL_INT_RC_FEAT_REQ 0x20
+#define MHL_INT_RC_FEAT_COMPLETE 0x40
+
+#define MHL_INT_DC_EDID_CHG 0x02
+
+enum {
+ MHL_ACK = 0x33, /* Command or Data byte acknowledge */
+ MHL_NACK = 0x34, /* Command or Data byte not acknowledge */
+ MHL_ABORT = 0x35, /* Transaction abort */
+ MHL_WRITE_STAT = 0xe0, /* Write one status register */
+ MHL_SET_INT = 0x60, /* Write one interrupt register */
+ MHL_READ_DEVCAP_REG = 0x61, /* Read one register */
+ MHL_GET_STATE = 0x62, /* Read CBUS revision level from follower */
+ MHL_GET_VENDOR_ID = 0x63, /* Read vendor ID value from follower */
+ MHL_SET_HPD = 0x64, /* Set Hot Plug Detect in follower */
+ MHL_CLR_HPD = 0x65, /* Clear Hot Plug Detect in follower */
+ MHL_SET_CAP_ID = 0x66, /* Set Capture ID for downstream device */
+ MHL_GET_CAP_ID = 0x67, /* Get Capture ID from downstream device */
+ MHL_MSC_MSG = 0x68, /* VS command to send RCP sub-commands */
+ MHL_GET_SC1_ERRORCODE = 0x69, /* Get Vendor-Specific error code */
+ MHL_GET_DDC_ERRORCODE = 0x6A, /* Get DDC channel command error code */
+ MHL_GET_MSC_ERRORCODE = 0x6B, /* Get MSC command error code */
+ MHL_WRITE_BURST = 0x6C, /* Write 1-16 bytes to responder's scratchpad */
+ MHL_GET_SC3_ERRORCODE = 0x6D, /* Get channel 3 command error code */
+ MHL_WRITE_XSTAT = 0x70, /* Write one extended status register */
+ MHL_READ_XDEVCAP_REG = 0x71, /* Read one extended devcap register */
+ /* let the rest of these float, they are software specific */
+ MHL_READ_EDID_BLOCK,
+ MHL_SEND_3D_REQ_OR_FEAT_REQ,
+ MHL_READ_DEVCAP,
+ MHL_READ_XDEVCAP
+};
+
+/* MSC message types */
+enum {
+ MHL_MSC_MSG_RCP = 0x10, /* RCP sub-command */
+ MHL_MSC_MSG_RCPK = 0x11, /* RCP Acknowledge sub-command */
+ MHL_MSC_MSG_RCPE = 0x12, /* RCP Error sub-command */
+ MHL_MSC_MSG_RAP = 0x20, /* Mode Change Warning sub-command */
+ MHL_MSC_MSG_RAPK = 0x21, /* MCW Acknowledge sub-command */
+ MHL_MSC_MSG_RBP = 0x22, /* Remote Button Protocol sub-command */
+ MHL_MSC_MSG_RBPK = 0x23, /* RBP Acknowledge sub-command */
+ MHL_MSC_MSG_RBPE = 0x24, /* RBP Error sub-command */
+ MHL_MSC_MSG_UCP = 0x30, /* UCP sub-command */
+ MHL_MSC_MSG_UCPK = 0x31, /* UCP Acknowledge sub-command */
+ MHL_MSC_MSG_UCPE = 0x32, /* UCP Error sub-command */
+ MHL_MSC_MSG_RUSB = 0x40, /* Request USB host role */
+ MHL_MSC_MSG_RUSBK = 0x41, /* Acknowledge request for USB host role */
+ MHL_MSC_MSG_RHID = 0x42, /* Request HID host role */
+ MHL_MSC_MSG_RHIDK = 0x43, /* Acknowledge request for HID host role */
+ MHL_MSC_MSG_ATT = 0x50, /* Request attention sub-command */
+ MHL_MSC_MSG_ATTK = 0x51, /* ATT Acknowledge sub-command */
+ MHL_MSC_MSG_BIST_TRIGGER = 0x60,
+ MHL_MSC_MSG_BIST_REQUEST_STAT = 0x61,
+ MHL_MSC_MSG_BIST_READY = 0x62,
+ MHL_MSC_MSG_BIST_STOP = 0x63,
+};
+
+/* RAP action codes */
+#define MHL_RAP_POLL 0x00 /* Just do an ack */
+#define MHL_RAP_CONTENT_ON 0x10 /* Turn content stream ON */
+#define MHL_RAP_CONTENT_OFF 0x11 /* Turn content stream OFF */
+#define MHL_RAP_CBUS_MODE_DOWN 0x20
+#define MHL_RAP_CBUS_MODE_UP 0x21
+
+/* RAPK status codes */
+#define MHL_RAPK_NO_ERR 0x00 /* RAP action recognized & supported */
+#define MHL_RAPK_UNRECOGNIZED 0x01 /* Unknown RAP action code received */
+#define MHL_RAPK_UNSUPPORTED 0x02 /* Rcvd RAP action code not supported */
+#define MHL_RAPK_BUSY 0x03 /* Responder too busy to respond */
+
+/*
+ * Error status codes for RCPE messages
+ */
+/* No error. (Not allowed in RCPE messages) */
+#define MHL_RCPE_STATUS_NO_ERROR 0x00
+/* Unsupported/unrecognized key code */
+#define MHL_RCPE_STATUS_INEFFECTIVE_KEY_CODE 0x01
+/* Responder busy. Initiator may retry message */
+#define MHL_RCPE_STATUS_BUSY 0x02
+
+/*
+ * Error status codes for RBPE messages
+ */
+/* No error. (Not allowed in RBPE messages) */
+#define MHL_RBPE_STATUS_NO_ERROR 0x00
+/* Unsupported/unrecognized button code */
+#define MHL_RBPE_STATUS_INEFFECTIVE_BUTTON_CODE 0x01
+/* Responder busy. Initiator may retry message */
+#define MHL_RBPE_STATUS_BUSY 0x02
+
+/*
+ * Error status codes for UCPE messages
+ */
+/* No error. (Not allowed in UCPE messages) */
+#define MHL_UCPE_STATUS_NO_ERROR 0x00
+/* Unsupported/unrecognized key code */
+#define MHL_UCPE_STATUS_INEFFECTIVE_KEY_CODE 0x01
+
+#endif /* __MHL_H__ */
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 672644031bd5..a9cfd33c7b1a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -57,7 +57,7 @@
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <asm/mman.h>
#include <asm/pgalloc.h>
@@ -76,6 +76,7 @@
#include <drm/drm_os_linux.h>
#include <drm/drm_sarea.h>
#include <drm/drm_vma_manager.h>
+#include <drm/drm_drv.h>
struct module;
@@ -135,35 +136,12 @@ struct dma_buf_attachment;
#define DRM_UT_PRIME 0x08
#define DRM_UT_ATOMIC 0x10
#define DRM_UT_VBL 0x20
-
-extern __printf(6, 7)
-void drm_dev_printk(const struct device *dev, const char *level,
- unsigned int category, const char *function_name,
- const char *prefix, const char *format, ...);
-
-extern __printf(3, 4)
-void drm_printk(const char *level, unsigned int category,
- const char *format, ...);
+#define DRM_UT_STATE 0x40
/***********************************************************************/
/** \name DRM template customization defaults */
/*@{*/
-/* driver capabilities and requirements mask */
-#define DRIVER_USE_AGP 0x1
-#define DRIVER_LEGACY 0x2
-#define DRIVER_PCI_DMA 0x8
-#define DRIVER_SG 0x10
-#define DRIVER_HAVE_DMA 0x20
-#define DRIVER_HAVE_IRQ 0x40
-#define DRIVER_IRQ_SHARED 0x80
-#define DRIVER_GEM 0x1000
-#define DRIVER_MODESET 0x2000
-#define DRIVER_PRIME 0x4000
-#define DRIVER_RENDER 0x8000
-#define DRIVER_ATOMIC 0x10000
-#define DRIVER_KMS_LEGACY_CONTEXT 0x20000
-
/***********************************************************************/
/** \name Macros to make printk easier */
/*@{*/
@@ -306,6 +284,27 @@ void drm_printk(const char *level, unsigned int category,
#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \
DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
+/* Format strings and argument splitters to simplify printing
+ * various "complex" objects
+ */
+#define DRM_MODE_FMT "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
+#define DRM_MODE_ARG(m) \
+ (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \
+ (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \
+ (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \
+ (m)->type, (m)->flags
+
+#define DRM_RECT_FMT "%dx%d%+d%+d"
+#define DRM_RECT_ARG(r) drm_rect_width(r), drm_rect_height(r), (r)->x1, (r)->y1
+
+/* for rect's in fixed-point format: */
+#define DRM_RECT_FP_FMT "%d.%06ux%d.%06u%+d.%06u%+d.%06u"
+#define DRM_RECT_FP_ARG(r) \
+ drm_rect_width(r) >> 16, ((drm_rect_width(r) & 0xffff) * 15625) >> 10, \
+ drm_rect_height(r) >> 16, ((drm_rect_height(r) & 0xffff) * 15625) >> 10, \
+ (r)->x1 >> 16, (((r)->x1 & 0xffff) * 15625) >> 10, \
+ (r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10
+
/*@}*/
/***********************************************************************/
@@ -362,7 +361,7 @@ struct drm_ioctl_desc {
struct drm_pending_event {
struct completion *completion;
struct drm_event *event;
- struct fence *fence;
+ struct dma_fence *fence;
struct list_head link;
struct list_head pending_link;
struct drm_file *file_priv;
@@ -458,263 +457,6 @@ struct drm_lock_data {
#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
-/**
- * DRM driver structure. This structure represent the common code for
- * a family of cards. There will one drm_device for each card present
- * in this family
- */
-struct drm_driver {
- int (*load) (struct drm_device *, unsigned long flags);
- int (*firstopen) (struct drm_device *);
- int (*open) (struct drm_device *, struct drm_file *);
- void (*preclose) (struct drm_device *, struct drm_file *file_priv);
- void (*postclose) (struct drm_device *, struct drm_file *);
- void (*lastclose) (struct drm_device *);
- int (*unload) (struct drm_device *);
- int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
- int (*dma_quiescent) (struct drm_device *);
- int (*context_dtor) (struct drm_device *dev, int context);
- int (*set_busid)(struct drm_device *dev, struct drm_master *master);
-
- /**
- * get_vblank_counter - get raw hardware vblank counter
- * @dev: DRM device
- * @pipe: counter to fetch
- *
- * Driver callback for fetching a raw hardware vblank counter for @crtc.
- * If a device doesn't have a hardware counter, the driver can simply
- * use drm_vblank_no_hw_counter() function. The DRM core will account for
- * missed vblank events while interrupts where disabled based on system
- * timestamps.
- *
- * Wraparound handling and loss of events due to modesetting is dealt
- * with in the DRM core code.
- *
- * RETURNS
- * Raw vblank counter value.
- */
- u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
-
- /**
- * enable_vblank - enable vblank interrupt events
- * @dev: DRM device
- * @pipe: which irq to enable
- *
- * Enable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, the driver should use the
- * drm_vblank_no_hw_counter() function that keeps a virtual counter.
- *
- * RETURNS
- * Zero on success, appropriate errno if the given @crtc's vblank
- * interrupt cannot be enabled.
- */
- int (*enable_vblank) (struct drm_device *dev, unsigned int pipe);
-
- /**
- * disable_vblank - disable vblank interrupt events
- * @dev: DRM device
- * @pipe: which irq to enable
- *
- * Disable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, the driver should use the
- * drm_vblank_no_hw_counter() function that keeps a virtual counter.
- */
- void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
-
- /**
- * Called by \c drm_device_is_agp. Typically used to determine if a
- * card is really attached to AGP or not.
- *
- * \param dev DRM device handle
- *
- * \returns
- * One of three values is returned depending on whether or not the
- * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
- * (return of 1), or may or may not be AGP (return of 2).
- */
- int (*device_is_agp) (struct drm_device *dev);
-
- /**
- * Called by vblank timestamping code.
- *
- * Return the current display scanout position from a crtc, and an
- * optional accurate ktime_get timestamp of when position was measured.
- *
- * \param dev DRM device.
- * \param pipe Id of the crtc to query.
- * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
- * \param *vpos Target location for current vertical scanout position.
- * \param *hpos Target location for current horizontal scanout position.
- * \param *stime Target location for timestamp taken immediately before
- * scanout position query. Can be NULL to skip timestamp.
- * \param *etime Target location for timestamp taken immediately after
- * scanout position query. Can be NULL to skip timestamp.
- * \param mode Current display timings.
- *
- * Returns vpos as a positive number while in active scanout area.
- * Returns vpos as a negative number inside vblank, counting the number
- * of scanlines to go until end of vblank, e.g., -1 means "one scanline
- * until start of active scanout / end of vblank."
- *
- * \return Flags, or'ed together as follows:
- *
- * DRM_SCANOUTPOS_VALID = Query successful.
- * DRM_SCANOUTPOS_INVBL = Inside vblank.
- * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
- * this flag means that returned position may be offset by a constant
- * but unknown small number of scanlines wrt. real scanout position.
- *
- */
- int (*get_scanout_position) (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);
-
- /**
- * Called by \c drm_get_last_vbltimestamp. Should return a precise
- * timestamp when the most recent VBLANK interval ended or will end.
- *
- * Specifically, the timestamp in @vblank_time should correspond as
- * closely as possible to the time when the first video scanline of
- * the video frame after the end of VBLANK will start scanning out,
- * the time immediately after end of the VBLANK interval. If the
- * @crtc is currently inside VBLANK, this will be a time in the future.
- * If the @crtc is currently scanning out a frame, this will be the
- * past start time of the current scanout. This is meant to adhere
- * to the OpenML OML_sync_control extension specification.
- *
- * \param dev dev DRM device handle.
- * \param pipe crtc for which timestamp should be returned.
- * \param *max_error Maximum allowable timestamp error in nanoseconds.
- * Implementation should strive to provide timestamp
- * with an error of at most *max_error nanoseconds.
- * Returns true upper bound on error for timestamp.
- * \param *vblank_time Target location for returned vblank timestamp.
- * \param flags 0 = Defaults, no special treatment needed.
- * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
- * irq handler. Some drivers need to apply some workarounds
- * for gpu-specific vblank irq quirks if flag is set.
- *
- * \returns
- * Zero if timestamping isn't supported in current display mode or a
- * negative number on failure. A positive status code on success,
- * which describes how the vblank_time timestamp was computed.
- */
- int (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
- int *max_error,
- struct timeval *vblank_time,
- unsigned flags);
-
- /* these have to be filled in */
-
- irqreturn_t(*irq_handler) (int irq, void *arg);
- void (*irq_preinstall) (struct drm_device *dev);
- int (*irq_postinstall) (struct drm_device *dev);
- void (*irq_uninstall) (struct drm_device *dev);
-
- /* Master routines */
- int (*master_create)(struct drm_device *dev, struct drm_master *master);
- void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
- /**
- * master_set is called whenever the minor master is set.
- * master_drop is called whenever the minor master is dropped.
- */
-
- int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
- bool from_open);
- void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv);
-
- int (*debugfs_init)(struct drm_minor *minor);
- void (*debugfs_cleanup)(struct drm_minor *minor);
-
- /**
- * @gem_free_object: deconstructor for drm_gem_objects
- *
- * This is deprecated and should not be used by new drivers. Use
- * @gem_free_object_unlocked instead.
- */
- void (*gem_free_object) (struct drm_gem_object *obj);
-
- /**
- * @gem_free_object_unlocked: deconstructor for drm_gem_objects
- *
- * This is for drivers which are not encumbered with dev->struct_mutex
- * legacy locking schemes. Use this hook instead of @gem_free_object.
- */
- void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
-
- int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
- void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
-
- /**
- * Hook for allocating the GEM object struct, for use by core
- * helpers.
- */
- struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
- size_t size);
-
- /* prime: */
- /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
- int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
- uint32_t handle, uint32_t flags, int *prime_fd);
- /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
- int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
- int prime_fd, uint32_t *handle);
- /* export GEM -> dmabuf */
- struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
- struct drm_gem_object *obj, int flags);
- /* import dmabuf -> GEM */
- struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
- struct dma_buf *dma_buf);
- /* low-level interface used by drm_gem_prime_{import,export} */
- int (*gem_prime_pin)(struct drm_gem_object *obj);
- void (*gem_prime_unpin)(struct drm_gem_object *obj);
- struct reservation_object * (*gem_prime_res_obj)(
- struct drm_gem_object *obj);
- struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
- struct drm_gem_object *(*gem_prime_import_sg_table)(
- struct drm_device *dev,
- struct dma_buf_attachment *attach,
- struct sg_table *sgt);
- void *(*gem_prime_vmap)(struct drm_gem_object *obj);
- void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
- int (*gem_prime_mmap)(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
-
- /* vga arb irq handler */
- void (*vgaarb_irq)(struct drm_device *dev, bool state);
-
- /* dumb alloc support */
- int (*dumb_create)(struct drm_file *file_priv,
- struct drm_device *dev,
- struct drm_mode_create_dumb *args);
- int (*dumb_map_offset)(struct drm_file *file_priv,
- struct drm_device *dev, uint32_t handle,
- uint64_t *offset);
- int (*dumb_destroy)(struct drm_file *file_priv,
- struct drm_device *dev,
- uint32_t handle);
-
- /* Driver private ops for this object */
- const struct vm_operations_struct *gem_vm_ops;
-
- int major;
- int minor;
- int patchlevel;
- char *name;
- char *desc;
- char *date;
-
- u32 driver_features;
- int dev_priv_size;
- const struct drm_ioctl_desc *ioctls;
- int num_ioctls;
- const struct file_operations *fops;
-
- /* List of devices hanging off this driver with stealth attach. */
- struct list_head legacy_dev_list;
-};
-
enum drm_minor_type {
DRM_MINOR_PRIMARY,
DRM_MINOR_CONTROL,
@@ -941,8 +683,13 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
extern long drm_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
extern long drm_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
+#else
+/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
+#define drm_compat_ioctl NULL
+#endif
extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
/* File Operations (drm_fops.c) */
@@ -980,15 +727,6 @@ void drm_clflush_virt_range(void *addr, unsigned long length);
* DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
*/
-/* Modesetting support */
-extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe);
-extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe);
-
-/* drm_drv.c */
-void drm_put_dev(struct drm_device *dev);
-void drm_unplug_dev(struct drm_device *dev);
-extern unsigned int drm_debug;
-
/* Debugfs support */
#if defined(CONFIG_DEBUG_FS)
extern int drm_debugfs_create_files(const struct drm_info_list *files,
@@ -1041,19 +779,6 @@ extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
-struct drm_device *drm_dev_alloc(struct drm_driver *driver,
- struct device *parent);
-int drm_dev_init(struct drm_device *dev,
- struct drm_driver *driver,
- struct device *parent);
-void drm_dev_ref(struct drm_device *dev);
-void drm_dev_unref(struct drm_device *dev);
-int drm_dev_register(struct drm_device *dev, unsigned long flags);
-void drm_dev_unregister(struct drm_device *dev);
-
-struct drm_minor *drm_minor_acquire(unsigned int minor_id);
-void drm_minor_release(struct drm_minor *minor);
-
/*@}*/
/* PCI section */
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 9701f2dfb784..d6d241f63b9f 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -144,6 +144,7 @@ struct __drm_crtcs_state {
struct drm_crtc *ptr;
struct drm_crtc_state *state;
struct drm_crtc_commit *commit;
+ s64 __user *out_fence_ptr;
};
struct __drm_connnectors_state {
@@ -153,6 +154,7 @@ struct __drm_connnectors_state {
/**
* struct drm_atomic_state - the global state object for atomic updates
+ * @ref: count of all references to this state (will not be freed until zero)
* @dev: parent DRM device
* @allow_modeset: allow full modeset
* @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
@@ -164,6 +166,8 @@ struct __drm_connnectors_state {
* @acquire_ctx: acquire context for this atomic modeset state update
*/
struct drm_atomic_state {
+ struct kref ref;
+
struct drm_device *dev;
bool allow_modeset : 1;
bool legacy_cursor_update : 1;
@@ -193,7 +197,33 @@ static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit)
struct drm_atomic_state * __must_check
drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);
-void drm_atomic_state_free(struct drm_atomic_state *state);
+
+/**
+ * drm_atomic_state_get - acquire a reference to the atomic state
+ * @state: The atomic state
+ *
+ * Returns a new reference to the @state
+ */
+static inline struct drm_atomic_state *
+drm_atomic_state_get(struct drm_atomic_state *state)
+{
+ kref_get(&state->ref);
+ return state;
+}
+
+void __drm_atomic_state_free(struct kref *ref);
+
+/**
+ * drm_atomic_state_put - release a reference to the atomic state
+ * @state: The atomic state
+ *
+ * This releases a reference to @state which is freed after removing the
+ * final reference. No locking required and callable from any context.
+ */
+static inline void drm_atomic_state_put(struct drm_atomic_state *state)
+{
+ kref_put(&state->ref, __drm_atomic_state_free);
+}
int __must_check
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state);
@@ -316,6 +346,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc);
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
struct drm_framebuffer *fb);
+void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+ struct dma_fence *fence);
int __must_check
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
struct drm_crtc *crtc);
@@ -335,6 +367,14 @@ int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
int __must_check drm_atomic_commit(struct drm_atomic_state *state);
int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
+void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
+
+#ifdef CONFIG_DEBUG_FS
+struct drm_minor;
+int drm_atomic_debugfs_init(struct drm_minor *minor);
+int drm_atomic_debugfs_cleanup(struct drm_minor *minor);
+#endif
+
#define for_each_connector_in_state(__state, connector, connector_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->num_connector && \
@@ -365,11 +405,20 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
*
* To give drivers flexibility struct &drm_crtc_state has 3 booleans to track
* whether the state CRTC changed enough to need a full modeset cycle:
- * connectors_changed, mode_changed and active_change. This helper simply
+ * connectors_changed, mode_changed and active_changed. This helper simply
* combines these three to compute the overall need for a modeset for @state.
+ *
+ * The atomic helper code sets these booleans, but drivers can and should
+ * change them appropriately to accurately represent whether a modeset is
+ * really needed. In general, drivers should avoid full modesets whenever
+ * possible.
+ *
+ * For example if the CRTC mode has changed, and the hardware is able to enact
+ * the requested mode change without going through a full modeset, the driver
+ * should clear mode_changed during its ->atomic_check.
*/
static inline bool
-drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
+drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
{
return state->mode_changed || state->active_changed ||
state->connectors_changed;
diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h
index 36baa175de99..13221cf9b3eb 100644
--- a/include/drm/drm_blend.h
+++ b/include/drm/drm_blend.h
@@ -47,8 +47,14 @@ struct drm_atomic_state;
#define DRM_REFLECT_Y BIT(5)
#define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
-struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
- unsigned int supported_rotations);
+static inline bool drm_rotation_90_or_270(unsigned int rotation)
+{
+ return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270);
+}
+
+int drm_plane_create_rotation_property(struct drm_plane *plane,
+ unsigned int rotation,
+ unsigned int supported_rotations);
unsigned int drm_rotation_simplify(unsigned int rotation,
unsigned int supported_rotations);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ac9d7d8e0e43..a9b95246e26e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -37,6 +37,7 @@ struct drm_crtc;
struct drm_encoder;
struct drm_property;
struct drm_property_blob;
+struct drm_printer;
struct edid;
enum drm_connector_force {
@@ -194,10 +195,40 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
unsigned int num_formats);
/**
+ * struct drm_tv_connector_state - TV connector related states
+ * @subconnector: selected subconnector
+ * @margins: left/right/top/bottom margins
+ * @mode: TV mode
+ * @brightness: brightness in percent
+ * @contrast: contrast in percent
+ * @flicker_reduction: flicker reduction in percent
+ * @overscan: overscan in percent
+ * @saturation: saturation in percent
+ * @hue: hue in percent
+ */
+struct drm_tv_connector_state {
+ enum drm_mode_subconnector subconnector;
+ struct {
+ unsigned int left;
+ unsigned int right;
+ unsigned int top;
+ unsigned int bottom;
+ } margins;
+ unsigned int mode;
+ unsigned int brightness;
+ unsigned int contrast;
+ unsigned int flicker_reduction;
+ unsigned int overscan;
+ unsigned int saturation;
+ unsigned int hue;
+};
+
+/**
* struct drm_connector_state - mutable connector state
* @connector: backpointer to the connector
* @best_encoder: can be used by helpers and drivers to select the encoder
* @state: backpointer to global drm_atomic_state
+ * @tv: TV connector state
*/
struct drm_connector_state {
struct drm_connector *connector;
@@ -213,6 +244,8 @@ struct drm_connector_state {
struct drm_encoder *best_encoder;
struct drm_atomic_state *state;
+
+ struct drm_tv_connector_state tv;
};
/**
@@ -261,6 +294,9 @@ struct drm_connector_funcs {
* connector due to a user request. force can be used by the driver to
* avoid expensive, destructive operations during automated probing.
*
+ * This callback is optional, if not implemented the connector will be
+ * considered as always being attached.
+ *
* FIXME:
*
* Note that this hook is only called by the probe helper. It's not in
@@ -481,6 +517,18 @@ struct drm_connector_funcs {
const struct drm_connector_state *state,
struct drm_property *property,
uint64_t *val);
+
+ /**
+ * @atomic_print_state:
+ *
+ * If driver subclasses struct &drm_connector_state, it should implement
+ * this optional hook for printing additional driver specific state.
+ *
+ * Do not call this directly, use drm_atomic_connector_print_state()
+ * instead.
+ */
+ void (*atomic_print_state)(struct drm_printer *p,
+ const struct drm_connector_state *state);
};
/* mode specified on the command line */
@@ -762,6 +810,30 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
const struct edid *edid);
/**
+ * struct drm_tile_group - Tile group metadata
+ * @refcount: reference count
+ * @dev: DRM device
+ * @id: tile group id exposed to userspace
+ * @group_data: Sink-private data identifying this group
+ *
+ * @group_data corresponds to displayid vend/prod/serial for external screens
+ * with an EDID.
+ */
+struct drm_tile_group {
+ struct kref refcount;
+ struct drm_device *dev;
+ int id;
+ u8 group_data[8];
+};
+
+struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+ char topology[8]);
+struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+ char topology[8]);
+void drm_mode_put_tile_group(struct drm_device *dev,
+ struct drm_tile_group *tg);
+
+/**
* drm_for_each_connector - iterate over all connectors
* @connector: the loop cursor
* @dev: the DRM device
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0aa292526567..946672f97e1e 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -28,7 +28,6 @@
#include <linux/i2c.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <linux/idr.h>
#include <linux/fb.h>
#include <linux/hdmi.h>
#include <linux/media-bus-format.h>
@@ -47,13 +46,16 @@
#include <drm/drm_plane.h>
#include <drm/drm_blend.h>
#include <drm/drm_color_mgmt.h>
+#include <drm/drm_debugfs_crc.h>
+#include <drm/drm_mode_config.h>
struct drm_device;
struct drm_mode_set;
struct drm_file;
struct drm_clip_rect;
+struct drm_printer;
struct device_node;
-struct fence;
+struct dma_fence;
struct edid;
static inline int64_t U642I64(uint64_t val)
@@ -65,14 +67,6 @@ static inline uint64_t I642U64(int64_t val)
return (uint64_t)*((uint64_t *)&val);
}
-/* data corresponds to displayid vend/prod/serial */
-struct drm_tile_group {
- struct kref refcount;
- struct drm_device *dev;
- int id;
- u8 group_data[8];
-};
-
struct drm_crtc;
struct drm_encoder;
struct drm_pending_vblank_event;
@@ -116,6 +110,11 @@ struct drm_plane_helper_funcs;
* never return in a failure from the ->atomic_check callback. Userspace assumes
* that a DPMS On will always succeed. In other words: @enable controls resource
* assignment, @active controls the actual hardware state.
+ *
+ * The three booleans active_changed, connectors_changed and mode_changed are
+ * intended to indicate whether a full modeset is needed, rather than strictly
+ * describing what has changed in a commit.
+ * See also: drm_atomic_crtc_needs_modeset()
*/
struct drm_crtc_state {
struct drm_crtc *crtc;
@@ -564,6 +563,42 @@ struct drm_crtc_funcs {
* before data structures are torndown.
*/
void (*early_unregister)(struct drm_crtc *crtc);
+
+ /**
+ * @set_crc_source:
+ *
+ * Changes the source of CRC checksums of frames at the request of
+ * userspace, typically for testing purposes. The sources available are
+ * specific of each driver and a %NULL value indicates that CRC
+ * generation is to be switched off.
+ *
+ * When CRC generation is enabled, the driver should call
+ * drm_crtc_add_crc_entry() at each frame, providing any information
+ * that characterizes the frame contents in the crcN arguments, as
+ * provided from the configured source. Drivers must accept a "auto"
+ * source name that will select a default source for this CRTC.
+ *
+ * This callback is optional if the driver does not support any CRC
+ * generation functionality.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+ int (*set_crc_source)(struct drm_crtc *crtc, const char *source,
+ size_t *values_cnt);
+
+ /**
+ * @atomic_print_state:
+ *
+ * If driver subclasses struct &drm_crtc_state, it should implement
+ * this optional hook for printing additional driver specific state.
+ *
+ * Do not call this directly, use drm_atomic_crtc_print_state()
+ * instead.
+ */
+ void (*atomic_print_state)(struct drm_printer *p,
+ const struct drm_crtc_state *state);
};
/**
@@ -680,660 +715,90 @@ struct drm_crtc {
* context.
*/
struct drm_modeset_acquire_ctx *acquire_ctx;
-};
-/**
- * struct drm_mode_set - new values for a CRTC config change
- * @fb: framebuffer to use for new config
- * @crtc: CRTC whose configuration we're about to change
- * @mode: mode timings to use
- * @x: position of this CRTC relative to @fb
- * @y: position of this CRTC relative to @fb
- * @connectors: array of connectors to drive with this CRTC if possible
- * @num_connectors: size of @connectors array
- *
- * Represents a single crtc the connectors that it drives with what mode
- * and from which framebuffer it scans out from.
- *
- * This is used to set modes.
- */
-struct drm_mode_set {
- struct drm_framebuffer *fb;
- struct drm_crtc *crtc;
- struct drm_display_mode *mode;
-
- uint32_t x;
- uint32_t y;
-
- struct drm_connector **connectors;
- size_t num_connectors;
-};
-
-/**
- * struct drm_mode_config_funcs - basic driver provided mode setting functions
- *
- * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
- * involve drivers.
- */
-struct drm_mode_config_funcs {
+#ifdef CONFIG_DEBUG_FS
/**
- * @fb_create:
- *
- * Create a new framebuffer object. The core does basic checks on the
- * requested metadata, but most of that is left to the driver. See
- * struct &drm_mode_fb_cmd2 for details.
- *
- * If the parameters are deemed valid and the backing storage objects in
- * the underlying memory manager all exist, then the driver allocates
- * a new &drm_framebuffer structure, subclassed to contain
- * driver-specific information (like the internal native buffer object
- * references). It also needs to fill out all relevant metadata, which
- * should be done by calling drm_helper_mode_fill_fb_struct().
+ * @debugfs_entry:
*
- * The initialization is finalized by calling drm_framebuffer_init(),
- * which registers the framebuffer and makes it accessible to other
- * threads.
- *
- * RETURNS:
- *
- * A new framebuffer with an initial reference count of 1 or a negative
- * error code encoded with ERR_PTR().
+ * Debugfs directory for this CRTC.
*/
- struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
- struct drm_file *file_priv,
- const struct drm_mode_fb_cmd2 *mode_cmd);
+ struct dentry *debugfs_entry;
/**
- * @output_poll_changed:
- *
- * Callback used by helpers to inform the driver of output configuration
- * changes.
+ * @crc:
*
- * Drivers implementing fbdev emulation with the helpers can call
- * drm_fb_helper_hotplug_changed from this hook to inform the fbdev
- * helper of output changes.
- *
- * FIXME:
- *
- * Except that there's no vtable for device-level helper callbacks
- * there's no reason this is a core function.
+ * Configuration settings of CRC capture.
*/
- void (*output_poll_changed)(struct drm_device *dev);
+ struct drm_crtc_crc crc;
+#endif
/**
- * @atomic_check:
- *
- * This is the only hook to validate an atomic modeset update. This
- * function must reject any modeset and state changes which the hardware
- * or driver doesn't support. This includes but is of course not limited
- * to:
- *
- * - Checking that the modes, framebuffers, scaling and placement
- * requirements and so on are within the limits of the hardware.
- *
- * - Checking that any hidden shared resources are not oversubscribed.
- * This can be shared PLLs, shared lanes, overall memory bandwidth,
- * display fifo space (where shared between planes or maybe even
- * CRTCs).
- *
- * - Checking that virtualized resources exported to userspace are not
- * oversubscribed. For various reasons it can make sense to expose
- * more planes, crtcs or encoders than which are physically there. One
- * example is dual-pipe operations (which generally should be hidden
- * from userspace if when lockstepped in hardware, exposed otherwise),
- * where a plane might need 1 hardware plane (if it's just on one
- * pipe), 2 hardware planes (when it spans both pipes) or maybe even
- * shared a hardware plane with a 2nd plane (if there's a compatible
- * plane requested on the area handled by the other pipe).
- *
- * - Check that any transitional state is possible and that if
- * requested, the update can indeed be done in the vblank period
- * without temporarily disabling some functions.
- *
- * - Check any other constraints the driver or hardware might have.
- *
- * - This callback also needs to correctly fill out the &drm_crtc_state
- * in this update to make sure that drm_atomic_crtc_needs_modeset()
- * reflects the nature of the possible update and returns true if and
- * only if the update cannot be applied without tearing within one
- * vblank on that CRTC. The core uses that information to reject
- * updates which require a full modeset (i.e. blanking the screen, or
- * at least pausing updates for a substantial amount of time) if
- * userspace has disallowed that in its request.
- *
- * - The driver also does not need to repeat basic input validation
- * like done for the corresponding legacy entry points. The core does
- * that before calling this hook.
- *
- * See the documentation of @atomic_commit for an exhaustive list of
- * error conditions which don't have to be checked at the
- * ->atomic_check() stage?
- *
- * See the documentation for struct &drm_atomic_state for how exactly
- * an atomic modeset update is described.
- *
- * Drivers using the atomic helpers can implement this hook using
- * drm_atomic_helper_check(), or one of the exported sub-functions of
- * it.
+ * @fence_context:
*
- * RETURNS:
- *
- * 0 on success or one of the below negative error codes:
- *
- * - -EINVAL, if any of the above constraints are violated.
- *
- * - -EDEADLK, when returned from an attempt to acquire an additional
- * &drm_modeset_lock through drm_modeset_lock().
- *
- * - -ENOMEM, if allocating additional state sub-structures failed due
- * to lack of memory.
- *
- * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted.
- * This can either be due to a pending signal, or because the driver
- * needs to completely bail out to recover from an exceptional
- * situation like a GPU hang. From a userspace point all errors are
- * treated equally.
+ * timeline context used for fence operations.
*/
- int (*atomic_check)(struct drm_device *dev,
- struct drm_atomic_state *state);
+ unsigned int fence_context;
/**
- * @atomic_commit:
- *
- * This is the only hook to commit an atomic modeset update. The core
- * guarantees that @atomic_check has been called successfully before
- * calling this function, and that nothing has been changed in the
- * interim.
- *
- * See the documentation for struct &drm_atomic_state for how exactly
- * an atomic modeset update is described.
- *
- * Drivers using the atomic helpers can implement this hook using
- * drm_atomic_helper_commit(), or one of the exported sub-functions of
- * it.
- *
- * Nonblocking commits (as indicated with the nonblock parameter) must
- * do any preparatory work which might result in an unsuccessful commit
- * in the context of this callback. The only exceptions are hardware
- * errors resulting in -EIO. But even in that case the driver must
- * ensure that the display pipe is at least running, to avoid
- * compositors crashing when pageflips don't work. Anything else,
- * specifically committing the update to the hardware, should be done
- * without blocking the caller. For updates which do not require a
- * modeset this must be guaranteed.
- *
- * The driver must wait for any pending rendering to the new
- * framebuffers to complete before executing the flip. It should also
- * wait for any pending rendering from other drivers if the underlying
- * buffer is a shared dma-buf. Nonblocking commits must not wait for
- * rendering in the context of this callback.
- *
- * An application can request to be notified when the atomic commit has
- * completed. These events are per-CRTC and can be distinguished by the
- * CRTC index supplied in &drm_event to userspace.
- *
- * The drm core will supply a struct &drm_event in the event
- * member of each CRTC's &drm_crtc_state structure. See the
- * documentation for &drm_crtc_state for more details about the precise
- * semantics of this event.
- *
- * NOTE:
- *
- * Drivers are not allowed to shut down any display pipe successfully
- * enabled through an atomic commit on their own. Doing so can result in
- * compositors crashing if a page flip is suddenly rejected because the
- * pipe is off.
- *
- * RETURNS:
- *
- * 0 on success or one of the below negative error codes:
- *
- * - -EBUSY, if a nonblocking updated is requested and there is
- * an earlier updated pending. Drivers are allowed to support a queue
- * of outstanding updates, but currently no driver supports that.
- * Note that drivers must wait for preceding updates to complete if a
- * synchronous update is requested, they are not allowed to fail the
- * commit in that case.
- *
- * - -ENOMEM, if the driver failed to allocate memory. Specifically
- * this can happen when trying to pin framebuffers, which must only
- * be done when committing the state.
- *
- * - -ENOSPC, as a refinement of the more generic -ENOMEM to indicate
- * that the driver has run out of vram, iommu space or similar GPU
- * address space needed for framebuffer.
- *
- * - -EIO, if the hardware completely died.
+ * @fence_lock:
*
- * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted.
- * This can either be due to a pending signal, or because the driver
- * needs to completely bail out to recover from an exceptional
- * situation like a GPU hang. From a userspace point of view all errors are
- * treated equally.
- *
- * This list is exhaustive. Specifically this hook is not allowed to
- * return -EINVAL (any invalid requests should be caught in
- * @atomic_check) or -EDEADLK (this function must not acquire
- * additional modeset locks).
- */
- int (*atomic_commit)(struct drm_device *dev,
- struct drm_atomic_state *state,
- bool nonblock);
-
- /**
- * @atomic_state_alloc:
- *
- * This optional hook can be used by drivers that want to subclass struct
- * &drm_atomic_state to be able to track their own driver-private global
- * state easily. If this hook is implemented, drivers must also
- * implement @atomic_state_clear and @atomic_state_free.
- *
- * RETURNS:
- *
- * A new &drm_atomic_state on success or NULL on failure.
+ * spinlock to protect the fences in the fence_context.
*/
- struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
+ spinlock_t fence_lock;
/**
- * @atomic_state_clear:
- *
- * This hook must clear any driver private state duplicated into the
- * passed-in &drm_atomic_state. This hook is called when the caller
- * encountered a &drm_modeset_lock deadlock and needs to drop all
- * already acquired locks as part of the deadlock avoidance dance
- * implemented in drm_modeset_lock_backoff().
+ * @fence_seqno:
*
- * Any duplicated state must be invalidated since a concurrent atomic
- * update might change it, and the drm atomic interfaces always apply
- * updates as relative changes to the current state.
- *
- * Drivers that implement this must call drm_atomic_state_default_clear()
- * to clear common state.
+ * Seqno variable used as monotonic counter for the fences
+ * created on the CRTC's timeline.
*/
- void (*atomic_state_clear)(struct drm_atomic_state *state);
+ unsigned long fence_seqno;
/**
- * @atomic_state_free:
- *
- * This hook needs driver private resources and the &drm_atomic_state
- * itself. Note that the core first calls drm_atomic_state_clear() to
- * avoid code duplicate between the clear and free hooks.
+ * @timeline_name:
*
- * Drivers that implement this must call drm_atomic_state_default_free()
- * to release common resources.
+ * The name of the CRTC's fence timeline.
*/
- void (*atomic_state_free)(struct drm_atomic_state *state);
+ char timeline_name[32];
};
/**
- * struct drm_mode_config - Mode configuration control structure
- * @mutex: mutex protecting KMS related lists and structures
- * @connection_mutex: ww mutex protecting connector state and routing
- * @acquire_ctx: global implicit acquire context used by atomic drivers for
- * legacy IOCTLs
- * @fb_lock: mutex to protect fb state and lists
- * @num_fb: number of fbs available
- * @fb_list: list of framebuffers available
- * @num_encoder: number of encoders on this device
- * @encoder_list: list of encoder objects
- * @num_overlay_plane: number of overlay planes on this device
- * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device
- * @plane_list: list of plane objects
- * @num_crtc: number of CRTCs on this device
- * @crtc_list: list of CRTC objects
- * @property_list: list of property objects
- * @min_width: minimum pixel width on this device
- * @min_height: minimum pixel height on this device
- * @max_width: maximum pixel width on this device
- * @max_height: maximum pixel height on this device
- * @funcs: core driver provided mode setting functions
- * @fb_base: base address of the framebuffer
- * @poll_enabled: track polling support for this device
- * @poll_running: track polling status for this device
- * @delayed_event: track delayed poll uevent deliver for this device
- * @output_poll_work: delayed work for polling in process context
- * @property_blob_list: list of all the blob property objects
- * @blob_lock: mutex for blob property allocation and management
- * @*_property: core property tracking
- * @preferred_depth: preferred RBG pixel depth, used by fb helpers
- * @prefer_shadow: hint to userspace to prefer shadow-fb rendering
- * @cursor_width: hint to userspace for max cursor width
- * @cursor_height: hint to userspace for max cursor height
- * @helper_private: mid-layer private data
+ * struct drm_mode_set - new values for a CRTC config change
+ * @fb: framebuffer to use for new config
+ * @crtc: CRTC whose configuration we're about to change
+ * @mode: mode timings to use
+ * @x: position of this CRTC relative to @fb
+ * @y: position of this CRTC relative to @fb
+ * @connectors: array of connectors to drive with this CRTC if possible
+ * @num_connectors: size of @connectors array
*
- * Core mode resource tracking structure. All CRTC, encoders, and connectors
- * enumerated by the driver are added here, as are global properties. Some
- * global restrictions are also here, e.g. dimension restrictions.
+ * Represents a single crtc the connectors that it drives with what mode
+ * and from which framebuffer it scans out from.
+ *
+ * This is used to set modes.
*/
-struct drm_mode_config {
- struct mutex mutex; /* protects configuration (mode lists etc.) */
- struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
- struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
-
- /**
- * @idr_mutex:
- *
- * Mutex for KMS ID allocation and management. Protects both @crtc_idr
- * and @tile_idr.
- */
- struct mutex idr_mutex;
-
- /**
- * @crtc_idr:
- *
- * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc,
- * connector, modes - just makes life easier to have only one.
- */
- struct idr crtc_idr;
-
- /**
- * @tile_idr:
- *
- * Use this idr for allocating new IDs for tiled sinks like use in some
- * high-res DP MST screens.
- */
- struct idr tile_idr;
-
- struct mutex fb_lock; /* proctects global and per-file fb lists */
- int num_fb;
- struct list_head fb_list;
-
- /**
- * @num_connector: Number of connectors on this device.
- */
- int num_connector;
- /**
- * @connector_ida: ID allocator for connector indices.
- */
- struct ida connector_ida;
- /**
- * @connector_list: List of connector objects.
- */
- struct list_head connector_list;
- int num_encoder;
- struct list_head encoder_list;
-
- /*
- * Track # of overlay planes separately from # of total planes. By
- * default we only advertise overlay planes to userspace; if userspace
- * sets the "universal plane" capability bit, we'll go ahead and
- * expose all planes.
- */
- int num_overlay_plane;
- int num_total_plane;
- struct list_head plane_list;
-
- int num_crtc;
- struct list_head crtc_list;
-
- struct list_head property_list;
-
- int min_width, min_height;
- int max_width, max_height;
- const struct drm_mode_config_funcs *funcs;
- resource_size_t fb_base;
-
- /* output poll support */
- bool poll_enabled;
- bool poll_running;
- bool delayed_event;
- struct delayed_work output_poll_work;
-
- struct mutex blob_lock;
-
- /* pointers to standard properties */
- struct list_head property_blob_list;
- /**
- * @edid_property: Default connector property to hold the EDID of the
- * currently connected sink, if any.
- */
- struct drm_property *edid_property;
- /**
- * @dpms_property: Default connector property to control the
- * connector's DPMS state.
- */
- struct drm_property *dpms_property;
- /**
- * @path_property: Default connector property to hold the DP MST path
- * for the port.
- */
- struct drm_property *path_property;
- /**
- * @tile_property: Default connector property to store the tile
- * position of a tiled screen, for sinks which need to be driven with
- * multiple CRTCs.
- */
- struct drm_property *tile_property;
- /**
- * @plane_type_property: Default plane property to differentiate
- * CURSOR, PRIMARY and OVERLAY legacy uses of planes.
- */
- struct drm_property *plane_type_property;
- /**
- * @rotation_property: Optional property for planes or CRTCs to specifiy
- * rotation.
- */
- struct drm_property *rotation_property;
- /**
- * @prop_src_x: Default atomic plane property for the plane source
- * position in the connected &drm_framebuffer.
- */
- struct drm_property *prop_src_x;
- /**
- * @prop_src_y: Default atomic plane property for the plane source
- * position in the connected &drm_framebuffer.
- */
- struct drm_property *prop_src_y;
- /**
- * @prop_src_w: Default atomic plane property for the plane source
- * position in the connected &drm_framebuffer.
- */
- struct drm_property *prop_src_w;
- /**
- * @prop_src_h: Default atomic plane property for the plane source
- * position in the connected &drm_framebuffer.
- */
- struct drm_property *prop_src_h;
- /**
- * @prop_crtc_x: Default atomic plane property for the plane destination
- * position in the &drm_crtc is is being shown on.
- */
- struct drm_property *prop_crtc_x;
- /**
- * @prop_crtc_y: Default atomic plane property for the plane destination
- * position in the &drm_crtc is is being shown on.
- */
- struct drm_property *prop_crtc_y;
- /**
- * @prop_crtc_w: Default atomic plane property for the plane destination
- * position in the &drm_crtc is is being shown on.
- */
- struct drm_property *prop_crtc_w;
- /**
- * @prop_crtc_h: Default atomic plane property for the plane destination
- * position in the &drm_crtc is is being shown on.
- */
- struct drm_property *prop_crtc_h;
- /**
- * @prop_fb_id: Default atomic plane property to specify the
- * &drm_framebuffer.
- */
- struct drm_property *prop_fb_id;
- /**
- * @prop_crtc_id: Default atomic plane property to specify the
- * &drm_crtc.
- */
- struct drm_property *prop_crtc_id;
- /**
- * @prop_active: Default atomic CRTC property to control the active
- * state, which is the simplified implementation for DPMS in atomic
- * drivers.
- */
- struct drm_property *prop_active;
- /**
- * @prop_mode_id: Default atomic CRTC property to set the mode for a
- * CRTC. A 0 mode implies that the CRTC is entirely disabled - all
- * connectors must be of and active must be set to disabled, too.
- */
- struct drm_property *prop_mode_id;
-
- /**
- * @dvi_i_subconnector_property: Optional DVI-I property to
- * differentiate between analog or digital mode.
- */
- struct drm_property *dvi_i_subconnector_property;
- /**
- * @dvi_i_select_subconnector_property: Optional DVI-I property to
- * select between analog or digital mode.
- */
- struct drm_property *dvi_i_select_subconnector_property;
-
- /**
- * @tv_subconnector_property: Optional TV property to differentiate
- * between different TV connector types.
- */
- struct drm_property *tv_subconnector_property;
- /**
- * @tv_select_subconnector_property: Optional TV property to select
- * between different TV connector types.
- */
- struct drm_property *tv_select_subconnector_property;
- /**
- * @tv_mode_property: Optional TV property to select
- * the output TV mode.
- */
- struct drm_property *tv_mode_property;
- /**
- * @tv_left_margin_property: Optional TV property to set the left
- * margin.
- */
- struct drm_property *tv_left_margin_property;
- /**
- * @tv_right_margin_property: Optional TV property to set the right
- * margin.
- */
- struct drm_property *tv_right_margin_property;
- /**
- * @tv_top_margin_property: Optional TV property to set the right
- * margin.
- */
- struct drm_property *tv_top_margin_property;
- /**
- * @tv_bottom_margin_property: Optional TV property to set the right
- * margin.
- */
- struct drm_property *tv_bottom_margin_property;
- /**
- * @tv_brightness_property: Optional TV property to set the
- * brightness.
- */
- struct drm_property *tv_brightness_property;
- /**
- * @tv_contrast_property: Optional TV property to set the
- * contrast.
- */
- struct drm_property *tv_contrast_property;
- /**
- * @tv_flicker_reduction_property: Optional TV property to control the
- * flicker reduction mode.
- */
- struct drm_property *tv_flicker_reduction_property;
- /**
- * @tv_overscan_property: Optional TV property to control the overscan
- * setting.
- */
- struct drm_property *tv_overscan_property;
- /**
- * @tv_saturation_property: Optional TV property to set the
- * saturation.
- */
- struct drm_property *tv_saturation_property;
- /**
- * @tv_hue_property: Optional TV property to set the hue.
- */
- struct drm_property *tv_hue_property;
-
- /**
- * @scaling_mode_property: Optional connector property to control the
- * upscaling, mostly used for built-in panels.
- */
- struct drm_property *scaling_mode_property;
- /**
- * @aspect_ratio_property: Optional connector property to control the
- * HDMI infoframe aspect ratio setting.
- */
- struct drm_property *aspect_ratio_property;
- /**
- * @degamma_lut_property: Optional CRTC property to set the LUT used to
- * convert the framebuffer's colors to linear gamma.
- */
- struct drm_property *degamma_lut_property;
- /**
- * @degamma_lut_size_property: Optional CRTC property for the size of
- * the degamma LUT as supported by the driver (read-only).
- */
- struct drm_property *degamma_lut_size_property;
- /**
- * @ctm_property: Optional CRTC property to set the
- * matrix used to convert colors after the lookup in the
- * degamma LUT.
- */
- struct drm_property *ctm_property;
- /**
- * @gamma_lut_property: Optional CRTC property to set the LUT used to
- * convert the colors, after the CTM matrix, to the gamma space of the
- * connected screen.
- */
- struct drm_property *gamma_lut_property;
- /**
- * @gamma_lut_size_property: Optional CRTC property for the size of the
- * gamma LUT as supported by the driver (read-only).
- */
- struct drm_property *gamma_lut_size_property;
-
- /**
- * @suggested_x_property: Optional connector property with a hint for
- * the position of the output on the host's screen.
- */
- struct drm_property *suggested_x_property;
- /**
- * @suggested_y_property: Optional connector property with a hint for
- * the position of the output on the host's screen.
- */
- struct drm_property *suggested_y_property;
-
- /* dumb ioctl parameters */
- uint32_t preferred_depth, prefer_shadow;
-
- /**
- * @async_page_flip: Does this device support async flips on the primary
- * plane?
- */
- bool async_page_flip;
-
- /**
- * @allow_fb_modifiers:
- *
- * Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call.
- */
- bool allow_fb_modifiers;
+struct drm_mode_set {
+ struct drm_framebuffer *fb;
+ struct drm_crtc *crtc;
+ struct drm_display_mode *mode;
- /* cursor size */
- uint32_t cursor_width, cursor_height;
+ uint32_t x;
+ uint32_t y;
- struct drm_mode_config_helper_funcs *helper_private;
+ struct drm_connector **connectors;
+ size_t num_connectors;
};
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
-extern __printf(6, 7)
+__printf(6, 7)
int drm_crtc_init_with_planes(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_plane *primary,
struct drm_plane *cursor,
const struct drm_crtc_funcs *funcs,
const char *name, ...);
-extern void drm_crtc_cleanup(struct drm_crtc *crtc);
+void drm_crtc_cleanup(struct drm_crtc *crtc);
/**
* drm_crtc_index - find the index of a registered CRTC
@@ -1354,28 +819,17 @@ static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc)
* Given a registered CRTC, return the mask bit of that CRTC for an
* encoder's possible_crtcs field.
*/
-static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
+static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc)
{
return 1 << drm_crtc_index(crtc);
}
-extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
- int *hdisplay, int *vdisplay);
-extern int drm_crtc_force_disable(struct drm_crtc *crtc);
-extern int drm_crtc_force_disable_all(struct drm_device *dev);
-
-extern void drm_mode_config_init(struct drm_device *dev);
-extern void drm_mode_config_reset(struct drm_device *dev);
-extern void drm_mode_config_cleanup(struct drm_device *dev);
-
-extern int drm_mode_set_config_internal(struct drm_mode_set *set);
+void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
+ int *hdisplay, int *vdisplay);
+int drm_crtc_force_disable(struct drm_crtc *crtc);
+int drm_crtc_force_disable_all(struct drm_device *dev);
-extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
- char topology[8]);
-extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
- char topology[8]);
-extern void drm_mode_put_tile_group(struct drm_device *dev,
- struct drm_tile_group *tg);
+int drm_mode_set_config_internal(struct drm_mode_set *set);
/* Helpers */
static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
diff --git a/include/drm/drm_debugfs_crc.h b/include/drm/drm_debugfs_crc.h
new file mode 100644
index 000000000000..7d63b1d4adb9
--- /dev/null
+++ b/include/drm/drm_debugfs_crc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2016 Collabora Ltd.
+ *
+ * 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.
+ */
+#ifndef __DRM_DEBUGFS_CRC_H__
+#define __DRM_DEBUGFS_CRC_H__
+
+#define DRM_MAX_CRC_NR 10
+
+/**
+ * struct drm_crtc_crc_entry - entry describing a frame's content
+ * @has_frame_counter: whether the source was able to provide a frame number
+ * @frame: number of the frame this CRC is about, if @has_frame_counter is true
+ * @crc: array of values that characterize the frame
+ */
+struct drm_crtc_crc_entry {
+ bool has_frame_counter;
+ uint32_t frame;
+ uint32_t crcs[DRM_MAX_CRC_NR];
+};
+
+#define DRM_CRC_ENTRIES_NR 128
+
+/**
+ * struct drm_crtc_crc - data supporting CRC capture on a given CRTC
+ * @lock: protects the fields in this struct
+ * @source: name of the currently configured source of CRCs
+ * @opened: whether userspace has opened the data file for reading
+ * @entries: array of entries, with size of %DRM_CRC_ENTRIES_NR
+ * @head: head of circular queue
+ * @tail: tail of circular queue
+ * @values_cnt: number of CRC values per entry, up to %DRM_MAX_CRC_NR
+ * @wq: workqueue used to synchronize reading and writing
+ */
+struct drm_crtc_crc {
+ spinlock_t lock;
+ const char *source;
+ bool opened;
+ struct drm_crtc_crc_entry *entries;
+ int head, tail;
+ size_t values_cnt;
+ wait_queue_head_t wq;
+};
+
+#if defined(CONFIG_DEBUG_FS)
+int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
+ uint32_t frame, uint32_t *crcs);
+#else
+static inline int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
+ uint32_t frame, uint32_t *crcs)
+{
+ return -EINVAL;
+}
+#endif /* defined(CONFIG_DEBUG_FS) */
+
+#endif /* __DRM_DEBUGFS_CRC_H__ */
diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
index e8a9dfd0e055..4c42db81fcb4 100644
--- a/include/drm/drm_dp_dual_mode_helper.h
+++ b/include/drm/drm_dp_dual_mode_helper.h
@@ -40,6 +40,8 @@
#define DP_DUAL_MODE_REV_TYPE2 0x00
#define DP_DUAL_MODE_TYPE_MASK 0xf0
#define DP_DUAL_MODE_TYPE_TYPE2 0xa0
+/* This field is marked reserved in dual mode spec, used in LSPCON */
+#define DP_DUAL_MODE_TYPE_HAS_DPCD 0x08
#define DP_DUAL_MODE_IEEE_OUI 0x11 /* 11-13*/
#define DP_DUAL_IEEE_OUI_LEN 3
#define DP_DUAL_DEVICE_ID 0x14 /* 14-19 */
@@ -55,6 +57,11 @@
#define DP_DUAL_MODE_CEC_ENABLE 0x01
#define DP_DUAL_MODE_I2C_SPEED_CTRL 0x22
+/* LSPCON specific registers, defined by MCA */
+#define DP_DUAL_MODE_LSPCON_MODE_CHANGE 0x40
+#define DP_DUAL_MODE_LSPCON_CURRENT_MODE 0x41
+#define DP_DUAL_MODE_LSPCON_MODE_PCON 0x1
+
struct i2c_adapter;
ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
@@ -63,6 +70,20 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter,
u8 offset, const void *buffer, size_t size);
/**
+ * enum drm_lspcon_mode
+ * @DRM_LSPCON_MODE_INVALID: No LSPCON.
+ * @DRM_LSPCON_MODE_LS: Level shifter mode of LSPCON
+ * which drives DP++ to HDMI 1.4 conversion.
+ * @DRM_LSPCON_MODE_PCON: Protocol converter mode of LSPCON
+ * which drives DP++ to HDMI 2.0 active conversion.
+ */
+enum drm_lspcon_mode {
+ DRM_LSPCON_MODE_INVALID,
+ DRM_LSPCON_MODE_LS,
+ DRM_LSPCON_MODE_PCON,
+};
+
+/**
* enum drm_dp_dual_mode_type - Type of the DP dual mode adaptor
* @DRM_DP_DUAL_MODE_NONE: No DP dual mode adaptor
* @DRM_DP_DUAL_MODE_UNKNOWN: Could be either none or type 1 DVI adaptor
@@ -70,6 +91,7 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter,
* @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor
* @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor
* @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor
+ * @DRM_DP_DUAL_MODE_LSPCON: Level shifter / protocol converter
*/
enum drm_dp_dual_mode_type {
DRM_DP_DUAL_MODE_NONE,
@@ -78,6 +100,7 @@ enum drm_dp_dual_mode_type {
DRM_DP_DUAL_MODE_TYPE1_HDMI,
DRM_DP_DUAL_MODE_TYPE2_DVI,
DRM_DP_DUAL_MODE_TYPE2_HDMI,
+ DRM_DP_DUAL_MODE_LSPCON,
};
enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter);
@@ -89,4 +112,8 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
struct i2c_adapter *adapter, bool enable);
const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type);
+int drm_lspcon_get_mode(struct i2c_adapter *adapter,
+ enum drm_lspcon_mode *current_mode);
+int drm_lspcon_set_mode(struct i2c_adapter *adapter,
+ enum drm_lspcon_mode reqd_mode);
#endif
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 2a79882cb68e..55bbeb0ff594 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -690,6 +690,12 @@ drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED;
}
+static inline bool
+drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+ return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT;
+}
+
/*
* DisplayPort AUX channel
*/
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
new file mode 100644
index 000000000000..c4fc49583dc0
--- /dev/null
+++ b/include/drm/drm_drv.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * Copyright 2016 Intel Corp.
+ *
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 _DRM_DRV_H_
+#define _DRM_DRV_H_
+
+#include <linux/list.h>
+#include <linux/irqreturn.h>
+
+struct drm_device;
+struct drm_file;
+struct drm_gem_object;
+struct drm_master;
+struct drm_minor;
+struct dma_buf_attachment;
+struct drm_display_mode;
+struct drm_mode_create_dumb;
+
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP 0x1
+#define DRIVER_LEGACY 0x2
+#define DRIVER_PCI_DMA 0x8
+#define DRIVER_SG 0x10
+#define DRIVER_HAVE_DMA 0x20
+#define DRIVER_HAVE_IRQ 0x40
+#define DRIVER_IRQ_SHARED 0x80
+#define DRIVER_GEM 0x1000
+#define DRIVER_MODESET 0x2000
+#define DRIVER_PRIME 0x4000
+#define DRIVER_RENDER 0x8000
+#define DRIVER_ATOMIC 0x10000
+#define DRIVER_KMS_LEGACY_CONTEXT 0x20000
+
+/**
+ * struct drm_driver - DRM driver structure
+ *
+ * This structure represent the common code for a family of cards. There will
+ * one drm_device for each card present in this family. It contains lots of
+ * vfunc entries, and a pile of those probably should be moved to more
+ * appropriate places like &drm_mode_config_funcs or into a new operations
+ * structure for GEM drivers.
+ */
+struct drm_driver {
+ int (*load) (struct drm_device *, unsigned long flags);
+ int (*firstopen) (struct drm_device *);
+ int (*open) (struct drm_device *, struct drm_file *);
+ void (*preclose) (struct drm_device *, struct drm_file *file_priv);
+ void (*postclose) (struct drm_device *, struct drm_file *);
+ void (*lastclose) (struct drm_device *);
+ int (*unload) (struct drm_device *);
+ int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
+ int (*dma_quiescent) (struct drm_device *);
+ int (*context_dtor) (struct drm_device *dev, int context);
+ int (*set_busid)(struct drm_device *dev, struct drm_master *master);
+
+ /**
+ * @get_vblank_counter:
+ *
+ * Driver callback for fetching a raw hardware vblank counter for the
+ * CRTC specified with the pipe argument. If a device doesn't have a
+ * hardware counter, the driver can simply use
+ * drm_vblank_no_hw_counter() function. The DRM core will account for
+ * missed vblank events while interrupts where disabled based on system
+ * timestamps.
+ *
+ * Wraparound handling and loss of events due to modesetting is dealt
+ * with in the DRM core code, as long as drivers call
+ * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
+ * enabling a CRTC.
+ *
+ * Returns:
+ *
+ * Raw vblank counter value.
+ */
+ u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
+
+ /**
+ * @enable_vblank:
+ *
+ * Enable vblank interrupts for the CRTC specified with the pipe
+ * argument.
+ *
+ * Returns:
+ *
+ * Zero on success, appropriate errno if the given @crtc's vblank
+ * interrupt cannot be enabled.
+ */
+ int (*enable_vblank) (struct drm_device *dev, unsigned int pipe);
+
+ /**
+ * @disable_vblank:
+ *
+ * Disable vblank interrupts for the CRTC specified with the pipe
+ * argument.
+ */
+ void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
+
+ /**
+ * @device_is_agp:
+ *
+ * Called by drm_device_is_agp(). Typically used to determine if a card
+ * is really attached to AGP or not.
+ *
+ * Returns:
+ *
+ * One of three values is returned depending on whether or not the
+ * card is absolutely not AGP (return of 0), absolutely is AGP
+ * (return of 1), or may or may not be AGP (return of 2).
+ */
+ int (*device_is_agp) (struct drm_device *dev);
+
+ /**
+ * @get_scanout_position:
+ *
+ * Called by vblank timestamping code.
+ *
+ * Returns the current display scanout position from a crtc, and an
+ * optional accurate ktime_get() timestamp of when position was
+ * measured. Note that this is a helper callback which is only used if a
+ * driver uses drm_calc_vbltimestamp_from_scanoutpos() for the
+ * @get_vblank_timestamp callback.
+ *
+ * Parameters:
+ *
+ * dev:
+ * DRM device.
+ * pipe:
+ * Id of the crtc to query.
+ * flags:
+ * Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
+ * vpos:
+ * Target location for current vertical scanout position.
+ * hpos:
+ * Target location for current horizontal scanout position.
+ * stime:
+ * Target location for timestamp taken immediately before
+ * scanout position query. Can be NULL to skip timestamp.
+ * etime:
+ * Target location for timestamp taken immediately after
+ * scanout position query. Can be NULL to skip timestamp.
+ * mode:
+ * Current display timings.
+ *
+ * Returns vpos as a positive number while in active scanout area.
+ * Returns vpos as a negative number inside vblank, counting the number
+ * of scanlines to go until end of vblank, e.g., -1 means "one scanline
+ * until start of active scanout / end of vblank."
+ *
+ * Returns:
+ *
+ * Flags, or'ed together as follows:
+ *
+ * DRM_SCANOUTPOS_VALID:
+ * Query successful.
+ * DRM_SCANOUTPOS_INVBL:
+ * Inside vblank.
+ * DRM_SCANOUTPOS_ACCURATE: Returned position is accurate. A lack of
+ * this flag means that returned position may be offset by a
+ * constant but unknown small number of scanlines wrt. real scanout
+ * position.
+ *
+ */
+ int (*get_scanout_position) (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);
+
+ /**
+ * @get_vblank_timestamp:
+ *
+ * Called by drm_get_last_vbltimestamp(). Should return a precise
+ * timestamp when the most recent VBLANK interval ended or will end.
+ *
+ * Specifically, the timestamp in @vblank_time should correspond as
+ * closely as possible to the time when the first video scanline of
+ * the video frame after the end of VBLANK will start scanning out,
+ * the time immediately after end of the VBLANK interval. If the
+ * @crtc is currently inside VBLANK, this will be a time in the future.
+ * If the @crtc is currently scanning out a frame, this will be the
+ * past start time of the current scanout. This is meant to adhere
+ * to the OpenML OML_sync_control extension specification.
+ *
+ * Paramters:
+ *
+ * dev:
+ * dev DRM device handle.
+ * pipe:
+ * crtc for which timestamp should be returned.
+ * max_error:
+ * Maximum allowable timestamp error in nanoseconds.
+ * Implementation should strive to provide timestamp
+ * with an error of at most max_error nanoseconds.
+ * Returns true upper bound on error for timestamp.
+ * vblank_time:
+ * Target location for returned vblank timestamp.
+ * flags:
+ * 0 = Defaults, no special treatment needed.
+ * DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
+ * irq handler. Some drivers need to apply some workarounds
+ * for gpu-specific vblank irq quirks if flag is set.
+ *
+ * Returns:
+ *
+ * Zero if timestamping isn't supported in current display mode or a
+ * negative number on failure. A positive status code on success,
+ * which describes how the vblank_time timestamp was computed.
+ */
+ int (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
+ int *max_error,
+ struct timeval *vblank_time,
+ unsigned flags);
+
+ /* these have to be filled in */
+
+ irqreturn_t(*irq_handler) (int irq, void *arg);
+ void (*irq_preinstall) (struct drm_device *dev);
+ int (*irq_postinstall) (struct drm_device *dev);
+ void (*irq_uninstall) (struct drm_device *dev);
+
+ /**
+ * @master_create:
+ *
+ * Called whenever a new master is created. Only used by vmwgfx.
+ */
+ int (*master_create)(struct drm_device *dev, struct drm_master *master);
+
+ /**
+ * @master_destroy:
+ *
+ * Called whenever a master is destroyed. Only used by vmwgfx.
+ */
+ void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+
+ /**
+ * @master_set:
+ *
+ * Called whenever the minor master is set. Only used by vmwgfx.
+ */
+ int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
+ bool from_open);
+ /**
+ * @master_drop:
+ *
+ * Called whenever the minor master is dropped. Only used by vmwgfx.
+ */
+ void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv);
+
+ int (*debugfs_init)(struct drm_minor *minor);
+ void (*debugfs_cleanup)(struct drm_minor *minor);
+
+ /**
+ * @gem_free_object: deconstructor for drm_gem_objects
+ *
+ * This is deprecated and should not be used by new drivers. Use
+ * @gem_free_object_unlocked instead.
+ */
+ void (*gem_free_object) (struct drm_gem_object *obj);
+
+ /**
+ * @gem_free_object_unlocked: deconstructor for drm_gem_objects
+ *
+ * This is for drivers which are not encumbered with dev->struct_mutex
+ * legacy locking schemes. Use this hook instead of @gem_free_object.
+ */
+ void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
+
+ int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+ void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
+
+ /**
+ * @gem_create_object: constructor for gem objects
+ *
+ * Hook for allocating the GEM object struct, for use by core
+ * helpers.
+ */
+ struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
+ size_t size);
+
+ /* prime: */
+ /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
+ int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
+ uint32_t handle, uint32_t flags, int *prime_fd);
+ /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
+ int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
+ int prime_fd, uint32_t *handle);
+ /* export GEM -> dmabuf */
+ struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags);
+ /* import dmabuf -> GEM */
+ struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
+ struct dma_buf *dma_buf);
+ /* low-level interface used by drm_gem_prime_{import,export} */
+ int (*gem_prime_pin)(struct drm_gem_object *obj);
+ void (*gem_prime_unpin)(struct drm_gem_object *obj);
+ struct reservation_object * (*gem_prime_res_obj)(
+ struct drm_gem_object *obj);
+ struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
+ struct drm_gem_object *(*gem_prime_import_sg_table)(
+ struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt);
+ void *(*gem_prime_vmap)(struct drm_gem_object *obj);
+ void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
+ int (*gem_prime_mmap)(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
+
+ /* vga arb irq handler */
+ void (*vgaarb_irq)(struct drm_device *dev, bool state);
+
+ /**
+ * @dumb_create:
+ *
+ * This creates a new dumb buffer in the driver's backing storage manager (GEM,
+ * TTM or something else entirely) and returns the resulting buffer handle. This
+ * handle can then be wrapped up into a framebuffer modeset object.
+ *
+ * Note that userspace is not allowed to use such objects for render
+ * acceleration - drivers must create their own private ioctls for such a use
+ * case.
+ *
+ * Width, height and depth are specified in the &drm_mode_create_dumb
+ * argument. The callback needs to fill the handle, pitch and size for
+ * the created buffer.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_create)(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+ /**
+ * @dumb_map_offset:
+ *
+ * Allocate an offset in the drm device node's address space to be able to
+ * memory map a dumb buffer. GEM-based drivers must use
+ * drm_gem_create_mmap_offset() to implement this.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_map_offset)(struct drm_file *file_priv,
+ struct drm_device *dev, uint32_t handle,
+ uint64_t *offset);
+ /**
+ * @dumb_destroy:
+ *
+ * This destroys the userspace handle for the given dumb backing storage buffer.
+ * Since buffer objects must be reference counted in the kernel a buffer object
+ * won't be immediately freed if a framebuffer modeset object still uses it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_destroy)(struct drm_file *file_priv,
+ struct drm_device *dev,
+ uint32_t handle);
+
+ /* Driver private ops for this object */
+ const struct vm_operations_struct *gem_vm_ops;
+
+ int major;
+ int minor;
+ int patchlevel;
+ char *name;
+ char *desc;
+ char *date;
+
+ u32 driver_features;
+ int dev_priv_size;
+ const struct drm_ioctl_desc *ioctls;
+ int num_ioctls;
+ const struct file_operations *fops;
+
+ /* List of devices hanging off this driver with stealth attach. */
+ struct list_head legacy_dev_list;
+};
+
+extern __printf(6, 7)
+void drm_dev_printk(const struct device *dev, const char *level,
+ unsigned int category, const char *function_name,
+ const char *prefix, const char *format, ...);
+extern __printf(3, 4)
+void drm_printk(const char *level, unsigned int category,
+ const char *format, ...);
+extern unsigned int drm_debug;
+
+int drm_dev_init(struct drm_device *dev,
+ struct drm_driver *driver,
+ struct device *parent);
+struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+ struct device *parent);
+int drm_dev_register(struct drm_device *dev, unsigned long flags);
+void drm_dev_unregister(struct drm_device *dev);
+
+void drm_dev_ref(struct drm_device *dev);
+void drm_dev_unref(struct drm_device *dev);
+void drm_put_dev(struct drm_device *dev);
+void drm_unplug_dev(struct drm_device *dev);
+
+int drm_dev_set_unique(struct drm_device *dev, const char *name);
+
+
+#endif
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index c3a7d440bc11..38eabf65f19d 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -330,7 +330,6 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb);
int drm_av_sync_delay(struct drm_connector *connector,
const struct drm_display_mode *mode);
-struct drm_connector *drm_select_eld(struct drm_encoder *encoder);
#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
int drm_load_edid_firmware(struct drm_connector *connector);
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 387e33a4d6ee..c7438ff0d609 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -189,7 +189,7 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
}
/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
-static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc);
+static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index f313211f8ed5..3b00f6480b83 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -12,6 +12,8 @@ struct drm_fb_helper;
struct drm_device;
struct drm_file;
struct drm_mode_fb_cmd2;
+struct drm_plane;
+struct drm_plane_state;
struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc,
@@ -41,6 +43,9 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
+int drm_fb_cma_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *state);
+
#ifdef CONFIG_DEBUG_FS
struct seq_file;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index ed8edfef75b2..975deedd593e 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -228,7 +228,9 @@ struct drm_fb_helper {
.fb_set_par = drm_fb_helper_set_par, \
.fb_setcmap = drm_fb_helper_setcmap, \
.fb_blank = drm_fb_helper_blank, \
- .fb_pan_display = drm_fb_helper_pan_display
+ .fb_pan_display = drm_fb_helper_pan_display, \
+ .fb_debug_enter = drm_fb_helper_debug_enter, \
+ .fb_debug_leave = drm_fb_helper_debug_leave
#ifdef CONFIG_DRM_FBDEV_EMULATION
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 30c30fa87ee8..fcc08da850c8 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -25,14 +25,43 @@
#include <linux/types.h>
#include <uapi/drm/drm_fourcc.h>
+/**
+ * struct drm_format_info - information about a DRM format
+ * @format: 4CC format identifier (DRM_FORMAT_*)
+ * @depth: Color depth (number of bits per pixel excluding padding bits),
+ * valid for a subset of RGB formats only. This is a legacy field, do not
+ * use in new code and set to 0 for new formats.
+ * @num_planes: Number of color planes (1 to 3)
+ * @cpp: Number of bytes per pixel (per plane)
+ * @hsub: Horizontal chroma subsampling factor
+ * @vsub: Vertical chroma subsampling factor
+ */
+struct drm_format_info {
+ u32 format;
+ u8 depth;
+ u8 num_planes;
+ u8 cpp[3];
+ u8 hsub;
+ u8 vsub;
+};
+
+/**
+ * struct drm_format_name_buf - name of a DRM format
+ * @str: string buffer containing the format name
+ */
+struct drm_format_name_buf {
+ char str[32];
+};
+
+const struct drm_format_info *__drm_format_info(u32 format);
+const struct drm_format_info *drm_format_info(u32 format);
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
-void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp);
int drm_format_num_planes(uint32_t format);
int drm_format_plane_cpp(uint32_t format, int plane);
int drm_format_horz_chroma_subsampling(uint32_t format);
int drm_format_vert_chroma_subsampling(uint32_t format);
int drm_format_plane_width(int width, uint32_t format, int plane);
int drm_format_plane_height(int height, uint32_t format, int plane);
-char *drm_get_format_name(uint32_t format) __malloc;
+const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf);
#endif /* __DRM_FOURCC_H__ */
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index f5ae1f436a4b..1ddfa2928802 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -149,12 +149,12 @@ struct drm_framebuffer {
*/
unsigned int offsets[4];
/**
- * @modifier: Data layout modifier, per buffer. This is used to describe
+ * @modifier: Data layout modifier. This is used to describe
* tiling, or also special layouts (like compression) of auxiliary
* buffers. For userspace created object this is copied from
* drm_mode_fb_cmd2.
*/
- uint64_t modifier[4];
+ uint64_t modifier;
/**
* @width: Logical width of the visible area of the framebuffer, in
* pixels.
@@ -251,6 +251,24 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
}
/**
+ * drm_framebuffer_assign - store a reference to the fb
+ * @p: location to store framebuffer
+ * @fb: new framebuffer (maybe NULL)
+ *
+ * This functions sets the location to store a reference to the framebuffer,
+ * unreferencing the framebuffer that was previously stored in that location.
+ */
+static inline void drm_framebuffer_assign(struct drm_framebuffer **p,
+ struct drm_framebuffer *fb)
+{
+ if (fb)
+ drm_framebuffer_reference(fb);
+ if (*p)
+ drm_framebuffer_unreference(*p);
+ *p = fb;
+}
+
+/*
* drm_for_each_fb - iterate over all framebuffers
* @fb: the loop cursor
* @dev: the DRM device
diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h
index 2401b14d301f..293d08caab60 100644
--- a/include/drm/drm_irq.h
+++ b/include/drm/drm_irq.h
@@ -130,42 +130,37 @@ struct drm_vblank_crtc {
bool enabled;
};
-extern int drm_irq_install(struct drm_device *dev, int irq);
-extern int drm_irq_uninstall(struct drm_device *dev);
+int drm_irq_install(struct drm_device *dev, int irq);
+int drm_irq_uninstall(struct drm_device *dev);
-extern int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
-extern int drm_wait_vblank(struct drm_device *dev, void *data,
- struct drm_file *filp);
-extern u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe);
-extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
-extern u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
- struct timeval *vblanktime);
-extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
- struct drm_pending_vblank_event *e);
-extern void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
- struct drm_pending_vblank_event *e);
-extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
-extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
-extern int drm_crtc_vblank_get(struct drm_crtc *crtc);
-extern void drm_crtc_vblank_put(struct drm_crtc *crtc);
-extern void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
-extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
-extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe);
-extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe);
-extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
-extern void drm_crtc_vblank_reset(struct drm_crtc *crtc);
-extern void drm_crtc_vblank_on(struct drm_crtc *crtc);
-extern void drm_vblank_cleanup(struct drm_device *dev);
-extern u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
-extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
+int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
+u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
+u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
+ struct timeval *vblanktime);
+void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
+ struct drm_pending_vblank_event *e);
+void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
+ struct drm_pending_vblank_event *e);
+bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
+bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
+int drm_crtc_vblank_get(struct drm_crtc *crtc);
+void drm_crtc_vblank_put(struct drm_crtc *crtc);
+void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
+void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
+void drm_crtc_vblank_off(struct drm_crtc *crtc);
+void drm_crtc_vblank_reset(struct drm_crtc *crtc);
+void drm_crtc_vblank_on(struct drm_crtc *crtc);
+void drm_vblank_cleanup(struct drm_device *dev);
+u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
+u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
-extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
- unsigned int pipe, int *max_error,
- struct timeval *vblank_time,
- unsigned flags,
- const struct drm_display_mode *mode);
-extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
- const struct drm_display_mode *mode);
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
+ unsigned int pipe, int *max_error,
+ struct timeval *vblank_time,
+ unsigned flags,
+ const struct drm_display_mode *mode);
+void drm_calc_timestamping_constants(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode);
/**
* drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 205ddcf6d55d..0b8371795aeb 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -44,6 +44,9 @@
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
#endif
+#ifdef CONFIG_DRM_DEBUG_MM
+#include <linux/stackdepot.h>
+#endif
enum drm_mm_search_flags {
DRM_MM_SEARCH_DEFAULT = 0,
@@ -74,6 +77,9 @@ struct drm_mm_node {
u64 size;
u64 __subtree_last;
struct drm_mm *mm;
+#ifdef CONFIG_DRM_DEBUG_MM
+ depot_stack_handle_t stack;
+#endif
};
struct drm_mm {
@@ -302,10 +308,26 @@ void drm_mm_takedown(struct drm_mm *mm);
bool drm_mm_clean(struct drm_mm *mm);
struct drm_mm_node *
-drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
+__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
-struct drm_mm_node *
-drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last);
+/**
+ * drm_mm_for_each_node_in_range - iterator to walk over a range of
+ * allocated nodes
+ * @node__: drm_mm_node structure to assign to in each iteration step
+ * @mm__: drm_mm allocator to walk
+ * @start__: starting offset, the first node will overlap this
+ * @end__: ending offset, the last node will start before this (but may overlap)
+ *
+ * This iterator walks over all nodes in the range allocator that lie
+ * between @start and @end. It is implemented similarly to list_for_each(),
+ * but using the internal interval tree to accelerate the search for the
+ * starting node, and so not safe against removal of elements. It assumes
+ * that @end is within (or is the upper limit of) the drm_mm allocator.
+ */
+#define drm_mm_for_each_node_in_range(node__, mm__, start__, end__) \
+ for (node__ = __drm_mm_interval_first((mm__), (start__), (end__)-1); \
+ node__ && node__->start < (end__); \
+ node__ = list_next_entry(node__, node_list))
void drm_mm_init_scan(struct drm_mm *mm,
u64 size,
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
new file mode 100644
index 000000000000..bf9991b20611
--- /dev/null
+++ b/include/drm/drm_mode_config.h
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef __DRM_MODE_CONFIG_H__
+#define __DRM_MODE_CONFIG_H__
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/idr.h>
+#include <linux/workqueue.h>
+
+#include <drm/drm_modeset_lock.h>
+
+struct drm_file;
+struct drm_device;
+struct drm_atomic_state;
+struct drm_mode_fb_cmd2;
+
+/**
+ * struct drm_mode_config_funcs - basic driver provided mode setting functions
+ *
+ * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
+ * involve drivers.
+ */
+struct drm_mode_config_funcs {
+ /**
+ * @fb_create:
+ *
+ * Create a new framebuffer object. The core does basic checks on the
+ * requested metadata, but most of that is left to the driver. See
+ * struct &drm_mode_fb_cmd2 for details.
+ *
+ * If the parameters are deemed valid and the backing storage objects in
+ * the underlying memory manager all exist, then the driver allocates
+ * a new &drm_framebuffer structure, subclassed to contain
+ * driver-specific information (like the internal native buffer object
+ * references). It also needs to fill out all relevant metadata, which
+ * should be done by calling drm_helper_mode_fill_fb_struct().
+ *
+ * The initialization is finalized by calling drm_framebuffer_init(),
+ * which registers the framebuffer and makes it accessible to other
+ * threads.
+ *
+ * RETURNS:
+ *
+ * A new framebuffer with an initial reference count of 1 or a negative
+ * error code encoded with ERR_PTR().
+ */
+ struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
+ struct drm_file *file_priv,
+ const struct drm_mode_fb_cmd2 *mode_cmd);
+
+ /**
+ * @output_poll_changed:
+ *
+ * Callback used by helpers to inform the driver of output configuration
+ * changes.
+ *
+ * Drivers implementing fbdev emulation with the helpers can call
+ * drm_fb_helper_hotplug_changed from this hook to inform the fbdev
+ * helper of output changes.
+ *
+ * FIXME:
+ *
+ * Except that there's no vtable for device-level helper callbacks
+ * there's no reason this is a core function.
+ */
+ void (*output_poll_changed)(struct drm_device *dev);
+
+ /**
+ * @atomic_check:
+ *
+ * This is the only hook to validate an atomic modeset update. This
+ * function must reject any modeset and state changes which the hardware
+ * or driver doesn't support. This includes but is of course not limited
+ * to:
+ *
+ * - Checking that the modes, framebuffers, scaling and placement
+ * requirements and so on are within the limits of the hardware.
+ *
+ * - Checking that any hidden shared resources are not oversubscribed.
+ * This can be shared PLLs, shared lanes, overall memory bandwidth,
+ * display fifo space (where shared between planes or maybe even
+ * CRTCs).
+ *
+ * - Checking that virtualized resources exported to userspace are not
+ * oversubscribed. For various reasons it can make sense to expose
+ * more planes, crtcs or encoders than which are physically there. One
+ * example is dual-pipe operations (which generally should be hidden
+ * from userspace if when lockstepped in hardware, exposed otherwise),
+ * where a plane might need 1 hardware plane (if it's just on one
+ * pipe), 2 hardware planes (when it spans both pipes) or maybe even
+ * shared a hardware plane with a 2nd plane (if there's a compatible
+ * plane requested on the area handled by the other pipe).
+ *
+ * - Check that any transitional state is possible and that if
+ * requested, the update can indeed be done in the vblank period
+ * without temporarily disabling some functions.
+ *
+ * - Check any other constraints the driver or hardware might have.
+ *
+ * - This callback also needs to correctly fill out the &drm_crtc_state
+ * in this update to make sure that drm_atomic_crtc_needs_modeset()
+ * reflects the nature of the possible update and returns true if and
+ * only if the update cannot be applied without tearing within one
+ * vblank on that CRTC. The core uses that information to reject
+ * updates which require a full modeset (i.e. blanking the screen, or
+ * at least pausing updates for a substantial amount of time) if
+ * userspace has disallowed that in its request.
+ *
+ * - The driver also does not need to repeat basic input validation
+ * like done for the corresponding legacy entry points. The core does
+ * that before calling this hook.
+ *
+ * See the documentation of @atomic_commit for an exhaustive list of
+ * error conditions which don't have to be checked at the
+ * ->atomic_check() stage?
+ *
+ * See the documentation for struct &drm_atomic_state for how exactly
+ * an atomic modeset update is described.
+ *
+ * Drivers using the atomic helpers can implement this hook using
+ * drm_atomic_helper_check(), or one of the exported sub-functions of
+ * it.
+ *
+ * RETURNS:
+ *
+ * 0 on success or one of the below negative error codes:
+ *
+ * - -EINVAL, if any of the above constraints are violated.
+ *
+ * - -EDEADLK, when returned from an attempt to acquire an additional
+ * &drm_modeset_lock through drm_modeset_lock().
+ *
+ * - -ENOMEM, if allocating additional state sub-structures failed due
+ * to lack of memory.
+ *
+ * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted.
+ * This can either be due to a pending signal, or because the driver
+ * needs to completely bail out to recover from an exceptional
+ * situation like a GPU hang. From a userspace point all errors are
+ * treated equally.
+ */
+ int (*atomic_check)(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
+ /**
+ * @atomic_commit:
+ *
+ * This is the only hook to commit an atomic modeset update. The core
+ * guarantees that @atomic_check has been called successfully before
+ * calling this function, and that nothing has been changed in the
+ * interim.
+ *
+ * See the documentation for struct &drm_atomic_state for how exactly
+ * an atomic modeset update is described.
+ *
+ * Drivers using the atomic helpers can implement this hook using
+ * drm_atomic_helper_commit(), or one of the exported sub-functions of
+ * it.
+ *
+ * Nonblocking commits (as indicated with the nonblock parameter) must
+ * do any preparatory work which might result in an unsuccessful commit
+ * in the context of this callback. The only exceptions are hardware
+ * errors resulting in -EIO. But even in that case the driver must
+ * ensure that the display pipe is at least running, to avoid
+ * compositors crashing when pageflips don't work. Anything else,
+ * specifically committing the update to the hardware, should be done
+ * without blocking the caller. For updates which do not require a
+ * modeset this must be guaranteed.
+ *
+ * The driver must wait for any pending rendering to the new
+ * framebuffers to complete before executing the flip. It should also
+ * wait for any pending rendering from other drivers if the underlying
+ * buffer is a shared dma-buf. Nonblocking commits must not wait for
+ * rendering in the context of this callback.
+ *
+ * An application can request to be notified when the atomic commit has
+ * completed. These events are per-CRTC and can be distinguished by the
+ * CRTC index supplied in &drm_event to userspace.
+ *
+ * The drm core will supply a struct &drm_event in the event
+ * member of each CRTC's &drm_crtc_state structure. See the
+ * documentation for &drm_crtc_state for more details about the precise
+ * semantics of this event.
+ *
+ * NOTE:
+ *
+ * Drivers are not allowed to shut down any display pipe successfully
+ * enabled through an atomic commit on their own. Doing so can result in
+ * compositors crashing if a page flip is suddenly rejected because the
+ * pipe is off.
+ *
+ * RETURNS:
+ *
+ * 0 on success or one of the below negative error codes:
+ *
+ * - -EBUSY, if a nonblocking updated is requested and there is
+ * an earlier updated pending. Drivers are allowed to support a queue
+ * of outstanding updates, but currently no driver supports that.
+ * Note that drivers must wait for preceding updates to complete if a
+ * synchronous update is requested, they are not allowed to fail the
+ * commit in that case.
+ *
+ * - -ENOMEM, if the driver failed to allocate memory. Specifically
+ * this can happen when trying to pin framebuffers, which must only
+ * be done when committing the state.
+ *
+ * - -ENOSPC, as a refinement of the more generic -ENOMEM to indicate
+ * that the driver has run out of vram, iommu space or similar GPU
+ * address space needed for framebuffer.
+ *
+ * - -EIO, if the hardware completely died.
+ *
+ * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted.
+ * This can either be due to a pending signal, or because the driver
+ * needs to completely bail out to recover from an exceptional
+ * situation like a GPU hang. From a userspace point of view all errors are
+ * treated equally.
+ *
+ * This list is exhaustive. Specifically this hook is not allowed to
+ * return -EINVAL (any invalid requests should be caught in
+ * @atomic_check) or -EDEADLK (this function must not acquire
+ * additional modeset locks).
+ */
+ int (*atomic_commit)(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ bool nonblock);
+
+ /**
+ * @atomic_state_alloc:
+ *
+ * This optional hook can be used by drivers that want to subclass struct
+ * &drm_atomic_state to be able to track their own driver-private global
+ * state easily. If this hook is implemented, drivers must also
+ * implement @atomic_state_clear and @atomic_state_free.
+ *
+ * RETURNS:
+ *
+ * A new &drm_atomic_state on success or NULL on failure.
+ */
+ struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
+
+ /**
+ * @atomic_state_clear:
+ *
+ * This hook must clear any driver private state duplicated into the
+ * passed-in &drm_atomic_state. This hook is called when the caller
+ * encountered a &drm_modeset_lock deadlock and needs to drop all
+ * already acquired locks as part of the deadlock avoidance dance
+ * implemented in drm_modeset_lock_backoff().
+ *
+ * Any duplicated state must be invalidated since a concurrent atomic
+ * update might change it, and the drm atomic interfaces always apply
+ * updates as relative changes to the current state.
+ *
+ * Drivers that implement this must call drm_atomic_state_default_clear()
+ * to clear common state.
+ */
+ void (*atomic_state_clear)(struct drm_atomic_state *state);
+
+ /**
+ * @atomic_state_free:
+ *
+ * This hook needs driver private resources and the &drm_atomic_state
+ * itself. Note that the core first calls drm_atomic_state_clear() to
+ * avoid code duplicate between the clear and free hooks.
+ *
+ * Drivers that implement this must call drm_atomic_state_default_free()
+ * to release common resources.
+ */
+ void (*atomic_state_free)(struct drm_atomic_state *state);
+};
+
+/**
+ * struct drm_mode_config - Mode configuration control structure
+ * @mutex: mutex protecting KMS related lists and structures
+ * @connection_mutex: ww mutex protecting connector state and routing
+ * @acquire_ctx: global implicit acquire context used by atomic drivers for
+ * legacy IOCTLs
+ * @fb_lock: mutex to protect fb state and lists
+ * @num_fb: number of fbs available
+ * @fb_list: list of framebuffers available
+ * @num_encoder: number of encoders on this device
+ * @encoder_list: list of encoder objects
+ * @num_overlay_plane: number of overlay planes on this device
+ * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device
+ * @plane_list: list of plane objects
+ * @num_crtc: number of CRTCs on this device
+ * @crtc_list: list of CRTC objects
+ * @property_list: list of property objects
+ * @min_width: minimum pixel width on this device
+ * @min_height: minimum pixel height on this device
+ * @max_width: maximum pixel width on this device
+ * @max_height: maximum pixel height on this device
+ * @funcs: core driver provided mode setting functions
+ * @fb_base: base address of the framebuffer
+ * @poll_enabled: track polling support for this device
+ * @poll_running: track polling status for this device
+ * @delayed_event: track delayed poll uevent deliver for this device
+ * @output_poll_work: delayed work for polling in process context
+ * @property_blob_list: list of all the blob property objects
+ * @blob_lock: mutex for blob property allocation and management
+ * @*_property: core property tracking
+ * @preferred_depth: preferred RBG pixel depth, used by fb helpers
+ * @prefer_shadow: hint to userspace to prefer shadow-fb rendering
+ * @cursor_width: hint to userspace for max cursor width
+ * @cursor_height: hint to userspace for max cursor height
+ * @helper_private: mid-layer private data
+ *
+ * Core mode resource tracking structure. All CRTC, encoders, and connectors
+ * enumerated by the driver are added here, as are global properties. Some
+ * global restrictions are also here, e.g. dimension restrictions.
+ */
+struct drm_mode_config {
+ struct mutex mutex; /* protects configuration (mode lists etc.) */
+ struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
+ struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
+
+ /**
+ * @idr_mutex:
+ *
+ * Mutex for KMS ID allocation and management. Protects both @crtc_idr
+ * and @tile_idr.
+ */
+ struct mutex idr_mutex;
+
+ /**
+ * @crtc_idr:
+ *
+ * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc,
+ * connector, modes - just makes life easier to have only one.
+ */
+ struct idr crtc_idr;
+
+ /**
+ * @tile_idr:
+ *
+ * Use this idr for allocating new IDs for tiled sinks like use in some
+ * high-res DP MST screens.
+ */
+ struct idr tile_idr;
+
+ struct mutex fb_lock; /* proctects global and per-file fb lists */
+ int num_fb;
+ struct list_head fb_list;
+
+ /**
+ * @num_connector: Number of connectors on this device.
+ */
+ int num_connector;
+ /**
+ * @connector_ida: ID allocator for connector indices.
+ */
+ struct ida connector_ida;
+ /**
+ * @connector_list: List of connector objects.
+ */
+ struct list_head connector_list;
+ int num_encoder;
+ struct list_head encoder_list;
+
+ /*
+ * Track # of overlay planes separately from # of total planes. By
+ * default we only advertise overlay planes to userspace; if userspace
+ * sets the "universal plane" capability bit, we'll go ahead and
+ * expose all planes.
+ */
+ int num_overlay_plane;
+ int num_total_plane;
+ struct list_head plane_list;
+
+ int num_crtc;
+ struct list_head crtc_list;
+
+ struct list_head property_list;
+
+ int min_width, min_height;
+ int max_width, max_height;
+ const struct drm_mode_config_funcs *funcs;
+ resource_size_t fb_base;
+
+ /* output poll support */
+ bool poll_enabled;
+ bool poll_running;
+ bool delayed_event;
+ struct delayed_work output_poll_work;
+
+ struct mutex blob_lock;
+
+ /* pointers to standard properties */
+ struct list_head property_blob_list;
+ /**
+ * @edid_property: Default connector property to hold the EDID of the
+ * currently connected sink, if any.
+ */
+ struct drm_property *edid_property;
+ /**
+ * @dpms_property: Default connector property to control the
+ * connector's DPMS state.
+ */
+ struct drm_property *dpms_property;
+ /**
+ * @path_property: Default connector property to hold the DP MST path
+ * for the port.
+ */
+ struct drm_property *path_property;
+ /**
+ * @tile_property: Default connector property to store the tile
+ * position of a tiled screen, for sinks which need to be driven with
+ * multiple CRTCs.
+ */
+ struct drm_property *tile_property;
+ /**
+ * @plane_type_property: Default plane property to differentiate
+ * CURSOR, PRIMARY and OVERLAY legacy uses of planes.
+ */
+ struct drm_property *plane_type_property;
+ /**
+ * @prop_src_x: Default atomic plane property for the plane source
+ * position in the connected &drm_framebuffer.
+ */
+ struct drm_property *prop_src_x;
+ /**
+ * @prop_src_y: Default atomic plane property for the plane source
+ * position in the connected &drm_framebuffer.
+ */
+ struct drm_property *prop_src_y;
+ /**
+ * @prop_src_w: Default atomic plane property for the plane source
+ * position in the connected &drm_framebuffer.
+ */
+ struct drm_property *prop_src_w;
+ /**
+ * @prop_src_h: Default atomic plane property for the plane source
+ * position in the connected &drm_framebuffer.
+ */
+ struct drm_property *prop_src_h;
+ /**
+ * @prop_crtc_x: Default atomic plane property for the plane destination
+ * position in the &drm_crtc is is being shown on.
+ */
+ struct drm_property *prop_crtc_x;
+ /**
+ * @prop_crtc_y: Default atomic plane property for the plane destination
+ * position in the &drm_crtc is is being shown on.
+ */
+ struct drm_property *prop_crtc_y;
+ /**
+ * @prop_crtc_w: Default atomic plane property for the plane destination
+ * position in the &drm_crtc is is being shown on.
+ */
+ struct drm_property *prop_crtc_w;
+ /**
+ * @prop_crtc_h: Default atomic plane property for the plane destination
+ * position in the &drm_crtc is is being shown on.
+ */
+ struct drm_property *prop_crtc_h;
+ /**
+ * @prop_fb_id: Default atomic plane property to specify the
+ * &drm_framebuffer.
+ */
+ struct drm_property *prop_fb_id;
+ /**
+ * @prop_in_fence_fd: Sync File fd representing the incoming fences
+ * for a Plane.
+ */
+ struct drm_property *prop_in_fence_fd;
+ /**
+ * @prop_out_fence_ptr: Sync File fd pointer representing the
+ * outgoing fences for a CRTC. Userspace should provide a pointer to a
+ * value of type s64, and then cast that pointer to u64.
+ */
+ struct drm_property *prop_out_fence_ptr;
+ /**
+ * @prop_crtc_id: Default atomic plane property to specify the
+ * &drm_crtc.
+ */
+ struct drm_property *prop_crtc_id;
+ /**
+ * @prop_active: Default atomic CRTC property to control the active
+ * state, which is the simplified implementation for DPMS in atomic
+ * drivers.
+ */
+ struct drm_property *prop_active;
+ /**
+ * @prop_mode_id: Default atomic CRTC property to set the mode for a
+ * CRTC. A 0 mode implies that the CRTC is entirely disabled - all
+ * connectors must be of and active must be set to disabled, too.
+ */
+ struct drm_property *prop_mode_id;
+
+ /**
+ * @dvi_i_subconnector_property: Optional DVI-I property to
+ * differentiate between analog or digital mode.
+ */
+ struct drm_property *dvi_i_subconnector_property;
+ /**
+ * @dvi_i_select_subconnector_property: Optional DVI-I property to
+ * select between analog or digital mode.
+ */
+ struct drm_property *dvi_i_select_subconnector_property;
+
+ /**
+ * @tv_subconnector_property: Optional TV property to differentiate
+ * between different TV connector types.
+ */
+ struct drm_property *tv_subconnector_property;
+ /**
+ * @tv_select_subconnector_property: Optional TV property to select
+ * between different TV connector types.
+ */
+ struct drm_property *tv_select_subconnector_property;
+ /**
+ * @tv_mode_property: Optional TV property to select
+ * the output TV mode.
+ */
+ struct drm_property *tv_mode_property;
+ /**
+ * @tv_left_margin_property: Optional TV property to set the left
+ * margin.
+ */
+ struct drm_property *tv_left_margin_property;
+ /**
+ * @tv_right_margin_property: Optional TV property to set the right
+ * margin.
+ */
+ struct drm_property *tv_right_margin_property;
+ /**
+ * @tv_top_margin_property: Optional TV property to set the right
+ * margin.
+ */
+ struct drm_property *tv_top_margin_property;
+ /**
+ * @tv_bottom_margin_property: Optional TV property to set the right
+ * margin.
+ */
+ struct drm_property *tv_bottom_margin_property;
+ /**
+ * @tv_brightness_property: Optional TV property to set the
+ * brightness.
+ */
+ struct drm_property *tv_brightness_property;
+ /**
+ * @tv_contrast_property: Optional TV property to set the
+ * contrast.
+ */
+ struct drm_property *tv_contrast_property;
+ /**
+ * @tv_flicker_reduction_property: Optional TV property to control the
+ * flicker reduction mode.
+ */
+ struct drm_property *tv_flicker_reduction_property;
+ /**
+ * @tv_overscan_property: Optional TV property to control the overscan
+ * setting.
+ */
+ struct drm_property *tv_overscan_property;
+ /**
+ * @tv_saturation_property: Optional TV property to set the
+ * saturation.
+ */
+ struct drm_property *tv_saturation_property;
+ /**
+ * @tv_hue_property: Optional TV property to set the hue.
+ */
+ struct drm_property *tv_hue_property;
+
+ /**
+ * @scaling_mode_property: Optional connector property to control the
+ * upscaling, mostly used for built-in panels.
+ */
+ struct drm_property *scaling_mode_property;
+ /**
+ * @aspect_ratio_property: Optional connector property to control the
+ * HDMI infoframe aspect ratio setting.
+ */
+ struct drm_property *aspect_ratio_property;
+ /**
+ * @degamma_lut_property: Optional CRTC property to set the LUT used to
+ * convert the framebuffer's colors to linear gamma.
+ */
+ struct drm_property *degamma_lut_property;
+ /**
+ * @degamma_lut_size_property: Optional CRTC property for the size of
+ * the degamma LUT as supported by the driver (read-only).
+ */
+ struct drm_property *degamma_lut_size_property;
+ /**
+ * @ctm_property: Optional CRTC property to set the
+ * matrix used to convert colors after the lookup in the
+ * degamma LUT.
+ */
+ struct drm_property *ctm_property;
+ /**
+ * @gamma_lut_property: Optional CRTC property to set the LUT used to
+ * convert the colors, after the CTM matrix, to the gamma space of the
+ * connected screen.
+ */
+ struct drm_property *gamma_lut_property;
+ /**
+ * @gamma_lut_size_property: Optional CRTC property for the size of the
+ * gamma LUT as supported by the driver (read-only).
+ */
+ struct drm_property *gamma_lut_size_property;
+
+ /**
+ * @suggested_x_property: Optional connector property with a hint for
+ * the position of the output on the host's screen.
+ */
+ struct drm_property *suggested_x_property;
+ /**
+ * @suggested_y_property: Optional connector property with a hint for
+ * the position of the output on the host's screen.
+ */
+ struct drm_property *suggested_y_property;
+
+ /* dumb ioctl parameters */
+ uint32_t preferred_depth, prefer_shadow;
+
+ /**
+ * @async_page_flip: Does this device support async flips on the primary
+ * plane?
+ */
+ bool async_page_flip;
+
+ /**
+ * @allow_fb_modifiers:
+ *
+ * Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call.
+ */
+ bool allow_fb_modifiers;
+
+ /* cursor size */
+ uint32_t cursor_width, cursor_height;
+
+ struct drm_mode_config_helper_funcs *helper_private;
+};
+
+void drm_mode_config_init(struct drm_device *dev);
+void drm_mode_config_reset(struct drm_device *dev);
+void drm_mode_config_cleanup(struct drm_device *dev);
+
+#endif
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 10e449c86dbd..69c3974bf133 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -361,8 +361,8 @@ struct drm_crtc_helper_funcs {
*
* Note that the power state of the display pipe when this function is
* called depends upon the exact helpers and calling sequence the driver
- * has picked. See drm_atomic_commit_planes() for a discussion of the
- * tradeoffs and variants of plane commit helpers.
+ * has picked. See drm_atomic_helper_commit_planes() for a discussion of
+ * the tradeoffs and variants of plane commit helpers.
*
* This callback is used by the atomic modeset helpers and by the
* transitional plane helpers, but it is optional.
@@ -385,8 +385,8 @@ struct drm_crtc_helper_funcs {
*
* Note that the power state of the display pipe when this function is
* called depends upon the exact helpers and calling sequence the driver
- * has picked. See drm_atomic_commit_planes() for a discussion of the
- * tradeoffs and variants of plane commit helpers.
+ * has picked. See drm_atomic_helper_commit_planes() for a discussion of
+ * the tradeoffs and variants of plane commit helpers.
*
* This callback is used by the atomic modeset helpers and by the
* transitional plane helpers, but it is optional.
@@ -940,8 +940,8 @@ struct drm_plane_helper_funcs {
*
* Note that the power state of the display pipe when this function is
* called depends upon the exact helpers and calling sequence the driver
- * has picked. See drm_atomic_commit_planes() for a discussion of the
- * tradeoffs and variants of plane commit helpers.
+ * has picked. See drm_atomic_helper_commit_planes() for a discussion of
+ * the tradeoffs and variants of plane commit helpers.
*
* This callback is used by the atomic modeset helpers and by the
* transitional plane helpers, but it is optional.
@@ -963,8 +963,8 @@ struct drm_plane_helper_funcs {
*
* Note that the power state of the display pipe when this function is
* called depends upon the exact helpers and calling sequence the driver
- * has picked. See drm_atomic_commit_planes() for a discussion of the
- * tradeoffs and variants of plane commit helpers.
+ * has picked. See drm_atomic_helper_commit_planes() for a discussion of
+ * the tradeoffs and variants of plane commit helpers.
*
* This callback is used by the atomic modeset helpers and by the
* transitional plane helpers, but it is optional.
@@ -999,10 +999,14 @@ struct drm_mode_config_helper_funcs {
* to implement blocking and nonblocking commits easily. It is not used
* by the atomic helpers
*
- * This hook should first commit the given atomic state to the hardware.
- * But drivers can add more waiting calls at the start of their
- * implementation, e.g. to wait for driver-internal request for implicit
- * syncing, before starting to commit the update to the hardware.
+ * This function is called when the new atomic state has already been
+ * swapped into the various state pointers. The passed in state
+ * therefore contains copies of the old/previous state. This hook should
+ * commit the new state into hardware. Note that the helpers have
+ * already waited for preceeding atomic commits and fences, but drivers
+ * can add more waiting calls at the start of their implementation, e.g.
+ * to wait for driver-internal request for implicit syncing, before
+ * starting to commit the update to the hardware.
*
* After the atomic update is committed to the hardware this hook needs
* to call drm_atomic_helper_commit_hw_done(). Then wait for the upate
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index c5576fbcb909..d918ce45ec2c 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -82,8 +82,6 @@ struct drm_modeset_lock {
struct list_head head;
};
-extern struct ww_class crtc_ww_class;
-
void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
uint32_t flags);
void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
@@ -91,15 +89,7 @@ void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx);
void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx);
int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx *ctx);
-/**
- * drm_modeset_lock_init - initialize lock
- * @lock: lock to init
- */
-static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock)
-{
- ww_mutex_init(&lock->mutex, &crtc_ww_class);
- INIT_LIST_HEAD(&lock->head);
-}
+void drm_modeset_lock_init(struct drm_modeset_lock *lock);
/**
* drm_modeset_lock_fini - cleanup lock
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index 3fd87b386ed7..26a64805cc15 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -4,6 +4,7 @@
#include <linux/of_graph.h>
struct component_master_ops;
+struct component_match;
struct device;
struct drm_device;
struct drm_encoder;
@@ -12,6 +13,10 @@ struct device_node;
#ifdef CONFIG_OF
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port);
+extern void drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node);
extern int drm_of_component_probe(struct device *dev,
int (*compare_of)(struct device *, void *),
const struct component_master_ops *m_ops);
@@ -25,6 +30,14 @@ static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
return 0;
}
+static inline void
+drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node)
+{
+}
+
static inline int
drm_of_component_probe(struct device *dev,
int (*compare_of)(struct device *, void *),
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 8b4dc62470ff..db3bbdeb36d5 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -28,15 +28,11 @@
#include <drm/drm_mode_object.h>
struct drm_crtc;
+struct drm_printer;
/**
* struct drm_plane_state - mutable plane state
* @plane: backpointer to the plane
- * @crtc: currently bound CRTC, NULL if disabled
- * @fb: currently bound framebuffer
- * @fence: optional fence to wait for before scanning out @fb
- * @crtc_x: left position of visible portion of plane on crtc
- * @crtc_y: upper position of visible portion of plane on crtc
* @crtc_w: width of visible portion of plane on crtc
* @crtc_h: height of visible portion of plane on crtc
* @src_x: left position of visible portion of plane within
@@ -57,18 +53,51 @@ struct drm_crtc;
* it can be trusted.
* @src: clipped source coordinates of the plane (in 16.16)
* @dst: clipped destination coordinates of the plane
- * @visible: visibility of the plane
* @state: backpointer to global drm_atomic_state
*/
struct drm_plane_state {
struct drm_plane *plane;
- struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
- struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
- struct fence *fence;
+ /**
+ * @crtc:
+ *
+ * Currently bound CRTC, NULL if disabled. Do not this write directly,
+ * use drm_atomic_set_crtc_for_plane()
+ */
+ struct drm_crtc *crtc;
+
+ /**
+ * @fb:
+ *
+ * Currently bound framebuffer. Do not write this directly, use
+ * drm_atomic_set_fb_for_plane()
+ */
+ struct drm_framebuffer *fb;
+
+ /**
+ * @fence:
+ *
+ * Optional fence to wait for before scanning out @fb. Do not write this
+ * directly, use drm_atomic_set_fence_for_plane()
+ */
+ struct dma_fence *fence;
+
+ /**
+ * @crtc_x:
+ *
+ * Left position of visible portion of plane on crtc, signed dest
+ * location allows it to be partially off screen.
+ */
+
+ int32_t crtc_x;
+ /**
+ * @crtc_y:
+ *
+ * Upper position of visible portion of plane on crtc, signed dest
+ * location allows it to be partially off screen.
+ */
+ int32_t crtc_y;
- /* Signed dest location allows it to be partially off screen */
- int32_t crtc_x, crtc_y;
uint32_t crtc_w, crtc_h;
/* Source values are 16.16 fixed point */
@@ -85,15 +114,40 @@ struct drm_plane_state {
/* Clipped coordinates */
struct drm_rect src, dst;
- /*
- * Is the plane actually visible? Can be false even
- * if fb!=NULL and crtc!=NULL, due to clipping.
+ /**
+ * @visible:
+ *
+ * Visibility of the plane. This can be false even if fb!=NULL and
+ * crtc!=NULL, due to clipping.
*/
bool visible;
struct drm_atomic_state *state;
};
+static inline struct drm_rect
+drm_plane_state_src(const struct drm_plane_state *state)
+{
+ struct drm_rect src = {
+ .x1 = state->src_x,
+ .y1 = state->src_y,
+ .x2 = state->src_x + state->src_w,
+ .y2 = state->src_y + state->src_h,
+ };
+ return src;
+}
+
+static inline struct drm_rect
+drm_plane_state_dest(const struct drm_plane_state *state)
+{
+ struct drm_rect dest = {
+ .x1 = state->crtc_x,
+ .y1 = state->crtc_y,
+ .x2 = state->crtc_x + state->crtc_w,
+ .y2 = state->crtc_y + state->crtc_h,
+ };
+ return dest;
+}
/**
* struct drm_plane_funcs - driver plane control functions
@@ -323,6 +377,18 @@ struct drm_plane_funcs {
* before data structures are torndown.
*/
void (*early_unregister)(struct drm_plane *plane);
+
+ /**
+ * @atomic_print_state:
+ *
+ * If driver subclasses struct &drm_plane_state, it should implement
+ * this optional hook for printing additional driver specific state.
+ *
+ * Do not call this directly, use drm_atomic_plane_print_state()
+ * instead.
+ */
+ void (*atomic_print_state)(struct drm_printer *p,
+ const struct drm_plane_state *state);
};
/**
@@ -392,6 +458,7 @@ enum drm_plane_type {
* @type: type of plane (overlay, primary, cursor)
* @state: current atomic state for this plane
* @zpos_property: zpos property for this plane
+ * @rotation_property: rotation property for this plane
* @helper_private: mid-layer private data
*/
struct drm_plane {
@@ -438,6 +505,7 @@ struct drm_plane {
struct drm_plane_state *state;
struct drm_property *zpos_property;
+ struct drm_property *rotation_property;
};
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
@@ -445,7 +513,7 @@ struct drm_plane {
extern __printf(8, 9)
int drm_universal_plane_init(struct drm_device *dev,
struct drm_plane *plane,
- unsigned long possible_crtcs,
+ uint32_t possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats,
unsigned int format_count,
@@ -453,7 +521,7 @@ int drm_universal_plane_init(struct drm_device *dev,
const char *name, ...);
extern int drm_plane_init(struct drm_device *dev,
struct drm_plane *plane,
- unsigned long possible_crtcs,
+ uint32_t possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats, unsigned int format_count,
bool is_primary);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
new file mode 100644
index 000000000000..1adf84aea622
--- /dev/null
+++ b/include/drm/drm_print.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * 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:
+ * Rob Clark <robdclark@gmail.com>
+ */
+
+#ifndef DRM_PRINT_H_
+#define DRM_PRINT_H_
+
+#include <linux/seq_file.h>
+#include <linux/device.h>
+
+/**
+ * DOC: print
+ *
+ * A simple wrapper for dev_printk(), seq_printf(), etc. Allows same
+ * debug code to be used for both debugfs and printk logging.
+ *
+ * For example::
+ *
+ * void log_some_info(struct drm_printer *p)
+ * {
+ * drm_printf(p, "foo=%d\n", foo);
+ * drm_printf(p, "bar=%d\n", bar);
+ * }
+ *
+ * #ifdef CONFIG_DEBUG_FS
+ * void debugfs_show(struct seq_file *f)
+ * {
+ * struct drm_printer p = drm_seq_file_printer(f);
+ * log_some_info(&p);
+ * }
+ * #endif
+ *
+ * void some_other_function(...)
+ * {
+ * struct drm_printer p = drm_info_printer(drm->dev);
+ * log_some_info(&p);
+ * }
+ */
+
+/**
+ * struct drm_printer - drm output "stream"
+ * @printfn: actual output fxn
+ * @arg: output fxn specific data
+ *
+ * Do not use struct members directly. Use drm_printer_seq_file(),
+ * drm_printer_info(), etc to initialize. And drm_printf() for output.
+ */
+struct drm_printer {
+ void (*printfn)(struct drm_printer *p, struct va_format *vaf);
+ void *arg;
+};
+
+void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
+void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
+
+void drm_printf(struct drm_printer *p, const char *f, ...);
+
+
+/**
+ * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
+ * @f: the struct &seq_file to output to
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer drm_seq_file_printer(struct seq_file *f)
+{
+ struct drm_printer p = {
+ .printfn = __drm_printfn_seq_file,
+ .arg = f,
+ };
+ return p;
+}
+
+/**
+ * drm_info_printer - construct a &drm_printer that outputs to dev_printk()
+ * @dev: the struct &device pointer
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer drm_info_printer(struct device *dev)
+{
+ struct drm_printer p = {
+ .printfn = __drm_printfn_info,
+ .arg = dev,
+ };
+ return p;
+}
+
+#endif /* DRM_PRINT_H_ */
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index b46fa0ef3005..545c6e0fea7d 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -64,7 +64,7 @@ struct i915_audio_component_ops {
* Called from audio driver. After audio driver sets the
* sample rate, it will call this function to set n/cts
*/
- int (*sync_audio_rate)(struct device *, int port, int rate);
+ int (*sync_audio_rate)(struct device *, int port, int pipe, int rate);
/**
* @get_eld: fill the audio state and ELD bytes for the given port
*
@@ -77,7 +77,7 @@ struct i915_audio_component_ops {
* Note that the returned size may be over @max_bytes. Then it
* implies that only a part of ELD has been copied to the buffer.
*/
- int (*get_eld)(struct device *, int port, bool *enabled,
+ int (*get_eld)(struct device *, int port, int pipe, bool *enabled,
unsigned char *buf, int max_bytes);
};
@@ -97,7 +97,7 @@ struct i915_audio_component_audio_ops {
* status accordingly (even when the HDA controller is in power save
* mode).
*/
- void (*pin_eld_notify)(void *audio_ptr, int port);
+ void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
};
/**
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 9eb940d6755f..652e45be97c8 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -47,6 +47,8 @@ struct drm_mm_node;
struct ttm_placement;
+struct ttm_place;
+
/**
* struct ttm_bus_placement
*
@@ -209,7 +211,7 @@ struct ttm_buffer_object {
* Members protected by a bo reservation.
*/
- struct fence *moving;
+ struct dma_fence *moving;
struct drm_vma_offset_node vma_node;
@@ -396,6 +398,17 @@ extern void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev,
int resched);
/**
+ * ttm_bo_eviction_valuable
+ *
+ * @bo: The buffer object to evict
+ * @place: the placement we need to make room for
+ *
+ * Check if it is valuable to evict the BO to make room for the given placement.
+ */
+bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
+ const struct ttm_place *place);
+
+/**
* ttm_bo_synccpu_write_grab
*
* @bo: The buffer object:
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 4f0a92185995..cdbdb40eb5bd 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -303,7 +303,7 @@ struct ttm_mem_type_manager {
/*
* Protected by @move_lock.
*/
- struct fence *move;
+ struct dma_fence *move;
};
/**
@@ -371,9 +371,21 @@ struct ttm_bo_driver {
* submission as a consequence.
*/
- int (*invalidate_caches) (struct ttm_bo_device *bdev, uint32_t flags);
- int (*init_mem_type) (struct ttm_bo_device *bdev, uint32_t type,
- struct ttm_mem_type_manager *man);
+ int (*invalidate_caches)(struct ttm_bo_device *bdev, uint32_t flags);
+ int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type,
+ struct ttm_mem_type_manager *man);
+
+ /**
+ * struct ttm_bo_driver member eviction_valuable
+ *
+ * @bo: the buffer object to be evicted
+ * @place: placement we need room for
+ *
+ * Check with the driver if it is valuable to evict a BO to make room
+ * for a certain placement.
+ */
+ bool (*eviction_valuable)(struct ttm_buffer_object *bo,
+ const struct ttm_place *place);
/**
* struct ttm_bo_driver member evict_flags:
*
@@ -384,8 +396,9 @@ struct ttm_bo_driver {
* finished, they'll end up in bo->mem.flags
*/
- void(*evict_flags) (struct ttm_buffer_object *bo,
- struct ttm_placement *placement);
+ void (*evict_flags)(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement);
+
/**
* struct ttm_bo_driver member move:
*
@@ -399,10 +412,9 @@ struct ttm_bo_driver {
*
* Move a buffer between two memory regions.
*/
- int (*move) (struct ttm_buffer_object *bo,
- bool evict, bool interruptible,
- bool no_wait_gpu,
- struct ttm_mem_reg *new_mem);
+ int (*move)(struct ttm_buffer_object *bo, bool evict,
+ bool interruptible, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem);
/**
* struct ttm_bo_driver_member verify_access
@@ -416,8 +428,8 @@ struct ttm_bo_driver {
* access for all buffer objects.
* This function should return 0 if access is granted, -EPERM otherwise.
*/
- int (*verify_access) (struct ttm_buffer_object *bo,
- struct file *filp);
+ int (*verify_access)(struct ttm_buffer_object *bo,
+ struct file *filp);
/* hook to notify driver about a driver move so it
* can do tiling things */
@@ -430,7 +442,7 @@ struct ttm_bo_driver {
/**
* notify the driver that we're about to swap out this bo
*/
- void (*swap_notify) (struct ttm_buffer_object *bo);
+ void (*swap_notify)(struct ttm_buffer_object *bo);
/**
* Driver callback on when mapping io memory (for bo_move_memcpy
@@ -438,8 +450,10 @@ struct ttm_bo_driver {
* the mapping is not use anymore. io_mem_reserve & io_mem_free
* are balanced.
*/
- int (*io_mem_reserve)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem);
- void (*io_mem_free)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem);
+ int (*io_mem_reserve)(struct ttm_bo_device *bdev,
+ struct ttm_mem_reg *mem);
+ void (*io_mem_free)(struct ttm_bo_device *bdev,
+ struct ttm_mem_reg *mem);
/**
* Optional driver callback for when BO is removed from the LRU.
@@ -1025,7 +1039,7 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo);
*/
extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
- struct fence *fence, bool evict,
+ struct dma_fence *fence, bool evict,
struct ttm_mem_reg *new_mem);
/**
@@ -1040,7 +1054,7 @@ extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
* immediately or hang it on a temporary buffer object.
*/
int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
- struct fence *fence, bool evict,
+ struct dma_fence *fence, bool evict,
struct ttm_mem_reg *new_mem);
/**
diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h
index b620c317c772..47f35b8e6d09 100644
--- a/include/drm/ttm/ttm_execbuf_util.h
+++ b/include/drm/ttm/ttm_execbuf_util.h
@@ -114,6 +114,6 @@ extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
struct list_head *list,
- struct fence *fence);
+ struct dma_fence *fence);
#endif
diff --git a/include/dt-bindings/clock/hi3516cv300-clock.h b/include/dt-bindings/clock/hi3516cv300-clock.h
new file mode 100644
index 000000000000..5ba51b8388fc
--- /dev/null
+++ b/include/dt-bindings/clock/hi3516cv300-clock.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HI3516CV300_CLOCK_H
+#define __DTS_HI3516CV300_CLOCK_H
+
+/* hi3516CV300 core CRG */
+#define HI3516CV300_APB_CLK 0
+#define HI3516CV300_UART0_CLK 1
+#define HI3516CV300_UART1_CLK 2
+#define HI3516CV300_UART2_CLK 3
+#define HI3516CV300_SPI0_CLK 4
+#define HI3516CV300_SPI1_CLK 5
+#define HI3516CV300_FMC_CLK 6
+#define HI3516CV300_MMC0_CLK 7
+#define HI3516CV300_MMC1_CLK 8
+#define HI3516CV300_MMC2_CLK 9
+#define HI3516CV300_MMC3_CLK 10
+#define HI3516CV300_ETH_CLK 11
+#define HI3516CV300_ETH_MACIF_CLK 12
+#define HI3516CV300_DMAC_CLK 13
+#define HI3516CV300_PWM_CLK 14
+#define HI3516CV300_USB2_BUS_CLK 15
+#define HI3516CV300_USB2_OHCI48M_CLK 16
+#define HI3516CV300_USB2_OHCI12M_CLK 17
+#define HI3516CV300_USB2_OTG_UTMI_CLK 18
+#define HI3516CV300_USB2_HST_PHY_CLK 19
+#define HI3516CV300_USB2_UTMI0_CLK 20
+#define HI3516CV300_USB2_PHY_CLK 21
+
+/* hi3516CV300 sysctrl CRG */
+#define HI3516CV300_WDT_CLK 1
+
+#endif /* __DTS_HI3516CV300_CLOCK_H */
diff --git a/include/dt-bindings/clock/histb-clock.h b/include/dt-bindings/clock/histb-clock.h
new file mode 100644
index 000000000000..181c0f070f7c
--- /dev/null
+++ b/include/dt-bindings/clock/histb-clock.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HISTB_CLOCK_H
+#define __DTS_HISTB_CLOCK_H
+
+/* clocks provided by core CRG */
+#define HISTB_OSC_CLK 0
+#define HISTB_APB_CLK 1
+#define HISTB_AHB_CLK 2
+#define HISTB_UART1_CLK 3
+#define HISTB_UART2_CLK 4
+#define HISTB_UART3_CLK 5
+#define HISTB_I2C0_CLK 6
+#define HISTB_I2C1_CLK 7
+#define HISTB_I2C2_CLK 8
+#define HISTB_I2C3_CLK 9
+#define HISTB_I2C4_CLK 10
+#define HISTB_I2C5_CLK 11
+#define HISTB_SPI0_CLK 12
+#define HISTB_SPI1_CLK 13
+#define HISTB_SPI2_CLK 14
+#define HISTB_SCI_CLK 15
+#define HISTB_FMC_CLK 16
+#define HISTB_MMC_BIU_CLK 17
+#define HISTB_MMC_CIU_CLK 18
+#define HISTB_MMC_DRV_CLK 19
+#define HISTB_MMC_SAMPLE_CLK 20
+#define HISTB_SDIO0_BIU_CLK 21
+#define HISTB_SDIO0_CIU_CLK 22
+#define HISTB_SDIO0_DRV_CLK 23
+#define HISTB_SDIO0_SAMPLE_CLK 24
+#define HISTB_PCIE_AUX_CLK 25
+#define HISTB_PCIE_PIPE_CLK 26
+#define HISTB_PCIE_SYS_CLK 27
+#define HISTB_PCIE_BUS_CLK 28
+#define HISTB_ETH0_MAC_CLK 29
+#define HISTB_ETH0_MACIF_CLK 30
+#define HISTB_ETH1_MAC_CLK 31
+#define HISTB_ETH1_MACIF_CLK 32
+#define HISTB_COMBPHY1_CLK 33
+
+
+/* clocks provided by mcu CRG */
+#define HISTB_MCE_CLK 1
+#define HISTB_IR_CLK 2
+#define HISTB_TIMER01_CLK 3
+#define HISTB_LEDC_CLK 4
+#define HISTB_UART0_CLK 5
+#define HISTB_LSADC_CLK 6
+
+#endif /* __DTS_HISTB_CLOCK_H */
diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
index fd8aee8f64ae..ee9f1a508d2f 100644
--- a/include/dt-bindings/clock/imx6ul-clock.h
+++ b/include/dt-bindings/clock/imx6ul-clock.h
@@ -236,6 +236,19 @@
#define IMX6UL_CLK_PLL3_120M 223
#define IMX6UL_CLK_KPP 224
-#define IMX6UL_CLK_END 225
+/* For i.MX6ULL */
+#define IMX6ULL_CLK_ESAI_PRED 225
+#define IMX6ULL_CLK_ESAI_PODF 226
+#define IMX6ULL_CLK_ESAI_EXTAL 227
+#define IMX6ULL_CLK_ESAI_MEM 228
+#define IMX6ULL_CLK_ESAI_IPG 229
+#define IMX6ULL_CLK_DCP_CLK 230
+#define IMX6ULL_CLK_EPDC_PRE_SEL 231
+#define IMX6ULL_CLK_EPDC_SEL 232
+#define IMX6ULL_CLK_EPDC_PODF 233
+#define IMX6ULL_CLK_EPDC_ACLK 234
+#define IMX6ULL_CLK_EPDC_PIX 235
+#define IMX6ULL_CLK_ESAI_SEL 236
+#define IMX6UL_CLK_END 237
#endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
diff --git a/include/dt-bindings/clock/oxsemi,ox810se.h b/include/dt-bindings/clock/oxsemi,ox810se.h
new file mode 100644
index 000000000000..d5facb5e83f1
--- /dev/null
+++ b/include/dt-bindings/clock/oxsemi,ox810se.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+#ifndef DT_CLOCK_OXSEMI_OX810SE_H
+#define DT_CLOCK_OXSEMI_OX810SE_H
+
+#define CLK_810_LEON 0
+#define CLK_810_DMA_SGDMA 1
+#define CLK_810_CIPHER 2
+#define CLK_810_SATA 3
+#define CLK_810_AUDIO 4
+#define CLK_810_USBMPH 5
+#define CLK_810_ETHA 6
+#define CLK_810_PCIEA 7
+#define CLK_810_NAND 8
+
+#endif /* DT_CLOCK_OXSEMI_OX810SE_H */
diff --git a/include/dt-bindings/clock/oxsemi,ox820.h b/include/dt-bindings/clock/oxsemi,ox820.h
new file mode 100644
index 000000000000..f661ecc8d760
--- /dev/null
+++ b/include/dt-bindings/clock/oxsemi,ox820.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+#ifndef DT_CLOCK_OXSEMI_OX820_H
+#define DT_CLOCK_OXSEMI_OX820_H
+
+/* PLLs */
+#define CLK_820_PLLA 0
+#define CLK_820_PLLB 1
+
+/* Gate Clocks */
+#define CLK_820_LEON 2
+#define CLK_820_DMA_SGDMA 3
+#define CLK_820_CIPHER 4
+#define CLK_820_SD 5
+#define CLK_820_SATA 6
+#define CLK_820_AUDIO 7
+#define CLK_820_USBMPH 8
+#define CLK_820_ETHA 9
+#define CLK_820_PCIEA 10
+#define CLK_820_NAND 11
+#define CLK_820_PCIEB 12
+#define CLK_820_ETHB 13
+#define CLK_820_REF600 14
+#define CLK_820_USBDEV 15
+
+#endif /* DT_CLOCK_OXSEMI_OX820_H */
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8994.h b/include/dt-bindings/clock/qcom,gcc-msm8994.h
new file mode 100644
index 000000000000..8fa535be2ebc
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8994.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2016, 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
+ * 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 _DT_BINDINGS_CLK_MSM_GCC_8994_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8994_H
+
+#define GPLL0_EARLY 0
+#define GPLL0 1
+#define GPLL4_EARLY 2
+#define GPLL4 3
+#define UFS_AXI_CLK_SRC 4
+#define USB30_MASTER_CLK_SRC 5
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 6
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 7
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 8
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 9
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 10
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 11
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 12
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 13
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC 14
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC 15
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC 16
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC 17
+#define BLSP1_UART1_APPS_CLK_SRC 18
+#define BLSP1_UART2_APPS_CLK_SRC 19
+#define BLSP1_UART3_APPS_CLK_SRC 20
+#define BLSP1_UART4_APPS_CLK_SRC 21
+#define BLSP1_UART5_APPS_CLK_SRC 22
+#define BLSP1_UART6_APPS_CLK_SRC 23
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 24
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 25
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 26
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 27
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 28
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 29
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 30
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 31
+#define BLSP2_QUP5_I2C_APPS_CLK_SRC 32
+#define BLSP2_QUP5_SPI_APPS_CLK_SRC 33
+#define BLSP2_QUP6_I2C_APPS_CLK_SRC 34
+#define BLSP2_QUP6_SPI_APPS_CLK_SRC 35
+#define BLSP2_UART1_APPS_CLK_SRC 36
+#define BLSP2_UART2_APPS_CLK_SRC 37
+#define BLSP2_UART3_APPS_CLK_SRC 38
+#define BLSP2_UART4_APPS_CLK_SRC 39
+#define BLSP2_UART5_APPS_CLK_SRC 40
+#define BLSP2_UART6_APPS_CLK_SRC 41
+#define GP1_CLK_SRC 42
+#define GP2_CLK_SRC 43
+#define GP3_CLK_SRC 44
+#define PCIE_0_AUX_CLK_SRC 45
+#define PCIE_0_PIPE_CLK_SRC 46
+#define PCIE_1_AUX_CLK_SRC 47
+#define PCIE_1_PIPE_CLK_SRC 48
+#define PDM2_CLK_SRC 49
+#define SDCC1_APPS_CLK_SRC 50
+#define SDCC2_APPS_CLK_SRC 51
+#define SDCC3_APPS_CLK_SRC 52
+#define SDCC4_APPS_CLK_SRC 53
+#define TSIF_REF_CLK_SRC 54
+#define USB30_MOCK_UTMI_CLK_SRC 55
+#define USB3_PHY_AUX_CLK_SRC 56
+#define USB_HS_SYSTEM_CLK_SRC 57
+#define GCC_BLSP1_AHB_CLK 58
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 59
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 60
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 61
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 62
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 63
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 64
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 65
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 66
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK 67
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK 68
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK 69
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK 70
+#define GCC_BLSP1_UART1_APPS_CLK 71
+#define GCC_BLSP1_UART2_APPS_CLK 72
+#define GCC_BLSP1_UART3_APPS_CLK 73
+#define GCC_BLSP1_UART4_APPS_CLK 74
+#define GCC_BLSP1_UART5_APPS_CLK 75
+#define GCC_BLSP1_UART6_APPS_CLK 76
+#define GCC_BLSP2_AHB_CLK 77
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 78
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 79
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 80
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 81
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 82
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 83
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 84
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 85
+#define GCC_BLSP2_QUP5_I2C_APPS_CLK 86
+#define GCC_BLSP2_QUP5_SPI_APPS_CLK 87
+#define GCC_BLSP2_QUP6_I2C_APPS_CLK 88
+#define GCC_BLSP2_QUP6_SPI_APPS_CLK 89
+#define GCC_BLSP2_UART1_APPS_CLK 90
+#define GCC_BLSP2_UART2_APPS_CLK 91
+#define GCC_BLSP2_UART3_APPS_CLK 92
+#define GCC_BLSP2_UART4_APPS_CLK 93
+#define GCC_BLSP2_UART5_APPS_CLK 94
+#define GCC_BLSP2_UART6_APPS_CLK 95
+#define GCC_GP1_CLK 96
+#define GCC_GP2_CLK 97
+#define GCC_GP3_CLK 98
+#define GCC_PCIE_0_AUX_CLK 99
+#define GCC_PCIE_0_PIPE_CLK 100
+#define GCC_PCIE_1_AUX_CLK 101
+#define GCC_PCIE_1_PIPE_CLK 102
+#define GCC_PDM2_CLK 103
+#define GCC_SDCC1_APPS_CLK 104
+#define GCC_SDCC2_APPS_CLK 105
+#define GCC_SDCC3_APPS_CLK 106
+#define GCC_SDCC4_APPS_CLK 107
+#define GCC_SYS_NOC_UFS_AXI_CLK 108
+#define GCC_SYS_NOC_USB3_AXI_CLK 109
+#define GCC_TSIF_REF_CLK 110
+#define GCC_UFS_AXI_CLK 111
+#define GCC_UFS_RX_CFG_CLK 112
+#define GCC_UFS_TX_CFG_CLK 113
+#define GCC_USB30_MASTER_CLK 114
+#define GCC_USB30_MOCK_UTMI_CLK 115
+#define GCC_USB3_PHY_AUX_CLK 116
+#define GCC_USB_HS_SYSTEM_CLK 117
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h
new file mode 100644
index 000000000000..5924cdb71336
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,rpmcc.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 Linaro Limited
+ *
+ * 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 _DT_BINDINGS_CLK_MSM_RPMCC_H
+#define _DT_BINDINGS_CLK_MSM_RPMCC_H
+
+/* apq8064 */
+#define RPM_PXO_CLK 0
+#define RPM_PXO_A_CLK 1
+#define RPM_CXO_CLK 2
+#define RPM_CXO_A_CLK 3
+#define RPM_APPS_FABRIC_CLK 4
+#define RPM_APPS_FABRIC_A_CLK 5
+#define RPM_CFPB_CLK 6
+#define RPM_CFPB_A_CLK 7
+#define RPM_QDSS_CLK 8
+#define RPM_QDSS_A_CLK 9
+#define RPM_DAYTONA_FABRIC_CLK 10
+#define RPM_DAYTONA_FABRIC_A_CLK 11
+#define RPM_EBI1_CLK 12
+#define RPM_EBI1_A_CLK 13
+#define RPM_MM_FABRIC_CLK 14
+#define RPM_MM_FABRIC_A_CLK 15
+#define RPM_MMFPB_CLK 16
+#define RPM_MMFPB_A_CLK 17
+#define RPM_SYS_FABRIC_CLK 18
+#define RPM_SYS_FABRIC_A_CLK 19
+#define RPM_SFPB_CLK 20
+#define RPM_SFPB_A_CLK 21
+
+/* msm8916 */
+#define RPM_SMD_XO_CLK_SRC 0
+#define RPM_SMD_XO_A_CLK_SRC 1
+#define RPM_SMD_PCNOC_CLK 2
+#define RPM_SMD_PCNOC_A_CLK 3
+#define RPM_SMD_SNOC_CLK 4
+#define RPM_SMD_SNOC_A_CLK 5
+#define RPM_SMD_BIMC_CLK 6
+#define RPM_SMD_BIMC_A_CLK 7
+#define RPM_SMD_QDSS_CLK 8
+#define RPM_SMD_QDSS_A_CLK 9
+#define RPM_SMD_BB_CLK1 10
+#define RPM_SMD_BB_CLK1_A 11
+#define RPM_SMD_BB_CLK2 12
+#define RPM_SMD_BB_CLK2_A 13
+#define RPM_SMD_RF_CLK1 14
+#define RPM_SMD_RF_CLK1_A 15
+#define RPM_SMD_RF_CLK2 16
+#define RPM_SMD_RF_CLK2_A 17
+#define RPM_SMD_BB_CLK1_PIN 18
+#define RPM_SMD_BB_CLK1_A_PIN 19
+#define RPM_SMD_BB_CLK2_PIN 20
+#define RPM_SMD_BB_CLK2_A_PIN 21
+#define RPM_SMD_RF_CLK1_PIN 22
+#define RPM_SMD_RF_CLK1_A_PIN 23
+#define RPM_SMD_RF_CLK2_PIN 24
+#define RPM_SMD_RF_CLK2_A_PIN 25
+
+#endif
diff --git a/include/dt-bindings/clock/r8a7743-cpg-mssr.h b/include/dt-bindings/clock/r8a7743-cpg-mssr.h
new file mode 100644
index 000000000000..e1d1f3c6a99e
--- /dev/null
+++ b/include/dt-bindings/clock/r8a7743-cpg-mssr.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Cogent Embedded 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.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7743 CPG Core Clocks */
+#define R8A7743_CLK_Z 0
+#define R8A7743_CLK_ZG 1
+#define R8A7743_CLK_ZTR 2
+#define R8A7743_CLK_ZTRD2 3
+#define R8A7743_CLK_ZT 4
+#define R8A7743_CLK_ZX 5
+#define R8A7743_CLK_ZS 6
+#define R8A7743_CLK_HP 7
+#define R8A7743_CLK_B 9
+#define R8A7743_CLK_LB 10
+#define R8A7743_CLK_P 11
+#define R8A7743_CLK_CL 12
+#define R8A7743_CLK_M2 13
+#define R8A7743_CLK_ZB3 15
+#define R8A7743_CLK_ZB3D2 16
+#define R8A7743_CLK_DDR 17
+#define R8A7743_CLK_SDH 18
+#define R8A7743_CLK_SD0 19
+#define R8A7743_CLK_SD2 20
+#define R8A7743_CLK_SD3 21
+#define R8A7743_CLK_MMC0 22
+#define R8A7743_CLK_MP 23
+#define R8A7743_CLK_QSPI 26
+#define R8A7743_CLK_CP 27
+#define R8A7743_CLK_RCAN 28
+#define R8A7743_CLK_R 29
+#define R8A7743_CLK_OSC 30
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/clock/r8a7745-cpg-mssr.h b/include/dt-bindings/clock/r8a7745-cpg-mssr.h
new file mode 100644
index 000000000000..56ad6f0c6760
--- /dev/null
+++ b/include/dt-bindings/clock/r8a7745-cpg-mssr.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Cogent Embedded 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.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A7745_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7745_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7745 CPG Core Clocks */
+#define R8A7745_CLK_Z2 0
+#define R8A7745_CLK_ZG 1
+#define R8A7745_CLK_ZTR 2
+#define R8A7745_CLK_ZTRD2 3
+#define R8A7745_CLK_ZT 4
+#define R8A7745_CLK_ZX 5
+#define R8A7745_CLK_ZS 6
+#define R8A7745_CLK_HP 7
+#define R8A7745_CLK_B 9
+#define R8A7745_CLK_LB 10
+#define R8A7745_CLK_P 11
+#define R8A7745_CLK_CL 12
+#define R8A7745_CLK_CP 13
+#define R8A7745_CLK_M2 14
+#define R8A7745_CLK_ZB3 16
+#define R8A7745_CLK_ZB3D2 17
+#define R8A7745_CLK_DDR 18
+#define R8A7745_CLK_SDH 19
+#define R8A7745_CLK_SD0 20
+#define R8A7745_CLK_SD2 21
+#define R8A7745_CLK_SD3 22
+#define R8A7745_CLK_MMC0 23
+#define R8A7745_CLK_MP 24
+#define R8A7745_CLK_QSPI 25
+#define R8A7745_CLK_CPEX 26
+#define R8A7745_CLK_RCAN 27
+#define R8A7745_CLK_R 28
+#define R8A7745_CLK_OSC 29
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7745_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h
new file mode 100644
index 000000000000..9350a5527a36
--- /dev/null
+++ b/include/dt-bindings/clock/rk1108-cru.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+
+/* pll id */
+#define PLL_APLL 0
+#define PLL_DPLL 1
+#define PLL_GPLL 2
+#define ARMCLK 3
+
+/* sclk gates (special clocks) */
+#define SCLK_SPI0 65
+#define SCLK_NANDC 67
+#define SCLK_SDMMC 68
+#define SCLK_SDIO 69
+#define SCLK_EMMC 71
+#define SCLK_UART0 72
+#define SCLK_UART1 73
+#define SCLK_UART2 74
+#define SCLK_I2S0 75
+#define SCLK_I2S1 76
+#define SCLK_I2S2 77
+#define SCLK_TIMER0 78
+#define SCLK_TIMER1 79
+#define SCLK_SFC 80
+#define SCLK_SDMMC_DRV 81
+#define SCLK_SDIO_DRV 82
+#define SCLK_EMMC_DRV 83
+#define SCLK_SDMMC_SAMPLE 84
+#define SCLK_SDIO_SAMPLE 85
+#define SCLK_EMMC_SAMPLE 86
+
+/* aclk gates */
+#define ACLK_DMAC 192
+#define ACLK_PRE 193
+#define ACLK_CORE 194
+#define ACLK_ENMCORE 195
+
+/* pclk gates */
+#define PCLK_GPIO1 256
+#define PCLK_GPIO2 257
+#define PCLK_GPIO3 258
+#define PCLK_GRF 259
+#define PCLK_I2C1 260
+#define PCLK_I2C2 261
+#define PCLK_I2C3 262
+#define PCLK_SPI 263
+#define PCLK_SFC 264
+#define PCLK_UART0 265
+#define PCLK_UART1 266
+#define PCLK_UART2 267
+#define PCLK_TSADC 268
+#define PCLK_PWM 269
+#define PCLK_TIMER 270
+#define PCLK_PERI 271
+
+/* hclk gates */
+#define HCLK_I2S0_8CH 320
+#define HCLK_I2S1_8CH 321
+#define HCLK_I2S2_2CH 322
+#define HCLK_NANDC 323
+#define HCLK_SDMMC 324
+#define HCLK_SDIO 325
+#define HCLK_EMMC 326
+#define HCLK_PERI 327
+#define HCLK_SFC 328
+
+#define CLK_NR_CLKS (HCLK_SFC + 1)
+
+/* reset id */
+#define SRST_CORE_PO_AD 0
+#define SRST_CORE_AD 1
+#define SRST_L2_AD 2
+#define SRST_CPU_NIU_AD 3
+#define SRST_CORE_PO 4
+#define SRST_CORE 5
+#define SRST_L2 6
+#define SRST_CORE_DBG 8
+#define PRST_DBG 9
+#define RST_DAP 10
+#define PRST_DBG_NIU 11
+#define ARST_STRC_SYS_AD 15
+
+#define SRST_DDRPHY_CLKDIV 16
+#define SRST_DDRPHY 17
+#define PRST_DDRPHY 18
+#define PRST_HDMIPHY 19
+#define PRST_VDACPHY 20
+#define PRST_VADCPHY 21
+#define PRST_MIPI_CSI_PHY 22
+#define PRST_MIPI_DSI_PHY 23
+#define PRST_ACODEC 24
+#define ARST_BUS_NIU 25
+#define PRST_TOP_NIU 26
+#define ARST_INTMEM 27
+#define HRST_ROM 28
+#define ARST_DMAC 29
+#define SRST_MSCH_NIU 30
+#define PRST_MSCH_NIU 31
+
+#define PRST_DDRUPCTL 32
+#define NRST_DDRUPCTL 33
+#define PRST_DDRMON 34
+#define HRST_I2S0_8CH 35
+#define MRST_I2S0_8CH 36
+#define HRST_I2S1_2CH 37
+#define MRST_IS21_2CH 38
+#define HRST_I2S2_2CH 39
+#define MRST_I2S2_2CH 40
+#define HRST_CRYPTO 41
+#define SRST_CRYPTO 42
+#define PRST_SPI 43
+#define SRST_SPI 44
+#define PRST_UART0 45
+#define PRST_UART1 46
+#define PRST_UART2 47
+
+#define SRST_UART0 48
+#define SRST_UART1 49
+#define SRST_UART2 50
+#define PRST_I2C1 51
+#define PRST_I2C2 52
+#define PRST_I2C3 53
+#define SRST_I2C1 54
+#define SRST_I2C2 55
+#define SRST_I2C3 56
+#define PRST_PWM1 58
+#define SRST_PWM1 60
+#define PRST_WDT 61
+#define PRST_GPIO1 62
+#define PRST_GPIO2 63
+
+#define PRST_GPIO3 64
+#define PRST_GRF 65
+#define PRST_EFUSE 66
+#define PRST_EFUSE512 67
+#define PRST_TIMER0 68
+#define SRST_TIMER0 69
+#define SRST_TIMER1 70
+#define PRST_TSADC 71
+#define SRST_TSADC 72
+#define PRST_SARADC 73
+#define SRST_SARADC 74
+#define HRST_SYSBUS 75
+#define PRST_USBGRF 76
+
+#define ARST_PERIPH_NIU 80
+#define HRST_PERIPH_NIU 81
+#define PRST_PERIPH_NIU 82
+#define HRST_PERIPH 83
+#define HRST_SDMMC 84
+#define HRST_SDIO 85
+#define HRST_EMMC 86
+#define HRST_NANDC 87
+#define NRST_NANDC 88
+#define HRST_SFC 89
+#define SRST_SFC 90
+#define ARST_GMAC 91
+#define HRST_OTG 92
+#define SRST_OTG 93
+#define SRST_OTG_ADP 94
+#define HRST_HOST0 95
+
+#define HRST_HOST0_AUX 96
+#define HRST_HOST0_ARB 97
+#define SRST_HOST0_EHCIPHY 98
+#define SRST_HOST0_UTMI 99
+#define SRST_USBPOR 100
+#define SRST_UTMI0 101
+#define SRST_UTMI1 102
+
+#define ARST_VIO0_NIU 102
+#define ARST_VIO1_NIU 103
+#define HRST_VIO_NIU 104
+#define PRST_VIO_NIU 105
+#define ARST_VOP 106
+#define HRST_VOP 107
+#define DRST_VOP 108
+#define ARST_IEP 109
+#define HRST_IEP 110
+#define ARST_RGA 111
+#define HRST_RGA 112
+#define SRST_RGA 113
+#define PRST_CVBS 114
+#define PRST_HDMI 115
+#define SRST_HDMI 116
+#define PRST_MIPI_DSI 117
+
+#define ARST_ISP_NIU 118
+#define HRST_ISP_NIU 119
+#define HRST_ISP 120
+#define SRST_ISP 121
+#define ARST_VIP0 122
+#define HRST_VIP0 123
+#define PRST_VIP0 124
+#define ARST_VIP1 125
+#define HRST_VIP1 126
+#define PRST_VIP1 127
+#define ARST_VIP2 128
+#define HRST_VIP2 129
+#define PRST_VIP2 120
+#define ARST_VIP3 121
+#define HRST_VIP3 122
+#define PRST_VIP4 123
+
+#define PRST_CIF1TO4 124
+#define SRST_CVBS_CLK 125
+#define HRST_CVBS 126
+
+#define ARST_VPU_NIU 140
+#define HRST_VPU_NIU 141
+#define ARST_VPU 142
+#define HRST_VPU 143
+#define ARST_RKVDEC_NIU 144
+#define HRST_RKVDEC_NIU 145
+#define ARST_RKVDEC 146
+#define HRST_RKVDEC 147
+#define SRST_RKVDEC_CABAC 148
+#define SRST_RKVDEC_CORE 149
+#define ARST_RKVENC_NIU 150
+#define HRST_RKVENC_NIU 151
+#define ARST_RKVENC 152
+#define HRST_RKVENC 153
+#define SRST_RKVENC_CORE 154
+
+#define SRST_DSP_CORE 156
+#define SRST_DSP_SYS 157
+#define SRST_DSP_GLOBAL 158
+#define SRST_DSP_OECM 159
+#define PRST_DSP_IOP_NIU 160
+#define ARST_DSP_EPP_NIU 161
+#define ARST_DSP_EDP_NIU 162
+#define PRST_DSP_DBG_NIU 163
+#define PRST_DSP_CFG_NIU 164
+#define PRST_DSP_GRF 165
+#define PRST_DSP_MAILBOX 166
+#define PRST_DSP_INTC 167
+#define PRST_DSP_PFM_MON 169
+#define SRST_DSP_PFM_MON 170
+#define ARST_DSP_EDAP_NIU 171
+
+#define SRST_PMU 172
+#define SRST_PMU_I2C0 173
+#define PRST_PMU_I2C0 174
+#define PRST_PMU_GPIO0 175
+#define PRST_PMU_INTMEM 176
+#define PRST_PMU_PWM0 177
+#define SRST_PMU_PWM0 178
+#define PRST_PMU_GRF 179
+#define SRST_PMU_NIU 180
+#define SRST_PMU_PVTM 181
+#define ARST_DSP_EDP_PERF 184
+#define ARST_DSP_EPP_PERF 185
+
+#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
diff --git a/include/dt-bindings/clock/rk3188-cru-common.h b/include/dt-bindings/clock/rk3188-cru-common.h
index 4f53e70f68ee..d141c1f0c778 100644
--- a/include/dt-bindings/clock/rk3188-cru-common.h
+++ b/include/dt-bindings/clock/rk3188-cru-common.h
@@ -72,6 +72,8 @@
#define ACLK_IPP 200
#define ACLK_RGA 201
#define ACLK_CIF0 202
+#define ACLK_CPU 203
+#define ACLK_PERI 204
/* pclk gates */
#define PCLK_GRF 320
@@ -104,6 +106,8 @@
#define PCLK_EFUSE 347
#define PCLK_TZPC 348
#define PCLK_TSADC 349
+#define PCLK_CPU 350
+#define PCLK_PERI 351
/* hclk gates */
#define HCLK_SDMMC 448
@@ -126,8 +130,10 @@
#define HCLK_IPP 465
#define HCLK_RGA 466
#define HCLK_NANDC0 467
+#define HCLK_CPU 468
+#define HCLK_PERI 469
-#define CLK_NR_CLKS (HCLK_NANDC0 + 1)
+#define CLK_NR_CLKS (HCLK_PERI + 1)
/* soft-reset indices */
#define SRST_MCORE 2
diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
new file mode 100644
index 000000000000..370c0a0473fc
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) 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.
+ *
+ * Or, alternatively,
+ *
+ * b) 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 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 _DT_BINDINGS_CLK_SUN50I_A64_H_
+#define _DT_BINDINGS_CLK_SUN50I_A64_H_
+
+#define CLK_BUS_MIPI_DSI 28
+#define CLK_BUS_CE 29
+#define CLK_BUS_DMA 30
+#define CLK_BUS_MMC0 31
+#define CLK_BUS_MMC1 32
+#define CLK_BUS_MMC2 33
+#define CLK_BUS_NAND 34
+#define CLK_BUS_DRAM 35
+#define CLK_BUS_EMAC 36
+#define CLK_BUS_TS 37
+#define CLK_BUS_HSTIMER 38
+#define CLK_BUS_SPI0 39
+#define CLK_BUS_SPI1 40
+#define CLK_BUS_OTG 41
+#define CLK_BUS_EHCI0 42
+#define CLK_BUS_EHCI1 43
+#define CLK_BUS_OHCI0 44
+#define CLK_BUS_OHCI1 45
+#define CLK_BUS_VE 46
+#define CLK_BUS_TCON0 47
+#define CLK_BUS_TCON1 48
+#define CLK_BUS_DEINTERLACE 49
+#define CLK_BUS_CSI 50
+#define CLK_BUS_HDMI 51
+#define CLK_BUS_DE 52
+#define CLK_BUS_GPU 53
+#define CLK_BUS_MSGBOX 54
+#define CLK_BUS_SPINLOCK 55
+#define CLK_BUS_CODEC 56
+#define CLK_BUS_SPDIF 57
+#define CLK_BUS_PIO 58
+#define CLK_BUS_THS 59
+#define CLK_BUS_I2S0 60
+#define CLK_BUS_I2S1 61
+#define CLK_BUS_I2S2 62
+#define CLK_BUS_I2C0 63
+#define CLK_BUS_I2C1 64
+#define CLK_BUS_I2C2 65
+#define CLK_BUS_SCR 66
+#define CLK_BUS_UART0 67
+#define CLK_BUS_UART1 68
+#define CLK_BUS_UART2 69
+#define CLK_BUS_UART3 70
+#define CLK_BUS_UART4 71
+#define CLK_BUS_DBG 72
+#define CLK_THS 73
+#define CLK_NAND 74
+#define CLK_MMC0 75
+#define CLK_MMC1 76
+#define CLK_MMC2 77
+#define CLK_TS 78
+#define CLK_CE 79
+#define CLK_SPI0 80
+#define CLK_SPI1 81
+#define CLK_I2S0 82
+#define CLK_I2S1 83
+#define CLK_I2S2 84
+#define CLK_SPDIF 85
+#define CLK_USB_PHY0 86
+#define CLK_USB_PHY1 87
+#define CLK_USB_HSIC 88
+#define CLK_USB_HSIC_12M 89
+
+#define CLK_USB_OHCI0 91
+
+#define CLK_USB_OHCI1 93
+
+#define CLK_DRAM_VE 95
+#define CLK_DRAM_CSI 96
+#define CLK_DRAM_DEINTERLACE 97
+#define CLK_DRAM_TS 98
+#define CLK_DE 99
+#define CLK_TCON0 100
+#define CLK_TCON1 101
+#define CLK_DEINTERLACE 102
+#define CLK_CSI_MISC 103
+#define CLK_CSI_SCLK 104
+#define CLK_CSI_MCLK 105
+#define CLK_VE 106
+#define CLK_AC_DIG 107
+#define CLK_AC_DIG_4X 108
+#define CLK_AVS 109
+#define CLK_HDMI 110
+#define CLK_HDMI_DDC 111
+
+#define CLK_DSI_DPHY 113
+#define CLK_GPU 114
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H_ */
diff --git a/include/dt-bindings/gpio/meson-gxl-gpio.h b/include/dt-bindings/gpio/meson-gxl-gpio.h
new file mode 100644
index 000000000000..684d0d7add1c
--- /dev/null
+++ b/include/dt-bindings/gpio/meson-gxl-gpio.h
@@ -0,0 +1,131 @@
+/*
+ * GPIO definitions for Amlogic Meson GXL SoCs
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DT_BINDINGS_MESON_GXL_GPIO_H
+#define _DT_BINDINGS_MESON_GXL_GPIO_H
+
+#define GPIOAO_0 0
+#define GPIOAO_1 1
+#define GPIOAO_2 2
+#define GPIOAO_3 3
+#define GPIOAO_4 4
+#define GPIOAO_5 5
+#define GPIOAO_6 6
+#define GPIOAO_7 7
+#define GPIOAO_8 8
+#define GPIOAO_9 9
+
+#define GPIOZ_0 0
+#define GPIOZ_1 1
+#define GPIOZ_2 2
+#define GPIOZ_3 3
+#define GPIOZ_4 4
+#define GPIOZ_5 5
+#define GPIOZ_6 6
+#define GPIOZ_7 7
+#define GPIOZ_8 8
+#define GPIOZ_9 9
+#define GPIOZ_10 10
+#define GPIOZ_11 11
+#define GPIOZ_12 12
+#define GPIOZ_13 13
+#define GPIOZ_14 14
+#define GPIOZ_15 15
+#define GPIOH_0 16
+#define GPIOH_1 17
+#define GPIOH_2 18
+#define GPIOH_3 19
+#define GPIOH_4 20
+#define GPIOH_5 21
+#define GPIOH_6 22
+#define GPIOH_7 23
+#define GPIOH_8 24
+#define GPIOH_9 25
+#define BOOT_0 26
+#define BOOT_1 27
+#define BOOT_2 28
+#define BOOT_3 29
+#define BOOT_4 30
+#define BOOT_5 31
+#define BOOT_6 32
+#define BOOT_7 33
+#define BOOT_8 34
+#define BOOT_9 35
+#define BOOT_10 36
+#define BOOT_11 37
+#define BOOT_12 38
+#define BOOT_13 39
+#define BOOT_14 40
+#define BOOT_15 41
+#define CARD_0 42
+#define CARD_1 43
+#define CARD_2 44
+#define CARD_3 45
+#define CARD_4 46
+#define CARD_5 47
+#define CARD_6 48
+#define GPIODV_0 49
+#define GPIODV_1 50
+#define GPIODV_2 51
+#define GPIODV_3 52
+#define GPIODV_4 53
+#define GPIODV_5 54
+#define GPIODV_6 55
+#define GPIODV_7 56
+#define GPIODV_8 57
+#define GPIODV_9 58
+#define GPIODV_10 59
+#define GPIODV_11 60
+#define GPIODV_12 61
+#define GPIODV_13 62
+#define GPIODV_14 63
+#define GPIODV_15 64
+#define GPIODV_16 65
+#define GPIODV_17 66
+#define GPIODV_18 67
+#define GPIODV_19 68
+#define GPIODV_20 69
+#define GPIODV_21 70
+#define GPIODV_22 71
+#define GPIODV_23 72
+#define GPIODV_24 73
+#define GPIODV_25 74
+#define GPIODV_26 75
+#define GPIODV_27 76
+#define GPIODV_28 77
+#define GPIODV_29 78
+#define GPIOX_0 79
+#define GPIOX_1 80
+#define GPIOX_2 81
+#define GPIOX_3 82
+#define GPIOX_4 83
+#define GPIOX_5 84
+#define GPIOX_6 85
+#define GPIOX_7 86
+#define GPIOX_8 87
+#define GPIOX_9 88
+#define GPIOX_10 89
+#define GPIOX_11 90
+#define GPIOX_12 91
+#define GPIOX_13 92
+#define GPIOX_14 93
+#define GPIOX_15 94
+#define GPIOX_16 95
+#define GPIOX_17 96
+#define GPIOX_18 97
+#define GPIOCLK_0 98
+#define GPIOCLK_1 99
+#define GPIO_TEST_N 100
+
+#endif
diff --git a/include/dt-bindings/net/mdio.h b/include/dt-bindings/net/mdio.h
new file mode 100644
index 000000000000..99c6d903d439
--- /dev/null
+++ b/include/dt-bindings/net/mdio.h
@@ -0,0 +1,19 @@
+/*
+ * This header provides generic constants for ethernet MDIO bindings
+ */
+
+#ifndef _DT_BINDINGS_NET_MDIO_H
+#define _DT_BINDINGS_NET_MDIO_H
+
+/*
+ * EEE capability Advertisement
+ */
+
+#define MDIO_EEE_100TX 0x0002 /* 100TX EEE cap */
+#define MDIO_EEE_1000T 0x0004 /* 1000T EEE cap */
+#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */
+#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */
+#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */
+#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */
+
+#endif
diff --git a/include/dt-bindings/net/mscc-phy-vsc8531.h b/include/dt-bindings/net/mscc-phy-vsc8531.h
deleted file mode 100644
index 2383dd20ff43..000000000000
--- a/include/dt-bindings/net/mscc-phy-vsc8531.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Device Tree constants for Microsemi VSC8531 PHY
- *
- * Author: Nagaraju Lakkaraju
- *
- * License: Dual MIT/GPL
- * Copyright (c) 2016 Microsemi Corporation
- */
-
-#ifndef _DT_BINDINGS_MSCC_VSC8531_H
-#define _DT_BINDINGS_MSCC_VSC8531_H
-
-/* MAC interface Edge rate control VDDMAC in milli Volts */
-#define MSCC_VDDMAC_3300 3300
-#define MSCC_VDDMAC_2500 2500
-#define MSCC_VDDMAC_1800 1800
-#define MSCC_VDDMAC_1500 1500
-#define MSCC_VDDMAC_MAX 4
-#define MSCC_SLOWDOWN_MAX 8
-
-#endif
diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
index bbca3d038900..2732d6c0fb39 100644
--- a/include/dt-bindings/pinctrl/at91.h
+++ b/include/dt-bindings/pinctrl/at91.h
@@ -15,6 +15,8 @@
#define AT91_PINCTRL_DEGLITCH (1 << 2)
#define AT91_PINCTRL_PULL_DOWN (1 << 3)
#define AT91_PINCTRL_DIS_SCHMIT (1 << 4)
+#define AT91_PINCTRL_OUTPUT (1 << 7)
+#define AT91_PINCTRL_OUTPUT_VAL(x) ((x & 0x1) << 8)
#define AT91_PINCTRL_DEBOUNCE (1 << 16)
#define AT91_PINCTRL_DEBOUNCE_VAL(x) (x << 17)
diff --git a/include/dt-bindings/reset/sun50i-a64-ccu.h b/include/dt-bindings/reset/sun50i-a64-ccu.h
new file mode 100644
index 000000000000..db60b29ddb11
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-a64-ccu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) 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.
+ *
+ * Or, alternatively,
+ *
+ * b) 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 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 _DT_BINDINGS_RST_SUN50I_A64_H_
+#define _DT_BINDINGS_RST_SUN50I_A64_H_
+
+#define RST_USB_PHY0 0
+#define RST_USB_PHY1 1
+#define RST_USB_HSIC 2
+#define RST_DRAM 3
+#define RST_MBUS 4
+#define RST_BUS_MIPI_DSI 5
+#define RST_BUS_CE 6
+#define RST_BUS_DMA 7
+#define RST_BUS_MMC0 8
+#define RST_BUS_MMC1 9
+#define RST_BUS_MMC2 10
+#define RST_BUS_NAND 11
+#define RST_BUS_DRAM 12
+#define RST_BUS_EMAC 13
+#define RST_BUS_TS 14
+#define RST_BUS_HSTIMER 15
+#define RST_BUS_SPI0 16
+#define RST_BUS_SPI1 17
+#define RST_BUS_OTG 18
+#define RST_BUS_EHCI0 19
+#define RST_BUS_EHCI1 20
+#define RST_BUS_OHCI0 21
+#define RST_BUS_OHCI1 22
+#define RST_BUS_VE 23
+#define RST_BUS_TCON0 24
+#define RST_BUS_TCON1 25
+#define RST_BUS_DEINTERLACE 26
+#define RST_BUS_CSI 27
+#define RST_BUS_HDMI0 28
+#define RST_BUS_HDMI1 29
+#define RST_BUS_DE 30
+#define RST_BUS_GPU 31
+#define RST_BUS_MSGBOX 32
+#define RST_BUS_SPINLOCK 33
+#define RST_BUS_DBG 34
+#define RST_BUS_LVDS 35
+#define RST_BUS_CODEC 36
+#define RST_BUS_SPDIF 37
+#define RST_BUS_THS 38
+#define RST_BUS_I2S0 39
+#define RST_BUS_I2S1 40
+#define RST_BUS_I2S2 41
+#define RST_BUS_I2C0 42
+#define RST_BUS_I2C1 43
+#define RST_BUS_I2C2 44
+#define RST_BUS_SCR 45
+#define RST_BUS_UART0 46
+#define RST_BUS_UART1 47
+#define RST_BUS_UART2 48
+#define RST_BUS_UART3 49
+#define RST_BUS_UART4 50
+
+#endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index cb4616641235..43b28f04a1f5 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -465,6 +465,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
#define OSC_SB_CPCV2_SUPPORT 0x00000040
#define OSC_SB_PCLPI_SUPPORT 0x00000080
#define OSC_SB_OSLPI_SUPPORT 0x00000100
+#define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000
extern bool osc_sb_apei_support_acked;
extern bool osc_pc_lpi_support_confirmed;
diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h
index 9d8031257a90..c70aac13244a 100644
--- a/include/linux/alarmtimer.h
+++ b/include/linux/alarmtimer.h
@@ -10,7 +10,12 @@ enum alarmtimer_type {
ALARM_REALTIME,
ALARM_BOOTTIME,
+ /* Supported types end here */
ALARM_NUMTYPE,
+
+ /* Used for tracing information. No usable types. */
+ ALARM_REALTIME_FREEZER,
+ ALARM_BOOTTIME_FREEZER,
};
enum alarmtimer_restart {
diff --git a/include/linux/amba/pl061.h b/include/linux/amba/pl061.h
deleted file mode 100644
index fb83c0453489..000000000000
--- a/include/linux/amba/pl061.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <linux/types.h>
-
-/* platform data for the PL061 GPIO driver */
-
-struct pl061_platform_data {
- /* number of the first GPIO */
- unsigned gpio_base;
-
- /* number of the first IRQ.
- * If the IRQ functionality in not desired this must be set to 0.
- */
- unsigned irq_base;
-
- u8 directions; /* startup directions, 1: out, 0: in */
- u8 values; /* startup values */
-};
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index c357f27d5483..e850e76acaaf 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -116,6 +116,8 @@ struct bdi_writeback {
struct list_head work_list;
struct delayed_work dwork; /* work item used for writeback */
+ unsigned long dirty_sleep; /* last wait */
+
struct list_head bdi_node; /* anchored at bdi->wb_list */
#ifdef CONFIG_CGROUP_WRITEBACK
@@ -136,12 +138,13 @@ struct bdi_writeback {
struct backing_dev_info {
struct list_head bdi_list;
unsigned long ra_pages; /* max readahead in PAGE_SIZE units */
- unsigned int capabilities; /* Device capabilities */
+ unsigned long io_pages; /* max allowed IO size */
congested_fn *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
char *name;
+ unsigned int capabilities; /* Device capabilities */
unsigned int min_ratio;
unsigned int max_ratio, max_prop_frac;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 97cb48f03dc7..7cf8a6c70a3f 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -63,6 +63,12 @@
#define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio)))
/*
+ * Return the data direction, READ or WRITE.
+ */
+#define bio_data_dir(bio) \
+ (op_is_write(bio_op(bio)) ? WRITE : READ)
+
+/*
* Check whether this bio carries any data or not. A NULL bio is allowed.
*/
static inline bool bio_has_data(struct bio *bio)
@@ -70,7 +76,8 @@ static inline bool bio_has_data(struct bio *bio)
if (bio &&
bio->bi_iter.bi_size &&
bio_op(bio) != REQ_OP_DISCARD &&
- bio_op(bio) != REQ_OP_SECURE_ERASE)
+ bio_op(bio) != REQ_OP_SECURE_ERASE &&
+ bio_op(bio) != REQ_OP_WRITE_ZEROES)
return true;
return false;
@@ -80,18 +87,8 @@ static inline bool bio_no_advance_iter(struct bio *bio)
{
return bio_op(bio) == REQ_OP_DISCARD ||
bio_op(bio) == REQ_OP_SECURE_ERASE ||
- bio_op(bio) == REQ_OP_WRITE_SAME;
-}
-
-static inline bool bio_is_rw(struct bio *bio)
-{
- if (!bio_has_data(bio))
- return false;
-
- if (bio_no_advance_iter(bio))
- return false;
-
- return true;
+ bio_op(bio) == REQ_OP_WRITE_SAME ||
+ bio_op(bio) == REQ_OP_WRITE_ZEROES;
}
static inline bool bio_mergeable(struct bio *bio)
@@ -193,18 +190,20 @@ static inline unsigned bio_segments(struct bio *bio)
struct bvec_iter iter;
/*
- * We special case discard/write same, because they interpret bi_size
- * differently:
+ * We special case discard/write same/write zeroes, because they
+ * interpret bi_size differently:
*/
- if (bio_op(bio) == REQ_OP_DISCARD)
- return 1;
-
- if (bio_op(bio) == REQ_OP_SECURE_ERASE)
- return 1;
-
- if (bio_op(bio) == REQ_OP_WRITE_SAME)
+ switch (bio_op(bio)) {
+ case REQ_OP_DISCARD:
+ case REQ_OP_SECURE_ERASE:
+ case REQ_OP_WRITE_ZEROES:
+ return 0;
+ case REQ_OP_WRITE_SAME:
return 1;
+ default:
+ break;
+ }
bio_for_each_segment(bv, bio, iter)
segs++;
@@ -409,6 +408,8 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
}
+extern blk_qc_t submit_bio(struct bio *);
+
extern void bio_endio(struct bio *);
static inline void bio_io_error(struct bio *bio)
@@ -423,13 +424,15 @@ extern int bio_phys_segments(struct request_queue *, struct bio *);
extern int submit_bio_wait(struct bio *bio);
extern void bio_advance(struct bio *, unsigned);
-extern void bio_init(struct bio *);
+extern void bio_init(struct bio *bio, struct bio_vec *table,
+ unsigned short max_vecs);
extern void bio_reset(struct bio *);
void bio_chain(struct bio *, struct bio *);
extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
unsigned int, unsigned int);
+int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter);
struct rq_map_data;
extern struct bio *bio_map_user_iov(struct request_queue *,
const struct iov_iter *, gfp_t);
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 3bf5d33800ab..01b62e7bac74 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -581,15 +581,14 @@ static inline void blkg_rwstat_exit(struct blkg_rwstat *rwstat)
/**
* blkg_rwstat_add - add a value to a blkg_rwstat
* @rwstat: target blkg_rwstat
- * @op: REQ_OP
- * @op_flags: rq_flag_bits
+ * @op: REQ_OP and flags
* @val: value to add
*
* Add @val to @rwstat. The counters are chosen according to @rw. The
* caller is responsible for synchronizing calls to this function.
*/
static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat,
- int op, int op_flags, uint64_t val)
+ unsigned int op, uint64_t val)
{
struct percpu_counter *cnt;
@@ -600,7 +599,7 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat,
__percpu_counter_add(cnt, val, BLKG_STAT_CPU_BATCH);
- if (op_flags & REQ_SYNC)
+ if (op_is_sync(op))
cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_SYNC];
else
cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_ASYNC];
@@ -705,9 +704,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q,
if (!throtl) {
blkg = blkg ?: q->root_blkg;
- blkg_rwstat_add(&blkg->stat_bytes, bio_op(bio), bio->bi_opf,
+ blkg_rwstat_add(&blkg->stat_bytes, bio->bi_opf,
bio->bi_iter.bi_size);
- blkg_rwstat_add(&blkg->stat_ios, bio_op(bio), bio->bi_opf, 1);
+ blkg_rwstat_add(&blkg->stat_ios, bio->bi_opf, 1);
}
rcu_read_unlock();
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 535ab2e13d2e..87e404aae267 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -3,6 +3,7 @@
#include <linux/blkdev.h>
#include <linux/sbitmap.h>
+#include <linux/srcu.h>
struct blk_mq_tags;
struct blk_flush_queue;
@@ -35,6 +36,8 @@ struct blk_mq_hw_ctx {
struct blk_mq_tags *tags;
+ struct srcu_struct queue_rq_srcu;
+
unsigned long queued;
unsigned long run;
#define BLK_MQ_MAX_DISPATCH_ORDER 7
@@ -215,18 +218,20 @@ void blk_mq_start_request(struct request *rq);
void blk_mq_end_request(struct request *rq, int error);
void __blk_mq_end_request(struct request *rq, int error);
-void blk_mq_requeue_request(struct request *rq);
-void blk_mq_add_to_requeue_list(struct request *rq, bool at_head);
-void blk_mq_cancel_requeue_work(struct request_queue *q);
+void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list);
+void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
+ bool kick_requeue_list);
void blk_mq_kick_requeue_list(struct request_queue *q);
void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
void blk_mq_abort_requeue_list(struct request_queue *q);
void blk_mq_complete_request(struct request *rq, int error);
+bool blk_mq_queue_stopped(struct request_queue *q);
void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx);
void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx);
void blk_mq_stop_hw_queues(struct request_queue *q);
void blk_mq_start_hw_queues(struct request_queue *q);
+void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
void blk_mq_run_hw_queues(struct request_queue *q, bool async);
void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index cd395ecec99d..519ea2c9df61 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -17,7 +17,6 @@ struct io_context;
struct cgroup_subsys_state;
typedef void (bio_end_io_t) (struct bio *);
-#ifdef CONFIG_BLOCK
/*
* main unit of I/O for the block layer and lower layers (ie drivers and
* stacking drivers)
@@ -88,24 +87,6 @@ struct bio {
struct bio_vec bi_inline_vecs[0];
};
-#define BIO_OP_SHIFT (8 * FIELD_SIZEOF(struct bio, bi_opf) - REQ_OP_BITS)
-#define bio_flags(bio) ((bio)->bi_opf & ((1 << BIO_OP_SHIFT) - 1))
-#define bio_op(bio) ((bio)->bi_opf >> BIO_OP_SHIFT)
-
-#define bio_set_op_attrs(bio, op, op_flags) do { \
- if (__builtin_constant_p(op)) \
- BUILD_BUG_ON((op) + 0U >= (1U << REQ_OP_BITS)); \
- else \
- WARN_ON_ONCE((op) + 0U >= (1U << REQ_OP_BITS)); \
- if (__builtin_constant_p(op_flags)) \
- BUILD_BUG_ON((op_flags) + 0U >= (1U << BIO_OP_SHIFT)); \
- else \
- WARN_ON_ONCE((op_flags) + 0U >= (1U << BIO_OP_SHIFT)); \
- (bio)->bi_opf = bio_flags(bio); \
- (bio)->bi_opf |= (((op) + 0U) << BIO_OP_SHIFT); \
- (bio)->bi_opf |= (op_flags); \
-} while (0)
-
#define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs)
/*
@@ -119,6 +100,8 @@ struct bio {
#define BIO_QUIET 6 /* Make BIO Quiet */
#define BIO_CHAIN 7 /* chained bio, ->bi_remaining in effect */
#define BIO_REFFED 8 /* bio has elevated ->bi_cnt */
+#define BIO_THROTTLED 9 /* This bio has already been subjected to
+ * throttling rules. Don't do it again. */
/*
* Flags starting here get preserved by bio_reset() - this includes
@@ -142,53 +125,61 @@ struct bio {
#define BVEC_POOL_OFFSET (16 - BVEC_POOL_BITS)
#define BVEC_POOL_IDX(bio) ((bio)->bi_flags >> BVEC_POOL_OFFSET)
-#endif /* CONFIG_BLOCK */
-
/*
- * Request flags. For use in the cmd_flags field of struct request, and in
- * bi_opf of struct bio. Note that some flags are only valid in either one.
+ * Operations and flags common to the bio and request structures.
+ * We use 8 bits for encoding the operation, and the remaining 24 for flags.
+ *
+ * The least significant bit of the operation number indicates the data
+ * transfer direction:
+ *
+ * - if the least significant bit is set transfers are TO the device
+ * - if the least significant bit is not set transfers are FROM the device
+ *
+ * If a operation does not transfer data the least significant bit has no
+ * meaning.
*/
-enum rq_flag_bits {
- /* common flags */
- __REQ_FAILFAST_DEV, /* no driver retries of device errors */
+#define REQ_OP_BITS 8
+#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1)
+#define REQ_FLAG_BITS 24
+
+enum req_opf {
+ /* read sectors from the device */
+ REQ_OP_READ = 0,
+ /* write sectors to the device */
+ REQ_OP_WRITE = 1,
+ /* flush the volatile write cache */
+ REQ_OP_FLUSH = 2,
+ /* discard sectors */
+ REQ_OP_DISCARD = 3,
+ /* get zone information */
+ REQ_OP_ZONE_REPORT = 4,
+ /* securely erase sectors */
+ REQ_OP_SECURE_ERASE = 5,
+ /* seset a zone write pointer */
+ REQ_OP_ZONE_RESET = 6,
+ /* write the same sector many times */
+ REQ_OP_WRITE_SAME = 7,
+ /* write the zero filled sector many times */
+ REQ_OP_WRITE_ZEROES = 8,
+
+ REQ_OP_LAST,
+};
+
+enum req_flag_bits {
+ __REQ_FAILFAST_DEV = /* no driver retries of device errors */
+ REQ_OP_BITS,
__REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */
__REQ_FAILFAST_DRIVER, /* no driver retries of driver errors */
-
__REQ_SYNC, /* request is sync (sync write or read) */
__REQ_META, /* metadata io request */
__REQ_PRIO, /* boost priority in cfq */
-
- __REQ_NOIDLE, /* don't anticipate more IO after this one */
+ __REQ_NOMERGE, /* don't touch this for merging */
+ __REQ_IDLE, /* anticipate more IO after this one */
__REQ_INTEGRITY, /* I/O includes block integrity payload */
__REQ_FUA, /* forced unit access */
__REQ_PREFLUSH, /* request for cache flush */
-
- /* bio only flags */
__REQ_RAHEAD, /* read ahead, can fail anytime */
- __REQ_THROTTLED, /* This bio has already been subjected to
- * throttling rules. Don't do it again. */
-
- /* request only flags */
- __REQ_SORTED, /* elevator knows about this request */
- __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */
- __REQ_NOMERGE, /* don't touch this for merging */
- __REQ_STARTED, /* drive already may have started this one */
- __REQ_DONTPREP, /* don't call prep for this one */
- __REQ_QUEUED, /* uses queueing */
- __REQ_ELVPRIV, /* elevator private data attached */
- __REQ_FAILED, /* set if the request failed */
- __REQ_QUIET, /* don't worry about errors */
- __REQ_PREEMPT, /* set for "ide_preempt" requests and also
- for requests for which the SCSI "quiesce"
- state must be ignored. */
- __REQ_ALLOCED, /* request came from our alloc pool */
- __REQ_COPY_USER, /* contains copies of user pages */
- __REQ_FLUSH_SEQ, /* request for flush sequence */
- __REQ_IO_STAT, /* account I/O stat */
- __REQ_MIXED_MERGE, /* merge of different types, fail separately */
- __REQ_PM, /* runtime pm request */
- __REQ_HASHED, /* on IO scheduler merge hash */
- __REQ_MQ_INFLIGHT, /* track inflight for MQ */
+ __REQ_BACKGROUND, /* background IO */
__REQ_NR_BITS, /* stops here */
};
@@ -198,54 +189,47 @@ enum rq_flag_bits {
#define REQ_SYNC (1ULL << __REQ_SYNC)
#define REQ_META (1ULL << __REQ_META)
#define REQ_PRIO (1ULL << __REQ_PRIO)
-#define REQ_NOIDLE (1ULL << __REQ_NOIDLE)
+#define REQ_NOMERGE (1ULL << __REQ_NOMERGE)
+#define REQ_IDLE (1ULL << __REQ_IDLE)
#define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY)
+#define REQ_FUA (1ULL << __REQ_FUA)
+#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH)
+#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
+#define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
#define REQ_FAILFAST_MASK \
(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
-#define REQ_COMMON_MASK \
- (REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | REQ_NOIDLE | \
- REQ_PREFLUSH | REQ_FUA | REQ_INTEGRITY | REQ_NOMERGE)
-#define REQ_CLONE_MASK REQ_COMMON_MASK
-/* This mask is used for both bio and request merge checking */
#define REQ_NOMERGE_FLAGS \
- (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_PREFLUSH | REQ_FUA | REQ_FLUSH_SEQ)
+ (REQ_NOMERGE | REQ_PREFLUSH | REQ_FUA)
-#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
-#define REQ_THROTTLED (1ULL << __REQ_THROTTLED)
+#define bio_op(bio) \
+ ((bio)->bi_opf & REQ_OP_MASK)
+#define req_op(req) \
+ ((req)->cmd_flags & REQ_OP_MASK)
-#define REQ_SORTED (1ULL << __REQ_SORTED)
-#define REQ_SOFTBARRIER (1ULL << __REQ_SOFTBARRIER)
-#define REQ_FUA (1ULL << __REQ_FUA)
-#define REQ_NOMERGE (1ULL << __REQ_NOMERGE)
-#define REQ_STARTED (1ULL << __REQ_STARTED)
-#define REQ_DONTPREP (1ULL << __REQ_DONTPREP)
-#define REQ_QUEUED (1ULL << __REQ_QUEUED)
-#define REQ_ELVPRIV (1ULL << __REQ_ELVPRIV)
-#define REQ_FAILED (1ULL << __REQ_FAILED)
-#define REQ_QUIET (1ULL << __REQ_QUIET)
-#define REQ_PREEMPT (1ULL << __REQ_PREEMPT)
-#define REQ_ALLOCED (1ULL << __REQ_ALLOCED)
-#define REQ_COPY_USER (1ULL << __REQ_COPY_USER)
-#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH)
-#define REQ_FLUSH_SEQ (1ULL << __REQ_FLUSH_SEQ)
-#define REQ_IO_STAT (1ULL << __REQ_IO_STAT)
-#define REQ_MIXED_MERGE (1ULL << __REQ_MIXED_MERGE)
-#define REQ_PM (1ULL << __REQ_PM)
-#define REQ_HASHED (1ULL << __REQ_HASHED)
-#define REQ_MQ_INFLIGHT (1ULL << __REQ_MQ_INFLIGHT)
-
-enum req_op {
- REQ_OP_READ,
- REQ_OP_WRITE,
- REQ_OP_DISCARD, /* request to discard sectors */
- REQ_OP_SECURE_ERASE, /* request to securely erase sectors */
- REQ_OP_WRITE_SAME, /* write same block many times */
- REQ_OP_FLUSH, /* request for cache flush */
-};
+/* obsolete, don't use in new code */
+static inline void bio_set_op_attrs(struct bio *bio, unsigned op,
+ unsigned op_flags)
+{
+ bio->bi_opf = op | op_flags;
+}
-#define REQ_OP_BITS 3
+static inline bool op_is_write(unsigned int op)
+{
+ return (op & 1);
+}
+
+/*
+ * Reads are always treated as synchronous, as are requests with the FUA or
+ * PREFLUSH flag. Other operations may be marked as synchronous using the
+ * REQ_SYNC flag.
+ */
+static inline bool op_is_sync(unsigned int op)
+{
+ return (op & REQ_OP_MASK) == REQ_OP_READ ||
+ (op & (REQ_SYNC | REQ_FUA | REQ_PREFLUSH));
+}
typedef unsigned int blk_qc_t;
#define BLK_QC_T_NONE -1U
@@ -271,4 +255,20 @@ static inline unsigned int blk_qc_t_to_tag(blk_qc_t cookie)
return cookie & ((1u << BLK_QC_T_SHIFT) - 1);
}
+struct blk_issue_stat {
+ u64 time;
+};
+
+#define BLK_RQ_STAT_BATCH 64
+
+struct blk_rq_stat {
+ s64 mean;
+ u64 min;
+ u64 max;
+ s32 nr_samples;
+ s32 nr_batch;
+ u64 batch;
+ s64 time;
+};
+
#endif /* __LINUX_BLK_TYPES_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c47c358ba052..c5393766909d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -24,6 +24,7 @@
#include <linux/rcupdate.h>
#include <linux/percpu-refcount.h>
#include <linux/scatterlist.h>
+#include <linux/blkzoned.h>
struct module;
struct scsi_ioctl_command;
@@ -37,6 +38,7 @@ struct bsg_job;
struct blkcg_gq;
struct blk_flush_queue;
struct pr_ops;
+struct rq_wb;
#define BLKDEV_MIN_RQ 4
#define BLKDEV_MAX_RQ 128 /* Default maximum */
@@ -77,6 +79,55 @@ enum rq_cmd_type_bits {
REQ_TYPE_DRV_PRIV, /* driver defined types from here */
};
+/*
+ * request flags */
+typedef __u32 __bitwise req_flags_t;
+
+/* elevator knows about this request */
+#define RQF_SORTED ((__force req_flags_t)(1 << 0))
+/* drive already may have started this one */
+#define RQF_STARTED ((__force req_flags_t)(1 << 1))
+/* uses tagged queueing */
+#define RQF_QUEUED ((__force req_flags_t)(1 << 2))
+/* may not be passed by ioscheduler */
+#define RQF_SOFTBARRIER ((__force req_flags_t)(1 << 3))
+/* request for flush sequence */
+#define RQF_FLUSH_SEQ ((__force req_flags_t)(1 << 4))
+/* merge of different types, fail separately */
+#define RQF_MIXED_MERGE ((__force req_flags_t)(1 << 5))
+/* track inflight for MQ */
+#define RQF_MQ_INFLIGHT ((__force req_flags_t)(1 << 6))
+/* don't call prep for this one */
+#define RQF_DONTPREP ((__force req_flags_t)(1 << 7))
+/* set for "ide_preempt" requests and also for requests for which the SCSI
+ "quiesce" state must be ignored. */
+#define RQF_PREEMPT ((__force req_flags_t)(1 << 8))
+/* contains copies of user pages */
+#define RQF_COPY_USER ((__force req_flags_t)(1 << 9))
+/* vaguely specified driver internal error. Ignored by the block layer */
+#define RQF_FAILED ((__force req_flags_t)(1 << 10))
+/* don't warn about errors */
+#define RQF_QUIET ((__force req_flags_t)(1 << 11))
+/* elevator private data attached */
+#define RQF_ELVPRIV ((__force req_flags_t)(1 << 12))
+/* account I/O stat */
+#define RQF_IO_STAT ((__force req_flags_t)(1 << 13))
+/* request came from our alloc pool */
+#define RQF_ALLOCED ((__force req_flags_t)(1 << 14))
+/* runtime pm request */
+#define RQF_PM ((__force req_flags_t)(1 << 15))
+/* on IO scheduler merge hash */
+#define RQF_HASHED ((__force req_flags_t)(1 << 16))
+/* IO stats tracking on */
+#define RQF_STATS ((__force req_flags_t)(1 << 17))
+/* Look at ->special_vec for the actual data payload instead of the
+ bio chain. */
+#define RQF_SPECIAL_PAYLOAD ((__force req_flags_t)(1 << 18))
+
+/* flags that prevent us from merging requests: */
+#define RQF_NOMERGE_FLAGS \
+ (RQF_STARTED | RQF_SOFTBARRIER | RQF_FLUSH_SEQ | RQF_SPECIAL_PAYLOAD)
+
#define BLK_MAX_CDB 16
/*
@@ -97,7 +148,8 @@ struct request {
int cpu;
unsigned cmd_type;
- u64 cmd_flags;
+ unsigned int cmd_flags; /* op and common flags */
+ req_flags_t rq_flags;
unsigned long atomic_flags;
/* the following two fields are internal, NEVER access directly */
@@ -126,6 +178,7 @@ struct request {
*/
union {
struct rb_node rb_node; /* sort/lookup */
+ struct bio_vec special_vec;
void *completion_data;
};
@@ -151,6 +204,7 @@ struct request {
struct gendisk *rq_disk;
struct hd_struct *part;
unsigned long start_time;
+ struct blk_issue_stat issue_stat;
#ifdef CONFIG_BLK_CGROUP
struct request_list *rl; /* rl this rq is alloced from */
unsigned long long start_time_ns;
@@ -198,20 +252,6 @@ struct request {
struct request *next_rq;
};
-#define REQ_OP_SHIFT (8 * sizeof(u64) - REQ_OP_BITS)
-#define req_op(req) ((req)->cmd_flags >> REQ_OP_SHIFT)
-
-#define req_set_op(req, op) do { \
- WARN_ON(op >= (1 << REQ_OP_BITS)); \
- (req)->cmd_flags &= ((1ULL << REQ_OP_SHIFT) - 1); \
- (req)->cmd_flags |= ((u64) (op) << REQ_OP_SHIFT); \
-} while (0)
-
-#define req_set_op_attrs(req, op, flags) do { \
- req_set_op(req, op); \
- (req)->cmd_flags |= flags; \
-} while (0)
-
static inline unsigned short req_get_ioprio(struct request *req)
{
return req->ioprio;
@@ -261,6 +301,15 @@ struct blk_queue_tag {
#define BLK_SCSI_MAX_CMDS (256)
#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
+/*
+ * Zoned block device models (zoned limit).
+ */
+enum blk_zoned_model {
+ BLK_ZONED_NONE, /* Regular block device */
+ BLK_ZONED_HA, /* Host-aware zoned block device */
+ BLK_ZONED_HM, /* Host-managed zoned block device */
+};
+
struct queue_limits {
unsigned long bounce_pfn;
unsigned long seg_boundary_mask;
@@ -278,6 +327,7 @@ struct queue_limits {
unsigned int max_discard_sectors;
unsigned int max_hw_discard_sectors;
unsigned int max_write_same_sectors;
+ unsigned int max_write_zeroes_sectors;
unsigned int discard_granularity;
unsigned int discard_alignment;
@@ -290,8 +340,45 @@ struct queue_limits {
unsigned char cluster;
unsigned char discard_zeroes_data;
unsigned char raid_partial_stripes_expensive;
+ enum blk_zoned_model zoned;
};
+#ifdef CONFIG_BLK_DEV_ZONED
+
+struct blk_zone_report_hdr {
+ unsigned int nr_zones;
+ u8 padding[60];
+};
+
+extern int blkdev_report_zones(struct block_device *bdev,
+ sector_t sector, struct blk_zone *zones,
+ unsigned int *nr_zones, gfp_t gfp_mask);
+extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors,
+ sector_t nr_sectors, gfp_t gfp_mask);
+
+extern int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg);
+extern int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg);
+
+#else /* CONFIG_BLK_DEV_ZONED */
+
+static inline int blkdev_report_zones_ioctl(struct block_device *bdev,
+ fmode_t mode, unsigned int cmd,
+ unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+static inline int blkdev_reset_zones_ioctl(struct block_device *bdev,
+ fmode_t mode, unsigned int cmd,
+ unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+#endif /* CONFIG_BLK_DEV_ZONED */
+
struct request_queue {
/*
* Together with queue_head for cacheline sharing
@@ -302,6 +389,8 @@ struct request_queue {
int nr_rqs[2]; /* # allocated [a]sync rqs */
int nr_rqs_elvpriv; /* # allocated rqs w/ elvpriv */
+ struct rq_wb *rq_wb;
+
/*
* If blkcg is not used, @q->root_rl serves all requests. If blkcg
* is used, root blkg allocates from @q->root_rl and all other
@@ -327,6 +416,8 @@ struct request_queue {
struct blk_mq_ctx __percpu *queue_ctx;
unsigned int nr_queues;
+ unsigned int queue_depth;
+
/* hw dispatch queues */
struct blk_mq_hw_ctx **queue_hw_ctx;
unsigned int nr_hw_queues;
@@ -412,6 +503,9 @@ struct request_queue {
unsigned int nr_sorted;
unsigned int in_flight[2];
+
+ struct blk_rq_stat rq_stats[2];
+
/*
* Number of active block driver functions for which blk_drain_queue()
* must wait. Must be incremented around functions that unlock the
@@ -420,6 +514,7 @@ struct request_queue {
unsigned int request_fn_active;
unsigned int rq_timeout;
+ int poll_nsec;
struct timer_list timeout;
struct work_struct timeout_work;
struct list_head timeout_list;
@@ -505,6 +600,7 @@ struct request_queue {
#define QUEUE_FLAG_FUA 24 /* device supports FUA writes */
#define QUEUE_FLAG_FLUSH_NQ 25 /* flush not queueuable */
#define QUEUE_FLAG_DAX 26 /* device supports DAX */
+#define QUEUE_FLAG_STATS 27 /* track rq completion times */
#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \
(1 << QUEUE_FLAG_STACKABLE) | \
@@ -601,7 +697,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
REQ_FAILFAST_DRIVER))
#define blk_account_rq(rq) \
- (((rq)->cmd_flags & REQ_STARTED) && \
+ (((rq)->rq_flags & RQF_STARTED) && \
((rq)->cmd_type == REQ_TYPE_FS))
#define blk_rq_cpu_valid(rq) ((rq)->cpu != -1)
@@ -627,17 +723,31 @@ static inline unsigned int blk_queue_cluster(struct request_queue *q)
return q->limits.cluster;
}
-/*
- * We regard a request as sync, if either a read or a sync write
- */
-static inline bool rw_is_sync(int op, unsigned int rw_flags)
+static inline enum blk_zoned_model
+blk_queue_zoned_model(struct request_queue *q)
{
- return op == REQ_OP_READ || (rw_flags & REQ_SYNC);
+ return q->limits.zoned;
+}
+
+static inline bool blk_queue_is_zoned(struct request_queue *q)
+{
+ switch (blk_queue_zoned_model(q)) {
+ case BLK_ZONED_HA:
+ case BLK_ZONED_HM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline unsigned int blk_queue_zone_size(struct request_queue *q)
+{
+ return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0;
}
static inline bool rq_is_sync(struct request *rq)
{
- return rw_is_sync(req_op(rq), rq->cmd_flags);
+ return op_is_sync(rq->cmd_flags);
}
static inline bool blk_rl_full(struct request_list *rl, bool sync)
@@ -669,8 +779,13 @@ static inline bool rq_mergeable(struct request *rq)
if (req_op(rq) == REQ_OP_FLUSH)
return false;
+ if (req_op(rq) == REQ_OP_WRITE_ZEROES)
+ return false;
+
if (rq->cmd_flags & REQ_NOMERGE_FLAGS)
return false;
+ if (rq->rq_flags & RQF_NOMERGE_FLAGS)
+ return false;
return true;
}
@@ -683,6 +798,14 @@ static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b)
return false;
}
+static inline unsigned int blk_queue_depth(struct request_queue *q)
+{
+ if (q->queue_depth)
+ return q->queue_depth;
+
+ return q->nr_requests;
+}
+
/*
* q->prep_rq_fn return values
*/
@@ -790,8 +913,6 @@ extern void __blk_put_request(struct request_queue *, struct request *);
extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
extern void blk_rq_set_block_pc(struct request *);
extern void blk_requeue_request(struct request_queue *, struct request *);
-extern void blk_add_request_payload(struct request *rq, struct page *page,
- int offset, unsigned int len);
extern int blk_lld_busy(struct request_queue *q);
extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
struct bio_set *bs, gfp_t gfp_mask,
@@ -824,6 +945,7 @@ extern void __blk_run_queue(struct request_queue *q);
extern void __blk_run_queue_uncond(struct request_queue *q);
extern void blk_run_queue(struct request_queue *);
extern void blk_run_queue_async(struct request_queue *q);
+extern void blk_mq_quiesce_queue(struct request_queue *q);
extern int blk_rq_map_user(struct request_queue *, struct request *,
struct rq_map_data *, void __user *, unsigned long,
gfp_t);
@@ -837,7 +959,7 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *,
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
struct request *, int, rq_end_io_fn *);
-bool blk_poll(struct request_queue *q, blk_qc_t cookie);
+bool blk_mq_poll(struct request_queue *q, blk_qc_t cookie);
static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
{
@@ -888,6 +1010,9 @@ static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
if (unlikely(op == REQ_OP_WRITE_SAME))
return q->limits.max_write_same_sectors;
+ if (unlikely(op == REQ_OP_WRITE_ZEROES))
+ return q->limits.max_write_zeroes_sectors;
+
return q->limits.max_sectors;
}
@@ -991,6 +1116,8 @@ extern void blk_queue_max_discard_sectors(struct request_queue *q,
unsigned int max_discard_sectors);
extern void blk_queue_max_write_same_sectors(struct request_queue *q,
unsigned int max_write_same_sectors);
+extern void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
+ unsigned int max_write_same_sectors);
extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
extern void blk_queue_alignment_offset(struct request_queue *q,
@@ -999,6 +1126,7 @@ extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
extern void blk_queue_io_min(struct request_queue *q, unsigned int min);
extern void blk_limits_io_opt(struct queue_limits *limits, unsigned int opt);
extern void blk_queue_io_opt(struct request_queue *q, unsigned int opt);
+extern void blk_set_queue_depth(struct request_queue *q, unsigned int depth);
extern void blk_set_default_limits(struct queue_limits *lim);
extern void blk_set_stacking_limits(struct queue_limits *lim);
extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
@@ -1027,6 +1155,13 @@ extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua);
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
+static inline unsigned short blk_rq_nr_phys_segments(struct request *rq)
+{
+ if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+ return 1;
+ return rq->nr_phys_segments;
+}
+
extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
extern void blk_dump_rq_flags(struct request *, char *);
extern long nr_blockdev_pages(void);
@@ -1057,7 +1192,7 @@ static inline int blk_pre_runtime_suspend(struct request_queue *q)
static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {}
static inline void blk_pre_runtime_resume(struct request_queue *q) {}
static inline void blk_post_runtime_resume(struct request_queue *q, int err) {}
-extern inline void blk_set_runtime_active(struct request_queue *q) {}
+static inline void blk_set_runtime_active(struct request_queue *q) {}
#endif
/*
@@ -1078,6 +1213,7 @@ struct blk_plug {
struct list_head cb_list; /* md requires an unplug callback */
};
#define BLK_MAX_REQUEST_COUNT 16
+#define BLK_PLUG_FLUSH_SIZE (128 * 1024)
struct blk_plug_cb;
typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *, bool);
@@ -1151,6 +1287,9 @@ extern int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
struct bio **biop);
extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct page *page);
+extern int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
+ bool discard);
extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, bool discard);
static inline int sb_issue_discard(struct super_block *sb, sector_t block,
@@ -1354,6 +1493,46 @@ static inline unsigned int bdev_write_same(struct block_device *bdev)
return 0;
}
+static inline unsigned int bdev_write_zeroes_sectors(struct block_device *bdev)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (q)
+ return q->limits.max_write_zeroes_sectors;
+
+ return 0;
+}
+
+static inline enum blk_zoned_model bdev_zoned_model(struct block_device *bdev)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (q)
+ return blk_queue_zoned_model(q);
+
+ return BLK_ZONED_NONE;
+}
+
+static inline bool bdev_is_zoned(struct block_device *bdev)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (q)
+ return blk_queue_is_zoned(q);
+
+ return false;
+}
+
+static inline unsigned int bdev_zone_size(struct block_device *bdev)
+{
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (q)
+ return blk_queue_zone_size(q);
+
+ return 0;
+}
+
static inline int queue_dma_alignment(struct request_queue *q)
{
return q ? q->dma_alignment : 511;
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index cceb72f9e29f..e417f080219a 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -118,7 +118,7 @@ static inline int blk_cmd_buf_len(struct request *rq)
}
extern void blk_dump_cmd(char *buf, struct request *rq);
-extern void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes);
+extern void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes);
#endif /* CONFIG_EVENT_TRACING && CONFIG_BLOCK */
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
new file mode 100644
index 000000000000..7b6e5d168c95
--- /dev/null
+++ b/include/linux/bpf-cgroup.h
@@ -0,0 +1,92 @@
+#ifndef _BPF_CGROUP_H
+#define _BPF_CGROUP_H
+
+#include <linux/jump_label.h>
+#include <uapi/linux/bpf.h>
+
+struct sock;
+struct cgroup;
+struct sk_buff;
+
+#ifdef CONFIG_CGROUP_BPF
+
+extern struct static_key_false cgroup_bpf_enabled_key;
+#define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key)
+
+struct cgroup_bpf {
+ /*
+ * Store two sets of bpf_prog pointers, one for programs that are
+ * pinned directly to this cgroup, and one for those that are effective
+ * when this cgroup is accessed.
+ */
+ struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE];
+ struct bpf_prog *effective[MAX_BPF_ATTACH_TYPE];
+};
+
+void cgroup_bpf_put(struct cgroup *cgrp);
+void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent);
+
+void __cgroup_bpf_update(struct cgroup *cgrp,
+ struct cgroup *parent,
+ struct bpf_prog *prog,
+ enum bpf_attach_type type);
+
+/* Wrapper for __cgroup_bpf_update() protected by cgroup_mutex */
+void cgroup_bpf_update(struct cgroup *cgrp,
+ struct bpf_prog *prog,
+ enum bpf_attach_type type);
+
+int __cgroup_bpf_run_filter_skb(struct sock *sk,
+ struct sk_buff *skb,
+ enum bpf_attach_type type);
+
+int __cgroup_bpf_run_filter_sk(struct sock *sk,
+ enum bpf_attach_type type);
+
+/* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
+#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb) \
+({ \
+ int __ret = 0; \
+ if (cgroup_bpf_enabled) \
+ __ret = __cgroup_bpf_run_filter_skb(sk, skb, \
+ BPF_CGROUP_INET_INGRESS); \
+ \
+ __ret; \
+})
+
+#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb) \
+({ \
+ int __ret = 0; \
+ if (cgroup_bpf_enabled && sk && sk == skb->sk) { \
+ typeof(sk) __sk = sk_to_full_sk(sk); \
+ if (sk_fullsock(__sk)) \
+ __ret = __cgroup_bpf_run_filter_skb(__sk, skb, \
+ BPF_CGROUP_INET_EGRESS); \
+ } \
+ __ret; \
+})
+
+#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) \
+({ \
+ int __ret = 0; \
+ if (cgroup_bpf_enabled && sk) { \
+ __ret = __cgroup_bpf_run_filter_sk(sk, \
+ BPF_CGROUP_INET_SOCK_CREATE); \
+ } \
+ __ret; \
+})
+
+#else
+
+struct cgroup_bpf {};
+static inline void cgroup_bpf_put(struct cgroup *cgrp) {}
+static inline void cgroup_bpf_inherit(struct cgroup *cgrp,
+ struct cgroup *parent) {}
+
+#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
+
+#endif /* CONFIG_CGROUP_BPF */
+
+#endif /* _BPF_CGROUP_H */
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index c201017b5730..8796ff03f472 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -216,6 +216,7 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
+void bpf_prog_calc_digest(struct bpf_prog *fp);
const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
@@ -233,13 +234,14 @@ void bpf_register_map_type(struct bpf_map_type_list *tl);
struct bpf_prog *bpf_prog_get(u32 ufd);
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type);
-struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i);
-struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
+struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i);
+void bpf_prog_sub(struct bpf_prog *prog, int i);
+struct bpf_prog * __must_check bpf_prog_inc(struct bpf_prog *prog);
void bpf_prog_put(struct bpf_prog *prog);
struct bpf_map *bpf_map_get_with_uref(u32 ufd);
struct bpf_map *__bpf_map_get(struct fd f);
-struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref);
+struct bpf_map * __must_check bpf_map_inc(struct bpf_map *map, bool uref);
void bpf_map_put_with_uref(struct bpf_map *map);
void bpf_map_put(struct bpf_map *map);
int bpf_map_precharge_memlock(u32 pages);
@@ -298,15 +300,21 @@ static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
{
return ERR_PTR(-EOPNOTSUPP);
}
-static inline struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
+static inline struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog,
+ int i)
{
return ERR_PTR(-EOPNOTSUPP);
}
+static inline void bpf_prog_sub(struct bpf_prog *prog, int i)
+{
+}
+
static inline void bpf_prog_put(struct bpf_prog *prog)
{
}
-static inline struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
+
+static inline struct bpf_prog * __must_check bpf_prog_inc(struct bpf_prog *prog)
{
return ERR_PTR(-EOPNOTSUPP);
}
@@ -319,6 +327,7 @@ extern const struct bpf_func_proto bpf_map_delete_elem_proto;
extern const struct bpf_func_proto bpf_get_prandom_u32_proto;
extern const struct bpf_func_proto bpf_get_smp_processor_id_proto;
+extern const struct bpf_func_proto bpf_get_numa_node_id_proto;
extern const struct bpf_func_proto bpf_tail_call_proto;
extern const struct bpf_func_proto bpf_ktime_get_ns_proto;
extern const struct bpf_func_proto bpf_get_current_pid_tgid_proto;
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 6aaf425cebc3..a13b031dc6b8 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -18,19 +18,12 @@
struct bpf_reg_state {
enum bpf_reg_type type;
- /*
- * Used to determine if any memory access using this register will
- * result in a bad access.
- */
- s64 min_value;
- u64 max_value;
union {
/* valid when type == CONST_IMM | PTR_TO_STACK | UNKNOWN_VALUE */
s64 imm;
/* valid when type == PTR_TO_PACKET* */
struct {
- u32 id;
u16 off;
u16 range;
};
@@ -40,6 +33,13 @@ struct bpf_reg_state {
*/
struct bpf_map *map_ptr;
};
+ u32 id;
+ /* Used to determine if any memory access using this register will
+ * result in a bad access. These two fields must be last.
+ * See states_equal()
+ */
+ s64 min_value;
+ u64 max_value;
};
enum bpf_stack_slot_type {
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index e3354b74286c..4f7d8be9ddbf 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -13,11 +13,13 @@
#define PHY_ID_BCM5241 0x0143bc30
#define PHY_ID_BCMAC131 0x0143bc70
#define PHY_ID_BCM5481 0x0143bca0
+#define PHY_ID_BCM54810 0x03625d00
#define PHY_ID_BCM5482 0x0143bcb0
#define PHY_ID_BCM5411 0x00206070
#define PHY_ID_BCM5421 0x002060e0
#define PHY_ID_BCM5464 0x002060b0
#define PHY_ID_BCM5461 0x002060c0
+#define PHY_ID_BCM54612E 0x03625e60
#define PHY_ID_BCM54616S 0x03625d10
#define PHY_ID_BCM57780 0x03625d90
@@ -55,6 +57,7 @@
#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
#define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
#define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
+
/* Broadcom BCM7xxx specific workarounds */
#define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
#define PHY_BRCM_7XXX_PATCH(x) ((x) & 0xff)
@@ -105,11 +108,15 @@
#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800
#define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000
+#define MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW 0x0100
#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
+#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN (1 << 8)
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN (1 << 4)
-#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
/*
* Broadcom LED source encodings. These are used in BCM5461, BCM5481,
@@ -124,6 +131,7 @@
#define BCM_LED_SRC_INTR 0x6
#define BCM_LED_SRC_QUALITY 0x7
#define BCM_LED_SRC_RCVLED 0x8
+#define BCM_LED_SRC_WIRESPEED 0x9
#define BCM_LED_SRC_MULTICOLOR1 0xa
#define BCM_LED_SRC_OPENSHORT 0xb
#define BCM_LED_SRC_OFF 0xe /* Tied high */
@@ -135,6 +143,14 @@
* Shadow values go into bits [14:10] of register 0x1c to select a shadow
* register to access.
*/
+
+/* 00100: Reserved control register 2 */
+#define BCM54XX_SHD_SCR2 0x04
+#define BCM54XX_SHD_SCR2_WSPD_RTRY_DIS 0x100
+#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT 2
+#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET 2
+#define BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK 0x7
+
/* 00101: Spare Control Register 3 */
#define BCM54XX_SHD_SCR3 0x05
#define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001
@@ -189,6 +205,12 @@
#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
+/* BCM54810 Registers */
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90)
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0)
+#define BCM54810_SHD_CLK_CTL 0x3
+#define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9)
+
/*****************************************************************************/
/* Fast Ethernet Transceiver definitions. */
@@ -222,6 +244,9 @@
#define LPI_FEATURE_EN_DIG1000X 0x4000
/* Core register definitions*/
+#define MII_BRCM_CORE_BASE12 0x12
+#define MII_BRCM_CORE_BASE13 0x13
+#define MII_BRCM_CORE_BASE14 0x14
#define MII_BRCM_CORE_BASE1E 0x1E
#define MII_BRCM_CORE_EXPB0 0xB0
#define MII_BRCM_CORE_EXPB1 0xB1
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 292d6a10b0c2..baff2e8fc8a8 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -121,4 +121,21 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
}
#endif /* CONFIG_GENERIC_BUG */
+
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures, this returns false if the corruption condition is found.
+ */
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...) \
+ do { \
+ if (unlikely(condition)) { \
+ if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+ pr_err(fmt, ##__VA_ARGS__); \
+ BUG(); \
+ } else \
+ WARN(1, fmt, ##__VA_ARGS__); \
+ return false; \
+ } \
+ } while (0)
+
#endif /* _LINUX_BUG_H */
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h
index 8dbd7879fdc6..67bcef2ecddb 100644
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -1,7 +1,7 @@
#ifndef __FS_CEPH_MESSENGER_H
#define __FS_CEPH_MESSENGER_H
-#include <linux/blk_types.h>
+#include <linux/bvec.h>
#include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/net.h>
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 5b17de62c962..861b4677fc5b 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -16,6 +16,7 @@
#include <linux/percpu-refcount.h>
#include <linux/percpu-rwsem.h>
#include <linux/workqueue.h>
+#include <linux/bpf-cgroup.h>
#ifdef CONFIG_CGROUPS
@@ -300,6 +301,9 @@ struct cgroup {
/* used to schedule release agent */
struct work_struct release_agent_work;
+ /* used to store eBPF programs */
+ struct cgroup_bpf bpf;
+
/* ids of the ancestors at each level including self */
int ancestor_ids[];
};
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 123c02788807..e9d36b3e49de 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -17,8 +17,9 @@
#include <linux/notifier.h>
struct device;
-
struct clk;
+struct device_node;
+struct of_phandle_args;
/**
* DOC: clk notifier callback types
@@ -249,6 +250,23 @@ struct clk *clk_get(struct device *dev, const char *id);
struct clk *devm_clk_get(struct device *dev, const char *id);
/**
+ * devm_get_clk_from_child - lookup and obtain a managed reference to a
+ * clock producer from child node.
+ * @dev: device for clock "consumer"
+ * @np: pointer to clock consumer node
+ * @con_id: clock consumer ID
+ *
+ * This function parses the clocks, and uses them to look up the
+ * struct clk from the registered list of clock providers by using
+ * @np and @con_id
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_get_clk_from_child(struct device *dev,
+ struct device_node *np, const char *con_id);
+
+/**
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
*
@@ -432,6 +450,12 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
return NULL;
}
+static inline struct clk *devm_get_clk_from_child(struct device *dev,
+ struct device_node *np, const char *con_id)
+{
+ return NULL;
+}
+
static inline void clk_put(struct clk *clk) {}
static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
@@ -501,9 +525,6 @@ static inline void clk_disable_unprepare(struct clk *clk)
clk_unprepare(clk);
}
-struct device_node;
-struct of_phandle_args;
-
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get(struct device_node *np, int index);
struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h
index ba6fa4148515..9ebf1f8243bb 100644
--- a/include/linux/clk/renesas.h
+++ b/include/linux/clk/renesas.h
@@ -20,10 +20,6 @@ struct device;
struct device_node;
struct generic_pm_domain;
-void r8a7778_clocks_init(u32 mode);
-void r8a7779_clocks_init(u32 mode);
-void rcar_gen2_clocks_init(u32 mode);
-
void cpg_mstp_add_clk_domain(struct device_node *np);
#ifdef CONFIG_CLK_RENESAS_CPG_MSTP
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev);
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 08398182f56e..65602d395a52 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -169,7 +169,10 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
* @mult: cycle to nanosecond multiplier
* @shift: cycle to nanosecond divisor (power of two)
*
- * Converts cycles to nanoseconds, using the given mult and shift.
+ * Converts clocksource cycles to nanoseconds, using the given @mult and @shift.
+ * The code is optimized for performance and is not intended to work
+ * with absolute clocksource cycles (as those will easily overflow),
+ * but is only intended to be used with relative (delta) clocksource cycles.
*
* XXX - This could use some mult_lxl_ll() asm optimization
*/
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 29f9e774ab76..6f0a91b37f68 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -1,6 +1,9 @@
#ifndef __CMA_H__
#define __CMA_H__
+#include <linux/init.h>
+#include <linux/types.h>
+
/*
* There is always at least global CMA area and a few optional
* areas configured in kernel .config.
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 928e5ca0caee..0444b1336268 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -21,7 +21,7 @@
* clobbered. The issue is as follows: while the inline asm might
* access any memory it wants, the compiler could have fit all of
* @ptr into memory registers instead, and since @ptr never escaped
- * from that, it proofed that the inline asm wasn't touching any of
+ * from that, it proved that the inline asm wasn't touching any of
* it. This version works well with both compilers, i.e. we're telling
* the compiler that the inline asm absolutely may see the contents
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index b886dc17f2f3..09807c2ce328 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -93,22 +93,16 @@ extern bool cpuhp_tasks_frozen;
{ .notifier_call = fn, .priority = pri }; \
__register_cpu_notifier(&fn##_nb); \
}
-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
-#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#ifdef CONFIG_HOTPLUG_CPU
extern int register_cpu_notifier(struct notifier_block *nb);
extern int __register_cpu_notifier(struct notifier_block *nb);
extern void unregister_cpu_notifier(struct notifier_block *nb);
extern void __unregister_cpu_notifier(struct notifier_block *nb);
-#else
-#ifndef MODULE
-extern int register_cpu_notifier(struct notifier_block *nb);
-extern int __register_cpu_notifier(struct notifier_block *nb);
-#else
+#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
+#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
+
static inline int register_cpu_notifier(struct notifier_block *nb)
{
return 0;
@@ -118,7 +112,6 @@ static inline int __register_cpu_notifier(struct notifier_block *nb)
{
return 0;
}
-#endif
static inline void unregister_cpu_notifier(struct notifier_block *nb)
{
@@ -245,6 +238,8 @@ void arch_cpu_idle_dead(void);
int cpu_report_state(int cpu);
int cpu_check_up_prepare(int cpu);
void cpu_set_state_online(int cpu);
+void play_idle(unsigned long duration_ms);
+
#ifdef CONFIG_HOTPLUG_CPU
bool cpu_wait_death(unsigned int cpu, int seconds);
bool cpu_report_death(void);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 32dc0cbd51ca..7e05c5e4e45c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -175,7 +175,7 @@ void disable_cpufreq(void);
u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
-int cpufreq_update_policy(unsigned int cpu);
+void cpufreq_update_policy(unsigned int cpu);
bool have_governor_per_policy(void);
struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
void cpufreq_enable_fast_switch(struct cpufreq_policy *policy);
@@ -234,6 +234,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
static struct freq_attr _name = \
__ATTR(_name, 0644, show_##_name, store_##_name)
+#define cpufreq_freq_attr_wo(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0200, NULL, store_##_name)
+
struct global_attr {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj,
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index afe641c02dca..22acee76cf4c 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -16,9 +16,11 @@ enum cpuhp_state {
CPUHP_PERF_SUPERH,
CPUHP_X86_HPET_DEAD,
CPUHP_X86_APB_DEAD,
+ CPUHP_X86_MCE_DEAD,
CPUHP_VIRT_NET_DEAD,
CPUHP_SLUB_DEAD,
CPUHP_MM_WRITEBACK_DEAD,
+ CPUHP_MM_VMSTAT_DEAD,
CPUHP_SOFTIRQ_DEAD,
CPUHP_NET_MVNETA_DEAD,
CPUHP_CPUIDLE_DEAD,
@@ -30,6 +32,15 @@ enum cpuhp_state {
CPUHP_ACPI_CPUDRV_DEAD,
CPUHP_S390_PFAULT_DEAD,
CPUHP_BLK_MQ_DEAD,
+ CPUHP_FS_BUFF_DEAD,
+ CPUHP_PRINTK_DEAD,
+ CPUHP_MM_MEMCQ_DEAD,
+ CPUHP_PERCPU_CNT_DEAD,
+ CPUHP_RADIX_DEAD,
+ CPUHP_PAGE_ALLOC_DEAD,
+ CPUHP_NET_DEV_DEAD,
+ CPUHP_PCI_XGENE_DEAD,
+ CPUHP_IOMMU_INTEL_DEAD,
CPUHP_WORKQUEUE_PREP,
CPUHP_POWER_NUMA_PREPARE,
CPUHP_HRTIMERS_PREPARE,
@@ -49,6 +60,16 @@ enum cpuhp_state {
CPUHP_ARM_SHMOBILE_SCU_PREPARE,
CPUHP_SH_SH3X_PREPARE,
CPUHP_BLK_MQ_PREPARE,
+ CPUHP_NET_FLOW_PREPARE,
+ CPUHP_TOPOLOGY_PREPARE,
+ CPUHP_NET_IUCV_PREPARE,
+ CPUHP_ARM_BL_PREPARE,
+ CPUHP_TRACE_RB_PREPARE,
+ CPUHP_MM_ZS_PREPARE,
+ CPUHP_MM_ZSWP_MEM_PREPARE,
+ CPUHP_MM_ZSWP_POOL_PREPARE,
+ CPUHP_KVM_PPC_BOOK3S_PREPARE,
+ CPUHP_ZCOMP_PREPARE,
CPUHP_TIMERS_DEAD,
CPUHP_NOTF_ERR_INJ_PREPARE,
CPUHP_MIPS_SOC_PREPARE,
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index bb31373c3478..da346f2817a8 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -74,6 +74,7 @@ struct cpuidle_driver_kobj;
struct cpuidle_device {
unsigned int registered:1;
unsigned int enabled:1;
+ unsigned int use_deepest_state:1;
unsigned int cpu;
int last_residency;
@@ -192,11 +193,12 @@ static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
#endif
-#if defined(CONFIG_CPU_IDLE) && defined(CONFIG_SUSPEND)
+#ifdef CONFIG_CPU_IDLE
extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
struct cpuidle_device *dev);
extern int cpuidle_enter_freeze(struct cpuidle_driver *drv,
struct cpuidle_device *dev);
+extern void cpuidle_use_deepest_state(bool enable);
#else
static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
struct cpuidle_device *dev)
@@ -204,6 +206,9 @@ static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
static inline int cpuidle_enter_freeze(struct cpuidle_driver *drv,
struct cpuidle_device *dev)
{return -ENODEV; }
+static inline void cpuidle_use_deepest_state(bool enable)
+{
+}
#endif
/* kernel/sched/idle.c */
@@ -235,8 +240,6 @@ struct cpuidle_governor {
int (*select) (struct cpuidle_driver *drv,
struct cpuidle_device *dev);
void (*reflect) (struct cpuidle_device *dev, int index);
-
- struct module *owner;
};
#ifdef CONFIG_CPU_IDLE
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 4d3f0d1aec73..bf1907d96097 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -52,7 +52,8 @@ extern struct srcu_struct debugfs_srcu;
* Must only be called under the protection established by
* debugfs_use_file_start().
*/
-static inline const struct file_operations *debugfs_real_fops(struct file *filp)
+static inline const struct file_operations *
+debugfs_real_fops(const struct file *filp)
__must_hold(&debugfs_srcu)
{
/*
diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h
index 7adf6cc4b305..c35d0c0e0ada 100644
--- a/include/linux/devfreq_cooling.h
+++ b/include/linux/devfreq_cooling.h
@@ -20,7 +20,6 @@
#include <linux/devfreq.h>
#include <linux/thermal.h>
-#ifdef CONFIG_DEVFREQ_THERMAL
/**
* struct devfreq_cooling_power - Devfreq cooling power ops
@@ -37,12 +36,16 @@
* @dyn_power_coeff * frequency * voltage^2
*/
struct devfreq_cooling_power {
- unsigned long (*get_static_power)(unsigned long voltage);
- unsigned long (*get_dynamic_power)(unsigned long freq,
+ unsigned long (*get_static_power)(struct devfreq *devfreq,
+ unsigned long voltage);
+ unsigned long (*get_dynamic_power)(struct devfreq *devfreq,
+ unsigned long freq,
unsigned long voltage);
unsigned long dyn_power_coeff;
};
+#ifdef CONFIG_DEVFREQ_THERMAL
+
struct thermal_cooling_device *
of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
struct devfreq_cooling_power *dfc_power);
diff --git a/include/linux/device.h b/include/linux/device.h
index bc41e87a969b..94926d3ad6c6 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -698,6 +698,25 @@ static inline int devm_add_action_or_reset(struct device *dev,
return ret;
}
+/**
+ * devm_alloc_percpu - Resource-managed alloc_percpu
+ * @dev: Device to allocate per-cpu memory for
+ * @type: Type to allocate per-cpu memory for
+ *
+ * Managed alloc_percpu. Per-cpu memory allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+#define devm_alloc_percpu(dev, type) \
+ ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), \
+ __alignof__(type)))
+
+void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
+ size_t align);
+void devm_free_percpu(struct device *dev, void __percpu *pdata);
+
struct device_dma_parameters {
/*
* a low level driver may set these to teach IOMMU code about
@@ -733,7 +752,7 @@ struct device_dma_parameters {
* minimizes board-specific #ifdefs in drivers.
* @driver_data: Private pointer for driver specific info.
* @power: For device power management.
- * See Documentation/power/devices.txt for details.
+ * See Documentation/power/admin-guide/devices.rst for details.
* @pm_domain: Provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions
* along with subsystem-level and driver-level callbacks.
diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
index b91b023deffb..a52c6580cc9a 100644
--- a/include/linux/dm-io.h
+++ b/include/linux/dm-io.h
@@ -58,7 +58,7 @@ struct dm_io_notify {
struct dm_io_client;
struct dm_io_request {
int bi_op; /* REQ_OP */
- int bi_op_flags; /* rq_flag_bits */
+ int bi_op_flags; /* req_flag_bits */
struct dm_io_memory mem; /* Memory to use for io */
struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
struct dm_io_client *client; /* Client memory handler */
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index e0b0741ae671..8daeb3ce0016 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -30,7 +30,7 @@
#include <linux/list.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/wait.h>
struct device;
@@ -143,7 +143,7 @@ struct dma_buf {
wait_queue_head_t poll;
struct dma_buf_poll_cb_t {
- struct fence_cb cb;
+ struct dma_fence_cb cb;
wait_queue_head_t *poll;
unsigned long active;
diff --git a/include/linux/dma-fence-array.h b/include/linux/dma-fence-array.h
new file mode 100644
index 000000000000..5900945f962d
--- /dev/null
+++ b/include/linux/dma-fence-array.h
@@ -0,0 +1,86 @@
+/*
+ * fence-array: aggregates fence to be waited together
+ *
+ * Copyright (C) 2016 Collabora Ltd
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ * Authors:
+ * Gustavo Padovan <gustavo@padovan.org>
+ * Christian König <christian.koenig@amd.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.
+ */
+
+#ifndef __LINUX_DMA_FENCE_ARRAY_H
+#define __LINUX_DMA_FENCE_ARRAY_H
+
+#include <linux/dma-fence.h>
+
+/**
+ * struct dma_fence_array_cb - callback helper for fence array
+ * @cb: fence callback structure for signaling
+ * @array: reference to the parent fence array object
+ */
+struct dma_fence_array_cb {
+ struct dma_fence_cb cb;
+ struct dma_fence_array *array;
+};
+
+/**
+ * struct dma_fence_array - fence to represent an array of fences
+ * @base: fence base class
+ * @lock: spinlock for fence handling
+ * @num_fences: number of fences in the array
+ * @num_pending: fences in the array still pending
+ * @fences: array of the fences
+ */
+struct dma_fence_array {
+ struct dma_fence base;
+
+ spinlock_t lock;
+ unsigned num_fences;
+ atomic_t num_pending;
+ struct dma_fence **fences;
+};
+
+extern const struct dma_fence_ops dma_fence_array_ops;
+
+/**
+ * dma_fence_is_array - check if a fence is from the array subsclass
+ * @fence: fence to test
+ *
+ * Return true if it is a dma_fence_array and false otherwise.
+ */
+static inline bool dma_fence_is_array(struct dma_fence *fence)
+{
+ return fence->ops == &dma_fence_array_ops;
+}
+
+/**
+ * to_dma_fence_array - cast a fence to a dma_fence_array
+ * @fence: fence to cast to a dma_fence_array
+ *
+ * Returns NULL if the fence is not a dma_fence_array,
+ * or the dma_fence_array otherwise.
+ */
+static inline struct dma_fence_array *
+to_dma_fence_array(struct dma_fence *fence)
+{
+ if (fence->ops != &dma_fence_array_ops)
+ return NULL;
+
+ return container_of(fence, struct dma_fence_array, base);
+}
+
+struct dma_fence_array *dma_fence_array_create(int num_fences,
+ struct dma_fence **fences,
+ u64 context, unsigned seqno,
+ bool signal_on_any);
+
+#endif /* __LINUX_DMA_FENCE_ARRAY_H */
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
new file mode 100644
index 000000000000..d51a7d23c358
--- /dev/null
+++ b/include/linux/dma-fence.h
@@ -0,0 +1,438 @@
+/*
+ * Fence mechanism for dma-buf to allow for asynchronous dma access
+ *
+ * Copyright (C) 2012 Canonical Ltd
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Maarten Lankhorst <maarten.lankhorst@canonical.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.
+ */
+
+#ifndef __LINUX_DMA_FENCE_H
+#define __LINUX_DMA_FENCE_H
+
+#include <linux/err.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/kref.h>
+#include <linux/sched.h>
+#include <linux/printk.h>
+#include <linux/rcupdate.h>
+
+struct dma_fence;
+struct dma_fence_ops;
+struct dma_fence_cb;
+
+/**
+ * struct dma_fence - software synchronization primitive
+ * @refcount: refcount for this fence
+ * @ops: dma_fence_ops associated with this fence
+ * @rcu: used for releasing fence with kfree_rcu
+ * @cb_list: list of all callbacks to call
+ * @lock: spin_lock_irqsave used for locking
+ * @context: execution context this fence belongs to, returned by
+ * dma_fence_context_alloc()
+ * @seqno: the sequence number of this fence inside the execution context,
+ * can be compared to decide which fence would be signaled later.
+ * @flags: A mask of DMA_FENCE_FLAG_* defined below
+ * @timestamp: Timestamp when the fence was signaled.
+ * @status: Optional, only valid if < 0, must be set before calling
+ * dma_fence_signal, indicates that the fence has completed with an error.
+ *
+ * the flags member must be manipulated and read using the appropriate
+ * atomic ops (bit_*), so taking the spinlock will not be needed most
+ * of the time.
+ *
+ * DMA_FENCE_FLAG_SIGNALED_BIT - fence is already signaled
+ * DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT - enable_signaling might have been called
+ * DMA_FENCE_FLAG_USER_BITS - start of the unused bits, can be used by the
+ * implementer of the fence for its own purposes. Can be used in different
+ * ways by different fence implementers, so do not rely on this.
+ *
+ * Since atomic bitops are used, this is not guaranteed to be the case.
+ * Particularly, if the bit was set, but dma_fence_signal was called right
+ * before this bit was set, it would have been able to set the
+ * DMA_FENCE_FLAG_SIGNALED_BIT, before enable_signaling was called.
+ * Adding a check for DMA_FENCE_FLAG_SIGNALED_BIT after setting
+ * DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT closes this race, and makes sure that
+ * after dma_fence_signal was called, any enable_signaling call will have either
+ * been completed, or never called at all.
+ */
+struct dma_fence {
+ struct kref refcount;
+ const struct dma_fence_ops *ops;
+ struct rcu_head rcu;
+ struct list_head cb_list;
+ spinlock_t *lock;
+ u64 context;
+ unsigned seqno;
+ unsigned long flags;
+ ktime_t timestamp;
+ int status;
+};
+
+enum dma_fence_flag_bits {
+ DMA_FENCE_FLAG_SIGNALED_BIT,
+ DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+ DMA_FENCE_FLAG_USER_BITS, /* must always be last member */
+};
+
+typedef void (*dma_fence_func_t)(struct dma_fence *fence,
+ struct dma_fence_cb *cb);
+
+/**
+ * struct dma_fence_cb - callback for dma_fence_add_callback
+ * @node: used by dma_fence_add_callback to append this struct to fence::cb_list
+ * @func: dma_fence_func_t to call
+ *
+ * This struct will be initialized by dma_fence_add_callback, additional
+ * data can be passed along by embedding dma_fence_cb in another struct.
+ */
+struct dma_fence_cb {
+ struct list_head node;
+ dma_fence_func_t func;
+};
+
+/**
+ * struct dma_fence_ops - operations implemented for fence
+ * @get_driver_name: returns the driver name.
+ * @get_timeline_name: return the name of the context this fence belongs to.
+ * @enable_signaling: enable software signaling of fence.
+ * @signaled: [optional] peek whether the fence is signaled, can be null.
+ * @wait: custom wait implementation, or dma_fence_default_wait.
+ * @release: [optional] called on destruction of fence, can be null
+ * @fill_driver_data: [optional] callback to fill in free-form debug info
+ * Returns amount of bytes filled, or -errno.
+ * @fence_value_str: [optional] fills in the value of the fence as a string
+ * @timeline_value_str: [optional] fills in the current value of the timeline
+ * as a string
+ *
+ * Notes on enable_signaling:
+ * For fence implementations that have the capability for hw->hw
+ * signaling, they can implement this op to enable the necessary
+ * irqs, or insert commands into cmdstream, etc. This is called
+ * in the first wait() or add_callback() path to let the fence
+ * implementation know that there is another driver waiting on
+ * the signal (ie. hw->sw case).
+ *
+ * This function can be called called from atomic context, but not
+ * from irq context, so normal spinlocks can be used.
+ *
+ * A return value of false indicates the fence already passed,
+ * or some failure occurred that made it impossible to enable
+ * signaling. True indicates successful enabling.
+ *
+ * fence->status may be set in enable_signaling, but only when false is
+ * returned.
+ *
+ * Calling dma_fence_signal before enable_signaling is called allows
+ * for a tiny race window in which enable_signaling is called during,
+ * before, or after dma_fence_signal. To fight this, it is recommended
+ * that before enable_signaling returns true an extra reference is
+ * taken on the fence, to be released when the fence is signaled.
+ * This will mean dma_fence_signal will still be called twice, but
+ * the second time will be a noop since it was already signaled.
+ *
+ * Notes on signaled:
+ * May set fence->status if returning true.
+ *
+ * Notes on wait:
+ * Must not be NULL, set to dma_fence_default_wait for default implementation.
+ * the dma_fence_default_wait implementation should work for any fence, as long
+ * as enable_signaling works correctly.
+ *
+ * Must return -ERESTARTSYS if the wait is intr = true and the wait was
+ * interrupted, and remaining jiffies if fence has signaled, or 0 if wait
+ * timed out. Can also return other error values on custom implementations,
+ * which should be treated as if the fence is signaled. For example a hardware
+ * lockup could be reported like that.
+ *
+ * Notes on release:
+ * Can be NULL, this function allows additional commands to run on
+ * destruction of the fence. Can be called from irq context.
+ * If pointer is set to NULL, kfree will get called instead.
+ */
+
+struct dma_fence_ops {
+ const char * (*get_driver_name)(struct dma_fence *fence);
+ const char * (*get_timeline_name)(struct dma_fence *fence);
+ bool (*enable_signaling)(struct dma_fence *fence);
+ bool (*signaled)(struct dma_fence *fence);
+ signed long (*wait)(struct dma_fence *fence,
+ bool intr, signed long timeout);
+ void (*release)(struct dma_fence *fence);
+
+ int (*fill_driver_data)(struct dma_fence *fence, void *data, int size);
+ void (*fence_value_str)(struct dma_fence *fence, char *str, int size);
+ void (*timeline_value_str)(struct dma_fence *fence,
+ char *str, int size);
+};
+
+void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
+ spinlock_t *lock, u64 context, unsigned seqno);
+
+void dma_fence_release(struct kref *kref);
+void dma_fence_free(struct dma_fence *fence);
+
+/**
+ * dma_fence_put - decreases refcount of the fence
+ * @fence: [in] fence to reduce refcount of
+ */
+static inline void dma_fence_put(struct dma_fence *fence)
+{
+ if (fence)
+ kref_put(&fence->refcount, dma_fence_release);
+}
+
+/**
+ * dma_fence_get - increases refcount of the fence
+ * @fence: [in] fence to increase refcount of
+ *
+ * Returns the same fence, with refcount increased by 1.
+ */
+static inline struct dma_fence *dma_fence_get(struct dma_fence *fence)
+{
+ if (fence)
+ kref_get(&fence->refcount);
+ return fence;
+}
+
+/**
+ * dma_fence_get_rcu - get a fence from a reservation_object_list with
+ * rcu read lock
+ * @fence: [in] fence to increase refcount of
+ *
+ * Function returns NULL if no refcount could be obtained, or the fence.
+ */
+static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence)
+{
+ if (kref_get_unless_zero(&fence->refcount))
+ return fence;
+ else
+ return NULL;
+}
+
+/**
+ * dma_fence_get_rcu_safe - acquire a reference to an RCU tracked fence
+ * @fencep: [in] pointer to fence to increase refcount of
+ *
+ * Function returns NULL if no refcount could be obtained, or the fence.
+ * This function handles acquiring a reference to a fence that may be
+ * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU),
+ * so long as the caller is using RCU on the pointer to the fence.
+ *
+ * An alternative mechanism is to employ a seqlock to protect a bunch of
+ * fences, such as used by struct reservation_object. When using a seqlock,
+ * the seqlock must be taken before and checked after a reference to the
+ * fence is acquired (as shown here).
+ *
+ * The caller is required to hold the RCU read lock.
+ */
+static inline struct dma_fence *
+dma_fence_get_rcu_safe(struct dma_fence * __rcu *fencep)
+{
+ do {
+ struct dma_fence *fence;
+
+ fence = rcu_dereference(*fencep);
+ if (!fence || !dma_fence_get_rcu(fence))
+ return NULL;
+
+ /* The atomic_inc_not_zero() inside dma_fence_get_rcu()
+ * provides a full memory barrier upon success (such as now).
+ * This is paired with the write barrier from assigning
+ * to the __rcu protected fence pointer so that if that
+ * pointer still matches the current fence, we know we
+ * have successfully acquire a reference to it. If it no
+ * longer matches, we are holding a reference to some other
+ * reallocated pointer. This is possible if the allocator
+ * is using a freelist like SLAB_DESTROY_BY_RCU where the
+ * fence remains valid for the RCU grace period, but it
+ * may be reallocated. When using such allocators, we are
+ * responsible for ensuring the reference we get is to
+ * the right fence, as below.
+ */
+ if (fence == rcu_access_pointer(*fencep))
+ return rcu_pointer_handoff(fence);
+
+ dma_fence_put(fence);
+ } while (1);
+}
+
+int dma_fence_signal(struct dma_fence *fence);
+int dma_fence_signal_locked(struct dma_fence *fence);
+signed long dma_fence_default_wait(struct dma_fence *fence,
+ bool intr, signed long timeout);
+int dma_fence_add_callback(struct dma_fence *fence,
+ struct dma_fence_cb *cb,
+ dma_fence_func_t func);
+bool dma_fence_remove_callback(struct dma_fence *fence,
+ struct dma_fence_cb *cb);
+void dma_fence_enable_sw_signaling(struct dma_fence *fence);
+
+/**
+ * dma_fence_is_signaled_locked - Return an indication if the fence
+ * is signaled yet.
+ * @fence: [in] the fence to check
+ *
+ * Returns true if the fence was already signaled, false if not. Since this
+ * function doesn't enable signaling, it is not guaranteed to ever return
+ * true if dma_fence_add_callback, dma_fence_wait or
+ * dma_fence_enable_sw_signaling haven't been called before.
+ *
+ * This function requires fence->lock to be held.
+ */
+static inline bool
+dma_fence_is_signaled_locked(struct dma_fence *fence)
+{
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return true;
+
+ if (fence->ops->signaled && fence->ops->signaled(fence)) {
+ dma_fence_signal_locked(fence);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * dma_fence_is_signaled - Return an indication if the fence is signaled yet.
+ * @fence: [in] the fence to check
+ *
+ * Returns true if the fence was already signaled, false if not. Since this
+ * function doesn't enable signaling, it is not guaranteed to ever return
+ * true if dma_fence_add_callback, dma_fence_wait or
+ * dma_fence_enable_sw_signaling haven't been called before.
+ *
+ * It's recommended for seqno fences to call dma_fence_signal when the
+ * operation is complete, it makes it possible to prevent issues from
+ * wraparound between time of issue and time of use by checking the return
+ * value of this function before calling hardware-specific wait instructions.
+ */
+static inline bool
+dma_fence_is_signaled(struct dma_fence *fence)
+{
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return true;
+
+ if (fence->ops->signaled && fence->ops->signaled(fence)) {
+ dma_fence_signal(fence);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * dma_fence_is_later - return if f1 is chronologically later than f2
+ * @f1: [in] the first fence from the same context
+ * @f2: [in] the second fence from the same context
+ *
+ * Returns true if f1 is chronologically later than f2. Both fences must be
+ * from the same context, since a seqno is not re-used across contexts.
+ */
+static inline bool dma_fence_is_later(struct dma_fence *f1,
+ struct dma_fence *f2)
+{
+ if (WARN_ON(f1->context != f2->context))
+ return false;
+
+ return (int)(f1->seqno - f2->seqno) > 0;
+}
+
+/**
+ * dma_fence_later - return the chronologically later fence
+ * @f1: [in] the first fence from the same context
+ * @f2: [in] the second fence from the same context
+ *
+ * Returns NULL if both fences are signaled, otherwise the fence that would be
+ * signaled last. Both fences must be from the same context, since a seqno is
+ * not re-used across contexts.
+ */
+static inline struct dma_fence *dma_fence_later(struct dma_fence *f1,
+ struct dma_fence *f2)
+{
+ if (WARN_ON(f1->context != f2->context))
+ return NULL;
+
+ /*
+ * Can't check just DMA_FENCE_FLAG_SIGNALED_BIT here, it may never
+ * have been set if enable_signaling wasn't called, and enabling that
+ * here is overkill.
+ */
+ if (dma_fence_is_later(f1, f2))
+ return dma_fence_is_signaled(f1) ? NULL : f1;
+ else
+ return dma_fence_is_signaled(f2) ? NULL : f2;
+}
+
+signed long dma_fence_wait_timeout(struct dma_fence *,
+ bool intr, signed long timeout);
+signed long dma_fence_wait_any_timeout(struct dma_fence **fences,
+ uint32_t count,
+ bool intr, signed long timeout,
+ uint32_t *idx);
+
+/**
+ * dma_fence_wait - sleep until the fence gets signaled
+ * @fence: [in] the fence to wait on
+ * @intr: [in] if true, do an interruptible wait
+ *
+ * This function will return -ERESTARTSYS if interrupted by a signal,
+ * or 0 if the fence was signaled. Other error values may be
+ * returned on custom implementations.
+ *
+ * Performs a synchronous wait on this fence. It is assumed the caller
+ * directly or indirectly holds a reference to the fence, otherwise the
+ * fence might be freed before return, resulting in undefined behavior.
+ */
+static inline signed long dma_fence_wait(struct dma_fence *fence, bool intr)
+{
+ signed long ret;
+
+ /* Since dma_fence_wait_timeout cannot timeout with
+ * MAX_SCHEDULE_TIMEOUT, only valid return values are
+ * -ERESTARTSYS and MAX_SCHEDULE_TIMEOUT.
+ */
+ ret = dma_fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT);
+
+ return ret < 0 ? ret : 0;
+}
+
+u64 dma_fence_context_alloc(unsigned num);
+
+#define DMA_FENCE_TRACE(f, fmt, args...) \
+ do { \
+ struct dma_fence *__ff = (f); \
+ if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE)) \
+ pr_info("f %llu#%u: " fmt, \
+ __ff->context, __ff->seqno, ##args); \
+ } while (0)
+
+#define DMA_FENCE_WARN(f, fmt, args...) \
+ do { \
+ struct dma_fence *__ff = (f); \
+ pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno, \
+ ##args); \
+ } while (0)
+
+#define DMA_FENCE_ERR(f, fmt, args...) \
+ do { \
+ struct dma_fence *__ff = (f); \
+ pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno, \
+ ##args); \
+ } while (0)
+
+#endif /* __LINUX_DMA_FENCE_H */
diff --git a/include/linux/drbd_genl.h b/include/linux/drbd_genl.h
index c934d3a96b5e..2896f93808ae 100644
--- a/include/linux/drbd_genl.h
+++ b/include/linux/drbd_genl.h
@@ -67,7 +67,7 @@
* genl_magic_func.h
* generates an entry in the static genl_ops array,
* and static register/unregister functions to
- * genl_register_family_with_ops().
+ * genl_register_family().
*
* flags and handler:
* GENL_op_init( .doit = x, .dumpit = y, .flags = something)
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 9e0d78966552..cb56dcba68c6 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -134,6 +134,7 @@ enum dev_type {
enum hw_event_mc_err_type {
HW_EVENT_ERR_CORRECTED,
HW_EVENT_ERR_UNCORRECTED,
+ HW_EVENT_ERR_DEFERRED,
HW_EVENT_ERR_FATAL,
HW_EVENT_ERR_INFO,
};
@@ -145,6 +146,8 @@ static inline char *mc_event_error_type(const unsigned int err_type)
return "Corrected";
case HW_EVENT_ERR_UNCORRECTED:
return "Uncorrected";
+ case HW_EVENT_ERR_DEFERRED:
+ return "Deferred";
case HW_EVENT_ERR_FATAL:
return "Fatal";
default:
@@ -192,10 +195,11 @@ static inline char *mc_event_error_type(const unsigned int err_type)
* @MEM_DDR3: DDR3 RAM
* @MEM_RDDR3: Registered DDR3 RAM
* This is a variant of the DDR3 memories.
- * @MEM_LRDDR3 Load-Reduced DDR3 memory.
+ * @MEM_LRDDR3: Load-Reduced DDR3 memory.
* @MEM_DDR4: Unbuffered DDR4 RAM
* @MEM_RDDR4: Registered DDR4 RAM
* This is a variant of the DDR4 memories.
+ * @MEM_LRDDR4: Load-Reduced DDR4 memory.
*/
enum mem_type {
MEM_EMPTY = 0,
@@ -218,6 +222,7 @@ enum mem_type {
MEM_LRDDR3,
MEM_DDR4,
MEM_RDDR4,
+ MEM_LRDDR4,
};
#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
@@ -239,6 +244,7 @@ enum mem_type {
#define MEM_FLAG_RDDR3 BIT(MEM_RDDR3)
#define MEM_FLAG_DDR4 BIT(MEM_DDR4)
#define MEM_FLAG_RDDR4 BIT(MEM_RDDR4)
+#define MEM_FLAG_LRDDR4 BIT(MEM_LRDDR4)
/**
* enum edac-type - Error Detection and Correction capabilities and mode
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2d089487d2da..a07a476178cd 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -443,6 +443,22 @@ typedef struct {
#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
+typedef struct {
+ u32 version;
+ u32 get;
+ u32 set;
+ u32 del;
+ u32 get_all;
+} apple_properties_protocol_32_t;
+
+typedef struct {
+ u64 version;
+ u64 get;
+ u64 set;
+ u64 del;
+ u64 get_all;
+} apple_properties_protocol_64_t;
+
/*
* Types and defines for EFI ResetSystem
*/
@@ -589,8 +605,10 @@ void efi_native_runtime_setup(void);
#define DEVICE_TREE_GUID EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
#define EFI_PROPERTIES_TABLE_GUID EFI_GUID(0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
#define EFI_RNG_PROTOCOL_GUID EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+#define EFI_RNG_ALGORITHM_RAW EFI_GUID(0xe43176d7, 0xb6e8, 0x4827, 0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
/*
* This GUID is used to pass to the kernel proper the struct screen_info
@@ -599,6 +617,7 @@ void efi_native_runtime_setup(void);
*/
#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
+#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
typedef struct {
efi_guid_t guid;
@@ -872,6 +891,7 @@ extern struct efi {
unsigned long esrt; /* ESRT table */
unsigned long properties_table; /* properties table */
unsigned long mem_attr_table; /* memory attributes table */
+ unsigned long rng_seed; /* UEFI firmware random seed */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
@@ -1145,6 +1165,26 @@ struct efi_generic_dev_path {
u16 length;
} __attribute ((packed));
+struct efi_dev_path {
+ u8 type; /* can be replaced with unnamed */
+ u8 sub_type; /* struct efi_generic_dev_path; */
+ u16 length; /* once we've moved to -std=c11 */
+ union {
+ struct {
+ u32 hid;
+ u32 uid;
+ } acpi;
+ struct {
+ u8 fn;
+ u8 dev;
+ } pci;
+ };
+} __attribute ((packed));
+
+#if IS_ENABLED(CONFIG_EFI_DEV_PATH_PARSER)
+struct device *efi_get_device_by_path(struct efi_dev_path **node, size_t *len);
+#endif
+
static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
{
*npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr);
@@ -1493,4 +1533,10 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
struct efi_boot_memmap *map,
void *priv,
efi_exit_boot_map_processing priv_func);
+
+struct linux_efi_random_seed {
+ u32 size;
+ u8 bits[];
+};
+
#endif /* _LINUX_EFI_H */
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index e7f358d2e5fc..b276e9ef0e0b 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -30,7 +30,7 @@ typedef int (elevator_dispatch_fn) (struct request_queue *, int);
typedef void (elevator_add_req_fn) (struct request_queue *, struct request *);
typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *);
typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
-typedef int (elevator_may_queue_fn) (struct request_queue *, int, int);
+typedef int (elevator_may_queue_fn) (struct request_queue *, unsigned int);
typedef void (elevator_init_icq_fn) (struct io_cq *);
typedef void (elevator_exit_icq_fn) (struct io_cq *);
@@ -108,6 +108,11 @@ struct elevator_type
#define ELV_HASH_BITS 6
+void elv_rqhash_del(struct request_queue *q, struct request *rq);
+void elv_rqhash_add(struct request_queue *q, struct request *rq);
+void elv_rqhash_reposition(struct request_queue *q, struct request *rq);
+struct request *elv_rqhash_find(struct request_queue *q, sector_t offset);
+
/*
* each queue has an elevator_queue associated with it
*/
@@ -139,7 +144,7 @@ extern struct request *elv_former_request(struct request_queue *, struct request
extern struct request *elv_latter_request(struct request_queue *, struct request *);
extern int elv_register_queue(struct request_queue *q);
extern void elv_unregister_queue(struct request_queue *q);
-extern int elv_may_queue(struct request_queue *, int, int);
+extern int elv_may_queue(struct request_queue *, unsigned int);
extern void elv_completed_request(struct request_queue *, struct request *);
extern int elv_set_request(struct request_queue *q, struct request *rq,
struct bio *bio, gfp_t gfp_mask);
diff --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h
index 9a79f0106da1..32c22cfb238b 100644
--- a/include/linux/fddidevice.h
+++ b/include/linux/fddidevice.h
@@ -26,7 +26,6 @@
#ifdef __KERNEL__
__be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev);
-int fddi_change_mtu(struct net_device *dev, int new_mtu);
struct net_device *alloc_fddidev(int sizeof_priv);
#endif
diff --git a/include/linux/fence-array.h b/include/linux/fence-array.h
deleted file mode 100644
index a44794e508df..000000000000
--- a/include/linux/fence-array.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * fence-array: aggregates fence to be waited together
- *
- * Copyright (C) 2016 Collabora Ltd
- * Copyright (C) 2016 Advanced Micro Devices, Inc.
- * Authors:
- * Gustavo Padovan <gustavo@padovan.org>
- * Christian König <christian.koenig@amd.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.
- */
-
-#ifndef __LINUX_FENCE_ARRAY_H
-#define __LINUX_FENCE_ARRAY_H
-
-#include <linux/fence.h>
-
-/**
- * struct fence_array_cb - callback helper for fence array
- * @cb: fence callback structure for signaling
- * @array: reference to the parent fence array object
- */
-struct fence_array_cb {
- struct fence_cb cb;
- struct fence_array *array;
-};
-
-/**
- * struct fence_array - fence to represent an array of fences
- * @base: fence base class
- * @lock: spinlock for fence handling
- * @num_fences: number of fences in the array
- * @num_pending: fences in the array still pending
- * @fences: array of the fences
- */
-struct fence_array {
- struct fence base;
-
- spinlock_t lock;
- unsigned num_fences;
- atomic_t num_pending;
- struct fence **fences;
-};
-
-extern const struct fence_ops fence_array_ops;
-
-/**
- * fence_is_array - check if a fence is from the array subsclass
- *
- * Return true if it is a fence_array and false otherwise.
- */
-static inline bool fence_is_array(struct fence *fence)
-{
- return fence->ops == &fence_array_ops;
-}
-
-/**
- * to_fence_array - cast a fence to a fence_array
- * @fence: fence to cast to a fence_array
- *
- * Returns NULL if the fence is not a fence_array,
- * or the fence_array otherwise.
- */
-static inline struct fence_array *to_fence_array(struct fence *fence)
-{
- if (fence->ops != &fence_array_ops)
- return NULL;
-
- return container_of(fence, struct fence_array, base);
-}
-
-struct fence_array *fence_array_create(int num_fences, struct fence **fences,
- u64 context, unsigned seqno,
- bool signal_on_any);
-
-#endif /* __LINUX_FENCE_ARRAY_H */
diff --git a/include/linux/fence.h b/include/linux/fence.h
deleted file mode 100644
index 0d763053f97a..000000000000
--- a/include/linux/fence.h
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Fence mechanism for dma-buf to allow for asynchronous dma access
- *
- * Copyright (C) 2012 Canonical Ltd
- * Copyright (C) 2012 Texas Instruments
- *
- * Authors:
- * Rob Clark <robdclark@gmail.com>
- * Maarten Lankhorst <maarten.lankhorst@canonical.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.
- */
-
-#ifndef __LINUX_FENCE_H
-#define __LINUX_FENCE_H
-
-#include <linux/err.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <linux/kref.h>
-#include <linux/sched.h>
-#include <linux/printk.h>
-#include <linux/rcupdate.h>
-
-struct fence;
-struct fence_ops;
-struct fence_cb;
-
-/**
- * struct fence - software synchronization primitive
- * @refcount: refcount for this fence
- * @ops: fence_ops associated with this fence
- * @rcu: used for releasing fence with kfree_rcu
- * @cb_list: list of all callbacks to call
- * @lock: spin_lock_irqsave used for locking
- * @context: execution context this fence belongs to, returned by
- * fence_context_alloc()
- * @seqno: the sequence number of this fence inside the execution context,
- * can be compared to decide which fence would be signaled later.
- * @flags: A mask of FENCE_FLAG_* defined below
- * @timestamp: Timestamp when the fence was signaled.
- * @status: Optional, only valid if < 0, must be set before calling
- * fence_signal, indicates that the fence has completed with an error.
- *
- * the flags member must be manipulated and read using the appropriate
- * atomic ops (bit_*), so taking the spinlock will not be needed most
- * of the time.
- *
- * FENCE_FLAG_SIGNALED_BIT - fence is already signaled
- * FENCE_FLAG_ENABLE_SIGNAL_BIT - enable_signaling might have been called*
- * FENCE_FLAG_USER_BITS - start of the unused bits, can be used by the
- * implementer of the fence for its own purposes. Can be used in different
- * ways by different fence implementers, so do not rely on this.
- *
- * Since atomic bitops are used, this is not guaranteed to be the case.
- * Particularly, if the bit was set, but fence_signal was called right
- * before this bit was set, it would have been able to set the
- * FENCE_FLAG_SIGNALED_BIT, before enable_signaling was called.
- * Adding a check for FENCE_FLAG_SIGNALED_BIT after setting
- * FENCE_FLAG_ENABLE_SIGNAL_BIT closes this race, and makes sure that
- * after fence_signal was called, any enable_signaling call will have either
- * been completed, or never called at all.
- */
-struct fence {
- struct kref refcount;
- const struct fence_ops *ops;
- struct rcu_head rcu;
- struct list_head cb_list;
- spinlock_t *lock;
- u64 context;
- unsigned seqno;
- unsigned long flags;
- ktime_t timestamp;
- int status;
-};
-
-enum fence_flag_bits {
- FENCE_FLAG_SIGNALED_BIT,
- FENCE_FLAG_ENABLE_SIGNAL_BIT,
- FENCE_FLAG_USER_BITS, /* must always be last member */
-};
-
-typedef void (*fence_func_t)(struct fence *fence, struct fence_cb *cb);
-
-/**
- * struct fence_cb - callback for fence_add_callback
- * @node: used by fence_add_callback to append this struct to fence::cb_list
- * @func: fence_func_t to call
- *
- * This struct will be initialized by fence_add_callback, additional
- * data can be passed along by embedding fence_cb in another struct.
- */
-struct fence_cb {
- struct list_head node;
- fence_func_t func;
-};
-
-/**
- * struct fence_ops - operations implemented for fence
- * @get_driver_name: returns the driver name.
- * @get_timeline_name: return the name of the context this fence belongs to.
- * @enable_signaling: enable software signaling of fence.
- * @signaled: [optional] peek whether the fence is signaled, can be null.
- * @wait: custom wait implementation, or fence_default_wait.
- * @release: [optional] called on destruction of fence, can be null
- * @fill_driver_data: [optional] callback to fill in free-form debug info
- * Returns amount of bytes filled, or -errno.
- * @fence_value_str: [optional] fills in the value of the fence as a string
- * @timeline_value_str: [optional] fills in the current value of the timeline
- * as a string
- *
- * Notes on enable_signaling:
- * For fence implementations that have the capability for hw->hw
- * signaling, they can implement this op to enable the necessary
- * irqs, or insert commands into cmdstream, etc. This is called
- * in the first wait() or add_callback() path to let the fence
- * implementation know that there is another driver waiting on
- * the signal (ie. hw->sw case).
- *
- * This function can be called called from atomic context, but not
- * from irq context, so normal spinlocks can be used.
- *
- * A return value of false indicates the fence already passed,
- * or some failure occurred that made it impossible to enable
- * signaling. True indicates successful enabling.
- *
- * fence->status may be set in enable_signaling, but only when false is
- * returned.
- *
- * Calling fence_signal before enable_signaling is called allows
- * for a tiny race window in which enable_signaling is called during,
- * before, or after fence_signal. To fight this, it is recommended
- * that before enable_signaling returns true an extra reference is
- * taken on the fence, to be released when the fence is signaled.
- * This will mean fence_signal will still be called twice, but
- * the second time will be a noop since it was already signaled.
- *
- * Notes on signaled:
- * May set fence->status if returning true.
- *
- * Notes on wait:
- * Must not be NULL, set to fence_default_wait for default implementation.
- * the fence_default_wait implementation should work for any fence, as long
- * as enable_signaling works correctly.
- *
- * Must return -ERESTARTSYS if the wait is intr = true and the wait was
- * interrupted, and remaining jiffies if fence has signaled, or 0 if wait
- * timed out. Can also return other error values on custom implementations,
- * which should be treated as if the fence is signaled. For example a hardware
- * lockup could be reported like that.
- *
- * Notes on release:
- * Can be NULL, this function allows additional commands to run on
- * destruction of the fence. Can be called from irq context.
- * If pointer is set to NULL, kfree will get called instead.
- */
-
-struct fence_ops {
- const char * (*get_driver_name)(struct fence *fence);
- const char * (*get_timeline_name)(struct fence *fence);
- bool (*enable_signaling)(struct fence *fence);
- bool (*signaled)(struct fence *fence);
- signed long (*wait)(struct fence *fence, bool intr, signed long timeout);
- void (*release)(struct fence *fence);
-
- int (*fill_driver_data)(struct fence *fence, void *data, int size);
- void (*fence_value_str)(struct fence *fence, char *str, int size);
- void (*timeline_value_str)(struct fence *fence, char *str, int size);
-};
-
-void fence_init(struct fence *fence, const struct fence_ops *ops,
- spinlock_t *lock, u64 context, unsigned seqno);
-
-void fence_release(struct kref *kref);
-void fence_free(struct fence *fence);
-
-/**
- * fence_get - increases refcount of the fence
- * @fence: [in] fence to increase refcount of
- *
- * Returns the same fence, with refcount increased by 1.
- */
-static inline struct fence *fence_get(struct fence *fence)
-{
- if (fence)
- kref_get(&fence->refcount);
- return fence;
-}
-
-/**
- * fence_get_rcu - get a fence from a reservation_object_list with rcu read lock
- * @fence: [in] fence to increase refcount of
- *
- * Function returns NULL if no refcount could be obtained, or the fence.
- */
-static inline struct fence *fence_get_rcu(struct fence *fence)
-{
- if (kref_get_unless_zero(&fence->refcount))
- return fence;
- else
- return NULL;
-}
-
-/**
- * fence_put - decreases refcount of the fence
- * @fence: [in] fence to reduce refcount of
- */
-static inline void fence_put(struct fence *fence)
-{
- if (fence)
- kref_put(&fence->refcount, fence_release);
-}
-
-int fence_signal(struct fence *fence);
-int fence_signal_locked(struct fence *fence);
-signed long fence_default_wait(struct fence *fence, bool intr, signed long timeout);
-int fence_add_callback(struct fence *fence, struct fence_cb *cb,
- fence_func_t func);
-bool fence_remove_callback(struct fence *fence, struct fence_cb *cb);
-void fence_enable_sw_signaling(struct fence *fence);
-
-/**
- * fence_is_signaled_locked - Return an indication if the fence is signaled yet.
- * @fence: [in] the fence to check
- *
- * Returns true if the fence was already signaled, false if not. Since this
- * function doesn't enable signaling, it is not guaranteed to ever return
- * true if fence_add_callback, fence_wait or fence_enable_sw_signaling
- * haven't been called before.
- *
- * This function requires fence->lock to be held.
- */
-static inline bool
-fence_is_signaled_locked(struct fence *fence)
-{
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
- return true;
-
- if (fence->ops->signaled && fence->ops->signaled(fence)) {
- fence_signal_locked(fence);
- return true;
- }
-
- return false;
-}
-
-/**
- * fence_is_signaled - Return an indication if the fence is signaled yet.
- * @fence: [in] the fence to check
- *
- * Returns true if the fence was already signaled, false if not. Since this
- * function doesn't enable signaling, it is not guaranteed to ever return
- * true if fence_add_callback, fence_wait or fence_enable_sw_signaling
- * haven't been called before.
- *
- * It's recommended for seqno fences to call fence_signal when the
- * operation is complete, it makes it possible to prevent issues from
- * wraparound between time of issue and time of use by checking the return
- * value of this function before calling hardware-specific wait instructions.
- */
-static inline bool
-fence_is_signaled(struct fence *fence)
-{
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
- return true;
-
- if (fence->ops->signaled && fence->ops->signaled(fence)) {
- fence_signal(fence);
- return true;
- }
-
- return false;
-}
-
-/**
- * fence_is_later - return if f1 is chronologically later than f2
- * @f1: [in] the first fence from the same context
- * @f2: [in] the second fence from the same context
- *
- * Returns true if f1 is chronologically later than f2. Both fences must be
- * from the same context, since a seqno is not re-used across contexts.
- */
-static inline bool fence_is_later(struct fence *f1, struct fence *f2)
-{
- if (WARN_ON(f1->context != f2->context))
- return false;
-
- return (int)(f1->seqno - f2->seqno) > 0;
-}
-
-/**
- * fence_later - return the chronologically later fence
- * @f1: [in] the first fence from the same context
- * @f2: [in] the second fence from the same context
- *
- * Returns NULL if both fences are signaled, otherwise the fence that would be
- * signaled last. Both fences must be from the same context, since a seqno is
- * not re-used across contexts.
- */
-static inline struct fence *fence_later(struct fence *f1, struct fence *f2)
-{
- if (WARN_ON(f1->context != f2->context))
- return NULL;
-
- /*
- * can't check just FENCE_FLAG_SIGNALED_BIT here, it may never have been
- * set if enable_signaling wasn't called, and enabling that here is
- * overkill.
- */
- if (fence_is_later(f1, f2))
- return fence_is_signaled(f1) ? NULL : f1;
- else
- return fence_is_signaled(f2) ? NULL : f2;
-}
-
-signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout);
-signed long fence_wait_any_timeout(struct fence **fences, uint32_t count,
- bool intr, signed long timeout);
-
-/**
- * fence_wait - sleep until the fence gets signaled
- * @fence: [in] the fence to wait on
- * @intr: [in] if true, do an interruptible wait
- *
- * This function will return -ERESTARTSYS if interrupted by a signal,
- * or 0 if the fence was signaled. Other error values may be
- * returned on custom implementations.
- *
- * Performs a synchronous wait on this fence. It is assumed the caller
- * directly or indirectly holds a reference to the fence, otherwise the
- * fence might be freed before return, resulting in undefined behavior.
- */
-static inline signed long fence_wait(struct fence *fence, bool intr)
-{
- signed long ret;
-
- /* Since fence_wait_timeout cannot timeout with
- * MAX_SCHEDULE_TIMEOUT, only valid return values are
- * -ERESTARTSYS and MAX_SCHEDULE_TIMEOUT.
- */
- ret = fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT);
-
- return ret < 0 ? ret : 0;
-}
-
-u64 fence_context_alloc(unsigned num);
-
-#define FENCE_TRACE(f, fmt, args...) \
- do { \
- struct fence *__ff = (f); \
- if (IS_ENABLED(CONFIG_FENCE_TRACE)) \
- pr_info("f %llu#%u: " fmt, \
- __ff->context, __ff->seqno, ##args); \
- } while (0)
-
-#define FENCE_WARN(f, fmt, args...) \
- do { \
- struct fence *__ff = (f); \
- pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno, \
- ##args); \
- } while (0)
-
-#define FENCE_ERR(f, fmt, args...) \
- do { \
- struct fence *__ff = (f); \
- pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno, \
- ##args); \
- } while (0)
-
-#endif /* __LINUX_FENCE_H */
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 1f09c521adfe..6a1658308612 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -14,6 +14,7 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/capability.h>
+#include <linux/cryptohash.h>
#include <net/sch_generic.h>
@@ -56,6 +57,9 @@ struct bpf_prog_aux;
/* BPF program can access up to 512 bytes of stack space. */
#define MAX_BPF_STACK 512
+/* Maximum BPF program size in bytes. */
+#define MAX_BPF_SIZE (BPF_MAXINSNS * sizeof(struct bpf_insn))
+
/* Helper macros for filter block array initializers. */
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@@ -402,14 +406,16 @@ struct bpf_prog {
u16 jited:1, /* Is our filter JIT'ed? */
gpl_compatible:1, /* Is filter GPL compatible? */
cb_access:1, /* Is control block accessed? */
- dst_needed:1; /* Do we need dst entry? */
+ dst_needed:1, /* Do we need dst entry? */
+ xdp_adjust_head:1; /* Adjusting pkt head? */
kmemcheck_bitfield_end(meta);
- u32 len; /* Number of filter blocks */
enum bpf_prog_type type; /* Type of BPF program */
+ u32 len; /* Number of filter blocks */
+ u32 digest[SHA_DIGEST_WORDS]; /* Program digest */
struct bpf_prog_aux *aux; /* Auxiliary fields */
struct sock_fprog_kern *orig_prog; /* Original BPF program */
- unsigned int (*bpf_func)(const struct sk_buff *skb,
- const struct bpf_insn *filter);
+ unsigned int (*bpf_func)(const void *ctx,
+ const struct bpf_insn *insn);
/* Instructions for interpreter */
union {
struct sock_filter insns[0];
@@ -435,10 +441,11 @@ struct bpf_skb_data_end {
struct xdp_buff {
void *data;
void *data_end;
+ void *data_hard_start;
};
/* compute the linear packet data range [data, data_end) which
- * will be accessed by cls_bpf and act_bpf programs
+ * will be accessed by cls_bpf, act_bpf and lwt programs
*/
static inline void bpf_compute_data_end(struct sk_buff *skb)
{
@@ -498,16 +505,16 @@ static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
return BPF_PROG_RUN(prog, skb);
}
-static inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
- struct xdp_buff *xdp)
+static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
+ struct xdp_buff *xdp)
{
- u32 ret;
-
- rcu_read_lock();
- ret = BPF_PROG_RUN(prog, (void *)xdp);
- rcu_read_unlock();
-
- return ret;
+ /* Caller needs to hold rcu_read_lock() (!), otherwise program
+ * can be released while still running, or map elements could be
+ * freed early while still having concurrent users. XDP fastpath
+ * already takes rcu_read_lock() when fetching the program, so
+ * it's not necessary here anymore.
+ */
+ return BPF_PROG_RUN(prog, xdp);
}
static inline unsigned int bpf_prog_size(unsigned int proglen)
@@ -590,7 +597,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog);
-bool bpf_helper_changes_skb_data(void *func);
+bool bpf_helper_changes_pkt_data(void *func);
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
const struct bpf_insn *patch, u32 len);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dc0478c07b2a..b84230e070be 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -28,7 +28,6 @@
#include <linux/uidgid.h>
#include <linux/lockdep.h>
#include <linux/percpu-rwsem.h>
-#include <linux/blk_types.h>
#include <linux/workqueue.h>
#include <linux/percpu-rwsem.h>
#include <linux/delayed_call.h>
@@ -38,6 +37,7 @@
struct backing_dev_info;
struct bdi_writeback;
+struct bio;
struct export_operations;
struct hd_geometry;
struct iovec;
@@ -152,58 +152,6 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define CHECK_IOVEC_ONLY -1
/*
- * The below are the various read and write flags that we support. Some of
- * them include behavioral modifiers that send information down to the
- * block layer and IO scheduler. They should be used along with a req_op.
- * Terminology:
- *
- * The block layer uses device plugging to defer IO a little bit, in
- * the hope that we will see more IO very shortly. This increases
- * coalescing of adjacent IO and thus reduces the number of IOs we
- * have to send to the device. It also allows for better queuing,
- * if the IO isn't mergeable. If the caller is going to be waiting
- * for the IO, then he must ensure that the device is unplugged so
- * that the IO is dispatched to the driver.
- *
- * All IO is handled async in Linux. This is fine for background
- * writes, but for reads or writes that someone waits for completion
- * on, we want to notify the block layer and IO scheduler so that they
- * know about it. That allows them to make better scheduling
- * decisions. So when the below references 'sync' and 'async', it
- * is referencing this priority hint.
- *
- * With that in mind, the available types are:
- *
- * READ A normal read operation. Device will be plugged.
- * READ_SYNC A synchronous read. Device is not plugged, caller can
- * immediately wait on this read without caring about
- * unplugging.
- * WRITE A normal async write. Device will be plugged.
- * WRITE_SYNC Synchronous write. Identical to WRITE, but passes down
- * the hint that someone will be waiting on this IO
- * shortly. The write equivalent of READ_SYNC.
- * WRITE_ODIRECT Special case write for O_DIRECT only.
- * WRITE_FLUSH Like WRITE_SYNC but with preceding cache flush.
- * WRITE_FUA Like WRITE_SYNC but data is guaranteed to be on
- * non-volatile media on completion.
- * WRITE_FLUSH_FUA Combination of WRITE_FLUSH and FUA. The IO is preceded
- * by a cache flush and data is guaranteed to be on
- * non-volatile media on completion.
- *
- */
-#define RW_MASK REQ_OP_WRITE
-
-#define READ REQ_OP_READ
-#define WRITE REQ_OP_WRITE
-
-#define READ_SYNC REQ_SYNC
-#define WRITE_SYNC (REQ_SYNC | REQ_NOIDLE)
-#define WRITE_ODIRECT REQ_SYNC
-#define WRITE_FLUSH (REQ_SYNC | REQ_NOIDLE | REQ_PREFLUSH)
-#define WRITE_FUA (REQ_SYNC | REQ_NOIDLE | REQ_FUA)
-#define WRITE_FLUSH_FUA (REQ_SYNC | REQ_NOIDLE | REQ_PREFLUSH | REQ_FUA)
-
-/*
* Attribute flags. These should be or-ed together to figure out what
* has been changed!
*/
@@ -2499,19 +2447,6 @@ extern void make_bad_inode(struct inode *);
extern bool is_bad_inode(struct inode *);
#ifdef CONFIG_BLOCK
-static inline bool op_is_write(unsigned int op)
-{
- return op == REQ_OP_READ ? false : true;
-}
-
-/*
- * return data direction, READ or WRITE
- */
-static inline int bio_data_dir(struct bio *bio)
-{
- return op_is_write(bio_op(bio)) ? WRITE : READ;
-}
-
extern void check_disk_size_change(struct gendisk *disk,
struct block_device *bdev);
extern int revalidate_disk(struct gendisk *);
@@ -2782,7 +2717,6 @@ static inline void remove_inode_hash(struct inode *inode)
extern void inode_sb_list_add(struct inode *inode);
#ifdef CONFIG_BLOCK
-extern blk_qc_t submit_bio(struct bio *);
extern int bdev_read_only(struct block_device *);
#endif
extern int set_blocksize(struct block_device *, int);
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
index 649e9171a9b3..3efa3b861d44 100644
--- a/include/linux/fsl/guts.h
+++ b/include/linux/fsl/guts.h
@@ -29,83 +29,112 @@
* #ifdefs.
*/
struct ccsr_guts {
- __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */
- __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */
- __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */
- __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */
- __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */
- __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */
+ u32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */
+ u32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */
+ u32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and
+ * Control Register
+ */
+ u32 pordevsr; /* 0x.000c - POR I/O Device Status Register */
+ u32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */
+ u32 pordevsr2; /* 0x.0014 - POR device status register 2 */
u8 res018[0x20 - 0x18];
- __be32 porcir; /* 0x.0020 - POR Configuration Information Register */
+ u32 porcir; /* 0x.0020 - POR Configuration Information
+ * Register
+ */
u8 res024[0x30 - 0x24];
- __be32 gpiocr; /* 0x.0030 - GPIO Control Register */
+ u32 gpiocr; /* 0x.0030 - GPIO Control Register */
u8 res034[0x40 - 0x34];
- __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */
+ u32 gpoutdr; /* 0x.0040 - General-Purpose Output Data
+ * Register
+ */
u8 res044[0x50 - 0x44];
- __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */
+ u32 gpindr; /* 0x.0050 - General-Purpose Input Data
+ * Register
+ */
u8 res054[0x60 - 0x54];
- __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */
- __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */
- __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */
+ u32 pmuxcr; /* 0x.0060 - Alternate Function Signal
+ * Multiplex Control
+ */
+ u32 pmuxcr2; /* 0x.0064 - Alternate function signal
+ * multiplex control 2
+ */
+ u32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */
u8 res06c[0x70 - 0x6c];
- __be32 devdisr; /* 0x.0070 - Device Disable Control */
+ u32 devdisr; /* 0x.0070 - Device Disable Control */
#define CCSR_GUTS_DEVDISR_TB1 0x00001000
#define CCSR_GUTS_DEVDISR_TB0 0x00004000
- __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */
+ u32 devdisr2; /* 0x.0074 - Device Disable Control 2 */
u8 res078[0x7c - 0x78];
- __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */
- __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */
- __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */
- __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */
- __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */
- __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */
- __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */
- __be32 ectrstcr; /* 0x.0098 - Exception reset control register */
- __be32 autorstsr; /* 0x.009c - Automatic reset status register */
- __be32 pvr; /* 0x.00a0 - Processor Version Register */
- __be32 svr; /* 0x.00a4 - System Version Register */
+ u32 pmjcr; /* 0x.007c - 4 Power Management Jog Control
+ * Register
+ */
+ u32 powmgtcsr; /* 0x.0080 - Power Management Status and
+ * Control Register
+ */
+ u32 pmrccr; /* 0x.0084 - Power Management Reset Counter
+ * Configuration Register
+ */
+ u32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter
+ * Configuration Register
+ */
+ u32 pmcdr; /* 0x.008c - 4Power management clock disable
+ * register
+ */
+ u32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */
+ u32 rstrscr; /* 0x.0094 - Reset Request Status and
+ * Control Register
+ */
+ u32 ectrstcr; /* 0x.0098 - Exception reset control register */
+ u32 autorstsr; /* 0x.009c - Automatic reset status register */
+ u32 pvr; /* 0x.00a0 - Processor Version Register */
+ u32 svr; /* 0x.00a4 - System Version Register */
u8 res0a8[0xb0 - 0xa8];
- __be32 rstcr; /* 0x.00b0 - Reset Control Register */
+ u32 rstcr; /* 0x.00b0 - Reset Control Register */
u8 res0b4[0xc0 - 0xb4];
- __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register
+ u32 iovselsr; /* 0x.00c0 - I/O voltage select status register
Called 'elbcvselcr' on 86xx SOCs */
u8 res0c4[0x100 - 0xc4];
- __be32 rcwsr[16]; /* 0x.0100 - Reset Control Word Status registers
+ u32 rcwsr[16]; /* 0x.0100 - Reset Control Word Status registers
There are 16 registers */
u8 res140[0x224 - 0x140];
- __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */
- __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */
+ u32 iodelay1; /* 0x.0224 - IO delay control register 1 */
+ u32 iodelay2; /* 0x.0228 - IO delay control register 2 */
u8 res22c[0x604 - 0x22c];
- __be32 pamubypenr; /* 0x.604 - PAMU bypass enable register */
+ u32 pamubypenr; /* 0x.604 - PAMU bypass enable register */
u8 res608[0x800 - 0x608];
- __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */
+ u32 clkdvdr; /* 0x.0800 - Clock Divide Register */
u8 res804[0x900 - 0x804];
- __be32 ircr; /* 0x.0900 - Infrared Control Register */
+ u32 ircr; /* 0x.0900 - Infrared Control Register */
u8 res904[0x908 - 0x904];
- __be32 dmacr; /* 0x.0908 - DMA Control Register */
+ u32 dmacr; /* 0x.0908 - DMA Control Register */
u8 res90c[0x914 - 0x90c];
- __be32 elbccr; /* 0x.0914 - eLBC Control Register */
+ u32 elbccr; /* 0x.0914 - eLBC Control Register */
u8 res918[0xb20 - 0x918];
- __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */
- __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */
- __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */
+ u32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */
+ u32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */
+ u32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */
u8 resb2c[0xe00 - 0xb2c];
- __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */
+ u32 clkocr; /* 0x.0e00 - Clock Out Select Register */
u8 rese04[0xe10 - 0xe04];
- __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */
+ u32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */
u8 rese14[0xe20 - 0xe14];
- __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */
- __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */
+ u32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */
+ u32 cpfor; /* 0x.0e24 - L2 charge pump fuse override
+ * register
+ */
u8 rese28[0xf04 - 0xe28];
- __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */
- __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */
+ u32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */
+ u32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */
u8 resf0c[0xf2c - 0xf0c];
- __be32 itcr; /* 0x.0f2c - Internal transaction control register */
+ u32 itcr; /* 0x.0f2c - Internal transaction control
+ * register
+ */
u8 resf30[0xf40 - 0xf30];
- __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */
- __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
+ u32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */
+ u32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
} __attribute__ ((packed));
+u32 fsl_guts_get_svr(void);
/* Alternate function signal multiplex control */
#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index b3d34d3e0e7e..d4a884db16a3 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -398,6 +398,7 @@ int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
void ftrace_set_global_filter(unsigned char *buf, int len, int reset);
void ftrace_set_global_notrace(unsigned char *buf, int len, int reset);
void ftrace_free_filter(struct ftrace_ops *ops);
+void ftrace_ops_set_global_filter(struct ftrace_ops *ops);
int register_ftrace_command(struct ftrace_func_command *cmd);
int unregister_ftrace_command(struct ftrace_func_command *cmd);
@@ -645,6 +646,7 @@ static inline unsigned long ftrace_location(unsigned long ip)
#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; })
#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; })
#define ftrace_free_filter(ops) do { } while (0)
+#define ftrace_ops_set_global_filter(ops) do { } while (0)
static inline ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos) { return -ENODEV; }
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 667c31101b8b..377257d8f7e3 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -259,16 +259,7 @@ static struct genl_ops ZZZ_genl_ops[] __read_mostly = {
* {{{2
*/
#define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family)
-static struct genl_family ZZZ_genl_family __read_mostly = {
- .id = GENL_ID_GENERATE,
- .name = __stringify(GENL_MAGIC_FAMILY),
- .version = GENL_MAGIC_VERSION,
-#ifdef GENL_MAGIC_FAMILY_HDRSZ
- .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ),
-#endif
- .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1,
-};
-
+static struct genl_family ZZZ_genl_family;
/*
* Magic: define multicast groups
* Magic: define multicast group registration helper
@@ -302,11 +293,23 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
#undef GENL_mc_group
#define GENL_mc_group(group)
+static struct genl_family ZZZ_genl_family __ro_after_init = {
+ .name = __stringify(GENL_MAGIC_FAMILY),
+ .version = GENL_MAGIC_VERSION,
+#ifdef GENL_MAGIC_FAMILY_HDRSZ
+ .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ),
+#endif
+ .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1,
+ .ops = ZZZ_genl_ops,
+ .n_ops = ARRAY_SIZE(ZZZ_genl_ops),
+ .mcgrps = ZZZ_genl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(ZZZ_genl_mcgrps),
+ .module = THIS_MODULE,
+};
+
int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
- return genl_register_family_with_ops_groups(&ZZZ_genl_family, \
- ZZZ_genl_ops, \
- ZZZ_genl_mcgrps);
+ return genl_register_family(&ZZZ_genl_family);
}
void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 24e2cc56beb1..c2748accea71 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -82,8 +82,6 @@ enum single_ended_mode {
* implies that if the chip supports IRQs, these IRQs need to be threaded
* as the chip access may sleep when e.g. reading out the IRQ status
* registers.
- * @irq_not_threaded: flag must be set if @can_sleep is set but the
- * IRQs don't need to be threaded
* @read_reg: reader function for generic GPIO
* @write_reg: writer function for generic GPIO
* @pin2mask: some generic GPIO controllers work with the big-endian bits
@@ -91,7 +89,7 @@ enum single_ended_mode {
* bit. This callback assigns the right bit mask.
* @reg_dat: data (in) register for generic GPIO
* @reg_set: output set register (out=high) for generic GPIO
- * @reg_clk: output clear register (out=low) for generic GPIO
+ * @reg_clr: output clear register (out=low) for generic GPIO
* @reg_dir: direction setting register for generic GPIO
* @bgpio_bits: number of register bits used for a generic GPIO i.e.
* <register width> * 8
@@ -109,8 +107,10 @@ enum single_ended_mode {
* for GPIO IRQs, provided by GPIO driver
* @irq_default_type: default IRQ triggering type applied during GPIO driver
* initialization, provided by GPIO driver
- * @irq_parent: GPIO IRQ chip parent/bank linux irq number,
- * provided by GPIO driver
+ * @irq_chained_parent: GPIO IRQ chip parent/bank linux irq number,
+ * provided by GPIO driver for chained interrupt (not for nested
+ * interrupts).
+ * @irq_nested: True if set the interrupt handling is nested.
* @irq_need_valid_mask: If set core allocates @irq_valid_mask with all
* bits set to one
* @irq_valid_mask: If not %NULL holds bitmask of GPIOs which are valid to
@@ -166,7 +166,6 @@ struct gpio_chip {
u16 ngpio;
const char *const *names;
bool can_sleep;
- bool irq_not_threaded;
#if IS_ENABLED(CONFIG_GPIO_GENERIC)
unsigned long (*read_reg)(void __iomem *reg);
@@ -192,7 +191,8 @@ struct gpio_chip {
unsigned int irq_base;
irq_flow_handler_t irq_handler;
unsigned int irq_default_type;
- int irq_parent;
+ int irq_chained_parent;
+ bool irq_nested;
bool irq_need_valid_mask;
unsigned long *irq_valid_mask;
struct lock_class_key *lock_key;
@@ -270,24 +270,40 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
int parent_irq,
irq_flow_handler_t parent_handler);
+void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ int parent_irq);
+
int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
unsigned int first_irq,
irq_flow_handler_t handler,
unsigned int type,
+ bool nested,
struct lock_class_key *lock_key);
+/* FIXME: I assume threaded IRQchips do not have the lockdep problem */
+static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
+ struct irq_chip *irqchip,
+ unsigned int first_irq,
+ irq_flow_handler_t handler,
+ unsigned int type)
+{
+ return _gpiochip_irqchip_add(gpiochip, irqchip, first_irq,
+ handler, type, true, NULL);
+}
+
#ifdef CONFIG_LOCKDEP
#define gpiochip_irqchip_add(...) \
( \
({ \
static struct lock_class_key _key; \
- _gpiochip_irqchip_add(__VA_ARGS__, &_key); \
+ _gpiochip_irqchip_add(__VA_ARGS__, false, &_key); \
}) \
)
#else
#define gpiochip_irqchip_add(...) \
- _gpiochip_irqchip_add(__VA_ARGS__, NULL)
+ _gpiochip_irqchip_add(__VA_ARGS__, false, NULL)
#endif
#endif /* CONFIG_GPIOLIB_IRQCHIP */
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index e31bcd4c7859..97585d9679f3 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -93,8 +93,6 @@ static __inline__ void debug_frame(const struct sk_buff *skb)
int hdlc_open(struct net_device *dev);
/* Must be called by hardware driver when HDLC device is being closed */
void hdlc_close(struct net_device *dev);
-/* May be used by hardware driver */
-int hdlc_change_mtu(struct net_device *dev, int new_mtu);
/* Must be pointed to by hw driver's dev->netdev_ops->ndo_start_xmit */
netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index e9744202fa29..edbb4fc674ed 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -78,6 +78,8 @@ enum hdmi_picture_aspect {
HDMI_PICTURE_ASPECT_NONE,
HDMI_PICTURE_ASPECT_4_3,
HDMI_PICTURE_ASPECT_16_9,
+ HDMI_PICTURE_ASPECT_64_27,
+ HDMI_PICTURE_ASPECT_256_135,
HDMI_PICTURE_ASPECT_RESERVED,
};
diff --git a/include/linux/hippidevice.h b/include/linux/hippidevice.h
index 8ec23fb0b412..402f99e328d4 100644
--- a/include/linux/hippidevice.h
+++ b/include/linux/hippidevice.h
@@ -32,7 +32,6 @@ struct hippi_cb {
};
__be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev);
-int hippi_change_mtu(struct net_device *dev, int new_mtu);
int hippi_mac_addr(struct net_device *dev, void *p);
int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p);
struct net_device *alloc_hippi_dev(int sizeof_priv);
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index e35e6de633b9..1f782aa1d8e6 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -189,6 +189,8 @@ static inline void deferred_split_huge_page(struct page *page) {}
#define split_huge_pmd(__vma, __pmd, __address) \
do { } while (0)
+static inline void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long address, bool freeze, struct page *page) {}
static inline void split_huge_pmd_address(struct vm_area_struct *vma,
unsigned long address, bool freeze, struct page *page) {}
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a80516fd65c8..fe849329511a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1576,6 +1576,9 @@ struct ieee80211_vht_operation {
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_FT 2
#define WLAN_AUTH_SAE 3
+#define WLAN_AUTH_FILS_SK 4
+#define WLAN_AUTH_FILS_SK_PFS 5
+#define WLAN_AUTH_FILS_PK 6
#define WLAN_AUTH_LEAP 128
#define WLAN_AUTH_CHALLENGE_LEN 128
@@ -1960,6 +1963,26 @@ enum ieee80211_eid {
WLAN_EID_VENDOR_SPECIFIC = 221,
WLAN_EID_QOS_PARAMETER = 222,
+ WLAN_EID_CAG_NUMBER = 237,
+ WLAN_EID_AP_CSN = 239,
+ WLAN_EID_FILS_INDICATION = 240,
+ WLAN_EID_DILS = 241,
+ WLAN_EID_FRAGMENT = 242,
+ WLAN_EID_EXTENSION = 255
+};
+
+/* Element ID Extensions for Element ID 255 */
+enum ieee80211_eid_ext {
+ WLAN_EID_EXT_ASSOC_DELAY_INFO = 1,
+ WLAN_EID_EXT_FILS_REQ_PARAMS = 2,
+ WLAN_EID_EXT_FILS_KEY_CONFIRM = 3,
+ WLAN_EID_EXT_FILS_SESSION = 4,
+ WLAN_EID_EXT_FILS_HLP_CONTAINER = 5,
+ WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6,
+ WLAN_EID_EXT_KEY_DELIVERY = 7,
+ WLAN_EID_EXT_FILS_WRAPPED_DATA = 8,
+ WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
+ WLAN_EID_EXT_FILS_NONCE = 13,
};
/* Action category code */
@@ -2073,6 +2096,9 @@ enum ieee80211_key_len {
#define IEEE80211_GCMP_MIC_LEN 16
#define IEEE80211_GCMP_PN_LEN 6
+#define FILS_NONCE_LEN 16
+#define FILS_MAX_KEK_LEN 64
+
/* Public action codes */
enum ieee80211_pub_actioncode {
WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index f563907ed776..3355efc89781 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -44,4 +44,20 @@ static inline int arp_hdr_len(struct net_device *dev)
return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
}
}
+
+static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
+{
+ switch (dev->type) {
+ case ARPHRD_TUNNEL:
+ case ARPHRD_TUNNEL6:
+ case ARPHRD_SIT:
+ case ARPHRD_IPGRE:
+ case ARPHRD_VOID:
+ case ARPHRD_NONE:
+ return false;
+ default:
+ return true;
+ }
+}
+
#endif /* _LINUX_IF_ARP_H */
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 3319d97d789d..8d5fcd6284ce 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -399,22 +399,6 @@ static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb)
skb->vlan_tci = 0;
return skb;
}
-/*
- * vlan_hwaccel_push_inside - pushes vlan tag to the payload
- * @skb: skbuff to tag
- *
- * Checks is tag is present in @skb->vlan_tci and if it is, it pushes the
- * VLAN tag from @skb->vlan_tci inside to the payload.
- *
- * Following the skb_unshare() example, in case of error, the calling function
- * doesn't have to worry about freeing the original skb.
- */
-static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb)
-{
- if (skb_vlan_tag_present(skb))
- skb = __vlan_hwaccel_push_inside(skb);
- return skb;
-}
/**
* __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 72f0721f75e7..53144e78a369 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -232,6 +232,18 @@ struct irq_affinity_notify {
void (*release)(struct kref *ref);
};
+/**
+ * struct irq_affinity - Description for automatic irq affinity assignements
+ * @pre_vectors: Don't apply affinity to @pre_vectors at beginning of
+ * the MSI(-X) vector space
+ * @post_vectors: Don't apply affinity to @post_vectors at end of
+ * the MSI(-X) vector space
+ */
+struct irq_affinity {
+ int pre_vectors;
+ int post_vectors;
+};
+
#if defined(CONFIG_SMP)
extern cpumask_var_t irq_default_affinity;
@@ -278,8 +290,8 @@ extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m);
extern int
irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
-struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity, int nvec);
-int irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec);
+struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
+int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd);
#else /* CONFIG_SMP */
@@ -313,13 +325,13 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
}
static inline struct cpumask *
-irq_create_affinity_masks(const struct cpumask *affinity, int nvec)
+irq_create_affinity_masks(int nvec, const struct irq_affinity *affd)
{
return NULL;
}
static inline int
-irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec)
+irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
{
return maxvec;
}
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index a0649973ee5b..671d014e6429 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -64,6 +64,11 @@ struct ipv6_devconf {
} stable_secret;
__s32 use_oif_addrs_only;
__s32 keep_addr_on_down;
+ __s32 seg6_enabled;
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ __s32 seg6_require_hmac;
+#endif
+ __u32 enhanced_dad;
struct ctl_table_header *sysctl_header;
};
@@ -229,8 +234,9 @@ struct ipv6_pinfo {
rxflow:1,
rxtclass:1,
rxpmtu:1,
- rxorigdstaddr:1;
- /* 2 bits hole */
+ rxorigdstaddr:1,
+ recvfragsize:1;
+ /* 1 bits hole */
} bits;
__u16 all;
} rxopt;
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b7e34313cdfe..5118d3a0c9ca 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -239,7 +239,7 @@
#define GITS_TYPER_PTA (1UL << 19)
#define GITS_TYPER_HWCOLLCNT_SHIFT 24
-#define GITS_CBASER_VALID (1UL << 63)
+#define GITS_CBASER_VALID (1ULL << 63)
#define GITS_CBASER_SHAREABILITY_SHIFT (10)
#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59)
#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53)
@@ -265,7 +265,7 @@
#define GITS_BASER_NR_REGS 8
-#define GITS_BASER_VALID (1UL << 63)
+#define GITS_BASER_VALID (1ULL << 63)
#define GITS_BASER_INDIRECT (1ULL << 62)
#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index bc6ed52a39b9..01b6b460c34d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -50,6 +50,10 @@
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
+/* generic data direction definitions */
+#define READ 0
+#define WRITE 1
+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
#define u64_to_user_ptr(x) ( \
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 44fda64ad434..00f776816aa3 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -78,8 +78,8 @@ static inline unsigned int kstat_cpu_irqs_sum(unsigned int cpu)
return kstat_cpu(cpu).irqs_sum;
}
-extern void account_user_time(struct task_struct *, cputime_t, cputime_t);
-extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t);
+extern void account_user_time(struct task_struct *, cputime_t);
+extern void account_system_time(struct task_struct *, int, cputime_t);
extern void account_steal_time(cputime_t);
extern void account_idle_time(cputime_t);
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index a6e82a69c363..4fec8b775895 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -48,6 +48,7 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
__k; \
})
+void free_kthread_struct(struct task_struct *k);
void kthread_bind(struct task_struct *k, unsigned int cpu);
void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask);
int kthread_stop(struct task_struct *k);
@@ -174,7 +175,7 @@ __printf(2, 3)
struct kthread_worker *
kthread_create_worker(unsigned int flags, const char namefmt[], ...);
-struct kthread_worker *
+__printf(3, 4) struct kthread_worker *
kthread_create_worker_on_cpu(int cpu, unsigned int flags,
const char namefmt[], ...);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 01c0b9cc3915..81ba3ba641ba 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -224,7 +224,6 @@ struct kvm_vcpu {
int fpu_active;
int guest_fpu_loaded, guest_xcr0_loaded;
- unsigned char fpu_counter;
struct swait_queue_head wq;
struct pid *pid;
int sigset_active;
@@ -645,6 +644,8 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
unsigned long len);
int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
void *data, unsigned long len);
+int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ void *data, int offset, unsigned long len);
int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
gpa_t gpa, unsigned long len);
int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index ddfcb2df3656..569cb531094c 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -42,16 +42,20 @@ struct led_classdev {
#define LED_UNREGISTERING (1 << 1)
/* Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME (1 << 16)
-#define LED_BLINK_SW (1 << 17)
-#define LED_BLINK_ONESHOT (1 << 18)
-#define LED_BLINK_ONESHOT_STOP (1 << 19)
-#define LED_BLINK_INVERT (1 << 20)
-#define LED_BLINK_BRIGHTNESS_CHANGE (1 << 21)
-#define LED_BLINK_DISABLE (1 << 22)
-#define LED_SYSFS_DISABLE (1 << 23)
-#define LED_DEV_CAP_FLASH (1 << 24)
-#define LED_HW_PLUGGABLE (1 << 25)
-#define LED_PANIC_INDICATOR (1 << 26)
+#define LED_SYSFS_DISABLE (1 << 17)
+#define LED_DEV_CAP_FLASH (1 << 18)
+#define LED_HW_PLUGGABLE (1 << 19)
+#define LED_PANIC_INDICATOR (1 << 20)
+
+ /* set_brightness_work / blink_timer flags, atomic, private. */
+ unsigned long work_flags;
+
+#define LED_BLINK_SW 0
+#define LED_BLINK_ONESHOT 1
+#define LED_BLINK_ONESHOT_STOP 2
+#define LED_BLINK_INVERT 3
+#define LED_BLINK_BRIGHTNESS_CHANGE 4
+#define LED_BLINK_DISABLE 5
/* Set LED brightness level
* Must not sleep. Use brightness_set_blocking for drivers
@@ -89,6 +93,7 @@ struct led_classdev {
unsigned long blink_delay_on, blink_delay_off;
struct timer_list blink_timer;
int blink_brightness;
+ int new_blink_brightness;
void (*flash_resume)(struct led_classdev *led_cdev);
struct work_struct set_brightness_work;
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786e4ad8..7c273bbc5351 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -47,6 +47,7 @@ struct ppa_addr {
struct nvm_rq;
struct nvm_id;
struct nvm_dev;
+struct nvm_tgt_dev;
typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
@@ -107,6 +108,8 @@ enum {
NVM_RSP_NOT_CHANGEABLE = 0x1,
NVM_RSP_ERR_FAILWRITE = 0x40ff,
NVM_RSP_ERR_EMPTYPAGE = 0x42ff,
+ NVM_RSP_ERR_FAILECC = 0x4281,
+ NVM_RSP_WARN_HIGHECC = 0x4700,
/* Device opcodes */
NVM_OP_HBREAD = 0x02,
@@ -208,7 +211,7 @@ struct nvm_id {
struct nvm_target {
struct list_head list;
- struct nvm_dev *dev;
+ struct nvm_tgt_dev *dev;
struct nvm_tgt_type *type;
struct gendisk *disk;
};
@@ -228,7 +231,7 @@ typedef void (nvm_end_io_fn)(struct nvm_rq *);
struct nvm_rq {
struct nvm_tgt_instance *ins;
- struct nvm_dev *dev;
+ struct nvm_tgt_dev *dev;
struct bio *bio;
@@ -263,35 +266,12 @@ static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata)
return rqdata + 1;
}
-struct nvm_block;
-
-struct nvm_lun {
- int id;
-
- int lun_id;
- int chnl_id;
-
- spinlock_t lock;
-
- unsigned int nr_free_blocks; /* Number of unused blocks */
- struct nvm_block *blocks;
-};
-
enum {
NVM_BLK_ST_FREE = 0x1, /* Free block */
NVM_BLK_ST_TGT = 0x2, /* Block in use by target */
NVM_BLK_ST_BAD = 0x8, /* Bad block */
};
-struct nvm_block {
- struct list_head list;
- struct nvm_lun *lun;
- unsigned long id;
-
- void *priv;
- int state;
-};
-
/* system block cpu representation */
struct nvm_sb_info {
unsigned long seqnr;
@@ -301,22 +281,12 @@ struct nvm_sb_info {
struct ppa_addr fs_ppa;
};
-struct nvm_dev {
- struct nvm_dev_ops *ops;
-
- struct list_head devices;
-
- /* Media manager */
- struct nvmm_type *mt;
- void *mp;
-
- /* System blocks */
- struct nvm_sb_info sb;
-
- /* Device information */
+/* Device generic information */
+struct nvm_geo {
int nr_chnls;
+ int nr_luns;
+ int luns_per_chnl; /* -1 if channels are not symmetric */
int nr_planes;
- int luns_per_chnl;
int sec_per_pg; /* only sectors for a single page */
int pgs_per_blk;
int blks_per_lun;
@@ -336,14 +306,44 @@ struct nvm_dev {
int sec_per_pl; /* all sectors across planes */
int sec_per_blk;
int sec_per_lun;
+};
+
+struct nvm_tgt_dev {
+ /* Device information */
+ struct nvm_geo geo;
+
+ /* Base ppas for target LUNs */
+ struct ppa_addr *luns;
+
+ sector_t total_secs;
+
+ struct nvm_id identity;
+ struct request_queue *q;
+
+ struct nvm_dev *parent;
+ void *map;
+};
+
+struct nvm_dev {
+ struct nvm_dev_ops *ops;
+
+ struct list_head devices;
+
+ /* Media manager */
+ struct nvmm_type *mt;
+ void *mp;
+
+ /* System blocks */
+ struct nvm_sb_info sb;
+
+ /* Device information */
+ struct nvm_geo geo;
/* lower page table */
int lps_per_blk;
int *lptbl;
- unsigned long total_blocks;
unsigned long total_secs;
- int nr_luns;
unsigned long *lun_map;
void *dma_pool;
@@ -352,26 +352,57 @@ struct nvm_dev {
/* Backend device */
struct request_queue *q;
- struct device dev;
- struct device *parent_dev;
char name[DISK_NAME_LEN];
void *private_data;
+ void *rmap;
+
struct mutex mlock;
spinlock_t lock;
};
+static inline struct ppa_addr linear_to_generic_addr(struct nvm_geo *geo,
+ u64 pba)
+{
+ struct ppa_addr l;
+ int secs, pgs, blks, luns;
+ sector_t ppa = pba;
+
+ l.ppa = 0;
+
+ div_u64_rem(ppa, geo->sec_per_pg, &secs);
+ l.g.sec = secs;
+
+ sector_div(ppa, geo->sec_per_pg);
+ div_u64_rem(ppa, geo->pgs_per_blk, &pgs);
+ l.g.pg = pgs;
+
+ sector_div(ppa, geo->pgs_per_blk);
+ div_u64_rem(ppa, geo->blks_per_lun, &blks);
+ l.g.blk = blks;
+
+ sector_div(ppa, geo->blks_per_lun);
+ div_u64_rem(ppa, geo->luns_per_chnl, &luns);
+ l.g.lun = luns;
+
+ sector_div(ppa, geo->luns_per_chnl);
+ l.g.ch = ppa;
+
+ return l;
+}
+
static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
struct ppa_addr r)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr l;
- l.ppa = ((u64)r.g.blk) << dev->ppaf.blk_offset;
- l.ppa |= ((u64)r.g.pg) << dev->ppaf.pg_offset;
- l.ppa |= ((u64)r.g.sec) << dev->ppaf.sect_offset;
- l.ppa |= ((u64)r.g.pl) << dev->ppaf.pln_offset;
- l.ppa |= ((u64)r.g.lun) << dev->ppaf.lun_offset;
- l.ppa |= ((u64)r.g.ch) << dev->ppaf.ch_offset;
+ l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
+ l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
+ l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
+ l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
+ l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
+ l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
return l;
}
@@ -379,24 +410,25 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
struct ppa_addr r)
{
+ struct nvm_geo *geo = &dev->geo;
struct ppa_addr l;
l.ppa = 0;
/*
* (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
*/
- l.g.blk = (r.ppa >> dev->ppaf.blk_offset) &
- (((1 << dev->ppaf.blk_len) - 1));
- l.g.pg |= (r.ppa >> dev->ppaf.pg_offset) &
- (((1 << dev->ppaf.pg_len) - 1));
- l.g.sec |= (r.ppa >> dev->ppaf.sect_offset) &
- (((1 << dev->ppaf.sect_len) - 1));
- l.g.pl |= (r.ppa >> dev->ppaf.pln_offset) &
- (((1 << dev->ppaf.pln_len) - 1));
- l.g.lun |= (r.ppa >> dev->ppaf.lun_offset) &
- (((1 << dev->ppaf.lun_len) - 1));
- l.g.ch |= (r.ppa >> dev->ppaf.ch_offset) &
- (((1 << dev->ppaf.ch_len) - 1));
+ l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
+ (((1 << geo->ppaf.blk_len) - 1));
+ l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
+ (((1 << geo->ppaf.pg_len) - 1));
+ l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
+ (((1 << geo->ppaf.sect_len) - 1));
+ l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
+ (((1 << geo->ppaf.pln_len) - 1));
+ l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
+ (((1 << geo->ppaf.lun_len) - 1));
+ l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
+ (((1 << geo->ppaf.ch_len) - 1));
return l;
}
@@ -411,18 +443,13 @@ static inline void ppa_set_empty(struct ppa_addr *ppa_addr)
ppa_addr->ppa = ADDR_EMPTY;
}
-static inline struct ppa_addr block_to_ppa(struct nvm_dev *dev,
- struct nvm_block *blk)
+static inline int ppa_cmp_blk(struct ppa_addr ppa1, struct ppa_addr ppa2)
{
- struct ppa_addr ppa;
- struct nvm_lun *lun = blk->lun;
-
- ppa.ppa = 0;
- ppa.g.blk = blk->id % dev->blks_per_lun;
- ppa.g.lun = lun->lun_id;
- ppa.g.ch = lun->chnl_id;
+ if (ppa_empty(ppa1) || ppa_empty(ppa2))
+ return 0;
- return ppa;
+ return ((ppa1.g.ch == ppa2.g.ch) && (ppa1.g.lun == ppa2.g.lun) &&
+ (ppa1.g.blk == ppa2.g.blk));
}
static inline int ppa_to_slc(struct nvm_dev *dev, int slc_pg)
@@ -432,7 +459,7 @@ static inline int ppa_to_slc(struct nvm_dev *dev, int slc_pg)
typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *);
typedef sector_t (nvm_tgt_capacity_fn)(void *);
-typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int);
+typedef void *(nvm_tgt_init_fn)(struct nvm_tgt_dev *, struct gendisk *);
typedef void (nvm_tgt_exit_fn)(void *);
struct nvm_tgt_type {
@@ -465,23 +492,18 @@ typedef void (nvmm_unregister_fn)(struct nvm_dev *);
typedef int (nvmm_create_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_create *);
typedef int (nvmm_remove_tgt_fn)(struct nvm_dev *, struct nvm_ioctl_remove *);
-typedef struct nvm_block *(nvmm_get_blk_fn)(struct nvm_dev *,
- struct nvm_lun *, unsigned long);
-typedef void (nvmm_put_blk_fn)(struct nvm_dev *, struct nvm_block *);
-typedef int (nvmm_open_blk_fn)(struct nvm_dev *, struct nvm_block *);
-typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *);
-typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *);
-typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
-typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
- unsigned long);
-typedef void (nvmm_mark_blk_fn)(struct nvm_dev *, struct ppa_addr, int);
-typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int);
-typedef int (nvmm_reserve_lun)(struct nvm_dev *, int);
-typedef void (nvmm_release_lun)(struct nvm_dev *, int);
-typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *);
-
+typedef int (nvmm_submit_io_fn)(struct nvm_tgt_dev *, struct nvm_rq *);
+typedef int (nvmm_erase_blk_fn)(struct nvm_tgt_dev *, struct ppa_addr *, int);
typedef int (nvmm_get_area_fn)(struct nvm_dev *, sector_t *, sector_t);
typedef void (nvmm_put_area_fn)(struct nvm_dev *, sector_t);
+typedef struct ppa_addr (nvmm_trans_ppa_fn)(struct nvm_tgt_dev *,
+ struct ppa_addr, int);
+typedef void (nvmm_part_to_tgt_fn)(struct nvm_dev *, sector_t*, int);
+
+enum {
+ TRANS_TGT_TO_DEV = 0x0,
+ TRANS_DEV_TO_TGT = 0x1,
+};
struct nvmm_type {
const char *name;
@@ -493,54 +515,41 @@ struct nvmm_type {
nvmm_create_tgt_fn *create_tgt;
nvmm_remove_tgt_fn *remove_tgt;
- /* Block administration callbacks */
- nvmm_get_blk_fn *get_blk;
- nvmm_put_blk_fn *put_blk;
- nvmm_open_blk_fn *open_blk;
- nvmm_close_blk_fn *close_blk;
- nvmm_flush_blk_fn *flush_blk;
-
nvmm_submit_io_fn *submit_io;
nvmm_erase_blk_fn *erase_blk;
- /* Bad block mgmt */
- nvmm_mark_blk_fn *mark_blk;
-
- /* Configuration management */
- nvmm_get_lun_fn *get_lun;
- nvmm_reserve_lun *reserve_lun;
- nvmm_release_lun *release_lun;
-
- /* Statistics */
- nvmm_lun_info_print_fn *lun_info_print;
-
nvmm_get_area_fn *get_area;
nvmm_put_area_fn *put_area;
+ nvmm_trans_ppa_fn *trans_ppa;
+ nvmm_part_to_tgt_fn *part_to_tgt;
+
struct list_head list;
};
extern int nvm_register_mgr(struct nvmm_type *);
extern void nvm_unregister_mgr(struct nvmm_type *);
-extern struct nvm_block *nvm_get_blk(struct nvm_dev *, struct nvm_lun *,
- unsigned long);
-extern void nvm_put_blk(struct nvm_dev *, struct nvm_block *);
-
extern struct nvm_dev *nvm_alloc_dev(int);
extern int nvm_register(struct nvm_dev *);
extern void nvm_unregister(struct nvm_dev *);
-void nvm_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type);
-
-extern int nvm_submit_io(struct nvm_dev *, struct nvm_rq *);
+extern int nvm_set_bb_tbl(struct nvm_dev *, struct ppa_addr *, int, int);
+extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
+ int, int);
+extern int nvm_max_phys_sects(struct nvm_tgt_dev *);
+extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *);
extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *);
extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *,
const struct ppa_addr *, int, int);
extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *);
-extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int);
-extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *);
+extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int, int);
+extern int nvm_erase_blk(struct nvm_tgt_dev *, struct ppa_addr *, int);
+extern int nvm_get_l2p_tbl(struct nvm_tgt_dev *, u64, u32, nvm_l2p_update_fn *,
+ void *);
+extern int nvm_get_area(struct nvm_tgt_dev *, sector_t *, sector_t);
+extern void nvm_put_area(struct nvm_tgt_dev *, sector_t);
extern void nvm_end_io(struct nvm_rq *, int);
extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int,
void *, int);
@@ -548,6 +557,7 @@ extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int,
int, void *, int);
extern int nvm_bb_tbl_fold(struct nvm_dev *, u8 *, int);
extern int nvm_get_bb_tbl(struct nvm_dev *, struct ppa_addr, u8 *);
+extern int nvm_get_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr, u8 *);
/* sysblk.c */
#define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */
@@ -569,10 +579,10 @@ extern int nvm_init_sysblock(struct nvm_dev *, struct nvm_sb_info *);
extern int nvm_dev_factory(struct nvm_dev *, int flags);
-#define nvm_for_each_lun_ppa(dev, ppa, chid, lunid) \
- for ((chid) = 0, (ppa).ppa = 0; (chid) < (dev)->nr_chnls; \
+#define nvm_for_each_lun_ppa(geo, ppa, chid, lunid) \
+ for ((chid) = 0, (ppa).ppa = 0; (chid) < (geo)->nr_chnls; \
(chid)++, (ppa).g.ch = (chid)) \
- for ((lunid) = 0; (lunid) < (dev)->luns_per_chnl; \
+ for ((lunid) = 0; (lunid) < (geo)->luns_per_chnl; \
(lunid)++, (ppa).g.lun = (lunid))
#else /* CONFIG_NVM */
diff --git a/include/linux/list.h b/include/linux/list.h
index 5809e9a2de5b..d1039ecaf94f 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -28,27 +28,42 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
list->prev = list;
}
+#ifdef CONFIG_DEBUG_LIST
+extern bool __list_add_valid(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next);
+extern bool __list_del_entry_valid(struct list_head *entry);
+#else
+static inline bool __list_add_valid(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ return true;
+}
+static inline bool __list_del_entry_valid(struct list_head *entry)
+{
+ return true;
+}
+#endif
+
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
+ if (!__list_add_valid(new, prev, next))
+ return;
+
next->prev = new;
new->next = next;
new->prev = prev;
WRITE_ONCE(prev->next, new);
}
-#else
-extern void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next);
-#endif
/**
* list_add - add a new entry
@@ -96,22 +111,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
+ if (!__list_del_entry_valid(entry))
+ return;
+
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
+ __list_del_entry(entry);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
/**
* list_replace - replace old entry by new one
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
index 2931aa43dab1..0d3f14fd2621 100644
--- a/include/linux/mbus.h
+++ b/include/linux/mbus.h
@@ -82,6 +82,7 @@ static inline int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size,
}
#endif
+#ifdef CONFIG_MVEBU_MBUS
int mvebu_mbus_save_cpu_target(u32 __iomem *store_addr);
void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
@@ -97,5 +98,12 @@ int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
size_t mbus_size, phys_addr_t sdram_phys_base,
size_t sdram_size);
int mvebu_mbus_dt_init(bool is_coherent);
+#else
+static inline int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target,
+ u8 *attr)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_MVEBU_MBUS */
#endif /* __LINUX_MBUS_H */
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
index a585b4b5fa0e..0661af17a758 100644
--- a/include/linux/mc146818rtc.h
+++ b/include/linux/mc146818rtc.h
@@ -16,6 +16,7 @@
#include <asm/mc146818rtc.h> /* register access macros */
#include <linux/bcd.h>
#include <linux/delay.h>
+#include <linux/pm-trace.h>
#ifdef __KERNEL__
#include <linux/spinlock.h> /* spinlock_t */
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
new file mode 100644
index 000000000000..ec819e9a115a
--- /dev/null
+++ b/include/linux/mdev.h
@@ -0,0 +1,168 @@
+/*
+ * Mediated device definition
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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.
+ */
+
+#ifndef MDEV_H
+#define MDEV_H
+
+/* Parent device */
+struct parent_device {
+ struct device *dev;
+ const struct parent_ops *ops;
+
+ /* internal */
+ struct kref ref;
+ struct mutex lock;
+ struct list_head next;
+ struct kset *mdev_types_kset;
+ struct list_head type_list;
+};
+
+/* Mediated device */
+struct mdev_device {
+ struct device dev;
+ struct parent_device *parent;
+ uuid_le uuid;
+ void *driver_data;
+
+ /* internal */
+ struct kref ref;
+ struct list_head next;
+ struct kobject *type_kobj;
+};
+
+/**
+ * struct parent_ops - Structure to be registered for each parent device to
+ * register the device to mdev module.
+ *
+ * @owner: The module owner.
+ * @dev_attr_groups: Attributes of the parent device.
+ * @mdev_attr_groups: Attributes of the mediated device.
+ * @supported_type_groups: Attributes to define supported types. It is mandatory
+ * to provide supported types.
+ * @create: Called to allocate basic resources in parent device's
+ * driver for a particular mediated device. It is
+ * mandatory to provide create ops.
+ * @kobj: kobject of type for which 'create' is called.
+ * @mdev: mdev_device structure on of mediated device
+ * that is being created
+ * Returns integer: success (0) or error (< 0)
+ * @remove: Called to free resources in parent device's driver for a
+ * a mediated device. It is mandatory to provide 'remove'
+ * ops.
+ * @mdev: mdev_device device structure which is being
+ * destroyed
+ * Returns integer: success (0) or error (< 0)
+ * @open: Open mediated device.
+ * @mdev: mediated device.
+ * Returns integer: success (0) or error (< 0)
+ * @release: release mediated device
+ * @mdev: mediated device.
+ * @read: Read emulation callback
+ * @mdev: mediated device structure
+ * @buf: read buffer
+ * @count: number of bytes to read
+ * @ppos: address.
+ * Retuns number on bytes read on success or error.
+ * @write: Write emulation callback
+ * @mdev: mediated device structure
+ * @buf: write buffer
+ * @count: number of bytes to be written
+ * @ppos: address.
+ * Retuns number on bytes written on success or error.
+ * @ioctl: IOCTL callback
+ * @mdev: mediated device structure
+ * @cmd: ioctl command
+ * @arg: arguments to ioctl
+ * @mmap: mmap callback
+ * @mdev: mediated device structure
+ * @vma: vma structure
+ * Parent device that support mediated device should be registered with mdev
+ * module with parent_ops structure.
+ **/
+
+struct parent_ops {
+ struct module *owner;
+ const struct attribute_group **dev_attr_groups;
+ const struct attribute_group **mdev_attr_groups;
+ struct attribute_group **supported_type_groups;
+
+ int (*create)(struct kobject *kobj, struct mdev_device *mdev);
+ int (*remove)(struct mdev_device *mdev);
+ int (*open)(struct mdev_device *mdev);
+ void (*release)(struct mdev_device *mdev);
+ ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
+ size_t count, loff_t *ppos);
+ ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
+ size_t count, loff_t *ppos);
+ ssize_t (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
+ unsigned long arg);
+ int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
+};
+
+/* interface for exporting mdev supported type attributes */
+struct mdev_type_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct kobject *kobj, struct device *dev, char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct device *dev,
+ const char *buf, size_t count);
+};
+
+#define MDEV_TYPE_ATTR(_name, _mode, _show, _store) \
+struct mdev_type_attribute mdev_type_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+#define MDEV_TYPE_ATTR_RW(_name) \
+ struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RW(_name)
+#define MDEV_TYPE_ATTR_RO(_name) \
+ struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
+#define MDEV_TYPE_ATTR_WO(_name) \
+ struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_WO(_name)
+
+/**
+ * struct mdev_driver - Mediated device driver
+ * @name: driver name
+ * @probe: called when new device created
+ * @remove: called when device removed
+ * @driver: device driver structure
+ *
+ **/
+struct mdev_driver {
+ const char *name;
+ int (*probe)(struct device *dev);
+ void (*remove)(struct device *dev);
+ struct device_driver driver;
+};
+
+#define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver)
+#define to_mdev_device(dev) container_of(dev, struct mdev_device, dev)
+
+static inline void *mdev_get_drvdata(struct mdev_device *mdev)
+{
+ return mdev->driver_data;
+}
+
+static inline void mdev_set_drvdata(struct mdev_device *mdev, void *data)
+{
+ mdev->driver_data = data;
+}
+
+extern struct bus_type mdev_bus_type;
+
+#define dev_is_mdev(d) ((d)->bus == &mdev_bus_type)
+
+extern int mdev_register_device(struct device *dev,
+ const struct parent_ops *ops);
+extern void mdev_unregister_device(struct device *dev);
+
+extern int mdev_register_driver(struct mdev_driver *drv, struct module *owner);
+extern void mdev_unregister_driver(struct mdev_driver *drv);
+
+#endif /* MDEV_H */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 5e5b2969d931..5f4d8281832b 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -7,6 +7,7 @@
#include <linux/mmzone.h>
+#include <linux/dax.h>
#include <linux/slab.h>
#include <linux/rbtree.h>
#include <linux/spinlock.h>
@@ -177,6 +178,13 @@ static inline bool vma_migratable(struct vm_area_struct *vma)
if (vma->vm_flags & (VM_IO | VM_PFNMAP))
return false;
+ /*
+ * DAX device mappings require predictable access latency, so avoid
+ * incurring periodic faults.
+ */
+ if (vma_is_dax(vma))
+ return false;
+
#ifndef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
if (vma->vm_flags & VM_HUGETLB)
return false;
diff --git a/include/linux/mfd/max77620.h b/include/linux/mfd/max77620.h
index 3ca0af07fc78..ad2a9a852aea 100644
--- a/include/linux/mfd/max77620.h
+++ b/include/linux/mfd/max77620.h
@@ -180,6 +180,7 @@
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
+#define MAX20024_SD_CFG1_MPOK_MASK BIT(1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
@@ -187,6 +188,7 @@
/* LDO_CNFG2 */
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
#define MAX77620_LDO_POWER_MODE_SHIFT 6
+#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2)
#define MAX77620_LDO_CFG2_ADE_MASK BIT(1)
#define MAX77620_LDO_CFG2_ADE_DISABLE 0
#define MAX77620_LDO_CFG2_ADE_ENABLE BIT(1)
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 7a26286db895..fba44abd05ba 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -100,6 +100,11 @@
#define TMIO_MMC_SDIO_STATUS_QUIRK (1 << 8)
/*
+ * Some controllers have a 32-bit wide data port register
+ */
+#define TMIO_MMC_32BIT_DATA_PORT (1 << 9)
+
+/*
* Some controllers allows to set SDx actual clock
*/
#define TMIO_MMC_CLK_ACTUAL (1 << 10)
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 47492c9631b3..1629a0c32679 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -31,7 +31,11 @@ struct mii_if_info {
extern int mii_link_ok (struct mii_if_info *mii);
extern int mii_nway_restart (struct mii_if_info *mii);
extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_ethtool_get_link_ksettings(
+ struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_ethtool_set_link_ksettings(
+ struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
extern int mii_check_gmii_support(struct mii_if_info *mii);
extern void mii_check_link (struct mii_if_info *mii);
extern unsigned int mii_check_media (struct mii_if_info *mii,
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 58276144ba81..9f489365b3d3 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -277,6 +277,7 @@ enum mlx5_event {
MLX5_EVENT_TYPE_INTERNAL_ERROR = 0x08,
MLX5_EVENT_TYPE_PORT_CHANGE = 0x09,
MLX5_EVENT_TYPE_GPIO_EVENT = 0x15,
+ MLX5_EVENT_TYPE_PORT_MODULE_EVENT = 0x16,
MLX5_EVENT_TYPE_REMOTE_CONFIG = 0x19,
MLX5_EVENT_TYPE_DB_BF_CONGESTION = 0x1a,
@@ -552,6 +553,15 @@ struct mlx5_eqe_vport_change {
__be32 rsvd1[6];
} __packed;
+struct mlx5_eqe_port_module {
+ u8 reserved_at_0[1];
+ u8 module;
+ u8 reserved_at_2[1];
+ u8 module_status;
+ u8 reserved_at_4[2];
+ u8 error_type;
+} __packed;
+
union ev_data {
__be32 raw[7];
struct mlx5_eqe_cmd cmd;
@@ -565,6 +575,7 @@ union ev_data {
struct mlx5_eqe_page_req req_pages;
struct mlx5_eqe_page_fault page_fault;
struct mlx5_eqe_vport_change vport_change;
+ struct mlx5_eqe_port_module port_module;
} __packed;
struct mlx5_eqe {
@@ -1060,6 +1071,11 @@ enum {
MLX5_INFINIBAND_PORT_COUNTERS_GROUP = 0x20,
};
+enum {
+ MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP = 0x0,
+ MLX5_PCIE_TIMERS_AND_STATES_COUNTERS_GROUP = 0x2,
+};
+
static inline u16 mlx5_to_sw_pkey_sz(int pkey_sz)
{
if (pkey_sz > MLX5_MAX_LOG_PKEY_TABLE)
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index ecc451d89ccd..0ae55361e674 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -104,6 +104,8 @@ enum {
enum {
MLX5_REG_QETCR = 0x4005,
MLX5_REG_QTCT = 0x400a,
+ MLX5_REG_DCBX_PARAM = 0x4020,
+ MLX5_REG_DCBX_APP = 0x4021,
MLX5_REG_PCAP = 0x5001,
MLX5_REG_PMTU = 0x5003,
MLX5_REG_PTYS = 0x5004,
@@ -121,6 +123,12 @@ enum {
MLX5_REG_HOST_ENDIANNESS = 0x7004,
MLX5_REG_MCIA = 0x9014,
MLX5_REG_MLCR = 0x902b,
+ MLX5_REG_MPCNT = 0x9051,
+};
+
+enum mlx5_dcbx_oper_mode {
+ MLX5E_DCBX_PARAM_VER_OPER_HOST = 0x0,
+ MLX5E_DCBX_PARAM_VER_OPER_AUTO = 0x3,
};
enum {
@@ -208,7 +216,7 @@ struct mlx5_cmd_first {
struct mlx5_cmd_msg {
struct list_head list;
- struct cache_ent *cache;
+ struct cmd_msg_cache *parent;
u32 len;
struct mlx5_cmd_first first;
struct mlx5_cmd_mailbox *next;
@@ -228,17 +236,17 @@ struct mlx5_cmd_debug {
u16 outlen;
};
-struct cache_ent {
+struct cmd_msg_cache {
/* protect block chain allocations
*/
spinlock_t lock;
struct list_head head;
+ unsigned int max_inbox_size;
+ unsigned int num_ent;
};
-struct cmd_msg_cache {
- struct cache_ent large;
- struct cache_ent med;
-
+enum {
+ MLX5_NUM_COMMAND_CACHES = 5,
};
struct mlx5_cmd_stats {
@@ -281,7 +289,7 @@ struct mlx5_cmd {
struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS];
struct pci_pool *pool;
struct mlx5_cmd_debug dbg;
- struct cmd_msg_cache cache;
+ struct cmd_msg_cache cache[MLX5_NUM_COMMAND_CACHES];
int checksum_disabled;
struct mlx5_cmd_stats stats[MLX5_CMD_OP_MAX];
};
@@ -310,6 +318,13 @@ struct mlx5_buf {
u8 page_shift;
};
+struct mlx5_frag_buf {
+ struct mlx5_buf_list *frags;
+ int npages;
+ int size;
+ u8 page_shift;
+};
+
struct mlx5_eq_tasklet {
struct list_head list;
struct list_head process_list;
@@ -498,6 +513,31 @@ struct mlx5_rl_table {
struct mlx5_rl_entry *rl_entry;
};
+enum port_module_event_status_type {
+ MLX5_MODULE_STATUS_PLUGGED = 0x1,
+ MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
+ MLX5_MODULE_STATUS_ERROR = 0x3,
+ MLX5_MODULE_STATUS_NUM = 0x3,
+};
+
+enum port_module_event_error_type {
+ MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED,
+ MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX_CABLE_MODULE,
+ MLX5_MODULE_EVENT_ERROR_BUS_STUCK,
+ MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT,
+ MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST,
+ MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER,
+ MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE,
+ MLX5_MODULE_EVENT_ERROR_BAD_CABLE,
+ MLX5_MODULE_EVENT_ERROR_UNKNOWN,
+ MLX5_MODULE_EVENT_ERROR_NUM,
+};
+
+struct mlx5_port_module_event_stats {
+ u64 status_counters[MLX5_MODULE_STATUS_NUM];
+ u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
+};
+
struct mlx5_priv {
char name[MLX5_MAX_NAME_LEN];
struct mlx5_eq_table eq_table;
@@ -559,6 +599,8 @@ struct mlx5_priv {
unsigned long pci_dev_data;
struct mlx5_fc_stats fc_stats;
struct mlx5_rl_table rl_table;
+
+ struct mlx5_port_module_event_stats pme_stats;
};
enum mlx5_device_state {
@@ -787,6 +829,9 @@ int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size,
struct mlx5_buf *buf, int node);
int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, struct mlx5_buf *buf);
void mlx5_buf_free(struct mlx5_core_dev *dev, struct mlx5_buf *buf);
+int mlx5_frag_buf_alloc_node(struct mlx5_core_dev *dev, int size,
+ struct mlx5_frag_buf *buf, int node);
+void mlx5_frag_buf_free(struct mlx5_core_dev *dev, struct mlx5_frag_buf *buf);
struct mlx5_cmd_mailbox *mlx5_alloc_cmd_mailbox_chain(struct mlx5_core_dev *dev,
gfp_t flags, int npages);
void mlx5_free_cmd_mailbox_chain(struct mlx5_core_dev *dev,
@@ -831,6 +876,7 @@ void mlx5_unregister_debugfs(void);
int mlx5_eq_init(struct mlx5_core_dev *dev);
void mlx5_eq_cleanup(struct mlx5_core_dev *dev);
void mlx5_fill_page_array(struct mlx5_buf *buf, __be64 *pas);
+void mlx5_fill_page_frag_array(struct mlx5_frag_buf *frag_buf, __be64 *pas);
void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn);
void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type);
#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index 93ebc5e21334..949b24b6c479 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -42,6 +42,10 @@ enum {
MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO = 1 << 16,
};
+enum {
+ MLX5_FLOW_TABLE_TUNNEL_EN = BIT(0),
+};
+
#define LEFTOVERS_RULE_NUM 2
static inline void build_leftovers_ft_param(int *priority,
int *n_ent,
@@ -69,8 +73,8 @@ enum mlx5_flow_namespace_type {
struct mlx5_flow_table;
struct mlx5_flow_group;
-struct mlx5_flow_rule;
struct mlx5_flow_namespace;
+struct mlx5_flow_handle;
struct mlx5_flow_spec {
u8 match_criteria_enable;
@@ -97,13 +101,15 @@ mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
int prio,
int num_flow_table_entries,
int max_num_groups,
- u32 level);
+ u32 level,
+ u32 flags);
struct mlx5_flow_table *
mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
int prio,
int num_flow_table_entries,
- u32 level);
+ u32 level,
+ u32 flags);
struct mlx5_flow_table *
mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
int prio,
@@ -124,21 +130,28 @@ struct mlx5_flow_group *
mlx5_create_flow_group(struct mlx5_flow_table *ft, u32 *in);
void mlx5_destroy_flow_group(struct mlx5_flow_group *fg);
+struct mlx5_flow_act {
+ u32 action;
+ u32 flow_tag;
+ u32 encap_id;
+};
+
/* Single destination per rule.
* Group ID is implied by the match criteria.
*/
-struct mlx5_flow_rule *
-mlx5_add_flow_rule(struct mlx5_flow_table *ft,
- struct mlx5_flow_spec *spec,
- u32 action,
- u32 flow_tag,
- struct mlx5_flow_destination *dest);
-void mlx5_del_flow_rule(struct mlx5_flow_rule *fr);
-
-int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
- struct mlx5_flow_destination *dest);
-
-struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule);
+struct mlx5_flow_handle *
+mlx5_add_flow_rules(struct mlx5_flow_table *ft,
+ struct mlx5_flow_spec *spec,
+ struct mlx5_flow_act *flow_act,
+ struct mlx5_flow_destination *dest,
+ int dest_num);
+void mlx5_del_flow_rules(struct mlx5_flow_handle *fr);
+
+int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler,
+ struct mlx5_flow_destination *new_dest,
+ struct mlx5_flow_destination *old_dest);
+
+struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handler);
struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
void mlx5_fc_query_cached(struct mlx5_fc *counter,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 6045d4d58065..a5f0fbedf1e7 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -83,6 +83,7 @@ enum {
MLX5_CMD_OP_SET_HCA_CAP = 0x109,
MLX5_CMD_OP_QUERY_ISSI = 0x10a,
MLX5_CMD_OP_SET_ISSI = 0x10b,
+ MLX5_CMD_OP_SET_DRIVER_VERSION = 0x10d,
MLX5_CMD_OP_CREATE_MKEY = 0x200,
MLX5_CMD_OP_QUERY_MKEY = 0x201,
MLX5_CMD_OP_DESTROY_MKEY = 0x202,
@@ -145,6 +146,12 @@ enum {
MLX5_CMD_OP_QUERY_Q_COUNTER = 0x773,
MLX5_CMD_OP_SET_RATE_LIMIT = 0x780,
MLX5_CMD_OP_QUERY_RATE_LIMIT = 0x781,
+ MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT = 0x782,
+ MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT = 0x783,
+ MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT = 0x784,
+ MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT = 0x785,
+ MLX5_CMD_OP_CREATE_QOS_PARA_VPORT = 0x786,
+ MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT = 0x787,
MLX5_CMD_OP_ALLOC_PD = 0x800,
MLX5_CMD_OP_DEALLOC_PD = 0x801,
MLX5_CMD_OP_ALLOC_UAR = 0x802,
@@ -537,13 +544,27 @@ struct mlx5_ifc_e_switch_cap_bits {
struct mlx5_ifc_qos_cap_bits {
u8 packet_pacing[0x1];
- u8 reserved_0[0x1f];
- u8 reserved_1[0x20];
+ u8 esw_scheduling[0x1];
+ u8 reserved_at_2[0x1e];
+
+ u8 reserved_at_20[0x20];
+
u8 packet_pacing_max_rate[0x20];
+
u8 packet_pacing_min_rate[0x20];
- u8 reserved_2[0x10];
+
+ u8 reserved_at_80[0x10];
u8 packet_pacing_rate_table_size[0x10];
- u8 reserved_3[0x760];
+
+ u8 esw_element_type[0x10];
+ u8 esw_tsar_type[0x10];
+
+ u8 reserved_at_c0[0x10];
+ u8 max_qos_para_vport[0x10];
+
+ u8 max_tsar_bw_share[0x20];
+
+ u8 reserved_at_100[0x700];
};
struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
@@ -804,7 +825,8 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 early_vf_enable[0x1];
u8 reserved_at_1a9[0x2];
u8 local_ca_ack_delay[0x5];
- u8 reserved_at_1af[0x2];
+ u8 port_module_event[0x1];
+ u8 reserved_at_1b0[0x1];
u8 ports_check[0x1];
u8 reserved_at_1b2[0x1];
u8 disable_link_up[0x1];
@@ -888,7 +910,7 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 log_pg_sz[0x8];
u8 bf[0x1];
- u8 reserved_at_261[0x1];
+ u8 driver_version[0x1];
u8 pad_tx_eth_packet[0x1];
u8 reserved_at_263[0x8];
u8 log_bf_reg_size[0x5];
@@ -1735,6 +1757,80 @@ struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits {
u8 reserved_at_4c0[0x300];
};
+struct mlx5_ifc_pcie_perf_cntrs_grp_data_layout_bits {
+ u8 life_time_counter_high[0x20];
+
+ u8 life_time_counter_low[0x20];
+
+ u8 rx_errors[0x20];
+
+ u8 tx_errors[0x20];
+
+ u8 l0_to_recovery_eieos[0x20];
+
+ u8 l0_to_recovery_ts[0x20];
+
+ u8 l0_to_recovery_framing[0x20];
+
+ u8 l0_to_recovery_retrain[0x20];
+
+ u8 crc_error_dllp[0x20];
+
+ u8 crc_error_tlp[0x20];
+
+ u8 reserved_at_140[0x680];
+};
+
+struct mlx5_ifc_pcie_tas_cntrs_grp_data_layout_bits {
+ u8 life_time_counter_high[0x20];
+
+ u8 life_time_counter_low[0x20];
+
+ u8 time_to_boot_image_start[0x20];
+
+ u8 time_to_link_image[0x20];
+
+ u8 calibration_time[0x20];
+
+ u8 time_to_first_perst[0x20];
+
+ u8 time_to_detect_state[0x20];
+
+ u8 time_to_l0[0x20];
+
+ u8 time_to_crs_en[0x20];
+
+ u8 time_to_plastic_image_start[0x20];
+
+ u8 time_to_iron_image_start[0x20];
+
+ u8 perst_handler[0x20];
+
+ u8 times_in_l1[0x20];
+
+ u8 times_in_l23[0x20];
+
+ u8 dl_down[0x20];
+
+ u8 config_cycle1usec[0x20];
+
+ u8 config_cycle2to7usec[0x20];
+
+ u8 config_cycle_8to15usec[0x20];
+
+ u8 config_cycle_16_to_63usec[0x20];
+
+ u8 config_cycle_64usec[0x20];
+
+ u8 correctable_err_msg_sent[0x20];
+
+ u8 non_fatal_err_msg_sent[0x20];
+
+ u8 fatal_err_msg_sent[0x20];
+
+ u8 reserved_at_2e0[0x4e0];
+};
+
struct mlx5_ifc_cmd_inter_comp_event_bits {
u8 command_completion_vector[0x20];
@@ -2333,6 +2429,30 @@ struct mlx5_ifc_sqc_bits {
struct mlx5_ifc_wq_bits wq;
};
+enum {
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR = 0x0,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT = 0x1,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC = 0x2,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC = 0x3,
+};
+
+struct mlx5_ifc_scheduling_context_bits {
+ u8 element_type[0x8];
+ u8 reserved_at_8[0x18];
+
+ u8 element_attributes[0x20];
+
+ u8 parent_element_id[0x20];
+
+ u8 reserved_at_60[0x40];
+
+ u8 bw_share[0x20];
+
+ u8 max_average_bw[0x20];
+
+ u8 reserved_at_e0[0x120];
+};
+
struct mlx5_ifc_rqtc_bits {
u8 reserved_at_0[0xa0];
@@ -2844,7 +2964,7 @@ struct mlx5_ifc_xrqc_bits {
struct mlx5_ifc_tag_matching_topology_context_bits tag_matching_topology_context;
- u8 reserved_at_180[0x200];
+ u8 reserved_at_180[0x880];
struct mlx5_ifc_wq_bits wq;
};
@@ -2875,6 +2995,12 @@ union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits {
u8 reserved_at_0[0x7c0];
};
+union mlx5_ifc_pcie_cntrs_grp_data_layout_auto_bits {
+ struct mlx5_ifc_pcie_perf_cntrs_grp_data_layout_bits pcie_perf_cntrs_grp_data_layout;
+ struct mlx5_ifc_pcie_tas_cntrs_grp_data_layout_bits pcie_tas_cntrs_grp_data_layout;
+ u8 reserved_at_0[0x7c0];
+};
+
union mlx5_ifc_event_auto_bits {
struct mlx5_ifc_comp_event_bits comp_event;
struct mlx5_ifc_dct_events_bits dct_events;
@@ -2920,6 +3046,29 @@ struct mlx5_ifc_register_loopback_control_bits {
u8 reserved_at_20[0x60];
};
+struct mlx5_ifc_vport_tc_element_bits {
+ u8 traffic_class[0x4];
+ u8 reserved_at_4[0xc];
+ u8 vport_number[0x10];
+};
+
+struct mlx5_ifc_vport_element_bits {
+ u8 reserved_at_0[0x10];
+ u8 vport_number[0x10];
+};
+
+enum {
+ TSAR_ELEMENT_TSAR_TYPE_DWRR = 0x0,
+ TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN = 0x1,
+ TSAR_ELEMENT_TSAR_TYPE_ETS = 0x2,
+};
+
+struct mlx5_ifc_tsar_element_bits {
+ u8 reserved_at_0[0x8];
+ u8 tsar_type[0x8];
+ u8 reserved_at_10[0x10];
+};
+
struct mlx5_ifc_teardown_hca_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -3540,6 +3689,39 @@ struct mlx5_ifc_query_special_contexts_in_bits {
u8 reserved_at_40[0x40];
};
+struct mlx5_ifc_query_scheduling_element_out_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_at_40[0xc0];
+
+ struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+ u8 reserved_at_300[0x100];
+};
+
+enum {
+ SCHEDULING_HIERARCHY_E_SWITCH = 0x2,
+};
+
+struct mlx5_ifc_query_scheduling_element_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+
+ u8 scheduling_hierarchy[0x8];
+ u8 reserved_at_48[0x18];
+
+ u8 scheduling_element_id[0x20];
+
+ u8 reserved_at_80[0x180];
+};
+
struct mlx5_ifc_query_rqt_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -3904,6 +4086,25 @@ struct mlx5_ifc_query_issi_in_bits {
u8 reserved_at_40[0x40];
};
+struct mlx5_ifc_set_driver_version_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+ u8 reserved_1[0x40];
+};
+
+struct mlx5_ifc_set_driver_version_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x40];
+ u8 driver_version[64][0x8];
+};
+
struct mlx5_ifc_query_hca_vport_pkey_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -4725,6 +4926,43 @@ struct mlx5_ifc_modify_sq_in_bits {
struct mlx5_ifc_sqc_bits ctx;
};
+struct mlx5_ifc_modify_scheduling_element_out_bits {
+ u8 status[0x8];
+ u8 reserved_at_8[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_at_40[0x1c0];
+};
+
+enum {
+ MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE = 0x1,
+ MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW = 0x2,
+};
+
+struct mlx5_ifc_modify_scheduling_element_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+
+ u8 scheduling_hierarchy[0x8];
+ u8 reserved_at_48[0x18];
+
+ u8 scheduling_element_id[0x20];
+
+ u8 reserved_at_80[0x20];
+
+ u8 modify_bitmask[0x20];
+
+ u8 reserved_at_c0[0x40];
+
+ struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+ u8 reserved_at_300[0x100];
+};
+
struct mlx5_ifc_modify_rqt_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -5390,6 +5628,30 @@ struct mlx5_ifc_destroy_sq_in_bits {
u8 reserved_at_60[0x20];
};
+struct mlx5_ifc_destroy_scheduling_element_out_bits {
+ u8 status[0x8];
+ u8 reserved_at_8[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_at_40[0x1c0];
+};
+
+struct mlx5_ifc_destroy_scheduling_element_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+
+ u8 scheduling_hierarchy[0x8];
+ u8 reserved_at_48[0x18];
+
+ u8 scheduling_element_id[0x20];
+
+ u8 reserved_at_80[0x180];
+};
+
struct mlx5_ifc_destroy_rqt_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -6017,6 +6279,36 @@ struct mlx5_ifc_create_sq_in_bits {
struct mlx5_ifc_sqc_bits ctx;
};
+struct mlx5_ifc_create_scheduling_element_out_bits {
+ u8 status[0x8];
+ u8 reserved_at_8[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_at_40[0x40];
+
+ u8 scheduling_element_id[0x20];
+
+ u8 reserved_at_a0[0x160];
+};
+
+struct mlx5_ifc_create_scheduling_element_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_at_10[0x10];
+
+ u8 reserved_at_20[0x10];
+ u8 op_mod[0x10];
+
+ u8 scheduling_hierarchy[0x8];
+ u8 reserved_at_48[0x18];
+
+ u8 reserved_at_60[0xa0];
+
+ struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+ u8 reserved_at_300[0x100];
+};
+
struct mlx5_ifc_create_rqt_out_bits {
u8 status[0x8];
u8 reserved_at_8[0x18];
@@ -7028,6 +7320,18 @@ struct mlx5_ifc_ppcnt_reg_bits {
union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits counter_set;
};
+struct mlx5_ifc_mpcnt_reg_bits {
+ u8 reserved_at_0[0x8];
+ u8 pcie_index[0x8];
+ u8 reserved_at_10[0xa];
+ u8 grp[0x6];
+
+ u8 clr[0x1];
+ u8 reserved_at_21[0x1f];
+
+ union mlx5_ifc_pcie_cntrs_grp_data_layout_auto_bits counter_set;
+};
+
struct mlx5_ifc_ppad_reg_bits {
u8 reserved_at_0[0x3];
u8 single_mac[0x1];
@@ -7633,6 +7937,7 @@ union mlx5_ifc_ports_control_registers_document_bits {
struct mlx5_ifc_pmtu_reg_bits pmtu_reg;
struct mlx5_ifc_ppad_reg_bits ppad_reg;
struct mlx5_ifc_ppcnt_reg_bits ppcnt_reg;
+ struct mlx5_ifc_mpcnt_reg_bits mpcnt_reg;
struct mlx5_ifc_pplm_reg_bits pplm_reg;
struct mlx5_ifc_pplr_reg_bits pplr_reg;
struct mlx5_ifc_ppsc_reg_bits ppsc_reg;
diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h
index b3065acd20b4..e527732fb31b 100644
--- a/include/linux/mlx5/port.h
+++ b/include/linux/mlx5/port.h
@@ -94,6 +94,9 @@ enum mlx5e_link_mode {
#define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
+#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
+#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF
+
int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps);
int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
int ptys_size, int proto_mask, u8 local_port);
@@ -138,8 +141,12 @@ int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx,
int mlx5_max_tc(struct mlx5_core_dev *mdev);
int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc);
+int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
+ u8 prio, u8 *tc);
int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group);
int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw);
+int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
+ u8 tc, u8 *bw_pct);
int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
u8 *max_bw_value,
u8 *max_bw_unit);
@@ -155,4 +162,6 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
u16 offset, u16 size, u8 *data);
+int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
+int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
#endif /* __MLX5_PORT_H__ */
diff --git a/include/linux/mlx5/srq.h b/include/linux/mlx5/srq.h
index 33c97dc900f8..1cde0fd53f90 100644
--- a/include/linux/mlx5/srq.h
+++ b/include/linux/mlx5/srq.h
@@ -55,7 +55,7 @@ struct mlx5_srq_attr {
u32 lwm;
u32 user_index;
u64 db_record;
- u64 *pas;
+ __be64 *pas;
};
struct mlx5_core_dev;
diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h
index 451b0bde9083..ec35157ea725 100644
--- a/include/linux/mlx5/vport.h
+++ b/include/linux/mlx5/vport.h
@@ -36,6 +36,12 @@
#include <linux/mlx5/driver.h>
#include <linux/mlx5/device.h>
+enum {
+ MLX5_CAP_INLINE_MODE_L2,
+ MLX5_CAP_INLINE_MODE_VPORT_CONTEXT,
+ MLX5_CAP_INLINE_MODE_NOT_REQUIRED,
+};
+
u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport);
u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
u16 vport);
@@ -43,8 +49,8 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
u16 vport, u8 state);
int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
u16 vport, u8 *addr);
-void mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
- u8 *min_inline);
+int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
+ u16 vport, u8 *min_inline);
int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev,
u16 vport, u8 min_inline);
int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *dev,
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 73fad83acbcb..95d69d498296 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -89,6 +89,8 @@ struct mmc_ext_csd {
unsigned int boot_ro_lock; /* ro lock support */
bool boot_ro_lockable;
bool ffu_capable; /* Firmware upgrade support */
+ bool cmdq_support; /* Command Queue supported */
+ unsigned int cmdq_depth; /* Command Queue depth */
#define MMC_FIRMWARE_LEN 8
u8 fwrev[MMC_FIRMWARE_LEN]; /* FW version */
u8 raw_exception_status; /* 54 */
@@ -207,18 +209,6 @@ struct sdio_func_tuple;
#define SDIO_MAX_FUNCS 7
-enum mmc_blk_status {
- MMC_BLK_SUCCESS = 0,
- MMC_BLK_PARTIAL,
- MMC_BLK_CMD_ERR,
- MMC_BLK_RETRY,
- MMC_BLK_ABORT,
- MMC_BLK_DATA_ERR,
- MMC_BLK_ECC_ERR,
- MMC_BLK_NOMEDIUM,
- MMC_BLK_NEW_REQUEST,
-};
-
/* The number of MMC physical partitions. These consist of:
* boot partitions (2), general purpose partitions (4) and
* RPMB partition (1) in MMC v4.4.
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 2b953eb8ceae..e33cc748dcfe 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -15,6 +15,18 @@ struct request;
struct mmc_data;
struct mmc_request;
+enum mmc_blk_status {
+ MMC_BLK_SUCCESS = 0,
+ MMC_BLK_PARTIAL,
+ MMC_BLK_CMD_ERR,
+ MMC_BLK_RETRY,
+ MMC_BLK_ABORT,
+ MMC_BLK_DATA_ERR,
+ MMC_BLK_ECC_ERR,
+ MMC_BLK_NOMEDIUM,
+ MMC_BLK_NEW_REQUEST,
+};
+
struct mmc_command {
u32 opcode;
u32 arg;
@@ -150,7 +162,8 @@ struct mmc_async_req;
extern int mmc_stop_bkops(struct mmc_card *);
extern int mmc_read_bkops_status(struct mmc_card *);
extern struct mmc_async_req *mmc_start_req(struct mmc_host *,
- struct mmc_async_req *, int *);
+ struct mmc_async_req *,
+ enum mmc_blk_status *);
extern int mmc_interrupt_hpi(struct mmc_card *);
extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
extern void mmc_wait_for_req_done(struct mmc_host *host,
@@ -163,6 +176,7 @@ extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
extern int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
+extern int mmc_abort_tuning(struct mmc_host *host, u32 opcode);
extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
#define MMC_ERASE_ARG 0x00000000
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index f5af2bd35e7f..15db6f83f53f 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -39,6 +39,12 @@ enum {
EVENT_DATA_ERROR,
};
+enum dw_mci_cookie {
+ COOKIE_UNMAPPED,
+ COOKIE_PRE_MAPPED, /* mapped by pre_req() of dwmmc */
+ COOKIE_MAPPED, /* mapped by prepare_data() of dwmmc */
+};
+
struct mmc_data;
enum {
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0b2439441cc8..8bc884121465 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -93,8 +93,7 @@ struct mmc_host_ops {
*/
void (*post_req)(struct mmc_host *host, struct mmc_request *req,
int err);
- void (*pre_req)(struct mmc_host *host, struct mmc_request *req,
- bool is_first_req);
+ void (*pre_req)(struct mmc_host *host, struct mmc_request *req);
void (*request)(struct mmc_host *host, struct mmc_request *req);
/*
@@ -173,7 +172,7 @@ struct mmc_async_req {
* Check error status of completed mmc request.
* Returns 0 if success otherwise non zero.
*/
- int (*err_check) (struct mmc_card *, struct mmc_async_req *);
+ enum mmc_blk_status (*err_check)(struct mmc_card *, struct mmc_async_req *);
};
/**
@@ -198,14 +197,12 @@ struct mmc_slot {
* @is_new_req wake up reason was new request
* @is_waiting_last_req mmc context waiting for single running request
* @wait wait queue
- * @lock lock to protect data fields
*/
struct mmc_context_info {
bool is_done_rcv;
bool is_new_req;
bool is_waiting_last_req;
wait_queue_head_t wait;
- spinlock_t lock;
};
struct regulator;
@@ -495,11 +492,6 @@ static inline int mmc_host_uhs(struct mmc_host *host)
MMC_CAP_UHS_DDR50);
}
-static inline int mmc_host_packed_wr(struct mmc_host *host)
-{
- return host->caps2 & MMC_CAP2_PACKED_WR;
-}
-
static inline int mmc_card_hs(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_SD_HS ||
@@ -546,6 +538,11 @@ static inline void mmc_retune_recheck(struct mmc_host *host)
host->retune_now = 1;
}
+static inline bool mmc_can_retune(struct mmc_host *host)
+{
+ return host->can_retune == 1;
+}
+
void mmc_retune_pause(struct mmc_host *host);
void mmc_retune_unpause(struct mmc_host *host);
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index c376209c70ef..672730acc705 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -84,6 +84,13 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
+ /* class 11 */
+#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
+#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
+#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
+#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
+#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
+
static inline bool mmc_op_multi(u32 opcode)
{
return opcode == MMC_WRITE_MULTIPLE_BLOCK ||
@@ -272,6 +279,7 @@ struct _mmc_csd {
* EXT_CSD fields
*/
+#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
@@ -331,6 +339,8 @@ struct _mmc_csd {
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
+#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
+#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
@@ -438,6 +448,13 @@ struct _mmc_csd {
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
/*
+ * Command Queue
+ */
+#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0)
+#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0)
+#define EXT_CSD_CMDQ_SUPPORTED BIT(0)
+
+/*
* MMC_SWITCH access modes
*/
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
index 3945a8c9d3cb..a7972cd3bc14 100644
--- a/include/linux/mmc/slot-gpio.h
+++ b/include/linux/mmc/slot-gpio.h
@@ -29,5 +29,6 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
void mmc_gpio_set_cd_isr(struct mmc_host *host,
irqreturn_t (*isr)(int irq, void *dev_id));
void mmc_gpiod_request_cd_irq(struct mmc_host *host);
+bool mmc_can_gpio_cd(struct mmc_host *host);
#endif
diff --git a/include/linux/mutex-debug.h b/include/linux/mutex-debug.h
deleted file mode 100644
index 4ac8b1977b73..000000000000
--- a/include/linux/mutex-debug.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __LINUX_MUTEX_DEBUG_H
-#define __LINUX_MUTEX_DEBUG_H
-
-#include <linux/linkage.h>
-#include <linux/lockdep.h>
-#include <linux/debug_locks.h>
-
-/*
- * Mutexes - debugging helpers:
- */
-
-#define __DEBUG_MUTEX_INITIALIZER(lockname) \
- , .magic = &lockname
-
-#define mutex_init(mutex) \
-do { \
- static struct lock_class_key __key; \
- \
- __mutex_init((mutex), #mutex, &__key); \
-} while (0)
-
-extern void mutex_destroy(struct mutex *lock);
-
-#endif
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 2cb7531e7d7a..b97870f2debd 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -18,6 +18,7 @@
#include <linux/atomic.h>
#include <asm/processor.h>
#include <linux/osq_lock.h>
+#include <linux/debug_locks.h>
/*
* Simple, straightforward mutexes with strict semantics:
@@ -48,16 +49,12 @@
* locks and tasks (and only those tasks)
*/
struct mutex {
- /* 1: unlocked, 0: locked, negative: locked, possible waiters */
- atomic_t count;
+ atomic_long_t owner;
spinlock_t wait_lock;
- struct list_head wait_list;
-#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
- struct task_struct *owner;
-#endif
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
struct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
+ struct list_head wait_list;
#ifdef CONFIG_DEBUG_MUTEXES
void *magic;
#endif
@@ -66,6 +63,11 @@ struct mutex {
#endif
};
+static inline struct task_struct *__mutex_owner(struct mutex *lock)
+{
+ return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x03);
+}
+
/*
* This is the control structure for tasks blocked on mutex,
* which resides on the blocked task's kernel stack:
@@ -79,9 +81,20 @@ struct mutex_waiter {
};
#ifdef CONFIG_DEBUG_MUTEXES
-# include <linux/mutex-debug.h>
+
+#define __DEBUG_MUTEX_INITIALIZER(lockname) \
+ , .magic = &lockname
+
+extern void mutex_destroy(struct mutex *lock);
+
#else
+
# define __DEBUG_MUTEX_INITIALIZER(lockname)
+
+static inline void mutex_destroy(struct mutex *lock) {}
+
+#endif
+
/**
* mutex_init - initialize the mutex
* @mutex: the mutex to be initialized
@@ -90,14 +103,12 @@ struct mutex_waiter {
*
* It is not allowed to initialize an already locked mutex.
*/
-# define mutex_init(mutex) \
-do { \
- static struct lock_class_key __key; \
- \
- __mutex_init((mutex), #mutex, &__key); \
+#define mutex_init(mutex) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __mutex_init((mutex), #mutex, &__key); \
} while (0)
-static inline void mutex_destroy(struct mutex *lock) {}
-#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
@@ -107,7 +118,7 @@ static inline void mutex_destroy(struct mutex *lock) {}
#endif
#define __MUTEX_INITIALIZER(lockname) \
- { .count = ATOMIC_INIT(1) \
+ { .owner = ATOMIC_LONG_INIT(0) \
, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \
, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \
__DEBUG_MUTEX_INITIALIZER(lockname) \
@@ -127,7 +138,10 @@ extern void __mutex_init(struct mutex *lock, const char *name,
*/
static inline int mutex_is_locked(struct mutex *lock)
{
- return atomic_read(&lock->count) != 1;
+ /*
+ * XXX think about spin_is_locked
+ */
+ return __mutex_owner(lock) != NULL;
}
/*
@@ -175,4 +189,35 @@ extern void mutex_unlock(struct mutex *lock);
extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
+/*
+ * These values are chosen such that FAIL and SUCCESS match the
+ * values of the regular mutex_trylock().
+ */
+enum mutex_trylock_recursive_enum {
+ MUTEX_TRYLOCK_FAILED = 0,
+ MUTEX_TRYLOCK_SUCCESS = 1,
+ MUTEX_TRYLOCK_RECURSIVE,
+};
+
+/**
+ * mutex_trylock_recursive - trylock variant that allows recursive locking
+ * @lock: mutex to be locked
+ *
+ * This function should not be used, _ever_. It is purely for hysterical GEM
+ * raisins, and once those are gone this will be removed.
+ *
+ * Returns:
+ * MUTEX_TRYLOCK_FAILED - trylock failed,
+ * MUTEX_TRYLOCK_SUCCESS - lock acquired,
+ * MUTEX_TRYLOCK_RECURSIVE - we already owned the lock.
+ */
+static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
+mutex_trylock_recursive(struct mutex *lock)
+{
+ if (unlikely(__mutex_owner(lock) == current))
+ return MUTEX_TRYLOCK_RECURSIVE;
+
+ return mutex_trylock(lock);
+}
+
#endif /* __LINUX_MUTEX_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e16a2a980ea8..994f7423a74b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -192,6 +192,7 @@ struct net_device_stats {
#ifdef CONFIG_RPS
#include <linux/static_key.h>
extern struct static_key rps_needed;
+extern struct static_key rfs_needed;
#endif
struct neighbour;
@@ -316,7 +317,6 @@ struct napi_struct {
unsigned int gro_count;
int (*poll)(struct napi_struct *, int);
#ifdef CONFIG_NETPOLL
- spinlock_t poll_lock;
int poll_owner;
#endif
struct net_device *dev;
@@ -334,6 +334,16 @@ enum {
NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */
NAPI_STATE_HASHED, /* In NAPI hash (busy polling possible) */
NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */
+ NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */
+};
+
+enum {
+ NAPIF_STATE_SCHED = (1UL << NAPI_STATE_SCHED),
+ NAPIF_STATE_DISABLE = (1UL << NAPI_STATE_DISABLE),
+ NAPIF_STATE_NPSVC = (1UL << NAPI_STATE_NPSVC),
+ NAPIF_STATE_HASHED = (1UL << NAPI_STATE_HASHED),
+ NAPIF_STATE_NO_BUSY_POLL = (1UL << NAPI_STATE_NO_BUSY_POLL),
+ NAPIF_STATE_IN_BUSY_POLL = (1UL << NAPI_STATE_IN_BUSY_POLL),
};
enum gro_result {
@@ -453,32 +463,22 @@ static inline bool napi_reschedule(struct napi_struct *napi)
return false;
}
-void __napi_complete(struct napi_struct *n);
-void napi_complete_done(struct napi_struct *n, int work_done);
+bool __napi_complete(struct napi_struct *n);
+bool napi_complete_done(struct napi_struct *n, int work_done);
/**
* napi_complete - NAPI processing complete
* @n: NAPI context
*
* Mark NAPI processing as complete.
* Consider using napi_complete_done() instead.
+ * Return false if device should avoid rearming interrupts.
*/
-static inline void napi_complete(struct napi_struct *n)
+static inline bool napi_complete(struct napi_struct *n)
{
return napi_complete_done(n, 0);
}
/**
- * napi_hash_add - add a NAPI to global hashtable
- * @napi: NAPI context
- *
- * Generate a new napi_id and store a @napi under it in napi_hash.
- * Used for busy polling (CONFIG_NET_RX_BUSY_POLL).
- * Note: This is normally automatically done from netif_napi_add(),
- * so might disappear in a future Linux version.
- */
-void napi_hash_add(struct napi_struct *napi);
-
-/**
* napi_hash_del - remove a NAPI from global table
* @napi: NAPI context
*
@@ -732,8 +732,8 @@ struct xps_dev_maps {
struct rcu_head rcu;
struct xps_map __rcu *cpu_map[0];
};
-#define XPS_DEV_MAPS_SIZE (sizeof(struct xps_dev_maps) + \
- (nr_cpu_ids * sizeof(struct xps_map *)))
+#define XPS_DEV_MAPS_SIZE(_tcs) (sizeof(struct xps_dev_maps) + \
+ (nr_cpu_ids * (_tcs) * sizeof(struct xps_map *)))
#endif /* CONFIG_XPS */
#define TC_MAX_QUEUE 16
@@ -803,6 +803,7 @@ struct tc_to_netdev {
struct tc_cls_matchall_offload *cls_mall;
struct tc_cls_bpf_offload *cls_bpf;
};
+ bool egress_dev;
};
/* These structures hold the attributes of xdp state that are being passed
@@ -926,7 +927,7 @@ struct netdev_xdp {
* 3. Update dev->stats asynchronously and atomically, and define
* neither operation.
*
- * bool (*ndo_has_offload_stats)(int attr_id)
+ * bool (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id)
* Return true if this device supports offload stats of this attr_id.
*
* int (*ndo_get_offload_stats)(int attr_id, const struct net_device *dev,
@@ -1166,7 +1167,7 @@ struct net_device_ops {
struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev,
struct rtnl_link_stats64 *storage);
- bool (*ndo_has_offload_stats)(int attr_id);
+ bool (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id);
int (*ndo_get_offload_stats)(int attr_id,
const struct net_device *dev,
void *attr_data);
@@ -1456,7 +1457,6 @@ enum netdev_priv_flags {
* @ptype_specific: Device-specific, protocol-specific packet handlers
*
* @adj_list: Directly linked devices, like slaves for bonding
- * @all_adj_list: All linked devices, *including* neighbours
* @features: Currently active device features
* @hw_features: User-changeable features
*
@@ -1506,6 +1506,8 @@ enum netdev_priv_flags {
* @if_port: Selectable AUI, TP, ...
* @dma: DMA channel
* @mtu: Interface MTU value
+ * @min_mtu: Interface Minimum MTU value
+ * @max_mtu: Interface Maximum MTU value
* @type: Interface hardware type
* @hard_header_len: Maximum hardware header length.
*
@@ -1673,11 +1675,6 @@ struct net_device {
struct list_head lower;
} adj_list;
- struct {
- struct list_head upper;
- struct list_head lower;
- } all_adj_list;
-
netdev_features_t features;
netdev_features_t hw_features;
netdev_features_t wanted_features;
@@ -1726,6 +1723,8 @@ struct net_device {
unsigned char dma;
unsigned int mtu;
+ unsigned int min_mtu;
+ unsigned int max_mtu;
unsigned short type;
unsigned short hard_header_len;
@@ -1922,34 +1921,10 @@ int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)
return 0;
}
-static inline
-void netdev_reset_tc(struct net_device *dev)
-{
- dev->num_tc = 0;
- memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
- memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
-}
-
-static inline
-int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
-{
- if (tc >= dev->num_tc)
- return -EINVAL;
-
- dev->tc_to_txq[tc].count = count;
- dev->tc_to_txq[tc].offset = offset;
- return 0;
-}
-
-static inline
-int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
-{
- if (num_tc > TC_MAX_QUEUE)
- return -EINVAL;
-
- dev->num_tc = num_tc;
- return 0;
-}
+int netdev_txq_to_tc(struct net_device *dev, unsigned int txq);
+void netdev_reset_tc(struct net_device *dev);
+int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset);
+int netdev_set_num_tc(struct net_device *dev, u8 num_tc);
static inline
int netdev_get_num_tc(struct net_device *dev)
@@ -2686,71 +2661,6 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
remcsum_unadjust((__sum16 *)ptr, grc->delta);
}
-struct skb_csum_offl_spec {
- __u16 ipv4_okay:1,
- ipv6_okay:1,
- encap_okay:1,
- ip_options_okay:1,
- ext_hdrs_okay:1,
- tcp_okay:1,
- udp_okay:1,
- sctp_okay:1,
- vlan_okay:1,
- no_encapped_ipv6:1,
- no_not_encapped:1;
-};
-
-bool __skb_csum_offload_chk(struct sk_buff *skb,
- const struct skb_csum_offl_spec *spec,
- bool *csum_encapped,
- bool csum_help);
-
-static inline bool skb_csum_offload_chk(struct sk_buff *skb,
- const struct skb_csum_offl_spec *spec,
- bool *csum_encapped,
- bool csum_help)
-{
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return false;
-
- return __skb_csum_offload_chk(skb, spec, csum_encapped, csum_help);
-}
-
-static inline bool skb_csum_offload_chk_help(struct sk_buff *skb,
- const struct skb_csum_offl_spec *spec)
-{
- bool csum_encapped;
-
- return skb_csum_offload_chk(skb, spec, &csum_encapped, true);
-}
-
-static inline bool skb_csum_off_chk_help_cmn(struct sk_buff *skb)
-{
- static const struct skb_csum_offl_spec csum_offl_spec = {
- .ipv4_okay = 1,
- .ip_options_okay = 1,
- .ipv6_okay = 1,
- .vlan_okay = 1,
- .tcp_okay = 1,
- .udp_okay = 1,
- };
-
- return skb_csum_offload_chk_help(skb, &csum_offl_spec);
-}
-
-static inline bool skb_csum_off_chk_help_cmn_v4_only(struct sk_buff *skb)
-{
- static const struct skb_csum_offl_spec csum_offl_spec = {
- .ipv4_okay = 1,
- .ip_options_okay = 1,
- .tcp_okay = 1,
- .udp_okay = 1,
- .vlan_okay = 1,
- };
-
- return skb_csum_offload_chk_help(skb, &csum_offl_spec);
-}
-
static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type,
const void *daddr, const void *saddr,
@@ -3345,7 +3255,7 @@ int dev_get_phys_port_id(struct net_device *dev,
int dev_get_phys_port_name(struct net_device *dev,
char *name, size_t len);
int dev_change_proto_down(struct net_device *dev, bool proto_down);
-int dev_change_xdp_fd(struct net_device *dev, int fd);
+int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags);
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq, int *ret);
@@ -3554,6 +3464,17 @@ static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
txq->xmit_lock_owner = cpu;
}
+static inline bool __netif_tx_acquire(struct netdev_queue *txq)
+{
+ __acquire(&txq->_xmit_lock);
+ return true;
+}
+
+static inline void __netif_tx_release(struct netdev_queue *txq)
+{
+ __release(&txq->_xmit_lock);
+}
+
static inline void __netif_tx_lock_bh(struct netdev_queue *txq)
{
spin_lock_bh(&txq->_xmit_lock);
@@ -3655,17 +3576,21 @@ static inline void netif_tx_unlock_bh(struct net_device *dev)
#define HARD_TX_LOCK(dev, txq, cpu) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
__netif_tx_lock(txq, cpu); \
+ } else { \
+ __netif_tx_acquire(txq); \
} \
}
#define HARD_TX_TRYLOCK(dev, txq) \
(((dev->features & NETIF_F_LLTX) == 0) ? \
__netif_tx_trylock(txq) : \
- true )
+ __netif_tx_acquire(txq))
#define HARD_TX_UNLOCK(dev, txq) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
__netif_tx_unlock(txq); \
+ } else { \
+ __netif_tx_release(txq); \
} \
}
@@ -3884,12 +3809,13 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
updev; \
updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
-/* iterate through upper list, must be called under RCU read lock */
-#define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
- for (iter = &(dev)->all_adj_list.upper, \
- updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \
- updev; \
- updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
+int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
+ int (*fn)(struct net_device *upper_dev,
+ void *data),
+ void *data);
+
+bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
+ struct net_device *upper_dev);
void *netdev_lower_get_next_private(struct net_device *dev,
struct list_head **iter);
@@ -3922,17 +3848,14 @@ struct net_device *netdev_all_lower_get_next(struct net_device *dev,
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
struct list_head **iter);
-#define netdev_for_each_all_lower_dev(dev, ldev, iter) \
- for (iter = (dev)->all_adj_list.lower.next, \
- ldev = netdev_all_lower_get_next(dev, &(iter)); \
- ldev; \
- ldev = netdev_all_lower_get_next(dev, &(iter)))
-
-#define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \
- for (iter = &(dev)->all_adj_list.lower, \
- ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \
- ldev; \
- ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))
+int netdev_walk_all_lower_dev(struct net_device *dev,
+ int (*fn)(struct net_device *lower_dev,
+ void *data),
+ void *data);
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+ int (*fn)(struct net_device *lower_dev,
+ void *data),
+ void *data);
void *netdev_adjacent_get_private(struct list_head *adj_list);
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
@@ -4009,19 +3932,6 @@ static inline bool can_checksum_protocol(netdev_features_t features,
}
}
-/* Map an ethertype into IP protocol if possible */
-static inline int eproto_to_ipproto(int eproto)
-{
- switch (eproto) {
- case htons(ETH_P_IP):
- return IPPROTO_IP;
- case htons(ETH_P_IPV6):
- return IPPROTO_IPV6;
- default:
- return -1;
- }
-}
-
#ifdef CONFIG_BUG
void netdev_rx_csum_fault(struct net_device *dev);
#else
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index abc7fdcb9eb1..a4b97be30b28 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -49,13 +49,11 @@ struct sock;
struct nf_hook_state {
unsigned int hook;
- int thresh;
u_int8_t pf;
struct net_device *in;
struct net_device *out;
struct sock *sk;
struct net *net;
- struct nf_hook_entry __rcu *hook_entries;
int (*okfn)(struct net *, struct sock *, struct sk_buff *);
};
@@ -77,14 +75,42 @@ struct nf_hook_ops {
struct nf_hook_entry {
struct nf_hook_entry __rcu *next;
- struct nf_hook_ops ops;
+ nf_hookfn *hook;
+ void *priv;
const struct nf_hook_ops *orig_ops;
};
+static inline void
+nf_hook_entry_init(struct nf_hook_entry *entry, const struct nf_hook_ops *ops)
+{
+ entry->next = NULL;
+ entry->hook = ops->hook;
+ entry->priv = ops->priv;
+ entry->orig_ops = ops;
+}
+
+static inline int
+nf_hook_entry_priority(const struct nf_hook_entry *entry)
+{
+ return entry->orig_ops->priority;
+}
+
+static inline int
+nf_hook_entry_hookfn(const struct nf_hook_entry *entry, struct sk_buff *skb,
+ struct nf_hook_state *state)
+{
+ return entry->hook(entry->priv, skb, state);
+}
+
+static inline const struct nf_hook_ops *
+nf_hook_entry_ops(const struct nf_hook_entry *entry)
+{
+ return entry->orig_ops;
+}
+
static inline void nf_hook_state_init(struct nf_hook_state *p,
- struct nf_hook_entry *hook_entry,
unsigned int hook,
- int thresh, u_int8_t pf,
+ u_int8_t pf,
struct net_device *indev,
struct net_device *outdev,
struct sock *sk,
@@ -92,13 +118,11 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
p->hook = hook;
- p->thresh = thresh;
p->pf = pf;
p->in = indev;
p->out = outdev;
p->sk = sk;
p->net = net;
- RCU_INIT_POINTER(p->hook_entries, hook_entry);
p->okfn = okfn;
}
@@ -152,23 +176,20 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
#endif
-int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
+int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
+ struct nf_hook_entry *entry);
/**
- * nf_hook_thresh - call a netfilter hook
+ * nf_hook - call a netfilter hook
*
* Returns 1 if the hook has allowed the packet to pass. The function
* okfn must be invoked by the caller in this case. Any other return
* value indicates the packet has been consumed by the hook.
*/
-static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
- struct net *net,
- struct sock *sk,
- struct sk_buff *skb,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct net *, struct sock *, struct sk_buff *),
- int thresh)
+static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
+ struct sock *sk, struct sk_buff *skb,
+ struct net_device *indev, struct net_device *outdev,
+ int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
struct nf_hook_entry *hook_head;
int ret = 1;
@@ -185,24 +206,16 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
if (hook_head) {
struct nf_hook_state state;
- nf_hook_state_init(&state, hook_head, hook, thresh,
- pf, indev, outdev, sk, net, okfn);
+ nf_hook_state_init(&state, hook, pf, indev, outdev,
+ sk, net, okfn);
- ret = nf_hook_slow(skb, &state);
+ ret = nf_hook_slow(skb, &state, hook_head);
}
rcu_read_unlock();
return ret;
}
-static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
- struct sock *sk, struct sk_buff *skb,
- struct net_device *indev, struct net_device *outdev,
- int (*okfn)(struct net *, struct sock *, struct sk_buff *))
-{
- return nf_hook_thresh(pf, hook, net, sk, skb, indev, outdev, okfn, INT_MIN);
-}
-
/* Activate hook; either okfn or kfree_skb called, unless a hook
returns NF_STOLEN (in which case, it's up to the hook to deal with
the consequences).
@@ -221,19 +234,6 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
*/
static inline int
-NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
- struct sk_buff *skb, struct net_device *in,
- struct net_device *out,
- int (*okfn)(struct net *, struct sock *, struct sk_buff *),
- int thresh)
-{
- int ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, thresh);
- if (ret == 1)
- ret = okfn(net, sk, skb);
- return ret;
-}
-
-static inline int
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
struct sk_buff *skb, struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *),
@@ -242,7 +242,7 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
int ret;
if (!cond ||
- ((ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, INT_MIN)) == 1))
+ ((ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn)) == 1))
ret = okfn(net, sk, skb);
return ret;
}
@@ -252,7 +252,10 @@ NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct
struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
- return NF_HOOK_THRESH(pf, hook, net, sk, skb, in, out, okfn, INT_MIN);
+ int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn);
+ if (ret == 1)
+ ret = okfn(net, sk, skb);
+ return ret;
}
/* Call setsockopt() */
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 83b9a2e0d8d4..8e42253e5d4d 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -79,10 +79,12 @@ enum ip_set_ext_id {
IPSET_EXT_ID_MAX,
};
+struct ip_set;
+
/* Extension type */
struct ip_set_ext_type {
/* Destroy extension private data (can be NULL) */
- void (*destroy)(void *ext);
+ void (*destroy)(struct ip_set *set, void *ext);
enum ip_set_extension type;
enum ipset_cadt_flags flag;
/* Size and minimal alignment */
@@ -92,17 +94,6 @@ struct ip_set_ext_type {
extern const struct ip_set_ext_type ip_set_extensions[];
-struct ip_set_ext {
- u64 packets;
- u64 bytes;
- u32 timeout;
- u32 skbmark;
- u32 skbmarkmask;
- u32 skbprio;
- u16 skbqueue;
- char *comment;
-};
-
struct ip_set_counter {
atomic64_t bytes;
atomic64_t packets;
@@ -122,6 +113,15 @@ struct ip_set_skbinfo {
u32 skbmarkmask;
u32 skbprio;
u16 skbqueue;
+ u16 __pad;
+};
+
+struct ip_set_ext {
+ struct ip_set_skbinfo skbinfo;
+ u64 packets;
+ u64 bytes;
+ char *comment;
+ u32 timeout;
};
struct ip_set;
@@ -252,6 +252,10 @@ struct ip_set {
u8 flags;
/* Default timeout value, if enabled */
u32 timeout;
+ /* Number of elements (vs timeout) */
+ u32 elements;
+ /* Size of the dynamic extensions (vs timeout) */
+ size_t ext_size;
/* Element data size */
size_t dsize;
/* Offsets to extensions in elements */
@@ -268,7 +272,7 @@ ip_set_ext_destroy(struct ip_set *set, void *data)
*/
if (SET_WITH_COMMENT(set))
ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(
- ext_comment(data, set));
+ set, ext_comment(data, set));
}
static inline int
@@ -294,104 +298,6 @@ ip_set_put_flags(struct sk_buff *skb, struct ip_set *set)
return nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(cadt_flags));
}
-static inline void
-ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
-{
- atomic64_add((long long)bytes, &(counter)->bytes);
-}
-
-static inline void
-ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
-{
- atomic64_add((long long)packets, &(counter)->packets);
-}
-
-static inline u64
-ip_set_get_bytes(const struct ip_set_counter *counter)
-{
- return (u64)atomic64_read(&(counter)->bytes);
-}
-
-static inline u64
-ip_set_get_packets(const struct ip_set_counter *counter)
-{
- return (u64)atomic64_read(&(counter)->packets);
-}
-
-static inline void
-ip_set_update_counter(struct ip_set_counter *counter,
- const struct ip_set_ext *ext,
- struct ip_set_ext *mext, u32 flags)
-{
- if (ext->packets != ULLONG_MAX &&
- !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
- ip_set_add_bytes(ext->bytes, counter);
- ip_set_add_packets(ext->packets, counter);
- }
- if (flags & IPSET_FLAG_MATCH_COUNTERS) {
- mext->packets = ip_set_get_packets(counter);
- mext->bytes = ip_set_get_bytes(counter);
- }
-}
-
-static inline void
-ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo,
- const struct ip_set_ext *ext,
- struct ip_set_ext *mext, u32 flags)
-{
- mext->skbmark = skbinfo->skbmark;
- mext->skbmarkmask = skbinfo->skbmarkmask;
- mext->skbprio = skbinfo->skbprio;
- mext->skbqueue = skbinfo->skbqueue;
-}
-static inline bool
-ip_set_put_skbinfo(struct sk_buff *skb, struct ip_set_skbinfo *skbinfo)
-{
- /* Send nonzero parameters only */
- return ((skbinfo->skbmark || skbinfo->skbmarkmask) &&
- nla_put_net64(skb, IPSET_ATTR_SKBMARK,
- cpu_to_be64((u64)skbinfo->skbmark << 32 |
- skbinfo->skbmarkmask),
- IPSET_ATTR_PAD)) ||
- (skbinfo->skbprio &&
- nla_put_net32(skb, IPSET_ATTR_SKBPRIO,
- cpu_to_be32(skbinfo->skbprio))) ||
- (skbinfo->skbqueue &&
- nla_put_net16(skb, IPSET_ATTR_SKBQUEUE,
- cpu_to_be16(skbinfo->skbqueue)));
-}
-
-static inline void
-ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
- const struct ip_set_ext *ext)
-{
- skbinfo->skbmark = ext->skbmark;
- skbinfo->skbmarkmask = ext->skbmarkmask;
- skbinfo->skbprio = ext->skbprio;
- skbinfo->skbqueue = ext->skbqueue;
-}
-
-static inline bool
-ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter)
-{
- return nla_put_net64(skb, IPSET_ATTR_BYTES,
- cpu_to_be64(ip_set_get_bytes(counter)),
- IPSET_ATTR_PAD) ||
- nla_put_net64(skb, IPSET_ATTR_PACKETS,
- cpu_to_be64(ip_set_get_packets(counter)),
- IPSET_ATTR_PAD);
-}
-
-static inline void
-ip_set_init_counter(struct ip_set_counter *counter,
- const struct ip_set_ext *ext)
-{
- if (ext->bytes != ULLONG_MAX)
- atomic64_set(&(counter)->bytes, (long long)(ext->bytes));
- if (ext->packets != ULLONG_MAX)
- atomic64_set(&(counter)->packets, (long long)(ext->packets));
-}
-
/* Netlink CB args */
enum {
IPSET_CB_NET = 0, /* net namespace */
@@ -431,6 +337,8 @@ extern size_t ip_set_elem_len(struct ip_set *set, struct nlattr *tb[],
size_t len, size_t align);
extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
struct ip_set_ext *ext);
+extern int ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
+ const void *e, bool active);
static inline int
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
@@ -546,10 +454,8 @@ bitmap_bytes(u32 a, u32 b)
#include <linux/netfilter/ipset/ip_set_timeout.h>
#include <linux/netfilter/ipset/ip_set_comment.h>
-
-int
-ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
- const void *e, bool active);
+#include <linux/netfilter/ipset/ip_set_counter.h>
+#include <linux/netfilter/ipset/ip_set_skbinfo.h>
#define IP_SET_INIT_KEXT(skb, opt, set) \
{ .bytes = (skb)->len, .packets = 1, \
diff --git a/include/linux/netfilter/ipset/ip_set_bitmap.h b/include/linux/netfilter/ipset/ip_set_bitmap.h
index 5e4662a71e01..366d6c0ea04f 100644
--- a/include/linux/netfilter/ipset/ip_set_bitmap.h
+++ b/include/linux/netfilter/ipset/ip_set_bitmap.h
@@ -6,8 +6,8 @@
#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
enum {
+ IPSET_ADD_STORE_PLAIN_TIMEOUT = -1,
IPSET_ADD_FAILED = 1,
- IPSET_ADD_STORE_PLAIN_TIMEOUT,
IPSET_ADD_START_STORED_TIMEOUT,
};
diff --git a/include/linux/netfilter/ipset/ip_set_comment.h b/include/linux/netfilter/ipset/ip_set_comment.h
index 8d0248525957..8e2bab1e8e90 100644
--- a/include/linux/netfilter/ipset/ip_set_comment.h
+++ b/include/linux/netfilter/ipset/ip_set_comment.h
@@ -20,13 +20,14 @@ ip_set_comment_uget(struct nlattr *tb)
* The kadt functions don't use the comment extensions in any way.
*/
static inline void
-ip_set_init_comment(struct ip_set_comment *comment,
+ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
const struct ip_set_ext *ext)
{
struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1);
size_t len = ext->comment ? strlen(ext->comment) : 0;
if (unlikely(c)) {
+ set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
}
@@ -34,16 +35,17 @@ ip_set_init_comment(struct ip_set_comment *comment,
return;
if (unlikely(len > IPSET_MAX_COMMENT_SIZE))
len = IPSET_MAX_COMMENT_SIZE;
- c = kzalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
+ c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
if (unlikely(!c))
return;
strlcpy(c->str, ext->comment, len + 1);
+ set->ext_size += sizeof(*c) + strlen(c->str) + 1;
rcu_assign_pointer(comment->c, c);
}
/* Used only when dumping a set, protected by rcu_read_lock_bh() */
static inline int
-ip_set_put_comment(struct sk_buff *skb, struct ip_set_comment *comment)
+ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment)
{
struct ip_set_comment_rcu *c = rcu_dereference_bh(comment->c);
@@ -58,13 +60,14 @@ ip_set_put_comment(struct sk_buff *skb, struct ip_set_comment *comment)
* of the set data anymore.
*/
static inline void
-ip_set_comment_free(struct ip_set_comment *comment)
+ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment)
{
struct ip_set_comment_rcu *c;
c = rcu_dereference_protected(comment->c, 1);
if (unlikely(!c))
return;
+ set->ext_size -= sizeof(*c) + strlen(c->str) + 1;
kfree_rcu(c, rcu);
rcu_assign_pointer(comment->c, NULL);
}
diff --git a/include/linux/netfilter/ipset/ip_set_counter.h b/include/linux/netfilter/ipset/ip_set_counter.h
new file mode 100644
index 000000000000..bb6fba480118
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_counter.h
@@ -0,0 +1,75 @@
+#ifndef _IP_SET_COUNTER_H
+#define _IP_SET_COUNTER_H
+
+/* Copyright (C) 2015 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+
+static inline void
+ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
+{
+ atomic64_add((long long)bytes, &(counter)->bytes);
+}
+
+static inline void
+ip_set_add_packets(u64 packets, struct ip_set_counter *counter)
+{
+ atomic64_add((long long)packets, &(counter)->packets);
+}
+
+static inline u64
+ip_set_get_bytes(const struct ip_set_counter *counter)
+{
+ return (u64)atomic64_read(&(counter)->bytes);
+}
+
+static inline u64
+ip_set_get_packets(const struct ip_set_counter *counter)
+{
+ return (u64)atomic64_read(&(counter)->packets);
+}
+
+static inline void
+ip_set_update_counter(struct ip_set_counter *counter,
+ const struct ip_set_ext *ext,
+ struct ip_set_ext *mext, u32 flags)
+{
+ if (ext->packets != ULLONG_MAX &&
+ !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
+ ip_set_add_bytes(ext->bytes, counter);
+ ip_set_add_packets(ext->packets, counter);
+ }
+ if (flags & IPSET_FLAG_MATCH_COUNTERS) {
+ mext->packets = ip_set_get_packets(counter);
+ mext->bytes = ip_set_get_bytes(counter);
+ }
+}
+
+static inline bool
+ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter)
+{
+ return nla_put_net64(skb, IPSET_ATTR_BYTES,
+ cpu_to_be64(ip_set_get_bytes(counter)),
+ IPSET_ATTR_PAD) ||
+ nla_put_net64(skb, IPSET_ATTR_PACKETS,
+ cpu_to_be64(ip_set_get_packets(counter)),
+ IPSET_ATTR_PAD);
+}
+
+static inline void
+ip_set_init_counter(struct ip_set_counter *counter,
+ const struct ip_set_ext *ext)
+{
+ if (ext->bytes != ULLONG_MAX)
+ atomic64_set(&(counter)->bytes, (long long)(ext->bytes));
+ if (ext->packets != ULLONG_MAX)
+ atomic64_set(&(counter)->packets, (long long)(ext->packets));
+}
+
+#endif /* __KERNEL__ */
+#endif /* _IP_SET_COUNTER_H */
diff --git a/include/linux/netfilter/ipset/ip_set_skbinfo.h b/include/linux/netfilter/ipset/ip_set_skbinfo.h
new file mode 100644
index 000000000000..29d7ef2bc3fa
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_skbinfo.h
@@ -0,0 +1,46 @@
+#ifndef _IP_SET_SKBINFO_H
+#define _IP_SET_SKBINFO_H
+
+/* Copyright (C) 2015 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+
+static inline void
+ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo,
+ const struct ip_set_ext *ext,
+ struct ip_set_ext *mext, u32 flags)
+{
+ mext->skbinfo = *skbinfo;
+}
+
+static inline bool
+ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo)
+{
+ /* Send nonzero parameters only */
+ return ((skbinfo->skbmark || skbinfo->skbmarkmask) &&
+ nla_put_net64(skb, IPSET_ATTR_SKBMARK,
+ cpu_to_be64((u64)skbinfo->skbmark << 32 |
+ skbinfo->skbmarkmask),
+ IPSET_ATTR_PAD)) ||
+ (skbinfo->skbprio &&
+ nla_put_net32(skb, IPSET_ATTR_SKBPRIO,
+ cpu_to_be32(skbinfo->skbprio))) ||
+ (skbinfo->skbqueue &&
+ nla_put_net16(skb, IPSET_ATTR_SKBQUEUE,
+ cpu_to_be16(skbinfo->skbqueue)));
+}
+
+static inline void
+ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
+ const struct ip_set_ext *ext)
+{
+ *skbinfo = ext->skbinfo;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _IP_SET_SKBINFO_H */
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
index 1d6a935c1ac5..bfb3531fd88a 100644
--- a/include/linux/netfilter/ipset/ip_set_timeout.h
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -40,7 +40,7 @@ ip_set_timeout_uget(struct nlattr *tb)
}
static inline bool
-ip_set_timeout_expired(unsigned long *t)
+ip_set_timeout_expired(const unsigned long *t)
{
return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t);
}
@@ -63,7 +63,7 @@ ip_set_timeout_set(unsigned long *timeout, u32 value)
}
static inline u32
-ip_set_timeout_get(unsigned long *timeout)
+ip_set_timeout_get(const unsigned long *timeout)
{
return *timeout == IPSET_ELEM_PERMANENT ? 0 :
jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC;
diff --git a/include/linux/netfilter/nf_conntrack_dccp.h b/include/linux/netfilter/nf_conntrack_dccp.h
index 40dcc82058d1..ff721d7325cf 100644
--- a/include/linux/netfilter/nf_conntrack_dccp.h
+++ b/include/linux/netfilter/nf_conntrack_dccp.h
@@ -25,7 +25,7 @@ enum ct_dccp_roles {
#define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1)
#ifdef __KERNEL__
-#include <net/netfilter/nf_conntrack_tuple.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
struct nf_ct_dccp {
u_int8_t role[IP_CT_DIR_MAX];
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 2ad1a2b289b5..5117e4d2ddfa 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -4,6 +4,7 @@
#include <linux/netdevice.h>
#include <linux/static_key.h>
+#include <linux/netfilter.h>
#include <uapi/linux/netfilter/x_tables.h>
/* Test a struct->invflags and a boolean for inequality */
@@ -17,14 +18,9 @@
* @target: the target extension
* @matchinfo: per-match data
* @targetinfo: per-target data
- * @net network namespace through which the action was invoked
- * @in: input netdevice
- * @out: output netdevice
+ * @state: pointer to hook state this packet came from
* @fragoff: packet is a fragment, this is the data offset
* @thoff: position of transport header relative to skb->data
- * @hook: hook number given packet came from
- * @family: Actual NFPROTO_* through which the function is invoked
- * (helpful when match->family == NFPROTO_UNSPEC)
*
* Fields written to by extensions:
*
@@ -38,15 +34,47 @@ struct xt_action_param {
union {
const void *matchinfo, *targinfo;
};
- struct net *net;
- const struct net_device *in, *out;
+ const struct nf_hook_state *state;
int fragoff;
unsigned int thoff;
- unsigned int hooknum;
- u_int8_t family;
bool hotdrop;
};
+static inline struct net *xt_net(const struct xt_action_param *par)
+{
+ return par->state->net;
+}
+
+static inline struct net_device *xt_in(const struct xt_action_param *par)
+{
+ return par->state->in;
+}
+
+static inline const char *xt_inname(const struct xt_action_param *par)
+{
+ return par->state->in->name;
+}
+
+static inline struct net_device *xt_out(const struct xt_action_param *par)
+{
+ return par->state->out;
+}
+
+static inline const char *xt_outname(const struct xt_action_param *par)
+{
+ return par->state->out->name;
+}
+
+static inline unsigned int xt_hooknum(const struct xt_action_param *par)
+{
+ return par->state->hook;
+}
+
+static inline u_int8_t xt_family(const struct xt_action_param *par)
+{
+ return par->state->pf;
+}
+
/**
* struct xt_mtchk_param - parameters for match extensions'
* checkentry functions
@@ -375,38 +403,14 @@ static inline unsigned long ifname_compare_aligned(const char *_a,
return ret;
}
+struct xt_percpu_counter_alloc_state {
+ unsigned int off;
+ const char __percpu *mem;
+};
-/* On SMP, ip(6)t_entry->counters.pcnt holds address of the
- * real (percpu) counter. On !SMP, its just the packet count,
- * so nothing needs to be done there.
- *
- * xt_percpu_counter_alloc returns the address of the percpu
- * counter, or 0 on !SMP. We force an alignment of 16 bytes
- * so that bytes/packets share a common cache line.
- *
- * Hence caller must use IS_ERR_VALUE to check for error, this
- * allows us to return 0 for single core systems without forcing
- * callers to deal with SMP vs. NONSMP issues.
- */
-static inline unsigned long xt_percpu_counter_alloc(void)
-{
- if (nr_cpu_ids > 1) {
- void __percpu *res = __alloc_percpu(sizeof(struct xt_counters),
- sizeof(struct xt_counters));
-
- if (res == NULL)
- return -ENOMEM;
-
- return (__force unsigned long) res;
- }
-
- return 0;
-}
-static inline void xt_percpu_counter_free(u64 pcnt)
-{
- if (nr_cpu_ids > 1)
- free_percpu((void __percpu *) (unsigned long) pcnt);
-}
+bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state,
+ struct xt_counters *counter);
+void xt_percpu_counter_free(struct xt_counters *cnt);
static inline struct xt_counters *
xt_get_this_cpu_counter(struct xt_counters *cnt)
diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_ingress.h
index 33e37fb41d5d..59476061de86 100644
--- a/include/linux/netfilter_ingress.h
+++ b/include/linux/netfilter_ingress.h
@@ -19,6 +19,7 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
{
struct nf_hook_entry *e = rcu_dereference(skb->dev->nf_hooks_ingress);
struct nf_hook_state state;
+ int ret;
/* Must recheck the ingress hook head, in the event it became NULL
* after the check in nf_hook_ingress_active evaluated to true.
@@ -26,10 +27,14 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
if (unlikely(!e))
return 0;
- nf_hook_state_init(&state, e, NF_NETDEV_INGRESS, INT_MIN,
+ nf_hook_state_init(&state, NF_NETDEV_INGRESS,
NFPROTO_NETDEV, skb->dev, NULL, NULL,
dev_net(skb->dev), NULL);
- return nf_hook_slow(skb, &state);
+ ret = nf_hook_slow(skb, &state, e);
+ if (ret == 0)
+ return -1;
+
+ return ret;
}
static inline void nf_hook_ingress_init(struct net_device *dev)
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index b25ee9ffdbe6..1828900c9411 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -78,8 +78,11 @@ static inline void *netpoll_poll_lock(struct napi_struct *napi)
struct net_device *dev = napi->dev;
if (dev && dev->npinfo) {
- spin_lock(&napi->poll_lock);
- napi->poll_owner = smp_processor_id();
+ int owner = smp_processor_id();
+
+ while (cmpxchg(&napi->poll_owner, -1, owner) != -1)
+ cpu_relax();
+
return napi;
}
return NULL;
@@ -89,10 +92,8 @@ static inline void netpoll_poll_unlock(void *have)
{
struct napi_struct *napi = have;
- if (napi) {
- napi->poll_owner = -1;
- spin_unlock(&napi->poll_lock);
- }
+ if (napi)
+ smp_store_release(&napi->poll_owner, -1);
}
static inline bool netpoll_tx_running(struct net_device *dev)
diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h
new file mode 100644
index 000000000000..f21471f7ee40
--- /dev/null
+++ b/include/linux/nvme-fc-driver.h
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2016, Avago Technologies
+ *
+ * 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_FC_DRIVER_H
+#define _NVME_FC_DRIVER_H 1
+
+
+/*
+ * ********************** LLDD FC-NVME Host API ********************
+ *
+ * For FC LLDD's that are the NVME Host role.
+ *
+ * ******************************************************************
+ */
+
+
+
+/* FC Port role bitmask - can merge with FC Port Roles in fc transport */
+#define FC_PORT_ROLE_NVME_INITIATOR 0x10
+#define FC_PORT_ROLE_NVME_TARGET 0x11
+#define FC_PORT_ROLE_NVME_DISCOVERY 0x12
+
+
+/**
+ * struct nvme_fc_port_info - port-specific ids and FC connection-specific
+ * data element used during NVME Host role
+ * registrations
+ *
+ * Static fields describing the port being registered:
+ * @node_name: FC WWNN for the port
+ * @port_name: FC WWPN for the port
+ * @port_role: What NVME roles are supported (see FC_PORT_ROLE_xxx)
+ *
+ * Initialization values for dynamic port fields:
+ * @port_id: FC N_Port_ID currently assigned the port. Upper 8 bits must
+ * be set to 0.
+ */
+struct nvme_fc_port_info {
+ u64 node_name;
+ u64 port_name;
+ u32 port_role;
+ u32 port_id;
+};
+
+
+/**
+ * struct nvmefc_ls_req - Request structure passed from NVME-FC transport
+ * to LLDD in order to perform a NVME FC-4 LS
+ * request and obtain a response.
+ *
+ * Values set by the NVME-FC layer prior to calling the LLDD ls_req
+ * entrypoint.
+ * @rqstaddr: pointer to request buffer
+ * @rqstdma: PCI DMA address of request buffer
+ * @rqstlen: Length, in bytes, of request buffer
+ * @rspaddr: pointer to response buffer
+ * @rspdma: PCI DMA address of response buffer
+ * @rsplen: Length, in bytes, of response buffer
+ * @timeout: Maximum amount of time, in seconds, to wait for the LS response.
+ * If timeout exceeded, LLDD to abort LS exchange and complete
+ * LS request with error status.
+ * @private: pointer to memory allocated alongside the ls request structure
+ * that is specifically for the LLDD to use while processing the
+ * request. The length of the buffer corresponds to the
+ * lsrqst_priv_sz value specified in the nvme_fc_port_template
+ * supplied by the LLDD.
+ * @done: The callback routine the LLDD is to invoke upon completion of
+ * the LS request. req argument is the pointer to the original LS
+ * request structure. Status argument must be 0 upon success, a
+ * negative errno on failure (example: -ENXIO).
+ */
+struct nvmefc_ls_req {
+ void *rqstaddr;
+ dma_addr_t rqstdma;
+ u32 rqstlen;
+ void *rspaddr;
+ dma_addr_t rspdma;
+ u32 rsplen;
+ u32 timeout;
+
+ void *private;
+
+ void (*done)(struct nvmefc_ls_req *req, int status);
+
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+
+enum nvmefc_fcp_datadir {
+ NVMEFC_FCP_NODATA, /* payload_length and sg_cnt will be zero */
+ NVMEFC_FCP_WRITE,
+ NVMEFC_FCP_READ,
+};
+
+
+#define NVME_FC_MAX_SEGMENTS 256
+
+/**
+ * struct nvmefc_fcp_req - Request structure passed from NVME-FC transport
+ * to LLDD in order to perform a NVME FCP IO operation.
+ *
+ * Values set by the NVME-FC layer prior to calling the LLDD fcp_io
+ * entrypoint.
+ * @cmdaddr: pointer to the FCP CMD IU buffer
+ * @rspaddr: pointer to the FCP RSP IU buffer
+ * @cmddma: PCI DMA address of the FCP CMD IU buffer
+ * @rspdma: PCI DMA address of the FCP RSP IU buffer
+ * @cmdlen: Length, in bytes, of the FCP CMD IU buffer
+ * @rsplen: Length, in bytes, of the FCP RSP IU buffer
+ * @payload_length: Length of DATA_IN or DATA_OUT payload data to transfer
+ * @sg_table: scatter/gather structure for payload data
+ * @first_sgl: memory for 1st scatter/gather list segment for payload data
+ * @sg_cnt: number of elements in the scatter/gather list
+ * @io_dir: direction of the FCP request (see NVMEFC_FCP_xxx)
+ * @sqid: The nvme SQID the command is being issued on
+ * @done: The callback routine the LLDD is to invoke upon completion of
+ * the FCP operation. req argument is the pointer to the original
+ * FCP IO operation.
+ * @private: pointer to memory allocated alongside the FCP operation
+ * request structure that is specifically for the LLDD to use
+ * while processing the operation. The length of the buffer
+ * corresponds to the fcprqst_priv_sz value specified in the
+ * nvme_fc_port_template supplied by the LLDD.
+ *
+ * Values set by the LLDD indicating completion status of the FCP operation.
+ * Must be set prior to calling the done() callback.
+ * @transferred_length: amount of payload data, in bytes, that were
+ * transferred. Should equal payload_length on success.
+ * @rcv_rsplen: length, in bytes, of the FCP RSP IU received.
+ * @status: Completion status of the FCP operation. must be 0 upon success,
+ * NVME_SC_FC_xxx value upon failure. Note: this is NOT a
+ * reflection of the NVME CQE completion status. Only the status
+ * of the FCP operation at the NVME-FC level.
+ */
+struct nvmefc_fcp_req {
+ void *cmdaddr;
+ void *rspaddr;
+ dma_addr_t cmddma;
+ dma_addr_t rspdma;
+ u16 cmdlen;
+ u16 rsplen;
+
+ u32 payload_length;
+ struct sg_table sg_table;
+ struct scatterlist *first_sgl;
+ int sg_cnt;
+ enum nvmefc_fcp_datadir io_dir;
+
+ __le16 sqid;
+
+ void (*done)(struct nvmefc_fcp_req *req);
+
+ void *private;
+
+ u32 transferred_length;
+ u16 rcv_rsplen;
+ u32 status;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+
+/*
+ * Direct copy of fc_port_state enum. For later merging
+ */
+enum nvme_fc_obj_state {
+ FC_OBJSTATE_UNKNOWN,
+ FC_OBJSTATE_NOTPRESENT,
+ FC_OBJSTATE_ONLINE,
+ FC_OBJSTATE_OFFLINE, /* User has taken Port Offline */
+ FC_OBJSTATE_BLOCKED,
+ FC_OBJSTATE_BYPASSED,
+ FC_OBJSTATE_DIAGNOSTICS,
+ FC_OBJSTATE_LINKDOWN,
+ FC_OBJSTATE_ERROR,
+ FC_OBJSTATE_LOOPBACK,
+ FC_OBJSTATE_DELETED,
+};
+
+
+/**
+ * struct nvme_fc_local_port - structure used between NVME-FC transport and
+ * a LLDD to reference a local NVME host port.
+ * Allocated/created by the nvme_fc_register_localport()
+ * transport interface.
+ *
+ * Fields with static values for the port. Initialized by the
+ * port_info struct supplied to the registration call.
+ * @port_num: NVME-FC transport host port number
+ * @port_role: NVME roles are supported on the port (see FC_PORT_ROLE_xxx)
+ * @node_name: FC WWNN for the port
+ * @port_name: FC WWPN for the port
+ * @private: pointer to memory allocated alongside the local port
+ * structure that is specifically for the LLDD to use.
+ * The length of the buffer corresponds to the local_priv_sz
+ * value specified in the nvme_fc_port_template supplied by
+ * the LLDD.
+ *
+ * Fields with dynamic values. Values may change base on link state. LLDD
+ * may reference fields directly to change them. Initialized by the
+ * port_info struct supplied to the registration call.
+ * @port_id: FC N_Port_ID currently assigned the port. Upper 8 bits must
+ * be set to 0.
+ * @port_state: Operational state of the port.
+ */
+struct nvme_fc_local_port {
+ /* static/read-only fields */
+ u32 port_num;
+ u32 port_role;
+ u64 node_name;
+ u64 port_name;
+
+ void *private;
+
+ /* dynamic fields */
+ u32 port_id;
+ enum nvme_fc_obj_state port_state;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+
+/**
+ * struct nvme_fc_remote_port - structure used between NVME-FC transport and
+ * a LLDD to reference a remote NVME subsystem port.
+ * Allocated/created by the nvme_fc_register_remoteport()
+ * transport interface.
+ *
+ * Fields with static values for the port. Initialized by the
+ * port_info struct supplied to the registration call.
+ * @port_num: NVME-FC transport remote subsystem port number
+ * @port_role: NVME roles are supported on the port (see FC_PORT_ROLE_xxx)
+ * @node_name: FC WWNN for the port
+ * @port_name: FC WWPN for the port
+ * @localport: pointer to the NVME-FC local host port the subsystem is
+ * connected to.
+ * @private: pointer to memory allocated alongside the remote port
+ * structure that is specifically for the LLDD to use.
+ * The length of the buffer corresponds to the remote_priv_sz
+ * value specified in the nvme_fc_port_template supplied by
+ * the LLDD.
+ *
+ * Fields with dynamic values. Values may change base on link or login
+ * state. LLDD may reference fields directly to change them. Initialized by
+ * the port_info struct supplied to the registration call.
+ * @port_id: FC N_Port_ID currently assigned the port. Upper 8 bits must
+ * be set to 0.
+ * @port_state: Operational state of the remote port. Valid values are
+ * ONLINE or UNKNOWN.
+ */
+struct nvme_fc_remote_port {
+ /* static fields */
+ u32 port_num;
+ u32 port_role;
+ u64 node_name;
+ u64 port_name;
+
+ struct nvme_fc_local_port *localport;
+
+ void *private;
+
+ /* dynamic fields */
+ u32 port_id;
+ enum nvme_fc_obj_state port_state;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+
+/**
+ * struct nvme_fc_port_template - structure containing static entrypoints and
+ * operational parameters for an LLDD that supports NVME host
+ * behavior. Passed by reference in port registrations.
+ * NVME-FC transport remembers template reference and may
+ * access it during runtime operation.
+ *
+ * Host/Initiator Transport Entrypoints/Parameters:
+ *
+ * @localport_delete: The LLDD initiates deletion of a localport via
+ * nvme_fc_deregister_localport(). However, the teardown is
+ * asynchronous. This routine is called upon the completion of the
+ * teardown to inform the LLDD that the localport has been deleted.
+ * Entrypoint is Mandatory.
+ *
+ * @remoteport_delete: The LLDD initiates deletion of a remoteport via
+ * nvme_fc_deregister_remoteport(). However, the teardown is
+ * asynchronous. This routine is called upon the completion of the
+ * teardown to inform the LLDD that the remoteport has been deleted.
+ * Entrypoint is Mandatory.
+ *
+ * @create_queue: Upon creating a host<->controller association, queues are
+ * created such that they can be affinitized to cpus/cores. This
+ * callback into the LLDD to notify that a controller queue is being
+ * created. The LLDD may choose to allocate an associated hw queue
+ * or map it onto a shared hw queue. Upon return from the call, the
+ * LLDD specifies a handle that will be given back to it for any
+ * command that is posted to the controller queue. The handle can
+ * be used by the LLDD to map quickly to the proper hw queue for
+ * command execution. The mask of cpu's that will map to this queue
+ * at the block-level is also passed in. The LLDD should use the
+ * queue id and/or cpu masks to ensure proper affinitization of the
+ * controller queue to the hw queue.
+ * Entrypoint is Optional.
+ *
+ * @delete_queue: This is the inverse of the crete_queue. During
+ * host<->controller association teardown, this routine is called
+ * when a controller queue is being terminated. Any association with
+ * a hw queue should be termined. If there is a unique hw queue, the
+ * hw queue should be torn down.
+ * Entrypoint is Optional.
+ *
+ * @poll_queue: Called to poll for the completion of an io on a blk queue.
+ * Entrypoint is Optional.
+ *
+ * @ls_req: Called to issue a FC-NVME FC-4 LS service request.
+ * The nvme_fc_ls_req structure will fully describe the buffers for
+ * the request payload and where to place the response payload. The
+ * LLDD is to allocate an exchange, issue the LS request, obtain the
+ * LS response, and call the "done" routine specified in the request
+ * structure (argument to done is the ls request structure itself).
+ * Entrypoint is Mandatory.
+ *
+ * @fcp_io: called to issue a FC-NVME I/O request. The I/O may be for
+ * an admin queue or an i/o queue. The nvmefc_fcp_req structure will
+ * fully describe the io: the buffer containing the FC-NVME CMD IU
+ * (which contains the SQE), the sg list for the payload if applicable,
+ * and the buffer to place the FC-NVME RSP IU into. The LLDD will
+ * complete the i/o, indicating the amount of data transferred or
+ * any transport error, and call the "done" routine specified in the
+ * request structure (argument to done is the fcp request structure
+ * itself).
+ * Entrypoint is Mandatory.
+ *
+ * @ls_abort: called to request the LLDD to abort the indicated ls request.
+ * The call may return before the abort has completed. After aborting
+ * the request, the LLDD must still call the ls request done routine
+ * indicating an FC transport Aborted status.
+ * Entrypoint is Mandatory.
+ *
+ * @fcp_abort: called to request the LLDD to abort the indicated fcp request.
+ * The call may return before the abort has completed. After aborting
+ * the request, the LLDD must still call the fcp request done routine
+ * indicating an FC transport Aborted status.
+ * Entrypoint is Mandatory.
+ *
+ * @max_hw_queues: indicates the maximum number of hw queues the LLDD
+ * supports for cpu affinitization.
+ * Value is Mandatory. Must be at least 1.
+ *
+ * @max_sgl_segments: indicates the maximum number of sgl segments supported
+ * by the LLDD
+ * Value is Mandatory. Must be at least 1. Recommend at least 256.
+ *
+ * @max_dif_sgl_segments: indicates the maximum number of sgl segments
+ * supported by the LLDD for DIF operations.
+ * Value is Mandatory. Must be at least 1. Recommend at least 256.
+ *
+ * @dma_boundary: indicates the dma address boundary where dma mappings
+ * will be split across.
+ * Value is Mandatory. Typical value is 0xFFFFFFFF to split across
+ * 4Gig address boundarys
+ *
+ * @local_priv_sz: The LLDD sets this field to the amount of additional
+ * memory that it would like fc nvme layer to allocate on the LLDD's
+ * behalf whenever a localport is allocated. The additional memory
+ * area solely for the of the LLDD and its location is specified by
+ * the localport->private pointer.
+ * Value is Mandatory. Allowed to be zero.
+ *
+ * @remote_priv_sz: The LLDD sets this field to the amount of additional
+ * memory that it would like fc nvme layer to allocate on the LLDD's
+ * behalf whenever a remoteport is allocated. The additional memory
+ * area solely for the of the LLDD and its location is specified by
+ * the remoteport->private pointer.
+ * Value is Mandatory. Allowed to be zero.
+ *
+ * @lsrqst_priv_sz: The LLDD sets this field to the amount of additional
+ * memory that it would like fc nvme layer to allocate on the LLDD's
+ * behalf whenever a ls request structure is allocated. The additional
+ * memory area solely for the of the LLDD and its location is
+ * specified by the ls_request->private pointer.
+ * Value is Mandatory. Allowed to be zero.
+ *
+ * @fcprqst_priv_sz: The LLDD sets this field to the amount of additional
+ * memory that it would like fc nvme layer to allocate on the LLDD's
+ * behalf whenever a fcp request structure is allocated. The additional
+ * memory area solely for the of the LLDD and its location is
+ * specified by the fcp_request->private pointer.
+ * Value is Mandatory. Allowed to be zero.
+ */
+struct nvme_fc_port_template {
+ /* initiator-based functions */
+ void (*localport_delete)(struct nvme_fc_local_port *);
+ void (*remoteport_delete)(struct nvme_fc_remote_port *);
+ int (*create_queue)(struct nvme_fc_local_port *,
+ unsigned int qidx, u16 qsize,
+ void **handle);
+ void (*delete_queue)(struct nvme_fc_local_port *,
+ unsigned int qidx, void *handle);
+ void (*poll_queue)(struct nvme_fc_local_port *, void *handle);
+ int (*ls_req)(struct nvme_fc_local_port *,
+ struct nvme_fc_remote_port *,
+ struct nvmefc_ls_req *);
+ int (*fcp_io)(struct nvme_fc_local_port *,
+ struct nvme_fc_remote_port *,
+ void *hw_queue_handle,
+ struct nvmefc_fcp_req *);
+ void (*ls_abort)(struct nvme_fc_local_port *,
+ struct nvme_fc_remote_port *,
+ struct nvmefc_ls_req *);
+ void (*fcp_abort)(struct nvme_fc_local_port *,
+ struct nvme_fc_remote_port *,
+ void *hw_queue_handle,
+ struct nvmefc_fcp_req *);
+
+ u32 max_hw_queues;
+ u16 max_sgl_segments;
+ u16 max_dif_sgl_segments;
+ u64 dma_boundary;
+
+ /* sizes of additional private data for data structures */
+ u32 local_priv_sz;
+ u32 remote_priv_sz;
+ u32 lsrqst_priv_sz;
+ u32 fcprqst_priv_sz;
+};
+
+
+/*
+ * Initiator/Host functions
+ */
+
+int nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
+ struct nvme_fc_port_template *template,
+ struct device *dev,
+ struct nvme_fc_local_port **lport_p);
+
+int nvme_fc_unregister_localport(struct nvme_fc_local_port *localport);
+
+int nvme_fc_register_remoteport(struct nvme_fc_local_port *localport,
+ struct nvme_fc_port_info *pinfo,
+ struct nvme_fc_remote_port **rport_p);
+
+int nvme_fc_unregister_remoteport(struct nvme_fc_remote_port *remoteport);
+
+
+
+/*
+ * *************** LLDD FC-NVME Target/Subsystem API ***************
+ *
+ * For FC LLDD's that are the NVME Subsystem role
+ *
+ * ******************************************************************
+ */
+
+/**
+ * struct nvmet_fc_port_info - port-specific ids and FC connection-specific
+ * data element used during NVME Subsystem role
+ * registrations
+ *
+ * Static fields describing the port being registered:
+ * @node_name: FC WWNN for the port
+ * @port_name: FC WWPN for the port
+ *
+ * Initialization values for dynamic port fields:
+ * @port_id: FC N_Port_ID currently assigned the port. Upper 8 bits must
+ * be set to 0.
+ */
+struct nvmet_fc_port_info {
+ u64 node_name;
+ u64 port_name;
+ u32 port_id;
+};
+
+
+/**
+ * struct nvmefc_tgt_ls_req - Structure used between LLDD and NVMET-FC
+ * layer to represent the exchange context for
+ * a FC-NVME Link Service (LS).
+ *
+ * The structure is allocated by the LLDD whenever a LS Request is received
+ * from the FC link. The address of the structure is passed to the nvmet-fc
+ * layer via the nvmet_fc_rcv_ls_req() call. The address of the structure
+ * will be passed back to the LLDD when the response is to be transmit.
+ * The LLDD is to use the address to map back to the LLDD exchange structure
+ * which maintains information such as the targetport the LS was received
+ * on, the remote FC NVME initiator that sent the LS, and any FC exchange
+ * context. Upon completion of the LS response transmit, the address of the
+ * structure will be passed back to the LS rsp done() routine, allowing the
+ * nvmet-fc layer to release dma resources. Upon completion of the done()
+ * routine, no further access will be made by the nvmet-fc layer and the
+ * LLDD can de-allocate the structure.
+ *
+ * Field initialization:
+ * At the time of the nvmet_fc_rcv_ls_req() call, there is no content that
+ * is valid in the structure.
+ *
+ * When the structure is used for the LLDD->xmt_ls_rsp() call, the nvmet-fc
+ * layer will fully set the fields in order to specify the response
+ * payload buffer and its length as well as the done routine to be called
+ * upon compeletion of the transmit. The nvmet-fc layer will also set a
+ * private pointer for its own use in the done routine.
+ *
+ * Values set by the NVMET-FC layer prior to calling the LLDD xmt_ls_rsp
+ * entrypoint.
+ * @rspbuf: pointer to the LS response buffer
+ * @rspdma: PCI DMA address of the LS response buffer
+ * @rsplen: Length, in bytes, of the LS response buffer
+ * @done: The callback routine the LLDD is to invoke upon completion of
+ * transmitting the LS response. req argument is the pointer to
+ * the original ls request.
+ * @nvmet_fc_private: pointer to an internal NVMET-FC layer structure used
+ * as part of the NVMET-FC processing. The LLDD is not to access
+ * this pointer.
+ */
+struct nvmefc_tgt_ls_req {
+ void *rspbuf;
+ dma_addr_t rspdma;
+ u16 rsplen;
+
+ void (*done)(struct nvmefc_tgt_ls_req *req);
+ void *nvmet_fc_private; /* LLDD is not to access !! */
+};
+
+/* Operations that NVME-FC layer may request the LLDD to perform for FCP */
+enum {
+ NVMET_FCOP_READDATA = 1, /* xmt data to initiator */
+ NVMET_FCOP_WRITEDATA = 2, /* xmt data from initiator */
+ NVMET_FCOP_READDATA_RSP = 3, /* xmt data to initiator and send
+ * rsp as well
+ */
+ NVMET_FCOP_RSP = 4, /* send rsp frame */
+ NVMET_FCOP_ABORT = 5, /* abort exchange via ABTS */
+ NVMET_FCOP_BA_ACC = 6, /* send BA_ACC */
+ NVMET_FCOP_BA_RJT = 7, /* send BA_RJT */
+};
+
+/**
+ * struct nvmefc_tgt_fcp_req - Structure used between LLDD and NVMET-FC
+ * layer to represent the exchange context and
+ * the specific FC-NVME IU operation(s) to perform
+ * for a FC-NVME FCP IO.
+ *
+ * Structure used between LLDD and nvmet-fc layer to represent the exchange
+ * context for a FC-NVME FCP I/O operation (e.g. a nvme sqe, the sqe-related
+ * memory transfers, and its assocated cqe transfer).
+ *
+ * The structure is allocated by the LLDD whenever a FCP CMD IU is received
+ * from the FC link. The address of the structure is passed to the nvmet-fc
+ * layer via the nvmet_fc_rcv_fcp_req() call. The address of the structure
+ * will be passed back to the LLDD for the data operations and transmit of
+ * the response. The LLDD is to use the address to map back to the LLDD
+ * exchange structure which maintains information such as the targetport
+ * the FCP I/O was received on, the remote FC NVME initiator that sent the
+ * FCP I/O, and any FC exchange context. Upon completion of the FCP target
+ * operation, the address of the structure will be passed back to the FCP
+ * op done() routine, allowing the nvmet-fc layer to release dma resources.
+ * Upon completion of the done() routine for either RSP or ABORT ops, no
+ * further access will be made by the nvmet-fc layer and the LLDD can
+ * de-allocate the structure.
+ *
+ * Field initialization:
+ * At the time of the nvmet_fc_rcv_fcp_req() call, there is no content that
+ * is valid in the structure.
+ *
+ * When the structure is used for an FCP target operation, the nvmet-fc
+ * layer will fully set the fields in order to specify the scattergather
+ * list, the transfer length, as well as the done routine to be called
+ * upon compeletion of the operation. The nvmet-fc layer will also set a
+ * private pointer for its own use in the done routine.
+ *
+ * Note: the LLDD must never fail a NVMET_FCOP_ABORT request !!
+ *
+ * Values set by the NVMET-FC layer prior to calling the LLDD fcp_op
+ * entrypoint.
+ * @op: Indicates the FCP IU operation to perform (see NVMET_FCOP_xxx)
+ * @hwqid: Specifies the hw queue index (0..N-1, where N is the
+ * max_hw_queues value from the LLD's nvmet_fc_target_template)
+ * that the operation is to use.
+ * @offset: Indicates the DATA_OUT/DATA_IN payload offset to be tranferred.
+ * Field is only valid on WRITEDATA, READDATA, or READDATA_RSP ops.
+ * @timeout: amount of time, in seconds, to wait for a response from the NVME
+ * host. A value of 0 is an infinite wait.
+ * Valid only for the following ops:
+ * WRITEDATA: caps the wait for data reception
+ * READDATA_RSP & RSP: caps wait for FCP_CONF reception (if used)
+ * @transfer_length: the length, in bytes, of the DATA_OUT or DATA_IN payload
+ * that is to be transferred.
+ * Valid only for the WRITEDATA, READDATA, or READDATA_RSP ops.
+ * @ba_rjt: Contains the BA_RJT payload that is to be transferred.
+ * Valid only for the NVMET_FCOP_BA_RJT op.
+ * @sg: Scatter/gather list for the DATA_OUT/DATA_IN payload data.
+ * Valid only for the WRITEDATA, READDATA, or READDATA_RSP ops.
+ * @sg_cnt: Number of valid entries in the scatter/gather list.
+ * Valid only for the WRITEDATA, READDATA, or READDATA_RSP ops.
+ * @rspaddr: pointer to the FCP RSP IU buffer to be transmit
+ * Used by RSP and READDATA_RSP ops
+ * @rspdma: PCI DMA address of the FCP RSP IU buffer
+ * Used by RSP and READDATA_RSP ops
+ * @rsplen: Length, in bytes, of the FCP RSP IU buffer
+ * Used by RSP and READDATA_RSP ops
+ * @done: The callback routine the LLDD is to invoke upon completion of
+ * the operation. req argument is the pointer to the original
+ * FCP subsystem op request.
+ * @nvmet_fc_private: pointer to an internal NVMET-FC layer structure used
+ * as part of the NVMET-FC processing. The LLDD is not to
+ * reference this field.
+ *
+ * Values set by the LLDD indicating completion status of the FCP operation.
+ * Must be set prior to calling the done() callback.
+ * @transferred_length: amount of DATA_OUT payload data received by a
+ * a WRITEDATA operation. If not a WRITEDATA operation, value must
+ * be set to 0. Should equal transfer_length on success.
+ * @fcp_error: status of the FCP operation. Must be 0 on success; on failure
+ * must be a NVME_SC_FC_xxxx value.
+ */
+struct nvmefc_tgt_fcp_req {
+ u8 op;
+ u16 hwqid;
+ u32 offset;
+ u32 timeout;
+ u32 transfer_length;
+ struct fc_ba_rjt ba_rjt;
+ struct scatterlist sg[NVME_FC_MAX_SEGMENTS];
+ int sg_cnt;
+ void *rspaddr;
+ dma_addr_t rspdma;
+ u16 rsplen;
+
+ void (*done)(struct nvmefc_tgt_fcp_req *);
+
+ void *nvmet_fc_private; /* LLDD is not to access !! */
+
+ u32 transferred_length;
+ int fcp_error;
+};
+
+
+/* Target Features (Bit fields) LLDD supports */
+enum {
+ NVMET_FCTGTFEAT_READDATA_RSP = (1 << 0),
+ /* Bit 0: supports the NVMET_FCPOP_READDATA_RSP op, which
+ * sends (the last) Read Data sequence followed by the RSP
+ * sequence in one LLDD operation. Errors during Data
+ * sequence transmit must not allow RSP sequence to be sent.
+ */
+ NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED = (1 << 1),
+ /* Bit 1: When 0, the LLDD will deliver FCP CMD
+ * on the CPU it should be affinitized to. Thus work will
+ * be scheduled on the cpu received on. When 1, the LLDD
+ * may not deliver the CMD on the CPU it should be worked
+ * on. The transport should pick a cpu to schedule the work
+ * on.
+ */
+};
+
+
+/**
+ * struct nvmet_fc_target_port - structure used between NVME-FC transport and
+ * a LLDD to reference a local NVME subsystem port.
+ * Allocated/created by the nvme_fc_register_targetport()
+ * transport interface.
+ *
+ * Fields with static values for the port. Initialized by the
+ * port_info struct supplied to the registration call.
+ * @port_num: NVME-FC transport subsytem port number
+ * @node_name: FC WWNN for the port
+ * @port_name: FC WWPN for the port
+ * @private: pointer to memory allocated alongside the local port
+ * structure that is specifically for the LLDD to use.
+ * The length of the buffer corresponds to the target_priv_sz
+ * value specified in the nvme_fc_target_template supplied by
+ * the LLDD.
+ *
+ * Fields with dynamic values. Values may change base on link state. LLDD
+ * may reference fields directly to change them. Initialized by the
+ * port_info struct supplied to the registration call.
+ * @port_id: FC N_Port_ID currently assigned the port. Upper 8 bits must
+ * be set to 0.
+ * @port_state: Operational state of the port.
+ */
+struct nvmet_fc_target_port {
+ /* static/read-only fields */
+ u32 port_num;
+ u64 node_name;
+ u64 port_name;
+
+ void *private;
+
+ /* dynamic fields */
+ u32 port_id;
+ enum nvme_fc_obj_state port_state;
+} __aligned(sizeof(u64)); /* alignment for other things alloc'd with */
+
+
+/**
+ * struct nvmet_fc_target_template - structure containing static entrypoints
+ * and operational parameters for an LLDD that supports NVME
+ * subsystem behavior. Passed by reference in port
+ * registrations. NVME-FC transport remembers template
+ * reference and may access it during runtime operation.
+ *
+ * Subsystem/Target Transport Entrypoints/Parameters:
+ *
+ * @targetport_delete: The LLDD initiates deletion of a targetport via
+ * nvmet_fc_unregister_targetport(). However, the teardown is
+ * asynchronous. This routine is called upon the completion of the
+ * teardown to inform the LLDD that the targetport has been deleted.
+ * Entrypoint is Mandatory.
+ *
+ * @xmt_ls_rsp: Called to transmit the response to a FC-NVME FC-4 LS service.
+ * The nvmefc_tgt_ls_req structure is the same LLDD-supplied exchange
+ * structure specified in the nvmet_fc_rcv_ls_req() call made when
+ * the LS request was received. The structure will fully describe
+ * the buffers for the response payload and the dma address of the
+ * payload. The LLDD is to transmit the response (or return a non-zero
+ * errno status), and upon completion of the transmit, call the
+ * "done" routine specified in the nvmefc_tgt_ls_req structure
+ * (argument to done is the ls reqwuest structure itself).
+ * After calling the done routine, the LLDD shall consider the
+ * LS handling complete and the nvmefc_tgt_ls_req structure may
+ * be freed/released.
+ * Entrypoint is Mandatory.
+ *
+ * @fcp_op: Called to perform a data transfer, transmit a response, or
+ * abort an FCP opertion. The nvmefc_tgt_fcp_req structure is the same
+ * LLDD-supplied exchange structure specified in the
+ * nvmet_fc_rcv_fcp_req() call made when the FCP CMD IU was received.
+ * The op field in the structure shall indicate the operation for
+ * the LLDD to perform relative to the io.
+ * NVMET_FCOP_READDATA operation: the LLDD is to send the
+ * payload data (described by sglist) to the host in 1 or
+ * more FC sequences (preferrably 1). Note: the fc-nvme layer
+ * may call the READDATA operation multiple times for longer
+ * payloads.
+ * NVMET_FCOP_WRITEDATA operation: the LLDD is to receive the
+ * payload data (described by sglist) from the host via 1 or
+ * more FC sequences (preferrably 1). The LLDD is to generate
+ * the XFER_RDY IU(s) corresponding to the data being requested.
+ * Note: the FC-NVME layer may call the WRITEDATA operation
+ * multiple times for longer payloads.
+ * NVMET_FCOP_READDATA_RSP operation: the LLDD is to send the
+ * payload data (described by sglist) to the host in 1 or
+ * more FC sequences (preferrably 1). If an error occurs during
+ * payload data transmission, the LLDD is to set the
+ * nvmefc_tgt_fcp_req fcp_error and transferred_length field, then
+ * consider the operation complete. On error, the LLDD is to not
+ * transmit the FCP_RSP iu. If all payload data is transferred
+ * successfully, the LLDD is to update the nvmefc_tgt_fcp_req
+ * transferred_length field and may subsequently transmit the
+ * FCP_RSP iu payload (described by rspbuf, rspdma, rsplen).
+ * The LLDD is to await FCP_CONF reception to confirm the RSP
+ * reception by the host. The LLDD may retramsit the FCP_RSP iu
+ * if necessary per FC-NVME. Upon reception of FCP_CONF, or upon
+ * FCP_CONF failure, the LLDD is to set the nvmefc_tgt_fcp_req
+ * fcp_error field and consider the operation complete..
+ * NVMET_FCOP_RSP: the LLDD is to transmit the FCP_RSP iu payload
+ * (described by rspbuf, rspdma, rsplen). The LLDD is to await
+ * FCP_CONF reception to confirm the RSP reception by the host.
+ * The LLDD may retramsit the FCP_RSP iu if necessary per FC-NVME.
+ * Upon reception of FCP_CONF, or upon FCP_CONF failure, the
+ * LLDD is to set the nvmefc_tgt_fcp_req fcp_error field and
+ * consider the operation complete..
+ * NVMET_FCOP_ABORT: the LLDD is to terminate the exchange
+ * corresponding to the fcp operation. The LLDD shall send
+ * ABTS and follow FC exchange abort-multi rules, including
+ * ABTS retries and possible logout.
+ * Upon completing the indicated operation, the LLDD is to set the
+ * status fields for the operation (tranferred_length and fcp_error
+ * status) in the request, then all the "done" routine
+ * indicated in the fcp request. Upon return from the "done"
+ * routine for either a NVMET_FCOP_RSP or NVMET_FCOP_ABORT operation
+ * the fc-nvme layer will not longer reference the fcp request,
+ * allowing the LLDD to free/release the fcp request.
+ * Note: when calling the done routine for READDATA or WRITEDATA
+ * operations, the fc-nvme layer may immediate convert, in the same
+ * thread and before returning to the LLDD, the fcp operation to
+ * the next operation for the fcp io and call the LLDDs fcp_op
+ * call again. If fields in the fcp request are to be accessed post
+ * the done call, the LLDD should save their values prior to calling
+ * the done routine, and inspect the save values after the done
+ * routine.
+ * Returns 0 on success, -<errno> on failure (Ex: -EIO)
+ * Entrypoint is Mandatory.
+ *
+ * @max_hw_queues: indicates the maximum number of hw queues the LLDD
+ * supports for cpu affinitization.
+ * Value is Mandatory. Must be at least 1.
+ *
+ * @max_sgl_segments: indicates the maximum number of sgl segments supported
+ * by the LLDD
+ * Value is Mandatory. Must be at least 1. Recommend at least 256.
+ *
+ * @max_dif_sgl_segments: indicates the maximum number of sgl segments
+ * supported by the LLDD for DIF operations.
+ * Value is Mandatory. Must be at least 1. Recommend at least 256.
+ *
+ * @dma_boundary: indicates the dma address boundary where dma mappings
+ * will be split across.
+ * Value is Mandatory. Typical value is 0xFFFFFFFF to split across
+ * 4Gig address boundarys
+ *
+ * @target_features: The LLDD sets bits in this field to correspond to
+ * optional features that are supported by the LLDD.
+ * Refer to the NVMET_FCTGTFEAT_xxx values.
+ * Value is Mandatory. Allowed to be zero.
+ *
+ * @target_priv_sz: The LLDD sets this field to the amount of additional
+ * memory that it would like fc nvme layer to allocate on the LLDD's
+ * behalf whenever a targetport is allocated. The additional memory
+ * area solely for the of the LLDD and its location is specified by
+ * the targetport->private pointer.
+ * Value is Mandatory. Allowed to be zero.
+ */
+struct nvmet_fc_target_template {
+ void (*targetport_delete)(struct nvmet_fc_target_port *tgtport);
+ int (*xmt_ls_rsp)(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_tgt_ls_req *tls_req);
+ int (*fcp_op)(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_tgt_fcp_req *);
+
+ u32 max_hw_queues;
+ u16 max_sgl_segments;
+ u16 max_dif_sgl_segments;
+ u64 dma_boundary;
+
+ u32 target_features;
+
+ u32 target_priv_sz;
+};
+
+
+int nvmet_fc_register_targetport(struct nvmet_fc_port_info *portinfo,
+ struct nvmet_fc_target_template *template,
+ struct device *dev,
+ struct nvmet_fc_target_port **tgtport_p);
+
+int nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *tgtport);
+
+int nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_tgt_ls_req *lsreq,
+ void *lsreqbuf, u32 lsreqbuf_len);
+
+int nvmet_fc_rcv_fcp_req(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_tgt_fcp_req *fcpreq,
+ void *cmdiubuf, u32 cmdiubuf_len);
+
+#endif /* _NVME_FC_DRIVER_H */
diff --git a/include/linux/nvme-fc.h b/include/linux/nvme-fc.h
new file mode 100644
index 000000000000..4b45226bd604
--- /dev/null
+++ b/include/linux/nvme-fc.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2016 Avago Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO
+ * THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
+ * See the GNU General Public License for more details, a copy of which
+ * can be found in the file COPYING included with this package
+ *
+ */
+
+/*
+ * This file contains definitions relative to FC-NVME r1.11 and a few
+ * newer items
+ */
+
+#ifndef _NVME_FC_H
+#define _NVME_FC_H 1
+
+
+#define NVME_CMD_SCSI_ID 0xFD
+#define NVME_CMD_FC_ID FC_TYPE_NVME
+
+/* FC-NVME Cmd IU Flags */
+#define FCNVME_CMD_FLAGS_DIRMASK 0x03
+#define FCNVME_CMD_FLAGS_WRITE 0x01
+#define FCNVME_CMD_FLAGS_READ 0x02
+
+struct nvme_fc_cmd_iu {
+ __u8 scsi_id;
+ __u8 fc_id;
+ __be16 iu_len;
+ __u8 rsvd4[3];
+ __u8 flags;
+ __be64 connection_id;
+ __be32 csn;
+ __be32 data_len;
+ struct nvme_command sqe;
+ __be32 rsvd88[2];
+};
+
+#define NVME_FC_SIZEOF_ZEROS_RSP 12
+
+struct nvme_fc_ersp_iu {
+ __u8 rsvd0[2];
+ __be16 iu_len;
+ __be32 rsn;
+ __be32 xfrd_len;
+ __be32 rsvd12;
+ struct nvme_completion cqe;
+ /* for now - no additional payload */
+};
+
+
+/* FC-NVME r1.03/16-119v0 NVME Link Services */
+enum {
+ FCNVME_LS_RSVD = 0,
+ FCNVME_LS_RJT = 1,
+ FCNVME_LS_ACC = 2,
+ FCNVME_LS_CREATE_ASSOCIATION = 3,
+ FCNVME_LS_CREATE_CONNECTION = 4,
+ FCNVME_LS_DISCONNECT = 5,
+};
+
+/* FC-NVME r1.03/16-119v0 NVME Link Service Descriptors */
+enum {
+ FCNVME_LSDESC_RSVD = 0x0,
+ FCNVME_LSDESC_RQST = 0x1,
+ FCNVME_LSDESC_RJT = 0x2,
+ FCNVME_LSDESC_CREATE_ASSOC_CMD = 0x3,
+ FCNVME_LSDESC_CREATE_CONN_CMD = 0x4,
+ FCNVME_LSDESC_DISCONN_CMD = 0x5,
+ FCNVME_LSDESC_CONN_ID = 0x6,
+ FCNVME_LSDESC_ASSOC_ID = 0x7,
+};
+
+
+/* ********** start of Link Service Descriptors ********** */
+
+
+/*
+ * fills in length of a descriptor. Struture minus descriptor header
+ */
+static inline __be32 fcnvme_lsdesc_len(size_t sz)
+{
+ return cpu_to_be32(sz - (2 * sizeof(u32)));
+}
+
+
+struct fcnvme_ls_rqst_w0 {
+ u8 ls_cmd; /* FCNVME_LS_xxx */
+ u8 zeros[3];
+};
+
+/* FCNVME_LSDESC_RQST */
+struct fcnvme_lsdesc_rqst {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 rsvd12;
+};
+
+
+
+
+/* FCNVME_LSDESC_RJT */
+struct fcnvme_lsdesc_rjt {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ u8 rsvd8;
+
+ /*
+ * Reject reason and explanaction codes are generic
+ * to ELs's from LS-3.
+ */
+ u8 reason_code;
+ u8 reason_explanation;
+
+ u8 vendor;
+ __be32 rsvd12;
+};
+
+
+#define FCNVME_ASSOC_HOSTID_LEN 64
+#define FCNVME_ASSOC_HOSTNQN_LEN 256
+#define FCNVME_ASSOC_SUBNQN_LEN 256
+
+/* FCNVME_LSDESC_CREATE_ASSOC_CMD */
+struct fcnvme_lsdesc_cr_assoc_cmd {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ __be16 ersp_ratio;
+ __be16 rsvd10;
+ __be32 rsvd12[9];
+ __be16 cntlid;
+ __be16 sqsize;
+ __be32 rsvd52;
+ u8 hostid[FCNVME_ASSOC_HOSTID_LEN];
+ u8 hostnqn[FCNVME_ASSOC_HOSTNQN_LEN];
+ u8 subnqn[FCNVME_ASSOC_SUBNQN_LEN];
+ u8 rsvd632[384];
+};
+
+/* FCNVME_LSDESC_CREATE_CONN_CMD */
+struct fcnvme_lsdesc_cr_conn_cmd {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ __be16 ersp_ratio;
+ __be16 rsvd10;
+ __be32 rsvd12[9];
+ __be16 qid;
+ __be16 sqsize;
+ __be32 rsvd52;
+};
+
+/* Disconnect Scope Values */
+enum {
+ FCNVME_DISCONN_ASSOCIATION = 0,
+ FCNVME_DISCONN_CONNECTION = 1,
+};
+
+/* FCNVME_LSDESC_DISCONN_CMD */
+struct fcnvme_lsdesc_disconn_cmd {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ u8 rsvd8[3];
+ /* note: scope is really a 1 bit field */
+ u8 scope; /* FCNVME_DISCONN_xxx */
+ __be32 rsvd12;
+ __be64 id;
+};
+
+/* FCNVME_LSDESC_CONN_ID */
+struct fcnvme_lsdesc_conn_id {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ __be64 connection_id;
+};
+
+/* FCNVME_LSDESC_ASSOC_ID */
+struct fcnvme_lsdesc_assoc_id {
+ __be32 desc_tag; /* FCNVME_LSDESC_xxx */
+ __be32 desc_len;
+ __be64 association_id;
+};
+
+/* r_ctl values */
+enum {
+ FCNVME_RS_RCTL_DATA = 1,
+ FCNVME_RS_RCTL_XFER_RDY = 5,
+ FCNVME_RS_RCTL_RSP = 8,
+};
+
+
+/* ********** start of Link Services ********** */
+
+
+/* FCNVME_LS_RJT */
+struct fcnvme_ls_rjt {
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 desc_list_len;
+ struct fcnvme_lsdesc_rqst rqst;
+ struct fcnvme_lsdesc_rjt rjt;
+};
+
+/* FCNVME_LS_ACC */
+struct fcnvme_ls_acc_hdr {
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 desc_list_len;
+ struct fcnvme_lsdesc_rqst rqst;
+ /* Followed by cmd-specific ACC descriptors, see next definitions */
+};
+
+/* FCNVME_LS_CREATE_ASSOCIATION */
+struct fcnvme_ls_cr_assoc_rqst {
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 desc_list_len;
+ struct fcnvme_lsdesc_cr_assoc_cmd assoc_cmd;
+};
+
+struct fcnvme_ls_cr_assoc_acc {
+ struct fcnvme_ls_acc_hdr hdr;
+ struct fcnvme_lsdesc_assoc_id associd;
+ struct fcnvme_lsdesc_conn_id connectid;
+};
+
+
+/* FCNVME_LS_CREATE_CONNECTION */
+struct fcnvme_ls_cr_conn_rqst {
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 desc_list_len;
+ struct fcnvme_lsdesc_assoc_id associd;
+ struct fcnvme_lsdesc_cr_conn_cmd connect_cmd;
+};
+
+struct fcnvme_ls_cr_conn_acc {
+ struct fcnvme_ls_acc_hdr hdr;
+ struct fcnvme_lsdesc_conn_id connectid;
+};
+
+/* FCNVME_LS_DISCONNECT */
+struct fcnvme_ls_disconnect_rqst {
+ struct fcnvme_ls_rqst_w0 w0;
+ __be32 desc_list_len;
+ struct fcnvme_lsdesc_assoc_id associd;
+ struct fcnvme_lsdesc_disconn_cmd discon_cmd;
+};
+
+struct fcnvme_ls_disconnect_acc {
+ struct fcnvme_ls_acc_hdr hdr;
+};
+
+
+/*
+ * Yet to be defined in FC-NVME:
+ */
+#define NVME_FC_CONNECT_TIMEOUT_SEC 2 /* 2 seconds */
+#define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */
+#define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */
+
+
+#endif /* _NVME_FC_H */
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index fc3c24206593..3d1c6f1b15c9 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -242,6 +242,7 @@ enum {
NVME_CTRL_ONCS_COMPARE = 1 << 0,
NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1,
NVME_CTRL_ONCS_DSM = 1 << 2,
+ NVME_CTRL_ONCS_WRITE_ZEROES = 1 << 3,
NVME_CTRL_VWC_PRESENT = 1 << 0,
};
@@ -558,6 +559,23 @@ struct nvme_dsm_range {
__le64 slba;
};
+struct nvme_write_zeroes_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u64 rsvd2;
+ __le64 metadata;
+ union nvme_data_ptr dptr;
+ __le64 slba;
+ __le16 length;
+ __le16 control;
+ __le32 dsmgmt;
+ __le32 reftag;
+ __le16 apptag;
+ __le16 appmask;
+};
+
/* Admin commands */
enum nvme_admin_opcode {
@@ -857,6 +875,7 @@ struct nvme_command {
struct nvme_download_firmware dlfw;
struct nvme_format_cmd format;
struct nvme_dsm_cmd dsm;
+ struct nvme_write_zeroes_cmd write_zeroes;
struct nvme_abort_cmd abort;
struct nvme_get_log_page_command get_log_page;
struct nvmf_common_command fabrics;
@@ -947,6 +966,7 @@ enum {
NVME_SC_BAD_ATTRIBUTES = 0x180,
NVME_SC_INVALID_PI = 0x181,
NVME_SC_READ_ONLY = 0x182,
+ NVME_SC_ONCS_NOT_SUPPORTED = 0x183,
/*
* I/O Command Set Specific - Fabrics commands:
@@ -973,17 +993,30 @@ enum {
NVME_SC_UNWRITTEN_BLOCK = 0x287,
NVME_SC_DNR = 0x4000,
+
+
+ /*
+ * FC Transport-specific error status values for NVME commands
+ *
+ * Transport-specific status code values must be in the range 0xB0..0xBF
+ */
+
+ /* Generic FC failure - catchall */
+ NVME_SC_FC_TRANSPORT_ERROR = 0x00B0,
+
+ /* I/O failure due to FC ABTS'd */
+ NVME_SC_FC_TRANSPORT_ABORTED = 0x00B1,
};
struct nvme_completion {
/*
* Used by Admin and Fabrics commands to return data:
*/
- union {
- __le16 result16;
- __le32 result;
- __le64 result64;
- };
+ union nvme_result {
+ __le16 u16;
+ __le32 u32;
+ __le64 u64;
+ } result;
__le16 sq_head; /* how much of this queue may be reclaimed */
__le16 sq_id; /* submission queue that generated this entry */
__u16 command_id; /* of the command which completed */
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 4341f32516d8..271b3fdf0070 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -71,6 +71,7 @@ extern int early_init_dt_scan_chosen_stdout(void);
extern void early_init_fdt_scan_reserved_mem(void);
extern void early_init_fdt_reserve_self(void);
extern void early_init_dt_add_memory_arch(u64 base, u64 size);
+extern int early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size);
extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
bool no_map);
extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
diff --git a/include/linux/parser.h b/include/linux/parser.h
index 39d5b7955b23..884c1e6eb3fe 100644
--- a/include/linux/parser.h
+++ b/include/linux/parser.h
@@ -27,6 +27,7 @@ typedef struct {
int match_token(char *, const match_table_t table, substring_t args[]);
int match_int(substring_t *, int *result);
+int match_u64(substring_t *, u64 *result);
int match_octal(substring_t *, int *result);
int match_hex(substring_t *, int *result);
bool match_wildcard(const char *pattern, const char *str);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a38772a85588..30d6c162e053 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -244,6 +244,7 @@ struct pci_cap_saved_state {
struct pci_cap_saved_data cap;
};
+struct irq_affinity;
struct pcie_link_state;
struct pci_vpd;
struct pci_sriov;
@@ -332,7 +333,6 @@ struct pci_dev {
* directly, use the values stored here. They might be different!
*/
unsigned int irq;
- struct cpumask *irq_affinity;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
bool match_driver; /* Skip attaching driver */
@@ -1310,8 +1310,10 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
return rc;
return 0;
}
-int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
- unsigned int max_vecs, unsigned int flags);
+int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
+ unsigned int max_vecs, unsigned int flags,
+ const struct irq_affinity *affd);
+
void pci_free_irq_vectors(struct pci_dev *dev);
int pci_irq_vector(struct pci_dev *dev, unsigned int nr);
const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec);
@@ -1339,14 +1341,17 @@ static inline int pci_enable_msix_range(struct pci_dev *dev,
static inline int pci_enable_msix_exact(struct pci_dev *dev,
struct msix_entry *entries, int nvec)
{ return -ENOSYS; }
-static inline int pci_alloc_irq_vectors(struct pci_dev *dev,
- unsigned int min_vecs, unsigned int max_vecs,
- unsigned int flags)
+
+static inline int
+pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
+ unsigned int max_vecs, unsigned int flags,
+ const struct irq_affinity *aff_desc)
{
if (min_vecs > 1)
return -EINVAL;
return 1;
}
+
static inline void pci_free_irq_vectors(struct pci_dev *dev)
{
}
@@ -1364,6 +1369,14 @@ static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev,
}
#endif
+static inline int
+pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
+ unsigned int max_vecs, unsigned int flags)
+{
+ return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
+ NULL);
+}
+
#ifdef CONFIG_PCIEPORTBUS
extern bool pcie_ports_disabled;
extern bool pcie_ports_auto;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e25f1830fbcf..f7d95f644eed 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -25,6 +25,7 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/mod_devicetable.h>
+#include <linux/phy_led_triggers.h>
#include <linux/atomic.h>
@@ -85,6 +86,21 @@ typedef enum {
} phy_interface_t;
/**
+ * phy_supported_speeds - return all speeds currently supported by a phy device
+ * @phy: The phy device to return supported speeds of.
+ * @speeds: buffer to store supported speeds in.
+ * @size: size of speeds buffer.
+ *
+ * Description: Returns the number of supported speeds, and
+ * fills the speeds * buffer with the supported speeds. If speeds buffer is
+ * too small to contain * all currently supported speeds, will return as
+ * many speeds as can fit.
+ */
+unsigned int phy_supported_speeds(struct phy_device *phy,
+ unsigned int *speeds,
+ unsigned int size);
+
+/**
* It maps 'enum phy_interface_t' found in include/linux/phy.h
* into the device tree binding of 'phy-mode', so that Ethernet
* device driver can get phy interface from device tree.
@@ -343,7 +359,7 @@ struct phy_c45_device_ids {
* giving up on the current attempt at acquiring a link
* irq: IRQ number of the PHY's interrupt (-1 if none)
* phy_timer: The timer for handling the state machine
- * phy_queue: A work_queue for the interrupt
+ * phy_queue: A work_queue for the phy_mac_interrupt
* attached_dev: The attached enet driver's device instance ptr
* adjust_link: Callback for the enet controller to respond to
* changes in the link state.
@@ -401,10 +417,19 @@ struct phy_device {
u32 advertising;
u32 lp_advertising;
+ /* Energy efficient ethernet modes which should be prohibited */
+ u32 eee_broken_modes;
+
int autoneg;
int link_timeout;
+#ifdef CONFIG_LED_TRIGGER_PHY
+ struct phy_led_trigger *phy_led_triggers;
+ unsigned int phy_num_led_triggers;
+ struct phy_led_trigger *last_triggered;
+#endif
+
/*
* Interrupt number for this PHY
* -1 means no interrupt
@@ -425,6 +450,7 @@ struct phy_device {
struct net_device *attached_dev;
u8 mdix;
+ u8 mdix_ctrl;
void (*adjust_link)(struct net_device *dev);
};
@@ -589,6 +615,13 @@ struct phy_driver {
void (*get_strings)(struct phy_device *dev, u8 *data);
void (*get_stats)(struct phy_device *dev,
struct ethtool_stats *stats, u64 *data);
+
+ /* Get and Set PHY tunables */
+ int (*get_tunable)(struct phy_device *dev,
+ struct ethtool_tunable *tuna, void *data);
+ int (*set_tunable)(struct phy_device *dev,
+ struct ethtool_tunable *tuna,
+ const void *data);
};
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
@@ -764,6 +797,7 @@ void phy_detach(struct phy_device *phydev);
void phy_start(struct phy_device *phydev);
void phy_stop(struct phy_device *phydev);
int phy_start_aneg(struct phy_device *phydev);
+int phy_aneg_done(struct phy_device *phydev);
int phy_stop_interrupts(struct phy_device *phydev);
@@ -802,7 +836,8 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner);
int phy_drivers_register(struct phy_driver *new_driver, int n,
struct module *owner);
void phy_state_machine(struct work_struct *work);
-void phy_change(struct work_struct *work);
+void phy_change(struct phy_device *phydev);
+void phy_change_work(struct work_struct *work);
void phy_mac_interrupt(struct phy_device *phydev, int new_link);
void phy_start_machine(struct phy_device *phydev);
void phy_stop_machine(struct phy_device *phydev);
@@ -825,6 +860,10 @@ int phy_register_fixup_for_id(const char *bus_id,
int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
+int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask);
+int phy_unregister_fixup_for_id(const char *bus_id);
+int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
+
int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
int phy_get_eee_err(struct phy_device *phydev);
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
@@ -836,6 +875,7 @@ int phy_ethtool_get_link_ksettings(struct net_device *ndev,
struct ethtool_link_ksettings *cmd);
int phy_ethtool_set_link_ksettings(struct net_device *ndev,
const struct ethtool_link_ksettings *cmd);
+int phy_ethtool_nway_reset(struct net_device *ndev);
int __init mdio_bus_init(void);
void mdio_bus_exit(void);
diff --git a/include/linux/phy_led_triggers.h b/include/linux/phy_led_triggers.h
new file mode 100644
index 000000000000..a2daea0a37d2
--- /dev/null
+++ b/include/linux/phy_led_triggers.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2016 National Instruments Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PHY_LED_TRIGGERS
+#define __PHY_LED_TRIGGERS
+
+struct phy_device;
+
+#ifdef CONFIG_LED_TRIGGER_PHY
+
+#include <linux/leds.h>
+
+#define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE 10
+#define PHY_MII_BUS_ID_SIZE (20 - 3)
+
+#define PHY_LINK_LED_TRIGGER_NAME_SIZE (PHY_MII_BUS_ID_SIZE + \
+ FIELD_SIZEOF(struct mdio_device, addr)+\
+ PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE)
+
+struct phy_led_trigger {
+ struct led_trigger trigger;
+ char name[PHY_LINK_LED_TRIGGER_NAME_SIZE];
+ unsigned int speed;
+};
+
+
+extern int phy_led_triggers_register(struct phy_device *phy);
+extern void phy_led_triggers_unregister(struct phy_device *phy);
+extern void phy_led_trigger_change_speed(struct phy_device *phy);
+
+#else
+
+static inline int phy_led_triggers_register(struct phy_device *phy)
+{
+ return 0;
+}
+static inline void phy_led_triggers_unregister(struct phy_device *phy) { }
+static inline void phy_led_trigger_change_speed(struct phy_device *phy) { }
+
+#endif
+
+#endif
diff --git a/include/linux/pim.h b/include/linux/pim.h
index e1d756f81348..0e81b2778ae0 100644
--- a/include/linux/pim.h
+++ b/include/linux/pim.h
@@ -1,6 +1,7 @@
#ifndef __LINUX_PIM_H
#define __LINUX_PIM_H
+#include <linux/skbuff.h>
#include <asm/byteorder.h>
/* Message types - V1 */
@@ -9,24 +10,86 @@
/* Message types - V2 */
#define PIM_VERSION 2
-#define PIM_REGISTER 1
+
+/* RFC7761, sec 4.9:
+ * Type
+ * Types for specific PIM messages. PIM Types are:
+ *
+ * Message Type Destination
+ * ---------------------------------------------------------------------
+ * 0 = Hello Multicast to ALL-PIM-ROUTERS
+ * 1 = Register Unicast to RP
+ * 2 = Register-Stop Unicast to source of Register
+ * packet
+ * 3 = Join/Prune Multicast to ALL-PIM-ROUTERS
+ * 4 = Bootstrap Multicast to ALL-PIM-ROUTERS
+ * 5 = Assert Multicast to ALL-PIM-ROUTERS
+ * 6 = Graft (used in PIM-DM only) Unicast to RPF'(S)
+ * 7 = Graft-Ack (used in PIM-DM only) Unicast to source of Graft
+ * packet
+ * 8 = Candidate-RP-Advertisement Unicast to Domain's BSR
+ */
+enum {
+ PIM_TYPE_HELLO,
+ PIM_TYPE_REGISTER,
+ PIM_TYPE_REGISTER_STOP,
+ PIM_TYPE_JOIN_PRUNE,
+ PIM_TYPE_BOOTSTRAP,
+ PIM_TYPE_ASSERT,
+ PIM_TYPE_GRAFT,
+ PIM_TYPE_GRAFT_ACK,
+ PIM_TYPE_CANDIDATE_RP_ADV
+};
#define PIM_NULL_REGISTER cpu_to_be32(0x40000000)
-static inline bool ipmr_pimsm_enabled(void)
-{
- return IS_BUILTIN(CONFIG_IP_PIMSM_V1) || IS_BUILTIN(CONFIG_IP_PIMSM_V2);
-}
+/* RFC7761, sec 4.9:
+ * The PIM header common to all PIM messages is:
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |PIM Ver| Type | Reserved | Checksum |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct pimhdr {
+ __u8 type;
+ __u8 reserved;
+ __be16 csum;
+};
/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
-struct pimreghdr
-{
+struct pimreghdr {
__u8 type;
__u8 reserved;
__be16 csum;
__be32 flags;
};
-struct sk_buff;
-extern int pim_rcv_v1(struct sk_buff *);
+int pim_rcv_v1(struct sk_buff *skb);
+
+static inline bool ipmr_pimsm_enabled(void)
+{
+ return IS_BUILTIN(CONFIG_IP_PIMSM_V1) || IS_BUILTIN(CONFIG_IP_PIMSM_V2);
+}
+
+static inline struct pimhdr *pim_hdr(const struct sk_buff *skb)
+{
+ return (struct pimhdr *)skb_transport_header(skb);
+}
+
+static inline u8 pim_hdr_version(const struct pimhdr *pimhdr)
+{
+ return pimhdr->type >> 4;
+}
+
+static inline u8 pim_hdr_type(const struct pimhdr *pimhdr)
+{
+ return pimhdr->type & 0xf;
+}
+
+/* check if the address is 224.0.0.13, RFC7761 sec 4.3.1 */
+static inline bool pim_ipv4_all_pim_routers(__be32 addr)
+{
+ return addr == htonl(0xE000000D);
+}
#endif
diff --git a/include/linux/pm-trace.h b/include/linux/pm-trace.h
index ecbde7a5548e..7b78793f07d7 100644
--- a/include/linux/pm-trace.h
+++ b/include/linux/pm-trace.h
@@ -1,11 +1,17 @@
#ifndef PM_TRACE_H
#define PM_TRACE_H
+#include <linux/types.h>
#ifdef CONFIG_PM_TRACE
#include <asm/pm-trace.h>
-#include <linux/types.h>
extern int pm_trace_enabled;
+extern bool pm_trace_rtc_abused;
+
+static inline bool pm_trace_rtc_valid(void)
+{
+ return !pm_trace_rtc_abused;
+}
static inline int pm_trace_is_enabled(void)
{
@@ -24,6 +30,7 @@ extern int show_trace_dev_match(char *buf, size_t size);
#else
+static inline bool pm_trace_rtc_valid(void) { return true; }
static inline int pm_trace_is_enabled(void) { return 0; }
#define TRACE_DEVICE(dev) do { } while (0)
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 06eb353182ab..efa67b2dfee9 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -258,7 +258,7 @@ typedef struct pm_message {
* example, if it detects that a child was unplugged while the system was
* asleep).
*
- * Refer to Documentation/power/devices.txt for more information about the role
+ * Refer to Documentation/power/admin-guide/devices.rst for more information about the role
* of the above callbacks in the system suspend process.
*
* There also are callbacks related to runtime power management of devices.
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index a09fe5c009c8..81ece61075df 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -15,11 +15,11 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/notifier.h>
+#include <linux/spinlock.h>
/* Defines used for the flags field in the struct generic_pm_domain */
#define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */
-
-#define GENPD_MAX_NUM_STATES 8 /* Number of possible low power states */
+#define GENPD_FLAG_IRQ_SAFE (1U << 1) /* PM domain operates in atomic */
enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */
@@ -40,15 +40,18 @@ struct gpd_dev_ops {
struct genpd_power_state {
s64 power_off_latency_ns;
s64 power_on_latency_ns;
+ s64 residency_ns;
+ struct fwnode_handle *fwnode;
};
+struct genpd_lock_ops;
+
struct generic_pm_domain {
struct dev_pm_domain domain; /* PM domain operations */
struct list_head gpd_list_node; /* Node in the global PM domains list */
struct list_head master_links; /* Links with PM domain as a master */
struct list_head slave_links; /* Links with PM domain as a slave */
struct list_head dev_list; /* List of devices */
- struct mutex lock;
struct dev_power_governor *gov;
struct work_struct power_off_work;
struct fwnode_handle *provider; /* Identity of the domain provider */
@@ -70,9 +73,18 @@ struct generic_pm_domain {
void (*detach_dev)(struct generic_pm_domain *domain,
struct device *dev);
unsigned int flags; /* Bit field of configs for genpd */
- struct genpd_power_state states[GENPD_MAX_NUM_STATES];
+ struct genpd_power_state *states;
unsigned int state_count; /* number of states */
unsigned int state_idx; /* state that genpd will go to when off */
+ void *free; /* Free the state that was allocated for default */
+ const struct genpd_lock_ops *lock_ops;
+ union {
+ struct mutex mlock;
+ struct {
+ spinlock_t slock;
+ unsigned long lock_flags;
+ };
+ };
};
@@ -205,6 +217,8 @@ extern int of_genpd_add_device(struct of_phandle_args *args,
extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
struct of_phandle_args *new_subdomain);
extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
+extern int of_genpd_parse_idle_states(struct device_node *dn,
+ struct genpd_power_state **states, int *n);
int genpd_dev_pm_attach(struct device *dev);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -234,6 +248,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
return -ENODEV;
}
+static inline int of_genpd_parse_idle_states(struct device_node *dn,
+ struct genpd_power_state **states, int *n)
+{
+ return -ENODEV;
+}
+
static inline int genpd_dev_pm_attach(struct device *dev)
{
return -ENODEV;
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bca26157f5b6..0edd88f93904 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -17,13 +17,65 @@
#include <linux/err.h>
#include <linux/notifier.h>
+struct clk;
+struct regulator;
struct dev_pm_opp;
struct device;
+struct opp_table;
enum dev_pm_opp_event {
OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
};
+/**
+ * struct dev_pm_opp_supply - Power supply voltage/current values
+ * @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
+ *
+ * This structure stores the voltage/current values for a single power supply.
+ */
+struct dev_pm_opp_supply {
+ unsigned long u_volt;
+ unsigned long u_volt_min;
+ unsigned long u_volt_max;
+ unsigned long u_amp;
+};
+
+/**
+ * struct dev_pm_opp_info - OPP freq/voltage/current values
+ * @rate: Target clk rate in hz
+ * @supplies: Array of voltage/current values for all power supplies
+ *
+ * This structure stores the freq/voltage/current values for a single OPP.
+ */
+struct dev_pm_opp_info {
+ unsigned long rate;
+ struct dev_pm_opp_supply *supplies;
+};
+
+/**
+ * struct dev_pm_set_opp_data - Set OPP data
+ * @old_opp: Old OPP info
+ * @new_opp: New OPP info
+ * @regulators: Array of regulator pointers
+ * @regulator_count: Number of regulators
+ * @clk: Pointer to clk
+ * @dev: Pointer to the struct device
+ *
+ * This structure contains all information required for setting an OPP.
+ */
+struct dev_pm_set_opp_data {
+ struct dev_pm_opp_info old_opp;
+ struct dev_pm_opp_info new_opp;
+
+ struct regulator **regulators;
+ unsigned int regulator_count;
+ struct clk *clk;
+ struct device *dev;
+};
+
#if defined(CONFIG_PM_OPP)
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
@@ -62,8 +114,10 @@ int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
void dev_pm_opp_put_supported_hw(struct device *dev);
int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
void dev_pm_opp_put_prop_name(struct device *dev);
-int dev_pm_opp_set_regulator(struct device *dev, const char *name);
-void dev_pm_opp_put_regulator(struct device *dev);
+struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
+void dev_pm_opp_put_regulators(struct opp_table *opp_table);
+int dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
+void dev_pm_opp_register_put_opp_helper(struct device *dev);
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);
int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
@@ -163,6 +217,14 @@ static inline int dev_pm_opp_set_supported_hw(struct device *dev,
static inline void dev_pm_opp_put_supported_hw(struct device *dev) {}
+static inline int dev_pm_opp_register_set_opp_helper(struct device *dev,
+ int (*set_opp)(struct dev_pm_set_opp_data *data))
+{
+ return -ENOTSUPP;
+}
+
+static inline void dev_pm_opp_register_put_opp_helper(struct device *dev) {}
+
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
{
return -ENOTSUPP;
@@ -170,12 +232,12 @@ static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
-static inline int dev_pm_opp_set_regulator(struct device *dev, const char *name)
+static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count)
{
- return -ENOTSUPP;
+ return ERR_PTR(-ENOTSUPP);
}
-static inline void dev_pm_opp_put_regulator(struct device *dev) {}
+static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {}
static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 2e14d2667b6c..4957fc185ea9 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -61,12 +61,6 @@ static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
dev->power.ignore_children = enable;
}
-static inline bool pm_children_suspended(struct device *dev)
-{
- return dev->power.ignore_children
- || !atomic_read(&dev->power.child_count);
-}
-
static inline void pm_runtime_get_noresume(struct device *dev)
{
atomic_inc(&dev->power.usage_count);
@@ -162,7 +156,6 @@ static inline void pm_runtime_allow(struct device *dev) {}
static inline void pm_runtime_forbid(struct device *dev) {}
static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {}
-static inline bool pm_children_suspended(struct device *dev) { return false; }
static inline void pm_runtime_get_noresume(struct device *dev) {}
static inline void pm_runtime_put_noidle(struct device *dev) {}
static inline bool device_run_wake(struct device *dev) { return false; }
@@ -265,9 +258,9 @@ static inline int pm_runtime_set_active(struct device *dev)
return __pm_runtime_set_status(dev, RPM_ACTIVE);
}
-static inline void pm_runtime_set_suspended(struct device *dev)
+static inline int pm_runtime_set_suspended(struct device *dev)
{
- __pm_runtime_set_status(dev, RPM_SUSPENDED);
+ return __pm_runtime_set_status(dev, RPM_SUSPENDED);
}
static inline void pm_runtime_disable(struct device *dev)
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 75e4e30677f1..7eeceac52dea 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -65,19 +65,24 @@
/*
* Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- * in_softirq - Are we currently processing softirq or have bh disabled?
- * in_serving_softirq - Are we currently processing softirq?
+ *
+ * in_irq() - We're in (hard) IRQ context
+ * in_softirq() - We have BH disabled, or are processing softirqs
+ * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled
+ * in_serving_softirq() - We're in softirq context
+ * in_nmi() - We're in NMI context
+ * in_task() - We're in task context
+ *
+ * Note: due to the BH disabled confusion: in_softirq(),in_interrupt() really
+ * should not be used in new code.
*/
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
-
-/*
- * Are we in NMI context?
- */
-#define in_nmi() (preempt_count() & NMI_MASK)
+#define in_nmi() (preempt_count() & NMI_MASK)
+#define in_task() (!(preempt_count() & \
+ (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
/*
* The preempt_count offset after preempt_disable();
diff --git a/include/linux/printk.h b/include/linux/printk.h
index eac1af8502bb..3472cc6b7a60 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -10,6 +10,8 @@
extern const char linux_banner[];
extern const char linux_proc_banner[];
+#define PRINTK_MAX_SINGLE_HEADER_LEN 2
+
static inline int printk_get_level(const char *buffer)
{
if (buffer[0] == KERN_SOH_ASCII && buffer[1]) {
@@ -31,6 +33,14 @@ static inline const char *printk_skip_level(const char *buffer)
return buffer;
}
+static inline const char *printk_skip_headers(const char *buffer)
+{
+ while (printk_get_level(buffer))
+ buffer = printk_skip_level(buffer);
+
+ return buffer;
+}
+
#define CONSOLE_EXT_LOG_MAX 8192
/* printk's without a loglevel use this.. */
@@ -40,10 +50,15 @@ static inline const char *printk_skip_level(const char *buffer)
#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */
#define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */
-#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */
+/*
+ * Default used to be hard-coded at 7, we're now allowing it to be set from
+ * kernel config.
+ */
+#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
+
extern int console_printk[];
#define console_loglevel (console_printk[0])
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index b97bf2ef996e..368c7ad06ae5 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -82,4 +82,8 @@ static inline struct proc_dir_entry *proc_net_mkdir(
return proc_mkdir_data(name, 0, parent, net);
}
+struct ns_common;
+int open_related_ns(struct ns_common *ns,
+ struct ns_common *(*get_ns)(struct ns_common *ns));
+
#endif /* _LINUX_PROC_FS_H */
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 92013cc9cc8c..0da29cae009b 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -89,4 +89,80 @@ extern int pstore_register(struct pstore_info *);
extern void pstore_unregister(struct pstore_info *);
extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
+struct pstore_ftrace_record {
+ unsigned long ip;
+ unsigned long parent_ip;
+ u64 ts;
+};
+
+/*
+ * ftrace related stuff: Both backends and frontends need these so expose
+ * them here.
+ */
+
+#if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB)
+#define PSTORE_CPU_IN_IP 0x1
+#elif NR_CPUS <= 4 && defined(CONFIG_ARM)
+#define PSTORE_CPU_IN_IP 0x3
+#endif
+
+#define TS_CPU_SHIFT 8
+#define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1)
+
+/*
+ * If CPU number can be stored in IP, store it there, otherwise store it in
+ * the time stamp. This means more timestamp resolution is available when
+ * the CPU can be stored in the IP.
+ */
+#ifdef PSTORE_CPU_IN_IP
+static inline void
+pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
+{
+ rec->ip |= cpu;
+}
+
+static inline unsigned int
+pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
+{
+ return rec->ip & PSTORE_CPU_IN_IP;
+}
+
+static inline u64
+pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec)
+{
+ return rec->ts;
+}
+
+static inline void
+pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val)
+{
+ rec->ts = val;
+}
+#else
+static inline void
+pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
+{
+ rec->ts &= ~(TS_CPU_MASK);
+ rec->ts |= cpu;
+}
+
+static inline unsigned int
+pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
+{
+ return rec->ts & TS_CPU_MASK;
+}
+
+static inline u64
+pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec)
+{
+ return rec->ts >> TS_CPU_SHIFT;
+}
+
+static inline void
+pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val)
+{
+ rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT);
+}
+#endif
+
#endif /*_LINUX_PSTORE_H*/
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index c668c861c96c..9395f06e8372 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -24,6 +24,13 @@
#include <linux/list.h>
#include <linux/types.h>
+/*
+ * Choose whether access to the RAM zone requires locking or not. If a zone
+ * can be written to from different CPUs like with ftrace for example, then
+ * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
+ */
+#define PRZ_FLAG_NO_LOCK BIT(0)
+
struct persistent_ram_buffer;
struct rs_control;
@@ -40,6 +47,8 @@ struct persistent_ram_zone {
void *vaddr;
struct persistent_ram_buffer *buffer;
size_t buffer_size;
+ u32 flags;
+ raw_spinlock_t buffer_lock;
/* ECC correction */
char *par_buffer;
@@ -55,7 +64,7 @@ struct persistent_ram_zone {
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
- unsigned int memtype);
+ unsigned int memtype, u32 flags);
void persistent_ram_free(struct persistent_ram_zone *prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
@@ -77,6 +86,8 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
* @mem_address physical memory address to contain ramoops
*/
+#define RAMOOPS_FLAG_FTRACE_PER_CPU BIT(0)
+
struct ramoops_platform_data {
unsigned long mem_size;
phys_addr_t mem_address;
@@ -86,6 +97,7 @@ struct ramoops_platform_data {
unsigned long ftrace_size;
unsigned long pmsg_size;
int dump_oops;
+ u32 flags;
struct persistent_ram_ecc_info ecc_info;
};
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 5ad54fc66cf0..a026bfd089db 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -58,7 +58,14 @@ struct system_device_crosststamp;
*
* clock operations
*
+ * @adjfine: Adjusts the frequency of the hardware clock.
+ * parameter scaled_ppm: Desired frequency offset from
+ * nominal frequency in parts per million, but with a
+ * 16 bit binary fractional field.
+ *
* @adjfreq: Adjusts the frequency of the hardware clock.
+ * This method is deprecated. New drivers should implement
+ * the @adjfine method instead.
* parameter delta: Desired frequency offset from nominal frequency
* in parts per billion
*
@@ -108,6 +115,7 @@ struct ptp_clock_info {
int n_pins;
int pps;
struct ptp_pin_desc *pin_config;
+ int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
@@ -122,30 +130,6 @@ struct ptp_clock_info {
struct ptp_clock;
-/**
- * ptp_clock_register() - register a PTP hardware clock driver
- *
- * @info: Structure describing the new clock.
- * @parent: Pointer to the parent device of the new clock.
- *
- * Returns a valid pointer on success or PTR_ERR on failure. If PHC
- * support is missing at the configuration level, this function
- * returns NULL, and drivers are expected to gracefully handle that
- * case separately.
- */
-
-extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
- struct device *parent);
-
-/**
- * ptp_clock_unregister() - unregister a PTP hardware clock driver
- *
- * @ptp: The clock to remove from service.
- */
-
-extern int ptp_clock_unregister(struct ptp_clock *ptp);
-
-
enum ptp_clock_events {
PTP_CLOCK_ALARM,
PTP_CLOCK_EXTTS,
@@ -171,6 +155,31 @@ struct ptp_clock_event {
};
};
+#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+
+/**
+ * ptp_clock_register() - register a PTP hardware clock driver
+ *
+ * @info: Structure describing the new clock.
+ * @parent: Pointer to the parent device of the new clock.
+ *
+ * Returns a valid pointer on success or PTR_ERR on failure. If PHC
+ * support is missing at the configuration level, this function
+ * returns NULL, and drivers are expected to gracefully handle that
+ * case separately.
+ */
+
+extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
+ struct device *parent);
+
+/**
+ * ptp_clock_unregister() - unregister a PTP hardware clock driver
+ *
+ * @ptp: The clock to remove from service.
+ */
+
+extern int ptp_clock_unregister(struct ptp_clock *ptp);
+
/**
* ptp_clock_event() - notify the PTP layer about an event
*
@@ -202,4 +211,20 @@ extern int ptp_clock_index(struct ptp_clock *ptp);
int ptp_find_pin(struct ptp_clock *ptp,
enum ptp_pin_function func, unsigned int chan);
+#else
+static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
+ struct device *parent)
+{ return NULL; }
+static inline int ptp_clock_unregister(struct ptp_clock *ptp)
+{ return 0; }
+static inline void ptp_clock_event(struct ptp_clock *ptp,
+ struct ptp_clock_event *event)
+{ }
+static inline int ptp_clock_index(struct ptp_clock *ptp)
+{ return -1; }
+static inline int ptp_find_pin(struct ptp_clock *ptp,
+ enum ptp_pin_function func, unsigned int chan)
+{ return -1; }
+#endif
+
#endif
diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h
index 72d88cf3ca25..37dfba101c6c 100644
--- a/include/linux/qed/qed_chain.h
+++ b/include/linux/qed/qed_chain.h
@@ -56,23 +56,6 @@ struct qed_chain_pbl_u32 {
u32 cons_page_idx;
};
-struct qed_chain_pbl {
- /* Base address of a pre-allocated buffer for pbl */
- dma_addr_t p_phys_table;
- void *p_virt_table;
-
- /* Table for keeping the virtual addresses of the chain pages,
- * respectively to the physical addresses in the pbl table.
- */
- void **pp_virt_addr_tbl;
-
- /* Index to current used page by producer/consumer */
- union {
- struct qed_chain_pbl_u16 pbl16;
- struct qed_chain_pbl_u32 pbl32;
- } u;
-};
-
struct qed_chain_u16 {
/* Cyclic index of next element to produce/consme */
u16 prod_idx;
@@ -86,46 +69,78 @@ struct qed_chain_u32 {
};
struct qed_chain {
- void *p_virt_addr;
- dma_addr_t p_phys_addr;
- void *p_prod_elem;
- void *p_cons_elem;
+ /* fastpath portion of the chain - required for commands such
+ * as produce / consume.
+ */
+ /* Point to next element to produce/consume */
+ void *p_prod_elem;
+ void *p_cons_elem;
+
+ /* Fastpath portions of the PBL [if exists] */
+ struct {
+ /* Table for keeping the virtual addresses of the chain pages,
+ * respectively to the physical addresses in the pbl table.
+ */
+ void **pp_virt_addr_tbl;
- enum qed_chain_mode mode;
- enum qed_chain_use_mode intended_use; /* used to produce/consume */
- enum qed_chain_cnt_type cnt_type;
+ union {
+ struct qed_chain_pbl_u16 u16;
+ struct qed_chain_pbl_u32 u32;
+ } c;
+ } pbl;
union {
struct qed_chain_u16 chain16;
struct qed_chain_u32 chain32;
} u;
+ /* Capacity counts only usable elements */
+ u32 capacity;
u32 page_cnt;
- /* Number of elements - capacity is for usable elements only,
- * while size will contain total number of elements [for entire chain].
+ enum qed_chain_mode mode;
+
+ /* Elements information for fast calculations */
+ u16 elem_per_page;
+ u16 elem_per_page_mask;
+ u16 elem_size;
+ u16 next_page_mask;
+ u16 usable_per_page;
+ u8 elem_unusable;
+
+ u8 cnt_type;
+
+ /* Slowpath of the chain - required for initialization and destruction,
+ * but isn't involved in regular functionality.
*/
- u32 capacity;
+
+ /* Base address of a pre-allocated buffer for pbl */
+ struct {
+ dma_addr_t p_phys_table;
+ void *p_virt_table;
+ } pbl_sp;
+
+ /* Address of first page of the chain - the address is required
+ * for fastpath operation [consume/produce] but only for the the SINGLE
+ * flavour which isn't considered fastpath [== SPQ].
+ */
+ void *p_virt_addr;
+ dma_addr_t p_phys_addr;
+
+ /* Total number of elements [for entire chain] */
u32 size;
- /* Elements information for fast calculations */
- u16 elem_per_page;
- u16 elem_per_page_mask;
- u16 elem_unusable;
- u16 usable_per_page;
- u16 elem_size;
- u16 next_page_mask;
- struct qed_chain_pbl pbl;
+ u8 intended_use;
};
#define QED_CHAIN_PBL_ENTRY_SIZE (8)
#define QED_CHAIN_PAGE_SIZE (0x1000)
#define ELEMS_PER_PAGE(elem_size) (QED_CHAIN_PAGE_SIZE / (elem_size))
-#define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode) \
- ((mode == QED_CHAIN_MODE_NEXT_PTR) ? \
- (1 + ((sizeof(struct qed_chain_next) - 1) / \
- (elem_size))) : 0)
+#define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode) \
+ (((mode) == QED_CHAIN_MODE_NEXT_PTR) ? \
+ (u8)(1 + ((sizeof(struct qed_chain_next) - 1) / \
+ (elem_size))) : 0)
#define USABLE_ELEMS_PER_PAGE(elem_size, mode) \
((u32)(ELEMS_PER_PAGE(elem_size) - \
@@ -186,7 +201,7 @@ static inline u16 qed_chain_get_usable_per_page(struct qed_chain *p_chain)
return p_chain->usable_per_page;
}
-static inline u16 qed_chain_get_unusable_per_page(struct qed_chain *p_chain)
+static inline u8 qed_chain_get_unusable_per_page(struct qed_chain *p_chain)
{
return p_chain->elem_unusable;
}
@@ -198,7 +213,7 @@ static inline u32 qed_chain_get_page_cnt(struct qed_chain *p_chain)
static inline dma_addr_t qed_chain_get_pbl_phys(struct qed_chain *p_chain)
{
- return p_chain->pbl.p_phys_table;
+ return p_chain->pbl_sp.p_phys_table;
}
/**
@@ -214,10 +229,10 @@ static inline dma_addr_t qed_chain_get_pbl_phys(struct qed_chain *p_chain)
static inline void
qed_chain_advance_page(struct qed_chain *p_chain,
void **p_next_elem, void *idx_to_inc, void *page_to_inc)
-
{
struct qed_chain_next *p_next = NULL;
u32 page_index = 0;
+
switch (p_chain->mode) {
case QED_CHAIN_MODE_NEXT_PTR:
p_next = *p_next_elem;
@@ -305,7 +320,7 @@ static inline void *qed_chain_produce(struct qed_chain *p_chain)
if ((p_chain->u.chain16.prod_idx &
p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
p_prod_idx = &p_chain->u.chain16.prod_idx;
- p_prod_page_idx = &p_chain->pbl.u.pbl16.prod_page_idx;
+ p_prod_page_idx = &p_chain->pbl.c.u16.prod_page_idx;
qed_chain_advance_page(p_chain, &p_chain->p_prod_elem,
p_prod_idx, p_prod_page_idx);
}
@@ -314,7 +329,7 @@ static inline void *qed_chain_produce(struct qed_chain *p_chain)
if ((p_chain->u.chain32.prod_idx &
p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
p_prod_idx = &p_chain->u.chain32.prod_idx;
- p_prod_page_idx = &p_chain->pbl.u.pbl32.prod_page_idx;
+ p_prod_page_idx = &p_chain->pbl.c.u32.prod_page_idx;
qed_chain_advance_page(p_chain, &p_chain->p_prod_elem,
p_prod_idx, p_prod_page_idx);
}
@@ -378,7 +393,7 @@ static inline void *qed_chain_consume(struct qed_chain *p_chain)
if ((p_chain->u.chain16.cons_idx &
p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
p_cons_idx = &p_chain->u.chain16.cons_idx;
- p_cons_page_idx = &p_chain->pbl.u.pbl16.cons_page_idx;
+ p_cons_page_idx = &p_chain->pbl.c.u16.cons_page_idx;
qed_chain_advance_page(p_chain, &p_chain->p_cons_elem,
p_cons_idx, p_cons_page_idx);
}
@@ -387,8 +402,8 @@ static inline void *qed_chain_consume(struct qed_chain *p_chain)
if ((p_chain->u.chain32.cons_idx &
p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
p_cons_idx = &p_chain->u.chain32.cons_idx;
- p_cons_page_idx = &p_chain->pbl.u.pbl32.cons_page_idx;
- qed_chain_advance_page(p_chain, &p_chain->p_cons_elem,
+ p_cons_page_idx = &p_chain->pbl.c.u32.cons_page_idx;
+ qed_chain_advance_page(p_chain, &p_chain->p_cons_elem,
p_cons_idx, p_cons_page_idx);
}
p_chain->u.chain32.cons_idx++;
@@ -429,25 +444,26 @@ static inline void qed_chain_reset(struct qed_chain *p_chain)
u32 reset_val = p_chain->page_cnt - 1;
if (is_chain_u16(p_chain)) {
- p_chain->pbl.u.pbl16.prod_page_idx = (u16)reset_val;
- p_chain->pbl.u.pbl16.cons_page_idx = (u16)reset_val;
+ p_chain->pbl.c.u16.prod_page_idx = (u16)reset_val;
+ p_chain->pbl.c.u16.cons_page_idx = (u16)reset_val;
} else {
- p_chain->pbl.u.pbl32.prod_page_idx = reset_val;
- p_chain->pbl.u.pbl32.cons_page_idx = reset_val;
+ p_chain->pbl.c.u32.prod_page_idx = reset_val;
+ p_chain->pbl.c.u32.cons_page_idx = reset_val;
}
}
switch (p_chain->intended_use) {
- case QED_CHAIN_USE_TO_CONSUME_PRODUCE:
- case QED_CHAIN_USE_TO_PRODUCE:
- /* Do nothing */
- break;
-
case QED_CHAIN_USE_TO_CONSUME:
/* produce empty elements */
for (i = 0; i < p_chain->capacity; i++)
qed_chain_recycle_consumed(p_chain);
break;
+
+ case QED_CHAIN_USE_TO_CONSUME_PRODUCE:
+ case QED_CHAIN_USE_TO_PRODUCE:
+ default:
+ /* Do nothing */
+ break;
}
}
@@ -473,13 +489,13 @@ static inline void qed_chain_init_params(struct qed_chain *p_chain,
p_chain->p_virt_addr = NULL;
p_chain->p_phys_addr = 0;
p_chain->elem_size = elem_size;
- p_chain->intended_use = intended_use;
+ p_chain->intended_use = (u8)intended_use;
p_chain->mode = mode;
- p_chain->cnt_type = cnt_type;
+ p_chain->cnt_type = (u8)cnt_type;
- p_chain->elem_per_page = ELEMS_PER_PAGE(elem_size);
+ p_chain->elem_per_page = ELEMS_PER_PAGE(elem_size);
p_chain->usable_per_page = USABLE_ELEMS_PER_PAGE(elem_size, mode);
- p_chain->elem_per_page_mask = p_chain->elem_per_page - 1;
+ p_chain->elem_per_page_mask = p_chain->elem_per_page - 1;
p_chain->elem_unusable = UNUSABLE_ELEMS_PER_PAGE(elem_size, mode);
p_chain->next_page_mask = (p_chain->usable_per_page &
p_chain->elem_per_page_mask);
@@ -488,8 +504,8 @@ static inline void qed_chain_init_params(struct qed_chain *p_chain,
p_chain->capacity = p_chain->usable_per_page * page_cnt;
p_chain->size = p_chain->elem_per_page * page_cnt;
- p_chain->pbl.p_phys_table = 0;
- p_chain->pbl.p_virt_table = NULL;
+ p_chain->pbl_sp.p_phys_table = 0;
+ p_chain->pbl_sp.p_virt_table = NULL;
p_chain->pbl.pp_virt_addr_tbl = NULL;
}
@@ -530,8 +546,8 @@ static inline void qed_chain_init_pbl_mem(struct qed_chain *p_chain,
dma_addr_t p_phys_pbl,
void **pp_virt_addr_tbl)
{
- p_chain->pbl.p_phys_table = p_phys_pbl;
- p_chain->pbl.p_virt_table = p_virt_pbl;
+ p_chain->pbl_sp.p_phys_table = p_phys_pbl;
+ p_chain->pbl_sp.p_virt_table = p_virt_pbl;
p_chain->pbl.pp_virt_addr_tbl = pp_virt_addr_tbl;
}
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index 33c24ebc9b7f..7a52f7c58c37 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -15,6 +15,29 @@
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_iov_if.h>
+struct qed_queue_start_common_params {
+ /* Should always be relative to entity sending this. */
+ u8 vport_id;
+ u16 queue_id;
+
+ /* Relative, but relevant only for PFs */
+ u8 stats_id;
+
+ /* These are always absolute */
+ u16 sb;
+ u8 sb_idx;
+};
+
+struct qed_rxq_start_ret_params {
+ void __iomem *p_prod;
+ void *p_handle;
+};
+
+struct qed_txq_start_ret_params {
+ void __iomem *p_doorbell;
+ void *p_handle;
+};
+
struct qed_dev_eth_info {
struct qed_dev_info common;
@@ -22,7 +45,8 @@ struct qed_dev_eth_info {
u8 num_tc;
u8 port_mac[ETH_ALEN];
- u8 num_vlan_filters;
+ u16 num_vlan_filters;
+ u16 num_mac_filters;
/* Legacy VF - this affects the datapath, so qede has to know */
bool is_legacy;
@@ -55,18 +79,6 @@ struct qed_start_vport_params {
bool clear_stats;
};
-struct qed_stop_rxq_params {
- u8 rss_id;
- u8 rx_queue_id;
- u8 vport_id;
- bool eq_completion_only;
-};
-
-struct qed_stop_txq_params {
- u8 rss_id;
- u8 tx_queue_id;
-};
-
enum qed_filter_rx_mode_type {
QED_FILTER_RX_MODE_TYPE_REGULAR,
QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC,
@@ -111,15 +123,6 @@ struct qed_filter_params {
union qed_filter_type_params filter;
};
-struct qed_queue_start_common_params {
- u8 rss_id;
- u8 queue_id;
- u8 vport_id;
- u16 sb;
- u16 sb_idx;
- u16 vf_qid;
-};
-
struct qed_tunn_params {
u16 vxlan_port;
u8 update_vxlan_port;
@@ -129,7 +132,7 @@ struct qed_tunn_params {
struct qed_eth_cb_ops {
struct qed_common_cb_ops common;
- void (*force_mac) (void *dev, u8 *mac);
+ void (*force_mac) (void *dev, u8 *mac, bool forced);
};
#ifdef CONFIG_DCB
@@ -219,24 +222,24 @@ struct qed_eth_ops {
struct qed_update_vport_params *params);
int (*q_rx_start)(struct qed_dev *cdev,
+ u8 rss_num,
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_rxq_start_ret_params *ret_params);
- int (*q_rx_stop)(struct qed_dev *cdev,
- struct qed_stop_rxq_params *params);
+ int (*q_rx_stop)(struct qed_dev *cdev, u8 rss_id, void *handle);
int (*q_tx_start)(struct qed_dev *cdev,
+ u8 rss_num,
struct qed_queue_start_common_params *params,
dma_addr_t pbl_addr,
u16 pbl_size,
- void __iomem **pp_doorbell);
+ struct qed_txq_start_ret_params *ret_params);
- int (*q_tx_stop)(struct qed_dev *cdev,
- struct qed_stop_txq_params *params);
+ int (*q_tx_stop)(struct qed_dev *cdev, u8 rss_id, void *handle);
int (*filter_config)(struct qed_dev *cdev,
struct qed_filter_params *params);
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 8978a60371f4..4b454f4f5b25 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -166,6 +166,7 @@ struct qed_iscsi_pf_params {
u32 max_cwnd;
u16 cq_num_entries;
u16 cmdq_num_entries;
+ u32 two_msl_timer;
u16 dup_ack_threshold;
u16 tx_sws_timer;
u16 min_rto;
@@ -267,11 +268,15 @@ struct qed_dev_info {
u8 mf_mode;
bool tx_switching;
bool rdma_supported;
+ u16 mtu;
+
+ bool wol_support;
};
enum qed_sb_type {
QED_SB_TYPE_L2_QUEUE,
QED_SB_TYPE_CNQ,
+ QED_SB_TYPE_STORAGE,
};
enum qed_protocol {
@@ -401,6 +406,15 @@ struct qed_selftest_ops {
* @return 0 on success, error otherwise.
*/
int (*selftest_clock)(struct qed_dev *cdev);
+
+/**
+ * @brief selftest_nvram - Perform nvram test
+ *
+ * @param cdev
+ *
+ * @return 0 on success, error otherwise.
+ */
+ int (*selftest_nvram) (struct qed_dev *cdev);
};
struct qed_common_ops {
@@ -554,6 +568,41 @@ struct qed_common_ops {
*/
int (*set_led)(struct qed_dev *cdev,
enum qed_led_mode mode);
+
+/**
+ * @brief update_drv_state - API to inform the change in the driver state.
+ *
+ * @param cdev
+ * @param active
+ *
+ */
+ int (*update_drv_state)(struct qed_dev *cdev, bool active);
+
+/**
+ * @brief update_mac - API to inform the change in the mac address
+ *
+ * @param cdev
+ * @param mac
+ *
+ */
+ int (*update_mac)(struct qed_dev *cdev, u8 *mac);
+
+/**
+ * @brief update_mtu - API to inform the change in the mtu
+ *
+ * @param cdev
+ * @param mtu
+ *
+ */
+ int (*update_mtu)(struct qed_dev *cdev, u16 mtu);
+
+/**
+ * @brief update_wol - update of changes in the WoL configuration
+ *
+ * @param cdev
+ * @param enabled - true iff WoL should be enabled.
+ */
+ int (*update_wol) (struct qed_dev *cdev, bool enabled);
};
#define MASK_FIELD(_name, _value) \
diff --git a/include/linux/qed/qed_iscsi_if.h b/include/linux/qed/qed_iscsi_if.h
new file mode 100644
index 000000000000..d27912480cb3
--- /dev/null
+++ b/include/linux/qed/qed_iscsi_if.h
@@ -0,0 +1,229 @@
+/* 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_ISCSI_IF_H
+#define _QED_ISCSI_IF_H
+#include <linux/types.h>
+#include <linux/qed/qed_if.h>
+
+typedef int (*iscsi_event_cb_t) (void *context,
+ u8 fw_event_code, void *fw_handle);
+struct qed_iscsi_stats {
+ u64 iscsi_rx_bytes_cnt;
+ u64 iscsi_rx_packet_cnt;
+ u64 iscsi_rx_new_ooo_isle_events_cnt;
+ u32 iscsi_cmdq_threshold_cnt;
+ u32 iscsi_rq_threshold_cnt;
+ u32 iscsi_immq_threshold_cnt;
+
+ u64 iscsi_rx_dropped_pdus_task_not_valid;
+
+ u64 iscsi_rx_data_pdu_cnt;
+ u64 iscsi_rx_r2t_pdu_cnt;
+ u64 iscsi_rx_total_pdu_cnt;
+
+ u64 iscsi_tx_go_to_slow_start_event_cnt;
+ u64 iscsi_tx_fast_retransmit_event_cnt;
+
+ u64 iscsi_tx_data_pdu_cnt;
+ u64 iscsi_tx_r2t_pdu_cnt;
+ u64 iscsi_tx_total_pdu_cnt;
+
+ u64 iscsi_tx_bytes_cnt;
+ u64 iscsi_tx_packet_cnt;
+};
+
+struct qed_dev_iscsi_info {
+ struct qed_dev_info common;
+
+ void __iomem *primary_dbq_rq_addr;
+ void __iomem *secondary_bdq_rq_addr;
+};
+
+struct qed_iscsi_id_params {
+ u8 mac[ETH_ALEN];
+ u32 ip[4];
+ u16 port;
+};
+
+struct qed_iscsi_params_offload {
+ u8 layer_code;
+ dma_addr_t sq_pbl_addr;
+ u32 initial_ack;
+
+ struct qed_iscsi_id_params src;
+ struct qed_iscsi_id_params dst;
+ u16 vlan_id;
+ u8 tcp_flags;
+ u8 ip_version;
+ u8 default_cq;
+
+ u8 ka_max_probe_cnt;
+ u8 dup_ack_theshold;
+ u32 rcv_next;
+ u32 snd_una;
+ u32 snd_next;
+ u32 snd_max;
+ u32 snd_wnd;
+ u32 rcv_wnd;
+ u32 snd_wl1;
+ u32 cwnd;
+ u32 ss_thresh;
+ u16 srtt;
+ u16 rtt_var;
+ u32 ts_time;
+ u32 ts_recent;
+ u32 ts_recent_age;
+ u32 total_rt;
+ u32 ka_timeout_delta;
+ u32 rt_timeout_delta;
+ u8 dup_ack_cnt;
+ u8 snd_wnd_probe_cnt;
+ u8 ka_probe_cnt;
+ u8 rt_cnt;
+ u32 flow_label;
+ u32 ka_timeout;
+ u32 ka_interval;
+ u32 max_rt_time;
+ u32 initial_rcv_wnd;
+ u8 ttl;
+ u8 tos_or_tc;
+ u16 remote_port;
+ u16 local_port;
+ u16 mss;
+ u8 snd_wnd_scale;
+ u8 rcv_wnd_scale;
+ u32 ts_ticks_per_second;
+ u16 da_timeout_value;
+ u8 ack_frequency;
+};
+
+struct qed_iscsi_params_update {
+ u8 update_flag;
+#define QED_ISCSI_CONN_HD_EN BIT(0)
+#define QED_ISCSI_CONN_DD_EN BIT(1)
+#define QED_ISCSI_CONN_INITIAL_R2T BIT(2)
+#define QED_ISCSI_CONN_IMMEDIATE_DATA BIT(3)
+
+ u32 max_seq_size;
+ u32 max_recv_pdu_length;
+ u32 max_send_pdu_length;
+ u32 first_seq_length;
+ u32 exp_stat_sn;
+};
+
+#define MAX_TID_BLOCKS_ISCSI (512)
+struct qed_iscsi_tid {
+ u32 size; /* In bytes per task */
+ u32 num_tids_per_block;
+ u8 *blocks[MAX_TID_BLOCKS_ISCSI];
+};
+
+struct qed_iscsi_cb_ops {
+ struct qed_common_cb_ops common;
+};
+
+/**
+ * struct qed_iscsi_ops - qed iSCSI operations.
+ * @common: common operations pointer
+ * @ll2: light L2 operations pointer
+ * @fill_dev_info: fills iSCSI specific information
+ * @param cdev
+ * @param info
+ * @return 0 on sucesss, otherwise error value.
+ * @register_ops: register iscsi operations
+ * @param cdev
+ * @param ops - specified using qed_iscsi_cb_ops
+ * @param cookie - driver private
+ * @start: iscsi in FW
+ * @param cdev
+ * @param tasks - qed will fill information about tasks
+ * return 0 on success, otherwise error value.
+ * @stop: iscsi in FW
+ * @param cdev
+ * return 0 on success, otherwise error value.
+ * @acquire_conn: acquire a new iscsi connection
+ * @param cdev
+ * @param handle - qed will fill handle that should be
+ * used henceforth as identifier of the
+ * connection.
+ * @param p_doorbell - qed will fill the address of the
+ * doorbell.
+ * @return 0 on sucesss, otherwise error value.
+ * @release_conn: release a previously acquired iscsi connection
+ * @param cdev
+ * @param handle - the connection handle.
+ * @return 0 on success, otherwise error value.
+ * @offload_conn: configures an offloaded connection
+ * @param cdev
+ * @param handle - the connection handle.
+ * @param conn_info - the configuration to use for the
+ * offload.
+ * @return 0 on success, otherwise error value.
+ * @update_conn: updates an offloaded connection
+ * @param cdev
+ * @param handle - the connection handle.
+ * @param conn_info - the configuration to use for the
+ * offload.
+ * @return 0 on success, otherwise error value.
+ * @destroy_conn: stops an offloaded connection
+ * @param cdev
+ * @param handle - the connection handle.
+ * @return 0 on success, otherwise error value.
+ * @clear_sq: clear all task in sq
+ * @param cdev
+ * @param handle - the connection handle.
+ * @return 0 on success, otherwise error value.
+ * @get_stats: iSCSI related statistics
+ * @param cdev
+ * @param stats - pointer to struck that would be filled
+ * we stats
+ * @return 0 on success, error otherwise.
+ */
+struct qed_iscsi_ops {
+ const struct qed_common_ops *common;
+
+ const struct qed_ll2_ops *ll2;
+
+ int (*fill_dev_info)(struct qed_dev *cdev,
+ struct qed_dev_iscsi_info *info);
+
+ void (*register_ops)(struct qed_dev *cdev,
+ struct qed_iscsi_cb_ops *ops, void *cookie);
+
+ int (*start)(struct qed_dev *cdev,
+ struct qed_iscsi_tid *tasks,
+ void *event_context, iscsi_event_cb_t async_event_cb);
+
+ int (*stop)(struct qed_dev *cdev);
+
+ int (*acquire_conn)(struct qed_dev *cdev,
+ u32 *handle,
+ u32 *fw_cid, void __iomem **p_doorbell);
+
+ int (*release_conn)(struct qed_dev *cdev, u32 handle);
+
+ int (*offload_conn)(struct qed_dev *cdev,
+ u32 handle,
+ struct qed_iscsi_params_offload *conn_info);
+
+ int (*update_conn)(struct qed_dev *cdev,
+ u32 handle,
+ struct qed_iscsi_params_update *conn_info);
+
+ int (*destroy_conn)(struct qed_dev *cdev, u32 handle, u8 abrt_conn);
+
+ int (*clear_sq)(struct qed_dev *cdev, u32 handle);
+
+ int (*get_stats)(struct qed_dev *cdev,
+ struct qed_iscsi_stats *stats);
+};
+
+const struct qed_iscsi_ops *qed_get_iscsi_ops(void);
+void qed_put_iscsi_ops(void);
+#endif
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index af3581b8a451..744486057e9e 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -80,14 +80,11 @@ static inline bool radix_tree_is_internal_node(void *ptr)
#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
RADIX_TREE_MAP_SHIFT))
-/* Internally used bits of node->count */
-#define RADIX_TREE_COUNT_SHIFT (RADIX_TREE_MAP_SHIFT + 1)
-#define RADIX_TREE_COUNT_MASK ((1UL << RADIX_TREE_COUNT_SHIFT) - 1)
-
struct radix_tree_node {
- unsigned char shift; /* Bits remaining in each slot */
- unsigned char offset; /* Slot offset in parent */
- unsigned int count;
+ unsigned char shift; /* Bits remaining in each slot */
+ unsigned char offset; /* Slot offset in parent */
+ unsigned char count; /* Total entry count */
+ unsigned char exceptional; /* Exceptional entry count */
union {
struct {
/* Used when ascending tree */
@@ -248,20 +245,6 @@ static inline int radix_tree_exception(void *arg)
return unlikely((unsigned long)arg & RADIX_TREE_ENTRY_MASK);
}
-/**
- * radix_tree_replace_slot - replace item in a slot
- * @pslot: pointer to slot, returned by radix_tree_lookup_slot
- * @item: new item to store in the slot.
- *
- * For use with radix_tree_lookup_slot(). Caller must hold tree write locked
- * across slot lookup and replacement.
- */
-static inline void radix_tree_replace_slot(void **pslot, void *item)
-{
- BUG_ON(radix_tree_is_internal_node(item));
- rcu_assign_pointer(*pslot, item);
-}
-
int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
unsigned order, struct radix_tree_node **nodep,
void ***slotp);
@@ -276,7 +259,14 @@ void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index,
struct radix_tree_node **nodep, void ***slotp);
void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
-bool __radix_tree_delete_node(struct radix_tree_root *root,
+typedef void (*radix_tree_update_node_t)(struct radix_tree_node *, void *);
+void __radix_tree_replace(struct radix_tree_root *root,
+ struct radix_tree_node *node,
+ void **slot, void *item,
+ radix_tree_update_node_t update_node, void *private);
+void radix_tree_replace_slot(struct radix_tree_root *root,
+ void **slot, void *item);
+void __radix_tree_delete_node(struct radix_tree_root *root,
struct radix_tree_node *node);
void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
void *radix_tree_delete(struct radix_tree_root *, unsigned long);
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 8beb98dcf14f..4f7a9561b8c4 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -45,19 +45,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_add_rcu(struct list_head *new,
struct list_head *prev, struct list_head *next)
{
+ if (!__list_add_valid(new, prev, next))
+ return;
+
new->next = next;
new->prev = prev;
rcu_assign_pointer(list_next_rcu(prev), new);
next->prev = new;
}
-#else
-void __list_add_rcu(struct list_head *new,
- struct list_head *prev, struct list_head *next);
-#endif
/**
* list_add_rcu - add a new entry to rcu-protected list
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 692108222271..ea0fffa5faeb 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -120,6 +120,25 @@ struct regmap;
#define REGULATOR_EVENT_PRE_DISABLE 0x400
#define REGULATOR_EVENT_ABORT_DISABLE 0x800
+/*
+ * Regulator errors that can be queried using regulator_get_error_flags
+ *
+ * UNDER_VOLTAGE Regulator output is under voltage.
+ * OVER_CURRENT Regulator output current is too high.
+ * REGULATION_OUT Regulator output is out of regulation.
+ * FAIL Regulator output has failed.
+ * OVER_TEMP Regulator over temp.
+ *
+ * NOTE: These errors can be OR'ed together.
+ */
+
+#define REGULATOR_ERROR_UNDER_VOLTAGE BIT(1)
+#define REGULATOR_ERROR_OVER_CURRENT BIT(2)
+#define REGULATOR_ERROR_REGULATION_OUT BIT(3)
+#define REGULATOR_ERROR_FAIL BIT(4)
+#define REGULATOR_ERROR_OVER_TEMP BIT(5)
+
+
/**
* struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event
*
@@ -237,6 +256,8 @@ int regulator_get_current_limit(struct regulator *regulator);
int regulator_set_mode(struct regulator *regulator, unsigned int mode);
unsigned int regulator_get_mode(struct regulator *regulator);
+int regulator_get_error_flags(struct regulator *regulator,
+ unsigned int *flags);
int regulator_set_load(struct regulator *regulator, int load_uA);
int regulator_allow_bypass(struct regulator *regulator, bool allow);
@@ -477,6 +498,12 @@ static inline unsigned int regulator_get_mode(struct regulator *regulator)
return REGULATOR_MODE_NORMAL;
}
+static inline int regulator_get_error_flags(struct regulator *regulator,
+ unsigned int *flags)
+{
+ return -EINVAL;
+}
+
static inline int regulator_set_load(struct regulator *regulator, int load_uA)
{
return REGULATOR_MODE_NORMAL;
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 37b532410528..dac8e7b16bc6 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -100,6 +100,7 @@ struct regulator_linear_range {
*
* @set_mode: Set the configured operating mode for the regulator.
* @get_mode: Get the configured operating mode for the regulator.
+ * @get_error_flags: Get the current error(s) for the regulator.
* @get_status: Return actual (not as-configured) status of regulator, as a
* REGULATOR_STATUS value (or negative errno)
* @get_optimum_mode: Get the most efficient operating mode for the regulator
@@ -169,6 +170,9 @@ struct regulator_ops {
int (*set_mode) (struct regulator_dev *, unsigned int mode);
unsigned int (*get_mode) (struct regulator_dev *);
+ /* retrieve current error flags on the regulator */
+ int (*get_error_flags)(struct regulator_dev *, unsigned int *flags);
+
/* Time taken to enable or set voltage on the regulator */
int (*enable_time) (struct regulator_dev *);
int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 930023b7c825..e2f3a3281d8f 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -400,6 +400,7 @@ enum rproc_crash_type {
* @firmware_loading_complete: marks e/o asynchronous firmware loading
* @bootaddr: address of first instruction to boot rproc with (optional)
* @rvdevs: list of remote virtio devices
+ * @subdevs: list of subdevices, to following the running state
* @notifyids: idr for dynamically assigning rproc-wide unique notify ids
* @index: index of this rproc device
* @crash_handler: workqueue for handling a crash
@@ -407,15 +408,14 @@ enum rproc_crash_type {
* @crash_comp: completion used to sync crash handler and the rproc reload
* @recovery_disabled: flag that state if recovery was disabled
* @max_notifyid: largest allocated notify id.
- * @table_ptr: pointer to the resource table in effect
- * @cached_table: copy of the resource table
+ * @table_ptr: our copy of the resource table
* @has_iommu: flag to indicate if remote processor is behind an MMU
*/
struct rproc {
struct list_head node;
struct iommu_domain *domain;
const char *name;
- const char *firmware;
+ char *firmware;
void *priv;
const struct rproc_ops *ops;
struct device dev;
@@ -431,6 +431,7 @@ struct rproc {
struct completion firmware_loading_complete;
u32 bootaddr;
struct list_head rvdevs;
+ struct list_head subdevs;
struct idr notifyids;
int index;
struct work_struct crash_handler;
@@ -439,11 +440,23 @@ struct rproc {
bool recovery_disabled;
int max_notifyid;
struct resource_table *table_ptr;
- struct resource_table *cached_table;
bool has_iommu;
bool auto_boot;
};
+/**
+ * struct rproc_subdev - subdevice tied to a remoteproc
+ * @node: list node related to the rproc subdevs list
+ * @probe: probe function, called as the rproc is started
+ * @remove: remove function, called as the rproc is stopped
+ */
+struct rproc_subdev {
+ struct list_head node;
+
+ int (*probe)(struct rproc_subdev *subdev);
+ void (*remove)(struct rproc_subdev *subdev);
+};
+
/* we currently support only two vrings per rvdev */
#define RVDEV_NUM_VRINGS 2
@@ -472,6 +485,9 @@ struct rproc_vring {
/**
* struct rproc_vdev - remoteproc state for a supported virtio device
+ * @refcount: reference counter for the vdev and vring allocations
+ * @subdev: handle for registering the vdev as a rproc subdevice
+ * @id: virtio device id (as in virtio_ids.h)
* @node: list node
* @rproc: the rproc handle
* @vdev: the virio device
@@ -479,6 +495,11 @@ struct rproc_vring {
* @rsc_offset: offset of the vdev's resource entry
*/
struct rproc_vdev {
+ struct kref refcount;
+
+ struct rproc_subdev subdev;
+
+ unsigned int id;
struct list_head node;
struct rproc *rproc;
struct virtio_device vdev;
@@ -511,4 +532,11 @@ static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev)
return rvdev->rproc;
}
+void rproc_add_subdev(struct rproc *rproc,
+ struct rproc_subdev *subdev,
+ int (*probe)(struct rproc_subdev *subdev),
+ void (*remove)(struct rproc_subdev *subdev));
+
+void rproc_remove_subdev(struct rproc *rproc, struct rproc_subdev *subdev);
+
#endif /* REMOTEPROC_H */
diff --git a/include/linux/remoteproc/st_slim_rproc.h b/include/linux/remoteproc/st_slim_rproc.h
new file mode 100644
index 000000000000..4155556fa4b2
--- /dev/null
+++ b/include/linux/remoteproc/st_slim_rproc.h
@@ -0,0 +1,58 @@
+/*
+ * SLIM core rproc driver header
+ *
+ * Copyright (C) 2016 STMicroelectronics
+ *
+ * Author: Peter Griffin <peter.griffin@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.
+ */
+#ifndef _ST_REMOTEPROC_SLIM_H
+#define _ST_REMOTEPROC_SLIM_H
+
+#define ST_SLIM_MEM_MAX 2
+#define ST_SLIM_MAX_CLK 4
+
+enum {
+ ST_SLIM_DMEM,
+ ST_SLIM_IMEM,
+};
+
+/**
+ * struct st_slim_mem - slim internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @size: Size of the memory region
+ */
+struct st_slim_mem {
+ void __iomem *cpu_addr;
+ phys_addr_t bus_addr;
+ size_t size;
+};
+
+/**
+ * struct st_slim_rproc - SLIM slim core
+ * @rproc: rproc handle
+ * @mem: slim memory information
+ * @slimcore: slim slimcore regs
+ * @peri: slim peripheral regs
+ * @clks: slim clocks
+ */
+struct st_slim_rproc {
+ struct rproc *rproc;
+ struct st_slim_mem mem[ST_SLIM_MEM_MAX];
+ void __iomem *slimcore;
+ void __iomem *peri;
+
+ /* st_slim_rproc private */
+ struct clk *clks[ST_SLIM_MAX_CLK];
+};
+
+struct st_slim_rproc *st_slim_rproc_alloc(struct platform_device *pdev,
+ char *fw_name);
+void st_slim_rproc_put(struct st_slim_rproc *slim_rproc);
+
+#endif
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index b0f305e77b7f..d9706a6f5ae2 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -40,7 +40,7 @@
#define _LINUX_RESERVATION_H
#include <linux/ww_mutex.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/slab.h>
#include <linux/seqlock.h>
#include <linux/rcupdate.h>
@@ -59,7 +59,7 @@ extern const char reservation_seqcount_string[];
struct reservation_object_list {
struct rcu_head rcu;
u32 shared_count, shared_max;
- struct fence __rcu *shared[];
+ struct dma_fence __rcu *shared[];
};
/**
@@ -74,7 +74,7 @@ struct reservation_object {
struct ww_mutex lock;
seqcount_t seq;
- struct fence __rcu *fence_excl;
+ struct dma_fence __rcu *fence_excl;
struct reservation_object_list __rcu *fence;
struct reservation_object_list *staged;
};
@@ -107,7 +107,7 @@ reservation_object_fini(struct reservation_object *obj)
{
int i;
struct reservation_object_list *fobj;
- struct fence *excl;
+ struct dma_fence *excl;
/*
* This object should be dead and all references must have
@@ -115,12 +115,12 @@ reservation_object_fini(struct reservation_object *obj)
*/
excl = rcu_dereference_protected(obj->fence_excl, 1);
if (excl)
- fence_put(excl);
+ dma_fence_put(excl);
fobj = rcu_dereference_protected(obj->fence, 1);
if (fobj) {
for (i = 0; i < fobj->shared_count; ++i)
- fence_put(rcu_dereference_protected(fobj->shared[i], 1));
+ dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1));
kfree(fobj);
}
@@ -155,7 +155,7 @@ reservation_object_get_list(struct reservation_object *obj)
* RETURNS
* The exclusive fence or NULL
*/
-static inline struct fence *
+static inline struct dma_fence *
reservation_object_get_excl(struct reservation_object *obj)
{
return rcu_dereference_protected(obj->fence_excl,
@@ -173,35 +173,32 @@ reservation_object_get_excl(struct reservation_object *obj)
* RETURNS
* The exclusive fence or NULL if none
*/
-static inline struct fence *
+static inline struct dma_fence *
reservation_object_get_excl_rcu(struct reservation_object *obj)
{
- struct fence *fence;
- unsigned seq;
-retry:
- seq = read_seqcount_begin(&obj->seq);
+ struct dma_fence *fence;
+
+ if (!rcu_access_pointer(obj->fence_excl))
+ return NULL;
+
rcu_read_lock();
- fence = rcu_dereference(obj->fence_excl);
- if (read_seqcount_retry(&obj->seq, seq)) {
- rcu_read_unlock();
- goto retry;
- }
- fence = fence_get(fence);
+ fence = dma_fence_get_rcu_safe(&obj->fence_excl);
rcu_read_unlock();
+
return fence;
}
int reservation_object_reserve_shared(struct reservation_object *obj);
void reservation_object_add_shared_fence(struct reservation_object *obj,
- struct fence *fence);
+ struct dma_fence *fence);
void reservation_object_add_excl_fence(struct reservation_object *obj,
- struct fence *fence);
+ struct dma_fence *fence);
int reservation_object_get_fences_rcu(struct reservation_object *obj,
- struct fence **pfence_excl,
+ struct dma_fence **pfence_excl,
unsigned *pshared_count,
- struct fence ***pshared);
+ struct dma_fence ***pshared);
long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
bool wait_all, bool intr,
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 4acc552e9279..b6d4568795a7 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -198,4 +198,10 @@ enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0,
};
+#ifdef CONFIG_RING_BUFFER
+int trace_rb_cpu_prepare(unsigned int cpu, struct hlist_node *node);
+#else
+#define trace_rb_cpu_prepare NULL
+#endif
+
#endif /* _LINUX_RING_BUFFER_H */
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index b46bb5620a76..15321fb1df6b 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -137,11 +137,19 @@ static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
* anon_vma helper functions.
*/
void anon_vma_init(void); /* create anon_vma_cachep */
-int anon_vma_prepare(struct vm_area_struct *);
+int __anon_vma_prepare(struct vm_area_struct *);
void unlink_anon_vmas(struct vm_area_struct *);
int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
+static inline int anon_vma_prepare(struct vm_area_struct *vma)
+{
+ if (likely(vma->anon_vma))
+ return 0;
+
+ return __anon_vma_prepare(vma);
+}
+
static inline void anon_vma_merge(struct vm_area_struct *vma,
struct vm_area_struct *next)
{
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 452d393cc8dd..18f9e1ae4b7e 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -37,6 +37,7 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/err.h>
#include <linux/mod_devicetable.h>
#include <linux/kref.h>
#include <linux/mutex.h>
@@ -64,6 +65,7 @@ struct rpmsg_channel_info {
* rpmsg_device - device that belong to the rpmsg bus
* @dev: the device struct
* @id: device id (used to match between rpmsg drivers and devices)
+ * @driver_override: driver name to force a match
* @src: local address
* @dst: destination address
* @ept: the rpmsg endpoint of this channel
@@ -72,6 +74,7 @@ struct rpmsg_channel_info {
struct rpmsg_device {
struct device dev;
struct rpmsg_device_id id;
+ char *driver_override;
u32 src;
u32 dst;
struct rpmsg_endpoint *ept;
@@ -132,6 +135,8 @@ struct rpmsg_driver {
int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
};
+#if IS_ENABLED(CONFIG_RPMSG)
+
int register_rpmsg_device(struct rpmsg_device *dev);
void unregister_rpmsg_device(struct rpmsg_device *dev);
int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
@@ -141,6 +146,116 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
rpmsg_rx_cb_t cb, void *priv,
struct rpmsg_channel_info chinfo);
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+ void *data, int len);
+
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+ void *data, int len);
+
+#else
+
+static inline int register_rpmsg_device(struct rpmsg_device *dev)
+{
+ return -ENXIO;
+}
+
+static inline void unregister_rpmsg_device(struct rpmsg_device *dev)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+}
+
+static inline int __register_rpmsg_driver(struct rpmsg_driver *drv,
+ struct module *owner)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+static inline void unregister_rpmsg_driver(struct rpmsg_driver *drv)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+}
+
+static inline void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+}
+
+static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
+ rpmsg_rx_cb_t cb,
+ void *priv,
+ struct rpmsg_channel_info chinfo)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return ERR_PTR(-ENXIO);
+}
+
+static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
+ u32 dst)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+
+}
+
+static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
+ u32 dst, void *data, int len)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
+ int len, u32 dst)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
+ u32 dst, void *data, int len)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return -ENXIO;
+}
+
+#endif /* IS_ENABLED(CONFIG_RPMSG) */
+
/* use a macro to avoid include chaining to get THIS_MODULE */
#define register_rpmsg_driver(drv) \
__register_rpmsg_driver(drv, THIS_MODULE)
@@ -157,14 +272,4 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
module_driver(__rpmsg_driver, register_rpmsg_driver, \
unregister_rpmsg_driver)
-int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
- void *data, int len);
-
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
- void *data, int len);
-
#endif /* _LINUX_RPMSG_H */
diff --git a/include/linux/rpmsg/qcom_smd.h b/include/linux/rpmsg/qcom_smd.h
new file mode 100644
index 000000000000..e674b2e3074b
--- /dev/null
+++ b/include/linux/rpmsg/qcom_smd.h
@@ -0,0 +1,33 @@
+
+#ifndef _LINUX_RPMSG_QCOM_SMD_H
+#define _LINUX_RPMSG_QCOM_SMD_H
+
+#include <linux/device.h>
+
+struct qcom_smd_edge;
+
+#if IS_ENABLED(CONFIG_RPMSG_QCOM_SMD) || IS_ENABLED(CONFIG_QCOM_SMD)
+
+struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
+ struct device_node *node);
+int qcom_smd_unregister_edge(struct qcom_smd_edge *edge);
+
+#else
+
+static inline struct qcom_smd_edge *
+qcom_smd_register_edge(struct device *parent,
+ struct device_node *node)
+{
+ return ERR_PTR(-ENXIO);
+}
+
+static inline int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+ return -ENXIO;
+}
+
+#endif
+
+#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e9c009dc3a4a..5ccbbfe41345 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -262,20 +262,9 @@ extern char ___assert_task_state[1 - 2*!!(
#define set_task_state(tsk, state_value) \
do { \
(tsk)->task_state_change = _THIS_IP_; \
- smp_store_mb((tsk)->state, (state_value)); \
+ smp_store_mb((tsk)->state, (state_value)); \
} while (0)
-/*
- * set_current_state() includes a barrier so that the write of current->state
- * is correctly serialised wrt the caller's subsequent test of whether to
- * actually sleep:
- *
- * set_current_state(TASK_UNINTERRUPTIBLE);
- * if (do_i_need_to_sleep())
- * schedule();
- *
- * If the caller does not need such serialisation then use __set_current_state()
- */
#define __set_current_state(state_value) \
do { \
current->task_state_change = _THIS_IP_; \
@@ -284,11 +273,19 @@ extern char ___assert_task_state[1 - 2*!!(
#define set_current_state(state_value) \
do { \
current->task_state_change = _THIS_IP_; \
- smp_store_mb(current->state, (state_value)); \
+ smp_store_mb(current->state, (state_value)); \
} while (0)
#else
+/*
+ * @tsk had better be current, or you get to keep the pieces.
+ *
+ * The only reason is that computing current can be more expensive than
+ * using a pointer that's already available.
+ *
+ * Therefore, see set_current_state().
+ */
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
#define set_task_state(tsk, state_value) \
@@ -299,11 +296,34 @@ extern char ___assert_task_state[1 - 2*!!(
* is correctly serialised wrt the caller's subsequent test of whether to
* actually sleep:
*
+ * for (;;) {
* set_current_state(TASK_UNINTERRUPTIBLE);
- * if (do_i_need_to_sleep())
- * schedule();
+ * if (!need_sleep)
+ * break;
+ *
+ * schedule();
+ * }
+ * __set_current_state(TASK_RUNNING);
+ *
+ * If the caller does not need such serialisation (because, for instance, the
+ * condition test and condition change and wakeup are under the same lock) then
+ * use __set_current_state().
+ *
+ * The above is typically ordered against the wakeup, which does:
+ *
+ * need_sleep = false;
+ * wake_up_state(p, TASK_UNINTERRUPTIBLE);
+ *
+ * Where wake_up_state() (and all other wakeup primitives) imply enough
+ * barriers to order the store of the variable against wakeup.
*
- * If the caller does not need such serialisation then use __set_current_state()
+ * Wakeup will do: if (@state & p->state) p->state = TASK_RUNNING, that is,
+ * once it observes the TASK_UNINTERRUPTIBLE store the waking CPU can issue a
+ * TASK_RUNNING store which can collide with __set_current_state(TASK_RUNNING).
+ *
+ * This is obviously fine, since they both store the exact same value.
+ *
+ * Also see the comments of try_to_wake_up().
*/
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
@@ -520,7 +540,11 @@ static inline int get_dumpable(struct mm_struct *mm)
/* leave room for more dump flags */
#define MMF_VM_MERGEABLE 16 /* KSM may merge identical pages */
#define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */
-#define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */
+/*
+ * This one-shot flag is dropped due to necessity of changing exe once again
+ * on NFS restore
+ */
+//#define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */
#define MMF_HAS_UPROBES 19 /* has uprobes */
#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */
@@ -989,7 +1013,7 @@ enum cpu_idle_type {
* already in a wake queue, the wakeup will happen soon and the second
* waker can just skip it.
*
- * The WAKE_Q macro declares and initializes the list head.
+ * The DEFINE_WAKE_Q macro declares and initializes the list head.
* wake_up_q() does NOT reinitialize the list; it's expected to be
* called near the end of a function, where the fact that the queue is
* not used again will be easy to see by inspection.
@@ -1009,7 +1033,7 @@ struct wake_q_head {
#define WAKE_Q_TAIL ((struct wake_q_node *) 0x01)
-#define WAKE_Q(name) \
+#define DEFINE_WAKE_Q(name) \
struct wake_q_head name = { WAKE_Q_TAIL, &name.first }
extern void wake_q_add(struct wake_q_head *head,
@@ -1057,6 +1081,8 @@ static inline int cpu_numa_flags(void)
}
#endif
+extern int arch_asym_cpu_priority(int cpu);
+
struct sched_domain_attr {
int relax_domain_level;
};
@@ -1627,7 +1653,10 @@ struct task_struct {
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
- cputime_t utime, stime, utimescaled, stimescaled;
+ cputime_t utime, stime;
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
+ cputime_t utimescaled, stimescaled;
+#endif
cputime_t gtime;
struct prev_cputime prev_cputime;
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
@@ -2220,40 +2249,45 @@ struct task_struct *try_get_task_struct(struct task_struct **ptask);
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
extern void task_cputime(struct task_struct *t,
cputime_t *utime, cputime_t *stime);
-extern void task_cputime_scaled(struct task_struct *t,
- cputime_t *utimescaled, cputime_t *stimescaled);
extern cputime_t task_gtime(struct task_struct *t);
#else
static inline void task_cputime(struct task_struct *t,
cputime_t *utime, cputime_t *stime)
{
- if (utime)
- *utime = t->utime;
- if (stime)
- *stime = t->stime;
+ *utime = t->utime;
+ *stime = t->stime;
}
+static inline cputime_t task_gtime(struct task_struct *t)
+{
+ return t->gtime;
+}
+#endif
+
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
static inline void task_cputime_scaled(struct task_struct *t,
cputime_t *utimescaled,
cputime_t *stimescaled)
{
- if (utimescaled)
- *utimescaled = t->utimescaled;
- if (stimescaled)
- *stimescaled = t->stimescaled;
+ *utimescaled = t->utimescaled;
+ *stimescaled = t->stimescaled;
}
-
-static inline cputime_t task_gtime(struct task_struct *t)
+#else
+static inline void task_cputime_scaled(struct task_struct *t,
+ cputime_t *utimescaled,
+ cputime_t *stimescaled)
{
- return t->gtime;
+ task_cputime(t, utimescaled, stimescaled);
}
#endif
+
extern void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
/*
* Per process flags
*/
+#define PF_IDLE 0x00000002 /* I am an IDLE thread */
#define PF_EXITING 0x00000004 /* getting shut down */
#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
#define PF_VCPU 0x00000010 /* I'm a virtual CPU */
@@ -2444,6 +2478,10 @@ static inline void calc_load_enter_idle(void) { }
static inline void calc_load_exit_idle(void) { }
#endif /* CONFIG_NO_HZ_COMMON */
+#ifndef cpu_relax_yield
+#define cpu_relax_yield() cpu_relax()
+#endif
+
/*
* Do not use outside of architecture code which knows its limitations.
*
@@ -2611,7 +2649,7 @@ extern struct task_struct *idle_task(int cpu);
*/
static inline bool is_idle_task(const struct task_struct *p)
{
- return p->pid == 0;
+ return !!(p->flags & PF_IDLE);
}
extern struct task_struct *curr_task(int cpu);
extern void ia64_set_curr_task(int cpu, struct task_struct *p);
@@ -3508,6 +3546,18 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
#endif /* CONFIG_SMP */
+/*
+ * In order to reduce various lock holder preemption latencies provide an
+ * interface to see if a vCPU is currently running or not.
+ *
+ * This allows us to terminate optimistic spin loops and block, analogous to
+ * the native optimistic spin heuristic of testing if the lock owner task is
+ * running or not.
+ */
+#ifndef vcpu_is_preempted
+# define vcpu_is_preempted(cpu) false
+#endif
+
extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 22db1e63707e..441145351301 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -36,7 +36,6 @@ extern unsigned int sysctl_numa_balancing_scan_size;
extern unsigned int sysctl_sched_migration_cost;
extern unsigned int sysctl_sched_nr_migrate;
extern unsigned int sysctl_sched_time_avg;
-extern unsigned int sysctl_sched_shares_window;
int sched_proc_update_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *length,
diff --git a/include/linux/seg6.h b/include/linux/seg6.h
new file mode 100644
index 000000000000..7a66d2b4c5a6
--- /dev/null
+++ b/include/linux/seg6.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_SEG6_H
+#define _LINUX_SEG6_H
+
+#include <uapi/linux/seg6.h>
+
+#endif
diff --git a/include/linux/seg6_genl.h b/include/linux/seg6_genl.h
new file mode 100644
index 000000000000..d6c3fb4f3734
--- /dev/null
+++ b/include/linux/seg6_genl.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_SEG6_GENL_H
+#define _LINUX_SEG6_GENL_H
+
+#include <uapi/linux/seg6_genl.h>
+
+#endif
diff --git a/include/linux/seg6_hmac.h b/include/linux/seg6_hmac.h
new file mode 100644
index 000000000000..da437ebdc6cd
--- /dev/null
+++ b/include/linux/seg6_hmac.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_SEG6_HMAC_H
+#define _LINUX_SEG6_HMAC_H
+
+#include <uapi/linux/seg6_hmac.h>
+
+#endif
diff --git a/include/linux/seg6_iptunnel.h b/include/linux/seg6_iptunnel.h
new file mode 100644
index 000000000000..5377cf6a5a02
--- /dev/null
+++ b/include/linux/seg6_iptunnel.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_SEG6_IPTUNNEL_H
+#define _LINUX_SEG6_IPTUNNEL_H
+
+#include <uapi/linux/seg6_iptunnel.h>
+
+#endif
diff --git a/include/linux/seqno-fence.h b/include/linux/seqno-fence.h
index a1ba6a5ccdd6..c58c535d12a8 100644
--- a/include/linux/seqno-fence.h
+++ b/include/linux/seqno-fence.h
@@ -20,7 +20,7 @@
#ifndef __LINUX_SEQNO_FENCE_H
#define __LINUX_SEQNO_FENCE_H
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
#include <linux/dma-buf.h>
enum seqno_fence_condition {
@@ -29,15 +29,15 @@ enum seqno_fence_condition {
};
struct seqno_fence {
- struct fence base;
+ struct dma_fence base;
- const struct fence_ops *ops;
+ const struct dma_fence_ops *ops;
struct dma_buf *sync_buf;
uint32_t seqno_ofs;
enum seqno_fence_condition condition;
};
-extern const struct fence_ops seqno_fence_ops;
+extern const struct dma_fence_ops seqno_fence_ops;
/**
* to_seqno_fence - cast a fence to a seqno_fence
@@ -47,7 +47,7 @@ extern const struct fence_ops seqno_fence_ops;
* or the seqno_fence otherwise.
*/
static inline struct seqno_fence *
-to_seqno_fence(struct fence *fence)
+to_seqno_fence(struct dma_fence *fence)
{
if (fence->ops != &seqno_fence_ops)
return NULL;
@@ -83,9 +83,9 @@ to_seqno_fence(struct fence *fence)
* dma-buf for sync_buf, since mapping or unmapping the sync_buf to the
* device's vm can be expensive.
*
- * It is recommended for creators of seqno_fence to call fence_signal
+ * It is recommended for creators of seqno_fence to call dma_fence_signal()
* before destruction. This will prevent possible issues from wraparound at
- * time of issue vs time of check, since users can check fence_is_signaled
+ * time of issue vs time of check, since users can check dma_fence_is_signaled()
* before submitting instructions for the hardware to wait on the fence.
* However, when ops.enable_signaling is not called, it doesn't have to be
* done as soon as possible, just before there's any real danger of seqno
@@ -96,18 +96,18 @@ seqno_fence_init(struct seqno_fence *fence, spinlock_t *lock,
struct dma_buf *sync_buf, uint32_t context,
uint32_t seqno_ofs, uint32_t seqno,
enum seqno_fence_condition cond,
- const struct fence_ops *ops)
+ const struct dma_fence_ops *ops)
{
BUG_ON(!fence || !sync_buf || !ops);
BUG_ON(!ops->wait || !ops->enable_signaling ||
!ops->get_driver_name || !ops->get_timeline_name);
/*
- * ops is used in fence_init for get_driver_name, so needs to be
+ * ops is used in dma_fence_init for get_driver_name, so needs to be
* initialized first
*/
fence->ops = ops;
- fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno);
+ dma_fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno);
get_dma_buf(sync_buf);
fence->sync_buf = sync_buf;
fence->seqno_ofs = seqno_ofs;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 32810f279f8e..332e76756f54 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -645,8 +645,15 @@ struct sk_buff {
struct rb_node rbnode; /* used in netem & tcp stack */
};
struct sock *sk;
- struct net_device *dev;
+ union {
+ struct net_device *dev;
+ /* Some protocols might use this space to store information,
+ * while device pointer would be NULL.
+ * UDP receive path is one user.
+ */
+ unsigned long dev_scratch;
+ };
/*
* This is the control buffer. It is free to use for every
* layer. Please put your private variables there. If you
@@ -1087,7 +1094,7 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4)
}
void __skb_get_hash(struct sk_buff *skb);
-u32 __skb_get_hash_symmetric(struct sk_buff *skb);
+u32 __skb_get_hash_symmetric(const struct sk_buff *skb);
u32 skb_get_poff(const struct sk_buff *skb);
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
const struct flow_keys *keys, int hlen);
@@ -1799,11 +1806,11 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb)
return skb->len - skb->data_len;
}
-static inline int skb_pagelen(const struct sk_buff *skb)
+static inline unsigned int skb_pagelen(const struct sk_buff *skb)
{
- int i, len = 0;
+ unsigned int i, len = 0;
- for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
+ for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--)
len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
return len + skb_headlen(skb);
}
@@ -1966,6 +1973,8 @@ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
}
+void skb_condense(struct sk_buff *skb);
+
/**
* skb_headroom - bytes at buffer head
* @skb: buffer to check
@@ -3033,9 +3042,13 @@ static inline void skb_frag_list_init(struct sk_buff *skb)
int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
const struct sk_buff *skb);
struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned flags,
+ void (*destructor)(struct sock *sk,
+ struct sk_buff *skb),
int *peeked, int *off, int *err,
struct sk_buff **last);
struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
+ void (*destructor)(struct sock *sk,
+ struct sk_buff *skb),
int *peeked, int *off, int *err);
struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
int *err);
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
index e302c447e057..129bc674dcf5 100644
--- a/include/linux/smc91x.h
+++ b/include/linux/smc91x.h
@@ -39,6 +39,7 @@ struct smc91x_platdata {
unsigned long flags;
unsigned char leda;
unsigned char ledb;
+ bool pxa_u16_align4; /* PXA buggy u16 writes on 4*n+2 addresses */
};
#endif /* __SMC91X_H__ */
diff --git a/include/linux/soc/renesas/rcar-rst.h b/include/linux/soc/renesas/rcar-rst.h
new file mode 100644
index 000000000000..a18e0783946b
--- /dev/null
+++ b/include/linux/soc/renesas/rcar-rst.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__
+#define __LINUX_SOC_RENESAS_RCAR_RST_H__
+
+int rcar_rst_read_mode_pins(u32 *mode);
+
+#endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 705840e0438f..266dab9ad782 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -88,6 +88,9 @@ struct stmmac_mdio_bus_data {
struct stmmac_dma_cfg {
int pbl;
+ int txpbl;
+ int rxpbl;
+ bool pblx8;
int fixed_burst;
int mixed_burst;
bool aal;
@@ -135,8 +138,6 @@ struct plat_stmmacenet_data {
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
- void (*suspend)(struct platform_device *pdev, void *priv);
- void (*resume)(struct platform_device *pdev, void *priv);
void *bsp_priv;
struct stmmac_axi *axi;
int has_gmac4;
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index d9718378a8be..0c729c3c8549 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -194,6 +194,8 @@ struct platform_freeze_ops {
};
#ifdef CONFIG_SUSPEND
+extern suspend_state_t mem_sleep_default;
+
/**
* suspend_set_ops - set platform dependent suspend operations
* @ops: The new suspend operations to set.
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a56523cefb9b..09f4be179ff3 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -246,39 +246,7 @@ struct swap_info_struct {
void *workingset_eviction(struct address_space *mapping, struct page *page);
bool workingset_refault(void *shadow);
void workingset_activation(struct page *page);
-extern struct list_lru workingset_shadow_nodes;
-
-static inline unsigned int workingset_node_pages(struct radix_tree_node *node)
-{
- return node->count & RADIX_TREE_COUNT_MASK;
-}
-
-static inline void workingset_node_pages_inc(struct radix_tree_node *node)
-{
- node->count++;
-}
-
-static inline void workingset_node_pages_dec(struct radix_tree_node *node)
-{
- VM_WARN_ON_ONCE(!workingset_node_pages(node));
- node->count--;
-}
-
-static inline unsigned int workingset_node_shadows(struct radix_tree_node *node)
-{
- return node->count >> RADIX_TREE_COUNT_SHIFT;
-}
-
-static inline void workingset_node_shadows_inc(struct radix_tree_node *node)
-{
- node->count += 1U << RADIX_TREE_COUNT_SHIFT;
-}
-
-static inline void workingset_node_shadows_dec(struct radix_tree_node *node)
-{
- VM_WARN_ON_ONCE(!workingset_node_shadows(node));
- node->count -= 1U << RADIX_TREE_COUNT_SHIFT;
-}
+void workingset_update_node(struct radix_tree_node *node, void *private);
/* linux/mm/page_alloc.c */
extern unsigned long totalram_pages;
@@ -351,6 +319,9 @@ extern int kswapd_run(int nid);
extern void kswapd_stop(int nid);
#ifdef CONFIG_SWAP
+
+#include <linux/blk_types.h> /* for bio_end_io_t */
+
/* linux/mm/page_io.c */
extern int swap_readpage(struct page *);
extern int swap_writepage(struct page *page, struct writeback_control *wbc);
diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h
index aa17ccfc2f57..3e3ab84fc4cd 100644
--- a/include/linux/sync_file.h
+++ b/include/linux/sync_file.h
@@ -18,8 +18,8 @@
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/fence.h>
-#include <linux/fence-array.h>
+#include <linux/dma-fence.h>
+#include <linux/dma-fence-array.h>
/**
* struct sync_file - sync file to export to the userspace
@@ -41,13 +41,13 @@ struct sync_file {
wait_queue_head_t wq;
- struct fence *fence;
- struct fence_cb cb;
+ struct dma_fence *fence;
+ struct dma_fence_cb cb;
};
-#define POLL_ENABLED FENCE_FLAG_USER_BITS
+#define POLL_ENABLED DMA_FENCE_FLAG_USER_BITS
-struct sync_file *sync_file_create(struct fence *fence);
-struct fence *sync_file_get_fence(int fd);
+struct sync_file *sync_file_create(struct dma_fence *fence);
+struct dma_fence *sync_file_get_fence(int fd);
#endif /* _LINUX_SYNC_H */
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
index 2739ccb69571..bed223b70217 100644
--- a/include/linux/sys_soc.h
+++ b/include/linux/sys_soc.h
@@ -13,6 +13,7 @@ struct soc_device_attribute {
const char *family;
const char *revision;
const char *soc_id;
+ const void *data;
};
/**
@@ -34,4 +35,12 @@ void soc_device_unregister(struct soc_device *soc_dev);
*/
struct device *soc_device_to_device(struct soc_device *soc);
+#ifdef CONFIG_SOC_BUS
+const struct soc_device_attribute *soc_device_match(
+ const struct soc_device_attribute *matches);
+#else
+static inline const struct soc_device_attribute *soc_device_match(
+ const struct soc_device_attribute *matches) { return NULL; }
+#endif
+
#endif /* __SOC_BUS_H */
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index a17ae7b85218..fc5848dad7a4 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -123,6 +123,7 @@ struct tcp_request_sock {
u32 txhash;
u32 rcv_isn;
u32 snt_isn;
+ u32 ts_off;
u32 last_oow_ack_time; /* last SYNACK */
u32 rcv_nxt; /* the ack # by SYNACK. For
* FastOpen it's the seq#
@@ -176,8 +177,6 @@ struct tcp_sock {
* sum(delta(snd_una)), or how many bytes
* were acked.
*/
- struct u64_stats_sync syncp; /* protects 64bit vars (cf tcp_get_info()) */
-
u32 snd_una; /* First byte we want an ack for */
u32 snd_sml; /* Last byte of the most recently transmitted small packet */
u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
@@ -187,7 +186,6 @@ struct tcp_sock {
u32 tsoffset; /* timestamp offset */
struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
- unsigned long tsq_flags;
/* Data for direct copy to user */
struct {
@@ -213,8 +211,11 @@ struct tcp_sock {
u8 reord; /* reordering detected */
} rack;
u16 advmss; /* Advertised MSS */
- u8 rate_app_limited:1, /* rate_{delivered,interval_us} limited? */
- unused:7;
+ u32 chrono_start; /* Start time in jiffies of a TCP chrono */
+ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */
+ u8 chrono_type:2, /* current chronograph type */
+ rate_app_limited:1, /* rate_{delivered,interval_us} limited? */
+ unused:5;
u8 nonagle : 4,/* Disable Nagle algorithm? */
thin_lto : 1,/* Use linear timeouts for thin streams */
thin_dupack : 1,/* Fast retransmit on first dupack */
@@ -362,7 +363,7 @@ struct tcp_sock {
u32 *saved_syn;
};
-enum tsq_flags {
+enum tsq_enum {
TSQ_THROTTLED,
TSQ_QUEUED,
TCP_TSQ_DEFERRED, /* tcp_tasklet_func() found socket was owned */
@@ -373,6 +374,15 @@ enum tsq_flags {
*/
};
+enum tsq_flags {
+ TSQF_THROTTLED = (1UL << TSQ_THROTTLED),
+ TSQF_QUEUED = (1UL << TSQ_QUEUED),
+ TCPF_TSQ_DEFERRED = (1UL << TCP_TSQ_DEFERRED),
+ TCPF_WRITE_TIMER_DEFERRED = (1UL << TCP_WRITE_TIMER_DEFERRED),
+ TCPF_DELACK_TIMER_DEFERRED = (1UL << TCP_DELACK_TIMER_DEFERRED),
+ TCPF_MTU_REDUCED_DEFERRED = (1UL << TCP_MTU_REDUCED_DEFERRED),
+};
+
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
{
return (struct tcp_sock *)sk;
@@ -427,4 +437,6 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp)
tp->saved_syn = NULL;
}
+struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk);
+
#endif /* _LINUX_TCP_H */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 511182a88e76..e275e98bdceb 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -28,6 +28,7 @@
#include <linux/of.h>
#include <linux/idr.h>
#include <linux/device.h>
+#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include <uapi/linux/thermal.h>
@@ -204,6 +205,7 @@ struct thermal_zone_device {
int id;
char type[THERMAL_NAME_LENGTH];
struct device device;
+ struct attribute_group trips_attribute_group;
struct thermal_attr *trip_temp_attrs;
struct thermal_attr *trip_type_attrs;
struct thermal_attr *trip_hyst_attrs;
diff --git a/include/linux/time.h b/include/linux/time.h
index 4cea09d94208..23f0f5ce3090 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -172,8 +172,6 @@ extern int do_setitimer(int which, struct itimerval *value,
struct itimerval *ovalue);
extern int do_getitimer(int which, struct itimerval *value);
-extern unsigned int alarm_setitimer(unsigned int seconds);
-
extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
struct tms;
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 09168c52ab64..361f8bf1429d 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -249,6 +249,7 @@ static inline u64 ktime_get_raw_ns(void)
extern u64 ktime_get_mono_fast_ns(void);
extern u64 ktime_get_raw_fast_ns(void);
+extern u64 ktime_get_boot_fast_ns(void);
/*
* Timespec interfaces utilizing the ktime based ones
diff --git a/include/linux/udp.h b/include/linux/udp.h
index d1fd8cd39478..c0f530809d1f 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -79,6 +79,9 @@ struct udp_sock {
int (*gro_complete)(struct sock *sk,
struct sk_buff *skb,
int nhoff);
+
+ /* This field is dirtied by udp_recvmsg() */
+ int forward_deficit;
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 6e22b544d039..d5aba1512b8b 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -125,7 +125,7 @@ static inline bool iter_is_iovec(const struct iov_iter *i)
*
* The ?: is just for type safety.
*/
-#define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & RW_MASK)
+#define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & (READ | WRITE))
/*
* Cap the iov_iter by given limit; note that the second argument is
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 4a29c75b146e..0a294e950df8 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -27,6 +27,7 @@
#include <linux/errno.h>
#include <linux/rbtree.h>
#include <linux/types.h>
+#include <linux/wait.h>
struct vm_area_struct;
struct mm_struct;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 0ecae0b1cd34..edf9b2cad277 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -75,7 +75,16 @@ struct vfio_iommu_driver_ops {
struct iommu_group *group);
void (*detach_group)(void *iommu_data,
struct iommu_group *group);
-
+ int (*pin_pages)(void *iommu_data, unsigned long *user_pfn,
+ int npage, int prot,
+ unsigned long *phys_pfn);
+ int (*unpin_pages)(void *iommu_data,
+ unsigned long *user_pfn, int npage);
+ int (*register_notifier)(void *iommu_data,
+ unsigned long *events,
+ struct notifier_block *nb);
+ int (*unregister_notifier)(void *iommu_data,
+ struct notifier_block *nb);
};
extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
@@ -92,6 +101,36 @@ extern int vfio_external_user_iommu_id(struct vfio_group *group);
extern long vfio_external_check_extension(struct vfio_group *group,
unsigned long arg);
+#define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long))
+
+extern int vfio_pin_pages(struct device *dev, unsigned long *user_pfn,
+ int npage, int prot, unsigned long *phys_pfn);
+extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn,
+ int npage);
+
+/* each type has independent events */
+enum vfio_notify_type {
+ VFIO_IOMMU_NOTIFY = 0,
+ VFIO_GROUP_NOTIFY = 1,
+};
+
+/* events for VFIO_IOMMU_NOTIFY */
+#define VFIO_IOMMU_NOTIFY_DMA_UNMAP BIT(0)
+
+/* events for VFIO_GROUP_NOTIFY */
+#define VFIO_GROUP_NOTIFY_SET_KVM BIT(0)
+
+extern int vfio_register_notifier(struct device *dev,
+ enum vfio_notify_type type,
+ unsigned long *required_events,
+ struct notifier_block *nb);
+extern int vfio_unregister_notifier(struct device *dev,
+ enum vfio_notify_type type,
+ struct notifier_block *nb);
+
+struct kvm;
+extern void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
+
/*
* Sub-module helpers
*/
@@ -103,6 +142,13 @@ extern struct vfio_info_cap_header *vfio_info_cap_add(
struct vfio_info_cap *caps, size_t size, u16 id, u16 version);
extern void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset);
+extern int vfio_info_add_capability(struct vfio_info_cap *caps,
+ int cap_type_id, void *cap_type);
+
+extern int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr,
+ int num_irqs, int max_irq_type,
+ size_t *data_size);
+
struct pci_dev;
#ifdef CONFIG_EEH
extern void vfio_spapr_pci_eeh_open(struct pci_dev *pdev);
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 1c912f85e041..66204007d7ac 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -58,7 +58,7 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
struct virtio_net_hdr *hdr,
bool little_endian)
{
- memset(hdr, 0, sizeof(*hdr));
+ memset(hdr, 0, sizeof(*hdr)); /* no info leak */
if (skb_is_gso(skb)) {
struct skb_shared_info *sinfo = skb_shinfo(skb);
@@ -98,4 +98,4 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
return 0;
}
-#endif /* _LINUX_VIRTIO_BYTEORDER */
+#endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 3d9d786a943c..d68edffbf142 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -82,6 +82,7 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
const void *caller);
extern void vfree(const void *addr);
+extern void vfree_atomic(const void *addr);
extern void *vmap(struct page **pages, unsigned int count,
unsigned long flags, pgprot_t prot);
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index fc6e22186405..d4f16cf6281c 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -119,18 +119,30 @@ struct delayed_work {
int cpu;
};
-/*
- * A struct for workqueue attributes. This can be used to change
- * attributes of an unbound workqueue.
+/**
+ * struct workqueue_attrs - A struct for workqueue attributes.
*
- * Unlike other fields, ->no_numa isn't a property of a worker_pool. It
- * only modifies how apply_workqueue_attrs() select pools and thus doesn't
- * participate in pool hash calculations or equality comparisons.
+ * This can be used to change attributes of an unbound workqueue.
*/
struct workqueue_attrs {
- int nice; /* nice level */
- cpumask_var_t cpumask; /* allowed CPUs */
- bool no_numa; /* disable NUMA affinity */
+ /**
+ * @nice: nice level
+ */
+ int nice;
+
+ /**
+ * @cpumask: allowed CPUs
+ */
+ cpumask_var_t cpumask;
+
+ /**
+ * @no_numa: disable NUMA affinity
+ *
+ * Unlike other fields, ``no_numa`` isn't a property of a worker_pool. It
+ * only modifies how :c:func:`apply_workqueue_attrs` select pools and thus
+ * doesn't participate in pool hash calculations or equality comparisons.
+ */
+ bool no_numa;
};
static inline struct delayed_work *to_delayed_work(struct work_struct *work)
@@ -272,7 +284,7 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
/*
* Workqueue flags and constants. For details, please refer to
- * Documentation/workqueue.txt.
+ * Documentation/core-api/workqueue.rst.
*/
enum {
WQ_UNBOUND = 1 << 1, /* not bound to any cpu */
@@ -370,7 +382,8 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
* @args...: args for @fmt
*
* Allocate a workqueue with the specified parameters. For detailed
- * information on WQ_* flags, please refer to Documentation/workqueue.txt.
+ * information on WQ_* flags, please refer to
+ * Documentation/core-api/workqueue.rst.
*
* The __lock_name macro dance is to guarantee that single lock_class_key
* doesn't end up with different namesm, which isn't allowed by lockdep.
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 797100e10010..c78f9f0920b5 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -9,6 +9,9 @@
#include <linux/fs.h>
#include <linux/flex_proportions.h>
#include <linux/backing-dev-defs.h>
+#include <linux/blk_types.h>
+
+struct bio;
DECLARE_PER_CPU(int, dirty_throttle_leaks);
@@ -100,6 +103,16 @@ struct writeback_control {
#endif
};
+static inline int wbc_to_write_flags(struct writeback_control *wbc)
+{
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ return REQ_SYNC;
+ else if (wbc->for_kupdate || wbc->for_background)
+ return REQ_BACKGROUND;
+
+ return 0;
+}
+
/*
* A wb_domain represents a domain that wb's (bdi_writeback's) belong to
* and are measured against each other in. There always is one global
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 2bb5deb0012e..7b0066814fa0 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -120,7 +120,7 @@ static inline void ww_acquire_init(struct ww_acquire_ctx *ctx,
struct ww_class *ww_class)
{
ctx->task = current;
- ctx->stamp = atomic_long_inc_return(&ww_class->stamp);
+ ctx->stamp = atomic_long_inc_return_relaxed(&ww_class->stamp);
ctx->acquired = 0;
#ifdef CONFIG_DEBUG_MUTEXES
ctx->ww_class = ww_class;
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 82f3c912a5b1..1d716449209e 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -36,13 +36,12 @@ struct tc_action {
struct tcf_t tcfa_tm;
struct gnet_stats_basic_packed tcfa_bstats;
struct gnet_stats_queue tcfa_qstats;
- struct gnet_stats_rate_est64 tcfa_rate_est;
+ struct net_rate_estimator __rcu *tcfa_rate_est;
spinlock_t tcfa_lock;
struct rcu_head tcfa_rcu;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
};
-#define tcf_act common.tcfa_act
#define tcf_head common.tcfa_head
#define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt
@@ -120,6 +119,8 @@ struct tc_action_ops {
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, const struct tc_action_ops *);
void (*stats_update)(struct tc_action *, u64, u32, u64);
+ int (*get_dev)(const struct tc_action *a, struct net *net,
+ struct net_device **mirred_dev);
};
struct tc_action_net {
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 0a1e21d7bce1..01487192f628 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -197,7 +197,7 @@ typedef struct {
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
-static inline bool bdaddr_type_is_valid(__u8 type)
+static inline bool bdaddr_type_is_valid(u8 type)
{
switch (type) {
case BDADDR_BREDR:
@@ -209,7 +209,7 @@ static inline bool bdaddr_type_is_valid(__u8 type)
return false;
}
-static inline bool bdaddr_type_is_le(__u8 type)
+static inline bool bdaddr_type_is_le(u8 type)
{
switch (type) {
case BDADDR_LE_PUBLIC:
@@ -279,15 +279,16 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
struct l2cap_ctrl {
- __u8 sframe:1,
+ u8 sframe:1,
poll:1,
final:1,
fcs:1,
sar:2,
super:2;
- __u16 reqseq;
- __u16 txseq;
- __u8 retries;
+
+ u16 reqseq;
+ u16 txseq;
+ u8 retries;
__le16 psm;
bdaddr_t bdaddr;
struct l2cap_chan *chan;
@@ -303,7 +304,7 @@ typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status,
#define HCI_REQ_SKB BIT(1)
struct hci_ctrl {
- __u16 opcode;
+ u16 opcode;
u8 req_flags;
u8 req_event;
union {
@@ -313,10 +314,10 @@ struct hci_ctrl {
};
struct bt_skb_cb {
- __u8 pkt_type;
- __u8 force_active;
- __u16 expect;
- __u8 incoming:1;
+ u8 pkt_type;
+ u8 force_active;
+ u16 expect;
+ u8 incoming:1;
union {
struct l2cap_ctrl l2cap;
struct hci_ctrl hci;
@@ -366,7 +367,7 @@ out:
return NULL;
}
-int bt_to_errno(__u16 code);
+int bt_to_errno(u16 code);
void hci_sock_set_flag(struct sock *sk, int nr);
void hci_sock_clear_flag(struct sock *sk, int nr);
diff --git a/include/net/bonding.h b/include/net/bonding.h
index f32f7ef8a23a..3c857778a6ca 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -681,7 +681,7 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
}
/* exported from bond_main.c */
-extern int bond_net_id;
+extern unsigned int bond_net_id;
extern const struct bond_parm_tbl bond_lacp_tbl[];
extern const struct bond_parm_tbl xmit_hashtype_tbl[];
extern const struct bond_parm_tbl arp_validate_tbl[];
diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h
index 2fbeb1313c0f..d73b849e29a6 100644
--- a/include/net/busy_poll.h
+++ b/include/net/busy_poll.h
@@ -58,10 +58,9 @@ static inline unsigned long busy_loop_end_time(void)
return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_busy_poll);
}
-static inline bool sk_can_busy_loop(struct sock *sk)
+static inline bool sk_can_busy_loop(const struct sock *sk)
{
- return sk->sk_ll_usec && sk->sk_napi_id &&
- !need_resched() && !signal_pending(current);
+ return sk->sk_ll_usec && sk->sk_napi_id && !signal_pending(current);
}
@@ -81,11 +80,6 @@ static inline void skb_mark_napi_id(struct sk_buff *skb,
skb->napi_id = napi->napi_id;
}
-/* used in the protocol hanlder to propagate the napi_id to the socket */
-static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
-{
- sk->sk_napi_id = skb->napi_id;
-}
#else /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long net_busy_loop_on(void)
@@ -108,10 +102,6 @@ static inline void skb_mark_napi_id(struct sk_buff *skb,
{
}
-static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
-{
-}
-
static inline bool busy_loop_timeout(unsigned long end_time)
{
return true;
@@ -123,4 +113,23 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock)
}
#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+/* used in the protocol hanlder to propagate the napi_id to the socket */
+static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ sk->sk_napi_id = skb->napi_id;
+#endif
+}
+
+/* variant used for unconnected sockets */
+static inline void sk_mark_napi_id_once(struct sock *sk,
+ const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ if (!sk->sk_napi_id)
+ sk->sk_napi_id = skb->napi_id;
+#endif
+}
+
#endif /* _LINUX_NET_BUSY_POLL_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 14b51d739c3b..814be4b4200c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -772,6 +772,30 @@ struct cfg80211_csa_settings {
};
/**
+ * struct iface_combination_params - input parameters for interface combinations
+ *
+ * Used to pass interface combination parameters
+ *
+ * @num_different_channels: the number of different channels we want
+ * to use for verification
+ * @radar_detect: a bitmap where each bit corresponds to a channel
+ * width where radar detection is needed, as in the definition of
+ * &struct ieee80211_iface_combination.@radar_detect_widths
+ * @iftype_num: array with the number of interfaces of each interface
+ * type. The index is the interface type as specified in &enum
+ * nl80211_iftype.
+ * @new_beacon_int: set this to the beacon interval of a new interface
+ * that's not operating yet, if such is to be checked as part of
+ * the verification
+ */
+struct iface_combination_params {
+ int num_different_channels;
+ u8 radar_detect;
+ int iftype_num[NUM_NL80211_IFTYPES];
+ u32 new_beacon_int;
+};
+
+/**
* enum station_parameters_apply_mask - station parameter values to apply
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
* @STATION_PARAM_APPLY_CAPABILITY: apply new capability
@@ -1761,9 +1785,11 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
- * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
- * Authentication transaction sequence number field.
- * @sae_data_len: Length of sae_data buffer in octets
+ * @auth_data: Fields and elements in Authentication frames. This contains
+ * the authentication frame body (non-IE and IE data), excluding the
+ * Authentication algorithm number, i.e., starting at the Authentication
+ * transaction sequence number field.
+ * @auth_data_len: Length of auth_data buffer in octets
*/
struct cfg80211_auth_request {
struct cfg80211_bss *bss;
@@ -1772,8 +1798,8 @@ struct cfg80211_auth_request {
enum nl80211_auth_type auth_type;
const u8 *key;
u8 key_len, key_idx;
- const u8 *sae_data;
- size_t sae_data_len;
+ const u8 *auth_data;
+ size_t auth_data_len;
};
/**
@@ -1814,6 +1840,12 @@ enum cfg80211_assoc_req_flags {
* @ht_capa_mask: The bits of ht_capa which are to be used.
* @vht_capa: VHT capability override
* @vht_capa_mask: VHT capability mask indicating which fields to use
+ * @fils_kek: FILS KEK for protecting (Re)Association Request/Response frame or
+ * %NULL if FILS is not used.
+ * @fils_kek_len: Length of fils_kek in octets
+ * @fils_nonces: FILS nonces (part of AAD) for protecting (Re)Association
+ * Request/Response frame or %NULL if FILS is not used. This field starts
+ * with 16 octets of STA Nonce followed by 16 octets of AP Nonce.
*/
struct cfg80211_assoc_request {
struct cfg80211_bss *bss;
@@ -1825,6 +1857,9 @@ struct cfg80211_assoc_request {
struct ieee80211_ht_cap ht_capa;
struct ieee80211_ht_cap ht_capa_mask;
struct ieee80211_vht_cap vht_capa, vht_capa_mask;
+ const u8 *fils_kek;
+ size_t fils_kek_len;
+ const u8 *fils_nonces;
};
/**
@@ -2016,6 +2051,18 @@ struct cfg80211_connect_params {
};
/**
+ * enum cfg80211_connect_params_changed - Connection parameters being updated
+ *
+ * This enum provides information of all connect parameters that
+ * have to be updated as part of update_connect_params() call.
+ *
+ * @UPDATE_ASSOC_IES: Indicates whether association request IEs are updated
+ */
+enum cfg80211_connect_params_changed {
+ UPDATE_ASSOC_IES = BIT(0),
+};
+
+/**
* enum wiphy_params_flags - set_wiphy_params bitfield values
* @WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
* @WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed
@@ -2536,9 +2583,18 @@ struct cfg80211_nan_func {
* cases, the result of roaming is indicated with a call to
* cfg80211_roamed() or cfg80211_roamed_bss().
* (invoked with the wireless_dev mutex held)
- * @disconnect: Disconnect from the BSS/ESS. Once done, call
- * cfg80211_disconnected().
+ * @update_connect_params: Update the connect parameters while connected to a
+ * BSS. The updated parameters can be used by driver/firmware for
+ * subsequent BSS selection (roaming) decisions and to form the
+ * Authentication/(Re)Association Request frames. This call does not
+ * request an immediate disassociation or reassociation with the current
+ * BSS, i.e., this impacts only subsequent (re)associations. The bits in
+ * changed are defined in &enum cfg80211_connect_params_changed.
* (invoked with the wireless_dev mutex held)
+ * @disconnect: Disconnect from the BSS/ESS or stop connection attempts if
+ * connection is in progress. Once done, call cfg80211_disconnected() in
+ * case connection was already established (invoked with the
+ * wireless_dev mutex held), otherwise call cfg80211_connect_timeout().
*
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
@@ -2706,6 +2762,8 @@ struct cfg80211_nan_func {
* @nan_change_conf: changes NAN configuration. The changed parameters must
* be specified in @changes (using &enum cfg80211_nan_conf_changes);
* All other parameters must be ignored.
+ *
+ * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2820,6 +2878,10 @@ struct cfg80211_ops {
int (*connect)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme);
+ int (*update_connect_params)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_connect_params *sme,
+ u32 changed);
int (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code);
@@ -2982,6 +3044,10 @@ struct cfg80211_ops {
struct wireless_dev *wdev,
struct cfg80211_nan_conf *conf,
u32 changes);
+
+ int (*set_multicast_to_unicast)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const bool enabled);
};
/*
@@ -3080,6 +3146,12 @@ struct ieee80211_iface_limit {
* only in special cases.
* @radar_detect_widths: bitmap of channel widths supported for radar detection
* @radar_detect_regions: bitmap of regions supported for radar detection
+ * @beacon_int_min_gcd: This interface combination supports different
+ * beacon intervals.
+ * = 0 - all beacon intervals for different interface must be same.
+ * > 0 - any beacon interval for the interface part of this combination AND
+ * *GCD* of all beacon intervals from beaconing interfaces of this
+ * combination must be greater or equal to this value.
*
* With this structure the driver can describe which interface
* combinations it supports concurrently.
@@ -3145,6 +3217,7 @@ struct ieee80211_iface_combination {
bool beacon_int_infra_match;
u8 radar_detect_widths;
u8 radar_detect_regions;
+ u32 beacon_int_min_gcd;
};
struct ieee80211_txrx_stypes {
@@ -3752,8 +3825,8 @@ struct cfg80211_cached_keys;
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
* @address: The address for this device, valid only if @netdev is %NULL
- * @p2p_started: true if this is a P2P Device that has been started
- * @nan_started: true if this is a NAN interface that has been started
+ * @is_running: true if this is a non-netdev device that has been started, e.g.
+ * the P2P Device.
* @cac_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered.
* @cac_time_ms: CAC time in ms
@@ -3785,7 +3858,7 @@ struct wireless_dev {
struct mutex mtx;
- bool use_4addr, p2p_started, nan_started;
+ bool use_4addr, is_running;
u8 address[ETH_ALEN] __aligned(sizeof(u16));
@@ -3842,6 +3915,13 @@ static inline u8 *wdev_address(struct wireless_dev *wdev)
return wdev->address;
}
+static inline bool wdev_running(struct wireless_dev *wdev)
+{
+ if (wdev->netdev)
+ return netif_running(wdev->netdev);
+ return wdev->is_running;
+}
+
/**
* wdev_priv - return wiphy priv from wireless_dev
*
@@ -4163,6 +4243,27 @@ static inline const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
}
/**
+ * cfg80211_find_ext_ie - find information element with EID Extension in data
+ *
+ * @ext_eid: element ID Extension
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the extended element ID could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data), or a pointer to the first byte of the requested
+ * element, that is the byte containing the element ID.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data.
+ */
+static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
+{
+ return cfg80211_find_ie_match(WLAN_EID_EXTENSION, ies, len,
+ &ext_eid, 1, 2);
+}
+
+/**
* cfg80211_find_vendor_ie - find vendor specific information element in data
*
* @oui: vendor OUI
@@ -4562,7 +4663,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
* moves to cfg80211 in this call
* @buf: authentication frame (header + body)
* @len: length of the frame data
- * @uapsd_queues: bitmap of ACs configured to uapsd. -1 if n/a.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Same format
+ * as the AC bitmap in the QoS info field
*
* After being asked to associate via cfg80211_ops::assoc() the driver must
* call either this function or cfg80211_auth_timeout().
@@ -4584,6 +4686,17 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss);
/**
+ * cfg80211_abandon_assoc - notify cfg80211 of abandoned association attempt
+ * @dev: network device
+ * @bss: The BSS entry with which association was abandoned.
+ *
+ * Call this whenever - for reasons reported through other API, like deauth RX,
+ * an association attempt was abandoned.
+ * This function may sleep. The caller must hold the corresponding wdev's mutex.
+ */
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss);
+
+/**
* cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
* @dev: network device
* @buf: 802.11 frame (header + body)
@@ -5598,36 +5711,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
* cfg80211_check_combinations - check interface combinations
*
* @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- * to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- * width where radar detection is needed, as in the definition of
- * &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- * type. The index is the interface type as specified in &enum
- * nl80211_iftype.
+ * @params: the interface combinations parameter
*
* This function can be called by the driver to check whether a
* combination of interfaces and their types are allowed according to
* the interface combinations.
*/
int cfg80211_check_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES]);
+ struct iface_combination_params *params);
/**
* cfg80211_iter_combinations - iterate over matching combinations
*
* @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- * to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- * width where radar detection is needed, as in the definition of
- * &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- * type. The index is the interface type as specified in &enum
- * nl80211_iftype.
+ * @params: the interface combinations parameter
* @iter: function to call for each matching combination
* @data: pointer to pass to iter function
*
@@ -5636,9 +5733,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
* purposes.
*/
int cfg80211_iter_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
+ struct iface_combination_params *params,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data);
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 211bd3c37028..d29e5fc82582 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -92,6 +92,8 @@ struct devlink_ops {
int (*eswitch_mode_get)(struct devlink *devlink, u16 *p_mode);
int (*eswitch_mode_set)(struct devlink *devlink, u16 mode);
+ int (*eswitch_inline_mode_get)(struct devlink *devlink, u8 *p_inline_mode);
+ int (*eswitch_inline_mode_set)(struct devlink *devlink, u8 inline_mode);
};
static inline void *devlink_priv(struct devlink *devlink)
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
index 6965c8f68ade..701fc814d0af 100644
--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -115,6 +115,7 @@ static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb
static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
__be32 daddr,
__u8 tos, __u8 ttl,
+ __be16 tp_dst,
__be16 flags,
__be64 tunnel_id,
int md_size)
@@ -127,7 +128,7 @@ static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
ip_tunnel_key_init(&tun_dst->u.tun_info.key,
saddr, daddr, tos, ttl,
- 0, 0, 0, tunnel_id, flags);
+ 0, 0, tp_dst, tunnel_id, flags);
return tun_dst;
}
@@ -139,12 +140,13 @@ static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
const struct iphdr *iph = ip_hdr(skb);
return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
- flags, tunnel_id, md_size);
+ 0, flags, tunnel_id, md_size);
}
static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__u8 tos, __u8 ttl,
+ __be16 tp_dst,
__be32 label,
__be16 flags,
__be64 tunnel_id,
@@ -162,7 +164,7 @@ static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *sad
info->key.tun_flags = flags;
info->key.tun_id = tunnel_id;
info->key.tp_src = 0;
- info->key.tp_dst = 0;
+ info->key.tp_dst = tp_dst;
info->key.u.ipv6.src = *saddr;
info->key.u.ipv6.dst = *daddr;
@@ -183,7 +185,7 @@ static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
ipv6_get_dsfield(ip6h), ip6h->hop_limit,
- ip6_flowlabel(ip6h), flags, tunnel_id,
+ 0, ip6_flowlabel(ip6h), flags, tunnel_id,
md_size);
}
#endif /* __NET_DST_METADATA_H */
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 456e4a6006ab..8dbfdf728cd8 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -8,6 +8,11 @@
#include <net/flow.h>
#include <net/rtnetlink.h>
+struct fib_kuid_range {
+ kuid_t start;
+ kuid_t end;
+};
+
struct fib_rule {
struct list_head list;
int iifindex;
@@ -30,6 +35,7 @@ struct fib_rule {
int suppress_prefixlen;
char iifname[IFNAMSIZ];
char oifname[IFNAMSIZ];
+ struct fib_kuid_range uid_range;
struct rcu_head rcu;
};
@@ -92,7 +98,8 @@ struct fib_rules_ops {
[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
[FRA_GOTO] = { .type = NLA_U32 }, \
- [FRA_L3MDEV] = { .type = NLA_U8 }
+ [FRA_L3MDEV] = { .type = NLA_U8 }, \
+ [FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) }
static inline void fib_rule_get(struct fib_rule *rule)
{
diff --git a/include/net/flow.h b/include/net/flow.h
index 035aa7716967..6984f1913dc1 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -11,6 +11,7 @@
#include <linux/in6.h>
#include <linux/atomic.h>
#include <net/flow_dissector.h>
+#include <linux/uidgid.h>
/*
* ifindex generation is per-net namespace, and loopback is
@@ -37,6 +38,7 @@ struct flowi_common {
#define FLOWI_FLAG_SKIP_NH_OIF 0x04
__u32 flowic_secid;
struct flowi_tunnel flowic_tun_key;
+ kuid_t flowic_uid;
};
union flowi_uli {
@@ -74,6 +76,7 @@ struct flowi4 {
#define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid
#define flowi4_tun_key __fl_common.flowic_tun_key
+#define flowi4_uid __fl_common.flowic_uid
/* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr;
@@ -93,7 +96,8 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
__u32 mark, __u8 tos, __u8 scope,
__u8 proto, __u8 flags,
__be32 daddr, __be32 saddr,
- __be16 dport, __be16 sport)
+ __be16 dport, __be16 sport,
+ kuid_t uid)
{
fl4->flowi4_oif = oif;
fl4->flowi4_iif = LOOPBACK_IFINDEX;
@@ -104,6 +108,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0;
fl4->flowi4_tun_key.tun_id = 0;
+ fl4->flowi4_uid = uid;
fl4->daddr = daddr;
fl4->saddr = saddr;
fl4->fl4_dport = dport;
@@ -131,6 +136,7 @@ struct flowi6 {
#define flowi6_flags __fl_common.flowic_flags
#define flowi6_secid __fl_common.flowic_secid
#define flowi6_tun_key __fl_common.flowic_tun_key
+#define flowi6_uid __fl_common.flowic_uid
struct in6_addr daddr;
struct in6_addr saddr;
/* Note: flowi6_tos is encoded in flowlabel, too. */
@@ -176,6 +182,7 @@ struct flowi {
#define flowi_flags u.__fl_common.flowic_flags
#define flowi_secid u.__fl_common.flowic_secid
#define flowi_tun_key u.__fl_common.flowic_tun_key
+#define flowi_uid u.__fl_common.flowic_uid
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
@@ -239,6 +246,7 @@ struct flow_cache_object *flow_cache_lookup(struct net *net,
void *ctx);
int flow_cache_init(struct net *net);
void flow_cache_fini(struct net *net);
+void flow_cache_hp_init(void);
void flow_cache_flush(struct net *net);
void flow_cache_flush_deferred(struct net *net);
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index d9534927d93b..d896a33e00d4 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -104,6 +104,22 @@ struct flow_dissector_key_ports {
};
};
+/**
+ * flow_dissector_key_icmp:
+ * @ports: type and code of ICMP header
+ * icmp: ICMP type (high) and code (low)
+ * type: ICMP type
+ * code: ICMP code
+ */
+struct flow_dissector_key_icmp {
+ union {
+ __be16 icmp;
+ struct {
+ u8 type;
+ u8 code;
+ };
+ };
+};
/**
* struct flow_dissector_key_eth_addrs:
@@ -122,12 +138,18 @@ enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
+ FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
FLOW_DISSECTOR_KEY_TIPC_ADDRS, /* struct flow_dissector_key_tipc_addrs */
FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
FLOW_DISSECTOR_KEY_FLOW_LABEL, /* struct flow_dissector_key_flow_tags */
FLOW_DISSECTOR_KEY_GRE_KEYID, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_MPLS_ENTROPY, /* struct flow_dissector_key_keyid */
+ FLOW_DISSECTOR_KEY_ENC_KEYID, /* struct flow_dissector_key_keyid */
+ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
+ FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
+ FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */
+ FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_MAX,
};
diff --git a/include/net/flowcache.h b/include/net/flowcache.h
index c8f665ec6e0d..9caf3bfc8d2d 100644
--- a/include/net/flowcache.h
+++ b/include/net/flowcache.h
@@ -17,7 +17,7 @@ struct flow_cache_percpu {
struct flow_cache {
u32 hash_shift;
struct flow_cache_percpu __percpu *percpu;
- struct notifier_block hotcpu_notifier;
+ struct hlist_node node;
int low_watermark;
int high_watermark;
struct timer_list rnd_timer;
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index 231e121cc7d9..8b7aa370e7a4 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -11,6 +11,8 @@ struct gnet_stats_basic_cpu {
struct u64_stats_sync syncp;
};
+struct net_rate_estimator;
+
struct gnet_dump {
spinlock_t * lock;
struct sk_buff * skb;
@@ -42,8 +44,7 @@ void __gnet_stats_copy_basic(const seqcount_t *running,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
int gnet_stats_copy_rate_est(struct gnet_dump *d,
- const struct gnet_stats_basic_packed *b,
- struct gnet_stats_rate_est64 *r);
+ struct net_rate_estimator __rcu **ptr);
int gnet_stats_copy_queue(struct gnet_dump *d,
struct gnet_stats_queue __percpu *cpu_q,
struct gnet_stats_queue *q, __u32 qlen);
@@ -53,16 +54,16 @@ int gnet_stats_finish_copy(struct gnet_dump *d);
int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
- struct gnet_stats_rate_est64 *rate_est,
+ struct net_rate_estimator __rcu **rate_est,
spinlock_t *stats_lock,
seqcount_t *running, struct nlattr *opt);
-void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
- struct gnet_stats_rate_est64 *rate_est);
+void gen_kill_estimator(struct net_rate_estimator __rcu **ptr);
int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
- struct gnet_stats_rate_est64 *rate_est,
+ struct net_rate_estimator __rcu **ptr,
spinlock_t *stats_lock,
seqcount_t *running, struct nlattr *opt);
-bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
- const struct gnet_stats_rate_est64 *rate_est);
+bool gen_estimator_active(struct net_rate_estimator __rcu **ptr);
+bool gen_estimator_read(struct net_rate_estimator __rcu **ptr,
+ struct gnet_stats_rate_est64 *sample);
#endif
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 8d4608ce8716..a34275be3600 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -20,7 +20,7 @@ struct genl_info;
/**
* struct genl_family - generic netlink family
- * @id: protocol family idenfitier
+ * @id: protocol family identifier (private)
* @hdrsize: length of user specific header in bytes
* @name: name of family
* @version: protocol version
@@ -39,16 +39,16 @@ struct genl_info;
* Note that unbind() will not be called symmetrically if the
* generic netlink family is removed while there are still open
* sockets.
- * @attrbuf: buffer to store parsed attributes
- * @family_list: family list
- * @mcgrps: multicast groups used by this family (private)
- * @n_mcgrps: number of multicast groups (private)
+ * @attrbuf: buffer to store parsed attributes (private)
+ * @mcgrps: multicast groups used by this family
+ * @n_mcgrps: number of multicast groups
* @mcgrp_offset: starting number of multicast group IDs in this family
- * @ops: the operations supported by this family (private)
- * @n_ops: number of operations supported by this family (private)
+ * (private)
+ * @ops: the operations supported by this family
+ * @n_ops: number of operations supported by this family
*/
struct genl_family {
- unsigned int id;
+ int id; /* private */
unsigned int hdrsize;
char name[GENL_NAMSIZ];
unsigned int version;
@@ -64,15 +64,16 @@ struct genl_family {
int (*mcast_bind)(struct net *net, int group);
void (*mcast_unbind)(struct net *net, int group);
struct nlattr ** attrbuf; /* private */
- const struct genl_ops * ops; /* private */
- const struct genl_multicast_group *mcgrps; /* private */
- unsigned int n_ops; /* private */
- unsigned int n_mcgrps; /* private */
+ const struct genl_ops * ops;
+ const struct genl_multicast_group *mcgrps;
+ unsigned int n_ops;
+ unsigned int n_mcgrps;
unsigned int mcgrp_offset; /* private */
- struct list_head family_list; /* private */
struct module *module;
};
+struct nlattr **genl_family_attrbuf(const struct genl_family *family);
+
/**
* struct genl_info - receiving information
* @snd_seq: sending sequence number
@@ -130,64 +131,13 @@ struct genl_ops {
u8 flags;
};
-int __genl_register_family(struct genl_family *family);
-
-static inline int genl_register_family(struct genl_family *family)
-{
- family->module = THIS_MODULE;
- return __genl_register_family(family);
-}
-
-/**
- * genl_register_family_with_ops - register a generic netlink family with ops
- * @family: generic netlink family
- * @ops: operations to be registered
- * @n_ops: number of elements to register
- *
- * Registers the specified family and operations from the specified table.
- * Only one family may be registered with the same family name or identifier.
- *
- * The family id may equal GENL_ID_GENERATE causing an unique id to
- * be automatically generated and assigned.
- *
- * Either a doit or dumpit callback must be specified for every registered
- * operation or the function will fail. Only one operation structure per
- * command identifier may be registered.
- *
- * See include/net/genetlink.h for more documenation on the operations
- * structure.
- *
- * Return 0 on success or a negative error code.
- */
-static inline int
-_genl_register_family_with_ops_grps(struct genl_family *family,
- const struct genl_ops *ops, size_t n_ops,
- const struct genl_multicast_group *mcgrps,
- size_t n_mcgrps)
-{
- family->module = THIS_MODULE;
- family->ops = ops;
- family->n_ops = n_ops;
- family->mcgrps = mcgrps;
- family->n_mcgrps = n_mcgrps;
- return __genl_register_family(family);
-}
-
-#define genl_register_family_with_ops(family, ops) \
- _genl_register_family_with_ops_grps((family), \
- (ops), ARRAY_SIZE(ops), \
- NULL, 0)
-#define genl_register_family_with_ops_groups(family, ops, grps) \
- _genl_register_family_with_ops_grps((family), \
- (ops), ARRAY_SIZE(ops), \
- (grps), ARRAY_SIZE(grps))
-
-int genl_unregister_family(struct genl_family *family);
-void genl_notify(struct genl_family *family, struct sk_buff *skb,
+int genl_register_family(struct genl_family *family);
+int genl_unregister_family(const struct genl_family *family);
+void genl_notify(const struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
- struct genl_family *family, int flags, u8 cmd);
+ const struct genl_family *family, int flags, u8 cmd);
/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
@@ -196,8 +146,8 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
*
* Returns pointer to netlink header.
*/
-static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
- struct genl_family *family)
+static inline struct nlmsghdr *
+genlmsg_nlhdr(void *user_hdr, const struct genl_family *family)
{
return (struct nlmsghdr *)((char *)user_hdr -
family->hdrsize -
@@ -233,7 +183,7 @@ static inline int genlmsg_parse(const struct nlmsghdr *nlh,
*/
static inline void genl_dump_check_consistent(struct netlink_callback *cb,
void *user_hdr,
- struct genl_family *family)
+ const struct genl_family *family)
{
nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
}
@@ -250,7 +200,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb,
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info,
- struct genl_family *family,
+ const struct genl_family *family,
int flags, u8 cmd)
{
return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
@@ -287,7 +237,7 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
-static inline int genlmsg_multicast_netns(struct genl_family *family,
+static inline int genlmsg_multicast_netns(const struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
@@ -305,7 +255,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
-static inline int genlmsg_multicast(struct genl_family *family,
+static inline int genlmsg_multicast(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
@@ -323,7 +273,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
*
* This function must hold the RTNL or rcu_read_lock().
*/
-int genlmsg_multicast_allns(struct genl_family *family,
+int genlmsg_multicast_allns(const struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);
@@ -407,8 +357,9 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
-static inline int genl_set_err(struct genl_family *family, struct net *net,
- u32 portid, u32 group, int code)
+static inline int genl_set_err(const struct genl_family *family,
+ struct net *net, u32 portid,
+ u32 group, int code)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
@@ -416,7 +367,7 @@ static inline int genl_set_err(struct genl_family *family, struct net *net,
return netlink_set_err(net->genl_sock, portid, group, code);
}
-static inline int genl_has_listeners(struct genl_family *family,
+static inline int genl_has_listeners(const struct genl_family *family,
struct net *net, unsigned int group)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index ba07b9d8ed63..d0e7e3f8e67a 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -333,9 +333,9 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS 0x0003
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK 0x00F0
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU 0x0000
-#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0010
+#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0010
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU 0x0020
-#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0030
+#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0030
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN 0x00F0
#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT 0x00
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index b0576cb2ab25..0fa4c324b713 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -55,6 +55,7 @@ struct inet6_ifaddr {
__u8 stable_privacy_retry;
__u16 scope;
+ __u64 dad_nonce;
unsigned long cstamp; /* created timestamp */
unsigned long tstamp; /* updated timestamp */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 197a30d221e9..146054ceea8e 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -289,11 +289,6 @@ static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
}
-static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
-{
- return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
-}
-
static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 236a81034fef..c9cff977a7fb 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -228,6 +228,7 @@ struct inet_sock {
#define IP_CMSG_PASSSEC BIT(5)
#define IP_CMSG_ORIGDSTADDR BIT(6)
#define IP_CMSG_CHECKSUM BIT(7)
+#define IP_CMSG_RECVFRAGSIZE BIT(8)
/**
* sk_to_full_sk - Access to a full socket
diff --git a/include/net/ip.h b/include/net/ip.h
index d3a107850a41..ab6761a7c883 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -178,6 +178,7 @@ struct ip_reply_arg {
/* -1 if not needed */
int bound_dev_if;
u8 tos;
+ kuid_t uid;
};
#define IP_REPLY_ARG_NOSRCCHECK 1
@@ -577,7 +578,8 @@ int ip_options_rcv_srr(struct sk_buff *skb);
*/
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
-void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int tlen, int offset);
+void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb, int tlen, int offset);
int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
struct ipcm_cookie *ipc, bool allow_ipv6);
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
@@ -599,7 +601,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
{
- ip_cmsg_recv_offset(msg, skb, 0, 0);
+ ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
}
bool icmp_global_allow(void);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index f83e78d071a3..9dc2c182a263 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -140,9 +140,10 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr);
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
- u32 mark);
+ u32 mark, kuid_t uid);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+ kuid_t uid);
void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
u32 mark);
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index f390c3bb05c5..5f376af377c7 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -221,7 +221,8 @@ enum fib_event_type {
FIB_EVENT_RULE_DEL,
};
-int register_fib_notifier(struct notifier_block *nb);
+int register_fib_notifier(struct notifier_block *nb,
+ void (*cb)(struct notifier_block *nb));
int unregister_fib_notifier(struct notifier_block *nb);
int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
struct fib_notifier_info *info);
@@ -397,6 +398,11 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
void free_fib_info(struct fib_info *fi);
+static inline void fib_info_hold(struct fib_info *fi)
+{
+ atomic_inc(&fi->fib_clntref);
+}
+
static inline void fib_info_put(struct fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 59557c07904b..e893fe43dd13 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -129,7 +129,7 @@ struct ip_tunnel {
#endif
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
unsigned int prl_count; /* # of entries in PRL */
- int ip_tnl_net_id;
+ unsigned int ip_tnl_net_id;
struct gro_cells gro_cells;
bool collect_md;
bool ignore_df;
@@ -248,7 +248,7 @@ void ip_tunnel_uninit(struct net_device *dev);
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
struct net *ip_tunnel_get_link_net(const struct net_device *dev);
int ip_tunnel_get_iflink(const struct net_device *dev);
-int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
+int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname);
void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
@@ -275,7 +275,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p);
int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p);
-void ip_tunnel_setup(struct net_device *dev, int net_id);
+void ip_tunnel_setup(struct net_device *dev, unsigned int net_id);
struct ip_tunnel_encap_ops {
size_t (*encap_hlen)(struct ip_tunnel_encap *e);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f11ca837361b..487e57391664 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -932,7 +932,8 @@ int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
*/
void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
- u8 *proto, struct in6_addr **daddr_p);
+ u8 *proto, struct in6_addr **daddr_p,
+ struct in6_addr *saddr);
void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto);
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index ea3f80f58fd6..d4c1c75b8862 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -24,11 +24,11 @@ enum {
struct lwtunnel_state {
__u16 type;
__u16 flags;
+ __u16 headroom;
atomic_t refcnt;
int (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*orig_input)(struct sk_buff *);
- int len;
- __u16 headroom;
+ struct rcu_head rcu;
__u8 data[0];
};
@@ -36,6 +36,7 @@ struct lwtunnel_encap_ops {
int (*build_state)(struct net_device *dev, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts);
+ void (*destroy_state)(struct lwtunnel_state *lws);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*input)(struct sk_buff *skb);
int (*fill_encap)(struct sk_buff *skb,
@@ -46,10 +47,7 @@ struct lwtunnel_encap_ops {
};
#ifdef CONFIG_LWTUNNEL
-static inline void lwtstate_free(struct lwtunnel_state *lws)
-{
- kfree(lws);
-}
+void lwtstate_free(struct lwtunnel_state *lws);
static inline struct lwtunnel_state *
lwtstate_get(struct lwtunnel_state *lws)
@@ -96,7 +94,8 @@ static inline bool lwtunnel_xmit_redirect(struct lwtunnel_state *lwtstate)
static inline unsigned int lwtunnel_headroom(struct lwtunnel_state *lwtstate,
unsigned int mtu)
{
- if (lwtunnel_xmit_redirect(lwtstate) && lwtstate->headroom < mtu)
+ if ((lwtunnel_xmit_redirect(lwtstate) ||
+ lwtunnel_output_redirect(lwtstate)) && lwtstate->headroom < mtu)
return lwtstate->headroom;
return 0;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e2dba93e374f..5345d358a510 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1442,7 +1442,7 @@ enum ieee80211_vif_flags {
struct ieee80211_vif {
enum nl80211_iftype type;
struct ieee80211_bss_conf bss_conf;
- u8 addr[ETH_ALEN];
+ u8 addr[ETH_ALEN] __aligned(2);
bool p2p;
bool csa_active;
bool mu_mimo_owner;
@@ -1749,7 +1749,8 @@ struct ieee80211_sta_rates {
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void \*), size is determined in hw information.
* @uapsd_queues: bitmap of queues configured for uapsd. Only valid
- * if wme is supported.
+ * if wme is supported. The bits order is like in
+ * IEEE80211_WMM_IE_STA_QOSINFO_AC_*.
* @max_sp: max Service Period. Only valid if wme is supported.
* @bandwidth: current bandwidth the station can receive with
* @rx_nss: in HT/VHT, the maximum number of spatial streams the
@@ -2029,6 +2030,10 @@ struct ieee80211_txq {
* drivers, mac80211 packet loss mechanism will not be triggered and driver
* is completely depending on firmware event for station kickout.
*
+ * @IEEE80211_HW_SUPPORTS_TX_FRAG: Hardware does fragmentation by itself.
+ * The stack will not do fragmentation.
+ * The callback for @set_frag_threshold should be set as well.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2070,6 +2075,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_TX_AMSDU,
IEEE80211_HW_TX_FRAG_LIST,
IEEE80211_HW_REPORTS_LOW_ACK,
+ IEEE80211_HW_SUPPORTS_TX_FRAG,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
@@ -3098,8 +3104,9 @@ enum ieee80211_reconfig_type {
* The callback must be atomic.
*
* @set_frag_threshold: Configuration of fragmentation threshold. Assign this
- * if the device does fragmentation by itself; if this callback is
- * implemented then the stack will not do fragmentation.
+ * if the device does fragmentation by itself. Note that to prevent the
+ * stack from doing fragmentation IEEE80211_HW_SUPPORTS_TX_FRAG
+ * should be set as well.
* The callback can sleep.
*
* @set_rts_threshold: Configuration of RTS threshold (if device needs it)
@@ -4092,6 +4099,10 @@ void ieee80211_sta_pspoll(struct ieee80211_sta *sta);
* This must be used in conjunction with ieee80211_sta_ps_transition()
* and possibly ieee80211_sta_pspoll(); calls to all three must be
* serialized.
+ * %IEEE80211_NUM_TIDS can be passed as the tid if the tid is unknown.
+ * In this case, mac80211 will not check that this tid maps to an AC
+ * that is trigger enabled and assume that the caller did the proper
+ * checks.
*/
void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, u8 tid);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index be1fe2283254..d562a2fe4860 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -31,6 +31,7 @@ enum {
ND_OPT_PREFIX_INFO = 3, /* RFC2461 */
ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */
ND_OPT_MTU = 5, /* RFC2461 */
+ ND_OPT_NONCE = 14, /* RFC7527 */
__ND_OPT_ARRAY_MAX,
ND_OPT_ROUTE_INFO = 24, /* RFC4191 */
ND_OPT_RDNSS = 25, /* RFC5006 */
@@ -121,6 +122,7 @@ struct ndisc_options {
#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
+#define nd_opts_nonce nd_opt_array[ND_OPT_NONCE]
#define nd_802154_opts_src_lladdr nd_802154_opt_array[ND_OPT_SOURCE_LL_ADDR]
#define nd_802154_opts_tgt_lladdr nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR]
@@ -398,7 +400,8 @@ void ndisc_cleanup(void);
int ndisc_rcv(struct sk_buff *skb);
void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
- const struct in6_addr *daddr, const struct in6_addr *saddr);
+ const struct in6_addr *daddr, const struct in6_addr *saddr,
+ u64 nonce);
void ndisc_send_rs(struct net_device *dev,
const struct in6_addr *saddr, const struct in6_addr *daddr);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 0940598c002f..af8fe8a909dc 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -291,7 +291,7 @@ struct pernet_operations {
int (*init)(struct net *net);
void (*exit)(struct net *net);
void (*exit_batch)(struct list_head *net_exit_list);
- int *id;
+ unsigned int *id;
size_t size;
};
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 981c327374da..919e4e8af327 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -15,6 +15,15 @@ extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4;
+#endif
int nf_conntrack_ipv4_compat_init(void);
void nf_conntrack_ipv4_compat_fini(void);
diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
index f01ef208dff6..db405f70e538 100644
--- a/include/net/netfilter/ipv4/nf_defrag_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
@@ -1,6 +1,7 @@
#ifndef _NF_DEFRAG_IPV4_H
#define _NF_DEFRAG_IPV4_H
-void nf_defrag_ipv4_enable(void);
+struct net;
+int nf_defrag_ipv4_enable(struct net *);
#endif /* _NF_DEFRAG_IPV4_H */
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index a4c993685795..eaea968f8657 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -6,6 +6,15 @@ extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6;
+#endif
#include <linux/sysctl.h>
extern struct ctl_table nf_ct_ipv6_sysctl_table[];
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index ddf162f7966f..7664efe37974 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -1,7 +1,8 @@
#ifndef _NF_DEFRAG_IPV6_H
#define _NF_DEFRAG_IPV6_H
-void nf_defrag_ipv6_enable(void);
+struct net;
+int nf_defrag_ipv6_enable(struct net *);
int nf_ct_frag6_init(void);
void nf_ct_frag6_cleanup(void);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index d9d52c020a70..5916aa9ab3f0 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -181,6 +181,10 @@ static inline void nf_ct_put(struct nf_conn *ct)
int nf_ct_l3proto_try_module_get(unsigned short l3proto);
void nf_ct_l3proto_module_put(unsigned short l3proto);
+/* load module; enable/disable conntrack in this namespace */
+int nf_ct_netns_get(struct net *net, u8 nfproto);
+void nf_ct_netns_put(struct net *net, u8 nfproto);
+
/*
* Allocate a hashtable of hlist_head (if nulls == 0),
* or hlist_nulls_head (if nulls == 1)
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 8992e4229da9..e01559b4d781 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -52,6 +52,10 @@ struct nf_conntrack_l3proto {
int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);
+ /* Called when netns wants to use connection tracking */
+ int (*net_ns_get)(struct net *);
+ void (*net_ns_put)(struct net *);
+
/*
* Calculate size of tuple nlattr
*/
@@ -63,18 +67,24 @@ struct nf_conntrack_l3proto {
size_t nla_size;
- /* Init l3proto pernet data */
- int (*init_net)(struct net *net);
-
/* Module (if any) which this is connected to. */
struct module *me;
};
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
+#ifdef CONFIG_SYSCTL
/* Protocol pernet registration. */
int nf_ct_l3proto_pernet_register(struct net *net,
struct nf_conntrack_l3proto *proto);
+#else
+static inline int nf_ct_l3proto_pernet_register(struct net *n,
+ struct nf_conntrack_l3proto *p)
+{
+ return 0;
+}
+#endif
+
void nf_ct_l3proto_pernet_unregister(struct net *net,
struct nf_conntrack_l3proto *proto);
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index de629f1520df..e7b836590f0b 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -98,7 +98,7 @@ struct nf_conntrack_l4proto {
const struct nla_policy *nla_policy;
} ctnl_timeout;
#endif
- int *net_id;
+ unsigned int *net_id;
/* Init l4proto pernet data */
int (*init_net)(struct net *net, u_int16_t proto);
@@ -125,14 +125,24 @@ struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u_int16_t l3proto,
void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol pernet registration. */
+int nf_ct_l4proto_pernet_register_one(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_pernet_unregister_one(struct net *net,
+ struct nf_conntrack_l4proto *proto);
int nf_ct_l4proto_pernet_register(struct net *net,
- struct nf_conntrack_l4proto *proto);
+ struct nf_conntrack_l4proto *proto[],
+ unsigned int num_proto);
void nf_ct_l4proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l4proto *proto);
+ struct nf_conntrack_l4proto *proto[],
+ unsigned int num_proto);
/* Protocol global registration. */
-int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
-void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_unregister_one(struct nf_conntrack_l4proto *proto);
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto[],
+ unsigned int num_proto);
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto[],
+ unsigned int num_proto);
/* Generic netlink helpers */
int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
diff --git a/include/net/netfilter/nf_conntrack_synproxy.h b/include/net/netfilter/nf_conntrack_synproxy.h
index e6937318546c..b0ca402c1f72 100644
--- a/include/net/netfilter/nf_conntrack_synproxy.h
+++ b/include/net/netfilter/nf_conntrack_synproxy.h
@@ -54,7 +54,7 @@ struct synproxy_net {
struct synproxy_stats __percpu *stats;
};
-extern int synproxy_net_id;
+extern unsigned int synproxy_net_id;
static inline struct synproxy_net *synproxy_pernet(struct net *net)
{
return net_generic(net, synproxy_net_id);
diff --git a/include/net/netfilter/nf_dup_netdev.h b/include/net/netfilter/nf_dup_netdev.h
index 397dcae349f9..3e919356bedf 100644
--- a/include/net/netfilter/nf_dup_netdev.h
+++ b/include/net/netfilter/nf_dup_netdev.h
@@ -2,5 +2,6 @@
#define _NF_DUP_NETDEV_H_
void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
+void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif);
#endif
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h
index 309cd267be4f..450f87f95415 100644
--- a/include/net/netfilter/nf_log.h
+++ b/include/net/netfilter/nf_log.h
@@ -109,5 +109,12 @@ void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
const struct net_device *out,
const struct nf_loginfo *loginfo,
const char *prefix);
+void nf_log_l2packet(struct net *net, u_int8_t pf,
+ __be16 protocol,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *loginfo, const char *prefix);
#endif /* _NF_LOG_H */
diff --git a/include/net/netfilter/nf_nat_l4proto.h b/include/net/netfilter/nf_nat_l4proto.h
index 12f4cc841b6e..3923150f2a1e 100644
--- a/include/net/netfilter/nf_nat_l4proto.h
+++ b/include/net/netfilter/nf_nat_l4proto.h
@@ -54,6 +54,15 @@ extern const struct nf_nat_l4proto nf_nat_l4proto_udp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
+#ifdef CONFIG_NF_NAT_PROTO_DCCP
+extern const struct nf_nat_l4proto nf_nat_l4proto_dccp;
+#endif
+#ifdef CONFIG_NF_NAT_PROTO_SCTP
+extern const struct nf_nat_l4proto nf_nat_l4proto_sctp;
+#endif
+#ifdef CONFIG_NF_NAT_PROTO_UDPLITE
+extern const struct nf_nat_l4proto nf_nat_l4proto_udplite;
+#endif
bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 2280cfe86c56..09948d10e38e 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -12,6 +12,7 @@ struct nf_queue_entry {
unsigned int id;
struct nf_hook_state state;
+ struct nf_hook_entry *hook;
u16 size; /* sizeof(entry) + saved route keys */
/* extra space to store route keys */
diff --git a/include/net/netfilter/nf_socket.h b/include/net/netfilter/nf_socket.h
new file mode 100644
index 000000000000..f2fc39c97d43
--- /dev/null
+++ b/include/net/netfilter/nf_socket.h
@@ -0,0 +1,27 @@
+#ifndef _NF_SOCK_H_
+#define _NF_SOCK_H_
+
+struct net_device;
+struct sk_buff;
+struct sock;
+struct net;
+
+static inline bool nf_sk_is_transparent(struct sock *sk)
+{
+ switch (sk->sk_state) {
+ case TCP_TIME_WAIT:
+ return inet_twsk(sk)->tw_transparent;
+ case TCP_NEW_SYN_RECV:
+ return inet_rsk(inet_reqsk(sk))->no_srccheck;
+ default:
+ return inet_sk(sk)->transparent;
+ }
+}
+
+struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
+ const struct net_device *indev);
+
+struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
+ const struct net_device *indev);
+
+#endif
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index b02af0bf5777..924325c46aab 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -14,27 +14,43 @@
struct nft_pktinfo {
struct sk_buff *skb;
- struct net *net;
- const struct net_device *in;
- const struct net_device *out;
- u8 pf;
- u8 hook;
bool tprot_set;
u8 tprot;
/* for x_tables compatibility */
struct xt_action_param xt;
};
+static inline struct net *nft_net(const struct nft_pktinfo *pkt)
+{
+ return pkt->xt.state->net;
+}
+
+static inline unsigned int nft_hook(const struct nft_pktinfo *pkt)
+{
+ return pkt->xt.state->hook;
+}
+
+static inline u8 nft_pf(const struct nft_pktinfo *pkt)
+{
+ return pkt->xt.state->pf;
+}
+
+static inline const struct net_device *nft_in(const struct nft_pktinfo *pkt)
+{
+ return pkt->xt.state->in;
+}
+
+static inline const struct net_device *nft_out(const struct nft_pktinfo *pkt)
+{
+ return pkt->xt.state->out;
+}
+
static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
pkt->skb = skb;
- pkt->net = pkt->xt.net = state->net;
- pkt->in = pkt->xt.in = state->in;
- pkt->out = pkt->xt.out = state->out;
- pkt->hook = pkt->xt.hooknum = state->hook;
- pkt->pf = pkt->xt.family = state->pf;
+ pkt->xt.state = state;
}
static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
@@ -243,7 +259,8 @@ struct nft_expr;
* @lookup: look up an element within the set
* @insert: insert new element into set
* @activate: activate new element in the next generation
- * @deactivate: deactivate element in the next generation
+ * @deactivate: lookup for element and deactivate it in the next generation
+ * @deactivate_one: deactivate element in the next generation
* @remove: remove element from set
* @walk: iterate over all set elemeennts
* @privsize: function to return size of set private data
@@ -278,6 +295,9 @@ struct nft_set_ops {
void * (*deactivate)(const struct net *net,
const struct nft_set *set,
const struct nft_set_elem *elem);
+ bool (*deactivate_one)(const struct net *net,
+ const struct nft_set *set,
+ void *priv);
void (*remove)(const struct nft_set *set,
const struct nft_set_elem *elem);
void (*walk)(const struct nft_ctx *ctx,
@@ -310,6 +330,7 @@ void nft_unregister_set(struct nft_set_ops *ops);
* @name: name of the set
* @ktype: key type (numeric type defined by userspace, not used in the kernel)
* @dtype: data type (verdict or numeric type defined by userspace)
+ * @objtype: object type (see NFT_OBJECT_* definitions)
* @size: maximum set size
* @nelems: number of elements
* @ndeact: number of deactivated elements queued for removal
@@ -331,6 +352,7 @@ struct nft_set {
char name[NFT_SET_MAXNAMELEN];
u32 ktype;
u32 dtype;
+ u32 objtype;
u32 size;
atomic_t nelems;
u32 ndeact;
@@ -400,6 +422,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
* @NFT_SET_EXT_EXPIRATION: element expiration time
* @NFT_SET_EXT_USERDATA: user data associated with the element
* @NFT_SET_EXT_EXPR: expression assiociated with the element
+ * @NFT_SET_EXT_OBJREF: stateful object reference associated with element
* @NFT_SET_EXT_NUM: number of extension types
*/
enum nft_set_extensions {
@@ -410,6 +433,7 @@ enum nft_set_extensions {
NFT_SET_EXT_EXPIRATION,
NFT_SET_EXT_USERDATA,
NFT_SET_EXT_EXPR,
+ NFT_SET_EXT_OBJREF,
NFT_SET_EXT_NUM
};
@@ -538,6 +562,11 @@ static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
return elem + set->ops->elemsize;
}
+static inline struct nft_object **nft_set_ext_obj(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_OBJREF);
+}
+
void *nft_set_elem_init(const struct nft_set *set,
const struct nft_set_ext_tmpl *tmpl,
const u32 *key, const u32 *data,
@@ -859,6 +888,7 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);
* @list: used internally
* @chains: chains in the table
* @sets: sets in the table
+ * @objects: stateful objects in the table
* @hgenerator: handle generator state
* @use: number of chain references to this table
* @flags: table flag (see enum nft_table_flags)
@@ -869,6 +899,7 @@ struct nft_table {
struct list_head list;
struct list_head chains;
struct list_head sets;
+ struct list_head objects;
u64 hgenerator;
u32 use;
u16 flags:14,
@@ -919,6 +950,80 @@ int nft_verdict_dump(struct sk_buff *skb, int type,
const struct nft_verdict *v);
/**
+ * struct nft_object - nf_tables stateful object
+ *
+ * @list: table stateful object list node
+ * @table: table this object belongs to
+ * @type: pointer to object type
+ * @data: pointer to object data
+ * @name: name of this stateful object
+ * @genmask: generation mask
+ * @use: number of references to this stateful object
+ * @data: object data, layout depends on type
+ */
+struct nft_object {
+ struct list_head list;
+ char name[NFT_OBJ_MAXNAMELEN];
+ struct nft_table *table;
+ u32 genmask:2,
+ use:30;
+ /* runtime data below here */
+ const struct nft_object_type *type ____cacheline_aligned;
+ unsigned char data[]
+ __attribute__((aligned(__alignof__(u64))));
+};
+
+static inline void *nft_obj_data(const struct nft_object *obj)
+{
+ return (void *)obj->data;
+}
+
+#define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr))
+
+struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
+ const struct nlattr *nla, u32 objtype,
+ u8 genmask);
+
+int nft_obj_notify(struct net *net, struct nft_table *table,
+ struct nft_object *obj, u32 portid, u32 seq,
+ int event, int family, int report, gfp_t gfp);
+
+/**
+ * struct nft_object_type - stateful object type
+ *
+ * @eval: stateful object evaluation function
+ * @list: list node in list of object types
+ * @type: stateful object numeric type
+ * @size: stateful object size
+ * @owner: module owner
+ * @maxattr: maximum netlink attribute
+ * @policy: netlink attribute policy
+ * @init: initialize object from netlink attributes
+ * @destroy: release existing stateful object
+ * @dump: netlink dump stateful object
+ */
+struct nft_object_type {
+ void (*eval)(struct nft_object *obj,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+ struct list_head list;
+ u32 type;
+ unsigned int size;
+ unsigned int maxattr;
+ struct module *owner;
+ const struct nla_policy *policy;
+ int (*init)(const struct nlattr * const tb[],
+ struct nft_object *obj);
+ void (*destroy)(struct nft_object *obj);
+ int (*dump)(struct sk_buff *skb,
+ struct nft_object *obj,
+ bool reset);
+};
+
+int nft_register_obj(struct nft_object_type *obj_type);
+void nft_unregister_obj(struct nft_object_type *obj_type);
+
+/**
* struct nft_traceinfo - nft tracing information and state
*
* @pkt: pktinfo currently processed
@@ -965,6 +1070,9 @@ void nft_trace_notify(struct nft_traceinfo *info);
#define MODULE_ALIAS_NFT_SET() \
MODULE_ALIAS("nft-set")
+#define MODULE_ALIAS_NFT_OBJ(type) \
+ MODULE_ALIAS("nft-obj-" __stringify(type))
+
/*
* The gencursor defines two generations, the currently active and the
* next one. Objects contain a bitmask of 2 bits specifying the generations
@@ -1141,4 +1249,11 @@ struct nft_trans_elem {
#define nft_trans_elem(trans) \
(((struct nft_trans_elem *)trans->data)->elem)
+struct nft_trans_obj {
+ struct nft_object *obj;
+};
+
+#define nft_trans_obj(trans) \
+ (((struct nft_trans_obj *)trans->data)->obj)
+
#endif /* _NET_NF_TABLES_H */
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index 00f4f6b1b1ba..8f690effec37 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -1,12 +1,18 @@
#ifndef _NET_NF_TABLES_CORE_H
#define _NET_NF_TABLES_CORE_H
+extern struct nft_expr_type nft_imm_type;
+extern struct nft_expr_type nft_cmp_type;
+extern struct nft_expr_type nft_lookup_type;
+extern struct nft_expr_type nft_bitwise_type;
+extern struct nft_expr_type nft_byteorder_type;
+extern struct nft_expr_type nft_payload_type;
+extern struct nft_expr_type nft_dynset_type;
+extern struct nft_expr_type nft_range_type;
+
int nf_tables_core_module_init(void);
void nf_tables_core_module_exit(void);
-int nft_immediate_module_init(void);
-void nft_immediate_module_exit(void);
-
struct nft_cmp_fast_expr {
u32 data;
enum nft_registers sreg:8;
@@ -25,24 +31,6 @@ static inline u32 nft_cmp_fast_mask(unsigned int len)
extern const struct nft_expr_ops nft_cmp_fast_ops;
-int nft_cmp_module_init(void);
-void nft_cmp_module_exit(void);
-
-int nft_range_module_init(void);
-void nft_range_module_exit(void);
-
-int nft_lookup_module_init(void);
-void nft_lookup_module_exit(void);
-
-int nft_dynset_module_init(void);
-void nft_dynset_module_exit(void);
-
-int nft_bitwise_module_init(void);
-void nft_bitwise_module_exit(void);
-
-int nft_byteorder_module_init(void);
-void nft_byteorder_module_exit(void);
-
struct nft_payload {
enum nft_payload_bases base:8;
u8 offset;
@@ -57,12 +45,10 @@ struct nft_payload_set {
enum nft_registers sreg:8;
u8 csum_type;
u8 csum_offset;
+ u8 csum_flags;
};
extern const struct nft_expr_ops nft_payload_fast_ops;
extern struct static_key_false nft_trace_enabled;
-int nft_payload_module_init(void);
-void nft_payload_module_exit(void);
-
#endif /* _NET_NF_TABLES_CORE_H */
diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h
new file mode 100644
index 000000000000..cbedda077db2
--- /dev/null
+++ b/include/net/netfilter/nft_fib.h
@@ -0,0 +1,31 @@
+#ifndef _NFT_FIB_H_
+#define _NFT_FIB_H_
+
+struct nft_fib {
+ enum nft_registers dreg:8;
+ u8 result;
+ u32 flags;
+};
+
+extern const struct nla_policy nft_fib_policy[];
+
+int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr);
+int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nft_data **data);
+
+
+void nft_fib4_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+void nft_fib_store_result(void *reg, enum nft_fib_result r,
+ const struct nft_pktinfo *pkt, int index);
+#endif
diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h
index 79f45e19f31e..130e58361f99 100644
--- a/include/net/netfilter/xt_rateest.h
+++ b/include/net/netfilter/xt_rateest.h
@@ -1,19 +1,23 @@
#ifndef _XT_RATEEST_H
#define _XT_RATEEST_H
+#include <net/gen_stats.h>
+
struct xt_rateest {
/* keep lock and bstats on same cache line to speedup xt_rateest_tg() */
struct gnet_stats_basic_packed bstats;
spinlock_t lock;
- /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */
- struct gnet_stats_rate_est64 rstats;
+
/* following fields not accessed in hot path */
+ unsigned int refcnt;
struct hlist_node list;
char name[IFNAMSIZ];
- unsigned int refcnt;
struct gnet_estimator params;
struct rcu_head rcu;
+
+ /* keep this field far away to speedup xt_rateest_mt() */
+ struct net_rate_estimator __rcu *rate_est;
};
struct xt_rateest *xt_rateest_lookup(const char *name);
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 254a0fc01800..dd657a33f8c3 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -698,8 +698,7 @@ static inline int nla_len(const struct nlattr *nla)
*/
static inline int nla_ok(const struct nlattr *nla, int remaining)
{
- return remaining >= (int) sizeof(*nla) &&
- nla->nla_len >= sizeof(*nla) &&
+ return nla->nla_len >= sizeof(*nla) &&
nla->nla_len <= remaining;
}
@@ -713,7 +712,7 @@ static inline int nla_ok(const struct nlattr *nla, int remaining)
*/
static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
{
- int totlen = NLA_ALIGN(nla->nla_len);
+ unsigned int totlen = NLA_ALIGN(nla->nla_len);
*remaining -= totlen;
return (struct nlattr *) ((char *) nla + totlen);
@@ -1191,6 +1190,16 @@ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla)
}
/**
+ * nla_memdup - duplicate attribute memory (kmemdup)
+ * @src: netlink attribute to duplicate from
+ * @gfp: GFP mask
+ */
+static inline void *nla_memdup(const struct nlattr *src, gfp_t gfp)
+{
+ return kmemdup(nla_data(src), nla_len(src), gfp);
+}
+
+/**
* nla_nest_start - Start a new level of nested attributes
* @skb: socket buffer to add attributes to
* @attrtype: attribute type of container
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index e469e85de3f9..cf799fc3fdec 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -6,6 +6,12 @@
#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/netfilter/nf_conntrack_tcp.h>
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+#include <linux/netfilter/nf_conntrack_dccp.h>
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+#include <linux/netfilter/nf_conntrack_sctp.h>
+#endif
#include <linux/seqlock.h>
struct ctl_table_header;
@@ -48,12 +54,49 @@ struct nf_icmp_net {
unsigned int timeout;
};
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+struct nf_dccp_net {
+ struct nf_proto_net pn;
+ int dccp_loose;
+ unsigned int dccp_timeout[CT_DCCP_MAX + 1];
+};
+#endif
+
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+struct nf_sctp_net {
+ struct nf_proto_net pn;
+ unsigned int timeouts[SCTP_CONNTRACK_MAX];
+};
+#endif
+
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+enum udplite_conntrack {
+ UDPLITE_CT_UNREPLIED,
+ UDPLITE_CT_REPLIED,
+ UDPLITE_CT_MAX
+};
+
+struct nf_udplite_net {
+ struct nf_proto_net pn;
+ unsigned int timeouts[UDPLITE_CT_MAX];
+};
+#endif
+
struct nf_ip_net {
struct nf_generic_net generic;
struct nf_tcp_net tcp;
struct nf_udp_net udp;
struct nf_icmp_net icmp;
struct nf_icmp_net icmpv6;
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+ struct nf_dccp_net dccp;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+ struct nf_sctp_net sctp;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+ struct nf_udplite_net udplite;
+#endif
};
struct ct_pcpu {
@@ -91,7 +134,6 @@ struct netns_ct {
struct nf_ip_net nf_ct_proto;
#if defined(CONFIG_NF_CONNTRACK_LABELS)
unsigned int labels_used;
- u8 label_words;
#endif
};
#endif
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
index 70e158551704..f15daaa89385 100644
--- a/include/net/netns/generic.h
+++ b/include/net/netns/generic.h
@@ -25,20 +25,24 @@
*/
struct net_generic {
- unsigned int len;
- struct rcu_head rcu;
-
- void *ptr[0];
+ union {
+ struct {
+ unsigned int len;
+ struct rcu_head rcu;
+ } s;
+
+ void *ptr[0];
+ };
};
-static inline void *net_generic(const struct net *net, int id)
+static inline void *net_generic(const struct net *net, unsigned int id)
{
struct net_generic *ng;
void *ptr;
rcu_read_lock();
ng = rcu_dereference(net->gen);
- ptr = ng->ptr[id - 1];
+ ptr = ng->ptr[id];
rcu_read_unlock();
return ptr;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 7adf4386ac8f..f0cf5a1b777e 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -135,6 +135,9 @@ struct netns_ipv4 {
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int sysctl_fib_multipath_use_neigh;
#endif
+
+ unsigned int fib_seq; /* protected by rtnl_mutex */
+
atomic_t rt_genid;
};
#endif
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 10d0848f5b8a..de7745e2edcc 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -85,6 +85,7 @@ struct netns_ipv6 {
#endif
atomic_t dev_addr_genid;
atomic_t fib6_sernum;
+ struct seg6_pernet_data *seg6_data;
};
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index 58487b1cc99a..cea396b53a60 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -17,5 +17,11 @@ struct netns_nf {
struct ctl_table_header *nf_log_dir_header;
#endif
struct nf_hook_entry __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
+ bool defrag_ipv4;
+#endif
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+ bool defrag_ipv6;
+#endif
};
#endif
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 767b03a3fe67..f0a051480c6c 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -171,6 +171,8 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
struct tcf_exts *src);
int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
+int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
+ struct net_device **hw_dev);
/**
* struct tcf_pkt_info - packet information
@@ -425,16 +427,14 @@ struct tc_cls_u32_offload {
};
};
-static inline bool tc_should_offload(const struct net_device *dev,
- const struct tcf_proto *tp, u32 flags)
+static inline bool tc_can_offload(const struct net_device *dev,
+ const struct tcf_proto *tp)
{
const struct Qdisc *sch = tp->q;
const struct Qdisc_class_ops *cops = sch->ops->cl_ops;
if (!(dev->features & NETIF_F_HW_TC))
return false;
- if (flags & TCA_CLS_FLAGS_SKIP_HW)
- return false;
if (!dev->netdev_ops->ndo_setup_tc)
return false;
if (cops && cops->tcf_cl_offload)
@@ -443,6 +443,19 @@ static inline bool tc_should_offload(const struct net_device *dev,
return true;
}
+static inline bool tc_skip_hw(u32 flags)
+{
+ return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false;
+}
+
+static inline bool tc_should_offload(const struct net_device *dev,
+ const struct tcf_proto *tp, u32 flags)
+{
+ if (tc_skip_hw(flags))
+ return false;
+ return tc_can_offload(dev, tp);
+}
+
static inline bool tc_skip_sw(u32 flags)
{
return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false;
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index cd334c9584e9..f1b76b8e6d2d 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -6,6 +6,8 @@
#include <linux/if_vlan.h>
#include <net/sch_generic.h>
+#define DEFAULT_TX_QUEUE_LEN 1000
+
struct qdisc_walker {
int stop;
int skip;
diff --git a/include/net/raw.h b/include/net/raw.h
index 3e789008394d..57c33dd22ec4 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -23,6 +23,12 @@
extern struct proto raw_prot;
+extern struct raw_hashinfo raw_v4_hashinfo;
+struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+ unsigned short num, __be32 raddr,
+ __be32 laddr, int dif);
+
+int raw_abort(struct sock *sk, int err);
void raw_icmp_error(struct sk_buff *, int, u32);
int raw_local_deliver(struct sk_buff *, int);
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index 87783dea0791..cbe4e9de1894 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -3,6 +3,13 @@
#include <net/protocol.h>
+extern struct raw_hashinfo raw_v6_hashinfo;
+struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ unsigned short num, const struct in6_addr *loc_addr,
+ const struct in6_addr *rmt_addr, int dif);
+
+int raw_abort(struct sock *sk, int err);
+
void raw6_icmp_error(struct sk_buff *, int nexthdr,
u8 type, u8 code, int inner_offset, __be32);
bool raw6_local_deliver(struct sk_buff *, int);
diff --git a/include/net/route.h b/include/net/route.h
index 0429d47cad25..c0874c87c173 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -153,7 +153,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
RT_SCOPE_UNIVERSE, proto,
sk ? inet_sk_flowi_flags(sk) : 0,
- daddr, saddr, dport, sport);
+ daddr, saddr, dport, sport, sock_net_uid(net, sk));
if (sk)
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(net, fl4, sk);
@@ -269,7 +269,8 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
flow_flags |= FLOWI_FLAG_ANYSRC;
flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
- protocol, flow_flags, dst, src, dport, sport);
+ protocol, flow_flags, dst, src, dport, sport,
+ sk->sk_uid);
}
static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index e6aa0a249672..498f81b229a4 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -76,7 +76,7 @@ struct Qdisc {
struct netdev_queue *dev_queue;
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 31acc3f4f132..f0dcaebebddb 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -164,7 +164,7 @@ void sctp_backlog_migrate(struct sctp_association *assoc,
struct sock *oldsk, struct sock *newsk);
int sctp_transport_hashtable_init(void);
void sctp_transport_hashtable_destroy(void);
-void sctp_hash_transport(struct sctp_transport *t);
+int sctp_hash_transport(struct sctp_transport *t);
void sctp_unhash_transport(struct sctp_transport *t);
struct sctp_transport *sctp_addrs_lookup_transport(
struct net *net,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 11c3bf262a85..92daabdc007d 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -124,7 +124,7 @@ extern struct sctp_globals {
/* This is the sctp port control hash. */
struct sctp_bind_hashbucket *port_hashtable;
/* This is the hash of all transports. */
- struct rhashtable transport_hashtable;
+ struct rhltable transport_hashtable;
/* Sizes of above hashtables. */
int ep_hashsize;
@@ -530,7 +530,6 @@ struct sctp_datamsg {
/* Did the messenge fail to send? */
int send_error;
u8 send_failed:1,
- can_abandon:1, /* can chunks from this message can be abandoned. */
can_delay; /* should this message be Nagle delayed */
};
@@ -641,7 +640,6 @@ struct sctp_chunk {
#define SCTP_NEED_FRTX 0x1
#define SCTP_DONT_FRTX 0x2
__u16 rtt_in_progress:1, /* This chunk used for RTT calc? */
- resent:1, /* Has this chunk ever been resent. */
has_tsn:1, /* Does this chunk have a TSN yet? */
has_ssn:1, /* Does this chunk have a SSN yet? */
singleton:1, /* Only chunk in the packet? */
@@ -656,6 +654,7 @@ struct sctp_chunk {
fast_retransmit:2; /* Is this chunk fast retransmitted? */
};
+#define sctp_chunk_retransmitted(chunk) (chunk->sent_count > 1)
void sctp_chunk_hold(struct sctp_chunk *);
void sctp_chunk_put(struct sctp_chunk *);
int sctp_user_addto_chunk(struct sctp_chunk *chunk, int len,
@@ -762,7 +761,7 @@ static inline int sctp_packet_empty(struct sctp_packet *packet)
struct sctp_transport {
/* A list of transports. */
struct list_head transports;
- struct rhash_head node;
+ struct rhlist_head node;
/* Reference counting. */
atomic_t refcnt;
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
index 3f36d45b714a..0caee631a836 100644
--- a/include/net/secure_seq.h
+++ b/include/net/secure_seq.h
@@ -6,10 +6,10 @@
u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
__be16 dport);
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport);
-__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
- __be16 sport, __be16 dport);
+u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport, u32 *tsoff);
+u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+ __be16 sport, __be16 dport, u32 *tsoff);
u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
__be16 sport, __be16 dport);
u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
diff --git a/include/net/seg6.h b/include/net/seg6.h
new file mode 100644
index 000000000000..4e0357517d79
--- /dev/null
+++ b/include/net/seg6.h
@@ -0,0 +1,62 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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 _NET_SEG6_H
+#define _NET_SEG6_H
+
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <net/lwtunnel.h>
+#include <linux/seg6.h>
+#include <linux/rhashtable.h>
+
+static inline void update_csum_diff4(struct sk_buff *skb, __be32 from,
+ __be32 to)
+{
+ __be32 diff[] = { ~from, to };
+
+ skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum);
+}
+
+static inline void update_csum_diff16(struct sk_buff *skb, __be32 *from,
+ __be32 *to)
+{
+ __be32 diff[] = {
+ ~from[0], ~from[1], ~from[2], ~from[3],
+ to[0], to[1], to[2], to[3],
+ };
+
+ skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum);
+}
+
+struct seg6_pernet_data {
+ struct mutex lock;
+ struct in6_addr __rcu *tun_src;
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ struct rhashtable hmac_infos;
+#endif
+};
+
+static inline struct seg6_pernet_data *seg6_pernet(struct net *net)
+{
+ return net->ipv6.seg6_data;
+}
+
+extern int seg6_init(void);
+extern void seg6_exit(void);
+extern int seg6_iptunnel_init(void);
+extern void seg6_iptunnel_exit(void);
+
+extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);
+
+#endif
diff --git a/include/net/seg6_hmac.h b/include/net/seg6_hmac.h
new file mode 100644
index 000000000000..69c3a106056b
--- /dev/null
+++ b/include/net/seg6_hmac.h
@@ -0,0 +1,62 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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 _NET_SEG6_HMAC_H
+#define _NET_SEG6_HMAC_H
+
+#include <net/flow.h>
+#include <net/ip6_fib.h>
+#include <net/sock.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/route.h>
+#include <net/seg6.h>
+#include <linux/seg6_hmac.h>
+#include <linux/rhashtable.h>
+
+#define SEG6_HMAC_MAX_DIGESTSIZE 160
+#define SEG6_HMAC_RING_SIZE 256
+
+struct seg6_hmac_info {
+ struct rhash_head node;
+ struct rcu_head rcu;
+
+ u32 hmackeyid;
+ char secret[SEG6_HMAC_SECRET_LEN];
+ u8 slen;
+ u8 alg_id;
+};
+
+struct seg6_hmac_algo {
+ u8 alg_id;
+ char name[64];
+ struct crypto_shash * __percpu *tfms;
+ struct shash_desc * __percpu *shashs;
+};
+
+extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
+ struct ipv6_sr_hdr *hdr, struct in6_addr *saddr,
+ u8 *output);
+extern struct seg6_hmac_info *seg6_hmac_info_lookup(struct net *net, u32 key);
+extern int seg6_hmac_info_add(struct net *net, u32 key,
+ struct seg6_hmac_info *hinfo);
+extern int seg6_hmac_info_del(struct net *net, u32 key);
+extern int seg6_push_hmac(struct net *net, struct in6_addr *saddr,
+ struct ipv6_sr_hdr *srh);
+extern bool seg6_hmac_validate_skb(struct sk_buff *skb);
+extern int seg6_hmac_init(void);
+extern void seg6_hmac_exit(void);
+extern int seg6_hmac_net_init(struct net *net);
+extern void seg6_hmac_net_exit(struct net *net);
+
+#endif
diff --git a/include/net/sock.h b/include/net/sock.h
index 92b269709b9a..e17aa3de2b4d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -343,6 +343,9 @@ struct sock {
#define sk_rxhash __sk_common.skc_rxhash
socket_lock_t sk_lock;
+ atomic_t sk_drops;
+ int sk_rcvlowat;
+ struct sk_buff_head sk_error_queue;
struct sk_buff_head sk_receive_queue;
/*
* The backlog queue is special, it is always used with
@@ -359,14 +362,13 @@ struct sock {
struct sk_buff *tail;
} sk_backlog;
#define sk_rmem_alloc sk_backlog.rmem_alloc
- int sk_forward_alloc;
- __u32 sk_txhash;
+ int sk_forward_alloc;
#ifdef CONFIG_NET_RX_BUSY_POLL
- unsigned int sk_napi_id;
unsigned int sk_ll_usec;
+ /* ===== mostly read cache line ===== */
+ unsigned int sk_napi_id;
#endif
- atomic_t sk_drops;
int sk_rcvbuf;
struct sk_filter __rcu *sk_filter;
@@ -379,16 +381,50 @@ struct sock {
#endif
struct dst_entry *sk_rx_dst;
struct dst_entry __rcu *sk_dst_cache;
- /* Note: 32bit hole on 64bit arches */
- atomic_t sk_wmem_alloc;
atomic_t sk_omem_alloc;
int sk_sndbuf;
+
+ /* ===== cache line for TX ===== */
+ int sk_wmem_queued;
+ atomic_t sk_wmem_alloc;
+ unsigned long sk_tsq_flags;
+ struct sk_buff *sk_send_head;
struct sk_buff_head sk_write_queue;
+ __s32 sk_peek_off;
+ int sk_write_pending;
+ long sk_sndtimeo;
+ struct timer_list sk_timer;
+ __u32 sk_priority;
+ __u32 sk_mark;
+ u32 sk_pacing_rate; /* bytes per second */
+ u32 sk_max_pacing_rate;
+ struct page_frag sk_frag;
+ netdev_features_t sk_route_caps;
+ netdev_features_t sk_route_nocaps;
+ int sk_gso_type;
+ unsigned int sk_gso_max_size;
+ gfp_t sk_allocation;
+ __u32 sk_txhash;
/*
* Because of non atomicity rules, all
* changes are protected by socket lock.
*/
+ unsigned int __sk_flags_offset[0];
+#ifdef __BIG_ENDIAN_BITFIELD
+#define SK_FL_PROTO_SHIFT 16
+#define SK_FL_PROTO_MASK 0x00ff0000
+
+#define SK_FL_TYPE_SHIFT 0
+#define SK_FL_TYPE_MASK 0x0000ffff
+#else
+#define SK_FL_PROTO_SHIFT 8
+#define SK_FL_PROTO_MASK 0x0000ff00
+
+#define SK_FL_TYPE_SHIFT 16
+#define SK_FL_TYPE_MASK 0xffff0000
+#endif
+
kmemcheck_bitfield_begin(flags);
unsigned int sk_padding : 2,
sk_no_check_tx : 1,
@@ -399,41 +435,24 @@ struct sock {
#define SK_PROTOCOL_MAX U8_MAX
kmemcheck_bitfield_end(flags);
- int sk_wmem_queued;
- gfp_t sk_allocation;
- u32 sk_pacing_rate; /* bytes per second */
- u32 sk_max_pacing_rate;
- netdev_features_t sk_route_caps;
- netdev_features_t sk_route_nocaps;
- int sk_gso_type;
- unsigned int sk_gso_max_size;
u16 sk_gso_max_segs;
- int sk_rcvlowat;
unsigned long sk_lingertime;
- struct sk_buff_head sk_error_queue;
struct proto *sk_prot_creator;
rwlock_t sk_callback_lock;
int sk_err,
sk_err_soft;
u32 sk_ack_backlog;
u32 sk_max_ack_backlog;
- __u32 sk_priority;
- __u32 sk_mark;
+ kuid_t sk_uid;
struct pid *sk_peer_pid;
const struct cred *sk_peer_cred;
long sk_rcvtimeo;
- long sk_sndtimeo;
- struct timer_list sk_timer;
ktime_t sk_stamp;
u16 sk_tsflags;
u8 sk_shutdown;
u32 sk_tskey;
struct socket *sk_socket;
void *sk_user_data;
- struct page_frag sk_frag;
- struct sk_buff *sk_send_head;
- __s32 sk_peek_off;
- int sk_write_pending;
#ifdef CONFIG_SECURITY
void *sk_security;
#endif
@@ -894,7 +913,20 @@ static inline void sock_rps_record_flow_hash(__u32 hash)
static inline void sock_rps_record_flow(const struct sock *sk)
{
#ifdef CONFIG_RPS
- sock_rps_record_flow_hash(sk->sk_rxhash);
+ if (static_key_false(&rfs_needed)) {
+ /* Reading sk->sk_rxhash might incur an expensive cache line
+ * miss.
+ *
+ * TCP_ESTABLISHED does cover almost all states where RFS
+ * might be useful, and is cheaper [1] than testing :
+ * IPv4: inet_sk(sk)->inet_daddr
+ * IPv6: ipv6_addr_any(&sk->sk_v6_daddr)
+ * OR an additional socket flag
+ * [1] : sk_state and sk_prot are in the same cache line.
+ */
+ if (sk->sk_state == TCP_ESTABLISHED)
+ sock_rps_record_flow_hash(sk->sk_rxhash);
+ }
#endif
}
@@ -914,14 +946,16 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
#endif
}
-#define sk_wait_event(__sk, __timeo, __condition) \
+#define sk_wait_event(__sk, __timeo, __condition, __wait) \
({ int __rc; \
release_sock(__sk); \
__rc = __condition; \
if (!__rc) { \
- *(__timeo) = schedule_timeout(*(__timeo)); \
+ *(__timeo) = wait_woken(__wait, \
+ TASK_INTERRUPTIBLE, \
+ *(__timeo)); \
} \
- sched_annotate_sleep(); \
+ sched_annotate_sleep(); \
lock_sock(__sk); \
__rc = __condition; \
__rc; \
@@ -1162,11 +1196,6 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
sk->sk_prot->enter_memory_pressure(sk);
}
-static inline long sk_prot_mem_limits(const struct sock *sk, int index)
-{
- return sk->sk_prot->sysctl_mem[index];
-}
-
static inline long
sk_memory_allocated(const struct sock *sk)
{
@@ -1276,14 +1305,32 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
/*
* Functions for memory accounting
*/
+int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind);
int __sk_mem_schedule(struct sock *sk, int size, int kind);
+void __sk_mem_reduce_allocated(struct sock *sk, int amount);
void __sk_mem_reclaim(struct sock *sk, int amount);
-#define SK_MEM_QUANTUM ((int)PAGE_SIZE)
+/* We used to have PAGE_SIZE here, but systems with 64KB pages
+ * do not necessarily have 16x time more memory than 4KB ones.
+ */
+#define SK_MEM_QUANTUM 4096
#define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM)
#define SK_MEM_SEND 0
#define SK_MEM_RECV 1
+/* sysctl_mem values are in pages, we convert them in SK_MEM_QUANTUM units */
+static inline long sk_prot_mem_limits(const struct sock *sk, int index)
+{
+ long val = sk->sk_prot->sysctl_mem[index];
+
+#if PAGE_SIZE > SK_MEM_QUANTUM
+ val <<= PAGE_SHIFT - SK_MEM_QUANTUM_SHIFT;
+#elif PAGE_SIZE < SK_MEM_QUANTUM
+ val >>= SK_MEM_QUANTUM_SHIFT - PAGE_SHIFT;
+#endif
+ return val;
+}
+
static inline int sk_mem_pages(int amt)
{
return (amt + SK_MEM_QUANTUM - 1) >> SK_MEM_QUANTUM_SHIFT;
@@ -1651,6 +1698,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
sk->sk_wq = parent->wq;
parent->sk = sk;
sk_set_socket(sk, parent);
+ sk->sk_uid = SOCK_INODE(parent)->i_uid;
security_sock_graft(sk, parent);
write_unlock_bh(&sk->sk_callback_lock);
}
@@ -1658,6 +1706,11 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
kuid_t sock_i_uid(struct sock *sk);
unsigned long sock_i_ino(struct sock *sk);
+static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
+{
+ return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
+}
+
static inline u32 net_tx_rndhash(void)
{
u32 v = prandom_u32();
@@ -1952,6 +2005,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
void sk_stop_timer(struct sock *sk, struct timer_list *timer);
+int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
+ unsigned int flags);
int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
@@ -2108,7 +2163,8 @@ struct sock_skb_cb {
static inline void
sock_skb_set_dropcount(const struct sock *sk, struct sk_buff *skb)
{
- SOCK_SKB_CB(skb)->dropcount = atomic_read(&sk->sk_drops);
+ SOCK_SKB_CB(skb)->dropcount = sock_flag(sk, SOCK_RXQ_OVFL) ?
+ atomic_read(&sk->sk_drops) : 0;
}
static inline void sk_drops_add(struct sock *sk, const struct sk_buff *skb)
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
index 62770add15bd..604bc31e23ab 100644
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -8,13 +8,13 @@ struct tcf_mirred {
struct tc_action common;
int tcfm_eaction;
int tcfm_ifindex;
- int tcfm_ok_push;
+ bool tcfm_mac_header_xmit;
struct net_device __rcu *tcfm_dev;
struct list_head tcfm_list;
};
#define to_mirred(a) ((struct tcf_mirred *)a)
-static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
+static inline bool is_tcf_mirred_egress_redirect(const struct tc_action *a)
{
#ifdef CONFIG_NET_CLS_ACT
if (a->ops && a->ops->type == TCA_ACT_MIRRED)
@@ -23,7 +23,7 @@ static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
return false;
}
-static inline bool is_tcf_mirred_mirror(const struct tc_action *a)
+static inline bool is_tcf_mirred_egress_mirror(const struct tc_action *a)
{
#ifdef CONFIG_NET_CLS_ACT
if (a->ops && a->ops->type == TCA_ACT_MIRRED)
diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
index 5767e9dbcf92..19cd3d345804 100644
--- a/include/net/tc_act/tc_skbedit.h
+++ b/include/net/tc_act/tc_skbedit.h
@@ -27,6 +27,7 @@ struct tcf_skbedit {
u32 flags;
u32 priority;
u32 mark;
+ u32 mask;
u16 queue_mapping;
u16 ptype;
};
diff --git a/include/net/tc_act/tc_tunnel_key.h b/include/net/tc_act/tc_tunnel_key.h
index 253f8da6c2a6..efef0b4b1b2b 100644
--- a/include/net/tc_act/tc_tunnel_key.h
+++ b/include/net/tc_act/tc_tunnel_key.h
@@ -12,6 +12,8 @@
#define __NET_TC_TUNNEL_KEY_H
#include <net/act_api.h>
+#include <linux/tc_act/tc_tunnel_key.h>
+#include <net/dst_metadata.h>
struct tcf_tunnel_key_params {
struct rcu_head rcu;
@@ -27,4 +29,39 @@ struct tcf_tunnel_key {
#define to_tunnel_key(a) ((struct tcf_tunnel_key *)a)
+static inline bool is_tcf_tunnel_set(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ struct tcf_tunnel_key *t = to_tunnel_key(a);
+ struct tcf_tunnel_key_params *params = rtnl_dereference(t->params);
+
+ if (a->ops && a->ops->type == TCA_ACT_TUNNEL_KEY)
+ return params->tcft_action == TCA_TUNNEL_KEY_ACT_SET;
+#endif
+ return false;
+}
+
+static inline bool is_tcf_tunnel_release(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ struct tcf_tunnel_key *t = to_tunnel_key(a);
+ struct tcf_tunnel_key_params *params = rtnl_dereference(t->params);
+
+ if (a->ops && a->ops->type == TCA_ACT_TUNNEL_KEY)
+ return params->tcft_action == TCA_TUNNEL_KEY_ACT_RELEASE;
+#endif
+ return false;
+}
+
+static inline struct ip_tunnel_info *tcf_tunnel_info(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ struct tcf_tunnel_key *t = to_tunnel_key(a);
+ struct tcf_tunnel_key_params *params = rtnl_dereference(t->params);
+
+ return &params->tcft_enc_metadata->u.tun_info;
+#else
+ return NULL;
+#endif
+}
#endif /* __NET_TC_TUNNEL_KEY_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 123979fe12bf..207147b4c6b2 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -958,6 +958,7 @@ u32 tcp_slow_start(struct tcp_sock *tp, u32 acked);
void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked);
u32 tcp_reno_ssthresh(struct sock *sk);
+u32 tcp_reno_undo_cwnd(struct sock *sk);
void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked);
extern struct tcp_congestion_ops tcp_reno;
@@ -1515,11 +1516,26 @@ struct tcp_fastopen_context {
struct rcu_head rcu;
};
+/* Latencies incurred by various limits for a sender. They are
+ * chronograph-like stats that are mutually exclusive.
+ */
+enum tcp_chrono {
+ TCP_CHRONO_UNSPEC,
+ TCP_CHRONO_BUSY, /* Actively sending data (non-empty write queue) */
+ TCP_CHRONO_RWND_LIMITED, /* Stalled by insufficient receive window */
+ TCP_CHRONO_SNDBUF_LIMITED, /* Stalled by insufficient send buffer */
+ __TCP_CHRONO_MAX,
+};
+
+void tcp_chrono_start(struct sock *sk, const enum tcp_chrono type);
+void tcp_chrono_stop(struct sock *sk, const enum tcp_chrono type);
+
/* write queue abstraction */
static inline void tcp_write_queue_purge(struct sock *sk)
{
struct sk_buff *skb;
+ tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
sk_wmem_free_skb(sk, skb);
sk_mem_reclaim(sk);
@@ -1578,8 +1594,10 @@ static inline void tcp_advance_send_head(struct sock *sk, const struct sk_buff *
static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked)
{
- if (sk->sk_send_head == skb_unlinked)
+ if (sk->sk_send_head == skb_unlinked) {
sk->sk_send_head = NULL;
+ tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
+ }
if (tcp_sk(sk)->highest_sack == skb_unlinked)
tcp_sk(sk)->highest_sack = NULL;
}
@@ -1601,6 +1619,7 @@ static inline void tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb
/* Queue it, remembering where we must start sending. */
if (sk->sk_send_head == NULL) {
sk->sk_send_head = skb;
+ tcp_chrono_start(sk, TCP_CHRONO_BUSY);
if (tcp_sk(sk)->highest_sack == NULL)
tcp_sk(sk)->highest_sack = skb;
@@ -1808,7 +1827,7 @@ struct tcp_request_sock_ops {
struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
const struct request_sock *req,
bool *strict);
- __u32 (*init_seq)(const struct sk_buff *skb);
+ __u32 (*init_seq)(const struct sk_buff *skb, u32 *tsoff);
int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
struct flowi *fl, struct request_sock *req,
struct tcp_fastopen_cookie *foc,
diff --git a/include/net/udp.h b/include/net/udp.h
index 4948790d393d..1661791e8ca1 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -246,6 +246,25 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
}
/* net/ipv4/udp.c */
+void udp_destruct_sock(struct sock *sk);
+void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb);
+void udp_skb_destructor(struct sock *sk, struct sk_buff *skb);
+static inline struct sk_buff *
+__skb_recv_udp(struct sock *sk, unsigned int flags, int noblock, int *peeked,
+ int *off, int *err)
+{
+ return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
+ udp_skb_destructor, peeked, off, err);
+}
+static inline struct sk_buff *skb_recv_udp(struct sock *sk, unsigned int flags,
+ int noblock, int *err)
+{
+ int peeked, off = 0;
+
+ return __skb_recv_udp(sk, flags, noblock, &peeked, &off, err);
+}
+
void udp_v4_early_demux(struct sk_buff *skb);
int udp_get_port(struct sock *sk, unsigned short snum,
int (*saddr_cmp)(const struct sock *,
@@ -258,6 +277,7 @@ void udp_flush_pending_frames(struct sock *sk);
void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
int udp_rcv(struct sk_buff *skb);
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+int udp_init_sock(struct sock *sk);
int __udp_disconnect(struct sock *sk, int flags);
int udp_disconnect(struct sock *sk, int flags);
unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 80761938b9a7..36097d388219 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -27,6 +27,7 @@ static __inline__ int udplite_getfrag(void *from, char *to, int offset,
static inline int udplite_sk_init(struct sock *sk)
{
udp_sk(sk)->pcflag = UDPLITE_BIT;
+ sk->sk_destruct = udp_destruct_sock;
return 0;
}
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 308adc4154f4..49a59202f85e 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -281,16 +281,6 @@ struct vxlan_dev {
struct net_device *vxlan_dev_create(struct net *net, const char *name,
u8 name_assign_type, struct vxlan_config *conf);
-static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan,
- unsigned short family)
-{
-#if IS_ENABLED(CONFIG_IPV6)
- if (family == AF_INET6)
- return inet_sk(vxlan->vn6_sock->sock->sk)->inet_sport;
-#endif
- return inet_sk(vxlan->vn4_sock->sock->sk)->inet_sport;
-}
-
static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
netdev_features_t features)
{
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 8a9563144890..8990e580b278 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -414,14 +414,14 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
extern int scsi_execute_req_flags(struct scsi_device *sdev,
const unsigned char *cmd, int data_direction, void *buffer,
unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
- int retries, int *resid, u64 flags);
+ int retries, int *resid, u64 flags, req_flags_t rq_flags);
static inline int scsi_execute_req(struct scsi_device *sdev,
const unsigned char *cmd, int data_direction, void *buffer,
unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
int retries, int *resid)
{
return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
- bufflen, sshdr, timeout, retries, resid, 0);
+ bufflen, sshdr, timeout, retries, resid, 0, 0);
}
extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev);
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index d1defd1ebd95..6ba66e01f6df 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -299,4 +299,21 @@ struct scsi_lun {
#define SCSI_ACCESS_STATE_MASK 0x0f
#define SCSI_ACCESS_STATE_PREFERRED 0x80
+/* Reporting options for REPORT ZONES */
+enum zbc_zone_reporting_options {
+ ZBC_ZONE_REPORTING_OPTION_ALL = 0,
+ ZBC_ZONE_REPORTING_OPTION_EMPTY,
+ ZBC_ZONE_REPORTING_OPTION_IMPLICIT_OPEN,
+ ZBC_ZONE_REPORTING_OPTION_EXPLICIT_OPEN,
+ ZBC_ZONE_REPORTING_OPTION_CLOSED,
+ ZBC_ZONE_REPORTING_OPTION_FULL,
+ ZBC_ZONE_REPORTING_OPTION_READONLY,
+ ZBC_ZONE_REPORTING_OPTION_OFFLINE,
+ ZBC_ZONE_REPORTING_OPTION_NEED_RESET_WP = 0x10,
+ ZBC_ZONE_REPORTING_OPTION_NON_SEQWRITE,
+ ZBC_ZONE_REPORTING_OPTION_NON_WP = 0x3f,
+};
+
+#define ZBC_REPORT_ZONE_PARTIAL 0x80
+
#endif /* _SCSI_PROTO_H_ */
diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h
index 796cabf6be5e..5ab972e116ec 100644
--- a/include/sound/hda_i915.h
+++ b/include/sound/hda_i915.h
@@ -10,8 +10,9 @@
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
void snd_hdac_i915_set_bclk(struct hdac_bus *bus);
-int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate);
-int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
+int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
+ int dev_id, int rate);
+int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_i915_init(struct hdac_bus *bus);
int snd_hdac_i915_exit(struct hdac_bus *bus);
@@ -29,13 +30,13 @@ static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
{
}
static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
- hda_nid_t nid, int rate)
+ hda_nid_t nid, int dev_id, int rate)
{
return 0;
}
static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
- bool *audio_enabled, char *buffer,
- int max_bytes)
+ int dev_id, bool *audio_enabled,
+ char *buffer, int max_bytes)
{
return -ENODEV;
}
diff --git a/include/trace/events/alarmtimer.h b/include/trace/events/alarmtimer.h
new file mode 100644
index 000000000000..a1c108c16c9c
--- /dev/null
+++ b/include/trace/events/alarmtimer.h
@@ -0,0 +1,96 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM alarmtimer
+
+#if !defined(_TRACE_ALARMTIMER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ALARMTIMER_H
+
+#include <linux/alarmtimer.h>
+#include <linux/rtc.h>
+#include <linux/tracepoint.h>
+
+TRACE_DEFINE_ENUM(ALARM_REALTIME);
+TRACE_DEFINE_ENUM(ALARM_BOOTTIME);
+TRACE_DEFINE_ENUM(ALARM_REALTIME_FREEZER);
+TRACE_DEFINE_ENUM(ALARM_BOOTTIME_FREEZER);
+
+#define show_alarm_type(type) __print_flags(type, " | ", \
+ { 1 << ALARM_REALTIME, "REALTIME" }, \
+ { 1 << ALARM_BOOTTIME, "BOOTTIME" }, \
+ { 1 << ALARM_REALTIME_FREEZER, "REALTIME Freezer" }, \
+ { 1 << ALARM_BOOTTIME_FREEZER, "BOOTTIME Freezer" })
+
+TRACE_EVENT(alarmtimer_suspend,
+
+ TP_PROTO(ktime_t expires, int flag),
+
+ TP_ARGS(expires, flag),
+
+ TP_STRUCT__entry(
+ __field(s64, expires)
+ __field(unsigned char, alarm_type)
+ ),
+
+ TP_fast_assign(
+ __entry->expires = expires.tv64;
+ __entry->alarm_type = flag;
+ ),
+
+ TP_printk("alarmtimer type:%s expires:%llu",
+ show_alarm_type((1 << __entry->alarm_type)),
+ __entry->expires
+ )
+);
+
+DECLARE_EVENT_CLASS(alarm_class,
+
+ TP_PROTO(struct alarm *alarm, ktime_t now),
+
+ TP_ARGS(alarm, now),
+
+ TP_STRUCT__entry(
+ __field(void *, alarm)
+ __field(unsigned char, alarm_type)
+ __field(s64, expires)
+ __field(s64, now)
+ ),
+
+ TP_fast_assign(
+ __entry->alarm = alarm;
+ __entry->alarm_type = alarm->type;
+ __entry->expires = alarm->node.expires.tv64;
+ __entry->now = now.tv64;
+ ),
+
+ TP_printk("alarmtimer:%p type:%s expires:%llu now:%llu",
+ __entry->alarm,
+ show_alarm_type((1 << __entry->alarm_type)),
+ __entry->expires,
+ __entry->now
+ )
+);
+
+DEFINE_EVENT(alarm_class, alarmtimer_fired,
+
+ TP_PROTO(struct alarm *alarm, ktime_t now),
+
+ TP_ARGS(alarm, now)
+);
+
+DEFINE_EVENT(alarm_class, alarmtimer_start,
+
+ TP_PROTO(struct alarm *alarm, ktime_t now),
+
+ TP_ARGS(alarm, now)
+);
+
+DEFINE_EVENT(alarm_class, alarmtimer_cancel,
+
+ TP_PROTO(struct alarm *alarm, ktime_t now),
+
+ TP_ARGS(alarm, now)
+);
+
+#endif /* _TRACE_ALARMTIMER_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
index d336b890e31f..df3e9ae5ad8d 100644
--- a/include/trace/events/bcache.h
+++ b/include/trace/events/bcache.h
@@ -27,8 +27,7 @@ DECLARE_EVENT_CLASS(bcache_request,
__entry->sector = bio->bi_iter.bi_sector;
__entry->orig_sector = bio->bi_iter.bi_sector - 16;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
),
TP_printk("%d,%d %s %llu + %u (from %d,%d @ %llu)",
@@ -102,8 +101,7 @@ DECLARE_EVENT_CLASS(bcache_bio,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
),
TP_printk("%d,%d %s %llu + %u",
@@ -138,8 +136,7 @@ TRACE_EVENT(bcache_read,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
__entry->cache_hit = hit;
__entry->bypass = bypass;
),
@@ -170,8 +167,7 @@ TRACE_EVENT(bcache_write,
__entry->inode = inode;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
__entry->writeback = writeback;
__entry->bypass = bypass;
),
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 8f3a163b8166..3e02e3a25413 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -84,8 +84,7 @@ DECLARE_EVENT_CLASS(block_rq_with_error,
0 : blk_rq_sectors(rq);
__entry->errors = rq->errors;
- blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags,
- blk_rq_bytes(rq));
+ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq));
blk_dump_cmd(__get_str(cmd), rq);
),
@@ -163,7 +162,7 @@ TRACE_EVENT(block_rq_complete,
__entry->nr_sector = nr_bytes >> 9;
__entry->errors = rq->errors;
- blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, nr_bytes);
+ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, nr_bytes);
blk_dump_cmd(__get_str(cmd), rq);
),
@@ -199,8 +198,7 @@ DECLARE_EVENT_CLASS(block_rq,
__entry->bytes = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ?
blk_rq_bytes(rq) : 0;
- blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags,
- blk_rq_bytes(rq));
+ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq));
blk_dump_cmd(__get_str(cmd), rq);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -274,8 +272,7 @@ TRACE_EVENT(block_bio_bounce,
bio->bi_bdev->bd_dev : 0;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -313,8 +310,7 @@ TRACE_EVENT(block_bio_complete,
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
__entry->error = error;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
),
TP_printk("%d,%d %s %llu + %u [%d]",
@@ -341,8 +337,7 @@ DECLARE_EVENT_CLASS(block_bio_merge,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -409,8 +404,7 @@ TRACE_EVENT(block_bio_queue,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -438,7 +432,7 @@ DECLARE_EVENT_CLASS(block_get_rq,
__entry->dev = bio ? bio->bi_bdev->bd_dev : 0;
__entry->sector = bio ? bio->bi_iter.bi_sector : 0;
__entry->nr_sector = bio ? bio_sectors(bio) : 0;
- blk_fill_rwbs(__entry->rwbs, bio ? bio_op(bio) : 0,
+ blk_fill_rwbs(__entry->rwbs,
bio ? bio->bi_opf : 0, __entry->nr_sector);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -573,8 +567,7 @@ TRACE_EVENT(block_split,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->new_sector = new_sector;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -617,8 +610,7 @@ TRACE_EVENT(block_bio_remap,
__entry->nr_sector = bio_sectors(bio);
__entry->old_dev = dev;
__entry->old_sector = from;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
- bio->bi_iter.bi_size);
+ blk_fill_rwbs(__entry->rwbs, bio->bi_opf, bio->bi_iter.bi_size);
),
TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu",
@@ -664,8 +656,7 @@ TRACE_EVENT(block_rq_remap,
__entry->old_dev = dev;
__entry->old_sector = from;
__entry->nr_bios = blk_rq_count_bios(rq);
- blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags,
- blk_rq_bytes(rq));
+ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq));
),
TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu %u",
diff --git a/include/trace/events/fence.h b/include/trace/events/dma_fence.h
index d6dfa05ba322..1157cb4c3c6f 100644
--- a/include/trace/events/fence.h
+++ b/include/trace/events/dma_fence.h
@@ -1,17 +1,17 @@
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM fence
+#define TRACE_SYSTEM dma_fence
#if !defined(_TRACE_FENCE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_FENCE_H
+#define _TRACE_DMA_FENCE_H
#include <linux/tracepoint.h>
-struct fence;
+struct dma_fence;
-TRACE_EVENT(fence_annotate_wait_on,
+TRACE_EVENT(dma_fence_annotate_wait_on,
/* fence: the fence waiting on f1, f1: the fence to be waited on. */
- TP_PROTO(struct fence *fence, struct fence *f1),
+ TP_PROTO(struct dma_fence *fence, struct dma_fence *f1),
TP_ARGS(fence, f1),
@@ -48,9 +48,9 @@ TRACE_EVENT(fence_annotate_wait_on,
__entry->waiting_context, __entry->waiting_seqno)
);
-DECLARE_EVENT_CLASS(fence,
+DECLARE_EVENT_CLASS(dma_fence,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence),
@@ -73,56 +73,56 @@ DECLARE_EVENT_CLASS(fence,
__entry->seqno)
);
-DEFINE_EVENT(fence, fence_emit,
+DEFINE_EVENT(dma_fence, dma_fence_emit,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_init,
+DEFINE_EVENT(dma_fence, dma_fence_init,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_destroy,
+DEFINE_EVENT(dma_fence, dma_fence_destroy,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_enable_signal,
+DEFINE_EVENT(dma_fence, dma_fence_enable_signal,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_signaled,
+DEFINE_EVENT(dma_fence, dma_fence_signaled,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_wait_start,
+DEFINE_EVENT(dma_fence, dma_fence_wait_start,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(fence, fence_wait_end,
+DEFINE_EVENT(dma_fence, dma_fence_wait_end,
- TP_PROTO(struct fence *fence),
+ TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-#endif /* _TRACE_FENCE_H */
+#endif /* _TRACE_DMA_FENCE_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 903a09165bb1..5da2c829a718 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -32,7 +32,7 @@ TRACE_DEFINE_ENUM(LFS);
TRACE_DEFINE_ENUM(SSR);
TRACE_DEFINE_ENUM(__REQ_RAHEAD);
TRACE_DEFINE_ENUM(__REQ_SYNC);
-TRACE_DEFINE_ENUM(__REQ_NOIDLE);
+TRACE_DEFINE_ENUM(__REQ_IDLE);
TRACE_DEFINE_ENUM(__REQ_PREFLUSH);
TRACE_DEFINE_ENUM(__REQ_FUA);
TRACE_DEFINE_ENUM(__REQ_PRIO);
@@ -55,7 +55,7 @@ TRACE_DEFINE_ENUM(CP_DISCARD);
{ IPU, "IN-PLACE" }, \
{ OPU, "OUT-OF-PLACE" })
-#define F2FS_BIO_FLAG_MASK(t) (t & (REQ_RAHEAD | WRITE_FLUSH_FUA))
+#define F2FS_BIO_FLAG_MASK(t) (t & (REQ_RAHEAD | REQ_PREFLUSH | REQ_FUA))
#define F2FS_BIO_EXTRA_MASK(t) (t & (REQ_META | REQ_PRIO))
#define show_bio_type(op_flags) show_bio_op_flags(op_flags), \
@@ -65,11 +65,9 @@ TRACE_DEFINE_ENUM(CP_DISCARD);
__print_symbolic(F2FS_BIO_FLAG_MASK(flags), \
{ 0, "WRITE" }, \
{ REQ_RAHEAD, "READAHEAD" }, \
- { READ_SYNC, "READ_SYNC" }, \
- { WRITE_SYNC, "WRITE_SYNC" }, \
- { WRITE_FLUSH, "WRITE_FLUSH" }, \
- { WRITE_FUA, "WRITE_FUA" }, \
- { WRITE_FLUSH_FUA, "WRITE_FLUSH_FUA" })
+ { REQ_SYNC, "REQ_SYNC" }, \
+ { REQ_PREFLUSH, "REQ_PREFLUSH" }, \
+ { REQ_FUA, "REQ_FUA" })
#define show_bio_extra(type) \
__print_symbolic(F2FS_BIO_EXTRA_MASK(type), \
diff --git a/include/trace/events/mdio.h b/include/trace/events/mdio.h
new file mode 100644
index 000000000000..00d85f5f54e4
--- /dev/null
+++ b/include/trace/events/mdio.h
@@ -0,0 +1,42 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mdio
+
+#if !defined(_TRACE_MDIO_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MDIO_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT_CONDITION(mdio_access,
+
+ TP_PROTO(struct mii_bus *bus, char read,
+ u8 addr, unsigned regnum, u16 val, int err),
+
+ TP_ARGS(bus, read, addr, regnum, val, err),
+
+ TP_CONDITION(err >= 0),
+
+ TP_STRUCT__entry(
+ __array(char, busid, MII_BUS_ID_SIZE)
+ __field(char, read)
+ __field(u8, addr)
+ __field(u16, val)
+ __field(unsigned, regnum)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->busid, bus->id, MII_BUS_ID_SIZE);
+ __entry->read = read;
+ __entry->addr = addr;
+ __entry->regnum = regnum;
+ __entry->val = val;
+ ),
+
+ TP_printk("%s %-5s phy:0x%02hhx reg:0x%02x val:0x%04hx",
+ __entry->busid, __entry->read ? "read" : "write",
+ __entry->addr, __entry->regnum, __entry->val)
+);
+
+#endif /* if !defined(_TRACE_MDIO_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index d3e756539d44..9d4f9b3a2b7b 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -698,7 +698,10 @@ TRACE_EVENT(rcu_batch_end,
/*
* Tracepoint for rcutorture readers. The first argument is the name
* of the RCU flavor from rcutorture's viewpoint and the second argument
- * is the callback address.
+ * is the callback address. The third argument is the start time in
+ * seconds, and the last two arguments are the grace period numbers
+ * at the beginning and end of the read, respectively. Note that the
+ * callback address can be NULL.
*/
TRACE_EVENT(rcu_torture_read,
diff --git a/include/trace/events/wbt.h b/include/trace/events/wbt.h
new file mode 100644
index 000000000000..3c518e455680
--- /dev/null
+++ b/include/trace/events/wbt.h
@@ -0,0 +1,153 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM wbt
+
+#if !defined(_TRACE_WBT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_WBT_H
+
+#include <linux/tracepoint.h>
+#include "../../../block/blk-wbt.h"
+
+/**
+ * wbt_stat - trace stats for blk_wb
+ * @stat: array of read/write stats
+ */
+TRACE_EVENT(wbt_stat,
+
+ TP_PROTO(struct backing_dev_info *bdi, struct blk_rq_stat *stat),
+
+ TP_ARGS(bdi, stat),
+
+ TP_STRUCT__entry(
+ __array(char, name, 32)
+ __field(s64, rmean)
+ __field(u64, rmin)
+ __field(u64, rmax)
+ __field(s64, rnr_samples)
+ __field(s64, rtime)
+ __field(s64, wmean)
+ __field(u64, wmin)
+ __field(u64, wmax)
+ __field(s64, wnr_samples)
+ __field(s64, wtime)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->name, dev_name(bdi->dev), 32);
+ __entry->rmean = stat[0].mean;
+ __entry->rmin = stat[0].min;
+ __entry->rmax = stat[0].max;
+ __entry->rnr_samples = stat[0].nr_samples;
+ __entry->wmean = stat[1].mean;
+ __entry->wmin = stat[1].min;
+ __entry->wmax = stat[1].max;
+ __entry->wnr_samples = stat[1].nr_samples;
+ ),
+
+ TP_printk("%s: rmean=%llu, rmin=%llu, rmax=%llu, rsamples=%llu, "
+ "wmean=%llu, wmin=%llu, wmax=%llu, wsamples=%llu\n",
+ __entry->name, __entry->rmean, __entry->rmin, __entry->rmax,
+ __entry->rnr_samples, __entry->wmean, __entry->wmin,
+ __entry->wmax, __entry->wnr_samples)
+);
+
+/**
+ * wbt_lat - trace latency event
+ * @lat: latency trigger
+ */
+TRACE_EVENT(wbt_lat,
+
+ TP_PROTO(struct backing_dev_info *bdi, unsigned long lat),
+
+ TP_ARGS(bdi, lat),
+
+ TP_STRUCT__entry(
+ __array(char, name, 32)
+ __field(unsigned long, lat)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->name, dev_name(bdi->dev), 32);
+ __entry->lat = div_u64(lat, 1000);
+ ),
+
+ TP_printk("%s: latency %lluus\n", __entry->name,
+ (unsigned long long) __entry->lat)
+);
+
+/**
+ * wbt_step - trace wb event step
+ * @msg: context message
+ * @step: the current scale step count
+ * @window: the current monitoring window
+ * @bg: the current background queue limit
+ * @normal: the current normal writeback limit
+ * @max: the current max throughput writeback limit
+ */
+TRACE_EVENT(wbt_step,
+
+ TP_PROTO(struct backing_dev_info *bdi, const char *msg,
+ int step, unsigned long window, unsigned int bg,
+ unsigned int normal, unsigned int max),
+
+ TP_ARGS(bdi, msg, step, window, bg, normal, max),
+
+ TP_STRUCT__entry(
+ __array(char, name, 32)
+ __field(const char *, msg)
+ __field(int, step)
+ __field(unsigned long, window)
+ __field(unsigned int, bg)
+ __field(unsigned int, normal)
+ __field(unsigned int, max)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->name, dev_name(bdi->dev), 32);
+ __entry->msg = msg;
+ __entry->step = step;
+ __entry->window = div_u64(window, 1000);
+ __entry->bg = bg;
+ __entry->normal = normal;
+ __entry->max = max;
+ ),
+
+ TP_printk("%s: %s: step=%d, window=%luus, background=%u, normal=%u, max=%u\n",
+ __entry->name, __entry->msg, __entry->step, __entry->window,
+ __entry->bg, __entry->normal, __entry->max)
+);
+
+/**
+ * wbt_timer - trace wb timer event
+ * @status: timer state status
+ * @step: the current scale step count
+ * @inflight: tracked writes inflight
+ */
+TRACE_EVENT(wbt_timer,
+
+ TP_PROTO(struct backing_dev_info *bdi, unsigned int status,
+ int step, unsigned int inflight),
+
+ TP_ARGS(bdi, status, step, inflight),
+
+ TP_STRUCT__entry(
+ __array(char, name, 32)
+ __field(unsigned int, status)
+ __field(int, step)
+ __field(unsigned int, inflight)
+ ),
+
+ TP_fast_assign(
+ strncpy(__entry->name, dev_name(bdi->dev), 32);
+ __entry->status = status;
+ __entry->step = step;
+ __entry->inflight = inflight;
+ ),
+
+ TP_printk("%s: status=%u, step=%d, inflight=%u\n", __entry->name,
+ __entry->status, __entry->step, __entry->inflight)
+);
+
+#endif /* _TRACE_WBT_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 67d632f1743d..2c748ddad5f8 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -92,4 +92,6 @@
#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index d6b5a21f3d3c..396183628f3c 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -50,6 +50,7 @@ extern "C" {
#define DRM_AMDGPU_WAIT_CS 0x09
#define DRM_AMDGPU_GEM_OP 0x10
#define DRM_AMDGPU_GEM_USERPTR 0x11
+#define DRM_AMDGPU_WAIT_FENCES 0x12
#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
@@ -63,6 +64,7 @@ extern "C" {
#define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs)
#define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op)
#define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
+#define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
#define AMDGPU_GEM_DOMAIN_CPU 0x1
#define AMDGPU_GEM_DOMAIN_GTT 0x2
@@ -81,6 +83,8 @@ extern "C" {
#define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3)
/* Flag that create shadow bo(GTT) while allocating vram bo */
#define AMDGPU_GEM_CREATE_SHADOW (1 << 4)
+/* Flag that allocating the BO should use linear VRAM */
+#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5)
struct drm_amdgpu_gem_create_in {
/** the requested memory size */
@@ -305,6 +309,32 @@ union drm_amdgpu_wait_cs {
struct drm_amdgpu_wait_cs_out out;
};
+struct drm_amdgpu_fence {
+ __u32 ctx_id;
+ __u32 ip_type;
+ __u32 ip_instance;
+ __u32 ring;
+ __u64 seq_no;
+};
+
+struct drm_amdgpu_wait_fences_in {
+ /** This points to uint64_t * which points to fences */
+ __u64 fences;
+ __u32 fence_count;
+ __u32 wait_all;
+ __u64 timeout_ns;
+};
+
+struct drm_amdgpu_wait_fences_out {
+ __u32 status;
+ __u32 first_signaled;
+};
+
+union drm_amdgpu_wait_fences {
+ struct drm_amdgpu_wait_fences_in in;
+ struct drm_amdgpu_wait_fences_out out;
+};
+
#define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0
#define AMDGPU_GEM_OP_SET_PLACEMENT 1
@@ -436,6 +466,7 @@ struct drm_amdgpu_cs_chunk_data {
*
*/
#define AMDGPU_IDS_FLAGS_FUSION 0x1
+#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2
/* indicate if acceleration can be working */
#define AMDGPU_INFO_ACCEL_WORKING 0x00
@@ -487,6 +518,16 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_VIS_VRAM_USAGE 0x17
/* number of TTM buffer evictions */
#define AMDGPU_INFO_NUM_EVICTIONS 0x18
+/* Query memory about VRAM and GTT domains */
+#define AMDGPU_INFO_MEMORY 0x19
+/* Query vce clock table */
+#define AMDGPU_INFO_VCE_CLOCK_TABLE 0x1A
+/* Query vbios related information */
+#define AMDGPU_INFO_VBIOS 0x1B
+ /* Subquery id: Query vbios size */
+ #define AMDGPU_INFO_VBIOS_SIZE 0x1
+ /* Subquery id: Query vbios image */
+ #define AMDGPU_INFO_VBIOS_IMAGE 0x2
#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
@@ -545,6 +586,11 @@ struct drm_amdgpu_info {
} read_mmr_reg;
struct drm_amdgpu_query_fw query_fw;
+
+ struct {
+ __u32 type;
+ __u32 offset;
+ } vbios_info;
};
};
@@ -572,6 +618,34 @@ struct drm_amdgpu_info_vram_gtt {
__u64 gtt_size;
};
+struct drm_amdgpu_heap_info {
+ /** max. physical memory */
+ __u64 total_heap_size;
+
+ /** Theoretical max. available memory in the given heap */
+ __u64 usable_heap_size;
+
+ /**
+ * Number of bytes allocated in the heap. This includes all processes
+ * and private allocations in the kernel. It changes when new buffers
+ * are allocated, freed, and moved. It cannot be larger than
+ * heap_size.
+ */
+ __u64 heap_usage;
+
+ /**
+ * Theoretical possible max. size of buffer which
+ * could be allocated in the given heap
+ */
+ __u64 max_allocation;
+};
+
+struct drm_amdgpu_memory_info {
+ struct drm_amdgpu_heap_info vram;
+ struct drm_amdgpu_heap_info cpu_accessible_vram;
+ struct drm_amdgpu_heap_info gtt;
+};
+
struct drm_amdgpu_info_firmware {
__u32 ver;
__u32 feature;
@@ -645,6 +719,24 @@ struct drm_amdgpu_info_hw_ip {
__u32 _pad;
};
+#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES 6
+
+struct drm_amdgpu_info_vce_clock_table_entry {
+ /** System clock */
+ __u32 sclk;
+ /** Memory clock */
+ __u32 mclk;
+ /** VCE clock */
+ __u32 eclk;
+ __u32 pad;
+};
+
+struct drm_amdgpu_info_vce_clock_table {
+ struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES];
+ __u32 num_valid_entries;
+ __u32 pad;
+};
+
/*
* Supported GPU families
*/
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index df0e3504c349..ce7efe2e8a5e 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -47,7 +47,15 @@ extern "C" {
#define DRM_MODE_TYPE_DRIVER (1<<6)
/* Video mode flags */
-/* bit compatible with the xorg definitions. */
+/* bit compatible with the xrandr RR_ definitions (bits 0-13)
+ *
+ * ABI warning: Existing userspace really expects
+ * the mode flags to match the xrandr definitions. Any
+ * changes that don't match the xrandr definitions will
+ * likely need a new client cap or some other mechanism
+ * to avoid breaking existing userspace. This includes
+ * allocating new flags in the previously unused bits!
+ */
#define DRM_MODE_FLAG_PHSYNC (1<<0)
#define DRM_MODE_FLAG_NHSYNC (1<<1)
#define DRM_MODE_FLAG_PVSYNC (1<<2)
@@ -77,6 +85,19 @@ extern "C" {
#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14)
#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
+/* Picture aspect ratio options */
+#define DRM_MODE_PICTURE_ASPECT_NONE 0
+#define DRM_MODE_PICTURE_ASPECT_4_3 1
+#define DRM_MODE_PICTURE_ASPECT_16_9 2
+
+/* Aspect ratio flag bitmask (4 bits 22:19) */
+#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19)
+#define DRM_MODE_FLAG_PIC_AR_NONE \
+ (DRM_MODE_PICTURE_ASPECT_NONE<<19)
+#define DRM_MODE_FLAG_PIC_AR_4_3 \
+ (DRM_MODE_PICTURE_ASPECT_4_3<<19)
+#define DRM_MODE_FLAG_PIC_AR_16_9 \
+ (DRM_MODE_PICTURE_ASPECT_16_9<<19)
/* DPMS flags */
/* bit compatible with the xorg definitions. */
@@ -92,11 +113,6 @@ extern "C" {
#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */
#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */
-/* Picture aspect ratio options */
-#define DRM_MODE_PICTURE_ASPECT_NONE 0
-#define DRM_MODE_PICTURE_ASPECT_4_3 1
-#define DRM_MODE_PICTURE_ASPECT_16_9 2
-
/* Dithering mode options */
#define DRM_MODE_DITHERING_OFF 0
#define DRM_MODE_DITHERING_ON 1
@@ -220,14 +236,16 @@ struct drm_mode_get_encoder {
/* This is for connectors with multiple signal types. */
/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
-#define DRM_MODE_SUBCONNECTOR_Automatic 0
-#define DRM_MODE_SUBCONNECTOR_Unknown 0
-#define DRM_MODE_SUBCONNECTOR_DVID 3
-#define DRM_MODE_SUBCONNECTOR_DVIA 4
-#define DRM_MODE_SUBCONNECTOR_Composite 5
-#define DRM_MODE_SUBCONNECTOR_SVIDEO 6
-#define DRM_MODE_SUBCONNECTOR_Component 8
-#define DRM_MODE_SUBCONNECTOR_SCART 9
+enum drm_mode_subconnector {
+ DRM_MODE_SUBCONNECTOR_Automatic = 0,
+ DRM_MODE_SUBCONNECTOR_Unknown = 0,
+ DRM_MODE_SUBCONNECTOR_DVID = 3,
+ DRM_MODE_SUBCONNECTOR_DVIA = 4,
+ DRM_MODE_SUBCONNECTOR_Composite = 5,
+ DRM_MODE_SUBCONNECTOR_SVIDEO = 6,
+ DRM_MODE_SUBCONNECTOR_Component = 8,
+ DRM_MODE_SUBCONNECTOR_SCART = 9,
+};
#define DRM_MODE_CONNECTOR_Unknown 0
#define DRM_MODE_CONNECTOR_VGA 1
@@ -392,17 +410,20 @@ struct drm_mode_fb_cmd2 {
* offsets[1]. Note that offsets[0] will generally
* be 0 (but this is not required).
*
- * To accommodate tiled, compressed, etc formats, a per-plane
+ * To accommodate tiled, compressed, etc formats, a
* modifier can be specified. The default value of zero
* indicates "native" format as specified by the fourcc.
- * Vendor specific modifier token. This allows, for example,
- * different tiling/swizzling pattern on different planes.
- * See discussion above of DRM_FORMAT_MOD_xxx.
+ * Vendor specific modifier token. Note that even though
+ * it looks like we have a modifier per-plane, we in fact
+ * do not. The modifier for each plane must be identical.
+ * Thus all combinations of different data layouts for
+ * multi plane formats must be enumerated as separate
+ * modifiers.
*/
__u32 handles[4];
__u32 pitches[4]; /* pitch for each plane */
__u32 offsets[4]; /* offset of each plane */
- __u64 modifier[4]; /* ie, tiling, compressed (per plane) */
+ __u64 modifier[4]; /* ie, tiling, compress */
};
#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 03725fe89859..1c12a350eca3 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -389,6 +389,11 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_MIN_EU_IN_POOL 39
#define I915_PARAM_MMAP_GTT_VERSION 40
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
+ * priorities and the driver will attempt to execute batches in priority order.
+ */
+#define I915_PARAM_HAS_SCHEDULER 41
+
typedef struct drm_i915_getparam {
__s32 param;
/*
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 8c51e8a0df89..4d5d6a2bc59e 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -2,17 +2,24 @@
* 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.
+ * 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:
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
- * 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 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 __MSM_DRM_H__
diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h
index ad7edc3edf7c..f07a09016726 100644
--- a/include/uapi/drm/vc4_drm.h
+++ b/include/uapi/drm/vc4_drm.h
@@ -286,6 +286,8 @@ struct drm_vc4_get_hang_state {
#define DRM_VC4_PARAM_V3D_IDENT1 1
#define DRM_VC4_PARAM_V3D_IDENT2 2
#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3
+#define DRM_VC4_PARAM_SUPPORTS_ETC1 4
+#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5
struct drm_vc4_get_param {
__u32 param;
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index cd2be1c8e9fb..bc2ef9fef7c8 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -70,6 +70,7 @@ header-y += bfs_fs.h
header-y += binfmts.h
header-y += blkpg.h
header-y += blktrace_api.h
+header-y += blkzoned.h
header-y += bpf_common.h
header-y += bpf_perf_event.h
header-y += bpf.h
@@ -426,6 +427,7 @@ header-y += udp.h
header-y += uhid.h
header-y += uinput.h
header-y += uio.h
+header-y += uleds.h
header-y += ultrasound.h
header-y += un.h
header-y += unistd.h
diff --git a/include/uapi/linux/blkzoned.h b/include/uapi/linux/blkzoned.h
new file mode 100644
index 000000000000..40d1d7bff537
--- /dev/null
+++ b/include/uapi/linux/blkzoned.h
@@ -0,0 +1,143 @@
+/*
+ * Zoned block devices handling.
+ *
+ * Copyright (C) 2015 Seagate Technology PLC
+ *
+ * Written by: Shaun Tancheff <shaun.tancheff@seagate.com>
+ *
+ * Modified by: Damien Le Moal <damien.lemoal@hgst.com>
+ * Copyright (C) 2016 Western Digital
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef _UAPI_BLKZONED_H
+#define _UAPI_BLKZONED_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/**
+ * enum blk_zone_type - Types of zones allowed in a zoned device.
+ *
+ * @BLK_ZONE_TYPE_CONVENTIONAL: The zone has no write pointer and can be writen
+ * randomly. Zone reset has no effect on the zone.
+ * @BLK_ZONE_TYPE_SEQWRITE_REQ: The zone must be written sequentially
+ * @BLK_ZONE_TYPE_SEQWRITE_PREF: The zone can be written non-sequentially
+ *
+ * Any other value not defined is reserved and must be considered as invalid.
+ */
+enum blk_zone_type {
+ BLK_ZONE_TYPE_CONVENTIONAL = 0x1,
+ BLK_ZONE_TYPE_SEQWRITE_REQ = 0x2,
+ BLK_ZONE_TYPE_SEQWRITE_PREF = 0x3,
+};
+
+/**
+ * enum blk_zone_cond - Condition [state] of a zone in a zoned device.
+ *
+ * @BLK_ZONE_COND_NOT_WP: The zone has no write pointer, it is conventional.
+ * @BLK_ZONE_COND_EMPTY: The zone is empty.
+ * @BLK_ZONE_COND_IMP_OPEN: The zone is open, but not explicitly opened.
+ * @BLK_ZONE_COND_EXP_OPEN: The zones was explicitly opened by an
+ * OPEN ZONE command.
+ * @BLK_ZONE_COND_CLOSED: The zone was [explicitly] closed after writing.
+ * @BLK_ZONE_COND_FULL: The zone is marked as full, possibly by a zone
+ * FINISH ZONE command.
+ * @BLK_ZONE_COND_READONLY: The zone is read-only.
+ * @BLK_ZONE_COND_OFFLINE: The zone is offline (sectors cannot be read/written).
+ *
+ * The Zone Condition state machine in the ZBC/ZAC standards maps the above
+ * deinitions as:
+ * - ZC1: Empty | BLK_ZONE_EMPTY
+ * - ZC2: Implicit Open | BLK_ZONE_COND_IMP_OPEN
+ * - ZC3: Explicit Open | BLK_ZONE_COND_EXP_OPEN
+ * - ZC4: Closed | BLK_ZONE_CLOSED
+ * - ZC5: Full | BLK_ZONE_FULL
+ * - ZC6: Read Only | BLK_ZONE_READONLY
+ * - ZC7: Offline | BLK_ZONE_OFFLINE
+ *
+ * Conditions 0x5 to 0xC are reserved by the current ZBC/ZAC spec and should
+ * be considered invalid.
+ */
+enum blk_zone_cond {
+ BLK_ZONE_COND_NOT_WP = 0x0,
+ BLK_ZONE_COND_EMPTY = 0x1,
+ BLK_ZONE_COND_IMP_OPEN = 0x2,
+ BLK_ZONE_COND_EXP_OPEN = 0x3,
+ BLK_ZONE_COND_CLOSED = 0x4,
+ BLK_ZONE_COND_READONLY = 0xD,
+ BLK_ZONE_COND_FULL = 0xE,
+ BLK_ZONE_COND_OFFLINE = 0xF,
+};
+
+/**
+ * struct blk_zone - Zone descriptor for BLKREPORTZONE ioctl.
+ *
+ * @start: Zone start in 512 B sector units
+ * @len: Zone length in 512 B sector units
+ * @wp: Zone write pointer location in 512 B sector units
+ * @type: see enum blk_zone_type for possible values
+ * @cond: see enum blk_zone_cond for possible values
+ * @non_seq: Flag indicating that the zone is using non-sequential resources
+ * (for host-aware zoned block devices only).
+ * @reset: Flag indicating that a zone reset is recommended.
+ * @reserved: Padding to 64 B to match the ZBC/ZAC defined zone descriptor size.
+ *
+ * start, len and wp use the regular 512 B sector unit, regardless of the
+ * device logical block size. The overall structure size is 64 B to match the
+ * ZBC/ZAC defined zone descriptor and allow support for future additional
+ * zone information.
+ */
+struct blk_zone {
+ __u64 start; /* Zone start sector */
+ __u64 len; /* Zone length in number of sectors */
+ __u64 wp; /* Zone write pointer position */
+ __u8 type; /* Zone type */
+ __u8 cond; /* Zone condition */
+ __u8 non_seq; /* Non-sequential write resources active */
+ __u8 reset; /* Reset write pointer recommended */
+ __u8 reserved[36];
+};
+
+/**
+ * struct blk_zone_report - BLKREPORTZONE ioctl request/reply
+ *
+ * @sector: starting sector of report
+ * @nr_zones: IN maximum / OUT actual
+ * @reserved: padding to 16 byte alignment
+ * @zones: Space to hold @nr_zones @zones entries on reply.
+ *
+ * The array of at most @nr_zones must follow this structure in memory.
+ */
+struct blk_zone_report {
+ __u64 sector;
+ __u32 nr_zones;
+ __u8 reserved[4];
+ struct blk_zone zones[0];
+} __packed;
+
+/**
+ * struct blk_zone_range - BLKRESETZONE ioctl request
+ * @sector: starting sector of the first zone to issue reset write pointer
+ * @nr_sectors: Total number of sectors of 1 or more zones to reset
+ */
+struct blk_zone_range {
+ __u64 sector;
+ __u64 nr_sectors;
+};
+
+/**
+ * Zoned block device ioctl's:
+ *
+ * @BLKREPORTZONE: Get zone information. Takes a zone report as argument.
+ * The zone report will start from the zone containing the
+ * sector specified in the report request structure.
+ * @BLKRESETZONE: Reset the write pointer of the zones in the specified
+ * sector range. The sector range must be zone aligned.
+ */
+#define BLKREPORTZONE _IOWR(0x12, 130, struct blk_zone_report)
+#define BLKRESETZONE _IOW(0x12, 131, struct blk_zone_range)
+
+#endif /* _UAPI_BLKZONED_H */
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f09c70b97eca..0eb0e87dbe9f 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -73,6 +73,8 @@ enum bpf_cmd {
BPF_PROG_LOAD,
BPF_OBJ_PIN,
BPF_OBJ_GET,
+ BPF_PROG_ATTACH,
+ BPF_PROG_DETACH,
};
enum bpf_map_type {
@@ -85,6 +87,8 @@ enum bpf_map_type {
BPF_MAP_TYPE_PERCPU_ARRAY,
BPF_MAP_TYPE_STACK_TRACE,
BPF_MAP_TYPE_CGROUP_ARRAY,
+ BPF_MAP_TYPE_LRU_HASH,
+ BPF_MAP_TYPE_LRU_PERCPU_HASH,
};
enum bpf_prog_type {
@@ -96,8 +100,22 @@ enum bpf_prog_type {
BPF_PROG_TYPE_TRACEPOINT,
BPF_PROG_TYPE_XDP,
BPF_PROG_TYPE_PERF_EVENT,
+ BPF_PROG_TYPE_CGROUP_SKB,
+ BPF_PROG_TYPE_CGROUP_SOCK,
+ BPF_PROG_TYPE_LWT_IN,
+ BPF_PROG_TYPE_LWT_OUT,
+ BPF_PROG_TYPE_LWT_XMIT,
};
+enum bpf_attach_type {
+ BPF_CGROUP_INET_INGRESS,
+ BPF_CGROUP_INET_EGRESS,
+ BPF_CGROUP_INET_SOCK_CREATE,
+ __MAX_BPF_ATTACH_TYPE
+};
+
+#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
+
#define BPF_PSEUDO_MAP_FD 1
/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -106,6 +124,13 @@ enum bpf_prog_type {
#define BPF_EXIST 2 /* update existing element */
#define BPF_F_NO_PREALLOC (1U << 0)
+/* Instead of having one common LRU list in the
+ * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
+ * which can scale and perform better.
+ * Note, the LRU nodes (including free nodes) cannot be moved
+ * across different LRU lists.
+ */
+#define BPF_F_NO_COMMON_LRU (1U << 1)
union bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */
@@ -141,293 +166,327 @@ union bpf_attr {
__aligned_u64 pathname;
__u32 bpf_fd;
};
+
+ struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
+ __u32 target_fd; /* container object to attach to */
+ __u32 attach_bpf_fd; /* eBPF program to attach */
+ __u32 attach_type;
+ };
} __attribute__((aligned(8)));
+/* BPF helper function descriptions:
+ *
+ * void *bpf_map_lookup_elem(&map, &key)
+ * Return: Map value or NULL
+ *
+ * int bpf_map_update_elem(&map, &key, &value, flags)
+ * Return: 0 on success or negative error
+ *
+ * int bpf_map_delete_elem(&map, &key)
+ * Return: 0 on success or negative error
+ *
+ * int bpf_probe_read(void *dst, int size, void *src)
+ * Return: 0 on success or negative error
+ *
+ * u64 bpf_ktime_get_ns(void)
+ * Return: current ktime
+ *
+ * int bpf_trace_printk(const char *fmt, int fmt_size, ...)
+ * Return: length of buffer written or negative error
+ *
+ * u32 bpf_prandom_u32(void)
+ * Return: random value
+ *
+ * u32 bpf_raw_smp_processor_id(void)
+ * Return: SMP processor ID
+ *
+ * int bpf_skb_store_bytes(skb, offset, from, len, flags)
+ * store bytes into packet
+ * @skb: pointer to skb
+ * @offset: offset within packet from skb->mac_header
+ * @from: pointer where to copy bytes from
+ * @len: number of bytes to store into packet
+ * @flags: bit 0 - if true, recompute skb->csum
+ * other bits - reserved
+ * Return: 0 on success or negative error
+ *
+ * int bpf_l3_csum_replace(skb, offset, from, to, flags)
+ * recompute IP checksum
+ * @skb: pointer to skb
+ * @offset: offset within packet where IP checksum is located
+ * @from: old value of header field
+ * @to: new value of header field
+ * @flags: bits 0-3 - size of header field
+ * other bits - reserved
+ * Return: 0 on success or negative error
+ *
+ * int bpf_l4_csum_replace(skb, offset, from, to, flags)
+ * recompute TCP/UDP checksum
+ * @skb: pointer to skb
+ * @offset: offset within packet where TCP/UDP checksum is located
+ * @from: old value of header field
+ * @to: new value of header field
+ * @flags: bits 0-3 - size of header field
+ * bit 4 - is pseudo header
+ * other bits - reserved
+ * Return: 0 on success or negative error
+ *
+ * int bpf_tail_call(ctx, prog_array_map, index)
+ * jump into another BPF program
+ * @ctx: context pointer passed to next program
+ * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
+ * @index: index inside array that selects specific program to run
+ * Return: 0 on success or negative error
+ *
+ * int bpf_clone_redirect(skb, ifindex, flags)
+ * redirect to another netdev
+ * @skb: pointer to skb
+ * @ifindex: ifindex of the net device
+ * @flags: bit 0 - if set, redirect to ingress instead of egress
+ * other bits - reserved
+ * Return: 0 on success or negative error
+ *
+ * u64 bpf_get_current_pid_tgid(void)
+ * Return: current->tgid << 32 | current->pid
+ *
+ * u64 bpf_get_current_uid_gid(void)
+ * Return: current_gid << 32 | current_uid
+ *
+ * int bpf_get_current_comm(char *buf, int size_of_buf)
+ * stores current->comm into buf
+ * Return: 0 on success or negative error
+ *
+ * u32 bpf_get_cgroup_classid(skb)
+ * retrieve a proc's classid
+ * @skb: pointer to skb
+ * Return: classid if != 0
+ *
+ * int bpf_skb_vlan_push(skb, vlan_proto, vlan_tci)
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_vlan_pop(skb)
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_get_tunnel_key(skb, key, size, flags)
+ * int bpf_skb_set_tunnel_key(skb, key, size, flags)
+ * retrieve or populate tunnel metadata
+ * @skb: pointer to skb
+ * @key: pointer to 'struct bpf_tunnel_key'
+ * @size: size of 'struct bpf_tunnel_key'
+ * @flags: room for future extensions
+ * Return: 0 on success or negative error
+ *
+ * u64 bpf_perf_event_read(&map, index)
+ * Return: Number events read or error code
+ *
+ * int bpf_redirect(ifindex, flags)
+ * redirect to another netdev
+ * @ifindex: ifindex of the net device
+ * @flags: bit 0 - if set, redirect to ingress instead of egress
+ * other bits - reserved
+ * Return: TC_ACT_REDIRECT
+ *
+ * u32 bpf_get_route_realm(skb)
+ * retrieve a dst's tclassid
+ * @skb: pointer to skb
+ * Return: realm if != 0
+ *
+ * int bpf_perf_event_output(ctx, map, index, data, size)
+ * output perf raw sample
+ * @ctx: struct pt_regs*
+ * @map: pointer to perf_event_array map
+ * @index: index of event in the map
+ * @data: data on stack to be output as raw data
+ * @size: size of data
+ * Return: 0 on success or negative error
+ *
+ * int bpf_get_stackid(ctx, map, flags)
+ * walk user or kernel stack and return id
+ * @ctx: struct pt_regs*
+ * @map: pointer to stack_trace map
+ * @flags: bits 0-7 - numer of stack frames to skip
+ * bit 8 - collect user stack instead of kernel
+ * bit 9 - compare stacks by hash only
+ * bit 10 - if two different stacks hash into the same stackid
+ * discard old
+ * other bits - reserved
+ * Return: >= 0 stackid on success or negative error
+ *
+ * s64 bpf_csum_diff(from, from_size, to, to_size, seed)
+ * calculate csum diff
+ * @from: raw from buffer
+ * @from_size: length of from buffer
+ * @to: raw to buffer
+ * @to_size: length of to buffer
+ * @seed: optional seed
+ * Return: csum result or negative error code
+ *
+ * int bpf_skb_get_tunnel_opt(skb, opt, size)
+ * retrieve tunnel options metadata
+ * @skb: pointer to skb
+ * @opt: pointer to raw tunnel option data
+ * @size: size of @opt
+ * Return: option size
+ *
+ * int bpf_skb_set_tunnel_opt(skb, opt, size)
+ * populate tunnel options metadata
+ * @skb: pointer to skb
+ * @opt: pointer to raw tunnel option data
+ * @size: size of @opt
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_change_proto(skb, proto, flags)
+ * Change protocol of the skb. Currently supported is v4 -> v6,
+ * v6 -> v4 transitions. The helper will also resize the skb. eBPF
+ * program is expected to fill the new headers via skb_store_bytes
+ * and lX_csum_replace.
+ * @skb: pointer to skb
+ * @proto: new skb->protocol type
+ * @flags: reserved
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_change_type(skb, type)
+ * Change packet type of skb.
+ * @skb: pointer to skb
+ * @type: new skb->pkt_type type
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_under_cgroup(skb, map, index)
+ * Check cgroup2 membership of skb
+ * @skb: pointer to skb
+ * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+ * @index: index of the cgroup in the bpf_map
+ * Return:
+ * == 0 skb failed the cgroup2 descendant test
+ * == 1 skb succeeded the cgroup2 descendant test
+ * < 0 error
+ *
+ * u32 bpf_get_hash_recalc(skb)
+ * Retrieve and possibly recalculate skb->hash.
+ * @skb: pointer to skb
+ * Return: hash
+ *
+ * u64 bpf_get_current_task(void)
+ * Returns current task_struct
+ * Return: current
+ *
+ * int bpf_probe_write_user(void *dst, void *src, int len)
+ * safely attempt to write to a location
+ * @dst: destination address in userspace
+ * @src: source address on stack
+ * @len: number of bytes to copy
+ * Return: 0 on success or negative error
+ *
+ * int bpf_current_task_under_cgroup(map, index)
+ * Check cgroup2 membership of current task
+ * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+ * @index: index of the cgroup in the bpf_map
+ * Return:
+ * == 0 current failed the cgroup2 descendant test
+ * == 1 current succeeded the cgroup2 descendant test
+ * < 0 error
+ *
+ * int bpf_skb_change_tail(skb, len, flags)
+ * The helper will resize the skb to the given new size, to be used f.e.
+ * with control messages.
+ * @skb: pointer to skb
+ * @len: new skb length
+ * @flags: reserved
+ * Return: 0 on success or negative error
+ *
+ * int bpf_skb_pull_data(skb, len)
+ * The helper will pull in non-linear data in case the skb is non-linear
+ * and not all of len are part of the linear section. Only needed for
+ * read/write with direct packet access.
+ * @skb: pointer to skb
+ * @len: len to make read/writeable
+ * Return: 0 on success or negative error
+ *
+ * s64 bpf_csum_update(skb, csum)
+ * Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
+ * @skb: pointer to skb
+ * @csum: csum to add
+ * Return: csum on success or negative error
+ *
+ * void bpf_set_hash_invalid(skb)
+ * Invalidate current skb->hash.
+ * @skb: pointer to skb
+ *
+ * int bpf_get_numa_node_id()
+ * Return: Id of current NUMA node.
+ *
+ * int bpf_skb_change_head()
+ * Grows headroom of skb and adjusts MAC header offset accordingly.
+ * Will extends/reallocae as required automatically.
+ * May change skb data pointer and will thus invalidate any check
+ * performed for direct packet access.
+ * @skb: pointer to skb
+ * @len: length of header to be pushed in front
+ * @flags: Flags (unused for now)
+ * Return: 0 on success or negative error
+ *
+ * int bpf_xdp_adjust_head(xdp_md, delta)
+ * Adjust the xdp_md.data by delta
+ * @xdp_md: pointer to xdp_md
+ * @delta: An positive/negative integer to be added to xdp_md.data
+ * Return: 0 on success or negative on error
+ */
+#define __BPF_FUNC_MAPPER(FN) \
+ FN(unspec), \
+ FN(map_lookup_elem), \
+ FN(map_update_elem), \
+ FN(map_delete_elem), \
+ FN(probe_read), \
+ FN(ktime_get_ns), \
+ FN(trace_printk), \
+ FN(get_prandom_u32), \
+ FN(get_smp_processor_id), \
+ FN(skb_store_bytes), \
+ FN(l3_csum_replace), \
+ FN(l4_csum_replace), \
+ FN(tail_call), \
+ FN(clone_redirect), \
+ FN(get_current_pid_tgid), \
+ FN(get_current_uid_gid), \
+ FN(get_current_comm), \
+ FN(get_cgroup_classid), \
+ FN(skb_vlan_push), \
+ FN(skb_vlan_pop), \
+ FN(skb_get_tunnel_key), \
+ FN(skb_set_tunnel_key), \
+ FN(perf_event_read), \
+ FN(redirect), \
+ FN(get_route_realm), \
+ FN(perf_event_output), \
+ FN(skb_load_bytes), \
+ FN(get_stackid), \
+ FN(csum_diff), \
+ FN(skb_get_tunnel_opt), \
+ FN(skb_set_tunnel_opt), \
+ FN(skb_change_proto), \
+ FN(skb_change_type), \
+ FN(skb_under_cgroup), \
+ FN(get_hash_recalc), \
+ FN(get_current_task), \
+ FN(probe_write_user), \
+ FN(current_task_under_cgroup), \
+ FN(skb_change_tail), \
+ FN(skb_pull_data), \
+ FN(csum_update), \
+ FN(set_hash_invalid), \
+ FN(get_numa_node_id), \
+ FN(skb_change_head), \
+ FN(xdp_adjust_head),
+
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
*/
+#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x
enum bpf_func_id {
- BPF_FUNC_unspec,
- BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
- BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
- BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
- BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
- BPF_FUNC_ktime_get_ns, /* u64 bpf_ktime_get_ns(void) */
- BPF_FUNC_trace_printk, /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
- BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */
- BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */
-
- /**
- * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet
- * @skb: pointer to skb
- * @offset: offset within packet from skb->mac_header
- * @from: pointer where to copy bytes from
- * @len: number of bytes to store into packet
- * @flags: bit 0 - if true, recompute skb->csum
- * other bits - reserved
- * Return: 0 on success
- */
- BPF_FUNC_skb_store_bytes,
-
- /**
- * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum
- * @skb: pointer to skb
- * @offset: offset within packet where IP checksum is located
- * @from: old value of header field
- * @to: new value of header field
- * @flags: bits 0-3 - size of header field
- * other bits - reserved
- * Return: 0 on success
- */
- BPF_FUNC_l3_csum_replace,
-
- /**
- * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum
- * @skb: pointer to skb
- * @offset: offset within packet where TCP/UDP checksum is located
- * @from: old value of header field
- * @to: new value of header field
- * @flags: bits 0-3 - size of header field
- * bit 4 - is pseudo header
- * other bits - reserved
- * Return: 0 on success
- */
- BPF_FUNC_l4_csum_replace,
-
- /**
- * bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program
- * @ctx: context pointer passed to next program
- * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
- * @index: index inside array that selects specific program to run
- * Return: 0 on success
- */
- BPF_FUNC_tail_call,
-
- /**
- * bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev
- * @skb: pointer to skb
- * @ifindex: ifindex of the net device
- * @flags: bit 0 - if set, redirect to ingress instead of egress
- * other bits - reserved
- * Return: 0 on success
- */
- BPF_FUNC_clone_redirect,
-
- /**
- * u64 bpf_get_current_pid_tgid(void)
- * Return: current->tgid << 32 | current->pid
- */
- BPF_FUNC_get_current_pid_tgid,
-
- /**
- * u64 bpf_get_current_uid_gid(void)
- * Return: current_gid << 32 | current_uid
- */
- BPF_FUNC_get_current_uid_gid,
-
- /**
- * bpf_get_current_comm(char *buf, int size_of_buf)
- * stores current->comm into buf
- * Return: 0 on success
- */
- BPF_FUNC_get_current_comm,
-
- /**
- * bpf_get_cgroup_classid(skb) - retrieve a proc's classid
- * @skb: pointer to skb
- * Return: classid if != 0
- */
- BPF_FUNC_get_cgroup_classid,
- BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
- BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */
-
- /**
- * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags)
- * retrieve or populate tunnel metadata
- * @skb: pointer to skb
- * @key: pointer to 'struct bpf_tunnel_key'
- * @size: size of 'struct bpf_tunnel_key'
- * @flags: room for future extensions
- * Retrun: 0 on success
- */
- BPF_FUNC_skb_get_tunnel_key,
- BPF_FUNC_skb_set_tunnel_key,
- BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */
- /**
- * bpf_redirect(ifindex, flags) - redirect to another netdev
- * @ifindex: ifindex of the net device
- * @flags: bit 0 - if set, redirect to ingress instead of egress
- * other bits - reserved
- * Return: TC_ACT_REDIRECT
- */
- BPF_FUNC_redirect,
-
- /**
- * bpf_get_route_realm(skb) - retrieve a dst's tclassid
- * @skb: pointer to skb
- * Return: realm if != 0
- */
- BPF_FUNC_get_route_realm,
-
- /**
- * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
- * @ctx: struct pt_regs*
- * @map: pointer to perf_event_array map
- * @index: index of event in the map
- * @data: data on stack to be output as raw data
- * @size: size of data
- * Return: 0 on success
- */
- BPF_FUNC_perf_event_output,
- BPF_FUNC_skb_load_bytes,
-
- /**
- * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id
- * @ctx: struct pt_regs*
- * @map: pointer to stack_trace map
- * @flags: bits 0-7 - numer of stack frames to skip
- * bit 8 - collect user stack instead of kernel
- * bit 9 - compare stacks by hash only
- * bit 10 - if two different stacks hash into the same stackid
- * discard old
- * other bits - reserved
- * Return: >= 0 stackid on success or negative error
- */
- BPF_FUNC_get_stackid,
-
- /**
- * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff
- * @from: raw from buffer
- * @from_size: length of from buffer
- * @to: raw to buffer
- * @to_size: length of to buffer
- * @seed: optional seed
- * Return: csum result
- */
- BPF_FUNC_csum_diff,
-
- /**
- * bpf_skb_[gs]et_tunnel_opt(skb, opt, size)
- * retrieve or populate tunnel options metadata
- * @skb: pointer to skb
- * @opt: pointer to raw tunnel option data
- * @size: size of @opt
- * Return: 0 on success for set, option size for get
- */
- BPF_FUNC_skb_get_tunnel_opt,
- BPF_FUNC_skb_set_tunnel_opt,
-
- /**
- * bpf_skb_change_proto(skb, proto, flags)
- * Change protocol of the skb. Currently supported is
- * v4 -> v6, v6 -> v4 transitions. The helper will also
- * resize the skb. eBPF program is expected to fill the
- * new headers via skb_store_bytes and lX_csum_replace.
- * @skb: pointer to skb
- * @proto: new skb->protocol type
- * @flags: reserved
- * Return: 0 on success or negative error
- */
- BPF_FUNC_skb_change_proto,
-
- /**
- * bpf_skb_change_type(skb, type)
- * Change packet type of skb.
- * @skb: pointer to skb
- * @type: new skb->pkt_type type
- * Return: 0 on success or negative error
- */
- BPF_FUNC_skb_change_type,
-
- /**
- * bpf_skb_under_cgroup(skb, map, index) - Check cgroup2 membership of skb
- * @skb: pointer to skb
- * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
- * @index: index of the cgroup in the bpf_map
- * Return:
- * == 0 skb failed the cgroup2 descendant test
- * == 1 skb succeeded the cgroup2 descendant test
- * < 0 error
- */
- BPF_FUNC_skb_under_cgroup,
-
- /**
- * bpf_get_hash_recalc(skb)
- * Retrieve and possibly recalculate skb->hash.
- * @skb: pointer to skb
- * Return: hash
- */
- BPF_FUNC_get_hash_recalc,
-
- /**
- * u64 bpf_get_current_task(void)
- * Returns current task_struct
- * Return: current
- */
- BPF_FUNC_get_current_task,
-
- /**
- * bpf_probe_write_user(void *dst, void *src, int len)
- * safely attempt to write to a location
- * @dst: destination address in userspace
- * @src: source address on stack
- * @len: number of bytes to copy
- * Return: 0 on success or negative error
- */
- BPF_FUNC_probe_write_user,
-
- /**
- * bpf_current_task_under_cgroup(map, index) - Check cgroup2 membership of current task
- * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
- * @index: index of the cgroup in the bpf_map
- * Return:
- * == 0 current failed the cgroup2 descendant test
- * == 1 current succeeded the cgroup2 descendant test
- * < 0 error
- */
- BPF_FUNC_current_task_under_cgroup,
-
- /**
- * bpf_skb_change_tail(skb, len, flags)
- * The helper will resize the skb to the given new size,
- * to be used f.e. with control messages.
- * @skb: pointer to skb
- * @len: new skb length
- * @flags: reserved
- * Return: 0 on success or negative error
- */
- BPF_FUNC_skb_change_tail,
-
- /**
- * bpf_skb_pull_data(skb, len)
- * The helper will pull in non-linear data in case the
- * skb is non-linear and not all of len are part of the
- * linear section. Only needed for read/write with direct
- * packet access.
- * @skb: pointer to skb
- * @len: len to make read/writeable
- * Return: 0 on success or negative error
- */
- BPF_FUNC_skb_pull_data,
-
- /**
- * bpf_csum_update(skb, csum)
- * Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
- * @skb: pointer to skb
- * @csum: csum to add
- * Return: csum on success or negative error
- */
- BPF_FUNC_csum_update,
-
- /**
- * bpf_set_hash_invalid(skb)
- * Invalidate current skb>hash.
- * @skb: pointer to skb
- */
- BPF_FUNC_set_hash_invalid,
-
+ __BPF_FUNC_MAPPER(__BPF_ENUM_FN)
__BPF_FUNC_MAX_ID,
};
+#undef __BPF_ENUM_FN
/* All flags used by eBPF helper functions, placed here. */
@@ -501,6 +560,31 @@ struct bpf_tunnel_key {
__u32 tunnel_label;
};
+/* Generic BPF return codes which all BPF program types may support.
+ * The values are binary compatible with their TC_ACT_* counter-part to
+ * provide backwards compatibility with existing SCHED_CLS and SCHED_ACT
+ * programs.
+ *
+ * XDP is handled seprately, see XDP_*.
+ */
+enum bpf_ret_code {
+ BPF_OK = 0,
+ /* 1 reserved */
+ BPF_DROP = 2,
+ /* 3-6 reserved */
+ BPF_REDIRECT = 7,
+ /* >127 are reserved for prog type specific return codes */
+};
+
+struct bpf_sock {
+ __u32 bound_dev_if;
+ __u32 family;
+ __u32 type;
+ __u32 protocol;
+};
+
+#define XDP_PACKET_HEADROOM 256
+
/* User return codes for XDP prog type.
* A valid XDP program must return one of these defined values. All other
* return codes are reserved for future use. Unknown return codes will result
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 915bfa74458c..9014c33d4e77 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -102,6 +102,13 @@ enum devlink_eswitch_mode {
DEVLINK_ESWITCH_MODE_SWITCHDEV,
};
+enum devlink_eswitch_inline_mode {
+ DEVLINK_ESWITCH_INLINE_MODE_NONE,
+ DEVLINK_ESWITCH_INLINE_MODE_LINK,
+ DEVLINK_ESWITCH_INLINE_MODE_NETWORK,
+ DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT,
+};
+
enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,
@@ -133,6 +140,7 @@ enum devlink_attr {
DEVLINK_ATTR_SB_OCC_CUR, /* u32 */
DEVLINK_ATTR_SB_OCC_MAX, /* u32 */
DEVLINK_ATTR_ESWITCH_MODE, /* u16 */
+ DEVLINK_ATTR_ESWITCH_INLINE_MODE, /* u8 */
/* add new attributes above here, update the policy in devlink.c */
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 8e547231c1b7..f0db7788f887 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -248,6 +248,19 @@ struct ethtool_tunable {
void *data[0];
};
+#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff
+#define DOWNSHIFT_DEV_DISABLE 0
+
+enum phy_tunable_id {
+ ETHTOOL_PHY_ID_UNSPEC,
+ ETHTOOL_PHY_DOWNSHIFT,
+ /*
+ * Add your fresh new phy tunable attribute above and remember to update
+ * phy_tunable_strings[] in net/core/ethtool.c
+ */
+ __ETHTOOL_PHY_TUNABLE_COUNT,
+};
+
/**
* struct ethtool_regs - hardware register dump
* @cmd: Command number = %ETHTOOL_GREGS
@@ -548,6 +561,7 @@ struct ethtool_pauseparam {
* @ETH_SS_FEATURES: Device feature names
* @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
* @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS
+ * @ETH_SS_PHY_TUNABLES: PHY tunable names
*/
enum ethtool_stringset {
ETH_SS_TEST = 0,
@@ -558,6 +572,7 @@ enum ethtool_stringset {
ETH_SS_RSS_HASH_FUNCS,
ETH_SS_TUNABLES,
ETH_SS_PHY_STATS,
+ ETH_SS_PHY_TUNABLES,
};
/**
@@ -1313,7 +1328,8 @@ struct ethtool_per_queue_op {
#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */
#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */
-
+#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */
+#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index 14404b3ebb89..bbf02a63a011 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -29,6 +29,11 @@ struct fib_rule_hdr {
__u32 flags;
};
+struct fib_rule_uid_range {
+ __u32 start;
+ __u32 end;
+};
+
enum {
FRA_UNSPEC,
FRA_DST, /* destination address */
@@ -51,6 +56,7 @@ enum {
FRA_OIFNAME,
FRA_PAD,
FRA_L3MDEV, /* iif or oif is l3mdev goto its table */
+ FRA_UID_RANGE, /* UID range */
__FRA_MAX
};
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index acb2b6152ba0..c1d11df07b28 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -225,6 +225,10 @@ struct fsxattr {
#define BLKSECDISCARD _IO(0x12,125)
#define BLKROTATIONAL _IO(0x12,126)
#define BLKZEROOUT _IO(0x12,127)
+/*
+ * A jump here: 130-131 are reserved for zoned block devices
+ * (see uapi/linux/blkzoned.h)
+ */
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
index 5512c90af7e3..adc899381e0d 100644
--- a/include/uapi/linux/genetlink.h
+++ b/include/uapi/linux/genetlink.h
@@ -26,10 +26,11 @@ struct genlmsghdr {
/*
* List of reserved static generic netlink identifiers:
*/
-#define GENL_ID_GENERATE 0
#define GENL_ID_CTRL NLMSG_MIN_TYPE
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
+/* must be last reserved + 1 */
+#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
/**************************************************************************
* Controller
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 117d02e0fc31..3e5185e9ef03 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -35,6 +35,9 @@
#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
#define ETH_FCS_LEN 4 /* Octets in the FCS */
+#define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */
+#define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU */
+
/*
* These are the defined Ethernet Protocol ID's.
*/
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index b4fba662cd32..6b13e591abc9 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -275,6 +275,8 @@ enum {
IFLA_BR_PAD,
IFLA_BR_VLAN_STATS_ENABLED,
IFLA_BR_MCAST_STATS_ENABLED,
+ IFLA_BR_MCAST_IGMP_VERSION,
+ IFLA_BR_MCAST_MLD_VERSION,
__IFLA_BR_MAX,
};
@@ -874,10 +876,14 @@ enum {
/* XDP section */
+#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
+#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST)
+
enum {
IFLA_XDP_UNSPEC,
IFLA_XDP_FD,
IFLA_XDP_ATTACHED,
+ IFLA_XDP_FLAGS,
__IFLA_XDP_MAX,
};
diff --git a/include/uapi/linux/if_pppol2tp.h b/include/uapi/linux/if_pppol2tp.h
index 4bd1f55d6377..6418c4d10241 100644
--- a/include/uapi/linux/if_pppol2tp.h
+++ b/include/uapi/linux/if_pppol2tp.h
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/in.h>
#include <linux/in6.h>
+#include <linux/l2tp.h>
/* Structure used to connect() the socket to a particular tunnel UDP
* socket over IPv4.
@@ -90,14 +91,12 @@ enum {
PPPOL2TP_SO_REORDERTO = 5,
};
-/* Debug message categories for the DEBUG socket option */
+/* Debug message categories for the DEBUG socket option (deprecated) */
enum {
- PPPOL2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if
- * compiled in) */
- PPPOL2TP_MSG_CONTROL = (1 << 1), /* userspace - kernel
- * interface */
- PPPOL2TP_MSG_SEQ = (1 << 2), /* sequence numbers */
- PPPOL2TP_MSG_DATA = (1 << 3), /* data packets */
+ PPPOL2TP_MSG_DEBUG = L2TP_MSG_DEBUG,
+ PPPOL2TP_MSG_CONTROL = L2TP_MSG_CONTROL,
+ PPPOL2TP_MSG_SEQ = L2TP_MSG_SEQ,
+ PPPOL2TP_MSG_DATA = L2TP_MSG_DATA,
};
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
index eaf94919291a..4e557f4e9553 100644
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -117,6 +117,7 @@ struct in_addr {
#define IP_NODEFRAG 22
#define IP_CHECKSUM 23
#define IP_BIND_ADDRESS_NO_PORT 24
+#define IP_RECVFRAGSIZE 25
/* IP_MTU_DISCOVER values */
#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index b39ea4f2e701..46444f8fbee4 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -283,6 +283,7 @@ struct in6_flowlabel_req {
#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
#define IPV6_TRANSPARENT 75
#define IPV6_UNICAST_IF 76
+#define IPV6_RECVFRAGSIZE 77
/*
* Multicast Routing:
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 509cd961068d..bbe201047df6 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -43,6 +43,23 @@ struct inet_diag_req_v2 {
struct inet_diag_sockid id;
};
+/*
+ * SOCK_RAW sockets require the underlied protocol to be
+ * additionally specified so we can use @pad member for
+ * this, but we can't rename it because userspace programs
+ * still may depend on this name. Instead lets use another
+ * structure definition as an alias for struct
+ * @inet_diag_req_v2.
+ */
+struct inet_diag_req_raw {
+ __u8 sdiag_family;
+ __u8 sdiag_protocol;
+ __u8 idiag_ext;
+ __u8 sdiag_raw_protocol;
+ __u32 idiag_states;
+ struct inet_diag_sockid id;
+};
+
enum {
INET_DIAG_REQ_NONE,
INET_DIAG_REQ_BYTECODE,
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index 8c2772340c3f..eaf65dc82e22 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -39,6 +39,7 @@ struct in6_ifreq {
#define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */
#define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */
#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */
+#define IPV6_SRCRT_TYPE_4 4 /* Segment Routing with IPv6 */
/*
* routing header
@@ -178,6 +179,9 @@ enum {
DEVCONF_DROP_UNSOLICITED_NA,
DEVCONF_KEEP_ADDR_ON_DOWN,
DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
+ DEVCONF_SEG6_ENABLED,
+ DEVCONF_SEG6_REQUIRE_HMAC,
+ DEVCONF_ENHANCED_DAD,
DEVCONF_MAX
};
diff --git a/include/uapi/linux/l2tp.h b/include/uapi/linux/l2tp.h
index 4bd27d0270a2..85ddb74fcd1c 100644
--- a/include/uapi/linux/l2tp.h
+++ b/include/uapi/linux/l2tp.h
@@ -108,7 +108,7 @@ enum {
L2TP_ATTR_VLAN_ID, /* u16 */
L2TP_ATTR_COOKIE, /* 0, 4 or 8 bytes */
L2TP_ATTR_PEER_COOKIE, /* 0, 4 or 8 bytes */
- L2TP_ATTR_DEBUG, /* u32 */
+ L2TP_ATTR_DEBUG, /* u32, enum l2tp_debug_flags */
L2TP_ATTR_RECV_SEQ, /* u8 */
L2TP_ATTR_SEND_SEQ, /* u8 */
L2TP_ATTR_LNS_MODE, /* u8 */
@@ -124,8 +124,8 @@ enum {
L2TP_ATTR_STATS, /* nested */
L2TP_ATTR_IP6_SADDR, /* struct in6_addr */
L2TP_ATTR_IP6_DADDR, /* struct in6_addr */
- L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* u8 */
- L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* u8 */
+ L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* flag */
+ L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* flag */
L2TP_ATTR_PAD,
__L2TP_ATTR_MAX,
};
@@ -175,6 +175,21 @@ enum l2tp_seqmode {
L2TP_SEQ_ALL = 2,
};
+/**
+ * enum l2tp_debug_flags - debug message categories for L2TP tunnels/sessions
+ *
+ * @L2TP_MSG_DEBUG: verbose debug (if compiled in)
+ * @L2TP_MSG_CONTROL: userspace - kernel interface
+ * @L2TP_MSG_SEQ: sequence numbers
+ * @L2TP_MSG_DATA: data packets
+ */
+enum l2tp_debug_flags {
+ L2TP_MSG_DEBUG = (1 << 0),
+ L2TP_MSG_CONTROL = (1 << 1),
+ L2TP_MSG_SEQ = (1 << 2),
+ L2TP_MSG_DATA = (1 << 3),
+};
+
/*
* NETLINK_GENERIC related info
*/
diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h
index a478fe80e203..92724cba1eba 100644
--- a/include/uapi/linux/lwtunnel.h
+++ b/include/uapi/linux/lwtunnel.h
@@ -9,6 +9,8 @@ enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_IP,
LWTUNNEL_ENCAP_ILA,
LWTUNNEL_ENCAP_IP6,
+ LWTUNNEL_ENCAP_SEG6,
+ LWTUNNEL_ENCAP_BPF,
__LWTUNNEL_ENCAP_MAX,
};
@@ -42,4 +44,26 @@ enum lwtunnel_ip6_t {
#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1)
+enum {
+ LWT_BPF_PROG_UNSPEC,
+ LWT_BPF_PROG_FD,
+ LWT_BPF_PROG_NAME,
+ __LWT_BPF_PROG_MAX,
+};
+
+#define LWT_BPF_PROG_MAX (__LWT_BPF_PROG_MAX - 1)
+
+enum {
+ LWT_BPF_UNSPEC,
+ LWT_BPF_IN,
+ LWT_BPF_OUT,
+ LWT_BPF_XMIT,
+ LWT_BPF_XMIT_HEADROOM,
+ __LWT_BPF_MAX,
+};
+
+#define LWT_BPF_MAX (__LWT_BPF_MAX - 1)
+
+#define LWT_BPF_MAX_HEADROOM 256
+
#endif /* _UAPI_LWTUNNEL_H_ */
diff --git a/include/uapi/linux/major.h b/include/uapi/linux/major.h
index 620252e69b44..19e195bee990 100644
--- a/include/uapi/linux/major.h
+++ b/include/uapi/linux/major.h
@@ -3,7 +3,7 @@
/*
* This file has definitions for major device numbers.
- * For the device number assignments, see Documentation/devices.txt.
+ * For the device number assignments, see Documentation/admin-guide/devices.rst.
*/
#define UNNAMED_MAJOR 0
diff --git a/include/uapi/linux/mmc/ioctl.h b/include/uapi/linux/mmc/ioctl.h
index 7e385b83b9d8..700a55156eee 100644
--- a/include/uapi/linux/mmc/ioctl.h
+++ b/include/uapi/linux/mmc/ioctl.h
@@ -69,6 +69,6 @@ struct mmc_ioc_multi_cmd {
* is enforced per ioctl call. For larger data transfers, use the normal
* block device operations.
*/
-#define MMC_IOC_MAX_BYTES (512L * 256)
+#define MMC_IOC_MAX_BYTES (512L * 1024)
#define MMC_IOC_MAX_CMDS 255
#endif /* LINUX_MMC_IOCTL_H */
diff --git a/include/uapi/linux/nbd.h b/include/uapi/linux/nbd.h
index e08e413d5f71..c91c642ea900 100644
--- a/include/uapi/linux/nbd.h
+++ b/include/uapi/linux/nbd.h
@@ -38,11 +38,12 @@ enum {
};
/* values for flags field */
-#define NBD_FLAG_HAS_FLAGS (1 << 0) /* nbd-server supports flags */
-#define NBD_FLAG_READ_ONLY (1 << 1) /* device is read-only */
-#define NBD_FLAG_SEND_FLUSH (1 << 2) /* can flush writeback cache */
+#define NBD_FLAG_HAS_FLAGS (1 << 0) /* nbd-server supports flags */
+#define NBD_FLAG_READ_ONLY (1 << 1) /* device is read-only */
+#define NBD_FLAG_SEND_FLUSH (1 << 2) /* can flush writeback cache */
/* there is a gap here to match userspace */
-#define NBD_FLAG_SEND_TRIM (1 << 5) /* send trim/discard */
+#define NBD_FLAG_SEND_TRIM (1 << 5) /* send trim/discard */
+#define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Server supports multiple connections per export. */
/* userspace doesn't need the nbd_device structure */
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index 264e515de16f..464dcca5ed68 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -25,8 +25,9 @@ enum {
SOF_TIMESTAMPING_TX_ACK = (1<<9),
SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),
+ SOF_TIMESTAMPING_OPT_STATS = (1<<12),
- SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TSONLY,
+ SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_STATS,
SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
SOF_TIMESTAMPING_LAST
};
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index d93f949d1d9a..7550e9176a54 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -13,7 +13,7 @@
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
-#define NF_STOP 5
+#define NF_STOP 5 /* Deprecated, for userspace nf_queue compatibility. */
#define NF_MAX_VERDICT NF_STOP
/* we overload the higher bits for encoding auxiliary data such as the queue
diff --git a/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h b/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
index a9c3834abdd4..526b42496b78 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
@@ -2,7 +2,10 @@
#define _NF_CONNTRACK_TUPLE_COMMON_H
#include <linux/types.h>
+#ifndef __KERNEL__
#include <linux/netfilter.h>
+#endif
+#include <linux/netfilter/nf_conntrack_common.h> /* IP_CT_IS_REPLY */
enum ip_conntrack_dir {
IP_CT_DIR_ORIGINAL,
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index c6c4477c136b..881d49e94569 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -4,6 +4,7 @@
#define NFT_TABLE_MAXNAMELEN 32
#define NFT_CHAIN_MAXNAMELEN 32
#define NFT_SET_MAXNAMELEN 32
+#define NFT_OBJ_MAXNAMELEN 32
#define NFT_USERDATA_MAXLEN 256
/**
@@ -85,6 +86,10 @@ enum nft_verdicts {
* @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes)
* @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes)
* @NFT_MSG_TRACE: trace event (enum nft_trace_attributes)
+ * @NFT_MSG_NEWOBJ: create a stateful object (enum nft_obj_attributes)
+ * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes)
+ * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes)
+ * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes)
*/
enum nf_tables_msg_types {
NFT_MSG_NEWTABLE,
@@ -105,6 +110,10 @@ enum nf_tables_msg_types {
NFT_MSG_NEWGEN,
NFT_MSG_GETGEN,
NFT_MSG_TRACE,
+ NFT_MSG_NEWOBJ,
+ NFT_MSG_GETOBJ,
+ NFT_MSG_DELOBJ,
+ NFT_MSG_GETOBJ_RESET,
NFT_MSG_MAX,
};
@@ -246,6 +255,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_MAP: set is used as a dictionary
* @NFT_SET_TIMEOUT: set uses timeouts
* @NFT_SET_EVAL: set contains expressions for evaluation
+ * @NFT_SET_OBJECT: set contains stateful objects
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
@@ -254,6 +264,7 @@ enum nft_set_flags {
NFT_SET_MAP = 0x8,
NFT_SET_TIMEOUT = 0x10,
NFT_SET_EVAL = 0x20,
+ NFT_SET_OBJECT = 0x40,
};
/**
@@ -295,6 +306,7 @@ enum nft_set_desc_attributes {
* @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
* @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
* @NFTA_SET_USERDATA: user data (NLA_BINARY)
+ * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
@@ -312,6 +324,7 @@ enum nft_set_attributes {
NFTA_SET_GC_INTERVAL,
NFTA_SET_USERDATA,
NFTA_SET_PAD,
+ NFTA_SET_OBJ_TYPE,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -335,6 +348,7 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
+ * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING)
*/
enum nft_set_elem_attributes {
NFTA_SET_ELEM_UNSPEC,
@@ -346,6 +360,7 @@ enum nft_set_elem_attributes {
NFTA_SET_ELEM_USERDATA,
NFTA_SET_ELEM_EXPR,
NFTA_SET_ELEM_PAD,
+ NFTA_SET_ELEM_OBJREF,
__NFTA_SET_ELEM_MAX
};
#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -659,6 +674,10 @@ enum nft_payload_csum_types {
NFT_PAYLOAD_CSUM_INET,
};
+enum nft_payload_csum_flags {
+ NFT_PAYLOAD_L4CSUM_PSEUDOHDR = (1 << 0),
+};
+
/**
* enum nft_payload_attributes - nf_tables payload expression netlink attributes
*
@@ -669,6 +688,7 @@ enum nft_payload_csum_types {
* @NFTA_PAYLOAD_SREG: source register to load data from (NLA_U32: nft_registers)
* @NFTA_PAYLOAD_CSUM_TYPE: checksum type (NLA_U32)
* @NFTA_PAYLOAD_CSUM_OFFSET: checksum offset relative to base (NLA_U32)
+ * @NFTA_PAYLOAD_CSUM_FLAGS: checksum flags (NLA_U32)
*/
enum nft_payload_attributes {
NFTA_PAYLOAD_UNSPEC,
@@ -679,6 +699,7 @@ enum nft_payload_attributes {
NFTA_PAYLOAD_SREG,
NFTA_PAYLOAD_CSUM_TYPE,
NFTA_PAYLOAD_CSUM_OFFSET,
+ NFTA_PAYLOAD_CSUM_FLAGS,
__NFTA_PAYLOAD_MAX
};
#define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1)
@@ -759,6 +780,19 @@ enum nft_meta_keys {
};
/**
+ * enum nft_rt_keys - nf_tables routing expression keys
+ *
+ * @NFT_RT_CLASSID: realm value of packet's route (skb->dst->tclassid)
+ * @NFT_RT_NEXTHOP4: routing nexthop for IPv4
+ * @NFT_RT_NEXTHOP6: routing nexthop for IPv6
+ */
+enum nft_rt_keys {
+ NFT_RT_CLASSID,
+ NFT_RT_NEXTHOP4,
+ NFT_RT_NEXTHOP6,
+};
+
+/**
* enum nft_hash_attributes - nf_tables hash expression netlink attributes
*
* @NFTA_HASH_SREG: source register (NLA_U32)
@@ -797,6 +831,20 @@ enum nft_meta_attributes {
#define NFTA_META_MAX (__NFTA_META_MAX - 1)
/**
+ * enum nft_rt_attributes - nf_tables routing expression netlink attributes
+ *
+ * @NFTA_RT_DREG: destination register (NLA_U32)
+ * @NFTA_RT_KEY: routing data item to load (NLA_U32: nft_rt_keys)
+ */
+enum nft_rt_attributes {
+ NFTA_RT_UNSPEC,
+ NFTA_RT_DREG,
+ NFTA_RT_KEY,
+ __NFTA_RT_MAX
+};
+#define NFTA_RT_MAX (__NFTA_RT_MAX - 1)
+
+/**
* enum nft_ct_keys - nf_tables ct expression keys
*
* @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
@@ -941,6 +989,7 @@ enum nft_queue_attributes {
enum nft_quota_flags {
NFT_QUOTA_F_INV = (1 << 0),
+ NFT_QUOTA_F_DEPLETED = (1 << 1),
};
/**
@@ -948,12 +997,14 @@ enum nft_quota_flags {
*
* @NFTA_QUOTA_BYTES: quota in bytes (NLA_U16)
* @NFTA_QUOTA_FLAGS: flags (NLA_U32)
+ * @NFTA_QUOTA_CONSUMED: quota already consumed in bytes (NLA_U64)
*/
enum nft_quota_attributes {
NFTA_QUOTA_UNSPEC,
NFTA_QUOTA_BYTES,
NFTA_QUOTA_FLAGS,
NFTA_QUOTA_PAD,
+ NFTA_QUOTA_CONSUMED,
__NFTA_QUOTA_MAX
};
#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)
@@ -1098,6 +1149,26 @@ enum nft_fwd_attributes {
#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
/**
+ * enum nft_objref_attributes - nf_tables stateful object expression netlink attributes
+ *
+ * @NFTA_OBJREF_IMM_TYPE: object type for immediate reference (NLA_U32: nft_register)
+ * @NFTA_OBJREF_IMM_NAME: object name for immediate reference (NLA_STRING)
+ * @NFTA_OBJREF_SET_SREG: source register of the data to look for (NLA_U32: nft_registers)
+ * @NFTA_OBJREF_SET_NAME: name of the set where to look for (NLA_STRING)
+ * @NFTA_OBJREF_SET_ID: id of the set where to look for in this transaction (NLA_U32)
+ */
+enum nft_objref_attributes {
+ NFTA_OBJREF_UNSPEC,
+ NFTA_OBJREF_IMM_TYPE,
+ NFTA_OBJREF_IMM_NAME,
+ NFTA_OBJREF_SET_SREG,
+ NFTA_OBJREF_SET_NAME,
+ NFTA_OBJREF_SET_ID,
+ __NFTA_OBJREF_MAX
+};
+#define NFTA_OBJREF_MAX (__NFTA_OBJREF_MAX - 1)
+
+/**
* enum nft_gen_attributes - nf_tables ruleset generation attributes
*
* @NFTA_GEN_ID: Ruleset generation ID (NLA_U32)
@@ -1109,6 +1180,68 @@ enum nft_gen_attributes {
};
#define NFTA_GEN_MAX (__NFTA_GEN_MAX - 1)
+/*
+ * enum nft_fib_attributes - nf_tables fib expression netlink attributes
+ *
+ * @NFTA_FIB_DREG: destination register (NLA_U32)
+ * @NFTA_FIB_RESULT: desired result (NLA_U32)
+ * @NFTA_FIB_FLAGS: flowi fields to initialize when querying the FIB (NLA_U32)
+ *
+ * The FIB expression performs a route lookup according
+ * to the packet data.
+ */
+enum nft_fib_attributes {
+ NFTA_FIB_UNSPEC,
+ NFTA_FIB_DREG,
+ NFTA_FIB_RESULT,
+ NFTA_FIB_FLAGS,
+ __NFTA_FIB_MAX
+};
+#define NFTA_FIB_MAX (__NFTA_FIB_MAX - 1)
+
+enum nft_fib_result {
+ NFT_FIB_RESULT_UNSPEC,
+ NFT_FIB_RESULT_OIF,
+ NFT_FIB_RESULT_OIFNAME,
+ NFT_FIB_RESULT_ADDRTYPE,
+ __NFT_FIB_RESULT_MAX
+};
+#define NFT_FIB_RESULT_MAX (__NFT_FIB_RESULT_MAX - 1)
+
+enum nft_fib_flags {
+ NFTA_FIB_F_SADDR = 1 << 0, /* look up src */
+ NFTA_FIB_F_DADDR = 1 << 1, /* look up dst */
+ NFTA_FIB_F_MARK = 1 << 2, /* use skb->mark */
+ NFTA_FIB_F_IIF = 1 << 3, /* restrict to iif */
+ NFTA_FIB_F_OIF = 1 << 4, /* restrict to oif */
+};
+
+#define NFT_OBJECT_UNSPEC 0
+#define NFT_OBJECT_COUNTER 1
+#define NFT_OBJECT_QUOTA 2
+#define __NFT_OBJECT_MAX 3
+#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
+
+/**
+ * enum nft_object_attributes - nf_tables stateful object netlink attributes
+ *
+ * @NFTA_OBJ_TABLE: name of the table containing the expression (NLA_STRING)
+ * @NFTA_OBJ_NAME: name of this expression type (NLA_STRING)
+ * @NFTA_OBJ_TYPE: stateful object type (NLA_U32)
+ * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
+ * @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
+ */
+enum nft_object_attributes {
+ NFTA_OBJ_UNSPEC,
+ NFTA_OBJ_TABLE,
+ NFTA_OBJ_NAME,
+ NFTA_OBJ_TYPE,
+ NFTA_OBJ_DATA,
+ NFTA_OBJ_USE,
+ __NFTA_OBJ_MAX
+};
+#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
+
/**
* enum nft_trace_attributes - nf_tables trace netlink attributes
*
diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h
index 1fad2c27ac32..b97725af2ac0 100644
--- a/include/uapi/linux/netfilter/xt_bpf.h
+++ b/include/uapi/linux/netfilter/xt_bpf.h
@@ -2,9 +2,11 @@
#define _XT_BPF_H
#include <linux/filter.h>
+#include <linux/limits.h>
#include <linux/types.h>
#define XT_BPF_MAX_NUM_INSTR 64
+#define XT_BPF_PATH_MAX (XT_BPF_MAX_NUM_INSTR * sizeof(struct sock_filter))
struct bpf_prog;
@@ -16,4 +18,23 @@ struct xt_bpf_info {
struct bpf_prog *filter __attribute__((aligned(8)));
};
+enum xt_bpf_modes {
+ XT_BPF_MODE_BYTECODE,
+ XT_BPF_MODE_FD_PINNED,
+ XT_BPF_MODE_FD_ELF,
+};
+
+struct xt_bpf_info_v1 {
+ __u16 mode;
+ __u16 bpf_program_num_elem;
+ __s32 fd;
+ union {
+ struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR];
+ char path[XT_BPF_PATH_MAX];
+ };
+
+ /* only used in the kernel */
+ struct bpf_prog *filter __attribute__((aligned(8)));
+};
+
#endif /*_XT_BPF_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9b4622..6b76e3b0c18e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -323,7 +323,7 @@
* @NL80211_CMD_GET_SCAN: get scan results
* @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
* %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
- * probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to
+ * probe requests at CCK rate or not. %NL80211_ATTR_BSSID can be used to
* specify a BSSID to scan for; if not included, the wildcard BSSID will
* be used.
* @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
@@ -600,6 +600,20 @@
*
* @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
*
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform
+ * multicast to unicast conversion. When enabled, all multicast packets
+ * with ethertype ARP, IPv4 or IPv6 (possibly within an 802.1Q header)
+ * will be sent out to each station once with the destination (multicast)
+ * MAC address replaced by the station's MAC address. Note that this may
+ * break certain expectations of the receiver, e.g. the ability to drop
+ * unicast IP packets encapsulated in multicast L2 frames, or the ability
+ * to not send destination unreachable messages in such cases.
+ * This can only be toggled per BSS. Configure this on an interface of
+ * type %NL80211_IFTYPE_AP. It applies to all its VLAN interfaces
+ * (%NL80211_IFTYPE_AP_VLAN), except for those in 4addr (WDS) mode.
+ * If %NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED is not present with this
+ * command, the feature is disabled.
+ *
* @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
* mesh config parameters may be given.
* @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
@@ -874,6 +888,12 @@
* This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
* %NL80211_ATTR_COOKIE.
*
+ * @NL80211_CMD_UPDATE_CONNECT_PARAMS: Update one or more connect parameters
+ * for subsequent roaming cases if the driver or firmware uses internal
+ * BSS selection. This command can be issued only while connected and it
+ * does not result in a change for the current association. Currently,
+ * only the %NL80211_ATTR_IE data is used and updated with this command.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1069,6 +1089,10 @@ enum nl80211_commands {
NL80211_CMD_CHANGE_NAN_CONFIG,
NL80211_CMD_NAN_MATCH,
+ NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
+ NL80211_CMD_UPDATE_CONNECT_PARAMS,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1638,8 +1662,16 @@ enum nl80211_commands {
* the connection request from a station. nl80211_connect_failed_reason
* enum has different reasons of connection failure.
*
- * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
- * with the Authentication transaction sequence number field.
+ * @NL80211_ATTR_AUTH_DATA: Fields and elements in Authentication frames.
+ * This contains the authentication frame body (non-IE and IE data),
+ * excluding the Authentication algorithm number, i.e., starting at the
+ * Authentication transaction sequence number field. It is used with
+ * authentication algorithms that need special fields to be added into
+ * the frames (SAE and FILS). Currently, only the SAE cases use the
+ * initial two fields (Authentication transaction sequence number and
+ * Status code). However, those fields are included in the attribute data
+ * for all authentication algorithms to keep the attribute definition
+ * consistent.
*
* @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
* association request when used with NL80211_CMD_NEW_STATION)
@@ -1936,6 +1968,17 @@ enum nl80211_commands {
* attribute.
* @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute.
* See &enum nl80211_nan_match_attributes.
+ * @NL80211_ATTR_FILS_KEK: KEK for FILS (Re)Association Request/Response frame
+ * protection.
+ * @NL80211_ATTR_FILS_NONCES: Nonces (part of AAD) for FILS (Re)Association
+ * Request/Response frame protection. This attribute contains the 16 octet
+ * STA Nonce followed by 16 octets of AP Nonce.
+ *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
+ * packets should be send out as unicast to all stations (flag attribute).
+ *
+ * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
+ * used in various commands/events for specifying the BSSID.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2195,7 +2238,7 @@ enum nl80211_attrs {
NL80211_ATTR_CONN_FAILED_REASON,
- NL80211_ATTR_SAE_DATA,
+ NL80211_ATTR_AUTH_DATA,
NL80211_ATTR_VHT_CAPABILITY,
@@ -2336,6 +2379,13 @@ enum nl80211_attrs {
NL80211_ATTR_NAN_FUNC,
NL80211_ATTR_NAN_MATCH,
+ NL80211_ATTR_FILS_KEK,
+ NL80211_ATTR_FILS_NONCES,
+
+ NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
+ NL80211_ATTR_BSSID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2347,6 +2397,7 @@ enum nl80211_attrs {
#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
+#define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA
/*
* Allow user space programs to use #ifdef on new attributes by defining them
@@ -3660,6 +3711,9 @@ enum nl80211_bss_status {
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
* @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
+ * @NL80211_AUTHTYPE_FILS_SK: Fast Initial Link Setup shared key
+ * @NL80211_AUTHTYPE_FILS_SK_PFS: Fast Initial Link Setup shared key with PFS
+ * @NL80211_AUTHTYPE_FILS_PK: Fast Initial Link Setup public key
* @__NL80211_AUTHTYPE_NUM: internal
* @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
* @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -3672,6 +3726,9 @@ enum nl80211_auth_type {
NL80211_AUTHTYPE_FT,
NL80211_AUTHTYPE_NETWORK_EAP,
NL80211_AUTHTYPE_SAE,
+ NL80211_AUTHTYPE_FILS_SK,
+ NL80211_AUTHTYPE_FILS_SK_PFS,
+ NL80211_AUTHTYPE_FILS_PK,
/* keep last */
__NL80211_AUTHTYPE_NUM,
@@ -4280,6 +4337,9 @@ enum nl80211_iface_limit_attrs {
* of supported channel widths for radar detection.
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
* of supported regulatory regions for radar detection.
+ * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
+ * different beacon intervals supported by all the interface combinations
+ * in this group (if not present, all beacon intervals be identical).
* @NUM_NL80211_IFACE_COMB: number of attributes
* @MAX_NL80211_IFACE_COMB: highest attribute number
*
@@ -4287,8 +4347,8 @@ enum nl80211_iface_limit_attrs {
* limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
* => allows an AP and a STA that must match BIs
*
- * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
- * => allows 8 of AP/GO
+ * numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
+ * => allows 8 of AP/GO that can have BI gcd >= min gcd
*
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
* => allows two STAs on different channels
@@ -4314,6 +4374,7 @@ enum nl80211_if_combination_attrs {
NL80211_IFACE_COMB_NUM_CHANNELS,
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
+ NL80211_IFACE_COMB_BI_MIN_GCD,
/* keep last */
NUM_NL80211_IFACE_COMB,
@@ -4634,6 +4695,8 @@ enum nl80211_feature_flags {
* configuration (AP/mesh) with HT rates.
* @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
* configuration (AP/mesh) with VHT rates.
+ * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup
+ * with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4648,6 +4711,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
NL80211_EXT_FEATURE_BEACON_RATE_HT,
NL80211_EXT_FEATURE_BEACON_RATE_VHT,
+ NL80211_EXT_FEATURE_FILS_STA,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 59ed3992c760..375d812fea36 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -705,6 +705,15 @@ enum ovs_nat_attr {
#define OVS_NAT_ATTR_MAX (__OVS_NAT_ATTR_MAX - 1)
+/*
+ * struct ovs_action_push_eth - %OVS_ACTION_ATTR_PUSH_ETH action argument.
+ * @addresses: Source and destination MAC addresses.
+ * @eth_type: Ethernet type
+ */
+struct ovs_action_push_eth {
+ struct ovs_key_ethernet addresses;
+};
+
/**
* enum ovs_action_attr - Action types.
*
@@ -738,6 +747,10 @@ enum ovs_nat_attr {
* is no MPLS label stack, as determined by ethertype, no action is taken.
* @OVS_ACTION_ATTR_CT: Track the connection. Populate the conntrack-related
* entries in the flow key.
+ * @OVS_ACTION_ATTR_PUSH_ETH: Push a new outermost Ethernet header onto the
+ * packet.
+ * @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the
+ * packet.
*
* Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
* fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -765,6 +778,8 @@ enum ovs_action_attr {
* bits. */
OVS_ACTION_ATTR_CT, /* Nested OVS_CT_ATTR_* . */
OVS_ACTION_ATTR_TRUNC, /* u32 struct ovs_action_trunc. */
+ OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */
+ OVS_ACTION_ATTR_POP_ETH, /* No argument. */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 8fd715f806a2..cb4bcdc58543 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -397,6 +397,7 @@ enum {
TCA_BPF_NAME,
TCA_BPF_FLAGS,
TCA_BPF_FLAGS_GEN,
+ TCA_BPF_DIGEST,
__TCA_BPF_MAX,
};
@@ -447,11 +448,38 @@ enum {
TCA_FLOWER_KEY_TCP_DST_MASK, /* be16 */
TCA_FLOWER_KEY_UDP_SRC_MASK, /* be16 */
TCA_FLOWER_KEY_UDP_DST_MASK, /* be16 */
+ TCA_FLOWER_KEY_SCTP_SRC_MASK, /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST_MASK, /* be16 */
+
+ TCA_FLOWER_KEY_SCTP_SRC, /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST, /* be16 */
+
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */
+
+ TCA_FLOWER_KEY_FLAGS, /* be32 */
+ TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */
+
+ TCA_FLOWER_KEY_ICMPV4_CODE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
__TCA_FLOWER_MAX,
};
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
+enum {
+ TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
+};
+
/* Match-all classifier */
enum {
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 5a78be518101..e14377f2ec27 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -318,6 +318,7 @@ enum rtattr_type_t {
RTA_ENCAP,
RTA_EXPIRES,
RTA_PAD,
+ RTA_UID,
__RTA_MAX
};
diff --git a/include/uapi/linux/seg6.h b/include/uapi/linux/seg6.h
new file mode 100644
index 000000000000..c396a8052f73
--- /dev/null
+++ b/include/uapi/linux/seg6.h
@@ -0,0 +1,54 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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 _UAPI_LINUX_SEG6_H
+#define _UAPI_LINUX_SEG6_H
+
+/*
+ * SRH
+ */
+struct ipv6_sr_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ __u8 type;
+ __u8 segments_left;
+ __u8 first_segment;
+ __u8 flag_1;
+ __u8 flag_2;
+ __u8 reserved;
+
+ struct in6_addr segments[0];
+};
+
+#define SR6_FLAG1_CLEANUP (1 << 7)
+#define SR6_FLAG1_PROTECTED (1 << 6)
+#define SR6_FLAG1_OAM (1 << 5)
+#define SR6_FLAG1_ALERT (1 << 4)
+#define SR6_FLAG1_HMAC (1 << 3)
+
+#define SR6_TLV_INGRESS 1
+#define SR6_TLV_EGRESS 2
+#define SR6_TLV_OPAQUE 3
+#define SR6_TLV_PADDING 4
+#define SR6_TLV_HMAC 5
+
+#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP)
+#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC)
+
+struct sr6_tlv {
+ __u8 type;
+ __u8 len;
+ __u8 data[0];
+};
+
+#endif
diff --git a/include/uapi/linux/seg6_genl.h b/include/uapi/linux/seg6_genl.h
new file mode 100644
index 000000000000..fcf1c60d7df3
--- /dev/null
+++ b/include/uapi/linux/seg6_genl.h
@@ -0,0 +1,32 @@
+#ifndef _UAPI_LINUX_SEG6_GENL_H
+#define _UAPI_LINUX_SEG6_GENL_H
+
+#define SEG6_GENL_NAME "SEG6"
+#define SEG6_GENL_VERSION 0x1
+
+enum {
+ SEG6_ATTR_UNSPEC,
+ SEG6_ATTR_DST,
+ SEG6_ATTR_DSTLEN,
+ SEG6_ATTR_HMACKEYID,
+ SEG6_ATTR_SECRET,
+ SEG6_ATTR_SECRETLEN,
+ SEG6_ATTR_ALGID,
+ SEG6_ATTR_HMACINFO,
+ __SEG6_ATTR_MAX,
+};
+
+#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1)
+
+enum {
+ SEG6_CMD_UNSPEC,
+ SEG6_CMD_SETHMAC,
+ SEG6_CMD_DUMPHMAC,
+ SEG6_CMD_SET_TUNSRC,
+ SEG6_CMD_GET_TUNSRC,
+ __SEG6_CMD_MAX,
+};
+
+#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1)
+
+#endif
diff --git a/include/uapi/linux/seg6_hmac.h b/include/uapi/linux/seg6_hmac.h
new file mode 100644
index 000000000000..b652dfd51bc5
--- /dev/null
+++ b/include/uapi/linux/seg6_hmac.h
@@ -0,0 +1,21 @@
+#ifndef _UAPI_LINUX_SEG6_HMAC_H
+#define _UAPI_LINUX_SEG6_HMAC_H
+
+#include <linux/seg6.h>
+
+#define SEG6_HMAC_SECRET_LEN 64
+#define SEG6_HMAC_FIELD_LEN 32
+
+struct sr6_tlv_hmac {
+ struct sr6_tlv tlvhdr;
+ __u16 reserved;
+ __be32 hmackeyid;
+ __u8 hmac[SEG6_HMAC_FIELD_LEN];
+};
+
+enum {
+ SEG6_HMAC_ALGO_SHA1 = 1,
+ SEG6_HMAC_ALGO_SHA256 = 2,
+};
+
+#endif
diff --git a/include/uapi/linux/seg6_iptunnel.h b/include/uapi/linux/seg6_iptunnel.h
new file mode 100644
index 000000000000..0f7dbd280a9c
--- /dev/null
+++ b/include/uapi/linux/seg6_iptunnel.h
@@ -0,0 +1,44 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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 _UAPI_LINUX_SEG6_IPTUNNEL_H
+#define _UAPI_LINUX_SEG6_IPTUNNEL_H
+
+enum {
+ SEG6_IPTUNNEL_UNSPEC,
+ SEG6_IPTUNNEL_SRH,
+ __SEG6_IPTUNNEL_MAX,
+};
+#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
+
+struct seg6_iptunnel_encap {
+ int mode;
+ struct ipv6_sr_hdr srh[0];
+};
+
+#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))
+
+enum {
+ SEG6_IPTUN_MODE_INLINE,
+ SEG6_IPTUN_MODE_ENCAP,
+};
+
+static inline size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
+{
+ int encap = (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP);
+
+ return ((tuninfo->srh->hdrlen + 1) << 3) +
+ (encap * sizeof(struct ipv6hdr));
+}
+
+#endif
diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h
index 8e7890b26d9a..79d029d25310 100644
--- a/include/uapi/linux/sockios.h
+++ b/include/uapi/linux/sockios.h
@@ -24,6 +24,8 @@
#define SIOCINQ FIONREAD
#define SIOCOUTQ TIOCOUTQ /* output queue size (not sent + not acked) */
+#define SOCK_IOC_TYPE 0x89
+
/* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */
#define SIOCDELRT 0x890C /* delete routing table entry */
@@ -84,6 +86,7 @@
#define SIOCWANDEV 0x894A /* get/set netdev parameters */
#define SIOCOUTQNSD 0x894B /* output queue size (not sent only) */
+#define SIOCGSKNS 0x894C /* get socket network namespace */
/* ARP cache control calls. */
/* 0x8950 - 0x8952 * obsolete calls, don't re-use */
diff --git a/include/uapi/linux/tc_act/tc_bpf.h b/include/uapi/linux/tc_act/tc_bpf.h
index 063d9d465119..a6b88a6f7f71 100644
--- a/include/uapi/linux/tc_act/tc_bpf.h
+++ b/include/uapi/linux/tc_act/tc_bpf.h
@@ -27,6 +27,7 @@ enum {
TCA_ACT_BPF_FD,
TCA_ACT_BPF_NAME,
TCA_ACT_BPF_PAD,
+ TCA_ACT_BPF_DIGEST,
__TCA_ACT_BPF_MAX,
};
#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h b/include/uapi/linux/tc_act/tc_skbedit.h
index a4d00c608d8f..2884425738ce 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -28,6 +28,7 @@
#define SKBEDIT_F_QUEUE_MAPPING 0x2
#define SKBEDIT_F_MARK 0x4
#define SKBEDIT_F_PTYPE 0x8
+#define SKBEDIT_F_MASK 0x10
struct tc_skbedit {
tc_gen;
@@ -42,6 +43,7 @@ enum {
TCA_SKBEDIT_MARK,
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
+ TCA_SKBEDIT_MASK,
__TCA_SKBEDIT_MAX
};
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/include/uapi/linux/tc_act/tc_tunnel_key.h b/include/uapi/linux/tc_act/tc_tunnel_key.h
index 890106ff16e6..84ea55e1076b 100644
--- a/include/uapi/linux/tc_act/tc_tunnel_key.h
+++ b/include/uapi/linux/tc_act/tc_tunnel_key.h
@@ -33,6 +33,7 @@ enum {
TCA_TUNNEL_KEY_ENC_IPV6_DST, /* struct in6_addr */
TCA_TUNNEL_KEY_ENC_KEY_ID, /* be64 */
TCA_TUNNEL_KEY_PAD,
+ TCA_TUNNEL_KEY_ENC_DST_PORT, /* be16 */
__TCA_TUNNEL_KEY_MAX,
};
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 73ac0db487f8..c53de2691cec 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -214,6 +214,18 @@ struct tcp_info {
__u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */
__u64 tcpi_delivery_rate;
+
+ __u64 tcpi_busy_time; /* Time (usec) busy sending data */
+ __u64 tcpi_rwnd_limited; /* Time (usec) limited by receive window */
+ __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
+};
+
+/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
+enum {
+ TCP_NLA_PAD,
+ TCP_NLA_BUSY, /* Time (usec) busy sending data */
+ TCP_NLA_RWND_LIMITED, /* Time (usec) limited by receive window */
+ TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer */
};
/* for TCP_MD5SIG socket option */
diff --git a/include/uapi/linux/uleds.h b/include/uapi/linux/uleds.h
new file mode 100644
index 000000000000..95186578c46e
--- /dev/null
+++ b/include/uapi/linux/uleds.h
@@ -0,0 +1,24 @@
+/*
+ * Userspace driver support for the LED subsystem
+ *
+ * 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 _UAPI__ULEDS_H_
+#define _UAPI__ULEDS_H_
+
+#define LED_MAX_NAME_SIZE 64
+
+struct uleds_user_dev {
+ char name[LED_MAX_NAME_SIZE];
+ int max_brightness;
+};
+
+#endif /* _UAPI__ULEDS_H_ */
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 255a2113f53c..519eff362c1c 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -203,6 +203,16 @@ struct vfio_device_info {
};
#define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7)
+/*
+ * Vendor driver using Mediated device framework should provide device_api
+ * attribute in supported type attribute groups. Device API string should be one
+ * of the following corresponding to device flags in vfio_device_info structure.
+ */
+
+#define VFIO_DEVICE_API_PCI_STRING "vfio-pci"
+#define VFIO_DEVICE_API_PLATFORM_STRING "vfio-platform"
+#define VFIO_DEVICE_API_AMBA_STRING "vfio-amba"
+
/**
* VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
* struct vfio_region_info)
diff --git a/include/uapi/scsi/fc/fc_fs.h b/include/uapi/scsi/fc/fc_fs.h
index 50f28b143451..dcf314dc2a27 100644
--- a/include/uapi/scsi/fc/fc_fs.h
+++ b/include/uapi/scsi/fc/fc_fs.h
@@ -190,6 +190,7 @@ enum fc_fh_type {
FC_TYPE_FCP = 0x08, /* SCSI FCP */
FC_TYPE_CT = 0x20, /* Fibre Channel Services (FC-CT) */
FC_TYPE_ILS = 0x22, /* internal link service */
+ FC_TYPE_NVME = 0x28, /* FC-NVME */
};
/*
@@ -203,6 +204,7 @@ enum fc_fh_type {
[FC_TYPE_FCP] = "FCP", \
[FC_TYPE_CT] = "CT", \
[FC_TYPE_ILS] = "ILS", \
+ [FC_TYPE_NVME] = "NVME", \
}
/*
diff --git a/include/video/display_timing.h b/include/video/display_timing.h
index 28d9d0d566ca..3d289e990aca 100644
--- a/include/video/display_timing.h
+++ b/include/video/display_timing.h
@@ -28,6 +28,10 @@ enum display_flags {
DISPLAY_FLAGS_INTERLACED = BIT(8),
DISPLAY_FLAGS_DOUBLESCAN = BIT(9),
DISPLAY_FLAGS_DOUBLECLK = BIT(10),
+ /* drive sync on pos. edge */
+ DISPLAY_FLAGS_SYNC_POSEDGE = BIT(11),
+ /* drive sync on neg. edge */
+ DISPLAY_FLAGS_SYNC_NEGEDGE = BIT(12),
};
/*
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 173073eb6aaf..53cd07ccaa4c 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -247,8 +247,6 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
unsigned int uv_stride,
unsigned int u_offset,
unsigned int v_offset);
-void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
- u32 pixel_format, int stride, int height);
int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc);
int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image);
void ipu_cpmem_dump(struct ipuv3_channel *ch);
@@ -320,6 +318,7 @@ int ipu_csi_init_interface(struct ipu_csi *csi,
bool ipu_csi_is_interlaced(struct ipu_csi *csi);
void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w);
void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w);
+void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert);
void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
u32 r_value, u32 g_value, u32 b_value,
u32 pix_clk);
diff --git a/include/video/of_display_timing.h b/include/video/of_display_timing.h
index ea755b5616d8..956455fc9f9a 100644
--- a/include/video/of_display_timing.h
+++ b/include/video/of_display_timing.h
@@ -16,21 +16,22 @@ struct display_timings;
#define OF_USE_NATIVE_MODE -1
#ifdef CONFIG_OF
-int of_get_display_timing(struct device_node *np, const char *name,
+int of_get_display_timing(const struct device_node *np, const char *name,
struct display_timing *dt);
-struct display_timings *of_get_display_timings(struct device_node *np);
-int of_display_timings_exist(struct device_node *np);
+struct display_timings *of_get_display_timings(const struct device_node *np);
+int of_display_timings_exist(const struct device_node *np);
#else
-static inline int of_get_display_timing(struct device_node *np, const char *name,
- struct display_timing *dt)
+static inline int of_get_display_timing(const struct device_node *np,
+ const char *name, struct display_timing *dt)
{
return -ENOSYS;
}
-static inline struct display_timings *of_get_display_timings(struct device_node *np)
+static inline struct display_timings *
+of_get_display_timings(const struct device_node *np)
{
return NULL;
}
-static inline int of_display_timings_exist(struct device_node *np)
+static inline int of_display_timings_exist(const struct device_node *np)
{
return -ENOSYS;
}
diff --git a/init/Kconfig b/init/Kconfig
index 34407f15e6d3..aafafeb0c117 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1154,6 +1154,18 @@ config CGROUP_PERF
Say N if unsure.
+config CGROUP_BPF
+ bool "Support for eBPF programs attached to cgroups"
+ depends on BPF_SYSCALL && SOCK_CGROUP_DATA
+ help
+ Allow attaching eBPF programs to a cgroup using the bpf(2)
+ syscall command BPF_PROG_ATTACH.
+
+ In which context these programs are accessed depends on the type
+ of attachment. For instance, programs that are attached using
+ BPF_CGROUP_INET_INGRESS will be executed on the ingress path of
+ inet sockets.
+
config CGROUP_DEBUG
bool "Example controller"
default n
@@ -1306,7 +1318,7 @@ config BLK_DEV_INITRD
boot loader (loadlin or lilo) and that is mounted as root
before the normal boot procedure. It is typically used to
load modules needed to mount the "real" root file system,
- etc. See <file:Documentation/initrd.txt> for details.
+ etc. See <file:Documentation/admin-guide/initrd.rst> for details.
If RAM disk support (BLK_DEV_RAM) is also included, this
also enables initial RAM disk (initrd) support and adds
@@ -1445,6 +1457,23 @@ config SYSCTL_SYSCALL
If unsure say N here.
+config POSIX_TIMERS
+ bool "Posix Clocks & timers" if EXPERT
+ default y
+ help
+ This includes native support for POSIX timers to the kernel.
+ Some embedded systems have no use for them and therefore they
+ can be configured out to reduce the size of the kernel image.
+
+ When this option is disabled, the following syscalls won't be
+ available: timer_create, timer_gettime: timer_getoverrun,
+ timer_settime, timer_delete, clock_adjtime, getitimer,
+ setitimer, alarm. Furthermore, the clock_settime, clock_gettime,
+ clock_getres and clock_nanosleep syscalls will be limited to
+ CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_BOOTTIME only.
+
+ If unsure say y.
+
config KALLSYMS
bool "Load all symbols for debugging/ksymoops" if EXPERT
default y
diff --git a/init/do_mounts.c b/init/do_mounts.c
index dea5de95c2dd..c2de5104aad2 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -588,7 +588,7 @@ void __init prepare_namespace(void)
saved_root_name);
while (driver_probe_done() != 0 ||
(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
- msleep(100);
+ msleep(5);
async_synchronize_full();
}
diff --git a/init/main.c b/init/main.c
index 2858be732f6d..fa201166cba7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -448,6 +448,8 @@ void __init parse_early_param(void)
done = 1;
}
+void __init __weak arch_post_acpi_subsys_init(void) { }
+
void __init __weak smp_setup_processor_id(void)
{
}
@@ -649,6 +651,7 @@ asmlinkage __visible void __init start_kernel(void)
check_bugs();
acpi_subsystem_init();
+ arch_post_acpi_subsys_init();
sfi_init_late();
if (efi_enabled(EFI_RUNTIME_SERVICES)) {
@@ -980,7 +983,7 @@ static int __ref kernel_init(void *unused)
return 0;
panic("No working init found. Try passing init= option to kernel. "
- "See Linux Documentation/init.txt for guidance.");
+ "See Linux Documentation/admin-guide/init.rst for guidance.");
}
static noinline void __init kernel_init_freeable(void)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 8cbd6e6894d5..7a2d8f0c8ae5 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -967,7 +967,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
struct timespec ts;
struct posix_msg_tree_node *new_leaf = NULL;
int ret = 0;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
if (u_abs_timeout) {
int res = prepare_timeout(u_abs_timeout, &expires, &ts);
@@ -1151,7 +1151,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
msg_ptr = wait.msg;
}
} else {
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
msg_ptr = msg_get(info);
diff --git a/ipc/msg.c b/ipc/msg.c
index e12307d0c920..32e9bd837cde 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -235,7 +235,7 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
{
struct msg_msg *msg, *t;
struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
expunge_all(msq, -EIDRM, &wake_q);
ss_wakeup(msq, &wake_q, true);
@@ -397,7 +397,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
goto out_up;
case IPC_SET:
{
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
!capable(CAP_SYS_RESOURCE)) {
@@ -634,7 +634,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
struct msg_msg *msg;
int err;
struct ipc_namespace *ns;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
ns = current->nsproxy->ipc_ns;
@@ -850,7 +850,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
struct msg_queue *msq;
struct ipc_namespace *ns;
struct msg_msg *msg, *copy = NULL;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
ns = current->nsproxy->ipc_ns;
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index ebdb0043203a..84d882f3e299 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -225,7 +225,7 @@ config ARCH_SUPPORTS_ATOMIC_RMW
config MUTEX_SPIN_ON_OWNER
def_bool y
- depends on SMP && !DEBUG_MUTEXES && ARCH_SUPPORTS_ATOMIC_RMW
+ depends on SMP && ARCH_SUPPORTS_ATOMIC_RMW
config RWSEM_SPIN_ON_OWNER
def_bool y
diff --git a/kernel/audit.c b/kernel/audit.c
index f1ca11613379..67b9fbd871be 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -126,7 +126,7 @@ static atomic_t audit_lost = ATOMIC_INIT(0);
/* The netlink socket. */
static struct sock *audit_sock;
-static int audit_net_id;
+static unsigned int audit_net_id;
/* Hash for inode-based rules */
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
@@ -1172,9 +1172,8 @@ static void __net_exit audit_net_exit(struct net *net)
audit_sock = NULL;
}
- RCU_INIT_POINTER(aunet->nlsk, NULL);
- synchronize_net();
netlink_kernel_release(sock);
+ aunet->nlsk = NULL;
}
static struct pernet_operations audit_net_ops __net_initdata = {
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index eed911d091da..1276474ac3cd 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -1,7 +1,8 @@
obj-y := core.o
obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o
-obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o
+obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o
ifeq ($(CONFIG_PERF_EVENTS),y)
obj-$(CONFIG_BPF_SYSCALL) += stackmap.o
endif
+obj-$(CONFIG_CGROUP_BPF) += cgroup.o
diff --git a/kernel/bpf/bpf_lru_list.c b/kernel/bpf/bpf_lru_list.c
new file mode 100644
index 000000000000..89b7ef41c86b
--- /dev/null
+++ b/kernel/bpf/bpf_lru_list.c
@@ -0,0 +1,695 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute 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/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+
+#include "bpf_lru_list.h"
+
+#define LOCAL_FREE_TARGET (128)
+#define LOCAL_NR_SCANS LOCAL_FREE_TARGET
+
+#define PERCPU_FREE_TARGET (16)
+#define PERCPU_NR_SCANS PERCPU_FREE_TARGET
+
+/* Helpers to get the local list index */
+#define LOCAL_LIST_IDX(t) ((t) - BPF_LOCAL_LIST_T_OFFSET)
+#define LOCAL_FREE_LIST_IDX LOCAL_LIST_IDX(BPF_LRU_LOCAL_LIST_T_FREE)
+#define LOCAL_PENDING_LIST_IDX LOCAL_LIST_IDX(BPF_LRU_LOCAL_LIST_T_PENDING)
+#define IS_LOCAL_LIST_TYPE(t) ((t) >= BPF_LOCAL_LIST_T_OFFSET)
+
+static int get_next_cpu(int cpu)
+{
+ cpu = cpumask_next(cpu, cpu_possible_mask);
+ if (cpu >= nr_cpu_ids)
+ cpu = cpumask_first(cpu_possible_mask);
+ return cpu;
+}
+
+/* Local list helpers */
+static struct list_head *local_free_list(struct bpf_lru_locallist *loc_l)
+{
+ return &loc_l->lists[LOCAL_FREE_LIST_IDX];
+}
+
+static struct list_head *local_pending_list(struct bpf_lru_locallist *loc_l)
+{
+ return &loc_l->lists[LOCAL_PENDING_LIST_IDX];
+}
+
+/* bpf_lru_node helpers */
+static bool bpf_lru_node_is_ref(const struct bpf_lru_node *node)
+{
+ return node->ref;
+}
+
+static void bpf_lru_list_count_inc(struct bpf_lru_list *l,
+ enum bpf_lru_list_type type)
+{
+ if (type < NR_BPF_LRU_LIST_COUNT)
+ l->counts[type]++;
+}
+
+static void bpf_lru_list_count_dec(struct bpf_lru_list *l,
+ enum bpf_lru_list_type type)
+{
+ if (type < NR_BPF_LRU_LIST_COUNT)
+ l->counts[type]--;
+}
+
+static void __bpf_lru_node_move_to_free(struct bpf_lru_list *l,
+ struct bpf_lru_node *node,
+ struct list_head *free_list,
+ enum bpf_lru_list_type tgt_free_type)
+{
+ if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)))
+ return;
+
+ /* If the removing node is the next_inactive_rotation candidate,
+ * move the next_inactive_rotation pointer also.
+ */
+ if (&node->list == l->next_inactive_rotation)
+ l->next_inactive_rotation = l->next_inactive_rotation->prev;
+
+ bpf_lru_list_count_dec(l, node->type);
+
+ node->type = tgt_free_type;
+ list_move(&node->list, free_list);
+}
+
+/* Move nodes from local list to the LRU list */
+static void __bpf_lru_node_move_in(struct bpf_lru_list *l,
+ struct bpf_lru_node *node,
+ enum bpf_lru_list_type tgt_type)
+{
+ if (WARN_ON_ONCE(!IS_LOCAL_LIST_TYPE(node->type)) ||
+ WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(tgt_type)))
+ return;
+
+ bpf_lru_list_count_inc(l, tgt_type);
+ node->type = tgt_type;
+ node->ref = 0;
+ list_move(&node->list, &l->lists[tgt_type]);
+}
+
+/* Move nodes between or within active and inactive list (like
+ * active to inactive, inactive to active or tail of active back to
+ * the head of active).
+ */
+static void __bpf_lru_node_move(struct bpf_lru_list *l,
+ struct bpf_lru_node *node,
+ enum bpf_lru_list_type tgt_type)
+{
+ if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)) ||
+ WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(tgt_type)))
+ return;
+
+ if (node->type != tgt_type) {
+ bpf_lru_list_count_dec(l, node->type);
+ bpf_lru_list_count_inc(l, tgt_type);
+ node->type = tgt_type;
+ }
+ node->ref = 0;
+
+ /* If the moving node is the next_inactive_rotation candidate,
+ * move the next_inactive_rotation pointer also.
+ */
+ if (&node->list == l->next_inactive_rotation)
+ l->next_inactive_rotation = l->next_inactive_rotation->prev;
+
+ list_move(&node->list, &l->lists[tgt_type]);
+}
+
+static bool bpf_lru_list_inactive_low(const struct bpf_lru_list *l)
+{
+ return l->counts[BPF_LRU_LIST_T_INACTIVE] <
+ l->counts[BPF_LRU_LIST_T_ACTIVE];
+}
+
+/* Rotate the active list:
+ * 1. Start from tail
+ * 2. If the node has the ref bit set, it will be rotated
+ * back to the head of active list with the ref bit cleared.
+ * Give this node one more chance to survive in the active list.
+ * 3. If the ref bit is not set, move it to the head of the
+ * inactive list.
+ * 4. It will at most scan nr_scans nodes
+ */
+static void __bpf_lru_list_rotate_active(struct bpf_lru *lru,
+ struct bpf_lru_list *l)
+{
+ struct list_head *active = &l->lists[BPF_LRU_LIST_T_ACTIVE];
+ struct bpf_lru_node *node, *tmp_node, *first_node;
+ unsigned int i = 0;
+
+ first_node = list_first_entry(active, struct bpf_lru_node, list);
+ list_for_each_entry_safe_reverse(node, tmp_node, active, list) {
+ if (bpf_lru_node_is_ref(node))
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
+ else
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_INACTIVE);
+
+ if (++i == lru->nr_scans || node == first_node)
+ break;
+ }
+}
+
+/* Rotate the inactive list. It starts from the next_inactive_rotation
+ * 1. If the node has ref bit set, it will be moved to the head
+ * of active list with the ref bit cleared.
+ * 2. If the node does not have ref bit set, it will leave it
+ * at its current location (i.e. do nothing) so that it can
+ * be considered during the next inactive_shrink.
+ * 3. It will at most scan nr_scans nodes
+ */
+static void __bpf_lru_list_rotate_inactive(struct bpf_lru *lru,
+ struct bpf_lru_list *l)
+{
+ struct list_head *inactive = &l->lists[BPF_LRU_LIST_T_INACTIVE];
+ struct list_head *cur, *last, *next = inactive;
+ struct bpf_lru_node *node;
+ unsigned int i = 0;
+
+ if (list_empty(inactive))
+ return;
+
+ last = l->next_inactive_rotation->next;
+ if (last == inactive)
+ last = last->next;
+
+ cur = l->next_inactive_rotation;
+ while (i < lru->nr_scans) {
+ if (cur == inactive) {
+ cur = cur->prev;
+ continue;
+ }
+
+ node = list_entry(cur, struct bpf_lru_node, list);
+ next = cur->prev;
+ if (bpf_lru_node_is_ref(node))
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
+ if (cur == last)
+ break;
+ cur = next;
+ i++;
+ }
+
+ l->next_inactive_rotation = next;
+}
+
+/* Shrink the inactive list. It starts from the tail of the
+ * inactive list and only move the nodes without the ref bit
+ * set to the designated free list.
+ */
+static unsigned int
+__bpf_lru_list_shrink_inactive(struct bpf_lru *lru,
+ struct bpf_lru_list *l,
+ unsigned int tgt_nshrink,
+ struct list_head *free_list,
+ enum bpf_lru_list_type tgt_free_type)
+{
+ struct list_head *inactive = &l->lists[BPF_LRU_LIST_T_INACTIVE];
+ struct bpf_lru_node *node, *tmp_node, *first_node;
+ unsigned int nshrinked = 0;
+ unsigned int i = 0;
+
+ first_node = list_first_entry(inactive, struct bpf_lru_node, list);
+ list_for_each_entry_safe_reverse(node, tmp_node, inactive, list) {
+ if (bpf_lru_node_is_ref(node)) {
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
+ } else if (lru->del_from_htab(lru->del_arg, node)) {
+ __bpf_lru_node_move_to_free(l, node, free_list,
+ tgt_free_type);
+ if (++nshrinked == tgt_nshrink)
+ break;
+ }
+
+ if (++i == lru->nr_scans)
+ break;
+ }
+
+ return nshrinked;
+}
+
+/* 1. Rotate the active list (if needed)
+ * 2. Always rotate the inactive list
+ */
+static void __bpf_lru_list_rotate(struct bpf_lru *lru, struct bpf_lru_list *l)
+{
+ if (bpf_lru_list_inactive_low(l))
+ __bpf_lru_list_rotate_active(lru, l);
+
+ __bpf_lru_list_rotate_inactive(lru, l);
+}
+
+/* Calls __bpf_lru_list_shrink_inactive() to shrink some
+ * ref-bit-cleared nodes and move them to the designated
+ * free list.
+ *
+ * If it cannot get a free node after calling
+ * __bpf_lru_list_shrink_inactive(). It will just remove
+ * one node from either inactive or active list without
+ * honoring the ref-bit. It prefers inactive list to active
+ * list in this situation.
+ */
+static unsigned int __bpf_lru_list_shrink(struct bpf_lru *lru,
+ struct bpf_lru_list *l,
+ unsigned int tgt_nshrink,
+ struct list_head *free_list,
+ enum bpf_lru_list_type tgt_free_type)
+
+{
+ struct bpf_lru_node *node, *tmp_node;
+ struct list_head *force_shrink_list;
+ unsigned int nshrinked;
+
+ nshrinked = __bpf_lru_list_shrink_inactive(lru, l, tgt_nshrink,
+ free_list, tgt_free_type);
+ if (nshrinked)
+ return nshrinked;
+
+ /* Do a force shrink by ignoring the reference bit */
+ if (!list_empty(&l->lists[BPF_LRU_LIST_T_INACTIVE]))
+ force_shrink_list = &l->lists[BPF_LRU_LIST_T_INACTIVE];
+ else
+ force_shrink_list = &l->lists[BPF_LRU_LIST_T_ACTIVE];
+
+ list_for_each_entry_safe_reverse(node, tmp_node, force_shrink_list,
+ list) {
+ if (lru->del_from_htab(lru->del_arg, node)) {
+ __bpf_lru_node_move_to_free(l, node, free_list,
+ tgt_free_type);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Flush the nodes from the local pending list to the LRU list */
+static void __local_list_flush(struct bpf_lru_list *l,
+ struct bpf_lru_locallist *loc_l)
+{
+ struct bpf_lru_node *node, *tmp_node;
+
+ list_for_each_entry_safe_reverse(node, tmp_node,
+ local_pending_list(loc_l), list) {
+ if (bpf_lru_node_is_ref(node))
+ __bpf_lru_node_move_in(l, node, BPF_LRU_LIST_T_ACTIVE);
+ else
+ __bpf_lru_node_move_in(l, node,
+ BPF_LRU_LIST_T_INACTIVE);
+ }
+}
+
+static void bpf_lru_list_push_free(struct bpf_lru_list *l,
+ struct bpf_lru_node *node)
+{
+ unsigned long flags;
+
+ if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)))
+ return;
+
+ raw_spin_lock_irqsave(&l->lock, flags);
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_FREE);
+ raw_spin_unlock_irqrestore(&l->lock, flags);
+}
+
+static void bpf_lru_list_pop_free_to_local(struct bpf_lru *lru,
+ struct bpf_lru_locallist *loc_l)
+{
+ struct bpf_lru_list *l = &lru->common_lru.lru_list;
+ struct bpf_lru_node *node, *tmp_node;
+ unsigned int nfree = 0;
+
+ raw_spin_lock(&l->lock);
+
+ __local_list_flush(l, loc_l);
+
+ __bpf_lru_list_rotate(lru, l);
+
+ list_for_each_entry_safe(node, tmp_node, &l->lists[BPF_LRU_LIST_T_FREE],
+ list) {
+ __bpf_lru_node_move_to_free(l, node, local_free_list(loc_l),
+ BPF_LRU_LOCAL_LIST_T_FREE);
+ if (++nfree == LOCAL_FREE_TARGET)
+ break;
+ }
+
+ if (nfree < LOCAL_FREE_TARGET)
+ __bpf_lru_list_shrink(lru, l, LOCAL_FREE_TARGET - nfree,
+ local_free_list(loc_l),
+ BPF_LRU_LOCAL_LIST_T_FREE);
+
+ raw_spin_unlock(&l->lock);
+}
+
+static void __local_list_add_pending(struct bpf_lru *lru,
+ struct bpf_lru_locallist *loc_l,
+ int cpu,
+ struct bpf_lru_node *node,
+ u32 hash)
+{
+ *(u32 *)((void *)node + lru->hash_offset) = hash;
+ node->cpu = cpu;
+ node->type = BPF_LRU_LOCAL_LIST_T_PENDING;
+ node->ref = 0;
+ list_add(&node->list, local_pending_list(loc_l));
+}
+
+struct bpf_lru_node *__local_list_pop_free(struct bpf_lru_locallist *loc_l)
+{
+ struct bpf_lru_node *node;
+
+ node = list_first_entry_or_null(local_free_list(loc_l),
+ struct bpf_lru_node,
+ list);
+ if (node)
+ list_del(&node->list);
+
+ return node;
+}
+
+struct bpf_lru_node *__local_list_pop_pending(struct bpf_lru *lru,
+ struct bpf_lru_locallist *loc_l)
+{
+ struct bpf_lru_node *node;
+ bool force = false;
+
+ignore_ref:
+ /* Get from the tail (i.e. older element) of the pending list. */
+ list_for_each_entry_reverse(node, local_pending_list(loc_l),
+ list) {
+ if ((!bpf_lru_node_is_ref(node) || force) &&
+ lru->del_from_htab(lru->del_arg, node)) {
+ list_del(&node->list);
+ return node;
+ }
+ }
+
+ if (!force) {
+ force = true;
+ goto ignore_ref;
+ }
+
+ return NULL;
+}
+
+static struct bpf_lru_node *bpf_percpu_lru_pop_free(struct bpf_lru *lru,
+ u32 hash)
+{
+ struct list_head *free_list;
+ struct bpf_lru_node *node = NULL;
+ struct bpf_lru_list *l;
+ unsigned long flags;
+ int cpu = raw_smp_processor_id();
+
+ l = per_cpu_ptr(lru->percpu_lru, cpu);
+
+ raw_spin_lock_irqsave(&l->lock, flags);
+
+ __bpf_lru_list_rotate(lru, l);
+
+ free_list = &l->lists[BPF_LRU_LIST_T_FREE];
+ if (list_empty(free_list))
+ __bpf_lru_list_shrink(lru, l, PERCPU_FREE_TARGET, free_list,
+ BPF_LRU_LIST_T_FREE);
+
+ if (!list_empty(free_list)) {
+ node = list_first_entry(free_list, struct bpf_lru_node, list);
+ *(u32 *)((void *)node + lru->hash_offset) = hash;
+ node->ref = 0;
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_INACTIVE);
+ }
+
+ raw_spin_unlock_irqrestore(&l->lock, flags);
+
+ return node;
+}
+
+static struct bpf_lru_node *bpf_common_lru_pop_free(struct bpf_lru *lru,
+ u32 hash)
+{
+ struct bpf_lru_locallist *loc_l, *steal_loc_l;
+ struct bpf_common_lru *clru = &lru->common_lru;
+ struct bpf_lru_node *node;
+ int steal, first_steal;
+ unsigned long flags;
+ int cpu = raw_smp_processor_id();
+
+ loc_l = per_cpu_ptr(clru->local_list, cpu);
+
+ raw_spin_lock_irqsave(&loc_l->lock, flags);
+
+ node = __local_list_pop_free(loc_l);
+ if (!node) {
+ bpf_lru_list_pop_free_to_local(lru, loc_l);
+ node = __local_list_pop_free(loc_l);
+ }
+
+ if (node)
+ __local_list_add_pending(lru, loc_l, cpu, node, hash);
+
+ raw_spin_unlock_irqrestore(&loc_l->lock, flags);
+
+ if (node)
+ return node;
+
+ /* No free nodes found from the local free list and
+ * the global LRU list.
+ *
+ * Steal from the local free/pending list of the
+ * current CPU and remote CPU in RR. It starts
+ * with the loc_l->next_steal CPU.
+ */
+
+ first_steal = loc_l->next_steal;
+ steal = first_steal;
+ do {
+ steal_loc_l = per_cpu_ptr(clru->local_list, steal);
+
+ raw_spin_lock_irqsave(&steal_loc_l->lock, flags);
+
+ node = __local_list_pop_free(steal_loc_l);
+ if (!node)
+ node = __local_list_pop_pending(lru, steal_loc_l);
+
+ raw_spin_unlock_irqrestore(&steal_loc_l->lock, flags);
+
+ steal = get_next_cpu(steal);
+ } while (!node && steal != first_steal);
+
+ loc_l->next_steal = steal;
+
+ if (node) {
+ raw_spin_lock_irqsave(&loc_l->lock, flags);
+ __local_list_add_pending(lru, loc_l, cpu, node, hash);
+ raw_spin_unlock_irqrestore(&loc_l->lock, flags);
+ }
+
+ return node;
+}
+
+struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash)
+{
+ if (lru->percpu)
+ return bpf_percpu_lru_pop_free(lru, hash);
+ else
+ return bpf_common_lru_pop_free(lru, hash);
+}
+
+static void bpf_common_lru_push_free(struct bpf_lru *lru,
+ struct bpf_lru_node *node)
+{
+ unsigned long flags;
+
+ if (WARN_ON_ONCE(node->type == BPF_LRU_LIST_T_FREE) ||
+ WARN_ON_ONCE(node->type == BPF_LRU_LOCAL_LIST_T_FREE))
+ return;
+
+ if (node->type == BPF_LRU_LOCAL_LIST_T_PENDING) {
+ struct bpf_lru_locallist *loc_l;
+
+ loc_l = per_cpu_ptr(lru->common_lru.local_list, node->cpu);
+
+ raw_spin_lock_irqsave(&loc_l->lock, flags);
+
+ if (unlikely(node->type != BPF_LRU_LOCAL_LIST_T_PENDING)) {
+ raw_spin_unlock_irqrestore(&loc_l->lock, flags);
+ goto check_lru_list;
+ }
+
+ node->type = BPF_LRU_LOCAL_LIST_T_FREE;
+ node->ref = 0;
+ list_move(&node->list, local_free_list(loc_l));
+
+ raw_spin_unlock_irqrestore(&loc_l->lock, flags);
+ return;
+ }
+
+check_lru_list:
+ bpf_lru_list_push_free(&lru->common_lru.lru_list, node);
+}
+
+static void bpf_percpu_lru_push_free(struct bpf_lru *lru,
+ struct bpf_lru_node *node)
+{
+ struct bpf_lru_list *l;
+ unsigned long flags;
+
+ l = per_cpu_ptr(lru->percpu_lru, node->cpu);
+
+ raw_spin_lock_irqsave(&l->lock, flags);
+
+ __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_FREE);
+
+ raw_spin_unlock_irqrestore(&l->lock, flags);
+}
+
+void bpf_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node)
+{
+ if (lru->percpu)
+ bpf_percpu_lru_push_free(lru, node);
+ else
+ bpf_common_lru_push_free(lru, node);
+}
+
+void bpf_common_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
+ u32 elem_size, u32 nr_elems)
+{
+ struct bpf_lru_list *l = &lru->common_lru.lru_list;
+ u32 i;
+
+ for (i = 0; i < nr_elems; i++) {
+ struct bpf_lru_node *node;
+
+ node = (struct bpf_lru_node *)(buf + node_offset);
+ node->type = BPF_LRU_LIST_T_FREE;
+ node->ref = 0;
+ list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]);
+ buf += elem_size;
+ }
+}
+
+void bpf_percpu_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
+ u32 elem_size, u32 nr_elems)
+{
+ u32 i, pcpu_entries;
+ int cpu;
+ struct bpf_lru_list *l;
+
+ pcpu_entries = nr_elems / num_possible_cpus();
+
+ i = 0;
+
+ for_each_possible_cpu(cpu) {
+ struct bpf_lru_node *node;
+
+ l = per_cpu_ptr(lru->percpu_lru, cpu);
+again:
+ node = (struct bpf_lru_node *)(buf + node_offset);
+ node->cpu = cpu;
+ node->type = BPF_LRU_LIST_T_FREE;
+ node->ref = 0;
+ list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]);
+ i++;
+ buf += elem_size;
+ if (i == nr_elems)
+ break;
+ if (i % pcpu_entries)
+ goto again;
+ }
+}
+
+void bpf_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
+ u32 elem_size, u32 nr_elems)
+{
+ if (lru->percpu)
+ bpf_percpu_lru_populate(lru, buf, node_offset, elem_size,
+ nr_elems);
+ else
+ bpf_common_lru_populate(lru, buf, node_offset, elem_size,
+ nr_elems);
+}
+
+static void bpf_lru_locallist_init(struct bpf_lru_locallist *loc_l, int cpu)
+{
+ int i;
+
+ for (i = 0; i < NR_BPF_LRU_LOCAL_LIST_T; i++)
+ INIT_LIST_HEAD(&loc_l->lists[i]);
+
+ loc_l->next_steal = cpu;
+
+ raw_spin_lock_init(&loc_l->lock);
+}
+
+static void bpf_lru_list_init(struct bpf_lru_list *l)
+{
+ int i;
+
+ for (i = 0; i < NR_BPF_LRU_LIST_T; i++)
+ INIT_LIST_HEAD(&l->lists[i]);
+
+ for (i = 0; i < NR_BPF_LRU_LIST_COUNT; i++)
+ l->counts[i] = 0;
+
+ l->next_inactive_rotation = &l->lists[BPF_LRU_LIST_T_INACTIVE];
+
+ raw_spin_lock_init(&l->lock);
+}
+
+int bpf_lru_init(struct bpf_lru *lru, bool percpu, u32 hash_offset,
+ del_from_htab_func del_from_htab, void *del_arg)
+{
+ int cpu;
+
+ if (percpu) {
+ lru->percpu_lru = alloc_percpu(struct bpf_lru_list);
+ if (!lru->percpu_lru)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ struct bpf_lru_list *l;
+
+ l = per_cpu_ptr(lru->percpu_lru, cpu);
+ bpf_lru_list_init(l);
+ }
+ lru->nr_scans = PERCPU_NR_SCANS;
+ } else {
+ struct bpf_common_lru *clru = &lru->common_lru;
+
+ clru->local_list = alloc_percpu(struct bpf_lru_locallist);
+ if (!clru->local_list)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ struct bpf_lru_locallist *loc_l;
+
+ loc_l = per_cpu_ptr(clru->local_list, cpu);
+ bpf_lru_locallist_init(loc_l, cpu);
+ }
+
+ bpf_lru_list_init(&clru->lru_list);
+ lru->nr_scans = LOCAL_NR_SCANS;
+ }
+
+ lru->percpu = percpu;
+ lru->del_from_htab = del_from_htab;
+ lru->del_arg = del_arg;
+ lru->hash_offset = hash_offset;
+
+ return 0;
+}
+
+void bpf_lru_destroy(struct bpf_lru *lru)
+{
+ if (lru->percpu)
+ free_percpu(lru->percpu_lru);
+ else
+ free_percpu(lru->common_lru.local_list);
+}
diff --git a/kernel/bpf/bpf_lru_list.h b/kernel/bpf/bpf_lru_list.h
new file mode 100644
index 000000000000..5c35a98d02bf
--- /dev/null
+++ b/kernel/bpf/bpf_lru_list.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#ifndef __BPF_LRU_LIST_H_
+#define __BPF_LRU_LIST_H_
+
+#include <linux/list.h>
+#include <linux/spinlock_types.h>
+
+#define NR_BPF_LRU_LIST_T (3)
+#define NR_BPF_LRU_LIST_COUNT (2)
+#define NR_BPF_LRU_LOCAL_LIST_T (2)
+#define BPF_LOCAL_LIST_T_OFFSET NR_BPF_LRU_LIST_T
+
+enum bpf_lru_list_type {
+ BPF_LRU_LIST_T_ACTIVE,
+ BPF_LRU_LIST_T_INACTIVE,
+ BPF_LRU_LIST_T_FREE,
+ BPF_LRU_LOCAL_LIST_T_FREE,
+ BPF_LRU_LOCAL_LIST_T_PENDING,
+};
+
+struct bpf_lru_node {
+ struct list_head list;
+ u16 cpu;
+ u8 type;
+ u8 ref;
+};
+
+struct bpf_lru_list {
+ struct list_head lists[NR_BPF_LRU_LIST_T];
+ unsigned int counts[NR_BPF_LRU_LIST_COUNT];
+ /* The next inacitve list rotation starts from here */
+ struct list_head *next_inactive_rotation;
+
+ raw_spinlock_t lock ____cacheline_aligned_in_smp;
+};
+
+struct bpf_lru_locallist {
+ struct list_head lists[NR_BPF_LRU_LOCAL_LIST_T];
+ u16 next_steal;
+ raw_spinlock_t lock;
+};
+
+struct bpf_common_lru {
+ struct bpf_lru_list lru_list;
+ struct bpf_lru_locallist __percpu *local_list;
+};
+
+typedef bool (*del_from_htab_func)(void *arg, struct bpf_lru_node *node);
+
+struct bpf_lru {
+ union {
+ struct bpf_common_lru common_lru;
+ struct bpf_lru_list __percpu *percpu_lru;
+ };
+ del_from_htab_func del_from_htab;
+ void *del_arg;
+ unsigned int hash_offset;
+ unsigned int nr_scans;
+ bool percpu;
+};
+
+static inline void bpf_lru_node_set_ref(struct bpf_lru_node *node)
+{
+ /* ref is an approximation on access frequency. It does not
+ * have to be very accurate. Hence, no protection is used.
+ */
+ node->ref = 1;
+}
+
+int bpf_lru_init(struct bpf_lru *lru, bool percpu, u32 hash_offset,
+ del_from_htab_func del_from_htab, void *delete_arg);
+void bpf_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
+ u32 elem_size, u32 nr_elems);
+void bpf_lru_destroy(struct bpf_lru *lru);
+struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash);
+void bpf_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node);
+void bpf_lru_promote(struct bpf_lru *lru, struct bpf_lru_node *node);
+
+#endif
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
new file mode 100644
index 000000000000..a515f7b007c6
--- /dev/null
+++ b/kernel/bpf/cgroup.c
@@ -0,0 +1,200 @@
+/*
+ * Functions to manage eBPF programs attached to cgroups
+ *
+ * Copyright (c) 2016 Daniel Mack
+ *
+ * This file is subject to the terms and conditions of version 2 of the GNU
+ * General Public License. See the file COPYING in the main directory of the
+ * Linux distribution for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/atomic.h>
+#include <linux/cgroup.h>
+#include <linux/slab.h>
+#include <linux/bpf.h>
+#include <linux/bpf-cgroup.h>
+#include <net/sock.h>
+
+DEFINE_STATIC_KEY_FALSE(cgroup_bpf_enabled_key);
+EXPORT_SYMBOL(cgroup_bpf_enabled_key);
+
+/**
+ * cgroup_bpf_put() - put references of all bpf programs
+ * @cgrp: the cgroup to modify
+ */
+void cgroup_bpf_put(struct cgroup *cgrp)
+{
+ unsigned int type;
+
+ for (type = 0; type < ARRAY_SIZE(cgrp->bpf.prog); type++) {
+ struct bpf_prog *prog = cgrp->bpf.prog[type];
+
+ if (prog) {
+ bpf_prog_put(prog);
+ static_branch_dec(&cgroup_bpf_enabled_key);
+ }
+ }
+}
+
+/**
+ * cgroup_bpf_inherit() - inherit effective programs from parent
+ * @cgrp: the cgroup to modify
+ * @parent: the parent to inherit from
+ */
+void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent)
+{
+ unsigned int type;
+
+ for (type = 0; type < ARRAY_SIZE(cgrp->bpf.effective); type++) {
+ struct bpf_prog *e;
+
+ e = rcu_dereference_protected(parent->bpf.effective[type],
+ lockdep_is_held(&cgroup_mutex));
+ rcu_assign_pointer(cgrp->bpf.effective[type], e);
+ }
+}
+
+/**
+ * __cgroup_bpf_update() - Update the pinned program of a cgroup, and
+ * propagate the change to descendants
+ * @cgrp: The cgroup which descendants to traverse
+ * @parent: The parent of @cgrp, or %NULL if @cgrp is the root
+ * @prog: A new program to pin
+ * @type: Type of pinning operation (ingress/egress)
+ *
+ * Each cgroup has a set of two pointers for bpf programs; one for eBPF
+ * programs it owns, and which is effective for execution.
+ *
+ * If @prog is not %NULL, this function attaches a new program to the cgroup
+ * and releases the one that is currently attached, if any. @prog is then made
+ * the effective program of type @type in that cgroup.
+ *
+ * If @prog is %NULL, the currently attached program of type @type is released,
+ * and the effective program of the parent cgroup (if any) is inherited to
+ * @cgrp.
+ *
+ * Then, the descendants of @cgrp are walked and the effective program for
+ * each of them is set to the effective program of @cgrp unless the
+ * descendant has its own program attached, in which case the subbranch is
+ * skipped. This ensures that delegated subcgroups with own programs are left
+ * untouched.
+ *
+ * Must be called with cgroup_mutex held.
+ */
+void __cgroup_bpf_update(struct cgroup *cgrp,
+ struct cgroup *parent,
+ struct bpf_prog *prog,
+ enum bpf_attach_type type)
+{
+ struct bpf_prog *old_prog, *effective;
+ struct cgroup_subsys_state *pos;
+
+ old_prog = xchg(cgrp->bpf.prog + type, prog);
+
+ effective = (!prog && parent) ?
+ rcu_dereference_protected(parent->bpf.effective[type],
+ lockdep_is_held(&cgroup_mutex)) :
+ prog;
+
+ css_for_each_descendant_pre(pos, &cgrp->self) {
+ struct cgroup *desc = container_of(pos, struct cgroup, self);
+
+ /* skip the subtree if the descendant has its own program */
+ if (desc->bpf.prog[type] && desc != cgrp)
+ pos = css_rightmost_descendant(pos);
+ else
+ rcu_assign_pointer(desc->bpf.effective[type],
+ effective);
+ }
+
+ if (prog)
+ static_branch_inc(&cgroup_bpf_enabled_key);
+
+ if (old_prog) {
+ bpf_prog_put(old_prog);
+ static_branch_dec(&cgroup_bpf_enabled_key);
+ }
+}
+
+/**
+ * __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
+ * @sk: The socken sending or receiving traffic
+ * @skb: The skb that is being sent or received
+ * @type: The type of program to be exectuted
+ *
+ * If no socket is passed, or the socket is not of type INET or INET6,
+ * this function does nothing and returns 0.
+ *
+ * The program type passed in via @type must be suitable for network
+ * filtering. No further check is performed to assert that.
+ *
+ * This function will return %-EPERM if any if an attached program was found
+ * and if it returned != 1 during execution. In all other cases, 0 is returned.
+ */
+int __cgroup_bpf_run_filter_skb(struct sock *sk,
+ struct sk_buff *skb,
+ enum bpf_attach_type type)
+{
+ struct bpf_prog *prog;
+ struct cgroup *cgrp;
+ int ret = 0;
+
+ if (!sk || !sk_fullsock(sk))
+ return 0;
+
+ if (sk->sk_family != AF_INET &&
+ sk->sk_family != AF_INET6)
+ return 0;
+
+ cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
+
+ rcu_read_lock();
+
+ prog = rcu_dereference(cgrp->bpf.effective[type]);
+ if (prog) {
+ unsigned int offset = skb->data - skb_network_header(skb);
+
+ __skb_push(skb, offset);
+ ret = bpf_prog_run_save_cb(prog, skb) == 1 ? 0 : -EPERM;
+ __skb_pull(skb, offset);
+ }
+
+ rcu_read_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL(__cgroup_bpf_run_filter_skb);
+
+/**
+ * __cgroup_bpf_run_filter_sk() - Run a program on a sock
+ * @sk: sock structure to manipulate
+ * @type: The type of program to be exectuted
+ *
+ * socket is passed is expected to be of type INET or INET6.
+ *
+ * The program type passed in via @type must be suitable for sock
+ * filtering. No further check is performed to assert that.
+ *
+ * This function will return %-EPERM if any if an attached program was found
+ * and if it returned != 1 during execution. In all other cases, 0 is returned.
+ */
+int __cgroup_bpf_run_filter_sk(struct sock *sk,
+ enum bpf_attach_type type)
+{
+ struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
+ struct bpf_prog *prog;
+ int ret = 0;
+
+
+ rcu_read_lock();
+
+ prog = rcu_dereference(cgrp->bpf.effective[type]);
+ if (prog)
+ ret = BPF_PROG_RUN(prog, sk) == 1 ? 0 : -EPERM;
+
+ rcu_read_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index aa6d98154106..83e0d153b0b4 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -136,6 +136,71 @@ void __bpf_prog_free(struct bpf_prog *fp)
vfree(fp);
}
+#define SHA_BPF_RAW_SIZE \
+ round_up(MAX_BPF_SIZE + sizeof(__be64) + 1, SHA_MESSAGE_BYTES)
+
+/* Called under verifier mutex. */
+void bpf_prog_calc_digest(struct bpf_prog *fp)
+{
+ const u32 bits_offset = SHA_MESSAGE_BYTES - sizeof(__be64);
+ static u32 ws[SHA_WORKSPACE_WORDS];
+ static u8 raw[SHA_BPF_RAW_SIZE];
+ struct bpf_insn *dst = (void *)raw;
+ u32 i, bsize, psize, blocks;
+ bool was_ld_map;
+ u8 *todo = raw;
+ __be32 *result;
+ __be64 *bits;
+
+ sha_init(fp->digest);
+ memset(ws, 0, sizeof(ws));
+
+ /* We need to take out the map fd for the digest calculation
+ * since they are unstable from user space side.
+ */
+ for (i = 0, was_ld_map = false; i < fp->len; i++) {
+ dst[i] = fp->insnsi[i];
+ if (!was_ld_map &&
+ dst[i].code == (BPF_LD | BPF_IMM | BPF_DW) &&
+ dst[i].src_reg == BPF_PSEUDO_MAP_FD) {
+ was_ld_map = true;
+ dst[i].imm = 0;
+ } else if (was_ld_map &&
+ dst[i].code == 0 &&
+ dst[i].dst_reg == 0 &&
+ dst[i].src_reg == 0 &&
+ dst[i].off == 0) {
+ was_ld_map = false;
+ dst[i].imm = 0;
+ } else {
+ was_ld_map = false;
+ }
+ }
+
+ psize = fp->len * sizeof(struct bpf_insn);
+ memset(&raw[psize], 0, sizeof(raw) - psize);
+ raw[psize++] = 0x80;
+
+ bsize = round_up(psize, SHA_MESSAGE_BYTES);
+ blocks = bsize / SHA_MESSAGE_BYTES;
+ if (bsize - psize >= sizeof(__be64)) {
+ bits = (__be64 *)(todo + bsize - sizeof(__be64));
+ } else {
+ bits = (__be64 *)(todo + bsize + bits_offset);
+ blocks++;
+ }
+ *bits = cpu_to_be64((psize - 1) << 3);
+
+ while (blocks--) {
+ sha_transform(fp->digest, todo, ws);
+ todo += SHA_MESSAGE_BYTES;
+ }
+
+ result = (__force __be32 *)fp->digest;
+ for (i = 0; i < SHA_DIGEST_WORDS; i++)
+ result[i] = cpu_to_be32(fp->digest[i]);
+}
+
static bool bpf_is_jmp_and_has_target(const struct bpf_insn *insn)
{
return BPF_CLASS(insn->code) == BPF_JMP &&
@@ -1043,6 +1108,7 @@ const struct bpf_func_proto bpf_map_delete_elem_proto __weak;
const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
+const struct bpf_func_proto bpf_get_numa_node_id_proto __weak;
const struct bpf_func_proto bpf_ktime_get_ns_proto __weak;
const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak;
@@ -1077,7 +1143,7 @@ struct bpf_prog * __weak bpf_int_jit_compile(struct bpf_prog *prog)
return prog;
}
-bool __weak bpf_helper_changes_skb_data(void *func)
+bool __weak bpf_helper_changes_pkt_data(void *func)
{
return false;
}
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index ad1bc67aff1b..34debc1a9641 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -15,6 +15,7 @@
#include <linux/filter.h>
#include <linux/vmalloc.h>
#include "percpu_freelist.h"
+#include "bpf_lru_list.h"
struct bucket {
struct hlist_head head;
@@ -25,7 +26,10 @@ struct bpf_htab {
struct bpf_map map;
struct bucket *buckets;
void *elems;
- struct pcpu_freelist freelist;
+ union {
+ struct pcpu_freelist freelist;
+ struct bpf_lru lru;
+ };
void __percpu *extra_elems;
atomic_t count; /* number of elements in this hashtable */
u32 n_buckets; /* number of hash buckets */
@@ -48,11 +52,26 @@ struct htab_elem {
union {
struct rcu_head rcu;
enum extra_elem_state state;
+ struct bpf_lru_node lru_node;
};
u32 hash;
char key[0] __aligned(8);
};
+static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node);
+
+static bool htab_is_lru(const struct bpf_htab *htab)
+{
+ return htab->map.map_type == BPF_MAP_TYPE_LRU_HASH ||
+ htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
+}
+
+static bool htab_is_percpu(const struct bpf_htab *htab)
+{
+ return htab->map.map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
+}
+
static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size,
void __percpu *pptr)
{
@@ -73,7 +92,7 @@ static void htab_free_elems(struct bpf_htab *htab)
{
int i;
- if (htab->map.map_type != BPF_MAP_TYPE_PERCPU_HASH)
+ if (!htab_is_percpu(htab))
goto free_elems;
for (i = 0; i < htab->map.max_entries; i++) {
@@ -87,7 +106,22 @@ free_elems:
vfree(htab->elems);
}
-static int prealloc_elems_and_freelist(struct bpf_htab *htab)
+static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
+ u32 hash)
+{
+ struct bpf_lru_node *node = bpf_lru_pop_free(&htab->lru, hash);
+ struct htab_elem *l;
+
+ if (node) {
+ l = container_of(node, struct htab_elem, lru_node);
+ memcpy(l->key, key, htab->map.key_size);
+ return l;
+ }
+
+ return NULL;
+}
+
+static int prealloc_init(struct bpf_htab *htab)
{
int err = -ENOMEM, i;
@@ -95,7 +129,7 @@ static int prealloc_elems_and_freelist(struct bpf_htab *htab)
if (!htab->elems)
return -ENOMEM;
- if (htab->map.map_type != BPF_MAP_TYPE_PERCPU_HASH)
+ if (!htab_is_percpu(htab))
goto skip_percpu_elems;
for (i = 0; i < htab->map.max_entries; i++) {
@@ -110,12 +144,27 @@ static int prealloc_elems_and_freelist(struct bpf_htab *htab)
}
skip_percpu_elems:
- err = pcpu_freelist_init(&htab->freelist);
+ if (htab_is_lru(htab))
+ err = bpf_lru_init(&htab->lru,
+ htab->map.map_flags & BPF_F_NO_COMMON_LRU,
+ offsetof(struct htab_elem, hash) -
+ offsetof(struct htab_elem, lru_node),
+ htab_lru_map_delete_node,
+ htab);
+ else
+ err = pcpu_freelist_init(&htab->freelist);
+
if (err)
goto free_elems;
- pcpu_freelist_populate(&htab->freelist, htab->elems, htab->elem_size,
- htab->map.max_entries);
+ if (htab_is_lru(htab))
+ bpf_lru_populate(&htab->lru, htab->elems,
+ offsetof(struct htab_elem, lru_node),
+ htab->elem_size, htab->map.max_entries);
+ else
+ pcpu_freelist_populate(&htab->freelist, htab->elems,
+ htab->elem_size, htab->map.max_entries);
+
return 0;
free_elems:
@@ -123,6 +172,16 @@ free_elems:
return err;
}
+static void prealloc_destroy(struct bpf_htab *htab)
+{
+ htab_free_elems(htab);
+
+ if (htab_is_lru(htab))
+ bpf_lru_destroy(&htab->lru);
+ else
+ pcpu_freelist_destroy(&htab->freelist);
+}
+
static int alloc_extra_elems(struct bpf_htab *htab)
{
void __percpu *pptr;
@@ -143,15 +202,37 @@ static int alloc_extra_elems(struct bpf_htab *htab)
/* Called from syscall */
static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
{
- bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_HASH;
+ bool percpu = (attr->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ attr->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH);
+ bool lru = (attr->map_type == BPF_MAP_TYPE_LRU_HASH ||
+ attr->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH);
+ /* percpu_lru means each cpu has its own LRU list.
+ * it is different from BPF_MAP_TYPE_PERCPU_HASH where
+ * the map's value itself is percpu. percpu_lru has
+ * nothing to do with the map's value.
+ */
+ bool percpu_lru = (attr->map_flags & BPF_F_NO_COMMON_LRU);
+ bool prealloc = !(attr->map_flags & BPF_F_NO_PREALLOC);
struct bpf_htab *htab;
int err, i;
u64 cost;
- if (attr->map_flags & ~BPF_F_NO_PREALLOC)
+ if (lru && !capable(CAP_SYS_ADMIN))
+ /* LRU implementation is much complicated than other
+ * maps. Hence, limit to CAP_SYS_ADMIN for now.
+ */
+ return ERR_PTR(-EPERM);
+
+ if (attr->map_flags & ~(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU))
/* reserved bits should not be used */
return ERR_PTR(-EINVAL);
+ if (!lru && percpu_lru)
+ return ERR_PTR(-EINVAL);
+
+ if (lru && !prealloc)
+ return ERR_PTR(-ENOTSUPP);
+
htab = kzalloc(sizeof(*htab), GFP_USER);
if (!htab)
return ERR_PTR(-ENOMEM);
@@ -171,6 +252,18 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
htab->map.value_size == 0)
goto free_htab;
+ if (percpu_lru) {
+ /* ensure each CPU's lru list has >=1 elements.
+ * since we are at it, make each lru list has the same
+ * number of elements.
+ */
+ htab->map.max_entries = roundup(attr->max_entries,
+ num_possible_cpus());
+ if (htab->map.max_entries < attr->max_entries)
+ htab->map.max_entries = rounddown(attr->max_entries,
+ num_possible_cpus());
+ }
+
/* hash table size must be power of 2 */
htab->n_buckets = roundup_pow_of_two(htab->map.max_entries);
@@ -241,14 +334,17 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
raw_spin_lock_init(&htab->buckets[i].lock);
}
- if (!percpu) {
+ if (!percpu && !lru) {
+ /* lru itself can remove the least used element, so
+ * there is no need for an extra elem during map_update.
+ */
err = alloc_extra_elems(htab);
if (err)
goto free_buckets;
}
- if (!(attr->map_flags & BPF_F_NO_PREALLOC)) {
- err = prealloc_elems_and_freelist(htab);
+ if (prealloc) {
+ err = prealloc_init(htab);
if (err)
goto free_extra_elems;
}
@@ -323,6 +419,46 @@ static void *htab_map_lookup_elem(struct bpf_map *map, void *key)
return NULL;
}
+static void *htab_lru_map_lookup_elem(struct bpf_map *map, void *key)
+{
+ struct htab_elem *l = __htab_map_lookup_elem(map, key);
+
+ if (l) {
+ bpf_lru_node_set_ref(&l->lru_node);
+ return l->key + round_up(map->key_size, 8);
+ }
+
+ return NULL;
+}
+
+/* It is called from the bpf_lru_list when the LRU needs to delete
+ * older elements from the htab.
+ */
+static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
+{
+ struct bpf_htab *htab = (struct bpf_htab *)arg;
+ struct htab_elem *l, *tgt_l;
+ struct hlist_head *head;
+ unsigned long flags;
+ struct bucket *b;
+
+ tgt_l = container_of(node, struct htab_elem, lru_node);
+ b = __select_bucket(htab, tgt_l->hash);
+ head = &b->head;
+
+ raw_spin_lock_irqsave(&b->lock, flags);
+
+ hlist_for_each_entry_rcu(l, head, hash_node)
+ if (l == tgt_l) {
+ hlist_del_rcu(&l->hash_node);
+ break;
+ }
+
+ raw_spin_unlock_irqrestore(&b->lock, flags);
+
+ return l == tgt_l;
+}
+
/* Called from syscall */
static int htab_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
{
@@ -420,6 +556,24 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
}
}
+static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
+ void *value, bool onallcpus)
+{
+ if (!onallcpus) {
+ /* copy true value_size bytes */
+ memcpy(this_cpu_ptr(pptr), value, htab->map.value_size);
+ } else {
+ u32 size = round_up(htab->map.value_size, 8);
+ int off = 0, cpu;
+
+ for_each_possible_cpu(cpu) {
+ bpf_long_memcpy(per_cpu_ptr(pptr, cpu),
+ value + off, size);
+ off += size;
+ }
+ }
+}
+
static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
void *value, u32 key_size, u32 hash,
bool percpu, bool onallcpus,
@@ -479,18 +633,8 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
}
}
- if (!onallcpus) {
- /* copy true value_size bytes */
- memcpy(this_cpu_ptr(pptr), value, htab->map.value_size);
- } else {
- int off = 0, cpu;
+ pcpu_copy_value(htab, pptr, value, onallcpus);
- for_each_possible_cpu(cpu) {
- bpf_long_memcpy(per_cpu_ptr(pptr, cpu),
- value + off, size);
- off += size;
- }
- }
if (!prealloc)
htab_elem_set_ptr(l_new, key_size, pptr);
} else {
@@ -571,6 +715,70 @@ err:
return ret;
}
+static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
+ u64 map_flags)
+{
+ struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ struct htab_elem *l_new, *l_old = NULL;
+ struct hlist_head *head;
+ unsigned long flags;
+ struct bucket *b;
+ u32 key_size, hash;
+ int ret;
+
+ if (unlikely(map_flags > BPF_EXIST))
+ /* unknown flags */
+ return -EINVAL;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ key_size = map->key_size;
+
+ hash = htab_map_hash(key, key_size);
+
+ b = __select_bucket(htab, hash);
+ head = &b->head;
+
+ /* For LRU, we need to alloc before taking bucket's
+ * spinlock because getting free nodes from LRU may need
+ * to remove older elements from htab and this removal
+ * operation will need a bucket lock.
+ */
+ l_new = prealloc_lru_pop(htab, key, hash);
+ if (!l_new)
+ return -ENOMEM;
+ memcpy(l_new->key + round_up(map->key_size, 8), value, map->value_size);
+
+ /* bpf_map_update_elem() can be called in_irq() */
+ raw_spin_lock_irqsave(&b->lock, flags);
+
+ l_old = lookup_elem_raw(head, hash, key, key_size);
+
+ ret = check_flags(htab, l_old, map_flags);
+ if (ret)
+ goto err;
+
+ /* add new element to the head of the list, so that
+ * concurrent search will find it before old elem
+ */
+ hlist_add_head_rcu(&l_new->hash_node, head);
+ if (l_old) {
+ bpf_lru_node_set_ref(&l_new->lru_node);
+ hlist_del_rcu(&l_old->hash_node);
+ }
+ ret = 0;
+
+err:
+ raw_spin_unlock_irqrestore(&b->lock, flags);
+
+ if (ret)
+ bpf_lru_push_free(&htab->lru, &l_new->lru_node);
+ else if (l_old)
+ bpf_lru_push_free(&htab->lru, &l_old->lru_node);
+
+ return ret;
+}
+
static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
void *value, u64 map_flags,
bool onallcpus)
@@ -606,22 +814,9 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
goto err;
if (l_old) {
- void __percpu *pptr = htab_elem_get_ptr(l_old, key_size);
- u32 size = htab->map.value_size;
-
/* per-cpu hash map can update value in-place */
- if (!onallcpus) {
- memcpy(this_cpu_ptr(pptr), value, size);
- } else {
- int off = 0, cpu;
-
- size = round_up(size, 8);
- for_each_possible_cpu(cpu) {
- bpf_long_memcpy(per_cpu_ptr(pptr, cpu),
- value + off, size);
- off += size;
- }
- }
+ pcpu_copy_value(htab, htab_elem_get_ptr(l_old, key_size),
+ value, onallcpus);
} else {
l_new = alloc_htab_elem(htab, key, value, key_size,
hash, true, onallcpus, false);
@@ -637,12 +832,84 @@ err:
return ret;
}
+static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
+ void *value, u64 map_flags,
+ bool onallcpus)
+{
+ struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ struct htab_elem *l_new = NULL, *l_old;
+ struct hlist_head *head;
+ unsigned long flags;
+ struct bucket *b;
+ u32 key_size, hash;
+ int ret;
+
+ if (unlikely(map_flags > BPF_EXIST))
+ /* unknown flags */
+ return -EINVAL;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ key_size = map->key_size;
+
+ hash = htab_map_hash(key, key_size);
+
+ b = __select_bucket(htab, hash);
+ head = &b->head;
+
+ /* For LRU, we need to alloc before taking bucket's
+ * spinlock because LRU's elem alloc may need
+ * to remove older elem from htab and this removal
+ * operation will need a bucket lock.
+ */
+ if (map_flags != BPF_EXIST) {
+ l_new = prealloc_lru_pop(htab, key, hash);
+ if (!l_new)
+ return -ENOMEM;
+ }
+
+ /* bpf_map_update_elem() can be called in_irq() */
+ raw_spin_lock_irqsave(&b->lock, flags);
+
+ l_old = lookup_elem_raw(head, hash, key, key_size);
+
+ ret = check_flags(htab, l_old, map_flags);
+ if (ret)
+ goto err;
+
+ if (l_old) {
+ bpf_lru_node_set_ref(&l_old->lru_node);
+
+ /* per-cpu hash map can update value in-place */
+ pcpu_copy_value(htab, htab_elem_get_ptr(l_old, key_size),
+ value, onallcpus);
+ } else {
+ pcpu_copy_value(htab, htab_elem_get_ptr(l_new, key_size),
+ value, onallcpus);
+ hlist_add_head_rcu(&l_new->hash_node, head);
+ l_new = NULL;
+ }
+ ret = 0;
+err:
+ raw_spin_unlock_irqrestore(&b->lock, flags);
+ if (l_new)
+ bpf_lru_push_free(&htab->lru, &l_new->lru_node);
+ return ret;
+}
+
static int htab_percpu_map_update_elem(struct bpf_map *map, void *key,
void *value, u64 map_flags)
{
return __htab_percpu_map_update_elem(map, key, value, map_flags, false);
}
+static int htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
+ void *value, u64 map_flags)
+{
+ return __htab_lru_percpu_map_update_elem(map, key, value, map_flags,
+ false);
+}
+
/* Called from syscall or from eBPF program */
static int htab_map_delete_elem(struct bpf_map *map, void *key)
{
@@ -676,6 +943,39 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
return ret;
}
+static int htab_lru_map_delete_elem(struct bpf_map *map, void *key)
+{
+ struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ struct hlist_head *head;
+ struct bucket *b;
+ struct htab_elem *l;
+ unsigned long flags;
+ u32 hash, key_size;
+ int ret = -ENOENT;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ key_size = map->key_size;
+
+ hash = htab_map_hash(key, key_size);
+ b = __select_bucket(htab, hash);
+ head = &b->head;
+
+ raw_spin_lock_irqsave(&b->lock, flags);
+
+ l = lookup_elem_raw(head, hash, key, key_size);
+
+ if (l) {
+ hlist_del_rcu(&l->hash_node);
+ ret = 0;
+ }
+
+ raw_spin_unlock_irqrestore(&b->lock, flags);
+ if (l)
+ bpf_lru_push_free(&htab->lru, &l->lru_node);
+ return ret;
+}
+
static void delete_all_elements(struct bpf_htab *htab)
{
int i;
@@ -708,12 +1008,11 @@ static void htab_map_free(struct bpf_map *map)
* not have executed. Wait for them.
*/
rcu_barrier();
- if (htab->map.map_flags & BPF_F_NO_PREALLOC) {
+ if (htab->map.map_flags & BPF_F_NO_PREALLOC)
delete_all_elements(htab);
- } else {
- htab_free_elems(htab);
- pcpu_freelist_destroy(&htab->freelist);
- }
+ else
+ prealloc_destroy(htab);
+
free_percpu(htab->extra_elems);
kvfree(htab->buckets);
kfree(htab);
@@ -733,6 +1032,20 @@ static struct bpf_map_type_list htab_type __read_mostly = {
.type = BPF_MAP_TYPE_HASH,
};
+static const struct bpf_map_ops htab_lru_ops = {
+ .map_alloc = htab_map_alloc,
+ .map_free = htab_map_free,
+ .map_get_next_key = htab_map_get_next_key,
+ .map_lookup_elem = htab_lru_map_lookup_elem,
+ .map_update_elem = htab_lru_map_update_elem,
+ .map_delete_elem = htab_lru_map_delete_elem,
+};
+
+static struct bpf_map_type_list htab_lru_type __read_mostly = {
+ .ops = &htab_lru_ops,
+ .type = BPF_MAP_TYPE_LRU_HASH,
+};
+
/* Called from eBPF program */
static void *htab_percpu_map_lookup_elem(struct bpf_map *map, void *key)
{
@@ -744,8 +1057,21 @@ static void *htab_percpu_map_lookup_elem(struct bpf_map *map, void *key)
return NULL;
}
+static void *htab_lru_percpu_map_lookup_elem(struct bpf_map *map, void *key)
+{
+ struct htab_elem *l = __htab_map_lookup_elem(map, key);
+
+ if (l) {
+ bpf_lru_node_set_ref(&l->lru_node);
+ return this_cpu_ptr(htab_elem_get_ptr(l, map->key_size));
+ }
+
+ return NULL;
+}
+
int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value)
{
+ struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
struct htab_elem *l;
void __percpu *pptr;
int ret = -ENOENT;
@@ -761,6 +1087,8 @@ int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value)
l = __htab_map_lookup_elem(map, key);
if (!l)
goto out;
+ if (htab_is_lru(htab))
+ bpf_lru_node_set_ref(&l->lru_node);
pptr = htab_elem_get_ptr(l, map->key_size);
for_each_possible_cpu(cpu) {
bpf_long_memcpy(value + off,
@@ -776,10 +1104,16 @@ out:
int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value,
u64 map_flags)
{
+ struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
int ret;
rcu_read_lock();
- ret = __htab_percpu_map_update_elem(map, key, value, map_flags, true);
+ if (htab_is_lru(htab))
+ ret = __htab_lru_percpu_map_update_elem(map, key, value,
+ map_flags, true);
+ else
+ ret = __htab_percpu_map_update_elem(map, key, value, map_flags,
+ true);
rcu_read_unlock();
return ret;
@@ -799,10 +1133,26 @@ static struct bpf_map_type_list htab_percpu_type __read_mostly = {
.type = BPF_MAP_TYPE_PERCPU_HASH,
};
+static const struct bpf_map_ops htab_lru_percpu_ops = {
+ .map_alloc = htab_map_alloc,
+ .map_free = htab_map_free,
+ .map_get_next_key = htab_map_get_next_key,
+ .map_lookup_elem = htab_lru_percpu_map_lookup_elem,
+ .map_update_elem = htab_lru_percpu_map_update_elem,
+ .map_delete_elem = htab_lru_map_delete_elem,
+};
+
+static struct bpf_map_type_list htab_lru_percpu_type __read_mostly = {
+ .ops = &htab_lru_percpu_ops,
+ .type = BPF_MAP_TYPE_LRU_PERCPU_HASH,
+};
+
static int __init register_htab_map(void)
{
bpf_register_map_type(&htab_type);
bpf_register_map_type(&htab_percpu_type);
+ bpf_register_map_type(&htab_lru_type);
+ bpf_register_map_type(&htab_lru_percpu_type);
return 0;
}
late_initcall(register_htab_map);
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 39918402e6e9..045cbe673356 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -13,6 +13,7 @@
#include <linux/rcupdate.h>
#include <linux/random.h>
#include <linux/smp.h>
+#include <linux/topology.h>
#include <linux/ktime.h>
#include <linux/sched.h>
#include <linux/uidgid.h>
@@ -92,6 +93,17 @@ const struct bpf_func_proto bpf_get_smp_processor_id_proto = {
.ret_type = RET_INTEGER,
};
+BPF_CALL_0(bpf_get_numa_node_id)
+{
+ return numa_node_id();
+}
+
+const struct bpf_func_proto bpf_get_numa_node_id_proto = {
+ .func = bpf_get_numa_node_id,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+};
+
BPF_CALL_0(bpf_ktime_get_ns)
{
/* NMI safe access to clock monotonic */
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 1ed8473ec537..0b030c9126d3 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -18,6 +18,7 @@
#include <linux/namei.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
+#include <linux/parser.h>
#include <linux/filter.h>
#include <linux/bpf.h>
@@ -87,6 +88,7 @@ static struct inode *bpf_get_inode(struct super_block *sb,
switch (mode & S_IFMT) {
case S_IFDIR:
case S_IFREG:
+ case S_IFLNK:
break;
default:
return ERR_PTR(-EINVAL);
@@ -119,6 +121,16 @@ static int bpf_inode_type(const struct inode *inode, enum bpf_type *type)
return 0;
}
+static void bpf_dentry_finalize(struct dentry *dentry, struct inode *inode,
+ struct inode *dir)
+{
+ d_instantiate(dentry, inode);
+ dget(dentry);
+
+ dir->i_mtime = current_time(dir);
+ dir->i_ctime = dir->i_mtime;
+}
+
static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct inode *inode;
@@ -133,9 +145,7 @@ static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
inc_nlink(inode);
inc_nlink(dir);
- d_instantiate(dentry, inode);
- dget(dentry);
-
+ bpf_dentry_finalize(dentry, inode, dir);
return 0;
}
@@ -151,9 +161,7 @@ static int bpf_mkobj_ops(struct inode *dir, struct dentry *dentry,
inode->i_op = iops;
inode->i_private = dentry->d_fsdata;
- d_instantiate(dentry, inode);
- dget(dentry);
-
+ bpf_dentry_finalize(dentry, inode, dir);
return 0;
}
@@ -181,13 +189,37 @@ bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags)
{
if (strchr(dentry->d_name.name, '.'))
return ERR_PTR(-EPERM);
+
return simple_lookup(dir, dentry, flags);
}
+static int bpf_symlink(struct inode *dir, struct dentry *dentry,
+ const char *target)
+{
+ char *link = kstrdup(target, GFP_USER | __GFP_NOWARN);
+ struct inode *inode;
+
+ if (!link)
+ return -ENOMEM;
+
+ inode = bpf_get_inode(dir->i_sb, dir, S_IRWXUGO | S_IFLNK);
+ if (IS_ERR(inode)) {
+ kfree(link);
+ return PTR_ERR(inode);
+ }
+
+ inode->i_op = &simple_symlink_inode_operations;
+ inode->i_link = link;
+
+ bpf_dentry_finalize(dentry, inode, dir);
+ return 0;
+}
+
static const struct inode_operations bpf_dir_iops = {
.lookup = bpf_lookup,
.mknod = bpf_mkobj,
.mkdir = bpf_mkdir,
+ .symlink = bpf_symlink,
.rmdir = simple_rmdir,
.rename = simple_rename,
.link = simple_link,
@@ -324,6 +356,8 @@ static void bpf_evict_inode(struct inode *inode)
truncate_inode_pages_final(&inode->i_data);
clear_inode(inode);
+ if (S_ISLNK(inode->i_mode))
+ kfree(inode->i_link);
if (!bpf_inode_type(inode, &type))
bpf_any_put(inode->i_private, type);
}
@@ -331,15 +365,66 @@ static void bpf_evict_inode(struct inode *inode)
static const struct super_operations bpf_super_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
+ .show_options = generic_show_options,
.evict_inode = bpf_evict_inode,
};
+enum {
+ OPT_MODE,
+ OPT_ERR,
+};
+
+static const match_table_t bpf_mount_tokens = {
+ { OPT_MODE, "mode=%o" },
+ { OPT_ERR, NULL },
+};
+
+struct bpf_mount_opts {
+ umode_t mode;
+};
+
+static int bpf_parse_options(char *data, struct bpf_mount_opts *opts)
+{
+ substring_t args[MAX_OPT_ARGS];
+ int option, token;
+ char *ptr;
+
+ opts->mode = S_IRWXUGO;
+
+ while ((ptr = strsep(&data, ",")) != NULL) {
+ if (!*ptr)
+ continue;
+
+ token = match_token(ptr, bpf_mount_tokens, args);
+ switch (token) {
+ case OPT_MODE:
+ if (match_octal(&args[0], &option))
+ return -EINVAL;
+ opts->mode = option & S_IALLUGO;
+ break;
+ /* We might like to report bad mount options here, but
+ * traditionally we've ignored all mount options, so we'd
+ * better continue to ignore non-existing options for bpf.
+ */
+ }
+ }
+
+ return 0;
+}
+
static int bpf_fill_super(struct super_block *sb, void *data, int silent)
{
static struct tree_descr bpf_rfiles[] = { { "" } };
+ struct bpf_mount_opts opts;
struct inode *inode;
int ret;
+ save_mount_options(sb, data);
+
+ ret = bpf_parse_options(data, &opts);
+ if (ret)
+ return ret;
+
ret = simple_fill_super(sb, BPF_FS_MAGIC, bpf_rfiles);
if (ret)
return ret;
@@ -349,7 +434,7 @@ static int bpf_fill_super(struct super_block *sb, void *data, int silent)
inode = sb->s_root->d_inode;
inode->i_op = &bpf_dir_iops;
inode->i_mode &= ~S_IALLUGO;
- inode->i_mode |= S_ISVTX | S_IRWXUGO;
+ inode->i_mode |= S_ISVTX | opts.mode;
return 0;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 237f3d6a7ddc..4819ec9d95f6 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -17,6 +17,7 @@
#include <linux/license.h>
#include <linux/filter.h>
#include <linux/version.h>
+#include <linux/kernel.h>
DEFINE_PER_CPU(int, bpf_prog_active);
@@ -137,18 +138,31 @@ static int bpf_map_release(struct inode *inode, struct file *filp)
static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
{
const struct bpf_map *map = filp->private_data;
+ const struct bpf_array *array;
+ u32 owner_prog_type = 0;
+
+ if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
+ array = container_of(map, struct bpf_array, map);
+ owner_prog_type = array->owner_prog_type;
+ }
seq_printf(m,
"map_type:\t%u\n"
"key_size:\t%u\n"
"value_size:\t%u\n"
"max_entries:\t%u\n"
- "map_flags:\t%#x\n",
+ "map_flags:\t%#x\n"
+ "memlock:\t%llu\n",
map->map_type,
map->key_size,
map->value_size,
map->max_entries,
- map->map_flags);
+ map->map_flags,
+ map->pages * 1ULL << PAGE_SHIFT);
+
+ if (owner_prog_type)
+ seq_printf(m, "owner_prog_type:\t%u\n",
+ owner_prog_type);
}
#endif
@@ -254,12 +268,6 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd)
return map;
}
-/* helper to convert user pointers passed inside __aligned_u64 fields */
-static void __user *u64_to_ptr(__u64 val)
-{
- return (void __user *) (unsigned long) val;
-}
-
int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
{
return -ENOTSUPP;
@@ -270,8 +278,8 @@ int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
static int map_lookup_elem(union bpf_attr *attr)
{
- void __user *ukey = u64_to_ptr(attr->key);
- void __user *uvalue = u64_to_ptr(attr->value);
+ void __user *ukey = u64_to_user_ptr(attr->key);
+ void __user *uvalue = u64_to_user_ptr(attr->value);
int ufd = attr->map_fd;
struct bpf_map *map;
void *key, *value, *ptr;
@@ -297,6 +305,7 @@ static int map_lookup_elem(union bpf_attr *attr)
goto free_key;
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
value_size = round_up(map->value_size, 8) * num_possible_cpus();
else
@@ -307,7 +316,8 @@ static int map_lookup_elem(union bpf_attr *attr)
if (!value)
goto free_key;
- if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
+ if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
err = bpf_percpu_hash_copy(map, key, value);
} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
err = bpf_percpu_array_copy(map, key, value);
@@ -344,8 +354,8 @@ err_put:
static int map_update_elem(union bpf_attr *attr)
{
- void __user *ukey = u64_to_ptr(attr->key);
- void __user *uvalue = u64_to_ptr(attr->value);
+ void __user *ukey = u64_to_user_ptr(attr->key);
+ void __user *uvalue = u64_to_user_ptr(attr->value);
int ufd = attr->map_fd;
struct bpf_map *map;
void *key, *value;
@@ -371,6 +381,7 @@ static int map_update_elem(union bpf_attr *attr)
goto free_key;
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
value_size = round_up(map->value_size, 8) * num_possible_cpus();
else
@@ -390,7 +401,8 @@ static int map_update_elem(union bpf_attr *attr)
*/
preempt_disable();
__this_cpu_inc(bpf_prog_active);
- if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
+ if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+ map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
err = bpf_percpu_hash_update(map, key, value, attr->flags);
} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
err = bpf_percpu_array_update(map, key, value, attr->flags);
@@ -422,7 +434,7 @@ err_put:
static int map_delete_elem(union bpf_attr *attr)
{
- void __user *ukey = u64_to_ptr(attr->key);
+ void __user *ukey = u64_to_user_ptr(attr->key);
int ufd = attr->map_fd;
struct bpf_map *map;
struct fd f;
@@ -466,8 +478,8 @@ err_put:
static int map_get_next_key(union bpf_attr *attr)
{
- void __user *ukey = u64_to_ptr(attr->key);
- void __user *unext_key = u64_to_ptr(attr->next_key);
+ void __user *ukey = u64_to_user_ptr(attr->key);
+ void __user *unext_key = u64_to_user_ptr(attr->next_key);
int ufd = attr->map_fd;
struct bpf_map *map;
void *key, *next_key;
@@ -567,6 +579,8 @@ static void fixup_bpf_calls(struct bpf_prog *prog)
prog->dst_needed = 1;
if (insn->imm == BPF_FUNC_get_prandom_u32)
bpf_user_rnd_init_once();
+ if (insn->imm == BPF_FUNC_xdp_adjust_head)
+ prog->xdp_adjust_head = 1;
if (insn->imm == BPF_FUNC_tail_call) {
/* mark bpf_tail_call as different opcode
* to avoid conditional branch in
@@ -650,8 +664,30 @@ static int bpf_prog_release(struct inode *inode, struct file *filp)
return 0;
}
+#ifdef CONFIG_PROC_FS
+static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
+{
+ const struct bpf_prog *prog = filp->private_data;
+ char prog_digest[sizeof(prog->digest) * 2 + 1] = { };
+
+ bin2hex(prog_digest, prog->digest, sizeof(prog->digest));
+ seq_printf(m,
+ "prog_type:\t%u\n"
+ "prog_jited:\t%u\n"
+ "prog_digest:\t%s\n"
+ "memlock:\t%llu\n",
+ prog->type,
+ prog->jited,
+ prog_digest,
+ prog->pages * 1ULL << PAGE_SHIFT);
+}
+#endif
+
static const struct file_operations bpf_prog_fops = {
- .release = bpf_prog_release,
+#ifdef CONFIG_PROC_FS
+ .show_fdinfo = bpf_prog_show_fdinfo,
+#endif
+ .release = bpf_prog_release,
};
int bpf_prog_new_fd(struct bpf_prog *prog)
@@ -682,10 +718,22 @@ struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
}
EXPORT_SYMBOL_GPL(bpf_prog_add);
+void bpf_prog_sub(struct bpf_prog *prog, int i)
+{
+ /* Only to be used for undoing previous bpf_prog_add() in some
+ * error path. We still know that another entity in our call
+ * path holds a reference to the program, thus atomic_sub() can
+ * be safely used in such cases!
+ */
+ WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
+}
+EXPORT_SYMBOL_GPL(bpf_prog_sub);
+
struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
{
return bpf_prog_add(prog, 1);
}
+EXPORT_SYMBOL_GPL(bpf_prog_inc);
static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
{
@@ -732,7 +780,7 @@ static int bpf_prog_load(union bpf_attr *attr)
return -EINVAL;
/* copy eBPF program license from user space */
- if (strncpy_from_user(license, u64_to_ptr(attr->license),
+ if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
sizeof(license) - 1) < 0)
return -EFAULT;
license[sizeof(license) - 1] = 0;
@@ -740,8 +788,8 @@ static int bpf_prog_load(union bpf_attr *attr)
/* eBPF programs must be GPL compatible to use GPL-ed functions */
is_gpl = license_is_gpl_compatible(license);
- if (attr->insn_cnt >= BPF_MAXINSNS)
- return -EINVAL;
+ if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS)
+ return -E2BIG;
if (type == BPF_PROG_TYPE_KPROBE &&
attr->kern_version != LINUX_VERSION_CODE)
@@ -762,7 +810,7 @@ static int bpf_prog_load(union bpf_attr *attr)
prog->len = attr->insn_cnt;
err = -EFAULT;
- if (copy_from_user(prog->insns, u64_to_ptr(attr->insns),
+ if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
prog->len * sizeof(struct bpf_insn)) != 0)
goto free_prog;
@@ -813,7 +861,7 @@ static int bpf_obj_pin(const union bpf_attr *attr)
if (CHECK_ATTR(BPF_OBJ))
return -EINVAL;
- return bpf_obj_pin_user(attr->bpf_fd, u64_to_ptr(attr->pathname));
+ return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
}
static int bpf_obj_get(const union bpf_attr *attr)
@@ -821,8 +869,84 @@ static int bpf_obj_get(const union bpf_attr *attr)
if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0)
return -EINVAL;
- return bpf_obj_get_user(u64_to_ptr(attr->pathname));
+ return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
+}
+
+#ifdef CONFIG_CGROUP_BPF
+
+#define BPF_PROG_ATTACH_LAST_FIELD attach_type
+
+static int bpf_prog_attach(const union bpf_attr *attr)
+{
+ struct bpf_prog *prog;
+ struct cgroup *cgrp;
+ enum bpf_prog_type ptype;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (CHECK_ATTR(BPF_PROG_ATTACH))
+ return -EINVAL;
+
+ switch (attr->attach_type) {
+ case BPF_CGROUP_INET_INGRESS:
+ case BPF_CGROUP_INET_EGRESS:
+ ptype = BPF_PROG_TYPE_CGROUP_SKB;
+ break;
+ case BPF_CGROUP_INET_SOCK_CREATE:
+ ptype = BPF_PROG_TYPE_CGROUP_SOCK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
+ if (IS_ERR(prog))
+ return PTR_ERR(prog);
+
+ cgrp = cgroup_get_from_fd(attr->target_fd);
+ if (IS_ERR(cgrp)) {
+ bpf_prog_put(prog);
+ return PTR_ERR(cgrp);
+ }
+
+ cgroup_bpf_update(cgrp, prog, attr->attach_type);
+ cgroup_put(cgrp);
+
+ return 0;
+}
+
+#define BPF_PROG_DETACH_LAST_FIELD attach_type
+
+static int bpf_prog_detach(const union bpf_attr *attr)
+{
+ struct cgroup *cgrp;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (CHECK_ATTR(BPF_PROG_DETACH))
+ return -EINVAL;
+
+ switch (attr->attach_type) {
+ case BPF_CGROUP_INET_INGRESS:
+ case BPF_CGROUP_INET_EGRESS:
+ case BPF_CGROUP_INET_SOCK_CREATE:
+ cgrp = cgroup_get_from_fd(attr->target_fd);
+ if (IS_ERR(cgrp))
+ return PTR_ERR(cgrp);
+
+ cgroup_bpf_update(cgrp, NULL, attr->attach_type);
+ cgroup_put(cgrp);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
}
+#endif /* CONFIG_CGROUP_BPF */
SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
{
@@ -890,6 +1014,16 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
case BPF_OBJ_GET:
err = bpf_obj_get(&attr);
break;
+
+#ifdef CONFIG_CGROUP_BPF
+ case BPF_PROG_ATTACH:
+ err = bpf_prog_attach(&attr);
+ break;
+ case BPF_PROG_DETACH:
+ err = bpf_prog_detach(&attr);
+ break;
+#endif
+
default:
err = -EINVAL;
break;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8199821f54cf..d28f9a3380a9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -19,6 +19,7 @@
#include <net/netlink.h>
#include <linux/file.h>
#include <linux/vmalloc.h>
+#include <linux/stringify.h>
/* bpf_check() is a static code analyzer that walks eBPF program
* instruction by instruction and updates register/stack state.
@@ -190,6 +191,22 @@ static const char * const reg_type_str[] = {
[PTR_TO_PACKET_END] = "pkt_end",
};
+#define __BPF_FUNC_STR_FN(x) [BPF_FUNC_ ## x] = __stringify(bpf_ ## x)
+static const char * const func_id_str[] = {
+ __BPF_FUNC_MAPPER(__BPF_FUNC_STR_FN)
+};
+#undef __BPF_FUNC_STR_FN
+
+static const char *func_id_name(int id)
+{
+ BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID);
+
+ if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id])
+ return func_id_str[id];
+ else
+ return "unknown";
+}
+
static void print_verifier_state(struct bpf_verifier_state *state)
{
struct bpf_reg_state *reg;
@@ -212,9 +229,10 @@ static void print_verifier_state(struct bpf_verifier_state *state)
else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE ||
t == PTR_TO_MAP_VALUE_OR_NULL ||
t == PTR_TO_MAP_VALUE_ADJ)
- verbose("(ks=%d,vs=%d)",
+ verbose("(ks=%d,vs=%d,id=%u)",
reg->map_ptr->key_size,
- reg->map_ptr->value_size);
+ reg->map_ptr->value_size,
+ reg->id);
if (reg->min_value != BPF_REGISTER_MIN_RANGE)
verbose(",min_value=%lld",
(long long)reg->min_value);
@@ -353,7 +371,8 @@ static void print_bpf_insn(struct bpf_insn *insn)
u8 opcode = BPF_OP(insn->code);
if (opcode == BPF_CALL) {
- verbose("(%02x) call %d\n", insn->code, insn->imm);
+ verbose("(%02x) call %s#%d\n", insn->code,
+ func_id_name(insn->imm), insn->imm);
} else if (insn->code == (BPF_JMP | BPF_JA)) {
verbose("(%02x) goto pc%+d\n",
insn->code, insn->off);
@@ -447,6 +466,7 @@ static void mark_reg_unknown_value(struct bpf_reg_state *regs, u32 regno)
{
BUG_ON(regno >= MAX_BPF_REG);
regs[regno].type = UNKNOWN_VALUE;
+ regs[regno].id = 0;
regs[regno].imm = 0;
}
@@ -613,12 +633,19 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, int off,
#define MAX_PACKET_OFF 0xffff
static bool may_access_direct_pkt_data(struct bpf_verifier_env *env,
- const struct bpf_call_arg_meta *meta)
+ const struct bpf_call_arg_meta *meta,
+ enum bpf_access_type t)
{
switch (env->prog->type) {
+ case BPF_PROG_TYPE_LWT_IN:
+ case BPF_PROG_TYPE_LWT_OUT:
+ /* dst_input() and dst_output() can't write for now */
+ if (t == BPF_WRITE)
+ return false;
case BPF_PROG_TYPE_SCHED_CLS:
case BPF_PROG_TYPE_SCHED_ACT:
case BPF_PROG_TYPE_XDP:
+ case BPF_PROG_TYPE_LWT_XMIT:
if (meta)
return meta->pkt_access;
@@ -817,7 +844,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
err = check_stack_read(state, off, size, value_regno);
}
} else if (state->regs[regno].type == PTR_TO_PACKET) {
- if (t == BPF_WRITE && !may_access_direct_pkt_data(env, NULL)) {
+ if (t == BPF_WRITE && !may_access_direct_pkt_data(env, NULL, t)) {
verbose("cannot write into packet\n");
return -EACCES;
}
@@ -950,7 +977,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
return 0;
}
- if (type == PTR_TO_PACKET && !may_access_direct_pkt_data(env, meta)) {
+ if (type == PTR_TO_PACKET &&
+ !may_access_direct_pkt_data(env, meta, BPF_READ)) {
verbose("helper access to the packet is not allowed\n");
return -EACCES;
}
@@ -1112,8 +1140,8 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
return 0;
error:
- verbose("cannot pass map_type %d into func %d\n",
- map->map_type, func_id);
+ verbose("cannot pass map_type %d into func %s#%d\n",
+ map->map_type, func_id_name(func_id), func_id);
return -EINVAL;
}
@@ -1170,7 +1198,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
/* find function prototype */
if (func_id < 0 || func_id >= __BPF_FUNC_MAX_ID) {
- verbose("invalid func %d\n", func_id);
+ verbose("invalid func %s#%d\n", func_id_name(func_id), func_id);
return -EINVAL;
}
@@ -1178,7 +1206,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
fn = env->prog->aux->ops->get_func_proto(func_id);
if (!fn) {
- verbose("unknown func %d\n", func_id);
+ verbose("unknown func %s#%d\n", func_id_name(func_id), func_id);
return -EINVAL;
}
@@ -1188,7 +1216,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
return -EINVAL;
}
- changes_data = bpf_helper_changes_skb_data(fn->func);
+ changes_data = bpf_helper_changes_pkt_data(fn->func);
memset(&meta, 0, sizeof(meta));
meta.pkt_access = fn->pkt_access;
@@ -1198,7 +1226,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
*/
err = check_raw_mode(fn);
if (err) {
- verbose("kernel subsystem misconfigured func %d\n", func_id);
+ verbose("kernel subsystem misconfigured func %s#%d\n",
+ func_id_name(func_id), func_id);
return err;
}
@@ -1252,9 +1281,10 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
return -EINVAL;
}
regs[BPF_REG_0].map_ptr = meta.map_ptr;
+ regs[BPF_REG_0].id = ++env->id_gen;
} else {
- verbose("unknown return type %d of func %d\n",
- fn->ret_type, func_id);
+ verbose("unknown return type %d of func %s#%d\n",
+ fn->ret_type, func_id_name(func_id), func_id);
return -EINVAL;
}
@@ -1451,14 +1481,19 @@ static int evaluate_reg_imm_alu(struct bpf_verifier_env *env,
struct bpf_reg_state *src_reg = &regs[insn->src_reg];
u8 opcode = BPF_OP(insn->code);
- /* dst_reg->type == CONST_IMM here, simulate execution of 'add' insn.
- * Don't care about overflow or negative values, just add them
+ /* dst_reg->type == CONST_IMM here, simulate execution of 'add'/'or'
+ * insn. Don't care about overflow or negative values, just add them
*/
if (opcode == BPF_ADD && BPF_SRC(insn->code) == BPF_K)
dst_reg->imm += insn->imm;
else if (opcode == BPF_ADD && BPF_SRC(insn->code) == BPF_X &&
src_reg->type == CONST_IMM)
dst_reg->imm += src_reg->imm;
+ else if (opcode == BPF_OR && BPF_SRC(insn->code) == BPF_K)
+ dst_reg->imm |= insn->imm;
+ else if (opcode == BPF_OR && BPF_SRC(insn->code) == BPF_X &&
+ src_reg->type == CONST_IMM)
+ dst_reg->imm |= src_reg->imm;
else
mark_reg_unknown_value(regs, insn->dst_reg);
return 0;
@@ -1479,7 +1514,6 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
struct bpf_reg_state *regs = env->cur_state.regs, *dst_reg;
s64 min_val = BPF_REGISTER_MIN_RANGE;
u64 max_val = BPF_REGISTER_MAX_RANGE;
- bool min_set = false, max_set = false;
u8 opcode = BPF_OP(insn->code);
dst_reg = &regs[insn->dst_reg];
@@ -1502,7 +1536,6 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
} else if (insn->imm < BPF_REGISTER_MAX_RANGE &&
(s64)insn->imm > BPF_REGISTER_MIN_RANGE) {
min_val = max_val = insn->imm;
- min_set = max_set = true;
}
/* We don't know anything about what was done to this register, mark it
@@ -1668,8 +1701,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
insn->src_reg);
return -EACCES;
}
- regs[insn->dst_reg].type = UNKNOWN_VALUE;
- regs[insn->dst_reg].map_ptr = NULL;
+ mark_reg_unknown_value(regs, insn->dst_reg);
}
} else {
/* case: R = imm
@@ -1931,6 +1963,38 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
check_reg_overflow(true_reg);
}
+static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
+ enum bpf_reg_type type)
+{
+ struct bpf_reg_state *reg = &regs[regno];
+
+ if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
+ reg->type = type;
+ if (type == UNKNOWN_VALUE)
+ mark_reg_unknown_value(regs, regno);
+ }
+}
+
+/* The logic is similar to find_good_pkt_pointers(), both could eventually
+ * be folded together at some point.
+ */
+static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
+ enum bpf_reg_type type)
+{
+ struct bpf_reg_state *regs = state->regs;
+ int i;
+
+ for (i = 0; i < MAX_BPF_REG; i++)
+ mark_map_reg(regs, i, regs[regno].id, type);
+
+ for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
+ if (state->stack_slot_type[i] != STACK_SPILL)
+ continue;
+ mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE,
+ regs[regno].id, type);
+ }
+}
+
static int check_cond_jmp_op(struct bpf_verifier_env *env,
struct bpf_insn *insn, int *insn_idx)
{
@@ -2018,18 +2082,13 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
if (BPF_SRC(insn->code) == BPF_K &&
insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
dst_reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
- if (opcode == BPF_JEQ) {
- /* next fallthrough insn can access memory via
- * this register
- */
- regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
- /* branch targer cannot access it, since reg == 0 */
- mark_reg_unknown_value(other_branch->regs,
- insn->dst_reg);
- } else {
- other_branch->regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
- mark_reg_unknown_value(regs, insn->dst_reg);
- }
+ /* Mark all identical map registers in each branch as either
+ * safe or unknown depending R == 0 or R != 0 conditional.
+ */
+ mark_map_regs(this_branch, insn->dst_reg,
+ opcode == BPF_JEQ ? PTR_TO_MAP_VALUE : UNKNOWN_VALUE);
+ mark_map_regs(other_branch, insn->dst_reg,
+ opcode == BPF_JEQ ? UNKNOWN_VALUE : PTR_TO_MAP_VALUE);
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
dst_reg->type == PTR_TO_PACKET &&
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
@@ -2469,7 +2528,7 @@ static bool states_equal(struct bpf_verifier_env *env,
* we didn't do a variable access into a map then we are a-ok.
*/
if (!varlen_map_access &&
- rold->type == rcur->type && rold->imm == rcur->imm)
+ memcmp(rold, rcur, offsetofend(struct bpf_reg_state, id)) == 0)
continue;
/* If we didn't map access then again we don't care about the
@@ -3074,9 +3133,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
struct bpf_verifier_env *env;
int ret = -EINVAL;
- if ((*prog)->len <= 0 || (*prog)->len > BPF_MAXINSNS)
- return -E2BIG;
-
/* 'struct bpf_verifier_env' can be global, but since it's not small,
* allocate/free it every time bpf_check() is called
*/
@@ -3117,6 +3173,8 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
log_level = 0;
}
+ bpf_prog_calc_digest(env->prog);
+
ret = replace_map_fd_with_map_ptr(env);
if (ret < 0)
goto skip_full_check;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 85bc9beb046d..2ee9ec3051b2 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5074,6 +5074,8 @@ static void css_release_work_fn(struct work_struct *work)
if (cgrp->kn)
RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv,
NULL);
+
+ cgroup_bpf_put(cgrp);
}
mutex_unlock(&cgroup_mutex);
@@ -5281,6 +5283,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
if (!cgroup_on_dfl(cgrp))
cgrp->subtree_control = cgroup_control(cgrp);
+ if (parent)
+ cgroup_bpf_inherit(cgrp, parent);
+
cgroup_propagate_control(cgrp);
/* @cgrp doesn't have dir yet so the following will only create csses */
@@ -6495,6 +6500,19 @@ static __init int cgroup_namespaces_init(void)
}
subsys_initcall(cgroup_namespaces_init);
+#ifdef CONFIG_CGROUP_BPF
+void cgroup_bpf_update(struct cgroup *cgrp,
+ struct bpf_prog *prog,
+ enum bpf_attach_type type)
+{
+ struct cgroup *parent = cgroup_parent(cgrp);
+
+ mutex_lock(&cgroup_mutex);
+ __cgroup_bpf_update(cgrp, parent, prog, type);
+ mutex_unlock(&cgroup_mutex);
+}
+#endif /* CONFIG_CGROUP_BPF */
+
#ifdef CONFIG_CGROUP_DEBUG
static struct cgroup_subsys_state *
debug_css_alloc(struct cgroup_subsys_state *parent_css)
diff --git a/kernel/compat.c b/kernel/compat.c
index 333d364be29d..b3a047f208a7 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -307,12 +307,17 @@ static inline long put_compat_itimerval(struct compat_itimerval __user *o,
__put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
}
+asmlinkage long sys_ni_posix_timers(void);
+
COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
struct compat_itimerval __user *, it)
{
struct itimerval kit;
int error;
+ if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+ return sys_ni_posix_timers();
+
error = do_getitimer(which, &kit);
if (!error && put_compat_itimerval(it, &kit))
error = -EFAULT;
@@ -326,6 +331,9 @@ COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
struct itimerval kin, kout;
int error;
+ if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+ return sys_ni_posix_timers();
+
if (in) {
if (get_compat_itimerval(&kin, in))
return -EFAULT;
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 29de1a9352c0..217fd2e7f435 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -659,7 +659,6 @@ void __init cpuhp_threads_init(void)
kthread_unpark(this_cpu_read(cpuhp_state.thread));
}
-#ifdef CONFIG_HOTPLUG_CPU
EXPORT_SYMBOL(register_cpu_notifier);
EXPORT_SYMBOL(__register_cpu_notifier);
void unregister_cpu_notifier(struct notifier_block *nb)
@@ -676,6 +675,7 @@ void __unregister_cpu_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL(__unregister_cpu_notifier);
+#ifdef CONFIG_HOTPLUG_CPU
/**
* clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
* @cpu: a CPU id
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index fc1ef736253c..98c9011eac78 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -697,7 +697,7 @@ kdb_printit:
* Write to all consoles.
*/
retlen = strlen(kdb_buffer);
- cp = (char *) printk_skip_level(kdb_buffer);
+ cp = (char *) printk_skip_headers(kdb_buffer);
if (!dbg_kdb_mode && kgdb_connected) {
gdbstub_msg_write(cp, retlen - (cp - kdb_buffer));
} else {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 02c8421f8c01..faf073d0287f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7723,7 +7723,7 @@ static void bpf_overflow_handler(struct perf_event *event,
if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1))
goto out;
rcu_read_lock();
- ret = BPF_PROG_RUN(event->prog, (void *)&ctx);
+ ret = BPF_PROG_RUN(event->prog, &ctx);
rcu_read_unlock();
out:
__this_cpu_dec(bpf_prog_active);
diff --git a/kernel/exit.c b/kernel/exit.c
index 3076f3089919..aacff8e2aec0 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -54,6 +54,7 @@
#include <linux/writeback.h>
#include <linux/shm.h>
#include <linux/kcov.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -91,11 +92,10 @@ static void __exit_signal(struct task_struct *tsk)
lockdep_tasklist_lock_is_held());
spin_lock(&sighand->siglock);
+#ifdef CONFIG_POSIX_TIMERS
posix_cpu_timers_exit(tsk);
if (group_dead) {
posix_cpu_timers_exit_group(tsk);
- tty = sig->tty;
- sig->tty = NULL;
} else {
/*
* This can only happen if the caller is de_thread().
@@ -104,7 +104,13 @@ static void __exit_signal(struct task_struct *tsk)
*/
if (unlikely(has_group_leader_pid(tsk)))
posix_cpu_timers_exit_group(tsk);
+ }
+#endif
+ if (group_dead) {
+ tty = sig->tty;
+ sig->tty = NULL;
+ } else {
/*
* If there is any task waiting for the group exit
* then notify it:
@@ -116,6 +122,9 @@ static void __exit_signal(struct task_struct *tsk)
sig->curr_target = next_thread(tsk);
}
+ add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
+ sizeof(unsigned long long));
+
/*
* Accumulate here the counters for all threads as they die. We could
* skip the group leader because it is the last user of signal_struct,
@@ -799,8 +808,10 @@ void __noreturn do_exit(long code)
acct_update_integrals(tsk);
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
+#ifdef CONFIG_POSIX_TIMERS
hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
+#endif
if (tsk->mm)
setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index 997ac1d584f7..a439ac429669 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -229,7 +229,7 @@ static inline void free_thread_stack(struct task_struct *tsk)
}
local_irq_restore(flags);
- vfree(tsk->stack);
+ vfree_atomic(tsk->stack);
return;
}
#endif
@@ -354,6 +354,8 @@ void free_task(struct task_struct *tsk)
ftrace_graph_exit_task(tsk);
put_seccomp_filter(tsk);
arch_release_task_struct(tsk);
+ if (tsk->flags & PF_KTHREAD)
+ free_kthread_struct(tsk);
free_task_struct(tsk);
}
EXPORT_SYMBOL(free_task);
@@ -1345,8 +1347,10 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
seqlock_init(&sig->stats_lock);
prev_cputime_init(&sig->prev_cputime);
+#ifdef CONFIG_POSIX_TIMERS
hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
sig->real_timer.function = it_real_fn;
+#endif
task_lock(current->group_leader);
memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
@@ -1540,7 +1544,7 @@ static __latent_entropy struct task_struct *copy_process(
goto bad_fork_cleanup_count;
delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
- p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER);
+ p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER | PF_IDLE);
p->flags |= PF_FORKNOEXEC;
INIT_LIST_HEAD(&p->children);
INIT_LIST_HEAD(&p->sibling);
@@ -1551,7 +1555,9 @@ static __latent_entropy struct task_struct *copy_process(
init_sigpending(&p->pending);
p->utime = p->stime = p->gtime = 0;
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
p->utimescaled = p->stimescaled = 0;
+#endif
prev_cputime_init(&p->prev_cputime);
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
diff --git a/kernel/futex.c b/kernel/futex.c
index 2c4be467fecd..9246d9f593d1 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1298,7 +1298,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this,
struct task_struct *new_owner;
struct futex_pi_state *pi_state = this->pi_state;
u32 uninitialized_var(curval), newval;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
bool deboost;
int ret = 0;
@@ -1415,7 +1415,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
struct futex_q *this, *next;
union futex_key key = FUTEX_KEY_INIT;
int ret;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
if (!bitset)
return -EINVAL;
@@ -1469,7 +1469,7 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
int ret, op_ret;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
retry:
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
@@ -1708,7 +1708,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
struct futex_pi_state *pi_state = NULL;
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
if (requeue_pi) {
/*
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 2b59c82cc3e1..40c07e4fa116 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -106,7 +106,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
* complain:
*/
if (sysctl_hung_task_warnings) {
- sysctl_hung_task_warnings--;
+ if (sysctl_hung_task_warnings > 0)
+ sysctl_hung_task_warnings--;
pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
t->comm, t->pid, timeout);
pr_err(" %s %s %.*s\n",
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index 17f51d63da56..9be9bda7c1f9 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -51,16 +51,17 @@ static int get_nodes_in_cpumask(const struct cpumask *mask, nodemask_t *nodemsk)
/**
* irq_create_affinity_masks - Create affinity masks for multiqueue spreading
- * @affinity: The affinity mask to spread. If NULL cpu_online_mask
- * is used
- * @nvecs: The number of vectors
+ * @nvecs: The total number of vectors
+ * @affd: Description of the affinity requirements
*
* Returns the masks pointer or NULL if allocation failed.
*/
-struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity,
- int nvec)
+struct cpumask *
+irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
{
- int n, nodes, vecs_per_node, cpus_per_vec, extra_vecs, curvec = 0;
+ int n, nodes, vecs_per_node, cpus_per_vec, extra_vecs, curvec;
+ int affv = nvecs - affd->pre_vectors - affd->post_vectors;
+ int last_affv = affv + affd->pre_vectors;
nodemask_t nodemsk = NODE_MASK_NONE;
struct cpumask *masks;
cpumask_var_t nmsk;
@@ -68,46 +69,47 @@ struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity,
if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
return NULL;
- masks = kzalloc(nvec * sizeof(*masks), GFP_KERNEL);
+ masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
if (!masks)
goto out;
+ /* Fill out vectors at the beginning that don't need affinity */
+ for (curvec = 0; curvec < affd->pre_vectors; curvec++)
+ cpumask_copy(masks + curvec, irq_default_affinity);
+
/* Stabilize the cpumasks */
get_online_cpus();
- /* If the supplied affinity mask is NULL, use cpu online mask */
- if (!affinity)
- affinity = cpu_online_mask;
-
- nodes = get_nodes_in_cpumask(affinity, &nodemsk);
+ nodes = get_nodes_in_cpumask(cpu_online_mask, &nodemsk);
/*
* If the number of nodes in the mask is less than or equal the
* number of vectors we just spread the vectors across the nodes.
*/
- if (nvec <= nodes) {
+ if (affv <= nodes) {
for_each_node_mask(n, nodemsk) {
cpumask_copy(masks + curvec, cpumask_of_node(n));
- if (++curvec == nvec)
+ if (++curvec == last_affv)
break;
}
- goto outonl;
+ goto done;
}
/* Spread the vectors per node */
- vecs_per_node = nvec / nodes;
+ vecs_per_node = affv / nodes;
/* Account for rounding errors */
- extra_vecs = nvec - (nodes * vecs_per_node);
+ extra_vecs = affv - (nodes * vecs_per_node);
for_each_node_mask(n, nodemsk) {
int ncpus, v, vecs_to_assign = vecs_per_node;
/* Get the cpus on this node which are in the mask */
- cpumask_and(nmsk, affinity, cpumask_of_node(n));
+ cpumask_and(nmsk, cpu_online_mask, cpumask_of_node(n));
/* Calculate the number of cpus per vector */
ncpus = cpumask_weight(nmsk);
- for (v = 0; curvec < nvec && v < vecs_to_assign; curvec++, v++) {
+ for (v = 0; curvec < last_affv && v < vecs_to_assign;
+ curvec++, v++) {
cpus_per_vec = ncpus / vecs_to_assign;
/* Account for extra vectors to compensate rounding errors */
@@ -119,36 +121,36 @@ struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity,
irq_spread_init_one(masks + curvec, nmsk, cpus_per_vec);
}
- if (curvec >= nvec)
+ if (curvec >= last_affv)
break;
}
-outonl:
+done:
put_online_cpus();
+
+ /* Fill out vectors at the end that don't need affinity */
+ for (; curvec < nvecs; curvec++)
+ cpumask_copy(masks + curvec, irq_default_affinity);
out:
free_cpumask_var(nmsk);
return masks;
}
/**
- * irq_calc_affinity_vectors - Calculate to optimal number of vectors for a given affinity mask
- * @affinity: The affinity mask to spread. If NULL cpu_online_mask
- * is used
- * @maxvec: The maximum number of vectors available
+ * irq_calc_affinity_vectors - Calculate the optimal number of vectors
+ * @maxvec: The maximum number of vectors available
+ * @affd: Description of the affinity requirements
*/
-int irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec)
+int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
{
- int cpus, ret;
+ int resv = affd->pre_vectors + affd->post_vectors;
+ int vecs = maxvec - resv;
+ int cpus;
/* Stabilize the cpumasks */
get_online_cpus();
- /* If the supplied affinity mask is NULL, use cpu online mask */
- if (!affinity)
- affinity = cpu_online_mask;
-
- cpus = cpumask_weight(affinity);
- ret = (cpus < maxvec) ? cpus : maxvec;
-
+ cpus = cpumask_weight(cpu_online_mask);
put_online_cpus();
- return ret;
+
+ return min(cpus, vecs) + resv;
}
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 8a3e872798f3..ee230063f033 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -14,9 +14,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/msi.h>
-
-/* Temparory solution for building, will be removed later */
-#include <linux/pci.h>
+#include <linux/slab.h>
/**
* alloc_msi_entry - Allocate an initialize msi_entry
diff --git a/kernel/kthread.c b/kernel/kthread.c
index be2cc1f9dd57..2318fba86277 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -53,20 +53,29 @@ enum KTHREAD_BITS {
KTHREAD_IS_PARKED,
};
-#define __to_kthread(vfork) \
- container_of(vfork, struct kthread, exited)
+static inline void set_kthread_struct(void *kthread)
+{
+ /*
+ * We abuse ->set_child_tid to avoid the new member and because it
+ * can't be wrongly copied by copy_process(). We also rely on fact
+ * that the caller can't exec, so PF_KTHREAD can't be cleared.
+ */
+ current->set_child_tid = (__force void __user *)kthread;
+}
static inline struct kthread *to_kthread(struct task_struct *k)
{
- return __to_kthread(k->vfork_done);
+ WARN_ON(!(k->flags & PF_KTHREAD));
+ return (__force void *)k->set_child_tid;
}
-static struct kthread *to_live_kthread(struct task_struct *k)
+void free_kthread_struct(struct task_struct *k)
{
- struct completion *vfork = ACCESS_ONCE(k->vfork_done);
- if (likely(vfork) && try_get_task_stack(k))
- return __to_kthread(vfork);
- return NULL;
+ /*
+ * Can be NULL if this kthread was created by kernel_thread()
+ * or if kmalloc() in kthread() failed.
+ */
+ kfree(to_kthread(k));
}
/**
@@ -181,14 +190,11 @@ static int kthread(void *_create)
int (*threadfn)(void *data) = create->threadfn;
void *data = create->data;
struct completion *done;
- struct kthread self;
+ struct kthread *self;
int ret;
- self.flags = 0;
- self.data = data;
- init_completion(&self.exited);
- init_completion(&self.parked);
- current->vfork_done = &self.exited;
+ self = kmalloc(sizeof(*self), GFP_KERNEL);
+ set_kthread_struct(self);
/* If user was SIGKILLed, I release the structure. */
done = xchg(&create->done, NULL);
@@ -196,6 +202,19 @@ static int kthread(void *_create)
kfree(create);
do_exit(-EINTR);
}
+
+ if (!self) {
+ create->result = ERR_PTR(-ENOMEM);
+ complete(done);
+ do_exit(-ENOMEM);
+ }
+
+ self->flags = 0;
+ self->data = data;
+ init_completion(&self->exited);
+ init_completion(&self->parked);
+ current->vfork_done = &self->exited;
+
/* OK, tell user we're spawned, wait for stop or wakeup */
__set_current_state(TASK_UNINTERRUPTIBLE);
create->result = current;
@@ -203,12 +222,10 @@ static int kthread(void *_create)
schedule();
ret = -EINTR;
-
- if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) {
- __kthread_parkme(&self);
+ if (!test_bit(KTHREAD_SHOULD_STOP, &self->flags)) {
+ __kthread_parkme(self);
ret = threadfn(data);
}
- /* we can't just return, we must preserve "self" on stack */
do_exit(ret);
}
@@ -244,7 +261,8 @@ static void create_kthread(struct kthread_create_info *create)
}
}
-static struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
+static __printf(4, 0)
+struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
void *data, int node,
const char namefmt[],
va_list args)
@@ -409,8 +427,18 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
return p;
}
-static void __kthread_unpark(struct task_struct *k, struct kthread *kthread)
+/**
+ * kthread_unpark - unpark a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ *
+ * Sets kthread_should_park() for @k to return false, wakes it, and
+ * waits for it to return. If the thread is marked percpu then its
+ * bound to the cpu again.
+ */
+void kthread_unpark(struct task_struct *k)
{
+ struct kthread *kthread = to_kthread(k);
+
clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
/*
* We clear the IS_PARKED bit here as we don't wait
@@ -428,24 +456,6 @@ static void __kthread_unpark(struct task_struct *k, struct kthread *kthread)
wake_up_state(k, TASK_PARKED);
}
}
-
-/**
- * kthread_unpark - unpark a thread created by kthread_create().
- * @k: thread created by kthread_create().
- *
- * Sets kthread_should_park() for @k to return false, wakes it, and
- * waits for it to return. If the thread is marked percpu then its
- * bound to the cpu again.
- */
-void kthread_unpark(struct task_struct *k)
-{
- struct kthread *kthread = to_live_kthread(k);
-
- if (kthread) {
- __kthread_unpark(k, kthread);
- put_task_stack(k);
- }
-}
EXPORT_SYMBOL_GPL(kthread_unpark);
/**
@@ -462,21 +472,20 @@ EXPORT_SYMBOL_GPL(kthread_unpark);
*/
int kthread_park(struct task_struct *k)
{
- struct kthread *kthread = to_live_kthread(k);
- int ret = -ENOSYS;
-
- if (kthread) {
- if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
- set_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
- if (k != current) {
- wake_up_process(k);
- wait_for_completion(&kthread->parked);
- }
+ struct kthread *kthread = to_kthread(k);
+
+ if (WARN_ON(k->flags & PF_EXITING))
+ return -ENOSYS;
+
+ if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
+ set_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+ if (k != current) {
+ wake_up_process(k);
+ wait_for_completion(&kthread->parked);
}
- put_task_stack(k);
- ret = 0;
}
- return ret;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(kthread_park);
@@ -503,14 +512,11 @@ int kthread_stop(struct task_struct *k)
trace_sched_kthread_stop(k);
get_task_struct(k);
- kthread = to_live_kthread(k);
- if (kthread) {
- set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
- __kthread_unpark(k, kthread);
- wake_up_process(k);
- wait_for_completion(&kthread->exited);
- put_task_stack(k);
- }
+ kthread = to_kthread(k);
+ set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
+ kthread_unpark(k);
+ wake_up_process(k);
+ wait_for_completion(&kthread->exited);
ret = k->exit_code;
put_task_struct(k);
@@ -630,12 +636,13 @@ repeat:
}
EXPORT_SYMBOL_GPL(kthread_worker_fn);
-static struct kthread_worker *
+static __printf(3, 0) struct kthread_worker *
__kthread_create_worker(int cpu, unsigned int flags,
const char namefmt[], va_list args)
{
struct kthread_worker *worker;
struct task_struct *task;
+ int node = -1;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (!worker)
@@ -643,25 +650,17 @@ __kthread_create_worker(int cpu, unsigned int flags,
kthread_init_worker(worker);
- if (cpu >= 0) {
- char name[TASK_COMM_LEN];
-
- /*
- * kthread_create_worker_on_cpu() allows to pass a generic
- * namefmt in compare with kthread_create_on_cpu. We need
- * to format it here.
- */
- vsnprintf(name, sizeof(name), namefmt, args);
- task = kthread_create_on_cpu(kthread_worker_fn, worker,
- cpu, name);
- } else {
- task = __kthread_create_on_node(kthread_worker_fn, worker,
- -1, namefmt, args);
- }
+ if (cpu >= 0)
+ node = cpu_to_node(cpu);
+ task = __kthread_create_on_node(kthread_worker_fn, worker,
+ node, namefmt, args);
if (IS_ERR(task))
goto fail_task;
+ if (cpu >= 0)
+ kthread_bind(task, cpu);
+
worker->flags = flags;
worker->task = task;
wake_up_process(task);
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 4d7ffc0a0d00..7bd265f6b098 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -840,9 +840,9 @@ static struct lock_list *alloc_list_entry(void)
/*
* Add a new dependency to the head of the list:
*/
-static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
- struct list_head *head, unsigned long ip,
- int distance, struct stack_trace *trace)
+static int add_lock_to_list(struct lock_class *this, struct list_head *head,
+ unsigned long ip, int distance,
+ struct stack_trace *trace)
{
struct lock_list *entry;
/*
@@ -1868,14 +1868,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
* Ok, all validations passed, add the new lock
* to the previous lock's dependency list:
*/
- ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
+ ret = add_lock_to_list(hlock_class(next),
&hlock_class(prev)->locks_after,
next->acquire_ip, distance, &trace);
if (!ret)
return 0;
- ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
+ ret = add_lock_to_list(hlock_class(prev),
&hlock_class(next)->locks_before,
next->acquire_ip, distance, &trace);
if (!ret)
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
index c835270f0c2f..6a385aabcce7 100644
--- a/kernel/locking/mcs_spinlock.h
+++ b/kernel/locking/mcs_spinlock.h
@@ -28,7 +28,7 @@ struct mcs_spinlock {
#define arch_mcs_spin_lock_contended(l) \
do { \
while (!(smp_load_acquire(l))) \
- cpu_relax_lowlatency(); \
+ cpu_relax(); \
} while (0)
#endif
@@ -108,7 +108,7 @@ void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
return;
/* Wait until the next pointer is set */
while (!(next = READ_ONCE(node->next)))
- cpu_relax_lowlatency();
+ cpu_relax();
}
/* Pass lock to next waiter. */
diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c
index 9c951fade415..9aa713629387 100644
--- a/kernel/locking/mutex-debug.c
+++ b/kernel/locking/mutex-debug.c
@@ -73,21 +73,8 @@ void debug_mutex_unlock(struct mutex *lock)
{
if (likely(debug_locks)) {
DEBUG_LOCKS_WARN_ON(lock->magic != lock);
-
- if (!lock->owner)
- DEBUG_LOCKS_WARN_ON(!lock->owner);
- else
- DEBUG_LOCKS_WARN_ON(lock->owner != current);
-
DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
}
-
- /*
- * __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug
- * mutexes so that we can do it here after we've verified state.
- */
- mutex_clear_owner(lock);
- atomic_set(&lock->count, 1);
}
void debug_mutex_init(struct mutex *lock, const char *name,
diff --git a/kernel/locking/mutex-debug.h b/kernel/locking/mutex-debug.h
index 57a871ae3c81..a459faa48987 100644
--- a/kernel/locking/mutex-debug.h
+++ b/kernel/locking/mutex-debug.h
@@ -27,16 +27,6 @@ extern void debug_mutex_unlock(struct mutex *lock);
extern void debug_mutex_init(struct mutex *lock, const char *name,
struct lock_class_key *key);
-static inline void mutex_set_owner(struct mutex *lock)
-{
- WRITE_ONCE(lock->owner, current);
-}
-
-static inline void mutex_clear_owner(struct mutex *lock)
-{
- WRITE_ONCE(lock->owner, NULL);
-}
-
#define spin_lock_mutex(lock, flags) \
do { \
struct mutex *l = container_of(lock, struct mutex, wait_lock); \
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index a70b90db3909..9b349619f431 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -27,41 +27,176 @@
#include <linux/debug_locks.h>
#include <linux/osq_lock.h>
-/*
- * In the DEBUG case we are using the "NULL fastpath" for mutexes,
- * which forces all calls into the slowpath:
- */
#ifdef CONFIG_DEBUG_MUTEXES
# include "mutex-debug.h"
-# include <asm-generic/mutex-null.h>
-/*
- * Must be 0 for the debug case so we do not do the unlock outside of the
- * wait_lock region. debug_mutex_unlock() will do the actual unlock in this
- * case.
- */
-# undef __mutex_slowpath_needs_to_unlock
-# define __mutex_slowpath_needs_to_unlock() 0
#else
# include "mutex.h"
-# include <asm/mutex.h>
#endif
void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
- atomic_set(&lock->count, 1);
+ atomic_long_set(&lock->owner, 0);
spin_lock_init(&lock->wait_lock);
INIT_LIST_HEAD(&lock->wait_list);
- mutex_clear_owner(lock);
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
osq_lock_init(&lock->osq);
#endif
debug_mutex_init(lock, name, key);
}
-
EXPORT_SYMBOL(__mutex_init);
+/*
+ * @owner: contains: 'struct task_struct *' to the current lock owner,
+ * NULL means not owned. Since task_struct pointers are aligned at
+ * ARCH_MIN_TASKALIGN (which is at least sizeof(void *)), we have low
+ * bits to store extra state.
+ *
+ * Bit0 indicates a non-empty waiter list; unlock must issue a wakeup.
+ * Bit1 indicates unlock needs to hand the lock to the top-waiter
+ */
+#define MUTEX_FLAG_WAITERS 0x01
+#define MUTEX_FLAG_HANDOFF 0x02
+
+#define MUTEX_FLAGS 0x03
+
+static inline struct task_struct *__owner_task(unsigned long owner)
+{
+ return (struct task_struct *)(owner & ~MUTEX_FLAGS);
+}
+
+static inline unsigned long __owner_flags(unsigned long owner)
+{
+ return owner & MUTEX_FLAGS;
+}
+
+/*
+ * Actual trylock that will work on any unlocked state.
+ *
+ * When setting the owner field, we must preserve the low flag bits.
+ *
+ * Be careful with @handoff, only set that in a wait-loop (where you set
+ * HANDOFF) to avoid recursive lock attempts.
+ */
+static inline bool __mutex_trylock(struct mutex *lock, const bool handoff)
+{
+ unsigned long owner, curr = (unsigned long)current;
+
+ owner = atomic_long_read(&lock->owner);
+ for (;;) { /* must loop, can race against a flag */
+ unsigned long old, flags = __owner_flags(owner);
+
+ if (__owner_task(owner)) {
+ if (handoff && unlikely(__owner_task(owner) == current)) {
+ /*
+ * Provide ACQUIRE semantics for the lock-handoff.
+ *
+ * We cannot easily use load-acquire here, since
+ * the actual load is a failed cmpxchg, which
+ * doesn't imply any barriers.
+ *
+ * Also, this is a fairly unlikely scenario, and
+ * this contains the cost.
+ */
+ smp_mb(); /* ACQUIRE */
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ * We set the HANDOFF bit, we must make sure it doesn't live
+ * past the point where we acquire it. This would be possible
+ * if we (accidentally) set the bit on an unlocked mutex.
+ */
+ if (handoff)
+ flags &= ~MUTEX_FLAG_HANDOFF;
+
+ old = atomic_long_cmpxchg_acquire(&lock->owner, owner, curr | flags);
+ if (old == owner)
+ return true;
+
+ owner = old;
+ }
+}
+
+#ifndef CONFIG_DEBUG_LOCK_ALLOC
+/*
+ * Lockdep annotations are contained to the slow paths for simplicity.
+ * There is nothing that would stop spreading the lockdep annotations outwards
+ * except more code.
+ */
+
+/*
+ * Optimistic trylock that only works in the uncontended case. Make sure to
+ * follow with a __mutex_trylock() before failing.
+ */
+static __always_inline bool __mutex_trylock_fast(struct mutex *lock)
+{
+ unsigned long curr = (unsigned long)current;
+
+ if (!atomic_long_cmpxchg_acquire(&lock->owner, 0UL, curr))
+ return true;
+
+ return false;
+}
+
+static __always_inline bool __mutex_unlock_fast(struct mutex *lock)
+{
+ unsigned long curr = (unsigned long)current;
+
+ if (atomic_long_cmpxchg_release(&lock->owner, curr, 0UL) == curr)
+ return true;
+
+ return false;
+}
+#endif
+
+static inline void __mutex_set_flag(struct mutex *lock, unsigned long flag)
+{
+ atomic_long_or(flag, &lock->owner);
+}
+
+static inline void __mutex_clear_flag(struct mutex *lock, unsigned long flag)
+{
+ atomic_long_andnot(flag, &lock->owner);
+}
+
+static inline bool __mutex_waiter_is_first(struct mutex *lock, struct mutex_waiter *waiter)
+{
+ return list_first_entry(&lock->wait_list, struct mutex_waiter, list) == waiter;
+}
+
+/*
+ * Give up ownership to a specific task, when @task = NULL, this is equivalent
+ * to a regular unlock. Clears HANDOFF, preserves WAITERS. Provides RELEASE
+ * semantics like a regular unlock, the __mutex_trylock() provides matching
+ * ACQUIRE semantics for the handoff.
+ */
+static void __mutex_handoff(struct mutex *lock, struct task_struct *task)
+{
+ unsigned long owner = atomic_long_read(&lock->owner);
+
+ for (;;) {
+ unsigned long old, new;
+
+#ifdef CONFIG_DEBUG_MUTEXES
+ DEBUG_LOCKS_WARN_ON(__owner_task(owner) != current);
+#endif
+
+ new = (owner & MUTEX_FLAG_WAITERS);
+ new |= (unsigned long)task;
+
+ old = atomic_long_cmpxchg_release(&lock->owner, owner, new);
+ if (old == owner)
+ break;
+
+ owner = old;
+ }
+}
+
#ifndef CONFIG_DEBUG_LOCK_ALLOC
/*
* We split the mutex lock/unlock logic into separate fastpath and
@@ -69,7 +204,7 @@ EXPORT_SYMBOL(__mutex_init);
* We also put the fastpath first in the kernel image, to make sure the
* branch is predicted by the CPU as default-untaken.
*/
-__visible void __sched __mutex_lock_slowpath(atomic_t *lock_count);
+static void __sched __mutex_lock_slowpath(struct mutex *lock);
/**
* mutex_lock - acquire the mutex
@@ -95,14 +230,10 @@ __visible void __sched __mutex_lock_slowpath(atomic_t *lock_count);
void __sched mutex_lock(struct mutex *lock)
{
might_sleep();
- /*
- * The locking fastpath is the 1->0 transition from
- * 'unlocked' into 'locked' state.
- */
- __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
- mutex_set_owner(lock);
-}
+ if (!__mutex_trylock_fast(lock))
+ __mutex_lock_slowpath(lock);
+}
EXPORT_SYMBOL(mutex_lock);
#endif
@@ -149,9 +280,6 @@ static __always_inline void ww_mutex_lock_acquired(struct ww_mutex *ww,
/*
* After acquiring lock with fastpath or when we lost out in contested
* slowpath, set ctx and wake up any waiters so they can recheck.
- *
- * This function is never called when CONFIG_DEBUG_LOCK_ALLOC is set,
- * as the fastpath and opportunistic spinning are disabled in that case.
*/
static __always_inline void
ww_mutex_set_context_fastpath(struct ww_mutex *lock,
@@ -176,7 +304,7 @@ ww_mutex_set_context_fastpath(struct ww_mutex *lock,
/*
* Check if lock is contended, if not there is nobody to wake up
*/
- if (likely(atomic_read(&lock->base.count) == 0))
+ if (likely(!(atomic_long_read(&lock->base.owner) & MUTEX_FLAG_WAITERS)))
return;
/*
@@ -227,7 +355,7 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
bool ret = true;
rcu_read_lock();
- while (lock->owner == owner) {
+ while (__mutex_owner(lock) == owner) {
/*
* Ensure we emit the owner->on_cpu, dereference _after_
* checking lock->owner still matches owner. If that fails,
@@ -236,12 +364,16 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
*/
barrier();
- if (!owner->on_cpu || need_resched()) {
+ /*
+ * Use vcpu_is_preempted to detect lock holder preemption issue.
+ */
+ if (!owner->on_cpu || need_resched() ||
+ vcpu_is_preempted(task_cpu(owner))) {
ret = false;
break;
}
- cpu_relax_lowlatency();
+ cpu_relax();
}
rcu_read_unlock();
@@ -260,27 +392,25 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
return 0;
rcu_read_lock();
- owner = READ_ONCE(lock->owner);
+ owner = __mutex_owner(lock);
+
+ /*
+ * As lock holder preemption issue, we both skip spinning if task is not
+ * on cpu or its cpu is preempted
+ */
if (owner)
- retval = owner->on_cpu;
+ retval = owner->on_cpu && !vcpu_is_preempted(task_cpu(owner));
rcu_read_unlock();
+
/*
- * if lock->owner is not set, the mutex owner may have just acquired
- * it and not set the owner yet or the mutex has been released.
+ * If lock->owner is not set, the mutex has been released. Return true
+ * such that we'll trylock in the spin path, which is a faster option
+ * than the blocking slow path.
*/
return retval;
}
/*
- * Atomically try to take the lock when it is available
- */
-static inline bool mutex_try_to_acquire(struct mutex *lock)
-{
- return !mutex_is_locked(lock) &&
- (atomic_cmpxchg_acquire(&lock->count, 1, 0) == 1);
-}
-
-/*
* Optimistic spinning.
*
* We try to spin for acquisition when we find that the lock owner
@@ -288,13 +418,6 @@ static inline bool mutex_try_to_acquire(struct mutex *lock)
* need to reschedule. The rationale is that if the lock owner is
* running, it is likely to release the lock soon.
*
- * Since this needs the lock owner, and this mutex implementation
- * doesn't track the owner atomically in the lock field, we need to
- * track it non-atomically.
- *
- * We can't do this for DEBUG_MUTEXES because that relies on wait_lock
- * to serialize everything.
- *
* The mutex spinners are queued up using MCS lock so that only one
* spinner can compete for the mutex. However, if mutex spinning isn't
* going to happen, there is no point in going through the lock/unlock
@@ -302,24 +425,39 @@ static inline bool mutex_try_to_acquire(struct mutex *lock)
*
* Returns true when the lock was taken, otherwise false, indicating
* that we need to jump to the slowpath and sleep.
+ *
+ * The waiter flag is set to true if the spinner is a waiter in the wait
+ * queue. The waiter-spinner will spin on the lock directly and concurrently
+ * with the spinner at the head of the OSQ, if present, until the owner is
+ * changed to itself.
*/
static bool mutex_optimistic_spin(struct mutex *lock,
- struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
+ struct ww_acquire_ctx *ww_ctx,
+ const bool use_ww_ctx, const bool waiter)
{
struct task_struct *task = current;
- if (!mutex_can_spin_on_owner(lock))
- goto done;
+ if (!waiter) {
+ /*
+ * The purpose of the mutex_can_spin_on_owner() function is
+ * to eliminate the overhead of osq_lock() and osq_unlock()
+ * in case spinning isn't possible. As a waiter-spinner
+ * is not going to take OSQ lock anyway, there is no need
+ * to call mutex_can_spin_on_owner().
+ */
+ if (!mutex_can_spin_on_owner(lock))
+ goto fail;
- /*
- * In order to avoid a stampede of mutex spinners trying to
- * acquire the mutex all at once, the spinners need to take a
- * MCS (queued) lock first before spinning on the owner field.
- */
- if (!osq_lock(&lock->osq))
- goto done;
+ /*
+ * In order to avoid a stampede of mutex spinners trying to
+ * acquire the mutex all at once, the spinners need to take a
+ * MCS (queued) lock first before spinning on the owner field.
+ */
+ if (!osq_lock(&lock->osq))
+ goto fail;
+ }
- while (true) {
+ for (;;) {
struct task_struct *owner;
if (use_ww_ctx && ww_ctx->acquired > 0) {
@@ -335,40 +473,26 @@ static bool mutex_optimistic_spin(struct mutex *lock,
* performed the optimistic spinning cannot be done.
*/
if (READ_ONCE(ww->ctx))
- break;
+ goto fail_unlock;
}
/*
* If there's an owner, wait for it to either
* release the lock or go to sleep.
*/
- owner = READ_ONCE(lock->owner);
- if (owner && !mutex_spin_on_owner(lock, owner))
- break;
-
- /* Try to acquire the mutex if it is unlocked. */
- if (mutex_try_to_acquire(lock)) {
- lock_acquired(&lock->dep_map, ip);
-
- if (use_ww_ctx) {
- struct ww_mutex *ww;
- ww = container_of(lock, struct ww_mutex, base);
-
- ww_mutex_set_context_fastpath(ww, ww_ctx);
+ owner = __mutex_owner(lock);
+ if (owner) {
+ if (waiter && owner == task) {
+ smp_mb(); /* ACQUIRE */
+ break;
}
- mutex_set_owner(lock);
- osq_unlock(&lock->osq);
- return true;
+ if (!mutex_spin_on_owner(lock, owner))
+ goto fail_unlock;
}
- /*
- * When there's no owner, we might have preempted between the
- * owner acquiring the lock and setting the owner field. If
- * we're an RT task that will live-lock because we won't let
- * the owner complete.
- */
- if (!owner && (need_resched() || rt_task(task)))
+ /* Try to acquire the mutex if it is unlocked. */
+ if (__mutex_trylock(lock, waiter))
break;
/*
@@ -377,11 +501,20 @@ static bool mutex_optimistic_spin(struct mutex *lock,
* memory barriers as we'll eventually observe the right
* values at the cost of a few extra spins.
*/
- cpu_relax_lowlatency();
+ cpu_relax();
}
- osq_unlock(&lock->osq);
-done:
+ if (!waiter)
+ osq_unlock(&lock->osq);
+
+ return true;
+
+
+fail_unlock:
+ if (!waiter)
+ osq_unlock(&lock->osq);
+
+fail:
/*
* If we fell out of the spin path because of need_resched(),
* reschedule now, before we try-lock the mutex. This avoids getting
@@ -400,14 +533,14 @@ done:
}
#else
static bool mutex_optimistic_spin(struct mutex *lock,
- struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
+ struct ww_acquire_ctx *ww_ctx,
+ const bool use_ww_ctx, const bool waiter)
{
return false;
}
#endif
-__visible __used noinline
-void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
+static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigned long ip);
/**
* mutex_unlock - release the mutex
@@ -422,21 +555,12 @@ void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
*/
void __sched mutex_unlock(struct mutex *lock)
{
- /*
- * The unlocking fastpath is the 0->1 transition from 'locked'
- * into 'unlocked' state:
- */
-#ifndef CONFIG_DEBUG_MUTEXES
- /*
- * When debugging is enabled we must not clear the owner before time,
- * the slow path will always be taken, and that clears the owner field
- * after verifying that it was indeed current.
- */
- mutex_clear_owner(lock);
+#ifndef CONFIG_DEBUG_LOCK_ALLOC
+ if (__mutex_unlock_fast(lock))
+ return;
#endif
- __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
+ __mutex_unlock_slowpath(lock, _RET_IP_);
}
-
EXPORT_SYMBOL(mutex_unlock);
/**
@@ -465,15 +589,7 @@ void __sched ww_mutex_unlock(struct ww_mutex *lock)
lock->ctx = NULL;
}
-#ifndef CONFIG_DEBUG_MUTEXES
- /*
- * When debugging is enabled we must not clear the owner before time,
- * the slow path will always be taken, and that clears the owner field
- * after verifying that it was indeed current.
- */
- mutex_clear_owner(&lock->base);
-#endif
- __mutex_fastpath_unlock(&lock->base.count, __mutex_unlock_slowpath);
+ mutex_unlock(&lock->base);
}
EXPORT_SYMBOL(ww_mutex_unlock);
@@ -509,10 +625,12 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
struct task_struct *task = current;
struct mutex_waiter waiter;
unsigned long flags;
+ bool first = false;
+ struct ww_mutex *ww;
int ret;
if (use_ww_ctx) {
- struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
+ ww = container_of(lock, struct ww_mutex, base);
if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
return -EALREADY;
}
@@ -520,20 +638,21 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
preempt_disable();
mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);
- if (mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx)) {
+ if (__mutex_trylock(lock, false) ||
+ mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, false)) {
/* got the lock, yay! */
+ lock_acquired(&lock->dep_map, ip);
+ if (use_ww_ctx)
+ ww_mutex_set_context_fastpath(ww, ww_ctx);
preempt_enable();
return 0;
}
spin_lock_mutex(&lock->wait_lock, flags);
-
/*
- * Once more, try to acquire the lock. Only try-lock the mutex if
- * it is unlocked to reduce unnecessary xchg() operations.
+ * After waiting to acquire the wait_lock, try again.
*/
- if (!mutex_is_locked(lock) &&
- (atomic_xchg_acquire(&lock->count, 0) == 1))
+ if (__mutex_trylock(lock, false))
goto skip_wait;
debug_mutex_lock_common(lock, &waiter);
@@ -543,26 +662,26 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
list_add_tail(&waiter.list, &lock->wait_list);
waiter.task = task;
+ if (__mutex_waiter_is_first(lock, &waiter))
+ __mutex_set_flag(lock, MUTEX_FLAG_WAITERS);
+
lock_contended(&lock->dep_map, ip);
+ set_task_state(task, state);
for (;;) {
/*
- * Lets try to take the lock again - this is needed even if
- * we get here for the first time (shortly after failing to
- * acquire the lock), to make sure that we get a wakeup once
- * it's unlocked. Later on, if we sleep, this is the
- * operation that gives us the lock. We xchg it to -1, so
- * that when we release the lock, we properly wake up the
- * other waiters. We only attempt the xchg if the count is
- * non-negative in order to avoid unnecessary xchg operations:
+ * Once we hold wait_lock, we're serialized against
+ * mutex_unlock() handing the lock off to us, do a trylock
+ * before testing the error conditions to make sure we pick up
+ * the handoff.
*/
- if (atomic_read(&lock->count) >= 0 &&
- (atomic_xchg_acquire(&lock->count, -1) == 1))
- break;
+ if (__mutex_trylock(lock, first))
+ goto acquired;
/*
- * got a signal? (This code gets eliminated in the
- * TASK_UNINTERRUPTIBLE case.)
+ * Check for signals and wound conditions while holding
+ * wait_lock. This ensures the lock cancellation is ordered
+ * against mutex_unlock() and wake-ups do not go missing.
*/
if (unlikely(signal_pending_state(state, task))) {
ret = -EINTR;
@@ -575,36 +694,49 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
goto err;
}
- __set_task_state(task, state);
-
- /* didn't get the lock, go to sleep: */
spin_unlock_mutex(&lock->wait_lock, flags);
schedule_preempt_disabled();
+
+ if (!first && __mutex_waiter_is_first(lock, &waiter)) {
+ first = true;
+ __mutex_set_flag(lock, MUTEX_FLAG_HANDOFF);
+ }
+
+ set_task_state(task, state);
+ /*
+ * Here we order against unlock; we must either see it change
+ * state back to RUNNING and fall through the next schedule(),
+ * or we must see its unlock and acquire.
+ */
+ if ((first && mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, true)) ||
+ __mutex_trylock(lock, first))
+ break;
+
spin_lock_mutex(&lock->wait_lock, flags);
}
+ spin_lock_mutex(&lock->wait_lock, flags);
+acquired:
__set_task_state(task, TASK_RUNNING);
mutex_remove_waiter(lock, &waiter, task);
- /* set it to 0 if there are no waiters left: */
if (likely(list_empty(&lock->wait_list)))
- atomic_set(&lock->count, 0);
+ __mutex_clear_flag(lock, MUTEX_FLAGS);
+
debug_mutex_free_waiter(&waiter);
skip_wait:
/* got the lock - cleanup and rejoice! */
lock_acquired(&lock->dep_map, ip);
- mutex_set_owner(lock);
- if (use_ww_ctx) {
- struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
+ if (use_ww_ctx)
ww_mutex_set_context_slowpath(ww, ww_ctx);
- }
spin_unlock_mutex(&lock->wait_lock, flags);
preempt_enable();
return 0;
err:
+ __set_task_state(task, TASK_RUNNING);
mutex_remove_waiter(lock, &waiter, task);
spin_unlock_mutex(&lock->wait_lock, flags);
debug_mutex_free_waiter(&waiter);
@@ -631,7 +763,6 @@ _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest)
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
0, nest, _RET_IP_, NULL, 0);
}
-
EXPORT_SYMBOL_GPL(_mutex_lock_nest_lock);
int __sched
@@ -650,7 +781,6 @@ mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
subclass, NULL, _RET_IP_, NULL, 0);
}
-
EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
static inline int
@@ -715,54 +845,64 @@ EXPORT_SYMBOL_GPL(__ww_mutex_lock_interruptible);
/*
* Release the lock, slowpath:
*/
-static inline void
-__mutex_unlock_common_slowpath(struct mutex *lock, int nested)
+static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigned long ip)
{
- unsigned long flags;
- WAKE_Q(wake_q);
+ struct task_struct *next = NULL;
+ unsigned long owner, flags;
+ DEFINE_WAKE_Q(wake_q);
+
+ mutex_release(&lock->dep_map, 1, ip);
/*
- * As a performance measurement, release the lock before doing other
- * wakeup related duties to follow. This allows other tasks to acquire
- * the lock sooner, while still handling cleanups in past unlock calls.
- * This can be done as we do not enforce strict equivalence between the
- * mutex counter and wait_list.
- *
+ * Release the lock before (potentially) taking the spinlock such that
+ * other contenders can get on with things ASAP.
*
- * Some architectures leave the lock unlocked in the fastpath failure
- * case, others need to leave it locked. In the later case we have to
- * unlock it here - as the lock counter is currently 0 or negative.
+ * Except when HANDOFF, in that case we must not clear the owner field,
+ * but instead set it to the top waiter.
*/
- if (__mutex_slowpath_needs_to_unlock())
- atomic_set(&lock->count, 1);
+ owner = atomic_long_read(&lock->owner);
+ for (;;) {
+ unsigned long old;
+
+#ifdef CONFIG_DEBUG_MUTEXES
+ DEBUG_LOCKS_WARN_ON(__owner_task(owner) != current);
+#endif
+
+ if (owner & MUTEX_FLAG_HANDOFF)
+ break;
+
+ old = atomic_long_cmpxchg_release(&lock->owner, owner,
+ __owner_flags(owner));
+ if (old == owner) {
+ if (owner & MUTEX_FLAG_WAITERS)
+ break;
+
+ return;
+ }
+
+ owner = old;
+ }
spin_lock_mutex(&lock->wait_lock, flags);
- mutex_release(&lock->dep_map, nested, _RET_IP_);
debug_mutex_unlock(lock);
-
if (!list_empty(&lock->wait_list)) {
/* get the first entry from the wait-list: */
struct mutex_waiter *waiter =
- list_entry(lock->wait_list.next,
- struct mutex_waiter, list);
+ list_first_entry(&lock->wait_list,
+ struct mutex_waiter, list);
+
+ next = waiter->task;
debug_mutex_wake_waiter(lock, waiter);
- wake_q_add(&wake_q, waiter->task);
+ wake_q_add(&wake_q, next);
}
- spin_unlock_mutex(&lock->wait_lock, flags);
- wake_up_q(&wake_q);
-}
+ if (owner & MUTEX_FLAG_HANDOFF)
+ __mutex_handoff(lock, next);
-/*
- * Release the lock, slowpath:
- */
-__visible void
-__mutex_unlock_slowpath(atomic_t *lock_count)
-{
- struct mutex *lock = container_of(lock_count, struct mutex, count);
+ spin_unlock_mutex(&lock->wait_lock, flags);
- __mutex_unlock_common_slowpath(lock, 1);
+ wake_up_q(&wake_q);
}
#ifndef CONFIG_DEBUG_LOCK_ALLOC
@@ -789,38 +929,30 @@ __mutex_lock_interruptible_slowpath(struct mutex *lock);
*/
int __sched mutex_lock_interruptible(struct mutex *lock)
{
- int ret;
-
might_sleep();
- ret = __mutex_fastpath_lock_retval(&lock->count);
- if (likely(!ret)) {
- mutex_set_owner(lock);
+
+ if (__mutex_trylock_fast(lock))
return 0;
- } else
- return __mutex_lock_interruptible_slowpath(lock);
+
+ return __mutex_lock_interruptible_slowpath(lock);
}
EXPORT_SYMBOL(mutex_lock_interruptible);
int __sched mutex_lock_killable(struct mutex *lock)
{
- int ret;
-
might_sleep();
- ret = __mutex_fastpath_lock_retval(&lock->count);
- if (likely(!ret)) {
- mutex_set_owner(lock);
+
+ if (__mutex_trylock_fast(lock))
return 0;
- } else
- return __mutex_lock_killable_slowpath(lock);
+
+ return __mutex_lock_killable_slowpath(lock);
}
EXPORT_SYMBOL(mutex_lock_killable);
-__visible void __sched
-__mutex_lock_slowpath(atomic_t *lock_count)
+static noinline void __sched
+__mutex_lock_slowpath(struct mutex *lock)
{
- struct mutex *lock = container_of(lock_count, struct mutex, count);
-
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0,
NULL, _RET_IP_, NULL, 0);
}
@@ -856,37 +988,6 @@ __ww_mutex_lock_interruptible_slowpath(struct ww_mutex *lock,
#endif
-/*
- * Spinlock based trylock, we take the spinlock and check whether we
- * can get the lock:
- */
-static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
-{
- struct mutex *lock = container_of(lock_count, struct mutex, count);
- unsigned long flags;
- int prev;
-
- /* No need to trylock if the mutex is locked. */
- if (mutex_is_locked(lock))
- return 0;
-
- spin_lock_mutex(&lock->wait_lock, flags);
-
- prev = atomic_xchg_acquire(&lock->count, -1);
- if (likely(prev == 1)) {
- mutex_set_owner(lock);
- mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
- }
-
- /* Set it back to 0 if there are no waiters: */
- if (likely(list_empty(&lock->wait_list)))
- atomic_set(&lock->count, 0);
-
- spin_unlock_mutex(&lock->wait_lock, flags);
-
- return prev == 1;
-}
-
/**
* mutex_trylock - try to acquire the mutex, without waiting
* @lock: the mutex to be acquired
@@ -903,13 +1004,12 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
*/
int __sched mutex_trylock(struct mutex *lock)
{
- int ret;
+ bool locked = __mutex_trylock(lock, false);
- ret = __mutex_fastpath_trylock(&lock->count, __mutex_trylock_slowpath);
- if (ret)
- mutex_set_owner(lock);
+ if (locked)
+ mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
- return ret;
+ return locked;
}
EXPORT_SYMBOL(mutex_trylock);
@@ -917,36 +1017,28 @@ EXPORT_SYMBOL(mutex_trylock);
int __sched
__ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
{
- int ret;
-
might_sleep();
- ret = __mutex_fastpath_lock_retval(&lock->base.count);
-
- if (likely(!ret)) {
+ if (__mutex_trylock_fast(&lock->base)) {
ww_mutex_set_context_fastpath(lock, ctx);
- mutex_set_owner(&lock->base);
- } else
- ret = __ww_mutex_lock_slowpath(lock, ctx);
- return ret;
+ return 0;
+ }
+
+ return __ww_mutex_lock_slowpath(lock, ctx);
}
EXPORT_SYMBOL(__ww_mutex_lock);
int __sched
__ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
{
- int ret;
-
might_sleep();
- ret = __mutex_fastpath_lock_retval(&lock->base.count);
-
- if (likely(!ret)) {
+ if (__mutex_trylock_fast(&lock->base)) {
ww_mutex_set_context_fastpath(lock, ctx);
- mutex_set_owner(&lock->base);
- } else
- ret = __ww_mutex_lock_interruptible_slowpath(lock, ctx);
- return ret;
+ return 0;
+ }
+
+ return __ww_mutex_lock_interruptible_slowpath(lock, ctx);
}
EXPORT_SYMBOL(__ww_mutex_lock_interruptible);
diff --git a/kernel/locking/mutex.h b/kernel/locking/mutex.h
index 6cd6b8e9efd7..4410a4af42a3 100644
--- a/kernel/locking/mutex.h
+++ b/kernel/locking/mutex.h
@@ -16,32 +16,6 @@
#define mutex_remove_waiter(lock, waiter, task) \
__list_del((waiter)->list.prev, (waiter)->list.next)
-#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-/*
- * The mutex owner can get read and written to locklessly.
- * We should use WRITE_ONCE when writing the owner value to
- * avoid store tearing, otherwise, a thread could potentially
- * read a partially written and incomplete owner value.
- */
-static inline void mutex_set_owner(struct mutex *lock)
-{
- WRITE_ONCE(lock->owner, current);
-}
-
-static inline void mutex_clear_owner(struct mutex *lock)
-{
- WRITE_ONCE(lock->owner, NULL);
-}
-#else
-static inline void mutex_set_owner(struct mutex *lock)
-{
-}
-
-static inline void mutex_clear_owner(struct mutex *lock)
-{
-}
-#endif
-
#define debug_mutex_wake_waiter(lock, waiter) do { } while (0)
#define debug_mutex_free_waiter(waiter) do { } while (0)
#define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0)
diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c
index 05a37857ab55..a3167941093b 100644
--- a/kernel/locking/osq_lock.c
+++ b/kernel/locking/osq_lock.c
@@ -21,6 +21,11 @@ static inline int encode_cpu(int cpu_nr)
return cpu_nr + 1;
}
+static inline int node_cpu(struct optimistic_spin_node *node)
+{
+ return node->cpu - 1;
+}
+
static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val)
{
int cpu_nr = encoded_cpu_val - 1;
@@ -75,7 +80,7 @@ osq_wait_next(struct optimistic_spin_queue *lock,
break;
}
- cpu_relax_lowlatency();
+ cpu_relax();
}
return next;
@@ -118,11 +123,13 @@ bool osq_lock(struct optimistic_spin_queue *lock)
while (!READ_ONCE(node->locked)) {
/*
* If we need to reschedule bail... so we can block.
+ * Use vcpu_is_preempted() to avoid waiting for a preempted
+ * lock holder:
*/
- if (need_resched())
+ if (need_resched() || vcpu_is_preempted(node_cpu(node->prev)))
goto unqueue;
- cpu_relax_lowlatency();
+ cpu_relax();
}
return true;
@@ -148,7 +155,7 @@ unqueue:
if (smp_load_acquire(&node->locked))
return true;
- cpu_relax_lowlatency();
+ cpu_relax();
/*
* Or we race against a concurrent unqueue()'s step-B, in which
diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
index 19248ddf37ce..cc3ed0ccdfa2 100644
--- a/kernel/locking/qrwlock.c
+++ b/kernel/locking/qrwlock.c
@@ -54,7 +54,7 @@ static __always_inline void
rspin_until_writer_unlock(struct qrwlock *lock, u32 cnts)
{
while ((cnts & _QW_WMASK) == _QW_LOCKED) {
- cpu_relax_lowlatency();
+ cpu_relax();
cnts = atomic_read_acquire(&lock->cnts);
}
}
@@ -130,7 +130,7 @@ void queued_write_lock_slowpath(struct qrwlock *lock)
(cmpxchg_relaxed(&l->wmode, 0, _QW_WAITING) == 0))
break;
- cpu_relax_lowlatency();
+ cpu_relax();
}
/* When no more readers, set the locked flag */
@@ -141,7 +141,7 @@ void queued_write_lock_slowpath(struct qrwlock *lock)
_QW_LOCKED) == _QW_WAITING))
break;
- cpu_relax_lowlatency();
+ cpu_relax();
}
unlock:
arch_spin_unlock(&lock->wait_lock);
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 2c49d76f96c3..2f443ed2320a 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1446,7 +1446,7 @@ rt_mutex_fastunlock(struct rt_mutex *lock,
bool (*slowfn)(struct rt_mutex *lock,
struct wake_q_head *wqh))
{
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
if (likely(rt_mutex_cmpxchg_release(lock, current, NULL))) {
rt_mutex_deadlock_account_unlock(current);
@@ -1619,11 +1619,15 @@ EXPORT_SYMBOL_GPL(__rt_mutex_init);
* rt_mutex_init_proxy_locked - initialize and lock a rt_mutex on behalf of a
* proxy owner
*
- * @lock: the rt_mutex to be locked
+ * @lock: the rt_mutex to be locked
* @proxy_owner:the task to set as owner
*
* No locking. Caller has to do serializing itself
- * Special API call for PI-futex support
+ *
+ * Special API call for PI-futex support. This initializes the rtmutex and
+ * assigns it to @proxy_owner. Concurrent operations on the rtmutex are not
+ * possible at this point because the pi_state which contains the rtmutex
+ * is not yet visible to other tasks.
*/
void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
struct task_struct *proxy_owner)
@@ -1637,10 +1641,14 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
/**
* rt_mutex_proxy_unlock - release a lock on behalf of owner
*
- * @lock: the rt_mutex to be locked
+ * @lock: the rt_mutex to be locked
*
* No locking. Caller has to do serializing itself
- * Special API call for PI-futex support
+ *
+ * Special API call for PI-futex support. This merrily cleans up the rtmutex
+ * (debugging) state. Concurrent operations on this rt_mutex are not
+ * possible because it belongs to the pi_state which is about to be freed
+ * and it is not longer visible to other tasks.
*/
void rt_mutex_proxy_unlock(struct rt_mutex *lock,
struct task_struct *proxy_owner)
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index e317e1cbb3eb..990134617b4c 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -71,13 +71,12 @@ task_top_pi_waiter(struct task_struct *p)
* lock->owner state tracking:
*/
#define RT_MUTEX_HAS_WAITERS 1UL
-#define RT_MUTEX_OWNER_MASKALL 1UL
static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
{
unsigned long owner = (unsigned long) READ_ONCE(lock->owner);
- return (struct task_struct *) (owner & ~RT_MUTEX_OWNER_MASKALL);
+ return (struct task_struct *) (owner & ~RT_MUTEX_HAS_WAITERS);
}
/*
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 2337b4bb2366..631506004f9e 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -225,7 +225,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
long count, adjustment = -RWSEM_ACTIVE_READ_BIAS;
struct rwsem_waiter waiter;
struct task_struct *tsk = current;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
waiter.task = tsk;
waiter.type = RWSEM_WAITING_FOR_READ;
@@ -336,7 +336,11 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
goto done;
}
- ret = owner->on_cpu;
+ /*
+ * As lock holder preemption issue, we both skip spinning if task is not
+ * on cpu or its cpu is preempted
+ */
+ ret = owner->on_cpu && !vcpu_is_preempted(task_cpu(owner));
done:
rcu_read_unlock();
return ret;
@@ -362,13 +366,17 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem)
*/
barrier();
- /* abort spinning when need_resched or owner is not running */
- if (!owner->on_cpu || need_resched()) {
+ /*
+ * abort spinning when need_resched or owner is not running or
+ * owner's cpu is preempted.
+ */
+ if (!owner->on_cpu || need_resched() ||
+ vcpu_is_preempted(task_cpu(owner))) {
rcu_read_unlock();
return false;
}
- cpu_relax_lowlatency();
+ cpu_relax();
}
rcu_read_unlock();
out:
@@ -423,7 +431,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
* memory barriers as we'll eventually observe the right
* values at the cost of a few extra spins.
*/
- cpu_relax_lowlatency();
+ cpu_relax();
}
osq_unlock(&sem->osq);
done:
@@ -461,7 +469,7 @@ __rwsem_down_write_failed_common(struct rw_semaphore *sem, int state)
bool waiting = true; /* any queued threads before us */
struct rwsem_waiter waiter;
struct rw_semaphore *ret = sem;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
/* undo write bias from down_write operation, stop active locking */
count = atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS, &sem->count);
@@ -495,7 +503,7 @@ __rwsem_down_write_failed_common(struct rw_semaphore *sem, int state)
* wake any read locks that were queued ahead of us.
*/
if (count > RWSEM_WAITING_BIAS) {
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
__rwsem_mark_wake(sem, RWSEM_WAKE_READERS, &wake_q);
/*
@@ -571,7 +579,7 @@ __visible
struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
{
unsigned long flags;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
/*
* If a spinner is present, it is not necessary to do the wakeup.
@@ -625,7 +633,7 @@ __visible
struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
{
unsigned long flags;
- WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_q);
raw_spin_lock_irqsave(&sem->wait_lock, flags);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 281a697fd458..d401c21136d1 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -78,6 +78,78 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
power_attr(pm_async);
+#ifdef CONFIG_SUSPEND
+static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ char *s = buf;
+ suspend_state_t i;
+
+ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
+ if (mem_sleep_states[i]) {
+ const char *label = mem_sleep_states[i];
+
+ if (mem_sleep_current == i)
+ s += sprintf(s, "[%s] ", label);
+ else
+ s += sprintf(s, "%s ", label);
+ }
+
+ /* Convert the last space to a newline if needed. */
+ if (s != buf)
+ *(s-1) = '\n';
+
+ return (s - buf);
+}
+
+static suspend_state_t decode_suspend_state(const char *buf, size_t n)
+{
+ suspend_state_t state;
+ char *p;
+ int len;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+ for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
+ const char *label = mem_sleep_states[state];
+
+ if (label && len == strlen(label) && !strncmp(buf, label, len))
+ return state;
+ }
+
+ return PM_SUSPEND_ON;
+}
+
+static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ suspend_state_t state;
+ int error;
+
+ error = pm_autosleep_lock();
+ if (error)
+ return error;
+
+ if (pm_autosleep_state() > PM_SUSPEND_ON) {
+ error = -EBUSY;
+ goto out;
+ }
+
+ state = decode_suspend_state(buf, n);
+ if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
+ mem_sleep_current = state;
+ else
+ error = -EINVAL;
+
+ out:
+ pm_autosleep_unlock();
+ return error ? error : n;
+}
+
+power_attr(mem_sleep);
+#endif /* CONFIG_SUSPEND */
+
#ifdef CONFIG_PM_DEBUG
int pm_test_level = TEST_NONE;
@@ -368,12 +440,16 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
}
state = decode_state(buf, n);
- if (state < PM_SUSPEND_MAX)
+ if (state < PM_SUSPEND_MAX) {
+ if (state == PM_SUSPEND_MEM)
+ state = mem_sleep_current;
+
error = pm_suspend(state);
- else if (state == PM_SUSPEND_MAX)
+ } else if (state == PM_SUSPEND_MAX) {
error = hibernate();
- else
+ } else {
error = -EINVAL;
+ }
out:
pm_autosleep_unlock();
@@ -485,6 +561,9 @@ static ssize_t autosleep_store(struct kobject *kobj,
&& strcmp(buf, "off") && strcmp(buf, "off\n"))
return -EINVAL;
+ if (state == PM_SUSPEND_MEM)
+ state = mem_sleep_current;
+
error = pm_autosleep_set_state(state);
return error ? error : n;
}
@@ -602,6 +681,9 @@ static struct attribute * g[] = {
#ifdef CONFIG_PM_SLEEP
&pm_async_attr.attr,
&wakeup_count_attr.attr,
+#ifdef CONFIG_SUSPEND
+ &mem_sleep_attr.attr,
+#endif
#ifdef CONFIG_PM_AUTOSLEEP
&autosleep_attr.attr,
#endif
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 56d1d0dedf76..1dfa0da827d3 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -189,11 +189,15 @@ extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *);
#ifdef CONFIG_SUSPEND
/* kernel/power/suspend.c */
-extern const char *pm_labels[];
+extern const char * const pm_labels[];
extern const char *pm_states[];
+extern const char *mem_sleep_states[];
+extern suspend_state_t mem_sleep_current;
extern int suspend_devices_and_enter(suspend_state_t state);
#else /* !CONFIG_SUSPEND */
+#define mem_sleep_current PM_SUSPEND_ON
+
static inline int suspend_devices_and_enter(suspend_state_t state)
{
return -ENOSYS;
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 6ccb08f57fcb..f67ceb7768b8 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -32,8 +32,21 @@
#include "power.h"
-const char *pm_labels[] = { "mem", "standby", "freeze", NULL };
+const char * const pm_labels[] = {
+ [PM_SUSPEND_FREEZE] = "freeze",
+ [PM_SUSPEND_STANDBY] = "standby",
+ [PM_SUSPEND_MEM] = "mem",
+};
const char *pm_states[PM_SUSPEND_MAX];
+static const char * const mem_sleep_labels[] = {
+ [PM_SUSPEND_FREEZE] = "s2idle",
+ [PM_SUSPEND_STANDBY] = "shallow",
+ [PM_SUSPEND_MEM] = "deep",
+};
+const char *mem_sleep_states[PM_SUSPEND_MAX];
+
+suspend_state_t mem_sleep_current = PM_SUSPEND_FREEZE;
+suspend_state_t mem_sleep_default = PM_SUSPEND_MAX;
unsigned int pm_suspend_global_flags;
EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
@@ -110,30 +123,32 @@ static bool valid_state(suspend_state_t state)
return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
}
-/*
- * If this is set, the "mem" label always corresponds to the deepest sleep state
- * available, the "standby" label corresponds to the second deepest sleep state
- * available (if any), and the "freeze" label corresponds to the remaining
- * available sleep state (if there is one).
- */
-static bool relative_states;
-
void __init pm_states_init(void)
{
+ /* "mem" and "freeze" are always present in /sys/power/state. */
+ pm_states[PM_SUSPEND_MEM] = pm_labels[PM_SUSPEND_MEM];
+ pm_states[PM_SUSPEND_FREEZE] = pm_labels[PM_SUSPEND_FREEZE];
/*
- * freeze state should be supported even without any suspend_ops,
- * initialize pm_states accordingly here
+ * Suspend-to-idle should be supported even without any suspend_ops,
+ * initialize mem_sleep_states[] accordingly here.
*/
- pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2];
+ mem_sleep_states[PM_SUSPEND_FREEZE] = mem_sleep_labels[PM_SUSPEND_FREEZE];
}
-static int __init sleep_states_setup(char *str)
+static int __init mem_sleep_default_setup(char *str)
{
- relative_states = !strncmp(str, "1", 1);
+ suspend_state_t state;
+
+ for (state = PM_SUSPEND_FREEZE; state <= PM_SUSPEND_MEM; state++)
+ if (mem_sleep_labels[state] &&
+ !strcmp(str, mem_sleep_labels[state])) {
+ mem_sleep_default = state;
+ break;
+ }
+
return 1;
}
-
-__setup("relative_sleep_states=", sleep_states_setup);
+__setup("mem_sleep_default=", mem_sleep_default_setup);
/**
* suspend_set_ops - Set the global suspend method table.
@@ -141,21 +156,21 @@ __setup("relative_sleep_states=", sleep_states_setup);
*/
void suspend_set_ops(const struct platform_suspend_ops *ops)
{
- suspend_state_t i;
- int j = 0;
-
lock_system_sleep();
suspend_ops = ops;
- for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
- if (valid_state(i)) {
- pm_states[i] = pm_labels[j++];
- } else if (!relative_states) {
- pm_states[i] = NULL;
- j++;
- }
- pm_states[PM_SUSPEND_FREEZE] = pm_labels[j];
+ if (valid_state(PM_SUSPEND_STANDBY)) {
+ mem_sleep_states[PM_SUSPEND_STANDBY] = mem_sleep_labels[PM_SUSPEND_STANDBY];
+ pm_states[PM_SUSPEND_STANDBY] = pm_labels[PM_SUSPEND_STANDBY];
+ if (mem_sleep_default == PM_SUSPEND_STANDBY)
+ mem_sleep_current = PM_SUSPEND_STANDBY;
+ }
+ if (valid_state(PM_SUSPEND_MEM)) {
+ mem_sleep_states[PM_SUSPEND_MEM] = mem_sleep_labels[PM_SUSPEND_MEM];
+ if (mem_sleep_default >= PM_SUSPEND_MEM)
+ mem_sleep_current = PM_SUSPEND_MEM;
+ }
unlock_system_sleep();
}
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index a3b1e617bcdc..32e0c232efba 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -307,7 +307,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
{
int error;
- hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block,
+ hib_submit_io(REQ_OP_READ, 0, swsusp_resume_block,
swsusp_header, NULL);
if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
!memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
@@ -317,7 +317,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
swsusp_header->flags = flags;
if (flags & SF_CRC32_MODE)
swsusp_header->crc32 = handle->crc32;
- error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC,
+ error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC,
swsusp_resume_block, swsusp_header, NULL);
} else {
printk(KERN_ERR "PM: Swap header not found!\n");
@@ -397,7 +397,7 @@ static int write_page(void *buf, sector_t offset, struct hib_bio_batch *hb)
} else {
src = buf;
}
- return hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, offset, src, hb);
+ return hib_submit_io(REQ_OP_WRITE, REQ_SYNC, offset, src, hb);
}
static void release_swap_writer(struct swap_map_handle *handle)
@@ -1000,8 +1000,7 @@ static int get_swap_reader(struct swap_map_handle *handle,
return -ENOMEM;
}
- error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset,
- tmp->map, NULL);
+ error = hib_submit_io(REQ_OP_READ, 0, offset, tmp->map, NULL);
if (error) {
release_swap_reader(handle);
return error;
@@ -1025,7 +1024,7 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf,
offset = handle->cur->entries[handle->k];
if (!offset)
return -EFAULT;
- error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset, buf, hb);
+ error = hib_submit_io(REQ_OP_READ, 0, offset, buf, hb);
if (error)
return error;
if (++handle->k >= MAP_PAGE_ENTRIES) {
@@ -1534,7 +1533,7 @@ int swsusp_check(void)
if (!IS_ERR(hib_resume_bdev)) {
set_blocksize(hib_resume_bdev, PAGE_SIZE);
clear_page(swsusp_header);
- error = hib_submit_io(REQ_OP_READ, READ_SYNC,
+ error = hib_submit_io(REQ_OP_READ, 0,
swsusp_resume_block,
swsusp_header, NULL);
if (error)
@@ -1543,7 +1542,7 @@ int swsusp_check(void)
if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) {
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
/* Reset swap signature now */
- error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC,
+ error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC,
swsusp_resume_block,
swsusp_header, NULL);
} else {
@@ -1588,11 +1587,11 @@ int swsusp_unmark(void)
{
int error;
- hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block,
+ hib_submit_io(REQ_OP_READ, 0, swsusp_resume_block,
swsusp_header, NULL);
if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) {
memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10);
- error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC,
+ error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC,
swsusp_resume_block,
swsusp_header, NULL);
} else {
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index 16bab471c7e2..f011aaef583c 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -67,7 +67,8 @@ static int vprintk_nmi(const char *fmt, va_list args)
again:
len = atomic_read(&s->len);
- if (len >= sizeof(s->buffer)) {
+ /* The trailing '\0' is not counted into len. */
+ if (len >= sizeof(s->buffer) - 1) {
atomic_inc(&nmi_message_lost);
return 0;
}
@@ -79,7 +80,7 @@ again:
if (!len)
smp_rmb();
- add = vsnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args);
+ add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args);
/*
* Do it once again if the buffer has been flushed in the meantime.
@@ -113,16 +114,51 @@ static void printk_nmi_flush_line(const char *text, int len)
}
-/*
- * printk one line from the temporary buffer from @start index until
- * and including the @end index.
- */
-static void printk_nmi_flush_seq_line(struct nmi_seq_buf *s,
- int start, int end)
+/* printk part of the temporary buffer line by line */
+static int printk_nmi_flush_buffer(const char *start, size_t len)
{
- const char *buf = s->buffer + start;
+ const char *c, *end;
+ bool header;
+
+ c = start;
+ end = start + len;
+ header = true;
+
+ /* Print line by line. */
+ while (c < end) {
+ if (*c == '\n') {
+ printk_nmi_flush_line(start, c - start + 1);
+ start = ++c;
+ header = true;
+ continue;
+ }
+
+ /* Handle continuous lines or missing new line. */
+ if ((c + 1 < end) && printk_get_level(c)) {
+ if (header) {
+ c = printk_skip_level(c);
+ continue;
+ }
+
+ printk_nmi_flush_line(start, c - start);
+ start = c++;
+ header = true;
+ continue;
+ }
+
+ header = false;
+ c++;
+ }
- printk_nmi_flush_line(buf, (end - start) + 1);
+ /* Check if there was a partial line. Ignore pure header. */
+ if (start < end && !header) {
+ static const char newline[] = KERN_CONT "\n";
+
+ printk_nmi_flush_line(start, end - start);
+ printk_nmi_flush_line(newline, strlen(newline));
+ }
+
+ return len;
}
/*
@@ -135,8 +171,8 @@ static void __printk_nmi_flush(struct irq_work *work)
__RAW_SPIN_LOCK_INITIALIZER(read_lock);
struct nmi_seq_buf *s = container_of(work, struct nmi_seq_buf, work);
unsigned long flags;
- size_t len, size;
- int i, last_i;
+ size_t len;
+ int i;
/*
* The lock has two functions. First, one reader has to flush all
@@ -154,12 +190,14 @@ more:
/*
* This is just a paranoid check that nobody has manipulated
* the buffer an unexpected way. If we printed something then
- * @len must only increase.
+ * @len must only increase. Also it should never overflow the
+ * buffer size.
*/
- if (i && i >= len) {
+ if ((i && i >= len) || len > sizeof(s->buffer)) {
const char *msg = "printk_nmi_flush: internal error\n";
printk_nmi_flush_line(msg, strlen(msg));
+ len = 0;
}
if (!len)
@@ -167,22 +205,7 @@ more:
/* Make sure that data has been written up to the @len */
smp_rmb();
-
- size = min(len, sizeof(s->buffer));
- last_i = i;
-
- /* Print line by line. */
- for (; i < size; i++) {
- if (s->buffer[i] == '\n') {
- printk_nmi_flush_seq_line(s, last_i, i);
- last_i = i + 1;
- }
- }
- /* Check if there was a partial line. */
- if (last_i < size) {
- printk_nmi_flush_seq_line(s, last_i, size - 1);
- printk_nmi_flush_line("\n", strlen("\n"));
- }
+ i += printk_nmi_flush_buffer(s->buffer + i, len - i);
/*
* Check that nothing has got added in the meantime and truncate
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index f7a55e9ff2f7..577f2288d19f 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2166,27 +2166,20 @@ void resume_console(void)
/**
* console_cpu_notify - print deferred console messages after CPU hotplug
- * @self: notifier struct
- * @action: CPU hotplug event
- * @hcpu: unused
+ * @cpu: unused
*
* If printk() is called from a CPU that is not online yet, the messages
* will be spooled but will not show up on the console. This function is
* called when a new CPU comes online (or fails to come up), and ensures
* that any such output gets printed.
*/
-static int console_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- switch (action) {
- case CPU_ONLINE:
- case CPU_DEAD:
- case CPU_DOWN_FAILED:
- case CPU_UP_CANCELED:
+static int console_cpu_notify(unsigned int cpu)
+{
+ if (!cpuhp_tasks_frozen) {
console_lock();
console_unlock();
}
- return NOTIFY_OK;
+ return 0;
}
/**
@@ -2824,6 +2817,7 @@ EXPORT_SYMBOL(unregister_console);
static int __init printk_late_init(void)
{
struct console *con;
+ int ret;
for_each_console(con) {
if (!keep_bootcon && con->flags & CON_BOOT) {
@@ -2838,7 +2832,12 @@ static int __init printk_late_init(void)
unregister_console(con);
}
}
- hotcpu_notifier(console_cpu_notify, 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,
+ console_cpu_notify);
+ WARN_ON(ret < 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "printk:online",
+ console_cpu_notify, NULL);
+ WARN_ON(ret < 0);
return 0;
}
late_initcall(printk_late_init);
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index bf08fee53dc7..87c51225ceec 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -289,15 +289,24 @@ static int rcu_torture_read_lock(void) __acquires(RCU)
static void rcu_read_delay(struct torture_random_state *rrsp)
{
+ unsigned long started;
+ unsigned long completed;
const unsigned long shortdelay_us = 200;
const unsigned long longdelay_ms = 50;
+ unsigned long long ts;
/* We want a short delay sometimes to make a reader delay the grace
* period, and we want a long delay occasionally to trigger
* force_quiescent_state. */
- if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms)))
+ if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) {
+ started = cur_ops->completed();
+ ts = rcu_trace_clock_local();
mdelay(longdelay_ms);
+ completed = cur_ops->completed();
+ do_trace_rcu_torture_read(cur_ops->name, NULL, ts,
+ started, completed);
+ }
if (!(torture_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
udelay(shortdelay_us);
#ifdef CONFIG_PREEMPT
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 69a5611a7e7c..96c52e43f7ca 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1304,7 +1304,8 @@ static void rcu_stall_kick_kthreads(struct rcu_state *rsp)
if (!rcu_kick_kthreads)
return;
j = READ_ONCE(rsp->jiffies_kick_kthreads);
- if (time_after(jiffies, j) && rsp->gp_kthread) {
+ if (time_after(jiffies, j) && rsp->gp_kthread &&
+ (rcu_gp_in_progress(rsp) || READ_ONCE(rsp->gp_flags))) {
WARN_ONCE(1, "Kicking %s grace-period kthread\n", rsp->name);
rcu_ftrace_dump(DUMP_ALL);
wake_up_process(rsp->gp_kthread);
@@ -2828,8 +2829,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
* Also schedule RCU core processing.
*
* This function must be called from hardirq context. It is normally
- * invoked from the scheduling-clock interrupt. If rcu_pending returns
- * false, there is no point in invoking rcu_check_callbacks().
+ * invoked from the scheduling-clock interrupt.
*/
void rcu_check_callbacks(int user)
{
@@ -3121,7 +3121,9 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func,
unsigned long flags;
struct rcu_data *rdp;
- WARN_ON_ONCE((unsigned long)head & 0x1); /* Misaligned rcu_head! */
+ /* Misaligned rcu_head! */
+ WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1));
+
if (debug_rcu_head_queue(head)) {
/* Probable double call_rcu(), so leak the callback. */
WRITE_ONCE(head->func, rcu_leak_callback);
@@ -3130,13 +3132,6 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func,
}
head->func = func;
head->next = NULL;
-
- /*
- * Opportunistically note grace-period endings and beginnings.
- * Note that we might see a beginning right after we see an
- * end, but never vice versa, since this CPU has to pass through
- * a quiescent state betweentimes.
- */
local_irq_save(flags);
rdp = this_cpu_ptr(rsp->rda);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index e99a5234d9ed..fe98dd24adf8 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -404,6 +404,7 @@ struct rcu_data {
atomic_long_t exp_workdone1; /* # done by others #1. */
atomic_long_t exp_workdone2; /* # done by others #2. */
atomic_long_t exp_workdone3; /* # done by others #3. */
+ int exp_dynticks_snap; /* Double-check need for IPI. */
/* 7) Callback offloading. */
#ifdef CONFIG_RCU_NOCB_CPU
diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h
index 24343eb87b58..d3053e99fdb6 100644
--- a/kernel/rcu/tree_exp.h
+++ b/kernel/rcu/tree_exp.h
@@ -358,8 +358,10 @@ static void sync_rcu_exp_select_cpus(struct rcu_state *rsp,
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+ rdp->exp_dynticks_snap =
+ atomic_add_return(0, &rdtp->dynticks);
if (raw_smp_processor_id() == cpu ||
- !(atomic_add_return(0, &rdtp->dynticks) & 0x1) ||
+ !(rdp->exp_dynticks_snap & 0x1) ||
!(rnp->qsmaskinitnext & rdp->grpmask))
mask_ofl_test |= rdp->grpmask;
}
@@ -377,9 +379,17 @@ static void sync_rcu_exp_select_cpus(struct rcu_state *rsp,
/* IPI the remaining CPUs for expedited quiescent state. */
for_each_leaf_node_possible_cpu(rnp, cpu) {
unsigned long mask = leaf_node_cpu_bit(rnp, cpu);
+ struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
+ struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
if (!(mask_ofl_ipi & mask))
continue;
retry_ipi:
+ if (atomic_add_return(0, &rdtp->dynticks) !=
+ rdp->exp_dynticks_snap) {
+ mask_ofl_test |= mask;
+ continue;
+ }
ret = smp_call_function_single(cpu, func, rsp, 0);
if (!ret) {
mask_ofl_ipi &= ~mask;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 154fd689fe02..966556ebdbb3 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -75,11 +75,11 @@
#include <linux/compiler.h>
#include <linux/frame.h>
#include <linux/prefetch.h>
+#include <linux/mutex.h>
#include <asm/switch_to.h>
#include <asm/tlb.h>
#include <asm/irq_regs.h>
-#include <asm/mutex.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
@@ -1995,14 +1995,15 @@ static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)
* @state: the mask of task states that can be woken
* @wake_flags: wake modifier flags (WF_*)
*
- * Put it on the run-queue if it's not already there. The "current"
- * thread is always on the run-queue (except when the actual
- * re-schedule is in progress), and as such you're allowed to do
- * the simpler "current->state = TASK_RUNNING" to mark yourself
- * runnable without the overhead of this.
+ * If (@state & @p->state) @p->state = TASK_RUNNING.
*
- * Return: %true if @p was woken up, %false if it was already running.
- * or @state didn't match @p's state.
+ * If the task was not queued/runnable, also place it back on a runqueue.
+ *
+ * Atomic against schedule() which would dequeue a task, also see
+ * set_current_state().
+ *
+ * Return: %true if @p->state changes (an actual wakeup was done),
+ * %false otherwise.
*/
static int
try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
@@ -5279,6 +5280,7 @@ void init_idle(struct task_struct *idle, int cpu)
__sched_fork(0, idle);
idle->state = TASK_RUNNING;
idle->se.exec_start = sched_clock();
+ idle->flags |= PF_IDLE;
kasan_unpoison_task_stack(idle);
@@ -5707,7 +5709,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
printk(KERN_CONT " %*pbl",
cpumask_pr_args(sched_group_cpus(group)));
if (group->sgc->capacity != SCHED_CAPACITY_SCALE) {
- printk(KERN_CONT " (cpu_capacity = %d)",
+ printk(KERN_CONT " (cpu_capacity = %lu)",
group->sgc->capacity);
}
@@ -6184,6 +6186,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
* die on a /0 trap.
*/
sg->sgc->capacity = SCHED_CAPACITY_SCALE * cpumask_weight(sg_span);
+ sg->sgc->min_capacity = SCHED_CAPACITY_SCALE;
/*
* Make sure the first group of this domain contains the
@@ -6301,7 +6304,22 @@ static void init_sched_groups_capacity(int cpu, struct sched_domain *sd)
WARN_ON(!sg);
do {
+ int cpu, max_cpu = -1;
+
sg->group_weight = cpumask_weight(sched_group_cpus(sg));
+
+ if (!(sd->flags & SD_ASYM_PACKING))
+ goto next;
+
+ for_each_cpu(cpu, sched_group_cpus(sg)) {
+ if (max_cpu < 0)
+ max_cpu = cpu;
+ else if (sched_asym_prefer(cpu, max_cpu))
+ max_cpu = cpu;
+ }
+ sg->asym_prefer_cpu = max_cpu;
+
+next:
sg = sg->next;
} while (sg != sd->groups);
@@ -7602,6 +7620,7 @@ void __init sched_init(void)
#ifdef CONFIG_FAIR_GROUP_SCHED
root_task_group.shares = ROOT_TASK_GROUP_LOAD;
INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
/*
* How much cpu bandwidth does root_task_group get?
*
diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
index bc0b309c3f19..9add206b5608 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -297,7 +297,7 @@ static int cpuacct_stats_show(struct seq_file *sf, void *v)
for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) {
seq_printf(sf, "%s %lld\n",
cpuacct_stat_desc[stat],
- cputime64_to_clock_t(val[stat]));
+ (long long)cputime64_to_clock_t(val[stat]));
}
return 0;
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 69e06898997d..fd4659313640 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -12,11 +12,14 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/cpufreq.h>
+#include <linux/kthread.h>
#include <linux/slab.h>
#include <trace/events/power.h>
#include "sched.h"
+#define SUGOV_KTHREAD_PRIORITY 50
+
struct sugov_tunables {
struct gov_attr_set attr_set;
unsigned int rate_limit_us;
@@ -35,8 +38,10 @@ struct sugov_policy {
/* The next fields are only needed if fast switch cannot be used. */
struct irq_work irq_work;
- struct work_struct work;
+ struct kthread_work work;
struct mutex work_lock;
+ struct kthread_worker worker;
+ struct task_struct *thread;
bool work_in_progress;
bool need_freq_update;
@@ -291,7 +296,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
raw_spin_unlock(&sg_policy->update_lock);
}
-static void sugov_work(struct work_struct *work)
+static void sugov_work(struct kthread_work *work)
{
struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
@@ -308,7 +313,21 @@ static void sugov_irq_work(struct irq_work *irq_work)
struct sugov_policy *sg_policy;
sg_policy = container_of(irq_work, struct sugov_policy, irq_work);
- schedule_work_on(smp_processor_id(), &sg_policy->work);
+
+ /*
+ * For RT and deadline tasks, the schedutil governor shoots the
+ * frequency to maximum. Special care must be taken to ensure that this
+ * kthread doesn't result in the same behavior.
+ *
+ * This is (mostly) guaranteed by the work_in_progress flag. The flag is
+ * updated only at the end of the sugov_work() function and before that
+ * the schedutil governor rejects all other frequency scaling requests.
+ *
+ * There is a very rare case though, where the RT thread yields right
+ * after the work_in_progress flag is cleared. The effects of that are
+ * neglected for now.
+ */
+ kthread_queue_work(&sg_policy->worker, &sg_policy->work);
}
/************************** sysfs interface ************************/
@@ -371,19 +390,64 @@ static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy)
return NULL;
sg_policy->policy = policy;
- init_irq_work(&sg_policy->irq_work, sugov_irq_work);
- INIT_WORK(&sg_policy->work, sugov_work);
- mutex_init(&sg_policy->work_lock);
raw_spin_lock_init(&sg_policy->update_lock);
return sg_policy;
}
static void sugov_policy_free(struct sugov_policy *sg_policy)
{
- mutex_destroy(&sg_policy->work_lock);
kfree(sg_policy);
}
+static int sugov_kthread_create(struct sugov_policy *sg_policy)
+{
+ struct task_struct *thread;
+ struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO / 2 };
+ struct cpufreq_policy *policy = sg_policy->policy;
+ int ret;
+
+ /* kthread only required for slow path */
+ if (policy->fast_switch_enabled)
+ return 0;
+
+ kthread_init_work(&sg_policy->work, sugov_work);
+ kthread_init_worker(&sg_policy->worker);
+ thread = kthread_create(kthread_worker_fn, &sg_policy->worker,
+ "sugov:%d",
+ cpumask_first(policy->related_cpus));
+ if (IS_ERR(thread)) {
+ pr_err("failed to create sugov thread: %ld\n", PTR_ERR(thread));
+ return PTR_ERR(thread);
+ }
+
+ ret = sched_setscheduler_nocheck(thread, SCHED_FIFO, &param);
+ if (ret) {
+ kthread_stop(thread);
+ pr_warn("%s: failed to set SCHED_FIFO\n", __func__);
+ return ret;
+ }
+
+ sg_policy->thread = thread;
+ kthread_bind_mask(thread, policy->related_cpus);
+ init_irq_work(&sg_policy->irq_work, sugov_irq_work);
+ mutex_init(&sg_policy->work_lock);
+
+ wake_up_process(thread);
+
+ return 0;
+}
+
+static void sugov_kthread_stop(struct sugov_policy *sg_policy)
+{
+ /* kthread only required for slow path */
+ if (sg_policy->policy->fast_switch_enabled)
+ return;
+
+ kthread_flush_worker(&sg_policy->worker);
+ kthread_stop(sg_policy->thread);
+ mutex_destroy(&sg_policy->work_lock);
+}
+
static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy)
{
struct sugov_tunables *tunables;
@@ -416,16 +480,24 @@ static int sugov_init(struct cpufreq_policy *policy)
if (policy->governor_data)
return -EBUSY;
+ cpufreq_enable_fast_switch(policy);
+
sg_policy = sugov_policy_alloc(policy);
- if (!sg_policy)
- return -ENOMEM;
+ if (!sg_policy) {
+ ret = -ENOMEM;
+ goto disable_fast_switch;
+ }
+
+ ret = sugov_kthread_create(sg_policy);
+ if (ret)
+ goto free_sg_policy;
mutex_lock(&global_tunables_lock);
if (global_tunables) {
if (WARN_ON(have_governor_per_policy())) {
ret = -EINVAL;
- goto free_sg_policy;
+ goto stop_kthread;
}
policy->governor_data = sg_policy;
sg_policy->tunables = global_tunables;
@@ -437,7 +509,7 @@ static int sugov_init(struct cpufreq_policy *policy)
tunables = sugov_tunables_alloc(sg_policy);
if (!tunables) {
ret = -ENOMEM;
- goto free_sg_policy;
+ goto stop_kthread;
}
tunables->rate_limit_us = LATENCY_MULTIPLIER;
@@ -454,20 +526,25 @@ static int sugov_init(struct cpufreq_policy *policy)
if (ret)
goto fail;
- out:
+out:
mutex_unlock(&global_tunables_lock);
-
- cpufreq_enable_fast_switch(policy);
return 0;
- fail:
+fail:
policy->governor_data = NULL;
sugov_tunables_free(tunables);
- free_sg_policy:
+stop_kthread:
+ sugov_kthread_stop(sg_policy);
+
+free_sg_policy:
mutex_unlock(&global_tunables_lock);
sugov_policy_free(sg_policy);
+
+disable_fast_switch:
+ cpufreq_disable_fast_switch(policy);
+
pr_err("initialization failed (error %d)\n", ret);
return ret;
}
@@ -478,8 +555,6 @@ static void sugov_exit(struct cpufreq_policy *policy)
struct sugov_tunables *tunables = sg_policy->tunables;
unsigned int count;
- cpufreq_disable_fast_switch(policy);
-
mutex_lock(&global_tunables_lock);
count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
@@ -489,7 +564,9 @@ static void sugov_exit(struct cpufreq_policy *policy)
mutex_unlock(&global_tunables_lock);
+ sugov_kthread_stop(sg_policy);
sugov_policy_free(sg_policy);
+ cpufreq_disable_fast_switch(policy);
}
static int sugov_start(struct cpufreq_policy *policy)
@@ -535,8 +612,10 @@ static void sugov_stop(struct cpufreq_policy *policy)
synchronize_sched();
- irq_work_sync(&sg_policy->irq_work);
- cancel_work_sync(&sg_policy->work);
+ if (!policy->fast_switch_enabled) {
+ irq_work_sync(&sg_policy->irq_work);
+ kthread_cancel_work_sync(&sg_policy->work);
+ }
}
static void sugov_limits(struct cpufreq_policy *policy)
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 5ebee3164e64..7700a9cba335 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -128,16 +128,13 @@ static inline void task_group_account_field(struct task_struct *p, int index,
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @cputime: the cpu time spent in user space since the last update
- * @cputime_scaled: cputime scaled by cpu frequency
*/
-void account_user_time(struct task_struct *p, cputime_t cputime,
- cputime_t cputime_scaled)
+void account_user_time(struct task_struct *p, cputime_t cputime)
{
int index;
/* Add user time to process. */
p->utime += cputime;
- p->utimescaled += cputime_scaled;
account_group_user_time(p, cputime);
index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
@@ -153,16 +150,13 @@ void account_user_time(struct task_struct *p, cputime_t cputime,
* Account guest cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @cputime: the cpu time spent in virtual machine since the last update
- * @cputime_scaled: cputime scaled by cpu frequency
*/
-static void account_guest_time(struct task_struct *p, cputime_t cputime,
- cputime_t cputime_scaled)
+static void account_guest_time(struct task_struct *p, cputime_t cputime)
{
u64 *cpustat = kcpustat_this_cpu->cpustat;
/* Add guest time to process. */
p->utime += cputime;
- p->utimescaled += cputime_scaled;
account_group_user_time(p, cputime);
p->gtime += cputime;
@@ -180,16 +174,13 @@ static void account_guest_time(struct task_struct *p, cputime_t cputime,
* Account system cpu time to a process and desired cpustat field
* @p: the process that the cpu time gets accounted to
* @cputime: the cpu time spent in kernel space since the last update
- * @cputime_scaled: cputime scaled by cpu frequency
- * @target_cputime64: pointer to cpustat field that has to be updated
+ * @index: pointer to cpustat field that has to be updated
*/
static inline
-void __account_system_time(struct task_struct *p, cputime_t cputime,
- cputime_t cputime_scaled, int index)
+void __account_system_time(struct task_struct *p, cputime_t cputime, int index)
{
/* Add system time to process. */
p->stime += cputime;
- p->stimescaled += cputime_scaled;
account_group_system_time(p, cputime);
/* Add system time to cpustat. */
@@ -204,15 +195,14 @@ void __account_system_time(struct task_struct *p, cputime_t cputime,
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
* @cputime: the cpu time spent in kernel space since the last update
- * @cputime_scaled: cputime scaled by cpu frequency
*/
void account_system_time(struct task_struct *p, int hardirq_offset,
- cputime_t cputime, cputime_t cputime_scaled)
+ cputime_t cputime)
{
int index;
if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
- account_guest_time(p, cputime, cputime_scaled);
+ account_guest_time(p, cputime);
return;
}
@@ -223,7 +213,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
else
index = CPUTIME_SYSTEM;
- __account_system_time(p, cputime, cputime_scaled, index);
+ __account_system_time(p, cputime, index);
}
/*
@@ -390,7 +380,7 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
struct rq *rq, int ticks)
{
u64 cputime = (__force u64) cputime_one_jiffy * ticks;
- cputime_t scaled, other;
+ cputime_t other;
/*
* When returning from idle, many ticks can get accounted at
@@ -403,7 +393,6 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
if (other >= cputime)
return;
cputime -= other;
- scaled = cputime_to_scaled(cputime);
if (this_cpu_ksoftirqd() == p) {
/*
@@ -411,15 +400,15 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
* So, we have to handle it separately here.
* Also, p->stime needs to be updated for ksoftirqd.
*/
- __account_system_time(p, cputime, scaled, CPUTIME_SOFTIRQ);
+ __account_system_time(p, cputime, CPUTIME_SOFTIRQ);
} else if (user_tick) {
- account_user_time(p, cputime, scaled);
+ account_user_time(p, cputime);
} else if (p == rq->idle) {
account_idle_time(cputime);
} else if (p->flags & PF_VCPU) { /* System time or guest time */
- account_guest_time(p, cputime, scaled);
+ account_guest_time(p, cputime);
} else {
- __account_system_time(p, cputime, scaled, CPUTIME_SYSTEM);
+ __account_system_time(p, cputime, CPUTIME_SYSTEM);
}
}
@@ -502,7 +491,7 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
*/
void account_process_tick(struct task_struct *p, int user_tick)
{
- cputime_t cputime, scaled, steal;
+ cputime_t cputime, steal;
struct rq *rq = this_rq();
if (vtime_accounting_cpu_enabled())
@@ -520,12 +509,11 @@ void account_process_tick(struct task_struct *p, int user_tick)
return;
cputime -= steal;
- scaled = cputime_to_scaled(cputime);
if (user_tick)
- account_user_time(p, cputime, scaled);
+ account_user_time(p, cputime);
else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
- account_system_time(p, HARDIRQ_OFFSET, cputime, scaled);
+ account_system_time(p, HARDIRQ_OFFSET, cputime);
else
account_idle_time(cputime);
}
@@ -746,7 +734,7 @@ static void __vtime_account_system(struct task_struct *tsk)
{
cputime_t delta_cpu = get_vtime_delta(tsk);
- account_system_time(tsk, irq_count(), delta_cpu, cputime_to_scaled(delta_cpu));
+ account_system_time(tsk, irq_count(), delta_cpu);
}
void vtime_account_system(struct task_struct *tsk)
@@ -767,7 +755,7 @@ void vtime_account_user(struct task_struct *tsk)
tsk->vtime_snap_whence = VTIME_SYS;
if (vtime_delta(tsk)) {
delta_cpu = get_vtime_delta(tsk);
- account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu));
+ account_user_time(tsk, delta_cpu);
}
write_seqcount_end(&tsk->vtime_seqcount);
}
@@ -863,29 +851,25 @@ cputime_t task_gtime(struct task_struct *t)
* add up the pending nohz execution time since the last
* cputime snapshot.
*/
-static void
-fetch_task_cputime(struct task_struct *t,
- cputime_t *u_dst, cputime_t *s_dst,
- cputime_t *u_src, cputime_t *s_src,
- cputime_t *udelta, cputime_t *sdelta)
+void task_cputime(struct task_struct *t, cputime_t *utime, cputime_t *stime)
{
+ cputime_t delta;
unsigned int seq;
- unsigned long long delta;
- do {
- *udelta = 0;
- *sdelta = 0;
+ if (!vtime_accounting_enabled()) {
+ *utime = t->utime;
+ *stime = t->stime;
+ return;
+ }
+ do {
seq = read_seqcount_begin(&t->vtime_seqcount);
- if (u_dst)
- *u_dst = *u_src;
- if (s_dst)
- *s_dst = *s_src;
+ *utime = t->utime;
+ *stime = t->stime;
/* Task is sleeping, nothing to add */
- if (t->vtime_snap_whence == VTIME_INACTIVE ||
- is_idle_task(t))
+ if (t->vtime_snap_whence == VTIME_INACTIVE || is_idle_task(t))
continue;
delta = vtime_delta(t);
@@ -894,54 +878,10 @@ fetch_task_cputime(struct task_struct *t,
* Task runs either in user or kernel space, add pending nohz time to
* the right place.
*/
- if (t->vtime_snap_whence == VTIME_USER || t->flags & PF_VCPU) {
- *udelta = delta;
- } else {
- if (t->vtime_snap_whence == VTIME_SYS)
- *sdelta = delta;
- }
+ if (t->vtime_snap_whence == VTIME_USER || t->flags & PF_VCPU)
+ *utime += delta;
+ else if (t->vtime_snap_whence == VTIME_SYS)
+ *stime += delta;
} while (read_seqcount_retry(&t->vtime_seqcount, seq));
}
-
-
-void task_cputime(struct task_struct *t, cputime_t *utime, cputime_t *stime)
-{
- cputime_t udelta, sdelta;
-
- if (!vtime_accounting_enabled()) {
- if (utime)
- *utime = t->utime;
- if (stime)
- *stime = t->stime;
- return;
- }
-
- fetch_task_cputime(t, utime, stime, &t->utime,
- &t->stime, &udelta, &sdelta);
- if (utime)
- *utime += udelta;
- if (stime)
- *stime += sdelta;
-}
-
-void task_cputime_scaled(struct task_struct *t,
- cputime_t *utimescaled, cputime_t *stimescaled)
-{
- cputime_t udelta, sdelta;
-
- if (!vtime_accounting_enabled()) {
- if (utimescaled)
- *utimescaled = t->utimescaled;
- if (stimescaled)
- *stimescaled = t->stimescaled;
- return;
- }
-
- fetch_task_cputime(t, utimescaled, stimescaled,
- &t->utimescaled, &t->stimescaled, &udelta, &sdelta);
- if (utimescaled)
- *utimescaled += cputime_to_scaled(udelta);
- if (stimescaled)
- *stimescaled += cputime_to_scaled(sdelta);
-}
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 37e2449186c4..70ef2b1901e4 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -586,7 +586,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
/*
* The task might have changed its scheduling policy to something
- * different than SCHED_DEADLINE (through switched_fromd_dl()).
+ * different than SCHED_DEADLINE (through switched_from_dl()).
*/
if (!dl_task(p)) {
__dl_clear_params(p);
@@ -1137,7 +1137,7 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct pin_cookie coo
pull_dl_task(rq);
lockdep_repin_lock(&rq->lock, cookie);
/*
- * pull_rt_task() can drop (and re-acquire) rq->lock; this
+ * pull_dl_task() can drop (and re-acquire) rq->lock; this
* means a stop task can slip in, in which case we need to
* re-start task selection.
*/
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index c242944f5cbd..6559d197e08a 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -37,7 +37,6 @@
/*
* Targeted preemption latency for CPU-bound tasks:
- * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
*
* NOTE: this latency value is not the same as the concept of
* 'timeslice length' - timeslices in CFS are of variable length
@@ -46,31 +45,35 @@
*
* (to see the precise effective timeslice length of your workload,
* run vmstat and monitor the context-switches (cs) field)
+ *
+ * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
*/
-unsigned int sysctl_sched_latency = 6000000ULL;
-unsigned int normalized_sysctl_sched_latency = 6000000ULL;
+unsigned int sysctl_sched_latency = 6000000ULL;
+unsigned int normalized_sysctl_sched_latency = 6000000ULL;
/*
* The initial- and re-scaling of tunables is configurable
- * (default SCHED_TUNABLESCALING_LOG = *(1+ilog(ncpus))
*
* Options are:
- * SCHED_TUNABLESCALING_NONE - unscaled, always *1
- * SCHED_TUNABLESCALING_LOG - scaled logarithmical, *1+ilog(ncpus)
- * SCHED_TUNABLESCALING_LINEAR - scaled linear, *ncpus
+ *
+ * SCHED_TUNABLESCALING_NONE - unscaled, always *1
+ * SCHED_TUNABLESCALING_LOG - scaled logarithmical, *1+ilog(ncpus)
+ * SCHED_TUNABLESCALING_LINEAR - scaled linear, *ncpus
+ *
+ * (default SCHED_TUNABLESCALING_LOG = *(1+ilog(ncpus))
*/
-enum sched_tunable_scaling sysctl_sched_tunable_scaling
- = SCHED_TUNABLESCALING_LOG;
+enum sched_tunable_scaling sysctl_sched_tunable_scaling = SCHED_TUNABLESCALING_LOG;
/*
* Minimal preemption granularity for CPU-bound tasks:
+ *
* (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds)
*/
-unsigned int sysctl_sched_min_granularity = 750000ULL;
-unsigned int normalized_sysctl_sched_min_granularity = 750000ULL;
+unsigned int sysctl_sched_min_granularity = 750000ULL;
+unsigned int normalized_sysctl_sched_min_granularity = 750000ULL;
/*
- * is kept at sysctl_sched_latency / sysctl_sched_min_granularity
+ * This value is kept at sysctl_sched_latency/sysctl_sched_min_granularity
*/
static unsigned int sched_nr_latency = 8;
@@ -82,23 +85,27 @@ unsigned int sysctl_sched_child_runs_first __read_mostly;
/*
* SCHED_OTHER wake-up granularity.
- * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
*
* This option delays the preemption effects of decoupled workloads
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
+ *
+ * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
*/
-unsigned int sysctl_sched_wakeup_granularity = 1000000UL;
-unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL;
+unsigned int sysctl_sched_wakeup_granularity = 1000000UL;
+unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL;
-const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+#ifdef CONFIG_SMP
/*
- * The exponential sliding window over which load is averaged for shares
- * distribution.
- * (default: 10msec)
+ * For asym packing, by default the lower numbered cpu has higher priority.
*/
-unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL;
+int __weak arch_asym_cpu_priority(int cpu)
+{
+ return -cpu;
+}
+#endif
#ifdef CONFIG_CFS_BANDWIDTH
/*
@@ -109,16 +116,18 @@ unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL;
* to consumption or the quota being specified to be smaller than the slice)
* we will always only issue the remaining available time.
*
- * default: 5 msec, units: microseconds
- */
-unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
+ * (default: 5 msec, units: microseconds)
+ */
+unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
#endif
/*
* The margin used when comparing utilization with CPU capacity:
- * util * 1024 < capacity * margin
+ * util * margin < capacity * 1024
+ *
+ * (default: ~20%)
*/
-unsigned int capacity_margin = 1280; /* ~20% */
+unsigned int capacity_margin = 1280;
static inline void update_load_add(struct load_weight *lw, unsigned long inc)
{
@@ -290,19 +299,59 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
{
if (!cfs_rq->on_list) {
+ struct rq *rq = rq_of(cfs_rq);
+ int cpu = cpu_of(rq);
/*
* Ensure we either appear before our parent (if already
* enqueued) or force our parent to appear after us when it is
- * enqueued. The fact that we always enqueue bottom-up
- * reduces this to two cases.
+ * enqueued. The fact that we always enqueue bottom-up
+ * reduces this to two cases and a special case for the root
+ * cfs_rq. Furthermore, it also means that we will always reset
+ * tmp_alone_branch either when the branch is connected
+ * to a tree or when we reach the beg of the tree
*/
if (cfs_rq->tg->parent &&
- cfs_rq->tg->parent->cfs_rq[cpu_of(rq_of(cfs_rq))]->on_list) {
- list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
- &rq_of(cfs_rq)->leaf_cfs_rq_list);
- } else {
+ cfs_rq->tg->parent->cfs_rq[cpu]->on_list) {
+ /*
+ * If parent is already on the list, we add the child
+ * just before. Thanks to circular linked property of
+ * the list, this means to put the child at the tail
+ * of the list that starts by parent.
+ */
list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
- &rq_of(cfs_rq)->leaf_cfs_rq_list);
+ &(cfs_rq->tg->parent->cfs_rq[cpu]->leaf_cfs_rq_list));
+ /*
+ * The branch is now connected to its tree so we can
+ * reset tmp_alone_branch to the beginning of the
+ * list.
+ */
+ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
+ } else if (!cfs_rq->tg->parent) {
+ /*
+ * cfs rq without parent should be put
+ * at the tail of the list.
+ */
+ list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
+ &rq->leaf_cfs_rq_list);
+ /*
+ * We have reach the beg of a tree so we can reset
+ * tmp_alone_branch to the beginning of the list.
+ */
+ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
+ } else {
+ /*
+ * The parent has not already been added so we want to
+ * make sure that it will be put after us.
+ * tmp_alone_branch points to the beg of the branch
+ * where we will add parent.
+ */
+ list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
+ rq->tmp_alone_branch);
+ /*
+ * update tmp_alone_branch to points to the new beg
+ * of the branch
+ */
+ rq->tmp_alone_branch = &cfs_rq->leaf_cfs_rq_list;
}
cfs_rq->on_list = 1;
@@ -708,9 +757,7 @@ void init_entity_runnable_average(struct sched_entity *se)
}
static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
-static int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq);
-static void update_tg_load_avg(struct cfs_rq *cfs_rq, int force);
-static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se);
+static void attach_entity_cfs_rq(struct sched_entity *se);
/*
* With new tasks being created, their initial util_avgs are extrapolated
@@ -742,7 +789,6 @@ void post_init_entity_util_avg(struct sched_entity *se)
struct cfs_rq *cfs_rq = cfs_rq_of(se);
struct sched_avg *sa = &se->avg;
long cap = (long)(SCHED_CAPACITY_SCALE - cfs_rq->avg.util_avg) / 2;
- u64 now = cfs_rq_clock_task(cfs_rq);
if (cap > 0) {
if (cfs_rq->avg.util_avg != 0) {
@@ -770,14 +816,12 @@ void post_init_entity_util_avg(struct sched_entity *se)
* such that the next switched_to_fair() has the
* expected state.
*/
- se->avg.last_update_time = now;
+ se->avg.last_update_time = cfs_rq_clock_task(cfs_rq);
return;
}
}
- update_cfs_rq_load_avg(now, cfs_rq, false);
- attach_entity_load_avg(cfs_rq, se);
- update_tg_load_avg(cfs_rq, false);
+ attach_entity_cfs_rq(se);
}
#else /* !CONFIG_SMP */
@@ -2890,6 +2934,26 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa,
return decayed;
}
+/*
+ * Signed add and clamp on underflow.
+ *
+ * Explicitly do a load-store to ensure the intermediate value never hits
+ * memory. This allows lockless observations without ever seeing the negative
+ * values.
+ */
+#define add_positive(_ptr, _val) do { \
+ typeof(_ptr) ptr = (_ptr); \
+ typeof(_val) val = (_val); \
+ typeof(*ptr) res, var = READ_ONCE(*ptr); \
+ \
+ res = var + val; \
+ \
+ if (val < 0 && res > var) \
+ res = 0; \
+ \
+ WRITE_ONCE(*ptr, res); \
+} while (0)
+
#ifdef CONFIG_FAIR_GROUP_SCHED
/**
* update_tg_load_avg - update the tg's load avg
@@ -2969,8 +3033,138 @@ void set_task_rq_fair(struct sched_entity *se,
se->avg.last_update_time = n_last_update_time;
}
}
+
+/* Take into account change of utilization of a child task group */
+static inline void
+update_tg_cfs_util(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ struct cfs_rq *gcfs_rq = group_cfs_rq(se);
+ long delta = gcfs_rq->avg.util_avg - se->avg.util_avg;
+
+ /* Nothing to update */
+ if (!delta)
+ return;
+
+ /* Set new sched_entity's utilization */
+ se->avg.util_avg = gcfs_rq->avg.util_avg;
+ se->avg.util_sum = se->avg.util_avg * LOAD_AVG_MAX;
+
+ /* Update parent cfs_rq utilization */
+ add_positive(&cfs_rq->avg.util_avg, delta);
+ cfs_rq->avg.util_sum = cfs_rq->avg.util_avg * LOAD_AVG_MAX;
+}
+
+/* Take into account change of load of a child task group */
+static inline void
+update_tg_cfs_load(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ struct cfs_rq *gcfs_rq = group_cfs_rq(se);
+ long delta, load = gcfs_rq->avg.load_avg;
+
+ /*
+ * If the load of group cfs_rq is null, the load of the
+ * sched_entity will also be null so we can skip the formula
+ */
+ if (load) {
+ long tg_load;
+
+ /* Get tg's load and ensure tg_load > 0 */
+ tg_load = atomic_long_read(&gcfs_rq->tg->load_avg) + 1;
+
+ /* Ensure tg_load >= load and updated with current load*/
+ tg_load -= gcfs_rq->tg_load_avg_contrib;
+ tg_load += load;
+
+ /*
+ * We need to compute a correction term in the case that the
+ * task group is consuming more CPU than a task of equal
+ * weight. A task with a weight equals to tg->shares will have
+ * a load less or equal to scale_load_down(tg->shares).
+ * Similarly, the sched_entities that represent the task group
+ * at parent level, can't have a load higher than
+ * scale_load_down(tg->shares). And the Sum of sched_entities'
+ * load must be <= scale_load_down(tg->shares).
+ */
+ if (tg_load > scale_load_down(gcfs_rq->tg->shares)) {
+ /* scale gcfs_rq's load into tg's shares*/
+ load *= scale_load_down(gcfs_rq->tg->shares);
+ load /= tg_load;
+ }
+ }
+
+ delta = load - se->avg.load_avg;
+
+ /* Nothing to update */
+ if (!delta)
+ return;
+
+ /* Set new sched_entity's load */
+ se->avg.load_avg = load;
+ se->avg.load_sum = se->avg.load_avg * LOAD_AVG_MAX;
+
+ /* Update parent cfs_rq load */
+ add_positive(&cfs_rq->avg.load_avg, delta);
+ cfs_rq->avg.load_sum = cfs_rq->avg.load_avg * LOAD_AVG_MAX;
+
+ /*
+ * If the sched_entity is already enqueued, we also have to update the
+ * runnable load avg.
+ */
+ if (se->on_rq) {
+ /* Update parent cfs_rq runnable_load_avg */
+ add_positive(&cfs_rq->runnable_load_avg, delta);
+ cfs_rq->runnable_load_sum = cfs_rq->runnable_load_avg * LOAD_AVG_MAX;
+ }
+}
+
+static inline void set_tg_cfs_propagate(struct cfs_rq *cfs_rq)
+{
+ cfs_rq->propagate_avg = 1;
+}
+
+static inline int test_and_clear_tg_cfs_propagate(struct sched_entity *se)
+{
+ struct cfs_rq *cfs_rq = group_cfs_rq(se);
+
+ if (!cfs_rq->propagate_avg)
+ return 0;
+
+ cfs_rq->propagate_avg = 0;
+ return 1;
+}
+
+/* Update task and its cfs_rq load average */
+static inline int propagate_entity_load_avg(struct sched_entity *se)
+{
+ struct cfs_rq *cfs_rq;
+
+ if (entity_is_task(se))
+ return 0;
+
+ if (!test_and_clear_tg_cfs_propagate(se))
+ return 0;
+
+ cfs_rq = cfs_rq_of(se);
+
+ set_tg_cfs_propagate(cfs_rq);
+
+ update_tg_cfs_util(cfs_rq, se);
+ update_tg_cfs_load(cfs_rq, se);
+
+ return 1;
+}
+
#else /* CONFIG_FAIR_GROUP_SCHED */
+
static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {}
+
+static inline int propagate_entity_load_avg(struct sched_entity *se)
+{
+ return 0;
+}
+
+static inline void set_tg_cfs_propagate(struct cfs_rq *cfs_rq) {}
+
#endif /* CONFIG_FAIR_GROUP_SCHED */
static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
@@ -3041,6 +3235,7 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
sub_positive(&sa->load_avg, r);
sub_positive(&sa->load_sum, r * LOAD_AVG_MAX);
removed_load = 1;
+ set_tg_cfs_propagate(cfs_rq);
}
if (atomic_long_read(&cfs_rq->removed_util_avg)) {
@@ -3048,6 +3243,7 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
sub_positive(&sa->util_avg, r);
sub_positive(&sa->util_sum, r * LOAD_AVG_MAX);
removed_util = 1;
+ set_tg_cfs_propagate(cfs_rq);
}
decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
@@ -3064,23 +3260,35 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
return decayed || removed_load;
}
+/*
+ * Optional action to be done while updating the load average
+ */
+#define UPDATE_TG 0x1
+#define SKIP_AGE_LOAD 0x2
+
/* Update task and its cfs_rq load average */
-static inline void update_load_avg(struct sched_entity *se, int update_tg)
+static inline void update_load_avg(struct sched_entity *se, int flags)
{
struct cfs_rq *cfs_rq = cfs_rq_of(se);
u64 now = cfs_rq_clock_task(cfs_rq);
struct rq *rq = rq_of(cfs_rq);
int cpu = cpu_of(rq);
+ int decayed;
/*
* Track task load average for carrying it to new CPU after migrated, and
* track group sched_entity load average for task_h_load calc in migration
*/
- __update_load_avg(now, cpu, &se->avg,
+ if (se->avg.last_update_time && !(flags & SKIP_AGE_LOAD)) {
+ __update_load_avg(now, cpu, &se->avg,
se->on_rq * scale_load_down(se->load.weight),
cfs_rq->curr == se, NULL);
+ }
- if (update_cfs_rq_load_avg(now, cfs_rq, true) && update_tg)
+ decayed = update_cfs_rq_load_avg(now, cfs_rq, true);
+ decayed |= propagate_entity_load_avg(se);
+
+ if (decayed && (flags & UPDATE_TG))
update_tg_load_avg(cfs_rq, 0);
}
@@ -3094,31 +3302,12 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg)
*/
static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
- if (!sched_feat(ATTACH_AGE_LOAD))
- goto skip_aging;
-
- /*
- * If we got migrated (either between CPUs or between cgroups) we'll
- * have aged the average right before clearing @last_update_time.
- *
- * Or we're fresh through post_init_entity_util_avg().
- */
- if (se->avg.last_update_time) {
- __update_load_avg(cfs_rq->avg.last_update_time, cpu_of(rq_of(cfs_rq)),
- &se->avg, 0, 0, NULL);
-
- /*
- * XXX: we could have just aged the entire load away if we've been
- * absent from the fair class for too long.
- */
- }
-
-skip_aging:
se->avg.last_update_time = cfs_rq->avg.last_update_time;
cfs_rq->avg.load_avg += se->avg.load_avg;
cfs_rq->avg.load_sum += se->avg.load_sum;
cfs_rq->avg.util_avg += se->avg.util_avg;
cfs_rq->avg.util_sum += se->avg.util_sum;
+ set_tg_cfs_propagate(cfs_rq);
cfs_rq_util_change(cfs_rq);
}
@@ -3133,14 +3322,12 @@ skip_aging:
*/
static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
- __update_load_avg(cfs_rq->avg.last_update_time, cpu_of(rq_of(cfs_rq)),
- &se->avg, se->on_rq * scale_load_down(se->load.weight),
- cfs_rq->curr == se, NULL);
sub_positive(&cfs_rq->avg.load_avg, se->avg.load_avg);
sub_positive(&cfs_rq->avg.load_sum, se->avg.load_sum);
sub_positive(&cfs_rq->avg.util_avg, se->avg.util_avg);
sub_positive(&cfs_rq->avg.util_sum, se->avg.util_sum);
+ set_tg_cfs_propagate(cfs_rq);
cfs_rq_util_change(cfs_rq);
}
@@ -3150,34 +3337,20 @@ static inline void
enqueue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
struct sched_avg *sa = &se->avg;
- u64 now = cfs_rq_clock_task(cfs_rq);
- int migrated, decayed;
-
- migrated = !sa->last_update_time;
- if (!migrated) {
- __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
- se->on_rq * scale_load_down(se->load.weight),
- cfs_rq->curr == se, NULL);
- }
-
- decayed = update_cfs_rq_load_avg(now, cfs_rq, !migrated);
cfs_rq->runnable_load_avg += sa->load_avg;
cfs_rq->runnable_load_sum += sa->load_sum;
- if (migrated)
+ if (!sa->last_update_time) {
attach_entity_load_avg(cfs_rq, se);
-
- if (decayed || migrated)
update_tg_load_avg(cfs_rq, 0);
+ }
}
/* Remove the runnable load generated by se from cfs_rq's runnable load average */
static inline void
dequeue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
- update_load_avg(se, 1);
-
cfs_rq->runnable_load_avg =
max_t(long, cfs_rq->runnable_load_avg - se->avg.load_avg, 0);
cfs_rq->runnable_load_sum =
@@ -3206,13 +3379,25 @@ static inline u64 cfs_rq_last_update_time(struct cfs_rq *cfs_rq)
#endif
/*
+ * Synchronize entity load avg of dequeued entity without locking
+ * the previous rq.
+ */
+void sync_entity_load_avg(struct sched_entity *se)
+{
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
+ u64 last_update_time;
+
+ last_update_time = cfs_rq_last_update_time(cfs_rq);
+ __update_load_avg(last_update_time, cpu_of(rq_of(cfs_rq)), &se->avg, 0, 0, NULL);
+}
+
+/*
* Task first catches up with cfs_rq, and then subtract
* itself from the cfs_rq (task must be off the queue now).
*/
void remove_entity_load_avg(struct sched_entity *se)
{
struct cfs_rq *cfs_rq = cfs_rq_of(se);
- u64 last_update_time;
/*
* tasks cannot exit without having gone through wake_up_new_task() ->
@@ -3224,9 +3409,7 @@ void remove_entity_load_avg(struct sched_entity *se)
* calls this.
*/
- last_update_time = cfs_rq_last_update_time(cfs_rq);
-
- __update_load_avg(last_update_time, cpu_of(rq_of(cfs_rq)), &se->avg, 0, 0, NULL);
+ sync_entity_load_avg(se);
atomic_long_add(se->avg.load_avg, &cfs_rq->removed_load_avg);
atomic_long_add(se->avg.util_avg, &cfs_rq->removed_util_avg);
}
@@ -3251,7 +3434,10 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
return 0;
}
-static inline void update_load_avg(struct sched_entity *se, int not_used)
+#define UPDATE_TG 0x0
+#define SKIP_AGE_LOAD 0x0
+
+static inline void update_load_avg(struct sched_entity *se, int not_used1)
{
cpufreq_update_util(rq_of(cfs_rq_of(se)), 0);
}
@@ -3396,6 +3582,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
if (renorm && !curr)
se->vruntime += cfs_rq->min_vruntime;
+ update_load_avg(se, UPDATE_TG);
enqueue_entity_load_avg(cfs_rq, se);
account_entity_enqueue(cfs_rq, se);
update_cfs_shares(cfs_rq);
@@ -3470,6 +3657,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
* Update run-time statistics of the 'current'.
*/
update_curr(cfs_rq);
+ update_load_avg(se, UPDATE_TG);
dequeue_entity_load_avg(cfs_rq, se);
update_stats_dequeue(cfs_rq, se, flags);
@@ -3557,7 +3745,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
*/
update_stats_wait_end(cfs_rq, se);
__dequeue_entity(cfs_rq, se);
- update_load_avg(se, 1);
+ update_load_avg(se, UPDATE_TG);
}
update_stats_curr_start(cfs_rq, se);
@@ -3675,7 +3863,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
/*
* Ensure that runnable average is periodically updated.
*/
- update_load_avg(curr, 1);
+ update_load_avg(curr, UPDATE_TG);
update_cfs_shares(cfs_rq);
#ifdef CONFIG_SCHED_HRTICK
@@ -4572,7 +4760,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (cfs_rq_throttled(cfs_rq))
break;
- update_load_avg(se, 1);
+ update_load_avg(se, UPDATE_TG);
update_cfs_shares(cfs_rq);
}
@@ -4631,7 +4819,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (cfs_rq_throttled(cfs_rq))
break;
- update_load_avg(se, 1);
+ update_load_avg(se, UPDATE_TG);
update_cfs_shares(cfs_rq);
}
@@ -5199,6 +5387,14 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
return 1;
}
+static inline int task_util(struct task_struct *p);
+static int cpu_util_wake(int cpu, struct task_struct *p);
+
+static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+{
+ return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
+}
+
/*
* find_idlest_group finds and returns the least busy CPU group within the
* domain.
@@ -5208,15 +5404,21 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
int this_cpu, int sd_flag)
{
struct sched_group *idlest = NULL, *group = sd->groups;
- unsigned long min_load = ULONG_MAX, this_load = 0;
+ struct sched_group *most_spare_sg = NULL;
+ unsigned long min_runnable_load = ULONG_MAX, this_runnable_load = 0;
+ unsigned long min_avg_load = ULONG_MAX, this_avg_load = 0;
+ unsigned long most_spare = 0, this_spare = 0;
int load_idx = sd->forkexec_idx;
- int imbalance = 100 + (sd->imbalance_pct-100)/2;
+ int imbalance_scale = 100 + (sd->imbalance_pct-100)/2;
+ unsigned long imbalance = scale_load_down(NICE_0_LOAD) *
+ (sd->imbalance_pct-100) / 100;
if (sd_flag & SD_BALANCE_WAKE)
load_idx = sd->wake_idx;
do {
- unsigned long load, avg_load;
+ unsigned long load, avg_load, runnable_load;
+ unsigned long spare_cap, max_spare_cap;
int local_group;
int i;
@@ -5228,8 +5430,13 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
local_group = cpumask_test_cpu(this_cpu,
sched_group_cpus(group));
- /* Tally up the load of all CPUs in the group */
+ /*
+ * Tally up the load of all CPUs in the group and find
+ * the group containing the CPU with most spare capacity.
+ */
avg_load = 0;
+ runnable_load = 0;
+ max_spare_cap = 0;
for_each_cpu(i, sched_group_cpus(group)) {
/* Bias balancing toward cpus of our domain */
@@ -5238,22 +5445,84 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
else
load = target_load(i, load_idx);
- avg_load += load;
+ runnable_load += load;
+
+ avg_load += cfs_rq_load_avg(&cpu_rq(i)->cfs);
+
+ spare_cap = capacity_spare_wake(i, p);
+
+ if (spare_cap > max_spare_cap)
+ max_spare_cap = spare_cap;
}
/* Adjust by relative CPU capacity of the group */
- avg_load = (avg_load * SCHED_CAPACITY_SCALE) / group->sgc->capacity;
+ avg_load = (avg_load * SCHED_CAPACITY_SCALE) /
+ group->sgc->capacity;
+ runnable_load = (runnable_load * SCHED_CAPACITY_SCALE) /
+ group->sgc->capacity;
if (local_group) {
- this_load = avg_load;
- } else if (avg_load < min_load) {
- min_load = avg_load;
- idlest = group;
+ this_runnable_load = runnable_load;
+ this_avg_load = avg_load;
+ this_spare = max_spare_cap;
+ } else {
+ if (min_runnable_load > (runnable_load + imbalance)) {
+ /*
+ * The runnable load is significantly smaller
+ * so we can pick this new cpu
+ */
+ min_runnable_load = runnable_load;
+ min_avg_load = avg_load;
+ idlest = group;
+ } else if ((runnable_load < (min_runnable_load + imbalance)) &&
+ (100*min_avg_load > imbalance_scale*avg_load)) {
+ /*
+ * The runnable loads are close so take the
+ * blocked load into account through avg_load.
+ */
+ min_avg_load = avg_load;
+ idlest = group;
+ }
+
+ if (most_spare < max_spare_cap) {
+ most_spare = max_spare_cap;
+ most_spare_sg = group;
+ }
}
} while (group = group->next, group != sd->groups);
- if (!idlest || 100*this_load < imbalance*min_load)
+ /*
+ * The cross-over point between using spare capacity or least load
+ * is too conservative for high utilization tasks on partially
+ * utilized systems if we require spare_capacity > task_util(p),
+ * so we allow for some task stuffing by using
+ * spare_capacity > task_util(p)/2.
+ *
+ * Spare capacity can't be used for fork because the utilization has
+ * not been set yet, we must first select a rq to compute the initial
+ * utilization.
+ */
+ if (sd_flag & SD_BALANCE_FORK)
+ goto skip_spare;
+
+ if (this_spare > task_util(p) / 2 &&
+ imbalance_scale*this_spare > 100*most_spare)
+ return NULL;
+
+ if (most_spare > task_util(p) / 2)
+ return most_spare_sg;
+
+skip_spare:
+ if (!idlest)
+ return NULL;
+
+ if (min_runnable_load > (this_runnable_load + imbalance))
return NULL;
+
+ if ((this_runnable_load < (min_runnable_load + imbalance)) &&
+ (100*this_avg_load < imbalance_scale*min_avg_load))
+ return NULL;
+
return idlest;
}
@@ -5590,6 +5859,24 @@ static inline int task_util(struct task_struct *p)
}
/*
+ * cpu_util_wake: Compute cpu utilization with any contributions from
+ * the waking task p removed.
+ */
+static int cpu_util_wake(int cpu, struct task_struct *p)
+{
+ unsigned long util, capacity;
+
+ /* Task has no contribution or is new */
+ if (cpu != task_cpu(p) || !p->se.avg.last_update_time)
+ return cpu_util(cpu);
+
+ capacity = capacity_orig_of(cpu);
+ util = max_t(long, cpu_rq(cpu)->cfs.avg.util_avg - task_util(p), 0);
+
+ return (util >= capacity) ? capacity : util;
+}
+
+/*
* Disable WAKE_AFFINE in the case where task @p doesn't fit in the
* capacity of either the waking CPU @cpu or the previous CPU @prev_cpu.
*
@@ -5607,6 +5894,9 @@ static int wake_cap(struct task_struct *p, int cpu, int prev_cpu)
if (max_cap - min_cap < max_cap >> 3)
return 0;
+ /* Bring task utilization in sync with prev_cpu */
+ sync_entity_load_avg(&p->se);
+
return min_cap * 1024 < task_util(p) * capacity_margin;
}
@@ -6641,6 +6931,10 @@ static void update_blocked_averages(int cpu)
if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true))
update_tg_load_avg(cfs_rq, 0);
+
+ /* Propagate pending load changes to the parent */
+ if (cfs_rq->tg->se[cpu])
+ update_load_avg(cfs_rq->tg->se[cpu], 0);
}
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
@@ -6845,13 +7139,14 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
cpu_rq(cpu)->cpu_capacity = capacity;
sdg->sgc->capacity = capacity;
+ sdg->sgc->min_capacity = capacity;
}
void update_group_capacity(struct sched_domain *sd, int cpu)
{
struct sched_domain *child = sd->child;
struct sched_group *group, *sdg = sd->groups;
- unsigned long capacity;
+ unsigned long capacity, min_capacity;
unsigned long interval;
interval = msecs_to_jiffies(sd->balance_interval);
@@ -6864,6 +7159,7 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
}
capacity = 0;
+ min_capacity = ULONG_MAX;
if (child->flags & SD_OVERLAP) {
/*
@@ -6888,11 +7184,12 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
*/
if (unlikely(!rq->sd)) {
capacity += capacity_of(cpu);
- continue;
+ } else {
+ sgc = rq->sd->groups->sgc;
+ capacity += sgc->capacity;
}
- sgc = rq->sd->groups->sgc;
- capacity += sgc->capacity;
+ min_capacity = min(capacity, min_capacity);
}
} else {
/*
@@ -6902,12 +7199,16 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
group = child->groups;
do {
- capacity += group->sgc->capacity;
+ struct sched_group_capacity *sgc = group->sgc;
+
+ capacity += sgc->capacity;
+ min_capacity = min(sgc->min_capacity, min_capacity);
group = group->next;
} while (group != child->groups);
}
sdg->sgc->capacity = capacity;
+ sdg->sgc->min_capacity = min_capacity;
}
/*
@@ -6930,8 +7231,8 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd)
* cpumask covering 1 cpu of the first group and 3 cpus of the second group.
* Something like:
*
- * { 0 1 2 3 } { 4 5 6 7 }
- * * * * *
+ * { 0 1 2 3 } { 4 5 6 7 }
+ * * * * *
*
* If we were to balance group-wise we'd place two tasks in the first group and
* two tasks in the second group. Clearly this is undesired as it will overload
@@ -7002,6 +7303,17 @@ group_is_overloaded(struct lb_env *env, struct sg_lb_stats *sgs)
return false;
}
+/*
+ * group_smaller_cpu_capacity: Returns true if sched_group sg has smaller
+ * per-CPU capacity than sched_group ref.
+ */
+static inline bool
+group_smaller_cpu_capacity(struct sched_group *sg, struct sched_group *ref)
+{
+ return sg->sgc->min_capacity * capacity_margin <
+ ref->sgc->min_capacity * 1024;
+}
+
static inline enum
group_type group_classify(struct sched_group *group,
struct sg_lb_stats *sgs)
@@ -7105,6 +7417,20 @@ static bool update_sd_pick_busiest(struct lb_env *env,
if (sgs->avg_load <= busiest->avg_load)
return false;
+ if (!(env->sd->flags & SD_ASYM_CPUCAPACITY))
+ goto asym_packing;
+
+ /*
+ * Candidate sg has no more than one task per CPU and
+ * has higher per-CPU capacity. Migrating tasks to less
+ * capable CPUs may harm throughput. Maximize throughput,
+ * power/energy consequences are not considered.
+ */
+ if (sgs->sum_nr_running <= sgs->group_weight &&
+ group_smaller_cpu_capacity(sds->local, sg))
+ return false;
+
+asym_packing:
/* This is the busiest node in its class. */
if (!(env->sd->flags & SD_ASYM_PACKING))
return true;
@@ -7113,16 +7439,18 @@ static bool update_sd_pick_busiest(struct lb_env *env,
if (env->idle == CPU_NOT_IDLE)
return true;
/*
- * ASYM_PACKING needs to move all the work to the lowest
- * numbered CPUs in the group, therefore mark all groups
- * higher than ourself as busy.
+ * ASYM_PACKING needs to move all the work to the highest
+ * prority CPUs in the group, therefore mark all groups
+ * of lower priority than ourself as busy.
*/
- if (sgs->sum_nr_running && env->dst_cpu < group_first_cpu(sg)) {
+ if (sgs->sum_nr_running &&
+ sched_asym_prefer(env->dst_cpu, sg->asym_prefer_cpu)) {
if (!sds->busiest)
return true;
- /* Prefer to move from highest possible cpu's work */
- if (group_first_cpu(sds->busiest) < group_first_cpu(sg))
+ /* Prefer to move from lowest priority cpu's work */
+ if (sched_asym_prefer(sds->busiest->asym_prefer_cpu,
+ sg->asym_prefer_cpu))
return true;
}
@@ -7274,8 +7602,8 @@ static int check_asym_packing(struct lb_env *env, struct sd_lb_stats *sds)
if (!sds->busiest)
return 0;
- busiest_cpu = group_first_cpu(sds->busiest);
- if (env->dst_cpu > busiest_cpu)
+ busiest_cpu = sds->busiest->asym_prefer_cpu;
+ if (sched_asym_prefer(busiest_cpu, env->dst_cpu))
return 0;
env->imbalance = DIV_ROUND_CLOSEST(
@@ -7613,10 +7941,11 @@ static int need_active_balance(struct lb_env *env)
/*
* ASYM_PACKING needs to force migrate tasks from busy but
- * higher numbered CPUs in order to pack all tasks in the
- * lowest numbered CPUs.
+ * lower priority CPUs in order to pack all tasks in the
+ * highest priority CPUs.
*/
- if ((sd->flags & SD_ASYM_PACKING) && env->src_cpu > env->dst_cpu)
+ if ((sd->flags & SD_ASYM_PACKING) &&
+ sched_asym_prefer(env->dst_cpu, env->src_cpu))
return 1;
}
@@ -8465,7 +8794,7 @@ static inline bool nohz_kick_needed(struct rq *rq)
unsigned long now = jiffies;
struct sched_domain_shared *sds;
struct sched_domain *sd;
- int nr_busy, cpu = rq->cpu;
+ int nr_busy, i, cpu = rq->cpu;
bool kick = false;
if (unlikely(rq->idle_balance))
@@ -8516,12 +8845,18 @@ static inline bool nohz_kick_needed(struct rq *rq)
}
sd = rcu_dereference(per_cpu(sd_asym, cpu));
- if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
- sched_domain_span(sd)) < cpu)) {
- kick = true;
- goto unlock;
- }
+ if (sd) {
+ for_each_cpu(i, sched_domain_span(sd)) {
+ if (i == cpu ||
+ !cpumask_test_cpu(i, nohz.idle_cpus_mask))
+ continue;
+ if (sched_asym_prefer(i, cpu)) {
+ kick = true;
+ goto unlock;
+ }
+ }
+ }
unlock:
rcu_read_unlock();
return kick;
@@ -8687,32 +9022,45 @@ static inline bool vruntime_normalized(struct task_struct *p)
return false;
}
-static void detach_task_cfs_rq(struct task_struct *p)
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/*
+ * Propagate the changes of the sched_entity across the tg tree to make it
+ * visible to the root
+ */
+static void propagate_entity_cfs_rq(struct sched_entity *se)
{
- struct sched_entity *se = &p->se;
- struct cfs_rq *cfs_rq = cfs_rq_of(se);
- u64 now = cfs_rq_clock_task(cfs_rq);
+ struct cfs_rq *cfs_rq;
- if (!vruntime_normalized(p)) {
- /*
- * Fix up our vruntime so that the current sleep doesn't
- * cause 'unlimited' sleep bonus.
- */
- place_entity(cfs_rq, se, 0);
- se->vruntime -= cfs_rq->min_vruntime;
+ /* Start to propagate at parent */
+ se = se->parent;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+
+ if (cfs_rq_throttled(cfs_rq))
+ break;
+
+ update_load_avg(se, UPDATE_TG);
}
+}
+#else
+static void propagate_entity_cfs_rq(struct sched_entity *se) { }
+#endif
+
+static void detach_entity_cfs_rq(struct sched_entity *se)
+{
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
/* Catch up with the cfs_rq and remove our load when we leave */
- update_cfs_rq_load_avg(now, cfs_rq, false);
+ update_load_avg(se, 0);
detach_entity_load_avg(cfs_rq, se);
update_tg_load_avg(cfs_rq, false);
+ propagate_entity_cfs_rq(se);
}
-static void attach_task_cfs_rq(struct task_struct *p)
+static void attach_entity_cfs_rq(struct sched_entity *se)
{
- struct sched_entity *se = &p->se;
struct cfs_rq *cfs_rq = cfs_rq_of(se);
- u64 now = cfs_rq_clock_task(cfs_rq);
#ifdef CONFIG_FAIR_GROUP_SCHED
/*
@@ -8722,10 +9070,36 @@ static void attach_task_cfs_rq(struct task_struct *p)
se->depth = se->parent ? se->parent->depth + 1 : 0;
#endif
- /* Synchronize task with its cfs_rq */
- update_cfs_rq_load_avg(now, cfs_rq, false);
+ /* Synchronize entity with its cfs_rq */
+ update_load_avg(se, sched_feat(ATTACH_AGE_LOAD) ? 0 : SKIP_AGE_LOAD);
attach_entity_load_avg(cfs_rq, se);
update_tg_load_avg(cfs_rq, false);
+ propagate_entity_cfs_rq(se);
+}
+
+static void detach_task_cfs_rq(struct task_struct *p)
+{
+ struct sched_entity *se = &p->se;
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+ if (!vruntime_normalized(p)) {
+ /*
+ * Fix up our vruntime so that the current sleep doesn't
+ * cause 'unlimited' sleep bonus.
+ */
+ place_entity(cfs_rq, se, 0);
+ se->vruntime -= cfs_rq->min_vruntime;
+ }
+
+ detach_entity_cfs_rq(se);
+}
+
+static void attach_task_cfs_rq(struct task_struct *p)
+{
+ struct sched_entity *se = &p->se;
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+ attach_entity_cfs_rq(se);
if (!vruntime_normalized(p))
se->vruntime += cfs_rq->min_vruntime;
@@ -8779,6 +9153,9 @@ void init_cfs_rq(struct cfs_rq *cfs_rq)
cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
#endif
#ifdef CONFIG_SMP
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ cfs_rq->propagate_avg = 0;
+#endif
atomic_long_set(&cfs_rq->removed_load_avg, 0);
atomic_long_set(&cfs_rq->removed_util_avg, 0);
#endif
@@ -8887,7 +9264,7 @@ void online_fair_sched_group(struct task_group *tg)
se = tg->se[i];
raw_spin_lock_irq(&rq->lock);
- post_init_entity_util_avg(se);
+ attach_entity_cfs_rq(se);
sync_throttle(tg, i);
raw_spin_unlock_irq(&rq->lock);
}
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 1d8718d5300d..6a4bae0a649d 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -164,11 +164,14 @@ static void cpuidle_idle_call(void)
* timekeeping to prevent timer interrupts from kicking us out of idle
* until a proper wakeup interrupt happens.
*/
- if (idle_should_freeze()) {
- entered_state = cpuidle_enter_freeze(drv, dev);
- if (entered_state > 0) {
- local_irq_enable();
- goto exit_idle;
+
+ if (idle_should_freeze() || dev->use_deepest_state) {
+ if (idle_should_freeze()) {
+ entered_state = cpuidle_enter_freeze(drv, dev);
+ if (entered_state > 0) {
+ local_irq_enable();
+ goto exit_idle;
+ }
}
next_state = cpuidle_find_deepest_state(drv, dev);
@@ -202,76 +205,65 @@ exit_idle:
*
* Called with polling cleared.
*/
-static void cpu_idle_loop(void)
+static void do_idle(void)
{
- int cpu = smp_processor_id();
-
- while (1) {
- /*
- * If the arch has a polling bit, we maintain an invariant:
- *
- * Our polling bit is clear if we're not scheduled (i.e. if
- * rq->curr != rq->idle). This means that, if rq->idle has
- * the polling bit set, then setting need_resched is
- * guaranteed to cause the cpu to reschedule.
- */
-
- __current_set_polling();
- quiet_vmstat();
- tick_nohz_idle_enter();
+ /*
+ * If the arch has a polling bit, we maintain an invariant:
+ *
+ * Our polling bit is clear if we're not scheduled (i.e. if rq->curr !=
+ * rq->idle). This means that, if rq->idle has the polling bit set,
+ * then setting need_resched is guaranteed to cause the CPU to
+ * reschedule.
+ */
- while (!need_resched()) {
- check_pgt_cache();
- rmb();
+ __current_set_polling();
+ tick_nohz_idle_enter();
- if (cpu_is_offline(cpu)) {
- cpuhp_report_idle_dead();
- arch_cpu_idle_dead();
- }
+ while (!need_resched()) {
+ check_pgt_cache();
+ rmb();
- local_irq_disable();
- arch_cpu_idle_enter();
-
- /*
- * In poll mode we reenable interrupts and spin.
- *
- * Also if we detected in the wakeup from idle
- * path that the tick broadcast device expired
- * for us, we don't want to go deep idle as we
- * know that the IPI is going to arrive right
- * away
- */
- if (cpu_idle_force_poll || tick_check_broadcast_expired())
- cpu_idle_poll();
- else
- cpuidle_idle_call();
-
- arch_cpu_idle_exit();
+ if (cpu_is_offline(smp_processor_id())) {
+ cpuhp_report_idle_dead();
+ arch_cpu_idle_dead();
}
- /*
- * Since we fell out of the loop above, we know
- * TIF_NEED_RESCHED must be set, propagate it into
- * PREEMPT_NEED_RESCHED.
- *
- * This is required because for polling idle loops we will
- * not have had an IPI to fold the state for us.
- */
- preempt_set_need_resched();
- tick_nohz_idle_exit();
- __current_clr_polling();
+ local_irq_disable();
+ arch_cpu_idle_enter();
/*
- * We promise to call sched_ttwu_pending and reschedule
- * if need_resched is set while polling is set. That
- * means that clearing polling needs to be visible
- * before doing these things.
+ * In poll mode we reenable interrupts and spin. Also if we
+ * detected in the wakeup from idle path that the tick
+ * broadcast device expired for us, we don't want to go deep
+ * idle as we know that the IPI is going to arrive right away.
*/
- smp_mb__after_atomic();
-
- sched_ttwu_pending();
- schedule_preempt_disabled();
+ if (cpu_idle_force_poll || tick_check_broadcast_expired())
+ cpu_idle_poll();
+ else
+ cpuidle_idle_call();
+ arch_cpu_idle_exit();
}
+
+ /*
+ * Since we fell out of the loop above, we know TIF_NEED_RESCHED must
+ * be set, propagate it into PREEMPT_NEED_RESCHED.
+ *
+ * This is required because for polling idle loops we will not have had
+ * an IPI to fold the state for us.
+ */
+ preempt_set_need_resched();
+ tick_nohz_idle_exit();
+ __current_clr_polling();
+
+ /*
+ * We promise to call sched_ttwu_pending() and reschedule if
+ * need_resched() is set while polling is set. That means that clearing
+ * polling needs to be visible before doing these things.
+ */
+ smp_mb__after_atomic();
+
+ sched_ttwu_pending();
+ schedule_preempt_disabled();
}
bool cpu_in_idle(unsigned long pc)
@@ -280,6 +272,56 @@ bool cpu_in_idle(unsigned long pc)
pc < (unsigned long)__cpuidle_text_end;
}
+struct idle_timer {
+ struct hrtimer timer;
+ int done;
+};
+
+static enum hrtimer_restart idle_inject_timer_fn(struct hrtimer *timer)
+{
+ struct idle_timer *it = container_of(timer, struct idle_timer, timer);
+
+ WRITE_ONCE(it->done, 1);
+ set_tsk_need_resched(current);
+
+ return HRTIMER_NORESTART;
+}
+
+void play_idle(unsigned long duration_ms)
+{
+ struct idle_timer it;
+
+ /*
+ * Only FIFO tasks can disable the tick since they don't need the forced
+ * preemption.
+ */
+ WARN_ON_ONCE(current->policy != SCHED_FIFO);
+ WARN_ON_ONCE(current->nr_cpus_allowed != 1);
+ WARN_ON_ONCE(!(current->flags & PF_KTHREAD));
+ WARN_ON_ONCE(!(current->flags & PF_NO_SETAFFINITY));
+ WARN_ON_ONCE(!duration_ms);
+
+ rcu_sleep_check();
+ preempt_disable();
+ current->flags |= PF_IDLE;
+ cpuidle_use_deepest_state(true);
+
+ it.done = 0;
+ hrtimer_init_on_stack(&it.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ it.timer.function = idle_inject_timer_fn;
+ hrtimer_start(&it.timer, ms_to_ktime(duration_ms), HRTIMER_MODE_REL_PINNED);
+
+ while (!READ_ONCE(it.done))
+ do_idle();
+
+ cpuidle_use_deepest_state(false);
+ current->flags &= ~PF_IDLE;
+
+ preempt_fold_need_resched();
+ preempt_enable();
+}
+EXPORT_SYMBOL_GPL(play_idle);
+
void cpu_startup_entry(enum cpuhp_state state)
{
/*
@@ -299,5 +341,6 @@ void cpu_startup_entry(enum cpuhp_state state)
#endif
arch_cpu_idle_prepare();
cpuhp_online_idle(state);
- cpu_idle_loop();
+ while (1)
+ do_idle();
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 055f935d4421..7b34c7826ca5 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -404,6 +404,7 @@ struct cfs_rq {
unsigned long runnable_load_avg;
#ifdef CONFIG_FAIR_GROUP_SCHED
unsigned long tg_load_avg_contrib;
+ unsigned long propagate_avg;
#endif
atomic_long_t removed_load_avg, removed_util_avg;
#ifndef CONFIG_64BIT
@@ -539,6 +540,11 @@ struct dl_rq {
#ifdef CONFIG_SMP
+static inline bool sched_asym_prefer(int a, int b)
+{
+ return arch_asym_cpu_priority(a) > arch_asym_cpu_priority(b);
+}
+
/*
* We add the notion of a root-domain which will be used to define per-domain
* variables. Each exclusive cpuset essentially defines an island domain by
@@ -623,6 +629,7 @@ struct rq {
#ifdef CONFIG_FAIR_GROUP_SCHED
/* list of leaf cfs_rq on this cpu: */
struct list_head leaf_cfs_rq_list;
+ struct list_head *tmp_alone_branch;
#endif /* CONFIG_FAIR_GROUP_SCHED */
/*
@@ -892,7 +899,8 @@ struct sched_group_capacity {
* CPU capacity of this group, SCHED_CAPACITY_SCALE being max capacity
* for a single CPU.
*/
- unsigned int capacity;
+ unsigned long capacity;
+ unsigned long min_capacity; /* Min per-CPU capacity in group */
unsigned long next_update;
int imbalance; /* XXX unrelated to capacity but shared group state */
@@ -905,6 +913,7 @@ struct sched_group {
unsigned int group_weight;
struct sched_group_capacity *sgc;
+ int asym_prefer_cpu; /* cpu of highest priority in group */
/*
* The CPUs this group covers.
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 0db7c8a2afe2..bff9c774987a 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -195,7 +195,7 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd)
* value always takes priority (ignoring the DATA).
*/
for (; f; f = f->prev) {
- u32 cur_ret = BPF_PROG_RUN(f->prog, (void *)sd);
+ u32 cur_ret = BPF_PROG_RUN(f->prog, sd);
if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION))
ret = cur_ret;
diff --git a/kernel/signal.c b/kernel/signal.c
index 75761acc77cf..29a410780aa9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -427,6 +427,7 @@ void flush_signals(struct task_struct *t)
spin_unlock_irqrestore(&t->sighand->siglock, flags);
}
+#ifdef CONFIG_POSIX_TIMERS
static void __flush_itimer_signals(struct sigpending *pending)
{
sigset_t signal, retain;
@@ -460,6 +461,7 @@ void flush_itimer_signals(void)
__flush_itimer_signals(&tsk->signal->shared_pending);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
}
+#endif
void ignore_signals(struct task_struct *t)
{
@@ -567,6 +569,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
if (!signr) {
signr = __dequeue_signal(&tsk->signal->shared_pending,
mask, info);
+#ifdef CONFIG_POSIX_TIMERS
/*
* itimer signal ?
*
@@ -590,6 +593,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
hrtimer_restart(tmr);
}
}
+#endif
}
recalc_sigpending();
@@ -611,6 +615,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
*/
current->jobctl |= JOBCTL_STOP_DEQUEUED;
}
+#ifdef CONFIG_POSIX_TIMERS
if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
/*
* Release the siglock to ensure proper locking order
@@ -622,6 +627,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
do_schedule_next_timer(info);
spin_lock(&tsk->sighand->siglock);
}
+#endif
return signr;
}
diff --git a/kernel/smp.c b/kernel/smp.c
index bba3b201668d..77fcdb9f2775 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -3,6 +3,9 @@
*
* (C) Jens Axboe <jens.axboe@oracle.com> 2008
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/irq_work.h>
#include <linux/rcupdate.h>
#include <linux/rculist.h>
@@ -543,19 +546,17 @@ void __init setup_nr_cpu_ids(void)
nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
}
-void __weak smp_announce(void)
-{
- printk(KERN_INFO "Brought up %d CPUs\n", num_online_cpus());
-}
-
/* Called by boot processor to activate the rest. */
void __init smp_init(void)
{
+ int num_nodes, num_cpus;
unsigned int cpu;
idle_threads_init();
cpuhp_threads_init();
+ pr_info("Bringing up secondary CPUs ...\n");
+
/* FIXME: This should be done in userspace --RR */
for_each_present_cpu(cpu) {
if (num_online_cpus() >= setup_max_cpus)
@@ -564,8 +565,13 @@ void __init smp_init(void)
cpu_up(cpu);
}
+ num_nodes = num_online_nodes();
+ num_cpus = num_online_cpus();
+ pr_info("Brought up %d node%s, %d CPU%s\n",
+ num_nodes, (num_nodes > 1 ? "s" : ""),
+ num_cpus, (num_cpus > 1 ? "s" : ""));
+
/* Any cleanup work */
- smp_announce();
smp_cpus_done(setup_max_cpus);
}
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index ec9ab2f01489..1eb82661ecdb 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -194,7 +194,7 @@ static int multi_cpu_stop(void *data)
/* Simple state machine */
do {
/* Chill out and ensure we re-read multi_stop_state. */
- cpu_relax();
+ cpu_relax_yield();
if (msdata->state != curstate) {
curstate = msdata->state;
switch (curstate) {
diff --git a/kernel/sys.c b/kernel/sys.c
index 89d5be418157..9758892a2d09 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1416,7 +1416,8 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
* applications, so we live with it
*/
if (!retval && new_rlim && resource == RLIMIT_CPU &&
- new_rlim->rlim_cur != RLIM_INFINITY)
+ new_rlim->rlim_cur != RLIM_INFINITY &&
+ IS_ENABLED(CONFIG_POSIX_TIMERS))
update_rlimit_cpu(tsk, new_rlim->rlim_cur);
out:
read_unlock(&tasklist_lock);
@@ -1696,16 +1697,6 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
fput(exe_file);
}
- /*
- * The symlink can be changed only once, just to disallow arbitrary
- * transitions malicious software might bring in. This means one
- * could make a snapshot over all processes running and monitor
- * /proc/pid/exe changes to notice unusual activity if needed.
- */
- err = -EPERM;
- if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags))
- goto exit;
-
err = 0;
/* set the new file, lockless */
get_file(exe.file);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 706309f9ed84..39b3368f6de6 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -347,13 +347,6 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
- {
- .procname = "sched_shares_window_ns",
- .data = &sysctl_sched_shares_window,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
#ifdef CONFIG_SCHEDSTATS
{
.procname = "sched_schedstats",
@@ -990,13 +983,6 @@ static struct ctl_table kern_table[] = {
.proc_handler = proc_dointvec,
},
{
- .procname = "kstack_depth_to_print",
- .data = &kstack_depth_to_print,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
.procname = "io_delay_type",
.data = &io_delay_type,
.maxlen = sizeof(int),
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index cbb387a265db..8a5e44236f78 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -41,12 +41,7 @@ static DEFINE_PER_CPU(__u32, taskstats_seqnum);
static int family_registered;
struct kmem_cache *taskstats_cache;
-static struct genl_family family = {
- .id = GENL_ID_GENERATE,
- .name = TASKSTATS_GENL_NAME,
- .version = TASKSTATS_GENL_VERSION,
- .maxattr = TASKSTATS_CMD_ATTR_MAX,
-};
+static struct genl_family family;
static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
[TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 },
@@ -655,6 +650,15 @@ static const struct genl_ops taskstats_ops[] = {
},
};
+static struct genl_family family __ro_after_init = {
+ .name = TASKSTATS_GENL_NAME,
+ .version = TASKSTATS_GENL_VERSION,
+ .maxattr = TASKSTATS_CMD_ATTR_MAX,
+ .module = THIS_MODULE,
+ .ops = taskstats_ops,
+ .n_ops = ARRAY_SIZE(taskstats_ops),
+};
+
/* Needed early in initialization */
void __init taskstats_init_early(void)
{
@@ -671,7 +675,7 @@ static int __init taskstats_init(void)
{
int rc;
- rc = genl_register_family_with_ops(&family, taskstats_ops);
+ rc = genl_register_family(&family);
if (rc)
return rc;
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 49eca0beed32..976840d29a71 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,6 +1,12 @@
-obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
+obj-y += time.o timer.o hrtimer.o
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
-obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
+obj-y += timeconv.o timecounter.o alarmtimer.o
+
+ifeq ($(CONFIG_POSIX_TIMERS),y)
+ obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o itimer.o
+else
+ obj-y += posix-stubs.o
+endif
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 12dd190634ab..9b08ca391aed 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -26,6 +26,9 @@
#include <linux/workqueue.h>
#include <linux/freezer.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/alarmtimer.h>
+
/**
* struct alarm_base - Alarm timer bases
* @lock: Lock for syncrhonized access to the base
@@ -40,7 +43,9 @@ static struct alarm_base {
clockid_t base_clockid;
} alarm_bases[ALARM_NUMTYPE];
-/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
+/* freezer information to handle clock_nanosleep triggered wakeups */
+static enum alarmtimer_type freezer_alarmtype;
+static ktime_t freezer_expires;
static ktime_t freezer_delta;
static DEFINE_SPINLOCK(freezer_delta_lock);
@@ -194,6 +199,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
}
spin_unlock_irqrestore(&base->lock, flags);
+ trace_alarmtimer_fired(alarm, base->gettime());
return ret;
}
@@ -218,15 +224,16 @@ EXPORT_SYMBOL_GPL(alarm_expires_remaining);
*/
static int alarmtimer_suspend(struct device *dev)
{
- struct rtc_time tm;
- ktime_t min, now;
- unsigned long flags;
+ ktime_t min, now, expires;
+ int i, ret, type;
struct rtc_device *rtc;
- int i;
- int ret;
+ unsigned long flags;
+ struct rtc_time tm;
spin_lock_irqsave(&freezer_delta_lock, flags);
min = freezer_delta;
+ expires = freezer_expires;
+ type = freezer_alarmtype;
freezer_delta = ktime_set(0, 0);
spin_unlock_irqrestore(&freezer_delta_lock, flags);
@@ -247,8 +254,11 @@ static int alarmtimer_suspend(struct device *dev)
if (!next)
continue;
delta = ktime_sub(next->expires, base->gettime());
- if (!min.tv64 || (delta.tv64 < min.tv64))
+ if (!min.tv64 || (delta.tv64 < min.tv64)) {
+ expires = next->expires;
min = delta;
+ type = i;
+ }
}
if (min.tv64 == 0)
return 0;
@@ -258,6 +268,8 @@ static int alarmtimer_suspend(struct device *dev)
return -EBUSY;
}
+ trace_alarmtimer_suspend(expires, type);
+
/* Setup an rtc timer to fire that far in the future */
rtc_timer_cancel(rtc, &rtctimer);
rtc_read_time(rtc, &tm);
@@ -295,15 +307,32 @@ static int alarmtimer_resume(struct device *dev)
static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
{
- ktime_t delta;
+ struct alarm_base *base;
unsigned long flags;
- struct alarm_base *base = &alarm_bases[type];
+ ktime_t delta;
+
+ switch(type) {
+ case ALARM_REALTIME:
+ base = &alarm_bases[ALARM_REALTIME];
+ type = ALARM_REALTIME_FREEZER;
+ break;
+ case ALARM_BOOTTIME:
+ base = &alarm_bases[ALARM_BOOTTIME];
+ type = ALARM_BOOTTIME_FREEZER;
+ break;
+ default:
+ WARN_ONCE(1, "Invalid alarm type: %d\n", type);
+ return;
+ }
delta = ktime_sub(absexp, base->gettime());
spin_lock_irqsave(&freezer_delta_lock, flags);
- if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
+ if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64)) {
freezer_delta = delta;
+ freezer_expires = absexp;
+ freezer_alarmtype = type;
+ }
spin_unlock_irqrestore(&freezer_delta_lock, flags);
}
@@ -342,6 +371,8 @@ void alarm_start(struct alarm *alarm, ktime_t start)
alarmtimer_enqueue(base, alarm);
hrtimer_start(&alarm->timer, alarm->node.expires, HRTIMER_MODE_ABS);
spin_unlock_irqrestore(&base->lock, flags);
+
+ trace_alarmtimer_start(alarm, base->gettime());
}
EXPORT_SYMBOL_GPL(alarm_start);
@@ -390,6 +421,8 @@ int alarm_try_to_cancel(struct alarm *alarm)
if (ret >= 0)
alarmtimer_dequeue(base, alarm);
spin_unlock_irqrestore(&base->lock, flags);
+
+ trace_alarmtimer_cancel(alarm, base->gettime());
return ret;
}
EXPORT_SYMBOL_GPL(alarm_try_to_cancel);
@@ -846,8 +879,10 @@ static int __init alarmtimer_init(void)
alarmtimer_rtc_timer_init();
- posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
- posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
+ posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
+ posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
+ }
/* Initialize alarm bases */
alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 7e4fad75acaa..150242ccfcd2 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -89,6 +89,7 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
*mult = tmp;
*shift = sft;
}
+EXPORT_SYMBOL_GPL(clocks_calc_mult_shift);
/*[Clocksource internal variables]---------
* curr_clocksource:
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index bb5ec425dfe0..08be5c99d26b 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1742,15 +1742,19 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns.
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task.
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
*
- * Returns 0 when the timer has expired otherwise -EINTR
+ * Returns 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
*/
int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode)
@@ -1772,15 +1776,19 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
- * pass before the routine returns.
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process()).
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task.
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
*
- * Returns 0 when the timer has expired otherwise -EINTR
+ * Returns 0 when the timer has expired. If the task was woken before the
+ * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or
+ * by an explicit wakeup, it returns -EINTR.
*/
int __sched schedule_hrtimeout(ktime_t *expires,
const enum hrtimer_mode mode)
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c
index 1d5c7204ddc9..2b9f45bc955d 100644
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -238,6 +238,8 @@ again:
return 0;
}
+#ifdef __ARCH_WANT_SYS_ALARM
+
/**
* alarm_setitimer - set alarm in seconds
*
@@ -250,7 +252,7 @@ again:
* On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
* negative timeval settings which would cause immediate expiry.
*/
-unsigned int alarm_setitimer(unsigned int seconds)
+static unsigned int alarm_setitimer(unsigned int seconds)
{
struct itimerval it_new, it_old;
@@ -275,6 +277,17 @@ unsigned int alarm_setitimer(unsigned int seconds)
return it_old.it_value.tv_sec;
}
+/*
+ * For backwards compatibility? This can be done in libc so Alpha
+ * and all newer ports shouldn't need it.
+ */
+SYSCALL_DEFINE1(alarm, unsigned int, seconds)
+{
+ return alarm_setitimer(seconds);
+}
+
+#endif
+
SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
struct itimerval __user *, ovalue)
{
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 39008d78927a..f246763c9947 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -9,7 +9,6 @@
#include <asm/uaccess.h>
#include <linux/kernel_stat.h>
#include <trace/events/timer.h>
-#include <linux/random.h>
#include <linux/tick.h>
#include <linux/workqueue.h>
@@ -133,9 +132,9 @@ static inline unsigned long long prof_ticks(struct task_struct *p)
}
static inline unsigned long long virt_ticks(struct task_struct *p)
{
- cputime_t utime;
+ cputime_t utime, stime;
- task_cputime(p, &utime, NULL);
+ task_cputime(p, &utime, &stime);
return cputime_to_expires(utime);
}
@@ -447,10 +446,7 @@ static void cleanup_timers(struct list_head *head)
*/
void posix_cpu_timers_exit(struct task_struct *tsk)
{
- add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
- sizeof(unsigned long long));
cleanup_timers(tsk->cpu_timers);
-
}
void posix_cpu_timers_exit_group(struct task_struct *tsk)
{
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
new file mode 100644
index 000000000000..cd6716e115e8
--- /dev/null
+++ b/kernel/time/posix-stubs.c
@@ -0,0 +1,123 @@
+/*
+ * Dummy stubs used when CONFIG_POSIX_TIMERS=n
+ *
+ * Created by: Nicolas Pitre, July 2016
+ * Copyright: (C) 2016 Linaro 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/linkage.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/ktime.h>
+#include <linux/timekeeping.h>
+#include <linux/posix-timers.h>
+
+asmlinkage long sys_ni_posix_timers(void)
+{
+ pr_err_once("process %d (%s) attempted a POSIX timer syscall "
+ "while CONFIG_POSIX_TIMERS is not set\n",
+ current->pid, current->comm);
+ return -ENOSYS;
+}
+
+#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
+
+SYS_NI(timer_create);
+SYS_NI(timer_gettime);
+SYS_NI(timer_getoverrun);
+SYS_NI(timer_settime);
+SYS_NI(timer_delete);
+SYS_NI(clock_adjtime);
+SYS_NI(getitimer);
+SYS_NI(setitimer);
+#ifdef __ARCH_WANT_SYS_ALARM
+SYS_NI(alarm);
+#endif
+
+/*
+ * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
+ * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
+ * is also included for convenience as at least systemd uses it.
+ */
+
+SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
+ const struct timespec __user *, tp)
+{
+ struct timespec new_tp;
+
+ if (which_clock != CLOCK_REALTIME)
+ return -EINVAL;
+ if (copy_from_user(&new_tp, tp, sizeof (*tp)))
+ return -EFAULT;
+ return do_sys_settimeofday(&new_tp, NULL);
+}
+
+SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
+ struct timespec __user *,tp)
+{
+ struct timespec kernel_tp;
+
+ switch (which_clock) {
+ case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break;
+ case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break;
+ case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break;
+ default: return -EINVAL;
+ }
+ if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
+ return -EFAULT;
+ return 0;
+}
+
+SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
+{
+ struct timespec rtn_tp = {
+ .tv_sec = 0,
+ .tv_nsec = hrtimer_resolution,
+ };
+
+ switch (which_clock) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp)))
+ return -EFAULT;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
+ const struct timespec __user *, rqtp,
+ struct timespec __user *, rmtp)
+{
+ struct timespec t;
+
+ switch (which_clock) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
+ return -EFAULT;
+ if (!timespec_valid(&t))
+ return -EINVAL;
+ return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ?
+ HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+ which_clock);
+ default:
+ return -EINVAL;
+ }
+}
+
+#ifdef CONFIG_COMPAT
+long clock_nanosleep_restart(struct restart_block *restart_block)
+{
+ return hrtimer_nanosleep_restart(restart_block);
+}
+#endif
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 3bcb61b52f6c..71496a20e670 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -390,24 +390,16 @@ static int __init tick_nohz_full_setup(char *str)
}
__setup("nohz_full=", tick_nohz_full_setup);
-static int tick_nohz_cpu_down_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
+static int tick_nohz_cpu_down(unsigned int cpu)
{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_DOWN_PREPARE:
- /*
- * The boot CPU handles housekeeping duty (unbound timers,
- * workqueues, timekeeping, ...) on behalf of full dynticks
- * CPUs. It must remain online when nohz full is enabled.
- */
- if (tick_nohz_full_running && tick_do_timer_cpu == cpu)
- return NOTIFY_BAD;
- break;
- }
- return NOTIFY_OK;
+ /*
+ * The boot CPU handles housekeeping duty (unbound timers,
+ * workqueues, timekeeping, ...) on behalf of full dynticks
+ * CPUs. It must remain online when nohz full is enabled.
+ */
+ if (tick_nohz_full_running && tick_do_timer_cpu == cpu)
+ return -EBUSY;
+ return 0;
}
static int tick_nohz_init_all(void)
@@ -428,7 +420,7 @@ static int tick_nohz_init_all(void)
void __init tick_nohz_init(void)
{
- int cpu;
+ int cpu, ret;
if (!tick_nohz_full_running) {
if (tick_nohz_init_all() < 0)
@@ -469,7 +461,10 @@ void __init tick_nohz_init(void)
for_each_cpu(cpu, tick_nohz_full_mask)
context_tracking_cpu_set(cpu);
- cpu_notifier(tick_nohz_cpu_down_callback, 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "kernel/nohz:predown", NULL,
+ tick_nohz_cpu_down);
+ WARN_ON(ret < 0);
pr_info("NO_HZ: Full dynticks CPUs: %*pbl.\n",
cpumask_pr_args(tick_nohz_full_mask));
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 37dec7e3db43..da233cdf89b0 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -258,10 +258,9 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
tk->cycle_interval = interval;
/* Go back from cycles -> shifted ns */
- tk->xtime_interval = (u64) interval * clock->mult;
+ tk->xtime_interval = interval * clock->mult;
tk->xtime_remainder = ntpinterval - tk->xtime_interval;
- tk->raw_interval =
- ((u64) interval * clock->mult) >> clock->shift;
+ tk->raw_interval = (interval * clock->mult) >> clock->shift;
/* if changing clocks, convert xtime_nsec shift units */
if (old_clock) {
@@ -299,10 +298,10 @@ u32 (*arch_gettimeoffset)(void) = default_arch_gettimeoffset;
static inline u32 arch_gettimeoffset(void) { return 0; }
#endif
-static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
+static inline u64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
cycle_t delta)
{
- s64 nsec;
+ u64 nsec;
nsec = delta * tkr->mult + tkr->xtime_nsec;
nsec >>= tkr->shift;
@@ -311,7 +310,7 @@ static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
return nsec + arch_gettimeoffset();
}
-static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
+static inline u64 timekeeping_get_ns(struct tk_read_base *tkr)
{
cycle_t delta;
@@ -319,8 +318,8 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
return timekeeping_delta_to_ns(tkr, delta);
}
-static inline s64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
- cycle_t cycles)
+static inline u64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
+ cycle_t cycles)
{
cycle_t delta;
@@ -425,6 +424,35 @@ u64 ktime_get_raw_fast_ns(void)
}
EXPORT_SYMBOL_GPL(ktime_get_raw_fast_ns);
+/**
+ * ktime_get_boot_fast_ns - NMI safe and fast access to boot clock.
+ *
+ * To keep it NMI safe since we're accessing from tracing, we're not using a
+ * separate timekeeper with updates to monotonic clock and boot offset
+ * protected with seqlocks. This has the following minor side effects:
+ *
+ * (1) Its possible that a timestamp be taken after the boot offset is updated
+ * but before the timekeeper is updated. If this happens, the new boot offset
+ * is added to the old timekeeping making the clock appear to update slightly
+ * earlier:
+ * CPU 0 CPU 1
+ * timekeeping_inject_sleeptime64()
+ * __timekeeping_inject_sleeptime(tk, delta);
+ * timestamp();
+ * timekeeping_update(tk, TK_CLEAR_NTP...);
+ *
+ * (2) On 32-bit systems, the 64-bit boot offset (tk->offs_boot) may be
+ * partially updated. Since the tk->offs_boot update is a rare event, this
+ * should be a rare occurrence which postprocessing should be able to handle.
+ */
+u64 notrace ktime_get_boot_fast_ns(void)
+{
+ struct timekeeper *tk = &tk_core.timekeeper;
+
+ return (ktime_get_mono_fast_ns() + ktime_to_ns(tk->offs_boot));
+}
+EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns);
+
/* Suspend-time cycles value for halted fast timekeeper. */
static cycle_t cycles_at_suspend;
@@ -623,7 +651,7 @@ static void timekeeping_forward_now(struct timekeeper *tk)
{
struct clocksource *clock = tk->tkr_mono.clock;
cycle_t cycle_now, delta;
- s64 nsec;
+ u64 nsec;
cycle_now = tk->tkr_mono.read(clock);
delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
@@ -652,7 +680,7 @@ int __getnstimeofday64(struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
unsigned long seq;
- s64 nsecs = 0;
+ u64 nsecs;
do {
seq = read_seqcount_begin(&tk_core.seq);
@@ -692,7 +720,7 @@ ktime_t ktime_get(void)
struct timekeeper *tk = &tk_core.timekeeper;
unsigned int seq;
ktime_t base;
- s64 nsecs;
+ u64 nsecs;
WARN_ON(timekeeping_suspended);
@@ -735,7 +763,7 @@ ktime_t ktime_get_with_offset(enum tk_offsets offs)
struct timekeeper *tk = &tk_core.timekeeper;
unsigned int seq;
ktime_t base, *offset = offsets[offs];
- s64 nsecs;
+ u64 nsecs;
WARN_ON(timekeeping_suspended);
@@ -779,7 +807,7 @@ ktime_t ktime_get_raw(void)
struct timekeeper *tk = &tk_core.timekeeper;
unsigned int seq;
ktime_t base;
- s64 nsecs;
+ u64 nsecs;
do {
seq = read_seqcount_begin(&tk_core.seq);
@@ -804,8 +832,8 @@ void ktime_get_ts64(struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 tomono;
- s64 nsec;
unsigned int seq;
+ u64 nsec;
WARN_ON(timekeeping_suspended);
@@ -893,8 +921,8 @@ void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
unsigned long seq;
ktime_t base_raw;
ktime_t base_real;
- s64 nsec_raw;
- s64 nsec_real;
+ u64 nsec_raw;
+ u64 nsec_real;
cycle_t now;
WARN_ON_ONCE(timekeeping_suspended);
@@ -1052,7 +1080,7 @@ int get_device_system_crosststamp(int (*get_time_fn)
cycle_t cycles, now, interval_start;
unsigned int clock_was_set_seq = 0;
ktime_t base_real, base_raw;
- s64 nsec_real, nsec_raw;
+ u64 nsec_real, nsec_raw;
u8 cs_was_changed_seq;
unsigned long seq;
bool do_interp;
@@ -1365,7 +1393,7 @@ void getrawmonotonic64(struct timespec64 *ts)
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts64;
unsigned long seq;
- s64 nsecs;
+ u64 nsecs;
do {
seq = read_seqcount_begin(&tk_core.seq);
@@ -1616,7 +1644,7 @@ void timekeeping_resume(void)
struct clocksource *clock = tk->tkr_mono.clock;
unsigned long flags;
struct timespec64 ts_new, ts_delta;
- cycle_t cycle_now, cycle_delta;
+ cycle_t cycle_now;
sleeptime_injected = false;
read_persistent_clock64(&ts_new);
@@ -1642,27 +1670,11 @@ void timekeeping_resume(void)
cycle_now = tk->tkr_mono.read(clock);
if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
cycle_now > tk->tkr_mono.cycle_last) {
- u64 num, max = ULLONG_MAX;
- u32 mult = clock->mult;
- u32 shift = clock->shift;
- s64 nsec = 0;
-
- cycle_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
- tk->tkr_mono.mask);
-
- /*
- * "cycle_delta * mutl" may cause 64 bits overflow, if the
- * suspended time is too long. In that case we need do the
- * 64 bits math carefully
- */
- do_div(max, mult);
- if (cycle_delta > max) {
- num = div64_u64(cycle_delta, max);
- nsec = (((u64) max * mult) >> shift) * num;
- cycle_delta -= num * max;
- }
- nsec += ((u64) cycle_delta * mult) >> shift;
+ u64 nsec, cyc_delta;
+ cyc_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
+ tk->tkr_mono.mask);
+ nsec = mul_u64_u32_shr(cyc_delta, clock->mult, clock->shift);
ts_delta = ns_to_timespec64(nsec);
sleeptime_injected = true;
} else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index c611c47de884..ea4fbf8477a9 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1615,7 +1615,8 @@ void update_process_times(int user_tick)
irq_work_tick();
#endif
scheduler_tick();
- run_posix_cpu_timers(p);
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS))
+ run_posix_cpu_timers(p);
}
/**
@@ -1676,19 +1677,6 @@ void run_local_timers(void)
raise_softirq(TIMER_SOFTIRQ);
}
-#ifdef __ARCH_WANT_SYS_ALARM
-
-/*
- * For backwards compatibility? This can be done in libc so Alpha
- * and all newer ports shouldn't need it.
- */
-SYSCALL_DEFINE1(alarm, unsigned int, seconds)
-{
- return alarm_setitimer(seconds);
-}
-
-#endif
-
static void process_timeout(unsigned long __data)
{
wake_up_process((struct task_struct *)__data);
@@ -1705,11 +1693,12 @@ static void process_timeout(unsigned long __data)
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
- * pass before the routine returns. The routine will return 0
+ * pass before the routine returns unless the current task is explicitly
+ * woken up, (e.g. by wake_up_process())".
*
* %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task. In this case the remaining time
- * in jiffies will be returned, or 0 if the timer expired in time
+ * delivered to the current task or the current task is explicitly woken
+ * up.
*
* The current task state is guaranteed to be TASK_RUNNING when this
* routine returns.
@@ -1718,7 +1707,9 @@ static void process_timeout(unsigned long __data)
* the CPU away without a bound on the timeout. In this case the return
* value will be %MAX_SCHEDULE_TIMEOUT.
*
- * In all cases the return value is guaranteed to be non-negative.
+ * Returns 0 when the timer has expired otherwise the remaining time in
+ * jiffies will be returned. In all cases the return value is guaranteed
+ * to be non-negative.
*/
signed long __sched schedule_timeout(signed long timeout)
{
@@ -1910,16 +1901,6 @@ unsigned long msleep_interruptible(unsigned int msecs)
EXPORT_SYMBOL(msleep_interruptible);
-static void __sched do_usleep_range(unsigned long min, unsigned long max)
-{
- ktime_t kmin;
- u64 delta;
-
- kmin = ktime_set(0, min * NSEC_PER_USEC);
- delta = (u64)(max - min) * NSEC_PER_USEC;
- schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL);
-}
-
/**
* usleep_range - Sleep for an approximate time
* @min: Minimum time in usecs to sleep
@@ -1933,7 +1914,14 @@ static void __sched do_usleep_range(unsigned long min, unsigned long max)
*/
void __sched usleep_range(unsigned long min, unsigned long max)
{
- __set_current_state(TASK_UNINTERRUPTIBLE);
- do_usleep_range(min, max);
+ ktime_t exp = ktime_add_us(ktime_get(), min);
+ u64 delta = (u64)(max - min) * NSEC_PER_USEC;
+
+ for (;;) {
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ /* Do not return before the requested sleep time has elapsed */
+ if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS))
+ break;
+ }
}
EXPORT_SYMBOL(usleep_range);
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index dbafc5df03f3..95cecbf67f5c 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -1777,14 +1777,14 @@ void blk_dump_cmd(char *buf, struct request *rq)
}
}
-void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes)
+void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes)
{
int i = 0;
- if (rw & REQ_PREFLUSH)
+ if (op & REQ_PREFLUSH)
rwbs[i++] = 'F';
- switch (op) {
+ switch (op & REQ_OP_MASK) {
case REQ_OP_WRITE:
case REQ_OP_WRITE_SAME:
rwbs[i++] = 'W';
@@ -1806,13 +1806,13 @@ void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes)
rwbs[i++] = 'N';
}
- if (rw & REQ_FUA)
+ if (op & REQ_FUA)
rwbs[i++] = 'F';
- if (rw & REQ_RAHEAD)
+ if (op & REQ_RAHEAD)
rwbs[i++] = 'A';
- if (rw & REQ_SYNC)
+ if (op & REQ_SYNC)
rwbs[i++] = 'S';
- if (rw & REQ_META)
+ if (op & REQ_META)
rwbs[i++] = 'M';
rwbs[i] = '\0';
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 5dcb99281259..fa77311dadb2 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -422,6 +422,8 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
return bpf_get_trace_printk_proto();
case BPF_FUNC_get_smp_processor_id:
return &bpf_get_smp_processor_id_proto;
+ case BPF_FUNC_get_numa_node_id:
+ return &bpf_get_numa_node_id_proto;
case BPF_FUNC_perf_event_read:
return &bpf_perf_event_read_proto;
case BPF_FUNC_probe_write_user:
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index da87b3cba5b3..33dd57f53f88 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4258,6 +4258,23 @@ int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
}
EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
+/**
+ * ftrace_ops_set_global_filter - setup ops to use global filters
+ * @ops - the ops which will use the global filters
+ *
+ * ftrace users who need global function trace filtering should call this.
+ * It can set the global filter only if ops were not initialized before.
+ */
+void ftrace_ops_set_global_filter(struct ftrace_ops *ops)
+{
+ if (ops->flags & FTRACE_OPS_FL_INITIALIZED)
+ return;
+
+ ftrace_ops_init(ops);
+ ops->func_hash = &global_ops.local_hash;
+}
+EXPORT_SYMBOL_GPL(ftrace_ops_set_global_filter);
+
static int
ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
int reset, int enable)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9c143739b8d7..89a2611a1635 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -479,9 +479,7 @@ struct ring_buffer {
struct ring_buffer_per_cpu **buffers;
-#ifdef CONFIG_HOTPLUG_CPU
- struct notifier_block cpu_notify;
-#endif
+ struct hlist_node node;
u64 (*clock)(void);
struct rb_irq_work irq_work;
@@ -1274,11 +1272,6 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer)
kfree(cpu_buffer);
}
-#ifdef CONFIG_HOTPLUG_CPU
-static int rb_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu);
-#endif
-
/**
* __ring_buffer_alloc - allocate a new ring_buffer
* @size: the size in bytes per cpu that is needed.
@@ -1296,6 +1289,7 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
long nr_pages;
int bsize;
int cpu;
+ int ret;
/* keep it in its own cache line */
buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
@@ -1303,7 +1297,7 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
if (!buffer)
return NULL;
- if (!alloc_cpumask_var(&buffer->cpumask, GFP_KERNEL))
+ if (!zalloc_cpumask_var(&buffer->cpumask, GFP_KERNEL))
goto fail_free_buffer;
nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
@@ -1318,17 +1312,6 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
if (nr_pages < 2)
nr_pages = 2;
- /*
- * In case of non-hotplug cpu, if the ring-buffer is allocated
- * in early initcall, it will not be notified of secondary cpus.
- * In that off case, we need to allocate for all possible cpus.
- */
-#ifdef CONFIG_HOTPLUG_CPU
- cpu_notifier_register_begin();
- cpumask_copy(buffer->cpumask, cpu_online_mask);
-#else
- cpumask_copy(buffer->cpumask, cpu_possible_mask);
-#endif
buffer->cpus = nr_cpu_ids;
bsize = sizeof(void *) * nr_cpu_ids;
@@ -1337,19 +1320,15 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
if (!buffer->buffers)
goto fail_free_cpumask;
- for_each_buffer_cpu(buffer, cpu) {
- buffer->buffers[cpu] =
- rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
- if (!buffer->buffers[cpu])
- goto fail_free_buffers;
- }
+ cpu = raw_smp_processor_id();
+ cpumask_set_cpu(cpu, buffer->cpumask);
+ buffer->buffers[cpu] = rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
+ if (!buffer->buffers[cpu])
+ goto fail_free_buffers;
-#ifdef CONFIG_HOTPLUG_CPU
- buffer->cpu_notify.notifier_call = rb_cpu_notify;
- buffer->cpu_notify.priority = 0;
- __register_cpu_notifier(&buffer->cpu_notify);
- cpu_notifier_register_done();
-#endif
+ ret = cpuhp_state_add_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
+ if (ret < 0)
+ goto fail_free_buffers;
mutex_init(&buffer->mutex);
@@ -1364,9 +1343,6 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
fail_free_cpumask:
free_cpumask_var(buffer->cpumask);
-#ifdef CONFIG_HOTPLUG_CPU
- cpu_notifier_register_done();
-#endif
fail_free_buffer:
kfree(buffer);
@@ -1383,18 +1359,11 @@ ring_buffer_free(struct ring_buffer *buffer)
{
int cpu;
-#ifdef CONFIG_HOTPLUG_CPU
- cpu_notifier_register_begin();
- __unregister_cpu_notifier(&buffer->cpu_notify);
-#endif
+ cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
for_each_buffer_cpu(buffer, cpu)
rb_free_cpu_buffer(buffer->buffers[cpu]);
-#ifdef CONFIG_HOTPLUG_CPU
- cpu_notifier_register_done();
-#endif
-
kfree(buffer->buffers);
free_cpumask_var(buffer->cpumask);
@@ -4633,62 +4602,48 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
}
EXPORT_SYMBOL_GPL(ring_buffer_read_page);
-#ifdef CONFIG_HOTPLUG_CPU
-static int rb_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+/*
+ * We only allocate new buffers, never free them if the CPU goes down.
+ * If we were to free the buffer, then the user would lose any trace that was in
+ * the buffer.
+ */
+int trace_rb_cpu_prepare(unsigned int cpu, struct hlist_node *node)
{
- struct ring_buffer *buffer =
- container_of(self, struct ring_buffer, cpu_notify);
- long cpu = (long)hcpu;
+ struct ring_buffer *buffer;
long nr_pages_same;
int cpu_i;
unsigned long nr_pages;
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- if (cpumask_test_cpu(cpu, buffer->cpumask))
- return NOTIFY_OK;
-
- nr_pages = 0;
- nr_pages_same = 1;
- /* check if all cpu sizes are same */
- for_each_buffer_cpu(buffer, cpu_i) {
- /* fill in the size from first enabled cpu */
- if (nr_pages == 0)
- nr_pages = buffer->buffers[cpu_i]->nr_pages;
- if (nr_pages != buffer->buffers[cpu_i]->nr_pages) {
- nr_pages_same = 0;
- break;
- }
- }
- /* allocate minimum pages, user can later expand it */
- if (!nr_pages_same)
- nr_pages = 2;
- buffer->buffers[cpu] =
- rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
- if (!buffer->buffers[cpu]) {
- WARN(1, "failed to allocate ring buffer on CPU %ld\n",
- cpu);
- return NOTIFY_OK;
+ buffer = container_of(node, struct ring_buffer, node);
+ if (cpumask_test_cpu(cpu, buffer->cpumask))
+ return 0;
+
+ nr_pages = 0;
+ nr_pages_same = 1;
+ /* check if all cpu sizes are same */
+ for_each_buffer_cpu(buffer, cpu_i) {
+ /* fill in the size from first enabled cpu */
+ if (nr_pages == 0)
+ nr_pages = buffer->buffers[cpu_i]->nr_pages;
+ if (nr_pages != buffer->buffers[cpu_i]->nr_pages) {
+ nr_pages_same = 0;
+ break;
}
- smp_wmb();
- cpumask_set_cpu(cpu, buffer->cpumask);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- /*
- * Do nothing.
- * If we were to free the buffer, then the user would
- * lose any trace that was in the buffer.
- */
- break;
- default:
- break;
}
- return NOTIFY_OK;
+ /* allocate minimum pages, user can later expand it */
+ if (!nr_pages_same)
+ nr_pages = 2;
+ buffer->buffers[cpu] =
+ rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
+ if (!buffer->buffers[cpu]) {
+ WARN(1, "failed to allocate ring buffer on CPU %u\n",
+ cpu);
+ return -ENOMEM;
+ }
+ smp_wmb();
+ cpumask_set_cpu(cpu, buffer->cpumask);
+ return 0;
}
-#endif
#ifdef CONFIG_RING_BUFFER_STARTUP_TEST
/*
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8696ce6bf2f6..54d5270a5042 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1125,6 +1125,7 @@ static struct {
{ trace_clock, "perf", 1 },
{ ktime_get_mono_fast_ns, "mono", 1 },
{ ktime_get_raw_fast_ns, "mono_raw", 1 },
+ { ktime_get_boot_fast_ns, "boot", 1 },
ARCH_TRACE_CLOCKS
};
@@ -7659,10 +7660,21 @@ __init static int tracer_alloc_buffers(void)
raw_spin_lock_init(&global_trace.start_lock);
+ /*
+ * The prepare callbacks allocates some memory for the ring buffer. We
+ * don't free the buffer if the if the CPU goes down. If we were to free
+ * the buffer, then the user would lose any trace that was in the
+ * buffer. The memory will be removed once the "instance" is removed.
+ */
+ ret = cpuhp_setup_state_multi(CPUHP_TRACE_RB_PREPARE,
+ "trace/RB:preapre", trace_rb_cpu_prepare,
+ NULL);
+ if (ret < 0)
+ goto out_free_cpumask;
/* Used for event triggers */
temp_buffer = ring_buffer_alloc(PAGE_SIZE, RB_FL_OVERWRITE);
if (!temp_buffer)
- goto out_free_cpumask;
+ goto out_rm_hp_state;
if (trace_create_savedcmd() < 0)
goto out_free_temp_buffer;
@@ -7723,6 +7735,8 @@ out_free_savedcmd:
free_saved_cmdlines_buffer(savedcmd);
out_free_temp_buffer:
ring_buffer_free(temp_buffer);
+out_rm_hp_state:
+ cpuhp_remove_multi_state(CPUHP_TRACE_RB_PREPARE);
out_free_cpumask:
free_cpumask_var(global_trace.tracing_cpumask);
out_free_buffer_mask:
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a6c8db1d62f6..e6327d102184 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -13,7 +13,22 @@ config PRINTK_TIME
be included, not that the timestamp is recorded.
The behavior is also controlled by the kernel command line
- parameter printk.time=1. See Documentation/kernel-parameters.txt
+ parameter printk.time=1. See Documentation/admin-guide/kernel-parameters.rst
+
+config CONSOLE_LOGLEVEL_DEFAULT
+ int "Default console loglevel (1-15)"
+ range 1 15
+ default "7"
+ help
+ Default loglevel to determine what will be printed on the console.
+
+ Setting a default here is equivalent to passing in loglevel=<x> in
+ the kernel bootargs. loglevel=<x> continues to override whatever
+ value is specified here as well.
+
+ Note: This does not affect the log level of un-prefixed prink()
+ usage in the kernel. That is controlled by the MESSAGE_LOGLEVEL_DEFAULT
+ option.
config MESSAGE_LOGLEVEL_DEFAULT
int "Default message log level (1-7)"
@@ -26,6 +41,10 @@ config MESSAGE_LOGLEVEL_DEFAULT
that are auditing their logs closely may want to set it to a lower
priority.
+ Note: This does not affect what message level gets printed on the console
+ by default. To change that, use loglevel=<x> in the kernel bootargs,
+ or pick a different CONSOLE_LOGLEVEL_DEFAULT configuration value.
+
config BOOT_PRINTK_DELAY
bool "Delay each boot printk message by N milliseconds"
depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY
@@ -1218,7 +1237,7 @@ config DEBUG_BUGVERBOSE
config DEBUG_LIST
bool "Debug linked list manipulation"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL || BUG_ON_DATA_CORRUPTION
help
Enable this to turn on extended checks in the linked-list
walking routines.
@@ -1434,7 +1453,8 @@ config RCU_TRACE
select TRACE_CLOCK
help
This option provides tracing in RCU which presents stats
- in debugfs for debugging RCU implementation.
+ in debugfs for debugging RCU implementation. It also enables
+ additional tracepoints for ftrace-style event tracing.
Say Y here if you want to enable RCU tracing
Say N if you are unsure.
@@ -1964,6 +1984,16 @@ config TEST_STATIC_KEYS
If unsure, say N.
+config BUG_ON_DATA_CORRUPTION
+ bool "Trigger a BUG when data corruption is detected"
+ select DEBUG_LIST
+ help
+ Select this option if the kernel should BUG when it encounters
+ data corruption in kernel memory structures when they get checked
+ for validity.
+
+ If unsure, say N.
+
source "samples/Kconfig"
source "lib/Kconfig.kgdb"
@@ -1975,7 +2005,7 @@ config ARCH_HAS_DEVMEM_IS_ALLOWED
config STRICT_DEVMEM
bool "Filter access to /dev/mem"
- depends on MMU
+ depends on MMU && DEVMEM
depends on ARCH_HAS_DEVMEM_IS_ALLOWED
default y if TILE || PPC
---help---
diff --git a/lib/idr.c b/lib/idr.c
index 6098336df267..52d2979a05e8 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -927,6 +927,9 @@ EXPORT_SYMBOL(ida_pre_get);
* and go back to the ida_pre_get() call. If the ida is full, it will
* return %-ENOSPC.
*
+ * Note that callers must ensure that concurrent access to @ida is not possible.
+ * See ida_simple_get() for a varaint which takes care of locking.
+ *
* @p_id returns a value in the range @starting_id ... %0x7fffffff.
*/
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
@@ -1073,6 +1076,9 @@ EXPORT_SYMBOL(ida_destroy);
* Allocates an id in the range start <= id < end, or returns -ENOSPC.
* On memory allocation failure, returns -ENOMEM.
*
+ * Compared to ida_get_new_above() this function does its own locking, and
+ * should be used unless there are special requirements.
+ *
* Use ida_simple_remove() to get rid of an id.
*/
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
@@ -1119,6 +1125,11 @@ EXPORT_SYMBOL(ida_simple_get);
* ida_simple_remove - remove an allocated id.
* @ida: the (initialized) ida.
* @id: the id returned by ida_simple_get.
+ *
+ * Use to release an id allocated with ida_simple_get().
+ *
+ * Compared to ida_remove() this function does its own locking, and should be
+ * used unless there are special requirements.
*/
void ida_simple_remove(struct ida *ida, unsigned int id)
{
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f2bd21b93dfc..691a52b634fe 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1,4 +1,5 @@
#include <linux/export.h>
+#include <linux/bvec.h>
#include <linux/uio.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 3859bf63561c..7f7bfa55eb6d 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -2,8 +2,7 @@
* Copyright 2006, Red Hat, Inc., Dave Jones
* Released under the General Public License (GPL).
*
- * This file contains the linked list implementations for
- * DEBUG_LIST.
+ * This file contains the linked list validation for DEBUG_LIST.
*/
#include <linux/export.h>
@@ -13,88 +12,48 @@
#include <linux/rculist.h>
/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
+ * Check that the data structures for the list manipulations are reasonably
+ * valid. Failures here indicate memory corruption (and possibly an exploit
+ * attempt).
*/
-void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
+bool __list_add_valid(struct list_head *new, struct list_head *prev,
+ struct list_head *next)
{
- WARN(next->prev != prev,
- "list_add corruption. next->prev should be "
- "prev (%p), but was %p. (next=%p).\n",
+ CHECK_DATA_CORRUPTION(next->prev != prev,
+ "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
prev, next->prev, next);
- WARN(prev->next != next,
- "list_add corruption. prev->next should be "
- "next (%p), but was %p. (prev=%p).\n",
+ CHECK_DATA_CORRUPTION(prev->next != next,
+ "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
next, prev->next, prev);
- WARN(new == prev || new == next,
- "list_add double add: new=%p, prev=%p, next=%p.\n",
- new, prev, next);
- next->prev = new;
- new->next = next;
- new->prev = prev;
- WRITE_ONCE(prev->next, new);
+ CHECK_DATA_CORRUPTION(new == prev || new == next,
+ "list_add double add: new=%p, prev=%p, next=%p.\n",
+ new, prev, next);
+
+ return true;
}
-EXPORT_SYMBOL(__list_add);
+EXPORT_SYMBOL(__list_add_valid);
-void __list_del_entry(struct list_head *entry)
+bool __list_del_entry_valid(struct list_head *entry)
{
struct list_head *prev, *next;
prev = entry->prev;
next = entry->next;
- if (WARN(next == LIST_POISON1,
+ CHECK_DATA_CORRUPTION(next == LIST_POISON1,
"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
- entry, LIST_POISON1) ||
- WARN(prev == LIST_POISON2,
+ entry, LIST_POISON1);
+ CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
- entry, LIST_POISON2) ||
- WARN(prev->next != entry,
- "list_del corruption. prev->next should be %p, "
- "but was %p\n", entry, prev->next) ||
- WARN(next->prev != entry,
- "list_del corruption. next->prev should be %p, "
- "but was %p\n", entry, next->prev))
- return;
-
- __list_del(prev, next);
-}
-EXPORT_SYMBOL(__list_del_entry);
+ entry, LIST_POISON2);
+ CHECK_DATA_CORRUPTION(prev->next != entry,
+ "list_del corruption. prev->next should be %p, but was %p\n",
+ entry, prev->next);
+ CHECK_DATA_CORRUPTION(next->prev != entry,
+ "list_del corruption. next->prev should be %p, but was %p\n",
+ entry, next->prev);
+ return true;
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-void list_del(struct list_head *entry)
-{
- __list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-EXPORT_SYMBOL(list_del);
-
-/*
- * RCU variants.
- */
-void __list_add_rcu(struct list_head *new,
- struct list_head *prev, struct list_head *next)
-{
- WARN(next->prev != prev,
- "list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
- prev, next->prev, next);
- WARN(prev->next != next,
- "list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
- next, prev->next, prev);
- new->next = next;
- new->prev = prev;
- rcu_assign_pointer(list_next_rcu(prev), new);
- next->prev = new;
}
-EXPORT_SYMBOL(__list_add_rcu);
+EXPORT_SYMBOL(__list_del_entry_valid);
diff --git a/lib/lockref.c b/lib/lockref.c
index 5a92189ad711..c4bfcb8836cd 100644
--- a/lib/lockref.c
+++ b/lib/lockref.c
@@ -20,7 +20,7 @@
if (likely(old.lock_count == prev.lock_count)) { \
SUCCESS; \
} \
- cpu_relax_lowlatency(); \
+ cpu_relax(); \
} \
} while (0)
diff --git a/lib/nlattr.c b/lib/nlattr.c
index fce1e9afc6d9..b42b8577fc23 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -14,7 +14,7 @@
#include <linux/types.h>
#include <net/netlink.h>
-static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
+static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
[NLA_U8] = sizeof(u8),
[NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32),
diff --git a/lib/parser.c b/lib/parser.c
index b6d11631231b..3278958b472a 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -152,6 +152,36 @@ static int match_number(substring_t *s, int *result, int base)
}
/**
+ * match_u64int: scan a number in the given base from a substring_t
+ * @s: substring to be scanned
+ * @result: resulting u64 on success
+ * @base: base to use when converting string
+ *
+ * Description: Given a &substring_t and a base, attempts to parse the substring
+ * as a number in that base. On success, sets @result to the integer represented
+ * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
+ */
+static int match_u64int(substring_t *s, u64 *result, int base)
+{
+ char *buf;
+ int ret;
+ u64 val;
+ size_t len = s->to - s->from;
+
+ buf = kmalloc(len + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ memcpy(buf, s->from, len);
+ buf[len] = '\0';
+
+ ret = kstrtoull(buf, base, &val);
+ if (!ret)
+ *result = val;
+ kfree(buf);
+ return ret;
+}
+
+/**
* match_int: - scan a decimal representation of an integer from a substring_t
* @s: substring_t to be scanned
* @result: resulting integer on success
@@ -167,6 +197,23 @@ int match_int(substring_t *s, int *result)
EXPORT_SYMBOL(match_int);
/**
+ * match_u64: - scan a decimal representation of a u64 from
+ * a substring_t
+ * @s: substring_t to be scanned
+ * @result: resulting unsigned long long on success
+ *
+ * Description: Attempts to parse the &substring_t @s as a long decimal
+ * integer. On success, sets @result to the integer represented by the
+ * string and returns 0.
+ * Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
+ */
+int match_u64(substring_t *s, u64 *result)
+{
+ return match_u64int(s, result, 0);
+}
+EXPORT_SYMBOL(match_u64);
+
+/**
* match_octal: - scan an octal representation of an integer from a substring_t
* @s: substring_t to be scanned
* @result: resulting integer on success
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 72d36113ccaa..c8cebb137076 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -158,25 +158,21 @@ EXPORT_SYMBOL(percpu_counter_destroy);
int percpu_counter_batch __read_mostly = 32;
EXPORT_SYMBOL(percpu_counter_batch);
-static void compute_batch_value(void)
+static int compute_batch_value(unsigned int cpu)
{
int nr = num_online_cpus();
percpu_counter_batch = max(32, nr*2);
+ return 0;
}
-static int percpu_counter_hotcpu_callback(struct notifier_block *nb,
- unsigned long action, void *hcpu)
+static int percpu_counter_cpu_dead(unsigned int cpu)
{
#ifdef CONFIG_HOTPLUG_CPU
- unsigned int cpu;
struct percpu_counter *fbc;
- compute_batch_value();
- if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
- return NOTIFY_OK;
+ compute_batch_value(cpu);
- cpu = (unsigned long)hcpu;
spin_lock_irq(&percpu_counters_lock);
list_for_each_entry(fbc, &percpu_counters, list) {
s32 *pcount;
@@ -190,7 +186,7 @@ static int percpu_counter_hotcpu_callback(struct notifier_block *nb,
}
spin_unlock_irq(&percpu_counters_lock);
#endif
- return NOTIFY_OK;
+ return 0;
}
/*
@@ -222,8 +218,15 @@ EXPORT_SYMBOL(__percpu_counter_compare);
static int __init percpu_counter_startup(void)
{
- compute_batch_value();
- hotcpu_notifier(percpu_counter_hotcpu_callback, 0);
+ int ret;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "lib/percpu_cnt:online",
+ compute_batch_value, NULL);
+ WARN_ON(ret < 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_PERCPU_CNT_DEAD,
+ "lib/percpu_cnt:dead", NULL,
+ percpu_counter_cpu_dead);
+ WARN_ON(ret < 0);
return 0;
}
module_init(percpu_counter_startup);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 8e6d552c40dd..2e8c6f7aa56e 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -220,10 +220,10 @@ static void dump_node(struct radix_tree_node *node, unsigned long index)
{
unsigned long i;
- pr_debug("radix node: %p offset %d tags %lx %lx %lx shift %d count %d parent %p\n",
+ pr_debug("radix node: %p offset %d tags %lx %lx %lx shift %d count %d exceptional %d parent %p\n",
node, node->offset,
node->tags[0][0], node->tags[1][0], node->tags[2][0],
- node->shift, node->count, node->parent);
+ node->shift, node->count, node->exceptional, node->parent);
for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
unsigned long first = index | (i << node->shift);
@@ -325,7 +325,6 @@ static void radix_tree_node_rcu_free(struct rcu_head *head)
tag_clear(node, i, 0);
node->slots[0] = NULL;
- node->count = 0;
kmem_cache_free(radix_tree_node_cachep, node);
}
@@ -522,8 +521,13 @@ static int radix_tree_extend(struct radix_tree_root *root,
node->offset = 0;
node->count = 1;
node->parent = NULL;
- if (radix_tree_is_internal_node(slot))
+ if (radix_tree_is_internal_node(slot)) {
entry_to_node(slot)->parent = node;
+ } else {
+ /* Moving an exceptional root->rnode to a node */
+ if (radix_tree_exceptional_entry(slot))
+ node->exceptional = 1;
+ }
node->slots[0] = slot;
slot = node_to_entry(node);
rcu_assign_pointer(root->rnode, slot);
@@ -534,6 +538,104 @@ out:
}
/**
+ * radix_tree_shrink - shrink radix tree to minimum height
+ * @root radix tree root
+ */
+static inline void radix_tree_shrink(struct radix_tree_root *root,
+ radix_tree_update_node_t update_node,
+ void *private)
+{
+ for (;;) {
+ struct radix_tree_node *node = root->rnode;
+ struct radix_tree_node *child;
+
+ if (!radix_tree_is_internal_node(node))
+ break;
+ node = entry_to_node(node);
+
+ /*
+ * The candidate node has more than one child, or its child
+ * is not at the leftmost slot, or the child is a multiorder
+ * entry, we cannot shrink.
+ */
+ if (node->count != 1)
+ break;
+ child = node->slots[0];
+ if (!child)
+ break;
+ if (!radix_tree_is_internal_node(child) && node->shift)
+ break;
+
+ if (radix_tree_is_internal_node(child))
+ entry_to_node(child)->parent = NULL;
+
+ /*
+ * We don't need rcu_assign_pointer(), since we are simply
+ * moving the node from one part of the tree to another: if it
+ * was safe to dereference the old pointer to it
+ * (node->slots[0]), it will be safe to dereference the new
+ * one (root->rnode) as far as dependent read barriers go.
+ */
+ root->rnode = child;
+
+ /*
+ * We have a dilemma here. The node's slot[0] must not be
+ * NULLed in case there are concurrent lookups expecting to
+ * find the item. However if this was a bottom-level node,
+ * then it may be subject to the slot pointer being visible
+ * to callers dereferencing it. If item corresponding to
+ * slot[0] is subsequently deleted, these callers would expect
+ * their slot to become empty sooner or later.
+ *
+ * For example, lockless pagecache will look up a slot, deref
+ * the page pointer, and if the page has 0 refcount it means it
+ * was concurrently deleted from pagecache so try the deref
+ * again. Fortunately there is already a requirement for logic
+ * to retry the entire slot lookup -- the indirect pointer
+ * problem (replacing direct root node with an indirect pointer
+ * also results in a stale slot). So tag the slot as indirect
+ * to force callers to retry.
+ */
+ node->count = 0;
+ if (!radix_tree_is_internal_node(child)) {
+ node->slots[0] = RADIX_TREE_RETRY;
+ if (update_node)
+ update_node(node, private);
+ }
+
+ radix_tree_node_free(node);
+ }
+}
+
+static void delete_node(struct radix_tree_root *root,
+ struct radix_tree_node *node,
+ radix_tree_update_node_t update_node, void *private)
+{
+ do {
+ struct radix_tree_node *parent;
+
+ if (node->count) {
+ if (node == entry_to_node(root->rnode))
+ radix_tree_shrink(root, update_node, private);
+ return;
+ }
+
+ parent = node->parent;
+ if (parent) {
+ parent->slots[node->offset] = NULL;
+ parent->count--;
+ } else {
+ root_tag_clear_all(root);
+ root->rnode = NULL;
+ }
+
+ radix_tree_node_free(node);
+
+ node = parent;
+ } while (node);
+}
+
+/**
* __radix_tree_create - create a slot in a radix tree
* @root: radix tree root
* @index: index key
@@ -649,6 +751,8 @@ int __radix_tree_insert(struct radix_tree_root *root, unsigned long index,
if (node) {
unsigned offset = get_slot_offset(node, slot);
node->count++;
+ if (radix_tree_exceptional_entry(item))
+ node->exceptional++;
BUG_ON(tag_get(node, 0, offset));
BUG_ON(tag_get(node, 1, offset));
BUG_ON(tag_get(node, 2, offset));
@@ -746,6 +850,85 @@ void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
}
EXPORT_SYMBOL(radix_tree_lookup);
+static void replace_slot(struct radix_tree_root *root,
+ struct radix_tree_node *node,
+ void **slot, void *item,
+ bool warn_typeswitch)
+{
+ void *old = rcu_dereference_raw(*slot);
+ int count, exceptional;
+
+ WARN_ON_ONCE(radix_tree_is_internal_node(item));
+
+ count = !!item - !!old;
+ exceptional = !!radix_tree_exceptional_entry(item) -
+ !!radix_tree_exceptional_entry(old);
+
+ WARN_ON_ONCE(warn_typeswitch && (count || exceptional));
+
+ if (node) {
+ node->count += count;
+ node->exceptional += exceptional;
+ }
+
+ rcu_assign_pointer(*slot, item);
+}
+
+/**
+ * __radix_tree_replace - replace item in a slot
+ * @root: radix tree root
+ * @node: pointer to tree node
+ * @slot: pointer to slot in @node
+ * @item: new item to store in the slot.
+ * @update_node: callback for changing leaf nodes
+ * @private: private data to pass to @update_node
+ *
+ * For use with __radix_tree_lookup(). Caller must hold tree write locked
+ * across slot lookup and replacement.
+ */
+void __radix_tree_replace(struct radix_tree_root *root,
+ struct radix_tree_node *node,
+ void **slot, void *item,
+ radix_tree_update_node_t update_node, void *private)
+{
+ /*
+ * This function supports replacing exceptional entries and
+ * deleting entries, but that needs accounting against the
+ * node unless the slot is root->rnode.
+ */
+ replace_slot(root, node, slot, item,
+ !node && slot != (void **)&root->rnode);
+
+ if (!node)
+ return;
+
+ if (update_node)
+ update_node(node, private);
+
+ delete_node(root, node, update_node, private);
+}
+
+/**
+ * radix_tree_replace_slot - replace item in a slot
+ * @root: radix tree root
+ * @slot: pointer to slot
+ * @item: new item to store in the slot.
+ *
+ * For use with radix_tree_lookup_slot(), radix_tree_gang_lookup_slot(),
+ * radix_tree_gang_lookup_tag_slot(). Caller must hold tree write locked
+ * across slot lookup and replacement.
+ *
+ * NOTE: This cannot be used to switch between non-entries (empty slots),
+ * regular entries, and exceptional entries, as that requires accounting
+ * inside the radix tree node. When switching from one type of entry or
+ * deleting, use __radix_tree_lookup() and __radix_tree_replace().
+ */
+void radix_tree_replace_slot(struct radix_tree_root *root,
+ void **slot, void *item)
+{
+ replace_slot(root, NULL, slot, item, true);
+}
+
/**
* radix_tree_tag_set - set a tag on a radix tree node
* @root: radix tree root
@@ -1394,75 +1577,6 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
#endif /* CONFIG_SHMEM && CONFIG_SWAP */
/**
- * radix_tree_shrink - shrink radix tree to minimum height
- * @root radix tree root
- */
-static inline bool radix_tree_shrink(struct radix_tree_root *root)
-{
- bool shrunk = false;
-
- for (;;) {
- struct radix_tree_node *node = root->rnode;
- struct radix_tree_node *child;
-
- if (!radix_tree_is_internal_node(node))
- break;
- node = entry_to_node(node);
-
- /*
- * The candidate node has more than one child, or its child
- * is not at the leftmost slot, or the child is a multiorder
- * entry, we cannot shrink.
- */
- if (node->count != 1)
- break;
- child = node->slots[0];
- if (!child)
- break;
- if (!radix_tree_is_internal_node(child) && node->shift)
- break;
-
- if (radix_tree_is_internal_node(child))
- entry_to_node(child)->parent = NULL;
-
- /*
- * We don't need rcu_assign_pointer(), since we are simply
- * moving the node from one part of the tree to another: if it
- * was safe to dereference the old pointer to it
- * (node->slots[0]), it will be safe to dereference the new
- * one (root->rnode) as far as dependent read barriers go.
- */
- root->rnode = child;
-
- /*
- * We have a dilemma here. The node's slot[0] must not be
- * NULLed in case there are concurrent lookups expecting to
- * find the item. However if this was a bottom-level node,
- * then it may be subject to the slot pointer being visible
- * to callers dereferencing it. If item corresponding to
- * slot[0] is subsequently deleted, these callers would expect
- * their slot to become empty sooner or later.
- *
- * For example, lockless pagecache will look up a slot, deref
- * the page pointer, and if the page has 0 refcount it means it
- * was concurrently deleted from pagecache so try the deref
- * again. Fortunately there is already a requirement for logic
- * to retry the entire slot lookup -- the indirect pointer
- * problem (replacing direct root node with an indirect pointer
- * also results in a stale slot). So tag the slot as indirect
- * to force callers to retry.
- */
- if (!radix_tree_is_internal_node(child))
- node->slots[0] = RADIX_TREE_RETRY;
-
- radix_tree_node_free(node);
- shrunk = true;
- }
-
- return shrunk;
-}
-
-/**
* __radix_tree_delete_node - try to free node after clearing a slot
* @root: radix tree root
* @node: node containing @index
@@ -1470,39 +1584,11 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root)
* After clearing the slot at @index in @node from radix tree
* rooted at @root, call this function to attempt freeing the
* node and shrinking the tree.
- *
- * Returns %true if @node was freed, %false otherwise.
*/
-bool __radix_tree_delete_node(struct radix_tree_root *root,
+void __radix_tree_delete_node(struct radix_tree_root *root,
struct radix_tree_node *node)
{
- bool deleted = false;
-
- do {
- struct radix_tree_node *parent;
-
- if (node->count) {
- if (node == entry_to_node(root->rnode))
- deleted |= radix_tree_shrink(root);
- return deleted;
- }
-
- parent = node->parent;
- if (parent) {
- parent->slots[node->offset] = NULL;
- parent->count--;
- } else {
- root_tag_clear_all(root);
- root->rnode = NULL;
- }
-
- radix_tree_node_free(node);
- deleted = true;
-
- node = parent;
- } while (node);
-
- return deleted;
+ delete_node(root, node, NULL, NULL);
}
static inline void delete_sibling_entries(struct radix_tree_node *node,
@@ -1559,10 +1645,7 @@ void *radix_tree_delete_item(struct radix_tree_root *root,
node_tag_clear(root, node, tag, offset);
delete_sibling_entries(node, node_to_entry(slot), offset);
- node->slots[offset] = NULL;
- node->count--;
-
- __radix_tree_delete_node(root, node);
+ __radix_tree_replace(root, node, slot, NULL, NULL, NULL);
return entry;
}
@@ -1642,32 +1725,31 @@ static __init void radix_tree_init_maxnodes(void)
}
}
-static int radix_tree_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+static int radix_tree_cpu_dead(unsigned int cpu)
{
- int cpu = (long)hcpu;
struct radix_tree_preload *rtp;
struct radix_tree_node *node;
/* Free per-cpu pool of preloaded nodes */
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
- rtp = &per_cpu(radix_tree_preloads, cpu);
- while (rtp->nr) {
- node = rtp->nodes;
- rtp->nodes = node->private_data;
- kmem_cache_free(radix_tree_node_cachep, node);
- rtp->nr--;
- }
+ rtp = &per_cpu(radix_tree_preloads, cpu);
+ while (rtp->nr) {
+ node = rtp->nodes;
+ rtp->nodes = node->private_data;
+ kmem_cache_free(radix_tree_node_cachep, node);
+ rtp->nr--;
}
- return NOTIFY_OK;
+ return 0;
}
void __init radix_tree_init(void)
{
+ int ret;
radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
sizeof(struct radix_tree_node), 0,
SLAB_PANIC | SLAB_RECLAIM_ACCOUNT,
radix_tree_node_ctor);
radix_tree_init_maxnodes();
- hotcpu_notifier(radix_tree_callback, 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_RADIX_DEAD, "lib/radix:dead",
+ NULL, radix_tree_cpu_dead);
+ WARN_ON(ret < 0);
}
diff --git a/lib/rbtree.c b/lib/rbtree.c
index eb8a19fee110..1f8b112a7c35 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -296,11 +296,26 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
*
* (p) (p)
* / \ / \
- * N S --> N Sl
+ * N S --> N sl
* / \ \
- * sl Sr s
+ * sl Sr S
* \
* Sr
+ *
+ * Note: p might be red, and then both
+ * p and sl are red after rotation(which
+ * breaks property 4). This is fixed in
+ * Case 4 (in __rb_rotate_set_parents()
+ * which set sl the color of p
+ * and set p RB_BLACK)
+ *
+ * (p) (sl)
+ * / \ / \
+ * N sl --> P S
+ * \ / \
+ * S N Sr
+ * \
+ * Sr
*/
tmp1 = tmp2->rb_right;
WRITE_ONCE(sibling->rb_left, tmp1);
@@ -365,7 +380,7 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
}
break;
}
- /* Case 3 - right rotate at sibling */
+ /* Case 3 - left rotate at sibling */
tmp1 = tmp2->rb_left;
WRITE_ONCE(sibling->rb_right, tmp1);
WRITE_ONCE(tmp2->rb_left, sibling);
@@ -377,7 +392,7 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
tmp1 = sibling;
sibling = tmp2;
}
- /* Case 4 - left rotate at parent + color flips */
+ /* Case 4 - right rotate at parent + color flips */
tmp2 = sibling->rb_right;
WRITE_ONCE(parent->rb_left, tmp2);
WRITE_ONCE(sibling->rb_right, parent);
diff --git a/mm/Kconfig b/mm/Kconfig
index 86e3e0e74d20..9b8fccb969dc 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -153,7 +153,7 @@ config MOVABLE_NODE
bool "Enable to assign a node which has only movable memory"
depends on HAVE_MEMBLOCK
depends on NO_BOOTMEM
- depends on X86_64
+ depends on X86_64 || OF_EARLY_FLATTREE || MEMORY_HOTPLUG
depends on NUMA
default n
help
@@ -447,13 +447,9 @@ choice
benefit.
endchoice
-#
-# We don't deposit page tables on file THP mapping,
-# but Power makes use of them to address MMU quirk.
-#
config TRANSPARENT_HUGE_PAGECACHE
def_bool y
- depends on TRANSPARENT_HUGEPAGE && !PPC
+ depends on TRANSPARENT_HUGEPAGE
#
# UP and nommu archs use km based percpu allocator
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 8fde443f36d7..3bfed5ab2475 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -310,6 +310,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
spin_lock_init(&wb->work_lock);
INIT_LIST_HEAD(&wb->work_list);
INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
+ wb->dirty_sleep = jiffies;
wb->congested = wb_congested_get_create(bdi, blkcg_id, gfp);
if (!wb->congested)
diff --git a/mm/compaction.c b/mm/compaction.c
index 0409a4ad6ea1..223464227299 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -634,22 +634,6 @@ isolate_freepages_range(struct compact_control *cc,
return pfn;
}
-/* Update the number of anon and file isolated pages in the zone */
-static void acct_isolated(struct zone *zone, struct compact_control *cc)
-{
- struct page *page;
- unsigned int count[2] = { 0, };
-
- if (list_empty(&cc->migratepages))
- return;
-
- list_for_each_entry(page, &cc->migratepages, lru)
- count[!!page_is_file_cache(page)]++;
-
- mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON, count[0]);
- mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, count[1]);
-}
-
/* Similar to reclaim, but different enough that they don't share logic */
static bool too_many_isolated(struct zone *zone)
{
@@ -866,6 +850,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
/* Successfully isolated */
del_page_from_lru_list(page, lruvec, page_lru(page));
+ inc_node_page_state(page,
+ NR_ISOLATED_ANON + page_is_file_cache(page));
isolate_success:
list_add(&page->lru, &cc->migratepages);
@@ -902,7 +888,6 @@ isolate_fail:
spin_unlock_irqrestore(zone_lru_lock(zone), flags);
locked = false;
}
- acct_isolated(zone, cc);
putback_movable_pages(&cc->migratepages);
cc->nr_migratepages = 0;
cc->last_migrated_pfn = 0;
@@ -988,7 +973,6 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
if (cc->nr_migratepages == COMPACT_CLUSTER_MAX)
break;
}
- acct_isolated(cc->zone, cc);
return pfn;
}
@@ -1258,10 +1242,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
low_pfn = isolate_migratepages_block(cc, low_pfn,
block_end_pfn, isolate_mode);
- if (!low_pfn || cc->contended) {
- acct_isolated(zone, cc);
+ if (!low_pfn || cc->contended)
return ISOLATE_ABORT;
- }
/*
* Either we isolated something and proceed with migration. Or
@@ -1271,7 +1253,6 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
break;
}
- acct_isolated(zone, cc);
/* Record where migration scanner will be restarted. */
cc->migrate_pfn = low_pfn;
@@ -2043,33 +2024,38 @@ void kcompactd_stop(int nid)
* away, we get changed to run anywhere: as the first one comes back,
* restore their cpu bindings.
*/
-static int cpu_callback(struct notifier_block *nfb, unsigned long action,
- void *hcpu)
+static int kcompactd_cpu_online(unsigned int cpu)
{
int nid;
- if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
- for_each_node_state(nid, N_MEMORY) {
- pg_data_t *pgdat = NODE_DATA(nid);
- const struct cpumask *mask;
+ for_each_node_state(nid, N_MEMORY) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ const struct cpumask *mask;
- mask = cpumask_of_node(pgdat->node_id);
+ mask = cpumask_of_node(pgdat->node_id);
- if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
- /* One of our CPUs online: restore mask */
- set_cpus_allowed_ptr(pgdat->kcompactd, mask);
- }
+ if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
+ /* One of our CPUs online: restore mask */
+ set_cpus_allowed_ptr(pgdat->kcompactd, mask);
}
- return NOTIFY_OK;
+ return 0;
}
static int __init kcompactd_init(void)
{
int nid;
+ int ret;
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "mm/compaction:online",
+ kcompactd_cpu_online, NULL);
+ if (ret < 0) {
+ pr_err("kcompactd: failed to register hotplug callbacks.\n");
+ return ret;
+ }
for_each_node_state(nid, N_MEMORY)
kcompactd_run(nid);
- hotcpu_notifier(cpu_callback, 0);
return 0;
}
subsys_initcall(kcompactd_init)
diff --git a/mm/debug.c b/mm/debug.c
index 9feb699c5d25..db1cd26d8752 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -59,6 +59,10 @@ void __dump_page(struct page *page, const char *reason)
pr_emerg("flags: %#lx(%pGp)\n", page->flags, &page->flags);
+ print_hex_dump(KERN_ALERT, "raw: ", DUMP_PREFIX_NONE, 32,
+ sizeof(unsigned long), page,
+ sizeof(struct page), false);
+
if (reason)
pr_alert("page dumped because: %s\n", reason);
diff --git a/mm/filemap.c b/mm/filemap.c
index 50b52fe51937..5b4dd03130da 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -132,44 +132,29 @@ static int page_cache_tree_insert(struct address_space *mapping,
if (!dax_mapping(mapping)) {
if (shadowp)
*shadowp = p;
- if (node)
- workingset_node_shadows_dec(node);
} else {
/* DAX can replace empty locked entry with a hole */
WARN_ON_ONCE(p !=
(void *)(RADIX_TREE_EXCEPTIONAL_ENTRY |
RADIX_DAX_ENTRY_LOCK));
- /* DAX accounts exceptional entries as normal pages */
- if (node)
- workingset_node_pages_dec(node);
/* Wakeup waiters for exceptional entry lock */
dax_wake_mapping_entry_waiter(mapping, page->index,
false);
}
}
- radix_tree_replace_slot(slot, page);
+ __radix_tree_replace(&mapping->page_tree, node, slot, page,
+ workingset_update_node, mapping);
mapping->nrpages++;
- if (node) {
- workingset_node_pages_inc(node);
- /*
- * Don't track node that contains actual pages.
- *
- * Avoid acquiring the list_lru lock if already
- * untracked. The list_empty() test is safe as
- * node->private_list is protected by
- * mapping->tree_lock.
- */
- if (!list_empty(&node->private_list))
- list_lru_del(&workingset_shadow_nodes,
- &node->private_list);
- }
return 0;
}
static void page_cache_tree_delete(struct address_space *mapping,
struct page *page, void *shadow)
{
- int i, nr = PageHuge(page) ? 1 : hpage_nr_pages(page);
+ int i, nr;
+
+ /* hugetlb pages are represented by one entry in the radix tree */
+ nr = PageHuge(page) ? 1 : hpage_nr_pages(page);
VM_BUG_ON_PAGE(!PageLocked(page), page);
VM_BUG_ON_PAGE(PageTail(page), page);
@@ -182,44 +167,11 @@ static void page_cache_tree_delete(struct address_space *mapping,
__radix_tree_lookup(&mapping->page_tree, page->index + i,
&node, &slot);
- radix_tree_clear_tags(&mapping->page_tree, node, slot);
-
- if (!node) {
- VM_BUG_ON_PAGE(nr != 1, page);
- /*
- * We need a node to properly account shadow
- * entries. Don't plant any without. XXX
- */
- shadow = NULL;
- }
-
- radix_tree_replace_slot(slot, shadow);
+ VM_BUG_ON_PAGE(!node && nr != 1, page);
- if (!node)
- break;
-
- workingset_node_pages_dec(node);
- if (shadow)
- workingset_node_shadows_inc(node);
- else
- if (__radix_tree_delete_node(&mapping->page_tree, node))
- continue;
-
- /*
- * Track node that only contains shadow entries. DAX mappings
- * contain no shadow entries and may contain other exceptional
- * entries so skip those.
- *
- * Avoid acquiring the list_lru lock if already tracked.
- * The list_empty() test is safe as node->private_list is
- * protected by mapping->tree_lock.
- */
- if (!dax_mapping(mapping) && !workingset_node_pages(node) &&
- list_empty(&node->private_list)) {
- node->private_data = mapping;
- list_lru_add(&workingset_shadow_nodes,
- &node->private_list);
- }
+ radix_tree_clear_tags(&mapping->page_tree, node, slot);
+ __radix_tree_replace(&mapping->page_tree, node, slot, shadow,
+ workingset_update_node, mapping);
}
if (shadow) {
diff --git a/mm/gup.c b/mm/gup.c
index ec4f82704b6f..e50178c58b97 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -632,7 +632,8 @@ next_page:
return i;
}
-bool vma_permits_fault(struct vm_area_struct *vma, unsigned int fault_flags)
+static bool vma_permits_fault(struct vm_area_struct *vma,
+ unsigned int fault_flags)
{
bool write = !!(fault_flags & FAULT_FLAG_WRITE);
bool foreign = !!(fault_flags & FAULT_FLAG_REMOTE);
@@ -857,14 +858,12 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
EXPORT_SYMBOL(get_user_pages_locked);
/*
- * Same as get_user_pages_unlocked(...., FOLL_TOUCH) but it allows to
- * pass additional gup_flags as last parameter (like FOLL_HWPOISON).
+ * Same as get_user_pages_unlocked(...., FOLL_TOUCH) but it allows for
+ * tsk, mm to be specified.
*
* NOTE: here FOLL_TOUCH is not set implicitly and must be set by the
- * caller if required (just like with __get_user_pages). "FOLL_GET",
- * "FOLL_WRITE" and "FOLL_FORCE" are set implicitly as needed
- * according to the parameters "pages", "write", "force"
- * respectively.
+ * caller if required (just like with __get_user_pages). "FOLL_GET"
+ * is set implicitly if "pages" is non-NULL.
*/
__always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
@@ -894,10 +893,8 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
* get_user_pages_unlocked(tsk, mm, ..., pages);
*
* It is functionally equivalent to get_user_pages_fast so
- * get_user_pages_fast should be used instead, if the two parameters
- * "tsk" and "mm" are respectively equal to current and current->mm,
- * or if "force" shall be set to 1 (get_user_pages_fast misses the
- * "force" parameter).
+ * get_user_pages_fast should be used instead if specific gup_flags
+ * (e.g. FOLL_FORCE) are not required.
*/
long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
struct page **pages, unsigned int gup_flags)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d4a6e4001512..cee42cf05477 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -285,6 +285,15 @@ static ssize_t use_zero_page_store(struct kobject *kobj,
}
static struct kobj_attribute use_zero_page_attr =
__ATTR(use_zero_page, 0644, use_zero_page_show, use_zero_page_store);
+
+static ssize_t hpage_pmd_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", HPAGE_PMD_SIZE);
+}
+static struct kobj_attribute hpage_pmd_size_attr =
+ __ATTR_RO(hpage_pmd_size);
+
#ifdef CONFIG_DEBUG_VM
static ssize_t debug_cow_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
@@ -307,6 +316,7 @@ static struct attribute *hugepage_attr[] = {
&enabled_attr.attr,
&defrag_attr.attr,
&use_zero_page_attr.attr,
+ &hpage_pmd_size_attr.attr,
#if defined(CONFIG_SHMEM) && defined(CONFIG_TRANSPARENT_HUGE_PAGECACHE)
&shmem_enabled_attr.attr,
#endif
@@ -737,8 +747,9 @@ int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
if (addr < vma->vm_start || addr >= vma->vm_end)
return VM_FAULT_SIGBUS;
- if (track_pfn_insert(vma, &pgprot, pfn))
- return VM_FAULT_SIGBUS;
+
+ track_pfn_insert(vma, &pgprot, pfn);
+
insert_pfn_pmd(vma, addr, pmd, pfn, pgprot, write);
return VM_FAULT_NOPAGE;
}
@@ -1322,6 +1333,8 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
struct mm_struct *mm = tlb->mm;
bool ret = false;
+ tlb_remove_check_page_size_change(tlb, HPAGE_PMD_SIZE);
+
ptl = pmd_trans_huge_lock(pmd, vma);
if (!ptl)
goto out_unlocked;
@@ -1377,12 +1390,23 @@ out_unlocked:
return ret;
}
+static inline void zap_deposited_table(struct mm_struct *mm, pmd_t *pmd)
+{
+ pgtable_t pgtable;
+
+ pgtable = pgtable_trans_huge_withdraw(mm, pmd);
+ pte_free(mm, pgtable);
+ atomic_long_dec(&mm->nr_ptes);
+}
+
int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
pmd_t *pmd, unsigned long addr)
{
pmd_t orig_pmd;
spinlock_t *ptl;
+ tlb_remove_check_page_size_change(tlb, HPAGE_PMD_SIZE);
+
ptl = __pmd_trans_huge_lock(pmd, vma);
if (!ptl)
return 0;
@@ -1398,12 +1422,12 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
if (vma_is_dax(vma)) {
spin_unlock(ptl);
if (is_huge_zero_pmd(orig_pmd))
- tlb_remove_page(tlb, pmd_page(orig_pmd));
+ tlb_remove_page_size(tlb, pmd_page(orig_pmd), HPAGE_PMD_SIZE);
} else if (is_huge_zero_pmd(orig_pmd)) {
pte_free(tlb->mm, pgtable_trans_huge_withdraw(tlb->mm, pmd));
atomic_long_dec(&tlb->mm->nr_ptes);
spin_unlock(ptl);
- tlb_remove_page(tlb, pmd_page(orig_pmd));
+ tlb_remove_page_size(tlb, pmd_page(orig_pmd), HPAGE_PMD_SIZE);
} else {
struct page *page = pmd_page(orig_pmd);
page_remove_rmap(page, true);
@@ -1416,6 +1440,8 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
atomic_long_dec(&tlb->mm->nr_ptes);
add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
} else {
+ if (arch_needs_pgtable_deposit())
+ zap_deposited_table(tlb->mm, pmd);
add_mm_counter(tlb->mm, MM_FILEPAGES, -HPAGE_PMD_NR);
}
spin_unlock(ptl);
@@ -1424,6 +1450,21 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
return 1;
}
+#ifndef pmd_move_must_withdraw
+static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl,
+ spinlock_t *old_pmd_ptl,
+ struct vm_area_struct *vma)
+{
+ /*
+ * With split pmd lock we also need to move preallocated
+ * PTE page table if new_pmd is on different PMD page table.
+ *
+ * We also don't deposit and withdraw tables for file pages.
+ */
+ return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
+}
+#endif
+
bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
unsigned long new_addr, unsigned long old_end,
pmd_t *old_pmd, pmd_t *new_pmd, bool *need_flush)
@@ -1461,8 +1502,7 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
force_flush = true;
VM_BUG_ON(!pmd_none(*new_pmd));
- if (pmd_move_must_withdraw(new_ptl, old_ptl) &&
- vma_is_anonymous(vma)) {
+ if (pmd_move_must_withdraw(new_ptl, old_ptl, vma)) {
pgtable_t pgtable;
pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
@@ -1588,6 +1628,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
if (!vma_is_anonymous(vma)) {
_pmd = pmdp_huge_clear_flush_notify(vma, haddr, pmd);
+ /*
+ * We are going to unmap this huge page. So
+ * just go ahead and zap it
+ */
+ if (arch_needs_pgtable_deposit())
+ zap_deposited_table(mm, pmd);
if (vma_is_dax(vma))
return;
page = pmd_page(_pmd);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 418bf01a50ed..3edb759c5c7d 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3286,6 +3286,11 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
BUG_ON(start & ~huge_page_mask(h));
BUG_ON(end & ~huge_page_mask(h));
+ /*
+ * This is a hugetlb vma, all the pte entries should point
+ * to huge page.
+ */
+ tlb_remove_check_page_size_change(tlb, sz);
tlb_start_vma(tlb, vma);
mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
address = start;
@@ -3336,7 +3341,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
}
pte = huge_ptep_get_and_clear(mm, address, ptep);
- tlb_remove_tlb_entry(tlb, ptep, address);
+ tlb_remove_huge_tlb_entry(h, tlb, ptep, address);
if (huge_pte_dirty(pte))
set_page_dirty(page);
@@ -3450,15 +3455,17 @@ static void unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
* Keep the pte_same checks anyway to make transition from the mutex easier.
*/
static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep, pte_t pte,
- struct page *pagecache_page, spinlock_t *ptl)
+ unsigned long address, pte_t *ptep,
+ struct page *pagecache_page, spinlock_t *ptl)
{
+ pte_t pte;
struct hstate *h = hstate_vma(vma);
struct page *old_page, *new_page;
int ret = 0, outside_reserve = 0;
unsigned long mmun_start; /* For mmu_notifiers */
unsigned long mmun_end; /* For mmu_notifiers */
+ pte = huge_ptep_get(ptep);
old_page = pte_page(pte);
retry_avoidcopy:
@@ -3711,8 +3718,7 @@ retry:
vma_end_reservation(h, vma, address);
}
- ptl = huge_pte_lockptr(h, mm, ptep);
- spin_lock(ptl);
+ ptl = huge_pte_lock(h, mm, ptep);
size = i_size_read(mapping->host) >> huge_page_shift(h);
if (idx >= size)
goto backout;
@@ -3733,7 +3739,7 @@ retry:
hugetlb_count_add(pages_per_huge_page(h), mm);
if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) {
/* Optimization, do the COW without a second fault */
- ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page, ptl);
+ ret = hugetlb_cow(mm, vma, address, ptep, page, ptl);
}
spin_unlock(ptl);
@@ -3888,8 +3894,8 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
if (flags & FAULT_FLAG_WRITE) {
if (!huge_pte_write(entry)) {
- ret = hugetlb_cow(mm, vma, address, ptep, entry,
- pagecache_page, ptl);
+ ret = hugetlb_cow(mm, vma, address, ptep,
+ pagecache_page, ptl);
goto out_put_page;
}
entry = huge_pte_mkdirty(entry);
@@ -4330,8 +4336,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
if (!spte)
goto out;
- ptl = huge_pte_lockptr(hstate_vma(vma), mm, spte);
- spin_lock(ptl);
+ ptl = huge_pte_lock(hstate_vma(vma), mm, spte);
if (pud_none(*pud)) {
pud_populate(mm, pud,
(pmd_t *)((unsigned long)spte & PAGE_MASK));
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 0e9505f66ec1..b2a0cff2bb35 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -80,7 +80,14 @@ void kasan_unpoison_task_stack(struct task_struct *task)
/* Unpoison the stack for the current task beyond a watermark sp value. */
asmlinkage void kasan_unpoison_task_stack_below(const void *watermark)
{
- __kasan_unpoison_stack(current, watermark);
+ /*
+ * Calculate the task stack base address. Avoid using 'current'
+ * because this function is called by early resume code which hasn't
+ * yet set up the percpu register (%gs).
+ */
+ void *base = (void *)((unsigned long)watermark & ~(THREAD_SIZE - 1));
+
+ kasan_unpoison_shadow(base, watermark - base);
}
/*
diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
index baabaad4a4aa..dae929c02bbb 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -86,24 +86,9 @@ static void qlist_move_all(struct qlist_head *from, struct qlist_head *to)
qlist_init(from);
}
-static void qlist_move(struct qlist_head *from, struct qlist_node *last,
- struct qlist_head *to, size_t size)
-{
- if (unlikely(last == from->tail)) {
- qlist_move_all(from, to);
- return;
- }
- if (qlist_empty(to))
- to->head = from->head;
- else
- to->tail->next = from->head;
- to->tail = last;
- from->head = last->next;
- last->next = NULL;
- from->bytes -= size;
- to->bytes += size;
-}
-
+#define QUARANTINE_PERCPU_SIZE (1 << 20)
+#define QUARANTINE_BATCHES \
+ (1024 > 4 * CONFIG_NR_CPUS ? 1024 : 4 * CONFIG_NR_CPUS)
/*
* The object quarantine consists of per-cpu queues and a global queue,
@@ -111,11 +96,22 @@ static void qlist_move(struct qlist_head *from, struct qlist_node *last,
*/
static DEFINE_PER_CPU(struct qlist_head, cpu_quarantine);
-static struct qlist_head global_quarantine;
+/* Round-robin FIFO array of batches. */
+static struct qlist_head global_quarantine[QUARANTINE_BATCHES];
+static int quarantine_head;
+static int quarantine_tail;
+/* Total size of all objects in global_quarantine across all batches. */
+static unsigned long quarantine_size;
static DEFINE_SPINLOCK(quarantine_lock);
/* Maximum size of the global queue. */
-static unsigned long quarantine_size;
+static unsigned long quarantine_max_size;
+
+/*
+ * Target size of a batch in global_quarantine.
+ * Usually equal to QUARANTINE_PERCPU_SIZE unless we have too much RAM.
+ */
+static unsigned long quarantine_batch_size;
/*
* The fraction of physical memory the quarantine is allowed to occupy.
@@ -124,9 +120,6 @@ static unsigned long quarantine_size;
*/
#define QUARANTINE_FRACTION 32
-#define QUARANTINE_LOW_SIZE (READ_ONCE(quarantine_size) * 3 / 4)
-#define QUARANTINE_PERCPU_SIZE (1 << 20)
-
static struct kmem_cache *qlink_to_cache(struct qlist_node *qlink)
{
return virt_to_head_page(qlink)->slab_cache;
@@ -191,21 +184,30 @@ void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
if (unlikely(!qlist_empty(&temp))) {
spin_lock_irqsave(&quarantine_lock, flags);
- qlist_move_all(&temp, &global_quarantine);
+ WRITE_ONCE(quarantine_size, quarantine_size + temp.bytes);
+ qlist_move_all(&temp, &global_quarantine[quarantine_tail]);
+ if (global_quarantine[quarantine_tail].bytes >=
+ READ_ONCE(quarantine_batch_size)) {
+ int new_tail;
+
+ new_tail = quarantine_tail + 1;
+ if (new_tail == QUARANTINE_BATCHES)
+ new_tail = 0;
+ if (new_tail != quarantine_head)
+ quarantine_tail = new_tail;
+ }
spin_unlock_irqrestore(&quarantine_lock, flags);
}
}
void quarantine_reduce(void)
{
- size_t new_quarantine_size, percpu_quarantines;
+ size_t total_size, new_quarantine_size, percpu_quarantines;
unsigned long flags;
struct qlist_head to_free = QLIST_INIT;
- size_t size_to_free = 0;
- struct qlist_node *last;
- if (likely(READ_ONCE(global_quarantine.bytes) <=
- READ_ONCE(quarantine_size)))
+ if (likely(READ_ONCE(quarantine_size) <=
+ READ_ONCE(quarantine_max_size)))
return;
spin_lock_irqsave(&quarantine_lock, flags);
@@ -214,24 +216,23 @@ void quarantine_reduce(void)
* Update quarantine size in case of hotplug. Allocate a fraction of
* the installed memory to quarantine minus per-cpu queue limits.
*/
- new_quarantine_size = (READ_ONCE(totalram_pages) << PAGE_SHIFT) /
+ total_size = (READ_ONCE(totalram_pages) << PAGE_SHIFT) /
QUARANTINE_FRACTION;
percpu_quarantines = QUARANTINE_PERCPU_SIZE * num_online_cpus();
- new_quarantine_size = (new_quarantine_size < percpu_quarantines) ?
- 0 : new_quarantine_size - percpu_quarantines;
- WRITE_ONCE(quarantine_size, new_quarantine_size);
-
- last = global_quarantine.head;
- while (last) {
- struct kmem_cache *cache = qlink_to_cache(last);
-
- size_to_free += cache->size;
- if (!last->next || size_to_free >
- global_quarantine.bytes - QUARANTINE_LOW_SIZE)
- break;
- last = last->next;
+ new_quarantine_size = (total_size < percpu_quarantines) ?
+ 0 : total_size - percpu_quarantines;
+ WRITE_ONCE(quarantine_max_size, new_quarantine_size);
+ /* Aim at consuming at most 1/2 of slots in quarantine. */
+ WRITE_ONCE(quarantine_batch_size, max((size_t)QUARANTINE_PERCPU_SIZE,
+ 2 * total_size / QUARANTINE_BATCHES));
+
+ if (likely(quarantine_size > quarantine_max_size)) {
+ qlist_move_all(&global_quarantine[quarantine_head], &to_free);
+ WRITE_ONCE(quarantine_size, quarantine_size - to_free.bytes);
+ quarantine_head++;
+ if (quarantine_head == QUARANTINE_BATCHES)
+ quarantine_head = 0;
}
- qlist_move(&global_quarantine, last, &to_free, size_to_free);
spin_unlock_irqrestore(&quarantine_lock, flags);
@@ -275,13 +276,14 @@ static void per_cpu_remove_cache(void *arg)
void quarantine_remove_cache(struct kmem_cache *cache)
{
- unsigned long flags;
+ unsigned long flags, i;
struct qlist_head to_free = QLIST_INIT;
on_each_cpu(per_cpu_remove_cache, cache, 1);
spin_lock_irqsave(&quarantine_lock, flags);
- qlist_move_cache(&global_quarantine, &to_free, cache);
+ for (i = 0; i < QUARANTINE_BATCHES; i++)
+ qlist_move_cache(&global_quarantine[i], &to_free, cache);
spin_unlock_irqrestore(&quarantine_lock, flags);
qlist_free_all(&to_free, cache);
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 073325aedc68..b82b3e215157 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -136,6 +136,8 @@ static void kasan_end_report(unsigned long *flags)
pr_err("==================================================================\n");
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irqrestore(&report_lock, *flags);
+ if (panic_on_warn)
+ panic("panic_on_warn set ...\n");
kasan_enable_current();
}
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 87e1a7ca3846..09460955e818 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1242,6 +1242,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
struct vm_area_struct *vma;
unsigned long addr;
pmd_t *pmd, _pmd;
+ bool deposited = false;
i_mmap_lock_write(mapping);
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
@@ -1266,10 +1267,26 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
spinlock_t *ptl = pmd_lock(vma->vm_mm, pmd);
/* assume page table is clear */
_pmd = pmdp_collapse_flush(vma, addr, pmd);
+ /*
+ * now deposit the pgtable for arch that need it
+ * otherwise free it.
+ */
+ if (arch_needs_pgtable_deposit()) {
+ /*
+ * The deposit should be visibile only after
+ * collapse is seen by others.
+ */
+ smp_wmb();
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd,
+ pmd_pgtable(_pmd));
+ deposited = true;
+ }
spin_unlock(ptl);
up_write(&vma->vm_mm->mmap_sem);
- atomic_long_dec(&vma->vm_mm->nr_ptes);
- pte_free(vma->vm_mm, pmd_pgtable(_pmd));
+ if (!deposited) {
+ atomic_long_dec(&vma->vm_mm->nr_ptes);
+ pte_free(vma->vm_mm, pmd_pgtable(_pmd));
+ }
}
}
i_mmap_unlock_write(mapping);
@@ -1403,6 +1420,9 @@ static void collapse_shmem(struct mm_struct *mm,
spin_lock_irq(&mapping->tree_lock);
+ slot = radix_tree_lookup_slot(&mapping->page_tree, index);
+ VM_BUG_ON_PAGE(page != radix_tree_deref_slot_protected(slot,
+ &mapping->tree_lock), page);
VM_BUG_ON_PAGE(page_mapped(page), page);
/*
@@ -1423,9 +1443,10 @@ static void collapse_shmem(struct mm_struct *mm,
list_add_tail(&page->lru, &pagelist);
/* Finally, replace with the new page. */
- radix_tree_replace_slot(slot,
+ radix_tree_replace_slot(&mapping->page_tree, slot,
new_page + (index % HPAGE_PMD_NR));
+ slot = radix_tree_iter_next(&iter);
index++;
continue;
out_lru:
@@ -1521,9 +1542,11 @@ tree_unlocked:
if (!page || iter.index < page->index) {
if (!nr_none)
break;
- /* Put holes back where they were */
- radix_tree_replace_slot(slot, NULL);
nr_none--;
+ /* Put holes back where they were */
+ radix_tree_delete(&mapping->page_tree,
+ iter.index);
+ slot = radix_tree_iter_next(&iter);
continue;
}
@@ -1532,11 +1555,13 @@ tree_unlocked:
/* Unfreeze the page. */
list_del(&page->lru);
page_ref_unfreeze(page, 2);
- radix_tree_replace_slot(slot, page);
+ radix_tree_replace_slot(&mapping->page_tree,
+ slot, page);
spin_unlock_irq(&mapping->tree_lock);
putback_lru_page(page);
unlock_page(page);
spin_lock_irq(&mapping->tree_lock);
+ slot = radix_tree_iter_next(&iter);
}
VM_BUG_ON(nr_none);
spin_unlock_irq(&mapping->tree_lock);
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index d1380ed93fdf..da3436953022 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -19,7 +19,7 @@
*
*
* For more information on the algorithm and kmemleak usage, please see
- * Documentation/kmemleak.txt.
+ * Documentation/dev-tools/kmemleak.rst.
*
* Notes on locking
* ----------------
diff --git a/mm/madvise.c b/mm/madvise.c
index 93fb63e88b5e..0e3828eae9f8 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -281,6 +281,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
if (pmd_trans_unstable(pmd))
return 0;
+ tlb_remove_check_page_size_change(tlb, PAGE_SIZE);
orig_pte = pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
arch_enter_lazy_mmu_mode();
for (; addr != end; pte++, addr += PAGE_SIZE) {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 0f870ba43942..175ec51c346d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1816,22 +1816,13 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
mutex_unlock(&percpu_charge_mutex);
}
-static int memcg_cpu_hotplug_callback(struct notifier_block *nb,
- unsigned long action,
- void *hcpu)
+static int memcg_hotplug_cpu_dead(unsigned int cpu)
{
- int cpu = (unsigned long)hcpu;
struct memcg_stock_pcp *stock;
- if (action == CPU_ONLINE)
- return NOTIFY_OK;
-
- if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
- return NOTIFY_OK;
-
stock = &per_cpu(memcg_stock, cpu);
drain_stock(stock);
- return NOTIFY_OK;
+ return 0;
}
static void reclaim_high(struct mem_cgroup *memcg,
@@ -2154,6 +2145,8 @@ struct memcg_kmem_cache_create_work {
struct work_struct work;
};
+static struct workqueue_struct *memcg_kmem_cache_create_wq;
+
static void memcg_kmem_cache_create_func(struct work_struct *w)
{
struct memcg_kmem_cache_create_work *cw =
@@ -2185,7 +2178,7 @@ static void __memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
cw->cachep = cachep;
INIT_WORK(&cw->work, memcg_kmem_cache_create_func);
- schedule_work(&cw->work);
+ queue_work(memcg_kmem_cache_create_wq, &cw->work);
}
static void memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
@@ -5774,16 +5767,28 @@ __setup("cgroup.memory=", cgroup_memory);
/*
* subsys_initcall() for memory controller.
*
- * Some parts like hotcpu_notifier() have to be initialized from this context
- * because of lock dependencies (cgroup_lock -> cpu hotplug) but basically
- * everything that doesn't depend on a specific mem_cgroup structure should
- * be initialized from here.
+ * Some parts like memcg_hotplug_cpu_dead() have to be initialized from this
+ * context because of lock dependencies (cgroup_lock -> cpu hotplug) but
+ * basically everything that doesn't depend on a specific mem_cgroup structure
+ * should be initialized from here.
*/
static int __init mem_cgroup_init(void)
{
int cpu, node;
- hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
+#ifndef CONFIG_SLOB
+ /*
+ * Kmem cache creation is mostly done with the slab_mutex held,
+ * so use a special workqueue to avoid stalling all worker
+ * threads in case lots of cgroups are created simultaneously.
+ */
+ memcg_kmem_cache_create_wq =
+ alloc_ordered_workqueue("memcg_kmem_cache_create", 0);
+ BUG_ON(!memcg_kmem_cache_create_wq);
+#endif
+
+ cpuhp_setup_state_nocalls(CPUHP_MM_MEMCQ_DEAD, "mm/memctrl:dead", NULL,
+ memcg_hotplug_cpu_dead);
for_each_possible_cpu(cpu)
INIT_WORK(&per_cpu_ptr(&memcg_stock, cpu)->work,
diff --git a/mm/memory.c b/mm/memory.c
index e18c57bdc75c..32e9b7aec366 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -300,15 +300,14 @@ bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, int page_
struct mmu_gather_batch *batch;
VM_BUG_ON(!tlb->end);
-
- if (!tlb->page_size)
- tlb->page_size = page_size;
- else {
- if (page_size != tlb->page_size)
- return true;
- }
+ VM_WARN_ON(tlb->page_size != page_size);
batch = tlb->active;
+ /*
+ * Add the page and check if we are full. If so
+ * force a flush.
+ */
+ batch->pages[batch->nr++] = page;
if (batch->nr == batch->max) {
if (!tlb_next_batch(tlb))
return true;
@@ -316,7 +315,6 @@ bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, int page_
}
VM_BUG_ON_PAGE(batch->nr > batch->max, page);
- batch->pages[batch->nr++] = page;
return false;
}
@@ -528,7 +526,11 @@ void free_pgd_range(struct mmu_gather *tlb,
end -= PMD_SIZE;
if (addr > end - 1)
return;
-
+ /*
+ * We add page table cache pages with PAGE_SIZE,
+ * (see pte_free_tlb()), flush the tlb if we need
+ */
+ tlb_remove_check_page_size_change(tlb, PAGE_SIZE);
pgd = pgd_offset(tlb->mm, addr);
do {
next = pgd_addr_end(addr, end);
@@ -1118,8 +1120,8 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
pte_t *start_pte;
pte_t *pte;
swp_entry_t entry;
- struct page *pending_page = NULL;
+ tlb_remove_check_page_size_change(tlb, PAGE_SIZE);
again:
init_rss_vec(rss);
start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
@@ -1172,7 +1174,6 @@ again:
print_bad_pte(vma, addr, ptent, page);
if (unlikely(__tlb_remove_page(tlb, page))) {
force_flush = 1;
- pending_page = page;
addr += PAGE_SIZE;
break;
}
@@ -1213,11 +1214,6 @@ again:
if (force_flush) {
force_flush = 0;
tlb_flush_mmu_free(tlb);
- if (pending_page) {
- /* remove the page with new size */
- __tlb_remove_pte_page(tlb, pending_page);
- pending_page = NULL;
- }
if (addr != end)
goto again;
}
@@ -1240,7 +1236,7 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
if (next - addr != HPAGE_PMD_SIZE) {
VM_BUG_ON_VMA(vma_is_anonymous(vma) &&
!rwsem_is_locked(&tlb->mm->mmap_sem), vma);
- split_huge_pmd(vma, pmd, addr);
+ __split_huge_pmd(vma, pmd, addr, false, NULL);
} else if (zap_huge_pmd(tlb, vma, pmd, addr))
goto next;
/* fall through */
@@ -1637,8 +1633,8 @@ int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
if (addr < vma->vm_start || addr >= vma->vm_end)
return -EFAULT;
- if (track_pfn_insert(vma, &pgprot, __pfn_to_pfn_t(pfn, PFN_DEV)))
- return -EINVAL;
+
+ track_pfn_insert(vma, &pgprot, __pfn_to_pfn_t(pfn, PFN_DEV));
ret = insert_pfn(vma, addr, __pfn_to_pfn_t(pfn, PFN_DEV), pgprot);
@@ -1655,8 +1651,8 @@ int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
if (addr < vma->vm_start || addr >= vma->vm_end)
return -EFAULT;
- if (track_pfn_insert(vma, &pgprot, pfn))
- return -EINVAL;
+
+ track_pfn_insert(vma, &pgprot, pfn);
/*
* If we don't have pte special, then we have to use the pfn_valid()
@@ -2939,6 +2935,19 @@ static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
return true;
}
+static void deposit_prealloc_pte(struct fault_env *fe)
+{
+ struct vm_area_struct *vma = fe->vma;
+
+ pgtable_trans_huge_deposit(vma->vm_mm, fe->pmd, fe->prealloc_pte);
+ /*
+ * We are going to consume the prealloc table,
+ * count that as nr_ptes.
+ */
+ atomic_long_inc(&vma->vm_mm->nr_ptes);
+ fe->prealloc_pte = 0;
+}
+
static int do_set_pmd(struct fault_env *fe, struct page *page)
{
struct vm_area_struct *vma = fe->vma;
@@ -2953,6 +2962,17 @@ static int do_set_pmd(struct fault_env *fe, struct page *page)
ret = VM_FAULT_FALLBACK;
page = compound_head(page);
+ /*
+ * Archs like ppc64 need additonal space to store information
+ * related to pte entry. Use the preallocated table for that.
+ */
+ if (arch_needs_pgtable_deposit() && !fe->prealloc_pte) {
+ fe->prealloc_pte = pte_alloc_one(vma->vm_mm, fe->address);
+ if (!fe->prealloc_pte)
+ return VM_FAULT_OOM;
+ smp_wmb(); /* See comment in __pte_alloc() */
+ }
+
fe->ptl = pmd_lock(vma->vm_mm, fe->pmd);
if (unlikely(!pmd_none(*fe->pmd)))
goto out;
@@ -2966,6 +2986,11 @@ static int do_set_pmd(struct fault_env *fe, struct page *page)
add_mm_counter(vma->vm_mm, MM_FILEPAGES, HPAGE_PMD_NR);
page_add_file_rmap(page, true);
+ /*
+ * deposit and withdraw with pmd lock held
+ */
+ if (arch_needs_pgtable_deposit())
+ deposit_prealloc_pte(fe);
set_pmd_at(vma->vm_mm, haddr, fe->pmd, entry);
@@ -2975,6 +3000,13 @@ static int do_set_pmd(struct fault_env *fe, struct page *page)
ret = 0;
count_vm_event(THP_FILE_MAPPED);
out:
+ /*
+ * If we are going to fallback to pte mapping, do a
+ * withdraw with pmd lock held.
+ */
+ if (arch_needs_pgtable_deposit() && ret == VM_FAULT_FALLBACK)
+ fe->prealloc_pte = pgtable_trans_huge_withdraw(vma->vm_mm,
+ fe->pmd);
spin_unlock(fe->ptl);
return ret;
}
@@ -3014,18 +3046,20 @@ int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
ret = do_set_pmd(fe, page);
if (ret != VM_FAULT_FALLBACK)
- return ret;
+ goto fault_handled;
}
if (!fe->pte) {
ret = pte_alloc_one_map(fe);
if (ret)
- return ret;
+ goto fault_handled;
}
/* Re-check under ptl */
- if (unlikely(!pte_none(*fe->pte)))
- return VM_FAULT_NOPAGE;
+ if (unlikely(!pte_none(*fe->pte))) {
+ ret = VM_FAULT_NOPAGE;
+ goto fault_handled;
+ }
flush_icache_page(vma, page);
entry = mk_pte(page, vma->vm_page_prot);
@@ -3045,8 +3079,15 @@ int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
/* no need to invalidate: a not-present page won't be cached */
update_mmu_cache(vma, fe->address, fe->pte);
+ ret = 0;
- return 0;
+fault_handled:
+ /* preallocated pagetable is unused: free it */
+ if (fe->prealloc_pte) {
+ pte_free(fe->vma->vm_mm, fe->prealloc_pte);
+ fe->prealloc_pte = 0;
+ }
+ return ret;
}
static unsigned long fault_around_bytes __read_mostly =
@@ -3145,11 +3186,6 @@ static int do_fault_around(struct fault_env *fe, pgoff_t start_pgoff)
fe->vma->vm_ops->map_pages(fe, start_pgoff, end_pgoff);
- /* preallocated pagetable is unused: free it */
- if (fe->prealloc_pte) {
- pte_free(fe->vma->vm_mm, fe->prealloc_pte);
- fe->prealloc_pte = 0;
- }
/* Huge page is mapped? Page fault is solved */
if (pmd_trans_huge(*fe->pmd)) {
ret = VM_FAULT_NOPAGE;
@@ -3454,7 +3490,7 @@ static int wp_huge_pmd(struct fault_env *fe, pmd_t orig_pmd)
/* COW handled on pte level: split pmd */
VM_BUG_ON_VMA(fe->vma->vm_flags & VM_SHARED, fe->vma);
- split_huge_pmd(fe->vma, fe->pmd, fe->address);
+ __split_huge_pmd(fe->vma, fe->pmd, fe->address, false, NULL);
return VM_FAULT_FALLBACK;
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index cad4b9125695..e43142c15631 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1727,26 +1727,6 @@ static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
static int __init cmdline_parse_movable_node(char *p)
{
#ifdef CONFIG_MOVABLE_NODE
- /*
- * Memory used by the kernel cannot be hot-removed because Linux
- * cannot migrate the kernel pages. When memory hotplug is
- * enabled, we should prevent memblock from allocating memory
- * for the kernel.
- *
- * ACPI SRAT records all hotpluggable memory ranges. But before
- * SRAT is parsed, we don't know about it.
- *
- * The kernel image is loaded into memory at very early time. We
- * cannot prevent this anyway. So on NUMA system, we set any
- * node the kernel resides in as un-hotpluggable.
- *
- * Since on modern servers, one node could have double-digit
- * gigabytes memory, we can assume the memory around the kernel
- * image is also un-hotpluggable. So before SRAT is parsed, just
- * allocate memory near the kernel image to try the best to keep
- * the kernel away from hotpluggable memory.
- */
- memblock_set_bottom_up(true);
movable_node_enabled = true;
#else
pr_warn("movable_node option not supported\n");
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 0b859af06b87..6d3639e1f254 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -276,7 +276,9 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
return ERR_PTR(-EINVAL);
}
} else if (mode == MPOL_LOCAL) {
- if (!nodes_empty(*nodes))
+ if (!nodes_empty(*nodes) ||
+ (flags & MPOL_F_STATIC_NODES) ||
+ (flags & MPOL_F_RELATIVE_NODES))
return ERR_PTR(-EINVAL);
mode = MPOL_PREFERRED;
} else if (nodes_empty(*nodes))
@@ -496,7 +498,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
page = pmd_page(*pmd);
if (is_huge_zero_page(page)) {
spin_unlock(ptl);
- split_huge_pmd(vma, pmd, addr);
+ __split_huge_pmd(vma, pmd, addr, false, NULL);
} else {
get_page(page);
spin_unlock(ptl);
@@ -1679,25 +1681,17 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy)
static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy,
int nd)
{
- switch (policy->mode) {
- case MPOL_PREFERRED:
- if (!(policy->flags & MPOL_F_LOCAL))
- nd = policy->v.preferred_node;
- break;
- case MPOL_BIND:
+ if (policy->mode == MPOL_PREFERRED && !(policy->flags & MPOL_F_LOCAL))
+ nd = policy->v.preferred_node;
+ else {
/*
- * Normally, MPOL_BIND allocations are node-local within the
- * allowed nodemask. However, if __GFP_THISNODE is set and the
- * current node isn't part of the mask, we use the zonelist for
- * the first node in the mask instead.
+ * __GFP_THISNODE shouldn't even be used with the bind policy
+ * because we might easily break the expectation to stay on the
+ * requested node and not break the policy.
*/
- if (unlikely(gfp & __GFP_THISNODE) &&
- unlikely(!node_isset(nd, policy->v.nodes)))
- nd = first_node(policy->v.nodes);
- break;
- default:
- BUG();
+ WARN_ON_ONCE(policy->mode == MPOL_BIND && (gfp & __GFP_THISNODE));
}
+
return node_zonelist(nd, gfp);
}
diff --git a/mm/migrate.c b/mm/migrate.c
index 99250aee1ac1..0ed24b1fa77b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -168,8 +168,6 @@ void putback_movable_pages(struct list_head *l)
continue;
}
list_del(&page->lru);
- dec_node_page_state(page, NR_ISOLATED_ANON +
- page_is_file_cache(page));
/*
* We isolated non-lru movable page so here we can use
* __PageMovable because LRU page's mapping cannot have
@@ -186,6 +184,8 @@ void putback_movable_pages(struct list_head *l)
put_page(page);
} else {
putback_lru_page(page);
+ dec_node_page_state(page, NR_ISOLATED_ANON +
+ page_is_file_cache(page));
}
}
}
@@ -482,7 +482,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
SetPageDirty(newpage);
}
- radix_tree_replace_slot(pslot, newpage);
+ radix_tree_replace_slot(&mapping->page_tree, pslot, newpage);
/*
* Drop cache reference from old page by unfreezing
@@ -556,7 +556,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
get_page(newpage);
- radix_tree_replace_slot(pslot, newpage);
+ radix_tree_replace_slot(&mapping->page_tree, pslot, newpage);
page_ref_unfreeze(page, expected_count - 1);
@@ -1121,8 +1121,15 @@ out:
* restored.
*/
list_del(&page->lru);
- dec_node_page_state(page, NR_ISOLATED_ANON +
- page_is_file_cache(page));
+
+ /*
+ * Compaction can migrate also non-LRU pages which are
+ * not accounted to NR_ISOLATED_*. They can be recognized
+ * as __PageMovable
+ */
+ if (likely(!__PageMovable(page)))
+ dec_node_page_state(page, NR_ISOLATED_ANON +
+ page_is_file_cache(page));
}
/*
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 11936526b08b..cc2459c57f60 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -69,11 +69,17 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
pte_t *pte, oldpte;
spinlock_t *ptl;
unsigned long pages = 0;
+ int target_node = NUMA_NO_NODE;
pte = lock_pte_protection(vma, pmd, addr, prot_numa, &ptl);
if (!pte)
return 0;
+ /* Get target node for single threaded private VMAs */
+ if (prot_numa && !(vma->vm_flags & VM_SHARED) &&
+ atomic_read(&vma->vm_mm->mm_users) == 1)
+ target_node = numa_node_id();
+
arch_enter_lazy_mmu_mode();
do {
oldpte = *pte;
@@ -95,6 +101,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
/* Avoid TLB flush if possible */
if (pte_protnone(oldpte))
continue;
+
+ /*
+ * Don't mess with PTEs if page is already on the node
+ * a single-threaded process is running on.
+ */
+ if (target_node == page_to_nid(page))
+ continue;
}
ptent = ptep_modify_prot_start(mm, addr, pte);
@@ -163,7 +176,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
if (next - addr != HPAGE_PMD_SIZE) {
- split_huge_pmd(vma, pmd, addr);
+ __split_huge_pmd(vma, pmd, addr, false, NULL);
if (pmd_trans_unstable(pmd))
continue;
} else {
@@ -484,6 +497,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
return do_mprotect_pkey(start, len, prot, -1);
}
+#ifdef CONFIG_ARCH_HAS_PKEYS
+
SYSCALL_DEFINE4(pkey_mprotect, unsigned long, start, size_t, len,
unsigned long, prot, int, pkey)
{
@@ -534,3 +549,5 @@ SYSCALL_DEFINE1(pkey_free, int, pkey)
*/
return ret;
}
+
+#endif /* CONFIG_ARCH_HAS_PKEYS */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 439cc63ad903..52e2f8e3b472 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1778,6 +1778,7 @@ pause:
pause,
start_time);
__set_current_state(TASK_KILLABLE);
+ wb->dirty_sleep = now;
io_schedule_timeout(pause);
current->dirty_paused_when = now + pause;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6de9440e3ae2..f64e7bcb43b7 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2058,8 +2058,12 @@ out_unlock:
* potentially hurts the reliability of high-order allocations when under
* intense memory pressure but failed atomic allocations should be easier
* to recover from than an OOM.
+ *
+ * If @force is true, try to unreserve a pageblock even though highatomic
+ * pageblock is exhausted.
*/
-static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
+static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
+ bool force)
{
struct zonelist *zonelist = ac->zonelist;
unsigned long flags;
@@ -2067,11 +2071,16 @@ static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
struct zone *zone;
struct page *page;
int order;
+ bool ret;
for_each_zone_zonelist_nodemask(zone, z, zonelist, ac->high_zoneidx,
ac->nodemask) {
- /* Preserve at least one pageblock */
- if (zone->nr_reserved_highatomic <= pageblock_nr_pages)
+ /*
+ * Preserve at least one pageblock unless memory pressure
+ * is really high.
+ */
+ if (!force && zone->nr_reserved_highatomic <=
+ pageblock_nr_pages)
continue;
spin_lock_irqsave(&zone->lock, flags);
@@ -2085,13 +2094,25 @@ static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
continue;
/*
- * It should never happen but changes to locking could
- * inadvertently allow a per-cpu drain to add pages
- * to MIGRATE_HIGHATOMIC while unreserving so be safe
- * and watch for underflows.
+ * In page freeing path, migratetype change is racy so
+ * we can counter several free pages in a pageblock
+ * in this loop althoug we changed the pageblock type
+ * from highatomic to ac->migratetype. So we should
+ * adjust the count once.
*/
- zone->nr_reserved_highatomic -= min(pageblock_nr_pages,
- zone->nr_reserved_highatomic);
+ if (get_pageblock_migratetype(page) ==
+ MIGRATE_HIGHATOMIC) {
+ /*
+ * It should never happen but changes to
+ * locking could inadvertently allow a per-cpu
+ * drain to add pages to MIGRATE_HIGHATOMIC
+ * while unreserving so be safe and watch for
+ * underflows.
+ */
+ zone->nr_reserved_highatomic -= min(
+ pageblock_nr_pages,
+ zone->nr_reserved_highatomic);
+ }
/*
* Convert to ac->migratetype and avoid the normal
@@ -2103,12 +2124,16 @@ static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
* may increase.
*/
set_pageblock_migratetype(page, ac->migratetype);
- move_freepages_block(zone, page, ac->migratetype);
- spin_unlock_irqrestore(&zone->lock, flags);
- return;
+ ret = move_freepages_block(zone, page, ac->migratetype);
+ if (ret) {
+ spin_unlock_irqrestore(&zone->lock, flags);
+ return ret;
+ }
}
spin_unlock_irqrestore(&zone->lock, flags);
}
+
+ return false;
}
/* Remove an element from the buddy allocator from the fallback list */
@@ -2133,7 +2158,8 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
page = list_first_entry(&area->free_list[fallback_mt],
struct page, lru);
- if (can_steal)
+ if (can_steal &&
+ get_pageblock_migratetype(page) != MIGRATE_HIGHATOMIC)
steal_suitable_fallback(zone, page, start_migratetype);
/* Remove the page from the freelists */
@@ -2192,7 +2218,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
unsigned long count, struct list_head *list,
int migratetype, bool cold)
{
- int i;
+ int i, alloced = 0;
spin_lock(&zone->lock);
for (i = 0; i < count; ++i) {
@@ -2217,13 +2243,21 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
else
list_add_tail(&page->lru, list);
list = &page->lru;
+ alloced++;
if (is_migrate_cma(get_pcppage_migratetype(page)))
__mod_zone_page_state(zone, NR_FREE_CMA_PAGES,
-(1 << order));
}
+
+ /*
+ * i pages were removed from the buddy list even if some leak due
+ * to check_pcp_refill failing so adjust NR_FREE_PAGES based
+ * on i. Do not confuse with 'alloced' which is the number of
+ * pages added to the pcp list.
+ */
__mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order));
spin_unlock(&zone->lock);
- return i;
+ return alloced;
}
#ifdef CONFIG_NUMA
@@ -2534,7 +2568,8 @@ int __isolate_free_page(struct page *page, unsigned int order)
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
int mt = get_pageblock_migratetype(page);
- if (!is_migrate_isolate(mt) && !is_migrate_cma(mt))
+ if (!is_migrate_isolate(mt) && !is_migrate_cma(mt)
+ && mt != MIGRATE_HIGHATOMIC)
set_pageblock_migratetype(page,
MIGRATE_MOVABLE);
}
@@ -3305,7 +3340,7 @@ retry:
* Shrink them them and try again
*/
if (!page && !drained) {
- unreserve_highatomic_pageblock(ac);
+ unreserve_highatomic_pageblock(ac, false);
drain_all_pages(NULL);
drained = true;
goto retry;
@@ -3422,8 +3457,10 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
* Make sure we converge to OOM if we cannot make any progress
* several times in the row.
*/
- if (*no_progress_loops > MAX_RECLAIM_RETRIES)
- return false;
+ if (*no_progress_loops > MAX_RECLAIM_RETRIES) {
+ /* Before OOM, exhaust highatomic_reserve */
+ return unreserve_highatomic_pageblock(ac, true);
+ }
/*
* Keep reclaiming pages while there is a chance this will lead
@@ -6399,8 +6436,8 @@ unsigned long free_reserved_area(void *start, void *end, int poison, char *s)
}
if (pages && s)
- pr_info("Freeing %s memory: %ldK (%p - %p)\n",
- s, pages << (PAGE_SHIFT - 10), start, end);
+ pr_info("Freeing %s memory: %ldK\n",
+ s, pages << (PAGE_SHIFT - 10));
return pages;
}
@@ -6491,38 +6528,39 @@ void __init free_area_init(unsigned long *zones_size)
__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
}
-static int page_alloc_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static int page_alloc_cpu_dead(unsigned int cpu)
{
- int cpu = (unsigned long)hcpu;
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
- lru_add_drain_cpu(cpu);
- drain_pages(cpu);
+ lru_add_drain_cpu(cpu);
+ drain_pages(cpu);
- /*
- * Spill the event counters of the dead processor
- * into the current processors event counters.
- * This artificially elevates the count of the current
- * processor.
- */
- vm_events_fold_cpu(cpu);
+ /*
+ * Spill the event counters of the dead processor
+ * into the current processors event counters.
+ * This artificially elevates the count of the current
+ * processor.
+ */
+ vm_events_fold_cpu(cpu);
- /*
- * Zero the differential counters of the dead processor
- * so that the vm statistics are consistent.
- *
- * This is only okay since the processor is dead and cannot
- * race with what we are doing.
- */
- cpu_vm_stats_fold(cpu);
- }
- return NOTIFY_OK;
+ /*
+ * Zero the differential counters of the dead processor
+ * so that the vm statistics are consistent.
+ *
+ * This is only okay since the processor is dead and cannot
+ * race with what we are doing.
+ */
+ cpu_vm_stats_fold(cpu);
+ return 0;
}
void __init page_alloc_init(void)
{
- hotcpu_notifier(page_alloc_cpu_notify, 0);
+ int ret;
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_PAGE_ALLOC_DEAD,
+ "mm/page_alloc:dead", NULL,
+ page_alloc_cpu_dead);
+ WARN_ON(ret < 0);
}
/*
diff --git a/mm/page_io.c b/mm/page_io.c
index a2651f58c86a..23f6d0d3470f 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -320,10 +320,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
ret = -ENOMEM;
goto out;
}
- if (wbc->sync_mode == WB_SYNC_ALL)
- bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC);
- else
- bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+ bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
count_vm_event(PSWPOUT);
set_page_writeback(page);
unlock_page(page);
diff --git a/mm/percpu.c b/mm/percpu.c
index 255714302394..f696385bcc44 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -2093,6 +2093,8 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
size_t pages_size;
struct page **pages;
int unit, i, j, rc;
+ int upa;
+ int nr_g0_units;
snprintf(psize_str, sizeof(psize_str), "%luK", PAGE_SIZE >> 10);
@@ -2100,7 +2102,12 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
if (IS_ERR(ai))
return PTR_ERR(ai);
BUG_ON(ai->nr_groups != 1);
- BUG_ON(ai->groups[0].nr_units != num_possible_cpus());
+ upa = ai->alloc_size/ai->unit_size;
+ nr_g0_units = roundup(num_possible_cpus(), upa);
+ if (unlikely(WARN_ON(ai->groups[0].nr_units != nr_g0_units))) {
+ pcpu_free_alloc_info(ai);
+ return -EINVAL;
+ }
unit_pages = ai->unit_size >> PAGE_SHIFT;
@@ -2111,21 +2118,22 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
/* allocate pages */
j = 0;
- for (unit = 0; unit < num_possible_cpus(); unit++)
+ for (unit = 0; unit < num_possible_cpus(); unit++) {
+ unsigned int cpu = ai->groups[0].cpu_map[unit];
for (i = 0; i < unit_pages; i++) {
- unsigned int cpu = ai->groups[0].cpu_map[unit];
void *ptr;
ptr = alloc_fn(cpu, PAGE_SIZE, PAGE_SIZE);
if (!ptr) {
pr_warn("failed to allocate %s page for cpu%u\n",
- psize_str, cpu);
+ psize_str, cpu);
goto enomem;
}
/* kmemleak tracks the percpu allocations separately */
kmemleak_free(ptr);
pages[j++] = virt_to_page(ptr);
}
+ }
/* allocate vm area, map the pages and copy static data */
vm.flags = VM_ALLOC;
diff --git a/mm/readahead.c b/mm/readahead.c
index c8a955b1297e..c4ca70239233 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -207,12 +207,21 @@ out:
* memory at once.
*/
int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
- pgoff_t offset, unsigned long nr_to_read)
+ pgoff_t offset, unsigned long nr_to_read)
{
+ struct backing_dev_info *bdi = inode_to_bdi(mapping->host);
+ struct file_ra_state *ra = &filp->f_ra;
+ unsigned long max_pages;
+
if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages))
return -EINVAL;
- nr_to_read = min(nr_to_read, inode_to_bdi(mapping->host)->ra_pages);
+ /*
+ * If the request exceeds the readahead window, allow the read to
+ * be up to the optimal hardware IO size
+ */
+ max_pages = max_t(unsigned long, bdi->io_pages, ra->ra_pages);
+ nr_to_read = min(nr_to_read, max_pages);
while (nr_to_read) {
int err;
@@ -369,10 +378,18 @@ ondemand_readahead(struct address_space *mapping,
bool hit_readahead_marker, pgoff_t offset,
unsigned long req_size)
{
- unsigned long max = ra->ra_pages;
+ struct backing_dev_info *bdi = inode_to_bdi(mapping->host);
+ unsigned long max_pages = ra->ra_pages;
pgoff_t prev_offset;
/*
+ * If the request exceeds the readahead window, allow the read to
+ * be up to the optimal hardware IO size
+ */
+ if (req_size > max_pages && bdi->io_pages > max_pages)
+ max_pages = min(req_size, bdi->io_pages);
+
+ /*
* start of file
*/
if (!offset)
@@ -385,7 +402,7 @@ ondemand_readahead(struct address_space *mapping,
if ((offset == (ra->start + ra->size - ra->async_size) ||
offset == (ra->start + ra->size))) {
ra->start += ra->size;
- ra->size = get_next_ra_size(ra, max);
+ ra->size = get_next_ra_size(ra, max_pages);
ra->async_size = ra->size;
goto readit;
}
@@ -400,16 +417,16 @@ ondemand_readahead(struct address_space *mapping,
pgoff_t start;
rcu_read_lock();
- start = page_cache_next_hole(mapping, offset + 1, max);
+ start = page_cache_next_hole(mapping, offset + 1, max_pages);
rcu_read_unlock();
- if (!start || start - offset > max)
+ if (!start || start - offset > max_pages)
return 0;
ra->start = start;
ra->size = start - offset; /* old async_size */
ra->size += req_size;
- ra->size = get_next_ra_size(ra, max);
+ ra->size = get_next_ra_size(ra, max_pages);
ra->async_size = ra->size;
goto readit;
}
@@ -417,7 +434,7 @@ ondemand_readahead(struct address_space *mapping,
/*
* oversize read
*/
- if (req_size > max)
+ if (req_size > max_pages)
goto initial_readahead;
/*
@@ -433,7 +450,7 @@ ondemand_readahead(struct address_space *mapping,
* Query the page cache and look for the traces(cached history pages)
* that a sequential stream would leave behind.
*/
- if (try_context_readahead(mapping, ra, offset, req_size, max))
+ if (try_context_readahead(mapping, ra, offset, req_size, max_pages))
goto readit;
/*
@@ -444,7 +461,7 @@ ondemand_readahead(struct address_space *mapping,
initial_readahead:
ra->start = offset;
- ra->size = get_init_ra_size(req_size, max);
+ ra->size = get_init_ra_size(req_size, max_pages);
ra->async_size = ra->size > req_size ? ra->size - req_size : ra->size;
readit:
@@ -454,7 +471,7 @@ readit:
* the resulted next readahead window into the current one.
*/
if (offset == ra->start && ra->size == ra->async_size) {
- ra->async_size = get_next_ra_size(ra, max);
+ ra->async_size = get_next_ra_size(ra, max_pages);
ra->size += ra->async_size;
}
diff --git a/mm/rmap.c b/mm/rmap.c
index 1ef36404e7b2..91619fd70939 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -141,14 +141,15 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
}
/**
- * anon_vma_prepare - attach an anon_vma to a memory region
+ * __anon_vma_prepare - attach an anon_vma to a memory region
* @vma: the memory region in question
*
* This makes sure the memory mapping described by 'vma' has
* an 'anon_vma' attached to it, so that we can associate the
* anonymous pages mapped into it with that anon_vma.
*
- * The common case will be that we already have one, but if
+ * The common case will be that we already have one, which
+ * is handled inline by anon_vma_prepare(). But if
* not we either need to find an adjacent mapping that we
* can re-use the anon_vma from (very common when the only
* reason for splitting a vma has been mprotect()), or we
@@ -167,48 +168,46 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
*
* This must be called with the mmap_sem held for reading.
*/
-int anon_vma_prepare(struct vm_area_struct *vma)
+int __anon_vma_prepare(struct vm_area_struct *vma)
{
- struct anon_vma *anon_vma = vma->anon_vma;
+ struct mm_struct *mm = vma->vm_mm;
+ struct anon_vma *anon_vma, *allocated;
struct anon_vma_chain *avc;
might_sleep();
- if (unlikely(!anon_vma)) {
- struct mm_struct *mm = vma->vm_mm;
- struct anon_vma *allocated;
- avc = anon_vma_chain_alloc(GFP_KERNEL);
- if (!avc)
- goto out_enomem;
+ avc = anon_vma_chain_alloc(GFP_KERNEL);
+ if (!avc)
+ goto out_enomem;
+
+ anon_vma = find_mergeable_anon_vma(vma);
+ allocated = NULL;
+ if (!anon_vma) {
+ anon_vma = anon_vma_alloc();
+ if (unlikely(!anon_vma))
+ goto out_enomem_free_avc;
+ allocated = anon_vma;
+ }
- anon_vma = find_mergeable_anon_vma(vma);
+ anon_vma_lock_write(anon_vma);
+ /* page_table_lock to protect against threads */
+ spin_lock(&mm->page_table_lock);
+ if (likely(!vma->anon_vma)) {
+ vma->anon_vma = anon_vma;
+ anon_vma_chain_link(vma, avc, anon_vma);
+ /* vma reference or self-parent link for new root */
+ anon_vma->degree++;
allocated = NULL;
- if (!anon_vma) {
- anon_vma = anon_vma_alloc();
- if (unlikely(!anon_vma))
- goto out_enomem_free_avc;
- allocated = anon_vma;
- }
+ avc = NULL;
+ }
+ spin_unlock(&mm->page_table_lock);
+ anon_vma_unlock_write(anon_vma);
- anon_vma_lock_write(anon_vma);
- /* page_table_lock to protect against threads */
- spin_lock(&mm->page_table_lock);
- if (likely(!vma->anon_vma)) {
- vma->anon_vma = anon_vma;
- anon_vma_chain_link(vma, avc, anon_vma);
- /* vma reference or self-parent link for new root */
- anon_vma->degree++;
- allocated = NULL;
- avc = NULL;
- }
- spin_unlock(&mm->page_table_lock);
- anon_vma_unlock_write(anon_vma);
+ if (unlikely(allocated))
+ put_anon_vma(allocated);
+ if (unlikely(avc))
+ anon_vma_chain_free(avc);
- if (unlikely(allocated))
- put_anon_vma(allocated);
- if (unlikely(avc))
- anon_vma_chain_free(avc);
- }
return 0;
out_enomem_free_avc:
diff --git a/mm/shmem.c b/mm/shmem.c
index 9d32e1cb9f38..abd7403aba41 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -300,18 +300,19 @@ void shmem_uncharge(struct inode *inode, long pages)
static int shmem_radix_tree_replace(struct address_space *mapping,
pgoff_t index, void *expected, void *replacement)
{
+ struct radix_tree_node *node;
void **pslot;
void *item;
VM_BUG_ON(!expected);
VM_BUG_ON(!replacement);
- pslot = radix_tree_lookup_slot(&mapping->page_tree, index);
- if (!pslot)
+ item = __radix_tree_lookup(&mapping->page_tree, index, &node, &pslot);
+ if (!item)
return -ENOENT;
- item = radix_tree_deref_slot_protected(pslot, &mapping->tree_lock);
if (item != expected)
return -ENOENT;
- radix_tree_replace_slot(pslot, replacement);
+ __radix_tree_replace(&mapping->page_tree, node, pslot,
+ replacement, NULL, NULL);
return 0;
}
@@ -370,6 +371,7 @@ static bool shmem_confirm_swap(struct address_space *mapping,
int shmem_huge __read_mostly;
+#if defined(CONFIG_SYSFS) || defined(CONFIG_TMPFS)
static int shmem_parse_huge(const char *str)
{
if (!strcmp(str, "never"))
@@ -407,6 +409,7 @@ static const char *shmem_format_huge(int huge)
return "bad_val";
}
}
+#endif
static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
struct shrink_control *sc, unsigned long nr_to_split)
@@ -1539,7 +1542,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
struct mm_struct *fault_mm, int *fault_type)
{
struct address_space *mapping = inode->i_mapping;
- struct shmem_inode_info *info;
+ struct shmem_inode_info *info = SHMEM_I(inode);
struct shmem_sb_info *sbinfo;
struct mm_struct *charge_mm;
struct mem_cgroup *memcg;
@@ -1589,7 +1592,6 @@ repeat:
* Fast cache lookup did not find it:
* bring it back from swap or allocate.
*/
- info = SHMEM_I(inode);
sbinfo = SHMEM_SB(inode->i_sb);
charge_mm = fault_mm ? : current->mm;
@@ -1837,7 +1839,6 @@ unlock:
put_page(page);
}
if (error == -ENOSPC && !once++) {
- info = SHMEM_I(inode);
spin_lock_irq(&info->lock);
shmem_recalc_inode(inode);
spin_unlock_irq(&info->lock);
diff --git a/mm/slab.c b/mm/slab.c
index 0b0550ca85b4..87b29e76cafd 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -227,13 +227,14 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent)
INIT_LIST_HEAD(&parent->slabs_full);
INIT_LIST_HEAD(&parent->slabs_partial);
INIT_LIST_HEAD(&parent->slabs_free);
+ parent->total_slabs = 0;
+ parent->free_slabs = 0;
parent->shared = NULL;
parent->alien = NULL;
parent->colour_next = 0;
spin_lock_init(&parent->list_lock);
parent->free_objects = 0;
parent->free_touched = 0;
- parent->num_slabs = 0;
}
#define MAKE_LIST(cachep, listp, slab, nodeid) \
@@ -1366,7 +1367,6 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
{
#if DEBUG
struct kmem_cache_node *n;
- struct page *page;
unsigned long flags;
int node;
static DEFINE_RATELIMIT_STATE(slab_oom_rs, DEFAULT_RATELIMIT_INTERVAL,
@@ -1381,32 +1381,18 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
cachep->name, cachep->size, cachep->gfporder);
for_each_kmem_cache_node(cachep, node, n) {
- unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
- unsigned long active_slabs = 0, num_slabs = 0;
- unsigned long num_slabs_partial = 0, num_slabs_free = 0;
- unsigned long num_slabs_full;
+ unsigned long total_slabs, free_slabs, free_objs;
spin_lock_irqsave(&n->list_lock, flags);
- num_slabs = n->num_slabs;
- list_for_each_entry(page, &n->slabs_partial, lru) {
- active_objs += page->active;
- num_slabs_partial++;
- }
- list_for_each_entry(page, &n->slabs_free, lru)
- num_slabs_free++;
-
- free_objects += n->free_objects;
+ total_slabs = n->total_slabs;
+ free_slabs = n->free_slabs;
+ free_objs = n->free_objects;
spin_unlock_irqrestore(&n->list_lock, flags);
- num_objs = num_slabs * cachep->num;
- active_slabs = num_slabs - num_slabs_free;
- num_slabs_full = num_slabs -
- (num_slabs_partial + num_slabs_free);
- active_objs += (num_slabs_full * cachep->num);
-
- pr_warn(" node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
- node, active_slabs, num_slabs, active_objs, num_objs,
- free_objects);
+ pr_warn(" node %d: slabs: %ld/%ld, objs: %ld/%ld\n",
+ node, total_slabs - free_slabs, total_slabs,
+ (total_slabs * cachep->num) - free_objs,
+ total_slabs * cachep->num);
}
#endif
}
@@ -2318,7 +2304,8 @@ static int drain_freelist(struct kmem_cache *cache,
page = list_entry(p, struct page, lru);
list_del(&page->lru);
- n->num_slabs--;
+ n->free_slabs--;
+ n->total_slabs--;
/*
* Safe to drop the lock. The slab is no longer linked
* to the cache.
@@ -2332,7 +2319,7 @@ out:
return nr_freed;
}
-int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate)
+int __kmem_cache_shrink(struct kmem_cache *cachep)
{
int ret = 0;
int node;
@@ -2352,7 +2339,7 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate)
int __kmem_cache_shutdown(struct kmem_cache *cachep)
{
- return __kmem_cache_shrink(cachep, false);
+ return __kmem_cache_shrink(cachep);
}
void __kmem_cache_release(struct kmem_cache *cachep)
@@ -2753,12 +2740,13 @@ static void cache_grow_end(struct kmem_cache *cachep, struct page *page)
n = get_node(cachep, page_to_nid(page));
spin_lock(&n->list_lock);
- if (!page->active)
+ n->total_slabs++;
+ if (!page->active) {
list_add_tail(&page->lru, &(n->slabs_free));
- else
+ n->free_slabs++;
+ } else
fixup_slab_list(cachep, n, page, &list);
- n->num_slabs++;
STATS_INC_GROWN(cachep);
n->free_objects += cachep->num - page->active;
spin_unlock(&n->list_lock);
@@ -2903,9 +2891,10 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
/* Move pfmemalloc slab to the end of list to speed up next search */
list_del(&page->lru);
- if (!page->active)
+ if (!page->active) {
list_add_tail(&page->lru, &n->slabs_free);
- else
+ n->free_slabs++;
+ } else
list_add_tail(&page->lru, &n->slabs_partial);
list_for_each_entry(page, &n->slabs_partial, lru) {
@@ -2913,9 +2902,12 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
return page;
}
+ n->free_touched = 1;
list_for_each_entry(page, &n->slabs_free, lru) {
- if (!PageSlabPfmemalloc(page))
+ if (!PageSlabPfmemalloc(page)) {
+ n->free_slabs--;
return page;
+ }
}
return NULL;
@@ -2925,16 +2917,18 @@ static struct page *get_first_slab(struct kmem_cache_node *n, bool pfmemalloc)
{
struct page *page;
- page = list_first_entry_or_null(&n->slabs_partial,
- struct page, lru);
+ assert_spin_locked(&n->list_lock);
+ page = list_first_entry_or_null(&n->slabs_partial, struct page, lru);
if (!page) {
n->free_touched = 1;
- page = list_first_entry_or_null(&n->slabs_free,
- struct page, lru);
+ page = list_first_entry_or_null(&n->slabs_free, struct page,
+ lru);
+ if (page)
+ n->free_slabs--;
}
if (sk_memalloc_socks())
- return get_valid_first_slab(n, page, pfmemalloc);
+ page = get_valid_first_slab(n, page, pfmemalloc);
return page;
}
@@ -3434,9 +3428,10 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
STATS_DEC_ACTIVE(cachep);
/* fixup slab chains */
- if (page->active == 0)
+ if (page->active == 0) {
list_add(&page->lru, &n->slabs_free);
- else {
+ n->free_slabs++;
+ } else {
/* Unconditionally move a slab to the end of the
* partial list on free - maximum time for the
* other objects to be freed, too.
@@ -3450,7 +3445,8 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
page = list_last_entry(&n->slabs_free, struct page, lru);
list_move(&page->lru, list);
- n->num_slabs--;
+ n->free_slabs--;
+ n->total_slabs--;
}
}
@@ -4102,64 +4098,33 @@ out:
#ifdef CONFIG_SLABINFO
void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
{
- struct page *page;
- unsigned long active_objs;
- unsigned long num_objs;
- unsigned long active_slabs = 0;
- unsigned long num_slabs, free_objects = 0, shared_avail = 0;
- unsigned long num_slabs_partial = 0, num_slabs_free = 0;
- unsigned long num_slabs_full = 0;
- const char *name;
- char *error = NULL;
+ unsigned long active_objs, num_objs, active_slabs;
+ unsigned long total_slabs = 0, free_objs = 0, shared_avail = 0;
+ unsigned long free_slabs = 0;
int node;
struct kmem_cache_node *n;
- active_objs = 0;
- num_slabs = 0;
for_each_kmem_cache_node(cachep, node, n) {
-
check_irq_on();
spin_lock_irq(&n->list_lock);
- num_slabs += n->num_slabs;
+ total_slabs += n->total_slabs;
+ free_slabs += n->free_slabs;
+ free_objs += n->free_objects;
- list_for_each_entry(page, &n->slabs_partial, lru) {
- if (page->active == cachep->num && !error)
- error = "slabs_partial accounting error";
- if (!page->active && !error)
- error = "slabs_partial accounting error";
- active_objs += page->active;
- num_slabs_partial++;
- }
-
- list_for_each_entry(page, &n->slabs_free, lru) {
- if (page->active && !error)
- error = "slabs_free accounting error";
- num_slabs_free++;
- }
-
- free_objects += n->free_objects;
if (n->shared)
shared_avail += n->shared->avail;
spin_unlock_irq(&n->list_lock);
}
- num_objs = num_slabs * cachep->num;
- active_slabs = num_slabs - num_slabs_free;
- num_slabs_full = num_slabs - (num_slabs_partial + num_slabs_free);
- active_objs += (num_slabs_full * cachep->num);
-
- if (num_objs - active_objs != free_objects && !error)
- error = "free_objects accounting error";
-
- name = cachep->name;
- if (error)
- pr_err("slab: cache %s error: %s\n", name, error);
+ num_objs = total_slabs * cachep->num;
+ active_slabs = total_slabs - free_slabs;
+ active_objs = num_objs - free_objs;
sinfo->active_objs = active_objs;
sinfo->num_objs = num_objs;
sinfo->active_slabs = active_slabs;
- sinfo->num_slabs = num_slabs;
+ sinfo->num_slabs = total_slabs;
sinfo->shared_avail = shared_avail;
sinfo->limit = cachep->limit;
sinfo->batchcount = cachep->batchcount;
diff --git a/mm/slab.h b/mm/slab.h
index bc05fdc3edce..de6579dc362c 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -142,11 +142,26 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size,
#define SLAB_CACHE_FLAGS (0)
#endif
+/* Common flags available with current configuration */
#define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS)
+/* Common flags permitted for kmem_cache_create */
+#define SLAB_FLAGS_PERMITTED (SLAB_CORE_FLAGS | \
+ SLAB_RED_ZONE | \
+ SLAB_POISON | \
+ SLAB_STORE_USER | \
+ SLAB_TRACE | \
+ SLAB_CONSISTENCY_CHECKS | \
+ SLAB_MEM_SPREAD | \
+ SLAB_NOLEAKTRACE | \
+ SLAB_RECLAIM_ACCOUNT | \
+ SLAB_TEMPORARY | \
+ SLAB_NOTRACK | \
+ SLAB_ACCOUNT)
+
int __kmem_cache_shutdown(struct kmem_cache *);
void __kmem_cache_release(struct kmem_cache *);
-int __kmem_cache_shrink(struct kmem_cache *, bool);
+int __kmem_cache_shrink(struct kmem_cache *);
void slab_kmem_cache_release(struct kmem_cache *);
struct seq_file;
@@ -432,7 +447,8 @@ struct kmem_cache_node {
struct list_head slabs_partial; /* partial list first, better asm code */
struct list_head slabs_full;
struct list_head slabs_free;
- unsigned long num_slabs;
+ unsigned long total_slabs; /* length of all slab lists */
+ unsigned long free_slabs; /* length of free slab list only */
unsigned long free_objects;
unsigned int free_limit;
unsigned int colour_next; /* Per-node cache coloring */
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 329b03843863..ae323841adb1 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -404,6 +404,12 @@ kmem_cache_create(const char *name, size_t size, size_t align,
goto out_unlock;
}
+ /* Refuse requests with allocator specific flags */
+ if (flags & ~SLAB_FLAGS_PERMITTED) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
/*
* Some allocators will constraint the set of valid flags to a subset
* of all flags. We expect them to define CACHE_CREATE_MASK in this
@@ -573,6 +579,29 @@ void memcg_deactivate_kmem_caches(struct mem_cgroup *memcg)
get_online_cpus();
get_online_mems();
+#ifdef CONFIG_SLUB
+ /*
+ * In case of SLUB, we need to disable empty slab caching to
+ * avoid pinning the offline memory cgroup by freeable kmem
+ * pages charged to it. SLAB doesn't need this, as it
+ * periodically purges unused slabs.
+ */
+ mutex_lock(&slab_mutex);
+ list_for_each_entry(s, &slab_caches, list) {
+ c = is_root_cache(s) ? cache_from_memcg_idx(s, idx) : NULL;
+ if (c) {
+ c->cpu_partial = 0;
+ c->min_partial = 0;
+ }
+ }
+ mutex_unlock(&slab_mutex);
+ /*
+ * kmem_cache->cpu_partial is checked locklessly (see
+ * put_cpu_partial()). Make sure the change is visible.
+ */
+ synchronize_sched();
+#endif
+
mutex_lock(&slab_mutex);
list_for_each_entry(s, &slab_caches, list) {
if (!is_root_cache(s))
@@ -584,7 +613,7 @@ void memcg_deactivate_kmem_caches(struct mem_cgroup *memcg)
if (!c)
continue;
- __kmem_cache_shrink(c, true);
+ __kmem_cache_shrink(c);
arr->entries[idx] = NULL;
}
mutex_unlock(&slab_mutex);
@@ -755,7 +784,7 @@ int kmem_cache_shrink(struct kmem_cache *cachep)
get_online_cpus();
get_online_mems();
kasan_cache_shrink(cachep);
- ret = __kmem_cache_shrink(cachep, false);
+ ret = __kmem_cache_shrink(cachep);
put_online_mems();
put_online_cpus();
return ret;
diff --git a/mm/slob.c b/mm/slob.c
index 5ec158054ffe..eac04d4357ec 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -634,7 +634,7 @@ void __kmem_cache_release(struct kmem_cache *c)
{
}
-int __kmem_cache_shrink(struct kmem_cache *d, bool deactivate)
+int __kmem_cache_shrink(struct kmem_cache *d)
{
return 0;
}
diff --git a/mm/slub.c b/mm/slub.c
index 2b3e740609e9..067598a00849 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3076,7 +3076,7 @@ void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
struct detached_freelist df;
size = build_detached_freelist(s, size, p, &df);
- if (unlikely(!df.page))
+ if (!df.page)
continue;
slab_free(df.s, df.page, df.freelist, df.tail, df.cnt,_RET_IP_);
@@ -3883,7 +3883,7 @@ EXPORT_SYMBOL(kfree);
* being allocated from last increasing the chance that the last objects
* are freed in them.
*/
-int __kmem_cache_shrink(struct kmem_cache *s, bool deactivate)
+int __kmem_cache_shrink(struct kmem_cache *s)
{
int node;
int i;
@@ -3895,21 +3895,6 @@ int __kmem_cache_shrink(struct kmem_cache *s, bool deactivate)
unsigned long flags;
int ret = 0;
- if (deactivate) {
- /*
- * Disable empty slabs caching. Used to avoid pinning offline
- * memory cgroups by kmem pages that can be freed.
- */
- s->cpu_partial = 0;
- s->min_partial = 0;
-
- /*
- * s->cpu_partial is checked locklessly (see put_cpu_partial),
- * so we have to make sure the change is visible.
- */
- synchronize_sched();
- }
-
flush_all(s);
for_each_kmem_cache_node(s, node, n) {
INIT_LIST_HEAD(&discard);
@@ -3966,7 +3951,7 @@ static int slab_mem_going_offline_callback(void *arg)
mutex_lock(&slab_mutex);
list_for_each_entry(s, &slab_caches, list)
- __kmem_cache_shrink(s, false);
+ __kmem_cache_shrink(s);
mutex_unlock(&slab_mutex);
return 0;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f30438970cd1..1c6e0321205d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1234,6 +1234,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud,
pmd = pmd_offset(pud, addr);
do {
+ cond_resched();
next = pmd_addr_end(addr, end);
if (pmd_none_or_trans_huge_or_clear_bad(pmd))
continue;
@@ -1313,6 +1314,7 @@ static int unuse_mm(struct mm_struct *mm,
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if (vma->anon_vma && (ret = unuse_vma(vma, entry, page)))
break;
+ cond_resched();
}
up_read(&mm->mmap_sem);
return (ret < 0)? ret: 0;
@@ -1350,15 +1352,12 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si,
prev = 0;
i = 1;
}
- if (frontswap) {
- if (frontswap_test(si, i))
- break;
- else
- continue;
- }
count = READ_ONCE(si->swap_map[i]);
if (count && swap_count(count) != SWAP_MAP_BAD)
- break;
+ if (!frontswap || frontswap_test(si, i))
+ break;
+ if ((i % LATENCY_LIMIT) == 0)
+ cond_resched();
}
return i;
}
diff --git a/mm/truncate.c b/mm/truncate.c
index 8d8c62d89e6d..fd97f1dbce29 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -44,28 +44,13 @@ static void clear_exceptional_entry(struct address_space *mapping,
* without the tree itself locked. These unlocked entries
* need verification under the tree lock.
*/
- if (!__radix_tree_lookup(&mapping->page_tree, index, &node,
- &slot))
+ if (!__radix_tree_lookup(&mapping->page_tree, index, &node, &slot))
goto unlock;
if (*slot != entry)
goto unlock;
- radix_tree_replace_slot(slot, NULL);
+ __radix_tree_replace(&mapping->page_tree, node, slot, NULL,
+ workingset_update_node, mapping);
mapping->nrexceptional--;
- if (!node)
- goto unlock;
- workingset_node_shadows_dec(node);
- /*
- * Don't track node without shadow entries.
- *
- * Avoid acquiring the list_lru lock if already untracked.
- * The list_empty() test is safe as node->private_list is
- * protected by mapping->tree_lock.
- */
- if (!workingset_node_shadows(node) &&
- !list_empty(&node->private_list))
- list_lru_del(&workingset_shadow_nodes,
- &node->private_list);
- __radix_tree_delete_node(&mapping->page_tree, node);
unlock:
spin_unlock_irq(&mapping->tree_lock);
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f2481cb4e6b2..a5584384eabc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -365,7 +365,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
BUG_ON(offset_in_page(size));
BUG_ON(!is_power_of_2(align));
- might_sleep_if(gfpflags_allow_blocking(gfp_mask));
+ might_sleep();
va = kmalloc_node(sizeof(struct vmap_area),
gfp_mask & GFP_RECLAIM_MASK, node);
@@ -601,6 +601,13 @@ static unsigned long lazy_max_pages(void)
static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
+/*
+ * Serialize vmap purging. There is no actual criticial section protected
+ * by this look, but we want to avoid concurrent calls for performance
+ * reasons and to make the pcpu_get_vm_areas more deterministic.
+ */
+static DEFINE_MUTEX(vmap_purge_lock);
+
/* for per-CPU blocks */
static void purge_fragmented_blocks_allcpus(void);
@@ -615,59 +622,40 @@ void set_iounmap_nonlazy(void)
/*
* Purges all lazily-freed vmap areas.
- *
- * If sync is 0 then don't purge if there is already a purge in progress.
- * If force_flush is 1, then flush kernel TLBs between *start and *end even
- * if we found no lazy vmap areas to unmap (callers can use this to optimise
- * their own TLB flushing).
- * Returns with *start = min(*start, lowest purged address)
- * *end = max(*end, highest purged address)
*/
-static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
- int sync, int force_flush)
+static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
{
- static DEFINE_SPINLOCK(purge_lock);
struct llist_node *valist;
struct vmap_area *va;
struct vmap_area *n_va;
- int nr = 0;
+ bool do_free = false;
- /*
- * If sync is 0 but force_flush is 1, we'll go sync anyway but callers
- * should not expect such behaviour. This just simplifies locking for
- * the case that isn't actually used at the moment anyway.
- */
- if (!sync && !force_flush) {
- if (!spin_trylock(&purge_lock))
- return;
- } else
- spin_lock(&purge_lock);
-
- if (sync)
- purge_fragmented_blocks_allcpus();
+ lockdep_assert_held(&vmap_purge_lock);
valist = llist_del_all(&vmap_purge_list);
llist_for_each_entry(va, valist, purge_list) {
- if (va->va_start < *start)
- *start = va->va_start;
- if (va->va_end > *end)
- *end = va->va_end;
- nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
+ if (va->va_start < start)
+ start = va->va_start;
+ if (va->va_end > end)
+ end = va->va_end;
+ do_free = true;
}
- if (nr)
- atomic_sub(nr, &vmap_lazy_nr);
+ if (!do_free)
+ return false;
- if (nr || force_flush)
- flush_tlb_kernel_range(*start, *end);
+ flush_tlb_kernel_range(start, end);
- if (nr) {
- spin_lock(&vmap_area_lock);
- llist_for_each_entry_safe(va, n_va, valist, purge_list)
- __free_vmap_area(va);
- spin_unlock(&vmap_area_lock);
+ spin_lock(&vmap_area_lock);
+ llist_for_each_entry_safe(va, n_va, valist, purge_list) {
+ int nr = (va->va_end - va->va_start) >> PAGE_SHIFT;
+
+ __free_vmap_area(va);
+ atomic_sub(nr, &vmap_lazy_nr);
+ cond_resched_lock(&vmap_area_lock);
}
- spin_unlock(&purge_lock);
+ spin_unlock(&vmap_area_lock);
+ return true;
}
/*
@@ -676,9 +664,10 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
*/
static void try_purge_vmap_area_lazy(void)
{
- unsigned long start = ULONG_MAX, end = 0;
-
- __purge_vmap_area_lazy(&start, &end, 0, 0);
+ if (mutex_trylock(&vmap_purge_lock)) {
+ __purge_vmap_area_lazy(ULONG_MAX, 0);
+ mutex_unlock(&vmap_purge_lock);
+ }
}
/*
@@ -686,9 +675,10 @@ static void try_purge_vmap_area_lazy(void)
*/
static void purge_vmap_area_lazy(void)
{
- unsigned long start = ULONG_MAX, end = 0;
-
- __purge_vmap_area_lazy(&start, &end, 1, 0);
+ mutex_lock(&vmap_purge_lock);
+ purge_fragmented_blocks_allcpus();
+ __purge_vmap_area_lazy(ULONG_MAX, 0);
+ mutex_unlock(&vmap_purge_lock);
}
/*
@@ -711,22 +701,13 @@ static void free_vmap_area_noflush(struct vmap_area *va)
}
/*
- * Free and unmap a vmap area, caller ensuring flush_cache_vunmap had been
- * called for the correct range previously.
- */
-static void free_unmap_vmap_area_noflush(struct vmap_area *va)
-{
- unmap_vmap_area(va);
- free_vmap_area_noflush(va);
-}
-
-/*
* Free and unmap a vmap area
*/
static void free_unmap_vmap_area(struct vmap_area *va)
{
flush_cache_vunmap(va->va_start, va->va_end);
- free_unmap_vmap_area_noflush(va);
+ unmap_vmap_area(va);
+ free_vmap_area_noflush(va);
}
static struct vmap_area *find_vmap_area(unsigned long addr)
@@ -740,16 +721,6 @@ static struct vmap_area *find_vmap_area(unsigned long addr)
return va;
}
-static void free_unmap_vmap_area_addr(unsigned long addr)
-{
- struct vmap_area *va;
-
- va = find_vmap_area(addr);
- BUG_ON(!va);
- free_unmap_vmap_area(va);
-}
-
-
/*** Per cpu kva allocator ***/
/*
@@ -1070,6 +1041,8 @@ void vm_unmap_aliases(void)
if (unlikely(!vmap_initialized))
return;
+ might_sleep();
+
for_each_possible_cpu(cpu) {
struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu);
struct vmap_block *vb;
@@ -1094,7 +1067,11 @@ void vm_unmap_aliases(void)
rcu_read_unlock();
}
- __purge_vmap_area_lazy(&start, &end, 1, flush);
+ mutex_lock(&vmap_purge_lock);
+ purge_fragmented_blocks_allcpus();
+ if (!__purge_vmap_area_lazy(start, end) && flush)
+ flush_tlb_kernel_range(start, end);
+ mutex_unlock(&vmap_purge_lock);
}
EXPORT_SYMBOL_GPL(vm_unmap_aliases);
@@ -1107,7 +1084,9 @@ void vm_unmap_ram(const void *mem, unsigned int count)
{
unsigned long size = (unsigned long)count << PAGE_SHIFT;
unsigned long addr = (unsigned long)mem;
+ struct vmap_area *va;
+ might_sleep();
BUG_ON(!addr);
BUG_ON(addr < VMALLOC_START);
BUG_ON(addr > VMALLOC_END);
@@ -1116,10 +1095,14 @@ void vm_unmap_ram(const void *mem, unsigned int count)
debug_check_no_locks_freed(mem, size);
vmap_debug_free_range(addr, addr+size);
- if (likely(count <= VMAP_MAX_ALLOC))
+ if (likely(count <= VMAP_MAX_ALLOC)) {
vb_free(mem, size);
- else
- free_unmap_vmap_area_addr(addr);
+ return;
+ }
+
+ va = find_vmap_area(addr);
+ BUG_ON(!va);
+ free_unmap_vmap_area(va);
}
EXPORT_SYMBOL(vm_unmap_ram);
@@ -1455,6 +1438,8 @@ struct vm_struct *remove_vm_area(const void *addr)
{
struct vmap_area *va;
+ might_sleep();
+
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA) {
struct vm_struct *vm = va->vm;
@@ -1510,7 +1495,39 @@ static void __vunmap(const void *addr, int deallocate_pages)
kfree(area);
return;
}
-
+
+static inline void __vfree_deferred(const void *addr)
+{
+ /*
+ * Use raw_cpu_ptr() because this can be called from preemptible
+ * context. Preemption is absolutely fine here, because the llist_add()
+ * implementation is lockless, so it works even if we are adding to
+ * nother cpu's list. schedule_work() should be fine with this too.
+ */
+ struct vfree_deferred *p = raw_cpu_ptr(&vfree_deferred);
+
+ if (llist_add((struct llist_node *)addr, &p->list))
+ schedule_work(&p->wq);
+}
+
+/**
+ * vfree_atomic - release memory allocated by vmalloc()
+ * @addr: memory base address
+ *
+ * This one is just like vfree() but can be called in any atomic context
+ * except NMIs.
+ */
+void vfree_atomic(const void *addr)
+{
+ BUG_ON(in_nmi());
+
+ kmemleak_free(addr);
+
+ if (!addr)
+ return;
+ __vfree_deferred(addr);
+}
+
/**
* vfree - release memory allocated by vmalloc()
* @addr: memory base address
@@ -1533,11 +1550,9 @@ void vfree(const void *addr)
if (!addr)
return;
- if (unlikely(in_interrupt())) {
- struct vfree_deferred *p = this_cpu_ptr(&vfree_deferred);
- if (llist_add((struct llist_node *)addr, &p->list))
- schedule_work(&p->wq);
- } else
+ if (unlikely(in_interrupt()))
+ __vfree_deferred(addr);
+ else
__vunmap(addr, 1);
}
EXPORT_SYMBOL(vfree);
@@ -2574,32 +2589,13 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
static void *s_start(struct seq_file *m, loff_t *pos)
__acquires(&vmap_area_lock)
{
- loff_t n = *pos;
- struct vmap_area *va;
-
spin_lock(&vmap_area_lock);
- va = list_first_entry(&vmap_area_list, typeof(*va), list);
- while (n > 0 && &va->list != &vmap_area_list) {
- n--;
- va = list_next_entry(va, list);
- }
- if (!n && &va->list != &vmap_area_list)
- return va;
-
- return NULL;
-
+ return seq_list_start(&vmap_area_list, *pos);
}
static void *s_next(struct seq_file *m, void *p, loff_t *pos)
{
- struct vmap_area *va = p, *next;
-
- ++*pos;
- next = list_next_entry(va, list);
- if (&next->list != &vmap_area_list)
- return next;
-
- return NULL;
+ return seq_list_next(p, &vmap_area_list, pos);
}
static void s_stop(struct seq_file *m, void *p)
@@ -2634,9 +2630,11 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v)
static int s_show(struct seq_file *m, void *p)
{
- struct vmap_area *va = p;
+ struct vmap_area *va;
struct vm_struct *v;
+ va = list_entry(p, struct vmap_area, list);
+
/*
* s_show can encounter race with remove_vm_area, !VM_VM_AREA on
* behalf of vmap area is being tear down or vm_map_ram allocation.
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d75cdf360730..6aa5b01d3e75 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -291,6 +291,7 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
int nid = shrinkctl->nid;
long batch_size = shrinker->batch ? shrinker->batch
: SHRINK_BATCH;
+ long scanned = 0, next_deferred;
freeable = shrinker->count_objects(shrinker, shrinkctl);
if (freeable == 0)
@@ -312,7 +313,9 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
shrinker->scan_objects, total_scan);
total_scan = freeable;
- }
+ next_deferred = nr;
+ } else
+ next_deferred = total_scan;
/*
* We need to avoid excessive windup on filesystem shrinkers
@@ -369,17 +372,22 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
count_vm_events(SLABS_SCANNED, nr_to_scan);
total_scan -= nr_to_scan;
+ scanned += nr_to_scan;
cond_resched();
}
+ if (next_deferred >= scanned)
+ next_deferred -= scanned;
+ else
+ next_deferred = 0;
/*
* move the unused scan count back into the shrinker in a
* manner that handles concurrent updates. If we exhausted the
* scan, there is no need to do an update.
*/
- if (total_scan > 0)
- new_nr = atomic_long_add_return(total_scan,
+ if (next_deferred > 0)
+ new_nr = atomic_long_add_return(next_deferred,
&shrinker->nr_deferred[nid]);
else
new_nr = atomic_long_read(&shrinker->nr_deferred[nid]);
@@ -3558,24 +3566,21 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
not required for correctness. So if the last cpu in a node goes
away, we get changed to run anywhere: as the first one comes back,
restore their cpu bindings. */
-static int cpu_callback(struct notifier_block *nfb, unsigned long action,
- void *hcpu)
+static int kswapd_cpu_online(unsigned int cpu)
{
int nid;
- if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
- for_each_node_state(nid, N_MEMORY) {
- pg_data_t *pgdat = NODE_DATA(nid);
- const struct cpumask *mask;
+ for_each_node_state(nid, N_MEMORY) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ const struct cpumask *mask;
- mask = cpumask_of_node(pgdat->node_id);
+ mask = cpumask_of_node(pgdat->node_id);
- if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
- /* One of our CPUs online: restore mask */
- set_cpus_allowed_ptr(pgdat->kswapd, mask);
- }
+ if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
+ /* One of our CPUs online: restore mask */
+ set_cpus_allowed_ptr(pgdat->kswapd, mask);
}
- return NOTIFY_OK;
+ return 0;
}
/*
@@ -3617,12 +3622,15 @@ void kswapd_stop(int nid)
static int __init kswapd_init(void)
{
- int nid;
+ int nid, ret;
swap_setup();
for_each_node_state(nid, N_MEMORY)
kswapd_run(nid);
- hotcpu_notifier(cpu_callback, 0);
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "mm/vmscan:online", kswapd_cpu_online,
+ NULL);
+ WARN_ON(ret < 0);
return 0;
}
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 604f26a4f696..7c28df36f50f 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1720,75 +1720,66 @@ static void __init start_shepherd_timer(void)
static void __init init_cpu_node_state(void)
{
- int cpu;
+ int node;
- get_online_cpus();
- for_each_online_cpu(cpu)
- node_set_state(cpu_to_node(cpu), N_CPU);
- put_online_cpus();
+ for_each_online_node(node) {
+ if (cpumask_weight(cpumask_of_node(node)) > 0)
+ node_set_state(node, N_CPU);
+ }
}
-static void vmstat_cpu_dead(int node)
+static int vmstat_cpu_online(unsigned int cpu)
{
- int cpu;
-
- get_online_cpus();
- for_each_online_cpu(cpu)
- if (cpu_to_node(cpu) == node)
- goto end;
+ refresh_zone_stat_thresholds();
+ node_set_state(cpu_to_node(cpu), N_CPU);
+ return 0;
+}
- node_clear_state(node, N_CPU);
-end:
- put_online_cpus();
+static int vmstat_cpu_down_prep(unsigned int cpu)
+{
+ cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
+ return 0;
}
-/*
- * Use the cpu notifier to insure that the thresholds are recalculated
- * when necessary.
- */
-static int vmstat_cpuup_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
-{
- long cpu = (long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- refresh_zone_stat_thresholds();
- node_set_state(cpu_to_node(cpu), N_CPU);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
- break;
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- refresh_zone_stat_thresholds();
- vmstat_cpu_dead(cpu_to_node(cpu));
- break;
- default:
- break;
- }
- return NOTIFY_OK;
+static int vmstat_cpu_dead(unsigned int cpu)
+{
+ const struct cpumask *node_cpus;
+ int node;
+
+ node = cpu_to_node(cpu);
+
+ refresh_zone_stat_thresholds();
+ node_cpus = cpumask_of_node(node);
+ if (cpumask_weight(node_cpus) > 0)
+ return 0;
+
+ node_clear_state(node, N_CPU);
+ return 0;
}
-static struct notifier_block vmstat_notifier =
- { &vmstat_cpuup_callback, NULL, 0 };
#endif
static int __init setup_vmstat(void)
{
#ifdef CONFIG_SMP
- cpu_notifier_register_begin();
- __register_cpu_notifier(&vmstat_notifier);
+ int ret;
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
+ NULL, vmstat_cpu_dead);
+ if (ret < 0)
+ pr_err("vmstat: failed to register 'dead' hotplug state\n");
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "mm/vmstat:online",
+ vmstat_cpu_online,
+ vmstat_cpu_down_prep);
+ if (ret < 0)
+ pr_err("vmstat: failed to register 'online' hotplug state\n");
+
+ get_online_cpus();
init_cpu_node_state();
+ put_online_cpus();
start_shepherd_timer();
- cpu_notifier_register_done();
#endif
#ifdef CONFIG_PROC_FS
proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
diff --git a/mm/workingset.c b/mm/workingset.c
index fb1f9183d89a..241fa5d6b3b2 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -10,6 +10,7 @@
#include <linux/atomic.h>
#include <linux/module.h>
#include <linux/swap.h>
+#include <linux/dax.h>
#include <linux/fs.h>
#include <linux/mm.h>
@@ -334,48 +335,81 @@ out:
* point where they would still be useful.
*/
-struct list_lru workingset_shadow_nodes;
+static struct list_lru shadow_nodes;
+
+void workingset_update_node(struct radix_tree_node *node, void *private)
+{
+ struct address_space *mapping = private;
+
+ /* Only regular page cache has shadow entries */
+ if (dax_mapping(mapping) || shmem_mapping(mapping))
+ return;
+
+ /*
+ * Track non-empty nodes that contain only shadow entries;
+ * unlink those that contain pages or are being freed.
+ *
+ * Avoid acquiring the list_lru lock when the nodes are
+ * already where they should be. The list_empty() test is safe
+ * as node->private_list is protected by &mapping->tree_lock.
+ */
+ if (node->count && node->count == node->exceptional) {
+ if (list_empty(&node->private_list)) {
+ node->private_data = mapping;
+ list_lru_add(&shadow_nodes, &node->private_list);
+ }
+ } else {
+ if (!list_empty(&node->private_list))
+ list_lru_del(&shadow_nodes, &node->private_list);
+ }
+}
static unsigned long count_shadow_nodes(struct shrinker *shrinker,
struct shrink_control *sc)
{
- unsigned long shadow_nodes;
unsigned long max_nodes;
- unsigned long pages;
+ unsigned long nodes;
+ unsigned long cache;
/* list_lru lock nests inside IRQ-safe mapping->tree_lock */
local_irq_disable();
- shadow_nodes = list_lru_shrink_count(&workingset_shadow_nodes, sc);
+ nodes = list_lru_shrink_count(&shadow_nodes, sc);
local_irq_enable();
- if (sc->memcg) {
- pages = mem_cgroup_node_nr_lru_pages(sc->memcg, sc->nid,
- LRU_ALL_FILE);
- } else {
- pages = node_page_state(NODE_DATA(sc->nid), NR_ACTIVE_FILE) +
- node_page_state(NODE_DATA(sc->nid), NR_INACTIVE_FILE);
- }
-
/*
- * Active cache pages are limited to 50% of memory, and shadow
- * entries that represent a refault distance bigger than that
- * do not have any effect. Limit the number of shadow nodes
- * such that shadow entries do not exceed the number of active
- * cache pages, assuming a worst-case node population density
- * of 1/8th on average.
+ * Approximate a reasonable limit for the radix tree nodes
+ * containing shadow entries. We don't need to keep more
+ * shadow entries than possible pages on the active list,
+ * since refault distances bigger than that are dismissed.
+ *
+ * The size of the active list converges toward 100% of
+ * overall page cache as memory grows, with only a tiny
+ * inactive list. Assume the total cache size for that.
+ *
+ * Nodes might be sparsely populated, with only one shadow
+ * entry in the extreme case. Obviously, we cannot keep one
+ * node for every eligible shadow entry, so compromise on a
+ * worst-case density of 1/8th. Below that, not all eligible
+ * refaults can be detected anymore.
*
* On 64-bit with 7 radix_tree_nodes per page and 64 slots
* each, this will reclaim shadow entries when they consume
- * ~2% of available memory:
+ * ~1.8% of available memory:
*
- * PAGE_SIZE / radix_tree_nodes / node_entries / PAGE_SIZE
+ * PAGE_SIZE / radix_tree_nodes / node_entries * 8 / PAGE_SIZE
*/
- max_nodes = pages >> (1 + RADIX_TREE_MAP_SHIFT - 3);
+ if (sc->memcg) {
+ cache = mem_cgroup_node_nr_lru_pages(sc->memcg, sc->nid,
+ LRU_ALL_FILE);
+ } else {
+ cache = node_page_state(NODE_DATA(sc->nid), NR_ACTIVE_FILE) +
+ node_page_state(NODE_DATA(sc->nid), NR_INACTIVE_FILE);
+ }
+ max_nodes = cache >> (RADIX_TREE_MAP_SHIFT - 3);
- if (shadow_nodes <= max_nodes)
+ if (nodes <= max_nodes)
return 0;
-
- return shadow_nodes - max_nodes;
+ return nodes - max_nodes;
}
static enum lru_status shadow_lru_isolate(struct list_head *item,
@@ -418,23 +452,30 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
* no pages, so we expect to be able to remove them all and
* delete and free the empty node afterwards.
*/
- BUG_ON(!workingset_node_shadows(node));
- BUG_ON(workingset_node_pages(node));
-
+ if (WARN_ON_ONCE(!node->exceptional))
+ goto out_invalid;
+ if (WARN_ON_ONCE(node->count != node->exceptional))
+ goto out_invalid;
for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
if (node->slots[i]) {
- BUG_ON(!radix_tree_exceptional_entry(node->slots[i]));
+ if (WARN_ON_ONCE(!radix_tree_exceptional_entry(node->slots[i])))
+ goto out_invalid;
+ if (WARN_ON_ONCE(!node->exceptional))
+ goto out_invalid;
+ if (WARN_ON_ONCE(!mapping->nrexceptional))
+ goto out_invalid;
node->slots[i] = NULL;
- workingset_node_shadows_dec(node);
- BUG_ON(!mapping->nrexceptional);
+ node->exceptional--;
+ node->count--;
mapping->nrexceptional--;
}
}
- BUG_ON(workingset_node_shadows(node));
+ if (WARN_ON_ONCE(node->exceptional))
+ goto out_invalid;
inc_node_state(page_pgdat(virt_to_page(node)), WORKINGSET_NODERECLAIM);
- if (!__radix_tree_delete_node(&mapping->page_tree, node))
- BUG();
+ __radix_tree_delete_node(&mapping->page_tree, node);
+out_invalid:
spin_unlock(&mapping->tree_lock);
ret = LRU_REMOVED_RETRY;
out:
@@ -452,8 +493,7 @@ static unsigned long scan_shadow_nodes(struct shrinker *shrinker,
/* list_lru lock nests inside IRQ-safe mapping->tree_lock */
local_irq_disable();
- ret = list_lru_shrink_walk(&workingset_shadow_nodes, sc,
- shadow_lru_isolate, NULL);
+ ret = list_lru_shrink_walk(&shadow_nodes, sc, shadow_lru_isolate, NULL);
local_irq_enable();
return ret;
}
@@ -492,7 +532,7 @@ static int __init workingset_init(void)
pr_info("workingset: timestamp_bits=%d max_order=%d bucket_order=%u\n",
timestamp_bits, max_order, bucket_order);
- ret = list_lru_init_key(&workingset_shadow_nodes, &shadow_nodes_key);
+ ret = list_lru_init_key(&shadow_nodes, &shadow_nodes_key);
if (ret)
goto err;
ret = register_shrinker(&workingset_shadow_shrinker);
@@ -500,7 +540,7 @@ static int __init workingset_init(void)
goto err_list_lru;
return 0;
err_list_lru:
- list_lru_destroy(&workingset_shadow_nodes);
+ list_lru_destroy(&shadow_nodes);
err:
return ret;
}
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index b0bc023d25c5..9cc3c0b2c2c1 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1284,61 +1284,21 @@ out:
#endif /* CONFIG_PGTABLE_MAPPING */
-static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action,
- void *pcpu)
+static int zs_cpu_prepare(unsigned int cpu)
{
- int ret, cpu = (long)pcpu;
struct mapping_area *area;
- switch (action) {
- case CPU_UP_PREPARE:
- area = &per_cpu(zs_map_area, cpu);
- ret = __zs_cpu_up(area);
- if (ret)
- return notifier_from_errno(ret);
- break;
- case CPU_DEAD:
- case CPU_UP_CANCELED:
- area = &per_cpu(zs_map_area, cpu);
- __zs_cpu_down(area);
- break;
- }
-
- return NOTIFY_OK;
+ area = &per_cpu(zs_map_area, cpu);
+ return __zs_cpu_up(area);
}
-static struct notifier_block zs_cpu_nb = {
- .notifier_call = zs_cpu_notifier
-};
-
-static int zs_register_cpu_notifier(void)
+static int zs_cpu_dead(unsigned int cpu)
{
- int cpu, uninitialized_var(ret);
-
- cpu_notifier_register_begin();
-
- __register_cpu_notifier(&zs_cpu_nb);
- for_each_online_cpu(cpu) {
- ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
- if (notifier_to_errno(ret))
- break;
- }
-
- cpu_notifier_register_done();
- return notifier_to_errno(ret);
-}
-
-static void zs_unregister_cpu_notifier(void)
-{
- int cpu;
-
- cpu_notifier_register_begin();
-
- for_each_online_cpu(cpu)
- zs_cpu_notifier(NULL, CPU_DEAD, (void *)(long)cpu);
- __unregister_cpu_notifier(&zs_cpu_nb);
+ struct mapping_area *area;
- cpu_notifier_register_done();
+ area = &per_cpu(zs_map_area, cpu);
+ __zs_cpu_down(area);
+ return 0;
}
static void __init init_zs_size_classes(void)
@@ -2534,10 +2494,10 @@ static int __init zs_init(void)
if (ret)
goto out;
- ret = zs_register_cpu_notifier();
-
+ ret = cpuhp_setup_state(CPUHP_MM_ZS_PREPARE, "mm/zsmalloc:prepare",
+ zs_cpu_prepare, zs_cpu_dead);
if (ret)
- goto notifier_fail;
+ goto hp_setup_fail;
init_zs_size_classes();
@@ -2549,8 +2509,7 @@ static int __init zs_init(void)
return 0;
-notifier_fail:
- zs_unregister_cpu_notifier();
+hp_setup_fail:
zsmalloc_unmount();
out:
return ret;
@@ -2562,7 +2521,7 @@ static void __exit zs_exit(void)
zpool_unregister_driver(&zs_zpool_driver);
#endif
zsmalloc_unmount();
- zs_unregister_cpu_notifier();
+ cpuhp_remove_state(CPUHP_MM_ZS_PREPARE);
zs_stat_exit();
}
diff --git a/mm/zswap.c b/mm/zswap.c
index 275b22cc8df4..067a0d62f318 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -118,7 +118,7 @@ struct zswap_pool {
struct kref kref;
struct list_head list;
struct work_struct work;
- struct notifier_block notifier;
+ struct hlist_node node;
char tfm_name[CRYPTO_MAX_ALG_NAME];
};
@@ -352,143 +352,58 @@ static struct zswap_entry *zswap_entry_find_get(struct rb_root *root,
**********************************/
static DEFINE_PER_CPU(u8 *, zswap_dstmem);
-static int __zswap_cpu_dstmem_notifier(unsigned long action, unsigned long cpu)
+static int zswap_dstmem_prepare(unsigned int cpu)
{
u8 *dst;
- switch (action) {
- case CPU_UP_PREPARE:
- dst = kmalloc_node(PAGE_SIZE * 2, GFP_KERNEL, cpu_to_node(cpu));
- if (!dst) {
- pr_err("can't allocate compressor buffer\n");
- return NOTIFY_BAD;
- }
- per_cpu(zswap_dstmem, cpu) = dst;
- break;
- case CPU_DEAD:
- case CPU_UP_CANCELED:
- dst = per_cpu(zswap_dstmem, cpu);
- kfree(dst);
- per_cpu(zswap_dstmem, cpu) = NULL;
- break;
- default:
- break;
+ dst = kmalloc_node(PAGE_SIZE * 2, GFP_KERNEL, cpu_to_node(cpu));
+ if (!dst) {
+ pr_err("can't allocate compressor buffer\n");
+ return -ENOMEM;
}
- return NOTIFY_OK;
+ per_cpu(zswap_dstmem, cpu) = dst;
+ return 0;
}
-static int zswap_cpu_dstmem_notifier(struct notifier_block *nb,
- unsigned long action, void *pcpu)
+static int zswap_dstmem_dead(unsigned int cpu)
{
- return __zswap_cpu_dstmem_notifier(action, (unsigned long)pcpu);
-}
+ u8 *dst;
-static struct notifier_block zswap_dstmem_notifier = {
- .notifier_call = zswap_cpu_dstmem_notifier,
-};
+ dst = per_cpu(zswap_dstmem, cpu);
+ kfree(dst);
+ per_cpu(zswap_dstmem, cpu) = NULL;
-static int __init zswap_cpu_dstmem_init(void)
-{
- unsigned long cpu;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- if (__zswap_cpu_dstmem_notifier(CPU_UP_PREPARE, cpu) ==
- NOTIFY_BAD)
- goto cleanup;
- __register_cpu_notifier(&zswap_dstmem_notifier);
- cpu_notifier_register_done();
return 0;
-
-cleanup:
- for_each_online_cpu(cpu)
- __zswap_cpu_dstmem_notifier(CPU_UP_CANCELED, cpu);
- cpu_notifier_register_done();
- return -ENOMEM;
-}
-
-static void zswap_cpu_dstmem_destroy(void)
-{
- unsigned long cpu;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- __zswap_cpu_dstmem_notifier(CPU_UP_CANCELED, cpu);
- __unregister_cpu_notifier(&zswap_dstmem_notifier);
- cpu_notifier_register_done();
}
-static int __zswap_cpu_comp_notifier(struct zswap_pool *pool,
- unsigned long action, unsigned long cpu)
+static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)
{
+ struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
struct crypto_comp *tfm;
- switch (action) {
- case CPU_UP_PREPARE:
- if (WARN_ON(*per_cpu_ptr(pool->tfm, cpu)))
- break;
- tfm = crypto_alloc_comp(pool->tfm_name, 0, 0);
- if (IS_ERR_OR_NULL(tfm)) {
- pr_err("could not alloc crypto comp %s : %ld\n",
- pool->tfm_name, PTR_ERR(tfm));
- return NOTIFY_BAD;
- }
- *per_cpu_ptr(pool->tfm, cpu) = tfm;
- break;
- case CPU_DEAD:
- case CPU_UP_CANCELED:
- tfm = *per_cpu_ptr(pool->tfm, cpu);
- if (!IS_ERR_OR_NULL(tfm))
- crypto_free_comp(tfm);
- *per_cpu_ptr(pool->tfm, cpu) = NULL;
- break;
- default:
- break;
- }
- return NOTIFY_OK;
-}
-
-static int zswap_cpu_comp_notifier(struct notifier_block *nb,
- unsigned long action, void *pcpu)
-{
- unsigned long cpu = (unsigned long)pcpu;
- struct zswap_pool *pool = container_of(nb, typeof(*pool), notifier);
-
- return __zswap_cpu_comp_notifier(pool, action, cpu);
-}
+ if (WARN_ON(*per_cpu_ptr(pool->tfm, cpu)))
+ return 0;
-static int zswap_cpu_comp_init(struct zswap_pool *pool)
-{
- unsigned long cpu;
-
- memset(&pool->notifier, 0, sizeof(pool->notifier));
- pool->notifier.notifier_call = zswap_cpu_comp_notifier;
-
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- if (__zswap_cpu_comp_notifier(pool, CPU_UP_PREPARE, cpu) ==
- NOTIFY_BAD)
- goto cleanup;
- __register_cpu_notifier(&pool->notifier);
- cpu_notifier_register_done();
+ tfm = crypto_alloc_comp(pool->tfm_name, 0, 0);
+ if (IS_ERR_OR_NULL(tfm)) {
+ pr_err("could not alloc crypto comp %s : %ld\n",
+ pool->tfm_name, PTR_ERR(tfm));
+ return -ENOMEM;
+ }
+ *per_cpu_ptr(pool->tfm, cpu) = tfm;
return 0;
-
-cleanup:
- for_each_online_cpu(cpu)
- __zswap_cpu_comp_notifier(pool, CPU_UP_CANCELED, cpu);
- cpu_notifier_register_done();
- return -ENOMEM;
}
-static void zswap_cpu_comp_destroy(struct zswap_pool *pool)
+static int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node)
{
- unsigned long cpu;
+ struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
+ struct crypto_comp *tfm;
- cpu_notifier_register_begin();
- for_each_online_cpu(cpu)
- __zswap_cpu_comp_notifier(pool, CPU_UP_CANCELED, cpu);
- __unregister_cpu_notifier(&pool->notifier);
- cpu_notifier_register_done();
+ tfm = *per_cpu_ptr(pool->tfm, cpu);
+ if (!IS_ERR_OR_NULL(tfm))
+ crypto_free_comp(tfm);
+ *per_cpu_ptr(pool->tfm, cpu) = NULL;
+ return 0;
}
/*********************************
@@ -569,6 +484,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
struct zswap_pool *pool;
char name[38]; /* 'zswap' + 32 char (max) num + \0 */
gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
+ int ret;
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
if (!pool) {
@@ -593,7 +509,9 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
goto error;
}
- if (zswap_cpu_comp_init(pool))
+ ret = cpuhp_state_add_instance(CPUHP_MM_ZSWP_POOL_PREPARE,
+ &pool->node);
+ if (ret)
goto error;
pr_debug("using %s compressor\n", pool->tfm_name);
@@ -647,7 +565,7 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
{
zswap_pool_debug("destroying", pool);
- zswap_cpu_comp_destroy(pool);
+ cpuhp_state_remove_instance(CPUHP_MM_ZSWP_POOL_PREPARE, &pool->node);
free_percpu(pool->tfm);
zpool_destroy_pool(pool->zpool);
kfree(pool);
@@ -1238,6 +1156,7 @@ static void __exit zswap_debugfs_exit(void) { }
static int __init init_zswap(void)
{
struct zswap_pool *pool;
+ int ret;
zswap_init_started = true;
@@ -1246,11 +1165,20 @@ static int __init init_zswap(void)
goto cache_fail;
}
- if (zswap_cpu_dstmem_init()) {
+ ret = cpuhp_setup_state(CPUHP_MM_ZSWP_MEM_PREPARE, "mm/zswap:prepare",
+ zswap_dstmem_prepare, zswap_dstmem_dead);
+ if (ret) {
pr_err("dstmem alloc failed\n");
goto dstmem_fail;
}
+ ret = cpuhp_setup_state_multi(CPUHP_MM_ZSWP_POOL_PREPARE,
+ "mm/zswap_pool:prepare",
+ zswap_cpu_comp_prepare,
+ zswap_cpu_comp_dead);
+ if (ret)
+ goto hp_fail;
+
pool = __zswap_pool_create_fallback();
if (!pool) {
pr_err("pool creation failed\n");
@@ -1267,7 +1195,9 @@ static int __init init_zswap(void)
return 0;
pool_fail:
- zswap_cpu_dstmem_destroy();
+ cpuhp_remove_state_nocalls(CPUHP_MM_ZSWP_POOL_PREPARE);
+hp_fail:
+ cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
dstmem_fail:
zswap_entry_cache_destroy();
cache_fail:
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 7d3a0af954e8..6356623fc238 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -141,15 +141,6 @@ __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
EXPORT_SYMBOL(fddi_type_trans);
-int fddi_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-EXPORT_SYMBOL(fddi_change_mtu);
-
static const struct header_ops fddi_header_ops = {
.create = fddi_header,
};
@@ -161,6 +152,8 @@ static void fddi_setup(struct net_device *dev)
dev->type = ARPHRD_FDDI;
dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */
dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */
+ dev->min_mtu = FDDI_K_SNAP_HLEN;
+ dev->max_mtu = FDDI_K_SNAP_DLEN;
dev->addr_len = FDDI_K_ALEN;
dev->tx_queue_len = 100; /* Long queues on FDDI */
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
diff --git a/net/802/hippi.c b/net/802/hippi.c
index ade1a52cdcff..5e4427beab2b 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -116,18 +116,6 @@ __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
EXPORT_SYMBOL(hippi_type_trans);
-int hippi_change_mtu(struct net_device *dev, int new_mtu)
-{
- /*
- * HIPPI's got these nice large MTUs.
- */
- if ((new_mtu < 68) || (new_mtu > 65280))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-EXPORT_SYMBOL(hippi_change_mtu);
-
/*
* For HIPPI we will actually use the lower 4 bytes of the hardware
* address as the I-FIELD rather than the actual hardware address.
@@ -174,6 +162,8 @@ static void hippi_setup(struct net_device *dev)
dev->type = ARPHRD_HIPPI;
dev->hard_header_len = HIPPI_HLEN;
dev->mtu = 65280;
+ dev->min_mtu = 68;
+ dev->max_mtu = 65280;
dev->addr_len = HIPPI_ALEN;
dev->tx_queue_len = 25 /* 5 */;
memset(dev->broadcast, 0xFF, HIPPI_ALEN);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index f2531ad66b68..691f0ad7067d 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -44,7 +44,7 @@
/* Global VLAN variables */
-int vlan_net_id __read_mostly;
+unsigned int vlan_net_id __read_mostly;
const char vlan_fullname[] = "802.1Q VLAN Support";
const char vlan_version[] = DRV_VERSION;
@@ -515,8 +515,8 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
return -EFAULT;
/* Null terminate this sucker, just in case. */
- args.device1[23] = 0;
- args.u.device2[23] = 0;
+ args.device1[sizeof(args.device1) - 1] = 0;
+ args.u.device2[sizeof(args.u.device2) - 1] = 0;
rtnl_lock();
@@ -571,8 +571,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
err = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
- if ((args.u.name_type >= 0) &&
- (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
+ if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
struct vlan_net *vn;
vn = net_generic(net, vlan_net_id);
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index cc1557978066..df8bd65dd370 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -159,7 +159,7 @@ void vlan_netlink_fini(void);
extern struct rtnl_link_ops vlan_link_ops;
-extern int vlan_net_id;
+extern unsigned int vlan_net_id;
struct proc_dir_entry;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index fbfacd51aa34..10da6c588bf8 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -826,5 +826,8 @@ void vlan_setup(struct net_device *dev)
dev->destructor = vlan_dev_free;
dev->ethtool_ops = &vlan_ethtool_ops;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
+
eth_zero_addr(dev->broadcast);
}
diff --git a/net/Kconfig b/net/Kconfig
index 7b6cd340b72b..a1005007224c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -402,6 +402,14 @@ config LWTUNNEL
weight tunnel endpoint. Tunnel encapsulation parameters are stored
with light weight tunnel state associated with fib routes.
+config LWTUNNEL_BPF
+ bool "Execute BPF program as route nexthop action"
+ depends on LWTUNNEL
+ default y if LWTUNNEL=y
+ ---help---
+ Allows to run BPF programs as a nexthop action following a route
+ lookup for incoming and outgoing packets.
+
config DST_CACHE
bool
default n
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index aa0047c5c467..fca84e111c89 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -620,14 +620,12 @@ error:
static const struct net_device_ops br2684_netdev_ops = {
.ndo_start_xmit = br2684_start_xmit,
.ndo_set_mac_address = br2684_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
static const struct net_device_ops br2684_netdev_ops_routed = {
.ndo_start_xmit = br2684_start_xmit,
.ndo_set_mac_address = br2684_mac_addr,
- .ndo_change_mtu = eth_change_mtu
};
static void br2684_setup(struct net_device *netdev)
@@ -651,7 +649,9 @@ static void br2684_setup_routed(struct net_device *netdev)
netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */
netdev->netdev_ops = &br2684_netdev_ops_routed;
netdev->addr_len = 0;
- netdev->mtu = 1500;
+ netdev->mtu = ETH_DATA_LEN;
+ netdev->min_mtu = 0;
+ netdev->max_mtu = ETH_MAX_MTU;
netdev->type = ARPHRD_PPP;
netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
netdev->tx_queue_len = 100;
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 5d2693826afb..779b3fa6052d 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -544,15 +544,6 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
return 0;
}
-/* shamelessly stolen from drivers/net/net_init.c */
-static int lec_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > 18190))
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static void lec_set_multicast_list(struct net_device *dev)
{
/*
@@ -565,7 +556,6 @@ static const struct net_device_ops lec_netdev_ops = {
.ndo_open = lec_open,
.ndo_stop = lec_close,
.ndo_start_xmit = lec_start_xmit,
- .ndo_change_mtu = lec_change_mtu,
.ndo_tx_timeout = lec_tx_timeout,
.ndo_set_rx_mode = lec_set_multicast_list,
};
@@ -742,6 +732,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
if (!dev_lec[i])
return -ENOMEM;
dev_lec[i]->netdev_ops = &lec_netdev_ops;
+ dev_lec[i]->max_mtu = 18190;
snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
if (register_netdev(dev_lec[i])) {
free_netdev(dev_lec[i]);
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index f20742cbae6d..b73b96a2854b 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -17,7 +17,7 @@ config BATMAN_ADV
config BATMAN_ADV_BATMAN_V
bool "B.A.T.M.A.N. V protocol (experimental)"
- depends on BATMAN_ADV && CFG80211=y || (CFG80211=m && BATMAN_ADV=m)
+ depends on BATMAN_ADV && !(CFG80211=m && BATMAN_ADV=y)
default n
help
This option enables the B.A.T.M.A.N. V protocol, the successor
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e2d18d0b1f06..f00f666e2ccd 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -698,7 +698,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size);
if (!forw_packet_aggr->skb) {
- batadv_forw_packet_free(forw_packet_aggr);
+ batadv_forw_packet_free(forw_packet_aggr, true);
return;
}
@@ -717,17 +717,10 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
if (direct_link)
forw_packet_aggr->direct_link_flags |= 1;
- /* add new packet to packet list */
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
-
- /* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
batadv_iv_send_outstanding_bat_ogm_packet);
- queue_delayed_work(batadv_event_workqueue,
- &forw_packet_aggr->delayed_work,
- send_time - jiffies);
+
+ batadv_forw_packet_ogmv1_queue(bat_priv, forw_packet_aggr, send_time);
}
/* aggregate a new packet into the existing ogm packet */
@@ -1272,7 +1265,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
*/
tq_iface_penalty = BATADV_TQ_MAX_VALUE;
if (if_outgoing && (if_incoming == if_outgoing) &&
- batadv_is_wifi_netdev(if_outgoing->net_dev))
+ batadv_is_wifi_hardif(if_outgoing))
tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
bat_priv);
@@ -1611,7 +1604,7 @@ out:
if (hardif_neigh)
batadv_hardif_neigh_put(hardif_neigh);
- kfree_skb(skb_priv);
+ consume_skb(skb_priv);
}
/**
@@ -1783,17 +1776,17 @@ static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
struct delayed_work *delayed_work;
struct batadv_forw_packet *forw_packet;
struct batadv_priv *bat_priv;
+ bool dropped = false;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_del(&forw_packet->list);
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
- if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
+ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
+ dropped = true;
goto out;
+ }
batadv_iv_ogm_emit(forw_packet);
@@ -1810,7 +1803,10 @@ static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
batadv_iv_ogm_schedule(forw_packet->if_incoming);
out:
- batadv_forw_packet_free(forw_packet);
+ /* do we get something for free()? */
+ if (batadv_forw_packet_steal(forw_packet,
+ &bat_priv->forw_bat_list_lock))
+ batadv_forw_packet_free(forw_packet, dropped);
}
static int batadv_iv_ogm_receive(struct sk_buff *skb,
@@ -1820,17 +1816,18 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
struct batadv_ogm_packet *ogm_packet;
u8 *packet_pos;
int ogm_offset;
- bool ret;
+ bool res;
+ int ret = NET_RX_DROP;
- ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
- if (!ret)
- return NET_RX_DROP;
+ res = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
+ if (!res)
+ goto free_skb;
/* did we receive a B.A.T.M.A.N. IV OGM packet on an interface
* that does not have B.A.T.M.A.N. IV enabled ?
*/
if (bat_priv->algo_ops->iface.enable != batadv_iv_ogm_iface_enable)
- return NET_RX_DROP;
+ goto free_skb;
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
@@ -1851,8 +1848,15 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
ogm_packet = (struct batadv_ogm_packet *)packet_pos;
}
- kfree_skb(skb);
- return NET_RX_SUCCESS;
+ ret = NET_RX_SUCCESS;
+
+free_skb:
+ if (ret == NET_RX_SUCCESS)
+ consume_skb(skb);
+ else
+ kfree_skb(skb);
+
+ return ret;
}
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
@@ -2486,7 +2490,7 @@ batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
struct batadv_orig_node *orig_node;
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
orig_node = gw_node->orig_node;
router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
if (!router)
@@ -2674,7 +2678,7 @@ static void batadv_iv_gw_print(struct batadv_priv *bat_priv,
" Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth\n");
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
/* fails if orig_node has no router */
if (batadv_iv_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
continue;
@@ -2774,7 +2778,7 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
int idx = 0;
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip)
continue;
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index e79f6f01182e..2ac612d7bab4 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -750,7 +750,7 @@ batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
u32 max_bw = 0, bw;
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
if (!kref_get_unless_zero(&gw_node->refcount))
continue;
@@ -787,7 +787,7 @@ static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
struct batadv_orig_node *curr_gw_orig,
struct batadv_orig_node *orig_node)
{
- struct batadv_gw_node *curr_gw = NULL, *orig_gw = NULL;
+ struct batadv_gw_node *curr_gw, *orig_gw = NULL;
u32 gw_throughput, orig_throughput, threshold;
bool ret = false;
@@ -889,7 +889,7 @@ static void batadv_v_gw_print(struct batadv_priv *bat_priv,
" Gateway ( throughput) Nexthop [outgoingIF]: advertised uplink bandwidth\n");
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
/* fails if orig_node has no router */
if (batadv_v_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
continue;
@@ -1009,7 +1009,7 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
int idx = 0;
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip)
continue;
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index ee08540ce503..f2fb2f05b6bf 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -75,6 +75,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
{
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
struct ethtool_link_ksettings link_settings;
+ struct net_device *real_netdev;
struct station_info sinfo;
u32 throughput;
int ret;
@@ -89,23 +90,27 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
/* if this is a wireless device, then ask its throughput through
* cfg80211 API
*/
- if (batadv_is_wifi_netdev(hard_iface->net_dev)) {
- if (hard_iface->net_dev->ieee80211_ptr) {
- ret = cfg80211_get_station(hard_iface->net_dev,
- neigh->addr, &sinfo);
- if (ret == -ENOENT) {
- /* Node is not associated anymore! It would be
- * possible to delete this neighbor. For now set
- * the throughput metric to 0.
- */
- return 0;
- }
- if (!ret)
- return sinfo.expected_throughput / 100;
+ if (batadv_is_wifi_hardif(hard_iface)) {
+ if (!batadv_is_cfg80211_hardif(hard_iface))
+ /* unsupported WiFi driver version */
+ goto default_throughput;
+
+ real_netdev = batadv_get_real_netdev(hard_iface->net_dev);
+ if (!real_netdev)
+ goto default_throughput;
+
+ ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
+
+ dev_put(real_netdev);
+ if (ret == -ENOENT) {
+ /* Node is not associated anymore! It would be
+ * possible to delete this neighbor. For now set
+ * the throughput metric to 0.
+ */
+ return 0;
}
-
- /* unsupported WiFi driver version */
- goto default_throughput;
+ if (!ret)
+ return sinfo.expected_throughput / 100;
}
/* if not a wifi interface, check if this device provides data via
@@ -187,7 +192,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
int elp_skb_len;
/* this probing routine is for Wifi neighbours only */
- if (!batadv_is_wifi_netdev(hard_iface->net_dev))
+ if (!batadv_is_wifi_hardif(hard_iface))
return true;
/* probe the neighbor only if no unicast packets have been sent
@@ -352,7 +357,7 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
/* warn the user (again) if there is no throughput data is available */
hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
- if (batadv_is_wifi_netdev(hard_iface->net_dev))
+ if (batadv_is_wifi_hardif(hard_iface))
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
@@ -492,20 +497,21 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb,
struct batadv_elp_packet *elp_packet;
struct batadv_hard_iface *primary_if;
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
- bool ret;
+ bool res;
+ int ret = NET_RX_DROP;
- ret = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
- if (!ret)
- return NET_RX_DROP;
+ res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
+ if (!res)
+ goto free_skb;
if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
- return NET_RX_DROP;
+ goto free_skb;
/* did we receive a B.A.T.M.A.N. V ELP packet on an interface
* that does not have B.A.T.M.A.N. V ELP enabled ?
*/
if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
- return NET_RX_DROP;
+ goto free_skb;
elp_packet = (struct batadv_elp_packet *)skb->data;
@@ -516,14 +522,19 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb,
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
- goto out;
+ goto free_skb;
batadv_v_elp_neigh_update(bat_priv, ethhdr->h_source, if_incoming,
elp_packet);
-out:
- if (primary_if)
- batadv_hardif_put(primary_if);
- consume_skb(skb);
- return NET_RX_SUCCESS;
+ ret = NET_RX_SUCCESS;
+ batadv_hardif_put(primary_if);
+
+free_skb:
+ if (ret == NET_RX_SUCCESS)
+ consume_skb(skb);
+ else
+ kfree_skb(skb);
+
+ return ret;
}
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index 1aeeadca620c..38b9aab83fc0 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -140,6 +140,7 @@ static void batadv_v_ogm_send(struct work_struct *work)
unsigned char *ogm_buff, *pkt_buff;
int ogm_buff_len;
u16 tvlv_len = 0;
+ int ret;
bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
@@ -182,6 +183,31 @@ static void batadv_v_ogm_send(struct work_struct *work)
if (!kref_get_unless_zero(&hard_iface->refcount))
continue;
+ ret = batadv_hardif_no_broadcast(hard_iface, NULL, NULL);
+ if (ret) {
+ char *type;
+
+ switch (ret) {
+ case BATADV_HARDIF_BCAST_NORECIPIENT:
+ type = "no neighbor";
+ break;
+ case BATADV_HARDIF_BCAST_DUPFWD:
+ type = "single neighbor is source";
+ break;
+ case BATADV_HARDIF_BCAST_DUPORIG:
+ type = "single neighbor is originator";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 from ourselve on %s surpressed: %s\n",
+ hard_iface->net_dev->name, type);
+
+ batadv_hardif_put(hard_iface);
+ continue;
+ }
+
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
ogm_packet->orig, ntohl(ogm_packet->seqno),
@@ -401,7 +427,7 @@ static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_incoming,
struct batadv_hard_iface *if_outgoing)
{
- struct batadv_orig_ifinfo *orig_ifinfo = NULL;
+ struct batadv_orig_ifinfo *orig_ifinfo;
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
bool protection_started = false;
int ret = -EINVAL;
@@ -486,7 +512,7 @@ static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing)
{
struct batadv_neigh_node *router = NULL;
- struct batadv_orig_node *orig_neigh_node = NULL;
+ struct batadv_orig_node *orig_neigh_node;
struct batadv_neigh_node *orig_neigh_router = NULL;
struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
u32 router_throughput, neigh_throughput;
@@ -651,6 +677,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
struct batadv_hard_iface *hard_iface;
struct batadv_ogm2_packet *ogm_packet;
u32 ogm_throughput, link_throughput, path_throughput;
+ int ret;
ethhdr = eth_hdr(skb);
ogm_packet = (struct batadv_ogm2_packet *)(skb->data + ogm_offset);
@@ -716,6 +743,35 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
if (!kref_get_unless_zero(&hard_iface->refcount))
continue;
+ ret = batadv_hardif_no_broadcast(hard_iface,
+ ogm_packet->orig,
+ hardif_neigh->orig);
+
+ if (ret) {
+ char *type;
+
+ switch (ret) {
+ case BATADV_HARDIF_BCAST_NORECIPIENT:
+ type = "no neighbor";
+ break;
+ case BATADV_HARDIF_BCAST_DUPFWD:
+ type = "single neighbor is source";
+ break;
+ case BATADV_HARDIF_BCAST_DUPORIG:
+ type = "single neighbor is originator";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 packet from %pM on %s surpressed: %s\n",
+ ogm_packet->orig, hard_iface->net_dev->name,
+ type);
+
+ batadv_hardif_put(hard_iface);
+ continue;
+ }
+
batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
orig_node, neigh_node,
if_incoming, hard_iface);
@@ -754,18 +810,18 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
* B.A.T.M.A.N. V enabled ?
*/
if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
- return NET_RX_DROP;
+ goto free_skb;
if (!batadv_check_management_packet(skb, if_incoming, BATADV_OGM2_HLEN))
- return NET_RX_DROP;
+ goto free_skb;
if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
- return NET_RX_DROP;
+ goto free_skb;
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
if (batadv_is_my_mac(bat_priv, ogm_packet->orig))
- return NET_RX_DROP;
+ goto free_skb;
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
@@ -786,7 +842,12 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
}
ret = NET_RX_SUCCESS;
- consume_skb(skb);
+
+free_skb:
+ if (ret == NET_RX_SUCCESS)
+ consume_skb(skb);
+ else
+ kfree_skb(skb);
return ret;
}
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index b4ffba7dd583..77925504379d 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -186,7 +186,7 @@ struct batadv_debuginfo batadv_debuginfo_##_name = { \
/* the following attributes are general and therefore they will be directly
* placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
*/
-static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+static BATADV_DEBUGINFO(routing_algos, 0444, batadv_algorithms_open);
static struct batadv_debuginfo *batadv_general_debuginfos[] = {
&batadv_debuginfo_routing_algos,
@@ -194,26 +194,24 @@ static struct batadv_debuginfo *batadv_general_debuginfos[] = {
};
/* The following attributes are per soft interface */
-static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open);
-static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
-static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
-static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
- batadv_transtable_global_open);
+static BATADV_DEBUGINFO(neighbors, 0444, neighbors_open);
+static BATADV_DEBUGINFO(originators, 0444, batadv_originators_open);
+static BATADV_DEBUGINFO(gateways, 0444, batadv_gateways_open);
+static BATADV_DEBUGINFO(transtable_global, 0444, batadv_transtable_global_open);
#ifdef CONFIG_BATMAN_ADV_BLA
-static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
-static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
+static BATADV_DEBUGINFO(bla_claim_table, 0444, batadv_bla_claim_table_open);
+static BATADV_DEBUGINFO(bla_backbone_table, 0444,
batadv_bla_backbone_table_open);
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
-static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
+static BATADV_DEBUGINFO(dat_cache, 0444, batadv_dat_cache_open);
#endif
-static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
- batadv_transtable_local_open);
+static BATADV_DEBUGINFO(transtable_local, 0444, batadv_transtable_local_open);
#ifdef CONFIG_BATMAN_ADV_NC
-static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
+static BATADV_DEBUGINFO(nc_nodes, 0444, batadv_nc_nodes_open);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
-static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open);
+static BATADV_DEBUGINFO(mcast_flags, 0444, batadv_mcast_flags_open);
#endif
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
@@ -253,7 +251,7 @@ struct batadv_debuginfo batadv_hardif_debuginfo_##_name = { \
}, \
}
-static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
+static BATADV_HARDIF_DEBUGINFO(originators, 0444,
batadv_originators_hardif_open);
static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index e257efdc5d03..49576c5a3fe3 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -369,12 +369,11 @@ out:
* batadv_dbg_arp - print a debug message containing all the ARP packet details
* @bat_priv: the bat priv with all the soft interface information
* @skb: ARP packet
- * @type: ARP type
* @hdr_size: size of the possible header before the ARP packet
* @msg: message to print together with the debugging information
*/
static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
- u16 type, int hdr_size, char *msg)
+ int hdr_size, char *msg)
{
struct batadv_unicast_4addr_packet *unicast_4addr_packet;
struct batadv_bcast_packet *bcast_pkt;
@@ -441,7 +440,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
#else
static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
- u16 type, int hdr_size, char *msg)
+ int hdr_size, char *msg)
{
}
@@ -950,6 +949,41 @@ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size)
}
/**
+ * batadv_dat_arp_create_reply - create an ARP Reply
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip_src: ARP sender IP
+ * @ip_dst: ARP target IP
+ * @hw_src: Ethernet source and ARP sender MAC
+ * @hw_dst: Ethernet destination and ARP target MAC
+ * @vid: VLAN identifier (optional, set to zero otherwise)
+ *
+ * Creates an ARP Reply from the given values, optionally encapsulated in a
+ * VLAN header.
+ *
+ * Return: An skb containing an ARP Reply.
+ */
+static struct sk_buff *
+batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
+ __be32 ip_dst, u8 *hw_src, u8 *hw_dst,
+ unsigned short vid)
+{
+ struct sk_buff *skb;
+
+ skb = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_dst, bat_priv->soft_iface,
+ ip_src, hw_dst, hw_src, hw_dst);
+ if (!skb)
+ return NULL;
+
+ skb_reset_mac_header(skb);
+
+ if (vid & BATADV_VLAN_HAS_TAG)
+ skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
+ vid & VLAN_VID_MASK);
+
+ return skb;
+}
+
+/**
* batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
* answer using DAT
* @bat_priv: the bat priv with all the soft interface information
@@ -983,8 +1017,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
if (type != ARPOP_REQUEST)
goto out;
- batadv_dbg_arp(bat_priv, skb, type, hdr_size,
- "Parsing outgoing ARP REQUEST");
+ batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing outgoing ARP REQUEST");
ip_src = batadv_arp_ip_src(skb, hdr_size);
hw_src = batadv_arp_hw_src(skb, hdr_size);
@@ -1007,20 +1040,12 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
goto out;
}
- skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
- bat_priv->soft_iface, ip_dst, hw_src,
- dat_entry->mac_addr, hw_src);
+ skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src,
+ dat_entry->mac_addr,
+ hw_src, vid);
if (!skb_new)
goto out;
- if (vid & BATADV_VLAN_HAS_TAG) {
- skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q),
- vid & VLAN_VID_MASK);
- if (!skb_new)
- goto out;
- }
-
- skb_reset_mac_header(skb_new);
skb_new->protocol = eth_type_trans(skb_new,
bat_priv->soft_iface);
bat_priv->stats.rx_packets++;
@@ -1075,8 +1100,7 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
ip_src = batadv_arp_ip_src(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dbg_arp(bat_priv, skb, type, hdr_size,
- "Parsing incoming ARP REQUEST");
+ batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REQUEST");
batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
@@ -1084,25 +1108,11 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
if (!dat_entry)
goto out;
- skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
- bat_priv->soft_iface, ip_dst, hw_src,
- dat_entry->mac_addr, hw_src);
-
+ skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src,
+ dat_entry->mac_addr, hw_src, vid);
if (!skb_new)
goto out;
- /* the rest of the TX path assumes that the mac_header offset pointing
- * to the inner Ethernet header has been set, therefore reset it now.
- */
- skb_reset_mac_header(skb_new);
-
- if (vid & BATADV_VLAN_HAS_TAG) {
- skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q),
- vid & VLAN_VID_MASK);
- if (!skb_new)
- goto out;
- }
-
/* To preserve backwards compatibility, the node has choose the outgoing
* format based on the incoming request packet type. The assumption is
* that a node not using the 4addr packet format doesn't support it.
@@ -1149,8 +1159,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
if (type != ARPOP_REPLY)
return;
- batadv_dbg_arp(bat_priv, skb, type, hdr_size,
- "Parsing outgoing ARP REPLY");
+ batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing outgoing ARP REPLY");
hw_src = batadv_arp_hw_src(skb, hdr_size);
ip_src = batadv_arp_ip_src(skb, hdr_size);
@@ -1195,8 +1204,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
if (type != ARPOP_REPLY)
goto out;
- batadv_dbg_arp(bat_priv, skb, type, hdr_size,
- "Parsing incoming ARP REPLY");
+ batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REPLY");
hw_src = batadv_arp_hw_src(skb, hdr_size);
ip_src = batadv_arp_ip_src(skb, hdr_size);
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 0934730fb7ff..9c561e683f4b 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -20,6 +20,7 @@
#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
+#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/fs.h>
#include <linux/if_ether.h>
@@ -42,17 +43,23 @@
/**
* batadv_frag_clear_chain - delete entries in the fragment buffer chain
* @head: head of chain with entries.
+ * @dropped: whether the chain is cleared because all fragments are dropped
*
* Free fragments in the passed hlist. Should be called with appropriate lock.
*/
-static void batadv_frag_clear_chain(struct hlist_head *head)
+static void batadv_frag_clear_chain(struct hlist_head *head, bool dropped)
{
struct batadv_frag_list_entry *entry;
struct hlist_node *node;
hlist_for_each_entry_safe(entry, node, head, list) {
hlist_del(&entry->list);
- kfree_skb(entry->skb);
+
+ if (dropped)
+ kfree_skb(entry->skb);
+ else
+ consume_skb(entry->skb);
+
kfree(entry);
}
}
@@ -73,7 +80,7 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node,
spin_lock_bh(&chain->lock);
if (!check_cb || check_cb(chain)) {
- batadv_frag_clear_chain(&chain->head);
+ batadv_frag_clear_chain(&chain->fragment_list, true);
chain->size = 0;
}
@@ -117,8 +124,8 @@ static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain,
if (chain->seqno == seqno)
return false;
- if (!hlist_empty(&chain->head))
- batadv_frag_clear_chain(&chain->head);
+ if (!hlist_empty(&chain->fragment_list))
+ batadv_frag_clear_chain(&chain->fragment_list, true);
chain->size = 0;
chain->seqno = seqno;
@@ -176,7 +183,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
chain = &orig_node->fragments[bucket];
spin_lock_bh(&chain->lock);
if (batadv_frag_init_chain(chain, seqno)) {
- hlist_add_head(&frag_entry_new->list, &chain->head);
+ hlist_add_head(&frag_entry_new->list, &chain->fragment_list);
chain->size = skb->len - hdr_size;
chain->timestamp = jiffies;
chain->total_size = ntohs(frag_packet->total_size);
@@ -185,7 +192,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
}
/* Find the position for the new fragment. */
- hlist_for_each_entry(frag_entry_curr, &chain->head, list) {
+ hlist_for_each_entry(frag_entry_curr, &chain->fragment_list, list) {
/* Drop packet if fragment already exists. */
if (frag_entry_curr->no == frag_entry_new->no)
goto err_unlock;
@@ -220,11 +227,11 @@ out:
* exceeds the maximum size of one merged packet. Don't allow
* packets to have different total_size.
*/
- batadv_frag_clear_chain(&chain->head);
+ batadv_frag_clear_chain(&chain->fragment_list, true);
chain->size = 0;
} else if (ntohs(frag_packet->total_size) == chain->size) {
/* All fragments received. Hand over chain to caller. */
- hlist_move_list(&chain->head, chain_out);
+ hlist_move_list(&chain->fragment_list, chain_out);
chain->size = 0;
}
@@ -252,8 +259,9 @@ batadv_frag_merge_packets(struct hlist_head *chain)
{
struct batadv_frag_packet *packet;
struct batadv_frag_list_entry *entry;
- struct sk_buff *skb_out = NULL;
+ struct sk_buff *skb_out;
int size, hdr_size = sizeof(struct batadv_frag_packet);
+ bool dropped = false;
/* Remove first entry, as this is the destination for the rest of the
* fragments.
@@ -270,6 +278,7 @@ batadv_frag_merge_packets(struct hlist_head *chain)
if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) {
kfree_skb(skb_out);
skb_out = NULL;
+ dropped = true;
goto free;
}
@@ -291,7 +300,7 @@ batadv_frag_merge_packets(struct hlist_head *chain)
free:
/* Locking is not needed, because 'chain' is not part of any orig. */
- batadv_frag_clear_chain(chain);
+ batadv_frag_clear_chain(chain, dropped);
return skb_out;
}
@@ -352,7 +361,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
struct batadv_orig_node *orig_node_src)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
- struct batadv_orig_node *orig_node_dst = NULL;
+ struct batadv_orig_node *orig_node_dst;
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_frag_packet *packet;
u16 total_size;
@@ -433,8 +442,7 @@ err:
* @orig_node: final destination of the created fragments
* @neigh_node: next-hop of the created fragments
*
- * Return: the netdev tx status or -1 in case of error.
- * When -1 is returned the skb is not consumed.
+ * Return: the netdev tx status or a negative errno code on a failure
*/
int batadv_frag_send_packet(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
@@ -447,7 +455,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
unsigned int header_size = sizeof(frag_header);
unsigned int max_fragment_size, max_packet_size;
- int ret = -1;
+ int ret;
/* To avoid merge and refragmentation at next-hops we never send
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -457,13 +465,17 @@ int batadv_frag_send_packet(struct sk_buff *skb,
max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS;
/* Don't even try to fragment, if we need more than 16 fragments */
- if (skb->len > max_packet_size)
- goto out;
+ if (skb->len > max_packet_size) {
+ ret = -EAGAIN;
+ goto free_skb;
+ }
bat_priv = orig_node->bat_priv;
primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- goto out;
+ if (!primary_if) {
+ ret = -EINVAL;
+ goto put_primary_if;
+ }
/* Create one header to be copied to all fragments */
frag_header.packet_type = BATADV_UNICAST_FRAG;
@@ -488,34 +500,35 @@ int batadv_frag_send_packet(struct sk_buff *skb,
/* Eat and send fragments from the tail of skb */
while (skb->len > max_fragment_size) {
skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
- if (!skb_fragment)
- goto out;
+ if (!skb_fragment) {
+ ret = -ENOMEM;
+ goto free_skb;
+ }
batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
skb_fragment->len + ETH_HLEN);
ret = batadv_send_unicast_skb(skb_fragment, neigh_node);
if (ret != NET_XMIT_SUCCESS) {
- /* return -1 so that the caller can free the original
- * skb
- */
- ret = -1;
- goto out;
+ ret = NET_XMIT_DROP;
+ goto free_skb;
}
frag_header.no++;
/* The initial check in this function should cover this case */
if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
- ret = -1;
- goto out;
+ ret = -EINVAL;
+ goto free_skb;
}
}
/* Make room for the fragment header. */
if (batadv_skb_head_push(skb, header_size) < 0 ||
- pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0)
- goto out;
+ pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0) {
+ ret = -ENOMEM;
+ goto free_skb;
+ }
memcpy(skb->data, &frag_header, header_size);
@@ -524,10 +537,13 @@ int batadv_frag_send_packet(struct sk_buff *skb,
batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
skb->len + ETH_HLEN);
ret = batadv_send_unicast_skb(skb, neigh_node);
+ /* skb was consumed */
+ skb = NULL;
-out:
- if (primary_if)
- batadv_hardif_put(primary_if);
+put_primary_if:
+ batadv_hardif_put(primary_if);
+free_skb:
+ kfree_skb(skb);
return ret;
}
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 3202fe329e63..b95f619606af 100644
--- a/net/batman-adv/fragmentation.h
+++ b/net/batman-adv/fragmentation.h
@@ -47,7 +47,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
static inline bool
batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry)
{
- if (!hlist_empty(&frags_entry->head) &&
+ if (!hlist_empty(&frags_entry->fragment_list) &&
batadv_has_timed_out(frags_entry->timestamp, BATADV_FRAG_TIMEOUT))
return true;
return false;
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index de055d64debe..52b8bd6ec431 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -348,7 +348,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->gw.list_lock);
kref_get(&gw_node->refcount);
- hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
+ hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
spin_unlock_bh(&bat_priv->gw.list_lock);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -376,7 +376,8 @@ struct batadv_gw_node *batadv_gw_node_get(struct batadv_priv *bat_priv,
struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
rcu_read_lock();
- hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) {
+ hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.gateway_list,
+ list) {
if (gw_node_tmp->orig_node != orig_node)
continue;
@@ -475,7 +476,7 @@ void batadv_gw_node_free(struct batadv_priv *bat_priv)
spin_lock_bh(&bat_priv->gw.list_lock);
hlist_for_each_entry_safe(gw_node, node_tmp,
- &bat_priv->gw.list, list) {
+ &bat_priv->gw.gateway_list, list) {
hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_put(gw_node);
}
@@ -704,7 +705,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
{
struct batadv_neigh_node *neigh_curr = NULL;
struct batadv_neigh_node *neigh_old = NULL;
- struct batadv_orig_node *orig_dst_node = NULL;
+ struct batadv_orig_node *orig_dst_node;
struct batadv_gw_node *gw_node = NULL;
struct batadv_gw_node *curr_gw = NULL;
struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 08ce36147c4c..61a431a9772b 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -92,8 +92,8 @@ out:
*
* Return: result of rtnl_link_ops->get_link_net or @fallback_net
*/
-static const struct net *batadv_getlink_net(const struct net_device *netdev,
- const struct net *fallback_net)
+static struct net *batadv_getlink_net(const struct net_device *netdev,
+ struct net *fallback_net)
{
if (!netdev->rtnl_link_ops)
return fallback_net;
@@ -116,9 +116,9 @@ static const struct net *batadv_getlink_net(const struct net_device *netdev,
* Return: true if the devices are each others parent, otherwise false
*/
static bool batadv_mutual_parents(const struct net_device *dev1,
- const struct net *net1,
+ struct net *net1,
const struct net_device *dev2,
- const struct net *net2)
+ struct net *net2)
{
int dev1_parent_iflink = dev_get_iflink(dev1);
int dev2_parent_iflink = dev_get_iflink(dev2);
@@ -154,7 +154,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
{
struct net *net = dev_net(net_dev);
struct net_device *parent_dev;
- const struct net *parent_net;
+ struct net *parent_net;
bool ret;
/* check if this is a batman-adv mesh interface */
@@ -202,13 +202,77 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
}
/**
- * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
- * interface
+ * batadv_get_real_netdevice - check if the given netdev struct is a virtual
+ * interface on top of another 'real' interface
+ * @netdev: the device to check
+ *
+ * Callers must hold the rtnl semaphore. You may want batadv_get_real_netdev()
+ * instead of this.
+ *
+ * Return: the 'real' net device or the original net device and NULL in case
+ * of an error.
+ */
+static struct net_device *batadv_get_real_netdevice(struct net_device *netdev)
+{
+ struct batadv_hard_iface *hard_iface = NULL;
+ struct net_device *real_netdev = NULL;
+ struct net *real_net;
+ struct net *net;
+ int ifindex;
+
+ ASSERT_RTNL();
+
+ if (!netdev)
+ return NULL;
+
+ if (netdev->ifindex == dev_get_iflink(netdev)) {
+ dev_hold(netdev);
+ return netdev;
+ }
+
+ hard_iface = batadv_hardif_get_by_netdev(netdev);
+ if (!hard_iface || !hard_iface->soft_iface)
+ goto out;
+
+ net = dev_net(hard_iface->soft_iface);
+ ifindex = dev_get_iflink(netdev);
+ real_net = batadv_getlink_net(netdev, net);
+ real_netdev = dev_get_by_index(real_net, ifindex);
+
+out:
+ if (hard_iface)
+ batadv_hardif_put(hard_iface);
+ return real_netdev;
+}
+
+/**
+ * batadv_get_real_netdev - check if the given net_device struct is a virtual
+ * interface on top of another 'real' interface
* @net_device: the device to check
*
- * Return: true if the net device is a 802.11 wireless device, false otherwise.
+ * Return: the 'real' net device or the original net device and NULL in case
+ * of an error.
*/
-bool batadv_is_wifi_netdev(struct net_device *net_device)
+struct net_device *batadv_get_real_netdev(struct net_device *net_device)
+{
+ struct net_device *real_netdev;
+
+ rtnl_lock();
+ real_netdev = batadv_get_real_netdevice(net_device);
+ rtnl_unlock();
+
+ return real_netdev;
+}
+
+/**
+ * batadv_is_wext_netdev - check if the given net_device struct is a
+ * wext wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a wext wireless device, false
+ * otherwise.
+ */
+static bool batadv_is_wext_netdev(struct net_device *net_device)
{
if (!net_device)
return false;
@@ -221,6 +285,22 @@ bool batadv_is_wifi_netdev(struct net_device *net_device)
return true;
#endif
+ return false;
+}
+
+/**
+ * batadv_is_cfg80211_netdev - check if the given net_device struct is a
+ * cfg80211 wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ * otherwise.
+ */
+static bool batadv_is_cfg80211_netdev(struct net_device *net_device)
+{
+ if (!net_device)
+ return false;
+
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
@@ -228,6 +308,125 @@ bool batadv_is_wifi_netdev(struct net_device *net_device)
return false;
}
+/**
+ * batadv_wifi_flags_evaluate - calculate wifi flags for net_device
+ * @net_device: the device to check
+ *
+ * Return: batadv_hard_iface_wifi_flags flags of the device
+ */
+static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
+{
+ u32 wifi_flags = 0;
+ struct net_device *real_netdev;
+
+ if (batadv_is_wext_netdev(net_device))
+ wifi_flags |= BATADV_HARDIF_WIFI_WEXT_DIRECT;
+
+ if (batadv_is_cfg80211_netdev(net_device))
+ wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+
+ real_netdev = batadv_get_real_netdevice(net_device);
+ if (!real_netdev)
+ return wifi_flags;
+
+ if (real_netdev == net_device)
+ goto out;
+
+ if (batadv_is_wext_netdev(real_netdev))
+ wifi_flags |= BATADV_HARDIF_WIFI_WEXT_INDIRECT;
+
+ if (batadv_is_cfg80211_netdev(real_netdev))
+ wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+
+out:
+ dev_put(real_netdev);
+ return wifi_flags;
+}
+
+/**
+ * batadv_is_cfg80211_hardif - check if the given hardif is a cfg80211 wifi
+ * interface
+ * @hard_iface: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ * otherwise.
+ */
+bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
+{
+ u32 allowed_flags = 0;
+
+ allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+ allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+
+ return !!(hard_iface->wifi_flags & allowed_flags);
+}
+
+/**
+ * batadv_is_wifi_hardif - check if the given hardif is a wifi interface
+ * @hard_iface: the device to check
+ *
+ * Return: true if the net device is a 802.11 wireless device, false otherwise.
+ */
+bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface)
+{
+ if (!hard_iface)
+ return false;
+
+ return hard_iface->wifi_flags != 0;
+}
+
+/**
+ * batadv_hardif_no_broadcast - check whether (re)broadcast is necessary
+ * @if_outgoing: the outgoing interface checked and considered for (re)broadcast
+ * @orig_addr: the originator of this packet
+ * @orig_neigh: originator address of the forwarder we just got the packet from
+ * (NULL if we originated)
+ *
+ * Checks whether a packet needs to be (re)broadcasted on the given interface.
+ *
+ * Return:
+ * BATADV_HARDIF_BCAST_NORECIPIENT: No neighbor on interface
+ * BATADV_HARDIF_BCAST_DUPFWD: Just one neighbor, but it is the forwarder
+ * BATADV_HARDIF_BCAST_DUPORIG: Just one neighbor, but it is the originator
+ * BATADV_HARDIF_BCAST_OK: Several neighbors, must broadcast
+ */
+int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
+ u8 *orig_addr, u8 *orig_neigh)
+{
+ struct batadv_hardif_neigh_node *hardif_neigh;
+ struct hlist_node *first;
+ int ret = BATADV_HARDIF_BCAST_OK;
+
+ rcu_read_lock();
+
+ /* 0 neighbors -> no (re)broadcast */
+ first = rcu_dereference(hlist_first_rcu(&if_outgoing->neigh_list));
+ if (!first) {
+ ret = BATADV_HARDIF_BCAST_NORECIPIENT;
+ goto out;
+ }
+
+ /* >1 neighbors -> (re)brodcast */
+ if (rcu_dereference(hlist_next_rcu(first)))
+ goto out;
+
+ hardif_neigh = hlist_entry(first, struct batadv_hardif_neigh_node,
+ list);
+
+ /* 1 neighbor, is the originator -> no rebroadcast */
+ if (orig_addr && batadv_compare_eth(hardif_neigh->orig, orig_addr)) {
+ ret = BATADV_HARDIF_BCAST_DUPORIG;
+ /* 1 neighbor, is the one we received from -> no rebroadcast */
+ } else if (orig_neigh &&
+ batadv_compare_eth(hardif_neigh->orig, orig_neigh)) {
+ ret = BATADV_HARDIF_BCAST_DUPFWD;
+ }
+
+out:
+ rcu_read_unlock();
+ return ret;
+}
+
static struct batadv_hard_iface *
batadv_hardif_get_active(const struct net_device *soft_iface)
{
@@ -697,7 +896,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
kref_init(&hard_iface->refcount);
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
- if (batadv_is_wifi_netdev(net_dev))
+ hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+ if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
batadv_v_hardif_init(hard_iface);
@@ -806,6 +1006,11 @@ static int batadv_hard_if_event(struct notifier_block *this,
if (hard_iface == primary_if)
batadv_primary_if_update_addr(bat_priv, NULL);
break;
+ case NETDEV_CHANGEUPPER:
+ hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+ if (batadv_is_wifi_hardif(hard_iface))
+ hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+ break;
default:
break;
}
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index a76724d369bf..d6309a423629 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -40,6 +40,20 @@ enum batadv_hard_if_state {
};
/**
+ * enum batadv_hard_if_bcast - broadcast avoidance options
+ * @BATADV_HARDIF_BCAST_OK: Do broadcast on according hard interface
+ * @BATADV_HARDIF_BCAST_NORECIPIENT: Broadcast not needed, there is no recipient
+ * @BATADV_HARDIF_BCAST_DUPFWD: There is just the neighbor we got it from
+ * @BATADV_HARDIF_BCAST_DUPORIG: There is just the originator
+ */
+enum batadv_hard_if_bcast {
+ BATADV_HARDIF_BCAST_OK = 0,
+ BATADV_HARDIF_BCAST_NORECIPIENT,
+ BATADV_HARDIF_BCAST_DUPFWD,
+ BATADV_HARDIF_BCAST_DUPORIG,
+};
+
+/**
* enum batadv_hard_if_cleanup - Cleanup modi for soft_iface after slave removal
* @BATADV_IF_CLEANUP_KEEP: Don't automatically delete soft-interface
* @BATADV_IF_CLEANUP_AUTO: Delete soft-interface after last slave was removed
@@ -51,8 +65,9 @@ enum batadv_hard_if_cleanup {
extern struct notifier_block batadv_hard_if_notifier;
-bool batadv_is_wifi_netdev(struct net_device *net_device);
-bool batadv_is_wifi_iface(int ifindex);
+struct net_device *batadv_get_real_netdev(struct net_device *net_device);
+bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface);
+bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
struct batadv_hard_iface*
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
@@ -63,6 +78,8 @@ void batadv_hardif_remove_interfaces(void);
int batadv_hardif_min_mtu(struct net_device *soft_iface);
void batadv_update_min_mtu(struct net_device *soft_iface);
void batadv_hardif_release(struct kref *ref);
+int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
+ u8 *orig_addr, u8 *orig_neigh);
/**
* batadv_hardif_put - decrement the hard interface refcounter and possibly
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index cbbf87075f06..557a7044cfbc 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -61,36 +61,6 @@ void batadv_hash_set_lock_class(struct batadv_hashtable *hash,
/* free only the hashtable and the hash itself. */
void batadv_hash_destroy(struct batadv_hashtable *hash);
-/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
- * called to remove the elements inside of the hash. if you don't remove the
- * elements, memory might be leaked.
- */
-static inline void batadv_hash_delete(struct batadv_hashtable *hash,
- batadv_hashdata_free_cb free_cb,
- void *arg)
-{
- struct hlist_head *head;
- struct hlist_node *node, *node_tmp;
- spinlock_t *list_lock; /* spinlock to protect write access */
- u32 i;
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
- list_lock = &hash->list_locks[i];
-
- spin_lock_bh(list_lock);
- hlist_for_each_safe(node, node_tmp, head) {
- hlist_del_rcu(node);
-
- if (free_cb)
- free_cb(node, arg);
- }
- spin_unlock_bh(list_lock);
- }
-
- batadv_hash_destroy(hash);
-}
-
/**
* batadv_hash_add - adds data to the hashtable
* @hash: storage hash table
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 378cc1119d66..b310f381ae02 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -38,7 +38,6 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/uaccess.h>
@@ -322,8 +321,8 @@ int batadv_socket_setup(struct batadv_priv *bat_priv)
if (!bat_priv->debug_dir)
goto err;
- d = debugfs_create_file(BATADV_ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
- bat_priv->debug_dir, bat_priv, &batadv_fops);
+ d = debugfs_create_file(BATADV_ICMP_SOCKET, 0600, bat_priv->debug_dir,
+ bat_priv, &batadv_fops);
if (!d)
goto err;
diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c
index 56dc532f7a2c..c73c31769aba 100644
--- a/net/batman-adv/log.c
+++ b/net/batman-adv/log.c
@@ -31,7 +31,6 @@
#include <linux/sched.h> /* for linux/wait.h */
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/uaccess.h>
@@ -212,8 +211,7 @@ int batadv_debug_log_setup(struct batadv_priv *bat_priv)
spin_lock_init(&bat_priv->debug_log->lock);
init_waitqueue_head(&bat_priv->debug_log->queue_wait);
- d = debugfs_create_file("log", S_IFREG | S_IRUSR,
- bat_priv->debug_dir, bat_priv,
+ d = debugfs_create_file("log", 0400, bat_priv->debug_dir, bat_priv,
&batadv_log_fops);
if (!d)
goto err;
diff --git a/net/batman-adv/log.h b/net/batman-adv/log.h
index d2905a855d1b..3284a7b0325d 100644
--- a/net/batman-adv/log.h
+++ b/net/batman-adv/log.h
@@ -71,12 +71,12 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
__printf(2, 3);
/* possibly ratelimited debug output */
-#define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...) \
- do { \
- if (atomic_read(&bat_priv->log_level) & type && \
- (!ratelimited || net_ratelimit())) \
- batadv_debug_log(bat_priv, fmt, ## arg);\
- } \
+#define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...) \
+ do { \
+ if (atomic_read(&(bat_priv)->log_level) & (type) && \
+ (!(ratelimited) || net_ratelimit())) \
+ batadv_debug_log(bat_priv, fmt, ## arg); \
+ } \
while (0)
#else /* !CONFIG_BATMAN_ADV_DEBUG */
__printf(4, 5)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 2c017ab47557..d46415edd3be 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -23,6 +23,7 @@
#include <linux/crc32c.h>
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/genetlink.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/init.h>
@@ -44,6 +45,7 @@
#include <linux/workqueue.h>
#include <net/dsfield.h>
#include <net/rtnetlink.h>
+#include <uapi/linux/batman_adv.h>
#include "bat_algo.h"
#include "bat_iv_ogm.h"
@@ -160,7 +162,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
- INIT_HLIST_HEAD(&bat_priv->gw.list);
+ INIT_HLIST_HEAD(&bat_priv->gw.gateway_list);
#ifdef CONFIG_BATMAN_ADV_MCAST
INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list);
INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list);
@@ -402,6 +404,8 @@ void batadv_skb_set_priority(struct sk_buff *skb, int offset)
static int batadv_recv_unhandled_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
+ kfree_skb(skb);
+
return NET_RX_DROP;
}
@@ -416,7 +420,6 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct batadv_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *hard_iface;
u8 idx;
- int ret;
hard_iface = container_of(ptype, struct batadv_hard_iface,
batman_adv_ptype);
@@ -466,14 +469,8 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
/* reset control block to avoid left overs from previous users */
memset(skb->cb, 0, sizeof(struct batadv_skb_cb));
- /* all receive handlers return whether they received or reused
- * the supplied skb. if not, we have to free the skb.
- */
idx = batadv_ogm_packet->packet_type;
- ret = (*batadv_rx_handler[idx])(skb, hard_iface);
-
- if (ret == NET_RX_DROP)
- kfree_skb(skb);
+ (*batadv_rx_handler[idx])(skb, hard_iface);
batadv_hardif_put(hard_iface);
@@ -653,3 +650,4 @@ MODULE_DESCRIPTION(BATADV_DRIVER_DESC);
MODULE_SUPPORTED_DEVICE(BATADV_DRIVER_DEVICE);
MODULE_VERSION(BATADV_SOURCE_VERSION);
MODULE_ALIAS_RTNL_LINK("batadv");
+MODULE_ALIAS_GENL_FAMILY(BATADV_NL_NAME);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 09af21e27639..a6cc8040a21d 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -24,7 +24,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2016.4"
+#define BATADV_SOURCE_VERSION "2016.5"
#endif
/* B.A.T.M.A.N. parameters */
@@ -48,6 +48,7 @@
#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
#define BATADV_TT_WORK_PERIOD 5000 /* 5 seconds */
#define BATADV_ORIG_WORK_PERIOD 1000 /* 1 second */
+#define BATADV_MCAST_WORK_PERIOD 500 /* 0.5 seconds */
#define BATADV_DAT_ENTRY_TIMEOUT (5 * 60000) /* 5 mins in milliseconds */
/* sliding packet range of received originator messages in sequence numbers
* (should be a multiple of our word size)
@@ -185,7 +186,6 @@ enum batadv_uev_type {
#include <linux/bitops.h> /* for packet.h */
#include <linux/compiler.h>
-#include <linux/cpumask.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h> /* for packet.h */
#include <linux/if_vlan.h>
@@ -200,8 +200,8 @@ struct packet_type;
struct seq_file;
struct sk_buff;
-#define BATADV_PRINT_VID(vid) ((vid & BATADV_VLAN_HAS_TAG) ? \
- (int)(vid & VLAN_VID_MASK) : -1)
+#define BATADV_PRINT_VID(vid) (((vid) & BATADV_VLAN_HAS_TAG) ? \
+ (int)((vid) & VLAN_VID_MASK) : -1)
extern struct list_head batadv_hardif_list;
@@ -284,26 +284,6 @@ static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx,
#define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1)
-/**
- * batadv_sum_counter - Sum the cpu-local counters for index 'idx'
- * @bat_priv: the bat priv with all the soft interface information
- * @idx: index of counter to sum up
- *
- * Return: sum of all cpu-local counters
- */
-static inline u64 batadv_sum_counter(struct batadv_priv *bat_priv, size_t idx)
-{
- u64 *counters, sum = 0;
- int cpu;
-
- for_each_possible_cpu(cpu) {
- counters = per_cpu_ptr(bat_priv->bat_counters, cpu);
- sum += counters[idx];
- }
-
- return sum;
-}
-
/* Define a macro to reach the control buffer of the skb. The members of the
* control buffer are defined in struct batadv_skb_cb in types.h.
* The macro is inspired by the similar macro TCP_SKB_CB() in tcp.h.
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 13661f43386f..090a69fc342e 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -33,6 +33,7 @@
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
@@ -48,6 +49,7 @@
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#include <net/addrconf.h>
#include <net/if_inet6.h>
#include <net/ip.h>
@@ -60,6 +62,18 @@
#include "translation-table.h"
#include "tvlv.h"
+static void batadv_mcast_mla_update(struct work_struct *work);
+
+/**
+ * batadv_mcast_start_timer - schedule the multicast periodic worker
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_mcast_start_timer(struct batadv_priv *bat_priv)
+{
+ queue_delayed_work(batadv_event_workqueue, &bat_priv->mcast.work,
+ msecs_to_jiffies(BATADV_MCAST_WORK_PERIOD));
+}
+
/**
* batadv_mcast_get_bridge - get the bridge on top of the softif if it exists
* @soft_iface: netdev struct of the mesh interface
@@ -231,19 +245,15 @@ out:
/**
* batadv_mcast_mla_list_free - free a list of multicast addresses
- * @bat_priv: the bat priv with all the soft interface information
* @mcast_list: the list to free
*
* Removes and frees all items in the given mcast_list.
*/
-static void batadv_mcast_mla_list_free(struct batadv_priv *bat_priv,
- struct hlist_head *mcast_list)
+static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
- lockdep_assert_held(&bat_priv->tt.commit_lock);
-
hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
hlist_del(&mcast_entry->list);
kfree(mcast_entry);
@@ -259,6 +269,8 @@ static void batadv_mcast_mla_list_free(struct batadv_priv *bat_priv,
* translation table except the ones listed in the given mcast_list.
*
* If mcast_list is NULL then all are retracted.
+ *
+ * Do not call outside of the mcast worker! (or cancel mcast worker first)
*/
static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
@@ -266,7 +278,7 @@ static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
- lockdep_assert_held(&bat_priv->tt.commit_lock);
+ WARN_ON(delayed_work_pending(&bat_priv->mcast.work));
hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
list) {
@@ -291,6 +303,8 @@ static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
*
* Adds multicast listener announcements from the given mcast_list to the
* translation table if they have not been added yet.
+ *
+ * Do not call outside of the mcast worker! (or cancel mcast worker first)
*/
static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
@@ -298,7 +312,7 @@ static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
- lockdep_assert_held(&bat_priv->tt.commit_lock);
+ WARN_ON(delayed_work_pending(&bat_priv->mcast.work));
if (!mcast_list)
return;
@@ -532,13 +546,18 @@ update:
}
/**
- * batadv_mcast_mla_update - update the own MLAs
+ * __batadv_mcast_mla_update - update the own MLAs
* @bat_priv: the bat priv with all the soft interface information
*
* Updates the own multicast listener announcements in the translation
* table as well as the own, announced multicast tvlv container.
+ *
+ * Note that non-conflicting reads and writes to bat_priv->mcast.mla_list
+ * in batadv_mcast_mla_tt_retract() and batadv_mcast_mla_tt_add() are
+ * ensured by the non-parallel execution of the worker this function
+ * belongs to.
*/
-void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
+static void __batadv_mcast_mla_update(struct batadv_priv *bat_priv)
{
struct net_device *soft_iface = bat_priv->soft_iface;
struct hlist_head mcast_list = HLIST_HEAD_INIT;
@@ -560,7 +579,30 @@ update:
batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
out:
- batadv_mcast_mla_list_free(bat_priv, &mcast_list);
+ batadv_mcast_mla_list_free(&mcast_list);
+}
+
+/**
+ * batadv_mcast_mla_update - update the own MLAs
+ * @work: kernel work struct
+ *
+ * Updates the own multicast listener announcements in the translation
+ * table as well as the own, announced multicast tvlv container.
+ *
+ * In the end, reschedules the work timer.
+ */
+static void batadv_mcast_mla_update(struct work_struct *work)
+{
+ struct delayed_work *delayed_work;
+ struct batadv_priv_mcast *priv_mcast;
+ struct batadv_priv *bat_priv;
+
+ delayed_work = to_delayed_work(work);
+ priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
+ bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);
+
+ __batadv_mcast_mla_update(bat_priv);
+ batadv_mcast_start_timer(bat_priv);
}
/**
@@ -1132,6 +1174,9 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler,
NULL, BATADV_TVLV_MCAST, 2,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
+
+ INIT_DELAYED_WORK(&bat_priv->mcast.work, batadv_mcast_mla_update);
+ batadv_mcast_start_timer(bat_priv);
}
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
@@ -1243,12 +1288,13 @@ int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
*/
void batadv_mcast_free(struct batadv_priv *bat_priv)
{
+ cancel_delayed_work_sync(&bat_priv->mcast.work);
+
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
- spin_lock_bh(&bat_priv->tt.commit_lock);
+ /* safely calling outside of worker, as worker was canceled above */
batadv_mcast_mla_tt_retract(bat_priv, NULL);
- spin_unlock_bh(&bat_priv->tt.commit_lock);
}
/**
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h
index 1fb00ba84907..2cddaf52a21d 100644
--- a/net/batman-adv/multicast.h
+++ b/net/batman-adv/multicast.h
@@ -39,8 +39,6 @@ enum batadv_forw_mode {
#ifdef CONFIG_BATMAN_ADV_MCAST
-void batadv_mcast_mla_update(struct batadv_priv *bat_priv);
-
enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
struct batadv_orig_node **mcast_single_orig);
@@ -55,10 +53,6 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
#else
-static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
-{
-}
-
static inline enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
struct batadv_orig_node **mcast_single_orig)
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 64cb6acbe0a6..062738163bdc 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -20,11 +20,14 @@
#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
+#include <linux/cache.h>
#include <linux/errno.h>
+#include <linux/export.h>
#include <linux/fs.h>
#include <linux/genetlink.h>
#include <linux/if_ether.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/printk.h>
@@ -48,14 +51,7 @@
#include "tp_meter.h"
#include "translation-table.h"
-struct genl_family batadv_netlink_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = BATADV_NL_NAME,
- .version = 1,
- .maxattr = BATADV_ATTR_MAX,
- .netnsok = true,
-};
+struct genl_family batadv_netlink_family;
/* multicast groups */
enum batadv_netlink_multicast_groups {
@@ -534,7 +530,7 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
return msg->len;
}
-static struct genl_ops batadv_netlink_ops[] = {
+static const struct genl_ops batadv_netlink_ops[] = {
{
.cmd = BATADV_CMD_GET_MESH_INFO,
.flags = GENL_ADMIN_PERM,
@@ -610,6 +606,19 @@ static struct genl_ops batadv_netlink_ops[] = {
};
+struct genl_family batadv_netlink_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = BATADV_NL_NAME,
+ .version = 1,
+ .maxattr = BATADV_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = batadv_netlink_ops,
+ .n_ops = ARRAY_SIZE(batadv_netlink_ops),
+ .mcgrps = batadv_netlink_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
+};
+
/**
* batadv_netlink_register - register batadv genl netlink family
*/
@@ -617,9 +626,7 @@ void __init batadv_netlink_register(void)
{
int ret;
- ret = genl_register_family_with_ops_groups(&batadv_netlink_family,
- batadv_netlink_ops,
- batadv_netlink_mcgrps);
+ ret = genl_register_family(&batadv_netlink_family);
if (ret)
pr_warn("unable to register netlink family");
}
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index e3baf697a35c..ab5a3bf0765f 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -44,7 +44,6 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/workqueue.h>
@@ -261,10 +260,16 @@ static void batadv_nc_path_put(struct batadv_nc_path *nc_path)
/**
* batadv_nc_packet_free - frees nc packet
* @nc_packet: the nc packet to free
+ * @dropped: whether the packet is freed because is is dropped
*/
-static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet)
+static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet,
+ bool dropped)
{
- kfree_skb(nc_packet->skb);
+ if (dropped)
+ kfree_skb(nc_packet->skb);
+ else
+ consume_skb(nc_packet->skb);
+
batadv_nc_path_put(nc_packet->nc_path);
kfree(nc_packet);
}
@@ -577,7 +582,7 @@ static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet)
{
batadv_send_unicast_skb(nc_packet->skb, nc_packet->neigh_node);
nc_packet->skb = NULL;
- batadv_nc_packet_free(nc_packet);
+ batadv_nc_packet_free(nc_packet, false);
}
/**
@@ -611,7 +616,7 @@ static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv,
/* purge nc packet */
list_del(&nc_packet->list);
- batadv_nc_packet_free(nc_packet);
+ batadv_nc_packet_free(nc_packet, true);
res = true;
@@ -1209,11 +1214,11 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
}
/* skb_src is now coded into skb_dest, so free it */
- kfree_skb(skb_src);
+ consume_skb(skb_src);
/* avoid duplicate free of skb from nc_packet */
nc_packet->skb = NULL;
- batadv_nc_packet_free(nc_packet);
+ batadv_nc_packet_free(nc_packet, false);
/* Send the coded packet and return true */
batadv_send_unicast_skb(skb_dest, first_dest);
@@ -1400,7 +1405,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
/* batadv_nc_skb_store_for_decoding() clones the skb, so we must free
* our ref
*/
- kfree_skb(skb);
+ consume_skb(skb);
}
/**
@@ -1724,7 +1729,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
ether_addr_copy(unicast_packet->dest, orig_dest);
unicast_packet->ttvn = ttvn;
- batadv_nc_packet_free(nc_packet);
+ batadv_nc_packet_free(nc_packet, false);
return unicast_packet;
}
@@ -1814,11 +1819,11 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
/* Check if network coding is enabled */
if (!atomic_read(&bat_priv->network_coding))
- return NET_RX_DROP;
+ goto free_skb;
/* Make sure we can access (and remove) header */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
- return NET_RX_DROP;
+ goto free_skb;
coded_packet = (struct batadv_coded_packet *)skb->data;
ethhdr = eth_hdr(skb);
@@ -1826,7 +1831,7 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
/* Verify frame is destined for us */
if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) &&
!batadv_is_my_mac(bat_priv, coded_packet->second_dest))
- return NET_RX_DROP;
+ goto free_skb;
/* Update stat counter */
if (batadv_is_my_mac(bat_priv, coded_packet->second_dest))
@@ -1836,7 +1841,7 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
coded_packet);
if (!nc_packet) {
batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
- return NET_RX_DROP;
+ goto free_skb;
}
/* Make skb's linear, because decoding accesses the entire buffer */
@@ -1861,7 +1866,10 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
return batadv_recv_unicast_packet(skb, recv_if);
free_nc_packet:
- batadv_nc_packet_free(nc_packet);
+ batadv_nc_packet_free(nc_packet, true);
+free_skb:
+ kfree_skb(skb);
+
return NET_RX_DROP;
}
@@ -1961,17 +1969,16 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
if (!nc_dir)
goto out;
- file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
- &bat_priv->nc.min_tq);
+ file = debugfs_create_u8("min_tq", 0644, nc_dir, &bat_priv->nc.min_tq);
if (!file)
goto out;
- file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir,
+ file = debugfs_create_u32("max_fwd_delay", 0644, nc_dir,
&bat_priv->nc.max_fwd_delay);
if (!file)
goto out;
- file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir,
+ file = debugfs_create_u32("max_buffer_time", 0644, nc_dir,
&bat_priv->nc.max_buffer_time);
if (!file)
goto out;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 7c8d16086f0f..8f3b2969cc4e 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -364,7 +364,7 @@ struct batadv_orig_ifinfo *
batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *if_outgoing)
{
- struct batadv_orig_ifinfo *orig_ifinfo = NULL;
+ struct batadv_orig_ifinfo *orig_ifinfo;
unsigned long reset_time;
spin_lock_bh(&orig_node->neigh_list_lock);
@@ -512,15 +512,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
* batadv_hardif_neigh_create - create a hardif neighbour node
* @hard_iface: the interface this neighbour is connected to
* @neigh_addr: the interface address of the neighbour to retrieve
+ * @orig_node: originator object representing the neighbour
*
* Return: the hardif neighbour node if found or created or NULL otherwise.
*/
static struct batadv_hardif_neigh_node *
batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
- const u8 *neigh_addr)
+ const u8 *neigh_addr,
+ struct batadv_orig_node *orig_node)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
- struct batadv_hardif_neigh_node *hardif_neigh = NULL;
+ struct batadv_hardif_neigh_node *hardif_neigh;
spin_lock_bh(&hard_iface->neigh_list_lock);
@@ -536,6 +538,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
kref_get(&hard_iface->refcount);
INIT_HLIST_NODE(&hardif_neigh->list);
ether_addr_copy(hardif_neigh->addr, neigh_addr);
+ ether_addr_copy(hardif_neigh->orig, orig_node->orig);
hardif_neigh->if_incoming = hard_iface;
hardif_neigh->last_seen = jiffies;
@@ -556,21 +559,23 @@ out:
* node
* @hard_iface: the interface this neighbour is connected to
* @neigh_addr: the interface address of the neighbour to retrieve
+ * @orig_node: originator object representing the neighbour
*
* Return: the hardif neighbour node if found or created or NULL otherwise.
*/
static struct batadv_hardif_neigh_node *
batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface,
- const u8 *neigh_addr)
+ const u8 *neigh_addr,
+ struct batadv_orig_node *orig_node)
{
- struct batadv_hardif_neigh_node *hardif_neigh = NULL;
+ struct batadv_hardif_neigh_node *hardif_neigh;
/* first check without locking to avoid the overhead */
hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
if (hardif_neigh)
return hardif_neigh;
- return batadv_hardif_neigh_create(hard_iface, neigh_addr);
+ return batadv_hardif_neigh_create(hard_iface, neigh_addr, orig_node);
}
/**
@@ -630,7 +635,7 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
goto out;
hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface,
- neigh_addr);
+ neigh_addr, orig_node);
if (!hardif_neigh)
goto out;
@@ -683,7 +688,7 @@ batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
- struct batadv_neigh_node *neigh_node = NULL;
+ struct batadv_neigh_node *neigh_node;
/* first check without locking to avoid the overhead */
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
@@ -1021,7 +1026,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
batadv_orig_node_vlan_put(vlan);
for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
- INIT_HLIST_HEAD(&orig_node->fragments[i].head);
+ INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list);
spin_lock_init(&orig_node->fragments[i].lock);
orig_node->fragments[i].size = 0;
}
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 6afc0b86950e..7a36bcfa0ba0 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -21,7 +21,7 @@
#include <asm/byteorder.h>
#include <linux/types.h>
-#define batadv_tp_is_error(n) ((u8)n > 127 ? 1 : 0)
+#define batadv_tp_is_error(n) ((u8)(n) > 127 ? 1 : 0)
/**
* enum batadv_packettype - types for batman-adv encapsulated packets
@@ -252,16 +252,6 @@ struct batadv_elp_packet {
#define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet)
/**
- * enum batadv_icmp_user_cmd_type - types for batman-adv icmp cmd modes
- * @BATADV_TP_START: start a throughput meter run
- * @BATADV_TP_STOP: stop a throughput meter run
- */
-enum batadv_icmp_user_cmd_type {
- BATADV_TP_START = 0,
- BATADV_TP_STOP = 2,
-};
-
-/**
* struct batadv_icmp_header - common members among all the ICMP packets
* @packet_type: batman-adv packet type, part of the general header
* @version: batman-adv protocol version, part of the genereal header
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 7e8dc648b95a..6713bdf414cd 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -196,8 +196,8 @@ bool batadv_check_management_packet(struct sk_buff *skb,
if (!is_broadcast_ether_addr(ethhdr->h_dest))
return false;
- /* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ /* packet with invalid sender address */
+ if (!is_valid_ether_addr(ethhdr->h_source))
return false;
/* create a copy of the skb, if needed, to modify it. */
@@ -262,11 +262,11 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmph->ttl = BATADV_TTL;
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res == -1)
- goto out;
-
- ret = NET_RX_SUCCESS;
+ if (res == NET_XMIT_SUCCESS)
+ ret = NET_RX_SUCCESS;
+ /* skb was consumed */
+ skb = NULL;
break;
case BATADV_TP:
if (!pskb_may_pull(skb, sizeof(struct batadv_icmp_tp_packet)))
@@ -274,6 +274,8 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
batadv_tp_meter_recv(bat_priv, skb);
ret = NET_RX_SUCCESS;
+ /* skb was consumed */
+ skb = NULL;
goto out;
default:
/* drop unknown type */
@@ -284,6 +286,9 @@ out:
batadv_hardif_put(primary_if);
if (orig_node)
batadv_orig_node_put(orig_node);
+
+ kfree_skb(skb);
+
return ret;
}
@@ -325,14 +330,20 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet->ttl = BATADV_TTL;
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res != -1)
- ret = NET_RX_SUCCESS;
+ if (res == NET_RX_SUCCESS)
+ ret = NET_XMIT_SUCCESS;
+
+ /* skb was consumed */
+ skb = NULL;
out:
if (primary_if)
batadv_hardif_put(primary_if);
if (orig_node)
batadv_orig_node_put(orig_node);
+
+ kfree_skb(skb);
+
return ret;
}
@@ -349,21 +360,21 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
- goto out;
+ goto free_skb;
ethhdr = eth_hdr(skb);
- /* packet with unicast indication but broadcast recipient */
- if (is_broadcast_ether_addr(ethhdr->h_dest))
- goto out;
+ /* packet with unicast indication but non-unicast recipient */
+ if (!is_valid_ether_addr(ethhdr->h_dest))
+ goto free_skb;
- /* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
- goto out;
+ /* packet with broadcast/multicast sender address */
+ if (is_multicast_ether_addr(ethhdr->h_source))
+ goto free_skb;
/* not for me */
if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
- goto out;
+ goto free_skb;
icmph = (struct batadv_icmp_header *)skb->data;
@@ -372,17 +383,17 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmph->msg_type == BATADV_ECHO_REQUEST) &&
(skb->len >= sizeof(struct batadv_icmp_packet_rr))) {
if (skb_linearize(skb) < 0)
- goto out;
+ goto free_skb;
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
- goto out;
+ goto free_skb;
ethhdr = eth_hdr(skb);
icmph = (struct batadv_icmp_header *)skb->data;
icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmph;
if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN)
- goto out;
+ goto free_skb;
ether_addr_copy(icmp_packet_rr->rr[icmp_packet_rr->rr_cur],
ethhdr->h_dest);
@@ -400,11 +411,11 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
/* get routing information */
orig_node = batadv_orig_hash_find(bat_priv, icmph->dst);
if (!orig_node)
- goto out;
+ goto free_skb;
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
- goto out;
+ goto put_orig_node;
icmph = (struct batadv_icmp_header *)skb->data;
@@ -413,12 +424,18 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
/* route it */
res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
- if (res != -1)
+ if (res == NET_XMIT_SUCCESS)
ret = NET_RX_SUCCESS;
-out:
+ /* skb was consumed */
+ skb = NULL;
+
+put_orig_node:
if (orig_node)
batadv_orig_node_put(orig_node);
+free_skb:
+ kfree_skb(skb);
+
return ret;
}
@@ -445,12 +462,12 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
ethhdr = eth_hdr(skb);
- /* packet with unicast indication but broadcast recipient */
- if (is_broadcast_ether_addr(ethhdr->h_dest))
+ /* packet with unicast indication but non-unicast recipient */
+ if (!is_valid_ether_addr(ethhdr->h_dest))
return -EBADR;
- /* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ /* packet with broadcast/multicast sender address */
+ if (is_multicast_ether_addr(ethhdr->h_source))
return -EBADR;
/* not for me */
@@ -667,18 +684,18 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
if (unicast_packet->ttl < 2) {
pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
ethhdr->h_source, unicast_packet->dest);
- goto out;
+ goto free_skb;
}
/* get routing information */
orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest);
if (!orig_node)
- goto out;
+ goto free_skb;
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
- goto out;
+ goto put_orig_node;
/* decrement ttl */
unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -702,8 +719,11 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
len = skb->len;
res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
- if (res == -1)
- goto out;
+ if (res == NET_XMIT_SUCCESS)
+ ret = NET_RX_SUCCESS;
+
+ /* skb was consumed */
+ skb = NULL;
/* translate transmit result into receive result */
if (res == NET_XMIT_SUCCESS) {
@@ -713,11 +733,11 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
len + ETH_HLEN);
}
- ret = NET_RX_SUCCESS;
+put_orig_node:
+ batadv_orig_node_put(orig_node);
+free_skb:
+ kfree_skb(skb);
-out:
- if (orig_node)
- batadv_orig_node_put(orig_node);
return ret;
}
@@ -902,14 +922,18 @@ int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
if (check < 0)
- return NET_RX_DROP;
+ goto free_skb;
/* we don't know about this type, drop it. */
unicast_packet = (struct batadv_unicast_packet *)skb->data;
if (batadv_is_my_mac(bat_priv, unicast_packet->dest))
- return NET_RX_DROP;
+ goto free_skb;
return batadv_route_unicast_packet(skb, recv_if);
+
+free_skb:
+ kfree_skb(skb);
+ return NET_RX_DROP;
}
int batadv_recv_unicast_packet(struct sk_buff *skb,
@@ -923,6 +947,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
int check, hdr_size = sizeof(*unicast_packet);
enum batadv_subtype subtype;
bool is4addr;
+ int ret = NET_RX_DROP;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
@@ -942,9 +967,9 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
batadv_nc_skb_store_sniffed_unicast(bat_priv, skb);
if (check < 0)
- return NET_RX_DROP;
+ goto free_skb;
if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
- return NET_RX_DROP;
+ goto free_skb;
/* packet for me */
if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
@@ -982,7 +1007,14 @@ rx_success:
return NET_RX_SUCCESS;
}
- return batadv_route_unicast_packet(skb, recv_if);
+ ret = batadv_route_unicast_packet(skb, recv_if);
+ /* skb was consumed */
+ skb = NULL;
+
+free_skb:
+ kfree_skb(skb);
+
+ return ret;
}
/**
@@ -1004,15 +1036,15 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
int ret = NET_RX_DROP;
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
- return NET_RX_DROP;
+ goto free_skb;
/* the header is likely to be modified while forwarding */
if (skb_cow(skb, hdr_size) < 0)
- return NET_RX_DROP;
+ goto free_skb;
/* packet needs to be linearized to access the tvlv content */
if (skb_linearize(skb) < 0)
- return NET_RX_DROP;
+ goto free_skb;
unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data;
@@ -1020,17 +1052,21 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len);
if (tvlv_buff_len > skb->len - hdr_size)
- return NET_RX_DROP;
+ goto free_skb;
ret = batadv_tvlv_containers_process(bat_priv, false, NULL,
unicast_tvlv_packet->src,
unicast_tvlv_packet->dst,
tvlv_buff, tvlv_buff_len);
- if (ret != NET_RX_SUCCESS)
+ if (ret != NET_RX_SUCCESS) {
ret = batadv_route_unicast_packet(skb, recv_if);
- else
- consume_skb(skb);
+ /* skb was consumed */
+ skb = NULL;
+ }
+
+free_skb:
+ kfree_skb(skb);
return ret;
}
@@ -1056,20 +1092,22 @@ int batadv_recv_frag_packet(struct sk_buff *skb,
if (batadv_check_unicast_packet(bat_priv, skb,
sizeof(*frag_packet)) < 0)
- goto out;
+ goto free_skb;
frag_packet = (struct batadv_frag_packet *)skb->data;
orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig);
if (!orig_node_src)
- goto out;
+ goto free_skb;
skb->priority = frag_packet->priority + 256;
/* Route the fragment if it is not for us and too big to be merged. */
if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
+ /* skb was consumed */
+ skb = NULL;
ret = NET_RX_SUCCESS;
- goto out;
+ goto put_orig_node;
}
batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
@@ -1077,20 +1115,24 @@ int batadv_recv_frag_packet(struct sk_buff *skb,
/* Add fragment to buffer and merge if possible. */
if (!batadv_frag_skb_buffer(&skb, orig_node_src))
- goto out;
+ goto put_orig_node;
/* Deliver merged packet to the appropriate handler, if it was
* merged
*/
- if (skb)
+ if (skb) {
batadv_batman_skb_recv(skb, recv_if->net_dev,
&recv_if->batman_adv_ptype, NULL);
+ /* skb was consumed */
+ skb = NULL;
+ }
ret = NET_RX_SUCCESS;
-out:
- if (orig_node_src)
- batadv_orig_node_put(orig_node_src);
+put_orig_node:
+ batadv_orig_node_put(orig_node_src);
+free_skb:
+ kfree_skb(skb);
return ret;
}
@@ -1109,35 +1151,35 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
- goto out;
+ goto free_skb;
ethhdr = eth_hdr(skb);
/* packet with broadcast indication but unicast recipient */
if (!is_broadcast_ether_addr(ethhdr->h_dest))
- goto out;
+ goto free_skb;
- /* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
- goto out;
+ /* packet with broadcast/multicast sender address */
+ if (is_multicast_ether_addr(ethhdr->h_source))
+ goto free_skb;
/* ignore broadcasts sent by myself */
if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
- goto out;
+ goto free_skb;
bcast_packet = (struct batadv_bcast_packet *)skb->data;
/* ignore broadcasts originated by myself */
if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
- goto out;
+ goto free_skb;
if (bcast_packet->ttl < 2)
- goto out;
+ goto free_skb;
orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
if (!orig_node)
- goto out;
+ goto free_skb;
spin_lock_bh(&orig_node->bcast_seqno_lock);
@@ -1165,18 +1207,18 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
/* check whether this has been sent by another originator before */
if (batadv_bla_check_bcast_duplist(bat_priv, skb))
- goto out;
+ goto free_skb;
batadv_skb_set_priority(skb, sizeof(struct batadv_bcast_packet));
/* rebroadcast packet */
- batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
+ batadv_add_bcast_packet_to_list(bat_priv, skb, 1, false);
/* don't hand the broadcast up if it is from an originator
* from the same backbone.
*/
if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
- goto out;
+ goto free_skb;
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
goto rx_success;
@@ -1192,6 +1234,8 @@ rx_success:
spin_unlock:
spin_unlock_bh(&orig_node->bcast_seqno_lock);
+free_skb:
+ kfree_skb(skb);
out:
if (orig_node)
batadv_orig_node_put(orig_node);
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 8d4e1f578574..49021b7124f3 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -19,6 +19,7 @@
#include "main.h"
#include <linux/atomic.h>
+#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
@@ -64,8 +65,11 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
* If neigh_node is NULL, then the packet is broadcasted using hard_iface,
* otherwise it is sent as unicast to the given neighbor.
*
- * Return: NET_TX_DROP in case of error or the result of dev_queue_xmit(skb)
- * otherwise
+ * Regardless of the return value, the skb is consumed.
+ *
+ * Return: A negative errno code is returned on a failure. A success does not
+ * guarantee the frame will be transmitted as it may be dropped due
+ * to congestion or traffic shaping.
*/
int batadv_send_skb_packet(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface,
@@ -73,7 +77,6 @@ int batadv_send_skb_packet(struct sk_buff *skb,
{
struct batadv_priv *bat_priv;
struct ethhdr *ethhdr;
- int ret;
bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -111,15 +114,8 @@ int batadv_send_skb_packet(struct sk_buff *skb,
/* dev_queue_xmit() returns a negative result on error. However on
* congestion and traffic shaping, it drops and returns NET_XMIT_DROP
* (which is > 0). This will not be treated as an error.
- *
- * a negative value cannot be returned because it could be interepreted
- * as not consumed skb by callers of batadv_send_skb_to_orig.
*/
- ret = dev_queue_xmit(skb);
- if (ret < 0)
- ret = NET_XMIT_DROP;
-
- return ret;
+ return dev_queue_xmit(skb);
send_skb_err:
kfree_skb(skb);
return NET_XMIT_DROP;
@@ -165,11 +161,9 @@ int batadv_send_unicast_skb(struct sk_buff *skb,
* host, NULL can be passed as recv_if and no interface alternating is
* attempted.
*
- * Return: -1 on failure (and the skb is not consumed), -EINPROGRESS if the
- * skb is buffered for later transmit or the NET_XMIT status returned by the
+ * Return: negative errno code on a failure, -EINPROGRESS if the skb is
+ * buffered for later transmit or the NET_XMIT status returned by the
* lower routine if the packet has been passed down.
- *
- * If the returning value is not -1 the skb has been consumed.
*/
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
@@ -177,12 +171,14 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
{
struct batadv_priv *bat_priv = orig_node->bat_priv;
struct batadv_neigh_node *neigh_node;
- int ret = -1;
+ int ret;
/* batadv_find_router() increases neigh_nodes refcount if found. */
neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
- if (!neigh_node)
- goto out;
+ if (!neigh_node) {
+ ret = -EINVAL;
+ goto free_skb;
+ }
/* Check if the skb is too large to send in one piece and fragment
* it if needed.
@@ -191,8 +187,10 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
skb->len > neigh_node->if_incoming->net_dev->mtu) {
/* Fragment and send packet. */
ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
+ /* skb was consumed */
+ skb = NULL;
- goto out;
+ goto put_neigh_node;
}
/* try to network code the packet, if it is received on an interface
@@ -204,9 +202,13 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
else
ret = batadv_send_unicast_skb(skb, neigh_node);
-out:
- if (neigh_node)
- batadv_neigh_node_put(neigh_node);
+ /* skb was consumed */
+ skb = NULL;
+
+put_neigh_node:
+ batadv_neigh_node_put(neigh_node);
+free_skb:
+ kfree_skb(skb);
return ret;
}
@@ -327,7 +329,7 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
{
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr;
- int res, ret = NET_XMIT_DROP;
+ int ret = NET_XMIT_DROP;
if (!orig_node)
goto out;
@@ -364,13 +366,12 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
unicast_packet->ttvn = unicast_packet->ttvn - 1;
- res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res != -1)
- ret = NET_XMIT_SUCCESS;
+ ret = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ /* skb was consumed */
+ skb = NULL;
out:
- if (ret == NET_XMIT_DROP)
- kfree_skb(skb);
+ kfree_skb(skb);
return ret;
}
@@ -451,13 +452,19 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
/**
* batadv_forw_packet_free - free a forwarding packet
* @forw_packet: The packet to free
+ * @dropped: whether the packet is freed because is is dropped
*
* This frees a forwarding packet and releases any resources it might
* have claimed.
*/
-void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
+void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet,
+ bool dropped)
{
- kfree_skb(forw_packet->skb);
+ if (dropped)
+ kfree_skb(forw_packet->skb);
+ else
+ consume_skb(forw_packet->skb);
+
if (forw_packet->if_incoming)
batadv_hardif_put(forw_packet->if_incoming);
if (forw_packet->if_outgoing)
@@ -514,6 +521,8 @@ batadv_forw_packet_alloc(struct batadv_hard_iface *if_incoming,
if (if_outgoing)
kref_get(&if_outgoing->refcount);
+ INIT_HLIST_NODE(&forw_packet->list);
+ INIT_HLIST_NODE(&forw_packet->cleanup_list);
forw_packet->skb = NULL;
forw_packet->queue_left = queue_left;
forw_packet->if_incoming = if_incoming;
@@ -529,19 +538,191 @@ err:
return NULL;
}
+/**
+ * batadv_forw_packet_was_stolen - check whether someone stole this packet
+ * @forw_packet: the forwarding packet to check
+ *
+ * This function checks whether the given forwarding packet was claimed by
+ * someone else for free().
+ *
+ * Return: True if someone stole it, false otherwise.
+ */
+static bool
+batadv_forw_packet_was_stolen(struct batadv_forw_packet *forw_packet)
+{
+ return !hlist_unhashed(&forw_packet->cleanup_list);
+}
+
+/**
+ * batadv_forw_packet_steal - claim a forw_packet for free()
+ * @forw_packet: the forwarding packet to steal
+ * @lock: a key to the store to steal from (e.g. forw_{bat,bcast}_list_lock)
+ *
+ * This function tries to steal a specific forw_packet from global
+ * visibility for the purpose of getting it for free(). That means
+ * the caller is *not* allowed to requeue it afterwards.
+ *
+ * Return: True if stealing was successful. False if someone else stole it
+ * before us.
+ */
+bool batadv_forw_packet_steal(struct batadv_forw_packet *forw_packet,
+ spinlock_t *lock)
+{
+ /* did purging routine steal it earlier? */
+ spin_lock_bh(lock);
+ if (batadv_forw_packet_was_stolen(forw_packet)) {
+ spin_unlock_bh(lock);
+ return false;
+ }
+
+ hlist_del_init(&forw_packet->list);
+
+ /* Just to spot misuse of this function */
+ hlist_add_fake(&forw_packet->cleanup_list);
+
+ spin_unlock_bh(lock);
+ return true;
+}
+
+/**
+ * batadv_forw_packet_list_steal - claim a list of forward packets for free()
+ * @forw_list: the to be stolen forward packets
+ * @cleanup_list: a backup pointer, to be able to dispose the packet later
+ * @hard_iface: the interface to steal forward packets from
+ *
+ * This function claims responsibility to free any forw_packet queued on the
+ * given hard_iface. If hard_iface is NULL forwarding packets on all hard
+ * interfaces will be claimed.
+ *
+ * The packets are being moved from the forw_list to the cleanup_list and
+ * by that allows already running threads to notice the claiming.
+ */
static void
-_batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
- struct batadv_forw_packet *forw_packet,
- unsigned long send_time)
+batadv_forw_packet_list_steal(struct hlist_head *forw_list,
+ struct hlist_head *cleanup_list,
+ const struct batadv_hard_iface *hard_iface)
{
- /* add new packet to packet list */
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list);
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, safe_tmp_node,
+ forw_list, list) {
+ /* if purge_outstanding_packets() was called with an argument
+ * we delete only packets belonging to the given interface
+ */
+ if (hard_iface &&
+ (forw_packet->if_incoming != hard_iface) &&
+ (forw_packet->if_outgoing != hard_iface))
+ continue;
+
+ hlist_del(&forw_packet->list);
+ hlist_add_head(&forw_packet->cleanup_list, cleanup_list);
+ }
+}
+
+/**
+ * batadv_forw_packet_list_free - free a list of forward packets
+ * @head: a list of to be freed forw_packets
+ *
+ * This function cancels the scheduling of any packet in the provided list,
+ * waits for any possibly running packet forwarding thread to finish and
+ * finally, safely frees this forward packet.
+ *
+ * This function might sleep.
+ */
+static void batadv_forw_packet_list_free(struct hlist_head *head)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, safe_tmp_node, head,
+ cleanup_list) {
+ cancel_delayed_work_sync(&forw_packet->delayed_work);
+
+ hlist_del(&forw_packet->cleanup_list);
+ batadv_forw_packet_free(forw_packet, true);
+ }
+}
+
+/**
+ * batadv_forw_packet_queue - try to queue a forwarding packet
+ * @forw_packet: the forwarding packet to queue
+ * @lock: a key to the store (e.g. forw_{bat,bcast}_list_lock)
+ * @head: the shelve to queue it on (e.g. forw_{bat,bcast}_list)
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ *
+ * This function tries to (re)queue a forwarding packet. Requeuing
+ * is prevented if the according interface is shutting down
+ * (e.g. if batadv_forw_packet_list_steal() was called for this
+ * packet earlier).
+ *
+ * Calling batadv_forw_packet_queue() after a call to
+ * batadv_forw_packet_steal() is forbidden!
+ *
+ * Caller needs to ensure that forw_packet->delayed_work was initialized.
+ */
+static void batadv_forw_packet_queue(struct batadv_forw_packet *forw_packet,
+ spinlock_t *lock, struct hlist_head *head,
+ unsigned long send_time)
+{
+ spin_lock_bh(lock);
+
+ /* did purging routine steal it from us? */
+ if (batadv_forw_packet_was_stolen(forw_packet)) {
+ /* If you got it for free() without trouble, then
+ * don't get back into the queue after stealing...
+ */
+ WARN_ONCE(hlist_fake(&forw_packet->cleanup_list),
+ "Requeuing after batadv_forw_packet_steal() not allowed!\n");
- /* start timer for this packet */
- queue_delayed_work(batadv_event_workqueue, &forw_packet->delayed_work,
- send_time);
+ spin_unlock_bh(lock);
+ return;
+ }
+
+ hlist_del_init(&forw_packet->list);
+ hlist_add_head(&forw_packet->list, head);
+
+ queue_delayed_work(batadv_event_workqueue,
+ &forw_packet->delayed_work,
+ send_time - jiffies);
+ spin_unlock_bh(lock);
+}
+
+/**
+ * batadv_forw_packet_bcast_queue - try to queue a broadcast packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @forw_packet: the forwarding packet to queue
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ *
+ * This function tries to (re)queue a broadcast packet.
+ *
+ * Caller needs to ensure that forw_packet->delayed_work was initialized.
+ */
+static void
+batadv_forw_packet_bcast_queue(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet,
+ unsigned long send_time)
+{
+ batadv_forw_packet_queue(forw_packet, &bat_priv->forw_bcast_list_lock,
+ &bat_priv->forw_bcast_list, send_time);
+}
+
+/**
+ * batadv_forw_packet_ogmv1_queue - try to queue an OGMv1 packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @forw_packet: the forwarding packet to queue
+ * @send_time: timestamp (jiffies) when the packet is to be sent
+ *
+ * This function tries to (re)queue an OGMv1 packet.
+ *
+ * Caller needs to ensure that forw_packet->delayed_work was initialized.
+ */
+void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet,
+ unsigned long send_time)
+{
+ batadv_forw_packet_queue(forw_packet, &bat_priv->forw_bat_list_lock,
+ &bat_priv->forw_bat_list, send_time);
}
/**
@@ -549,6 +730,7 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
+ * @own_packet: true if it is a self-generated broadcast packet
*
* add a broadcast packet to the queue and setup timers. broadcast packets
* are sent multiple times to increase probability for being received.
@@ -560,9 +742,10 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
*/
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
- unsigned long delay)
+ unsigned long delay,
+ bool own_packet)
{
- struct batadv_hard_iface *primary_if = NULL;
+ struct batadv_hard_iface *primary_if;
struct batadv_forw_packet *forw_packet;
struct batadv_bcast_packet *bcast_packet;
struct sk_buff *newskb;
@@ -586,18 +769,17 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
bcast_packet = (struct batadv_bcast_packet *)newskb->data;
bcast_packet->ttl--;
- skb_reset_mac_header(newskb);
-
forw_packet->skb = newskb;
+ forw_packet->own = own_packet;
INIT_DELAYED_WORK(&forw_packet->delayed_work,
batadv_send_outstanding_bcast_packet);
- _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay);
+ batadv_forw_packet_bcast_queue(bat_priv, forw_packet, jiffies + delay);
return NETDEV_TX_OK;
err_packet_free:
- batadv_forw_packet_free(forw_packet);
+ batadv_forw_packet_free(forw_packet, true);
err:
return NETDEV_TX_BUSY;
}
@@ -605,11 +787,18 @@ err:
static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
{
struct batadv_hard_iface *hard_iface;
+ struct batadv_hardif_neigh_node *neigh_node;
struct delayed_work *delayed_work;
struct batadv_forw_packet *forw_packet;
+ struct batadv_bcast_packet *bcast_packet;
struct sk_buff *skb1;
struct net_device *soft_iface;
struct batadv_priv *bat_priv;
+ unsigned long send_time = jiffies + msecs_to_jiffies(5);
+ bool dropped = false;
+ u8 *neigh_addr;
+ u8 *orig_neigh;
+ int ret = 0;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
@@ -617,15 +806,17 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
soft_iface = forw_packet->if_incoming->soft_iface;
bat_priv = netdev_priv(soft_iface);
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_del(&forw_packet->list);
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
-
- if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
+ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
+ dropped = true;
goto out;
+ }
- if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
+ if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) {
+ dropped = true;
goto out;
+ }
+
+ bcast_packet = (struct batadv_bcast_packet *)forw_packet->skb->data;
/* rebroadcast packet */
rcu_read_lock();
@@ -636,6 +827,49 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (forw_packet->num_packets >= hard_iface->num_bcasts)
continue;
+ if (forw_packet->own) {
+ neigh_node = NULL;
+ } else {
+ neigh_addr = eth_hdr(forw_packet->skb)->h_source;
+ neigh_node = batadv_hardif_neigh_get(hard_iface,
+ neigh_addr);
+ }
+
+ orig_neigh = neigh_node ? neigh_node->orig : NULL;
+
+ ret = batadv_hardif_no_broadcast(hard_iface, bcast_packet->orig,
+ orig_neigh);
+
+ if (ret) {
+ char *type;
+
+ switch (ret) {
+ case BATADV_HARDIF_BCAST_NORECIPIENT:
+ type = "no neighbor";
+ break;
+ case BATADV_HARDIF_BCAST_DUPFWD:
+ type = "single neighbor is source";
+ break;
+ case BATADV_HARDIF_BCAST_DUPORIG:
+ type = "single neighbor is originator";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "BCAST packet from orig %pM on %s surpressed: %s\n",
+ bcast_packet->orig,
+ hard_iface->net_dev->name, type);
+
+ if (neigh_node)
+ batadv_hardif_neigh_put(neigh_node);
+
+ continue;
+ }
+
+ if (neigh_node)
+ batadv_hardif_neigh_put(neigh_node);
+
if (!kref_get_unless_zero(&hard_iface->refcount))
continue;
@@ -652,22 +886,34 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
/* if we still have some more bcasts to send */
if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) {
- _batadv_add_bcast_packet_to_list(bat_priv, forw_packet,
- msecs_to_jiffies(5));
+ batadv_forw_packet_bcast_queue(bat_priv, forw_packet,
+ send_time);
return;
}
out:
- batadv_forw_packet_free(forw_packet);
+ /* do we get something for free()? */
+ if (batadv_forw_packet_steal(forw_packet,
+ &bat_priv->forw_bcast_list_lock))
+ batadv_forw_packet_free(forw_packet, dropped);
}
+/**
+ * batadv_purge_outstanding_packets - stop/purge scheduled bcast/OGMv1 packets
+ * @bat_priv: the bat priv with all the soft interface information
+ * @hard_iface: the hard interface to cancel and purge bcast/ogm packets on
+ *
+ * This method cancels and purges any broadcast and OGMv1 packet on the given
+ * hard_iface. If hard_iface is NULL, broadcast and OGMv1 packets on all hard
+ * interfaces will be canceled and purged.
+ *
+ * This function might sleep.
+ */
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface)
{
- struct batadv_forw_packet *forw_packet;
- struct hlist_node *safe_tmp_node;
- bool pending;
+ struct hlist_head head = HLIST_HEAD_INIT;
if (hard_iface)
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -677,57 +923,18 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"purge_outstanding_packets()\n");
- /* free bcast list */
+ /* claim bcast list for free() */
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_for_each_entry_safe(forw_packet, safe_tmp_node,
- &bat_priv->forw_bcast_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface) &&
- (forw_packet->if_outgoing != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
-
- /* batadv_send_outstanding_bcast_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_forw_packet_list_steal(&bat_priv->forw_bcast_list, &head,
+ hard_iface);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
- /* free batman packet list */
+ /* claim batman packet list for free() */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_for_each_entry_safe(forw_packet, safe_tmp_node,
- &bat_priv->forw_bat_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface) &&
- (forw_packet->if_outgoing != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
-
- /* send_outstanding_bat_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_forw_packet_list_steal(&bat_priv->forw_bat_list, &head,
+ hard_iface);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+
+ /* then cancel or wait for packet workers to finish and free */
+ batadv_forw_packet_list_free(&head);
}
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 999f78683d9e..a94e1e8639ca 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -21,18 +21,24 @@
#include "main.h"
#include <linux/compiler.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#include "packet.h"
struct sk_buff;
-void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet);
+void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet,
+ bool dropped);
struct batadv_forw_packet *
batadv_forw_packet_alloc(struct batadv_hard_iface *if_incoming,
struct batadv_hard_iface *if_outgoing,
atomic_t *queue_left,
struct batadv_priv *bat_priv);
+bool batadv_forw_packet_steal(struct batadv_forw_packet *packet, spinlock_t *l);
+void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet,
+ unsigned long send_time);
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
@@ -46,7 +52,8 @@ int batadv_send_unicast_skb(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node);
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
- unsigned long delay);
+ unsigned long delay,
+ bool own_packet);
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 49e16b6e0ba3..7b3494ae6ad9 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -22,6 +22,7 @@
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
+#include <linux/cpumask.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -116,6 +117,26 @@ static int batadv_interface_release(struct net_device *dev)
return 0;
}
+/**
+ * batadv_sum_counter - Sum the cpu-local counters for index 'idx'
+ * @bat_priv: the bat priv with all the soft interface information
+ * @idx: index of counter to sum up
+ *
+ * Return: sum of all cpu-local counters
+ */
+static u64 batadv_sum_counter(struct batadv_priv *bat_priv, size_t idx)
+{
+ u64 *counters, sum = 0;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ counters = per_cpu_ptr(bat_priv->bat_counters, cpu);
+ sum += counters[idx];
+ }
+
+ return sum;
+}
+
static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
{
struct batadv_priv *bat_priv = netdev_priv(dev);
@@ -336,12 +357,12 @@ send:
seqno = atomic_inc_return(&bat_priv->bcast_seqno);
bcast_packet->seqno = htonl(seqno);
- batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
+ batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay, true);
/* a copy is stored in the bcast list, therefore removing
* the original skb.
*/
- kfree_skb(skb);
+ consume_skb(skb);
/* unicast packet */
} else {
@@ -365,7 +386,7 @@ send:
ret = batadv_send_skb_via_tt(bat_priv, skb, dst_hint,
vid);
}
- if (ret == NET_XMIT_DROP)
+ if (ret != NET_XMIT_SUCCESS)
goto dropped_freed;
}
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 02d96f224c60..17c844196eb2 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -33,7 +33,6 @@
#include <linux/rcupdate.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
-#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/stringify.h>
@@ -666,41 +665,36 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
return count;
}
-BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
-BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL);
+BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL);
#ifdef CONFIG_BATMAN_ADV_BLA
-BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR,
- batadv_bla_status_update);
+BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, 0644, batadv_bla_status_update);
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
-BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
- batadv_dat_status_update);
+BATADV_ATTR_SIF_BOOL(distributed_arp_table, 0644, batadv_dat_status_update);
#endif
-BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
-static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
-static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
- batadv_store_gw_mode);
-BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
- 2 * BATADV_JITTER, INT_MAX, NULL);
-BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
- BATADV_TQ_MAX_VALUE, NULL);
-static BATADV_ATTR(gw_sel_class, S_IRUGO | S_IWUSR, batadv_show_gw_sel_class,
+BATADV_ATTR_SIF_BOOL(fragmentation, 0644, batadv_update_min_mtu);
+static BATADV_ATTR(routing_algo, 0444, batadv_show_bat_algo, NULL);
+static BATADV_ATTR(gw_mode, 0644, batadv_show_gw_mode, batadv_store_gw_mode);
+BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, 0644, 2 * BATADV_JITTER,
+ INT_MAX, NULL);
+BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, 0644, 0, BATADV_TQ_MAX_VALUE,
+ NULL);
+static BATADV_ATTR(gw_sel_class, 0644, batadv_show_gw_sel_class,
batadv_store_gw_sel_class);
-static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
+static BATADV_ATTR(gw_bandwidth, 0644, batadv_show_gw_bwidth,
batadv_store_gw_bwidth);
#ifdef CONFIG_BATMAN_ADV_MCAST
-BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_SIF_BOOL(multicast_mode, 0644, NULL);
#endif
#ifdef CONFIG_BATMAN_ADV_DEBUG
-BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
- BATADV_DBG_ALL, NULL);
+BATADV_ATTR_SIF_UINT(log_level, log_level, 0644, 0, BATADV_DBG_ALL, NULL);
#endif
#ifdef CONFIG_BATMAN_ADV_NC
-BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
- batadv_nc_status_update);
+BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update);
#endif
-static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
- batadv_show_isolation_mark, batadv_store_isolation_mark);
+static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark,
+ batadv_store_isolation_mark);
static struct batadv_attribute *batadv_mesh_attrs[] = {
&batadv_attr_aggregated_ogms,
@@ -731,7 +725,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
NULL,
};
-BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_VLAN_BOOL(ap_isolation, 0644, NULL);
/* array of vlan specific sysfs attributes */
static struct batadv_attribute *batadv_vlan_attrs[] = {
@@ -1116,14 +1110,13 @@ static ssize_t batadv_show_throughput_override(struct kobject *kobj,
#endif
-static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
+static BATADV_ATTR(mesh_iface, 0644, batadv_show_mesh_iface,
batadv_store_mesh_iface);
-static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+static BATADV_ATTR(iface_status, 0444, batadv_show_iface_status, NULL);
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
-BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
+BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, 0644,
2 * BATADV_JITTER, INT_MAX, NULL);
-static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
- batadv_show_throughput_override,
+static BATADV_ATTR(throughput_override, 0644, batadv_show_throughput_override,
batadv_store_throughput_override);
#endif
diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
index 8af1611b8ab2..981e8c5b07e9 100644
--- a/net/batman-adv/tp_meter.c
+++ b/net/batman-adv/tp_meter.c
@@ -615,9 +615,6 @@ static int batadv_tp_send_msg(struct batadv_tp_vars *tp_vars, const u8 *src,
batadv_tp_fill_prerandom(tp_vars, data, data_len);
r = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (r == -1)
- kfree_skb(skb);
-
if (r == NET_XMIT_SUCCESS)
return 0;
@@ -1207,9 +1204,6 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst,
/* send the ack */
r = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (r == -1)
- kfree_skb(skb);
-
if (unlikely(r < 0) || (r == NET_XMIT_DROP)) {
ret = BATADV_TP_REASON_DST_UNREACHABLE;
goto out;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 0dc85eb1cb7a..30ecbfb40adf 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -56,7 +56,6 @@
#include "hard-interface.h"
#include "hash.h"
#include "log.h"
-#include "multicast.h"
#include "netlink.h"
#include "originator.h"
#include "packet.h"
@@ -647,6 +646,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
struct net *net = dev_net(soft_iface);
struct batadv_softif_vlan *vlan;
struct net_device *in_dev = NULL;
+ struct batadv_hard_iface *in_hardif = NULL;
struct hlist_head *head;
struct batadv_tt_orig_list_entry *orig_entry;
int hash_added, table_size, packet_size_max;
@@ -658,6 +658,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
if (ifindex != BATADV_NULL_IFINDEX)
in_dev = dev_get_by_index(net, ifindex);
+ if (in_dev)
+ in_hardif = batadv_hardif_get_by_netdev(in_dev);
+
tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
if (!is_multicast_ether_addr(addr))
@@ -731,7 +734,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
*/
tt_local->common.flags = BATADV_TT_CLIENT_NEW;
tt_local->common.vid = vid;
- if (batadv_is_wifi_netdev(in_dev))
+ if (batadv_is_wifi_hardif(in_hardif))
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
kref_init(&tt_local->common.refcount);
tt_local->last_seen = jiffies;
@@ -791,7 +794,7 @@ check_roaming:
*/
remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
- if (batadv_is_wifi_netdev(in_dev))
+ if (batadv_is_wifi_hardif(in_hardif))
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
else
tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
@@ -815,6 +818,8 @@ check_roaming:
ret = true;
out:
+ if (in_hardif)
+ batadv_hardif_put(in_hardif);
if (in_dev)
dev_put(in_dev);
if (tt_local)
@@ -3795,9 +3800,6 @@ static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
{
lockdep_assert_held(&bat_priv->tt.commit_lock);
- /* Update multicast addresses in local translation table */
- batadv_mcast_mla_update(bat_priv);
-
if (atomic_read(&bat_priv->tt.local_changes) < 1) {
if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
batadv_tt_tvlv_container_update(bat_priv);
@@ -3835,8 +3837,8 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
unsigned short vid)
{
- struct batadv_tt_local_entry *tt_local_entry = NULL;
- struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_local_entry *tt_local_entry;
+ struct batadv_tt_global_entry *tt_global_entry;
struct batadv_softif_vlan *vlan;
bool ret = false;
@@ -3845,27 +3847,24 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
return false;
if (!atomic_read(&vlan->ap_isolation))
- goto out;
+ goto vlan_put;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
if (!tt_local_entry)
- goto out;
+ goto vlan_put;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
if (!tt_global_entry)
- goto out;
+ goto local_entry_put;
- if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
- goto out;
-
- ret = true;
+ if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
+ ret = true;
-out:
+ batadv_tt_global_entry_put(tt_global_entry);
+local_entry_put:
+ batadv_tt_local_entry_put(tt_local_entry);
+vlan_put:
batadv_softif_vlan_put(vlan);
- if (tt_global_entry)
- batadv_tt_global_entry_put(tt_global_entry);
- if (tt_local_entry)
- batadv_tt_local_entry_put(tt_local_entry);
return ret;
}
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index 77654f055f24..a783420356ae 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -600,7 +600,6 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
unsigned char *tvlv_buff;
unsigned int tvlv_len;
ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
- int res;
orig_node = batadv_orig_hash_find(bat_priv, dst);
if (!orig_node)
@@ -633,9 +632,7 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
tvlv_buff += sizeof(*tvlv_hdr);
memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
- res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res == -1)
- kfree_skb(skb);
+ batadv_send_skb_to_orig(skb, orig_node, NULL);
out:
batadv_orig_node_put(orig_node);
}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index b3dd1a381aad..e913aee28c98 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -119,12 +119,28 @@ struct batadv_hard_iface_bat_v {
};
/**
+ * enum batadv_hard_iface_wifi_flags - Flags describing the wifi configuration
+ * of a batadv_hard_iface
+ * @BATADV_HARDIF_WIFI_WEXT_DIRECT: it is a wext wifi device
+ * @BATADV_HARDIF_WIFI_CFG80211_DIRECT: it is a cfg80211 wifi device
+ * @BATADV_HARDIF_WIFI_WEXT_INDIRECT: link device is a wext wifi device
+ * @BATADV_HARDIF_WIFI_CFG80211_INDIRECT: link device is a cfg80211 wifi device
+ */
+enum batadv_hard_iface_wifi_flags {
+ BATADV_HARDIF_WIFI_WEXT_DIRECT = BIT(0),
+ BATADV_HARDIF_WIFI_CFG80211_DIRECT = BIT(1),
+ BATADV_HARDIF_WIFI_WEXT_INDIRECT = BIT(2),
+ BATADV_HARDIF_WIFI_CFG80211_INDIRECT = BIT(3),
+};
+
+/**
* struct batadv_hard_iface - network device known to batman-adv
* @list: list node for batadv_hardif_list
* @if_num: identificator of the interface
* @if_status: status of the interface for batman-adv
- * @net_dev: pointer to the net_device
* @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
+ * @wifi_flags: flags whether this is (directly or indirectly) a wifi interface
+ * @net_dev: pointer to the net_device
* @hardif_obj: kobject of the per interface sysfs "mesh" directory
* @refcount: number of contexts the object is used
* @batman_adv_ptype: packet type describing packets that should be processed by
@@ -141,8 +157,9 @@ struct batadv_hard_iface {
struct list_head list;
s16 if_num;
char if_status;
- struct net_device *net_dev;
u8 num_bcasts;
+ u32 wifi_flags;
+ struct net_device *net_dev;
struct kobject *hardif_obj;
struct kref refcount;
struct packet_type batman_adv_ptype;
@@ -184,7 +201,7 @@ struct batadv_orig_ifinfo {
/**
* struct batadv_frag_table_entry - head in the fragment buffer table
- * @head: head of list with fragments
+ * @fragment_list: head of list with fragments
* @lock: lock to protect the list of fragments
* @timestamp: time (jiffie) of last received fragment
* @seqno: sequence number of the fragments in the list
@@ -192,8 +209,8 @@ struct batadv_orig_ifinfo {
* @total_size: expected size of the assembled packet
*/
struct batadv_frag_table_entry {
- struct hlist_head head;
- spinlock_t lock; /* protects head */
+ struct hlist_head fragment_list;
+ spinlock_t lock; /* protects fragment_list */
unsigned long timestamp;
u16 seqno;
u16 size;
@@ -408,6 +425,7 @@ struct batadv_hardif_neigh_node_bat_v {
* struct batadv_hardif_neigh_node - unique neighbor per hard-interface
* @list: list node for batadv_hard_iface::neigh_list
* @addr: the MAC address of the neighboring interface
+ * @orig: the address of the originator this neighbor node belongs to
* @if_incoming: pointer to incoming hard-interface
* @last_seen: when last packet via this neighbor was received
* @bat_v: B.A.T.M.A.N. V private data
@@ -417,6 +435,7 @@ struct batadv_hardif_neigh_node_bat_v {
struct batadv_hardif_neigh_node {
struct hlist_node list;
u8 addr[ETH_ALEN];
+ u8 orig[ETH_ALEN];
struct batadv_hard_iface *if_incoming;
unsigned long last_seen;
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
@@ -706,8 +725,8 @@ struct batadv_priv_debug_log {
/**
* struct batadv_priv_gw - per mesh interface gateway data
- * @list: list of available gateway nodes
- * @list_lock: lock protecting gw_list & curr_gw
+ * @gateway_list: list of available gateway nodes
+ * @list_lock: lock protecting gateway_list & curr_gw
* @curr_gw: pointer to currently selected gateway node
* @mode: gateway operation: off, client or server (see batadv_gw_modes)
* @sel_class: gateway selection class (applies if gw_mode client)
@@ -716,8 +735,8 @@ struct batadv_priv_debug_log {
* @reselect: bool indicating a gateway re-selection is in progress
*/
struct batadv_priv_gw {
- struct hlist_head list;
- spinlock_t list_lock; /* protects gw_list & curr_gw */
+ struct hlist_head gateway_list;
+ spinlock_t list_lock; /* protects gateway_list & curr_gw */
struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */
atomic_t mode;
atomic_t sel_class;
@@ -785,9 +804,10 @@ struct batadv_mcast_querier_state {
* @num_want_all_ipv6: counter for items in want_all_ipv6_list
* @want_lists_lock: lock for protecting modifications to mcast want lists
* (traversals are rcu-locked)
+ * @work: work queue callback item for multicast TT and TVLV updates
*/
struct batadv_priv_mcast {
- struct hlist_head mla_list;
+ struct hlist_head mla_list; /* see __batadv_mcast_mla_update() */
struct hlist_head want_all_unsnoopables_list;
struct hlist_head want_all_ipv4_list;
struct hlist_head want_all_ipv6_list;
@@ -802,6 +822,7 @@ struct batadv_priv_mcast {
atomic_t num_want_all_ipv6;
/* protects want_all_{unsnoopables,ipv4,ipv6}_list */
spinlock_t want_lists_lock;
+ struct delayed_work work;
};
#endif
@@ -1363,7 +1384,8 @@ struct batadv_skb_cb {
/**
* struct batadv_forw_packet - structure for bcast packets to be sent/forwarded
- * @list: list node for batadv_socket_client::queue_list
+ * @list: list node for batadv_priv::forw_{bat,bcast}_list
+ * @cleanup_list: list node for purging functions
* @send_time: execution time for delayed_work (packet sending)
* @own: bool for locally generated packets (local OGMs are re-scheduled after
* sending)
@@ -1380,6 +1402,7 @@ struct batadv_skb_cb {
*/
struct batadv_forw_packet {
struct hlist_node list;
+ struct hlist_node cleanup_list;
unsigned long send_time;
u8 own;
struct sk_buff *skb;
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index f4fcb4a9d5c1..2b875edf77e1 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -211,7 +211,6 @@ static const struct net_device_ops bnep_netdev_ops = {
.ndo_set_rx_mode = bnep_net_set_mc_list,
.ndo_set_mac_address = bnep_net_set_mac_addr,
.ndo_tx_timeout = bnep_net_timeout,
- .ndo_change_mtu = eth_change_mtu,
};
@@ -222,6 +221,8 @@ void bnep_net_setup(struct net_device *dev)
dev->addr_len = ETH_ALEN;
ether_setup(dev);
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->netdev_ops = &bnep_netdev_ops;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 43faf2aea2ab..fae391f1871f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -57,7 +57,7 @@
#define SMP_TIMEOUT msecs_to_jiffies(30000)
#define AUTH_REQ_MASK(dev) (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
- 0x1f : 0x07)
+ 0x3f : 0x07)
#define KEY_DIST_MASK 0x07
/* Maximum message length that can be passed to aes_cmac */
@@ -76,6 +76,7 @@ enum {
SMP_FLAG_DHKEY_PENDING,
SMP_FLAG_REMOTE_OOB,
SMP_FLAG_LOCAL_OOB,
+ SMP_FLAG_CT2,
};
struct smp_dev {
@@ -357,6 +358,22 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
return err;
}
+static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16],
+ const u8 salt[16], u8 res[16])
+{
+ int err;
+
+ SMP_DBG("w %16phN salt %16phN", w, salt);
+
+ err = aes_cmac(tfm_cmac, salt, w, 16, res);
+ if (err)
+ return err;
+
+ SMP_DBG("res %16phN", res);
+
+ return err;
+}
+
/* The following functions map to the legacy SMP crypto functions e, c1,
* s1 and ah.
*/
@@ -1130,20 +1147,31 @@ static void sc_add_ltk(struct smp_chan *smp)
static void sc_generate_link_key(struct smp_chan *smp)
{
- /* These constants are as specified in the core specification.
- * In ASCII they spell out to 'tmp1' and 'lebr'.
- */
- const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+ /* From core spec. Spells out in ASCII as 'lebr'. */
const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
smp->link_key = kzalloc(16, GFP_KERNEL);
if (!smp->link_key)
return;
- if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
- kzfree(smp->link_key);
- smp->link_key = NULL;
- return;
+ if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+ /* SALT = 0x00000000000000000000000000000000746D7031 */
+ const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 };
+
+ if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) {
+ kzfree(smp->link_key);
+ smp->link_key = NULL;
+ return;
+ }
+ } else {
+ /* From core spec. Spells out in ASCII as 'tmp1'. */
+ const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+
+ if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
+ kzfree(smp->link_key);
+ smp->link_key = NULL;
+ return;
+ }
}
if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
@@ -1169,10 +1197,7 @@ static void smp_allow_key_dist(struct smp_chan *smp)
static void sc_generate_ltk(struct smp_chan *smp)
{
- /* These constants are as specified in the core specification.
- * In ASCII they spell out to 'tmp2' and 'brle'.
- */
- const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+ /* From core spec. Spells out in ASCII as 'brle'. */
const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
struct hci_conn *hcon = smp->conn->hcon;
struct hci_dev *hdev = hcon->hdev;
@@ -1187,8 +1212,19 @@ static void sc_generate_ltk(struct smp_chan *smp)
if (key->type == HCI_LK_DEBUG_COMBINATION)
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
- if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
- return;
+ if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+ /* SALT = 0x00000000000000000000000000000000746D7032 */
+ const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
+
+ if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk))
+ return;
+ } else {
+ /* From core spec. Spells out in ASCII as 'tmp2'. */
+ const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+
+ if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
+ return;
+ }
if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
return;
@@ -1669,6 +1705,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
if (!rsp) {
memset(req, 0, sizeof(*req));
+ req->auth_req = SMP_AUTH_CT2;
req->init_key_dist = local_dist;
req->resp_key_dist = remote_dist;
req->max_key_size = conn->hcon->enc_key_size;
@@ -1680,6 +1717,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
memset(rsp, 0, sizeof(*rsp));
+ rsp->auth_req = SMP_AUTH_CT2;
rsp->max_key_size = conn->hcon->enc_key_size;
rsp->init_key_dist = req->init_key_dist & remote_dist;
rsp->resp_key_dist = req->resp_key_dist & local_dist;
@@ -1744,6 +1782,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
build_bredr_pairing_cmd(smp, req, &rsp);
+ if (req->auth_req & SMP_AUTH_CT2)
+ set_bit(SMP_FLAG_CT2, &smp->flags);
+
key_size = min(req->max_key_size, rsp.max_key_size);
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
@@ -1761,9 +1802,13 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
build_pairing_cmd(conn, req, &rsp, auth);
- if (rsp.auth_req & SMP_AUTH_SC)
+ if (rsp.auth_req & SMP_AUTH_SC) {
set_bit(SMP_FLAG_SC, &smp->flags);
+ if (rsp.auth_req & SMP_AUTH_CT2)
+ set_bit(SMP_FLAG_CT2, &smp->flags);
+ }
+
if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
else
@@ -1917,6 +1962,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
*/
smp->remote_key_dist &= rsp->resp_key_dist;
+ if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2))
+ set_bit(SMP_FLAG_CT2, &smp->flags);
+
/* For BR/EDR this means we're done and can start phase 3 */
if (conn->hcon->type == ACL_LINK) {
/* Clear bits which are generated but not distributed */
@@ -2312,8 +2360,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
authreq = seclevel_to_authreq(sec_level);
- if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
+ if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) {
authreq |= SMP_AUTH_SC;
+ if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED))
+ authreq |= SMP_AUTH_CT2;
+ }
/* Require MITM if IO Capability allows or the security level
* requires it.
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index ffcc70b6b199..0ff6247eaa6c 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -57,6 +57,7 @@ struct smp_cmd_pairing {
#define SMP_AUTH_MITM 0x04
#define SMP_AUTH_SC 0x08
#define SMP_AUTH_KEYPRESS 0x10
+#define SMP_AUTH_CT2 0x20
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct smp_cmd_pairing_confirm {
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 89a687f3c0a3..bca5ead3e973 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -185,7 +185,7 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev,
static int br_change_mtu(struct net_device *dev, int new_mtu)
{
struct net_bridge *br = netdev_priv(dev);
- if (new_mtu < 68 || new_mtu > br_min_mtu(br))
+ if (new_mtu > br_min_mtu(br))
return -EINVAL;
dev->mtu = new_mtu;
@@ -409,7 +409,8 @@ void br_dev_setup(struct net_device *dev)
br->bridge_max_age = br->max_age = 20 * HZ;
br->bridge_hello_time = br->hello_time = 2 * HZ;
br->bridge_forward_delay = br->forward_delay = 15 * HZ;
- br->ageing_time = BR_DEFAULT_AGEING_TIME;
+ br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;
+ dev->max_mtu = ETH_MAX_MTU;
br_netfilter_rtable_init(br);
br_stp_timer_init(br);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 6b43c8c88f19..e4a4176171c9 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -535,9 +535,8 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
*/
if (fdb->is_local)
return 0;
- br_warn(br, "adding interface %s with same address "
- "as a received packet\n",
- source ? source->dev->name : br->dev->name);
+ br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
+ source ? source->dev->name : br->dev->name, addr, vid);
fdb_delete(br, fdb);
}
@@ -583,9 +582,8 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
/* attempt to update an entry for a local interface */
if (unlikely(fdb->is_local)) {
if (net_ratelimit())
- br_warn(br, "received packet on %s with "
- "own address as source address\n",
- source->dev->name);
+ br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n",
+ source->dev->name, addr, vid);
} else {
/* fastpath: update of existing entry */
if (unlikely(source != fdb->dst)) {
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 2136e45f5277..b30e77e8427c 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/inetdevice.h>
+#include <linux/mroute.h>
#include <net/ip.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
@@ -364,13 +365,18 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
__be32 group,
u8 *igmp_type)
{
+ struct igmpv3_query *ihv3;
+ size_t igmp_hdr_size;
struct sk_buff *skb;
struct igmphdr *ih;
struct ethhdr *eth;
struct iphdr *iph;
+ igmp_hdr_size = sizeof(*ih);
+ if (br->multicast_igmp_version == 3)
+ igmp_hdr_size = sizeof(*ihv3);
skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) +
- sizeof(*ih) + 4);
+ igmp_hdr_size + 4);
if (!skb)
goto out;
@@ -395,7 +401,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
iph->version = 4;
iph->ihl = 6;
iph->tos = 0xc0;
- iph->tot_len = htons(sizeof(*iph) + sizeof(*ih) + 4);
+ iph->tot_len = htons(sizeof(*iph) + igmp_hdr_size + 4);
iph->id = 0;
iph->frag_off = htons(IP_DF);
iph->ttl = 1;
@@ -411,17 +417,37 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
skb_put(skb, 24);
skb_set_transport_header(skb, skb->len);
- ih = igmp_hdr(skb);
*igmp_type = IGMP_HOST_MEMBERSHIP_QUERY;
- ih->type = IGMP_HOST_MEMBERSHIP_QUERY;
- ih->code = (group ? br->multicast_last_member_interval :
- br->multicast_query_response_interval) /
- (HZ / IGMP_TIMER_SCALE);
- ih->group = group;
- ih->csum = 0;
- ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr));
- skb_put(skb, sizeof(*ih));
+ switch (br->multicast_igmp_version) {
+ case 2:
+ ih = igmp_hdr(skb);
+ ih->type = IGMP_HOST_MEMBERSHIP_QUERY;
+ ih->code = (group ? br->multicast_last_member_interval :
+ br->multicast_query_response_interval) /
+ (HZ / IGMP_TIMER_SCALE);
+ ih->group = group;
+ ih->csum = 0;
+ ih->csum = ip_compute_csum((void *)ih, sizeof(*ih));
+ break;
+ case 3:
+ ihv3 = igmpv3_query_hdr(skb);
+ ihv3->type = IGMP_HOST_MEMBERSHIP_QUERY;
+ ihv3->code = (group ? br->multicast_last_member_interval :
+ br->multicast_query_response_interval) /
+ (HZ / IGMP_TIMER_SCALE);
+ ihv3->group = group;
+ ihv3->qqic = br->multicast_query_interval / HZ;
+ ihv3->nsrcs = 0;
+ ihv3->resv = 0;
+ ihv3->suppress = 0;
+ ihv3->qrv = 2;
+ ihv3->csum = 0;
+ ihv3->csum = ip_compute_csum((void *)ihv3, sizeof(*ihv3));
+ break;
+ }
+
+ skb_put(skb, igmp_hdr_size);
__skb_pull(skb, sizeof(*eth));
out:
@@ -433,15 +459,20 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
const struct in6_addr *grp,
u8 *igmp_type)
{
- struct sk_buff *skb;
+ struct mld2_query *mld2q;
+ unsigned long interval;
struct ipv6hdr *ip6h;
struct mld_msg *mldq;
+ size_t mld_hdr_size;
+ struct sk_buff *skb;
struct ethhdr *eth;
u8 *hopopt;
- unsigned long interval;
+ mld_hdr_size = sizeof(*mldq);
+ if (br->multicast_mld_version == 2)
+ mld_hdr_size = sizeof(*mld2q);
skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*ip6h) +
- 8 + sizeof(*mldq));
+ 8 + mld_hdr_size);
if (!skb)
goto out;
@@ -460,7 +491,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
ip6h = ipv6_hdr(skb);
*(__force __be32 *)ip6h = htonl(0x60000000);
- ip6h->payload_len = htons(8 + sizeof(*mldq));
+ ip6h->payload_len = htons(8 + mld_hdr_size);
ip6h->nexthdr = IPPROTO_HOPOPTS;
ip6h->hop_limit = 1;
ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
@@ -488,26 +519,47 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
/* ICMPv6 */
skb_set_transport_header(skb, skb->len);
- mldq = (struct mld_msg *) icmp6_hdr(skb);
-
interval = ipv6_addr_any(grp) ?
br->multicast_query_response_interval :
br->multicast_last_member_interval;
-
*igmp_type = ICMPV6_MGM_QUERY;
- mldq->mld_type = ICMPV6_MGM_QUERY;
- mldq->mld_code = 0;
- mldq->mld_cksum = 0;
- mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval));
- mldq->mld_reserved = 0;
- mldq->mld_mca = *grp;
-
- /* checksum */
- mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
- sizeof(*mldq), IPPROTO_ICMPV6,
- csum_partial(mldq,
- sizeof(*mldq), 0));
- skb_put(skb, sizeof(*mldq));
+ switch (br->multicast_mld_version) {
+ case 1:
+ mldq = (struct mld_msg *)icmp6_hdr(skb);
+ mldq->mld_type = ICMPV6_MGM_QUERY;
+ mldq->mld_code = 0;
+ mldq->mld_cksum = 0;
+ mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval));
+ mldq->mld_reserved = 0;
+ mldq->mld_mca = *grp;
+ mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ sizeof(*mldq), IPPROTO_ICMPV6,
+ csum_partial(mldq,
+ sizeof(*mldq),
+ 0));
+ break;
+ case 2:
+ mld2q = (struct mld2_query *)icmp6_hdr(skb);
+ mld2q->mld2q_mrc = ntohs((u16)jiffies_to_msecs(interval));
+ mld2q->mld2q_type = ICMPV6_MGM_QUERY;
+ mld2q->mld2q_code = 0;
+ mld2q->mld2q_cksum = 0;
+ mld2q->mld2q_resv1 = 0;
+ mld2q->mld2q_resv2 = 0;
+ mld2q->mld2q_suppress = 0;
+ mld2q->mld2q_qrv = 2;
+ mld2q->mld2q_nsrcs = 0;
+ mld2q->mld2q_qqic = br->multicast_query_interval / HZ;
+ mld2q->mld2q_mca = *grp;
+ mld2q->mld2q_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ sizeof(*mld2q),
+ IPPROTO_ICMPV6,
+ csum_partial(mld2q,
+ sizeof(*mld2q),
+ 0));
+ break;
+ }
+ skb_put(skb, mld_hdr_size);
__skb_pull(skb, sizeof(*eth));
@@ -607,7 +659,8 @@ err:
}
struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
- struct net_bridge_port *port, struct br_ip *group)
+ struct net_bridge_port *p,
+ struct br_ip *group)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -623,7 +676,7 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
}
hash = br_ip_hash(mdb, group);
- mp = br_multicast_get_group(br, port, group, hash);
+ mp = br_multicast_get_group(br, p, group, hash);
switch (PTR_ERR(mp)) {
case 0:
break;
@@ -680,9 +733,9 @@ static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *group)
{
- struct net_bridge_mdb_entry *mp;
- struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp;
+ struct net_bridge_port_group *p;
+ struct net_bridge_mdb_entry *mp;
unsigned long now = jiffies;
int err;
@@ -860,9 +913,9 @@ static void br_multicast_send_query(struct net_bridge *br,
struct net_bridge_port *port,
struct bridge_mcast_own_query *own_query)
{
- unsigned long time;
- struct br_ip br_group;
struct bridge_mcast_other_query *other_query = NULL;
+ struct br_ip br_group;
+ unsigned long time;
if (!netif_running(br->dev) || br->multicast_disabled ||
!br->multicast_querier)
@@ -1638,6 +1691,21 @@ static void br_multicast_err_count(const struct net_bridge *br,
u64_stats_update_end(&pstats->syncp);
}
+static void br_multicast_pim(struct net_bridge *br,
+ struct net_bridge_port *port,
+ const struct sk_buff *skb)
+{
+ unsigned int offset = skb_transport_offset(skb);
+ struct pimhdr *pimhdr, _pimhdr;
+
+ pimhdr = skb_header_pointer(skb, offset, sizeof(_pimhdr), &_pimhdr);
+ if (!pimhdr || pim_hdr_version(pimhdr) != PIM_VERSION ||
+ pim_hdr_type(pimhdr) != PIM_TYPE_HELLO)
+ return;
+
+ br_multicast_mark_router(br, port);
+}
+
static int br_multicast_ipv4_rcv(struct net_bridge *br,
struct net_bridge_port *port,
struct sk_buff *skb,
@@ -1650,8 +1718,12 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
err = ip_mc_check_igmp(skb, &skb_trimmed);
if (err == -ENOMSG) {
- if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr))
+ if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) {
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
+ } else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) {
+ if (ip_hdr(skb)->protocol == IPPROTO_PIM)
+ br_multicast_pim(br, port, skb);
+ }
return 0;
} else if (err < 0) {
br_multicast_err_count(br, port, skb->protocol);
@@ -1811,7 +1883,9 @@ void br_multicast_init(struct net_bridge *br)
br->ip4_other_query.delay_time = 0;
br->ip4_querier.port = NULL;
+ br->multicast_igmp_version = 2;
#if IS_ENABLED(CONFIG_IPV6)
+ br->multicast_mld_version = 1;
br->ip6_other_query.delay_time = 0;
br->ip6_querier.port = NULL;
#endif
@@ -2112,6 +2186,44 @@ unlock:
return err;
}
+int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val)
+{
+ /* Currently we support only version 2 and 3 */
+ switch (val) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&br->multicast_lock);
+ br->multicast_igmp_version = val;
+ spin_unlock_bh(&br->multicast_lock);
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val)
+{
+ /* Currently we support version 1 and 2 */
+ switch (val) {
+ case 1:
+ case 2:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&br->multicast_lock);
+ br->multicast_mld_version = val;
+ spin_unlock_bh(&br->multicast_lock);
+
+ return 0;
+}
+#endif
+
/**
* br_multicast_list_adjacent - Returns snooped multicast addresses
* @dev: The bridge port adjacent to which to retrieve addresses
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 2fe9345c1407..b12501a77f18 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -46,7 +46,7 @@
#include <linux/sysctl.h>
#endif
-static int brnf_net_id __read_mostly;
+static unsigned int brnf_net_id __read_mostly;
struct brnf_net {
bool enabled;
@@ -561,8 +561,8 @@ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff
}
nf_bridge_push_encap_header(skb);
- NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_FORWARD, net, sk, skb,
- in, skb->dev, br_forward_finish, 1);
+ br_nf_hook_thresh(NF_BR_FORWARD, net, sk, skb, in, skb->dev,
+ br_forward_finish);
return 0;
}
@@ -845,8 +845,10 @@ static unsigned int ip_sabotage_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
- if (skb->nf_bridge && !skb->nf_bridge->in_prerouting)
- return NF_STOP;
+ if (skb->nf_bridge && !skb->nf_bridge->in_prerouting) {
+ state->okfn(state->net, state->sk, skb);
+ return NF_STOLEN;
+ }
return NF_ACCEPT;
}
@@ -1006,20 +1008,20 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
struct nf_hook_state state;
int ret;
- elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
-
- while (elem && (elem->ops.priority <= NF_BR_PRI_BRNF))
- elem = rcu_dereference(elem->next);
+ for (elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
+ elem && nf_hook_entry_priority(elem) <= NF_BR_PRI_BRNF;
+ elem = rcu_dereference(elem->next))
+ ;
if (!elem)
return okfn(net, sk, skb);
/* We may already have this, but read-locks nest anyway */
rcu_read_lock();
- nf_hook_state_init(&state, elem, hook, NF_BR_PRI_BRNF + 1,
- NFPROTO_BRIDGE, indev, outdev, sk, net, okfn);
+ nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
+ sk, net, okfn);
- ret = nf_hook_slow(skb, &state);
+ ret = nf_hook_slow(skb, &state, elem);
rcu_read_unlock();
if (ret == 1)
ret = okfn(net, sk, skb);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index e99037c6f7b7..71c7453268c1 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -858,6 +858,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
[IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NLA_U16 },
[IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 },
[IFLA_BR_MCAST_STATS_ENABLED] = { .type = NLA_U8 },
+ [IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 },
+ [IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 },
};
static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -1069,6 +1071,26 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
mcast_stats = nla_get_u8(data[IFLA_BR_MCAST_STATS_ENABLED]);
br->multicast_stats_enabled = !!mcast_stats;
}
+
+ if (data[IFLA_BR_MCAST_IGMP_VERSION]) {
+ __u8 igmp_version;
+
+ igmp_version = nla_get_u8(data[IFLA_BR_MCAST_IGMP_VERSION]);
+ err = br_multicast_set_igmp_version(br, igmp_version);
+ if (err)
+ return err;
+ }
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (data[IFLA_BR_MCAST_MLD_VERSION]) {
+ __u8 mld_version;
+
+ mld_version = nla_get_u8(data[IFLA_BR_MCAST_MLD_VERSION]);
+ err = br_multicast_set_mld_version(br, mld_version);
+ if (err)
+ return err;
+ }
+#endif
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (data[IFLA_BR_NF_CALL_IPTABLES]) {
@@ -1135,6 +1157,8 @@ static size_t br_get_size(const struct net_device *brdev)
nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_INTVL */
nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_RESPONSE_INTVL */
nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_STARTUP_QUERY_INTVL */
+ nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_IGMP_VERSION */
+ nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_MLD_VERSION */
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_IPTABLES */
@@ -1210,9 +1234,15 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
nla_put_u32(skb, IFLA_BR_MCAST_LAST_MEMBER_CNT,
br->multicast_last_member_count) ||
nla_put_u32(skb, IFLA_BR_MCAST_STARTUP_QUERY_CNT,
- br->multicast_startup_query_count))
+ br->multicast_startup_query_count) ||
+ nla_put_u8(skb, IFLA_BR_MCAST_IGMP_VERSION,
+ br->multicast_igmp_version))
return -EMSGSIZE;
-
+#if IS_ENABLED(CONFIG_IPV6)
+ if (nla_put_u8(skb, IFLA_BR_MCAST_MLD_VERSION,
+ br->multicast_mld_version))
+ return -EMSGSIZE;
+#endif
clockval = jiffies_to_clock_t(br->multicast_last_member_interval);
if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_LAST_MEMBER_INTVL, clockval,
IFLA_BR_PAD))
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1b63177e0ccd..8ce621e8345c 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -300,10 +300,11 @@ struct net_bridge
unsigned long max_age;
unsigned long hello_time;
unsigned long forward_delay;
- unsigned long bridge_max_age;
unsigned long ageing_time;
+ unsigned long bridge_max_age;
unsigned long bridge_hello_time;
unsigned long bridge_forward_delay;
+ unsigned long bridge_ageing_time;
u8 group_addr[ETH_ALEN];
bool group_addr_set;
@@ -333,6 +334,8 @@ struct net_bridge
u32 multicast_last_member_count;
u32 multicast_startup_query_count;
+ u8 multicast_igmp_version;
+
unsigned long multicast_last_member_interval;
unsigned long multicast_membership_interval;
unsigned long multicast_querier_interval;
@@ -353,6 +356,7 @@ struct net_bridge
struct bridge_mcast_other_query ip6_other_query;
struct bridge_mcast_own_query ip6_own_query;
struct bridge_mcast_querier ip6_querier;
+ u8 multicast_mld_version;
#endif /* IS_ENABLED(CONFIG_IPV6) */
#endif
@@ -582,6 +586,10 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val);
int br_multicast_toggle(struct net_bridge *br, unsigned long val);
int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
+int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val);
+#if IS_ENABLED(CONFIG_IPV6)
+int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val);
+#endif
struct net_bridge_mdb_entry *
br_mdb_ip_get(struct net_bridge_mdb_htable *mdb, struct br_ip *dst);
struct net_bridge_mdb_entry *
@@ -992,6 +1000,7 @@ void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
int br_set_forward_delay(struct net_bridge *br, unsigned long x);
int br_set_hello_time(struct net_bridge *br, unsigned long x);
int br_set_max_age(struct net_bridge *br, unsigned long x);
+int __set_ageing_time(struct net_device *dev, unsigned long t);
int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time);
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h
index 2fe910c4e170..3f7543a29b76 100644
--- a/net/bridge/br_private_stp.h
+++ b/net/bridge/br_private_stp.h
@@ -61,6 +61,7 @@ void br_received_tcn_bpdu(struct net_bridge_port *p);
void br_transmit_config(struct net_bridge_port *p);
void br_transmit_tcn(struct net_bridge *br);
void br_topology_change_detection(struct net_bridge *br);
+void __br_set_topology_change(struct net_bridge *br, unsigned char val);
/* br_stp_bpdu.c */
void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 9258b8ef14ff..71fd1a4e63cc 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -234,7 +234,7 @@ static void br_record_config_timeout_values(struct net_bridge *br,
br->max_age = bpdu->max_age;
br->hello_time = bpdu->hello_time;
br->forward_delay = bpdu->forward_delay;
- br->topology_change = bpdu->topology_change;
+ __br_set_topology_change(br, bpdu->topology_change);
}
/* called under bridge lock */
@@ -344,7 +344,7 @@ void br_topology_change_detection(struct net_bridge *br)
isroot ? "propagating" : "sending tcn bpdu");
if (isroot) {
- br->topology_change = 1;
+ __br_set_topology_change(br, 1);
mod_timer(&br->topology_change_timer, jiffies
+ br->bridge_forward_delay + br->bridge_max_age);
} else if (!br->topology_change_detected) {
@@ -562,6 +562,24 @@ int br_set_max_age(struct net_bridge *br, unsigned long val)
}
+/* called under bridge lock */
+int __set_ageing_time(struct net_device *dev, unsigned long t)
+{
+ struct switchdev_attr attr = {
+ .orig_dev = dev,
+ .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
+ .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER,
+ .u.ageing_time = jiffies_to_clock_t(t),
+ };
+ int err;
+
+ err = switchdev_port_attr_set(dev, &attr);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ return 0;
+}
+
/* Set time interval that dynamic forwarding entries live
* For pure software bridge, allow values outside the 802.1
* standard specification for special cases:
@@ -572,25 +590,52 @@ int br_set_max_age(struct net_bridge *br, unsigned long val)
*/
int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time)
{
- struct switchdev_attr attr = {
- .orig_dev = br->dev,
- .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
- .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP,
- .u.ageing_time = ageing_time,
- };
unsigned long t = clock_t_to_jiffies(ageing_time);
int err;
- err = switchdev_port_attr_set(br->dev, &attr);
- if (err && err != -EOPNOTSUPP)
+ err = __set_ageing_time(br->dev, t);
+ if (err)
return err;
+ spin_lock_bh(&br->lock);
+ br->bridge_ageing_time = t;
br->ageing_time = t;
+ spin_unlock_bh(&br->lock);
+
mod_timer(&br->gc_timer, jiffies);
return 0;
}
+/* called under bridge lock */
+void __br_set_topology_change(struct net_bridge *br, unsigned char val)
+{
+ unsigned long t;
+ int err;
+
+ if (br->stp_enabled == BR_KERNEL_STP && br->topology_change != val) {
+ /* On topology change, set the bridge ageing time to twice the
+ * forward delay. Otherwise, restore its default ageing time.
+ */
+
+ if (val) {
+ t = 2 * br->forward_delay;
+ br_debug(br, "decreasing ageing time to %lu\n", t);
+ } else {
+ t = br->bridge_ageing_time;
+ br_debug(br, "restoring ageing time to %lu\n", t);
+ }
+
+ err = __set_ageing_time(br->dev, t);
+ if (err)
+ br_warn(br, "error offloading ageing time\n");
+ else
+ br->ageing_time = t;
+ }
+
+ br->topology_change = val;
+}
+
void __br_set_forward_delay(struct net_bridge *br, unsigned long t)
{
br->bridge_forward_delay = t;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index d8ad73b38de2..6c1e21411125 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -36,12 +36,6 @@ static inline port_id br_make_port_id(__u8 priority, __u16 port_no)
/* called under bridge lock */
void br_init_port(struct net_bridge_port *p)
{
- struct switchdev_attr attr = {
- .orig_dev = p->dev,
- .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
- .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER,
- .u.ageing_time = jiffies_to_clock_t(p->br->ageing_time),
- };
int err;
p->port_id = br_make_port_id(p->priority, p->port_no);
@@ -50,9 +44,9 @@ void br_init_port(struct net_bridge_port *p)
p->topology_change_ack = 0;
p->config_pending = 0;
- err = switchdev_port_attr_set(p->dev, &attr);
- if (err && err != -EOPNOTSUPP)
- netdev_err(p->dev, "failed to set HW ageing time\n");
+ err = __set_ageing_time(p->dev, p->br->ageing_time);
+ if (err)
+ netdev_err(p->dev, "failed to offload ageing time\n");
}
/* NO locks held */
@@ -87,7 +81,7 @@ void br_stp_disable_bridge(struct net_bridge *br)
}
- br->topology_change = 0;
+ __br_set_topology_change(br, 0);
br->topology_change_detected = 0;
spin_unlock_bh(&br->lock);
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index da058b85aa22..7ddb38e0a06e 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -125,7 +125,7 @@ static void br_topology_change_timer_expired(unsigned long arg)
br_debug(br, "topo change timer expired\n");
spin_lock(&br->lock);
br->topology_change_detected = 0;
- br->topology_change = 0;
+ __br_set_topology_change(br, 0);
spin_unlock(&br->lock);
}
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index f88c4df3f91e..a18148213b08 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -440,6 +440,23 @@ static ssize_t hash_max_store(struct device *d, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(hash_max);
+static ssize_t multicast_igmp_version_show(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+
+ return sprintf(buf, "%u\n", br->multicast_igmp_version);
+}
+
+static ssize_t multicast_igmp_version_store(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return store_bridge_parm(d, buf, len, br_multicast_set_igmp_version);
+}
+static DEVICE_ATTR_RW(multicast_igmp_version);
+
static ssize_t multicast_last_member_count_show(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -642,6 +659,25 @@ static ssize_t multicast_stats_enabled_store(struct device *d,
return store_bridge_parm(d, buf, len, set_stats_enabled);
}
static DEVICE_ATTR_RW(multicast_stats_enabled);
+
+#if IS_ENABLED(CONFIG_IPV6)
+static ssize_t multicast_mld_version_show(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+
+ return sprintf(buf, "%u\n", br->multicast_mld_version);
+}
+
+static ssize_t multicast_mld_version_store(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return store_bridge_parm(d, buf, len, br_multicast_set_mld_version);
+}
+static DEVICE_ATTR_RW(multicast_mld_version);
+#endif
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static ssize_t nf_call_iptables_show(
@@ -809,6 +845,10 @@ static struct attribute *bridge_attrs[] = {
&dev_attr_multicast_query_response_interval.attr,
&dev_attr_multicast_startup_query_interval.attr,
&dev_attr_multicast_stats_enabled.attr,
+ &dev_attr_multicast_igmp_version.attr,
+#if IS_ENABLED(CONFIG_IPV6)
+ &dev_attr_multicast_mld_version.attr,
+#endif
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
&dev_attr_nf_call_iptables.attr,
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index 9cebf47ac840..e7ef1a1ef3a6 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -22,6 +22,7 @@ config NFT_BRIDGE_REJECT
config NF_LOG_BRIDGE
tristate "Bridge packet logging"
+ select NF_LOG_COMMON
endif # NF_TABLES_BRIDGE
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 070cf134a22f..5929309beaa1 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -51,7 +51,8 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (diptr == NULL)
return EBT_DROP;
- arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)par->in,
+ arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr,
+ (struct net_device *)xt_in(par),
*diptr, shp, info->mac, shp);
return info->target;
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 9a11086ba6ff..e88bd4827ac1 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -179,7 +179,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_log_info *info = par->targinfo;
struct nf_loginfo li;
- struct net *net = par->net;
+ struct net *net = xt_net(par);
li.type = NF_LOG_TYPE_LOG;
li.u.log.level = info->loglevel;
@@ -190,11 +190,12 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
* nf_log_packet() with NFT_LOG_TYPE_LOG here. --Pablo
*/
if (info->bitmask & EBT_LOG_NFLOG)
- nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb,
- par->in, par->out, &li, "%s", info->prefix);
+ nf_log_packet(net, NFPROTO_BRIDGE, xt_hooknum(par), skb,
+ xt_in(par), xt_out(par), &li, "%s",
+ info->prefix);
else
- ebt_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, par->in,
- par->out, &li, info->prefix);
+ ebt_log_packet(net, NFPROTO_BRIDGE, xt_hooknum(par), skb,
+ xt_in(par), xt_out(par), &li, info->prefix);
return EBT_CONTINUE;
}
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
index 54816150608e..c1dc48686200 100644
--- a/net/bridge/netfilter/ebt_nflog.c
+++ b/net/bridge/netfilter/ebt_nflog.c
@@ -23,16 +23,16 @@ static unsigned int
ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_nflog_info *info = par->targinfo;
+ struct net *net = xt_net(par);
struct nf_loginfo li;
- struct net *net = par->net;
li.type = NF_LOG_TYPE_ULOG;
li.u.ulog.copy_len = info->len;
li.u.ulog.group = info->group;
li.u.ulog.qthreshold = info->threshold;
- nf_log_packet(net, PF_BRIDGE, par->hooknum, skb, par->in,
- par->out, &li, "%s", info->prefix);
+ nf_log_packet(net, PF_BRIDGE, xt_hooknum(par), skb, xt_in(par),
+ xt_out(par), &li, "%s", info->prefix);
return EBT_CONTINUE;
}
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 2e7c4f974340..8d2a85e0594e 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -23,12 +23,12 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (!skb_make_writable(skb, 0))
return EBT_DROP;
- if (par->hooknum != NF_BR_BROUTING)
+ if (xt_hooknum(par) != NF_BR_BROUTING)
/* rcu_read_lock()ed by nf_hook_thresh */
ether_addr_copy(eth_hdr(skb)->h_dest,
- br_port_get_rcu(par->in)->br->dev->dev_addr);
+ br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
else
- ether_addr_copy(eth_hdr(skb)->h_dest, par->in->dev_addr);
+ ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
skb->pkt_type = PACKET_HOST;
return info->target;
}
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index ec94c6f1ae88..8fe36dc3aab2 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -53,7 +53,7 @@ static int ebt_broute(struct sk_buff *skb)
struct nf_hook_state state;
int ret;
- nf_hook_state_init(&state, NULL, NF_BR_BROUTING, INT_MIN,
+ nf_hook_state_init(&state, NF_BR_BROUTING,
NFPROTO_BRIDGE, skb->dev, NULL, NULL,
dev_net(skb->dev), NULL);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index f5c11bbe27db..1ab6014cf0f8 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -194,12 +194,8 @@ unsigned int ebt_do_table(struct sk_buff *skb,
const struct ebt_table_info *private;
struct xt_action_param acpar;
- acpar.family = NFPROTO_BRIDGE;
- acpar.net = state->net;
- acpar.in = state->in;
- acpar.out = state->out;
+ acpar.state = state;
acpar.hotdrop = false;
- acpar.hooknum = hook;
read_lock_bh(&table->lock);
private = table->private;
diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c
index 1663df598545..bd2b3c78f59b 100644
--- a/net/bridge/netfilter/nf_log_bridge.c
+++ b/net/bridge/netfilter/nf_log_bridge.c
@@ -24,21 +24,8 @@ static void nf_log_bridge_packet(struct net *net, u_int8_t pf,
const struct nf_loginfo *loginfo,
const char *prefix)
{
- switch (eth_hdr(skb)->h_proto) {
- case htons(ETH_P_IP):
- nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
- loginfo, "%s", prefix);
- break;
- case htons(ETH_P_IPV6):
- nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out,
- loginfo, "%s", prefix);
- break;
- case htons(ETH_P_ARP):
- case htons(ETH_P_RARP):
- nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out,
- loginfo, "%s", prefix);
- break;
- }
+ nf_log_l2packet(net, pf, eth_hdr(skb)->h_proto, hooknum, skb,
+ in, out, loginfo, prefix);
}
static struct nf_logger nf_bridge_logger __read_mostly = {
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c
index ad47a921b701..5974dbc1ea24 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -23,7 +23,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt)
{
const struct nft_meta *priv = nft_expr_priv(expr);
- const struct net_device *in = pkt->in, *out = pkt->out;
+ const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
u32 *dest = &regs->data[priv->dreg];
const struct net_bridge_port *p;
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index 4b3df6b0e3b9..206dc266ecd2 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -315,17 +315,20 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
case htons(ETH_P_IP):
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
- pkt->in, pkt->hook,
+ nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt),
priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
- nft_reject_br_send_v4_tcp_reset(pkt->net, pkt->skb,
- pkt->in, pkt->hook);
+ nft_reject_br_send_v4_tcp_reset(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt));
break;
case NFT_REJECT_ICMPX_UNREACH:
- nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
- pkt->in, pkt->hook,
+ nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt),
nft_reject_icmp_code(priv->icmp_code));
break;
}
@@ -333,17 +336,20 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
case htons(ETH_P_IPV6):
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
- pkt->in, pkt->hook,
+ nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt),
priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
- nft_reject_br_send_v6_tcp_reset(pkt->net, pkt->skb,
- pkt->in, pkt->hook);
+ nft_reject_br_send_v6_tcp_reset(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt));
break;
case NFT_REJECT_ICMPX_UNREACH:
- nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
- pkt->in, pkt->hook,
+ nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb,
+ nft_in(pkt),
+ nft_hook(pkt),
nft_reject_icmpv6_code(priv->icmp_code));
break;
}
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index d730a0f68f46..2d38b6e34203 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -52,7 +52,7 @@ struct caif_net {
struct caif_device_entry_list caifdevs;
};
-static int caif_net_id;
+static unsigned int caif_net_id;
static int q_high = 50; /* Percent */
struct cfcnfg *get_cfcnfg(struct net *net)
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index fa39fc298708..273cb07f57d8 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -390,8 +390,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
rcu_read_lock();
if (adapt_layer == NULL) {
- pr_debug("link setup response but no client exist,"
- "send linkdown back\n");
+ pr_debug("link setup response but no client exist, send linkdown back\n");
cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
goto unlock;
}
@@ -401,8 +400,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
if (phyinfo == NULL) {
- pr_err("ERROR: Link Layer Device disappeared"
- "while connecting\n");
+ pr_err("ERROR: Link Layer Device disappeared while connecting\n");
goto unlock;
}
@@ -436,8 +434,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
break;
default:
- pr_err("Protocol error. Link setup response "
- "- unknown channel type\n");
+ pr_err("Protocol error. Link setup response - unknown channel type\n");
goto unlock;
}
if (!servicel)
diff --git a/net/core/Makefile b/net/core/Makefile
index d6508c2ddca5..f6761b6e3b29 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o
obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
+obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o
obj-$(CONFIG_DST_CACHE) += dst_cache.o
obj-$(CONFIG_HWBM) += hwbm.o
obj-$(CONFIG_NET_DEVLINK) += devlink.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b7de71f8d5d3..9482037a5c8c 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -165,6 +165,7 @@ done:
* __skb_try_recv_datagram - Receive a datagram skbuff
* @sk: socket
* @flags: MSG_ flags
+ * @destructor: invoked under the receive lock on successful dequeue
* @peeked: returns non-zero if this packet has been seen before
* @off: an offset in bytes to peek skb from. Returns an offset
* within an skb where data actually starts
@@ -197,6 +198,8 @@ done:
* the standard around please.
*/
struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
+ void (*destructor)(struct sock *sk,
+ struct sk_buff *skb),
int *peeked, int *off, int *err,
struct sk_buff **last)
{
@@ -211,6 +214,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
if (error)
goto no_packet;
+ *peeked = 0;
do {
/* Again only user level code calls this function, so nothing
* interrupt level will suddenly eat the receive_queue.
@@ -224,26 +228,28 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
spin_lock_irqsave(&queue->lock, cpu_flags);
skb_queue_walk(queue, skb) {
*last = skb;
- *peeked = skb->peeked;
if (flags & MSG_PEEK) {
if (_off >= skb->len && (skb->len || _off ||
skb->peeked)) {
_off -= skb->len;
continue;
}
-
- skb = skb_set_peeked(skb);
- error = PTR_ERR(skb);
- if (IS_ERR(skb)) {
- spin_unlock_irqrestore(&queue->lock,
- cpu_flags);
- goto no_packet;
+ if (!skb->len) {
+ skb = skb_set_peeked(skb);
+ if (IS_ERR(skb)) {
+ error = PTR_ERR(skb);
+ spin_unlock_irqrestore(&queue->lock,
+ cpu_flags);
+ goto no_packet;
+ }
}
-
+ *peeked = 1;
atomic_inc(&skb->users);
- } else
+ } else {
__skb_unlink(skb, queue);
-
+ if (destructor)
+ destructor(sk, skb);
+ }
spin_unlock_irqrestore(&queue->lock, cpu_flags);
*off = _off;
return skb;
@@ -262,6 +268,8 @@ no_packet:
EXPORT_SYMBOL(__skb_try_recv_datagram);
struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
+ void (*destructor)(struct sock *sk,
+ struct sk_buff *skb),
int *peeked, int *off, int *err)
{
struct sk_buff *skb, *last;
@@ -270,8 +278,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
do {
- skb = __skb_try_recv_datagram(sk, flags, peeked, off, err,
- &last);
+ skb = __skb_try_recv_datagram(sk, flags, destructor, peeked,
+ off, err, &last);
if (skb)
return skb;
@@ -290,7 +298,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned int flags,
int peeked, off = 0;
return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
- &peeked, &off, err);
+ NULL, &peeked, &off, err);
}
EXPORT_SYMBOL(skb_recv_datagram);
@@ -323,6 +331,27 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
}
EXPORT_SYMBOL(__skb_free_datagram_locked);
+int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
+ unsigned int flags)
+{
+ int err = 0;
+
+ if (flags & MSG_PEEK) {
+ err = -ENOENT;
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ if (skb == skb_peek(&sk->sk_receive_queue)) {
+ __skb_unlink(skb, &sk->sk_receive_queue);
+ atomic_dec(&skb->users);
+ err = 0;
+ }
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ }
+
+ atomic_inc(&sk->sk_drops);
+ return err;
+}
+EXPORT_SYMBOL(__sk_queue_drop_skb);
+
/**
* skb_kill_datagram - Free a datagram skbuff forcibly
* @sk: socket
@@ -346,23 +375,10 @@ EXPORT_SYMBOL(__skb_free_datagram_locked);
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
{
- int err = 0;
-
- if (flags & MSG_PEEK) {
- err = -ENOENT;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- if (skb == skb_peek(&sk->sk_receive_queue)) {
- __skb_unlink(skb, &sk->sk_receive_queue);
- atomic_dec(&skb->users);
- err = 0;
- }
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- }
+ int err = __sk_queue_drop_skb(sk, skb, flags);
kfree_skb(skb);
- atomic_inc(&sk->sk_drops);
sk_mem_reclaim_partial(sk);
-
return err;
}
EXPORT_SYMBOL(skb_kill_datagram);
diff --git a/net/core/dev.c b/net/core/dev.c
index 6666b28b6815..6372117f653f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -139,7 +139,6 @@
#include <linux/errqueue.h>
#include <linux/hrtimer.h>
#include <linux/netfilter_ingress.h>
-#include <linux/sctp.h>
#include <linux/crash_dump.h>
#include "net-sysfs.h"
@@ -1944,37 +1943,80 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
}
}
+int netdev_txq_to_tc(struct net_device *dev, unsigned int txq)
+{
+ if (dev->num_tc) {
+ struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
+ int i;
+
+ for (i = 0; i < TC_MAX_QUEUE; i++, tc++) {
+ if ((txq - tc->offset) < tc->count)
+ return i;
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_XPS
static DEFINE_MUTEX(xps_map_mutex);
#define xmap_dereference(P) \
rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
-static struct xps_map *remove_xps_queue(struct xps_dev_maps *dev_maps,
- int cpu, u16 index)
+static bool remove_xps_queue(struct xps_dev_maps *dev_maps,
+ int tci, u16 index)
{
struct xps_map *map = NULL;
int pos;
if (dev_maps)
- map = xmap_dereference(dev_maps->cpu_map[cpu]);
+ map = xmap_dereference(dev_maps->cpu_map[tci]);
+ if (!map)
+ return false;
- for (pos = 0; map && pos < map->len; pos++) {
- if (map->queues[pos] == index) {
- if (map->len > 1) {
- map->queues[pos] = map->queues[--map->len];
- } else {
- RCU_INIT_POINTER(dev_maps->cpu_map[cpu], NULL);
- kfree_rcu(map, rcu);
- map = NULL;
- }
+ for (pos = map->len; pos--;) {
+ if (map->queues[pos] != index)
+ continue;
+
+ if (map->len > 1) {
+ map->queues[pos] = map->queues[--map->len];
break;
}
+
+ RCU_INIT_POINTER(dev_maps->cpu_map[tci], NULL);
+ kfree_rcu(map, rcu);
+ return false;
+ }
+
+ return true;
+}
+
+static bool remove_xps_queue_cpu(struct net_device *dev,
+ struct xps_dev_maps *dev_maps,
+ int cpu, u16 offset, u16 count)
+{
+ int num_tc = dev->num_tc ? : 1;
+ bool active = false;
+ int tci;
+
+ for (tci = cpu * num_tc; num_tc--; tci++) {
+ int i, j;
+
+ for (i = count, j = offset; i--; j++) {
+ if (!remove_xps_queue(dev_maps, cpu, j))
+ break;
+ }
+
+ active |= i < 0;
}
- return map;
+ return active;
}
-static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
+static void netif_reset_xps_queues(struct net_device *dev, u16 offset,
+ u16 count)
{
struct xps_dev_maps *dev_maps;
int cpu, i;
@@ -1986,21 +2028,16 @@ static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
if (!dev_maps)
goto out_no_maps;
- for_each_possible_cpu(cpu) {
- for (i = index; i < dev->num_tx_queues; i++) {
- if (!remove_xps_queue(dev_maps, cpu, i))
- break;
- }
- if (i == dev->num_tx_queues)
- active = true;
- }
+ for_each_possible_cpu(cpu)
+ active |= remove_xps_queue_cpu(dev, dev_maps, cpu,
+ offset, count);
if (!active) {
RCU_INIT_POINTER(dev->xps_maps, NULL);
kfree_rcu(dev_maps, rcu);
}
- for (i = index; i < dev->num_tx_queues; i++)
+ for (i = offset + (count - 1); count--; i--)
netdev_queue_numa_node_write(netdev_get_tx_queue(dev, i),
NUMA_NO_NODE);
@@ -2008,6 +2045,11 @@ out_no_maps:
mutex_unlock(&xps_map_mutex);
}
+static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
+{
+ netif_reset_xps_queues(dev, index, dev->num_tx_queues - index);
+}
+
static struct xps_map *expand_xps_map(struct xps_map *map,
int cpu, u16 index)
{
@@ -2047,20 +2089,28 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
u16 index)
{
struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
+ int i, cpu, tci, numa_node_id = -2;
+ int maps_sz, num_tc = 1, tc = 0;
struct xps_map *map, *new_map;
- int maps_sz = max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES);
- int cpu, numa_node_id = -2;
bool active = false;
+ if (dev->num_tc) {
+ num_tc = dev->num_tc;
+ tc = netdev_txq_to_tc(dev, index);
+ if (tc < 0)
+ return -EINVAL;
+ }
+
+ maps_sz = XPS_DEV_MAPS_SIZE(num_tc);
+ if (maps_sz < L1_CACHE_BYTES)
+ maps_sz = L1_CACHE_BYTES;
+
mutex_lock(&xps_map_mutex);
dev_maps = xmap_dereference(dev->xps_maps);
/* allocate memory for queue storage */
- for_each_online_cpu(cpu) {
- if (!cpumask_test_cpu(cpu, mask))
- continue;
-
+ for_each_cpu_and(cpu, cpu_online_mask, mask) {
if (!new_dev_maps)
new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
if (!new_dev_maps) {
@@ -2068,25 +2118,38 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
return -ENOMEM;
}
- map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
+ tci = cpu * num_tc + tc;
+ map = dev_maps ? xmap_dereference(dev_maps->cpu_map[tci]) :
NULL;
map = expand_xps_map(map, cpu, index);
if (!map)
goto error;
- RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
+ RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
}
if (!new_dev_maps)
goto out_no_new_maps;
for_each_possible_cpu(cpu) {
+ /* copy maps belonging to foreign traffic classes */
+ for (i = tc, tci = cpu * num_tc; dev_maps && i--; tci++) {
+ /* fill in the new device map from the old device map */
+ map = xmap_dereference(dev_maps->cpu_map[tci]);
+ RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
+ }
+
+ /* We need to explicitly update tci as prevous loop
+ * could break out early if dev_maps is NULL.
+ */
+ tci = cpu * num_tc + tc;
+
if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu)) {
/* add queue to CPU maps */
int pos = 0;
- map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
+ map = xmap_dereference(new_dev_maps->cpu_map[tci]);
while ((pos < map->len) && (map->queues[pos] != index))
pos++;
@@ -2100,26 +2163,36 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
#endif
} else if (dev_maps) {
/* fill in the new device map from the old device map */
- map = xmap_dereference(dev_maps->cpu_map[cpu]);
- RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
+ map = xmap_dereference(dev_maps->cpu_map[tci]);
+ RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
}
+ /* copy maps belonging to foreign traffic classes */
+ for (i = num_tc - tc, tci++; dev_maps && --i; tci++) {
+ /* fill in the new device map from the old device map */
+ map = xmap_dereference(dev_maps->cpu_map[tci]);
+ RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
+ }
}
rcu_assign_pointer(dev->xps_maps, new_dev_maps);
/* Cleanup old maps */
- if (dev_maps) {
- for_each_possible_cpu(cpu) {
- new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
- map = xmap_dereference(dev_maps->cpu_map[cpu]);
+ if (!dev_maps)
+ goto out_no_old_maps;
+
+ for_each_possible_cpu(cpu) {
+ for (i = num_tc, tci = cpu * num_tc; i--; tci++) {
+ new_map = xmap_dereference(new_dev_maps->cpu_map[tci]);
+ map = xmap_dereference(dev_maps->cpu_map[tci]);
if (map && map != new_map)
kfree_rcu(map, rcu);
}
-
- kfree_rcu(dev_maps, rcu);
}
+ kfree_rcu(dev_maps, rcu);
+
+out_no_old_maps:
dev_maps = new_dev_maps;
active = true;
@@ -2134,11 +2207,12 @@ out_no_new_maps:
/* removes queue from unused CPUs */
for_each_possible_cpu(cpu) {
- if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu))
- continue;
-
- if (remove_xps_queue(dev_maps, cpu, index))
- active = true;
+ for (i = tc, tci = cpu * num_tc; i--; tci++)
+ active |= remove_xps_queue(dev_maps, tci, index);
+ if (!cpumask_test_cpu(cpu, mask) || !cpu_online(cpu))
+ active |= remove_xps_queue(dev_maps, tci, index);
+ for (i = num_tc - tc, tci++; --i; tci++)
+ active |= remove_xps_queue(dev_maps, tci, index);
}
/* free map if not active */
@@ -2154,11 +2228,14 @@ out_no_maps:
error:
/* remove any maps that we added */
for_each_possible_cpu(cpu) {
- new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
- map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
- NULL;
- if (new_map && new_map != map)
- kfree(new_map);
+ for (i = num_tc, tci = cpu * num_tc; i--; tci++) {
+ new_map = xmap_dereference(new_dev_maps->cpu_map[tci]);
+ map = dev_maps ?
+ xmap_dereference(dev_maps->cpu_map[tci]) :
+ NULL;
+ if (new_map && new_map != map)
+ kfree(new_map);
+ }
}
mutex_unlock(&xps_map_mutex);
@@ -2169,6 +2246,44 @@ error:
EXPORT_SYMBOL(netif_set_xps_queue);
#endif
+void netdev_reset_tc(struct net_device *dev)
+{
+#ifdef CONFIG_XPS
+ netif_reset_xps_queues_gt(dev, 0);
+#endif
+ dev->num_tc = 0;
+ memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
+ memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
+}
+EXPORT_SYMBOL(netdev_reset_tc);
+
+int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
+{
+ if (tc >= dev->num_tc)
+ return -EINVAL;
+
+#ifdef CONFIG_XPS
+ netif_reset_xps_queues(dev, offset, count);
+#endif
+ dev->tc_to_txq[tc].count = count;
+ dev->tc_to_txq[tc].offset = offset;
+ return 0;
+}
+EXPORT_SYMBOL(netdev_set_tc_queue);
+
+int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
+{
+ if (num_tc > TC_MAX_QUEUE)
+ return -EINVAL;
+
+#ifdef CONFIG_XPS
+ netif_reset_xps_queues_gt(dev, 0);
+#endif
+ dev->num_tc = num_tc;
+ return 0;
+}
+EXPORT_SYMBOL(netdev_set_num_tc);
+
/*
* Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
* greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
@@ -2487,141 +2602,6 @@ out:
}
EXPORT_SYMBOL(skb_checksum_help);
-/* skb_csum_offload_check - Driver helper function to determine if a device
- * with limited checksum offload capabilities is able to offload the checksum
- * for a given packet.
- *
- * Arguments:
- * skb - sk_buff for the packet in question
- * spec - contains the description of what device can offload
- * csum_encapped - returns true if the checksum being offloaded is
- * encpasulated. That is it is checksum for the transport header
- * in the inner headers.
- * checksum_help - when set indicates that helper function should
- * call skb_checksum_help if offload checks fail
- *
- * Returns:
- * true: Packet has passed the checksum checks and should be offloadable to
- * the device (a driver may still need to check for additional
- * restrictions of its device)
- * false: Checksum is not offloadable. If checksum_help was set then
- * skb_checksum_help was called to resolve checksum for non-GSO
- * packets and when IP protocol is not SCTP
- */
-bool __skb_csum_offload_chk(struct sk_buff *skb,
- const struct skb_csum_offl_spec *spec,
- bool *csum_encapped,
- bool csum_help)
-{
- struct iphdr *iph;
- struct ipv6hdr *ipv6;
- void *nhdr;
- int protocol;
- u8 ip_proto;
-
- if (skb->protocol == htons(ETH_P_8021Q) ||
- skb->protocol == htons(ETH_P_8021AD)) {
- if (!spec->vlan_okay)
- goto need_help;
- }
-
- /* We check whether the checksum refers to a transport layer checksum in
- * the outermost header or an encapsulated transport layer checksum that
- * corresponds to the inner headers of the skb. If the checksum is for
- * something else in the packet we need help.
- */
- if (skb_checksum_start_offset(skb) == skb_transport_offset(skb)) {
- /* Non-encapsulated checksum */
- protocol = eproto_to_ipproto(vlan_get_protocol(skb));
- nhdr = skb_network_header(skb);
- *csum_encapped = false;
- if (spec->no_not_encapped)
- goto need_help;
- } else if (skb->encapsulation && spec->encap_okay &&
- skb_checksum_start_offset(skb) ==
- skb_inner_transport_offset(skb)) {
- /* Encapsulated checksum */
- *csum_encapped = true;
- switch (skb->inner_protocol_type) {
- case ENCAP_TYPE_ETHER:
- protocol = eproto_to_ipproto(skb->inner_protocol);
- break;
- case ENCAP_TYPE_IPPROTO:
- protocol = skb->inner_protocol;
- break;
- }
- nhdr = skb_inner_network_header(skb);
- } else {
- goto need_help;
- }
-
- switch (protocol) {
- case IPPROTO_IP:
- if (!spec->ipv4_okay)
- goto need_help;
- iph = nhdr;
- ip_proto = iph->protocol;
- if (iph->ihl != 5 && !spec->ip_options_okay)
- goto need_help;
- break;
- case IPPROTO_IPV6:
- if (!spec->ipv6_okay)
- goto need_help;
- if (spec->no_encapped_ipv6 && *csum_encapped)
- goto need_help;
- ipv6 = nhdr;
- nhdr += sizeof(*ipv6);
- ip_proto = ipv6->nexthdr;
- break;
- default:
- goto need_help;
- }
-
-ip_proto_again:
- switch (ip_proto) {
- case IPPROTO_TCP:
- if (!spec->tcp_okay ||
- skb->csum_offset != offsetof(struct tcphdr, check))
- goto need_help;
- break;
- case IPPROTO_UDP:
- if (!spec->udp_okay ||
- skb->csum_offset != offsetof(struct udphdr, check))
- goto need_help;
- break;
- case IPPROTO_SCTP:
- if (!spec->sctp_okay ||
- skb->csum_offset != offsetof(struct sctphdr, checksum))
- goto cant_help;
- break;
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_DEST: {
- u8 *opthdr = nhdr;
-
- if (protocol != IPPROTO_IPV6 || !spec->ext_hdrs_okay)
- goto need_help;
-
- ip_proto = opthdr[0];
- nhdr += (opthdr[1] + 1) << 3;
-
- goto ip_proto_again;
- }
- default:
- goto need_help;
- }
-
- /* Passed the tests for offloading checksum */
- return true;
-
-need_help:
- if (csum_help && !skb_shinfo(skb)->gso_size)
- skb_checksum_help(skb);
-cant_help:
- return false;
-}
-EXPORT_SYMBOL(__skb_csum_offload_chk);
-
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
{
__be16 type = skb->protocol;
@@ -3216,8 +3196,14 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
rcu_read_lock();
dev_maps = rcu_dereference(dev->xps_maps);
if (dev_maps) {
- map = rcu_dereference(
- dev_maps->cpu_map[skb->sender_cpu - 1]);
+ unsigned int tci = skb->sender_cpu - 1;
+
+ if (dev->num_tc) {
+ tci *= dev->num_tc;
+ tci += netdev_get_prio_tc_map(dev, skb->priority);
+ }
+
+ map = rcu_dereference(dev_maps->cpu_map[tci]);
if (map) {
if (map->len == 1)
queue_index = map->queues[0];
@@ -3461,6 +3447,8 @@ EXPORT_SYMBOL(rps_cpu_mask);
struct static_key rps_needed __read_mostly;
EXPORT_SYMBOL(rps_needed);
+struct static_key rfs_needed __read_mostly;
+EXPORT_SYMBOL(rfs_needed);
static struct rps_dev_flow *
set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
@@ -4491,7 +4479,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
if (!(skb->dev->features & NETIF_F_GRO))
goto normal;
- if (skb_is_gso(skb) || skb_has_frag_list(skb) || skb->csum_bad)
+ if (skb->csum_bad)
goto normal;
gro_list_prepare(napi, skb);
@@ -4504,7 +4492,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
skb_set_network_header(skb, skb_gro_offset(skb));
skb_reset_mac_len(skb);
NAPI_GRO_CB(skb)->same_flow = 0;
- NAPI_GRO_CB(skb)->flush = 0;
+ NAPI_GRO_CB(skb)->flush = skb_is_gso(skb) || skb_has_frag_list(skb);
NAPI_GRO_CB(skb)->free = 0;
NAPI_GRO_CB(skb)->encap_mark = 0;
NAPI_GRO_CB(skb)->recursion_counter = 0;
@@ -4912,26 +4900,36 @@ void __napi_schedule_irqoff(struct napi_struct *n)
}
EXPORT_SYMBOL(__napi_schedule_irqoff);
-void __napi_complete(struct napi_struct *n)
+bool __napi_complete(struct napi_struct *n)
{
BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
+ /* Some drivers call us directly, instead of calling
+ * napi_complete_done().
+ */
+ if (unlikely(test_bit(NAPI_STATE_IN_BUSY_POLL, &n->state)))
+ return false;
+
list_del_init(&n->poll_list);
smp_mb__before_atomic();
clear_bit(NAPI_STATE_SCHED, &n->state);
+ return true;
}
EXPORT_SYMBOL(__napi_complete);
-void napi_complete_done(struct napi_struct *n, int work_done)
+bool napi_complete_done(struct napi_struct *n, int work_done)
{
unsigned long flags;
/*
- * don't let napi dequeue from the cpu poll list
- * just in case its running on a different cpu
+ * 1) Don't let napi dequeue from the cpu poll list
+ * just in case its running on a different cpu.
+ * 2) If we are busy polling, do nothing here, we have
+ * the guarantee we will be called later.
*/
- if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state)))
- return;
+ if (unlikely(n->state & (NAPIF_STATE_NPSVC |
+ NAPIF_STATE_IN_BUSY_POLL)))
+ return false;
if (n->gro_list) {
unsigned long timeout = 0;
@@ -4953,6 +4951,7 @@ void napi_complete_done(struct napi_struct *n, int work_done)
__napi_complete(n);
local_irq_restore(flags);
}
+ return true;
}
EXPORT_SYMBOL(napi_complete_done);
@@ -4970,13 +4969,41 @@ static struct napi_struct *napi_by_id(unsigned int napi_id)
}
#if defined(CONFIG_NET_RX_BUSY_POLL)
+
#define BUSY_POLL_BUDGET 8
+
+static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock)
+{
+ int rc;
+
+ clear_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state);
+
+ local_bh_disable();
+
+ /* All we really want here is to re-enable device interrupts.
+ * Ideally, a new ndo_busy_poll_stop() could avoid another round.
+ */
+ rc = napi->poll(napi, BUSY_POLL_BUDGET);
+ netpoll_poll_unlock(have_poll_lock);
+ if (rc == BUSY_POLL_BUDGET)
+ __napi_schedule(napi);
+ local_bh_enable();
+ if (local_softirq_pending())
+ do_softirq();
+}
+
bool sk_busy_loop(struct sock *sk, int nonblock)
{
unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0;
+ int (*napi_poll)(struct napi_struct *napi, int budget);
int (*busy_poll)(struct napi_struct *dev);
+ void *have_poll_lock = NULL;
struct napi_struct *napi;
- int rc = false;
+ int rc;
+
+restart:
+ rc = false;
+ napi_poll = NULL;
rcu_read_lock();
@@ -4987,24 +5014,33 @@ bool sk_busy_loop(struct sock *sk, int nonblock)
/* Note: ndo_busy_poll method is optional in linux-4.5 */
busy_poll = napi->dev->netdev_ops->ndo_busy_poll;
- do {
+ preempt_disable();
+ for (;;) {
rc = 0;
local_bh_disable();
if (busy_poll) {
rc = busy_poll(napi);
- } else if (napi_schedule_prep(napi)) {
- void *have = netpoll_poll_lock(napi);
-
- if (test_bit(NAPI_STATE_SCHED, &napi->state)) {
- rc = napi->poll(napi, BUSY_POLL_BUDGET);
- trace_napi_poll(napi, rc, BUSY_POLL_BUDGET);
- if (rc == BUSY_POLL_BUDGET) {
- napi_complete_done(napi, rc);
- napi_schedule(napi);
- }
- }
- netpoll_poll_unlock(have);
+ goto count;
+ }
+ if (!napi_poll) {
+ unsigned long val = READ_ONCE(napi->state);
+
+ /* If multiple threads are competing for this napi,
+ * we avoid dirtying napi->state as much as we can.
+ */
+ if (val & (NAPIF_STATE_DISABLE | NAPIF_STATE_SCHED |
+ NAPIF_STATE_IN_BUSY_POLL))
+ goto count;
+ if (cmpxchg(&napi->state, val,
+ val | NAPIF_STATE_IN_BUSY_POLL |
+ NAPIF_STATE_SCHED) != val)
+ goto count;
+ have_poll_lock = netpoll_poll_lock(napi);
+ napi_poll = napi->poll;
}
+ rc = napi_poll(napi, BUSY_POLL_BUDGET);
+ trace_napi_poll(napi, rc, BUSY_POLL_BUDGET);
+count:
if (rc > 0)
__NET_ADD_STATS(sock_net(sk),
LINUX_MIB_BUSYPOLLRXPACKETS, rc);
@@ -5013,10 +5049,26 @@ bool sk_busy_loop(struct sock *sk, int nonblock)
if (rc == LL_FLUSH_FAILED)
break; /* permanent failure */
- cpu_relax();
- } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
- !need_resched() && !busy_loop_timeout(end_time));
+ if (nonblock || !skb_queue_empty(&sk->sk_receive_queue) ||
+ busy_loop_timeout(end_time))
+ break;
+ if (unlikely(need_resched())) {
+ if (napi_poll)
+ busy_poll_stop(napi, have_poll_lock);
+ preempt_enable();
+ rcu_read_unlock();
+ cond_resched();
+ rc = !skb_queue_empty(&sk->sk_receive_queue);
+ if (rc || busy_loop_timeout(end_time))
+ return rc;
+ goto restart;
+ }
+ cpu_relax();
+ }
+ if (napi_poll)
+ busy_poll_stop(napi, have_poll_lock);
+ preempt_enable();
rc = !skb_queue_empty(&sk->sk_receive_queue);
out:
rcu_read_unlock();
@@ -5026,7 +5078,7 @@ EXPORT_SYMBOL(sk_busy_loop);
#endif /* CONFIG_NET_RX_BUSY_POLL */
-void napi_hash_add(struct napi_struct *napi)
+static void napi_hash_add(struct napi_struct *napi)
{
if (test_bit(NAPI_STATE_NO_BUSY_POLL, &napi->state) ||
test_and_set_bit(NAPI_STATE_HASHED, &napi->state))
@@ -5046,7 +5098,6 @@ void napi_hash_add(struct napi_struct *napi)
spin_unlock(&napi_hash_lock);
}
-EXPORT_SYMBOL_GPL(napi_hash_add);
/* Warning : caller is responsible to make sure rcu grace period
* is respected before freeing memory containing @napi
@@ -5094,7 +5145,6 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
list_add(&napi->dev_list, &dev->napi_list);
napi->dev = dev;
#ifdef CONFIG_NETPOLL
- spin_lock_init(&napi->poll_lock);
napi->poll_owner = -1;
#endif
set_bit(NAPI_STATE_SCHED, &napi->state);
@@ -5212,7 +5262,7 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
if (list_empty(&list)) {
if (!sd_has_rps_ipi_waiting(sd) && list_empty(&repoll))
- return;
+ goto out;
break;
}
@@ -5230,7 +5280,6 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
}
}
- __kfree_skb_flush();
local_irq_disable();
list_splice_tail_init(&sd->poll_list, &list);
@@ -5240,6 +5289,8 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
net_rps_action_and_irq_enable(sd);
+out:
+ __kfree_skb_flush();
}
struct netdev_adjacent {
@@ -5270,6 +5321,13 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
return NULL;
}
+static int __netdev_has_upper_dev(struct net_device *upper_dev, void *data)
+{
+ struct net_device *dev = data;
+
+ return upper_dev == dev;
+}
+
/**
* netdev_has_upper_dev - Check if device is linked to an upper device
* @dev: device
@@ -5284,11 +5342,30 @@ bool netdev_has_upper_dev(struct net_device *dev,
{
ASSERT_RTNL();
- return __netdev_find_adj(upper_dev, &dev->all_adj_list.upper);
+ return netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+ upper_dev);
}
EXPORT_SYMBOL(netdev_has_upper_dev);
/**
+ * netdev_has_upper_dev_all - Check if device is linked to an upper device
+ * @dev: device
+ * @upper_dev: upper device to check
+ *
+ * Find out if a device is linked to specified upper device and return true
+ * in case it is. Note that this checks the entire upper device chain.
+ * The caller must hold rcu lock.
+ */
+
+bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ return !!netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+ upper_dev);
+}
+EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu);
+
+/**
* netdev_has_any_upper_dev - Check if device is linked to some device
* @dev: device
*
@@ -5299,7 +5376,7 @@ static bool netdev_has_any_upper_dev(struct net_device *dev)
{
ASSERT_RTNL();
- return !list_empty(&dev->all_adj_list.upper);
+ return !list_empty(&dev->adj_list.upper);
}
/**
@@ -5326,6 +5403,20 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
+/**
+ * netdev_has_any_lower_dev - Check if device is linked to some device
+ * @dev: device
+ *
+ * Find out if a device is linked to a lower device and return true in case
+ * it is. The caller must hold the RTNL lock.
+ */
+static bool netdev_has_any_lower_dev(struct net_device *dev)
+{
+ ASSERT_RTNL();
+
+ return !list_empty(&dev->adj_list.lower);
+}
+
void *netdev_adjacent_get_private(struct list_head *adj_list)
{
struct netdev_adjacent *adj;
@@ -5362,16 +5453,8 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
-/**
- * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next device from the dev's upper list, starting from iter
- * position. The caller must hold RCU read lock.
- */
-struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
- struct list_head **iter)
+static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *upper;
@@ -5379,14 +5462,41 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
- if (&upper->list == &dev->all_adj_list.upper)
+ if (&upper->list == &dev->adj_list.upper)
return NULL;
*iter = &upper->list;
return upper->dev;
}
-EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
+
+int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *udev;
+ struct list_head *iter;
+ int ret;
+
+ for (iter = &dev->adj_list.upper,
+ udev = netdev_next_upper_dev_rcu(dev, &iter);
+ udev;
+ udev = netdev_next_upper_dev_rcu(dev, &iter)) {
+ /* first is the upper device itself */
+ ret = fn(udev, data);
+ if (ret)
+ return ret;
+
+ /* then look at all of its upper devices */
+ ret = netdev_walk_all_upper_dev_rcu(udev, fn, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
/**
* netdev_lower_get_next_private - Get the next ->private from the
@@ -5469,55 +5579,90 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
}
EXPORT_SYMBOL(netdev_lower_get_next);
-/**
- * netdev_all_lower_get_next - Get the next device from all lower neighbour list
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent from the dev's all lower neighbour
- * list, starting from iter position. The caller must hold RTNL lock or
- * its own locking that guarantees that the neighbour all lower
- * list will remain unchanged.
- */
-struct net_device *netdev_all_lower_get_next(struct net_device *dev, struct list_head **iter)
+static struct net_device *netdev_next_lower_dev(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *lower;
- lower = list_entry(*iter, struct netdev_adjacent, list);
+ lower = list_entry((*iter)->next, struct netdev_adjacent, list);
- if (&lower->list == &dev->all_adj_list.lower)
+ if (&lower->list == &dev->adj_list.lower)
return NULL;
- *iter = lower->list.next;
+ *iter = &lower->list;
return lower->dev;
}
-EXPORT_SYMBOL(netdev_all_lower_get_next);
-/**
- * netdev_all_lower_get_next_rcu - Get the next device from all
- * lower neighbour list, RCU variant
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent from the dev's all lower neighbour
- * list, starting from iter position. The caller must hold RCU read lock.
- */
-struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
- struct list_head **iter)
+int netdev_walk_all_lower_dev(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *ldev;
+ struct list_head *iter;
+ int ret;
+
+ for (iter = &dev->adj_list.lower,
+ ldev = netdev_next_lower_dev(dev, &iter);
+ ldev;
+ ldev = netdev_next_lower_dev(dev, &iter)) {
+ /* first is the lower device itself */
+ ret = fn(ldev, data);
+ if (ret)
+ return ret;
+
+ /* then look at all of its lower devices */
+ ret = netdev_walk_all_lower_dev(ldev, fn, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev);
+
+static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *lower;
lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
-
- if (&lower->list == &dev->all_adj_list.lower)
+ if (&lower->list == &dev->adj_list.lower)
return NULL;
*iter = &lower->list;
return lower->dev;
}
-EXPORT_SYMBOL(netdev_all_lower_get_next_rcu);
+
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *ldev;
+ struct list_head *iter;
+ int ret;
+
+ for (iter = &dev->adj_list.lower,
+ ldev = netdev_next_lower_dev_rcu(dev, &iter);
+ ldev;
+ ldev = netdev_next_lower_dev_rcu(dev, &iter)) {
+ /* first is the lower device itself */
+ ret = fn(ldev, data);
+ if (ret)
+ return ret;
+
+ /* then look at all of its lower devices */
+ ret = netdev_walk_all_lower_dev_rcu(ldev, fn, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev_rcu);
/**
* netdev_lower_get_first_private_rcu - Get the first ->private from the
@@ -5590,7 +5735,6 @@ static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev,
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
- u16 ref_nr,
struct list_head *dev_list,
void *private, bool master)
{
@@ -5600,7 +5744,10 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj = __netdev_find_adj(adj_dev, dev_list);
if (adj) {
- adj->ref_nr += ref_nr;
+ adj->ref_nr += 1;
+ pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d\n",
+ dev->name, adj_dev->name, adj->ref_nr);
+
return 0;
}
@@ -5610,12 +5757,12 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
- adj->ref_nr = ref_nr;
+ adj->ref_nr = 1;
adj->private = private;
dev_hold(adj_dev);
- pr_debug("dev_hold for %s, because of link added from %s to %s\n",
- adj_dev->name, dev->name, adj_dev->name);
+ pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n",
+ dev->name, adj_dev->name, adj->ref_nr, adj_dev->name);
if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) {
ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list);
@@ -5654,17 +5801,22 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
{
struct netdev_adjacent *adj;
+ pr_debug("Remove adjacency: dev %s adj_dev %s ref_nr %d\n",
+ dev->name, adj_dev->name, ref_nr);
+
adj = __netdev_find_adj(adj_dev, dev_list);
if (!adj) {
- pr_err("tried to remove device %s from %s\n",
+ pr_err("Adjacency does not exist for device %s from %s\n",
dev->name, adj_dev->name);
- BUG();
+ WARN_ON(1);
+ return;
}
if (adj->ref_nr > ref_nr) {
- pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name,
- ref_nr, adj->ref_nr-ref_nr);
+ pr_debug("adjacency: %s to %s ref_nr - %d = %d\n",
+ dev->name, adj_dev->name, ref_nr,
+ adj->ref_nr - ref_nr);
adj->ref_nr -= ref_nr;
return;
}
@@ -5676,7 +5828,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
list_del_rcu(&adj->list);
- pr_debug("dev_put for %s, because link removed from %s to %s\n",
+ pr_debug("adjacency: dev_put for %s, because link removed from %s to %s\n",
adj_dev->name, dev->name, adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
@@ -5684,38 +5836,27 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
static int __netdev_adjacent_dev_link_lists(struct net_device *dev,
struct net_device *upper_dev,
- u16 ref_nr,
struct list_head *up_list,
struct list_head *down_list,
void *private, bool master)
{
int ret;
- ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list,
+ ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list,
private, master);
if (ret)
return ret;
- ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list,
+ ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list,
private, false);
if (ret) {
- __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list);
+ __netdev_adjacent_dev_remove(dev, upper_dev, 1, up_list);
return ret;
}
return 0;
}
-static int __netdev_adjacent_dev_link(struct net_device *dev,
- struct net_device *upper_dev,
- u16 ref_nr)
-{
- return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr,
- &dev->all_adj_list.upper,
- &upper_dev->all_adj_list.lower,
- NULL, false);
-}
-
static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
struct net_device *upper_dev,
u16 ref_nr,
@@ -5726,40 +5867,19 @@ static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
__netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list);
}
-static void __netdev_adjacent_dev_unlink(struct net_device *dev,
- struct net_device *upper_dev,
- u16 ref_nr)
-{
- __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr,
- &dev->all_adj_list.upper,
- &upper_dev->all_adj_list.lower);
-}
-
static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
struct net_device *upper_dev,
void *private, bool master)
{
- int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1);
-
- if (ret)
- return ret;
-
- ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1,
- &dev->adj_list.upper,
- &upper_dev->adj_list.lower,
- private, master);
- if (ret) {
- __netdev_adjacent_dev_unlink(dev, upper_dev, 1);
- return ret;
- }
-
- return 0;
+ return __netdev_adjacent_dev_link_lists(dev, upper_dev,
+ &dev->adj_list.upper,
+ &upper_dev->adj_list.lower,
+ private, master);
}
static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
struct net_device *upper_dev)
{
- __netdev_adjacent_dev_unlink(dev, upper_dev, 1);
__netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1,
&dev->adj_list.upper,
&upper_dev->adj_list.lower);
@@ -5770,7 +5890,6 @@ static int __netdev_upper_dev_link(struct net_device *dev,
void *upper_priv, void *upper_info)
{
struct netdev_notifier_changeupper_info changeupper_info;
- struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0;
ASSERT_RTNL();
@@ -5779,10 +5898,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (__netdev_find_adj(dev, &upper_dev->all_adj_list.upper))
+ if (netdev_has_upper_dev(upper_dev, dev))
return -EBUSY;
- if (__netdev_find_adj(upper_dev, &dev->adj_list.upper))
+ if (netdev_has_upper_dev(dev, upper_dev))
return -EEXIST;
if (master && netdev_master_upper_dev_get(dev))
@@ -5804,80 +5923,15 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (ret)
return ret;
- /* Now that we linked these devs, make all the upper_dev's
- * all_adj_list.upper visible to every dev's all_adj_list.lower an
- * versa, and don't forget the devices itself. All of these
- * links are non-neighbours.
- */
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
- pr_debug("Interlinking %s with %s, non-neighbour\n",
- i->dev->name, j->dev->name);
- ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr);
- if (ret)
- goto rollback_mesh;
- }
- }
-
- /* add dev to every upper_dev's upper device */
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
- pr_debug("linking %s's upper device %s with %s\n",
- upper_dev->name, i->dev->name, dev->name);
- ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr);
- if (ret)
- goto rollback_upper_mesh;
- }
-
- /* add upper_dev to every dev's lower device */
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- pr_debug("linking %s's lower device %s with %s\n", dev->name,
- i->dev->name, upper_dev->name);
- ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr);
- if (ret)
- goto rollback_lower_mesh;
- }
-
ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
&changeupper_info.info);
ret = notifier_to_errno(ret);
if (ret)
- goto rollback_lower_mesh;
+ goto rollback;
return 0;
-rollback_lower_mesh:
- to_i = i;
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- if (i == to_i)
- break;
- __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
- }
-
- i = NULL;
-
-rollback_upper_mesh:
- to_i = i;
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
- if (i == to_i)
- break;
- __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
- }
-
- i = j = NULL;
-
-rollback_mesh:
- to_i = i;
- to_j = j;
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
- if (i == to_i && j == to_j)
- break;
- __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
- }
- if (i == to_i)
- break;
- }
-
+rollback:
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
return ret;
@@ -5934,7 +5988,6 @@ void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
struct netdev_notifier_changeupper_info changeupper_info;
- struct netdev_adjacent *i, *j;
ASSERT_RTNL();
changeupper_info.upper_dev = upper_dev;
@@ -5946,23 +5999,6 @@ void netdev_upper_dev_unlink(struct net_device *dev,
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
- /* Here is the tricky part. We must remove all dev's lower
- * devices from all upper_dev's upper devices and vice
- * versa, to maintain the graph relationship.
- */
- list_for_each_entry(i, &dev->all_adj_list.lower, list)
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
- __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
-
- /* remove also the devices itself from lower/upper device
- * list
- */
- list_for_each_entry(i, &dev->all_adj_list.lower, list)
- __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
-
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
- __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
-
call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
&changeupper_info.info);
}
@@ -6500,9 +6536,18 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
if (new_mtu == dev->mtu)
return 0;
- /* MTU must be positive. */
- if (new_mtu < 0)
+ /* MTU must be positive, and in range */
+ if (new_mtu < 0 || new_mtu < dev->min_mtu) {
+ net_err_ratelimited("%s: Invalid MTU %d requested, hw min %d\n",
+ dev->name, new_mtu, dev->min_mtu);
return -EINVAL;
+ }
+
+ if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) {
+ net_err_ratelimited("%s: Invalid MTU %d requested, hw max %d\n",
+ dev->name, new_mtu, dev->max_mtu);
+ return -EINVAL;
+ }
if (!netif_device_present(dev))
return -ENODEV;
@@ -6649,26 +6694,42 @@ EXPORT_SYMBOL(dev_change_proto_down);
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
* @dev: device
* @fd: new program fd or negative value to clear
+ * @flags: xdp-related flags
*
* Set or clear a bpf program for a device
*/
-int dev_change_xdp_fd(struct net_device *dev, int fd)
+int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
struct bpf_prog *prog = NULL;
- struct netdev_xdp xdp = {};
+ struct netdev_xdp xdp;
int err;
+ ASSERT_RTNL();
+
if (!ops->ndo_xdp)
return -EOPNOTSUPP;
if (fd >= 0) {
+ if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) {
+ memset(&xdp, 0, sizeof(xdp));
+ xdp.command = XDP_QUERY_PROG;
+
+ err = ops->ndo_xdp(dev, &xdp);
+ if (err < 0)
+ return err;
+ if (xdp.prog_attached)
+ return -EBUSY;
+ }
+
prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
if (IS_ERR(prog))
return PTR_ERR(prog);
}
+ memset(&xdp, 0, sizeof(xdp));
xdp.command = XDP_SETUP_PROG;
xdp.prog = prog;
+
err = ops->ndo_xdp(dev, &xdp);
if (err < 0 && prog)
bpf_prog_put(prog);
@@ -6777,6 +6838,7 @@ static void rollback_registered_many(struct list_head *head)
/* Notifier chain MUST detach us all upper devices. */
WARN_ON(netdev_has_any_upper_dev(dev));
+ WARN_ON(netdev_has_any_lower_dev(dev));
/* Remove entries from kobject tree */
netdev_unregister_kobject(dev);
@@ -7655,8 +7717,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->link_watch_list);
INIT_LIST_HEAD(&dev->adj_list.upper);
INIT_LIST_HEAD(&dev->adj_list.lower);
- INIT_LIST_HEAD(&dev->all_adj_list.upper);
- INIT_LIST_HEAD(&dev->all_adj_list.lower);
INIT_LIST_HEAD(&dev->ptype_all);
INIT_LIST_HEAD(&dev->ptype_specific);
#ifdef CONFIG_NET_SCHED
@@ -7667,7 +7727,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
if (!dev->tx_queue_len) {
dev->priv_flags |= IFF_NO_QUEUE;
- dev->tx_queue_len = 1;
+ dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
}
dev->num_tx_queues = txqs;
@@ -7948,18 +8008,13 @@ out:
}
EXPORT_SYMBOL_GPL(dev_change_net_namespace);
-static int dev_cpu_callback(struct notifier_block *nfb,
- unsigned long action,
- void *ocpu)
+static int dev_cpu_dead(unsigned int oldcpu)
{
struct sk_buff **list_skb;
struct sk_buff *skb;
- unsigned int cpu, oldcpu = (unsigned long)ocpu;
+ unsigned int cpu;
struct softnet_data *sd, *oldsd;
- if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
- return NOTIFY_OK;
-
local_irq_disable();
cpu = smp_processor_id();
sd = &per_cpu(softnet_data, cpu);
@@ -8009,10 +8064,9 @@ static int dev_cpu_callback(struct notifier_block *nfb,
input_queue_head_incr(oldsd);
}
- return NOTIFY_OK;
+ return 0;
}
-
/**
* netdev_increment_features - increment feature set by one
* @all: current feature set
@@ -8346,7 +8400,9 @@ static int __init net_dev_init(void)
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
- hotcpu_notifier(dev_cpu_callback, 0);
+ rc = cpuhp_setup_state_nocalls(CPUHP_NET_DEV_DEAD, "net/dev:dead",
+ NULL, dev_cpu_dead);
+ WARN_ON(rc < 0);
dst_subsys_init();
rc = 0;
out:
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 1b5063088f1a..2b5bf9efa720 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -341,15 +341,7 @@ static void devlink_nl_post_doit(const struct genl_ops *ops,
mutex_unlock(&devlink_mutex);
}
-static struct genl_family devlink_nl_family = {
- .id = GENL_ID_GENERATE,
- .name = DEVLINK_GENL_NAME,
- .version = DEVLINK_GENL_VERSION,
- .maxattr = DEVLINK_ATTR_MAX,
- .netnsok = true,
- .pre_doit = devlink_nl_pre_doit,
- .post_doit = devlink_nl_post_doit,
-};
+static struct genl_family devlink_nl_family;
enum devlink_multicast_groups {
DEVLINK_MCGRP_CONFIG,
@@ -608,6 +600,8 @@ static int devlink_port_type_set(struct devlink *devlink,
if (devlink->ops && devlink->ops->port_type_set) {
if (port_type == DEVLINK_PORT_TYPE_NOTSET)
return -EINVAL;
+ if (port_type == devlink_port->type)
+ return 0;
err = devlink->ops->port_type_set(devlink_port, port_type);
if (err)
return err;
@@ -1400,26 +1394,45 @@ static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
static int devlink_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
enum devlink_command cmd, u32 portid,
- u32 seq, int flags, u16 mode)
+ u32 seq, int flags)
{
+ const struct devlink_ops *ops = devlink->ops;
void *hdr;
+ int err = 0;
+ u16 mode;
+ u8 inline_mode;
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
if (!hdr)
return -EMSGSIZE;
- if (devlink_nl_put_handle(msg, devlink))
- goto nla_put_failure;
+ err = devlink_nl_put_handle(msg, devlink);
+ if (err)
+ goto out;
- if (nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode))
- goto nla_put_failure;
+ err = ops->eswitch_mode_get(devlink, &mode);
+ if (err)
+ goto out;
+ err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
+ if (err)
+ goto out;
+
+ if (ops->eswitch_inline_mode_get) {
+ err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
+ if (err)
+ goto out;
+ err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
+ inline_mode);
+ if (err)
+ goto out;
+ }
genlmsg_end(msg, hdr);
return 0;
-nla_put_failure:
+out:
genlmsg_cancel(msg, hdr);
- return -EMSGSIZE;
+ return err;
}
static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb,
@@ -1428,22 +1441,17 @@ static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb,
struct devlink *devlink = info->user_ptr[0];
const struct devlink_ops *ops = devlink->ops;
struct sk_buff *msg;
- u16 mode;
int err;
if (!ops || !ops->eswitch_mode_get)
return -EOPNOTSUPP;
- err = ops->eswitch_mode_get(devlink, &mode);
- if (err)
- return err;
-
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
err = devlink_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_MODE_GET,
- info->snd_portid, info->snd_seq, 0, mode);
+ info->snd_portid, info->snd_seq, 0);
if (err) {
nlmsg_free(msg);
@@ -1459,15 +1467,32 @@ static int devlink_nl_cmd_eswitch_mode_set_doit(struct sk_buff *skb,
struct devlink *devlink = info->user_ptr[0];
const struct devlink_ops *ops = devlink->ops;
u16 mode;
+ u8 inline_mode;
+ int err = 0;
- if (!info->attrs[DEVLINK_ATTR_ESWITCH_MODE])
- return -EINVAL;
+ if (!ops)
+ return -EOPNOTSUPP;
- mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
+ if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
+ if (!ops->eswitch_mode_set)
+ return -EOPNOTSUPP;
+ mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
+ err = ops->eswitch_mode_set(devlink, mode);
+ if (err)
+ return err;
+ }
- if (ops && ops->eswitch_mode_set)
- return ops->eswitch_mode_set(devlink, mode);
- return -EOPNOTSUPP;
+ if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
+ if (!ops->eswitch_inline_mode_set)
+ return -EOPNOTSUPP;
+ inline_mode = nla_get_u8(
+ info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
+ err = ops->eswitch_inline_mode_set(devlink, inline_mode);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
@@ -1484,6 +1509,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
[DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
[DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
+ [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
};
static const struct genl_ops devlink_nl_ops[] = {
@@ -1618,6 +1644,20 @@ static const struct genl_ops devlink_nl_ops[] = {
},
};
+static struct genl_family devlink_nl_family __ro_after_init = {
+ .name = DEVLINK_GENL_NAME,
+ .version = DEVLINK_GENL_VERSION,
+ .maxattr = DEVLINK_ATTR_MAX,
+ .netnsok = true,
+ .pre_doit = devlink_nl_pre_doit,
+ .post_doit = devlink_nl_post_doit,
+ .module = THIS_MODULE,
+ .ops = devlink_nl_ops,
+ .n_ops = ARRAY_SIZE(devlink_nl_ops),
+ .mcgrps = devlink_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
+};
+
/**
* devlink_alloc - Allocate new devlink instance resources
*
@@ -1840,9 +1880,7 @@ EXPORT_SYMBOL_GPL(devlink_sb_unregister);
static int __init devlink_module_init(void)
{
- return genl_register_family_with_ops_groups(&devlink_nl_family,
- devlink_nl_ops,
- devlink_nl_mcgrps);
+ return genl_register_family(&devlink_nl_family);
}
static void __exit devlink_module_exit(void)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 72cfb0c61125..8e0c0635ee97 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -59,12 +59,7 @@ struct dm_hw_stat_delta {
unsigned long last_drop_val;
};
-static struct genl_family net_drop_monitor_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = "NET_DM",
- .version = 2,
-};
+static struct genl_family net_drop_monitor_family;
static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
@@ -351,6 +346,17 @@ static const struct genl_ops dropmon_ops[] = {
},
};
+static struct genl_family net_drop_monitor_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = "NET_DM",
+ .version = 2,
+ .module = THIS_MODULE,
+ .ops = dropmon_ops,
+ .n_ops = ARRAY_SIZE(dropmon_ops),
+ .mcgrps = dropmon_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(dropmon_mcgrps),
+};
+
static struct notifier_block dropmon_net_notifier = {
.notifier_call = dropmon_net_event
};
@@ -367,8 +373,7 @@ static int __init init_net_drop_monitor(void)
return -ENOSPC;
}
- rc = genl_register_family_with_ops_groups(&net_drop_monitor_family,
- dropmon_ops, dropmon_mcgrps);
+ rc = genl_register_family(&net_drop_monitor_family);
if (rc) {
pr_err("Could not create drop monitor netlink family\n");
return rc;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 047a1752ece1..e23766c7e3ba 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -119,6 +119,12 @@ tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
[ETHTOOL_TX_COPYBREAK] = "tx-copybreak",
};
+static const char
+phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
+ [ETHTOOL_ID_UNSPEC] = "Unspec",
+ [ETHTOOL_PHY_DOWNSHIFT] = "phy-downshift",
+};
+
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
{
struct ethtool_gfeatures cmd = {
@@ -227,6 +233,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
if (sset == ETH_SS_TUNABLES)
return ARRAY_SIZE(tunable_strings);
+ if (sset == ETH_SS_PHY_TUNABLES)
+ return ARRAY_SIZE(phy_tunable_strings);
+
if (sset == ETH_SS_PHY_STATS) {
if (dev->phydev)
return phy_get_sset_count(dev->phydev);
@@ -253,6 +262,8 @@ static void __ethtool_get_strings(struct net_device *dev,
sizeof(rss_hash_func_strings));
else if (stringset == ETH_SS_TUNABLES)
memcpy(data, tunable_strings, sizeof(tunable_strings));
+ else if (stringset == ETH_SS_PHY_TUNABLES)
+ memcpy(data, phy_tunable_strings, sizeof(phy_tunable_strings));
else if (stringset == ETH_SS_PHY_STATS) {
struct phy_device *phydev = dev->phydev;
@@ -2422,6 +2433,85 @@ static int ethtool_set_per_queue(struct net_device *dev, void __user *useraddr)
};
}
+static int ethtool_phy_tunable_valid(const struct ethtool_tunable *tuna)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_DOWNSHIFT:
+ if (tuna->len != sizeof(u8) ||
+ tuna->type_id != ETHTOOL_TUNABLE_U8)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_phy_tunable(struct net_device *dev, void __user *useraddr)
+{
+ int ret;
+ struct ethtool_tunable tuna;
+ struct phy_device *phydev = dev->phydev;
+ void *data;
+
+ if (!(phydev && phydev->drv && phydev->drv->get_tunable))
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
+ return -EFAULT;
+ ret = ethtool_phy_tunable_valid(&tuna);
+ if (ret)
+ return ret;
+ data = kmalloc(tuna.len, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+ mutex_lock(&phydev->lock);
+ ret = phydev->drv->get_tunable(phydev, &tuna, data);
+ mutex_unlock(&phydev->lock);
+ if (ret)
+ goto out;
+ useraddr += sizeof(tuna);
+ ret = -EFAULT;
+ if (copy_to_user(useraddr, data, tuna.len))
+ goto out;
+ ret = 0;
+
+out:
+ kfree(data);
+ return ret;
+}
+
+static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
+{
+ int ret;
+ struct ethtool_tunable tuna;
+ struct phy_device *phydev = dev->phydev;
+ void *data;
+
+ if (!(phydev && phydev->drv && phydev->drv->set_tunable))
+ return -EOPNOTSUPP;
+ if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
+ return -EFAULT;
+ ret = ethtool_phy_tunable_valid(&tuna);
+ if (ret)
+ return ret;
+ data = kmalloc(tuna.len, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+ useraddr += sizeof(tuna);
+ ret = -EFAULT;
+ if (copy_from_user(data, useraddr, tuna.len))
+ goto out;
+ mutex_lock(&phydev->lock);
+ ret = phydev->drv->set_tunable(phydev, &tuna, data);
+ mutex_unlock(&phydev->lock);
+
+out:
+ kfree(data);
+ return ret;
+}
+
/* The main entry point in this file. Called from net/core/dev_ioctl.c */
int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -2479,6 +2569,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_GET_TS_INFO:
case ETHTOOL_GEEE:
case ETHTOOL_GTUNABLE:
+ case ETHTOOL_PHY_GTUNABLE:
case ETHTOOL_GLINKSETTINGS:
break;
default:
@@ -2685,6 +2776,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SLINKSETTINGS:
rc = ethtool_set_link_ksettings(dev, useraddr);
break;
+ case ETHTOOL_PHY_GTUNABLE:
+ rc = get_phy_tunable(dev, useraddr);
+ break;
+ case ETHTOOL_PHY_STUNABLE:
+ rc = set_phy_tunable(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index be4629c344a6..b6791d94841d 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -18,6 +18,11 @@
#include <net/fib_rules.h>
#include <net/ip_tunnels.h>
+static const struct fib_kuid_range fib_kuid_range_unset = {
+ KUIDT_INIT(0),
+ KUIDT_INIT(~0),
+};
+
int fib_default_rule_add(struct fib_rules_ops *ops,
u32 pref, u32 table, u32 flags)
{
@@ -33,6 +38,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
r->table = table;
r->flags = flags;
r->fr_net = ops->fro_net;
+ r->uid_range = fib_kuid_range_unset;
r->suppress_prefixlen = -1;
r->suppress_ifgroup = -1;
@@ -172,6 +178,34 @@ void fib_rules_unregister(struct fib_rules_ops *ops)
}
EXPORT_SYMBOL_GPL(fib_rules_unregister);
+static int uid_range_set(struct fib_kuid_range *range)
+{
+ return uid_valid(range->start) && uid_valid(range->end);
+}
+
+static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb)
+{
+ struct fib_rule_uid_range *in;
+ struct fib_kuid_range out;
+
+ in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]);
+
+ out.start = make_kuid(current_user_ns(), in->start);
+ out.end = make_kuid(current_user_ns(), in->end);
+
+ return out;
+}
+
+static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
+{
+ struct fib_rule_uid_range out = {
+ from_kuid_munged(current_user_ns(), range->start),
+ from_kuid_munged(current_user_ns(), range->end)
+ };
+
+ return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
+}
+
static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
struct flowi *fl, int flags,
struct fib_lookup_arg *arg)
@@ -193,6 +227,10 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
if (rule->l3mdev && !l3mdev_fib_rule_match(rule->fr_net, fl, arg))
goto out;
+ if (uid_lt(fl->flowi_uid, rule->uid_range.start) ||
+ uid_gt(fl->flowi_uid, rule->uid_range.end))
+ goto out;
+
ret = ops->match(rule, fl, flags);
out:
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
@@ -305,6 +343,10 @@ static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh,
if (r->l3mdev != rule->l3mdev)
continue;
+ if (!uid_eq(r->uid_range.start, rule->uid_range.start) ||
+ !uid_eq(r->uid_range.end, rule->uid_range.end))
+ continue;
+
if (!ops->compare(r, frh, tb))
continue;
return 1;
@@ -429,6 +471,21 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh)
if (rule->l3mdev && rule->table)
goto errout_free;
+ if (tb[FRA_UID_RANGE]) {
+ if (current_user_ns() != net->user_ns) {
+ err = -EPERM;
+ goto errout_free;
+ }
+
+ rule->uid_range = nla_get_kuid_range(tb);
+
+ if (!uid_range_set(&rule->uid_range) ||
+ !uid_lte(rule->uid_range.start, rule->uid_range.end))
+ goto errout_free;
+ } else {
+ rule->uid_range = fib_kuid_range_unset;
+ }
+
if ((nlh->nlmsg_flags & NLM_F_EXCL) &&
rule_exists(ops, frh, tb, rule)) {
err = -EEXIST;
@@ -497,6 +554,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
struct fib_rules_ops *ops = NULL;
struct fib_rule *rule, *tmp;
struct nlattr *tb[FRA_MAX+1];
+ struct fib_kuid_range range;
int err = -EINVAL;
if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
@@ -516,6 +574,14 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err < 0)
goto errout;
+ if (tb[FRA_UID_RANGE]) {
+ range = nla_get_kuid_range(tb);
+ if (!uid_range_set(&range))
+ goto errout;
+ } else {
+ range = fib_kuid_range_unset;
+ }
+
list_for_each_entry(rule, &ops->rules_list, list) {
if (frh->action && (frh->action != rule->action))
continue;
@@ -552,6 +618,11 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
(rule->l3mdev != nla_get_u8(tb[FRA_L3MDEV])))
continue;
+ if (uid_range_set(&range) &&
+ (!uid_eq(rule->uid_range.start, range.start) ||
+ !uid_eq(rule->uid_range.end, range.end)))
+ continue;
+
if (!ops->compare(rule, frh, tb))
continue;
@@ -619,7 +690,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
+ nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
+ nla_total_size(4) /* FRA_FWMARK */
+ nla_total_size(4) /* FRA_FWMASK */
- + nla_total_size_64bit(8); /* FRA_TUN_ID */
+ + nla_total_size_64bit(8) /* FRA_TUN_ID */
+ + nla_total_size(sizeof(struct fib_kuid_range));
if (ops->nlmsg_payload)
payload += ops->nlmsg_payload(rule);
@@ -679,7 +751,9 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
(rule->tun_id &&
nla_put_be64(skb, FRA_TUN_ID, rule->tun_id, FRA_PAD)) ||
(rule->l3mdev &&
- nla_put_u8(skb, FRA_L3MDEV, rule->l3mdev)))
+ nla_put_u8(skb, FRA_L3MDEV, rule->l3mdev)) ||
+ (uid_range_set(&rule->uid_range) &&
+ nla_put_uid_range(skb, &rule->uid_range)))
goto nla_put_failure;
if (rule->suppress_ifgroup != -1) {
diff --git a/net/core/filter.c b/net/core/filter.c
index b391209838ef..b1461708a977 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -30,6 +30,7 @@
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_packet.h>
+#include <linux/if_arp.h>
#include <linux/gfp.h>
#include <net/ip.h>
#include <net/protocol.h>
@@ -78,6 +79,10 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
return -ENOMEM;
+ err = BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb);
+ if (err)
+ return err;
+
err = security_sock_rcv_skb(sk, skb);
if (err)
return err;
@@ -1684,6 +1689,12 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev,
u32 flags)
{
+ /* Verify that a link layer header is carried */
+ if (unlikely(skb->mac_header >= skb->network_header)) {
+ kfree_skb(skb);
+ return -ERANGE;
+ }
+
bpf_push_mac_rcsum(skb);
return flags & BPF_F_INGRESS ?
__bpf_rx_skb(dev, skb) : __bpf_tx_skb(dev, skb);
@@ -1692,17 +1703,10 @@ static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev,
static int __bpf_redirect(struct sk_buff *skb, struct net_device *dev,
u32 flags)
{
- switch (dev->type) {
- case ARPHRD_TUNNEL:
- case ARPHRD_TUNNEL6:
- case ARPHRD_SIT:
- case ARPHRD_IPGRE:
- case ARPHRD_VOID:
- case ARPHRD_NONE:
- return __bpf_redirect_no_mac(skb, dev, flags);
- default:
+ if (dev_is_mac_header_xmit(dev))
return __bpf_redirect_common(skb, dev, flags);
- }
+ else
+ return __bpf_redirect_no_mac(skb, dev, flags);
}
BPF_CALL_3(bpf_clone_redirect, struct sk_buff *, skb, u32, ifindex, u64, flags)
@@ -2190,16 +2194,79 @@ static const struct bpf_func_proto bpf_skb_change_tail_proto = {
.arg3_type = ARG_ANYTHING,
};
-bool bpf_helper_changes_skb_data(void *func)
+BPF_CALL_3(bpf_skb_change_head, struct sk_buff *, skb, u32, head_room,
+ u64, flags)
+{
+ u32 max_len = __bpf_skb_max_len(skb);
+ u32 new_len = skb->len + head_room;
+ int ret;
+
+ if (unlikely(flags || (!skb_is_gso(skb) && new_len > max_len) ||
+ new_len < skb->len))
+ return -EINVAL;
+
+ ret = skb_cow(skb, head_room);
+ if (likely(!ret)) {
+ /* Idea for this helper is that we currently only
+ * allow to expand on mac header. This means that
+ * skb->protocol network header, etc, stay as is.
+ * Compared to bpf_skb_change_tail(), we're more
+ * flexible due to not needing to linearize or
+ * reset GSO. Intention for this helper is to be
+ * used by an L3 skb that needs to push mac header
+ * for redirection into L2 device.
+ */
+ __skb_push(skb, head_room);
+ memset(skb->data, 0, head_room);
+ skb_reset_mac_header(skb);
+ }
+
+ bpf_compute_data_end(skb);
+ return 0;
+}
+
+static const struct bpf_func_proto bpf_skb_change_head_proto = {
+ .func = bpf_skb_change_head,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+};
+
+BPF_CALL_2(bpf_xdp_adjust_head, struct xdp_buff *, xdp, int, offset)
+{
+ void *data = xdp->data + offset;
+
+ if (unlikely(data < xdp->data_hard_start ||
+ data > xdp->data_end - ETH_HLEN))
+ return -EINVAL;
+
+ xdp->data = data;
+
+ return 0;
+}
+
+static const struct bpf_func_proto bpf_xdp_adjust_head_proto = {
+ .func = bpf_xdp_adjust_head,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+};
+
+bool bpf_helper_changes_pkt_data(void *func)
{
if (func == bpf_skb_vlan_push ||
func == bpf_skb_vlan_pop ||
func == bpf_skb_store_bytes ||
func == bpf_skb_change_proto ||
+ func == bpf_skb_change_head ||
func == bpf_skb_change_tail ||
func == bpf_skb_pull_data ||
func == bpf_l3_csum_replace ||
- func == bpf_l4_csum_replace)
+ func == bpf_l4_csum_replace ||
+ func == bpf_xdp_adjust_head)
return true;
return false;
@@ -2544,6 +2611,8 @@ sk_filter_func_proto(enum bpf_func_id func_id)
return &bpf_get_prandom_u32_proto;
case BPF_FUNC_get_smp_processor_id:
return &bpf_get_raw_smp_processor_id_proto;
+ case BPF_FUNC_get_numa_node_id:
+ return &bpf_get_numa_node_id_proto;
case BPF_FUNC_tail_call:
return &bpf_tail_call_proto;
case BPF_FUNC_ktime_get_ns:
@@ -2623,12 +2692,87 @@ xdp_func_proto(enum bpf_func_id func_id)
return &bpf_xdp_event_output_proto;
case BPF_FUNC_get_smp_processor_id:
return &bpf_get_smp_processor_id_proto;
+ case BPF_FUNC_xdp_adjust_head:
+ return &bpf_xdp_adjust_head_proto;
+ default:
+ return sk_filter_func_proto(func_id);
+ }
+}
+
+static const struct bpf_func_proto *
+cg_skb_func_proto(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ case BPF_FUNC_skb_load_bytes:
+ return &bpf_skb_load_bytes_proto;
+ default:
+ return sk_filter_func_proto(func_id);
+ }
+}
+
+static const struct bpf_func_proto *
+lwt_inout_func_proto(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ case BPF_FUNC_skb_load_bytes:
+ return &bpf_skb_load_bytes_proto;
+ case BPF_FUNC_skb_pull_data:
+ return &bpf_skb_pull_data_proto;
+ case BPF_FUNC_csum_diff:
+ return &bpf_csum_diff_proto;
+ case BPF_FUNC_get_cgroup_classid:
+ return &bpf_get_cgroup_classid_proto;
+ case BPF_FUNC_get_route_realm:
+ return &bpf_get_route_realm_proto;
+ case BPF_FUNC_get_hash_recalc:
+ return &bpf_get_hash_recalc_proto;
+ case BPF_FUNC_perf_event_output:
+ return &bpf_skb_event_output_proto;
+ case BPF_FUNC_get_smp_processor_id:
+ return &bpf_get_smp_processor_id_proto;
+ case BPF_FUNC_skb_under_cgroup:
+ return &bpf_skb_under_cgroup_proto;
default:
return sk_filter_func_proto(func_id);
}
}
-static bool __is_valid_access(int off, int size, enum bpf_access_type type)
+static const struct bpf_func_proto *
+lwt_xmit_func_proto(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ case BPF_FUNC_skb_get_tunnel_key:
+ return &bpf_skb_get_tunnel_key_proto;
+ case BPF_FUNC_skb_set_tunnel_key:
+ return bpf_get_skb_set_tunnel_proto(func_id);
+ case BPF_FUNC_skb_get_tunnel_opt:
+ return &bpf_skb_get_tunnel_opt_proto;
+ case BPF_FUNC_skb_set_tunnel_opt:
+ return bpf_get_skb_set_tunnel_proto(func_id);
+ case BPF_FUNC_redirect:
+ return &bpf_redirect_proto;
+ case BPF_FUNC_clone_redirect:
+ return &bpf_clone_redirect_proto;
+ case BPF_FUNC_skb_change_tail:
+ return &bpf_skb_change_tail_proto;
+ case BPF_FUNC_skb_change_head:
+ return &bpf_skb_change_head_proto;
+ case BPF_FUNC_skb_store_bytes:
+ return &bpf_skb_store_bytes_proto;
+ case BPF_FUNC_csum_update:
+ return &bpf_csum_update_proto;
+ case BPF_FUNC_l3_csum_replace:
+ return &bpf_l3_csum_replace_proto;
+ case BPF_FUNC_l4_csum_replace:
+ return &bpf_l4_csum_replace_proto;
+ case BPF_FUNC_set_hash_invalid:
+ return &bpf_set_hash_invalid_proto;
+ default:
+ return lwt_inout_func_proto(func_id);
+ }
+}
+
+static bool __is_valid_access(int off, int size)
{
if (off < 0 || off >= sizeof(struct __sk_buff))
return false;
@@ -2662,7 +2806,64 @@ static bool sk_filter_is_valid_access(int off, int size,
}
}
- return __is_valid_access(off, size, type);
+ return __is_valid_access(off, size);
+}
+
+static bool lwt_is_valid_access(int off, int size,
+ enum bpf_access_type type,
+ enum bpf_reg_type *reg_type)
+{
+ switch (off) {
+ case offsetof(struct __sk_buff, tc_classid):
+ return false;
+ }
+
+ if (type == BPF_WRITE) {
+ switch (off) {
+ case offsetof(struct __sk_buff, mark):
+ case offsetof(struct __sk_buff, priority):
+ case offsetof(struct __sk_buff, cb[0]) ...
+ offsetof(struct __sk_buff, cb[4]):
+ break;
+ default:
+ return false;
+ }
+ }
+
+ switch (off) {
+ case offsetof(struct __sk_buff, data):
+ *reg_type = PTR_TO_PACKET;
+ break;
+ case offsetof(struct __sk_buff, data_end):
+ *reg_type = PTR_TO_PACKET_END;
+ break;
+ }
+
+ return __is_valid_access(off, size);
+}
+
+static bool sock_filter_is_valid_access(int off, int size,
+ enum bpf_access_type type,
+ enum bpf_reg_type *reg_type)
+{
+ if (type == BPF_WRITE) {
+ switch (off) {
+ case offsetof(struct bpf_sock, bound_dev_if):
+ break;
+ default:
+ return false;
+ }
+ }
+
+ if (off < 0 || off + size > sizeof(struct bpf_sock))
+ return false;
+ /* The verifier guarantees that size > 0. */
+ if (off % size != 0)
+ return false;
+ if (size != sizeof(__u32))
+ return false;
+
+ return true;
}
static int tc_cls_act_prologue(struct bpf_insn *insn_buf, bool direct_write,
@@ -2731,11 +2932,10 @@ static bool tc_cls_act_is_valid_access(int off, int size,
break;
}
- return __is_valid_access(off, size, type);
+ return __is_valid_access(off, size);
}
-static bool __is_valid_xdp_access(int off, int size,
- enum bpf_access_type type)
+static bool __is_valid_xdp_access(int off, int size)
{
if (off < 0 || off >= sizeof(struct xdp_md))
return false;
@@ -2763,7 +2963,7 @@ static bool xdp_is_valid_access(int off, int size,
break;
}
- return __is_valid_xdp_access(off, size, type);
+ return __is_valid_xdp_access(off, size);
}
void bpf_warn_invalid_xdp_action(u32 act)
@@ -2923,6 +3123,51 @@ static u32 sk_filter_convert_ctx_access(enum bpf_access_type type, int dst_reg,
return insn - insn_buf;
}
+static u32 sock_filter_convert_ctx_access(enum bpf_access_type type,
+ int dst_reg, int src_reg,
+ int ctx_off,
+ struct bpf_insn *insn_buf,
+ struct bpf_prog *prog)
+{
+ struct bpf_insn *insn = insn_buf;
+
+ switch (ctx_off) {
+ case offsetof(struct bpf_sock, bound_dev_if):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_bound_dev_if) != 4);
+
+ if (type == BPF_WRITE)
+ *insn++ = BPF_STX_MEM(BPF_W, dst_reg, src_reg,
+ offsetof(struct sock, sk_bound_dev_if));
+ else
+ *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
+ offsetof(struct sock, sk_bound_dev_if));
+ break;
+
+ case offsetof(struct bpf_sock, family):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_family) != 2);
+
+ *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
+ offsetof(struct sock, sk_family));
+ break;
+
+ case offsetof(struct bpf_sock, type):
+ *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
+ offsetof(struct sock, __sk_flags_offset));
+ *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, SK_FL_TYPE_MASK);
+ *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, SK_FL_TYPE_SHIFT);
+ break;
+
+ case offsetof(struct bpf_sock, protocol):
+ *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
+ offsetof(struct sock, __sk_flags_offset));
+ *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, SK_FL_PROTO_MASK);
+ *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, SK_FL_PROTO_SHIFT);
+ break;
+ }
+
+ return insn - insn_buf;
+}
+
static u32 tc_cls_act_convert_ctx_access(enum bpf_access_type type, int dst_reg,
int src_reg, int ctx_off,
struct bpf_insn *insn_buf,
@@ -2990,6 +3235,31 @@ static const struct bpf_verifier_ops xdp_ops = {
.convert_ctx_access = xdp_convert_ctx_access,
};
+static const struct bpf_verifier_ops cg_skb_ops = {
+ .get_func_proto = cg_skb_func_proto,
+ .is_valid_access = sk_filter_is_valid_access,
+ .convert_ctx_access = sk_filter_convert_ctx_access,
+};
+
+static const struct bpf_verifier_ops lwt_inout_ops = {
+ .get_func_proto = lwt_inout_func_proto,
+ .is_valid_access = lwt_is_valid_access,
+ .convert_ctx_access = sk_filter_convert_ctx_access,
+};
+
+static const struct bpf_verifier_ops lwt_xmit_ops = {
+ .get_func_proto = lwt_xmit_func_proto,
+ .is_valid_access = lwt_is_valid_access,
+ .convert_ctx_access = sk_filter_convert_ctx_access,
+ .gen_prologue = tc_cls_act_prologue,
+};
+
+static const struct bpf_verifier_ops cg_sock_ops = {
+ .get_func_proto = sk_filter_func_proto,
+ .is_valid_access = sock_filter_is_valid_access,
+ .convert_ctx_access = sock_filter_convert_ctx_access,
+};
+
static struct bpf_prog_type_list sk_filter_type __read_mostly = {
.ops = &sk_filter_ops,
.type = BPF_PROG_TYPE_SOCKET_FILTER,
@@ -3010,12 +3280,42 @@ static struct bpf_prog_type_list xdp_type __read_mostly = {
.type = BPF_PROG_TYPE_XDP,
};
+static struct bpf_prog_type_list cg_skb_type __read_mostly = {
+ .ops = &cg_skb_ops,
+ .type = BPF_PROG_TYPE_CGROUP_SKB,
+};
+
+static struct bpf_prog_type_list lwt_in_type __read_mostly = {
+ .ops = &lwt_inout_ops,
+ .type = BPF_PROG_TYPE_LWT_IN,
+};
+
+static struct bpf_prog_type_list lwt_out_type __read_mostly = {
+ .ops = &lwt_inout_ops,
+ .type = BPF_PROG_TYPE_LWT_OUT,
+};
+
+static struct bpf_prog_type_list lwt_xmit_type __read_mostly = {
+ .ops = &lwt_xmit_ops,
+ .type = BPF_PROG_TYPE_LWT_XMIT,
+};
+
+static struct bpf_prog_type_list cg_sock_type __read_mostly = {
+ .ops = &cg_sock_ops,
+ .type = BPF_PROG_TYPE_CGROUP_SOCK
+};
+
static int __init register_sk_filter_ops(void)
{
bpf_register_prog_type(&sk_filter_type);
bpf_register_prog_type(&sched_cls_type);
bpf_register_prog_type(&sched_act_type);
bpf_register_prog_type(&xdp_type);
+ bpf_register_prog_type(&cg_skb_type);
+ bpf_register_prog_type(&cg_sock_type);
+ bpf_register_prog_type(&lwt_in_type);
+ bpf_register_prog_type(&lwt_out_type);
+ bpf_register_prog_type(&lwt_xmit_type);
return 0;
}
diff --git a/net/core/flow.c b/net/core/flow.c
index 18e8893d4be5..f765c11d8df5 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -417,28 +417,20 @@ static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)
return 0;
}
-static int flow_cache_cpu(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
+static int flow_cache_cpu_up_prep(unsigned int cpu, struct hlist_node *node)
{
- struct flow_cache *fc = container_of(nfb, struct flow_cache,
- hotcpu_notifier);
- int res, cpu = (unsigned long) hcpu;
+ struct flow_cache *fc = hlist_entry_safe(node, struct flow_cache, node);
+
+ return flow_cache_cpu_prepare(fc, cpu);
+}
+
+static int flow_cache_cpu_dead(unsigned int cpu, struct hlist_node *node)
+{
+ struct flow_cache *fc = hlist_entry_safe(node, struct flow_cache, node);
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- res = flow_cache_cpu_prepare(fc, cpu);
- if (res)
- return notifier_from_errno(res);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- __flow_cache_shrink(fc, fcp, 0);
- break;
- }
- return NOTIFY_OK;
+ __flow_cache_shrink(fc, fcp, 0);
+ return 0;
}
int flow_cache_init(struct net *net)
@@ -465,18 +457,8 @@ int flow_cache_init(struct net *net)
if (!fc->percpu)
return -ENOMEM;
- cpu_notifier_register_begin();
-
- for_each_online_cpu(i) {
- if (flow_cache_cpu_prepare(fc, i))
- goto err;
- }
- fc->hotcpu_notifier = (struct notifier_block){
- .notifier_call = flow_cache_cpu,
- };
- __register_hotcpu_notifier(&fc->hotcpu_notifier);
-
- cpu_notifier_register_done();
+ if (cpuhp_state_add_instance(CPUHP_NET_FLOW_PREPARE, &fc->node))
+ goto err;
setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
(unsigned long) fc);
@@ -492,8 +474,6 @@ err:
fcp->hash_table = NULL;
}
- cpu_notifier_register_done();
-
free_percpu(fc->percpu);
fc->percpu = NULL;
@@ -507,7 +487,8 @@ void flow_cache_fini(struct net *net)
struct flow_cache *fc = &net->xfrm.flow_cache_global;
del_timer_sync(&fc->rnd_timer);
- unregister_hotcpu_notifier(&fc->hotcpu_notifier);
+
+ cpuhp_state_remove_instance_nocalls(CPUHP_NET_FLOW_PREPARE, &fc->node);
for_each_possible_cpu(i) {
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
@@ -519,3 +500,14 @@ void flow_cache_fini(struct net *net)
fc->percpu = NULL;
}
EXPORT_SYMBOL(flow_cache_fini);
+
+void __init flow_cache_hp_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_NET_FLOW_PREPARE,
+ "net/flow:prepare",
+ flow_cache_cpu_up_prep,
+ flow_cache_cpu_dead);
+ WARN_ON(ret < 0);
+}
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index c6d8207ffa7e..d6447dc10371 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -58,6 +58,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
EXPORT_SYMBOL(skb_flow_dissector_init);
/**
+ * skb_flow_get_be16 - extract be16 entity
+ * @skb: sk_buff to extract from
+ * @poff: offset to extract at
+ * @data: raw buffer pointer to the packet
+ * @hlen: packet header length
+ *
+ * The function will try to retrieve a be32 entity at
+ * offset poff
+ */
+__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
+ int hlen)
+{
+ __be16 *u, _u;
+
+ u = __skb_header_pointer(skb, poff, sizeof(_u), data, hlen, &_u);
+ if (u)
+ return *u;
+
+ return 0;
+}
+
+/**
* __skb_flow_get_ports - extract the upper layer ports and return them
* @skb: sk_buff to extract the ports from
* @thoff: transport header offset
@@ -117,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector_key_basic *key_basic;
struct flow_dissector_key_addrs *key_addrs;
struct flow_dissector_key_ports *key_ports;
+ struct flow_dissector_key_icmp *key_icmp;
struct flow_dissector_key_tags *key_tags;
struct flow_dissector_key_vlan *key_vlan;
struct flow_dissector_key_keyid *key_keyid;
@@ -546,6 +569,14 @@ ip_proto_again:
data, hlen);
}
+ if (dissector_uses_key(flow_dissector,
+ FLOW_DISSECTOR_KEY_ICMP)) {
+ key_icmp = skb_flow_dissector_target(flow_dissector,
+ FLOW_DISSECTOR_KEY_ICMP,
+ target_container);
+ key_icmp->icmp = skb_flow_get_be16(skb, nhoff, data, hlen);
+ }
+
out_good:
ret = true;
@@ -726,7 +757,7 @@ EXPORT_SYMBOL(make_flow_keys_digest);
static struct flow_dissector flow_keys_dissector_symmetric __read_mostly;
-u32 __skb_get_hash_symmetric(struct sk_buff *skb)
+u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
{
struct flow_keys keys;
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index cad8e791f28e..101b5d0e2142 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -7,6 +7,7 @@
* 2 of the License, or (at your option) any later version.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Eric Dumazet <edumazet@google.com>
*
* Changes:
* Jamal Hadi Salim - moved it to net/core and reshulfed
@@ -30,165 +31,79 @@
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
-#include <linux/rbtree.h>
#include <linux/slab.h>
+#include <linux/seqlock.h>
#include <net/sock.h>
#include <net/gen_stats.h>
-/*
- This code is NOT intended to be used for statistics collection,
- its purpose is to provide a base for statistical multiplexing
- for controlled load service.
- If you need only statistics, run a user level daemon which
- periodically reads byte counters.
-
- Unfortunately, rate estimation is not a very easy task.
- F.e. I did not find a simple way to estimate the current peak rate
- and even failed to formulate the problem 8)8)
-
- So I preferred not to built an estimator into the scheduler,
- but run this task separately.
- Ideally, it should be kernel thread(s), but for now it runs
- from timers, which puts apparent top bounds on the number of rated
- flows, has minimal overhead on small, but is enough
- to handle controlled load service, sets of aggregates.
-
- We measure rate over A=(1<<interval) seconds and evaluate EWMA:
-
- avrate = avrate*(1-W) + rate*W
-
- where W is chosen as negative power of 2: W = 2^(-ewma_log)
-
- The resulting time constant is:
-
- T = A/(-ln(1-W))
-
-
- NOTES.
-
- * avbps and avpps are scaled by 2^5.
- * both values are reported as 32 bit unsigned values. bps can
- overflow for fast links : max speed being 34360Mbit/sec
- * Minimal interval is HZ/4=250msec (it is the greatest common divisor
- for HZ=100 and HZ=1024 8)), maximal interval
- is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals
- are too expensive, longer ones can be implemented
- at user level painlessly.
+/* This code is NOT intended to be used for statistics collection,
+ * its purpose is to provide a base for statistical multiplexing
+ * for controlled load service.
+ * If you need only statistics, run a user level daemon which
+ * periodically reads byte counters.
*/
-#define EST_MAX_INTERVAL 5
-
-struct gen_estimator
-{
- struct list_head list;
+struct net_rate_estimator {
struct gnet_stats_basic_packed *bstats;
- struct gnet_stats_rate_est64 *rate_est;
spinlock_t *stats_lock;
seqcount_t *running;
- int ewma_log;
+ struct gnet_stats_basic_cpu __percpu *cpu_bstats;
+ u8 ewma_log;
+ u8 intvl_log; /* period : (250ms << intvl_log) */
+
+ seqcount_t seq;
u32 last_packets;
- unsigned long avpps;
u64 last_bytes;
+
+ u64 avpps;
u64 avbps;
- struct rcu_head e_rcu;
- struct rb_node node;
- struct gnet_stats_basic_cpu __percpu *cpu_bstats;
- struct rcu_head head;
-};
-struct gen_estimator_head
-{
- struct timer_list timer;
- struct list_head list;
+ unsigned long next_jiffies;
+ struct timer_list timer;
+ struct rcu_head rcu;
};
-static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
-
-/* Protects against NULL dereference */
-static DEFINE_RWLOCK(est_lock);
-
-/* Protects against soft lockup during large deletion */
-static struct rb_root est_root = RB_ROOT;
-static DEFINE_SPINLOCK(est_tree_lock);
-
-static void est_timer(unsigned long arg)
+static void est_fetch_counters(struct net_rate_estimator *e,
+ struct gnet_stats_basic_packed *b)
{
- int idx = (int)arg;
- struct gen_estimator *e;
+ if (e->stats_lock)
+ spin_lock(e->stats_lock);
- rcu_read_lock();
- list_for_each_entry_rcu(e, &elist[idx].list, list) {
- struct gnet_stats_basic_packed b = {0};
- unsigned long rate;
- u64 brate;
-
- if (e->stats_lock)
- spin_lock(e->stats_lock);
- read_lock(&est_lock);
- if (e->bstats == NULL)
- goto skip;
-
- __gnet_stats_copy_basic(e->running, &b, e->cpu_bstats, e->bstats);
-
- brate = (b.bytes - e->last_bytes)<<(7 - idx);
- e->last_bytes = b.bytes;
- e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log);
- WRITE_ONCE(e->rate_est->bps, (e->avbps + 0xF) >> 5);
-
- rate = b.packets - e->last_packets;
- rate <<= (7 - idx);
- e->last_packets = b.packets;
- e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log);
- WRITE_ONCE(e->rate_est->pps, (e->avpps + 0xF) >> 5);
-skip:
- read_unlock(&est_lock);
- if (e->stats_lock)
- spin_unlock(e->stats_lock);
- }
+ __gnet_stats_copy_basic(e->running, b, e->cpu_bstats, e->bstats);
+
+ if (e->stats_lock)
+ spin_unlock(e->stats_lock);
- if (!list_empty(&elist[idx].list))
- mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
- rcu_read_unlock();
}
-static void gen_add_node(struct gen_estimator *est)
+static void est_timer(unsigned long arg)
{
- struct rb_node **p = &est_root.rb_node, *parent = NULL;
+ struct net_rate_estimator *est = (struct net_rate_estimator *)arg;
+ struct gnet_stats_basic_packed b;
+ u64 rate, brate;
- while (*p) {
- struct gen_estimator *e;
+ est_fetch_counters(est, &b);
+ brate = (b.bytes - est->last_bytes) << (8 - est->ewma_log);
+ brate -= (est->avbps >> est->ewma_log);
- parent = *p;
- e = rb_entry(parent, struct gen_estimator, node);
+ rate = (u64)(b.packets - est->last_packets) << (8 - est->ewma_log);
+ rate -= (est->avpps >> est->ewma_log);
- if (est->bstats > e->bstats)
- p = &parent->rb_right;
- else
- p = &parent->rb_left;
- }
- rb_link_node(&est->node, parent, p);
- rb_insert_color(&est->node, &est_root);
-}
+ write_seqcount_begin(&est->seq);
+ est->avbps += brate;
+ est->avpps += rate;
+ write_seqcount_end(&est->seq);
-static
-struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats,
- const struct gnet_stats_rate_est64 *rate_est)
-{
- struct rb_node *p = est_root.rb_node;
-
- while (p) {
- struct gen_estimator *e;
+ est->last_bytes = b.bytes;
+ est->last_packets = b.packets;
- e = rb_entry(p, struct gen_estimator, node);
+ est->next_jiffies += ((HZ/4) << est->intvl_log);
- if (bstats > e->bstats)
- p = p->rb_right;
- else if (bstats < e->bstats || rate_est != e->rate_est)
- p = p->rb_left;
- else
- return e;
+ if (unlikely(time_after_eq(jiffies, est->next_jiffies))) {
+ /* Ouch... timer was delayed. */
+ est->next_jiffies = jiffies + 1;
}
- return NULL;
+ mod_timer(&est->timer, est->next_jiffies);
}
/**
@@ -211,83 +126,76 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
*/
int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
- struct gnet_stats_rate_est64 *rate_est,
+ struct net_rate_estimator __rcu **rate_est,
spinlock_t *stats_lock,
seqcount_t *running,
struct nlattr *opt)
{
- struct gen_estimator *est;
struct gnet_estimator *parm = nla_data(opt);
- struct gnet_stats_basic_packed b = {0};
- int idx;
+ struct net_rate_estimator *old, *est;
+ struct gnet_stats_basic_packed b;
+ int intvl_log;
if (nla_len(opt) < sizeof(*parm))
return -EINVAL;
+ /* allowed timer periods are :
+ * -2 : 250ms, -1 : 500ms, 0 : 1 sec
+ * 1 : 2 sec, 2 : 4 sec, 3 : 8 sec
+ */
if (parm->interval < -2 || parm->interval > 3)
return -EINVAL;
est = kzalloc(sizeof(*est), GFP_KERNEL);
- if (est == NULL)
+ if (!est)
return -ENOBUFS;
- __gnet_stats_copy_basic(running, &b, cpu_bstats, bstats);
-
- idx = parm->interval + 2;
+ seqcount_init(&est->seq);
+ intvl_log = parm->interval + 2;
est->bstats = bstats;
- est->rate_est = rate_est;
est->stats_lock = stats_lock;
est->running = running;
est->ewma_log = parm->ewma_log;
- est->last_bytes = b.bytes;
- est->avbps = rate_est->bps<<5;
- est->last_packets = b.packets;
- est->avpps = rate_est->pps<<10;
+ est->intvl_log = intvl_log;
est->cpu_bstats = cpu_bstats;
- spin_lock_bh(&est_tree_lock);
- if (!elist[idx].timer.function) {
- INIT_LIST_HEAD(&elist[idx].list);
- setup_timer(&elist[idx].timer, est_timer, idx);
+ est_fetch_counters(est, &b);
+ est->last_bytes = b.bytes;
+ est->last_packets = b.packets;
+ old = rcu_dereference_protected(*rate_est, 1);
+ if (old) {
+ del_timer_sync(&old->timer);
+ est->avbps = old->avbps;
+ est->avpps = old->avpps;
}
- if (list_empty(&elist[idx].list))
- mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
-
- list_add_rcu(&est->list, &elist[idx].list);
- gen_add_node(est);
- spin_unlock_bh(&est_tree_lock);
+ est->next_jiffies = jiffies + ((HZ/4) << intvl_log);
+ setup_timer(&est->timer, est_timer, (unsigned long)est);
+ mod_timer(&est->timer, est->next_jiffies);
+ rcu_assign_pointer(*rate_est, est);
+ if (old)
+ kfree_rcu(old, rcu);
return 0;
}
EXPORT_SYMBOL(gen_new_estimator);
/**
* gen_kill_estimator - remove a rate estimator
- * @bstats: basic statistics
- * @rate_est: rate estimator statistics
+ * @rate_est: rate estimator
*
- * Removes the rate estimator specified by &bstats and &rate_est.
+ * Removes the rate estimator.
*
- * Note : Caller should respect an RCU grace period before freeing stats_lock
*/
-void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
- struct gnet_stats_rate_est64 *rate_est)
+void gen_kill_estimator(struct net_rate_estimator __rcu **rate_est)
{
- struct gen_estimator *e;
-
- spin_lock_bh(&est_tree_lock);
- while ((e = gen_find_node(bstats, rate_est))) {
- rb_erase(&e->node, &est_root);
+ struct net_rate_estimator *est;
- write_lock(&est_lock);
- e->bstats = NULL;
- write_unlock(&est_lock);
-
- list_del_rcu(&e->list);
- kfree_rcu(e, e_rcu);
+ est = xchg((__force struct net_rate_estimator **)rate_est, NULL);
+ if (est) {
+ del_timer_sync(&est->timer);
+ kfree_rcu(est, rcu);
}
- spin_unlock_bh(&est_tree_lock);
}
EXPORT_SYMBOL(gen_kill_estimator);
@@ -307,33 +215,47 @@ EXPORT_SYMBOL(gen_kill_estimator);
*/
int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
- struct gnet_stats_rate_est64 *rate_est,
+ struct net_rate_estimator __rcu **rate_est,
spinlock_t *stats_lock,
seqcount_t *running, struct nlattr *opt)
{
- gen_kill_estimator(bstats, rate_est);
- return gen_new_estimator(bstats, cpu_bstats, rate_est, stats_lock, running, opt);
+ return gen_new_estimator(bstats, cpu_bstats, rate_est,
+ stats_lock, running, opt);
}
EXPORT_SYMBOL(gen_replace_estimator);
/**
* gen_estimator_active - test if estimator is currently in use
- * @bstats: basic statistics
- * @rate_est: rate estimator statistics
+ * @rate_est: rate estimator
*
* Returns true if estimator is active, and false if not.
*/
-bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
- const struct gnet_stats_rate_est64 *rate_est)
+bool gen_estimator_active(struct net_rate_estimator __rcu **rate_est)
{
- bool res;
+ return !!rcu_access_pointer(*rate_est);
+}
+EXPORT_SYMBOL(gen_estimator_active);
- ASSERT_RTNL();
+bool gen_estimator_read(struct net_rate_estimator __rcu **rate_est,
+ struct gnet_stats_rate_est64 *sample)
+{
+ struct net_rate_estimator *est;
+ unsigned seq;
+
+ rcu_read_lock();
+ est = rcu_dereference(*rate_est);
+ if (!est) {
+ rcu_read_unlock();
+ return false;
+ }
- spin_lock_bh(&est_tree_lock);
- res = gen_find_node(bstats, rate_est) != NULL;
- spin_unlock_bh(&est_tree_lock);
+ do {
+ seq = read_seqcount_begin(&est->seq);
+ sample->bps = est->avbps >> 8;
+ sample->pps = est->avpps >> 8;
+ } while (read_seqcount_retry(&est->seq, seq));
- return res;
+ rcu_read_unlock();
+ return true;
}
-EXPORT_SYMBOL(gen_estimator_active);
+EXPORT_SYMBOL(gen_estimator_read);
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
index 508e051304fb..87f28557b329 100644
--- a/net/core/gen_stats.c
+++ b/net/core/gen_stats.c
@@ -194,8 +194,7 @@ EXPORT_SYMBOL(gnet_stats_copy_basic);
/**
* gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV
* @d: dumping handle
- * @b: basic statistics
- * @r: rate estimator statistics
+ * @rate_est: rate estimator
*
* Appends the rate estimator statistics to the top level TLV created by
* gnet_stats_start_copy().
@@ -205,18 +204,17 @@ EXPORT_SYMBOL(gnet_stats_copy_basic);
*/
int
gnet_stats_copy_rate_est(struct gnet_dump *d,
- const struct gnet_stats_basic_packed *b,
- struct gnet_stats_rate_est64 *r)
+ struct net_rate_estimator __rcu **rate_est)
{
+ struct gnet_stats_rate_est64 sample;
struct gnet_stats_rate_est est;
int res;
- if (b && !gen_estimator_active(b, r))
+ if (!gen_estimator_read(rate_est, &sample))
return 0;
-
- est.bps = min_t(u64, UINT_MAX, r->bps);
+ est.bps = min_t(u64, UINT_MAX, sample.bps);
/* we have some time before reaching 2^32 packets per second */
- est.pps = r->pps;
+ est.pps = sample.pps;
if (d->compat_tc_stats) {
d->tc_stats.bps = est.bps;
@@ -226,11 +224,11 @@ gnet_stats_copy_rate_est(struct gnet_dump *d,
if (d->tail) {
res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est),
TCA_STATS_PAD);
- if (res < 0 || est.bps == r->bps)
+ if (res < 0 || est.bps == sample.bps)
return res;
/* emit 64bit stats only if needed */
- return gnet_stats_copy(d, TCA_STATS_RATE_EST64, r, sizeof(*r),
- TCA_STATS_PAD);
+ return gnet_stats_copy(d, TCA_STATS_RATE_EST64, &sample,
+ sizeof(sample), TCA_STATS_PAD);
}
return 0;
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
new file mode 100644
index 000000000000..71bb3e2eca08
--- /dev/null
+++ b/net/core/lwt_bpf.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/skbuff.h>
+#include <linux/types.h>
+#include <linux/bpf.h>
+#include <net/lwtunnel.h>
+
+struct bpf_lwt_prog {
+ struct bpf_prog *prog;
+ char *name;
+};
+
+struct bpf_lwt {
+ struct bpf_lwt_prog in;
+ struct bpf_lwt_prog out;
+ struct bpf_lwt_prog xmit;
+ int family;
+};
+
+#define MAX_PROG_NAME 256
+
+static inline struct bpf_lwt *bpf_lwt_lwtunnel(struct lwtunnel_state *lwt)
+{
+ return (struct bpf_lwt *)lwt->data;
+}
+
+#define NO_REDIRECT false
+#define CAN_REDIRECT true
+
+static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+ struct dst_entry *dst, bool can_redirect)
+{
+ int ret;
+
+ /* Preempt disable is needed to protect per-cpu redirect_info between
+ * BPF prog and skb_do_redirect(). The call_rcu in bpf_prog_put() and
+ * access to maps strictly require a rcu_read_lock() for protection,
+ * mixing with BH RCU lock doesn't work.
+ */
+ preempt_disable();
+ rcu_read_lock();
+ bpf_compute_data_end(skb);
+ ret = bpf_prog_run_save_cb(lwt->prog, skb);
+ rcu_read_unlock();
+
+ switch (ret) {
+ case BPF_OK:
+ break;
+
+ case BPF_REDIRECT:
+ if (unlikely(!can_redirect)) {
+ pr_warn_once("Illegal redirect return code in prog %s\n",
+ lwt->name ? : "<unknown>");
+ ret = BPF_OK;
+ } else {
+ ret = skb_do_redirect(skb);
+ if (ret == 0)
+ ret = BPF_REDIRECT;
+ }
+ break;
+
+ case BPF_DROP:
+ kfree_skb(skb);
+ ret = -EPERM;
+ break;
+
+ default:
+ pr_warn_once("bpf-lwt: Illegal return value %u, expect packet loss\n", ret);
+ kfree_skb(skb);
+ ret = -EINVAL;
+ break;
+ }
+
+ preempt_enable();
+
+ return ret;
+}
+
+static int bpf_input(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct bpf_lwt *bpf;
+ int ret;
+
+ bpf = bpf_lwt_lwtunnel(dst->lwtstate);
+ if (bpf->in.prog) {
+ ret = run_lwt_bpf(skb, &bpf->in, dst, NO_REDIRECT);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (unlikely(!dst->lwtstate->orig_input)) {
+ pr_warn_once("orig_input not set on dst for prog %s\n",
+ bpf->out.name);
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ return dst->lwtstate->orig_input(skb);
+}
+
+static int bpf_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct bpf_lwt *bpf;
+ int ret;
+
+ bpf = bpf_lwt_lwtunnel(dst->lwtstate);
+ if (bpf->out.prog) {
+ ret = run_lwt_bpf(skb, &bpf->out, dst, NO_REDIRECT);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (unlikely(!dst->lwtstate->orig_output)) {
+ pr_warn_once("orig_output not set on dst for prog %s\n",
+ bpf->out.name);
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ return dst->lwtstate->orig_output(net, sk, skb);
+}
+
+static int xmit_check_hhlen(struct sk_buff *skb)
+{
+ int hh_len = skb_dst(skb)->dev->hard_header_len;
+
+ if (skb_headroom(skb) < hh_len) {
+ int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb));
+
+ if (pskb_expand_head(skb, nhead, 0, GFP_ATOMIC))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int bpf_xmit(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct bpf_lwt *bpf;
+
+ bpf = bpf_lwt_lwtunnel(dst->lwtstate);
+ if (bpf->xmit.prog) {
+ int ret;
+
+ ret = run_lwt_bpf(skb, &bpf->xmit, dst, CAN_REDIRECT);
+ switch (ret) {
+ case BPF_OK:
+ /* If the header was expanded, headroom might be too
+ * small for L2 header to come, expand as needed.
+ */
+ ret = xmit_check_hhlen(skb);
+ if (unlikely(ret))
+ return ret;
+
+ return LWTUNNEL_XMIT_CONTINUE;
+ case BPF_REDIRECT:
+ return LWTUNNEL_XMIT_DONE;
+ default:
+ return ret;
+ }
+ }
+
+ return LWTUNNEL_XMIT_CONTINUE;
+}
+
+static void bpf_lwt_prog_destroy(struct bpf_lwt_prog *prog)
+{
+ if (prog->prog)
+ bpf_prog_put(prog->prog);
+
+ kfree(prog->name);
+}
+
+static void bpf_destroy_state(struct lwtunnel_state *lwt)
+{
+ struct bpf_lwt *bpf = bpf_lwt_lwtunnel(lwt);
+
+ bpf_lwt_prog_destroy(&bpf->in);
+ bpf_lwt_prog_destroy(&bpf->out);
+ bpf_lwt_prog_destroy(&bpf->xmit);
+}
+
+static const struct nla_policy bpf_prog_policy[LWT_BPF_PROG_MAX + 1] = {
+ [LWT_BPF_PROG_FD] = { .type = NLA_U32, },
+ [LWT_BPF_PROG_NAME] = { .type = NLA_NUL_STRING,
+ .len = MAX_PROG_NAME },
+};
+
+static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog,
+ enum bpf_prog_type type)
+{
+ struct nlattr *tb[LWT_BPF_PROG_MAX + 1];
+ struct bpf_prog *p;
+ int ret;
+ u32 fd;
+
+ ret = nla_parse_nested(tb, LWT_BPF_PROG_MAX, attr, bpf_prog_policy);
+ if (ret < 0)
+ return ret;
+
+ if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME])
+ return -EINVAL;
+
+ prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_KERNEL);
+ if (!prog->name)
+ return -ENOMEM;
+
+ fd = nla_get_u32(tb[LWT_BPF_PROG_FD]);
+ p = bpf_prog_get_type(fd, type);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ prog->prog = p;
+
+ return 0;
+}
+
+static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = {
+ [LWT_BPF_IN] = { .type = NLA_NESTED, },
+ [LWT_BPF_OUT] = { .type = NLA_NESTED, },
+ [LWT_BPF_XMIT] = { .type = NLA_NESTED, },
+ [LWT_BPF_XMIT_HEADROOM] = { .type = NLA_U32 },
+};
+
+static int bpf_build_state(struct net_device *dev, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts)
+{
+ struct nlattr *tb[LWT_BPF_MAX + 1];
+ struct lwtunnel_state *newts;
+ struct bpf_lwt *bpf;
+ int ret;
+
+ if (family != AF_INET && family != AF_INET6)
+ return -EAFNOSUPPORT;
+
+ ret = nla_parse_nested(tb, LWT_BPF_MAX, nla, bpf_nl_policy);
+ if (ret < 0)
+ return ret;
+
+ if (!tb[LWT_BPF_IN] && !tb[LWT_BPF_OUT] && !tb[LWT_BPF_XMIT])
+ return -EINVAL;
+
+ newts = lwtunnel_state_alloc(sizeof(*bpf));
+ if (!newts)
+ return -ENOMEM;
+
+ newts->type = LWTUNNEL_ENCAP_BPF;
+ bpf = bpf_lwt_lwtunnel(newts);
+
+ if (tb[LWT_BPF_IN]) {
+ newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
+ ret = bpf_parse_prog(tb[LWT_BPF_IN], &bpf->in,
+ BPF_PROG_TYPE_LWT_IN);
+ if (ret < 0)
+ goto errout;
+ }
+
+ if (tb[LWT_BPF_OUT]) {
+ newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
+ ret = bpf_parse_prog(tb[LWT_BPF_OUT], &bpf->out,
+ BPF_PROG_TYPE_LWT_OUT);
+ if (ret < 0)
+ goto errout;
+ }
+
+ if (tb[LWT_BPF_XMIT]) {
+ newts->flags |= LWTUNNEL_STATE_XMIT_REDIRECT;
+ ret = bpf_parse_prog(tb[LWT_BPF_XMIT], &bpf->xmit,
+ BPF_PROG_TYPE_LWT_XMIT);
+ if (ret < 0)
+ goto errout;
+ }
+
+ if (tb[LWT_BPF_XMIT_HEADROOM]) {
+ u32 headroom = nla_get_u32(tb[LWT_BPF_XMIT_HEADROOM]);
+
+ if (headroom > LWT_BPF_MAX_HEADROOM) {
+ ret = -ERANGE;
+ goto errout;
+ }
+
+ newts->headroom = headroom;
+ }
+
+ bpf->family = family;
+ *ts = newts;
+
+ return 0;
+
+errout:
+ bpf_destroy_state(newts);
+ kfree(newts);
+ return ret;
+}
+
+static int bpf_fill_lwt_prog(struct sk_buff *skb, int attr,
+ struct bpf_lwt_prog *prog)
+{
+ struct nlattr *nest;
+
+ if (!prog->prog)
+ return 0;
+
+ nest = nla_nest_start(skb, attr);
+ if (!nest)
+ return -EMSGSIZE;
+
+ if (prog->name &&
+ nla_put_string(skb, LWT_BPF_PROG_NAME, prog->name))
+ return -EMSGSIZE;
+
+ return nla_nest_end(skb, nest);
+}
+
+static int bpf_fill_encap_info(struct sk_buff *skb, struct lwtunnel_state *lwt)
+{
+ struct bpf_lwt *bpf = bpf_lwt_lwtunnel(lwt);
+
+ if (bpf_fill_lwt_prog(skb, LWT_BPF_IN, &bpf->in) < 0 ||
+ bpf_fill_lwt_prog(skb, LWT_BPF_OUT, &bpf->out) < 0 ||
+ bpf_fill_lwt_prog(skb, LWT_BPF_XMIT, &bpf->xmit) < 0)
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int bpf_encap_nlsize(struct lwtunnel_state *lwtstate)
+{
+ int nest_len = nla_total_size(sizeof(struct nlattr)) +
+ nla_total_size(MAX_PROG_NAME) + /* LWT_BPF_PROG_NAME */
+ 0;
+
+ return nest_len + /* LWT_BPF_IN */
+ nest_len + /* LWT_BPF_OUT */
+ nest_len + /* LWT_BPF_XMIT */
+ 0;
+}
+
+int bpf_lwt_prog_cmp(struct bpf_lwt_prog *a, struct bpf_lwt_prog *b)
+{
+ /* FIXME:
+ * The LWT state is currently rebuilt for delete requests which
+ * results in a new bpf_prog instance. Comparing names for now.
+ */
+ if (!a->name && !b->name)
+ return 0;
+
+ if (!a->name || !b->name)
+ return 1;
+
+ return strcmp(a->name, b->name);
+}
+
+static int bpf_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
+{
+ struct bpf_lwt *a_bpf = bpf_lwt_lwtunnel(a);
+ struct bpf_lwt *b_bpf = bpf_lwt_lwtunnel(b);
+
+ return bpf_lwt_prog_cmp(&a_bpf->in, &b_bpf->in) ||
+ bpf_lwt_prog_cmp(&a_bpf->out, &b_bpf->out) ||
+ bpf_lwt_prog_cmp(&a_bpf->xmit, &b_bpf->xmit);
+}
+
+static const struct lwtunnel_encap_ops bpf_encap_ops = {
+ .build_state = bpf_build_state,
+ .destroy_state = bpf_destroy_state,
+ .input = bpf_input,
+ .output = bpf_output,
+ .xmit = bpf_xmit,
+ .fill_encap = bpf_fill_encap_info,
+ .get_encap_size = bpf_encap_nlsize,
+ .cmp_encap = bpf_encap_cmp,
+};
+
+static int __init bpf_lwt_init(void)
+{
+ return lwtunnel_encap_add_ops(&bpf_encap_ops, LWTUNNEL_ENCAP_BPF);
+}
+
+subsys_initcall(bpf_lwt_init)
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index e5f84c26ba1a..a5d4e866ce88 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -39,6 +39,10 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
return "MPLS";
case LWTUNNEL_ENCAP_ILA:
return "ILA";
+ case LWTUNNEL_ENCAP_SEG6:
+ return "SEG6";
+ case LWTUNNEL_ENCAP_BPF:
+ return "BPF";
case LWTUNNEL_ENCAP_IP6:
case LWTUNNEL_ENCAP_IP:
case LWTUNNEL_ENCAP_NONE:
@@ -130,6 +134,19 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
}
EXPORT_SYMBOL(lwtunnel_build_state);
+void lwtstate_free(struct lwtunnel_state *lws)
+{
+ const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
+
+ if (ops->destroy_state) {
+ ops->destroy_state(lws);
+ kfree_rcu(lws, rcu);
+ } else {
+ kfree(lws);
+ }
+}
+EXPORT_SYMBOL(lwtstate_free);
+
int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
{
const struct lwtunnel_encap_ops *ops;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 2ae929f9bd06..782dd8663665 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2291,13 +2291,10 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
n != NULL;
n = rcu_dereference_bh(n->next)) {
- if (!net_eq(dev_net(n->dev), net))
- continue;
- if (neigh_ifindex_filtered(n->dev, filter_idx))
- continue;
- if (neigh_master_filtered(n->dev, filter_master_idx))
- continue;
- if (idx < s_idx)
+ if (idx < s_idx || !net_eq(dev_net(n->dev), net))
+ goto next;
+ if (neigh_ifindex_filtered(n->dev, filter_idx) ||
+ neigh_master_filtered(n->dev, filter_master_idx))
goto next;
if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
@@ -2332,9 +2329,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
if (h > s_h)
s_idx = 0;
for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
- if (pneigh_net(n) != net)
- continue;
- if (idx < s_idx)
+ if (idx < s_idx || pneigh_net(n) != net)
goto next;
if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 6e4f34721080..b0c04cf4851d 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -950,10 +950,13 @@ net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
}
while (--i >= new_num) {
+ struct kobject *kobj = &dev->_rx[i].kobj;
+
+ if (!list_empty(&dev_net(dev)->exit_list))
+ kobj->uevent_suppress = 1;
if (dev->sysfs_rx_queue_group)
- sysfs_remove_group(&dev->_rx[i].kobj,
- dev->sysfs_rx_queue_group);
- kobject_put(&dev->_rx[i].kobj);
+ sysfs_remove_group(kobj, dev->sysfs_rx_queue_group);
+ kobject_put(kobj);
}
return error;
@@ -1021,7 +1024,6 @@ static ssize_t show_trans_timeout(struct netdev_queue *queue,
return sprintf(buf, "%lu", trans_timeout);
}
-#ifdef CONFIG_XPS
static unsigned int get_netdev_queue_index(struct netdev_queue *queue)
{
struct net_device *dev = queue->dev;
@@ -1033,6 +1035,21 @@ static unsigned int get_netdev_queue_index(struct netdev_queue *queue)
return i;
}
+static ssize_t show_traffic_class(struct netdev_queue *queue,
+ struct netdev_queue_attribute *attribute,
+ char *buf)
+{
+ struct net_device *dev = queue->dev;
+ int index = get_netdev_queue_index(queue);
+ int tc = netdev_txq_to_tc(dev, index);
+
+ if (tc < 0)
+ return -EINVAL;
+
+ return sprintf(buf, "%u\n", tc);
+}
+
+#ifdef CONFIG_XPS
static ssize_t show_tx_maxrate(struct netdev_queue *queue,
struct netdev_queue_attribute *attribute,
char *buf)
@@ -1075,6 +1092,9 @@ static struct netdev_queue_attribute queue_tx_maxrate =
static struct netdev_queue_attribute queue_trans_timeout =
__ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL);
+static struct netdev_queue_attribute queue_traffic_class =
+ __ATTR(traffic_class, S_IRUGO, show_traffic_class, NULL);
+
#ifdef CONFIG_BQL
/*
* Byte queue limits sysfs structures and functions.
@@ -1190,29 +1210,38 @@ static ssize_t show_xps_map(struct netdev_queue *queue,
struct netdev_queue_attribute *attribute, char *buf)
{
struct net_device *dev = queue->dev;
+ int cpu, len, num_tc = 1, tc = 0;
struct xps_dev_maps *dev_maps;
cpumask_var_t mask;
unsigned long index;
- int i, len;
if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
index = get_netdev_queue_index(queue);
+ if (dev->num_tc) {
+ num_tc = dev->num_tc;
+ tc = netdev_txq_to_tc(dev, index);
+ if (tc < 0)
+ return -EINVAL;
+ }
+
rcu_read_lock();
dev_maps = rcu_dereference(dev->xps_maps);
if (dev_maps) {
- for_each_possible_cpu(i) {
- struct xps_map *map =
- rcu_dereference(dev_maps->cpu_map[i]);
- if (map) {
- int j;
- for (j = 0; j < map->len; j++) {
- if (map->queues[j] == index) {
- cpumask_set_cpu(i, mask);
- break;
- }
+ for_each_possible_cpu(cpu) {
+ int i, tci = cpu * num_tc + tc;
+ struct xps_map *map;
+
+ map = rcu_dereference(dev_maps->cpu_map[tci]);
+ if (!map)
+ continue;
+
+ for (i = map->len; i--;) {
+ if (map->queues[i] == index) {
+ cpumask_set_cpu(cpu, mask);
+ break;
}
}
}
@@ -1260,6 +1289,7 @@ static struct netdev_queue_attribute xps_cpus_attribute =
static struct attribute *netdev_queue_default_attrs[] = {
&queue_trans_timeout.attr,
+ &queue_traffic_class.attr,
#ifdef CONFIG_XPS
&xps_cpus_attribute.attr,
&queue_tx_maxrate.attr,
@@ -1340,6 +1370,8 @@ netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
while (--i >= new_num) {
struct netdev_queue *queue = dev->_tx + i;
+ if (!list_empty(&dev_net(dev)->exit_list))
+ queue->kobj.uevent_suppress = 1;
#ifdef CONFIG_BQL
sysfs_remove_group(&queue->kobj, &dql_group);
#endif
@@ -1525,6 +1557,9 @@ void netdev_unregister_kobject(struct net_device *ndev)
{
struct device *dev = &(ndev->dev);
+ if (!list_empty(&dev_net(ndev)->exit_list))
+ dev_set_uevent_suppress(dev, 1);
+
kobject_get(&dev->kobj);
remove_queue_kobjects(ndev);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 7001da910c6b..50fdc1b59777 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -39,6 +39,9 @@ EXPORT_SYMBOL(init_net);
static bool init_net_initialized;
+#define MIN_PERNET_OPS_ID \
+ ((sizeof(struct net_generic) + sizeof(void *) - 1) / sizeof(void *))
+
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
@@ -46,27 +49,28 @@ static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
static struct net_generic *net_alloc_generic(void)
{
struct net_generic *ng;
- size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+ unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
ng = kzalloc(generic_size, GFP_KERNEL);
if (ng)
- ng->len = max_gen_ptrs;
+ ng->s.len = max_gen_ptrs;
return ng;
}
-static int net_assign_generic(struct net *net, int id, void *data)
+static int net_assign_generic(struct net *net, unsigned int id, void *data)
{
struct net_generic *ng, *old_ng;
BUG_ON(!mutex_is_locked(&net_mutex));
- BUG_ON(id == 0);
+ BUG_ON(id < MIN_PERNET_OPS_ID);
old_ng = rcu_dereference_protected(net->gen,
lockdep_is_held(&net_mutex));
- ng = old_ng;
- if (old_ng->len >= id)
- goto assign;
+ if (old_ng->s.len > id) {
+ old_ng->ptr[id] = data;
+ return 0;
+ }
ng = net_alloc_generic();
if (ng == NULL)
@@ -83,12 +87,12 @@ static int net_assign_generic(struct net *net, int id, void *data)
* the old copy for kfree after a grace period.
*/
- memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
+ memcpy(&ng->ptr[MIN_PERNET_OPS_ID], &old_ng->ptr[MIN_PERNET_OPS_ID],
+ (old_ng->s.len - MIN_PERNET_OPS_ID) * sizeof(void *));
+ ng->ptr[id] = data;
rcu_assign_pointer(net->gen, ng);
- kfree_rcu(old_ng, rcu);
-assign:
- ng->ptr[id - 1] = data;
+ kfree_rcu(old_ng, s.rcu);
return 0;
}
@@ -122,8 +126,7 @@ out:
static void ops_free(const struct pernet_operations *ops, struct net *net)
{
if (ops->id && ops->size) {
- int id = *ops->id;
- kfree(net_generic(net, id));
+ kfree(net_generic(net, *ops->id));
}
}
@@ -384,7 +387,14 @@ struct net *copy_net_ns(unsigned long flags,
get_user_ns(user_ns);
- mutex_lock(&net_mutex);
+ rv = mutex_lock_killable(&net_mutex);
+ if (rv < 0) {
+ net_free(net);
+ dec_net_namespaces(ucounts);
+ put_user_ns(user_ns);
+ return ERR_PTR(rv);
+ }
+
net->ucounts = ucounts;
rv = setup_net(net, user_ns);
if (rv == 0) {
@@ -868,7 +878,7 @@ static int register_pernet_operations(struct list_head *list,
if (ops->id) {
again:
- error = ida_get_new_above(&net_generic_ids, 1, ops->id);
+ error = ida_get_new_above(&net_generic_ids, MIN_PERNET_OPS_ID, ops->id);
if (error < 0) {
if (error == -EAGAIN) {
ida_pre_get(&net_generic_ids, GFP_KERNEL);
@@ -876,7 +886,7 @@ again:
}
return error;
}
- max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
+ max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
}
error = __register_pernet_operations(list, ops);
if (error) {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 53599bd0c82d..9424673009c1 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -171,12 +171,12 @@ static void poll_one_napi(struct napi_struct *napi)
static void poll_napi(struct net_device *dev)
{
struct napi_struct *napi;
+ int cpu = smp_processor_id();
list_for_each_entry(napi, &dev->napi_list, dev_list) {
- if (napi->poll_owner != smp_processor_id() &&
- spin_trylock(&napi->poll_lock)) {
+ if (cmpxchg(&napi->poll_owner, -1, cpu) == -1) {
poll_one_napi(napi);
- spin_unlock(&napi->poll_lock);
+ smp_store_release(&napi->poll_owner, -1);
}
}
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 306b8f0e03c1..8e69ce472236 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -413,7 +413,7 @@ struct pktgen_hdr {
};
-static int pg_net_id __read_mostly;
+static unsigned int pg_net_id __read_mostly;
struct pktgen_net {
struct net *net;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a6196cf844f6..c482491a63d8 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1505,6 +1505,7 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = {
[IFLA_XDP_FD] = { .type = NLA_S32 },
[IFLA_XDP_ATTACHED] = { .type = NLA_U8 },
+ [IFLA_XDP_FLAGS] = { .type = NLA_U32 },
};
static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla)
@@ -2164,6 +2165,7 @@ static int do_setlink(const struct sk_buff *skb,
if (tb[IFLA_XDP]) {
struct nlattr *xdp[IFLA_XDP_MAX + 1];
+ u32 xdp_flags = 0;
err = nla_parse_nested(xdp, IFLA_XDP_MAX, tb[IFLA_XDP],
ifla_xdp_policy);
@@ -2174,9 +2176,19 @@ static int do_setlink(const struct sk_buff *skb,
err = -EINVAL;
goto errout;
}
+
+ if (xdp[IFLA_XDP_FLAGS]) {
+ xdp_flags = nla_get_u32(xdp[IFLA_XDP_FLAGS]);
+ if (xdp_flags & ~XDP_FLAGS_MASK) {
+ err = -EINVAL;
+ goto errout;
+ }
+ }
+
if (xdp[IFLA_XDP_FD]) {
err = dev_change_xdp_fd(dev,
- nla_get_s32(xdp[IFLA_XDP_FD]));
+ nla_get_s32(xdp[IFLA_XDP_FD]),
+ xdp_flags);
if (err)
goto errout;
status |= DO_SETLINK_NOTIFY;
@@ -3165,7 +3177,7 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
err = nlmsg_populate_fdb(skb, cb, dev, idx, &dev->uc);
if (err)
goto out;
- nlmsg_populate_fdb(skb, cb, dev, idx, &dev->mc);
+ err = nlmsg_populate_fdb(skb, cb, dev, idx, &dev->mc);
out:
netif_addr_unlock_bh(dev);
return err;
@@ -3671,7 +3683,7 @@ static int rtnl_get_offload_stats(struct sk_buff *skb, struct net_device *dev,
if (!size)
continue;
- if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
+ if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id))
continue;
attr = nla_reserve_64bit(skb, attr_id, size,
@@ -3712,7 +3724,7 @@ static int rtnl_get_offload_stats_size(const struct net_device *dev)
for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST;
attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) {
- if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
+ if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id))
continue;
size = rtnl_get_offload_stats_attr_size(attr_id);
nla_size += nla_total_size_64bit(size);
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index fd3ce461fbe6..88a8e429fc3e 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -12,6 +12,7 @@
#include <net/secure_seq.h>
#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
+#include <net/tcp.h>
#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
@@ -40,8 +41,8 @@ static u32 seq_scale(u32 seq)
#endif
#if IS_ENABLED(CONFIG_IPV6)
-__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
- __be16 sport, __be16 dport)
+u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+ __be16 sport, __be16 dport, u32 *tsoff)
{
u32 secret[MD5_MESSAGE_BYTES / 4];
u32 hash[MD5_DIGEST_WORDS];
@@ -58,6 +59,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
md5_transform(hash, secret);
+ *tsoff = sysctl_tcp_timestamps == 1 ? hash[1] : 0;
return seq_scale(hash[0]);
}
EXPORT_SYMBOL(secure_tcpv6_sequence_number);
@@ -86,8 +88,8 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#ifdef CONFIG_INET
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport)
+u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport, u32 *tsoff)
{
u32 hash[MD5_DIGEST_WORDS];
@@ -99,6 +101,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
md5_transform(hash, net_secret);
+ *tsoff = sysctl_tcp_timestamps == 1 ? hash[1] : 0;
return seq_scale(hash[0]);
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1e3e0087245b..65a74e13c45b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -354,7 +354,7 @@ EXPORT_SYMBOL(build_skb);
struct napi_alloc_cache {
struct page_frag_cache page;
- size_t skb_count;
+ unsigned int skb_count;
void *skb_cache[NAPI_SKB_CACHE_SIZE];
};
@@ -2656,7 +2656,9 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
struct skb_frag_struct *fragfrom, *fragto;
BUG_ON(shiftlen > skb->len);
- BUG_ON(skb_headlen(skb)); /* Would corrupt stream */
+
+ if (skb_headlen(skb))
+ return 0;
todo = shiftlen;
from = 0;
@@ -3712,21 +3714,29 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
}
EXPORT_SYMBOL(sock_queue_err_skb);
+static bool is_icmp_err_skb(const struct sk_buff *skb)
+{
+ return skb && (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
+ SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP6);
+}
+
struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
{
struct sk_buff_head *q = &sk->sk_error_queue;
- struct sk_buff *skb, *skb_next;
+ struct sk_buff *skb, *skb_next = NULL;
+ bool icmp_next = false;
unsigned long flags;
- int err = 0;
spin_lock_irqsave(&q->lock, flags);
skb = __skb_dequeue(q);
if (skb && (skb_next = skb_peek(q)))
- err = SKB_EXT_ERR(skb_next)->ee.ee_errno;
+ icmp_next = is_icmp_err_skb(skb_next);
spin_unlock_irqrestore(&q->lock, flags);
- sk->sk_err = err;
- if (err)
+ if (is_icmp_err_skb(skb) && !icmp_next)
+ sk->sk_err = 0;
+
+ if (skb_next)
sk->sk_error_report(sk);
return skb;
@@ -3838,10 +3848,18 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
if (!skb_may_tx_timestamp(sk, tsonly))
return;
- if (tsonly)
- skb = alloc_skb(0, GFP_ATOMIC);
- else
+ if (tsonly) {
+#ifdef CONFIG_INET
+ if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
+ sk->sk_protocol == IPPROTO_TCP &&
+ sk->sk_type == SOCK_STREAM)
+ skb = tcp_get_timestamping_opt_stats(sk);
+ else
+#endif
+ skb = alloc_skb(0, GFP_ATOMIC);
+ } else {
skb = skb_clone(orig_skb, GFP_ATOMIC);
+ }
if (!skb)
return;
@@ -4913,3 +4931,35 @@ struct sk_buff *pskb_extract(struct sk_buff *skb, int off,
return clone;
}
EXPORT_SYMBOL(pskb_extract);
+
+/**
+ * skb_condense - try to get rid of fragments/frag_list if possible
+ * @skb: buffer
+ *
+ * Can be used to save memory before skb is added to a busy queue.
+ * If packet has bytes in frags and enough tail room in skb->head,
+ * pull all of them, so that we can free the frags right now and adjust
+ * truesize.
+ * Notes:
+ * We do not reallocate skb->head thus can not fail.
+ * Caller must re-evaluate skb->truesize if needed.
+ */
+void skb_condense(struct sk_buff *skb)
+{
+ if (skb->data_len) {
+ if (skb->data_len > skb->end - skb->tail ||
+ skb_cloned(skb))
+ return;
+
+ /* Nice, we can free page frag(s) right now */
+ __pskb_pull_tail(skb, skb->data_len);
+ }
+ /* At this point, skb->truesize might be over estimated,
+ * because skb had a fragment, and fragments do not tell
+ * their truesize.
+ * When we pulled its content into skb->head, fragment
+ * was freed, but __pskb_pull_tail() could not possibly
+ * adjust skb->truesize, not knowing the frag truesize.
+ */
+ skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
+}
diff --git a/net/core/sock.c b/net/core/sock.c
index 00a074dbfe9b..9fa46b956bdc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -854,6 +854,13 @@ set_rcvbuf:
sk->sk_tskey = 0;
}
}
+
+ if (val & SOF_TIMESTAMPING_OPT_STATS &&
+ !(val & SOF_TIMESTAMPING_OPT_TSONLY)) {
+ ret = -EINVAL;
+ break;
+ }
+
sk->sk_tsflags = val;
if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
sock_enable_timestamp(sk,
@@ -2080,37 +2087,31 @@ void __sk_flush_backlog(struct sock *sk)
*/
int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
int rc;
- DEFINE_WAIT(wait);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb);
+ rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb, &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}
EXPORT_SYMBOL(sk_wait_data);
/**
- * __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
+ * __sk_mem_raise_allocated - increase memory_allocated
* @sk: socket
* @size: memory size to allocate
+ * @amt: pages to allocate
* @kind: allocation type
*
- * If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
- * rmem allocation. This function assumes that protocols which have
- * memory_pressure use sk_wmem_queued as write buffer accounting.
+ * Similar to __sk_mem_schedule(), but does not update sk_forward_alloc
*/
-int __sk_mem_schedule(struct sock *sk, int size, int kind)
+int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
{
struct proto *prot = sk->sk_prot;
- int amt = sk_mem_pages(size);
- long allocated;
-
- sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
-
- allocated = sk_memory_allocated_add(sk, amt);
+ long allocated = sk_memory_allocated_add(sk, amt);
if (mem_cgroup_sockets_enabled && sk->sk_memcg &&
!mem_cgroup_charge_skmem(sk->sk_memcg, amt))
@@ -2171,9 +2172,6 @@ suppress_allocation:
trace_sock_exceed_buf_limit(sk, prot, allocated);
- /* Alas. Undo changes. */
- sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
-
sk_memory_allocated_sub(sk, amt);
if (mem_cgroup_sockets_enabled && sk->sk_memcg)
@@ -2181,18 +2179,40 @@ suppress_allocation:
return 0;
}
+EXPORT_SYMBOL(__sk_mem_raise_allocated);
+
+/**
+ * __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
+ * @sk: socket
+ * @size: memory size to allocate
+ * @kind: allocation type
+ *
+ * If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
+ * rmem allocation. This function assumes that protocols which have
+ * memory_pressure use sk_wmem_queued as write buffer accounting.
+ */
+int __sk_mem_schedule(struct sock *sk, int size, int kind)
+{
+ int ret, amt = sk_mem_pages(size);
+
+ sk->sk_forward_alloc += amt << SK_MEM_QUANTUM_SHIFT;
+ ret = __sk_mem_raise_allocated(sk, size, amt, kind);
+ if (!ret)
+ sk->sk_forward_alloc -= amt << SK_MEM_QUANTUM_SHIFT;
+ return ret;
+}
EXPORT_SYMBOL(__sk_mem_schedule);
/**
- * __sk_mem_reclaim - reclaim memory_allocated
+ * __sk_mem_reduce_allocated - reclaim memory_allocated
* @sk: socket
- * @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
+ * @amount: number of quanta
+ *
+ * Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc
*/
-void __sk_mem_reclaim(struct sock *sk, int amount)
+void __sk_mem_reduce_allocated(struct sock *sk, int amount)
{
- amount >>= SK_MEM_QUANTUM_SHIFT;
sk_memory_allocated_sub(sk, amount);
- sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
if (mem_cgroup_sockets_enabled && sk->sk_memcg)
mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
@@ -2201,6 +2221,19 @@ void __sk_mem_reclaim(struct sock *sk, int amount)
(sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
sk_leave_memory_pressure(sk);
}
+EXPORT_SYMBOL(__sk_mem_reduce_allocated);
+
+/**
+ * __sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated
+ * @sk: socket
+ * @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
+ */
+void __sk_mem_reclaim(struct sock *sk, int amount)
+{
+ amount >>= SK_MEM_QUANTUM_SHIFT;
+ sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
+ __sk_mem_reduce_allocated(sk, amount);
+}
EXPORT_SYMBOL(__sk_mem_reclaim);
int sk_set_peek_off(struct sock *sk, int val)
@@ -2436,8 +2469,11 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_type = sock->type;
sk->sk_wq = sock->wq;
sock->sk = sk;
- } else
+ sk->sk_uid = SOCK_INODE(sock)->i_uid;
+ } else {
sk->sk_wq = NULL;
+ sk->sk_uid = make_kuid(sock_net(sk)->user_ns, 0);
+ }
rwlock_init(&sk->sk_callback_lock);
lockdep_set_class_and_name(&sk->sk_callback_lock,
diff --git a/net/core/stream.c b/net/core/stream.c
index 1086c8b280a8..f575bcf64af2 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -53,8 +53,8 @@ void sk_stream_write_space(struct sock *sk)
*/
int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct task_struct *tsk = current;
- DEFINE_WAIT(wait);
int done;
do {
@@ -68,13 +68,13 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
if (signal_pending(tsk))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
sk->sk_write_pending++;
done = sk_wait_event(sk, timeo_p,
!sk->sk_err &&
!((1 << sk->sk_state) &
- ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
- finish_wait(sk_sleep(sk), &wait);
+ ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
sk->sk_write_pending--;
} while (!done);
return 0;
@@ -94,16 +94,16 @@ static inline int sk_stream_closing(struct sock *sk)
void sk_stream_wait_close(struct sock *sk, long timeout)
{
if (timeout) {
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+ add_wait_queue(sk_sleep(sk), &wait);
do {
- prepare_to_wait(sk_sleep(sk), &wait,
- TASK_INTERRUPTIBLE);
- if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk)))
+ if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk), &wait))
break;
} while (!signal_pending(current) && timeout);
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
}
}
EXPORT_SYMBOL(sk_stream_wait_close);
@@ -119,16 +119,16 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
long vm_wait = 0;
long current_timeo = *timeo_p;
bool noblock = (*timeo_p ? false : true);
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
if (sk_stream_memory_free(sk))
current_timeo = vm_wait = (prandom_u32() % (HZ / 5)) + 2;
+ add_wait_queue(sk_sleep(sk), &wait);
+
while (1) {
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
goto do_error;
if (!*timeo_p) {
@@ -147,7 +147,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
sk_wait_event(sk, &current_timeo, sk->sk_err ||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
(sk_stream_memory_free(sk) &&
- !vm_wait));
+ !vm_wait), &wait);
sk->sk_write_pending--;
if (vm_wait) {
@@ -161,7 +161,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
*timeo_p = current_timeo;
}
out:
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return err;
do_error:
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 0df2aa652530..2a46e4009f62 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -79,10 +79,13 @@ static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
if (sock_table != orig_sock_table) {
rcu_assign_pointer(rps_sock_flow_table, sock_table);
- if (sock_table)
+ if (sock_table) {
static_key_slow_inc(&rps_needed);
+ static_key_slow_inc(&rfs_needed);
+ }
if (orig_sock_table) {
static_key_slow_dec(&rps_needed);
+ static_key_slow_dec(&rfs_needed);
synchronize_rcu();
vfree(orig_sock_table);
}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index edbe59d203ef..d859a5c36e70 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -590,13 +590,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (inet_csk_reqsk_queue_is_full(sk))
goto drop;
- /*
- * Accept backlog is full. If we have already queued enough
- * of warm entries in syn queue, drop request. It is better than
- * clogging syn queue with openreqs with exponentially increasing
- * timeout.
- */
- if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+ if (sk_acceptq_is_full(sk))
goto drop;
req = inet_reqsk_alloc(&dccp_request_sock_ops, sk, true);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 715e5d1dc107..adfc790f7193 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -326,7 +326,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (inet_csk_reqsk_queue_is_full(sk))
goto drop;
- if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+ if (sk_acceptq_is_full(sk))
goto drop;
req = inet_reqsk_alloc(&dccp6_request_sock_ops, sk, true);
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 13d6b1a6e0fc..a90ed67027b0 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1718,7 +1718,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
* See if there is data ready to read, sleep if there isn't
*/
for(;;) {
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
if (sk->sk_err)
goto out;
@@ -1749,11 +1749,11 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
goto out;
}
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target));
+ sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
}
skb_queue_walk_safe(queue, skb, n) {
@@ -1999,19 +1999,19 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
* size.
*/
if (dn_queue_too_long(scp, queue, flags)) {
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
if (flags & MSG_DONTWAIT) {
err = -EWOULDBLOCK;
goto out;
}
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
sk_wait_event(sk, &timeo,
- !dn_queue_too_long(scp, queue, flags));
+ !dn_queue_too_long(scp, queue, flags), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
continue;
}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 30e2e21d7619..68c9eea00518 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -641,7 +641,8 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
/* ethtool operations *******************************************************/
static int
-dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct dsa_slave_priv *p = netdev_priv(dev);
int err;
@@ -650,19 +651,20 @@ dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (p->phy != NULL) {
err = phy_read_status(p->phy);
if (err == 0)
- err = phy_ethtool_gset(p->phy, cmd);
+ err = phy_ethtool_ksettings_get(p->phy, cmd);
}
return err;
}
static int
-dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct dsa_slave_priv *p = netdev_priv(dev);
if (p->phy != NULL)
- return phy_ethtool_sset(p->phy, cmd);
+ return phy_ethtool_ksettings_set(p->phy, cmd);
return -EOPNOTSUPP;
}
@@ -990,8 +992,6 @@ void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
}
static const struct ethtool_ops dsa_slave_ethtool_ops = {
- .get_settings = dsa_slave_get_settings,
- .set_settings = dsa_slave_set_settings,
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
.get_regs = dsa_slave_get_regs,
@@ -1007,6 +1007,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_wol = dsa_slave_get_wol,
.set_eee = dsa_slave_set_eee,
.get_eee = dsa_slave_get_eee,
+ .get_link_ksettings = dsa_slave_get_link_ksettings,
+ .set_link_ksettings = dsa_slave_set_link_ksettings,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
@@ -1250,6 +1252,8 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
slave_dev->priv_flags |= IFF_NO_QUEUE;
slave_dev->netdev_ops = &dsa_slave_netdev_ops;
slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
+ slave_dev->min_mtu = 0;
+ slave_dev->max_mtu = ETH_MAX_MTU;
SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 02acfff36028..8c5a479681ca 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -62,6 +62,7 @@
#include <net/dsa.h>
#include <net/flow_dissector.h>
#include <linux/uaccess.h>
+#include <net/pkt_sched.h>
__setup("ether=", netdev_boot_setup);
@@ -322,8 +323,7 @@ EXPORT_SYMBOL(eth_mac_addr);
*/
int eth_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
- return -EINVAL;
+ netdev_warn(dev, "%s is deprecated\n", __func__);
dev->mtu = new_mtu;
return 0;
}
@@ -357,8 +357,10 @@ void ether_setup(struct net_device *dev)
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
- dev->tx_queue_len = 1000; /* Ethernet wants good queues */
+ dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
dev->priv_flags |= IFF_TX_SKB_SHARING;
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 16737cd8dae8..fc65b145f6e7 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -398,6 +398,7 @@ void hsr_dev_setup(struct net_device *dev)
random_ether_addr(dev->dev_addr);
ether_setup(dev);
+ dev->min_mtu = 0;
dev->header_ops = &hsr_header_ops;
dev->netdev_ops = &hsr_device_ops;
SET_NETDEV_DEVTYPE(dev, &hsr_type);
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index d4d1617f43a8..1ab30e7d3f99 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -131,13 +131,7 @@ static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = {
[HSR_A_IF2_SEQ] = { .type = NLA_U16 },
};
-static struct genl_family hsr_genl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = "HSR",
- .version = 1,
- .maxattr = HSR_A_MAX,
-};
+static struct genl_family hsr_genl_family;
static const struct genl_multicast_group hsr_mcgrps[] = {
{ .name = "hsr-network", },
@@ -467,6 +461,18 @@ static const struct genl_ops hsr_ops[] = {
},
};
+static struct genl_family hsr_genl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = "HSR",
+ .version = 1,
+ .maxattr = HSR_A_MAX,
+ .module = THIS_MODULE,
+ .ops = hsr_ops,
+ .n_ops = ARRAY_SIZE(hsr_ops),
+ .mcgrps = hsr_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(hsr_mcgrps),
+};
+
int __init hsr_netlink_init(void)
{
int rc;
@@ -475,8 +481,7 @@ int __init hsr_netlink_init(void)
if (rc)
goto fail_rtnl_link_register;
- rc = genl_register_family_with_ops_groups(&hsr_genl_family, hsr_ops,
- hsr_mcgrps);
+ rc = genl_register_family(&hsr_genl_family);
if (rc)
goto fail_genl_register_family;
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index c8133c07ceee..6bde9e5a5503 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -28,14 +28,6 @@
static unsigned int ieee802154_seq_num;
static DEFINE_SPINLOCK(ieee802154_seq_lock);
-struct genl_family nl802154_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = IEEE802154_NL_NAME,
- .version = 1,
- .maxattr = IEEE802154_ATTR_MAX,
-};
-
/* Requests to userspace */
struct sk_buff *ieee802154_nl_create(int flags, u8 req)
{
@@ -139,11 +131,21 @@ static const struct genl_multicast_group ieee802154_mcgrps[] = {
[IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
};
+struct genl_family nl802154_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = IEEE802154_NL_NAME,
+ .version = 1,
+ .maxattr = IEEE802154_ATTR_MAX,
+ .module = THIS_MODULE,
+ .ops = ieee8021154_ops,
+ .n_ops = ARRAY_SIZE(ieee8021154_ops),
+ .mcgrps = ieee802154_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(ieee802154_mcgrps),
+};
+
int __init ieee802154_nl_init(void)
{
- return genl_register_family_with_ops_groups(&nl802154_family,
- ieee8021154_ops,
- ieee802154_mcgrps);
+ return genl_register_family(&nl802154_family);
}
void ieee802154_nl_exit(void)
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 77d73014bde3..dc2960be51e0 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -286,9 +286,12 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info)
if (name[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] != '\0')
return -EINVAL; /* name should be null-terminated */
+ rc = -ENODEV;
dev = dev_get_by_name(genl_info_net(info), name);
if (!dev)
- return -ENODEV;
+ return rc;
+ if (dev->type != ARPHRD_IEEE802154)
+ goto out;
phy = dev->ieee802154_ptr->wpan_phy;
BUG_ON(!phy);
@@ -342,6 +345,7 @@ nla_put_failure:
nlmsg_free(msg);
out_dev:
wpan_phy_put(phy);
+out:
if (dev)
dev_put(dev);
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index d90a4ed5b8a0..fc60cd061f39 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -26,23 +26,8 @@
#include "rdev-ops.h"
#include "core.h"
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-
/* the netlink family */
-static struct genl_family nl802154_fam = {
- .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
- .name = NL802154_GENL_NAME, /* have users key off the name instead */
- .hdrsize = 0, /* no private header */
- .version = 1, /* no particular meaning now */
- .maxattr = NL802154_ATTR_MAX,
- .netnsok = true,
- .pre_doit = nl802154_pre_doit,
- .post_doit = nl802154_post_doit,
-};
+static struct genl_family nl802154_fam;
/* multicast groups */
enum nl802154_multicast_groups {
@@ -263,13 +248,14 @@ nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
if (!cb->args[0]) {
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
- nl802154_fam.attrbuf, nl802154_fam.maxattr,
+ genl_family_attrbuf(&nl802154_fam),
+ nl802154_fam.maxattr,
nl802154_policy);
if (err)
goto out_unlock;
*wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
- nl802154_fam.attrbuf);
+ genl_family_attrbuf(&nl802154_fam));
if (IS_ERR(*wpan_dev)) {
err = PTR_ERR(*wpan_dev);
goto out_unlock;
@@ -575,7 +561,7 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
struct netlink_callback *cb,
struct nl802154_dump_wpan_phy_state *state)
{
- struct nlattr **tb = nl802154_fam.attrbuf;
+ struct nlattr **tb = genl_family_attrbuf(&nl802154_fam);
int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
tb, nl802154_fam.maxattr, nl802154_policy);
@@ -2476,11 +2462,25 @@ static const struct genl_ops nl802154_ops[] = {
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
};
+static struct genl_family nl802154_fam __ro_after_init = {
+ .name = NL802154_GENL_NAME, /* have users key off the name instead */
+ .hdrsize = 0, /* no private header */
+ .version = 1, /* no particular meaning now */
+ .maxattr = NL802154_ATTR_MAX,
+ .netnsok = true,
+ .pre_doit = nl802154_pre_doit,
+ .post_doit = nl802154_post_doit,
+ .module = THIS_MODULE,
+ .ops = nl802154_ops,
+ .n_ops = ARRAY_SIZE(nl802154_ops),
+ .mcgrps = nl802154_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(nl802154_mcgrps),
+};
+
/* initialisation/exit functions */
-int nl802154_init(void)
+int __init nl802154_init(void)
{
- return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
- nl802154_mcgrps);
+ return genl_register_family(&nl802154_fam);
}
void nl802154_exit(void)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index b54b3ca939db..6e7baaf814c6 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -430,6 +430,14 @@ config INET_UDP_DIAG
Support for UDP socket monitoring interface used by the ss tool.
If unsure, say Y.
+config INET_RAW_DIAG
+ tristate "RAW: socket monitoring interface"
+ depends on INET_DIAG && (IPV6 || IPV6=n)
+ default n
+ ---help---
+ Support for RAW socket monitoring interface used by the ss tool.
+ If unsure, say Y.
+
config INET_DIAG_DESTROY
bool "INET: allow privileged process to administratively close sockets"
depends on INET_DIAG
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index bc6a6c8b9bcd..48af58a5686e 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
obj-$(CONFIG_INET_DIAG) += inet_diag.o
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
+obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o
obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 215143246e4b..1830e6f0e9cc 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -374,8 +374,18 @@ lookup_protocol:
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);
- if (err)
+ if (err) {
+ sk_common_release(sk);
+ goto out;
+ }
+ }
+
+ if (!kern) {
+ err = BPF_CGROUP_RUN_PROG_INET_SOCK(sk);
+ if (err) {
sk_common_release(sk);
+ goto out;
+ }
}
out:
return err;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 161fc0f0d752..dbad5a1c161a 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -620,6 +620,7 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
[RTA_FLOW] = { .type = NLA_U32 },
[RTA_ENCAP_TYPE] = { .type = NLA_U16 },
[RTA_ENCAP] = { .type = NLA_NESTED },
+ [RTA_UID] = { .type = NLA_U32 },
};
static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
@@ -1218,6 +1219,8 @@ static int __net_init ip_fib_net_init(struct net *net)
int err;
size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ;
+ net->ipv4.fib_seq = 0;
+
/* Avoid false sharing : Use at least a full cache line */
size = max_t(size_t, size, L1_CACHE_BYTES);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 388d3e21629b..c1bc1e92de0e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -234,6 +234,7 @@ void free_fib_info(struct fib_info *fi)
#endif
call_rcu(&fi->rcu, free_fib_info_rcu);
}
+EXPORT_SYMBOL_GPL(free_fib_info);
void fib_release_info(struct fib_info *fi)
{
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index e3665bf7a7f3..1b0e7d1f5217 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -84,25 +84,114 @@
#include <trace/events/fib.h>
#include "fib_lookup.h"
-static BLOCKING_NOTIFIER_HEAD(fib_chain);
+static unsigned int fib_seq_sum(void)
+{
+ unsigned int fib_seq = 0;
+ struct net *net;
+
+ rtnl_lock();
+ for_each_net(net)
+ fib_seq += net->ipv4.fib_seq;
+ rtnl_unlock();
+
+ return fib_seq;
+}
+
+static ATOMIC_NOTIFIER_HEAD(fib_chain);
-int register_fib_notifier(struct notifier_block *nb)
+static int call_fib_notifier(struct notifier_block *nb, struct net *net,
+ enum fib_event_type event_type,
+ struct fib_notifier_info *info)
{
- return blocking_notifier_chain_register(&fib_chain, nb);
+ info->net = net;
+ return nb->notifier_call(nb, event_type, info);
+}
+
+static void fib_rules_notify(struct net *net, struct notifier_block *nb,
+ enum fib_event_type event_type)
+{
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_notifier_info info;
+
+ if (net->ipv4.fib_has_custom_rules)
+ call_fib_notifier(nb, net, event_type, &info);
+#endif
+}
+
+static void fib_notify(struct net *net, struct notifier_block *nb,
+ enum fib_event_type event_type);
+
+static int call_fib_entry_notifier(struct notifier_block *nb, struct net *net,
+ enum fib_event_type event_type, u32 dst,
+ int dst_len, struct fib_info *fi,
+ u8 tos, u8 type, u32 tb_id, u32 nlflags)
+{
+ struct fib_entry_notifier_info info = {
+ .dst = dst,
+ .dst_len = dst_len,
+ .fi = fi,
+ .tos = tos,
+ .type = type,
+ .tb_id = tb_id,
+ .nlflags = nlflags,
+ };
+ return call_fib_notifier(nb, net, event_type, &info.info);
+}
+
+static bool fib_dump_is_consistent(struct notifier_block *nb,
+ void (*cb)(struct notifier_block *nb),
+ unsigned int fib_seq)
+{
+ atomic_notifier_chain_register(&fib_chain, nb);
+ if (fib_seq == fib_seq_sum())
+ return true;
+ atomic_notifier_chain_unregister(&fib_chain, nb);
+ if (cb)
+ cb(nb);
+ return false;
+}
+
+#define FIB_DUMP_MAX_RETRIES 5
+int register_fib_notifier(struct notifier_block *nb,
+ void (*cb)(struct notifier_block *nb))
+{
+ int retries = 0;
+
+ do {
+ unsigned int fib_seq = fib_seq_sum();
+ struct net *net;
+
+ /* Mutex semantics guarantee that every change done to
+ * FIB tries before we read the change sequence counter
+ * is now visible to us.
+ */
+ rcu_read_lock();
+ for_each_net_rcu(net) {
+ fib_rules_notify(net, nb, FIB_EVENT_RULE_ADD);
+ fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
+ }
+ rcu_read_unlock();
+
+ if (fib_dump_is_consistent(nb, cb, fib_seq))
+ return 0;
+ } while (++retries < FIB_DUMP_MAX_RETRIES);
+
+ return -EBUSY;
}
EXPORT_SYMBOL(register_fib_notifier);
int unregister_fib_notifier(struct notifier_block *nb)
{
- return blocking_notifier_chain_unregister(&fib_chain, nb);
+ return atomic_notifier_chain_unregister(&fib_chain, nb);
}
EXPORT_SYMBOL(unregister_fib_notifier);
int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
struct fib_notifier_info *info)
{
+ net->ipv4.fib_seq++;
info->net = net;
- return blocking_notifier_call_chain(&fib_chain, event_type, info);
+ return atomic_notifier_call_chain(&fib_chain, event_type, info);
}
static int call_fib_entry_notifiers(struct net *net,
@@ -1903,6 +1992,62 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
return found;
}
+static void fib_leaf_notify(struct net *net, struct key_vector *l,
+ struct fib_table *tb, struct notifier_block *nb,
+ enum fib_event_type event_type)
+{
+ struct fib_alias *fa;
+
+ hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
+ struct fib_info *fi = fa->fa_info;
+
+ if (!fi)
+ continue;
+
+ /* local and main table can share the same trie,
+ * so don't notify twice for the same entry.
+ */
+ if (tb->tb_id != fa->tb_id)
+ continue;
+
+ call_fib_entry_notifier(nb, net, event_type, l->key,
+ KEYLENGTH - fa->fa_slen, fi, fa->fa_tos,
+ fa->fa_type, fa->tb_id, 0);
+ }
+}
+
+static void fib_table_notify(struct net *net, struct fib_table *tb,
+ struct notifier_block *nb,
+ enum fib_event_type event_type)
+{
+ struct trie *t = (struct trie *)tb->tb_data;
+ struct key_vector *l, *tp = t->kv;
+ t_key key = 0;
+
+ while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
+ fib_leaf_notify(net, l, tb, nb, event_type);
+
+ key = l->key + 1;
+ /* stop in case of wrap around */
+ if (key < l->key)
+ break;
+ }
+}
+
+static void fib_notify(struct net *net, struct notifier_block *nb,
+ enum fib_event_type event_type)
+{
+ unsigned int h;
+
+ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+ struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+ struct fib_table *tb;
+
+ hlist_for_each_entry_rcu(tb, head, tb_hlist)
+ fib_table_notify(net, tb, nb, event_type);
+ }
+}
+
static void __trie_free_rcu(struct rcu_head *head)
{
struct fib_table *tb = container_of(head, struct fib_table, rcu);
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 030d1531e897..805f6607f8d9 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -622,14 +622,7 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg)
return err;
}
-static struct genl_family fou_nl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = FOU_GENL_NAME,
- .version = FOU_GENL_VERSION,
- .maxattr = FOU_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family fou_nl_family;
static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
[FOU_ATTR_PORT] = { .type = NLA_U16, },
@@ -831,6 +824,17 @@ static const struct genl_ops fou_nl_ops[] = {
},
};
+static struct genl_family fou_nl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = FOU_GENL_NAME,
+ .version = FOU_GENL_VERSION,
+ .maxattr = FOU_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = fou_nl_ops,
+ .n_ops = ARRAY_SIZE(fou_nl_ops),
+};
+
size_t fou_encap_hlen(struct ip_tunnel_encap *e)
{
return sizeof(struct udphdr);
@@ -1086,8 +1090,7 @@ static int __init fou_init(void)
if (ret)
goto exit;
- ret = genl_register_family_with_ops(&fou_nl_family,
- fou_nl_ops);
+ ret = genl_register_family(&fou_nl_family);
if (ret < 0)
goto unregister;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 48734ee6293f..f79d7a8ab1c6 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -425,6 +425,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
fl4.daddr = daddr;
fl4.saddr = saddr;
fl4.flowi4_mark = mark;
+ fl4.flowi4_uid = sock_net_uid(net, NULL);
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_proto = IPPROTO_ICMP;
fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev);
@@ -473,6 +474,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
param->replyopts.opt.opt.faddr : iph->saddr);
fl4->saddr = saddr;
fl4->flowi4_mark = mark;
+ fl4->flowi4_uid = sock_net_uid(net, NULL);
fl4->flowi4_tos = RT_TOS(tos);
fl4->flowi4_proto = IPPROTO_ICMP;
fl4->fl4_icmp_type = type;
@@ -1045,12 +1047,12 @@ int icmp_rcv(struct sk_buff *skb)
if (success) {
consume_skb(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
drop:
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
csum_error:
__ICMP_INC_STATS(net, ICMP_MIB_CSUMERRORS);
error:
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 61a9deec2993..d5d3ead0a6c3 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -415,7 +415,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port,
- htons(ireq->ir_num));
+ htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt))
@@ -452,7 +452,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port,
- htons(ireq->ir_num));
+ htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt))
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index e4d16fc5bbb3..4dea33e5f295 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -200,6 +200,15 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
goto errout;
+ /*
+ * RAW sockets might have user-defined protocols assigned,
+ * so report the one supplied on socket creation.
+ */
+ if (sk->sk_type == SOCK_RAW) {
+ if (nla_put_u8(skb, INET_DIAG_PROTOCOL, sk->sk_protocol))
+ goto errout;
+ }
+
if (!icsk) {
handler->idiag_get_info(sk, r, NULL);
goto out;
@@ -852,10 +861,11 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
struct netlink_callback *cb,
const struct inet_diag_req_v2 *r, struct nlattr *bc)
{
+ bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
struct net *net = sock_net(skb->sk);
- int i, num, s_i, s_num;
u32 idiag_states = r->idiag_states;
- bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
+ int i, num, s_i, s_num;
+ struct sock *sk;
if (idiag_states & TCPF_SYN_RECV)
idiag_states |= TCPF_NEW_SYN_RECV;
@@ -863,16 +873,15 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
s_num = num = cb->args[2];
if (cb->args[0] == 0) {
- if (!(idiag_states & TCPF_LISTEN))
+ if (!(idiag_states & TCPF_LISTEN) || r->id.idiag_dport)
goto skip_listen_ht;
for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
struct inet_listen_hashbucket *ilb;
- struct sock *sk;
num = 0;
ilb = &hashinfo->listening_hash[i];
- spin_lock_bh(&ilb->lock);
+ spin_lock(&ilb->lock);
sk_for_each(sk, &ilb->head) {
struct inet_sock *inet = inet_sk(sk);
@@ -892,26 +901,18 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
r->id.idiag_sport)
goto next_listen;
- if (r->id.idiag_dport ||
- cb->args[3] > 0)
- goto next_listen;
-
if (inet_csk_diag_dump(sk, skb, cb, r,
bc, net_admin) < 0) {
- spin_unlock_bh(&ilb->lock);
+ spin_unlock(&ilb->lock);
goto done;
}
next_listen:
- cb->args[3] = 0;
- cb->args[4] = 0;
++num;
}
- spin_unlock_bh(&ilb->lock);
+ spin_unlock(&ilb->lock);
s_num = 0;
- cb->args[3] = 0;
- cb->args[4] = 0;
}
skip_listen_ht:
cb->args[0] = 1;
@@ -921,13 +922,14 @@ skip_listen_ht:
if (!(idiag_states & ~TCPF_LISTEN))
goto out;
+#define SKARR_SZ 16
for (i = s_i; i <= hashinfo->ehash_mask; i++) {
struct inet_ehash_bucket *head = &hashinfo->ehash[i];
spinlock_t *lock = inet_ehash_lockp(hashinfo, i);
struct hlist_nulls_node *node;
- struct sock *sk;
-
- num = 0;
+ struct sock *sk_arr[SKARR_SZ];
+ int num_arr[SKARR_SZ];
+ int idx, accum, res;
if (hlist_nulls_empty(&head->chain))
continue;
@@ -935,9 +937,12 @@ skip_listen_ht:
if (i > s_i)
s_num = 0;
+next_chunk:
+ num = 0;
+ accum = 0;
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &head->chain) {
- int state, res;
+ int state;
if (!net_eq(sock_net(sk), net))
continue;
@@ -961,21 +966,35 @@ skip_listen_ht:
if (!inet_diag_bc_sk(bc, sk))
goto next_normal;
- res = sk_diag_fill(sk, skb, r,
+ sock_hold(sk);
+ num_arr[accum] = num;
+ sk_arr[accum] = sk;
+ if (++accum == SKARR_SZ)
+ break;
+next_normal:
+ ++num;
+ }
+ spin_unlock_bh(lock);
+ res = 0;
+ for (idx = 0; idx < accum; idx++) {
+ if (res >= 0) {
+ res = sk_diag_fill(sk_arr[idx], skb, r,
sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
cb->nlh, net_admin);
- if (res < 0) {
- spin_unlock_bh(lock);
- goto done;
+ if (res < 0)
+ num = num_arr[idx];
}
-next_normal:
- ++num;
+ sock_gen_put(sk_arr[idx]);
}
-
- spin_unlock_bh(lock);
+ if (res < 0)
+ break;
cond_resched();
+ if (accum == SKARR_SZ) {
+ s_num = num + 1;
+ goto next_chunk;
+ }
}
done:
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 576f705d8180..78fd62048335 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -113,8 +113,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
static int ipgre_tunnel_init(struct net_device *dev);
-static int ipgre_net_id __read_mostly;
-static int gre_tap_net_id __read_mostly;
+static unsigned int ipgre_net_id __read_mostly;
+static unsigned int gre_tap_net_id __read_mostly;
static void ipgre_err(struct sk_buff *skb, u32 info,
const struct tnl_ptk_info *tpi)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 877bdb02e887..9ffc2625cddd 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -74,6 +74,7 @@
#include <net/checksum.h>
#include <net/inetpeer.h>
#include <net/lwtunnel.h>
+#include <linux/bpf-cgroup.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_bridge.h>
@@ -287,6 +288,13 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
unsigned int mtu;
+ int ret;
+
+ ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
/* Policy lookup after SNAT yielded a new policy */
@@ -305,6 +313,20 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk
return ip_finish_output2(net, sk, skb);
}
+static int ip_mc_finish_output(struct net *net, struct sock *sk,
+ struct sk_buff *skb)
+{
+ int ret;
+
+ ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ return dev_loopback_xmit(net, sk, skb);
+}
+
int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct rtable *rt = skb_rtable(skb);
@@ -342,7 +364,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
if (newskb)
NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,
net, sk, newskb, NULL, newskb->dev,
- dev_loopback_xmit);
+ ip_mc_finish_output);
}
/* Multicasts with ttl 0 must not go beyond the host */
@@ -358,7 +380,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
if (newskb)
NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,
net, sk, newskb, NULL, newskb->dev,
- dev_loopback_xmit);
+ ip_mc_finish_output);
}
return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
@@ -583,7 +605,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
*/
if (skb_has_frag_list(skb)) {
struct sk_buff *frag, *frag2;
- int first_len = skb_pagelen(skb);
+ unsigned int first_len = skb_pagelen(skb);
if (first_len - hlen > mtu ||
((first_len - hlen) & 7) ||
@@ -1594,7 +1616,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,
ip_reply_arg_flowi_flags(arg),
daddr, saddr,
- tcp_hdr(skb)->source, tcp_hdr(skb)->dest);
+ tcp_hdr(skb)->source, tcp_hdr(skb)->dest,
+ arg->uid);
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index b8a2d63d1fb8..8b13881ed064 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -97,6 +97,17 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
}
+static void ip_cmsg_recv_fragsize(struct msghdr *msg, struct sk_buff *skb)
+{
+ int val;
+
+ if (IPCB(skb)->frag_max_size == 0)
+ return;
+
+ val = IPCB(skb)->frag_max_size;
+ put_cmsg(msg, SOL_IP, IP_RECVFRAGSIZE, sizeof(val), &val);
+}
+
static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
int tlen, int offset)
{
@@ -153,10 +164,10 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
put_cmsg(msg, SOL_IP, IP_ORIGDSTADDR, sizeof(sin), &sin);
}
-void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
- int tlen, int offset)
+void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb, int tlen, int offset)
{
- struct inet_sock *inet = inet_sk(skb->sk);
+ struct inet_sock *inet = inet_sk(sk);
unsigned int flags = inet->cmsg_flags;
/* Ordered by supposed usage frequency */
@@ -218,6 +229,9 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
if (flags & IP_CMSG_CHECKSUM)
ip_cmsg_recv_checksum(msg, skb, tlen, offset);
+
+ if (flags & IP_CMSG_RECVFRAGSIZE)
+ ip_cmsg_recv_fragsize(msg, skb);
}
EXPORT_SYMBOL(ip_cmsg_recv_offset);
@@ -614,6 +628,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
case IP_MULTICAST_LOOP:
case IP_RECVORIGDSTADDR:
case IP_CHECKSUM:
+ case IP_RECVFRAGSIZE:
if (optlen >= sizeof(int)) {
if (get_user(val, (int __user *) optval))
return -EFAULT;
@@ -726,6 +741,14 @@ static int do_ip_setsockopt(struct sock *sk, int level,
}
}
break;
+ case IP_RECVFRAGSIZE:
+ if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
+ goto e_inval;
+ if (val)
+ inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE;
+ else
+ inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
+ break;
case IP_TOS: /* This sets both TOS and Precedence */
if (sk->sk_type == SOCK_STREAM) {
val &= ~INET_ECN_MASK;
@@ -1357,6 +1380,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
case IP_CHECKSUM:
val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0;
break;
+ case IP_RECVFRAGSIZE:
+ val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0;
+ break;
case IP_TOS:
val = inet->tos;
break;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 5719d6ba0824..823abaef006b 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -358,6 +358,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
{
struct ip_tunnel *nt;
struct net_device *dev;
+ int t_hlen;
BUG_ON(!itn->fb_tunnel_dev);
dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
@@ -367,6 +368,9 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
dev->mtu = ip_tunnel_bind_dev(dev);
nt = netdev_priv(dev);
+ t_hlen = nt->hlen + sizeof(struct iphdr);
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
ip_tunnel_add(itn, nt);
return nt;
}
@@ -929,7 +933,7 @@ int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
- if (new_mtu < 68)
+ if (new_mtu < ETH_MIN_MTU)
return -EINVAL;
if (new_mtu > max_mtu) {
@@ -990,7 +994,7 @@ int ip_tunnel_get_iflink(const struct net_device *dev)
}
EXPORT_SYMBOL(ip_tunnel_get_iflink);
-int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
+int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname)
{
struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
@@ -1192,7 +1196,7 @@ void ip_tunnel_uninit(struct net_device *dev)
EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
/* Do least required initialization, rest of init is done in tunnel_init call */
-void ip_tunnel_setup(struct net_device *dev, int net_id)
+void ip_tunnel_setup(struct net_device *dev, unsigned int net_id)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
tunnel->ip_tnl_net_id = net_id;
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 5d7944f394d9..8b14f1404c8f 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -46,7 +46,7 @@
static struct rtnl_link_ops vti_link_ops __read_mostly;
-static int vti_net_id __read_mostly;
+static unsigned int vti_net_id __read_mostly;
static int vti_tunnel_init(struct net_device *dev);
static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index c9392589c415..79489f017854 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -121,7 +121,7 @@ static bool log_ecn_error = true;
module_param(log_ecn_error, bool, 0644);
MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
-static int ipip_net_id __read_mostly;
+static unsigned int ipip_net_id __read_mostly;
static int ipip_tunnel_init(struct net_device *dev);
static struct rtnl_link_ops ipip_link_ops __read_mostly;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 27089f5ebbb1..665505d86b12 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -137,6 +137,9 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
.flags = FIB_LOOKUP_NOREF,
};
+ /* update flow if oif or iif point to device enslaved to l3mdev */
+ l3mdev_update_flow(net, flowi4_to_flowi(flp4));
+
err = fib_rules_lookup(net->ipv4.mr_rules_ops,
flowi4_to_flowi(flp4), 0, &arg);
if (err < 0)
@@ -163,7 +166,9 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
return -EINVAL;
}
- mrt = ipmr_get_table(rule->fr_net, rule->table);
+ arg->table = fib_rule_get_table(rule, arg);
+
+ mrt = ipmr_get_table(rule->fr_net, arg->table);
if (!mrt)
return -EAGAIN;
res->mrt = mrt;
@@ -1809,6 +1814,12 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
/* Wrong interface: drop packet and (maybe) send PIM assert. */
if (mrt->vif_table[vif].dev != skb->dev) {
+ struct net_device *mdev;
+
+ mdev = l3mdev_master_dev_rcu(mrt->vif_table[vif].dev);
+ if (mdev == skb->dev)
+ goto forward;
+
if (rt_is_output_route(skb_rtable(skb))) {
/* It is our own packet, looped back.
* Very complicated situation...
@@ -2053,7 +2064,7 @@ static int pim_rcv(struct sk_buff *skb)
goto drop;
pim = (struct pimreghdr *)skb_transport_header(skb);
- if (pim->type != ((PIM_VERSION << 4) | (PIM_REGISTER)) ||
+ if (pim->type != ((PIM_VERSION << 4) | (PIM_TYPE_REGISTER)) ||
(pim->flags & PIM_NULL_REGISTER) ||
(ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
csum_fold(skb_checksum(skb, 0, skb->len, 0))))
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d613309e3e5d..c11eb1744ab1 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -25,6 +25,12 @@ config NF_CONNTRACK_IPV4
To compile it as a module, choose M here. If unsure, say N.
+config NF_SOCKET_IPV4
+ tristate "IPv4 socket lookup support"
+ help
+ This option enables the IPv4 socket lookup infrastructure. This is
+ is required by the iptables socket match.
+
if NF_TABLES
config NF_TABLES_IPV4
@@ -54,6 +60,14 @@ config NFT_DUP_IPV4
help
This module enables IPv4 packet duplication support for nf_tables.
+config NFT_FIB_IPV4
+ select NFT_FIB
+ tristate "nf_tables fib / ip route lookup support"
+ help
+ This module enables IPv4 FIB lookups, e.g. for reverse path filtering.
+ It also allows query of the FIB for the route type, e.g. local, unicast,
+ multicast or blackhole.
+
endif # NF_TABLES_IPV4
config NF_TABLES_ARP
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 853328f8fd05..f462fee66ac8 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -14,6 +14,8 @@ obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
# defrag
obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
+obj-$(CONFIG_NF_SOCKET_IPV4) += nf_socket_ipv4.o
+
# logging
obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o
obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
+obj-$(CONFIG_NFT_FIB_IPV4) += nft_fib_ipv4.o
obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o
obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redir_ipv4.o
obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 697538464e6e..1258a9ab62ef 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -217,11 +217,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
*/
e = get_entry(table_base, private->hook_entry[hook]);
- acpar.net = state->net;
- acpar.in = state->in;
- acpar.out = state->out;
- acpar.hooknum = hook;
- acpar.family = NFPROTO_ARP;
+ acpar.state = state;
acpar.hotdrop = false;
arp = arp_hdr(skb);
@@ -415,17 +411,15 @@ static inline int check_target(struct arpt_entry *e, const char *name)
}
static inline int
-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
+find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+ struct xt_percpu_counter_alloc_state *alloc_state)
{
struct xt_entry_target *t;
struct xt_target *target;
- unsigned long pcnt;
int ret;
- pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(pcnt))
+ if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
return -ENOMEM;
- e->counters.pcnt = pcnt;
t = arpt_get_target(e);
target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
@@ -443,7 +437,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
err:
module_put(t->u.kernel.target->me);
out:
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
return ret;
}
@@ -523,7 +517,7 @@ static inline void cleanup_entry(struct arpt_entry *e)
if (par.target->destroy != NULL)
par.target->destroy(&par);
module_put(par.target->me);
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
}
/* Checks and translates the user-supplied table segment (held in
@@ -532,6 +526,7 @@ static inline void cleanup_entry(struct arpt_entry *e)
static int translate_table(struct xt_table_info *newinfo, void *entry0,
const struct arpt_replace *repl)
{
+ struct xt_percpu_counter_alloc_state alloc_state = { 0 };
struct arpt_entry *iter;
unsigned int *offsets;
unsigned int i;
@@ -594,7 +589,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
/* Finally, each sanity check must pass */
i = 0;
xt_entry_foreach(iter, entry0, newinfo->size) {
- ret = find_check_entry(iter, repl->name, repl->size);
+ ret = find_check_entry(iter, repl->name, repl->size,
+ &alloc_state);
if (ret != 0)
break;
++i;
@@ -809,7 +805,7 @@ static int get_info(struct net *net, void __user *user,
#endif
t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
"arptable_%s", name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
struct arpt_getinfo info;
const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT
@@ -838,7 +834,7 @@ static int get_info(struct net *net, void __user *user,
xt_table_unlock(t);
module_put(t->me);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
#ifdef CONFIG_COMPAT
if (compat)
xt_compat_unlock(NFPROTO_ARP);
@@ -863,7 +859,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
const struct xt_table_info *private = t->private;
if (get.size == private->size)
@@ -875,7 +871,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
return ret;
}
@@ -902,8 +898,8 @@ static int __do_replace(struct net *net, const char *name,
t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
"arptable_%s", name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free_newinfo_counters_untrans;
}
@@ -1018,8 +1014,8 @@ static int do_add_counters(struct net *net, const void __user *user,
return PTR_ERR(paddc);
t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free;
}
@@ -1408,7 +1404,7 @@ static int compat_get_entries(struct net *net,
xt_compat_lock(NFPROTO_ARP);
t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
const struct xt_table_info *private = t->private;
struct xt_table_info info;
@@ -1423,7 +1419,7 @@ static int compat_get_entries(struct net *net,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
xt_compat_unlock(NFPROTO_ARP);
return ret;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7c00ce90adb8..308b456723f0 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -261,11 +261,7 @@ ipt_do_table(struct sk_buff *skb,
acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
acpar.thoff = ip_hdrlen(skb);
acpar.hotdrop = false;
- acpar.net = state->net;
- acpar.in = state->in;
- acpar.out = state->out;
- acpar.family = NFPROTO_IPV4;
- acpar.hooknum = hook;
+ acpar.state = state;
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
local_bh_disable();
@@ -535,7 +531,8 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name)
static int
find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
- unsigned int size)
+ unsigned int size,
+ struct xt_percpu_counter_alloc_state *alloc_state)
{
struct xt_entry_target *t;
struct xt_target *target;
@@ -543,12 +540,9 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
unsigned int j;
struct xt_mtchk_param mtpar;
struct xt_entry_match *ematch;
- unsigned long pcnt;
- pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(pcnt))
+ if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
return -ENOMEM;
- e->counters.pcnt = pcnt;
j = 0;
mtpar.net = net;
@@ -586,7 +580,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
cleanup_match(ematch, net);
}
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
return ret;
}
@@ -674,7 +668,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net)
if (par.target->destroy != NULL)
par.target->destroy(&par);
module_put(par.target->me);
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
}
/* Checks and translates the user-supplied table segment (held in
@@ -683,6 +677,7 @@ static int
translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
const struct ipt_replace *repl)
{
+ struct xt_percpu_counter_alloc_state alloc_state = { 0 };
struct ipt_entry *iter;
unsigned int *offsets;
unsigned int i;
@@ -742,7 +737,8 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
/* Finally, each sanity check must pass */
i = 0;
xt_entry_foreach(iter, entry0, newinfo->size) {
- ret = find_check_entry(iter, net, repl->name, repl->size);
+ ret = find_check_entry(iter, net, repl->name, repl->size,
+ &alloc_state);
if (ret != 0)
break;
++i;
@@ -977,7 +973,7 @@ static int get_info(struct net *net, void __user *user,
#endif
t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
"iptable_%s", name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
struct ipt_getinfo info;
const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT
@@ -1007,7 +1003,7 @@ static int get_info(struct net *net, void __user *user,
xt_table_unlock(t);
module_put(t->me);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
#ifdef CONFIG_COMPAT
if (compat)
xt_compat_unlock(AF_INET);
@@ -1032,7 +1028,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,
get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, AF_INET, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
const struct xt_table_info *private = t->private;
if (get.size == private->size)
ret = copy_entries_to_user(private->size,
@@ -1043,7 +1039,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
return ret;
}
@@ -1068,8 +1064,8 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
"iptable_%s", name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free_newinfo_counters_untrans;
}
@@ -1184,8 +1180,8 @@ do_add_counters(struct net *net, const void __user *user,
return PTR_ERR(paddc);
t = xt_find_table_lock(net, AF_INET, tmp.name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free;
}
@@ -1630,7 +1626,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
xt_compat_lock(AF_INET);
t = xt_find_table_lock(net, AF_INET, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
const struct xt_table_info *private = t->private;
struct xt_table_info info;
ret = compat_table_info(private, &info);
@@ -1644,7 +1640,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
xt_compat_unlock(AF_INET);
return ret;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 4a9e6db9df8d..21db00d0362b 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -62,7 +62,7 @@ struct clusterip_config {
static const struct file_operations clusterip_proc_fops;
#endif
-static int clusterip_net_id __read_mostly;
+static unsigned int clusterip_net_id __read_mostly;
struct clusterip_net {
struct list_head configs;
@@ -419,7 +419,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
}
cipinfo->config = config;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -444,7 +444,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
clusterip_config_put(cipinfo->config);
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_get(par->net, par->family);
}
#ifdef CONFIG_COMPAT
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index da7f02a0b868..a03e4e7ef5f9 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -41,7 +41,7 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par)
pr_debug("bad rangesize %u\n", mr->rangesize);
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(par->net, par->family);
}
static unsigned int
@@ -55,7 +55,13 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
range.min_proto = mr->range[0].min;
range.max_proto = mr->range[0].max;
- return nf_nat_masquerade_ipv4(skb, par->hooknum, &range, par->out);
+ return nf_nat_masquerade_ipv4(skb, xt_hooknum(par), &range,
+ xt_out(par));
+}
+
+static void masquerade_tg_destroy(const struct xt_tgdtor_param *par)
+{
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_target masquerade_tg_reg __read_mostly = {
@@ -66,6 +72,7 @@ static struct xt_target masquerade_tg_reg __read_mostly = {
.table = "nat",
.hooks = 1 << NF_INET_POST_ROUTING,
.checkentry = masquerade_tg_check,
+ .destroy = masquerade_tg_destroy,
.me = THIS_MODULE,
};
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 1d16c0f28df0..8bd0d7b26632 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -34,7 +34,7 @@ static unsigned int
reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ipt_reject_info *reject = par->targinfo;
- int hook = par->hooknum;
+ int hook = xt_hooknum(par);
switch (reject->with) {
case IPT_ICMP_NET_UNREACHABLE:
@@ -59,7 +59,7 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
nf_send_unreach(skb, ICMP_PKT_FILTERED, hook);
break;
case IPT_TCP_RESET:
- nf_send_reset(par->net, skb, hook);
+ nf_send_reset(xt_net(par), skb, hook);
case IPT_ICMP_ECHOREPLY:
/* Doesn't happen. */
break;
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index db5b87509446..30c0de53e254 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -263,12 +263,12 @@ static unsigned int
synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_synproxy_info *info = par->targinfo;
- struct net *net = par->net;
+ struct net *net = xt_net(par);
struct synproxy_net *snet = synproxy_pernet(net);
struct synproxy_options opts = {};
struct tcphdr *th, _th;
- if (nf_ip_checksum(skb, par->hooknum, par->thoff, IPPROTO_TCP))
+ if (nf_ip_checksum(skb, xt_hooknum(par), par->thoff, IPPROTO_TCP))
return NF_DROP;
th = skb_header_pointer(skb, par->thoff, sizeof(_th), &_th);
@@ -418,12 +418,12 @@ static int synproxy_tg4_check(const struct xt_tgchk_param *par)
e->ip.invflags & XT_INV_PROTO)
return -EINVAL;
- return nf_ct_l3proto_try_module_get(par->family);
+ return nf_ct_netns_get(par->net, par->family);
}
static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_target synproxy_tg4_reg __read_mostly = {
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index 78cc64eddfc1..f273098e48fd 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -83,10 +83,12 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
return true ^ invert;
iph = ip_hdr(skb);
- if (ipv4_is_multicast(iph->daddr)) {
- if (ipv4_is_zeronet(iph->saddr))
- return ipv4_is_local_multicast(iph->daddr) ^ invert;
+ if (ipv4_is_zeronet(iph->saddr)) {
+ if (ipv4_is_lbcast(iph->daddr) ||
+ ipv4_is_local_multicast(iph->daddr))
+ return true ^ invert;
}
+
flow.flowi4_iif = LOOPBACK_IFINDEX;
flow.daddr = iph->saddr;
flow.saddr = rpfilter_get_saddr(iph->daddr);
@@ -95,7 +97,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
flow.flowi4_tos = RT_TOS(iph->tos);
flow.flowi4_scope = RT_SCOPE_UNIVERSE;
- return rpfilter_lookup_reverse(par->net, &flow, par->in, info->flags) ^ invert;
+ return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
}
static int rpfilter_check(const struct xt_mtchk_param *par)
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 713c09a74b90..fcfd071f4705 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -31,6 +31,13 @@
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#include <net/netfilter/nf_log.h>
+static int conntrack4_net_id __read_mostly;
+static DEFINE_MUTEX(register_ipv4_hooks);
+
+struct conntrack4_net {
+ unsigned int users;
+};
+
static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -307,9 +314,42 @@ static struct nf_sockopt_ops so_getorigdst = {
.owner = THIS_MODULE,
};
-static int ipv4_init_net(struct net *net)
+static int ipv4_hooks_register(struct net *net)
{
- return 0;
+ struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id);
+ int err = 0;
+
+ mutex_lock(&register_ipv4_hooks);
+
+ cnet->users++;
+ if (cnet->users > 1)
+ goto out_unlock;
+
+ err = nf_defrag_ipv4_enable(net);
+ if (err) {
+ cnet->users = 0;
+ goto out_unlock;
+ }
+
+ err = nf_register_net_hooks(net, ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
+
+ if (err)
+ cnet->users = 0;
+ out_unlock:
+ mutex_unlock(&register_ipv4_hooks);
+ return err;
+}
+
+static void ipv4_hooks_unregister(struct net *net)
+{
+ struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id);
+
+ mutex_lock(&register_ipv4_hooks);
+ if (cnet->users && (--cnet->users == 0))
+ nf_unregister_net_hooks(net, ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
+ mutex_unlock(&register_ipv4_hooks);
}
struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
@@ -325,7 +365,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
.nlattr_to_tuple = ipv4_nlattr_to_tuple,
.nla_policy = ipv4_nla_policy,
#endif
- .init_net = ipv4_init_net,
+ .net_ns_get = ipv4_hooks_register,
+ .net_ns_put = ipv4_hooks_unregister,
.me = THIS_MODULE,
};
@@ -336,52 +377,50 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_ALIAS("ip_conntrack");
MODULE_LICENSE("GPL");
+static struct nf_conntrack_l4proto *builtin_l4proto4[] = {
+ &nf_conntrack_l4proto_tcp4,
+ &nf_conntrack_l4proto_udp4,
+ &nf_conntrack_l4proto_icmp,
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+ &nf_conntrack_l4proto_dccp4,
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+ &nf_conntrack_l4proto_sctp4,
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+ &nf_conntrack_l4proto_udplite4,
+#endif
+};
+
static int ipv4_net_init(struct net *net)
{
int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp4);
- if (ret < 0) {
- pr_err("nf_conntrack_tcp4: pernet registration failed\n");
- goto out_tcp;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp4);
- if (ret < 0) {
- pr_err("nf_conntrack_udp4: pernet registration failed\n");
- goto out_udp;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmp);
- if (ret < 0) {
- pr_err("nf_conntrack_icmp4: pernet registration failed\n");
- goto out_icmp;
- }
+ ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
+ if (ret < 0)
+ return ret;
ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: pernet registration failed\n");
- goto out_ipv4;
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
}
- return 0;
-out_ipv4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
-out_icmp:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
-out_udp:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
-out_tcp:
return ret;
}
static void ipv4_net_exit(struct net *net)
{
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
}
static struct pernet_operations ipv4_net_ops = {
.init = ipv4_net_init,
.exit = ipv4_net_exit,
+ .id = &conntrack4_net_id,
+ .size = sizeof(struct conntrack4_net),
};
static int __init nf_conntrack_l3proto_ipv4_init(void)
@@ -389,7 +428,6 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
int ret = 0;
need_conntrack();
- nf_defrag_ipv4_enable();
ret = nf_register_sockopt(&so_getorigdst);
if (ret < 0) {
@@ -403,46 +441,21 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
goto cleanup_sockopt;
}
- ret = nf_register_hooks(ipv4_conntrack_ops,
- ARRAY_SIZE(ipv4_conntrack_ops));
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register hooks.\n");
+ ret = nf_ct_l4proto_register(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
+ if (ret < 0)
goto cleanup_pernet;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp4);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register tcp4 proto.\n");
- goto cleanup_hooks;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp4);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register udp4 proto.\n");
- goto cleanup_tcp4;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmp);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register icmpv4 proto.\n");
- goto cleanup_udp4;
- }
ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
- goto cleanup_icmpv4;
+ goto cleanup_l4proto;
}
return ret;
- cleanup_icmpv4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
- cleanup_udp4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
- cleanup_tcp4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
- cleanup_hooks:
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+cleanup_l4proto:
+ nf_ct_l4proto_unregister(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
cleanup_pernet:
unregister_pernet_subsys(&ipv4_net_ops);
cleanup_sockopt:
@@ -454,10 +467,8 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
synchronize_net();
nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+ nf_ct_l4proto_unregister(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
unregister_pernet_subsys(&ipv4_net_ops);
nf_unregister_sockopt(&so_getorigdst);
}
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index d88da36b383c..49bd6a54404f 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -11,6 +11,7 @@
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <net/netns/generic.h>
#include <net/route.h>
#include <net/ip.h>
@@ -22,6 +23,8 @@
#endif
#include <net/netfilter/nf_conntrack_zones.h>
+static DEFINE_MUTEX(defrag4_mutex);
+
static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
u_int32_t user)
{
@@ -102,18 +105,50 @@ static struct nf_hook_ops ipv4_defrag_ops[] = {
},
};
+static void __net_exit defrag4_net_exit(struct net *net)
+{
+ if (net->nf.defrag_ipv4) {
+ nf_unregister_net_hooks(net, ipv4_defrag_ops,
+ ARRAY_SIZE(ipv4_defrag_ops));
+ net->nf.defrag_ipv4 = false;
+ }
+}
+
+static struct pernet_operations defrag4_net_ops = {
+ .exit = defrag4_net_exit,
+};
+
static int __init nf_defrag_init(void)
{
- return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
+ return register_pernet_subsys(&defrag4_net_ops);
}
static void __exit nf_defrag_fini(void)
{
- nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
+ unregister_pernet_subsys(&defrag4_net_ops);
}
-void nf_defrag_ipv4_enable(void)
+int nf_defrag_ipv4_enable(struct net *net)
{
+ int err = 0;
+
+ might_sleep();
+
+ if (net->nf.defrag_ipv4)
+ return 0;
+
+ mutex_lock(&defrag4_mutex);
+ if (net->nf.defrag_ipv4)
+ goto out_unlock;
+
+ err = nf_register_net_hooks(net, ipv4_defrag_ops,
+ ARRAY_SIZE(ipv4_defrag_ops));
+ if (err == 0)
+ net->nf.defrag_ipv4 = true;
+
+ out_unlock:
+ mutex_unlock(&defrag4_mutex);
+ return err;
}
EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
diff --git a/net/ipv4/netfilter/nf_socket_ipv4.c b/net/ipv4/netfilter/nf_socket_ipv4.c
new file mode 100644
index 000000000000..a83d558e1aae
--- /dev/null
+++ b/net/ipv4/netfilter/nf_socket_ipv4.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2007-2008 BalaBit IT Ltd.
+ * Author: Krisztian Kovacs
+ *
+ * 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/module.h>
+#include <linux/skbuff.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+#include <net/sock.h>
+#include <net/inet_sock.h>
+#include <net/netfilter/nf_socket.h>
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+static int
+extract_icmp4_fields(const struct sk_buff *skb, u8 *protocol,
+ __be32 *raddr, __be32 *laddr,
+ __be16 *rport, __be16 *lport)
+{
+ unsigned int outside_hdrlen = ip_hdrlen(skb);
+ struct iphdr *inside_iph, _inside_iph;
+ struct icmphdr *icmph, _icmph;
+ __be16 *ports, _ports[2];
+
+ icmph = skb_header_pointer(skb, outside_hdrlen,
+ sizeof(_icmph), &_icmph);
+ if (icmph == NULL)
+ return 1;
+
+ switch (icmph->type) {
+ case ICMP_DEST_UNREACH:
+ case ICMP_SOURCE_QUENCH:
+ case ICMP_REDIRECT:
+ case ICMP_TIME_EXCEEDED:
+ case ICMP_PARAMETERPROB:
+ break;
+ default:
+ return 1;
+ }
+
+ inside_iph = skb_header_pointer(skb, outside_hdrlen +
+ sizeof(struct icmphdr),
+ sizeof(_inside_iph), &_inside_iph);
+ if (inside_iph == NULL)
+ return 1;
+
+ if (inside_iph->protocol != IPPROTO_TCP &&
+ inside_iph->protocol != IPPROTO_UDP)
+ return 1;
+
+ ports = skb_header_pointer(skb, outside_hdrlen +
+ sizeof(struct icmphdr) +
+ (inside_iph->ihl << 2),
+ sizeof(_ports), &_ports);
+ if (ports == NULL)
+ return 1;
+
+ /* the inside IP packet is the one quoted from our side, thus
+ * its saddr is the local address */
+ *protocol = inside_iph->protocol;
+ *laddr = inside_iph->saddr;
+ *lport = ports[0];
+ *raddr = inside_iph->daddr;
+ *rport = ports[1];
+
+ return 0;
+}
+
+static struct sock *
+nf_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff,
+ const u8 protocol,
+ const __be32 saddr, const __be32 daddr,
+ const __be16 sport, const __be16 dport,
+ const struct net_device *in)
+{
+ switch (protocol) {
+ case IPPROTO_TCP:
+ return inet_lookup(net, &tcp_hashinfo, skb, doff,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ case IPPROTO_UDP:
+ return udp4_lib_lookup(net, saddr, sport, daddr, dport,
+ in->ifindex);
+ }
+ return NULL;
+}
+
+struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
+ const struct net_device *indev)
+{
+ __be32 uninitialized_var(daddr), uninitialized_var(saddr);
+ __be16 uninitialized_var(dport), uninitialized_var(sport);
+ const struct iphdr *iph = ip_hdr(skb);
+ struct sk_buff *data_skb = NULL;
+ u8 uninitialized_var(protocol);
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn const *ct;
+#endif
+ int doff = 0;
+
+ if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
+ struct udphdr _hdr, *hp;
+
+ hp = skb_header_pointer(skb, ip_hdrlen(skb),
+ sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return NULL;
+
+ protocol = iph->protocol;
+ saddr = iph->saddr;
+ sport = hp->source;
+ daddr = iph->daddr;
+ dport = hp->dest;
+ data_skb = (struct sk_buff *)skb;
+ doff = iph->protocol == IPPROTO_TCP ?
+ ip_hdrlen(skb) + __tcp_hdrlen((struct tcphdr *)hp) :
+ ip_hdrlen(skb) + sizeof(*hp);
+
+ } else if (iph->protocol == IPPROTO_ICMP) {
+ if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
+ &sport, &dport))
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ /* Do the lookup with the original socket address in
+ * case this is a reply packet of an established
+ * SNAT-ted connection.
+ */
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct && !nf_ct_is_untracked(ct) &&
+ ((iph->protocol != IPPROTO_ICMP &&
+ ctinfo == IP_CT_ESTABLISHED_REPLY) ||
+ (iph->protocol == IPPROTO_ICMP &&
+ ctinfo == IP_CT_RELATED_REPLY)) &&
+ (ct->status & IPS_SRC_NAT_DONE)) {
+
+ daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
+ dport = (iph->protocol == IPPROTO_TCP) ?
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
+ }
+#endif
+
+ return nf_socket_get_sock_v4(net, data_skb, doff, protocol, saddr,
+ daddr, sport, dport, indev);
+}
+EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v4);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
+MODULE_DESCRIPTION("Netfilter IPv4 socket lookup infrastructure");
diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c
index 0c01a270bf9f..0af3d8df70dd 100644
--- a/net/ipv4/netfilter/nft_dup_ipv4.c
+++ b/net/ipv4/netfilter/nft_dup_ipv4.c
@@ -30,7 +30,7 @@ static void nft_dup_ipv4_eval(const struct nft_expr *expr,
};
int oif = priv->sreg_dev ? regs->data[priv->sreg_dev] : -1;
- nf_dup_ipv4(pkt->net, pkt->skb, pkt->hook, &gw, oif);
+ nf_dup_ipv4(nft_net(pkt), pkt->skb, nft_hook(pkt), &gw, oif);
}
static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
diff --git a/net/ipv4/netfilter/nft_fib_ipv4.c b/net/ipv4/netfilter/nft_fib_ipv4.c
new file mode 100644
index 000000000000..965b1a161369
--- /dev/null
+++ b/net/ipv4/netfilter/nft_fib_ipv4.c
@@ -0,0 +1,241 @@
+/*
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nft_fib.h>
+
+#include <net/ip_fib.h>
+#include <net/route.h>
+
+/* don't try to find route from mcast/bcast/zeronet */
+static __be32 get_saddr(__be32 addr)
+{
+ if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) ||
+ ipv4_is_zeronet(addr))
+ return 0;
+ return addr;
+}
+
+static bool fib4_is_local(const struct sk_buff *skb)
+{
+ const struct rtable *rt = skb_rtable(skb);
+
+ return rt && (rt->rt_flags & RTCF_LOCAL);
+}
+
+#define DSCP_BITS 0xfc
+
+void nft_fib4_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ u32 *dst = &regs->data[priv->dreg];
+ const struct net_device *dev = NULL;
+ const struct iphdr *iph;
+ __be32 addr;
+
+ if (priv->flags & NFTA_FIB_F_IIF)
+ dev = nft_in(pkt);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+ dev = nft_out(pkt);
+
+ iph = ip_hdr(pkt->skb);
+ if (priv->flags & NFTA_FIB_F_DADDR)
+ addr = iph->daddr;
+ else
+ addr = iph->saddr;
+
+ *dst = inet_dev_addr_type(nft_net(pkt), dev, addr);
+}
+EXPORT_SYMBOL_GPL(nft_fib4_eval_type);
+
+static int get_ifindex(const struct net_device *dev)
+{
+ return dev ? dev->ifindex : 0;
+}
+
+void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ u32 *dest = &regs->data[priv->dreg];
+ const struct iphdr *iph;
+ struct fib_result res;
+ struct flowi4 fl4 = {
+ .flowi4_scope = RT_SCOPE_UNIVERSE,
+ .flowi4_iif = LOOPBACK_IFINDEX,
+ };
+ const struct net_device *oif;
+ struct net_device *found;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int i;
+#endif
+
+ /*
+ * Do not set flowi4_oif, it restricts results (for example, asking
+ * for oif 3 will get RTN_UNICAST result even if the daddr exits
+ * on another interface.
+ *
+ * Search results for the desired outinterface instead.
+ */
+ if (priv->flags & NFTA_FIB_F_OIF)
+ oif = nft_out(pkt);
+ else if (priv->flags & NFTA_FIB_F_IIF)
+ oif = nft_in(pkt);
+ else
+ oif = NULL;
+
+ if (nft_hook(pkt) == NF_INET_PRE_ROUTING && fib4_is_local(pkt->skb)) {
+ nft_fib_store_result(dest, priv->result, pkt, LOOPBACK_IFINDEX);
+ return;
+ }
+
+ iph = ip_hdr(pkt->skb);
+ if (ipv4_is_zeronet(iph->saddr)) {
+ if (ipv4_is_lbcast(iph->daddr) ||
+ ipv4_is_local_multicast(iph->daddr)) {
+ nft_fib_store_result(dest, priv->result, pkt,
+ get_ifindex(pkt->skb->dev));
+ return;
+ }
+ }
+
+ if (priv->flags & NFTA_FIB_F_MARK)
+ fl4.flowi4_mark = pkt->skb->mark;
+
+ fl4.flowi4_tos = iph->tos & DSCP_BITS;
+
+ if (priv->flags & NFTA_FIB_F_DADDR) {
+ fl4.daddr = iph->daddr;
+ fl4.saddr = get_saddr(iph->saddr);
+ } else {
+ fl4.daddr = iph->saddr;
+ fl4.saddr = get_saddr(iph->daddr);
+ }
+
+ *dest = 0;
+
+ if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
+ return;
+
+ switch (res.type) {
+ case RTN_UNICAST:
+ break;
+ case RTN_LOCAL: /* should not appear here, see fib4_is_local() above */
+ return;
+ default:
+ break;
+ }
+
+ if (!oif) {
+ found = FIB_RES_DEV(res);
+ goto ok;
+ }
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ for (i = 0; i < res.fi->fib_nhs; i++) {
+ struct fib_nh *nh = &res.fi->fib_nh[i];
+
+ if (nh->nh_dev == oif) {
+ found = nh->nh_dev;
+ goto ok;
+ }
+ }
+ return;
+#else
+ found = FIB_RES_DEV(res);
+ if (found != oif)
+ return;
+#endif
+ok:
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ *dest = found->ifindex;
+ break;
+ case NFT_FIB_RESULT_OIFNAME:
+ strncpy((char *)dest, found->name, IFNAMSIZ);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(nft_fib4_eval);
+
+static struct nft_expr_type nft_fib4_type;
+
+static const struct nft_expr_ops nft_fib4_type_ops = {
+ .type = &nft_fib4_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_fib)),
+ .eval = nft_fib4_eval_type,
+ .init = nft_fib_init,
+ .dump = nft_fib_dump,
+ .validate = nft_fib_validate,
+};
+
+static const struct nft_expr_ops nft_fib4_ops = {
+ .type = &nft_fib4_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_fib)),
+ .eval = nft_fib4_eval,
+ .init = nft_fib_init,
+ .dump = nft_fib_dump,
+ .validate = nft_fib_validate,
+};
+
+static const struct nft_expr_ops *
+nft_fib4_select_ops(const struct nft_ctx *ctx,
+ const struct nlattr * const tb[])
+{
+ enum nft_fib_result result;
+
+ if (!tb[NFTA_FIB_RESULT])
+ return ERR_PTR(-EINVAL);
+
+ result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
+
+ switch (result) {
+ case NFT_FIB_RESULT_OIF:
+ return &nft_fib4_ops;
+ case NFT_FIB_RESULT_OIFNAME:
+ return &nft_fib4_ops;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ return &nft_fib4_type_ops;
+ default:
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+}
+
+static struct nft_expr_type nft_fib4_type __read_mostly = {
+ .name = "fib",
+ .select_ops = &nft_fib4_select_ops,
+ .policy = nft_fib_policy,
+ .maxattr = NFTA_FIB_MAX,
+ .family = NFPROTO_IPV4,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_fib4_module_init(void)
+{
+ return nft_register_expr(&nft_fib4_type);
+}
+
+static void __exit nft_fib4_module_exit(void)
+{
+ nft_unregister_expr(&nft_fib4_type);
+}
+
+module_init(nft_fib4_module_init);
+module_exit(nft_fib4_module_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+MODULE_ALIAS_NFT_AF_EXPR(2, "fib");
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c
index 51ced81b616c..a0ea8aad1bf1 100644
--- a/net/ipv4/netfilter/nft_masq_ipv4.c
+++ b/net/ipv4/netfilter/nft_masq_ipv4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -31,8 +31,14 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
range.max_proto.all =
*(__be16 *)&regs->data[priv->sreg_proto_max];
}
- regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook,
- &range, pkt->out);
+ regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt),
+ &range, nft_out(pkt));
+}
+
+static void
+nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
+{
+ nf_ct_netns_put(ctx->net, NFPROTO_IPV4);
}
static struct nft_expr_type nft_masq_ipv4_type;
@@ -41,6 +47,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
.eval = nft_masq_ipv4_eval,
.init = nft_masq_init,
+ .destroy = nft_masq_ipv4_destroy,
.dump = nft_masq_dump,
.validate = nft_masq_validate,
};
@@ -77,5 +84,5 @@ module_init(nft_masq_ipv4_module_init);
module_exit(nft_masq_ipv4_module_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c
index c09d4381427e..1650ed23c15d 100644
--- a/net/ipv4/netfilter/nft_redir_ipv4.c
+++ b/net/ipv4/netfilter/nft_redir_ipv4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -35,8 +35,13 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
mr.range[0].flags |= priv->flags;
- regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr,
- pkt->hook);
+ regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));
+}
+
+static void
+nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
+{
+ nf_ct_netns_put(ctx->net, NFPROTO_IPV4);
}
static struct nft_expr_type nft_redir_ipv4_type;
@@ -45,6 +50,7 @@ static const struct nft_expr_ops nft_redir_ipv4_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv4_eval,
.init = nft_redir_init,
+ .destroy = nft_redir_ipv4_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
@@ -72,5 +78,5 @@ module_init(nft_redir_ipv4_module_init);
module_exit(nft_redir_ipv4_module_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
index 2c2553b9026c..517ce93699de 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -27,10 +27,10 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach(pkt->skb, priv->icmp_code, pkt->hook);
+ nf_send_unreach(pkt->skb, priv->icmp_code, nft_hook(pkt));
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset(pkt->net, pkt->skb, pkt->hook);
+ nf_send_reset(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
default:
break;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 96b8e2b95731..5b2635e69a92 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -793,7 +793,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol,
- inet_sk_flowi_flags(sk), faddr, saddr, 0, 0);
+ inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
+ sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
rt = ip_route_output_flow(net, &fl4, sk);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index ecbe5a7c2d6d..2300fae11b22 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -89,9 +89,10 @@ struct raw_frag_vec {
int hlen;
};
-static struct raw_hashinfo raw_v4_hashinfo = {
+struct raw_hashinfo raw_v4_hashinfo = {
.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
};
+EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
int raw_hash_sk(struct sock *sk)
{
@@ -120,7 +121,7 @@ void raw_unhash_sk(struct sock *sk)
}
EXPORT_SYMBOL_GPL(raw_unhash_sk);
-static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
unsigned short num, __be32 raddr, __be32 laddr, int dif)
{
sk_for_each_from(sk) {
@@ -136,6 +137,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
found:
return sk;
}
+EXPORT_SYMBOL_GPL(__raw_v4_lookup);
/*
* 0 - deliver
@@ -604,7 +606,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk) |
(inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
- daddr, saddr, 0, 0);
+ daddr, saddr, 0, 0, sk->sk_uid);
if (!inet->hdrincl) {
rfv.msg = msg;
@@ -693,12 +695,20 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+ u32 tb_id = RT_TABLE_LOCAL;
int ret = -EINVAL;
int chk_addr_ret;
if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
goto out;
- chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+
+ if (sk->sk_bound_dev_if)
+ tb_id = l3mdev_fib_table_by_index(sock_net(sk),
+ sk->sk_bound_dev_if) ? : tb_id;
+
+ chk_addr_ret = inet_addr_type_table(sock_net(sk), addr->sin_addr.s_addr,
+ tb_id);
+
ret = -EADDRNOTAVAIL;
if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
@@ -912,6 +922,20 @@ static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg
}
#endif
+int raw_abort(struct sock *sk, int err)
+{
+ lock_sock(sk);
+
+ sk->sk_err = err;
+ sk->sk_error_report(sk);
+ __udp_disconnect(sk, 0);
+
+ release_sock(sk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(raw_abort);
+
struct proto raw_prot = {
.name = "RAW",
.owner = THIS_MODULE,
@@ -937,6 +961,7 @@ struct proto raw_prot = {
.compat_getsockopt = compat_raw_getsockopt,
.compat_ioctl = compat_raw_ioctl,
#endif
+ .diag_destroy = raw_abort,
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
new file mode 100644
index 000000000000..e1a51ca68d23
--- /dev/null
+++ b/net/ipv4/raw_diag.c
@@ -0,0 +1,266 @@
+#include <linux/module.h>
+
+#include <linux/inet_diag.h>
+#include <linux/sock_diag.h>
+
+#include <net/inet_sock.h>
+#include <net/raw.h>
+#include <net/rawv6.h>
+
+#ifdef pr_fmt
+# undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+static struct raw_hashinfo *
+raw_get_hashinfo(const struct inet_diag_req_v2 *r)
+{
+ if (r->sdiag_family == AF_INET) {
+ return &raw_v4_hashinfo;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (r->sdiag_family == AF_INET6) {
+ return &raw_v6_hashinfo;
+#endif
+ } else {
+ pr_warn_once("Unexpected inet family %d\n",
+ r->sdiag_family);
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-EINVAL);
+ }
+}
+
+/*
+ * Due to requirement of not breaking user API we can't simply
+ * rename @pad field in inet_diag_req_v2 structure, instead
+ * use helper to figure it out.
+ */
+
+static struct sock *raw_lookup(struct net *net, struct sock *from,
+ const struct inet_diag_req_v2 *req)
+{
+ struct inet_diag_req_raw *r = (void *)req;
+ struct sock *sk = NULL;
+
+ if (r->sdiag_family == AF_INET)
+ sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol,
+ r->id.idiag_dst[0],
+ r->id.idiag_src[0],
+ r->id.idiag_if);
+#if IS_ENABLED(CONFIG_IPV6)
+ else
+ sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
+ (const struct in6_addr *)r->id.idiag_src,
+ (const struct in6_addr *)r->id.idiag_dst,
+ r->id.idiag_if);
+#endif
+ return sk;
+}
+
+static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
+{
+ struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
+ struct sock *sk = NULL, *s;
+ int slot;
+
+ if (IS_ERR(hashinfo))
+ return ERR_CAST(hashinfo);
+
+ read_lock(&hashinfo->lock);
+ for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
+ sk_for_each(s, &hashinfo->ht[slot]) {
+ sk = raw_lookup(net, s, r);
+ if (sk) {
+ /*
+ * Grab it and keep until we fill
+ * diag meaage to be reported, so
+ * caller should call sock_put then.
+ * We can do that because we're keeping
+ * hashinfo->lock here.
+ */
+ sock_hold(sk);
+ goto out_unlock;
+ }
+ }
+ }
+out_unlock:
+ read_unlock(&hashinfo->lock);
+
+ return sk ? sk : ERR_PTR(-ENOENT);
+}
+
+static int raw_diag_dump_one(struct sk_buff *in_skb,
+ const struct nlmsghdr *nlh,
+ const struct inet_diag_req_v2 *r)
+{
+ struct net *net = sock_net(in_skb->sk);
+ struct sk_buff *rep;
+ struct sock *sk;
+ int err;
+
+ sk = raw_sock_get(net, r);
+ if (IS_ERR(sk))
+ return PTR_ERR(sk);
+
+ rep = nlmsg_new(sizeof(struct inet_diag_msg) +
+ sizeof(struct inet_diag_meminfo) + 64,
+ GFP_KERNEL);
+ if (!rep) {
+ sock_put(sk);
+ return -ENOMEM;
+ }
+
+ err = inet_sk_diag_fill(sk, NULL, rep, r,
+ sk_user_ns(NETLINK_CB(in_skb).sk),
+ NETLINK_CB(in_skb).portid,
+ nlh->nlmsg_seq, 0, nlh,
+ netlink_net_capable(in_skb, CAP_NET_ADMIN));
+ sock_put(sk);
+
+ if (err < 0) {
+ kfree_skb(rep);
+ return err;
+ }
+
+ err = netlink_unicast(net->diag_nlsk, rep,
+ NETLINK_CB(in_skb).portid,
+ MSG_DONTWAIT);
+ if (err > 0)
+ err = 0;
+ return err;
+}
+
+static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
+ struct netlink_callback *cb,
+ const struct inet_diag_req_v2 *r,
+ struct nlattr *bc, bool net_admin)
+{
+ if (!inet_diag_bc_sk(bc, sk))
+ return 0;
+
+ return inet_sk_diag_fill(sk, NULL, skb, r,
+ sk_user_ns(NETLINK_CB(cb->skb).sk),
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ cb->nlh, net_admin);
+}
+
+static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ const struct inet_diag_req_v2 *r, struct nlattr *bc)
+{
+ bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
+ struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
+ struct net *net = sock_net(skb->sk);
+ int num, s_num, slot, s_slot;
+ struct sock *sk = NULL;
+
+ if (IS_ERR(hashinfo))
+ return;
+
+ s_slot = cb->args[0];
+ num = s_num = cb->args[1];
+
+ read_lock(&hashinfo->lock);
+ for (slot = s_slot; slot < RAW_HTABLE_SIZE; s_num = 0, slot++) {
+ num = 0;
+
+ sk_for_each(sk, &hashinfo->ht[slot]) {
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (!net_eq(sock_net(sk), net))
+ continue;
+ if (num < s_num)
+ goto next;
+ if (sk->sk_family != r->sdiag_family)
+ goto next;
+ if (r->id.idiag_sport != inet->inet_sport &&
+ r->id.idiag_sport)
+ goto next;
+ if (r->id.idiag_dport != inet->inet_dport &&
+ r->id.idiag_dport)
+ goto next;
+ if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0)
+ goto out_unlock;
+next:
+ num++;
+ }
+ }
+
+out_unlock:
+ read_unlock(&hashinfo->lock);
+
+ cb->args[0] = slot;
+ cb->args[1] = num;
+}
+
+static void raw_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+ void *info)
+{
+ r->idiag_rqueue = sk_rmem_alloc_get(sk);
+ r->idiag_wqueue = sk_wmem_alloc_get(sk);
+}
+
+#ifdef CONFIG_INET_DIAG_DESTROY
+static int raw_diag_destroy(struct sk_buff *in_skb,
+ const struct inet_diag_req_v2 *r)
+{
+ struct net *net = sock_net(in_skb->sk);
+ struct sock *sk;
+ int err;
+
+ sk = raw_sock_get(net, r);
+ if (IS_ERR(sk))
+ return PTR_ERR(sk);
+ err = sock_diag_destroy(sk, ECONNABORTED);
+ sock_put(sk);
+ return err;
+}
+#endif
+
+static const struct inet_diag_handler raw_diag_handler = {
+ .dump = raw_diag_dump,
+ .dump_one = raw_diag_dump_one,
+ .idiag_get_info = raw_diag_get_info,
+ .idiag_type = IPPROTO_RAW,
+ .idiag_info_size = 0,
+#ifdef CONFIG_INET_DIAG_DESTROY
+ .destroy = raw_diag_destroy,
+#endif
+};
+
+static void __always_unused __check_inet_diag_req_raw(void)
+{
+ /*
+ * Make sure the two structures are identical,
+ * except the @pad field.
+ */
+#define __offset_mismatch(m1, m2) \
+ (offsetof(struct inet_diag_req_v2, m1) != \
+ offsetof(struct inet_diag_req_raw, m2))
+
+ BUILD_BUG_ON(sizeof(struct inet_diag_req_v2) !=
+ sizeof(struct inet_diag_req_raw));
+ BUILD_BUG_ON(__offset_mismatch(sdiag_family, sdiag_family));
+ BUILD_BUG_ON(__offset_mismatch(sdiag_protocol, sdiag_protocol));
+ BUILD_BUG_ON(__offset_mismatch(idiag_ext, idiag_ext));
+ BUILD_BUG_ON(__offset_mismatch(pad, sdiag_raw_protocol));
+ BUILD_BUG_ON(__offset_mismatch(idiag_states, idiag_states));
+ BUILD_BUG_ON(__offset_mismatch(id, id));
+#undef __offset_mismatch
+}
+
+static int __init raw_diag_init(void)
+{
+ return inet_diag_register(&raw_diag_handler);
+}
+
+static void __exit raw_diag_exit(void)
+{
+ inet_diag_unregister(&raw_diag_handler);
+}
+
+module_init(raw_diag_init);
+module_exit(raw_diag_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-255 /* AF_INET - IPPROTO_RAW */);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10-255 /* AF_INET6 - IPPROTO_RAW */);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2a57566e6e91..fa5c037227cb 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -507,7 +507,8 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
}
EXPORT_SYMBOL(__ip_select_ident);
-static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
+static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
+ const struct sock *sk,
const struct iphdr *iph,
int oif, u8 tos,
u8 prot, u32 mark, int flow_flags)
@@ -523,19 +524,21 @@ static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
flowi4_init_output(fl4, oif, mark, tos,
RT_SCOPE_UNIVERSE, prot,
flow_flags,
- iph->daddr, iph->saddr, 0, 0);
+ iph->daddr, iph->saddr, 0, 0,
+ sock_net_uid(net, sk));
}
static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
const struct sock *sk)
{
+ const struct net *net = dev_net(skb->dev);
const struct iphdr *iph = ip_hdr(skb);
int oif = skb->dev->ifindex;
u8 tos = RT_TOS(iph->tos);
u8 prot = iph->protocol;
u32 mark = skb->mark;
- __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
+ __build_flow_key(net, fl4, sk, iph, oif, tos, prot, mark, 0);
}
static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
@@ -552,7 +555,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk),
- daddr, inet->inet_saddr, 0, 0);
+ daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
rcu_read_unlock();
}
@@ -802,7 +805,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
rt = (struct rtable *) dst;
- __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
+ __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
__ip_do_redirect(rt, skb, &fl4, true);
}
@@ -1020,7 +1023,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
if (!mark)
mark = IP4_REPLY_MARK(net, skb->mark);
- __build_flow_key(&fl4, NULL, iph, oif,
+ __build_flow_key(net, &fl4, NULL, iph, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) {
@@ -1036,7 +1039,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
struct flowi4 fl4;
struct rtable *rt;
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+ __build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
if (!fl4.flowi4_mark)
fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@@ -1055,6 +1058,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
struct rtable *rt;
struct dst_entry *odst = NULL;
bool new = false;
+ struct net *net = sock_net(sk);
bh_lock_sock(sk);
@@ -1068,7 +1072,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
goto out;
}
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+ __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
rt = (struct rtable *)odst;
if (odst->obsolete && !odst->ops->check(odst, 0)) {
@@ -1108,7 +1112,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
struct flowi4 fl4;
struct rtable *rt;
- __build_flow_key(&fl4, NULL, iph, oif,
+ __build_flow_key(net, &fl4, NULL, iph, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) {
@@ -1123,9 +1127,10 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
const struct iphdr *iph = (const struct iphdr *) skb->data;
struct flowi4 fl4;
struct rtable *rt;
+ struct net *net = sock_net(sk);
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
- rt = __ip_route_output_key(sock_net(sk), &fl4);
+ __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
+ rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) {
__ip_do_redirect(rt, skb, &fl4, false);
ip_rt_put(rt);
@@ -1598,6 +1603,19 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
spin_unlock_bh(&fnhe_lock);
}
+static void set_lwt_redirect(struct rtable *rth)
+{
+ if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
+ rth->dst.lwtstate->orig_output = rth->dst.output;
+ rth->dst.output = lwtunnel_output;
+ }
+
+ if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
+ rth->dst.lwtstate->orig_input = rth->dst.input;
+ rth->dst.input = lwtunnel_input;
+ }
+}
+
/* called in rcu_read_lock() section */
static int __mkroute_input(struct sk_buff *skb,
const struct fib_result *res,
@@ -1687,14 +1705,7 @@ rt_cache:
rth->dst.input = ip_forward;
rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag);
- if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
- rth->dst.lwtstate->orig_output = rth->dst.output;
- rth->dst.output = lwtunnel_output;
- }
- if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
- rth->dst.lwtstate->orig_input = rth->dst.input;
- rth->dst.input = lwtunnel_input;
- }
+ set_lwt_redirect(rth);
skb_dst_set(skb, &rth->dst);
out:
err = 0;
@@ -1921,8 +1932,18 @@ local_input:
rth->dst.error= -err;
rth->rt_flags &= ~RTCF_LOCAL;
}
+
if (do_cache) {
- if (unlikely(!rt_cache_route(&FIB_RES_NH(res), rth))) {
+ struct fib_nh *nh = &FIB_RES_NH(res);
+
+ rth->dst.lwtstate = lwtstate_get(nh->nh_lwtstate);
+ if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
+ WARN_ON(rth->dst.input == lwtunnel_input);
+ rth->dst.lwtstate->orig_input = rth->dst.input;
+ rth->dst.input = lwtunnel_input;
+ }
+
+ if (unlikely(!rt_cache_route(nh, rth))) {
rth->dst.flags |= DST_NOCACHE;
rt_add_uncached_list(rth);
}
@@ -1982,25 +2003,35 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
*/
if (ipv4_is_multicast(daddr)) {
struct in_device *in_dev = __in_dev_get_rcu(dev);
+ int our = 0;
+
+ if (in_dev)
+ our = ip_check_mc_rcu(in_dev, daddr, saddr,
+ ip_hdr(skb)->protocol);
+
+ /* check l3 master if no match yet */
+ if ((!in_dev || !our) && netif_is_l3_slave(dev)) {
+ struct in_device *l3_in_dev;
- if (in_dev) {
- int our = ip_check_mc_rcu(in_dev, daddr, saddr,
- ip_hdr(skb)->protocol);
- if (our
+ l3_in_dev = __in_dev_get_rcu(skb->dev);
+ if (l3_in_dev)
+ our = ip_check_mc_rcu(l3_in_dev, daddr, saddr,
+ ip_hdr(skb)->protocol);
+ }
+
+ res = -EINVAL;
+ if (our
#ifdef CONFIG_IP_MROUTE
- ||
- (!ipv4_is_local_multicast(daddr) &&
- IN_DEV_MFORWARD(in_dev))
+ ||
+ (!ipv4_is_local_multicast(daddr) &&
+ IN_DEV_MFORWARD(in_dev))
#endif
- ) {
- int res = ip_route_input_mc(skb, daddr, saddr,
- tos, dev, our);
- rcu_read_unlock();
- return res;
- }
+ ) {
+ res = ip_route_input_mc(skb, daddr, saddr,
+ tos, dev, our);
}
rcu_read_unlock();
- return -EINVAL;
+ return res;
}
res = ip_route_input_slow(skb, daddr, saddr, tos, dev);
rcu_read_unlock();
@@ -2140,8 +2171,7 @@ add:
}
rt_set_nexthop(rth, fl4->daddr, res, fnhe, fi, type, 0);
- if (lwtunnel_output_redirect(rth->dst.lwtstate))
- rth->dst.output = lwtunnel_output;
+ set_lwt_redirect(rth);
return rth;
}
@@ -2268,7 +2298,8 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
res.fi = NULL;
res.table = NULL;
if (fl4->flowi4_oif &&
- !netif_index_is_l3_master(net, fl4->flowi4_oif)) {
+ (ipv4_is_multicast(fl4->daddr) ||
+ !netif_index_is_l3_master(net, fl4->flowi4_oif))) {
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.
@@ -2495,6 +2526,11 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))
goto nla_put_failure;
+ if (!uid_eq(fl4->flowi4_uid, INVALID_UID) &&
+ nla_put_u32(skb, RTA_UID,
+ from_kuid_munged(current_user_ns(), fl4->flowi4_uid)))
+ goto nla_put_failure;
+
error = rt->dst.error;
if (rt_is_input_route(rt)) {
@@ -2547,6 +2583,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
int mark;
struct sk_buff *skb;
u32 table_id = RT_TABLE_MAIN;
+ kuid_t uid;
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
if (err < 0)
@@ -2574,6 +2611,10 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
dst = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
+ if (tb[RTA_UID])
+ uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID]));
+ else
+ uid = (iif ? INVALID_UID : current_uid());
memset(&fl4, 0, sizeof(fl4));
fl4.daddr = dst;
@@ -2581,6 +2622,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
fl4.flowi4_tos = rtm->rtm_tos;
fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
fl4.flowi4_mark = mark;
+ fl4.flowi4_uid = uid;
if (iif) {
struct net_device *dev;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e3c4043c27de..3e88467d70ee 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -334,6 +334,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
treq = tcp_rsk(req);
treq->rcv_isn = ntohl(th->seq) - 1;
treq->snt_isn = cookie;
+ treq->ts_off = 0;
req->mss = mss;
ireq->ir_num = ntohs(th->dest);
ireq->ir_rmt_port = th->source;
@@ -372,7 +373,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
opt->srr ? opt->faddr : ireq->ir_rmt_addr,
- ireq->ir_loc_addr, th->source, th->dest);
+ ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(&fl4));
rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt)) {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 814af89c1bd3..1ef3165114ba 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -279,7 +279,6 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-#include <asm/unaligned.h>
#include <net/busy_poll.h>
int sysctl_tcp_min_tso_segs __read_mostly = 2;
@@ -405,7 +404,6 @@ void tcp_init_sock(struct sock *sk)
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
tp->snd_cwnd_clamp = ~0;
tp->mss_cache = TCP_MSS_DEFAULT;
- u64_stats_init(&tp->syncp);
tp->reordering = sock_net(sk)->ipv4.sysctl_tcp_reordering;
tcp_enable_early_retrans(tp);
@@ -665,9 +663,9 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
if (tcp_should_autocork(sk, skb, size_goal)) {
/* avoid atomic op if TSQ_THROTTLED bit is already set */
- if (!test_bit(TSQ_THROTTLED, &tp->tsq_flags)) {
+ if (!test_bit(TSQ_THROTTLED, &sk->sk_tsq_flags)) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);
- set_bit(TSQ_THROTTLED, &tp->tsq_flags);
+ set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);
}
/* It is possible TX completion already happened
* before we set TSQ_THROTTLED.
@@ -998,8 +996,11 @@ do_error:
goto out;
out_err:
/* make sure we wake any epoll edge trigger waiter */
- if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 && err == -EAGAIN))
+ if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 &&
+ err == -EAGAIN)) {
sk->sk_write_space(sk);
+ tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
+ }
return sk_stream_error(sk, flags, err);
}
@@ -1333,8 +1334,11 @@ do_error:
out_err:
err = sk_stream_error(sk, flags, err);
/* make sure we wake any epoll edge trigger waiter */
- if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 && err == -EAGAIN))
+ if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 &&
+ err == -EAGAIN)) {
sk->sk_write_space(sk);
+ tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
+ }
release_sock(sk);
return err;
}
@@ -2302,7 +2306,7 @@ EXPORT_SYMBOL(tcp_disconnect);
static inline bool tcp_can_repair_sock(const struct sock *sk)
{
return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
- ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
+ (sk->sk_state != TCP_LISTEN);
}
static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int len)
@@ -2704,15 +2708,33 @@ int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
EXPORT_SYMBOL(compat_tcp_setsockopt);
#endif
+static void tcp_get_info_chrono_stats(const struct tcp_sock *tp,
+ struct tcp_info *info)
+{
+ u64 stats[__TCP_CHRONO_MAX], total = 0;
+ enum tcp_chrono i;
+
+ for (i = TCP_CHRONO_BUSY; i < __TCP_CHRONO_MAX; ++i) {
+ stats[i] = tp->chrono_stat[i - 1];
+ if (i == tp->chrono_type)
+ stats[i] += tcp_time_stamp - tp->chrono_start;
+ stats[i] *= USEC_PER_SEC / HZ;
+ total += stats[i];
+ }
+
+ info->tcpi_busy_time = total;
+ info->tcpi_rwnd_limited = stats[TCP_CHRONO_RWND_LIMITED];
+ info->tcpi_sndbuf_limited = stats[TCP_CHRONO_SNDBUF_LIMITED];
+}
+
/* Return information about state of tcp endpoint in API format. */
void tcp_get_info(struct sock *sk, struct tcp_info *info)
{
const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
const struct inet_connection_sock *icsk = inet_csk(sk);
u32 now = tcp_time_stamp, intv;
- unsigned int start;
- int notsent_bytes;
u64 rate64;
+ bool slow;
u32 rate;
memset(info, 0, sizeof(*info));
@@ -2721,6 +2743,27 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_state = sk_state_load(sk);
+ /* Report meaningful fields for all TCP states, including listeners */
+ rate = READ_ONCE(sk->sk_pacing_rate);
+ rate64 = rate != ~0U ? rate : ~0ULL;
+ info->tcpi_pacing_rate = rate64;
+
+ rate = READ_ONCE(sk->sk_max_pacing_rate);
+ rate64 = rate != ~0U ? rate : ~0ULL;
+ info->tcpi_max_pacing_rate = rate64;
+
+ info->tcpi_reordering = tp->reordering;
+ info->tcpi_snd_cwnd = tp->snd_cwnd;
+
+ if (info->tcpi_state == TCP_LISTEN) {
+ /* listeners aliased fields :
+ * tcpi_unacked -> Number of children ready for accept()
+ * tcpi_sacked -> max backlog
+ */
+ info->tcpi_unacked = sk->sk_ack_backlog;
+ info->tcpi_sacked = sk->sk_max_ack_backlog;
+ return;
+ }
info->tcpi_ca_state = icsk->icsk_ca_state;
info->tcpi_retransmits = icsk->icsk_retransmits;
info->tcpi_probes = icsk->icsk_probes_out;
@@ -2748,13 +2791,9 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_snd_mss = tp->mss_cache;
info->tcpi_rcv_mss = icsk->icsk_ack.rcv_mss;
- if (info->tcpi_state == TCP_LISTEN) {
- info->tcpi_unacked = sk->sk_ack_backlog;
- info->tcpi_sacked = sk->sk_max_ack_backlog;
- } else {
- info->tcpi_unacked = tp->packets_out;
- info->tcpi_sacked = tp->sacked_out;
- }
+ info->tcpi_unacked = tp->packets_out;
+ info->tcpi_sacked = tp->sacked_out;
+
info->tcpi_lost = tp->lost_out;
info->tcpi_retrans = tp->retrans_out;
info->tcpi_fackets = tp->fackets_out;
@@ -2768,34 +2807,25 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_rtt = tp->srtt_us >> 3;
info->tcpi_rttvar = tp->mdev_us >> 2;
info->tcpi_snd_ssthresh = tp->snd_ssthresh;
- info->tcpi_snd_cwnd = tp->snd_cwnd;
info->tcpi_advmss = tp->advmss;
- info->tcpi_reordering = tp->reordering;
info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
info->tcpi_rcv_space = tp->rcvq_space.space;
info->tcpi_total_retrans = tp->total_retrans;
- rate = READ_ONCE(sk->sk_pacing_rate);
- rate64 = rate != ~0U ? rate : ~0ULL;
- put_unaligned(rate64, &info->tcpi_pacing_rate);
+ slow = lock_sock_fast(sk);
- rate = READ_ONCE(sk->sk_max_pacing_rate);
- rate64 = rate != ~0U ? rate : ~0ULL;
- put_unaligned(rate64, &info->tcpi_max_pacing_rate);
+ info->tcpi_bytes_acked = tp->bytes_acked;
+ info->tcpi_bytes_received = tp->bytes_received;
+ info->tcpi_notsent_bytes = max_t(int, 0, tp->write_seq - tp->snd_nxt);
+ tcp_get_info_chrono_stats(tp, info);
+
+ unlock_sock_fast(sk, slow);
- do {
- start = u64_stats_fetch_begin_irq(&tp->syncp);
- put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked);
- put_unaligned(tp->bytes_received, &info->tcpi_bytes_received);
- } while (u64_stats_fetch_retry_irq(&tp->syncp, start));
info->tcpi_segs_out = tp->segs_out;
info->tcpi_segs_in = tp->segs_in;
- notsent_bytes = READ_ONCE(tp->write_seq) - READ_ONCE(tp->snd_nxt);
- info->tcpi_notsent_bytes = max(0, notsent_bytes);
-
info->tcpi_min_rtt = tcp_min_rtt(tp);
info->tcpi_data_segs_in = tp->data_segs_in;
info->tcpi_data_segs_out = tp->data_segs_out;
@@ -2806,11 +2836,31 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
if (rate && intv) {
rate64 = (u64)rate * tp->mss_cache * USEC_PER_SEC;
do_div(rate64, intv);
- put_unaligned(rate64, &info->tcpi_delivery_rate);
+ info->tcpi_delivery_rate = rate64;
}
}
EXPORT_SYMBOL_GPL(tcp_get_info);
+struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct sk_buff *stats;
+ struct tcp_info info;
+
+ stats = alloc_skb(3 * nla_total_size_64bit(sizeof(u64)), GFP_ATOMIC);
+ if (!stats)
+ return NULL;
+
+ tcp_get_info_chrono_stats(tp, &info);
+ nla_put_u64_64bit(stats, TCP_NLA_BUSY,
+ info.tcpi_busy_time, TCP_NLA_PAD);
+ nla_put_u64_64bit(stats, TCP_NLA_RWND_LIMITED,
+ info.tcpi_rwnd_limited, TCP_NLA_PAD);
+ nla_put_u64_64bit(stats, TCP_NLA_SNDBUF_LIMITED,
+ info.tcpi_sndbuf_limited, TCP_NLA_PAD);
+ return stats;
+}
+
static int do_tcp_getsockopt(struct sock *sk, int level,
int optname, char __user *optval, int __user *optlen)
{
diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c
index 0ea66c2c9344..b89bce4c721e 100644
--- a/net/ipv4/tcp_bbr.c
+++ b/net/ipv4/tcp_bbr.c
@@ -14,6 +14,36 @@
* observed, or adjust the sending rate if it estimates there is a
* traffic policer, in order to keep the drop rate reasonable.
*
+ * Here is a state transition diagram for BBR:
+ *
+ * |
+ * V
+ * +---> STARTUP ----+
+ * | | |
+ * | V |
+ * | DRAIN ----+
+ * | | |
+ * | V |
+ * +---> PROBE_BW ----+
+ * | ^ | |
+ * | | | |
+ * | +----+ |
+ * | |
+ * +---- PROBE_RTT <--+
+ *
+ * A BBR flow starts in STARTUP, and ramps up its sending rate quickly.
+ * When it estimates the pipe is full, it enters DRAIN to drain the queue.
+ * In steady state a BBR flow only uses PROBE_BW and PROBE_RTT.
+ * A long-lived BBR flow spends the vast majority of its time remaining
+ * (repeatedly) in PROBE_BW, fully probing and utilizing the pipe's bandwidth
+ * in a fair manner, with a small, bounded queue. *If* a flow has been
+ * continuously sending for the entire min_rtt window, and hasn't seen an RTT
+ * sample that matches or decreases its min_rtt estimate for 10 seconds, then
+ * it briefly enters PROBE_RTT to cut inflight to a minimum value to re-probe
+ * the path's two-way propagation delay (min_rtt). When exiting PROBE_RTT, if
+ * we estimated that we reached the full bw of the pipe then we enter PROBE_BW;
+ * otherwise we enter STARTUP to try to fill the pipe.
+ *
* BBR is described in detail in:
* "BBR: Congestion-Based Congestion Control",
* Neal Cardwell, Yuchung Cheng, C. Stephen Gunn, Soheil Hassas Yeganeh,
@@ -51,7 +81,7 @@ enum bbr_mode {
BBR_STARTUP, /* ramp up sending rate rapidly to fill pipe */
BBR_DRAIN, /* drain any queue created during startup */
BBR_PROBE_BW, /* discover, share bw: pace around estimated bw */
- BBR_PROBE_RTT, /* cut cwnd to min to probe min_rtt */
+ BBR_PROBE_RTT, /* cut inflight to min to probe min_rtt */
};
/* BBR congestion control block */
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index f9038d6b109e..79c4817abc94 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -68,8 +68,9 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
{
int ret = 0;
- /* all algorithms must implement ssthresh and cong_avoid ops */
- if (!ca->ssthresh || !(ca->cong_avoid || ca->cong_control)) {
+ /* all algorithms must implement these */
+ if (!ca->ssthresh || !ca->undo_cwnd ||
+ !(ca->cong_avoid || ca->cong_control)) {
pr_err("%s does not implement required ops\n", ca->name);
return -EINVAL;
}
@@ -443,10 +444,19 @@ u32 tcp_reno_ssthresh(struct sock *sk)
}
EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
+u32 tcp_reno_undo_cwnd(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+
+ return max(tp->snd_cwnd, tp->snd_ssthresh << 1);
+}
+EXPORT_SYMBOL_GPL(tcp_reno_undo_cwnd);
+
struct tcp_congestion_ops tcp_reno = {
.flags = TCP_CONG_NON_RESTRICTED,
.name = "reno",
.owner = THIS_MODULE,
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
+ .undo_cwnd = tcp_reno_undo_cwnd,
};
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
index ab37c6775630..5f5e5936760e 100644
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -335,6 +335,7 @@ static struct tcp_congestion_ops dctcp __read_mostly = {
static struct tcp_congestion_ops dctcp_reno __read_mostly = {
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
+ .undo_cwnd = tcp_reno_undo_cwnd,
.get_info = dctcp_get_info,
.owner = THIS_MODULE,
.name = "dctcp-reno",
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index db7842495a64..6d9879e93648 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -94,6 +94,7 @@ static const struct hstcp_aimd_val {
struct hstcp {
u32 ai;
+ u32 loss_cwnd;
};
static void hstcp_init(struct sock *sk)
@@ -150,16 +151,24 @@ static void hstcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
static u32 hstcp_ssthresh(struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk);
- const struct hstcp *ca = inet_csk_ca(sk);
+ struct hstcp *ca = inet_csk_ca(sk);
+ ca->loss_cwnd = tp->snd_cwnd;
/* Do multiplicative decrease */
return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
}
+static u32 hstcp_cwnd_undo(struct sock *sk)
+{
+ const struct hstcp *ca = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
+}
static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
.init = hstcp_init,
.ssthresh = hstcp_ssthresh,
+ .undo_cwnd = hstcp_cwnd_undo,
.cong_avoid = hstcp_cong_avoid,
.owner = THIS_MODULE,
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index 083831e359df..0f7175c3338e 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -166,6 +166,7 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked)
static struct tcp_congestion_ops tcp_hybla __read_mostly = {
.init = hybla_init,
.ssthresh = tcp_reno_ssthresh,
+ .undo_cwnd = tcp_reno_undo_cwnd,
.cong_avoid = hybla_cong_avoid,
.set_state = hybla_state,
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index c8e6d86be114..60352ff4f5a8 100644
--- a/net/ipv4/tcp_illinois.c
+++ b/net/ipv4/tcp_illinois.c
@@ -48,6 +48,7 @@ struct illinois {
u32 end_seq; /* right edge of current RTT */
u32 alpha; /* Additive increase */
u32 beta; /* Muliplicative decrease */
+ u32 loss_cwnd; /* cwnd on loss */
u16 acked; /* # packets acked by current ACK */
u8 rtt_above; /* average rtt has gone above threshold */
u8 rtt_low; /* # of rtts measurements below threshold */
@@ -296,10 +297,18 @@ static u32 tcp_illinois_ssthresh(struct sock *sk)
struct tcp_sock *tp = tcp_sk(sk);
struct illinois *ca = inet_csk_ca(sk);
+ ca->loss_cwnd = tp->snd_cwnd;
/* Multiplicative decrease */
return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->beta) >> BETA_SHIFT), 2U);
}
+static u32 tcp_illinois_cwnd_undo(struct sock *sk)
+{
+ const struct illinois *ca = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
+}
+
/* Extract info for Tcp socket info provided via netlink. */
static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
union tcp_cc_info *info)
@@ -327,6 +336,7 @@ static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
static struct tcp_congestion_ops tcp_illinois __read_mostly = {
.init = tcp_illinois_init,
.ssthresh = tcp_illinois_ssthresh,
+ .undo_cwnd = tcp_illinois_cwnd_undo,
.cong_avoid = tcp_illinois_cong_avoid,
.set_state = tcp_illinois_state,
.get_info = tcp_illinois_info,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c71d49ce0c93..6c790754ae3e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -85,6 +85,7 @@ int sysctl_tcp_dsack __read_mostly = 1;
int sysctl_tcp_app_win __read_mostly = 31;
int sysctl_tcp_adv_win_scale __read_mostly = 1;
EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
+EXPORT_SYMBOL(sysctl_tcp_timestamps);
/* rfc5961 challenge ack rate limiting */
int sysctl_tcp_challenge_ack_limit = 1000;
@@ -2414,10 +2415,7 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss)
if (tp->prior_ssthresh) {
const struct inet_connection_sock *icsk = inet_csk(sk);
- if (icsk->icsk_ca_ops->undo_cwnd)
- tp->snd_cwnd = icsk->icsk_ca_ops->undo_cwnd(sk);
- else
- tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1);
+ tp->snd_cwnd = icsk->icsk_ca_ops->undo_cwnd(sk);
if (tp->prior_ssthresh > tp->snd_ssthresh) {
tp->snd_ssthresh = tp->prior_ssthresh;
@@ -3201,6 +3199,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
tp->lost_skb_hint = NULL;
}
+ if (!skb)
+ tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
+
if (likely(between(tp->snd_up, prior_snd_una, tp->snd_una)))
tp->snd_up = tp->snd_una;
@@ -3371,9 +3372,7 @@ static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack)
u32 delta = ack - tp->snd_una;
sock_owned_by_me((struct sock *)tp);
- u64_stats_update_begin_raw(&tp->syncp);
tp->bytes_acked += delta;
- u64_stats_update_end_raw(&tp->syncp);
tp->snd_una = ack;
}
@@ -3383,9 +3382,7 @@ static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq)
u32 delta = seq - tp->rcv_nxt;
sock_owned_by_me((struct sock *)tp);
- u64_stats_update_begin_raw(&tp->syncp);
tp->bytes_received += delta;
- u64_stats_update_end_raw(&tp->syncp);
tp->rcv_nxt = seq;
}
@@ -5083,8 +5080,11 @@ static void tcp_check_space(struct sock *sk)
/* pairs with tcp_poll() */
smp_mb__after_atomic();
if (sk->sk_socket &&
- test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
+ test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
tcp_new_space(sk);
+ if (!test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
+ tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
+ }
}
}
@@ -6318,13 +6318,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
goto drop;
}
-
- /* Accept backlog is full. If we have already queued enough
- * of warm entries in syn queue, drop request. It is better than
- * clogging syn queue with openreqs with exponentially increasing
- * timeout.
- */
- if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+ if (sk_acceptq_is_full(sk)) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
goto drop;
}
@@ -6334,6 +6328,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
goto drop;
tcp_rsk(req)->af_specific = af_ops;
+ tcp_rsk(req)->ts_off = 0;
tcp_clear_options(&tmp_opt);
tmp_opt.mss_clamp = af_ops->mss_clamp;
@@ -6355,6 +6350,9 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;
+ if (isn && tmp_opt.tstamp_ok)
+ af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
+
if (!want_cookie && !isn) {
/* VJ's idea. We save last timestamp seen
* from the destination in peer table, when entering
@@ -6395,7 +6393,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
goto drop_and_release;
}
- isn = af_ops->init_seq(skb);
+ isn = af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
}
if (!dst) {
dst = af_ops->route_req(sk, &fl, req, NULL);
@@ -6407,6 +6405,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
if (want_cookie) {
isn = cookie_init_sequence(af_ops, sk, skb, &req->mss);
+ tcp_rsk(req)->ts_off = 0;
req->cookie_ts = tmp_opt.tstamp_ok;
if (!tmp_opt.tstamp_ok)
inet_rsk(req)->ecn_ok = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 2259114c7242..30d81f533ada 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -95,12 +95,12 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
struct inet_hashinfo tcp_hashinfo;
EXPORT_SYMBOL(tcp_hashinfo);
-static __u32 tcp_v4_init_sequence(const struct sk_buff *skb)
+static u32 tcp_v4_init_sequence(const struct sk_buff *skb, u32 *tsoff)
{
return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
ip_hdr(skb)->saddr,
tcp_hdr(skb)->dest,
- tcp_hdr(skb)->source);
+ tcp_hdr(skb)->source, tsoff);
}
int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -237,7 +237,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
inet->inet_daddr,
inet->inet_sport,
- usin->sin_port);
+ usin->sin_port,
+ &tp->tsoffset);
inet->inet_id = tp->write_seq ^ jiffies;
@@ -442,7 +443,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
if (!sock_owned_by_user(sk)) {
tcp_v4_mtu_reduced(sk);
} else {
- if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags))
+ if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &sk->sk_tsq_flags))
sock_hold(sk);
}
goto out;
@@ -691,6 +692,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
offsetof(struct inet_timewait_sock, tw_bound_dev_if));
arg.tos = ip_hdr(skb)->tos;
+ arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
local_bh_disable();
ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
skb, &TCP_SKB_CB(skb)->header.h4.opt,
@@ -711,7 +713,7 @@ out:
outside socket context is ugly, certainly. What can I do?
*/
-static void tcp_v4_send_ack(struct net *net,
+static void tcp_v4_send_ack(const struct sock *sk,
struct sk_buff *skb, u32 seq, u32 ack,
u32 win, u32 tsval, u32 tsecr, int oif,
struct tcp_md5sig_key *key,
@@ -726,6 +728,7 @@ static void tcp_v4_send_ack(struct net *net,
#endif
];
} rep;
+ struct net *net = sock_net(sk);
struct ip_reply_arg arg;
memset(&rep.th, 0, sizeof(struct tcphdr));
@@ -775,6 +778,7 @@ static void tcp_v4_send_ack(struct net *net,
if (oif)
arg.bound_dev_if = oif;
arg.tos = tos;
+ arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
local_bh_disable();
ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
skb, &TCP_SKB_CB(skb)->header.h4.opt,
@@ -790,7 +794,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
struct inet_timewait_sock *tw = inet_twsk(sk);
struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v4_send_ack(sock_net(sk), skb,
+ tcp_v4_send_ack(sk, skb,
tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
tcp_time_stamp + tcptw->tw_ts_offset,
@@ -818,10 +822,10 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
* exception of <SYN> segments, MUST be right-shifted by
* Rcv.Wind.Shift bits:
*/
- tcp_v4_send_ack(sock_net(sk), skb, seq,
+ tcp_v4_send_ack(sk, skb, seq,
tcp_rsk(req)->rcv_nxt,
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
- tcp_time_stamp,
+ tcp_time_stamp + tcp_rsk(req)->ts_off,
req->ts_recent,
0,
tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr,
@@ -1908,7 +1912,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (!sk) {
get_head:
ilb = &tcp_hashinfo.listening_hash[st->bucket];
- spin_lock_bh(&ilb->lock);
+ spin_lock(&ilb->lock);
sk = sk_head(&ilb->head);
st->offset = 0;
goto get_sk;
@@ -1925,7 +1929,7 @@ get_sk:
if (sk->sk_family == st->family)
return sk;
}
- spin_unlock_bh(&ilb->lock);
+ spin_unlock(&ilb->lock);
st->offset = 0;
if (++st->bucket < INET_LHTABLE_SIZE)
goto get_head;
@@ -2133,7 +2137,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
switch (st->state) {
case TCP_SEQ_STATE_LISTENING:
if (v != SEQ_START_TOKEN)
- spin_unlock_bh(&tcp_hashinfo.listening_hash[st->bucket].lock);
+ spin_unlock(&tcp_hashinfo.listening_hash[st->bucket].lock);
break;
case TCP_SEQ_STATE_ESTABLISHED:
if (v)
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index c67ece1390c2..046fd3910873 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -316,6 +316,7 @@ static void tcp_lp_pkts_acked(struct sock *sk, const struct ack_sample *sample)
static struct tcp_congestion_ops tcp_lp __read_mostly = {
.init = tcp_lp_init,
.ssthresh = tcp_reno_ssthresh,
+ .undo_cwnd = tcp_reno_undo_cwnd,
.cong_avoid = tcp_lp_cong_avoid,
.pkts_acked = tcp_lp_pkts_acked,
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index bf1f3b2b29d1..d46f4d5b1c62 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -742,14 +742,7 @@ void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
rcu_read_unlock();
}
-static struct genl_family tcp_metrics_nl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = TCP_METRICS_GENL_NAME,
- .version = TCP_METRICS_GENL_VERSION,
- .maxattr = TCP_METRICS_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family tcp_metrics_nl_family;
static const struct nla_policy tcp_metrics_nl_policy[TCP_METRICS_ATTR_MAX + 1] = {
[TCP_METRICS_ATTR_ADDR_IPV4] = { .type = NLA_U32, },
@@ -1116,6 +1109,17 @@ static const struct genl_ops tcp_metrics_nl_ops[] = {
},
};
+static struct genl_family tcp_metrics_nl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = TCP_METRICS_GENL_NAME,
+ .version = TCP_METRICS_GENL_VERSION,
+ .maxattr = TCP_METRICS_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = tcp_metrics_nl_ops,
+ .n_ops = ARRAY_SIZE(tcp_metrics_nl_ops),
+};
+
static unsigned int tcpmhash_entries;
static int __init set_tcpmhash_entries(char *str)
{
@@ -1179,8 +1183,7 @@ void __init tcp_metrics_init(void)
if (ret < 0)
panic("Could not allocate the tcp_metrics hash table\n");
- ret = genl_register_family_with_ops(&tcp_metrics_nl_family,
- tcp_metrics_nl_ops);
+ ret = genl_register_family(&tcp_metrics_nl_family);
if (ret < 0)
panic("Could not register tcp_metrics generic netlink\n");
}
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 6234ebaa7db1..28ce5ee831f5 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -532,7 +532,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
newtp->rx_opt.ts_recent_stamp = 0;
newtp->tcp_header_len = sizeof(struct tcphdr);
}
- newtp->tsoffset = 0;
+ newtp->tsoffset = treq->ts_off;
#ifdef CONFIG_TCP_MD5SIG
newtp->md5sig_info = NULL; /*XXX*/
if (newtp->af_specific->md5_lookup(sk, newsk))
@@ -581,6 +581,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
if (tmp_opt.saw_tstamp) {
tmp_opt.ts_recent = req->ts_recent;
+ if (tmp_opt.rcv_tsecr)
+ tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off;
/* We do not store true stamp, but it is not required,
* it can be estimated (approximately)
* from another data.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 896e9dfbdb5c..b45101f3d2bd 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -640,7 +640,7 @@ static unsigned int tcp_synack_options(struct request_sock *req,
}
if (likely(ireq->tstamp_ok)) {
opts->options |= OPTION_TS;
- opts->tsval = tcp_skb_timestamp(skb);
+ opts->tsval = tcp_skb_timestamp(skb) + tcp_rsk(req)->ts_off;
opts->tsecr = req->ts_recent;
remaining -= TCPOLEN_TSTAMP_ALIGNED;
}
@@ -769,25 +769,26 @@ static void tcp_tasklet_func(unsigned long data)
list_del(&tp->tsq_node);
sk = (struct sock *)tp;
- bh_lock_sock(sk);
-
- if (!sock_owned_by_user(sk)) {
- tcp_tsq_handler(sk);
- } else {
- /* defer the work to tcp_release_cb() */
- set_bit(TCP_TSQ_DEFERRED, &tp->tsq_flags);
+ clear_bit(TSQ_QUEUED, &sk->sk_tsq_flags);
+
+ if (!sk->sk_lock.owned &&
+ test_bit(TCP_TSQ_DEFERRED, &sk->sk_tsq_flags)) {
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk)) {
+ clear_bit(TCP_TSQ_DEFERRED, &sk->sk_tsq_flags);
+ tcp_tsq_handler(sk);
+ }
+ bh_unlock_sock(sk);
}
- bh_unlock_sock(sk);
- clear_bit(TSQ_QUEUED, &tp->tsq_flags);
sk_free(sk);
}
}
-#define TCP_DEFERRED_ALL ((1UL << TCP_TSQ_DEFERRED) | \
- (1UL << TCP_WRITE_TIMER_DEFERRED) | \
- (1UL << TCP_DELACK_TIMER_DEFERRED) | \
- (1UL << TCP_MTU_REDUCED_DEFERRED))
+#define TCP_DEFERRED_ALL (TCPF_TSQ_DEFERRED | \
+ TCPF_WRITE_TIMER_DEFERRED | \
+ TCPF_DELACK_TIMER_DEFERRED | \
+ TCPF_MTU_REDUCED_DEFERRED)
/**
* tcp_release_cb - tcp release_sock() callback
* @sk: socket
@@ -797,18 +798,17 @@ static void tcp_tasklet_func(unsigned long data)
*/
void tcp_release_cb(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
unsigned long flags, nflags;
/* perform an atomic operation only if at least one flag is set */
do {
- flags = tp->tsq_flags;
+ flags = sk->sk_tsq_flags;
if (!(flags & TCP_DEFERRED_ALL))
return;
nflags = flags & ~TCP_DEFERRED_ALL;
- } while (cmpxchg(&tp->tsq_flags, flags, nflags) != flags);
+ } while (cmpxchg(&sk->sk_tsq_flags, flags, nflags) != flags);
- if (flags & (1UL << TCP_TSQ_DEFERRED))
+ if (flags & TCPF_TSQ_DEFERRED)
tcp_tsq_handler(sk);
/* Here begins the tricky part :
@@ -822,15 +822,15 @@ void tcp_release_cb(struct sock *sk)
*/
sock_release_ownership(sk);
- if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) {
+ if (flags & TCPF_WRITE_TIMER_DEFERRED) {
tcp_write_timer_handler(sk);
__sock_put(sk);
}
- if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) {
+ if (flags & TCPF_DELACK_TIMER_DEFERRED) {
tcp_delack_timer_handler(sk);
__sock_put(sk);
}
- if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) {
+ if (flags & TCPF_MTU_REDUCED_DEFERRED) {
inet_csk(sk)->icsk_af_ops->mtu_reduced(sk);
__sock_put(sk);
}
@@ -860,6 +860,7 @@ void tcp_wfree(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
struct tcp_sock *tp = tcp_sk(sk);
+ unsigned long flags, nval, oval;
int wmem;
/* Keep one reference on sk_wmem_alloc.
@@ -877,16 +878,25 @@ void tcp_wfree(struct sk_buff *skb)
if (wmem >= SKB_TRUESIZE(1) && this_cpu_ksoftirqd() == current)
goto out;
- if (test_and_clear_bit(TSQ_THROTTLED, &tp->tsq_flags) &&
- !test_and_set_bit(TSQ_QUEUED, &tp->tsq_flags)) {
- unsigned long flags;
+ for (oval = READ_ONCE(sk->sk_tsq_flags);; oval = nval) {
struct tsq_tasklet *tsq;
+ bool empty;
+
+ if (!(oval & TSQF_THROTTLED) || (oval & TSQF_QUEUED))
+ goto out;
+
+ nval = (oval & ~TSQF_THROTTLED) | TSQF_QUEUED | TCPF_TSQ_DEFERRED;
+ nval = cmpxchg(&sk->sk_tsq_flags, oval, nval);
+ if (nval != oval)
+ continue;
/* queue this socket to tasklet queue */
local_irq_save(flags);
tsq = this_cpu_ptr(&tsq_tasklet);
+ empty = list_empty(&tsq->head);
list_add(&tp->tsq_node, &tsq->head);
- tasklet_schedule(&tsq->tasklet);
+ if (empty)
+ tasklet_schedule(&tsq->tasklet);
local_irq_restore(flags);
return;
}
@@ -1514,6 +1524,18 @@ static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited)
if (sysctl_tcp_slow_start_after_idle &&
(s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto)
tcp_cwnd_application_limited(sk);
+
+ /* The following conditions together indicate the starvation
+ * is caused by insufficient sender buffer:
+ * 1) just sent some data (see tcp_write_xmit)
+ * 2) not cwnd limited (this else condition)
+ * 3) no more data to send (null tcp_send_head )
+ * 4) application is hitting buffer limit (SOCK_NOSPACE)
+ */
+ if (!tcp_send_head(sk) && sk->sk_socket &&
+ test_bit(SOCK_NOSPACE, &sk->sk_socket->flags) &&
+ (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+ tcp_chrono_start(sk, TCP_CHRONO_SNDBUF_LIMITED);
}
}
@@ -1910,26 +1932,26 @@ static inline void tcp_mtu_check_reprobe(struct sock *sk)
*/
static int tcp_mtu_probe(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb, *nskb, *next;
struct net *net = sock_net(sk);
- int len;
int probe_size;
int size_needed;
- int copy;
+ int copy, len;
int mss_now;
int interval;
/* Not currently probing/verifying,
* not in recovery,
* have enough cwnd, and
- * not SACKing (the variable headers throw things off) */
- if (!icsk->icsk_mtup.enabled ||
- icsk->icsk_mtup.probe_size ||
- inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
- tp->snd_cwnd < 11 ||
- tp->rx_opt.num_sacks || tp->rx_opt.dsack)
+ * not SACKing (the variable headers throw things off)
+ */
+ if (likely(!icsk->icsk_mtup.enabled ||
+ icsk->icsk_mtup.probe_size ||
+ inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
+ tp->snd_cwnd < 11 ||
+ tp->rx_opt.num_sacks || tp->rx_opt.dsack))
return -1;
/* Use binary search for probe_size between tcp_mss_base,
@@ -2069,7 +2091,16 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
limit <<= factor;
if (atomic_read(&sk->sk_wmem_alloc) > limit) {
- set_bit(TSQ_THROTTLED, &tcp_sk(sk)->tsq_flags);
+ /* Always send the 1st or 2nd skb in write queue.
+ * No need to wait for TX completion to call us back,
+ * after softirq/tasklet schedule.
+ * This helps when TX completions are delayed too much.
+ */
+ if (skb == sk->sk_write_queue.next ||
+ skb->prev == sk->sk_write_queue.next)
+ return false;
+
+ set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);
/* It is possible TX completion already happened
* before we set TSQ_THROTTLED, so we must
* test again the condition.
@@ -2081,6 +2112,47 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
return false;
}
+static void tcp_chrono_set(struct tcp_sock *tp, const enum tcp_chrono new)
+{
+ const u32 now = tcp_time_stamp;
+
+ if (tp->chrono_type > TCP_CHRONO_UNSPEC)
+ tp->chrono_stat[tp->chrono_type - 1] += now - tp->chrono_start;
+ tp->chrono_start = now;
+ tp->chrono_type = new;
+}
+
+void tcp_chrono_start(struct sock *sk, const enum tcp_chrono type)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ /* If there are multiple conditions worthy of tracking in a
+ * chronograph then the highest priority enum takes precedence
+ * over the other conditions. So that if something "more interesting"
+ * starts happening, stop the previous chrono and start a new one.
+ */
+ if (type > tp->chrono_type)
+ tcp_chrono_set(tp, type);
+}
+
+void tcp_chrono_stop(struct sock *sk, const enum tcp_chrono type)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+
+ /* There are multiple conditions worthy of tracking in a
+ * chronograph, so that the highest priority enum takes
+ * precedence over the other conditions (see tcp_chrono_start).
+ * If a condition stops, we only stop chrono tracking if
+ * it's the "most interesting" or current chrono we are
+ * tracking and starts busy chrono if we have pending data.
+ */
+ if (tcp_write_queue_empty(sk))
+ tcp_chrono_set(tp, TCP_CHRONO_UNSPEC);
+ else if (type == tp->chrono_type)
+ tcp_chrono_set(tp, TCP_CHRONO_BUSY);
+}
+
/* This routine writes packets to the network. It advances the
* send_head. This happens as incoming acks open up the remote
* window for us.
@@ -2103,7 +2175,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
unsigned int tso_segs, sent_pkts;
int cwnd_quota;
int result;
- bool is_cwnd_limited = false;
+ bool is_cwnd_limited = false, is_rwnd_limited = false;
u32 max_segs;
sent_pkts = 0;
@@ -2140,8 +2212,10 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
break;
}
- if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
+ if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) {
+ is_rwnd_limited = true;
break;
+ }
if (tso_segs == 1) {
if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
@@ -2167,6 +2241,8 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
break;
+ if (test_bit(TCP_TSQ_DEFERRED, &sk->sk_tsq_flags))
+ clear_bit(TCP_TSQ_DEFERRED, &sk->sk_tsq_flags);
if (tcp_small_queue_check(sk, skb, 0))
break;
@@ -2186,6 +2262,11 @@ repair:
break;
}
+ if (is_rwnd_limited)
+ tcp_chrono_start(sk, TCP_CHRONO_RWND_LIMITED);
+ else
+ tcp_chrono_stop(sk, TCP_CHRONO_RWND_LIMITED);
+
if (likely(sent_pkts)) {
if (tcp_in_cwnd_reduction(sk))
tp->prr_out += sent_pkts;
@@ -2514,7 +2595,7 @@ void tcp_skb_collapse_tstamp(struct sk_buff *skb,
}
/* Collapses two adjacent SKB's during retransmission. */
-static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
+static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *next_skb = tcp_write_queue_next(sk, skb);
@@ -2525,13 +2606,17 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1);
+ if (next_skb_size) {
+ if (next_skb_size <= skb_availroom(skb))
+ skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size),
+ next_skb_size);
+ else if (!skb_shift(skb, next_skb, next_skb_size))
+ return false;
+ }
tcp_highest_sack_combine(sk, next_skb, skb);
tcp_unlink_write_queue(next_skb, sk);
- skb_copy_from_linear_data(next_skb, skb_put(skb, next_skb_size),
- next_skb_size);
-
if (next_skb->ip_summed == CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_PARTIAL;
@@ -2560,6 +2645,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
tcp_skb_collapse_tstamp(skb, next_skb);
sk_wmem_free_skb(sk, next_skb);
+ return true;
}
/* Check if coalescing SKBs is legal. */
@@ -2567,14 +2653,11 @@ static bool tcp_can_collapse(const struct sock *sk, const struct sk_buff *skb)
{
if (tcp_skb_pcount(skb) > 1)
return false;
- /* TODO: SACK collapsing could be used to remove this condition */
- if (skb_shinfo(skb)->nr_frags != 0)
- return false;
if (skb_cloned(skb))
return false;
if (skb == tcp_send_head(sk))
return false;
- /* Some heurestics for collapsing over SACK'd could be invented */
+ /* Some heuristics for collapsing over SACK'd could be invented */
if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
return false;
@@ -2612,16 +2695,12 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
if (space < 0)
break;
- /* Punt if not enough space exists in the first SKB for
- * the data in the second
- */
- if (skb->len > skb_availroom(to))
- break;
if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp)))
break;
- tcp_collapse_retrans(sk, to);
+ if (!tcp_collapse_retrans(sk, to))
+ break;
}
}
@@ -3300,6 +3379,8 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
fo->copied = space;
tcp_connect_queue_skb(sk, syn_data);
+ if (syn_data->len)
+ tcp_chrono_start(sk, TCP_CHRONO_BUSY);
err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation);
@@ -3464,8 +3545,6 @@ void tcp_send_ack(struct sock *sk)
/* We do not want pure acks influencing TCP Small Queues or fq/pacing
* too much.
* SKB_TRUESIZE(max(1 .. 66, MAX_TCP_HEADER)) is unfortunately ~784
- * We also avoid tcp_wfree() overhead (cache line miss accessing
- * tp->tsq_flags) by using regular sock_wfree()
*/
skb_set_tcp_pure_ack(buff);
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
index bf5ea9e9bbc1..f2123075ce6e 100644
--- a/net/ipv4/tcp_scalable.c
+++ b/net/ipv4/tcp_scalable.c
@@ -15,6 +15,10 @@
#define TCP_SCALABLE_AI_CNT 50U
#define TCP_SCALABLE_MD_SCALE 3
+struct scalable {
+ u32 loss_cwnd;
+};
+
static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -32,12 +36,23 @@ static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked)
static u32 tcp_scalable_ssthresh(struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk);
+ struct scalable *ca = inet_csk_ca(sk);
+
+ ca->loss_cwnd = tp->snd_cwnd;
return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
}
+static u32 tcp_scalable_cwnd_undo(struct sock *sk)
+{
+ const struct scalable *ca = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
+}
+
static struct tcp_congestion_ops tcp_scalable __read_mostly = {
.ssthresh = tcp_scalable_ssthresh,
+ .undo_cwnd = tcp_scalable_cwnd_undo,
.cong_avoid = tcp_scalable_cong_avoid,
.owner = THIS_MODULE,
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 3ea1cf804748..3705075f42c3 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -310,7 +310,7 @@ static void tcp_delack_timer(unsigned long data)
inet_csk(sk)->icsk_ack.blocked = 1;
__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
/* deleguate our work to tcp_release_cb() */
- if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags))
+ if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &sk->sk_tsq_flags))
sock_hold(sk);
}
bh_unlock_sock(sk);
@@ -592,7 +592,7 @@ static void tcp_write_timer(unsigned long data)
tcp_write_timer_handler(sk);
} else {
/* delegate our work to tcp_release_cb() */
- if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags))
+ if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &sk->sk_tsq_flags))
sock_hold(sk);
}
bh_unlock_sock(sk);
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 4c4bac1b5eab..218cfcc77650 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -307,6 +307,7 @@ EXPORT_SYMBOL_GPL(tcp_vegas_get_info);
static struct tcp_congestion_ops tcp_vegas __read_mostly = {
.init = tcp_vegas_init,
.ssthresh = tcp_reno_ssthresh,
+ .undo_cwnd = tcp_reno_undo_cwnd,
.cong_avoid = tcp_vegas_cong_avoid,
.pkts_acked = tcp_vegas_pkts_acked,
.set_state = tcp_vegas_state,
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
index 40171e163cff..76005d4b8dfc 100644
--- a/net/ipv4/tcp_veno.c
+++ b/net/ipv4/tcp_veno.c
@@ -30,6 +30,7 @@ struct veno {
u32 basertt; /* the min of all Veno rtt measurements seen (in usec) */
u32 inc; /* decide whether to increase cwnd */
u32 diff; /* calculate the diff rate */
+ u32 loss_cwnd; /* cwnd when loss occured */
};
/* There are several situations when we must "re-start" Veno:
@@ -193,6 +194,7 @@ static u32 tcp_veno_ssthresh(struct sock *sk)
const struct tcp_sock *tp = tcp_sk(sk);
struct veno *veno = inet_csk_ca(sk);
+ veno->loss_cwnd = tp->snd_cwnd;
if (veno->diff < beta)
/* in "non-congestive state", cut cwnd by 1/5 */
return max(tp->snd_cwnd * 4 / 5, 2U);
@@ -201,9 +203,17 @@ static u32 tcp_veno_ssthresh(struct sock *sk)
return max(tp->snd_cwnd >> 1U, 2U);
}
+static u32 tcp_veno_cwnd_undo(struct sock *sk)
+{
+ const struct veno *veno = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, veno->loss_cwnd);
+}
+
static struct tcp_congestion_ops tcp_veno __read_mostly = {
.init = tcp_veno_init,
.ssthresh = tcp_veno_ssthresh,
+ .undo_cwnd = tcp_veno_cwnd_undo,
.cong_avoid = tcp_veno_cong_avoid,
.pkts_acked = tcp_veno_pkts_acked,
.set_state = tcp_veno_state,
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 4b03a2e2a050..fed66dc0e0f5 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -278,6 +278,7 @@ static struct tcp_congestion_ops tcp_westwood __read_mostly = {
.init = tcp_westwood_init,
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
+ .undo_cwnd = tcp_reno_undo_cwnd,
.cwnd_event = tcp_westwood_event,
.in_ack_event = tcp_westwood_ack,
.get_info = tcp_westwood_info,
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c
index 9c5fc973267f..e6ff99c4bd3b 100644
--- a/net/ipv4/tcp_yeah.c
+++ b/net/ipv4/tcp_yeah.c
@@ -37,6 +37,7 @@ struct yeah {
u32 fast_count;
u32 pkts_acked;
+ u32 loss_cwnd;
};
static void tcp_yeah_init(struct sock *sk)
@@ -219,13 +220,22 @@ static u32 tcp_yeah_ssthresh(struct sock *sk)
yeah->fast_count = 0;
yeah->reno_count = max(yeah->reno_count>>1, 2U);
+ yeah->loss_cwnd = tp->snd_cwnd;
return max_t(int, tp->snd_cwnd - reduction, 2);
}
+static u32 tcp_yeah_cwnd_undo(struct sock *sk)
+{
+ const struct yeah *yeah = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, yeah->loss_cwnd);
+}
+
static struct tcp_congestion_ops tcp_yeah __read_mostly = {
.init = tcp_yeah_init,
.ssthresh = tcp_yeah_ssthresh,
+ .undo_cwnd = tcp_yeah_cwnd_undo,
.cong_avoid = tcp_yeah_cong_avoid,
.set_state = tcp_vegas_state,
.cwnd_event = tcp_vegas_cwnd_event,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5bab6c3f7a2f..9ca279b130d5 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -580,7 +580,8 @@ EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb);
* Does increment socket refcount.
*/
#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \
- IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY)
+ IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) || \
+ IS_ENABLED(CONFIG_NF_SOCKET_IPV4)
struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif)
{
@@ -1019,7 +1020,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol,
flow_flags,
- faddr, saddr, dport, inet->inet_sport);
+ faddr, saddr, dport, inet->inet_sport,
+ sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk);
@@ -1172,6 +1174,181 @@ out:
return ret;
}
+/* fully reclaim rmem/fwd memory allocated for skb */
+static void udp_rmem_release(struct sock *sk, int size, int partial)
+{
+ struct udp_sock *up = udp_sk(sk);
+ int amt;
+
+ if (likely(partial)) {
+ up->forward_deficit += size;
+ size = up->forward_deficit;
+ if (size < (sk->sk_rcvbuf >> 2) &&
+ !skb_queue_empty(&sk->sk_receive_queue))
+ return;
+ } else {
+ size += up->forward_deficit;
+ }
+ up->forward_deficit = 0;
+
+ sk->sk_forward_alloc += size;
+ amt = (sk->sk_forward_alloc - partial) & ~(SK_MEM_QUANTUM - 1);
+ sk->sk_forward_alloc -= amt;
+
+ if (amt)
+ __sk_mem_reduce_allocated(sk, amt >> SK_MEM_QUANTUM_SHIFT);
+
+ atomic_sub(size, &sk->sk_rmem_alloc);
+}
+
+/* Note: called with sk_receive_queue.lock held.
+ * Instead of using skb->truesize here, find a copy of it in skb->dev_scratch
+ * This avoids a cache line miss while receive_queue lock is held.
+ * Look at __udp_enqueue_schedule_skb() to find where this copy is done.
+ */
+void udp_skb_destructor(struct sock *sk, struct sk_buff *skb)
+{
+ udp_rmem_release(sk, skb->dev_scratch, 1);
+}
+EXPORT_SYMBOL(udp_skb_destructor);
+
+/* Idea of busylocks is to let producers grab an extra spinlock
+ * to relieve pressure on the receive_queue spinlock shared by consumer.
+ * Under flood, this means that only one producer can be in line
+ * trying to acquire the receive_queue spinlock.
+ * These busylock can be allocated on a per cpu manner, instead of a
+ * per socket one (that would consume a cache line per socket)
+ */
+static int udp_busylocks_log __read_mostly;
+static spinlock_t *udp_busylocks __read_mostly;
+
+static spinlock_t *busylock_acquire(void *ptr)
+{
+ spinlock_t *busy;
+
+ busy = udp_busylocks + hash_ptr(ptr, udp_busylocks_log);
+ spin_lock(busy);
+ return busy;
+}
+
+static void busylock_release(spinlock_t *busy)
+{
+ if (busy)
+ spin_unlock(busy);
+}
+
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+{
+ struct sk_buff_head *list = &sk->sk_receive_queue;
+ int rmem, delta, amt, err = -ENOMEM;
+ spinlock_t *busy = NULL;
+ int size;
+
+ /* try to avoid the costly atomic add/sub pair when the receive
+ * queue is full; always allow at least a packet
+ */
+ rmem = atomic_read(&sk->sk_rmem_alloc);
+ if (rmem > sk->sk_rcvbuf)
+ goto drop;
+
+ /* Under mem pressure, it might be helpful to help udp_recvmsg()
+ * having linear skbs :
+ * - Reduce memory overhead and thus increase receive queue capacity
+ * - Less cache line misses at copyout() time
+ * - Less work at consume_skb() (less alien page frag freeing)
+ */
+ if (rmem > (sk->sk_rcvbuf >> 1)) {
+ skb_condense(skb);
+
+ busy = busylock_acquire(sk);
+ }
+ size = skb->truesize;
+ /* Copy skb->truesize into skb->dev_scratch to avoid a cache line miss
+ * in udp_skb_destructor()
+ */
+ skb->dev_scratch = size;
+
+ /* we drop only if the receive buf is full and the receive
+ * queue contains some other skb
+ */
+ rmem = atomic_add_return(size, &sk->sk_rmem_alloc);
+ if (rmem > (size + sk->sk_rcvbuf))
+ goto uncharge_drop;
+
+ spin_lock(&list->lock);
+ if (size >= sk->sk_forward_alloc) {
+ amt = sk_mem_pages(size);
+ delta = amt << SK_MEM_QUANTUM_SHIFT;
+ if (!__sk_mem_raise_allocated(sk, delta, amt, SK_MEM_RECV)) {
+ err = -ENOBUFS;
+ spin_unlock(&list->lock);
+ goto uncharge_drop;
+ }
+
+ sk->sk_forward_alloc += delta;
+ }
+
+ sk->sk_forward_alloc -= size;
+
+ /* no need to setup a destructor, we will explicitly release the
+ * forward allocated memory on dequeue
+ */
+ sock_skb_set_dropcount(sk, skb);
+
+ __skb_queue_tail(list, skb);
+ spin_unlock(&list->lock);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk);
+
+ busylock_release(busy);
+ return 0;
+
+uncharge_drop:
+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+
+drop:
+ atomic_inc(&sk->sk_drops);
+ busylock_release(busy);
+ return err;
+}
+EXPORT_SYMBOL_GPL(__udp_enqueue_schedule_skb);
+
+void udp_destruct_sock(struct sock *sk)
+{
+ /* reclaim completely the forward allocated memory */
+ unsigned int total = 0;
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ total += skb->truesize;
+ kfree_skb(skb);
+ }
+ udp_rmem_release(sk, total, 0);
+
+ inet_sock_destruct(sk);
+}
+EXPORT_SYMBOL_GPL(udp_destruct_sock);
+
+int udp_init_sock(struct sock *sk)
+{
+ sk->sk_destruct = udp_destruct_sock;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(udp_init_sock);
+
+void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
+{
+ if (unlikely(READ_ONCE(sk->sk_peek_off) >= 0)) {
+ bool slow = lock_sock_fast(sk);
+
+ sk_peek_offset_bwd(sk, len);
+ unlock_sock_fast(sk, slow);
+ }
+ consume_skb(skb);
+}
+EXPORT_SYMBOL_GPL(skb_consume_udp);
+
/**
* first_packet_length - return length of first packet in receive queue
* @sk: socket
@@ -1181,12 +1358,11 @@ out:
*/
static int first_packet_length(struct sock *sk)
{
- struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue;
+ struct sk_buff_head *rcvq = &sk->sk_receive_queue;
struct sk_buff *skb;
+ int total = 0;
int res;
- __skb_queue_head_init(&list_kill);
-
spin_lock_bh(&rcvq->lock);
while ((skb = skb_peek(rcvq)) != NULL &&
udp_lib_checksum_complete(skb)) {
@@ -1196,18 +1372,13 @@ static int first_packet_length(struct sock *sk)
IS_UDPLITE(sk));
atomic_inc(&sk->sk_drops);
__skb_unlink(skb, rcvq);
- __skb_queue_tail(&list_kill, skb);
+ total += skb->truesize;
+ kfree_skb(skb);
}
res = skb ? skb->len : -1;
+ if (total)
+ udp_rmem_release(sk, total, 1);
spin_unlock_bh(&rcvq->lock);
-
- if (!skb_queue_empty(&list_kill)) {
- bool slow = lock_sock_fast(sk);
-
- __skb_queue_purge(&list_kill);
- sk_mem_reclaim_partial(sk);
- unlock_sock_fast(sk, slow);
- }
return res;
}
@@ -1256,15 +1427,13 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
int err;
int is_udplite = IS_UDPLITE(sk);
bool checksum_valid = false;
- bool slow;
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len, addr_len);
try_again:
peeking = off = sk_peek_offset(sk, flags);
- skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
- &peeked, &off, &err);
+ skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb)
return err;
@@ -1281,7 +1450,8 @@ try_again:
* coverage checksum (UDP-Lite), do it before the copy.
*/
- if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) {
+ if (copied < ulen || peeking ||
+ (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
checksum_valid = !udp_lib_checksum_complete(skb);
if (!checksum_valid)
goto csum_copy_err;
@@ -1297,13 +1467,12 @@ try_again:
}
if (unlikely(err)) {
- trace_kfree_skb(skb, udp_recvmsg);
if (!peeked) {
atomic_inc(&sk->sk_drops);
UDP_INC_STATS(sock_net(sk),
UDP_MIB_INERRORS, is_udplite);
}
- skb_free_datagram_locked(sk, skb);
+ kfree_skb(skb);
return err;
}
@@ -1322,22 +1491,21 @@ try_again:
*addr_len = sizeof(*sin);
}
if (inet->cmsg_flags)
- ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off);
+ ip_cmsg_recv_offset(msg, sk, skb, sizeof(struct udphdr), off);
err = copied;
if (flags & MSG_TRUNC)
err = ulen;
- __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+ skb_consume_udp(sk, skb, peeking ? -err : err);
return err;
csum_copy_err:
- slow = lock_sock_fast(sk);
- if (!skb_kill_datagram(sk, skb, flags)) {
+ if (!__sk_queue_drop_skb(sk, skb, flags)) {
UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
}
- unlock_sock_fast(sk, slow);
+ kfree_skb(skb);
/* starting over for a new packet, but check if we need to yield */
cond_resched();
@@ -1463,9 +1631,11 @@ int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
sock_rps_save_rxhash(sk, skb);
sk_mark_napi_id(sk, skb);
sk_incoming_cpu_update(sk);
+ } else {
+ sk_mark_napi_id_once(sk, skb);
}
- rc = __sock_queue_rcv_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
@@ -1480,7 +1650,6 @@ int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
}
return 0;
-
}
static struct static_key udp_encap_needed __read_mostly;
@@ -1502,7 +1671,6 @@ EXPORT_SYMBOL(udp_encap_enable);
int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
- int rc;
int is_udplite = IS_UDPLITE(sk);
/*
@@ -1589,25 +1757,9 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
goto drop;
udp_csum_pull_header(skb);
- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS,
- is_udplite);
- goto drop;
- }
-
- rc = 0;
ipv4_pktinfo_prepare(sk, skb);
- bh_lock_sock(sk);
- if (!sock_owned_by_user(sk))
- rc = __udp_queue_rcv_skb(sk, skb);
- else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
- bh_unlock_sock(sk);
- goto drop;
- }
- bh_unlock_sock(sk);
-
- return rc;
+ return __udp_queue_rcv_skb(sk, skb);
csum_error:
__UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@ -2217,13 +2369,13 @@ struct proto udp_prot = {
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .init = udp_init_sock,
.destroy = udp_destroy_sock,
.setsockopt = udp_setsockopt,
.getsockopt = udp_getsockopt,
.sendmsg = udp_sendmsg,
.recvmsg = udp_recvmsg,
.sendpage = udp_sendpage,
- .backlog_rcv = __udp_queue_rcv_skb,
.release_cb = ip4_datagram_release_cb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
@@ -2512,6 +2664,7 @@ EXPORT_SYMBOL(udp_flow_hashrnd);
void __init udp_init(void)
{
unsigned long limit;
+ unsigned int i;
udp_table_init(&udp_table, "UDP");
limit = nr_free_buffer_pages() / 8;
@@ -2522,4 +2675,13 @@ void __init udp_init(void)
sysctl_udp_rmem_min = SK_MEM_QUANTUM;
sysctl_udp_wmem_min = SK_MEM_QUANTUM;
+
+ /* 16 spinlocks per cpu */
+ udp_busylocks_log = ilog2(nr_cpu_ids) + 4;
+ udp_busylocks = kmalloc(sizeof(spinlock_t) << udp_busylocks_log,
+ GFP_KERNEL);
+ if (!udp_busylocks)
+ panic("UDP: failed to alloc udp_busylocks\n");
+ for (i = 0; i < (1U << udp_busylocks_log); i++)
+ spin_lock_init(udp_busylocks + i);
}
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index ff450c2aad9b..59f10fe9782e 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -50,10 +50,11 @@ struct proto udplite_prot = {
.sendmsg = udp_sendmsg,
.recvmsg = udp_recvmsg,
.sendpage = udp_sendpage,
- .backlog_rcv = __udp_queue_rcv_skb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
.get_port = udp_v4_get_port,
+ .memory_allocated = &udp_memory_allocated,
+ .sysctl_mem = sysctl_udp_mem,
.obj_size = sizeof(struct udp_sock),
.h.udp_table = &udplite_table,
#ifdef CONFIG_COMPAT
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 2343e4f2e0bf..ec1267e2bd1f 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -289,4 +289,39 @@ config IPV6_PIMSM_V2
Support for IPv6 PIM multicast routing protocol PIM-SMv2.
If unsure, say N.
+config IPV6_SEG6_LWTUNNEL
+ bool "IPv6: Segment Routing Header encapsulation support"
+ depends on IPV6
+ select LWTUNNEL
+ ---help---
+ Support for encapsulation of packets within an outer IPv6
+ header and a Segment Routing Header using the lightweight
+ tunnels mechanism.
+
+ If unsure, say N.
+
+config IPV6_SEG6_INLINE
+ bool "IPv6: direct Segment Routing Header insertion "
+ depends on IPV6_SEG6_LWTUNNEL
+ ---help---
+ Support for direct insertion of the Segment Routing Header,
+ also known as inline mode. Be aware that direct insertion of
+ extension headers (as opposed to encapsulation) may break
+ multiple mechanisms such as PMTUD or IPSec AH. Use this feature
+ only if you know exactly what you are doing.
+
+ If unsure, say N.
+
+config IPV6_SEG6_HMAC
+ bool "IPv6: Segment Routing HMAC support"
+ depends on IPV6
+ select CRYPTO_HMAC
+ select CRYPTO_SHA1
+ select CRYPTO_SHA256
+ ---help---
+ Support for HMAC signature generation and verification
+ of SR-enabled packets.
+
+ If unsure, say N.
+
endif # IPV6
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index c174ccb340a1..a9e9fec387ce 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -9,7 +9,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \
- udp_offload.o
+ udp_offload.o seg6.o
ipv6-offload := ip6_offload.o tcpv6_offload.o exthdrs_offload.o
@@ -23,6 +23,8 @@ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
ipv6-$(CONFIG_PROC_FS) += proc.o
ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
ipv6-$(CONFIG_NETLABEL) += calipso.o
+ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o
+ipv6-$(CONFIG_IPV6_SEG6_HMAC) += seg6_hmac.o
ipv6-objs += $(ipv6-y)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4bc5ba3ae452..c1e124bc8e1e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -238,6 +238,11 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.use_oif_addrs_only = 0,
.ignore_routes_with_linkdown = 0,
.keep_addr_on_down = 0,
+ .seg6_enabled = 0,
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ .seg6_require_hmac = 0,
+#endif
+ .enhanced_dad = 1,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -284,6 +289,11 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.use_oif_addrs_only = 0,
.ignore_routes_with_linkdown = 0,
.keep_addr_on_down = 0,
+ .seg6_enabled = 0,
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ .seg6_require_hmac = 0,
+#endif
+ .enhanced_dad = 1,
};
/* Check if a valid qdisc is available */
@@ -3727,12 +3737,21 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
{
unsigned long rand_num;
struct inet6_dev *idev = ifp->idev;
+ u64 nonce;
if (ifp->flags & IFA_F_OPTIMISTIC)
rand_num = 0;
else
rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
+ nonce = 0;
+ if (idev->cnf.enhanced_dad ||
+ dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad) {
+ do
+ get_random_bytes(&nonce, 6);
+ while (nonce == 0);
+ }
+ ifp->dad_nonce = nonce;
ifp->dad_probes = idev->cnf.dad_transmits;
addrconf_mod_dad_work(ifp, rand_num);
}
@@ -3910,7 +3929,8 @@ static void addrconf_dad_work(struct work_struct *w)
/* send a neighbour solicitation for our addr */
addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
- ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any);
+ ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any,
+ ifp->dad_nonce);
out:
in6_ifa_put(ifp);
rtnl_unlock();
@@ -4950,6 +4970,11 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast;
array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na;
array[DEVCONF_KEEP_ADDR_ON_DOWN] = cnf->keep_addr_on_down;
+ array[DEVCONF_SEG6_ENABLED] = cnf->seg6_enabled;
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
+#endif
+ array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
}
static inline size_t inet6_ifla6_size(void)
@@ -6042,6 +6067,29 @@ static const struct ctl_table addrconf_sysctl[] = {
},
{
+ .procname = "seg6_enabled",
+ .data = &ipv6_devconf.seg6_enabled,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ {
+ .procname = "seg6_require_hmac",
+ .data = &ipv6_devconf.seg6_require_hmac,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+#endif
+ {
+ .procname = "enhanced_dad",
+ .data = &ipv6_devconf.enhanced_dad,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
/* sentinel */
}
};
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 46ad699937fd..237e654ba717 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -61,6 +61,7 @@
#include <net/ip6_tunnel.h>
#endif
#include <net/calipso.h>
+#include <net/seg6.h>
#include <asm/uaccess.h>
#include <linux/mroute6.h>
@@ -257,6 +258,14 @@ lookup_protocol:
goto out;
}
}
+
+ if (!kern) {
+ err = BPF_CGROUP_RUN_PROG_INET_SOCK(sk);
+ if (err) {
+ sk_common_release(sk);
+ goto out;
+ }
+ }
out:
return err;
out_rcu_unlock:
@@ -678,6 +687,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_dport = inet->inet_dport;
fl6.fl6_sport = inet->inet_sport;
+ fl6.flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
rcu_read_lock();
@@ -990,6 +1000,10 @@ static int __init inet6_init(void)
if (err)
goto calipso_fail;
+ err = seg6_init();
+ if (err)
+ goto seg6_fail;
+
#ifdef CONFIG_SYSCTL
err = ipv6_sysctl_register();
if (err)
@@ -1000,8 +1014,10 @@ out:
#ifdef CONFIG_SYSCTL
sysctl_fail:
- calipso_exit();
+ seg6_exit();
#endif
+seg6_fail:
+ calipso_exit();
calipso_fail:
pingv6_exit();
pingv6_fail:
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 0630a4d5daaa..189eb10b742d 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -662,9 +662,10 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
else
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x);
return 0;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index ccf40550c475..0489e19258ad 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -54,6 +54,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
fl6->fl6_dport = inet->inet_dport;
fl6->fl6_sport = inet->inet_sport;
fl6->flowlabel = np->flow_label;
+ fl6->flowi6_uid = sk->sk_uid;
if (!fl6->flowi6_oif)
fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
@@ -717,6 +718,11 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
}
}
+ if (np->rxopt.bits.recvfragsize && opt->frag_max_size) {
+ int val = opt->frag_max_size;
+
+ put_cmsg(msg, SOL_IPV6, IPV6_RECVFRAGSIZE, sizeof(val), &val);
+ }
}
void ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 111ba55fd512..cbcdd5db31f4 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -474,9 +474,10 @@ static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
else
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x);
return 0;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 139ceb68bd37..926818c331e5 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -47,6 +47,11 @@
#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/xfrm.h>
#endif
+#include <linux/seg6.h>
+#include <net/seg6.h>
+#ifdef CONFIG_IPV6_SEG6_HMAC
+#include <net/seg6_hmac.h>
+#endif
#include <linux/uaccess.h>
@@ -286,6 +291,182 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
return -1;
}
+static void seg6_update_csum(struct sk_buff *skb)
+{
+ struct ipv6_sr_hdr *hdr;
+ struct in6_addr *addr;
+ __be32 from, to;
+
+ /* srh is at transport offset and seg_left is already decremented
+ * but daddr is not yet updated with next segment
+ */
+
+ hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
+ addr = hdr->segments + hdr->segments_left;
+
+ hdr->segments_left++;
+ from = *(__be32 *)hdr;
+
+ hdr->segments_left--;
+ to = *(__be32 *)hdr;
+
+ /* update skb csum with diff resulting from seg_left decrement */
+
+ update_csum_diff4(skb, from, to);
+
+ /* compute csum diff between current and next segment and update */
+
+ update_csum_diff16(skb, (__be32 *)(&ipv6_hdr(skb)->daddr),
+ (__be32 *)addr);
+}
+
+static int ipv6_srh_rcv(struct sk_buff *skb)
+{
+ struct inet6_skb_parm *opt = IP6CB(skb);
+ struct net *net = dev_net(skb->dev);
+ struct ipv6_sr_hdr *hdr;
+ struct inet6_dev *idev;
+ struct in6_addr *addr;
+ bool cleanup = false;
+ int accept_seg6;
+
+ hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
+
+ idev = __in6_dev_get(skb->dev);
+
+ accept_seg6 = net->ipv6.devconf_all->seg6_enabled;
+ if (accept_seg6 > idev->cnf.seg6_enabled)
+ accept_seg6 = idev->cnf.seg6_enabled;
+
+ if (!accept_seg6) {
+ kfree_skb(skb);
+ return -1;
+ }
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (!seg6_hmac_validate_skb(skb)) {
+ kfree_skb(skb);
+ return -1;
+ }
+#endif
+
+looped_back:
+ if (hdr->segments_left > 0) {
+ if (hdr->nexthdr != NEXTHDR_IPV6 && hdr->segments_left == 1 &&
+ sr_has_cleanup(hdr))
+ cleanup = true;
+ } else {
+ if (hdr->nexthdr == NEXTHDR_IPV6) {
+ int offset = (hdr->hdrlen + 1) << 3;
+
+ skb_postpull_rcsum(skb, skb_network_header(skb),
+ skb_network_header_len(skb));
+
+ if (!pskb_pull(skb, offset)) {
+ kfree_skb(skb);
+ return -1;
+ }
+ skb_postpull_rcsum(skb, skb_transport_header(skb),
+ offset);
+
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ skb->encapsulation = 0;
+
+ __skb_tunnel_rx(skb, skb->dev, net);
+
+ netif_rx(skb);
+ return -1;
+ }
+
+ opt->srcrt = skb_network_header_len(skb);
+ opt->lastopt = opt->srcrt;
+ skb->transport_header += (hdr->hdrlen + 1) << 3;
+ opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
+
+ return 1;
+ }
+
+ if (hdr->segments_left >= (hdr->hdrlen >> 1)) {
+ __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
+ IPSTATS_MIB_INHDRERRORS);
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+ ((&hdr->segments_left) -
+ skb_network_header(skb)));
+ kfree_skb(skb);
+ return -1;
+ }
+
+ if (skb_cloned(skb)) {
+ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+ __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
+ IPSTATS_MIB_OUTDISCARDS);
+ kfree_skb(skb);
+ return -1;
+ }
+ }
+
+ hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
+
+ hdr->segments_left--;
+ addr = hdr->segments + hdr->segments_left;
+
+ skb_push(skb, sizeof(struct ipv6hdr));
+
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ seg6_update_csum(skb);
+
+ ipv6_hdr(skb)->daddr = *addr;
+
+ if (cleanup) {
+ int srhlen = (hdr->hdrlen + 1) << 3;
+ int nh = hdr->nexthdr;
+
+ skb_pull_rcsum(skb, sizeof(struct ipv6hdr) + srhlen);
+ memmove(skb_network_header(skb) + srhlen,
+ skb_network_header(skb),
+ (unsigned char *)hdr - skb_network_header(skb));
+ skb->network_header += srhlen;
+ ipv6_hdr(skb)->nexthdr = nh;
+ ipv6_hdr(skb)->payload_len = htons(skb->len -
+ sizeof(struct ipv6hdr));
+ skb_push_rcsum(skb, sizeof(struct ipv6hdr));
+ }
+
+ skb_dst_drop(skb);
+
+ ip6_route_input(skb);
+
+ if (skb_dst(skb)->error) {
+ dst_input(skb);
+ return -1;
+ }
+
+ if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
+ if (ipv6_hdr(skb)->hop_limit <= 1) {
+ __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
+ IPSTATS_MIB_INHDRERRORS);
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0);
+ kfree_skb(skb);
+ return -1;
+ }
+ ipv6_hdr(skb)->hop_limit--;
+
+ /* be sure that srh is still present before reinjecting */
+ if (!cleanup) {
+ skb_pull(skb, sizeof(struct ipv6hdr));
+ goto looped_back;
+ }
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+ IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
+ }
+
+ dst_input(skb);
+
+ return -1;
+}
+
/********************************
Routing header.
********************************/
@@ -326,6 +507,10 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
return -1;
}
+ /* segment routing */
+ if (hdr->type == IPV6_SRCRT_TYPE_4)
+ return ipv6_srh_rcv(skb);
+
looped_back:
if (hdr->segments_left == 0) {
switch (hdr->type) {
@@ -679,9 +864,9 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
* for headers.
*/
-static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
- struct ipv6_rt_hdr *opt,
- struct in6_addr **addr_p)
+static void ipv6_push_rthdr0(struct sk_buff *skb, u8 *proto,
+ struct ipv6_rt_hdr *opt,
+ struct in6_addr **addr_p, struct in6_addr *saddr)
{
struct rt0_hdr *phdr, *ihdr;
int hops;
@@ -704,6 +889,62 @@ static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
*proto = NEXTHDR_ROUTING;
}
+static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
+ struct ipv6_rt_hdr *opt,
+ struct in6_addr **addr_p, struct in6_addr *saddr)
+{
+ struct ipv6_sr_hdr *sr_phdr, *sr_ihdr;
+ int plen, hops;
+
+ sr_ihdr = (struct ipv6_sr_hdr *)opt;
+ plen = (sr_ihdr->hdrlen + 1) << 3;
+
+ sr_phdr = (struct ipv6_sr_hdr *)skb_push(skb, plen);
+ memcpy(sr_phdr, sr_ihdr, sizeof(struct ipv6_sr_hdr));
+
+ hops = sr_ihdr->first_segment + 1;
+ memcpy(sr_phdr->segments + 1, sr_ihdr->segments + 1,
+ (hops - 1) * sizeof(struct in6_addr));
+
+ sr_phdr->segments[0] = **addr_p;
+ *addr_p = &sr_ihdr->segments[hops - 1];
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (sr_has_hmac(sr_phdr)) {
+ struct net *net = NULL;
+
+ if (skb->dev)
+ net = dev_net(skb->dev);
+ else if (skb->sk)
+ net = sock_net(skb->sk);
+
+ WARN_ON(!net);
+
+ if (net)
+ seg6_push_hmac(net, saddr, sr_phdr);
+ }
+#endif
+
+ sr_phdr->nexthdr = *proto;
+ *proto = NEXTHDR_ROUTING;
+}
+
+static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
+ struct ipv6_rt_hdr *opt,
+ struct in6_addr **addr_p, struct in6_addr *saddr)
+{
+ switch (opt->type) {
+ case IPV6_SRCRT_TYPE_0:
+ ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
+ break;
+ case IPV6_SRCRT_TYPE_4:
+ ipv6_push_rthdr4(skb, proto, opt, addr_p, saddr);
+ break;
+ default:
+ break;
+ }
+}
+
static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
{
struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
@@ -715,10 +956,10 @@ static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv
void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto,
- struct in6_addr **daddr)
+ struct in6_addr **daddr, struct in6_addr *saddr)
{
if (opt->srcrt) {
- ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
+ ipv6_push_rthdr(skb, proto, opt->srcrt, daddr, saddr);
/*
* IPV6_RTHDRDSTOPTS is ignored
* unless IPV6_RTHDR is set (RFC3542).
@@ -945,7 +1186,22 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
return NULL;
*orig = fl6->daddr;
- fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
+
+ switch (opt->srcrt->type) {
+ case IPV6_SRCRT_TYPE_0:
+ fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
+ break;
+ case IPV6_SRCRT_TYPE_4:
+ {
+ struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)opt->srcrt;
+
+ fl6->daddr = srh->segments[srh->first_segment];
+ break;
+ }
+ default:
+ return NULL;
+ }
+
return orig;
}
EXPORT_SYMBOL_GPL(fl6_update_dst);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 2772004ba5a1..17fa28f7a0ff 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -92,9 +92,10 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct net *net = dev_net(skb->dev);
if (type == ICMPV6_PKT_TOOBIG)
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
else if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
if (!(type & ICMPV6_INFOMSG_MASK))
if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
@@ -486,6 +487,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
fl6.flowi6_oif = iif;
fl6.fl6_icmp_type = type;
fl6.fl6_icmp_code = code;
+ fl6.flowi6_uid = sock_net_uid(net, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
sk = icmpv6_xmit_lock(net);
@@ -660,6 +662,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
fl6.flowi6_oif = skb->dev->ifindex;
fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
fl6.flowi6_mark = mark;
+ fl6.flowi6_uid = sock_net_uid(net, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
sk = icmpv6_xmit_lock(net);
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index e50c27a93e17..a7bc54ab46e2 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -6,29 +6,88 @@
#include <linux/socket.h>
#include <linux/types.h>
#include <net/checksum.h>
+#include <net/dst_cache.h>
#include <net/ip.h>
#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
#include <net/lwtunnel.h>
#include <net/protocol.h>
#include <uapi/linux/ila.h>
#include "ila.h"
+struct ila_lwt {
+ struct ila_params p;
+ struct dst_cache dst_cache;
+ u32 connected : 1;
+};
+
+static inline struct ila_lwt *ila_lwt_lwtunnel(
+ struct lwtunnel_state *lwt)
+{
+ return (struct ila_lwt *)lwt->data;
+}
+
static inline struct ila_params *ila_params_lwtunnel(
- struct lwtunnel_state *lwstate)
+ struct lwtunnel_state *lwt)
{
- return (struct ila_params *)lwstate->data;
+ return &ila_lwt_lwtunnel(lwt)->p;
}
static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
+ struct dst_entry *orig_dst = skb_dst(skb);
+ struct rt6_info *rt = (struct rt6_info *)orig_dst;
+ struct ila_lwt *ilwt = ila_lwt_lwtunnel(orig_dst->lwtstate);
+ struct dst_entry *dst;
+ int err = -EINVAL;
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), true);
+ ila_update_ipv6_locator(skb, ila_params_lwtunnel(orig_dst->lwtstate),
+ true);
- return dst->lwtstate->orig_output(net, sk, skb);
+ if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
+ /* Already have a next hop address in route, no need for
+ * dest cache route.
+ */
+ return orig_dst->lwtstate->orig_output(net, sk, skb);
+ }
+
+ dst = dst_cache_get(&ilwt->dst_cache);
+ if (unlikely(!dst)) {
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ struct flowi6 fl6;
+
+ /* Lookup a route for the new destination. Take into
+ * account that the base route may already have a gateway.
+ */
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.flowi6_oif = orig_dst->dev->ifindex;
+ fl6.flowi6_iif = LOOPBACK_IFINDEX;
+ fl6.daddr = *rt6_nexthop((struct rt6_info *)orig_dst,
+ &ip6h->daddr);
+
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (dst->error) {
+ err = -EHOSTUNREACH;
+ dst_release(dst);
+ goto drop;
+ }
+
+ dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ goto drop;
+ }
+
+ if (ilwt->connected)
+ dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr);
+ }
+
+ skb_dst_set(skb, dst);
+ return dst_output(net, sk, skb);
drop:
kfree_skb(skb);
@@ -60,9 +119,9 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts)
{
+ struct ila_lwt *ilwt;
struct ila_params *p;
struct nlattr *tb[ILA_ATTR_MAX + 1];
- size_t encap_len = sizeof(*p);
struct lwtunnel_state *newts;
const struct fib6_config *cfg6 = cfg;
struct ila_addr *iaddr;
@@ -71,7 +130,7 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
if (family != AF_INET6)
return -EINVAL;
- if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) {
+ if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
/* Need to have full locator and at least type field
* included in destination
*/
@@ -95,11 +154,17 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
if (!tb[ILA_ATTR_LOCATOR])
return -EINVAL;
- newts = lwtunnel_state_alloc(encap_len);
+ newts = lwtunnel_state_alloc(sizeof(*ilwt));
if (!newts)
return -ENOMEM;
- newts->len = encap_len;
+ ilwt = ila_lwt_lwtunnel(newts);
+ ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+ if (ret) {
+ kfree(newts);
+ return ret;
+ }
+
p = ila_params_lwtunnel(newts);
p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
@@ -120,11 +185,19 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
LWTUNNEL_STATE_INPUT_REDIRECT;
+ if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
+ ilwt->connected = 1;
+
*ts = newts;
return 0;
}
+static void ila_destroy_state(struct lwtunnel_state *lwt)
+{
+ dst_cache_destroy(&ila_lwt_lwtunnel(lwt)->dst_cache);
+}
+
static int ila_fill_encap_info(struct sk_buff *skb,
struct lwtunnel_state *lwtstate)
{
@@ -159,6 +232,7 @@ static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
static const struct lwtunnel_encap_ops ila_encap_ops = {
.build_state = ila_build_state,
+ .destroy_state = ila_destroy_state,
.output = ila_output,
.input = ila_input,
.fill_encap = ila_fill_encap_info,
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index e604013dd814..af8f52ee7180 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -118,15 +118,7 @@ static const struct rhashtable_params rht_params = {
.obj_cmpfn = ila_cmpfn,
};
-static struct genl_family ila_nl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = ILA_GENL_NAME,
- .version = ILA_GENL_VERSION,
- .maxattr = ILA_ATTR_MAX,
- .netnsok = true,
- .parallel_ops = true,
-};
+static struct genl_family ila_nl_family;
static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
[ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
@@ -482,7 +474,15 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
- struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
+ struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
+
+ if (!iter) {
+ iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
+
+ cb->args[0] = (long)iter;
+ }
return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
GFP_KERNEL);
@@ -490,16 +490,18 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
static int ila_nl_dump_done(struct netlink_callback *cb)
{
- struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
+ struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
rhashtable_walk_exit(&iter->rhiter);
+ kfree(iter);
+
return 0;
}
static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
+ struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
struct ila_map *ila;
int ret;
@@ -561,6 +563,18 @@ static const struct genl_ops ila_nl_ops[] = {
},
};
+static struct genl_family ila_nl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = ILA_GENL_NAME,
+ .version = ILA_GENL_VERSION,
+ .maxattr = ILA_ATTR_MAX,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .ops = ila_nl_ops,
+ .n_ops = ARRAY_SIZE(ila_nl_ops),
+};
+
#define ILA_HASH_TABLE_SIZE 1024
static __net_init int ila_init_net(struct net *net)
@@ -623,7 +637,7 @@ static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral)
return 0;
}
-int ila_xlat_init(void)
+int __init ila_xlat_init(void)
{
int ret;
@@ -631,8 +645,7 @@ int ila_xlat_init(void)
if (ret)
goto exit;
- ret = genl_register_family_with_ops(&ila_nl_family,
- ila_nl_ops);
+ ret = genl_register_family(&ila_nl_family);
if (ret < 0)
goto unregister;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 532c3ef282c5..1c86c478f578 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -88,6 +88,7 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
fl6->flowi6_mark = ireq->ir_mark;
fl6->fl6_dport = ireq->ir_rmt_port;
fl6->fl6_sport = htons(ireq->ir_num);
+ fl6->flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(fl6));
dst = ip6_dst_lookup_flow(sk, fl6, final_p);
@@ -136,6 +137,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
fl6->flowi6_mark = sk->sk_mark;
fl6->fl6_sport = inet->inet_sport;
fl6->fl6_dport = inet->inet_dport;
+ fl6->flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
rcu_read_lock();
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index d7d6d3ae0b3b..75b6108234dd 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
#define IP6_GRE_HASH_SIZE_SHIFT 5
#define IP6_GRE_HASH_SIZE (1 << IP6_GRE_HASH_SIZE_SHIFT)
-static int ip6gre_net_id __read_mostly;
+static unsigned int ip6gre_net_id __read_mostly;
struct ip6gre_net {
struct ip6_tnl __rcu *tunnels[4][IP6_GRE_HASH_SIZE];
@@ -548,6 +548,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM));
if (err)
return -1;
@@ -602,6 +604,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)))
return -1;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 59eb4ed99ce8..70d0de404197 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -39,6 +39,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/bpf-cgroup.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
@@ -131,6 +132,14 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
+ int ret;
+
+ ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
dst_allfrag(skb_dst(skb)) ||
(IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
@@ -203,7 +212,8 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
if (opt->opt_flen)
ipv6_push_frag_opts(skb, opt, &proto);
if (opt->opt_nflen)
- ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop);
+ ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop,
+ &fl6->saddr);
}
skb_push(skb, sizeof(struct ipv6hdr));
@@ -624,7 +634,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
hroom = LL_RESERVED_SPACE(rt->dst.dev);
if (skb_has_frag_list(skb)) {
- int first_len = skb_pagelen(skb);
+ unsigned int first_len = skb_pagelen(skb);
struct sk_buff *frag2;
if (first_len - hlen > mtu ||
@@ -1672,7 +1682,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
if (opt && opt->opt_flen)
ipv6_push_frag_opts(skb, opt, &proto);
if (opt && opt->opt_nflen)
- ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst);
+ ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst, &fl6->saddr);
skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d76674efe523..8b186b56183a 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -83,7 +83,7 @@ static int ip6_tnl_dev_init(struct net_device *dev);
static void ip6_tnl_dev_setup(struct net_device *dev);
static struct rtnl_link_ops ip6_link_ops __read_mostly;
-static int ip6_tnl_net_id __read_mostly;
+static unsigned int ip6_tnl_net_id __read_mostly;
struct ip6_tnl_net {
/* the IPv6 tunnel fallback device */
struct net_device *fb_tnl_dev;
@@ -1166,7 +1166,7 @@ route_lookup:
if (encap_limit >= 0) {
init_tel_txopt(&opt, encap_limit);
- ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
+ ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL, NULL);
}
/* Calculate max headroom for all the headers and adjust
@@ -1248,6 +1248,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
fl6.flowi6_mark = skb->mark;
}
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
@@ -1326,6 +1328,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
fl6.flowi6_mark = skb->mark;
}
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
@@ -1645,7 +1649,7 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
struct ip6_tnl *tnl = netdev_priv(dev);
if (tnl->parms.proto == IPPROTO_IPIP) {
- if (new_mtu < 68)
+ if (new_mtu < ETH_MIN_MTU)
return -EINVAL;
} else {
if (new_mtu < IPV6_MIN_MTU)
@@ -1798,6 +1802,8 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
dev->mtu = ETH_DATA_LEN - t_hlen;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
dev->mtu -= 8;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = 0xFFF8 - dev->hard_header_len;
return 0;
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index c299c1e2bbf0..f4b4a4a5f4ba 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -64,7 +64,7 @@ static int vti6_dev_init(struct net_device *dev);
static void vti6_dev_setup(struct net_device *dev);
static struct rtnl_link_ops vti6_link_ops __read_mostly;
-static int vti6_net_id __read_mostly;
+static unsigned int vti6_net_id __read_mostly;
struct vti6_net {
/* the vti6 tunnel fallback device */
struct net_device *fb_tnl_dev;
@@ -608,9 +608,10 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
else
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x);
return 0;
@@ -812,30 +813,11 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
-/**
- * vti6_tnl_change_mtu - change mtu manually for tunnel device
- * @dev: virtual device associated with tunnel
- * @new_mtu: the new mtu
- *
- * Return:
- * 0 on success,
- * %-EINVAL if mtu too small
- **/
-static int vti6_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < IPV6_MIN_MTU)
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops vti6_netdev_ops = {
.ndo_init = vti6_dev_init,
.ndo_uninit = vti6_dev_uninit,
.ndo_start_xmit = vti6_tnl_xmit,
.ndo_do_ioctl = vti6_ioctl,
- .ndo_change_mtu = vti6_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip6_tnl_get_iflink,
};
@@ -855,6 +837,8 @@ static void vti6_dev_setup(struct net_device *dev)
dev->type = ARPHRD_TUNNEL6;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = IPV6_MIN_MTU;
+ dev->max_mtu = IP_MAX_MTU;
dev->flags |= IFF_NOARP;
dev->addr_len = sizeof(struct in6_addr);
netif_keep_dst(dev);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7f4265b1649b..52101b37ad6e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -636,7 +636,7 @@ static int pim6_rcv(struct sk_buff *skb)
goto drop;
pim = (struct pimreghdr *)skb_transport_header(skb);
- if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
+ if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
(pim->flags & PIM_NULL_REGISTER) ||
(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
sizeof(*pim), IPPROTO_PIM,
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 1b9316e1386a..54d165b9845a 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -74,9 +74,10 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
else
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x);
return 0;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 636ec56f5f50..3ba530373560 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -52,6 +52,7 @@
#include <net/udplite.h>
#include <net/xfrm.h>
#include <net/compat.h>
+#include <net/seg6.h>
#include <asm/uaccess.h>
@@ -430,6 +431,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
#endif
+ case IPV6_SRCRT_TYPE_4:
+ {
+ struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)
+ opt->srcrt;
+
+ if (!seg6_validate_srh(srh, optlen))
+ goto sticky_done;
+ break;
+ }
default:
goto sticky_done;
}
@@ -868,6 +878,10 @@ pref_skip_coa:
np->autoflowlabel = valbool;
retv = 0;
break;
+ case IPV6_RECVFRAGSIZE:
+ np->rxopt.bits.recvfragsize = valbool;
+ retv = 0;
+ break;
}
release_sock(sk);
@@ -1310,6 +1324,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
val = np->autoflowlabel;
break;
+ case IPV6_RECVFRAGSIZE:
+ val = np->rxopt.bits.recvfragsize;
+ break;
+
default:
return -ENOPROTOOPT;
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index d8e671457d10..7ebac630d3c6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -233,6 +233,7 @@ struct ndisc_options *ndisc_parse_options(const struct net_device *dev,
case ND_OPT_SOURCE_LL_ADDR:
case ND_OPT_TARGET_LL_ADDR:
case ND_OPT_MTU:
+ case ND_OPT_NONCE:
case ND_OPT_REDIRECT_HDR:
if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
ND_PRINTK(2, warn,
@@ -568,7 +569,8 @@ static void ndisc_send_unsol_na(struct net_device *dev)
}
void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
- const struct in6_addr *daddr, const struct in6_addr *saddr)
+ const struct in6_addr *daddr, const struct in6_addr *saddr,
+ u64 nonce)
{
struct sk_buff *skb;
struct in6_addr addr_buf;
@@ -588,6 +590,8 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
if (inc_opt)
optlen += ndisc_opt_addr_space(dev,
NDISC_NEIGHBOUR_SOLICITATION);
+ if (nonce != 0)
+ optlen += 8;
skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
if (!skb)
@@ -605,6 +609,13 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
dev->dev_addr,
NDISC_NEIGHBOUR_SOLICITATION);
+ if (nonce != 0) {
+ u8 *opt = skb_put(skb, 8);
+
+ opt[0] = ND_OPT_NONCE;
+ opt[1] = 8 >> 3;
+ memcpy(opt + 2, &nonce, 6);
+ }
ndisc_send_skb(skb, daddr, saddr);
}
@@ -693,12 +704,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
"%s: trying to ucast probe in NUD_INVALID: %pI6\n",
__func__, target);
}
- ndisc_send_ns(dev, target, target, saddr);
+ ndisc_send_ns(dev, target, target, saddr, 0);
} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
neigh_app_ns(neigh);
} else {
addrconf_addr_solict_mult(target, &mcaddr);
- ndisc_send_ns(dev, target, &mcaddr, saddr);
+ ndisc_send_ns(dev, target, &mcaddr, saddr, 0);
}
}
@@ -742,6 +753,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
int dad = ipv6_addr_any(saddr);
bool inc;
int is_router = -1;
+ u64 nonce = 0;
if (skb->len < sizeof(struct nd_msg)) {
ND_PRINTK(2, warn, "NS: packet too short\n");
@@ -786,6 +798,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
return;
}
}
+ if (ndopts.nd_opts_nonce)
+ memcpy(&nonce, (u8 *)(ndopts.nd_opts_nonce + 1), 6);
inc = ipv6_addr_is_multicast(daddr);
@@ -794,6 +808,15 @@ static void ndisc_recv_ns(struct sk_buff *skb)
have_ifp:
if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
if (dad) {
+ if (nonce != 0 && ifp->dad_nonce == nonce) {
+ u8 *np = (u8 *)&nonce;
+ /* Matching nonce if looped back */
+ ND_PRINTK(2, notice,
+ "%s: IPv6 DAD loopback for address %pI6c nonce %pM ignored\n",
+ ifp->idev->dev->name,
+ &ifp->addr, np);
+ goto out;
+ }
/*
* We are colliding with another node
* who is doing DAD
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d11c46833d61..39970e212ad5 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -26,6 +26,7 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
struct flowi6 fl6 = {
.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
.flowi6_mark = skb->mark,
+ .flowi6_uid = sock_net_uid(net, skb->sk),
.daddr = iph->daddr,
.saddr = iph->saddr,
};
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index e10a04c9cdc7..6acb2eecd986 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -25,6 +25,12 @@ config NF_CONNTRACK_IPV6
To compile it as a module, choose M here. If unsure, say N.
+config NF_SOCKET_IPV6
+ tristate "IPv6 socket lookup support"
+ help
+ This option enables the IPv6 socket lookup infrastructure. This
+ is used by the ip6tables socket match.
+
if NF_TABLES
config NF_TABLES_IPV6
@@ -54,6 +60,14 @@ config NFT_DUP_IPV6
help
This module enables IPv6 packet duplication support for nf_tables.
+config NFT_FIB_IPV6
+ tristate "nf_tables fib / ipv6 route lookup support"
+ select NFT_FIB
+ help
+ This module enables IPv6 FIB lookups, e.g. for reverse path filtering.
+ It also allows query of the FIB for the route type, e.g. local, unicast,
+ multicast or blackhole.
+
endif # NF_TABLES_IPV6
endif # NF_TABLES
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index b4f7d0b4e2af..fe180c96040e 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o
nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
+obj-$(CONFIG_NF_SOCKET_IPV6) += nf_socket_ipv6.o
+
# logging
obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o
@@ -40,6 +42,7 @@ obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o
obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redir_ipv6.o
obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o
+obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o
# matches
obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 55aacea24396..d56d8ac09a94 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -291,11 +291,7 @@ ip6t_do_table(struct sk_buff *skb,
* rule is also a fragment-specific rule, non-fragments won't
* match it. */
acpar.hotdrop = false;
- acpar.net = state->net;
- acpar.in = state->in;
- acpar.out = state->out;
- acpar.family = NFPROTO_IPV6;
- acpar.hooknum = hook;
+ acpar.state = state;
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
@@ -566,7 +562,8 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
static int
find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
- unsigned int size)
+ unsigned int size,
+ struct xt_percpu_counter_alloc_state *alloc_state)
{
struct xt_entry_target *t;
struct xt_target *target;
@@ -574,12 +571,9 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
unsigned int j;
struct xt_mtchk_param mtpar;
struct xt_entry_match *ematch;
- unsigned long pcnt;
- pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(pcnt))
+ if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
return -ENOMEM;
- e->counters.pcnt = pcnt;
j = 0;
mtpar.net = net;
@@ -616,7 +610,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
cleanup_match(ematch, net);
}
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
return ret;
}
@@ -703,8 +697,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net)
if (par.target->destroy != NULL)
par.target->destroy(&par);
module_put(par.target->me);
-
- xt_percpu_counter_free(e->counters.pcnt);
+ xt_percpu_counter_free(&e->counters);
}
/* Checks and translates the user-supplied table segment (held in
@@ -713,6 +706,7 @@ static int
translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
const struct ip6t_replace *repl)
{
+ struct xt_percpu_counter_alloc_state alloc_state = { 0 };
struct ip6t_entry *iter;
unsigned int *offsets;
unsigned int i;
@@ -772,7 +766,8 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
/* Finally, each sanity check must pass */
i = 0;
xt_entry_foreach(iter, entry0, newinfo->size) {
- ret = find_check_entry(iter, net, repl->name, repl->size);
+ ret = find_check_entry(iter, net, repl->name, repl->size,
+ &alloc_state);
if (ret != 0)
break;
++i;
@@ -1007,7 +1002,7 @@ static int get_info(struct net *net, void __user *user,
#endif
t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
"ip6table_%s", name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
struct ip6t_getinfo info;
const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT
@@ -1037,7 +1032,7 @@ static int get_info(struct net *net, void __user *user,
xt_table_unlock(t);
module_put(t->me);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
#ifdef CONFIG_COMPAT
if (compat)
xt_compat_unlock(AF_INET6);
@@ -1063,7 +1058,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, AF_INET6, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
struct xt_table_info *private = t->private;
if (get.size == private->size)
ret = copy_entries_to_user(private->size,
@@ -1074,7 +1069,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
return ret;
}
@@ -1099,8 +1094,8 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
"ip6table_%s", name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free_newinfo_counters_untrans;
}
@@ -1214,8 +1209,8 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
if (IS_ERR(paddc))
return PTR_ERR(paddc);
t = xt_find_table_lock(net, AF_INET6, tmp.name);
- if (IS_ERR_OR_NULL(t)) {
- ret = t ? PTR_ERR(t) : -ENOENT;
+ if (!t) {
+ ret = -ENOENT;
goto free;
}
@@ -1651,7 +1646,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
xt_compat_lock(AF_INET6);
t = xt_find_table_lock(net, AF_INET6, get.name);
- if (!IS_ERR_OR_NULL(t)) {
+ if (t) {
const struct xt_table_info *private = t->private;
struct xt_table_info info;
ret = compat_table_info(private, &info);
@@ -1665,7 +1660,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
module_put(t->me);
xt_table_unlock(t);
} else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ ret = -ENOENT;
xt_compat_unlock(AF_INET6);
return ret;
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c
index 7f9f45d829d2..2b1a15846f9a 100644
--- a/net/ipv6/netfilter/ip6t_MASQUERADE.c
+++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c
@@ -24,7 +24,7 @@
static unsigned int
masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
- return nf_nat_masquerade_ipv6(skb, par->targinfo, par->out);
+ return nf_nat_masquerade_ipv6(skb, par->targinfo, xt_out(par));
}
static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index db29bbf41b59..fa51a205918d 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -39,35 +39,40 @@ static unsigned int
reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ip6t_reject_info *reject = par->targinfo;
- struct net *net = par->net;
+ struct net *net = xt_net(par);
switch (reject->with) {
case IP6T_ICMP6_NO_ROUTE:
- nf_send_unreach6(net, skb, ICMPV6_NOROUTE, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_NOROUTE, xt_hooknum(par));
break;
case IP6T_ICMP6_ADM_PROHIBITED:
- nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED,
+ xt_hooknum(par));
break;
case IP6T_ICMP6_NOT_NEIGHBOUR:
- nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR,
+ xt_hooknum(par));
break;
case IP6T_ICMP6_ADDR_UNREACH:
- nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH,
+ xt_hooknum(par));
break;
case IP6T_ICMP6_PORT_UNREACH:
- nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH,
+ xt_hooknum(par));
break;
case IP6T_ICMP6_ECHOREPLY:
/* Do nothing */
break;
case IP6T_TCP_RESET:
- nf_send_reset6(net, skb, par->hooknum);
+ nf_send_reset6(net, skb, xt_hooknum(par));
break;
case IP6T_ICMP6_POLICY_FAIL:
- nf_send_unreach6(net, skb, ICMPV6_POLICY_FAIL, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_POLICY_FAIL, xt_hooknum(par));
break;
case IP6T_ICMP6_REJECT_ROUTE:
- nf_send_unreach6(net, skb, ICMPV6_REJECT_ROUTE, par->hooknum);
+ nf_send_unreach6(net, skb, ICMPV6_REJECT_ROUTE,
+ xt_hooknum(par));
break;
}
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 06bed74cf5ee..98c8dd38575a 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -277,12 +277,12 @@ static unsigned int
synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_synproxy_info *info = par->targinfo;
- struct net *net = par->net;
+ struct net *net = xt_net(par);
struct synproxy_net *snet = synproxy_pernet(net);
struct synproxy_options opts = {};
struct tcphdr *th, _th;
- if (nf_ip6_checksum(skb, par->hooknum, par->thoff, IPPROTO_TCP))
+ if (nf_ip6_checksum(skb, xt_hooknum(par), par->thoff, IPPROTO_TCP))
return NF_DROP;
th = skb_header_pointer(skb, par->thoff, sizeof(_th), &_th);
@@ -440,12 +440,12 @@ static int synproxy_tg6_check(const struct xt_tgchk_param *par)
e->ipv6.invflags & XT_INV_PROTO)
return -EINVAL;
- return nf_ct_l3proto_try_module_get(par->family);
+ return nf_ct_netns_get(par->net, par->family);
}
static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_target synproxy_tg6_reg __read_mostly = {
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
index 1ee1b25df096..d5263dc364a9 100644
--- a/net/ipv6/netfilter/ip6t_rpfilter.c
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -93,7 +93,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
if (unlikely(saddrtype == IPV6_ADDR_ANY))
return true ^ invert; /* not routable: forward path will drop it */
- return rpfilter_lookup_reverse6(par->net, skb, par->in, info->flags) ^ invert;
+ return rpfilter_lookup_reverse6(xt_net(par), skb, xt_in(par),
+ info->flags) ^ invert;
}
static int rpfilter_check(const struct xt_mtchk_param *par)
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 963ee3848675..4e3402486833 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -34,6 +34,13 @@
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
#include <net/netfilter/nf_log.h>
+static int conntrack6_net_id;
+static DEFINE_MUTEX(register_ipv6_hooks);
+
+struct conntrack6_net {
+ unsigned int users;
+};
+
static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -308,6 +315,42 @@ static int ipv6_nlattr_tuple_size(void)
}
#endif
+static int ipv6_hooks_register(struct net *net)
+{
+ struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id);
+ int err = 0;
+
+ mutex_lock(&register_ipv6_hooks);
+ cnet->users++;
+ if (cnet->users > 1)
+ goto out_unlock;
+
+ err = nf_defrag_ipv6_enable(net);
+ if (err < 0) {
+ cnet->users = 0;
+ goto out_unlock;
+ }
+
+ err = nf_register_net_hooks(net, ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
+ if (err)
+ cnet->users = 0;
+ out_unlock:
+ mutex_unlock(&register_ipv6_hooks);
+ return err;
+}
+
+static void ipv6_hooks_unregister(struct net *net)
+{
+ struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id);
+
+ mutex_lock(&register_ipv6_hooks);
+ if (cnet->users && (--cnet->users == 0))
+ nf_unregister_net_hooks(net, ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
+ mutex_unlock(&register_ipv6_hooks);
+}
+
struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
.l3proto = PF_INET6,
.name = "ipv6",
@@ -321,6 +364,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
.nlattr_to_tuple = ipv6_nlattr_to_tuple,
.nla_policy = ipv6_nla_policy,
#endif
+ .net_ns_get = ipv6_hooks_register,
+ .net_ns_put = ipv6_hooks_unregister,
.me = THIS_MODULE,
};
@@ -336,52 +381,51 @@ static struct nf_sockopt_ops so_getorigdst6 = {
.owner = THIS_MODULE,
};
+static struct nf_conntrack_l4proto *builtin_l4proto6[] = {
+ &nf_conntrack_l4proto_tcp6,
+ &nf_conntrack_l4proto_udp6,
+ &nf_conntrack_l4proto_icmpv6,
+#ifdef CONFIG_NF_CT_PROTO_DCCP
+ &nf_conntrack_l4proto_dccp6,
+#endif
+#ifdef CONFIG_NF_CT_PROTO_SCTP
+ &nf_conntrack_l4proto_sctp6,
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE
+ &nf_conntrack_l4proto_udplite6,
+#endif
+};
+
static int ipv6_net_init(struct net *net)
{
int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp6);
- if (ret < 0) {
- pr_err("nf_conntrack_tcp6: pernet registration failed\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp6);
- if (ret < 0) {
- pr_err("nf_conntrack_udp6: pernet registration failed\n");
- goto cleanup_tcp6;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmpv6);
- if (ret < 0) {
- pr_err("nf_conntrack_icmp6: pernet registration failed\n");
- goto cleanup_udp6;
- }
+ ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
+ if (ret < 0)
+ return ret;
+
ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: pernet registration failed.\n");
- goto cleanup_icmpv6;
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
}
- return 0;
- cleanup_icmpv6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
- cleanup_udp6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
- cleanup_tcp6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
- out:
return ret;
}
static void ipv6_net_exit(struct net *net)
{
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
}
static struct pernet_operations ipv6_net_ops = {
.init = ipv6_net_init,
.exit = ipv6_net_exit,
+ .id = &conntrack6_net_id,
+ .size = sizeof(struct conntrack6_net),
};
static int __init nf_conntrack_l3proto_ipv6_init(void)
@@ -389,7 +433,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
int ret = 0;
need_conntrack();
- nf_defrag_ipv6_enable();
ret = nf_register_sockopt(&so_getorigdst6);
if (ret < 0) {
@@ -401,47 +444,20 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
if (ret < 0)
goto cleanup_sockopt;
- ret = nf_register_hooks(ipv6_conntrack_ops,
- ARRAY_SIZE(ipv6_conntrack_ops));
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register pre-routing defrag "
- "hook.\n");
+ ret = nf_ct_l4proto_register(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
+ if (ret < 0)
goto cleanup_pernet;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register tcp6 proto.\n");
- goto cleanup_hooks;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register udp6 proto.\n");
- goto cleanup_tcp6;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmpv6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register icmpv6 proto.\n");
- goto cleanup_udp6;
- }
ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
- goto cleanup_icmpv6;
+ goto cleanup_l4proto;
}
return ret;
-
- cleanup_icmpv6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
- cleanup_udp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
- cleanup_tcp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- cleanup_hooks:
- nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+cleanup_l4proto:
+ nf_ct_l4proto_unregister(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
cleanup_pernet:
unregister_pernet_subsys(&ipv6_net_ops);
cleanup_sockopt:
@@ -453,10 +469,8 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
synchronize_net();
nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
- nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+ nf_ct_l4proto_unregister(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
unregister_pernet_subsys(&ipv6_net_ops);
nf_unregister_sockopt(&so_getorigdst6);
}
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index f06b0471f39f..8e0bdd058787 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -30,6 +30,8 @@
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+static DEFINE_MUTEX(defrag6_mutex);
+
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
struct sk_buff *skb)
{
@@ -87,6 +89,19 @@ static struct nf_hook_ops ipv6_defrag_ops[] = {
},
};
+static void __net_exit defrag6_net_exit(struct net *net)
+{
+ if (net->nf.defrag_ipv6) {
+ nf_unregister_net_hooks(net, ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ net->nf.defrag_ipv6 = false;
+ }
+}
+
+static struct pernet_operations defrag6_net_ops = {
+ .exit = defrag6_net_exit,
+};
+
static int __init nf_defrag_init(void)
{
int ret = 0;
@@ -96,9 +111,9 @@ static int __init nf_defrag_init(void)
pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
return ret;
}
- ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+ ret = register_pernet_subsys(&defrag6_net_ops);
if (ret < 0) {
- pr_err("nf_defrag_ipv6: can't register hooks\n");
+ pr_err("nf_defrag_ipv6: can't register pernet ops\n");
goto cleanup_frag6;
}
return ret;
@@ -111,12 +126,31 @@ cleanup_frag6:
static void __exit nf_defrag_fini(void)
{
- nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+ unregister_pernet_subsys(&defrag6_net_ops);
nf_ct_frag6_cleanup();
}
-void nf_defrag_ipv6_enable(void)
+int nf_defrag_ipv6_enable(struct net *net)
{
+ int err = 0;
+
+ might_sleep();
+
+ if (net->nf.defrag_ipv6)
+ return 0;
+
+ mutex_lock(&defrag6_mutex);
+ if (net->nf.defrag_ipv6)
+ goto out_unlock;
+
+ err = nf_register_net_hooks(net, ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ if (err == 0)
+ net->nf.defrag_ipv6 = true;
+
+ out_unlock:
+ mutex_unlock(&defrag6_mutex);
+ return err;
}
EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
diff --git a/net/ipv6/netfilter/nf_socket_ipv6.c b/net/ipv6/netfilter/nf_socket_ipv6.c
new file mode 100644
index 000000000000..ebb2bf84232a
--- /dev/null
+++ b/net/ipv6/netfilter/nf_socket_ipv6.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2007-2008 BalaBit IT Ltd.
+ * Author: Krisztian Kovacs
+ *
+ * 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/module.h>
+#include <linux/skbuff.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+#include <net/sock.h>
+#include <net/inet_sock.h>
+#include <net/inet6_hashtables.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+#include <net/netfilter/nf_socket.h>
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+static int
+extract_icmp6_fields(const struct sk_buff *skb,
+ unsigned int outside_hdrlen,
+ int *protocol,
+ const struct in6_addr **raddr,
+ const struct in6_addr **laddr,
+ __be16 *rport,
+ __be16 *lport,
+ struct ipv6hdr *ipv6_var)
+{
+ const struct ipv6hdr *inside_iph;
+ struct icmp6hdr *icmph, _icmph;
+ __be16 *ports, _ports[2];
+ u8 inside_nexthdr;
+ __be16 inside_fragoff;
+ int inside_hdrlen;
+
+ icmph = skb_header_pointer(skb, outside_hdrlen,
+ sizeof(_icmph), &_icmph);
+ if (icmph == NULL)
+ return 1;
+
+ if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
+ return 1;
+
+ inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph),
+ sizeof(*ipv6_var), ipv6_var);
+ if (inside_iph == NULL)
+ return 1;
+ inside_nexthdr = inside_iph->nexthdr;
+
+ inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) +
+ sizeof(*ipv6_var),
+ &inside_nexthdr, &inside_fragoff);
+ if (inside_hdrlen < 0)
+ return 1; /* hjm: Packet has no/incomplete transport layer headers. */
+
+ if (inside_nexthdr != IPPROTO_TCP &&
+ inside_nexthdr != IPPROTO_UDP)
+ return 1;
+
+ ports = skb_header_pointer(skb, inside_hdrlen,
+ sizeof(_ports), &_ports);
+ if (ports == NULL)
+ return 1;
+
+ /* the inside IP packet is the one quoted from our side, thus
+ * its saddr is the local address */
+ *protocol = inside_nexthdr;
+ *laddr = &inside_iph->saddr;
+ *lport = ports[0];
+ *raddr = &inside_iph->daddr;
+ *rport = ports[1];
+
+ return 0;
+}
+
+static struct sock *
+nf_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff,
+ const u8 protocol,
+ const struct in6_addr *saddr, const struct in6_addr *daddr,
+ const __be16 sport, const __be16 dport,
+ const struct net_device *in)
+{
+ switch (protocol) {
+ case IPPROTO_TCP:
+ return inet6_lookup(net, &tcp_hashinfo, skb, doff,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ case IPPROTO_UDP:
+ return udp6_lib_lookup(net, saddr, sport, daddr, dport,
+ in->ifindex);
+ }
+
+ return NULL;
+}
+
+struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
+ const struct net_device *indev)
+{
+ __be16 uninitialized_var(dport), uninitialized_var(sport);
+ const struct in6_addr *daddr = NULL, *saddr = NULL;
+ struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct sk_buff *data_skb = NULL;
+ int doff = 0;
+ int thoff = 0, tproto;
+
+ tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
+ if (tproto < 0) {
+ pr_debug("unable to find transport header in IPv6 packet, dropping\n");
+ return NULL;
+ }
+
+ if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) {
+ struct udphdr _hdr, *hp;
+
+ hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return NULL;
+
+ saddr = &iph->saddr;
+ sport = hp->source;
+ daddr = &iph->daddr;
+ dport = hp->dest;
+ data_skb = (struct sk_buff *)skb;
+ doff = tproto == IPPROTO_TCP ?
+ thoff + __tcp_hdrlen((struct tcphdr *)hp) :
+ thoff + sizeof(*hp);
+
+ } else if (tproto == IPPROTO_ICMPV6) {
+ struct ipv6hdr ipv6_var;
+
+ if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
+ &sport, &dport, &ipv6_var))
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ return nf_socket_get_sock_v6(net, data_skb, doff, tproto, saddr, daddr,
+ sport, dport, indev);
+}
+EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v6);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
+MODULE_DESCRIPTION("Netfilter IPv6 socket lookup infrastructure");
diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c
index 831f86e1ec08..d8b5b60b7d53 100644
--- a/net/ipv6/netfilter/nft_dup_ipv6.c
+++ b/net/ipv6/netfilter/nft_dup_ipv6.c
@@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr,
struct in6_addr *gw = (struct in6_addr *)&regs->data[priv->sreg_addr];
int oif = priv->sreg_dev ? regs->data[priv->sreg_dev] : -1;
- nf_dup_ipv6(pkt->net, pkt->skb, pkt->hook, gw, oif);
+ nf_dup_ipv6(nft_net(pkt), pkt->skb, nft_hook(pkt), gw, oif);
}
static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
diff --git a/net/ipv6/netfilter/nft_fib_ipv6.c b/net/ipv6/netfilter/nft_fib_ipv6.c
new file mode 100644
index 000000000000..c947aad8bcc6
--- /dev/null
+++ b/net/ipv6/netfilter/nft_fib_ipv6.c
@@ -0,0 +1,275 @@
+/*
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nft_fib.h>
+
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+
+static bool fib6_is_local(const struct sk_buff *skb)
+{
+ const struct rt6_info *rt = (const void *)skb_dst(skb);
+
+ return rt && (rt->rt6i_flags & RTF_LOCAL);
+}
+
+static int get_ifindex(const struct net_device *dev)
+{
+ return dev ? dev->ifindex : 0;
+}
+
+static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv,
+ const struct nft_pktinfo *pkt,
+ const struct net_device *dev)
+{
+ const struct ipv6hdr *iph = ipv6_hdr(pkt->skb);
+ int lookup_flags = 0;
+
+ if (priv->flags & NFTA_FIB_F_DADDR) {
+ fl6->daddr = iph->daddr;
+ fl6->saddr = iph->saddr;
+ } else {
+ fl6->daddr = iph->saddr;
+ fl6->saddr = iph->daddr;
+ }
+
+ if (ipv6_addr_type(&fl6->daddr) & IPV6_ADDR_LINKLOCAL) {
+ lookup_flags |= RT6_LOOKUP_F_IFACE;
+ fl6->flowi6_oif = get_ifindex(dev ? dev : pkt->skb->dev);
+ }
+
+ if (ipv6_addr_type(&fl6->saddr) & IPV6_ADDR_UNICAST)
+ lookup_flags |= RT6_LOOKUP_F_HAS_SADDR;
+
+ if (priv->flags & NFTA_FIB_F_MARK)
+ fl6->flowi6_mark = pkt->skb->mark;
+
+ fl6->flowlabel = (*(__be32 *)iph) & IPV6_FLOWINFO_MASK;
+
+ return lookup_flags;
+}
+
+static u32 __nft_fib6_eval_type(const struct nft_fib *priv,
+ const struct nft_pktinfo *pkt)
+{
+ const struct net_device *dev = NULL;
+ const struct nf_ipv6_ops *v6ops;
+ const struct nf_afinfo *afinfo;
+ int route_err, addrtype;
+ struct rt6_info *rt;
+ struct flowi6 fl6 = {
+ .flowi6_iif = LOOPBACK_IFINDEX,
+ .flowi6_proto = pkt->tprot,
+ };
+ u32 ret = 0;
+
+ afinfo = nf_get_afinfo(NFPROTO_IPV6);
+ if (!afinfo)
+ return RTN_UNREACHABLE;
+
+ if (priv->flags & NFTA_FIB_F_IIF)
+ dev = nft_in(pkt);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+ dev = nft_out(pkt);
+
+ nft_fib6_flowi_init(&fl6, priv, pkt, dev);
+
+ v6ops = nf_get_ipv6_ops();
+ if (dev && v6ops && v6ops->chk_addr(nft_net(pkt), &fl6.daddr, dev, true))
+ ret = RTN_LOCAL;
+
+ route_err = afinfo->route(nft_net(pkt), (struct dst_entry **)&rt,
+ flowi6_to_flowi(&fl6), false);
+ if (route_err)
+ goto err;
+
+ if (rt->rt6i_flags & RTF_REJECT) {
+ route_err = rt->dst.error;
+ dst_release(&rt->dst);
+ goto err;
+ }
+
+ if (ipv6_anycast_destination((struct dst_entry *)rt, &fl6.daddr))
+ ret = RTN_ANYCAST;
+ else if (!dev && rt->rt6i_flags & RTF_LOCAL)
+ ret = RTN_LOCAL;
+
+ dst_release(&rt->dst);
+
+ if (ret)
+ return ret;
+
+ addrtype = ipv6_addr_type(&fl6.daddr);
+
+ if (addrtype & IPV6_ADDR_MULTICAST)
+ return RTN_MULTICAST;
+ if (addrtype & IPV6_ADDR_UNICAST)
+ return RTN_UNICAST;
+
+ return RTN_UNSPEC;
+ err:
+ switch (route_err) {
+ case -EINVAL:
+ return RTN_BLACKHOLE;
+ case -EACCES:
+ return RTN_PROHIBIT;
+ case -EAGAIN:
+ return RTN_THROW;
+ default:
+ break;
+ }
+
+ return RTN_UNREACHABLE;
+}
+
+void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ u32 *dest = &regs->data[priv->dreg];
+
+ *dest = __nft_fib6_eval_type(priv, pkt);
+}
+EXPORT_SYMBOL_GPL(nft_fib6_eval_type);
+
+void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ const struct net_device *oif = NULL;
+ u32 *dest = &regs->data[priv->dreg];
+ struct flowi6 fl6 = {
+ .flowi6_iif = LOOPBACK_IFINDEX,
+ .flowi6_proto = pkt->tprot,
+ };
+ struct rt6_info *rt;
+ int lookup_flags;
+
+ if (priv->flags & NFTA_FIB_F_IIF)
+ oif = nft_in(pkt);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+ oif = nft_out(pkt);
+
+ lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif);
+
+ if (nft_hook(pkt) == NF_INET_PRE_ROUTING && fib6_is_local(pkt->skb)) {
+ nft_fib_store_result(dest, priv->result, pkt, LOOPBACK_IFINDEX);
+ return;
+ }
+
+ *dest = 0;
+ again:
+ rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, lookup_flags);
+ if (rt->dst.error)
+ goto put_rt_err;
+
+ /* Should not see RTF_LOCAL here */
+ if (rt->rt6i_flags & (RTF_REJECT | RTF_ANYCAST | RTF_LOCAL))
+ goto put_rt_err;
+
+ if (oif && oif != rt->rt6i_idev->dev) {
+ /* multipath route? Try again with F_IFACE */
+ if ((lookup_flags & RT6_LOOKUP_F_IFACE) == 0) {
+ lookup_flags |= RT6_LOOKUP_F_IFACE;
+ fl6.flowi6_oif = oif->ifindex;
+ ip6_rt_put(rt);
+ goto again;
+ }
+ }
+
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ *dest = rt->rt6i_idev->dev->ifindex;
+ break;
+ case NFT_FIB_RESULT_OIFNAME:
+ strncpy((char *)dest, rt->rt6i_idev->dev->name, IFNAMSIZ);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ put_rt_err:
+ ip6_rt_put(rt);
+}
+EXPORT_SYMBOL_GPL(nft_fib6_eval);
+
+static struct nft_expr_type nft_fib6_type;
+
+static const struct nft_expr_ops nft_fib6_type_ops = {
+ .type = &nft_fib6_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_fib)),
+ .eval = nft_fib6_eval_type,
+ .init = nft_fib_init,
+ .dump = nft_fib_dump,
+ .validate = nft_fib_validate,
+};
+
+static const struct nft_expr_ops nft_fib6_ops = {
+ .type = &nft_fib6_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_fib)),
+ .eval = nft_fib6_eval,
+ .init = nft_fib_init,
+ .dump = nft_fib_dump,
+ .validate = nft_fib_validate,
+};
+
+static const struct nft_expr_ops *
+nft_fib6_select_ops(const struct nft_ctx *ctx,
+ const struct nlattr * const tb[])
+{
+ enum nft_fib_result result;
+
+ if (!tb[NFTA_FIB_RESULT])
+ return ERR_PTR(-EINVAL);
+
+ result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
+
+ switch (result) {
+ case NFT_FIB_RESULT_OIF:
+ return &nft_fib6_ops;
+ case NFT_FIB_RESULT_OIFNAME:
+ return &nft_fib6_ops;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ return &nft_fib6_type_ops;
+ default:
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+}
+
+static struct nft_expr_type nft_fib6_type __read_mostly = {
+ .name = "fib",
+ .select_ops = &nft_fib6_select_ops,
+ .policy = nft_fib_policy,
+ .maxattr = NFTA_FIB_MAX,
+ .family = NFPROTO_IPV6,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_fib6_module_init(void)
+{
+ return nft_register_expr(&nft_fib6_type);
+}
+
+static void __exit nft_fib6_module_exit(void)
+{
+ nft_unregister_expr(&nft_fib6_type);
+}
+module_init(nft_fib6_module_init);
+module_exit(nft_fib6_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+MODULE_ALIAS_NFT_AF_EXPR(10, "fib");
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c
index 9597ffb74077..6c5b5b1830a7 100644
--- a/net/ipv6/netfilter/nft_masq_ipv6.c
+++ b/net/ipv6/netfilter/nft_masq_ipv6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -32,7 +32,14 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
range.max_proto.all =
*(__be16 *)&regs->data[priv->sreg_proto_max];
}
- regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
+ regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
+ nft_out(pkt));
+}
+
+static void
+nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
+{
+ nf_ct_netns_put(ctx->net, NFPROTO_IPV6);
}
static struct nft_expr_type nft_masq_ipv6_type;
@@ -41,6 +48,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
.eval = nft_masq_ipv6_eval,
.init = nft_masq_init,
+ .destroy = nft_masq_ipv6_destroy,
.dump = nft_masq_dump,
.validate = nft_masq_validate,
};
@@ -77,5 +85,5 @@ module_init(nft_masq_ipv6_module_init);
module_exit(nft_masq_ipv6_module_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c
index aca44e89a881..f5ac080fc084 100644
--- a/net/ipv6/netfilter/nft_redir_ipv6.c
+++ b/net/ipv6/netfilter/nft_redir_ipv6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -35,7 +35,14 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
range.flags |= priv->flags;
- regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->hook);
+ regs->verdict.code =
+ nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));
+}
+
+static void
+nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
+{
+ nf_ct_netns_put(ctx->net, NFPROTO_IPV6);
}
static struct nft_expr_type nft_redir_ipv6_type;
@@ -44,6 +51,7 @@ static const struct nft_expr_ops nft_redir_ipv6_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv6_eval,
.init = nft_redir_init,
+ .destroy = nft_redir_ipv6_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
@@ -71,5 +79,5 @@ module_init(nft_redir_ipv6_module_init);
module_exit(nft_redir_ipv6_module_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c
index 92bda9908bb9..057deeaff1cb 100644
--- a/net/ipv6/netfilter/nft_reject_ipv6.c
+++ b/net/ipv6/netfilter/nft_reject_ipv6.c
@@ -27,11 +27,11 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr,
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach6(pkt->net, pkt->skb, priv->icmp_code,
- pkt->hook);
+ nf_send_unreach6(nft_net(pkt), pkt->skb, priv->icmp_code,
+ nft_hook(pkt));
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset6(pkt->net, pkt->skb, pkt->hook);
+ nf_send_reset6(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
default:
break;
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 66e2d9dfc43a..e1f8b34d7a2e 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -113,6 +113,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
fl6.daddr = *daddr;
fl6.flowi6_oif = oif;
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
fl6.fl6_icmp_type = user_icmph.icmp6_type;
fl6.fl6_icmp_code = user_icmph.icmp6_code;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 054a1d84fc5e..291ebc260e70 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -65,11 +65,12 @@
#define ICMPV6_HDRLEN 4 /* ICMPv6 header, RFC 4443 Section 2.1 */
-static struct raw_hashinfo raw_v6_hashinfo = {
+struct raw_hashinfo raw_v6_hashinfo = {
.lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
};
+EXPORT_SYMBOL_GPL(raw_v6_hashinfo);
-static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
unsigned short num, const struct in6_addr *loc_addr,
const struct in6_addr *rmt_addr, int dif)
{
@@ -102,6 +103,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
found:
return sk;
}
+EXPORT_SYMBOL_GPL(__raw_v6_lookup);
/*
* 0 - deliver
@@ -774,6 +776,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
ipc6.hlimit = -1;
ipc6.tclass = -1;
@@ -1259,6 +1262,7 @@ struct proto rawv6_prot = {
.compat_getsockopt = compat_rawv6_getsockopt,
.compat_ioctl = compat_rawv6_ioctl,
#endif
+ .diag_destroy = raw_abort,
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 3815e8505ed2..e1da5b888cc4 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -211,7 +211,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
{
struct sk_buff *prev, *next;
struct net_device *dev;
- int offset, end;
+ int offset, end, fragsize;
struct net *net = dev_net(skb_dst(skb)->dev);
u8 ecn;
@@ -336,6 +336,10 @@ found:
fq->ecn |= ecn;
add_frag_mem_limit(fq->q.net, skb->truesize);
+ fragsize = -skb_network_offset(skb) + skb->len;
+ if (fragsize > fq->q.max_size)
+ fq->q.max_size = fragsize;
+
/* The first fragment.
* nhoffset is obtained from the first fragment, of course.
*/
@@ -495,6 +499,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
IP6CB(head)->nhoff = nhoff;
IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
+ IP6CB(head)->frag_max_size = fq->q.max_size;
/* Yes, and fold redundant checksum back. 8) */
skb_postpush_rcsum(head, skb_network_header(head),
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1b57e11e6e0d..2413a0637d99 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -527,7 +527,7 @@ static void rt6_probe_deferred(struct work_struct *w)
container_of(w, struct __rt6_probe_work, work);
addrconf_addr_solict_mult(&work->target, &mcaddr);
- ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL);
+ ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, 0);
dev_put(work->dev);
kfree(work);
}
@@ -1408,7 +1408,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
}
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
- int oif, u32 mark)
+ int oif, u32 mark, kuid_t uid)
{
const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst;
@@ -1420,6 +1420,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph);
+ fl6.flowi6_uid = uid;
dst = ip6_route_output(net, NULL, &fl6);
if (!dst->error)
@@ -1433,7 +1434,7 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
struct dst_entry *dst;
ip6_update_pmtu(skb, sock_net(sk), mtu,
- sk->sk_bound_dev_if, sk->sk_mark);
+ sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid);
dst = __sk_dst_get(sk);
if (!dst || !dst->obsolete ||
@@ -1525,7 +1526,8 @@ static struct dst_entry *ip6_route_redirect(struct net *net,
flags, __ip6_route_redirect);
}
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+ kuid_t uid)
{
const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst;
@@ -1538,6 +1540,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph);
+ fl6.flowi6_uid = uid;
dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
rt6_do_redirect(dst, NULL, skb);
@@ -1559,6 +1562,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
fl6.flowi6_mark = mark;
fl6.daddr = msg->dest;
fl6.saddr = iph->daddr;
+ fl6.flowi6_uid = sock_net_uid(net, NULL);
dst = ip6_route_redirect(net, &fl6, &iph->saddr);
rt6_do_redirect(dst, NULL, skb);
@@ -1567,7 +1571,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
{
- ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
+ ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
+ sk->sk_uid);
}
EXPORT_SYMBOL_GPL(ip6_sk_redirect);
@@ -1995,8 +2000,11 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)
It is very good, but in some (rare!) circumstances
(SIT, PtP, NBMA NOARP links) it is handy to allow
some exceptions. --ANK
+ We allow IPv4-mapped nexthops to support RFC4798-type
+ addressing
*/
- if (!(gwa_type & IPV6_ADDR_UNICAST))
+ if (!(gwa_type & (IPV6_ADDR_UNICAST |
+ IPV6_ADDR_MAPPED)))
goto out;
if (cfg->fc_table) {
@@ -2801,6 +2809,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_ENCAP_TYPE] = { .type = NLA_U16 },
[RTA_ENCAP] = { .type = NLA_NESTED },
[RTA_EXPIRES] = { .type = NLA_U32 },
+ [RTA_UID] = { .type = NLA_U32 },
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -3375,6 +3384,12 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
if (tb[RTA_MARK])
fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]);
+ if (tb[RTA_UID])
+ fl6.flowi6_uid = make_kuid(current_user_ns(),
+ nla_get_u32(tb[RTA_UID]));
+ else
+ fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
+
if (iif) {
struct net_device *dev;
int flags = 0;
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
new file mode 100644
index 000000000000..b172d85c650a
--- /dev/null
+++ b/net/ipv6/seg6.c
@@ -0,0 +1,495 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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/types.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <linux/in6.h>
+#include <linux/slab.h>
+
+#include <net/ipv6.h>
+#include <net/protocol.h>
+
+#include <net/seg6.h>
+#include <net/genetlink.h>
+#include <linux/seg6.h>
+#include <linux/seg6_genl.h>
+#ifdef CONFIG_IPV6_SEG6_HMAC
+#include <net/seg6_hmac.h>
+#endif
+
+bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
+{
+ int trailing;
+ unsigned int tlv_offset;
+
+ if (srh->type != IPV6_SRCRT_TYPE_4)
+ return false;
+
+ if (((srh->hdrlen + 1) << 3) != len)
+ return false;
+
+ if (srh->segments_left != srh->first_segment)
+ return false;
+
+ tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4);
+
+ trailing = len - tlv_offset;
+ if (trailing < 0)
+ return false;
+
+ while (trailing) {
+ struct sr6_tlv *tlv;
+ unsigned int tlv_len;
+
+ tlv = (struct sr6_tlv *)((unsigned char *)srh + tlv_offset);
+ tlv_len = sizeof(*tlv) + tlv->len;
+
+ trailing -= tlv_len;
+ if (trailing < 0)
+ return false;
+
+ tlv_offset += tlv_len;
+ }
+
+ return true;
+}
+
+static struct genl_family seg6_genl_family;
+
+static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = {
+ [SEG6_ATTR_DST] = { .type = NLA_BINARY,
+ .len = sizeof(struct in6_addr) },
+ [SEG6_ATTR_DSTLEN] = { .type = NLA_S32, },
+ [SEG6_ATTR_HMACKEYID] = { .type = NLA_U32, },
+ [SEG6_ATTR_SECRET] = { .type = NLA_BINARY, },
+ [SEG6_ATTR_SECRETLEN] = { .type = NLA_U8, },
+ [SEG6_ATTR_ALGID] = { .type = NLA_U8, },
+ [SEG6_ATTR_HMACINFO] = { .type = NLA_NESTED, },
+};
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+
+static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct seg6_pernet_data *sdata;
+ struct seg6_hmac_info *hinfo;
+ u32 hmackeyid;
+ char *secret;
+ int err = 0;
+ u8 algid;
+ u8 slen;
+
+ sdata = seg6_pernet(net);
+
+ if (!info->attrs[SEG6_ATTR_HMACKEYID] ||
+ !info->attrs[SEG6_ATTR_SECRETLEN] ||
+ !info->attrs[SEG6_ATTR_ALGID])
+ return -EINVAL;
+
+ hmackeyid = nla_get_u32(info->attrs[SEG6_ATTR_HMACKEYID]);
+ slen = nla_get_u8(info->attrs[SEG6_ATTR_SECRETLEN]);
+ algid = nla_get_u8(info->attrs[SEG6_ATTR_ALGID]);
+
+ if (hmackeyid == 0)
+ return -EINVAL;
+
+ if (slen > SEG6_HMAC_SECRET_LEN)
+ return -EINVAL;
+
+ mutex_lock(&sdata->lock);
+ hinfo = seg6_hmac_info_lookup(net, hmackeyid);
+
+ if (!slen) {
+ if (!hinfo)
+ err = -ENOENT;
+
+ err = seg6_hmac_info_del(net, hmackeyid);
+
+ goto out_unlock;
+ }
+
+ if (!info->attrs[SEG6_ATTR_SECRET]) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
+ if (hinfo) {
+ err = seg6_hmac_info_del(net, hmackeyid);
+ if (err)
+ goto out_unlock;
+ }
+
+ secret = (char *)nla_data(info->attrs[SEG6_ATTR_SECRET]);
+
+ hinfo = kzalloc(sizeof(*hinfo), GFP_KERNEL);
+ if (!hinfo) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+
+ memcpy(hinfo->secret, secret, slen);
+ hinfo->slen = slen;
+ hinfo->alg_id = algid;
+ hinfo->hmackeyid = hmackeyid;
+
+ err = seg6_hmac_info_add(net, hmackeyid, hinfo);
+ if (err)
+ kfree(hinfo);
+
+out_unlock:
+ mutex_unlock(&sdata->lock);
+ return err;
+}
+
+#else
+
+static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info)
+{
+ return -ENOTSUPP;
+}
+
+#endif
+
+static int seg6_genl_set_tunsrc(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct in6_addr *val, *t_old, *t_new;
+ struct seg6_pernet_data *sdata;
+
+ sdata = seg6_pernet(net);
+
+ if (!info->attrs[SEG6_ATTR_DST])
+ return -EINVAL;
+
+ val = nla_data(info->attrs[SEG6_ATTR_DST]);
+ t_new = kmemdup(val, sizeof(*val), GFP_KERNEL);
+
+ mutex_lock(&sdata->lock);
+
+ t_old = sdata->tun_src;
+ rcu_assign_pointer(sdata->tun_src, t_new);
+
+ mutex_unlock(&sdata->lock);
+
+ synchronize_net();
+ kfree(t_old);
+
+ return 0;
+}
+
+static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct in6_addr *tun_src;
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &seg6_genl_family, 0, SEG6_CMD_GET_TUNSRC);
+ if (!hdr)
+ goto free_msg;
+
+ rcu_read_lock();
+ tun_src = rcu_dereference(seg6_pernet(net)->tun_src);
+
+ if (nla_put(msg, SEG6_ATTR_DST, sizeof(struct in6_addr), tun_src))
+ goto nla_put_failure;
+
+ rcu_read_unlock();
+
+ genlmsg_end(msg, hdr);
+ genlmsg_reply(msg, info);
+
+ return 0;
+
+nla_put_failure:
+ rcu_read_unlock();
+ genlmsg_cancel(msg, hdr);
+free_msg:
+ nlmsg_free(msg);
+ return -ENOMEM;
+}
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+
+static int __seg6_hmac_fill_info(struct seg6_hmac_info *hinfo,
+ struct sk_buff *msg)
+{
+ if (nla_put_u32(msg, SEG6_ATTR_HMACKEYID, hinfo->hmackeyid) ||
+ nla_put_u8(msg, SEG6_ATTR_SECRETLEN, hinfo->slen) ||
+ nla_put(msg, SEG6_ATTR_SECRET, hinfo->slen, hinfo->secret) ||
+ nla_put_u8(msg, SEG6_ATTR_ALGID, hinfo->alg_id))
+ return -1;
+
+ return 0;
+}
+
+static int __seg6_genl_dumphmac_element(struct seg6_hmac_info *hinfo,
+ u32 portid, u32 seq, u32 flags,
+ struct sk_buff *skb, u8 cmd)
+{
+ void *hdr;
+
+ hdr = genlmsg_put(skb, portid, seq, &seg6_genl_family, flags, cmd);
+ if (!hdr)
+ return -ENOMEM;
+
+ if (__seg6_hmac_fill_info(hinfo, skb) < 0)
+ goto nla_put_failure;
+
+ genlmsg_end(skb, hdr);
+ return 0;
+
+nla_put_failure:
+ genlmsg_cancel(skb, hdr);
+ return -EMSGSIZE;
+}
+
+static int seg6_genl_dumphmac_start(struct netlink_callback *cb)
+{
+ struct net *net = sock_net(cb->skb->sk);
+ struct seg6_pernet_data *sdata;
+ struct rhashtable_iter *iter;
+
+ sdata = seg6_pernet(net);
+ iter = (struct rhashtable_iter *)cb->args[0];
+
+ if (!iter) {
+ iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
+
+ cb->args[0] = (long)iter;
+ }
+
+ rhashtable_walk_enter(&sdata->hmac_infos, iter);
+
+ return 0;
+}
+
+static int seg6_genl_dumphmac_done(struct netlink_callback *cb)
+{
+ struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
+
+ rhashtable_walk_exit(iter);
+
+ kfree(iter);
+
+ return 0;
+}
+
+static int seg6_genl_dumphmac(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
+ struct net *net = sock_net(skb->sk);
+ struct seg6_pernet_data *sdata;
+ struct seg6_hmac_info *hinfo;
+ int ret;
+
+ sdata = seg6_pernet(net);
+
+ ret = rhashtable_walk_start(iter);
+ if (ret && ret != -EAGAIN)
+ goto done;
+
+ for (;;) {
+ hinfo = rhashtable_walk_next(iter);
+
+ if (IS_ERR(hinfo)) {
+ if (PTR_ERR(hinfo) == -EAGAIN)
+ continue;
+ ret = PTR_ERR(hinfo);
+ goto done;
+ } else if (!hinfo) {
+ break;
+ }
+
+ ret = __seg6_genl_dumphmac_element(hinfo,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ NLM_F_MULTI,
+ skb, SEG6_CMD_DUMPHMAC);
+ if (ret)
+ goto done;
+ }
+
+ ret = skb->len;
+
+done:
+ rhashtable_walk_stop(iter);
+ return ret;
+}
+
+#else
+
+static int seg6_genl_dumphmac_start(struct netlink_callback *cb)
+{
+ return 0;
+}
+
+static int seg6_genl_dumphmac_done(struct netlink_callback *cb)
+{
+ return 0;
+}
+
+static int seg6_genl_dumphmac(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ return -ENOTSUPP;
+}
+
+#endif
+
+static int __net_init seg6_net_init(struct net *net)
+{
+ struct seg6_pernet_data *sdata;
+
+ sdata = kzalloc(sizeof(*sdata), GFP_KERNEL);
+ if (!sdata)
+ return -ENOMEM;
+
+ mutex_init(&sdata->lock);
+
+ sdata->tun_src = kzalloc(sizeof(*sdata->tun_src), GFP_KERNEL);
+ if (!sdata->tun_src) {
+ kfree(sdata);
+ return -ENOMEM;
+ }
+
+ net->ipv6.seg6_data = sdata;
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ seg6_hmac_net_init(net);
+#endif
+
+ return 0;
+}
+
+static void __net_exit seg6_net_exit(struct net *net)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ seg6_hmac_net_exit(net);
+#endif
+
+ kfree(sdata->tun_src);
+ kfree(sdata);
+}
+
+static struct pernet_operations ip6_segments_ops = {
+ .init = seg6_net_init,
+ .exit = seg6_net_exit,
+};
+
+static const struct genl_ops seg6_genl_ops[] = {
+ {
+ .cmd = SEG6_CMD_SETHMAC,
+ .doit = seg6_genl_sethmac,
+ .policy = seg6_genl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = SEG6_CMD_DUMPHMAC,
+ .start = seg6_genl_dumphmac_start,
+ .dumpit = seg6_genl_dumphmac,
+ .done = seg6_genl_dumphmac_done,
+ .policy = seg6_genl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = SEG6_CMD_SET_TUNSRC,
+ .doit = seg6_genl_set_tunsrc,
+ .policy = seg6_genl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = SEG6_CMD_GET_TUNSRC,
+ .doit = seg6_genl_get_tunsrc,
+ .policy = seg6_genl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+static struct genl_family seg6_genl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = SEG6_GENL_NAME,
+ .version = SEG6_GENL_VERSION,
+ .maxattr = SEG6_ATTR_MAX,
+ .netnsok = true,
+ .parallel_ops = true,
+ .ops = seg6_genl_ops,
+ .n_ops = ARRAY_SIZE(seg6_genl_ops),
+ .module = THIS_MODULE,
+};
+
+int __init seg6_init(void)
+{
+ int err = -ENOMEM;
+
+ err = genl_register_family(&seg6_genl_family);
+ if (err)
+ goto out;
+
+ err = register_pernet_subsys(&ip6_segments_ops);
+ if (err)
+ goto out_unregister_genl;
+
+#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ err = seg6_iptunnel_init();
+ if (err)
+ goto out_unregister_pernet;
+#endif
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ err = seg6_hmac_init();
+ if (err)
+ goto out_unregister_iptun;
+#endif
+
+ pr_info("Segment Routing with IPv6\n");
+
+out:
+ return err;
+#ifdef CONFIG_IPV6_SEG6_HMAC
+out_unregister_iptun:
+#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ seg6_iptunnel_exit();
+#endif
+#endif
+#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+out_unregister_pernet:
+ unregister_pernet_subsys(&ip6_segments_ops);
+#endif
+out_unregister_genl:
+ genl_unregister_family(&seg6_genl_family);
+ goto out;
+}
+
+void seg6_exit(void)
+{
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ seg6_hmac_exit();
+#endif
+#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ seg6_iptunnel_exit();
+#endif
+ unregister_pernet_subsys(&ip6_segments_ops);
+ genl_unregister_family(&seg6_genl_family);
+}
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
new file mode 100644
index 000000000000..ef1c8a46e7ac
--- /dev/null
+++ b/net/ipv6/seg6_hmac.c
@@ -0,0 +1,484 @@
+/*
+ * SR-IPv6 implementation -- HMAC functions
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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/types.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/in6.h>
+#include <linux/icmpv6.h>
+#include <linux/mroute6.h>
+#include <linux/slab.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+
+#include <net/sock.h>
+#include <net/snmp.h>
+
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/transp_v6.h>
+#include <net/rawv6.h>
+#include <net/ndisc.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+#include <net/xfrm.h>
+
+#include <linux/cryptohash.h>
+#include <crypto/hash.h>
+#include <crypto/sha.h>
+#include <net/seg6.h>
+#include <net/genetlink.h>
+#include <net/seg6_hmac.h>
+#include <linux/random.h>
+
+static char * __percpu *hmac_ring;
+
+static int seg6_hmac_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
+{
+ const struct seg6_hmac_info *hinfo = obj;
+
+ return (hinfo->hmackeyid != *(__u32 *)arg->key);
+}
+
+static inline void seg6_hinfo_release(struct seg6_hmac_info *hinfo)
+{
+ kfree_rcu(hinfo, rcu);
+}
+
+static void seg6_free_hi(void *ptr, void *arg)
+{
+ struct seg6_hmac_info *hinfo = (struct seg6_hmac_info *)ptr;
+
+ if (hinfo)
+ seg6_hinfo_release(hinfo);
+}
+
+static const struct rhashtable_params rht_params = {
+ .head_offset = offsetof(struct seg6_hmac_info, node),
+ .key_offset = offsetof(struct seg6_hmac_info, hmackeyid),
+ .key_len = sizeof(u32),
+ .automatic_shrinking = true,
+ .obj_cmpfn = seg6_hmac_cmpfn,
+};
+
+static struct seg6_hmac_algo hmac_algos[] = {
+ {
+ .alg_id = SEG6_HMAC_ALGO_SHA1,
+ .name = "hmac(sha1)",
+ },
+ {
+ .alg_id = SEG6_HMAC_ALGO_SHA256,
+ .name = "hmac(sha256)",
+ },
+};
+
+static struct sr6_tlv_hmac *seg6_get_tlv_hmac(struct ipv6_sr_hdr *srh)
+{
+ struct sr6_tlv_hmac *tlv;
+
+ if (srh->hdrlen < (srh->first_segment + 1) * 2 + 5)
+ return NULL;
+
+ if (!sr_has_hmac(srh))
+ return NULL;
+
+ tlv = (struct sr6_tlv_hmac *)
+ ((char *)srh + ((srh->hdrlen + 1) << 3) - 40);
+
+ if (tlv->tlvhdr.type != SR6_TLV_HMAC || tlv->tlvhdr.len != 38)
+ return NULL;
+
+ return tlv;
+}
+
+static struct seg6_hmac_algo *__hmac_get_algo(u8 alg_id)
+{
+ struct seg6_hmac_algo *algo;
+ int i, alg_count;
+
+ alg_count = sizeof(hmac_algos) / sizeof(struct seg6_hmac_algo);
+ for (i = 0; i < alg_count; i++) {
+ algo = &hmac_algos[i];
+ if (algo->alg_id == alg_id)
+ return algo;
+ }
+
+ return NULL;
+}
+
+static int __do_hmac(struct seg6_hmac_info *hinfo, const char *text, u8 psize,
+ u8 *output, int outlen)
+{
+ struct seg6_hmac_algo *algo;
+ struct crypto_shash *tfm;
+ struct shash_desc *shash;
+ int ret, dgsize;
+
+ algo = __hmac_get_algo(hinfo->alg_id);
+ if (!algo)
+ return -ENOENT;
+
+ tfm = *this_cpu_ptr(algo->tfms);
+
+ dgsize = crypto_shash_digestsize(tfm);
+ if (dgsize > outlen) {
+ pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
+ dgsize, outlen);
+ return -ENOMEM;
+ }
+
+ ret = crypto_shash_setkey(tfm, hinfo->secret, hinfo->slen);
+ if (ret < 0) {
+ pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret);
+ goto failed;
+ }
+
+ shash = *this_cpu_ptr(algo->shashs);
+ shash->tfm = tfm;
+
+ ret = crypto_shash_digest(shash, text, psize, output);
+ if (ret < 0) {
+ pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret);
+ goto failed;
+ }
+
+ return dgsize;
+
+failed:
+ return ret;
+}
+
+int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
+ struct in6_addr *saddr, u8 *output)
+{
+ __be32 hmackeyid = cpu_to_be32(hinfo->hmackeyid);
+ u8 tmp_out[SEG6_HMAC_MAX_DIGESTSIZE];
+ int plen, i, dgsize, wrsize;
+ char *ring, *off;
+
+ /* a 160-byte buffer for digest output allows to store highest known
+ * hash function (RadioGatun) with up to 1216 bits
+ */
+
+ /* saddr(16) + first_seg(1) + cleanup(1) + keyid(4) + seglist(16n) */
+ plen = 16 + 1 + 1 + 4 + (hdr->first_segment + 1) * 16;
+
+ /* this limit allows for 14 segments */
+ if (plen >= SEG6_HMAC_RING_SIZE)
+ return -EMSGSIZE;
+
+ /* Let's build the HMAC text on the ring buffer. The text is composed
+ * as follows, in order:
+ *
+ * 1. Source IPv6 address (128 bits)
+ * 2. first_segment value (8 bits)
+ * 3. cleanup flag (8 bits: highest bit is cleanup value, others are 0)
+ * 4. HMAC Key ID (32 bits)
+ * 5. All segments in the segments list (n * 128 bits)
+ */
+
+ local_bh_disable();
+ ring = *this_cpu_ptr(hmac_ring);
+ off = ring;
+
+ /* source address */
+ memcpy(off, saddr, 16);
+ off += 16;
+
+ /* first_segment value */
+ *off++ = hdr->first_segment;
+
+ /* cleanup flag */
+ *off++ = !!(sr_has_cleanup(hdr)) << 7;
+
+ /* HMAC Key ID */
+ memcpy(off, &hmackeyid, 4);
+ off += 4;
+
+ /* all segments in the list */
+ for (i = 0; i < hdr->first_segment + 1; i++) {
+ memcpy(off, hdr->segments + i, 16);
+ off += 16;
+ }
+
+ dgsize = __do_hmac(hinfo, ring, plen, tmp_out,
+ SEG6_HMAC_MAX_DIGESTSIZE);
+ local_bh_enable();
+
+ if (dgsize < 0)
+ return dgsize;
+
+ wrsize = SEG6_HMAC_FIELD_LEN;
+ if (wrsize > dgsize)
+ wrsize = dgsize;
+
+ memset(output, 0, SEG6_HMAC_FIELD_LEN);
+ memcpy(output, tmp_out, wrsize);
+
+ return 0;
+}
+EXPORT_SYMBOL(seg6_hmac_compute);
+
+/* checks if an incoming SR-enabled packet's HMAC status matches
+ * the incoming policy.
+ *
+ * called with rcu_read_lock()
+ */
+bool seg6_hmac_validate_skb(struct sk_buff *skb)
+{
+ u8 hmac_output[SEG6_HMAC_FIELD_LEN];
+ struct net *net = dev_net(skb->dev);
+ struct seg6_hmac_info *hinfo;
+ struct sr6_tlv_hmac *tlv;
+ struct ipv6_sr_hdr *srh;
+ struct inet6_dev *idev;
+
+ idev = __in6_dev_get(skb->dev);
+
+ srh = (struct ipv6_sr_hdr *)skb_transport_header(skb);
+
+ tlv = seg6_get_tlv_hmac(srh);
+
+ /* mandatory check but no tlv */
+ if (idev->cnf.seg6_require_hmac > 0 && !tlv)
+ return false;
+
+ /* no check */
+ if (idev->cnf.seg6_require_hmac < 0)
+ return true;
+
+ /* check only if present */
+ if (idev->cnf.seg6_require_hmac == 0 && !tlv)
+ return true;
+
+ /* now, seg6_require_hmac >= 0 && tlv */
+
+ hinfo = seg6_hmac_info_lookup(net, be32_to_cpu(tlv->hmackeyid));
+ if (!hinfo)
+ return false;
+
+ if (seg6_hmac_compute(hinfo, srh, &ipv6_hdr(skb)->saddr, hmac_output))
+ return false;
+
+ if (memcmp(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN) != 0)
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL(seg6_hmac_validate_skb);
+
+/* called with rcu_read_lock() */
+struct seg6_hmac_info *seg6_hmac_info_lookup(struct net *net, u32 key)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+ struct seg6_hmac_info *hinfo;
+
+ hinfo = rhashtable_lookup_fast(&sdata->hmac_infos, &key, rht_params);
+
+ return hinfo;
+}
+EXPORT_SYMBOL(seg6_hmac_info_lookup);
+
+int seg6_hmac_info_add(struct net *net, u32 key, struct seg6_hmac_info *hinfo)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+ int err;
+
+ err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node,
+ rht_params);
+
+ return err;
+}
+EXPORT_SYMBOL(seg6_hmac_info_add);
+
+int seg6_hmac_info_del(struct net *net, u32 key)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+ struct seg6_hmac_info *hinfo;
+ int err = -ENOENT;
+
+ hinfo = rhashtable_lookup_fast(&sdata->hmac_infos, &key, rht_params);
+ if (!hinfo)
+ goto out;
+
+ err = rhashtable_remove_fast(&sdata->hmac_infos, &hinfo->node,
+ rht_params);
+ if (err)
+ goto out;
+
+ seg6_hinfo_release(hinfo);
+
+out:
+ return err;
+}
+EXPORT_SYMBOL(seg6_hmac_info_del);
+
+int seg6_push_hmac(struct net *net, struct in6_addr *saddr,
+ struct ipv6_sr_hdr *srh)
+{
+ struct seg6_hmac_info *hinfo;
+ struct sr6_tlv_hmac *tlv;
+ int err = -ENOENT;
+
+ tlv = seg6_get_tlv_hmac(srh);
+ if (!tlv)
+ return -EINVAL;
+
+ rcu_read_lock();
+
+ hinfo = seg6_hmac_info_lookup(net, be32_to_cpu(tlv->hmackeyid));
+ if (!hinfo)
+ goto out;
+
+ memset(tlv->hmac, 0, SEG6_HMAC_FIELD_LEN);
+ err = seg6_hmac_compute(hinfo, srh, saddr, tlv->hmac);
+
+out:
+ rcu_read_unlock();
+ return err;
+}
+EXPORT_SYMBOL(seg6_push_hmac);
+
+static int seg6_hmac_init_ring(void)
+{
+ int i;
+
+ hmac_ring = alloc_percpu(char *);
+
+ if (!hmac_ring)
+ return -ENOMEM;
+
+ for_each_possible_cpu(i) {
+ char *ring = kzalloc(SEG6_HMAC_RING_SIZE, GFP_KERNEL);
+
+ if (!ring)
+ return -ENOMEM;
+
+ *per_cpu_ptr(hmac_ring, i) = ring;
+ }
+
+ return 0;
+}
+
+static int seg6_hmac_init_algo(void)
+{
+ struct seg6_hmac_algo *algo;
+ struct crypto_shash *tfm;
+ struct shash_desc *shash;
+ int i, alg_count, cpu;
+
+ alg_count = sizeof(hmac_algos) / sizeof(struct seg6_hmac_algo);
+
+ for (i = 0; i < alg_count; i++) {
+ struct crypto_shash **p_tfm;
+ int shsize;
+
+ algo = &hmac_algos[i];
+ algo->tfms = alloc_percpu(struct crypto_shash *);
+ if (!algo->tfms)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ tfm = crypto_alloc_shash(algo->name, 0, GFP_KERNEL);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+ p_tfm = per_cpu_ptr(algo->tfms, cpu);
+ *p_tfm = tfm;
+ }
+
+ p_tfm = this_cpu_ptr(algo->tfms);
+ tfm = *p_tfm;
+
+ shsize = sizeof(*shash) + crypto_shash_descsize(tfm);
+
+ algo->shashs = alloc_percpu(struct shash_desc *);
+ if (!algo->shashs)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ shash = kzalloc(shsize, GFP_KERNEL);
+ if (!shash)
+ return -ENOMEM;
+ *per_cpu_ptr(algo->shashs, cpu) = shash;
+ }
+ }
+
+ return 0;
+}
+
+int __init seg6_hmac_init(void)
+{
+ int ret;
+
+ ret = seg6_hmac_init_ring();
+ if (ret < 0)
+ goto out;
+
+ ret = seg6_hmac_init_algo();
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(seg6_hmac_init);
+
+int __net_init seg6_hmac_net_init(struct net *net)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+
+ rhashtable_init(&sdata->hmac_infos, &rht_params);
+
+ return 0;
+}
+EXPORT_SYMBOL(seg6_hmac_net_init);
+
+void seg6_hmac_exit(void)
+{
+ struct seg6_hmac_algo *algo = NULL;
+ int i, alg_count, cpu;
+
+ for_each_possible_cpu(i) {
+ char *ring = *per_cpu_ptr(hmac_ring, i);
+
+ kfree(ring);
+ }
+ free_percpu(hmac_ring);
+
+ alg_count = sizeof(hmac_algos) / sizeof(struct seg6_hmac_algo);
+ for (i = 0; i < alg_count; i++) {
+ algo = &hmac_algos[i];
+ for_each_possible_cpu(cpu) {
+ struct crypto_shash *tfm;
+ struct shash_desc *shash;
+
+ shash = *per_cpu_ptr(algo->shashs, cpu);
+ kfree(shash);
+ tfm = *per_cpu_ptr(algo->tfms, cpu);
+ crypto_free_shash(tfm);
+ }
+ free_percpu(algo->tfms);
+ free_percpu(algo->shashs);
+ }
+}
+EXPORT_SYMBOL(seg6_hmac_exit);
+
+void __net_exit seg6_hmac_net_exit(struct net *net)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+
+ rhashtable_free_and_destroy(&sdata->hmac_infos, seg6_free_hi, NULL);
+}
+EXPORT_SYMBOL(seg6_hmac_net_exit);
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
new file mode 100644
index 000000000000..bbfca22c34ae
--- /dev/null
+++ b/net/ipv6/seg6_iptunnel.c
@@ -0,0 +1,431 @@
+/*
+ * SR-IPv6 implementation
+ *
+ * Author:
+ * David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ * 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/types.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/lwtunnel.h>
+#include <net/netevent.h>
+#include <net/netns/generic.h>
+#include <net/ip6_fib.h>
+#include <net/route.h>
+#include <net/seg6.h>
+#include <linux/seg6.h>
+#include <linux/seg6_iptunnel.h>
+#include <net/addrconf.h>
+#include <net/ip6_route.h>
+#ifdef CONFIG_DST_CACHE
+#include <net/dst_cache.h>
+#endif
+#ifdef CONFIG_IPV6_SEG6_HMAC
+#include <net/seg6_hmac.h>
+#endif
+
+struct seg6_lwt {
+#ifdef CONFIG_DST_CACHE
+ struct dst_cache cache;
+#endif
+ struct seg6_iptunnel_encap tuninfo[0];
+};
+
+static inline struct seg6_lwt *seg6_lwt_lwtunnel(struct lwtunnel_state *lwt)
+{
+ return (struct seg6_lwt *)lwt->data;
+}
+
+static inline struct seg6_iptunnel_encap *
+seg6_encap_lwtunnel(struct lwtunnel_state *lwt)
+{
+ return seg6_lwt_lwtunnel(lwt)->tuninfo;
+}
+
+static const struct nla_policy seg6_iptunnel_policy[SEG6_IPTUNNEL_MAX + 1] = {
+ [SEG6_IPTUNNEL_SRH] = { .type = NLA_BINARY },
+};
+
+int nla_put_srh(struct sk_buff *skb, int attrtype,
+ struct seg6_iptunnel_encap *tuninfo)
+{
+ struct seg6_iptunnel_encap *data;
+ struct nlattr *nla;
+ int len;
+
+ len = SEG6_IPTUN_ENCAP_SIZE(tuninfo);
+
+ nla = nla_reserve(skb, attrtype, len);
+ if (!nla)
+ return -EMSGSIZE;
+
+ data = nla_data(nla);
+ memcpy(data, tuninfo, len);
+
+ return 0;
+}
+
+static void set_tun_src(struct net *net, struct net_device *dev,
+ struct in6_addr *daddr, struct in6_addr *saddr)
+{
+ struct seg6_pernet_data *sdata = seg6_pernet(net);
+ struct in6_addr *tun_src;
+
+ rcu_read_lock();
+
+ tun_src = rcu_dereference(sdata->tun_src);
+
+ if (!ipv6_addr_any(tun_src)) {
+ memcpy(saddr, tun_src, sizeof(struct in6_addr));
+ } else {
+ ipv6_dev_get_saddr(net, dev, daddr, IPV6_PREFER_SRC_PUBLIC,
+ saddr);
+ }
+
+ rcu_read_unlock();
+}
+
+/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
+static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+{
+ struct net *net = dev_net(skb_dst(skb)->dev);
+ struct ipv6hdr *hdr, *inner_hdr;
+ struct ipv6_sr_hdr *isrh;
+ int hdrlen, tot_len, err;
+
+ hdrlen = (osrh->hdrlen + 1) << 3;
+ tot_len = hdrlen + sizeof(*hdr);
+
+ err = pskb_expand_head(skb, tot_len, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return err;
+
+ inner_hdr = ipv6_hdr(skb);
+
+ skb_push(skb, tot_len);
+ skb_reset_network_header(skb);
+ skb_mac_header_rebuild(skb);
+ hdr = ipv6_hdr(skb);
+
+ /* inherit tc, flowlabel and hlim
+ * hlim will be decremented in ip6_forward() afterwards and
+ * decapsulation will overwrite inner hlim with outer hlim
+ */
+ ip6_flow_hdr(hdr, ip6_tclass(ip6_flowinfo(inner_hdr)),
+ ip6_flowlabel(inner_hdr));
+ hdr->hop_limit = inner_hdr->hop_limit;
+ hdr->nexthdr = NEXTHDR_ROUTING;
+
+ isrh = (void *)hdr + sizeof(*hdr);
+ memcpy(isrh, osrh, hdrlen);
+
+ isrh->nexthdr = NEXTHDR_IPV6;
+
+ hdr->daddr = isrh->segments[isrh->first_segment];
+ set_tun_src(net, skb->dev, &hdr->daddr, &hdr->saddr);
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (sr_has_hmac(isrh)) {
+ err = seg6_push_hmac(net, &hdr->saddr, isrh);
+ if (unlikely(err))
+ return err;
+ }
+#endif
+
+ skb_postpush_rcsum(skb, hdr, tot_len);
+
+ return 0;
+}
+
+/* insert an SRH within an IPv6 packet, just after the IPv6 header */
+#ifdef CONFIG_IPV6_SEG6_INLINE
+static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+{
+ struct ipv6hdr *hdr, *oldhdr;
+ struct ipv6_sr_hdr *isrh;
+ int hdrlen, err;
+
+ hdrlen = (osrh->hdrlen + 1) << 3;
+
+ err = pskb_expand_head(skb, hdrlen, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return err;
+
+ oldhdr = ipv6_hdr(skb);
+
+ skb_pull(skb, sizeof(struct ipv6hdr));
+ skb_postpull_rcsum(skb, skb_network_header(skb),
+ sizeof(struct ipv6hdr));
+
+ skb_push(skb, sizeof(struct ipv6hdr) + hdrlen);
+ skb_reset_network_header(skb);
+ skb_mac_header_rebuild(skb);
+
+ hdr = ipv6_hdr(skb);
+
+ memmove(hdr, oldhdr, sizeof(*hdr));
+
+ isrh = (void *)hdr + sizeof(*hdr);
+ memcpy(isrh, osrh, hdrlen);
+
+ isrh->nexthdr = hdr->nexthdr;
+ hdr->nexthdr = NEXTHDR_ROUTING;
+
+ isrh->segments[0] = hdr->daddr;
+ hdr->daddr = isrh->segments[isrh->first_segment];
+
+#ifdef CONFIG_IPV6_SEG6_HMAC
+ if (sr_has_hmac(isrh)) {
+ struct net *net = dev_net(skb_dst(skb)->dev);
+
+ err = seg6_push_hmac(net, &hdr->saddr, isrh);
+ if (unlikely(err))
+ return err;
+ }
+#endif
+
+ skb_postpush_rcsum(skb, hdr, sizeof(struct ipv6hdr) + hdrlen);
+
+ return 0;
+}
+#endif
+
+static int seg6_do_srh(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+ struct seg6_iptunnel_encap *tinfo;
+ int err = 0;
+
+ tinfo = seg6_encap_lwtunnel(dst->lwtstate);
+
+ if (likely(!skb->encapsulation)) {
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+ }
+
+ switch (tinfo->mode) {
+#ifdef CONFIG_IPV6_SEG6_INLINE
+ case SEG6_IPTUN_MODE_INLINE:
+ err = seg6_do_srh_inline(skb, tinfo->srh);
+ skb_reset_inner_headers(skb);
+ break;
+#endif
+ case SEG6_IPTUN_MODE_ENCAP:
+ err = seg6_do_srh_encap(skb, tinfo->srh);
+ break;
+ }
+
+ if (err)
+ return err;
+
+ ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+
+ skb_set_inner_protocol(skb, skb->protocol);
+
+ return 0;
+}
+
+int seg6_input(struct sk_buff *skb)
+{
+ int err;
+
+ err = seg6_do_srh(skb);
+ if (unlikely(err)) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ skb_dst_drop(skb);
+ ip6_route_input(skb);
+
+ return dst_input(skb);
+}
+
+int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+{
+ struct dst_entry *orig_dst = skb_dst(skb);
+ struct dst_entry *dst = NULL;
+ struct seg6_lwt *slwt;
+ int err = -EINVAL;
+
+ err = seg6_do_srh(skb);
+ if (unlikely(err))
+ goto drop;
+
+ slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
+
+#ifdef CONFIG_DST_CACHE
+ dst = dst_cache_get(&slwt->cache);
+#endif
+
+ if (unlikely(!dst)) {
+ struct ipv6hdr *hdr = ipv6_hdr(skb);
+ struct flowi6 fl6;
+
+ fl6.daddr = hdr->daddr;
+ fl6.saddr = hdr->saddr;
+ fl6.flowlabel = ip6_flowinfo(hdr);
+ fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_proto = hdr->nexthdr;
+
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (dst->error) {
+ err = dst->error;
+ dst_release(dst);
+ goto drop;
+ }
+
+#ifdef CONFIG_DST_CACHE
+ dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
+#endif
+ }
+
+ skb_dst_drop(skb);
+ skb_dst_set(skb, dst);
+
+ return dst_output(net, sk, skb);
+drop:
+ kfree_skb(skb);
+ return err;
+}
+
+static int seg6_build_state(struct net_device *dev, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts)
+{
+ struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1];
+ struct seg6_iptunnel_encap *tuninfo;
+ struct lwtunnel_state *newts;
+ int tuninfo_len, min_size;
+ struct seg6_lwt *slwt;
+ int err;
+
+ err = nla_parse_nested(tb, SEG6_IPTUNNEL_MAX, nla,
+ seg6_iptunnel_policy);
+
+ if (err < 0)
+ return err;
+
+ if (!tb[SEG6_IPTUNNEL_SRH])
+ return -EINVAL;
+
+ tuninfo = nla_data(tb[SEG6_IPTUNNEL_SRH]);
+ tuninfo_len = nla_len(tb[SEG6_IPTUNNEL_SRH]);
+
+ /* tuninfo must contain at least the iptunnel encap structure,
+ * the SRH and one segment
+ */
+ min_size = sizeof(*tuninfo) + sizeof(struct ipv6_sr_hdr) +
+ sizeof(struct in6_addr);
+ if (tuninfo_len < min_size)
+ return -EINVAL;
+
+ switch (tuninfo->mode) {
+#ifdef CONFIG_IPV6_SEG6_INLINE
+ case SEG6_IPTUN_MODE_INLINE:
+ break;
+#endif
+ case SEG6_IPTUN_MODE_ENCAP:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* verify that SRH is consistent */
+ if (!seg6_validate_srh(tuninfo->srh, tuninfo_len - sizeof(*tuninfo)))
+ return -EINVAL;
+
+ newts = lwtunnel_state_alloc(tuninfo_len + sizeof(*slwt));
+ if (!newts)
+ return -ENOMEM;
+
+ slwt = seg6_lwt_lwtunnel(newts);
+
+#ifdef CONFIG_DST_CACHE
+ err = dst_cache_init(&slwt->cache, GFP_KERNEL);
+ if (err) {
+ kfree(newts);
+ return err;
+ }
+#endif
+
+ memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
+
+ newts->type = LWTUNNEL_ENCAP_SEG6;
+ newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
+ LWTUNNEL_STATE_INPUT_REDIRECT;
+ newts->headroom = seg6_lwt_headroom(tuninfo);
+
+ *ts = newts;
+
+ return 0;
+}
+
+#ifdef CONFIG_DST_CACHE
+static void seg6_destroy_state(struct lwtunnel_state *lwt)
+{
+ dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache);
+}
+#endif
+
+static int seg6_fill_encap_info(struct sk_buff *skb,
+ struct lwtunnel_state *lwtstate)
+{
+ struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
+
+ if (nla_put_srh(skb, SEG6_IPTUNNEL_SRH, tuninfo))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int seg6_encap_nlsize(struct lwtunnel_state *lwtstate)
+{
+ struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
+
+ return nla_total_size(SEG6_IPTUN_ENCAP_SIZE(tuninfo));
+}
+
+static int seg6_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
+{
+ struct seg6_iptunnel_encap *a_hdr = seg6_encap_lwtunnel(a);
+ struct seg6_iptunnel_encap *b_hdr = seg6_encap_lwtunnel(b);
+ int len = SEG6_IPTUN_ENCAP_SIZE(a_hdr);
+
+ if (len != SEG6_IPTUN_ENCAP_SIZE(b_hdr))
+ return 1;
+
+ return memcmp(a_hdr, b_hdr, len);
+}
+
+static const struct lwtunnel_encap_ops seg6_iptun_ops = {
+ .build_state = seg6_build_state,
+#ifdef CONFIG_DST_CACHE
+ .destroy_state = seg6_destroy_state,
+#endif
+ .output = seg6_output,
+ .input = seg6_input,
+ .fill_encap = seg6_fill_encap_info,
+ .get_encap_size = seg6_encap_nlsize,
+ .cmp_encap = seg6_encap_cmp,
+};
+
+int __init seg6_iptunnel_init(void)
+{
+ return lwtunnel_encap_add_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6);
+}
+
+void seg6_iptunnel_exit(void)
+{
+ lwtunnel_encap_del_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6);
+}
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b1cdf8009d29..0355231162b8 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -76,7 +76,7 @@ static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
__be32 *v4dst);
static struct rtnl_link_ops sit_link_ops __read_mostly;
-static int sit_net_id __read_mostly;
+static unsigned int sit_net_id __read_mostly;
struct sit_net {
struct ip_tunnel __rcu *tunnels_r_l[IP6_SIT_HASH_SIZE];
struct ip_tunnel __rcu *tunnels_r[IP6_SIT_HASH_SIZE];
@@ -1318,23 +1318,11 @@ done:
return err;
}
-static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct ip_tunnel *tunnel = netdev_priv(dev);
- int t_hlen = tunnel->hlen + sizeof(struct iphdr);
-
- if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - t_hlen)
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops ipip6_netdev_ops = {
.ndo_init = ipip6_tunnel_init,
.ndo_uninit = ipip6_tunnel_uninit,
.ndo_start_xmit = sit_tunnel_xmit,
.ndo_do_ioctl = ipip6_tunnel_ioctl,
- .ndo_change_mtu = ipip6_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
};
@@ -1365,6 +1353,8 @@ static void ipip6_tunnel_setup(struct net_device *dev)
dev->type = ARPHRD_SIT;
dev->hard_header_len = LL_MAX_HEADER + t_hlen;
dev->mtu = ETH_DATA_LEN - t_hlen;
+ dev->min_mtu = IPV6_MIN_MTU;
+ dev->max_mtu = 0xFFF8 - t_hlen;
dev->flags = IFF_NOARP;
netif_keep_dst(dev);
dev->addr_len = 4;
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 59c483937aec..a4d49760bf43 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -209,6 +209,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
treq->snt_synack.v64 = 0;
treq->rcv_isn = ntohl(th->seq) - 1;
treq->snt_isn = cookie;
+ treq->ts_off = 0;
/*
* We need to lookup the dst_entry to get the correct window size.
@@ -227,6 +228,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
fl6.flowi6_mark = ireq->ir_mark;
fl6.fl6_dport = ireq->ir_rmt_port;
fl6.fl6_sport = inet_sk(sk)->inet_sport;
+ fl6.flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(&fl6));
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b9f1fee9a886..73bc8fc68acd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -101,12 +101,12 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
}
}
-static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
+static u32 tcp_v6_init_sequence(const struct sk_buff *skb, u32 *tsoff)
{
return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
ipv6_hdr(skb)->saddr.s6_addr32,
tcp_hdr(skb)->dest,
- tcp_hdr(skb)->source);
+ tcp_hdr(skb)->source, tsoff);
}
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
@@ -233,6 +233,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_dport = usin->sin6_port;
fl6.fl6_sport = inet->inet_sport;
+ fl6.flowi6_uid = sk->sk_uid;
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
final_p = fl6_update_dst(&fl6, opt, &final);
@@ -282,7 +283,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
sk->sk_v6_daddr.s6_addr32,
inet->inet_sport,
- inet->inet_dport);
+ inet->inet_dport,
+ &tp->tsoffset);
err = tcp_connect(sk);
if (err)
@@ -397,7 +399,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (!sock_owned_by_user(sk))
tcp_v6_mtu_reduced(sk);
else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
- &tp->tsq_flags))
+ &sk->sk_tsq_flags))
sock_hold(sk);
goto out;
}
@@ -828,6 +830,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
fl6.fl6_dport = t1->dest;
fl6.fl6_sport = t1->source;
+ fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
/* Pass a socket to ip6_dst_lookup either it is for RST
@@ -954,7 +957,8 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
tcp_rsk(req)->rcv_nxt,
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
- tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
+ tcp_time_stamp + tcp_rsk(req)->ts_off,
+ req->ts_recent, sk->sk_bound_dev_if,
tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
0, 0);
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e4a8000d59ad..649efc26a252 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -302,7 +302,8 @@ EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
* Does increment socket refcount.
*/
#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \
- IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY)
+ IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) || \
+ IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport, int dif)
{
@@ -334,7 +335,6 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int is_udplite = IS_UDPLITE(sk);
bool checksum_valid = false;
int is_udp4;
- bool slow;
if (flags & MSG_ERRQUEUE)
return ipv6_recv_error(sk, msg, len, addr_len);
@@ -344,8 +344,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
try_again:
peeking = off = sk_peek_offset(sk, flags);
- skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
- &peeked, &off, &err);
+ skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb)
return err;
@@ -364,7 +363,8 @@ try_again:
* coverage checksum (UDP-Lite), do it before the copy.
*/
- if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) {
+ if (copied < ulen || peeking ||
+ (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
checksum_valid = !udp_lib_checksum_complete(skb);
if (!checksum_valid)
goto csum_copy_err;
@@ -378,7 +378,6 @@ try_again:
goto csum_copy_err;
}
if (unlikely(err)) {
- trace_kfree_skb(skb, udpv6_recvmsg);
if (!peeked) {
atomic_inc(&sk->sk_drops);
if (is_udp4)
@@ -388,7 +387,7 @@ try_again:
UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
is_udplite);
}
- skb_free_datagram_locked(sk, skb);
+ kfree_skb(skb);
return err;
}
if (!peeked) {
@@ -427,7 +426,7 @@ try_again:
if (is_udp4) {
if (inet->cmsg_flags)
- ip_cmsg_recv_offset(msg, skb,
+ ip_cmsg_recv_offset(msg, sk, skb,
sizeof(struct udphdr), off);
} else {
if (np->rxopt.all)
@@ -438,12 +437,11 @@ try_again:
if (flags & MSG_TRUNC)
err = ulen;
- __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+ skb_consume_udp(sk, skb, peeking ? -err : err);
return err;
csum_copy_err:
- slow = lock_sock_fast(sk);
- if (!skb_kill_datagram(sk, skb, flags)) {
+ if (!__sk_queue_drop_skb(sk, skb, flags)) {
if (is_udp4) {
UDP_INC_STATS(sock_net(sk),
UDP_MIB_CSUMERRORS, is_udplite);
@@ -456,7 +454,7 @@ csum_copy_err:
UDP_MIB_INERRORS, is_udplite);
}
}
- unlock_sock_fast(sk, slow);
+ kfree_skb(skb);
/* starting over for a new packet, but check if we need to yield */
cond_resched();
@@ -522,9 +520,11 @@ int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
sock_rps_save_rxhash(sk, skb);
sk_mark_napi_id(sk, skb);
sk_incoming_cpu_update(sk);
+ } else {
+ sk_mark_napi_id_once(sk, skb);
}
- rc = __sock_queue_rcv_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
@@ -536,6 +536,7 @@ int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
return -1;
}
+
return 0;
}
@@ -557,7 +558,6 @@ EXPORT_SYMBOL(udpv6_encap_enable);
int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
- int rc;
int is_udplite = IS_UDPLITE(sk);
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
@@ -623,25 +623,10 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
goto drop;
udp_csum_pull_header(skb);
- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
- __UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_RCVBUFERRORS, is_udplite);
- goto drop;
- }
skb_dst_drop(skb);
- bh_lock_sock(sk);
- rc = 0;
- if (!sock_owned_by_user(sk))
- rc = __udpv6_queue_rcv_skb(sk, skb);
- else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
- bh_unlock_sock(sk);
- goto drop;
- }
- bh_unlock_sock(sk);
-
- return rc;
+ return __udpv6_queue_rcv_skb(sk, skb);
csum_error:
__UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@ -1156,6 +1141,7 @@ do_udp_sendmsg:
fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
sockc.tsflags = sk->sk_tsflags;
if (msg->msg_controllen) {
@@ -1434,12 +1420,12 @@ struct proto udpv6_prot = {
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .init = udp_init_sock,
.destroy = udpv6_destroy_sock,
.setsockopt = udpv6_setsockopt,
.getsockopt = udpv6_getsockopt,
.sendmsg = udpv6_sendmsg,
.recvmsg = udpv6_recvmsg,
- .backlog_rcv = __udpv6_queue_rcv_skb,
.release_cb = ip6_datagram_release_cb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index 2f5101a12283..2784cc363f2b 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -45,10 +45,11 @@ struct proto udplitev6_prot = {
.getsockopt = udpv6_getsockopt,
.sendmsg = udpv6_sendmsg,
.recvmsg = udpv6_recvmsg,
- .backlog_rcv = __udpv6_queue_rcv_skb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
.get_port = udp_v6_get_port,
+ .memory_allocated = &udp_memory_allocated,
+ .sysctl_mem = sysctl_udp_mem,
.obj_size = sizeof(struct udp6_sock),
.h.udp_table = &udplite_table,
#ifdef CONFIG_COMPAT
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index e1c0bbe7996c..d7b731a78d09 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -44,7 +44,7 @@ struct xfrm6_tunnel_net {
u32 spi;
};
-static int xfrm6_tunnel_net_id __read_mostly;
+static unsigned int xfrm6_tunnel_net_id __read_mostly;
static inline struct xfrm6_tunnel_net *xfrm6_tunnel_pernet(struct net *net)
{
return net_generic(net, xfrm6_tunnel_net_id);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index d8b7267280c3..74d09f91709e 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -51,7 +51,6 @@ static const struct net_device_ops irlan_eth_netdev_ops = {
.ndo_stop = irlan_eth_close,
.ndo_start_xmit = irlan_eth_xmit,
.ndo_set_rx_mode = irlan_eth_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -67,7 +66,8 @@ static void irlan_eth_setup(struct net_device *dev)
dev->netdev_ops = &irlan_eth_netdev_ops;
dev->destructor = free_netdev;
-
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
/*
* Lets do all queueing in IrTTP instead of this device driver.
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
index e15c40e86660..7fc340e574cf 100644
--- a/net/irda/irnetlink.c
+++ b/net/irda/irnetlink.c
@@ -24,13 +24,7 @@
-static struct genl_family irda_nl_family = {
- .id = GENL_ID_GENERATE,
- .name = IRDA_NL_NAME,
- .hdrsize = 0,
- .version = IRDA_NL_VERSION,
- .maxattr = IRDA_NL_CMD_MAX,
-};
+static struct genl_family irda_nl_family;
static struct net_device * ifname_to_netdev(struct net *net, struct genl_info *info)
{
@@ -147,9 +141,19 @@ static const struct genl_ops irda_nl_ops[] = {
};
-int irda_nl_register(void)
+static struct genl_family irda_nl_family __ro_after_init = {
+ .name = IRDA_NL_NAME,
+ .hdrsize = 0,
+ .version = IRDA_NL_VERSION,
+ .maxattr = IRDA_NL_CMD_MAX,
+ .module = THIS_MODULE,
+ .ops = irda_nl_ops,
+ .n_ops = ARRAY_SIZE(irda_nl_ops),
+};
+
+int __init irda_nl_register(void)
{
- return genl_register_family_with_ops(&irda_nl_family, irda_nl_ops);
+ return genl_register_family(&irda_nl_family);
}
void irda_nl_unregister(void)
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 02b45a8e8b35..cfb9e5f4e28f 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -453,19 +453,27 @@ static void iucv_sever_path(struct sock *sk, int with_user_data)
}
}
-/* Send FIN through an IUCV socket for HIPER transport */
+/* Send controlling flags through an IUCV socket for HIPER transport */
static int iucv_send_ctrl(struct sock *sk, u8 flags)
{
int err = 0;
int blen;
struct sk_buff *skb;
+ u8 shutdown = 0;
blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+ if (sk->sk_shutdown & SEND_SHUTDOWN) {
+ /* controlling flags should be sent anyway */
+ shutdown = sk->sk_shutdown;
+ sk->sk_shutdown &= RCV_SHUTDOWN;
+ }
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (skb) {
skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb, flags);
}
+ if (shutdown)
+ sk->sk_shutdown = shutdown;
return err;
}
@@ -1315,8 +1323,13 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
}
IUCV_SKB_CB(skb)->offset = 0;
- if (sock_queue_rcv_skb(sk, skb))
- skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
+ if (sk_filter(sk, skb)) {
+ atomic_inc(&sk->sk_drops); /* skb rejected by filter */
+ kfree_skb(skb);
+ return;
+ }
+ if (__sock_queue_rcv_skb(sk, skb)) /* handle rcv queue full */
+ skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
}
/* iucv_process_message_q() - Process outstanding IUCV messages
@@ -1430,13 +1443,13 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
rskb = skb_dequeue(&iucv->backlog_skb_q);
while (rskb) {
IUCV_SKB_CB(rskb)->offset = 0;
- if (sock_queue_rcv_skb(sk, rskb)) {
+ if (__sock_queue_rcv_skb(sk, rskb)) {
+ /* handle rcv queue full */
skb_queue_head(&iucv->backlog_skb_q,
rskb);
break;
- } else {
- rskb = skb_dequeue(&iucv->backlog_skb_q);
}
+ rskb = skb_dequeue(&iucv->backlog_skb_q);
}
if (skb_queue_empty(&iucv->backlog_skb_q)) {
if (!list_empty(&iucv->message_q.list))
@@ -2116,12 +2129,17 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb)
skb_reset_transport_header(skb);
skb_reset_network_header(skb);
IUCV_SKB_CB(skb)->offset = 0;
+ if (sk_filter(sk, skb)) {
+ atomic_inc(&sk->sk_drops); /* skb rejected by filter */
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
+ }
+
spin_lock(&iucv->message_q.lock);
if (skb_queue_empty(&iucv->backlog_skb_q)) {
- if (sock_queue_rcv_skb(sk, skb)) {
+ if (__sock_queue_rcv_skb(sk, skb))
/* handle rcv queue full */
skb_queue_tail(&iucv->backlog_skb_q, skb);
- }
} else
skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
spin_unlock(&iucv->message_q.lock);
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 88a2a3ba4212..8f7ef167c45a 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -639,7 +639,7 @@ static void iucv_disable(void)
put_online_cpus();
}
-static void free_iucv_data(int cpu)
+static int iucv_cpu_dead(unsigned int cpu)
{
kfree(iucv_param_irq[cpu]);
iucv_param_irq[cpu] = NULL;
@@ -647,9 +647,10 @@ static void free_iucv_data(int cpu)
iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]);
iucv_irq_data[cpu] = NULL;
+ return 0;
}
-static int alloc_iucv_data(int cpu)
+static int iucv_cpu_prepare(unsigned int cpu)
{
/* Note: GFP_DMA used to get memory below 2G */
iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
@@ -671,58 +672,38 @@ static int alloc_iucv_data(int cpu)
return 0;
out_free:
- free_iucv_data(cpu);
+ iucv_cpu_dead(cpu);
return -ENOMEM;
}
-static int iucv_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static int iucv_cpu_online(unsigned int cpu)
{
- cpumask_t cpumask;
- long cpu = (long) hcpu;
-
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- if (alloc_iucv_data(cpu))
- return notifier_from_errno(-ENOMEM);
- break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- free_iucv_data(cpu);
- break;
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- if (!iucv_path_table)
- break;
- smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- if (!iucv_path_table)
- break;
- cpumask_copy(&cpumask, &iucv_buffer_cpumask);
- cpumask_clear_cpu(cpu, &cpumask);
- if (cpumask_empty(&cpumask))
- /* Can't offline last IUCV enabled cpu. */
- return notifier_from_errno(-EINVAL);
- smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1);
- if (cpumask_empty(&iucv_irq_cpumask))
- smp_call_function_single(
- cpumask_first(&iucv_buffer_cpumask),
- iucv_allow_cpu, NULL, 1);
- break;
- }
- return NOTIFY_OK;
+ if (!iucv_path_table)
+ return 0;
+ iucv_declare_cpu(NULL);
+ return 0;
}
-static struct notifier_block __refdata iucv_cpu_notifier = {
- .notifier_call = iucv_cpu_notify,
-};
+static int iucv_cpu_down_prep(unsigned int cpu)
+{
+ cpumask_t cpumask;
+
+ if (!iucv_path_table)
+ return 0;
+
+ cpumask_copy(&cpumask, &iucv_buffer_cpumask);
+ cpumask_clear_cpu(cpu, &cpumask);
+ if (cpumask_empty(&cpumask))
+ /* Can't offline last IUCV enabled cpu. */
+ return -EINVAL;
+
+ iucv_retrieve_cpu(NULL);
+ if (!cpumask_empty(&iucv_irq_cpumask))
+ return 0;
+ smp_call_function_single(cpumask_first(&iucv_buffer_cpumask),
+ iucv_allow_cpu, NULL, 1);
+ return 0;
+}
/**
* iucv_sever_pathid
@@ -2027,6 +2008,7 @@ struct iucv_interface iucv_if = {
};
EXPORT_SYMBOL(iucv_if);
+static enum cpuhp_state iucv_online;
/**
* iucv_init
*
@@ -2035,7 +2017,6 @@ EXPORT_SYMBOL(iucv_if);
static int __init iucv_init(void)
{
int rc;
- int cpu;
if (!MACHINE_IS_VM) {
rc = -EPROTONOSUPPORT;
@@ -2054,23 +2035,19 @@ static int __init iucv_init(void)
goto out_int;
}
- cpu_notifier_register_begin();
-
- for_each_online_cpu(cpu) {
- if (alloc_iucv_data(cpu)) {
- rc = -ENOMEM;
- goto out_free;
- }
- }
- rc = __register_hotcpu_notifier(&iucv_cpu_notifier);
+ rc = cpuhp_setup_state(CPUHP_NET_IUCV_PREPARE, "net/iucv:prepare",
+ iucv_cpu_prepare, iucv_cpu_dead);
if (rc)
- goto out_free;
-
- cpu_notifier_register_done();
+ goto out_dev;
+ rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "net/iucv:online",
+ iucv_cpu_online, iucv_cpu_down_prep);
+ if (rc < 0)
+ goto out_prep;
+ iucv_online = rc;
rc = register_reboot_notifier(&iucv_reboot_notifier);
if (rc)
- goto out_cpu;
+ goto out_remove_hp;
ASCEBC(iucv_error_no_listener, 16);
ASCEBC(iucv_error_no_memory, 16);
ASCEBC(iucv_error_pathid, 16);
@@ -2084,15 +2061,11 @@ static int __init iucv_init(void)
out_reboot:
unregister_reboot_notifier(&iucv_reboot_notifier);
-out_cpu:
- cpu_notifier_register_begin();
- __unregister_hotcpu_notifier(&iucv_cpu_notifier);
-out_free:
- for_each_possible_cpu(cpu)
- free_iucv_data(cpu);
-
- cpu_notifier_register_done();
-
+out_remove_hp:
+ cpuhp_remove_state(iucv_online);
+out_prep:
+ cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
+out_dev:
root_device_unregister(iucv_root);
out_int:
unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
@@ -2110,7 +2083,6 @@ out:
static void __exit iucv_exit(void)
{
struct iucv_irq_list *p, *n;
- int cpu;
spin_lock_irq(&iucv_queue_lock);
list_for_each_entry_safe(p, n, &iucv_task_queue, list)
@@ -2119,11 +2091,9 @@ static void __exit iucv_exit(void)
kfree(p);
spin_unlock_irq(&iucv_queue_lock);
unregister_reboot_notifier(&iucv_reboot_notifier);
- cpu_notifier_register_begin();
- __unregister_hotcpu_notifier(&iucv_cpu_notifier);
- for_each_possible_cpu(cpu)
- free_iucv_data(cpu);
- cpu_notifier_register_done();
+
+ cpuhp_remove_state_nocalls(iucv_online);
+ cpuhp_remove_state(CPUHP_NET_IUCV_PREPARE);
root_device_unregister(iucv_root);
bus_unregister(&iucv_bus);
unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index f9c9ecb0cdd3..c6252ed42c1d 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -36,7 +36,7 @@
#define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
#define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
-static int pfkey_net_id __read_mostly;
+static unsigned int pfkey_net_id __read_mostly;
struct netns_pfkey {
/* List of all pfkey sockets. */
struct hlist_head table;
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index a2ed3bda4ddc..85948c69b236 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -715,7 +715,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
l2tp_info(session, L2TP_MSG_SEQ,
"%s: requested to enable seq numbers by LNS\n",
session->name);
- session->send_seq = -1;
+ session->send_seq = 1;
l2tp_session_set_header_len(session, tunnel->version);
}
} else {
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 2599af6378e4..8f560f7140a0 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -23,16 +23,6 @@
#define L2TP_HASH_BITS_2 8
#define L2TP_HASH_SIZE_2 (1 << L2TP_HASH_BITS_2)
-/* Debug message categories for the DEBUG socket option */
-enum {
- L2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if
- * compiled in) */
- L2TP_MSG_CONTROL = (1 << 1), /* userspace - kernel
- * interface */
- L2TP_MSG_SEQ = (1 << 2), /* sequence numbers */
- L2TP_MSG_DATA = (1 << 3), /* data packets */
-};
-
struct sk_buff;
struct l2tp_stats {
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 965f7e344cef..e2c6ae024565 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -259,6 +259,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
session->mtu = dev->mtu - session->hdr_len;
dev->mtu = session->mtu;
dev->needed_headroom += session->hdr_len;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
priv = netdev_priv(dev);
priv->dev = dev;
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index aa821cb639e5..f092ac441fdd 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -525,6 +525,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
ipc6.hlimit = -1;
ipc6.tclass = -1;
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index bf3117771822..3620fba31786 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -31,14 +31,7 @@
#include "l2tp_core.h"
-static struct genl_family l2tp_nl_family = {
- .id = GENL_ID_GENERATE,
- .name = L2TP_GENL_NAME,
- .version = L2TP_GENL_VERSION,
- .hdrsize = 0,
- .maxattr = L2TP_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family l2tp_nl_family;
static const struct genl_multicast_group l2tp_multicast_group[] = {
{
@@ -227,14 +220,14 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
if (info->attrs[L2TP_ATTR_UDP_DPORT])
cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
- if (info->attrs[L2TP_ATTR_UDP_CSUM])
- cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
+ cfg.use_udp_checksums = nla_get_flag(
+ info->attrs[L2TP_ATTR_UDP_CSUM]);
#if IS_ENABLED(CONFIG_IPV6)
- if (info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX])
- cfg.udp6_zero_tx_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
- if (info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX])
- cfg.udp6_zero_rx_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
+ cfg.udp6_zero_tx_checksums = nla_get_flag(
+ info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
+ cfg.udp6_zero_rx_checksums = nla_get_flag(
+ info->attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
#endif
}
@@ -386,9 +379,24 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
switch (tunnel->encap) {
case L2TP_ENCAPTYPE_UDP:
+ switch (sk->sk_family) {
+ case AF_INET:
+ if (nla_put_u8(skb, L2TP_ATTR_UDP_CSUM, !sk->sk_no_check_tx))
+ goto nla_put_failure;
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ if (udp_get_no_check6_tx(sk) &&
+ nla_put_flag(skb, L2TP_ATTR_UDP_ZERO_CSUM6_TX))
+ goto nla_put_failure;
+ if (udp_get_no_check6_rx(sk) &&
+ nla_put_flag(skb, L2TP_ATTR_UDP_ZERO_CSUM6_RX))
+ goto nla_put_failure;
+ break;
+#endif
+ }
if (nla_put_u16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)) ||
- nla_put_u16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)) ||
- nla_put_u8(skb, L2TP_ATTR_UDP_CSUM, !sk->sk_no_check_tx))
+ nla_put_u16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)))
goto nla_put_failure;
/* NOBREAK */
case L2TP_ENCAPTYPE_IP:
@@ -977,6 +985,19 @@ static const struct genl_ops l2tp_nl_ops[] = {
},
};
+static struct genl_family l2tp_nl_family __ro_after_init = {
+ .name = L2TP_GENL_NAME,
+ .version = L2TP_GENL_VERSION,
+ .hdrsize = 0,
+ .maxattr = L2TP_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = l2tp_nl_ops,
+ .n_ops = ARRAY_SIZE(l2tp_nl_ops),
+ .mcgrps = l2tp_multicast_group,
+ .n_mcgrps = ARRAY_SIZE(l2tp_multicast_group),
+};
+
int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops)
{
int ret;
@@ -1010,12 +1031,10 @@ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type)
}
EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
-static int l2tp_nl_init(void)
+static int __init l2tp_nl_init(void)
{
pr_info("L2TP netlink interface\n");
- return genl_register_family_with_ops_groups(&l2tp_nl_family,
- l2tp_nl_ops,
- l2tp_multicast_group);
+ return genl_register_family(&l2tp_nl_family);
}
static void l2tp_nl_cleanup(void)
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 41d47bfda15c..36cc56fd0418 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -231,14 +231,14 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
if (sk->sk_state & PPPOX_BOUND) {
struct pppox_sock *po;
- l2tp_dbg(session, PPPOL2TP_MSG_DATA,
+ l2tp_dbg(session, L2TP_MSG_DATA,
"%s: recv %d byte data frame, passing to ppp\n",
session->name, data_len);
po = pppox_sk(sk);
ppp_input(&po->chan, skb);
} else {
- l2tp_dbg(session, PPPOL2TP_MSG_DATA,
+ l2tp_dbg(session, L2TP_MSG_DATA,
"%s: recv %d byte data frame, passing to L2TP socket\n",
session->name, data_len);
@@ -251,7 +251,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
return;
no_sock:
- l2tp_info(session, PPPOL2TP_MSG_DATA, "%s: no socket\n", session->name);
+ l2tp_info(session, L2TP_MSG_DATA, "%s: no socket\n", session->name);
kfree_skb(skb);
}
@@ -773,7 +773,7 @@ out_no_ppp:
/* This is how we get the session context from the socket. */
sk->sk_user_data = session;
sk->sk_state = PPPOX_CONNECTED;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: created\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: created\n",
session->name);
end:
@@ -827,7 +827,7 @@ static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_i
ps = l2tp_session_priv(session);
ps->tunnel_sock = tunnel->sock;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: created\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: created\n",
session->name);
error = 0;
@@ -989,7 +989,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
struct l2tp_tunnel *tunnel = session->tunnel;
struct pppol2tp_ioc_stats stats;
- l2tp_dbg(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_dbg(session, L2TP_MSG_CONTROL,
"%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n",
session->name, cmd, arg);
@@ -1009,7 +1009,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq)))
break;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: get mtu=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: get mtu=%d\n",
session->name, session->mtu);
err = 0;
break;
@@ -1025,7 +1025,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
session->mtu = ifr.ifr_mtu;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: set mtu=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: set mtu=%d\n",
session->name, session->mtu);
err = 0;
break;
@@ -1039,7 +1039,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
if (put_user(session->mru, (int __user *) arg))
break;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: get mru=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: get mru=%d\n",
session->name, session->mru);
err = 0;
break;
@@ -1054,7 +1054,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
break;
session->mru = val;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: set mru=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: set mru=%d\n",
session->name, session->mru);
err = 0;
break;
@@ -1064,7 +1064,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
if (put_user(ps->flags, (int __user *) arg))
break;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: get flags=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: get flags=%d\n",
session->name, ps->flags);
err = 0;
break;
@@ -1074,7 +1074,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
if (get_user(val, (int __user *) arg))
break;
ps->flags = val;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: set flags=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: set flags=%d\n",
session->name, ps->flags);
err = 0;
break;
@@ -1091,7 +1091,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
if (copy_to_user((void __user *) arg, &stats,
sizeof(stats)))
break;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: get L2TP stats\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: get L2TP stats\n",
session->name);
err = 0;
break;
@@ -1119,7 +1119,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel,
struct sock *sk;
struct pppol2tp_ioc_stats stats;
- l2tp_dbg(tunnel, PPPOL2TP_MSG_CONTROL,
+ l2tp_dbg(tunnel, L2TP_MSG_CONTROL,
"%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n",
tunnel->name, cmd, arg);
@@ -1155,7 +1155,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel,
err = -EFAULT;
break;
}
- l2tp_info(tunnel, PPPOL2TP_MSG_CONTROL, "%s: get L2TP stats\n",
+ l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: get L2TP stats\n",
tunnel->name);
err = 0;
break;
@@ -1245,7 +1245,7 @@ static int pppol2tp_tunnel_setsockopt(struct sock *sk,
switch (optname) {
case PPPOL2TP_SO_DEBUG:
tunnel->debug = val;
- l2tp_info(tunnel, PPPOL2TP_MSG_CONTROL, "%s: set debug=%x\n",
+ l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: set debug=%x\n",
tunnel->name, tunnel->debug);
break;
@@ -1272,8 +1272,8 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
err = -EINVAL;
break;
}
- session->recv_seq = val ? -1 : 0;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ session->recv_seq = !!val;
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: set recv_seq=%d\n",
session->name, session->recv_seq);
break;
@@ -1283,7 +1283,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
err = -EINVAL;
break;
}
- session->send_seq = val ? -1 : 0;
+ session->send_seq = !!val;
{
struct sock *ssk = ps->sock;
struct pppox_sock *po = pppox_sk(ssk);
@@ -1291,7 +1291,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
}
l2tp_session_set_header_len(session, session->tunnel->version);
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: set send_seq=%d\n",
session->name, session->send_seq);
break;
@@ -1301,21 +1301,21 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
err = -EINVAL;
break;
}
- session->lns_mode = val ? -1 : 0;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ session->lns_mode = !!val;
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: set lns_mode=%d\n",
session->name, session->lns_mode);
break;
case PPPOL2TP_SO_DEBUG:
session->debug = val;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: set debug=%x\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: set debug=%x\n",
session->name, session->debug);
break;
case PPPOL2TP_SO_REORDERTO:
session->reorder_timeout = msecs_to_jiffies(val);
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: set reorder_timeout=%d\n",
session->name, session->reorder_timeout);
break;
@@ -1396,7 +1396,7 @@ static int pppol2tp_tunnel_getsockopt(struct sock *sk,
switch (optname) {
case PPPOL2TP_SO_DEBUG:
*val = tunnel->debug;
- l2tp_info(tunnel, PPPOL2TP_MSG_CONTROL, "%s: get debug=%x\n",
+ l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: get debug=%x\n",
tunnel->name, tunnel->debug);
break;
@@ -1419,31 +1419,31 @@ static int pppol2tp_session_getsockopt(struct sock *sk,
switch (optname) {
case PPPOL2TP_SO_RECVSEQ:
*val = session->recv_seq;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: get recv_seq=%d\n", session->name, *val);
break;
case PPPOL2TP_SO_SENDSEQ:
*val = session->send_seq;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: get send_seq=%d\n", session->name, *val);
break;
case PPPOL2TP_SO_LNSMODE:
*val = session->lns_mode;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: get lns_mode=%d\n", session->name, *val);
break;
case PPPOL2TP_SO_DEBUG:
*val = session->debug;
- l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: get debug=%d\n",
+ l2tp_info(session, L2TP_MSG_CONTROL, "%s: get debug=%d\n",
session->name, *val);
break;
case PPPOL2TP_SO_REORDERTO:
*val = (int) jiffies_to_msecs(session->reorder_timeout);
- l2tp_info(session, PPPOL2TP_MSG_CONTROL,
+ l2tp_info(session, L2TP_MSG_CONTROL,
"%s: get reorder_timeout=%d\n", session->name, *val);
break;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index db916cf51ffe..5e9296382420 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -532,12 +532,12 @@ out:
static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
{
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
int rc = 0;
+ add_wait_queue(sk_sleep(sk), &wait);
while (1) {
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))
+ if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
break;
rc = -ERESTARTSYS;
if (signal_pending(current))
@@ -547,39 +547,39 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
break;
rc = 0;
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}
static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
{
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+ add_wait_queue(sk_sleep(sk), &wait);
while (1) {
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))
+ if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
break;
if (signal_pending(current) || !timeout)
break;
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return timeout;
}
static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
{
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct llc_sock *llc = llc_sk(sk);
int rc;
+ add_wait_queue(sk_sleep(sk), &wait);
while (1) {
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
rc = 0;
if (sk_wait_event(sk, &timeout,
(sk->sk_shutdown & RCV_SHUTDOWN) ||
(!llc_data_accept_state(llc->state) &&
!llc->remote_busy_flag &&
- !llc->p_flag)))
+ !llc->p_flag), &wait))
break;
rc = -ERESTARTSYS;
if (signal_pending(current))
@@ -588,7 +588,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
if (!timeout)
break;
}
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index f9137a8341f4..0b202b343fd4 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -19,6 +19,7 @@ mac80211-y := \
aes_gcm.o \
aes_cmac.o \
aes_gmac.o \
+ fils_aead.o \
cfg.o \
ethtool.o \
rx.o \
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index bdf0790d89cc..d0bd5fff5f0a 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -23,7 +23,7 @@
#define AAD_LEN 20
-static void gf_mulx(u8 *pad)
+void gf_mulx(u8 *pad)
{
int i, carry;
@@ -35,9 +35,9 @@ static void gf_mulx(u8 *pad)
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
}
-static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac,
- size_t mac_len)
+void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac,
+ size_t mac_len)
{
u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
const u8 *pos, *end;
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
index 3702041f44fd..c827e1d5de8b 100644
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -11,6 +11,10 @@
#include <linux/crypto.h>
+void gf_mulx(u8 *pad);
+void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac,
+ size_t mac_len);
struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
size_t key_len);
void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f6749dced021..3b5fd4188f2a 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -315,11 +315,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
mutex_lock(&sta->ampdu_mlme.mtx);
if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
- tid_agg_rx = rcu_dereference_protected(
- sta->ampdu_mlme.tid_rx[tid],
- lockdep_is_held(&sta->ampdu_mlme.mtx));
-
- if (tid_agg_rx->dialog_token == dialog_token) {
+ if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
ht_dbg_ratelimited(sta->sdata,
"updated AddBA Req from %pM on tid %u\n",
sta->sta.addr, tid);
@@ -396,7 +392,6 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
}
/* update data */
- tid_agg_rx->dialog_token = dialog_token;
tid_agg_rx->ssn = start_seq_num;
tid_agg_rx->head_seq_num = start_seq_num;
tid_agg_rx->buf_size = buf_size;
@@ -418,6 +413,7 @@ end:
if (status == WLAN_STATUS_SUCCESS) {
__set_bit(tid, sta->ampdu_mlme.agg_session_valid);
__clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
+ sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
}
mutex_unlock(&sta->ampdu_mlme.mtx);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fd6541f3ade3..e91e503bf992 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -357,10 +357,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
mutex_lock(&local->sta_mtx);
if (mac_addr) {
- if (ieee80211_vif_is_mesh(&sdata->vif))
- sta = sta_info_get(sdata, mac_addr);
- else
- sta = sta_info_get_bss(sdata, mac_addr);
+ sta = sta_info_get_bss(sdata, mac_addr);
/*
* The ASSOC test makes sure the driver is ready to
* receive the key. When wpa_supplicant has roamed
@@ -867,6 +864,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
sdata->needed_rx_chains = sdata->local->rx_chains;
+ sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+
mutex_lock(&local->mtx);
err = ieee80211_vif_use_channel(sdata, &params->chandef,
IEEE80211_CHANCTX_SHARED);
@@ -897,7 +896,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
vlan->vif.type);
}
- sdata->vif.bss_conf.beacon_int = params->beacon_interval;
sdata->vif.bss_conf.dtim_period = params->dtim_period;
sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
@@ -1523,9 +1521,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
goto out_err;
if (params->vlan && params->vlan != sta->sdata->dev) {
- bool prev_4addr = false;
- bool new_4addr = false;
-
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (params->vlan->ieee80211_ptr->use_4addr) {
@@ -1535,26 +1530,21 @@ static int ieee80211_change_station(struct wiphy *wiphy,
}
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
- new_4addr = true;
__ieee80211_check_fast_rx_iface(vlansdata);
}
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- sta->sdata->u.vlan.sta) {
+ sta->sdata->u.vlan.sta)
RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
- prev_4addr = true;
- }
+
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ ieee80211_vif_dec_num_mcast(sta->sdata);
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
- if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
- prev_4addr != new_4addr) {
- if (new_4addr)
- atomic_dec(&sta->sdata->bss->num_mcast_sta);
- else
- atomic_inc(&sta->sdata->bss->num_mcast_sta);
- }
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ ieee80211_vif_inc_num_mcast(sta->sdata);
ieee80211_send_layer2_update(sta);
}
@@ -2480,13 +2470,6 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
smps_mode == IEEE80211_SMPS_AUTOMATIC)
return 0;
- /* If no associated stations, there's no need to do anything */
- if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
- sdata->smps_mode = smps_mode;
- ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
- return 0;
- }
-
ht_dbg(sdata,
"SMPS %d requested in AP mode, sending Action frame to %d stations\n",
smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index f56e2f487d09..e02ba42ca827 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -210,6 +210,7 @@ static const char *hw_flag_names[] = {
FLAG(TX_AMSDU),
FLAG(TX_FRAG_LIST),
FLAG(REPORTS_LOW_ACK),
+ FLAG(SUPPORTS_TX_FRAG),
#undef FLAG
};
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bcec1240f41d..1a05f85cb1f0 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw);
IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
+IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -684,6 +685,13 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
}
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+ /* add num_mcast_sta_vlan using name num_mcast_sta */
+ debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
+ sdata, &num_mcast_sta_vlan_ops);
+}
+
static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD_MODE(tsf, 0600);
@@ -787,6 +795,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
+ case NL80211_IFTYPE_AP_VLAN:
+ add_vlan_files(sdata);
+ break;
case NL80211_IFTYPE_WDS:
add_wds_files(sdata);
break;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index a2fcdb47a0e6..f6003b8c2c33 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -199,13 +199,18 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
"TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+ bool tid_rx_valid;
+
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
+ tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid);
p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
- p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx);
+ p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
+ tid_rx_valid);
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
- tid_rx ? tid_rx->dialog_token : 0);
+ tid_rx_valid ?
+ sta->ampdu_mlme.tid_rx_token[i] : 0);
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
tid_rx ? tid_rx->ssn : 0);
diff --git a/net/mac80211/fils_aead.c b/net/mac80211/fils_aead.c
new file mode 100644
index 000000000000..ecfdd97758a3
--- /dev/null
+++ b/net/mac80211/fils_aead.c
@@ -0,0 +1,342 @@
+/*
+ * FILS AEAD for (Re)Association Request/Response frames
+ * Copyright 2016, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/skcipher.h>
+
+#include "ieee80211_i.h"
+#include "aes_cmac.h"
+#include "fils_aead.h"
+
+static int aes_s2v(struct crypto_cipher *tfm,
+ size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
+{
+ u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+ size_t i;
+ const u8 *data[2];
+ size_t data_len[2], data_elems;
+
+ /* D = AES-CMAC(K, <zero>) */
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ data[0] = tmp;
+ data_len[0] = AES_BLOCK_SIZE;
+ aes_cmac_vector(tfm, 1, data, data_len, d, AES_BLOCK_SIZE);
+
+ for (i = 0; i < num_elem - 1; i++) {
+ /* D = dbl(D) xor AES_CMAC(K, Si) */
+ gf_mulx(d); /* dbl */
+ aes_cmac_vector(tfm, 1, &addr[i], &len[i], tmp,
+ AES_BLOCK_SIZE);
+ crypto_xor(d, tmp, AES_BLOCK_SIZE);
+ }
+
+ if (len[i] >= AES_BLOCK_SIZE) {
+ /* len(Sn) >= 128 */
+ size_t j;
+ const u8 *pos;
+
+ /* T = Sn xorend D */
+
+ /* Use a temporary buffer to perform xorend on Sn (addr[i]) to
+ * avoid modifying the const input argument.
+ */
+ data[0] = addr[i];
+ data_len[0] = len[i] - AES_BLOCK_SIZE;
+ pos = addr[i] + data_len[0];
+ for (j = 0; j < AES_BLOCK_SIZE; j++)
+ tmp[j] = pos[j] ^ d[j];
+ data[1] = tmp;
+ data_len[1] = AES_BLOCK_SIZE;
+ data_elems = 2;
+ } else {
+ /* len(Sn) < 128 */
+ /* T = dbl(D) xor pad(Sn) */
+ gf_mulx(d); /* dbl */
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ memcpy(tmp, addr[i], len[i]);
+ tmp[len[i]] = 0x80;
+ crypto_xor(d, tmp, AES_BLOCK_SIZE);
+ data[0] = d;
+ data_len[0] = sizeof(d);
+ data_elems = 1;
+ }
+ /* V = AES-CMAC(K, T) */
+ aes_cmac_vector(tfm, data_elems, data, data_len, v, AES_BLOCK_SIZE);
+
+ return 0;
+}
+
+/* Note: addr[] and len[] needs to have one extra slot at the end. */
+static int aes_siv_encrypt(const u8 *key, size_t key_len,
+ const u8 *plain, size_t plain_len,
+ size_t num_elem, const u8 *addr[],
+ size_t len[], u8 *out)
+{
+ u8 v[AES_BLOCK_SIZE];
+ struct crypto_cipher *tfm;
+ struct crypto_skcipher *tfm2;
+ struct skcipher_request *req;
+ int res;
+ struct scatterlist src[1], dst[1];
+ u8 *tmp;
+
+ key_len /= 2; /* S2V key || CTR key */
+
+ addr[num_elem] = plain;
+ len[num_elem] = plain_len;
+ num_elem++;
+
+ /* S2V */
+
+ tfm = crypto_alloc_cipher("aes", 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+ /* K1 for S2V */
+ res = crypto_cipher_setkey(tfm, key, key_len);
+ if (!res)
+ res = aes_s2v(tfm, num_elem, addr, len, v);
+ crypto_free_cipher(tfm);
+ if (res)
+ return res;
+
+ /* Use a temporary buffer of the plaintext to handle need for
+ * overwriting this during AES-CTR.
+ */
+ tmp = kmemdup(plain, plain_len, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* IV for CTR before encrypted data */
+ memcpy(out, v, AES_BLOCK_SIZE);
+
+ /* Synthetic IV to be used as the initial counter in CTR:
+ * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
+ */
+ v[8] &= 0x7f;
+ v[12] &= 0x7f;
+
+ /* CTR */
+
+ tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+ if (IS_ERR(tfm2)) {
+ kfree(tmp);
+ return PTR_ERR(tfm2);
+ }
+ /* K2 for CTR */
+ res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
+ if (res)
+ goto fail;
+
+ req = skcipher_request_alloc(tfm2, GFP_KERNEL);
+ if (!req) {
+ res = -ENOMEM;
+ goto fail;
+ }
+
+ sg_init_one(src, tmp, plain_len);
+ sg_init_one(dst, out + AES_BLOCK_SIZE, plain_len);
+ skcipher_request_set_crypt(req, src, dst, plain_len, v);
+ res = crypto_skcipher_encrypt(req);
+ skcipher_request_free(req);
+fail:
+ kfree(tmp);
+ crypto_free_skcipher(tfm2);
+ return res;
+}
+
+/* Note: addr[] and len[] needs to have one extra slot at the end. */
+static int aes_siv_decrypt(const u8 *key, size_t key_len,
+ const u8 *iv_crypt, size_t iv_c_len,
+ size_t num_elem, const u8 *addr[], size_t len[],
+ u8 *out)
+{
+ struct crypto_cipher *tfm;
+ struct crypto_skcipher *tfm2;
+ struct skcipher_request *req;
+ struct scatterlist src[1], dst[1];
+ size_t crypt_len;
+ int res;
+ u8 frame_iv[AES_BLOCK_SIZE], iv[AES_BLOCK_SIZE];
+ u8 check[AES_BLOCK_SIZE];
+
+ crypt_len = iv_c_len - AES_BLOCK_SIZE;
+ key_len /= 2; /* S2V key || CTR key */
+ addr[num_elem] = out;
+ len[num_elem] = crypt_len;
+ num_elem++;
+
+ memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
+ memcpy(frame_iv, iv_crypt, AES_BLOCK_SIZE);
+
+ /* Synthetic IV to be used as the initial counter in CTR:
+ * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
+ */
+ iv[8] &= 0x7f;
+ iv[12] &= 0x7f;
+
+ /* CTR */
+
+ tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+ if (IS_ERR(tfm2))
+ return PTR_ERR(tfm2);
+ /* K2 for CTR */
+ res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
+ if (res) {
+ crypto_free_skcipher(tfm2);
+ return res;
+ }
+
+ req = skcipher_request_alloc(tfm2, GFP_KERNEL);
+ if (!req) {
+ crypto_free_skcipher(tfm2);
+ return -ENOMEM;
+ }
+
+ sg_init_one(src, iv_crypt + AES_BLOCK_SIZE, crypt_len);
+ sg_init_one(dst, out, crypt_len);
+ skcipher_request_set_crypt(req, src, dst, crypt_len, iv);
+ res = crypto_skcipher_decrypt(req);
+ skcipher_request_free(req);
+ crypto_free_skcipher(tfm2);
+ if (res)
+ return res;
+
+ /* S2V */
+
+ tfm = crypto_alloc_cipher("aes", 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+ /* K1 for S2V */
+ res = crypto_cipher_setkey(tfm, key, key_len);
+ if (!res)
+ res = aes_s2v(tfm, num_elem, addr, len, check);
+ crypto_free_cipher(tfm);
+ if (res)
+ return res;
+ if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0)
+ return -EINVAL;
+ return 0;
+}
+
+int fils_encrypt_assoc_req(struct sk_buff *skb,
+ struct ieee80211_mgd_assoc_data *assoc_data)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 *capab, *ies, *encr;
+ const u8 *addr[5 + 1], *session;
+ size_t len[5 + 1];
+ size_t crypt_len;
+
+ if (ieee80211_is_reassoc_req(mgmt->frame_control)) {
+ capab = (u8 *)&mgmt->u.reassoc_req.capab_info;
+ ies = mgmt->u.reassoc_req.variable;
+ } else {
+ capab = (u8 *)&mgmt->u.assoc_req.capab_info;
+ ies = mgmt->u.assoc_req.variable;
+ }
+
+ session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
+ ies, skb->data + skb->len - ies);
+ if (!session || session[1] != 1 + 8)
+ return -EINVAL;
+ /* encrypt after FILS Session element */
+ encr = (u8 *)session + 2 + 1 + 8;
+
+ /* AES-SIV AAD vectors */
+
+ /* The STA's MAC address */
+ addr[0] = mgmt->sa;
+ len[0] = ETH_ALEN;
+ /* The AP's BSSID */
+ addr[1] = mgmt->da;
+ len[1] = ETH_ALEN;
+ /* The STA's nonce */
+ addr[2] = assoc_data->fils_nonces;
+ len[2] = FILS_NONCE_LEN;
+ /* The AP's nonce */
+ addr[3] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
+ len[3] = FILS_NONCE_LEN;
+ /* The (Re)Association Request frame from the Capability Information
+ * field to the FILS Session element (both inclusive).
+ */
+ addr[4] = capab;
+ len[4] = encr - capab;
+
+ crypt_len = skb->data + skb->len - encr;
+ skb_put(skb, AES_BLOCK_SIZE);
+ return aes_siv_encrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
+ encr, crypt_len, 1, addr, len, encr);
+}
+
+int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ u8 *frame, size_t *frame_len,
+ struct ieee80211_mgd_assoc_data *assoc_data)
+{
+ struct ieee80211_mgmt *mgmt = (void *)frame;
+ u8 *capab, *ies, *encr;
+ const u8 *addr[5 + 1], *session;
+ size_t len[5 + 1];
+ int res;
+ size_t crypt_len;
+
+ if (*frame_len < 24 + 6)
+ return -EINVAL;
+
+ capab = (u8 *)&mgmt->u.assoc_resp.capab_info;
+ ies = mgmt->u.assoc_resp.variable;
+ session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
+ ies, frame + *frame_len - ies);
+ if (!session || session[1] != 1 + 8) {
+ mlme_dbg(sdata,
+ "No (valid) FILS Session element in (Re)Association Response frame from %pM",
+ mgmt->sa);
+ return -EINVAL;
+ }
+ /* decrypt after FILS Session element */
+ encr = (u8 *)session + 2 + 1 + 8;
+
+ /* AES-SIV AAD vectors */
+
+ /* The AP's BSSID */
+ addr[0] = mgmt->sa;
+ len[0] = ETH_ALEN;
+ /* The STA's MAC address */
+ addr[1] = mgmt->da;
+ len[1] = ETH_ALEN;
+ /* The AP's nonce */
+ addr[2] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
+ len[2] = FILS_NONCE_LEN;
+ /* The STA's nonce */
+ addr[3] = assoc_data->fils_nonces;
+ len[3] = FILS_NONCE_LEN;
+ /* The (Re)Association Response frame from the Capability Information
+ * field to the FILS Session element (both inclusive).
+ */
+ addr[4] = capab;
+ len[4] = encr - capab;
+
+ crypt_len = frame + *frame_len - encr;
+ if (crypt_len < AES_BLOCK_SIZE) {
+ mlme_dbg(sdata,
+ "Not enough room for AES-SIV data after FILS Session element in (Re)Association Response frame from %pM",
+ mgmt->sa);
+ return -EINVAL;
+ }
+ res = aes_siv_decrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
+ encr, crypt_len, 5, addr, len, encr);
+ if (res != 0) {
+ mlme_dbg(sdata,
+ "AES-SIV decryption of (Re)Association Response frame from %pM failed",
+ mgmt->sa);
+ return res;
+ }
+ *frame_len -= AES_BLOCK_SIZE;
+ return 0;
+}
diff --git a/net/mac80211/fils_aead.h b/net/mac80211/fils_aead.h
new file mode 100644
index 000000000000..fbc65232f0b3
--- /dev/null
+++ b/net/mac80211/fils_aead.h
@@ -0,0 +1,19 @@
+/*
+ * FILS AEAD for (Re)Association Request/Response frames
+ * Copyright 2016, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FILS_AEAD_H
+#define FILS_AEAD_H
+
+int fils_encrypt_assoc_req(struct sk_buff *skb,
+ struct ieee80211_mgd_assoc_data *assoc_data);
+int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ u8 *frame, size_t *frame_len,
+ struct ieee80211_mgd_assoc_data *assoc_data);
+
+#endif /* FILS_AEAD_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34c2add2c455..d37a577f63a1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -84,6 +84,8 @@ struct ieee80211_local;
#define IEEE80211_DEFAULT_MAX_SP_LEN \
IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
+extern const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS];
+
#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */)
#define IEEE80211_MAX_NAN_INSTANCE_ID 255
@@ -307,6 +309,7 @@ struct ieee80211_if_vlan {
/* used for all tx if the VLAN is configured to 4-addr mode */
struct sta_info __rcu *sta;
+ atomic_t num_mcast_sta; /* number of stations receiving multicast */
};
struct mesh_stats {
@@ -398,6 +401,10 @@ struct ieee80211_mgd_assoc_data {
struct ieee80211_vht_cap ap_vht_cap;
+ u8 fils_nonces[2 * FILS_NONCE_LEN];
+ u8 fils_kek[FILS_MAX_KEK_LEN];
+ size_t fils_kek_len;
+
size_t ie_len;
u8 ie[];
};
@@ -442,7 +449,7 @@ struct ieee80211_if_managed {
struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_mgd_assoc_data *assoc_data;
- u8 bssid[ETH_ALEN];
+ u8 bssid[ETH_ALEN] __aligned(2);
u16 aid;
@@ -1527,6 +1534,23 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
return false;
}
+void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata);
+void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata);
+
+/* This function returns the number of multicast stations connected to this
+ * interface. It returns -1 if that number is not tracked, that is for netdevs
+ * not in AP or AP_VLAN mode or when using 4addr.
+ */
+static inline int
+ieee80211_vif_get_num_mcast_if(struct ieee80211_sub_if_data *sdata)
+{
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ return atomic_read(&sdata->u.ap.num_mcast_sta);
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
+ return atomic_read(&sdata->u.vlan.num_mcast_sta);
+ return -1;
+}
+
u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
struct ieee80211_rx_status *status,
unsigned int mpdu_len,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 638ec0759078..41497b670e2b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -150,15 +150,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
ieee80211_hw_config(local, change);
}
-static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
bool check_dup)
{
@@ -1166,7 +1157,6 @@ static const struct net_device_ops ieee80211_dataif_ops = {
.ndo_uninit = ieee80211_uninit,
.ndo_start_xmit = ieee80211_subif_start_xmit,
.ndo_set_rx_mode = ieee80211_set_multicast_list,
- .ndo_change_mtu = ieee80211_change_mtu,
.ndo_set_mac_address = ieee80211_change_mac,
.ndo_select_queue = ieee80211_netdev_select_queue,
.ndo_get_stats64 = ieee80211_get_stats64,
@@ -1200,7 +1190,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
.ndo_uninit = ieee80211_uninit,
.ndo_start_xmit = ieee80211_monitor_start_xmit,
.ndo_set_rx_mode = ieee80211_set_multicast_list,
- .ndo_change_mtu = ieee80211_change_mtu,
.ndo_set_mac_address = ieee80211_change_mac,
.ndo_select_queue = ieee80211_monitor_select_queue,
.ndo_get_stats64 = ieee80211_get_stats64,
@@ -1884,6 +1873,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
+ /* MTU range: 256 - 2304 */
+ ndev->min_mtu = 256;
+ ndev->max_mtu = IEEE80211_MAX_DATA_LEN;
+
ret = register_netdevice(ndev);
if (ret) {
ieee80211_if_free(ndev);
@@ -2005,3 +1998,19 @@ void ieee80211_iface_exit(void)
{
unregister_netdevice_notifier(&mac80211_netdev_notifier);
}
+
+void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata)
+{
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ atomic_inc(&sdata->u.ap.num_mcast_sta);
+ else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ atomic_inc(&sdata->u.vlan.num_mcast_sta);
+}
+
+void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata)
+{
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ atomic_dec(&sdata->u.ap.num_mcast_sta);
+ else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ atomic_dec(&sdata->u.vlan.num_mcast_sta);
+}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1075ac24c8c5..1822c77f2b1c 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -549,6 +549,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
NL80211_FEATURE_MAC_ON_CREATE |
NL80211_FEATURE_USERSPACE_MPM |
NL80211_FEATURE_FULL_AP_CLIENT_STATE;
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
if (!ops->hw_scan)
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
@@ -821,6 +822,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
!local->ops->tdls_recv_channel_switch))
return -EOPNOTSUPP;
+ if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_TX_FRAG) &&
+ !local->ops->set_frag_threshold))
+ return -EINVAL;
+
if (WARN_ON(local->hw.wiphy->interface_modes &
BIT(NL80211_IFTYPE_NAN) &&
(!local->ops->start_nan || !local->ops->stop_nan)))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7486f2dab4ba..098ce9b179ee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -30,6 +30,7 @@
#include "driver-ops.h"
#include "rate.h"
#include "led.h"
+#include "fils_aead.h"
#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2)
@@ -652,6 +653,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
2 + sizeof(struct ieee80211_ht_cap) + /* HT */
2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
assoc_data->ie_len + /* extra IEs */
+ (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
9, /* WMM */
GFP_KERNEL);
if (!skb)
@@ -875,6 +877,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
memcpy(pos, assoc_data->ie + offset, noffset - offset);
}
+ if (assoc_data->fils_kek_len &&
+ fils_encrypt_assoc_req(skb, assoc_data) < 0) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
drv_mgd_prepare_tx(local, sdata);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -2510,7 +2518,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
}
static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
- bool assoc)
+ bool assoc, bool abandon)
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
@@ -2533,6 +2541,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
mutex_lock(&sdata->local->mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&sdata->local->mtx);
+
+ if (abandon)
+ cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
}
kfree(assoc_data);
@@ -2618,6 +2629,9 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
case WLAN_AUTH_LEAP:
case WLAN_AUTH_FT:
case WLAN_AUTH_SAE:
+ case WLAN_AUTH_FILS_SK:
+ case WLAN_AUTH_FILS_SK_PFS:
+ case WLAN_AUTH_FILS_PK:
break;
case WLAN_AUTH_SHARED_KEY:
if (ifmgd->auth_data->expected_transaction != 4) {
@@ -2762,7 +2776,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
bssid, reason_code,
ieee80211_get_reason_code_string(reason_code));
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, true);
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
return;
@@ -3143,6 +3157,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
reassoc ? "Rea" : "A", mgmt->sa,
capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+ if (assoc_data->fils_kek_len &&
+ fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
+ return;
+
pos = mgmt->u.assoc_resp.variable;
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
@@ -3167,14 +3185,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied association (code=%d)\n",
mgmt->sa, status_code);
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, false);
event.u.mlme.status = MLME_DENIED;
event.u.mlme.reason = status_code;
drv_event_callback(sdata->local, sdata, &event);
} else {
if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss);
return;
}
@@ -3187,13 +3205,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
* recalc after assoc_data is NULL but before associated
* is set can cause the interface to go idle
*/
- ieee80211_destroy_assoc_data(sdata, true);
+ ieee80211_destroy_assoc_data(sdata, true, false);
/* get uapsd queues configuration */
uapsd_queues = 0;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
if (sdata->tx_conf[ac].uapsd)
- uapsd_queues |= BIT(ac);
+ uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
}
cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
@@ -3886,7 +3904,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
.u.mlme.status = MLME_TIMEOUT,
};
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss);
drv_event_callback(sdata->local, sdata, &event);
}
@@ -4025,7 +4043,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
WLAN_REASON_DEAUTH_LEAVING,
false, frame_buf);
if (ifmgd->assoc_data)
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, true);
if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false);
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
@@ -4479,24 +4497,36 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
case NL80211_AUTHTYPE_SAE:
auth_alg = WLAN_AUTH_SAE;
break;
+ case NL80211_AUTHTYPE_FILS_SK:
+ auth_alg = WLAN_AUTH_FILS_SK;
+ break;
+ case NL80211_AUTHTYPE_FILS_SK_PFS:
+ auth_alg = WLAN_AUTH_FILS_SK_PFS;
+ break;
+ case NL80211_AUTHTYPE_FILS_PK:
+ auth_alg = WLAN_AUTH_FILS_PK;
+ break;
default:
return -EOPNOTSUPP;
}
- auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
+ auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
req->ie_len, GFP_KERNEL);
if (!auth_data)
return -ENOMEM;
auth_data->bss = req->bss;
- if (req->sae_data_len >= 4) {
- __le16 *pos = (__le16 *) req->sae_data;
- auth_data->sae_trans = le16_to_cpu(pos[0]);
- auth_data->sae_status = le16_to_cpu(pos[1]);
- memcpy(auth_data->data, req->sae_data + 4,
- req->sae_data_len - 4);
- auth_data->data_len += req->sae_data_len - 4;
+ if (req->auth_data_len >= 4) {
+ if (req->auth_type == NL80211_AUTHTYPE_SAE) {
+ __le16 *pos = (__le16 *) req->auth_data;
+
+ auth_data->sae_trans = le16_to_cpu(pos[0]);
+ auth_data->sae_status = le16_to_cpu(pos[1]);
+ }
+ memcpy(auth_data->data, req->auth_data + 4,
+ req->auth_data_len - 4);
+ auth_data->data_len += req->auth_data_len - 4;
}
if (req->ie && req->ie_len) {
@@ -4692,6 +4722,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->ie_len = req->ie_len;
}
+ if (req->fils_kek) {
+ /* should already be checked in cfg80211 - so warn */
+ if (WARN_ON(req->fils_kek_len > FILS_MAX_KEK_LEN)) {
+ err = -EINVAL;
+ goto err_free;
+ }
+ memcpy(assoc_data->fils_kek, req->fils_kek,
+ req->fils_kek_len);
+ assoc_data->fils_kek_len = req->fils_kek_len;
+ }
+
+ if (req->fils_nonces)
+ memcpy(assoc_data->fils_nonces, req->fils_nonces,
+ 2 * FILS_NONCE_LEN);
+
assoc_data->bss = req->bss;
if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
@@ -4907,7 +4952,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
IEEE80211_STYPE_DEAUTH,
req->reason_code, tx,
frame_buf);
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, true);
ieee80211_report_disconnect(sdata, frame_buf,
sizeof(frame_buf), true,
req->reason_code);
@@ -4982,7 +5027,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
sdata_lock(sdata);
if (ifmgd->assoc_data) {
struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
- ieee80211_destroy_assoc_data(sdata, false);
+ ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss);
}
if (ifmgd->auth_data)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a47bbc973f2d..eeab7250f4b9 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1394,13 +1394,15 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
u8 ac = ieee802_1d_to_ac[tid & 7];
/*
- * If this AC is not trigger-enabled do nothing.
+ * If this AC is not trigger-enabled do nothing unless the
+ * driver is calling us after it already checked.
*
* NB: This could/should check a separate bitmap of trigger-
* enabled queues, but for now we only implement uAPSD w/o
* TSPEC changes to the ACs, so they're always the same.
*/
- if (!(sta->sta.uapsd_queues & BIT(ac)))
+ if (!(sta->sta.uapsd_queues & ieee80211_ac_to_qos_mask[ac]) &&
+ tid != IEEE80211_NUM_TIDS)
return;
/* if we are in a service period, do nothing */
@@ -2215,7 +2217,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
- if (is_multicast_ether_addr(ehdr->h_dest)) {
+ if (is_multicast_ether_addr(ehdr->h_dest) &&
+ ieee80211_vif_get_num_mcast_if(sdata) != 0) {
/*
* send multicast frames both to higher layers in
* local net stack and back to the wireless medium
@@ -2224,7 +2227,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
if (!xmit_skb)
net_info_ratelimited("%s: failed to clone multicast frame\n",
dev->name);
- } else {
+ } else if (!is_multicast_ether_addr(ehdr->h_dest)) {
dsta = sta_info_get(sdata, skb->data);
if (dsta) {
/*
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 8e05032689f0..1711bae4abf2 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -709,7 +709,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
unsigned long tids;
- if (ignore_for_tim & BIT(ac))
+ if (ignore_for_tim & ieee80211_ac_to_qos_mask[ac])
continue;
indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1389,7 +1389,7 @@ ieee80211_sta_ps_more_data(struct sta_info *sta, u8 ignored_acs,
return true;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- if (ignored_acs & BIT(ac))
+ if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
continue;
if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1414,7 +1414,7 @@ ieee80211_sta_ps_get_frames(struct sta_info *sta, int n_frames, u8 ignored_acs,
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
unsigned long tids;
- if (ignored_acs & BIT(ac))
+ if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
continue;
tids = ieee80211_tids_for_ac(ac);
@@ -1482,7 +1482,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
BIT(find_highest_prio_tid(driver_release_tids));
if (skb_queue_empty(&frames) && !driver_release_tids) {
- int tid;
+ int tid, ac;
/*
* For PS-Poll, this can only happen due to a race condition
@@ -1500,7 +1500,10 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
*/
/* This will evaluate to 1, 3, 5 or 7. */
- tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
+ if (ignored_acs & BIT(ac))
+ continue;
+ tid = 7 - 2 * ac;
ieee80211_send_null_response(sta, tid, reason, true, false);
} else if (!driver_release_tids) {
@@ -1871,10 +1874,7 @@ int sta_info_move_state(struct sta_info *sta,
if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_dec(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_dec_num_mcast(sta->sdata);
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_clear_fast_xmit(sta);
ieee80211_clear_fast_rx(sta);
@@ -1882,10 +1882,7 @@ int sta_info_move_state(struct sta_info *sta,
break;
case IEEE80211_STA_AUTHORIZED:
if (sta->sta_state == IEEE80211_STA_ASSOC) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_inc(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_inc_num_mcast(sta->sdata);
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_check_fast_xmit(sta);
ieee80211_check_fast_rx(sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ed5fcb984a01..dd06ef0b8861 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -184,7 +184,6 @@ struct tid_ampdu_tx {
* @ssn: Starting Sequence Number expected to be aggregated.
* @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value (in TUs).
- * @dialog_token: dialog token for aggregation session
* @rcu_head: RCU head used for freeing this struct
* @reorder_lock: serializes access to reorder buffer, see below.
* @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
@@ -213,7 +212,6 @@ struct tid_ampdu_rx {
u16 ssn;
u16 buf_size;
u16 timeout;
- u8 dialog_token;
bool auto_seq;
bool removed;
};
@@ -225,6 +223,7 @@ struct tid_ampdu_rx {
* to tid_tx[idx], which are protected by the sta spinlock)
* tid_start_tx is also protected by sta->lock.
* @tid_rx: aggregation info for Rx per TID -- RCU protected
+ * @tid_rx_token: dialog tokens for valid aggregation sessions
* @tid_rx_timer_expired: bitmap indicating on which TIDs the
* RX timer expired until the work for it runs
* @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the
@@ -243,6 +242,7 @@ struct sta_ampdu_mlme {
struct mutex mtx;
/* rx */
struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
+ u8 tid_rx_token[IEEE80211_NUM_TIDS];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bd5f4be89435..2c21b7039136 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -331,9 +331,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
}
- } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
- ieee80211_is_data(hdr->frame_control) &&
- !atomic_read(&tx->sdata->u.ap.num_mcast_sta))) {
+ } else if (unlikely(ieee80211_is_data(hdr->frame_control) &&
+ ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) {
/*
* No associated STAs - no need to send multicast
* frames.
@@ -935,7 +934,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
return TX_CONTINUE;
- if (tx->local->ops->set_frag_threshold)
+ if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG))
return TX_CONTINUE;
/*
@@ -2798,7 +2797,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
/* fast-xmit doesn't handle fragmentation at all */
if (local->hw.wiphy->frag_threshold != (u32)-1 &&
- !local->ops->set_frag_threshold)
+ !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
goto out;
rcu_read_lock();
@@ -3057,11 +3056,12 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
- struct ethhdr amsdu_hdr;
+ struct ethhdr *amsdu_hdr;
int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
int subframe_len = skb->len - hdr_len;
void *data;
- u8 *qc;
+ u8 *qc, *h_80211_src, *h_80211_dst;
+ const u8 *bssid;
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
return false;
@@ -3069,19 +3069,44 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
return true;
- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr),
+ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr),
&subframe_len))
return false;
- amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
- memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
- memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
+ data = skb_push(skb, sizeof(*amsdu_hdr));
+ memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
+ hdr = data;
+ amsdu_hdr = data + hdr_len;
+ /* h_80211_src/dst is addr* field within hdr */
+ h_80211_src = data + fast_tx->sa_offs;
+ h_80211_dst = data + fast_tx->da_offs;
+
+ amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
+ ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
+ ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
+
+ /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
+ * fields needs to be changed to BSSID for A-MSDU frames depending
+ * on FromDS/ToDS values.
+ */
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ bssid = sdata->u.mgd.bssid;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ bssid = sdata->vif.addr;
+ break;
+ default:
+ bssid = NULL;
+ }
- data = skb_push(skb, sizeof(amsdu_hdr));
- memmove(data, data + sizeof(amsdu_hdr), hdr_len);
- memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
+ if (bssid && ieee80211_has_fromds(hdr->frame_control))
+ ether_addr_copy(h_80211_src, bssid);
+
+ if (bssid && ieee80211_has_tods(hdr->frame_control))
+ ether_addr_copy(h_80211_dst, bssid);
- hdr = data;
qc = ieee80211_get_qos_ctl(hdr);
*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 545c79a42a77..ac59fbd280df 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3308,10 +3308,11 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *sdata_iter;
enum nl80211_iftype iftype = sdata->wdev.iftype;
- int num[NUM_NL80211_IFTYPES];
struct ieee80211_chanctx *ctx;
- int num_different_channels = 0;
int total = 1;
+ struct iface_combination_params params = {
+ .radar_detect = radar_detect,
+ };
lockdep_assert_held(&local->chanctx_mtx);
@@ -3322,12 +3323,19 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
!chandef->chan))
return -EINVAL;
- if (chandef)
- num_different_channels = 1;
-
if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
return -EINVAL;
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+ /*
+ * always passing this is harmless, since it'll be the
+ * same value that cfg80211 finds if it finds the same
+ * interface ... and that's always allowed
+ */
+ params.new_beacon_int = sdata->vif.bss_conf.beacon_int;
+ }
+
/* Always allow software iftypes */
if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
if (radar_detect)
@@ -3335,24 +3343,26 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
return 0;
}
- memset(num, 0, sizeof(num));
+ if (chandef)
+ params.num_different_channels = 1;
if (iftype != NL80211_IFTYPE_UNSPECIFIED)
- num[iftype] = 1;
+ params.iftype_num[iftype] = 1;
list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
- radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
+ params.radar_detect |=
+ ieee80211_chanctx_radar_detect(local, ctx);
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
- num_different_channels++;
+ params.num_different_channels++;
continue;
}
if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
cfg80211_chandef_compatible(chandef,
&ctx->conf.def))
continue;
- num_different_channels++;
+ params.num_different_channels++;
}
list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
@@ -3365,16 +3375,14 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
continue;
- num[wdev_iter->iftype]++;
+ params.iftype_num[wdev_iter->iftype]++;
total++;
}
- if (total == 1 && !radar_detect)
+ if (total == 1 && !params.radar_detect)
return 0;
- return cfg80211_check_combinations(local->hw.wiphy,
- num_different_channels,
- radar_detect, num);
+ return cfg80211_check_combinations(local->hw.wiphy, &params);
}
static void
@@ -3390,12 +3398,10 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
int ieee80211_max_num_channels(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
- int num[NUM_NL80211_IFTYPES] = {};
struct ieee80211_chanctx *ctx;
- int num_different_channels = 0;
- u8 radar_detect = 0;
u32 max_num_different_channels = 1;
int err;
+ struct iface_combination_params params = {0};
lockdep_assert_held(&local->chanctx_mtx);
@@ -3403,17 +3409,17 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
- num_different_channels++;
+ params.num_different_channels++;
- radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
+ params.radar_detect |=
+ ieee80211_chanctx_radar_detect(local, ctx);
}
list_for_each_entry_rcu(sdata, &local->interfaces, list)
- num[sdata->wdev.iftype]++;
+ params.iftype_num[sdata->wdev.iftype]++;
- err = cfg80211_iter_combinations(local->hw.wiphy,
- num_different_channels, radar_detect,
- num, ieee80211_iter_max_chans,
+ err = cfg80211_iter_combinations(local->hw.wiphy, &params,
+ ieee80211_iter_max_chans,
&max_num_different_channels);
if (err < 0)
return err;
@@ -3456,3 +3462,10 @@ void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
*byte_cnt = txqi->tin.backlog_bytes + frag_bytes;
}
EXPORT_SYMBOL(ieee80211_txq_get_depth);
+
+const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS] = {
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_VO,
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_VI,
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_BE,
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_BK
+};
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 9eb0aee9105b..3e3d3014e9ab 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -236,26 +236,35 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ u8 flags;
u8 *p;
- u8 ack_policy, tid;
if (!ieee80211_is_data_qos(hdr->frame_control))
return;
p = ieee80211_get_qos_ctl(hdr);
- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- /* preserve EOSP bit */
- ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
+ /* set up the first byte */
+
+ /*
+ * preserve everything but the TID and ACK policy
+ * (which we both write here)
+ */
+ flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK |
+ IEEE80211_QOS_CTL_ACK_POLICY_MASK);
if (is_multicast_ether_addr(hdr->addr1) ||
sdata->noack_map & BIT(tid)) {
- ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
+ flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
info->flags |= IEEE80211_TX_CTL_NO_ACK;
}
- /* qos header is 2 bytes */
- *p++ = ack_policy | tid;
+ *p = flags | tid;
+
+ /* set up the second byte */
+ p++;
+
if (ieee80211_vif_is_mesh(&sdata->vif)) {
/* preserve RSPI and Mesh PS Level bit */
*p &= ((IEEE80211_QOS_CTL_RSPI |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 42ce9bd4426f..8af6dd388d11 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -57,7 +57,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
if (info->control.hw_key &&
(info->flags & IEEE80211_TX_CTL_DONTFRAG ||
- tx->local->ops->set_frag_threshold) &&
+ ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
/* hwaccel - with no need for SW-generated MMIC */
return TX_CONTINUE;
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index cf52cf30ac4b..2f7ccd934416 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -133,7 +133,6 @@ static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
struct mpls_iptunnel_encap *tun_encap_info;
struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
struct lwtunnel_state *newts;
- int tun_encap_info_len;
int ret;
ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla,
@@ -144,13 +143,11 @@ static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
if (!tb[MPLS_IPTUNNEL_DST])
return -EINVAL;
- tun_encap_info_len = sizeof(*tun_encap_info);
- newts = lwtunnel_state_alloc(tun_encap_info_len);
+ newts = lwtunnel_state_alloc(sizeof(*tun_encap_info));
if (!newts)
return -ENOMEM;
- newts->len = tun_encap_info_len;
tun_encap_info = mpls_lwtunnel_encap(newts);
ret = nla_get_labels(tb[MPLS_IPTUNNEL_DST], MAX_NEW_LABELS,
&tun_encap_info->labels, tun_encap_info->label);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index e8d56d9a4df2..63729b489c2c 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -57,6 +57,10 @@ config NF_CONNTRACK
config NF_LOG_COMMON
tristate
+config NF_LOG_NETDEV
+ tristate "Netdev packet logging"
+ select NF_LOG_COMMON
+
if NF_CONNTRACK
config NF_CONNTRACK_MARK
@@ -142,38 +146,38 @@ config NF_CONNTRACK_LABELS
to connection tracking entries. It selected by the connlabel match.
config NF_CT_PROTO_DCCP
- tristate 'DCCP protocol connection tracking support'
+ bool 'DCCP protocol connection tracking support'
depends on NETFILTER_ADVANCED
- default IP_DCCP
+ default y
help
With this option enabled, the layer 3 independent connection
tracking code will be able to do state tracking on DCCP connections.
- If unsure, say 'N'.
+ If unsure, say Y.
config NF_CT_PROTO_GRE
tristate
config NF_CT_PROTO_SCTP
- tristate 'SCTP protocol connection tracking support'
+ bool 'SCTP protocol connection tracking support'
depends on NETFILTER_ADVANCED
- default IP_SCTP
+ default y
help
With this option enabled, the layer 3 independent connection
tracking code will be able to do state tracking on SCTP connections.
- If you want to compile it as a module, say M here and read
- <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+ If unsure, say Y.
config NF_CT_PROTO_UDPLITE
- tristate 'UDP-Lite protocol connection tracking support'
+ bool 'UDP-Lite protocol connection tracking support'
depends on NETFILTER_ADVANCED
+ default y
help
With this option enabled, the layer 3 independent connection
tracking code will be able to do state tracking on UDP-Lite
connections.
- To compile it as a module, choose M here. If unsure, say N.
+ If unsure, say Y.
config NF_CONNTRACK_AMANDA
tristate "Amanda backup protocol support"
@@ -380,17 +384,17 @@ config NF_NAT_NEEDED
default y
config NF_NAT_PROTO_DCCP
- tristate
+ bool
depends on NF_NAT && NF_CT_PROTO_DCCP
default NF_NAT && NF_CT_PROTO_DCCP
config NF_NAT_PROTO_UDPLITE
- tristate
+ bool
depends on NF_NAT && NF_CT_PROTO_UDPLITE
default NF_NAT && NF_CT_PROTO_UDPLITE
config NF_NAT_PROTO_SCTP
- tristate
+ bool
default NF_NAT && NF_CT_PROTO_SCTP
depends on NF_NAT && NF_CT_PROTO_SCTP
select LIBCRC32C
@@ -474,6 +478,12 @@ config NFT_META
This option adds the "meta" expression that you can use to match and
to set packet metainformation such as the packet mark.
+config NFT_RT
+ tristate "Netfilter nf_tables routing module"
+ help
+ This option adds the "rt" expression that you can use to match
+ packet routing information such as the packet nexthop.
+
config NFT_NUMGEN
tristate "Netfilter nf_tables number generator module"
help
@@ -541,6 +551,12 @@ config NFT_NAT
This option adds the "nat" expression that you can use to perform
typical Network Address Translation (NAT) packet transformations.
+config NFT_OBJREF
+ tristate "Netfilter nf_tables stateful object reference module"
+ help
+ This option adds the "objref" expression that allows you to refer to
+ stateful objects, such as counters and quotas.
+
config NFT_QUEUE
depends on NETFILTER_NETLINK_QUEUE
tristate "Netfilter nf_tables queue module"
@@ -581,6 +597,19 @@ config NFT_HASH
This option adds the "hash" expression that you can use to perform
a hash operation on registers.
+config NFT_FIB
+ tristate
+
+config NFT_FIB_INET
+ depends on NF_TABLES_INET
+ depends on NFT_FIB_IPV4
+ depends on NFT_FIB_IPV6
+ tristate "Netfilter nf_tables fib inet support"
+ help
+ This option allows using the FIB expression from the inet table.
+ The lookup will be delegated to the IPv4 or IPv6 FIB depending
+ on the protocol of the packet.
+
if NF_TABLES_NETDEV
config NF_DUP_NETDEV
@@ -1409,9 +1438,10 @@ config NETFILTER_XT_MATCH_SOCKET
tristate '"socket" match support'
depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
- depends on !NF_CONNTRACK || NF_CONNTRACK
depends on IPV6 || IPV6=n
depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n
+ depends on NF_SOCKET_IPV4
+ depends on NF_SOCKET_IPV6
select NF_DEFRAG_IPV4
select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n
help
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index c23c3c84416f..ca30d1960f1d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -5,6 +5,9 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o
+nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
+nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+nf_conntrack-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -16,11 +19,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
# connection tracking
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
-# SCTP protocol connection tracking
-obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
-obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
-obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
# netlink interface for nf_conntrack
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
@@ -45,17 +44,20 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \
nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o
+# NAT protocols (nf_nat)
+nf_nat-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
+nf_nat-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
+nf_nat-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
+
# generic transport layer logging
obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o
+# packet logging for netdev family
+obj-$(CONFIG_NF_LOG_NETDEV) += nf_log_netdev.o
+
obj-$(CONFIG_NF_NAT) += nf_nat.o
obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o
-# NAT protocols (nf_nat)
-obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
-obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
-obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
-
# NAT helpers
obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
@@ -81,10 +83,12 @@ obj-$(CONFIG_NF_TABLES_NETDEV) += nf_tables_netdev.o
obj-$(CONFIG_NFT_COMPAT) += nft_compat.o
obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o
obj-$(CONFIG_NFT_META) += nft_meta.o
+obj-$(CONFIG_NFT_RT) += nft_rt.o
obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o
obj-$(CONFIG_NFT_CT) += nft_ct.o
obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
obj-$(CONFIG_NFT_NAT) += nft_nat.o
+obj-$(CONFIG_NFT_OBJREF) += nft_objref.o
obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
obj-$(CONFIG_NFT_QUOTA) += nft_quota.o
obj-$(CONFIG_NFT_REJECT) += nft_reject.o
@@ -96,6 +100,8 @@ obj-$(CONFIG_NFT_LOG) += nft_log.o
obj-$(CONFIG_NFT_MASQ) += nft_masq.o
obj-$(CONFIG_NFT_REDIR) += nft_redir.o
obj-$(CONFIG_NFT_HASH) += nft_hash.o
+obj-$(CONFIG_NFT_FIB) += nft_fib.o
+obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o
# nf_tables netdev
obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 004af030ef1a..ce6adfae521a 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -102,17 +102,14 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
if (!entry)
return -ENOMEM;
- entry->orig_ops = reg;
- entry->ops = *reg;
- entry->next = NULL;
+ nf_hook_entry_init(entry, reg);
mutex_lock(&nf_hook_mutex);
/* Find the spot in the list */
- while ((p = nf_entry_dereference(*pp)) != NULL) {
- if (reg->priority < p->orig_ops->priority)
+ for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) {
+ if (reg->priority < nf_hook_entry_priority(p))
break;
- pp = &p->next;
}
rcu_assign_pointer(entry->next, p);
rcu_assign_pointer(*pp, entry);
@@ -139,12 +136,11 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
return;
mutex_lock(&nf_hook_mutex);
- while ((p = nf_entry_dereference(*pp)) != NULL) {
- if (p->orig_ops == reg) {
+ for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) {
+ if (nf_hook_entry_ops(p) == reg) {
rcu_assign_pointer(*pp, p->next);
break;
}
- pp = &p->next;
}
mutex_unlock(&nf_hook_mutex);
if (!p) {
@@ -302,70 +298,40 @@ void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
}
EXPORT_SYMBOL(_nf_unregister_hooks);
-unsigned int nf_iterate(struct sk_buff *skb,
- struct nf_hook_state *state,
- struct nf_hook_entry **entryp)
+/* Returns 1 if okfn() needs to be executed by the caller,
+ * -EPERM for NF_DROP, 0 otherwise. Caller must hold rcu_read_lock. */
+int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
+ struct nf_hook_entry *entry)
{
unsigned int verdict;
+ int ret;
- /*
- * The caller must not block between calls to this
- * function because of risk of continuing from deleted element.
- */
- while (*entryp) {
- if (state->thresh > (*entryp)->ops.priority) {
- *entryp = rcu_dereference((*entryp)->next);
- continue;
- }
-
- /* Optimization: we don't need to hold module
- reference here, since function can't sleep. --RR */
-repeat:
- verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
- if (verdict != NF_ACCEPT) {
-#ifdef CONFIG_NETFILTER_DEBUG
- if (unlikely((verdict & NF_VERDICT_MASK)
- > NF_MAX_VERDICT)) {
- NFDEBUG("Evil return from %p(%u).\n",
- (*entryp)->ops.hook, state->hook);
- *entryp = rcu_dereference((*entryp)->next);
+ do {
+ verdict = nf_hook_entry_hookfn(entry, skb, state);
+ switch (verdict & NF_VERDICT_MASK) {
+ case NF_ACCEPT:
+ entry = rcu_dereference(entry->next);
+ break;
+ case NF_DROP:
+ kfree_skb(skb);
+ ret = NF_DROP_GETERR(verdict);
+ if (ret == 0)
+ ret = -EPERM;
+ return ret;
+ case NF_QUEUE:
+ ret = nf_queue(skb, state, &entry, verdict);
+ if (ret == 1 && entry)
continue;
- }
-#endif
- if (verdict != NF_REPEAT)
- return verdict;
- goto repeat;
+ return ret;
+ default:
+ /* Implicit handling for NF_STOLEN, as well as any other
+ * non conventional verdicts.
+ */
+ return 0;
}
- *entryp = rcu_dereference((*entryp)->next);
- }
- return NF_ACCEPT;
-}
-
+ } while (entry);
-/* Returns 1 if okfn() needs to be executed by the caller,
- * -EPERM for NF_DROP, 0 otherwise. Caller must hold rcu_read_lock. */
-int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
-{
- struct nf_hook_entry *entry;
- unsigned int verdict;
- int ret = 0;
-
- entry = rcu_dereference(state->hook_entries);
-next_hook:
- verdict = nf_iterate(skb, state, &entry);
- if (verdict == NF_ACCEPT || verdict == NF_STOP) {
- ret = 1;
- } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
- kfree_skb(skb);
- ret = NF_DROP_GETERR(verdict);
- if (ret == 0)
- ret = -EPERM;
- } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
- ret = nf_queue(skb, state, &entry, verdict);
- if (ret == 1 && entry)
- goto next_hook;
- }
- return ret;
+ return 1;
}
EXPORT_SYMBOL(nf_hook_slow);
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
index 234a8ec82076..4083a8051f0f 100644
--- a/net/netfilter/ipset/Kconfig
+++ b/net/netfilter/ipset/Kconfig
@@ -99,6 +99,15 @@ config IP_SET_HASH_IPPORTNET
To compile it as a module, choose M here. If unsure, say N.
+config IP_SET_HASH_IPMAC
+ tristate "hash:ip,mac set support"
+ depends on IP_SET
+ help
+ This option adds the hash:ip,mac set type support, by which
+ one can store IPv4/IPv6 address and MAC (ethernet address) pairs in a set.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_SET_HASH_MAC
tristate "hash:mac set support"
depends on IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
index 3dbd5e958489..28ec148df02d 100644
--- a/net/netfilter/ipset/Makefile
+++ b/net/netfilter/ipset/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IP_SET_BITMAP_PORT) += ip_set_bitmap_port.o
# hash types
obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o
+obj-$(CONFIG_IP_SET_HASH_IPMAC) += ip_set_hash_ipmac.o
obj-$(CONFIG_IP_SET_HASH_IPMARK) += ip_set_hash_ipmark.o
obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o
obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
index 2e8e7e5fb4a6..6f09a99298cd 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -22,6 +22,7 @@
#define mtype_kadt IPSET_TOKEN(MTYPE, _kadt)
#define mtype_uadt IPSET_TOKEN(MTYPE, _uadt)
#define mtype_destroy IPSET_TOKEN(MTYPE, _destroy)
+#define mtype_memsize IPSET_TOKEN(MTYPE, _memsize)
#define mtype_flush IPSET_TOKEN(MTYPE, _flush)
#define mtype_head IPSET_TOKEN(MTYPE, _head)
#define mtype_same_set IPSET_TOKEN(MTYPE, _same_set)
@@ -40,11 +41,8 @@ mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
{
struct mtype *map = set->data;
- init_timer(&map->gc);
- map->gc.data = (unsigned long)set;
- map->gc.function = gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
- add_timer(&map->gc);
+ setup_timer(&map->gc, gc, (unsigned long)set);
+ mod_timer(&map->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
}
static void
@@ -82,6 +80,16 @@ mtype_flush(struct ip_set *set)
if (set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set);
memset(map->members, 0, map->memsize);
+ set->elements = 0;
+ set->ext_size = 0;
+}
+
+/* Calculate the actual memory size of the set data */
+static size_t
+mtype_memsize(const struct mtype *map, size_t dsize)
+{
+ return sizeof(*map) + map->memsize +
+ map->elements * dsize;
}
static int
@@ -89,14 +97,15 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
{
const struct mtype *map = set->data;
struct nlattr *nested;
- size_t memsize = sizeof(*map) + map->memsize;
+ size_t memsize = mtype_memsize(map, set->dsize) + set->ext_size;
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested)
goto nla_put_failure;
if (mtype_do_head(skb, map) ||
nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
- nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)))
+ nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
+ nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
goto nla_put_failure;
if (unlikely(ip_set_put_flags(skb, set)))
goto nla_put_failure;
@@ -140,6 +149,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (ret == IPSET_ADD_FAILED) {
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(x, set))) {
+ set->elements--;
ret = 0;
} else if (!(flags & IPSET_FLAG_EXIST)) {
set_bit(e->id, map->members);
@@ -148,6 +158,8 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
/* Element is re-added, cleanup extensions */
ip_set_ext_destroy(set, x);
}
+ if (ret > 0)
+ set->elements--;
if (SET_WITH_TIMEOUT(set))
#ifdef IP_SET_BITMAP_STORED_TIMEOUT
@@ -159,12 +171,13 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(x, set), ext);
if (SET_WITH_COMMENT(set))
- ip_set_init_comment(ext_comment(x, set), ext);
+ ip_set_init_comment(set, ext_comment(x, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(x, set), ext);
/* Activate element */
set_bit(e->id, map->members);
+ set->elements++;
return 0;
}
@@ -181,6 +194,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
return -IPSET_ERR_EXIST;
ip_set_ext_destroy(set, x);
+ set->elements--;
if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(x, set)))
return -IPSET_ERR_EXIST;
@@ -276,6 +290,7 @@ mtype_gc(unsigned long ul_set)
if (ip_set_timeout_expired(ext_timeout(x, set))) {
clear_bit(id, map->members);
ip_set_ext_destroy(set, x);
+ set->elements--;
}
}
spin_unlock_bh(&set->lock);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index a748b0c2c981..c296f9b606d4 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -36,7 +36,7 @@ struct ip_set_net {
bool is_destroyed; /* all sets are destroyed */
};
-static int ip_set_net_id __read_mostly;
+static unsigned int ip_set_net_id __read_mostly;
static inline struct ip_set_net *ip_set_pernet(struct net *net)
{
@@ -324,7 +324,7 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
}
EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
-typedef void (*destroyer)(void *);
+typedef void (*destroyer)(struct ip_set *, void *);
/* ipset data extension types, in size order */
const struct ip_set_ext_type ip_set_extensions[] = {
@@ -426,20 +426,20 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO;
fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK]));
- ext->skbmark = fullmark >> 32;
- ext->skbmarkmask = fullmark & 0xffffffff;
+ ext->skbinfo.skbmark = fullmark >> 32;
+ ext->skbinfo.skbmarkmask = fullmark & 0xffffffff;
}
if (tb[IPSET_ATTR_SKBPRIO]) {
if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO;
- ext->skbprio = be32_to_cpu(nla_get_be32(
- tb[IPSET_ATTR_SKBPRIO]));
+ ext->skbinfo.skbprio =
+ be32_to_cpu(nla_get_be32(tb[IPSET_ATTR_SKBPRIO]));
}
if (tb[IPSET_ATTR_SKBQUEUE]) {
if (!SET_WITH_SKBINFO(set))
return -IPSET_ERR_SKBINFO;
- ext->skbqueue = be16_to_cpu(nla_get_be16(
- tb[IPSET_ATTR_SKBQUEUE]));
+ ext->skbinfo.skbqueue =
+ be16_to_cpu(nla_get_be16(tb[IPSET_ATTR_SKBQUEUE]));
}
return 0;
}
@@ -541,7 +541,7 @@ int
ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_rcu_get(par->net, index);
+ struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
int ret = 0;
BUG_ON(!set);
@@ -579,7 +579,7 @@ int
ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_rcu_get(par->net, index);
+ struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
int ret;
BUG_ON(!set);
@@ -601,7 +601,7 @@ int
ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_rcu_get(par->net, index);
+ struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
int ret = 0;
BUG_ON(!set);
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index d32fd6b036bf..1b05d4a7d5a1 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -85,6 +85,8 @@ struct htable {
};
#define hbucket(h, i) ((h)->bucket[i])
+#define ext_size(n, dsize) \
+ (sizeof(struct hbucket) + (n) * (dsize))
#ifndef IPSET_NET_COUNT
#define IPSET_NET_COUNT 1
@@ -150,24 +152,34 @@ htable_bits(u32 hashsize)
#define INIT_CIDR(cidr, host_mask) \
DCIDR_PUT(((cidr) ? NCIDR_GET(cidr) : host_mask))
-#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
-
#ifdef IP_SET_HASH_WITH_NET0
-/* cidr from 0 to SET_HOST_MASK() value and c = cidr + 1 */
-#define NLEN(family) (SET_HOST_MASK(family) + 1)
+/* cidr from 0 to HOST_MASK value and c = cidr + 1 */
+#define NLEN (HOST_MASK + 1)
#define CIDR_POS(c) ((c) - 1)
#else
-/* cidr from 1 to SET_HOST_MASK() value and c = cidr + 1 */
-#define NLEN(family) SET_HOST_MASK(family)
+/* cidr from 1 to HOST_MASK value and c = cidr + 1 */
+#define NLEN HOST_MASK
#define CIDR_POS(c) ((c) - 2)
#endif
#else
-#define NLEN(family) 0
+#define NLEN 0
#endif /* IP_SET_HASH_WITH_NETS */
#endif /* _IP_SET_HASH_GEN_H */
+#ifndef MTYPE
+#error "MTYPE is not defined!"
+#endif
+
+#ifndef HTYPE
+#error "HTYPE is not defined!"
+#endif
+
+#ifndef HOST_MASK
+#error "HOST_MASK is not defined!"
+#endif
+
/* Family dependent templates */
#undef ahash_data
@@ -191,7 +203,6 @@ htable_bits(u32 hashsize)
#undef mtype_same_set
#undef mtype_kadt
#undef mtype_uadt
-#undef mtype
#undef mtype_add
#undef mtype_del
@@ -207,6 +218,7 @@ htable_bits(u32 hashsize)
#undef mtype_variant
#undef mtype_data_match
+#undef htype
#undef HKEY
#define mtype_data_equal IPSET_TOKEN(MTYPE, _data_equal)
@@ -233,7 +245,6 @@ htable_bits(u32 hashsize)
#define mtype_same_set IPSET_TOKEN(MTYPE, _same_set)
#define mtype_kadt IPSET_TOKEN(MTYPE, _kadt)
#define mtype_uadt IPSET_TOKEN(MTYPE, _uadt)
-#define mtype MTYPE
#define mtype_add IPSET_TOKEN(MTYPE, _add)
#define mtype_del IPSET_TOKEN(MTYPE, _del)
@@ -249,62 +260,54 @@ htable_bits(u32 hashsize)
#define mtype_variant IPSET_TOKEN(MTYPE, _variant)
#define mtype_data_match IPSET_TOKEN(MTYPE, _data_match)
-#ifndef MTYPE
-#error "MTYPE is not defined!"
-#endif
-
-#ifndef HOST_MASK
-#error "HOST_MASK is not defined!"
-#endif
-
#ifndef HKEY_DATALEN
#define HKEY_DATALEN sizeof(struct mtype_elem)
#endif
-#define HKEY(data, initval, htable_bits) \
-(jhash2((u32 *)(data), HKEY_DATALEN / sizeof(u32), initval) \
- & jhash_mask(htable_bits))
+#define htype MTYPE
-#ifndef htype
-#ifndef HTYPE
-#error "HTYPE is not defined!"
-#endif /* HTYPE */
-#define htype HTYPE
+#define HKEY(data, initval, htable_bits) \
+({ \
+ const u32 *__k = (const u32 *)data; \
+ u32 __l = HKEY_DATALEN / sizeof(u32); \
+ \
+ BUILD_BUG_ON(HKEY_DATALEN % sizeof(u32) != 0); \
+ \
+ jhash2(__k, __l, initval) & jhash_mask(htable_bits); \
+})
/* The generic hash structure */
struct htype {
struct htable __rcu *table; /* the hash table */
+ struct timer_list gc; /* garbage collection when timeout enabled */
u32 maxelem; /* max elements in the hash */
- u32 elements; /* current element (vs timeout) */
u32 initval; /* random jhash init value */
#ifdef IP_SET_HASH_WITH_MARKMASK
u32 markmask; /* markmask value for mark mask to store */
#endif
- struct timer_list gc; /* garbage collection when timeout enabled */
- struct mtype_elem next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_MULTI
u8 ahash_max; /* max elements in an array block */
#endif
#ifdef IP_SET_HASH_WITH_NETMASK
u8 netmask; /* netmask value for subnets to store */
#endif
+ struct mtype_elem next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_NETS
- struct net_prefixes nets[0]; /* book-keeping of prefixes */
+ struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */
#endif
};
-#endif /* htype */
#ifdef IP_SET_HASH_WITH_NETS
/* Network cidr size book keeping when the hash stores different
* sized networks. cidr == real cidr + 1 to support /0.
*/
static void
-mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
+mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
{
int i, j;
/* Add in increasing prefix order, so larger cidr first */
- for (i = 0, j = -1; i < nets_length && h->nets[i].cidr[n]; i++) {
+ for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) {
if (j != -1) {
continue;
} else if (h->nets[i].cidr[n] < cidr) {
@@ -323,11 +326,11 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
}
static void
-mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
+mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
{
- u8 i, j, net_end = nets_length - 1;
+ u8 i, j, net_end = NLEN - 1;
- for (i = 0; i < nets_length; i++) {
+ for (i = 0; i < NLEN; i++) {
if (h->nets[i].cidr[n] != cidr)
continue;
h->nets[CIDR_POS(cidr)].nets[n]--;
@@ -343,24 +346,9 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
/* Calculate the actual memory size of the set data */
static size_t
-mtype_ahash_memsize(const struct htype *h, const struct htable *t,
- u8 nets_length, size_t dsize)
+mtype_ahash_memsize(const struct htype *h, const struct htable *t)
{
- u32 i;
- struct hbucket *n;
- size_t memsize = sizeof(*h) + sizeof(*t);
-
-#ifdef IP_SET_HASH_WITH_NETS
- memsize += sizeof(struct net_prefixes) * nets_length;
-#endif
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = rcu_dereference_bh(hbucket(t, i));
- if (!n)
- continue;
- memsize += sizeof(struct hbucket) + n->size * dsize;
- }
-
- return memsize;
+ return sizeof(*h) + sizeof(*t);
}
/* Get the ith element from the array block n */
@@ -398,9 +386,10 @@ mtype_flush(struct ip_set *set)
kfree_rcu(n, rcu);
}
#ifdef IP_SET_HASH_WITH_NETS
- memset(h->nets, 0, sizeof(struct net_prefixes) * NLEN(set->family));
+ memset(h->nets, 0, sizeof(h->nets));
#endif
- h->elements = 0;
+ set->elements = 0;
+ set->ext_size = 0;
}
/* Destroy the hashtable part of the set */
@@ -444,11 +433,8 @@ mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
{
struct htype *h = set->data;
- init_timer(&h->gc);
- h->gc.data = (unsigned long)set;
- h->gc.function = gc;
- h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
- add_timer(&h->gc);
+ setup_timer(&h->gc, gc, (unsigned long)set);
+ mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
pr_debug("gc initialized, run in every %u\n",
IPSET_GC_PERIOD(set->timeout));
}
@@ -473,12 +459,13 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
/* Delete expired elements from the hashtable */
static void
-mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
+mtype_expire(struct ip_set *set, struct htype *h)
{
struct htable *t;
struct hbucket *n, *tmp;
struct mtype_elem *data;
u32 i, j, d;
+ size_t dsize = set->dsize;
#ifdef IP_SET_HASH_WITH_NETS
u8 k;
#endif
@@ -494,21 +481,20 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
continue;
}
data = ahash_data(n, j, dsize);
- if (ip_set_timeout_expired(ext_timeout(data, set))) {
- pr_debug("expired %u/%u\n", i, j);
- clear_bit(j, n->used);
- smp_mb__after_atomic();
+ if (!ip_set_timeout_expired(ext_timeout(data, set)))
+ continue;
+ pr_debug("expired %u/%u\n", i, j);
+ clear_bit(j, n->used);
+ smp_mb__after_atomic();
#ifdef IP_SET_HASH_WITH_NETS
- for (k = 0; k < IPSET_NET_COUNT; k++)
- mtype_del_cidr(h,
- NCIDR_PUT(DCIDR_GET(data->cidr,
- k)),
- nets_length, k);
+ for (k = 0; k < IPSET_NET_COUNT; k++)
+ mtype_del_cidr(h,
+ NCIDR_PUT(DCIDR_GET(data->cidr, k)),
+ k);
#endif
- ip_set_ext_destroy(set, data);
- h->elements--;
- d++;
- }
+ ip_set_ext_destroy(set, data);
+ set->elements--;
+ d++;
}
if (d >= AHASH_INIT_SIZE) {
if (d >= n->size) {
@@ -532,6 +518,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
d++;
}
tmp->pos = d;
+ set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
rcu_assign_pointer(hbucket(t, i), tmp);
kfree_rcu(n, rcu);
}
@@ -546,7 +533,7 @@ mtype_gc(unsigned long ul_set)
pr_debug("called\n");
spin_lock_bh(&set->lock);
- mtype_expire(set, h, NLEN(set->family), set->dsize);
+ mtype_expire(set, h);
spin_unlock_bh(&set->lock);
h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
@@ -563,7 +550,7 @@ mtype_resize(struct ip_set *set, bool retried)
struct htype *h = set->data;
struct htable *t, *orig;
u8 htable_bits;
- size_t dsize = set->dsize;
+ size_t extsize, dsize = set->dsize;
#ifdef IP_SET_HASH_WITH_NETS
u8 flags;
struct mtype_elem *tmp;
@@ -606,6 +593,7 @@ retry:
/* There can't be another parallel resizing, but dumping is possible */
atomic_set(&orig->ref, 1);
atomic_inc(&orig->uref);
+ extsize = 0;
pr_debug("attempt to resize set %s from %u to %u, t %p\n",
set->name, orig->htable_bits, htable_bits, orig);
for (i = 0; i < jhash_size(orig->htable_bits); i++) {
@@ -636,6 +624,7 @@ retry:
goto cleanup;
}
m->size = AHASH_INIT_SIZE;
+ extsize = ext_size(AHASH_INIT_SIZE, dsize);
RCU_INIT_POINTER(hbucket(t, key), m);
} else if (m->pos >= m->size) {
struct hbucket *ht;
@@ -655,6 +644,7 @@ retry:
memcpy(ht, m, sizeof(struct hbucket) +
m->size * dsize);
ht->size = m->size + AHASH_INIT_SIZE;
+ extsize += ext_size(AHASH_INIT_SIZE, dsize);
kfree(m);
m = ht;
RCU_INIT_POINTER(hbucket(t, key), ht);
@@ -668,6 +658,7 @@ retry:
}
}
rcu_assign_pointer(h->table, t);
+ set->ext_size = extsize;
spin_unlock_bh(&set->lock);
@@ -715,11 +706,11 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
bool deleted = false, forceadd = false, reuse = false;
u32 key, multi = 0;
- if (h->elements >= h->maxelem) {
+ if (set->elements >= h->maxelem) {
if (SET_WITH_TIMEOUT(set))
/* FIXME: when set is full, we slow down here */
- mtype_expire(set, h, NLEN(set->family), set->dsize);
- if (h->elements >= h->maxelem && SET_WITH_FORCEADD(set))
+ mtype_expire(set, h);
+ if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set))
forceadd = true;
}
@@ -727,20 +718,15 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
key = HKEY(value, h->initval, t->htable_bits);
n = __ipset_dereference_protected(hbucket(t, key), 1);
if (!n) {
- if (forceadd) {
- if (net_ratelimit())
- pr_warn("Set %s is full, maxelem %u reached\n",
- set->name, h->maxelem);
- return -IPSET_ERR_HASH_FULL;
- } else if (h->elements >= h->maxelem) {
+ if (forceadd || set->elements >= h->maxelem)
goto set_full;
- }
old = NULL;
n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize,
GFP_ATOMIC);
if (!n)
return -ENOMEM;
n->size = AHASH_INIT_SIZE;
+ set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
goto copy_elem;
}
for (i = 0; i < n->pos; i++) {
@@ -778,14 +764,14 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
for (i = 0; i < IPSET_NET_COUNT; i++)
mtype_del_cidr(h,
NCIDR_PUT(DCIDR_GET(data->cidr, i)),
- NLEN(set->family), i);
+ i);
#endif
ip_set_ext_destroy(set, data);
- h->elements--;
+ set->elements--;
}
goto copy_data;
}
- if (h->elements >= h->maxelem)
+ if (set->elements >= h->maxelem)
goto set_full;
/* Create a new slot */
if (n->pos >= n->size) {
@@ -804,17 +790,17 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
memcpy(n, old, sizeof(struct hbucket) +
old->size * set->dsize);
n->size = old->size + AHASH_INIT_SIZE;
+ set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
}
copy_elem:
j = n->pos++;
data = ahash_data(n, j, set->dsize);
copy_data:
- h->elements++;
+ set->elements++;
#ifdef IP_SET_HASH_WITH_NETS
for (i = 0; i < IPSET_NET_COUNT; i++)
- mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)),
- NLEN(set->family), i);
+ mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
#endif
memcpy(data, d, sizeof(struct mtype_elem));
overwrite_extensions:
@@ -824,7 +810,7 @@ overwrite_extensions:
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(data, set), ext);
if (SET_WITH_COMMENT(set))
- ip_set_init_comment(ext_comment(data, set), ext);
+ ip_set_init_comment(set, ext_comment(data, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(data, set), ext);
/* Must come last for the case when timed out entry is reused */
@@ -883,11 +869,11 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
smp_mb__after_atomic();
if (i + 1 == n->pos)
n->pos--;
- h->elements--;
+ set->elements--;
#ifdef IP_SET_HASH_WITH_NETS
for (j = 0; j < IPSET_NET_COUNT; j++)
mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)),
- NLEN(set->family), j);
+ j);
#endif
ip_set_ext_destroy(set, data);
@@ -896,6 +882,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
k++;
}
if (n->pos == 0 && k == 0) {
+ set->ext_size -= ext_size(n->size, dsize);
rcu_assign_pointer(hbucket(t, key), NULL);
kfree_rcu(n, rcu);
} else if (k >= AHASH_INIT_SIZE) {
@@ -914,6 +901,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
k++;
}
tmp->pos = k;
+ set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
rcu_assign_pointer(hbucket(t, key), tmp);
kfree_rcu(n, rcu);
}
@@ -957,14 +945,13 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
int i, j = 0;
#endif
u32 key, multi = 0;
- u8 nets_length = NLEN(set->family);
pr_debug("test by nets\n");
- for (; j < nets_length && h->nets[j].cidr[0] && !multi; j++) {
+ for (; j < NLEN && h->nets[j].cidr[0] && !multi; j++) {
#if IPSET_NET_COUNT == 2
mtype_data_reset_elem(d, &orig);
mtype_data_netmask(d, NCIDR_GET(h->nets[j].cidr[0]), false);
- for (k = 0; k < nets_length && h->nets[k].cidr[1] && !multi;
+ for (k = 0; k < NLEN && h->nets[k].cidr[1] && !multi;
k++) {
mtype_data_netmask(d, NCIDR_GET(h->nets[k].cidr[1]),
true);
@@ -1021,7 +1008,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
* try all possible network sizes
*/
for (i = 0; i < IPSET_NET_COUNT; i++)
- if (DCIDR_GET(d->cidr, i) != SET_HOST_MASK(set->family))
+ if (DCIDR_GET(d->cidr, i) != HOST_MASK)
break;
if (i == IPSET_NET_COUNT) {
ret = mtype_test_cidrs(set, d, ext, mext, flags);
@@ -1062,7 +1049,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
rcu_read_lock_bh();
t = rcu_dereference_bh_nfnl(h->table);
- memsize = mtype_ahash_memsize(h, t, NLEN(set->family), set->dsize);
+ memsize = mtype_ahash_memsize(h, t) + set->ext_size;
htable_bits = t->htable_bits;
rcu_read_unlock_bh();
@@ -1083,7 +1070,8 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
goto nla_put_failure;
#endif
if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
- nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)))
+ nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
+ nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
goto nla_put_failure;
if (unlikely(ip_set_put_flags(skb, set)))
goto nla_put_failure;
@@ -1238,41 +1226,35 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
struct htype *h;
struct htable *t;
+ pr_debug("Create set %s with family %s\n",
+ set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
+
#ifndef IP_SET_PROTO_UNDEF
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY;
#endif
-#ifdef IP_SET_HASH_WITH_MARKMASK
- markmask = 0xffffffff;
-#endif
-#ifdef IP_SET_HASH_WITH_NETMASK
- netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
- pr_debug("Create set %s with family %s\n",
- set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
-#endif
-
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL;
+
#ifdef IP_SET_HASH_WITH_MARKMASK
/* Separated condition in order to avoid directive in argument list */
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_MARKMASK)))
return -IPSET_ERR_PROTOCOL;
-#endif
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
+ markmask = 0xffffffff;
+ if (tb[IPSET_ATTR_MARKMASK]) {
+ markmask = ntohl(nla_get_be32(tb[IPSET_ATTR_MARKMASK]));
+ if (markmask == 0)
+ return -IPSET_ERR_INVALID_MARKMASK;
}
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+#endif
#ifdef IP_SET_HASH_WITH_NETMASK
+ netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
if (tb[IPSET_ATTR_NETMASK]) {
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
@@ -1282,33 +1264,21 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
return -IPSET_ERR_INVALID_NETMASK;
}
#endif
-#ifdef IP_SET_HASH_WITH_MARKMASK
- if (tb[IPSET_ATTR_MARKMASK]) {
- markmask = ntohl(nla_get_be32(tb[IPSET_ATTR_MARKMASK]));
- if (markmask == 0)
- return -IPSET_ERR_INVALID_MARKMASK;
+ if (tb[IPSET_ATTR_HASHSIZE]) {
+ hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+ if (hashsize < IPSET_MIMINAL_HASHSIZE)
+ hashsize = IPSET_MIMINAL_HASHSIZE;
}
-#endif
+
+ if (tb[IPSET_ATTR_MAXELEM])
+ maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
hsize = sizeof(*h);
-#ifdef IP_SET_HASH_WITH_NETS
- hsize += sizeof(struct net_prefixes) * NLEN(set->family);
-#endif
h = kzalloc(hsize, GFP_KERNEL);
if (!h)
return -ENOMEM;
- h->maxelem = maxelem;
-#ifdef IP_SET_HASH_WITH_NETMASK
- h->netmask = netmask;
-#endif
-#ifdef IP_SET_HASH_WITH_MARKMASK
- h->markmask = markmask;
-#endif
- get_random_bytes(&h->initval, sizeof(h->initval));
- set->timeout = IPSET_NO_TIMEOUT;
-
hbits = htable_bits(hashsize);
hsize = htable_size(hbits);
if (hsize == 0) {
@@ -1320,8 +1290,17 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
kfree(h);
return -ENOMEM;
}
+ h->maxelem = maxelem;
+#ifdef IP_SET_HASH_WITH_NETMASK
+ h->netmask = netmask;
+#endif
+#ifdef IP_SET_HASH_WITH_MARKMASK
+ h->markmask = markmask;
+#endif
+ get_random_bytes(&h->initval, sizeof(h->initval));
+
t->htable_bits = hbits;
- rcu_assign_pointer(h->table, t);
+ RCU_INIT_POINTER(h->table, t);
set->data = h;
#ifndef IP_SET_PROTO_UNDEF
@@ -1339,6 +1318,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
__alignof__(struct IPSET_TOKEN(HTYPE, 6_elem)));
}
#endif
+ set->timeout = IPSET_NO_TIMEOUT;
if (tb[IPSET_ATTR_TIMEOUT]) {
set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
#ifndef IP_SET_PROTO_UNDEF
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index 9d6bf19f7b78..20bfbd315f61 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -82,7 +82,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ip *h = set->data;
+ const struct hash_ip4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip4_elem e = { 0 };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -101,7 +101,7 @@ static int
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ip *h = set->data;
+ const struct hash_ip4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip4_elem e = { 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -199,7 +199,7 @@ nla_put_failure:
}
static inline void
-hash_ip6_data_next(struct hash_ip4_elem *next, const struct hash_ip6_elem *e)
+hash_ip6_data_next(struct hash_ip6_elem *next, const struct hash_ip6_elem *e)
{
}
@@ -217,7 +217,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ip *h = set->data;
+ const struct hash_ip6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip6_elem e = { { .all = { 0 } } };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -234,7 +234,7 @@ static int
hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ip *h = set->data;
+ const struct hash_ip6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip6_elem e = { { .all = { 0 } } };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_ipmac.c b/net/netfilter/ipset/ip_set_hash_ipmac.c
new file mode 100644
index 000000000000..1ab5ed2f6839
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipmac.c
@@ -0,0 +1,315 @@
+/* Copyright (C) 2016 Tomasz Chilinski <tomasz.chilinski@chilan.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.
+ */
+
+/* Kernel module implementing an IP set type: the hash:ip,mac type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/if_ether.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+#define IPSET_TYPE_REV_MIN 0
+#define IPSET_TYPE_REV_MAX 0
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomasz Chilinski <tomasz.chilinski@chilan.com>");
+IP_SET_MODULE_DESC("hash:ip,mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
+MODULE_ALIAS("ip_set_hash:ip,mac");
+
+/* Type specific function prefix */
+#define HTYPE hash_ipmac
+
+/* Zero valued element is not supported */
+static const unsigned char invalid_ether[ETH_ALEN] = { 0 };
+
+/* IPv4 variant */
+
+/* Member elements */
+struct hash_ipmac4_elem {
+ /* Zero valued IP addresses cannot be stored */
+ __be32 ip;
+ union {
+ unsigned char ether[ETH_ALEN];
+ __be32 foo[2];
+ };
+};
+
+/* Common functions */
+
+static inline bool
+hash_ipmac4_data_equal(const struct hash_ipmac4_elem *e1,
+ const struct hash_ipmac4_elem *e2,
+ u32 *multi)
+{
+ return e1->ip == e2->ip && ether_addr_equal(e1->ether, e2->ether);
+}
+
+static bool
+hash_ipmac4_data_list(struct sk_buff *skb, const struct hash_ipmac4_elem *e)
+{
+ if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, e->ip) ||
+ nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether))
+ goto nla_put_failure;
+ return false;
+
+nla_put_failure:
+ return true;
+}
+
+static inline void
+hash_ipmac4_data_next(struct hash_ipmac4_elem *next,
+ const struct hash_ipmac4_elem *e)
+{
+ next->ip = e->ip;
+}
+
+#define MTYPE hash_ipmac4
+#define PF 4
+#define HOST_MASK 32
+#define HKEY_DATALEN sizeof(struct hash_ipmac4_elem)
+#include "ip_set_hash_gen.h"
+
+static int
+hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+ enum ipset_adt adt, struct ip_set_adt_opt *opt)
+{
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
+ struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
+
+ /* MAC can be src only */
+ if (!(opt->flags & IPSET_DIM_TWO_SRC))
+ return 0;
+
+ if (skb_mac_header(skb) < skb->head ||
+ (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+ return -EINVAL;
+
+ memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
+ if (ether_addr_equal(e.ether, invalid_ether))
+ return -EINVAL;
+
+ ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
+
+ return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
+}
+
+static int
+hash_ipmac4_uadt(struct ip_set *set, struct nlattr *tb[],
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ int ret;
+
+ if (unlikely(!tb[IPSET_ATTR_IP] ||
+ !tb[IPSET_ATTR_ETHER] ||
+ nla_len(tb[IPSET_ATTR_ETHER]) != ETH_ALEN ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
+ return -IPSET_ERR_PROTOCOL;
+
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+ ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) ||
+ ip_set_get_extensions(set, tb, &ext);
+ if (ret)
+ return ret;
+ memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
+ if (ether_addr_equal(e.ether, invalid_ether))
+ return -IPSET_ERR_HASH_ELEM;
+
+ return adtfn(set, &e, &ext, &ext, flags);
+}
+
+/* IPv6 variant */
+
+/* Member elements */
+struct hash_ipmac6_elem {
+ /* Zero valued IP addresses cannot be stored */
+ union nf_inet_addr ip;
+ union {
+ unsigned char ether[ETH_ALEN];
+ __be32 foo[2];
+ };
+};
+
+/* Common functions */
+
+static inline bool
+hash_ipmac6_data_equal(const struct hash_ipmac6_elem *e1,
+ const struct hash_ipmac6_elem *e2,
+ u32 *multi)
+{
+ return ipv6_addr_equal(&e1->ip.in6, &e2->ip.in6) &&
+ ether_addr_equal(e1->ether, e2->ether);
+}
+
+static bool
+hash_ipmac6_data_list(struct sk_buff *skb, const struct hash_ipmac6_elem *e)
+{
+ if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
+ nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether))
+ goto nla_put_failure;
+ return false;
+
+nla_put_failure:
+ return true;
+}
+
+static inline void
+hash_ipmac6_data_next(struct hash_ipmac6_elem *next,
+ const struct hash_ipmac6_elem *e)
+{
+}
+
+#undef MTYPE
+#undef PF
+#undef HOST_MASK
+#undef HKEY_DATALEN
+
+#define MTYPE hash_ipmac6
+#define PF 6
+#define HOST_MASK 128
+#define HKEY_DATALEN sizeof(struct hash_ipmac6_elem)
+#define IP_SET_EMIT_CREATE
+#include "ip_set_hash_gen.h"
+
+static int
+hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
+ const struct xt_action_param *par,
+ enum ipset_adt adt, struct ip_set_adt_opt *opt)
+{
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_ipmac6_elem e = {
+ { .all = { 0 } },
+ { .foo[0] = 0, .foo[1] = 0 }
+ };
+ struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
+
+ /* MAC can be src only */
+ if (!(opt->flags & IPSET_DIM_TWO_SRC))
+ return 0;
+
+ if (skb_mac_header(skb) < skb->head ||
+ (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+ return -EINVAL;
+
+ memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
+ if (ether_addr_equal(e.ether, invalid_ether))
+ return -EINVAL;
+
+ ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
+
+ return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
+}
+
+static int
+hash_ipmac6_uadt(struct ip_set *set, struct nlattr *tb[],
+ enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct hash_ipmac6_elem e = {
+ { .all = { 0 } },
+ { .foo[0] = 0, .foo[1] = 0 }
+ };
+ struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
+ int ret;
+
+ if (unlikely(!tb[IPSET_ATTR_IP] ||
+ !tb[IPSET_ATTR_ETHER] ||
+ nla_len(tb[IPSET_ATTR_ETHER]) != ETH_ALEN ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
+ !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
+ return -IPSET_ERR_PROTOCOL;
+
+ if (tb[IPSET_ATTR_LINENO])
+ *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+ ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
+ ip_set_get_extensions(set, tb, &ext);
+ if (ret)
+ return ret;
+
+ memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
+ if (ether_addr_equal(e.ether, invalid_ether))
+ return -IPSET_ERR_HASH_ELEM;
+
+ return adtfn(set, &e, &ext, &ext, flags);
+}
+
+static struct ip_set_type hash_ipmac_type __read_mostly = {
+ .name = "hash:ip,mac",
+ .protocol = IPSET_PROTOCOL,
+ .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
+ .dimension = IPSET_DIM_TWO,
+ .family = NFPROTO_UNSPEC,
+ .revision_min = IPSET_TYPE_REV_MIN,
+ .revision_max = IPSET_TYPE_REV_MAX,
+ .create = hash_ipmac_create,
+ .create_policy = {
+ [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
+ [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
+ [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
+ [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
+ [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
+ [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
+ },
+ .adt_policy = {
+ [IPSET_ATTR_IP] = { .type = NLA_NESTED },
+ [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
+ .len = ETH_ALEN },
+ [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
+ [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
+ [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
+ [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
+ [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
+ [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
+ [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
+ [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
+ },
+ .me = THIS_MODULE,
+};
+
+static int __init
+hash_ipmac_init(void)
+{
+ return ip_set_type_register(&hash_ipmac_type);
+}
+
+static void __exit
+hash_ipmac_fini(void)
+{
+ ip_set_type_unregister(&hash_ipmac_type);
+}
+
+module_init(hash_ipmac_init);
+module_exit(hash_ipmac_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c
index a0695a2ab585..b64cf14e8352 100644
--- a/net/netfilter/ipset/ip_set_hash_ipmark.c
+++ b/net/netfilter/ipset/ip_set_hash_ipmark.c
@@ -85,7 +85,7 @@ hash_ipmark4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ipmark *h = set->data;
+ const struct hash_ipmark4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipmark4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -101,7 +101,7 @@ static int
hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipmark *h = set->data;
+ const struct hash_ipmark4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipmark4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -193,7 +193,7 @@ nla_put_failure:
}
static inline void
-hash_ipmark6_data_next(struct hash_ipmark4_elem *next,
+hash_ipmark6_data_next(struct hash_ipmark6_elem *next,
const struct hash_ipmark6_elem *d)
{
}
@@ -211,7 +211,7 @@ hash_ipmark6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ipmark *h = set->data;
+ const struct hash_ipmark6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipmark6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -227,7 +227,7 @@ static int
hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipmark *h = set->data;
+ const struct hash_ipmark6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipmark6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index 9d84b3dff603..f438740e6c6a 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -108,7 +108,7 @@ static int
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipport *h = set->data;
+ const struct hash_ipport4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem e = { .ip = 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -231,7 +231,7 @@ nla_put_failure:
}
static inline void
-hash_ipport6_data_next(struct hash_ipport4_elem *next,
+hash_ipport6_data_next(struct hash_ipport6_elem *next,
const struct hash_ipport6_elem *d)
{
next->port = d->port;
@@ -266,7 +266,7 @@ static int
hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipport *h = set->data;
+ const struct hash_ipport6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem e = { .ip = { .all = { 0 } } };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 215b7b942038..6215fb898c50 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -111,7 +111,7 @@ static int
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportip *h = set->data;
+ const struct hash_ipportip4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem e = { .ip = 0 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -241,7 +241,7 @@ nla_put_failure:
}
static inline void
-hash_ipportip6_data_next(struct hash_ipportip4_elem *next,
+hash_ipportip6_data_next(struct hash_ipportip6_elem *next,
const struct hash_ipportip6_elem *d)
{
next->port = d->port;
@@ -277,7 +277,7 @@ static int
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportip *h = set->data;
+ const struct hash_ipportip6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem e = { .ip = { .all = { 0 } } };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 9ca719625ea3..5ab1b99a53c2 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -138,7 +138,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ipportnet *h = set->data;
+ const struct hash_ipportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -163,7 +163,7 @@ static int
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportnet *h = set->data;
+ const struct hash_ipportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -370,7 +370,7 @@ nla_put_failure:
}
static inline void
-hash_ipportnet6_data_next(struct hash_ipportnet4_elem *next,
+hash_ipportnet6_data_next(struct hash_ipportnet6_elem *next,
const struct hash_ipportnet6_elem *d)
{
next->port = d->port;
@@ -389,7 +389,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_ipportnet *h = set->data;
+ const struct hash_ipportnet6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet6_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -414,7 +414,7 @@ static int
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_ipportnet *h = set->data;
+ const struct hash_ipportnet6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 3e4bffdc1cc0..5d9e895452e7 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -117,7 +117,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_net *h = set->data;
+ const struct hash_net4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net4_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -139,7 +139,7 @@ static int
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_net *h = set->data;
+ const struct hash_net4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net4_elem e = { .cidr = HOST_MASK };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -268,7 +268,7 @@ nla_put_failure:
}
static inline void
-hash_net6_data_next(struct hash_net4_elem *next,
+hash_net6_data_next(struct hash_net6_elem *next,
const struct hash_net6_elem *d)
{
}
@@ -286,7 +286,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_net *h = set->data;
+ const struct hash_net6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net6_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index f0f688db6213..44cf11939c91 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -156,7 +156,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- struct hash_netiface *h = set->data;
+ struct hash_netiface4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -170,7 +170,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
e.ip &= ip_set_netmask(e.cidr);
-#define IFACE(dir) (par->dir ? par->dir->name : "")
+#define IFACE(dir) (par->state->dir ? par->state->dir->name : "")
#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
@@ -196,7 +196,7 @@ static int
hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- struct hash_netiface *h = set->data;
+ struct hash_netiface4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -348,7 +348,7 @@ nla_put_failure:
}
static inline void
-hash_netiface6_data_next(struct hash_netiface4_elem *next,
+hash_netiface6_data_next(struct hash_netiface6_elem *next,
const struct hash_netiface6_elem *d)
{
}
@@ -367,7 +367,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- struct hash_netiface *h = set->data;
+ struct hash_netiface6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface6_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
index a93dfebffa81..db614e13b193 100644
--- a/net/netfilter/ipset/ip_set_hash_netnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netnet.c
@@ -143,7 +143,7 @@ hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netnet *h = set->data;
+ const struct hash_netnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -165,7 +165,7 @@ static int
hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netnet *h = set->data;
+ const struct hash_netnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -352,7 +352,7 @@ nla_put_failure:
}
static inline void
-hash_netnet6_data_next(struct hash_netnet4_elem *next,
+hash_netnet6_data_next(struct hash_netnet6_elem *next,
const struct hash_netnet6_elem *d)
{
}
@@ -377,7 +377,7 @@ hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netnet *h = set->data;
+ const struct hash_netnet6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index 731813e0f08c..54b64b6cd0cd 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -133,7 +133,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netport *h = set->data;
+ const struct hash_netport4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport4_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -157,7 +157,7 @@ static int
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netport *h = set->data;
+ const struct hash_netport4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -329,7 +329,7 @@ nla_put_failure:
}
static inline void
-hash_netport6_data_next(struct hash_netport4_elem *next,
+hash_netport6_data_next(struct hash_netport6_elem *next,
const struct hash_netport6_elem *d)
{
next->port = d->port;
@@ -348,7 +348,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netport *h = set->data;
+ const struct hash_netport6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport6_elem e = {
.cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
@@ -372,7 +372,7 @@ static int
hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netport *h = set->data;
+ const struct hash_netport6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport6_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
index 9a14c237830f..aff846960ac4 100644
--- a/net/netfilter/ipset/ip_set_hash_netportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netportnet.c
@@ -154,7 +154,7 @@ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netportnet *h = set->data;
+ const struct hash_netportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -180,7 +180,7 @@ static int
hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netportnet *h = set->data;
+ const struct hash_netportnet4 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
@@ -406,7 +406,7 @@ nla_put_failure:
}
static inline void
-hash_netportnet6_data_next(struct hash_netportnet4_elem *next,
+hash_netportnet6_data_next(struct hash_netportnet6_elem *next,
const struct hash_netportnet6_elem *d)
{
next->port = d->port;
@@ -432,7 +432,7 @@ hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt)
{
- const struct hash_netportnet *h = set->data;
+ const struct hash_netportnet6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
@@ -458,7 +458,7 @@ static int
hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
- const struct hash_netportnet *h = set->data;
+ const struct hash_netportnet6 *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netportnet6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index a2a89e4e0a14..51077c53d76b 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -166,6 +166,7 @@ __list_set_del_rcu(struct rcu_head * rcu)
static inline void
list_set_del(struct ip_set *set, struct set_elem *e)
{
+ set->elements--;
list_del_rcu(&e->list);
call_rcu(&e->rcu, __list_set_del_rcu);
}
@@ -227,7 +228,7 @@ list_set_init_extensions(struct ip_set *set, const struct ip_set_ext *ext,
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(e, set), ext);
if (SET_WITH_COMMENT(set))
- ip_set_init_comment(ext_comment(e, set), ext);
+ ip_set_init_comment(set, ext_comment(e, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(e, set), ext);
/* Update timeout last */
@@ -309,6 +310,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
list_add_rcu(&e->list, &prev->list);
else
list_add_tail_rcu(&e->list, &map->members);
+ set->elements++;
return 0;
}
@@ -419,6 +421,8 @@ list_set_flush(struct ip_set *set)
list_for_each_entry_safe(e, n, &map->members, list)
list_set_del(set, e);
+ set->elements = 0;
+ set->ext_size = 0;
}
static void
@@ -441,12 +445,12 @@ list_set_destroy(struct ip_set *set)
set->data = NULL;
}
-static int
-list_set_head(struct ip_set *set, struct sk_buff *skb)
+/* Calculate the actual memory size of the set data */
+static size_t
+list_set_memsize(const struct list_set *map, size_t dsize)
{
- const struct list_set *map = set->data;
- struct nlattr *nested;
struct set_elem *e;
+ size_t memsize;
u32 n = 0;
rcu_read_lock();
@@ -454,13 +458,25 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
n++;
rcu_read_unlock();
+ memsize = sizeof(*map) + n * dsize;
+
+ return memsize;
+}
+
+static int
+list_set_head(struct ip_set *set, struct sk_buff *skb)
+{
+ const struct list_set *map = set->data;
+ struct nlattr *nested;
+ size_t memsize = list_set_memsize(map, set->dsize) + set->ext_size;
+
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested)
goto nla_put_failure;
if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) ||
nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
- nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
- htonl(sizeof(*map) + n * set->dsize)))
+ nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
+ nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
goto nla_put_failure;
if (unlikely(ip_set_put_flags(skb, set)))
goto nla_put_failure;
@@ -570,11 +586,8 @@ list_set_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
{
struct list_set *map = set->data;
- init_timer(&map->gc);
- map->gc.data = (unsigned long)set;
- map->gc.function = gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
- add_timer(&map->gc);
+ setup_timer(&map->gc, gc, (unsigned long)set);
+ mod_timer(&map->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
}
/* Create list:set type of sets */
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 2c1b498a7a27..db40050f8785 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -70,7 +70,7 @@ EXPORT_SYMBOL(ip_vs_get_debug_level);
#endif
EXPORT_SYMBOL(ip_vs_new_conn_out);
-static int ip_vs_net_id __read_mostly;
+static unsigned int ip_vs_net_id __read_mostly;
/* netns cnt used for uniqueness */
static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index a6e44ef2ec9a..3d02b0c13547 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2840,14 +2840,7 @@ static struct nf_sockopt_ops ip_vs_sockopts = {
*/
/* IPVS genetlink family */
-static struct genl_family ip_vs_genl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = IPVS_GENL_NAME,
- .version = IPVS_GENL_VERSION,
- .maxattr = IPVS_CMD_ATTR_MAX,
- .netnsok = true, /* Make ipvsadm to work on netns */
-};
+static struct genl_family ip_vs_genl_family;
/* Policy used for first-level command attributes */
static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = {
@@ -3267,7 +3260,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
svc = ip_vs_genl_find_service(ipvs, attrs[IPVS_CMD_ATTR_SERVICE]);
- if (IS_ERR(svc) || svc == NULL)
+ if (IS_ERR_OR_NULL(svc))
goto out_err;
/* Dump the destinations */
@@ -3872,10 +3865,20 @@ static const struct genl_ops ip_vs_genl_ops[] = {
},
};
+static struct genl_family ip_vs_genl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = IPVS_GENL_NAME,
+ .version = IPVS_GENL_VERSION,
+ .maxattr = IPVS_CMD_ATTR_MAX,
+ .netnsok = true, /* Make ipvsadm to work on netns */
+ .module = THIS_MODULE,
+ .ops = ip_vs_genl_ops,
+ .n_ops = ARRAY_SIZE(ip_vs_genl_ops),
+};
+
static int __init ip_vs_genl_register(void)
{
- return genl_register_family_with_ops(&ip_vs_genl_family,
- ip_vs_genl_ops);
+ return genl_register_family(&ip_vs_genl_family);
}
static void ip_vs_genl_unregister(void)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 01d3d894de46..4e1a98fcc8c3 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -254,6 +254,54 @@ static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
return true;
}
+static inline bool decrement_ttl(struct netns_ipvs *ipvs,
+ int skb_af,
+ struct sk_buff *skb)
+{
+ struct net *net = ipvs->net;
+
+#ifdef CONFIG_IP_VS_IPV6
+ if (skb_af == AF_INET6) {
+ struct dst_entry *dst = skb_dst(skb);
+
+ /* check and decrement ttl */
+ if (ipv6_hdr(skb)->hop_limit <= 1) {
+ /* Force OUTPUT device used as source address */
+ skb->dev = dst->dev;
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0);
+ __IP6_INC_STATS(net, ip6_dst_idev(dst),
+ IPSTATS_MIB_INHDRERRORS);
+
+ return false;
+ }
+
+ /* don't propagate ttl change to cloned packets */
+ if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
+ return false;
+
+ ipv6_hdr(skb)->hop_limit--;
+ } else
+#endif
+ {
+ if (ip_hdr(skb)->ttl <= 1) {
+ /* Tell the sender its packet died... */
+ __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
+ icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+ return false;
+ }
+
+ /* don't propagate ttl change to cloned packets */
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
+ return false;
+
+ /* Decrease ttl */
+ ip_decrease_ttl(ip_hdr(skb));
+ }
+
+ return true;
+}
+
/* Get route to destination or remote server */
static int
__ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
@@ -326,6 +374,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
return local;
}
+ if (!decrement_ttl(ipvs, skb_af, skb))
+ goto err_put;
+
if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
mtu = dst_mtu(&rt->dst);
} else {
@@ -473,6 +524,9 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
return local;
}
+ if (!decrement_ttl(ipvs, skb_af, skb))
+ goto err_put;
+
/* MTU checking */
if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
mtu = dst_mtu(&rt->dst);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0f87e5d21be7..6a0bbfa8e702 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1338,7 +1338,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
if (skb->nfct)
goto out;
}
-
+repeat:
ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
l3proto, l4proto, &set_reply, &ctinfo);
if (!ct) {
@@ -1370,6 +1370,12 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
NF_CT_STAT_INC_ATOMIC(net, invalid);
if (ret == -NF_DROP)
NF_CT_STAT_INC_ATOMIC(net, drop);
+ /* Special case: TCP tracker reports an attempt to reopen a
+ * closed/aborted connection. We have to go back and create a
+ * fresh conntrack.
+ */
+ if (ret == -NF_REPEAT)
+ goto repeat;
ret = -ret;
goto out;
}
@@ -1377,15 +1383,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
nf_conntrack_event_cache(IPCT_REPLY, ct);
out:
- if (tmpl) {
- /* Special case: we have to repeat this hook, assign the
- * template again to this packet. We assume that this packet
- * has no conntrack assigned. This is used by nf_ct_tcp. */
- if (ret == NF_REPEAT)
- skb->nfct = (struct nf_conntrack *)tmpl;
- else
- nf_ct_put(tmpl);
- }
+ if (tmpl)
+ nf_ct_put(tmpl);
return ret;
}
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 8d2c7d8c666a..2d6ee1803415 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -125,6 +125,54 @@ void nf_ct_l3proto_module_put(unsigned short l3proto)
}
EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
+int nf_ct_netns_get(struct net *net, u8 nfproto)
+{
+ const struct nf_conntrack_l3proto *l3proto;
+ int ret;
+
+ might_sleep();
+
+ ret = nf_ct_l3proto_try_module_get(nfproto);
+ if (ret < 0)
+ return ret;
+
+ /* we already have a reference, can't fail */
+ rcu_read_lock();
+ l3proto = __nf_ct_l3proto_find(nfproto);
+ rcu_read_unlock();
+
+ if (!l3proto->net_ns_get)
+ return 0;
+
+ ret = l3proto->net_ns_get(net);
+ if (ret < 0)
+ nf_ct_l3proto_module_put(nfproto);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_netns_get);
+
+void nf_ct_netns_put(struct net *net, u8 nfproto)
+{
+ const struct nf_conntrack_l3proto *l3proto;
+
+ might_sleep();
+
+ /* same as nf_conntrack_netns_get(), reference assumed */
+ rcu_read_lock();
+ l3proto = __nf_ct_l3proto_find(nfproto);
+ rcu_read_unlock();
+
+ if (WARN_ON(!l3proto))
+ return;
+
+ if (l3proto->net_ns_put)
+ l3proto->net_ns_put(net);
+
+ nf_ct_l3proto_module_put(nfproto);
+}
+EXPORT_SYMBOL_GPL(nf_ct_netns_put);
+
struct nf_conntrack_l4proto *
nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num)
{
@@ -190,20 +238,19 @@ out_unlock:
}
EXPORT_SYMBOL_GPL(nf_ct_l3proto_register);
+#ifdef CONFIG_SYSCTL
+extern unsigned int nf_conntrack_default_on;
+
int nf_ct_l3proto_pernet_register(struct net *net,
struct nf_conntrack_l3proto *proto)
{
- int ret;
-
- if (proto->init_net) {
- ret = proto->init_net(net);
- if (ret < 0)
- return ret;
- }
+ if (nf_conntrack_default_on == 0)
+ return 0;
- return 0;
+ return proto->net_ns_get ? proto->net_ns_get(net) : 0;
}
EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_register);
+#endif
void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
{
@@ -224,6 +271,16 @@ EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister);
void nf_ct_l3proto_pernet_unregister(struct net *net,
struct nf_conntrack_l3proto *proto)
{
+ /*
+ * nf_conntrack_default_on *might* have registered hooks.
+ * ->net_ns_put must cope with more puts() than get(), i.e.
+ * if nf_conntrack_default_on was 0 at time of
+ * nf_ct_l3proto_pernet_register invocation this net_ns_put()
+ * should be a noop.
+ */
+ if (proto->net_ns_put)
+ proto->net_ns_put(net);
+
/* Remove all contrack entries for this protocol */
nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0);
}
@@ -281,15 +338,15 @@ void nf_ct_l4proto_unregister_sysctl(struct net *net,
/* FIXME: Allow NULL functions and sub in pointers to generic for
them. --RR */
-int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto)
+int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
if (l4proto->l3proto >= PF_MAX)
return -EBUSY;
- if ((l4proto->to_nlattr && !l4proto->nlattr_size)
- || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))
+ if ((l4proto->to_nlattr && !l4proto->nlattr_size) ||
+ (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))
return -EINVAL;
mutex_lock(&nf_ct_proto_mutex);
@@ -307,7 +364,8 @@ int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto)
}
for (i = 0; i < MAX_NF_CT_PROTO; i++)
- RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic);
+ RCU_INIT_POINTER(proto_array[i],
+ &nf_conntrack_l4proto_generic);
/* Before making proto_array visible to lockless readers,
* we must make sure its content is committed to memory.
@@ -335,10 +393,10 @@ out_unlock:
mutex_unlock(&nf_ct_proto_mutex);
return ret;
}
-EXPORT_SYMBOL_GPL(nf_ct_l4proto_register);
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_register_one);
-int nf_ct_l4proto_pernet_register(struct net *net,
- struct nf_conntrack_l4proto *l4proto)
+int nf_ct_l4proto_pernet_register_one(struct net *net,
+ struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
struct nf_proto_net *pn = NULL;
@@ -361,9 +419,9 @@ int nf_ct_l4proto_pernet_register(struct net *net,
out:
return ret;
}
-EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register);
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register_one);
-void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
+void nf_ct_l4proto_unregister_one(struct nf_conntrack_l4proto *l4proto)
{
BUG_ON(l4proto->l3proto >= PF_MAX);
@@ -378,10 +436,10 @@ void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
synchronize_rcu();
}
-EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister);
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister_one);
-void nf_ct_l4proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l4proto *l4proto)
+void nf_ct_l4proto_pernet_unregister_one(struct net *net,
+ struct nf_conntrack_l4proto *l4proto)
{
struct nf_proto_net *pn = NULL;
@@ -395,6 +453,66 @@ void nf_ct_l4proto_pernet_unregister(struct net *net,
/* Remove all contrack entries for this protocol */
nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0);
}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister_one);
+
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto[],
+ unsigned int num_proto)
+{
+ int ret = -EINVAL, ver;
+ unsigned int i;
+
+ for (i = 0; i < num_proto; i++) {
+ ret = nf_ct_l4proto_register_one(l4proto[i]);
+ if (ret < 0)
+ break;
+ }
+ if (i != num_proto) {
+ ver = l4proto[i]->l3proto == PF_INET6 ? 6 : 4;
+ pr_err("nf_conntrack_ipv%d: can't register %s%d proto.\n",
+ ver, l4proto[i]->name, ver);
+ nf_ct_l4proto_unregister(l4proto, i);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_register);
+
+int nf_ct_l4proto_pernet_register(struct net *net,
+ struct nf_conntrack_l4proto *l4proto[],
+ unsigned int num_proto)
+{
+ int ret = -EINVAL;
+ unsigned int i;
+
+ for (i = 0; i < num_proto; i++) {
+ ret = nf_ct_l4proto_pernet_register_one(net, l4proto[i]);
+ if (ret < 0)
+ break;
+ }
+ if (i != num_proto) {
+ pr_err("nf_conntrack_%s%d: pernet registration failed\n",
+ l4proto[i]->name,
+ l4proto[i]->l3proto == PF_INET6 ? 6 : 4);
+ nf_ct_l4proto_pernet_unregister(net, l4proto, i);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register);
+
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[],
+ unsigned int num_proto)
+{
+ while (num_proto-- != 0)
+ nf_ct_l4proto_unregister_one(l4proto[num_proto]);
+}
+EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister);
+
+void nf_ct_l4proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l4proto *l4proto[],
+ unsigned int num_proto)
+{
+ while (num_proto-- != 0)
+ nf_ct_l4proto_pernet_unregister_one(net, l4proto[num_proto]);
+}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister);
int nf_conntrack_proto_pernet_init(struct net *net)
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index a45bee52dccc..b68ce6ac13b3 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -9,7 +9,6 @@
*
*/
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
@@ -384,17 +383,9 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] =
},
};
-/* this module per-net specifics */
-static int dccp_net_id __read_mostly;
-struct dccp_net {
- struct nf_proto_net pn;
- int dccp_loose;
- unsigned int dccp_timeout[CT_DCCP_MAX + 1];
-};
-
-static inline struct dccp_net *dccp_pernet(struct net *net)
+static inline struct nf_dccp_net *dccp_pernet(struct net *net)
{
- return net_generic(net, dccp_net_id);
+ return &net->ct.nf_ct_proto.dccp;
}
static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -424,7 +415,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff, unsigned int *timeouts)
{
struct net *net = nf_ct_net(ct);
- struct dccp_net *dn;
+ struct nf_dccp_net *dn;
struct dccp_hdr _dh, *dh;
const char *msg;
u_int8_t state;
@@ -719,7 +710,7 @@ static int dccp_nlattr_size(void)
static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{
- struct dccp_net *dn = dccp_pernet(net);
+ struct nf_dccp_net *dn = dccp_pernet(net);
unsigned int *timeouts = data;
int i;
@@ -820,7 +811,7 @@ static struct ctl_table dccp_sysctl_table[] = {
#endif /* CONFIG_SYSCTL */
static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
- struct dccp_net *dn)
+ struct nf_dccp_net *dn)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
@@ -850,7 +841,7 @@ static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
static int dccp_init_net(struct net *net, u_int16_t proto)
{
- struct dccp_net *dn = dccp_pernet(net);
+ struct nf_dccp_net *dn = dccp_pernet(net);
struct nf_proto_net *pn = &dn->pn;
if (!pn->users) {
@@ -868,7 +859,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto)
return dccp_kmemdup_sysctl_table(net, pn, dn);
}
-static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
+struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = {
.l3proto = AF_INET,
.l4proto = IPPROTO_DCCP,
.name = "dccp",
@@ -898,11 +889,11 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
.nla_policy = dccp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
- .net_id = &dccp_net_id,
.init_net = dccp_init_net,
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);
-static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
+struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = {
.l3proto = AF_INET6,
.l4proto = IPPROTO_DCCP,
.name = "dccp",
@@ -932,78 +923,6 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
.nla_policy = dccp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
- .net_id = &dccp_net_id,
.init_net = dccp_init_net,
};
-
-static __net_init int dccp_net_init(struct net *net)
-{
- int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &dccp_proto4);
- if (ret < 0) {
- pr_err("nf_conntrack_dccp4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &dccp_proto6);
- if (ret < 0) {
- pr_err("nf_conntrack_dccp6: pernet registration failed.\n");
- goto cleanup_dccp4;
- }
- return 0;
-cleanup_dccp4:
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto4);
-out:
- return ret;
-}
-
-static __net_exit void dccp_net_exit(struct net *net)
-{
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto6);
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto4);
-}
-
-static struct pernet_operations dccp_net_ops = {
- .init = dccp_net_init,
- .exit = dccp_net_exit,
- .id = &dccp_net_id,
- .size = sizeof(struct dccp_net),
-};
-
-static int __init nf_conntrack_proto_dccp_init(void)
-{
- int ret;
-
- ret = register_pernet_subsys(&dccp_net_ops);
- if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&dccp_proto4);
- if (ret < 0)
- goto out_dccp4;
-
- ret = nf_ct_l4proto_register(&dccp_proto6);
- if (ret < 0)
- goto out_dccp6;
-
- return 0;
-out_dccp6:
- nf_ct_l4proto_unregister(&dccp_proto4);
-out_dccp4:
- unregister_pernet_subsys(&dccp_net_ops);
-out_pernet:
- return ret;
-}
-
-static void __exit nf_conntrack_proto_dccp_fini(void)
-{
- nf_ct_l4proto_unregister(&dccp_proto6);
- nf_ct_l4proto_unregister(&dccp_proto4);
- unregister_pernet_subsys(&dccp_net_ops);
-}
-
-module_init(nf_conntrack_proto_dccp_init);
-module_exit(nf_conntrack_proto_dccp_fini);
-
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp6);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 9a715f88b2f1..87bb40a3feb5 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -53,7 +53,7 @@ static unsigned int gre_timeouts[GRE_CT_MAX] = {
[GRE_CT_REPLIED] = 180*HZ,
};
-static int proto_gre_net_id __read_mostly;
+static unsigned int proto_gre_net_id __read_mostly;
struct netns_proto_gre {
struct nf_proto_net nf;
rwlock_t keymap_lock;
@@ -396,7 +396,9 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
static int proto_gre_net_init(struct net *net)
{
int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_gre4);
+
+ ret = nf_ct_l4proto_pernet_register_one(net,
+ &nf_conntrack_l4proto_gre4);
if (ret < 0)
pr_err("nf_conntrack_gre4: pernet registration failed.\n");
return ret;
@@ -404,7 +406,7 @@ static int proto_gre_net_init(struct net *net)
static void proto_gre_net_exit(struct net *net)
{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_gre4);
+ nf_ct_l4proto_pernet_unregister_one(net, &nf_conntrack_l4proto_gre4);
nf_ct_gre_keymap_flush(net);
}
@@ -422,8 +424,7 @@ static int __init nf_ct_proto_gre_init(void)
ret = register_pernet_subsys(&proto_gre_net_ops);
if (ret < 0)
goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4);
+ ret = nf_ct_l4proto_register_one(&nf_conntrack_l4proto_gre4);
if (ret < 0)
goto out_gre4;
@@ -436,7 +437,7 @@ out_pernet:
static void __exit nf_ct_proto_gre_fini(void)
{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_gre4);
+ nf_ct_l4proto_unregister_one(&nf_conntrack_l4proto_gre4);
unregister_pernet_subsys(&proto_gre_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 982ea62606c7..a0efde38da44 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -15,7 +15,6 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/netfilter.h>
-#include <linux/module.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/sctp.h>
@@ -144,15 +143,9 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
}
};
-static int sctp_net_id __read_mostly;
-struct sctp_net {
- struct nf_proto_net pn;
- unsigned int timeouts[SCTP_CONNTRACK_MAX];
-};
-
-static inline struct sctp_net *sctp_pernet(struct net *net)
+static inline struct nf_sctp_net *sctp_pernet(struct net *net)
{
- return net_generic(net, sctp_net_id);
+ return &net->ct.nf_ct_proto.sctp;
}
static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -600,7 +593,7 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{
unsigned int *timeouts = data;
- struct sctp_net *sn = sctp_pernet(net);
+ struct nf_sctp_net *sn = sctp_pernet(net);
int i;
/* set default SCTP timeouts. */
@@ -708,7 +701,7 @@ static struct ctl_table sctp_sysctl_table[] = {
#endif
static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
- struct sctp_net *sn)
+ struct nf_sctp_net *sn)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
@@ -735,7 +728,7 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
static int sctp_init_net(struct net *net, u_int16_t proto)
{
- struct sctp_net *sn = sctp_pernet(net);
+ struct nf_sctp_net *sn = sctp_pernet(net);
struct nf_proto_net *pn = &sn->pn;
if (!pn->users) {
@@ -748,7 +741,7 @@ static int sctp_init_net(struct net *net, u_int16_t proto)
return sctp_kmemdup_sysctl_table(pn, sn);
}
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.l3proto = PF_INET,
.l4proto = IPPROTO_SCTP,
.name = "sctp",
@@ -778,11 +771,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.nla_policy = sctp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
- .net_id = &sctp_net_id,
.init_net = sctp_init_net,
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4);
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.l3proto = PF_INET6,
.l4proto = IPPROTO_SCTP,
.name = "sctp",
@@ -812,81 +805,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#endif
- .net_id = &sctp_net_id,
.init_net = sctp_init_net,
};
-
-static int sctp_net_init(struct net *net)
-{
- int ret = 0;
-
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp4);
- if (ret < 0) {
- pr_err("nf_conntrack_sctp4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp6);
- if (ret < 0) {
- pr_err("nf_conntrack_sctp6: pernet registration failed.\n");
- goto cleanup_sctp4;
- }
- return 0;
-
-cleanup_sctp4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
-out:
- return ret;
-}
-
-static void sctp_net_exit(struct net *net)
-{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
-}
-
-static struct pernet_operations sctp_net_ops = {
- .init = sctp_net_init,
- .exit = sctp_net_exit,
- .id = &sctp_net_id,
- .size = sizeof(struct sctp_net),
-};
-
-static int __init nf_conntrack_proto_sctp_init(void)
-{
- int ret;
-
- ret = register_pernet_subsys(&sctp_net_ops);
- if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp4);
- if (ret < 0)
- goto out_sctp4;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp6);
- if (ret < 0)
- goto out_sctp6;
-
- return 0;
-out_sctp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
-out_sctp4:
- unregister_pernet_subsys(&sctp_net_ops);
-out_pernet:
- return ret;
-}
-
-static void __exit nf_conntrack_proto_sctp_fini(void)
-{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
- unregister_pernet_subsys(&sctp_net_ops);
-}
-
-module_init(nf_conntrack_proto_sctp_init);
-module_exit(nf_conntrack_proto_sctp_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kiran Kumar Immidi");
-MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
-MODULE_ALIAS("ip_conntrack_proto_sctp");
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp6);
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 029206e8dec4..c35f7bf05d8c 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -9,7 +9,6 @@
#include <linux/types.h>
#include <linux/timer.h>
-#include <linux/module.h>
#include <linux/udp.h>
#include <linux/seq_file.h>
#include <linux/skbuff.h>
@@ -24,26 +23,14 @@
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_log.h>
-enum udplite_conntrack {
- UDPLITE_CT_UNREPLIED,
- UDPLITE_CT_REPLIED,
- UDPLITE_CT_MAX
-};
-
static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = {
[UDPLITE_CT_UNREPLIED] = 30*HZ,
[UDPLITE_CT_REPLIED] = 180*HZ,
};
-static int udplite_net_id __read_mostly;
-struct udplite_net {
- struct nf_proto_net pn;
- unsigned int timeouts[UDPLITE_CT_MAX];
-};
-
-static inline struct udplite_net *udplite_pernet(struct net *net)
+static inline struct nf_udplite_net *udplite_pernet(struct net *net)
{
- return net_generic(net, udplite_net_id);
+ return &net->ct.nf_ct_proto.udplite;
}
static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
@@ -178,7 +165,7 @@ static int udplite_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{
unsigned int *timeouts = data;
- struct udplite_net *un = udplite_pernet(net);
+ struct nf_udplite_net *un = udplite_pernet(net);
/* set default timeouts for UDPlite. */
timeouts[UDPLITE_CT_UNREPLIED] = un->timeouts[UDPLITE_CT_UNREPLIED];
@@ -237,7 +224,7 @@ static struct ctl_table udplite_sysctl_table[] = {
#endif /* CONFIG_SYSCTL */
static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn,
- struct udplite_net *un)
+ struct nf_udplite_net *un)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
@@ -257,7 +244,7 @@ static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn,
static int udplite_init_net(struct net *net, u_int16_t proto)
{
- struct udplite_net *un = udplite_pernet(net);
+ struct nf_udplite_net *un = udplite_pernet(net);
struct nf_proto_net *pn = &un->pn;
if (!pn->users) {
@@ -270,7 +257,7 @@ static int udplite_init_net(struct net *net, u_int16_t proto)
return udplite_kmemdup_sysctl_table(pn, un);
}
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
{
.l3proto = PF_INET,
.l4proto = IPPROTO_UDPLITE,
@@ -299,11 +286,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.nla_policy = udplite_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
- .net_id = &udplite_net_id,
.init_net = udplite_init_net,
};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4);
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
{
.l3proto = PF_INET6,
.l4proto = IPPROTO_UDPLITE,
@@ -332,78 +319,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.nla_policy = udplite_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
- .net_id = &udplite_net_id,
.init_net = udplite_init_net,
};
-
-static int udplite_net_init(struct net *net)
-{
- int ret = 0;
-
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udplite4);
- if (ret < 0) {
- pr_err("nf_conntrack_udplite4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udplite6);
- if (ret < 0) {
- pr_err("nf_conntrack_udplite6: pernet registration failed.\n");
- goto cleanup_udplite4;
- }
- return 0;
-
-cleanup_udplite4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite4);
-out:
- return ret;
-}
-
-static void udplite_net_exit(struct net *net)
-{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite4);
-}
-
-static struct pernet_operations udplite_net_ops = {
- .init = udplite_net_init,
- .exit = udplite_net_exit,
- .id = &udplite_net_id,
- .size = sizeof(struct udplite_net),
-};
-
-static int __init nf_conntrack_proto_udplite_init(void)
-{
- int ret;
-
- ret = register_pernet_subsys(&udplite_net_ops);
- if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite4);
- if (ret < 0)
- goto out_udplite4;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite6);
- if (ret < 0)
- goto out_udplite6;
-
- return 0;
-out_udplite6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
-out_udplite4:
- unregister_pernet_subsys(&udplite_net_ops);
-out_pernet:
- return ret;
-}
-
-static void __exit nf_conntrack_proto_udplite_exit(void)
-{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
- unregister_pernet_subsys(&udplite_net_ops);
-}
-
-module_init(nf_conntrack_proto_udplite_init);
-module_exit(nf_conntrack_proto_udplite_exit);
-
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 5f446cd9f3fd..d009ae663453 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -452,6 +452,9 @@ static int log_invalid_proto_max __read_mostly = 255;
/* size the user *wants to set */
static unsigned int nf_conntrack_htable_size_user __read_mostly;
+extern unsigned int nf_conntrack_default_on;
+unsigned int nf_conntrack_default_on __read_mostly = 1;
+
static int
nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -517,6 +520,13 @@ static struct ctl_table nf_ct_sysctl_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "nf_conntrack_default_on",
+ .data = &nf_conntrack_default_on,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
{ }
};
diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c
index 7ec69723940f..c9d7f95768ab 100644
--- a/net/netfilter/nf_dup_netdev.c
+++ b/net/netfilter/nf_dup_netdev.c
@@ -14,24 +14,41 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>
+static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev)
+{
+ if (skb_mac_header_was_set(skb))
+ skb_push(skb, skb->mac_len);
+
+ skb->dev = dev;
+ dev_queue_xmit(skb);
+}
+
+void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)
+{
+ struct net_device *dev;
+
+ dev = dev_get_by_index_rcu(nft_net(pkt), oif);
+ if (!dev) {
+ kfree_skb(pkt->skb);
+ return;
+ }
+
+ nf_do_netdev_egress(pkt->skb, dev);
+}
+EXPORT_SYMBOL_GPL(nf_fwd_netdev_egress);
+
void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
{
struct net_device *dev;
struct sk_buff *skb;
- dev = dev_get_by_index_rcu(pkt->net, oif);
+ dev = dev_get_by_index_rcu(nft_net(pkt), oif);
if (dev == NULL)
return;
skb = skb_clone(pkt->skb, GFP_ATOMIC);
- if (skb == NULL)
- return;
-
- if (skb_mac_header_was_set(skb))
- skb_push(skb, skb->mac_len);
-
- skb->dev = dev;
- dev_queue_xmit(skb);
+ if (skb)
+ nf_do_netdev_egress(skb, dev);
}
EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index 9fdb655f85bc..c46d214d5323 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -11,11 +11,6 @@
#define NFDEBUG(format, args...)
#endif
-
-/* core.c */
-unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
- struct nf_hook_entry **entryp);
-
/* nf_queue.c */
int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
struct nf_hook_entry **entryp, unsigned int verdict);
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c
index 119fe1cb1ea9..dc61399e30be 100644
--- a/net/netfilter/nf_log_common.c
+++ b/net/netfilter/nf_log_common.c
@@ -175,6 +175,34 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
}
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
+/* bridge and netdev logging families share this code. */
+void nf_log_l2packet(struct net *net, u_int8_t pf,
+ __be16 protocol,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *loginfo,
+ const char *prefix)
+{
+ switch (protocol) {
+ case htons(ETH_P_IP):
+ nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
+ loginfo, "%s", prefix);
+ break;
+ case htons(ETH_P_IPV6):
+ nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out,
+ loginfo, "%s", prefix);
+ break;
+ case htons(ETH_P_ARP):
+ case htons(ETH_P_RARP):
+ nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out,
+ loginfo, "%s", prefix);
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(nf_log_l2packet);
+
static int __init nf_log_common_init(void)
{
return 0;
diff --git a/net/netfilter/nf_log_netdev.c b/net/netfilter/nf_log_netdev.c
new file mode 100644
index 000000000000..350eb147754d
--- /dev/null
+++ b/net/netfilter/nf_log_netdev.c
@@ -0,0 +1,81 @@
+/*
+ * (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/route.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_log.h>
+
+static void nf_log_netdev_packet(struct net *net, u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *loginfo,
+ const char *prefix)
+{
+ nf_log_l2packet(net, pf, skb->protocol, hooknum, skb, in, out,
+ loginfo, prefix);
+}
+
+static struct nf_logger nf_netdev_logger __read_mostly = {
+ .name = "nf_log_netdev",
+ .type = NF_LOG_TYPE_LOG,
+ .logfn = nf_log_netdev_packet,
+ .me = THIS_MODULE,
+};
+
+static int __net_init nf_log_netdev_net_init(struct net *net)
+{
+ return nf_log_set(net, NFPROTO_NETDEV, &nf_netdev_logger);
+}
+
+static void __net_exit nf_log_netdev_net_exit(struct net *net)
+{
+ nf_log_unset(net, &nf_netdev_logger);
+}
+
+static struct pernet_operations nf_log_netdev_net_ops = {
+ .init = nf_log_netdev_net_init,
+ .exit = nf_log_netdev_net_exit,
+};
+
+static int __init nf_log_netdev_init(void)
+{
+ int ret;
+
+ /* Request to load the real packet loggers. */
+ nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG);
+ nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG);
+ nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG);
+
+ ret = register_pernet_subsys(&nf_log_netdev_net_ops);
+ if (ret < 0)
+ return ret;
+
+ nf_log_register(NFPROTO_NETDEV, &nf_netdev_logger);
+ return 0;
+}
+
+static void __exit nf_log_netdev_exit(void)
+{
+ unregister_pernet_subsys(&nf_log_netdev_net_ops);
+ nf_log_unregister(&nf_netdev_logger);
+}
+
+module_init(nf_log_netdev_init);
+module_exit(nf_log_netdev_exit);
+
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_DESCRIPTION("Netfilter netdev packet logging");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NF_LOGGER(5, 0); /* NFPROTO_NETDEV */
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 5b9c884a452e..94b14c5a8b17 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -682,6 +682,18 @@ int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto)
&nf_nat_l4proto_tcp);
RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP],
&nf_nat_l4proto_udp);
+#ifdef CONFIG_NF_NAT_PROTO_DCCP
+ RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_DCCP],
+ &nf_nat_l4proto_dccp);
+#endif
+#ifdef CONFIG_NF_NAT_PROTO_SCTP
+ RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_SCTP],
+ &nf_nat_l4proto_sctp);
+#endif
+#ifdef CONFIG_NF_NAT_PROTO_UDPLITE
+ RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDPLITE],
+ &nf_nat_l4proto_udplite);
+#endif
mutex_unlock(&nf_nat_proto_mutex);
RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);
diff --git a/net/netfilter/nf_nat_proto_dccp.c b/net/netfilter/nf_nat_proto_dccp.c
index 15c47b246d0d..269fcd5dc34c 100644
--- a/net/netfilter/nf_nat_proto_dccp.c
+++ b/net/netfilter/nf_nat_proto_dccp.c
@@ -10,8 +10,6 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/dccp.h>
@@ -73,7 +71,7 @@ dccp_manip_pkt(struct sk_buff *skb,
return true;
}
-static const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
+const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
.l4proto = IPPROTO_DCCP,
.manip_pkt = dccp_manip_pkt,
.in_range = nf_nat_l4proto_in_range,
@@ -82,35 +80,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
#endif
};
-
-static int __init nf_nat_proto_dccp_init(void)
-{
- int err;
-
- err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
- if (err < 0)
- goto err1;
- err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
-err1:
- return err;
-}
-
-static void __exit nf_nat_proto_dccp_fini(void)
-{
- nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
-
-}
-
-module_init(nf_nat_proto_dccp_init);
-module_exit(nf_nat_proto_dccp_fini);
-
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("DCCP NAT protocol helper");
-MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c
index cbc7ade1487b..31d358691af0 100644
--- a/net/netfilter/nf_nat_proto_sctp.c
+++ b/net/netfilter/nf_nat_proto_sctp.c
@@ -7,9 +7,7 @@
*/
#include <linux/types.h>
-#include <linux/init.h>
#include <linux/sctp.h>
-#include <linux/module.h>
#include <net/sctp/checksum.h>
#include <net/netfilter/nf_nat_l4proto.h>
@@ -49,12 +47,15 @@ sctp_manip_pkt(struct sk_buff *skb,
hdr->dest = tuple->dst.u.sctp.port;
}
- hdr->checksum = sctp_compute_cksum(skb, hdroff);
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ hdr->checksum = sctp_compute_cksum(skb, hdroff);
+ skb->ip_summed = CHECKSUM_NONE;
+ }
return true;
}
-static const struct nf_nat_l4proto nf_nat_l4proto_sctp = {
+const struct nf_nat_l4proto nf_nat_l4proto_sctp = {
.l4proto = IPPROTO_SCTP,
.manip_pkt = sctp_manip_pkt,
.in_range = nf_nat_l4proto_in_range,
@@ -63,34 +64,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_sctp = {
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
#endif
};
-
-static int __init nf_nat_proto_sctp_init(void)
-{
- int err;
-
- err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
- if (err < 0)
- goto err1;
- err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_sctp);
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
-err1:
- return err;
-}
-
-static void __exit nf_nat_proto_sctp_exit(void)
-{
- nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_sctp);
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
-}
-
-module_init(nf_nat_proto_sctp_init);
-module_exit(nf_nat_proto_sctp_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SCTP NAT protocol helper");
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/netfilter/nf_nat_proto_udplite.c b/net/netfilter/nf_nat_proto_udplite.c
index 58340c97bd83..366bfbfd82a1 100644
--- a/net/netfilter/nf_nat_proto_udplite.c
+++ b/net/netfilter/nf_nat_proto_udplite.c
@@ -8,11 +8,9 @@
*/
#include <linux/types.h>
-#include <linux/init.h>
#include <linux/udp.h>
#include <linux/netfilter.h>
-#include <linux/module.h>
#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_l3proto.h>
#include <net/netfilter/nf_nat_l4proto.h>
@@ -64,7 +62,7 @@ udplite_manip_pkt(struct sk_buff *skb,
return true;
}
-static const struct nf_nat_l4proto nf_nat_l4proto_udplite = {
+const struct nf_nat_l4proto nf_nat_l4proto_udplite = {
.l4proto = IPPROTO_UDPLITE,
.manip_pkt = udplite_manip_pkt,
.in_range = nf_nat_l4proto_in_range,
@@ -73,34 +71,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_udplite = {
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
#endif
};
-
-static int __init nf_nat_proto_udplite_init(void)
-{
- int err;
-
- err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
- if (err < 0)
- goto err1;
- err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_udplite);
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
-err1:
- return err;
-}
-
-static void __exit nf_nat_proto_udplite_fini(void)
-{
- nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_udplite);
- nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
-}
-
-module_init(nf_nat_proto_udplite_init);
-module_exit(nf_nat_proto_udplite_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("UDP-Lite NAT protocol helper");
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 8f08d759844a..4a7662486f44 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -108,7 +108,7 @@ void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry)
}
static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
- unsigned int queuenum)
+ struct nf_hook_entry *hook_entry, unsigned int queuenum)
{
int status = -ENOENT;
struct nf_queue_entry *entry = NULL;
@@ -136,6 +136,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
*entry = (struct nf_queue_entry) {
.skb = skb,
.state = *state,
+ .hook = hook_entry,
.size = sizeof(*entry) + afinfo->route_key_size,
};
@@ -163,8 +164,7 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
struct nf_hook_entry *entry = *entryp;
int ret;
- RCU_INIT_POINTER(state->hook_entries, entry);
- ret = __nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
+ ret = __nf_queue(skb, state, entry, verdict >> NF_VERDICT_QBITS);
if (ret < 0) {
if (ret == -ESRCH &&
(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) {
@@ -177,22 +177,38 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
return 0;
}
+static unsigned int nf_iterate(struct sk_buff *skb,
+ struct nf_hook_state *state,
+ struct nf_hook_entry **entryp)
+{
+ unsigned int verdict;
+
+ do {
+repeat:
+ verdict = nf_hook_entry_hookfn((*entryp), skb, state);
+ if (verdict != NF_ACCEPT) {
+ if (verdict != NF_REPEAT)
+ return verdict;
+ goto repeat;
+ }
+ *entryp = rcu_dereference((*entryp)->next);
+ } while (*entryp);
+
+ return NF_ACCEPT;
+}
+
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
{
- struct nf_hook_entry *hook_entry;
+ struct nf_hook_entry *hook_entry = entry->hook;
struct sk_buff *skb = entry->skb;
const struct nf_afinfo *afinfo;
- struct nf_hook_ops *elem;
int err;
- hook_entry = rcu_dereference(entry->state.hook_entries);
- elem = &hook_entry->ops;
-
nf_queue_entry_release_refs(entry);
/* Continue traversal iff userspace said ok... */
if (verdict == NF_REPEAT)
- verdict = elem->hook(elem->priv, skb, &entry->state);
+ verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state);
if (verdict == NF_ACCEPT) {
afinfo = nf_get_afinfo(entry->state.pf);
@@ -200,8 +216,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
verdict = NF_DROP;
}
- entry->state.thresh = INT_MIN;
-
if (verdict == NF_ACCEPT) {
hook_entry = rcu_dereference(hook_entry->next);
if (hook_entry)
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
index c8a4a48bced9..7c6d1fbe38b9 100644
--- a/net/netfilter/nf_synproxy_core.c
+++ b/net/netfilter/nf_synproxy_core.c
@@ -24,7 +24,7 @@
#include <net/netfilter/nf_conntrack_synproxy.h>
#include <net/netfilter/nf_conntrack_zones.h>
-int synproxy_net_id;
+unsigned int synproxy_net_id;
EXPORT_SYMBOL_GPL(synproxy_net_id);
bool
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index e5194f6f906c..a019a87e58ee 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -22,6 +22,7 @@
#include <net/sock.h>
static LIST_HEAD(nf_tables_expressions);
+static LIST_HEAD(nf_tables_objects);
/**
* nft_register_afinfo - register nf_tables address family info
@@ -110,12 +111,12 @@ static void nft_ctx_init(struct nft_ctx *ctx,
ctx->seq = nlh->nlmsg_seq;
}
-static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,
- u32 size)
+static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
+ int msg_type, u32 size, gfp_t gfp)
{
struct nft_trans *trans;
- trans = kzalloc(sizeof(struct nft_trans) + size, GFP_KERNEL);
+ trans = kzalloc(sizeof(struct nft_trans) + size, gfp);
if (trans == NULL)
return NULL;
@@ -125,6 +126,12 @@ static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,
return trans;
}
+static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
+ int msg_type, u32 size)
+{
+ return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
+}
+
static void nft_trans_destroy(struct nft_trans *trans)
{
list_del(&trans->list);
@@ -304,6 +311,38 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
return err;
}
+static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type,
+ struct nft_object *obj)
+{
+ struct nft_trans *trans;
+
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_obj));
+ if (trans == NULL)
+ return -ENOMEM;
+
+ if (msg_type == NFT_MSG_NEWOBJ)
+ nft_activate_next(ctx->net, obj);
+
+ nft_trans_obj(trans) = obj;
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
+
+ return 0;
+}
+
+static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
+{
+ int err;
+
+ err = nft_trans_obj_add(ctx, NFT_MSG_DELOBJ, obj);
+ if (err < 0)
+ return err;
+
+ nft_deactivate_next(ctx->net, obj);
+ ctx->table->use--;
+
+ return err;
+}
+
/*
* Tables
*/
@@ -688,6 +727,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN);
INIT_LIST_HEAD(&table->chains);
INIT_LIST_HEAD(&table->sets);
+ INIT_LIST_HEAD(&table->objects);
table->flags = flags;
nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
@@ -709,6 +749,7 @@ static int nft_flush_table(struct nft_ctx *ctx)
{
int err;
struct nft_chain *chain, *nc;
+ struct nft_object *obj, *ne;
struct nft_set *set, *ns;
list_for_each_entry(chain, &ctx->table->chains, list) {
@@ -735,6 +776,12 @@ static int nft_flush_table(struct nft_ctx *ctx)
goto out;
}
+ list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
+ err = nft_delobj(ctx, obj);
+ if (err < 0)
+ goto out;
+ }
+
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
if (!nft_is_active_next(ctx->net, chain))
continue;
@@ -2411,6 +2458,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
[NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
[NFTA_SET_USERDATA] = { .type = NLA_BINARY,
.len = NFT_USERDATA_MAXLEN },
+ [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
};
static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2462,6 +2510,7 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
}
return ERR_PTR(-ENOENT);
}
+EXPORT_SYMBOL_GPL(nf_tables_set_lookup);
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
const struct nlattr *nla,
@@ -2480,6 +2529,7 @@ struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
}
return ERR_PTR(-ENOENT);
}
+EXPORT_SYMBOL_GPL(nf_tables_set_lookup_byid);
static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
const char *name)
@@ -2568,6 +2618,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))
goto nla_put_failure;
}
+ if (set->flags & NFT_SET_OBJECT &&
+ nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype)))
+ goto nla_put_failure;
if (set->timeout &&
nla_put_be64(skb, NFTA_SET_TIMEOUT,
@@ -2797,7 +2850,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
unsigned int size;
bool create;
u64 timeout;
- u32 ktype, dtype, flags, policy, gc_int;
+ u32 ktype, dtype, flags, policy, gc_int, objtype;
struct nft_set_desc desc;
unsigned char *udata;
u16 udlen;
@@ -2827,11 +2880,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
- NFT_SET_MAP | NFT_SET_EVAL))
+ NFT_SET_MAP | NFT_SET_EVAL |
+ NFT_SET_OBJECT))
return -EINVAL;
- /* Only one of both operations is supported */
- if ((flags & (NFT_SET_MAP | NFT_SET_EVAL)) ==
- (NFT_SET_MAP | NFT_SET_EVAL))
+ /* Only one of these operations is supported */
+ if ((flags & (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT)) ==
+ (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT))
return -EOPNOTSUPP;
}
@@ -2856,6 +2910,19 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
} else if (flags & NFT_SET_MAP)
return -EINVAL;
+ if (nla[NFTA_SET_OBJ_TYPE] != NULL) {
+ if (!(flags & NFT_SET_OBJECT))
+ return -EINVAL;
+
+ objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
+ if (objtype == NFT_OBJECT_UNSPEC ||
+ objtype > NFT_OBJECT_MAX)
+ return -EINVAL;
+ } else if (flags & NFT_SET_OBJECT)
+ return -EINVAL;
+ else
+ objtype = NFT_OBJECT_UNSPEC;
+
timeout = 0;
if (nla[NFTA_SET_TIMEOUT] != NULL) {
if (!(flags & NFT_SET_TIMEOUT))
@@ -2943,6 +3010,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
set->ktype = ktype;
set->klen = desc.klen;
set->dtype = dtype;
+ set->objtype = objtype;
set->dlen = desc.dlen;
set->flags = flags;
set->size = desc.size;
@@ -3064,6 +3132,7 @@ bind:
list_add_tail_rcu(&binding->list, &set->bindings);
return 0;
}
+EXPORT_SYMBOL_GPL(nf_tables_bind_set);
void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_binding *binding)
@@ -3074,6 +3143,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
nft_is_active(ctx->net, set))
nf_tables_set_destroy(ctx, set);
}
+EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
const struct nft_set_ext_type nft_set_ext_types[] = {
[NFT_SET_EXT_KEY] = {
@@ -3085,6 +3155,10 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
[NFT_SET_EXT_EXPR] = {
.align = __alignof__(struct nft_expr),
},
+ [NFT_SET_EXT_OBJREF] = {
+ .len = sizeof(struct nft_object *),
+ .align = __alignof__(struct nft_object *),
+ },
[NFT_SET_EXT_FLAGS] = {
.len = sizeof(u8),
.align = __alignof__(u8),
@@ -3173,6 +3247,11 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0)
goto nla_put_failure;
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
+ nla_put_string(skb, NFTA_SET_ELEM_OBJREF,
+ (*nft_set_ext_obj(ext))->name) < 0)
+ goto nla_put_failure;
+
if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
nla_put_be32(skb, NFTA_SET_ELEM_FLAGS,
htonl(*nft_set_ext_flags(ext))))
@@ -3467,7 +3546,8 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
nft_data_uninit(nft_set_ext_data(ext), set->dtype);
if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
-
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
+ (*nft_set_ext_obj(ext))->use--;
kfree(elem);
}
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
@@ -3492,11 +3572,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
const struct nlattr *attr, u32 nlmsg_flags)
{
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
+ u8 genmask = nft_genmask_next(ctx->net);
struct nft_data_desc d1, d2;
struct nft_set_ext_tmpl tmpl;
struct nft_set_ext *ext, *ext2;
struct nft_set_elem elem;
struct nft_set_binding *binding;
+ struct nft_object *obj = NULL;
struct nft_userdata *udata;
struct nft_data data;
enum nft_registers dreg;
@@ -3559,6 +3641,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
}
+ if (nla[NFTA_SET_ELEM_OBJREF] != NULL) {
+ if (!(set->flags & NFT_SET_OBJECT)) {
+ err = -EINVAL;
+ goto err2;
+ }
+ obj = nf_tables_obj_lookup(ctx->table, nla[NFTA_SET_ELEM_OBJREF],
+ set->objtype, genmask);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto err2;
+ }
+ nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
+ }
+
if (nla[NFTA_SET_ELEM_DATA] != NULL) {
err = nft_data_init(ctx, &data, sizeof(data), &d2,
nla[NFTA_SET_ELEM_DATA]);
@@ -3617,6 +3713,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
udata->len = ulen - 1;
nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
}
+ if (obj) {
+ *nft_set_ext_obj(ext) = obj;
+ obj->use++;
+ }
trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
if (trans == NULL)
@@ -3626,10 +3726,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
err = set->ops->insert(ctx->net, set, &elem, &ext2);
if (err) {
if (err == -EEXIST) {
- if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
- nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
- memcmp(nft_set_ext_data(ext),
- nft_set_ext_data(ext2), set->dlen) != 0)
+ if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
+ nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
+ memcmp(nft_set_ext_data(ext),
+ nft_set_ext_data(ext2), set->dlen) != 0) ||
+ (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
+ nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) &&
+ *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2)))
err = -EBUSY;
else if (!(nlmsg_flags & NLM_F_EXCL))
err = 0;
@@ -3779,6 +3882,34 @@ err1:
return err;
}
+static int nft_flush_set(const struct nft_ctx *ctx,
+ const struct nft_set *set,
+ const struct nft_set_iter *iter,
+ const struct nft_set_elem *elem)
+{
+ struct nft_trans *trans;
+ int err;
+
+ trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
+ sizeof(struct nft_trans_elem), GFP_ATOMIC);
+ if (!trans)
+ return -ENOMEM;
+
+ if (!set->ops->deactivate_one(ctx->net, set, elem->priv)) {
+ err = -ENOENT;
+ goto err1;
+ }
+
+ nft_trans_elem_set(trans) = (struct nft_set *)set;
+ nft_trans_elem(trans) = *((struct nft_set_elem *)elem);
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
+
+ return 0;
+err1:
+ kfree(trans);
+ return err;
+}
+
static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[])
@@ -3789,9 +3920,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
struct nft_ctx ctx;
int rem, err = 0;
- if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
- return -EINVAL;
-
err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
if (err < 0)
return err;
@@ -3803,6 +3931,18 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
return -EBUSY;
+ if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) {
+ struct nft_set_dump_args args = {
+ .iter = {
+ .genmask = genmask,
+ .fn = nft_flush_set,
+ },
+ };
+ set->ops->walk(&ctx, set, &args.iter);
+
+ return args.iter.err;
+ }
+
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
err = nft_del_setelem(&ctx, set, attr);
if (err < 0)
@@ -3838,6 +3978,500 @@ struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
}
EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc);
+/*
+ * Stateful objects
+ */
+
+/**
+ * nft_register_obj- register nf_tables stateful object type
+ * @obj: object type
+ *
+ * Registers the object type for use with nf_tables. Returns zero on
+ * success or a negative errno code otherwise.
+ */
+int nft_register_obj(struct nft_object_type *obj_type)
+{
+ if (obj_type->type == NFT_OBJECT_UNSPEC)
+ return -EINVAL;
+
+ nfnl_lock(NFNL_SUBSYS_NFTABLES);
+ list_add_rcu(&obj_type->list, &nf_tables_objects);
+ nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nft_register_obj);
+
+/**
+ * nft_unregister_obj - unregister nf_tables object type
+ * @obj: object type
+ *
+ * Unregisters the object type for use with nf_tables.
+ */
+void nft_unregister_obj(struct nft_object_type *obj_type)
+{
+ nfnl_lock(NFNL_SUBSYS_NFTABLES);
+ list_del_rcu(&obj_type->list);
+ nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+}
+EXPORT_SYMBOL_GPL(nft_unregister_obj);
+
+struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
+ const struct nlattr *nla,
+ u32 objtype, u8 genmask)
+{
+ struct nft_object *obj;
+
+ list_for_each_entry(obj, &table->objects, list) {
+ if (!nla_strcmp(nla, obj->name) &&
+ objtype == obj->type->type &&
+ nft_active_genmask(obj, genmask))
+ return obj;
+ }
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
+
+static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
+ [NFTA_OBJ_TABLE] = { .type = NLA_STRING },
+ [NFTA_OBJ_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
+ [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
+};
+
+static struct nft_object *nft_obj_init(const struct nft_object_type *type,
+ const struct nlattr *attr)
+{
+ struct nlattr *tb[type->maxattr + 1];
+ struct nft_object *obj;
+ int err;
+
+ if (attr) {
+ err = nla_parse_nested(tb, type->maxattr, attr, type->policy);
+ if (err < 0)
+ goto err1;
+ } else {
+ memset(tb, 0, sizeof(tb[0]) * (type->maxattr + 1));
+ }
+
+ err = -ENOMEM;
+ obj = kzalloc(sizeof(struct nft_object) + type->size, GFP_KERNEL);
+ if (obj == NULL)
+ goto err1;
+
+ err = type->init((const struct nlattr * const *)tb, obj);
+ if (err < 0)
+ goto err2;
+
+ obj->type = type;
+ return obj;
+err2:
+ kfree(obj);
+err1:
+ return ERR_PTR(err);
+}
+
+static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
+ struct nft_object *obj, bool reset)
+{
+ struct nlattr *nest;
+
+ nest = nla_nest_start(skb, attr);
+ if (!nest)
+ goto nla_put_failure;
+ if (obj->type->dump(skb, obj, reset) < 0)
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
+{
+ const struct nft_object_type *type;
+
+ list_for_each_entry(type, &nf_tables_objects, list) {
+ if (objtype == type->type)
+ return type;
+ }
+ return NULL;
+}
+
+static const struct nft_object_type *nft_obj_type_get(u32 objtype)
+{
+ const struct nft_object_type *type;
+
+ type = __nft_obj_type_get(objtype);
+ if (type != NULL && try_module_get(type->owner))
+ return type;
+
+#ifdef CONFIG_MODULES
+ if (type == NULL) {
+ nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+ request_module("nft-obj-%u", objtype);
+ nfnl_lock(NFNL_SUBSYS_NFTABLES);
+ if (__nft_obj_type_get(objtype))
+ return ERR_PTR(-EAGAIN);
+ }
+#endif
+ return ERR_PTR(-ENOENT);
+}
+
+static int nf_tables_newobj(struct net *net, struct sock *nlsk,
+ struct sk_buff *skb, const struct nlmsghdr *nlh,
+ const struct nlattr * const nla[])
+{
+ const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+ const struct nft_object_type *type;
+ u8 genmask = nft_genmask_next(net);
+ int family = nfmsg->nfgen_family;
+ struct nft_af_info *afi;
+ struct nft_table *table;
+ struct nft_object *obj;
+ struct nft_ctx ctx;
+ u32 objtype;
+ int err;
+
+ if (!nla[NFTA_OBJ_TYPE] ||
+ !nla[NFTA_OBJ_NAME] ||
+ !nla[NFTA_OBJ_DATA])
+ return -EINVAL;
+
+ afi = nf_tables_afinfo_lookup(net, family, true);
+ if (IS_ERR(afi))
+ return PTR_ERR(afi);
+
+ table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
+ if (IS_ERR(table))
+ return PTR_ERR(table);
+
+ objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ if (err != -ENOENT)
+ return err;
+
+ obj = NULL;
+ }
+
+ if (obj != NULL) {
+ if (nlh->nlmsg_flags & NLM_F_EXCL)
+ return -EEXIST;
+
+ return 0;
+ }
+
+ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
+
+ type = nft_obj_type_get(objtype);
+ if (IS_ERR(type))
+ return PTR_ERR(type);
+
+ obj = nft_obj_init(type, nla[NFTA_OBJ_DATA]);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto err1;
+ }
+ obj->table = table;
+ nla_strlcpy(obj->name, nla[NFTA_OBJ_NAME], NFT_OBJ_MAXNAMELEN);
+
+ err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
+ if (err < 0)
+ goto err2;
+
+ list_add_tail_rcu(&obj->list, &table->objects);
+ table->use++;
+ return 0;
+err2:
+ if (obj->type->destroy)
+ obj->type->destroy(obj);
+ kfree(obj);
+err1:
+ module_put(type->owner);
+ return err;
+}
+
+static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
+ u32 portid, u32 seq, int event, u32 flags,
+ int family, const struct nft_table *table,
+ struct nft_object *obj, bool reset)
+{
+ struct nfgenmsg *nfmsg;
+ struct nlmsghdr *nlh;
+
+ event |= NFNL_SUBSYS_NFTABLES << 8;
+ nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
+ if (nlh == NULL)
+ goto nla_put_failure;
+
+ nfmsg = nlmsg_data(nlh);
+ nfmsg->nfgen_family = family;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
+
+ if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) ||
+ nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
+ nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->type->type)) ||
+ nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
+ nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset))
+ goto nla_put_failure;
+
+ nlmsg_end(skb, nlh);
+ return 0;
+
+nla_put_failure:
+ nlmsg_trim(skb, nlh);
+ return -1;
+}
+
+struct nft_obj_filter {
+ char table[NFT_OBJ_MAXNAMELEN];
+ u32 type;
+};
+
+static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
+ const struct nft_af_info *afi;
+ const struct nft_table *table;
+ unsigned int idx = 0, s_idx = cb->args[0];
+ struct nft_obj_filter *filter = cb->data;
+ struct net *net = sock_net(skb->sk);
+ int family = nfmsg->nfgen_family;
+ struct nft_object *obj;
+ bool reset = false;
+
+ if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
+ reset = true;
+
+ rcu_read_lock();
+ cb->seq = net->nft.base_seq;
+
+ list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+ if (family != NFPROTO_UNSPEC && family != afi->family)
+ continue;
+
+ list_for_each_entry_rcu(table, &afi->tables, list) {
+ list_for_each_entry_rcu(obj, &table->objects, list) {
+ if (!nft_is_active(net, obj))
+ goto cont;
+ if (idx < s_idx)
+ goto cont;
+ if (idx > s_idx)
+ memset(&cb->args[1], 0,
+ sizeof(cb->args) - sizeof(cb->args[0]));
+ if (filter->table[0] &&
+ strcmp(filter->table, table->name))
+ goto cont;
+ if (filter->type != NFT_OBJECT_UNSPEC &&
+ obj->type->type != filter->type)
+ goto cont;
+
+ if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ NFT_MSG_NEWOBJ,
+ NLM_F_MULTI | NLM_F_APPEND,
+ afi->family, table, obj, reset) < 0)
+ goto done;
+
+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+cont:
+ idx++;
+ }
+ }
+ }
+done:
+ rcu_read_unlock();
+
+ cb->args[0] = idx;
+ return skb->len;
+}
+
+static int nf_tables_dump_obj_done(struct netlink_callback *cb)
+{
+ kfree(cb->data);
+
+ return 0;
+}
+
+static struct nft_obj_filter *
+nft_obj_filter_alloc(const struct nlattr * const nla[])
+{
+ struct nft_obj_filter *filter;
+
+ filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+ if (!filter)
+ return ERR_PTR(-ENOMEM);
+
+ if (nla[NFTA_OBJ_TABLE])
+ nla_strlcpy(filter->table, nla[NFTA_OBJ_TABLE],
+ NFT_TABLE_MAXNAMELEN);
+ if (nla[NFTA_OBJ_TYPE])
+ filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+
+ return filter;
+}
+
+static int nf_tables_getobj(struct net *net, struct sock *nlsk,
+ struct sk_buff *skb, const struct nlmsghdr *nlh,
+ const struct nlattr * const nla[])
+{
+ const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+ u8 genmask = nft_genmask_cur(net);
+ int family = nfmsg->nfgen_family;
+ const struct nft_af_info *afi;
+ const struct nft_table *table;
+ struct nft_object *obj;
+ struct sk_buff *skb2;
+ bool reset = false;
+ u32 objtype;
+ int err;
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct netlink_dump_control c = {
+ .dump = nf_tables_dump_obj,
+ .done = nf_tables_dump_obj_done,
+ };
+
+ if (nla[NFTA_OBJ_TABLE] ||
+ nla[NFTA_OBJ_TYPE]) {
+ struct nft_obj_filter *filter;
+
+ filter = nft_obj_filter_alloc(nla);
+ if (IS_ERR(filter))
+ return -ENOMEM;
+
+ c.data = filter;
+ }
+ return netlink_dump_start(nlsk, skb, nlh, &c);
+ }
+
+ if (!nla[NFTA_OBJ_NAME] ||
+ !nla[NFTA_OBJ_TYPE])
+ return -EINVAL;
+
+ afi = nf_tables_afinfo_lookup(net, family, false);
+ if (IS_ERR(afi))
+ return PTR_ERR(afi);
+
+ table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
+ if (IS_ERR(table))
+ return PTR_ERR(table);
+
+ objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!skb2)
+ return -ENOMEM;
+
+ if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
+ reset = true;
+
+ err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
+ nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
+ family, table, obj, reset);
+ if (err < 0)
+ goto err;
+
+ return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
+err:
+ kfree_skb(skb2);
+ return err;
+
+ return 0;
+}
+
+static void nft_obj_destroy(struct nft_object *obj)
+{
+ if (obj->type->destroy)
+ obj->type->destroy(obj);
+
+ module_put(obj->type->owner);
+ kfree(obj);
+}
+
+static int nf_tables_delobj(struct net *net, struct sock *nlsk,
+ struct sk_buff *skb, const struct nlmsghdr *nlh,
+ const struct nlattr * const nla[])
+{
+ const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+ u8 genmask = nft_genmask_next(net);
+ int family = nfmsg->nfgen_family;
+ struct nft_af_info *afi;
+ struct nft_table *table;
+ struct nft_object *obj;
+ struct nft_ctx ctx;
+ u32 objtype;
+
+ if (!nla[NFTA_OBJ_TYPE] ||
+ !nla[NFTA_OBJ_NAME])
+ return -EINVAL;
+
+ afi = nf_tables_afinfo_lookup(net, family, true);
+ if (IS_ERR(afi))
+ return PTR_ERR(afi);
+
+ table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
+ if (IS_ERR(table))
+ return PTR_ERR(table);
+
+ objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
+ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+ if (obj->use > 0)
+ return -EBUSY;
+
+ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
+
+ return nft_delobj(&ctx, obj);
+}
+
+int nft_obj_notify(struct net *net, struct nft_table *table,
+ struct nft_object *obj, u32 portid, u32 seq, int event,
+ int family, int report, gfp_t gfp)
+{
+ struct sk_buff *skb;
+ int err;
+
+ if (!report &&
+ !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
+ return 0;
+
+ err = -ENOBUFS;
+ skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (skb == NULL)
+ goto err;
+
+ err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family,
+ table, obj, false);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto err;
+ }
+
+ err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
+err:
+ if (err < 0) {
+ nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(nft_obj_notify);
+
+static int nf_tables_obj_notify(const struct nft_ctx *ctx,
+ struct nft_object *obj, int event)
+{
+ return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid,
+ ctx->seq, event, ctx->afi->family, ctx->report,
+ GFP_KERNEL);
+}
+
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
u32 portid, u32 seq)
{
@@ -3998,6 +4632,26 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
[NFT_MSG_GETGEN] = {
.call = nf_tables_getgen,
},
+ [NFT_MSG_NEWOBJ] = {
+ .call_batch = nf_tables_newobj,
+ .attr_count = NFTA_OBJ_MAX,
+ .policy = nft_obj_policy,
+ },
+ [NFT_MSG_GETOBJ] = {
+ .call = nf_tables_getobj,
+ .attr_count = NFTA_OBJ_MAX,
+ .policy = nft_obj_policy,
+ },
+ [NFT_MSG_DELOBJ] = {
+ .call_batch = nf_tables_delobj,
+ .attr_count = NFTA_OBJ_MAX,
+ .policy = nft_obj_policy,
+ },
+ [NFT_MSG_GETOBJ_RESET] = {
+ .call = nf_tables_getobj,
+ .attr_count = NFTA_OBJ_MAX,
+ .policy = nft_obj_policy,
+ },
};
static void nft_chain_commit_update(struct nft_trans *trans)
@@ -4040,6 +4694,9 @@ static void nf_tables_commit_release(struct nft_trans *trans)
nft_set_elem_destroy(nft_trans_elem_set(trans),
nft_trans_elem(trans).priv, true);
break;
+ case NFT_MSG_DELOBJ:
+ nft_obj_destroy(nft_trans_obj(trans));
+ break;
}
kfree(trans);
}
@@ -4147,6 +4804,17 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
atomic_dec(&te->set->nelems);
te->set->ndeact--;
break;
+ case NFT_MSG_NEWOBJ:
+ nft_clear(net, nft_trans_obj(trans));
+ nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
+ NFT_MSG_NEWOBJ);
+ nft_trans_destroy(trans);
+ break;
+ case NFT_MSG_DELOBJ:
+ list_del_rcu(&nft_trans_obj(trans)->list);
+ nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
+ NFT_MSG_DELOBJ);
+ break;
}
}
@@ -4181,6 +4849,9 @@ static void nf_tables_abort_release(struct nft_trans *trans)
nft_set_elem_destroy(nft_trans_elem_set(trans),
nft_trans_elem(trans).priv, true);
break;
+ case NFT_MSG_NEWOBJ:
+ nft_obj_destroy(nft_trans_obj(trans));
+ break;
}
kfree(trans);
}
@@ -4261,6 +4932,15 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
nft_trans_destroy(trans);
break;
+ case NFT_MSG_NEWOBJ:
+ trans->ctx.table->use--;
+ list_del_rcu(&nft_trans_obj(trans)->list);
+ break;
+ case NFT_MSG_DELOBJ:
+ trans->ctx.table->use++;
+ nft_clear(trans->ctx.net, nft_trans_obj(trans));
+ nft_trans_destroy(trans);
+ break;
}
}
@@ -4807,6 +5487,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
{
struct nft_table *table, *nt;
struct nft_chain *chain, *nc;
+ struct nft_object *obj, *ne;
struct nft_rule *rule, *nr;
struct nft_set *set, *ns;
struct nft_ctx ctx = {
@@ -4833,6 +5514,11 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
table->use--;
nft_set_destroy(set);
}
+ list_for_each_entry_safe(obj, ne, &table->objects, list) {
+ list_del(&obj->list);
+ table->use--;
+ nft_obj_destroy(obj);
+ }
list_for_each_entry_safe(chain, nc, &table->chains, list) {
list_del(&chain->list);
table->use--;
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 0dd5c695482f..65dbeadcb118 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -53,10 +53,10 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
nft_trace_notify(info);
- nf_log_trace(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
- pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
- chain->table->name, chain->name, comments[type],
- rulenum);
+ nf_log_trace(nft_net(pkt), nft_pf(pkt), nft_hook(pkt), pkt->skb,
+ nft_in(pkt), nft_out(pkt), &trace_loginfo,
+ "TRACE: %s:%s:%s:%u ",
+ chain->table->name, chain->name, comments[type], rulenum);
}
static inline void nft_trace_packet(struct nft_traceinfo *info,
@@ -124,7 +124,7 @@ unsigned int
nft_do_chain(struct nft_pktinfo *pkt, void *priv)
{
const struct nft_chain *chain = priv, *basechain = chain;
- const struct net *net = pkt->net;
+ const struct net *net = nft_net(pkt);
const struct nft_rule *rule;
const struct nft_expr *expr, *last;
struct nft_regs regs;
@@ -178,6 +178,7 @@ next_rule:
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
+ case NF_STOLEN:
nft_trace_packet(&info, chain, rule,
rulenum, NFT_TRACETYPE_RULE);
return regs.verdict.code;
@@ -231,68 +232,40 @@ next_rule:
}
EXPORT_SYMBOL_GPL(nft_do_chain);
+static struct nft_expr_type *nft_basic_types[] = {
+ &nft_imm_type,
+ &nft_cmp_type,
+ &nft_lookup_type,
+ &nft_bitwise_type,
+ &nft_byteorder_type,
+ &nft_payload_type,
+ &nft_dynset_type,
+ &nft_range_type,
+};
+
int __init nf_tables_core_module_init(void)
{
- int err;
-
- err = nft_immediate_module_init();
- if (err < 0)
- goto err1;
-
- err = nft_cmp_module_init();
- if (err < 0)
- goto err2;
-
- err = nft_lookup_module_init();
- if (err < 0)
- goto err3;
-
- err = nft_bitwise_module_init();
- if (err < 0)
- goto err4;
+ int err, i;
- err = nft_byteorder_module_init();
- if (err < 0)
- goto err5;
-
- err = nft_payload_module_init();
- if (err < 0)
- goto err6;
-
- err = nft_dynset_module_init();
- if (err < 0)
- goto err7;
-
- err = nft_range_module_init();
- if (err < 0)
- goto err8;
+ for (i = 0; i < ARRAY_SIZE(nft_basic_types); i++) {
+ err = nft_register_expr(nft_basic_types[i]);
+ if (err)
+ goto err;
+ }
return 0;
-err8:
- nft_dynset_module_exit();
-err7:
- nft_payload_module_exit();
-err6:
- nft_byteorder_module_exit();
-err5:
- nft_bitwise_module_exit();
-err4:
- nft_lookup_module_exit();
-err3:
- nft_cmp_module_exit();
-err2:
- nft_immediate_module_exit();
-err1:
+
+err:
+ while (i-- > 0)
+ nft_unregister_expr(nft_basic_types[i]);
return err;
}
void nf_tables_core_module_exit(void)
{
- nft_dynset_module_exit();
- nft_payload_module_exit();
- nft_byteorder_module_exit();
- nft_bitwise_module_exit();
- nft_lookup_module_exit();
- nft_cmp_module_exit();
- nft_immediate_module_exit();
+ int i;
+
+ i = ARRAY_SIZE(nft_basic_types);
+ while (i-- > 0)
+ nft_unregister_expr(nft_basic_types[i]);
}
diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c
index ab695f8e2d29..12eb9041dca2 100644
--- a/net/netfilter/nf_tables_trace.c
+++ b/net/netfilter/nf_tables_trace.c
@@ -171,7 +171,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
unsigned int size;
int event = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_TRACE;
- if (!nfnetlink_has_listeners(pkt->net, NFNLGRP_NFTRACE))
+ if (!nfnetlink_has_listeners(nft_net(pkt), NFNLGRP_NFTRACE))
return;
size = nlmsg_total_size(sizeof(struct nfgenmsg)) +
@@ -207,7 +207,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;
- if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(pkt->pf)))
+ if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(nft_pf(pkt))))
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type)))
@@ -249,7 +249,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
goto nla_put_failure;
if (!info->packet_dumped) {
- if (nf_trace_fill_dev_info(skb, pkt->in, pkt->out))
+ if (nf_trace_fill_dev_info(skb, nft_in(pkt), nft_out(pkt)))
goto nla_put_failure;
if (nf_trace_fill_pkt_info(skb, pkt))
@@ -258,7 +258,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
}
nlmsg_end(skb, nlh);
- nfnetlink_send(skb, pkt->net, 0, NFNLGRP_NFTRACE, 0, GFP_ATOMIC);
+ nfnetlink_send(skb, nft_net(pkt), 0, NFNLGRP_NFTRACE, 0, GFP_ATOMIC);
return;
nla_put_failure:
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index eb086a192c5a..200922bb2036 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -80,7 +80,7 @@ struct nfulnl_instance {
#define INSTANCE_BUCKETS 16
-static int nfnl_log_net_id __read_mostly;
+static unsigned int nfnl_log_net_id __read_mostly;
struct nfnl_log_net {
spinlock_t instances_lock;
@@ -330,7 +330,7 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
* message. WARNING: has to be <= 128k due to slab restrictions */
n = max(inst_size, pkt_size);
- skb = alloc_skb(n, GFP_ATOMIC);
+ skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN);
if (!skb) {
if (n > pkt_size) {
/* try to allocate only as much as we need for current
@@ -1152,6 +1152,7 @@ MODULE_ALIAS_NF_LOGGER(AF_INET, 1);
MODULE_ALIAS_NF_LOGGER(AF_INET6, 1);
MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1);
MODULE_ALIAS_NF_LOGGER(3, 1); /* NFPROTO_ARP */
+MODULE_ALIAS_NF_LOGGER(5, 1); /* NFPROTO_NETDEV */
module_init(nfnetlink_log_init);
module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index af832c526048..be7627b80400 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -69,7 +69,7 @@ struct nfqnl_instance {
* Following fields are dirtied for each queued packet,
* keep them in same cache line if possible.
*/
- spinlock_t lock;
+ spinlock_t lock ____cacheline_aligned_in_smp;
unsigned int queue_total;
unsigned int id_sequence; /* 'sequence' of pkt ids */
struct list_head queue_list; /* packets in queue */
@@ -77,7 +77,7 @@ struct nfqnl_instance {
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
-static int nfnl_queue_net_id __read_mostly;
+static unsigned int nfnl_queue_net_id __read_mostly;
#define INSTANCE_BUCKETS 16
struct nfnl_queue_net {
@@ -919,7 +919,7 @@ static struct notifier_block nfqnl_dev_notifier = {
static int nf_hook_cmp(struct nf_queue_entry *entry, unsigned long entry_ptr)
{
- return rcu_access_pointer(entry->state.hook_entries) ==
+ return rcu_access_pointer(entry->hook) ==
(struct nf_hook_entry *)entry_ptr;
}
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index 31c15ed2e5fc..877d9acd91ef 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -121,7 +121,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_bitwise_type;
static const struct nft_expr_ops nft_bitwise_ops = {
.type = &nft_bitwise_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)),
@@ -130,20 +129,10 @@ static const struct nft_expr_ops nft_bitwise_ops = {
.dump = nft_bitwise_dump,
};
-static struct nft_expr_type nft_bitwise_type __read_mostly = {
+struct nft_expr_type nft_bitwise_type __read_mostly = {
.name = "bitwise",
.ops = &nft_bitwise_ops,
.policy = nft_bitwise_policy,
.maxattr = NFTA_BITWISE_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_bitwise_module_init(void)
-{
- return nft_register_expr(&nft_bitwise_type);
-}
-
-void nft_bitwise_module_exit(void)
-{
- nft_unregister_expr(&nft_bitwise_type);
-}
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
index ee63d981268d..13d4e421a6b3 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -169,7 +169,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_byteorder_type;
static const struct nft_expr_ops nft_byteorder_ops = {
.type = &nft_byteorder_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_byteorder)),
@@ -178,20 +177,10 @@ static const struct nft_expr_ops nft_byteorder_ops = {
.dump = nft_byteorder_dump,
};
-static struct nft_expr_type nft_byteorder_type __read_mostly = {
+struct nft_expr_type nft_byteorder_type __read_mostly = {
.name = "byteorder",
.ops = &nft_byteorder_ops,
.policy = nft_byteorder_policy,
.maxattr = NFTA_BYTEORDER_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_byteorder_module_init(void)
-{
- return nft_register_expr(&nft_byteorder_type);
-}
-
-void nft_byteorder_module_exit(void)
-{
- nft_unregister_expr(&nft_byteorder_type);
-}
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 2e53739812b1..2b96effeadc1 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -84,9 +84,6 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
if (err < 0)
return err;
- if (desc.len > U8_MAX)
- return -ERANGE;
-
priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP]));
priv->len = desc.len;
return 0;
@@ -110,7 +107,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_cmp_type;
static const struct nft_expr_ops nft_cmp_ops = {
.type = &nft_cmp_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_cmp_expr)),
@@ -211,20 +207,10 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
return &nft_cmp_ops;
}
-static struct nft_expr_type nft_cmp_type __read_mostly = {
+struct nft_expr_type nft_cmp_type __read_mostly = {
.name = "cmp",
.select_ops = nft_cmp_select_ops,
.policy = nft_cmp_policy,
.maxattr = NFTA_CMP_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_cmp_module_init(void)
-{
- return nft_register_expr(&nft_cmp_type);
-}
-
-void nft_cmp_module_exit(void)
-{
- nft_unregister_expr(&nft_cmp_type);
-}
diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c
index 77db8358ab14..7f8422213341 100644
--- a/net/netfilter/nft_counter.c
+++ b/net/netfilter/nft_counter.c
@@ -18,105 +18,197 @@
#include <net/netfilter/nf_tables.h>
struct nft_counter {
- u64 bytes;
- u64 packets;
-};
-
-struct nft_counter_percpu {
- struct nft_counter counter;
- struct u64_stats_sync syncp;
+ s64 bytes;
+ s64 packets;
};
struct nft_counter_percpu_priv {
- struct nft_counter_percpu __percpu *counter;
+ struct nft_counter __percpu *counter;
};
-static void nft_counter_eval(const struct nft_expr *expr,
- struct nft_regs *regs,
- const struct nft_pktinfo *pkt)
+static DEFINE_PER_CPU(seqcount_t, nft_counter_seq);
+
+static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
{
- struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
- struct nft_counter_percpu *this_cpu;
+ struct nft_counter *this_cpu;
+ seqcount_t *myseq;
local_bh_disable();
this_cpu = this_cpu_ptr(priv->counter);
- u64_stats_update_begin(&this_cpu->syncp);
- this_cpu->counter.bytes += pkt->skb->len;
- this_cpu->counter.packets++;
- u64_stats_update_end(&this_cpu->syncp);
+ myseq = this_cpu_ptr(&nft_counter_seq);
+
+ write_seqcount_begin(myseq);
+
+ this_cpu->bytes += pkt->skb->len;
+ this_cpu->packets++;
+
+ write_seqcount_end(myseq);
local_bh_enable();
}
-static void nft_counter_fetch(const struct nft_counter_percpu __percpu *counter,
+static inline void nft_counter_obj_eval(struct nft_object *obj,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
+
+ nft_counter_do_eval(priv, regs, pkt);
+}
+
+static int nft_counter_do_init(const struct nlattr * const tb[],
+ struct nft_counter_percpu_priv *priv)
+{
+ struct nft_counter __percpu *cpu_stats;
+ struct nft_counter *this_cpu;
+
+ cpu_stats = alloc_percpu(struct nft_counter);
+ if (cpu_stats == NULL)
+ return -ENOMEM;
+
+ preempt_disable();
+ this_cpu = this_cpu_ptr(cpu_stats);
+ if (tb[NFTA_COUNTER_PACKETS]) {
+ this_cpu->packets =
+ be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
+ }
+ if (tb[NFTA_COUNTER_BYTES]) {
+ this_cpu->bytes =
+ be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
+ }
+ preempt_enable();
+ priv->counter = cpu_stats;
+ return 0;
+}
+
+static int nft_counter_obj_init(const struct nlattr * const tb[],
+ struct nft_object *obj)
+{
+ struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
+
+ return nft_counter_do_init(tb, priv);
+}
+
+static void nft_counter_do_destroy(struct nft_counter_percpu_priv *priv)
+{
+ free_percpu(priv->counter);
+}
+
+static void nft_counter_obj_destroy(struct nft_object *obj)
+{
+ struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
+
+ nft_counter_do_destroy(priv);
+}
+
+static void nft_counter_reset(struct nft_counter_percpu_priv __percpu *priv,
struct nft_counter *total)
{
- const struct nft_counter_percpu *cpu_stats;
+ struct nft_counter *this_cpu;
+
+ local_bh_disable();
+ this_cpu = this_cpu_ptr(priv->counter);
+ this_cpu->packets -= total->packets;
+ this_cpu->bytes -= total->bytes;
+ local_bh_enable();
+}
+
+static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
+ struct nft_counter *total)
+{
+ struct nft_counter *this_cpu;
+ const seqcount_t *myseq;
u64 bytes, packets;
unsigned int seq;
int cpu;
memset(total, 0, sizeof(*total));
for_each_possible_cpu(cpu) {
- cpu_stats = per_cpu_ptr(counter, cpu);
+ myseq = per_cpu_ptr(&nft_counter_seq, cpu);
+ this_cpu = per_cpu_ptr(priv->counter, cpu);
do {
- seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
- bytes = cpu_stats->counter.bytes;
- packets = cpu_stats->counter.packets;
- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
+ seq = read_seqcount_begin(myseq);
+ bytes = this_cpu->bytes;
+ packets = this_cpu->packets;
+ } while (read_seqcount_retry(myseq, seq));
- total->packets += packets;
- total->bytes += bytes;
+ total->bytes += bytes;
+ total->packets += packets;
}
}
-static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)
+static int nft_counter_do_dump(struct sk_buff *skb,
+ struct nft_counter_percpu_priv *priv,
+ bool reset)
{
- struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
struct nft_counter total;
- nft_counter_fetch(priv->counter, &total);
+ nft_counter_fetch(priv, &total);
if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
NFTA_COUNTER_PAD) ||
nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets),
NFTA_COUNTER_PAD))
goto nla_put_failure;
+
+ if (reset)
+ nft_counter_reset(priv, &total);
+
return 0;
nla_put_failure:
return -1;
}
+static int nft_counter_obj_dump(struct sk_buff *skb,
+ struct nft_object *obj, bool reset)
+{
+ struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
+
+ return nft_counter_do_dump(skb, priv, reset);
+}
+
static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
[NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },
[NFTA_COUNTER_BYTES] = { .type = NLA_U64 },
};
+static struct nft_object_type nft_counter_obj __read_mostly = {
+ .type = NFT_OBJECT_COUNTER,
+ .size = sizeof(struct nft_counter_percpu_priv),
+ .maxattr = NFTA_COUNTER_MAX,
+ .policy = nft_counter_policy,
+ .eval = nft_counter_obj_eval,
+ .init = nft_counter_obj_init,
+ .destroy = nft_counter_obj_destroy,
+ .dump = nft_counter_obj_dump,
+ .owner = THIS_MODULE,
+};
+
+static void nft_counter_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
+
+ nft_counter_do_eval(priv, regs, pkt);
+}
+
+static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
+
+ return nft_counter_do_dump(skb, priv, false);
+}
+
static int nft_counter_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
- struct nft_counter_percpu __percpu *cpu_stats;
- struct nft_counter_percpu *this_cpu;
-
- cpu_stats = netdev_alloc_pcpu_stats(struct nft_counter_percpu);
- if (cpu_stats == NULL)
- return -ENOMEM;
- preempt_disable();
- this_cpu = this_cpu_ptr(cpu_stats);
- if (tb[NFTA_COUNTER_PACKETS]) {
- this_cpu->counter.packets =
- be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
- }
- if (tb[NFTA_COUNTER_BYTES]) {
- this_cpu->counter.bytes =
- be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
- }
- preempt_enable();
- priv->counter = cpu_stats;
- return 0;
+ return nft_counter_do_init(tb, priv);
}
static void nft_counter_destroy(const struct nft_ctx *ctx,
@@ -124,28 +216,27 @@ static void nft_counter_destroy(const struct nft_ctx *ctx,
{
struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
- free_percpu(priv->counter);
+ nft_counter_do_destroy(priv);
}
static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)
{
struct nft_counter_percpu_priv *priv = nft_expr_priv(src);
struct nft_counter_percpu_priv *priv_clone = nft_expr_priv(dst);
- struct nft_counter_percpu __percpu *cpu_stats;
- struct nft_counter_percpu *this_cpu;
+ struct nft_counter __percpu *cpu_stats;
+ struct nft_counter *this_cpu;
struct nft_counter total;
- nft_counter_fetch(priv->counter, &total);
+ nft_counter_fetch(priv, &total);
- cpu_stats = __netdev_alloc_pcpu_stats(struct nft_counter_percpu,
- GFP_ATOMIC);
+ cpu_stats = alloc_percpu_gfp(struct nft_counter, GFP_ATOMIC);
if (cpu_stats == NULL)
return -ENOMEM;
preempt_disable();
this_cpu = this_cpu_ptr(cpu_stats);
- this_cpu->counter.packets = total.packets;
- this_cpu->counter.bytes = total.bytes;
+ this_cpu->packets = total.packets;
+ this_cpu->bytes = total.bytes;
preempt_enable();
priv_clone->counter = cpu_stats;
@@ -174,12 +265,29 @@ static struct nft_expr_type nft_counter_type __read_mostly = {
static int __init nft_counter_module_init(void)
{
- return nft_register_expr(&nft_counter_type);
+ int cpu, err;
+
+ for_each_possible_cpu(cpu)
+ seqcount_init(per_cpu_ptr(&nft_counter_seq, cpu));
+
+ err = nft_register_obj(&nft_counter_obj);
+ if (err < 0)
+ return err;
+
+ err = nft_register_expr(&nft_counter_type);
+ if (err < 0)
+ goto err1;
+
+ return 0;
+err1:
+ nft_unregister_obj(&nft_counter_obj);
+ return err;
}
static void __exit nft_counter_module_exit(void)
{
nft_unregister_expr(&nft_counter_type);
+ nft_unregister_obj(&nft_counter_obj);
}
module_init(nft_counter_module_init);
@@ -188,3 +296,4 @@ module_exit(nft_counter_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_ALIAS_NFT_EXPR("counter");
+MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_COUNTER);
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index d7b0d171172a..e6baeaebe653 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -207,37 +208,37 @@ static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
[NFTA_CT_SREG] = { .type = NLA_U32 },
};
-static int nft_ct_l3proto_try_module_get(uint8_t family)
+static int nft_ct_netns_get(struct net *net, uint8_t family)
{
int err;
if (family == NFPROTO_INET) {
- err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4);
+ err = nf_ct_netns_get(net, NFPROTO_IPV4);
if (err < 0)
goto err1;
- err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6);
+ err = nf_ct_netns_get(net, NFPROTO_IPV6);
if (err < 0)
goto err2;
} else {
- err = nf_ct_l3proto_try_module_get(family);
+ err = nf_ct_netns_get(net, family);
if (err < 0)
goto err1;
}
return 0;
err2:
- nf_ct_l3proto_module_put(NFPROTO_IPV4);
+ nf_ct_netns_put(net, NFPROTO_IPV4);
err1:
return err;
}
-static void nft_ct_l3proto_module_put(uint8_t family)
+static void nft_ct_netns_put(struct net *net, uint8_t family)
{
if (family == NFPROTO_INET) {
- nf_ct_l3proto_module_put(NFPROTO_IPV4);
- nf_ct_l3proto_module_put(NFPROTO_IPV6);
+ nf_ct_netns_put(net, NFPROTO_IPV4);
+ nf_ct_netns_put(net, NFPROTO_IPV6);
} else
- nf_ct_l3proto_module_put(family);
+ nf_ct_netns_put(net, family);
}
static int nft_ct_get_init(const struct nft_ctx *ctx,
@@ -341,7 +342,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
if (err < 0)
return err;
- err = nft_ct_l3proto_try_module_get(ctx->afi->family);
+ err = nft_ct_netns_get(ctx->net, ctx->afi->family);
if (err < 0)
return err;
@@ -389,7 +390,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
if (err < 0)
goto err1;
- err = nft_ct_l3proto_try_module_get(ctx->afi->family);
+ err = nft_ct_netns_get(ctx->net, ctx->afi->family);
if (err < 0)
goto err1;
@@ -404,7 +405,7 @@ err1:
static void nft_ct_get_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
- nft_ct_l3proto_module_put(ctx->afi->family);
+ nf_ct_netns_put(ctx->net, ctx->afi->family);
}
static void nft_ct_set_destroy(const struct nft_ctx *ctx,
@@ -422,7 +423,7 @@ static void nft_ct_set_destroy(const struct nft_ctx *ctx,
break;
}
- nft_ct_l3proto_module_put(ctx->afi->family);
+ nft_ct_netns_put(ctx->net, ctx->afi->family);
}
static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -518,15 +519,61 @@ static struct nft_expr_type nft_ct_type __read_mostly = {
.owner = THIS_MODULE,
};
+static void nft_notrack_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct sk_buff *skb = pkt->skb;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+
+ ct = nf_ct_get(pkt->skb, &ctinfo);
+ /* Previously seen (loopback or untracked)? Ignore. */
+ if (ct)
+ return;
+
+ ct = nf_ct_untracked_get();
+ atomic_inc(&ct->ct_general.use);
+ skb->nfct = &ct->ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+}
+
+static struct nft_expr_type nft_notrack_type;
+static const struct nft_expr_ops nft_notrack_ops = {
+ .type = &nft_notrack_type,
+ .size = NFT_EXPR_SIZE(0),
+ .eval = nft_notrack_eval,
+};
+
+static struct nft_expr_type nft_notrack_type __read_mostly = {
+ .name = "notrack",
+ .ops = &nft_notrack_ops,
+ .owner = THIS_MODULE,
+};
+
static int __init nft_ct_module_init(void)
{
+ int err;
+
BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE);
- return nft_register_expr(&nft_ct_type);
+ err = nft_register_expr(&nft_ct_type);
+ if (err < 0)
+ return err;
+
+ err = nft_register_expr(&nft_notrack_type);
+ if (err < 0)
+ goto err1;
+
+ return 0;
+err1:
+ nft_unregister_expr(&nft_ct_type);
+ return err;
}
static void __exit nft_ct_module_exit(void)
{
+ nft_unregister_expr(&nft_notrack_type);
nft_unregister_expr(&nft_ct_type);
}
@@ -536,3 +583,4 @@ module_exit(nft_ct_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_ALIAS_NFT_EXPR("ct");
+MODULE_ALIAS_NFT_EXPR("notrack");
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
index 31ca94793aa9..7de2f46734a4 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -268,7 +268,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_dynset_type;
static const struct nft_expr_ops nft_dynset_ops = {
.type = &nft_dynset_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_dynset)),
@@ -278,20 +277,10 @@ static const struct nft_expr_ops nft_dynset_ops = {
.dump = nft_dynset_dump,
};
-static struct nft_expr_type nft_dynset_type __read_mostly = {
+struct nft_expr_type nft_dynset_type __read_mostly = {
.name = "dynset",
.ops = &nft_dynset_ops,
.policy = nft_dynset_policy,
.maxattr = NFTA_DYNSET_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_dynset_module_init(void)
-{
- return nft_register_expr(&nft_dynset_type);
-}
-
-void nft_dynset_module_exit(void)
-{
- nft_unregister_expr(&nft_dynset_type);
-}
diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c
new file mode 100644
index 000000000000..29a4906adc27
--- /dev/null
+++ b/net/netfilter/nft_fib.c
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ *
+ * Generic part shared by ipv4 and ipv6 backends.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nft_fib.h>
+
+const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
+ [NFTA_FIB_DREG] = { .type = NLA_U32 },
+ [NFTA_FIB_RESULT] = { .type = NLA_U32 },
+ [NFTA_FIB_FLAGS] = { .type = NLA_U32 },
+};
+EXPORT_SYMBOL(nft_fib_policy);
+
+#define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
+ NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)
+
+int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nft_data **data)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ unsigned int hooks;
+
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF: /* fallthrough */
+ case NFT_FIB_RESULT_OIFNAME:
+ hooks = (1 << NF_INET_PRE_ROUTING);
+ break;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ if (priv->flags & NFTA_FIB_F_IIF)
+ hooks = (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_FORWARD);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+ hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING) |
+ (1 << NF_INET_FORWARD);
+ else
+ hooks = (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_POST_ROUTING);
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return nft_chain_validate_hooks(ctx->chain, hooks);
+}
+EXPORT_SYMBOL_GPL(nft_fib_validate);
+
+int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_fib *priv = nft_expr_priv(expr);
+ unsigned int len;
+ int err;
+
+ if (!tb[NFTA_FIB_DREG] || !tb[NFTA_FIB_RESULT] || !tb[NFTA_FIB_FLAGS])
+ return -EINVAL;
+
+ priv->flags = ntohl(nla_get_be32(tb[NFTA_FIB_FLAGS]));
+
+ if (priv->flags == 0 || (priv->flags & ~NFTA_FIB_F_ALL))
+ return -EINVAL;
+
+ if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) ==
+ (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR))
+ return -EINVAL;
+ if ((priv->flags & (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)) ==
+ (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF))
+ return -EINVAL;
+ if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)
+ return -EINVAL;
+
+ priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
+ priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);
+
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ if (priv->flags & NFTA_FIB_F_OIF)
+ return -EINVAL;
+ len = sizeof(int);
+ break;
+ case NFT_FIB_RESULT_OIFNAME:
+ if (priv->flags & NFTA_FIB_F_OIF)
+ return -EINVAL;
+ len = IFNAMSIZ;
+ break;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ len = sizeof(u32);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = nft_validate_register_store(ctx, priv->dreg, NULL,
+ NFT_DATA_VALUE, len);
+ if (err < 0)
+ return err;
+
+ return nft_fib_validate(ctx, expr, NULL);
+}
+EXPORT_SYMBOL_GPL(nft_fib_init);
+
+int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+
+ if (nft_dump_register(skb, NFTA_FIB_DREG, priv->dreg))
+ return -1;
+
+ if (nla_put_be32(skb, NFTA_FIB_RESULT, htonl(priv->result)))
+ return -1;
+
+ if (nla_put_be32(skb, NFTA_FIB_FLAGS, htonl(priv->flags)))
+ return -1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nft_fib_dump);
+
+void nft_fib_store_result(void *reg, enum nft_fib_result r,
+ const struct nft_pktinfo *pkt, int index)
+{
+ struct net_device *dev;
+ u32 *dreg = reg;
+
+ switch (r) {
+ case NFT_FIB_RESULT_OIF:
+ *dreg = index;
+ break;
+ case NFT_FIB_RESULT_OIFNAME:
+ dev = dev_get_by_index_rcu(nft_net(pkt), index);
+ strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ *dreg = 0;
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(nft_fib_store_result);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
diff --git a/net/netfilter/nft_fib_inet.c b/net/netfilter/nft_fib_inet.c
new file mode 100644
index 000000000000..9120fc7228f4
--- /dev/null
+++ b/net/netfilter/nft_fib_inet.c
@@ -0,0 +1,82 @@
+/*
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+
+#include <net/netfilter/nft_fib.h>
+
+static void nft_fib_inet_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+
+ switch (nft_pf(pkt)) {
+ case NFPROTO_IPV4:
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ case NFT_FIB_RESULT_OIFNAME:
+ return nft_fib4_eval(expr, regs, pkt);
+ case NFT_FIB_RESULT_ADDRTYPE:
+ return nft_fib4_eval_type(expr, regs, pkt);
+ }
+ break;
+ case NFPROTO_IPV6:
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ case NFT_FIB_RESULT_OIFNAME:
+ return nft_fib6_eval(expr, regs, pkt);
+ case NFT_FIB_RESULT_ADDRTYPE:
+ return nft_fib6_eval_type(expr, regs, pkt);
+ }
+ break;
+ }
+
+ regs->verdict.code = NF_DROP;
+}
+
+static struct nft_expr_type nft_fib_inet_type;
+static const struct nft_expr_ops nft_fib_inet_ops = {
+ .type = &nft_fib_inet_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_fib)),
+ .eval = nft_fib_inet_eval,
+ .init = nft_fib_init,
+ .dump = nft_fib_dump,
+ .validate = nft_fib_validate,
+};
+
+static struct nft_expr_type nft_fib_inet_type __read_mostly = {
+ .family = NFPROTO_INET,
+ .name = "fib",
+ .ops = &nft_fib_inet_ops,
+ .policy = nft_fib_policy,
+ .maxattr = NFTA_FIB_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_fib_inet_module_init(void)
+{
+ return nft_register_expr(&nft_fib_inet_type);
+}
+
+static void __exit nft_fib_inet_module_exit(void)
+{
+ nft_unregister_expr(&nft_fib_inet_type);
+}
+
+module_init(nft_fib_inet_module_init);
+module_exit(nft_fib_inet_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+MODULE_ALIAS_NFT_AF_EXPR(1, "fib");
diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
index 763ebc3e0b2b..ce13a50b9189 100644
--- a/net/netfilter/nft_fwd_netdev.c
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -26,8 +26,8 @@ static void nft_fwd_netdev_eval(const struct nft_expr *expr,
struct nft_fwd_netdev *priv = nft_expr_priv(expr);
int oif = regs->data[priv->sreg_dev];
- nf_dup_netdev_egress(pkt, oif);
- regs->verdict.code = NF_DROP;
+ nf_fwd_netdev_egress(pkt, oif);
+ regs->verdict.code = NF_STOLEN;
}
static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index d5447a22275c..eb2721af898d 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -58,7 +58,6 @@ static int nft_hash_init(const struct nft_ctx *ctx,
if (!tb[NFTA_HASH_SREG] ||
!tb[NFTA_HASH_DREG] ||
!tb[NFTA_HASH_LEN] ||
- !tb[NFTA_HASH_SEED] ||
!tb[NFTA_HASH_MODULUS])
return -EINVAL;
@@ -83,7 +82,10 @@ static int nft_hash_init(const struct nft_ctx *ctx,
if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;
- priv->seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED]));
+ if (tb[NFTA_HASH_SEED])
+ priv->seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED]));
+ else
+ get_random_bytes(&priv->seed, sizeof(priv->seed));
return nft_validate_register_load(priv->sreg, len) &&
nft_validate_register_store(ctx, priv->dreg, NULL,
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index d17018ff54e6..728baf88295a 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -54,9 +54,6 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
if (err < 0)
return err;
- if (desc.len > U8_MAX)
- return -ERANGE;
-
priv->dlen = desc.len;
priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]);
@@ -105,7 +102,6 @@ static int nft_immediate_validate(const struct nft_ctx *ctx,
return 0;
}
-static struct nft_expr_type nft_imm_type;
static const struct nft_expr_ops nft_imm_ops = {
.type = &nft_imm_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
@@ -116,20 +112,10 @@ static const struct nft_expr_ops nft_imm_ops = {
.validate = nft_immediate_validate,
};
-static struct nft_expr_type nft_imm_type __read_mostly = {
+struct nft_expr_type nft_imm_type __read_mostly = {
.name = "immediate",
.ops = &nft_imm_ops,
.policy = nft_immediate_policy,
.maxattr = NFTA_IMMEDIATE_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_immediate_module_init(void)
-{
- return nft_register_expr(&nft_imm_type);
-}
-
-void nft_immediate_module_exit(void)
-{
- nft_unregister_expr(&nft_imm_type);
-}
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 1b01404bb33f..6271e40a3dd6 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -32,8 +32,9 @@ static void nft_log_eval(const struct nft_expr *expr,
{
const struct nft_log *priv = nft_expr_priv(expr);
- nf_log_packet(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
- pkt->out, &priv->loginfo, "%s", priv->prefix);
+ nf_log_packet(nft_net(pkt), nft_pf(pkt), nft_hook(pkt), pkt->skb,
+ nft_in(pkt), nft_out(pkt), &priv->loginfo, "%s",
+ priv->prefix);
}
static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index 8166b6994cc7..d4f97fa7e21d 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -35,9 +35,8 @@ static void nft_lookup_eval(const struct nft_expr *expr,
const struct nft_set_ext *ext;
bool found;
- found = set->ops->lookup(pkt->net, set, &regs->data[priv->sreg], &ext) ^
- priv->invert;
-
+ found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg],
+ &ext) ^ priv->invert;
if (!found) {
regs->verdict.code = NFT_BREAK;
return;
@@ -155,7 +154,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_lookup_type;
static const struct nft_expr_ops nft_lookup_ops = {
.type = &nft_lookup_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
@@ -165,20 +163,10 @@ static const struct nft_expr_ops nft_lookup_ops = {
.dump = nft_lookup_dump,
};
-static struct nft_expr_type nft_lookup_type __read_mostly = {
+struct nft_expr_type nft_lookup_type __read_mostly = {
.name = "lookup",
.ops = &nft_lookup_ops,
.policy = nft_lookup_policy,
.maxattr = NFTA_LOOKUP_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_lookup_module_init(void)
-{
- return nft_register_expr(&nft_lookup_type);
-}
-
-void nft_lookup_module_exit(void)
-{
- nft_unregister_expr(&nft_lookup_type);
-}
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index 81b5ad6165ac..11ce016cd479 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -77,7 +77,7 @@ int nft_masq_init(const struct nft_ctx *ctx,
}
}
- return 0;
+ return nf_ct_netns_get(ctx->net, ctx->afi->family);
}
EXPORT_SYMBOL_GPL(nft_masq_init);
@@ -105,4 +105,4 @@ nla_put_failure:
EXPORT_SYMBOL_GPL(nft_masq_dump);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 6c1e0246706e..66c7f4b4c49b 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -36,7 +36,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
{
const struct nft_meta *priv = nft_expr_priv(expr);
const struct sk_buff *skb = pkt->skb;
- const struct net_device *in = pkt->in, *out = pkt->out;
+ const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
struct sock *sk;
u32 *dest = &regs->data[priv->dreg];
@@ -49,7 +49,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
*(__be16 *)dest = skb->protocol;
break;
case NFT_META_NFPROTO:
- *dest = pkt->pf;
+ *dest = nft_pf(pkt);
break;
case NFT_META_L4PROTO:
if (!pkt->tprot_set)
@@ -146,7 +146,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
break;
}
- switch (pkt->pf) {
+ switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
if (ipv4_is_multicast(ip_hdr(skb)->daddr))
*dest = PACKET_MULTICAST;
@@ -310,6 +310,11 @@ int nft_meta_set_validate(const struct nft_ctx *ctx,
case NFPROTO_NETDEV:
hooks = 1 << NF_NETDEV_INGRESS;
break;
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ case NFPROTO_INET:
+ hooks = 1 << NF_INET_PRE_ROUTING;
+ break;
default:
return -EOPNOTSUPP;
}
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index ee2d71753746..19a7bf3236f9 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -209,7 +209,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(ctx->net, family);
}
static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -257,12 +257,21 @@ nla_put_failure:
return -1;
}
+static void
+nft_nat_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
+{
+ const struct nft_nat *priv = nft_expr_priv(expr);
+
+ nf_ct_netns_put(ctx->net, priv->family);
+}
+
static struct nft_expr_type nft_nat_type;
static const struct nft_expr_ops nft_nat_ops = {
.type = &nft_nat_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
.eval = nft_nat_eval,
.init = nft_nat_init,
+ .destroy = nft_nat_destroy,
.dump = nft_nat_dump,
.validate = nft_nat_validate,
};
diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c
index 55bc5ab78d4a..a66b36097b8f 100644
--- a/net/netfilter/nft_numgen.c
+++ b/net/netfilter/nft_numgen.c
@@ -65,7 +65,7 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
return -EOVERFLOW;
priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
- atomic_set(&priv->counter, 0);
+ atomic_set(&priv->counter, priv->modulus - 1);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c
new file mode 100644
index 000000000000..415a65ba2b85
--- /dev/null
+++ b/net/netfilter/nft_objref.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+#define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr))
+
+static void nft_objref_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_object *obj = nft_objref_priv(expr);
+
+ obj->type->eval(obj, regs, pkt);
+}
+
+static int nft_objref_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_object *obj = nft_objref_priv(expr);
+ u8 genmask = nft_genmask_next(ctx->net);
+ u32 objtype;
+
+ if (!tb[NFTA_OBJREF_IMM_NAME] ||
+ !tb[NFTA_OBJREF_IMM_TYPE])
+ return -EINVAL;
+
+ objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE]));
+ obj = nf_tables_obj_lookup(ctx->table, tb[NFTA_OBJREF_IMM_NAME], objtype,
+ genmask);
+ if (IS_ERR(obj))
+ return -ENOENT;
+
+ nft_objref_priv(expr) = obj;
+ obj->use++;
+
+ return 0;
+}
+
+static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_object *obj = nft_objref_priv(expr);
+
+ if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->name) ||
+ nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE, htonl(obj->type->type)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static void nft_objref_destroy(const struct nft_ctx *ctx,
+ const struct nft_expr *expr)
+{
+ struct nft_object *obj = nft_objref_priv(expr);
+
+ obj->use--;
+}
+
+static struct nft_expr_type nft_objref_type;
+static const struct nft_expr_ops nft_objref_ops = {
+ .type = &nft_objref_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)),
+ .eval = nft_objref_eval,
+ .init = nft_objref_init,
+ .destroy = nft_objref_destroy,
+ .dump = nft_objref_dump,
+};
+
+struct nft_objref_map {
+ struct nft_set *set;
+ enum nft_registers sreg:8;
+ struct nft_set_binding binding;
+};
+
+static void nft_objref_map_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_objref_map *priv = nft_expr_priv(expr);
+ const struct nft_set *set = priv->set;
+ const struct nft_set_ext *ext;
+ struct nft_object *obj;
+ bool found;
+
+ found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg],
+ &ext);
+ if (!found) {
+ regs->verdict.code = NFT_BREAK;
+ return;
+ }
+ obj = *nft_set_ext_obj(ext);
+ obj->type->eval(obj, regs, pkt);
+}
+
+static int nft_objref_map_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_objref_map *priv = nft_expr_priv(expr);
+ u8 genmask = nft_genmask_next(ctx->net);
+ struct nft_set *set;
+ int err;
+
+ set = nf_tables_set_lookup(ctx->table, tb[NFTA_OBJREF_SET_NAME], genmask);
+ if (IS_ERR(set)) {
+ if (tb[NFTA_OBJREF_SET_ID]) {
+ set = nf_tables_set_lookup_byid(ctx->net,
+ tb[NFTA_OBJREF_SET_ID],
+ genmask);
+ }
+ if (IS_ERR(set))
+ return PTR_ERR(set);
+ }
+
+ if (!(set->flags & NFT_SET_OBJECT))
+ return -EINVAL;
+
+ priv->sreg = nft_parse_register(tb[NFTA_OBJREF_SET_SREG]);
+ err = nft_validate_register_load(priv->sreg, set->klen);
+ if (err < 0)
+ return err;
+
+ priv->binding.flags = set->flags & NFT_SET_OBJECT;
+
+ err = nf_tables_bind_set(ctx, set, &priv->binding);
+ if (err < 0)
+ return err;
+
+ priv->set = set;
+ return 0;
+}
+
+static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ const struct nft_objref_map *priv = nft_expr_priv(expr);
+
+ if (nft_dump_register(skb, NFTA_OBJREF_SET_SREG, priv->sreg) ||
+ nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static void nft_objref_map_destroy(const struct nft_ctx *ctx,
+ const struct nft_expr *expr)
+{
+ struct nft_objref_map *priv = nft_expr_priv(expr);
+
+ nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+}
+
+static struct nft_expr_type nft_objref_type;
+static const struct nft_expr_ops nft_objref_map_ops = {
+ .type = &nft_objref_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
+ .eval = nft_objref_map_eval,
+ .init = nft_objref_map_init,
+ .destroy = nft_objref_map_destroy,
+ .dump = nft_objref_map_dump,
+};
+
+static const struct nft_expr_ops *
+nft_objref_select_ops(const struct nft_ctx *ctx,
+ const struct nlattr * const tb[])
+{
+ if (tb[NFTA_OBJREF_SET_SREG] &&
+ (tb[NFTA_OBJREF_SET_NAME] ||
+ tb[NFTA_OBJREF_SET_ID]))
+ return &nft_objref_map_ops;
+ else if (tb[NFTA_OBJREF_IMM_NAME] &&
+ tb[NFTA_OBJREF_IMM_TYPE])
+ return &nft_objref_ops;
+
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = {
+ [NFTA_OBJREF_IMM_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJREF_IMM_TYPE] = { .type = NLA_U32 },
+ [NFTA_OBJREF_SET_SREG] = { .type = NLA_U32 },
+ [NFTA_OBJREF_SET_NAME] = { .type = NLA_STRING },
+ [NFTA_OBJREF_SET_ID] = { .type = NLA_U32 },
+};
+
+static struct nft_expr_type nft_objref_type __read_mostly = {
+ .name = "objref",
+ .select_ops = nft_objref_select_ops,
+ .policy = nft_objref_policy,
+ .maxattr = NFTA_OBJREF_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_objref_module_init(void)
+{
+ return nft_register_expr(&nft_objref_type);
+}
+
+static void __exit nft_objref_module_exit(void)
+{
+ nft_unregister_expr(&nft_objref_type);
+}
+
+module_init(nft_objref_module_init);
+module_exit(nft_objref_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_ALIAS_NFT_EXPR("objref");
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index b2f88617611a..36d2b1096546 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,6 +18,10 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+/* For layer 4 checksum field offset. */
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmpv6.h>
/* add vlan header into the user buffer for if tag was removed by offloads */
static bool
@@ -148,7 +153,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_payload_type;
static const struct nft_expr_ops nft_payload_ops = {
.type = &nft_payload_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
@@ -165,6 +169,87 @@ const struct nft_expr_ops nft_payload_fast_ops = {
.dump = nft_payload_dump,
};
+static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum)
+{
+ *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum));
+ if (*sum == 0)
+ *sum = CSUM_MANGLED_0;
+}
+
+static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff)
+{
+ struct udphdr *uh, _uh;
+
+ uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh);
+ if (!uh)
+ return false;
+
+ return uh->check;
+}
+
+static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
+ struct sk_buff *skb,
+ unsigned int *l4csum_offset)
+{
+ switch (pkt->tprot) {
+ case IPPROTO_TCP:
+ *l4csum_offset = offsetof(struct tcphdr, check);
+ break;
+ case IPPROTO_UDP:
+ if (!nft_payload_udp_checksum(skb, pkt->xt.thoff))
+ return -1;
+ /* Fall through. */
+ case IPPROTO_UDPLITE:
+ *l4csum_offset = offsetof(struct udphdr, check);
+ break;
+ case IPPROTO_ICMPV6:
+ *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
+ break;
+ default:
+ return -1;
+ }
+
+ *l4csum_offset += pkt->xt.thoff;
+ return 0;
+}
+
+static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
+ struct sk_buff *skb,
+ __wsum fsum, __wsum tsum)
+{
+ int l4csum_offset;
+ __sum16 sum;
+
+ /* If we cannot determine layer 4 checksum offset or this packet doesn't
+ * require layer 4 checksum recalculation, skip this packet.
+ */
+ if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0)
+ return 0;
+
+ if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
+ return -1;
+
+ /* Checksum mangling for an arbitrary amount of bytes, based on
+ * inet_proto_csum_replace*() functions.
+ */
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ nft_csum_replace(&sum, fsum, tsum);
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum),
+ tsum);
+ }
+ } else {
+ sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum),
+ tsum));
+ }
+
+ if (!skb_make_writable(skb, l4csum_offset + sizeof(sum)) ||
+ skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
+ return -1;
+
+ return 0;
+}
+
static void nft_payload_set_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
@@ -205,14 +290,15 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
fsum = skb_checksum(skb, offset, priv->len, 0);
tsum = csum_partial(src, priv->len, 0);
- sum = csum_fold(csum_add(csum_sub(~csum_unfold(sum), fsum),
- tsum));
- if (sum == 0)
- sum = CSUM_MANGLED_0;
+ nft_csum_replace(&sum, fsum, tsum);
if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
goto err;
+
+ if (priv->csum_flags &&
+ nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0)
+ goto err;
}
if (!skb_make_writable(skb, max(offset + priv->len, 0)) ||
@@ -241,6 +327,15 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
if (tb[NFTA_PAYLOAD_CSUM_OFFSET])
priv->csum_offset =
ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));
+ if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) {
+ u32 flags;
+
+ flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS]));
+ if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR)
+ return -EINVAL;
+
+ priv->csum_flags = flags;
+ }
switch (priv->csum_type) {
case NFT_PAYLOAD_CSUM_NONE:
@@ -263,7 +358,8 @@ static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr
nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) ||
nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) ||
nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET,
- htonl(priv->csum_offset)))
+ htonl(priv->csum_offset)) ||
+ nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags)))
goto nla_put_failure;
return 0;
@@ -320,20 +416,10 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
return &nft_payload_ops;
}
-static struct nft_expr_type nft_payload_type __read_mostly = {
+struct nft_expr_type nft_payload_type __read_mostly = {
.name = "payload",
.select_ops = nft_payload_select_ops,
.policy = nft_payload_policy,
.maxattr = NFTA_PAYLOAD_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_payload_module_init(void)
-{
- return nft_register_expr(&nft_payload_type);
-}
-
-void nft_payload_module_exit(void)
-{
- nft_unregister_expr(&nft_payload_type);
-}
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
index 393d359a1889..3e19fa1230dc 100644
--- a/net/netfilter/nft_queue.c
+++ b/net/netfilter/nft_queue.c
@@ -43,7 +43,7 @@ static void nft_queue_eval(const struct nft_expr *expr,
queue = priv->queuenum + cpu % priv->queues_total;
} else {
queue = nfqueue_hash(pkt->skb, queue,
- priv->queues_total, pkt->pf,
+ priv->queues_total, nft_pf(pkt),
jhash_initval);
}
}
diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
index c00104c07095..bd6efc53f26d 100644
--- a/net/netfilter/nft_quota.c
+++ b/net/netfilter/nft_quota.c
@@ -17,38 +17,59 @@
struct nft_quota {
u64 quota;
- bool invert;
- atomic64_t remain;
+ unsigned long flags;
+ atomic64_t consumed;
};
static inline bool nft_overquota(struct nft_quota *priv,
- const struct nft_pktinfo *pkt)
+ const struct sk_buff *skb)
{
- return atomic64_sub_return(pkt->skb->len, &priv->remain) < 0;
+ return atomic64_add_return(skb->len, &priv->consumed) >= priv->quota;
}
-static void nft_quota_eval(const struct nft_expr *expr,
- struct nft_regs *regs,
- const struct nft_pktinfo *pkt)
+static inline bool nft_quota_invert(struct nft_quota *priv)
{
- struct nft_quota *priv = nft_expr_priv(expr);
+ return priv->flags & NFT_QUOTA_F_INV;
+}
- if (nft_overquota(priv, pkt) ^ priv->invert)
+static inline void nft_quota_do_eval(struct nft_quota *priv,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ if (nft_overquota(priv, pkt->skb) ^ nft_quota_invert(priv))
regs->verdict.code = NFT_BREAK;
}
static const struct nla_policy nft_quota_policy[NFTA_QUOTA_MAX + 1] = {
[NFTA_QUOTA_BYTES] = { .type = NLA_U64 },
[NFTA_QUOTA_FLAGS] = { .type = NLA_U32 },
+ [NFTA_QUOTA_CONSUMED] = { .type = NLA_U64 },
};
-static int nft_quota_init(const struct nft_ctx *ctx,
- const struct nft_expr *expr,
- const struct nlattr * const tb[])
+#define NFT_QUOTA_DEPLETED_BIT 1 /* From NFT_QUOTA_F_DEPLETED. */
+
+static void nft_quota_obj_eval(struct nft_object *obj,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
{
- struct nft_quota *priv = nft_expr_priv(expr);
- u32 flags = 0;
- u64 quota;
+ struct nft_quota *priv = nft_obj_data(obj);
+ bool overquota;
+
+ overquota = nft_overquota(priv, pkt->skb);
+ if (overquota ^ nft_quota_invert(priv))
+ regs->verdict.code = NFT_BREAK;
+
+ if (overquota &&
+ !test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
+ nft_obj_notify(nft_net(pkt), obj->table, obj, 0, 0,
+ NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC);
+}
+
+static int nft_quota_do_init(const struct nlattr * const tb[],
+ struct nft_quota *priv)
+{
+ unsigned long flags = 0;
+ u64 quota, consumed = 0;
if (!tb[NFTA_QUOTA_BYTES])
return -EINVAL;
@@ -57,26 +78,60 @@ static int nft_quota_init(const struct nft_ctx *ctx,
if (quota > S64_MAX)
return -EOVERFLOW;
+ if (tb[NFTA_QUOTA_CONSUMED]) {
+ consumed = be64_to_cpu(nla_get_be64(tb[NFTA_QUOTA_CONSUMED]));
+ if (consumed > quota)
+ return -EINVAL;
+ }
+
if (tb[NFTA_QUOTA_FLAGS]) {
flags = ntohl(nla_get_be32(tb[NFTA_QUOTA_FLAGS]));
if (flags & ~NFT_QUOTA_F_INV)
return -EINVAL;
+ if (flags & NFT_QUOTA_F_DEPLETED)
+ return -EOPNOTSUPP;
}
priv->quota = quota;
- priv->invert = (flags & NFT_QUOTA_F_INV) ? true : false;
- atomic64_set(&priv->remain, quota);
+ priv->flags = flags;
+ atomic64_set(&priv->consumed, consumed);
return 0;
}
-static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)
+static int nft_quota_obj_init(const struct nlattr * const tb[],
+ struct nft_object *obj)
+{
+ struct nft_quota *priv = nft_obj_data(obj);
+
+ return nft_quota_do_init(tb, priv);
+}
+
+static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
+ bool reset)
{
- const struct nft_quota *priv = nft_expr_priv(expr);
- u32 flags = priv->invert ? NFT_QUOTA_F_INV : 0;
+ u32 flags = priv->flags;
+ u64 consumed;
+
+ if (reset) {
+ consumed = atomic64_xchg(&priv->consumed, 0);
+ if (test_and_clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
+ flags |= NFT_QUOTA_F_DEPLETED;
+ } else {
+ consumed = atomic64_read(&priv->consumed);
+ }
+
+ /* Since we inconditionally increment consumed quota for each packet
+ * that we see, don't go over the quota boundary in what we send to
+ * userspace.
+ */
+ if (consumed > priv->quota)
+ consumed = priv->quota;
if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),
NFTA_QUOTA_PAD) ||
+ nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed),
+ NFTA_QUOTA_PAD) ||
nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
goto nla_put_failure;
return 0;
@@ -85,6 +140,50 @@ nla_put_failure:
return -1;
}
+static int nft_quota_obj_dump(struct sk_buff *skb, struct nft_object *obj,
+ bool reset)
+{
+ struct nft_quota *priv = nft_obj_data(obj);
+
+ return nft_quota_do_dump(skb, priv, reset);
+}
+
+static struct nft_object_type nft_quota_obj __read_mostly = {
+ .type = NFT_OBJECT_QUOTA,
+ .size = sizeof(struct nft_quota),
+ .maxattr = NFTA_QUOTA_MAX,
+ .policy = nft_quota_policy,
+ .init = nft_quota_obj_init,
+ .eval = nft_quota_obj_eval,
+ .dump = nft_quota_obj_dump,
+ .owner = THIS_MODULE,
+};
+
+static void nft_quota_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ struct nft_quota *priv = nft_expr_priv(expr);
+
+ nft_quota_do_eval(priv, regs, pkt);
+}
+
+static int nft_quota_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_quota *priv = nft_expr_priv(expr);
+
+ return nft_quota_do_init(tb, priv);
+}
+
+static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+ struct nft_quota *priv = nft_expr_priv(expr);
+
+ return nft_quota_do_dump(skb, priv, false);
+}
+
static struct nft_expr_type nft_quota_type;
static const struct nft_expr_ops nft_quota_ops = {
.type = &nft_quota_type,
@@ -105,12 +204,26 @@ static struct nft_expr_type nft_quota_type __read_mostly = {
static int __init nft_quota_module_init(void)
{
- return nft_register_expr(&nft_quota_type);
+ int err;
+
+ err = nft_register_obj(&nft_quota_obj);
+ if (err < 0)
+ return err;
+
+ err = nft_register_expr(&nft_quota_type);
+ if (err < 0)
+ goto err1;
+
+ return 0;
+err1:
+ nft_unregister_obj(&nft_quota_obj);
+ return err;
}
static void __exit nft_quota_module_exit(void)
{
- nft_unregister_expr(&nft_quota_type);
+ nft_unregister_expr(&nft_quota_type);
+ nft_unregister_obj(&nft_quota_obj);
}
module_init(nft_quota_module_init);
@@ -119,3 +232,4 @@ module_exit(nft_quota_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
MODULE_ALIAS_NFT_EXPR("quota");
+MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_QUOTA);
diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c
index 8f0aaaea1376..9edc74eedc10 100644
--- a/net/netfilter/nft_range.c
+++ b/net/netfilter/nft_range.c
@@ -128,7 +128,6 @@ nla_put_failure:
return -1;
}
-static struct nft_expr_type nft_range_type;
static const struct nft_expr_ops nft_range_ops = {
.type = &nft_range_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_range_expr)),
@@ -137,20 +136,10 @@ static const struct nft_expr_ops nft_range_ops = {
.dump = nft_range_dump,
};
-static struct nft_expr_type nft_range_type __read_mostly = {
+struct nft_expr_type nft_range_type __read_mostly = {
.name = "range",
.ops = &nft_range_ops,
.policy = nft_range_policy,
.maxattr = NFTA_RANGE_MAX,
.owner = THIS_MODULE,
};
-
-int __init nft_range_module_init(void)
-{
- return nft_register_expr(&nft_range_type);
-}
-
-void nft_range_module_exit(void)
-{
- nft_unregister_expr(&nft_range_type);
-}
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 03f7bf40ae75..40dcd05146d5 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
+ * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -79,7 +79,7 @@ int nft_redir_init(const struct nft_ctx *ctx,
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(ctx->net, ctx->afi->family);
}
EXPORT_SYMBOL_GPL(nft_redir_init);
@@ -108,4 +108,4 @@ nla_put_failure:
EXPORT_SYMBOL_GPL(nft_redir_dump);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c
index e79d9ca2ffee..9e90a02cb104 100644
--- a/net/netfilter/nft_reject_inet.c
+++ b/net/netfilter/nft_reject_inet.c
@@ -23,36 +23,36 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
{
struct nft_reject *priv = nft_expr_priv(expr);
- switch (pkt->pf) {
+ switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nf_send_unreach(pkt->skb, priv->icmp_code,
- pkt->hook);
+ nft_hook(pkt));
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset(pkt->net, pkt->skb, pkt->hook);
+ nf_send_reset(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
case NFT_REJECT_ICMPX_UNREACH:
nf_send_unreach(pkt->skb,
nft_reject_icmp_code(priv->icmp_code),
- pkt->hook);
+ nft_hook(pkt));
break;
}
break;
case NFPROTO_IPV6:
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach6(pkt->net, pkt->skb, priv->icmp_code,
- pkt->hook);
+ nf_send_unreach6(nft_net(pkt), pkt->skb,
+ priv->icmp_code, nft_hook(pkt));
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset6(pkt->net, pkt->skb, pkt->hook);
+ nf_send_reset6(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
case NFT_REJECT_ICMPX_UNREACH:
- nf_send_unreach6(pkt->net, pkt->skb,
+ nf_send_unreach6(nft_net(pkt), pkt->skb,
nft_reject_icmpv6_code(priv->icmp_code),
- pkt->hook);
+ nft_hook(pkt));
break;
}
break;
diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c
new file mode 100644
index 000000000000..d3eb640bc784
--- /dev/null
+++ b/net/netfilter/nft_rt.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016 Anders K. Pedersen <akp@cohaesio.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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/dst.h>
+#include <net/ip6_route.h>
+#include <net/route.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+
+struct nft_rt {
+ enum nft_rt_keys key:8;
+ enum nft_registers dreg:8;
+};
+
+void nft_rt_get_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_rt *priv = nft_expr_priv(expr);
+ const struct sk_buff *skb = pkt->skb;
+ u32 *dest = &regs->data[priv->dreg];
+ const struct dst_entry *dst;
+
+ dst = skb_dst(skb);
+ if (!dst)
+ goto err;
+
+ switch (priv->key) {
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ case NFT_RT_CLASSID:
+ *dest = dst->tclassid;
+ break;
+#endif
+ case NFT_RT_NEXTHOP4:
+ if (nft_pf(pkt) != NFPROTO_IPV4)
+ goto err;
+
+ *dest = rt_nexthop((const struct rtable *)dst,
+ ip_hdr(skb)->daddr);
+ break;
+ case NFT_RT_NEXTHOP6:
+ if (nft_pf(pkt) != NFPROTO_IPV6)
+ goto err;
+
+ memcpy(dest, rt6_nexthop((struct rt6_info *)dst,
+ &ipv6_hdr(skb)->daddr),
+ sizeof(struct in6_addr));
+ break;
+ default:
+ WARN_ON(1);
+ goto err;
+ }
+ return;
+
+err:
+ regs->verdict.code = NFT_BREAK;
+}
+
+const struct nla_policy nft_rt_policy[NFTA_RT_MAX + 1] = {
+ [NFTA_RT_DREG] = { .type = NLA_U32 },
+ [NFTA_RT_KEY] = { .type = NLA_U32 },
+};
+
+int nft_rt_get_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_rt *priv = nft_expr_priv(expr);
+ unsigned int len;
+
+ if (tb[NFTA_RT_KEY] == NULL ||
+ tb[NFTA_RT_DREG] == NULL)
+ return -EINVAL;
+
+ priv->key = ntohl(nla_get_be32(tb[NFTA_RT_KEY]));
+ switch (priv->key) {
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ case NFT_RT_CLASSID:
+#endif
+ case NFT_RT_NEXTHOP4:
+ len = sizeof(u32);
+ break;
+ case NFT_RT_NEXTHOP6:
+ len = sizeof(struct in6_addr);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]);
+ return nft_validate_register_store(ctx, priv->dreg, NULL,
+ NFT_DATA_VALUE, len);
+}
+
+int nft_rt_get_dump(struct sk_buff *skb,
+ const struct nft_expr *expr)
+{
+ const struct nft_rt *priv = nft_expr_priv(expr);
+
+ if (nla_put_be32(skb, NFTA_RT_KEY, htonl(priv->key)))
+ goto nla_put_failure;
+ if (nft_dump_register(skb, NFTA_RT_DREG, priv->dreg))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nft_expr_type nft_rt_type;
+static const struct nft_expr_ops nft_rt_get_ops = {
+ .type = &nft_rt_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_rt)),
+ .eval = nft_rt_get_eval,
+ .init = nft_rt_get_init,
+ .dump = nft_rt_get_dump,
+};
+
+static struct nft_expr_type nft_rt_type __read_mostly = {
+ .name = "rt",
+ .ops = &nft_rt_get_ops,
+ .policy = nft_rt_policy,
+ .maxattr = NFTA_RT_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_rt_module_init(void)
+{
+ return nft_register_expr(&nft_rt_type);
+}
+
+static void __exit nft_rt_module_exit(void)
+{
+ nft_unregister_expr(&nft_rt_type);
+}
+
+module_init(nft_rt_module_init);
+module_exit(nft_rt_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anders K. Pedersen <akp@cohaesio.com>");
+MODULE_ALIAS_NFT_EXPR("rt");
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index a3dface3e6e6..1e20e2bbb6d9 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -167,6 +167,19 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set,
nft_set_elem_clear_busy(&he->ext);
}
+static bool nft_hash_deactivate_one(const struct net *net,
+ const struct nft_set *set, void *priv)
+{
+ struct nft_hash_elem *he = priv;
+
+ if (!nft_set_elem_mark_busy(&he->ext) ||
+ !nft_is_active(net, &he->ext)) {
+ nft_set_elem_change_active(net, set, &he->ext);
+ return true;
+ }
+ return false;
+}
+
static void *nft_hash_deactivate(const struct net *net,
const struct nft_set *set,
const struct nft_set_elem *elem)
@@ -181,13 +194,10 @@ static void *nft_hash_deactivate(const struct net *net,
rcu_read_lock();
he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
- if (he != NULL) {
- if (!nft_set_elem_mark_busy(&he->ext) ||
- !nft_is_active(net, &he->ext))
- nft_set_elem_change_active(net, set, &he->ext);
- else
- he = NULL;
- }
+ if (he != NULL &&
+ !nft_hash_deactivate_one(net, set, he))
+ he = NULL;
+
rcu_read_unlock();
return he;
@@ -387,6 +397,7 @@ static struct nft_set_ops nft_hash_ops __read_mostly = {
.insert = nft_hash_insert,
.activate = nft_hash_activate,
.deactivate = nft_hash_deactivate,
+ .deactivate_one = nft_hash_deactivate_one,
.remove = nft_hash_remove,
.lookup = nft_hash_lookup,
.update = nft_hash_update,
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 36493a7cae88..08376e50f6cd 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -171,6 +171,15 @@ static void nft_rbtree_activate(const struct net *net,
nft_set_elem_change_active(net, set, &rbe->ext);
}
+static bool nft_rbtree_deactivate_one(const struct net *net,
+ const struct nft_set *set, void *priv)
+{
+ struct nft_rbtree_elem *rbe = priv;
+
+ nft_set_elem_change_active(net, set, &rbe->ext);
+ return true;
+}
+
static void *nft_rbtree_deactivate(const struct net *net,
const struct nft_set *set,
const struct nft_set_elem *elem)
@@ -204,7 +213,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
parent = parent->rb_right;
continue;
}
- nft_set_elem_change_active(net, set, &rbe->ext);
+ nft_rbtree_deactivate_one(net, set, rbe);
return rbe;
}
}
@@ -295,6 +304,7 @@ static struct nft_set_ops nft_rbtree_ops __read_mostly = {
.insert = nft_rbtree_insert,
.remove = nft_rbtree_remove,
.deactivate = nft_rbtree_deactivate,
+ .deactivate_one = nft_rbtree_deactivate_one,
.activate = nft_rbtree_activate,
.lookup = nft_rbtree_lookup,
.walk = nft_rbtree_walk,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index fc4977456c30..2ff499680cc6 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -40,6 +40,7 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
+#define XT_PCPU_BLOCK_SIZE 4096
struct compat_delta {
unsigned int offset; /* offset in kernel */
@@ -958,7 +959,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
if (!info) {
- info = vmalloc(sz);
+ info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN |
+ __GFP_NORETRY | __GFP_HIGHMEM,
+ PAGE_KERNEL);
if (!info)
return NULL;
}
@@ -982,7 +985,7 @@ void xt_free_table_info(struct xt_table_info *info)
}
EXPORT_SYMBOL(xt_free_table_info);
-/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
+/* Find table by name, grabs mutex & ref. Returns NULL on error. */
struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
const char *name)
{
@@ -1615,6 +1618,59 @@ void xt_proto_fini(struct net *net, u_int8_t af)
}
EXPORT_SYMBOL_GPL(xt_proto_fini);
+/**
+ * xt_percpu_counter_alloc - allocate x_tables rule counter
+ *
+ * @state: pointer to xt_percpu allocation state
+ * @counter: pointer to counter struct inside the ip(6)/arpt_entry struct
+ *
+ * On SMP, the packet counter [ ip(6)t_entry->counters.pcnt ] will then
+ * contain the address of the real (percpu) counter.
+ *
+ * Rule evaluation needs to use xt_get_this_cpu_counter() helper
+ * to fetch the real percpu counter.
+ *
+ * To speed up allocation and improve data locality, a 4kb block is
+ * allocated.
+ *
+ * xt_percpu_counter_alloc_state contains the base address of the
+ * allocated page and the current sub-offset.
+ *
+ * returns false on error.
+ */
+bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state,
+ struct xt_counters *counter)
+{
+ BUILD_BUG_ON(XT_PCPU_BLOCK_SIZE < (sizeof(*counter) * 2));
+
+ if (nr_cpu_ids <= 1)
+ return true;
+
+ if (!state->mem) {
+ state->mem = __alloc_percpu(XT_PCPU_BLOCK_SIZE,
+ XT_PCPU_BLOCK_SIZE);
+ if (!state->mem)
+ return false;
+ }
+ counter->pcnt = (__force unsigned long)(state->mem + state->off);
+ state->off += sizeof(*counter);
+ if (state->off > (XT_PCPU_BLOCK_SIZE - sizeof(*counter))) {
+ state->mem = NULL;
+ state->off = 0;
+ }
+ return true;
+}
+EXPORT_SYMBOL_GPL(xt_percpu_counter_alloc);
+
+void xt_percpu_counter_free(struct xt_counters *counters)
+{
+ unsigned long pcnt = counters->pcnt;
+
+ if (nr_cpu_ids > 1 && (pcnt & (XT_PCPU_BLOCK_SIZE - 1)) == 0)
+ free_percpu((void __percpu *)pcnt);
+}
+EXPORT_SYMBOL_GPL(xt_percpu_counter_free);
+
static int __net_init xt_net_init(struct net *net)
{
int i;
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 4973cbddc446..19247a17e511 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -132,9 +132,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
goto errout;
audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s",
- info->type, par->hooknum, skb->len,
- par->in ? par->in->name : "?",
- par->out ? par->out->name : "?");
+ info->type, xt_hooknum(par), skb->len,
+ xt_in(par) ? xt_inname(par) : "?",
+ xt_out(par) ? xt_outname(par) : "?");
if (skb->mark)
audit_log_format(ab, " mark=%#x", skb->mark);
@@ -144,7 +144,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
ntohs(eth_hdr(skb)->h_proto));
- if (par->family == NFPROTO_BRIDGE) {
+ if (xt_family(par) == NFPROTO_BRIDGE) {
switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
audit_ip4(ab, skb);
@@ -157,7 +157,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
}
}
- switch (par->family) {
+ switch (xt_family(par)) {
case NFPROTO_IPV4:
audit_ip4(ab, skb);
break;
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index e04dc282e3bb..da56c06a443c 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -106,7 +106,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
return -EINVAL;
}
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -115,7 +115,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par)
static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_target connsecmark_tg_reg __read_mostly = {
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 6669e68d589e..95c750358747 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -216,7 +216,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
goto err1;
#endif
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
goto err1;
@@ -260,7 +260,7 @@ out:
err3:
nf_ct_tmpl_free(ct);
err2:
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
err1:
return ret;
}
@@ -341,7 +341,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
if (help)
module_put(help->helper->me);
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
xt_ct_destroy_timeout(ct);
nf_ct_put(info->ct);
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index 1763ab82bcd7..c3b2017ebe41 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -32,15 +32,15 @@ static unsigned int
log_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_log_info *loginfo = par->targinfo;
+ struct net *net = xt_net(par);
struct nf_loginfo li;
- struct net *net = par->net;
li.type = NF_LOG_TYPE_LOG;
li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags;
- nf_log_packet(net, par->family, par->hooknum, skb, par->in, par->out,
- &li, "%s", loginfo->prefix);
+ nf_log_packet(net, xt_family(par), xt_hooknum(par), skb, xt_in(par),
+ xt_out(par), &li, "%s", loginfo->prefix);
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_NETMAP.c b/net/netfilter/xt_NETMAP.c
index b253e07cb1c5..e45a01255e70 100644
--- a/net/netfilter/xt_NETMAP.c
+++ b/net/netfilter/xt_NETMAP.c
@@ -33,8 +33,8 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
range->max_addr.ip6[i]);
- if (par->hooknum == NF_INET_PRE_ROUTING ||
- par->hooknum == NF_INET_LOCAL_OUT)
+ if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+ xt_hooknum(par) == NF_INET_LOCAL_OUT)
new_addr.in6 = ipv6_hdr(skb)->daddr;
else
new_addr.in6 = ipv6_hdr(skb)->saddr;
@@ -51,7 +51,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
newrange.min_proto = range->min_proto;
newrange.max_proto = range->max_proto;
- return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+ return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
}
static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -60,7 +60,12 @@ static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
return -EINVAL;
- return 0;
+ return nf_ct_netns_get(par->net, par->family);
+}
+
+static void netmap_tg_destroy(const struct xt_tgdtor_param *par)
+{
+ nf_ct_netns_put(par->net, par->family);
}
static unsigned int
@@ -72,16 +77,16 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
struct nf_nat_range newrange;
- NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
- par->hooknum == NF_INET_POST_ROUTING ||
- par->hooknum == NF_INET_LOCAL_OUT ||
- par->hooknum == NF_INET_LOCAL_IN);
+ NF_CT_ASSERT(xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+ xt_hooknum(par) == NF_INET_POST_ROUTING ||
+ xt_hooknum(par) == NF_INET_LOCAL_OUT ||
+ xt_hooknum(par) == NF_INET_LOCAL_IN);
ct = nf_ct_get(skb, &ctinfo);
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
- if (par->hooknum == NF_INET_PRE_ROUTING ||
- par->hooknum == NF_INET_LOCAL_OUT)
+ if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+ xt_hooknum(par) == NF_INET_LOCAL_OUT)
new_ip = ip_hdr(skb)->daddr & ~netmask;
else
new_ip = ip_hdr(skb)->saddr & ~netmask;
@@ -96,7 +101,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
newrange.max_proto = mr->range[0].max;
/* Hand modified range to generic setup. */
- return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+ return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
}
static int netmap_tg4_check(const struct xt_tgchk_param *par)
@@ -111,7 +116,7 @@ static int netmap_tg4_check(const struct xt_tgchk_param *par)
pr_debug("bad rangesize %u.\n", mr->rangesize);
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(par->net, par->family);
}
static struct xt_target netmap_tg_reg[] __read_mostly = {
@@ -127,6 +132,7 @@ static struct xt_target netmap_tg_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_LOCAL_IN),
.checkentry = netmap_tg6_checkentry,
+ .destroy = netmap_tg_destroy,
.me = THIS_MODULE,
},
{
@@ -141,6 +147,7 @@ static struct xt_target netmap_tg_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_LOCAL_IN),
.checkentry = netmap_tg4_check,
+ .destroy = netmap_tg_destroy,
.me = THIS_MODULE,
},
};
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 8668a5c18dc3..c7f8958cea4a 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -25,8 +25,8 @@ static unsigned int
nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_nflog_info *info = par->targinfo;
+ struct net *net = xt_net(par);
struct nf_loginfo li;
- struct net *net = par->net;
li.type = NF_LOG_TYPE_ULOG;
li.u.ulog.copy_len = info->len;
@@ -37,8 +37,8 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (info->flags & XT_NFLOG_F_COPY_LEN)
li.u.ulog.flags |= NF_LOG_F_COPY_LEN;
- nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in,
- par->out, &li, info->prefix);
+ nfulnl_log_packet(net, xt_family(par), xt_hooknum(par), skb,
+ xt_in(par), xt_out(par), &li, info->prefix);
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 8f1779ff7e30..a360b99a958a 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -43,7 +43,7 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
if (info->queues_total > 1) {
queue = nfqueue_hash(skb, queue, info->queues_total,
- par->family, jhash_initval);
+ xt_family(par), jhash_initval);
}
return NF_QUEUE_NR(queue);
}
@@ -98,7 +98,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
queue = info->queuenum + cpu % info->queues_total;
} else {
queue = nfqueue_hash(skb, queue, info->queues_total,
- par->family, jhash_initval);
+ xt_family(par), jhash_initval);
}
}
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index dbd6c4a12b97..91a373a3f534 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -63,7 +63,7 @@ void xt_rateest_put(struct xt_rateest *est)
mutex_lock(&xt_rateest_mutex);
if (--est->refcnt == 0) {
hlist_del(&est->list);
- gen_kill_estimator(&est->bstats, &est->rstats);
+ gen_kill_estimator(&est->rate_est);
/*
* gen_estimator est_timer() might access est->lock or bstats,
* wait a RCU grace period before freeing 'est'
@@ -132,7 +132,7 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
cfg.est.interval = info->interval;
cfg.est.ewma_log = info->ewma_log;
- ret = gen_new_estimator(&est->bstats, NULL, &est->rstats,
+ ret = gen_new_estimator(&est->bstats, NULL, &est->rate_est,
&est->lock, NULL, &cfg.opt);
if (ret < 0)
goto err2;
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c
index 03f0b370e178..98a4c6d4f1cb 100644
--- a/net/netfilter/xt_REDIRECT.c
+++ b/net/netfilter/xt_REDIRECT.c
@@ -31,7 +31,7 @@
static unsigned int
redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
- return nf_nat_redirect_ipv6(skb, par->targinfo, par->hooknum);
+ return nf_nat_redirect_ipv6(skb, par->targinfo, xt_hooknum(par));
}
static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -40,7 +40,13 @@ static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
if (range->flags & NF_NAT_RANGE_MAP_IPS)
return -EINVAL;
- return 0;
+
+ return nf_ct_netns_get(par->net, par->family);
+}
+
+static void redirect_tg_destroy(const struct xt_tgdtor_param *par)
+{
+ nf_ct_netns_put(par->net, par->family);
}
/* FIXME: Take multiple ranges --RR */
@@ -56,13 +62,13 @@ static int redirect_tg4_check(const struct xt_tgchk_param *par)
pr_debug("bad rangesize %u.\n", mr->rangesize);
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(par->net, par->family);
}
static unsigned int
redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par)
{
- return nf_nat_redirect_ipv4(skb, par->targinfo, par->hooknum);
+ return nf_nat_redirect_ipv4(skb, par->targinfo, xt_hooknum(par));
}
static struct xt_target redirect_tg_reg[] __read_mostly = {
@@ -72,6 +78,7 @@ static struct xt_target redirect_tg_reg[] __read_mostly = {
.revision = 0,
.table = "nat",
.checkentry = redirect_tg6_checkentry,
+ .destroy = redirect_tg_destroy,
.target = redirect_tg6,
.targetsize = sizeof(struct nf_nat_range),
.hooks = (1 << NF_INET_PRE_ROUTING) |
@@ -85,6 +92,7 @@ static struct xt_target redirect_tg_reg[] __read_mostly = {
.table = "nat",
.target = redirect_tg4,
.checkentry = redirect_tg4_check,
+ .destroy = redirect_tg_destroy,
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
.hooks = (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_OUT),
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 872db2d0e2a9..27241a767f17 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -108,7 +108,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
return -1;
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
- struct net *net = par->net;
+ struct net *net = xt_net(par);
unsigned int in_mtu = tcpmss_reverse_mtu(net, skb, family);
unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu);
@@ -172,7 +172,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
* length IPv6 header of 60, ergo the default MSS value is 1220
* Since no MSS was provided, we must use the default values
*/
- if (par->family == NFPROTO_IPV4)
+ if (xt_family(par) == NFPROTO_IPV4)
newmss = min(newmss, (u16)536);
else
newmss = min(newmss, (u16)1220);
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 0471db4032c5..1c57ace75ae6 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -33,7 +33,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
const struct xt_tee_tginfo *info = par->targinfo;
int oif = info->priv ? info->priv->oif : 0;
- nf_dup_ipv4(par->net, skb, par->hooknum, &info->gw.in, oif);
+ nf_dup_ipv4(xt_net(par), skb, xt_hooknum(par), &info->gw.in, oif);
return XT_CONTINUE;
}
@@ -45,7 +45,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
const struct xt_tee_tginfo *info = par->targinfo;
int oif = info->priv ? info->priv->oif : 0;
- nf_dup_ipv6(par->net, skb, par->hooknum, &info->gw.in6, oif);
+ nf_dup_ipv6(xt_net(par), skb, xt_hooknum(par), &info->gw.in6, oif);
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 663c4c3c9072..80cb7babeb64 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -364,7 +364,8 @@ tproxy_tg4_v0(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_tproxy_target_info *tgi = par->targinfo;
- return tproxy_tg4(par->net, skb, tgi->laddr, tgi->lport, tgi->mark_mask, tgi->mark_value);
+ return tproxy_tg4(xt_net(par), skb, tgi->laddr, tgi->lport,
+ tgi->mark_mask, tgi->mark_value);
}
static unsigned int
@@ -372,7 +373,8 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
- return tproxy_tg4(par->net, skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
+ return tproxy_tg4(xt_net(par), skb, tgi->laddr.ip, tgi->lport,
+ tgi->mark_mask, tgi->mark_value);
}
#ifdef XT_TPROXY_HAVE_IPV6
@@ -442,7 +444,7 @@ tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
* to a listener socket if there's one */
struct sock *sk2;
- sk2 = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
+ sk2 = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto,
&iph->saddr,
tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
hp->source,
@@ -485,10 +487,10 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
* addresses, this happens if the redirect already happened
* and the current packet belongs to an already established
* connection */
- sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
+ sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto,
&iph->saddr, &iph->daddr,
hp->source, hp->dest,
- par->in, NFT_LOOKUP_ESTABLISHED);
+ xt_in(par), NFT_LOOKUP_ESTABLISHED);
laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr);
lport = tgi->lport ? tgi->lport : hp->dest;
@@ -500,10 +502,10 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
else if (!sk)
/* no there's no established connection, check if
* there's a listener on the redirected addr/port */
- sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp,
+ sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp,
tproto, &iph->saddr, laddr,
hp->source, lport,
- par->in, NFT_LOOKUP_LISTENER);
+ xt_in(par), NFT_LOOKUP_LISTENER);
/* NOTE: assign_sock consumes our sk reference */
if (sk && tproxy_sk_is_transparent(sk)) {
@@ -529,6 +531,11 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
static int tproxy_tg6_check(const struct xt_tgchk_param *par)
{
const struct ip6t_ip6 *i = par->entryinfo;
+ int err;
+
+ err = nf_defrag_ipv6_enable(par->net);
+ if (err)
+ return err;
if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&
!(i->invflags & IP6T_INV_PROTO))
@@ -543,6 +550,11 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par)
static int tproxy_tg4_check(const struct xt_tgchk_param *par)
{
const struct ipt_ip *i = par->entryinfo;
+ int err;
+
+ err = nf_defrag_ipv4_enable(par->net);
+ if (err)
+ return err;
if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
&& !(i->invflags & IPT_INV_PROTO))
@@ -594,11 +606,6 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = {
static int __init tproxy_tg_init(void)
{
- nf_defrag_ipv4_enable();
-#ifdef XT_TPROXY_HAVE_IPV6
- nf_defrag_ipv6_enable();
-#endif
-
return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
}
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c
index 11d6091991a4..e329dabde35f 100644
--- a/net/netfilter/xt_addrtype.c
+++ b/net/netfilter/xt_addrtype.c
@@ -125,7 +125,7 @@ static inline bool match_type(struct net *net, const struct net_device *dev,
static bool
addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
{
- struct net *net = par->net;
+ struct net *net = xt_net(par);
const struct xt_addrtype_info *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
bool ret = true;
@@ -143,19 +143,19 @@ addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
static bool
addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
{
- struct net *net = par->net;
+ struct net *net = xt_net(par);
const struct xt_addrtype_info_v1 *info = par->matchinfo;
const struct iphdr *iph;
const struct net_device *dev = NULL;
bool ret = true;
if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
- dev = par->in;
+ dev = xt_in(par);
else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
- dev = par->out;
+ dev = xt_out(par);
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
- if (par->family == NFPROTO_IPV6)
+ if (xt_family(par) == NFPROTO_IPV6)
return addrtype_mt6(net, dev, skb, info);
#endif
iph = ip_hdr(skb);
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c
index dffee9d47ec4..2dedaa23ab0a 100644
--- a/net/netfilter/xt_bpf.c
+++ b/net/netfilter/xt_bpf.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/filter.h>
+#include <linux/bpf.h>
#include <linux/netfilter/xt_bpf.h>
#include <linux/netfilter/x_tables.h>
@@ -20,15 +21,15 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_bpf");
MODULE_ALIAS("ip6t_bpf");
-static int bpf_mt_check(const struct xt_mtchk_param *par)
+static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
+ struct bpf_prog **ret)
{
- struct xt_bpf_info *info = par->matchinfo;
struct sock_fprog_kern program;
- program.len = info->bpf_program_num_elem;
- program.filter = info->bpf_program;
+ program.len = len;
+ program.filter = insns;
- if (bpf_prog_create(&info->filter, &program)) {
+ if (bpf_prog_create(ret, &program)) {
pr_info("bpf: check failed: parse error\n");
return -EINVAL;
}
@@ -36,6 +37,42 @@ static int bpf_mt_check(const struct xt_mtchk_param *par)
return 0;
}
+static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret)
+{
+ struct bpf_prog *prog;
+
+ prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER);
+ if (IS_ERR(prog))
+ return PTR_ERR(prog);
+
+ *ret = prog;
+ return 0;
+}
+
+static int bpf_mt_check(const struct xt_mtchk_param *par)
+{
+ struct xt_bpf_info *info = par->matchinfo;
+
+ return __bpf_mt_check_bytecode(info->bpf_program,
+ info->bpf_program_num_elem,
+ &info->filter);
+}
+
+static int bpf_mt_check_v1(const struct xt_mtchk_param *par)
+{
+ struct xt_bpf_info_v1 *info = par->matchinfo;
+
+ if (info->mode == XT_BPF_MODE_BYTECODE)
+ return __bpf_mt_check_bytecode(info->bpf_program,
+ info->bpf_program_num_elem,
+ &info->filter);
+ else if (info->mode == XT_BPF_MODE_FD_PINNED ||
+ info->mode == XT_BPF_MODE_FD_ELF)
+ return __bpf_mt_check_fd(info->fd, &info->filter);
+ else
+ return -EINVAL;
+}
+
static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;
@@ -43,31 +80,58 @@ static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
return BPF_PROG_RUN(info->filter, skb);
}
+static bool bpf_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
+{
+ const struct xt_bpf_info_v1 *info = par->matchinfo;
+
+ return !!bpf_prog_run_save_cb(info->filter, (struct sk_buff *) skb);
+}
+
static void bpf_mt_destroy(const struct xt_mtdtor_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;
+
+ bpf_prog_destroy(info->filter);
+}
+
+static void bpf_mt_destroy_v1(const struct xt_mtdtor_param *par)
+{
+ const struct xt_bpf_info_v1 *info = par->matchinfo;
+
bpf_prog_destroy(info->filter);
}
-static struct xt_match bpf_mt_reg __read_mostly = {
- .name = "bpf",
- .revision = 0,
- .family = NFPROTO_UNSPEC,
- .checkentry = bpf_mt_check,
- .match = bpf_mt,
- .destroy = bpf_mt_destroy,
- .matchsize = sizeof(struct xt_bpf_info),
- .me = THIS_MODULE,
+static struct xt_match bpf_mt_reg[] __read_mostly = {
+ {
+ .name = "bpf",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = bpf_mt_check,
+ .match = bpf_mt,
+ .destroy = bpf_mt_destroy,
+ .matchsize = sizeof(struct xt_bpf_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "bpf",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = bpf_mt_check_v1,
+ .match = bpf_mt_v1,
+ .destroy = bpf_mt_destroy_v1,
+ .matchsize = sizeof(struct xt_bpf_info_v1),
+ .me = THIS_MODULE,
+ },
};
static int __init bpf_mt_init(void)
{
- return xt_register_match(&bpf_mt_reg);
+ return xt_register_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
}
static void __exit bpf_mt_exit(void)
{
- xt_unregister_match(&bpf_mt_reg);
+ xt_unregister_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
}
module_init(bpf_mt_init);
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c
index 96fa26b20b67..9a9884a39c0e 100644
--- a/net/netfilter/xt_cluster.c
+++ b/net/netfilter/xt_cluster.c
@@ -112,7 +112,7 @@ xt_cluster_mt(const struct sk_buff *skb, struct xt_action_param *par)
* know, matches should not alter packets, but we are doing this here
* because we would need to add a PKTTYPE target for this sole purpose.
*/
- if (!xt_cluster_is_multicast_addr(skb, par->family) &&
+ if (!xt_cluster_is_multicast_addr(skb, xt_family(par)) &&
skb->pkt_type == PACKET_MULTICAST) {
pskb->pkt_type = PACKET_HOST;
}
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index d4bec261e74e..cad0b7b5eb35 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -110,7 +110,7 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
return -EINVAL;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -129,7 +129,7 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_match connbytes_mt_reg __read_mostly = {
diff --git a/net/netfilter/xt_connlabel.c b/net/netfilter/xt_connlabel.c
index 03d66f1c5e69..7827128d5a95 100644
--- a/net/netfilter/xt_connlabel.c
+++ b/net/netfilter/xt_connlabel.c
@@ -61,7 +61,7 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par)
return -EINVAL;
}
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) {
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -70,14 +70,14 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par)
ret = nf_connlabels_get(par->net, info->bit);
if (ret < 0)
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
return ret;
}
static void connlabel_mt_destroy(const struct xt_mtdtor_param *par)
{
nf_connlabels_put(par->net);
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_match connlabels_mt_reg __read_mostly = {
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index b6dc322593a3..2aff2b7c4689 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -317,7 +317,7 @@ static int count_them(struct net *net,
static bool
connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
- struct net *net = par->net;
+ struct net *net = xt_net(par);
const struct xt_connlimit_info *info = par->matchinfo;
union nf_inet_addr addr;
struct nf_conntrack_tuple tuple;
@@ -332,11 +332,11 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
zone = nf_ct_zone(ct);
} else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
- par->family, net, &tuple)) {
+ xt_family(par), net, &tuple)) {
goto hotdrop;
}
- if (par->family == NFPROTO_IPV6) {
+ if (xt_family(par) == NFPROTO_IPV6) {
const struct ipv6hdr *iph = ipv6_hdr(skb);
memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
&iph->daddr : &iph->saddr, sizeof(addr.ip6));
@@ -347,7 +347,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
}
connections = count_them(net, info->data, tuple_ptr, &addr,
- &info->mask, par->family, zone);
+ &info->mask, xt_family(par), zone);
if (connections == 0)
/* kmalloc failed, drop it entirely */
goto hotdrop;
@@ -368,7 +368,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
net_get_random_once(&connlimit_rnd, sizeof(connlimit_rnd));
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) {
pr_info("cannot load conntrack support for "
"address family %u\n", par->family);
@@ -378,7 +378,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
/* init private data */
info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
if (info->data == NULL) {
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
return -ENOMEM;
}
@@ -414,7 +414,7 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
const struct xt_connlimit_info *info = par->matchinfo;
unsigned int i;
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i)
destroy_tree(&info->data->climit_root4[i]);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index b83e158e116a..9935d5029b0e 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -77,7 +77,7 @@ static int connmark_tg_check(const struct xt_tgchk_param *par)
{
int ret;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -86,7 +86,7 @@ static int connmark_tg_check(const struct xt_tgchk_param *par)
static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static bool
@@ -107,7 +107,7 @@ static int connmark_mt_check(const struct xt_mtchk_param *par)
{
int ret;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -116,7 +116,7 @@ static int connmark_mt_check(const struct xt_mtchk_param *par)
static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_target connmark_tg_reg __read_mostly = {
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index a3b8f697cfc5..c0fb217bc649 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -200,22 +200,22 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
return false;
if (info->match_flags & XT_CONNTRACK_ORIGSRC)
- if (conntrack_mt_origsrc(ct, info, par->family) ^
+ if (conntrack_mt_origsrc(ct, info, xt_family(par)) ^
!(info->invert_flags & XT_CONNTRACK_ORIGSRC))
return false;
if (info->match_flags & XT_CONNTRACK_ORIGDST)
- if (conntrack_mt_origdst(ct, info, par->family) ^
+ if (conntrack_mt_origdst(ct, info, xt_family(par)) ^
!(info->invert_flags & XT_CONNTRACK_ORIGDST))
return false;
if (info->match_flags & XT_CONNTRACK_REPLSRC)
- if (conntrack_mt_replsrc(ct, info, par->family) ^
+ if (conntrack_mt_replsrc(ct, info, xt_family(par)) ^
!(info->invert_flags & XT_CONNTRACK_REPLSRC))
return false;
if (info->match_flags & XT_CONNTRACK_REPLDST)
- if (conntrack_mt_repldst(ct, info, par->family) ^
+ if (conntrack_mt_repldst(ct, info, xt_family(par)) ^
!(info->invert_flags & XT_CONNTRACK_REPLDST))
return false;
@@ -271,7 +271,7 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par)
{
int ret;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -280,7 +280,7 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par)
static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_match conntrack_mt_reg[] __read_mostly = {
diff --git a/net/netfilter/xt_devgroup.c b/net/netfilter/xt_devgroup.c
index d9202cdd25c9..96ebe1cdefec 100644
--- a/net/netfilter/xt_devgroup.c
+++ b/net/netfilter/xt_devgroup.c
@@ -24,12 +24,12 @@ static bool devgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_devgroup_info *info = par->matchinfo;
if (info->flags & XT_DEVGROUP_MATCH_SRC &&
- (((info->src_group ^ par->in->group) & info->src_mask ? 1 : 0) ^
+ (((info->src_group ^ xt_in(par)->group) & info->src_mask ? 1 : 0) ^
((info->flags & XT_DEVGROUP_INVERT_SRC) ? 1 : 0)))
return false;
if (info->flags & XT_DEVGROUP_MATCH_DST &&
- (((info->dst_group ^ par->out->group) & info->dst_mask ? 1 : 0) ^
+ (((info->dst_group ^ xt_out(par)->group) & info->dst_mask ? 1 : 0) ^
((info->flags & XT_DEVGROUP_INVERT_DST) ? 1 : 0)))
return false;
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 64670fc5d0e1..236ac8008909 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -58,7 +58,7 @@ static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_tos_match_info *info = par->matchinfo;
- if (par->family == NFPROTO_IPV4)
+ if (xt_family(par) == NFPROTO_IPV4)
return ((ip_hdr(skb)->tos & info->tos_mask) ==
info->tos_value) ^ !!info->invert;
else
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index b89b688e9d01..10063408141d 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -49,7 +49,7 @@ struct hashlimit_net {
struct proc_dir_entry *ip6t_hashlimit;
};
-static int hashlimit_net_id;
+static unsigned int hashlimit_net_id;
static inline struct hashlimit_net *hashlimit_pernet(struct net *net)
{
return net_generic(net, hashlimit_net_id);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index f679dd4c272a..38a78151c0e9 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -59,7 +59,7 @@ static int helper_mt_check(const struct xt_mtchk_param *par)
struct xt_helper_info *info = par->matchinfo;
int ret;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) {
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -71,7 +71,7 @@ static int helper_mt_check(const struct xt_mtchk_param *par)
static void helper_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_match helper_mt_reg __read_mostly = {
diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c
index 71a9d95e0a81..0fdc89064488 100644
--- a/net/netfilter/xt_ipvs.c
+++ b/net/netfilter/xt_ipvs.c
@@ -48,9 +48,9 @@ static bool
ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_ipvs_mtinfo *data = par->matchinfo;
- struct netns_ipvs *ipvs = net_ipvs(par->net);
+ struct netns_ipvs *ipvs = net_ipvs(xt_net(par));
/* ipvs_mt_check ensures that family is only NFPROTO_IPV[46]. */
- const u_int8_t family = par->family;
+ const u_int8_t family = xt_family(par);
struct ip_vs_iphdr iph;
struct ip_vs_protocol *pp;
struct ip_vs_conn *cp;
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index ac1d3c3d09e7..1cde0e4985b7 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -42,29 +42,43 @@ ports_match_v1(const struct xt_multiport_v1 *minfo,
e = minfo->ports[++i];
pr_debug("src or dst matches with %d-%d?\n", s, e);
- if (minfo->flags == XT_MULTIPORT_SOURCE
- && src >= s && src <= e)
- return true ^ minfo->invert;
- if (minfo->flags == XT_MULTIPORT_DESTINATION
- && dst >= s && dst <= e)
- return true ^ minfo->invert;
- if (minfo->flags == XT_MULTIPORT_EITHER
- && ((dst >= s && dst <= e)
- || (src >= s && src <= e)))
- return true ^ minfo->invert;
+ switch (minfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ if (src >= s && src <= e)
+ return true ^ minfo->invert;
+ break;
+ case XT_MULTIPORT_DESTINATION:
+ if (dst >= s && dst <= e)
+ return true ^ minfo->invert;
+ break;
+ case XT_MULTIPORT_EITHER:
+ if ((dst >= s && dst <= e) ||
+ (src >= s && src <= e))
+ return true ^ minfo->invert;
+ break;
+ default:
+ break;
+ }
} else {
/* exact port matching */
pr_debug("src or dst matches with %d?\n", s);
- if (minfo->flags == XT_MULTIPORT_SOURCE
- && src == s)
- return true ^ minfo->invert;
- if (minfo->flags == XT_MULTIPORT_DESTINATION
- && dst == s)
- return true ^ minfo->invert;
- if (minfo->flags == XT_MULTIPORT_EITHER
- && (src == s || dst == s))
- return true ^ minfo->invert;
+ switch (minfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ if (src == s)
+ return true ^ minfo->invert;
+ break;
+ case XT_MULTIPORT_DESTINATION:
+ if (dst == s)
+ return true ^ minfo->invert;
+ break;
+ case XT_MULTIPORT_EITHER:
+ if (src == s || dst == s)
+ return true ^ minfo->invert;
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c
index bea7464cc43f..8107b3eb865f 100644
--- a/net/netfilter/xt_nat.c
+++ b/net/netfilter/xt_nat.c
@@ -23,7 +23,17 @@ static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
par->target->name);
return -EINVAL;
}
- return 0;
+ return nf_ct_netns_get(par->net, par->family);
+}
+
+static int xt_nat_checkentry(const struct xt_tgchk_param *par)
+{
+ return nf_ct_netns_get(par->net, par->family);
+}
+
+static void xt_nat_destroy(const struct xt_tgdtor_param *par)
+{
+ nf_ct_netns_put(par->net, par->family);
}
static void xt_nat_convert_range(struct nf_nat_range *dst,
@@ -106,6 +116,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
.name = "SNAT",
.revision = 0,
.checkentry = xt_nat_checkentry_v0,
+ .destroy = xt_nat_destroy,
.target = xt_snat_target_v0,
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
.family = NFPROTO_IPV4,
@@ -118,6 +129,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
.name = "DNAT",
.revision = 0,
.checkentry = xt_nat_checkentry_v0,
+ .destroy = xt_nat_destroy,
.target = xt_dnat_target_v0,
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
.family = NFPROTO_IPV4,
@@ -129,6 +141,8 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
{
.name = "SNAT",
.revision = 1,
+ .checkentry = xt_nat_checkentry,
+ .destroy = xt_nat_destroy,
.target = xt_snat_target_v1,
.targetsize = sizeof(struct nf_nat_range),
.table = "nat",
@@ -139,6 +153,8 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
{
.name = "DNAT",
.revision = 1,
+ .checkentry = xt_nat_checkentry,
+ .destroy = xt_nat_destroy,
.target = xt_dnat_target_v1,
.targetsize = sizeof(struct nf_nat_range),
.table = "nat",
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c
index cf327593852a..cc0518fe598e 100644
--- a/net/netfilter/xt_nfacct.c
+++ b/net/netfilter/xt_nfacct.c
@@ -26,7 +26,7 @@ static bool nfacct_mt(const struct sk_buff *skb, struct xt_action_param *par)
nfnl_acct_update(skb, info->nfacct);
- overquota = nfnl_acct_overquota(par->net, skb, info->nfacct);
+ overquota = nfnl_acct_overquota(xt_net(par), skb, info->nfacct);
return overquota == NFACCT_UNDERQUOTA ? false : true;
}
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 2455b69b5810..c05fefcec238 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -201,7 +201,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
unsigned char opts[MAX_IPOPTLEN];
const struct xt_osf_finger *kf;
const struct xt_osf_user_finger *f;
- struct net *net = p->net;
+ struct net *net = xt_net(p);
if (!info)
return false;
@@ -326,8 +326,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
fcount++;
if (info->flags & XT_OSF_LOG)
- nf_log_packet(net, p->family, p->hooknum, skb,
- p->in, p->out, NULL,
+ nf_log_packet(net, xt_family(p), xt_hooknum(p), skb,
+ xt_in(p), xt_out(p), NULL,
"%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
f->genre, f->version, f->subtype,
&ip->saddr, ntohs(tcp->source),
@@ -341,8 +341,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
rcu_read_unlock();
if (!fcount && (info->flags & XT_OSF_LOG))
- nf_log_packet(net, p->family, p->hooknum, skb, p->in,
- p->out, NULL,
+ nf_log_packet(net, xt_family(p), xt_hooknum(p), skb, xt_in(p),
+ xt_out(p), NULL,
"Remote OS is not known: %pI4:%u -> %pI4:%u\n",
&ip->saddr, ntohs(tcp->source),
&ip->daddr, ntohs(tcp->dest));
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
index a20e731b5b6c..16477df45b3b 100644
--- a/net/netfilter/xt_owner.c
+++ b/net/netfilter/xt_owner.c
@@ -63,7 +63,7 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_owner_match_info *info = par->matchinfo;
const struct file *filp;
struct sock *sk = skb_to_full_sk(skb);
- struct net *net = par->net;
+ struct net *net = xt_net(par);
if (sk == NULL || sk->sk_socket == NULL)
return (info->match ^ info->invert) == 0;
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 5b645cb598fc..57efb703ff18 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -30,10 +30,10 @@ pkttype_mt(const struct sk_buff *skb, struct xt_action_param *par)
if (skb->pkt_type != PACKET_LOOPBACK)
type = skb->pkt_type;
- else if (par->family == NFPROTO_IPV4 &&
+ else if (xt_family(par) == NFPROTO_IPV4 &&
ipv4_is_multicast(ip_hdr(skb)->daddr))
type = PACKET_MULTICAST;
- else if (par->family == NFPROTO_IPV6 &&
+ else if (xt_family(par) == NFPROTO_IPV6 &&
ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF)
type = PACKET_MULTICAST;
else
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index f23e97bb42d7..2b4ab189bba7 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -116,9 +116,9 @@ policy_mt(const struct sk_buff *skb, struct xt_action_param *par)
int ret;
if (info->flags & XT_POLICY_MATCH_IN)
- ret = match_policy_in(skb, info, par->family);
+ ret = match_policy_in(skb, info, xt_family(par));
else
- ret = match_policy_out(skb, info, par->family);
+ ret = match_policy_out(skb, info, xt_family(par));
if (ret < 0)
ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
index 7720b036d76a..1db02f6fca54 100644
--- a/net/netfilter/xt_rateest.c
+++ b/net/netfilter/xt_rateest.c
@@ -18,35 +18,33 @@ static bool
xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_rateest_match_info *info = par->matchinfo;
- struct gnet_stats_rate_est64 *r;
+ struct gnet_stats_rate_est64 sample = {0};
u_int32_t bps1, bps2, pps1, pps2;
bool ret = true;
- spin_lock_bh(&info->est1->lock);
- r = &info->est1->rstats;
+ gen_estimator_read(&info->est1->rate_est, &sample);
+
if (info->flags & XT_RATEEST_MATCH_DELTA) {
- bps1 = info->bps1 >= r->bps ? info->bps1 - r->bps : 0;
- pps1 = info->pps1 >= r->pps ? info->pps1 - r->pps : 0;
+ bps1 = info->bps1 >= sample.bps ? info->bps1 - sample.bps : 0;
+ pps1 = info->pps1 >= sample.pps ? info->pps1 - sample.pps : 0;
} else {
- bps1 = r->bps;
- pps1 = r->pps;
+ bps1 = sample.bps;
+ pps1 = sample.pps;
}
- spin_unlock_bh(&info->est1->lock);
if (info->flags & XT_RATEEST_MATCH_ABS) {
bps2 = info->bps2;
pps2 = info->pps2;
} else {
- spin_lock_bh(&info->est2->lock);
- r = &info->est2->rstats;
+ gen_estimator_read(&info->est2->rate_est, &sample);
+
if (info->flags & XT_RATEEST_MATCH_DELTA) {
- bps2 = info->bps2 >= r->bps ? info->bps2 - r->bps : 0;
- pps2 = info->pps2 >= r->pps ? info->pps2 - r->pps : 0;
+ bps2 = info->bps2 >= sample.bps ? info->bps2 - sample.bps : 0;
+ pps2 = info->pps2 >= sample.pps ? info->pps2 - sample.pps : 0;
} else {
- bps2 = r->bps;
- pps2 = r->pps;
+ bps2 = sample.bps;
+ pps2 = sample.pps;
}
- spin_unlock_bh(&info->est2->lock);
}
switch (info->mode) {
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index e3b7a09b103e..1d89a4eaf841 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -95,7 +95,7 @@ struct recent_net {
#endif
};
-static int recent_net_id __read_mostly;
+static unsigned int recent_net_id __read_mostly;
static inline struct recent_net *recent_pernet(struct net *net)
{
@@ -236,7 +236,7 @@ static void recent_table_flush(struct recent_table *t)
static bool
recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
- struct net *net = par->net;
+ struct net *net = xt_net(par);
struct recent_net *recent_net = recent_pernet(net);
const struct xt_recent_mtinfo_v1 *info = par->matchinfo;
struct recent_table *t;
@@ -245,7 +245,7 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
u_int8_t ttl;
bool ret = info->invert;
- if (par->family == NFPROTO_IPV4) {
+ if (xt_family(par) == NFPROTO_IPV4) {
const struct iphdr *iph = ip_hdr(skb);
if (info->side == XT_RECENT_DEST)
@@ -266,7 +266,7 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
}
/* use TTL as seen before forwarding */
- if (par->out != NULL && skb->sk == NULL)
+ if (xt_out(par) != NULL && skb->sk == NULL)
ttl++;
spin_lock_bh(&recent_lock);
@@ -274,12 +274,12 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
nf_inet_addr_mask(&addr, &addr_mask, &t->mask);
- e = recent_entry_lookup(t, &addr_mask, par->family,
+ e = recent_entry_lookup(t, &addr_mask, xt_family(par),
(info->check_set & XT_RECENT_TTL) ? ttl : 0);
if (e == NULL) {
if (!(info->check_set & XT_RECENT_SET))
goto out;
- e = recent_entry_init(t, &addr_mask, par->family, ttl);
+ e = recent_entry_init(t, &addr_mask, xt_family(par), ttl);
if (e == NULL)
par->hotdrop = true;
ret = !ret;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 5669e5b453f4..64285702afd5 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -55,7 +55,7 @@ set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_set_info_match_v0 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
+ ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
info->match_set.u.compat.flags, 0, UINT_MAX);
return match_set(info->match_set.index, skb, par, &opt,
@@ -118,7 +118,7 @@ set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_set_info_match_v1 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.dim,
+ ADT_OPT(opt, xt_family(par), info->match_set.dim,
info->match_set.flags, 0, UINT_MAX);
if (opt.flags & IPSET_RETURN_NOMATCH)
@@ -184,7 +184,7 @@ set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_set_info_match_v3 *info = par->matchinfo;
int ret;
- ADT_OPT(opt, par->family, info->match_set.dim,
+ ADT_OPT(opt, xt_family(par), info->match_set.dim,
info->match_set.flags, info->flags, UINT_MAX);
if (info->packets.op != IPSET_COUNTER_NONE ||
@@ -231,7 +231,7 @@ set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_set_info_match_v4 *info = par->matchinfo;
int ret;
- ADT_OPT(opt, par->family, info->match_set.dim,
+ ADT_OPT(opt, xt_family(par), info->match_set.dim,
info->match_set.flags, info->flags, UINT_MAX);
if (info->packets.op != IPSET_COUNTER_NONE ||
@@ -259,9 +259,9 @@ set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v0 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
+ ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
info->add_set.u.compat.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
+ ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
info->del_set.u.compat.flags, 0, UINT_MAX);
if (info->add_set.index != IPSET_INVALID_ID)
@@ -332,9 +332,9 @@ set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v1 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
+ ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
info->add_set.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
+ ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
info->del_set.flags, 0, UINT_MAX);
if (info->add_set.index != IPSET_INVALID_ID)
@@ -401,9 +401,9 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v2 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
+ ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
info->add_set.flags, info->flags, info->timeout);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
+ ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
info->del_set.flags, 0, UINT_MAX);
/* Normalize to fit into jiffies */
@@ -423,17 +423,19 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
/* Revision 3 target */
+#define MOPT(opt, member) ((opt).ext.skbinfo.member)
+
static unsigned int
set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v3 *info = par->targinfo;
int ret;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
+ ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
info->add_set.flags, info->flags, info->timeout);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
+ ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
info->del_set.flags, 0, UINT_MAX);
- ADT_OPT(map_opt, par->family, info->map_set.dim,
+ ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
info->map_set.flags, 0, UINT_MAX);
/* Normalize to fit into jiffies */
@@ -453,14 +455,14 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
if (!ret)
return XT_CONTINUE;
if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
- skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
- ^ (map_opt.ext.skbmark);
+ skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
+ ^ MOPT(map_opt, skbmark);
if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
- skb->priority = map_opt.ext.skbprio;
+ skb->priority = MOPT(map_opt, skbprio);
if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
skb->dev &&
- skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
- skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
+ skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
+ skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
}
return XT_CONTINUE;
}
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index b10ade272b50..770bbec878f1 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -22,76 +22,14 @@
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-#define XT_SOCKET_HAVE_IPV6 1
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/inet6_hashtables.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
#endif
+#include <net/netfilter/nf_socket.h>
#include <linux/netfilter/xt_socket.h>
-#if IS_ENABLED(CONFIG_NF_CONNTRACK)
-#define XT_SOCKET_HAVE_CONNTRACK 1
-#include <net/netfilter/nf_conntrack.h>
-#endif
-
-static int
-extract_icmp4_fields(const struct sk_buff *skb,
- u8 *protocol,
- __be32 *raddr,
- __be32 *laddr,
- __be16 *rport,
- __be16 *lport)
-{
- unsigned int outside_hdrlen = ip_hdrlen(skb);
- struct iphdr *inside_iph, _inside_iph;
- struct icmphdr *icmph, _icmph;
- __be16 *ports, _ports[2];
-
- icmph = skb_header_pointer(skb, outside_hdrlen,
- sizeof(_icmph), &_icmph);
- if (icmph == NULL)
- return 1;
-
- switch (icmph->type) {
- case ICMP_DEST_UNREACH:
- case ICMP_SOURCE_QUENCH:
- case ICMP_REDIRECT:
- case ICMP_TIME_EXCEEDED:
- case ICMP_PARAMETERPROB:
- break;
- default:
- return 1;
- }
-
- inside_iph = skb_header_pointer(skb, outside_hdrlen +
- sizeof(struct icmphdr),
- sizeof(_inside_iph), &_inside_iph);
- if (inside_iph == NULL)
- return 1;
-
- if (inside_iph->protocol != IPPROTO_TCP &&
- inside_iph->protocol != IPPROTO_UDP)
- return 1;
-
- ports = skb_header_pointer(skb, outside_hdrlen +
- sizeof(struct icmphdr) +
- (inside_iph->ihl << 2),
- sizeof(_ports), &_ports);
- if (ports == NULL)
- return 1;
-
- /* the inside IP packet is the one quoted from our side, thus
- * its saddr is the local address */
- *protocol = inside_iph->protocol;
- *laddr = inside_iph->saddr;
- *lport = ports[0];
- *raddr = inside_iph->daddr;
- *rport = ports[1];
-
- return 0;
-}
-
/* "socket" match based redirection (no specific rule)
* ===================================================
*
@@ -111,104 +49,6 @@ extract_icmp4_fields(const struct sk_buff *skb,
* then local services could intercept traffic going through the
* box.
*/
-static struct sock *
-xt_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff,
- const u8 protocol,
- const __be32 saddr, const __be32 daddr,
- const __be16 sport, const __be16 dport,
- const struct net_device *in)
-{
- switch (protocol) {
- case IPPROTO_TCP:
- return inet_lookup(net, &tcp_hashinfo, skb, doff,
- saddr, sport, daddr, dport,
- in->ifindex);
- case IPPROTO_UDP:
- return udp4_lib_lookup(net, saddr, sport, daddr, dport,
- in->ifindex);
- }
- return NULL;
-}
-
-static bool xt_socket_sk_is_transparent(struct sock *sk)
-{
- switch (sk->sk_state) {
- case TCP_TIME_WAIT:
- return inet_twsk(sk)->tw_transparent;
-
- case TCP_NEW_SYN_RECV:
- return inet_rsk(inet_reqsk(sk))->no_srccheck;
-
- default:
- return inet_sk(sk)->transparent;
- }
-}
-
-static struct sock *xt_socket_lookup_slow_v4(struct net *net,
- const struct sk_buff *skb,
- const struct net_device *indev)
-{
- const struct iphdr *iph = ip_hdr(skb);
- struct sk_buff *data_skb = NULL;
- int doff = 0;
- __be32 uninitialized_var(daddr), uninitialized_var(saddr);
- __be16 uninitialized_var(dport), uninitialized_var(sport);
- u8 uninitialized_var(protocol);
-#ifdef XT_SOCKET_HAVE_CONNTRACK
- struct nf_conn const *ct;
- enum ip_conntrack_info ctinfo;
-#endif
-
- if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
- struct udphdr _hdr, *hp;
-
- hp = skb_header_pointer(skb, ip_hdrlen(skb),
- sizeof(_hdr), &_hdr);
- if (hp == NULL)
- return NULL;
-
- protocol = iph->protocol;
- saddr = iph->saddr;
- sport = hp->source;
- daddr = iph->daddr;
- dport = hp->dest;
- data_skb = (struct sk_buff *)skb;
- doff = iph->protocol == IPPROTO_TCP ?
- ip_hdrlen(skb) + __tcp_hdrlen((struct tcphdr *)hp) :
- ip_hdrlen(skb) + sizeof(*hp);
-
- } else if (iph->protocol == IPPROTO_ICMP) {
- if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
- &sport, &dport))
- return NULL;
- } else {
- return NULL;
- }
-
-#ifdef XT_SOCKET_HAVE_CONNTRACK
- /* Do the lookup with the original socket address in
- * case this is a reply packet of an established
- * SNAT-ted connection.
- */
- ct = nf_ct_get(skb, &ctinfo);
- if (ct && !nf_ct_is_untracked(ct) &&
- ((iph->protocol != IPPROTO_ICMP &&
- ctinfo == IP_CT_ESTABLISHED_REPLY) ||
- (iph->protocol == IPPROTO_ICMP &&
- ctinfo == IP_CT_RELATED_REPLY)) &&
- (ct->status & IPS_SRC_NAT_DONE)) {
-
- daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
- dport = (iph->protocol == IPPROTO_TCP) ?
- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
- }
-#endif
-
- return xt_socket_get_sock_v4(net, data_skb, doff, protocol, saddr,
- daddr, sport, dport, indev);
-}
-
static bool
socket_match(const struct sk_buff *skb, struct xt_action_param *par,
const struct xt_socket_mtinfo1 *info)
@@ -217,7 +57,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
struct sock *sk = skb->sk;
if (!sk)
- sk = xt_socket_lookup_slow_v4(par->net, skb, par->in);
+ sk = nf_sk_lookup_slow_v4(xt_net(par), skb, xt_in(par));
if (sk) {
bool wildcard;
bool transparent = true;
@@ -233,7 +73,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
* if XT_SOCKET_TRANSPARENT is used
*/
if (info->flags & XT_SOCKET_TRANSPARENT)
- transparent = xt_socket_sk_is_transparent(sk);
+ transparent = nf_sk_is_transparent(sk);
if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
transparent)
@@ -265,132 +105,7 @@ socket_mt4_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
return socket_match(skb, par, par->matchinfo);
}
-#ifdef XT_SOCKET_HAVE_IPV6
-
-static int
-extract_icmp6_fields(const struct sk_buff *skb,
- unsigned int outside_hdrlen,
- int *protocol,
- const struct in6_addr **raddr,
- const struct in6_addr **laddr,
- __be16 *rport,
- __be16 *lport,
- struct ipv6hdr *ipv6_var)
-{
- const struct ipv6hdr *inside_iph;
- struct icmp6hdr *icmph, _icmph;
- __be16 *ports, _ports[2];
- u8 inside_nexthdr;
- __be16 inside_fragoff;
- int inside_hdrlen;
-
- icmph = skb_header_pointer(skb, outside_hdrlen,
- sizeof(_icmph), &_icmph);
- if (icmph == NULL)
- return 1;
-
- if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
- return 1;
-
- inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph),
- sizeof(*ipv6_var), ipv6_var);
- if (inside_iph == NULL)
- return 1;
- inside_nexthdr = inside_iph->nexthdr;
-
- inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) +
- sizeof(*ipv6_var),
- &inside_nexthdr, &inside_fragoff);
- if (inside_hdrlen < 0)
- return 1; /* hjm: Packet has no/incomplete transport layer headers. */
-
- if (inside_nexthdr != IPPROTO_TCP &&
- inside_nexthdr != IPPROTO_UDP)
- return 1;
-
- ports = skb_header_pointer(skb, inside_hdrlen,
- sizeof(_ports), &_ports);
- if (ports == NULL)
- return 1;
-
- /* the inside IP packet is the one quoted from our side, thus
- * its saddr is the local address */
- *protocol = inside_nexthdr;
- *laddr = &inside_iph->saddr;
- *lport = ports[0];
- *raddr = &inside_iph->daddr;
- *rport = ports[1];
-
- return 0;
-}
-
-static struct sock *
-xt_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff,
- const u8 protocol,
- const struct in6_addr *saddr, const struct in6_addr *daddr,
- const __be16 sport, const __be16 dport,
- const struct net_device *in)
-{
- switch (protocol) {
- case IPPROTO_TCP:
- return inet6_lookup(net, &tcp_hashinfo, skb, doff,
- saddr, sport, daddr, dport,
- in->ifindex);
- case IPPROTO_UDP:
- return udp6_lib_lookup(net, saddr, sport, daddr, dport,
- in->ifindex);
- }
-
- return NULL;
-}
-
-static struct sock *xt_socket_lookup_slow_v6(struct net *net,
- const struct sk_buff *skb,
- const struct net_device *indev)
-{
- __be16 uninitialized_var(dport), uninitialized_var(sport);
- const struct in6_addr *daddr = NULL, *saddr = NULL;
- struct ipv6hdr *iph = ipv6_hdr(skb);
- struct sk_buff *data_skb = NULL;
- int doff = 0;
- int thoff = 0, tproto;
-
- tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
- if (tproto < 0) {
- pr_debug("unable to find transport header in IPv6 packet, dropping\n");
- return NULL;
- }
-
- if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) {
- struct udphdr _hdr, *hp;
-
- hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
- if (hp == NULL)
- return NULL;
-
- saddr = &iph->saddr;
- sport = hp->source;
- daddr = &iph->daddr;
- dport = hp->dest;
- data_skb = (struct sk_buff *)skb;
- doff = tproto == IPPROTO_TCP ?
- thoff + __tcp_hdrlen((struct tcphdr *)hp) :
- thoff + sizeof(*hp);
-
- } else if (tproto == IPPROTO_ICMPV6) {
- struct ipv6hdr ipv6_var;
-
- if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
- &sport, &dport, &ipv6_var))
- return NULL;
- } else {
- return NULL;
- }
-
- return xt_socket_get_sock_v6(net, data_skb, doff, tproto, saddr, daddr,
- sport, dport, indev);
-}
-
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
static bool
socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
{
@@ -399,7 +114,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
struct sock *sk = skb->sk;
if (!sk)
- sk = xt_socket_lookup_slow_v6(par->net, skb, par->in);
+ sk = nf_sk_lookup_slow_v6(xt_net(par), skb, xt_in(par));
if (sk) {
bool wildcard;
bool transparent = true;
@@ -415,7 +130,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
* if XT_SOCKET_TRANSPARENT is used
*/
if (info->flags & XT_SOCKET_TRANSPARENT)
- transparent = xt_socket_sk_is_transparent(sk);
+ transparent = nf_sk_is_transparent(sk);
if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
transparent)
@@ -432,9 +147,28 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
}
#endif
+static int socket_mt_enable_defrag(struct net *net, int family)
+{
+ switch (family) {
+ case NFPROTO_IPV4:
+ return nf_defrag_ipv4_enable(net);
+#ifdef XT_SOCKET_HAVE_IPV6
+ case NFPROTO_IPV6:
+ return nf_defrag_ipv6_enable(net);
+#endif
+ }
+ WARN_ONCE(1, "Unknown family %d\n", family);
+ return 0;
+}
+
static int socket_mt_v1_check(const struct xt_mtchk_param *par)
{
const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
+ int err;
+
+ err = socket_mt_enable_defrag(par->net, par->family);
+ if (err)
+ return err;
if (info->flags & ~XT_SOCKET_FLAGS_V1) {
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1);
@@ -446,6 +180,11 @@ static int socket_mt_v1_check(const struct xt_mtchk_param *par)
static int socket_mt_v2_check(const struct xt_mtchk_param *par)
{
const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
+ int err;
+
+ err = socket_mt_enable_defrag(par->net, par->family);
+ if (err)
+ return err;
if (info->flags & ~XT_SOCKET_FLAGS_V2) {
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2);
@@ -458,7 +197,11 @@ static int socket_mt_v3_check(const struct xt_mtchk_param *par)
{
const struct xt_socket_mtinfo3 *info =
(struct xt_socket_mtinfo3 *)par->matchinfo;
+ int err;
+ err = socket_mt_enable_defrag(par->net, par->family);
+ if (err)
+ return err;
if (info->flags & ~XT_SOCKET_FLAGS_V3) {
pr_info("unknown flags 0x%x\n",
info->flags & ~XT_SOCKET_FLAGS_V3);
@@ -488,7 +231,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
},
-#ifdef XT_SOCKET_HAVE_IPV6
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "socket",
.revision = 1,
@@ -512,7 +255,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
},
-#ifdef XT_SOCKET_HAVE_IPV6
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "socket",
.revision = 2,
@@ -536,7 +279,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
},
-#ifdef XT_SOCKET_HAVE_IPV6
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "socket",
.revision = 3,
@@ -553,11 +296,6 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
static int __init socket_mt_init(void)
{
- nf_defrag_ipv4_enable();
-#ifdef XT_SOCKET_HAVE_IPV6
- nf_defrag_ipv6_enable();
-#endif
-
return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
}
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index a507922d80cd..5746a33789a5 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -43,7 +43,7 @@ static int state_mt_check(const struct xt_mtchk_param *par)
{
int ret;
- ret = nf_ct_l3proto_try_module_get(par->family);
+ ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0)
pr_info("cannot load conntrack support for proto=%u\n",
par->family);
@@ -52,7 +52,7 @@ static int state_mt_check(const struct xt_mtchk_param *par)
static void state_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(par->family);
+ nf_ct_netns_put(par->net, par->family);
}
static struct xt_match state_mt_reg __read_mostly = {
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c
index 2ec93c5e77bb..d177dd066504 100644
--- a/net/netlabel/netlabel_calipso.c
+++ b/net/netlabel/netlabel_calipso.c
@@ -60,13 +60,7 @@ struct netlbl_domhsh_walk_arg {
};
/* NetLabel Generic NETLINK CALIPSO family */
-static struct genl_family netlbl_calipso_gnl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = NETLBL_NLTYPE_CALIPSO_NAME,
- .version = NETLBL_PROTO_VERSION,
- .maxattr = NLBL_CALIPSO_A_MAX,
-};
+static struct genl_family netlbl_calipso_gnl_family;
/* NetLabel Netlink attribute policy */
static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
@@ -355,6 +349,16 @@ static const struct genl_ops netlbl_calipso_ops[] = {
},
};
+static struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = NETLBL_NLTYPE_CALIPSO_NAME,
+ .version = NETLBL_PROTO_VERSION,
+ .maxattr = NLBL_CALIPSO_A_MAX,
+ .module = THIS_MODULE,
+ .ops = netlbl_calipso_ops,
+ .n_ops = ARRAY_SIZE(netlbl_calipso_ops),
+};
+
/* NetLabel Generic NETLINK Protocol Functions
*/
@@ -368,8 +372,7 @@ static const struct genl_ops netlbl_calipso_ops[] = {
*/
int __init netlbl_calipso_genl_init(void)
{
- return genl_register_family_with_ops(&netlbl_calipso_gnl_family,
- netlbl_calipso_ops);
+ return genl_register_family(&netlbl_calipso_gnl_family);
}
static const struct netlbl_calipso_ops *calipso_ops;
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 7fd1104ba900..4149d3e63589 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -59,14 +59,7 @@ struct netlbl_domhsh_walk_arg {
};
/* NetLabel Generic NETLINK CIPSOv4 family */
-static struct genl_family netlbl_cipsov4_gnl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = NETLBL_NLTYPE_CIPSOV4_NAME,
- .version = NETLBL_PROTO_VERSION,
- .maxattr = NLBL_CIPSOV4_A_MAX,
-};
-
+static struct genl_family netlbl_cipsov4_gnl_family;
/* NetLabel Netlink attribute policy */
static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
[NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
@@ -767,6 +760,16 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
},
};
+static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = NETLBL_NLTYPE_CIPSOV4_NAME,
+ .version = NETLBL_PROTO_VERSION,
+ .maxattr = NLBL_CIPSOV4_A_MAX,
+ .module = THIS_MODULE,
+ .ops = netlbl_cipsov4_ops,
+ .n_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
+};
+
/*
* NetLabel Generic NETLINK Protocol Functions
*/
@@ -781,6 +784,5 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
*/
int __init netlbl_cipsov4_genl_init(void)
{
- return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
- netlbl_cipsov4_ops);
+ return genl_register_family(&netlbl_cipsov4_gnl_family);
}
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index f85d0e07af2d..21e0095b1d14 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -60,13 +60,7 @@ struct netlbl_domhsh_walk_arg {
};
/* NetLabel Generic NETLINK CIPSOv4 family */
-static struct genl_family netlbl_mgmt_gnl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = NETLBL_NLTYPE_MGMT_NAME,
- .version = NETLBL_PROTO_VERSION,
- .maxattr = NLBL_MGMT_A_MAX,
-};
+static struct genl_family netlbl_mgmt_gnl_family;
/* NetLabel Netlink attribute policy */
static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
@@ -834,6 +828,16 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
},
};
+static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = NETLBL_NLTYPE_MGMT_NAME,
+ .version = NETLBL_PROTO_VERSION,
+ .maxattr = NLBL_MGMT_A_MAX,
+ .module = THIS_MODULE,
+ .ops = netlbl_mgmt_genl_ops,
+ .n_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops),
+};
+
/*
* NetLabel Generic NETLINK Protocol Functions
*/
@@ -848,6 +852,5 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
*/
int __init netlbl_mgmt_genl_init(void)
{
- return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
- netlbl_mgmt_genl_ops);
+ return genl_register_family(&netlbl_mgmt_gnl_family);
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 4528cff9138b..22dc1b9d6362 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -123,13 +123,7 @@ static struct netlbl_unlhsh_iface __rcu *netlbl_unlhsh_def;
static u8 netlabel_unlabel_acceptflg;
/* NetLabel Generic NETLINK unlabeled family */
-static struct genl_family netlbl_unlabel_gnl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = NETLBL_NLTYPE_UNLABELED_NAME,
- .version = NETLBL_PROTO_VERSION,
- .maxattr = NLBL_UNLABEL_A_MAX,
-};
+static struct genl_family netlbl_unlabel_gnl_family;
/* NetLabel Netlink attribute policy */
static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
@@ -1378,6 +1372,16 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
},
};
+static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = NETLBL_NLTYPE_UNLABELED_NAME,
+ .version = NETLBL_PROTO_VERSION,
+ .maxattr = NLBL_UNLABEL_A_MAX,
+ .module = THIS_MODULE,
+ .ops = netlbl_unlabel_genl_ops,
+ .n_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops),
+};
+
/*
* NetLabel Generic NETLINK Protocol Functions
*/
@@ -1392,8 +1396,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
*/
int __init netlbl_unlabel_genl_init(void)
{
- return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
- netlbl_unlabel_genl_ops);
+ return genl_register_family(&netlbl_unlabel_gnl_family);
}
/*
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 246f29d365c0..801d474de75b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -113,7 +113,7 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
-static ATOMIC_NOTIFIER_HEAD(netlink_chain);
+static BLOCKING_NOTIFIER_HEAD(netlink_chain);
static DEFINE_SPINLOCK(netlink_tap_lock);
static struct list_head netlink_tap_all __read_mostly;
@@ -711,7 +711,7 @@ static int netlink_release(struct socket *sock)
.protocol = sk->sk_protocol,
.portid = nlk->portid,
};
- atomic_notifier_call_chain(&netlink_chain,
+ blocking_notifier_call_chain(&netlink_chain,
NETLINK_URELEASE, &n);
}
@@ -2504,13 +2504,13 @@ static const struct file_operations netlink_seq_fops = {
int netlink_register_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_register(&netlink_chain, nb);
+ return blocking_notifier_chain_register(&netlink_chain, nb);
}
EXPORT_SYMBOL(netlink_register_notifier);
int netlink_unregister_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_unregister(&netlink_chain, nb);
+ return blocking_notifier_chain_unregister(&netlink_chain, nb);
}
EXPORT_SYMBOL(netlink_unregister_notifier);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 49c28e8ef01b..fb6e10fdb217 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -17,6 +17,7 @@
#include <linux/mutex.h>
#include <linux/bitmap.h>
#include <linux/rwsem.h>
+#include <linux/idr.h>
#include <net/sock.h>
#include <net/genetlink.h>
@@ -58,10 +59,8 @@ static void genl_unlock_all(void)
up_write(&cb_lock);
}
-#define GENL_FAM_TAB_SIZE 16
-#define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1)
+static DEFINE_IDR(genl_fam_idr);
-static struct list_head family_ht[GENL_FAM_TAB_SIZE];
/*
* Bitmap of multicast groups that are currently in use.
*
@@ -86,45 +85,29 @@ static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
-static int genl_ctrl_event(int event, struct genl_family *family,
+static int genl_ctrl_event(int event, const struct genl_family *family,
const struct genl_multicast_group *grp,
int grp_id);
-static inline unsigned int genl_family_hash(unsigned int id)
+static const struct genl_family *genl_family_find_byid(unsigned int id)
{
- return id & GENL_FAM_TAB_MASK;
+ return idr_find(&genl_fam_idr, id);
}
-static inline struct list_head *genl_family_chain(unsigned int id)
+static const struct genl_family *genl_family_find_byname(char *name)
{
- return &family_ht[genl_family_hash(id)];
-}
-
-static struct genl_family *genl_family_find_byid(unsigned int id)
-{
- struct genl_family *f;
-
- list_for_each_entry(f, genl_family_chain(id), family_list)
- if (f->id == id)
- return f;
-
- return NULL;
-}
-
-static struct genl_family *genl_family_find_byname(char *name)
-{
- struct genl_family *f;
- int i;
+ const struct genl_family *family;
+ unsigned int id;
- for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
- list_for_each_entry(f, genl_family_chain(i), family_list)
- if (strcmp(f->name, name) == 0)
- return f;
+ idr_for_each_entry(&genl_fam_idr, family, id)
+ if (strcmp(family->name, name) == 0)
+ return family;
return NULL;
}
-static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
+static const struct genl_ops *genl_get_cmd(u8 cmd,
+ const struct genl_family *family)
{
int i;
@@ -135,26 +118,6 @@ static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
return NULL;
}
-/* Of course we are going to have problems once we hit
- * 2^16 alive types, but that can only happen by year 2K
-*/
-static u16 genl_generate_id(void)
-{
- static u16 id_gen_idx = GENL_MIN_ID;
- int i;
-
- for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
- if (id_gen_idx != GENL_ID_VFS_DQUOT &&
- id_gen_idx != GENL_ID_PMCRAID &&
- !genl_family_find_byid(id_gen_idx))
- return id_gen_idx;
- if (++id_gen_idx > GENL_MAX_ID)
- id_gen_idx = GENL_MIN_ID;
- }
-
- return 0;
-}
-
static int genl_allocate_reserve_groups(int n_groups, int *first_id)
{
unsigned long *new_groups;
@@ -295,7 +258,7 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
return err;
}
-static void genl_unregister_mc_groups(struct genl_family *family)
+static void genl_unregister_mc_groups(const struct genl_family *family)
{
struct net *net;
int i;
@@ -344,28 +307,21 @@ static int genl_validate_ops(const struct genl_family *family)
}
/**
- * __genl_register_family - register a generic netlink family
+ * genl_register_family - register a generic netlink family
* @family: generic netlink family
*
* Registers the specified family after validating it first. Only one
* family may be registered with the same family name or identifier.
- * The family id may equal GENL_ID_GENERATE causing an unique id to
- * be automatically generated and assigned.
*
- * The family's ops array must already be assigned, you can use the
- * genl_register_family_with_ops() helper function.
+ * The family's ops, multicast groups and module pointer must already
+ * be assigned.
*
* Return 0 on success or a negative error code.
*/
-int __genl_register_family(struct genl_family *family)
+int genl_register_family(struct genl_family *family)
{
- int err = -EINVAL, i;
-
- if (family->id && family->id < GENL_MIN_ID)
- goto errout;
-
- if (family->id > GENL_MAX_ID)
- goto errout;
+ int err, i;
+ int start = GENL_START_ALLOC, end = GENL_MAX_ID;
err = genl_validate_ops(family);
if (err)
@@ -378,18 +334,20 @@ int __genl_register_family(struct genl_family *family)
goto errout_locked;
}
- if (family->id == GENL_ID_GENERATE) {
- u16 newid = genl_generate_id();
-
- if (!newid) {
- err = -ENOMEM;
- goto errout_locked;
- }
-
- family->id = newid;
- } else if (genl_family_find_byid(family->id)) {
- err = -EEXIST;
- goto errout_locked;
+ /*
+ * Sadly, a few cases need to be special-cased
+ * due to them having previously abused the API
+ * and having used their family ID also as their
+ * multicast group ID, so we use reserved IDs
+ * for both to be sure we can do that mapping.
+ */
+ if (family == &genl_ctrl) {
+ /* and this needs to be special for initial family lookups */
+ start = end = GENL_ID_CTRL;
+ } else if (strcmp(family->name, "pmcraid") == 0) {
+ start = end = GENL_ID_PMCRAID;
+ } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+ start = end = GENL_ID_VFS_DQUOT;
}
if (family->maxattr && !family->parallel_ops) {
@@ -402,11 +360,17 @@ int __genl_register_family(struct genl_family *family)
} else
family->attrbuf = NULL;
+ family->id = idr_alloc(&genl_fam_idr, family,
+ start, end + 1, GFP_KERNEL);
+ if (family->id < 0) {
+ err = family->id;
+ goto errout_locked;
+ }
+
err = genl_validate_assign_mc_groups(family);
if (err)
- goto errout_free;
+ goto errout_remove;
- list_add_tail(&family->family_list, genl_family_chain(family->id));
genl_unlock_all();
/* send all events */
@@ -417,14 +381,14 @@ int __genl_register_family(struct genl_family *family)
return 0;
-errout_free:
+errout_remove:
+ idr_remove(&genl_fam_idr, family->id);
kfree(family->attrbuf);
errout_locked:
genl_unlock_all();
-errout:
return err;
}
-EXPORT_SYMBOL(__genl_register_family);
+EXPORT_SYMBOL(genl_register_family);
/**
* genl_unregister_family - unregister generic netlink family
@@ -434,33 +398,29 @@ EXPORT_SYMBOL(__genl_register_family);
*
* Returns 0 on success or a negative error code.
*/
-int genl_unregister_family(struct genl_family *family)
+int genl_unregister_family(const struct genl_family *family)
{
- struct genl_family *rc;
-
genl_lock_all();
- list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
- if (family->id != rc->id || strcmp(rc->name, family->name))
- continue;
+ if (!genl_family_find_byid(family->id)) {
+ genl_unlock_all();
+ return -ENOENT;
+ }
- genl_unregister_mc_groups(family);
+ genl_unregister_mc_groups(family);
- list_del(&rc->family_list);
- family->n_ops = 0;
- up_write(&cb_lock);
- wait_event(genl_sk_destructing_waitq,
- atomic_read(&genl_sk_destructing_cnt) == 0);
- genl_unlock();
+ idr_remove(&genl_fam_idr, family->id);
- kfree(family->attrbuf);
- genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
- return 0;
- }
+ up_write(&cb_lock);
+ wait_event(genl_sk_destructing_waitq,
+ atomic_read(&genl_sk_destructing_cnt) == 0);
+ genl_unlock();
- genl_unlock_all();
+ kfree(family->attrbuf);
+
+ genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
- return -ENOENT;
+ return 0;
}
EXPORT_SYMBOL(genl_unregister_family);
@@ -476,7 +436,7 @@ EXPORT_SYMBOL(genl_unregister_family);
* Returns pointer to user specific header
*/
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
- struct genl_family *family, int flags, u8 cmd)
+ const struct genl_family *family, int flags, u8 cmd)
{
struct nlmsghdr *nlh;
struct genlmsghdr *hdr;
@@ -535,7 +495,7 @@ static int genl_lock_done(struct netlink_callback *cb)
return rc;
}
-static int genl_family_rcv_msg(struct genl_family *family,
+static int genl_family_rcv_msg(const struct genl_family *family,
struct sk_buff *skb,
struct nlmsghdr *nlh)
{
@@ -647,7 +607,7 @@ out:
static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
- struct genl_family *family;
+ const struct genl_family *family;
int err;
family = genl_family_find_byid(nlh->nlmsg_type);
@@ -676,15 +636,9 @@ static void genl_rcv(struct sk_buff *skb)
* Controller
**************************************************************************/
-static struct genl_family genl_ctrl = {
- .id = GENL_ID_CTRL,
- .name = "nlctrl",
- .version = 0x2,
- .maxattr = CTRL_ATTR_MAX,
- .netnsok = true,
-};
+static struct genl_family genl_ctrl;
-static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
+static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq,
u32 flags, struct sk_buff *skb, u8 cmd)
{
void *hdr;
@@ -771,7 +725,7 @@ nla_put_failure:
return -EMSGSIZE;
}
-static int ctrl_fill_mcgrp_info(struct genl_family *family,
+static int ctrl_fill_mcgrp_info(const struct genl_family *family,
const struct genl_multicast_group *grp,
int grp_id, u32 portid, u32 seq, u32 flags,
struct sk_buff *skb, u8 cmd)
@@ -814,37 +768,30 @@ nla_put_failure:
static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
{
-
- int i, n = 0;
+ int n = 0;
struct genl_family *rt;
struct net *net = sock_net(skb->sk);
- int chains_to_skip = cb->args[0];
- int fams_to_skip = cb->args[1];
-
- for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
- n = 0;
- list_for_each_entry(rt, genl_family_chain(i), family_list) {
- if (!rt->netnsok && !net_eq(net, &init_net))
- continue;
- if (++n < fams_to_skip)
- continue;
- if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI,
- skb, CTRL_CMD_NEWFAMILY) < 0)
- goto errout;
- }
+ int fams_to_skip = cb->args[0];
+ unsigned int id;
- fams_to_skip = 0;
- }
+ idr_for_each_entry(&genl_fam_idr, rt, id) {
+ if (!rt->netnsok && !net_eq(net, &init_net))
+ continue;
+
+ if (n++ < fams_to_skip)
+ continue;
-errout:
- cb->args[0] = i;
- cb->args[1] = n;
+ if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ skb, CTRL_CMD_NEWFAMILY) < 0)
+ break;
+ }
+ cb->args[0] = n;
return skb->len;
}
-static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
+static struct sk_buff *ctrl_build_family_msg(const struct genl_family *family,
u32 portid, int seq, u8 cmd)
{
struct sk_buff *skb;
@@ -864,7 +811,7 @@ static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
}
static struct sk_buff *
-ctrl_build_mcgrp_msg(struct genl_family *family,
+ctrl_build_mcgrp_msg(const struct genl_family *family,
const struct genl_multicast_group *grp,
int grp_id, u32 portid, int seq, u8 cmd)
{
@@ -894,7 +841,7 @@ static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *msg;
- struct genl_family *res = NULL;
+ const struct genl_family *res = NULL;
int err = -EINVAL;
if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
@@ -938,7 +885,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
return genlmsg_reply(msg, info);
}
-static int genl_ctrl_event(int event, struct genl_family *family,
+static int genl_ctrl_event(int event, const struct genl_family *family,
const struct genl_multicast_group *grp,
int grp_id)
{
@@ -992,27 +939,39 @@ static const struct genl_multicast_group genl_ctrl_groups[] = {
{ .name = "notify", },
};
+static struct genl_family genl_ctrl __ro_after_init = {
+ .module = THIS_MODULE,
+ .ops = genl_ctrl_ops,
+ .n_ops = ARRAY_SIZE(genl_ctrl_ops),
+ .mcgrps = genl_ctrl_groups,
+ .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),
+ .id = GENL_ID_CTRL,
+ .name = "nlctrl",
+ .version = 0x2,
+ .maxattr = CTRL_ATTR_MAX,
+ .netnsok = true,
+};
+
static int genl_bind(struct net *net, int group)
{
- int i, err = -ENOENT;
+ struct genl_family *f;
+ int err = -ENOENT;
+ unsigned int id;
down_read(&cb_lock);
- for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
- struct genl_family *f;
-
- list_for_each_entry(f, genl_family_chain(i), family_list) {
- if (group >= f->mcgrp_offset &&
- group < f->mcgrp_offset + f->n_mcgrps) {
- int fam_grp = group - f->mcgrp_offset;
-
- if (!f->netnsok && net != &init_net)
- err = -ENOENT;
- else if (f->mcast_bind)
- err = f->mcast_bind(net, fam_grp);
- else
- err = 0;
- break;
- }
+
+ idr_for_each_entry(&genl_fam_idr, f, id) {
+ if (group >= f->mcgrp_offset &&
+ group < f->mcgrp_offset + f->n_mcgrps) {
+ int fam_grp = group - f->mcgrp_offset;
+
+ if (!f->netnsok && net != &init_net)
+ err = -ENOENT;
+ else if (f->mcast_bind)
+ err = f->mcast_bind(net, fam_grp);
+ else
+ err = 0;
+ break;
}
}
up_read(&cb_lock);
@@ -1022,21 +981,19 @@ static int genl_bind(struct net *net, int group)
static void genl_unbind(struct net *net, int group)
{
- int i;
+ struct genl_family *f;
+ unsigned int id;
down_read(&cb_lock);
- for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
- struct genl_family *f;
- list_for_each_entry(f, genl_family_chain(i), family_list) {
- if (group >= f->mcgrp_offset &&
- group < f->mcgrp_offset + f->n_mcgrps) {
- int fam_grp = group - f->mcgrp_offset;
+ idr_for_each_entry(&genl_fam_idr, f, id) {
+ if (group >= f->mcgrp_offset &&
+ group < f->mcgrp_offset + f->n_mcgrps) {
+ int fam_grp = group - f->mcgrp_offset;
- if (f->mcast_unbind)
- f->mcast_unbind(net, fam_grp);
- break;
- }
+ if (f->mcast_unbind)
+ f->mcast_unbind(net, fam_grp);
+ break;
}
}
up_read(&cb_lock);
@@ -1076,13 +1033,9 @@ static struct pernet_operations genl_pernet_ops = {
static int __init genl_init(void)
{
- int i, err;
-
- for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
- INIT_LIST_HEAD(&family_ht[i]);
+ int err;
- err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops,
- genl_ctrl_groups);
+ err = genl_register_family(&genl_ctrl);
if (err < 0)
goto problem;
@@ -1098,6 +1051,25 @@ problem:
subsys_initcall(genl_init);
+/**
+ * genl_family_attrbuf - return family's attrbuf
+ * @family: the family
+ *
+ * Return the family's attrbuf, while validating that it's
+ * actually valid to access it.
+ *
+ * You cannot use this function with a family that has parallel_ops
+ * and you can only use it within (pre/post) doit/dumpit callbacks.
+ */
+struct nlattr **genl_family_attrbuf(const struct genl_family *family)
+{
+ if (!WARN_ON(family->parallel_ops))
+ lockdep_assert_held(&genl_mutex);
+
+ return family->attrbuf;
+}
+EXPORT_SYMBOL(genl_family_attrbuf);
+
static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
gfp_t flags)
{
@@ -1127,8 +1099,9 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
return err;
}
-int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
- u32 portid, unsigned int group, gfp_t flags)
+int genlmsg_multicast_allns(const struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
+ unsigned int group, gfp_t flags)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
@@ -1137,7 +1110,7 @@ int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
}
EXPORT_SYMBOL(genlmsg_multicast_allns);
-void genl_notify(struct genl_family *family, struct sk_buff *skb,
+void genl_notify(const struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags)
{
struct net *net = genl_info_net(info);
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index ea023b35f1c2..03f3d5c7beb8 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -38,14 +38,7 @@ static const struct genl_multicast_group nfc_genl_mcgrps[] = {
{ .name = NFC_GENL_MCAST_EVENT_NAME, },
};
-static struct genl_family nfc_genl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = NFC_GENL_NAME,
- .version = NFC_GENL_VERSION,
- .maxattr = NFC_ATTR_MAX,
-};
-
+static struct genl_family nfc_genl_family;
static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
[NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },
[NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
@@ -120,21 +113,20 @@ nla_put_failure:
static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
{
+ struct nlattr **attrbuf = genl_family_attrbuf(&nfc_genl_family);
struct nfc_dev *dev;
int rc;
u32 idx;
rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
- nfc_genl_family.attrbuf,
- nfc_genl_family.maxattr,
- nfc_genl_policy);
+ attrbuf, nfc_genl_family.maxattr, nfc_genl_policy);
if (rc < 0)
return ERR_PTR(rc);
- if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
+ if (!attrbuf[NFC_ATTR_DEVICE_INDEX])
return ERR_PTR(-EINVAL);
- idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
+ idx = nla_get_u32(attrbuf[NFC_ATTR_DEVICE_INDEX]);
dev = nfc_get_device(idx);
if (!dev)
@@ -1754,6 +1746,18 @@ static const struct genl_ops nfc_genl_ops[] = {
},
};
+static struct genl_family nfc_genl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = NFC_GENL_NAME,
+ .version = NFC_GENL_VERSION,
+ .maxattr = NFC_ATTR_MAX,
+ .module = THIS_MODULE,
+ .ops = nfc_genl_ops,
+ .n_ops = ARRAY_SIZE(nfc_genl_ops),
+ .mcgrps = nfc_genl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(nfc_genl_mcgrps),
+};
+
struct urelease_work {
struct work_struct w;
@@ -1839,9 +1843,7 @@ int __init nfc_genl_init(void)
{
int rc;
- rc = genl_register_family_with_ops_groups(&nfc_genl_family,
- nfc_genl_ops,
- nfc_genl_mcgrps);
+ rc = genl_register_family(&nfc_genl_family);
if (rc)
return rc;
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 4e03f64709bc..514f7bcf7c63 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -62,9 +62,11 @@ struct ovs_frag_data {
struct vport *vport;
struct ovs_skb_cb cb;
__be16 inner_protocol;
- __u16 vlan_tci;
+ u16 network_offset; /* valid only for MPLS */
+ u16 vlan_tci;
__be16 vlan_proto;
unsigned int l2_len;
+ u8 mac_proto;
u8 l2_data[MAX_L2_LEN];
};
@@ -136,12 +138,12 @@ static struct deferred_action *add_deferred_actions(struct sk_buff *skb,
static void invalidate_flow_key(struct sw_flow_key *key)
{
- key->eth.type = htons(0);
+ key->mac_proto |= SW_FLOW_KEY_INVALID;
}
static bool is_flow_key_valid(const struct sw_flow_key *key)
{
- return !!key->eth.type;
+ return !(key->mac_proto & SW_FLOW_KEY_INVALID);
}
static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
@@ -185,7 +187,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
- update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
+ if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET)
+ update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
skb->protocol = mpls->mpls_ethertype;
invalidate_flow_key(key);
@@ -195,7 +198,6 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const __be16 ethertype)
{
- struct ethhdr *hdr;
int err;
err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
@@ -211,11 +213,15 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_reset_mac_header(skb);
skb_set_network_header(skb, skb->mac_len);
- /* mpls_hdr() is used to locate the ethertype field correctly in the
- * presence of VLAN tags.
- */
- hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
- update_ethertype(skb, hdr, ethertype);
+ if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET) {
+ struct ethhdr *hdr;
+
+ /* mpls_hdr() is used to locate the ethertype field correctly in the
+ * presence of VLAN tags.
+ */
+ hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
+ update_ethertype(skb, hdr, ethertype);
+ }
if (eth_p_mpls(skb->protocol))
skb->protocol = ethertype;
@@ -311,6 +317,47 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
return 0;
}
+/* pop_eth does not support VLAN packets as this action is never called
+ * for them.
+ */
+static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ skb_pull_rcsum(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+
+ /* safe right before invalidate_flow_key */
+ key->mac_proto = MAC_PROTO_NONE;
+ invalidate_flow_key(key);
+ return 0;
+}
+
+static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct ovs_action_push_eth *ethh)
+{
+ struct ethhdr *hdr;
+
+ /* Add the new Ethernet header */
+ if (skb_cow_head(skb, ETH_HLEN) < 0)
+ return -ENOMEM;
+
+ skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+
+ hdr = eth_hdr(skb);
+ ether_addr_copy(hdr->h_source, ethh->addresses.eth_src);
+ ether_addr_copy(hdr->h_dest, ethh->addresses.eth_dst);
+ hdr->h_proto = skb->protocol;
+
+ skb_postpush_rcsum(skb, hdr, ETH_HLEN);
+
+ /* safe right before invalidate_flow_key */
+ key->mac_proto = MAC_PROTO_ETHERNET;
+ invalidate_flow_key(key);
+ return 0;
+}
+
static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
__be32 addr, __be32 new_addr)
{
@@ -666,7 +713,13 @@ static int ovs_vport_output(struct net *net, struct sock *sk, struct sk_buff *sk
skb_postpush_rcsum(skb, skb->data, data->l2_len);
skb_reset_mac_header(skb);
- ovs_vport_send(vport, skb);
+ if (eth_p_mpls(skb->protocol)) {
+ skb->inner_network_header = skb->network_header;
+ skb_set_network_header(skb, data->network_offset);
+ skb_reset_mac_len(skb);
+ }
+
+ ovs_vport_send(vport, skb, data->mac_proto);
return 0;
}
@@ -684,7 +737,8 @@ static struct dst_ops ovs_dst_ops = {
/* prepare_frag() is called once per (larger-than-MTU) frame; its inverse is
* ovs_vport_output(), which is called once per fragmented packet.
*/
-static void prepare_frag(struct vport *vport, struct sk_buff *skb)
+static void prepare_frag(struct vport *vport, struct sk_buff *skb,
+ u16 orig_network_offset, u8 mac_proto)
{
unsigned int hlen = skb_network_offset(skb);
struct ovs_frag_data *data;
@@ -694,8 +748,10 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb)
data->vport = vport;
data->cb = *OVS_CB(skb);
data->inner_protocol = skb->inner_protocol;
+ data->network_offset = orig_network_offset;
data->vlan_tci = skb->vlan_tci;
data->vlan_proto = skb->vlan_proto;
+ data->mac_proto = mac_proto;
data->l2_len = hlen;
memcpy(&data->l2_data, skb->data, hlen);
@@ -704,18 +760,27 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb)
}
static void ovs_fragment(struct net *net, struct vport *vport,
- struct sk_buff *skb, u16 mru, __be16 ethertype)
+ struct sk_buff *skb, u16 mru,
+ struct sw_flow_key *key)
{
+ u16 orig_network_offset = 0;
+
+ if (eth_p_mpls(skb->protocol)) {
+ orig_network_offset = skb_network_offset(skb);
+ skb->network_header = skb->inner_network_header;
+ }
+
if (skb_network_offset(skb) > MAX_L2_LEN) {
OVS_NLERR(1, "L2 header too long to fragment");
goto err;
}
- if (ethertype == htons(ETH_P_IP)) {
+ if (key->eth.type == htons(ETH_P_IP)) {
struct dst_entry ovs_dst;
unsigned long orig_dst;
- prepare_frag(vport, skb);
+ prepare_frag(vport, skb, orig_network_offset,
+ ovs_key_mac_proto(key));
dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1,
DST_OBSOLETE_NONE, DST_NOCOUNT);
ovs_dst.dev = vport->dev;
@@ -726,7 +791,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
ip_do_fragment(net, skb->sk, skb, ovs_vport_output);
refdst_drop(orig_dst);
- } else if (ethertype == htons(ETH_P_IPV6)) {
+ } else if (key->eth.type == htons(ETH_P_IPV6)) {
const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
unsigned long orig_dst;
struct rt6_info ovs_rt;
@@ -735,7 +800,8 @@ static void ovs_fragment(struct net *net, struct vport *vport,
goto err;
}
- prepare_frag(vport, skb);
+ prepare_frag(vport, skb, orig_network_offset,
+ ovs_key_mac_proto(key));
memset(&ovs_rt, 0, sizeof(ovs_rt));
dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1,
DST_OBSOLETE_NONE, DST_NOCOUNT);
@@ -749,7 +815,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
refdst_drop(orig_dst);
} else {
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
- ovs_vport_name(vport), ntohs(ethertype), mru,
+ ovs_vport_name(vport), ntohs(key->eth.type), mru,
vport->dev->mtu);
goto err;
}
@@ -769,26 +835,19 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
u32 cutlen = OVS_CB(skb)->cutlen;
if (unlikely(cutlen > 0)) {
- if (skb->len - cutlen > ETH_HLEN)
+ if (skb->len - cutlen > ovs_mac_header_len(key))
pskb_trim(skb, skb->len - cutlen);
else
- pskb_trim(skb, ETH_HLEN);
+ pskb_trim(skb, ovs_mac_header_len(key));
}
- if (likely(!mru || (skb->len <= mru + ETH_HLEN))) {
- ovs_vport_send(vport, skb);
+ if (likely(!mru ||
+ (skb->len <= mru + vport->dev->hard_header_len))) {
+ ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
} else if (mru <= vport->dev->mtu) {
struct net *net = read_pnet(&dp->net);
- __be16 ethertype = key->eth.type;
-
- if (!is_flow_key_valid(key)) {
- if (eth_p_mpls(skb->protocol))
- ethertype = skb->inner_protocol;
- else
- ethertype = vlan_get_protocol(skb);
- }
- ovs_fragment(net, vport, skb, mru, ethertype);
+ ovs_fragment(net, vport, skb, mru, key);
} else {
kfree_skb(skb);
}
@@ -1182,6 +1241,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
if (err)
return err == -EINPROGRESS ? 0 : err;
break;
+
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ err = push_eth(skb, key, nla_data(a));
+ break;
+
+ case OVS_ACTION_ATTR_POP_ETH:
+ err = pop_eth(skb, key);
+ break;
}
if (unlikely(err)) {
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index fecefa2dc94e..6b78bab27755 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -728,12 +728,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
skb->nfctinfo = IP_CT_NEW;
}
- /* Repeat if requested, see nf_iterate(). */
- do {
- err = nf_conntrack_in(net, info->family,
- NF_INET_PRE_ROUTING, skb);
- } while (err == NF_REPEAT);
-
+ err = nf_conntrack_in(net, info->family,
+ NF_INET_PRE_ROUTING, skb);
if (err != NF_ACCEPT)
return -ENOENT;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 4d67ea856067..2d4c4d3911c0 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -58,8 +58,7 @@
#include "vport-internal_dev.h"
#include "vport-netdev.h"
-int ovs_net_id __read_mostly;
-EXPORT_SYMBOL_GPL(ovs_net_id);
+unsigned int ovs_net_id __read_mostly;
static struct genl_family dp_packet_genl_family;
static struct genl_family dp_flow_genl_family;
@@ -131,7 +130,6 @@ int lockdep_ovsl_is_held(void)
else
return 1;
}
-EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held);
#endif
static struct vport *new_vport(const struct vport_parms *);
@@ -562,7 +560,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
struct sw_flow *flow;
struct sw_flow_actions *sf_acts;
struct datapath *dp;
- struct ethhdr *eth;
struct vport *input_vport;
u16 mru = 0;
int len;
@@ -583,17 +580,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len);
- skb_reset_mac_header(packet);
- eth = eth_hdr(packet);
-
- /* Normally, setting the skb 'protocol' field would be handled by a
- * call to eth_type_trans(), but it assumes there's a sending
- * device, which we may not have. */
- if (eth_proto_is_802_3(eth->h_proto))
- packet->protocol = eth->h_proto;
- else
- packet->protocol = htons(ETH_P_802_2);
-
/* Set packet's mru */
if (a[OVS_PACKET_ATTR_MRU]) {
mru = nla_get_u16(a[OVS_PACKET_ATTR_MRU]);
@@ -620,6 +606,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
rcu_assign_pointer(flow->sf_acts, acts);
packet->priority = flow->key.phy.priority;
packet->mark = flow->key.phy.skb_mark;
+ packet->protocol = flow->key.eth.type;
rcu_read_lock();
dp = get_dp_rcu(net, ovs_header->dp_ifindex);
@@ -672,8 +659,7 @@ static const struct genl_ops dp_packet_genl_ops[] = {
}
};
-static struct genl_family dp_packet_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family dp_packet_genl_family __ro_after_init = {
.hdrsize = sizeof(struct ovs_header),
.name = OVS_PACKET_FAMILY,
.version = OVS_PACKET_VERSION,
@@ -682,6 +668,7 @@ static struct genl_family dp_packet_genl_family = {
.parallel_ops = true,
.ops = dp_packet_genl_ops,
.n_ops = ARRAY_SIZE(dp_packet_genl_ops),
+ .module = THIS_MODULE,
};
static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
@@ -1437,8 +1424,7 @@ static const struct genl_ops dp_flow_genl_ops[] = {
},
};
-static struct genl_family dp_flow_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family dp_flow_genl_family __ro_after_init = {
.hdrsize = sizeof(struct ovs_header),
.name = OVS_FLOW_FAMILY,
.version = OVS_FLOW_VERSION,
@@ -1449,6 +1435,7 @@ static struct genl_family dp_flow_genl_family = {
.n_ops = ARRAY_SIZE(dp_flow_genl_ops),
.mcgrps = &ovs_dp_flow_multicast_group,
.n_mcgrps = 1,
+ .module = THIS_MODULE,
};
static size_t ovs_dp_cmd_msg_size(void)
@@ -1823,8 +1810,7 @@ static const struct genl_ops dp_datapath_genl_ops[] = {
},
};
-static struct genl_family dp_datapath_genl_family = {
- .id = GENL_ID_GENERATE,
+static struct genl_family dp_datapath_genl_family __ro_after_init = {
.hdrsize = sizeof(struct ovs_header),
.name = OVS_DATAPATH_FAMILY,
.version = OVS_DATAPATH_VERSION,
@@ -1835,6 +1821,7 @@ static struct genl_family dp_datapath_genl_family = {
.n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
.mcgrps = &ovs_dp_datapath_multicast_group,
.n_mcgrps = 1,
+ .module = THIS_MODULE,
};
/* Called with ovs_mutex or RCU read lock. */
@@ -2245,8 +2232,7 @@ static const struct genl_ops dp_vport_genl_ops[] = {
},
};
-struct genl_family dp_vport_genl_family = {
- .id = GENL_ID_GENERATE,
+struct genl_family dp_vport_genl_family __ro_after_init = {
.hdrsize = sizeof(struct ovs_header),
.name = OVS_VPORT_FAMILY,
.version = OVS_VPORT_VERSION,
@@ -2257,6 +2243,7 @@ struct genl_family dp_vport_genl_family = {
.n_ops = ARRAY_SIZE(dp_vport_genl_ops),
.mcgrps = &ovs_dp_vport_multicast_group,
.n_mcgrps = 1,
+ .module = THIS_MODULE,
};
static struct genl_family * const dp_genl_families[] = {
@@ -2274,7 +2261,7 @@ static void dp_unregister_genl(int n_families)
genl_unregister_family(dp_genl_families[i]);
}
-static int dp_register_genl(void)
+static int __init dp_register_genl(void)
{
int err;
int i;
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index ab85c1cae255..1c6e9377436d 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -144,7 +144,7 @@ struct ovs_net {
bool xt_label;
};
-extern int ovs_net_id;
+extern unsigned int ovs_net_id;
void ovs_lock(void);
void ovs_unlock(void);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 22087062bd10..08aa926cd5cf 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -334,14 +334,17 @@ static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh)
return 1;
}
-static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
+static void clear_vlan(struct sw_flow_key *key)
{
- int res;
-
key->eth.vlan.tci = 0;
key->eth.vlan.tpid = 0;
key->eth.cvlan.tci = 0;
key->eth.cvlan.tpid = 0;
+}
+
+static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ int res;
if (skb_vlan_tag_present(skb)) {
key->eth.vlan.tci = htons(skb->vlan_tci);
@@ -483,17 +486,20 @@ invalid:
*
* Returns 0 if successful, otherwise a negative errno value.
*
- * Initializes @skb header pointers as follows:
+ * Initializes @skb header fields as follows:
*
- * - skb->mac_header: the Ethernet header.
+ * - skb->mac_header: the L2 header.
*
- * - skb->network_header: just past the Ethernet header, or just past the
- * VLAN header, to the first byte of the Ethernet payload.
+ * - skb->network_header: just past the L2 header, or just past the
+ * VLAN header, to the first byte of the L2 payload.
*
* - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
* on output, then just past the IP header, if one is present and
* of a correct length, otherwise the same as skb->network_header.
* For other key->eth.type values it is left untouched.
+ *
+ * - skb->protocol: the type of the data starting at skb->network_header.
+ * Equals to key->eth.type.
*/
static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
{
@@ -505,28 +511,35 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
skb_reset_mac_header(skb);
- /* Link layer. We are guaranteed to have at least the 14 byte Ethernet
- * header in the linear data area.
- */
- eth = eth_hdr(skb);
- ether_addr_copy(key->eth.src, eth->h_source);
- ether_addr_copy(key->eth.dst, eth->h_dest);
+ /* Link layer. */
+ clear_vlan(key);
+ if (key->mac_proto == MAC_PROTO_NONE) {
+ if (unlikely(eth_type_vlan(skb->protocol)))
+ return -EINVAL;
- __skb_pull(skb, 2 * ETH_ALEN);
- /* We are going to push all headers that we pull, so no need to
- * update skb->csum here.
- */
+ skb_reset_network_header(skb);
+ } else {
+ eth = eth_hdr(skb);
+ ether_addr_copy(key->eth.src, eth->h_source);
+ ether_addr_copy(key->eth.dst, eth->h_dest);
- if (unlikely(parse_vlan(skb, key)))
- return -ENOMEM;
+ __skb_pull(skb, 2 * ETH_ALEN);
+ /* We are going to push all headers that we pull, so no need to
+ * update skb->csum here.
+ */
- key->eth.type = parse_ethertype(skb);
- if (unlikely(key->eth.type == htons(0)))
- return -ENOMEM;
+ if (unlikely(parse_vlan(skb, key)))
+ return -ENOMEM;
+
+ skb->protocol = parse_ethertype(skb);
+ if (unlikely(skb->protocol == htons(0)))
+ return -ENOMEM;
- skb_reset_network_header(skb);
+ skb_reset_network_header(skb);
+ __skb_push(skb, skb->data - skb_mac_header(skb));
+ }
skb_reset_mac_len(skb);
- __skb_push(skb, skb->data - skb_mac_header(skb));
+ key->eth.type = skb->protocol;
/* Network layer. */
if (key->eth.type == htons(ETH_P_IP)) {
@@ -721,9 +734,25 @@ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
return key_extract(skb, key);
}
+static int key_extract_mac_proto(struct sk_buff *skb)
+{
+ switch (skb->dev->type) {
+ case ARPHRD_ETHER:
+ return MAC_PROTO_ETHERNET;
+ case ARPHRD_NONE:
+ if (skb->protocol == htons(ETH_P_TEB))
+ return MAC_PROTO_ETHERNET;
+ return MAC_PROTO_NONE;
+ }
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+}
+
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
struct sk_buff *skb, struct sw_flow_key *key)
{
+ int res;
+
/* Extract metadata from packet. */
if (tun_info) {
key->tun_proto = ip_tunnel_info_af(tun_info);
@@ -751,6 +780,10 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
key->phy.skb_mark = skb->mark;
ovs_ct_fill_key(skb, key);
key->ovs_flow_hash = 0;
+ res = key_extract_mac_proto(skb);
+ if (res < 0)
+ return res;
+ key->mac_proto = res;
key->recirc_id = 0;
return key_extract(skb, key);
@@ -767,5 +800,29 @@ int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
if (err)
return err;
+ if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
+ /* key_extract assumes that skb->protocol is set-up for
+ * layer 3 packets which is the case for other callers,
+ * in particular packets recieved from the network stack.
+ * Here the correct value can be set from the metadata
+ * extracted above.
+ */
+ skb->protocol = key->eth.type;
+ } else {
+ struct ethhdr *eth;
+
+ skb_reset_mac_header(skb);
+ eth = eth_hdr(skb);
+
+ /* Normally, setting the skb 'protocol' field would be
+ * handled by a call to eth_type_trans(), but it assumes
+ * there's a sending device, which we may not have.
+ */
+ if (eth_proto_is_802_3(eth->h_proto))
+ skb->protocol = eth->h_proto;
+ else
+ skb->protocol = htons(ETH_P_802_2);
+ }
+
return key_extract(skb, key);
}
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index ae783f5c6695..f61cae7f9030 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -37,6 +37,12 @@
struct sk_buff;
+enum sw_flow_mac_proto {
+ MAC_PROTO_NONE = 0,
+ MAC_PROTO_ETHERNET,
+};
+#define SW_FLOW_KEY_INVALID 0x80
+
/* Store options at the end of the array if they are less than the
* maximum size. This allows us to get the benefits of variable length
* matching for small options.
@@ -68,6 +74,7 @@ struct sw_flow_key {
u32 skb_mark; /* SKB mark. */
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
} __packed phy; /* Safe when right after 'tun_key'. */
+ u8 mac_proto; /* MAC layer protocol (e.g. Ethernet). */
u8 tun_proto; /* Protocol of encapsulating tunnel. */
u32 ovs_flow_hash; /* Datapath computed hash value. */
u32 recirc_id; /* Recirculation ID. */
@@ -206,6 +213,21 @@ struct arp_eth_header {
unsigned char ar_tip[4]; /* target IP address */
} __packed;
+static inline u8 ovs_key_mac_proto(const struct sw_flow_key *key)
+{
+ return key->mac_proto & ~SW_FLOW_KEY_INVALID;
+}
+
+static inline u16 __ovs_mac_header_len(u8 mac_proto)
+{
+ return mac_proto == MAC_PROTO_ETHERNET ? ETH_HLEN : 0;
+}
+
+static inline u16 ovs_mac_header_len(const struct sw_flow_key *key)
+{
+ return __ovs_mac_header_len(ovs_key_mac_proto(key));
+}
+
static inline bool ovs_identifier_is_ufid(const struct sw_flow_id *sfid)
{
return sfid->ufid_len;
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index ae25ded82b3b..d19044f2b1f4 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -123,7 +123,7 @@ static void update_range(struct sw_flow_match *match,
static bool match_validate(const struct sw_flow_match *match,
u64 key_attrs, u64 mask_attrs, bool log)
{
- u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
+ u64 key_expected = 0;
u64 mask_allowed = key_attrs; /* At most allow all key attributes */
/* The following mask attributes allowed only if they
@@ -969,10 +969,33 @@ static int parse_vlan_from_nlattrs(struct sw_flow_match *match,
return 0;
}
+static int parse_eth_type_from_nlattrs(struct sw_flow_match *match,
+ u64 *attrs, const struct nlattr **a,
+ bool is_mask, bool log)
+{
+ __be16 eth_type;
+
+ eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
+ if (is_mask) {
+ /* Always exact match EtherType. */
+ eth_type = htons(0xffff);
+ } else if (!eth_proto_is_802_3(eth_type)) {
+ OVS_NLERR(log, "EtherType %x is less than min %x",
+ ntohs(eth_type), ETH_P_802_3_MIN);
+ return -EINVAL;
+ }
+
+ SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
+ *attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
+ return 0;
+}
+
static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
u64 *attrs, const struct nlattr **a,
bool is_mask, bool log)
{
+ u8 mac_proto = MAC_PROTO_ETHERNET;
+
if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
@@ -1059,6 +1082,21 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
sizeof(*cl), is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
+
+ /* For layer 3 packets the Ethernet type is provided
+ * and treated as metadata but no MAC addresses are provided.
+ */
+ if (!(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
+ (*attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)))
+ mac_proto = MAC_PROTO_NONE;
+
+ /* Always exact match mac_proto */
+ SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : mac_proto, is_mask);
+
+ if (mac_proto == MAC_PROTO_NONE)
+ return parse_eth_type_from_nlattrs(match, attrs, a, is_mask,
+ log);
+
return 0;
}
@@ -1081,33 +1119,26 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
SW_FLOW_KEY_MEMCPY(match, eth.dst,
eth_key->eth_dst, ETH_ALEN, is_mask);
attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
- }
- if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
- /* VLAN attribute is always parsed before getting here since it
- * may occur multiple times.
- */
- OVS_NLERR(log, "VLAN attribute unexpected.");
- return -EINVAL;
- }
-
- if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
- __be16 eth_type;
-
- eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
- if (is_mask) {
- /* Always exact match EtherType. */
- eth_type = htons(0xffff);
- } else if (!eth_proto_is_802_3(eth_type)) {
- OVS_NLERR(log, "EtherType %x is less than min %x",
- ntohs(eth_type), ETH_P_802_3_MIN);
+ if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
+ /* VLAN attribute is always parsed before getting here since it
+ * may occur multiple times.
+ */
+ OVS_NLERR(log, "VLAN attribute unexpected.");
return -EINVAL;
}
- SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
- attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
- } else if (!is_mask) {
- SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
+ if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
+ err = parse_eth_type_from_nlattrs(match, &attrs, a, is_mask,
+ log);
+ if (err)
+ return err;
+ } else if (!is_mask) {
+ SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
+ }
+ } else if (!match->key->eth.type) {
+ OVS_NLERR(log, "Either Ethernet header or EtherType is required.");
+ return -EINVAL;
}
if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
@@ -1556,42 +1587,44 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
if (ovs_ct_put_key(output, skb))
goto nla_put_failure;
- nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
- if (!nla)
- goto nla_put_failure;
-
- eth_key = nla_data(nla);
- ether_addr_copy(eth_key->eth_src, output->eth.src);
- ether_addr_copy(eth_key->eth_dst, output->eth.dst);
-
- if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) {
- if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask))
+ if (ovs_key_mac_proto(swkey) == MAC_PROTO_ETHERNET) {
+ nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
+ if (!nla)
goto nla_put_failure;
- encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
- if (!swkey->eth.vlan.tci)
- goto unencap;
- if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) {
- if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask))
+ eth_key = nla_data(nla);
+ ether_addr_copy(eth_key->eth_src, output->eth.src);
+ ether_addr_copy(eth_key->eth_dst, output->eth.dst);
+
+ if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) {
+ if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask))
goto nla_put_failure;
- in_encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
- if (!swkey->eth.cvlan.tci)
+ encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
+ if (!swkey->eth.vlan.tci)
goto unencap;
+
+ if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) {
+ if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask))
+ goto nla_put_failure;
+ in_encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
+ if (!swkey->eth.cvlan.tci)
+ goto unencap;
+ }
}
- }
- if (swkey->eth.type == htons(ETH_P_802_2)) {
- /*
- * Ethertype 802.2 is represented in the netlink with omitted
- * OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
- * 0xffff in the mask attribute. Ethertype can also
- * be wildcarded.
- */
- if (is_mask && output->eth.type)
- if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
- output->eth.type))
- goto nla_put_failure;
- goto unencap;
+ if (swkey->eth.type == htons(ETH_P_802_2)) {
+ /*
+ * Ethertype 802.2 is represented in the netlink with omitted
+ * OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
+ * 0xffff in the mask attribute. Ethertype can also
+ * be wildcarded.
+ */
+ if (is_mask && output->eth.type)
+ if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
+ output->eth.type))
+ goto nla_put_failure;
+ goto unencap;
+ }
}
if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
@@ -2126,8 +2159,8 @@ static bool validate_masked(u8 *data, int len)
static int validate_set(const struct nlattr *a,
const struct sw_flow_key *flow_key,
- struct sw_flow_actions **sfa,
- bool *skip_copy, __be16 eth_type, bool masked, bool log)
+ struct sw_flow_actions **sfa, bool *skip_copy,
+ u8 mac_proto, __be16 eth_type, bool masked, bool log)
{
const struct nlattr *ovs_key = nla_data(a);
int key_type = nla_type(ovs_key);
@@ -2157,9 +2190,12 @@ static int validate_set(const struct nlattr *a,
case OVS_KEY_ATTR_SKB_MARK:
case OVS_KEY_ATTR_CT_MARK:
case OVS_KEY_ATTR_CT_LABELS:
- case OVS_KEY_ATTR_ETHERNET:
break;
+ case OVS_KEY_ATTR_ETHERNET:
+ if (mac_proto != MAC_PROTO_ETHERNET)
+ return -EINVAL;
+
case OVS_KEY_ATTR_TUNNEL:
if (masked)
return -EINVAL; /* Masked tunnel set not supported. */
@@ -2324,6 +2360,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
int depth, struct sw_flow_actions **sfa,
__be16 eth_type, __be16 vlan_tci, bool log)
{
+ u8 mac_proto = ovs_key_mac_proto(key);
const struct nlattr *a;
int rem, err;
@@ -2346,6 +2383,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
[OVS_ACTION_ATTR_CT] = (u32)-1,
[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
+ [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
+ [OVS_ACTION_ATTR_POP_ETH] = 0,
};
const struct ovs_action_push_vlan *vlan;
int type = nla_type(a);
@@ -2394,10 +2433,14 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
}
case OVS_ACTION_ATTR_POP_VLAN:
+ if (mac_proto != MAC_PROTO_ETHERNET)
+ return -EINVAL;
vlan_tci = htons(0);
break;
case OVS_ACTION_ATTR_PUSH_VLAN:
+ if (mac_proto != MAC_PROTO_ETHERNET)
+ return -EINVAL;
vlan = nla_data(a);
if (!eth_type_vlan(vlan->vlan_tpid))
return -EINVAL;
@@ -2447,14 +2490,16 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
case OVS_ACTION_ATTR_SET:
err = validate_set(a, key, sfa,
- &skip_copy, eth_type, false, log);
+ &skip_copy, mac_proto, eth_type,
+ false, log);
if (err)
return err;
break;
case OVS_ACTION_ATTR_SET_MASKED:
err = validate_set(a, key, sfa,
- &skip_copy, eth_type, true, log);
+ &skip_copy, mac_proto, eth_type,
+ true, log);
if (err)
return err;
break;
@@ -2474,6 +2519,22 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
skip_copy = true;
break;
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ /* Disallow pushing an Ethernet header if one
+ * is already present */
+ if (mac_proto != MAC_PROTO_NONE)
+ return -EINVAL;
+ mac_proto = MAC_PROTO_NONE;
+ break;
+
+ case OVS_ACTION_ATTR_POP_ETH:
+ if (mac_proto != MAC_PROTO_ETHERNET)
+ return -EINVAL;
+ if (vlan_tci & htons(VLAN_TAG_PRESENT))
+ return -EINVAL;
+ mac_proto = MAC_PROTO_ETHERNET;
+ break;
+
default:
OVS_NLERR(log, "Unknown Action type %d", type);
return -EINVAL;
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index e7da29021b38..d5d6caecd072 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -89,15 +89,6 @@ static const struct ethtool_ops internal_dev_ethtool_ops = {
.get_link = ethtool_op_get_link,
};
-static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu)
-{
- if (new_mtu < 68)
- return -EINVAL;
-
- netdev->mtu = new_mtu;
- return 0;
-}
-
static void internal_dev_destructor(struct net_device *dev)
{
struct vport *vport = ovs_internal_dev_get_vport(dev);
@@ -148,7 +139,6 @@ static const struct net_device_ops internal_dev_netdev_ops = {
.ndo_stop = internal_dev_stop,
.ndo_start_xmit = internal_dev_xmit,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = internal_dev_change_mtu,
.ndo_get_stats64 = internal_get_stats,
.ndo_set_rx_headroom = internal_set_rx_headroom,
};
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 4e3972344aa6..0389398fa4ab 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -57,8 +57,10 @@ static void netdev_port_receive(struct sk_buff *skb)
if (unlikely(!skb))
return;
- skb_push(skb, ETH_HLEN);
- skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+ if (skb->dev->type == ARPHRD_ETHER) {
+ skb_push(skb, ETH_HLEN);
+ skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+ }
ovs_vport_receive(vport, skb, skb_tunnel_info(skb));
return;
error:
@@ -97,7 +99,8 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)
}
if (vport->dev->flags & IFF_LOOPBACK ||
- vport->dev->type != ARPHRD_ETHER ||
+ (vport->dev->type != ARPHRD_ETHER &&
+ vport->dev->type != ARPHRD_NONE) ||
ovs_is_internal_dev(vport->dev)) {
err = -EINVAL;
goto error_put;
@@ -162,7 +165,6 @@ void ovs_netdev_detach_dev(struct vport *vport)
netdev_master_upper_dev_get(vport->dev));
dev_set_promiscuity(vport->dev, -1);
}
-EXPORT_SYMBOL_GPL(ovs_netdev_detach_dev);
static void netdev_destroy(struct vport *vport)
{
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 7387418ac514..b6c8524032a0 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -463,27 +463,11 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
ovs_dp_process_packet(skb, &key);
return 0;
}
-EXPORT_SYMBOL_GPL(ovs_vport_receive);
-static void free_vport_rcu(struct rcu_head *rcu)
+static unsigned int packet_length(const struct sk_buff *skb,
+ struct net_device *dev)
{
- struct vport *vport = container_of(rcu, struct vport, rcu);
-
- ovs_vport_free(vport);
-}
-
-void ovs_vport_deferred_free(struct vport *vport)
-{
- if (!vport)
- return;
-
- call_rcu(&vport->rcu, free_vport_rcu);
-}
-EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
-
-static unsigned int packet_length(const struct sk_buff *skb)
-{
- unsigned int length = skb->len - ETH_HLEN;
+ unsigned int length = skb->len - dev->hard_header_len;
if (!skb_vlan_tag_present(skb) &&
eth_type_vlan(skb->protocol))
@@ -497,14 +481,34 @@ static unsigned int packet_length(const struct sk_buff *skb)
return length;
}
-void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
+void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
{
int mtu = vport->dev->mtu;
- if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+ switch (vport->dev->type) {
+ case ARPHRD_NONE:
+ if (mac_proto == MAC_PROTO_ETHERNET) {
+ skb_reset_network_header(skb);
+ skb_reset_mac_len(skb);
+ skb->protocol = htons(ETH_P_TEB);
+ } else if (mac_proto != MAC_PROTO_NONE) {
+ WARN_ON_ONCE(1);
+ goto drop;
+ }
+ break;
+ case ARPHRD_ETHER:
+ if (mac_proto != MAC_PROTO_ETHERNET)
+ goto drop;
+ break;
+ default:
+ goto drop;
+ }
+
+ if (unlikely(packet_length(skb, vport->dev) > mtu &&
+ !skb_is_gso(skb))) {
net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
vport->dev->name,
- packet_length(skb), mtu);
+ packet_length(skb, vport->dev), mtu);
vport->dev->stats.tx_errors++;
goto drop;
}
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index f01f28a567ad..cda66c26ad08 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -149,7 +149,6 @@ struct vport_ops {
struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *,
const struct vport_parms *);
void ovs_vport_free(struct vport *);
-void ovs_vport_deferred_free(struct vport *vport);
#define VPORT_ALIGN 8
@@ -198,6 +197,6 @@ int __ovs_vport_ops_register(struct vport_ops *ops);
})
void ovs_vport_ops_unregister(struct vport_ops *ops);
-void ovs_vport_send(struct vport *vport, struct sk_buff *skb);
+void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto);
#endif /* vport.h */
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index dd2332390c45..89f2e8c1f4dc 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1967,17 +1967,6 @@ static unsigned int run_filter(struct sk_buff *skb,
return res;
}
-static int __packet_rcv_vnet(const struct sk_buff *skb,
- struct virtio_net_hdr *vnet_hdr)
-{
- *vnet_hdr = (const struct virtio_net_hdr) { 0 };
-
- if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le()))
- BUG();
-
- return 0;
-}
-
static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
size_t *len)
{
@@ -1987,7 +1976,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
return -EINVAL;
*len -= sizeof(vnet_hdr);
- if (__packet_rcv_vnet(skb, &vnet_hdr))
+ if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le()))
return -EINVAL;
return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr));
@@ -2246,8 +2235,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
spin_unlock(&sk->sk_receive_queue.lock);
if (po->has_vnet_hdr) {
- if (__packet_rcv_vnet(skb, h.raw + macoff -
- sizeof(struct virtio_net_hdr))) {
+ if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
+ sizeof(struct virtio_net_hdr),
+ vio_le())) {
spin_lock(&sk->sk_receive_queue.lock);
goto drop_n_account;
}
@@ -2390,8 +2380,6 @@ static void tpacket_set_protocol(const struct net_device *dev,
static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len)
{
- unsigned short gso_type = 0;
-
if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
(__virtio16_to_cpu(vio_le(), vnet_hdr->csum_start) +
__virtio16_to_cpu(vio_le(), vnet_hdr->csum_offset) + 2 >
@@ -2403,29 +2391,6 @@ static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len)
if (__virtio16_to_cpu(vio_le(), vnet_hdr->hdr_len) > len)
return -EINVAL;
- if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
- switch (vnet_hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
- case VIRTIO_NET_HDR_GSO_TCPV4:
- gso_type = SKB_GSO_TCPV4;
- break;
- case VIRTIO_NET_HDR_GSO_TCPV6:
- gso_type = SKB_GSO_TCPV6;
- break;
- case VIRTIO_NET_HDR_GSO_UDP:
- gso_type = SKB_GSO_UDP;
- break;
- default:
- return -EINVAL;
- }
-
- if (vnet_hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
- gso_type |= SKB_GSO_TCP_ECN;
-
- if (vnet_hdr->gso_size == 0)
- return -EINVAL;
- }
-
- vnet_hdr->gso_type = gso_type; /* changes type, temporary storage */
return 0;
}
@@ -2445,27 +2410,6 @@ static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len,
return __packet_snd_vnet_parse(vnet_hdr, *len);
}
-static int packet_snd_vnet_gso(struct sk_buff *skb,
- struct virtio_net_hdr *vnet_hdr)
-{
- if (vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
- u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr->csum_start);
- u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr->csum_offset);
-
- if (!skb_partial_csum_set(skb, s, o))
- return -EINVAL;
- }
-
- skb_shinfo(skb)->gso_size =
- __virtio16_to_cpu(vio_le(), vnet_hdr->gso_size);
- skb_shinfo(skb)->gso_type = vnet_hdr->gso_type;
-
- /* Header must be checked, and gso_segs computed. */
- skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
- skb_shinfo(skb)->gso_segs = 0;
- return 0;
-}
-
static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
void *frame, struct net_device *dev, void *data, int tp_len,
__be16 proto, unsigned char *addr, int hlen, int copylen,
@@ -2725,7 +2669,8 @@ tpacket_error:
}
}
- if (po->has_vnet_hdr && packet_snd_vnet_gso(skb, vnet_hdr)) {
+ if (po->has_vnet_hdr && virtio_net_hdr_to_skb(skb, vnet_hdr,
+ vio_le())) {
tp_len = -EINVAL;
goto tpacket_error;
}
@@ -2916,7 +2861,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
packet_pick_tx_queue(dev, skb);
if (po->has_vnet_hdr) {
- err = packet_snd_vnet_gso(skb, &vnet_hdr);
+ err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le());
if (err)
goto out_free;
len += sizeof(vnet_hdr);
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index fa8237fdc57b..21c28b51be94 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -217,20 +217,10 @@ static netdev_tx_t gprs_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static int gprs_set_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11)))
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
static const struct net_device_ops gprs_netdev_ops = {
.ndo_open = gprs_open,
.ndo_stop = gprs_close,
.ndo_start_xmit = gprs_xmit,
- .ndo_change_mtu = gprs_set_mtu,
};
static void gprs_setup(struct net_device *dev)
@@ -239,6 +229,8 @@ static void gprs_setup(struct net_device *dev)
dev->type = ARPHRD_PHONET_PIPE;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = GPRS_DEFAULT_MTU;
+ dev->min_mtu = 576;
+ dev->max_mtu = (PHONET_MAX_MTU - 11);
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->tx_queue_len = 10;
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 850a86cde0b3..8bad5624a27a 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1167,7 +1167,7 @@ disabled:
/* Wait until flow control allows TX */
done = atomic_read(&pn->tx_credits);
while (!done) {
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
if (!timeo) {
err = -EAGAIN;
@@ -1178,10 +1178,9 @@ disabled:
goto out;
}
- prepare_to_wait(sk_sleep(sk), &wait,
- TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
- finish_wait(sk_sleep(sk), &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
+ done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
if (sk->sk_state != TCP_ESTABLISHED)
goto disabled;
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index a58680016472..2cb4c5dfad6f 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -44,7 +44,7 @@ struct phonet_net {
struct phonet_routes routes;
};
-static int phonet_net_id __read_mostly;
+static unsigned int phonet_net_id __read_mostly;
static struct phonet_net *phonet_pernet(struct net *net)
{
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index 6beaeb1138f3..2ac1e6194be3 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -605,10 +605,14 @@ static void rds_exit(void)
}
module_exit(rds_exit);
+u32 rds_gen_num;
+
static int rds_init(void)
{
int ret;
+ net_get_random_once(&rds_gen_num, sizeof(rds_gen_num));
+
ret = rds_bind_lock_init();
if (ret)
goto out;
diff --git a/net/rds/connection.c b/net/rds/connection.c
index f5058559bb08..fe9d31c0b22d 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -269,6 +269,8 @@ static struct rds_connection *__rds_conn_create(struct net *net,
kmem_cache_free(rds_conn_slab, conn);
conn = found;
} else {
+ conn->c_my_gen_num = rds_gen_num;
+ conn->c_peer_gen_num = 0;
hlist_add_head_rcu(&conn->c_hash_node, head);
rds_cong_add_conn(conn);
rds_conn_count++;
@@ -681,6 +683,7 @@ void rds_conn_path_connect_if_down(struct rds_conn_path *cp)
!test_and_set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags))
queue_delayed_work(rds_wq, &cp->cp_conn_w, 0);
}
+EXPORT_SYMBOL_GPL(rds_conn_path_connect_if_down);
void rds_conn_connect_if_down(struct rds_connection *conn)
{
@@ -689,21 +692,6 @@ void rds_conn_connect_if_down(struct rds_connection *conn)
}
EXPORT_SYMBOL_GPL(rds_conn_connect_if_down);
-/*
- * An error occurred on the connection
- */
-void
-__rds_conn_error(struct rds_connection *conn, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintk(fmt, ap);
- va_end(ap);
-
- rds_conn_drop(conn);
-}
-
void
__rds_conn_path_error(struct rds_conn_path *cp, const char *fmt, ...)
{
diff --git a/net/rds/message.c b/net/rds/message.c
index 6cb91061556a..49bfb512d808 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -42,6 +42,7 @@ static unsigned int rds_exthdr_size[__RDS_EXTHDR_MAX] = {
[RDS_EXTHDR_RDMA] = sizeof(struct rds_ext_header_rdma),
[RDS_EXTHDR_RDMA_DEST] = sizeof(struct rds_ext_header_rdma_dest),
[RDS_EXTHDR_NPATHS] = sizeof(u16),
+[RDS_EXTHDR_GEN_NUM] = sizeof(u32),
};
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 67ba67c058b1..ebbf909b87ec 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -151,6 +151,9 @@ struct rds_connection {
struct rds_conn_path c_path[RDS_MPATH_WORKERS];
wait_queue_head_t c_hs_waitq; /* handshake waitq */
+
+ u32 c_my_gen_num;
+ u32 c_peer_gen_num;
};
static inline
@@ -243,7 +246,8 @@ struct rds_ext_header_rdma_dest {
/* Extension header announcing number of paths.
* Implicit length = 2 bytes.
*/
-#define RDS_EXTHDR_NPATHS 4
+#define RDS_EXTHDR_NPATHS 5
+#define RDS_EXTHDR_GEN_NUM 6
#define __RDS_EXTHDR_MAX 16 /* for now */
@@ -338,6 +342,7 @@ static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
#define RDS_MSG_RETRANSMITTED 5
#define RDS_MSG_MAPPED 6
#define RDS_MSG_PAGEVEC 7
+#define RDS_MSG_FLUSH 8
struct rds_message {
atomic_t m_refcount;
@@ -664,6 +669,7 @@ void rds_cong_exit(void);
struct rds_message *rds_cong_update_alloc(struct rds_connection *conn);
/* conn.c */
+extern u32 rds_gen_num;
int rds_conn_init(void);
void rds_conn_exit(void);
struct rds_connection *rds_conn_create(struct net *net,
@@ -683,10 +689,6 @@ void rds_for_each_conn_info(struct socket *sock, unsigned int len,
struct rds_info_lengths *lens,
int (*visitor)(struct rds_connection *, void *),
size_t item_len);
-__printf(2, 3)
-void __rds_conn_error(struct rds_connection *conn, const char *, ...);
-#define rds_conn_error(conn, fmt...) \
- __rds_conn_error(conn, KERN_WARNING "RDS: " fmt)
__printf(2, 3)
void __rds_conn_path_error(struct rds_conn_path *cp, const char *, ...);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index cbfabdf3ff48..9d0666e5fe35 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -120,6 +120,36 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk,
/* do nothing if no change in cong state */
}
+static void rds_conn_peer_gen_update(struct rds_connection *conn,
+ u32 peer_gen_num)
+{
+ int i;
+ struct rds_message *rm, *tmp;
+ unsigned long flags;
+
+ WARN_ON(conn->c_trans->t_type != RDS_TRANS_TCP);
+ if (peer_gen_num != 0) {
+ if (conn->c_peer_gen_num != 0 &&
+ peer_gen_num != conn->c_peer_gen_num) {
+ for (i = 0; i < RDS_MPATH_WORKERS; i++) {
+ struct rds_conn_path *cp;
+
+ cp = &conn->c_path[i];
+ spin_lock_irqsave(&cp->cp_lock, flags);
+ cp->cp_next_tx_seq = 1;
+ cp->cp_next_rx_seq = 0;
+ list_for_each_entry_safe(rm, tmp,
+ &cp->cp_retrans,
+ m_conn_item) {
+ set_bit(RDS_MSG_FLUSH, &rm->m_flags);
+ }
+ spin_unlock_irqrestore(&cp->cp_lock, flags);
+ }
+ }
+ conn->c_peer_gen_num = peer_gen_num;
+ }
+}
+
/*
* Process all extension headers that come with this message.
*/
@@ -163,7 +193,9 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr,
union {
struct rds_ext_header_version version;
u16 rds_npaths;
+ u32 rds_gen_num;
} buffer;
+ u32 new_peer_gen_num = 0;
while (1) {
len = sizeof(buffer);
@@ -176,6 +208,9 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr,
conn->c_npaths = min_t(int, RDS_MPATH_WORKERS,
buffer.rds_npaths);
break;
+ case RDS_EXTHDR_GEN_NUM:
+ new_peer_gen_num = buffer.rds_gen_num;
+ break;
default:
pr_warn_ratelimited("ignoring unknown exthdr type "
"0x%x\n", type);
@@ -183,6 +218,7 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr,
}
/* if RDS_EXTHDR_NPATHS was not found, default to a single-path */
conn->c_npaths = max_t(int, conn->c_npaths, 1);
+ rds_conn_peer_gen_update(conn, new_peer_gen_num);
}
/* rds_start_mprds() will synchronously start multiple paths when appropriate.
diff --git a/net/rds/send.c b/net/rds/send.c
index 896626b9a0ef..77c8c6e613ad 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -259,8 +259,9 @@ restart:
* connection.
* Therefore, we never retransmit messages with RDMA ops.
*/
- if (rm->rdma.op_active &&
- test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags)) {
+ if (test_bit(RDS_MSG_FLUSH, &rm->m_flags) ||
+ (rm->rdma.op_active &&
+ test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags))) {
spin_lock_irqsave(&cp->cp_lock, flags);
if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
list_move(&rm->m_conn_item, &to_be_dropped);
@@ -1209,6 +1210,10 @@ rds_send_probe(struct rds_conn_path *cp, __be16 sport,
rds_message_add_extension(&rm->m_inc.i_hdr,
RDS_EXTHDR_NPATHS, &npaths,
sizeof(npaths));
+ rds_message_add_extension(&rm->m_inc.i_hdr,
+ RDS_EXTHDR_GEN_NUM,
+ &cp->cp_conn->c_my_gen_num,
+ sizeof(u32));
}
spin_unlock_irqrestore(&cp->cp_lock, flags);
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 20e2923dc827..57bb52361e0f 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -220,7 +220,7 @@ void rds_tcp_set_callbacks(struct socket *sock, struct rds_conn_path *cp)
write_unlock_bh(&sock->sk->sk_callback_lock);
}
-static void rds_tcp_tc_info(struct socket *sock, unsigned int len,
+static void rds_tcp_tc_info(struct socket *rds_sock, unsigned int len,
struct rds_info_iterator *iter,
struct rds_info_lengths *lens)
{
@@ -229,6 +229,7 @@ static void rds_tcp_tc_info(struct socket *sock, unsigned int len,
unsigned long flags;
struct sockaddr_in sin;
int sinlen;
+ struct socket *sock;
spin_lock_irqsave(&rds_tcp_tc_list_lock, flags);
@@ -237,12 +238,17 @@ static void rds_tcp_tc_info(struct socket *sock, unsigned int len,
list_for_each_entry(tc, &rds_tcp_tc_list, t_list_item) {
- sock->ops->getname(sock, (struct sockaddr *)&sin, &sinlen, 0);
- tsinfo.local_addr = sin.sin_addr.s_addr;
- tsinfo.local_port = sin.sin_port;
- sock->ops->getname(sock, (struct sockaddr *)&sin, &sinlen, 1);
- tsinfo.peer_addr = sin.sin_addr.s_addr;
- tsinfo.peer_port = sin.sin_port;
+ sock = tc->t_sock;
+ if (sock) {
+ sock->ops->getname(sock, (struct sockaddr *)&sin,
+ &sinlen, 0);
+ tsinfo.local_addr = sin.sin_addr.s_addr;
+ tsinfo.local_port = sin.sin_port;
+ sock->ops->getname(sock, (struct sockaddr *)&sin,
+ &sinlen, 1);
+ tsinfo.peer_addr = sin.sin_addr.s_addr;
+ tsinfo.peer_port = sin.sin_port;
+ }
tsinfo.hdr_rem = tc->t_tinc_hdr_rem;
tsinfo.data_rem = tc->t_tinc_data_rem;
@@ -360,7 +366,7 @@ struct rds_transport rds_tcp_transport = {
.t_mp_capable = 1,
};
-static int rds_tcp_netid;
+static unsigned int rds_tcp_netid;
/* per-network namespace private data for this module */
struct rds_tcp_net {
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index 05f61c533ed3..d6839d96d539 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -60,7 +60,19 @@ void rds_tcp_state_change(struct sock *sk)
case TCP_SYN_RECV:
break;
case TCP_ESTABLISHED:
- rds_connect_path_complete(cp, RDS_CONN_CONNECTING);
+ /* Force the peer to reconnect so that we have the
+ * TCP ports going from <smaller-ip>.<transient> to
+ * <larger-ip>.<RDS_TCP_PORT>. We avoid marking the
+ * RDS connection as RDS_CONN_UP until the reconnect,
+ * to avoid RDS datagram loss.
+ */
+ if (cp->cp_conn->c_laddr > cp->cp_conn->c_faddr &&
+ rds_conn_path_transition(cp, RDS_CONN_CONNECTING,
+ RDS_CONN_ERROR)) {
+ rds_conn_path_drop(cp);
+ } else {
+ rds_connect_path_complete(cp, RDS_CONN_CONNECTING);
+ }
break;
case TCP_CLOSE_WAIT:
case TCP_CLOSE:
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index e0b23fb5b8d5..f74bab3ecdca 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -83,27 +83,22 @@ struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn)
{
int i;
bool peer_is_smaller = (conn->c_faddr < conn->c_laddr);
- int npaths = conn->c_npaths;
-
- if (npaths <= 1) {
- struct rds_conn_path *cp = &conn->c_path[0];
- int ret;
-
- ret = rds_conn_path_transition(cp, RDS_CONN_DOWN,
- RDS_CONN_CONNECTING);
- if (!ret)
- rds_conn_path_transition(cp, RDS_CONN_ERROR,
- RDS_CONN_CONNECTING);
- return cp->cp_transport_data;
- }
+ int npaths = max_t(int, 1, conn->c_npaths);
- /* for mprds, paths with cp_index > 0 MUST be initiated by the peer
+ /* for mprds, all paths MUST be initiated by the peer
* with the smaller address.
*/
- if (!peer_is_smaller)
+ if (!peer_is_smaller) {
+ /* Make sure we initiate at least one path if this
+ * has not already been done; rds_start_mprds() will
+ * take care of additional paths, if necessary.
+ */
+ if (npaths == 1)
+ rds_conn_path_connect_if_down(&conn->c_path[0]);
return NULL;
+ }
- for (i = 1; i < npaths; i++) {
+ for (i = 0; i < npaths; i++) {
struct rds_conn_path *cp = &conn->c_path[i];
if (rds_conn_path_transition(cp, RDS_CONN_DOWN,
@@ -171,8 +166,8 @@ int rds_tcp_accept_one(struct socket *sock)
mutex_lock(&rs_tcp->t_conn_path_lock);
cp = rs_tcp->t_cpath;
conn_state = rds_conn_path_state(cp);
- if (conn_state != RDS_CONN_CONNECTING && conn_state != RDS_CONN_UP &&
- conn_state != RDS_CONN_ERROR)
+ WARN_ON(conn_state == RDS_CONN_UP);
+ if (conn_state != RDS_CONN_CONNECTING && conn_state != RDS_CONN_ERROR)
goto rst_nsk;
if (rs_tcp->t_sock) {
/* Need to resolve a duelling SYN between peers.
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
index 89d09b481f47..dcf4742083ea 100644
--- a/net/rds/tcp_send.c
+++ b/net/rds/tcp_send.c
@@ -100,6 +100,9 @@ int rds_tcp_xmit(struct rds_connection *conn, struct rds_message *rm,
set_bit(RDS_MSG_HAS_ACK_SEQ, &rm->m_flags);
tc->t_last_expected_una = rm->m_ack_seq + 1;
+ if (test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags))
+ rm->m_inc.i_hdr.h_flags |= RDS_FLAG_RETRANSMITTED;
+
rdsdebug("rm %p tcp nxt %u ack_seq %llu\n",
rm, rds_tcp_snd_nxt(tc),
(unsigned long long)rm->m_ack_seq);
diff --git a/net/rds/threads.c b/net/rds/threads.c
index e42df11bf30a..e36e333a0aa0 100644
--- a/net/rds/threads.c
+++ b/net/rds/threads.c
@@ -171,8 +171,7 @@ void rds_connect_worker(struct work_struct *work)
RDS_CONN_DOWN))
rds_queue_reconnect(cp);
else
- rds_conn_path_error(cp,
- "RDS: connect failed\n");
+ rds_conn_path_error(cp, "connect failed\n");
}
}
}
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 44fb8d893c7d..1d87b5453ef7 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1053,7 +1053,7 @@ void rxrpc_data_ready(struct sock *udp_sk)
ASSERT(!irqs_disabled());
- skb = skb_recv_datagram(udp_sk, 0, 1, &ret);
+ skb = skb_recv_udp(udp_sk, 0, 1, &ret);
if (!skb) {
if (ret == -EAGAIN)
return;
@@ -1075,10 +1075,9 @@ void rxrpc_data_ready(struct sock *udp_sk)
__UDP_INC_STATS(&init_net, UDP_MIB_INDATAGRAMS, 0);
- /* The socket buffer we have is owned by UDP, with UDP's data all over
- * it, but we really want our own data there.
+ /* The UDP protocol already released all skb resources;
+ * we are free to add our own data there.
*/
- skb_orphan(skb);
sp = rxrpc_skb(skb);
/* dig out the RxRPC connection details */
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index f893d180da1c..2095c83ce773 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -41,8 +41,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *p)
spin_lock_bh(&hinfo->lock);
hlist_del(&p->tcfa_head);
spin_unlock_bh(&hinfo->lock);
- gen_kill_estimator(&p->tcfa_bstats,
- &p->tcfa_rate_est);
+ gen_kill_estimator(&p->tcfa_rate_est);
/*
* gen_estimator est_timer() might access p->tcfa_lock
* or bstats, wait a RCU grace period before freeing p
@@ -237,8 +236,7 @@ EXPORT_SYMBOL(tcf_hash_check);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
{
if (est)
- gen_kill_estimator(&a->tcfa_bstats,
- &a->tcfa_rate_est);
+ gen_kill_estimator(&a->tcfa_rate_est);
call_rcu(&a->tcfa_rcu, free_tcf);
}
EXPORT_SYMBOL(tcf_hash_cleanup);
@@ -670,8 +668,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
goto errout;
if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
- gnet_stats_copy_rate_est(&d, &p->tcfa_bstats,
- &p->tcfa_rate_est) < 0 ||
+ gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
gnet_stats_copy_queue(&d, p->cpu_qstats,
&p->tcfa_qstats,
p->tcfa_qstats.qlen) < 0)
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 1d3960033f61..1c60317f0121 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -28,12 +28,11 @@ struct tcf_bpf_cfg {
struct bpf_prog *filter;
struct sock_filter *bpf_ops;
const char *bpf_name;
- u32 bpf_fd;
u16 bpf_num_ops;
bool is_ebpf;
};
-static int bpf_net_id;
+static unsigned int bpf_net_id;
static struct tc_action_ops act_bpf_ops;
static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
@@ -118,13 +117,19 @@ static int tcf_bpf_dump_bpf_info(const struct tcf_bpf *prog,
static int tcf_bpf_dump_ebpf_info(const struct tcf_bpf *prog,
struct sk_buff *skb)
{
- if (nla_put_u32(skb, TCA_ACT_BPF_FD, prog->bpf_fd))
- return -EMSGSIZE;
+ struct nlattr *nla;
if (prog->bpf_name &&
nla_put_string(skb, TCA_ACT_BPF_NAME, prog->bpf_name))
return -EMSGSIZE;
+ nla = nla_reserve(skb, TCA_ACT_BPF_DIGEST,
+ sizeof(prog->filter->digest));
+ if (nla == NULL)
+ return -EMSGSIZE;
+
+ memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
+
return 0;
}
@@ -226,16 +231,13 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
return PTR_ERR(fp);
if (tb[TCA_ACT_BPF_NAME]) {
- name = kmemdup(nla_data(tb[TCA_ACT_BPF_NAME]),
- nla_len(tb[TCA_ACT_BPF_NAME]),
- GFP_KERNEL);
+ name = nla_memdup(tb[TCA_ACT_BPF_NAME], GFP_KERNEL);
if (!name) {
bpf_prog_put(fp);
return -ENOMEM;
}
}
- cfg->bpf_fd = bpf_fd;
cfg->bpf_name = name;
cfg->filter = fp;
cfg->is_ebpf = true;
@@ -334,8 +336,6 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (cfg.bpf_num_ops)
prog->bpf_num_ops = cfg.bpf_num_ops;
- if (cfg.bpf_fd)
- prog->bpf_fd = cfg.bpf_fd;
prog->tcf_action = parm->action;
rcu_assign_pointer(prog->filter, cfg.filter);
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index eae07a2e774d..ab8062909962 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -30,7 +30,7 @@
#define CONNMARK_TAB_MASK 3
-static int connmark_net_id;
+static unsigned int connmark_net_id;
static struct tc_action_ops act_connmark_ops;
static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index e0defcef376d..a0edd80a44db 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -42,7 +42,7 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
};
-static int csum_net_id;
+static unsigned int csum_net_id;
static struct tc_action_ops act_csum_ops;
static int tcf_csum_init(struct net *net, struct nlattr *nla,
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e0aa30f83c6c..e6c874a2b283 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -25,7 +25,7 @@
#define GACT_TAB_MASK 15
-static int gact_net_id;
+static unsigned int gact_net_id;
static struct tc_action_ops act_gact_ops;
#ifdef CONFIG_GACT_PROB
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 95c463cbb9a6..80b848d3f096 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -35,7 +35,7 @@
#define IFE_TAB_MASK 15
-static int ife_net_id;
+static unsigned int ife_net_id;
static int max_metacnt = IFE_META_MAX + 1;
static struct tc_action_ops act_ife_ops;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 378c1c976058..992ef8d624f1 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -30,10 +30,10 @@
#define IPT_TAB_MASK 15
-static int ipt_net_id;
+static unsigned int ipt_net_id;
static struct tc_action_ops act_ipt_ops;
-static int xt_net_id;
+static unsigned int xt_net_id;
static struct tc_action_ops act_xt_ops;
static int ipt_init_target(struct xt_entry_target *t, char *table,
@@ -213,6 +213,12 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
int ret = 0, result = 0;
struct tcf_ipt *ipt = to_ipt(a);
struct xt_action_param par;
+ struct nf_hook_state state = {
+ .net = dev_net(skb->dev),
+ .in = skb->dev,
+ .hook = ipt->tcfi_hook,
+ .pf = NFPROTO_IPV4,
+ };
if (skb_unclone(skb, GFP_ATOMIC))
return TC_ACT_UNSPEC;
@@ -226,13 +232,9 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
* worry later - danger - this API seems to have changed
* from earlier kernels
*/
- par.net = dev_net(skb->dev);
- par.in = skb->dev;
- par.out = NULL;
- par.hooknum = ipt->tcfi_hook;
+ par.state = &state;
par.target = ipt->tcfi_t->u.kernel.target;
par.targinfo = ipt->tcfi_t->data;
- par.family = NFPROTO_IPV4;
ret = par.target->target(skb, &par);
switch (ret) {
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 6b07fba5770b..2d9fa6e0a1b4 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gfp.h>
+#include <linux/if_arp.h>
#include <net/net_namespace.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -33,6 +34,25 @@
static LIST_HEAD(mirred_list);
static DEFINE_SPINLOCK(mirred_list_lock);
+static bool tcf_mirred_is_act_redirect(int action)
+{
+ return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
+}
+
+static u32 tcf_mirred_act_direction(int action)
+{
+ switch (action) {
+ case TCA_EGRESS_REDIR:
+ case TCA_EGRESS_MIRROR:
+ return AT_EGRESS;
+ case TCA_INGRESS_REDIR:
+ case TCA_INGRESS_MIRROR:
+ return AT_INGRESS;
+ default:
+ BUG();
+ }
+}
+
static void tcf_mirred_release(struct tc_action *a, int bind)
{
struct tcf_mirred *m = to_mirred(a);
@@ -51,7 +71,7 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
[TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
};
-static int mirred_net_id;
+static unsigned int mirred_net_id;
static struct tc_action_ops act_mirred_ops;
static int tcf_mirred_init(struct net *net, struct nlattr *nla,
@@ -60,11 +80,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
struct nlattr *tb[TCA_MIRRED_MAX + 1];
+ bool mac_header_xmit = false;
struct tc_mirred *parm;
struct tcf_mirred *m;
struct net_device *dev;
- int ret, ok_push = 0;
bool exists = false;
+ int ret;
if (nla == NULL)
return -EINVAL;
@@ -82,6 +103,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
switch (parm->eaction) {
case TCA_EGRESS_MIRROR:
case TCA_EGRESS_REDIR:
+ case TCA_INGRESS_REDIR:
+ case TCA_INGRESS_MIRROR:
break;
default:
if (exists)
@@ -95,19 +118,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
tcf_hash_release(*a, bind);
return -ENODEV;
}
- switch (dev->type) {
- case ARPHRD_TUNNEL:
- case ARPHRD_TUNNEL6:
- case ARPHRD_SIT:
- case ARPHRD_IPGRE:
- case ARPHRD_VOID:
- case ARPHRD_NONE:
- ok_push = 0;
- break;
- default:
- ok_push = 1;
- break;
- }
+ mac_header_xmit = dev_is_mac_header_xmit(dev);
} else {
dev = NULL;
}
@@ -136,7 +147,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
dev_put(rcu_dereference_protected(m->tcfm_dev, 1));
dev_hold(dev);
rcu_assign_pointer(m->tcfm_dev, dev);
- m->tcfm_ok_push = ok_push;
+ m->tcfm_mac_header_xmit = mac_header_xmit;
}
if (ret == ACT_P_CREATED) {
@@ -153,15 +164,20 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res)
{
struct tcf_mirred *m = to_mirred(a);
+ bool m_mac_header_xmit;
struct net_device *dev;
struct sk_buff *skb2;
- int retval, err;
+ int retval, err = 0;
+ int m_eaction;
+ int mac_len;
u32 at;
tcf_lastuse_update(&m->tcf_tm);
bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
rcu_read_lock();
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+ m_eaction = READ_ONCE(m->tcfm_eaction);
retval = READ_ONCE(m->tcf_action);
dev = rcu_dereference(m->tcfm_dev);
if (unlikely(!dev)) {
@@ -180,23 +196,36 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
if (!skb2)
goto out;
- if (!(at & AT_EGRESS)) {
- if (m->tcfm_ok_push)
+ /* If action's target direction differs than filter's direction,
+ * and devices expect a mac header on xmit, then mac push/pull is
+ * needed.
+ */
+ if (at != tcf_mirred_act_direction(m_eaction) && m_mac_header_xmit) {
+ if (at & AT_EGRESS) {
+ /* caught at egress, act ingress: pull mac */
+ mac_len = skb_network_header(skb) - skb_mac_header(skb);
+ skb_pull_rcsum(skb2, mac_len);
+ } else {
+ /* caught at ingress, act egress: push mac */
skb_push_rcsum(skb2, skb->mac_len);
+ }
}
/* mirror is always swallowed */
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+ if (tcf_mirred_is_act_redirect(m_eaction))
skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
skb2->skb_iif = skb->dev->ifindex;
skb2->dev = dev;
- err = dev_queue_xmit(skb2);
+ if (tcf_mirred_act_direction(m_eaction) & AT_EGRESS)
+ err = dev_queue_xmit(skb2);
+ else
+ err = netif_receive_skb(skb2);
if (err) {
out:
qstats_overlimit_inc(this_cpu_ptr(m->common.cpu_qstats));
- if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+ if (tcf_mirred_is_act_redirect(m_eaction))
retval = TC_ACT_SHOT;
}
rcu_read_unlock();
@@ -286,6 +315,17 @@ static struct notifier_block mirred_device_notifier = {
.notifier_call = mirred_device_event,
};
+static int tcf_mirred_device(const struct tc_action *a, struct net *net,
+ struct net_device **mirred_dev)
+{
+ int ifindex = tcf_mirred_ifindex(a);
+
+ *mirred_dev = __dev_get_by_index(net, ifindex);
+ if (!*mirred_dev)
+ return -EINVAL;
+ return 0;
+}
+
static struct tc_action_ops act_mirred_ops = {
.kind = "mirred",
.type = TCA_ACT_MIRRED,
@@ -298,6 +338,7 @@ static struct tc_action_ops act_mirred_ops = {
.walk = tcf_mirred_walker,
.lookup = tcf_mirred_search,
.size = sizeof(struct tcf_mirred),
+ .get_dev = tcf_mirred_device,
};
static __net_init int mirred_init_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 8e8b0cc30704..9b6aec665495 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -31,7 +31,7 @@
#define NAT_TAB_MASK 15
-static int nat_net_id;
+static unsigned int nat_net_id;
static struct tc_action_ops act_nat_ops;
static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index cf9b2fe8eac6..b27c4daec88f 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -25,7 +25,7 @@
#define PEDIT_TAB_MASK 15
-static int pedit_net_id;
+static unsigned int pedit_net_id;
static struct tc_action_ops act_pedit_ops;
static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index d1bd248fe146..0ba91d1ce994 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -55,7 +55,7 @@ struct tc_police_compat {
/* Each policer is serialized by its individual spinlock */
-static int police_net_id;
+static unsigned int police_net_id;
static struct tc_action_ops act_police_ops;
static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
@@ -142,8 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
goto failure_unlock;
} else if (tb[TCA_POLICE_AVRATE] &&
(ret == ACT_P_CREATED ||
- !gen_estimator_active(&police->tcf_bstats,
- &police->tcf_rate_est))) {
+ !gen_estimator_active(&police->tcf_rate_est))) {
err = -EINVAL;
goto failure_unlock;
}
@@ -216,13 +215,17 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
bstats_update(&police->tcf_bstats, skb);
tcf_lastuse_update(&police->tcf_tm);
- if (police->tcfp_ewma_rate &&
- police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
- police->tcf_qstats.overlimits++;
- if (police->tcf_action == TC_ACT_SHOT)
- police->tcf_qstats.drops++;
- spin_unlock(&police->tcf_lock);
- return police->tcf_action;
+ if (police->tcfp_ewma_rate) {
+ struct gnet_stats_rate_est64 sample;
+
+ if (!gen_estimator_read(&police->tcf_rate_est, &sample) ||
+ sample.bps >= police->tcfp_ewma_rate) {
+ police->tcf_qstats.overlimits++;
+ if (police->tcf_action == TC_ACT_SHOT)
+ police->tcf_qstats.drops++;
+ spin_unlock(&police->tcf_lock);
+ return police->tcf_action;
+ }
}
if (qdisc_pkt_len(skb) <= police->tcfp_mtu) {
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 289af6f9bb3b..823a73ad0c60 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -26,7 +26,7 @@
#define SIMP_TAB_MASK 7
-static int simp_net_id;
+static unsigned int simp_net_id;
static struct tc_action_ops act_simp_ops;
#define SIMP_MAX_DATA 32
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index a133dcb82132..06ccae3c12ee 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -29,7 +29,7 @@
#define SKBEDIT_TAB_MASK 15
-static int skbedit_net_id;
+static unsigned int skbedit_net_id;
static struct tc_action_ops act_skbedit_ops;
static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
@@ -46,8 +46,10 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
- if (d->flags & SKBEDIT_F_MARK)
- skb->mark = d->mark;
+ if (d->flags & SKBEDIT_F_MARK) {
+ skb->mark &= ~d->mask;
+ skb->mark |= d->mark & d->mask;
+ }
if (d->flags & SKBEDIT_F_PTYPE)
skb->pkt_type = d->ptype;
@@ -61,6 +63,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
[TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
+ [TCA_SKBEDIT_MASK] = { .len = sizeof(u32) },
};
static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -71,7 +74,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
struct tc_skbedit *parm;
struct tcf_skbedit *d;
- u32 flags = 0, *priority = NULL, *mark = NULL;
+ u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL;
u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false;
int ret = 0, err;
@@ -108,6 +111,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
mark = nla_data(tb[TCA_SKBEDIT_MARK]);
}
+ if (tb[TCA_SKBEDIT_MASK] != NULL) {
+ flags |= SKBEDIT_F_MASK;
+ mask = nla_data(tb[TCA_SKBEDIT_MASK]);
+ }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
@@ -145,6 +153,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
d->mark = *mark;
if (flags & SKBEDIT_F_PTYPE)
d->ptype = *ptype;
+ /* default behaviour is to use all the bits */
+ d->mask = 0xffffffff;
+ if (flags & SKBEDIT_F_MASK)
+ d->mask = *mask;
d->tcf_action = parm->action;
@@ -182,6 +194,9 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
if ((d->flags & SKBEDIT_F_PTYPE) &&
nla_put_u16(skb, TCA_SKBEDIT_PTYPE, d->ptype))
goto nla_put_failure;
+ if ((d->flags & SKBEDIT_F_MASK) &&
+ nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
+ goto nla_put_failure;
tcf_tm_dump(&t, &d->tcf_tm);
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index e7d96381c908..3b7074e23024 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -22,7 +22,7 @@
#define SKBMOD_TAB_MASK 15
-static int skbmod_net_id;
+static unsigned int skbmod_net_id;
static struct tc_action_ops act_skbmod_ops;
#define MAX_EDIT_LEN ETH_HLEN
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index af47bdf2f483..7af712526f01 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -16,14 +16,13 @@
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/dst.h>
-#include <net/dst_metadata.h>
#include <linux/tc_act/tc_tunnel_key.h>
#include <net/tc_act/tc_tunnel_key.h>
#define TUNNEL_KEY_TAB_MASK 15
-static int tunnel_key_net_id;
+static unsigned int tunnel_key_net_id;
static struct tc_action_ops act_tunnel_key_ops;
static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a,
@@ -67,6 +66,7 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
[TCA_TUNNEL_KEY_ENC_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
[TCA_TUNNEL_KEY_ENC_IPV6_DST] = { .len = sizeof(struct in6_addr) },
[TCA_TUNNEL_KEY_ENC_KEY_ID] = { .type = NLA_U32 },
+ [TCA_TUNNEL_KEY_ENC_DST_PORT] = {.type = NLA_U16},
};
static int tunnel_key_init(struct net *net, struct nlattr *nla,
@@ -81,6 +81,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
struct tc_tunnel_key *parm;
struct tcf_tunnel_key *t;
bool exists = false;
+ __be16 dst_port = 0;
__be64 key_id;
int ret = 0;
int err;
@@ -111,6 +112,9 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
key_id = key32_to_tunnel_id(nla_get_be32(tb[TCA_TUNNEL_KEY_ENC_KEY_ID]));
+ if (tb[TCA_TUNNEL_KEY_ENC_DST_PORT])
+ dst_port = nla_get_be16(tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
+
if (tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC] &&
tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]) {
__be32 saddr;
@@ -120,7 +124,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
daddr = nla_get_in_addr(tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
metadata = __ip_tun_set_dst(saddr, daddr, 0, 0,
- TUNNEL_KEY, key_id, 0);
+ dst_port, TUNNEL_KEY,
+ key_id, 0);
} else if (tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC] &&
tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]) {
struct in6_addr saddr;
@@ -130,7 +135,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
daddr = nla_get_in6_addr(tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
metadata = __ipv6_tun_set_dst(&saddr, &daddr, 0, 0, 0,
- TUNNEL_KEY, key_id, 0);
+ dst_port, TUNNEL_KEY,
+ key_id, 0);
}
if (!metadata) {
@@ -258,7 +264,8 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
if (nla_put_be32(skb, TCA_TUNNEL_KEY_ENC_KEY_ID, key_id) ||
tunnel_key_dump_addresses(skb,
- &params->tcft_enc_metadata->u.tun_info))
+ &params->tcft_enc_metadata->u.tun_info) ||
+ nla_put_be16(skb, TCA_TUNNEL_KEY_ENC_DST_PORT, key->tp_dst))
goto nla_put_failure;
}
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index b57fcbcefea1..19e0dba305ce 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -21,7 +21,7 @@
#define VLAN_TAB_MASK 15
-static int vlan_net_id;
+static unsigned int vlan_net_id;
static struct tc_action_ops act_vlan_ops;
static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b05d4a2155b0..3fbba79a4ef0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -682,6 +682,30 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts)
}
EXPORT_SYMBOL(tcf_exts_dump_stats);
+int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
+ struct net_device **hw_dev)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ const struct tc_action *a;
+ LIST_HEAD(actions);
+
+ if (tc_no_actions(exts))
+ return -EINVAL;
+
+ tcf_exts_to_list(exts, &actions);
+ list_for_each_entry(a, &actions, list) {
+ if (a->ops->get_dev) {
+ a->ops->get_dev(a, dev_net(dev), hw_dev);
+ break;
+ }
+ }
+ if (*hw_dev)
+ return 0;
+#endif
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(tcf_exts_get_dev);
+
static int __init tc_filter_init(void)
{
rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 0a47ba5e6109..adc776048d1a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -45,10 +45,7 @@ struct cls_bpf_prog {
u32 gen_flags;
struct tcf_exts exts;
u32 handle;
- union {
- u32 bpf_fd;
- u16 bpf_num_ops;
- };
+ u16 bpf_num_ops;
struct sock_filter *bpf_ops;
const char *bpf_name;
struct tcf_proto *tp;
@@ -244,7 +241,7 @@ static int cls_bpf_init(struct tcf_proto *tp)
return 0;
}
-static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog)
+static void __cls_bpf_delete_prog(struct cls_bpf_prog *prog)
{
tcf_exts_destroy(&prog->exts);
@@ -258,22 +255,22 @@ static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog)
kfree(prog);
}
-static void __cls_bpf_delete_prog(struct rcu_head *rcu)
+static void cls_bpf_delete_prog_rcu(struct rcu_head *rcu)
{
- struct cls_bpf_prog *prog = container_of(rcu, struct cls_bpf_prog, rcu);
-
- cls_bpf_delete_prog(prog->tp, prog);
+ __cls_bpf_delete_prog(container_of(rcu, struct cls_bpf_prog, rcu));
}
-static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg)
+static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog)
{
- struct cls_bpf_prog *prog = (struct cls_bpf_prog *) arg;
-
cls_bpf_stop_offload(tp, prog);
list_del_rcu(&prog->link);
tcf_unbind_filter(tp, &prog->res);
- call_rcu(&prog->rcu, __cls_bpf_delete_prog);
+ call_rcu(&prog->rcu, cls_bpf_delete_prog_rcu);
+}
+static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg)
+{
+ __cls_bpf_delete(tp, (struct cls_bpf_prog *) arg);
return 0;
}
@@ -285,12 +282,8 @@ static bool cls_bpf_destroy(struct tcf_proto *tp, bool force)
if (!force && !list_empty(&head->plist))
return false;
- list_for_each_entry_safe(prog, tmp, &head->plist, link) {
- cls_bpf_stop_offload(tp, prog);
- list_del_rcu(&prog->link);
- tcf_unbind_filter(tp, &prog->res);
- call_rcu(&prog->rcu, __cls_bpf_delete_prog);
- }
+ list_for_each_entry_safe(prog, tmp, &head->plist, link)
+ __cls_bpf_delete(tp, prog);
kfree_rcu(head, rcu);
return true;
@@ -365,9 +358,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
return PTR_ERR(fp);
if (tb[TCA_BPF_NAME]) {
- name = kmemdup(nla_data(tb[TCA_BPF_NAME]),
- nla_len(tb[TCA_BPF_NAME]),
- GFP_KERNEL);
+ name = nla_memdup(tb[TCA_BPF_NAME], GFP_KERNEL);
if (!name) {
bpf_prog_put(fp);
return -ENOMEM;
@@ -375,7 +366,6 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
}
prog->bpf_ops = NULL;
- prog->bpf_fd = bpf_fd;
prog->bpf_name = name;
prog->filter = fp;
@@ -517,14 +507,14 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
ret = cls_bpf_offload(tp, prog, oldprog);
if (ret) {
- cls_bpf_delete_prog(tp, prog);
+ __cls_bpf_delete_prog(prog);
return ret;
}
if (oldprog) {
list_replace_rcu(&oldprog->link, &prog->link);
tcf_unbind_filter(tp, &oldprog->res);
- call_rcu(&oldprog->rcu, __cls_bpf_delete_prog);
+ call_rcu(&oldprog->rcu, cls_bpf_delete_prog_rcu);
} else {
list_add_rcu(&prog->link, &head->plist);
}
@@ -559,13 +549,18 @@ static int cls_bpf_dump_bpf_info(const struct cls_bpf_prog *prog,
static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
struct sk_buff *skb)
{
- if (nla_put_u32(skb, TCA_BPF_FD, prog->bpf_fd))
- return -EMSGSIZE;
+ struct nlattr *nla;
if (prog->bpf_name &&
nla_put_string(skb, TCA_BPF_NAME, prog->bpf_name))
return -EMSGSIZE;
+ nla = nla_reserve(skb, TCA_BPF_DIGEST, sizeof(prog->filter->digest));
+ if (nla == NULL)
+ return -EMSGSIZE;
+
+ memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
+
return 0;
}
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 904442421db3..e040c5140f61 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -39,11 +39,13 @@ struct fl_flow_key {
struct flow_dissector_key_ipv6_addrs ipv6;
};
struct flow_dissector_key_ports tp;
+ struct flow_dissector_key_icmp icmp;
struct flow_dissector_key_keyid enc_key_id;
union {
struct flow_dissector_key_ipv4_addrs enc_ipv4;
struct flow_dissector_key_ipv6_addrs enc_ipv6;
};
+ struct flow_dissector_key_ports enc_tp;
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
struct fl_flow_mask_range {
@@ -81,6 +83,8 @@ struct cls_fl_filter {
u32 handle;
u32 flags;
struct rcu_head rcu;
+ struct tc_to_netdev tc;
+ struct net_device *hw_dev;
};
static unsigned short int fl_mask_range(const struct fl_flow_mask *mask)
@@ -159,6 +163,8 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
}
skb_key.enc_key_id.keyid = tunnel_id_to_key32(key->tun_id);
+ skb_key.enc_tp.src = key->tp_src;
+ skb_key.enc_tp.dst = key->tp_dst;
}
skb_key.indev_ifindex = skb->skb_iif;
@@ -202,75 +208,90 @@ static void fl_destroy_filter(struct rcu_head *head)
kfree(f);
}
-static void fl_hw_destroy_filter(struct tcf_proto *tp, unsigned long cookie)
+static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_flower_offload offload = {0};
- struct tc_to_netdev tc;
+ struct net_device *dev = f->hw_dev;
+ struct tc_to_netdev *tc = &f->tc;
- if (!tc_should_offload(dev, tp, 0))
+ if (!tc_can_offload(dev, tp))
return;
offload.command = TC_CLSFLOWER_DESTROY;
- offload.cookie = cookie;
+ offload.cookie = (unsigned long)f;
- tc.type = TC_SETUP_CLSFLOWER;
- tc.cls_flower = &offload;
+ tc->type = TC_SETUP_CLSFLOWER;
+ tc->cls_flower = &offload;
- dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
+ dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
}
static int fl_hw_replace_filter(struct tcf_proto *tp,
struct flow_dissector *dissector,
struct fl_flow_key *mask,
- struct fl_flow_key *key,
- struct tcf_exts *actions,
- unsigned long cookie, u32 flags)
+ struct cls_fl_filter *f)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_flower_offload offload = {0};
- struct tc_to_netdev tc;
+ struct tc_to_netdev *tc = &f->tc;
int err;
- if (!tc_should_offload(dev, tp, flags))
- return tc_skip_sw(flags) ? -EINVAL : 0;
+ if (!tc_can_offload(dev, tp)) {
+ if (tcf_exts_get_dev(dev, &f->exts, &f->hw_dev) ||
+ (f->hw_dev && !tc_can_offload(f->hw_dev, tp))) {
+ f->hw_dev = dev;
+ return tc_skip_sw(f->flags) ? -EINVAL : 0;
+ }
+ dev = f->hw_dev;
+ tc->egress_dev = true;
+ } else {
+ f->hw_dev = dev;
+ }
offload.command = TC_CLSFLOWER_REPLACE;
- offload.cookie = cookie;
+ offload.cookie = (unsigned long)f;
offload.dissector = dissector;
offload.mask = mask;
- offload.key = key;
- offload.exts = actions;
+ offload.key = &f->key;
+ offload.exts = &f->exts;
- tc.type = TC_SETUP_CLSFLOWER;
- tc.cls_flower = &offload;
+ tc->type = TC_SETUP_CLSFLOWER;
+ tc->cls_flower = &offload;
err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
- &tc);
+ tc);
- if (tc_skip_sw(flags))
+ if (tc_skip_sw(f->flags))
return err;
-
return 0;
}
static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_flower_offload offload = {0};
- struct tc_to_netdev tc;
+ struct net_device *dev = f->hw_dev;
+ struct tc_to_netdev *tc = &f->tc;
- if (!tc_should_offload(dev, tp, 0))
+ if (!tc_can_offload(dev, tp))
return;
offload.command = TC_CLSFLOWER_STATS;
offload.cookie = (unsigned long)f;
offload.exts = &f->exts;
- tc.type = TC_SETUP_CLSFLOWER;
- tc.cls_flower = &offload;
+ tc->type = TC_SETUP_CLSFLOWER;
+ tc->cls_flower = &offload;
+
+ dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
+}
- dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
+static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
+{
+ list_del_rcu(&f->list);
+ if (!tc_skip_hw(f->flags))
+ fl_hw_destroy_filter(tp, f);
+ tcf_unbind_filter(tp, &f->res);
+ call_rcu(&f->rcu, fl_destroy_filter);
}
static void fl_destroy_sleepable(struct work_struct *work)
@@ -299,14 +320,12 @@ static bool fl_destroy(struct tcf_proto *tp, bool force)
if (!force && !list_empty(&head->filters))
return false;
- list_for_each_entry_safe(f, next, &head->filters, list) {
- fl_hw_destroy_filter(tp, (unsigned long)f);
- list_del_rcu(&f->list);
- call_rcu(&f->rcu, fl_destroy_filter);
- }
+ list_for_each_entry_safe(f, next, &head->filters, list)
+ __fl_delete(tp, f);
__module_get(THIS_MODULE);
call_rcu(&head->rcu, fl_destroy_rcu);
+
return true;
}
@@ -360,6 +379,24 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
[TCA_FLOWER_KEY_TCP_DST_MASK] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_UDP_SRC_MASK] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_UDP_DST_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_SCTP_SRC_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_SCTP_DST_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_SCTP_SRC] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_SCTP_DST] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_ENC_UDP_SRC_PORT] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_ENC_UDP_DST_PORT] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_FLAGS] = { .type = NLA_U32 },
+ [TCA_FLOWER_KEY_FLAGS_MASK] = { .type = NLA_U32 },
+ [TCA_FLOWER_KEY_ICMPV4_TYPE] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV4_TYPE_MASK] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV4_CODE] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV4_CODE_MASK] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV6_TYPE] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV6_TYPE_MASK] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV6_CODE] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_ICMPV6_CODE_MASK] = { .type = NLA_U8 },
};
static void fl_set_key_val(struct nlattr **tb,
@@ -394,6 +431,39 @@ static void fl_set_key_vlan(struct nlattr **tb,
}
}
+static void fl_set_key_flag(u32 flower_key, u32 flower_mask,
+ u32 *dissector_key, u32 *dissector_mask,
+ u32 flower_flag_bit, u32 dissector_flag_bit)
+{
+ if (flower_mask & flower_flag_bit) {
+ *dissector_mask |= dissector_flag_bit;
+ if (flower_key & flower_flag_bit)
+ *dissector_key |= dissector_flag_bit;
+ }
+}
+
+static void fl_set_key_flags(struct nlattr **tb,
+ u32 *flags_key, u32 *flags_mask)
+{
+ u32 key, mask;
+
+ if (!tb[TCA_FLOWER_KEY_FLAGS])
+ return;
+
+ key = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS]));
+
+ if (!tb[TCA_FLOWER_KEY_FLAGS_MASK])
+ mask = ~0;
+ else
+ mask = be32_to_cpu(nla_get_u32(tb[TCA_FLOWER_KEY_FLAGS_MASK]));
+
+ *flags_key = 0;
+ *flags_mask = 0;
+
+ fl_set_key_flag(key, mask, flags_key, flags_mask,
+ TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT);
+}
+
static int fl_set_key(struct net *net, struct nlattr **tb,
struct fl_flow_key *key, struct fl_flow_key *mask)
{
@@ -469,6 +539,33 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
fl_set_key_val(tb, &key->tp.dst, TCA_FLOWER_KEY_UDP_DST,
&mask->tp.dst, TCA_FLOWER_KEY_UDP_DST_MASK,
sizeof(key->tp.dst));
+ } else if (key->basic.ip_proto == IPPROTO_SCTP) {
+ fl_set_key_val(tb, &key->tp.src, TCA_FLOWER_KEY_SCTP_SRC,
+ &mask->tp.src, TCA_FLOWER_KEY_SCTP_SRC_MASK,
+ sizeof(key->tp.src));
+ fl_set_key_val(tb, &key->tp.dst, TCA_FLOWER_KEY_SCTP_DST,
+ &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
+ sizeof(key->tp.dst));
+ } else if (key->basic.n_proto == htons(ETH_P_IP) &&
+ key->basic.ip_proto == IPPROTO_ICMP) {
+ fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV4_TYPE,
+ &mask->icmp.type,
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+ sizeof(key->icmp.type));
+ fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+ &mask->icmp.code,
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+ sizeof(key->icmp.code));
+ } else if (key->basic.n_proto == htons(ETH_P_IPV6) &&
+ key->basic.ip_proto == IPPROTO_ICMPV6) {
+ fl_set_key_val(tb, &key->icmp.type, TCA_FLOWER_KEY_ICMPV6_TYPE,
+ &mask->icmp.type,
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+ sizeof(key->icmp.type));
+ fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+ &mask->icmp.code,
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+ sizeof(key->icmp.code));
}
if (tb[TCA_FLOWER_KEY_ENC_IPV4_SRC] ||
@@ -505,6 +602,16 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
&mask->enc_key_id.keyid, TCA_FLOWER_UNSPEC,
sizeof(key->enc_key_id.keyid));
+ fl_set_key_val(tb, &key->enc_tp.src, TCA_FLOWER_KEY_ENC_UDP_SRC_PORT,
+ &mask->enc_tp.src, TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,
+ sizeof(key->enc_tp.src));
+
+ fl_set_key_val(tb, &key->enc_tp.dst, TCA_FLOWER_KEY_ENC_UDP_DST_PORT,
+ &mask->enc_tp.dst, TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,
+ sizeof(key->enc_tp.dst));
+
+ fl_set_key_flags(tb, &key->control.flags, &mask->control.flags);
+
return 0;
}
@@ -571,7 +678,21 @@ static void fl_init_dissector(struct cls_fl_head *head,
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
FLOW_DISSECTOR_KEY_PORTS, tp);
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+ FLOW_DISSECTOR_KEY_ICMP, icmp);
+ FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
FLOW_DISSECTOR_KEY_VLAN, vlan);
+ FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+ FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id);
+ FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, enc_ipv4);
+ FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+ FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, enc_ipv6);
+ if (FL_KEY_IS_MASKED(&mask->key, enc_ipv4) ||
+ FL_KEY_IS_MASKED(&mask->key, enc_ipv6))
+ FL_KEY_SET(keys, cnt, FLOW_DISSECTOR_KEY_ENC_CONTROL,
+ enc_control);
+ FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
+ FLOW_DISSECTOR_KEY_ENC_PORTS, enc_tp);
skb_flow_dissector_init(&head->dissector, keys, cnt);
}
@@ -721,21 +842,21 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
goto errout;
}
- err = fl_hw_replace_filter(tp,
- &head->dissector,
- &mask.key,
- &fnew->key,
- &fnew->exts,
- (unsigned long)fnew,
- fnew->flags);
- if (err)
- goto errout;
+ if (!tc_skip_hw(fnew->flags)) {
+ err = fl_hw_replace_filter(tp,
+ &head->dissector,
+ &mask.key,
+ fnew);
+ if (err)
+ goto errout;
+ }
if (fold) {
if (!tc_skip_sw(fold->flags))
rhashtable_remove_fast(&head->ht, &fold->ht_node,
head->ht_params);
- fl_hw_destroy_filter(tp, (unsigned long)fold);
+ if (!tc_skip_hw(fold->flags))
+ fl_hw_destroy_filter(tp, fold);
}
*arg = (unsigned long) fnew;
@@ -764,10 +885,7 @@ static int fl_delete(struct tcf_proto *tp, unsigned long arg)
if (!tc_skip_sw(f->flags))
rhashtable_remove_fast(&head->ht, &f->ht_node,
head->ht_params);
- list_del_rcu(&f->list);
- fl_hw_destroy_filter(tp, (unsigned long)f);
- tcf_unbind_filter(tp, &f->res);
- call_rcu(&f->rcu, fl_destroy_filter);
+ __fl_delete(tp, f);
return 0;
}
@@ -830,6 +948,42 @@ static int fl_dump_key_vlan(struct sk_buff *skb,
return 0;
}
+static void fl_get_key_flag(u32 dissector_key, u32 dissector_mask,
+ u32 *flower_key, u32 *flower_mask,
+ u32 flower_flag_bit, u32 dissector_flag_bit)
+{
+ if (dissector_mask & dissector_flag_bit) {
+ *flower_mask |= flower_flag_bit;
+ if (dissector_key & dissector_flag_bit)
+ *flower_key |= flower_flag_bit;
+ }
+}
+
+static int fl_dump_key_flags(struct sk_buff *skb, u32 flags_key, u32 flags_mask)
+{
+ u32 key, mask;
+ __be32 _key, _mask;
+ int err;
+
+ if (!memchr_inv(&flags_mask, 0, sizeof(flags_mask)))
+ return 0;
+
+ key = 0;
+ mask = 0;
+
+ fl_get_key_flag(flags_key, flags_mask, &key, &mask,
+ TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_IS_FRAGMENT);
+
+ _key = cpu_to_be32(key);
+ _mask = cpu_to_be32(mask);
+
+ err = nla_put(skb, TCA_FLOWER_KEY_FLAGS, 4, &_key);
+ if (err)
+ return err;
+
+ return nla_put(skb, TCA_FLOWER_KEY_FLAGS_MASK, 4, &_mask);
+}
+
static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
struct sk_buff *skb, struct tcmsg *t)
{
@@ -862,7 +1016,8 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
goto nla_put_failure;
}
- fl_hw_update_stats(tp, f);
+ if (!tc_skip_hw(f->flags))
+ fl_hw_update_stats(tp, f);
if (fl_dump_key_val(skb, key->eth.dst, TCA_FLOWER_KEY_ETH_DST,
mask->eth.dst, TCA_FLOWER_KEY_ETH_DST_MASK,
@@ -918,6 +1073,36 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
&mask->tp.dst, TCA_FLOWER_KEY_UDP_DST_MASK,
sizeof(key->tp.dst))))
goto nla_put_failure;
+ else if (key->basic.ip_proto == IPPROTO_SCTP &&
+ (fl_dump_key_val(skb, &key->tp.src, TCA_FLOWER_KEY_SCTP_SRC,
+ &mask->tp.src, TCA_FLOWER_KEY_SCTP_SRC_MASK,
+ sizeof(key->tp.src)) ||
+ fl_dump_key_val(skb, &key->tp.dst, TCA_FLOWER_KEY_SCTP_DST,
+ &mask->tp.dst, TCA_FLOWER_KEY_SCTP_DST_MASK,
+ sizeof(key->tp.dst))))
+ goto nla_put_failure;
+ else if (key->basic.n_proto == htons(ETH_P_IP) &&
+ key->basic.ip_proto == IPPROTO_ICMP &&
+ (fl_dump_key_val(skb, &key->icmp.type,
+ TCA_FLOWER_KEY_ICMPV4_TYPE, &mask->icmp.type,
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,
+ sizeof(key->icmp.type)) ||
+ fl_dump_key_val(skb, &key->icmp.code,
+ TCA_FLOWER_KEY_ICMPV4_CODE, &mask->icmp.code,
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+ sizeof(key->icmp.code))))
+ goto nla_put_failure;
+ else if (key->basic.n_proto == htons(ETH_P_IPV6) &&
+ key->basic.ip_proto == IPPROTO_ICMPV6 &&
+ (fl_dump_key_val(skb, &key->icmp.type,
+ TCA_FLOWER_KEY_ICMPV6_TYPE, &mask->icmp.type,
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
+ sizeof(key->icmp.type)) ||
+ fl_dump_key_val(skb, &key->icmp.code,
+ TCA_FLOWER_KEY_ICMPV6_CODE, &mask->icmp.code,
+ TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
+ sizeof(key->icmp.code))))
+ goto nla_put_failure;
if (key->enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
(fl_dump_key_val(skb, &key->enc_ipv4.src,
@@ -943,7 +1128,20 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
if (fl_dump_key_val(skb, &key->enc_key_id, TCA_FLOWER_KEY_ENC_KEY_ID,
&mask->enc_key_id, TCA_FLOWER_UNSPEC,
- sizeof(key->enc_key_id)))
+ sizeof(key->enc_key_id)) ||
+ fl_dump_key_val(skb, &key->enc_tp.src,
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT,
+ &mask->enc_tp.src,
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,
+ sizeof(key->enc_tp.src)) ||
+ fl_dump_key_val(skb, &key->enc_tp.dst,
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT,
+ &mask->enc_tp.dst,
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,
+ sizeof(key->enc_tp.dst)))
+ goto nla_put_failure;
+
+ if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags))
goto nla_put_failure;
nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags);
diff --git a/net/sched/em_ipset.c b/net/sched/em_ipset.c
index c66ca9400ab4..c1b23e3060b8 100644
--- a/net/sched/em_ipset.c
+++ b/net/sched/em_ipset.c
@@ -57,17 +57,20 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
struct xt_action_param acpar;
const struct xt_set_info *set = (const void *) em->data;
struct net_device *dev, *indev = NULL;
+ struct nf_hook_state state = {
+ .net = em->net,
+ };
int ret, network_offset;
switch (tc_skb_protocol(skb)) {
case htons(ETH_P_IP):
- acpar.family = NFPROTO_IPV4;
+ state.pf = NFPROTO_IPV4;
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
return 0;
acpar.thoff = ip_hdrlen(skb);
break;
case htons(ETH_P_IPV6):
- acpar.family = NFPROTO_IPV6;
+ state.pf = NFPROTO_IPV6;
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
return 0;
/* doesn't call ipv6_find_hdr() because ipset doesn't use thoff, yet */
@@ -77,9 +80,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
return 0;
}
- acpar.hooknum = 0;
-
- opt.family = acpar.family;
+ opt.family = state.pf;
opt.dim = set->dim;
opt.flags = set->flags;
opt.cmdflags = 0;
@@ -95,9 +96,9 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
if (skb->skb_iif)
indev = dev_get_by_index_rcu(em->net, skb->skb_iif);
- acpar.net = em->net;
- acpar.in = indev ? indev : dev;
- acpar.out = dev;
+ state.in = indev ? indev : dev;
+ state.out = dev;
+ acpar.state = &state;
ret = ip_set_test(set->index, skb, &acpar, &opt);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index a309a07ccb35..41c80b6c3906 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -176,11 +176,12 @@ META_COLLECTOR(int_vlan_tag)
{
unsigned short tag;
- tag = skb_vlan_tag_get(skb);
- if (!tag && __vlan_get_tag(skb, &tag))
- *err = -1;
- else
+ if (skb_vlan_tag_present(skb))
+ dst->value = skb_vlan_tag_get(skb);
+ else if (!__vlan_get_tag(skb, &tag))
dst->value = tag;
+ else
+ *err = -1;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 206dc24add3a..d7b93429f0cc 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -960,6 +960,17 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
sch->handle = handle;
+ /* This exist to keep backward compatible with a userspace
+ * loophole, what allowed userspace to get IFF_NO_QUEUE
+ * facility on older kernels by setting tx_queue_len=0 (prior
+ * to qdisc init), and then forgot to reinit tx_queue_len
+ * before again attaching a qdisc.
+ */
+ if ((dev->priv_flags & IFF_NO_QUEUE) && (dev->tx_queue_len == 0)) {
+ dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
+ netdev_info(dev, "Caught tx_queue_len zero misconfig\n");
+ }
+
if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
if (qdisc_is_percpu_stats(sch)) {
sch->cpu_bstats =
@@ -1384,7 +1395,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(q),
&d, cpu_bstats, &q->bstats) < 0 ||
- gnet_stats_copy_rate_est(&d, &q->bstats, &q->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
gnet_stats_copy_queue(&d, cpu_qstats, &q->qstats, qlen) < 0)
goto nla_put_failure;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index beb554aa8cfb..9ffe1c220b02 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -122,7 +122,7 @@ struct cbq_class {
psched_time_t penalized;
struct gnet_stats_basic_packed bstats;
struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
struct tc_cbq_xstats xstats;
struct tcf_proto __rcu *filter_list;
@@ -1346,7 +1346,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
d, NULL, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->q->q.qlen) < 0)
return -1;
@@ -1405,7 +1405,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
tcf_destroy_chain(&cl->filter_list);
qdisc_destroy(cl->q);
qdisc_put_rtab(cl->R_tab);
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
if (cl != &q->link)
kfree(cl);
}
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 8af5c59eef84..bb4cbdf75004 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -25,7 +25,7 @@ struct drr_class {
struct gnet_stats_basic_packed bstats;
struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
struct list_head alist;
struct Qdisc *qdisc;
@@ -142,7 +142,7 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
static void drr_destroy_class(struct Qdisc *sch, struct drr_class *cl)
{
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
qdisc_destroy(cl->qdisc);
kfree(cl);
}
@@ -283,7 +283,7 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
d, NULL, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
gnet_stats_copy_queue(d, NULL, &cl->qdisc->qstats, qlen) < 0)
return -1;
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 18e752439f6f..86309a3156a5 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -245,7 +245,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
skb_orphan(skb);
}
- root = &q->fq_root[hash_32((u32)(long)sk, q->fq_trees_log)];
+ root = &q->fq_root[hash_ptr(sk, q->fq_trees_log)];
if (q->flows >= (2U << q->fq_trees_log) &&
q->inactive_flows > q->flows/2)
@@ -599,7 +599,7 @@ static void fq_rehash(struct fq_sched_data *q,
kmem_cache_free(fq_flow_cachep, of);
continue;
}
- nroot = &new_array[hash_32((u32)(long)of->sk, new_log)];
+ nroot = &new_array[hash_ptr(of->sk, new_log)];
np = &nroot->rb_node;
parent = NULL;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 6cfb6e9038c2..6eb9c8e88519 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -709,7 +709,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
qdisc_put_stab(rtnl_dereference(qdisc->stab));
#endif
- gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
+ gen_kill_estimator(&qdisc->rate_est);
if (ops->reset)
ops->reset(qdisc);
if (ops->destroy)
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 000f1d36128e..3ffaa6fb0990 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -114,7 +114,7 @@ struct hfsc_class {
struct gnet_stats_basic_packed bstats;
struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
struct tcf_proto __rcu *filter_list; /* filter list */
unsigned int filter_cnt; /* filter count */
unsigned int level; /* class level in hierarchy */
@@ -1091,7 +1091,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
tcf_destroy_chain(&cl->filter_list);
qdisc_destroy(cl->qdisc);
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
if (cl != &q->root)
kfree(cl);
}
@@ -1348,7 +1348,7 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
xstats.rtwork = cl->cl_cumul;
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), d, NULL, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->qdisc->q.qlen) < 0)
return -1;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index c798d0de8a9d..760f39e7caee 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -111,7 +111,7 @@ struct htb_class {
unsigned int children;
struct htb_class *parent; /* parent class */
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
/*
* Written often fields
@@ -1145,7 +1145,7 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
d, NULL, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
gnet_stats_copy_queue(d, NULL, &qs, qlen) < 0)
return -1;
@@ -1228,7 +1228,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
WARN_ON(!cl->un.leaf.q);
qdisc_destroy(cl->un.leaf.q);
}
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
tcf_destroy_chain(&cl->filter_list);
kfree(cl);
}
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index ca0516e6f743..f9e712ce2d15 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -137,7 +137,7 @@ struct qfq_class {
struct gnet_stats_basic_packed bstats;
struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est64 rate_est;
+ struct net_rate_estimator __rcu *rate_est;
struct Qdisc *qdisc;
struct list_head alist; /* Link for active-classes list. */
struct qfq_aggregate *agg; /* Parent aggregate. */
@@ -508,7 +508,7 @@ set_change_agg:
new_agg = kzalloc(sizeof(*new_agg), GFP_KERNEL);
if (new_agg == NULL) {
err = -ENOBUFS;
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
goto destroy_class;
}
sch_tree_lock(sch);
@@ -533,7 +533,7 @@ static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
struct qfq_sched *q = qdisc_priv(sch);
qfq_rm_from_agg(q, cl);
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ gen_kill_estimator(&cl->rate_est);
qdisc_destroy(cl->qdisc);
kfree(cl);
}
@@ -667,7 +667,7 @@ static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
d, NULL, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
gnet_stats_copy_queue(d, NULL,
&cl->qdisc->qstats, cl->qdisc->q.qlen) < 0)
return -1;
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 2cd9b4478b92..b0196366d58d 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -418,9 +418,6 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu)
struct teql_master *m = netdev_priv(dev);
struct Qdisc *q;
- if (new_mtu < 68)
- return -EINVAL;
-
q = m->slaves;
if (q) {
do {
@@ -460,6 +457,8 @@ static __init void teql_master_setup(struct net_device *dev)
dev->netdev_ops = &teql_netdev_ops;
dev->type = ARPHRD_VOID;
dev->mtu = 1500;
+ dev->min_mtu = 68;
+ dev->max_mtu = 65535;
dev->tx_queue_len = 100;
dev->flags = IFF_NOARP;
dev->hard_header_len = LL_MAX_HEADER;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index f10d3397f917..68428e1f7181 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -700,11 +700,15 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Set the peer's active state. */
peer->state = peer_state;
+ /* Add this peer into the transport hashtable */
+ if (sctp_hash_transport(peer)) {
+ sctp_transport_free(peer);
+ return NULL;
+ }
+
/* Attach the remote transport to our asoc. */
list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
asoc->peer.transport_count++;
- /* Add this peer into the transport hashtable */
- sctp_hash_transport(peer);
/* If we do not yet have a primary path, set one. */
if (!asoc->peer.primary_path) {
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 7a1cdf43e49d..615f0ddd41df 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -52,7 +52,6 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg)
atomic_set(&msg->refcnt, 1);
msg->send_failed = 0;
msg->send_error = 0;
- msg->can_abandon = 0;
msg->can_delay = 1;
msg->expires_at = 0;
INIT_LIST_HEAD(&msg->chunks);
@@ -182,20 +181,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* Note: Calculate this outside of the loop, so that all fragments
* have the same expiration.
*/
- if (sinfo->sinfo_timetolive) {
- /* sinfo_timetolive is in milliseconds */
+ if (asoc->peer.prsctp_capable && sinfo->sinfo_timetolive &&
+ (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags) ||
+ !SCTP_PR_POLICY(sinfo->sinfo_flags)))
msg->expires_at = jiffies +
msecs_to_jiffies(sinfo->sinfo_timetolive);
- msg->can_abandon = 1;
-
- pr_debug("%s: msg:%p expires_at:%ld jiffies:%ld\n", __func__,
- msg, msg->expires_at, jiffies);
- }
-
- if (asoc->peer.prsctp_capable &&
- SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
- msg->expires_at =
- jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
/* This is the biggest possible DATA chunk that can fit into
* the packet
@@ -354,18 +344,8 @@ errout:
/* Check whether this message has expired. */
int sctp_chunk_abandoned(struct sctp_chunk *chunk)
{
- if (!chunk->asoc->peer.prsctp_capable ||
- !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) {
- struct sctp_datamsg *msg = chunk->msg;
-
- if (!msg->can_abandon)
- return 0;
-
- if (time_after(jiffies, msg->expires_at))
- return 1;
-
+ if (!chunk->asoc->peer.prsctp_capable)
return 0;
- }
if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
time_after(jiffies, chunk->msg->expires_at)) {
@@ -378,6 +358,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
return 1;
+ } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
+ chunk->msg->expires_at &&
+ time_after(jiffies, chunk->msg->expires_at)) {
+ return 1;
}
/* PRIO policy is processed by sendmsg, not here */
diff --git a/net/sctp/input.c b/net/sctp/input.c
index a01a56ec8b8c..458e506ef84b 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -790,10 +790,9 @@ hit:
/* rhashtable for transport */
struct sctp_hash_cmp_arg {
- const struct sctp_endpoint *ep;
- const union sctp_addr *laddr;
- const union sctp_addr *paddr;
- const struct net *net;
+ const union sctp_addr *paddr;
+ const struct net *net;
+ u16 lport;
};
static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
@@ -801,7 +800,6 @@ static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
{
struct sctp_transport *t = (struct sctp_transport *)ptr;
const struct sctp_hash_cmp_arg *x = arg->key;
- struct sctp_association *asoc;
int err = 1;
if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
@@ -809,19 +807,10 @@ static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
if (!sctp_transport_hold(t))
return err;
- asoc = t->asoc;
- if (!net_eq(sock_net(asoc->base.sk), x->net))
+ if (!net_eq(sock_net(t->asoc->base.sk), x->net))
+ goto out;
+ if (x->lport != htons(t->asoc->base.bind_addr.port))
goto out;
- if (x->ep) {
- if (x->ep != asoc->ep)
- goto out;
- } else {
- if (x->laddr->v4.sin_port != htons(asoc->base.bind_addr.port))
- goto out;
- if (!sctp_bind_addr_match(&asoc->base.bind_addr,
- x->laddr, sctp_sk(asoc->base.sk)))
- goto out;
- }
err = 0;
out:
@@ -851,11 +840,9 @@ static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed)
const struct sctp_hash_cmp_arg *x = data;
const union sctp_addr *paddr = x->paddr;
const struct net *net = x->net;
- u16 lport;
+ u16 lport = x->lport;
u32 addr;
- lport = x->ep ? htons(x->ep->base.bind_addr.port) :
- x->laddr->v4.sin_port;
if (paddr->sa.sa_family == AF_INET6)
addr = jhash(&paddr->v6.sin6_addr, 16, seed);
else
@@ -875,29 +862,32 @@ static const struct rhashtable_params sctp_hash_params = {
int sctp_transport_hashtable_init(void)
{
- return rhashtable_init(&sctp_transport_hashtable, &sctp_hash_params);
+ return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params);
}
void sctp_transport_hashtable_destroy(void)
{
- rhashtable_destroy(&sctp_transport_hashtable);
+ rhltable_destroy(&sctp_transport_hashtable);
}
-void sctp_hash_transport(struct sctp_transport *t)
+int sctp_hash_transport(struct sctp_transport *t)
{
struct sctp_hash_cmp_arg arg;
+ int err;
if (t->asoc->temp)
- return;
+ return 0;
- arg.ep = t->asoc->ep;
- arg.paddr = &t->ipaddr;
arg.net = sock_net(t->asoc->base.sk);
+ arg.paddr = &t->ipaddr;
+ arg.lport = htons(t->asoc->base.bind_addr.port);
-reinsert:
- if (rhashtable_lookup_insert_key(&sctp_transport_hashtable, &arg,
- &t->node, sctp_hash_params) == -EBUSY)
- goto reinsert;
+ err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
+ &t->node, sctp_hash_params);
+ if (err)
+ pr_err_once("insert transport fail, errno %d\n", err);
+
+ return err;
}
void sctp_unhash_transport(struct sctp_transport *t)
@@ -905,39 +895,62 @@ void sctp_unhash_transport(struct sctp_transport *t)
if (t->asoc->temp)
return;
- rhashtable_remove_fast(&sctp_transport_hashtable, &t->node,
- sctp_hash_params);
+ rhltable_remove(&sctp_transport_hashtable, &t->node,
+ sctp_hash_params);
}
+/* return a transport with holding it */
struct sctp_transport *sctp_addrs_lookup_transport(
struct net *net,
const union sctp_addr *laddr,
const union sctp_addr *paddr)
{
+ struct rhlist_head *tmp, *list;
+ struct sctp_transport *t;
struct sctp_hash_cmp_arg arg = {
- .ep = NULL,
- .laddr = laddr,
.paddr = paddr,
.net = net,
+ .lport = laddr->v4.sin_port,
};
- return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg,
- sctp_hash_params);
+ list = rhltable_lookup(&sctp_transport_hashtable, &arg,
+ sctp_hash_params);
+
+ rhl_for_each_entry_rcu(t, tmp, list, node) {
+ if (!sctp_transport_hold(t))
+ continue;
+
+ if (sctp_bind_addr_match(&t->asoc->base.bind_addr,
+ laddr, sctp_sk(t->asoc->base.sk)))
+ return t;
+ sctp_transport_put(t);
+ }
+
+ return NULL;
}
+/* return a transport without holding it, as it's only used under sock lock */
struct sctp_transport *sctp_epaddr_lookup_transport(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr)
{
struct net *net = sock_net(ep->base.sk);
+ struct rhlist_head *tmp, *list;
+ struct sctp_transport *t;
struct sctp_hash_cmp_arg arg = {
- .ep = ep,
.paddr = paddr,
.net = net,
+ .lport = htons(ep->base.bind_addr.port),
};
- return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg,
- sctp_hash_params);
+ list = rhltable_lookup(&sctp_transport_hashtable, &arg,
+ sctp_hash_params);
+
+ rhl_for_each_entry_rcu(t, tmp, list, node)
+ if (ep == t->asoc->ep)
+ return t;
+
+ return NULL;
}
/* Look up an association. */
@@ -951,7 +964,7 @@ static struct sctp_association *__sctp_lookup_association(
struct sctp_association *asoc = NULL;
t = sctp_addrs_lookup_transport(net, local, peer);
- if (!t || !sctp_transport_hold(t))
+ if (!t)
goto out;
asoc = t->asoc;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 6cb0df859195..f5320a87341e 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -399,186 +399,72 @@ static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
atomic_inc(&sk->sk_wmem_alloc);
}
-/* All packets are sent to the network through this function from
- * sctp_outq_tail().
- *
- * The return value is a normal kernel error return value.
- */
-int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
+static int sctp_packet_pack(struct sctp_packet *packet,
+ struct sk_buff *head, int gso, gfp_t gfp)
{
struct sctp_transport *tp = packet->transport;
- struct sctp_association *asoc = tp->asoc;
- struct sctphdr *sh;
- struct sk_buff *nskb = NULL, *head = NULL;
+ struct sctp_auth_chunk *auth = NULL;
struct sctp_chunk *chunk, *tmp;
- struct sock *sk;
- int err = 0;
- int padding; /* How much padding do we need? */
- int pkt_size;
- __u8 has_data = 0;
- int gso = 0;
- int pktcount = 0;
+ int pkt_count = 0, pkt_size;
+ struct sock *sk = head->sk;
+ struct sk_buff *nskb;
int auth_len = 0;
- struct dst_entry *dst;
- unsigned char *auth = NULL; /* pointer to auth in skb data */
-
- pr_debug("%s: packet:%p\n", __func__, packet);
-
- /* Do NOT generate a chunkless packet. */
- if (list_empty(&packet->chunk_list))
- return err;
-
- /* Set up convenience variables... */
- chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
- sk = chunk->skb->sk;
- /* Allocate the head skb, or main one if not in GSO */
- if (packet->size > tp->pathmtu && !packet->ipfragok) {
- if (sk_can_gso(sk)) {
- gso = 1;
- pkt_size = packet->overhead;
- } else {
- /* If this happens, we trash this packet and try
- * to build a new one, hopefully correct this
- * time. Application may notice this error.
- */
- pr_err_once("Trying to GSO but underlying device doesn't support it.");
- goto err;
- }
- } else {
- pkt_size = packet->size;
- }
- head = alloc_skb(pkt_size + MAX_HEADER, gfp);
- if (!head)
- goto err;
if (gso) {
- NAPI_GRO_CB(head)->last = head;
skb_shinfo(head)->gso_type = sk->sk_gso_type;
+ NAPI_GRO_CB(head)->last = head;
+ } else {
+ nskb = head;
+ pkt_size = packet->size;
+ goto merge;
}
- /* Make sure the outbound skb has enough header room reserved. */
- skb_reserve(head, packet->overhead + MAX_HEADER);
-
- /* Set the owning socket so that we know where to get the
- * destination IP address.
- */
- sctp_packet_set_owner_w(head, sk);
-
- if (!sctp_transport_dst_check(tp)) {
- sctp_transport_route(tp, NULL, sctp_sk(sk));
- if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
- sctp_assoc_sync_pmtu(sk, asoc);
- }
- }
- dst = dst_clone(tp->dst);
- if (!dst) {
- if (asoc)
- IP_INC_STATS(sock_net(asoc->base.sk),
- IPSTATS_MIB_OUTNOROUTES);
- goto nodst;
- }
- skb_dst_set(head, dst);
-
- /* Build the SCTP header. */
- sh = (struct sctphdr *)skb_push(head, sizeof(struct sctphdr));
- skb_reset_transport_header(head);
- sh->source = htons(packet->source_port);
- sh->dest = htons(packet->destination_port);
-
- /* From 6.8 Adler-32 Checksum Calculation:
- * After the packet is constructed (containing the SCTP common
- * header and one or more control or DATA chunks), the
- * transmitter shall:
- *
- * 1) Fill in the proper Verification Tag in the SCTP common
- * header and initialize the checksum field to 0's.
- */
- sh->vtag = htonl(packet->vtag);
- sh->checksum = 0;
-
- pr_debug("***sctp_transmit_packet***\n");
-
do {
- /* Set up convenience variables... */
- chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
- pktcount++;
-
- /* Calculate packet size, so it fits in PMTU. Leave
- * other chunks for the next packets.
- */
- if (gso) {
- pkt_size = packet->overhead;
- list_for_each_entry(chunk, &packet->chunk_list, list) {
- int padded = SCTP_PAD4(chunk->skb->len);
-
- if (chunk == packet->auth)
- auth_len = padded;
- else if (auth_len + padded + packet->overhead >
- tp->pathmtu)
- goto nomem;
- else if (pkt_size + padded > tp->pathmtu)
- break;
- pkt_size += padded;
- }
+ /* calculate the pkt_size and alloc nskb */
+ pkt_size = packet->overhead;
+ list_for_each_entry_safe(chunk, tmp, &packet->chunk_list,
+ list) {
+ int padded = SCTP_PAD4(chunk->skb->len);
- /* Allocate a new skb. */
- nskb = alloc_skb(pkt_size + MAX_HEADER, gfp);
- if (!nskb)
- goto nomem;
-
- /* Make sure the outbound skb has enough header
- * room reserved.
- */
- skb_reserve(nskb, packet->overhead + MAX_HEADER);
- } else {
- nskb = head;
+ if (chunk == packet->auth)
+ auth_len = padded;
+ else if (auth_len + padded + packet->overhead >
+ tp->pathmtu)
+ return 0;
+ else if (pkt_size + padded > tp->pathmtu)
+ break;
+ pkt_size += padded;
}
+ nskb = alloc_skb(pkt_size + MAX_HEADER, gfp);
+ if (!nskb)
+ return 0;
+ skb_reserve(nskb, packet->overhead + MAX_HEADER);
- /**
- * 3.2 Chunk Field Descriptions
- *
- * The total length of a chunk (including Type, Length and
- * Value fields) MUST be a multiple of 4 bytes. If the length
- * of the chunk is not a multiple of 4 bytes, the sender MUST
- * pad the chunk with all zero bytes and this padding is not
- * included in the chunk length field. The sender should
- * never pad with more than 3 bytes.
- *
- * [This whole comment explains SCTP_PAD4() below.]
- */
-
+merge:
+ /* merge chunks into nskb and append nskb into head list */
pkt_size -= packet->overhead;
list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+ int padding;
+
list_del_init(&chunk->list);
if (sctp_chunk_is_data(chunk)) {
- /* 6.3.1 C4) When data is in flight and when allowed
- * by rule C5, a new RTT measurement MUST be made each
- * round trip. Furthermore, new RTT measurements
- * SHOULD be made no more than once per round-trip
- * for a given destination transport address.
- */
-
- if (!chunk->resent && !tp->rto_pending) {
+ if (!sctp_chunk_retransmitted(chunk) &&
+ !tp->rto_pending) {
chunk->rtt_in_progress = 1;
tp->rto_pending = 1;
}
-
- has_data = 1;
}
padding = SCTP_PAD4(chunk->skb->len) - chunk->skb->len;
if (padding)
memset(skb_put(chunk->skb, padding), 0, padding);
- /* if this is the auth chunk that we are adding,
- * store pointer where it will be added and put
- * the auth into the packet.
- */
if (chunk == packet->auth)
- auth = skb_tail_pointer(nskb);
+ auth = (struct sctp_auth_chunk *)
+ skb_tail_pointer(nskb);
- memcpy(skb_put(nskb, chunk->skb->len),
- chunk->skb->data, chunk->skb->len);
+ memcpy(skb_put(nskb, chunk->skb->len), chunk->skb->data,
+ chunk->skb->len);
pr_debug("*** Chunk:%p[%s] %s 0x%x, length:%d, chunk->skb->len:%d, rtt_in_progress:%d\n",
chunk,
@@ -588,11 +474,6 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
ntohs(chunk->chunk_hdr->length), chunk->skb->len,
chunk->rtt_in_progress);
- /* If this is a control chunk, this is our last
- * reference. Free data chunks after they've been
- * acknowledged or have failed.
- * Re-queue auth chunks if needed.
- */
pkt_size -= SCTP_PAD4(chunk->skb->len);
if (!sctp_chunk_is_data(chunk) && chunk != packet->auth)
@@ -602,160 +483,161 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
break;
}
- /* SCTP-AUTH, Section 6.2
- * The sender MUST calculate the MAC as described in RFC2104 [2]
- * using the hash function H as described by the MAC Identifier and
- * the shared association key K based on the endpoint pair shared key
- * described by the shared key identifier. The 'data' used for the
- * computation of the AUTH-chunk is given by the AUTH chunk with its
- * HMAC field set to zero (as shown in Figure 6) followed by all
- * chunks that are placed after the AUTH chunk in the SCTP packet.
- */
- if (auth)
- sctp_auth_calculate_hmac(asoc, nskb,
- (struct sctp_auth_chunk *)auth,
- gfp);
-
- if (packet->auth) {
- if (!list_empty(&packet->chunk_list)) {
- /* We will generate more packets, so re-queue
- * auth chunk.
- */
+ if (auth) {
+ sctp_auth_calculate_hmac(tp->asoc, nskb, auth, gfp);
+ /* free auth if no more chunks, or add it back */
+ if (list_empty(&packet->chunk_list))
+ sctp_chunk_free(packet->auth);
+ else
list_add(&packet->auth->list,
&packet->chunk_list);
- } else {
- sctp_chunk_free(packet->auth);
- packet->auth = NULL;
- }
}
- if (!gso)
- break;
-
- if (skb_gro_receive(&head, nskb)) {
- kfree_skb(nskb);
- goto nomem;
+ if (gso) {
+ if (skb_gro_receive(&head, nskb)) {
+ kfree_skb(nskb);
+ return 0;
+ }
+ if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >=
+ sk->sk_gso_max_segs))
+ return 0;
}
- nskb = NULL;
- if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >=
- sk->sk_gso_max_segs))
- goto nomem;
+
+ pkt_count++;
} while (!list_empty(&packet->chunk_list));
- /* 2) Calculate the Adler-32 checksum of the whole packet,
- * including the SCTP common header and all the
- * chunks.
- *
- * Note: Adler-32 is no longer applicable, as has been replaced
- * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
- *
- * If it's a GSO packet, it's postponed to sctp_skb_segment.
- */
- if (!sctp_checksum_disable || gso) {
- if (!gso && (!(dst->dev->features & NETIF_F_SCTP_CRC) ||
- dst_xfrm(dst) || packet->ipfragok)) {
- sh->checksum = sctp_compute_cksum(head, 0);
- } else {
- /* no need to seed pseudo checksum for SCTP */
- head->ip_summed = CHECKSUM_PARTIAL;
- head->csum_start = skb_transport_header(head) - head->head;
- head->csum_offset = offsetof(struct sctphdr, checksum);
+ if (gso) {
+ memset(head->cb, 0, max(sizeof(struct inet_skb_parm),
+ sizeof(struct inet6_skb_parm)));
+ skb_shinfo(head)->gso_segs = pkt_count;
+ skb_shinfo(head)->gso_size = GSO_BY_FRAGS;
+ rcu_read_lock();
+ if (skb_dst(head) != tp->dst) {
+ dst_hold(tp->dst);
+ sk_setup_caps(sk, tp->dst);
}
+ rcu_read_unlock();
+ goto chksum;
}
- /* IP layer ECN support
- * From RFC 2481
- * "The ECN-Capable Transport (ECT) bit would be set by the
- * data sender to indicate that the end-points of the
- * transport protocol are ECN-capable."
- *
- * Now setting the ECT bit all the time, as it should not cause
- * any problems protocol-wise even if our peer ignores it.
- *
- * Note: The works for IPv6 layer checks this bit too later
- * in transmission. See IP6_ECN_flow_xmit().
- */
- tp->af_specific->ecn_capable(sk);
+ if (sctp_checksum_disable)
+ return 1;
- /* Set up the IP options. */
- /* BUG: not implemented
- * For v4 this all lives somewhere in sk->sk_opt...
- */
+ if (!(skb_dst(head)->dev->features & NETIF_F_SCTP_CRC) ||
+ dst_xfrm(skb_dst(head)) || packet->ipfragok) {
+ struct sctphdr *sh =
+ (struct sctphdr *)skb_transport_header(head);
- /* Dump that on IP! */
- if (asoc) {
- asoc->stats.opackets += pktcount;
- if (asoc->peer.last_sent_to != tp)
- /* Considering the multiple CPU scenario, this is a
- * "correcter" place for last_sent_to. --xguo
- */
- asoc->peer.last_sent_to = tp;
+ sh->checksum = sctp_compute_cksum(head, 0);
+ } else {
+chksum:
+ head->ip_summed = CHECKSUM_PARTIAL;
+ head->csum_start = skb_transport_header(head) - head->head;
+ head->csum_offset = offsetof(struct sctphdr, checksum);
}
- if (has_data) {
- struct timer_list *timer;
- unsigned long timeout;
+ return pkt_count;
+}
+
+/* All packets are sent to the network through this function from
+ * sctp_outq_tail().
+ *
+ * The return value is always 0 for now.
+ */
+int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
+{
+ struct sctp_transport *tp = packet->transport;
+ struct sctp_association *asoc = tp->asoc;
+ struct sctp_chunk *chunk, *tmp;
+ int pkt_count, gso = 0;
+ struct dst_entry *dst;
+ struct sk_buff *head;
+ struct sctphdr *sh;
+ struct sock *sk;
- /* Restart the AUTOCLOSE timer when sending data. */
- if (sctp_state(asoc, ESTABLISHED) &&
- asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
- timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
- timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
+ pr_debug("%s: packet:%p\n", __func__, packet);
+ if (list_empty(&packet->chunk_list))
+ return 0;
+ chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
+ sk = chunk->skb->sk;
- if (!mod_timer(timer, jiffies + timeout))
- sctp_association_hold(asoc);
+ /* check gso */
+ if (packet->size > tp->pathmtu && !packet->ipfragok) {
+ if (!sk_can_gso(sk)) {
+ pr_err_once("Trying to GSO but underlying device doesn't support it.");
+ goto out;
}
+ gso = 1;
+ }
+
+ /* alloc head skb */
+ head = alloc_skb((gso ? packet->overhead : packet->size) +
+ MAX_HEADER, gfp);
+ if (!head)
+ goto out;
+ skb_reserve(head, packet->overhead + MAX_HEADER);
+ sctp_packet_set_owner_w(head, sk);
+
+ /* set sctp header */
+ sh = (struct sctphdr *)skb_push(head, sizeof(struct sctphdr));
+ skb_reset_transport_header(head);
+ sh->source = htons(packet->source_port);
+ sh->dest = htons(packet->destination_port);
+ sh->vtag = htonl(packet->vtag);
+ sh->checksum = 0;
+
+ /* update dst if in need */
+ if (!sctp_transport_dst_check(tp)) {
+ sctp_transport_route(tp, NULL, sctp_sk(sk));
+ if (asoc && asoc->param_flags & SPP_PMTUD_ENABLE)
+ sctp_assoc_sync_pmtu(sk, asoc);
}
+ dst = dst_clone(tp->dst);
+ if (!dst) {
+ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+ kfree_skb(head);
+ goto out;
+ }
+ skb_dst_set(head, dst);
+ /* pack up chunks */
+ pkt_count = sctp_packet_pack(packet, head, gso, gfp);
+ if (!pkt_count) {
+ kfree_skb(head);
+ goto out;
+ }
pr_debug("***sctp_transmit_packet*** skb->len:%d\n", head->len);
- if (gso) {
- /* Cleanup our debris for IP stacks */
- memset(head->cb, 0, max(sizeof(struct inet_skb_parm),
- sizeof(struct inet6_skb_parm)));
+ /* start autoclose timer */
+ if (packet->has_data && sctp_state(asoc, ESTABLISHED) &&
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
+ struct timer_list *timer =
+ &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
+ unsigned long timeout =
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
- skb_shinfo(head)->gso_segs = pktcount;
- skb_shinfo(head)->gso_size = GSO_BY_FRAGS;
+ if (!mod_timer(timer, jiffies + timeout))
+ sctp_association_hold(asoc);
+ }
- /* We have to refresh this in case we are xmiting to
- * more than one transport at a time
- */
- rcu_read_lock();
- if (__sk_dst_get(sk) != tp->dst) {
- dst_hold(tp->dst);
- sk_setup_caps(sk, tp->dst);
- }
- rcu_read_unlock();
+ /* sctp xmit */
+ tp->af_specific->ecn_capable(sk);
+ if (asoc) {
+ asoc->stats.opackets += pkt_count;
+ if (asoc->peer.last_sent_to != tp)
+ asoc->peer.last_sent_to = tp;
}
head->ignore_df = packet->ipfragok;
tp->af_specific->sctp_xmit(head, tp);
- goto out;
-
-nomem:
- if (packet->auth && list_empty(&packet->auth->list))
- sctp_chunk_free(packet->auth);
-
-nodst:
- /* FIXME: Returning the 'err' will effect all the associations
- * associated with a socket, although only one of the paths of the
- * association is unreachable.
- * The real failure of a transport or association can be passed on
- * to the user via notifications. So setting this error may not be
- * required.
- */
- /* err = -EHOSTUNREACH; */
- kfree_skb(head);
-err:
+out:
list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
list_del_init(&chunk->list);
if (!sctp_chunk_is_data(chunk))
sctp_chunk_free(chunk);
}
-
-out:
sctp_packet_reset(packet);
- return err;
+ return 0;
}
/********************************************************************
@@ -871,9 +753,6 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
rwnd = 0;
asoc->peer.rwnd = rwnd;
- /* Has been accepted for transmission. */
- if (!asoc->peer.prsctp_capable)
- chunk->msg->can_abandon = 0;
sctp_chunk_assign_tsn(chunk);
sctp_chunk_assign_ssn(chunk);
}
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 582585393d35..e54082699520 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -507,8 +507,6 @@ void sctp_retransmit_mark(struct sctp_outq *q,
transport->rto_pending = 0;
}
- chunk->resent = 1;
-
/* Move the chunk to the retransmit queue. The chunks
* on the retransmit queue are always kept in order.
*/
@@ -1439,7 +1437,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* instance).
*/
if (!tchunk->tsn_gap_acked &&
- !tchunk->resent &&
+ !sctp_chunk_retransmitted(tchunk) &&
tchunk->rtt_in_progress) {
tchunk->rtt_in_progress = 0;
rtt = jiffies - tchunk->sent_at;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index f23ad913dc7a..d5f4b4a8369b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4392,10 +4392,7 @@ int sctp_transport_walk_start(struct rhashtable_iter *iter)
{
int err;
- err = rhashtable_walk_init(&sctp_transport_hashtable, iter,
- GFP_KERNEL);
- if (err)
- return err;
+ rhltable_walk_enter(&sctp_transport_hashtable, iter);
err = rhashtable_walk_start(iter);
if (err && err != -EAGAIN) {
@@ -4479,7 +4476,7 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
rcu_read_lock();
transport = sctp_addrs_lookup_transport(net, laddr, paddr);
- if (!transport || !sctp_transport_hold(transport))
+ if (!transport)
goto out;
rcu_read_unlock();
diff --git a/net/socket.c b/net/socket.c
index 73dc69f9681e..dc01d7be2fda 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -533,8 +533,22 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
return used;
}
+int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ int err = simple_setattr(dentry, iattr);
+
+ if (!err) {
+ struct socket *sock = SOCKET_I(d_inode(dentry));
+
+ sock->sk->sk_uid = iattr->ia_uid;
+ }
+
+ return err;
+}
+
static const struct inode_operations sockfs_inode_ops = {
.listxattr = sockfs_listxattr,
+ .setattr = sockfs_setattr,
};
/**
@@ -679,9 +693,14 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
empty = 0;
- if (!empty)
+ if (!empty) {
put_cmsg(msg, SOL_SOCKET,
SCM_TIMESTAMPING, sizeof(tss), &tss);
+
+ if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
+ put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
+ skb->len, skb->data);
+ }
}
EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
@@ -892,6 +911,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
* what to do with it - that's up to the protocol still.
*/
+static struct ns_common *get_net_ns(struct ns_common *ns)
+{
+ return &get_net(container_of(ns, struct net, ns))->ns;
+}
+
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct socket *sock;
@@ -960,6 +984,13 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = dlci_ioctl_hook(cmd, argp);
mutex_unlock(&dlci_ioctl_mutex);
break;
+ case SIOCGSKNS:
+ err = -EPERM;
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ break;
+
+ err = open_related_ns(&net->ns, get_net_ns);
+ break;
default:
err = sock_do_ioctl(net, sock, cmd, arg);
break;
@@ -1887,7 +1918,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
struct sockaddr_storage address;
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20]
- __attribute__ ((aligned(sizeof(__kernel_size_t))));
+ __aligned(sizeof(__kernel_size_t));
/* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl;
int ctl_len;
@@ -3110,6 +3141,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCSIFVLAN:
case SIOCADDDLCI:
case SIOCDELDLCI:
+ case SIOCGSKNS:
return sock_ioctl(file, cmd, arg);
case SIOCGIFFLAGS:
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index df5826876535..394ce523174c 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -34,7 +34,7 @@ struct sunrpc_net {
struct proc_dir_entry *use_gssp_proc;
};
-extern int sunrpc_net_id;
+extern unsigned int sunrpc_net_id;
int ip_map_cache_create(struct net *);
void ip_map_cache_destroy(struct net *);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index ee5d3d253102..d1c330a7953a 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -24,7 +24,7 @@
#include "netns.h"
-int sunrpc_net_id;
+unsigned int sunrpc_net_id;
EXPORT_SYMBOL_GPL(sunrpc_net_id);
static __net_init int sunrpc_init_net(struct net *net)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a4bc98265d88..135ec2c11b3b 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -39,6 +39,7 @@
#include <net/checksum.h>
#include <net/ip.h>
#include <net/ipv6.h>
+#include <net/udp.h>
#include <net/tcp.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
@@ -129,6 +130,18 @@ static void svc_release_skb(struct svc_rqst *rqstp)
}
}
+static void svc_release_udp_skb(struct svc_rqst *rqstp)
+{
+ struct sk_buff *skb = rqstp->rq_xprt_ctxt;
+
+ if (skb) {
+ rqstp->rq_xprt_ctxt = NULL;
+
+ dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
+ consume_skb(skb);
+ }
+}
+
union svc_pktinfo_u {
struct in_pktinfo pkti;
struct in6_pktinfo pkti6;
@@ -549,7 +562,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
0, 0, MSG_PEEK | MSG_DONTWAIT);
if (err >= 0)
- skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err);
+ skb = skb_recv_udp(svsk->sk_sk, 0, 1, &err);
if (skb == NULL) {
if (err != -EAGAIN) {
@@ -590,7 +603,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
goto out_free;
}
local_bh_enable();
- skb_free_datagram_locked(svsk->sk_sk, skb);
+ consume_skb(skb);
} else {
/* we can use it in-place */
rqstp->rq_arg.head[0].iov_base = skb->data;
@@ -617,8 +630,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
return len;
out_free:
- trace_kfree_skb(skb, svc_udp_recvfrom);
- skb_free_datagram_locked(svsk->sk_sk, skb);
+ kfree_skb(skb);
return 0;
}
@@ -679,7 +691,7 @@ static struct svc_xprt_ops svc_udp_ops = {
.xpo_create = svc_udp_create,
.xpo_recvfrom = svc_udp_recvfrom,
.xpo_sendto = svc_udp_sendto,
- .xpo_release_rqst = svc_release_skb,
+ .xpo_release_rqst = svc_release_udp_skb,
.xpo_detach = svc_sock_detach,
.xpo_free = svc_sock_free,
.xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index e01c825bc683..af392d9b9cec 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1080,10 +1080,10 @@ static void xs_udp_data_receive(struct sock_xprt *transport)
if (sk == NULL)
goto out;
for (;;) {
- skb = skb_recv_datagram(sk, 0, 1, &err);
+ skb = skb_recv_udp(sk, 0, 1, &err);
if (skb != NULL) {
xs_udp_data_read_skb(&transport->xprt, sk, skb);
- skb_free_datagram_locked(sk, skb);
+ consume_skb(skb);
continue;
}
if (!test_and_clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state))
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 3b95fe980fa2..017801f9dbaa 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -624,13 +624,10 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
struct switchdev_notifier_info *info)
{
- int err;
-
ASSERT_RTNL();
info->dev = dev;
- err = raw_notifier_call_chain(&switchdev_notif_chain, val, info);
- return err;
+ return raw_notifier_call_chain(&switchdev_notif_chain, val, info);
}
EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 236b043a4156..0b982d048fb9 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -47,7 +47,7 @@
#include <linux/module.h>
/* configurable TIPC parameters */
-int tipc_net_id __read_mostly;
+unsigned int tipc_net_id __read_mostly;
int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */
static int __net_init tipc_init_net(struct net *net)
diff --git a/net/tipc/core.h b/net/tipc/core.h
index a1845fb27d80..5cc5398be722 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -74,7 +74,7 @@ struct tipc_monitor;
#define MAX_BEARERS 3
#define TIPC_DEF_MON_THRESHOLD 32
-extern int tipc_net_id __read_mostly;
+extern unsigned int tipc_net_id __read_mostly;
extern int sysctl_tipc_rmem[3] __read_mostly;
extern int sysctl_tipc_named_timeout __read_mostly;
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 50a739860d37..8d408612ffa4 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -95,7 +95,7 @@ struct plist;
#define TIPC_MEDIA_INFO_OFFSET 5
struct tipc_skb_cb {
- void *handle;
+ u32 bytes_read;
struct sk_buff *tail;
bool validated;
bool wakeup_pending;
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 3200059d14b2..26ca8dd64ded 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -135,15 +135,6 @@ const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
/* Users of the legacy API (tipc-config) can't handle that we add operations,
* so we have a separate genl handling for the new API.
*/
-struct genl_family tipc_genl_family = {
- .id = GENL_ID_GENERATE,
- .name = TIPC_GENL_V2_NAME,
- .version = TIPC_GENL_V2_VERSION,
- .hdrsize = 0,
- .maxattr = TIPC_NLA_MAX,
- .netnsok = true,
-};
-
static const struct genl_ops tipc_genl_v2_ops[] = {
{
.cmd = TIPC_NL_BEARER_DISABLE,
@@ -258,23 +249,33 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
#endif
};
+struct genl_family tipc_genl_family __ro_after_init = {
+ .name = TIPC_GENL_V2_NAME,
+ .version = TIPC_GENL_V2_VERSION,
+ .hdrsize = 0,
+ .maxattr = TIPC_NLA_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = tipc_genl_v2_ops,
+ .n_ops = ARRAY_SIZE(tipc_genl_v2_ops),
+};
+
int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
{
u32 maxattr = tipc_genl_family.maxattr;
- *attr = tipc_genl_family.attrbuf;
+ *attr = genl_family_attrbuf(&tipc_genl_family);
if (!*attr)
return -EOPNOTSUPP;
return nlmsg_parse(nlh, GENL_HDRLEN, *attr, maxattr, tipc_nl_policy);
}
-int tipc_netlink_start(void)
+int __init tipc_netlink_start(void)
{
int res;
- res = genl_register_family_with_ops(&tipc_genl_family,
- tipc_genl_v2_ops);
+ res = genl_register_family(&tipc_genl_family);
if (res) {
pr_err("Failed to register netlink interface\n");
return res;
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 1fd464764765..e1ae8a8a2b8e 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -1215,15 +1215,6 @@ send:
return err;
}
-static struct genl_family tipc_genl_compat_family = {
- .id = GENL_ID_GENERATE,
- .name = TIPC_GENL_NAME,
- .version = TIPC_GENL_VERSION,
- .hdrsize = TIPC_GENL_HDRLEN,
- .maxattr = 0,
- .netnsok = true,
-};
-
static struct genl_ops tipc_genl_compat_ops[] = {
{
.cmd = TIPC_GENL_CMD,
@@ -1231,12 +1222,22 @@ static struct genl_ops tipc_genl_compat_ops[] = {
},
};
-int tipc_netlink_compat_start(void)
+static struct genl_family tipc_genl_compat_family __ro_after_init = {
+ .name = TIPC_GENL_NAME,
+ .version = TIPC_GENL_VERSION,
+ .hdrsize = TIPC_GENL_HDRLEN,
+ .maxattr = 0,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = tipc_genl_compat_ops,
+ .n_ops = ARRAY_SIZE(tipc_genl_compat_ops),
+};
+
+int __init tipc_netlink_compat_start(void)
{
int res;
- res = genl_register_family_with_ops(&tipc_genl_compat_family,
- tipc_genl_compat_ops);
+ res = genl_register_family(&tipc_genl_compat_family);
if (res) {
pr_err("Failed to register legacy compat interface\n");
return res;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 41f013888f07..333c5dae0072 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -44,44 +44,43 @@
#include "bcast.h"
#include "netlink.h"
-#define SS_LISTENING -1 /* socket is listening */
-#define SS_READY -2 /* socket is connectionless */
-
#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */
#define TIPC_FWD_MSG 1
-#define TIPC_CONN_OK 0
-#define TIPC_CONN_PROBING 1
#define TIPC_MAX_PORT 0xffffffff
#define TIPC_MIN_PORT 1
+enum {
+ TIPC_LISTEN = TCP_LISTEN,
+ TIPC_ESTABLISHED = TCP_ESTABLISHED,
+ TIPC_OPEN = TCP_CLOSE,
+ TIPC_DISCONNECTING = TCP_CLOSE_WAIT,
+ TIPC_CONNECTING = TCP_SYN_SENT,
+};
+
/**
* struct tipc_sock - TIPC socket structure
* @sk: socket - interacts with 'port' and with user via the socket API
- * @connected: non-zero if port is currently connected to a peer port
* @conn_type: TIPC type used when connection was established
* @conn_instance: TIPC instance used when connection was established
* @published: non-zero if port has one or more associated names
* @max_pkt: maximum packet size "hint" used when building messages sent by port
* @portid: unique port identity in TIPC socket hash table
* @phdr: preformatted message header used when sending messages
- * @port_list: adjacent ports in TIPC's global list of ports
* @publications: list of publications for port
* @pub_count: total # of publications port has made during its lifetime
* @probing_state:
- * @probing_intv:
* @conn_timeout: the time we can wait for an unresponded setup request
* @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
* @link_cong: non-zero if owner must sleep because of link congestion
* @sent_unacked: # messages sent by socket, and not yet acked by peer
* @rcv_unacked: # messages read by user, but not yet acked back to peer
- * @remote: 'connected' peer for dgram/rdm
+ * @peer: 'connected' peer for dgram/rdm
* @node: hash table node
* @rcu: rcu struct for tipc_sock
*/
struct tipc_sock {
struct sock sk;
- int connected;
u32 conn_type;
u32 conn_instance;
int published;
@@ -91,17 +90,16 @@ struct tipc_sock {
struct list_head sock_list;
struct list_head publications;
u32 pub_count;
- u32 probing_state;
- unsigned long probing_intv;
uint conn_timeout;
atomic_t dupl_rcvcnt;
+ bool probe_unacked;
bool link_cong;
u16 snt_unacked;
u16 snd_win;
u16 peer_caps;
u16 rcv_unacked;
u16 rcv_win;
- struct sockaddr_tipc remote;
+ struct sockaddr_tipc peer;
struct rhash_head node;
struct rcu_head rcu;
};
@@ -248,6 +246,21 @@ static void tsk_rej_rx_queue(struct sock *sk)
tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
}
+static bool tipc_sk_connected(struct sock *sk)
+{
+ return sk->sk_state == TIPC_ESTABLISHED;
+}
+
+/* tipc_sk_type_connectionless - check if the socket is datagram socket
+ * @sk: socket
+ *
+ * Returns true if connection less, false otherwise
+ */
+static bool tipc_sk_type_connectionless(struct sock *sk)
+{
+ return sk->sk_type == SOCK_RDM || sk->sk_type == SOCK_DGRAM;
+}
+
/* tsk_peer_msg - verify if message was sent by connected port's peer
*
* Handles cases where the node's network address has changed from
@@ -255,12 +268,13 @@ static void tsk_rej_rx_queue(struct sock *sk)
*/
static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
{
- struct tipc_net *tn = net_generic(sock_net(&tsk->sk), tipc_net_id);
+ struct sock *sk = &tsk->sk;
+ struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
u32 peer_port = tsk_peer_port(tsk);
u32 orig_node;
u32 peer_node;
- if (unlikely(!tsk->connected))
+ if (unlikely(!tipc_sk_connected(sk)))
return false;
if (unlikely(msg_origport(msg) != peer_port))
@@ -281,6 +295,45 @@ static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
return false;
}
+/* tipc_set_sk_state - set the sk_state of the socket
+ * @sk: socket
+ *
+ * Caller must hold socket lock
+ *
+ * Returns 0 on success, errno otherwise
+ */
+static int tipc_set_sk_state(struct sock *sk, int state)
+{
+ int oldsk_state = sk->sk_state;
+ int res = -EINVAL;
+
+ switch (state) {
+ case TIPC_OPEN:
+ res = 0;
+ break;
+ case TIPC_LISTEN:
+ case TIPC_CONNECTING:
+ if (oldsk_state == TIPC_OPEN)
+ res = 0;
+ break;
+ case TIPC_ESTABLISHED:
+ if (oldsk_state == TIPC_CONNECTING ||
+ oldsk_state == TIPC_OPEN)
+ res = 0;
+ break;
+ case TIPC_DISCONNECTING:
+ if (oldsk_state == TIPC_CONNECTING ||
+ oldsk_state == TIPC_ESTABLISHED)
+ res = 0;
+ break;
+ }
+
+ if (!res)
+ sk->sk_state = state;
+
+ return res;
+}
+
/**
* tipc_sk_create - create a TIPC socket
* @net: network namespace (must be default network)
@@ -298,7 +351,6 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
{
struct tipc_net *tn;
const struct proto_ops *ops;
- socket_state state;
struct sock *sk;
struct tipc_sock *tsk;
struct tipc_msg *msg;
@@ -310,16 +362,13 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
switch (sock->type) {
case SOCK_STREAM:
ops = &stream_ops;
- state = SS_UNCONNECTED;
break;
case SOCK_SEQPACKET:
ops = &packet_ops;
- state = SS_UNCONNECTED;
break;
case SOCK_DGRAM:
case SOCK_RDM:
ops = &msg_ops;
- state = SS_READY;
break;
default:
return -EPROTOTYPE;
@@ -340,14 +389,15 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
/* Finish initializing socket data structures */
sock->ops = ops;
- sock->state = state;
sock_init_data(sock, sk);
+ tipc_set_sk_state(sk, TIPC_OPEN);
if (tipc_sk_insert(tsk)) {
pr_warn("Socket create failed; port number exhausted\n");
return -EINVAL;
}
msg_set_origport(msg, tsk->portid);
setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
+ sk->sk_shutdown = 0;
sk->sk_backlog_rcv = tipc_backlog_rcv;
sk->sk_rcvbuf = sysctl_tipc_rmem[1];
sk->sk_data_ready = tipc_data_ready;
@@ -360,11 +410,12 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
tsk->snd_win = tsk_adv_blocks(RCVBUF_MIN);
tsk->rcv_win = tsk->snd_win;
- if (sock->state == SS_READY) {
+ if (tipc_sk_type_connectionless(sk)) {
tsk_set_unreturnable(tsk, true);
if (sock->type == SOCK_DGRAM)
tsk_set_unreliable(tsk, true);
}
+
return 0;
}
@@ -375,6 +426,44 @@ static void tipc_sk_callback(struct rcu_head *head)
sock_put(&tsk->sk);
}
+/* Caller should hold socket lock for the socket. */
+static void __tipc_shutdown(struct socket *sock, int error)
+{
+ struct sock *sk = sock->sk;
+ struct tipc_sock *tsk = tipc_sk(sk);
+ struct net *net = sock_net(sk);
+ u32 dnode = tsk_peer_node(tsk);
+ struct sk_buff *skb;
+
+ /* Reject all unreceived messages, except on an active connection
+ * (which disconnects locally & sends a 'FIN+' to peer).
+ */
+ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (TIPC_SKB_CB(skb)->bytes_read) {
+ kfree_skb(skb);
+ } else {
+ if (!tipc_sk_type_connectionless(sk) &&
+ sk->sk_state != TIPC_DISCONNECTING) {
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ tipc_node_remove_conn(net, dnode, tsk->portid);
+ }
+ tipc_sk_respond(sk, skb, error);
+ }
+ }
+ if (sk->sk_state != TIPC_DISCONNECTING) {
+ skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
+ TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
+ tsk_own_node(tsk), tsk_peer_port(tsk),
+ tsk->portid, error);
+ if (skb)
+ tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
+ if (!tipc_sk_type_connectionless(sk)) {
+ tipc_node_remove_conn(net, dnode, tsk->portid);
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ }
+ }
+}
+
/**
* tipc_release - destroy a TIPC socket
* @sock: socket to destroy
@@ -394,10 +483,7 @@ static void tipc_sk_callback(struct rcu_head *head)
static int tipc_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct net *net;
struct tipc_sock *tsk;
- struct sk_buff *skb;
- u32 dnode;
/*
* Exit if socket isn't fully initialized (occurs when a failed accept()
@@ -406,47 +492,16 @@ static int tipc_release(struct socket *sock)
if (sk == NULL)
return 0;
- net = sock_net(sk);
tsk = tipc_sk(sk);
lock_sock(sk);
- /*
- * Reject all unreceived messages, except on an active connection
- * (which disconnects locally & sends a 'FIN+' to peer)
- */
- dnode = tsk_peer_node(tsk);
- while (sock->state != SS_DISCONNECTING) {
- skb = __skb_dequeue(&sk->sk_receive_queue);
- if (skb == NULL)
- break;
- if (TIPC_SKB_CB(skb)->handle != NULL)
- kfree_skb(skb);
- else {
- if ((sock->state == SS_CONNECTING) ||
- (sock->state == SS_CONNECTED)) {
- sock->state = SS_DISCONNECTING;
- tsk->connected = 0;
- tipc_node_remove_conn(net, dnode, tsk->portid);
- }
- tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
- }
- }
-
+ __tipc_shutdown(sock, TIPC_ERR_NO_PORT);
+ sk->sk_shutdown = SHUTDOWN_MASK;
tipc_sk_withdraw(tsk, 0, NULL);
sk_stop_timer(sk, &sk->sk_timer);
tipc_sk_remove(tsk);
- if (tsk->connected) {
- skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
- TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
- tsk_own_node(tsk), tsk_peer_port(tsk),
- tsk->portid, TIPC_ERR_NO_PORT);
- if (skb)
- tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
- tipc_node_remove_conn(net, dnode, tsk->portid);
- }
/* Reject any messages that accumulated in backlog queue */
- sock->state = SS_DISCONNECTING;
release_sock(sk);
call_rcu(&tsk->rcu, tipc_sk_callback);
@@ -532,13 +587,14 @@ static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
- struct tipc_sock *tsk = tipc_sk(sock->sk);
+ struct sock *sk = sock->sk;
+ struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id);
memset(addr, 0, sizeof(*addr));
if (peer) {
- if ((sock->state != SS_CONNECTED) &&
- ((peer != 2) || (sock->state != SS_DISCONNECTING)))
+ if ((!tipc_sk_connected(sk)) &&
+ ((peer != 2) || (sk->sk_state != TIPC_DISCONNECTING)))
return -ENOTCONN;
addr->addr.id.ref = tsk_peer_port(tsk);
addr->addr.id.node = tsk_peer_node(tsk);
@@ -570,28 +626,6 @@ static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
* exits. TCP and other protocols seem to rely on higher level poll routines
* to handle any preventable race conditions, so TIPC will do the same ...
*
- * TIPC sets the returned events as follows:
- *
- * socket state flags set
- * ------------ ---------
- * unconnected no read flags
- * POLLOUT if port is not congested
- *
- * connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
- * no write flags
- *
- * connected POLLIN/POLLRDNORM if data in rx queue
- * POLLOUT if port is not congested
- *
- * disconnecting POLLIN/POLLRDNORM/POLLHUP
- * no write flags
- *
- * listening POLLIN if SYN in rx queue
- * no write flags
- *
- * ready POLLIN/POLLRDNORM if data in rx queue
- * [connectionless] POLLOUT (since port cannot be congested)
- *
* IMPORTANT: The fact that a read or write operation is indicated does NOT
* imply that the operation will succeed, merely that it should be performed
* and will not block.
@@ -605,22 +639,29 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
sock_poll_wait(file, sk_sleep(sk), wait);
- switch ((int)sock->state) {
- case SS_UNCONNECTED:
- if (!tsk->link_cong)
- mask |= POLLOUT;
- break;
- case SS_READY:
- case SS_CONNECTED:
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP | POLLIN | POLLRDNORM;
+ if (sk->sk_shutdown == SHUTDOWN_MASK)
+ mask |= POLLHUP;
+
+ switch (sk->sk_state) {
+ case TIPC_ESTABLISHED:
if (!tsk->link_cong && !tsk_conn_cong(tsk))
mask |= POLLOUT;
/* fall thru' */
- case SS_CONNECTING:
- case SS_LISTENING:
+ case TIPC_LISTEN:
+ case TIPC_CONNECTING:
if (!skb_queue_empty(&sk->sk_receive_queue))
mask |= (POLLIN | POLLRDNORM);
break;
- case SS_DISCONNECTING:
+ case TIPC_OPEN:
+ if (!tsk->link_cong)
+ mask |= POLLOUT;
+ if (tipc_sk_type_connectionless(sk) &&
+ (!skb_queue_empty(&sk->sk_receive_queue)))
+ mask |= (POLLIN | POLLRDNORM);
+ break;
+ case TIPC_DISCONNECTING:
mask = (POLLIN | POLLRDNORM | POLLHUP);
break;
}
@@ -651,6 +692,9 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
uint mtu;
int rc;
+ if (!timeo && tsk->link_cong)
+ return -ELINKCONG;
+
msg_set_type(mhdr, TIPC_MCAST_MSG);
msg_set_lookup_scope(mhdr, TIPC_CLUSTER_SCOPE);
msg_set_destport(mhdr, 0);
@@ -763,7 +807,7 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
if (!tsk_peer_msg(tsk, hdr))
goto exit;
- tsk->probing_state = TIPC_CONN_OK;
+ tsk->probe_unacked = false;
if (mtyp == CONN_PROBE) {
msg_set_type(hdr, CONN_PROBE_REPLY);
@@ -786,25 +830,25 @@ exit:
static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk);
- DEFINE_WAIT(wait);
int done;
do {
int err = sock_error(sk);
if (err)
return err;
- if (sock->state == SS_DISCONNECTING)
+ if (sk->sk_shutdown & SEND_SHUTDOWN)
return -EPIPE;
if (!*timeo_p)
return -EAGAIN;
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, timeo_p, !tsk->link_cong);
- finish_wait(sk_sleep(sk), &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
+ done = sk_wait_event(sk, timeo_p, !tsk->link_cong, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@ -844,6 +888,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
struct tipc_msg *mhdr = &tsk->phdr;
u32 dnode, dport;
struct sk_buff_head pktchain;
+ bool is_connectionless = tipc_sk_type_connectionless(sk);
struct sk_buff *skb;
struct tipc_name_seq *seq;
struct iov_iter save;
@@ -854,18 +899,18 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
if (dsz > TIPC_MAX_USER_MSG_SIZE)
return -EMSGSIZE;
if (unlikely(!dest)) {
- if (tsk->connected && sock->state == SS_READY)
- dest = &tsk->remote;
+ if (is_connectionless && tsk->peer.family == AF_TIPC)
+ dest = &tsk->peer;
else
return -EDESTADDRREQ;
} else if (unlikely(m->msg_namelen < sizeof(*dest)) ||
dest->family != AF_TIPC) {
return -EINVAL;
}
- if (unlikely(sock->state != SS_READY)) {
- if (sock->state == SS_LISTENING)
+ if (!is_connectionless) {
+ if (sk->sk_state == TIPC_LISTEN)
return -EPIPE;
- if (sock->state != SS_UNCONNECTED)
+ if (sk->sk_state != TIPC_OPEN)
return -EISCONN;
if (tsk->published)
return -EOPNOTSUPP;
@@ -917,8 +962,8 @@ new_mtu:
TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
if (likely(!rc)) {
- if (sock->state != SS_READY)
- sock->state = SS_CONNECTING;
+ if (!is_connectionless)
+ tipc_set_sk_state(sk, TIPC_CONNECTING);
return dsz;
}
if (rc == -ELINKCONG) {
@@ -940,30 +985,30 @@ new_mtu:
static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk);
- DEFINE_WAIT(wait);
int done;
do {
int err = sock_error(sk);
if (err)
return err;
- if (sock->state == SS_DISCONNECTING)
+ if (sk->sk_state == TIPC_DISCONNECTING)
return -EPIPE;
- else if (sock->state != SS_CONNECTED)
+ else if (!tipc_sk_connected(sk))
return -ENOTCONN;
if (!*timeo_p)
return -EAGAIN;
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
done = sk_wait_event(sk, timeo_p,
(!tsk->link_cong &&
!tsk_conn_cong(tsk)) ||
- !tsk->connected);
- finish_wait(sk_sleep(sk), &wait);
+ !tipc_sk_connected(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@ -1018,14 +1063,17 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
if (dsz > (uint)INT_MAX)
return -EMSGSIZE;
- if (unlikely(sock->state != SS_CONNECTED)) {
- if (sock->state == SS_DISCONNECTING)
+ if (unlikely(!tipc_sk_connected(sk))) {
+ if (sk->sk_state == TIPC_DISCONNECTING)
return -EPIPE;
else
return -ENOTCONN;
}
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
+ if (!timeo && tsk->link_cong)
+ return -ELINKCONG;
+
dnode = tsk_peer_node(tsk);
skb_queue_head_init(&pktchain);
@@ -1099,10 +1147,8 @@ static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port,
msg_set_lookup_scope(msg, 0);
msg_set_hdr_sz(msg, SHORT_H_SIZE);
- tsk->probing_intv = CONN_PROBING_INTERVAL;
- tsk->probing_state = TIPC_CONN_OK;
- tsk->connected = 1;
- sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
+ sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
+ tipc_set_sk_state(sk, TIPC_ESTABLISHED);
tipc_node_add_conn(net, peer_node, tsk->portid, peer_port);
tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid);
tsk->peer_caps = tipc_node_get_capabilities(net, peer_node);
@@ -1210,13 +1256,14 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
static void tipc_sk_send_ack(struct tipc_sock *tsk)
{
- struct net *net = sock_net(&tsk->sk);
+ struct sock *sk = &tsk->sk;
+ struct net *net = sock_net(sk);
struct sk_buff *skb = NULL;
struct tipc_msg *msg;
u32 peer_port = tsk_peer_port(tsk);
u32 dnode = tsk_peer_node(tsk);
- if (!tsk->connected)
+ if (!tipc_sk_connected(sk))
return;
skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0,
dnode, tsk_own_node(tsk), peer_port,
@@ -1245,7 +1292,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
for (;;) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
- if (sock->state == SS_DISCONNECTING) {
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
err = -ENOTCONN;
break;
}
@@ -1286,6 +1333,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, size_t buf_len,
struct tipc_sock *tsk = tipc_sk(sk);
struct sk_buff *buf;
struct tipc_msg *msg;
+ bool is_connectionless = tipc_sk_type_connectionless(sk);
long timeo;
unsigned int sz;
u32 err;
@@ -1297,7 +1345,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, size_t buf_len,
lock_sock(sk);
- if (unlikely(sock->state == SS_UNCONNECTED)) {
+ if (!is_connectionless && unlikely(sk->sk_state == TIPC_OPEN)) {
res = -ENOTCONN;
goto exit;
}
@@ -1342,8 +1390,8 @@ restart:
goto exit;
res = sz;
} else {
- if ((sock->state == SS_READY) ||
- ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
+ if (is_connectionless || err == TIPC_CONN_SHUTDOWN ||
+ m->msg_control)
res = 0;
else
res = -ECONNRESET;
@@ -1352,7 +1400,7 @@ restart:
if (unlikely(flags & MSG_PEEK))
goto exit;
- if (likely(sock->state != SS_READY)) {
+ if (likely(!is_connectionless)) {
tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
tipc_sk_send_ack(tsk);
@@ -1383,7 +1431,7 @@ static int tipc_recv_stream(struct socket *sock, struct msghdr *m,
struct tipc_msg *msg;
long timeo;
unsigned int sz;
- int sz_to_copy, target, needed;
+ int target;
int sz_copied = 0;
u32 err;
int res = 0, hlen;
@@ -1394,7 +1442,7 @@ static int tipc_recv_stream(struct socket *sock, struct msghdr *m,
lock_sock(sk);
- if (unlikely(sock->state == SS_UNCONNECTED)) {
+ if (unlikely(sk->sk_state == TIPC_OPEN)) {
res = -ENOTCONN;
goto exit;
}
@@ -1431,11 +1479,13 @@ restart:
/* Capture message data (if valid) & compute return value (always) */
if (!err) {
- u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
+ u32 offset = TIPC_SKB_CB(buf)->bytes_read;
+ u32 needed;
+ int sz_to_copy;
sz -= offset;
needed = (buf_len - sz_copied);
- sz_to_copy = (sz <= needed) ? sz : needed;
+ sz_to_copy = min(sz, needed);
res = skb_copy_datagram_msg(buf, hlen + offset, m, sz_to_copy);
if (res)
@@ -1445,8 +1495,8 @@ restart:
if (sz_to_copy < sz) {
if (!(flags & MSG_PEEK))
- TIPC_SKB_CB(buf)->handle =
- (void *)(unsigned long)(offset + sz_to_copy);
+ TIPC_SKB_CB(buf)->bytes_read =
+ offset + sz_to_copy;
goto exit;
}
} else {
@@ -1528,49 +1578,31 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
{
struct sock *sk = &tsk->sk;
struct net *net = sock_net(sk);
- struct socket *sock = sk->sk_socket;
struct tipc_msg *hdr = buf_msg(skb);
if (unlikely(msg_mcast(hdr)))
return false;
- switch ((int)sock->state) {
- case SS_CONNECTED:
-
- /* Accept only connection-based messages sent by peer */
- if (unlikely(!tsk_peer_msg(tsk, hdr)))
- return false;
-
- if (unlikely(msg_errcode(hdr))) {
- sock->state = SS_DISCONNECTING;
- tsk->connected = 0;
- /* Let timer expire on it's own */
- tipc_node_remove_conn(net, tsk_peer_node(tsk),
- tsk->portid);
- }
- return true;
-
- case SS_CONNECTING:
-
+ switch (sk->sk_state) {
+ case TIPC_CONNECTING:
/* Accept only ACK or NACK message */
if (unlikely(!msg_connected(hdr)))
return false;
if (unlikely(msg_errcode(hdr))) {
- sock->state = SS_DISCONNECTING;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = ECONNREFUSED;
return true;
}
if (unlikely(!msg_isdata(hdr))) {
- sock->state = SS_DISCONNECTING;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = EINVAL;
return true;
}
tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr));
msg_set_importance(&tsk->phdr, msg_importance(hdr));
- sock->state = SS_CONNECTED;
/* If 'ACK+' message, add to socket receive queue */
if (msg_data_sz(hdr))
@@ -1584,18 +1616,31 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
msg_set_dest_droppable(hdr, 1);
return false;
- case SS_LISTENING:
- case SS_UNCONNECTED:
-
+ case TIPC_OPEN:
+ case TIPC_DISCONNECTING:
+ break;
+ case TIPC_LISTEN:
/* Accept only SYN message */
if (!msg_connected(hdr) && !(msg_errcode(hdr)))
return true;
break;
- case SS_DISCONNECTING:
- break;
+ case TIPC_ESTABLISHED:
+ /* Accept only connection-based messages sent by peer */
+ if (unlikely(!tsk_peer_msg(tsk, hdr)))
+ return false;
+
+ if (unlikely(msg_errcode(hdr))) {
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ /* Let timer expire on it's own */
+ tipc_node_remove_conn(net, tsk_peer_node(tsk),
+ tsk->portid);
+ sk->sk_state_change(sk);
+ }
+ return true;
default:
- pr_err("Unknown socket state %u\n", sock->state);
+ pr_err("Unknown sk_state %u\n", sk->sk_state);
}
+
return false;
}
@@ -1646,7 +1691,6 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *skb)
static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
struct sk_buff_head *xmitq)
{
- struct socket *sock = sk->sk_socket;
struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_msg *hdr = buf_msg(skb);
unsigned int limit = rcvbuf_limit(sk, skb);
@@ -1672,7 +1716,7 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
}
/* Reject if wrong message type for current socket state */
- if (unlikely(sock->state == SS_READY)) {
+ if (tipc_sk_type_connectionless(sk)) {
if (msg_connected(hdr)) {
err = TIPC_ERR_NO_PORT;
goto reject;
@@ -1689,7 +1733,7 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
}
/* Enqueue message */
- TIPC_SKB_CB(skb)->handle = NULL;
+ TIPC_SKB_CB(skb)->bytes_read = 0;
__skb_queue_tail(&sk->sk_receive_queue, skb);
skb_set_owner_r(skb, sk);
@@ -1839,8 +1883,8 @@ xmit:
static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
- DEFINE_WAIT(wait);
int done;
do {
@@ -1852,9 +1896,10 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
- finish_wait(sk_sleep(sk), &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
+ done = sk_wait_event(sk, timeo_p,
+ sk->sk_state != TIPC_CONNECTING, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@ -1876,21 +1921,19 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
struct msghdr m = {NULL,};
long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
- socket_state previous;
+ int previous;
int res = 0;
lock_sock(sk);
/* DGRAM/RDM connect(), just save the destaddr */
- if (sock->state == SS_READY) {
+ if (tipc_sk_type_connectionless(sk)) {
if (dst->family == AF_UNSPEC) {
- memset(&tsk->remote, 0, sizeof(struct sockaddr_tipc));
- tsk->connected = 0;
+ memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc));
} else if (destlen != sizeof(struct sockaddr_tipc)) {
res = -EINVAL;
} else {
- memcpy(&tsk->remote, dest, destlen);
- tsk->connected = 1;
+ memcpy(&tsk->peer, dest, destlen);
}
goto exit;
}
@@ -1906,9 +1949,10 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
goto exit;
}
- previous = sock->state;
- switch (sock->state) {
- case SS_UNCONNECTED:
+ previous = sk->sk_state;
+
+ switch (sk->sk_state) {
+ case TIPC_OPEN:
/* Send a 'SYN-' to destination */
m.msg_name = dest;
m.msg_namelen = destlen;
@@ -1923,27 +1967,29 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
if ((res < 0) && (res != -EWOULDBLOCK))
goto exit;
- /* Just entered SS_CONNECTING state; the only
+ /* Just entered TIPC_CONNECTING state; the only
* difference is that return value in non-blocking
* case is EINPROGRESS, rather than EALREADY.
*/
res = -EINPROGRESS;
- case SS_CONNECTING:
- if (previous == SS_CONNECTING)
- res = -EALREADY;
- if (!timeout)
+ /* fall thru' */
+ case TIPC_CONNECTING:
+ if (!timeout) {
+ if (previous == TIPC_CONNECTING)
+ res = -EALREADY;
goto exit;
+ }
timeout = msecs_to_jiffies(timeout);
/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
res = tipc_wait_for_connect(sock, &timeout);
break;
- case SS_CONNECTED:
+ case TIPC_ESTABLISHED:
res = -EISCONN;
break;
default:
res = -EINVAL;
- break;
}
+
exit:
release_sock(sk);
return res;
@@ -1962,15 +2008,9 @@ static int tipc_listen(struct socket *sock, int len)
int res;
lock_sock(sk);
-
- if (sock->state != SS_UNCONNECTED)
- res = -EINVAL;
- else {
- sock->state = SS_LISTENING;
- res = 0;
- }
-
+ res = tipc_set_sk_state(sk, TIPC_LISTEN);
release_sock(sk);
+
return res;
}
@@ -1996,9 +2036,6 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)
err = 0;
if (!skb_queue_empty(&sk->sk_receive_queue))
break;
- err = -EINVAL;
- if (sock->state != SS_LISTENING)
- break;
err = -EAGAIN;
if (!timeo)
break;
@@ -2029,7 +2066,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
lock_sock(sk);
- if (sock->state != SS_LISTENING) {
+ if (sk->sk_state != TIPC_LISTEN) {
res = -EINVAL;
goto exit;
}
@@ -2040,7 +2077,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
buf = skb_peek(&sk->sk_receive_queue);
- res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
+ res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 0);
if (res)
goto exit;
security_sk_clone(sock->sk, new_sock->sk);
@@ -2060,7 +2097,6 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
/* Connect new socket to it's peer */
tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
- new_sock->state = SS_CONNECTED;
tsk_set_importance(new_tsock, msg_importance(msg));
if (msg_named(msg)) {
@@ -2100,13 +2136,6 @@ exit:
static int tipc_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
- struct net *net = sock_net(sk);
- struct tipc_sock *tsk = tipc_sk(sk);
- struct sk_buff *skb;
- u32 dnode = tsk_peer_node(tsk);
- u32 dport = tsk_peer_port(tsk);
- u32 onode = tipc_own_addr(net);
- u32 oport = tsk->portid;
int res;
if (how != SHUT_RDWR)
@@ -2114,45 +2143,17 @@ static int tipc_shutdown(struct socket *sock, int how)
lock_sock(sk);
- switch (sock->state) {
- case SS_CONNECTING:
- case SS_CONNECTED:
-
-restart:
- dnode = tsk_peer_node(tsk);
-
- /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
- skb = __skb_dequeue(&sk->sk_receive_queue);
- if (skb) {
- if (TIPC_SKB_CB(skb)->handle != NULL) {
- kfree_skb(skb);
- goto restart;
- }
- tipc_sk_respond(sk, skb, TIPC_CONN_SHUTDOWN);
- } else {
- skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
- TIPC_CONN_MSG, SHORT_H_SIZE,
- 0, dnode, onode, dport, oport,
- TIPC_CONN_SHUTDOWN);
- if (skb)
- tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
- }
- tsk->connected = 0;
- sock->state = SS_DISCONNECTING;
- tipc_node_remove_conn(net, dnode, tsk->portid);
- /* fall through */
-
- case SS_DISCONNECTING:
+ __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
+ sk->sk_shutdown = SEND_SHUTDOWN;
+ if (sk->sk_state == TIPC_DISCONNECTING) {
/* Discard any unreceived messages */
__skb_queue_purge(&sk->sk_receive_queue);
/* Wake up anyone sleeping in poll */
sk->sk_state_change(sk);
res = 0;
- break;
-
- default:
+ } else {
res = -ENOTCONN;
}
@@ -2169,17 +2170,16 @@ static void tipc_sk_timeout(unsigned long data)
u32 own_node = tsk_own_node(tsk);
bh_lock_sock(sk);
- if (!tsk->connected) {
+ if (!tipc_sk_connected(sk)) {
bh_unlock_sock(sk);
goto exit;
}
peer_port = tsk_peer_port(tsk);
peer_node = tsk_peer_node(tsk);
- if (tsk->probing_state == TIPC_CONN_PROBING) {
+ if (tsk->probe_unacked) {
if (!sock_owned_by_user(sk)) {
- sk->sk_socket->state = SS_DISCONNECTING;
- tsk->connected = 0;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
tsk_peer_port(tsk));
sk->sk_state_change(sk);
@@ -2188,13 +2188,15 @@ static void tipc_sk_timeout(unsigned long data)
sk_reset_timer(sk, &sk->sk_timer, (HZ / 20));
}
- } else {
- skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
- INT_H_SIZE, 0, peer_node, own_node,
- peer_port, tsk->portid, TIPC_OK);
- tsk->probing_state = TIPC_CONN_PROBING;
- sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
+ bh_unlock_sock(sk);
+ goto exit;
}
+
+ skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
+ INT_H_SIZE, 0, peer_node, own_node,
+ peer_port, tsk->portid, TIPC_OK);
+ tsk->probe_unacked = true;
+ sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
bh_unlock_sock(sk);
if (skb)
tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid);
@@ -2205,11 +2207,12 @@ exit:
static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
struct tipc_name_seq const *seq)
{
- struct net *net = sock_net(&tsk->sk);
+ struct sock *sk = &tsk->sk;
+ struct net *net = sock_net(sk);
struct publication *publ;
u32 key;
- if (tsk->connected)
+ if (tipc_sk_connected(sk))
return -EINVAL;
key = tsk->portid + tsk->pub_count + 1;
if (key == tsk->portid)
@@ -2667,6 +2670,7 @@ static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb,
struct nlattr *attrs;
struct net *net = sock_net(skb->sk);
struct tipc_net *tn = net_generic(net, tipc_net_id);
+ struct sock *sk = &tsk->sk;
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET);
@@ -2681,7 +2685,7 @@ static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb,
if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr))
goto attr_msg_cancel;
- if (tsk->connected) {
+ if (tipc_sk_connected(sk)) {
err = __tipc_nl_add_sk_con(skb, tsk);
if (err)
goto attr_msg_cancel;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2358f2690ec5..1752d6b10ac4 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2113,8 +2113,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
mutex_lock(&u->iolock);
skip = sk_peek_offset(sk, flags);
- skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err,
- &last);
+ skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip,
+ &err, &last);
if (skb)
break;
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
index 936d7eee62d0..2e47f9f06b96 100644
--- a/net/vmw_vsock/virtio_transport.c
+++ b/net/vmw_vsock/virtio_transport.c
@@ -44,6 +44,10 @@ struct virtio_vsock {
spinlock_t send_pkt_list_lock;
struct list_head send_pkt_list;
+ struct work_struct loopback_work;
+ spinlock_t loopback_list_lock; /* protects loopback_list */
+ struct list_head loopback_list;
+
atomic_t queued_replies;
/* The following fields are protected by rx_lock. vqs[VSOCK_VQ_RX]
@@ -74,6 +78,42 @@ static u32 virtio_transport_get_local_cid(void)
return vsock->guest_cid;
}
+static void virtio_transport_loopback_work(struct work_struct *work)
+{
+ struct virtio_vsock *vsock =
+ container_of(work, struct virtio_vsock, loopback_work);
+ LIST_HEAD(pkts);
+
+ spin_lock_bh(&vsock->loopback_list_lock);
+ list_splice_init(&vsock->loopback_list, &pkts);
+ spin_unlock_bh(&vsock->loopback_list_lock);
+
+ mutex_lock(&vsock->rx_lock);
+ while (!list_empty(&pkts)) {
+ struct virtio_vsock_pkt *pkt;
+
+ pkt = list_first_entry(&pkts, struct virtio_vsock_pkt, list);
+ list_del_init(&pkt->list);
+
+ virtio_transport_recv_pkt(pkt);
+ }
+ mutex_unlock(&vsock->rx_lock);
+}
+
+static int virtio_transport_send_pkt_loopback(struct virtio_vsock *vsock,
+ struct virtio_vsock_pkt *pkt)
+{
+ int len = pkt->len;
+
+ spin_lock_bh(&vsock->loopback_list_lock);
+ list_add_tail(&pkt->list, &vsock->loopback_list);
+ spin_unlock_bh(&vsock->loopback_list_lock);
+
+ queue_work(virtio_vsock_workqueue, &vsock->loopback_work);
+
+ return len;
+}
+
static void
virtio_transport_send_pkt_work(struct work_struct *work)
{
@@ -159,6 +199,9 @@ virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt)
return -ENODEV;
}
+ if (le32_to_cpu(pkt->hdr.dst_cid) == vsock->guest_cid)
+ return virtio_transport_send_pkt_loopback(vsock, pkt);
+
if (pkt->reply)
atomic_inc(&vsock->queued_replies);
@@ -510,10 +553,13 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
mutex_init(&vsock->event_lock);
spin_lock_init(&vsock->send_pkt_list_lock);
INIT_LIST_HEAD(&vsock->send_pkt_list);
+ spin_lock_init(&vsock->loopback_list_lock);
+ INIT_LIST_HEAD(&vsock->loopback_list);
INIT_WORK(&vsock->rx_work, virtio_transport_rx_work);
INIT_WORK(&vsock->tx_work, virtio_transport_tx_work);
INIT_WORK(&vsock->event_work, virtio_transport_event_work);
INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work);
+ INIT_WORK(&vsock->loopback_work, virtio_transport_loopback_work);
mutex_lock(&vsock->rx_lock);
virtio_vsock_rx_fill(vsock);
@@ -539,6 +585,7 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
struct virtio_vsock *vsock = vdev->priv;
struct virtio_vsock_pkt *pkt;
+ flush_work(&vsock->loopback_work);
flush_work(&vsock->rx_work);
flush_work(&vsock->tx_work);
flush_work(&vsock->event_work);
@@ -565,6 +612,15 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
}
spin_unlock_bh(&vsock->send_pkt_list_lock);
+ spin_lock_bh(&vsock->loopback_list_lock);
+ while (!list_empty(&vsock->loopback_list)) {
+ pkt = list_first_entry(&vsock->loopback_list,
+ struct virtio_vsock_pkt, list);
+ list_del(&pkt->list);
+ virtio_transport_free_pkt(pkt);
+ }
+ spin_unlock_bh(&vsock->loopback_list_lock);
+
mutex_lock(&the_virtio_vsock_mutex);
the_virtio_vsock = NULL;
vsock_core_exit();
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index a53b3a16b4f1..687e9fdb3d67 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -619,17 +619,17 @@ static int virtio_transport_reset_no_sock(struct virtio_vsock_pkt *pkt)
static void virtio_transport_wait_close(struct sock *sk, long timeout)
{
if (timeout) {
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+ add_wait_queue(sk_sleep(sk), &wait);
do {
- prepare_to_wait(sk_sleep(sk), &wait,
- TASK_INTERRUPTIBLE);
if (sk_wait_event(sk, &timeout,
- sock_flag(sk, SOCK_DONE)))
+ sock_flag(sk, SOCK_DONE), &wait))
break;
} while (!signal_pending(current) && timeout);
- finish_wait(sk_sleep(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
}
}
diff --git a/net/wimax/stack.c b/net/wimax/stack.c
index 3f816e2971ee..5db731512014 100644
--- a/net/wimax/stack.c
+++ b/net/wimax/stack.c
@@ -572,16 +572,20 @@ struct d_level D_LEVEL[] = {
size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
-struct genl_family wimax_gnl_family = {
- .id = GENL_ID_GENERATE,
+static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
+ { .name = "msg", },
+};
+
+struct genl_family wimax_gnl_family __ro_after_init = {
.name = "WiMAX",
.version = WIMAX_GNL_VERSION,
.hdrsize = 0,
.maxattr = WIMAX_GNL_ATTR_MAX,
-};
-
-static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
- { .name = "msg", },
+ .module = THIS_MODULE,
+ .ops = wimax_gnl_ops,
+ .n_ops = ARRAY_SIZE(wimax_gnl_ops),
+ .mcgrps = wimax_gnl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(wimax_gnl_mcgrps),
};
@@ -596,11 +600,7 @@ int __init wimax_subsys_init(void)
d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params,
"wimax.debug");
- snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
- "WiMAX");
- result = genl_register_family_with_ops_groups(&wimax_gnl_family,
- wimax_gnl_ops,
- wimax_gnl_mcgrps);
+ result = genl_register_family(&wimax_gnl_family);
if (unlikely(result < 0)) {
pr_err("cannot register generic netlink family: %d\n", result);
goto error_register_family;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d7449e..158c59ecf90a 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -210,11 +210,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return;
- if (!wdev->p2p_started)
+ if (!wdev_running(wdev))
return;
rdev_stop_p2p_device(rdev, wdev);
- wdev->p2p_started = false;
+ wdev->is_running = false;
rdev->opencount--;
@@ -233,11 +233,11 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
return;
- if (!wdev->nan_started)
+ if (!wdev_running(wdev))
return;
rdev_stop_nan(rdev, wdev);
- wdev->nan_started = false;
+ wdev->is_running = false;
rdev->opencount--;
}
@@ -562,6 +562,21 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
c->limits[j].max > 1))
return -EINVAL;
+ /*
+ * This isn't well-defined right now. If you have an
+ * IBSS interface, then its beacon interval may change
+ * by joining other networks, and nothing prevents it
+ * from doing that.
+ * So technically we probably shouldn't even allow AP
+ * and IBSS in the same interface, but it seems that
+ * some drivers support that, possibly only with fixed
+ * beacon intervals for IBSS.
+ */
+ if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
+ c->beacon_int_min_gcd)) {
+ return -EINVAL;
+ }
+
cnt += c->limits[j].max;
/*
* Don't advertise an unsupported type
@@ -571,6 +586,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
return -EINVAL;
}
+#ifndef CONFIG_WIRELESS_WDS
+ if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS)))
+ return -EINVAL;
+#endif
+
/* You can't even choose that many! */
if (WARN_ON(cnt < c->max_interfaces))
return -EINVAL;
@@ -609,6 +629,11 @@ int wiphy_register(struct wiphy *wiphy)
!rdev->ops->add_nan_func || !rdev->ops->del_nan_func)))
return -EINVAL;
+#ifndef CONFIG_WIRELESS_WDS
+ if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
+ return -EINVAL;
+#endif
+
/*
* if a wiphy has unsupported modes for regulatory channel enforcement,
* opt-out of enforcement checking
diff --git a/net/wireless/core.h b/net/wireless/core.h
index f0c0c8a48c92..af6e023020b1 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -346,7 +346,7 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx,
- const u8 *sae_data, int sae_data_len);
+ const u8 *auth_data, int auth_data_len);
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ieee80211_channel *chan,
@@ -410,6 +410,7 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev);
void cfg80211_sme_deauth(struct wireless_dev *wdev);
void cfg80211_sme_auth_timeout(struct wireless_dev *wdev);
void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev);
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
/* internal helpers */
bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
@@ -476,7 +477,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
u32 *mask);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int);
+ enum nl80211_iftype iftype, u32 beacon_int);
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num);
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index 71447cf86306..ba0a1f398ce5 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -556,7 +556,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
break;
- case 0:
+ default:
memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
break;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index fa2066b56f36..2d8518a37eab 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -183,6 +183,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
wdev->mesh_id_len = setup->mesh_id_len;
wdev->chandef = setup->chandef;
+ wdev->beacon_interval = setup->beacon_interval;
}
return err;
@@ -258,6 +259,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
err = rdev_leave_mesh(rdev, dev);
if (!err) {
wdev->mesh_id_len = 0;
+ wdev->beacon_interval = 0;
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
rdev_set_qos_map(rdev, dev, NULL);
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index cbb48e26a871..4646cf5695b9 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -149,6 +149,18 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
}
EXPORT_SYMBOL(cfg80211_assoc_timeout);
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+
+ cfg80211_sme_abandon_assoc(wdev);
+
+ cfg80211_unhold_bss(bss_from_pub(bss));
+ cfg80211_put_bss(wiphy, bss);
+}
+EXPORT_SYMBOL(cfg80211_abandon_assoc);
+
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -204,14 +216,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx,
- const u8 *sae_data, int sae_data_len)
+ const u8 *auth_data, int auth_data_len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_auth_request req = {
.ie = ie,
.ie_len = ie_len,
- .sae_data = sae_data,
- .sae_data_len = sae_data_len,
+ .auth_data = auth_data,
+ .auth_data_len = auth_data_len,
.auth_type = auth_type,
.key = key,
.key_len = key_len,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810f0b7c..3df85a751a85 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -32,22 +32,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
struct cfg80211_crypto_settings *settings,
int cipher_limit);
-static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-
/* the netlink family */
-static struct genl_family nl80211_fam = {
- .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
- .name = NL80211_GENL_NAME, /* have users key off the name instead */
- .hdrsize = 0, /* no private header */
- .version = 1, /* no particular meaning now */
- .maxattr = NL80211_ATTR_MAX,
- .netnsok = true,
- .pre_doit = nl80211_pre_doit,
- .post_doit = nl80211_post_doit,
-};
+static struct genl_family nl80211_fam;
/* multicast groups */
enum nl80211_multicast_groups {
@@ -357,7 +343,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
- [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+ [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
[NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
@@ -414,6 +400,11 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
[NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 },
[NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
+ [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
+ .len = FILS_MAX_KEK_LEN },
+ [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
+ [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
+ [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
};
/* policy for the key attributes */
@@ -435,6 +426,7 @@ nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
[NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
};
+#ifdef CONFIG_PM
/* policy for WoWLAN attributes */
static const struct nla_policy
nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
@@ -468,6 +460,7 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
};
+#endif /* CONFIG_PM */
/* policy for coalesce rule attributes */
static const struct nla_policy
@@ -551,13 +544,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
if (!cb->args[0]) {
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
+ genl_family_attrbuf(&nl80211_fam),
+ nl80211_fam.maxattr, nl80211_policy);
if (err)
goto out_unlock;
- *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
- nl80211_fam.attrbuf);
+ *wdev = __cfg80211_wdev_from_attrs(
+ sock_net(skb->sk),
+ genl_family_attrbuf(&nl80211_fam));
if (IS_ERR(*wdev)) {
err = PTR_ERR(*wdev);
goto out_unlock;
@@ -1075,6 +1069,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
c->radar_detect_regions)))
goto nla_put_failure;
+ if (c->beacon_int_min_gcd &&
+ nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
+ c->beacon_int_min_gcd))
+ goto nla_put_failure;
nla_nest_end(msg, nl_combi);
}
@@ -1322,6 +1320,95 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
return 0;
}
+#define CMD(op, n) \
+ do { \
+ if (rdev->ops->op) { \
+ i++; \
+ if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
+ goto nla_put_failure; \
+ } \
+ } while (0)
+
+static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
+ struct sk_buff *msg)
+{
+ int i = 0;
+
+ /*
+ * do *NOT* add anything into this function, new things need to be
+ * advertised only to new versions of userspace that can deal with
+ * the split (and they can't possibly care about new features...
+ */
+ CMD(add_virtual_intf, NEW_INTERFACE);
+ CMD(change_virtual_intf, SET_INTERFACE);
+ CMD(add_key, NEW_KEY);
+ CMD(start_ap, START_AP);
+ CMD(add_station, NEW_STATION);
+ CMD(add_mpath, NEW_MPATH);
+ CMD(update_mesh_config, SET_MESH_CONFIG);
+ CMD(change_bss, SET_BSS);
+ CMD(auth, AUTHENTICATE);
+ CMD(assoc, ASSOCIATE);
+ CMD(deauth, DEAUTHENTICATE);
+ CMD(disassoc, DISASSOCIATE);
+ CMD(join_ibss, JOIN_IBSS);
+ CMD(join_mesh, JOIN_MESH);
+ CMD(set_pmksa, SET_PMKSA);
+ CMD(del_pmksa, DEL_PMKSA);
+ CMD(flush_pmksa, FLUSH_PMKSA);
+ if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
+ CMD(remain_on_channel, REMAIN_ON_CHANNEL);
+ CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
+ CMD(mgmt_tx, FRAME);
+ CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
+ if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
+ i++;
+ if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
+ goto nla_put_failure;
+ }
+ if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
+ rdev->ops->join_mesh) {
+ i++;
+ if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
+ goto nla_put_failure;
+ }
+ CMD(set_wds_peer, SET_WDS_PEER);
+ if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+ CMD(tdls_mgmt, TDLS_MGMT);
+ CMD(tdls_oper, TDLS_OPER);
+ }
+ if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+ CMD(sched_scan_start, START_SCHED_SCAN);
+ CMD(probe_client, PROBE_CLIENT);
+ CMD(set_noack_map, SET_NOACK_MAP);
+ if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
+ i++;
+ if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
+ goto nla_put_failure;
+ }
+ CMD(start_p2p_device, START_P2P_DEVICE);
+ CMD(set_mcast_rate, SET_MCAST_RATE);
+#ifdef CONFIG_NL80211_TESTMODE
+ CMD(testmode_cmd, TESTMODE);
+#endif
+
+ if (rdev->ops->connect || rdev->ops->auth) {
+ i++;
+ if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
+ goto nla_put_failure;
+ }
+
+ if (rdev->ops->disconnect || rdev->ops->deauth) {
+ i++;
+ if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
+ goto nla_put_failure;
+ }
+
+ return i;
+ nla_put_failure:
+ return -ENOBUFS;
+}
+
struct nl80211_dump_wiphy_state {
s64 filter_wiphy;
long start;
@@ -1549,68 +1636,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
if (!nl_cmds)
goto nla_put_failure;
- i = 0;
-#define CMD(op, n) \
- do { \
- if (rdev->ops->op) { \
- i++; \
- if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
- goto nla_put_failure; \
- } \
- } while (0)
-
- CMD(add_virtual_intf, NEW_INTERFACE);
- CMD(change_virtual_intf, SET_INTERFACE);
- CMD(add_key, NEW_KEY);
- CMD(start_ap, START_AP);
- CMD(add_station, NEW_STATION);
- CMD(add_mpath, NEW_MPATH);
- CMD(update_mesh_config, SET_MESH_CONFIG);
- CMD(change_bss, SET_BSS);
- CMD(auth, AUTHENTICATE);
- CMD(assoc, ASSOCIATE);
- CMD(deauth, DEAUTHENTICATE);
- CMD(disassoc, DISASSOCIATE);
- CMD(join_ibss, JOIN_IBSS);
- CMD(join_mesh, JOIN_MESH);
- CMD(set_pmksa, SET_PMKSA);
- CMD(del_pmksa, DEL_PMKSA);
- CMD(flush_pmksa, FLUSH_PMKSA);
- if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
- CMD(remain_on_channel, REMAIN_ON_CHANNEL);
- CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
- CMD(mgmt_tx, FRAME);
- CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
- if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
- i++;
- if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
- goto nla_put_failure;
- }
- if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
- rdev->ops->join_mesh) {
- i++;
- if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
- goto nla_put_failure;
- }
- CMD(set_wds_peer, SET_WDS_PEER);
- if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
- CMD(tdls_mgmt, TDLS_MGMT);
- CMD(tdls_oper, TDLS_OPER);
- }
- if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
- CMD(sched_scan_start, START_SCHED_SCAN);
- CMD(probe_client, PROBE_CLIENT);
- CMD(set_noack_map, SET_NOACK_MAP);
- if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
- i++;
- if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
- goto nla_put_failure;
- }
- CMD(start_p2p_device, START_P2P_DEVICE);
- CMD(set_mcast_rate, SET_MCAST_RATE);
-#ifdef CONFIG_NL80211_TESTMODE
- CMD(testmode_cmd, TESTMODE);
-#endif
+ i = nl80211_add_commands_unsplit(rdev, msg);
+ if (i < 0)
+ goto nla_put_failure;
if (state->split) {
CMD(crit_proto_start, CRIT_PROTOCOL_START);
CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
@@ -1620,22 +1648,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
if (rdev->wiphy.features &
NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
CMD(add_tx_ts, ADD_TX_TS);
+ CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
+ CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
}
- /* add into the if now */
#undef CMD
- if (rdev->ops->connect || rdev->ops->auth) {
- i++;
- if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
- goto nla_put_failure;
- }
-
- if (rdev->ops->disconnect || rdev->ops->deauth) {
- i++;
- if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
- goto nla_put_failure;
- }
-
nla_nest_end(msg, nl_cmds);
state->split_start++;
if (state->split)
@@ -1881,7 +1898,7 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
struct netlink_callback *cb,
struct nl80211_dump_wiphy_state *state)
{
- struct nlattr **tb = nl80211_fam.attrbuf;
+ struct nlattr **tb = genl_family_attrbuf(&nl80211_fam);
int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
tb, nl80211_fam.maxattr, nl80211_policy);
/* ignore parse errors for backward compatibility */
@@ -2296,10 +2313,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
rem_txq_params) {
- result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
- nla_data(nl_txq_params),
- nla_len(nl_txq_params),
- txq_params_policy);
+ result = nla_parse_nested(tb, NL80211_TXQ_ATTR_MAX,
+ nl_txq_params,
+ txq_params_policy);
if (result)
return result;
result = parse_txq_params(tb, &txq_params);
@@ -3549,8 +3565,8 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
sband = rdev->wiphy.bands[band];
if (sband == NULL)
return -EINVAL;
- err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
- nla_len(tx_rates), nl80211_txattr_policy);
+ err = nla_parse_nested(tb, NL80211_TXRATE_MAX, tx_rates,
+ nl80211_txattr_policy);
if (err)
return err;
if (tb[NL80211_TXRATE_LEGACY]) {
@@ -3756,12 +3772,23 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
auth_type == NL80211_AUTHTYPE_SAE)
return false;
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_FILS_STA) &&
+ (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+ auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+ auth_type == NL80211_AUTHTYPE_FILS_PK))
+ return false;
return true;
case NL80211_CMD_CONNECT:
case NL80211_CMD_START_AP:
/* SAE not supported yet */
if (auth_type == NL80211_AUTHTYPE_SAE)
return false;
+ /* FILS not supported yet */
+ if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+ auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+ auth_type == NL80211_AUTHTYPE_FILS_PK)
+ return false;
return true;
default:
return false;
@@ -3803,7 +3830,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.dtim_period =
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
- err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
+ params.beacon_interval);
if (err)
return err;
@@ -6305,9 +6333,8 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
rem_reg_rules) {
- r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
- nla_data(nl_reg_rule), nla_len(nl_reg_rule),
- reg_rule_policy);
+ r = nla_parse_nested(tb, NL80211_REG_RULE_ATTR_MAX,
+ nl_reg_rule, reg_rule_policy);
if (r)
goto bad_reg;
r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
@@ -6374,8 +6401,8 @@ static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
if (!nla_ok(nest, nla_len(nest)))
return -EINVAL;
- err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest),
- nla_len(nest), nl80211_bss_select_policy);
+ err = nla_parse_nested(attr, NL80211_BSS_SELECT_ATTR_MAX, nest,
+ nl80211_bss_select_policy);
if (err)
return err;
@@ -6677,7 +6704,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
- if (info->attrs[NL80211_ATTR_MAC])
+ /* Initial implementation used NL80211_ATTR_MAC to set the specific
+ * BSSID to scan for. This was problematic because that same attribute
+ * was already used for another purpose (local random MAC address). The
+ * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
+ * compatibility with older userspace components, also use the
+ * NL80211_ATTR_MAC value here if it can be determined to be used for
+ * the specific BSSID use case instead of the random MAC address
+ * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
+ */
+ if (info->attrs[NL80211_ATTR_BSSID])
+ memcpy(request->bssid,
+ nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
+ else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
+ info->attrs[NL80211_ATTR_MAC])
memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
ETH_ALEN);
else
@@ -6765,9 +6805,8 @@ nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
if (WARN_ON(i >= n_plans))
return -EINVAL;
- err = nla_parse(plan, NL80211_SCHED_SCAN_PLAN_MAX,
- nla_data(attr), nla_len(attr),
- nl80211_plan_policy);
+ err = nla_parse_nested(plan, NL80211_SCHED_SCAN_PLAN_MAX,
+ attr, nl80211_plan_policy);
if (err)
return err;
@@ -6856,9 +6895,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
tmp) {
struct nlattr *rssi;
- err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
- nla_data(attr), nla_len(attr),
- nl80211_match_policy);
+ err = nla_parse_nested(tb,
+ NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+ attr, nl80211_match_policy);
if (err)
return ERR_PTR(err);
/* add other standalone attributes here */
@@ -7029,9 +7068,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
tmp) {
struct nlattr *ssid, *rssi;
- err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
- nla_data(attr), nla_len(attr),
- nl80211_match_policy);
+ err = nla_parse_nested(tb,
+ NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+ attr, nl80211_match_policy);
if (err)
goto out_free;
ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
@@ -7643,6 +7682,7 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
struct survey_info survey;
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
@@ -7655,7 +7695,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
return res;
/* prepare_wdev_dump parsed the attributes */
- radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
+ radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
if (!wdev->netdev) {
res = -EINVAL;
@@ -7708,8 +7748,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct ieee80211_channel *chan;
- const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
- int err, ssid_len, ie_len = 0, sae_data_len = 0;
+ const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
+ int err, ssid_len, ie_len = 0, auth_data_len = 0;
enum nl80211_auth_type auth_type;
struct key_parse key;
bool local_state_change;
@@ -7789,17 +7829,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
return -EINVAL;
- if (auth_type == NL80211_AUTHTYPE_SAE &&
- !info->attrs[NL80211_ATTR_SAE_DATA])
+ if ((auth_type == NL80211_AUTHTYPE_SAE ||
+ auth_type == NL80211_AUTHTYPE_FILS_SK ||
+ auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+ auth_type == NL80211_AUTHTYPE_FILS_PK) &&
+ !info->attrs[NL80211_ATTR_AUTH_DATA])
return -EINVAL;
- if (info->attrs[NL80211_ATTR_SAE_DATA]) {
- if (auth_type != NL80211_AUTHTYPE_SAE)
+ if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
+ if (auth_type != NL80211_AUTHTYPE_SAE &&
+ auth_type != NL80211_AUTHTYPE_FILS_SK &&
+ auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
+ auth_type != NL80211_AUTHTYPE_FILS_PK)
return -EINVAL;
- sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
- sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
+ auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
+ auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
/* need to include at least Auth Transaction and Status Code */
- if (sae_data_len < 4)
+ if (auth_data_len < 4)
return -EINVAL;
}
@@ -7816,7 +7862,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key.p.key, key.p.key_len, key.idx,
- sae_data, sae_data_len);
+ auth_data, auth_data_len);
wdev_unlock(dev->ieee80211_ptr);
return err;
}
@@ -7995,6 +8041,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
req.flags |= ASSOC_REQ_USE_RRM;
}
+ if (info->attrs[NL80211_ATTR_FILS_KEK]) {
+ req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
+ req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
+ if (!info->attrs[NL80211_ATTR_FILS_NONCES])
+ return -EINVAL;
+ req.fils_nonces =
+ nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
+ }
+
err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
if (!err) {
wdev_lock(dev->ieee80211_ptr);
@@ -8152,7 +8207,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
+ ibss.beacon_interval);
if (err)
return err;
@@ -8478,14 +8534,14 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
*/
phy_idx = cb->args[0] - 1;
} else {
+ struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
+
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
+ attrbuf, nl80211_fam.maxattr, nl80211_policy);
if (err)
goto out_err;
- rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
- nl80211_fam.attrbuf);
+ rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
if (IS_ERR(rdev)) {
err = PTR_ERR(rdev);
goto out_err;
@@ -8493,9 +8549,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
phy_idx = rdev->wiphy_idx;
rdev = NULL;
- if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
- cb->args[1] =
- (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
+ if (attrbuf[NL80211_ATTR_TESTDATA])
+ cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
}
if (cb->args[1]) {
@@ -8726,6 +8781,37 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return err;
}
+static int nl80211_update_connect_params(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_connect_params connect = {};
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ u32 changed = 0;
+ int ret;
+
+ if (!rdev->ops->update_connect_params)
+ return -EOPNOTSUPP;
+
+ if (info->attrs[NL80211_ATTR_IE]) {
+ if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
+ connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ changed |= UPDATE_ASSOC_IES;
+ }
+
+ wdev_lock(dev->ieee80211_ptr);
+ if (!wdev->current_bss)
+ ret = -ENOLINK;
+ else
+ ret = rdev_update_connect_params(rdev, dev, &connect, changed);
+ wdev_unlock(dev->ieee80211_ptr);
+
+ return ret;
+}
+
static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9417,7 +9503,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
setup.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev,
+ NL80211_IFTYPE_MESH_POINT,
+ setup.beacon_interval);
if (err)
return err;
}
@@ -9728,9 +9816,8 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
if (!rdev->wiphy.wowlan->tcp)
return -EINVAL;
- err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP,
- nla_data(attr), nla_len(attr),
- nl80211_wowlan_tcp_policy);
+ err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TCP, attr,
+ nl80211_wowlan_tcp_policy);
if (err)
return err;
@@ -9875,9 +9962,7 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
goto out;
}
- err = nla_parse(tb, NL80211_ATTR_MAX,
- nla_data(attr), nla_len(attr),
- nl80211_policy);
+ err = nla_parse_nested(tb, NL80211_ATTR_MAX, attr, nl80211_policy);
if (err)
goto out;
@@ -9911,10 +9996,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
goto set_wakeup;
}
- err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG,
- nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
- nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
- nl80211_wowlan_policy);
+ err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TRIG,
+ info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
+ nl80211_wowlan_policy);
if (err)
return err;
@@ -9996,8 +10080,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
rem) {
u8 *mask_pat;
- nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
- nla_len(pat), NULL);
+ nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
+ NULL);
err = -EINVAL;
if (!pat_tb[NL80211_PKTPAT_MASK] ||
!pat_tb[NL80211_PKTPAT_PATTERN])
@@ -10207,8 +10291,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
- err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
- nla_len(rule), nl80211_coalesce_policy);
+ err = nla_parse_nested(tb, NL80211_ATTR_COALESCE_RULE_MAX, rule,
+ nl80211_coalesce_policy);
if (err)
return err;
@@ -10246,8 +10330,7 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
rem) {
u8 *mask_pat;
- nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
- nla_len(pat), NULL);
+ nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, NULL);
if (!pat_tb[NL80211_PKTPAT_MASK] ||
!pat_tb[NL80211_PKTPAT_PATTERN])
return -EINVAL;
@@ -10366,10 +10449,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
if (!info->attrs[NL80211_ATTR_REKEY_DATA])
return -EINVAL;
- err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
- nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
- nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
- nl80211_rekey_policy);
+ err = nla_parse_nested(tb, MAX_NL80211_REKEY_DATA,
+ info->attrs[NL80211_ATTR_REKEY_DATA],
+ nl80211_rekey_policy);
if (err)
return err;
@@ -10518,7 +10600,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
return -EOPNOTSUPP;
- if (wdev->p2p_started)
+ if (wdev_running(wdev))
return 0;
if (rfkill_blocked(rdev->rfkill))
@@ -10528,7 +10610,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- wdev->p2p_started = true;
+ wdev->is_running = true;
rdev->opencount++;
return 0;
@@ -10560,7 +10642,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (wdev->nan_started)
+ if (wdev_running(wdev))
return -EEXIST;
if (rfkill_blocked(rdev->rfkill))
@@ -10583,7 +10665,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- wdev->nan_started = true;
+ wdev->is_running = true;
rdev->opencount++;
return 0;
@@ -10638,8 +10720,7 @@ static int handle_nan_filter(struct nlattr *attr_filter,
i = 0;
nla_for_each_nested(attr, attr_filter, rem) {
- filter[i].filter = kmemdup(nla_data(attr), nla_len(attr),
- GFP_KERNEL);
+ filter[i].filter = nla_memdup(attr, GFP_KERNEL);
filter[i].len = nla_len(attr);
i++;
}
@@ -10668,7 +10749,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_running(wdev))
return -ENOTCONN;
if (!info->attrs[NL80211_ATTR_NAN_FUNC])
@@ -10678,10 +10759,9 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
wdev->owner_nlportid != info->snd_portid)
return -ENOTCONN;
- err = nla_parse(tb, NL80211_NAN_FUNC_ATTR_MAX,
- nla_data(info->attrs[NL80211_ATTR_NAN_FUNC]),
- nla_len(info->attrs[NL80211_ATTR_NAN_FUNC]),
- nl80211_nan_func_policy);
+ err = nla_parse_nested(tb, NL80211_NAN_FUNC_ATTR_MAX,
+ info->attrs[NL80211_ATTR_NAN_FUNC],
+ nl80211_nan_func_policy);
if (err)
return err;
@@ -10776,9 +10856,9 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
if (tb[NL80211_NAN_FUNC_SRF]) {
struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
- err = nla_parse(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
- nla_data(tb[NL80211_NAN_FUNC_SRF]),
- nla_len(tb[NL80211_NAN_FUNC_SRF]), NULL);
+ err = nla_parse_nested(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
+ tb[NL80211_NAN_FUNC_SRF],
+ nl80211_nan_srf_policy);
if (err)
goto out;
@@ -10904,7 +10984,7 @@ static int nl80211_nan_del_func(struct sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_running(wdev))
return -ENOTCONN;
if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -10932,7 +11012,7 @@ static int nl80211_nan_change_config(struct sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_running(wdev))
return -ENOTCONN;
if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
@@ -11244,10 +11324,7 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
- if (wdev->netdev &&
- !netif_running(wdev->netdev))
- return -ENETDOWN;
- if (!wdev->netdev && !wdev->p2p_started)
+ if (!wdev_running(wdev))
return -ENETDOWN;
}
@@ -11277,6 +11354,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
struct cfg80211_registered_device **rdev,
struct wireless_dev **wdev)
{
+ struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
u32 vid, subcmd;
unsigned int i;
int vcmd_idx = -1;
@@ -11312,31 +11390,28 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
}
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
+ attrbuf, nl80211_fam.maxattr, nl80211_policy);
if (err)
goto out_unlock;
- if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] ||
- !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
+ if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
+ !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
err = -EINVAL;
goto out_unlock;
}
- *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
- nl80211_fam.attrbuf);
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
if (IS_ERR(*wdev))
*wdev = NULL;
- *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
- nl80211_fam.attrbuf);
+ *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
if (IS_ERR(*rdev)) {
err = PTR_ERR(*rdev);
goto out_unlock;
}
- vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]);
- subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
+ vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
+ subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
const struct wiphy_vendor_command *vcmd;
@@ -11360,9 +11435,9 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
goto out_unlock;
}
- if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) {
- data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
- data_len = nla_len(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
+ if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
+ data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
+ data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
}
/* 0 is the first index - add 1 to parse only once */
@@ -11410,10 +11485,7 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
return -EINVAL;
if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
- if (wdev->netdev &&
- !netif_running(wdev->netdev))
- return -ENETDOWN;
- if (!wdev->netdev && !wdev->p2p_started)
+ if (!wdev_running(wdev))
return -ENETDOWN;
}
}
@@ -11726,6 +11798,31 @@ static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
return 0;
}
+static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ const struct nlattr *nla;
+ bool enabled;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ if (!rdev->ops->set_multicast_to_unicast)
+ return -EOPNOTSUPP;
+
+ if (wdev->iftype != NL80211_IFTYPE_AP &&
+ wdev->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
+
+ nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
+ enabled = nla_get_flag(nla);
+
+ return rdev_set_multicast_to_unicast(rdev, dev, enabled);
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -11784,29 +11881,15 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[1] = wdev;
}
- if (dev) {
- if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
- !netif_running(dev)) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
+ if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+ !wdev_running(wdev)) {
+ if (rtnl)
+ rtnl_unlock();
+ return -ENETDOWN;
+ }
+ if (dev)
dev_hold(dev);
- } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
- if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
- !wdev->p2p_started) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
- if (wdev->iftype == NL80211_IFTYPE_NAN &&
- !wdev->nan_started) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
- }
info->user_ptr[0] = rdev;
}
@@ -12179,6 +12262,14 @@ static const struct genl_ops nl80211_ops[] = {
NL80211_FLAG_NEED_RTNL,
},
{
+ .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
+ .doit = nl80211_update_connect_params,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
.cmd = NL80211_CMD_DISCONNECT,
.doit = nl80211_disconnect,
.policy = nl80211_policy,
@@ -12599,6 +12690,29 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+ .doit = nl80211_set_multicast_to_unicast,
+ .policy = nl80211_policy,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
+};
+
+static struct genl_family nl80211_fam __ro_after_init = {
+ .name = NL80211_GENL_NAME, /* have users key off the name instead */
+ .hdrsize = 0, /* no private header */
+ .version = 1, /* no particular meaning now */
+ .maxattr = NL80211_ATTR_MAX,
+ .netnsok = true,
+ .pre_doit = nl80211_pre_doit,
+ .post_doit = nl80211_post_doit,
+ .module = THIS_MODULE,
+ .ops = nl80211_ops,
+ .n_ops = ARRAY_SIZE(nl80211_ops),
+ .mcgrps = nl80211_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
};
/* notification functions */
@@ -14563,12 +14677,11 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
/* initialisation/exit functions */
-int nl80211_init(void)
+int __init nl80211_init(void)
{
int err;
- err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
- nl80211_mcgrps);
+ err = genl_register_family(&nl80211_fam);
if (err)
return err;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 11cf83c8ad4f..2f425075ada8 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -490,6 +490,18 @@ static inline int rdev_connect(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int
+rdev_update_connect_params(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *sme, u32 changed)
+{
+ int ret;
+ trace_rdev_update_connect_params(&rdev->wiphy, dev, sme, changed);
+ ret = rdev->ops->update_connect_params(&rdev->wiphy, dev, sme, changed);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
static inline int rdev_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason_code)
{
@@ -562,6 +574,18 @@ static inline int rdev_set_wds_peer(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int
+rdev_set_multicast_to_unicast(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ const bool enabled)
+{
+ int ret;
+ trace_rdev_set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+ ret = rdev->ops->set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
{
trace_rdev_rfkill_poll(&rdev->wiphy);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a77db333927e..5e0d19380302 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -39,6 +39,7 @@ struct cfg80211_conn {
CFG80211_CONN_ASSOCIATING,
CFG80211_CONN_ASSOC_FAILED,
CFG80211_CONN_DEAUTH,
+ CFG80211_CONN_ABANDON,
CFG80211_CONN_CONNECTED,
} state;
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
@@ -206,6 +207,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
WLAN_REASON_DEAUTH_LEAVING, false);
+ /* fall through */
+ case CFG80211_CONN_ABANDON:
/* free directly, disconnected event already sent */
cfg80211_sme_free(wdev);
return 0;
@@ -423,6 +426,17 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
schedule_work(&rdev->conn_work);
}
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+ if (!wdev->conn)
+ return;
+
+ wdev->conn->state = CFG80211_CONN_ABANDON;
+ schedule_work(&rdev->conn_work);
+}
+
static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
const u8 *ies, size_t ies_len,
const u8 **out_ies, size_t *out_ies_len)
@@ -1088,7 +1102,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
err = cfg80211_sme_disconnect(wdev, reason);
else if (!rdev->ops->disconnect)
cfg80211_mlme_down(rdev, dev);
- else if (wdev->current_bss)
+ else if (wdev->ssid_len)
err = rdev_disconnect(rdev, dev, reason);
return err;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a3d0a91b1e09..ea1b47e04fa4 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1281,6 +1281,24 @@ TRACE_EVENT(rdev_connect,
__entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid))
);
+TRACE_EVENT(rdev_update_connect_params,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_connect_params *sme, u32 changed),
+ TP_ARGS(wiphy, netdev, sme, changed),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u32, changed)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->changed = changed;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", parameters changed: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->changed)
+);
+
TRACE_EVENT(rdev_set_cqm_rssi_config,
TP_PROTO(struct wiphy *wiphy,
struct net_device *netdev, s32 rssi_thold,
@@ -3030,6 +3048,25 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
TP_ARGS(wiphy, wdev)
);
+
+TRACE_EVENT(rdev_set_multicast_to_unicast,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ const bool enabled),
+ TP_ARGS(wiphy, netdev, enabled),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(bool, enabled)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->enabled = enabled;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG,
+ BOOL_TO_STR(__entry->enabled))
+);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 659b507b347d..e9d040d29846 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -13,6 +13,7 @@
#include <net/dsfield.h>
#include <linux/if_vlan.h>
#include <linux/mpls.h>
+#include <linux/gcd.h>
#include "core.h"
#include "rdev-ops.h"
@@ -1378,6 +1379,25 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
return false;
}
+static size_t skip_ie(const u8 *ies, size_t ielen, size_t pos)
+{
+ /* we assume a validly formed IEs buffer */
+ u8 len = ies[pos + 1];
+
+ pos += 2 + len;
+
+ /* the IE itself must have 255 bytes for fragments to follow */
+ if (len < 255)
+ return pos;
+
+ while (pos < ielen && ies[pos] == WLAN_EID_FRAGMENT) {
+ len = ies[pos + 1];
+ pos += 2 + len;
+ }
+
+ return pos;
+}
+
size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids,
const u8 *after_ric, int n_after_ric,
@@ -1387,14 +1407,14 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
while (pos < ielen &&
!ieee80211_id_in_list(after_ric, n_after_ric,
ies[pos]))
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
} else {
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
}
}
@@ -1555,31 +1575,57 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
}
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int)
+static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+ u32 *beacon_int_gcd,
+ bool *beacon_int_different)
{
struct wireless_dev *wdev;
- int res = 0;
- if (beacon_int < 10 || beacon_int > 10000)
- return -EINVAL;
+ *beacon_int_gcd = 0;
+ *beacon_int_different = false;
- list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
- if (wdev->beacon_interval != beacon_int) {
- res = -EINVAL;
- break;
+
+ if (!*beacon_int_gcd) {
+ *beacon_int_gcd = wdev->beacon_interval;
+ continue;
}
+
+ if (wdev->beacon_interval == *beacon_int_gcd)
+ continue;
+
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
}
- return res;
+ if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+ if (*beacon_int_gcd)
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
+ }
+}
+
+int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype, u32 beacon_int)
+{
+ /*
+ * This is just a basic pre-condition check; if interface combinations
+ * are possible the driver must already be checking those with a call
+ * to cfg80211_check_combinations(), in which case we'll validate more
+ * through the cfg80211_calculate_bi_data() call and code in
+ * cfg80211_iter_combinations().
+ */
+
+ if (beacon_int < 10 || beacon_int > 10000)
+ return -EINVAL;
+
+ return 0;
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
+ struct iface_combination_params *params,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data)
@@ -1589,8 +1635,23 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
int i, j, iftype;
int num_interfaces = 0;
u32 used_iftypes = 0;
+ u32 beacon_int_gcd;
+ bool beacon_int_different;
+
+ /*
+ * This is a bit strange, since the iteration used to rely only on
+ * the data given by the driver, but here it now relies on context,
+ * in form of the currently operating interfaces.
+ * This is OK for all current users, and saves us from having to
+ * push the GCD calculations into all the drivers.
+ * In the future, this should probably rely more on data that's in
+ * cfg80211 already - the only thing not would appear to be any new
+ * interfaces (while being brought up) and channel/radar data.
+ */
+ cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+ &beacon_int_gcd, &beacon_int_different);
- if (radar_detect) {
+ if (params->radar_detect) {
rcu_read_lock();
regdom = rcu_dereference(cfg80211_regdomain);
if (regdom)
@@ -1599,8 +1660,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
}
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
- num_interfaces += iftype_num[iftype];
- if (iftype_num[iftype] > 0 &&
+ num_interfaces += params->iftype_num[iftype];
+ if (params->iftype_num[iftype] > 0 &&
!(wiphy->software_iftypes & BIT(iftype)))
used_iftypes |= BIT(iftype);
}
@@ -1614,7 +1675,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if (num_interfaces > c->max_interfaces)
continue;
- if (num_different_channels > c->num_different_channels)
+ if (params->num_different_channels > c->num_different_channels)
continue;
limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
@@ -1629,16 +1690,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
all_iftypes |= limits[j].types;
if (!(limits[j].types & BIT(iftype)))
continue;
- if (limits[j].max < iftype_num[iftype])
+ if (limits[j].max < params->iftype_num[iftype])
goto cont;
- limits[j].max -= iftype_num[iftype];
+ limits[j].max -= params->iftype_num[iftype];
}
}
- if (radar_detect != (c->radar_detect_widths & radar_detect))
+ if (params->radar_detect !=
+ (c->radar_detect_widths & params->radar_detect))
goto cont;
- if (radar_detect && c->radar_detect_regions &&
+ if (params->radar_detect && c->radar_detect_regions &&
!(c->radar_detect_regions & BIT(region)))
goto cont;
@@ -1650,6 +1712,14 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
+ if (beacon_int_gcd) {
+ if (c->beacon_int_min_gcd &&
+ beacon_int_gcd < c->beacon_int_min_gcd)
+ goto cont;
+ if (!c->beacon_int_min_gcd && beacon_int_different)
+ goto cont;
+ }
+
/* This combination covered all interface types and
* supported the requested numbers, so we're good.
*/
@@ -1672,14 +1742,11 @@ cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
}
int cfg80211_check_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES])
+ struct iface_combination_params *params)
{
int err, num = 0;
- err = cfg80211_iter_combinations(wiphy, num_different_channels,
- radar_detect, iftype_num,
+ err = cfg80211_iter_combinations(wiphy, params,
cfg80211_iter_sum_ifcombs, &num);
if (err)
return err;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 5bf7e1bfeac7..177e208e8ff5 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3113,6 +3113,7 @@ static struct pernet_operations __net_initdata xfrm_net_ops = {
void __init xfrm_init(void)
{
+ flow_cache_hp_init();
register_pernet_subsys(&xfrm_net_ops);
seqcount_init(&xfrm_policy_hash_generation);
xfrm_input_init();
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 419bf5d463bd..45cb7c699b65 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -388,14 +388,6 @@ static void xfrm_state_gc_task(struct work_struct *work)
xfrm_state_gc_destroy(x);
}
-static inline unsigned long make_jiffies(long secs)
-{
- if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
- return MAX_SCHEDULE_TIMEOUT-1;
- else
- return secs*HZ;
-}
-
static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
{
struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 72c58675973e..f2219c1489e5 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -2,7 +2,7 @@
obj- := dummy.o
# List of programs to build
-hostprogs-y := test_verifier test_maps
+hostprogs-y := test_lru_dist
hostprogs-y += sock_example
hostprogs-y += fds_example
hostprogs-y += sockex1
@@ -22,15 +22,20 @@ hostprogs-y += spintest
hostprogs-y += map_perf_test
hostprogs-y += test_overhead
hostprogs-y += test_cgrp2_array_pin
+hostprogs-y += test_cgrp2_attach
+hostprogs-y += test_cgrp2_attach2
+hostprogs-y += test_cgrp2_sock
+hostprogs-y += test_cgrp2_sock2
hostprogs-y += xdp1
hostprogs-y += xdp2
hostprogs-y += test_current_task_under_cgroup
hostprogs-y += trace_event
hostprogs-y += sampleip
hostprogs-y += tc_l2_redirect
+hostprogs-y += lwt_len_hist
+hostprogs-y += xdp_tx_iptunnel
-test_verifier-objs := test_verifier.o libbpf.o
-test_maps-objs := test_maps.o libbpf.o
+test_lru_dist-objs := test_lru_dist.o libbpf.o
sock_example-objs := sock_example.o libbpf.o
fds_example-objs := bpf_load.o libbpf.o fds_example.o
sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
@@ -50,14 +55,20 @@ spintest-objs := bpf_load.o libbpf.o spintest_user.o
map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o
test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o
+test_cgrp2_attach-objs := libbpf.o test_cgrp2_attach.o
+test_cgrp2_attach2-objs := libbpf.o test_cgrp2_attach2.o cgroup_helpers.o
+test_cgrp2_sock-objs := libbpf.o test_cgrp2_sock.o
+test_cgrp2_sock2-objs := bpf_load.o libbpf.o test_cgrp2_sock2.o
xdp1-objs := bpf_load.o libbpf.o xdp1_user.o
# reuse xdp1 source intentionally
xdp2-objs := bpf_load.o libbpf.o xdp1_user.o
-test_current_task_under_cgroup-objs := bpf_load.o libbpf.o \
+test_current_task_under_cgroup-objs := bpf_load.o libbpf.o cgroup_helpers.o \
test_current_task_under_cgroup_user.o
trace_event-objs := bpf_load.o libbpf.o trace_event_user.o
sampleip-objs := bpf_load.o libbpf.o sampleip_user.o
tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o
+lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o
+xdp_tx_iptunnel-objs := bpf_load.o libbpf.o xdp_tx_iptunnel_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
@@ -70,6 +81,7 @@ always += tracex3_kern.o
always += tracex4_kern.o
always += tracex5_kern.o
always += tracex6_kern.o
+always += sock_flags_kern.o
always += test_probe_write_user_kern.o
always += trace_output_kern.o
always += tcbpf1_kern.o
@@ -88,8 +100,11 @@ always += xdp2_kern.o
always += test_current_task_under_cgroup_kern.o
always += trace_event_kern.o
always += sampleip_kern.o
+always += lwt_len_hist_kern.o
+always += xdp_tx_iptunnel_kern.o
HOSTCFLAGS += -I$(objtree)/usr/include
+HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
HOSTLOADLIBES_fds_example += -lelf
@@ -102,6 +117,7 @@ HOSTLOADLIBES_tracex3 += -lelf
HOSTLOADLIBES_tracex4 += -lelf -lrt
HOSTLOADLIBES_tracex5 += -lelf
HOSTLOADLIBES_tracex6 += -lelf
+HOSTLOADLIBES_test_cgrp2_sock2 += -lelf
HOSTLOADLIBES_test_probe_write_user += -lelf
HOSTLOADLIBES_trace_output += -lelf -lrt
HOSTLOADLIBES_lathist += -lelf
@@ -115,6 +131,8 @@ HOSTLOADLIBES_test_current_task_under_cgroup += -lelf
HOSTLOADLIBES_trace_event += -lelf
HOSTLOADLIBES_sampleip += -lelf
HOSTLOADLIBES_tc_l2_redirect += -l elf
+HOSTLOADLIBES_lwt_len_hist += -l elf
+HOSTLOADLIBES_xdp_tx_iptunnel += -lelf
# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
@@ -156,4 +174,6 @@ $(obj)/%.o: $(src)/%.c
$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \
-D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \
-Wno-compare-distinct-pointer-types \
+ -Wno-gnu-variable-sized-type-not-at-end \
+ -Wno-address-of-packed-member -Wno-tautological-compare \
-O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index dadd5161bd91..faaffe2e139a 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -57,6 +57,8 @@ static int (*bpf_skb_set_tunnel_opt)(void *ctx, void *md, int size) =
(void *) BPF_FUNC_skb_set_tunnel_opt;
static unsigned long long (*bpf_get_prandom_u32)(void) =
(void *) BPF_FUNC_get_prandom_u32;
+static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
+ (void *) BPF_FUNC_xdp_adjust_head;
/* llvm builtin functions that eBPF C program may use to
* emit BPF_LD_ABS and BPF_LD_IND instructions
@@ -80,6 +82,8 @@ struct bpf_map_def {
unsigned int map_flags;
};
+static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
+ (void *) BPF_FUNC_skb_load_bytes;
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
(void *) BPF_FUNC_skb_store_bytes;
static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) =
@@ -88,6 +92,8 @@ static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flag
(void *) BPF_FUNC_l4_csum_replace;
static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
(void *) BPF_FUNC_skb_under_cgroup;
+static int (*bpf_skb_change_head)(void *, int len, int flags) =
+ (void *) BPF_FUNC_skb_change_head;
#if defined(__x86_64__)
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 97913e109b14..e30b6de94f2e 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -12,6 +12,10 @@
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/perf_event.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -52,6 +56,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0;
bool is_xdp = strncmp(event, "xdp", 3) == 0;
bool is_perf_event = strncmp(event, "perf_event", 10) == 0;
+ bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0;
+ bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
enum bpf_prog_type prog_type;
char buf[256];
int fd, efd, err, id;
@@ -72,6 +78,10 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
prog_type = BPF_PROG_TYPE_XDP;
} else if (is_perf_event) {
prog_type = BPF_PROG_TYPE_PERF_EVENT;
+ } else if (is_cgroup_skb) {
+ prog_type = BPF_PROG_TYPE_CGROUP_SKB;
+ } else if (is_cgroup_sk) {
+ prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
} else {
printf("Unknown event '%s'\n", event);
return -1;
@@ -85,7 +95,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
prog_fd[prog_cnt++] = fd;
- if (is_xdp || is_perf_event)
+ if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk)
return 0;
if (is_socket) {
@@ -317,6 +327,10 @@ int load_bpf_file(char *path)
&shdr_prog, &data_prog))
continue;
+ if (shdr_prog.sh_type != SHT_PROGBITS ||
+ !(shdr_prog.sh_flags & SHF_EXECINSTR))
+ continue;
+
insns = (struct bpf_insn *) data_prog->d_buf;
processed_sec[shdr.sh_info] = true;
@@ -330,7 +344,8 @@ int load_bpf_file(char *path)
memcmp(shname_prog, "tracepoint/", 11) == 0 ||
memcmp(shname_prog, "xdp", 3) == 0 ||
memcmp(shname_prog, "perf_event", 10) == 0 ||
- memcmp(shname_prog, "socket", 6) == 0)
+ memcmp(shname_prog, "socket", 6) == 0 ||
+ memcmp(shname_prog, "cgroup/", 7) == 0)
load_and_attach(shname_prog, insns, data_prog->d_size);
}
}
@@ -349,7 +364,8 @@ int load_bpf_file(char *path)
memcmp(shname, "tracepoint/", 11) == 0 ||
memcmp(shname, "xdp", 3) == 0 ||
memcmp(shname, "perf_event", 10) == 0 ||
- memcmp(shname, "socket", 6) == 0)
+ memcmp(shname, "socket", 6) == 0 ||
+ memcmp(shname, "cgroup/", 7) == 0)
load_and_attach(shname, data->d_buf, data->d_size);
}
@@ -438,3 +454,93 @@ struct ksym *ksym_search(long key)
/* out of range. return _stext */
return &syms[0];
}
+
+int set_link_xdp_fd(int ifindex, int fd)
+{
+ struct sockaddr_nl sa;
+ int sock, seq = 0, len, ret = -1;
+ char buf[4096];
+ struct nlattr *nla, *nla_xdp;
+ struct {
+ struct nlmsghdr nh;
+ struct ifinfomsg ifinfo;
+ char attrbuf[64];
+ } req;
+ struct nlmsghdr *nh;
+ struct nlmsgerr *err;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+
+ sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (sock < 0) {
+ printf("open netlink socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+ printf("bind to netlink: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ memset(&req, 0, sizeof(req));
+ req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.nh.nlmsg_type = RTM_SETLINK;
+ req.nh.nlmsg_pid = 0;
+ req.nh.nlmsg_seq = ++seq;
+ req.ifinfo.ifi_family = AF_UNSPEC;
+ req.ifinfo.ifi_index = ifindex;
+ nla = (struct nlattr *)(((char *)&req)
+ + NLMSG_ALIGN(req.nh.nlmsg_len));
+ nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/;
+
+ nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN);
+ nla_xdp->nla_type = 1/*IFLA_XDP_FD*/;
+ nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
+ memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
+ nla->nla_len = NLA_HDRLEN + nla_xdp->nla_len;
+
+ req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
+
+ if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
+ printf("send to netlink: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ len = recv(sock, buf, sizeof(buf), 0);
+ if (len < 0) {
+ printf("recv from netlink: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
+ nh = NLMSG_NEXT(nh, len)) {
+ if (nh->nlmsg_pid != getpid()) {
+ printf("Wrong pid %d, expected %d\n",
+ nh->nlmsg_pid, getpid());
+ goto cleanup;
+ }
+ if (nh->nlmsg_seq != seq) {
+ printf("Wrong seq %d, expected %d\n",
+ nh->nlmsg_seq, seq);
+ goto cleanup;
+ }
+ switch (nh->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(nh);
+ if (!err->error)
+ continue;
+ printf("nlmsg error %s\n", strerror(-err->error));
+ goto cleanup;
+ case NLMSG_DONE:
+ break;
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ close(sock);
+ return ret;
+}
diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h
index dfa57fe65c8e..fb46a421ab41 100644
--- a/samples/bpf/bpf_load.h
+++ b/samples/bpf/bpf_load.h
@@ -7,6 +7,7 @@
extern int map_fd[MAX_MAPS];
extern int prog_fd[MAX_PROGS];
extern int event_fd[MAX_PROGS];
+extern int prog_cnt;
/* parses elf file compiled by llvm .c->.o
* . parses 'maps' section and creates maps via BPF syscall
@@ -30,4 +31,5 @@ struct ksym {
int load_kallsyms(void);
struct ksym *ksym_search(long key);
+int set_link_xdp_fd(int ifindex, int fd);
#endif
diff --git a/samples/bpf/cgroup_helpers.c b/samples/bpf/cgroup_helpers.c
new file mode 100644
index 000000000000..9d1be9426401
--- /dev/null
+++ b/samples/bpf/cgroup_helpers.c
@@ -0,0 +1,177 @@
+#define _GNU_SOURCE
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <linux/sched.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ftw.h>
+
+
+#include "cgroup_helpers.h"
+
+/*
+ * To avoid relying on the system setup, when setup_cgroup_env is called
+ * we create a new mount namespace, and cgroup namespace. The cgroup2
+ * root is mounted at CGROUP_MOUNT_PATH
+ *
+ * Unfortunately, most people don't have cgroupv2 enabled at this point in time.
+ * It's easier to create our own mount namespace and manage it ourselves.
+ *
+ * We assume /mnt exists.
+ */
+
+#define WALK_FD_LIMIT 16
+#define CGROUP_MOUNT_PATH "/mnt"
+#define CGROUP_WORK_DIR "/cgroup-test-work-dir"
+#define format_cgroup_path(buf, path) \
+ snprintf(buf, sizeof(buf), "%s%s%s", CGROUP_MOUNT_PATH, \
+ CGROUP_WORK_DIR, path)
+
+/**
+ * setup_cgroup_environment() - Setup the cgroup environment
+ *
+ * After calling this function, cleanup_cgroup_environment should be called
+ * once testing is complete.
+ *
+ * This function will print an error to stderr and return 1 if it is unable
+ * to setup the cgroup environment. If setup is successful, 0 is returned.
+ */
+int setup_cgroup_environment(void)
+{
+ char cgroup_workdir[PATH_MAX + 1];
+
+ format_cgroup_path(cgroup_workdir, "");
+
+ if (unshare(CLONE_NEWNS)) {
+ log_err("unshare");
+ return 1;
+ }
+
+ if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
+ log_err("mount fakeroot");
+ return 1;
+ }
+
+ if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) {
+ log_err("mount cgroup2");
+ return 1;
+ }
+
+ /* Cleanup existing failed runs, now that the environment is setup */
+ cleanup_cgroup_environment();
+
+ if (mkdir(cgroup_workdir, 0777) && errno != EEXIST) {
+ log_err("mkdir cgroup work dir");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int nftwfunc(const char *filename, const struct stat *statptr,
+ int fileflags, struct FTW *pfwt)
+{
+ if ((fileflags & FTW_D) && rmdir(filename))
+ log_err("Removing cgroup: %s", filename);
+ return 0;
+}
+
+
+static int join_cgroup_from_top(char *cgroup_path)
+{
+ char cgroup_procs_path[PATH_MAX + 1];
+ pid_t pid = getpid();
+ int fd, rc = 0;
+
+ snprintf(cgroup_procs_path, sizeof(cgroup_procs_path),
+ "%s/cgroup.procs", cgroup_path);
+
+ fd = open(cgroup_procs_path, O_WRONLY);
+ if (fd < 0) {
+ log_err("Opening Cgroup Procs: %s", cgroup_procs_path);
+ return 1;
+ }
+
+ if (dprintf(fd, "%d\n", pid) < 0) {
+ log_err("Joining Cgroup");
+ rc = 1;
+ }
+
+ close(fd);
+ return rc;
+}
+
+/**
+ * join_cgroup() - Join a cgroup
+ * @path: The cgroup path, relative to the workdir, to join
+ *
+ * This function expects a cgroup to already be created, relative to the cgroup
+ * work dir, and it joins it. For example, passing "/my-cgroup" as the path
+ * would actually put the calling process into the cgroup
+ * "/cgroup-test-work-dir/my-cgroup"
+ *
+ * On success, it returns 0, otherwise on failure it returns 1.
+ */
+int join_cgroup(char *path)
+{
+ char cgroup_path[PATH_MAX + 1];
+
+ format_cgroup_path(cgroup_path, path);
+ return join_cgroup_from_top(cgroup_path);
+}
+
+/**
+ * cleanup_cgroup_environment() - Cleanup Cgroup Testing Environment
+ *
+ * This is an idempotent function to delete all temporary cgroups that
+ * have been created during the test, including the cgroup testing work
+ * directory.
+ *
+ * At call time, it moves the calling process to the root cgroup, and then
+ * runs the deletion process. It is idempotent, and should not fail, unless
+ * a process is lingering.
+ *
+ * On failure, it will print an error to stderr, and try to continue.
+ */
+void cleanup_cgroup_environment(void)
+{
+ char cgroup_workdir[PATH_MAX + 1];
+
+ format_cgroup_path(cgroup_workdir, "");
+ join_cgroup_from_top(CGROUP_MOUNT_PATH);
+ nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT);
+}
+
+/**
+ * create_and_get_cgroup() - Create a cgroup, relative to workdir, and get the FD
+ * @path: The cgroup path, relative to the workdir, to join
+ *
+ * This function creates a cgroup under the top level workdir and returns the
+ * file descriptor. It is idempotent.
+ *
+ * On success, it returns the file descriptor. On failure it returns 0.
+ * If there is a failure, it prints the error to stderr.
+ */
+int create_and_get_cgroup(char *path)
+{
+ char cgroup_path[PATH_MAX + 1];
+ int fd;
+
+ format_cgroup_path(cgroup_path, path);
+ if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
+ log_err("mkdiring cgroup");
+ return 0;
+ }
+
+ fd = open(cgroup_path, O_RDONLY);
+ if (fd < 0) {
+ log_err("Opening Cgroup");
+ return 0;
+ }
+
+ return fd;
+}
diff --git a/samples/bpf/cgroup_helpers.h b/samples/bpf/cgroup_helpers.h
new file mode 100644
index 000000000000..78c55207b6bd
--- /dev/null
+++ b/samples/bpf/cgroup_helpers.h
@@ -0,0 +1,16 @@
+#ifndef __CGROUP_HELPERS_H
+#define __CGROUP_HELPERS_H
+#include <errno.h>
+#include <string.h>
+
+#define clean_errno() (errno == 0 ? "None" : strerror(errno))
+#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
+ __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
+
+
+int create_and_get_cgroup(char *path);
+int join_cgroup(char *path);
+int setup_cgroup_environment(void);
+void cleanup_cgroup_environment(void);
+
+#endif
diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index 9969e35550c3..9ce707bf02a7 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -104,6 +104,27 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}
+int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
+{
+ union bpf_attr attr = {
+ .target_fd = target_fd,
+ .attach_bpf_fd = prog_fd,
+ .attach_type = type,
+ };
+
+ return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr));
+}
+
+int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
+{
+ union bpf_attr attr = {
+ .target_fd = target_fd,
+ .attach_type = type,
+ };
+
+ return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr));
+}
+
int bpf_obj_pin(int fd, const char *pathname)
{
union bpf_attr attr = {
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index ac6edb61b64a..94a901d86fc2 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -15,10 +15,13 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
const struct bpf_insn *insns, int insn_len,
const char *license, int kern_version);
+int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
+int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
+
int bpf_obj_pin(int fd, const char *pathname);
int bpf_obj_get(const char *pathname);
-#define LOG_BUF_SIZE 65536
+#define LOG_BUF_SIZE (256 * 1024)
extern char bpf_log_buf[LOG_BUF_SIZE];
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
diff --git a/samples/bpf/lwt_len_hist.sh b/samples/bpf/lwt_len_hist.sh
new file mode 100644
index 000000000000..7d567744c7fa
--- /dev/null
+++ b/samples/bpf/lwt_len_hist.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+NS1=lwt_ns1
+VETH0=tst_lwt1a
+VETH1=tst_lwt1b
+
+TRACE_ROOT=/sys/kernel/debug/tracing
+
+function cleanup {
+ ip route del 192.168.253.2/32 dev $VETH0 2> /dev/null
+ ip link del $VETH0 2> /dev/null
+ ip link del $VETH1 2> /dev/null
+ ip netns exec $NS1 killall netserver
+ ip netns delete $NS1 2> /dev/null
+}
+
+cleanup
+
+ip netns add $NS1
+ip link add $VETH0 type veth peer name $VETH1
+ip link set dev $VETH0 up
+ip addr add 192.168.253.1/24 dev $VETH0
+ip link set $VETH1 netns $NS1
+ip netns exec $NS1 ip link set dev $VETH1 up
+ip netns exec $NS1 ip addr add 192.168.253.2/24 dev $VETH1
+ip netns exec $NS1 netserver
+
+echo 1 > ${TRACE_ROOT}/tracing_on
+cp /dev/null ${TRACE_ROOT}/trace
+ip route add 192.168.253.2/32 encap bpf out obj lwt_len_hist_kern.o section len_hist dev $VETH0
+netperf -H 192.168.253.2 -t TCP_STREAM
+cat ${TRACE_ROOT}/trace | grep -v '^#'
+./lwt_len_hist
+cleanup
+echo 0 > ${TRACE_ROOT}/tracing_on
+
+exit 0
diff --git a/samples/bpf/lwt_len_hist_kern.c b/samples/bpf/lwt_len_hist_kern.c
new file mode 100644
index 000000000000..df75383280f9
--- /dev/null
+++ b/samples/bpf/lwt_len_hist_kern.c
@@ -0,0 +1,82 @@
+/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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 <uapi/linux/bpf.h>
+#include <uapi/linux/if_ether.h>
+#include <uapi/linux/ip.h>
+#include <uapi/linux/in.h>
+#include "bpf_helpers.h"
+
+# define printk(fmt, ...) \
+ ({ \
+ char ____fmt[] = fmt; \
+ bpf_trace_printk(____fmt, sizeof(____fmt), \
+ ##__VA_ARGS__); \
+ })
+
+struct bpf_elf_map {
+ __u32 type;
+ __u32 size_key;
+ __u32 size_value;
+ __u32 max_elem;
+ __u32 flags;
+ __u32 id;
+ __u32 pinning;
+};
+
+struct bpf_elf_map SEC("maps") lwt_len_hist_map = {
+ .type = BPF_MAP_TYPE_PERCPU_HASH,
+ .size_key = sizeof(__u64),
+ .size_value = sizeof(__u64),
+ .pinning = 2,
+ .max_elem = 1024,
+};
+
+static unsigned int log2(unsigned int v)
+{
+ unsigned int r;
+ unsigned int shift;
+
+ r = (v > 0xFFFF) << 4; v >>= r;
+ shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
+ shift = (v > 0xF) << 2; v >>= shift; r |= shift;
+ shift = (v > 0x3) << 1; v >>= shift; r |= shift;
+ r |= (v >> 1);
+ return r;
+}
+
+static unsigned int log2l(unsigned long v)
+{
+ unsigned int hi = v >> 32;
+ if (hi)
+ return log2(hi) + 32;
+ else
+ return log2(v);
+}
+
+SEC("len_hist")
+int do_len_hist(struct __sk_buff *skb)
+{
+ __u64 *value, key, init_val = 1;
+
+ key = log2l(skb->len);
+
+ value = bpf_map_lookup_elem(&lwt_len_hist_map, &key);
+ if (value)
+ __sync_fetch_and_add(value, 1);
+ else
+ bpf_map_update_elem(&lwt_len_hist_map, &key, &init_val, BPF_ANY);
+
+ return BPF_OK;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/lwt_len_hist_user.c b/samples/bpf/lwt_len_hist_user.c
new file mode 100644
index 000000000000..05d783fc5daf
--- /dev/null
+++ b/samples/bpf/lwt_len_hist_user.c
@@ -0,0 +1,76 @@
+#include <linux/unistd.h>
+#include <linux/bpf.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include "libbpf.h"
+#include "bpf_util.h"
+
+#define MAX_INDEX 64
+#define MAX_STARS 38
+
+static void stars(char *str, long val, long max, int width)
+{
+ int i;
+
+ for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
+ str[i] = '*';
+ if (val > max)
+ str[i - 1] = '+';
+ str[i] = '\0';
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int nr_cpus = bpf_num_possible_cpus();
+ const char *map_filename = "/sys/fs/bpf/tc/globals/lwt_len_hist_map";
+ uint64_t values[nr_cpus], sum, max_value = 0, data[MAX_INDEX] = {};
+ uint64_t key = 0, next_key, max_key = 0;
+ char starstr[MAX_STARS];
+ int i, map_fd;
+
+ map_fd = bpf_obj_get(map_filename);
+ if (map_fd < 0) {
+ fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n",
+ map_filename, strerror(errno), errno);
+ return -1;
+ }
+
+ while (bpf_get_next_key(map_fd, &key, &next_key) == 0) {
+ if (next_key >= MAX_INDEX) {
+ fprintf(stderr, "Key %lu out of bounds\n", next_key);
+ continue;
+ }
+
+ bpf_lookup_elem(map_fd, &next_key, values);
+
+ sum = 0;
+ for (i = 0; i < nr_cpus; i++)
+ sum += values[i];
+
+ data[next_key] = sum;
+ if (sum && next_key > max_key)
+ max_key = next_key;
+
+ if (sum > max_value)
+ max_value = sum;
+
+ key = next_key;
+ }
+
+ for (i = 1; i <= max_key + 1; i++) {
+ stars(starstr, data[i - 1], max_value, MAX_STARS);
+ printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
+ (1l << i) >> 1, (1l << i) - 1, data[i - 1],
+ MAX_STARS, starstr);
+ }
+
+ close(map_fd);
+
+ return 0;
+}
diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c
index 311538e5a701..7ee1574c8ccf 100644
--- a/samples/bpf/map_perf_test_kern.c
+++ b/samples/bpf/map_perf_test_kern.c
@@ -19,6 +19,21 @@ struct bpf_map_def SEC("maps") hash_map = {
.max_entries = MAX_ENTRIES,
};
+struct bpf_map_def SEC("maps") lru_hash_map = {
+ .type = BPF_MAP_TYPE_LRU_HASH,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(long),
+ .max_entries = 10000,
+};
+
+struct bpf_map_def SEC("maps") percpu_lru_hash_map = {
+ .type = BPF_MAP_TYPE_LRU_HASH,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(long),
+ .max_entries = 10000,
+ .map_flags = BPF_F_NO_COMMON_LRU,
+};
+
struct bpf_map_def SEC("maps") percpu_hash_map = {
.type = BPF_MAP_TYPE_PERCPU_HASH,
.key_size = sizeof(u32),
@@ -53,6 +68,7 @@ int stress_hmap(struct pt_regs *ctx)
value = bpf_map_lookup_elem(&hash_map, &key);
if (value)
bpf_map_delete_elem(&hash_map, &key);
+
return 0;
}
@@ -96,5 +112,28 @@ int stress_percpu_hmap_alloc(struct pt_regs *ctx)
bpf_map_delete_elem(&percpu_hash_map_alloc, &key);
return 0;
}
+
+SEC("kprobe/sys_getpid")
+int stress_lru_hmap_alloc(struct pt_regs *ctx)
+{
+ u32 key = bpf_get_prandom_u32();
+ long val = 1;
+
+ bpf_map_update_elem(&lru_hash_map, &key, &val, BPF_ANY);
+
+ return 0;
+}
+
+SEC("kprobe/sys_getppid")
+int stress_percpu_lru_hmap_alloc(struct pt_regs *ctx)
+{
+ u32 key = bpf_get_prandom_u32();
+ long val = 1;
+
+ bpf_map_update_elem(&percpu_lru_hash_map, &key, &val, BPF_ANY);
+
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/map_perf_test_user.c b/samples/bpf/map_perf_test_user.c
index 3147377e8fd3..9505b4d112f4 100644
--- a/samples/bpf/map_perf_test_user.c
+++ b/samples/bpf/map_perf_test_user.c
@@ -35,6 +35,8 @@ static __u64 time_get_ns(void)
#define PERCPU_HASH_PREALLOC (1 << 1)
#define HASH_KMALLOC (1 << 2)
#define PERCPU_HASH_KMALLOC (1 << 3)
+#define LRU_HASH_PREALLOC (1 << 4)
+#define PERCPU_LRU_HASH_PREALLOC (1 << 5)
static int test_flags = ~0;
@@ -50,6 +52,30 @@ static void test_hash_prealloc(int cpu)
cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
}
+static void test_lru_hash_prealloc(int cpu)
+{
+ __u64 start_time;
+ int i;
+
+ start_time = time_get_ns();
+ for (i = 0; i < MAX_CNT; i++)
+ syscall(__NR_getpid);
+ printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n",
+ cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
+}
+
+static void test_percpu_lru_hash_prealloc(int cpu)
+{
+ __u64 start_time;
+ int i;
+
+ start_time = time_get_ns();
+ for (i = 0; i < MAX_CNT; i++)
+ syscall(__NR_getppid);
+ printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n",
+ cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
+}
+
static void test_percpu_hash_prealloc(int cpu)
{
__u64 start_time;
@@ -105,6 +131,12 @@ static void loop(int cpu)
if (test_flags & PERCPU_HASH_KMALLOC)
test_percpu_hash_kmalloc(cpu);
+
+ if (test_flags & LRU_HASH_PREALLOC)
+ test_lru_hash_prealloc(cpu);
+
+ if (test_flags & PERCPU_LRU_HASH_PREALLOC)
+ test_percpu_lru_hash_prealloc(cpu);
}
static void run_perf_test(int tasks)
diff --git a/samples/bpf/sock_flags_kern.c b/samples/bpf/sock_flags_kern.c
new file mode 100644
index 000000000000..533dd11a6baa
--- /dev/null
+++ b/samples/bpf/sock_flags_kern.c
@@ -0,0 +1,44 @@
+#include <uapi/linux/bpf.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <uapi/linux/in.h>
+#include <uapi/linux/in6.h>
+#include "bpf_helpers.h"
+
+SEC("cgroup/sock1")
+int bpf_prog1(struct bpf_sock *sk)
+{
+ char fmt[] = "socket: family %d type %d protocol %d\n";
+
+ bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol);
+
+ /* block PF_INET6, SOCK_RAW, IPPROTO_ICMPV6 sockets
+ * ie., make ping6 fail
+ */
+ if (sk->family == PF_INET6 &&
+ sk->type == SOCK_RAW &&
+ sk->protocol == IPPROTO_ICMPV6)
+ return 0;
+
+ return 1;
+}
+
+SEC("cgroup/sock2")
+int bpf_prog2(struct bpf_sock *sk)
+{
+ char fmt[] = "socket: family %d type %d protocol %d\n";
+
+ bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol);
+
+ /* block PF_INET, SOCK_RAW, IPPROTO_ICMP sockets
+ * ie., make ping fail
+ */
+ if (sk->family == PF_INET &&
+ sk->type == SOCK_RAW &&
+ sk->protocol == IPPROTO_ICMP)
+ return 0;
+
+ return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c
index 44e5846c988f..f58acfc92556 100644
--- a/samples/bpf/sockex2_kern.c
+++ b/samples/bpf/sockex2_kern.c
@@ -198,7 +198,7 @@ struct bpf_map_def SEC("maps") hash_map = {
SEC("socket2")
int bpf_prog2(struct __sk_buff *skb)
{
- struct bpf_flow_keys flow;
+ struct bpf_flow_keys flow = {};
struct pair *value;
u32 key;
diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c
new file mode 100644
index 000000000000..a19484c45b79
--- /dev/null
+++ b/samples/bpf/test_cgrp2_attach.c
@@ -0,0 +1,167 @@
+/* eBPF example program:
+ *
+ * - Creates arraymap in kernel with 4 bytes keys and 8 byte values
+ *
+ * - Loads eBPF program
+ *
+ * The eBPF program accesses the map passed in to store two pieces of
+ * information. The number of invocations of the program, which maps
+ * to the number of packets received, is stored to key 0. Key 1 is
+ * incremented on each iteration by the number of bytes stored in
+ * the skb.
+ *
+ * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
+ *
+ * - Every second, reads map[0] and map[1] to see how many bytes and
+ * packets were seen on any socket of tasks in the given cgroup.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <linux/bpf.h>
+
+#include "libbpf.h"
+
+enum {
+ MAP_KEY_PACKETS,
+ MAP_KEY_BYTES,
+};
+
+static int prog_load(int map_fd, int verdict)
+{
+ struct bpf_insn prog[] = {
+ BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), /* save r6 so it's not clobbered by BPF_CALL */
+
+ /* Count packets */
+ BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_PACKETS), /* r0 = 0 */
+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
+ BPF_LD_MAP_FD(BPF_REG_1, map_fd), /* load map fd to r1 */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+ BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */
+ BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */
+
+ /* Count bytes */
+ BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_BYTES), /* r0 = 1 */
+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
+ BPF_LD_MAP_FD(BPF_REG_1, map_fd),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct __sk_buff, len)), /* r1 = skb->len */
+ BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */
+
+ BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
+ BPF_EXIT_INSN(),
+ };
+
+ return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB,
+ prog, sizeof(prog), "GPL", 0);
+}
+
+static int usage(const char *argv0)
+{
+ printf("Usage: %s [-d] [-D] <cg-path> <egress|ingress>\n", argv0);
+ printf(" -d Drop Traffic\n");
+ printf(" -D Detach filter, and exit\n");
+ return EXIT_FAILURE;
+}
+
+static int attach_filter(int cg_fd, int type, int verdict)
+{
+ int prog_fd, map_fd, ret, key;
+ long long pkt_cnt, byte_cnt;
+
+ map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY,
+ sizeof(key), sizeof(byte_cnt),
+ 256, 0);
+ if (map_fd < 0) {
+ printf("Failed to create map: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ prog_fd = prog_load(map_fd, verdict);
+ printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
+
+ if (prog_fd < 0) {
+ printf("Failed to load prog: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ ret = bpf_prog_attach(prog_fd, cg_fd, type);
+ if (ret < 0) {
+ printf("Failed to attach prog to cgroup: '%s'\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ while (1) {
+ key = MAP_KEY_PACKETS;
+ assert(bpf_lookup_elem(map_fd, &key, &pkt_cnt) == 0);
+
+ key = MAP_KEY_BYTES;
+ assert(bpf_lookup_elem(map_fd, &key, &byte_cnt) == 0);
+
+ printf("cgroup received %lld packets, %lld bytes\n",
+ pkt_cnt, byte_cnt);
+ sleep(1);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ int detach_only = 0, verdict = 1;
+ enum bpf_attach_type type;
+ int opt, cg_fd, ret;
+
+ while ((opt = getopt(argc, argv, "Dd")) != -1) {
+ switch (opt) {
+ case 'd':
+ verdict = 0;
+ break;
+ case 'D':
+ detach_only = 1;
+ break;
+ default:
+ return usage(argv[0]);
+ }
+ }
+
+ if (argc - optind < 2)
+ return usage(argv[0]);
+
+ if (strcmp(argv[optind + 1], "ingress") == 0)
+ type = BPF_CGROUP_INET_INGRESS;
+ else if (strcmp(argv[optind + 1], "egress") == 0)
+ type = BPF_CGROUP_INET_EGRESS;
+ else
+ return usage(argv[0]);
+
+ cg_fd = open(argv[optind], O_DIRECTORY | O_RDONLY);
+ if (cg_fd < 0) {
+ printf("Failed to open cgroup path: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ if (detach_only) {
+ ret = bpf_prog_detach(cg_fd, type);
+ printf("bpf_prog_detach() returned '%s' (%d)\n",
+ strerror(errno), errno);
+ } else
+ ret = attach_filter(cg_fd, type, verdict);
+
+ return ret;
+}
diff --git a/samples/bpf/test_cgrp2_attach2.c b/samples/bpf/test_cgrp2_attach2.c
new file mode 100644
index 000000000000..ddfac42ed4df
--- /dev/null
+++ b/samples/bpf/test_cgrp2_attach2.c
@@ -0,0 +1,132 @@
+/* eBPF example program:
+ *
+ * - Creates arraymap in kernel with 4 bytes keys and 8 byte values
+ *
+ * - Loads eBPF program
+ *
+ * The eBPF program accesses the map passed in to store two pieces of
+ * information. The number of invocations of the program, which maps
+ * to the number of packets received, is stored to key 0. Key 1 is
+ * incremented on each iteration by the number of bytes stored in
+ * the skb.
+ *
+ * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
+ *
+ * - Every second, reads map[0] and map[1] to see how many bytes and
+ * packets were seen on any socket of tasks in the given cgroup.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <linux/bpf.h>
+
+#include "libbpf.h"
+#include "cgroup_helpers.h"
+
+#define FOO "/foo"
+#define BAR "/foo/bar/"
+#define PING_CMD "ping -c1 -w1 127.0.0.1"
+
+static int prog_load(int verdict)
+{
+ int ret;
+ struct bpf_insn prog[] = {
+ BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
+ BPF_EXIT_INSN(),
+ };
+
+ ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB,
+ prog, sizeof(prog), "GPL", 0);
+
+ if (ret < 0) {
+ log_err("Loading program");
+ printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
+ return 0;
+ }
+ return ret;
+}
+
+
+int main(int argc, char **argv)
+{
+ int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0;
+
+ allow_prog = prog_load(1);
+ if (!allow_prog)
+ goto err;
+
+ drop_prog = prog_load(0);
+ if (!drop_prog)
+ goto err;
+
+ if (setup_cgroup_environment())
+ goto err;
+
+ /* Create cgroup /foo, get fd, and join it */
+ foo = create_and_get_cgroup(FOO);
+ if (!foo)
+ goto err;
+
+ if (join_cgroup(FOO))
+ goto err;
+
+ if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS)) {
+ log_err("Attaching prog to /foo");
+ goto err;
+ }
+
+ assert(system(PING_CMD) != 0);
+
+ /* Create cgroup /foo/bar, get fd, and join it */
+ bar = create_and_get_cgroup(BAR);
+ if (!bar)
+ goto err;
+
+ if (join_cgroup(BAR))
+ goto err;
+
+ assert(system(PING_CMD) != 0);
+
+ if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
+ log_err("Attaching prog to /foo/bar");
+ goto err;
+ }
+
+ assert(system(PING_CMD) == 0);
+
+
+ if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
+ log_err("Detaching program from /foo/bar");
+ goto err;
+ }
+
+ assert(system(PING_CMD) != 0);
+
+ if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
+ log_err("Attaching prog to /foo/bar");
+ goto err;
+ }
+
+ if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) {
+ log_err("Detaching program from /foo");
+ goto err;
+ }
+
+ assert(system(PING_CMD) == 0);
+
+ goto out;
+
+err:
+ rc = 1;
+
+out:
+ close(foo);
+ close(bar);
+ cleanup_cgroup_environment();
+ return rc;
+}
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
new file mode 100644
index 000000000000..d467b3c1c55c
--- /dev/null
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -0,0 +1,83 @@
+/* eBPF example program:
+ *
+ * - Loads eBPF program
+ *
+ * The eBPF program sets the sk_bound_dev_if index in new AF_INET{6}
+ * sockets opened by processes in the cgroup.
+ *
+ * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <linux/bpf.h>
+
+#include "libbpf.h"
+
+static int prog_load(int idx)
+{
+ struct bpf_insn prog[] = {
+ BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+ BPF_MOV64_IMM(BPF_REG_3, idx),
+ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)),
+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)),
+ BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
+ BPF_EXIT_INSN(),
+ };
+
+ return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog),
+ "GPL", 0);
+}
+
+static int usage(const char *argv0)
+{
+ printf("Usage: %s cg-path device-index\n", argv0);
+ return EXIT_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+ int cg_fd, prog_fd, ret;
+ unsigned int idx;
+
+ if (argc < 2)
+ return usage(argv[0]);
+
+ idx = if_nametoindex(argv[2]);
+ if (!idx) {
+ printf("Invalid device name\n");
+ return EXIT_FAILURE;
+ }
+
+ cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
+ if (cg_fd < 0) {
+ printf("Failed to open cgroup path: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ prog_fd = prog_load(idx);
+ printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
+
+ if (prog_fd < 0) {
+ printf("Failed to load prog: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
+ if (ret < 0) {
+ printf("Failed to attach prog to cgroup: '%s'\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/samples/bpf/test_cgrp2_sock.sh b/samples/bpf/test_cgrp2_sock.sh
new file mode 100755
index 000000000000..925fd467c7cc
--- /dev/null
+++ b/samples/bpf/test_cgrp2_sock.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+function config_device {
+ ip netns add at_ns0
+ ip link add veth0 type veth peer name veth0b
+ ip link set veth0b up
+ ip link set veth0 netns at_ns0
+ ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0
+ ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad
+ ip netns exec at_ns0 ip link set dev veth0 up
+ ip link add foo type vrf table 1234
+ ip link set foo up
+ ip addr add 172.16.1.101/24 dev veth0b
+ ip addr add 2401:db00::2/64 dev veth0b nodad
+ ip link set veth0b master foo
+}
+
+function attach_bpf {
+ rm -rf /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2
+ mount -t cgroup2 none /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2/foo
+ test_cgrp2_sock /tmp/cgroupv2/foo foo
+ echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
+}
+
+function cleanup {
+ set +ex
+ ip netns delete at_ns0
+ ip link del veth0
+ ip link del foo
+ umount /tmp/cgroupv2
+ rm -rf /tmp/cgroupv2
+ set -ex
+}
+
+function do_test {
+ ping -c1 -w1 172.16.1.100
+ ping6 -c1 -w1 2401:db00::1
+}
+
+cleanup 2>/dev/null
+config_device
+attach_bpf
+do_test
+cleanup
+echo "*** PASS ***"
diff --git a/samples/bpf/test_cgrp2_sock2.c b/samples/bpf/test_cgrp2_sock2.c
new file mode 100644
index 000000000000..455ef0d06e93
--- /dev/null
+++ b/samples/bpf/test_cgrp2_sock2.c
@@ -0,0 +1,66 @@
+/* eBPF example program:
+ *
+ * - Loads eBPF program
+ *
+ * The eBPF program loads a filter from file and attaches the
+ * program to a cgroup using BPF_PROG_ATTACH
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <linux/bpf.h>
+
+#include "libbpf.h"
+#include "bpf_load.h"
+
+static int usage(const char *argv0)
+{
+ printf("Usage: %s cg-path filter-path [filter-id]\n", argv0);
+ return EXIT_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+ int cg_fd, ret, filter_id = 0;
+
+ if (argc < 3)
+ return usage(argv[0]);
+
+ cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
+ if (cg_fd < 0) {
+ printf("Failed to open cgroup path: '%s'\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ if (load_bpf_file(argv[2]))
+ return EXIT_FAILURE;
+
+ printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
+
+ if (argc > 3)
+ filter_id = atoi(argv[3]);
+
+ if (filter_id > prog_cnt) {
+ printf("Invalid program id; program not found in file\n");
+ return EXIT_FAILURE;
+ }
+
+ ret = bpf_prog_attach(prog_fd[filter_id], cg_fd,
+ BPF_CGROUP_INET_SOCK_CREATE);
+ if (ret < 0) {
+ printf("Failed to attach prog to cgroup: '%s'\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/samples/bpf/test_cgrp2_sock2.sh b/samples/bpf/test_cgrp2_sock2.sh
new file mode 100755
index 000000000000..891f12a0e26f
--- /dev/null
+++ b/samples/bpf/test_cgrp2_sock2.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+function config_device {
+ ip netns add at_ns0
+ ip link add veth0 type veth peer name veth0b
+ ip link set veth0b up
+ ip link set veth0 netns at_ns0
+ ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0
+ ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad
+ ip netns exec at_ns0 ip link set dev veth0 up
+ ip addr add 172.16.1.101/24 dev veth0b
+ ip addr add 2401:db00::2/64 dev veth0b nodad
+}
+
+function config_cgroup {
+ rm -rf /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2
+ mount -t cgroup2 none /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2/foo
+ echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
+}
+
+
+function attach_bpf {
+ test_cgrp2_sock2 /tmp/cgroupv2/foo sock_flags_kern.o $1
+ [ $? -ne 0 ] && exit 1
+}
+
+function cleanup {
+ ip link del veth0b
+ ip netns delete at_ns0
+ umount /tmp/cgroupv2
+ rm -rf /tmp/cgroupv2
+}
+
+cleanup 2>/dev/null
+
+set -e
+config_device
+config_cgroup
+set +e
+
+#
+# Test 1 - fail ping6
+#
+attach_bpf 0
+ping -c1 -w1 172.16.1.100
+if [ $? -ne 0 ]; then
+ echo "ping failed when it should succeed"
+ cleanup
+ exit 1
+fi
+
+ping6 -c1 -w1 2401:db00::1
+if [ $? -eq 0 ]; then
+ echo "ping6 succeeded when it should not"
+ cleanup
+ exit 1
+fi
+
+#
+# Test 2 - fail ping
+#
+attach_bpf 1
+ping6 -c1 -w1 2401:db00::1
+if [ $? -ne 0 ]; then
+ echo "ping6 failed when it should succeed"
+ cleanup
+ exit 1
+fi
+
+ping -c1 -w1 172.16.1.100
+if [ $? -eq 0 ]; then
+ echo "ping succeeded when it should not"
+ cleanup
+ exit 1
+fi
+
+cleanup
+echo
+echo "*** PASS ***"
diff --git a/samples/bpf/test_current_task_under_cgroup_user.c b/samples/bpf/test_current_task_under_cgroup_user.c
index 30b0bce884f9..95aaaa846130 100644
--- a/samples/bpf/test_current_task_under_cgroup_user.c
+++ b/samples/bpf/test_current_task_under_cgroup_user.c
@@ -11,50 +11,16 @@
#include <unistd.h>
#include "libbpf.h"
#include "bpf_load.h"
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
#include <linux/bpf.h>
-#include <sched.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <linux/limits.h>
+#include "cgroup_helpers.h"
-#define CGROUP_MOUNT_PATH "/mnt"
-#define CGROUP_PATH "/mnt/my-cgroup"
-
-#define clean_errno() (errno == 0 ? "None" : strerror(errno))
-#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
- __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
-
-static int join_cgroup(char *path)
-{
- int fd, rc = 0;
- pid_t pid = getpid();
- char cgroup_path[PATH_MAX + 1];
-
- snprintf(cgroup_path, sizeof(cgroup_path), "%s/cgroup.procs", path);
-
- fd = open(cgroup_path, O_WRONLY);
- if (fd < 0) {
- log_err("Opening Cgroup");
- return 1;
- }
-
- if (dprintf(fd, "%d\n", pid) < 0) {
- log_err("Joining Cgroup");
- rc = 1;
- }
- close(fd);
- return rc;
-}
+#define CGROUP_PATH "/my-cgroup"
int main(int argc, char **argv)
{
- char filename[256];
- int cg2, idx = 0;
pid_t remote_pid, local_pid = getpid();
+ int cg2, idx = 0, rc = 0;
+ char filename[256];
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
if (load_bpf_file(filename)) {
@@ -62,47 +28,22 @@ int main(int argc, char **argv)
return 1;
}
- /*
- * This is to avoid interfering with existing cgroups. Unfortunately,
- * most people don't have cgroupv2 enabled at this point in time.
- * It's easier to create our own mount namespace and manage it
- * ourselves.
- */
- if (unshare(CLONE_NEWNS)) {
- log_err("unshare");
- return 1;
- }
-
- if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
- log_err("mount fakeroot");
- return 1;
- }
-
- if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) {
- log_err("mount cgroup2");
- return 1;
- }
+ if (setup_cgroup_environment())
+ goto err;
- if (mkdir(CGROUP_PATH, 0777) && errno != EEXIST) {
- log_err("mkdir cgroup");
- return 1;
- }
+ cg2 = create_and_get_cgroup(CGROUP_PATH);
- cg2 = open(CGROUP_PATH, O_RDONLY);
- if (cg2 < 0) {
- log_err("opening target cgroup");
- goto cleanup_cgroup_err;
- }
+ if (!cg2)
+ goto err;
if (bpf_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
log_err("Adding target cgroup to map");
- goto cleanup_cgroup_err;
- }
- if (join_cgroup("/mnt/my-cgroup")) {
- log_err("Leaving target cgroup");
- goto cleanup_cgroup_err;
+ goto err;
}
+ if (join_cgroup(CGROUP_PATH))
+ goto err;
+
/*
* The installed helper program catched the sync call, and should
* write it to the map.
@@ -115,12 +56,12 @@ int main(int argc, char **argv)
fprintf(stderr,
"BPF Helper didn't write correct PID to map, but: %d\n",
remote_pid);
- goto leave_cgroup_err;
+ goto err;
}
/* Verify the negative scenario; leave the cgroup */
- if (join_cgroup(CGROUP_MOUNT_PATH))
- goto leave_cgroup_err;
+ if (join_cgroup("/"))
+ goto err;
remote_pid = 0;
bpf_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY);
@@ -130,16 +71,15 @@ int main(int argc, char **argv)
if (local_pid == remote_pid) {
fprintf(stderr, "BPF cgroup negative test did not work\n");
- goto cleanup_cgroup_err;
+ goto err;
}
- rmdir(CGROUP_PATH);
- return 0;
+ goto out;
+err:
+ rc = 1;
- /* Error condition, cleanup */
-leave_cgroup_err:
- join_cgroup(CGROUP_MOUNT_PATH);
-cleanup_cgroup_err:
- rmdir(CGROUP_PATH);
- return 1;
+out:
+ close(cg2);
+ cleanup_cgroup_environment();
+ return rc;
}
diff --git a/samples/bpf/test_lru_dist.c b/samples/bpf/test_lru_dist.c
new file mode 100644
index 000000000000..316230a0ed23
--- /dev/null
+++ b/samples/bpf/test_lru_dist.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#define _GNU_SOURCE
+#include <linux/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/bpf.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "libbpf.h"
+#include "bpf_util.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+static int nr_cpus;
+static unsigned long long *dist_keys;
+static unsigned int dist_key_counts;
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void __list_del_entry(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add(list, head);
+}
+
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+struct pfect_lru_node {
+ struct list_head list;
+ unsigned long long key;
+};
+
+struct pfect_lru {
+ struct list_head list;
+ struct pfect_lru_node *free_nodes;
+ unsigned int cur_size;
+ unsigned int lru_size;
+ unsigned int nr_unique;
+ unsigned int nr_misses;
+ unsigned int total;
+ int map_fd;
+};
+
+static void pfect_lru_init(struct pfect_lru *lru, unsigned int lru_size,
+ unsigned int nr_possible_elems)
+{
+ lru->map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
+ sizeof(unsigned long long),
+ sizeof(struct pfect_lru_node *),
+ nr_possible_elems, 0);
+ assert(lru->map_fd != -1);
+
+ lru->free_nodes = malloc(lru_size * sizeof(struct pfect_lru_node));
+ assert(lru->free_nodes);
+
+ INIT_LIST_HEAD(&lru->list);
+ lru->cur_size = 0;
+ lru->lru_size = lru_size;
+ lru->nr_unique = lru->nr_misses = lru->total = 0;
+}
+
+static void pfect_lru_destroy(struct pfect_lru *lru)
+{
+ close(lru->map_fd);
+ free(lru->free_nodes);
+}
+
+static int pfect_lru_lookup_or_insert(struct pfect_lru *lru,
+ unsigned long long key)
+{
+ struct pfect_lru_node *node = NULL;
+ int seen = 0;
+
+ lru->total++;
+ if (!bpf_lookup_elem(lru->map_fd, &key, &node)) {
+ if (node) {
+ list_move(&node->list, &lru->list);
+ return 1;
+ }
+ seen = 1;
+ }
+
+ if (lru->cur_size < lru->lru_size) {
+ node = &lru->free_nodes[lru->cur_size++];
+ INIT_LIST_HEAD(&node->list);
+ } else {
+ struct pfect_lru_node *null_node = NULL;
+
+ node = list_last_entry(&lru->list,
+ struct pfect_lru_node,
+ list);
+ bpf_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST);
+ }
+
+ node->key = key;
+ list_move(&node->list, &lru->list);
+
+ lru->nr_misses++;
+ if (seen) {
+ assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_EXIST));
+ } else {
+ lru->nr_unique++;
+ assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST));
+ }
+
+ return seen;
+}
+
+static unsigned int read_keys(const char *dist_file,
+ unsigned long long **keys)
+{
+ struct stat fst;
+ unsigned long long *retkeys;
+ unsigned int counts = 0;
+ int dist_fd;
+ char *b, *l;
+ int i;
+
+ dist_fd = open(dist_file, 0);
+ assert(dist_fd != -1);
+
+ assert(fstat(dist_fd, &fst) == 0);
+ b = malloc(fst.st_size);
+ assert(b);
+
+ assert(read(dist_fd, b, fst.st_size) == fst.st_size);
+ close(dist_fd);
+ for (i = 0; i < fst.st_size; i++) {
+ if (b[i] == '\n')
+ counts++;
+ }
+ counts++; /* in case the last line has no \n */
+
+ retkeys = malloc(counts * sizeof(unsigned long long));
+ assert(retkeys);
+
+ counts = 0;
+ for (l = strtok(b, "\n"); l; l = strtok(NULL, "\n"))
+ retkeys[counts++] = strtoull(l, NULL, 10);
+ free(b);
+
+ *keys = retkeys;
+
+ return counts;
+}
+
+static int create_map(int map_type, int map_flags, unsigned int size)
+{
+ int map_fd;
+
+ map_fd = bpf_create_map(map_type, sizeof(unsigned long long),
+ sizeof(unsigned long long), size, map_flags);
+
+ if (map_fd == -1)
+ perror("bpf_create_map");
+
+ return map_fd;
+}
+
+static int sched_next_online(int pid, int next_to_try)
+{
+ cpu_set_t cpuset;
+
+ if (next_to_try == nr_cpus)
+ return -1;
+
+ while (next_to_try < nr_cpus) {
+ CPU_ZERO(&cpuset);
+ CPU_SET(next_to_try++, &cpuset);
+ if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset))
+ break;
+ }
+
+ return next_to_try;
+}
+
+static void run_parallel(unsigned int tasks, void (*fn)(int i, void *data),
+ void *data)
+{
+ int next_sched_cpu = 0;
+ pid_t pid[tasks];
+ int i;
+
+ for (i = 0; i < tasks; i++) {
+ pid[i] = fork();
+ if (pid[i] == 0) {
+ next_sched_cpu = sched_next_online(0, next_sched_cpu);
+ fn(i, data);
+ exit(0);
+ } else if (pid[i] == -1) {
+ printf("couldn't spawn #%d process\n", i);
+ exit(1);
+ }
+ /* It is mostly redundant and just allow the parent
+ * process to update next_shced_cpu for the next child
+ * process
+ */
+ next_sched_cpu = sched_next_online(pid[i], next_sched_cpu);
+ }
+ for (i = 0; i < tasks; i++) {
+ int status;
+
+ assert(waitpid(pid[i], &status, 0) == pid[i]);
+ assert(status == 0);
+ }
+}
+
+static void do_test_lru_dist(int task, void *data)
+{
+ unsigned int nr_misses = 0;
+ struct pfect_lru pfect_lru;
+ unsigned long long key, value = 1234;
+ unsigned int i;
+
+ unsigned int lru_map_fd = ((unsigned int *)data)[0];
+ unsigned int lru_size = ((unsigned int *)data)[1];
+ unsigned long long key_offset = task * dist_key_counts;
+
+ pfect_lru_init(&pfect_lru, lru_size, dist_key_counts);
+
+ for (i = 0; i < dist_key_counts; i++) {
+ key = dist_keys[i] + key_offset;
+
+ pfect_lru_lookup_or_insert(&pfect_lru, key);
+
+ if (!bpf_lookup_elem(lru_map_fd, &key, &value))
+ continue;
+
+ if (bpf_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) {
+ printf("bpf_update_elem(lru_map_fd, %llu): errno:%d\n",
+ key, errno);
+ assert(0);
+ }
+
+ nr_misses++;
+ }
+
+ printf(" task:%d BPF LRU: nr_unique:%u(/%u) nr_misses:%u(/%u)\n",
+ task, pfect_lru.nr_unique, dist_key_counts, nr_misses,
+ dist_key_counts);
+ printf(" task:%d Perfect LRU: nr_unique:%u(/%u) nr_misses:%u(/%u)\n",
+ task, pfect_lru.nr_unique, pfect_lru.total,
+ pfect_lru.nr_misses, pfect_lru.total);
+
+ pfect_lru_destroy(&pfect_lru);
+ close(lru_map_fd);
+}
+
+static void test_parallel_lru_dist(int map_type, int map_flags,
+ int nr_tasks, unsigned int lru_size)
+{
+ int child_data[2];
+ int lru_map_fd;
+
+ printf("%s (map_type:%d map_flags:0x%X):\n", __func__, map_type,
+ map_flags);
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ lru_map_fd = create_map(map_type, map_flags,
+ nr_cpus * lru_size);
+ else
+ lru_map_fd = create_map(map_type, map_flags,
+ nr_tasks * lru_size);
+ assert(lru_map_fd != -1);
+
+ child_data[0] = lru_map_fd;
+ child_data[1] = lru_size;
+
+ run_parallel(nr_tasks, do_test_lru_dist, child_data);
+
+ close(lru_map_fd);
+}
+
+static void test_lru_loss0(int map_type, int map_flags)
+{
+ unsigned long long key, value[nr_cpus];
+ unsigned int old_unused_losses = 0;
+ unsigned int new_unused_losses = 0;
+ unsigned int used_losses = 0;
+ int map_fd;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ map_fd = create_map(map_type, map_flags, 900 * nr_cpus);
+ else
+ map_fd = create_map(map_type, map_flags, 900);
+
+ assert(map_fd != -1);
+
+ value[0] = 1234;
+
+ for (key = 1; key <= 1000; key++) {
+ int start_key, end_key;
+
+ assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
+
+ start_key = 101;
+ end_key = min(key, 900);
+
+ while (start_key <= end_key) {
+ bpf_lookup_elem(map_fd, &start_key, value);
+ start_key++;
+ }
+ }
+
+ for (key = 1; key <= 1000; key++) {
+ if (bpf_lookup_elem(map_fd, &key, value)) {
+ if (key <= 100)
+ old_unused_losses++;
+ else if (key <= 900)
+ used_losses++;
+ else
+ new_unused_losses++;
+ }
+ }
+
+ close(map_fd);
+
+ printf("older-elem-losses:%d(/100) active-elem-losses:%d(/800) "
+ "newer-elem-losses:%d(/100)\n",
+ old_unused_losses, used_losses, new_unused_losses);
+}
+
+static void test_lru_loss1(int map_type, int map_flags)
+{
+ unsigned long long key, value[nr_cpus];
+ int map_fd;
+ unsigned int nr_losses = 0;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ map_fd = create_map(map_type, map_flags, 1000 * nr_cpus);
+ else
+ map_fd = create_map(map_type, map_flags, 1000);
+
+ assert(map_fd != -1);
+
+ value[0] = 1234;
+
+ for (key = 1; key <= 1000; key++)
+ assert(!bpf_update_elem(map_fd, &key, value, BPF_NOEXIST));
+
+ for (key = 1; key <= 1000; key++) {
+ if (bpf_lookup_elem(map_fd, &key, value))
+ nr_losses++;
+ }
+
+ close(map_fd);
+
+ printf("nr_losses:%d(/1000)\n", nr_losses);
+}
+
+static void do_test_parallel_lru_loss(int task, void *data)
+{
+ const unsigned int nr_stable_elems = 1000;
+ const unsigned int nr_repeats = 100000;
+
+ int map_fd = *(int *)data;
+ unsigned long long stable_base;
+ unsigned long long key, value[nr_cpus];
+ unsigned long long next_ins_key;
+ unsigned int nr_losses = 0;
+ unsigned int i;
+
+ stable_base = task * nr_repeats * 2 + 1;
+ next_ins_key = stable_base;
+ value[0] = 1234;
+ for (i = 0; i < nr_stable_elems; i++) {
+ assert(bpf_update_elem(map_fd, &next_ins_key, value,
+ BPF_NOEXIST) == 0);
+ next_ins_key++;
+ }
+
+ for (i = 0; i < nr_repeats; i++) {
+ int rn;
+
+ rn = rand();
+
+ if (rn % 10) {
+ key = rn % nr_stable_elems + stable_base;
+ bpf_lookup_elem(map_fd, &key, value);
+ } else {
+ bpf_update_elem(map_fd, &next_ins_key, value,
+ BPF_NOEXIST);
+ next_ins_key++;
+ }
+ }
+
+ key = stable_base;
+ for (i = 0; i < nr_stable_elems; i++) {
+ if (bpf_lookup_elem(map_fd, &key, value))
+ nr_losses++;
+ key++;
+ }
+
+ printf(" task:%d nr_losses:%u\n", task, nr_losses);
+}
+
+static void test_parallel_lru_loss(int map_type, int map_flags, int nr_tasks)
+{
+ int map_fd;
+
+ printf("%s (map_type:%d map_flags:0x%X):\n", __func__, map_type,
+ map_flags);
+
+ /* Give 20% more than the active working set */
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ map_fd = create_map(map_type, map_flags,
+ nr_cpus * (1000 + 200));
+ else
+ map_fd = create_map(map_type, map_flags,
+ nr_tasks * (1000 + 200));
+
+ assert(map_fd != -1);
+
+ run_parallel(nr_tasks, do_test_parallel_lru_loss, &map_fd);
+
+ close(map_fd);
+}
+
+int main(int argc, char **argv)
+{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
+ const char *dist_file;
+ int nr_tasks = 1;
+ int lru_size;
+ int f;
+
+ if (argc < 4) {
+ printf("Usage: %s <dist-file> <lru-size> <nr-tasks>\n",
+ argv[0]);
+ return -1;
+ }
+
+ dist_file = argv[1];
+ lru_size = atoi(argv[2]);
+ nr_tasks = atoi(argv[3]);
+
+ setbuf(stdout, NULL);
+
+ assert(!setrlimit(RLIMIT_MEMLOCK, &r));
+
+ srand(time(NULL));
+
+ nr_cpus = bpf_num_possible_cpus();
+ assert(nr_cpus != -1);
+ printf("nr_cpus:%d\n\n", nr_cpus);
+
+ nr_tasks = min(nr_tasks, nr_cpus);
+
+ dist_key_counts = read_keys(dist_file, &dist_keys);
+ if (!dist_key_counts) {
+ printf("%s has no key\n", dist_file);
+ return -1;
+ }
+
+ for (f = 0; f < sizeof(map_flags) / sizeof(*map_flags); f++) {
+ test_lru_loss0(BPF_MAP_TYPE_LRU_HASH, map_flags[f]);
+ test_lru_loss1(BPF_MAP_TYPE_LRU_HASH, map_flags[f]);
+ test_parallel_lru_loss(BPF_MAP_TYPE_LRU_HASH, map_flags[f],
+ nr_tasks);
+ test_parallel_lru_dist(BPF_MAP_TYPE_LRU_HASH, map_flags[f],
+ nr_tasks, lru_size);
+ printf("\n");
+ }
+
+ free(dist_keys);
+
+ return 0;
+}
diff --git a/samples/bpf/test_lwt_bpf.c b/samples/bpf/test_lwt_bpf.c
new file mode 100644
index 000000000000..bacc8013436b
--- /dev/null
+++ b/samples/bpf/test_lwt_bpf.c
@@ -0,0 +1,253 @@
+/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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 <stdint.h>
+#include <stddef.h>
+#include <linux/bpf.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmpv6.h>
+#include <linux/if_ether.h>
+#include "bpf_helpers.h"
+#include <string.h>
+
+# define printk(fmt, ...) \
+ ({ \
+ char ____fmt[] = fmt; \
+ bpf_trace_printk(____fmt, sizeof(____fmt), \
+ ##__VA_ARGS__); \
+ })
+
+#define CB_MAGIC 1234
+
+/* Test: Pass all packets through */
+SEC("nop")
+int do_nop(struct __sk_buff *skb)
+{
+ return BPF_OK;
+}
+
+/* Test: Verify context information can be accessed */
+SEC("test_ctx")
+int do_test_ctx(struct __sk_buff *skb)
+{
+ skb->cb[0] = CB_MAGIC;
+ printk("len %d hash %d protocol %d\n", skb->len, skb->hash,
+ skb->protocol);
+ printk("cb %d ingress_ifindex %d ifindex %d\n", skb->cb[0],
+ skb->ingress_ifindex, skb->ifindex);
+
+ return BPF_OK;
+}
+
+/* Test: Ensure skb->cb[] buffer is cleared */
+SEC("test_cb")
+int do_test_cb(struct __sk_buff *skb)
+{
+ printk("cb0: %x cb1: %x cb2: %x\n", skb->cb[0], skb->cb[1],
+ skb->cb[2]);
+ printk("cb3: %x cb4: %x\n", skb->cb[3], skb->cb[4]);
+
+ return BPF_OK;
+}
+
+/* Test: Verify skb data can be read */
+SEC("test_data")
+int do_test_data(struct __sk_buff *skb)
+{
+ void *data = (void *)(long)skb->data;
+ void *data_end = (void *)(long)skb->data_end;
+ struct iphdr *iph = data;
+
+ if (data + sizeof(*iph) > data_end) {
+ printk("packet truncated\n");
+ return BPF_DROP;
+ }
+
+ printk("src: %x dst: %x\n", iph->saddr, iph->daddr);
+
+ return BPF_OK;
+}
+
+#define IP_CSUM_OFF offsetof(struct iphdr, check)
+#define IP_DST_OFF offsetof(struct iphdr, daddr)
+#define IP_SRC_OFF offsetof(struct iphdr, saddr)
+#define IP_PROTO_OFF offsetof(struct iphdr, protocol)
+#define TCP_CSUM_OFF offsetof(struct tcphdr, check)
+#define UDP_CSUM_OFF offsetof(struct udphdr, check)
+#define IS_PSEUDO 0x10
+
+static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip,
+ uint32_t new_ip, int rw_daddr)
+{
+ int ret, off = 0, flags = IS_PSEUDO;
+ uint8_t proto;
+
+ ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1);
+ if (ret < 0) {
+ printk("bpf_l4_csum_replace failed: %d\n", ret);
+ return BPF_DROP;
+ }
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ off = TCP_CSUM_OFF;
+ break;
+
+ case IPPROTO_UDP:
+ off = UDP_CSUM_OFF;
+ flags |= BPF_F_MARK_MANGLED_0;
+ break;
+
+ case IPPROTO_ICMPV6:
+ off = offsetof(struct icmp6hdr, icmp6_cksum);
+ break;
+ }
+
+ if (off) {
+ ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip,
+ flags | sizeof(new_ip));
+ if (ret < 0) {
+ printk("bpf_l4_csum_replace failed: %d\n");
+ return BPF_DROP;
+ }
+ }
+
+ ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
+ if (ret < 0) {
+ printk("bpf_l3_csum_replace failed: %d\n", ret);
+ return BPF_DROP;
+ }
+
+ if (rw_daddr)
+ ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0);
+ else
+ ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);
+
+ if (ret < 0) {
+ printk("bpf_skb_store_bytes() failed: %d\n", ret);
+ return BPF_DROP;
+ }
+
+ return BPF_OK;
+}
+
+/* Test: Verify skb data can be modified */
+SEC("test_rewrite")
+int do_test_rewrite(struct __sk_buff *skb)
+{
+ uint32_t old_ip, new_ip = 0x3fea8c0;
+ int ret;
+
+ ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4);
+ if (ret < 0) {
+ printk("bpf_skb_load_bytes failed: %d\n", ret);
+ return BPF_DROP;
+ }
+
+ if (old_ip == 0x2fea8c0) {
+ printk("out: rewriting from %x to %x\n", old_ip, new_ip);
+ return rewrite(skb, old_ip, new_ip, 1);
+ }
+
+ return BPF_OK;
+}
+
+static inline int __do_push_ll_and_redirect(struct __sk_buff *skb)
+{
+ uint64_t smac = SRC_MAC, dmac = DST_MAC;
+ int ret, ifindex = DST_IFINDEX;
+ struct ethhdr ehdr;
+
+ ret = bpf_skb_change_head(skb, 14, 0);
+ if (ret < 0) {
+ printk("skb_change_head() failed: %d\n", ret);
+ }
+
+ ehdr.h_proto = __constant_htons(ETH_P_IP);
+ memcpy(&ehdr.h_source, &smac, 6);
+ memcpy(&ehdr.h_dest, &dmac, 6);
+
+ ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0);
+ if (ret < 0) {
+ printk("skb_store_bytes() failed: %d\n", ret);
+ return BPF_DROP;
+ }
+
+ return bpf_redirect(ifindex, 0);
+}
+
+SEC("push_ll_and_redirect_silent")
+int do_push_ll_and_redirect_silent(struct __sk_buff *skb)
+{
+ return __do_push_ll_and_redirect(skb);
+}
+
+SEC("push_ll_and_redirect")
+int do_push_ll_and_redirect(struct __sk_buff *skb)
+{
+ int ret, ifindex = DST_IFINDEX;
+
+ ret = __do_push_ll_and_redirect(skb);
+ if (ret >= 0)
+ printk("redirected to %d\n", ifindex);
+
+ return ret;
+}
+
+static inline void __fill_garbage(struct __sk_buff *skb)
+{
+ uint64_t f = 0xFFFFFFFFFFFFFFFF;
+
+ bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0);
+ bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0);
+}
+
+SEC("fill_garbage")
+int do_fill_garbage(struct __sk_buff *skb)
+{
+ __fill_garbage(skb);
+ printk("Set initial 96 bytes of header to FF\n");
+ return BPF_OK;
+}
+
+SEC("fill_garbage_and_redirect")
+int do_fill_garbage_and_redirect(struct __sk_buff *skb)
+{
+ int ifindex = DST_IFINDEX;
+ __fill_garbage(skb);
+ printk("redirected to %d\n", ifindex);
+ return bpf_redirect(ifindex, 0);
+}
+
+/* Drop all packets */
+SEC("drop_all")
+int do_drop_all(struct __sk_buff *skb)
+{
+ printk("dropping with: %d\n", BPF_DROP);
+ return BPF_DROP;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/test_lwt_bpf.sh b/samples/bpf/test_lwt_bpf.sh
new file mode 100644
index 000000000000..a695ae268c40
--- /dev/null
+++ b/samples/bpf/test_lwt_bpf.sh
@@ -0,0 +1,399 @@
+#!/bin/bash
+
+# Uncomment to see generated bytecode
+#VERBOSE=verbose
+
+NS1=lwt_ns1
+NS2=lwt_ns2
+VETH0=tst_lwt1a
+VETH1=tst_lwt1b
+VETH2=tst_lwt2a
+VETH3=tst_lwt2b
+IPVETH0="192.168.254.1"
+IPVETH1="192.168.254.2"
+IPVETH1b="192.168.254.3"
+
+IPVETH2="192.168.111.1"
+IPVETH3="192.168.111.2"
+
+IP_LOCAL="192.168.99.1"
+
+TRACE_ROOT=/sys/kernel/debug/tracing
+
+function lookup_mac()
+{
+ set +x
+ if [ ! -z "$2" ]; then
+ MAC=$(ip netns exec $2 ip link show $1 | grep ether | awk '{print $2}')
+ else
+ MAC=$(ip link show $1 | grep ether | awk '{print $2}')
+ fi
+ MAC="${MAC//:/}"
+ echo "0x${MAC:10:2}${MAC:8:2}${MAC:6:2}${MAC:4:2}${MAC:2:2}${MAC:0:2}"
+ set -x
+}
+
+function cleanup {
+ set +ex
+ rm test_lwt_bpf.o 2> /dev/null
+ ip link del $VETH0 2> /dev/null
+ ip link del $VETH1 2> /dev/null
+ ip link del $VETH2 2> /dev/null
+ ip link del $VETH3 2> /dev/null
+ ip netns exec $NS1 killall netserver
+ ip netns delete $NS1 2> /dev/null
+ ip netns delete $NS2 2> /dev/null
+ set -ex
+}
+
+function setup_one_veth {
+ ip netns add $1
+ ip link add $2 type veth peer name $3
+ ip link set dev $2 up
+ ip addr add $4/24 dev $2
+ ip link set $3 netns $1
+ ip netns exec $1 ip link set dev $3 up
+ ip netns exec $1 ip addr add $5/24 dev $3
+
+ if [ "$6" ]; then
+ ip netns exec $1 ip addr add $6/32 dev $3
+ fi
+}
+
+function get_trace {
+ set +x
+ cat ${TRACE_ROOT}/trace | grep -v '^#'
+ set -x
+}
+
+function cleanup_routes {
+ ip route del ${IPVETH1}/32 dev $VETH0 2> /dev/null || true
+ ip route del table local local ${IP_LOCAL}/32 dev lo 2> /dev/null || true
+}
+
+function install_test {
+ cleanup_routes
+ cp /dev/null ${TRACE_ROOT}/trace
+
+ OPTS="encap bpf headroom 14 $1 obj test_lwt_bpf.o section $2 $VERBOSE"
+
+ if [ "$1" == "in" ]; then
+ ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo
+ else
+ ip route add ${IPVETH1}/32 $OPTS dev $VETH0
+ fi
+}
+
+function remove_prog {
+ if [ "$1" == "in" ]; then
+ ip route del table local local ${IP_LOCAL}/32 dev lo
+ else
+ ip route del ${IPVETH1}/32 dev $VETH0
+ fi
+}
+
+function filter_trace {
+ # Add newline to allow starting EXPECT= variables on newline
+ NL=$'\n'
+ echo "${NL}$*" | sed -e 's/^.*: : //g'
+}
+
+function expect_fail {
+ set +x
+ echo "FAIL:"
+ echo "Expected: $1"
+ echo "Got: $2"
+ set -x
+ exit 1
+}
+
+function match_trace {
+ set +x
+ RET=0
+ TRACE=$1
+ EXPECT=$2
+ GOT="$(filter_trace "$TRACE")"
+
+ [ "$GOT" != "$EXPECT" ] && {
+ expect_fail "$EXPECT" "$GOT"
+ RET=1
+ }
+ set -x
+ return $RET
+}
+
+function test_start {
+ set +x
+ echo "----------------------------------------------------------------"
+ echo "Starting test: $*"
+ echo "----------------------------------------------------------------"
+ set -x
+}
+
+function failure {
+ get_trace
+ echo "FAIL: $*"
+ exit 1
+}
+
+function test_ctx_xmit {
+ test_start "test_ctx on lwt xmit"
+ install_test xmit test_ctx
+ ping -c 3 $IPVETH1 || {
+ failure "test_ctx xmit: packets are dropped"
+ }
+ match_trace "$(get_trace)" "
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1
+ remove_prog xmit
+}
+
+function test_ctx_out {
+ test_start "test_ctx on lwt out"
+ install_test out test_ctx
+ ping -c 3 $IPVETH1 || {
+ failure "test_ctx out: packets are dropped"
+ }
+ match_trace "$(get_trace)" "
+len 84 hash 0 protocol 0
+cb 1234 ingress_ifindex 0 ifindex 0
+len 84 hash 0 protocol 0
+cb 1234 ingress_ifindex 0 ifindex 0
+len 84 hash 0 protocol 0
+cb 1234 ingress_ifindex 0 ifindex 0" || exit 1
+ remove_prog out
+}
+
+function test_ctx_in {
+ test_start "test_ctx on lwt in"
+ install_test in test_ctx
+ ping -c 3 $IP_LOCAL || {
+ failure "test_ctx out: packets are dropped"
+ }
+ # We will both request & reply packets as the packets will
+ # be from $IP_LOCAL => $IP_LOCAL
+ match_trace "$(get_trace)" "
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1
+len 84 hash 0 protocol 8
+cb 1234 ingress_ifindex 1 ifindex 1" || exit 1
+ remove_prog in
+}
+
+function test_data {
+ test_start "test_data on lwt $1"
+ install_test $1 test_data
+ ping -c 3 $IPVETH1 || {
+ failure "test_data ${1}: packets are dropped"
+ }
+ match_trace "$(get_trace)" "
+src: 1fea8c0 dst: 2fea8c0
+src: 1fea8c0 dst: 2fea8c0
+src: 1fea8c0 dst: 2fea8c0" || exit 1
+ remove_prog $1
+}
+
+function test_data_in {
+ test_start "test_data on lwt in"
+ install_test in test_data
+ ping -c 3 $IP_LOCAL || {
+ failure "test_data in: packets are dropped"
+ }
+ # We will both request & reply packets as the packets will
+ # be from $IP_LOCAL => $IP_LOCAL
+ match_trace "$(get_trace)" "
+src: 163a8c0 dst: 163a8c0
+src: 163a8c0 dst: 163a8c0
+src: 163a8c0 dst: 163a8c0
+src: 163a8c0 dst: 163a8c0
+src: 163a8c0 dst: 163a8c0
+src: 163a8c0 dst: 163a8c0" || exit 1
+ remove_prog in
+}
+
+function test_cb {
+ test_start "test_cb on lwt $1"
+ install_test $1 test_cb
+ ping -c 3 $IPVETH1 || {
+ failure "test_cb ${1}: packets are dropped"
+ }
+ match_trace "$(get_trace)" "
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0" || exit 1
+ remove_prog $1
+}
+
+function test_cb_in {
+ test_start "test_cb on lwt in"
+ install_test in test_cb
+ ping -c 3 $IP_LOCAL || {
+ failure "test_cb in: packets are dropped"
+ }
+ # We will both request & reply packets as the packets will
+ # be from $IP_LOCAL => $IP_LOCAL
+ match_trace "$(get_trace)" "
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0
+cb0: 0 cb1: 0 cb2: 0
+cb3: 0 cb4: 0" || exit 1
+ remove_prog in
+}
+
+function test_drop_all {
+ test_start "test_drop_all on lwt $1"
+ install_test $1 drop_all
+ ping -c 3 $IPVETH1 && {
+ failure "test_drop_all ${1}: Unexpected success of ping"
+ }
+ match_trace "$(get_trace)" "
+dropping with: 2
+dropping with: 2
+dropping with: 2" || exit 1
+ remove_prog $1
+}
+
+function test_drop_all_in {
+ test_start "test_drop_all on lwt in"
+ install_test in drop_all
+ ping -c 3 $IP_LOCAL && {
+ failure "test_drop_all in: Unexpected success of ping"
+ }
+ match_trace "$(get_trace)" "
+dropping with: 2
+dropping with: 2
+dropping with: 2" || exit 1
+ remove_prog in
+}
+
+function test_push_ll_and_redirect {
+ test_start "test_push_ll_and_redirect on lwt xmit"
+ install_test xmit push_ll_and_redirect
+ ping -c 3 $IPVETH1 || {
+ failure "Redirected packets appear to be dropped"
+ }
+ match_trace "$(get_trace)" "
+redirected to $DST_IFINDEX
+redirected to $DST_IFINDEX
+redirected to $DST_IFINDEX" || exit 1
+ remove_prog xmit
+}
+
+function test_no_l2_and_redirect {
+ test_start "test_no_l2_and_redirect on lwt xmit"
+ install_test xmit fill_garbage_and_redirect
+ ping -c 3 $IPVETH1 && {
+ failure "Unexpected success despite lack of L2 header"
+ }
+ match_trace "$(get_trace)" "
+redirected to $DST_IFINDEX
+redirected to $DST_IFINDEX
+redirected to $DST_IFINDEX" || exit 1
+ remove_prog xmit
+}
+
+function test_rewrite {
+ test_start "test_rewrite on lwt xmit"
+ install_test xmit test_rewrite
+ ping -c 3 $IPVETH1 || {
+ failure "Rewritten packets appear to be dropped"
+ }
+ match_trace "$(get_trace)" "
+out: rewriting from 2fea8c0 to 3fea8c0
+out: rewriting from 2fea8c0 to 3fea8c0
+out: rewriting from 2fea8c0 to 3fea8c0" || exit 1
+ remove_prog out
+}
+
+function test_fill_garbage {
+ test_start "test_fill_garbage on lwt xmit"
+ install_test xmit fill_garbage
+ ping -c 3 $IPVETH1 && {
+ failure "test_drop_all ${1}: Unexpected success of ping"
+ }
+ match_trace "$(get_trace)" "
+Set initial 96 bytes of header to FF
+Set initial 96 bytes of header to FF
+Set initial 96 bytes of header to FF" || exit 1
+ remove_prog xmit
+}
+
+function test_netperf_nop {
+ test_start "test_netperf_nop on lwt xmit"
+ install_test xmit nop
+ netperf -H $IPVETH1 -t TCP_STREAM || {
+ failure "packets appear to be dropped"
+ }
+ match_trace "$(get_trace)" ""|| exit 1
+ remove_prog xmit
+}
+
+function test_netperf_redirect {
+ test_start "test_netperf_redirect on lwt xmit"
+ install_test xmit push_ll_and_redirect_silent
+ netperf -H $IPVETH1 -t TCP_STREAM || {
+ failure "Rewritten packets appear to be dropped"
+ }
+ match_trace "$(get_trace)" ""|| exit 1
+ remove_prog xmit
+}
+
+cleanup
+setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b
+setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3
+ip netns exec $NS1 netserver
+echo 1 > ${TRACE_ROOT}/tracing_on
+
+DST_MAC=$(lookup_mac $VETH1 $NS1)
+SRC_MAC=$(lookup_mac $VETH0)
+DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex)
+
+CLANG_OPTS="-O2 -target bpf -I ../include/"
+CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX"
+clang $CLANG_OPTS -c test_lwt_bpf.c -o test_lwt_bpf.o
+
+test_ctx_xmit
+test_ctx_out
+test_ctx_in
+test_data "xmit"
+test_data "out"
+test_data_in
+test_cb "xmit"
+test_cb "out"
+test_cb_in
+test_drop_all "xmit"
+test_drop_all "out"
+test_drop_all_in
+test_rewrite
+test_push_ll_and_redirect
+test_no_l2_and_redirect
+test_fill_garbage
+test_netperf_nop
+test_netperf_redirect
+
+cleanup
+echo 0 > ${TRACE_ROOT}/tracing_on
+exit 0
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c
deleted file mode 100644
index cce2b59751eb..000000000000
--- a/samples/bpf/test_maps.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Testsuite for eBPF maps
- *
- * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
- * Copyright (c) 2016 Facebook
- *
- * This program is free software; you can redistribute 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 <stdio.h>
-#include <unistd.h>
-#include <linux/bpf.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include "libbpf.h"
-
-static int map_flags;
-
-/* sanity tests for map API */
-static void test_hashmap_sanity(int i, void *data)
-{
- long long key, next_key, value;
- int map_fd;
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
- 2, map_flags);
- if (map_fd < 0) {
- printf("failed to create hashmap '%s'\n", strerror(errno));
- exit(1);
- }
-
- key = 1;
- value = 1234;
- /* insert key=1 element */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
- value = 0;
- /* BPF_NOEXIST means: add new element if it doesn't exist */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
- /* key=1 already exists */
- errno == EEXIST);
-
- assert(bpf_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL);
-
- /* check that key=1 can be found */
- assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
-
- key = 2;
- /* check that key=2 is not found */
- assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
- /* BPF_EXIST means: update existing element */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
- /* key=2 is not there */
- errno == ENOENT);
-
- /* insert key=2 element */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
-
- /* key=1 and key=2 were inserted, check that key=0 cannot be inserted
- * due to max_entries limit
- */
- key = 0;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
- errno == E2BIG);
-
- /* update existing element, thought the map is full */
- key = 1;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
- key = 2;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
- key = 1;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
- /* check that key = 0 doesn't exist */
- key = 0;
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
- /* iterate over two elements */
- assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
- (next_key == 1 || next_key == 2));
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
- (next_key == 1 || next_key == 2));
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
- errno == ENOENT);
-
- /* delete both elements */
- key = 1;
- assert(bpf_delete_elem(map_fd, &key) == 0);
- key = 2;
- assert(bpf_delete_elem(map_fd, &key) == 0);
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
- key = 0;
- /* check that map is empty */
- assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
- errno == ENOENT);
- close(map_fd);
-}
-
-/* sanity tests for percpu map API */
-static void test_percpu_hashmap_sanity(int task, void *data)
-{
- long long key, next_key;
- int expected_key_mask = 0;
- unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- long long value[nr_cpus];
- int map_fd, i;
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
- sizeof(value[0]), 2, map_flags);
- if (map_fd < 0) {
- printf("failed to create hashmap '%s'\n", strerror(errno));
- exit(1);
- }
-
- for (i = 0; i < nr_cpus; i++)
- value[i] = i + 100;
- key = 1;
- /* insert key=1 element */
- assert(!(expected_key_mask & key));
- assert(bpf_update_elem(map_fd, &key, value, BPF_ANY) == 0);
- expected_key_mask |= key;
-
- /* BPF_NOEXIST means: add new element if it doesn't exist */
- assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
- /* key=1 already exists */
- errno == EEXIST);
-
- /* -1 is an invalid flag */
- assert(bpf_update_elem(map_fd, &key, value, -1) == -1 &&
- errno == EINVAL);
-
- /* check that key=1 can be found. value could be 0 if the lookup
- * was run from a different cpu.
- */
- value[0] = 1;
- assert(bpf_lookup_elem(map_fd, &key, value) == 0 && value[0] == 100);
-
- key = 2;
- /* check that key=2 is not found */
- assert(bpf_lookup_elem(map_fd, &key, value) == -1 && errno == ENOENT);
-
- /* BPF_EXIST means: update existing element */
- assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == -1 &&
- /* key=2 is not there */
- errno == ENOENT);
-
- /* insert key=2 element */
- assert(!(expected_key_mask & key));
- assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
- expected_key_mask |= key;
-
- /* key=1 and key=2 were inserted, check that key=0 cannot be inserted
- * due to max_entries limit
- */
- key = 0;
- assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
- errno == E2BIG);
-
- /* check that key = 0 doesn't exist */
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
- /* iterate over two elements */
- while (!bpf_get_next_key(map_fd, &key, &next_key)) {
- assert((expected_key_mask & next_key) == next_key);
- expected_key_mask &= ~next_key;
-
- assert(bpf_lookup_elem(map_fd, &next_key, value) == 0);
- for (i = 0; i < nr_cpus; i++)
- assert(value[i] == i + 100);
-
- key = next_key;
- }
- assert(errno == ENOENT);
-
- /* Update with BPF_EXIST */
- key = 1;
- assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == 0);
-
- /* delete both elements */
- key = 1;
- assert(bpf_delete_elem(map_fd, &key) == 0);
- key = 2;
- assert(bpf_delete_elem(map_fd, &key) == 0);
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
- key = 0;
- /* check that map is empty */
- assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
- errno == ENOENT);
- close(map_fd);
-}
-
-static void test_arraymap_sanity(int i, void *data)
-{
- int key, next_key, map_fd;
- long long value;
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
- 2, 0);
- if (map_fd < 0) {
- printf("failed to create arraymap '%s'\n", strerror(errno));
- exit(1);
- }
-
- key = 1;
- value = 1234;
- /* insert key=1 element */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
- value = 0;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
- errno == EEXIST);
-
- /* check that key=1 can be found */
- assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
-
- key = 0;
- /* check that key=0 is also found and zero initialized */
- assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
-
-
- /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
- * due to max_entries limit
- */
- key = 2;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
- errno == E2BIG);
-
- /* check that key = 2 doesn't exist */
- assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
- /* iterate over two elements */
- assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
- next_key == 0);
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
- next_key == 1);
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
- errno == ENOENT);
-
- /* delete shouldn't succeed */
- key = 1;
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
-
- close(map_fd);
-}
-
-static void test_percpu_arraymap_many_keys(void)
-{
- unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- unsigned nr_keys = 20000;
- long values[nr_cpus];
- int key, map_fd, i;
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
- sizeof(values[0]), nr_keys, 0);
- if (map_fd < 0) {
- printf("failed to create per-cpu arraymap '%s'\n",
- strerror(errno));
- exit(1);
- }
-
- for (i = 0; i < nr_cpus; i++)
- values[i] = i + 10;
-
- for (key = 0; key < nr_keys; key++)
- assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);
-
- for (key = 0; key < nr_keys; key++) {
- for (i = 0; i < nr_cpus; i++)
- values[i] = 0;
- assert(bpf_lookup_elem(map_fd, &key, values) == 0);
- for (i = 0; i < nr_cpus; i++)
- assert(values[i] == i + 10);
- }
-
- close(map_fd);
-}
-
-static void test_percpu_arraymap_sanity(int i, void *data)
-{
- unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- long values[nr_cpus];
- int key, next_key, map_fd;
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
- sizeof(values[0]), 2, 0);
- if (map_fd < 0) {
- printf("failed to create arraymap '%s'\n", strerror(errno));
- exit(1);
- }
-
- for (i = 0; i < nr_cpus; i++)
- values[i] = i + 100;
-
- key = 1;
- /* insert key=1 element */
- assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);
-
- values[0] = 0;
- assert(bpf_update_elem(map_fd, &key, values, BPF_NOEXIST) == -1 &&
- errno == EEXIST);
-
- /* check that key=1 can be found */
- assert(bpf_lookup_elem(map_fd, &key, values) == 0 && values[0] == 100);
-
- key = 0;
- /* check that key=0 is also found and zero initialized */
- assert(bpf_lookup_elem(map_fd, &key, values) == 0 &&
- values[0] == 0 && values[nr_cpus - 1] == 0);
-
-
- /* check that key=2 cannot be inserted due to max_entries limit */
- key = 2;
- assert(bpf_update_elem(map_fd, &key, values, BPF_EXIST) == -1 &&
- errno == E2BIG);
-
- /* check that key = 2 doesn't exist */
- assert(bpf_lookup_elem(map_fd, &key, values) == -1 && errno == ENOENT);
-
- /* iterate over two elements */
- assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
- next_key == 0);
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
- next_key == 1);
- assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
- errno == ENOENT);
-
- /* delete shouldn't succeed */
- key = 1;
- assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
-
- close(map_fd);
-}
-
-#define MAP_SIZE (32 * 1024)
-static void test_map_large(void)
-{
- struct bigkey {
- int a;
- char b[116];
- long long c;
- } key;
- int map_fd, i, value;
-
- /* allocate 4Mbyte of memory */
- map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
- MAP_SIZE, map_flags);
- if (map_fd < 0) {
- printf("failed to create large map '%s'\n", strerror(errno));
- exit(1);
- }
-
- for (i = 0; i < MAP_SIZE; i++) {
- key = (struct bigkey) {.c = i};
- value = i;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
- }
- key.c = -1;
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
- errno == E2BIG);
-
- /* iterate through all elements */
- for (i = 0; i < MAP_SIZE; i++)
- assert(bpf_get_next_key(map_fd, &key, &key) == 0);
- assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-
- key.c = 0;
- assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
- key.a = 1;
- assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
- close(map_fd);
-}
-
-/* fork N children and wait for them to complete */
-static void run_parallel(int tasks, void (*fn)(int i, void *data), void *data)
-{
- pid_t pid[tasks];
- int i;
-
- for (i = 0; i < tasks; i++) {
- pid[i] = fork();
- if (pid[i] == 0) {
- fn(i, data);
- exit(0);
- } else if (pid[i] == -1) {
- printf("couldn't spawn #%d process\n", i);
- exit(1);
- }
- }
- for (i = 0; i < tasks; i++) {
- int status;
-
- assert(waitpid(pid[i], &status, 0) == pid[i]);
- assert(status == 0);
- }
-}
-
-static void test_map_stress(void)
-{
- run_parallel(100, test_hashmap_sanity, NULL);
- run_parallel(100, test_percpu_hashmap_sanity, NULL);
- run_parallel(100, test_arraymap_sanity, NULL);
- run_parallel(100, test_percpu_arraymap_sanity, NULL);
-}
-
-#define TASKS 1024
-#define DO_UPDATE 1
-#define DO_DELETE 0
-static void do_work(int fn, void *data)
-{
- int map_fd = ((int *)data)[0];
- int do_update = ((int *)data)[1];
- int i;
- int key, value;
-
- for (i = fn; i < MAP_SIZE; i += TASKS) {
- key = value = i;
- if (do_update) {
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
- assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
- } else {
- assert(bpf_delete_elem(map_fd, &key) == 0);
- }
- }
-}
-
-static void test_map_parallel(void)
-{
- int i, map_fd, key = 0, value = 0;
- int data[2];
-
- map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
- MAP_SIZE, map_flags);
- if (map_fd < 0) {
- printf("failed to create map for parallel test '%s'\n",
- strerror(errno));
- exit(1);
- }
-
- data[0] = map_fd;
- data[1] = DO_UPDATE;
- /* use the same map_fd in children to add elements to this map
- * child_0 adds key=0, key=1024, key=2048, ...
- * child_1 adds key=1, key=1025, key=2049, ...
- * child_1023 adds key=1023, ...
- */
- run_parallel(TASKS, do_work, data);
-
- /* check that key=0 is already there */
- assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
- errno == EEXIST);
-
- /* check that all elements were inserted */
- key = -1;
- for (i = 0; i < MAP_SIZE; i++)
- assert(bpf_get_next_key(map_fd, &key, &key) == 0);
- assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-
- /* another check for all elements */
- for (i = 0; i < MAP_SIZE; i++) {
- key = MAP_SIZE - i - 1;
- assert(bpf_lookup_elem(map_fd, &key, &value) == 0 &&
- value == key);
- }
-
- /* now let's delete all elemenets in parallel */
- data[1] = DO_DELETE;
- run_parallel(TASKS, do_work, data);
-
- /* nothing should be left */
- key = -1;
- assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-}
-
-static void run_all_tests(void)
-{
- test_hashmap_sanity(0, NULL);
- test_percpu_hashmap_sanity(0, NULL);
- test_arraymap_sanity(0, NULL);
- test_percpu_arraymap_sanity(0, NULL);
- test_percpu_arraymap_many_keys();
-
- test_map_large();
- test_map_parallel();
- test_map_stress();
-}
-
-int main(void)
-{
- map_flags = 0;
- run_all_tests();
- map_flags = BPF_F_NO_PREALLOC;
- run_all_tests();
- printf("test_maps: OK\n");
- return 0;
-}
diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c
index ab5b19e68acf..3e225e331f66 100644
--- a/samples/bpf/tracex2_user.c
+++ b/samples/bpf/tracex2_user.c
@@ -4,8 +4,10 @@
#include <signal.h>
#include <linux/bpf.h>
#include <string.h>
+
#include "libbpf.h"
#include "bpf_load.h"
+#include "bpf_util.h"
#define MAX_INDEX 64
#define MAX_STARS 38
@@ -36,8 +38,8 @@ struct hist_key {
static void print_hist_for_pid(int fd, void *task)
{
+ unsigned int nr_cpus = bpf_num_possible_cpus();
struct hist_key key = {}, next_key;
- unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
long values[nr_cpus];
char starstr[MAX_STARS];
long value;
diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c
index 48716f7f0d8b..d0851cb4fa8d 100644
--- a/samples/bpf/tracex3_user.c
+++ b/samples/bpf/tracex3_user.c
@@ -11,8 +11,10 @@
#include <stdbool.h>
#include <string.h>
#include <linux/bpf.h>
+
#include "libbpf.h"
#include "bpf_load.h"
+#include "bpf_util.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@@ -20,7 +22,7 @@
static void clear_stats(int fd)
{
- unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ unsigned int nr_cpus = bpf_num_possible_cpus();
__u64 values[nr_cpus];
__u32 key;
@@ -77,7 +79,7 @@ static void print_banner(void)
static void print_hist(int fd)
{
- unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ unsigned int nr_cpus = bpf_num_possible_cpus();
__u64 total_events = 0;
long values[nr_cpus];
__u64 max_cnt = 0;
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index a5e109e398a1..5f040a0d7712 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -5,109 +5,18 @@
* License as published by the Free Software Foundation.
*/
#include <linux/bpf.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/socket.h>
#include <unistd.h>
+
#include "bpf_load.h"
+#include "bpf_util.h"
#include "libbpf.h"
-static int set_link_xdp_fd(int ifindex, int fd)
-{
- struct sockaddr_nl sa;
- int sock, seq = 0, len, ret = -1;
- char buf[4096];
- struct nlattr *nla, *nla_xdp;
- struct {
- struct nlmsghdr nh;
- struct ifinfomsg ifinfo;
- char attrbuf[64];
- } req;
- struct nlmsghdr *nh;
- struct nlmsgerr *err;
-
- memset(&sa, 0, sizeof(sa));
- sa.nl_family = AF_NETLINK;
-
- sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock < 0) {
- printf("open netlink socket: %s\n", strerror(errno));
- return -1;
- }
-
- if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
- printf("bind to netlink: %s\n", strerror(errno));
- goto cleanup;
- }
-
- memset(&req, 0, sizeof(req));
- req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
- req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.nh.nlmsg_type = RTM_SETLINK;
- req.nh.nlmsg_pid = 0;
- req.nh.nlmsg_seq = ++seq;
- req.ifinfo.ifi_family = AF_UNSPEC;
- req.ifinfo.ifi_index = ifindex;
- nla = (struct nlattr *)(((char *)&req)
- + NLMSG_ALIGN(req.nh.nlmsg_len));
- nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/;
-
- nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN);
- nla_xdp->nla_type = 1/*IFLA_XDP_FD*/;
- nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
- memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
- nla->nla_len = NLA_HDRLEN + nla_xdp->nla_len;
-
- req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
-
- if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
- printf("send to netlink: %s\n", strerror(errno));
- goto cleanup;
- }
-
- len = recv(sock, buf, sizeof(buf), 0);
- if (len < 0) {
- printf("recv from netlink: %s\n", strerror(errno));
- goto cleanup;
- }
-
- for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
- nh = NLMSG_NEXT(nh, len)) {
- if (nh->nlmsg_pid != getpid()) {
- printf("Wrong pid %d, expected %d\n",
- nh->nlmsg_pid, getpid());
- goto cleanup;
- }
- if (nh->nlmsg_seq != seq) {
- printf("Wrong seq %d, expected %d\n",
- nh->nlmsg_seq, seq);
- goto cleanup;
- }
- switch (nh->nlmsg_type) {
- case NLMSG_ERROR:
- err = (struct nlmsgerr *)NLMSG_DATA(nh);
- if (!err->error)
- continue;
- printf("nlmsg error %s\n", strerror(-err->error));
- goto cleanup;
- case NLMSG_DONE:
- break;
- }
- }
-
- ret = 0;
-
-cleanup:
- close(sock);
- return ret;
-}
-
static int ifindex;
static void int_exit(int sig)
@@ -120,7 +29,7 @@ static void int_exit(int sig)
*/
static void poll_stats(int interval)
{
- unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ unsigned int nr_cpus = bpf_num_possible_cpus();
const unsigned int nr_keys = 256;
__u64 values[nr_cpus], prev[nr_keys][nr_cpus];
__u32 key;
diff --git a/samples/bpf/xdp_tx_iptunnel_common.h b/samples/bpf/xdp_tx_iptunnel_common.h
new file mode 100644
index 000000000000..dd12cc35110f
--- /dev/null
+++ b/samples/bpf/xdp_tx_iptunnel_common.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#ifndef _SAMPLES_BPF_XDP_TX_IPTNL_COMMON_H
+#define _SAMPLES_BPF_XDP_TX_IPTNL_COMMON_H
+
+#include <linux/types.h>
+
+#define MAX_IPTNL_ENTRIES 256U
+
+struct vip {
+ union {
+ __u32 v6[4];
+ __u32 v4;
+ } daddr;
+ __u16 dport;
+ __u16 family;
+ __u8 protocol;
+};
+
+struct iptnl_info {
+ union {
+ __u32 v6[4];
+ __u32 v4;
+ } saddr;
+ union {
+ __u32 v6[4];
+ __u32 v4;
+ } daddr;
+ __u16 family;
+ __u8 dmac[6];
+};
+
+#endif
diff --git a/samples/bpf/xdp_tx_iptunnel_kern.c b/samples/bpf/xdp_tx_iptunnel_kern.c
new file mode 100644
index 000000000000..85c38ecd3a2d
--- /dev/null
+++ b/samples/bpf/xdp_tx_iptunnel_kern.c
@@ -0,0 +1,236 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program shows how to use bpf_xdp_adjust_head() by
+ * encapsulating the incoming packet in an IPv4/v6 header
+ * and then XDP_TX it out.
+ */
+#include <uapi/linux/bpf.h>
+#include <linux/in.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include "bpf_helpers.h"
+#include "xdp_tx_iptunnel_common.h"
+
+struct bpf_map_def SEC("maps") rxcnt = {
+ .type = BPF_MAP_TYPE_PERCPU_ARRAY,
+ .key_size = sizeof(__u32),
+ .value_size = sizeof(__u64),
+ .max_entries = 256,
+};
+
+struct bpf_map_def SEC("maps") vip2tnl = {
+ .type = BPF_MAP_TYPE_HASH,
+ .key_size = sizeof(struct vip),
+ .value_size = sizeof(struct iptnl_info),
+ .max_entries = MAX_IPTNL_ENTRIES,
+};
+
+static __always_inline void count_tx(u32 protocol)
+{
+ u64 *rxcnt_count;
+
+ rxcnt_count = bpf_map_lookup_elem(&rxcnt, &protocol);
+ if (rxcnt_count)
+ *rxcnt_count += 1;
+}
+
+static __always_inline int get_dport(void *trans_data, void *data_end,
+ u8 protocol)
+{
+ struct tcphdr *th;
+ struct udphdr *uh;
+
+ switch (protocol) {
+ case IPPROTO_TCP:
+ th = (struct tcphdr *)trans_data;
+ if (th + 1 > data_end)
+ return -1;
+ return th->dest;
+ case IPPROTO_UDP:
+ uh = (struct udphdr *)trans_data;
+ if (uh + 1 > data_end)
+ return -1;
+ return uh->dest;
+ default:
+ return 0;
+ }
+}
+
+static __always_inline void set_ethhdr(struct ethhdr *new_eth,
+ const struct ethhdr *old_eth,
+ const struct iptnl_info *tnl,
+ __be16 h_proto)
+{
+ memcpy(new_eth->h_source, old_eth->h_dest, sizeof(new_eth->h_source));
+ memcpy(new_eth->h_dest, tnl->dmac, sizeof(new_eth->h_dest));
+ new_eth->h_proto = h_proto;
+}
+
+static __always_inline int handle_ipv4(struct xdp_md *xdp)
+{
+ void *data_end = (void *)(long)xdp->data_end;
+ void *data = (void *)(long)xdp->data;
+ struct iptnl_info *tnl;
+ struct ethhdr *new_eth;
+ struct ethhdr *old_eth;
+ struct iphdr *iph = data + sizeof(struct ethhdr);
+ u16 *next_iph_u16;
+ u16 payload_len;
+ struct vip vip = {};
+ int dport;
+ u32 csum = 0;
+ int i;
+
+ if (iph + 1 > data_end)
+ return XDP_DROP;
+
+ dport = get_dport(iph + 1, data_end, iph->protocol);
+ if (dport == -1)
+ return XDP_DROP;
+
+ vip.protocol = iph->protocol;
+ vip.family = AF_INET;
+ vip.daddr.v4 = iph->daddr;
+ vip.dport = dport;
+ payload_len = ntohs(iph->tot_len);
+
+ tnl = bpf_map_lookup_elem(&vip2tnl, &vip);
+ /* It only does v4-in-v4 */
+ if (!tnl || tnl->family != AF_INET)
+ return XDP_PASS;
+
+ /* The vip key is found. Add an IP header and send it out */
+
+ if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(struct iphdr)))
+ return XDP_DROP;
+
+ data = (void *)(long)xdp->data;
+ data_end = (void *)(long)xdp->data_end;
+
+ new_eth = data;
+ iph = data + sizeof(*new_eth);
+ old_eth = data + sizeof(*iph);
+
+ if (new_eth + 1 > data_end ||
+ old_eth + 1 > data_end ||
+ iph + 1 > data_end)
+ return XDP_DROP;
+
+ set_ethhdr(new_eth, old_eth, tnl, htons(ETH_P_IP));
+
+ iph->version = 4;
+ iph->ihl = sizeof(*iph) >> 2;
+ iph->frag_off = 0;
+ iph->protocol = IPPROTO_IPIP;
+ iph->check = 0;
+ iph->tos = 0;
+ iph->tot_len = htons(payload_len + sizeof(*iph));
+ iph->daddr = tnl->daddr.v4;
+ iph->saddr = tnl->saddr.v4;
+ iph->ttl = 8;
+
+ next_iph_u16 = (u16 *)iph;
+#pragma clang loop unroll(full)
+ for (i = 0; i < sizeof(*iph) >> 1; i++)
+ csum += *next_iph_u16++;
+
+ iph->check = ~((csum & 0xffff) + (csum >> 16));
+
+ count_tx(vip.protocol);
+
+ return XDP_TX;
+}
+
+static __always_inline int handle_ipv6(struct xdp_md *xdp)
+{
+ void *data_end = (void *)(long)xdp->data_end;
+ void *data = (void *)(long)xdp->data;
+ struct iptnl_info *tnl;
+ struct ethhdr *new_eth;
+ struct ethhdr *old_eth;
+ struct ipv6hdr *ip6h = data + sizeof(struct ethhdr);
+ __u16 payload_len;
+ struct vip vip = {};
+ int dport;
+
+ if (ip6h + 1 > data_end)
+ return XDP_DROP;
+
+ dport = get_dport(ip6h + 1, data_end, ip6h->nexthdr);
+ if (dport == -1)
+ return XDP_DROP;
+
+ vip.protocol = ip6h->nexthdr;
+ vip.family = AF_INET6;
+ memcpy(vip.daddr.v6, ip6h->daddr.s6_addr32, sizeof(vip.daddr));
+ vip.dport = dport;
+ payload_len = ip6h->payload_len;
+
+ tnl = bpf_map_lookup_elem(&vip2tnl, &vip);
+ /* It only does v6-in-v6 */
+ if (!tnl || tnl->family != AF_INET6)
+ return XDP_PASS;
+
+ /* The vip key is found. Add an IP header and send it out */
+
+ if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(struct ipv6hdr)))
+ return XDP_DROP;
+
+ data = (void *)(long)xdp->data;
+ data_end = (void *)(long)xdp->data_end;
+
+ new_eth = data;
+ ip6h = data + sizeof(*new_eth);
+ old_eth = data + sizeof(*ip6h);
+
+ if (new_eth + 1 > data_end ||
+ old_eth + 1 > data_end ||
+ ip6h + 1 > data_end)
+ return XDP_DROP;
+
+ set_ethhdr(new_eth, old_eth, tnl, htons(ETH_P_IPV6));
+
+ ip6h->version = 6;
+ ip6h->priority = 0;
+ memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));
+ ip6h->payload_len = htons(ntohs(payload_len) + sizeof(*ip6h));
+ ip6h->nexthdr = IPPROTO_IPV6;
+ ip6h->hop_limit = 8;
+ memcpy(ip6h->saddr.s6_addr32, tnl->saddr.v6, sizeof(tnl->saddr.v6));
+ memcpy(ip6h->daddr.s6_addr32, tnl->daddr.v6, sizeof(tnl->daddr.v6));
+
+ count_tx(vip.protocol);
+
+ return XDP_TX;
+}
+
+SEC("xdp_tx_iptunnel")
+int _xdp_tx_iptunnel(struct xdp_md *xdp)
+{
+ void *data_end = (void *)(long)xdp->data_end;
+ void *data = (void *)(long)xdp->data;
+ struct ethhdr *eth = data;
+ __u16 h_proto;
+
+ if (eth + 1 > data_end)
+ return XDP_DROP;
+
+ h_proto = eth->h_proto;
+
+ if (h_proto == htons(ETH_P_IP))
+ return handle_ipv4(xdp);
+ else if (h_proto == htons(ETH_P_IPV6))
+
+ return handle_ipv6(xdp);
+ else
+ return XDP_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
new file mode 100644
index 000000000000..7a71f5c74684
--- /dev/null
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -0,0 +1,256 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute 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/bpf.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+#include <unistd.h>
+#include <time.h>
+#include "bpf_load.h"
+#include "libbpf.h"
+#include "bpf_util.h"
+#include "xdp_tx_iptunnel_common.h"
+
+#define STATS_INTERVAL_S 2U
+
+static int ifindex = -1;
+
+static void int_exit(int sig)
+{
+ if (ifindex > -1)
+ set_link_xdp_fd(ifindex, -1);
+ exit(0);
+}
+
+/* simple per-protocol drop counter
+ */
+static void poll_stats(unsigned int kill_after_s)
+{
+ const unsigned int nr_protos = 256;
+ unsigned int nr_cpus = bpf_num_possible_cpus();
+ time_t started_at = time(NULL);
+ __u64 values[nr_cpus], prev[nr_protos][nr_cpus];
+ __u32 proto;
+ int i;
+
+ memset(prev, 0, sizeof(prev));
+
+ while (!kill_after_s || time(NULL) - started_at <= kill_after_s) {
+ sleep(STATS_INTERVAL_S);
+
+ for (proto = 0; proto < nr_protos; proto++) {
+ __u64 sum = 0;
+
+ assert(bpf_lookup_elem(map_fd[0], &proto, values) == 0);
+ for (i = 0; i < nr_cpus; i++)
+ sum += (values[i] - prev[proto][i]);
+
+ if (sum)
+ printf("proto %u: sum:%10llu pkts, rate:%10llu pkts/s\n",
+ proto, sum, sum / STATS_INTERVAL_S);
+ memcpy(prev[proto], values, sizeof(values));
+ }
+ }
+}
+
+static void usage(const char *cmd)
+{
+ printf("Start a XDP prog which encapsulates incoming packets\n"
+ "in an IPv4/v6 header and XDP_TX it out. The dst <VIP:PORT>\n"
+ "is used to select packets to encapsulate\n\n");
+ printf("Usage: %s [...]\n", cmd);
+ printf(" -i <ifindex> Interface Index\n");
+ printf(" -a <vip-service-address> IPv4 or IPv6\n");
+ printf(" -p <vip-service-port> A port range (e.g. 433-444) is also allowed\n");
+ printf(" -s <source-ip> Used in the IPTunnel header\n");
+ printf(" -d <dest-ip> Used in the IPTunnel header\n");
+ printf(" -m <dest-MAC> Used in sending the IP Tunneled pkt\n");
+ printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n");
+ printf(" -P <IP-Protocol> Default is TCP\n");
+ printf(" -h Display this help\n");
+}
+
+static int parse_ipstr(const char *ipstr, unsigned int *addr)
+{
+ if (inet_pton(AF_INET6, ipstr, addr) == 1) {
+ return AF_INET6;
+ } else if (inet_pton(AF_INET, ipstr, addr) == 1) {
+ addr[1] = addr[2] = addr[3] = 0;
+ return AF_INET;
+ }
+
+ fprintf(stderr, "%s is an invalid IP\n", ipstr);
+ return AF_UNSPEC;
+}
+
+static int parse_ports(const char *port_str, int *min_port, int *max_port)
+{
+ char *end;
+ long tmp_min_port;
+ long tmp_max_port;
+
+ tmp_min_port = strtol(optarg, &end, 10);
+ if (tmp_min_port < 1 || tmp_min_port > 65535) {
+ fprintf(stderr, "Invalid port(s):%s\n", optarg);
+ return 1;
+ }
+
+ if (*end == '-') {
+ end++;
+ tmp_max_port = strtol(end, NULL, 10);
+ if (tmp_max_port < 1 || tmp_max_port > 65535) {
+ fprintf(stderr, "Invalid port(s):%s\n", optarg);
+ return 1;
+ }
+ } else {
+ tmp_max_port = tmp_min_port;
+ }
+
+ if (tmp_min_port > tmp_max_port) {
+ fprintf(stderr, "Invalid port(s):%s\n", optarg);
+ return 1;
+ }
+
+ if (tmp_max_port - tmp_min_port + 1 > MAX_IPTNL_ENTRIES) {
+ fprintf(stderr, "Port range (%s) is larger than %u\n",
+ port_str, MAX_IPTNL_ENTRIES);
+ return 1;
+ }
+ *min_port = tmp_min_port;
+ *max_port = tmp_max_port;
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned char opt_flags[256] = {};
+ unsigned int kill_after_s = 0;
+ const char *optstr = "i:a:p:s:d:m:T:P:h";
+ int min_port = 0, max_port = 0;
+ struct iptnl_info tnl = {};
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ struct vip vip = {};
+ char filename[256];
+ int opt;
+ int i;
+
+ tnl.family = AF_UNSPEC;
+ vip.protocol = IPPROTO_TCP;
+
+ for (i = 0; i < strlen(optstr); i++)
+ if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
+ opt_flags[(unsigned char)optstr[i]] = 1;
+
+ while ((opt = getopt(argc, argv, optstr)) != -1) {
+ unsigned short family;
+ unsigned int *v6;
+
+ switch (opt) {
+ case 'i':
+ ifindex = atoi(optarg);
+ break;
+ case 'a':
+ vip.family = parse_ipstr(optarg, vip.daddr.v6);
+ if (vip.family == AF_UNSPEC)
+ return 1;
+ break;
+ case 'p':
+ if (parse_ports(optarg, &min_port, &max_port))
+ return 1;
+ break;
+ case 'P':
+ vip.protocol = atoi(optarg);
+ break;
+ case 's':
+ case 'd':
+ if (opt == 's')
+ v6 = tnl.saddr.v6;
+ else
+ v6 = tnl.daddr.v6;
+
+ family = parse_ipstr(optarg, v6);
+ if (family == AF_UNSPEC)
+ return 1;
+ if (tnl.family == AF_UNSPEC) {
+ tnl.family = family;
+ } else if (tnl.family != family) {
+ fprintf(stderr,
+ "The IP version of the src and dst addresses used in the IP encapsulation does not match\n");
+ return 1;
+ }
+ break;
+ case 'm':
+ if (!ether_aton_r(optarg,
+ (struct ether_addr *)tnl.dmac)) {
+ fprintf(stderr, "Invalid mac address:%s\n",
+ optarg);
+ return 1;
+ }
+ break;
+ case 'T':
+ kill_after_s = atoi(optarg);
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ opt_flags[opt] = 0;
+ }
+
+ for (i = 0; i < strlen(optstr); i++) {
+ if (opt_flags[(unsigned int)optstr[i]]) {
+ fprintf(stderr, "Missing argument -%c\n", optstr[i]);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if (setrlimit(RLIMIT_MEMLOCK, &r)) {
+ perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
+ return 1;
+ }
+
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+ if (load_bpf_file(filename)) {
+ printf("%s", bpf_log_buf);
+ return 1;
+ }
+
+ if (!prog_fd[0]) {
+ printf("load_bpf_file: %s\n", strerror(errno));
+ return 1;
+ }
+
+ signal(SIGINT, int_exit);
+
+ while (min_port <= max_port) {
+ vip.dport = htons(min_port++);
+ if (bpf_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
+ perror("bpf_update_elem(&vip2tnl)");
+ return 1;
+ }
+ }
+
+ if (set_link_xdp_fd(ifindex, prog_fd[0]) < 0) {
+ printf("link set xdp fd failed\n");
+ return 1;
+ }
+
+ poll_stats(kill_after_s);
+
+ set_link_xdp_fd(ifindex, -1);
+
+ return 0;
+}
diff --git a/samples/vfio-mdev/Makefile b/samples/vfio-mdev/Makefile
new file mode 100644
index 000000000000..a932edbe38eb
--- /dev/null
+++ b/samples/vfio-mdev/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for mtty.c file
+#
+KERNEL_DIR:=/lib/modules/$(shell uname -r)/build
+
+obj-m:=mtty.o
+
+modules clean modules_install:
+ $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) $@
+
+default: modules
+
+module: modules
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
new file mode 100644
index 000000000000..6b633a4ea333
--- /dev/null
+++ b/samples/vfio-mdev/mtty.c
@@ -0,0 +1,1503 @@
+/*
+ * Mediated virtual PCI serial host device driver
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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.
+ *
+ * Sample driver that creates mdev device that simulates serial port over PCI
+ * card.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uuid.h>
+#include <linux/vfio.h>
+#include <linux/iommu.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/mdev.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+#include <uapi/linux/serial_reg.h>
+#include <linux/eventfd.h>
+/*
+ * #defines
+ */
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR "NVIDIA Corporation"
+
+#define MTTY_CLASS_NAME "mtty"
+
+#define MTTY_NAME "mtty"
+
+#define MTTY_STRING_LEN 16
+
+#define MTTY_CONFIG_SPACE_SIZE 0xff
+#define MTTY_IO_BAR_SIZE 0x8
+#define MTTY_MMIO_BAR_SIZE 0x100000
+
+#define STORE_LE16(addr, val) (*(u16 *)addr = val)
+#define STORE_LE32(addr, val) (*(u32 *)addr = val)
+
+#define MAX_FIFO_SIZE 16
+
+#define CIRCULAR_BUF_INC_IDX(idx) (idx = (idx + 1) & (MAX_FIFO_SIZE - 1))
+
+#define MTTY_VFIO_PCI_OFFSET_SHIFT 40
+
+#define MTTY_VFIO_PCI_OFFSET_TO_INDEX(off) (off >> MTTY_VFIO_PCI_OFFSET_SHIFT)
+#define MTTY_VFIO_PCI_INDEX_TO_OFFSET(index) \
+ ((u64)(index) << MTTY_VFIO_PCI_OFFSET_SHIFT)
+#define MTTY_VFIO_PCI_OFFSET_MASK \
+ (((u64)(1) << MTTY_VFIO_PCI_OFFSET_SHIFT) - 1)
+#define MAX_MTTYS 24
+
+/*
+ * Global Structures
+ */
+
+struct mtty_dev {
+ dev_t vd_devt;
+ struct class *vd_class;
+ struct cdev vd_cdev;
+ struct idr vd_idr;
+ struct device dev;
+} mtty_dev;
+
+struct mdev_region_info {
+ u64 start;
+ u64 phys_start;
+ u32 size;
+ u64 vfio_offset;
+};
+
+#if defined(DEBUG_REGS)
+const char *wr_reg[] = {
+ "TX",
+ "IER",
+ "FCR",
+ "LCR",
+ "MCR",
+ "LSR",
+ "MSR",
+ "SCR"
+};
+
+const char *rd_reg[] = {
+ "RX",
+ "IER",
+ "IIR",
+ "LCR",
+ "MCR",
+ "LSR",
+ "MSR",
+ "SCR"
+};
+#endif
+
+/* loop back buffer */
+struct rxtx {
+ u8 fifo[MAX_FIFO_SIZE];
+ u8 head, tail;
+ u8 count;
+};
+
+struct serial_port {
+ u8 uart_reg[8]; /* 8 registers */
+ struct rxtx rxtx; /* loop back buffer */
+ bool dlab;
+ bool overrun;
+ u16 divisor;
+ u8 fcr; /* FIFO control register */
+ u8 max_fifo_size;
+ u8 intr_trigger_level; /* interrupt trigger level */
+};
+
+/* State of each mdev device */
+struct mdev_state {
+ int irq_fd;
+ struct eventfd_ctx *intx_evtfd;
+ struct eventfd_ctx *msi_evtfd;
+ int irq_index;
+ u8 *vconfig;
+ struct mutex ops_lock;
+ struct mdev_device *mdev;
+ struct mdev_region_info region_info[VFIO_PCI_NUM_REGIONS];
+ u32 bar_mask[VFIO_PCI_NUM_REGIONS];
+ struct list_head next;
+ struct serial_port s[2];
+ struct mutex rxtx_lock;
+ struct vfio_device_info dev_info;
+ int nr_ports;
+};
+
+struct mutex mdev_list_lock;
+struct list_head mdev_devices_list;
+
+static const struct file_operations vd_fops = {
+ .owner = THIS_MODULE,
+};
+
+/* function prototypes */
+
+static int mtty_trigger_interrupt(uuid_le uuid);
+
+/* Helper functions */
+static struct mdev_state *find_mdev_state_by_uuid(uuid_le uuid)
+{
+ struct mdev_state *mds;
+
+ list_for_each_entry(mds, &mdev_devices_list, next) {
+ if (uuid_le_cmp(mds->mdev->uuid, uuid) == 0)
+ return mds;
+ }
+
+ return NULL;
+}
+
+void dump_buffer(char *buf, uint32_t count)
+{
+#if defined(DEBUG)
+ int i;
+
+ pr_info("Buffer:\n");
+ for (i = 0; i < count; i++) {
+ pr_info("%2x ", *(buf + i));
+ if ((i + 1) % 16 == 0)
+ pr_info("\n");
+ }
+#endif
+}
+
+static void mtty_create_config_space(struct mdev_state *mdev_state)
+{
+ /* PCI dev ID */
+ STORE_LE32((u32 *) &mdev_state->vconfig[0x0], 0x32534348);
+
+ /* Control: I/O+, Mem-, BusMaster- */
+ STORE_LE16((u16 *) &mdev_state->vconfig[0x4], 0x0001);
+
+ /* Status: capabilities list absent */
+ STORE_LE16((u16 *) &mdev_state->vconfig[0x6], 0x0200);
+
+ /* Rev ID */
+ mdev_state->vconfig[0x8] = 0x10;
+
+ /* programming interface class : 16550-compatible serial controller */
+ mdev_state->vconfig[0x9] = 0x02;
+
+ /* Sub class : 00 */
+ mdev_state->vconfig[0xa] = 0x00;
+
+ /* Base class : Simple Communication controllers */
+ mdev_state->vconfig[0xb] = 0x07;
+
+ /* base address registers */
+ /* BAR0: IO space */
+ STORE_LE32((u32 *) &mdev_state->vconfig[0x10], 0x000001);
+ mdev_state->bar_mask[0] = ~(MTTY_IO_BAR_SIZE) + 1;
+
+ if (mdev_state->nr_ports == 2) {
+ /* BAR1: IO space */
+ STORE_LE32((u32 *) &mdev_state->vconfig[0x14], 0x000001);
+ mdev_state->bar_mask[1] = ~(MTTY_IO_BAR_SIZE) + 1;
+ }
+
+ /* Subsystem ID */
+ STORE_LE32((u32 *) &mdev_state->vconfig[0x2c], 0x32534348);
+
+ mdev_state->vconfig[0x34] = 0x00; /* Cap Ptr */
+ mdev_state->vconfig[0x3d] = 0x01; /* interrupt pin (INTA#) */
+
+ /* Vendor specific data */
+ mdev_state->vconfig[0x40] = 0x23;
+ mdev_state->vconfig[0x43] = 0x80;
+ mdev_state->vconfig[0x44] = 0x23;
+ mdev_state->vconfig[0x48] = 0x23;
+ mdev_state->vconfig[0x4c] = 0x23;
+
+ mdev_state->vconfig[0x60] = 0x50;
+ mdev_state->vconfig[0x61] = 0x43;
+ mdev_state->vconfig[0x62] = 0x49;
+ mdev_state->vconfig[0x63] = 0x20;
+ mdev_state->vconfig[0x64] = 0x53;
+ mdev_state->vconfig[0x65] = 0x65;
+ mdev_state->vconfig[0x66] = 0x72;
+ mdev_state->vconfig[0x67] = 0x69;
+ mdev_state->vconfig[0x68] = 0x61;
+ mdev_state->vconfig[0x69] = 0x6c;
+ mdev_state->vconfig[0x6a] = 0x2f;
+ mdev_state->vconfig[0x6b] = 0x55;
+ mdev_state->vconfig[0x6c] = 0x41;
+ mdev_state->vconfig[0x6d] = 0x52;
+ mdev_state->vconfig[0x6e] = 0x54;
+}
+
+static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
+ char *buf, u32 count)
+{
+ u32 cfg_addr, bar_mask, bar_index = 0;
+
+ switch (offset) {
+ case 0x04: /* device control */
+ case 0x06: /* device status */
+ /* do nothing */
+ break;
+ case 0x3c: /* interrupt line */
+ mdev_state->vconfig[0x3c] = buf[0];
+ break;
+ case 0x3d:
+ /*
+ * Interrupt Pin is hardwired to INTA.
+ * This field is write protected by hardware
+ */
+ break;
+ case 0x10: /* BAR0 */
+ case 0x14: /* BAR1 */
+ if (offset == 0x10)
+ bar_index = 0;
+ else if (offset == 0x14)
+ bar_index = 1;
+
+ if ((mdev_state->nr_ports == 1) && (bar_index == 1)) {
+ STORE_LE32(&mdev_state->vconfig[offset], 0);
+ break;
+ }
+
+ cfg_addr = *(u32 *)buf;
+ pr_info("BAR%d addr 0x%x\n", bar_index, cfg_addr);
+
+ if (cfg_addr == 0xffffffff) {
+ bar_mask = mdev_state->bar_mask[bar_index];
+ cfg_addr = (cfg_addr & bar_mask);
+ }
+
+ cfg_addr |= (mdev_state->vconfig[offset] & 0x3ul);
+ STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
+ break;
+ case 0x18: /* BAR2 */
+ case 0x1c: /* BAR3 */
+ case 0x20: /* BAR4 */
+ STORE_LE32(&mdev_state->vconfig[offset], 0);
+ break;
+ default:
+ pr_info("PCI config write @0x%x of %d bytes not handled\n",
+ offset, count);
+ break;
+ }
+}
+
+static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
+ u16 offset, char *buf, u32 count)
+{
+ u8 data = *buf;
+
+ /* Handle data written by guest */
+ switch (offset) {
+ case UART_TX:
+ /* if DLAB set, data is LSB of divisor */
+ if (mdev_state->s[index].dlab) {
+ mdev_state->s[index].divisor |= data;
+ break;
+ }
+
+ mutex_lock(&mdev_state->rxtx_lock);
+
+ /* save in TX buffer */
+ if (mdev_state->s[index].rxtx.count <
+ mdev_state->s[index].max_fifo_size) {
+ mdev_state->s[index].rxtx.fifo[
+ mdev_state->s[index].rxtx.head] = data;
+ mdev_state->s[index].rxtx.count++;
+ CIRCULAR_BUF_INC_IDX(mdev_state->s[index].rxtx.head);
+ mdev_state->s[index].overrun = false;
+
+ /*
+ * Trigger interrupt if receive data interrupt is
+ * enabled and fifo reached trigger level
+ */
+ if ((mdev_state->s[index].uart_reg[UART_IER] &
+ UART_IER_RDI) &&
+ (mdev_state->s[index].rxtx.count ==
+ mdev_state->s[index].intr_trigger_level)) {
+ /* trigger interrupt */
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: Fifo level trigger\n",
+ index);
+#endif
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+ } else {
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: Buffer Overflow\n", index);
+#endif
+ mdev_state->s[index].overrun = true;
+
+ /*
+ * Trigger interrupt if receiver line status interrupt
+ * is enabled
+ */
+ if (mdev_state->s[index].uart_reg[UART_IER] &
+ UART_IER_RLSI)
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+ mutex_unlock(&mdev_state->rxtx_lock);
+ break;
+
+ case UART_IER:
+ /* if DLAB set, data is MSB of divisor */
+ if (mdev_state->s[index].dlab)
+ mdev_state->s[index].divisor |= (u16)data << 8;
+ else {
+ mdev_state->s[index].uart_reg[offset] = data;
+ mutex_lock(&mdev_state->rxtx_lock);
+ if ((data & UART_IER_THRI) &&
+ (mdev_state->s[index].rxtx.head ==
+ mdev_state->s[index].rxtx.tail)) {
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: IER_THRI write\n",
+ index);
+#endif
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+
+ mutex_unlock(&mdev_state->rxtx_lock);
+ }
+
+ break;
+
+ case UART_FCR:
+ mdev_state->s[index].fcr = data;
+
+ mutex_lock(&mdev_state->rxtx_lock);
+ if (data & (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)) {
+ /* clear loop back FIFO */
+ mdev_state->s[index].rxtx.count = 0;
+ mdev_state->s[index].rxtx.head = 0;
+ mdev_state->s[index].rxtx.tail = 0;
+ }
+ mutex_unlock(&mdev_state->rxtx_lock);
+
+ switch (data & UART_FCR_TRIGGER_MASK) {
+ case UART_FCR_TRIGGER_1:
+ mdev_state->s[index].intr_trigger_level = 1;
+ break;
+
+ case UART_FCR_TRIGGER_4:
+ mdev_state->s[index].intr_trigger_level = 4;
+ break;
+
+ case UART_FCR_TRIGGER_8:
+ mdev_state->s[index].intr_trigger_level = 8;
+ break;
+
+ case UART_FCR_TRIGGER_14:
+ mdev_state->s[index].intr_trigger_level = 14;
+ break;
+ }
+
+ /*
+ * Set trigger level to 1 otherwise or implement timer with
+ * timeout of 4 characters and on expiring that timer set
+ * Recevice data timeout in IIR register
+ */
+ mdev_state->s[index].intr_trigger_level = 1;
+ if (data & UART_FCR_ENABLE_FIFO)
+ mdev_state->s[index].max_fifo_size = MAX_FIFO_SIZE;
+ else {
+ mdev_state->s[index].max_fifo_size = 1;
+ mdev_state->s[index].intr_trigger_level = 1;
+ }
+
+ break;
+
+ case UART_LCR:
+ if (data & UART_LCR_DLAB) {
+ mdev_state->s[index].dlab = true;
+ mdev_state->s[index].divisor = 0;
+ } else
+ mdev_state->s[index].dlab = false;
+
+ mdev_state->s[index].uart_reg[offset] = data;
+ break;
+
+ case UART_MCR:
+ mdev_state->s[index].uart_reg[offset] = data;
+
+ if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) &&
+ (data & UART_MCR_OUT2)) {
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: MCR_OUT2 write\n", index);
+#endif
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+
+ if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) &&
+ (data & (UART_MCR_RTS | UART_MCR_DTR))) {
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: MCR RTS/DTR write\n", index);
+#endif
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+ break;
+
+ case UART_LSR:
+ case UART_MSR:
+ /* do nothing */
+ break;
+
+ case UART_SCR:
+ mdev_state->s[index].uart_reg[offset] = data;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void handle_bar_read(unsigned int index, struct mdev_state *mdev_state,
+ u16 offset, char *buf, u32 count)
+{
+ /* Handle read requests by guest */
+ switch (offset) {
+ case UART_RX:
+ /* if DLAB set, data is LSB of divisor */
+ if (mdev_state->s[index].dlab) {
+ *buf = (u8)mdev_state->s[index].divisor;
+ break;
+ }
+
+ mutex_lock(&mdev_state->rxtx_lock);
+ /* return data in tx buffer */
+ if (mdev_state->s[index].rxtx.head !=
+ mdev_state->s[index].rxtx.tail) {
+ *buf = mdev_state->s[index].rxtx.fifo[
+ mdev_state->s[index].rxtx.tail];
+ mdev_state->s[index].rxtx.count--;
+ CIRCULAR_BUF_INC_IDX(mdev_state->s[index].rxtx.tail);
+ }
+
+ if (mdev_state->s[index].rxtx.head ==
+ mdev_state->s[index].rxtx.tail) {
+ /*
+ * Trigger interrupt if tx buffer empty interrupt is
+ * enabled and fifo is empty
+ */
+#if defined(DEBUG_INTR)
+ pr_err("Serial port %d: Buffer Empty\n", index);
+#endif
+ if (mdev_state->s[index].uart_reg[UART_IER] &
+ UART_IER_THRI)
+ mtty_trigger_interrupt(mdev_state->mdev->uuid);
+ }
+ mutex_unlock(&mdev_state->rxtx_lock);
+
+ break;
+
+ case UART_IER:
+ if (mdev_state->s[index].dlab) {
+ *buf = (u8)(mdev_state->s[index].divisor >> 8);
+ break;
+ }
+ *buf = mdev_state->s[index].uart_reg[offset] & 0x0f;
+ break;
+
+ case UART_IIR:
+ {
+ u8 ier = mdev_state->s[index].uart_reg[UART_IER];
+ *buf = 0;
+
+ mutex_lock(&mdev_state->rxtx_lock);
+ /* Interrupt priority 1: Parity, overrun, framing or break */
+ if ((ier & UART_IER_RLSI) && mdev_state->s[index].overrun)
+ *buf |= UART_IIR_RLSI;
+
+ /* Interrupt priority 2: Fifo trigger level reached */
+ if ((ier & UART_IER_RDI) &&
+ (mdev_state->s[index].rxtx.count ==
+ mdev_state->s[index].intr_trigger_level))
+ *buf |= UART_IIR_RDI;
+
+ /* Interrupt priotiry 3: transmitter holding register empty */
+ if ((ier & UART_IER_THRI) &&
+ (mdev_state->s[index].rxtx.head ==
+ mdev_state->s[index].rxtx.tail))
+ *buf |= UART_IIR_THRI;
+
+ /* Interrupt priotiry 4: Modem status: CTS, DSR, RI or DCD */
+ if ((ier & UART_IER_MSI) &&
+ (mdev_state->s[index].uart_reg[UART_MCR] &
+ (UART_MCR_RTS | UART_MCR_DTR)))
+ *buf |= UART_IIR_MSI;
+
+ /* bit0: 0=> interrupt pending, 1=> no interrupt is pending */
+ if (*buf == 0)
+ *buf = UART_IIR_NO_INT;
+
+ /* set bit 6 & 7 to be 16550 compatible */
+ *buf |= 0xC0;
+ mutex_unlock(&mdev_state->rxtx_lock);
+ }
+ break;
+
+ case UART_LCR:
+ case UART_MCR:
+ *buf = mdev_state->s[index].uart_reg[offset];
+ break;
+
+ case UART_LSR:
+ {
+ u8 lsr = 0;
+
+ mutex_lock(&mdev_state->rxtx_lock);
+ /* atleast one char in FIFO */
+ if (mdev_state->s[index].rxtx.head !=
+ mdev_state->s[index].rxtx.tail)
+ lsr |= UART_LSR_DR;
+
+ /* if FIFO overrun */
+ if (mdev_state->s[index].overrun)
+ lsr |= UART_LSR_OE;
+
+ /* transmit FIFO empty and tramsitter empty */
+ if (mdev_state->s[index].rxtx.head ==
+ mdev_state->s[index].rxtx.tail)
+ lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+
+ mutex_unlock(&mdev_state->rxtx_lock);
+ *buf = lsr;
+ break;
+ }
+ case UART_MSR:
+ *buf = UART_MSR_DSR | UART_MSR_DDSR | UART_MSR_DCD;
+
+ mutex_lock(&mdev_state->rxtx_lock);
+ /* if AFE is 1 and FIFO have space, set CTS bit */
+ if (mdev_state->s[index].uart_reg[UART_MCR] &
+ UART_MCR_AFE) {
+ if (mdev_state->s[index].rxtx.count <
+ mdev_state->s[index].max_fifo_size)
+ *buf |= UART_MSR_CTS | UART_MSR_DCTS;
+ } else
+ *buf |= UART_MSR_CTS | UART_MSR_DCTS;
+ mutex_unlock(&mdev_state->rxtx_lock);
+
+ break;
+
+ case UART_SCR:
+ *buf = mdev_state->s[index].uart_reg[offset];
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void mdev_read_base(struct mdev_state *mdev_state)
+{
+ int index, pos;
+ u32 start_lo, start_hi;
+ u32 mem_type;
+
+ pos = PCI_BASE_ADDRESS_0;
+
+ for (index = 0; index <= VFIO_PCI_BAR5_REGION_INDEX; index++) {
+
+ if (!mdev_state->region_info[index].size)
+ continue;
+
+ start_lo = (*(u32 *)(mdev_state->vconfig + pos)) &
+ PCI_BASE_ADDRESS_MEM_MASK;
+ mem_type = (*(u32 *)(mdev_state->vconfig + pos)) &
+ PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+
+ switch (mem_type) {
+ case PCI_BASE_ADDRESS_MEM_TYPE_64:
+ start_hi = (*(u32 *)(mdev_state->vconfig + pos + 4));
+ pos += 4;
+ break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_32:
+ case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+ /* 1M mem BAR treated as 32-bit BAR */
+ default:
+ /* mem unknown type treated as 32-bit BAR */
+ start_hi = 0;
+ break;
+ }
+ pos += 4;
+ mdev_state->region_info[index].start = ((u64)start_hi << 32) |
+ start_lo;
+ }
+}
+
+static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
+ loff_t pos, bool is_write)
+{
+ struct mdev_state *mdev_state;
+ unsigned int index;
+ loff_t offset;
+ int ret = 0;
+
+ if (!mdev || !buf)
+ return -EINVAL;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state) {
+ pr_err("%s mdev_state not found\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ index = MTTY_VFIO_PCI_OFFSET_TO_INDEX(pos);
+ offset = pos & MTTY_VFIO_PCI_OFFSET_MASK;
+ switch (index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+
+#if defined(DEBUG)
+ pr_info("%s: PCI config space %s at offset 0x%llx\n",
+ __func__, is_write ? "write" : "read", offset);
+#endif
+ if (is_write) {
+ dump_buffer(buf, count);
+ handle_pci_cfg_write(mdev_state, offset, buf, count);
+ } else {
+ memcpy(buf, (mdev_state->vconfig + offset), count);
+ dump_buffer(buf, count);
+ }
+
+ break;
+
+ case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
+ if (!mdev_state->region_info[index].start)
+ mdev_read_base(mdev_state);
+
+ if (is_write) {
+ dump_buffer(buf, count);
+
+#if defined(DEBUG_REGS)
+ pr_info("%s: BAR%d WR @0x%llx %s val:0x%02x dlab:%d\n",
+ __func__, index, offset, wr_reg[offset],
+ (u8)*buf, mdev_state->s[index].dlab);
+#endif
+ handle_bar_write(index, mdev_state, offset, buf, count);
+ } else {
+ handle_bar_read(index, mdev_state, offset, buf, count);
+ dump_buffer(buf, count);
+
+#if defined(DEBUG_REGS)
+ pr_info("%s: BAR%d RD @0x%llx %s val:0x%02x dlab:%d\n",
+ __func__, index, offset, rd_reg[offset],
+ (u8)*buf, mdev_state->s[index].dlab);
+#endif
+ }
+ break;
+
+ default:
+ ret = -1;
+ goto accessfailed;
+ }
+
+ ret = count;
+
+
+accessfailed:
+ mutex_unlock(&mdev_state->ops_lock);
+
+ return ret;
+}
+
+int mtty_create(struct kobject *kobj, struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state;
+ char name[MTTY_STRING_LEN];
+ int nr_ports = 0, i;
+
+ if (!mdev)
+ return -EINVAL;
+
+ for (i = 0; i < 2; i++) {
+ snprintf(name, MTTY_STRING_LEN, "%s-%d",
+ dev_driver_string(mdev->parent->dev), i + 1);
+ if (!strcmp(kobj->name, name)) {
+ nr_ports = i + 1;
+ break;
+ }
+ }
+
+ if (!nr_ports)
+ return -EINVAL;
+
+ mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
+ if (mdev_state == NULL)
+ return -ENOMEM;
+
+ mdev_state->nr_ports = nr_ports;
+ mdev_state->irq_index = -1;
+ mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
+ mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE;
+ mutex_init(&mdev_state->rxtx_lock);
+ mdev_state->vconfig = kzalloc(MTTY_CONFIG_SPACE_SIZE, GFP_KERNEL);
+
+ if (mdev_state->vconfig == NULL) {
+ kfree(mdev_state);
+ return -ENOMEM;
+ }
+
+ mutex_init(&mdev_state->ops_lock);
+ mdev_state->mdev = mdev;
+ mdev_set_drvdata(mdev, mdev_state);
+
+ mtty_create_config_space(mdev_state);
+
+ mutex_lock(&mdev_list_lock);
+ list_add(&mdev_state->next, &mdev_devices_list);
+ mutex_unlock(&mdev_list_lock);
+
+ return 0;
+}
+
+int mtty_remove(struct mdev_device *mdev)
+{
+ struct mdev_state *mds, *tmp_mds;
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ int ret = -EINVAL;
+
+ mutex_lock(&mdev_list_lock);
+ list_for_each_entry_safe(mds, tmp_mds, &mdev_devices_list, next) {
+ if (mdev_state == mds) {
+ list_del(&mdev_state->next);
+ mdev_set_drvdata(mdev, NULL);
+ kfree(mdev_state->vconfig);
+ kfree(mdev_state);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&mdev_list_lock);
+
+ return ret;
+}
+
+int mtty_reset(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state;
+
+ if (!mdev)
+ return -EINVAL;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -EINVAL;
+
+ pr_info("%s: called\n", __func__);
+
+ return 0;
+}
+
+ssize_t mtty_read(struct mdev_device *mdev, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 1;
+ }
+
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+
+read_err:
+ return -EFAULT;
+}
+
+ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 1;
+ }
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+write_err:
+ return -EFAULT;
+}
+
+static int mtty_set_irqs(struct mdev_device *mdev, uint32_t flags,
+ unsigned int index, unsigned int start,
+ unsigned int count, void *data)
+{
+ int ret = 0;
+ struct mdev_state *mdev_state;
+
+ if (!mdev)
+ return -EINVAL;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -EINVAL;
+
+ mutex_lock(&mdev_state->ops_lock);
+ switch (index) {
+ case VFIO_PCI_INTX_IRQ_INDEX:
+ switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+ case VFIO_IRQ_SET_ACTION_MASK:
+ case VFIO_IRQ_SET_ACTION_UNMASK:
+ break;
+ case VFIO_IRQ_SET_ACTION_TRIGGER:
+ {
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+ pr_info("%s: disable INTx\n", __func__);
+ if (mdev_state->intx_evtfd)
+ eventfd_ctx_put(mdev_state->intx_evtfd);
+ break;
+ }
+
+ if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ int fd = *(int *)data;
+
+ if (fd > 0) {
+ struct eventfd_ctx *evt;
+
+ evt = eventfd_ctx_fdget(fd);
+ if (IS_ERR(evt)) {
+ ret = PTR_ERR(evt);
+ break;
+ }
+ mdev_state->intx_evtfd = evt;
+ mdev_state->irq_fd = fd;
+ mdev_state->irq_index = index;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case VFIO_PCI_MSI_IRQ_INDEX:
+ switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+ case VFIO_IRQ_SET_ACTION_MASK:
+ case VFIO_IRQ_SET_ACTION_UNMASK:
+ break;
+ case VFIO_IRQ_SET_ACTION_TRIGGER:
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+ if (mdev_state->msi_evtfd)
+ eventfd_ctx_put(mdev_state->msi_evtfd);
+ pr_info("%s: disable MSI\n", __func__);
+ mdev_state->irq_index = VFIO_PCI_INTX_IRQ_INDEX;
+ break;
+ }
+ if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ int fd = *(int *)data;
+ struct eventfd_ctx *evt;
+
+ if (fd <= 0)
+ break;
+
+ if (mdev_state->msi_evtfd)
+ break;
+
+ evt = eventfd_ctx_fdget(fd);
+ if (IS_ERR(evt)) {
+ ret = PTR_ERR(evt);
+ break;
+ }
+ mdev_state->msi_evtfd = evt;
+ mdev_state->irq_fd = fd;
+ mdev_state->irq_index = index;
+ }
+ break;
+ }
+ break;
+ case VFIO_PCI_MSIX_IRQ_INDEX:
+ pr_info("%s: MSIX_IRQ\n", __func__);
+ break;
+ case VFIO_PCI_ERR_IRQ_INDEX:
+ pr_info("%s: ERR_IRQ\n", __func__);
+ break;
+ case VFIO_PCI_REQ_IRQ_INDEX:
+ pr_info("%s: REQ_IRQ\n", __func__);
+ break;
+ }
+
+ mutex_unlock(&mdev_state->ops_lock);
+ return ret;
+}
+
+static int mtty_trigger_interrupt(uuid_le uuid)
+{
+ int ret = -1;
+ struct mdev_state *mdev_state;
+
+ mdev_state = find_mdev_state_by_uuid(uuid);
+
+ if (!mdev_state) {
+ pr_info("%s: mdev not found\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((mdev_state->irq_index == VFIO_PCI_MSI_IRQ_INDEX) &&
+ (!mdev_state->msi_evtfd))
+ return -EINVAL;
+ else if ((mdev_state->irq_index == VFIO_PCI_INTX_IRQ_INDEX) &&
+ (!mdev_state->intx_evtfd)) {
+ pr_info("%s: Intr eventfd not found\n", __func__);
+ return -EINVAL;
+ }
+
+ if (mdev_state->irq_index == VFIO_PCI_MSI_IRQ_INDEX)
+ ret = eventfd_signal(mdev_state->msi_evtfd, 1);
+ else
+ ret = eventfd_signal(mdev_state->intx_evtfd, 1);
+
+#if defined(DEBUG_INTR)
+ pr_info("Intx triggered\n");
+#endif
+ if (ret != 1)
+ pr_err("%s: eventfd signal failed (%d)\n", __func__, ret);
+
+ return ret;
+}
+
+int mtty_get_region_info(struct mdev_device *mdev,
+ struct vfio_region_info *region_info,
+ u16 *cap_type_id, void **cap_type)
+{
+ unsigned int size = 0;
+ struct mdev_state *mdev_state;
+ int bar_index;
+
+ if (!mdev)
+ return -EINVAL;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -EINVAL;
+
+ mutex_lock(&mdev_state->ops_lock);
+ bar_index = region_info->index;
+
+ switch (bar_index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+ size = MTTY_CONFIG_SPACE_SIZE;
+ break;
+ case VFIO_PCI_BAR0_REGION_INDEX:
+ size = MTTY_IO_BAR_SIZE;
+ break;
+ case VFIO_PCI_BAR1_REGION_INDEX:
+ if (mdev_state->nr_ports == 2)
+ size = MTTY_IO_BAR_SIZE;
+ break;
+ default:
+ size = 0;
+ break;
+ }
+
+ mdev_state->region_info[bar_index].size = size;
+ mdev_state->region_info[bar_index].vfio_offset =
+ MTTY_VFIO_PCI_INDEX_TO_OFFSET(bar_index);
+
+ region_info->size = size;
+ region_info->offset = MTTY_VFIO_PCI_INDEX_TO_OFFSET(bar_index);
+ region_info->flags = VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE;
+ mutex_unlock(&mdev_state->ops_lock);
+ return 0;
+}
+
+int mtty_get_irq_info(struct mdev_device *mdev, struct vfio_irq_info *irq_info)
+{
+ switch (irq_info->index) {
+ case VFIO_PCI_INTX_IRQ_INDEX:
+ case VFIO_PCI_MSI_IRQ_INDEX:
+ case VFIO_PCI_REQ_IRQ_INDEX:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ irq_info->flags = VFIO_IRQ_INFO_EVENTFD;
+ irq_info->count = 1;
+
+ if (irq_info->index == VFIO_PCI_INTX_IRQ_INDEX)
+ irq_info->flags |= (VFIO_IRQ_INFO_MASKABLE |
+ VFIO_IRQ_INFO_AUTOMASKED);
+ else
+ irq_info->flags |= VFIO_IRQ_INFO_NORESIZE;
+
+ return 0;
+}
+
+int mtty_get_device_info(struct mdev_device *mdev,
+ struct vfio_device_info *dev_info)
+{
+ dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
+ dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
+ dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
+
+ return 0;
+}
+
+static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ unsigned long minsz;
+ struct mdev_state *mdev_state;
+
+ if (!mdev)
+ return -EINVAL;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -ENODEV;
+
+ switch (cmd) {
+ case VFIO_DEVICE_GET_INFO:
+ {
+ struct vfio_device_info info;
+
+ minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mtty_get_device_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ memcpy(&mdev_state->dev_info, &info, sizeof(info));
+
+ return copy_to_user((void __user *)arg, &info, minsz);
+ }
+ case VFIO_DEVICE_GET_REGION_INFO:
+ {
+ struct vfio_region_info info;
+ u16 cap_type_id = 0;
+ void *cap_type = NULL;
+
+ minsz = offsetofend(struct vfio_region_info, offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mtty_get_region_info(mdev, &info, &cap_type_id,
+ &cap_type);
+ if (ret)
+ return ret;
+
+ return copy_to_user((void __user *)arg, &info, minsz);
+ }
+
+ case VFIO_DEVICE_GET_IRQ_INFO:
+ {
+ struct vfio_irq_info info;
+
+ minsz = offsetofend(struct vfio_irq_info, count);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if ((info.argsz < minsz) ||
+ (info.index >= mdev_state->dev_info.num_irqs))
+ return -EINVAL;
+
+ ret = mtty_get_irq_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ if (info.count == -1)
+ return -EINVAL;
+
+ return copy_to_user((void __user *)arg, &info, minsz);
+ }
+ case VFIO_DEVICE_SET_IRQS:
+ {
+ struct vfio_irq_set hdr;
+ u8 *data = NULL, *ptr = NULL;
+ size_t data_size = 0;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+
+ if (copy_from_user(&hdr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ ret = vfio_set_irqs_validate_and_prepare(&hdr,
+ mdev_state->dev_info.num_irqs,
+ VFIO_PCI_NUM_IRQS,
+ &data_size);
+ if (ret)
+ return ret;
+
+ if (data_size) {
+ ptr = data = memdup_user((void __user *)(arg + minsz),
+ data_size);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+ }
+
+ ret = mtty_set_irqs(mdev, hdr.flags, hdr.index, hdr.start,
+ hdr.count, data);
+
+ kfree(ptr);
+ return ret;
+ }
+ case VFIO_DEVICE_RESET:
+ return mtty_reset(mdev);
+ }
+ return -ENOTTY;
+}
+
+int mtty_open(struct mdev_device *mdev)
+{
+ pr_info("%s\n", __func__);
+ return 0;
+}
+
+void mtty_close(struct mdev_device *mdev)
+{
+ pr_info("%s\n", __func__);
+}
+
+static ssize_t
+sample_mtty_dev_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "This is phy device\n");
+}
+
+static DEVICE_ATTR_RO(sample_mtty_dev);
+
+static struct attribute *mtty_dev_attrs[] = {
+ &dev_attr_sample_mtty_dev.attr,
+ NULL,
+};
+
+static const struct attribute_group mtty_dev_group = {
+ .name = "mtty_dev",
+ .attrs = mtty_dev_attrs,
+};
+
+const struct attribute_group *mtty_dev_groups[] = {
+ &mtty_dev_group,
+ NULL,
+};
+
+static ssize_t
+sample_mdev_dev_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mdev_device *mdev = to_mdev_device(dev);
+
+ if (mdev)
+ return sprintf(buf, "This is MDEV %s\n", dev_name(&mdev->dev));
+
+ return sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR_RO(sample_mdev_dev);
+
+static struct attribute *mdev_dev_attrs[] = {
+ &dev_attr_sample_mdev_dev.attr,
+ NULL,
+};
+
+static const struct attribute_group mdev_dev_group = {
+ .name = "vendor",
+ .attrs = mdev_dev_attrs,
+};
+
+const struct attribute_group *mdev_dev_groups[] = {
+ &mdev_dev_group,
+ NULL,
+};
+
+static ssize_t
+name_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ char name[MTTY_STRING_LEN];
+ int i;
+ const char *name_str[2] = {"Single port serial", "Dual port serial"};
+
+ for (i = 0; i < 2; i++) {
+ snprintf(name, MTTY_STRING_LEN, "%s-%d",
+ dev_driver_string(dev), i + 1);
+ if (!strcmp(kobj->name, name))
+ return sprintf(buf, "%s\n", name_str[i]);
+ }
+
+ return -EINVAL;
+}
+
+MDEV_TYPE_ATTR_RO(name);
+
+static ssize_t
+available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ char name[MTTY_STRING_LEN];
+ int i;
+ struct mdev_state *mds;
+ int ports = 0, used = 0;
+
+ for (i = 0; i < 2; i++) {
+ snprintf(name, MTTY_STRING_LEN, "%s-%d",
+ dev_driver_string(dev), i + 1);
+ if (!strcmp(kobj->name, name)) {
+ ports = i + 1;
+ break;
+ }
+ }
+
+ if (!ports)
+ return -EINVAL;
+
+ list_for_each_entry(mds, &mdev_devices_list, next)
+ used += mds->nr_ports;
+
+ return sprintf(buf, "%d\n", (MAX_MTTYS - used)/ports);
+}
+
+MDEV_TYPE_ATTR_RO(available_instances);
+
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
+}
+
+MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *mdev_types_attrs[] = {
+ &mdev_type_attr_name.attr,
+ &mdev_type_attr_device_api.attr,
+ &mdev_type_attr_available_instances.attr,
+ NULL,
+};
+
+static struct attribute_group mdev_type_group1 = {
+ .name = "1",
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group mdev_type_group2 = {
+ .name = "2",
+ .attrs = mdev_types_attrs,
+};
+
+struct attribute_group *mdev_type_groups[] = {
+ &mdev_type_group1,
+ &mdev_type_group2,
+ NULL,
+};
+
+struct parent_ops mdev_fops = {
+ .owner = THIS_MODULE,
+ .dev_attr_groups = mtty_dev_groups,
+ .mdev_attr_groups = mdev_dev_groups,
+ .supported_type_groups = mdev_type_groups,
+ .create = mtty_create,
+ .remove = mtty_remove,
+ .open = mtty_open,
+ .release = mtty_close,
+ .read = mtty_read,
+ .write = mtty_write,
+ .ioctl = mtty_ioctl,
+};
+
+static void mtty_device_release(struct device *dev)
+{
+ dev_dbg(dev, "mtty: released\n");
+}
+
+static int __init mtty_dev_init(void)
+{
+ int ret = 0;
+
+ pr_info("mtty_dev: %s\n", __func__);
+
+ memset(&mtty_dev, 0, sizeof(mtty_dev));
+
+ idr_init(&mtty_dev.vd_idr);
+
+ ret = alloc_chrdev_region(&mtty_dev.vd_devt, 0, MINORMASK, MTTY_NAME);
+
+ if (ret < 0) {
+ pr_err("Error: failed to register mtty_dev, err:%d\n", ret);
+ return ret;
+ }
+
+ cdev_init(&mtty_dev.vd_cdev, &vd_fops);
+ cdev_add(&mtty_dev.vd_cdev, mtty_dev.vd_devt, MINORMASK);
+
+ pr_info("major_number:%d\n", MAJOR(mtty_dev.vd_devt));
+
+ mtty_dev.vd_class = class_create(THIS_MODULE, MTTY_CLASS_NAME);
+
+ if (IS_ERR(mtty_dev.vd_class)) {
+ pr_err("Error: failed to register mtty_dev class\n");
+ goto failed1;
+ }
+
+ mtty_dev.dev.class = mtty_dev.vd_class;
+ mtty_dev.dev.release = mtty_device_release;
+ dev_set_name(&mtty_dev.dev, "%s", MTTY_NAME);
+
+ ret = device_register(&mtty_dev.dev);
+ if (ret)
+ goto failed2;
+
+ if (mdev_register_device(&mtty_dev.dev, &mdev_fops) != 0)
+ goto failed3;
+
+ mutex_init(&mdev_list_lock);
+ INIT_LIST_HEAD(&mdev_devices_list);
+
+ goto all_done;
+
+failed3:
+
+ device_unregister(&mtty_dev.dev);
+failed2:
+ class_destroy(mtty_dev.vd_class);
+
+failed1:
+ cdev_del(&mtty_dev.vd_cdev);
+ unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK);
+
+all_done:
+ return ret;
+}
+
+static void __exit mtty_dev_exit(void)
+{
+ mtty_dev.dev.bus = NULL;
+ mdev_unregister_device(&mtty_dev.dev);
+
+ device_unregister(&mtty_dev.dev);
+ idr_destroy(&mtty_dev.vd_idr);
+ cdev_del(&mtty_dev.vd_cdev);
+ unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK);
+ class_destroy(mtty_dev.vd_class);
+ mtty_dev.vd_class = NULL;
+ pr_info("mtty_dev: Unloaded!\n");
+}
+
+module_init(mtty_dev_init)
+module_exit(mtty_dev_exit)
+
+MODULE_LICENSE("GPL v2");
+MODULE_INFO(supported, "Test driver that simulate serial port over PCI");
+MODULE_VERSION(VERSION_STRING);
+MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 37323b0df374..9576775a86f6 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -28,4 +28,6 @@ else
CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
endif
endif
+
+CFLAGS_KASAN += $(call cc-option, -fsanitize-address-use-after-scope)
endif
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index d9ff038c1b28..a27677146410 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -16,19 +16,22 @@ if len(sys.argv) != 3:
sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0])
sys.exit(-1)
+re_NUMBER = re.compile(r'\.[0-9]+')
+
def getsizes(file):
sym = {}
- for l in os.popen("nm --size-sort " + file).readlines():
- size, type, name = l[:-1].split()
- if type in "tTdDbBrR":
- # strip generated symbols
- if name.startswith("__mod_"): continue
- if name.startswith("SyS_"): continue
- if name.startswith("compat_SyS_"): continue
- if name == "linux_banner": continue
- # statics and some other optimizations adds random .NUMBER
- name = re.sub(r'\.[0-9]+', '', name)
- sym[name] = sym.get(name, 0) + int(size, 16)
+ with os.popen("nm --size-sort " + file) as f:
+ for line in f:
+ size, type, name = line.split()
+ if type in "tTdDbBrR":
+ # strip generated symbols
+ if name.startswith("__mod_"): continue
+ if name.startswith("SyS_"): continue
+ if name.startswith("compat_SyS_"): continue
+ if name == "linux_banner": continue
+ # statics and some other optimizations adds random .NUMBER
+ name = re_NUMBER.sub('', name)
+ sym[name] = sym.get(name, 0) + int(size, 16)
return sym
old = getsizes(sys.argv[1])
diff --git a/scripts/check_00index.sh b/scripts/check_00index.sh
new file mode 100755
index 000000000000..6ac9527aeddb
--- /dev/null
+++ b/scripts/check_00index.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+cd Documentation/
+
+# Check entries that should be removed
+
+obsolete=""
+for i in $(tail -n +12 00-INDEX |grep -E '^[a-zA-Z0-9]+'); do
+ if [ ! -e $i ]; then
+ obsolete="$obsolete $i"
+ fi
+done
+
+# Check directory entries that should be added
+search=""
+dir=""
+for i in $(find . -maxdepth 1 -type d); do
+ if [ "$i" != "." ]; then
+ new=$(echo $i|perl -ne 's,./(.*),$1/,; print $_')
+ search="$search $new"
+ fi
+done
+
+for i in $search; do
+ if [ "$(grep -P "^$i" 00-INDEX)" == "" ]; then
+ dir="$dir $i"
+ fi
+done
+
+# Check file entries that should be added
+search=""
+file=""
+for i in $(find . -maxdepth 1 -type f); do
+ if [ "$i" != "./.gitignore" ]; then
+ new=$(echo $i|perl -ne 's,./(.*),$1,; print $_')
+ search="$search $new"
+ fi
+done
+
+for i in $search; do
+ if [ "$(grep -P "^$i\$" 00-INDEX)" == "" ]; then
+ file="$file $i"
+ fi
+done
+
+# Output its findings
+
+echo -e "Documentation/00-INDEX check results:\n"
+
+if [ "$obsolete" != "" ]; then
+ echo -e "- Should remove those entries:\n\t$obsolete\n"
+else
+ echo -e "- No obsolete entries\n"
+fi
+
+if [ "$dir" != "" ]; then
+ echo -e "- Should document those directories:\n\t$dir\n"
+else
+ echo -e "- No new directories to add\n"
+fi
+
+if [ "$file" != "" ]; then
+ echo -e "- Should document those files:\n\t$file"
+else
+ echo "- No new files to add"
+fi
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index a8368d1c4348..fd3556b2a5d1 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -761,7 +761,7 @@ sub seed_camelcase_file {
sub is_maintained_obsolete {
my ($filename) = @_;
- return 0 if (!(-e "$root/scripts/get_maintainer.pl"));
+ return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
@@ -2187,7 +2187,7 @@ sub process {
if ($rawline=~/^\+\+\+\s+(\S+)/) {
$setup_docs = 0;
- if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
+ if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) {
$setup_docs = 1;
}
#next;
@@ -2589,6 +2589,7 @@ sub process {
$line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
(defined($1) || defined($2))))) {
+ $is_patch = 1;
$reported_maintainer_file = 1;
WARN("FILE_PATH_CHANGES",
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
@@ -2601,20 +2602,6 @@ sub process {
$herecurr) if (!$emitted_corrupt++);
}
-# Check for absolute kernel paths.
- if ($tree) {
- while ($line =~ m{(?:^|\s)(/\S*)}g) {
- my $file = $1;
-
- if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
- check_absolute_file($1, $herecurr)) {
- #
- } else {
- check_absolute_file($file, $herecurr);
- }
- }
- }
-
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
$rawline !~ m/^$UTF8*$/) {
@@ -2652,6 +2639,20 @@ sub process {
"8-bit UTF-8 used in possible commit log\n" . $herecurr);
}
+# Check for absolute kernel paths in commit message
+ if ($tree && $in_commit_log) {
+ while ($line =~ m{(?:^|\s)(/\S*)}g) {
+ my $file = $1;
+
+ if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
+ check_absolute_file($1, $herecurr)) {
+ #
+ } else {
+ check_absolute_file($file, $herecurr);
+ }
+ }
+ }
+
# Check for various typo / spelling mistakes
if (defined($misspellings) &&
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
@@ -2805,7 +2806,7 @@ sub process {
}
# check we are in a valid source file if not then ignore this hunk
- next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/);
+ next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
# line length limit (with some exclusions)
#
@@ -3440,6 +3441,18 @@ sub process {
#ignore lines not being added
next if ($line =~ /^[^\+]/);
+# check for dereferences that span multiple lines
+ if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
+ $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
+ $prevline =~ /($Lval\s*(?:\.|->))\s*$/;
+ my $ref = $1;
+ $line =~ /^.\s*($Lval)/;
+ $ref .= $1;
+ $ref =~ s/\s//g;
+ WARN("MULTILINE_DEREFERENCE",
+ "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev);
+ }
+
# check for declarations of signed or unsigned without int
while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
my $type = $1;
@@ -5102,7 +5115,7 @@ sub process {
my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
WARN("VOLATILE",
- "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
+ "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
}
# Check for user-visible strings broken across lines, which breaks the ability
@@ -5548,8 +5561,9 @@ sub process {
"Using weak declarations can have unintended link defects\n" . $herecurr);
}
-# check for c99 types like uint8_t used outside of uapi/
+# check for c99 types like uint8_t used outside of uapi/ and tools/
if ($realfile !~ m@\binclude/uapi/@ &&
+ $realfile !~ m@\btools/@ &&
$line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
my $type = $1;
if ($type =~ /\b($typeC99Typedefs)\b/) {
@@ -5817,7 +5831,7 @@ sub process {
if (!grep(/$name/, @setup_docs)) {
CHK("UNDOCUMENTED_SETUP",
- "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+ "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr);
}
}
@@ -5925,7 +5939,7 @@ sub process {
}
if (!$has_break && $has_statement) {
WARN("MISSING_BREAK",
- "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr);
+ "Possible switch case/default not preceded by break or fallthrough comment\n" . $herecurr);
}
}
@@ -6076,6 +6090,12 @@ sub process {
}
}
+# check for mutex_trylock_recursive usage
+ if ($line =~ /mutex_trylock_recursive/) {
+ ERROR("LOCKING",
+ "recursive locking is bad, do not use this ever.\n" . $herecurr);
+ }
+
# check for lockdep_set_novalidate_class
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index c332684e1b5a..5206d99ddeb8 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -139,7 +139,8 @@ handle_line() {
while read line; do
# Let's see if we have an address in the line
- if [[ $line =~ \[\<([^]]+)\>\] ]]; then
+ if [[ $line =~ \[\<([^]]+)\>\] ]] ||
+ [[ $line =~ [^+\ ]+\+0x[0-9a-f]+/0x[0-9a-f]+ ]]; then
# Translate address to line numbers
handle_line "$line"
# Is it a code line?
diff --git a/scripts/faddr2line b/scripts/faddr2line
index 450b33257339..29df825d375c 100755
--- a/scripts/faddr2line
+++ b/scripts/faddr2line
@@ -105,9 +105,18 @@ __faddr2line() {
# In rare cases there might be duplicates.
while read symbol; do
local fields=($symbol)
- local sym_base=0x${fields[1]}
- local sym_size=${fields[2]}
- local sym_type=${fields[3]}
+ local sym_base=0x${fields[0]}
+ local sym_type=${fields[1]}
+ local sym_end=0x${fields[3]}
+
+ # calculate the size
+ local sym_size=$(($sym_end - $sym_base))
+ if [[ -z $sym_size ]] || [[ $sym_size -le 0 ]]; then
+ warn "bad symbol size: base: $sym_base end: $sym_end"
+ DONE=1
+ return
+ fi
+ sym_size=0x$(printf %x $sym_size)
# calculate the address
local addr=$(($sym_base + $offset))
@@ -116,26 +125,26 @@ __faddr2line() {
DONE=1
return
fi
- local hexaddr=0x$(printf %x $addr)
+ addr=0x$(printf %x $addr)
# weed out non-function symbols
- if [[ $sym_type != "FUNC" ]]; then
+ if [[ $sym_type != t ]] && [[ $sym_type != T ]]; then
[[ $print_warnings = 1 ]] &&
- echo "skipping $func address at $hexaddr due to non-function symbol"
+ echo "skipping $func address at $addr due to non-function symbol of type '$sym_type'"
continue
fi
# if the user provided a size, make sure it matches the symbol's size
if [[ -n $size ]] && [[ $size -ne $sym_size ]]; then
[[ $print_warnings = 1 ]] &&
- echo "skipping $func address at $hexaddr due to size mismatch ($size != $sym_size)"
+ echo "skipping $func address at $addr due to size mismatch ($size != $sym_size)"
continue;
fi
# make sure the provided offset is within the symbol's range
if [[ $offset -gt $sym_size ]]; then
[[ $print_warnings = 1 ]] &&
- echo "skipping $func address at $hexaddr due to size mismatch ($offset > $sym_size)"
+ echo "skipping $func address at $addr due to size mismatch ($offset > $sym_size)"
continue
fi
@@ -143,12 +152,12 @@ __faddr2line() {
[[ $FIRST = 0 ]] && echo
FIRST=0
- local hexsize=0x$(printf %x $sym_size)
- echo "$func+$offset/$hexsize:"
- addr2line -fpie $objfile $hexaddr | sed "s; $dir_prefix\(\./\)*; ;"
+ # pass real address to addr2line
+ echo "$func+$offset/$sym_size:"
+ addr2line -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;"
DONE=1
- done < <(readelf -sW $objfile | awk -v f=$func '$8 == f {print}')
+ done < <(nm -n $objfile | awk -v fn=$func '$3 == fn { found=1; line=$0; start=$1; next } found == 1 { found=0; print line, $1 }')
}
[[ $# -lt 2 ]] && usage
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index aed4511f0304..633f2dd3de27 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -49,6 +49,7 @@ my $scm = 0;
my $web = 0;
my $subsystem = 0;
my $status = 0;
+my $letters = "";
my $keywords = 1;
my $sections = 0;
my $file_emails = 0;
@@ -241,6 +242,7 @@ if (!GetOptions(
'status!' => \$status,
'scm!' => \$scm,
'web!' => \$web,
+ 'letters=s' => \$letters,
'pattern-depth=i' => \$pattern_depth,
'k|keywords!' => \$keywords,
'sections!' => \$sections,
@@ -271,7 +273,8 @@ $output_multiline = 0 if ($output_separator ne ", ");
$output_rolestats = 1 if ($interactive);
$output_roles = 1 if ($output_rolestats);
-if ($sections) {
+if ($sections || $letters ne "") {
+ $sections = 1;
$email = 0;
$email_list = 0;
$scm = 0;
@@ -682,8 +685,10 @@ sub get_maintainers {
$line =~ s/\\\./\./g; ##Convert \. to .
$line =~ s/\.\*/\*/g; ##Convert .* to *
}
- $line =~ s/^([A-Z]):/$1:\t/g;
- print("$line\n");
+ my $count = $line =~ s/^([A-Z]):/$1:\t/g;
+ if ($letters eq "" || (!$count || $letters =~ /$1/i)) {
+ print("$line\n");
+ }
}
print("\n");
}
@@ -814,6 +819,7 @@ Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
--keywords => scan patch for keywords (default: $keywords)
--sections => print all of the subsystem sections with pattern matches
+ --letters => print all matching 'letter' types from all matching sections
--mailmap => use .mailmap file (default: $email_use_mailmap)
--version => show version
--help => show this help information
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 973b6f733368..a73f762c48d6 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -85,6 +85,7 @@ struct symbol {
struct property *prop;
struct expr_value dir_dep;
struct expr_value rev_dep;
+ struct expr_value implied;
};
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
@@ -136,6 +137,7 @@ enum prop_type {
P_DEFAULT, /* default y */
P_CHOICE, /* choice value */
P_SELECT, /* select BAR */
+ P_IMPLY, /* imply BAR */
P_RANGE, /* range 7..100 (for a symbol) */
P_ENV, /* value from environment variable */
P_SYMBOL, /* where a symbol is defined */
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index aed678e8a777..e9357931b47d 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -233,6 +233,8 @@ static void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
+ char *use;
+
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
@@ -252,18 +254,20 @@ static void sym_check_prop(struct symbol *sym)
}
break;
case P_SELECT:
+ case P_IMPLY:
+ use = prop->type == P_SELECT ? "select" : "imply";
sym2 = prop_get_symbol(prop);
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
prop_warn(prop,
- "config symbol '%s' uses select, but is "
- "not boolean or tristate", sym->name);
+ "config symbol '%s' uses %s, but is "
+ "not boolean or tristate", sym->name, use);
else if (sym2->type != S_UNKNOWN &&
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
prop_warn(prop,
- "'%s' has wrong type. 'select' only "
+ "'%s' has wrong type. '%s' only "
"accept arguments of boolean and "
- "tristate type", sym2->name);
+ "tristate type", sym2->name, use);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
@@ -333,6 +337,10 @@ void menu_finalize(struct menu *parent)
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ } else if (prop->type == P_IMPLY) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->implied.expr = expr_alloc_or(es->implied.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
}
}
@@ -612,13 +620,30 @@ static struct property *get_symbol_prop(struct symbol *sym)
return prop;
}
+static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
+ enum prop_type tok, const char *prefix)
+{
+ bool hit = false;
+ struct property *prop;
+
+ for_all_properties(sym, prop, tok) {
+ if (!hit) {
+ str_append(r, prefix);
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
+ }
+ if (hit)
+ str_append(r, "\n");
+}
+
/*
* head is optional and may be NULL
*/
static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
- bool hit;
struct property *prop;
if (sym && sym->name) {
@@ -648,22 +673,20 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
}
}
- hit = false;
- for_all_properties(sym, prop, P_SELECT) {
- if (!hit) {
- str_append(r, " Selects: ");
- hit = true;
- } else
- str_printf(r, " && ");
- expr_gstr_print(prop->expr, r);
- }
- if (hit)
- str_append(r, "\n");
+ get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
if (sym->rev_dep.expr) {
str_append(r, _(" Selected by: "));
expr_gstr_print(sym->rev_dep.expr, r);
str_append(r, "\n");
}
+
+ get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
+ if (sym->implied.expr) {
+ str_append(r, _(" Implied by: "));
+ expr_gstr_print(sym->implied.expr, r);
+ str_append(r, "\n");
+ }
+
str_append(r, "\n\n");
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 2432298487fb..20136ffefb23 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -258,6 +258,15 @@ static void sym_calc_visibility(struct symbol *sym)
sym->rev_dep.tri = tri;
sym_set_changed(sym);
}
+ tri = no;
+ if (sym->implied.expr && sym->dir_dep.tri != no)
+ tri = expr_calc_value(sym->implied.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->implied.tri != tri) {
+ sym->implied.tri = tri;
+ sym_set_changed(sym);
+ }
}
/*
@@ -397,6 +406,10 @@ void sym_calc_value(struct symbol *sym)
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
prop->visible.tri);
}
+ if (sym->implied.tri != no) {
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
+ }
}
calc_newval:
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
@@ -413,7 +426,8 @@ void sym_calc_value(struct symbol *sym)
}
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
- if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ if (newval.tri == mod &&
+ (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
newval.tri = yes;
break;
case S_STRING:
@@ -498,6 +512,8 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
+ if (sym->implied.tri == yes && val == mod)
+ return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
@@ -750,6 +766,10 @@ const char *sym_get_string_default(struct symbol *sym)
if (sym->type == S_BOOLEAN && val == mod)
val = yes;
+ /* adjust the default value if this symbol is implied by another */
+ if (val < sym->implied.tri)
+ val = sym->implied.tri;
+
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
@@ -1352,6 +1372,8 @@ const char *prop_get_type_name(enum prop_type type)
return "choice";
case P_SELECT:
return "select";
+ case P_IMPLY:
+ return "imply";
case P_RANGE:
return "range";
case P_SYMBOL:
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index ac498f01b449..ead02edec936 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -38,6 +38,7 @@ int, T_TYPE, TF_COMMAND, S_INT
hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING
select, T_SELECT, TF_COMMAND
+imply, T_IMPLY, TF_COMMAND
range, T_RANGE, TF_COMMAND
visible, T_VISIBLE, TF_COMMAND
option, T_OPTION, TF_COMMAND
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 360a62df2b5e..d51b15de074a 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -55,10 +55,10 @@ kconf_id_hash (register const char *str, register unsigned int len)
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 5, 25, 25,
+ 73, 73, 73, 73, 73, 73, 73, 10, 25, 25,
0, 0, 0, 5, 0, 0, 73, 73, 5, 0,
10, 5, 45, 73, 20, 20, 0, 15, 15, 73,
- 20, 5, 73, 73, 73, 73, 73, 73, 73, 73,
+ 20, 0, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
@@ -120,6 +120,7 @@ struct kconf_id_strings_t
char kconf_id_strings_str43[sizeof("hex")];
char kconf_id_strings_str46[sizeof("config")];
char kconf_id_strings_str47[sizeof("boolean")];
+ char kconf_id_strings_str50[sizeof("imply")];
char kconf_id_strings_str51[sizeof("string")];
char kconf_id_strings_str54[sizeof("help")];
char kconf_id_strings_str56[sizeof("prompt")];
@@ -157,6 +158,7 @@ static const struct kconf_id_strings_t kconf_id_strings_contents =
"hex",
"config",
"boolean",
+ "imply",
"string",
"help",
"prompt",
@@ -174,7 +176,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 34,
+ TOTAL_KEYWORDS = 35,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2,
@@ -205,15 +207,15 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE},
#line 36 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
-#line 46 "scripts/kconfig/zconf.gperf"
+#line 47 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION},
{-1}, {-1},
-#line 44 "scripts/kconfig/zconf.gperf"
+#line 45 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM},
#line 29 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND},
{-1}, {-1},
-#line 43 "scripts/kconfig/zconf.gperf"
+#line 44 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND},
#line 17 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND},
@@ -223,9 +225,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
#line 23 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND},
{-1},
-#line 45 "scripts/kconfig/zconf.gperf"
+#line 46 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
-#line 48 "scripts/kconfig/zconf.gperf"
+#line 49 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPT_ALLNOCONFIG_Y,TF_OPTION},
#line 16 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
@@ -234,10 +236,10 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
#line 21 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
-#line 47 "scripts/kconfig/zconf.gperf"
+#line 48 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION},
{-1},
-#line 41 "scripts/kconfig/zconf.gperf"
+#line 42 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND},
#line 19 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND},
@@ -247,7 +249,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{-1},
#line 18 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND},
-#line 42 "scripts/kconfig/zconf.gperf"
+#line 43 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND},
#line 38 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX},
@@ -256,7 +258,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND},
#line 35 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
- {-1}, {-1}, {-1},
+ {-1}, {-1},
+#line 41 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str50, T_IMPLY, TF_COMMAND},
#line 39 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING},
{-1}, {-1},
@@ -289,5 +293,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
}
return 0;
}
-#line 49 "scripts/kconfig/zconf.gperf"
+#line 50 "scripts/kconfig/zconf.gperf"
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 7a4d658c2066..65b7515a577c 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.5.1. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@@ -26,7 +26,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.5.1"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,18 +58,16 @@
/* Pull parsers. */
#define YYPULL 1
-/* Using locations. */
-#define YYLSP_NEEDED 0
/* Substitute the variable and function names. */
#define yyparse zconfparse
#define yylex zconflex
#define yyerror zconferror
-#define yylval zconflval
-#define yychar zconfchar
#define yydebug zconfdebug
#define yynerrs zconfnerrs
+#define yylval zconflval
+#define yychar zconfchar
/* Copy the first part of user declarations. */
@@ -108,19 +106,14 @@ static struct menu *current_menu, *current_entry;
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
+# define YY_NULLPTR nullptr
# else
-# define YY_NULL 0
+# define YY_NULLPTR 0
# endif
# endif
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
@@ -129,62 +122,65 @@ static struct menu *current_menu, *current_entry;
# define YYERROR_VERBOSE 0
#endif
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int zconfdebug;
+#endif
-/* Tokens. */
+/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- T_MAINMENU = 258,
- T_MENU = 259,
- T_ENDMENU = 260,
- T_SOURCE = 261,
- T_CHOICE = 262,
- T_ENDCHOICE = 263,
- T_COMMENT = 264,
- T_CONFIG = 265,
- T_MENUCONFIG = 266,
- T_HELP = 267,
- T_HELPTEXT = 268,
- T_IF = 269,
- T_ENDIF = 270,
- T_DEPENDS = 271,
- T_OPTIONAL = 272,
- T_PROMPT = 273,
- T_TYPE = 274,
- T_DEFAULT = 275,
- T_SELECT = 276,
- T_RANGE = 277,
- T_VISIBLE = 278,
- T_OPTION = 279,
- T_ON = 280,
- T_WORD = 281,
- T_WORD_QUOTE = 282,
- T_UNEQUAL = 283,
- T_LESS = 284,
- T_LESS_EQUAL = 285,
- T_GREATER = 286,
- T_GREATER_EQUAL = 287,
- T_CLOSE_PAREN = 288,
- T_OPEN_PAREN = 289,
- T_EOL = 290,
- T_OR = 291,
- T_AND = 292,
- T_EQUAL = 293,
- T_NOT = 294
- };
+ enum yytokentype
+ {
+ T_MAINMENU = 258,
+ T_MENU = 259,
+ T_ENDMENU = 260,
+ T_SOURCE = 261,
+ T_CHOICE = 262,
+ T_ENDCHOICE = 263,
+ T_COMMENT = 264,
+ T_CONFIG = 265,
+ T_MENUCONFIG = 266,
+ T_HELP = 267,
+ T_HELPTEXT = 268,
+ T_IF = 269,
+ T_ENDIF = 270,
+ T_DEPENDS = 271,
+ T_OPTIONAL = 272,
+ T_PROMPT = 273,
+ T_TYPE = 274,
+ T_DEFAULT = 275,
+ T_SELECT = 276,
+ T_IMPLY = 277,
+ T_RANGE = 278,
+ T_VISIBLE = 279,
+ T_OPTION = 280,
+ T_ON = 281,
+ T_WORD = 282,
+ T_WORD_QUOTE = 283,
+ T_UNEQUAL = 284,
+ T_LESS = 285,
+ T_LESS_EQUAL = 286,
+ T_GREATER = 287,
+ T_GREATER_EQUAL = 288,
+ T_CLOSE_PAREN = 289,
+ T_OPEN_PAREN = 290,
+ T_EOL = 291,
+ T_OR = 292,
+ T_AND = 293,
+ T_EQUAL = 294,
+ T_NOT = 295
+ };
#endif
-
-
+/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
+
+union YYSTYPE
{
@@ -196,14 +192,20 @@ typedef union YYSTYPE
const struct kconf_id *id;
+};
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
+extern YYSTYPE zconflval;
+
+int zconfparse (void);
+
+
+
/* Copy the second part of user declarations. */
@@ -224,11 +226,8 @@ typedef unsigned char yytype_uint8;
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
#else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
#endif
#ifdef YYTYPE_UINT16
@@ -248,8 +247,7 @@ typedef short int yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -263,38 +261,67 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
#else
-static int
-YYID (yyi)
- int yyi;
+# define YY_INITIAL_VALUE(Value) Value
#endif
-{
- return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
#if ! defined yyoverflow || YYERROR_VERBOSE
@@ -313,8 +340,7 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
/* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
@@ -326,8 +352,8 @@ YYID (yyi)
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
@@ -343,7 +369,7 @@ YYID (yyi)
# endif
# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
+ && (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
@@ -351,15 +377,13 @@ YYID (yyi)
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined malloc && ! defined EXIT_SUCCESS
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
@@ -369,7 +393,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
@@ -394,16 +418,16 @@ union yyalloc
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
#endif
@@ -422,7 +446,7 @@ union yyalloc
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
- while (YYID (0))
+ while (0)
# endif
# endif
#endif /* !YYCOPY_NEEDED */
@@ -430,25 +454,27 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 11
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 298
+#define YYLAST 301
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 40
+#define YYNTOKENS 41
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 50
/* YYNRULES -- Number of rules. */
-#define YYNRULES 122
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 199
+#define YYNRULES 124
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 204
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 294
+#define YYMAXUTOK 295
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -480,90 +506,30 @@ static const yytype_uint8 yytranslate[] =
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
+ 35, 36, 37, 38, 39, 40
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint16 yyprhs[] =
-{
- 0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
- 23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
- 52, 54, 56, 58, 60, 62, 64, 66, 68, 72,
- 75, 79, 82, 86, 89, 90, 93, 96, 99, 102,
- 105, 108, 112, 117, 122, 127, 133, 137, 138, 142,
- 143, 146, 150, 153, 155, 159, 160, 163, 166, 169,
- 172, 175, 180, 184, 187, 192, 193, 196, 200, 202,
- 206, 207, 210, 213, 216, 220, 224, 228, 230, 234,
- 235, 238, 241, 244, 248, 252, 255, 258, 261, 262,
- 265, 268, 271, 276, 277, 280, 283, 286, 287, 290,
- 292, 294, 297, 300, 303, 305, 308, 309, 312, 314,
- 318, 322, 326, 330, 334, 338, 342, 345, 349, 353,
- 355, 357, 358
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 41, 0, -1, 85, 42, -1, 42, -1, 67, 43,
- -1, 43, -1, -1, 43, 45, -1, 43, 59, -1,
- 43, 71, -1, 43, 84, -1, 43, 26, 1, 35,
- -1, 43, 44, 1, 35, -1, 43, 1, 35, -1,
- 16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
- 22, -1, 20, -1, 23, -1, 35, -1, 65, -1,
- 75, -1, 48, -1, 50, -1, 73, -1, 26, 1,
- 35, -1, 1, 35, -1, 10, 26, 35, -1, 47,
- 51, -1, 11, 26, 35, -1, 49, 51, -1, -1,
- 51, 52, -1, 51, 53, -1, 51, 79, -1, 51,
- 77, -1, 51, 46, -1, 51, 35, -1, 19, 82,
- 35, -1, 18, 83, 86, 35, -1, 20, 87, 86,
- 35, -1, 21, 26, 86, 35, -1, 22, 88, 88,
- 86, 35, -1, 24, 54, 35, -1, -1, 54, 26,
- 55, -1, -1, 38, 83, -1, 7, 89, 35, -1,
- 56, 60, -1, 84, -1, 57, 62, 58, -1, -1,
- 60, 61, -1, 60, 79, -1, 60, 77, -1, 60,
- 35, -1, 60, 46, -1, 18, 83, 86, 35, -1,
- 19, 82, 35, -1, 17, 35, -1, 20, 26, 86,
- 35, -1, -1, 62, 45, -1, 14, 87, 85, -1,
- 84, -1, 63, 66, 64, -1, -1, 66, 45, -1,
- 66, 71, -1, 66, 59, -1, 3, 83, 85, -1,
- 4, 83, 35, -1, 68, 80, 78, -1, 84, -1,
- 69, 72, 70, -1, -1, 72, 45, -1, 72, 71,
- -1, 72, 59, -1, 6, 83, 35, -1, 9, 83,
- 35, -1, 74, 78, -1, 12, 35, -1, 76, 13,
- -1, -1, 78, 79, -1, 78, 35, -1, 78, 46,
- -1, 16, 25, 87, 35, -1, -1, 80, 81, -1,
- 80, 35, -1, 23, 86, -1, -1, 83, 86, -1,
- 26, -1, 27, -1, 5, 35, -1, 8, 35, -1,
- 15, 35, -1, 35, -1, 85, 35, -1, -1, 14,
- 87, -1, 88, -1, 88, 29, 88, -1, 88, 30,
- 88, -1, 88, 31, 88, -1, 88, 32, 88, -1,
- 88, 38, 88, -1, 88, 28, 88, -1, 34, 87,
- 33, -1, 39, 87, -1, 87, 36, 87, -1, 87,
- 37, 87, -1, 26, -1, 27, -1, -1, 26, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 108, 108, 108, 110, 110, 112, 114, 115, 116,
- 117, 118, 119, 123, 127, 127, 127, 127, 127, 127,
- 127, 127, 131, 132, 133, 134, 135, 136, 140, 141,
- 147, 155, 161, 169, 179, 181, 182, 183, 184, 185,
- 186, 189, 197, 203, 213, 219, 225, 228, 230, 241,
- 242, 247, 256, 261, 269, 272, 274, 275, 276, 277,
- 278, 281, 287, 298, 304, 314, 316, 321, 329, 337,
- 340, 342, 343, 344, 349, 356, 363, 368, 376, 379,
- 381, 382, 383, 386, 394, 401, 408, 414, 421, 423,
- 424, 425, 428, 436, 438, 439, 442, 449, 451, 456,
- 457, 460, 461, 462, 466, 467, 470, 471, 474, 475,
- 476, 477, 478, 479, 480, 481, 482, 483, 484, 487,
- 488, 491, 492
+ 0, 109, 109, 109, 111, 111, 113, 115, 116, 117,
+ 118, 119, 120, 124, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 132, 133, 134, 135, 136, 137, 141,
+ 142, 148, 156, 162, 170, 180, 182, 183, 184, 185,
+ 186, 187, 190, 198, 204, 214, 220, 226, 232, 235,
+ 237, 248, 249, 254, 263, 268, 276, 279, 281, 282,
+ 283, 284, 285, 288, 294, 305, 311, 321, 323, 328,
+ 336, 344, 347, 349, 350, 351, 356, 363, 370, 375,
+ 383, 386, 388, 389, 390, 393, 401, 408, 415, 421,
+ 428, 430, 431, 432, 435, 443, 445, 446, 449, 456,
+ 458, 463, 464, 467, 468, 469, 473, 474, 477, 478,
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
+ 491, 494, 495, 498, 499
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -571,9 +537,9 @@ static const char *const yytname[] =
"$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
"T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
"T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
- "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
- "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
- "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
+ "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_IMPLY",
+ "T_RANGE", "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE",
+ "T_UNEQUAL", "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
"T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
"T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
"common_stmt", "option_error", "config_entry_start", "config_stmt",
@@ -585,260 +551,254 @@ static const char *const yytname[] =
"menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
"comment", "comment_stmt", "help_start", "help", "depends_list",
"depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
- "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULL
+ "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULLPTR
};
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 288, 289, 290, 291, 292, 293, 294
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
+#define YYPACT_NINF -92
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-92)))
+
+#define YYTABLE_NINF -88
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
{
- 0, 40, 41, 41, 42, 42, 43, 43, 43, 43,
- 43, 43, 43, 43, 44, 44, 44, 44, 44, 44,
- 44, 44, 45, 45, 45, 45, 45, 45, 46, 46,
- 47, 48, 49, 50, 51, 51, 51, 51, 51, 51,
- 51, 52, 52, 52, 52, 52, 53, 54, 54, 55,
- 55, 56, 57, 58, 59, 60, 60, 60, 60, 60,
- 60, 61, 61, 61, 61, 62, 62, 63, 64, 65,
- 66, 66, 66, 66, 67, 68, 69, 70, 71, 72,
- 72, 72, 72, 73, 74, 75, 76, 77, 78, 78,
- 78, 78, 79, 80, 80, 80, 81, 82, 82, 83,
- 83, 84, 84, 84, 85, 85, 86, 86, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 88,
- 88, 89, 89
+ 17, 41, -92, 15, -92, 150, -92, 19, -92, -92,
+ -13, -92, 28, 41, 38, 41, 50, 47, 41, 79,
+ 82, 44, 76, -92, -92, -92, -92, -92, -92, -92,
+ -92, -92, 118, -92, 129, -92, -92, -92, -92, -92,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ -92, -92, 184, -92, -92, 107, -92, 111, -92, 113,
+ -92, 116, -92, 139, 140, 151, -92, -92, 44, 44,
+ 142, 256, -92, 160, 173, 27, 117, 80, 51, 255,
+ -15, 255, 217, -92, -92, -92, -92, -92, -92, -8,
+ -92, 44, 44, 107, 87, 87, 87, 87, 87, 87,
+ -92, -92, 174, 176, 187, 41, 41, 44, 188, 189,
+ 87, -92, 213, -92, -92, -92, -92, 206, -92, -92,
+ 193, 41, 41, 203, -92, -92, -92, -92, -92, -92,
+ -92, -92, -92, -92, -92, -92, -92, 229, -92, 241,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ 216, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ 44, 229, 222, 229, 64, 229, 229, 87, 31, 231,
+ -92, -92, 229, 236, 229, 44, -92, 145, 242, -92,
+ -92, 243, 244, 245, 229, 251, -92, -92, 247, -92,
+ 257, 125, -92, -92, -92, -92, -92, 260, 41, -92,
+ -92, -92, -92, -92
};
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
{
- 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
- 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 3, 2,
- 3, 2, 3, 2, 0, 2, 2, 2, 2, 2,
- 2, 3, 4, 4, 4, 5, 3, 0, 3, 0,
- 2, 3, 2, 1, 3, 0, 2, 2, 2, 2,
- 2, 4, 3, 2, 4, 0, 2, 3, 1, 3,
- 0, 2, 2, 2, 3, 3, 3, 1, 3, 0,
- 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
- 2, 2, 4, 0, 2, 2, 2, 0, 2, 1,
- 1, 2, 2, 2, 1, 2, 0, 2, 1, 3,
- 3, 3, 3, 3, 3, 3, 2, 3, 3, 1,
- 1, 0, 1
+ 6, 0, 106, 0, 3, 0, 6, 6, 101, 102,
+ 0, 1, 0, 0, 0, 0, 123, 0, 0, 0,
+ 0, 0, 0, 14, 19, 15, 16, 21, 17, 18,
+ 20, 22, 0, 23, 0, 7, 35, 26, 35, 27,
+ 57, 67, 8, 72, 24, 95, 81, 9, 28, 90,
+ 25, 10, 0, 107, 2, 76, 13, 0, 103, 0,
+ 124, 0, 104, 0, 0, 0, 121, 122, 0, 0,
+ 0, 110, 105, 0, 0, 0, 0, 0, 0, 0,
+ 90, 0, 0, 77, 85, 53, 86, 31, 33, 0,
+ 118, 0, 0, 69, 0, 0, 0, 0, 0, 0,
+ 11, 12, 0, 0, 0, 0, 99, 0, 0, 0,
+ 0, 49, 0, 41, 40, 36, 37, 0, 39, 38,
+ 0, 0, 99, 0, 61, 62, 58, 60, 59, 68,
+ 56, 55, 73, 75, 71, 74, 70, 108, 97, 0,
+ 96, 82, 84, 80, 83, 79, 92, 93, 91, 117,
+ 119, 120, 116, 111, 112, 113, 114, 115, 30, 88,
+ 0, 108, 0, 108, 108, 108, 108, 0, 0, 0,
+ 89, 65, 108, 0, 108, 0, 98, 0, 0, 42,
+ 100, 0, 0, 0, 108, 51, 48, 29, 0, 64,
+ 0, 109, 94, 43, 44, 45, 46, 0, 0, 50,
+ 63, 66, 47, 52
};
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
{
- 6, 0, 104, 0, 3, 0, 6, 6, 99, 100,
- 0, 1, 0, 0, 0, 0, 121, 0, 0, 0,
- 0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
- 21, 0, 22, 0, 7, 34, 25, 34, 26, 55,
- 65, 8, 70, 23, 93, 79, 9, 27, 88, 24,
- 10, 0, 105, 2, 74, 13, 0, 101, 0, 122,
- 0, 102, 0, 0, 0, 119, 120, 0, 0, 0,
- 108, 103, 0, 0, 0, 0, 0, 0, 0, 88,
- 0, 0, 75, 83, 51, 84, 30, 32, 0, 116,
- 0, 0, 67, 0, 0, 0, 0, 0, 0, 11,
- 12, 0, 0, 0, 0, 97, 0, 0, 0, 47,
- 0, 40, 39, 35, 36, 0, 38, 37, 0, 0,
- 97, 0, 59, 60, 56, 58, 57, 66, 54, 53,
- 71, 73, 69, 72, 68, 106, 95, 0, 94, 80,
- 82, 78, 81, 77, 90, 91, 89, 115, 117, 118,
- 114, 109, 110, 111, 112, 113, 29, 86, 0, 106,
- 0, 106, 106, 106, 0, 0, 0, 87, 63, 106,
- 0, 106, 0, 96, 0, 0, 41, 98, 0, 0,
- 106, 49, 46, 28, 0, 62, 0, 107, 92, 42,
- 43, 44, 0, 0, 48, 61, 64, 45, 50
+ -92, -92, 285, 291, -92, 32, -66, -92, -92, -92,
+ -92, 261, -92, -92, -92, -92, -92, -92, -92, 1,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ -92, 24, -92, -92, -92, -92, -92, 221, 220, -64,
+ -92, -92, 179, -1, 67, 0, 110, -67, -91, -92
};
-/* YYDEFGOTO[NTERM-NUM]. */
+ /* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 3, 4, 5, 33, 34, 112, 35, 36, 37,
- 38, 74, 113, 114, 165, 194, 39, 40, 128, 41,
- 76, 124, 77, 42, 132, 43, 78, 6, 44, 45,
- 141, 46, 80, 47, 48, 49, 115, 116, 81, 117,
- 79, 138, 160, 161, 50, 7, 173, 69, 70, 60
+ -1, 3, 4, 5, 34, 35, 114, 36, 37, 38,
+ 39, 75, 115, 116, 168, 199, 40, 41, 130, 42,
+ 77, 126, 78, 43, 134, 44, 79, 6, 45, 46,
+ 143, 47, 81, 48, 49, 50, 117, 118, 82, 119,
+ 80, 140, 162, 163, 51, 7, 176, 70, 71, 61
};
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -91
-static const yytype_int16 yypact[] =
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
{
- 19, 37, -91, 13, -91, 79, -91, 20, -91, -91,
- -16, -91, 21, 37, 25, 37, 41, 36, 37, 78,
- 83, 31, 56, -91, -91, -91, -91, -91, -91, -91,
- -91, 116, -91, 127, -91, -91, -91, -91, -91, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, 147, -91, -91, 105, -91, 109, -91, 111, -91,
- 114, -91, 136, 137, 142, -91, -91, 31, 31, 76,
- 254, -91, 143, 146, 27, 115, 207, 258, 243, -14,
- 243, 179, -91, -91, -91, -91, -91, -91, -7, -91,
- 31, 31, 105, 51, 51, 51, 51, 51, 51, -91,
- -91, 156, 168, 181, 37, 37, 31, 178, 51, -91,
- 206, -91, -91, -91, -91, 196, -91, -91, 175, 37,
- 37, 185, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, -91, -91, -91, -91, 214, -91, 230, -91, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, 183, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, 31, 214,
- 194, 214, 45, 214, 51, 26, 195, -91, -91, 214,
- 197, 214, 31, -91, 139, 208, -91, -91, 220, 224,
- 214, 222, -91, -91, 226, -91, 227, 123, -91, -91,
- -91, -91, 235, 37, -91, -91, -91, -91, -91
+ 10, 89, 90, 152, 153, 154, 155, 156, 157, 137,
+ 55, 125, 57, 128, 59, 11, 147, 63, 148, 167,
+ 1, 138, 1, 2, 150, 151, 149, -32, 102, 91,
+ 92, -32, -32, -32, -32, -32, -32, -32, -32, 103,
+ 164, -32, -32, 104, -32, 105, 106, 107, 108, 109,
+ 110, -32, 111, 2, 112, 53, 14, 15, 185, 17,
+ 18, 19, 20, 113, 56, 21, 22, 186, 8, 9,
+ 93, 66, 67, 147, 58, 148, 184, 60, 175, 68,
+ 133, 102, 142, 62, 69, -54, -54, 33, -54, -54,
+ -54, -54, 103, 177, -54, -54, 104, 120, 121, 122,
+ 123, 91, 92, 135, 161, 144, 64, 112, 191, 65,
+ 129, 132, 72, 141, 66, 67, 124, -34, 102, 73,
+ 172, -34, -34, -34, -34, -34, -34, -34, -34, 103,
+ 74, -34, -34, 104, -34, 105, 106, 107, 108, 109,
+ 110, -34, 111, 53, 112, 131, 136, 83, 145, 84,
+ -5, 12, 85, 113, 13, 14, 15, 16, 17, 18,
+ 19, 20, 91, 92, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 86, 87, 32, 2, 91,
+ 92, 192, 91, 92, -4, 12, 33, 88, 13, 14,
+ 15, 16, 17, 18, 19, 20, 100, 203, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 101,
+ 158, 32, 159, 160, 169, 165, 166, -87, 102, 170,
+ 33, -87, -87, -87, -87, -87, -87, -87, -87, 171,
+ 174, -87, -87, 104, -87, -87, -87, -87, -87, -87,
+ -87, -87, 102, 175, 112, -78, -78, -78, -78, -78,
+ -78, -78, -78, 146, 92, -78, -78, 104, 179, 13,
+ 14, 15, 16, 17, 18, 19, 20, 187, 112, 21,
+ 22, 178, 189, 180, 181, 182, 183, 146, 193, 194,
+ 195, 196, 188, 200, 190, 94, 95, 96, 97, 98,
+ 198, 33, 54, 201, 197, 99, 202, 52, 127, 76,
+ 139, 173
};
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int16 yypgoto[] =
+static const yytype_uint8 yycheck[] =
{
- -91, -91, 264, 268, -91, 30, -65, -91, -91, -91,
- -91, 238, -91, -91, -91, -91, -91, -91, -91, -12,
- -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, -5, -91, -91, -91, -91, -91, 200, 209, -61,
- -91, -91, 170, -1, 65, 0, 118, -66, -90, -91
+ 1, 68, 69, 94, 95, 96, 97, 98, 99, 24,
+ 10, 77, 13, 77, 15, 0, 82, 18, 82, 110,
+ 3, 36, 3, 36, 91, 92, 34, 0, 1, 37,
+ 38, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 107, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 36, 27, 36, 5, 6, 27, 8,
+ 9, 10, 11, 36, 36, 14, 15, 36, 27, 28,
+ 70, 27, 28, 139, 36, 139, 167, 27, 14, 35,
+ 79, 1, 81, 36, 40, 5, 6, 36, 8, 9,
+ 10, 11, 12, 160, 14, 15, 16, 17, 18, 19,
+ 20, 37, 38, 79, 105, 81, 27, 27, 175, 27,
+ 78, 79, 36, 81, 27, 28, 36, 0, 1, 1,
+ 121, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 36, 27, 78, 79, 36, 81, 36,
+ 0, 1, 36, 36, 4, 5, 6, 7, 8, 9,
+ 10, 11, 37, 38, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 36, 36, 27, 36, 37,
+ 38, 36, 37, 38, 0, 1, 36, 36, 4, 5,
+ 6, 7, 8, 9, 10, 11, 36, 198, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 36,
+ 36, 27, 36, 26, 1, 27, 27, 0, 1, 13,
+ 36, 4, 5, 6, 7, 8, 9, 10, 11, 36,
+ 27, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 1, 14, 27, 4, 5, 6, 7, 8,
+ 9, 10, 11, 36, 38, 14, 15, 16, 36, 4,
+ 5, 6, 7, 8, 9, 10, 11, 36, 27, 14,
+ 15, 161, 36, 163, 164, 165, 166, 36, 36, 36,
+ 36, 36, 172, 36, 174, 29, 30, 31, 32, 33,
+ 39, 36, 7, 36, 184, 39, 36, 6, 77, 38,
+ 80, 122
};
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -86
-static const yytype_int16 yytable[] =
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
{
- 10, 88, 89, 150, 151, 152, 153, 154, 155, 135,
- 54, 123, 56, 11, 58, 126, 145, 62, 164, 2,
- 146, 136, 1, 1, 148, 149, 147, -31, 101, 90,
- 91, -31, -31, -31, -31, -31, -31, -31, -31, 102,
- 162, -31, -31, 103, -31, 104, 105, 106, 107, 108,
- -31, 109, 181, 110, 2, 52, 55, 65, 66, 172,
- 57, 182, 111, 8, 9, 67, 131, 59, 140, 92,
- 68, 61, 145, 133, 180, 142, 146, 65, 66, -5,
- 12, 90, 91, 13, 14, 15, 16, 17, 18, 19,
- 20, 71, 174, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 159, 63, 31, 187, 127, 130, 64,
- 139, 2, 90, 91, 32, -33, 101, 72, 169, -33,
- -33, -33, -33, -33, -33, -33, -33, 102, 73, -33,
- -33, 103, -33, 104, 105, 106, 107, 108, -33, 109,
- 52, 110, 129, 134, 82, 143, 83, -4, 12, 84,
- 111, 13, 14, 15, 16, 17, 18, 19, 20, 90,
- 91, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 85, 86, 31, 188, 90, 91, 87, 99, -85,
- 101, 100, 32, -85, -85, -85, -85, -85, -85, -85,
- -85, 156, 198, -85, -85, 103, -85, -85, -85, -85,
- -85, -85, -85, 157, 163, 110, 158, 166, 101, 167,
- 168, 171, -52, -52, 144, -52, -52, -52, -52, 102,
- 91, -52, -52, 103, 118, 119, 120, 121, 172, 176,
- 183, 101, 185, 110, -76, -76, -76, -76, -76, -76,
- -76, -76, 122, 189, -76, -76, 103, 13, 14, 15,
- 16, 17, 18, 19, 20, 190, 110, 21, 22, 191,
- 193, 195, 196, 14, 15, 144, 17, 18, 19, 20,
- 197, 53, 21, 22, 51, 75, 125, 175, 32, 177,
- 178, 179, 93, 94, 95, 96, 97, 184, 137, 186,
- 170, 0, 98, 32, 0, 0, 0, 0, 192
+ 0, 3, 36, 42, 43, 44, 68, 86, 27, 28,
+ 84, 0, 1, 4, 5, 6, 7, 8, 9, 10,
+ 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 27, 36, 45, 46, 48, 49, 50, 51,
+ 57, 58, 60, 64, 66, 69, 70, 72, 74, 75,
+ 76, 85, 44, 36, 43, 86, 36, 84, 36, 84,
+ 27, 90, 36, 84, 27, 27, 27, 28, 35, 40,
+ 88, 89, 36, 1, 1, 52, 52, 61, 63, 67,
+ 81, 73, 79, 36, 36, 36, 36, 36, 36, 88,
+ 88, 37, 38, 86, 29, 30, 31, 32, 33, 39,
+ 36, 36, 1, 12, 16, 18, 19, 20, 21, 22,
+ 23, 25, 27, 36, 47, 53, 54, 77, 78, 80,
+ 17, 18, 19, 20, 36, 47, 62, 78, 80, 46,
+ 59, 85, 46, 60, 65, 72, 85, 24, 36, 79,
+ 82, 46, 60, 71, 72, 85, 36, 47, 80, 34,
+ 88, 88, 89, 89, 89, 89, 89, 89, 36, 36,
+ 26, 84, 83, 84, 88, 27, 27, 89, 55, 1,
+ 13, 36, 84, 83, 27, 14, 87, 88, 87, 36,
+ 87, 87, 87, 87, 89, 27, 36, 36, 87, 36,
+ 87, 88, 36, 36, 36, 36, 36, 87, 39, 56,
+ 36, 36, 36, 84
};
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-91))
-
-#define yytable_value_is_error(yytable_value) \
- YYID (0)
-
-static const yytype_int16 yycheck[] =
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
{
- 1, 67, 68, 93, 94, 95, 96, 97, 98, 23,
- 10, 76, 13, 0, 15, 76, 81, 18, 108, 35,
- 81, 35, 3, 3, 90, 91, 33, 0, 1, 36,
- 37, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 106, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 26, 26, 35, 35, 35, 26, 27, 14,
- 35, 35, 35, 26, 27, 34, 78, 26, 80, 69,
- 39, 35, 137, 78, 164, 80, 137, 26, 27, 0,
- 1, 36, 37, 4, 5, 6, 7, 8, 9, 10,
- 11, 35, 158, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 104, 26, 26, 172, 77, 78, 26,
- 80, 35, 36, 37, 35, 0, 1, 1, 119, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 1, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 35, 26, 77, 78, 35, 80, 35, 0, 1, 35,
- 35, 4, 5, 6, 7, 8, 9, 10, 11, 36,
- 37, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 35, 35, 26, 35, 36, 37, 35, 35, 0,
- 1, 35, 35, 4, 5, 6, 7, 8, 9, 10,
- 11, 35, 193, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 35, 26, 26, 25, 1, 1, 13,
- 35, 26, 5, 6, 35, 8, 9, 10, 11, 12,
- 37, 14, 15, 16, 17, 18, 19, 20, 14, 35,
- 35, 1, 35, 26, 4, 5, 6, 7, 8, 9,
- 10, 11, 35, 35, 14, 15, 16, 4, 5, 6,
- 7, 8, 9, 10, 11, 35, 26, 14, 15, 35,
- 38, 35, 35, 5, 6, 35, 8, 9, 10, 11,
- 35, 7, 14, 15, 6, 37, 76, 159, 35, 161,
- 162, 163, 28, 29, 30, 31, 32, 169, 79, 171,
- 120, -1, 38, 35, -1, -1, -1, -1, 180
+ 0, 41, 42, 42, 43, 43, 44, 44, 44, 44,
+ 44, 44, 44, 44, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 46, 46, 46, 46, 46, 46, 47,
+ 47, 48, 49, 50, 51, 52, 52, 52, 52, 52,
+ 52, 52, 53, 53, 53, 53, 53, 53, 54, 55,
+ 55, 56, 56, 57, 58, 59, 60, 61, 61, 61,
+ 61, 61, 61, 62, 62, 62, 62, 63, 63, 64,
+ 65, 66, 67, 67, 67, 67, 68, 69, 70, 71,
+ 72, 73, 73, 73, 73, 74, 75, 76, 77, 78,
+ 79, 79, 79, 79, 80, 81, 81, 81, 82, 83,
+ 83, 84, 84, 85, 85, 85, 86, 86, 87, 87,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 89, 89, 90, 90
};
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
{
- 0, 3, 35, 41, 42, 43, 67, 85, 26, 27,
- 83, 0, 1, 4, 5, 6, 7, 8, 9, 10,
- 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 26, 35, 44, 45, 47, 48, 49, 50, 56,
- 57, 59, 63, 65, 68, 69, 71, 73, 74, 75,
- 84, 43, 35, 42, 85, 35, 83, 35, 83, 26,
- 89, 35, 83, 26, 26, 26, 27, 34, 39, 87,
- 88, 35, 1, 1, 51, 51, 60, 62, 66, 80,
- 72, 78, 35, 35, 35, 35, 35, 35, 87, 87,
- 36, 37, 85, 28, 29, 30, 31, 32, 38, 35,
- 35, 1, 12, 16, 18, 19, 20, 21, 22, 24,
- 26, 35, 46, 52, 53, 76, 77, 79, 17, 18,
- 19, 20, 35, 46, 61, 77, 79, 45, 58, 84,
- 45, 59, 64, 71, 84, 23, 35, 78, 81, 45,
- 59, 70, 71, 84, 35, 46, 79, 33, 87, 87,
- 88, 88, 88, 88, 88, 88, 35, 35, 25, 83,
- 82, 83, 87, 26, 88, 54, 1, 13, 35, 83,
- 82, 26, 14, 86, 87, 86, 35, 86, 86, 86,
- 88, 26, 35, 35, 86, 35, 86, 87, 35, 35,
- 35, 35, 86, 38, 55, 35, 35, 35, 83
+ 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
+ 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 2, 3, 2, 3, 2, 0, 2, 2, 2, 2,
+ 2, 2, 3, 4, 4, 4, 4, 5, 3, 0,
+ 3, 0, 2, 3, 2, 1, 3, 0, 2, 2,
+ 2, 2, 2, 4, 3, 2, 4, 0, 2, 3,
+ 1, 3, 0, 2, 2, 2, 3, 3, 3, 1,
+ 3, 0, 2, 2, 2, 3, 3, 2, 2, 2,
+ 0, 2, 2, 2, 4, 0, 2, 2, 2, 0,
+ 2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
+ 1, 3, 3, 3, 3, 3, 3, 3, 2, 3,
+ 3, 1, 1, 0, 1
};
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
-
-#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
#define YYRECOVERING() (!!yyerrstatus)
@@ -855,55 +815,15 @@ do \
else \
{ \
yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+ YYERROR; \
+ } \
+while (0)
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
-/* YYLEX -- calling `yylex' with the right arguments. */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
/* Enable debugging if requested. */
#if YYDEBUG
@@ -913,40 +833,36 @@ while (YYID (0))
# define YYFPRINTF fprintf
# endif
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
{
FILE *yyo = yyoutput;
YYUSE (yyo);
@@ -955,14 +871,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
# endif
- switch (yytype)
- {
- default:
- break;
- }
+ YYUSE (yytype);
}
@@ -970,22 +880,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
yy_symbol_value_print (yyoutput, yytype, yyvaluep);
YYFPRINTF (yyoutput, ")");
@@ -996,16 +895,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
| TOP (included). |
`------------------------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
-#endif
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -1016,49 +907,42 @@ yy_stack_print (yybottom, yytop)
YYFPRINTF (stderr, "\n");
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
{
+ unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
+ yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- );
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
YYFPRINTF (stderr, "\n");
}
}
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -1072,7 +956,7 @@ int yydebug;
/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
+#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif
@@ -1095,15 +979,8 @@ int yydebug;
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
@@ -1119,16 +996,8 @@ yystrlen (yystr)
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1158,27 +1027,27 @@ yytnamerr (char *yyres, const char *yystr)
char const *yyp = yystr;
for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
do_not_strip_quotes: ;
}
@@ -1201,12 +1070,11 @@ static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
- const char *yyformat = YY_NULL;
+ const char *yyformat = YY_NULLPTR;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
@@ -1214,10 +1082,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
int yycount = 0;
/* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
is an error action. In that case, don't check for expected
@@ -1266,11 +1130,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
break;
}
yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
}
}
}
@@ -1290,10 +1156,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
# undef YYCASE_
}
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
if (*yymsg_alloc < yysize)
{
@@ -1330,78 +1198,58 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
{
YYUSE (yyvaluep);
-
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
switch (yytype)
{
- case 57: /* "choice_entry" */
+ case 58: /* choice_entry */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
+
+ break;
- break;
- case 63: /* "if_entry" */
+ case 64: /* if_entry */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
- break;
- case 69: /* "menu_entry" */
+ break;
- {
+ case 70: /* menu_entry */
+
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
+
+ break;
- break;
default:
- break;
+ break;
}
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
}
-/* Prevent warnings from -Wmissing-prototypes. */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
/* The lookahead symbol. */
@@ -1409,7 +1257,6 @@ int yychar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
-
/* Number of syntax errors so far. */
int yynerrs;
@@ -1418,35 +1265,16 @@ int yynerrs;
| yyparse. |
`----------*/
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
{
int yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
@@ -1466,7 +1294,7 @@ yyparse ()
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
- int yytoken;
+ int yytoken = 0;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
@@ -1484,9 +1312,8 @@ yyparse ()
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yytoken = 0;
- yyss = yyssa;
- yyvs = yyvsa;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1495,14 +1322,6 @@ yyparse ()
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;
-
goto yysetstate;
/*------------------------------------------------------------.
@@ -1523,23 +1342,23 @@ yyparse ()
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
@@ -1547,22 +1366,22 @@ yyparse ()
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
+ yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
@@ -1571,10 +1390,10 @@ yyparse ()
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long int) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
+ YYABORT;
}
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1603,7 +1422,7 @@ yybackup:
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
+ yychar = yylex ();
}
if (yychar <= YYEOF)
@@ -1643,7 +1462,9 @@ yybackup:
yychar = YYEMPTY;
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1666,7 +1487,7 @@ yyreduce:
yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
@@ -1682,64 +1503,73 @@ yyreduce:
case 10:
{ zconf_error("unexpected end statement"); }
+
break;
case 11:
- { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); }
+ { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); }
+
break;
case 12:
{
- zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
}
+
break;
case 13:
{ zconf_error("invalid statement"); }
+
break;
- case 28:
+ case 29:
+
+ { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); }
- { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); }
break;
- case 29:
+ case 30:
{ zconf_error("invalid option"); }
+
break;
- case 30:
+ case 31:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
}
+
break;
- case 31:
+ case 32:
{
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 32:
+ case 33:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
}
+
break;
- case 33:
+ case 34:
{
if (current_entry->prompt)
@@ -1749,352 +1579,410 @@ yyreduce:
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 41:
+ case 42:
{
- menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ menu_set_type((yyvsp[-2].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (3)].id)->stype);
+ (yyvsp[-2].id)->stype);
}
+
break;
- case 42:
+ case 43:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 43:
+ case 44:
{
- menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
- if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
- menu_set_type((yyvsp[(1) - (4)].id)->stype);
+ menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
+ if ((yyvsp[-3].id)->stype != S_UNKNOWN)
+ menu_set_type((yyvsp[-3].id)->stype);
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (4)].id)->stype);
+ (yyvsp[-3].id)->stype);
}
+
break;
- case 44:
+ case 45:
{
- menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 45:
+ case 46:
{
- menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
+ menu_add_symbol(P_IMPLY, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+ printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+}
+
+ break;
+
+ case 47:
+
+ {
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 48:
+ case 50:
{
- const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+ const struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
if (id && id->flags & TF_OPTION)
- menu_add_option(id->token, (yyvsp[(3) - (3)].string));
+ menu_add_option(id->token, (yyvsp[0].string));
else
- zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
- free((yyvsp[(2) - (3)].string));
+ zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+ free((yyvsp[-1].string));
}
+
break;
- case 49:
+ case 51:
{ (yyval.string) = NULL; }
+
break;
- case 50:
+ case 52:
+
+ { (yyval.string) = (yyvsp[0].string); }
- { (yyval.string) = (yyvsp[(2) - (2)].string); }
break;
- case 51:
+ case 53:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), SYMBOL_CHOICE);
sym->flags |= SYMBOL_AUTO;
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 52:
+ case 54:
{
(yyval.menu) = menu_add_menu();
}
+
break;
- case 53:
+ case 55:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
+ if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 61:
+ case 63:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 62:
+ case 64:
{
- if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
- menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
+ menu_set_type((yyvsp[-2].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (3)].id)->stype);
+ (yyvsp[-2].id)->stype);
} else
YYERROR;
}
+
break;
- case 63:
+ case 65:
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 64:
+ case 66:
{
- if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:default\n",
zconf_curname(), zconf_lineno());
} else
YYERROR;
}
+
break;
- case 67:
+ case 69:
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
- menu_add_dep((yyvsp[(2) - (3)].expr));
+ menu_add_dep((yyvsp[-1].expr));
(yyval.menu) = menu_add_menu();
}
+
break;
- case 68:
+ case 70:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
+ if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 74:
+ case 76:
{
- menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
}
+
break;
- case 75:
+ case 77:
{
menu_add_entry(NULL);
- menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 76:
+ case 78:
{
(yyval.menu) = menu_add_menu();
}
+
break;
- case 77:
+ case 79:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
+ if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 83:
+ case 85:
{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
- zconf_nextfile((yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+ zconf_nextfile((yyvsp[-1].string));
}
+
break;
- case 84:
+ case 86:
{
menu_add_entry(NULL);
- menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 85:
+ case 87:
{
menu_end_entry();
}
+
break;
- case 86:
+ case 88:
{
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
zconf_starthelp();
}
+
break;
- case 87:
+ case 89:
{
- current_entry->help = (yyvsp[(2) - (2)].string);
+ current_entry->help = (yyvsp[0].string);
}
+
break;
- case 92:
+ case 94:
{
- menu_add_dep((yyvsp[(3) - (4)].expr));
+ menu_add_dep((yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
}
- break;
-
- case 96:
- {
- menu_add_visibility((yyvsp[(2) - (2)].expr));
-}
break;
case 98:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
+ menu_add_visibility((yyvsp[0].expr));
}
- break;
- case 101:
-
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
- case 102:
+ case 100:
+
+ {
+ menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
+}
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
case 103:
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
+ { (yyval.id) = (yyvsp[-1].id); }
+
break;
- case 106:
+ case 104:
+
+ { (yyval.id) = (yyvsp[-1].id); }
- { (yyval.expr) = NULL; }
break;
- case 107:
+ case 105:
+
+ { (yyval.id) = (yyvsp[-1].id); }
- { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
break;
case 108:
- { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }
+ { (yyval.expr) = NULL; }
+
break;
case 109:
- { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = (yyvsp[0].expr); }
+
break;
case 110:
- { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); }
+
break;
case 111:
- { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 112:
- { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 113:
- { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 114:
- { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 115:
- { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
+ { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 116:
- { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }
+ { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 117:
- { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+ { (yyval.expr) = (yyvsp[-1].expr); }
+
break;
case 118:
- { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+ { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); }
+
break;
case 119:
- { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }
+ { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
break;
case 120:
- { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }
+ { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
break;
case 121:
+ { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); }
+
+ break;
+
+ case 122:
+
+ { (yyval.symbol) = sym_lookup((yyvsp[0].string), SYMBOL_CONST); free((yyvsp[0].string)); }
+
+ break;
+
+ case 123:
+
{ (yyval.string) = NULL; }
+
break;
@@ -2120,7 +2008,7 @@ yyreduce:
*++yyvsp = yyval;
- /* Now `shift' the result of the reduction. Determine what state
+ /* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
@@ -2135,9 +2023,9 @@ yyreduce:
goto yynewstate;
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
@@ -2188,20 +2076,20 @@ yyerrlab:
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
- error, discard it. */
+ error, discard it. */
if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval);
- yychar = YYEMPTY;
- }
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
}
/* Else will try to reuse lookahead token after shifting the error
@@ -2220,7 +2108,7 @@ yyerrorlab:
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
@@ -2233,35 +2121,37 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ YYABORT;
yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
+ yystos[yystate], yyvsp);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -2304,14 +2194,14 @@ yyreturn:
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
}
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
+ yystos[*yyssp], yyvsp);
YYPOPSTACK (1);
}
#ifndef yyoverflow
@@ -2322,14 +2212,11 @@ yyreturn:
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
+ return yyresult;
}
-
-
void conf_parse(const char *name)
{
struct symbol *sym;
@@ -2501,6 +2388,11 @@ static void print_symbol(FILE *out, struct menu *menu)
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
+ case P_IMPLY:
+ fputs( " imply ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
@@ -2577,4 +2469,3 @@ void zconfdump(FILE *out)
#include "expr.c"
#include "symbol.c"
#include "menu.c"
-
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 71bf8bff696a..001305fa080b 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
%}
-%expect 30
+%expect 32
%union
{
@@ -62,6 +62,7 @@ static struct menu *current_menu, *current_entry;
%token <id>T_TYPE
%token <id>T_DEFAULT
%token <id>T_SELECT
+%token <id>T_IMPLY
%token <id>T_RANGE
%token <id>T_VISIBLE
%token <id>T_OPTION
@@ -124,7 +125,7 @@ stmt_list:
;
option_name:
- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
;
common_stmt:
@@ -216,6 +217,12 @@ config_option: T_SELECT T_WORD if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
};
+config_option: T_IMPLY T_WORD if_expr T_EOL
+{
+ menu_add_symbol(P_IMPLY, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+};
+
config_option: T_RANGE symbol symbol if_expr T_EOL
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
@@ -664,6 +671,11 @@ static void print_symbol(FILE *out, struct menu *menu)
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
+ case P_IMPLY:
+ fputs( " imply ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 93721f3c91bf..030fc633acd4 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -204,6 +204,7 @@ EOF
## init lots of data
+
my $errors = 0;
my $warnings = 0;
my $anon_struct_union = 0;
@@ -211,7 +212,7 @@ my $anon_struct_union = 0;
# match expressions used to find embedded type information
my $type_constant = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
-my $type_param = '\@(\w+)';
+my $type_param = '\@(\w+(\.\.\.)?)';
my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_struct = '\&((struct\s*)*[_\w]+)';
my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
@@ -420,6 +421,7 @@ my $doc_block = $doc_com . 'DOC:\s*(.*)?';
my $doc_inline_start = '^\s*/\*\*\s*$';
my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
my $doc_inline_end = '^\s*\*/\s*$';
+my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
my %parameterdescs;
@@ -2353,7 +2355,10 @@ sub push_parameter($$$) {
if ($type eq "" && $param =~ /\.\.\.$/)
{
- $param = "...";
+ if (!$param =~ /\w\.\.\.$/) {
+ # handles unnamed variable parameters
+ $param = "...";
+ }
if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
$parameterdescs{$param} = "variable arguments";
}
@@ -3020,7 +3025,16 @@ sub process_file($) {
}
}
} elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype)
- if (/$doc_inline_start/) {
+ if (/$doc_inline_oneline/) {
+ $section = $1;
+ $contents = $2;
+ if ($contents ne "") {
+ $contents .= "\n";
+ dump_section($file, $section, xml_escape($contents));
+ $section = $section_default;
+ $contents = "";
+ }
+ } elsif (/$doc_inline_start/) {
$state = STATE_INLINE;
$inline_doc_state = STATE_INLINE_NAME;
} elsif ($decl_type eq 'function') {
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
index 53af6dc3e6c1..53af6dc3e6c1 100755..100644
--- a/scripts/sign-file.c
+++ b/scripts/sign-file.c
diff --git a/scripts/tags.sh b/scripts/tags.sh
index a2ff3388e5ea..df5fa777d300 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -304,11 +304,26 @@ if [ "${ARCH}" = "um" ]; then
elif [ "${SRCARCH}" = "arm" -a "${SUBARCH}" != "" ]; then
subarchdir=$(find ${tree}arch/$SRCARCH/ -name "mach-*" -type d -o \
-name "plat-*" -type d);
+ mach_suffix=$SUBARCH
+ plat_suffix=$SUBARCH
+
+ # Special cases when $plat_suffix != $mach_suffix
+ case $mach_suffix in
+ "omap1" | "omap2")
+ plat_suffix="omap"
+ ;;
+ esac
+
+ if [ ! -d ${tree}arch/$SRCARCH/mach-$mach_suffix ]; then
+ echo "Warning: arch/arm/mach-$mach_suffix/ not found." >&2
+ echo " Fix your \$SUBARCH appropriately" >&2
+ fi
+
for i in $subarchdir; do
case "$i" in
- *"mach-"${SUBARCH})
+ *"mach-"${mach_suffix})
;;
- *"plat-"${SUBARCH})
+ *"plat-"${plat_suffix})
;;
*)
subarchprune="$subarchprune \
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 09fd6108e421..38b79d797aaf 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2525,7 +2525,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
}
task_unlock(current);
- update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS))
+ update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
}
}
@@ -2555,9 +2556,11 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
*/
rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
if (rc) {
- memset(&itimer, 0, sizeof itimer);
- for (i = 0; i < 3; i++)
- do_setitimer(i, &itimer, NULL);
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
+ memset(&itimer, 0, sizeof itimer);
+ for (i = 0; i < 3; i++)
+ do_setitimer(i, &itimer, NULL);
+ }
spin_lock_irq(&current->sighand->siglock);
if (!fatal_signal_pending(current)) {
flush_sigqueue(&current->pending);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index f2e8226c88fb..21b228046e88 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -71,6 +71,7 @@ void __snd_printk(unsigned int level, const char *path, int line,
int kern_level;
struct va_format vaf;
char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
+ bool level_found = false;
#endif
#ifdef CONFIG_SND_DEBUG
@@ -83,15 +84,22 @@ void __snd_printk(unsigned int level, const char *path, int line,
vaf.fmt = format;
vaf.va = &args;
- kern_level = printk_get_level(format);
- if (kern_level) {
- const char *end_of_header = printk_skip_level(format);
- memcpy(verbose_fmt, format, end_of_header - format);
+ while ((kern_level = printk_get_level(vaf.fmt)) != 0) {
+ const char *end_of_header = printk_skip_level(vaf.fmt);
+
+ /* Ignore KERN_CONT. We print filename:line for each piece. */
+ if (kern_level >= '0' && kern_level <= '7') {
+ memcpy(verbose_fmt, vaf.fmt, end_of_header - vaf.fmt);
+ level_found = true;
+ }
+
vaf.fmt = end_of_header;
- } else if (level)
+ }
+
+ if (!level_found && level)
memcpy(verbose_fmt, KERN_DEBUG, sizeof(KERN_DEBUG) - 1);
- printk(verbose_fmt, sanity_file_name(path), line, &vaf);
+ printk(verbose_fmt, sanity_file_name(path), line, &vaf);
#else
vprintk(format, args);
#endif
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index c9af022676c2..0659bf389489 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -193,6 +193,7 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid)
* snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
* @codec: HDA codec
* @nid: the pin widget NID
+ * @dev_id: device identifier
* @rate: the sample rate to set
*
* This function is supposed to be used only by a HD-audio controller
@@ -201,18 +202,20 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid)
* This function sets N/CTS value based on the given sample rate.
* Returns zero for success, or a negative error code.
*/
-int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate)
+int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
+ int dev_id, int rate)
{
struct hdac_bus *bus = codec->bus;
struct i915_audio_component *acomp = bus->audio_component;
- int port;
+ int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
return -ENODEV;
port = pin2port(codec, nid);
if (port < 0)
return -EINVAL;
- return acomp->ops->sync_audio_rate(acomp->dev, port, rate);
+ pipe = dev_id;
+ return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
}
EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
@@ -220,6 +223,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
* snd_hdac_acomp_get_eld - Get the audio state and ELD via component
* @codec: HDA codec
* @nid: the pin widget NID
+ * @dev_id: device identifier
* @audio_enabled: the pointer to store the current audio state
* @buffer: the buffer pointer to store ELD bytes
* @max_bytes: the max bytes to be stored on @buffer
@@ -236,12 +240,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
* thus it may be over @max_bytes. If it's over @max_bytes, it implies
* that only a part of ELD bytes have been fetched.
*/
-int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
+int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes)
{
struct hdac_bus *bus = codec->bus;
struct i915_audio_component *acomp = bus->audio_component;
- int port;
+ int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->get_eld)
return -ENODEV;
@@ -249,7 +253,9 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
port = pin2port(codec, nid);
if (port < 0)
return -EINVAL;
- return acomp->ops->get_eld(acomp->dev, port, audio_enabled,
+
+ pipe = dev_id;
+ return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
buffer, max_bytes);
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 56e5204ac9c1..cf9bc042fe96 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1485,7 +1485,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
mutex_lock(&per_pin->lock);
eld->monitor_present = false;
- size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
+ size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, -1,
&eld->monitor_present, eld->eld_buffer,
ELD_MAX_SIZE);
if (size > 0) {
@@ -1744,7 +1744,8 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
/* Call sync_audio_rate to set the N/CTS/M manually if necessary */
/* Todo: add DP1.2 MST audio support later */
if (codec_has_acomp(codec))
- snd_hdac_sync_audio_rate(&codec->core, pin_nid, runtime->rate);
+ snd_hdac_sync_audio_rate(&codec->core, pin_nid, -1,
+ runtime->rate);
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
mutex_lock(&per_pin->lock);
@@ -2290,7 +2291,7 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
-static void intel_pin_eld_notify(void *audio_ptr, int port)
+static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
{
struct hda_codec *codec = audio_ptr;
int pin_nid;
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index c602c4960924..0c6228a0bf95 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -1368,7 +1368,7 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
return hdac_hdmi_init_dai_map(edev);
}
-static void hdac_hdmi_eld_notify_cb(void *aptr, int port)
+static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
{
struct hdac_ext_device *edev = aptr;
struct hdac_hdmi_priv *hdmi = edev->private_data;
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..00caacd3ed92 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -17,6 +17,7 @@ help:
@echo ' hv - tools used when in Hyper-V clients'
@echo ' iio - IIO tools'
@echo ' kvm_stat - top-like utility for displaying kvm statistics'
+ @echo ' leds - LEDs tools'
@echo ' lguest - a minimal 32-bit x86 hypervisor'
@echo ' net - misc networking tools'
@echo ' perf - Linux performance measurement and analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
cpupower: FORCE
$(call descend,power/$@)
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds: FORCE
$(call descend,$@)
liblockdep: FORCE
@@ -126,7 +127,7 @@ acpi_clean:
cpupower_clean:
$(call descend,power/cpupower,clean)
-cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean:
+cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean:
$(call descend,$(@:_clean=),clean)
liblockdep_clean:
@@ -164,6 +165,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_cle
perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
- gpio_clean objtool_clean
+ gpio_clean objtool_clean leds_clean
.PHONY: FORCE
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index a39629206864..cddd5d06e1cb 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -104,7 +104,6 @@
#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
-#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
diff --git a/tools/build/Build.include b/tools/build/Build.include
index 1dcb95e76f70..418871d02ebf 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -65,22 +65,22 @@ dep-cmd = $(if $(wildcard $(fixdep)),
printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \
cat $(depfile) >> $(dot-target).cmd; \
- printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
+ printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
###
# if_changed_dep - execute command if any prerequisite is newer than
# target, or command line has changed and update
# dependencies in the cmd file
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
- @set -e; \
- $(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
+ @set -e; \
+ $(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
# if_changed - execute command if any prerequisite is newer than
# target, or command line has changed
-if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
- @set -e; \
- $(echo-cmd) $(cmd_$(1)); \
- printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
+if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
+ @set -e; \
+ $(echo-cmd) $(cmd_$(1)); \
+ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
###
# C flags to be used in rule definitions, includes:
@@ -89,10 +89,12 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
# - per target C flags
# - per object C flags
# - BUILD_STR macro to allow '-D"$(variable)"' constructs
-c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
-cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
+c_flags_1 = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
+c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1))
+c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2))
+cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
###
## HOSTCC C flags
-host_c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
+host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index a47bffbae159..a22587475dbe 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -135,8 +135,10 @@ CFLAGS
It's possible to alter the standard object C flags in the following way:
- CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
- CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
+ CFLAGS_perf.o += '...' - adds CFLAGS for perf.o object
+ CFLAGS_gtk += '...' - adds CFLAGS for gtk build object
+ CFLAGS_REMOVE_perf.o += '...' - removes CFLAGS for perf.o object
+ CFLAGS_REMOVE_gtk += '...' - removes CFLAGS for gtk build object
This C flags changes has the scope of the Build makefile they are defined in.
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index ae52e029dd22..e3fb5ecbdcb6 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -27,58 +27,58 @@ endef
# the rule that uses them - an example for that is the 'bionic'
# feature check. ]
#
-FEATURE_TESTS_BASIC := \
- backtrace \
- dwarf \
- dwarf_getlocations \
- fortify-source \
- sync-compare-and-swap \
- glibc \
- gtk2 \
- gtk2-infobar \
- libaudit \
- libbfd \
- libelf \
- libelf-getphdrnum \
- libelf-gelf_getnote \
- libelf-getshdrstrndx \
- libelf-mmap \
- libnuma \
- numa_num_possible_cpus \
- libperl \
- libpython \
- libpython-version \
- libslang \
- libcrypto \
- libunwind \
- libunwind-x86 \
- libunwind-x86_64 \
- libunwind-arm \
- libunwind-aarch64 \
- pthread-attr-setaffinity-np \
- stackprotector-all \
- timerfd \
- libdw-dwarf-unwind \
- zlib \
- lzma \
- get_cpuid \
- bpf \
- sdt
+FEATURE_TESTS_BASIC := \
+ backtrace \
+ dwarf \
+ dwarf_getlocations \
+ fortify-source \
+ sync-compare-and-swap \
+ glibc \
+ gtk2 \
+ gtk2-infobar \
+ libaudit \
+ libbfd \
+ libelf \
+ libelf-getphdrnum \
+ libelf-gelf_getnote \
+ libelf-getshdrstrndx \
+ libelf-mmap \
+ libnuma \
+ numa_num_possible_cpus \
+ libperl \
+ libpython \
+ libpython-version \
+ libslang \
+ libcrypto \
+ libunwind \
+ libunwind-x86 \
+ libunwind-x86_64 \
+ libunwind-arm \
+ libunwind-aarch64 \
+ pthread-attr-setaffinity-np \
+ stackprotector-all \
+ timerfd \
+ libdw-dwarf-unwind \
+ zlib \
+ lzma \
+ get_cpuid \
+ bpf \
+ sdt
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
# of all feature tests
-FEATURE_TESTS_EXTRA := \
- bionic \
- compile-32 \
- compile-x32 \
- cplus-demangle \
- hello \
- libbabeltrace \
- liberty \
- liberty-z \
- libunwind-debug-frame \
- libunwind-debug-frame-arm \
- libunwind-debug-frame-aarch64
+FEATURE_TESTS_EXTRA := \
+ bionic \
+ compile-32 \
+ compile-x32 \
+ cplus-demangle \
+ hello \
+ libbabeltrace \
+ liberty \
+ liberty-z \
+ libunwind-debug-frame \
+ libunwind-debug-frame-arm \
+ libunwind-debug-frame-aarch64
FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
@@ -86,26 +86,26 @@ ifeq ($(FEATURE_TESTS),all)
FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA)
endif
-FEATURE_DISPLAY ?= \
- dwarf \
- dwarf_getlocations \
- glibc \
- gtk2 \
- libaudit \
- libbfd \
- libelf \
- libnuma \
- numa_num_possible_cpus \
- libperl \
- libpython \
- libslang \
- libcrypto \
- libunwind \
- libdw-dwarf-unwind \
- zlib \
- lzma \
- get_cpuid \
- bpf
+FEATURE_DISPLAY ?= \
+ dwarf \
+ dwarf_getlocations \
+ glibc \
+ gtk2 \
+ libaudit \
+ libbfd \
+ libelf \
+ libnuma \
+ numa_num_possible_cpus \
+ libperl \
+ libpython \
+ libslang \
+ libcrypto \
+ libunwind \
+ libdw-dwarf-unwind \
+ zlib \
+ lzma \
+ get_cpuid \
+ bpf
# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
# If in the future we need per-feature checks/flags for features not
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index ac9c477a2a48..b564a2eea039 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -1,59 +1,61 @@
-FILES= \
- test-all.bin \
- test-backtrace.bin \
- test-bionic.bin \
- test-dwarf.bin \
- test-dwarf_getlocations.bin \
- test-fortify-source.bin \
- test-sync-compare-and-swap.bin \
- test-glibc.bin \
- test-gtk2.bin \
- test-gtk2-infobar.bin \
- test-hello.bin \
- test-libaudit.bin \
- test-libbfd.bin \
- test-liberty.bin \
- test-liberty-z.bin \
- test-cplus-demangle.bin \
- test-libelf.bin \
- test-libelf-getphdrnum.bin \
- test-libelf-gelf_getnote.bin \
- test-libelf-getshdrstrndx.bin \
- test-libelf-mmap.bin \
- test-libnuma.bin \
- test-numa_num_possible_cpus.bin \
- test-libperl.bin \
- test-libpython.bin \
- test-libpython-version.bin \
- test-libslang.bin \
- test-libcrypto.bin \
- test-libunwind.bin \
- test-libunwind-debug-frame.bin \
- test-libunwind-x86.bin \
- test-libunwind-x86_64.bin \
- test-libunwind-arm.bin \
- test-libunwind-aarch64.bin \
- test-libunwind-debug-frame-arm.bin \
- test-libunwind-debug-frame-aarch64.bin \
- test-pthread-attr-setaffinity-np.bin \
- test-stackprotector-all.bin \
- test-timerfd.bin \
- test-libdw-dwarf-unwind.bin \
- test-libbabeltrace.bin \
- test-compile-32.bin \
- test-compile-x32.bin \
- test-zlib.bin \
- test-lzma.bin \
- test-bpf.bin \
- test-get_cpuid.bin \
- test-sdt.bin \
- test-cxx.bin
+FILES= \
+ test-all.bin \
+ test-backtrace.bin \
+ test-bionic.bin \
+ test-dwarf.bin \
+ test-dwarf_getlocations.bin \
+ test-fortify-source.bin \
+ test-sync-compare-and-swap.bin \
+ test-glibc.bin \
+ test-gtk2.bin \
+ test-gtk2-infobar.bin \
+ test-hello.bin \
+ test-libaudit.bin \
+ test-libbfd.bin \
+ test-liberty.bin \
+ test-liberty-z.bin \
+ test-cplus-demangle.bin \
+ test-libelf.bin \
+ test-libelf-getphdrnum.bin \
+ test-libelf-gelf_getnote.bin \
+ test-libelf-getshdrstrndx.bin \
+ test-libelf-mmap.bin \
+ test-libnuma.bin \
+ test-numa_num_possible_cpus.bin \
+ test-libperl.bin \
+ test-libpython.bin \
+ test-libpython-version.bin \
+ test-libslang.bin \
+ test-libcrypto.bin \
+ test-libunwind.bin \
+ test-libunwind-debug-frame.bin \
+ test-libunwind-x86.bin \
+ test-libunwind-x86_64.bin \
+ test-libunwind-arm.bin \
+ test-libunwind-aarch64.bin \
+ test-libunwind-debug-frame-arm.bin \
+ test-libunwind-debug-frame-aarch64.bin \
+ test-pthread-attr-setaffinity-np.bin \
+ test-stackprotector-all.bin \
+ test-timerfd.bin \
+ test-libdw-dwarf-unwind.bin \
+ test-libbabeltrace.bin \
+ test-compile-32.bin \
+ test-compile-x32.bin \
+ test-zlib.bin \
+ test-lzma.bin \
+ test-bpf.bin \
+ test-get_cpuid.bin \
+ test-sdt.bin \
+ test-cxx.bin \
+ test-jvmti.bin
FILES := $(addprefix $(OUTPUT),$(FILES))
CC := $(CROSS_COMPILE)gcc -MD
CXX := $(CROSS_COMPILE)g++ -MD
PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
all: $(FILES)
@@ -225,6 +227,30 @@ $(OUTPUT)test-sdt.bin:
$(OUTPUT)test-cxx.bin:
$(BUILDXX) -std=gnu++11
+$(OUTPUT)test-jvmti.bin:
+ $(BUILD)
+
+$(OUTPUT)test-llvm.bin:
+ $(BUILDXX) -std=gnu++11 \
+ -I$(shell $(LLVM_CONFIG) --includedir) \
+ -L$(shell $(LLVM_CONFIG) --libdir) \
+ $(shell $(LLVM_CONFIG) --libs Core BPF) \
+ $(shell $(LLVM_CONFIG) --system-libs)
+
+$(OUTPUT)test-llvm-version.bin:
+ $(BUILDXX) -std=gnu++11 \
+ -I$(shell $(LLVM_CONFIG) --includedir)
+
+$(OUTPUT)test-clang.bin:
+ $(BUILDXX) -std=gnu++11 \
+ -I$(shell $(LLVM_CONFIG) --includedir) \
+ -L$(shell $(LLVM_CONFIG) --libdir) \
+ -Wl,--start-group -lclangBasic -lclangDriver \
+ -lclangFrontend -lclangEdit -lclangLex \
+ -lclangAST -Wl,--end-group \
+ $(shell $(LLVM_CONFIG) --libs Core option) \
+ $(shell $(LLVM_CONFIG) --system-libs)
+
-include $(OUTPUT)*.d
###############################
diff --git a/tools/build/feature/test-clang.cpp b/tools/build/feature/test-clang.cpp
new file mode 100644
index 000000000000..e23c1b1f1b91
--- /dev/null
+++ b/tools/build/feature/test-clang.cpp
@@ -0,0 +1,21 @@
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+int main()
+{
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts);
+ Driver TheDriver("test", "bpf-pc-linux", Diags);
+
+ llvm::llvm_shutdown();
+ return 0;
+}
diff --git a/tools/build/feature/test-jvmti.c b/tools/build/feature/test-jvmti.c
new file mode 100644
index 000000000000..1c665f09b9d6
--- /dev/null
+++ b/tools/build/feature/test-jvmti.c
@@ -0,0 +1,13 @@
+#include <jvmti.h>
+#include <jvmticmlr.h>
+
+int main(void)
+{
+ JavaVM jvm __attribute__((unused));
+ jvmtiEventCallbacks cb __attribute__((unused));
+ jvmtiCapabilities caps __attribute__((unused));
+ jvmtiJlocationFormat format __attribute__((unused));
+ jvmtiEnv jvmti __attribute__((unused));
+
+ return 0;
+}
diff --git a/tools/build/feature/test-llvm-version.cpp b/tools/build/feature/test-llvm-version.cpp
new file mode 100644
index 000000000000..896d31724568
--- /dev/null
+++ b/tools/build/feature/test-llvm-version.cpp
@@ -0,0 +1,11 @@
+#include <cstdio>
+#include "llvm/Config/llvm-config.h"
+
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH)
+#define pass int main() {printf("%x\n", NUM_VERSION); return 0;}
+
+#if NUM_VERSION >= 0x030900
+pass
+#else
+# error This LLVM is not tested yet.
+#endif
diff --git a/tools/build/feature/test-llvm.cpp b/tools/build/feature/test-llvm.cpp
new file mode 100644
index 000000000000..455a332dc8a8
--- /dev/null
+++ b/tools/build/feature/test-llvm.cpp
@@ -0,0 +1,13 @@
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH)
+
+#if NUM_VERSION < 0x030900
+# error "LLVM version too low"
+#endif
+int main()
+{
+ llvm::errs() << "Hello World!\n";
+ llvm::llvm_shutdown();
+ return 0;
+}
diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c
index 1521d36cef0d..734d1547cbae 100644
--- a/tools/build/fixdep.c
+++ b/tools/build/fixdep.c
@@ -49,7 +49,7 @@ static void parse_dep_file(void *map, size_t len)
char *end = m + len;
char *p;
char s[PATH_MAX];
- int is_target;
+ int is_target, has_target = 0;
int saw_any_target = 0;
int is_first_dep = 0;
@@ -67,7 +67,8 @@ static void parse_dep_file(void *map, size_t len)
if (is_target) {
/* The /next/ file is the first dependency */
is_first_dep = 1;
- } else {
+ has_target = 1;
+ } else if (has_target) {
/* Save this token/filename */
memcpy(s, m, p-m);
s[p - m] = 0;
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c
index 37b3f141053d..f1eab587dfea 100644
--- a/tools/gpio/gpio-hammer.c
+++ b/tools/gpio/gpio-hammer.c
@@ -23,54 +23,31 @@
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>
+#include "gpio-utils.h"
int hammer_device(const char *device_name, unsigned int *lines, int nlines,
unsigned int loops)
{
- struct gpiohandle_request req;
struct gpiohandle_data data;
- char *chrdev_name;
char swirr[] = "-\\|/";
int fd;
int ret;
int i, j;
unsigned int iteration = 0;
- ret = asprintf(&chrdev_name, "/dev/%s", device_name);
+ memset(&data.values, 0, sizeof(data.values));
+ ret = gpiotools_request_linehandle(device_name, lines, nlines,
+ GPIOHANDLE_REQUEST_OUTPUT, &data,
+ "gpio-hammler");
if (ret < 0)
- return -ENOMEM;
+ goto exit_error;
+ else
+ fd = ret;
- fd = open(chrdev_name, 0);
- if (fd == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to open %s\n", chrdev_name);
- goto exit_close_error;
- }
-
- /* Request lines as output */
- for (i = 0; i < nlines; i++)
- req.lineoffsets[i] = lines[i];
- req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */
- strcpy(req.consumer_label, "gpio-hammer");
- req.lines = nlines;
- ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GET LINEHANDLE "
- "IOCTL (%d)\n",
- ret);
+ ret = gpiotools_get_values(fd, &data);
+ if (ret < 0)
goto exit_close_error;
- }
- /* Read initial states */
- ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
- "VALUES IOCTL (%d)\n",
- ret);
- goto exit_close_error;
- }
fprintf(stdout, "Hammer lines [");
for (i = 0; i < nlines; i++) {
fprintf(stdout, "%d", lines[i]);
@@ -92,23 +69,14 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines,
for (i = 0; i < nlines; i++)
data.values[i] = !data.values[i];
- ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GPIOHANDLE SET LINE "
- "VALUES IOCTL (%d)\n",
- ret);
+ ret = gpiotools_set_values(fd, &data);
+ if (ret < 0)
goto exit_close_error;
- }
+
/* Re-read values to get status */
- ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
- "VALUES IOCTL (%d)\n",
- ret);
+ ret = gpiotools_get_values(fd, &data);
+ if (ret < 0)
goto exit_close_error;
- }
fprintf(stdout, "[%c] ", swirr[j]);
j++;
@@ -132,9 +100,8 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines,
ret = 0;
exit_close_error:
- if (close(fd) == -1)
- perror("Failed to close GPIO character device file");
- free(chrdev_name);
+ gpiotools_release_linehandle(fd);
+exit_error:
return ret;
}
diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c
index 8208718f2c99..b86a32d90d88 100644
--- a/tools/gpio/gpio-utils.c
+++ b/tools/gpio/gpio-utils.c
@@ -2,10 +2,266 @@
* GPIO tools - helpers library for the GPIO tools
*
* Copyright (C) 2015 Linus Walleij
+ * Copyright (C) 2016 Bamvor Jian Zhang
*
* 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 <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <linux/gpio.h>
#include "gpio-utils.h"
+
+#define COMSUMER "gpio-utils"
+
+/**
+ * doc: Operation of gpio
+ *
+ * Provide the api of gpiochip for chardev interface. There are two
+ * types of api. The first one provide as same function as each
+ * ioctl, including request and release for lines of gpio, read/write
+ * the value of gpio. If the user want to do lots of read and write of
+ * lines of gpio, user should use this type of api.
+ *
+ * The second one provide the easy to use api for user. Each of the
+ * following api will request gpio lines, do the operation and then
+ * release these lines.
+ */
+/**
+ * gpiotools_request_linehandle() - request gpio lines in a gpiochip
+ * @device_name: The name of gpiochip without prefix "/dev/",
+ * such as "gpiochip0"
+ * @lines: An array desired lines, specified by offset
+ * index for the associated GPIO device.
+ * @nline: The number of lines to request.
+ * @flag: The new flag for requsted gpio. Reference
+ * "linux/gpio.h" for the meaning of flag.
+ * @data: Default value will be set to gpio when flag is
+ * GPIOHANDLE_REQUEST_OUTPUT.
+ * @consumer_label: The name of consumer, such as "sysfs",
+ * "powerkey". This is useful for other users to
+ * know who is using.
+ *
+ * Request gpio lines through the ioctl provided by chardev. User
+ * could call gpiotools_set_values() and gpiotools_get_values() to
+ * read and write respectively through the returned fd. Call
+ * gpiotools_release_linehandle() to release these lines after that.
+ *
+ * Return: On success return the fd;
+ * On failure return the errno.
+ */
+int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
+ unsigned int nlines, unsigned int flag,
+ struct gpiohandle_data *data,
+ const char *consumer_label)
+{
+ struct gpiohandle_request req;
+ char *chrdev_name;
+ int fd;
+ int i;
+ int ret;
+
+ ret = asprintf(&chrdev_name, "/dev/%s", device_name);
+ if (ret < 0)
+ return -ENOMEM;
+
+ fd = open(chrdev_name, 0);
+ if (fd == -1) {
+ ret = -errno;
+ fprintf(stderr, "Failed to open %s\n", chrdev_name);
+ goto exit_close_error;
+ }
+
+ for (i = 0; i < nlines; i++)
+ req.lineoffsets[i] = lines[i];
+
+ req.flags = flag;
+ strcpy(req.consumer_label, consumer_label);
+ req.lines = nlines;
+ if (flag & GPIOHANDLE_REQUEST_OUTPUT)
+ memcpy(req.default_values, data, sizeof(req.default_values));
+
+ ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret == -1) {
+ ret = -errno;
+ fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
+ ret);
+ }
+
+exit_close_error:
+ if (close(fd) == -1)
+ perror("Failed to close GPIO character device file");
+ free(chrdev_name);
+ return ret < 0 ? ret : req.fd;
+}
+/**
+ * gpiotools_set_values(): Set the value of gpio(s)
+ * @fd: The fd returned by
+ * gpiotools_request_linehandle().
+ * @data: The array of values want to set.
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
+{
+ int ret;
+
+ ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
+ if (ret == -1) {
+ ret = -errno;
+ fprintf(stderr, "Failed to issue %s (%d)\n",
+ "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
+ }
+
+ return ret;
+}
+
+/**
+ * gpiotools_get_values(): Get the value of gpio(s)
+ * @fd: The fd returned by
+ * gpiotools_request_linehandle().
+ * @data: The array of values get from hardware.
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
+{
+ int ret;
+
+ ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
+ if (ret == -1) {
+ ret = -errno;
+ fprintf(stderr, "Failed to issue %s (%d)\n",
+ "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret);
+ }
+
+ return ret;
+}
+
+/**
+ * gpiotools_release_linehandle(): Release the line(s) of gpiochip
+ * @fd: The fd returned by
+ * gpiotools_request_linehandle().
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_release_linehandle(const int fd)
+{
+ int ret;
+
+ ret = close(fd);
+ if (ret == -1) {
+ perror("Failed to close GPIO LINEHANDLE device file");
+ ret = -errno;
+ }
+
+ return ret;
+}
+
+/**
+ * gpiotools_get(): Get value from specific line
+ * @device_name: The name of gpiochip without prefix "/dev/",
+ * such as "gpiochip0"
+ * @line: number of line, such as 2.
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_get(const char *device_name, unsigned int line)
+{
+ struct gpiohandle_data data;
+ unsigned int lines[] = {line};
+
+ gpiotools_gets(device_name, lines, 1, &data);
+ return data.values[0];
+}
+
+
+/**
+ * gpiotools_gets(): Get values from specific lines.
+ * @device_name: The name of gpiochip without prefix "/dev/",
+ * such as "gpiochip0".
+ * @lines: An array desired lines, specified by offset
+ * index for the associated GPIO device.
+ * @nline: The number of lines to request.
+ * @data: The array of values get from gpiochip.
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_gets(const char *device_name, unsigned int *lines,
+ unsigned int nlines, struct gpiohandle_data *data)
+{
+ int fd;
+ int ret;
+ int ret_close;
+
+ ret = gpiotools_request_linehandle(device_name, lines, nlines,
+ GPIOHANDLE_REQUEST_INPUT, data,
+ COMSUMER);
+ if (ret < 0)
+ return ret;
+
+ fd = ret;
+ ret = gpiotools_get_values(fd, data);
+ ret_close = gpiotools_release_linehandle(fd);
+ return ret < 0 ? ret : ret_close;
+}
+
+/**
+ * gpiotools_set(): Set value to specific line
+ * @device_name: The name of gpiochip without prefix "/dev/",
+ * such as "gpiochip0"
+ * @line: number of line, such as 2.
+ * @value: The value of gpio, must be 0(low) or 1(high).
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_set(const char *device_name, unsigned int line,
+ unsigned int value)
+{
+ struct gpiohandle_data data;
+ unsigned int lines[] = {line};
+
+ data.values[0] = value;
+ return gpiotools_sets(device_name, lines, 1, &data);
+}
+
+/**
+ * gpiotools_sets(): Set values to specific lines.
+ * @device_name: The name of gpiochip without prefix "/dev/",
+ * such as "gpiochip0".
+ * @lines: An array desired lines, specified by offset
+ * index for the associated GPIO device.
+ * @nline: The number of lines to request.
+ * @data: The array of values set to gpiochip, must be
+ * 0(low) or 1(high).
+ *
+ * Return: On success return 0;
+ * On failure return the errno.
+ */
+int gpiotools_sets(const char *device_name, unsigned int *lines,
+ unsigned int nlines, struct gpiohandle_data *data)
+{
+ int ret;
+
+ ret = gpiotools_request_linehandle(device_name, lines, nlines,
+ GPIOHANDLE_REQUEST_OUTPUT, data,
+ COMSUMER);
+ if (ret < 0)
+ return ret;
+
+ return gpiotools_release_linehandle(ret);
+}
diff --git a/tools/gpio/gpio-utils.h b/tools/gpio/gpio-utils.h
index 5f57133b8c04..344ea041f8d4 100644
--- a/tools/gpio/gpio-utils.h
+++ b/tools/gpio/gpio-utils.h
@@ -24,4 +24,20 @@ static inline int check_prefix(const char *str, const char *prefix)
strncmp(str, prefix, strlen(prefix)) == 0;
}
+int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
+ unsigned int nlines, unsigned int flag,
+ struct gpiohandle_data *data,
+ const char *consumer_label);
+int gpiotools_set_values(const int fd, struct gpiohandle_data *data);
+int gpiotools_get_values(const int fd, struct gpiohandle_data *data);
+int gpiotools_release_linehandle(const int fd);
+
+int gpiotools_get(const char *device_name, unsigned int line);
+int gpiotools_gets(const char *device_name, unsigned int *lines,
+ unsigned int nlines, struct gpiohandle_data *data);
+int gpiotools_set(const char *device_name, unsigned int line,
+ unsigned int value);
+int gpiotools_sets(const char *device_name, unsigned int *lines,
+ unsigned int nlines, struct gpiohandle_data *data);
+
#endif /* _GPIO_UTILS_H_ */
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh
index 8e960234013d..4aa5369ffa4e 100755
--- a/tools/hv/bondvf.sh
+++ b/tools/hv/bondvf.sh
@@ -74,8 +74,8 @@ function create_eth_cfg_redhat {
echo DEVICE=$1 >>$fn
echo TYPE=Ethernet >>$fn
echo BOOTPROTO=none >>$fn
+ echo UUID=`uuidgen` >>$fn
echo ONBOOT=yes >>$fn
- echo NM_CONTROLLED=no >>$fn
echo PEERDNS=yes >>$fn
echo IPV6INIT=yes >>$fn
echo MASTER=$2 >>$fn
@@ -93,8 +93,8 @@ function create_bond_cfg_redhat {
echo DEVICE=$1 >>$fn
echo TYPE=Bond >>$fn
echo BOOTPROTO=dhcp >>$fn
+ echo UUID=`uuidgen` >>$fn
echo ONBOOT=yes >>$fn
- echo NM_CONTROLLED=no >>$fn
echo PEERDNS=yes >>$fn
echo IPV6INIT=yes >>$fn
echo BONDING_MASTER=yes >>$fn
diff --git a/tools/include/asm-generic/bitops.h b/tools/include/asm-generic/bitops.h
index 653d1bad77de..0304600121da 100644
--- a/tools/include/asm-generic/bitops.h
+++ b/tools/include/asm-generic/bitops.h
@@ -13,6 +13,7 @@
*/
#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/__ffz.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
diff --git a/tools/include/asm-generic/bitops/__ffz.h b/tools/include/asm-generic/bitops/__ffz.h
new file mode 100644
index 000000000000..6744bd4cdf46
--- /dev/null
+++ b/tools/include/asm-generic/bitops/__ffz.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_GENERIC_BITOPS_FFZ_H_
+#define _ASM_GENERIC_BITOPS_FFZ_H_
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+#define ffz(x) __ffs(~(x))
+
+#endif /* _ASM_GENERIC_BITOPS_FFZ_H_ */
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h
index 31f51547fcd4..5538ecdc964a 100644
--- a/tools/include/asm-generic/bitops/find.h
+++ b/tools/include/asm-generic/bitops/find.h
@@ -15,6 +15,21 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
size, unsigned long offset);
#endif
+#ifndef find_next_zero_bit
+
+/**
+ * find_next_zero_bit - find the next cleared bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ *
+ * Returns the bit number of the next zero bit
+ * If no bits are zero, returns @size.
+ */
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset);
+#endif
+
#ifndef find_first_bit
/**
@@ -30,4 +45,17 @@ extern unsigned long find_first_bit(const unsigned long *addr,
#endif /* find_first_bit */
+#ifndef find_first_zero_bit
+
+/**
+ * find_first_zero_bit - find the first cleared bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum number of bits to search
+ *
+ * Returns the bit number of the first cleared bit.
+ * If no bits are zero, returns @size.
+ */
+unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size);
+#endif
+
#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 49c929a104ee..fc446343ff41 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -39,6 +39,11 @@ extern unsigned long __sw_hweight64(__u64 w);
(bit) < (size); \
(bit) = find_next_bit((addr), (size), (bit) + 1))
+#define for_each_clear_bit(bit, addr, size) \
+ for ((bit) = find_first_zero_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
+
/* same as for_each_set_bit() but use bit as value to start with */
#define for_each_set_bit_from(bit, addr, size) \
for ((bit) = find_next_bit((addr), (size), (bit)); \
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h
index 3276625595b2..122153b16ea4 100644
--- a/tools/include/linux/filter.h
+++ b/tools/include/linux/filter.h
@@ -218,6 +218,30 @@
.off = OFF, \
.imm = IMM })
+/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
+
+#define BPF_LD_IMM64(DST, IMM) \
+ BPF_LD_IMM64_RAW(DST, 0, IMM)
+
+#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
+ ((struct bpf_insn) { \
+ .code = BPF_LD | BPF_DW | BPF_IMM, \
+ .dst_reg = DST, \
+ .src_reg = SRC, \
+ .off = 0, \
+ .imm = (__u32) (IMM) }), \
+ ((struct bpf_insn) { \
+ .code = 0, /* zero is reserved opcode */ \
+ .dst_reg = 0, \
+ .src_reg = 0, \
+ .off = 0, \
+ .imm = ((__u64) (IMM)) >> 32 })
+
+/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */
+
+#define BPF_LD_MAP_FD(DST, MAP_FD) \
+ BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
+
/* Program exit */
#define BPF_EXIT_INSN() \
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
index 58274382a616..8c27db0c5c08 100644
--- a/tools/include/uapi/asm-generic/mman-common.h
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -72,4 +72,9 @@
#define MAP_HUGE_SHIFT 26
#define MAP_HUGE_MASK 0x3f
+#define PKEY_DISABLE_ACCESS 0x1
+#define PKEY_DISABLE_WRITE 0x2
+#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
+ PKEY_DISABLE_WRITE)
+
#endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/tools/leds/.gitignore b/tools/leds/.gitignore
new file mode 100644
index 000000000000..ac96d9f53dfc
--- /dev/null
+++ b/tools/leds/.gitignore
@@ -0,0 +1 @@
+uledmon
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
new file mode 100644
index 000000000000..c03a79ebf9c8
--- /dev/null
+++ b/tools/leds/Makefile
@@ -0,0 +1,13 @@
+# Makefile for LEDs tools
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra -g -I../../include/uapi
+
+all: uledmon
+%: %.c
+ $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+ $(RM) uledmon
+
+.PHONY: all clean
diff --git a/tools/leds/uledmon.c b/tools/leds/uledmon.c
new file mode 100644
index 000000000000..25cbc7acf50a
--- /dev/null
+++ b/tools/leds/uledmon.c
@@ -0,0 +1,63 @@
+/*
+ * uledmon.c
+ *
+ * This program creates a new userspace LED class device and monitors it. A
+ * timestamp and brightness value is printed each time the brightness changes.
+ *
+ * Usage: uledmon <device-name>
+ *
+ * <device-name> is the name of the LED class device to be created. Pressing
+ * CTRL+C will exit.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/uleds.h>
+
+int main(int argc, char const *argv[])
+{
+ struct uleds_user_dev uleds_dev;
+ int fd, ret;
+ int brightness;
+ struct timespec ts;
+
+ if (argc != 2) {
+ fprintf(stderr, "Requires <device-name> argument\n");
+ return 1;
+ }
+
+ strncpy(uleds_dev.name, argv[1], LED_MAX_NAME_SIZE);
+ uleds_dev.max_brightness = 100;
+
+ fd = open("/dev/uleds", O_RDWR);
+ if (fd == -1) {
+ perror("Failed to open /dev/uleds");
+ return 1;
+ }
+
+ ret = write(fd, &uleds_dev, sizeof(uleds_dev));
+ if (ret == -1) {
+ perror("Failed to write to /dev/uleds");
+ close(fd);
+ return 1;
+ }
+
+ while (1) {
+ ret = read(fd, &brightness, sizeof(brightness));
+ if (ret == -1) {
+ perror("Failed to read from /dev/uleds");
+ close(fd);
+ return 1;
+ }
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ printf("[%ld.%09ld] %u\n", ts.tv_sec, ts.tv_nsec, brightness);
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 4212ed62235b..8143536b462a 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -110,3 +110,59 @@ int bpf_map_update_elem(int fd, void *key, void *value,
return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}
+
+int bpf_map_lookup_elem(int fd, void *key, void *value)
+{
+ union bpf_attr attr;
+
+ bzero(&attr, sizeof(attr));
+ attr.map_fd = fd;
+ attr.key = ptr_to_u64(key);
+ attr.value = ptr_to_u64(value);
+
+ return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_delete_elem(int fd, void *key)
+{
+ union bpf_attr attr;
+
+ bzero(&attr, sizeof(attr));
+ attr.map_fd = fd;
+ attr.key = ptr_to_u64(key);
+
+ return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
+{
+ union bpf_attr attr;
+
+ bzero(&attr, sizeof(attr));
+ attr.map_fd = fd;
+ attr.key = ptr_to_u64(key);
+ attr.next_key = ptr_to_u64(next_key);
+
+ return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+int bpf_obj_pin(int fd, const char *pathname)
+{
+ union bpf_attr attr;
+
+ bzero(&attr, sizeof(attr));
+ attr.pathname = ptr_to_u64((void *)pathname);
+ attr.bpf_fd = fd;
+
+ return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+}
+
+int bpf_obj_get(const char *pathname)
+{
+ union bpf_attr attr;
+
+ bzero(&attr, sizeof(attr));
+ attr.pathname = ptr_to_u64((void *)pathname);
+
+ return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index e8ba54087497..253c3dbb06b4 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -35,4 +35,11 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
int bpf_map_update_elem(int fd, void *key, void *value,
u64 flags);
+
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_delete_elem(int fd, void *key);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
+int bpf_obj_pin(int fd, const char *pathname);
+int bpf_obj_get(const char *pathname);
+
#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b699aea9a025..2e974593f3e8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -185,6 +185,7 @@ struct bpf_program {
struct bpf_map {
int fd;
char *name;
+ size_t offset;
struct bpf_map_def def;
void *priv;
bpf_map_clear_priv_t clear_priv;
@@ -228,6 +229,10 @@ struct bpf_object {
* all objects.
*/
struct list_head list;
+
+ void *priv;
+ bpf_object_clear_priv_t clear_priv;
+
char path[];
};
#define obj_elf_valid(o) ((o)->efile.elf)
@@ -513,57 +518,106 @@ bpf_object__init_kversion(struct bpf_object *obj,
}
static int
-bpf_object__init_maps(struct bpf_object *obj, void *data,
- size_t size)
+bpf_object__validate_maps(struct bpf_object *obj)
{
- size_t nr_maps;
int i;
- nr_maps = size / sizeof(struct bpf_map_def);
- if (!data || !nr_maps) {
- pr_debug("%s doesn't need map definition\n",
- obj->path);
+ /*
+ * If there's only 1 map, the only error case should have been
+ * catched in bpf_object__init_maps().
+ */
+ if (!obj->maps || !obj->nr_maps || (obj->nr_maps == 1))
return 0;
- }
- pr_debug("maps in %s: %zd bytes\n", obj->path, size);
+ for (i = 1; i < obj->nr_maps; i++) {
+ const struct bpf_map *a = &obj->maps[i - 1];
+ const struct bpf_map *b = &obj->maps[i];
- obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
- if (!obj->maps) {
- pr_warning("alloc maps for object failed\n");
- return -ENOMEM;
+ if (b->offset - a->offset < sizeof(struct bpf_map_def)) {
+ pr_warning("corrupted map section in %s: map \"%s\" too small\n",
+ obj->path, a->name);
+ return -EINVAL;
+ }
}
- obj->nr_maps = nr_maps;
-
- for (i = 0; i < nr_maps; i++) {
- struct bpf_map_def *def = &obj->maps[i].def;
+ return 0;
+}
- /*
- * fill all fd with -1 so won't close incorrect
- * fd (fd=0 is stdin) when failure (zclose won't close
- * negative fd)).
- */
- obj->maps[i].fd = -1;
+static int compare_bpf_map(const void *_a, const void *_b)
+{
+ const struct bpf_map *a = _a;
+ const struct bpf_map *b = _b;
- /* Save map definition into obj->maps */
- *def = ((struct bpf_map_def *)data)[i];
- }
- return 0;
+ return a->offset - b->offset;
}
static int
-bpf_object__init_maps_name(struct bpf_object *obj)
+bpf_object__init_maps(struct bpf_object *obj)
{
- int i;
+ int i, map_idx, nr_maps = 0;
+ Elf_Scn *scn;
+ Elf_Data *data;
Elf_Data *symbols = obj->efile.symbols;
- if (!symbols || obj->efile.maps_shndx < 0)
+ if (obj->efile.maps_shndx < 0)
+ return -EINVAL;
+ if (!symbols)
+ return -EINVAL;
+
+ scn = elf_getscn(obj->efile.elf, obj->efile.maps_shndx);
+ if (scn)
+ data = elf_getdata(scn, NULL);
+ if (!scn || !data) {
+ pr_warning("failed to get Elf_Data from map section %d\n",
+ obj->efile.maps_shndx);
return -EINVAL;
+ }
+ /*
+ * Count number of maps. Each map has a name.
+ * Array of maps is not supported: only the first element is
+ * considered.
+ *
+ * TODO: Detect array of map and report error.
+ */
for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
GElf_Sym sym;
- size_t map_idx;
+
+ if (!gelf_getsym(symbols, i, &sym))
+ continue;
+ if (sym.st_shndx != obj->efile.maps_shndx)
+ continue;
+ nr_maps++;
+ }
+
+ /* Alloc obj->maps and fill nr_maps. */
+ pr_debug("maps in %s: %d maps in %zd bytes\n", obj->path,
+ nr_maps, data->d_size);
+
+ if (!nr_maps)
+ return 0;
+
+ obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
+ if (!obj->maps) {
+ pr_warning("alloc maps for object failed\n");
+ return -ENOMEM;
+ }
+ obj->nr_maps = nr_maps;
+
+ /*
+ * fill all fd with -1 so won't close incorrect
+ * fd (fd=0 is stdin) when failure (zclose won't close
+ * negative fd)).
+ */
+ for (i = 0; i < nr_maps; i++)
+ obj->maps[i].fd = -1;
+
+ /*
+ * Fill obj->maps using data in "maps" section.
+ */
+ for (i = 0, map_idx = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
+ GElf_Sym sym;
const char *map_name;
+ struct bpf_map_def *def;
if (!gelf_getsym(symbols, i, &sym))
continue;
@@ -573,21 +627,27 @@ bpf_object__init_maps_name(struct bpf_object *obj)
map_name = elf_strptr(obj->efile.elf,
obj->efile.strtabidx,
sym.st_name);
- map_idx = sym.st_value / sizeof(struct bpf_map_def);
- if (map_idx >= obj->nr_maps) {
- pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
- map_name, map_idx, obj->nr_maps);
- continue;
+ obj->maps[map_idx].offset = sym.st_value;
+ if (sym.st_value + sizeof(struct bpf_map_def) > data->d_size) {
+ pr_warning("corrupted maps section in %s: last map \"%s\" too small\n",
+ obj->path, map_name);
+ return -EINVAL;
}
+
obj->maps[map_idx].name = strdup(map_name);
if (!obj->maps[map_idx].name) {
pr_warning("failed to alloc map name\n");
return -ENOMEM;
}
- pr_debug("map %zu is \"%s\"\n", map_idx,
+ pr_debug("map %d is \"%s\"\n", map_idx,
obj->maps[map_idx].name);
+ def = (struct bpf_map_def *)(data->d_buf + sym.st_value);
+ obj->maps[map_idx].def = *def;
+ map_idx++;
}
- return 0;
+
+ qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), compare_bpf_map);
+ return bpf_object__validate_maps(obj);
}
static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -645,11 +705,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
err = bpf_object__init_kversion(obj,
data->d_buf,
data->d_size);
- else if (strcmp(name, "maps") == 0) {
- err = bpf_object__init_maps(obj, data->d_buf,
- data->d_size);
+ else if (strcmp(name, "maps") == 0)
obj->efile.maps_shndx = idx;
- } else if (sh.sh_type == SHT_SYMTAB) {
+ else if (sh.sh_type == SHT_SYMTAB) {
if (obj->efile.symbols) {
pr_warning("bpf: multiple SYMTAB in %s\n",
obj->path);
@@ -698,7 +756,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
return LIBBPF_ERRNO__FORMAT;
}
if (obj->efile.maps_shndx >= 0)
- err = bpf_object__init_maps_name(obj);
+ err = bpf_object__init_maps(obj);
out:
return err;
}
@@ -807,7 +865,7 @@ bpf_object__create_maps(struct bpf_object *obj)
zclose(obj->maps[j].fd);
return err;
}
- pr_debug("create map: fd=%d\n", *pfd);
+ pr_debug("create map %s: fd=%d\n", obj->maps[i].name, *pfd);
}
return 0;
@@ -1175,6 +1233,9 @@ void bpf_object__close(struct bpf_object *obj)
if (!obj)
return;
+ if (obj->clear_priv)
+ obj->clear_priv(obj, obj->priv);
+
bpf_object__elf_finish(obj);
bpf_object__unload(obj);
@@ -1228,6 +1289,22 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
return obj ? obj->kern_version : 0;
}
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+ bpf_object_clear_priv_t clear_priv)
+{
+ if (obj->priv && obj->clear_priv)
+ obj->clear_priv(obj, obj->priv);
+
+ obj->priv = priv;
+ obj->clear_priv = clear_priv;
+ return 0;
+}
+
+void *bpf_object__priv(struct bpf_object *obj)
+{
+ return obj ? obj->priv : ERR_PTR(-EINVAL);
+}
+
struct bpf_program *
bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
{
@@ -1447,3 +1524,15 @@ bpf_object__find_map_by_name(struct bpf_object *obj, const char *name)
}
return NULL;
}
+
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
+{
+ int i;
+
+ for (i = 0; i < obj->nr_maps; i++) {
+ if (obj->maps[i].offset == offset)
+ return &obj->maps[i];
+ }
+ return ERR_PTR(-ENOENT);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dd7a513efb10..a5a8b86a06fe 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <linux/err.h>
+#include <sys/types.h> // for size_t
enum libbpf_errno {
__LIBBPF_ERRNO__START = 4000,
@@ -79,6 +80,11 @@ struct bpf_object *bpf_object__next(struct bpf_object *prev);
(pos) != NULL; \
(pos) = (tmp), (tmp) = bpf_object__next(tmp))
+typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *);
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+ bpf_object_clear_priv_t clear_priv);
+void *bpf_object__priv(struct bpf_object *prog);
+
/* Accessors of bpf_program. */
struct bpf_program;
struct bpf_program *bpf_program__next(struct bpf_program *prog,
@@ -195,6 +201,13 @@ struct bpf_map;
struct bpf_map *
bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
+/*
+ * Get bpf_map through the offset of corresponding struct bpf_map_def
+ * in the bpf object file.
+ */
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
+
struct bpf_map *
bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
#define bpf_map__for_each(pos, obj) \
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c
index 9122a9e80046..6d8b8f22cf55 100644
--- a/tools/lib/find_bit.c
+++ b/tools/lib/find_bit.c
@@ -82,3 +82,28 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
return size;
}
#endif
+
+#ifndef find_first_zero_bit
+/*
+ * Find the first cleared bit in a memory region.
+ */
+unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
+{
+ unsigned long idx;
+
+ for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
+ if (addr[idx] != ~0UL)
+ return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
+ }
+
+ return size;
+}
+#endif
+
+#ifndef find_next_zero_bit
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ return _find_next_bit(addr, size, offset, ~0UL);
+}
+#endif
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 981bb4481fd5..3284bb14ae78 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -314,12 +314,19 @@ static int get_value(struct parse_opt_ctx_t *p,
static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
{
+retry:
for (; options->type != OPTION_END; options++) {
if (options->short_name == *p->opt) {
p->opt = p->opt[1] ? p->opt + 1 : NULL;
return get_value(p, options, OPT_SHORT);
}
}
+
+ if (options->parent) {
+ options = options->parent;
+ goto retry;
+ }
+
return -2;
}
@@ -333,6 +340,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
if (!arg_end)
arg_end = arg + strlen(arg);
+retry:
for (; options->type != OPTION_END; options++) {
const char *rest;
int flags = 0;
@@ -426,6 +434,12 @@ match:
}
if (abbrev_option)
return get_value(p, abbrev_option, abbrev_flags);
+
+ if (options->parent) {
+ options = options->parent;
+ goto retry;
+ }
+
return -2;
}
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index d60cab2726da..8866ac438b34 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -109,11 +109,13 @@ struct option {
intptr_t defval;
bool *set;
void *data;
+ const struct option *parent;
};
#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
#define OPT_END() { .type = OPTION_END }
+#define OPT_PARENT(p) { .type = OPTION_END, .parent = (p) }
#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 7851df1490e0..c76012ebdb9c 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -99,8 +99,6 @@ libdir_SQ = $(subst ','\'',$(libdir))
libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
-LIB_FILE = libtraceevent.a libtraceevent.so
-
CONFIG_INCLUDES =
CONFIG_LIBS =
CONFIG_FLAGS =
@@ -114,6 +112,9 @@ N =
EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
+LIB_TARGET = libtraceevent.a libtraceevent.so.$(EVENT_PARSE_VERSION)
+LIB_INSTALL = libtraceevent.a libtraceevent.so*
+
INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
# Set compile option CFLAGS
@@ -156,11 +157,11 @@ PLUGINS += plugin_cfg80211.so
PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS))
PLUGINS_IN := $(PLUGINS:.so=-in.o)
-TE_IN := $(OUTPUT)libtraceevent-in.o
-LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
+TE_IN := $(OUTPUT)libtraceevent-in.o
+LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET))
DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list
-CMD_TARGETS = $(LIB_FILE) $(PLUGINS) $(DYNAMIC_LIST_FILE)
+CMD_TARGETS = $(LIB_TARGET) $(PLUGINS) $(DYNAMIC_LIST_FILE)
TARGETS = $(CMD_TARGETS)
@@ -171,8 +172,10 @@ all_cmd: $(CMD_TARGETS)
$(TE_IN): force
$(Q)$(MAKE) $(build)=libtraceevent
-$(OUTPUT)libtraceevent.so: $(TE_IN)
- $(QUIET_LINK)$(CC) --shared $^ -o $@
+$(OUTPUT)libtraceevent.so.$(EVENT_PARSE_VERSION): $(TE_IN)
+ $(QUIET_LINK)$(CC) --shared $^ -Wl,-soname,libtraceevent.so.$(EP_VERSION) -o $@
+ @ln -sf $(@F) $(OUTPUT)libtraceevent.so
+ @ln -sf $(@F) $(OUTPUT)libtraceevent.so.$(EP_VERSION)
$(OUTPUT)libtraceevent.a: $(TE_IN)
$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
@@ -236,11 +239,15 @@ TAGS: force
find . -name '*.[ch]' | xargs etags \
--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+define do_install_mkdir
+ if [ ! -d '$(DESTDIR_SQ)$1' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \
+ fi
+endef
+
define do_install
- if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
- $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
- fi; \
- $(INSTALL) $1 '$(DESTDIR_SQ)$2'
+ $(call do_install_mkdir,$2); \
+ $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2'
endef
define do_install_plugins
@@ -257,13 +264,20 @@ define do_generate_dynamic_list_file
endef
install_lib: all_cmd install_plugins
- $(call QUIET_INSTALL, $(LIB_FILE)) \
- $(call do_install,$(LIB_FILE),$(libdir_SQ))
+ $(call QUIET_INSTALL, $(LIB_TARGET)) \
+ $(call do_install_mkdir,$(libdir_SQ)); \
+ cp -fpR $(LIB_INSTALL) $(DESTDIR)$(libdir_SQ)
install_plugins: $(PLUGINS)
$(call QUIET_INSTALL, trace_plugins) \
$(call do_install_plugins, $(PLUGINS))
+install_headers:
+ $(call QUIET_INSTALL, headers) \
+ $(call do_install,event-parse.h,$(prefix)/include/traceevent,644); \
+ $(call do_install,event-utils.h,$(prefix)/include/traceevent,644); \
+ $(call do_install,kbuffer.h,$(prefix)/include/traceevent,644)
+
install: install_lib
clean:
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 664c90c8e22b..14a4f623c1a5 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <limits.h>
#include <linux/string.h>
+#include <linux/time64.h>
#include <netinet/in.h>
#include "event-parse.h"
@@ -5191,11 +5192,11 @@ struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type
}
/**
- * pevent_data_pid - parse the PID from raw data
+ * pevent_data_pid - parse the PID from record
* @pevent: a handle to the pevent
* @rec: the record to parse
*
- * This returns the PID from a raw data.
+ * This returns the PID from a record.
*/
int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
{
@@ -5203,6 +5204,32 @@ int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
}
/**
+ * pevent_data_prempt_count - parse the preempt count from the record
+ * @pevent: a handle to the pevent
+ * @rec: the record to parse
+ *
+ * This returns the preempt count from a record.
+ */
+int pevent_data_prempt_count(struct pevent *pevent, struct pevent_record *rec)
+{
+ return parse_common_pc(pevent, rec->data);
+}
+
+/**
+ * pevent_data_flags - parse the latency flags from the record
+ * @pevent: a handle to the pevent
+ * @rec: the record to parse
+ *
+ * This returns the latency flags from a record.
+ *
+ * Use trace_flag_type enum for the flags (see event-parse.h).
+ */
+int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec)
+{
+ return parse_common_flags(pevent, rec->data);
+}
+
+/**
* pevent_data_comm_from_pid - return the command line from PID
* @pevent: a handle to the pevent
* @pid: the PID of the task to search for
@@ -5424,8 +5451,8 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
use_usec_format = is_timestamp_in_us(pevent->trace_clock,
use_trace_clock);
if (use_usec_format) {
- secs = record->ts / NSECS_PER_SEC;
- nsecs = record->ts - secs * NSECS_PER_SEC;
+ secs = record->ts / NSEC_PER_SEC;
+ nsecs = record->ts - secs * NSEC_PER_SEC;
}
if (pevent->latency_format) {
@@ -5437,10 +5464,10 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
usecs = nsecs;
p = 9;
} else {
- usecs = (nsecs + 500) / NSECS_PER_USEC;
+ usecs = (nsecs + 500) / NSEC_PER_USEC;
/* To avoid usecs larger than 1 sec */
- if (usecs >= 1000000) {
- usecs -= 1000000;
+ if (usecs >= USEC_PER_SEC) {
+ usecs -= USEC_PER_SEC;
secs++;
}
p = 6;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 9ffde377e89d..7aae746ec2fe 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -172,9 +172,6 @@ struct pevent_plugin_option {
#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
-#define NSECS_PER_SEC 1000000000ULL
-#define NSECS_PER_USEC 1000ULL
-
enum format_flags {
FIELD_IS_ARRAY = 1,
FIELD_IS_POINTER = 2,
@@ -712,6 +709,8 @@ void pevent_data_lat_fmt(struct pevent *pevent,
int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
+int pevent_data_prempt_count(struct pevent *pevent, struct pevent_record *rec);
+int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec);
const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
struct cmdline;
struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
diff --git a/tools/perf/Build b/tools/perf/Build
index a43fae7f439a..b12d5d1666e3 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -21,6 +21,7 @@ perf-y += builtin-inject.o
perf-y += builtin-mem.o
perf-y += builtin-data.o
perf-y += builtin-version.o
+perf-y += builtin-c2c.o
perf-$(CONFIG_AUDIT) += builtin-trace.o
perf-$(CONFIG_LIBELF) += builtin-probe.o
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c6c8318e38a2..b0b3007d3c9c 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -550,6 +550,18 @@ Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users
have memory limits imposed upon them. That affects what buffer sizes they can
have as outlined above.
+The v4.2 kernel introduced support for a context switch metadata event,
+PERF_RECORD_SWITCH, which allows unprivileged users to see when their processes
+are scheduled out and in, just not by whom, which is left for the
+PERF_RECORD_SWITCH_CPU_WIDE, that is only accessible in system wide context,
+which in turn requires CAP_SYS_ADMIN.
+
+Please see the 45ac1403f564 ("perf: Add PERF_RECORD_SWITCH to indicate context
+switches") commit, that introduces these metadata events for further info.
+
+When working with kernels < v4.2, the following considerations must be taken,
+as the sched:sched_switch tracepoints will be used to receive such information:
+
Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users are
not permitted to use tracepoints which means there is insufficient side-band
information to decode Intel PT in per-cpu mode, and potentially workload-only
@@ -564,8 +576,11 @@ sched_switch tracepoint
-----------------------
The sched_switch tracepoint is used to provide side-band data for Intel PT
-decoding. sched_switch events are automatically added. e.g. the second event
-shown below
+decoding in kernels where the PERF_RECORD_SWITCH metadata event isn't
+available.
+
+The sched_switch events are automatically added. e.g. the second event shown
+below:
$ perf record -vv -e intel_pt//u uname
------------------------------------------------------------
diff --git a/tools/perf/Documentation/jitdump-specification.txt b/tools/perf/Documentation/jitdump-specification.txt
new file mode 100644
index 000000000000..4c62b0713651
--- /dev/null
+++ b/tools/perf/Documentation/jitdump-specification.txt
@@ -0,0 +1,170 @@
+JITDUMP specification version 2
+Last Revised: 09/15/2016
+Author: Stephane Eranian <eranian@gmail.com>
+
+--------------------------------------------------------
+| Revision | Date | Description |
+--------------------------------------------------------
+| 1 | 09/07/2016 | Initial revision |
+--------------------------------------------------------
+| 2 | 09/15/2016 | Add JIT_CODE_UNWINDING_INFO |
+--------------------------------------------------------
+
+
+I/ Introduction
+
+
+This document describes the jitdump file format. The file is generated by Just-In-time compiler runtimes to save meta-data information about the generated code, such as address, size, and name of generated functions, the native code generated, the source line information. The data may then be used by performance tools, such as Linux perf to generate function and assembly level profiles.
+
+The format is not specific to any particular programming language. It can be extended as need be.
+
+The format of the file is binary. It is self-describing in terms of endianness and is portable across multiple processor architectures.
+
+
+II/ Overview of the format
+
+
+The format requires only sequential accesses, i.e., append only mode. The file starts with a fixed size file header describing the version of the specification, the endianness.
+
+The header is followed by a series of records, each starting with a fixed size header describing the type of record and its size. It is, itself, followed by the payload for the record. Records can have a variable size even for a given type.
+
+Each entry in the file is timestamped. All timestamps must use the same clock source. The CLOCK_MONOTONIC clock source is recommended.
+
+
+III/ Jitdump file header format
+
+Each jitdump file starts with a fixed size header containing the following fields in order:
+
+
+* uint32_t magic : a magic number tagging the file type. The value is 4-byte long and represents the string "JiTD" in ASCII form. It is 0x4A695444 or 0x4454694a depending on the endianness. The field can be used to detect the endianness of the file
+* uint32_t version : a 4-byte value representing the format version. It is currently set to 2
+* uint32_t total_size: size in bytes of file header
+* uint32_t elf_mach : ELF architecture encoding (ELF e_machine value as specified in /usr/include/elf.h)
+* uint32_t pad1 : padding. Reserved for future use
+* uint32_t pid : JIT runtime process identification (OS specific)
+* uint64_t timestamp : timestamp of when the file was created
+* uint64_t flags : a bitmask of flags
+
+The flags currently defined are as follows:
+ * bit 0: JITDUMP_FLAGS_ARCH_TIMESTAMP : set if the jitdump file is using an architecture-specific timestamp clock source. For instance, on x86, one could use TSC directly
+
+IV/ Record header
+
+The file header is immediately followed by records. Each record starts with a fixed size header describing the record that follows.
+
+The record header is specified in order as follows:
+* uint32_t id : a value identifying the record type (see below)
+* uint32_t total_size: the size in bytes of the record including the header.
+* uint64_t timestamp : a timestamp of when the record was created.
+
+The following record types are defined:
+ * Value 0 : JIT_CODE_LOAD : record describing a jitted function
+ * Value 1 : JIT_CODE_MOVE : record describing an already jitted function which is moved
+ * Value 2 : JIT_CODE_DEBUG_INFO: record describing the debug information for a jitted function
+ * Value 3 : JIT_CODE_CLOSE : record marking the end of the jit runtime (optional)
+ * Value 4 : JIT_CODE_UNWINDING_INFO: record describing a function unwinding information
+
+ The payload of the record must immediately follow the record header without padding.
+
+V/ JIT_CODE_LOAD record
+
+
+ The record has the following fields following the fixed-size record header in order:
+ * uint32_t pid: OS process id of the runtime generating the jitted code
+ * uint32_t tid: OS thread identification of the runtime thread generating the jitted code
+ * uint64_t vma: virtual address of jitted code start
+ * uint64_t code_addr: code start address for the jitted code. By default vma = code_addr
+ * uint64_t code_size: size in bytes of the generated jitted code
+ * uint64_t code_index: unique identifier for the jitted code (see below)
+ * char[n]: function name in ASCII including the null termination
+ * native code: raw byte encoding of the jitted code
+
+ The record header total_size field is inclusive of all components:
+ * record header
+ * fixed-sized fields
+ * function name string, including termination
+ * native code length
+ * record specific variable data (e.g., array of data entries)
+
+The code_index is used to uniquely identify each jitted function. The index can be a monotonically increasing 64-bit value. Each time a function is jitted it gets a new number. This value is used in case the code for a function is moved and avoids having to issue another JIT_CODE_LOAD record.
+
+The format supports empty functions with no native code.
+
+
+VI/ JIT_CODE_MOVE record
+
+ The record type is optional.
+
+ The record has the following fields following the fixed-size record header in order:
+ * uint32_t pid : OS process id of the runtime generating the jitted code
+ * uint32_t tid : OS thread identification of the runtime thread generating the jitted code
+ * uint64_t vma : new virtual address of jitted code start
+ * uint64_t old_code_addr: previous code address for the same function
+ * uint64_t new_code_addr: alternate new code started address for the jitted code. By default it should be equal to the vma address.
+ * uint64_t code_size : size in bytes of the jitted code
+ * uint64_t code_index : index referring to the JIT_CODE_LOAD code_index record of when the function was initially jitted
+
+
+The MOVE record can be used in case an already jitted function is simply moved by the runtime inside the code cache.
+
+The JIT_CODE_MOVE record cannot come before the JIT_CODE_LOAD record for the same function name. The function cannot have changed name, otherwise a new JIT_CODE_LOAD record must be emitted.
+
+The code size of the function cannot change.
+
+
+VII/ JIT_DEBUG_INFO record
+
+The record type is optional.
+
+The record contains source lines debug information, i.e., a way to map a code address back to a source line. This information may be used by the performance tool.
+
+The record has the following fields following the fixed-size record header in order:
+ * uint64_t code_addr: address of function for which the debug information is generated
+ * uint64_t nr_entry : number of debug entries for the function
+ * debug_entry[n]: array of nr_entry debug entries for the function
+
+The debug_entry describes the source line information. It is defined as follows in order:
+* uint64_t code_addr: address of function for which the debug information is generated
+* uint32_t line : source file line number (starting at 1)
+* uint32_t discrim : column discriminator, 0 is default
+* char name[n] : source file name in ASCII, including null termination
+
+The debug_entry entries are saved in sequence but given that they have variable sizes due to the file name string, they cannot be indexed directly.
+They need to be walked sequentially. The next debug_entry is found at sizeof(debug_entry) + strlen(name) + 1.
+
+IMPORTANT:
+ The JIT_CODE_DEBUG for a given function must always be generated BEFORE the JIT_CODE_LOAD for the function. This facilitates greatly the parser for the jitdump file.
+
+
+VIII/ JIT_CODE_CLOSE record
+
+
+The record type is optional.
+
+The record is used as a marker for the end of the jitted runtime. It can be replaced by the end of the file.
+
+The JIT_CODE_CLOSE record does not have any specific fields, the record header contains all the information needed.
+
+
+IX/ JIT_CODE_UNWINDING_INFO
+
+
+The record type is optional.
+
+The record is used to describe the unwinding information for a jitted function.
+
+The record has the following fields following the fixed-size record header in order:
+
+uint64_t unwind_data_size : the size in bytes of the unwinding data table at the end of the record
+uint64_t eh_frame_hdr_size : the size in bytes of the DWARF EH Frame Header at the start of the unwinding data table at the end of the record
+uint64_t mapped_size : the size of the unwinding data mapped in memory
+const char unwinding_data[n]: an array of unwinding data, consisting of the EH Frame Header, followed by the actual EH Frame
+
+
+The EH Frame header follows the Linux Standard Base (LSB) specification as described in the document at https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
+
+
+The EH Frame follows the LSB specicfication as described in the document at https://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
+
+
+NOTE: The mapped_size is generally either the same as unwind_data_size (if the unwinding data was mapped in memory by the running process) or zero (if the unwinding data is not mapped by the process). If the unwinding data was not mapped, then only the EH Frame Header will be read, which can be used to specify FP based unwinding for a function which does not have unwinding information.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
new file mode 100644
index 000000000000..3f06730c7f47
--- /dev/null
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -0,0 +1,290 @@
+perf-c2c(1)
+===========
+
+NAME
+----
+perf-c2c - Shared Data C2C/HITM Analyzer.
+
+SYNOPSIS
+--------
+[verse]
+'perf c2c record' [<options>] <command>
+'perf c2c record' [<options>] -- [<record command options>] <command>
+'perf c2c report' [<options>]
+
+DESCRIPTION
+-----------
+C2C stands for Cache To Cache.
+
+The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
+you to track down the cacheline contentions.
+
+The tool is based on x86's load latency and precise store facility events
+provided by Intel CPUs. These events provide:
+ - memory address of the access
+ - type of the access (load and store details)
+ - latency (in cycles) of the load access
+
+The c2c tool provide means to record this data and report back access details
+for cachelines with highest contention - highest number of HITM accesses.
+
+The basic workflow with this tool follows the standard record/report phase.
+User uses the record command to record events data and report command to
+display it.
+
+
+RECORD OPTIONS
+--------------
+-e::
+--event=::
+ Select the PMU event. Use 'perf mem record -e list'
+ to list available events.
+
+-v::
+--verbose::
+ Be more verbose (show counter open errors, etc).
+
+-l::
+--ldlat::
+ Configure mem-loads latency.
+
+-k::
+--all-kernel::
+ Configure all used events to run in kernel space.
+
+-u::
+--all-user::
+ Configure all used events to run in user space.
+
+REPORT OPTIONS
+--------------
+-k::
+--vmlinux=<file>::
+ vmlinux pathname
+
+-v::
+--verbose::
+ Be more verbose (show counter open errors, etc).
+
+-i::
+--input::
+ Specify the input file to process.
+
+-N::
+--node-info::
+ Show extra node info in report (see NODE INFO section)
+
+-c::
+--coalesce::
+ Specify sorintg fields for single cacheline display.
+ Following fields are available: tid,pid,iaddr,dso
+ (see COALESCE)
+
+-g::
+--call-graph::
+ Setup callchains parameters.
+ Please refer to perf-report man page for details.
+
+--stdio::
+ Force the stdio output (see STDIO OUTPUT)
+
+--stats::
+ Display only statistic tables and force stdio mode.
+
+--full-symbols::
+ Display full length of symbols.
+
+--no-source::
+ Do not display Source:Line column.
+
+--show-all::
+ Show all captured HITM lines, with no regard to HITM % 0.0005 limit.
+
+-f::
+--force::
+ Don't do ownership validation.
+
+-d::
+--display::
+ Siwtch to HITM type (rmt, lcl) to display and sort on. Total HITMs as default.
+
+C2C RECORD
+----------
+The perf c2c record command setup options related to HITM cacheline analysis
+and calls standard perf record command.
+
+Following perf record options are configured by default:
+(check perf record man page for details)
+
+ -W,-d,--sample-cpu
+
+Unless specified otherwise with '-e' option, following events are monitored by
+default:
+
+ cpu/mem-loads,ldlat=30/P
+ cpu/mem-stores/P
+
+User can pass any 'perf record' option behind '--' mark, like (to enable
+callchains and system wide monitoring):
+
+ $ perf c2c record -- -g -a
+
+Please check RECORD OPTIONS section for specific c2c record options.
+
+C2C REPORT
+----------
+The perf c2c report command displays shared data analysis. It comes in two
+display modes: stdio and tui (default).
+
+The report command workflow is following:
+ - sort all the data based on the cacheline address
+ - store access details for each cacheline
+ - sort all cachelines based on user settings
+ - display data
+
+In general perf report output consist of 2 basic views:
+ 1) most expensive cachelines list
+ 2) offsets details for each cacheline
+
+For each cacheline in the 1) list we display following data:
+(Both stdio and TUI modes follow the same fields output)
+
+ Index
+ - zero based index to identify the cacheline
+
+ Cacheline
+ - cacheline address (hex number)
+
+ Total records
+ - sum of all cachelines accesses
+
+ Rmt/Lcl Hitm
+ - cacheline percentage of all Remote/Local HITM accesses
+
+ LLC Load Hitm - Total, Lcl, Rmt
+ - count of Total/Local/Remote load HITMs
+
+ Store Reference - Total, L1Hit, L1Miss
+ Total - all store accesses
+ L1Hit - store accesses that hit L1
+ L1Hit - store accesses that missed L1
+
+ Load Dram
+ - count of local and remote DRAM accesses
+
+ LLC Ld Miss
+ - count of all accesses that missed LLC
+
+ Total Loads
+ - sum of all load accesses
+
+ Core Load Hit - FB, L1, L2
+ - count of load hits in FB (Fill Buffer), L1 and L2 cache
+
+ LLC Load Hit - Llc, Rmt
+ - count of LLC and Remote load hits
+
+For each offset in the 2) list we display following data:
+
+ HITM - Rmt, Lcl
+ - % of Remote/Local HITM accesses for given offset within cacheline
+
+ Store Refs - L1 Hit, L1 Miss
+ - % of store accesses that hit/missed L1 for given offset within cacheline
+
+ Data address - Offset
+ - offset address
+
+ Pid
+ - pid of the process responsible for the accesses
+
+ Tid
+ - tid of the process responsible for the accesses
+
+ Code address
+ - code address responsible for the accesses
+
+ cycles - rmt hitm, lcl hitm, load
+ - sum of cycles for given accesses - Remote/Local HITM and generic load
+
+ cpu cnt
+ - number of cpus that participated on the access
+
+ Symbol
+ - code symbol related to the 'Code address' value
+
+ Shared Object
+ - shared object name related to the 'Code address' value
+
+ Source:Line
+ - source information related to the 'Code address' value
+
+ Node
+ - nodes participating on the access (see NODE INFO section)
+
+NODE INFO
+---------
+The 'Node' field displays nodes that accesses given cacheline
+offset. Its output comes in 3 flavors:
+ - node IDs separated by ','
+ - node IDs with stats for each ID, in following format:
+ Node{cpus %hitms %stores}
+ - node IDs with list of affected CPUs in following format:
+ Node{cpu list}
+
+User can switch between above flavors with -N option or
+use 'n' key to interactively switch in TUI mode.
+
+COALESCE
+--------
+User can specify how to sort offsets for cacheline.
+
+Following fields are available and governs the final
+output fields set for caheline offsets output:
+
+ tid - coalesced by process TIDs
+ pid - coalesced by process PIDs
+ iaddr - coalesced by code address, following fields are displayed:
+ Code address, Code symbol, Shared Object, Source line
+ dso - coalesced by shared object
+
+By default the coalescing is setup with 'pid,tid,iaddr'.
+
+STDIO OUTPUT
+------------
+The stdio output displays data on standard output.
+
+Following tables are displayed:
+ Trace Event Information
+ - overall statistics of memory accesses
+
+ Global Shared Cache Line Event Information
+ - overall statistics on shared cachelines
+
+ Shared Data Cache Line Table
+ - list of most expensive cachelines
+
+ Shared Cache Line Distribution Pareto
+ - list of all accessed offsets for each cacheline
+
+TUI OUTPUT
+----------
+The TUI output provides interactive interface to navigate
+through cachelines list and to display offset details.
+
+For details please refer to the help window by pressing '?' key.
+
+CREDITS
+-------
+Although Don Zickus, Dick Fowles and Joe Mario worked together
+to get this implemented, we got lots of early help from Arnaldo
+Carvalho de Melo, Stephane Eranian, Jiri Olsa and Andi Kleen.
+
+C2C BLOG
+--------
+Check Joe's blog on c2c tool for detailed use case explanation:
+ https://joemario.github.io/blog/2016/09/01/c2c-blog/
+
+SEE ALSO
+--------
+linkperf:perf-record[1], linkperf:perf-mem[1]
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index cb081ac59fd1..9365b75fd04f 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,6 +8,8 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
+'perf config' [<file-option>] [section.name[=value] ...]
+or
'perf config' [<file-option>] -l | --list
DESCRIPTION
@@ -118,6 +120,39 @@ Given a $HOME/.perfconfig like this:
children = true
group = true
+You can hide source code of annotate feature setting the config to false with
+
+ % perf config annotate.hide_src_code=true
+
+If you want to add or modify several config items, you can do like
+
+ % perf config ui.show-headers=false kmem.default=slab
+
+To modify the sort order of report functionality in user config file(i.e. `~/.perfconfig`), do
+
+ % perf config --user report sort-order=srcline
+
+To change colors of selected line to other foreground and background colors
+in system config file (i.e. `$(sysconf)/perfconfig`), do
+
+ % perf config --system colors.selected=yellow,green
+
+To query the record mode of call graph, do
+
+ % perf config call-graph.record-mode
+
+If you want to know multiple config key/value pairs, you can do like
+
+ % perf config report.queue-size call-graph.order report.children
+
+To query the config value of sort order of call graph in user config file (i.e. `~/.perfconfig`), do
+
+ % perf config --user call-graph.sort-order
+
+To query the config value of buildid directory in system config file (i.e. `$(sysconf)/perfconfig`), do
+
+ % perf config --system buildid.dir
+
Variables
~~~~~~~~~
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index ff0f433b3fce..479fc3261a50 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -61,6 +61,13 @@ OPTIONS
default, but this option shows live (currently allocated) pages
instead. (This option works with --page option only)
+--time::
+ Only analyze samples within given time window: <start>,<stop>. Times
+ have the format seconds.microseconds. If start is not given (i.e., time
+ string is ',x.y') then analysis starts at the beginning of the file. If
+ stop time is not given (i.e, time string is 'x.y,') then analysis goes
+ to end of file.
+
SEE ALSO
--------
linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 92335193dc33..27fc3617c6a4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -45,9 +45,9 @@ OPTIONS
param1 and param2 are defined as formats for the PMU in:
/sys/bus/event_source/devices/<pmu>/format/*
- There are also some params which are not defined in .../<pmu>/format/*.
+ There are also some parameters which are not defined in .../<pmu>/format/*.
These params can be used to overload default config values per event.
- Here is a list of the params.
+ Here are some common parameters:
- 'period': Set event sampling period
- 'freq': Set event sampling frequency
- 'time': Disable/enable time stamping. Acceptable values are 1 for
@@ -57,8 +57,11 @@ OPTIONS
FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and
"no" for disable callgraph.
- 'stack-size': user stack size for dwarf mode
+
+ See the linkperf:perf-list[1] man page for more parameters.
+
Note: If user explicitly sets options which conflict with the params,
- the value set by the params will be overridden.
+ the value set by the parameters will be overridden.
Also not defined in .../<pmu>/format/* are PMU driver specific
configuration parameters. Any configuration parameter preceded by
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2d1746295abf..f2914f03ae7b 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -239,7 +239,8 @@ OPTIONS
Accumulate callchain of children to parent entry so that then can
show up in the output. The output will have a new "Children" column
and will be sorted on the data. It requires callchains are recorded.
- See the `overhead calculation' section for more details.
+ See the `overhead calculation' section for more details. Enabled by
+ default, disable with --no-children.
--max-stack::
Set the stack depth limit when parsing the callchain, anything
@@ -382,6 +383,13 @@ OPTIONS
--header-only::
Show only perf.data header (forces --stdio).
+--time::
+ Only analyze samples within given time window: <start>,<stop>. Times
+ have the format seconds.microseconds. If start is not given (i.e., time
+ string is ',x.y') then analysis starts at the beginning of the file. If
+ stop time is not given (i.e, time string is 'x.y,') then analysis goes
+ to end of file.
+
--itrace::
Options for decoding instruction tracing data. The options are:
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 1cc08cc47ac5..7775b1eb2bee 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -8,11 +8,11 @@ perf-sched - Tool to trace/measure scheduler properties (latencies)
SYNOPSIS
--------
[verse]
-'perf sched' {record|latency|map|replay|script}
+'perf sched' {record|latency|map|replay|script|timehist}
DESCRIPTION
-----------
-There are five variants of perf sched:
+There are several variants of 'perf sched':
'perf sched record <command>' to record the scheduling events
of an arbitrary workload.
@@ -36,6 +36,30 @@ There are five variants of perf sched:
are running on a CPU. A '*' denotes the CPU that had the event, and
a dot signals an idle CPU.
+ 'perf sched timehist' provides an analysis of scheduling events.
+
+ Example usage:
+ perf sched record -- sleep 1
+ perf sched timehist
+
+ By default it shows the individual schedule events, including the wait
+ time (time between sched-out and next sched-in events for the task), the
+ task scheduling delay (time between wakeup and actually running) and run
+ time for the task:
+
+ time cpu task name wait time sch delay run time
+ [tid/pid] (msec) (msec) (msec)
+ -------------- ------ -------------------- --------- --------- ---------
+ 79371.874569 [0011] gcc[31949] 0.014 0.000 1.148
+ 79371.874591 [0010] gcc[31951] 0.000 0.000 0.024
+ 79371.874603 [0010] migration/10[59] 3.350 0.004 0.011
+ 79371.874604 [0011] <idle> 1.148 0.000 0.035
+ 79371.874723 [0005] <idle> 0.016 0.000 1.383
+ 79371.874746 [0005] gcc[31949] 0.153 0.078 0.022
+ ...
+
+ Times are in msec.usec.
+
OPTIONS
-------
-i::
@@ -66,6 +90,56 @@ OPTIONS for 'perf sched map'
--color-pids::
Highlight the given pids.
+OPTIONS for 'perf sched timehist'
+---------------------------------
+-k::
+--vmlinux=<file>::
+ vmlinux pathname
+
+--kallsyms=<file>::
+ kallsyms pathname
+
+-g::
+--no-call-graph::
+ Do not display call chains if present.
+
+--max-stack::
+ Maximum number of functions to display in backtrace, default 5.
+
+-s::
+--summary::
+ Show only a summary of scheduling by thread with min, max, and average
+ run times (in sec) and relative stddev.
+
+-S::
+--with-summary::
+ Show all scheduling events followed by a summary by thread with min,
+ max, and average run times (in sec) and relative stddev.
+
+--symfs=<directory>::
+ Look for files with symbols relative to this directory.
+
+-V::
+--cpu-visual::
+ Show visual aid for sched switches by CPU: 'i' marks idle time,
+ 's' are scheduler events.
+
+-w::
+--wakeups::
+ Show wakeup events.
+
+-M::
+--migrations::
+ Show migration events.
+
+--time::
+ Only analyze samples within given time window: <start>,<stop>. Times
+ have the format seconds.microseconds. If start is not given (i.e., time
+ string is ',x.y') then analysis starts at the beginning of the file. If
+ stop time is not given (i.e, time string is 'x.y,') then analysis goes
+ to end of file.
+
+
SEE ALSO
--------
linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 053bbbd84ece..5dc5c6a09ac4 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
- callindent. Field list can be prepended with the type, trace, sw or hw,
+ callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
@@ -181,6 +181,10 @@ OPTIONS
Instruction Trace decoding. For calls and returns, it will display the
name of the symbol indented with spaces to reflect the stack depth.
+ When doing instruction trace decoding insn and insnlen give the
+ instruction bytes and the instruction length of the current
+ instruction.
+
Finally, a user may not set fields to none for all event types.
i.e., -F "" is not allowed.
@@ -208,6 +212,9 @@ OPTIONS
--hide-call-graph::
When printing symbols do not display call chain.
+--stop-bt::
+ Stop display of callgraph at these symbols
+
-C::
--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
be provided as a comma-separated list with no space: 0,1. Ranges of
@@ -285,6 +292,13 @@ include::itrace.txt[]
--force::
Don't do ownership validation.
+--time::
+ Only analyze samples within given time window: <start>,<stop>. Times
+ have the format seconds.microseconds. If start is not given (i.e., time
+ string is ',x.y') then analysis starts at the beginning of the file. If
+ stop time is not given (i.e, time string is 'x.y,') then analysis goes
+ to end of file.
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 91d638df3a6b..e71d63843f45 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -170,6 +170,7 @@ Default is to monitor all CPUS.
show up in the output. The output will have a new "Children" column
and will be sorted on the data. It requires -g/--call-graph option
enabled. See the `overhead calculation' section for more details.
+ Enabled by default, disable with --no-children.
--max-stack::
Set the stack depth limit when parsing the callchain, anything
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 1ab0782369b1..781b019751a4 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -39,6 +39,11 @@ OPTIONS
Prefixing with ! shows all syscalls but the ones specified. You may
need to escape it.
+-D msecs::
+--delay msecs::
+After starting the program, wait msecs before measuring. This is useful to
+filter out the startup phase of the program, which is often very different.
+
-o::
--output=::
Output file name.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 0bda2cca2b3a..a511e5f31e36 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -51,6 +51,7 @@ tools/include/asm-generic/bitops/arch_hweight.h
tools/include/asm-generic/bitops/atomic.h
tools/include/asm-generic/bitops/const_hweight.h
tools/include/asm-generic/bitops/__ffs.h
+tools/include/asm-generic/bitops/__ffz.h
tools/include/asm-generic/bitops/__fls.h
tools/include/asm-generic/bitops/find.h
tools/include/asm-generic/bitops/fls64.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 72edf83d76b7..76c84f0eec52 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -136,6 +136,7 @@ endif
# Treat warnings as errors unless directed not to
ifneq ($(WERROR),0)
CFLAGS += -Werror
+ CXXFLAGS += -Werror
endif
ifndef DEBUG
@@ -182,6 +183,13 @@ CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -std=gnu99
+CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
+CXXFLAGS += -Wall
+CXXFLAGS += -fno-omit-frame-pointer
+CXXFLAGS += -ggdb3
+CXXFLAGS += -funwind-tables
+CXXFLAGS += -Wno-strict-aliasing
+
# Enforce a non-executable stack, as we may regress (again) in the future by
# adding assembler files missing the .GNU-stack linker note.
LDFLAGS += -Wl,-z,noexecstack
@@ -204,24 +212,27 @@ ifeq ($(DEBUG),0)
endif
endif
-CFLAGS += -I$(src-perf)/util/include
-CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
-CFLAGS += -I$(srctree)/tools/include/uapi
-CFLAGS += -I$(srctree)/tools/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
+INC_FLAGS += -I$(src-perf)/util/include
+INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
+INC_FLAGS += -I$(srctree)/tools/include/uapi
+INC_FLAGS += -I$(srctree)/tools/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
# $(obj-perf) for generated common-cmds.h
# $(obj-perf)/util for generated bison/flex headers
ifneq ($(OUTPUT),)
-CFLAGS += -I$(obj-perf)/util
-CFLAGS += -I$(obj-perf)
+INC_FLAGS += -I$(obj-perf)/util
+INC_FLAGS += -I$(obj-perf)
endif
-CFLAGS += -I$(src-perf)/util
-CFLAGS += -I$(src-perf)
-CFLAGS += -I$(srctree)/tools/lib/
+INC_FLAGS += -I$(src-perf)/util
+INC_FLAGS += -I$(src-perf)
+INC_FLAGS += -I$(srctree)/tools/lib/
+
+CFLAGS += $(INC_FLAGS)
+CXXFLAGS += $(INC_FLAGS)
CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
@@ -366,7 +377,7 @@ ifndef NO_SDT
endif
ifdef PERF_HAVE_JITDUMP
- ifndef NO_DWARF
+ ifndef NO_LIBELF
$(call detected,CONFIG_JITDUMP)
CFLAGS += -DHAVE_JITDUMP
endif
@@ -758,6 +769,62 @@ ifndef NO_AUXTRACE
endif
endif
+ifndef NO_JVMTI
+ ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
+ JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
+ else
+ ifneq (,$(wildcard /usr/sbin/alternatives))
+ JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
+ endif
+ endif
+ ifndef JDIR
+ $(warning No alternatives command found, you need to set JDIR= to point to the root of your Java directory)
+ NO_JVMTI := 1
+ endif
+endif
+
+ifndef NO_JVMTI
+ FEATURE_CHECK_CFLAGS-jvmti := -I$(JDIR)/include -I$(JDIR)/include/linux
+ $(call feature_check,jvmti)
+ ifeq ($(feature-jvmti), 1)
+ $(call detected_var,JDIR)
+ else
+ $(warning No openjdk development package found, please install JDK package)
+ NO_JVMTI := 1
+ endif
+endif
+
+USE_CXX = 0
+USE_CLANGLLVM = 0
+ifdef LIBCLANGLLVM
+ $(call feature_check,cxx)
+ ifneq ($(feature-cxx), 1)
+ msg := $(warning No g++ found, disable clang and llvm support. Please install g++)
+ else
+ $(call feature_check,llvm)
+ $(call feature_check,llvm-version)
+ ifneq ($(feature-llvm), 1)
+ msg := $(warning No suitable libLLVM found, disabling builtin clang and LLVM support. Please install llvm-dev(el) (>= 3.9.0))
+ else
+ $(call feature_check,clang)
+ ifneq ($(feature-clang), 1)
+ msg := $(warning No suitable libclang found, disabling builtin clang and LLVM support. Please install libclang-dev(el) (>= 3.9.0))
+ else
+ CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
+ CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir)
+ $(call detected,CONFIG_CXX)
+ $(call detected,CONFIG_CLANGLLVM)
+ USE_CXX = 1
+ USE_LLVM = 1
+ USE_CLANG = 1
+ ifneq ($(feature-llvm-version),1)
+ msg := $(warning This version of LLVM is not tested. May cause build errors)
+ endif
+ endif
+ endif
+ endif
+endif
+
# Among the variables below, these:
# perfexecdir
# template_dir
@@ -850,6 +917,7 @@ ifeq ($(VF),1)
$(call print_var,sysconfdir)
$(call print_var,LIBUNWIND_DIR)
$(call print_var,LIBDW_DIR)
+ $(call print_var,JDIR)
ifeq ($(dwarf-post-unwind),1)
$(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 982d6439bb07..8f1c258b151a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -86,6 +86,12 @@ include ../scripts/utilities.mak
#
# Define FEATURES_DUMP to provide features detection dump file
# and bypass the feature detection
+#
+# Define NO_JVMTI if you do not want jvmti agent built
+#
+# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
+# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
+# llvm-config is not in $PATH.
# As per kernel Makefile, avoid funny character set dependencies
unexport LC_ALL
@@ -122,10 +128,6 @@ endif
# (this improves performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -r
-$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
- $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
- $(Q)touch $(OUTPUT)PERF-VERSION-FILE
-
# Makefiles suck: This macro sets a default value of $(2) for the
# variable named by $(1), unless the variable has been set by
# environment or command line. This is necessary for CC and AR
@@ -141,6 +143,7 @@ endef
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
$(call allow-override,AR,$(CROSS_COMPILE)ar)
$(call allow-override,LD,$(CROSS_COMPILE)ld)
+$(call allow-override,CXX,$(CROSS_COMPILE)g++)
LD += $(EXTRA_LDFLAGS)
@@ -149,6 +152,7 @@ HOSTLD ?= ld
HOSTAR ?= ar
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
RM = rm -f
LN = ln -f
@@ -160,16 +164,11 @@ BISON = bison
STRIP = strip
AWK = awk
-LIB_DIR = $(srctree)/tools/lib/api/
-TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
-BPF_DIR = $(srctree)/tools/lib/bpf/
-SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
-
# include Makefile.config by default and rule out
# non-config cases
config := 1
-NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc
+NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf
ifdef MAKECMDGOALS
ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -177,6 +176,40 @@ ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
endif
endif
+# The fixdep build - we force fixdep tool to be built as
+# the first target in the separate make session not to be
+# disturbed by any parallel make jobs. Once fixdep is done
+# we issue the requested build with FIXDEP=1 variable.
+#
+# The fixdep build is disabled for $(NON_CONFIG_TARGETS)
+# targets, because it's not necessary.
+
+ifdef FIXDEP
+ force_fixdep := 0
+else
+ force_fixdep := $(config)
+endif
+
+export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
+export HOSTCC HOSTLD HOSTAR
+
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(force_fixdep),1)
+goals := $(filter-out all sub-make, $(MAKECMDGOALS))
+
+$(goals) all: sub-make
+
+sub-make: fixdep
+ $(Q)$(MAKE) FIXDEP=1 -f Makefile.perf $(goals)
+
+else # force_fixdep
+
+LIB_DIR = $(srctree)/tools/lib/api/
+TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
+BPF_DIR = $(srctree)/tools/lib/bpf/
+SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
+
# Set FEATURE_TESTS to 'all' so all possible feature checkers are executed.
# Without this setting the output feature dump file misses some features, for
# example, liberty. Select all checkers so we won't get an incomplete feature
@@ -260,17 +293,6 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
-$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
- $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
- CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
- $(PYTHON_WORD) util/setup.py \
- --quiet build_ext; \
- mkdir -p $(OUTPUT)python && \
- cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
-#
-# No Perl scripts right now:
-#
-
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
PROGRAMS += $(OUTPUT)perf
@@ -283,6 +305,12 @@ ifndef NO_PERF_READ_VDSOX32
PROGRAMS += $(OUTPUT)perf-read-vdsox32
endif
+LIBJVMTI = libperf-jvmti.so
+
+ifndef NO_JVMTI
+PROGRAMS += $(OUTPUT)$(LIBJVMTI)
+endif
+
# what 'all' will build and 'install' will install, in perfexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
@@ -317,11 +345,6 @@ endif
ifndef NO_GTK2
ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
GTK_IN := $(OUTPUT)gtk-in.o
-
-install-gtk: $(OUTPUT)libperf-gtk.so
- $(call QUIET_INSTALL, 'GTK UI') \
- $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
- $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
endif
ifdef ASCIIDOC8
@@ -330,6 +353,21 @@ endif
LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
+ifeq ($(USE_CLANG), 1)
+ CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
+ LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a))
+ LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
+endif
+
+ifeq ($(USE_LLVM), 1)
+ LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
+ LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
+endif
+
+ifeq ($(USE_CXX), 1)
+ LIBS += -lstdc++
+endif
+
export INSTALL SHELL_PATH
### Build rules
@@ -338,6 +376,14 @@ SHELL = $(SHELL_PATH)
all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
+$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
+ $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
+ CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
+ $(PYTHON_WORD) util/setup.py \
+ --quiet build_ext; \
+ mkdir -p $(OUTPUT)python && \
+ cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
+
please_set_SHELL_PATH_to_a_more_modern_shell:
$(Q)$$(:)
@@ -348,10 +394,6 @@ strip: $(PROGRAMS) $(OUTPUT)perf
PERF_IN := $(OUTPUT)perf-in.o
-export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
-export HOSTCC HOSTLD HOSTAR
-include $(srctree)/tools/build/Makefile.include
-
JEVENTS := $(OUTPUT)pmu-events/jevents
JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o
@@ -381,10 +423,10 @@ $(PERF_IN): prepare FORCE
(diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \
|| echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true
@(test -f ../../arch/x86/lib/memcpy_64.S && ( \
- (diff -B ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \
+ (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \
|| echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true
@(test -f ../../arch/x86/lib/memset_64.S && ( \
- (diff -B ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \
+ (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \
|| echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true
@(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \
(diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \
@@ -470,7 +512,7 @@ $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_L
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
$(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@
-$(GTK_IN): fixdep FORCE
+$(GTK_IN): FORCE
$(Q)$(MAKE) $(build)=gtk
$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
@@ -484,6 +526,10 @@ $(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
$(SCRIPTS) : % : %.sh
$(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
+$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
+ $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
+ $(Q)touch $(OUTPUT)PERF-VERSION-FILE
+
# These can record PERF_VERSION
perf.spec $(SCRIPTS) \
: $(OUTPUT)PERF-VERSION-FILE
@@ -515,7 +561,7 @@ endif
__build-dir = $(subst $(OUTPUT),,$(dir $@))
build-dir = $(if $(__build-dir),$(__build-dir),.)
-prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders
+prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders
$(OUTPUT)%.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -551,11 +597,21 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
$(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
endif
+ifndef NO_JVMTI
+LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
+
+$(LIBJVMTI_IN): FORCE
+ $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
+
+$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
+ $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt
+endif
+
$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
LIBPERF_IN := $(OUTPUT)libperf-in.o
-$(LIBPERF_IN): prepare fixdep FORCE
+$(LIBPERF_IN): prepare FORCE
$(Q)$(MAKE) $(build)=libperf
$(LIB_FILE): $(LIBPERF_IN)
@@ -563,10 +619,10 @@ $(LIB_FILE): $(LIBPERF_IN)
LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
-$(LIBTRACEEVENT): fixdep FORCE
+$(LIBTRACEEVENT): FORCE
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
-libtraceevent_plugins: fixdep FORCE
+libtraceevent_plugins: FORCE
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins
$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
@@ -579,21 +635,21 @@ $(LIBTRACEEVENT)-clean:
install-traceevent-plugins: libtraceevent_plugins
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
-$(LIBAPI): fixdep FORCE
+$(LIBAPI): FORCE
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
$(LIBAPI)-clean:
$(call QUIET_CLEAN, libapi)
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
-$(LIBBPF): fixdep FORCE
+$(LIBBPF): FORCE
$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT)
$(LIBBPF)-clean:
$(call QUIET_CLEAN, libbpf)
$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
-$(LIBSUBCMD): fixdep FORCE
+$(LIBSUBCMD): FORCE
$(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a
$(LIBSUBCMD)-clean:
@@ -673,7 +729,14 @@ check: $(OUTPUT)common-cmds.h
### Installation rules
+ifndef NO_GTK2
+install-gtk: $(OUTPUT)libperf-gtk.so
+ $(call QUIET_INSTALL, 'GTK UI') \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
+ $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
+else
install-gtk:
+endif
install-tools: all install-gtk
$(call QUIET_INSTALL, binaries) \
@@ -688,6 +751,10 @@ ifndef NO_PERF_READ_VDSOX32
$(call QUIET_INSTALL, perf-read-vdsox32) \
$(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
endif
+ifndef NO_JVMTI
+ $(call QUIET_INSTALL, $(LIBJVMTI)) \
+ $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
+endif
$(call QUIET_INSTALL, libexec) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
$(call QUIET_INSTALL, perf-archive) \
@@ -754,7 +821,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
$(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(Q)$(RM) $(OUTPUT).config-detected
- $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents
+ $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so
$(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
$(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
@@ -790,3 +857,4 @@ FORCE:
.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
.PHONY: libtraceevent_plugins archheaders
+endif # force_fixdep
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
new file mode 100644
index 000000000000..1ce0872b1726
--- /dev/null
+++ b/tools/perf/arch/arm/annotate/instructions.c
@@ -0,0 +1,59 @@
+#include <sys/types.h>
+#include <regex.h>
+
+struct arm_annotate {
+ regex_t call_insn,
+ jump_insn;
+};
+
+static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
+{
+ struct arm_annotate *arm = arch->priv;
+ struct ins_ops *ops;
+ regmatch_t match[2];
+
+ if (!regexec(&arm->call_insn, name, 2, match, 0))
+ ops = &call_ops;
+ else if (!regexec(&arm->jump_insn, name, 2, match, 0))
+ ops = &jump_ops;
+ else
+ return NULL;
+
+ arch__associate_ins_ops(arch, name, ops);
+ return ops;
+}
+
+static int arm__annotate_init(struct arch *arch)
+{
+ struct arm_annotate *arm;
+ int err;
+
+ if (arch->initialized)
+ return 0;
+
+ arm = zalloc(sizeof(*arm));
+ if (!arm)
+ return -1;
+
+#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)"
+ err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED);
+ if (err)
+ goto out_free_arm;
+ err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED);
+ if (err)
+ goto out_free_call;
+#undef ARM_CONDS
+
+ arch->initialized = true;
+ arch->priv = arm;
+ arch->associate_instruction_ops = arm__associate_instruction_ops;
+ arch->objdump.comment_char = ';';
+ arch->objdump.skip_functions_char = '+';
+ return 0;
+
+out_free_call:
+ regfree(&arm->call_insn);
+out_free_arm:
+ free(arm);
+ return -1;
+}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 47d584da5819..dfea6b635525 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -575,8 +575,6 @@ static FILE *cs_device__open_file(const char *name)
snprintf(path, PATH_MAX,
"%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
- printf("path: %s\n", path);
-
if (stat(path, &st) < 0)
return NULL;
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
new file mode 100644
index 000000000000..44eafd6f2d50
--- /dev/null
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -0,0 +1,62 @@
+#include <sys/types.h>
+#include <regex.h>
+
+struct arm64_annotate {
+ regex_t call_insn,
+ jump_insn;
+};
+
+static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
+{
+ struct arm64_annotate *arm = arch->priv;
+ struct ins_ops *ops;
+ regmatch_t match[2];
+
+ if (!regexec(&arm->jump_insn, name, 2, match, 0))
+ ops = &jump_ops;
+ else if (!regexec(&arm->call_insn, name, 2, match, 0))
+ ops = &call_ops;
+ else if (!strcmp(name, "ret"))
+ ops = &ret_ops;
+ else
+ return NULL;
+
+ arch__associate_ins_ops(arch, name, ops);
+ return ops;
+}
+
+static int arm64__annotate_init(struct arch *arch)
+{
+ struct arm64_annotate *arm;
+ int err;
+
+ if (arch->initialized)
+ return 0;
+
+ arm = zalloc(sizeof(*arm));
+ if (!arm)
+ return -1;
+
+ /* bl, blr */
+ err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
+ if (err)
+ goto out_free_arm;
+ /* b, b.cond, br, cbz/cbnz, tbz/tbnz */
+ err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl)?n?z?$",
+ REG_EXTENDED);
+ if (err)
+ goto out_free_call;
+
+ arch->initialized = true;
+ arch->priv = arm;
+ arch->associate_instruction_ops = arm64__associate_instruction_ops;
+ arch->objdump.comment_char = ';';
+ arch->objdump.skip_functions_char = '+';
+ return 0;
+
+out_free_call:
+ regfree(&arm->call_insn);
+out_free_arm:
+ free(arm);
+ return -1;
+}
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
new file mode 100644
index 000000000000..3c4004db81b9
--- /dev/null
+++ b/tools/perf/arch/powerpc/annotate/instructions.c
@@ -0,0 +1,58 @@
+static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
+{
+ int i;
+ struct ins_ops *ops;
+
+ /*
+ * - Interested only if instruction starts with 'b'.
+ * - Few start with 'b', but aren't branch instructions.
+ */
+ if (name[0] != 'b' ||
+ !strncmp(name, "bcd", 3) ||
+ !strncmp(name, "brinc", 5) ||
+ !strncmp(name, "bper", 4))
+ return NULL;
+
+ ops = &jump_ops;
+
+ i = strlen(name) - 1;
+ if (i < 0)
+ return NULL;
+
+ /* ignore optional hints at the end of the instructions */
+ if (name[i] == '+' || name[i] == '-')
+ i--;
+
+ if (name[i] == 'l' || (name[i] == 'a' && name[i-1] == 'l')) {
+ /*
+ * if the instruction ends up with 'l' or 'la', then
+ * those are considered 'calls' since they update LR.
+ * ... except for 'bnl' which is branch if not less than
+ * and the absolute form of the same.
+ */
+ if (strcmp(name, "bnl") && strcmp(name, "bnl+") &&
+ strcmp(name, "bnl-") && strcmp(name, "bnla") &&
+ strcmp(name, "bnla+") && strcmp(name, "bnla-"))
+ ops = &call_ops;
+ }
+ if (name[i] == 'r' && name[i-1] == 'l')
+ /*
+ * instructions ending with 'lr' are considered to be
+ * return instructions
+ */
+ ops = &ret_ops;
+
+ arch__associate_ins_ops(arch, name, ops);
+ return ops;
+}
+
+static int powerpc__annotate_init(struct arch *arch)
+{
+ if (!arch->initialized) {
+ arch->initialized = true;
+ arch->associate_instruction_ops = powerpc__associate_instruction_ops;
+ arch->objdump.comment_char = '#';
+ }
+
+ return 0;
+}
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
new file mode 100644
index 000000000000..c1625f256df3
--- /dev/null
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -0,0 +1,78 @@
+static struct ins x86__instructions[] = {
+ { .name = "add", .ops = &mov_ops, },
+ { .name = "addl", .ops = &mov_ops, },
+ { .name = "addq", .ops = &mov_ops, },
+ { .name = "addw", .ops = &mov_ops, },
+ { .name = "and", .ops = &mov_ops, },
+ { .name = "bts", .ops = &mov_ops, },
+ { .name = "call", .ops = &call_ops, },
+ { .name = "callq", .ops = &call_ops, },
+ { .name = "cmp", .ops = &mov_ops, },
+ { .name = "cmpb", .ops = &mov_ops, },
+ { .name = "cmpl", .ops = &mov_ops, },
+ { .name = "cmpq", .ops = &mov_ops, },
+ { .name = "cmpw", .ops = &mov_ops, },
+ { .name = "cmpxch", .ops = &mov_ops, },
+ { .name = "dec", .ops = &dec_ops, },
+ { .name = "decl", .ops = &dec_ops, },
+ { .name = "imul", .ops = &mov_ops, },
+ { .name = "inc", .ops = &dec_ops, },
+ { .name = "incl", .ops = &dec_ops, },
+ { .name = "ja", .ops = &jump_ops, },
+ { .name = "jae", .ops = &jump_ops, },
+ { .name = "jb", .ops = &jump_ops, },
+ { .name = "jbe", .ops = &jump_ops, },
+ { .name = "jc", .ops = &jump_ops, },
+ { .name = "jcxz", .ops = &jump_ops, },
+ { .name = "je", .ops = &jump_ops, },
+ { .name = "jecxz", .ops = &jump_ops, },
+ { .name = "jg", .ops = &jump_ops, },
+ { .name = "jge", .ops = &jump_ops, },
+ { .name = "jl", .ops = &jump_ops, },
+ { .name = "jle", .ops = &jump_ops, },
+ { .name = "jmp", .ops = &jump_ops, },
+ { .name = "jmpq", .ops = &jump_ops, },
+ { .name = "jna", .ops = &jump_ops, },
+ { .name = "jnae", .ops = &jump_ops, },
+ { .name = "jnb", .ops = &jump_ops, },
+ { .name = "jnbe", .ops = &jump_ops, },
+ { .name = "jnc", .ops = &jump_ops, },
+ { .name = "jne", .ops = &jump_ops, },
+ { .name = "jng", .ops = &jump_ops, },
+ { .name = "jnge", .ops = &jump_ops, },
+ { .name = "jnl", .ops = &jump_ops, },
+ { .name = "jnle", .ops = &jump_ops, },
+ { .name = "jno", .ops = &jump_ops, },
+ { .name = "jnp", .ops = &jump_ops, },
+ { .name = "jns", .ops = &jump_ops, },
+ { .name = "jnz", .ops = &jump_ops, },
+ { .name = "jo", .ops = &jump_ops, },
+ { .name = "jp", .ops = &jump_ops, },
+ { .name = "jpe", .ops = &jump_ops, },
+ { .name = "jpo", .ops = &jump_ops, },
+ { .name = "jrcxz", .ops = &jump_ops, },
+ { .name = "js", .ops = &jump_ops, },
+ { .name = "jz", .ops = &jump_ops, },
+ { .name = "lea", .ops = &mov_ops, },
+ { .name = "lock", .ops = &lock_ops, },
+ { .name = "mov", .ops = &mov_ops, },
+ { .name = "movb", .ops = &mov_ops, },
+ { .name = "movdqa", .ops = &mov_ops, },
+ { .name = "movl", .ops = &mov_ops, },
+ { .name = "movq", .ops = &mov_ops, },
+ { .name = "movslq", .ops = &mov_ops, },
+ { .name = "movzbl", .ops = &mov_ops, },
+ { .name = "movzwl", .ops = &mov_ops, },
+ { .name = "nop", .ops = &nop_ops, },
+ { .name = "nopl", .ops = &nop_ops, },
+ { .name = "nopw", .ops = &nop_ops, },
+ { .name = "or", .ops = &mov_ops, },
+ { .name = "orl", .ops = &mov_ops, },
+ { .name = "test", .ops = &mov_ops, },
+ { .name = "testb", .ops = &mov_ops, },
+ { .name = "testl", .ops = &mov_ops, },
+ { .name = "xadd", .ops = &mov_ops, },
+ { .name = "xbeginl", .ops = &jump_ops, },
+ { .name = "xbeginq", .ops = &jump_ops, },
+ { .name = "retq", .ops = &ret_ops, },
+};
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 555263e385c9..e93ef0b38db8 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -335,6 +335,9 @@
326 common copy_file_range sys_copy_file_range
327 64 preadv2 sys_preadv2
328 64 pwritev2 sys_pwritev2
+329 common pkey_mprotect sys_pkey_mprotect
+330 common pkey_alloc sys_pkey_alloc
+331 common pkey_free sys_pkey_free
#
# x32-specific system call numbers start at 512 to avoid cache impact
@@ -374,5 +377,5 @@
543 x32 io_setup compat_sys_io_setup
544 x32 io_submit compat_sys_io_submit
545 x32 execveat compat_sys_execveat/ptregs
-534 x32 preadv2 compat_sys_preadv2
-535 x32 pwritev2 compat_sys_pwritev2
+546 x32 preadv2 compat_sys_preadv64v2
+547 x32 pwritev2 compat_sys_pwritev64v2
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
index 2218cb64f840..99d66191e56c 100644
--- a/tools/perf/arch/x86/tests/arch-tests.c
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -4,27 +4,27 @@
struct test arch_tests[] = {
{
- .desc = "x86 rdpmc test",
+ .desc = "x86 rdpmc",
.func = test__rdpmc,
},
{
- .desc = "Test converting perf time to TSC",
+ .desc = "Convert perf time to TSC",
.func = test__perf_time_to_tsc,
},
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
- .desc = "Test dwarf unwind",
+ .desc = "DWARF unwind",
.func = test__dwarf_unwind,
},
#endif
#ifdef HAVE_AUXTRACE_SUPPORT
{
- .desc = "Test x86 instruction decoder - new instructions",
+ .desc = "x86 instruction decoder - new instructions",
.func = test__insn_x86,
},
#endif
{
- .desc = "Test intel cqm nmi context read",
+ .desc = "Intel cqm nmi context read",
.func = test__intel_cqm_count_nmi_context,
},
{
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 8024cd5febd2..bfbb6b5f609c 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -63,8 +63,9 @@ static const char * const bench_futex_hash_usage[] = {
static void *workerfn(void *arg)
{
int ret;
- unsigned int i;
struct worker *w = (struct worker *) arg;
+ unsigned int i;
+ unsigned long ops = w->ops; /* avoid cacheline bouncing */
pthread_mutex_lock(&thread_lock);
threads_starting--;
@@ -74,7 +75,7 @@ static void *workerfn(void *arg)
pthread_mutex_unlock(&thread_lock);
do {
- for (i = 0; i < nfutexes; i++, w->ops++) {
+ for (i = 0; i < nfutexes; i++, ops++) {
/*
* We want the futex calls to fail in order to stress
* the hashing of uaddr and not measure other steps,
@@ -88,6 +89,7 @@ static void *workerfn(void *arg)
}
} while (!done);
+ w->ops = ops;
return NULL;
}
@@ -128,6 +130,8 @@ int bench_futex_hash(int argc, const char **argv,
}
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ nsecs = futexbench_sanitize_numeric(nsecs);
+ nfutexes = futexbench_sanitize_numeric(nfutexes);
sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done;
@@ -135,6 +139,8 @@ int bench_futex_hash(int argc, const char **argv,
if (!nthreads) /* default to the number of CPUs */
nthreads = ncpus;
+ else
+ nthreads = futexbench_sanitize_numeric(nthreads);
worker = calloc(nthreads, sizeof(*worker));
if (!worker)
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 936d89d30483..465012b320ee 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -75,6 +75,7 @@ static void toggle_done(int sig __maybe_unused,
static void *workerfn(void *arg)
{
struct worker *w = (struct worker *) arg;
+ unsigned long ops = w->ops;
pthread_mutex_lock(&thread_lock);
threads_starting--;
@@ -103,9 +104,10 @@ static void *workerfn(void *arg)
if (ret && !silent)
warn("thread %d: Could not unlock pi-lock for %p (%d)",
w->tid, w->futex, ret);
- w->ops++; /* account for thread's share of work */
+ ops++; /* account for thread's share of work */
} while (!done);
+ w->ops = ops;
return NULL;
}
@@ -150,6 +152,7 @@ int bench_futex_lock_pi(int argc, const char **argv,
goto err;
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ nsecs = futexbench_sanitize_numeric(nsecs);
sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done;
@@ -157,6 +160,8 @@ int bench_futex_lock_pi(int argc, const char **argv,
if (!nthreads)
nthreads = ncpus;
+ else
+ nthreads = futexbench_sanitize_numeric(nthreads);
worker = calloc(nthreads, sizeof(*worker));
if (!worker)
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 2b9705a8734c..fd4ee95b689a 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -128,6 +128,8 @@ int bench_futex_requeue(int argc, const char **argv,
if (!nthreads)
nthreads = ncpus;
+ else
+ nthreads = futexbench_sanitize_numeric(nthreads);
worker = calloc(nthreads, sizeof(*worker));
if (!worker)
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 2c8fa67ad537..beaa6c142477 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -217,8 +217,12 @@ int bench_futex_wake_parallel(int argc, const char **argv,
sigaction(SIGINT, &act, NULL);
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ nwaking_threads = futexbench_sanitize_numeric(nwaking_threads);
+
if (!nblocked_threads)
nblocked_threads = ncpus;
+ else
+ nblocked_threads = futexbench_sanitize_numeric(nblocked_threads);
/* some sanity checks */
if (nwaking_threads > nblocked_threads || !nwaking_threads)
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index e246b1b8388a..46efcb98b5a4 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -129,6 +129,7 @@ int bench_futex_wake(int argc, const char **argv,
}
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+ nwakes = futexbench_sanitize_numeric(nwakes);
sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done;
@@ -136,6 +137,8 @@ int bench_futex_wake(int argc, const char **argv,
if (!nthreads)
nthreads = ncpus;
+ else
+ nthreads = futexbench_sanitize_numeric(nthreads);
worker = calloc(nthreads, sizeof(*worker));
if (!worker)
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index b2e06d1190d0..ba7c735c0c62 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -7,6 +7,7 @@
#ifndef _FUTEX_H
#define _FUTEX_H
+#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -99,4 +100,7 @@ static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
}
#endif
+/* User input sanitation */
+#define futexbench_sanitize_numeric(__n) abs((__n))
+
#endif /* _FUTEX_H */
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index c684910e5a48..52504a83b5a1 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -106,9 +106,10 @@ static double timeval2double(struct timeval *ts)
struct bench_mem_info {
const struct function *functions;
- u64 (*do_cycles)(const struct function *r, size_t size);
- double (*do_gettimeofday)(const struct function *r, size_t size);
+ u64 (*do_cycles)(const struct function *r, size_t size, void *src, void *dst);
+ double (*do_gettimeofday)(const struct function *r, size_t size, void *src, void *dst);
const char *const *usage;
+ bool alloc_src;
};
static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total)
@@ -116,16 +117,26 @@ static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t
const struct function *r = &info->functions[r_idx];
double result_bps = 0.0;
u64 result_cycles = 0;
+ void *src = NULL, *dst = zalloc(size);
printf("# function '%s' (%s)\n", r->name, r->desc);
+ if (dst == NULL)
+ goto out_alloc_failed;
+
+ if (info->alloc_src) {
+ src = zalloc(size);
+ if (src == NULL)
+ goto out_alloc_failed;
+ }
+
if (bench_format == BENCH_FORMAT_DEFAULT)
printf("# Copying %s bytes ...\n\n", size_str);
if (use_cycles) {
- result_cycles = info->do_cycles(r, size);
+ result_cycles = info->do_cycles(r, size, src, dst);
} else {
- result_bps = info->do_gettimeofday(r, size);
+ result_bps = info->do_gettimeofday(r, size, src, dst);
}
switch (bench_format) {
@@ -149,6 +160,14 @@ static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t
BUG_ON(1);
break;
}
+
+out_free:
+ free(src);
+ free(dst);
+ return;
+out_alloc_failed:
+ printf("# Memory allocation failed - maybe size (%s) is too large?\n", size_str);
+ goto out_free;
}
static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info)
@@ -201,28 +220,14 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *
return 0;
}
-static void memcpy_alloc_mem(void **dst, void **src, size_t size)
-{
- *dst = zalloc(size);
- if (!*dst)
- die("memory allocation failed - maybe size is too large?\n");
-
- *src = zalloc(size);
- if (!*src)
- die("memory allocation failed - maybe size is too large?\n");
-
- /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
- memset(*src, 0, size);
-}
-
-static u64 do_memcpy_cycles(const struct function *r, size_t size)
+static u64 do_memcpy_cycles(const struct function *r, size_t size, void *src, void *dst)
{
u64 cycle_start = 0ULL, cycle_end = 0ULL;
- void *src = NULL, *dst = NULL;
memcpy_t fn = r->fn.memcpy;
int i;
- memcpy_alloc_mem(&dst, &src, size);
+ /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
+ memset(src, 0, size);
/*
* We prefault the freshly allocated memory range here,
@@ -235,20 +240,15 @@ static u64 do_memcpy_cycles(const struct function *r, size_t size)
fn(dst, src, size);
cycle_end = get_cycles();
- free(src);
- free(dst);
return cycle_end - cycle_start;
}
-static double do_memcpy_gettimeofday(const struct function *r, size_t size)
+static double do_memcpy_gettimeofday(const struct function *r, size_t size, void *src, void *dst)
{
struct timeval tv_start, tv_end, tv_diff;
memcpy_t fn = r->fn.memcpy;
- void *src = NULL, *dst = NULL;
int i;
- memcpy_alloc_mem(&dst, &src, size);
-
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
@@ -262,9 +262,6 @@ static double do_memcpy_gettimeofday(const struct function *r, size_t size)
timersub(&tv_end, &tv_start, &tv_diff);
- free(src);
- free(dst);
-
return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
}
@@ -294,27 +291,18 @@ int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unu
.do_cycles = do_memcpy_cycles,
.do_gettimeofday = do_memcpy_gettimeofday,
.usage = bench_mem_memcpy_usage,
+ .alloc_src = true,
};
return bench_mem_common(argc, argv, &info);
}
-static void memset_alloc_mem(void **dst, size_t size)
-{
- *dst = zalloc(size);
- if (!*dst)
- die("memory allocation failed - maybe size is too large?\n");
-}
-
-static u64 do_memset_cycles(const struct function *r, size_t size)
+static u64 do_memset_cycles(const struct function *r, size_t size, void *src __maybe_unused, void *dst)
{
u64 cycle_start = 0ULL, cycle_end = 0ULL;
memset_t fn = r->fn.memset;
- void *dst = NULL;
int i;
- memset_alloc_mem(&dst, size);
-
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
@@ -326,19 +314,15 @@ static u64 do_memset_cycles(const struct function *r, size_t size)
fn(dst, i, size);
cycle_end = get_cycles();
- free(dst);
return cycle_end - cycle_start;
}
-static double do_memset_gettimeofday(const struct function *r, size_t size)
+static double do_memset_gettimeofday(const struct function *r, size_t size, void *src __maybe_unused, void *dst)
{
struct timeval tv_start, tv_end, tv_diff;
memset_t fn = r->fn.memset;
- void *dst = NULL;
int i;
- memset_alloc_mem(&dst, size);
-
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
@@ -352,7 +336,6 @@ static double do_memset_gettimeofday(const struct function *r, size_t size)
timersub(&tv_end, &tv_start, &tv_diff);
- free(dst);
return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
}
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
new file mode 100644
index 000000000000..4b419631753d
--- /dev/null
+++ b/tools/perf/builtin-c2c.c
@@ -0,0 +1,2780 @@
+/*
+ * This is rewrite of original c2c tool introduced in here:
+ * http://lwn.net/Articles/588866/
+ *
+ * The original tool was changed to fit in current perf state.
+ *
+ * Original authors:
+ * Don Zickus <dzickus@redhat.com>
+ * Dick Fowles <fowles@inreach.com>
+ * Joe Mario <jmario@redhat.com>
+ */
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/stringify.h>
+#include <asm/bug.h>
+#include "util.h"
+#include "debug.h"
+#include "builtin.h"
+#include <subcmd/parse-options.h>
+#include "mem-events.h"
+#include "session.h"
+#include "hist.h"
+#include "sort.h"
+#include "tool.h"
+#include "data.h"
+#include "sort.h"
+#include "evlist.h"
+#include "evsel.h"
+#include <asm/bug.h>
+#include "ui/browsers/hists.h"
+#include "evlist.h"
+
+struct c2c_hists {
+ struct hists hists;
+ struct perf_hpp_list list;
+ struct c2c_stats stats;
+};
+
+struct compute_stats {
+ struct stats lcl_hitm;
+ struct stats rmt_hitm;
+ struct stats load;
+};
+
+struct c2c_hist_entry {
+ struct c2c_hists *hists;
+ struct c2c_stats stats;
+ unsigned long *cpuset;
+ struct c2c_stats *node_stats;
+ unsigned int cacheline_idx;
+
+ struct compute_stats cstats;
+
+ /*
+ * must be at the end,
+ * because of its callchain dynamic entry
+ */
+ struct hist_entry he;
+};
+
+static char const *coalesce_default = "pid,tid,iaddr";
+
+struct perf_c2c {
+ struct perf_tool tool;
+ struct c2c_hists hists;
+
+ unsigned long **nodes;
+ int nodes_cnt;
+ int cpus_cnt;
+ int *cpu2node;
+ int node_info;
+
+ bool show_src;
+ bool show_all;
+ bool use_stdio;
+ bool stats_only;
+ bool symbol_full;
+
+ /* HITM shared clines stats */
+ struct c2c_stats hitm_stats;
+ int shared_clines;
+
+ int display;
+
+ const char *coalesce;
+ char *cl_sort;
+ char *cl_resort;
+ char *cl_output;
+};
+
+enum {
+ DISPLAY_LCL,
+ DISPLAY_RMT,
+ DISPLAY_TOT,
+ DISPLAY_MAX,
+};
+
+static const char *display_str[DISPLAY_MAX] = {
+ [DISPLAY_LCL] = "Local",
+ [DISPLAY_RMT] = "Remote",
+ [DISPLAY_TOT] = "Total",
+};
+
+static const struct option c2c_options[] = {
+ OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
+ OPT_END()
+};
+
+static struct perf_c2c c2c;
+
+static void *c2c_he_zalloc(size_t size)
+{
+ struct c2c_hist_entry *c2c_he;
+
+ c2c_he = zalloc(size + sizeof(*c2c_he));
+ if (!c2c_he)
+ return NULL;
+
+ c2c_he->cpuset = bitmap_alloc(c2c.cpus_cnt);
+ if (!c2c_he->cpuset)
+ return NULL;
+
+ c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
+ if (!c2c_he->node_stats)
+ return NULL;
+
+ init_stats(&c2c_he->cstats.lcl_hitm);
+ init_stats(&c2c_he->cstats.rmt_hitm);
+ init_stats(&c2c_he->cstats.load);
+
+ return &c2c_he->he;
+}
+
+static void c2c_he_free(void *he)
+{
+ struct c2c_hist_entry *c2c_he;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ if (c2c_he->hists) {
+ hists__delete_entries(&c2c_he->hists->hists);
+ free(c2c_he->hists);
+ }
+
+ free(c2c_he->cpuset);
+ free(c2c_he->node_stats);
+ free(c2c_he);
+}
+
+static struct hist_entry_ops c2c_entry_ops = {
+ .new = c2c_he_zalloc,
+ .free = c2c_he_free,
+};
+
+static int c2c_hists__init(struct c2c_hists *hists,
+ const char *sort,
+ int nr_header_lines);
+
+static struct c2c_hists*
+he__get_c2c_hists(struct hist_entry *he,
+ const char *sort,
+ int nr_header_lines)
+{
+ struct c2c_hist_entry *c2c_he;
+ struct c2c_hists *hists;
+ int ret;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ if (c2c_he->hists)
+ return c2c_he->hists;
+
+ hists = c2c_he->hists = zalloc(sizeof(*hists));
+ if (!hists)
+ return NULL;
+
+ ret = c2c_hists__init(hists, sort, nr_header_lines);
+ if (ret) {
+ free(hists);
+ return NULL;
+ }
+
+ return hists;
+}
+
+static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
+ struct perf_sample *sample)
+{
+ if (WARN_ONCE(sample->cpu == (unsigned int) -1,
+ "WARNING: no sample cpu value"))
+ return;
+
+ set_bit(sample->cpu, c2c_he->cpuset);
+}
+
+static void compute_stats(struct c2c_hist_entry *c2c_he,
+ struct c2c_stats *stats,
+ u64 weight)
+{
+ struct compute_stats *cstats = &c2c_he->cstats;
+
+ if (stats->rmt_hitm)
+ update_stats(&cstats->rmt_hitm, weight);
+ else if (stats->lcl_hitm)
+ update_stats(&cstats->lcl_hitm, weight);
+ else if (stats->load)
+ update_stats(&cstats->load, weight);
+}
+
+static int process_sample_event(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel __maybe_unused,
+ struct machine *machine)
+{
+ struct c2c_hists *c2c_hists = &c2c.hists;
+ struct c2c_hist_entry *c2c_he;
+ struct c2c_stats stats = { .nr_entries = 0, };
+ struct hist_entry *he;
+ struct addr_location al;
+ struct mem_info *mi, *mi_dup;
+ int ret;
+
+ if (machine__resolve(machine, &al, sample) < 0) {
+ pr_debug("problem processing %d event, skipping it.\n",
+ event->header.type);
+ return -1;
+ }
+
+ ret = sample__resolve_callchain(sample, &callchain_cursor, NULL,
+ evsel, &al, sysctl_perf_event_max_stack);
+ if (ret)
+ goto out;
+
+ mi = sample__resolve_mem(sample, &al);
+ if (mi == NULL)
+ return -ENOMEM;
+
+ mi_dup = memdup(mi, sizeof(*mi));
+ if (!mi_dup)
+ goto free_mi;
+
+ c2c_decode_stats(&stats, mi);
+
+ he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
+ &al, NULL, NULL, mi,
+ sample, true);
+ if (he == NULL)
+ goto free_mi_dup;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ c2c_add_stats(&c2c_he->stats, &stats);
+ c2c_add_stats(&c2c_hists->stats, &stats);
+
+ c2c_he__set_cpu(c2c_he, sample);
+
+ hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
+ ret = hist_entry__append_callchain(he, sample);
+
+ if (!ret) {
+ /*
+ * There's already been warning about missing
+ * sample's cpu value. Let's account all to
+ * node 0 in this case, without any further
+ * warning.
+ *
+ * Doing node stats only for single callchain data.
+ */
+ int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
+ int node = c2c.cpu2node[cpu];
+
+ mi = mi_dup;
+
+ mi_dup = memdup(mi, sizeof(*mi));
+ if (!mi_dup)
+ goto free_mi;
+
+ c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
+ if (!c2c_hists)
+ goto free_mi_dup;
+
+ he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
+ &al, NULL, NULL, mi,
+ sample, true);
+ if (he == NULL)
+ goto free_mi_dup;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ c2c_add_stats(&c2c_he->stats, &stats);
+ c2c_add_stats(&c2c_hists->stats, &stats);
+ c2c_add_stats(&c2c_he->node_stats[node], &stats);
+
+ compute_stats(c2c_he, &stats, sample->weight);
+
+ c2c_he__set_cpu(c2c_he, sample);
+
+ hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
+ ret = hist_entry__append_callchain(he, sample);
+ }
+
+out:
+ addr_location__put(&al);
+ return ret;
+
+free_mi_dup:
+ free(mi_dup);
+free_mi:
+ free(mi);
+ ret = -ENOMEM;
+ goto out;
+}
+
+static struct perf_c2c c2c = {
+ .tool = {
+ .sample = process_sample_event,
+ .mmap = perf_event__process_mmap,
+ .mmap2 = perf_event__process_mmap2,
+ .comm = perf_event__process_comm,
+ .exit = perf_event__process_exit,
+ .fork = perf_event__process_fork,
+ .lost = perf_event__process_lost,
+ .ordered_events = true,
+ .ordering_requires_timestamps = true,
+ },
+};
+
+static const char * const c2c_usage[] = {
+ "perf c2c {record|report}",
+ NULL
+};
+
+static const char * const __usage_report[] = {
+ "perf c2c report",
+ NULL
+};
+
+static const char * const *report_c2c_usage = __usage_report;
+
+#define C2C_HEADER_MAX 2
+
+struct c2c_header {
+ struct {
+ const char *text;
+ int span;
+ } line[C2C_HEADER_MAX];
+};
+
+struct c2c_dimension {
+ struct c2c_header header;
+ const char *name;
+ int width;
+ struct sort_entry *se;
+
+ int64_t (*cmp)(struct perf_hpp_fmt *fmt,
+ struct hist_entry *, struct hist_entry *);
+ int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he);
+ int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he);
+};
+
+struct c2c_fmt {
+ struct perf_hpp_fmt fmt;
+ struct c2c_dimension *dim;
+};
+
+#define SYMBOL_WIDTH 30
+
+static struct c2c_dimension dim_symbol;
+static struct c2c_dimension dim_srcline;
+
+static int symbol_width(struct hists *hists, struct sort_entry *se)
+{
+ int width = hists__col_len(hists, se->se_width_idx);
+
+ if (!c2c.symbol_full)
+ width = MIN(width, SYMBOL_WIDTH);
+
+ return width;
+}
+
+static int c2c_width(struct perf_hpp_fmt *fmt,
+ struct perf_hpp *hpp __maybe_unused,
+ struct hists *hists __maybe_unused)
+{
+ struct c2c_fmt *c2c_fmt;
+ struct c2c_dimension *dim;
+
+ c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ dim = c2c_fmt->dim;
+
+ if (dim == &dim_symbol || dim == &dim_srcline)
+ return symbol_width(hists, dim->se);
+
+ return dim->se ? hists__col_len(hists, dim->se->se_width_idx) :
+ c2c_fmt->dim->width;
+}
+
+static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hists *hists, int line, int *span)
+{
+ struct perf_hpp_list *hpp_list = hists->hpp_list;
+ struct c2c_fmt *c2c_fmt;
+ struct c2c_dimension *dim;
+ const char *text = NULL;
+ int width = c2c_width(fmt, hpp, hists);
+
+ c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ dim = c2c_fmt->dim;
+
+ if (dim->se) {
+ text = dim->header.line[line].text;
+ /* Use the last line from sort_entry if not defined. */
+ if (!text && (line == hpp_list->nr_header_lines - 1))
+ text = dim->se->se_header;
+ } else {
+ text = dim->header.line[line].text;
+
+ if (*span) {
+ (*span)--;
+ return 0;
+ } else {
+ *span = dim->header.line[line].span;
+ }
+ }
+
+ if (text == NULL)
+ text = "";
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, text);
+}
+
+#define HEX_STR(__s, __v) \
+({ \
+ scnprintf(__s, sizeof(__s), "0x%" PRIx64, __v); \
+ __s; \
+})
+
+static int64_t
+dcacheline_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__dcacheline_cmp(left, right);
+}
+
+static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ uint64_t addr = 0;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[20];
+
+ if (he->mem_info)
+ addr = cl_address(he->mem_info->daddr.addr);
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
+}
+
+static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ uint64_t addr = 0;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[20];
+
+ if (he->mem_info)
+ addr = cl_offset(he->mem_info->daddr.al_addr);
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
+}
+
+static int64_t
+offset_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ uint64_t l = 0, r = 0;
+
+ if (left->mem_info)
+ l = cl_offset(left->mem_info->daddr.addr);
+ if (right->mem_info)
+ r = cl_offset(right->mem_info->daddr.addr);
+
+ return (int64_t)(r - l);
+}
+
+static int
+iaddr_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ uint64_t addr = 0;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[20];
+
+ if (he->mem_info)
+ addr = he->mem_info->iaddr.addr;
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
+}
+
+static int64_t
+iaddr_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__iaddr_cmp(left, right);
+}
+
+static int
+tot_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ unsigned int tot_hitm;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ tot_hitm = c2c_he->stats.lcl_hitm + c2c_he->stats.rmt_hitm;
+
+ return scnprintf(hpp->buf, hpp->size, "%*u", width, tot_hitm);
+}
+
+static int64_t
+tot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ struct c2c_hist_entry *c2c_left;
+ struct c2c_hist_entry *c2c_right;
+ unsigned int tot_hitm_left;
+ unsigned int tot_hitm_right;
+
+ c2c_left = container_of(left, struct c2c_hist_entry, he);
+ c2c_right = container_of(right, struct c2c_hist_entry, he);
+
+ tot_hitm_left = c2c_left->stats.lcl_hitm + c2c_left->stats.rmt_hitm;
+ tot_hitm_right = c2c_right->stats.lcl_hitm + c2c_right->stats.rmt_hitm;
+
+ return tot_hitm_left - tot_hitm_right;
+}
+
+#define STAT_FN_ENTRY(__f) \
+static int \
+__f ## _entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, \
+ struct hist_entry *he) \
+{ \
+ struct c2c_hist_entry *c2c_he; \
+ int width = c2c_width(fmt, hpp, he->hists); \
+ \
+ c2c_he = container_of(he, struct c2c_hist_entry, he); \
+ return scnprintf(hpp->buf, hpp->size, "%*u", width, \
+ c2c_he->stats.__f); \
+}
+
+#define STAT_FN_CMP(__f) \
+static int64_t \
+__f ## _cmp(struct perf_hpp_fmt *fmt __maybe_unused, \
+ struct hist_entry *left, struct hist_entry *right) \
+{ \
+ struct c2c_hist_entry *c2c_left, *c2c_right; \
+ \
+ c2c_left = container_of(left, struct c2c_hist_entry, he); \
+ c2c_right = container_of(right, struct c2c_hist_entry, he); \
+ return c2c_left->stats.__f - c2c_right->stats.__f; \
+}
+
+#define STAT_FN(__f) \
+ STAT_FN_ENTRY(__f) \
+ STAT_FN_CMP(__f)
+
+STAT_FN(rmt_hitm)
+STAT_FN(lcl_hitm)
+STAT_FN(store)
+STAT_FN(st_l1hit)
+STAT_FN(st_l1miss)
+STAT_FN(ld_fbhit)
+STAT_FN(ld_l1hit)
+STAT_FN(ld_l2hit)
+STAT_FN(ld_llchit)
+STAT_FN(rmt_hit)
+
+static uint64_t llc_miss(struct c2c_stats *stats)
+{
+ uint64_t llcmiss;
+
+ llcmiss = stats->lcl_dram +
+ stats->rmt_dram +
+ stats->rmt_hitm +
+ stats->rmt_hit;
+
+ return llcmiss;
+}
+
+static int
+ld_llcmiss_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+ return scnprintf(hpp->buf, hpp->size, "%*lu", width,
+ llc_miss(&c2c_he->stats));
+}
+
+static int64_t
+ld_llcmiss_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ struct c2c_hist_entry *c2c_left;
+ struct c2c_hist_entry *c2c_right;
+
+ c2c_left = container_of(left, struct c2c_hist_entry, he);
+ c2c_right = container_of(right, struct c2c_hist_entry, he);
+
+ return llc_miss(&c2c_left->stats) - llc_miss(&c2c_right->stats);
+}
+
+static uint64_t total_records(struct c2c_stats *stats)
+{
+ uint64_t lclmiss, ldcnt, total;
+
+ lclmiss = stats->lcl_dram +
+ stats->rmt_dram +
+ stats->rmt_hitm +
+ stats->rmt_hit;
+
+ ldcnt = lclmiss +
+ stats->ld_fbhit +
+ stats->ld_l1hit +
+ stats->ld_l2hit +
+ stats->ld_llchit +
+ stats->lcl_hitm;
+
+ total = ldcnt +
+ stats->st_l1hit +
+ stats->st_l1miss;
+
+ return total;
+}
+
+static int
+tot_recs_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ uint64_t tot_recs;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ tot_recs = total_records(&c2c_he->stats);
+
+ return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
+}
+
+static int64_t
+tot_recs_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ struct c2c_hist_entry *c2c_left;
+ struct c2c_hist_entry *c2c_right;
+ uint64_t tot_recs_left;
+ uint64_t tot_recs_right;
+
+ c2c_left = container_of(left, struct c2c_hist_entry, he);
+ c2c_right = container_of(right, struct c2c_hist_entry, he);
+
+ tot_recs_left = total_records(&c2c_left->stats);
+ tot_recs_right = total_records(&c2c_right->stats);
+
+ return tot_recs_left - tot_recs_right;
+}
+
+static uint64_t total_loads(struct c2c_stats *stats)
+{
+ uint64_t lclmiss, ldcnt;
+
+ lclmiss = stats->lcl_dram +
+ stats->rmt_dram +
+ stats->rmt_hitm +
+ stats->rmt_hit;
+
+ ldcnt = lclmiss +
+ stats->ld_fbhit +
+ stats->ld_l1hit +
+ stats->ld_l2hit +
+ stats->ld_llchit +
+ stats->lcl_hitm;
+
+ return ldcnt;
+}
+
+static int
+tot_loads_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ uint64_t tot_recs;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ tot_recs = total_loads(&c2c_he->stats);
+
+ return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
+}
+
+static int64_t
+tot_loads_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ struct c2c_hist_entry *c2c_left;
+ struct c2c_hist_entry *c2c_right;
+ uint64_t tot_recs_left;
+ uint64_t tot_recs_right;
+
+ c2c_left = container_of(left, struct c2c_hist_entry, he);
+ c2c_right = container_of(right, struct c2c_hist_entry, he);
+
+ tot_recs_left = total_loads(&c2c_left->stats);
+ tot_recs_right = total_loads(&c2c_right->stats);
+
+ return tot_recs_left - tot_recs_right;
+}
+
+typedef double (get_percent_cb)(struct c2c_hist_entry *);
+
+static int
+percent_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he, get_percent_cb get_percent)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ double per;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ per = get_percent(c2c_he);
+
+#ifdef HAVE_SLANG_SUPPORT
+ if (use_browser)
+ return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per);
+#endif
+ return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per);
+}
+
+static double percent_hitm(struct c2c_hist_entry *c2c_he)
+{
+ struct c2c_hists *hists;
+ struct c2c_stats *stats;
+ struct c2c_stats *total;
+ int tot = 0, st = 0;
+ double p;
+
+ hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
+ stats = &c2c_he->stats;
+ total = &hists->stats;
+
+ switch (c2c.display) {
+ case DISPLAY_RMT:
+ st = stats->rmt_hitm;
+ tot = total->rmt_hitm;
+ break;
+ case DISPLAY_LCL:
+ st = stats->lcl_hitm;
+ tot = total->lcl_hitm;
+ break;
+ case DISPLAY_TOT:
+ st = stats->tot_hitm;
+ tot = total->tot_hitm;
+ default:
+ break;
+ }
+
+ p = tot ? (double) st / tot : 0;
+
+ return 100 * p;
+}
+
+#define PERC_STR(__s, __v) \
+({ \
+ scnprintf(__s, sizeof(__s), "%.2F%%", __v); \
+ __s; \
+})
+
+static int
+percent_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[10];
+ double per;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ per = percent_hitm(c2c_he);
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
+}
+
+static int
+percent_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ return percent_color(fmt, hpp, he, percent_hitm);
+}
+
+static int64_t
+percent_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ struct c2c_hist_entry *c2c_left;
+ struct c2c_hist_entry *c2c_right;
+ double per_left;
+ double per_right;
+
+ c2c_left = container_of(left, struct c2c_hist_entry, he);
+ c2c_right = container_of(right, struct c2c_hist_entry, he);
+
+ per_left = percent_hitm(c2c_left);
+ per_right = percent_hitm(c2c_right);
+
+ return per_left - per_right;
+}
+
+static struct c2c_stats *he_stats(struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ return &c2c_he->stats;
+}
+
+static struct c2c_stats *total_stats(struct hist_entry *he)
+{
+ struct c2c_hists *hists;
+
+ hists = container_of(he->hists, struct c2c_hists, hists);
+ return &hists->stats;
+}
+
+static double percent(int st, int tot)
+{
+ return tot ? 100. * (double) st / (double) tot : 0;
+}
+
+#define PERCENT(__h, __f) percent(he_stats(__h)->__f, total_stats(__h)->__f)
+
+#define PERCENT_FN(__f) \
+static double percent_ ## __f(struct c2c_hist_entry *c2c_he) \
+{ \
+ struct c2c_hists *hists; \
+ \
+ hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); \
+ return percent(c2c_he->stats.__f, hists->stats.__f); \
+}
+
+PERCENT_FN(rmt_hitm)
+PERCENT_FN(lcl_hitm)
+PERCENT_FN(st_l1hit)
+PERCENT_FN(st_l1miss)
+
+static int
+percent_rmt_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+ double per = PERCENT(he, rmt_hitm);
+ char buf[10];
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
+}
+
+static int
+percent_rmt_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ return percent_color(fmt, hpp, he, percent_rmt_hitm);
+}
+
+static int64_t
+percent_rmt_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ double per_left;
+ double per_right;
+
+ per_left = PERCENT(left, lcl_hitm);
+ per_right = PERCENT(right, lcl_hitm);
+
+ return per_left - per_right;
+}
+
+static int
+percent_lcl_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+ double per = PERCENT(he, lcl_hitm);
+ char buf[10];
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
+}
+
+static int
+percent_lcl_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ return percent_color(fmt, hpp, he, percent_lcl_hitm);
+}
+
+static int64_t
+percent_lcl_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ double per_left;
+ double per_right;
+
+ per_left = PERCENT(left, lcl_hitm);
+ per_right = PERCENT(right, lcl_hitm);
+
+ return per_left - per_right;
+}
+
+static int
+percent_stores_l1hit_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+ double per = PERCENT(he, st_l1hit);
+ char buf[10];
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
+}
+
+static int
+percent_stores_l1hit_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ return percent_color(fmt, hpp, he, percent_st_l1hit);
+}
+
+static int64_t
+percent_stores_l1hit_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ double per_left;
+ double per_right;
+
+ per_left = PERCENT(left, st_l1hit);
+ per_right = PERCENT(right, st_l1hit);
+
+ return per_left - per_right;
+}
+
+static int
+percent_stores_l1miss_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+ double per = PERCENT(he, st_l1miss);
+ char buf[10];
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
+}
+
+static int
+percent_stores_l1miss_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ return percent_color(fmt, hpp, he, percent_st_l1miss);
+}
+
+static int64_t
+percent_stores_l1miss_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ double per_left;
+ double per_right;
+
+ per_left = PERCENT(left, st_l1miss);
+ per_right = PERCENT(right, st_l1miss);
+
+ return per_left - per_right;
+}
+
+STAT_FN(lcl_dram)
+STAT_FN(rmt_dram)
+
+static int
+pid_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+
+ return scnprintf(hpp->buf, hpp->size, "%*d", width, he->thread->pid_);
+}
+
+static int64_t
+pid_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left, struct hist_entry *right)
+{
+ return left->thread->pid_ - right->thread->pid_;
+}
+
+static int64_t
+empty_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+ struct hist_entry *left __maybe_unused,
+ struct hist_entry *right __maybe_unused)
+{
+ return 0;
+}
+
+static int
+node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ bool first = true;
+ int node;
+ int ret = 0;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+ for (node = 0; node < c2c.nodes_cnt; node++) {
+ DECLARE_BITMAP(set, c2c.cpus_cnt);
+
+ bitmap_zero(set, c2c.cpus_cnt);
+ bitmap_and(set, c2c_he->cpuset, c2c.nodes[node], c2c.cpus_cnt);
+
+ if (!bitmap_weight(set, c2c.cpus_cnt)) {
+ if (c2c.node_info == 1) {
+ ret = scnprintf(hpp->buf, hpp->size, "%21s", " ");
+ advance_hpp(hpp, ret);
+ }
+ continue;
+ }
+
+ if (!first) {
+ ret = scnprintf(hpp->buf, hpp->size, " ");
+ advance_hpp(hpp, ret);
+ }
+
+ switch (c2c.node_info) {
+ case 0:
+ ret = scnprintf(hpp->buf, hpp->size, "%2d", node);
+ advance_hpp(hpp, ret);
+ break;
+ case 1:
+ {
+ int num = bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt);
+ struct c2c_stats *stats = &c2c_he->node_stats[node];
+
+ ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
+ advance_hpp(hpp, ret);
+
+ #define DISPLAY_HITM(__h) \
+ if (c2c_he->stats.__h> 0) { \
+ ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ", \
+ percent(stats->__h, c2c_he->stats.__h));\
+ } else { \
+ ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a"); \
+ }
+
+ switch (c2c.display) {
+ case DISPLAY_RMT:
+ DISPLAY_HITM(rmt_hitm);
+ break;
+ case DISPLAY_LCL:
+ DISPLAY_HITM(lcl_hitm);
+ break;
+ case DISPLAY_TOT:
+ DISPLAY_HITM(tot_hitm);
+ default:
+ break;
+ }
+
+ #undef DISPLAY_HITM
+
+ advance_hpp(hpp, ret);
+
+ if (c2c_he->stats.store > 0) {
+ ret = scnprintf(hpp->buf, hpp->size, "%5.1f%%}",
+ percent(stats->store, c2c_he->stats.store));
+ } else {
+ ret = scnprintf(hpp->buf, hpp->size, "%6s}", "n/a");
+ }
+
+ advance_hpp(hpp, ret);
+ break;
+ }
+ case 2:
+ ret = scnprintf(hpp->buf, hpp->size, "%2d{", node);
+ advance_hpp(hpp, ret);
+
+ ret = bitmap_scnprintf(set, c2c.cpus_cnt, hpp->buf, hpp->size);
+ advance_hpp(hpp, ret);
+
+ ret = scnprintf(hpp->buf, hpp->size, "}");
+ advance_hpp(hpp, ret);
+ break;
+ default:
+ break;
+ }
+
+ first = false;
+ }
+
+ return 0;
+}
+
+static int
+mean_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he, double mean)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[10];
+
+ scnprintf(buf, 10, "%6.0f", mean);
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
+}
+
+#define MEAN_ENTRY(__func, __val) \
+static int \
+__func(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he) \
+{ \
+ struct c2c_hist_entry *c2c_he; \
+ c2c_he = container_of(he, struct c2c_hist_entry, he); \
+ return mean_entry(fmt, hpp, he, avg_stats(&c2c_he->cstats.__val)); \
+}
+
+MEAN_ENTRY(mean_rmt_entry, rmt_hitm);
+MEAN_ENTRY(mean_lcl_entry, lcl_hitm);
+MEAN_ENTRY(mean_load_entry, load);
+
+static int
+cpucnt_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[10];
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+ scnprintf(buf, 10, "%d", bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt));
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
+}
+
+static int
+cl_idx_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ int width = c2c_width(fmt, hpp, he->hists);
+ char buf[10];
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+ scnprintf(buf, 10, "%u", c2c_he->cacheline_idx);
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
+}
+
+static int
+cl_idx_empty_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ int width = c2c_width(fmt, hpp, he->hists);
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, "");
+}
+
+#define HEADER_LOW(__h) \
+ { \
+ .line[1] = { \
+ .text = __h, \
+ }, \
+ }
+
+#define HEADER_BOTH(__h0, __h1) \
+ { \
+ .line[0] = { \
+ .text = __h0, \
+ }, \
+ .line[1] = { \
+ .text = __h1, \
+ }, \
+ }
+
+#define HEADER_SPAN(__h0, __h1, __s) \
+ { \
+ .line[0] = { \
+ .text = __h0, \
+ .span = __s, \
+ }, \
+ .line[1] = { \
+ .text = __h1, \
+ }, \
+ }
+
+#define HEADER_SPAN_LOW(__h) \
+ { \
+ .line[1] = { \
+ .text = __h, \
+ }, \
+ }
+
+static struct c2c_dimension dim_dcacheline = {
+ .header = HEADER_LOW("Cacheline"),
+ .name = "dcacheline",
+ .cmp = dcacheline_cmp,
+ .entry = dcacheline_entry,
+ .width = 18,
+};
+
+static struct c2c_header header_offset_tui = HEADER_LOW("Off");
+
+static struct c2c_dimension dim_offset = {
+ .header = HEADER_BOTH("Data address", "Offset"),
+ .name = "offset",
+ .cmp = offset_cmp,
+ .entry = offset_entry,
+ .width = 18,
+};
+
+static struct c2c_dimension dim_iaddr = {
+ .header = HEADER_LOW("Code address"),
+ .name = "iaddr",
+ .cmp = iaddr_cmp,
+ .entry = iaddr_entry,
+ .width = 18,
+};
+
+static struct c2c_dimension dim_tot_hitm = {
+ .header = HEADER_SPAN("----- LLC Load Hitm -----", "Total", 2),
+ .name = "tot_hitm",
+ .cmp = tot_hitm_cmp,
+ .entry = tot_hitm_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_lcl_hitm = {
+ .header = HEADER_SPAN_LOW("Lcl"),
+ .name = "lcl_hitm",
+ .cmp = lcl_hitm_cmp,
+ .entry = lcl_hitm_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_rmt_hitm = {
+ .header = HEADER_SPAN_LOW("Rmt"),
+ .name = "rmt_hitm",
+ .cmp = rmt_hitm_cmp,
+ .entry = rmt_hitm_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_cl_rmt_hitm = {
+ .header = HEADER_SPAN("----- HITM -----", "Rmt", 1),
+ .name = "cl_rmt_hitm",
+ .cmp = rmt_hitm_cmp,
+ .entry = rmt_hitm_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_cl_lcl_hitm = {
+ .header = HEADER_SPAN_LOW("Lcl"),
+ .name = "cl_lcl_hitm",
+ .cmp = lcl_hitm_cmp,
+ .entry = lcl_hitm_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_stores = {
+ .header = HEADER_SPAN("---- Store Reference ----", "Total", 2),
+ .name = "stores",
+ .cmp = store_cmp,
+ .entry = store_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_stores_l1hit = {
+ .header = HEADER_SPAN_LOW("L1Hit"),
+ .name = "stores_l1hit",
+ .cmp = st_l1hit_cmp,
+ .entry = st_l1hit_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_stores_l1miss = {
+ .header = HEADER_SPAN_LOW("L1Miss"),
+ .name = "stores_l1miss",
+ .cmp = st_l1miss_cmp,
+ .entry = st_l1miss_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_cl_stores_l1hit = {
+ .header = HEADER_SPAN("-- Store Refs --", "L1 Hit", 1),
+ .name = "cl_stores_l1hit",
+ .cmp = st_l1hit_cmp,
+ .entry = st_l1hit_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_cl_stores_l1miss = {
+ .header = HEADER_SPAN_LOW("L1 Miss"),
+ .name = "cl_stores_l1miss",
+ .cmp = st_l1miss_cmp,
+ .entry = st_l1miss_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_ld_fbhit = {
+ .header = HEADER_SPAN("----- Core Load Hit -----", "FB", 2),
+ .name = "ld_fbhit",
+ .cmp = ld_fbhit_cmp,
+ .entry = ld_fbhit_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_ld_l1hit = {
+ .header = HEADER_SPAN_LOW("L1"),
+ .name = "ld_l1hit",
+ .cmp = ld_l1hit_cmp,
+ .entry = ld_l1hit_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_ld_l2hit = {
+ .header = HEADER_SPAN_LOW("L2"),
+ .name = "ld_l2hit",
+ .cmp = ld_l2hit_cmp,
+ .entry = ld_l2hit_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_ld_llchit = {
+ .header = HEADER_SPAN("-- LLC Load Hit --", "Llc", 1),
+ .name = "ld_lclhit",
+ .cmp = ld_llchit_cmp,
+ .entry = ld_llchit_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_ld_rmthit = {
+ .header = HEADER_SPAN_LOW("Rmt"),
+ .name = "ld_rmthit",
+ .cmp = rmt_hit_cmp,
+ .entry = rmt_hit_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_ld_llcmiss = {
+ .header = HEADER_BOTH("LLC", "Ld Miss"),
+ .name = "ld_llcmiss",
+ .cmp = ld_llcmiss_cmp,
+ .entry = ld_llcmiss_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_tot_recs = {
+ .header = HEADER_BOTH("Total", "records"),
+ .name = "tot_recs",
+ .cmp = tot_recs_cmp,
+ .entry = tot_recs_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_tot_loads = {
+ .header = HEADER_BOTH("Total", "Loads"),
+ .name = "tot_loads",
+ .cmp = tot_loads_cmp,
+ .entry = tot_loads_entry,
+ .width = 7,
+};
+
+static struct c2c_header percent_hitm_header[] = {
+ [DISPLAY_LCL] = HEADER_BOTH("Lcl", "Hitm"),
+ [DISPLAY_RMT] = HEADER_BOTH("Rmt", "Hitm"),
+ [DISPLAY_TOT] = HEADER_BOTH("Tot", "Hitm"),
+};
+
+static struct c2c_dimension dim_percent_hitm = {
+ .name = "percent_hitm",
+ .cmp = percent_hitm_cmp,
+ .entry = percent_hitm_entry,
+ .color = percent_hitm_color,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_percent_rmt_hitm = {
+ .header = HEADER_SPAN("----- HITM -----", "Rmt", 1),
+ .name = "percent_rmt_hitm",
+ .cmp = percent_rmt_hitm_cmp,
+ .entry = percent_rmt_hitm_entry,
+ .color = percent_rmt_hitm_color,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_percent_lcl_hitm = {
+ .header = HEADER_SPAN_LOW("Lcl"),
+ .name = "percent_lcl_hitm",
+ .cmp = percent_lcl_hitm_cmp,
+ .entry = percent_lcl_hitm_entry,
+ .color = percent_lcl_hitm_color,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_percent_stores_l1hit = {
+ .header = HEADER_SPAN("-- Store Refs --", "L1 Hit", 1),
+ .name = "percent_stores_l1hit",
+ .cmp = percent_stores_l1hit_cmp,
+ .entry = percent_stores_l1hit_entry,
+ .color = percent_stores_l1hit_color,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_percent_stores_l1miss = {
+ .header = HEADER_SPAN_LOW("L1 Miss"),
+ .name = "percent_stores_l1miss",
+ .cmp = percent_stores_l1miss_cmp,
+ .entry = percent_stores_l1miss_entry,
+ .color = percent_stores_l1miss_color,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_dram_lcl = {
+ .header = HEADER_SPAN("--- Load Dram ----", "Lcl", 1),
+ .name = "dram_lcl",
+ .cmp = lcl_dram_cmp,
+ .entry = lcl_dram_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_dram_rmt = {
+ .header = HEADER_SPAN_LOW("Rmt"),
+ .name = "dram_rmt",
+ .cmp = rmt_dram_cmp,
+ .entry = rmt_dram_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_pid = {
+ .header = HEADER_LOW("Pid"),
+ .name = "pid",
+ .cmp = pid_cmp,
+ .entry = pid_entry,
+ .width = 7,
+};
+
+static struct c2c_dimension dim_tid = {
+ .header = HEADER_LOW("Tid"),
+ .name = "tid",
+ .se = &sort_thread,
+};
+
+static struct c2c_dimension dim_symbol = {
+ .name = "symbol",
+ .se = &sort_sym,
+};
+
+static struct c2c_dimension dim_dso = {
+ .header = HEADER_BOTH("Shared", "Object"),
+ .name = "dso",
+ .se = &sort_dso,
+};
+
+static struct c2c_header header_node[3] = {
+ HEADER_LOW("Node"),
+ HEADER_LOW("Node{cpus %hitms %stores}"),
+ HEADER_LOW("Node{cpu list}"),
+};
+
+static struct c2c_dimension dim_node = {
+ .name = "node",
+ .cmp = empty_cmp,
+ .entry = node_entry,
+ .width = 4,
+};
+
+static struct c2c_dimension dim_mean_rmt = {
+ .header = HEADER_SPAN("---------- cycles ----------", "rmt hitm", 2),
+ .name = "mean_rmt",
+ .cmp = empty_cmp,
+ .entry = mean_rmt_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_mean_lcl = {
+ .header = HEADER_SPAN_LOW("lcl hitm"),
+ .name = "mean_lcl",
+ .cmp = empty_cmp,
+ .entry = mean_lcl_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_mean_load = {
+ .header = HEADER_SPAN_LOW("load"),
+ .name = "mean_load",
+ .cmp = empty_cmp,
+ .entry = mean_load_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_cpucnt = {
+ .header = HEADER_BOTH("cpu", "cnt"),
+ .name = "cpucnt",
+ .cmp = empty_cmp,
+ .entry = cpucnt_entry,
+ .width = 8,
+};
+
+static struct c2c_dimension dim_srcline = {
+ .name = "cl_srcline",
+ .se = &sort_srcline,
+};
+
+static struct c2c_dimension dim_dcacheline_idx = {
+ .header = HEADER_LOW("Index"),
+ .name = "cl_idx",
+ .cmp = empty_cmp,
+ .entry = cl_idx_entry,
+ .width = 5,
+};
+
+static struct c2c_dimension dim_dcacheline_num = {
+ .header = HEADER_LOW("Num"),
+ .name = "cl_num",
+ .cmp = empty_cmp,
+ .entry = cl_idx_entry,
+ .width = 5,
+};
+
+static struct c2c_dimension dim_dcacheline_num_empty = {
+ .header = HEADER_LOW("Num"),
+ .name = "cl_num_empty",
+ .cmp = empty_cmp,
+ .entry = cl_idx_empty_entry,
+ .width = 5,
+};
+
+static struct c2c_dimension *dimensions[] = {
+ &dim_dcacheline,
+ &dim_offset,
+ &dim_iaddr,
+ &dim_tot_hitm,
+ &dim_lcl_hitm,
+ &dim_rmt_hitm,
+ &dim_cl_lcl_hitm,
+ &dim_cl_rmt_hitm,
+ &dim_stores,
+ &dim_stores_l1hit,
+ &dim_stores_l1miss,
+ &dim_cl_stores_l1hit,
+ &dim_cl_stores_l1miss,
+ &dim_ld_fbhit,
+ &dim_ld_l1hit,
+ &dim_ld_l2hit,
+ &dim_ld_llchit,
+ &dim_ld_rmthit,
+ &dim_ld_llcmiss,
+ &dim_tot_recs,
+ &dim_tot_loads,
+ &dim_percent_hitm,
+ &dim_percent_rmt_hitm,
+ &dim_percent_lcl_hitm,
+ &dim_percent_stores_l1hit,
+ &dim_percent_stores_l1miss,
+ &dim_dram_lcl,
+ &dim_dram_rmt,
+ &dim_pid,
+ &dim_tid,
+ &dim_symbol,
+ &dim_dso,
+ &dim_node,
+ &dim_mean_rmt,
+ &dim_mean_lcl,
+ &dim_mean_load,
+ &dim_cpucnt,
+ &dim_srcline,
+ &dim_dcacheline_idx,
+ &dim_dcacheline_num,
+ &dim_dcacheline_num_empty,
+ NULL,
+};
+
+static void fmt_free(struct perf_hpp_fmt *fmt)
+{
+ struct c2c_fmt *c2c_fmt;
+
+ c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ free(c2c_fmt);
+}
+
+static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
+{
+ struct c2c_fmt *c2c_a = container_of(a, struct c2c_fmt, fmt);
+ struct c2c_fmt *c2c_b = container_of(b, struct c2c_fmt, fmt);
+
+ return c2c_a->dim == c2c_b->dim;
+}
+
+static struct c2c_dimension *get_dimension(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; dimensions[i]; i++) {
+ struct c2c_dimension *dim = dimensions[i];
+
+ if (!strcmp(dim->name, name))
+ return dim;
+ };
+
+ return NULL;
+}
+
+static int c2c_se_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ struct c2c_dimension *dim = c2c_fmt->dim;
+ size_t len = fmt->user_len;
+
+ if (!len) {
+ len = hists__col_len(he->hists, dim->se->se_width_idx);
+
+ if (dim == &dim_symbol || dim == &dim_srcline)
+ len = symbol_width(he->hists, dim->se);
+ }
+
+ return dim->se->se_snprintf(he, hpp->buf, hpp->size, len);
+}
+
+static int64_t c2c_se_cmp(struct perf_hpp_fmt *fmt,
+ struct hist_entry *a, struct hist_entry *b)
+{
+ struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ struct c2c_dimension *dim = c2c_fmt->dim;
+
+ return dim->se->se_cmp(a, b);
+}
+
+static int64_t c2c_se_collapse(struct perf_hpp_fmt *fmt,
+ struct hist_entry *a, struct hist_entry *b)
+{
+ struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+ struct c2c_dimension *dim = c2c_fmt->dim;
+ int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
+
+ collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp;
+ return collapse_fn(a, b);
+}
+
+static struct c2c_fmt *get_format(const char *name)
+{
+ struct c2c_dimension *dim = get_dimension(name);
+ struct c2c_fmt *c2c_fmt;
+ struct perf_hpp_fmt *fmt;
+
+ if (!dim)
+ return NULL;
+
+ c2c_fmt = zalloc(sizeof(*c2c_fmt));
+ if (!c2c_fmt)
+ return NULL;
+
+ c2c_fmt->dim = dim;
+
+ fmt = &c2c_fmt->fmt;
+ INIT_LIST_HEAD(&fmt->list);
+ INIT_LIST_HEAD(&fmt->sort_list);
+
+ fmt->cmp = dim->se ? c2c_se_cmp : dim->cmp;
+ fmt->sort = dim->se ? c2c_se_cmp : dim->cmp;
+ fmt->color = dim->se ? NULL : dim->color;
+ fmt->entry = dim->se ? c2c_se_entry : dim->entry;
+ fmt->header = c2c_header;
+ fmt->width = c2c_width;
+ fmt->collapse = dim->se ? c2c_se_collapse : dim->cmp;
+ fmt->equal = fmt_equal;
+ fmt->free = fmt_free;
+
+ return c2c_fmt;
+}
+
+static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
+{
+ struct c2c_fmt *c2c_fmt = get_format(name);
+
+ if (!c2c_fmt) {
+ reset_dimensions();
+ return output_field_add(hpp_list, name);
+ }
+
+ perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
+ return 0;
+}
+
+static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
+{
+ struct c2c_fmt *c2c_fmt = get_format(name);
+ struct c2c_dimension *dim;
+
+ if (!c2c_fmt) {
+ reset_dimensions();
+ return sort_dimension__add(hpp_list, name, NULL, 0);
+ }
+
+ dim = c2c_fmt->dim;
+ if (dim == &dim_dso)
+ hpp_list->dso = 1;
+
+ perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt);
+ return 0;
+}
+
+#define PARSE_LIST(_list, _fn) \
+ do { \
+ char *tmp, *tok; \
+ ret = 0; \
+ \
+ if (!_list) \
+ break; \
+ \
+ for (tok = strtok_r((char *)_list, ", ", &tmp); \
+ tok; tok = strtok_r(NULL, ", ", &tmp)) { \
+ ret = _fn(hpp_list, tok); \
+ if (ret == -EINVAL) { \
+ error("Invalid --fields key: `%s'", tok); \
+ break; \
+ } else if (ret == -ESRCH) { \
+ error("Unknown --fields key: `%s'", tok); \
+ break; \
+ } \
+ } \
+ } while (0)
+
+static int hpp_list__parse(struct perf_hpp_list *hpp_list,
+ const char *output_,
+ const char *sort_)
+{
+ char *output = output_ ? strdup(output_) : NULL;
+ char *sort = sort_ ? strdup(sort_) : NULL;
+ int ret;
+
+ PARSE_LIST(output, c2c_hists__init_output);
+ PARSE_LIST(sort, c2c_hists__init_sort);
+
+ /* copy sort keys to output fields */
+ perf_hpp__setup_output_field(hpp_list);
+
+ /*
+ * We dont need other sorting keys other than those
+ * we already specified. It also really slows down
+ * the processing a lot with big number of output
+ * fields, so switching this off for c2c.
+ */
+
+#if 0
+ /* and then copy output fields to sort keys */
+ perf_hpp__append_sort_keys(&hists->list);
+#endif
+
+ free(output);
+ free(sort);
+ return ret;
+}
+
+static int c2c_hists__init(struct c2c_hists *hists,
+ const char *sort,
+ int nr_header_lines)
+{
+ __hists__init(&hists->hists, &hists->list);
+
+ /*
+ * Initialize only with sort fields, we need to resort
+ * later anyway, and that's where we add output fields
+ * as well.
+ */
+ perf_hpp_list__init(&hists->list);
+
+ /* Overload number of header lines.*/
+ hists->list.nr_header_lines = nr_header_lines;
+
+ return hpp_list__parse(&hists->list, NULL, sort);
+}
+
+__maybe_unused
+static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
+ const char *output,
+ const char *sort)
+{
+ perf_hpp__reset_output_field(&c2c_hists->list);
+ return hpp_list__parse(&c2c_hists->list, output, sort);
+}
+
+#define DISPLAY_LINE_LIMIT 0.0005
+
+static bool he__display(struct hist_entry *he, struct c2c_stats *stats)
+{
+ struct c2c_hist_entry *c2c_he;
+ double ld_dist;
+
+ if (c2c.show_all)
+ return true;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+#define FILTER_HITM(__h) \
+ if (stats->__h) { \
+ ld_dist = ((double)c2c_he->stats.__h / stats->__h); \
+ if (ld_dist < DISPLAY_LINE_LIMIT) \
+ he->filtered = HIST_FILTER__C2C; \
+ } else { \
+ he->filtered = HIST_FILTER__C2C; \
+ }
+
+ switch (c2c.display) {
+ case DISPLAY_LCL:
+ FILTER_HITM(lcl_hitm);
+ break;
+ case DISPLAY_RMT:
+ FILTER_HITM(rmt_hitm);
+ break;
+ case DISPLAY_TOT:
+ FILTER_HITM(tot_hitm);
+ default:
+ break;
+ };
+
+#undef FILTER_HITM
+
+ return he->filtered == 0;
+}
+
+static inline int valid_hitm_or_store(struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ bool has_hitm;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ has_hitm = c2c.display == DISPLAY_TOT ? c2c_he->stats.tot_hitm :
+ c2c.display == DISPLAY_LCL ? c2c_he->stats.lcl_hitm :
+ c2c_he->stats.rmt_hitm;
+ return has_hitm || c2c_he->stats.store;
+}
+
+static void calc_width(struct hist_entry *he)
+{
+ struct c2c_hists *c2c_hists;
+
+ c2c_hists = container_of(he->hists, struct c2c_hists, hists);
+ hists__calc_col_len(&c2c_hists->hists, he);
+}
+
+static int filter_cb(struct hist_entry *he)
+{
+ if (c2c.show_src && !he->srcline)
+ he->srcline = hist_entry__get_srcline(he);
+
+ calc_width(he);
+
+ if (!valid_hitm_or_store(he))
+ he->filtered = HIST_FILTER__C2C;
+
+ return 0;
+}
+
+static int resort_cl_cb(struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ struct c2c_hists *c2c_hists;
+ bool display = he__display(he, &c2c.hitm_stats);
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ c2c_hists = c2c_he->hists;
+
+ calc_width(he);
+
+ if (display && c2c_hists) {
+ static unsigned int idx;
+
+ c2c_he->cacheline_idx = idx++;
+
+ c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
+
+ hists__collapse_resort(&c2c_hists->hists, NULL);
+ hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
+ }
+
+ return 0;
+}
+
+static void setup_nodes_header(void)
+{
+ dim_node.header = header_node[c2c.node_info];
+}
+
+static int setup_nodes(struct perf_session *session)
+{
+ struct numa_node *n;
+ unsigned long **nodes;
+ int node, cpu;
+ int *cpu2node;
+
+ if (c2c.node_info > 2)
+ c2c.node_info = 2;
+
+ c2c.nodes_cnt = session->header.env.nr_numa_nodes;
+ c2c.cpus_cnt = session->header.env.nr_cpus_online;
+
+ n = session->header.env.numa_nodes;
+ if (!n)
+ return -EINVAL;
+
+ nodes = zalloc(sizeof(unsigned long *) * c2c.nodes_cnt);
+ if (!nodes)
+ return -ENOMEM;
+
+ c2c.nodes = nodes;
+
+ cpu2node = zalloc(sizeof(int) * c2c.cpus_cnt);
+ if (!cpu2node)
+ return -ENOMEM;
+
+ for (cpu = 0; cpu < c2c.cpus_cnt; cpu++)
+ cpu2node[cpu] = -1;
+
+ c2c.cpu2node = cpu2node;
+
+ for (node = 0; node < c2c.nodes_cnt; node++) {
+ struct cpu_map *map = n[node].map;
+ unsigned long *set;
+
+ set = bitmap_alloc(c2c.cpus_cnt);
+ if (!set)
+ return -ENOMEM;
+
+ for (cpu = 0; cpu < map->nr; cpu++) {
+ set_bit(map->map[cpu], set);
+
+ if (WARN_ONCE(cpu2node[map->map[cpu]] != -1, "node/cpu topology bug"))
+ return -EINVAL;
+
+ cpu2node[map->map[cpu]] = node;
+ }
+
+ nodes[node] = set;
+ }
+
+ setup_nodes_header();
+ return 0;
+}
+
+#define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm)
+
+static int resort_hitm_cb(struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+
+ if (HAS_HITMS(c2c_he)) {
+ c2c.shared_clines++;
+ c2c_add_stats(&c2c.hitm_stats, &c2c_he->stats);
+ }
+
+ return 0;
+}
+
+static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
+{
+ struct rb_node *next = rb_first(&hists->entries);
+ int ret = 0;
+
+ while (next) {
+ struct hist_entry *he;
+
+ he = rb_entry(next, struct hist_entry, rb_node);
+ ret = cb(he);
+ if (ret)
+ break;
+ next = rb_next(&he->rb_node);
+ }
+
+ return ret;
+}
+
+static void print_c2c__display_stats(FILE *out)
+{
+ int llc_misses;
+ struct c2c_stats *stats = &c2c.hists.stats;
+
+ llc_misses = stats->lcl_dram +
+ stats->rmt_dram +
+ stats->rmt_hit +
+ stats->rmt_hitm;
+
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Trace Event Information \n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Total records : %10d\n", stats->nr_entries);
+ fprintf(out, " Locked Load/Store Operations : %10d\n", stats->locks);
+ fprintf(out, " Load Operations : %10d\n", stats->load);
+ fprintf(out, " Loads - uncacheable : %10d\n", stats->ld_uncache);
+ fprintf(out, " Loads - IO : %10d\n", stats->ld_io);
+ fprintf(out, " Loads - Miss : %10d\n", stats->ld_miss);
+ fprintf(out, " Loads - no mapping : %10d\n", stats->ld_noadrs);
+ fprintf(out, " Load Fill Buffer Hit : %10d\n", stats->ld_fbhit);
+ fprintf(out, " Load L1D hit : %10d\n", stats->ld_l1hit);
+ fprintf(out, " Load L2D hit : %10d\n", stats->ld_l2hit);
+ fprintf(out, " Load LLC hit : %10d\n", stats->ld_llchit + stats->lcl_hitm);
+ fprintf(out, " Load Local HITM : %10d\n", stats->lcl_hitm);
+ fprintf(out, " Load Remote HITM : %10d\n", stats->rmt_hitm);
+ fprintf(out, " Load Remote HIT : %10d\n", stats->rmt_hit);
+ fprintf(out, " Load Local DRAM : %10d\n", stats->lcl_dram);
+ fprintf(out, " Load Remote DRAM : %10d\n", stats->rmt_dram);
+ fprintf(out, " Load MESI State Exclusive : %10d\n", stats->ld_excl);
+ fprintf(out, " Load MESI State Shared : %10d\n", stats->ld_shared);
+ fprintf(out, " Load LLC Misses : %10d\n", llc_misses);
+ fprintf(out, " LLC Misses to Local DRAM : %10.1f%%\n", ((double)stats->lcl_dram/(double)llc_misses) * 100.);
+ fprintf(out, " LLC Misses to Remote DRAM : %10.1f%%\n", ((double)stats->rmt_dram/(double)llc_misses) * 100.);
+ fprintf(out, " LLC Misses to Remote cache (HIT) : %10.1f%%\n", ((double)stats->rmt_hit /(double)llc_misses) * 100.);
+ fprintf(out, " LLC Misses to Remote cache (HITM) : %10.1f%%\n", ((double)stats->rmt_hitm/(double)llc_misses) * 100.);
+ fprintf(out, " Store Operations : %10d\n", stats->store);
+ fprintf(out, " Store - uncacheable : %10d\n", stats->st_uncache);
+ fprintf(out, " Store - no mapping : %10d\n", stats->st_noadrs);
+ fprintf(out, " Store L1D Hit : %10d\n", stats->st_l1hit);
+ fprintf(out, " Store L1D Miss : %10d\n", stats->st_l1miss);
+ fprintf(out, " No Page Map Rejects : %10d\n", stats->nomap);
+ fprintf(out, " Unable to parse data source : %10d\n", stats->noparse);
+}
+
+static void print_shared_cacheline_info(FILE *out)
+{
+ struct c2c_stats *stats = &c2c.hitm_stats;
+ int hitm_cnt = stats->lcl_hitm + stats->rmt_hitm;
+
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Global Shared Cache Line Event Information \n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Total Shared Cache Lines : %10d\n", c2c.shared_clines);
+ fprintf(out, " Load HITs on shared lines : %10d\n", stats->load);
+ fprintf(out, " Fill Buffer Hits on shared lines : %10d\n", stats->ld_fbhit);
+ fprintf(out, " L1D hits on shared lines : %10d\n", stats->ld_l1hit);
+ fprintf(out, " L2D hits on shared lines : %10d\n", stats->ld_l2hit);
+ fprintf(out, " LLC hits on shared lines : %10d\n", stats->ld_llchit + stats->lcl_hitm);
+ fprintf(out, " Locked Access on shared lines : %10d\n", stats->locks);
+ fprintf(out, " Store HITs on shared lines : %10d\n", stats->store);
+ fprintf(out, " Store L1D hits on shared lines : %10d\n", stats->st_l1hit);
+ fprintf(out, " Total Merged records : %10d\n", hitm_cnt + stats->store);
+}
+
+static void print_cacheline(struct c2c_hists *c2c_hists,
+ struct hist_entry *he_cl,
+ struct perf_hpp_list *hpp_list,
+ FILE *out)
+{
+ char bf[1000];
+ struct perf_hpp hpp = {
+ .buf = bf,
+ .size = 1000,
+ };
+ static bool once;
+
+ if (!once) {
+ hists__fprintf_headers(&c2c_hists->hists, out);
+ once = true;
+ } else {
+ fprintf(out, "\n");
+ }
+
+ fprintf(out, " -------------------------------------------------------------\n");
+ __hist_entry__snprintf(he_cl, &hpp, hpp_list);
+ fprintf(out, "%s\n", bf);
+ fprintf(out, " -------------------------------------------------------------\n");
+
+ hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, true);
+}
+
+static void print_pareto(FILE *out)
+{
+ struct perf_hpp_list hpp_list;
+ struct rb_node *nd;
+ int ret;
+
+ perf_hpp_list__init(&hpp_list);
+ ret = hpp_list__parse(&hpp_list,
+ "cl_num,"
+ "cl_rmt_hitm,"
+ "cl_lcl_hitm,"
+ "cl_stores_l1hit,"
+ "cl_stores_l1miss,"
+ "dcacheline",
+ NULL);
+
+ if (WARN_ONCE(ret, "failed to setup sort entries\n"))
+ return;
+
+ nd = rb_first(&c2c.hists.hists.entries);
+
+ for (; nd; nd = rb_next(nd)) {
+ struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
+ struct c2c_hist_entry *c2c_he;
+
+ if (he->filtered)
+ continue;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ print_cacheline(c2c_he->hists, he, &hpp_list, out);
+ }
+}
+
+static void print_c2c_info(FILE *out, struct perf_session *session)
+{
+ struct perf_evlist *evlist = session->evlist;
+ struct perf_evsel *evsel;
+ bool first = true;
+
+ fprintf(out, "=================================================\n");
+ fprintf(out, " c2c details \n");
+ fprintf(out, "=================================================\n");
+
+ evlist__for_each_entry(evlist, evsel) {
+ fprintf(out, "%-36s: %s\n", first ? " Events" : "",
+ perf_evsel__name(evsel));
+ first = false;
+ }
+ fprintf(out, " Cachelines sort on : %s HITMs\n",
+ display_str[c2c.display]);
+ fprintf(out, " Cacheline data grouping : %s\n", c2c.cl_sort);
+}
+
+static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
+{
+ setup_pager();
+
+ print_c2c__display_stats(out);
+ fprintf(out, "\n");
+ print_shared_cacheline_info(out);
+ fprintf(out, "\n");
+ print_c2c_info(out, session);
+
+ if (c2c.stats_only)
+ return;
+
+ fprintf(out, "\n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Shared Data Cache Line Table \n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, "#\n");
+
+ hists__fprintf(&c2c.hists.hists, true, 0, 0, 0, stdout, false);
+
+ fprintf(out, "\n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, " Shared Cache Line Distribution Pareto \n");
+ fprintf(out, "=================================================\n");
+ fprintf(out, "#\n");
+
+ print_pareto(out);
+}
+
+#ifdef HAVE_SLANG_SUPPORT
+static void c2c_browser__update_nr_entries(struct hist_browser *hb)
+{
+ u64 nr_entries = 0;
+ struct rb_node *nd = rb_first(&hb->hists->entries);
+
+ while (nd) {
+ struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
+
+ if (!he->filtered)
+ nr_entries++;
+
+ nd = rb_next(nd);
+ }
+
+ hb->nr_non_filtered_entries = nr_entries;
+}
+
+struct c2c_cacheline_browser {
+ struct hist_browser hb;
+ struct hist_entry *he;
+};
+
+static int
+perf_c2c_cacheline_browser__title(struct hist_browser *browser,
+ char *bf, size_t size)
+{
+ struct c2c_cacheline_browser *cl_browser;
+ struct hist_entry *he;
+ uint64_t addr = 0;
+
+ cl_browser = container_of(browser, struct c2c_cacheline_browser, hb);
+ he = cl_browser->he;
+
+ if (he->mem_info)
+ addr = cl_address(he->mem_info->daddr.addr);
+
+ scnprintf(bf, size, "Cacheline 0x%lx", addr);
+ return 0;
+}
+
+static struct c2c_cacheline_browser*
+c2c_cacheline_browser__new(struct hists *hists, struct hist_entry *he)
+{
+ struct c2c_cacheline_browser *browser;
+
+ browser = zalloc(sizeof(*browser));
+ if (browser) {
+ hist_browser__init(&browser->hb, hists);
+ browser->hb.c2c_filter = true;
+ browser->hb.title = perf_c2c_cacheline_browser__title;
+ browser->he = he;
+ }
+
+ return browser;
+}
+
+static int perf_c2c__browse_cacheline(struct hist_entry *he)
+{
+ struct c2c_hist_entry *c2c_he;
+ struct c2c_hists *c2c_hists;
+ struct c2c_cacheline_browser *cl_browser;
+ struct hist_browser *browser;
+ int key = -1;
+ const char help[] =
+ " ENTER Togle callchains (if present) \n"
+ " n Togle Node details info \n"
+ " s Togle full lenght of symbol and source line columns \n"
+ " q Return back to cacheline list \n";
+
+ /* Display compact version first. */
+ c2c.symbol_full = false;
+
+ c2c_he = container_of(he, struct c2c_hist_entry, he);
+ c2c_hists = c2c_he->hists;
+
+ cl_browser = c2c_cacheline_browser__new(&c2c_hists->hists, he);
+ if (cl_browser == NULL)
+ return -1;
+
+ browser = &cl_browser->hb;
+
+ /* reset abort key so that it can get Ctrl-C as a key */
+ SLang_reset_tty();
+ SLang_init_tty(0, 0, 0);
+
+ c2c_browser__update_nr_entries(browser);
+
+ while (1) {
+ key = hist_browser__run(browser, "? - help");
+
+ switch (key) {
+ case 's':
+ c2c.symbol_full = !c2c.symbol_full;
+ break;
+ case 'n':
+ c2c.node_info = (c2c.node_info + 1) % 3;
+ setup_nodes_header();
+ break;
+ case 'q':
+ goto out;
+ case '?':
+ ui_browser__help_window(&browser->b, help);
+ break;
+ default:
+ break;
+ }
+ }
+
+out:
+ free(cl_browser);
+ return 0;
+}
+
+static int perf_c2c_browser__title(struct hist_browser *browser,
+ char *bf, size_t size)
+{
+ scnprintf(bf, size,
+ "Shared Data Cache Line Table "
+ "(%lu entries, sorted on %s HITMs)",
+ browser->nr_non_filtered_entries,
+ display_str[c2c.display]);
+ return 0;
+}
+
+static struct hist_browser*
+perf_c2c_browser__new(struct hists *hists)
+{
+ struct hist_browser *browser = hist_browser__new(hists);
+
+ if (browser) {
+ browser->title = perf_c2c_browser__title;
+ browser->c2c_filter = true;
+ }
+
+ return browser;
+}
+
+static int perf_c2c__hists_browse(struct hists *hists)
+{
+ struct hist_browser *browser;
+ int key = -1;
+ const char help[] =
+ " d Display cacheline details \n"
+ " ENTER Togle callchains (if present) \n"
+ " q Quit \n";
+
+ browser = perf_c2c_browser__new(hists);
+ if (browser == NULL)
+ return -1;
+
+ /* reset abort key so that it can get Ctrl-C as a key */
+ SLang_reset_tty();
+ SLang_init_tty(0, 0, 0);
+
+ c2c_browser__update_nr_entries(browser);
+
+ while (1) {
+ key = hist_browser__run(browser, "? - help");
+
+ switch (key) {
+ case 'q':
+ goto out;
+ case 'd':
+ perf_c2c__browse_cacheline(browser->he_selection);
+ break;
+ case '?':
+ ui_browser__help_window(&browser->b, help);
+ break;
+ default:
+ break;
+ }
+ }
+
+out:
+ hist_browser__delete(browser);
+ return 0;
+}
+
+static void perf_c2c_display(struct perf_session *session)
+{
+ if (c2c.use_stdio)
+ perf_c2c__hists_fprintf(stdout, session);
+ else
+ perf_c2c__hists_browse(&c2c.hists.hists);
+}
+#else
+static void perf_c2c_display(struct perf_session *session)
+{
+ use_browser = 0;
+ perf_c2c__hists_fprintf(stdout, session);
+}
+#endif /* HAVE_SLANG_SUPPORT */
+
+static void ui_quirks(void)
+{
+ if (!c2c.use_stdio) {
+ dim_offset.width = 5;
+ dim_offset.header = header_offset_tui;
+ }
+
+ dim_percent_hitm.header = percent_hitm_header[c2c.display];
+}
+
+#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
+
+const char callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
+ CALLCHAIN_REPORT_HELP
+ "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
+
+static int
+parse_callchain_opt(const struct option *opt, const char *arg, int unset)
+{
+ struct callchain_param *callchain = opt->value;
+
+ callchain->enabled = !unset;
+ /*
+ * --no-call-graph
+ */
+ if (unset) {
+ symbol_conf.use_callchain = false;
+ callchain->mode = CHAIN_NONE;
+ return 0;
+ }
+
+ return parse_callchain_report_opt(arg);
+}
+
+static int setup_callchain(struct perf_evlist *evlist)
+{
+ u64 sample_type = perf_evlist__combined_sample_type(evlist);
+ enum perf_call_graph_mode mode = CALLCHAIN_NONE;
+
+ if ((sample_type & PERF_SAMPLE_REGS_USER) &&
+ (sample_type & PERF_SAMPLE_STACK_USER))
+ mode = CALLCHAIN_DWARF;
+ else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
+ mode = CALLCHAIN_LBR;
+ else if (sample_type & PERF_SAMPLE_CALLCHAIN)
+ mode = CALLCHAIN_FP;
+
+ if (!callchain_param.enabled &&
+ callchain_param.mode != CHAIN_NONE &&
+ mode != CALLCHAIN_NONE) {
+ symbol_conf.use_callchain = true;
+ if (callchain_register_param(&callchain_param) < 0) {
+ ui__error("Can't register callchain params.\n");
+ return -EINVAL;
+ }
+ }
+
+ callchain_param.record_mode = mode;
+ callchain_param.min_percent = 0;
+ return 0;
+}
+
+static int setup_display(const char *str)
+{
+ const char *display = str ?: "tot";
+
+ if (!strcmp(display, "tot"))
+ c2c.display = DISPLAY_TOT;
+ else if (!strcmp(display, "rmt"))
+ c2c.display = DISPLAY_RMT;
+ else if (!strcmp(display, "lcl"))
+ c2c.display = DISPLAY_LCL;
+ else {
+ pr_err("failed: unknown display type: %s\n", str);
+ return -1;
+ }
+
+ return 0;
+}
+
+#define for_each_token(__tok, __buf, __sep, __tmp) \
+ for (__tok = strtok_r(__buf, __sep, &__tmp); __tok; \
+ __tok = strtok_r(NULL, __sep, &__tmp))
+
+static int build_cl_output(char *cl_sort, bool no_source)
+{
+ char *tok, *tmp, *buf = strdup(cl_sort);
+ bool add_pid = false;
+ bool add_tid = false;
+ bool add_iaddr = false;
+ bool add_sym = false;
+ bool add_dso = false;
+ bool add_src = false;
+
+ if (!buf)
+ return -ENOMEM;
+
+ for_each_token(tok, buf, ",", tmp) {
+ if (!strcmp(tok, "tid")) {
+ add_tid = true;
+ } else if (!strcmp(tok, "pid")) {
+ add_pid = true;
+ } else if (!strcmp(tok, "iaddr")) {
+ add_iaddr = true;
+ add_sym = true;
+ add_dso = true;
+ add_src = no_source ? false : true;
+ } else if (!strcmp(tok, "dso")) {
+ add_dso = true;
+ } else if (strcmp(tok, "offset")) {
+ pr_err("unrecognized sort token: %s\n", tok);
+ return -EINVAL;
+ }
+ }
+
+ if (asprintf(&c2c.cl_output,
+ "%s%s%s%s%s%s%s%s%s%s",
+ c2c.use_stdio ? "cl_num_empty," : "",
+ "percent_rmt_hitm,"
+ "percent_lcl_hitm,"
+ "percent_stores_l1hit,"
+ "percent_stores_l1miss,"
+ "offset,",
+ add_pid ? "pid," : "",
+ add_tid ? "tid," : "",
+ add_iaddr ? "iaddr," : "",
+ "mean_rmt,"
+ "mean_lcl,"
+ "mean_load,"
+ "cpucnt,",
+ add_sym ? "symbol," : "",
+ add_dso ? "dso," : "",
+ add_src ? "cl_srcline," : "",
+ "node") < 0)
+ return -ENOMEM;
+
+ c2c.show_src = add_src;
+
+ free(buf);
+ return 0;
+}
+
+static int setup_coalesce(const char *coalesce, bool no_source)
+{
+ const char *c = coalesce ?: coalesce_default;
+
+ if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0)
+ return -ENOMEM;
+
+ if (build_cl_output(c2c.cl_sort, no_source))
+ return -1;
+
+ if (asprintf(&c2c.cl_resort, "offset,%s",
+ c2c.display == DISPLAY_TOT ?
+ "tot_hitm" :
+ c2c.display == DISPLAY_RMT ?
+ "rmt_hitm,lcl_hitm" :
+ "lcl_hitm,rmt_hitm") < 0)
+ return -ENOMEM;
+
+ pr_debug("coalesce sort fields: %s\n", c2c.cl_sort);
+ pr_debug("coalesce resort fields: %s\n", c2c.cl_resort);
+ pr_debug("coalesce output fields: %s\n", c2c.cl_output);
+ return 0;
+}
+
+static int perf_c2c__report(int argc, const char **argv)
+{
+ struct perf_session *session;
+ struct ui_progress prog;
+ struct perf_data_file file = {
+ .mode = PERF_DATA_MODE_READ,
+ };
+ char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
+ const char *display = NULL;
+ const char *coalesce = NULL;
+ bool no_source = false;
+ const struct option options[] = {
+ OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
+ "file", "vmlinux pathname"),
+ OPT_STRING('i', "input", &input_name, "file",
+ "the input file to process"),
+ OPT_INCR('N', "node-info", &c2c.node_info,
+ "show extra node info in report (repeat for more info)"),
+#ifdef HAVE_SLANG_SUPPORT
+ OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
+#endif
+ OPT_BOOLEAN(0, "stats", &c2c.stats_only,
+ "Use the stdio interface"),
+ OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
+ "Display full length of symbols"),
+ OPT_BOOLEAN(0, "no-source", &no_source,
+ "Do not display Source Line column"),
+ OPT_BOOLEAN(0, "show-all", &c2c.show_all,
+ "Show all captured HITM lines."),
+ OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
+ "print_type,threshold[,print_limit],order,sort_key[,branch],value",
+ callchain_help, &parse_callchain_opt,
+ callchain_default_opt),
+ OPT_STRING('d', "display", &display, "Switch HITM output type", "lcl,rmt"),
+ OPT_STRING('c', "coalesce", &coalesce, "coalesce fields",
+ "coalesce fields: pid,tid,iaddr,dso"),
+ OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
+ OPT_PARENT(c2c_options),
+ OPT_END()
+ };
+ int err = 0;
+
+ argc = parse_options(argc, argv, options, report_c2c_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ if (argc)
+ usage_with_options(report_c2c_usage, options);
+
+ if (c2c.stats_only)
+ c2c.use_stdio = true;
+
+ if (!input_name || !strlen(input_name))
+ input_name = "perf.data";
+
+ file.path = input_name;
+ file.force = symbol_conf.force;
+
+ err = setup_display(display);
+ if (err)
+ goto out;
+
+ err = setup_coalesce(coalesce, no_source);
+ if (err) {
+ pr_debug("Failed to initialize hists\n");
+ goto out;
+ }
+
+ err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
+ if (err) {
+ pr_debug("Failed to initialize hists\n");
+ goto out;
+ }
+
+ session = perf_session__new(&file, 0, &c2c.tool);
+ if (session == NULL) {
+ pr_debug("No memory for session\n");
+ goto out;
+ }
+
+ err = setup_nodes(session);
+ if (err) {
+ pr_err("Failed setup nodes\n");
+ goto out;
+ }
+
+ err = setup_callchain(session->evlist);
+ if (err)
+ goto out_session;
+
+ if (symbol__init(&session->header.env) < 0)
+ goto out_session;
+
+ /* No pipe support at the moment. */
+ if (perf_data_file__is_pipe(session->file)) {
+ pr_debug("No pipe support at the moment.\n");
+ goto out_session;
+ }
+
+ if (c2c.use_stdio)
+ use_browser = 0;
+ else
+ use_browser = 1;
+
+ setup_browser(false);
+
+ err = perf_session__process_events(session);
+ if (err) {
+ pr_err("failed to process sample\n");
+ goto out_session;
+ }
+
+ c2c_hists__reinit(&c2c.hists,
+ "cl_idx,"
+ "dcacheline,"
+ "tot_recs,"
+ "percent_hitm,"
+ "tot_hitm,lcl_hitm,rmt_hitm,"
+ "stores,stores_l1hit,stores_l1miss,"
+ "dram_lcl,dram_rmt,"
+ "ld_llcmiss,"
+ "tot_loads,"
+ "ld_fbhit,ld_l1hit,ld_l2hit,"
+ "ld_lclhit,ld_rmthit",
+ c2c.display == DISPLAY_TOT ? "tot_hitm" :
+ c2c.display == DISPLAY_LCL ? "lcl_hitm" : "rmt_hitm"
+ );
+
+ ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");
+
+ hists__collapse_resort(&c2c.hists.hists, NULL);
+ hists__output_resort_cb(&c2c.hists.hists, &prog, resort_hitm_cb);
+ hists__iterate_cb(&c2c.hists.hists, resort_cl_cb);
+
+ ui_progress__finish();
+
+ ui_quirks();
+
+ perf_c2c_display(session);
+
+out_session:
+ perf_session__delete(session);
+out:
+ return err;
+}
+
+static int parse_record_events(const struct option *opt __maybe_unused,
+ const char *str, int unset __maybe_unused)
+{
+ bool *event_set = (bool *) opt->value;
+
+ *event_set = true;
+ return perf_mem_events__parse(str);
+}
+
+
+static const char * const __usage_record[] = {
+ "perf c2c record [<options>] [<command>]",
+ "perf c2c record [<options>] -- <command> [<options>]",
+ NULL
+};
+
+static const char * const *record_mem_usage = __usage_record;
+
+static int perf_c2c__record(int argc, const char **argv)
+{
+ int rec_argc, i = 0, j;
+ const char **rec_argv;
+ int ret;
+ bool all_user = false, all_kernel = false;
+ bool event_set = false;
+ struct option options[] = {
+ OPT_CALLBACK('e', "event", &event_set, "event",
+ "event selector. Use 'perf mem record -e list' to list available events",
+ parse_record_events),
+ OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
+ OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
+ OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
+ OPT_PARENT(c2c_options),
+ OPT_END()
+ };
+
+ if (perf_mem_events__init()) {
+ pr_err("failed: memory events not supported\n");
+ return -1;
+ }
+
+ argc = parse_options(argc, argv, options, record_mem_usage,
+ PARSE_OPT_KEEP_UNKNOWN);
+
+ rec_argc = argc + 10; /* max number of arguments */
+ rec_argv = calloc(rec_argc + 1, sizeof(char *));
+ if (!rec_argv)
+ return -1;
+
+ rec_argv[i++] = "record";
+
+ if (!event_set) {
+ perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
+ perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
+ }
+
+ if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
+ rec_argv[i++] = "-W";
+
+ rec_argv[i++] = "-d";
+ rec_argv[i++] = "--sample-cpu";
+
+ for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+ if (!perf_mem_events[j].record)
+ continue;
+
+ if (!perf_mem_events[j].supported) {
+ pr_err("failed: event '%s' not supported\n",
+ perf_mem_events[j].name);
+ return -1;
+ }
+
+ rec_argv[i++] = "-e";
+ rec_argv[i++] = perf_mem_events__name(j);
+ };
+
+ if (all_user)
+ rec_argv[i++] = "--all-user";
+
+ if (all_kernel)
+ rec_argv[i++] = "--all-kernel";
+
+ for (j = 0; j < argc; j++, i++)
+ rec_argv[i] = argv[j];
+
+ if (verbose > 0) {
+ pr_debug("calling: ");
+
+ j = 0;
+
+ while (rec_argv[j]) {
+ pr_debug("%s ", rec_argv[j]);
+ j++;
+ }
+ pr_debug("\n");
+ }
+
+ ret = cmd_record(i, rec_argv, NULL);
+ free(rec_argv);
+ return ret;
+}
+
+int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+ argc = parse_options(argc, argv, c2c_options, c2c_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+
+ if (!argc)
+ usage_with_options(c2c_usage, c2c_options);
+
+ if (!strncmp(argv[0], "rec", 3)) {
+ return perf_c2c__record(argc, argv);
+ } else if (!strncmp(argv[0], "rep", 3)) {
+ return perf_c2c__report(argc, argv);
+ } else {
+ usage_with_options(c2c_usage, c2c_options);
+ }
+
+ return 0;
+}
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index e4207a23b52c..8c0d93b7c2f0 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -17,7 +17,7 @@
static bool use_system_config, use_user_config;
static const char * const config_usage[] = {
- "perf config [<file-option>] [options]",
+ "perf config [<file-option>] [options] [section.name[=value] ...]",
NULL
};
@@ -33,6 +33,73 @@ static struct option config_options[] = {
OPT_END()
};
+static int set_config(struct perf_config_set *set, const char *file_name,
+ const char *var, const char *value)
+{
+ struct perf_config_section *section = NULL;
+ struct perf_config_item *item = NULL;
+ const char *first_line = "# this file is auto-generated.";
+ FILE *fp;
+
+ if (set == NULL)
+ return -1;
+
+ fp = fopen(file_name, "w");
+ if (!fp)
+ return -1;
+
+ perf_config_set__collect(set, file_name, var, value);
+ fprintf(fp, "%s\n", first_line);
+
+ /* overwrite configvariables */
+ perf_config_items__for_each_entry(&set->sections, section) {
+ if (!use_system_config && section->from_system_config)
+ continue;
+ fprintf(fp, "[%s]\n", section->name);
+
+ perf_config_items__for_each_entry(&section->items, item) {
+ if (!use_system_config && section->from_system_config)
+ continue;
+ if (item->value)
+ fprintf(fp, "\t%s = %s\n",
+ item->name, item->value);
+ }
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+static int show_spec_config(struct perf_config_set *set, const char *var)
+{
+ struct perf_config_section *section;
+ struct perf_config_item *item;
+
+ if (set == NULL)
+ return -1;
+
+ perf_config_items__for_each_entry(&set->sections, section) {
+ if (prefixcmp(var, section->name) != 0)
+ continue;
+
+ perf_config_items__for_each_entry(&section->items, item) {
+ const char *name = var + strlen(section->name) + 1;
+
+ if (strcmp(name, item->name) == 0) {
+ char *value = item->value;
+
+ if (value) {
+ printf("%s=%s\n", var, value);
+ return 0;
+ }
+ }
+
+ }
+ }
+
+ return 0;
+}
+
static int show_config(struct perf_config_set *set)
{
struct perf_config_section *section;
@@ -52,9 +119,44 @@ static int show_config(struct perf_config_set *set)
return 0;
}
+static int parse_config_arg(char *arg, char **var, char **value)
+{
+ const char *last_dot = strchr(arg, '.');
+
+ /*
+ * Since "var" actually contains the section name and the real
+ * config variable name separated by a dot, we have to know where the dot is.
+ */
+ if (last_dot == NULL || last_dot == arg) {
+ pr_err("The config variable does not contain a section name: %s\n", arg);
+ return -1;
+ }
+ if (!last_dot[1]) {
+ pr_err("The config variable does not contain a variable name: %s\n", arg);
+ return -1;
+ }
+
+ *value = strchr(arg, '=');
+ if (*value == NULL)
+ *var = arg;
+ else if (!strcmp(*value, "=")) {
+ pr_err("The config variable does not contain a value: %s\n", arg);
+ return -1;
+ } else {
+ *value = *value + 1; /* excluding a first character '=' */
+ *var = strsep(&arg, "=");
+ if (*var[0] == '\0') {
+ pr_err("invalid config variable: %s\n", arg);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
- int ret = 0;
+ int i, ret = 0;
struct perf_config_set *set;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
@@ -100,7 +202,36 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
default:
- usage_with_options(config_usage, config_options);
+ if (argc) {
+ for (i = 0; argv[i]; i++) {
+ char *var, *value;
+ char *arg = strdup(argv[i]);
+
+ if (!arg) {
+ pr_err("%s: strdup failed\n", __func__);
+ ret = -1;
+ break;
+ }
+
+ if (parse_config_arg(arg, &var, &value) < 0) {
+ free(arg);
+ ret = -1;
+ break;
+ }
+
+ if (value == NULL)
+ ret = show_spec_config(set, var);
+ else {
+ const char *config_filename = config_exclusive_filename;
+
+ if (!config_exclusive_filename)
+ config_filename = user_config;
+ ret = set_config(set, config_filename, var, value);
+ }
+ free(arg);
+ }
+ } else
+ usage_with_options(config_usage, config_options);
}
perf_config_set__delete(set);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index d426dcb18ce9..35a02f8e5a4a 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -11,6 +11,7 @@
#include "util/session.h"
#include "util/tool.h"
#include "util/callchain.h"
+#include "util/time-utils.h"
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
@@ -49,6 +50,7 @@ struct alloc_stat {
u64 ptr;
u64 bytes_req;
u64 bytes_alloc;
+ u64 last_alloc;
u32 hit;
u32 pingpong;
@@ -62,9 +64,13 @@ static struct rb_root root_alloc_sorted;
static struct rb_root root_caller_stat;
static struct rb_root root_caller_sorted;
-static unsigned long total_requested, total_allocated;
+static unsigned long total_requested, total_allocated, total_freed;
static unsigned long nr_allocs, nr_cross_allocs;
+/* filters for controlling start and stop of time of analysis */
+static struct perf_time_interval ptime;
+const char *time_str;
+
static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
int bytes_req, int bytes_alloc, int cpu)
{
@@ -105,6 +111,8 @@ static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
}
data->call_site = call_site;
data->alloc_cpu = cpu;
+ data->last_alloc = bytes_alloc;
+
return 0;
}
@@ -223,6 +231,8 @@ static int perf_evsel__process_free_event(struct perf_evsel *evsel,
if (!s_alloc)
return 0;
+ total_freed += s_alloc->last_alloc;
+
if ((short)sample->cpu != s_alloc->alloc_cpu) {
s_alloc->pingpong++;
@@ -907,6 +917,15 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
return 0;
}
+static bool perf_kmem__skip_sample(struct perf_sample *sample)
+{
+ /* skip sample based on time? */
+ if (perf_time__skip_sample(&ptime, sample->time))
+ return true;
+
+ return false;
+}
+
typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
struct perf_sample *sample);
@@ -926,6 +945,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}
+ if (perf_kmem__skip_sample(sample))
+ return 0;
+
dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
if (evsel->handler != NULL) {
@@ -1128,6 +1150,11 @@ static void print_slab_summary(void)
printf("\n========================\n");
printf("Total bytes requested: %'lu\n", total_requested);
printf("Total bytes allocated: %'lu\n", total_allocated);
+ printf("Total bytes freed: %'lu\n", total_freed);
+ if (total_allocated > total_freed) {
+ printf("Net total bytes allocated: %'lu\n",
+ total_allocated - total_freed);
+ }
printf("Total bytes wasted on internal fragmentation: %'lu\n",
total_allocated - total_requested);
printf("Internal fragmentation: %f%%\n",
@@ -1884,6 +1911,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
parse_page_opt),
OPT_BOOLEAN(0, "live", &live_page, "Show live page stat"),
+ OPT_STRING(0, "time", &time_str, "str",
+ "Time span of interest (start,stop)"),
OPT_END()
};
const char *const kmem_subcommands[] = { "record", "stat", NULL };
@@ -1944,6 +1973,11 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
symbol__init(&session->header.env);
+ if (perf_time__parse_str(&ptime, time_str) != 0) {
+ pr_err("Invalid time string\n");
+ return -EINVAL;
+ }
+
if (!strcmp(argv[0], "stat")) {
setlocale(LC_ALL, "");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 67d2a9003294..fa26865364b6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -37,6 +37,7 @@
#include "util/llvm-utils.h"
#include "util/bpf-loader.h"
#include "util/trigger.h"
+#include "util/perf-hooks.h"
#include "asm/bug.h"
#include <unistd.h>
@@ -206,6 +207,12 @@ static void sig_handler(int sig)
done = 1;
}
+static void sigsegv_handler(int sig)
+{
+ perf_hooks__recover();
+ sighandler_dump_stack(sig);
+}
+
static void record__sig_exit(void)
{
if (signr == -1)
@@ -833,6 +840,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
+ signal(SIGSEGV, sigsegv_handler);
if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
signal(SIGUSR2, snapshot_sig_handler);
@@ -970,6 +978,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
trigger_ready(&auxtrace_snapshot_trigger);
trigger_ready(&switch_output_trigger);
+ perf_hooks__invoke_record_start();
for (;;) {
unsigned long long hits = rec->samples;
@@ -1114,6 +1123,8 @@ out_child:
}
}
+ perf_hooks__invoke_record_end();
+
if (!err && !quiet) {
char samples[128];
const char *postfix = rec->timestamp_filename ?
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 6e88460cd13d..d2afbe4a240d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -36,7 +36,7 @@
#include "util/hist.h"
#include "util/data.h"
#include "arch/common.h"
-
+#include "util/time-utils.h"
#include "util/auxtrace.h"
#include <dlfcn.h>
@@ -59,6 +59,8 @@ struct report {
const char *pretty_printing_style;
const char *cpu_list;
const char *symbol_filter_str;
+ const char *time_str;
+ struct perf_time_interval ptime;
float min_percent;
u64 nr_entries;
u64 queue_size;
@@ -158,6 +160,9 @@ static int process_sample_event(struct perf_tool *tool,
};
int ret = 0;
+ if (perf_time__skip_sample(&rep->ptime, sample->time))
+ return 0;
+
if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
@@ -207,11 +212,14 @@ static int process_read_event(struct perf_tool *tool,
if (rep->show_threads) {
const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
- perf_read_values_add_value(&rep->show_threads_values,
+ int err = perf_read_values_add_value(&rep->show_threads_values,
event->read.pid, event->read.tid,
event->read.id,
name,
event->read.value);
+
+ if (err)
+ return err;
}
dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
@@ -539,8 +547,11 @@ static int __cmd_report(struct report *rep)
}
}
- if (rep->show_threads)
- perf_read_values_init(&rep->show_threads_values);
+ if (rep->show_threads) {
+ ret = perf_read_values_init(&rep->show_threads_values);
+ if (ret)
+ return ret;
+ }
ret = report__setup_sample_type(rep);
if (ret) {
@@ -824,6 +835,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
"'always' (default), 'never' or 'auto' only applicable to --stdio mode",
stdio__config_color, "always"),
+ OPT_STRING(0, "time", &report.time_str, "str",
+ "Time span of interest (start,stop)"),
OPT_END()
};
struct perf_data_file file = {
@@ -905,6 +918,9 @@ repeat:
if (itrace_synth_opts.last_branch)
has_br_stack = true;
+ if (has_br_stack && branch_call_mode)
+ symbol_conf.show_branchflag_count = true;
+
/*
* Branch mode is a tristate:
* -1 means default, so decide based on the file having branch data.
@@ -1006,6 +1022,11 @@ repeat:
if (symbol__init(&session->header.env) < 0)
goto error;
+ if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
+ pr_err("Invalid time string\n");
+ return -EINVAL;
+ }
+
sort__setup_elide(stdout);
ret = __cmd_report(&report);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f5503ca22e1c..1a3f1be93372 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -13,12 +13,16 @@
#include "util/cloexec.h"
#include "util/thread_map.h"
#include "util/color.h"
+#include "util/stat.h"
+#include "util/callchain.h"
+#include "util/time-utils.h"
#include <subcmd/parse-options.h>
#include "util/trace-event.h"
#include "util/debug.h"
+#include <linux/log2.h>
#include <sys/prctl.h>
#include <sys/resource.h>
@@ -192,8 +196,45 @@ struct perf_sched {
bool force;
bool skip_merge;
struct perf_sched_map map;
+
+ /* options for timehist command */
+ bool summary;
+ bool summary_only;
+ bool show_callchain;
+ unsigned int max_stack;
+ bool show_cpu_visual;
+ bool show_wakeups;
+ bool show_migrations;
+ u64 skipped_samples;
+ const char *time_str;
+ struct perf_time_interval ptime;
+};
+
+/* per thread run time data */
+struct thread_runtime {
+ u64 last_time; /* time of previous sched in/out event */
+ u64 dt_run; /* run time */
+ u64 dt_wait; /* time between CPU access (off cpu) */
+ u64 dt_delay; /* time between wakeup and sched-in */
+ u64 ready_to_run; /* time of wakeup */
+
+ struct stats run_stats;
+ u64 total_run_time;
+
+ u64 migrations;
+};
+
+/* per event run time data */
+struct evsel_runtime {
+ u64 *last_time; /* time this event was last seen per cpu */
+ u32 ncpu; /* highest cpu slot allocated */
};
+/* track idle times per cpu */
+static struct thread **idle_threads;
+static int idle_max_cpu;
+static char idle_comm[] = "<idle>";
+
static u64 get_nsecs(void)
{
struct timespec ts;
@@ -1191,6 +1232,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
int i;
int ret;
u64 avg;
+ char max_lat_at[32];
if (!work_list->nb_atoms)
return;
@@ -1212,12 +1254,13 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
printf(" ");
avg = work_list->total_lat / work_list->nb_atoms;
+ timestamp__scnprintf_usec(work_list->max_lat_at, max_lat_at, sizeof(max_lat_at));
- printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n",
+ printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13s s\n",
(double)work_list->total_runtime / NSEC_PER_MSEC,
work_list->nb_atoms, (double)avg / NSEC_PER_MSEC,
(double)work_list->max_lat / NSEC_PER_MSEC,
- (double)work_list->max_lat_at / NSEC_PER_SEC);
+ max_lat_at);
}
static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
@@ -1402,6 +1445,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
int cpus_nr;
bool new_cpu = false;
const char *color = PERF_COLOR_NORMAL;
+ char stimestamp[32];
BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);
@@ -1479,7 +1523,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
cpu_color = COLOR_CPUS;
if (cpu != this_cpu)
- color_fprintf(stdout, cpu_color, " ");
+ color_fprintf(stdout, color, " ");
else
color_fprintf(stdout, cpu_color, "*");
@@ -1492,8 +1536,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
goto out;
- color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp / NSEC_PER_SEC);
- if (new_shortname) {
+ timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));
+ color_fprintf(stdout, color, " %12s secs ", stimestamp);
+ if (new_shortname || (verbose && sched_in->tid)) {
const char *pid_color = color;
if (thread__has_color(sched_in))
@@ -1650,6 +1695,988 @@ out_delete:
return rc;
}
+/*
+ * scheduling times are printed as msec.usec
+ */
+static inline void print_sched_time(unsigned long long nsecs, int width)
+{
+ unsigned long msecs;
+ unsigned long usecs;
+
+ msecs = nsecs / NSEC_PER_MSEC;
+ nsecs -= msecs * NSEC_PER_MSEC;
+ usecs = nsecs / NSEC_PER_USEC;
+ printf("%*lu.%03lu ", width, msecs, usecs);
+}
+
+/*
+ * returns runtime data for event, allocating memory for it the
+ * first time it is used.
+ */
+static struct evsel_runtime *perf_evsel__get_runtime(struct perf_evsel *evsel)
+{
+ struct evsel_runtime *r = evsel->priv;
+
+ if (r == NULL) {
+ r = zalloc(sizeof(struct evsel_runtime));
+ evsel->priv = r;
+ }
+
+ return r;
+}
+
+/*
+ * save last time event was seen per cpu
+ */
+static void perf_evsel__save_time(struct perf_evsel *evsel,
+ u64 timestamp, u32 cpu)
+{
+ struct evsel_runtime *r = perf_evsel__get_runtime(evsel);
+
+ if (r == NULL)
+ return;
+
+ if ((cpu >= r->ncpu) || (r->last_time == NULL)) {
+ int i, n = __roundup_pow_of_two(cpu+1);
+ void *p = r->last_time;
+
+ p = realloc(r->last_time, n * sizeof(u64));
+ if (!p)
+ return;
+
+ r->last_time = p;
+ for (i = r->ncpu; i < n; ++i)
+ r->last_time[i] = (u64) 0;
+
+ r->ncpu = n;
+ }
+
+ r->last_time[cpu] = timestamp;
+}
+
+/* returns last time this event was seen on the given cpu */
+static u64 perf_evsel__get_time(struct perf_evsel *evsel, u32 cpu)
+{
+ struct evsel_runtime *r = perf_evsel__get_runtime(evsel);
+
+ if ((r == NULL) || (r->last_time == NULL) || (cpu >= r->ncpu))
+ return 0;
+
+ return r->last_time[cpu];
+}
+
+static int comm_width = 20;
+
+static char *timehist_get_commstr(struct thread *thread)
+{
+ static char str[32];
+ const char *comm = thread__comm_str(thread);
+ pid_t tid = thread->tid;
+ pid_t pid = thread->pid_;
+ int n;
+
+ if (pid == 0)
+ n = scnprintf(str, sizeof(str), "%s", comm);
+
+ else if (tid != pid)
+ n = scnprintf(str, sizeof(str), "%s[%d/%d]", comm, tid, pid);
+
+ else
+ n = scnprintf(str, sizeof(str), "%s[%d]", comm, tid);
+
+ if (n > comm_width)
+ comm_width = n;
+
+ return str;
+}
+
+static void timehist_header(struct perf_sched *sched)
+{
+ u32 ncpus = sched->max_cpu + 1;
+ u32 i, j;
+
+ printf("%15s %6s ", "time", "cpu");
+
+ if (sched->show_cpu_visual) {
+ printf(" ");
+ for (i = 0, j = 0; i < ncpus; ++i) {
+ printf("%x", j++);
+ if (j > 15)
+ j = 0;
+ }
+ printf(" ");
+ }
+
+ printf(" %-20s %9s %9s %9s",
+ "task name", "wait time", "sch delay", "run time");
+
+ printf("\n");
+
+ /*
+ * units row
+ */
+ printf("%15s %-6s ", "", "");
+
+ if (sched->show_cpu_visual)
+ printf(" %*s ", ncpus, "");
+
+ printf(" %-20s %9s %9s %9s\n", "[tid/pid]", "(msec)", "(msec)", "(msec)");
+
+ /*
+ * separator
+ */
+ printf("%.15s %.6s ", graph_dotted_line, graph_dotted_line);
+
+ if (sched->show_cpu_visual)
+ printf(" %.*s ", ncpus, graph_dotted_line);
+
+ printf(" %.20s %.9s %.9s %.9s",
+ graph_dotted_line, graph_dotted_line, graph_dotted_line,
+ graph_dotted_line);
+
+ printf("\n");
+}
+
+static void timehist_print_sample(struct perf_sched *sched,
+ struct perf_sample *sample,
+ struct addr_location *al,
+ struct thread *thread,
+ u64 t)
+{
+ struct thread_runtime *tr = thread__priv(thread);
+ u32 max_cpus = sched->max_cpu + 1;
+ char tstr[64];
+
+ timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
+ printf("%15s [%04d] ", tstr, sample->cpu);
+
+ if (sched->show_cpu_visual) {
+ u32 i;
+ char c;
+
+ printf(" ");
+ for (i = 0; i < max_cpus; ++i) {
+ /* flag idle times with 'i'; others are sched events */
+ if (i == sample->cpu)
+ c = (thread->tid == 0) ? 'i' : 's';
+ else
+ c = ' ';
+ printf("%c", c);
+ }
+ printf(" ");
+ }
+
+ printf(" %-*s ", comm_width, timehist_get_commstr(thread));
+
+ print_sched_time(tr->dt_wait, 6);
+ print_sched_time(tr->dt_delay, 6);
+ print_sched_time(tr->dt_run, 6);
+
+ if (sched->show_wakeups)
+ printf(" %-*s", comm_width, "");
+
+ if (thread->tid == 0)
+ goto out;
+
+ if (sched->show_callchain)
+ printf(" ");
+
+ sample__fprintf_sym(sample, al, 0,
+ EVSEL__PRINT_SYM | EVSEL__PRINT_ONELINE |
+ EVSEL__PRINT_CALLCHAIN_ARROW |
+ EVSEL__PRINT_SKIP_IGNORED,
+ &callchain_cursor, stdout);
+
+out:
+ printf("\n");
+}
+
+/*
+ * Explanation of delta-time stats:
+ *
+ * t = time of current schedule out event
+ * tprev = time of previous sched out event
+ * also time of schedule-in event for current task
+ * last_time = time of last sched change event for current task
+ * (i.e, time process was last scheduled out)
+ * ready_to_run = time of wakeup for current task
+ *
+ * -----|------------|------------|------------|------
+ * last ready tprev t
+ * time to run
+ *
+ * |-------- dt_wait --------|
+ * |- dt_delay -|-- dt_run --|
+ *
+ * dt_run = run time of current task
+ * dt_wait = time between last schedule out event for task and tprev
+ * represents time spent off the cpu
+ * dt_delay = time between wakeup and schedule-in of task
+ */
+
+static void timehist_update_runtime_stats(struct thread_runtime *r,
+ u64 t, u64 tprev)
+{
+ r->dt_delay = 0;
+ r->dt_wait = 0;
+ r->dt_run = 0;
+ if (tprev) {
+ r->dt_run = t - tprev;
+ if (r->ready_to_run) {
+ if (r->ready_to_run > tprev)
+ pr_debug("time travel: wakeup time for task > previous sched_switch event\n");
+ else
+ r->dt_delay = tprev - r->ready_to_run;
+ }
+
+ if (r->last_time > tprev)
+ pr_debug("time travel: last sched out time for task > previous sched_switch event\n");
+ else if (r->last_time)
+ r->dt_wait = tprev - r->last_time;
+ }
+
+ update_stats(&r->run_stats, r->dt_run);
+ r->total_run_time += r->dt_run;
+}
+
+static bool is_idle_sample(struct perf_sched *sched,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
+{
+ struct thread *thread;
+ struct callchain_cursor *cursor = &callchain_cursor;
+
+ /* pid 0 == swapper == idle task */
+ if (sample->pid == 0)
+ return true;
+
+ if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0) {
+ if (perf_evsel__intval(evsel, sample, "prev_pid") == 0)
+ return true;
+ }
+
+ /* want main thread for process - has maps */
+ thread = machine__findnew_thread(machine, sample->pid, sample->pid);
+ if (thread == NULL) {
+ pr_debug("Failed to get thread for pid %d.\n", sample->pid);
+ return false;
+ }
+
+ if (!symbol_conf.use_callchain || sample->callchain == NULL)
+ return false;
+
+ if (thread__resolve_callchain(thread, cursor, evsel, sample,
+ NULL, NULL, sched->max_stack + 2) != 0) {
+ if (verbose)
+ error("Failed to resolve callchain. Skipping\n");
+
+ return false;
+ }
+
+ callchain_cursor_commit(cursor);
+
+ while (true) {
+ struct callchain_cursor_node *node;
+ struct symbol *sym;
+
+ node = callchain_cursor_current(cursor);
+ if (node == NULL)
+ break;
+
+ sym = node->sym;
+ if (sym && sym->name) {
+ if (!strcmp(sym->name, "schedule") ||
+ !strcmp(sym->name, "__schedule") ||
+ !strcmp(sym->name, "preempt_schedule"))
+ sym->ignore = 1;
+ }
+
+ callchain_cursor_advance(cursor);
+ }
+
+ return false;
+}
+
+/*
+ * Track idle stats per cpu by maintaining a local thread
+ * struct for the idle task on each cpu.
+ */
+static int init_idle_threads(int ncpu)
+{
+ int i;
+
+ idle_threads = zalloc(ncpu * sizeof(struct thread *));
+ if (!idle_threads)
+ return -ENOMEM;
+
+ idle_max_cpu = ncpu;
+
+ /* allocate the actual thread struct if needed */
+ for (i = 0; i < ncpu; ++i) {
+ idle_threads[i] = thread__new(0, 0);
+ if (idle_threads[i] == NULL)
+ return -ENOMEM;
+
+ thread__set_comm(idle_threads[i], idle_comm, 0);
+ }
+
+ return 0;
+}
+
+static void free_idle_threads(void)
+{
+ int i;
+
+ if (idle_threads == NULL)
+ return;
+
+ for (i = 0; i < idle_max_cpu; ++i) {
+ if ((idle_threads[i]))
+ thread__delete(idle_threads[i]);
+ }
+
+ free(idle_threads);
+}
+
+static struct thread *get_idle_thread(int cpu)
+{
+ /*
+ * expand/allocate array of pointers to local thread
+ * structs if needed
+ */
+ if ((cpu >= idle_max_cpu) || (idle_threads == NULL)) {
+ int i, j = __roundup_pow_of_two(cpu+1);
+ void *p;
+
+ p = realloc(idle_threads, j * sizeof(struct thread *));
+ if (!p)
+ return NULL;
+
+ idle_threads = (struct thread **) p;
+ for (i = idle_max_cpu; i < j; ++i)
+ idle_threads[i] = NULL;
+
+ idle_max_cpu = j;
+ }
+
+ /* allocate a new thread struct if needed */
+ if (idle_threads[cpu] == NULL) {
+ idle_threads[cpu] = thread__new(0, 0);
+
+ if (idle_threads[cpu]) {
+ idle_threads[cpu]->tid = 0;
+ thread__set_comm(idle_threads[cpu], idle_comm, 0);
+ }
+ }
+
+ return idle_threads[cpu];
+}
+
+/*
+ * handle runtime stats saved per thread
+ */
+static struct thread_runtime *thread__init_runtime(struct thread *thread)
+{
+ struct thread_runtime *r;
+
+ r = zalloc(sizeof(struct thread_runtime));
+ if (!r)
+ return NULL;
+
+ init_stats(&r->run_stats);
+ thread__set_priv(thread, r);
+
+ return r;
+}
+
+static struct thread_runtime *thread__get_runtime(struct thread *thread)
+{
+ struct thread_runtime *tr;
+
+ tr = thread__priv(thread);
+ if (tr == NULL) {
+ tr = thread__init_runtime(thread);
+ if (tr == NULL)
+ pr_debug("Failed to malloc memory for runtime data.\n");
+ }
+
+ return tr;
+}
+
+static struct thread *timehist_get_thread(struct perf_sched *sched,
+ struct perf_sample *sample,
+ struct machine *machine,
+ struct perf_evsel *evsel)
+{
+ struct thread *thread;
+
+ if (is_idle_sample(sched, sample, evsel, machine)) {
+ thread = get_idle_thread(sample->cpu);
+ if (thread == NULL)
+ pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu);
+
+ } else {
+ /* there were samples with tid 0 but non-zero pid */
+ thread = machine__findnew_thread(machine, sample->pid,
+ sample->tid ?: sample->pid);
+ if (thread == NULL) {
+ pr_debug("Failed to get thread for tid %d. skipping sample.\n",
+ sample->tid);
+ }
+ }
+
+ return thread;
+}
+
+static bool timehist_skip_sample(struct perf_sched *sched,
+ struct thread *thread)
+{
+ bool rc = false;
+
+ if (thread__is_filtered(thread)) {
+ rc = true;
+ sched->skipped_samples++;
+ }
+
+ return rc;
+}
+
+static void timehist_print_wakeup_event(struct perf_sched *sched,
+ struct perf_sample *sample,
+ struct machine *machine,
+ struct thread *awakened)
+{
+ struct thread *thread;
+ char tstr[64];
+
+ thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+ if (thread == NULL)
+ return;
+
+ /* show wakeup unless both awakee and awaker are filtered */
+ if (timehist_skip_sample(sched, thread) &&
+ timehist_skip_sample(sched, awakened)) {
+ return;
+ }
+
+ timestamp__scnprintf_usec(sample->time, tstr, sizeof(tstr));
+ printf("%15s [%04d] ", tstr, sample->cpu);
+ if (sched->show_cpu_visual)
+ printf(" %*s ", sched->max_cpu + 1, "");
+
+ printf(" %-*s ", comm_width, timehist_get_commstr(thread));
+
+ /* dt spacer */
+ printf(" %9s %9s %9s ", "", "", "");
+
+ printf("awakened: %s", timehist_get_commstr(awakened));
+
+ printf("\n");
+}
+
+static int timehist_sched_wakeup_event(struct perf_tool *tool,
+ union perf_event *event __maybe_unused,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+ struct thread *thread;
+ struct thread_runtime *tr = NULL;
+ /* want pid of awakened task not pid in sample */
+ const u32 pid = perf_evsel__intval(evsel, sample, "pid");
+
+ thread = machine__findnew_thread(machine, 0, pid);
+ if (thread == NULL)
+ return -1;
+
+ tr = thread__get_runtime(thread);
+ if (tr == NULL)
+ return -1;
+
+ if (tr->ready_to_run == 0)
+ tr->ready_to_run = sample->time;
+
+ /* show wakeups if requested */
+ if (sched->show_wakeups &&
+ !perf_time__skip_sample(&sched->ptime, sample->time))
+ timehist_print_wakeup_event(sched, sample, machine, thread);
+
+ return 0;
+}
+
+static void timehist_print_migration_event(struct perf_sched *sched,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine,
+ struct thread *migrated)
+{
+ struct thread *thread;
+ char tstr[64];
+ u32 max_cpus = sched->max_cpu + 1;
+ u32 ocpu, dcpu;
+
+ if (sched->summary_only)
+ return;
+
+ max_cpus = sched->max_cpu + 1;
+ ocpu = perf_evsel__intval(evsel, sample, "orig_cpu");
+ dcpu = perf_evsel__intval(evsel, sample, "dest_cpu");
+
+ thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+ if (thread == NULL)
+ return;
+
+ if (timehist_skip_sample(sched, thread) &&
+ timehist_skip_sample(sched, migrated)) {
+ return;
+ }
+
+ timestamp__scnprintf_usec(sample->time, tstr, sizeof(tstr));
+ printf("%15s [%04d] ", tstr, sample->cpu);
+
+ if (sched->show_cpu_visual) {
+ u32 i;
+ char c;
+
+ printf(" ");
+ for (i = 0; i < max_cpus; ++i) {
+ c = (i == sample->cpu) ? 'm' : ' ';
+ printf("%c", c);
+ }
+ printf(" ");
+ }
+
+ printf(" %-*s ", comm_width, timehist_get_commstr(thread));
+
+ /* dt spacer */
+ printf(" %9s %9s %9s ", "", "", "");
+
+ printf("migrated: %s", timehist_get_commstr(migrated));
+ printf(" cpu %d => %d", ocpu, dcpu);
+
+ printf("\n");
+}
+
+static int timehist_migrate_task_event(struct perf_tool *tool,
+ union perf_event *event __maybe_unused,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+ struct thread *thread;
+ struct thread_runtime *tr = NULL;
+ /* want pid of migrated task not pid in sample */
+ const u32 pid = perf_evsel__intval(evsel, sample, "pid");
+
+ thread = machine__findnew_thread(machine, 0, pid);
+ if (thread == NULL)
+ return -1;
+
+ tr = thread__get_runtime(thread);
+ if (tr == NULL)
+ return -1;
+
+ tr->migrations++;
+
+ /* show migrations if requested */
+ timehist_print_migration_event(sched, evsel, sample, machine, thread);
+
+ return 0;
+}
+
+static int timehist_sched_change_event(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+ struct perf_time_interval *ptime = &sched->ptime;
+ struct addr_location al;
+ struct thread *thread;
+ struct thread_runtime *tr = NULL;
+ u64 tprev, t = sample->time;
+ int rc = 0;
+
+ if (machine__resolve(machine, &al, sample) < 0) {
+ pr_err("problem processing %d event. skipping it\n",
+ event->header.type);
+ rc = -1;
+ goto out;
+ }
+
+ thread = timehist_get_thread(sched, sample, machine, evsel);
+ if (thread == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ if (timehist_skip_sample(sched, thread))
+ goto out;
+
+ tr = thread__get_runtime(thread);
+ if (tr == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ tprev = perf_evsel__get_time(evsel, sample->cpu);
+
+ /*
+ * If start time given:
+ * - sample time is under window user cares about - skip sample
+ * - tprev is under window user cares about - reset to start of window
+ */
+ if (ptime->start && ptime->start > t)
+ goto out;
+
+ if (ptime->start > tprev)
+ tprev = ptime->start;
+
+ /*
+ * If end time given:
+ * - previous sched event is out of window - we are done
+ * - sample time is beyond window user cares about - reset it
+ * to close out stats for time window interest
+ */
+ if (ptime->end) {
+ if (tprev > ptime->end)
+ goto out;
+
+ if (t > ptime->end)
+ t = ptime->end;
+ }
+
+ timehist_update_runtime_stats(tr, t, tprev);
+
+ if (!sched->summary_only)
+ timehist_print_sample(sched, sample, &al, thread, t);
+
+out:
+ if (tr) {
+ /* time of this sched_switch event becomes last time task seen */
+ tr->last_time = sample->time;
+
+ /* sched out event for task so reset ready to run time */
+ tr->ready_to_run = 0;
+ }
+
+ perf_evsel__save_time(evsel, sample->time, sample->cpu);
+
+ return rc;
+}
+
+static int timehist_sched_switch_event(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine __maybe_unused)
+{
+ return timehist_sched_change_event(tool, event, evsel, sample, machine);
+}
+
+static int process_lost(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine __maybe_unused)
+{
+ char tstr[64];
+
+ timestamp__scnprintf_usec(sample->time, tstr, sizeof(tstr));
+ printf("%15s ", tstr);
+ printf("lost %" PRIu64 " events on cpu %d\n", event->lost.lost, sample->cpu);
+
+ return 0;
+}
+
+
+static void print_thread_runtime(struct thread *t,
+ struct thread_runtime *r)
+{
+ double mean = avg_stats(&r->run_stats);
+ float stddev;
+
+ printf("%*s %5d %9" PRIu64 " ",
+ comm_width, timehist_get_commstr(t), t->ppid,
+ (u64) r->run_stats.n);
+
+ print_sched_time(r->total_run_time, 8);
+ stddev = rel_stddev_stats(stddev_stats(&r->run_stats), mean);
+ print_sched_time(r->run_stats.min, 6);
+ printf(" ");
+ print_sched_time((u64) mean, 6);
+ printf(" ");
+ print_sched_time(r->run_stats.max, 6);
+ printf(" ");
+ printf("%5.2f", stddev);
+ printf(" %5" PRIu64, r->migrations);
+ printf("\n");
+}
+
+struct total_run_stats {
+ u64 sched_count;
+ u64 task_count;
+ u64 total_run_time;
+};
+
+static int __show_thread_runtime(struct thread *t, void *priv)
+{
+ struct total_run_stats *stats = priv;
+ struct thread_runtime *r;
+
+ if (thread__is_filtered(t))
+ return 0;
+
+ r = thread__priv(t);
+ if (r && r->run_stats.n) {
+ stats->task_count++;
+ stats->sched_count += r->run_stats.n;
+ stats->total_run_time += r->total_run_time;
+ print_thread_runtime(t, r);
+ }
+
+ return 0;
+}
+
+static int show_thread_runtime(struct thread *t, void *priv)
+{
+ if (t->dead)
+ return 0;
+
+ return __show_thread_runtime(t, priv);
+}
+
+static int show_deadthread_runtime(struct thread *t, void *priv)
+{
+ if (!t->dead)
+ return 0;
+
+ return __show_thread_runtime(t, priv);
+}
+
+static void timehist_print_summary(struct perf_sched *sched,
+ struct perf_session *session)
+{
+ struct machine *m = &session->machines.host;
+ struct total_run_stats totals;
+ u64 task_count;
+ struct thread *t;
+ struct thread_runtime *r;
+ int i;
+
+ memset(&totals, 0, sizeof(totals));
+
+ if (comm_width < 30)
+ comm_width = 30;
+
+ printf("\nRuntime summary\n");
+ printf("%*s parent sched-in ", comm_width, "comm");
+ printf(" run-time min-run avg-run max-run stddev migrations\n");
+ printf("%*s (count) ", comm_width, "");
+ printf(" (msec) (msec) (msec) (msec) %%\n");
+ printf("%.117s\n", graph_dotted_line);
+
+ machine__for_each_thread(m, show_thread_runtime, &totals);
+ task_count = totals.task_count;
+ if (!task_count)
+ printf("<no still running tasks>\n");
+
+ printf("\nTerminated tasks:\n");
+ machine__for_each_thread(m, show_deadthread_runtime, &totals);
+ if (task_count == totals.task_count)
+ printf("<no terminated tasks>\n");
+
+ /* CPU idle stats not tracked when samples were skipped */
+ if (sched->skipped_samples)
+ return;
+
+ printf("\nIdle stats:\n");
+ for (i = 0; i < idle_max_cpu; ++i) {
+ t = idle_threads[i];
+ if (!t)
+ continue;
+
+ r = thread__priv(t);
+ if (r && r->run_stats.n) {
+ totals.sched_count += r->run_stats.n;
+ printf(" CPU %2d idle for ", i);
+ print_sched_time(r->total_run_time, 6);
+ printf(" msec\n");
+ } else
+ printf(" CPU %2d idle entire time window\n", i);
+ }
+
+ printf("\n"
+ " Total number of unique tasks: %" PRIu64 "\n"
+ "Total number of context switches: %" PRIu64 "\n"
+ " Total run time (msec): ",
+ totals.task_count, totals.sched_count);
+
+ print_sched_time(totals.total_run_time, 2);
+ printf("\n");
+}
+
+typedef int (*sched_handler)(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample,
+ struct machine *machine);
+
+static int perf_timehist__process_sample(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
+{
+ struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+ int err = 0;
+ int this_cpu = sample->cpu;
+
+ if (this_cpu > sched->max_cpu)
+ sched->max_cpu = this_cpu;
+
+ if (evsel->handler != NULL) {
+ sched_handler f = evsel->handler;
+
+ err = f(tool, event, evsel, sample, machine);
+ }
+
+ return err;
+}
+
+static int timehist_check_attr(struct perf_sched *sched,
+ struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+ struct evsel_runtime *er;
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ er = perf_evsel__get_runtime(evsel);
+ if (er == NULL) {
+ pr_err("Failed to allocate memory for evsel runtime data\n");
+ return -1;
+ }
+
+ if (sched->show_callchain &&
+ !(evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN)) {
+ pr_info("Samples do not have callchains.\n");
+ sched->show_callchain = 0;
+ symbol_conf.use_callchain = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int perf_sched__timehist(struct perf_sched *sched)
+{
+ const struct perf_evsel_str_handler handlers[] = {
+ { "sched:sched_switch", timehist_sched_switch_event, },
+ { "sched:sched_wakeup", timehist_sched_wakeup_event, },
+ { "sched:sched_wakeup_new", timehist_sched_wakeup_event, },
+ };
+ const struct perf_evsel_str_handler migrate_handlers[] = {
+ { "sched:sched_migrate_task", timehist_migrate_task_event, },
+ };
+ struct perf_data_file file = {
+ .path = input_name,
+ .mode = PERF_DATA_MODE_READ,
+ .force = sched->force,
+ };
+
+ struct perf_session *session;
+ struct perf_evlist *evlist;
+ int err = -1;
+
+ /*
+ * event handlers for timehist option
+ */
+ sched->tool.sample = perf_timehist__process_sample;
+ sched->tool.mmap = perf_event__process_mmap;
+ sched->tool.comm = perf_event__process_comm;
+ sched->tool.exit = perf_event__process_exit;
+ sched->tool.fork = perf_event__process_fork;
+ sched->tool.lost = process_lost;
+ sched->tool.attr = perf_event__process_attr;
+ sched->tool.tracing_data = perf_event__process_tracing_data;
+ sched->tool.build_id = perf_event__process_build_id;
+
+ sched->tool.ordered_events = true;
+ sched->tool.ordering_requires_timestamps = true;
+
+ symbol_conf.use_callchain = sched->show_callchain;
+
+ session = perf_session__new(&file, false, &sched->tool);
+ if (session == NULL)
+ return -ENOMEM;
+
+ evlist = session->evlist;
+
+ symbol__init(&session->header.env);
+
+ if (perf_time__parse_str(&sched->ptime, sched->time_str) != 0) {
+ pr_err("Invalid time string\n");
+ return -EINVAL;
+ }
+
+ if (timehist_check_attr(sched, evlist) != 0)
+ goto out;
+
+ setup_pager();
+
+ /* setup per-evsel handlers */
+ if (perf_session__set_tracepoints_handlers(session, handlers))
+ goto out;
+
+ /* sched_switch event at a minimum needs to exist */
+ if (!perf_evlist__find_tracepoint_by_name(session->evlist,
+ "sched:sched_switch")) {
+ pr_err("No sched_switch events found. Have you run 'perf sched record'?\n");
+ goto out;
+ }
+
+ if (sched->show_migrations &&
+ perf_session__set_tracepoints_handlers(session, migrate_handlers))
+ goto out;
+
+ /* pre-allocate struct for per-CPU idle stats */
+ sched->max_cpu = session->header.env.nr_cpus_online;
+ if (sched->max_cpu == 0)
+ sched->max_cpu = 4;
+ if (init_idle_threads(sched->max_cpu))
+ goto out;
+
+ /* summary_only implies summary option, but don't overwrite summary if set */
+ if (sched->summary_only)
+ sched->summary = sched->summary_only;
+
+ if (!sched->summary_only)
+ timehist_header(sched);
+
+ err = perf_session__process_events(session);
+ if (err) {
+ pr_err("Failed to process events, error %d", err);
+ goto out;
+ }
+
+ sched->nr_events = evlist->stats.nr_events[0];
+ sched->nr_lost_events = evlist->stats.total_lost;
+ sched->nr_lost_chunks = evlist->stats.nr_events[PERF_RECORD_LOST];
+
+ if (sched->summary)
+ timehist_print_summary(sched, session);
+
+out:
+ free_idle_threads();
+ perf_session__delete(session);
+
+ return err;
+}
+
+
static void print_bad_events(struct perf_sched *sched)
{
if (sched->nr_unordered_timestamps && sched->nr_timestamps) {
@@ -1953,38 +2980,32 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
.next_shortname1 = 'A',
.next_shortname2 = '0',
.skip_merge = 0,
+ .show_callchain = 1,
+ .max_stack = 5,
+ };
+ const struct option sched_options[] = {
+ OPT_STRING('i', "input", &input_name, "file",
+ "input file name"),
+ OPT_INCR('v', "verbose", &verbose,
+ "be more verbose (show symbol address, etc)"),
+ OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
+ "dump raw trace in ASCII"),
+ OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
+ OPT_END()
};
const struct option latency_options[] = {
OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
"sort by key(s): runtime, switch, avg, max"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show symbol address, etc)"),
OPT_INTEGER('C', "CPU", &sched.profile_cpu,
"CPU to profile on"),
- OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
- "dump raw trace in ASCII"),
OPT_BOOLEAN('p', "pids", &sched.skip_merge,
"latency stats per pid instead of per comm"),
- OPT_END()
+ OPT_PARENT(sched_options)
};
const struct option replay_options[] = {
OPT_UINTEGER('r', "repeat", &sched.replay_repeat,
"repeat the workload replay N times (-1: infinite)"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show symbol address, etc)"),
- OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
- "dump raw trace in ASCII"),
- OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
- OPT_END()
- };
- const struct option sched_options[] = {
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show symbol address, etc)"),
- OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
- "dump raw trace in ASCII"),
- OPT_END()
+ OPT_PARENT(sched_options)
};
const struct option map_options[] = {
OPT_BOOLEAN(0, "compact", &sched.map.comp,
@@ -1995,8 +3016,31 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
"highlight given CPUs in map"),
OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus",
"display given CPUs in map"),
- OPT_END()
+ OPT_PARENT(sched_options)
};
+ const struct option timehist_options[] = {
+ OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
+ "file", "vmlinux pathname"),
+ OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
+ "file", "kallsyms pathname"),
+ OPT_BOOLEAN('g', "call-graph", &sched.show_callchain,
+ "Display call chains if present (default on)"),
+ OPT_UINTEGER(0, "max-stack", &sched.max_stack,
+ "Maximum number of functions to display backtrace."),
+ OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
+ "Look for files with symbols relative to this directory"),
+ OPT_BOOLEAN('s', "summary", &sched.summary_only,
+ "Show only syscall summary with statistics"),
+ OPT_BOOLEAN('S', "with-summary", &sched.summary,
+ "Show all syscalls and summary with statistics"),
+ OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"),
+ OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"),
+ OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"),
+ OPT_STRING(0, "time", &sched.time_str, "str",
+ "Time span for analysis (start,stop)"),
+ OPT_PARENT(sched_options)
+ };
+
const char * const latency_usage[] = {
"perf sched latency [<options>]",
NULL
@@ -2009,8 +3053,13 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
"perf sched map [<options>]",
NULL
};
+ const char * const timehist_usage[] = {
+ "perf sched timehist [<options>]",
+ NULL
+ };
const char *const sched_subcommands[] = { "record", "latency", "map",
- "replay", "script", NULL };
+ "replay", "script",
+ "timehist", NULL };
const char *sched_usage[] = {
NULL,
NULL
@@ -2073,6 +3122,21 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
usage_with_options(replay_usage, replay_options);
}
return perf_sched__replay(&sched);
+ } else if (!strcmp(argv[0], "timehist")) {
+ if (argc) {
+ argc = parse_options(argc, argv, timehist_options,
+ timehist_usage, 0);
+ if (argc)
+ usage_with_options(timehist_usage, timehist_options);
+ }
+ if (sched.show_wakeups && sched.summary_only) {
+ pr_err(" Error: -s and -w are mutually exclusive.\n");
+ parse_options_usage(timehist_usage, timehist_options, "s", true);
+ parse_options_usage(NULL, timehist_options, "w", true);
+ return -EINVAL;
+ }
+
+ return perf_sched__timehist(&sched);
} else {
usage_with_options(sched_usage, sched_options);
}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7228d141a789..2f3ff69fc4e7 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -22,6 +22,7 @@
#include "util/thread_map.h"
#include "util/stat.h"
#include "util/thread-stack.h"
+#include "util/time-utils.h"
#include <linux/bitmap.h>
#include <linux/stringify.h>
#include <linux/time64.h>
@@ -66,6 +67,8 @@ enum perf_output_field {
PERF_OUTPUT_WEIGHT = 1U << 18,
PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
PERF_OUTPUT_CALLINDENT = 1U << 20,
+ PERF_OUTPUT_INSN = 1U << 21,
+ PERF_OUTPUT_INSNLEN = 1U << 22,
};
struct output_option {
@@ -93,6 +96,8 @@ struct output_option {
{.str = "weight", .field = PERF_OUTPUT_WEIGHT},
{.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
{.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
+ {.str = "insn", .field = PERF_OUTPUT_INSN},
+ {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
};
/* default set to maintain compatibility with current format */
@@ -437,7 +442,6 @@ static void print_sample_start(struct perf_sample *sample,
{
struct perf_event_attr *attr = &evsel->attr;
unsigned long secs;
- unsigned long usecs;
unsigned long long nsecs;
if (PRINT_FIELD(COMM)) {
@@ -467,11 +471,14 @@ static void print_sample_start(struct perf_sample *sample,
nsecs = sample->time;
secs = nsecs / NSEC_PER_SEC;
nsecs -= secs * NSEC_PER_SEC;
- usecs = nsecs / NSEC_PER_USEC;
+
if (nanosecs)
printf("%5lu.%09llu: ", secs, nsecs);
- else
- printf("%5lu.%06lu: ", secs, usecs);
+ else {
+ char sample_time[32];
+ timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
+ printf("%12s: ", sample_time);
+ }
}
}
@@ -624,6 +631,20 @@ static void print_sample_callindent(struct perf_sample *sample,
printf("%*s", spacing - len, "");
}
+static void print_insn(struct perf_sample *sample,
+ struct perf_event_attr *attr)
+{
+ if (PRINT_FIELD(INSNLEN))
+ printf(" ilen: %d", sample->insn_len);
+ if (PRINT_FIELD(INSN)) {
+ int i;
+
+ printf(" insn:");
+ for (i = 0; i < sample->insn_len; i++)
+ printf(" %02x", (unsigned char)sample->insn[i]);
+ }
+}
+
static void print_sample_bts(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
@@ -668,6 +689,8 @@ static void print_sample_bts(struct perf_sample *sample,
if (print_srcline_last)
map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
+ print_insn(sample, attr);
+
printf("\n");
}
@@ -811,6 +834,8 @@ struct perf_script {
struct cpu_map *cpus;
struct thread_map *threads;
int name_width;
+ const char *time_str;
+ struct perf_time_interval ptime;
};
static int perf_evlist__max_name_len(struct perf_evlist *evlist)
@@ -911,7 +936,7 @@ static void process_event(struct perf_script *script,
if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
print_sample_bpf_output(sample);
-
+ print_insn(sample, attr);
printf("\n");
}
@@ -992,6 +1017,9 @@ static int process_sample_event(struct perf_tool *tool,
struct perf_script *scr = container_of(tool, struct perf_script, tool);
struct addr_location al;
+ if (perf_time__skip_sample(&scr->ptime, sample->time))
+ return 0;
+
if (debug_mode) {
if (sample->time < last_timestamp) {
pr_err("Samples misordered, previous: %" PRIu64
@@ -2124,11 +2152,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
- "bpf-output,callindent", parse_output_fields),
+ "bpf-output,callindent,insn,insnlen", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
"only consider these symbols"),
+ OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
+ "Stop display of callgraph at these symbols"),
OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
"only display events for these comms"),
@@ -2162,7 +2192,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"Enable symbol demangling"),
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
"Enable kernel symbol demangling"),
-
+ OPT_STRING(0, "time", &script.time_str, "str",
+ "Time span of interest (start,stop)"),
OPT_END()
};
const char * const script_subcommands[] = { "record", "report", NULL };
@@ -2441,6 +2472,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
if (err < 0)
goto out_delete;
+ /* needs to be parsed after looking up reference time */
+ if (perf_time__parse_str(&script.ptime, script.time_str) != 0) {
+ pr_err("Invalid time string\n");
+ return -EINVAL;
+ }
+
err = __cmd_script(&script);
flush_scripting();
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fe3af9535e85..3df4178ba378 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -130,7 +130,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err;
}
- err = symbol__disassemble(sym, map, 0);
+ err = symbol__disassemble(sym, map, NULL, 0);
if (err == 0) {
out_assign:
top->sym_filter_entry = he;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c298bd3e1d90..206bf72b77fc 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -74,8 +74,6 @@ struct trace {
size_t nr;
int *entries;
} ev_qualifier_ids;
- struct intlist *tid_list;
- struct intlist *pid_list;
struct {
size_t nr;
pid_t *entries;
@@ -843,7 +841,6 @@ static size_t fprintf_duration(unsigned long t, FILE *fp)
*/
struct thread_trace {
u64 entry_time;
- u64 exit_time;
bool entry_pending;
unsigned long nr_events;
unsigned long pfmaj, pfmin;
@@ -1452,7 +1449,7 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp
duration = sample->time - ttrace->entry_time;
- printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
+ printed = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
ttrace->entry_pending = false;
@@ -1499,7 +1496,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
if (sc->is_exit) {
if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
- trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
+ trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
}
} else {
@@ -1571,8 +1568,6 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
++trace->stats.vfs_getname;
}
- ttrace->exit_time = sample->time;
-
if (ttrace->entry_time) {
duration = sample->time - ttrace->entry_time;
if (trace__filter_duration(trace, duration))
@@ -1592,7 +1587,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
if (trace->summary_only)
goto out;
- trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
+ trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
if (ttrace->entry_pending) {
fprintf(trace->output, "%-70s", ttrace->entry_str);
@@ -1893,18 +1888,6 @@ out_put:
return err;
}
-static bool skip_sample(struct trace *trace, struct perf_sample *sample)
-{
- if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
- (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
- return false;
-
- if (trace->pid_list || trace->tid_list)
- return true;
-
- return false;
-}
-
static void trace__set_base_time(struct trace *trace,
struct perf_evsel *evsel,
struct perf_sample *sample)
@@ -1929,11 +1912,13 @@ static int trace__process_sample(struct perf_tool *tool,
struct machine *machine __maybe_unused)
{
struct trace *trace = container_of(tool, struct trace, tool);
+ struct thread *thread;
int err = 0;
tracepoint_handler handler = evsel->handler;
- if (skip_sample(trace, sample))
+ thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+ if (thread && thread__is_filtered(thread))
return 0;
trace__set_base_time(trace, evsel, sample);
@@ -1946,27 +1931,6 @@ static int trace__process_sample(struct perf_tool *tool,
return err;
}
-static int parse_target_str(struct trace *trace)
-{
- if (trace->opts.target.pid) {
- trace->pid_list = intlist__new(trace->opts.target.pid);
- if (trace->pid_list == NULL) {
- pr_err("Error parsing process id string\n");
- return -EINVAL;
- }
- }
-
- if (trace->opts.target.tid) {
- trace->tid_list = intlist__new(trace->opts.target.tid);
- if (trace->tid_list == NULL) {
- pr_err("Error parsing thread id string\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
static int trace__record(struct trace *trace, int argc, const char **argv)
{
unsigned int rec_argc, i, j;
@@ -2310,12 +2274,17 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (err < 0)
goto out_error_mmap;
- if (!target__none(&trace->opts.target))
+ if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
perf_evlist__enable(evlist);
if (forks)
perf_evlist__start_workload(evlist);
+ if (trace->opts.initial_delay) {
+ usleep(trace->opts.initial_delay * 1000);
+ perf_evlist__enable(evlist);
+ }
+
trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
evlist->threads->nr > 1 ||
perf_evlist__first(evlist)->attr.inherit;
@@ -2458,6 +2427,12 @@ static int trace__replay(struct trace *trace)
if (session == NULL)
return -1;
+ if (trace->opts.target.pid)
+ symbol_conf.pid_list_str = strdup(trace->opts.target.pid);
+
+ if (trace->opts.target.tid)
+ symbol_conf.tid_list_str = strdup(trace->opts.target.tid);
+
if (symbol__init(&session->header.env) < 0)
goto out;
@@ -2501,10 +2476,6 @@ static int trace__replay(struct trace *trace)
evsel->handler = trace__pgfault;
}
- err = parse_target_str(trace);
- if (err != 0)
- goto out;
-
setup_pager();
err = perf_session__process_events(session);
@@ -2816,6 +2787,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
"Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
"per thread proc mmap processing timeout in ms"),
+ OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
+ "ms to wait before starting measurement after program "
+ "start"),
OPT_END()
};
bool __maybe_unused max_stack_user_set = true;
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 41c24010ab43..0bcf68e98ccc 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -18,6 +18,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix);
int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
int cmd_buildid_list(int argc, const char **argv, const char *prefix);
int cmd_config(int argc, const char **argv, const char *prefix);
+int cmd_c2c(int argc, const char **argv, const char *prefix);
int cmd_diff(int argc, const char **argv, const char *prefix);
int cmd_evlist(int argc, const char **argv, const char *prefix);
int cmd_help(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/jvmti/Build b/tools/perf/jvmti/Build
new file mode 100644
index 000000000000..eaeb8cb5379b
--- /dev/null
+++ b/tools/perf/jvmti/Build
@@ -0,0 +1,8 @@
+jvmti-y += libjvmti.o
+jvmti-y += jvmti_agent.o
+
+CFLAGS_jvmti = -fPIC -DPIC -I$(JDIR)/include -I$(JDIR)/include/linux
+CFLAGS_REMOVE_jvmti = -Wmissing-declarations
+CFLAGS_REMOVE_jvmti += -Wstrict-prototypes
+CFLAGS_REMOVE_jvmti += -Wextra
+CFLAGS_REMOVE_jvmti += -Wwrite-strings
diff --git a/tools/perf/jvmti/Makefile b/tools/perf/jvmti/Makefile
deleted file mode 100644
index df14e6b67b63..000000000000
--- a/tools/perf/jvmti/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-ARCH=$(shell uname -m)
-
-ifeq ($(ARCH), x86_64)
-JARCH=amd64
-endif
-ifeq ($(ARCH), armv7l)
-JARCH=armhf
-endif
-ifeq ($(ARCH), armv6l)
-JARCH=armhf
-endif
-ifeq ($(ARCH), aarch64)
-JARCH=aarch64
-endif
-ifeq ($(ARCH), ppc64)
-JARCH=powerpc
-endif
-ifeq ($(ARCH), ppc64le)
-JARCH=powerpc
-endif
-
-DESTDIR=/usr/local
-
-VERSION=1
-REVISION=0
-AGE=0
-
-LN=ln -sf
-RM=rm
-
-SLIBJVMTI=libjvmti.so.$(VERSION).$(REVISION).$(AGE)
-VLIBJVMTI=libjvmti.so.$(VERSION)
-SLDFLAGS=-shared -Wl,-soname -Wl,$(VLIBJVMTI)
-SOLIBEXT=so
-
-# The following works at least on fedora 23, you may need the next
-# line for other distros.
-ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
-JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
-else
- ifneq (,$(wildcard /usr/sbin/alternatives))
- JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
- endif
-endif
-ifndef JDIR
-$(error Could not find alternatives command, you need to set JDIR= to point to the root of your Java directory)
-else
- ifeq (,$(wildcard $(JDIR)/include/jvmti.h))
- $(error the openjdk development package appears to me missing, install and try again)
- endif
-endif
-$(info Using Java from $(JDIR))
-# -lrt required in 32-bit mode for clock_gettime()
-LIBS=-lelf -lrt
-INCDIR=-I $(JDIR)/include -I $(JDIR)/include/linux
-
-TARGETS=$(SLIBJVMTI)
-
-SRCS=libjvmti.c jvmti_agent.c
-OBJS=$(SRCS:.c=.o)
-SOBJS=$(OBJS:.o=.lo)
-OPT=-O2 -g -Werror -Wall
-
-CFLAGS=$(INCDIR) $(OPT)
-
-all: $(TARGETS)
-
-.c.o:
- $(CC) $(CFLAGS) -c $*.c
-.c.lo:
- $(CC) -fPIC -DPIC $(CFLAGS) -c $*.c -o $*.lo
-
-$(OBJS) $(SOBJS): Makefile jvmti_agent.h ../util/jitdump.h
-
-$(SLIBJVMTI): $(SOBJS)
- $(CC) $(CFLAGS) $(SLDFLAGS) -o $@ $(SOBJS) $(LIBS)
- $(LN) $@ libjvmti.$(SOLIBEXT)
-
-clean:
- $(RM) -f *.o *.so.* *.so *.lo
-
-install:
- -mkdir -p $(DESTDIR)/lib
- install -m 755 $(SLIBJVMTI) $(DESTDIR)/lib/
- (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) $(VLIBJVMTI))
- (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) libjvmti.$(SOLIBEXT))
- ldconfig
-
-.SUFFIXES: .c .S .o .lo
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 55daefff0d54..e9651a9d670e 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -44,11 +44,6 @@
static char jit_path[PATH_MAX];
static void *marker_addr;
-/*
- * padding buffer
- */
-static const char pad_bytes[7];
-
static inline pid_t gettid(void)
{
return (pid_t)syscall(__NR_gettid);
@@ -230,7 +225,6 @@ init_arch_timestamp(void)
void *jvmti_open(void)
{
- int pad_cnt;
char dump_path[PATH_MAX];
struct jitheader header;
int fd;
@@ -288,10 +282,6 @@ void *jvmti_open(void)
header.total_size = sizeof(header);
header.pid = getpid();
- /* calculate amount of padding '\0' */
- pad_cnt = PADDING_8ALIGNED(header.total_size);
- header.total_size += pad_cnt;
-
header.timestamp = perf_get_timestamp();
if (use_arch_timestamp)
@@ -301,13 +291,6 @@ void *jvmti_open(void)
warn("jvmti: cannot write dumpfile header");
goto error;
}
-
- /* write padding '\0' if necessary */
- if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, fp)) {
- warn("jvmti: cannot write dumpfile header padding");
- goto error;
- }
-
return fp;
error:
fclose(fp);
@@ -349,7 +332,6 @@ jvmti_write_code(void *agent, char const *sym,
static int code_generation = 1;
struct jr_code_load rec;
size_t sym_len;
- size_t padding_count;
FILE *fp = agent;
int ret = -1;
@@ -366,8 +348,6 @@ jvmti_write_code(void *agent, char const *sym,
rec.p.id = JIT_CODE_LOAD;
rec.p.total_size = sizeof(rec) + sym_len;
- padding_count = PADDING_8ALIGNED(rec.p.total_size);
- rec.p. total_size += padding_count;
rec.p.timestamp = perf_get_timestamp();
rec.code_size = size;
@@ -393,9 +373,6 @@ jvmti_write_code(void *agent, char const *sym,
ret = fwrite_unlocked(&rec, sizeof(rec), 1, fp);
fwrite_unlocked(sym, sym_len, 1, fp);
- if (padding_count)
- fwrite_unlocked(pad_bytes, padding_count, 1, fp);
-
if (code)
fwrite_unlocked(code, size, 1, fp);
@@ -412,7 +389,6 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
{
struct jr_code_debug_info rec;
size_t sret, len, size, flen;
- size_t padding_count;
uint64_t addr;
const char *fn = file;
FILE *fp = agent;
@@ -443,16 +419,10 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
* int : line number
* int : column discriminator
* file[] : source file name
- * padding : pad to multiple of 8 bytes
*/
size += nr_lines * sizeof(struct debug_entry);
size += flen * nr_lines;
- /*
- * pad to 8 bytes
- */
- padding_count = PADDING_8ALIGNED(size);
-
- rec.p.total_size = size + padding_count;
+ rec.p.total_size = size;
/*
* If JVM is multi-threaded, nultiple concurrent calls to agent
@@ -486,12 +456,6 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
if (sret != 1)
goto error;
}
- if (padding_count) {
- sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp);
- if (sret != 1)
- goto error;
- }
-
funlockfile(fp);
return 0;
error:
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c
index ac12e4b91a92..5612641c69b4 100644
--- a/tools/perf/jvmti/libjvmti.c
+++ b/tools/perf/jvmti/libjvmti.c
@@ -12,6 +12,19 @@
static int has_line_numbers;
void *jvmti_agent;
+static void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret)
+{
+ char *err_msg = NULL;
+ jvmtiError err;
+ err = (*jvmti)->GetErrorName(jvmti, ret, &err_msg);
+ if (err == JVMTI_ERROR_NONE) {
+ warnx("%s failed with %s", msg, err_msg);
+ (*jvmti)->Deallocate(jvmti, (unsigned char *)err_msg);
+ } else {
+ warnx("%s failed with an unknown error %d", msg, ret);
+ }
+}
+
static jvmtiError
do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
jvmti_line_info_t *tab, jint *nr)
@@ -22,8 +35,10 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
jvmtiError ret;
ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab);
- if (ret != JVMTI_ERROR_NONE)
+ if (ret != JVMTI_ERROR_NONE) {
+ print_error(jvmti, "GetLineNumberTable", ret);
return ret;
+ }
for (i = 0; i < nr_lines; i++) {
if (loc_tab[i].start_location < bci) {
@@ -71,6 +86,8 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **
/* free what was allocated for nothing */
(*jvmti)->Deallocate(jvmti, (unsigned char *)lne);
nr_total += (int)nr;
+ } else {
+ print_error(jvmti, "GetLineNumberTable", ret);
}
}
}
@@ -130,7 +147,7 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
&decl_class);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: cannot get declaring class");
+ print_error(jvmti, "GetMethodDeclaringClass", ret);
return;
}
@@ -144,21 +161,21 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: cannot get source filename ret=%d", ret);
+ print_error(jvmti, "GetSourceFileName", ret);
goto error;
}
ret = (*jvmti)->GetClassSignature(jvmti, decl_class,
&class_sign, NULL);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: getclassignature failed");
+ print_error(jvmti, "GetClassSignature", ret);
goto error;
}
ret = (*jvmti)->GetMethodName(jvmti, method, &func_name,
&func_sign, NULL);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: failed getmethodname");
+ print_error(jvmti, "GetMethodName", ret);
goto error;
}
@@ -253,7 +270,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: acquire compiled_method capability failed");
+ print_error(jvmti, "AddCapabilities", ret);
return -1;
}
ret = (*jvmti)->GetJLocationFormat(jvmti, &format);
@@ -264,7 +281,9 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
if (ret == JVMTI_ERROR_NONE)
has_line_numbers = 1;
- }
+ } else if (ret != JVMTI_ERROR_NONE)
+ print_error(jvmti, "GetJLocationFormat", ret);
+
memset(&cb, 0, sizeof(cb));
@@ -273,21 +292,21 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb));
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: cannot set event callbacks");
+ print_error(jvmti, "SetEventCallbacks", ret);
return -1;
}
ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: setnotification failed for method_load");
+ print_error(jvmti, "SetEventNotificationMode(METHOD_LOAD)", ret);
return -1;
}
ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
if (ret != JVMTI_ERROR_NONE) {
- warnx("jvmti: setnotification failed on code_generated");
+ print_error(jvmti, "SetEventNotificationMode(CODE_GENERATED)", ret);
return -1;
}
return 0;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 64c06961bfe4..aa23b3347d6b 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -43,6 +43,7 @@ static struct cmd_struct commands[] = {
{ "buildid-cache", cmd_buildid_cache, 0 },
{ "buildid-list", cmd_buildid_list, 0 },
{ "config", cmd_config, 0 },
+ { "c2c", cmd_c2c, 0 },
{ "diff", cmd_diff, 0 },
{ "evlist", cmd_evlist, 0 },
{ "help", cmd_help, 0 },
diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
new file mode 100644
index 000000000000..e925baa0c30b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -0,0 +1,21 @@
+# Format:
+# PVR,Version,JSON/file/pathname,Type
+#
+# where
+# PVR Processor version
+# Version could be used to track version of of JSON file
+# but currently unused.
+# JSON/file/pathname is the path to JSON file, relative
+# to tools/perf/pmu-events/arch/powerpc/.
+# Type is core, uncore etc
+#
+# Multiple PVRs could map to a single JSON file.
+#
+
+# Power8 entries
+004b0000,1,power8.json,core
+004b0201,1,power8.json,core
+004c0000,1,power8.json,core
+004d0000,1,power8.json,core
+004d0100,1,power8.json,core
+004d0200,1,power8.json,core
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/cache.json b/tools/perf/pmu-events/arch/powerpc/power8/cache.json
new file mode 100644
index 000000000000..4a3daa6b4b96
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/cache.json
@@ -0,0 +1,176 @@
+[
+ {,
+ "EventCode": "0x4c048",
+ "EventName": "PM_DATA_FROM_DL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c048",
+ "EventName": "PM_DATA_FROM_DL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c04c",
+ "EventName": "PM_DATA_FROM_DL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c042",
+ "EventName": "PM_DATA_FROM_L2",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x200fe",
+ "EventName": "PM_DATA_FROM_L2MISS",
+ "BriefDescription": "Demand LD - L2 Miss (not L2 hit)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1c04e",
+ "EventName": "PM_DATA_FROM_L2MISS_MOD",
+ "BriefDescription": "The processor's data cache was reloaded from a localtion other than the local core's L2 due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from a localtion other than the local core's L2 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c040",
+ "EventName": "PM_DATA_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x4c040",
+ "EventName": "PM_DATA_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c040",
+ "EventName": "PM_DATA_FROM_L2_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c040",
+ "EventName": "PM_DATA_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x4c042",
+ "EventName": "PM_DATA_FROM_L3",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x300fe",
+ "EventName": "PM_DATA_FROM_L3MISS",
+ "BriefDescription": "Demand LD - L3 Miss (not L2 hit and not L3 hit)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c04e",
+ "EventName": "PM_DATA_FROM_L3MISS_MOD",
+ "BriefDescription": "The processor's data cache was reloaded from a localtion other than the local core's L3 due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from a localtion other than the local core's L3 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c042",
+ "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c042",
+ "EventName": "PM_DATA_FROM_L3_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c044",
+ "EventName": "PM_DATA_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c04c",
+ "EventName": "PM_DATA_FROM_LL4",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x4c04a",
+ "EventName": "PM_DATA_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c048",
+ "EventName": "PM_DATA_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c046",
+ "EventName": "PM_DATA_FROM_RL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c04a",
+ "EventName": "PM_DATA_FROM_RL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3001a",
+ "EventName": "PM_DATA_TABLEWALK_CYC",
+ "BriefDescription": "Tablwalk Cycles (could be 1 or 2 active)",
+ "PublicDescription": "Data Tablewalk Active"
+ },
+ {,
+ "EventCode": "0x4e04e",
+ "EventName": "PM_DPTEG_FROM_L3MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L3 due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd094",
+ "EventName": "PM_DSLB_MISS",
+ "BriefDescription": "Data SLB Miss - Total of all segment sizes",
+ "PublicDescription": "Data SLB Miss - Total of all segment sizesData SLB misses"
+ },
+ {,
+ "EventCode": "0x1002c",
+ "EventName": "PM_L1_DCACHE_RELOADED_ALL",
+ "BriefDescription": "L1 data cache reloaded for demand or prefetch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x300f6",
+ "EventName": "PM_L1_DCACHE_RELOAD_VALID",
+ "BriefDescription": "DL1 reloaded due to Demand Load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e054",
+ "EventName": "PM_LD_MISS_L1",
+ "BriefDescription": "Load Missed L1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x100ee",
+ "EventName": "PM_LD_REF_L1",
+ "BriefDescription": "All L1 D cache load references counted at finish, gated by reject",
+ "PublicDescription": "Load Ref count combined for all units"
+ },
+ {,
+ "EventCode": "0x300f0",
+ "EventName": "PM_ST_MISS_L1",
+ "BriefDescription": "Store Missed L1",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/floating-point.json b/tools/perf/pmu-events/arch/powerpc/power8/floating-point.json
new file mode 100644
index 000000000000..5f1bb9fca40c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/floating-point.json
@@ -0,0 +1,14 @@
+[
+ {,
+ "EventCode": "0x2000e",
+ "EventName": "PM_FXU_BUSY",
+ "BriefDescription": "fxu0 busy and fxu1 busy",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1000e",
+ "EventName": "PM_FXU_IDLE",
+ "BriefDescription": "fxu0 idle and fxu1 idle",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/frontend.json b/tools/perf/pmu-events/arch/powerpc/power8/frontend.json
new file mode 100644
index 000000000000..04c5f1b7bee1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/frontend.json
@@ -0,0 +1,470 @@
+[
+ {,
+ "EventCode": "0x2505e",
+ "EventName": "PM_BACK_BR_CMPL",
+ "BriefDescription": "Branch instruction completed with a target address less than current instruction address",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10068",
+ "EventName": "PM_BRU_FIN",
+ "BriefDescription": "Branch Instruction Finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20036",
+ "EventName": "PM_BR_2PATH",
+ "BriefDescription": "two path branch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40060",
+ "EventName": "PM_BR_CMPL",
+ "BriefDescription": "Branch Instruction completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x400f6",
+ "EventName": "PM_BR_MPRED_CMPL",
+ "BriefDescription": "Number of Branch Mispredicts",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200fa",
+ "EventName": "PM_BR_TAKEN_CMPL",
+ "BriefDescription": "New event for Branch Taken",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10018",
+ "EventName": "PM_IC_DEMAND_CYC",
+ "BriefDescription": "Cycles when a demand ifetch was pending",
+ "PublicDescription": "Demand ifetch pending"
+ },
+ {,
+ "EventCode": "0x100f6",
+ "EventName": "PM_IERAT_RELOAD",
+ "BriefDescription": "Number of I-ERAT reloads",
+ "PublicDescription": "IERAT Reloaded (Miss)"
+ },
+ {,
+ "EventCode": "0x4006a",
+ "EventName": "PM_IERAT_RELOAD_16M",
+ "BriefDescription": "IERAT Reloaded (Miss) for a 16M page",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20064",
+ "EventName": "PM_IERAT_RELOAD_4K",
+ "BriefDescription": "IERAT Miss (Not implemented as DI on POWER6)",
+ "PublicDescription": "IERAT Reloaded (Miss) for a 4k page"
+ },
+ {,
+ "EventCode": "0x3006a",
+ "EventName": "PM_IERAT_RELOAD_64K",
+ "BriefDescription": "IERAT Reloaded (Miss) for a 64k page",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x14050",
+ "EventName": "PM_INST_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for an instruction fetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x2",
+ "EventName": "PM_INST_CMPL",
+ "BriefDescription": "Number of PowerPC Instructions that completed",
+ "PublicDescription": "PPC Instructions Finished (completed)"
+ },
+ {,
+ "EventCode": "0x200f2",
+ "EventName": "PM_INST_DISP",
+ "BriefDescription": "PPC Dispatched",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44048",
+ "EventName": "PM_INST_FROM_DL2L3_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x34048",
+ "EventName": "PM_INST_FROM_DL2L3_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x3404c",
+ "EventName": "PM_INST_FROM_DL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x4404c",
+ "EventName": "PM_INST_FROM_DMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group (Distant) due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group (Distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x14042",
+ "EventName": "PM_INST_FROM_L2",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x1404e",
+ "EventName": "PM_INST_FROM_L2MISS",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L2 due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L2 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x34040",
+ "EventName": "PM_INST_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with load hit store conflict due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 with load hit store conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x44040",
+ "EventName": "PM_INST_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with dispatch conflict due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 with dispatch conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24040",
+ "EventName": "PM_INST_FROM_L2_MEPF",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x14040",
+ "EventName": "PM_INST_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 without conflict due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 without conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x44042",
+ "EventName": "PM_INST_FROM_L3",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x300fa",
+ "EventName": "PM_INST_FROM_L3MISS",
+ "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet",
+ "PublicDescription": "Inst from L3 miss"
+ },
+ {,
+ "EventCode": "0x4404e",
+ "EventName": "PM_INST_FROM_L3MISS_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L3 due to a instruction fetch",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L3 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x34042",
+ "EventName": "PM_INST_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 with dispatch conflict due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 with dispatch conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24042",
+ "EventName": "PM_INST_FROM_L3_MEPF",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x14044",
+ "EventName": "PM_INST_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without conflict due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 without conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x1404c",
+ "EventName": "PM_INST_FROM_LL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's L4 cache due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from the local chip's L4 cache due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24048",
+ "EventName": "PM_INST_FROM_LMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's Memory due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from the local chip's Memory due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x2404c",
+ "EventName": "PM_INST_FROM_MEMORY",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x4404a",
+ "EventName": "PM_INST_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x14048",
+ "EventName": "PM_INST_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24046",
+ "EventName": "PM_INST_FROM_RL2L3_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x1404a",
+ "EventName": "PM_INST_FROM_RL2L3_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x2404a",
+ "EventName": "PM_INST_FROM_RL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x3404a",
+ "EventName": "PM_INST_FROM_RMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24050",
+ "EventName": "PM_INST_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for an instruction fetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x24052",
+ "EventName": "PM_INST_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for an instruction fetch",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x14052",
+ "EventName": "PM_INST_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x1003a",
+ "EventName": "PM_INST_IMC_MATCH_CMPL",
+ "BriefDescription": "IMC Match Count ( Not architected in P8)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x14054",
+ "EventName": "PM_INST_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for an instruction fetch",
+ "PublicDescription": "Pump prediction correct. Counts across all types of pumpsfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x44052",
+ "EventName": "PM_INST_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for an instruction fetch",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x34050",
+ "EventName": "PM_INST_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for an instruction fetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x34052",
+ "EventName": "PM_INST_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for an instruction fetch",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x44050",
+ "EventName": "PM_INST_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for an instruction fetch",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x45048",
+ "EventName": "PM_IPTEG_FROM_DL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x35048",
+ "EventName": "PM_IPTEG_FROM_DL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3504c",
+ "EventName": "PM_IPTEG_FROM_DL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4504c",
+ "EventName": "PM_IPTEG_FROM_DMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15042",
+ "EventName": "PM_IPTEG_FROM_L2",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1504e",
+ "EventName": "PM_IPTEG_FROM_L2MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L2 due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x25040",
+ "EventName": "PM_IPTEG_FROM_L2_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15040",
+ "EventName": "PM_IPTEG_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x45042",
+ "EventName": "PM_IPTEG_FROM_L3",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4504e",
+ "EventName": "PM_IPTEG_FROM_L3MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L3 due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x35042",
+ "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x25042",
+ "EventName": "PM_IPTEG_FROM_L3_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15044",
+ "EventName": "PM_IPTEG_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1504c",
+ "EventName": "PM_IPTEG_FROM_LL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x25048",
+ "EventName": "PM_IPTEG_FROM_LMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2504c",
+ "EventName": "PM_IPTEG_FROM_MEMORY",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4504a",
+ "EventName": "PM_IPTEG_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15048",
+ "EventName": "PM_IPTEG_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x25046",
+ "EventName": "PM_IPTEG_FROM_RL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1504a",
+ "EventName": "PM_IPTEG_FROM_RL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2504a",
+ "EventName": "PM_IPTEG_FROM_RL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3504a",
+ "EventName": "PM_IPTEG_FROM_RMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd096",
+ "EventName": "PM_ISLB_MISS",
+ "BriefDescription": "I SLB Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x400fc",
+ "EventName": "PM_ITLB_MISS",
+ "BriefDescription": "ITLB Reloaded (always zero on POWER6)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200fd",
+ "EventName": "PM_L1_ICACHE_MISS",
+ "BriefDescription": "Demand iCache Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40012",
+ "EventName": "PM_L1_ICACHE_RELOADED_ALL",
+ "BriefDescription": "Counts all Icache reloads includes demand, prefetchm prefetch turned into demand and demand turned into prefetch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30068",
+ "EventName": "PM_L1_ICACHE_RELOADED_PREF",
+ "BriefDescription": "Counts all Icache prefetch reloads ( includes demand turned into prefetch)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x300f4",
+ "EventName": "PM_THRD_CONC_RUN_INST",
+ "BriefDescription": "PPC Instructions Finished when both threads in run_cycles",
+ "PublicDescription": "Concurrent Run Instructions"
+ },
+ {,
+ "EventCode": "0x30060",
+ "EventName": "PM_TM_TRANS_RUN_INST",
+ "BriefDescription": "Instructions completed in transactional state",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e014",
+ "EventName": "PM_TM_TX_PASS_RUN_INST",
+ "BriefDescription": "run instructions spent in successful transactions",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/marked.json b/tools/perf/pmu-events/arch/powerpc/power8/marked.json
new file mode 100644
index 000000000000..dcdcede3c3fe
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/marked.json
@@ -0,0 +1,794 @@
+[
+ {,
+ "EventCode": "0x3515e",
+ "EventName": "PM_MRK_BACK_BR_CMPL",
+ "BriefDescription": "Marked branch instruction completed with a target address less than current instruction address",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2013a",
+ "EventName": "PM_MRK_BRU_FIN",
+ "BriefDescription": "bru marked instr finish",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1016e",
+ "EventName": "PM_MRK_BR_CMPL",
+ "BriefDescription": "Branch Instruction completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x301e4",
+ "EventName": "PM_MRK_BR_MPRED_CMPL",
+ "BriefDescription": "Marked Branch Mispredicted",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x101e2",
+ "EventName": "PM_MRK_BR_TAKEN_CMPL",
+ "BriefDescription": "Marked Branch Taken completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d148",
+ "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d128",
+ "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD_CYC",
+ "BriefDescription": "Duration in cycles to reload with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d148",
+ "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c128",
+ "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR_CYC",
+ "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d14c",
+ "EventName": "PM_MRK_DATA_FROM_DL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c12c",
+ "EventName": "PM_MRK_DATA_FROM_DL4_CYC",
+ "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d14c",
+ "EventName": "PM_MRK_DATA_FROM_DMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d12c",
+ "EventName": "PM_MRK_DATA_FROM_DMEM_CYC",
+ "BriefDescription": "Duration in cycles to reload from another chip's memory on the same Node or Group (Distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d142",
+ "EventName": "PM_MRK_DATA_FROM_L2",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d14e",
+ "EventName": "PM_MRK_DATA_FROM_L2MISS",
+ "BriefDescription": "Data cache reload L2 miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c12e",
+ "EventName": "PM_MRK_DATA_FROM_L2MISS_CYC",
+ "BriefDescription": "Duration in cycles to reload from a localtion other than the local core's L2 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c122",
+ "EventName": "PM_MRK_DATA_FROM_L2_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L2 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d140",
+ "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c120",
+ "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_LDHITST_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L2 with load hit store conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d140",
+ "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d120",
+ "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_OTHER_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L2 with dispatch conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d140",
+ "EventName": "PM_MRK_DATA_FROM_L2_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d120",
+ "EventName": "PM_MRK_DATA_FROM_L2_MEPF_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d140",
+ "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c120",
+ "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L2 without conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d142",
+ "EventName": "PM_MRK_DATA_FROM_L3",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x201e4",
+ "EventName": "PM_MRK_DATA_FROM_L3MISS",
+ "BriefDescription": "The processor's data cache was reloaded from a localtion other than the local core's L3 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d12e",
+ "EventName": "PM_MRK_DATA_FROM_L3MISS_CYC",
+ "BriefDescription": "Duration in cycles to reload from a localtion other than the local core's L3 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d122",
+ "EventName": "PM_MRK_DATA_FROM_L3_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L3 due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d142",
+ "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c122",
+ "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L3 with dispatch conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d142",
+ "EventName": "PM_MRK_DATA_FROM_L3_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d122",
+ "EventName": "PM_MRK_DATA_FROM_L3_MEPF_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d144",
+ "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c124",
+ "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT_CYC",
+ "BriefDescription": "Duration in cycles to reload from local core's L3 without conflict due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d14c",
+ "EventName": "PM_MRK_DATA_FROM_LL4",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c12c",
+ "EventName": "PM_MRK_DATA_FROM_LL4_CYC",
+ "BriefDescription": "Duration in cycles to reload from the local chip's L4 cache due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d148",
+ "EventName": "PM_MRK_DATA_FROM_LMEM",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's Memory due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d128",
+ "EventName": "PM_MRK_DATA_FROM_LMEM_CYC",
+ "BriefDescription": "Duration in cycles to reload from the local chip's Memory due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d14c",
+ "EventName": "PM_MRK_DATA_FROM_MEMORY",
+ "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d12c",
+ "EventName": "PM_MRK_DATA_FROM_MEMORY_CYC",
+ "BriefDescription": "Duration in cycles to reload from a memory location including L4 from local remote or distant due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d14a",
+ "EventName": "PM_MRK_DATA_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d12a",
+ "EventName": "PM_MRK_DATA_FROM_OFF_CHIP_CACHE_CYC",
+ "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d148",
+ "EventName": "PM_MRK_DATA_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c128",
+ "EventName": "PM_MRK_DATA_FROM_ON_CHIP_CACHE_CYC",
+ "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d146",
+ "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d126",
+ "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD_CYC",
+ "BriefDescription": "Duration in cycles to reload with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d14a",
+ "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c12a",
+ "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR_CYC",
+ "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d14a",
+ "EventName": "PM_MRK_DATA_FROM_RL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d12a",
+ "EventName": "PM_MRK_DATA_FROM_RL4_CYC",
+ "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d14a",
+ "EventName": "PM_MRK_DATA_FROM_RMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c12a",
+ "EventName": "PM_MRK_DATA_FROM_RMEM_CYC",
+ "BriefDescription": "Duration in cycles to reload from another chip's memory on the same Node or Group ( Remote) due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40118",
+ "EventName": "PM_MRK_DCACHE_RELOAD_INTV",
+ "BriefDescription": "Combined Intervention event",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x301e6",
+ "EventName": "PM_MRK_DERAT_MISS",
+ "BriefDescription": "Erat Miss (TLB Access) All page sizes",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d154",
+ "EventName": "PM_MRK_DERAT_MISS_16G",
+ "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d154",
+ "EventName": "PM_MRK_DERAT_MISS_16M",
+ "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d156",
+ "EventName": "PM_MRK_DERAT_MISS_4K",
+ "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 4K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d154",
+ "EventName": "PM_MRK_DERAT_MISS_64K",
+ "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 64K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20132",
+ "EventName": "PM_MRK_DFU_FIN",
+ "BriefDescription": "Decimal Unit marked Instruction Finish",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f148",
+ "EventName": "PM_MRK_DPTEG_FROM_DL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f148",
+ "EventName": "PM_MRK_DPTEG_FROM_DL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f14c",
+ "EventName": "PM_MRK_DPTEG_FROM_DL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f14c",
+ "EventName": "PM_MRK_DPTEG_FROM_DMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f142",
+ "EventName": "PM_MRK_DPTEG_FROM_L2",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f14e",
+ "EventName": "PM_MRK_DPTEG_FROM_L2MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L2 due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f140",
+ "EventName": "PM_MRK_DPTEG_FROM_L2_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f140",
+ "EventName": "PM_MRK_DPTEG_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f142",
+ "EventName": "PM_MRK_DPTEG_FROM_L3",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f14e",
+ "EventName": "PM_MRK_DPTEG_FROM_L3MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L3 due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f142",
+ "EventName": "PM_MRK_DPTEG_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f142",
+ "EventName": "PM_MRK_DPTEG_FROM_L3_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f144",
+ "EventName": "PM_MRK_DPTEG_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f14c",
+ "EventName": "PM_MRK_DPTEG_FROM_LL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f148",
+ "EventName": "PM_MRK_DPTEG_FROM_LMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f14c",
+ "EventName": "PM_MRK_DPTEG_FROM_MEMORY",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f14a",
+ "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f148",
+ "EventName": "PM_MRK_DPTEG_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f146",
+ "EventName": "PM_MRK_DPTEG_FROM_RL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f14a",
+ "EventName": "PM_MRK_DPTEG_FROM_RL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f14a",
+ "EventName": "PM_MRK_DPTEG_FROM_RL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f14a",
+ "EventName": "PM_MRK_DPTEG_FROM_RMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x401e4",
+ "EventName": "PM_MRK_DTLB_MISS",
+ "BriefDescription": "Marked dtlb miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d158",
+ "EventName": "PM_MRK_DTLB_MISS_16G",
+ "BriefDescription": "Marked Data TLB Miss page size 16G",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d156",
+ "EventName": "PM_MRK_DTLB_MISS_16M",
+ "BriefDescription": "Marked Data TLB Miss page size 16M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d156",
+ "EventName": "PM_MRK_DTLB_MISS_4K",
+ "BriefDescription": "Marked Data TLB Miss page size 4k",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d156",
+ "EventName": "PM_MRK_DTLB_MISS_64K",
+ "BriefDescription": "Marked Data TLB Miss page size 64K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40154",
+ "EventName": "PM_MRK_FAB_RSP_BKILL",
+ "BriefDescription": "Marked store had to do a bkill",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f150",
+ "EventName": "PM_MRK_FAB_RSP_BKILL_CYC",
+ "BriefDescription": "cycles L2 RC took for a bkill",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3015e",
+ "EventName": "PM_MRK_FAB_RSP_CLAIM_RTY",
+ "BriefDescription": "Sampled store did a rwitm and got a rty",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30154",
+ "EventName": "PM_MRK_FAB_RSP_DCLAIM",
+ "BriefDescription": "Marked store had to do a dclaim",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f152",
+ "EventName": "PM_MRK_FAB_RSP_DCLAIM_CYC",
+ "BriefDescription": "cycles L2 RC took for a dclaim",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4015e",
+ "EventName": "PM_MRK_FAB_RSP_RD_RTY",
+ "BriefDescription": "Sampled L2 reads retry count",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1015e",
+ "EventName": "PM_MRK_FAB_RSP_RD_T_INTV",
+ "BriefDescription": "Sampled Read got a T intervention",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f150",
+ "EventName": "PM_MRK_FAB_RSP_RWITM_CYC",
+ "BriefDescription": "cycles L2 RC took for a rwitm",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2015e",
+ "EventName": "PM_MRK_FAB_RSP_RWITM_RTY",
+ "BriefDescription": "Sampled store did a rwitm and got a rty",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20134",
+ "EventName": "PM_MRK_FXU_FIN",
+ "BriefDescription": "fxu marked instr finish",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x401e0",
+ "EventName": "PM_MRK_INST_CMPL",
+ "BriefDescription": "marked instruction completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20130",
+ "EventName": "PM_MRK_INST_DECODED",
+ "BriefDescription": "marked instruction decoded",
+ "PublicDescription": "marked instruction decoded. Name from ISU?"
+ },
+ {,
+ "EventCode": "0x101e0",
+ "EventName": "PM_MRK_INST_DISP",
+ "BriefDescription": "The thread has dispatched a randomly sampled marked instruction",
+ "PublicDescription": "Marked Instruction dispatched"
+ },
+ {,
+ "EventCode": "0x30130",
+ "EventName": "PM_MRK_INST_FIN",
+ "BriefDescription": "marked instruction finished",
+ "PublicDescription": "marked instr finish any unit"
+ },
+ {,
+ "EventCode": "0x401e6",
+ "EventName": "PM_MRK_INST_FROM_L3MISS",
+ "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet",
+ "PublicDescription": "n/a"
+ },
+ {,
+ "EventCode": "0x10132",
+ "EventName": "PM_MRK_INST_ISSUED",
+ "BriefDescription": "Marked instruction issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40134",
+ "EventName": "PM_MRK_INST_TIMEO",
+ "BriefDescription": "marked Instruction finish timeout (instruction lost)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x101e4",
+ "EventName": "PM_MRK_L1_ICACHE_MISS",
+ "BriefDescription": "sampled Instruction suffered an icache Miss",
+ "PublicDescription": "Marked L1 Icache Miss"
+ },
+ {,
+ "EventCode": "0x101ea",
+ "EventName": "PM_MRK_L1_RELOAD_VALID",
+ "BriefDescription": "Marked demand reload",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20114",
+ "EventName": "PM_MRK_L2_RC_DISP",
+ "BriefDescription": "Marked Instruction RC dispatched in L2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3012a",
+ "EventName": "PM_MRK_L2_RC_DONE",
+ "BriefDescription": "Marked RC done",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40116",
+ "EventName": "PM_MRK_LARX_FIN",
+ "BriefDescription": "Larx finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1013e",
+ "EventName": "PM_MRK_LD_MISS_EXPOSED_CYC",
+ "BriefDescription": "Marked Load exposed Miss cycles",
+ "PublicDescription": "Marked Load exposed Miss (use edge detect to count #)"
+ },
+ {,
+ "EventCode": "0x201e2",
+ "EventName": "PM_MRK_LD_MISS_L1",
+ "BriefDescription": "Marked DL1 Demand Miss counted at exec time",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4013e",
+ "EventName": "PM_MRK_LD_MISS_L1_CYC",
+ "BriefDescription": "Marked ld latency",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40132",
+ "EventName": "PM_MRK_LSU_FIN",
+ "BriefDescription": "lsu marked instr finish",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20112",
+ "EventName": "PM_MRK_NTF_FIN",
+ "BriefDescription": "Marked next to finish instruction finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d15e",
+ "EventName": "PM_MRK_RUN_CYC",
+ "BriefDescription": "Marked run cycles",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3013e",
+ "EventName": "PM_MRK_STALL_CMPLU_CYC",
+ "BriefDescription": "Marked Group completion Stall",
+ "PublicDescription": "Marked Group Completion Stall cycles (use edge detect to count #)"
+ },
+ {,
+ "EventCode": "0x3e158",
+ "EventName": "PM_MRK_STCX_FAIL",
+ "BriefDescription": "marked stcx failed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10134",
+ "EventName": "PM_MRK_ST_CMPL",
+ "BriefDescription": "marked store completed and sent to nest",
+ "PublicDescription": "Marked store completed"
+ },
+ {,
+ "EventCode": "0x30134",
+ "EventName": "PM_MRK_ST_CMPL_INT",
+ "BriefDescription": "marked store finished with intervention",
+ "PublicDescription": "marked store complete (data home) with intervention"
+ },
+ {,
+ "EventCode": "0x3f150",
+ "EventName": "PM_MRK_ST_DRAIN_TO_L2DISP_CYC",
+ "BriefDescription": "cycles to drain st from core to L2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3012c",
+ "EventName": "PM_MRK_ST_FWD",
+ "BriefDescription": "Marked st forwards",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f150",
+ "EventName": "PM_MRK_ST_L2DISP_TO_CMPL_CYC",
+ "BriefDescription": "cycles from L2 rc disp to l2 rc completion",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20138",
+ "EventName": "PM_MRK_ST_NEST",
+ "BriefDescription": "Marked store sent to nest",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30132",
+ "EventName": "PM_MRK_VSU_FIN",
+ "BriefDescription": "VSU marked instr finish",
+ "PublicDescription": "vsu (fpu) marked instr finish"
+ },
+ {,
+ "EventCode": "0x3d15e",
+ "EventName": "PM_MULT_MRK",
+ "BriefDescription": "mult marked instr",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15152",
+ "EventName": "PM_SYNC_MRK_BR_LINK",
+ "BriefDescription": "Marked Branch and link branch that can cause a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1515c",
+ "EventName": "PM_SYNC_MRK_BR_MPRED",
+ "BriefDescription": "Marked Branch mispredict that can cause a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15156",
+ "EventName": "PM_SYNC_MRK_FX_DIVIDE",
+ "BriefDescription": "Marked fixed point divide that can cause a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15158",
+ "EventName": "PM_SYNC_MRK_L2HIT",
+ "BriefDescription": "Marked L2 Hits that can throw a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1515a",
+ "EventName": "PM_SYNC_MRK_L2MISS",
+ "BriefDescription": "Marked L2 Miss that can throw a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15154",
+ "EventName": "PM_SYNC_MRK_L3MISS",
+ "BriefDescription": "Marked L3 misses that can throw a synchronous interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15150",
+ "EventName": "PM_SYNC_MRK_PROBE_NOP",
+ "BriefDescription": "Marked probeNops which can cause synchronous interrupts",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/memory.json b/tools/perf/pmu-events/arch/powerpc/power8/memory.json
new file mode 100644
index 000000000000..87cdaadba7bd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/memory.json
@@ -0,0 +1,212 @@
+[
+ {,
+ "EventCode": "0x10050",
+ "EventName": "PM_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for all data types ( demand load,data,inst prefetch,inst fetch,xlate (I or d)"
+ },
+ {,
+ "EventCode": "0x1c050",
+ "EventName": "PM_DATA_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for a demand load",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for a demand load"
+ },
+ {,
+ "EventCode": "0x4c04c",
+ "EventName": "PM_DATA_FROM_DMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c048",
+ "EventName": "PM_DATA_FROM_LMEM",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's Memory due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from the local chip's Memory due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c04c",
+ "EventName": "PM_DATA_FROM_MEMORY",
+ "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c04a",
+ "EventName": "PM_DATA_FROM_RL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c04a",
+ "EventName": "PM_DATA_FROM_RMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c050",
+ "EventName": "PM_DATA_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for a demand load",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for a demand load"
+ },
+ {,
+ "EventCode": "0x2c052",
+ "EventName": "PM_DATA_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for a demand load",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x1c052",
+ "EventName": "PM_DATA_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for a demand load",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor a demand load"
+ },
+ {,
+ "EventCode": "0x1c054",
+ "EventName": "PM_DATA_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for a demand load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c052",
+ "EventName": "PM_DATA_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for a demand load",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor a demand load"
+ },
+ {,
+ "EventCode": "0x3c050",
+ "EventName": "PM_DATA_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for a demand load",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for a demand load"
+ },
+ {,
+ "EventCode": "0x3c052",
+ "EventName": "PM_DATA_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x4c050",
+ "EventName": "PM_DATA_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for a demand load",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for a demand load"
+ },
+ {,
+ "EventCode": "0x3e04c",
+ "EventName": "PM_DPTEG_FROM_DL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e04c",
+ "EventName": "PM_DPTEG_FROM_DMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e04a",
+ "EventName": "PM_DPTEG_FROM_RMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20050",
+ "EventName": "PM_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20052",
+ "EventName": "PM_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x10052",
+ "EventName": "PM_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x18082",
+ "EventName": "PM_L3_CO_MEPF",
+ "BriefDescription": "L3 CO of line in Mep state ( includes casthrough",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c058",
+ "EventName": "PM_MEM_CO",
+ "BriefDescription": "Memory castouts from this lpar",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10058",
+ "EventName": "PM_MEM_LOC_THRESH_IFU",
+ "BriefDescription": "Local Memory above threshold for IFU speculation control",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40056",
+ "EventName": "PM_MEM_LOC_THRESH_LSU_HIGH",
+ "BriefDescription": "Local memory above threshold for LSU medium",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1c05e",
+ "EventName": "PM_MEM_LOC_THRESH_LSU_MED",
+ "BriefDescription": "Local memory above theshold for data prefetch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c058",
+ "EventName": "PM_MEM_PREF",
+ "BriefDescription": "Memory prefetch for this lpar. Includes L4",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10056",
+ "EventName": "PM_MEM_READ",
+ "BriefDescription": "Reads from Memory from this lpar (includes data/inst/xlate/l1prefetch/inst prefetch). Includes L4",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3c05e",
+ "EventName": "PM_MEM_RWITM",
+ "BriefDescription": "Memory rwitm for this lpar",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3006e",
+ "EventName": "PM_NEST_REF_CLK",
+ "BriefDescription": "Multiply by 4 to obtain the number of PB cycles",
+ "PublicDescription": "Nest reference clocks"
+ },
+ {,
+ "EventCode": "0x10054",
+ "EventName": "PM_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Pump prediction correct. Counts across all types of pumpsfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x40052",
+ "EventName": "PM_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x30050",
+ "EventName": "PM_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x30052",
+ "EventName": "PM_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x40050",
+ "EventName": "PM_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/other.json b/tools/perf/pmu-events/arch/powerpc/power8/other.json
new file mode 100644
index 000000000000..704302c3e67d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/other.json
@@ -0,0 +1,4064 @@
+[
+ {,
+ "EventCode": "0x1f05e",
+ "EventName": "PM_1LPAR_CYC",
+ "BriefDescription": "Number of cycles in single lpar mode. All threads in the core are assigned to the same lpar",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2006e",
+ "EventName": "PM_2LPAR_CYC",
+ "BriefDescription": "Cycles in 2-lpar mode. Threads 0-3 belong to Lpar0 and threads 4-7 belong to Lpar1",
+ "PublicDescription": "Number of cycles in 2 lpar mode"
+ },
+ {,
+ "EventCode": "0x4e05e",
+ "EventName": "PM_4LPAR_CYC",
+ "BriefDescription": "Number of cycles in 4 LPAR mode. Threads 0-1 belong to lpar0, threads 2-3 belong to lpar1, threads 4-5 belong to lpar2, and threads 6-7 belong to lpar3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x610050",
+ "EventName": "PM_ALL_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for all data types ( demand load,data,inst prefetch,inst fetch,xlate (I or d)"
+ },
+ {,
+ "EventCode": "0x520050",
+ "EventName": "PM_ALL_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x620052",
+ "EventName": "PM_ALL_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x610052",
+ "EventName": "PM_ALL_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x610054",
+ "EventName": "PM_ALL_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Pump prediction correct. Counts across all types of pumpsfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x640052",
+ "EventName": "PM_ALL_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x630050",
+ "EventName": "PM_ALL_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x630052",
+ "EventName": "PM_ALL_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x640050",
+ "EventName": "PM_ALL_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for all data types (demand load,data prefetch,inst prefetch,inst fetch,xlate)",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
+ },
+ {,
+ "EventCode": "0x4082",
+ "EventName": "PM_BANK_CONFLICT",
+ "BriefDescription": "Read blocked due to interleave conflict. The ifar logic will detect an interleave conflict and kill the data that was read that cycle",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5086",
+ "EventName": "PM_BR_BC_8",
+ "BriefDescription": "Pairable BC+8 branch that has not been converted to a Resolve Finished in the BRU pipeline",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5084",
+ "EventName": "PM_BR_BC_8_CONV",
+ "BriefDescription": "Pairable BC+8 branch that was converted to a Resolve Finished in the BRU pipeline",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40ac",
+ "EventName": "PM_BR_MPRED_CCACHE",
+ "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Count Cache Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40b8",
+ "EventName": "PM_BR_MPRED_CR",
+ "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the BHT Direction Prediction (taken/not taken)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40ae",
+ "EventName": "PM_BR_MPRED_LSTACK",
+ "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Link Stack Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40ba",
+ "EventName": "PM_BR_MPRED_TA",
+ "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Target Address Prediction from the Count Cache or Link Stack. Only XL-form branches that resolved Taken set this event",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10138",
+ "EventName": "PM_BR_MRK_2PATH",
+ "BriefDescription": "marked two path branch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x409c",
+ "EventName": "PM_BR_PRED_BR0",
+ "BriefDescription": "Conditional Branch Completed on BR0 (1st branch in group) in which the HW predicted the Direction or Target",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x409e",
+ "EventName": "PM_BR_PRED_BR1",
+ "BriefDescription": "Conditional Branch Completed on BR1 (2nd branch in group) in which the HW predicted the Direction or Target. Note: BR1 can only be used in Single Thread Mode. In all of the SMT modes, only one branch can complete, thus BR1 is unused",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x489c",
+ "EventName": "PM_BR_PRED_BR_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred(0) OR if_pc_br0_br_pred(1)",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x40a4",
+ "EventName": "PM_BR_PRED_CCACHE_BR0",
+ "BriefDescription": "Conditional Branch Completed on BR0 that used the Count Cache for Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40a6",
+ "EventName": "PM_BR_PRED_CCACHE_BR1",
+ "BriefDescription": "Conditional Branch Completed on BR1 that used the Count Cache for Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x48a4",
+ "EventName": "PM_BR_PRED_CCACHE_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred(0) AND if_pc_br0_pred_type",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x40b0",
+ "EventName": "PM_BR_PRED_CR_BR0",
+ "BriefDescription": "Conditional Branch Completed on BR0 that had its direction predicted. I-form branches do not set this event. In addition, B-form branches which do not use the BHT do not set this event - these are branches with BO-field set to 'always taken' and branches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40b2",
+ "EventName": "PM_BR_PRED_CR_BR1",
+ "BriefDescription": "Conditional Branch Completed on BR1 that had its direction predicted. I-form branches do not set this event. In addition, B-form branches which do not use the BHT do not set this event - these are branches with BO-field set to 'always taken' and branches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x48b0",
+ "EventName": "PM_BR_PRED_CR_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred(1)='1'",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x40a8",
+ "EventName": "PM_BR_PRED_LSTACK_BR0",
+ "BriefDescription": "Conditional Branch Completed on BR0 that used the Link Stack for Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40aa",
+ "EventName": "PM_BR_PRED_LSTACK_BR1",
+ "BriefDescription": "Conditional Branch Completed on BR1 that used the Link Stack for Target Prediction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x48a8",
+ "EventName": "PM_BR_PRED_LSTACK_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred(0) AND (not if_pc_br0_pred_type)",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x40b4",
+ "EventName": "PM_BR_PRED_TA_BR0",
+ "BriefDescription": "Conditional Branch Completed on BR0 that had its target address predicted. Only XL-form branches set this event",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40b6",
+ "EventName": "PM_BR_PRED_TA_BR1",
+ "BriefDescription": "Conditional Branch Completed on BR1 that had its target address predicted. Only XL-form branches set this event",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x48b4",
+ "EventName": "PM_BR_PRED_TA_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred(0)='1'",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x40a0",
+ "EventName": "PM_BR_UNCOND_BR0",
+ "BriefDescription": "Unconditional Branch Completed on BR0. HW branch prediction was not used for this branch. This can be an I-form branch, a B-form branch with BO-field set to branch always, or a B-form branch which was coverted to a Resolve",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40a2",
+ "EventName": "PM_BR_UNCOND_BR1",
+ "BriefDescription": "Unconditional Branch Completed on BR1. HW branch prediction was not used for this branch. This can be an I-form branch, a B-form branch with BO-field set to branch always, or a B-form branch which was coverted to a Resolve",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x48a0",
+ "EventName": "PM_BR_UNCOND_CMPL",
+ "BriefDescription": "Completion Time Event. This event can also be calculated from the direct bus as follows: if_pc_br0_br_pred=00 AND if_pc_br0_completed",
+ "PublicDescription": "IFU"
+ },
+ {,
+ "EventCode": "0x3094",
+ "EventName": "PM_CASTOUT_ISSUED",
+ "BriefDescription": "Castouts issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3096",
+ "EventName": "PM_CASTOUT_ISSUED_GPR",
+ "BriefDescription": "Castouts issued GPR",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2090",
+ "EventName": "PM_CLB_HELD",
+ "BriefDescription": "CLB Hold: Any Reason",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d018",
+ "EventName": "PM_CMPLU_STALL_BRU_CRU",
+ "BriefDescription": "Completion stall due to IFU",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30026",
+ "EventName": "PM_CMPLU_STALL_COQ_FULL",
+ "BriefDescription": "Completion stall due to CO q full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30038",
+ "EventName": "PM_CMPLU_STALL_FLUSH",
+ "BriefDescription": "completion stall due to flush by own thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30028",
+ "EventName": "PM_CMPLU_STALL_MEM_ECC_DELAY",
+ "BriefDescription": "Completion stall due to mem ECC delay",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e01c",
+ "EventName": "PM_CMPLU_STALL_NO_NTF",
+ "BriefDescription": "Completion stall due to nop",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e01e",
+ "EventName": "PM_CMPLU_STALL_NTCG_FLUSH",
+ "BriefDescription": "Completion stall due to ntcg flush",
+ "PublicDescription": "Completion stall due to reject (load hit store)"
+ },
+ {,
+ "EventCode": "0x4c010",
+ "EventName": "PM_CMPLU_STALL_REJECT",
+ "BriefDescription": "Completion stall due to LSU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c01a",
+ "EventName": "PM_CMPLU_STALL_REJECT_LHS",
+ "BriefDescription": "Completion stall due to reject (load hit store)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c014",
+ "EventName": "PM_CMPLU_STALL_REJ_LMQ_FULL",
+ "BriefDescription": "Completion stall due to LSU reject LMQ full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d010",
+ "EventName": "PM_CMPLU_STALL_SCALAR",
+ "BriefDescription": "Completion stall due to VSU scalar instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d010",
+ "EventName": "PM_CMPLU_STALL_SCALAR_LONG",
+ "BriefDescription": "Completion stall due to VSU scalar long latency instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c014",
+ "EventName": "PM_CMPLU_STALL_STORE",
+ "BriefDescription": "Completion stall by stores this includes store agen finishes in pipe LS0/LS1 and store data finishes in LS2/LS3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d014",
+ "EventName": "PM_CMPLU_STALL_VECTOR",
+ "BriefDescription": "Completion stall due to VSU vector instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d012",
+ "EventName": "PM_CMPLU_STALL_VECTOR_LONG",
+ "BriefDescription": "Completion stall due to VSU vector long instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d012",
+ "EventName": "PM_CMPLU_STALL_VSU",
+ "BriefDescription": "Completion stall due to VSU instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x16083",
+ "EventName": "PM_CO0_ALLOC",
+ "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x16082",
+ "EventName": "PM_CO0_BUSY",
+ "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x517082",
+ "EventName": "PM_CO_DISP_FAIL",
+ "BriefDescription": "CO dispatch failed due to all CO machines being busy",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x527084",
+ "EventName": "PM_CO_TM_SC_FOOTPRINT",
+ "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3608a",
+ "EventName": "PM_CO_USAGE",
+ "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 CO machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40066",
+ "EventName": "PM_CRU_FIN",
+ "BriefDescription": "IFU Finished a (non-branch) instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x61c050",
+ "EventName": "PM_DATA_ALL_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for either demand loads or data prefetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for a demand load"
+ },
+ {,
+ "EventCode": "0x64c048",
+ "EventName": "PM_DATA_ALL_FROM_DL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c048",
+ "EventName": "PM_DATA_ALL_FROM_DL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c04c",
+ "EventName": "PM_DATA_ALL_FROM_DL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c04c",
+ "EventName": "PM_DATA_ALL_FROM_DMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c042",
+ "EventName": "PM_DATA_ALL_FROM_L2",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c046",
+ "EventName": "PM_DATA_ALL_FROM_L21_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c046",
+ "EventName": "PM_DATA_ALL_FROM_L21_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c04e",
+ "EventName": "PM_DATA_ALL_FROM_L2MISS_MOD",
+ "BriefDescription": "The processor's data cache was reloaded from a localtion other than the local core's L2 due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from a localtion other than the local core's L2 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c040",
+ "EventName": "PM_DATA_ALL_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c040",
+ "EventName": "PM_DATA_ALL_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c040",
+ "EventName": "PM_DATA_ALL_FROM_L2_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c040",
+ "EventName": "PM_DATA_ALL_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c042",
+ "EventName": "PM_DATA_ALL_FROM_L3",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c044",
+ "EventName": "PM_DATA_ALL_FROM_L31_ECO_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c044",
+ "EventName": "PM_DATA_ALL_FROM_L31_ECO_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c044",
+ "EventName": "PM_DATA_ALL_FROM_L31_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c046",
+ "EventName": "PM_DATA_ALL_FROM_L31_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c04e",
+ "EventName": "PM_DATA_ALL_FROM_L3MISS_MOD",
+ "BriefDescription": "The processor's data cache was reloaded from a localtion other than the local core's L3 due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from a localtion other than the local core's L3 due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c042",
+ "EventName": "PM_DATA_ALL_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c042",
+ "EventName": "PM_DATA_ALL_FROM_L3_MEPF",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c044",
+ "EventName": "PM_DATA_ALL_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c04c",
+ "EventName": "PM_DATA_ALL_FROM_LL4",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c048",
+ "EventName": "PM_DATA_ALL_FROM_LMEM",
+ "BriefDescription": "The processor's data cache was reloaded from the local chip's Memory due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from the local chip's Memory due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c04c",
+ "EventName": "PM_DATA_ALL_FROM_MEMORY",
+ "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x64c04a",
+ "EventName": "PM_DATA_ALL_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c048",
+ "EventName": "PM_DATA_ALL_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c046",
+ "EventName": "PM_DATA_ALL_FROM_RL2L3_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x61c04a",
+ "EventName": "PM_DATA_ALL_FROM_RL2L3_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c04a",
+ "EventName": "PM_DATA_ALL_FROM_RL4",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x63c04a",
+ "EventName": "PM_DATA_ALL_FROM_RMEM",
+ "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to either demand loads or data prefetch",
+ "PublicDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x62c050",
+ "EventName": "PM_DATA_ALL_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for either demand loads or data prefetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for a demand load"
+ },
+ {,
+ "EventCode": "0x62c052",
+ "EventName": "PM_DATA_ALL_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for either demand loads or data prefetch",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x61c052",
+ "EventName": "PM_DATA_ALL_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for either demand loads or data prefetch",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor a demand load"
+ },
+ {,
+ "EventCode": "0x61c054",
+ "EventName": "PM_DATA_ALL_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for either demand loads or data prefetch",
+ "PublicDescription": "Pump prediction correct. Counts across all types of pumps for a demand load"
+ },
+ {,
+ "EventCode": "0x64c052",
+ "EventName": "PM_DATA_ALL_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for either demand loads or data prefetch",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor a demand load"
+ },
+ {,
+ "EventCode": "0x63c050",
+ "EventName": "PM_DATA_ALL_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for either demand loads or data prefetch",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for a demand load"
+ },
+ {,
+ "EventCode": "0x63c052",
+ "EventName": "PM_DATA_ALL_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for either demand loads or data prefetch",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x64c050",
+ "EventName": "PM_DATA_ALL_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for either demand loads or data prefetch",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for a demand load"
+ },
+ {,
+ "EventCode": "0x4c046",
+ "EventName": "PM_DATA_FROM_L21_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c046",
+ "EventName": "PM_DATA_FROM_L21_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x4c044",
+ "EventName": "PM_DATA_FROM_L31_ECO_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x3c044",
+ "EventName": "PM_DATA_FROM_L31_ECO_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x2c044",
+ "EventName": "PM_DATA_FROM_L31_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x1c046",
+ "EventName": "PM_DATA_FROM_L31_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to a demand load",
+ "PublicDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to either only demand loads or demand loads plus prefetches if MMCR1[16] is 1"
+ },
+ {,
+ "EventCode": "0x400fe",
+ "EventName": "PM_DATA_FROM_MEM",
+ "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a demand load",
+ "PublicDescription": "Data cache reload from memory (including L4)"
+ },
+ {,
+ "EventCode": "0xe0bc",
+ "EventName": "PM_DC_COLLISIONS",
+ "BriefDescription": "DATA Cache collisions",
+ "PublicDescription": "DATA Cache collisions42"
+ },
+ {,
+ "EventCode": "0x1e050",
+ "EventName": "PM_DC_PREF_STREAM_ALLOC",
+ "BriefDescription": "Stream marked valid. The stream could have been allocated through the hardware prefetch mechanism or through software. This is combined ls0 and ls1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e050",
+ "EventName": "PM_DC_PREF_STREAM_CONF",
+ "BriefDescription": "A demand load referenced a line in an active prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software. Combine up + down",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e050",
+ "EventName": "PM_DC_PREF_STREAM_FUZZY_CONF",
+ "BriefDescription": "A demand load referenced a line in an active fuzzy prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software.Fuzzy stream confirm (out of order effects, or pf cant keep up)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e050",
+ "EventName": "PM_DC_PREF_STREAM_STRIDED_CONF",
+ "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0ba",
+ "EventName": "PM_DFU",
+ "BriefDescription": "Finish DFU (all finish)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0be",
+ "EventName": "PM_DFU_DCFFIX",
+ "BriefDescription": "Convert from fixed opcode finish (dcffix,dcffixq)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0bc",
+ "EventName": "PM_DFU_DENBCD",
+ "BriefDescription": "BCD->DPD opcode finish (denbcd, denbcdq)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0b8",
+ "EventName": "PM_DFU_MC",
+ "BriefDescription": "Finish DFU multicycle",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2092",
+ "EventName": "PM_DISP_CLB_HELD_BAL",
+ "BriefDescription": "Dispatch/CLB Hold: Balance",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2094",
+ "EventName": "PM_DISP_CLB_HELD_RES",
+ "BriefDescription": "Dispatch/CLB Hold: Resource",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20a8",
+ "EventName": "PM_DISP_CLB_HELD_SB",
+ "BriefDescription": "Dispatch/CLB Hold: Scoreboard",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2098",
+ "EventName": "PM_DISP_CLB_HELD_SYNC",
+ "BriefDescription": "Dispatch/CLB Hold: Sync type instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2096",
+ "EventName": "PM_DISP_CLB_HELD_TLBIE",
+ "BriefDescription": "Dispatch Hold: Due to TLBIE",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20006",
+ "EventName": "PM_DISP_HELD_IQ_FULL",
+ "BriefDescription": "Dispatch held due to Issue q full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1002a",
+ "EventName": "PM_DISP_HELD_MAP_FULL",
+ "BriefDescription": "Dispatch for this thread was held because the Mappers were full",
+ "PublicDescription": "Dispatch held due to Mapper full"
+ },
+ {,
+ "EventCode": "0x30018",
+ "EventName": "PM_DISP_HELD_SRQ_FULL",
+ "BriefDescription": "Dispatch held due SRQ no room",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30a6",
+ "EventName": "PM_DISP_HOLD_GCT_FULL",
+ "BriefDescription": "Dispatch Hold Due to no space in the GCT",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30008",
+ "EventName": "PM_DISP_WT",
+ "BriefDescription": "Dispatched Starved",
+ "PublicDescription": "Dispatched Starved (not held, nothing to dispatch)"
+ },
+ {,
+ "EventCode": "0x4e046",
+ "EventName": "PM_DPTEG_FROM_L21_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e046",
+ "EventName": "PM_DPTEG_FROM_L21_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e040",
+ "EventName": "PM_DPTEG_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with load hit store conflict due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e040",
+ "EventName": "PM_DPTEG_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with dispatch conflict due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e044",
+ "EventName": "PM_DPTEG_FROM_L31_ECO_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e044",
+ "EventName": "PM_DPTEG_FROM_L31_ECO_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e044",
+ "EventName": "PM_DPTEG_FROM_L31_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e046",
+ "EventName": "PM_DPTEG_FROM_L31_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50a8",
+ "EventName": "PM_EAT_FORCE_MISPRED",
+ "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issue",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4084",
+ "EventName": "PM_EAT_FULL_CYC",
+ "BriefDescription": "Cycles No room in EAT",
+ "PublicDescription": "Cycles No room in EATSet on bank conflict and case where no ibuffers available"
+ },
+ {,
+ "EventCode": "0x2080",
+ "EventName": "PM_EE_OFF_EXT_INT",
+ "BriefDescription": "Ee off and external interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20b4",
+ "EventName": "PM_FAV_TBEGIN",
+ "BriefDescription": "Dispatch time Favored tbegin",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x100f4",
+ "EventName": "PM_FLOP",
+ "BriefDescription": "Floating Point Operation Finished",
+ "PublicDescription": "Floating Point Operations Finished"
+ },
+ {,
+ "EventCode": "0xa0ae",
+ "EventName": "PM_FLOP_SUM_SCALAR",
+ "BriefDescription": "flops summary scalar instructions",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0ac",
+ "EventName": "PM_FLOP_SUM_VEC",
+ "BriefDescription": "flops summary vector instructions",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2084",
+ "EventName": "PM_FLUSH_BR_MPRED",
+ "BriefDescription": "Flush caused by branch mispredict",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2082",
+ "EventName": "PM_FLUSH_DISP",
+ "BriefDescription": "Dispatch flush",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x208c",
+ "EventName": "PM_FLUSH_DISP_SB",
+ "BriefDescription": "Dispatch Flush: Scoreboard",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2088",
+ "EventName": "PM_FLUSH_DISP_SYNC",
+ "BriefDescription": "Dispatch Flush: Sync",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x208a",
+ "EventName": "PM_FLUSH_DISP_TLBIE",
+ "BriefDescription": "Dispatch Flush: TLBIE",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x208e",
+ "EventName": "PM_FLUSH_LSU",
+ "BriefDescription": "Flush initiated by LSU",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2086",
+ "EventName": "PM_FLUSH_PARTIAL",
+ "BriefDescription": "Partial flush",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0b0",
+ "EventName": "PM_FPU0_FCONV",
+ "BriefDescription": "Convert instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0b8",
+ "EventName": "PM_FPU0_FEST",
+ "BriefDescription": "Estimate instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0b4",
+ "EventName": "PM_FPU0_FRSP",
+ "BriefDescription": "Round to single precision instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0b2",
+ "EventName": "PM_FPU1_FCONV",
+ "BriefDescription": "Convert instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0ba",
+ "EventName": "PM_FPU1_FEST",
+ "BriefDescription": "Estimate instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0b6",
+ "EventName": "PM_FPU1_FRSP",
+ "BriefDescription": "Round to single precision instruction executed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50b0",
+ "EventName": "PM_FUSION_TOC_GRP0_1",
+ "BriefDescription": "One pair of instructions fused with TOC in Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50ae",
+ "EventName": "PM_FUSION_TOC_GRP0_2",
+ "BriefDescription": "Two pairs of instructions fused with TOCin Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50ac",
+ "EventName": "PM_FUSION_TOC_GRP0_3",
+ "BriefDescription": "Three pairs of instructions fused with TOC in Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50b2",
+ "EventName": "PM_FUSION_TOC_GRP1_1",
+ "BriefDescription": "One pair of instructions fused with TOX in Group1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50b8",
+ "EventName": "PM_FUSION_VSX_GRP0_1",
+ "BriefDescription": "One pair of instructions fused with VSX in Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50b6",
+ "EventName": "PM_FUSION_VSX_GRP0_2",
+ "BriefDescription": "Two pairs of instructions fused with VSX in Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50b4",
+ "EventName": "PM_FUSION_VSX_GRP0_3",
+ "BriefDescription": "Three pairs of instructions fused with VSX in Group0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50ba",
+ "EventName": "PM_FUSION_VSX_GRP1_1",
+ "BriefDescription": "One pair of instructions fused with VSX in Group1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3000e",
+ "EventName": "PM_FXU0_BUSY_FXU1_IDLE",
+ "BriefDescription": "fxu0 busy and fxu1 idle",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10004",
+ "EventName": "PM_FXU0_FIN",
+ "BriefDescription": "The fixed point unit Unit 0 finished an instruction. Instructions that finish may not necessary complete",
+ "PublicDescription": "FXU0 Finished"
+ },
+ {,
+ "EventCode": "0x4000e",
+ "EventName": "PM_FXU1_BUSY_FXU0_IDLE",
+ "BriefDescription": "fxu0 idle and fxu1 busy",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40004",
+ "EventName": "PM_FXU1_FIN",
+ "BriefDescription": "FXU1 Finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20008",
+ "EventName": "PM_GCT_EMPTY_CYC",
+ "BriefDescription": "No itags assigned either thread (GCT Empty)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30a4",
+ "EventName": "PM_GCT_MERGE",
+ "BriefDescription": "Group dispatched on a merged GCT empty. GCT entries can be merged only within the same thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d01e",
+ "EventName": "PM_GCT_NOSLOT_BR_MPRED",
+ "BriefDescription": "Gct empty for this thread due to branch mispred",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d01a",
+ "EventName": "PM_GCT_NOSLOT_BR_MPRED_ICMISS",
+ "BriefDescription": "Gct empty for this thread due to Icache Miss and branch mispred",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x100f8",
+ "EventName": "PM_GCT_NOSLOT_CYC",
+ "BriefDescription": "No itags assigned",
+ "PublicDescription": "Pipeline empty (No itags assigned , no GCT slots used)"
+ },
+ {,
+ "EventCode": "0x2d01e",
+ "EventName": "PM_GCT_NOSLOT_DISP_HELD_ISSQ",
+ "BriefDescription": "Gct empty for this thread due to dispatch hold on this thread due to Issue q full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d01c",
+ "EventName": "PM_GCT_NOSLOT_DISP_HELD_MAP",
+ "BriefDescription": "Gct empty for this thread due to dispatch hold on this thread due to Mapper full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e010",
+ "EventName": "PM_GCT_NOSLOT_DISP_HELD_OTHER",
+ "BriefDescription": "Gct empty for this thread due to dispatch hold on this thread due to sync",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d01c",
+ "EventName": "PM_GCT_NOSLOT_DISP_HELD_SRQ",
+ "BriefDescription": "Gct empty for this thread due to dispatch hold on this thread due to SRQ full",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e010",
+ "EventName": "PM_GCT_NOSLOT_IC_L3MISS",
+ "BriefDescription": "Gct empty for this thread due to icach l3 miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d01a",
+ "EventName": "PM_GCT_NOSLOT_IC_MISS",
+ "BriefDescription": "Gct empty for this thread due to Icache Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20a2",
+ "EventName": "PM_GCT_UTIL_11_14_ENTRIES",
+ "BriefDescription": "GCT Utilization 11-14 entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20a4",
+ "EventName": "PM_GCT_UTIL_15_17_ENTRIES",
+ "BriefDescription": "GCT Utilization 15-17 entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20a6",
+ "EventName": "PM_GCT_UTIL_18_ENTRIES",
+ "BriefDescription": "GCT Utilization 18+ entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x209c",
+ "EventName": "PM_GCT_UTIL_1_2_ENTRIES",
+ "BriefDescription": "GCT Utilization 1-2 entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x209e",
+ "EventName": "PM_GCT_UTIL_3_6_ENTRIES",
+ "BriefDescription": "GCT Utilization 3-6 entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20a0",
+ "EventName": "PM_GCT_UTIL_7_10_ENTRIES",
+ "BriefDescription": "GCT Utilization 7-10 entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1000a",
+ "EventName": "PM_GRP_BR_MPRED_NONSPEC",
+ "BriefDescription": "Group experienced non-speculative branch redirect",
+ "PublicDescription": "Group experienced Non-speculative br mispredicct"
+ },
+ {,
+ "EventCode": "0x30004",
+ "EventName": "PM_GRP_CMPL",
+ "BriefDescription": "group completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3000a",
+ "EventName": "PM_GRP_DISP",
+ "BriefDescription": "group dispatch",
+ "PublicDescription": "dispatch_success (Group Dispatched)"
+ },
+ {,
+ "EventCode": "0x1000c",
+ "EventName": "PM_GRP_IC_MISS_NONSPEC",
+ "BriefDescription": "Group experienced non-speculative I cache miss",
+ "PublicDescription": "Group experi enced Non-specu lative I cache miss"
+ },
+ {,
+ "EventCode": "0x10130",
+ "EventName": "PM_GRP_MRK",
+ "BriefDescription": "Instruction Marked",
+ "PublicDescription": "Instruction marked in idu"
+ },
+ {,
+ "EventCode": "0x509c",
+ "EventName": "PM_GRP_NON_FULL_GROUP",
+ "BriefDescription": "GROUPs where we did not have 6 non branch instructions in the group(ST mode), in SMT mode 3 non branches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50a4",
+ "EventName": "PM_GRP_TERM_2ND_BRANCH",
+ "BriefDescription": "There were enough instructions in the Ibuffer, but 2nd branch ends group",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50a6",
+ "EventName": "PM_GRP_TERM_FPU_AFTER_BR",
+ "BriefDescription": "There were enough instructions in the Ibuffer, but FPU OP IN same group after a branch terminates a group, cant do partial flushes",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x509e",
+ "EventName": "PM_GRP_TERM_NOINST",
+ "BriefDescription": "Do not fill every slot in the group, Not enough instructions in the Ibuffer. This includes cases where the group started with enough instructions, but some got knocked out by a cache miss or branch redirect (which would also empty the Ibuffer)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50a0",
+ "EventName": "PM_GRP_TERM_OTHER",
+ "BriefDescription": "There were enough instructions in the Ibuffer, but the group terminated early for some other reason, most likely due to a First or Last",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x50a2",
+ "EventName": "PM_GRP_TERM_SLOT_LIMIT",
+ "BriefDescription": "There were enough instructions in the Ibuffer, but 3 src RA/RB/RC , 2 way crack caused a group termination",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4086",
+ "EventName": "PM_IBUF_FULL_CYC",
+ "BriefDescription": "Cycles No room in ibuff",
+ "PublicDescription": "Cycles No room in ibufffully qualified transfer (if5 valid)"
+ },
+ {,
+ "EventCode": "0x4098",
+ "EventName": "PM_IC_DEMAND_L2_BHT_REDIRECT",
+ "BriefDescription": "L2 I cache demand request due to BHT redirect, branch redirect ( 2 bubbles 3 cycles)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x409a",
+ "EventName": "PM_IC_DEMAND_L2_BR_REDIRECT",
+ "BriefDescription": "L2 I cache demand request due to branch Mispredict ( 15 cycle path)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4088",
+ "EventName": "PM_IC_DEMAND_REQ",
+ "BriefDescription": "Demand Instruction fetch request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x508a",
+ "EventName": "PM_IC_INVALIDATE",
+ "BriefDescription": "Ic line invalidated",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4092",
+ "EventName": "PM_IC_PREF_CANCEL_HIT",
+ "BriefDescription": "Prefetch Canceled due to icache hit",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4094",
+ "EventName": "PM_IC_PREF_CANCEL_L2",
+ "BriefDescription": "L2 Squashed request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4090",
+ "EventName": "PM_IC_PREF_CANCEL_PAGE",
+ "BriefDescription": "Prefetch Canceled due to page boundary",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x408a",
+ "EventName": "PM_IC_PREF_REQ",
+ "BriefDescription": "Instruction prefetch requests",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x408e",
+ "EventName": "PM_IC_PREF_WRITE",
+ "BriefDescription": "Instruction prefetch written into IL1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4096",
+ "EventName": "PM_IC_RELOAD_PRIVATE",
+ "BriefDescription": "Reloading line was brought in private for a specific thread. Most lines are brought in shared for all eight thrreads. If RA does not match then invalidates and then brings it shared to other thread. In P7 line brought in private , then line was invalidat",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5088",
+ "EventName": "PM_IFU_L2_TOUCH",
+ "BriefDescription": "L2 touch to update MRU on a line",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x514050",
+ "EventName": "PM_INST_ALL_CHIP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for instruction fetches and prefetches",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was chip pump (prediction=correct) for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x544048",
+ "EventName": "PM_INST_ALL_FROM_DL2L3_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x534048",
+ "EventName": "PM_INST_ALL_FROM_DL2L3_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x53404c",
+ "EventName": "PM_INST_ALL_FROM_DL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x54404c",
+ "EventName": "PM_INST_ALL_FROM_DMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group (Distant) due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group (Distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x514042",
+ "EventName": "PM_INST_ALL_FROM_L2",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x544046",
+ "EventName": "PM_INST_ALL_FROM_L21_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L2 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L2 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x534046",
+ "EventName": "PM_INST_ALL_FROM_L21_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L2 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L2 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x51404e",
+ "EventName": "PM_INST_ALL_FROM_L2MISS",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L2 due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L2 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x534040",
+ "EventName": "PM_INST_ALL_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with load hit store conflict due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 with load hit store conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x544040",
+ "EventName": "PM_INST_ALL_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with dispatch conflict due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 with dispatch conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524040",
+ "EventName": "PM_INST_ALL_FROM_L2_MEPF",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x514040",
+ "EventName": "PM_INST_ALL_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 without conflict due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L2 without conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x544042",
+ "EventName": "PM_INST_ALL_FROM_L3",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x544044",
+ "EventName": "PM_INST_ALL_FROM_L31_ECO_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x534044",
+ "EventName": "PM_INST_ALL_FROM_L31_ECO_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524044",
+ "EventName": "PM_INST_ALL_FROM_L31_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L3 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x514046",
+ "EventName": "PM_INST_ALL_FROM_L31_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L3 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x54404e",
+ "EventName": "PM_INST_ALL_FROM_L3MISS_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L3 due to a instruction fetch",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a localtion other than the local core's L3 due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x534042",
+ "EventName": "PM_INST_ALL_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 with dispatch conflict due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 with dispatch conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524042",
+ "EventName": "PM_INST_ALL_FROM_L3_MEPF",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x514044",
+ "EventName": "PM_INST_ALL_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without conflict due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from local core's L3 without conflict due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x51404c",
+ "EventName": "PM_INST_ALL_FROM_LL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's L4 cache due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from the local chip's L4 cache due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524048",
+ "EventName": "PM_INST_ALL_FROM_LMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's Memory due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from the local chip's Memory due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x52404c",
+ "EventName": "PM_INST_ALL_FROM_MEMORY",
+ "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x54404a",
+ "EventName": "PM_INST_ALL_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x514048",
+ "EventName": "PM_INST_ALL_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524046",
+ "EventName": "PM_INST_ALL_FROM_RL2L3_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x51404a",
+ "EventName": "PM_INST_ALL_FROM_RL2L3_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x52404a",
+ "EventName": "PM_INST_ALL_FROM_RL4",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x53404a",
+ "EventName": "PM_INST_ALL_FROM_RMEM",
+ "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to instruction fetches and prefetches",
+ "PublicDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x524050",
+ "EventName": "PM_INST_ALL_GRP_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for instruction fetches and prefetches",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x524052",
+ "EventName": "PM_INST_ALL_GRP_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for instruction fetches and prefetches",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope OR Final Pump Scope(Group) got data from source that was at smaller scope(Chip) Final pump was group pump and initial pump was chip or final and initial pump was gro"
+ },
+ {,
+ "EventCode": "0x514052",
+ "EventName": "PM_INST_ALL_GRP_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for instruction fetches and prefetches",
+ "PublicDescription": "Final Pump Scope(Group) to get data sourced, ended up larger than Initial Pump Scope (Chip) Final pump was group pump and initial pump was chip pumpfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x514054",
+ "EventName": "PM_INST_ALL_PUMP_CPRED",
+ "BriefDescription": "Pump prediction correct. Counts across all types of pumps for instruction fetches and prefetches",
+ "PublicDescription": "Pump prediction correct. Counts across all types of pumpsfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x544052",
+ "EventName": "PM_INST_ALL_PUMP_MPRED",
+ "BriefDescription": "Pump misprediction. Counts across all types of pumps for instruction fetches and prefetches",
+ "PublicDescription": "Pump Mis prediction Counts across all types of pumpsfor an instruction fetch"
+ },
+ {,
+ "EventCode": "0x534050",
+ "EventName": "PM_INST_ALL_SYS_PUMP_CPRED",
+ "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for instruction fetches and prefetches",
+ "PublicDescription": "Initial and Final Pump Scope and data sourced across this scope was system pump for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x534052",
+ "EventName": "PM_INST_ALL_SYS_PUMP_MPRED",
+ "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for instruction fetches and prefetches",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope(Chip/Group) OR Final Pump Scope(system) got data from source that was at smaller scope(Chip/group) Final pump was system pump and initial pump was chip or group or"
+ },
+ {,
+ "EventCode": "0x544050",
+ "EventName": "PM_INST_ALL_SYS_PUMP_MPRED_RTY",
+ "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for instruction fetches and prefetches",
+ "PublicDescription": "Final Pump Scope(system) to get data sourced, ended up larger than Initial Pump Scope (Chip or Group) for an instruction fetch"
+ },
+ {,
+ "EventCode": "0x4080",
+ "EventName": "PM_INST_FROM_L1",
+ "BriefDescription": "Instruction fetches from L1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44046",
+ "EventName": "PM_INST_FROM_L21_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L2 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L2 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x34046",
+ "EventName": "PM_INST_FROM_L21_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L2 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L2 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x44044",
+ "EventName": "PM_INST_FROM_L31_ECO_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x34044",
+ "EventName": "PM_INST_FROM_L31_ECO_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x24044",
+ "EventName": "PM_INST_FROM_L31_MOD",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L3 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x14046",
+ "EventName": "PM_INST_FROM_L31_SHR",
+ "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L3 on the same chip due to an instruction fetch (not prefetch)",
+ "PublicDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L3 on the same chip due to either an instruction fetch or instruction fetch plus prefetch if MMCR1[17] is 1"
+ },
+ {,
+ "EventCode": "0x30016",
+ "EventName": "PM_INST_IMC_MATCH_DISP",
+ "BriefDescription": "Matched Instructions Dispatched",
+ "PublicDescription": "IMC Matches dispatched"
+ },
+ {,
+ "EventCode": "0x30014",
+ "EventName": "PM_IOPS_DISP",
+ "BriefDescription": "Internal Operations dispatched",
+ "PublicDescription": "IOPS dispatched"
+ },
+ {,
+ "EventCode": "0x45046",
+ "EventName": "PM_IPTEG_FROM_L21_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x35046",
+ "EventName": "PM_IPTEG_FROM_L21_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x35040",
+ "EventName": "PM_IPTEG_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with load hit store conflict due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x45040",
+ "EventName": "PM_IPTEG_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with dispatch conflict due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x45044",
+ "EventName": "PM_IPTEG_FROM_L31_ECO_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x35044",
+ "EventName": "PM_IPTEG_FROM_L31_ECO_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x25044",
+ "EventName": "PM_IPTEG_FROM_L31_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x15046",
+ "EventName": "PM_IPTEG_FROM_L31_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a instruction side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x617082",
+ "EventName": "PM_ISIDE_DISP",
+ "BriefDescription": "All i-side dispatch attempts",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x627084",
+ "EventName": "PM_ISIDE_DISP_FAIL",
+ "BriefDescription": "All i-side dispatch attempts that failed due to a addr collision with another machine",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x627086",
+ "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
+ "BriefDescription": "All i-side dispatch attempts that failed due to a reason other than addrs collision",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4608e",
+ "EventName": "PM_ISIDE_L2MEMACC",
+ "BriefDescription": "valid when first beat of data comes in for an i-side fetch where data came from mem(or L4)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44608e",
+ "EventName": "PM_ISIDE_MRU_TOUCH",
+ "BriefDescription": "Iside L2 MRU touch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30ac",
+ "EventName": "PM_ISU_REF_FX0",
+ "BriefDescription": "FX0 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30ae",
+ "EventName": "PM_ISU_REF_FX1",
+ "BriefDescription": "FX1 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x38ac",
+ "EventName": "PM_ISU_REF_FXU",
+ "BriefDescription": "FXU ISU reject from either pipe",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30b0",
+ "EventName": "PM_ISU_REF_LS0",
+ "BriefDescription": "LS0 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30b2",
+ "EventName": "PM_ISU_REF_LS1",
+ "BriefDescription": "LS1 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30b4",
+ "EventName": "PM_ISU_REF_LS2",
+ "BriefDescription": "LS2 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30b6",
+ "EventName": "PM_ISU_REF_LS3",
+ "BriefDescription": "LS3 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x309c",
+ "EventName": "PM_ISU_REJECTS_ALL",
+ "BriefDescription": "All isu rejects could be more than 1 per cycle",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30a2",
+ "EventName": "PM_ISU_REJECT_RES_NA",
+ "BriefDescription": "ISU reject due to resource not available",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x309e",
+ "EventName": "PM_ISU_REJECT_SAR_BYPASS",
+ "BriefDescription": "Reject because of SAR bypass",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30a0",
+ "EventName": "PM_ISU_REJECT_SRC_NA",
+ "BriefDescription": "ISU reject due to source not available",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30a8",
+ "EventName": "PM_ISU_REJ_VS0",
+ "BriefDescription": "VS0 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30aa",
+ "EventName": "PM_ISU_REJ_VS1",
+ "BriefDescription": "VS1 ISU reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x38a8",
+ "EventName": "PM_ISU_REJ_VSU",
+ "BriefDescription": "VSU ISU reject from either pipe",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30b8",
+ "EventName": "PM_ISYNC",
+ "BriefDescription": "Isync count per thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200301ea",
+ "EventName": "PM_L1MISS_LAT_EXC_1024",
+ "BriefDescription": "L1 misses that took longer than 1024 cyles to resolve (miss to reload)",
+ "PublicDescription": "Reload latency exceeded 1024 cyc"
+ },
+ {,
+ "EventCode": "0x200401ec",
+ "EventName": "PM_L1MISS_LAT_EXC_2048",
+ "BriefDescription": "L1 misses that took longer than 2048 cyles to resolve (miss to reload)",
+ "PublicDescription": "Reload latency exceeded 2048 cyc"
+ },
+ {,
+ "EventCode": "0x200101e8",
+ "EventName": "PM_L1MISS_LAT_EXC_256",
+ "BriefDescription": "L1 misses that took longer than 256 cyles to resolve (miss to reload)",
+ "PublicDescription": "Reload latency exceeded 256 cyc"
+ },
+ {,
+ "EventCode": "0x200201e6",
+ "EventName": "PM_L1MISS_LAT_EXC_32",
+ "BriefDescription": "L1 misses that took longer than 32 cyles to resolve (miss to reload)",
+ "PublicDescription": "Reload latency exceeded 32 cyc"
+ },
+ {,
+ "EventCode": "0x26086",
+ "EventName": "PM_L1PF_L2MEMACC",
+ "BriefDescription": "valid when first beat of data comes in for an L1pref where data came from mem(or L4)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x408c",
+ "EventName": "PM_L1_DEMAND_WRITE",
+ "BriefDescription": "Instruction Demand sectors wriittent into IL1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x417080",
+ "EventName": "PM_L2_CASTOUT_MOD",
+ "BriefDescription": "L2 Castouts - Modified (M, Mu, Me)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x417082",
+ "EventName": "PM_L2_CASTOUT_SHR",
+ "BriefDescription": "L2 Castouts - Shared (T, Te, Si, S)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x27084",
+ "EventName": "PM_L2_CHIP_PUMP",
+ "BriefDescription": "RC requests that were local on chip pump attempts",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x427086",
+ "EventName": "PM_L2_DC_INV",
+ "BriefDescription": "Dcache invalidates from L2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44608c",
+ "EventName": "PM_L2_DISP_ALL_L2MISS",
+ "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x27086",
+ "EventName": "PM_L2_GROUP_PUMP",
+ "BriefDescription": "RC requests that were on Node Pump attempts",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x626084",
+ "EventName": "PM_L2_GRP_GUESS_CORRECT",
+ "BriefDescription": "L2 guess grp and guess was correct (data intra-6chip AND ^on-chip)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x626086",
+ "EventName": "PM_L2_GRP_GUESS_WRONG",
+ "BriefDescription": "L2 guess grp and guess was not correct (ie data on-chip OR beyond-6chip)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x427084",
+ "EventName": "PM_L2_IC_INV",
+ "BriefDescription": "Icache Invalidates from L2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x436088",
+ "EventName": "PM_L2_INST",
+ "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x43608a",
+ "EventName": "PM_L2_INST_MISS",
+ "BriefDescription": "All successful i-side dispatches that were an L2miss for this thread (excludes i_l2mru_tch reqs)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x416080",
+ "EventName": "PM_L2_LD",
+ "BriefDescription": "All successful D-side Load dispatches for this thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x437088",
+ "EventName": "PM_L2_LD_DISP",
+ "BriefDescription": "All successful load dispatches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x43708a",
+ "EventName": "PM_L2_LD_HIT",
+ "BriefDescription": "All successful load dispatches that were L2 hits",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x426084",
+ "EventName": "PM_L2_LD_MISS",
+ "BriefDescription": "All successful D-Side Load dispatches that were an L2miss for this thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x616080",
+ "EventName": "PM_L2_LOC_GUESS_CORRECT",
+ "BriefDescription": "L2 guess loc and guess was correct (ie data local)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x616082",
+ "EventName": "PM_L2_LOC_GUESS_WRONG",
+ "BriefDescription": "L2 guess loc and guess was not correct (ie data not on chip)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x516080",
+ "EventName": "PM_L2_RCLD_DISP",
+ "BriefDescription": "L2 RC load dispatch attempt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x516082",
+ "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
+ "BriefDescription": "L2 RC load dispatch attempt failed due to address collision with RC/CO/SN/SQ",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x526084",
+ "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
+ "BriefDescription": "L2 RC load dispatch attempt failed due to other reasons",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x536088",
+ "EventName": "PM_L2_RCST_DISP",
+ "BriefDescription": "L2 RC store dispatch attempt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x53608a",
+ "EventName": "PM_L2_RCST_DISP_FAIL_ADDR",
+ "BriefDescription": "L2 RC store dispatch attempt failed due to address collision with RC/CO/SN/SQ",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x54608c",
+ "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
+ "BriefDescription": "L2 RC store dispatch attempt failed due to other reasons",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x537088",
+ "EventName": "PM_L2_RC_ST_DONE",
+ "BriefDescription": "RC did st to line that was Tx or Sx",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x63708a",
+ "EventName": "PM_L2_RTY_LD",
+ "BriefDescription": "RC retries on PB for any load from core",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3708a",
+ "EventName": "PM_L2_RTY_ST",
+ "BriefDescription": "RC retries on PB for any store from core",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x54708c",
+ "EventName": "PM_L2_SN_M_RD_DONE",
+ "BriefDescription": "SNP dispatched for a read and was M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x54708e",
+ "EventName": "PM_L2_SN_M_WR_DONE",
+ "BriefDescription": "SNP dispatched for a write and was M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x53708a",
+ "EventName": "PM_L2_SN_SX_I_DONE",
+ "BriefDescription": "SNP dispatched and went from Sx or Tx to Ix",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x17080",
+ "EventName": "PM_L2_ST",
+ "BriefDescription": "All successful D-side store dispatches for this thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44708c",
+ "EventName": "PM_L2_ST_DISP",
+ "BriefDescription": "All successful store dispatches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x44708e",
+ "EventName": "PM_L2_ST_HIT",
+ "BriefDescription": "All successful store dispatches that were L2Hits",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x17082",
+ "EventName": "PM_L2_ST_MISS",
+ "BriefDescription": "All successful D-side store dispatches for this thread that were L2 Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x636088",
+ "EventName": "PM_L2_SYS_GUESS_CORRECT",
+ "BriefDescription": "L2 guess sys and guess was correct (ie data beyond-6chip)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x63608a",
+ "EventName": "PM_L2_SYS_GUESS_WRONG",
+ "BriefDescription": "L2 guess sys and guess was not correct (ie data ^beyond-6chip)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x617080",
+ "EventName": "PM_L2_SYS_PUMP",
+ "BriefDescription": "RC requests that were system pump attempts",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e05e",
+ "EventName": "PM_L2_TM_REQ_ABORT",
+ "BriefDescription": "TM abort",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e05c",
+ "EventName": "PM_L2_TM_ST_ABORT_SISTER",
+ "BriefDescription": "TM marked store abort",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x23808a",
+ "EventName": "PM_L3_CINJ",
+ "BriefDescription": "l3 ci of cache inject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x128084",
+ "EventName": "PM_L3_CI_HIT",
+ "BriefDescription": "L3 Castins Hit (total count",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x128086",
+ "EventName": "PM_L3_CI_MISS",
+ "BriefDescription": "L3 castins miss (total count",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x819082",
+ "EventName": "PM_L3_CI_USAGE",
+ "BriefDescription": "rotating sample of 16 CI or CO actives",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x438088",
+ "EventName": "PM_L3_CO",
+ "BriefDescription": "l3 castout occurring ( does not include casthrough or log writes (cinj/dmaw)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x83908b",
+ "EventName": "PM_L3_CO0_ALLOC",
+ "BriefDescription": "lifetime, sample of CO machine 0 valid",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x83908a",
+ "EventName": "PM_L3_CO0_BUSY",
+ "BriefDescription": "lifetime, sample of CO machine 0 valid",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x28086",
+ "EventName": "PM_L3_CO_L31",
+ "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 ( lossy)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x238088",
+ "EventName": "PM_L3_CO_LCO",
+ "BriefDescription": "Total L3 castouts occurred on LCO",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x28084",
+ "EventName": "PM_L3_CO_MEM",
+ "BriefDescription": "L3 CO to memory OR of port 0 and 1 ( lossy)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb19082",
+ "EventName": "PM_L3_GRP_GUESS_CORRECT",
+ "BriefDescription": "Initial scope=group and data from same group (near) (pred successful)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb3908a",
+ "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
+ "BriefDescription": "Initial scope=group but data from local node. Predition too high",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb39088",
+ "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
+ "BriefDescription": "Initial scope=group but data from outside group (far or rem). Prediction too Low",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x218080",
+ "EventName": "PM_L3_HIT",
+ "BriefDescription": "L3 Hits",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x138088",
+ "EventName": "PM_L3_L2_CO_HIT",
+ "BriefDescription": "L2 castout hits",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x13808a",
+ "EventName": "PM_L3_L2_CO_MISS",
+ "BriefDescription": "L2 castout miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x14808c",
+ "EventName": "PM_L3_LAT_CI_HIT",
+ "BriefDescription": "L3 Lateral Castins Hit",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x14808e",
+ "EventName": "PM_L3_LAT_CI_MISS",
+ "BriefDescription": "L3 Lateral Castins Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x228084",
+ "EventName": "PM_L3_LD_HIT",
+ "BriefDescription": "L3 demand LD Hits",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x228086",
+ "EventName": "PM_L3_LD_MISS",
+ "BriefDescription": "L3 demand LD Miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e052",
+ "EventName": "PM_L3_LD_PREF",
+ "BriefDescription": "L3 Load Prefetches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb19080",
+ "EventName": "PM_L3_LOC_GUESS_CORRECT",
+ "BriefDescription": "initial scope=node/chip and data from local node (local) (pred successful)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb29086",
+ "EventName": "PM_L3_LOC_GUESS_WRONG",
+ "BriefDescription": "Initial scope=node but data from out side local node (near or far or rem). Prediction too Low",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x218082",
+ "EventName": "PM_L3_MISS",
+ "BriefDescription": "L3 Misses",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x54808c",
+ "EventName": "PM_L3_P0_CO_L31",
+ "BriefDescription": "l3 CO to L3.1 (lco) port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x538088",
+ "EventName": "PM_L3_P0_CO_MEM",
+ "BriefDescription": "l3 CO to memory port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x929084",
+ "EventName": "PM_L3_P0_CO_RTY",
+ "BriefDescription": "L3 CO received retry port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa29084",
+ "EventName": "PM_L3_P0_GRP_PUMP",
+ "BriefDescription": "L3 pf sent with grp scope port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x528084",
+ "EventName": "PM_L3_P0_LCO_DATA",
+ "BriefDescription": "lco sent with data port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x518080",
+ "EventName": "PM_L3_P0_LCO_NO_DATA",
+ "BriefDescription": "dataless l3 lco sent port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa4908c",
+ "EventName": "PM_L3_P0_LCO_RTY",
+ "BriefDescription": "L3 LCO received retry port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa19080",
+ "EventName": "PM_L3_P0_NODE_PUMP",
+ "BriefDescription": "L3 pf sent with nodal scope port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x919080",
+ "EventName": "PM_L3_P0_PF_RTY",
+ "BriefDescription": "L3 PF received retry port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x939088",
+ "EventName": "PM_L3_P0_SN_HIT",
+ "BriefDescription": "L3 snoop hit port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x118080",
+ "EventName": "PM_L3_P0_SN_INV",
+ "BriefDescription": "Port0 snooper detects someone doing a store to a line thats Sx",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x94908c",
+ "EventName": "PM_L3_P0_SN_MISS",
+ "BriefDescription": "L3 snoop miss port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa39088",
+ "EventName": "PM_L3_P0_SYS_PUMP",
+ "BriefDescription": "L3 pf sent with sys scope port 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x54808e",
+ "EventName": "PM_L3_P1_CO_L31",
+ "BriefDescription": "l3 CO to L3.1 (lco) port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x53808a",
+ "EventName": "PM_L3_P1_CO_MEM",
+ "BriefDescription": "l3 CO to memory port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x929086",
+ "EventName": "PM_L3_P1_CO_RTY",
+ "BriefDescription": "L3 CO received retry port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa29086",
+ "EventName": "PM_L3_P1_GRP_PUMP",
+ "BriefDescription": "L3 pf sent with grp scope port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x528086",
+ "EventName": "PM_L3_P1_LCO_DATA",
+ "BriefDescription": "lco sent with data port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x518082",
+ "EventName": "PM_L3_P1_LCO_NO_DATA",
+ "BriefDescription": "dataless l3 lco sent port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa4908e",
+ "EventName": "PM_L3_P1_LCO_RTY",
+ "BriefDescription": "L3 LCO received retry port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa19082",
+ "EventName": "PM_L3_P1_NODE_PUMP",
+ "BriefDescription": "L3 pf sent with nodal scope port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x919082",
+ "EventName": "PM_L3_P1_PF_RTY",
+ "BriefDescription": "L3 PF received retry port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x93908a",
+ "EventName": "PM_L3_P1_SN_HIT",
+ "BriefDescription": "L3 snoop hit port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x118082",
+ "EventName": "PM_L3_P1_SN_INV",
+ "BriefDescription": "Port1 snooper detects someone doing a store to a line thats Sx",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x94908e",
+ "EventName": "PM_L3_P1_SN_MISS",
+ "BriefDescription": "L3 snoop miss port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa3908a",
+ "EventName": "PM_L3_P1_SYS_PUMP",
+ "BriefDescription": "L3 pf sent with sys scope port 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x84908d",
+ "EventName": "PM_L3_PF0_ALLOC",
+ "BriefDescription": "lifetime, sample of PF machine 0 valid",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x84908c",
+ "EventName": "PM_L3_PF0_BUSY",
+ "BriefDescription": "lifetime, sample of PF machine 0 valid",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x428084",
+ "EventName": "PM_L3_PF_HIT_L3",
+ "BriefDescription": "l3 pf hit in l3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x18080",
+ "EventName": "PM_L3_PF_MISS_L3",
+ "BriefDescription": "L3 Prefetch missed in L3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3808a",
+ "EventName": "PM_L3_PF_OFF_CHIP_CACHE",
+ "BriefDescription": "L3 Prefetch from Off chip cache",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4808e",
+ "EventName": "PM_L3_PF_OFF_CHIP_MEM",
+ "BriefDescription": "L3 Prefetch from Off chip memory",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x38088",
+ "EventName": "PM_L3_PF_ON_CHIP_CACHE",
+ "BriefDescription": "L3 Prefetch from On chip cache",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4808c",
+ "EventName": "PM_L3_PF_ON_CHIP_MEM",
+ "BriefDescription": "L3 Prefetch from On chip memory",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x829084",
+ "EventName": "PM_L3_PF_USAGE",
+ "BriefDescription": "rotating sample of 32 PF actives",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e052",
+ "EventName": "PM_L3_PREF_ALL",
+ "BriefDescription": "Total HW L3 prefetches(Load+store)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x84908f",
+ "EventName": "PM_L3_RD0_ALLOC",
+ "BriefDescription": "lifetime, sample of RD machine 0 valid",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x84908e",
+ "EventName": "PM_L3_RD0_BUSY",
+ "BriefDescription": "lifetime, sample of RD machine 0 valid",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x829086",
+ "EventName": "PM_L3_RD_USAGE",
+ "BriefDescription": "rotating sample of 16 RD actives",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x839089",
+ "EventName": "PM_L3_SN0_ALLOC",
+ "BriefDescription": "lifetime, sample of snooper machine 0 valid",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x839088",
+ "EventName": "PM_L3_SN0_BUSY",
+ "BriefDescription": "lifetime, sample of snooper machine 0 valid",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x819080",
+ "EventName": "PM_L3_SN_USAGE",
+ "BriefDescription": "rotating sample of 8 snoop valids",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e052",
+ "EventName": "PM_L3_ST_PREF",
+ "BriefDescription": "L3 store Prefetches",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e052",
+ "EventName": "PM_L3_SW_PREF",
+ "BriefDescription": "Data stream touchto L3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb29084",
+ "EventName": "PM_L3_SYS_GUESS_CORRECT",
+ "BriefDescription": "Initial scope=system and data from outside group (far or rem)(pred successful)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb4908c",
+ "EventName": "PM_L3_SYS_GUESS_WRONG",
+ "BriefDescription": "Initial scope=system but data from local or near. Predction too high",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x24808e",
+ "EventName": "PM_L3_TRANS_PF",
+ "BriefDescription": "L3 Transient prefetch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x18081",
+ "EventName": "PM_L3_WI0_ALLOC",
+ "BriefDescription": "lifetime, sample of Write Inject machine 0 valid",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x418080",
+ "EventName": "PM_L3_WI0_BUSY",
+ "BriefDescription": "lifetime, sample of Write Inject machine 0 valid",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x418082",
+ "EventName": "PM_L3_WI_USAGE",
+ "BriefDescription": "rotating sample of 8 WI actives",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc080",
+ "EventName": "PM_LD_REF_L1_LSU0",
+ "BriefDescription": "LS0 L1 D cache load references counted at finish, gated by reject",
+ "PublicDescription": "LS0 L1 D cache load references counted at finish, gated by rejectLSU0 L1 D cache load references"
+ },
+ {,
+ "EventCode": "0xc082",
+ "EventName": "PM_LD_REF_L1_LSU1",
+ "BriefDescription": "LS1 L1 D cache load references counted at finish, gated by reject",
+ "PublicDescription": "LS1 L1 D cache load references counted at finish, gated by rejectLSU1 L1 D cache load references"
+ },
+ {,
+ "EventCode": "0xc094",
+ "EventName": "PM_LD_REF_L1_LSU2",
+ "BriefDescription": "LS2 L1 D cache load references counted at finish, gated by reject",
+ "PublicDescription": "LS2 L1 D cache load references counted at finish, gated by reject42"
+ },
+ {,
+ "EventCode": "0xc096",
+ "EventName": "PM_LD_REF_L1_LSU3",
+ "BriefDescription": "LS3 L1 D cache load references counted at finish, gated by reject",
+ "PublicDescription": "LS3 L1 D cache load references counted at finish, gated by reject42"
+ },
+ {,
+ "EventCode": "0x509a",
+ "EventName": "PM_LINK_STACK_INVALID_PTR",
+ "BriefDescription": "A flush were LS ptr is invalid, results in a pop , A lot of interrupts between push and pops",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5098",
+ "EventName": "PM_LINK_STACK_WRONG_ADD_PRED",
+ "BriefDescription": "Link stack predicts wrong address, because of link stack design limitation",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe080",
+ "EventName": "PM_LS0_ERAT_MISS_PREF",
+ "BriefDescription": "LS0 Erat miss due to prefetch",
+ "PublicDescription": "LS0 Erat miss due to prefetch42"
+ },
+ {,
+ "EventCode": "0xd0b8",
+ "EventName": "PM_LS0_L1_PREF",
+ "BriefDescription": "LS0 L1 cache data prefetches",
+ "PublicDescription": "LS0 L1 cache data prefetches42"
+ },
+ {,
+ "EventCode": "0xc098",
+ "EventName": "PM_LS0_L1_SW_PREF",
+ "BriefDescription": "Software L1 Prefetches, including SW Transient Prefetches",
+ "PublicDescription": "Software L1 Prefetches, including SW Transient Prefetches42"
+ },
+ {,
+ "EventCode": "0xe082",
+ "EventName": "PM_LS1_ERAT_MISS_PREF",
+ "BriefDescription": "LS1 Erat miss due to prefetch",
+ "PublicDescription": "LS1 Erat miss due to prefetch42"
+ },
+ {,
+ "EventCode": "0xd0ba",
+ "EventName": "PM_LS1_L1_PREF",
+ "BriefDescription": "LS1 L1 cache data prefetches",
+ "PublicDescription": "LS1 L1 cache data prefetches42"
+ },
+ {,
+ "EventCode": "0xc09a",
+ "EventName": "PM_LS1_L1_SW_PREF",
+ "BriefDescription": "Software L1 Prefetches, including SW Transient Prefetches",
+ "PublicDescription": "Software L1 Prefetches, including SW Transient Prefetches42"
+ },
+ {,
+ "EventCode": "0xc0b0",
+ "EventName": "PM_LSU0_FLUSH_LRQ",
+ "BriefDescription": "LS0 Flush: LRQ",
+ "PublicDescription": "LS0 Flush: LRQLSU0 LRQ flushes"
+ },
+ {,
+ "EventCode": "0xc0b8",
+ "EventName": "PM_LSU0_FLUSH_SRQ",
+ "BriefDescription": "LS0 Flush: SRQ",
+ "PublicDescription": "LS0 Flush: SRQLSU0 SRQ lhs flushes"
+ },
+ {,
+ "EventCode": "0xc0a4",
+ "EventName": "PM_LSU0_FLUSH_ULD",
+ "BriefDescription": "LS0 Flush: Unaligned Load",
+ "PublicDescription": "LS0 Flush: Unaligned LoadLSU0 unaligned load flushes"
+ },
+ {,
+ "EventCode": "0xc0ac",
+ "EventName": "PM_LSU0_FLUSH_UST",
+ "BriefDescription": "LS0 Flush: Unaligned Store",
+ "PublicDescription": "LS0 Flush: Unaligned StoreLSU0 unaligned store flushes"
+ },
+ {,
+ "EventCode": "0xf088",
+ "EventName": "PM_LSU0_L1_CAM_CANCEL",
+ "BriefDescription": "ls0 l1 tm cam cancel",
+ "PublicDescription": "ls0 l1 tm cam cancel42"
+ },
+ {,
+ "EventCode": "0x1e056",
+ "EventName": "PM_LSU0_LARX_FIN",
+ "BriefDescription": "Larx finished in LSU pipe0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd08c",
+ "EventName": "PM_LSU0_LMQ_LHR_MERGE",
+ "BriefDescription": "LS0 Load Merged with another cacheline request",
+ "PublicDescription": "LS0 Load Merged with another cacheline request42"
+ },
+ {,
+ "EventCode": "0xc08c",
+ "EventName": "PM_LSU0_NCLD",
+ "BriefDescription": "LS0 Non-cachable Loads counted at finish",
+ "PublicDescription": "LS0 Non-cachable Loads counted at finishLSU0 non-cacheable loads"
+ },
+ {,
+ "EventCode": "0xe090",
+ "EventName": "PM_LSU0_PRIMARY_ERAT_HIT",
+ "BriefDescription": "Primary ERAT hit",
+ "PublicDescription": "Primary ERAT hit42"
+ },
+ {,
+ "EventCode": "0x1e05a",
+ "EventName": "PM_LSU0_REJECT",
+ "BriefDescription": "LSU0 reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc09c",
+ "EventName": "PM_LSU0_SRQ_STFWD",
+ "BriefDescription": "LS0 SRQ forwarded data to a load",
+ "PublicDescription": "LS0 SRQ forwarded data to a loadLSU0 SRQ store forwarded"
+ },
+ {,
+ "EventCode": "0xf084",
+ "EventName": "PM_LSU0_STORE_REJECT",
+ "BriefDescription": "ls0 store reject",
+ "PublicDescription": "ls0 store reject42"
+ },
+ {,
+ "EventCode": "0xe0a8",
+ "EventName": "PM_LSU0_TMA_REQ_L2",
+ "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding",
+ "PublicDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding42"
+ },
+ {,
+ "EventCode": "0xe098",
+ "EventName": "PM_LSU0_TM_L1_HIT",
+ "BriefDescription": "Load tm hit in L1",
+ "PublicDescription": "Load tm hit in L142"
+ },
+ {,
+ "EventCode": "0xe0a0",
+ "EventName": "PM_LSU0_TM_L1_MISS",
+ "BriefDescription": "Load tm L1 miss",
+ "PublicDescription": "Load tm L1 miss42"
+ },
+ {,
+ "EventCode": "0xc0b2",
+ "EventName": "PM_LSU1_FLUSH_LRQ",
+ "BriefDescription": "LS1 Flush: LRQ",
+ "PublicDescription": "LS1 Flush: LRQLSU1 LRQ flushes"
+ },
+ {,
+ "EventCode": "0xc0ba",
+ "EventName": "PM_LSU1_FLUSH_SRQ",
+ "BriefDescription": "LS1 Flush: SRQ",
+ "PublicDescription": "LS1 Flush: SRQLSU1 SRQ lhs flushes"
+ },
+ {,
+ "EventCode": "0xc0a6",
+ "EventName": "PM_LSU1_FLUSH_ULD",
+ "BriefDescription": "LS 1 Flush: Unaligned Load",
+ "PublicDescription": "LS 1 Flush: Unaligned LoadLSU1 unaligned load flushes"
+ },
+ {,
+ "EventCode": "0xc0ae",
+ "EventName": "PM_LSU1_FLUSH_UST",
+ "BriefDescription": "LS1 Flush: Unaligned Store",
+ "PublicDescription": "LS1 Flush: Unaligned StoreLSU1 unaligned store flushes"
+ },
+ {,
+ "EventCode": "0xf08a",
+ "EventName": "PM_LSU1_L1_CAM_CANCEL",
+ "BriefDescription": "ls1 l1 tm cam cancel",
+ "PublicDescription": "ls1 l1 tm cam cancel42"
+ },
+ {,
+ "EventCode": "0x2e056",
+ "EventName": "PM_LSU1_LARX_FIN",
+ "BriefDescription": "Larx finished in LSU pipe1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd08e",
+ "EventName": "PM_LSU1_LMQ_LHR_MERGE",
+ "BriefDescription": "LS1 Load Merge with another cacheline request",
+ "PublicDescription": "LS1 Load Merge with another cacheline request42"
+ },
+ {,
+ "EventCode": "0xc08e",
+ "EventName": "PM_LSU1_NCLD",
+ "BriefDescription": "LS1 Non-cachable Loads counted at finish",
+ "PublicDescription": "LS1 Non-cachable Loads counted at finishLSU1 non-cacheable loads"
+ },
+ {,
+ "EventCode": "0xe092",
+ "EventName": "PM_LSU1_PRIMARY_ERAT_HIT",
+ "BriefDescription": "Primary ERAT hit",
+ "PublicDescription": "Primary ERAT hit42"
+ },
+ {,
+ "EventCode": "0x2e05a",
+ "EventName": "PM_LSU1_REJECT",
+ "BriefDescription": "LSU1 reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc09e",
+ "EventName": "PM_LSU1_SRQ_STFWD",
+ "BriefDescription": "LS1 SRQ forwarded data to a load",
+ "PublicDescription": "LS1 SRQ forwarded data to a loadLSU1 SRQ store forwarded"
+ },
+ {,
+ "EventCode": "0xf086",
+ "EventName": "PM_LSU1_STORE_REJECT",
+ "BriefDescription": "ls1 store reject",
+ "PublicDescription": "ls1 store reject42"
+ },
+ {,
+ "EventCode": "0xe0aa",
+ "EventName": "PM_LSU1_TMA_REQ_L2",
+ "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding",
+ "PublicDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding42"
+ },
+ {,
+ "EventCode": "0xe09a",
+ "EventName": "PM_LSU1_TM_L1_HIT",
+ "BriefDescription": "Load tm hit in L1",
+ "PublicDescription": "Load tm hit in L142"
+ },
+ {,
+ "EventCode": "0xe0a2",
+ "EventName": "PM_LSU1_TM_L1_MISS",
+ "BriefDescription": "Load tm L1 miss",
+ "PublicDescription": "Load tm L1 miss42"
+ },
+ {,
+ "EventCode": "0xc0b4",
+ "EventName": "PM_LSU2_FLUSH_LRQ",
+ "BriefDescription": "LS02Flush: LRQ",
+ "PublicDescription": "LS02Flush: LRQ42"
+ },
+ {,
+ "EventCode": "0xc0bc",
+ "EventName": "PM_LSU2_FLUSH_SRQ",
+ "BriefDescription": "LS2 Flush: SRQ",
+ "PublicDescription": "LS2 Flush: SRQ42"
+ },
+ {,
+ "EventCode": "0xc0a8",
+ "EventName": "PM_LSU2_FLUSH_ULD",
+ "BriefDescription": "LS3 Flush: Unaligned Load",
+ "PublicDescription": "LS3 Flush: Unaligned Load42"
+ },
+ {,
+ "EventCode": "0xf08c",
+ "EventName": "PM_LSU2_L1_CAM_CANCEL",
+ "BriefDescription": "ls2 l1 tm cam cancel",
+ "PublicDescription": "ls2 l1 tm cam cancel42"
+ },
+ {,
+ "EventCode": "0x3e056",
+ "EventName": "PM_LSU2_LARX_FIN",
+ "BriefDescription": "Larx finished in LSU pipe2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc084",
+ "EventName": "PM_LSU2_LDF",
+ "BriefDescription": "LS2 Scalar Loads",
+ "PublicDescription": "LS2 Scalar Loads42"
+ },
+ {,
+ "EventCode": "0xc088",
+ "EventName": "PM_LSU2_LDX",
+ "BriefDescription": "LS0 Vector Loads",
+ "PublicDescription": "LS0 Vector Loads42"
+ },
+ {,
+ "EventCode": "0xd090",
+ "EventName": "PM_LSU2_LMQ_LHR_MERGE",
+ "BriefDescription": "LS0 Load Merged with another cacheline request",
+ "PublicDescription": "LS0 Load Merged with another cacheline request42"
+ },
+ {,
+ "EventCode": "0xe094",
+ "EventName": "PM_LSU2_PRIMARY_ERAT_HIT",
+ "BriefDescription": "Primary ERAT hit",
+ "PublicDescription": "Primary ERAT hit42"
+ },
+ {,
+ "EventCode": "0x3e05a",
+ "EventName": "PM_LSU2_REJECT",
+ "BriefDescription": "LSU2 reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc0a0",
+ "EventName": "PM_LSU2_SRQ_STFWD",
+ "BriefDescription": "LS2 SRQ forwarded data to a load",
+ "PublicDescription": "LS2 SRQ forwarded data to a load42"
+ },
+ {,
+ "EventCode": "0xe0ac",
+ "EventName": "PM_LSU2_TMA_REQ_L2",
+ "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding",
+ "PublicDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding42"
+ },
+ {,
+ "EventCode": "0xe09c",
+ "EventName": "PM_LSU2_TM_L1_HIT",
+ "BriefDescription": "Load tm hit in L1",
+ "PublicDescription": "Load tm hit in L142"
+ },
+ {,
+ "EventCode": "0xe0a4",
+ "EventName": "PM_LSU2_TM_L1_MISS",
+ "BriefDescription": "Load tm L1 miss",
+ "PublicDescription": "Load tm L1 miss42"
+ },
+ {,
+ "EventCode": "0xc0b6",
+ "EventName": "PM_LSU3_FLUSH_LRQ",
+ "BriefDescription": "LS3 Flush: LRQ",
+ "PublicDescription": "LS3 Flush: LRQ42"
+ },
+ {,
+ "EventCode": "0xc0be",
+ "EventName": "PM_LSU3_FLUSH_SRQ",
+ "BriefDescription": "LS13 Flush: SRQ",
+ "PublicDescription": "LS13 Flush: SRQ42"
+ },
+ {,
+ "EventCode": "0xc0aa",
+ "EventName": "PM_LSU3_FLUSH_ULD",
+ "BriefDescription": "LS 14Flush: Unaligned Load",
+ "PublicDescription": "LS 14Flush: Unaligned Load42"
+ },
+ {,
+ "EventCode": "0xf08e",
+ "EventName": "PM_LSU3_L1_CAM_CANCEL",
+ "BriefDescription": "ls3 l1 tm cam cancel",
+ "PublicDescription": "ls3 l1 tm cam cancel42"
+ },
+ {,
+ "EventCode": "0x4e056",
+ "EventName": "PM_LSU3_LARX_FIN",
+ "BriefDescription": "Larx finished in LSU pipe3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc086",
+ "EventName": "PM_LSU3_LDF",
+ "BriefDescription": "LS3 Scalar Loads",
+ "PublicDescription": "LS3 Scalar Loads 42"
+ },
+ {,
+ "EventCode": "0xc08a",
+ "EventName": "PM_LSU3_LDX",
+ "BriefDescription": "LS1 Vector Loads",
+ "PublicDescription": "LS1 Vector Loads42"
+ },
+ {,
+ "EventCode": "0xd092",
+ "EventName": "PM_LSU3_LMQ_LHR_MERGE",
+ "BriefDescription": "LS1 Load Merge with another cacheline request",
+ "PublicDescription": "LS1 Load Merge with another cacheline request42"
+ },
+ {,
+ "EventCode": "0xe096",
+ "EventName": "PM_LSU3_PRIMARY_ERAT_HIT",
+ "BriefDescription": "Primary ERAT hit",
+ "PublicDescription": "Primary ERAT hit42"
+ },
+ {,
+ "EventCode": "0x4e05a",
+ "EventName": "PM_LSU3_REJECT",
+ "BriefDescription": "LSU3 reject",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc0a2",
+ "EventName": "PM_LSU3_SRQ_STFWD",
+ "BriefDescription": "LS3 SRQ forwarded data to a load",
+ "PublicDescription": "LS3 SRQ forwarded data to a load42"
+ },
+ {,
+ "EventCode": "0xe0ae",
+ "EventName": "PM_LSU3_TMA_REQ_L2",
+ "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding",
+ "PublicDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding42"
+ },
+ {,
+ "EventCode": "0xe09e",
+ "EventName": "PM_LSU3_TM_L1_HIT",
+ "BriefDescription": "Load tm hit in L1",
+ "PublicDescription": "Load tm hit in L142"
+ },
+ {,
+ "EventCode": "0xe0a6",
+ "EventName": "PM_LSU3_TM_L1_MISS",
+ "BriefDescription": "Load tm L1 miss",
+ "PublicDescription": "Load tm L1 miss42"
+ },
+ {,
+ "EventCode": "0xe880",
+ "EventName": "PM_LSU_ERAT_MISS_PREF",
+ "BriefDescription": "Erat miss due to prefetch, on either pipe",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xc8ac",
+ "EventName": "PM_LSU_FLUSH_UST",
+ "BriefDescription": "Unaligned Store Flush on either pipe",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xd0a4",
+ "EventName": "PM_LSU_FOUR_TABLEWALK_CYC",
+ "BriefDescription": "Cycles when four tablewalks pending on this thread",
+ "PublicDescription": "Cycles when four tablewalks pending on this thread42"
+ },
+ {,
+ "EventCode": "0x10066",
+ "EventName": "PM_LSU_FX_FIN",
+ "BriefDescription": "LSU Finished a FX operation (up to 2 per cycle",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd8b8",
+ "EventName": "PM_LSU_L1_PREF",
+ "BriefDescription": "hw initiated , include sw streaming forms as well , include sw streams as a separate event",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xc898",
+ "EventName": "PM_LSU_L1_SW_PREF",
+ "BriefDescription": "Software L1 Prefetches, including SW Transient Prefetches, on both pipes",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xc884",
+ "EventName": "PM_LSU_LDF",
+ "BriefDescription": "FPU loads only on LS2/LS3 ie LU0/LU1",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xc888",
+ "EventName": "PM_LSU_LDX",
+ "BriefDescription": "Vector loads can issue only on LS2/LS3",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xd0a2",
+ "EventName": "PM_LSU_LMQ_FULL_CYC",
+ "BriefDescription": "LMQ full",
+ "PublicDescription": "LMQ fullCycles LMQ full"
+ },
+ {,
+ "EventCode": "0xd0a1",
+ "EventName": "PM_LSU_LMQ_S0_ALLOC",
+ "BriefDescription": "Per thread - use edge detect to count allocates On a per thread basis, level signal indicating Slot 0 is valid. By instrumenting a single slot we can calculate service time for that slot. Previous machines required a separate signal indicating the slot was allocated. Because any signal can be routed to any counter in P8, we can count level in one PMC and edge detect in another PMC using the same signal",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xd0a0",
+ "EventName": "PM_LSU_LMQ_S0_VALID",
+ "BriefDescription": "Slot 0 of LMQ valid",
+ "PublicDescription": "Slot 0 of LMQ validLMQ slot 0 valid"
+ },
+ {,
+ "EventCode": "0x3001c",
+ "EventName": "PM_LSU_LMQ_SRQ_EMPTY_ALL_CYC",
+ "BriefDescription": "ALL threads lsu empty (lmq and srq empty)",
+ "PublicDescription": "ALL threads lsu empty (lmq and srq empty). Issue HW016541"
+ },
+ {,
+ "EventCode": "0xd09f",
+ "EventName": "PM_LSU_LRQ_S0_ALLOC",
+ "BriefDescription": "Per thread - use edge detect to count allocates On a per thread basis, level signal indicating Slot 0 is valid. By instrumenting a single slot we can calculate service time for that slot. Previous machines required a separate signal indicating the slot was allocated. Because any signal can be routed to any counter in P8, we can count level in one PMC and edge detect in another PMC using the same signal",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xd09e",
+ "EventName": "PM_LSU_LRQ_S0_VALID",
+ "BriefDescription": "Slot 0 of LRQ valid",
+ "PublicDescription": "Slot 0 of LRQ validLRQ slot 0 valid"
+ },
+ {,
+ "EventCode": "0xf091",
+ "EventName": "PM_LSU_LRQ_S43_ALLOC",
+ "BriefDescription": "LRQ slot 43 was released",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xf090",
+ "EventName": "PM_LSU_LRQ_S43_VALID",
+ "BriefDescription": "LRQ slot 43 was busy",
+ "PublicDescription": "LRQ slot 43 was busy42"
+ },
+ {,
+ "EventCode": "0x30162",
+ "EventName": "PM_LSU_MRK_DERAT_MISS",
+ "BriefDescription": "DERAT Reloaded (Miss)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc88c",
+ "EventName": "PM_LSU_NCLD",
+ "BriefDescription": "count at finish so can return only on ls0 or ls1",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xc092",
+ "EventName": "PM_LSU_NCST",
+ "BriefDescription": "Non-cachable Stores sent to nest",
+ "PublicDescription": "Non-cachable Stores sent to nest42"
+ },
+ {,
+ "EventCode": "0x10064",
+ "EventName": "PM_LSU_REJECT",
+ "BriefDescription": "LSU Reject (up to 4 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd082",
+ "EventName": "PM_LSU_SET_MPRED",
+ "BriefDescription": "Line already in cache at reload time",
+ "PublicDescription": "Line already in cache at reload time42"
+ },
+ {,
+ "EventCode": "0x40008",
+ "EventName": "PM_LSU_SRQ_EMPTY_CYC",
+ "BriefDescription": "ALL threads srq empty",
+ "PublicDescription": "All threads srq empty"
+ },
+ {,
+ "EventCode": "0xd09d",
+ "EventName": "PM_LSU_SRQ_S0_ALLOC",
+ "BriefDescription": "Per thread - use edge detect to count allocates On a per thread basis, level signal indicating Slot 0 is valid. By instrumenting a single slot we can calculate service time for that slot. Previous machines required a separate signal indicating the slot was allocated. Because any signal can be routed to any counter in P8, we can count level in one PMC and edge detect in another PMC using the same signal",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xd09c",
+ "EventName": "PM_LSU_SRQ_S0_VALID",
+ "BriefDescription": "Slot 0 of SRQ valid",
+ "PublicDescription": "Slot 0 of SRQ validSRQ slot 0 valid"
+ },
+ {,
+ "EventCode": "0xf093",
+ "EventName": "PM_LSU_SRQ_S39_ALLOC",
+ "BriefDescription": "SRQ slot 39 was released",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xf092",
+ "EventName": "PM_LSU_SRQ_S39_VALID",
+ "BriefDescription": "SRQ slot 39 was busy",
+ "PublicDescription": "SRQ slot 39 was busy42"
+ },
+ {,
+ "EventCode": "0xd09b",
+ "EventName": "PM_LSU_SRQ_SYNC",
+ "BriefDescription": "A sync in the SRQ ended",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0xd09a",
+ "EventName": "PM_LSU_SRQ_SYNC_CYC",
+ "BriefDescription": "A sync is in the SRQ (edge detect to count)",
+ "PublicDescription": "A sync is in the SRQ (edge detect to count)SRQ sync duration"
+ },
+ {,
+ "EventCode": "0xf084",
+ "EventName": "PM_LSU_STORE_REJECT",
+ "BriefDescription": "Store reject on either pipe",
+ "PublicDescription": "LSU"
+ },
+ {,
+ "EventCode": "0xd0a6",
+ "EventName": "PM_LSU_TWO_TABLEWALK_CYC",
+ "BriefDescription": "Cycles when two tablewalks pending on this thread",
+ "PublicDescription": "Cycles when two tablewalks pending on this thread42"
+ },
+ {,
+ "EventCode": "0x5094",
+ "EventName": "PM_LWSYNC",
+ "BriefDescription": "threaded version, IC Misses where we got EA dir hit but no sector valids were on. ICBI took line out",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x209a",
+ "EventName": "PM_LWSYNC_HELD",
+ "BriefDescription": "LWSYNC held at dispatch",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3013a",
+ "EventName": "PM_MRK_CRU_FIN",
+ "BriefDescription": "IFU non-branch finished",
+ "PublicDescription": "IFU non-branch marked instruction finished"
+ },
+ {,
+ "EventCode": "0x4d146",
+ "EventName": "PM_MRK_DATA_FROM_L21_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d126",
+ "EventName": "PM_MRK_DATA_FROM_L21_MOD_CYC",
+ "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's L2 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d146",
+ "EventName": "PM_MRK_DATA_FROM_L21_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c126",
+ "EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC",
+ "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d144",
+ "EventName": "PM_MRK_DATA_FROM_L31_ECO_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d124",
+ "EventName": "PM_MRK_DATA_FROM_L31_ECO_MOD_CYC",
+ "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d144",
+ "EventName": "PM_MRK_DATA_FROM_L31_ECO_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c124",
+ "EventName": "PM_MRK_DATA_FROM_L31_ECO_SHR_CYC",
+ "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's ECO L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d144",
+ "EventName": "PM_MRK_DATA_FROM_L31_MOD",
+ "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d124",
+ "EventName": "PM_MRK_DATA_FROM_L31_MOD_CYC",
+ "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d146",
+ "EventName": "PM_MRK_DATA_FROM_L31_SHR",
+ "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c126",
+ "EventName": "PM_MRK_DATA_FROM_L31_SHR_CYC",
+ "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x201e0",
+ "EventName": "PM_MRK_DATA_FROM_MEM",
+ "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a marked load",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f146",
+ "EventName": "PM_MRK_DPTEG_FROM_L21_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f146",
+ "EventName": "PM_MRK_DPTEG_FROM_L21_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f140",
+ "EventName": "PM_MRK_DPTEG_FROM_L2_DISP_CONFLICT_LDHITST",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with load hit store conflict due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f140",
+ "EventName": "PM_MRK_DPTEG_FROM_L2_DISP_CONFLICT_OTHER",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 with dispatch conflict due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f144",
+ "EventName": "PM_MRK_DPTEG_FROM_L31_ECO_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3f144",
+ "EventName": "PM_MRK_DPTEG_FROM_L31_ECO_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2f144",
+ "EventName": "PM_MRK_DPTEG_FROM_L31_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1f146",
+ "EventName": "PM_MRK_DPTEG_FROM_L31_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a marked data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30156",
+ "EventName": "PM_MRK_FAB_RSP_MATCH",
+ "BriefDescription": "ttype and cresp matched as specified in MMCR1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4f152",
+ "EventName": "PM_MRK_FAB_RSP_MATCH_CYC",
+ "BriefDescription": "cresp/ttype match cycles",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2013c",
+ "EventName": "PM_MRK_FILT_MATCH",
+ "BriefDescription": "Marked filter Match",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1013c",
+ "EventName": "PM_MRK_FIN_STALL_CYC",
+ "BriefDescription": "Marked instruction Finish Stall cycles (marked finish after NTC) (use edge detect to count )",
+ "PublicDescription": "Marked instruction Finish Stall cycles (marked finish after NTC) (use edge detect to count #)"
+ },
+ {,
+ "EventCode": "0x40130",
+ "EventName": "PM_MRK_GRP_CMPL",
+ "BriefDescription": "marked instruction finished (completed)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4013a",
+ "EventName": "PM_MRK_GRP_IC_MISS",
+ "BriefDescription": "Marked Group experienced I cache miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3013c",
+ "EventName": "PM_MRK_GRP_NTC",
+ "BriefDescription": "Marked group ntc cycles",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1013f",
+ "EventName": "PM_MRK_LD_MISS_EXPOSED",
+ "BriefDescription": "Marked Load exposed Miss (exposed period ended)",
+ "PublicDescription": "Marked Load exposed Miss (use edge detect to count #)"
+ },
+ {,
+ "EventCode": "0xd180",
+ "EventName": "PM_MRK_LSU_FLUSH",
+ "BriefDescription": "Flush: (marked) : All Cases",
+ "PublicDescription": "Flush: (marked) : All Cases42"
+ },
+ {,
+ "EventCode": "0xd188",
+ "EventName": "PM_MRK_LSU_FLUSH_LRQ",
+ "BriefDescription": "Flush: (marked) LRQ",
+ "PublicDescription": "Flush: (marked) LRQMarked LRQ flushes"
+ },
+ {,
+ "EventCode": "0xd18a",
+ "EventName": "PM_MRK_LSU_FLUSH_SRQ",
+ "BriefDescription": "Flush: (marked) SRQ",
+ "PublicDescription": "Flush: (marked) SRQMarked SRQ lhs flushes"
+ },
+ {,
+ "EventCode": "0xd184",
+ "EventName": "PM_MRK_LSU_FLUSH_ULD",
+ "BriefDescription": "Flush: (marked) Unaligned Load",
+ "PublicDescription": "Flush: (marked) Unaligned LoadMarked unaligned load flushes"
+ },
+ {,
+ "EventCode": "0xd186",
+ "EventName": "PM_MRK_LSU_FLUSH_UST",
+ "BriefDescription": "Flush: (marked) Unaligned Store",
+ "PublicDescription": "Flush: (marked) Unaligned StoreMarked unaligned store flushes"
+ },
+ {,
+ "EventCode": "0x40164",
+ "EventName": "PM_MRK_LSU_REJECT",
+ "BriefDescription": "LSU marked reject (up to 2 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30164",
+ "EventName": "PM_MRK_LSU_REJECT_ERAT_MISS",
+ "BriefDescription": "LSU marked reject due to ERAT (up to 2 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d15a",
+ "EventName": "PM_MRK_SRC_PREF_TRACK_EFF",
+ "BriefDescription": "Marked src pref track was effective",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d15a",
+ "EventName": "PM_MRK_SRC_PREF_TRACK_INEFF",
+ "BriefDescription": "Prefetch tracked was ineffective for marked src",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d15c",
+ "EventName": "PM_MRK_SRC_PREF_TRACK_MOD",
+ "BriefDescription": "Prefetch tracked was moderate for marked src",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1d15c",
+ "EventName": "PM_MRK_SRC_PREF_TRACK_MOD_L2",
+ "BriefDescription": "Marked src Prefetch Tracked was moderate (source L2)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3d15c",
+ "EventName": "PM_MRK_SRC_PREF_TRACK_MOD_L3",
+ "BriefDescription": "Prefetch tracked was moderate (L3 hit) for marked src",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1c15a",
+ "EventName": "PM_MRK_TGT_PREF_TRACK_EFF",
+ "BriefDescription": "Marked target pref track was effective",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3c15a",
+ "EventName": "PM_MRK_TGT_PREF_TRACK_INEFF",
+ "BriefDescription": "Prefetch tracked was ineffective for marked target",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c15c",
+ "EventName": "PM_MRK_TGT_PREF_TRACK_MOD",
+ "BriefDescription": "Prefetch tracked was moderate for marked target",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1c15c",
+ "EventName": "PM_MRK_TGT_PREF_TRACK_MOD_L2",
+ "BriefDescription": "Marked target Prefetch Tracked was moderate (source L2)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3c15c",
+ "EventName": "PM_MRK_TGT_PREF_TRACK_MOD_L3",
+ "BriefDescription": "Prefetch tracked was moderate (L3 hit) for marked target",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20b0",
+ "EventName": "PM_NESTED_TEND",
+ "BriefDescription": "Completion time nested tend",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20b6",
+ "EventName": "PM_NON_FAV_TBEGIN",
+ "BriefDescription": "Dispatch time non favored tbegin",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x328084",
+ "EventName": "PM_NON_TM_RST_SC",
+ "BriefDescription": "non tm snp rst tm sc",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2001a",
+ "EventName": "PM_NTCG_ALL_FIN",
+ "BriefDescription": "Cycles after all instructions have finished to group completed",
+ "PublicDescription": "Ccycles after all instructions have finished to group completed"
+ },
+ {,
+ "EventCode": "0x20ac",
+ "EventName": "PM_OUTER_TBEGIN",
+ "BriefDescription": "Completion time outer tbegin",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20ae",
+ "EventName": "PM_OUTER_TEND",
+ "BriefDescription": "Completion time outer tend",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2005a",
+ "EventName": "PM_PREF_TRACKED",
+ "BriefDescription": "Total number of Prefetch Operations that were tracked",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1005a",
+ "EventName": "PM_PREF_TRACK_EFF",
+ "BriefDescription": "Prefetch Tracked was effective",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3005a",
+ "EventName": "PM_PREF_TRACK_INEFF",
+ "BriefDescription": "Prefetch tracked was ineffective",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4005a",
+ "EventName": "PM_PREF_TRACK_MOD",
+ "BriefDescription": "Prefetch tracked was moderate",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1005c",
+ "EventName": "PM_PREF_TRACK_MOD_L2",
+ "BriefDescription": "Prefetch Tracked was moderate (source L2)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3005c",
+ "EventName": "PM_PREF_TRACK_MOD_L3",
+ "BriefDescription": "Prefetch tracked was moderate (L3)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe084",
+ "EventName": "PM_PTE_PREFETCH",
+ "BriefDescription": "PTE prefetches",
+ "PublicDescription": "PTE prefetches42"
+ },
+ {,
+ "EventCode": "0x16081",
+ "EventName": "PM_RC0_ALLOC",
+ "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x16080",
+ "EventName": "PM_RC0_BUSY",
+ "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200301ea",
+ "EventName": "PM_RC_LIFETIME_EXC_1024",
+ "BriefDescription": "Number of times the RC machine for a sampled instruction was active for more than 1024 cycles",
+ "PublicDescription": "Reload latency exceeded 1024 cyc"
+ },
+ {,
+ "EventCode": "0x200401ec",
+ "EventName": "PM_RC_LIFETIME_EXC_2048",
+ "BriefDescription": "Number of times the RC machine for a sampled instruction was active for more than 2048 cycles",
+ "PublicDescription": "Threshold counter exceeded a value of 2048"
+ },
+ {,
+ "EventCode": "0x200101e8",
+ "EventName": "PM_RC_LIFETIME_EXC_256",
+ "BriefDescription": "Number of times the RC machine for a sampled instruction was active for more than 256 cycles",
+ "PublicDescription": "Threshold counter exceed a count of 256"
+ },
+ {,
+ "EventCode": "0x200201e6",
+ "EventName": "PM_RC_LIFETIME_EXC_32",
+ "BriefDescription": "Number of times the RC machine for a sampled instruction was active for more than 32 cycles",
+ "PublicDescription": "Reload latency exceeded 32 cyc"
+ },
+ {,
+ "EventCode": "0x36088",
+ "EventName": "PM_RC_USAGE",
+ "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 RC machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x34808e",
+ "EventName": "PM_RD_CLEARING_SC",
+ "BriefDescription": "rd clearing sc",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x34808c",
+ "EventName": "PM_RD_FORMING_SC",
+ "BriefDescription": "rd forming sc",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x428086",
+ "EventName": "PM_RD_HIT_PF",
+ "BriefDescription": "rd machine hit l3 pf machine",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20004",
+ "EventName": "PM_REAL_SRQ_FULL",
+ "BriefDescription": "Out of real srq entries",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2006a",
+ "EventName": "PM_RUN_CYC_SMT2_SHRD_MODE",
+ "BriefDescription": "cycles this threads run latch is set and the core is in SMT2 shared mode",
+ "PublicDescription": "Cycles run latch is set and core is in SMT2-shared mode"
+ },
+ {,
+ "EventCode": "0x1006a",
+ "EventName": "PM_RUN_CYC_SMT2_SPLIT_MODE",
+ "BriefDescription": "Cycles run latch is set and core is in SMT2-split mode",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4006c",
+ "EventName": "PM_RUN_CYC_SMT8_MODE",
+ "BriefDescription": "Cycles run latch is set and core is in SMT8 mode",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xf082",
+ "EventName": "PM_SEC_ERAT_HIT",
+ "BriefDescription": "secondary ERAT Hit",
+ "PublicDescription": "secondary ERAT Hit42"
+ },
+ {,
+ "EventCode": "0x508c",
+ "EventName": "PM_SHL_CREATED",
+ "BriefDescription": "Store-Hit-Load Table Entry Created",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x508e",
+ "EventName": "PM_SHL_ST_CONVERT",
+ "BriefDescription": "Store-Hit-Load Table Read Hit with entry Enabled",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5090",
+ "EventName": "PM_SHL_ST_DISABLE",
+ "BriefDescription": "Store-Hit-Load Table Read Hit with entry Disabled (entry was disabled due to the entry shown to not prevent the flush)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x26085",
+ "EventName": "PM_SN0_ALLOC",
+ "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": "0.0"
+ },
+ {,
+ "EventCode": "0x26084",
+ "EventName": "PM_SN0_BUSY",
+ "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xd0b2",
+ "EventName": "PM_SNOOP_TLBIE",
+ "BriefDescription": "TLBIE snoop",
+ "PublicDescription": "TLBIE snoopSnoop TLBIE"
+ },
+ {,
+ "EventCode": "0x338088",
+ "EventName": "PM_SNP_TM_HIT_M",
+ "BriefDescription": "snp tm st hit m mu",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x33808a",
+ "EventName": "PM_SNP_TM_HIT_T",
+ "BriefDescription": "snp tm_st_hit t tn te",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4608c",
+ "EventName": "PM_SN_USAGE",
+ "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10028",
+ "EventName": "PM_STALL_END_GCT_EMPTY",
+ "BriefDescription": "Count ended because GCT went empty",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xc090",
+ "EventName": "PM_STCX_LSU",
+ "BriefDescription": "STCX executed reported at sent to nest",
+ "PublicDescription": "STCX executed reported at sent to nest42"
+ },
+ {,
+ "EventCode": "0x717080",
+ "EventName": "PM_ST_CAUSED_FAIL",
+ "BriefDescription": "Non TM St caused any thread to fail",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3090",
+ "EventName": "PM_SWAP_CANCEL",
+ "BriefDescription": "SWAP cancel , rtag not available",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3092",
+ "EventName": "PM_SWAP_CANCEL_GPR",
+ "BriefDescription": "SWAP cancel , rtag not available for gpr",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x308c",
+ "EventName": "PM_SWAP_COMPLETE",
+ "BriefDescription": "swap cast in completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x308e",
+ "EventName": "PM_SWAP_COMPLETE_GPR",
+ "BriefDescription": "swap cast in completed fpr gpr",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe086",
+ "EventName": "PM_TABLEWALK_CYC_PREF",
+ "BriefDescription": "tablewalk qualified for pte prefetches",
+ "PublicDescription": "tablewalk qualified for pte prefetches42"
+ },
+ {,
+ "EventCode": "0x20b2",
+ "EventName": "PM_TABORT_TRECLAIM",
+ "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe0ba",
+ "EventName": "PM_TEND_PEND_CYC",
+ "BriefDescription": "TEND latency per thread",
+ "PublicDescription": "TEND latency per thread42"
+ },
+ {,
+ "EventCode": "0x10012",
+ "EventName": "PM_THRD_GRP_CMPL_BOTH_CYC",
+ "BriefDescription": "Cycles group completed on both completion slots by any thread",
+ "PublicDescription": "Two threads finished same cycle (gated by run latch)"
+ },
+ {,
+ "EventCode": "0x40bc",
+ "EventName": "PM_THRD_PRIO_0_1_CYC",
+ "BriefDescription": "Cycles thread running at priority level 0 or 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x40be",
+ "EventName": "PM_THRD_PRIO_2_3_CYC",
+ "BriefDescription": "Cycles thread running at priority level 2 or 3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5080",
+ "EventName": "PM_THRD_PRIO_4_5_CYC",
+ "BriefDescription": "Cycles thread running at priority level 4 or 5",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x5082",
+ "EventName": "PM_THRD_PRIO_6_7_CYC",
+ "BriefDescription": "Cycles thread running at priority level 6 or 7",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3098",
+ "EventName": "PM_THRD_REBAL_CYC",
+ "BriefDescription": "cycles rebalance was active",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20b8",
+ "EventName": "PM_TM_BEGIN_ALL",
+ "BriefDescription": "Tm any tbegin",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x318082",
+ "EventName": "PM_TM_CAM_OVERFLOW",
+ "BriefDescription": "l3 tm cam overflow during L2 co of SC",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x74708c",
+ "EventName": "PM_TM_CAP_OVERFLOW",
+ "BriefDescription": "TM Footprint Capactiy Overflow",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20ba",
+ "EventName": "PM_TM_END_ALL",
+ "BriefDescription": "Tm any tend",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3086",
+ "EventName": "PM_TM_FAIL_CONF_NON_TM",
+ "BriefDescription": "TEXAS fail reason @ completion",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3088",
+ "EventName": "PM_TM_FAIL_CON_TM",
+ "BriefDescription": "TEXAS fail reason @ completion",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe0b2",
+ "EventName": "PM_TM_FAIL_DISALLOW",
+ "BriefDescription": "TM fail disallow",
+ "PublicDescription": "TM fail disallow42"
+ },
+ {,
+ "EventCode": "0x3084",
+ "EventName": "PM_TM_FAIL_FOOTPRINT_OVERFLOW",
+ "BriefDescription": "TEXAS fail reason @ completion",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe0b8",
+ "EventName": "PM_TM_FAIL_NON_TX_CONFLICT",
+ "BriefDescription": "Non transactional conflict from LSU whtver gets repoted to texas",
+ "PublicDescription": "Non transactional conflict from LSU whtver gets repoted to texas42"
+ },
+ {,
+ "EventCode": "0x308a",
+ "EventName": "PM_TM_FAIL_SELF",
+ "BriefDescription": "TEXAS fail reason @ completion",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe0b4",
+ "EventName": "PM_TM_FAIL_TLBIE",
+ "BriefDescription": "TLBIE hit bloom filter",
+ "PublicDescription": "TLBIE hit bloom filter42"
+ },
+ {,
+ "EventCode": "0xe0b6",
+ "EventName": "PM_TM_FAIL_TX_CONFLICT",
+ "BriefDescription": "Transactional conflict from LSU, whatever gets reported to texas",
+ "PublicDescription": "Transactional conflict from LSU, whatever gets reported to texas 42"
+ },
+ {,
+ "EventCode": "0x727086",
+ "EventName": "PM_TM_FAV_CAUSED_FAIL",
+ "BriefDescription": "TM Load (fav) caused another thread to fail",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x717082",
+ "EventName": "PM_TM_LD_CAUSED_FAIL",
+ "BriefDescription": "Non TM Ld caused any thread to fail",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x727084",
+ "EventName": "PM_TM_LD_CONF",
+ "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x328086",
+ "EventName": "PM_TM_RST_SC",
+ "BriefDescription": "tm snp rst tm sc",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x318080",
+ "EventName": "PM_TM_SC_CO",
+ "BriefDescription": "l3 castout tm Sc line",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x73708a",
+ "EventName": "PM_TM_ST_CAUSED_FAIL",
+ "BriefDescription": "TM Store (fav or non-fav) caused another thread to fail",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x737088",
+ "EventName": "PM_TM_ST_CONF",
+ "BriefDescription": "TM Store (fav or non-fav) ran into conflict (failed)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20bc",
+ "EventName": "PM_TM_TBEGIN",
+ "BriefDescription": "Tm nested tbegin",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3080",
+ "EventName": "PM_TM_TRESUME",
+ "BriefDescription": "Tm resume",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20be",
+ "EventName": "PM_TM_TSUSPEND",
+ "BriefDescription": "Tm suspend",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xe08c",
+ "EventName": "PM_UP_PREF_L3",
+ "BriefDescription": "Micropartition prefetch",
+ "PublicDescription": "Micropartition prefetch42"
+ },
+ {,
+ "EventCode": "0xe08e",
+ "EventName": "PM_UP_PREF_POINTER",
+ "BriefDescription": "Micrpartition pointer prefetches",
+ "PublicDescription": "Micrpartition pointer prefetches42"
+ },
+ {,
+ "EventCode": "0xa0a4",
+ "EventName": "PM_VSU0_16FLOP",
+ "BriefDescription": "Sixteen flops operation (SP vector versions of fdiv,fsqrt)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa080",
+ "EventName": "PM_VSU0_1FLOP",
+ "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation finished",
+ "PublicDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation finishedDecode into 1,2,4 FLOP according to instr IOP, multiplied by #vector elements according to route( eg x1, x2, x4) Only if instr sends finish to ISU"
+ },
+ {,
+ "EventCode": "0xa098",
+ "EventName": "PM_VSU0_2FLOP",
+ "BriefDescription": "two flops operation (scalar fmadd, fnmadd, fmsub, fnmsub and DP vector versions of single flop instructions)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa09c",
+ "EventName": "PM_VSU0_4FLOP",
+ "BriefDescription": "four flops operation (scalar fdiv, fsqrt, DP vector version of fmadd, fnmadd, fmsub, fnmsub, SP vector versions of single flop instructions)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0a0",
+ "EventName": "PM_VSU0_8FLOP",
+ "BriefDescription": "eight flops operation (DP vector versions of fdiv,fsqrt and SP vector versions of fmadd,fnmadd,fmsub,fnmsub)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0a4",
+ "EventName": "PM_VSU0_COMPLEX_ISSUED",
+ "BriefDescription": "Complex VMX instruction issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0b4",
+ "EventName": "PM_VSU0_CY_ISSUED",
+ "BriefDescription": "Cryptographic instruction RFC02196 Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0a8",
+ "EventName": "PM_VSU0_DD_ISSUED",
+ "BriefDescription": "64BIT Decimal Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa08c",
+ "EventName": "PM_VSU0_DP_2FLOP",
+ "BriefDescription": "DP vector version of fmul, fsub, fcmp, fsel, fabs, fnabs, fres ,fsqrte, fneg",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa090",
+ "EventName": "PM_VSU0_DP_FMA",
+ "BriefDescription": "DP vector version of fmadd,fnmadd,fmsub,fnmsub",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa094",
+ "EventName": "PM_VSU0_DP_FSQRT_FDIV",
+ "BriefDescription": "DP vector versions of fdiv,fsqrt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0ac",
+ "EventName": "PM_VSU0_DQ_ISSUED",
+ "BriefDescription": "128BIT Decimal Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0b0",
+ "EventName": "PM_VSU0_EX_ISSUED",
+ "BriefDescription": "Direct move 32/64b VRFtoGPR RFC02206 Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0bc",
+ "EventName": "PM_VSU0_FIN",
+ "BriefDescription": "VSU0 Finished an instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa084",
+ "EventName": "PM_VSU0_FMA",
+ "BriefDescription": "two flops operation (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only!",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb098",
+ "EventName": "PM_VSU0_FPSCR",
+ "BriefDescription": "Move to/from FPSCR type instruction issued on Pipe 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa088",
+ "EventName": "PM_VSU0_FSQRT_FDIV",
+ "BriefDescription": "four flops operation (fdiv,fsqrt) Scalar Instructions only!",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb090",
+ "EventName": "PM_VSU0_PERMUTE_ISSUED",
+ "BriefDescription": "Permute VMX Instruction Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb088",
+ "EventName": "PM_VSU0_SCALAR_DP_ISSUED",
+ "BriefDescription": "Double Precision scalar instruction issued on Pipe0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb094",
+ "EventName": "PM_VSU0_SIMPLE_ISSUED",
+ "BriefDescription": "Simple VMX instruction issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0a8",
+ "EventName": "PM_VSU0_SINGLE",
+ "BriefDescription": "FPU single precision",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb09c",
+ "EventName": "PM_VSU0_SQ",
+ "BriefDescription": "Store Vector Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb08c",
+ "EventName": "PM_VSU0_STF",
+ "BriefDescription": "FPU store (SP or DP) issued on Pipe0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb080",
+ "EventName": "PM_VSU0_VECTOR_DP_ISSUED",
+ "BriefDescription": "Double Precision vector instruction issued on Pipe0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb084",
+ "EventName": "PM_VSU0_VECTOR_SP_ISSUED",
+ "BriefDescription": "Single Precision vector instruction issued (executed)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0a6",
+ "EventName": "PM_VSU1_16FLOP",
+ "BriefDescription": "Sixteen flops operation (SP vector versions of fdiv,fsqrt)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa082",
+ "EventName": "PM_VSU1_1FLOP",
+ "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa09a",
+ "EventName": "PM_VSU1_2FLOP",
+ "BriefDescription": "two flops operation (scalar fmadd, fnmadd, fmsub, fnmsub and DP vector versions of single flop instructions)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa09e",
+ "EventName": "PM_VSU1_4FLOP",
+ "BriefDescription": "four flops operation (scalar fdiv, fsqrt, DP vector version of fmadd, fnmadd, fmsub, fnmsub, SP vector versions of single flop instructions)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0a2",
+ "EventName": "PM_VSU1_8FLOP",
+ "BriefDescription": "eight flops operation (DP vector versions of fdiv,fsqrt and SP vector versions of fmadd,fnmadd,fmsub,fnmsub)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0a6",
+ "EventName": "PM_VSU1_COMPLEX_ISSUED",
+ "BriefDescription": "Complex VMX instruction issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0b6",
+ "EventName": "PM_VSU1_CY_ISSUED",
+ "BriefDescription": "Cryptographic instruction RFC02196 Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0aa",
+ "EventName": "PM_VSU1_DD_ISSUED",
+ "BriefDescription": "64BIT Decimal Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa08e",
+ "EventName": "PM_VSU1_DP_2FLOP",
+ "BriefDescription": "DP vector version of fmul, fsub, fcmp, fsel, fabs, fnabs, fres ,fsqrte, fneg",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa092",
+ "EventName": "PM_VSU1_DP_FMA",
+ "BriefDescription": "DP vector version of fmadd,fnmadd,fmsub,fnmsub",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa096",
+ "EventName": "PM_VSU1_DP_FSQRT_FDIV",
+ "BriefDescription": "DP vector versions of fdiv,fsqrt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0ae",
+ "EventName": "PM_VSU1_DQ_ISSUED",
+ "BriefDescription": "128BIT Decimal Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb0b2",
+ "EventName": "PM_VSU1_EX_ISSUED",
+ "BriefDescription": "Direct move 32/64b VRFtoGPR RFC02206 Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0be",
+ "EventName": "PM_VSU1_FIN",
+ "BriefDescription": "VSU1 Finished an instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa086",
+ "EventName": "PM_VSU1_FMA",
+ "BriefDescription": "two flops operation (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only!",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb09a",
+ "EventName": "PM_VSU1_FPSCR",
+ "BriefDescription": "Move to/from FPSCR type instruction issued on Pipe 0",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa08a",
+ "EventName": "PM_VSU1_FSQRT_FDIV",
+ "BriefDescription": "four flops operation (fdiv,fsqrt) Scalar Instructions only!",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb092",
+ "EventName": "PM_VSU1_PERMUTE_ISSUED",
+ "BriefDescription": "Permute VMX Instruction Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb08a",
+ "EventName": "PM_VSU1_SCALAR_DP_ISSUED",
+ "BriefDescription": "Double Precision scalar instruction issued on Pipe1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb096",
+ "EventName": "PM_VSU1_SIMPLE_ISSUED",
+ "BriefDescription": "Simple VMX instruction issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xa0aa",
+ "EventName": "PM_VSU1_SINGLE",
+ "BriefDescription": "FPU single precision",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb09e",
+ "EventName": "PM_VSU1_SQ",
+ "BriefDescription": "Store Vector Issued",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb08e",
+ "EventName": "PM_VSU1_STF",
+ "BriefDescription": "FPU store (SP or DP) issued on Pipe1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb082",
+ "EventName": "PM_VSU1_VECTOR_DP_ISSUED",
+ "BriefDescription": "Double Precision vector instruction issued on Pipe1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0xb086",
+ "EventName": "PM_VSU1_VECTOR_SP_ISSUED",
+ "BriefDescription": "Single Precision vector instruction issued (executed)",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power8/pipeline.json
new file mode 100644
index 000000000000..293f3a4c6901
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/pipeline.json
@@ -0,0 +1,350 @@
+[
+ {,
+ "EventCode": "0x100f2",
+ "EventName": "PM_1PLUS_PPC_CMPL",
+ "BriefDescription": "1 or more ppc insts finished",
+ "PublicDescription": "1 or more ppc insts finished (completed)"
+ },
+ {,
+ "EventCode": "0x400f2",
+ "EventName": "PM_1PLUS_PPC_DISP",
+ "BriefDescription": "Cycles at least one Instr Dispatched",
+ "PublicDescription": "Cycles at least one Instr Dispatched. Could be a group with only microcode. Issue HW016521"
+ },
+ {,
+ "EventCode": "0x100fa",
+ "EventName": "PM_ANY_THRD_RUN_CYC",
+ "BriefDescription": "One of threads in run_cycles",
+ "PublicDescription": "Any thread in run_cycles (was one thread in run_cycles)"
+ },
+ {,
+ "EventCode": "0x4000a",
+ "EventName": "PM_CMPLU_STALL",
+ "BriefDescription": "Completion stall",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d018",
+ "EventName": "PM_CMPLU_STALL_BRU",
+ "BriefDescription": "Completion stall due to a Branch Unit",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c012",
+ "EventName": "PM_CMPLU_STALL_DCACHE_MISS",
+ "BriefDescription": "Completion stall by Dcache miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c018",
+ "EventName": "PM_CMPLU_STALL_DMISS_L21_L31",
+ "BriefDescription": "Completion stall by Dcache miss which resolved on chip ( excluding local L2/L3)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c016",
+ "EventName": "PM_CMPLU_STALL_DMISS_L2L3",
+ "BriefDescription": "Completion stall by Dcache miss which resolved in L2/L3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c016",
+ "EventName": "PM_CMPLU_STALL_DMISS_L2L3_CONFLICT",
+ "BriefDescription": "Completion stall due to cache miss that resolves in the L2 or L3 with a conflict",
+ "PublicDescription": "Completion stall due to cache miss resolving in core's L2/L3 with a conflict"
+ },
+ {,
+ "EventCode": "0x4c01a",
+ "EventName": "PM_CMPLU_STALL_DMISS_L3MISS",
+ "BriefDescription": "Completion stall due to cache miss resolving missed the L3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c018",
+ "EventName": "PM_CMPLU_STALL_DMISS_LMEM",
+ "BriefDescription": "Completion stall due to cache miss that resolves in local memory",
+ "PublicDescription": "Completion stall due to cache miss resolving in core's Local Memory"
+ },
+ {,
+ "EventCode": "0x2c01c",
+ "EventName": "PM_CMPLU_STALL_DMISS_REMOTE",
+ "BriefDescription": "Completion stall by Dcache miss which resolved from remote chip (cache or memory)",
+ "PublicDescription": "Completion stall by Dcache miss which resolved on chip ( excluding local L2/L3)"
+ },
+ {,
+ "EventCode": "0x4c012",
+ "EventName": "PM_CMPLU_STALL_ERAT_MISS",
+ "BriefDescription": "Completion stall due to LSU reject ERAT miss",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d016",
+ "EventName": "PM_CMPLU_STALL_FXLONG",
+ "BriefDescription": "Completion stall due to a long latency fixed point instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2d016",
+ "EventName": "PM_CMPLU_STALL_FXU",
+ "BriefDescription": "Completion stall due to FXU",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30036",
+ "EventName": "PM_CMPLU_STALL_HWSYNC",
+ "BriefDescription": "completion stall due to hwsync",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4d014",
+ "EventName": "PM_CMPLU_STALL_LOAD_FINISH",
+ "BriefDescription": "Completion stall due to a Load finish",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c010",
+ "EventName": "PM_CMPLU_STALL_LSU",
+ "BriefDescription": "Completion stall by LSU instruction",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10036",
+ "EventName": "PM_CMPLU_STALL_LWSYNC",
+ "BriefDescription": "completion stall due to isync/lwsync",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30006",
+ "EventName": "PM_CMPLU_STALL_OTHER_CMPL",
+ "BriefDescription": "Instructions core completed while this tread was stalled",
+ "PublicDescription": "Instructions core completed while this thread was stalled"
+ },
+ {,
+ "EventCode": "0x4c01c",
+ "EventName": "PM_CMPLU_STALL_ST_FWD",
+ "BriefDescription": "Completion stall due to store forward",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1001c",
+ "EventName": "PM_CMPLU_STALL_THRD",
+ "BriefDescription": "Completion Stalled due to thread conflict. Group ready to complete but it was another thread's turn",
+ "PublicDescription": "Completion stall due to thread conflict"
+ },
+ {,
+ "EventCode": "0x1e",
+ "EventName": "PM_CYC",
+ "BriefDescription": "Cycles",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10006",
+ "EventName": "PM_DISP_HELD",
+ "BriefDescription": "Dispatch Held",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4003c",
+ "EventName": "PM_DISP_HELD_SYNC_HOLD",
+ "BriefDescription": "Dispatch held due to SYNC hold",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200f8",
+ "EventName": "PM_EXT_INT",
+ "BriefDescription": "external interrupt",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x400f8",
+ "EventName": "PM_FLUSH",
+ "BriefDescription": "Flush (any type)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30012",
+ "EventName": "PM_FLUSH_COMPLETION",
+ "BriefDescription": "Completion Flush",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3000c",
+ "EventName": "PM_FREQ_DOWN",
+ "BriefDescription": "Power Management: Below Threshold B",
+ "PublicDescription": "Frequency is being slewed down due to Power Management"
+ },
+ {,
+ "EventCode": "0x4000c",
+ "EventName": "PM_FREQ_UP",
+ "BriefDescription": "Power Management: Above Threshold A",
+ "PublicDescription": "Frequency is being slewed up due to Power Management"
+ },
+ {,
+ "EventCode": "0x2000a",
+ "EventName": "PM_HV_CYC",
+ "BriefDescription": "Cycles in which msr_hv is high. Note that this event does not take msr_pr into consideration",
+ "PublicDescription": "cycles in hypervisor mode"
+ },
+ {,
+ "EventCode": "0x3405e",
+ "EventName": "PM_IFETCH_THROTTLE",
+ "BriefDescription": "Cycles in which Instruction fetch throttle was active",
+ "PublicDescription": "Cycles instruction fecth was throttled in IFU"
+ },
+ {,
+ "EventCode": "0x10014",
+ "EventName": "PM_IOPS_CMPL",
+ "BriefDescription": "Internal Operations completed",
+ "PublicDescription": "IOPS Completed"
+ },
+ {,
+ "EventCode": "0x3c058",
+ "EventName": "PM_LARX_FIN",
+ "BriefDescription": "Larx finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1002e",
+ "EventName": "PM_LD_CMPL",
+ "BriefDescription": "count of Loads completed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10062",
+ "EventName": "PM_LD_L3MISS_PEND_CYC",
+ "BriefDescription": "Cycles L3 miss was pending for this thread",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30066",
+ "EventName": "PM_LSU_FIN",
+ "BriefDescription": "LSU Finished an instruction (up to 2 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2003e",
+ "EventName": "PM_LSU_LMQ_SRQ_EMPTY_CYC",
+ "BriefDescription": "LSU empty (lmq and srq empty)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e05c",
+ "EventName": "PM_LSU_REJECT_ERAT_MISS",
+ "BriefDescription": "LSU Reject due to ERAT (up to 4 per cycles)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e05c",
+ "EventName": "PM_LSU_REJECT_LHS",
+ "BriefDescription": "LSU Reject due to LHS (up to 4 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e05c",
+ "EventName": "PM_LSU_REJECT_LMQ_FULL",
+ "BriefDescription": "LSU reject due to LMQ full ( 4 per cycle)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1001a",
+ "EventName": "PM_LSU_SRQ_FULL_CYC",
+ "BriefDescription": "Storage Queue is full and is blocking dispatch",
+ "PublicDescription": "SRQ is Full"
+ },
+ {,
+ "EventCode": "0x40014",
+ "EventName": "PM_PROBE_NOP_DISP",
+ "BriefDescription": "ProbeNops dispatched",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x600f4",
+ "EventName": "PM_RUN_CYC",
+ "BriefDescription": "Run_cycles",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3006c",
+ "EventName": "PM_RUN_CYC_SMT2_MODE",
+ "BriefDescription": "Cycles run latch is set and core is in SMT2 mode",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2006c",
+ "EventName": "PM_RUN_CYC_SMT4_MODE",
+ "BriefDescription": "cycles this threads run latch is set and the core is in SMT4 mode",
+ "PublicDescription": "Cycles run latch is set and core is in SMT4 mode"
+ },
+ {,
+ "EventCode": "0x1006c",
+ "EventName": "PM_RUN_CYC_ST_MODE",
+ "BriefDescription": "Cycles run latch is set and core is in ST mode",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x500fa",
+ "EventName": "PM_RUN_INST_CMPL",
+ "BriefDescription": "Run_Instructions",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e058",
+ "EventName": "PM_STCX_FAIL",
+ "BriefDescription": "stcx failed",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x20016",
+ "EventName": "PM_ST_CMPL",
+ "BriefDescription": "Store completion count",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200f0",
+ "EventName": "PM_ST_FIN",
+ "BriefDescription": "Store Instructions Finished",
+ "PublicDescription": "Store Instructions Finished (store sent to nest)"
+ },
+ {,
+ "EventCode": "0x20018",
+ "EventName": "PM_ST_FWD",
+ "BriefDescription": "Store forwards that finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10026",
+ "EventName": "PM_TABLEWALK_CYC",
+ "BriefDescription": "Cycles when a tablewalk (I or D) is active",
+ "PublicDescription": "Tablewalk Active"
+ },
+ {,
+ "EventCode": "0x300f8",
+ "EventName": "PM_TB_BIT_TRANS",
+ "BriefDescription": "timebase event",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2000c",
+ "EventName": "PM_THRD_ALL_RUN_CYC",
+ "BriefDescription": "All Threads in Run_cycles (was both threads in run_cycles)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30058",
+ "EventName": "PM_TLBIE_FIN",
+ "BriefDescription": "tlbie finished",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10060",
+ "EventName": "PM_TM_TRANS_RUN_CYC",
+ "BriefDescription": "run cycles in transactional state",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e012",
+ "EventName": "PM_TM_TX_PASS_RUN_CYC",
+ "BriefDescription": "cycles spent in successful transactions",
+ "PublicDescription": "run cycles spent in successful transactions"
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/pmc.json b/tools/perf/pmu-events/arch/powerpc/power8/pmc.json
new file mode 100644
index 000000000000..583e4d937621
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/pmc.json
@@ -0,0 +1,140 @@
+[
+ {,
+ "EventCode": "0x20010",
+ "EventName": "PM_PMC1_OVERFLOW",
+ "BriefDescription": "Overflow from counter 1",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30010",
+ "EventName": "PM_PMC2_OVERFLOW",
+ "BriefDescription": "Overflow from counter 2",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30020",
+ "EventName": "PM_PMC2_REWIND",
+ "BriefDescription": "PMC2 Rewind Event (did not match condition)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10022",
+ "EventName": "PM_PMC2_SAVED",
+ "BriefDescription": "PMC2 Rewind Value saved",
+ "PublicDescription": "PMC2 Rewind Value saved (matched condition)"
+ },
+ {,
+ "EventCode": "0x40010",
+ "EventName": "PM_PMC3_OVERFLOW",
+ "BriefDescription": "Overflow from counter 3",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10010",
+ "EventName": "PM_PMC4_OVERFLOW",
+ "BriefDescription": "Overflow from counter 4",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10020",
+ "EventName": "PM_PMC4_REWIND",
+ "BriefDescription": "PMC4 Rewind Event",
+ "PublicDescription": "PMC4 Rewind Event (did not match condition)"
+ },
+ {,
+ "EventCode": "0x30022",
+ "EventName": "PM_PMC4_SAVED",
+ "BriefDescription": "PMC4 Rewind Value saved (matched condition)",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10024",
+ "EventName": "PM_PMC5_OVERFLOW",
+ "BriefDescription": "Overflow from counter 5",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x30024",
+ "EventName": "PM_PMC6_OVERFLOW",
+ "BriefDescription": "Overflow from counter 6",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x400f4",
+ "EventName": "PM_RUN_PURR",
+ "BriefDescription": "Run_PURR",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x10008",
+ "EventName": "PM_RUN_SPURR",
+ "BriefDescription": "Run SPURR",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x0",
+ "EventName": "PM_SUSPENDED",
+ "BriefDescription": "Counter OFF",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x301ea",
+ "EventName": "PM_THRESH_EXC_1024",
+ "BriefDescription": "Threshold counter exceeded a value of 1024",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x401ea",
+ "EventName": "PM_THRESH_EXC_128",
+ "BriefDescription": "Threshold counter exceeded a value of 128",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x401ec",
+ "EventName": "PM_THRESH_EXC_2048",
+ "BriefDescription": "Threshold counter exceeded a value of 2048",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x101e8",
+ "EventName": "PM_THRESH_EXC_256",
+ "BriefDescription": "Threshold counter exceed a count of 256",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x201e6",
+ "EventName": "PM_THRESH_EXC_32",
+ "BriefDescription": "Threshold counter exceeded a value of 32",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x101e6",
+ "EventName": "PM_THRESH_EXC_4096",
+ "BriefDescription": "Threshold counter exceed a count of 4096",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x201e8",
+ "EventName": "PM_THRESH_EXC_512",
+ "BriefDescription": "Threshold counter exceeded a value of 512",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x301e8",
+ "EventName": "PM_THRESH_EXC_64",
+ "BriefDescription": "IFU non-branch finished",
+ "PublicDescription": "Threshold counter exceeded a value of 64"
+ },
+ {,
+ "EventCode": "0x101ec",
+ "EventName": "PM_THRESH_MET",
+ "BriefDescription": "threshold exceeded",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4016e",
+ "EventName": "PM_THRESH_NOT_MET",
+ "BriefDescription": "Threshold counter did not meet threshold",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/powerpc/power8/translation.json b/tools/perf/pmu-events/arch/powerpc/power8/translation.json
new file mode 100644
index 000000000000..e47a55459bc8
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power8/translation.json
@@ -0,0 +1,176 @@
+[
+ {,
+ "EventCode": "0x4c054",
+ "EventName": "PM_DERAT_MISS_16G",
+ "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3c054",
+ "EventName": "PM_DERAT_MISS_16M",
+ "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1c056",
+ "EventName": "PM_DERAT_MISS_4K",
+ "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 4K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c054",
+ "EventName": "PM_DERAT_MISS_64K",
+ "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 64K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e048",
+ "EventName": "PM_DPTEG_FROM_DL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e048",
+ "EventName": "PM_DPTEG_FROM_DL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e042",
+ "EventName": "PM_DPTEG_FROM_L2",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e04e",
+ "EventName": "PM_DPTEG_FROM_L2MISS",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a localtion other than the local core's L2 due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e040",
+ "EventName": "PM_DPTEG_FROM_L2_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e040",
+ "EventName": "PM_DPTEG_FROM_L2_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e042",
+ "EventName": "PM_DPTEG_FROM_L3",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3e042",
+ "EventName": "PM_DPTEG_FROM_L3_DISP_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e042",
+ "EventName": "PM_DPTEG_FROM_L3_MEPF",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e044",
+ "EventName": "PM_DPTEG_FROM_L3_NO_CONFLICT",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e04c",
+ "EventName": "PM_DPTEG_FROM_LL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e048",
+ "EventName": "PM_DPTEG_FROM_LMEM",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e04c",
+ "EventName": "PM_DPTEG_FROM_MEMORY",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4e04a",
+ "EventName": "PM_DPTEG_FROM_OFF_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e048",
+ "EventName": "PM_DPTEG_FROM_ON_CHIP_CACHE",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e046",
+ "EventName": "PM_DPTEG_FROM_RL2L3_MOD",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x1e04a",
+ "EventName": "PM_DPTEG_FROM_RL2L3_SHR",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2e04a",
+ "EventName": "PM_DPTEG_FROM_RL4",
+ "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a data side request",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x300fc",
+ "EventName": "PM_DTLB_MISS",
+ "BriefDescription": "Data PTEG reload",
+ "PublicDescription": "Data PTEG Reloaded (DTLB Miss)"
+ },
+ {,
+ "EventCode": "0x1c058",
+ "EventName": "PM_DTLB_MISS_16G",
+ "BriefDescription": "Data TLB Miss page size 16G",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x4c056",
+ "EventName": "PM_DTLB_MISS_16M",
+ "BriefDescription": "Data TLB Miss page size 16M",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x2c056",
+ "EventName": "PM_DTLB_MISS_4K",
+ "BriefDescription": "Data TLB Miss page size 4k",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x3c056",
+ "EventName": "PM_DTLB_MISS_64K",
+ "BriefDescription": "Data TLB Miss page size 64K",
+ "PublicDescription": ""
+ },
+ {,
+ "EventCode": "0x200f6",
+ "EventName": "PM_LSU_DERAT_MISS",
+ "BriefDescription": "DERAT Reloaded due to a DERAT miss",
+ "PublicDescription": "DERAT Reloaded (Miss)"
+ },
+ {,
+ "EventCode": "0x20066",
+ "EventName": "PM_TLB_MISS",
+ "BriefDescription": "TLB Miss (I + D)",
+ "PublicDescription": ""
+ },
+]
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/cache.json b/tools/perf/pmu-events/arch/x86/bonnell/cache.json
new file mode 100644
index 000000000000..ffab90c5891c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/cache.json
@@ -0,0 +1,746 @@
+[
+ {
+ "EventCode": "0x21",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_ADS.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cycles L2 address bus is in use."
+ },
+ {
+ "EventCode": "0x22",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_DBUS_BUSY.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cycles the L2 cache data bus is busy."
+ },
+ {
+ "EventCode": "0x23",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_DBUS_BUSY_RD.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cycles the L2 transfers data to the core."
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1",
+ "UMask": "0x70",
+ "EventName": "L2_LINES_IN.SELF.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache misses."
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_LINES_IN.SELF.DEMAND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache misses."
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1",
+ "UMask": "0x50",
+ "EventName": "L2_LINES_IN.SELF.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache misses."
+ },
+ {
+ "EventCode": "0x25",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_M_LINES_IN.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache line modifications."
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1",
+ "UMask": "0x70",
+ "EventName": "L2_LINES_OUT.SELF.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache lines evicted."
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_LINES_OUT.SELF.DEMAND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache lines evicted."
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1",
+ "UMask": "0x50",
+ "EventName": "L2_LINES_OUT.SELF.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache lines evicted."
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1",
+ "UMask": "0x70",
+ "EventName": "L2_M_LINES_OUT.SELF.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Modified lines evicted from the L2 cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_M_LINES_OUT.SELF.DEMAND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Modified lines evicted from the L2 cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1",
+ "UMask": "0x50",
+ "EventName": "L2_M_LINES_OUT.SELF.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Modified lines evicted from the L2 cache"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_IFETCH.SELF.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cacheable instruction fetch requests"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_IFETCH.SELF.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cacheable instruction fetch requests"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_IFETCH.SELF.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cacheable instruction fetch requests"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_IFETCH.SELF.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cacheable instruction fetch requests"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_IFETCH.SELF.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cacheable instruction fetch requests"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x74",
+ "EventName": "L2_LD.SELF.ANY.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x71",
+ "EventName": "L2_LD.SELF.ANY.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x78",
+ "EventName": "L2_LD.SELF.ANY.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x72",
+ "EventName": "L2_LD.SELF.ANY.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x7f",
+ "EventName": "L2_LD.SELF.ANY.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_LD.SELF.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_LD.SELF.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_LD.SELF.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_LD.SELF.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_LD.SELF.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x54",
+ "EventName": "L2_LD.SELF.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x51",
+ "EventName": "L2_LD.SELF.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x58",
+ "EventName": "L2_LD.SELF.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x52",
+ "EventName": "L2_LD.SELF.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x29",
+ "Counter": "0,1",
+ "UMask": "0x5f",
+ "EventName": "L2_LD.SELF.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache reads"
+ },
+ {
+ "EventCode": "0x2A",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_ST.SELF.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 store requests"
+ },
+ {
+ "EventCode": "0x2A",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_ST.SELF.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 store requests"
+ },
+ {
+ "EventCode": "0x2A",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_ST.SELF.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 store requests"
+ },
+ {
+ "EventCode": "0x2A",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_ST.SELF.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 store requests"
+ },
+ {
+ "EventCode": "0x2A",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_ST.SELF.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 store requests"
+ },
+ {
+ "EventCode": "0x2B",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_LOCK.SELF.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 locked accesses"
+ },
+ {
+ "EventCode": "0x2B",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_LOCK.SELF.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 locked accesses"
+ },
+ {
+ "EventCode": "0x2B",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_LOCK.SELF.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 locked accesses"
+ },
+ {
+ "EventCode": "0x2B",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_LOCK.SELF.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 locked accesses"
+ },
+ {
+ "EventCode": "0x2B",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_LOCK.SELF.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 locked accesses"
+ },
+ {
+ "EventCode": "0x2C",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_DATA_RQSTS.SELF.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All data requests from the L1 data cache"
+ },
+ {
+ "EventCode": "0x2C",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_DATA_RQSTS.SELF.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All data requests from the L1 data cache"
+ },
+ {
+ "EventCode": "0x2C",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_DATA_RQSTS.SELF.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All data requests from the L1 data cache"
+ },
+ {
+ "EventCode": "0x2C",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_DATA_RQSTS.SELF.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All data requests from the L1 data cache"
+ },
+ {
+ "EventCode": "0x2C",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_DATA_RQSTS.SELF.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All data requests from the L1 data cache"
+ },
+ {
+ "EventCode": "0x2D",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_LD_IFETCH.SELF.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All read requests from L1 instruction and data caches"
+ },
+ {
+ "EventCode": "0x2D",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_LD_IFETCH.SELF.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All read requests from L1 instruction and data caches"
+ },
+ {
+ "EventCode": "0x2D",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_LD_IFETCH.SELF.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All read requests from L1 instruction and data caches"
+ },
+ {
+ "EventCode": "0x2D",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_LD_IFETCH.SELF.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All read requests from L1 instruction and data caches"
+ },
+ {
+ "EventCode": "0x2D",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_LD_IFETCH.SELF.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All read requests from L1 instruction and data caches"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x74",
+ "EventName": "L2_RQSTS.SELF.ANY.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x71",
+ "EventName": "L2_RQSTS.SELF.ANY.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x78",
+ "EventName": "L2_RQSTS.SELF.ANY.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x72",
+ "EventName": "L2_RQSTS.SELF.ANY.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x7f",
+ "EventName": "L2_RQSTS.SELF.ANY.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_RQSTS.SELF.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_RQSTS.SELF.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_RQSTS.SELF.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x54",
+ "EventName": "L2_RQSTS.SELF.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x51",
+ "EventName": "L2_RQSTS.SELF.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x58",
+ "EventName": "L2_RQSTS.SELF.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x52",
+ "EventName": "L2_RQSTS.SELF.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x5f",
+ "EventName": "L2_RQSTS.SELF.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_RQSTS.SELF.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache demand requests from this core that missed the L2"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_RQSTS.SELF.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 cache demand requests from this core"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x74",
+ "EventName": "L2_REJECT_BUSQ.SELF.ANY.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x71",
+ "EventName": "L2_REJECT_BUSQ.SELF.ANY.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x78",
+ "EventName": "L2_REJECT_BUSQ.SELF.ANY.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x72",
+ "EventName": "L2_REJECT_BUSQ.SELF.ANY.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x7f",
+ "EventName": "L2_REJECT_BUSQ.SELF.ANY.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x44",
+ "EventName": "L2_REJECT_BUSQ.SELF.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_REJECT_BUSQ.SELF.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L2_REJECT_BUSQ.SELF.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x42",
+ "EventName": "L2_REJECT_BUSQ.SELF.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_REJECT_BUSQ.SELF.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x54",
+ "EventName": "L2_REJECT_BUSQ.SELF.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x51",
+ "EventName": "L2_REJECT_BUSQ.SELF.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x58",
+ "EventName": "L2_REJECT_BUSQ.SELF.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x52",
+ "EventName": "L2_REJECT_BUSQ.SELF.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x5f",
+ "EventName": "L2_REJECT_BUSQ.SELF.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Rejected L2 cache requests"
+ },
+ {
+ "EventCode": "0x32",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "L2_NO_REQ.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cycles no L2 cache requests are pending"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0xa1",
+ "EventName": "L1D_CACHE.LD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 Cacheable Data Reads"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0xa2",
+ "EventName": "L1D_CACHE.ST",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 Cacheable Data Writes"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x83",
+ "EventName": "L1D_CACHE.ALL_REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 Data reads and writes"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0xa3",
+ "EventName": "L1D_CACHE.ALL_CACHE_REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 Data Cacheable reads and writes"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE.REPL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1 Data line replacements"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x48",
+ "EventName": "L1D_CACHE.REPLM",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Modified cache lines allocated in the L1 data cache"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "L1D_CACHE.EVICT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Modified cache lines evicted from the L1 data cache"
+ },
+ {
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (precise event)."
+ },
+ {
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the L2 cache"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/floating-point.json b/tools/perf/pmu-events/arch/x86/bonnell/floating-point.json
new file mode 100644
index 000000000000..f0e090cdb9f0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/floating-point.json
@@ -0,0 +1,261 @@
+[
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "X87_COMP_OPS_EXE.ANY.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Floating point computational micro-ops executed."
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0x10",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "X87_COMP_OPS_EXE.ANY.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Floating point computational micro-ops retired."
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "X87_COMP_OPS_EXE.FXCH.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FXCH uops executed."
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0x10",
+ "Counter": "0,1",
+ "UMask": "0x82",
+ "EventName": "X87_COMP_OPS_EXE.FXCH.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FXCH uops retired."
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.S",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Floating point assists."
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "FP_ASSIST.AR",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Floating point assists for retired operations."
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "SIMD_UOPS_EXEC.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD micro-ops executed (excluding stores)."
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB0",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "SIMD_UOPS_EXEC.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD micro-ops retired (excluding stores)."
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "SIMD_SAT_UOP_EXEC.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD saturated arithmetic micro-ops executed."
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "SIMD_SAT_UOP_EXEC.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD saturated arithmetic micro-ops retired."
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "SIMD_UOP_TYPE_EXEC.MUL.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed multiply micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "SIMD_UOP_TYPE_EXEC.MUL.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed multiply micro-ops retired"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "SIMD_UOP_TYPE_EXEC.SHIFT.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed shift micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x82",
+ "EventName": "SIMD_UOP_TYPE_EXEC.SHIFT.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed shift micro-ops retired"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "SIMD_UOP_TYPE_EXEC.PACK.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x84",
+ "EventName": "SIMD_UOP_TYPE_EXEC.PACK.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed micro-ops retired"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "SIMD_UOP_TYPE_EXEC.UNPACK.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD unpacked micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x88",
+ "EventName": "SIMD_UOP_TYPE_EXEC.UNPACK.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD unpacked micro-ops retired"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "SIMD_UOP_TYPE_EXEC.LOGICAL.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed logical micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x90",
+ "EventName": "SIMD_UOP_TYPE_EXEC.LOGICAL.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed logical micro-ops retired"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "SIMD_UOP_TYPE_EXEC.ARITHMETIC.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed arithmetic micro-ops executed"
+ },
+ {
+ "EventCode": "0xB3",
+ "Counter": "0,1",
+ "UMask": "0xa0",
+ "EventName": "SIMD_UOP_TYPE_EXEC.ARITHMETIC.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD packed arithmetic micro-ops retired"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "SIMD_INST_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired Streaming SIMD Extensions (SSE) packed-single instructions."
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "SIMD_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired Streaming SIMD Extensions (SSE) scalar-single instructions."
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "SIMD_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired Streaming SIMD Extensions 2 (SSE2) scalar-double instructions."
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "SIMD_INST_RETIRED.VECTOR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired Streaming SIMD Extensions 2 (SSE2) vector instructions."
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "SIMD_COMP_INST_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired computational Streaming SIMD Extensions (SSE) packed-single instructions."
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "SIMD_COMP_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired computational Streaming SIMD Extensions (SSE) scalar-single instructions."
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "SIMD_COMP_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired computational Streaming SIMD Extensions 2 (SSE2) scalar-double instructions."
+ },
+ {
+ "EventCode": "0xCD",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "SIMD_ASSIST",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "SIMD assists invoked."
+ },
+ {
+ "EventCode": "0xCE",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "SIMD_INSTR_RETIRED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SIMD Instructions retired."
+ },
+ {
+ "EventCode": "0xCF",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "SIMD_SAT_INSTR_RETIRED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Saturated arithmetic instructions retired."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/frontend.json b/tools/perf/pmu-events/arch/x86/bonnell/frontend.json
new file mode 100644
index 000000000000..935b7dcf067d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/frontend.json
@@ -0,0 +1,83 @@
+[
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "ICACHE.ACCESSES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Instruction fetches."
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Icache hit"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Icache miss"
+ },
+ {
+ "EventCode": "0x86",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CYCLES_ICACHE_MEM_STALLED.ICACHE_MEM_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles during which instruction fetches are stalled."
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "DECODE_STALL.PFB_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Decode stall due to PFB empty"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "DECODE_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Decode stall due to IQ full"
+ },
+ {
+ "EventCode": "0xAA",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.NON_CISC_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Non-CISC nacro instructions decoded"
+ },
+ {
+ "EventCode": "0xAA",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MACRO_INSTS.CISC_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "CISC macro instructions decoded"
+ },
+ {
+ "EventCode": "0xAA",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "MACRO_INSTS.ALL_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Instructions decoded"
+ },
+ {
+ "EventCode": "0xA9",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "UOPS.MS_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "This event counts the cycles where 1 or more uops are issued by the micro-sequencer (MS), including microcode assists and inserted flows, and written to the IQ. ",
+ "CounterMask": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/memory.json b/tools/perf/pmu-events/arch/x86/bonnell/memory.json
new file mode 100644
index 000000000000..3ae843b20c8a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/memory.json
@@ -0,0 +1,154 @@
+[
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0xf",
+ "EventName": "MISALIGN_MEM_REF.SPLIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory references that cross an 8-byte boundary."
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x9",
+ "EventName": "MISALIGN_MEM_REF.LD_SPLIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load splits"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0xa",
+ "EventName": "MISALIGN_MEM_REF.ST_SPLIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Store splits"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x8f",
+ "EventName": "MISALIGN_MEM_REF.SPLIT.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory references that cross an 8-byte boundary (At Retirement)"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x89",
+ "EventName": "MISALIGN_MEM_REF.LD_SPLIT.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load splits (At Retirement)"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x8a",
+ "EventName": "MISALIGN_MEM_REF.ST_SPLIT.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Store splits (Ar Retirement)"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x8c",
+ "EventName": "MISALIGN_MEM_REF.RMW_SPLIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ld-op-st splits"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x97",
+ "EventName": "MISALIGN_MEM_REF.BUBBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Nonzero segbase 1 bubble"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x91",
+ "EventName": "MISALIGN_MEM_REF.LD_BUBBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Nonzero segbase load 1 bubble"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x92",
+ "EventName": "MISALIGN_MEM_REF.ST_BUBBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Nonzero segbase store 1 bubble"
+ },
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1",
+ "UMask": "0x94",
+ "EventName": "MISALIGN_MEM_REF.RMW_BUBBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Nonzero segbase ld-op-st 1 bubble"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "PREFETCH.PREFETCHT0",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Streaming SIMD Extensions (SSE) PrefetchT0 instructions executed."
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x82",
+ "EventName": "PREFETCH.PREFETCHT1",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Streaming SIMD Extensions (SSE) PrefetchT1 instructions executed."
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x84",
+ "EventName": "PREFETCH.PREFETCHT2",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Streaming SIMD Extensions (SSE) PrefetchT2 instructions executed."
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x86",
+ "EventName": "PREFETCH.SW_L2",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Streaming SIMD Extensions (SSE) PrefetchT1 and PrefetchT2 instructions executed"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x88",
+ "EventName": "PREFETCH.PREFETCHNTA",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Streaming SIMD Extensions (SSE) Prefetch NTA instructions executed"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "PREFETCH.HW_PREFETCH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 hardware prefetch request"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0xf",
+ "EventName": "PREFETCH.SOFTWARE_PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Any Software prefetch"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1",
+ "UMask": "0x8f",
+ "EventName": "PREFETCH.SOFTWARE_PREFETCH.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Any Software prefetch"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/other.json b/tools/perf/pmu-events/arch/x86/bonnell/other.json
new file mode 100644
index 000000000000..4bc1c582d1cd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/other.json
@@ -0,0 +1,450 @@
+[
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "SEGMENT_REG_LOADS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of segment register loads."
+ },
+ {
+ "EventCode": "0x9",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "DISPATCH_BLOCKED.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory cluster signals to block micro-op dispatch for any reason"
+ },
+ {
+ "EventCode": "0x3A",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "EIST_TRANS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions"
+ },
+ {
+ "EventCode": "0x3B",
+ "Counter": "0,1",
+ "UMask": "0xc0",
+ "EventName": "THERMAL_TRIP",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of thermal trips"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_REQUEST_OUTSTANDING.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Outstanding cacheable data read bus requests duration."
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_REQUEST_OUTSTANDING.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Outstanding cacheable data read bus requests duration."
+ },
+ {
+ "EventCode": "0x61",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "BUS_BNR_DRV.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of Bus Not Ready signals asserted."
+ },
+ {
+ "EventCode": "0x61",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BUS_BNR_DRV.THIS_AGENT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of Bus Not Ready signals asserted."
+ },
+ {
+ "EventCode": "0x62",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "BUS_DRDY_CLOCKS.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles when data is sent on the bus."
+ },
+ {
+ "EventCode": "0x62",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BUS_DRDY_CLOCKS.THIS_AGENT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles when data is sent on the bus."
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_LOCK_CLOCKS.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles when a LOCK signal is asserted."
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_LOCK_CLOCKS.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles when a LOCK signal is asserted."
+ },
+ {
+ "EventCode": "0x64",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_DATA_RCV.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles while processor receives data."
+ },
+ {
+ "EventCode": "0x65",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_BRD.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Burst read bus transactions."
+ },
+ {
+ "EventCode": "0x65",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_BRD.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Burst read bus transactions."
+ },
+ {
+ "EventCode": "0x66",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_RFO.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "RFO bus transactions."
+ },
+ {
+ "EventCode": "0x66",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_RFO.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "RFO bus transactions."
+ },
+ {
+ "EventCode": "0x67",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_WB.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Explicit writeback bus transactions."
+ },
+ {
+ "EventCode": "0x67",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_WB.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Explicit writeback bus transactions."
+ },
+ {
+ "EventCode": "0x68",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_IFETCH.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Instruction-fetch bus transactions."
+ },
+ {
+ "EventCode": "0x68",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_IFETCH.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Instruction-fetch bus transactions."
+ },
+ {
+ "EventCode": "0x69",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_INVAL.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Invalidate bus transactions."
+ },
+ {
+ "EventCode": "0x69",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_INVAL.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Invalidate bus transactions."
+ },
+ {
+ "EventCode": "0x6A",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_PWR.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Partial write bus transaction."
+ },
+ {
+ "EventCode": "0x6A",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_PWR.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Partial write bus transaction."
+ },
+ {
+ "EventCode": "0x6B",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_P.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Partial bus transactions."
+ },
+ {
+ "EventCode": "0x6B",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_P.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Partial bus transactions."
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_IO.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "IO bus transactions."
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_IO.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "IO bus transactions."
+ },
+ {
+ "EventCode": "0x6D",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_DEF.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Deferred bus transactions."
+ },
+ {
+ "EventCode": "0x6D",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_DEF.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Deferred bus transactions."
+ },
+ {
+ "EventCode": "0x6E",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_BURST.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Burst (full cache-line) bus transactions."
+ },
+ {
+ "EventCode": "0x6E",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_BURST.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Burst (full cache-line) bus transactions."
+ },
+ {
+ "EventCode": "0x6F",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_MEM.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory bus transactions."
+ },
+ {
+ "EventCode": "0x6F",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_MEM.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory bus transactions."
+ },
+ {
+ "EventCode": "0x70",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "BUS_TRANS_ANY.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All bus transactions."
+ },
+ {
+ "EventCode": "0x70",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_TRANS_ANY.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All bus transactions."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0xb",
+ "EventName": "EXT_SNOOP.THIS_AGENT.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "EXT_SNOOP.THIS_AGENT.CLEAN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "EXT_SNOOP.THIS_AGENT.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "EXT_SNOOP.THIS_AGENT.HITM",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x2b",
+ "EventName": "EXT_SNOOP.ALL_AGENTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x21",
+ "EventName": "EXT_SNOOP.ALL_AGENTS.CLEAN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x22",
+ "EventName": "EXT_SNOOP.ALL_AGENTS.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x77",
+ "Counter": "0,1",
+ "UMask": "0x28",
+ "EventName": "EXT_SNOOP.ALL_AGENTS.HITM",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "External snoops."
+ },
+ {
+ "EventCode": "0x7A",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "BUS_HIT_DRV.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "HIT signal asserted."
+ },
+ {
+ "EventCode": "0x7A",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BUS_HIT_DRV.THIS_AGENT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "HIT signal asserted."
+ },
+ {
+ "EventCode": "0x7B",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "BUS_HITM_DRV.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "HITM signal asserted."
+ },
+ {
+ "EventCode": "0x7B",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BUS_HITM_DRV.THIS_AGENT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "HITM signal asserted."
+ },
+ {
+ "EventCode": "0x7D",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUSQ_EMPTY.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus queue is empty."
+ },
+ {
+ "EventCode": "0x7E",
+ "Counter": "0,1",
+ "UMask": "0xe0",
+ "EventName": "SNOOP_STALL_DRV.ALL_AGENTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus stalled for snoops."
+ },
+ {
+ "EventCode": "0x7E",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "SNOOP_STALL_DRV.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus stalled for snoops."
+ },
+ {
+ "EventCode": "0x7F",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "BUS_IO_WAIT.SELF",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "IO requests waiting in the bus queue."
+ },
+ {
+ "EventCode": "0xC6",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CYCLES_INT_MASKED.CYCLES_INT_MASKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles during which interrupts are disabled."
+ },
+ {
+ "EventCode": "0xC6",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CYCLES_INT_MASKED.CYCLES_INT_PENDING_AND_MASKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles during which interrupts are pending and disabled."
+ },
+ {
+ "EventCode": "0xC8",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "HW_INT_RCV",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Hardware interrupts received."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/pipeline.json b/tools/perf/pmu-events/arch/x86/bonnell/pipeline.json
new file mode 100644
index 000000000000..b2e681c78466
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/pipeline.json
@@ -0,0 +1,364 @@
+[
+ {
+ "EventCode": "0x2",
+ "Counter": "0,1",
+ "UMask": "0x83",
+ "EventName": "STORE_FORWARDS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All store forwards"
+ },
+ {
+ "EventCode": "0x2",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "STORE_FORWARDS.GOOD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Good store forwards"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1",
+ "UMask": "0x7f",
+ "EventName": "REISSUE.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Micro-op reissues for any cause"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1",
+ "UMask": "0xff",
+ "EventName": "REISSUE.ANY.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Micro-op reissues for any cause (At Retirement)"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MUL.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed."
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "MUL.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations retired"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "DIV.S",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide operations executed."
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "DIV.AR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide operations retired"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy."
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.CORE_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Core cycles when core is not halted"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.BUS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Bus cycles when core is not halted"
+ },
+ {
+ "EventCode": "0xA",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Core cycles when core is not halted"
+ },
+ {
+ "EventCode": "0xA",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when core is not halted."
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BR_INST_TYPE_RETIRED.COND",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All macro conditional branch instructions."
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "BR_INST_TYPE_RETIRED.UNCOND",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All macro unconditional branch instructions, excluding calls and indirects"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "BR_INST_TYPE_RETIRED.IND",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All indirect branches that are not calls."
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "BR_INST_TYPE_RETIRED.RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All indirect branches that have a return mnemonic"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "BR_INST_TYPE_RETIRED.DIR_CALL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All non-indirect calls"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "BR_INST_TYPE_RETIRED.IND_CALL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All indirect calls, including both register and memory indirect."
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "BR_INST_TYPE_RETIRED.COND_TAKEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Only taken macro conditional branch instructions"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BR_MISSP_TYPE_RETIRED.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Mispredicted cond branch instructions retired"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "BR_MISSP_TYPE_RETIRED.IND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Mispredicted ind branches that are not calls"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "BR_MISSP_TYPE_RETIRED.RETURN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Mispredicted return branches"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "BR_MISSP_TYPE_RETIRED.IND_CALL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Mispredicted indirect calls, including both register and memory indirect. "
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1",
+ "UMask": "0x11",
+ "EventName": "BR_MISSP_TYPE_RETIRED.COND_TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Mispredicted and taken cond branch instructions retired"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (precise event)."
+ },
+ {
+ "EventCode": "0xA",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired."
+ },
+ {
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Micro-ops retired."
+ },
+ {
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "UOPS_RETIRED.STALLED_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no micro-ops retired."
+ },
+ {
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "UOPS_RETIRED.STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Periods no micro-ops retired."
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Self-Modifying Code detected."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired branch instructions."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.PRED_NOT_TAKEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired branch instructions that were predicted not-taken."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.MISPRED_NOT_TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions that were mispredicted not-taken."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.PRED_TAKEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired branch instructions that were predicted taken."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.MISPRED_TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions that were mispredicted taken."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xc",
+ "EventName": "BR_INST_RETIRED.TAKEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired taken branch instructions."
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xf",
+ "EventName": "BR_INST_RETIRED.ANY1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired branch instructions."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.MISPRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired mispredicted branch instructions (precise event)."
+ },
+ {
+ "EventCode": "0xDC",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles issue is stalled due to div busy."
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0xE4",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BOGUS_BR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Bogus branches"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEARS asserted."
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "REISSUE.OVERLAP_STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Micro-op reissues on a store-load collision"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1",
+ "UMask": "0x81",
+ "EventName": "REISSUE.OVERLAP_STORE.AR",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Micro-op reissues on a store-load collision (At Retirement)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/bonnell/virtual-memory.json b/tools/perf/pmu-events/arch/x86/bonnell/virtual-memory.json
new file mode 100644
index 000000000000..7bb817588721
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/bonnell/virtual-memory.json
@@ -0,0 +1,124 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1",
+ "UMask": "0x7",
+ "EventName": "DATA_TLB_MISSES.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory accesses that missed the DTLB."
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1",
+ "UMask": "0x5",
+ "EventName": "DATA_TLB_MISSES.DTLB_MISS_LD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses due to load operations."
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1",
+ "UMask": "0x9",
+ "EventName": "DATA_TLB_MISSES.L0_DTLB_MISS_LD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L0 DTLB misses due to load operations."
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1",
+ "UMask": "0x6",
+ "EventName": "DATA_TLB_MISSES.DTLB_MISS_ST",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses due to store operations."
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1",
+ "UMask": "0xa",
+ "EventName": "DATA_TLB_MISSES.L0_DTLB_MISS_ST",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L0 DTLB misses due to store operations"
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.WALKS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of page-walks executed."
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Duration of page-walks in core cycles"
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_WALKS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of D-side only page walks"
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Duration of D-side only page walks"
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_WALKS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of I-Side page walks"
+ },
+ {
+ "EventCode": "0xC",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Duration of I-Side page walks"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB hits."
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "ITLB.FLUSH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB flushes."
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0x82",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "ITLB.MISSES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB misses."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (precise event)."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/cache.json b/tools/perf/pmu-events/arch/x86/broadwell/cache.json
new file mode 100644
index 000000000000..73688a9dab2a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/cache.json
@@ -0,0 +1,3198 @@
+[
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests that hit L2 cache. Only not rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.L2_PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 prefetch requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that hit L2 cache. L3 prefetch new types.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x50",
+ "EventName": "L2_RQSTS.L2_PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 prefetch requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe1",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe2",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe4",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of requests from the L2 hardware prefetchers.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf8",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of WB requests that hit L2 cache.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x50",
+ "EventName": "L2_DEMAND_RQSTS.WB_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts core-originated cacheable demand requests that miss the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts core-originated cacheable demand requests that refer to the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand; from the demand Hit FB, if it is allocated by hardware or software prefetch.\nNote: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "This event counts duration of L1D miss outstanding in cycles.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "This event counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.\nNote: A prefetch promoted to Demand is counted from the promotion point.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both cacheable and noncachaeble code read requests.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the demand and prefetch data reads. All Core Data Reads include cacheable \"Demands\" and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.\nNote: Writeback pending FIFO has six entries.",
+ "EventCode": "0xb2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts store uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with locked access retired to the architected path.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "Errata": "BDM35",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted load uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted store uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts load uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement. This event also counts SW prefetches.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts store uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the nearest-level (L1) cache.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load. This event also counts SW prefetches independent of the actual data source.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the mid-level (L2) cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM35",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were data hits in the last-level (L3) cache without snoops required.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM100",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in L3 without snoops required.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the nearest-level (L1) cache. Counting excludes unknown and UC data source.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops misses in L1 cache as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the mid-level (L2) cache. Counting excludes unknown and UC data source.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "Errata": "BDM100, BDE70",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were load uops missed L1 but hit a fill buffer due to a preceding miss to the same cache line with the data not ready.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 Hit and a cross-core snoop missed in the on-pkg core cache.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM100",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 hit and a cross-core snoop hit in the on-pkg core cache.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM100",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were HitM responses from a core on same socket (shared L3).",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM100",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared L3.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the last-level (L3) cache without snoops required.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM100",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in L3 without snoops required.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uop whose Data Source was: local DRAM either Snoop not needed or Snoop Miss (RspI).",
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDE70, BDM100",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PublicDescription": "This event counts Demand Data Read requests that access L2 cache, including rejects.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts Read for Ownership (RFO) requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache accesses when fetching instructions.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts L2 or L3 HW prefetches that access L2 cache including rejects.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or L3 HW prefetches that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts L1D writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts L2 fill requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts L2 writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts transactions that access the L2 pipe including snoops, pagewalks, and so on.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines in the Invalidate state filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines in the Shared state filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines in the Exclusive state filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of split locks in the super queue.",
+ "EventCode": "0xf4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x44",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x27",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe7",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests to L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All requests that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All L2 requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM76",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000018000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f80020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00803c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01003c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02003c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/floating-point.json b/tools/perf/pmu-events/arch/x86/broadwell/floating-point.json
new file mode 100644
index 000000000000..102bfb808199
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/floating-point.json
@@ -0,0 +1,171 @@
+[
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from AVX-256 to legacy SSE when penalty is applicable.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM30",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from legacy SSE to AVX-256 when penalty is applicable.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "BDM30",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of x87 floating point (FP) micro-code assist (numeric overflow/underflow, inexact result) when the output value (destination register) is invalid.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts x87 floating point (FP) micro-code assist (invalid operation, denormal operand, SNaN operand) when the input value (one of the source operands to an FP instruction) is invalid.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of SSE* floating point (FP) micro-code assist (numeric overflow/underflow) when the output value (destination register) is invalid. Counting covers only cases involving penalties that require micro-code assist intervention.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts any input SSE* FP assist - invalid operation, denormal operand, dividing by zero, SNaN operand. Counting includes only cases involving penalties that required micro-code assist intervention.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xc7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar floating-point instructions retired. Applies to SSE* and AVX* scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "FP_ARITH_INST_RETIRED.PACKED",
+ "SampleAfterValue": "2000004",
+ "BriefDescription": "Number of SSE/AVX computational packed floating-point instructions retired. Applies to SSE* and AVX*, packed, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2a",
+ "EventName": "FP_ARITH_INST_RETIRED.SINGLE",
+ "SampleAfterValue": "2000005",
+ "BriefDescription": "Number of SSE/AVX computational single precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x15",
+ "EventName": "FP_ARITH_INST_RETIRED.DOUBLE",
+ "SampleAfterValue": "2000006",
+ "BriefDescription": "Number of SSE/AVX computational double precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/frontend.json b/tools/perf/pmu-events/arch/x86/broadwell/frontend.json
new file mode 100644
index 000000000000..b0cdf1f097a0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/frontend.json
@@ -0,0 +1,286 @@
+[
+ {
+ "PublicDescription": "This counts the number of cycles that the instruction decoder queue is empty and can indicate that the application may be bound in the front end. It does not determine whether there are uops being delivered to the Alloc stage since uops can be delivered by bypass skipping the Instruction Decode Queue (IDQ) when it is empty.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of uops delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of both cacheable and noncacheable Instruction Cache, Streaming Buffer and Victim Cache Reads including UC fetches.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of instruction cache, streaming buffer and victim cache misses. Counting includes UC accesses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes Uncacheable accesses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the demand fetch waits for data (wfdM104H) from L2 or iSB (opportunistic hit).",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE.IFDATA_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding ?4 ? x? when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when:\n a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread;\n b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions); \n c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >=3.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. \nMM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.\nPenalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 0?2 cycles.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/memory.json b/tools/perf/pmu-events/arch/x86/broadwell/memory.json
new file mode 100644
index 000000000000..ff5416d29d0d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/memory.json
@@ -0,0 +1,2845 @@
+[
+ {
+ "PublicDescription": "This event counts speculative cache-line split load uops dispatched to the L1 cache.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts speculative cache line split store-address (STA) uops dispatched to the L1 cache.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX line had a cache conflict",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times we could not allocate Lock Buffer",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a flowmarker.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_EXEC.MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_EXEC.MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RTM region detected inside HLE.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_EXEC.MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:\n1. memory disambiguation,\n2. external snoop, or\n3. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we entered an HLE region\n does not count nested transactions.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "HLE_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times we entered an HLE region; does not count nested transactions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times HLE commit succeeded",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times HLE abort was triggered",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an HLE abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "HLE_RETIRED.ABORTED_MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times the TSX watchdog signaled an HLE abort.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "HLE_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to uncommon conditions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a disallowed operation caused an HLE abort.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "HLE_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times HLE caused a fault.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "HLE_RETIRED.ABORTED_MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times HLE aborted and was not due to the abort conditions in subevents 3-6.",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "HLE_RETIRED.ABORTED_MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we entered an RTM region\n does not count nested transactions.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RTM_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times we entered an RTM region; does not count nested transactions",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times RTM commit succeeded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of times RTM abort was triggered .",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times RTM abort was triggered",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times an RTM abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RTM_RETIRED.ABORTED_MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times the TSX watchdog signaled an RTM abort.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RTM_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times a disallowed operation caused an RTM abort.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RTM_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times a RTM caused a fault.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RTM_RETIRED.ABORTED_MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times RTM aborted and was not due to the abort conditions in subevents 3-6.",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RTM_RETIRED.ABORTED_MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above four.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above eight.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 16.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 32.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads with latency value being above 32",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 64.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 128.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 256.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts loads with latency value being above 512.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "BDM100, BDM35",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts writebacks (modified to exclusive) that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000040 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L2_CODE_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000200 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_CODE_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000090 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000120 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000240 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_PF_CODE_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000091 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20003c0122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the target was non-DRAM system address.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f84000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 with no details on snoop-related information.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 with a snoop miss response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000122 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "ALL_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/other.json b/tools/perf/pmu-events/arch/x86/broadwell/other.json
new file mode 100644
index 000000000000..edf14f0d0eaf
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/other.json
@@ -0,0 +1,44 @@
+[
+ {
+ "PublicDescription": "This event counts the unhalted core cycles during which the thread is in the ring 0 privileged mode.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts unhalted core cycles during which the thread is in rings 1, 2, or 3.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts when there is a transition from ring 1,2 or 3 to ring0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles in which the L1 and L2 are locked due to a UC lock or split lock. A lock is asserted in case of locked memory access, due to noncacheable memory, locked operation that spans two cache lines, or a page walk from the noncacheable page table. L1D and L2 locks have a very high performance penalty and it is highly recommended to avoid such access.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/pipeline.json b/tools/perf/pmu-events/arch/x86/broadwell/pipeline.json
new file mode 100644
index 000000000000..78913ae87703
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/pipeline.json
@@ -0,0 +1,1417 @@
+[
+ {
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. \nNotes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. \nCounting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. \nNote: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. This event is clocked by base clock (100 Mhz) on Sandy Bridge. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "PublicDescription": "This event counts how many times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when:\n - preceding store conflicts with the load (incomplete overlap);\n - store forwarding is impossible due to u-arch limitations;\n - preceding lock RMW operations are not forwarded;\n - store has the no-forward bit set (uncacheable/page-split/masked stores);\n - all-blocking stores are used (mostly, fences and port I/O);\nand others.\nThe most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events.\nSee the table of not supported store forwards in the Optimization Guide.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles during which Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the current thread. This also includes the cycles during which the Allocator is serving another thread.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "INT_MISC.RAT_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles checkpoints in Resource Allocation Table (RAT) are recovering from JEClear or machine clear.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS).",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive\n added by GSR u-arch.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number of the divide operations executed. Uses edge-detect and a cmask value of 1 on ARITH.FPU_DIV_ACTIVE to get the number of the divide operations executed.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divider is busy executing divide operations",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a fixed-frequency event programmed to general counters. It counts when the core is unhalted at 100 Mhz.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by asm inspection of the nearby instructions.",
+ "EventCode": "0x4c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the hardware prefetch.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the reservation station (RS) is empty for the thread.\nNote: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts stalls occured due to changing prefix length (66, 67 or REX.W when they change the length of the decoded instruction). Occurrences counting is proportional to the number of prefixes in a 16B-line. This may result in the following penalties: three-cycle penalty for each LCP in a 16-byte chunk.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts not taken macro-conditional branch instructions.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions excluding calls and indirect branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired indirect branches excluding calls and return branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired indirect branches that have a return mnemonic.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired indirect calls including both register and memory indirect.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-conditional branch instructions.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-unconditional branch instructions, excluding calls and indirects.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches excluding calls and return branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches that have a return mnemonic.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired branch instructions.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired mispredicted macro conditional branch instructions.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches that have a return mnemonic.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted branch instructions.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts resource-related stall cycles. Reasons for stalls can be as follows:\n - *any* u-arch structure got full (LB, SB, RS, ROB, BOB, LM, Physical Register Reclaim Table (PRRT), or Physical History Table (PHT) slots)\n - *any* u-arch structure got empty (like INT/SIMD FreeLists)\n - FPU control word (FPCW), MXCSR\nand others. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts stall cycles caused by absence of eligible entries in the reservation station (RS). This may result from RS overflow, or from RS deallocation because of the RS array Write Port allocation scheme (each RS entry has two write ports instead of four. As a result, empty entries could not be used, although RS is not really full). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts stall cycles caused by the store buffer (SB) overflow (excluding draining from synch). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts ROB full stall cycles. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand* load request missing the L2 cache.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request missing the L1 data cache.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request (that is cycles with non-completed load waiting for its data from memory subsystem).",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand* load request missing the L2 cache.(as a footprint) * includes also L1 HW prefetch requests that may or may not be required by demands.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request missing the L1 data cache.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Number of Uops delivered by the LSD. ",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops executed from any thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "Errata": "BDM61",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts FP operations retired. For X87 FP operations that have no exceptions counting also includes flows that have several X87, or flows that use X87 uops in the exception handling.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "FP operations retired. X87 FP operations that have no exceptions:",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version (that is, uses PEBS) of the event that counts instructions retired.",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "Errata": "BDM11, BDM55",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts all actually retired uops. Counting increments by two for micro-fused uops, and by one for macro-fused and other uops. Maximal increment value for one cycle is eight.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of retirement slots used.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts cycles without actually retired uops.",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts both thread-specific (TS) and all-thread (AT) nukes.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles there was a Nuke. Account for both thread-specific and All Thread Nukes.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Maskmov false fault - counts number of time ucode passes through Maskmov flow due to instruction's mask being 0 while the flow was completed without raising a fault.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts conditional branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts both direct and indirect near call instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all (macro) branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts far branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "Errata": "BDW98",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDW98",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired. (Precise Event - PEBS)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted conditional branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all mispredicted macro branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted return instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_RETIRED.RET",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "This event counts the number of mispredicted ret instructions retired. Non PEBS",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts cases of saving new LBR records by hardware. This assumes proper enabling of LBRs and takes into account LBR filtering done by the LBR_SELECT register.",
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 6.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 7.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xe6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of micro-operations cancelled after they were dispatched from the scheduler to the execution units when the total number of physical register read ports across all dispatch ports exceeds the read bandwidth of the physical register file. The SIMD_PRF subevent applies to the following instructions: VDPPS, DPPS, VPCMPESTRI, PCMPESTRI, VPCMPESTRM, PCMPESTRM, VFMADD*, VFMADDSUB*, VFMSUB*, VMSUBADD*, VFNMADD*, VFNMSUB*. See the Broadwell Optimization Guide for more information.",
+ "EventCode": "0xA0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "UOP_DISPATCHES_CANCELLED.SIMD_PRF",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Micro-op dispatches cancelled due to insufficient SIMD physical register file read ports",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/virtual-memory.json b/tools/perf/pmu-events/arch/x86/broadwell/virtual-memory.json
new file mode 100644
index 000000000000..4301e6fbc5eb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/virtual-memory.json
@@ -0,0 +1,388 @@
+[
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (2M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (2M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles for an extended page table walk. The Extended Page directory cache differs from standard TLB caches by the operating system that use it. Virtual machine operating systems use the extended page directory cache, while guest operating systems use the standard TLB caches.",
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core misses that miss the DTLB and hit the STLB (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "ITLB_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code misses that miss the DTLB and hit the STLB (2M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L1+FB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L1+FB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L2.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L2.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x14",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L3 + XSNP.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L3 + XSNP.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "Errata": "BDM69, BDM98",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in Memory.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number of DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, and so on).",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "Errata": "BDM69",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "Errata": "BDM69",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "Errata": "BDM69",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/cache.json b/tools/perf/pmu-events/arch/x86/broadwellde/cache.json
new file mode 100644
index 000000000000..36fe398029b9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/cache.json
@@ -0,0 +1,774 @@
+[
+ {
+ "EventCode": "0x24",
+ "UMask": "0x21",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "PublicDescription": "This event counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x41",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "PublicDescription": "This event counts the number of demand Data Read requests that hit L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x30",
+ "BriefDescription": "L2 prefetch requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_MISS",
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x50",
+ "BriefDescription": "L2 prefetch requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_HIT",
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that hit L2 cache. L3 prefetch new types.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe1",
+ "BriefDescription": "Demand Data Read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "PublicDescription": "This event counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe2",
+ "BriefDescription": "RFO requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PublicDescription": "This event counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe4",
+ "BriefDescription": "L2 code requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PublicDescription": "This event counts the total number of L2 code requests.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xf8",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "PublicDescription": "This event counts the total number of requests from the L2 hardware prefetchers.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "UMask": "0x50",
+ "BriefDescription": "Not rejected writebacks that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_DEMAND_RQSTS.WB_HIT",
+ "PublicDescription": "This event counts the number of WB requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x41",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PublicDescription": "This event counts core-originated cacheable demand requests that miss the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x4f",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PublicDescription": "This event counts core-originated cacheable demand requests that refer to the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PublicDescription": "This event counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand; from the demand Hit FB, if it is allocated by hardware or software prefetch.\nNote: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts duration of L1D miss outstanding in cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x51",
+ "UMask": "0x1",
+ "BriefDescription": "L1D data line replacements",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D.REPLACEMENT",
+ "PublicDescription": "This event counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.\nNote: A prefetch promoted to Demand is counted from the promotion point.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles when L1D is locked",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "PublicDescription": "This event counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x2",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "PublicDescription": "This event counts both cacheable and noncachaeble code read requests.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x4",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PublicDescription": "This event counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x8",
+ "BriefDescription": "Demand and prefetch data reads",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PublicDescription": "This event counts the demand and prefetch data reads. All Core Data Reads include cacheable \"Demands\" and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb2",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "PublicDescription": "This event counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.\nNote: Writeback pending FIFO has six entries.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x11",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x12",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts store uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x21",
+ "BriefDescription": "Retired load uops with locked access.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "Errata": "BDM35",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with locked access retired to the architected path.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x41",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted load uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x42",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted store uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x81",
+ "BriefDescription": "All retired load uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "PublicDescription": "This event counts load uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement. This event also counts SW prefetches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x82",
+ "BriefDescription": "All retired store uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "PublicDescription": "This event counts store uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement.",
+ "SampleAfterValue": "2000003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the nearest-level (L1) cache.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load. This event also counts SW prefetches independent of the actual data source.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "Errata": "BDM35",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the mid-level (L2) cache.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were data hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were data hits in the last-level (L3) cache without snoops required.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops misses in L1 cache as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the nearest-level (L1) cache. Counting excludes unknown and UC data source.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x10",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the mid-level (L2) cache. Counting excludes unknown and UC data source.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x20",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_MISS",
+ "Errata": "BDM100, BDE70",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x40",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were load uops missed L1 but hit a fill buffer due to a preceding miss to the same cache line with the data not ready.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_MISS",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 Hit and a cross-core snoop missed in the on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 hit and a cross-core snoop hit in the on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared L3.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HITM",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were HitM responses from a core on same socket (shared L3).",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops which data sources were hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_NONE",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the last-level (L3) cache without snoops required.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x1",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
+ "Errata": "BDE70, BDM100",
+ "PublicDescription": "Retired load uop whose Data Source was: local DRAM either Snoop not needed or Snoop Miss (RspI).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "PublicDescription": "This event counts Demand Data Read requests that access L2 cache, including rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x2",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.RFO",
+ "PublicDescription": "This event counts Read for Ownership (RFO) requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.CODE_RD",
+ "PublicDescription": "This event counts the number of L2 cache accesses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x8",
+ "BriefDescription": "L2 or L3 HW prefetches that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_PF",
+ "PublicDescription": "This event counts L2 or L3 HW prefetches that access L2 cache including rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x10",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L1D_WB",
+ "PublicDescription": "This event counts L1D writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x20",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_FILL",
+ "PublicDescription": "This event counts L2 fill requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x40",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_WB",
+ "PublicDescription": "This event counts L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x80",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "PublicDescription": "This event counts transactions that access the L2 pipe including snoops, pagewalks, and so on.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x1",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.I",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Invalidate state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x2",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.S",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Shared state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.E",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Exclusive state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x7",
+ "BriefDescription": "L2 cache lines filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.ALL",
+ "PublicDescription": "This event counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "UMask": "0x5",
+ "BriefDescription": "Clean L2 cache lines evicted by demand.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf4",
+ "UMask": "0x10",
+ "BriefDescription": "Split locks in SQ",
+ "Counter": "0,1,2,3",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "PublicDescription": "This event counts the number of split locks in the super queue.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x42",
+ "BriefDescription": "RFO requests that hit L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x22",
+ "BriefDescription": "RFO requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x44",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x24",
+ "BriefDescription": "L2 cache misses when fetching instructions.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x27",
+ "BriefDescription": "Demand requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe7",
+ "BriefDescription": "Demand requests to L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x3f",
+ "BriefDescription": "All requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xff",
+ "BriefDescription": "All L2 requests.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "CounterMask": "6",
+ "Errata": "BDM76",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/floating-point.json b/tools/perf/pmu-events/arch/x86/broadwellde/floating-point.json
new file mode 100644
index 000000000000..4ae1ea24f22f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/floating-point.json
@@ -0,0 +1,171 @@
+[
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x8",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "Errata": "BDM30",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from AVX-256 to legacy SSE when penalty is applicable.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x10",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "Errata": "BDM30",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from legacy SSE to AVX-256 when penalty is applicable.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x1",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x2",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x4",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x10",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x2",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of x87 floating point (FP) micro-code assist (numeric overflow/underflow, inexact result) when the output value (destination register) is invalid.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x4",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts x87 floating point (FP) micro-code assist (invalid operation, denormal operand, SNaN operand) when the input value (one of the source operands to an FP instruction) is invalid.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of SSE* floating point (FP) micro-code assist (numeric overflow/underflow) when the output value (destination register) is invalid. Counting covers only cases involving penalties that require micro-code assist intervention.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x10",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts any input SSE* FP assist - invalid operation, denormal operand, dividing by zero, SNaN operand. Counting includes only cases involving penalties that required micro-code assist intervention.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x1e",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.ANY",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc7",
+ "UMask": "0x20",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x3",
+ "BriefDescription": "Number of SSE/AVX computational scalar floating-point instructions retired. Applies to SSE* and AVX* scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x3c",
+ "BriefDescription": "Number of SSE/AVX computational packed floating-point instructions retired. Applies to SSE* and AVX*, packed, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.PACKED",
+ "SampleAfterValue": "2000004",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x2a",
+ "BriefDescription": "Number of SSE/AVX computational single precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SINGLE",
+ "SampleAfterValue": "2000005",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x15",
+ "BriefDescription": "Number of SSE/AVX computational double precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.DOUBLE",
+ "SampleAfterValue": "2000006",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/frontend.json b/tools/perf/pmu-events/arch/x86/broadwellde/frontend.json
new file mode 100644
index 000000000000..06bf0a40e568
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/frontend.json
@@ -0,0 +1,286 @@
+[
+ {
+ "EventCode": "0x79",
+ "UMask": "0x2",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.EMPTY",
+ "PublicDescription": "This counts the number of cycles that the instruction decoder queue is empty and can indicate that the application may be bound in the front end. It does not determine whether there are uops being delivered to the Alloc stage since uops can be delivered by bypass skipping the Instruction Decode Queue (IDQ) when it is empty.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "PublicDescription": "This event counts the number of uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x20",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "PublicDescription": "This event counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_UOPS",
+ "PublicDescription": "This event counts the total number of uops delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x3c",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.HIT",
+ "PublicDescription": "This event counts the number of both cacheable and noncacheable Instruction Cache, Streaming Buffer and Victim Cache Reads including UC fetches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x2",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes Uncacheable accesses.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.MISSES",
+ "PublicDescription": "This event counts the number of instruction cache, streaming buffer and victim cache misses. Counting includes UC accesses.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.IFDATA_STALL",
+ "PublicDescription": "This event counts cycles during which the demand fetch waits for data (wfdM104H) from L2 or iSB (opportunistic hit).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "PublicDescription": "This event counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding ?4 ? x? when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when:\n a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread;\n b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions); \n c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "CounterMask": "3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >=3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "UMask": "0x2",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "Counter": "0,1,2,3",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "PublicDescription": "This event counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. \nMM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.\nPenalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 0?2 cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_SWITCHES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/memory.json b/tools/perf/pmu-events/arch/x86/broadwellde/memory.json
new file mode 100644
index 000000000000..cfa1e5876ec3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/memory.json
@@ -0,0 +1,433 @@
+[
+ {
+ "EventCode": "0x05",
+ "UMask": "0x1",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "PublicDescription": "This event counts speculative cache-line split load uops dispatched to the L1 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "UMask": "0x2",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "PublicDescription": "This event counts speculative cache line split store-address (STA) uops dispatched to the L1 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times a TSX line had a cache conflict",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times we could not allocate Lock Buffer",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x1",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC1",
+ "PublicDescription": "Unfriendly TSX abort triggered by a flowmarker.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC2",
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x4",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC3",
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x8",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC4",
+ "PublicDescription": "RTM region detected inside HLE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x10",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:\n1. memory disambiguation,\n2. external snoop, or\n3. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times we entered an HLE region; does not count nested transactions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.START",
+ "PublicDescription": "Number of times we entered an HLE region\n does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times HLE commit succeeded",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times HLE abort was triggered",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC1",
+ "PublicDescription": "Number of times an HLE abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an HLE execution aborted due to uncommon conditions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC2",
+ "PublicDescription": "Number of times the TSX watchdog signaled an HLE abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC3",
+ "PublicDescription": "Number of times a disallowed operation caused an HLE abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC4",
+ "PublicDescription": "Number of times HLE caused a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts)",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times HLE aborted and was not due to the abort conditions in subevents 3-6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times we entered an RTM region; does not count nested transactions",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.START",
+ "PublicDescription": "Number of times we entered an RTM region\n does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times RTM commit succeeded",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times RTM abort was triggered",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "PublicDescription": "Number of times RTM abort was triggered .",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC1",
+ "PublicDescription": "Number of times an RTM abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC2",
+ "PublicDescription": "Number of times the TSX watchdog signaled an RTM abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC3",
+ "PublicDescription": "Number of times a disallowed operation caused an RTM abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC4",
+ "PublicDescription": "Number of times a RTM caused a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times RTM aborted and was not due to the abort conditions in subevents 3-6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 4",
+ "PEBS": "2",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above four.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 8",
+ "PEBS": "2",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above eight.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 16",
+ "PEBS": "2",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 16.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 32",
+ "PEBS": "2",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 32.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 64",
+ "PEBS": "2",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 64.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "2003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 128",
+ "PEBS": "2",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 128.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "1009",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 256",
+ "PEBS": "2",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 256.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "503",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 512",
+ "PEBS": "2",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 512.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "101",
+ "CounterHTOff": "3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/other.json b/tools/perf/pmu-events/arch/x86/broadwellde/other.json
new file mode 100644
index 000000000000..718fcb1db2ee
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/other.json
@@ -0,0 +1,44 @@
+[
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0",
+ "PublicDescription": "This event counts the unhalted core cycles during which the thread is in the ring 0 privileged mode.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x2",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING123",
+ "PublicDescription": "This event counts unhalted core cycles during which the thread is in rings 1, 2, or 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts when there is a transition from ring 1,2 or 3 to ring0.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "PublicDescription": "This event counts cycles in which the L1 and L2 are locked due to a UC lock or split lock. A lock is asserted in case of locked memory access, due to noncacheable memory, locked operation that spans two cache lines, or a page walk from the noncacheable page table. L1D and L2 locks have a very high performance penalty and it is highly recommended to avoid such access.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/pipeline.json b/tools/perf/pmu-events/arch/x86/broadwellde/pipeline.json
new file mode 100644
index 000000000000..02b4e1035f2d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/pipeline.json
@@ -0,0 +1,1417 @@
+[
+ {
+ "EventCode": "0x00",
+ "UMask": "0x1",
+ "BriefDescription": "Instructions retired from execution.",
+ "Counter": "Fixed counter 1",
+ "EventName": "INST_RETIRED.ANY",
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. \nNotes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. \nCounting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x3",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "Counter": "Fixed counter 3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. \nNote: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. This event is clocked by base clock (100 Mhz) on Sandy Bridge. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x2",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "PublicDescription": "This event counts how many times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when:\n - preceding store conflicts with the load (incomplete overlap);\n - store forwarding is impossible due to u-arch limitations;\n - preceding lock RMW operations are not forwarded;\n - store has the no-forward bit set (uncacheable/page-split/masked stores);\n - all-blocking stores are used (mostly, fences and port I/O);\nand others.\nThe most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events.\nSee the table of not supported store forwards in the Optimization Guide.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x8",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x07",
+ "UMask": "0x1",
+ "BriefDescription": "False dependencies in MOB due to partial compare",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PublicDescription": "This event counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RAT_STALL_CYCLES",
+ "PublicDescription": "This event counts the number of cycles during which Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the current thread. This also includes the cycles during which the Allocator is serving another thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...)",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "Cycles checkpoints in Resource Allocation Table (RAT) are recovering from JEClear or machine clear.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PublicDescription": "This event counts the number of Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x10",
+ "BriefDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "PublicDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive\n added by GSR u-arch.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x20",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x40",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x14",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when divider is busy executing divide operations",
+ "Counter": "0,1,2,3",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "PublicDescription": "This event counts the number of the divide operations executed. Uses edge-detect and a cmask value of 1 on ARITH.FPU_DIV_ACTIVE to get the number of the divide operations executed.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "PublicDescription": "This is a fixed-frequency event programmed to general counters. It counts when the core is unhalted at 100 Mhz.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3c",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x4c",
+ "UMask": "0x1",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by asm inspection of the nearby instructions.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4C",
+ "UMask": "0x2",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the hardware prefetch.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x1",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x2",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x4",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PublicDescription": "This event counts cycles during which the reservation station (RS) is empty for the thread.\nNote: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "UMask": "0x1",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "Counter": "0,1,2,3",
+ "EventName": "ILD_STALL.LCP",
+ "PublicDescription": "This event counts stalls occured due to changing prefix length (66, 67 or REX.W when they change the length of the decoded instruction). Occurrences counting is proportional to the number of prefixes in a 16B-line. This may result in the following penalties: three-cycle penalty for each LCP in a 16-byte chunk.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts not taken macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x82",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions excluding calls and indirect branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts taken speculative and retired indirect branches excluding calls and return branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "PublicDescription": "This event counts taken speculative and retired indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x90",
+ "BriefDescription": "Taken speculative and retired direct near calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts taken speculative and retired direct near calls.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired indirect calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts taken speculative and retired indirect calls including both register and memory indirect.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc2",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-unconditional branch instructions, excluding calls and indirects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc4",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches excluding calls and return branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc8",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xd0",
+ "BriefDescription": "Speculative and retired direct near calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired direct near calls.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc4",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts both taken and not taken mispredicted indirect branches excluding calls and returns.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x1",
+ "BriefDescription": "Resource-related stall cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "PublicDescription": "This event counts resource-related stall cycles. Reasons for stalls can be as follows:\n - *any* u-arch structure got full (LB, SB, RS, ROB, BOB, LM, Physical Register Reclaim Table (PRRT), or Physical History Table (PHT) slots)\n - *any* u-arch structure got empty (like INT/SIMD FreeLists)\n - FPU control word (FPCW), MXCSR\nand others. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.RS",
+ "PublicDescription": "This event counts stall cycles caused by absence of eligible entries in the reservation station (RS). This may result from RS overflow, or from RS deallocation because of the RS array Write Port allocation scheme (each RS entry has two write ports instead of four. As a result, empty entries could not be used, although RS is not really full). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PublicDescription": "This event counts stall cycles caused by the store buffer (SB) overflow (excluding draining from synch). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "PublicDescription": "This event counts ROB full stall cycles. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "CounterMask": "1",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand* load request missing the L2 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "CounterMask": "8",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request missing the L1 data cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "CounterMask": "2",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request (that is cycles with non-completed load waiting for its data from memory subsystem).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x4",
+ "BriefDescription": "Total execution stalls",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "CounterMask": "4",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x5",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "CounterMask": "5",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand* load request missing the L2 cache.(as a footprint) * includes also L1 HW prefetch requests that may or may not be required by demands.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x6",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "CounterMask": "6",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0xc",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "CounterMask": "12",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request missing the L1 data cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.UOPS",
+ "PublicDescription": "Number of Uops delivered by the LSD. ",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x2",
+ "BriefDescription": "Number of uops executed on the core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "PublicDescription": "Number of uops executed from any thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x0",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.ANY_P",
+ "Errata": "BDM61",
+ "PublicDescription": "This event counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x2",
+ "BriefDescription": "FP operations retired. X87 FP operations that have no exceptions:",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.X87",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts FP operations retired. For X87 FP operations that have no exceptions counting also includes flows that have several X87, or flows that use X87 uops in the exception handling.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x1",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "PEBS": "2",
+ "Counter": "1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "Errata": "BDM11, BDM55",
+ "PublicDescription": "This is a precise version (that is, uses PEBS) of the event that counts instructions retired.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Actually retired uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.ALL",
+ "PublicDescription": "This event counts all actually retired uops. Counting increments by two for micro-fused uops, and by one for macro-fused and other uops. Maximal increment value for one cycle is eight.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x2",
+ "BriefDescription": "Retirement slots used.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of retirement slots used.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts cycles without actually retired uops.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "CounterMask": "10",
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles there was a Nuke. Account for both thread-specific and All Thread Nukes.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "PublicDescription": "This event counts both thread-specific (TS) and all-thread (AT) nukes.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x4",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PublicDescription": "This event counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x20",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "PublicDescription": "Maskmov false fault - counts number of time ucode passes through Maskmov flow due to instruction's mask being 0 while the flow was completed without raising a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x1",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x2",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts both direct and indirect near call instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x0",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "This event counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x8",
+ "BriefDescription": "Return instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts return instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x10",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x20",
+ "BriefDescription": "Taken branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x40",
+ "BriefDescription": "Far branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "Errata": "BDW98",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts far branch instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x4",
+ "BriefDescription": "All (macro) branch instructions retired. (Precise Event - PEBS)",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "Errata": "BDW98",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x1",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x0",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "This event counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x8",
+ "BriefDescription": "This event counts the number of mispredicted ret instructions retired. Non PEBS",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.RET",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted return instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x4",
+ "BriefDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS)",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCC",
+ "UMask": "0x20",
+ "BriefDescription": "Count cases of saving new LBR",
+ "Counter": "0,1,2,3",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "PublicDescription": "This event counts cases of saving new LBR records by hardware. This assumes proper enabling of LBRs and takes into account LBR filtering done by the LBR_SELECT register.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 1.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 2.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 3.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 4.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 5.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 6.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 7.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x20",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "CounterMask": "3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xe6",
+ "UMask": "0x1f",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "CounterMask": "8",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x4",
+ "BriefDescription": "Total execution stalls.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0xc",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "CounterMask": "12",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x5",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "CounterMask": "5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x6",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "CounterMask": "6",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "CounterMask": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "Invert": "1",
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "CounterMask": "1",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA0",
+ "UMask": "0x3",
+ "BriefDescription": "Micro-op dispatches cancelled due to insufficient SIMD physical register file read ports",
+ "Counter": "0,1,2,3",
+ "EventName": "UOP_DISPATCHES_CANCELLED.SIMD_PRF",
+ "PublicDescription": "This event counts the number of micro-operations cancelled after they were dispatched from the scheduler to the execution units when the total number of physical register read ports across all dispatch ports exceeds the read bandwidth of the physical register file. The SIMD_PRF subevent applies to the following instructions: VDPPS, DPPS, VPCMPESTRI, PCMPESTRI, VPCMPESTRM, PCMPESTRM, VFMADD*, VFMADDSUB*, VFMSUB*, VMSUBADD*, VFNMADD*, VFNMSUB*. See the Broadwell Optimization Guide for more information.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "CounterMask": "3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "PublicDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/virtual-memory.json b/tools/perf/pmu-events/arch/x86/broadwellde/virtual-memory.json
new file mode 100644
index 000000000000..5ce8b67ba076
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/virtual-memory.json
@@ -0,0 +1,388 @@
+[
+ {
+ "EventCode": "0x08",
+ "UMask": "0x1",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x2",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x4",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x8",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x20",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x40",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x1",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x2",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x4",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x8",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x20",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x40",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "UMask": "0x10",
+ "BriefDescription": "Cycle count for an Extended Page table walk.",
+ "Counter": "0,1,2,3",
+ "EventName": "EPT.WALK_CYCLES",
+ "PublicDescription": "This event counts cycles for an extended page table walk. The Extended Page directory cache differs from standard TLB caches by the operating system that use it. Virtual machine operating systems use the extended page directory cache, while guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x1",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x2",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x4",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x8",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x20",
+ "BriefDescription": "Core misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x40",
+ "BriefDescription": "Code misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAE",
+ "UMask": "0x1",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "PublicDescription": "This event counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x11",
+ "BriefDescription": "Number of DTLB page walker hits in the L1+FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L1",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x21",
+ "BriefDescription": "Number of ITLB page walker hits in the L1+FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L1",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x12",
+ "BriefDescription": "Number of DTLB page walker hits in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L2",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x22",
+ "BriefDescription": "Number of ITLB page walker hits in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L2",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x14",
+ "BriefDescription": "Number of DTLB page walker hits in the L3 + XSNP.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L3",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x24",
+ "BriefDescription": "Number of ITLB page walker hits in the L3 + XSNP.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L3",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x18",
+ "BriefDescription": "Number of DTLB page walker hits in Memory.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_MEMORY",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x1",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "PublicDescription": "This event counts the number of DTLB flush attempts of the thread-specific entries.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x20",
+ "BriefDescription": "STLB flush attempts",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PublicDescription": "This event counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, and so on).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0xe",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x60",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0xe",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x60",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0xe",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x60",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/cache.json b/tools/perf/pmu-events/arch/x86/broadwellx/cache.json
new file mode 100644
index 000000000000..d1d043829b95
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/cache.json
@@ -0,0 +1,942 @@
+[
+ {
+ "EventCode": "0x24",
+ "UMask": "0x21",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "PublicDescription": "This event counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x41",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "PublicDescription": "This event counts the number of demand Data Read requests that hit L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x30",
+ "BriefDescription": "L2 prefetch requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_MISS",
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x50",
+ "BriefDescription": "L2 prefetch requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_HIT",
+ "PublicDescription": "This event counts the number of requests from the L2 hardware prefetchers that hit L2 cache. L3 prefetch new types.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe1",
+ "BriefDescription": "Demand Data Read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "PublicDescription": "This event counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe2",
+ "BriefDescription": "RFO requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PublicDescription": "This event counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe4",
+ "BriefDescription": "L2 code requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PublicDescription": "This event counts the total number of L2 code requests.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xf8",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "PublicDescription": "This event counts the total number of requests from the L2 hardware prefetchers.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "UMask": "0x50",
+ "BriefDescription": "Not rejected writebacks that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_DEMAND_RQSTS.WB_HIT",
+ "PublicDescription": "This event counts the number of WB requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x41",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PublicDescription": "This event counts core-originated cacheable demand requests that miss the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x4f",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PublicDescription": "This event counts core-originated cacheable demand requests that refer to the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PublicDescription": "This event counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand; from the demand Hit FB, if it is allocated by hardware or software prefetch.\nNote: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts duration of L1D miss outstanding in cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x51",
+ "UMask": "0x1",
+ "BriefDescription": "L1D data line replacements",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D.REPLACEMENT",
+ "PublicDescription": "This event counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.\nNote: A prefetch promoted to Demand is counted from the promotion point.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "CounterMask": "1",
+ "Errata": "BDM76",
+ "PublicDescription": "This event counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The \"Offcore outstanding\" state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles when L1D is locked",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "PublicDescription": "This event counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x2",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "PublicDescription": "This event counts both cacheable and noncachaeble code read requests.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x4",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PublicDescription": "This event counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x8",
+ "BriefDescription": "Demand and prefetch data reads",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PublicDescription": "This event counts the demand and prefetch data reads. All Core Data Reads include cacheable \"Demands\" and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb2",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "PublicDescription": "This event counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.\nNote: Writeback pending FIFO has six entries.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x11",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x12",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts store uops with true STLB miss retired to the architected path. True STLB miss is an uop triggering page walk that gets completed without blocks, and later gets retired. This page walk can end up with or without a fault.",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x21",
+ "BriefDescription": "Retired load uops with locked access.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "Errata": "BDM35",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts load uops with locked access retired to the architected path.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x41",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted load uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x42",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts line-splitted store uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x81",
+ "BriefDescription": "All retired load uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "PublicDescription": "This event counts load uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement. This event also counts SW prefetches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x82",
+ "BriefDescription": "All retired store uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "PublicDescription": "This event counts store uops retired to the architected path with a filter on bits 0 and 1 applied.\nNote: This event counts AVX-256bit load/store double-pump memory uops as a single uop at retirement.",
+ "SampleAfterValue": "2000003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the nearest-level (L1) cache.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load. This event also counts SW prefetches independent of the actual data source.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "Errata": "BDM35",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the mid-level (L2) cache.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were data hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were data hits in the last-level (L3) cache without snoops required.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops misses in L1 cache as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the nearest-level (L1) cache. Counting excludes unknown and UC data source.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x10",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were misses in the mid-level (L2) cache. Counting excludes unknown and UC data source.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x20",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_MISS",
+ "Errata": "BDM100, BDE70",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x40",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were load uops missed L1 but hit a fill buffer due to a preceding miss to the same cache line with the data not ready.\nNote: Only two data-sources of L1/FB are applicable for AVX-256bit even though the corresponding AVX load could be serviced by a deeper level in the memory hierarchy. Data source is reported for the Low-half load.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_MISS",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 Hit and a cross-core snoop missed in the on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were L3 hit and a cross-core snoop hit in the on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared L3.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HITM",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were HitM responses from a core on same socket (shared L3).",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops which data sources were hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_NONE",
+ "Errata": "BDM100",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts retired load uops which data sources were hits in the last-level (L3) cache without snoops required.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x1",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
+ "Errata": "BDE70, BDM100",
+ "PublicDescription": "Retired load uop whose Data Source was: local DRAM either Snoop not needed or Snoop Miss (RspI).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uop whose Data Source was: remote DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_DRAM",
+ "Errata": "BDE70",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x10",
+ "BriefDescription": "Retired load uop whose Data Source was: Remote cache HITM",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_HITM",
+ "Errata": "BDE70",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x20",
+ "BriefDescription": "Retired load uop whose Data Source was: forwarded from remote cache",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD",
+ "Errata": "BDE70",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "PublicDescription": "This event counts Demand Data Read requests that access L2 cache, including rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x2",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.RFO",
+ "PublicDescription": "This event counts Read for Ownership (RFO) requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.CODE_RD",
+ "PublicDescription": "This event counts the number of L2 cache accesses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x8",
+ "BriefDescription": "L2 or L3 HW prefetches that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_PF",
+ "PublicDescription": "This event counts L2 or L3 HW prefetches that access L2 cache including rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x10",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L1D_WB",
+ "PublicDescription": "This event counts L1D writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x20",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_FILL",
+ "PublicDescription": "This event counts L2 fill requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x40",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_WB",
+ "PublicDescription": "This event counts L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "UMask": "0x80",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "PublicDescription": "This event counts transactions that access the L2 pipe including snoops, pagewalks, and so on.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x1",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.I",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Invalidate state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x2",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.S",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Shared state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.E",
+ "PublicDescription": "This event counts the number of L2 cache lines in the Exclusive state filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x7",
+ "BriefDescription": "L2 cache lines filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.ALL",
+ "PublicDescription": "This event counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "UMask": "0x5",
+ "BriefDescription": "Clean L2 cache lines evicted by demand.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf4",
+ "UMask": "0x10",
+ "BriefDescription": "Split locks in SQ",
+ "Counter": "0,1,2,3",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "PublicDescription": "This event counts the number of split locks in the super queue.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x42",
+ "BriefDescription": "RFO requests that hit L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x22",
+ "BriefDescription": "RFO requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x44",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x24",
+ "BriefDescription": "L2 cache misses when fetching instructions.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x27",
+ "BriefDescription": "Demand requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe7",
+ "BriefDescription": "Demand requests to L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x3f",
+ "BriefDescription": "All requests that miss L2 cache.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xff",
+ "BriefDescription": "All L2 requests.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "CounterMask": "6",
+ "Errata": "BDM76",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all requests that hit in the L3",
+ "MSRValue": "0x3f803c8fff",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c07f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c07f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3",
+ "MSRValue": "0x3f803c0100",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/floating-point.json b/tools/perf/pmu-events/arch/x86/broadwellx/floating-point.json
new file mode 100644
index 000000000000..4ae1ea24f22f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/floating-point.json
@@ -0,0 +1,171 @@
+[
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x8",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "Errata": "BDM30",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from AVX-256 to legacy SSE when penalty is applicable.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x10",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "Errata": "BDM30",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of transitions from legacy SSE to AVX-256 when penalty is applicable.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x1",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x2",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x4",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x10",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x2",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of x87 floating point (FP) micro-code assist (numeric overflow/underflow, inexact result) when the output value (destination register) is invalid.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x4",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts x87 floating point (FP) micro-code assist (invalid operation, denormal operand, SNaN operand) when the input value (one of the source operands to an FP instruction) is invalid.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of SSE* floating point (FP) micro-code assist (numeric overflow/underflow) when the output value (destination register) is invalid. Counting covers only cases involving penalties that require micro-code assist intervention.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x10",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts any input SSE* FP assist - invalid operation, denormal operand, dividing by zero, SNaN operand. Counting includes only cases involving penalties that required micro-code assist intervention.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x1e",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.ANY",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc7",
+ "UMask": "0x20",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x3",
+ "BriefDescription": "Number of SSE/AVX computational scalar floating-point instructions retired. Applies to SSE* and AVX* scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x3c",
+ "BriefDescription": "Number of SSE/AVX computational packed floating-point instructions retired. Applies to SSE* and AVX*, packed, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RSQRT RCP SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.PACKED",
+ "SampleAfterValue": "2000004",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x2a",
+ "BriefDescription": "Number of SSE/AVX computational single precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.SINGLE",
+ "SampleAfterValue": "2000005",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC7",
+ "UMask": "0x15",
+ "BriefDescription": "Number of SSE/AVX computational double precision floating-point instructions retired. Applies to SSE* and AVX*scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ?.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ARITH_INST_RETIRED.DOUBLE",
+ "SampleAfterValue": "2000006",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/frontend.json b/tools/perf/pmu-events/arch/x86/broadwellx/frontend.json
new file mode 100644
index 000000000000..06bf0a40e568
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/frontend.json
@@ -0,0 +1,286 @@
+[
+ {
+ "EventCode": "0x79",
+ "UMask": "0x2",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.EMPTY",
+ "PublicDescription": "This counts the number of cycles that the instruction decoder queue is empty and can indicate that the application may be bound in the front end. It does not determine whether there are uops being delivered to the Alloc stage since uops can be delivered by bypass skipping the Instruction Decode Queue (IDQ) when it is empty.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "PublicDescription": "This event counts the number of uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x20",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "PublicDescription": "This event counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_UOPS",
+ "PublicDescription": "This event counts the total number of uops delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may \"bypass\" the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while the Microcode Sequencer (MS) is busy. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may \"bypass\" the IDQ.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x3c",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may \"bypass\" the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.HIT",
+ "PublicDescription": "This event counts the number of both cacheable and noncacheable Instruction Cache, Streaming Buffer and Victim Cache Reads including UC fetches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x2",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes Uncacheable accesses.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.MISSES",
+ "PublicDescription": "This event counts the number of instruction cache, streaming buffer and victim cache misses. Counting includes UC accesses.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.IFDATA_STALL",
+ "PublicDescription": "This event counts cycles during which the demand fetch waits for data (wfdM104H) from L2 or iSB (opportunistic hit).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "PublicDescription": "This event counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding ?4 ? x? when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when:\n a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread;\n b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions); \n c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "CounterMask": "3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >=3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "UMask": "0x2",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "Counter": "0,1,2,3",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "PublicDescription": "This event counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. \nMM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.\nPenalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 0?2 cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_SWITCHES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/memory.json b/tools/perf/pmu-events/arch/x86/broadwellx/memory.json
new file mode 100644
index 000000000000..1204ea8ff30d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/memory.json
@@ -0,0 +1,649 @@
+[
+ {
+ "EventCode": "0x05",
+ "UMask": "0x1",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "PublicDescription": "This event counts speculative cache-line split load uops dispatched to the L1 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "UMask": "0x2",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "PublicDescription": "This event counts speculative cache line split store-address (STA) uops dispatched to the L1 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times a TSX line had a cache conflict",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to an evicted line caused by a transaction overflow.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times we could not allocate Lock Buffer",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x1",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC1",
+ "PublicDescription": "Unfriendly TSX abort triggered by a flowmarker.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC2",
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x4",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC3",
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x8",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC4",
+ "PublicDescription": "RTM region detected inside HLE.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x10",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:\n1. memory disambiguation,\n2. external snoop, or\n3. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times we entered an HLE region; does not count nested transactions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.START",
+ "PublicDescription": "Number of times we entered an HLE region\n does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times HLE commit succeeded",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times HLE abort was triggered",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC1",
+ "PublicDescription": "Number of times an HLE abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an HLE execution aborted due to uncommon conditions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC2",
+ "PublicDescription": "Number of times the TSX watchdog signaled an HLE abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC3",
+ "PublicDescription": "Number of times a disallowed operation caused an HLE abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC4",
+ "PublicDescription": "Number of times HLE caused a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts)",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times HLE aborted and was not due to the abort conditions in subevents 3-6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times we entered an RTM region; does not count nested transactions",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.START",
+ "PublicDescription": "Number of times we entered an RTM region\n does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times RTM commit succeeded",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times RTM abort was triggered",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "PublicDescription": "Number of times RTM abort was triggered .",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC1",
+ "PublicDescription": "Number of times an RTM abort was attributed to a Memory condition (See TSX_Memory event for additional details).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC2",
+ "PublicDescription": "Number of times the TSX watchdog signaled an RTM abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC3",
+ "PublicDescription": "Number of times a disallowed operation caused an RTM abort.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC4",
+ "PublicDescription": "Number of times a RTM caused a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times RTM aborted and was not due to the abort conditions in subevents 3-6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 4",
+ "PEBS": "2",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above four.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 8",
+ "PEBS": "2",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above eight.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 16",
+ "PEBS": "2",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 16.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 32",
+ "PEBS": "2",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 32.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 64",
+ "PEBS": "2",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 64.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "2003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 128",
+ "PEBS": "2",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 128.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "1009",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 256",
+ "PEBS": "2",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 256.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "503",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 512",
+ "PEBS": "2",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "Errata": "BDM100, BDM35",
+ "PublicDescription": "This event counts loads with latency value being above 512.",
+ "TakenAlone": "1",
+ "SampleAfterValue": "101",
+ "CounterHTOff": "3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all requests that miss in the L3",
+ "MSRValue": "0x3fbfc08fff",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and clean or shared data is transferred from remote cache",
+ "MSRValue": "0x087fc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the data is returned from remote dram",
+ "MSRValue": "0x063bc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x06040007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss in the L3",
+ "MSRValue": "0x3fbfc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0604000244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0604000122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3",
+ "MSRValue": "0x3fbfc00122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache",
+ "MSRValue": "0x087fc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram",
+ "MSRValue": "0x063bc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0604000091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3",
+ "MSRValue": "0x3fbfc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00200",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3",
+ "MSRValue": "0x3fbfc00100",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc00002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/other.json b/tools/perf/pmu-events/arch/x86/broadwellx/other.json
new file mode 100644
index 000000000000..718fcb1db2ee
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/other.json
@@ -0,0 +1,44 @@
+[
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0",
+ "PublicDescription": "This event counts the unhalted core cycles during which the thread is in the ring 0 privileged mode.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x2",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING123",
+ "PublicDescription": "This event counts unhalted core cycles during which the thread is in rings 1, 2, or 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts when there is a transition from ring 1,2 or 3 to ring0.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "PublicDescription": "This event counts cycles in which the L1 and L2 are locked due to a UC lock or split lock. A lock is asserted in case of locked memory access, due to noncacheable memory, locked operation that spans two cache lines, or a page walk from the noncacheable page table. L1D and L2 locks have a very high performance penalty and it is highly recommended to avoid such access.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/pipeline.json b/tools/perf/pmu-events/arch/x86/broadwellx/pipeline.json
new file mode 100644
index 000000000000..02b4e1035f2d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/pipeline.json
@@ -0,0 +1,1417 @@
+[
+ {
+ "EventCode": "0x00",
+ "UMask": "0x1",
+ "BriefDescription": "Instructions retired from execution.",
+ "Counter": "Fixed counter 1",
+ "EventName": "INST_RETIRED.ANY",
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. \nNotes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. \nCounting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x3",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "Counter": "Fixed counter 3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. \nNote: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. This event is clocked by base clock (100 Mhz) on Sandy Bridge. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x2",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "PublicDescription": "This event counts how many times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when:\n - preceding store conflicts with the load (incomplete overlap);\n - store forwarding is impossible due to u-arch limitations;\n - preceding lock RMW operations are not forwarded;\n - store has the no-forward bit set (uncacheable/page-split/masked stores);\n - all-blocking stores are used (mostly, fences and port I/O);\nand others.\nThe most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events.\nSee the table of not supported store forwards in the Optimization Guide.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x8",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x07",
+ "UMask": "0x1",
+ "BriefDescription": "False dependencies in MOB due to partial compare",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PublicDescription": "This event counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RAT_STALL_CYCLES",
+ "PublicDescription": "This event counts the number of cycles during which Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the current thread. This also includes the cycles during which the Allocator is serving another thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...)",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "Cycles checkpoints in Resource Allocation Table (RAT) are recovering from JEClear or machine clear.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PublicDescription": "This event counts the number of Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x10",
+ "BriefDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "PublicDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive\n added by GSR u-arch.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x20",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x40",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x14",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when divider is busy executing divide operations",
+ "Counter": "0,1,2,3",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "PublicDescription": "This event counts the number of the divide operations executed. Uses edge-detect and a cmask value of 1 on ARITH.FPU_DIV_ACTIVE to get the number of the divide operations executed.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "PublicDescription": "This is a fixed-frequency event programmed to general counters. It counts when the core is unhalted at 100 Mhz.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3c",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x4c",
+ "UMask": "0x1",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by asm inspection of the nearby instructions.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4C",
+ "UMask": "0x2",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the hardware prefetch.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x1",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x2",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x4",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PublicDescription": "This event counts cycles during which the reservation station (RS) is empty for the thread.\nNote: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "UMask": "0x1",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "Counter": "0,1,2,3",
+ "EventName": "ILD_STALL.LCP",
+ "PublicDescription": "This event counts stalls occured due to changing prefix length (66, 67 or REX.W when they change the length of the decoded instruction). Occurrences counting is proportional to the number of prefixes in a 16B-line. This may result in the following penalties: three-cycle penalty for each LCP in a 16-byte chunk.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts not taken macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x82",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "PublicDescription": "This event counts taken speculative and retired macro-conditional branch instructions excluding calls and indirect branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts taken speculative and retired indirect branches excluding calls and return branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "PublicDescription": "This event counts taken speculative and retired indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x90",
+ "BriefDescription": "Taken speculative and retired direct near calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts taken speculative and retired direct near calls.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired indirect calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts taken speculative and retired indirect calls including both register and memory indirect.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired macro-conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc2",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired macro-unconditional branch instructions, excluding calls and indirects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc4",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches excluding calls and return branches.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc8",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xd0",
+ "BriefDescription": "Speculative and retired direct near calls",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired direct near calls.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "PublicDescription": "This event counts taken speculative and retired mispredicted indirect branches that have a return mnemonic.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted macro conditional branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc4",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "PublicDescription": "This event counts both taken and not taken mispredicted indirect branches excluding calls and returns.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "PublicDescription": "This event counts both taken and not taken speculative and retired mispredicted branch instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x1",
+ "BriefDescription": "Resource-related stall cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "PublicDescription": "This event counts resource-related stall cycles. Reasons for stalls can be as follows:\n - *any* u-arch structure got full (LB, SB, RS, ROB, BOB, LM, Physical Register Reclaim Table (PRRT), or Physical History Table (PHT) slots)\n - *any* u-arch structure got empty (like INT/SIMD FreeLists)\n - FPU control word (FPCW), MXCSR\nand others. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.RS",
+ "PublicDescription": "This event counts stall cycles caused by absence of eligible entries in the reservation station (RS). This may result from RS overflow, or from RS deallocation because of the RS array Write Port allocation scheme (each RS entry has two write ports instead of four. As a result, empty entries could not be used, although RS is not really full). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PublicDescription": "This event counts stall cycles caused by the store buffer (SB) overflow (excluding draining from synch). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "PublicDescription": "This event counts ROB full stall cycles. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "CounterMask": "1",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand* load request missing the L2 cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "CounterMask": "8",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request missing the L1 data cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "CounterMask": "2",
+ "PublicDescription": "Counts number of cycles the CPU has at least one pending demand load request (that is cycles with non-completed load waiting for its data from memory subsystem).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x4",
+ "BriefDescription": "Total execution stalls",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "CounterMask": "4",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x5",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "CounterMask": "5",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand* load request missing the L2 cache.(as a footprint) * includes also L1 HW prefetch requests that may or may not be required by demands.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x6",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "CounterMask": "6",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0xc",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "CounterMask": "12",
+ "PublicDescription": "Counts number of cycles nothing is executed on any execution port, while there was at least one pending demand load request missing the L1 data cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.UOPS",
+ "PublicDescription": "Number of Uops delivered by the LSD. ",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x2",
+ "BriefDescription": "Number of uops executed on the core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "PublicDescription": "Number of uops executed from any thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x0",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.ANY_P",
+ "Errata": "BDM61",
+ "PublicDescription": "This event counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x2",
+ "BriefDescription": "FP operations retired. X87 FP operations that have no exceptions:",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.X87",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts FP operations retired. For X87 FP operations that have no exceptions counting also includes flows that have several X87, or flows that use X87 uops in the exception handling.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x1",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "PEBS": "2",
+ "Counter": "1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "Errata": "BDM11, BDM55",
+ "PublicDescription": "This is a precise version (that is, uses PEBS) of the event that counts instructions retired.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Actually retired uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.ALL",
+ "PublicDescription": "This event counts all actually retired uops. Counting increments by two for micro-fused uops, and by one for macro-fused and other uops. Maximal increment value for one cycle is eight.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x2",
+ "BriefDescription": "Retirement slots used.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of retirement slots used.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts cycles without actually retired uops.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "CounterMask": "10",
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles there was a Nuke. Account for both thread-specific and All Thread Nukes.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "PublicDescription": "This event counts both thread-specific (TS) and all-thread (AT) nukes.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x4",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PublicDescription": "This event counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x20",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "PublicDescription": "Maskmov false fault - counts number of time ucode passes through Maskmov flow due to instruction's mask being 0 while the flow was completed without raising a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x1",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x2",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts both direct and indirect near call instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x0",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "This event counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x8",
+ "BriefDescription": "Return instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts return instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x10",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x20",
+ "BriefDescription": "Taken branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x40",
+ "BriefDescription": "Far branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "Errata": "BDW98",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts far branch instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x4",
+ "BriefDescription": "All (macro) branch instructions retired. (Precise Event - PEBS)",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "Errata": "BDW98",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x1",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x0",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "This event counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x8",
+ "BriefDescription": "This event counts the number of mispredicted ret instructions retired. Non PEBS",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.RET",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted return instructions retired.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x4",
+ "BriefDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS)",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCC",
+ "UMask": "0x20",
+ "BriefDescription": "Count cases of saving new LBR",
+ "Counter": "0,1,2,3",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "PublicDescription": "This event counts cases of saving new LBR records by hardware. This assumes proper enabling of LBRs and takes into account LBR filtering done by the LBR_SELECT register.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 1.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 2.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 3.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 4.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 5.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 6.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 7.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x20",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "CounterMask": "3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xe6",
+ "UMask": "0x1f",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "CounterMask": "8",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x4",
+ "BriefDescription": "Total execution stalls.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0xc",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "CounterMask": "12",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x5",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "CounterMask": "5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x6",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "CounterMask": "6",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "CounterMask": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "Invert": "1",
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "CounterMask": "1",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7",
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA0",
+ "UMask": "0x3",
+ "BriefDescription": "Micro-op dispatches cancelled due to insufficient SIMD physical register file read ports",
+ "Counter": "0,1,2,3",
+ "EventName": "UOP_DISPATCHES_CANCELLED.SIMD_PRF",
+ "PublicDescription": "This event counts the number of micro-operations cancelled after they were dispatched from the scheduler to the execution units when the total number of physical register read ports across all dispatch ports exceeds the read bandwidth of the physical register file. The SIMD_PRF subevent applies to the following instructions: VDPPS, DPPS, VPCMPESTRI, PCMPESTRI, VPCMPESTRM, PCMPESTRM, VFMADD*, VFMADDSUB*, VFMSUB*, VMSUBADD*, VFNMADD*, VFNMSUB*. See the Broadwell Optimization Guide for more information.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "CounterMask": "2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "CounterMask": "3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "PublicDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/virtual-memory.json b/tools/perf/pmu-events/arch/x86/broadwellx/virtual-memory.json
new file mode 100644
index 000000000000..5ce8b67ba076
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/virtual-memory.json
@@ -0,0 +1,388 @@
+[
+ {
+ "EventCode": "0x08",
+ "UMask": "0x1",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x2",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x4",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x8",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x20",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x40",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x1",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x2",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x4",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x8",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x20",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x40",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "UMask": "0x10",
+ "BriefDescription": "Cycle count for an Extended Page table walk.",
+ "Counter": "0,1,2,3",
+ "EventName": "EPT.WALK_CYCLES",
+ "PublicDescription": "This event counts cycles for an extended page table walk. The Extended Page directory cache differs from standard TLB caches by the operating system that use it. Virtual machine operating systems use the extended page directory cache, while guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x1",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x2",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x4",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x8",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "Errata": "BDM69",
+ "PublicDescription": "This event counts the number of cycles while PMH is busy with the page walk.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x20",
+ "BriefDescription": "Core misses that miss the DTLB and hit the STLB (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x40",
+ "BriefDescription": "Code misses that miss the DTLB and hit the STLB (2M).",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAE",
+ "UMask": "0x1",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "PublicDescription": "This event counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x11",
+ "BriefDescription": "Number of DTLB page walker hits in the L1+FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L1",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x21",
+ "BriefDescription": "Number of ITLB page walker hits in the L1+FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L1",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x12",
+ "BriefDescription": "Number of DTLB page walker hits in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L2",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x22",
+ "BriefDescription": "Number of ITLB page walker hits in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L2",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x14",
+ "BriefDescription": "Number of DTLB page walker hits in the L3 + XSNP.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L3",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x24",
+ "BriefDescription": "Number of ITLB page walker hits in the L3 + XSNP.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L3",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x18",
+ "BriefDescription": "Number of DTLB page walker hits in Memory.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_MEMORY",
+ "Errata": "BDM69, BDM98",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x1",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "PublicDescription": "This event counts the number of DTLB flush attempts of the thread-specific entries.",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x20",
+ "BriefDescription": "STLB flush attempts",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PublicDescription": "This event counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, and so on).",
+ "SampleAfterValue": "100007",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0xe",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x60",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0xe",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x60",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0xe",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "Errata": "BDM69",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x60",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/cache.json b/tools/perf/pmu-events/arch/x86/goldmont/cache.json
new file mode 100644
index 000000000000..4e02e1e5e70d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/cache.json
@@ -0,0 +1,1127 @@
+[
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of demand and prefetch transactions that the L2 XQ rejects due to a full or near full condition which likely indicates back pressure from the intra-die interconnect (IDI) fabric. The XQ may reject transactions from the L2Q (non-cacheable requests), L2 misses and L2 write-back victims.",
+ "EventCode": "0x30",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "L2_REJECT_XQ.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests rejected by the XQ"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of demand and L1 prefetcher requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops.",
+ "EventCode": "0x31",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CORE_REJECT_L2Q.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests rejected by the L2Q "
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts memory requests originating from the core that reference a cache line in the L2 cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache requests"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts memory requests originating from the core that miss in the L2 cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache request misses"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts cycles that an ICache miss is outstanding, and instruction fetch is stalled. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes, while an Icache miss outstanding. Note this event is not the same as cycles to retrieve an instruction due to an Icache miss. Rather, it is the part of the Instruction Cache (ICache) miss time where no bytes are available for the decoder.",
+ "EventCode": "0x86",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles where code-fetch is stalled and an ICache miss is outstanding. This is not the same as an ICache Miss."
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of load uops retired.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of store uops retired.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Store uops retired (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts the number of memory uops retired that is either a loads or a store or both.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x83",
+ "EventName": "MEM_UOPS_RETIRED.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Memory uops retired (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts locked memory uops retired. This includes \"regular\" locks and bus locks. (To specifically count bus locks only, see the Offcore response event.) A locked access is one with a lock prefix, or an exchange to memory. See the SDM for a complete description of which memory load accesses are locks.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Locked load uops retired (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired where the data requested spans a 64 byte cache line boundary.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that split a cache-line (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts store uops retired where the data requested spans a 64 byte cache line boundary.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Stores uops retired that split a cache-line (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts memory uops retired where the data requested spans a 64 byte cache line boundary.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x43",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Memory uops retired that split a cache-line (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired that hit the L1 data cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that hit L1 data cache (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired that miss the L1 data cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that missed L1 data cache (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired that hit in the L2 cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that hit L2 (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired that miss in the L2 cache.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that missed L2 (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired where the cache line containing the data was in the modified state of another core or modules cache (HITM). More specifically, this means that when the load address was checked by other caching agents (typically another processor) in the system, one of those caching agents indicated that they had a dirty copy of the data. Loads that obtain a HITM response incur greater latency than most is typical for a load. In addition, since HITM indicates that some other processor had this data in its cache, it implies that the data was shared between processors, or potentially was a lock or semaphore value. This event is useful for locating sharing, false sharing, and contended locks.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HITM",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Memory uop retired where cross core or cross module HITM occurred (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts memory load uops retired where the data is retrieved from the WCB (or fill buffer), indicating that the load found its data while that data was in the process of being brought into the L1 cache. Typically a load will receive this indication when some other load or prefetch missed the L1 cache and was in the process of retrieving the cache line containing the data, but that process had not yet finished (and written the data back to the cache). For example, consider load X and Y, both referencing the same cache line that is not in the L1 cache. If load X misses cache first, it obtains and WCB (or fill buffer) and begins the process of requesting the data. When load Y requests the data, it will either hit the WCB, or the L1 cache, depending on exactly what time the request to Y occurs.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.WCB_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads retired that hit WCB (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts memory load uops retired where the data is retrieved from DRAM. Event is counted at retirement, so the speculative loads are ignored. A memory load can hit (or miss) the L1 cache, hit (or miss) the L2 cache, hit DRAM, hit in the WCB or receive a HITM response.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.DRAM_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads retired that came from DRAM (Precise event capable)"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts when a modified (dirty) cache line is evicted from the data L1 cache and needs to be written back to memory. No count will occur if the evicted line is clean, and hence does not require a writeback.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DL1.DIRTY_EVICTION",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1 Cache evictions for dirty data"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "EventCode": "0xB7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x36000032b7 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10000032b7 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x04000032b7 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x02000032b7 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00000432b7 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000022 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000022 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000022 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000022 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040022 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600003091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads (demand & prefetch) that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000003091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400003091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads (demand & prefetch) that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200003091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads (demand & prefetch) that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000043091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads (demand & prefetch) that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600003010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000003010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400003010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200003010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000043010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts requests to the uncore subsystem that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts requests to the uncore subsystem that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts requests to the uncore subsystem that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts requests to the uncore subsystem that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000018000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts requests to the uncore subsystem that have any transaction responses from the uncore subsystem.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600004800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000044800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600004000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts partial cache line data writes to uncacheable write combining (USWC) memory region that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000004000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts partial cache line data writes to uncacheable write combining (USWC) memory region that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400004000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts partial cache line data writes to uncacheable write combining (USWC) memory region that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200004000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts partial cache line data writes to uncacheable write combining (USWC) memory region that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000044000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts partial cache line data writes to uncacheable write combining (USWC) memory region that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600002000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000002000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400002000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200002000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000042000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600001000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache lines requests by software prefetch instructions that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000001000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache lines requests by software prefetch instructions that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400001000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache lines requests by software prefetch instructions that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200001000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache lines requests by software prefetch instructions that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000041000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cache lines requests by software prefetch instructions that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010400 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts bus lock and split lock requests that have any transaction responses from the uncore subsystem.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of demand write requests (RFO) generated by a write to partial data cache line, including the writes to uncacheable (UC) and write through (WT), and write protected (WP) types of memory that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand data partial reads, including data in uncacheable (UC) or uncacheable write combining (USWC) memory types that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040020 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040010 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.ANY",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040008 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_HIT",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache that are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line that hit the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3600000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that miss the L2 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that miss the L2 cache with a snoop hit in the other processor module, no data forwarding is required.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that true miss for the L2 cache with a snoop miss in the other processor module. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data reads of full cache lines that hit the L2 cache.",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/frontend.json b/tools/perf/pmu-events/arch/x86/goldmont/frontend.json
new file mode 100644
index 000000000000..9ba08518649e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/frontend.json
@@ -0,0 +1,52 @@
+[
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is in the ICache (hit). The event strives to count on a cache line basis, so that multiple accesses which hit in a single cache line count as one ICACHE.HIT. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "References per ICache line that are available in the ICache (hit). This event counts differently than Intel processors based on Silvermont microarchitecture"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is not in the ICache (miss). The event strives to count on a cache line basis, so that multiple accesses which miss in a single cache line count as one ICACHE.MISS. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is not in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "References per ICache line that are not available in the ICache (miss). This event counts differently than Intel processors based on Silvermont microarchitecture"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line. The event strives to count on a cache line basis, so that multiple fetches to a single cache line count as one ICACHE.ACCESS. Specifically, the event counts when accesses from straight line code crosses the cache line boundary, or when a branch target is to a new line.\r\nThis event counts differently than Intel processors based on Silvermont microarchitecture.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "ICACHE.ACCESSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "References per ICache line. This event counts differently than Intel processors based on Silvermont microarchitecture"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of times the Microcode Sequencer (MS) starts a flow of uops from the MSROM. It does not count every time a uop is read from the MSROM. The most common case that this counts is when a micro-coded instruction is encountered by the front end of the machine. Other cases include when an instruction encounters a fault, trap, or microcode assist of any sort that initiates a flow of uops. The event will count MS startups for uops that are speculative, and subsequently cleared by branch mispredict or a machine clear.",
+ "EventCode": "0xE7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MS_DECODED.MS_ENTRY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "MS decode starts"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of times the prediction (from the predecode cache) for instruction length is incorrect.",
+ "EventCode": "0xE9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Decode restrictions due to predicting wrong instruction length"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/memory.json b/tools/perf/pmu-events/arch/x86/goldmont/memory.json
new file mode 100644
index 000000000000..ac8b0d365a19
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/memory.json
@@ -0,0 +1,34 @@
+[
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts machine clears due to memory ordering issues. This occurs when a snoop request happens and the machine is uncertain if memory ordering will be preserved - as another core is in the process of modifying the data.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Machine clears due to memory ordering issue"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts when a memory load of a uop spans a page boundary (a split) is retired.",
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops that split a page (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts when a memory store of a uop spans a page boundary (a split) is retired.",
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MISALIGN_MEM_REF.STORE_PAGE_SPLIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Store uops that split a page (Precise event capable)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/other.json b/tools/perf/pmu-events/arch/x86/goldmont/other.json
new file mode 100644
index 000000000000..df25ca9542f1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/other.json
@@ -0,0 +1,52 @@
+[
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed because of a full resource in the backend. Including but not limited to resources such as the Re-order Buffer (ROB), reservation stations (RS), load/store buffers, physical registers, or any other needed machine resource that is currently unavailable. Note that uops must be available for consumption in order for this event to fire. If a uop is not available (Instruction Queue is empty), this event will not count.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RESOURCE_FULL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Unfilled issue slots per cycle because of a full resource in the backend"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend because allocation is stalled waiting for a mispredicted jump to retire or other branch-like conditions (e.g. the event is relevant during certain microcode flows). Counts all issue slots blocked while within this window including slots where uops were not available in the Instruction Queue.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RECOVERY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Unfilled issue slots per cycle to recover"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend due to either a full resource in the backend (RESOURCE_FULL) or due to the processor recovering from some event (RECOVERY).",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "ISSUE_SLOTS_NOT_CONSUMED.ANY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Unfilled issue slots per cycle"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts hardware interrupts received by the processor.",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "HW_INTERRUPTS.RECEIVED",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Hardware interrupts received (Precise event capable)"
+ },
+ {
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts core cycles during which there are pending interrupts, but interrupts are masked (EFLAGS.IF = 0).",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "HW_INTERRUPTS.PENDING_AND_MASKED",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles pending interrupts are masked (Precise event capable)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/pipeline.json b/tools/perf/pmu-events/arch/x86/goldmont/pipeline.json
new file mode 100644
index 000000000000..07f00041f56f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/pipeline.json
@@ -0,0 +1,433 @@
+[
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts branch instructions retired for all branch types. This is an architectural performance event.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired branch instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was taken and when it was not taken.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7e",
+ "EventName": "BR_INST_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired conditional branch instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were taken and does not count when the Jcc branch instruction were not taken.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xfe",
+ "EventName": "BR_INST_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired conditional branch instructions that were taken (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts near CALL branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf9",
+ "EventName": "BR_INST_RETIRED.CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired near call instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts near relative CALL branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xfd",
+ "EventName": "BR_INST_RETIRED.REL_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired near relative call instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts near indirect CALL branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xfb",
+ "EventName": "BR_INST_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired near indirect call instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts near return branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf7",
+ "EventName": "BR_INST_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired near return instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts near indirect call or near indirect jmp branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xeb",
+ "EventName": "BR_INST_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired instructions of near indirect Jmp or call (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts far branch instructions retired. This includes far jump, far call and return, and Interrupt call and return.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0xbf",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired far branch instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted branch instructions retired including all branch types.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted branch instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was supposed to be taken and when it was not supposed to be taken (but the processor predicted the opposite condition).",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7e",
+ "EventName": "BR_MISP_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted conditional branch instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were supposed to be taken but the processor predicted that it would not be taken.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0xfe",
+ "EventName": "BR_MISP_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted conditional branch instructions that were taken (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted near indirect CALL branch instructions retired, where the target address taken was not what the processor predicted.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0xfb",
+ "EventName": "BR_MISP_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted near indirect call instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted near RET branch instructions retired, where the return address taken was not what the processor predicted.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf7",
+ "EventName": "BR_MISP_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted near return instructions (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts mispredicted branch instructions retired that were near indirect call or near indirect jmp, where the target address taken was not what the processor predicted.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0xeb",
+ "EventName": "BR_MISP_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired mispredicted instructions of near indirect Jmp or near indirect call. (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts uops which retired.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops retired (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts uops retired that are from the complex flows issued by the micro-sequencer (MS). Counts both the uops from a micro-coded instruction, and the uops that might be generated from a micro-coded assist.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.MS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "MS uops retired (Precise event capable)"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of times that the processor detects that a program is writing to a code section and has to perform a machine clear because of that modification. Self-modifying code (SMC) causes a severe penalty in all Intel? architecture processors.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts machine clears due to floating point (FP) operations needing assists. For instance, if the result was a floating point denormal, the hardware clears the pipeline and reissues uops to produce the correct IEEE compliant denormal result.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.FP_ASSIST",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Machine clears due to FP assists"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts machine clears due to memory disambiguation. Memory disambiguation happens when a load which has been issued conflicts with a previous unretired store in the pipeline whose address was not known at issue time, but is later resolved to be the same as the load address.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MACHINE_CLEARS.DISAMBIGUATION",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Machine clears due to memory disambiguation"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts machine clears for any reason.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "MACHINE_CLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All machine clears"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The event continues counting during hardware interrupts, traps, and inside interrupt handlers. This is an architectural performance event. This event uses a (_P)rogrammable general purpose performance counter. *This event is Precise Event capable: The EventingRIP field in the PEBS record is precise to the address of the instruction which caused the event. Note: Because PEBS records can be collected only on IA32_PMC0, only one event can use the PEBS facility at a time.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired (Precise event capable)"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "This event used to measure front-end inefficiencies. I.e. when front-end of the machine is not delivering uops to the back-end and the back-end has is not stalled. This event can be used to identify if the machine is truly front-end bound. When this event occurs, it is an indication that the front-end of the machine is operating at less than its theoretical peak performance. Background: We can think of the processor pipeline as being divided into 2 broader parts: Front-end and Back-end. Front-end is responsible for fetching the instruction, decoding into uops in machine understandable format and putting them into a uop queue to be consumed by back end. The back-end then takes these uops, allocates the required resources. When all resources are ready, uops are executed. If the back-end is not ready to accept uops from the front-end, then we do not want to count these as front-end bottlenecks. However, whenever we have bottlenecks in the back-end, we will have allocation unit stalls and eventually forcing the front-end to wait until the back-end is ready to receive more uops. This event counts only when back-end is requesting more uops and front-end is not able to provide them. When 3 uops are requested and no uops are delivered, the event counts 3. When 3 are requested, and only 1 is delivered, the event counts 2. When only 2 are delivered, the event counts 1. Alternatively stated, the event will not count if 3 uops are delivered, or if the back end is stalled and not requesting any uops at all. Counts indicate missed opportunities for the front-end to deliver a uop to the back end. Some examples of conditions that cause front-end efficiencies are: ICache misses, ITLB misses, and decoder restrictions that limit the front-end bandwidth. Known Issues: Some uops require multiple allocation slots. These uops will not be charged as a front end 'not delivered' opportunity, and will be regarded as a back end problem. For example, the INC instruction has one uop that requires 2 issue slots. A stream of INC instructions will not count as UOPS_NOT_DELIVERED, even though only one instruction can be issued per clock. The low uop issue rate for a stream of INC instructions is considered to be a back end issue.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "UOPS_NOT_DELIVERED.ANY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Uops requested but not-delivered to the back-end per cycle"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts uops issued by the front end and allocated into the back end of the machine. This event counts uops that retire as well as uops that were speculatively executed but didn't retire. The sort of speculative uops that might be counted includes, but is not limited to those uops issued in the shadow of a miss-predicted branch, those uops that are inserted during an assist (such as for a denormal floating point result), and (previously allocated) uops that might be canceled during a machine clear.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Uops issued to the back end per cycle"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts core cycles if either divide unit is busy.",
+ "EventCode": "0xCD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CYCLES_DIV_BUSY.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a divider is busy"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts core cycles the integer divide unit is busy.",
+ "EventCode": "0xCD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLES_DIV_BUSY.IDIV",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles the integer divide unit is busy"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts core cycles the floating point divide unit is busy.",
+ "EventCode": "0xCD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLES_DIV_BUSY.FPDIV",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles the FP divide unit is busy"
+ },
+ {
+ "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The counter continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses fixed counter 0. You cannot collect a PEBs record for this event.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired (Fixed event)"
+ },
+ {
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses fixed counter 1. You cannot collect a PEBs record for this event.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when core is not halted (Fixed event)"
+ },
+ {
+ "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time. This event is not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. This event uses fixed counter 2. You cannot collect a PEBs record for this event.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when core is not halted (Fixed event)"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Core cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.CORE_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when core is not halted"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Reference cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when core is not halted"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of times a BACLEAR is signaled for any reason, including, but not limited to indirect branch/call, Jcc (Jump on Conditional Code/Jump if Condition is Met) branch, unconditional branch/call, and returns.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "BACLEARs asserted for any branch type"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts BACLEARS on return instructions.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BACLEARS.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "BACLEARs asserted for return branch"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts BACLEARS on Jcc (Jump on Conditional Code/Jump if Condition is Met) branches.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BACLEARS.COND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "BACLEARs asserted for conditional branch"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts anytime a load that retires is blocked for any reason.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "LD_BLOCKS.ALL_BLOCK",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts loads blocked because they are unable to find their physical address in the micro TLB (UTLB).",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.UTLB_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked because address in not in the UTLB (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts a load blocked from using a store forward because of an address/size mismatch, only one of the loads blocked from each store will be counted.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked due to store forward restriction (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts a load blocked from using a store forward, but did not occur because the store data was not available at the right time. The forward might occur subsequently when the data is available.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS.DATA_UNKNOWN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked due to store data not ready (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts loads that block because their address modulo 4K matches a pending store.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LD_BLOCKS.4K_ALIAS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked because address has 4k partial address false dependence (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "BR_INST_RETIRED.ALL_TAKEN_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Retired taken branch instructions (Precise event capable)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmont/virtual-memory.json b/tools/perf/pmu-events/arch/x86/goldmont/virtual-memory.json
new file mode 100644
index 000000000000..3202c4478836
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmont/virtual-memory.json
@@ -0,0 +1,75 @@
+[
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) for a linear address of an instruction fetch. It counts when new translation are filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.",
+ "EventCode": "0x81",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "ITLB misses"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts load uops retired that caused a DTLB miss.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops retired that missed the DTLB (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts store uops retired that caused a DTLB miss.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Store uops retired that missed the DTLB (Precise event capable)"
+ },
+ {
+ "PEBS": "2",
+ "CollectPEBSRecord": "2",
+ "PublicDescription": "Counts uops retired that had a DTLB miss on load, store or either. Note that when two distinct memory operations to the same page miss the DTLB, only one of them will be recorded as a DTLB miss.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x13",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Memory uops retired that missed the DTLB (Precise event capable)"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts every core cycle when a Data-side (walks due to a data operation) page walk is in progress.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Duration of D-side page-walks in cycles"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts every core cycle when a Instruction-side (walks due to an instruction fetch) page walk is in progress.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Duration of I-side pagewalks in cycles"
+ },
+ {
+ "CollectPEBSRecord": "1",
+ "PublicDescription": "Counts every core cycle a page-walk is in progress due to either a data memory operation or an instruction fetch.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Duration of page-walks in cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/cache.json b/tools/perf/pmu-events/arch/x86/haswell/cache.json
new file mode 100644
index 000000000000..bfb5ebf48c54
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/cache.json
@@ -0,0 +1,1041 @@
+[
+ {
+ "PublicDescription": "Demand data read requests that missed L2, no rejects.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand data read requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that missed L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.L2_PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 prefetch requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that hit L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x50",
+ "EventName": "L2_RQSTS.L2_PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 prefetch requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts any demand and L1 HW prefetch data load requests to L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe1",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 store RFO requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe2",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe4",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf8",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks that hit L2 cache.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x50",
+ "EventName": "L2_DEMAND_RQSTS.WB_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts each cache miss condition for references to the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts requests originating from the core that reference a cache line in the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments the number of outstanding L1D misses every cycle. Set Cmask = 1 and Edge =1 to count occurrences.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.REQUEST_FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch. HWP are e.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "This event counts when new data lines are brought into the L1 Data cache, which cause other lines to be evicted from the cache.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding demand data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD78, HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding Demand code Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding cacheable data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD78, HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D is locked.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand data read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD78",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand code read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand RFO read requests sent to uncore, including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Data read requests sent to uncore (demand and prefetch).",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "Errata": "HSD76, HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD76, HSD29, HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops with L3 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in L3 without snoops required.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops missed L1 cache as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops misses in L1 cache as data sources.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops missed L2. Unknown data source excluded.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "HSD29, HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops missed L3. Excludes unknown data source .",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "Errata": "HSM30",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared L3.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in L3 without snoops required.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts retired load uops where the data came from local DRAM. This does not include hardware prefetches.",
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD74, HSD29, HSD25, HSM30",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PublicDescription": "Demand data read requests that access L2 cache.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that access L2 cache.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache accesses when fetching instructions.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Any MLC or L3 HW prefetch accessing L2, including rejects.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or L3 HW prefetches that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L1D writebacks that access L2 cache.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 fill requests that access L2 cache.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 writebacks that access L2 cache.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Transactions accessing L2 pipe.",
+ "EventCode": "0xf0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in I state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in S state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in E state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines brought into the L2 cache. Lines are filled into the L2 cache when there was an L2 miss.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Clean L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of store RFO requests that hit the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of store RFO requests that miss the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that hit the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x44",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that missed the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x27",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand requests to L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe7",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "All requests that missed L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "All requests to L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "Errata": "HSD78",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All L2 requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD78, HSD62, HSD61",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c8fff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all requests that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c07f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c07f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/floating-point.json b/tools/perf/pmu-events/arch/x86/haswell/floating-point.json
new file mode 100644
index 000000000000..1732fa49c6d2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/floating-point.json
@@ -0,0 +1,83 @@
+[
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "HSD56, HSM57",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "HSD56, HSM57",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with any input/output SSE* or FP assists.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Note that a whole rep string only counts AVX_INST.ALL once.",
+ "EventCode": "0xC6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "AVX_INSTS.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Approximate counts of AVX & AVX2 256-bit instructions, including non-arithmetic instructions, loads, and stores. May count non-AVX instructions that employ 256-bit operations, including (but not necessarily limited to) rep string instructions that use 256-bit loads and stores for optimized performance, XSAVE* and XRSTOR*, and operations that transition the x87 FPU data registers between x87 and MMX.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/frontend.json b/tools/perf/pmu-events/arch/x86/haswell/frontend.json
new file mode 100644
index 000000000000..57a1ce46971f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/frontend.json
@@ -0,0 +1,294 @@
+[
+ {
+ "PublicDescription": "Counts cycles the IDQ is empty.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD135",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MITE path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle. # of uops delivered to IDQ from DSB path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts uops delivered by the Front-end with the assistance of the microcode sequencer. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the microcode sequencer assisted the Front-end in delivering uops. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered at least one uops. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered at least one uop. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops delivered to IDQ from any path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts Instruction Cache (ICACHE) misses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes Uncacheable accesses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE.IFETCH_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event count the number of undelivered (unallocated) uops from the Front-end to the Resource Allocation Table (RAT) while the Back-end of the processor is not stalled. The Front-end can allocate up to 4 uops per cycle so this event can increment 0-4 times per cycle depending on the number of unallocated uops. This event is counted on a per-core basis.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number cycles during which the Front-end allocated exactly zero uops to the Resource Allocation Table (RAT) while the Back-end of the processor is not stalled. This event is counted on a per-core basis.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE.IFDATA_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/memory.json b/tools/perf/pmu-events/arch/x86/haswell/memory.json
new file mode 100644
index 000000000000..aab981b42339
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/memory.json
@@ -0,0 +1,655 @@
+[
+ {
+ "PublicDescription": "Speculative cache-line split load uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative cache-line split store-address uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional writes.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_EXEC.MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_EXEC.MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_EXEC.MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of memory ordering machine clears detected. Memory ordering machine clears can result from memory address aliasing or snoops from another hardware thread or core to data inflight in the pipeline. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "HLE_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution started.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution successfully committed.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "HLE_RETIRED.ABORTED_MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "HLE_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to uncommon conditions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "HLE_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "Errata": "HSD65",
+ "EventName": "HLE_RETIRED.ABORTED_MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts).",
+ "EventCode": "0xc8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "HLE_RETIRED.ABORTED_MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RTM_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution started.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution successfully committed.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RTM_RETIRED.ABORTED_MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RTM_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RTM_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "Errata": "HSD65",
+ "EventName": "RTM_RETIRED.ABORTED_MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "EventCode": "0xc9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RTM_RETIRED.ABORTED_MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 32.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "Errata": "HSD76, HSD25, HSM26",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc08fff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all requests that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01004007f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc007f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_CODE_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss in the L3",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/other.json b/tools/perf/pmu-events/arch/x86/haswell/other.json
new file mode 100644
index 000000000000..85d6a14baf9d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/other.json
@@ -0,0 +1,43 @@
+[
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is not in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/pipeline.json b/tools/perf/pmu-events/arch/x86/haswell/pipeline.json
new file mode 100644
index 000000000000..0099848607ad
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/pipeline.json
@@ -0,0 +1,1329 @@
+[
+ {
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. INST_RETIRED.ANY is counted by a designated fixed counter, leaving the programmable counters available for other events. Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "Errata": "HSD140, HSD143",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "PublicDescription": "This event counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "PublicDescription": "This event counts loads that followed a store to the same address, where the data could not be forwarded inside the pipeline from the store to the load. The most common reason why store forwarding would be blocked is when a load's address range overlaps with a preceding smaller uncompleted store. The penalty for blocked store forwarding is that the load must wait for the store to write its value to the cache before it can be issued.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "loads blocked by overlapping with store buffer that cannot be forwarded",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Aliasing occurs when a load is issued after a store and their memory addresses are offset by 4K. This event counts the number of loads that aliased with a preceding store, resulting in an extended address check in the pipeline which can have a performance impact.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles spent waiting for a recovery after an event such as a processor nuke, JEClear, assist, hle/rtm abort etc.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops issued by the Front-end of the pipeline to the Back-end. This event is counted at the allocation stage and will count both retired and non-retired uops.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of flags-merge uops allocated. Such uops add delay.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of slow LEA or similar uops allocated. Such uop has 3 sources (for example, 2 sources + immediate) regardless of whether it is a result of LEA instruction or not.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of multiply packed/scalar single precision uops allocated.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.DIVIDER_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Any uop executed by the Divider. (This includes all divide uops, sqrt, ...)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments at the frequency of XCLK (100 MHz) when not halted.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.",
+ "EventCode": "0x4c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.",
+ "EventCode": "0x4c",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of integer move elimination candidate uops that were eliminated.",
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD move elimination candidate uops that were eliminated.",
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of integer move elimination candidate uops that were not eliminated.",
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD move elimination candidate uops that were not eliminated.",
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the Reservation Station ( RS ) is empty for the thread. The RS is a structure that buffers allocated micro-ops from the Front-end. If there are many cycles when the RS is empty, it may represent an underflow of instructions delivered from the Front-end.",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles where the decoder is stalled on an instruction with a length changing prefix (LCP).",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Stall cycles due to IQ is full.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stall cycles because IQ is full",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 0 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 1 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 2 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 3 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 4 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 5 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 6 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a uop is dispatched on port 7 in this thread.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles allocation is stalled due to resource related reason.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD135",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which no instructions were allocated because no Store Buffers (SB) were available.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L2 miss loads. Set Cmask=2 to count cycle.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD78",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L2 cache miss loads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L1 data cache miss loads. Set Cmask=8 to count cycle.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L1 cache miss loads.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Cycles with pending memory loads. Set Cmask=2 to count cycle.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending memory loads.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which no instructions were executed in the execution stage of the pipeline.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of loads missed L2.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L2 cache misses.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which no instructions were executed in the execution stage of the pipeline and there were memory instructions pending (waiting for data).",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to memory subsystem.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Execution stalls due to L1 data cache miss loads. Set Cmask=0CH.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L1 data cache misses",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Number of uops delivered by the LSD.",
+ "EventCode": "0xa8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts total number of uops to be executed per-core each cycle.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of instructions at retirement.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "Errata": "HSD11, HSD140",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts FP operations retired. For X87 FP operations that have no exceptions counting also includes flows that have several X87, or flows that use X87 uops in the exception handling.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "FP operations retired. X87 FP operations that have no exceptions: Counts also flows that have several X87 or flows that use X87 uops in the exception handling.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution.",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "Errata": "HSD140",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "CounterHTOff": "1"
+ },
+ {
+ "PublicDescription": "Number of microcode assists invoked by HW upon uop writeback.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of micro-ops retired. Use Cmask=1 and invert to count active cycles or stalled cycles.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of retirement slots used each cycle. There are potentially 4 slots that can be used each cycle - meaning, 4 uops or 4 instructions could retire each cycle.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles there was a Nuke. Account for both thread-specific and All Thread Nukes.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event is incremented when self-modifying code (SMC) is detected, which causes a machine clear. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of conditional branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Branch instructions at retirement.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of near return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Return instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of near taken branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of far branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Far branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Mispredicted branch instructions at retirement.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This event counts all mispredicted branch instructions retired. This is a precise event.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Count cases of saving new LBR records by hardware.",
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 6.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 7.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of near branch instructions retired that were taken but mispredicted.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This events counts the cycles where at least one uop was executed. It is counted per thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This events counts the cycles where at least two uop were executed. It is counted per thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This events counts the cycles where at least three uop were executed. It is counted per thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of front end re-steers due to BPU misprediction.",
+ "EventCode": "0xe6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "HSD30, HSM31",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted. (counts at 100 MHz rate)",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/virtual-memory.json b/tools/perf/pmu-events/arch/x86/haswell/virtual-memory.json
new file mode 100644
index 000000000000..ce80a08d0f08
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/virtual-memory.json
@@ -0,0 +1,484 @@
+[
+ {
+ "PublicDescription": "Misses in all TLB levels that cause a page walk of any page size.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to demand load misses that caused 4K page walks in any TLB levels.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to demand load misses that caused 2M/4M page walks in any TLB levels.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB load misses.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load operations from a 4K page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load operations from a 2M page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (2M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DTLB demand load misses with low part of linear-to-physical address translation missed.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_LOAD_MISSES.PDE_CACHE_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DTLB demand load misses with low part of linear-to-physical address translation missed",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Miss in all TLB levels causes a page walk of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to store misses in one or more TLB levels of 4K page structure.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to store misses in one or more TLB levels of 2M/4M page structure.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB store misses.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store operations from a 4K page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store operations from a 2M page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (2M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DTLB store misses with low part of linear-to-physical address translation missed.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_STORE_MISSES.PDE_CACHE_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DTLB store misses with low part of linear-to-physical address translation missed",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4f",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in ITLB that causes a page walk of any page size.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to misses in ITLB 4K page entries.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to misses in ITLB 2M/4M page entries.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by ITLB misses.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "ITLB misses that hit STLB (4K).",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISSES.STLB_HIT_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core misses that miss the DTLB and hit the STLB (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "ITLB misses that hit STLB (2M).",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "ITLB_MISSES.STLB_HIT_2M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code misses that miss the DTLB and hit the STLB (2M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of ITLB flushes, includes 4k/2M/4M pages.",
+ "EventCode": "0xae",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L1+FB.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L1+FB",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L1+FB.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L1+FB",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L1 and FB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L1 and FB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L2.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L2.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L2.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L2.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L3.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x14",
+ "Errata": "HSD25",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in the L3 + XSNP",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L3.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "Errata": "HSD25",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in the L3 + XSNP",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x44",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L3.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L2.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of DTLB page walker loads from memory.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "Errata": "HSD25",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of DTLB page walker hits in Memory",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of ITLB page walker loads from memory.",
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x28",
+ "Errata": "HSD25",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of ITLB page walker hits in Memory",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x48",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in memory.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in memory.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Count number of STLB flush attempts.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STLB flush attempts",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks in any TLB of any page size due to demand load misses.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of cache load STLB hits. No page walk.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks due to store miss in any TLB levels of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks in ITLB of any page size.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "ITLB misses that hit STLB. No page walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x60",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/cache.json b/tools/perf/pmu-events/arch/x86/haswellx/cache.json
new file mode 100644
index 000000000000..f1bae0817a6f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/cache.json
@@ -0,0 +1,1077 @@
+[
+ {
+ "EventCode": "0x24",
+ "UMask": "0x21",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "Errata": "HSD78",
+ "PublicDescription": "Demand data read requests that missed L2, no rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x41",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "Errata": "HSD78",
+ "PublicDescription": "Demand data read requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x30",
+ "BriefDescription": "L2 prefetch requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_MISS",
+ "PublicDescription": "Counts all L2 HW prefetcher requests that missed L2.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x50",
+ "BriefDescription": "L2 prefetch requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.L2_PF_HIT",
+ "PublicDescription": "Counts all L2 HW prefetcher requests that hit L2.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe1",
+ "BriefDescription": "Demand Data Read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "Errata": "HSD78",
+ "PublicDescription": "Counts any demand and L1 HW prefetch data load requests to L2.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe2",
+ "BriefDescription": "RFO requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PublicDescription": "Counts all L2 store RFO requests.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe4",
+ "BriefDescription": "L2 code requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PublicDescription": "Counts all L2 code requests.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xf8",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "PublicDescription": "Counts all L2 HW prefetcher requests.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "UMask": "0x50",
+ "BriefDescription": "Not rejected writebacks that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_DEMAND_RQSTS.WB_HIT",
+ "PublicDescription": "Not rejected writebacks that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x41",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PublicDescription": "This event counts each cache miss condition for references to the last level cache.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "UMask": "0x4f",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "Counter": "0,1,2,3",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PublicDescription": "This event counts requests originating from the core that reference a cache line in the last level cache.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PublicDescription": "Increments the number of outstanding L1D misses every cycle. Set Cmask = 1 and Edge =1 to count occurrences.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch. HWP are e.",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.REQUEST_FB_FULL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x51",
+ "UMask": "0x1",
+ "BriefDescription": "L1D data line replacements",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D.REPLACEMENT",
+ "PublicDescription": "This event counts when new data lines are brought into the L1 Data cache, which cause other lines to be evicted from the cache.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "Errata": "HSD78, HSD62, HSD61",
+ "PublicDescription": "Offcore outstanding demand data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "Errata": "HSD62, HSD61",
+ "PublicDescription": "Offcore outstanding Demand code Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "Errata": "HSD62, HSD61",
+ "PublicDescription": "Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "Errata": "HSD62, HSD61",
+ "PublicDescription": "Offcore outstanding cacheable data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "HSD78, HSD62, HSD61",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "CounterMask": "1",
+ "Errata": "HSD62, HSD61",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "CounterMask": "1",
+ "Errata": "HSD62, HSD61",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles when L1D is locked",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "PublicDescription": "Cycles in which the L1D is locked.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "Errata": "HSD78",
+ "PublicDescription": "Demand data read requests sent to uncore.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x2",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "PublicDescription": "Demand code read requests sent to uncore.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x4",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PublicDescription": "Demand RFO read requests sent to uncore, including regular RFOs, locks, ItoM.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "UMask": "0x8",
+ "BriefDescription": "Demand and prefetch data reads",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PublicDescription": "Data read requests sent to uncore (demand and prefetch).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb2",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x11",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x12",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x21",
+ "BriefDescription": "Retired load uops with locked access.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "Errata": "HSD76, HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x41",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x42",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x81",
+ "BriefDescription": "All retired load uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD0",
+ "UMask": "0x82",
+ "BriefDescription": "All retired store uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "2000003",
+ "L1_Hit_Indication": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "Errata": "HSD76, HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were data hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "PublicDescription": "Retired load uops with L3 cache hits as data sources.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops misses in L1 cache as data sources.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "Errata": "HSM30",
+ "PublicDescription": "Retired load uops missed L1 cache as data sources.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x10",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "Errata": "HSD29, HSM30",
+ "PublicDescription": "Retired load uops missed L2. Unknown data source excluded.",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x20",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_MISS",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "PublicDescription": "Retired load uops missed L3. Excludes unknown data source .",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "UMask": "0x40",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "Errata": "HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x1",
+ "BriefDescription": "Retired load uops which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_MISS",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x2",
+ "BriefDescription": "Retired load uops which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared L3.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HITM",
+ "Errata": "HSD29, HSD25, HSM26, HSM30",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "UMask": "0x8",
+ "BriefDescription": "Retired load uops which data sources were hits in L3 without snoops required.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_NONE",
+ "Errata": "HSD74, HSD29, HSD25, HSM26, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x1",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
+ "Errata": "HSD74, HSD29, HSD25, HSM30",
+ "PublicDescription": "This event counts retired load uops where the data came from local DRAM. This does not include hardware prefetches.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x4",
+ "BriefDescription": "Retired load uop whose Data Source was: remote DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_DRAM",
+ "Errata": "HSD29, HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x10",
+ "BriefDescription": "Retired load uop whose Data Source was: Remote cache HITM",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_HITM",
+ "Errata": "HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "UMask": "0x20",
+ "BriefDescription": "Retired load uop whose Data Source was: forwarded from remote cache",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD",
+ "Errata": "HSM30",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x1",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "PublicDescription": "Demand data read requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x2",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.RFO",
+ "PublicDescription": "RFO requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.CODE_RD",
+ "PublicDescription": "L2 cache accesses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x8",
+ "BriefDescription": "L2 or L3 HW prefetches that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_PF",
+ "PublicDescription": "Any MLC or L3 HW prefetch accessing L2, including rejects.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x10",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L1D_WB",
+ "PublicDescription": "L1D writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x20",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_FILL",
+ "PublicDescription": "L2 fill requests that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x40",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.L2_WB",
+ "PublicDescription": "L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf0",
+ "UMask": "0x80",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "PublicDescription": "Transactions accessing L2 pipe.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x1",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.I",
+ "PublicDescription": "L2 cache lines in I state filling L2.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x2",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.S",
+ "PublicDescription": "L2 cache lines in S state filling L2.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x4",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.E",
+ "PublicDescription": "L2 cache lines in E state filling L2.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "UMask": "0x7",
+ "BriefDescription": "L2 cache lines filling L2",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_IN.ALL",
+ "PublicDescription": "This event counts the number of L2 cache lines brought into the L2 cache. Lines are filled into the L2 cache when there was an L2 miss.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "UMask": "0x5",
+ "BriefDescription": "Clean L2 cache lines evicted by demand",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "PublicDescription": "Clean L2 cache lines evicted by demand.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "UMask": "0x6",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "PublicDescription": "Dirty L2 cache lines evicted by demand.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xf4",
+ "UMask": "0x10",
+ "BriefDescription": "Split locks in SQ",
+ "Counter": "0,1,2,3",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x42",
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "PublicDescription": "Counts the number of store RFO requests that hit the L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x22",
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "PublicDescription": "Counts the number of store RFO requests that miss the L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x44",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "PublicDescription": "Number of instruction fetches that hit the L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x24",
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "PublicDescription": "Number of instruction fetches that missed the L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x27",
+ "BriefDescription": "Demand requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "Errata": "HSD78",
+ "PublicDescription": "Demand requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xe7",
+ "BriefDescription": "Demand requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "Errata": "HSD78",
+ "PublicDescription": "Demand requests to L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0x3f",
+ "BriefDescription": "All requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.MISS",
+ "Errata": "HSD78",
+ "PublicDescription": "All requests that missed L2.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "UMask": "0xff",
+ "BriefDescription": "All L2 requests",
+ "Counter": "0,1,2,3",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "Errata": "HSD78",
+ "PublicDescription": "All requests to L2 cache.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "CounterMask": "6",
+ "Errata": "HSD78, HSD62, HSD61",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "Counter": "2",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "Counter": "0,1,2,3",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0001",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0004",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0004",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3",
+ "MSRValue": "0x3f803c0010",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3",
+ "MSRValue": "0x3f803c0020",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the L3",
+ "MSRValue": "0x3f803c0040",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3",
+ "MSRValue": "0x3f803c0080",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3",
+ "MSRValue": "0x3f803c0100",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the L3",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c0122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c0244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "MSRValue": "0x04003c07f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "MSRValue": "0x10003c07f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all requests that hit in the L3",
+ "MSRValue": "0x3f803c8fff",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/floating-point.json b/tools/perf/pmu-events/arch/x86/haswellx/floating-point.json
new file mode 100644
index 000000000000..6282aed6e090
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/floating-point.json
@@ -0,0 +1,83 @@
+[
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x8",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "Errata": "HSD56, HSM57",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x10",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "Errata": "HSD56, HSM57",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x2",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "PublicDescription": "Number of X87 FP assists due to output values.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x4",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "PublicDescription": "Number of X87 FP assists due to input values.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "PublicDescription": "Number of SIMD FP assists due to output values.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x10",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "PublicDescription": "Number of SIMD FP assists due to input values.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "UMask": "0x1e",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "Counter": "0,1,2,3",
+ "EventName": "FP_ASSIST.ANY",
+ "CounterMask": "1",
+ "PublicDescription": "Cycles with any input/output SSE* or FP assists.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC6",
+ "UMask": "0x7",
+ "BriefDescription": "Approximate counts of AVX & AVX2 256-bit instructions, including non-arithmetic instructions, loads, and stores. May count non-AVX instructions that employ 256-bit operations, including (but not necessarily limited to) rep string instructions that use 256-bit loads and stores for optimized performance, XSAVE* and XRSTOR*, and operations that transition the x87 FPU data registers between x87 and MMX.",
+ "Counter": "0,1,2,3",
+ "EventName": "AVX_INSTS.ALL",
+ "PublicDescription": "Note that a whole rep string only counts AVX_INST.ALL once.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/frontend.json b/tools/perf/pmu-events/arch/x86/haswellx/frontend.json
new file mode 100644
index 000000000000..2d0c7aac1e61
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/frontend.json
@@ -0,0 +1,294 @@
+[
+ {
+ "EventCode": "0x79",
+ "UMask": "0x2",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.EMPTY",
+ "Errata": "HSD135",
+ "PublicDescription": "Counts cycles the IDQ is empty.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_UOPS",
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MITE path. Set Cmask = 1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_UOPS",
+ "PublicDescription": "Increment each cycle. # of uops delivered to IDQ from DSB path. Set Cmask = 1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x20",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set Cmask = 1 to count cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_UOPS",
+ "PublicDescription": "This event counts uops delivered by the Front-end with the assistance of the microcode sequencer. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts cycles during which the microcode sequencer assisted the Front-end in delivering uops. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.DSB_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x10",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "Counts cycles DSB is delivered four uops. Set Cmask = 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x18",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "Counts cycles DSB is delivered at least one uops. Set Cmask = 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "PublicDescription": "Counts cycles MITE is delivered four uops. Set Cmask = 4.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x24",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "CounterMask": "1",
+ "PublicDescription": "Counts cycles MITE is delivered at least one uop. Set Cmask = 1.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "UMask": "0x3c",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "PublicDescription": "Number of uops delivered to IDQ from any path.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x2",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes Uncacheable accesses.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.MISSES",
+ "PublicDescription": "This event counts Instruction Cache (ICACHE) misses.",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.IFETCH_STALL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "Errata": "HSD135",
+ "PublicDescription": "This event count the number of undelivered (unallocated) uops from the Front-end to the Resource Allocation Table (RAT) while the Back-end of the processor is not stalled. The Front-end can allocate up to 4 uops per cycle so this event can increment 0-4 times per cycle depending on the number of unallocated uops. This event is counted on a per-core basis.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "CounterMask": "4",
+ "Errata": "HSD135",
+ "PublicDescription": "This event counts the number cycles during which the Front-end allocated exactly zero uops to the Resource Allocation Table (RAT) while the Back-end of the processor is not stalled. This event is counted on a per-core basis.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "CounterMask": "3",
+ "Errata": "HSD135",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "CounterMask": "2",
+ "Errata": "HSD135",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "CounterMask": "1",
+ "Errata": "HSD135",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x9C",
+ "UMask": "0x1",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "CounterMask": "1",
+ "Errata": "HSD135",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "UMask": "0x2",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "Counter": "0,1,2,3",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "UMask": "0x30",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "Counter": "0,1,2,3",
+ "EventName": "IDQ.MS_SWITCHES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x80",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction-cache miss.",
+ "Counter": "0,1,2,3",
+ "EventName": "ICACHE.IFDATA_STALL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/memory.json b/tools/perf/pmu-events/arch/x86/haswellx/memory.json
new file mode 100644
index 000000000000..0886cc000d22
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/memory.json
@@ -0,0 +1,739 @@
+[
+ {
+ "EventCode": "0x05",
+ "UMask": "0x1",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "PublicDescription": "Speculative cache-line split load uops dispatched to L1D.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "UMask": "0x2",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "Counter": "0,1,2,3",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "PublicDescription": "Speculative cache-line split store-address uops dispatched to L1D.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional writes.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x1",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x4",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x8",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5d",
+ "UMask": "0x10",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "Counter": "0,1,2,3",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x2",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PublicDescription": "This event counts the number of memory ordering machine clears detected. Memory ordering machine clears can result from memory address aliasing or snoops from another hardware thread or core to data inflight in the pipeline. Machine clears can have a significant performance impact if they are happening frequently.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times an HLE execution started.",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times an HLE execution successfully committed.",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an HLE execution aborted due to uncommon conditions.",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions.",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC4",
+ "Errata": "HSD65",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc8",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts)",
+ "Counter": "0,1,2,3",
+ "EventName": "HLE_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times an HLE execution aborted due to none of the previous 4 categories (e.g. interrupts).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC9",
+ "UMask": "0x1",
+ "BriefDescription": "Number of times an RTM execution started.",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x2",
+ "BriefDescription": "Number of times an RTM execution successfully committed.",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x4",
+ "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x8",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC1",
+ "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x10",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x20",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC4",
+ "Errata": "HSD65",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xc9",
+ "UMask": "0x80",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "Counter": "0,1,2,3",
+ "EventName": "RTM_RETIRED.ABORTED_MISC5",
+ "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 4.",
+ "PEBS": "2",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 8.",
+ "PEBS": "2",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "50021",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 16.",
+ "PEBS": "2",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "20011",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 32.",
+ "PEBS": "2",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 64.",
+ "PEBS": "2",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "2003",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 128.",
+ "PEBS": "2",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "1009",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 256.",
+ "PEBS": "2",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "503",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xCD",
+ "UMask": "0x1",
+ "BriefDescription": "Loads with latency value being above 512.",
+ "PEBS": "2",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "Errata": "HSD76, HSD25, HSM26",
+ "TakenAlone": "1",
+ "SampleAfterValue": "101",
+ "CounterHTOff": "3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts demand data reads that miss in the L3",
+ "MSRValue": "0x3fbfc00001",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400001",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss in the L3",
+ "MSRValue": "0x3fbfc00002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc00002",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00004",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400004",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3",
+ "MSRValue": "0x3fbfc00010",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3",
+ "MSRValue": "0x3fbfc00020",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00040",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3",
+ "MSRValue": "0x3fbfc00080",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3",
+ "MSRValue": "0x3fbfc00100",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00200",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3",
+ "MSRValue": "0x3fbfc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram",
+ "MSRValue": "0x063f800091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache",
+ "MSRValue": "0x083fc00091",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3",
+ "MSRValue": "0x3fbfc00122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400122",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss in the L3",
+ "MSRValue": "0x3fbfc00244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x0600400244",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss in the L3",
+ "MSRValue": "0x3fbfc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the data is returned from local dram",
+ "MSRValue": "0x06004007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the data is returned from remote dram",
+ "MSRValue": "0x063f8007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and the modified data is transferred from remote cache",
+ "MSRValue": "0x103fc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the L3 and clean or shared data is transferred from remote cache",
+ "MSRValue": "0x083fc007f7",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Offcore": "1",
+ "EventCode": "0xB7, 0xBB",
+ "UMask": "0x1",
+ "BriefDescription": "Counts all requests that miss in the L3",
+ "MSRValue": "0x3fbfc08fff",
+ "Counter": "0,1,2,3",
+ "EventName": "OFFCORE_RESPONSE.ALL_REQUESTS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/other.json b/tools/perf/pmu-events/arch/x86/haswellx/other.json
new file mode 100644
index 000000000000..4e1b6ce96ca3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/other.json
@@ -0,0 +1,43 @@
+[
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0",
+ "PublicDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "UMask": "0x2",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING123",
+ "PublicDescription": "Unhalted core cycles when the thread is not in ring 0.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0x5C",
+ "UMask": "0x1",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "CounterMask": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "Counter": "0,1,2,3",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "PublicDescription": "Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/pipeline.json b/tools/perf/pmu-events/arch/x86/haswellx/pipeline.json
new file mode 100644
index 000000000000..c3a163d34bd7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/pipeline.json
@@ -0,0 +1,1329 @@
+[
+ {
+ "EventCode": "0x00",
+ "UMask": "0x1",
+ "BriefDescription": "Instructions retired from execution.",
+ "Counter": "Fixed counter 1",
+ "EventName": "INST_RETIRED.ANY",
+ "Errata": "HSD140, HSD143",
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. INST_RETIRED.ANY is counted by a designated fixed counter, leaving the programmable counters available for other events. Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PublicDescription": "This event counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x3",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "Counter": "Fixed counter 3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x2",
+ "BriefDescription": "loads blocked by overlapping with store buffer that cannot be forwarded",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "PublicDescription": "This event counts loads that followed a store to the same address, where the data could not be forwarded inside the pipeline from the store to the load. The most common reason why store forwarding would be blocked is when a load's address range overlaps with a preceding smaller uncompleted store. The penalty for blocked store forwarding is that the load must wait for the store to write its value to the cache before it can be issued.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "UMask": "0x8",
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x07",
+ "UMask": "0x1",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "Counter": "0,1,2,3",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PublicDescription": "Aliasing occurs when a load is issued after a store and their memory addresses are offset by 4K. This event counts the number of loads that aliased with a preceding store, resulting in an extended address check in the pipeline which can have a performance impact.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...)",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "CounterMask": "1",
+ "PublicDescription": "This event counts the number of cycles spent waiting for a recovery after an event such as a processor nuke, JEClear, assist, hle/rtm abort etc.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PublicDescription": "This event counts the number of uops issued by the Front-end of the pipeline to the Back-end. This event is counted at the allocation stage and will count both retired and non-retired uops.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x10",
+ "BriefDescription": "Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "PublicDescription": "Number of flags-merge uops allocated. Such uops add delay.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x20",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "PublicDescription": "Number of slow LEA or similar uops allocated. Such uop has 3 sources (for example, 2 sources + immediate) regardless of whether it is a result of LEA instruction or not.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "UMask": "0x40",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "PublicDescription": "Number of multiply packed/scalar single precision uops allocated.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0x0E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x14",
+ "UMask": "0x2",
+ "BriefDescription": "Any uop executed by the Divider. (This includes all divide uops, sqrt, ...)",
+ "Counter": "0,1,2,3",
+ "EventName": "ARITH.DIVIDER_UOPS",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "PublicDescription": "Increments at the frequency of XCLK (100 MHz) when not halted.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3c",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x4c",
+ "UMask": "0x1",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4c",
+ "UMask": "0x2",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "Counter": "0,1,2,3",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x1",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "PublicDescription": "Number of integer move elimination candidate uops that were eliminated.",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x2",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "PublicDescription": "Number of SIMD move elimination candidate uops that were eliminated.",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x4",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "PublicDescription": "Number of integer move elimination candidate uops that were not eliminated.",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "UMask": "0x8",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "Counter": "0,1,2,3",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "PublicDescription": "Number of SIMD move elimination candidate uops that were not eliminated.",
+ "SampleAfterValue": "1000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PublicDescription": "This event counts cycles when the Reservation Station ( RS ) is empty for the thread. The RS is a structure that buffers allocated micro-ops from the Front-end. If there are many cycles when the RS is empty, it may represent an underflow of instructions delivered from the Front-end.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "UMask": "0x1",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "Counter": "0,1,2,3",
+ "EventName": "ILD_STALL.LCP",
+ "PublicDescription": "This event counts cycles where the decoder is stalled on an instruction with a length changing prefix (LCP).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "UMask": "0x4",
+ "BriefDescription": "Stall cycles because IQ is full",
+ "Counter": "0,1,2,3",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "PublicDescription": "Stall cycles due to IQ is full.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken macro-conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x82",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0x90",
+ "BriefDescription": "Taken speculative and retired direct near calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired indirect calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired macro-conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc2",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc4",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xc8",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xd0",
+ "BriefDescription": "Speculative and retired direct near calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x41",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x81",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x84",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0x88",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc1",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xc4",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xff",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0",
+ "PublicDescription": "Cycles which a uop is dispatched on port 0 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1",
+ "PublicDescription": "Cycles which a uop is dispatched on port 1 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2",
+ "PublicDescription": "Cycles which a uop is dispatched on port 2 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3",
+ "PublicDescription": "Cycles which a uop is dispatched on port 3 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4",
+ "PublicDescription": "Cycles which a uop is dispatched on port 4 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5",
+ "PublicDescription": "Cycles which a uop is dispatched on port 5 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6",
+ "PublicDescription": "Cycles which a uop is dispatched on port 6 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7",
+ "PublicDescription": "Cycles which a uop is dispatched on port 7 in this thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x1",
+ "BriefDescription": "Resource-related stall cycles",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "Errata": "HSD135",
+ "PublicDescription": "Cycles allocation is stalled due to resource related reason.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PublicDescription": "This event counts cycles during which no instructions were allocated because no Store Buffers (SB) were available.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "Counter": "0,1,2,3",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with pending L2 cache miss loads.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "CounterMask": "1",
+ "Errata": "HSD78",
+ "PublicDescription": "Cycles with pending L2 miss loads. Set Cmask=2 to count cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles with pending L1 cache miss loads.",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "CounterMask": "8",
+ "PublicDescription": "Cycles with pending L1 data cache miss loads. Set Cmask=8 to count cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles with pending memory loads.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "CounterMask": "2",
+ "PublicDescription": "Cycles with pending memory loads. Set Cmask=2 to count cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x4",
+ "BriefDescription": "Total execution stalls",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "CounterMask": "4",
+ "PublicDescription": "This event counts cycles during which no instructions were executed in the execution stage of the pipeline.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x5",
+ "BriefDescription": "Execution stalls due to L2 cache misses.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "CounterMask": "5",
+ "PublicDescription": "Number of loads missed L2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0x6",
+ "BriefDescription": "Execution stalls due to memory subsystem.",
+ "Counter": "0,1,2,3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "CounterMask": "6",
+ "PublicDescription": "This event counts cycles during which no instructions were executed in the execution stage of the pipeline and there were memory instructions pending (waiting for data).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "UMask": "0xc",
+ "BriefDescription": "Execution stalls due to L1 data cache misses",
+ "Counter": "2",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "CounterMask": "12",
+ "PublicDescription": "Execution stalls due to L1 data cache miss loads. Set Cmask=0CH.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xa8",
+ "UMask": "0x1",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.UOPS",
+ "PublicDescription": "Number of uops delivered by the LSD.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x2",
+ "BriefDescription": "Number of uops executed on the core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "Errata": "HSD30, HSM31",
+ "PublicDescription": "Counts total number of uops to be executed per-core each cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "CounterMask": "1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x0",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.ANY_P",
+ "Errata": "HSD11, HSD140",
+ "PublicDescription": "Number of instructions at retirement.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x2",
+ "BriefDescription": "FP operations retired. X87 FP operations that have no exceptions: Counts also flows that have several X87 or flows that use X87 uops in the exception handling.",
+ "Counter": "0,1,2,3",
+ "EventName": "INST_RETIRED.X87",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts FP operations retired. For X87 FP operations that have no exceptions counting also includes flows that have several X87, or flows that use X87 uops in the exception handling.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "UMask": "0x1",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "PEBS": "2",
+ "Counter": "1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "Errata": "HSD140",
+ "PublicDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "UMask": "0x40",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "Counter": "0,1,2,3",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "PublicDescription": "Number of microcode assists invoked by HW upon uop writeback.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Actually retired uops.",
+ "Data_LA": "1",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.ALL",
+ "PublicDescription": "Counts the number of micro-ops retired. Use Cmask=1 and invert to count active cycles or stalled cycles.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "UMask": "0x2",
+ "BriefDescription": "Retirement slots used.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "PublicDescription": "This event counts the number of retirement slots used each cycle. There are potentially 4 slots that can be used each cycle - meaning, 4 uops or 4 instructions could retire each cycle.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "CounterMask": "10",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xC2",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles there was a Nuke. Account for both thread-specific and All Thread Nukes.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x4",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PublicDescription": "This event is incremented when self-modifying code (SMC) is detected, which causes a machine clear. Machine clears can have a significant performance impact if they are happening frequently.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "UMask": "0x20",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x1",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "PublicDescription": "Counts the number of conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x2",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x0",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Branch instructions at retirement.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x8",
+ "BriefDescription": "Return instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PublicDescription": "Counts the number of near return instructions retired.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x10",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "PublicDescription": "Counts the number of not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x20",
+ "BriefDescription": "Taken branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "Number of near taken branches retired.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x40",
+ "BriefDescription": "Far branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "PublicDescription": "Number of far branches retired.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "UMask": "0x4",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x1",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x0",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Mispredicted branch instructions at retirement.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x4",
+ "BriefDescription": "Mispredicted macro branch instructions retired. ",
+ "PEBS": "2",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "PublicDescription": "This event counts all mispredicted branch instructions retired. This is a precise event.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xCC",
+ "UMask": "0x20",
+ "BriefDescription": "Count cases of saving new LBR",
+ "Counter": "0,1,2,3",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "PublicDescription": "Count cases of saving new LBR records by hardware.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PublicDescription": "Counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "UMask": "0xa0",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_0_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 1.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_1_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 2.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_2_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 3.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_3_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 4.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_4_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 5.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_5_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per core when uops are exectuted in port 6.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_6_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 7.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED_PORT.PORT_7_CORE",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "UMask": "0x20",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken.",
+ "PEBS": "1",
+ "Counter": "0,1,2,3",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "PublicDescription": "Number of near branch instructions retired that were taken but mispredicted.",
+ "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "CounterMask": "1",
+ "Errata": "HSD144, HSD30, HSM31",
+ "PublicDescription": "This events counts the cycles where at least one uop was executed. It is counted per thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "CounterMask": "2",
+ "Errata": "HSD144, HSD30, HSM31",
+ "PublicDescription": "This events counts the cycles where at least two uop were executed. It is counted per thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "CounterMask": "3",
+ "Errata": "HSD144, HSD30, HSM31",
+ "PublicDescription": "This events counts the cycles where at least three uop were executed. It is counted per thread.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "CounterMask": "4",
+ "Errata": "HSD144, HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xe6",
+ "UMask": "0x1f",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "Counter": "0,1,2,3",
+ "EventName": "BACLEARS.ANY",
+ "PublicDescription": "Number of front end re-steers due to BPU misprediction.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "EventCode": "0xC3",
+ "UMask": "0x1",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "Counter": "0,1,2,3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "CounterMask": "1",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "CounterMask": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "Counter": "0,1,2,3",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "CounterMask": "4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EdgeDetect": "1",
+ "Invert": "1",
+ "EventCode": "0x5E",
+ "UMask": "0x1",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "Counter": "0,1,2,3",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "CounterMask": "1",
+ "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x1",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x4",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x8",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x20",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x40",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "UMask": "0x80",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x00",
+ "UMask": "0x2",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x0",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "AnyThread": "1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "PublicDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "UMask": "0x3",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke)",
+ "Counter": "0,1,2,3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "AnyThread": "1",
+ "CounterMask": "1",
+ "PublicDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "CounterMask": "1",
+ "Errata": "HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "CounterMask": "2",
+ "Errata": "HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "CounterMask": "3",
+ "Errata": "HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "CounterMask": "4",
+ "Errata": "HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "Invert": "1",
+ "EventCode": "0xb1",
+ "UMask": "0x2",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "Errata": "HSD30, HSM31",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "PublicDescription": "Reference cycles when the thread is unhalted. (counts at 100 MHz rate)",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x1",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate)",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "AnyThread": "1",
+ "PublicDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "UMask": "0x2",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "Counter": "0,1,2,3",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/virtual-memory.json b/tools/perf/pmu-events/arch/x86/haswellx/virtual-memory.json
new file mode 100644
index 000000000000..9c00f8ef6a07
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/virtual-memory.json
@@ -0,0 +1,484 @@
+[
+ {
+ "EventCode": "0x08",
+ "UMask": "0x1",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Misses in all TLB levels that cause a page walk of any page size.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x2",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Completed page walks due to demand load misses that caused 4K page walks in any TLB levels.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x4",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Completed page walks due to demand load misses that caused 2M/4M page walks in any TLB levels.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x8",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB load misses.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x20",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_4K",
+ "PublicDescription": "This event counts load operations from a 4K page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x40",
+ "BriefDescription": "Load misses that miss the DTLB and hit the STLB (2M)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT_2M",
+ "PublicDescription": "This event counts load operations from a 2M page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x80",
+ "BriefDescription": "DTLB demand load misses with low part of linear-to-physical address translation missed",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.PDE_CACHE_MISS",
+ "PublicDescription": "DTLB demand load misses with low part of linear-to-physical address translation missed.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x1",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Miss in all TLB levels causes a page walk of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x2",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Completed page walks due to store misses in one or more TLB levels of 4K page structure.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x4",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Completed page walks due to store misses in one or more TLB levels of 2M/4M page structure.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x8",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB store misses.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x20",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_4K",
+ "PublicDescription": "This event counts store operations from a 4K page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x40",
+ "BriefDescription": "Store misses that miss the DTLB and hit the STLB (2M)",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT_2M",
+ "PublicDescription": "This event counts store operations from a 2M page that miss the first DTLB level but hit the second and do not cause page walks.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x80",
+ "BriefDescription": "DTLB store misses with low part of linear-to-physical address translation missed",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.PDE_CACHE_MISS",
+ "PublicDescription": "DTLB store misses with low part of linear-to-physical address translation missed.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4f",
+ "UMask": "0x10",
+ "BriefDescription": "Cycle count for an Extended Page table walk.",
+ "Counter": "0,1,2,3",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x1",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Misses in ITLB that causes a page walk of any page size.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x2",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Completed page walks due to misses in ITLB 4K page entries.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x4",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Completed page walks due to misses in ITLB 2M/4M page entries.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x8",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x10",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by ITLB misses.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x20",
+ "BriefDescription": "Core misses that miss the DTLB and hit the STLB (4K)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_4K",
+ "PublicDescription": "ITLB misses that hit STLB (4K).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x40",
+ "BriefDescription": "Code misses that miss the DTLB and hit the STLB (2M)",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT_2M",
+ "PublicDescription": "ITLB misses that hit STLB (2M).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xae",
+ "UMask": "0x1",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "PublicDescription": "Counts the number of ITLB flushes, includes 4k/2M/4M pages.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x11",
+ "BriefDescription": "Number of DTLB page walker hits in the L1+FB",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L1",
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L1+FB.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x21",
+ "BriefDescription": "Number of ITLB page walker hits in the L1+FB",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L1",
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L1+FB.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x41",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L1 and FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x81",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L1 and FB.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L1",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x12",
+ "BriefDescription": "Number of DTLB page walker hits in the L2",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L2",
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x22",
+ "BriefDescription": "Number of ITLB page walker hits in the L2",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L2",
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L2.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x42",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x82",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L2",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x14",
+ "BriefDescription": "Number of DTLB page walker hits in the L3 + XSNP",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_L3",
+ "Errata": "HSD25",
+ "PublicDescription": "Number of DTLB page walker loads that hit in the L3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x24",
+ "BriefDescription": "Number of ITLB page walker hits in the L3 + XSNP",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_L3",
+ "Errata": "HSD25",
+ "PublicDescription": "Number of ITLB page walker loads that hit in the L3.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x44",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in the L3.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_L3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x84",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in the L2.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_L3",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x18",
+ "BriefDescription": "Number of DTLB page walker hits in Memory",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.DTLB_MEMORY",
+ "Errata": "HSD25",
+ "PublicDescription": "Number of DTLB page walker loads from memory.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x28",
+ "BriefDescription": "Number of ITLB page walker hits in Memory",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.ITLB_MEMORY",
+ "Errata": "HSD25",
+ "PublicDescription": "Number of ITLB page walker loads from memory.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x48",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the DTLB that hit in memory.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_DTLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBC",
+ "UMask": "0x88",
+ "BriefDescription": "Counts the number of Extended Page Table walks from the ITLB that hit in memory.",
+ "Counter": "0,1,2,3",
+ "EventName": "PAGE_WALKER_LOADS.EPT_ITLB_MEMORY",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x1",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "PublicDescription": "DTLB flush attempts of the thread-specific entries.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "UMask": "0x20",
+ "BriefDescription": "STLB flush attempts",
+ "Counter": "0,1,2,3",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PublicDescription": "Count number of STLB flush attempts.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0xe",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Completed page walks in any TLB of any page size due to demand load misses.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "UMask": "0x60",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "PublicDescription": "Number of cache load STLB hits. No page walk.",
+ "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0xe",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Completed page walks due to store miss in any TLB levels of any page size (4K/2M/4M/1G).",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "UMask": "0x60",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "PublicDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0xe",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Completed page walks in ITLB of any page size.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "UMask": "0x60",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks",
+ "Counter": "0,1,2,3",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "PublicDescription": "ITLB misses that hit STLB. No page walk.",
+ "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/cache.json b/tools/perf/pmu-events/arch/x86/ivybridge/cache.json
new file mode 100644
index 000000000000..f1ee6d4853c5
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/cache.json
@@ -0,0 +1,1123 @@
+[
+ {
+ "PublicDescription": "Demand Data Read requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of store RFO requests that miss the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that hit the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that missed the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that hit L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that missed L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts any demand and L1 HW prefetch data load requests to L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 store RFO requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that miss cache lines.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_STORE_LOCK_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that miss cache lines",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that hit cache lines in M state.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in M state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that access cache lines in any state.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_STORE_LOCK_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that access cache lines in any state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks that missed LLC.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_L1D_WB_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Count the number of modified Lines evicted from L1 and missed L2. (Non-rejected WBs from the DCU.)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks from L1D to L2 cache lines in E state.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in E state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks from L1D to L2 cache lines in M state.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in M state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_L1D_WB_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts each cache miss condition for references to the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed LLC",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts requests originating from the core that reference a cache line in the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to LLC",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments the number of outstanding L1D misses every cycle. Set Cmask = 1 and Edge =1 to count occurrences.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Counts the number of lines brought into the L1 data cache.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding Demand Data Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding Demand Code Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding cacheable data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D is locked.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand data read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand code read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand RFO read requests sent to uncore, including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Data read requests sent to uncore (demand and prefetch).",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cases when offcore requests buffer cannot take more entries for core.",
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases when offcore requests buffer cannot take more entries for core",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops with L1 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops with L2 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was LLC hit with no snoop required.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in LLC without snoops required. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source followed an L1 miss.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources following L1 data-cache miss",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops that missed L2, excluding unknown sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source is LLC miss.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package core cache LLC hit and cross-core snoop missed.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC hit and cross-core snoop missed in on-pkg core cache. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package LLC hit and cross-core snoop hits.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC and cross-core snoop hits in on-pkg core cache. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package core cache with HitM responses.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared LLC. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was LLC hit with no snoop required.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in LLC without snoops required. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Retired load uop whose Data Source was: local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops which data sources missed LLC but serviced from local dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Demand Data Read requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache accesses when fetching instructions.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Any MLC or LLC HW prefetch accessing L2, including rejects.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or LLC HW prefetches that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L1D writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 fill requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Transactions accessing L2 pipe.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in I state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in S state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in E state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Clean L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Clean L2 cache lines evicted by the MLC prefetcher.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PF_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by L2 prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines evicted by the MLC prefetcher.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PF_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by L2 prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines filling the L2.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "L2_LINES_OUT.DIRTY_ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines filling the L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Retired load uops whose data source was local memory (cross-socket snoop not needed or missed).",
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops which data sources missed LLC but serviced from local dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch RFOs that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all writebacks from the core to the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x18000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts miscellaneous accesses that include port i/o, MMIO and uncacheable memory accesses. It also includes L2 hints sent to LLC to keep a line from being evicted out of the core caches",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10400",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.SPLIT_LOCK_UC_LOCK.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts requests where the address of an atomic lock instruction spans a cache line boundary or the lock instruction is executed on uncacheable address ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10800",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts non-temporal stores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand rfo's ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000105B3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch prefetch RFOs ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000107F7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo references (demand & prefetch) ",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json b/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json
new file mode 100644
index 000000000000..950b62c0908e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json
@@ -0,0 +1,151 @@
+[
+ {
+ "PublicDescription": "Counts number of X87 uops executed.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULsand IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts number of SSE* or AVX-128 double precision FP scalar uops executed.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar double-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts 256-bit packed single-precision floating-point instructions.",
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_FP_256.PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "number of GSSE-256 Computational FP single precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts 256-bit packed double-precision floating-point instructions.",
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_FP_256.PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "number of AVX-256 Computational FP double precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of assists associated with 256-bit AVX store operations.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OTHER_ASSISTS.AVX_STORE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of GSSE memory assist for stores. GSSE microcode assist is being invoked whenever the hardware is unable to properly handle GSSE-256b operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with any input/output SSE* or FP assists.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json b/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json
new file mode 100644
index 000000000000..de72b84b3536
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json
@@ -0,0 +1,305 @@
+[
+ {
+ "PublicDescription": "Counts cycles the IDQ is empty.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MITE path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle. # of uops delivered to IDQ from DSB path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MS by either DSB or MITE. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered at least one uops. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered at least one uops. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops delivered to IDQ from any path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes UC accesses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction cache, streaming buffer and victim cache misses",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where a code-fetch stalled due to L1 instruction-cache miss or an iTLB miss.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE.IFETCH_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code-fetch stalled due to L1 instruction-cache miss or an iTLB miss",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Count issue pipeline slots where no uop was delivered from the front end to the back end when there is no back-end stall.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of DSB to MITE switches.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles DSB to MITE switches caused delay.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DSB Fill encountered > 3 DSB lines.",
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DSB_FILL.EXCEED_DSB_LINES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Decode Stream Buffer (DSB) fill encounter more than 3 Decode Stream Buffer (DSB) lines",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/memory.json b/tools/perf/pmu-events/arch/x86/ivybridge/memory.json
new file mode 100644
index 000000000000..e1c6a1d4a4d5
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/memory.json
@@ -0,0 +1,236 @@
+[
+ {
+ "PublicDescription": "Speculative cache-line split load uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative cache-line split Store-address uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.LLC_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of any page walk that had a miss in LLC.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "Counter": "3",
+ "UMask": "0x2",
+ "EventName": "MEM_TRANS_RETIRED.PRECISE_STORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Sample stores and collect precise store operation via PEBS record. PMC3 only.",
+ "PRECISE_STORE": "1",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 4.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 8.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 16.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 32.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads with latency value being above 32",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 64.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 128.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 256.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 512.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the LLC and the data returned from dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the LLC and the data returned from dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3004003f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the LLC and the data returned from dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that miss the LLC and the data returned from dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6004001b3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN_SOCKET.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts LLC replacements",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/other.json b/tools/perf/pmu-events/arch/x86/ivybridge/other.json
new file mode 100644
index 000000000000..9c2dd0511a32
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/other.json
@@ -0,0 +1,44 @@
+[
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is not in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/pipeline.json b/tools/perf/pmu-events/arch/x86/ivybridge/pipeline.json
new file mode 100644
index 000000000000..2145c28193f7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/pipeline.json
@@ -0,0 +1,1307 @@
+[
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "PublicDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "False dependencies in MOB due to partial compare on address.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc.)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EdgeDetect": "1",
+ "EventName": "INT_MISC.RECOVERY_STALLS_COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of occurences waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc.)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments each cycle the # of Uops issued by the RAT to RS. Set Cmask = 1, Inv = 1, Any= 1to count stalled cycles of this core.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of flags-merge uops allocated. Such uops adds delay.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of flags-merge uops being allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of slow LEA or similar uops allocated. Such uop has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of multiply packed/scalar single precision uops allocated.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles that the divider is active, includes INT and FP. Set 'edge =1, cmask=1' to count the number of divides.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divider is busy executing divide operations",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Divide operations executed.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EdgeDetect": "1",
+ "EventName": "ARITH.FPU_DIV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Divide operations executed",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments at the frequency of XCLK (100 MHz) when not halted.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles the RS is empty for the thread.",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Stall cycles due to IQ is full.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stall cycles because IQ is full",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not taken macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 2.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched to port 2, loads and stores per core (speculative and retired).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when load or STA uops are dispatched to port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles Allocation is stalled due to Resource Related reason.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles stalled due to no store buffers available (not including draining form sync).",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L2 miss loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L2 cache miss loads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L1 cache miss loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L1 cache miss loads.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Cycles with pending memory loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending memory loads.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Total execution stalls.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of loads missed L2.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L2 cache misses.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to memory subsystem.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Execution stalls due to L1 data cache miss loads. Set Cmask=0CH.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L1 data cache misses",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts total number of uops to be executed per-thread each cycle. Set Cmask = 1, INV =1 to count stall cycles.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts total number of uops to be executed per-core each cycle.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of instructions at retirement.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution.",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of micro-ops retired, Use cmask=1 and invert to count active cycles or stalled cycles.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of retirement slots used each cycle.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of self-modifying-code machine clears detected.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of executed AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of conditional branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Direct and indirect near call instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Branch instructions at retirement.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of near return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of near taken branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of far branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Mispredicted conditional branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Mispredicted branch instructions at retirement.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Mispredicted taken branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Count cases of saving new LBR records by hardware.",
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of front end re-steers due to BPU misprediction.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss load* is outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss load* is outstanding.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted. (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted. (counts at 100 MHz rate)",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted. (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/virtual-memory.json b/tools/perf/pmu-events/arch/x86/ivybridge/virtual-memory.json
new file mode 100644
index 000000000000..f036f5398906
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/virtual-memory.json
@@ -0,0 +1,180 @@
+[
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "DTLB_LOAD_MISSES.LARGE_PAGE_WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Page walk for a large page completed for Demand load.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Miss in all TLB levels causes a page walk of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Miss in all TLB levels causes a page walk that completes of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles PMH is busy with this walk.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts load operations that missed 1st level DTLB but hit the 2nd level.",
+ "EventCode": "0x5F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all ITLB levels that cause page walks.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycle PMH is busy with a walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of cache load STLB hits. No page walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks in ITLB due to STLB load misses for large pages.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "ITLB_MISSES.LARGE_PAGE_WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Completed page walks in ITLB due to STLB load misses for large pages",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of ITLB flushes, includes 4k/2M/4M pages.",
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Count number of STLB flush attempts.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all TLB levels that cause a page walk of any page size from demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes an page walk of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all TLB levels that caused page walk completed of any size by demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycle PMH is busy with a walk due to demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load cycles page miss handler (PMH) is busy with this walk.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/cache.json b/tools/perf/pmu-events/arch/x86/ivytown/cache.json
new file mode 100644
index 000000000000..ff27a620edd8
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/cache.json
@@ -0,0 +1,1272 @@
+[
+ {
+ "PublicDescription": "Demand Data Read requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of store RFO requests that miss the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that hit the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of instruction fetches that missed the L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that hit L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests that missed L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts any demand and L1 HW prefetch data load requests to L2.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 store RFO requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all L2 HW prefetcher requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that miss cache lines.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_STORE_LOCK_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that miss cache lines",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that hit cache lines in M state.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in M state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFOs that access cache lines in any state.",
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_STORE_LOCK_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that access cache lines in any state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks that missed LLC.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_L1D_WB_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Count the number of modified Lines evicted from L1 and missed L2. (Non-rejected WBs from the DCU.)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks from L1D to L2 cache lines in E state.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in E state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not rejected writebacks from L1D to L2 cache lines in M state.",
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in M state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_L1D_WB_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts each cache miss condition for references to the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed LLC",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts requests originating from the core that reference a cache line in the last level cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to LLC",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments the number of outstanding L1D misses every cycle. Set Cmask = 1 and Edge =1 to count occurrences.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Counts the number of lines brought into the L1 data cache.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding Demand Data Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding Demand Code Read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding cacheable data read transactions in SQ to uncore. Set Cmask=1 to count cycles.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding code reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D is locked.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand data read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand code read requests sent to uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand RFO read requests sent to uncore, including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Data read requests sent to uncore (demand and prefetch).",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cases when offcore requests buffer cannot take more entries for core.",
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases when offcore requests buffer cannot take more entries for core",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops with L1 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops with L2 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was LLC hit with no snoop required.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in LLC without snoops required. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source followed an L1 miss.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources following L1 data-cache miss",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops that missed L2, excluding unknown sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Miss in mid-level (L2) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source is LLC miss.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package core cache LLC hit and cross-core snoop missed.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC hit and cross-core snoop missed in on-pkg core cache. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package LLC hit and cross-core snoop hits.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC and cross-core snoop hits in on-pkg core cache. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was an on-package core cache with HitM responses.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared LLC. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load uops whose data source was LLC hit with no snoop required.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in LLC without snoops required. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Retired load uop whose Data Source was: local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops which data sources missed LLC but serviced from local dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops whose data source was remote DRAM (Snoop not needed, Snoop Miss, or Snoop Hit data not forwarded).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_HITM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Remote cache HITM.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_FWD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Data forwarded from remote cache.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Demand Data Read requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache accesses when fetching instructions.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Any MLC or LLC HW prefetch accessing L2, including rejects.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or LLC HW prefetches that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L1D writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 fill requests that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Transactions accessing L2 pipe.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in I state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in S state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines in E state filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache lines filling L2.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Clean L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines evicted by demand.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Clean L2 cache lines evicted by the MLC prefetcher.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PF_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by L2 prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines evicted by the MLC prefetcher.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PF_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by L2 prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Dirty L2 cache lines filling the L2.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "L2_LINES_OUT.DIRTY_ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines filling the L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all writebacks from the core to the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x803c8000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LRU_HINTS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts L2 hints sent to LLC to keep a line from being evicted out of the core caches",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x23ffc08000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PORTIO_MMIO_UC",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts miscellaneous accesses that include port i/o, MMIO and uncacheable memory accesses",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10400",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.SPLIT_LOCK_UC_LOCK.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts requests where the address of an atomic lock instruction spans a cache line boundary or the lock instruction is executed on uncacheable address",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10800",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts non-temporal stores",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/floating-point.json b/tools/perf/pmu-events/arch/x86/ivytown/floating-point.json
new file mode 100644
index 000000000000..950b62c0908e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/floating-point.json
@@ -0,0 +1,151 @@
+[
+ {
+ "PublicDescription": "Counts number of X87 uops executed.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULsand IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts number of SSE* or AVX-128 double precision FP scalar uops executed.",
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar double-precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts 256-bit packed single-precision floating-point instructions.",
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_FP_256.PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "number of GSSE-256 Computational FP single precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts 256-bit packed double-precision floating-point instructions.",
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_FP_256.PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "number of AVX-256 Computational FP double precision uops issued this cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of assists associated with 256-bit AVX store operations.",
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OTHER_ASSISTS.AVX_STORE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of GSSE memory assist for stores. GSSE microcode assist is being invoked whenever the hardware is unable to properly handle GSSE-256b operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of X87 FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to output values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SIMD FP assists due to input values.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with any input/output SSE* or FP assists.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/frontend.json b/tools/perf/pmu-events/arch/x86/ivytown/frontend.json
new file mode 100644
index 000000000000..de72b84b3536
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/frontend.json
@@ -0,0 +1,305 @@
+[
+ {
+ "PublicDescription": "Counts cycles the IDQ is empty.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MITE path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle. # of uops delivered to IDQ from DSB path. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MS by either DSB or MITE. Set Cmask = 1 to count cycles.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles DSB is delivered at least one uops. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered four uops. Set Cmask = 4.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts cycles MITE is delivered at least one uops. Set Cmask = 1.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops delivered to IDQ from any path.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Misses. Includes UC accesses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction cache, streaming buffer and victim cache misses",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where a code-fetch stalled due to L1 instruction-cache miss or an iTLB miss.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE.IFETCH_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code-fetch stalled due to L1 instruction-cache miss or an iTLB miss",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Count issue pipeline slots where no uop was delivered from the front end to the back end when there is no back-end stall.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of DSB to MITE switches.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles DSB to MITE switches caused delay.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DSB Fill encountered > 3 DSB lines.",
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DSB_FILL.EXCEED_DSB_LINES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Decode Stream Buffer (DSB) fill encounter more than 3 Decode Stream Buffer (DSB) lines",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/memory.json b/tools/perf/pmu-events/arch/x86/ivytown/memory.json
new file mode 100644
index 000000000000..437d98f3e344
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/memory.json
@@ -0,0 +1,503 @@
+[
+ {
+ "PublicDescription": "Speculative cache-line split load uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative cache-line split Store-address uops dispatched to L1D.",
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "Counter": "3",
+ "UMask": "0x2",
+ "EventName": "MEM_TRANS_RETIRED.PRECISE_STORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Sample stores and collect precise store operation via PEBS record. PMC3 only.",
+ "PRECISE_STORE": "1",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 4.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 8.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 16.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 32.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads with latency value being above 32",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 64.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 128.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 256.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Loads with latency value being above 512.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc00244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f800244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hits the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc203f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6004003f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f8203f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc003f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67fc00001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc20002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the LLC and the data is found in M state in remote cache and forwarded from there.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67fc00010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/other.json b/tools/perf/pmu-events/arch/x86/ivytown/other.json
new file mode 100644
index 000000000000..9c2dd0511a32
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/other.json
@@ -0,0 +1,44 @@
+[
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unhalted core cycles when the thread is not in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.",
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/pipeline.json b/tools/perf/pmu-events/arch/x86/ivytown/pipeline.json
new file mode 100644
index 000000000000..2145c28193f7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/pipeline.json
@@ -0,0 +1,1307 @@
+[
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "PublicDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "False dependencies in MOB due to partial compare on address.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc.)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EdgeDetect": "1",
+ "EventName": "INT_MISC.RECOVERY_STALLS_COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of occurences waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc.)",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments each cycle the # of Uops issued by the RAT to RS. Set Cmask = 1, Inv = 1, Any= 1to count stalled cycles of this core.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of flags-merge uops allocated. Such uops adds delay.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_ISSUED.FLAGS_MERGE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of flags-merge uops being allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of slow LEA or similar uops allocated. Such uop has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of multiply packed/scalar single precision uops allocated.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_ISSUED.SINGLE_MUL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Multiply packed/scalar single precision uops allocated",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles that the divider is active, includes INT and FP. Set 'edge =1, cmask=1' to count the number of divides.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divider is busy executing divide operations",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Divide operations executed.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EdgeDetect": "1",
+ "EventName": "ARITH.FPU_DIV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Divide operations executed",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments at the frequency of XCLK (100 MHz) when not halted.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MOVE_ELIMINATION.INT_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MOVE_ELIMINATION.SIMD_NOT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were not eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MOVE_ELIMINATION.INT_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of integer Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x58",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MOVE_ELIMINATION.SIMD_ELIMINATED",
+ "SampleAfterValue": "1000003",
+ "BriefDescription": "Number of SIMD Move Elimination candidate uops that were eliminated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles the RS is empty for the thread.",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Stall cycles due to IQ is full.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stall cycles because IQ is full",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not taken macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired indirect calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired macro-conditional branches.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired direct near calls.",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts all near executed branches (not necessarily retired).",
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when uops are dispatched to port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 2.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles which a Uop is dispatched on port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched to port 2, loads and stores per core (speculative and retired).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles per core when load or STA uops are dispatched to port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles Allocation is stalled due to Resource Related reason.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles stalled due to no store buffers available (not including draining form sync).",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L2 miss loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L2 cache miss loads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with pending L1 cache miss loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending L1 cache miss loads.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "PublicDescription": "Cycles with pending memory loads. Set AnyThread to count per core.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with pending memory loads.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Total execution stalls.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_EXECUTE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of loads missed L2.",
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L2 cache misses.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_LDM_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to memory subsystem.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Execution stalls due to L1 data cache miss loads. Set Cmask=0CH.",
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls due to L1 data cache misses",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts total number of uops to be executed per-thread each cycle. Set Cmask = 1, INV =1 to count stall cycles.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts total number of uops to be executed per-core each cycle.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of instructions at retirement.",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution.",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OTHER_ASSISTS.ANY_WB_ASSIST",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times any microcode assist is invoked by HW upon uop writeback.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of micro-ops retired, Use cmask=1 and invert to count active cycles or stalled cycles.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of retirement slots used each cycle.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of self-modifying-code machine clears detected.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of executed AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of conditional branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Direct and indirect near call instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Branch instructions at retirement.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Counts the number of near return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of near taken branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of far branches retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Mispredicted conditional branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Mispredicted branch instructions at retirement.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Mispredicted taken branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "number of near branch instructions retired that were mispredicted and taken. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Count cases of saving new LBR records by hardware.",
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of front end re-steers due to BPU misprediction.",
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss load* is outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss load* is outstanding.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted. (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted. (counts at 100 MHz rate)",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted. (counts at 100 MHz rate)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/virtual-memory.json b/tools/perf/pmu-events/arch/x86/ivytown/virtual-memory.json
new file mode 100644
index 000000000000..c8de548b78fa
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/virtual-memory.json
@@ -0,0 +1,198 @@
+[
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "DTLB_LOAD_MISSES.DEMAND_LD_WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "DTLB_LOAD_MISSES.DEMAND_LD_WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load cycles page miss handler (PMH) is busy with this walk.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "DTLB_LOAD_MISSES.LARGE_PAGE_WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Page walk for a large page completed for Demand load.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Miss in all TLB levels causes a page walk of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Miss in all TLB levels causes a page walk that completes of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles PMH is busy with this walk.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts load operations that missed 1st level DTLB but hit the 2nd level.",
+ "EventCode": "0x5F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all ITLB levels that cause page walks.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycle PMH is busy with a walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of cache load STLB hits. No page walk.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Completed page walks in ITLB due to STLB load misses for large pages.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "ITLB_MISSES.LARGE_PAGE_WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Completed page walks in ITLB due to STLB load misses for large pages",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of ITLB flushes, includes 4k/2M/4M pages.",
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Count number of STLB flush attempts.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all TLB levels that cause a page walk of any page size from demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes an page walk of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Misses in all TLB levels that caused page walk completed of any size by demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes of any page size.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycle PMH is busy with a walk due to demand loads.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load cycles page miss handler (PMH) is busy with this walk.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/cache.json b/tools/perf/pmu-events/arch/x86/jaketown/cache.json
new file mode 100644
index 000000000000..f723e8f7bb09
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/cache.json
@@ -0,0 +1,1290 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts line-splitted load uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts line-splitted store uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load uops retired",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of store uops retired.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts retired load uops that hit in the last-level (L3) cache without snoops required.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in LLC without snoops required.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Miss in last-level (L3) cache. Excludes Unknown data-source.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC hit and cross-core snoop missed in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts retired load uops that hit in the last-level cache (L3) and were found in a non-modified state in a neighboring core's private cache (same package). Since the last level cache is inclusive, hits to the L3 may require snooping the private L2 caches of any cores on the same socket that have the line. In this case, a snoop was required, and another L2 had the line in a non-modified state.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC and cross-core snoop hits in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts retired load uops that hit in the last-level cache (L3) and were found in a non-modified state in a neighboring core's private cache (same package). Since the last level cache is inclusive, hits to the L3 may require snooping the private L2 caches of any cores on the same socket that have the line. In this case, a snoop was required, and another L2 had the line in a modified state, so the line had to be invalidated in that L2 cache and transferred to the requesting L2.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in LLC without snoops required.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Data from local DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xD3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_DRAM",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Data from remote DRAM either Snoop not needed or Snoop Miss (RspI)",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts L1D data line replacements. Replacements occur when a new line is brought into the cache, causing eviction of a line loaded earlier. ",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D.ALLOCATED_IN_M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Allocated L1D data cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D.EVICTION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data cache lines in M state evicted due to replacement.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D.ALL_M_REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cache lines in M state evicted out of L1D due to Snoop HitM or dirty line replacement.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles.",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases when offcore requests buffer cannot take more entries for core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_STORE_LOCK_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that miss cache lines.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in E state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_STORE_LOCK_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that access cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_L1D_WB_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Count the number of modified Lines evicted from L1 and missed L2. (Non-rejected WBs from the DCU.).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_S",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in S state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in E state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_L1D_WB_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or LLC HW prefetches that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines brought into the L2 cache. Lines are filled into the L2 cache when there was an L2 miss.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PF_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by L2 prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PF_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by L2 prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "L2_LINES_OUT.DIRTY_ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines filling the L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed LLC.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to LLC.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "L1D_BLOCKS.BANK_CONFLICT_CYCLES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when dispatched loads are cancelled due to L1D bank conflicts with other load ports.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_C6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all writebacks from the core to the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoop returned a clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x803c8000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LRU_HINTS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts L2 hints sent to LLC to keep a line from being evicted out of the core caches",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x23ffc08000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PORTIO_MMIO_UC",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts miscellaneous accesses that include port i/o, MMIO and uncacheable memory accesses",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10400",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.SPLIT_LOCK_UC_LOCK.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts requests where the address of an atomic lock instruction spans a cache line boundary or the lock instruction is executed on uncacheable address",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10800",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts non-temporal stores",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand rfo's",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000105B3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch prefetch RFOs",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000107F7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo references (demand & prefetch)",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/floating-point.json b/tools/perf/pmu-events/arch/x86/jaketown/floating-point.json
new file mode 100644
index 000000000000..982eda48785e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/floating-point.json
@@ -0,0 +1,138 @@
+[
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OTHER_ASSISTS.AVX_STORE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of GSSE memory assist for stores. GSSE microcode assist is being invoked whenever the hardware is unable to properly handle GSSE-256b operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULsand IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar double-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_FP_256.PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of GSSE-256 Computational FP single precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_FP_256.PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of AVX-256 Computational FP double precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/frontend.json b/tools/perf/pmu-events/arch/x86/jaketown/frontend.json
new file mode 100644
index 000000000000..1b7b1dd36c68
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/frontend.json
@@ -0,0 +1,305 @@
+[
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of instruction cache, streaming buffer and victim cache misses. Counting includes unchacheable accesses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction cache, streaming buffer and victim cache misses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the microcode sequencer assisted the front-end in delivering uops. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance. See the Intel? 64 and IA-32 Architectures Optimization Reference Manual for more information.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops not delivered to the back-end per cycle, per thread, when the back-end was not stalled. In the ideal case 4 uops can be delivered each cycle. The event counts the undelivered uops - so if 3 were delivered in one cycle, the counter would be incremented by 1 for that cycle (4 - 3). If the back-end is stalled, the count for this event is not incremented even when uops were not delivered, because the back-end would not have been able to accept them. This event is used in determining the front-end bound category of the top-down pipeline slots characterization.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the cycles attributed to a switch from the Decoded Stream Buffer (DSB), which holds decoded instructions, to the legacy decode pipeline. It excludes cycles when the back-end cannot accept new micro-ops. The penalty for these switches is potentially several cycles of instruction starvation, where no micro-ops are delivered to the back-end.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB_FILL.OTHER_CANCEL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases of cancelling valid DSB fill not because of exceeding way limit.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DSB_FILL.EXCEED_DSB_LINES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Decode Stream Buffer (DSB) fill encounter more than 3 Decode Stream Buffer (DSB) lines.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_GE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when 1 or more uops were delivered to the by the front end.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "DSB_FILL.ALL_CANCEL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases of cancelling valid Decode Stream Buffer (DSB) fill not because of exceeding way limit.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/memory.json b/tools/perf/pmu-events/arch/x86/jaketown/memory.json
new file mode 100644
index 000000000000..27e636428f4f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/memory.json
@@ -0,0 +1,422 @@
+[
+ {
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from memory disambiguation, external snoops, or cross SMT-HW-thread snoop (stores) hitting load buffers. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4 .",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads with latency value being above 32.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "Counter": "3",
+ "UMask": "0x2",
+ "EventName": "MEM_TRANS_RETIRED.PRECISE_STORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Sample stores and collect precise store operation via PEBS record. PMC3 only. (Precise Event - PEBS).",
+ "PRECISE_STORE": "1",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67fc00001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67fc00010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from remote & local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from local dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x67f800010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from remote dram",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x87f820010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data forwarded from remote cache",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x107fc00010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC the data is found in M state in remote cache and forwarded from there",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss in the LLC",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fffc20080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x600400077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DEMAND_MLC_PREF_READS.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all local dram accesses for all demand and L2 prefetches. LLC prefetches are excluded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3FFFC20077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DEMAND_MLC_PREF_READS.LLC_MISS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts all LLC misses for all demand and L2 prefetches. LLC prefetches are excluded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x187FC20077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DEMAND_MLC_PREF_READS.LLC_MISS.REMOTE_HITM_HIT_FORWARD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts all remote cache-to-cache transfers (includes HITM and HIT-Forward) for all demand and L2 prefetches. LLC prefetches are excluded.",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/other.json b/tools/perf/pmu-events/arch/x86/jaketown/other.json
new file mode 100644
index 000000000000..64b195b82c50
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/other.json
@@ -0,0 +1,58 @@
+[
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INSTS_WRITTEN_TO_IQ.INSTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Valid instructions written to IQ per cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "HW_PRE_REQ.DL1_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Hardware Prefetch requests that miss the L1D cache. This accounts for both L1 streamer and IP-based (IPP) HW prefetchers. A request is being counted each time it access the cache & miss it, including if a block is applicable or if hit the Fill Buffer for .",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/pipeline.json b/tools/perf/pmu-events/arch/x86/jaketown/pipeline.json
new file mode 100644
index 000000000000..8a597e45ed84
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/pipeline.json
@@ -0,0 +1,1220 @@
+[
+ {
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_MISP_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_MISP_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stall cycles because IQ is full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "INT_MISC.RAT_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Increments the number of flags-merge uops in flight each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles with at least one slow LEA uop being allocated. A uop is generally considered as slow LEA if it has three sources (for example, two sources and immediate) regardless of whether it is a result of LEA instruction or not. Examples of the slow LEA uop are or uops with base, index, and offset source operands using base and index reqisters, where base is EBR/RBP/R13, using RIP relative or 16-bit addressing modes. See the Intel? 64 and IA-32 Architectures Optimization Reference Manual for more details about slow LEA instructions.",
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least one slow LEA uop being allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "PARTIAL_RAT_STALLS.MUL_SINGLE_UOP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Multiply packed/scalar single precision uops allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the cycles of stall due to lack of load buffers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS2.BOB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Allocator is stalled if BOB is full and new branch needs it.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of Uops issued by the front-end of the pipeilne to the back-end.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event is incremented when self-modifying code (SMC) is detected, which causes a machine clear. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Maskmov false fault - counts number of time ucode passes through Maskmov flow due to instruction's mask being 0 while the flow was completed without raising a fault.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of micro-ops retired.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of retirement slots used each cycle. There are potentially 4 slots that can be used each cycle - meaning, 4 micro-ops or 4 instructions could retire each cycle. This event is used in determining the 'Retiring' category of the Top-Down pipeline slots characterization.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired. (Precise Event - PEBS).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect mispredicted near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS)",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OTHER_ASSISTS.ITLB_MISS_RETIRED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired instructions experiencing ITLB misses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divider is busy executing divide operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of the divide operations executed.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "ARITH.FPU_DIV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Divide operations executed.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched per thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched from any thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_DISPATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was no dispatch for this thread, increment by 1. Note this is connect to Umask 2. No dispatch can be deduced from the UOPS_EXECUTED event.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a miss-pending demand load this thread, increment by 1. Note this is in DCU and connected to Umask 1. Miss Pending demand load should be deduced by OR-ing increment bits of DCACHE_MISS_PEND.PENDING.",
+ "CounterMask": "2",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a MLC-miss pending demand load this thread (i.e. Non-completed valid SQ entry allocated for demand load and waiting for Uncore), increment by 1. Note this is in MLC and connected to Umask 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a miss-pending demand load this thread and no uops dispatched, increment by 1. Note this is in DCU and connected to Umask 1 and 2. Miss Pending demand load should be deduced by OR-ing increment bits of DCACHE_MISS_PEND.PENDING.",
+ "CounterMask": "6",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a MLC-miss pending demand load and no uops dispatched on this thread (i.e. Non-completed valid SQ entry allocated for demand load and waiting for Uncore), increment by 1. Note this is in MLC and connected to Umask 0 and 2.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS.DATA_UNKNOWN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads delayed due to SB blocks, preceding store operations with known addresses but unknown data.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts loads that followed a store to the same address, where the data could not be forwarded inside the pipeline from the store to the load. The most common reason why store forwarding would be blocked is when a load's address range overlaps with a preceeding smaller uncompleted store. See the table of not supported store forwards in the Intel? 64 and IA-32 Architectures Optimization Reference Manual. The penalty for blocked store forwarding is that the load must wait for the store to complete before it can be issued.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "LD_BLOCKS.ALL_BLOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of cases where any load ends up with a valid block-code written to the load buffer (including blocks due to Memory Order Buffer (MOB), Data Cache Unit (DCU), TLB, but load has no DCU miss).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Aliasing occurs when a load is issued after a store and their memory addresses are offset by 4K. This event counts the number of loads that aliased with a preceding store, resulting in an extended address check in the pipeline. The enhanced address check typically has a performance penalty of 5 cycles.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS_PARTIAL.ALL_STA_BLOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that load operations are temporarily blocked because of older stores, with addresses that are not yet known. A load operation may incur more than one block of this type.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "AGU_BYPASS_CANCEL.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts executed load operations with all the following traits: 1. addressing of the format [base + offset], 2. the offset is between 1 and 2047, 3. the address specified in the base register is in one page and the address [base+offset] is in an.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired. (Precise Event - PEBS).",
+ "TakenAlone": "1",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RESOURCE_STALLS2.ALL_PRF_CONTROL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls2 control structures full for physical registers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "RESOURCE_STALLS2.ALL_FL_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with either free list is empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "RESOURCE_STALLS.MEM_RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to memory buffers or Reservation Station (RS) being fully utilized.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "RESOURCE_STALLS.OOO_RSRC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to Rob being full, FCSW, MXCSR and OTHER.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "RESOURCE_STALLS2.OOO_RSRC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls out of order resources full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "RESOURCE_STALLS.LB_SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to load or store buffers all being in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles spent executing performance-sensitive flags-merging uops. For example, shift CL (merge_arith_flags). For more details, See the Intel? 64 and IA-32 Architectures Optimization Reference Manual.",
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Performance sensitive flags-merging uops added by Sandy Bridge u-arch.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EdgeDetect": "1",
+ "EventName": "INT_MISC.RECOVERY_STALLS_COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of occurences waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/virtual-memory.json b/tools/perf/pmu-events/arch/x86/jaketown/virtual-memory.json
new file mode 100644
index 000000000000..a654ab771fce
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/virtual-memory.json
@@ -0,0 +1,149 @@
+[
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event count cycles when Page Miss Handler (PMH) is servicing page walks caused by ITLB misses.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses at all DTLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB load misses.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load operations that miss the first DTLB level but hit the second and do not cause any page walks. The penalty in this case is approximately 7 cycles.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/cache.json b/tools/perf/pmu-events/arch/x86/knightslanding/cache.json
new file mode 100644
index 000000000000..88ba5994b994
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/cache.json
@@ -0,0 +1,2305 @@
+[
+ {
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "L2_REQUESTS_REJECT.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of MEC requests from the L2Q that reference a cache line (cacheable requests) exlcuding SW prefetches filling only to L2 cache and L1 evictions (automatically exlcudes L2HWP, UC, WC) that were rejected - Multiple repeated rejects should be counted multiple times"
+ },
+ {
+ "EventCode": "0x31",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "CORE_REJECT_L2Q.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of MEC requests that were not accepted into the L2Q because of any L2 queue reject condition. There is no concept of at-ret here. It might include requests due to instructions in the speculative path."
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "L2_REQUESTS.REFERENCE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of L2 cache references."
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "L2_REQUESTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of L2 cache misses"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles the fetch stalls because of an icache miss. This is a cumulative count of cycles the NIP stalled for all icache misses. ",
+ "EventCode": "0x86",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles the fetch stalls because of an icache miss. This is a cummulative count of core cycles the fetch stalled for all icache misses. "
+ },
+ {
+ "PublicDescription": "This event counts the number of load micro-ops retired that miss in L1 Data cache. Note that prefetch misses will not be counted. ",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MEM_UOPS_RETIRED.L1_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load micro-ops retired that miss in L1 D cache"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MEM_UOPS_RETIRED.L2_HIT_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load micro-ops retired that hit in the L2",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "MEM_UOPS_RETIRED.L2_MISS_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the number of load micro-ops retired that miss in the L2",
+ "Data_LA": "1"
+ },
+ {
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "MEM_UOPS_RETIRED.UTLB_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load micro-ops retired that caused micro TLB miss"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "MEM_UOPS_RETIRED.HITM",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the loads retired that get the data from the other core in the same tile in M state",
+ "Data_LA": "1"
+ },
+ {
+ "PublicDescription": "This event counts the number of load micro-ops retired.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all the load micro-ops retired"
+ },
+ {
+ "PublicDescription": "This event counts the number of store micro-ops retired.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all the store micro-ops retired"
+ },
+ {
+ "EventCode": "0xB7",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts the matrix events specified by MSR_OFFCORE_RESPx"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x40000032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10004032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x08004032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10000832f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x08000832f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00000132f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000403091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800403091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000083091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800083091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000013091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000408000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800408000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000088000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800088000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000018000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000014800 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts all streaming stores (WC and should be programmed on PMC1) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000014000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial streaming stores (WC and should be programmed on PMC1) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000402000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800402000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000082000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800082000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000012000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000401000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800401000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000081000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800081000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000011000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010800 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Full streaming stores (WC and should be programmed on PMC1) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.ANY_RESPONSE",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000020020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that provides no supplier details",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that are outstanding, per weighted cycle, from the time of the request to when any response is received. The oustanding response should be programmed only on PMC0. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000400001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_FAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800400001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_FAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from a snoop request hit with data forwarded from its Far(not in the same quadrant as the request)-other tile's L2 in E/F state. Valid only for SNC4 cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000080001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_NEAR_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in M state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0800080001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_NEAR_TILE_E_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from a snoop request hit with data forwarded from its Near-other tile's L2 in E/F state. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for any response",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00020032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0002000070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_THIS_TILE_M",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses which hit its own tile's L2 with data in M state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00040032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0004000070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_THIS_TILE_E",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses which hit its own tile's L2 with data in E state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0008000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00080032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_THIS_TILE_S",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses which hit its own tile's L2 with data in S state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00100032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0010000070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_THIS_TILE_F",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses which hit its own tile's L2 with data in F state ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800181000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800182000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800188000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800183091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x18001832f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800180070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_NEAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for reponses from snoop request hit with data forwarded from its Near-other tile L2 in E/F/M state",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800401000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800402000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800408000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800403091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x18004032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1800400070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.L2_HIT_FAR_TILE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for reponses from snoop request hit with data forwarded from it Far(not in the same quadrant as the request)-other tile L2 in E/F/M state. Valid only in SNC4 Cluster mode.",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/frontend.json b/tools/perf/pmu-events/arch/x86/knightslanding/frontend.json
new file mode 100644
index 000000000000..6d38636689a4
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/frontend.json
@@ -0,0 +1,34 @@
+[
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "ICACHE.ACCESSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all instruction fetches, including uncacheable fetches."
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all instruction fetches that hit the instruction cache."
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all instruction fetches that miss the instruction cache or produce memory requests. An instruction fetch miss is counted only once and not once for every cycle it is outstanding."
+ },
+ {
+ "EventCode": "0xE7",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MS_DECODED.MS_ENTRY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times the MSROM starts a flow of uops."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/memory.json b/tools/perf/pmu-events/arch/x86/knightslanding/memory.json
new file mode 100644
index 000000000000..700652566200
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/memory.json
@@ -0,0 +1,1110 @@
+[
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times the machine clears due to memory ordering hazards"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x01004032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00802032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x01010032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x00808032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100403091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080203091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101003091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080803091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100408000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080208000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101008000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080808000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100402000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080202000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101002000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080802000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100401000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080201000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101001000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080801000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.MCDRAM_FAR",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.MCDRAM_NEAR",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.DDR_FAR",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.DDR_NEAR",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2000020080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from any NON_DRAM system address. This includes MMIO transactions",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2000020020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from any NON_DRAM system address. This includes MMIO transactions",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0100400001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.MCDRAM_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for data responses from MCDRAM Far or Other tile L2 hit far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080200001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.MCDRAM_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for data responses from MCDRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0101000001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.DDR_FAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for data responses from DRAM Far. ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080800001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.DDR_NEAR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for data responses from DRAM Local.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600100 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.MCDRAM",
+ "MSRIndex": "0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial writes (UC or WT or WP and should be programmed on PMC1) that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180601000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180608000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180603091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x01806032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0180600070 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_PF_L2.MCDRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Prefetch requests that accounts for responses from MCDRAM (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800001 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand cacheable data and L1 prefetch data reads that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800002 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data writes that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800004 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand code reads and prefetch code reads that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800020 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800040 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L2 code HW prefetches that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800080 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Partial reads (UC or WC and is valid only for Outstanding response type). that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800200 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.UC_CODE_READS.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts UC code reads (valid only for Outstanding response type) that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800400 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Bus locks and split lock requests that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181801000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_SOFTWARE.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Software Prefetches that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181802000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts L1 data HW prefetches that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181808000 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181803091 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data and L1 prefetch data read requests that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800022 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand cacheable data write requests that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0181800044 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts Demand code reads and prefetch code read requests that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x01818032f7 ",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_READ.DDR",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any Read request that accounts for responses from DDR (local and far)",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json b/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json
new file mode 100644
index 000000000000..bb5494cfb5ae
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json
@@ -0,0 +1,435 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x7e",
+ "EventName": "BR_INST_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfe",
+ "EventName": "BR_INST_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps and predicted taken."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xf9",
+ "EventName": "BR_INST_RETIRED.CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfd",
+ "EventName": "BR_INST_RETIRED.REL_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near relative CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfb",
+ "EventName": "BR_INST_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near indirect CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xf7",
+ "EventName": "BR_INST_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near RET branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xeb",
+ "EventName": "BR_INST_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired that were near indirect CALL or near indirect JMP."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xbf",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of far branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0x7e",
+ "EventName": "BR_MISP_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xfe",
+ "EventName": "BR_MISP_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps and predicted taken."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xfb",
+ "EventName": "BR_MISP_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near indirect CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xf7",
+ "EventName": "BR_MISP_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near RET branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xeb",
+ "EventName": "BR_MISP_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired that were near indirect CALL or near indirect JMP."
+ },
+ {
+ "PublicDescription": "This event counts the number of micro-ops retired that were supplied from MSROM.",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.MS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of micro-ops retired that are from the complex flows issued by the micro-sequencer (MS)."
+ },
+ {
+ "PublicDescription": "This event counts the number of micro-ops (uops) retired. The processor decodes complex macro instructions into a sequence of simpler uops. Most instructions are composed of one or two uops. Some instructions are decoded into longer sequences such as repeat instructions, floating point transcendental instructions, and assists. ",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of micro-ops retired"
+ },
+ {
+ "PublicDescription": "This event counts the number of scalar SSE, AVX, AVX2, AVX-512 micro-ops retired (floating point, integer and store) except for loads (memory-to-register mov-type micro ops), division, sqrt.",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "UOPS_RETIRED.SCALAR_SIMD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of scalar SSE, AVX, AVX2, AVX-512 micro-ops retired. More specifically, it counts scalar SSE, AVX, AVX2, AVX-512 micro-ops except for loads (memory-to-register mov-type micro ops), division, sqrt."
+ },
+ {
+ "PublicDescription": "This event counts the number of packed vector SSE, AVX, AVX2, and AVX-512 micro-ops retired (floating point, integer and store) except for loads (memory-to-register mov-type micro-ops), packed byte and word multiplies.",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "UOPS_RETIRED.PACKED_SIMD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of vector SSE, AVX, AVX2, AVX-512 micro-ops retired. More specifically, it counts packed SSE, AVX, AVX2, AVX-512 micro-ops (both floating point and integer) except for loads (memory-to-register mov-type micro-ops), packed byte and word multiplies."
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times that the machine clears due to program modifying data within 1K of a recently fetched code page"
+ },
+ {
+ "PublicDescription": "This event counts the number of times that the pipeline stalled due to FP operations needing assists.",
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.FP_ASSIST",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of floating operations retired that required microcode assists"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "MACHINE_CLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all nukes"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "NO_ALLOC_CYCLES.ROB_FULL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles when no micro-ops are allocated and the ROB is full"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles when no uops are allocated and the alloc pipe is stalled waiting for a mispredicted branch to retire.",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "NO_ALLOC_CYCLES.MISPREDICTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles when no micro-ops are allocated and the alloc pipe is stalled waiting for a mispredicted branch to retire."
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "NO_ALLOC_CYCLES.RAT_STALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles when no micro-ops are allocated and a RATstall (caused by reservation station full) is asserted. "
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles when no uops are allocated, the instruction queue is empty and the alloc pipe is stalled waiting for instructions to be fetched.",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x90",
+ "EventName": "NO_ALLOC_CYCLES.NOT_DELIVERED",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles when no micro-ops are allocated, the IQ is empty, and no other condition is blocking allocation."
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x7f",
+ "EventName": "NO_ALLOC_CYCLES.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of core cycles when no micro-ops are allocated for any reason."
+ },
+ {
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "RS_FULL_STALL.MEC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of core cycles when allocation pipeline is stalled and is waiting for a free MEC reservation station entry."
+ },
+ {
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x1f",
+ "EventName": "RS_FULL_STALL.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of core cycles the Alloc pipeline is stalled when any one of the reservation stations is full. "
+ },
+ {
+ "EventCode": "0xC0",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the total number of instructions retired"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the divider is busy. More specifically cycles when the divide unit is unable to accept a new divide uop because it is busy processing a previously dispatched uop. The cycles will be counted irrespective of whether or not another divide uop is waiting to enter the divide unit (from the RS). This event counts integer divides, x87 divides, divss, divsd, sqrtss, sqrtsd event and does not count vector divides.",
+ "EventCode": "0xCD",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CYCLES_DIV_BUSY.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles the number of core cycles when divider is busy. Does not imply a stall waiting for the divider. "
+ },
+ {
+ "PublicDescription": "This event counts the number of instructions that retire. For instructions that consist of multiple micro-ops, this event counts exactly once, as the last micro-op of the instruction retires. The event continues counting while instructions retire, including during interrupt service routines caused by hardware interrupts, faults or traps.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of instructions retired"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted core clock cycles"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of unhalted reference clock cycles"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter\r\n",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of unhalted reference clock cycles"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BACLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times the front end resteers for any branch as a result of another branch handling mechanism in the front end."
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "BACLEARS.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times the front end resteers for RET branches as a result of another branch handling mechanism in the front end."
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "BACLEARS.COND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times the front end resteers for conditional branches as a result of another branch handling mechanism in the front end."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "RECYCLEQ.LD_BLOCK_ST_FORWARD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of occurences a retired load gets blocked because its address partially overlaps with a store ",
+ "Data_LA": "1"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "RECYCLEQ.LD_BLOCK_STD_NOTREADY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of occurences a retired load gets blocked because its address overlaps with a store whose data is not ready"
+ },
+ {
+ "PublicDescription": "This event counts the number of retired store that experienced a cache line boundary split(Precise Event). Note that each spilt should be counted only once.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "RECYCLEQ.ST_SPLITS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of occurences a retired store that is a cache line split. Each split should be counted only once."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "RECYCLEQ.LD_SPLITS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of occurences a retired load that is a cache line split. Each split should be counted only once.",
+ "Data_LA": "1"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "RECYCLEQ.LOCK",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all the retired locked loads. It does not include stores because we would double count if we count stores"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "RECYCLEQ.STA_FULL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the store micro-ops retired that were pushed in the rehad queue because the store address buffer is full"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "RECYCLEQ.ANY_LD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts any retired load that was pushed into the recycle queue for any reason."
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "RECYCLEQ.ANY_ST",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts any retired store that was pushed into the recycle queue for any reason."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xf9",
+ "EventName": "BR_MISP_RETIRED.CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xfd",
+ "EventName": "BR_MISP_RETIRED.REL_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near relative CALL branch instructions retired."
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xbf",
+ "EventName": "BR_MISP_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted far branch instructions retired."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json b/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json
new file mode 100644
index 000000000000..f31594507f8c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json
@@ -0,0 +1,65 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of load micro-ops retired that cause a DTLB miss",
+ "Data_LA": "1"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total D-side page walks that are completed or started. The page walks started in the speculative path will also be counted",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of core cycles for all the D-side page walks. The cycles for page walks started in speculative path will also be included."
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total I-side page walks that are completed.",
+ "EdgeDetect": "1"
+ },
+ {
+ "PublicDescription": "This event counts every cycle when an I-side (walks due to an instruction fetch) page walk is in progress. ",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of core cycles for all the I-side page walks. The cycles for page walks started in speculative path will also be included."
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total page walks that are completed (I-side and D-side)",
+ "EdgeDetect": "1"
+ },
+ {
+ "PublicDescription": "This event counts every cycle when a data (D) page walk or instruction (I) page walk is in progress.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the total number of core cycles for all the page walks. The cycles for page walks started in speculative path will also be included."
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
new file mode 100644
index 000000000000..12181bb1da2a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -0,0 +1,35 @@
+Family-model,Version,Filename,EventType
+GenuineIntel-6-56,v5,broadwellde,core
+GenuineIntel-6-3D,v17,broadwell,core
+GenuineIntel-6-47,v17,broadwell,core
+GenuineIntel-6-4F,v10,broadwellx,core
+GenuineIntel-6-1C,v4,bonnell,core
+GenuineIntel-6-26,v4,bonnell,core
+GenuineIntel-6-27,v4,bonnell,core
+GenuineIntel-6-36,v4,bonnell,core
+GenuineIntel-6-35,v4,bonnell,core
+GenuineIntel-6-5C,v8,goldmont,core
+GenuineIntel-6-3C,v24,haswell,core
+GenuineIntel-6-45,v24,haswell,core
+GenuineIntel-6-46,v24,haswell,core
+GenuineIntel-6-3F,v17,haswellx,core
+GenuineIntel-6-3A,v18,ivybridge,core
+GenuineIntel-6-3E,v19,ivytown,core
+GenuineIntel-6-2D,v20,jaketown,core
+GenuineIntel-6-57,v9,knightslanding,core
+GenuineIntel-6-1E,v2,nehalemep,core
+GenuineIntel-6-1F,v2,nehalemep,core
+GenuineIntel-6-1A,v2,nehalemep,core
+GenuineIntel-6-2E,v2,nehalemex,core
+GenuineIntel-6-4E,v24,skylake,core
+GenuineIntel-6-5E,v24,skylake,core
+GenuineIntel-6-8E,v24,skylake,core
+GenuineIntel-6-9E,v24,skylake,core
+GenuineIntel-6-37,v13,silvermont,core
+GenuineIntel-6-4D,v13,silvermont,core
+GenuineIntel-6-4C,v13,silvermont,core
+GenuineIntel-6-2A,v15,sandybridge,core
+GenuineIntel-6-2C,v2,westmereep-dp,core
+GenuineIntel-6-2C,v2,westmereep-dp,core
+GenuineIntel-6-25,v2,westmereep-sp,core
+GenuineIntel-6-2F,v2,westmereex,core
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/cache.json b/tools/perf/pmu-events/arch/x86/nehalemep/cache.json
new file mode 100644
index 000000000000..a11029efda2f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/cache.json
@@ -0,0 +1,3229 @@
+[
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CACHE_LOCK_CYCLES.L1D",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D locked"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CACHE_LOCK_CYCLES.L1D_L2",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D and L2 locked"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D.M_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines replaced in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D.M_REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines allocated in the M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D.M_SNOOP_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D snoop eviction of cache lines in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D.REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache lines allocated"
+ },
+ {
+ "EventCode": "0x43",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_ALL_REF.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All references to the L1 data cache"
+ },
+ {
+ "EventCode": "0x43",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_ALL_REF.CACHEABLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cacheable reads and writes"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_LD.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in E state"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LD.I_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in I state (misses)"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_LD.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in M state"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0xf",
+ "EventName": "L1D_CACHE_LD.MESI",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache reads"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_LD.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in S state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_LOCK.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in E state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LOCK.HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load lock hits"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_LOCK.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in M state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_LOCK.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in S state"
+ },
+ {
+ "EventCode": "0x53",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x52",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_PREFETCH_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D prefetch load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_ST.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in E state"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_ST.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in M state"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_ST.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in S state"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_PREFETCH.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch misses"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_PREFETCH.REQUESTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_PREFETCH.TRIGGERS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests triggered"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D_WB_L2.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in E state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_WB_L2.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in I state (misses)"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D_WB_L2.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in M state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L1D_WB_L2.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L1 writebacks to L2"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_WB_L2.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_DATA_RQSTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_DATA_RQSTS.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_DATA_RQSTS.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_DATA_RQSTS.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_DATA_RQSTS.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_DATA_RQSTS.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data prefetches"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the S state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines alloacated"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the E state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the S state"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_LINES_OUT.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PREFETCH_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PREFETCH_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.IFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.IFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.IFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.LD_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_RQSTS.LD_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.LOADS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xaa",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PREFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PREFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.PREFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 prefetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.RFOS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO requests"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANSACTIONS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANSACTIONS.FILL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 fill transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANSACTIONS.IFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANSACTIONS.L1D_WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D writeback to L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANSACTIONS.LOAD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 Load transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANSACTIONS.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANSACTIONS.RFO",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANSACTIONS.WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 writeback to LLC transactions"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_WRITE.LOCK.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in E state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe0",
+ "EventName": "L2_WRITE.LOCK.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_WRITE.LOCK.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_WRITE.LOCK.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_WRITE.LOCK.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_WRITE.LOCK.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in S state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "L2_WRITE.RFO.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_WRITE.RFO.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_WRITE.RFO.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_WRITE.RFO.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_WRITE.RFO.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in S state"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Longest latency cache miss"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Longest latency cache reference"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_INST_RETIRED.LOADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a load (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_INST_RETIRED.STORES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a store (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.HIT_LFB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss L1D and hit an previously allocated LFB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1D_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired loads that hit the L1 data cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.LLC_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.LLC_UNSHARED_HIT",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit valid versions in the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_UNCORE_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Load instructions retired with a data source of local DRAM or locally homed remote hitm (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_UNCORE_RETIRED.OTHER_CORE_L2_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Load instructions retired that HIT modified data in sibling core (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_CACHE_LOCAL_HOME_HIT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Load instructions retired remote cache HIT data source (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_DRAM",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Load instructions retired remote DRAM and remote home-remote cache HITM (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_UNCORE_RETIRED.UNCACHEABLE",
+ "SampleAfterValue": "4000",
+ "BriefDescription": "Load instructions retired IO (Precise Event)"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OFFCORE_REQUESTS.L1D_WRITEBACK",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore L1 data cache writebacks"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_SQ_FULL",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests blocked due to Super Queue full"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue lock splits across a cache line"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "STORE_BLOCKS.AT_RET",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads delayed with at-Retirement block code"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "STORE_BLOCKS.L1D_BLOCK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cacheable loads delayed with L1D block code"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x0",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Memory instructions retired above 0 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x400",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100",
+ "BriefDescription": "Memory instructions retired above 1024 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1000",
+ "BriefDescription": "Memory instructions retired above 128 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Memory instructions retired above 16 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5",
+ "BriefDescription": "Memory instructions retired above 16384 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x800",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50",
+ "BriefDescription": "Memory instructions retired above 2048 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "500",
+ "BriefDescription": "Memory instructions retired above 256 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5000",
+ "BriefDescription": "Memory instructions retired above 32 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "3",
+ "BriefDescription": "Memory instructions retired above 32768 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50000",
+ "BriefDescription": "Memory instructions retired above 4 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x1000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20",
+ "BriefDescription": "Memory instructions retired above 4096 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "200",
+ "BriefDescription": "Memory instructions retired above 512 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Memory instructions retired above 64 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Memory instructions retired above 8 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x2000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10",
+ "BriefDescription": "Memory instructions retired above 8192 clocks (Precise Event)"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x111",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x211",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x411",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x144",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x244",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x444",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFFFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x80FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x47FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x18FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x38FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x122",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x222",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x422",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore writebacks",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x108",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x408",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code or data read requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x177",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x277",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x477",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any cache_dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any location",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x133",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x233",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x433",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HIT in a remote cache ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x103",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x203",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x403",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x101",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x201",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x401",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x104",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x204",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x404",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x102",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x202",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x402",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore other requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x180",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x280",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x480",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x130",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x230",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x430",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x110",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x210",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x410",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x140",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x240",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x440",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x120",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x220",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x420",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x170",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x270",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x470",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HITM in a remote cache",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json b/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json
new file mode 100644
index 000000000000..7d2f71a9dee3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json
@@ -0,0 +1,229 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.ALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.INPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.OUTPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists for invalid output value (Precise Event)"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_COMP_OPS_EXE.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MMX Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP double precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE and SSE2 FP Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_PACKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP packed Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_SCALAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP scalar Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP single precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_COMP_OPS_EXE.SSE2_INTEGER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE2 integer Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Computational floating-point operations executed"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_MMX_TRANS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Floating Point to and from MMX transitions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_MMX_TRANS.TO_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from MMX to Floating Point instructions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_MMX_TRANS.TO_MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from Floating Point to MMX instructions"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_128.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer pack operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_128.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer arithmetic operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_128.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer logical operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_128.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer multiply operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_128.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shift operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_128.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shuffle/move operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_128.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer unpack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_64.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit pack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_64.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit arithmetic operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_64.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit logical operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_64.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit packed multiply operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_64.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shift operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_64.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shuffle/move operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_64.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit unpack operations"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/frontend.json b/tools/perf/pmu-events/arch/x86/nehalemep/frontend.json
new file mode 100644
index 000000000000..e5e21e03444d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions decoded"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.FUSIONS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused instructions decoded"
+ },
+ {
+ "EventCode": "0x19",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TWO_UOP_INSTS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Two Uop instructions decoded"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/memory.json b/tools/perf/pmu-events/arch/x86/nehalemep/memory.json
new file mode 100644
index 000000000000..f914a4525b65
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/memory.json
@@ -0,0 +1,739 @@
+[
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x60FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x40FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x20FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any LLC miss",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the local DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/other.json b/tools/perf/pmu-events/arch/x86/nehalemep/other.json
new file mode 100644
index 000000000000..af0860622445
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/other.json
@@ -0,0 +1,210 @@
+[
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_CLEARS.EARLY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Early Branch Prediciton Unit clears"
+ },
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BPU_CLEARS.LATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Late Branch Prediction Unit clears"
+ },
+ {
+ "EventCode": "0xE5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_MISSED_CALL_RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch prediction unit missed call or return"
+ },
+ {
+ "EventCode": "0xD5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ES_REG_RENAMES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ES segment renames"
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IO_TRANSACTIONS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "I/O transactions"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1I.CYCLES_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch stall cycles"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1I.HITS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch hits"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1I.MISSES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch misses"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L1I.READS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I Instruction fetches"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LARGE_ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Large ITLB hit"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "LOAD_DISPATCH.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All loads dispatched"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LOAD_DISPATCH.MOB",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_DISPATCH.RS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched that bypass the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_DISPATCH.RS_DELAYED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from stage 305"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PARTIAL_ADDRESS_ALIAS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "False dependencies due to partial address aliasing"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RAT_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All RAT stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RAT_STALLS.FLAGS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Flag stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RAT_STALLS.REGISTERS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Partial register stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RAT_STALLS.ROB_READ_PORT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB read port stalls cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RAT_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Scoreboard stall cycles"
+ },
+ {
+ "EventCode": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "SB_DRAIN.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All Store buffer stall cycles"
+ },
+ {
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SEG_RENAME_STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Segment rename stall cycles"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOP_RESPONSE.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HIT to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOP_RESPONSE.HITE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITE to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOP_RESPONSE.HITM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITM to snoop"
+ },
+ {
+ "EventCode": "0xF6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SQ_FULL_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue full stall cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/pipeline.json b/tools/perf/pmu-events/arch/x86/nehalemep/pipeline.json
new file mode 100644
index 000000000000..41006ddcd893
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/pipeline.json
@@ -0,0 +1,881 @@
+[
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy"
+ },
+ {
+ "EventCode": "0x14",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIV",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide Operations executed",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.MUL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BACLEAR.BAD_TARGET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted with bad target address"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR.CLEAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted, regardless of cause "
+ },
+ {
+ "EventCode": "0xA7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR_FORCE_IQ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction queue forced BACLEAR"
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_INST_EXEC.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_EXEC.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Conditional branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_EXEC.DIRECT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Unconditional branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Unconditional call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_INST_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_INST_EXEC.NON_CALLS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect return branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_EXEC.TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired conditional branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Retired near call instructions (Precise Event)"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_MISP_EXEC.ANY",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_EXEC.COND",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_EXEC.DIRECT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted unconditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_MISP_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_MISP_EXEC.NON_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted return branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_MISP_EXEC.TAKEN",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted near retired calls (Precise Event)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_P",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total CPU cycles",
+ "CounterMask": "2"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "ILD_STALL.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Any Instruction Length Decoder stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction Queue full stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Length Change Prefix stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ILD_STALL.MRU",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stall cycles due to BPU MRU bypass"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ILD_STALL.REGEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Regen stall cycles"
+ },
+ {
+ "EventCode": "0x18",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_DECODED.DEC0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions that must be decoded by decoder 0"
+ },
+ {
+ "EventCode": "0x1E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles instructions are written to the instruction queue"
+ },
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions written to instruction queue."
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (fixed counter)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (Programmable counter and Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "INST_RETIRED.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired MMX instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired floating-point operations (Precise Event)"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load operations conflicting with software prefetches"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xA8",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.INACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD_OVERFLOW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loops that can't stream from the instruction queue"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Cycles machine clear asserted"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEM_ORDER",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Execution pipeline restart due to Memory ordering conflicts"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RESOURCE_STALLS.FPCW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FPU control word write stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LOAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Load buffer stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS.MXCSR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MXCSR rename stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RESOURCE_STALLS.OTHER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Other Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reservation Station full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.STORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Store buffer stall cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SSEX_UOPS_RETIRED.VECTOR_INTEGER",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Vector Integer Uops retired (Precise Event)"
+ },
+ {
+ "EventCode": "0xDB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOP_UNFUSION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uop unfusions due to FP exceptions"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DECODED.ESP_FOLDING",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer instructions decoded"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DECODED.ESP_SYNC",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer sync operations"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DECODED.MS_CYCLES_ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops decoded by Microcode Sequencer",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xD1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DECODED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops are decoded",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on any port (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.PORT0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 0"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 0, 1 or 5"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0, 1 or 5",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.PORT1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT2_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 2 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT234_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 2, 3 or 4"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT3_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 3 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT4_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 4 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED.PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 5"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued on any thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CYCLES_ALL_THREADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops were issued on either thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Fused Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are being retired",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retirement slots used (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are not retiring (Precise Event)",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles using precise uop retired event (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/virtual-memory.json b/tools/perf/pmu-events/arch/x86/nehalemep/virtual-memory.json
new file mode 100644
index 000000000000..0596094e0ee9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemep/virtual-memory.json
@@ -0,0 +1,109 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load misses"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss caused by low part of address"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB second level hit"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walks complete"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB first level misses but second level hit"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss page walks"
+ },
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_FLUSH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB flushes"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISS_RETIRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired instructions that missed the ITLB (Precise Event)"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss page walks"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_STORE_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired stores that miss the DTLB (Precise Event)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/cache.json b/tools/perf/pmu-events/arch/x86/nehalemex/cache.json
new file mode 100644
index 000000000000..21a0f8fd057e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/cache.json
@@ -0,0 +1,3184 @@
+[
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CACHE_LOCK_CYCLES.L1D",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D locked"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CACHE_LOCK_CYCLES.L1D_L2",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D and L2 locked"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D.M_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines replaced in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D.M_REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines allocated in the M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D.M_SNOOP_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D snoop eviction of cache lines in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D.REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache lines allocated"
+ },
+ {
+ "EventCode": "0x43",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_ALL_REF.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All references to the L1 data cache"
+ },
+ {
+ "EventCode": "0x43",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_ALL_REF.CACHEABLE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cacheable reads and writes"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_LD.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in E state"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LD.I_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in I state (misses)"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_LD.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in M state"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0xf",
+ "EventName": "L1D_CACHE_LD.MESI",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache reads"
+ },
+ {
+ "EventCode": "0x40",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_LD.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache read in S state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_LOCK.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in E state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LOCK.HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load lock hits"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_LOCK.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in M state"
+ },
+ {
+ "EventCode": "0x42",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_LOCK.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache load locks in S state"
+ },
+ {
+ "EventCode": "0x53",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x52",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_PREFETCH_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D prefetch load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_CACHE_ST.E_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in E state"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D_CACHE_ST.M_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in M state"
+ },
+ {
+ "EventCode": "0x41",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_CACHE_ST.S_STATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache stores in S state"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_PREFETCH.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch misses"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_PREFETCH.REQUESTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_PREFETCH.TRIGGERS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests triggered"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D_WB_L2.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in E state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_WB_L2.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in I state (misses)"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D_WB_L2.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in M state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L1D_WB_L2.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L1 writebacks to L2"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_WB_L2.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_DATA_RQSTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_DATA_RQSTS.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_DATA_RQSTS.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_DATA_RQSTS.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_DATA_RQSTS.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_DATA_RQSTS.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data prefetches"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the S state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines alloacated"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the E state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the S state"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_LINES_OUT.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PREFETCH_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PREFETCH_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.IFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.IFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.IFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.LD_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_RQSTS.LD_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.LOADS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xaa",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PREFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PREFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.PREFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 prefetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.RFOS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO requests"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANSACTIONS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANSACTIONS.FILL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 fill transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANSACTIONS.IFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANSACTIONS.L1D_WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D writeback to L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANSACTIONS.LOAD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 Load transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANSACTIONS.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANSACTIONS.RFO",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANSACTIONS.WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 writeback to LLC transactions"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_WRITE.LOCK.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in E state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe0",
+ "EventName": "L2_WRITE.LOCK.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_WRITE.LOCK.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_WRITE.LOCK.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_WRITE.LOCK.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_WRITE.LOCK.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in S state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "L2_WRITE.RFO.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_WRITE.RFO.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_WRITE.RFO.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_WRITE.RFO.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_WRITE.RFO.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in S state"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Longest latency cache miss"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Longest latency cache reference"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_INST_RETIRED.LOADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a load (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_INST_RETIRED.STORES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a store (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.HIT_LFB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss L1D and hit an previously allocated LFB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1D_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired loads that hit the L1 data cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.LLC_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.LLC_UNSHARED_HIT",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit valid versions in the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event)"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OFFCORE_REQUESTS.L1D_WRITEBACK",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore L1 data cache writebacks"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_SQ_FULL",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests blocked due to Super Queue full"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue lock splits across a cache line"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "STORE_BLOCKS.AT_RET",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads delayed with at-Retirement block code"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "STORE_BLOCKS.L1D_BLOCK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cacheable loads delayed with L1D block code"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x0",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Memory instructions retired above 0 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x400",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100",
+ "BriefDescription": "Memory instructions retired above 1024 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1000",
+ "BriefDescription": "Memory instructions retired above 128 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Memory instructions retired above 16 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5",
+ "BriefDescription": "Memory instructions retired above 16384 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x800",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50",
+ "BriefDescription": "Memory instructions retired above 2048 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "500",
+ "BriefDescription": "Memory instructions retired above 256 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5000",
+ "BriefDescription": "Memory instructions retired above 32 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "3",
+ "BriefDescription": "Memory instructions retired above 32768 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50000",
+ "BriefDescription": "Memory instructions retired above 4 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x1000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20",
+ "BriefDescription": "Memory instructions retired above 4096 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "200",
+ "BriefDescription": "Memory instructions retired above 512 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Memory instructions retired above 64 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Memory instructions retired above 8 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x2000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10",
+ "BriefDescription": "Memory instructions retired above 8192 clocks (Precise Event)"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x111",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x211",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x411",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x144",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x244",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x444",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFFFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x80FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x47FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x18FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x38FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x122",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x222",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x422",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore writebacks",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x108",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x408",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code or data read requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x177",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x277",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x477",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any cache_dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any location",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x133",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x233",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x433",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HIT in a remote cache ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x103",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x203",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x403",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x101",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x201",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x401",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x104",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x204",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x404",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x102",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x202",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x402",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore other requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x180",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x280",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x480",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x130",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x230",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x430",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x110",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x210",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x410",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x140",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x240",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x440",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x120",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x220",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x420",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x170",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x270",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x470",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HITM in a remote cache",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json b/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json
new file mode 100644
index 000000000000..7d2f71a9dee3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json
@@ -0,0 +1,229 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.ALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.INPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.OUTPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists for invalid output value (Precise Event)"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_COMP_OPS_EXE.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MMX Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP double precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE and SSE2 FP Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_PACKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP packed Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_SCALAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP scalar Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP single precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_COMP_OPS_EXE.SSE2_INTEGER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE2 integer Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Computational floating-point operations executed"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_MMX_TRANS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Floating Point to and from MMX transitions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_MMX_TRANS.TO_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from MMX to Floating Point instructions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_MMX_TRANS.TO_MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from Floating Point to MMX instructions"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_128.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer pack operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_128.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer arithmetic operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_128.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer logical operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_128.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer multiply operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_128.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shift operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_128.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shuffle/move operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_128.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer unpack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_64.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit pack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_64.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit arithmetic operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_64.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit logical operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_64.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit packed multiply operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_64.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shift operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_64.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shuffle/move operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_64.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit unpack operations"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/frontend.json b/tools/perf/pmu-events/arch/x86/nehalemex/frontend.json
new file mode 100644
index 000000000000..e5e21e03444d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions decoded"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.FUSIONS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused instructions decoded"
+ },
+ {
+ "EventCode": "0x19",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TWO_UOP_INSTS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Two Uop instructions decoded"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/memory.json b/tools/perf/pmu-events/arch/x86/nehalemex/memory.json
new file mode 100644
index 000000000000..f914a4525b65
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/memory.json
@@ -0,0 +1,739 @@
+[
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x60FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x40FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x20FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any LLC miss",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the local DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/other.json b/tools/perf/pmu-events/arch/x86/nehalemex/other.json
new file mode 100644
index 000000000000..af0860622445
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/other.json
@@ -0,0 +1,210 @@
+[
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_CLEARS.EARLY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Early Branch Prediciton Unit clears"
+ },
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BPU_CLEARS.LATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Late Branch Prediction Unit clears"
+ },
+ {
+ "EventCode": "0xE5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_MISSED_CALL_RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch prediction unit missed call or return"
+ },
+ {
+ "EventCode": "0xD5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ES_REG_RENAMES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ES segment renames"
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IO_TRANSACTIONS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "I/O transactions"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1I.CYCLES_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch stall cycles"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1I.HITS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch hits"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1I.MISSES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch misses"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L1I.READS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I Instruction fetches"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LARGE_ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Large ITLB hit"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "LOAD_DISPATCH.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All loads dispatched"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LOAD_DISPATCH.MOB",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_DISPATCH.RS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched that bypass the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_DISPATCH.RS_DELAYED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from stage 305"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PARTIAL_ADDRESS_ALIAS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "False dependencies due to partial address aliasing"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RAT_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All RAT stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RAT_STALLS.FLAGS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Flag stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RAT_STALLS.REGISTERS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Partial register stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RAT_STALLS.ROB_READ_PORT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB read port stalls cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RAT_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Scoreboard stall cycles"
+ },
+ {
+ "EventCode": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "SB_DRAIN.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All Store buffer stall cycles"
+ },
+ {
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SEG_RENAME_STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Segment rename stall cycles"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOP_RESPONSE.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HIT to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOP_RESPONSE.HITE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITE to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOP_RESPONSE.HITM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITM to snoop"
+ },
+ {
+ "EventCode": "0xF6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SQ_FULL_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue full stall cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/pipeline.json b/tools/perf/pmu-events/arch/x86/nehalemex/pipeline.json
new file mode 100644
index 000000000000..41006ddcd893
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/pipeline.json
@@ -0,0 +1,881 @@
+[
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy"
+ },
+ {
+ "EventCode": "0x14",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIV",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide Operations executed",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.MUL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BACLEAR.BAD_TARGET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted with bad target address"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR.CLEAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted, regardless of cause "
+ },
+ {
+ "EventCode": "0xA7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR_FORCE_IQ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction queue forced BACLEAR"
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_INST_EXEC.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_EXEC.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Conditional branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_EXEC.DIRECT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Unconditional branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Unconditional call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_INST_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_INST_EXEC.NON_CALLS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect return branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_EXEC.TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired conditional branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Retired near call instructions (Precise Event)"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_MISP_EXEC.ANY",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_EXEC.COND",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_EXEC.DIRECT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted unconditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_MISP_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_MISP_EXEC.NON_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted return branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_MISP_EXEC.TAKEN",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted near retired calls (Precise Event)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_P",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total CPU cycles",
+ "CounterMask": "2"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "ILD_STALL.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Any Instruction Length Decoder stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction Queue full stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Length Change Prefix stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ILD_STALL.MRU",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stall cycles due to BPU MRU bypass"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ILD_STALL.REGEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Regen stall cycles"
+ },
+ {
+ "EventCode": "0x18",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_DECODED.DEC0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions that must be decoded by decoder 0"
+ },
+ {
+ "EventCode": "0x1E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles instructions are written to the instruction queue"
+ },
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions written to instruction queue."
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (fixed counter)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (Programmable counter and Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "INST_RETIRED.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired MMX instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired floating-point operations (Precise Event)"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load operations conflicting with software prefetches"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xA8",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.INACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD_OVERFLOW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loops that can't stream from the instruction queue"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Cycles machine clear asserted"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEM_ORDER",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Execution pipeline restart due to Memory ordering conflicts"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RESOURCE_STALLS.FPCW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FPU control word write stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LOAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Load buffer stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS.MXCSR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MXCSR rename stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RESOURCE_STALLS.OTHER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Other Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reservation Station full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.STORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Store buffer stall cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SSEX_UOPS_RETIRED.VECTOR_INTEGER",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Vector Integer Uops retired (Precise Event)"
+ },
+ {
+ "EventCode": "0xDB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOP_UNFUSION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uop unfusions due to FP exceptions"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DECODED.ESP_FOLDING",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer instructions decoded"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DECODED.ESP_SYNC",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer sync operations"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DECODED.MS_CYCLES_ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops decoded by Microcode Sequencer",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xD1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DECODED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops are decoded",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on any port (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.PORT0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 0"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 0, 1 or 5"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0, 1 or 5",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.PORT1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT2_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 2 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT234_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 2, 3 or 4"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT3_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 3 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT4_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 4 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED.PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 5"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued on any thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CYCLES_ALL_THREADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops were issued on either thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Fused Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are being retired",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retirement slots used (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are not retiring (Precise Event)",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles using precise uop retired event (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/virtual-memory.json b/tools/perf/pmu-events/arch/x86/nehalemex/virtual-memory.json
new file mode 100644
index 000000000000..0596094e0ee9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/nehalemex/virtual-memory.json
@@ -0,0 +1,109 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load misses"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss caused by low part of address"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB second level hit"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walks complete"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB first level misses but second level hit"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss page walks"
+ },
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_FLUSH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB flushes"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISS_RETIRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired instructions that missed the ITLB (Precise Event)"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss page walks"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_STORE_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired stores that miss the DTLB (Precise Event)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/cache.json b/tools/perf/pmu-events/arch/x86/sandybridge/cache.json
new file mode 100644
index 000000000000..bef73c499f83
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/cache.json
@@ -0,0 +1,1879 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that miss the STLB.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with locked access.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts line-splitted load uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts line-splitted store uops retired to the architected path. A line split is across 64B cache-line which includes a page split (4K).",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store uops that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load uops retired",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of store uops retired.",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store uops.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load uops with L1 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops with L2 cache hits as data sources.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts retired load uops that hit in the last-level (L3) cache without snoops required.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.LLC_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load uops which data sources were data hits in LLC without snoops required.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.HIT_LFB",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were load uops missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC hit and cross-core snoop missed in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts retired load uops that hit in the last-level cache (L3) and were found in a non-modified state in a neighboring core's private cache (same package). Since the last level cache is inclusive, hits to the L3 may require snooping the private L2 caches of any cores on the same socket that have the line. In this case, a snoop was required, and another L2 had the line in a non-modified state.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were LLC and cross-core snoop hits in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts retired load uops that hit in the last-level cache (L3) and were found in a non-modified state in a neighboring core's private cache (same package). Since the last level cache is inclusive, hits to the L3 may require snooping the private L2 caches of any cores on the same socket that have the line. In this case, a snoop was required, and another L2 had the line in a modified state, so the line had to be invalidated in that L2 cache and transferred to the requesting L2.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load uops which data sources were HitM responses from shared LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load uops which data sources were hits in LLC without snoops required.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts retired demand loads that missed the last-level (L3) cache. This means that the load is usually satisfied from memory in a client system or possibly from the remote socket in a server. Demand loads are non speculative load uops.",
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load uops with unknown information as data source in cache serviced the load.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts L1D data line replacements. Replacements occur when a new line is brought into the cache, causing eviction of a line loaded earlier. ",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D.ALLOCATED_IN_M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Allocated L1D data cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D.EVICTION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data cache lines in M state evicted due to replacement.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D.ALL_M_REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cache lines in M state evicted out of L1D due to Snoop HitM or dirty line replacement.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss oustandings duration in cycles.",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1D is locked.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding RFO store transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases when offcore requests buffer cannot take more entries for core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that hit L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L2 hardware prefetchers that miss L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_STORE_LOCK_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that miss cache lines.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in E state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_STORE_LOCK_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that hit cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_STORE_LOCK_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFOs that access cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_L1D_WB_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Count the number of modified Lines evicted from L1 and missed L2. (Non-rejected WBs from the DCU.).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_S",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in S state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_E",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in E state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_L1D_WB_RQSTS.HIT_M",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in M state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_L1D_WB_RQSTS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not rejected writebacks from L1D to L2 cache lines in any state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANS.DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANS.RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANS.CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache accesses when fetching instructions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 or LLC HW prefetches that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANS.L1D_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L1D writebacks that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANS.L2_FILL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 fill requests that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANS.ALL_REQUESTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Transactions accessing L2 pipe.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_IN.I",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in I state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in S state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines in E state filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines brought into the L2 cache. Lines are filled into the L2 cache when there was an L2 miss.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by demand.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by demand.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PF_CLEAN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Clean L2 cache lines evicted by L2 prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PF_DIRTY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines evicted by L2 prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "L2_LINES_OUT.DIRTY_ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Dirty L2 cache lines filling the L2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed LLC.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to LLC.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Split locks in SQ.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from L2 hardware prefetchers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "L1D_BLOCKS.BANK_CONFLICT_CYCLES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when dispatched loads are cancelled due to L1D bank conflicts with other load ports.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_C6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "2",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch code reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch code reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch data reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch code reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch code reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch code reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch data reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch RFOs that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch RFOs that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts data/code/rfo reads (demand & prefetch) that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c03f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts data/code/rfo reads (demand & prefetch) that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch RFOs that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch RFOs that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch RFOs that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand & prefetch RFOs that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "COREWB & ANY_RESPONSE",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x18000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts miscellaneous accesses that include port i/o, MMIO and uncacheable memory accesses. It also includes L2 hints sent to LLC to keep a line from being evicted out of the core caches.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x803c8000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LRU_HINTS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts L2 hints sent to LLC to keep a line from being evicted out of the core caches.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2380408000",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PORTIO_MMIO_UC",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts miscellaneous accesses that include port i/o, MMIO and uncacheable memory accesses.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) code reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) code reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) code reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) data reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) RFOs that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) RFOs that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) RFOs that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) RFOs that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) code reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) data reads that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3f803c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the LLC.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) RFOs that hit in the LLC and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10003c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) RFOs that hit in the LLC and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) RFOs that hit in the LLC and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003c0100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to LLC only) RFOs that hit in the LLC and the snoops sent to sibling cores return clean response.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10400",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.SPLIT_LOCK_UC_LOCK.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts requests where the address of an atomic lock instruction spans a cache line boundary or the lock instruction is executed on uncacheable address.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10800",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts non-temporal stores.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data reads .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand rfo's .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000105B3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00010122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch prefetch RFOs .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x000107F7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo references (demand & prefetch) .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10433",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = DATA_INTO_CORE and RESPONSE = ANY_RESPONSE",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_M.HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = DEMAND_RFO and RESPONSE = LLC_HIT_M and SNOOP = HITM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_RFO and RESPONSE = ANY_RESPONSE",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_LLC_DATA_RD and RESPONSE = ANY_RESPONSE",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L_IFETCH.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_LLC_IFETCH and RESPONSE = ANY_RESPONSE",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/floating-point.json b/tools/perf/pmu-events/arch/x86/sandybridge/floating-point.json
new file mode 100644
index 000000000000..982eda48785e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/floating-point.json
@@ -0,0 +1,138 @@
+[
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OTHER_ASSISTS.AVX_STORE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of GSSE memory assist for stores. GSSE microcode assist is being invoked whenever the hardware is unable to properly handle GSSE-256b operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OTHER_ASSISTS.AVX_TO_SSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from AVX-256 to legacy SSE when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "OTHER_ASSISTS.SSE_TO_AVX",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of transitions from SSE to AVX-256 when penalty applicable.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.X87_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to output value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.X87_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of X87 assists due to input value.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ASSIST.SIMD_OUTPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to Output values.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ASSIST.SIMD_INPUT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of SIMD FP assists due to input values.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULsand IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed double-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar single-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational packed single-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE* or AVX-128 FP Computational scalar double-precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_FP_256.PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of GSSE-256 Computational FP single precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_FP_256.PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of AVX-256 Computational FP double precision uops issued this cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/frontend.json b/tools/perf/pmu-events/arch/x86/sandybridge/frontend.json
new file mode 100644
index 000000000000..1b7b1dd36c68
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/frontend.json
@@ -0,0 +1,305 @@
+[
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Instruction Cache, Streaming Buffer and Victim Cache Reads. both cacheable and noncacheable, including UC fetches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of instruction cache, streaming buffer and victim cache misses. Counting includes unchacheable accesses.",
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction cache, streaming buffer and victim cache misses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "IDQ.EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instruction Decode Queue (IDQ) empty cycles.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the microcode sequencer assisted the front-end in delivering uops. Microcode assists are used for complex instructions or scenarios that can't be handled by the standard decoder. Using other instructions, if possible, will usually improve performance. See the Intel? 64 and IA-32 Architectures Optimization Reference Manual for more information.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops not delivered to the back-end per cycle, per thread, when the back-end was not stalled. In the ideal case 4 uops can be delivered each cycle. The event counts the undelivered uops - so if 3 were delivered in one cycle, the counter would be incremented by 1 for that cycle (4 - 3). If the back-end is stalled, the count for this event is not incremented even when uops were not delivered, because the back-end would not have been able to accept them. This event is used in determining the front-end bound category of the top-down pipeline slots characterization.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled .",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the cycles attributed to a switch from the Decoded Stream Buffer (DSB), which holds decoded instructions, to the legacy decode pipeline. It excludes cycles when the back-end cannot accept new micro-ops. The penalty for these switches is potentially several cycles of instruction starvation, where no micro-ops are delivered to the back-end.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB_FILL.OTHER_CANCEL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases of cancelling valid DSB fill not because of exceeding way limit.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DSB_FILL.EXCEED_DSB_LINES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Decode Stream Buffer (DSB) fill encounter more than 3 Decode Stream Buffer (DSB) lines.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_DSB_OCCUR",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_GE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when 1 or more uops were delivered to the by the front end.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xAC",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "DSB_FILL.ALL_CANCEL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cases of cancelling valid Decode Stream Buffer (DSB) fill not because of exceeding way limit.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3c",
+ "EventName": "IDQ.MITE_ALL_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/memory.json b/tools/perf/pmu-events/arch/x86/sandybridge/memory.json
new file mode 100644
index 000000000000..e6dfa89d00f3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/memory.json
@@ -0,0 +1,445 @@
+[
+ {
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from memory disambiguation, external snoops, or cross SMT-HW-thread snoop (stores) hitting load buffers. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads with latency value being above 4 .",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Loads with latency value being above 8.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Loads with latency value being above 16.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads with latency value being above 32.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Loads with latency value being above 64.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Loads with latency value being above 128.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Loads with latency value being above 256.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Loads with latency value being above 512.",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xCD",
+ "Counter": "3",
+ "UMask": "0x2",
+ "EventName": "MEM_TRANS_RETIRED.PRECISE_STORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Sample stores and collect precise store operation via PEBS record. PMC3 only. (Precise Event - PEBS).",
+ "PRECISE_STORE": "1",
+ "TakenAlone": "1",
+ "CounterHTOff": "3"
+ },
+ {
+ "EventCode": "0xBE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.LLC_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of any page walk that had a miss in LLC. Does not necessary cause a SUSPEND.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MISALIGN_MEM_REF.LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split load uops dispatched to L1 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x05",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Speculative cache line split STA uops dispatched to L1 cache.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch code reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400091",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch code reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400090",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch data reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch RFOs that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3004003f7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all data/code/rfo reads (demand & prefetch) that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand code reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data writes (RFOs) that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) code reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_CODE_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) code reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_DATA_RD.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x300400100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_LLC_RFO.LLC_MISS.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the LLC and the data returned from dram.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts all data requests (demand/prefetch data reads and demand data writes (RFOs) that miss the LLC where the data is returned from local DRAM",
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6004001b3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN_SOCKET.LLC_MISS.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts LLC replacements.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts any requests that miss the LLC where the data was returned from local DRAM",
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80408fff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = ANY_REQUEST and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x17004001b3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN_SOCKET.LLC_MISS_LOCAL.ANY_LLC_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = DATA_IN_SOCKET and RESPONSE = LLC_MISS_LOCAL and SNOOP = ANY_LLC_HIT",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80400004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = DEMAND_IFETCH and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80400010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_DATA_RD and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80400040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_RFO and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80400080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L_DATA_RD.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_LLC_DATA_RD and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1f80400200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE.PF_L_IFETCH.LLC_MISS_LOCAL.DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": " REQUEST = PF_LLC_IFETCH and RESPONSE = LLC_MISS_LOCAL and SNOOP = DRAM",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/other.json b/tools/perf/pmu-events/arch/x86/sandybridge/other.json
new file mode 100644
index 000000000000..64b195b82c50
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/other.json
@@ -0,0 +1,58 @@
+[
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INSTS_WRITTEN_TO_IQ.INSTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Valid instructions written to IQ per cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPL_CYCLES.RING0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when the thread is in ring 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "CPL_CYCLES.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Number of intervals between processor halts while thread is in ring 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPL_CYCLES.RING123",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Unhalted core cycles when thread is in rings 1, 2, or 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "HW_PRE_REQ.DL1_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Hardware Prefetch requests that miss the L1D cache. This accounts for both L1 streamer and IP-based (IPP) HW prefetchers. A request is being counted each time it access the cache & miss it, including if a block is applicable or if hit the Fill Buffer for .",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when L1 and L2 are locked due to UC or split lock.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/pipeline.json b/tools/perf/pmu-events/arch/x86/sandybridge/pipeline.json
new file mode 100644
index 000000000000..8a597e45ed84
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/pipeline.json
@@ -0,0 +1,1220 @@
+[
+ {
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. ",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_INST_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_INST_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_JUMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired macro-conditional branch instructions excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_INST_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_INST_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_INST_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc2",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_JMP",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired macro-unconditional branches excluding calls and indirects.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc8",
+ "EventName": "BR_INST_EXEC.ALL_INDIRECT_NEAR_RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired indirect return branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_INST_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "BR_MISP_EXEC.NONTAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Not taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "BR_MISP_EXEC.TAKEN_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x84",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x88",
+ "EventName": "BR_MISP_EXEC.TAKEN_RETURN_NEAR",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect branches with return mnemonic.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x90",
+ "EventName": "BR_MISP_EXEC.TAKEN_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa0",
+ "EventName": "BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Taken speculative and retired mispredicted indirect calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc1",
+ "EventName": "BR_MISP_EXEC.ALL_CONDITIONAL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc4",
+ "EventName": "BR_MISP_EXEC.ALL_INDIRECT_JUMP_NON_CALL_RET",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Mispredicted indirect branches excluding calls and returns.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd0",
+ "EventName": "BR_MISP_EXEC.ALL_DIRECT_NEAR_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted direct near calls.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stall cycles because IQ is full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "INT_MISC.RAT_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) external stall is sent to Instruction Decode Queue (IDQ) for the thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Increments the number of flags-merge uops in flight each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles with at least one slow LEA uop being allocated. A uop is generally considered as slow LEA if it has three sources (for example, two sources and immediate) regardless of whether it is a result of LEA instruction or not. Examples of the slow LEA uop are or uops with base, index, and offset source operands using base and index reqisters, where base is EBR/RBP/R13, using RIP relative or 16-bit addressing modes. See the Intel? 64 and IA-32 Architectures Optimization Reference Manual for more details about slow LEA instructions.",
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least one slow LEA uop being allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "PARTIAL_RAT_STALLS.MUL_SINGLE_UOP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Multiply packed/scalar single precision uops allocated.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the cycles of stall due to lack of load buffers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no eligible RS entry available.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to re-order buffer full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS2.BOB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Allocator is stalled if BOB is full and new branch needs it.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of Uops issued by the front-end of the pipeilne to the back-end.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count cases of saving new LBR.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event is incremented when self-modifying code (SMC) is detected, which causes a machine clear. Machine clears can have a significant performance impact if they are happening frequently.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Maskmov false fault - counts number of time ucode passes through Maskmov flow due to instruction's mask being 0 while the flow was completed without raising a fault.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MACHINE_CLEARS.MASKMOV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of executed Intel AVX masked load operations that refer to an illegal address range with the mask bits set to 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of micro-ops retired.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Actually retired uops.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of retirement slots used each cycle. There are potentially 4 slots that can be used each cycle - meaning, 4 micro-ops or 4 instructions could retire each cycle. This event is used in determining the 'Retiring' category of the Top-Down pipeline slots characterization.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired. (Precise Event - PEBS).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect mispredicted near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS)",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired. (Precise Event - PEBS).",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OTHER_ASSISTS.ITLB_MISS_RETIRED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired instructions experiencing ITLB misses.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.FPU_DIV_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divider is busy executing divide operations.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of the divide operations executed.",
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "ARITH.FPU_DIV",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Divide operations executed.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched per thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops dispatched from any thread.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are dispatched to port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_NO_DISPATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was no dispatch for this thread, increment by 1. Note this is connect to Umask 2. No dispatch can be deduced from the UOPS_EXECUTED event.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a miss-pending demand load this thread, increment by 1. Note this is in DCU and connected to Umask 1. Miss Pending demand load should be deduced by OR-ing increment bits of DCACHE_MISS_PEND.PENDING.",
+ "CounterMask": "2",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a MLC-miss pending demand load this thread (i.e. Non-completed valid SQ entry allocated for demand load and waiting for Uncore), increment by 1. Note this is in MLC and connected to Umask 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "2",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a miss-pending demand load this thread and no uops dispatched, increment by 1. Note this is in DCU and connected to Umask 1 and 2. Miss Pending demand load should be deduced by OR-ing increment bits of DCACHE_MISS_PEND.PENDING.",
+ "CounterMask": "6",
+ "CounterHTOff": "2"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Each cycle there was a MLC-miss pending demand load and no uops dispatched on this thread (i.e. Non-completed valid SQ entry allocated for demand load and waiting for Uncore), increment by 1. Note this is in MLC and connected to Umask 0 and 2.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for software prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_HIT_PRE.HW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Not software-prefetch load dispatches that hit FB allocated for hardware prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS.DATA_UNKNOWN",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads delayed due to SB blocks, preceding store operations with known addresses but unknown data.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts loads that followed a store to the same address, where the data could not be forwarded inside the pipeline from the store to the load. The most common reason why store forwarding would be blocked is when a load's address range overlaps with a preceeding smaller uncompleted store. See the table of not supported store forwards in the Intel? 64 and IA-32 Architectures Optimization Reference Manual. The penalty for blocked store forwarding is that the load must wait for the store to complete before it can be issued.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cases when loads get true Block-on-Store blocking code preventing store forwarding.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "LD_BLOCKS.ALL_BLOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of cases where any load ends up with a valid block-code written to the load buffer (including blocks due to Memory Order Buffer (MOB), Data Cache Unit (DCU), TLB, but load has no DCU miss).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Aliasing occurs when a load is issued after a store and their memory addresses are offset by 4K. This event counts the number of loads that aliased with a preceding store, resulting in an extended address check in the pipeline. The enhanced address check typically has a performance penalty of 5 cycles.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS_PARTIAL.ALL_STA_BLOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts the number of times that load operations are temporarily blocked because of older stores, with addresses that are not yet known. A load operation may incur more than one block of this type.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "AGU_BYPASS_CANCEL.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "This event counts executed load operations with all the following traits: 1. addressing of the format [base + offset], 2. the offset is between 1 and 2047, 3. the address specified in the base register is in one page and the address [base+offset] is in an.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other is halted.",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 0.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 1.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 4.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when uops are dispatched to port 5.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when load or STA uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 2.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "AnyThread": "1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3_CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per core when load or STA uops are dispatched to port 3.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired. (Precise Event - PEBS).",
+ "TakenAlone": "1",
+ "CounterHTOff": "1"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RESOURCE_STALLS2.ALL_PRF_CONTROL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls2 control structures full for physical registers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "RESOURCE_STALLS2.ALL_FL_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with either free list is empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "RESOURCE_STALLS.MEM_RS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to memory buffers or Reservation Station (RS) being fully utilized.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "RESOURCE_STALLS.OOO_RSRC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to Rob being full, FCSW, MXCSR and OTHER.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5B",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "RESOURCE_STALLS2.OOO_RSRC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls out of order resources full.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xa",
+ "EventName": "RESOURCE_STALLS.LB_SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource stalls due to load or store buffers all being in use.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles spent executing performance-sensitive flags-merging uops. For example, shift CL (merge_arith_flags). For more details, See the Intel? 64 and IA-32 Architectures Optimization Reference Manual.",
+ "EventCode": "0x59",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Performance sensitive flags-merging uops added by Sandy Bridge u-arch.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EdgeDetect": "1",
+ "EventName": "INT_MISC.RECOVERY_STALLS_COUNT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of occurences waiting for the checkpoints in Resource Allocation Table (RAT) to be recovered after Nuke due to all other cases except JEClear (e.g. whenever a ucode assist is needed like SSE exception, memory disambiguation, etc...).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_INST_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "BR_MISP_EXEC.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Speculative and retired mispredicted macro conditional branches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xc3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate)",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the thread is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the at least one thread on the physical core is unhalted (counts at 100 MHz rate).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Count XClk pulses when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/virtual-memory.json b/tools/perf/pmu-events/arch/x86/sandybridge/virtual-memory.json
new file mode 100644
index 000000000000..a654ab771fce
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/virtual-memory.json
@@ -0,0 +1,149 @@
+[
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycle count for an Extended Page table walk. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses in all ITLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event count cycles when Page Miss Handler (PMH) is servicing page walks caused by ITLB misses.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Operations that miss the first ITLB level but hit the second and do not cause any page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses at all DTLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB load misses.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load operations that miss the first DTLB level but hit the second and do not cause any page walks. The penalty in this case is approximately 7 cycles.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load operations that miss the first DTLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_DURATION",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when PMH is busy with page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store operations that miss the first TLB level but hit the second and do not cause page walks.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/silvermont/cache.json b/tools/perf/pmu-events/arch/x86/silvermont/cache.json
new file mode 100644
index 000000000000..0bd1bc5302de
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/silvermont/cache.json
@@ -0,0 +1,811 @@
+[
+ {
+ "PublicDescription": "This event counts the number of demand and prefetch transactions that the L2 XQ rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The XQ may reject transactions from the L2Q (non-cacheable requests), BBS (L2 misses) and WOB (L2 write-back victims).",
+ "EventCode": "0x30",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "L2_REJECT_XQ.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of request from the L2 that were not accepted into the XQ"
+ },
+ {
+ "PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full w condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a core?s dirty eviction when the address conflicts incoming external snoops. (Note that L2 prefetcher requests that are dropped are not counted by this event.)",
+ "EventCode": "0x31",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "CORE_REJECT_L2Q.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of request that were not accepted into the L2Q because the L2Q is FULL."
+ },
+ {
+ "PublicDescription": "This event counts requests originating from the core that references a cache line in the L2 cache.",
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache requests from this core"
+ },
+ {
+ "PublicDescription": "This event counts the total number of L2 cache references and the number of L2 cache misses respectively.",
+ "EventCode": "0x2E",
+ "Counter": "0,1",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache request misses"
+ },
+ {
+ "EventCode": "0x86",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles the NIP stalls because of an icache miss. This is a cumulative count of cycles the NIP stalled for all icache misses."
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of retired loads that were prohibited from receiving forwarded data from the store because of address mismatch.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "REHABQ.LD_BLOCK_ST_FORWARD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked due to store forward restriction"
+ },
+ {
+ "PublicDescription": "This event counts the cases where a forward was technically possible, but did not occur because the store data was not available at the right time.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "REHABQ.LD_BLOCK_STD_NOTREADY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads blocked due to store data not ready"
+ },
+ {
+ "PublicDescription": "This event counts the number of retire stores that experienced cache line boundary splits.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "REHABQ.ST_SPLITS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Store uops that split cache line boundary"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of retire loads that experienced cache line boundary splits.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "REHABQ.LD_SPLITS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Load uops that split cache line boundary"
+ },
+ {
+ "PublicDescription": "This event counts the number of retired memory operations with lock semantics. These are either implicit locked instructions such as the XCHG instruction or instructions with an explicit LOCK prefix (0xF0).",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "REHABQ.LOCK",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Uops with lock semantics"
+ },
+ {
+ "PublicDescription": "This event counts the number of retired stores that are delayed because there is not a store address buffer available.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "REHABQ.STA_FULL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Store address buffer full"
+ },
+ {
+ "PublicDescription": "This event counts the number of load uops reissued from Rehabq.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "REHABQ.ANY_LD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Any reissued load uops"
+ },
+ {
+ "PublicDescription": "This event counts the number of store uops reissued from Rehabq.",
+ "EventCode": "0x03",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "REHABQ.ANY_ST",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Any reissued store uops"
+ },
+ {
+ "PublicDescription": "This event counts the number of load ops retired that miss in L1 Data cache. Note that prefetch misses will not be counted.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MEM_UOPS_RETIRED.L1_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads missed L1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load ops retired that hit in the L2.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MEM_UOPS_RETIRED.L2_HIT_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads hit L2"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load ops retired that miss in the L2.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "MEM_UOPS_RETIRED.L2_MISS_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Loads missed L2"
+ },
+ {
+ "PublicDescription": "This event counts the number of load ops retired that had UTLB miss.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "MEM_UOPS_RETIRED.UTLB_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads missed UTLB"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load ops retired that got data from the other core or from the other module.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "MEM_UOPS_RETIRED.HITM",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cross core or cross module hitm"
+ },
+ {
+ "PublicDescription": "This event counts the number of load ops retired.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x40",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All Loads"
+ },
+ {
+ "PublicDescription": "This event counts the number of store ops retired.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All Stores"
+ },
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0xB7",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000044",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any code reads (demand & prefetch) that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000044",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any code reads (demand & prefetch) that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000044",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any code reads (demand & prefetch) that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000044",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any code reads (demand & prefetch) that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010044",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any code reads (demand & prefetch) that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000022",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any rfo reads (demand & prefetch) that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000022",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any rfo reads (demand & prefetch) that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000022",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any rfo reads (demand & prefetch) that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000022",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any rfo reads (demand & prefetch) that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010022",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any rfo reads (demand & prefetch) that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680003091",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data read (demand & prefetch) that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000003091",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data read (demand & prefetch) that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400003091",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data read (demand & prefetch) that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200003091",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data read (demand & prefetch) that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000013091",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any data read (demand & prefetch) that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680004800",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts streaming store that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000008008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400008008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200008008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000018008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts any request that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680002000",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts DCU hardware prefetcher data read that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000002000",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts DCU hardware prefetcher data read that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400002000",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts DCU hardware prefetcher data read that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200002000",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts DCU hardware prefetcher data read that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000012000",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts DCU hardware prefetcher data read that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000100",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_WRITES.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Countsof demand RFO requests to write to partial cache lines that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000080",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PARTIAL_READS.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand reads of partial cache lines (including UC and WC) that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000040",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts code reads generated by L2 prefetchers that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000040",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts code reads generated by L2 prefetchers that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000040",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_CODE_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts code reads generated by L2 prefetchers that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000020",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts RFO requests generated by L2 prefetchers that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000020",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts RFO requests generated by L2 prefetchers that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000020",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts RFO requests generated by L2 prefetchers that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000020",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts RFO requests generated by L2 prefetchers that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000010",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by L2 prefetchers that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000010",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by L2 prefetchers that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000010",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by L2 prefetchers that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000010",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts data cacheline reads generated by L2 prefetchers that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts writeback (modified to exclusive) that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0080000008",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts writeback (modified to exclusive) that miss L2 with no details on snoop-related information.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000004",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch instruction cacheline that are are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000004",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch instruction cacheline that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000004",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch instruction cacheline that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000004",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch instruction cacheline that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010004",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch instruction cacheline that have any response type.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000002",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch RFOs that are are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000002",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch RFOs that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000002",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch RFOs that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000002",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch RFOs that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000002",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch RFOs that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4000000001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OUTSTANDING",
+ "MSRIndex": "0x1a6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that are are outstanding, per cycle, from the time of the L2 miss to when any response is received.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1680000001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.ANY",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that miss L2.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1000000001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that hit in the other module where modified copies were found in other core's L1 cache.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0400000001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that miss L2 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0200000001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that miss L2 with a snoop miss response.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x0000010001",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts demand and DCU prefetch data read that have any response type.",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/silvermont/frontend.json b/tools/perf/pmu-events/arch/x86/silvermont/frontend.json
new file mode 100644
index 000000000000..204473badf5a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/silvermont/frontend.json
@@ -0,0 +1,47 @@
+[
+ {
+ "PublicDescription": "This event counts all instruction fetches, not including most uncacheable\r\nfetches.",
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "ICACHE.ACCESSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetches"
+ },
+ {
+ "PublicDescription": "This event counts all instruction fetches from the instruction cache.",
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "ICACHE.HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetches from Icache"
+ },
+ {
+ "PublicDescription": "This event counts all instruction fetches that miss the Instruction cache or produce memory requests. This includes uncacheable fetches. An instruction fetch miss is counted only once and not once for every cycle it is outstanding.",
+ "EventCode": "0x80",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "ICACHE.MISSES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Icache miss"
+ },
+ {
+ "PublicDescription": "Counts the number of times the MSROM starts a flow of UOPS. It does not count every time a UOP is read from the microcode ROM. The most common case that this counts is when a micro-coded instruction is encountered by the front end of the machine. Other cases include when an instruction encounters a fault, trap, or microcode assist of any sort. The event will count MSROM startups for UOPS that are speculative, and subsequently cleared by branch mispredict or machine clear. Background: UOPS are produced by two mechanisms. Either they are generated by hardware that decodes instructions into UOPS, or they are delivered by a ROM (called the MSROM) that holds UOPS associated with a specific instruction. MSROM UOPS might also be delivered in response to some condition such as a fault or other exceptional condition. This event is an excellent mechanism for detecting instructions that require the use of MSROM instructions.",
+ "EventCode": "0xE7",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MS_DECODED.MS_ENTRY",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times entered into a ucode flow in the FEC. Includes inserted flows due to front-end detected faults or assists. Speculative count."
+ },
+ {
+ "PublicDescription": "Counts the number of times a decode restriction reduced the decode throughput due to wrong instruction length prediction.",
+ "EventCode": "0xE9",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of times a decode restriction reduced the decode throughput due to wrong instruction length prediction"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/silvermont/memory.json b/tools/perf/pmu-events/arch/x86/silvermont/memory.json
new file mode 100644
index 000000000000..d72e09a5f929
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/silvermont/memory.json
@@ -0,0 +1,11 @@
+[
+ {
+ "PublicDescription": "This event counts the number of times that pipeline was cleared due to memory ordering issues.",
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Stalls due to Memory ordering"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/silvermont/pipeline.json b/tools/perf/pmu-events/arch/x86/silvermont/pipeline.json
new file mode 100644
index 000000000000..7468af99190a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/silvermont/pipeline.json
@@ -0,0 +1,359 @@
+[
+ {
+ "PEBS": "1",
+ "PublicDescription": "ALL_BRANCHES counts the number of any branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of branch instructions retired..."
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "JCC counts the number of conditional branch (JCC) instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x7e",
+ "EventName": "BR_INST_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of JCC branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "TAKEN_JCC counts the number of taken conditional branch (JCC) instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfe",
+ "EventName": "BR_INST_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of taken JCC branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "CALL counts the number of near CALL branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xf9",
+ "EventName": "BR_INST_RETIRED.CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near CALL branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "REL_CALL counts the number of near relative CALL branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfd",
+ "EventName": "BR_INST_RETIRED.REL_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near relative CALL branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "IND_CALL counts the number of near indirect CALL branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xfb",
+ "EventName": "BR_INST_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near indirect CALL branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "RETURN counts the number of near RET branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xf7",
+ "EventName": "BR_INST_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near RET branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "NON_RETURN_IND counts the number of near indirect JMP and near indirect CALL branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xeb",
+ "EventName": "BR_INST_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of near indirect JMP and near indirect CALL branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "FAR counts the number of far branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0xbf",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of far branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "ALL_BRANCHES counts the number of any mispredicted branch instructions retired. This umask is an architecturally defined event. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "JCC counts the number of mispredicted conditional branches (JCC) instructions retired. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0x7e",
+ "EventName": "BR_MISP_RETIRED.JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted JCC branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "TAKEN_JCC counts the number of mispredicted taken conditional branch (JCC) instructions retired. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xfe",
+ "EventName": "BR_MISP_RETIRED.TAKEN_JCC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted taken JCC branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "IND_CALL counts the number of mispredicted near indirect CALL branch instructions retired. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xfb",
+ "EventName": "BR_MISP_RETIRED.IND_CALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near indirect CALL branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "RETURN counts the number of mispredicted near RET branch instructions retired. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xf7",
+ "EventName": "BR_MISP_RETIRED.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near RET branch instructions retired"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "NON_RETURN_IND counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired. This event counts the number of retired branch instructions that were mispredicted by the processor, categorized by type. A branch misprediction occurs when the processor predicts that the branch would be taken, but it is not, or vice-versa. When the misprediction is discovered, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "EventCode": "0xC5",
+ "Counter": "0,1",
+ "UMask": "0xeb",
+ "EventName": "BR_MISP_RETIRED.NON_RETURN_IND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired"
+ },
+ {
+ "PublicDescription": "This event counts the number of micro-ops retired that were supplied from MSROM.",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.MS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "MSROM micro-ops retired"
+ },
+ {
+ "PublicDescription": "This event counts the number of micro-ops retired. The processor decodes complex macro instructions into a sequence of simpler micro-ops. Most instructions are composed of one or two micro-ops. Some instructions are decoded into longer sequences such as repeat instructions, floating point transcendental instructions, and assists. In some cases micro-op sequences are fused or whole instructions are fused into one micro-op. See other UOPS_RETIRED events for differentiating retired fused and non-fused micro-ops.",
+ "EventCode": "0xC2",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "UOPS_RETIRED.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Micro-ops retired"
+ },
+ {
+ "PublicDescription": "This event counts the number of times that a program writes to a code section. Self-modifying code causes a severe penalty in all Intel? architecture processors.",
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "PublicDescription": "This event counts the number of times that pipeline stalled due to FP operations needing assists.",
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.FP_ASSIST",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Stalls due to FP assists"
+ },
+ {
+ "PublicDescription": "Machine clears happen when something happens in the machine that causes the hardware to need to take special care to get the right answer. When such a condition is signaled on an instruction, the front end of the machine is notified that it must restart, so no more instructions will be decoded from the current path. All instructions \"older\" than this one will be allowed to finish. This instruction and all \"younger\" instructions must be cleared, since they must not be allowed to complete. Essentially, the hardware waits until the problematic instruction is the oldest instruction in the machine. This means all older instructions are retired, and all pending stores (from older instructions) are completed. Then the new path of instructions from the front end are allowed to start into the machine. There are many conditions that might cause a machine clear (including the receipt of an interrupt, or a trap or a fault). All those conditions (including but not limited to MACHINE_CLEARS.MEMORY_ORDERING, MACHINE_CLEARS.SMC, and MACHINE_CLEARS.FP_ASSIST) are captured in the ANY event. In addition, some conditions can be specifically counted (i.e. SMC, MEMORY_ORDERING, FP_ASSIST). However, the sum of SMC, MEMORY_ORDERING, and FP_ASSIST machine clears will not necessarily equal the number of ANY.",
+ "EventCode": "0xC3",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "MACHINE_CLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts all machine clears"
+ },
+ {
+ "PublicDescription": "Counts the number of cycles when no uops are allocated and the ROB is full (less than 2 entries available).",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "NO_ALLOC_CYCLES.ROB_FULL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles when no uops are allocated and the ROB is full (less than 2 entries available)"
+ },
+ {
+ "PublicDescription": "Counts the number of cycles when no uops are allocated and the alloc pipe is stalled waiting for a mispredicted jump to retire. After the misprediction is detected, the front end will start immediately but the allocate pipe stalls until the mispredicted.",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "NO_ALLOC_CYCLES.MISPREDICTS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles when no uops are allocated and the alloc pipe is stalled waiting for a mispredicted jump to retire. After the misprediction is detected, the front end will start immediately but the allocate pipe stalls until the mispredicted "
+ },
+ {
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "NO_ALLOC_CYCLES.RAT_STALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles when no uops are allocated and a RATstall is asserted."
+ },
+ {
+ "PublicDescription": "The NO_ALLOC_CYCLES.NOT_DELIVERED event is used to measure front-end inefficiencies, i.e. when front-end of the machine is not delivering micro-ops to the back-end and the back-end is not stalled. This event can be used to identify if the machine is truly front-end bound. When this event occurs, it is an indication that the front-end of the machine is operating at less than its theoretical peak performance. Background: We can think of the processor pipeline as being divided into 2 broader parts: Front-end and Back-end. Front-end is responsible for fetching the instruction, decoding into micro-ops (uops) in machine understandable format and putting them into a micro-op queue to be consumed by back end. The back-end then takes these micro-ops, allocates the required resources. When all resources are ready, micro-ops are executed. If the back-end is not ready to accept micro-ops from the front-end, then we do not want to count these as front-end bottlenecks. However, whenever we have bottlenecks in the back-end, we will have allocation unit stalls and eventually forcing the front-end to wait until the back-end is ready to receive more UOPS. This event counts the cycles only when back-end is requesting more uops and front-end is not able to provide them. Some examples of conditions that cause front-end efficiencies are: Icache misses, ITLB misses, and decoder restrictions that limit the the front-end bandwidth.",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x50",
+ "EventName": "NO_ALLOC_CYCLES.NOT_DELIVERED",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles when no uops are allocated, the IQ is empty, and no other condition is blocking allocation."
+ },
+ {
+ "PublicDescription": "The NO_ALLOC_CYCLES.ALL event counts the number of cycles when the front-end does not provide any instructions to be allocated for any reason. This event indicates the cycles where an allocation stalls occurs, and no UOPS are allocated in that cycle.",
+ "EventCode": "0xCA",
+ "Counter": "0,1",
+ "UMask": "0x3f",
+ "EventName": "NO_ALLOC_CYCLES.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles when no uops are allocated for any reason."
+ },
+ {
+ "PublicDescription": "Counts the number of cycles and allocation pipeline is stalled and is waiting for a free MEC reservation station entry. The cycles should be appropriately counted in case of the cracked ops e.g. In case of a cracked load-op, the load portion is sent to M.",
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "RS_FULL_STALL.MEC",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles and allocation pipeline is stalled and is waiting for a free MEC reservation station entry. The cycles should be appropriately counted in case of the cracked ops e.g. In case of a cracked load-op, the load portion is sent to M"
+ },
+ {
+ "EventCode": "0xCB",
+ "Counter": "0,1",
+ "UMask": "0x1f",
+ "EventName": "RS_FULL_STALL.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of cycles the Alloc pipeline is stalled when any one of the RSs (IEC, FPC and MEC) is full. This event is a superset of all the individual RS stall event counts."
+ },
+ {
+ "PublicDescription": "This event counts the number of instructions that retire execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. The counter continues counting during hardware interrupts, traps, and inside interrupt handlers.",
+ "EventCode": "0xC0",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired"
+ },
+ {
+ "PublicDescription": "Cycles the divider is busy.This event counts the cycles when the divide unit is unable to accept a new divide UOP because it is busy processing a previously dispatched UOP. The cycles will be counted irrespective of whether or not another divide UOP is waiting to enter the divide unit (from the RS). This event might count cycles while a divide is in progress even if the RS is empty. The divide instruction is one of the longest latency instructions in the machine. Hence, it has a special event associated with it to help determine if divides are delaying the retirement of instructions.",
+ "EventCode": "0xCD",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CYCLES_DIV_BUSY.ALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles the divider is busy. Does not imply a stall waiting for the divider."
+ },
+ {
+ "PublicDescription": "This event counts the number of instructions that retire. For instructions that consist of multiple micro-ops, this event counts exactly once, as the last micro-op of the instruction retires. The event continues counting while instructions retire, including during interrupt service routines caused by hardware interrupts, faults or traps. Background: Modern microprocessors employ extensive pipelining and speculative techniques. Since sometimes an instruction is started but never completed, the notion of \"retirement\" is introduced. A retired instruction is one that commits its states. Or stated differently, an instruction might be abandoned at some point. No instruction is truly finished until it retires. This counter measures the number of completed instructions. The fixed event is INST_RETIRED.ANY and the programmable event is INST_RETIRED.ANY_P.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of instructions retired"
+ },
+ {
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. In systems with a constant core frequency, this event can give you a measurement of the elapsed time while the core was not in halt state by dividing the event count by the core frequency. This event is architecturally defined and is a designated fixed counter. CPU_CLK_UNHALTED.CORE and CPU_CLK_UNHALTED.CORE_P use the core frequency which may change from time to time. CPU_CLK_UNHALTE.REF_TSC and CPU_CLK_UNHALTED.REF are not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. The fixed events are CPU_CLK_UNHALTED.CORE and CPU_CLK_UNHALTED.REF_TSC and the programmable events are CPU_CLK_UNHALTED.CORE_P and CPU_CLK_UNHALTED.REF.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles"
+ },
+ {
+ "PublicDescription": "Counts the number of reference cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time. This event is not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. Divide this event count by core frequency to determine the elapsed time while the core was not in halt state. Divide this event count by core frequency to determine the elapsed time while the core was not in halt state. This event is architecturally defined and is a designated fixed counter. CPU_CLK_UNHALTED.CORE and CPU_CLK_UNHALTED.CORE_P use the core frequency which may change from time to time. CPU_CLK_UNHALTE.REF_TSC and CPU_CLK_UNHALTED.REF are not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. The fixed events are CPU_CLK_UNHALTED.CORE and CPU_CLK_UNHALTED.REF_TSC and the programmable events are CPU_CLK_UNHALTED.CORE_P and CPU_CLK_UNHALTED.REF.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Fixed Counter: Counts the number of unhalted reference clock cycles"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time.",
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.CORE_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when core is not halted"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time. This event is not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time.",
+ "EventCode": "0x3C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when core is not halted"
+ },
+ {
+ "PublicDescription": "The BACLEARS event counts the number of times the front end is resteered, mainly when the Branch Prediction Unit cannot provide a correct prediction and this is corrected by the Branch Address Calculator at the front end. The BACLEARS.ANY event counts the number of baclears for any type of branch.",
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "BACLEARS.ALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of baclears"
+ },
+ {
+ "PublicDescription": "The BACLEARS event counts the number of times the front end is resteered, mainly when the Branch Prediction Unit cannot provide a correct prediction and this is corrected by the Branch Address Calculator at the front end. The BACLEARS.RETURN event counts the number of RETURN baclears.",
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "BACLEARS.RETURN",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of RETURN baclears"
+ },
+ {
+ "PublicDescription": "The BACLEARS event counts the number of times the front end is resteered, mainly when the Branch Prediction Unit cannot provide a correct prediction and this is corrected by the Branch Address Calculator at the front end. The BACLEARS.COND event counts the number of JCC (Jump on Condtional Code) baclears.",
+ "EventCode": "0xE6",
+ "Counter": "0,1",
+ "UMask": "0x10",
+ "EventName": "BACLEARS.COND",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of JCC baclears"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "ALL_TAKEN_BRANCHES counts the number of all taken branch instructions retired. Branch prediction predicts the branch target and enables the processor to begin executing instructions long before the branch true execution path is known. All branches utilize the branch prediction unit (BPU) for prediction. This unit predicts the target address not only based on the EIP of the branch but also based on the execution path through which execution reached this EIP. The BPU can efficiently predict the following branch types: conditional branches, direct calls and jumps, indirect calls and jumps, returns.",
+ "EventCode": "0xC4",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "PEBScounters": "0,1",
+ "EventName": "BR_INST_RETIRED.ALL_TAKEN_BRANCHES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of taken branch instructions retired"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/silvermont/virtual-memory.json b/tools/perf/pmu-events/arch/x86/silvermont/virtual-memory.json
new file mode 100644
index 000000000000..ad31479f8f60
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/silvermont/virtual-memory.json
@@ -0,0 +1,69 @@
+[
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts the number of load ops retired that had DTLB miss.",
+ "EventCode": "0x04",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Loads missed DTLB"
+ },
+ {
+ "PublicDescription": "This event counts when a data (D) page walk is completed or started. Since a page walk implies a TLB miss, the number of TLB misses can be counted by counting the number of pagewalks.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "D-side page-walks",
+ "EdgeDetect": "1"
+ },
+ {
+ "PublicDescription": "This event counts every cycle when a D-side (walks due to a load) page walk is in progress. Page walk duration divided by number of page walks is the average duration of page-walks.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "PAGE_WALKS.D_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Duration of D-side page-walks in core cycles"
+ },
+ {
+ "PublicDescription": "This event counts when an instruction (I) page walk is completed or started. Since a page walk implies a TLB miss, the number of TLB misses can be counted by counting the number of pagewalks.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "I-side page-walks",
+ "EdgeDetect": "1"
+ },
+ {
+ "PublicDescription": "This event counts every cycle when a I-side (walks due to an instruction fetch) page walk is in progress. Page walk duration divided by number of page walks is the average duration of page-walks.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "PAGE_WALKS.I_SIDE_CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Duration of I-side page-walks in core cycles"
+ },
+ {
+ "PublicDescription": "This event counts when a data (D) page walk or an instruction (I) page walk is completed or started. Since a page walk implies a TLB miss, the number of TLB misses can be counted by counting the number of pagewalks.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.WALKS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Total page walks that are completed (I-side and D-side)",
+ "EdgeDetect": "1"
+ },
+ {
+ "PublicDescription": "This event counts every cycle when a data (D) page walk or instruction (I) page walk is in progress. Since a pagewalk implies a TLB miss, the approximate cost of a TLB miss can be determined from this event.",
+ "EventCode": "0x05",
+ "Counter": "0,1",
+ "UMask": "0x3",
+ "EventName": "PAGE_WALKS.CYCLES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Total cycles for all the page walks. (I-side and D-side)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/cache.json b/tools/perf/pmu-events/arch/x86/skylake/cache.json
new file mode 100644
index 000000000000..0551a9ba865d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/cache.json
@@ -0,0 +1,4299 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x11",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x12",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store instructions that miss the STLB.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load instructions with locked access.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x81",
+ "EventName": "MEM_INST_RETIRED.ALL_LOADS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired load instructions.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x82",
+ "EventName": "MEM_INST_RETIRED.ALL_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "All retired store instructions.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "L1_Hit_Indication": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions with L1 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions with L3 cache hits as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.L3_HIT",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions missed L1 cache as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.L1_MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions missed L1 cache as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Retired load instructions missed L2 cache as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions missed L3 cache as data sources.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_LOAD_RETIRED.L3_MISS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load instructions missed L3 cache as data sources",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready.",
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.FB_HIT",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_MISC_RETIRED.UC",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1"
+ },
+ {
+ "PublicDescription": "This event counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "EventCode": "0x51",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D.REPLACEMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D data line replacements",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand\n from the demand Hit FB, if it is allocated by hardware or software prefetch.\nNote: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "L1D miss outstandings duration in cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts duration of L1D miss outstanding in cycles.",
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts both cacheable and noncachaeble code read requests.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand and prefetch data reads",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, and so on.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Any memory transaction that reached the SQ.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.\nNote: A prefetch promoted to Demand is counted from the promotion point.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.\nNote: Writeback pending FIFO has six entries.",
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts L2 writebacks that access L2 cache.",
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANS.L2_WB",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts core-originated cacheable demand requests that miss the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "Errata": "SKL057",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts core-originated cacheable demand requests that refer to the last level cache (LLC). Demand requests include loads, RFOs, and hardware prefetches from L1D, and instruction fetches from IFU.",
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "Errata": "SKL057",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cache line split locks sent to the uncore.",
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of cache line split locks sent to uncore.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "EventCode": "0xB7, 0xBB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x21",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests that hit L2 cache. Only not rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe1",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand Data Read requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe2",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of L2 code requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe4",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 code requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of requests from the L2 hardware prefetchers.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf8",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x38",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xd8",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that hit L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x42",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RFO requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x22",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x44",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "L2 cache misses when fetching instructions.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x27",
+ "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand requests to L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe7",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Demand requests to L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "All requests that miss L2 cache.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All requests that miss L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "All L2 requests.",
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "All L2 requests",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.SILENT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared or Exclusive state. A non-threaded event.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.NON_SILENT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines are in Modified state. Modified lines are written back to L3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache.",
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.USELESS_PREF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "L2_LINES_IN.ALL",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "L2 cache lines filling L2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x48",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.USELESS_HWPF",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000018000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts any other requests that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts streaming stores that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts streaming stores that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts streaming stores that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts streaming stores that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand code reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts all demand data writes (RFOs) that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc01c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10001c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x04001c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoops to sibling cores hit in either E/S state and the line is not forwarded.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x02001c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoops sent to sibling cores return clean response.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x01001c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00801c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00401c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc0020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1000020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0400020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0200020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0100020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0080020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0040020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0000010001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts demand data reads that have any response type.",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/floating-point.json b/tools/perf/pmu-events/arch/x86/skylake/floating-point.json
new file mode 100644
index 000000000000..3c6b59af5d54
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/floating-point.json
@@ -0,0 +1,68 @@
+[
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "EventCode": "0xCA",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1e",
+ "EventName": "FP_ASSIST.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/frontend.json b/tools/perf/pmu-events/arch/x86/skylake/frontend.json
new file mode 100644
index 000000000000..e697dbd63e6e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/frontend.json
@@ -0,0 +1,472 @@
+[
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE_16B.IFDATA_STALL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ICACHE_64B.IFTAG_HIT",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ICACHE_64B.IFTAG_MISS",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x83",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ICACHE_64B.IFTAG_STALL",
+ "SampleAfterValue": "200003",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "IDQ.MITE_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "IDQ.DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x18",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x24",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding ?4 ? x? when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when:\n a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread\n\n b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions)\n \n c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >=3.",
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x9C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. \nMM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.\nPenalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 0?2 cycles.",
+ "EventCode": "0xAB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.L1I_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.L2_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.ITLB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x15",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.STLB_MISS",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x400206",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x200206",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x400406",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EdgeDetect": "1",
+ "EventName": "IDQ.MS_SWITCHES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the total number of uops delivered to Instruction Decode Queue (IDQ) while the Microcode Sequenser (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "EventCode": "0x79",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "IDQ.MS_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x400806",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x401006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x402006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x404006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x408006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x410006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x420006",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x100206",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC6",
+ "MSRValue": "0x300206",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
+ "MSRIndex": "0x3F7",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/memory.json b/tools/perf/pmu-events/arch/x86/skylake/memory.json
new file mode 100644
index 000000000000..d7fd5b06825b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/memory.json
@@ -0,0 +1,2309 @@
+[
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a flowmarker.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_EXEC.MISC2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_EXEC.MISC3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "RTM region detected inside HLE.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_EXEC.MISC4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "EventCode": "0x5d",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_EXEC.MISC5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we entered an HLE region\n does not count nested transactions.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "HLE_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution started.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution successfully committed",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one). ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "HLE_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "HLE_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.). ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "HLE_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we entered an RTM region\n does not count nested transactions.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RTM_RETIRED.START",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution started.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution successfully committed",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "Number of times RTM abort was triggered.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one). ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RTM_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RTM_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "EventCode": "0xC9",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RTM_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:\n1. memory disambiguation,\n2. external snoop, or\n3. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "SKL089",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50021",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20011",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 16 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 32 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x40",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2003",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1009",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x100",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "503",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
+ "EventCode": "0xCD",
+ "MSRValue": "0x200",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "101",
+ "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "TX_MEM.ABORT_CAPACITY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "EventCode": "0x54",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand Data Read requests who miss L3 cache",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x6",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x60",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with at least 6 Demand Data Read requests that miss L3 cache in the superQ.",
+ "CounterMask": "6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044008000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000408000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c8000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000108000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000088000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000048000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000028000 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "OTHER & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020800 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "STREAMING_STORES & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020100 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020080 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "PF_L3_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020004 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_CODE_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020002 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_RFO & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3ffc000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x043c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x023c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x013c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x00bc000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x007c000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3fc4000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & ANY_SNOOP",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HITM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0404000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_HIT_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_HIT_NO_FWD",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0204000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_MISS",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0104000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NOT_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NOT_NEEDED",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0084000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SNOOP_NONE",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x0044000001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SPL_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_MISS_LOCAL_DRAM & SPL_HIT",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000400001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L4_HIT_LOCAL_L4.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L4_HIT_LOCAL_L4 & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20001c0001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000100001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_S & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000080001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_E & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000040001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & L3_HIT_M & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2000020001 ",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NON_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "DEMAND_DATA_RD & SUPPLIER_NONE & SNOOP_NON_DRAM",
+ "Offcore": "1",
+ "CounterHTOff": "0,1,2,3"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/other.json b/tools/perf/pmu-events/arch/x86/skylake/other.json
new file mode 100644
index 000000000000..cfdc323acc82
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/other.json
@@ -0,0 +1,12 @@
+[
+ {
+ "PublicDescription": "This event counts the number of hardware interruptions received by the processor.",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "HW_INTERRUPTS.RECEIVED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of hardware interrupts received by the processor.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/pipeline.json b/tools/perf/pmu-events/arch/x86/skylake/pipeline.json
new file mode 100644
index 000000000000..0f7adb809be3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/pipeline.json
@@ -0,0 +1,939 @@
+[
+ {
+ "PublicDescription": "This event counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, this event counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. \nNotes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. \nCounting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Instructions retired from execution.",
+ "CounterHTOff": "Fixed counter 1"
+ },
+ {
+ "PublicDescription": "This event counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "PublicDescription": "This event counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x3",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CounterHTOff": "Fixed counter 3"
+ },
+ {
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEARS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts stalls occured due to changing prefix length (66, 67 or REX.W when they change the length of the decoded instruction). Occurrences counting is proportional to the number of prefixes in a 16B-line. This may result in the following penalties: three-cycle penalty for each LCP in a 16-byte chunk.",
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles checkpoints in Resource Allocation Table (RAT) are recovering from JEClear or machine clear.",
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts resource-related stall cycles. Reasons for stalls can be as follows:\n - *any* u-arch structure got full (LB, SB, RS, ROB, BOB, LM, Physical Register Reclaim Table (PRRT), or Physical History Table (PHT) slots)\n - *any* u-arch structure got empty (like INT/SIMD FreeLists)\n - FPU control word (FPCW), MXCSR\nand others. This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Resource-related stall cycles",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts stall cycles caused by the store buffer (SB) overflow (excluding draining from synch). This counts cycles that the pipeline backend blocked uop delivery from the front end.",
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.SB",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS).",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "EventCode": "0x0E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which the reservation station (RS) is empty for the thread.\nNote: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "EventCode": "0x5E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x5E",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Increments whenever there is an update to the LBR array.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of machine clears (nukes) of any type.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EdgeDetect": "1",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of machine clears (nukes) of any type. ",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "Errata": "SKL091, SKL044",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version (that is, uses PEBS) of the event that counts instructions retired.",
+ "EventCode": "0xC0",
+ "Counter": "1",
+ "UMask": "0x1",
+ "Errata": "SKL091, SKL044",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "CounterHTOff": "1"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts the number of retirement slots used.",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Retirement slots used.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts cycles without actually retired uops.",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts conditional branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts both direct and indirect near call instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all (macro) branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts return instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Return instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts not taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts taken branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Taken branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts far branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Far branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "Errata": "SKL091",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All (macro) branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted conditional branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "PublicDescription": "This event counts both taken and not taken retired mispredicted direct and indirect near calls, including both register and memory indirect.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted direct and indirect near call instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all mispredicted macro branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "SampleAfterValue": "400009",
+ "BriefDescription": "Mispredicted macro branch instructions retired. ",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Number of uops executed from any thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of uops executed on the core.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_EXECUTED.X87",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts the number of x87 uops dispatched.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "EXE_ACTIVITY.3_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 0.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 1.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 2.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 3.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 4.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 5.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts, on the per-thread basis, cycles during which uops are dispatched from the Reservation Station (RS) to port 7.",
+ "EventCode": "0xA1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Total execution stalls.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CounterMask": "8",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CounterMask": "12",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by asm inspection of the nearby instructions.",
+ "EventCode": "0x4C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts how many times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when:\n - preceding store conflicts with the load (incomplete overlap)\n\n - store forwarding is impossible due to u-arch limitations\n\n - preceding lock RMW operations are not forwarded\n\n - store has the no-forward bit set (uncacheable/page-split/masked stores)\n\n - all-blocking stores are used (mostly, fences and port I/O)\n\nand others.\nThe most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events.\nSee the table of not supported store forwards in the Optimization Guide.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded .",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "EventCode": "0x03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "EventCode": "0x07",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x5",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "CounterMask": "5",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CounterMask": "16",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x14",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CounterMask": "20",
+ "CounterHTOff": "0,1,2,3"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2503",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PEBS": "2",
+ "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,2,3",
+ "UMask": "0x1",
+ "Errata": "SKL091, SKL044",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
+ "CounterMask": "10",
+ "CounterHTOff": "0,2,3"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIVIDER_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xC1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "EventName": "OTHER_ASSISTS.ANY",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Number of times a microcode assist is invoked by HW other than FP-assist. Examples include AD (page Access Dirty) and AVX* related assists.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register.\r\nFor more information, refer to ?Mixing Intel AVX and Intel SSE Code? section of the Optimization Guide.",
+ "EventCode": "0x0E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x00",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x2",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "Fixed counter 2"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2503",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x0D",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CounterMask": "2",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CounterMask": "3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CounterMask": "4",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EdgeDetect": "1",
+ "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "2503",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "2503",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "2503",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/skylake/virtual-memory.json
new file mode 100644
index 000000000000..02f32cbf6789
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/virtual-memory.json
@@ -0,0 +1,272 @@
+[
+ {
+ "PublicDescription": "This event counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts load misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a load. EPT page walk duration are excluded in Skylake. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause page walks of any page size (4K/2M/4M/1G).",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (4K page size). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (1G)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "SampleAfterValue": "2000003",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake. ",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Stores that miss the DTLB and hit the STLB.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of DTLB flush attempts of the thread-specific entries.",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "PublicDescription": "This event counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, and so on).",
+ "EventCode": "0xBD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "SampleAfterValue": "100007",
+ "BriefDescription": "STLB flush attempts",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store. EPT page walk duration are excluded in Skylake. ",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a load. EPT page walk duration are excluded in Skylake. ",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "ITLB_MISSES.WALK_ACTIVE",
+ "SampleAfterValue": "100003",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
+ "CounterMask": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/cache.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/cache.json
new file mode 100644
index 000000000000..6e61ae20d01a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/cache.json
@@ -0,0 +1,2817 @@
+[
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CACHE_LOCK_CYCLES.L1D",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D locked"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CACHE_LOCK_CYCLES.L1D_L2",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D and L2 locked"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D.M_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines replaced in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D.M_REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines allocated in the M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D.M_SNOOP_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D snoop eviction of cache lines in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D.REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache lines allocated"
+ },
+ {
+ "EventCode": "0x52",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_PREFETCH_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D prefetch load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_PREFETCH.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch misses"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_PREFETCH.REQUESTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_PREFETCH.TRIGGERS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests triggered"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D_WB_L2.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in E state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_WB_L2.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in I state (misses)"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D_WB_L2.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in M state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L1D_WB_L2.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L1 writebacks to L2"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_WB_L2.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_DATA_RQSTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_DATA_RQSTS.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_DATA_RQSTS.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_DATA_RQSTS.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_DATA_RQSTS.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_DATA_RQSTS.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data prefetches"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the S state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines alloacated"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the E state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the S state"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_LINES_OUT.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PREFETCH_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PREFETCH_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.IFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.IFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.IFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.LD_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_RQSTS.LD_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.LOADS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xaa",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PREFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PREFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.PREFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 prefetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.RFOS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO requests"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANSACTIONS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANSACTIONS.FILL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 fill transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANSACTIONS.IFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANSACTIONS.L1D_WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D writeback to L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANSACTIONS.LOAD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 Load transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANSACTIONS.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANSACTIONS.RFO",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANSACTIONS.WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 writeback to LLC transactions"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_WRITE.LOCK.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in E state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe0",
+ "EventName": "L2_WRITE.LOCK.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_WRITE.LOCK.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_WRITE.LOCK.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_WRITE.LOCK.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_WRITE.LOCK.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in S state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "L2_WRITE.RFO.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_WRITE.RFO.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_WRITE.RFO.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_WRITE.RFO.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_WRITE.RFO.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in S state"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Longest latency cache miss"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Longest latency cache reference"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_INST_RETIRED.LOADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a load (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_INST_RETIRED.STORES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a store (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.HIT_LFB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss L1D and hit an previously allocated LFB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1D_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired loads that hit the L1 data cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.LLC_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.LLC_UNSHARED_HIT",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit valid versions in the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event)"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OFFCORE_REQUESTS.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ANY.READ",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS.ANY.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OFFCORE_REQUESTS.L1D_WRITEBACK",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore L1 data cache writebacks"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore reads busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand code reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand code read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand data reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand data read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand RFOs"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand RFOs busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_SQ_FULL",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests blocked due to Super Queue full"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SQ_MISC.LRU_HINTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue LRU hints sent to LLC"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue lock splits across a cache line"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "STORE_BLOCKS.AT_RET",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads delayed with at-Retirement block code"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "STORE_BLOCKS.L1D_BLOCK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cacheable loads delayed with L1D block code"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x0",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Memory instructions retired above 0 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x400",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100",
+ "BriefDescription": "Memory instructions retired above 1024 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1000",
+ "BriefDescription": "Memory instructions retired above 128 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Memory instructions retired above 16 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5",
+ "BriefDescription": "Memory instructions retired above 16384 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x800",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50",
+ "BriefDescription": "Memory instructions retired above 2048 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "500",
+ "BriefDescription": "Memory instructions retired above 256 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5000",
+ "BriefDescription": "Memory instructions retired above 32 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "3",
+ "BriefDescription": "Memory instructions retired above 32768 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50000",
+ "BriefDescription": "Memory instructions retired above 4 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x1000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20",
+ "BriefDescription": "Memory instructions retired above 4096 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "200",
+ "BriefDescription": "Memory instructions retired above 512 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Memory instructions retired above 64 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Memory instructions retired above 8 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x2000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10",
+ "BriefDescription": "Memory instructions retired above 8192 clocks (Precise Event)"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x111",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x211",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x411",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x711",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f44",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff44",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x144",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x444",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x744",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x50ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7fff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xffff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x80ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f22",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff22",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x222",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x422",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x722",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x108",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x208",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x408",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x708",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f77",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff77",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x177",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x277",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x477",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x777",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f33",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff33",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x133",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x233",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x433",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x733",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x403",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x703",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f01",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff01",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x101",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x201",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x401",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x701",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f04",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff04",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x104",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x204",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x404",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x704",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f02",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff02",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x102",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x202",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x402",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x702",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x180",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x280",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x480",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x780",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f50",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff50",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x150",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x250",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x450",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x750",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x110",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x210",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x410",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x710",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f40",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff40",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x140",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x440",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x740",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x220",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x420",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x720",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ALL_LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = ALL_LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7f70",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = ANY_CACHE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xff70",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = ANY_LOCATION",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = IO_CSR_MMIO",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x170",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = LLC_HIT_NO_OTHER_CORE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x270",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x470",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = LLC_HIT_OTHER_CORE_HITM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x770",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = LOCAL_CACHE",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = LOCAL_DRAM AND REMOTE_CACHE_HIT",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = REMOTE_CACHE_HITM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json
new file mode 100644
index 000000000000..7d2f71a9dee3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json
@@ -0,0 +1,229 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.ALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.INPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.OUTPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists for invalid output value (Precise Event)"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_COMP_OPS_EXE.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MMX Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP double precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE and SSE2 FP Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_PACKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP packed Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_SCALAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP scalar Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP single precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_COMP_OPS_EXE.SSE2_INTEGER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE2 integer Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Computational floating-point operations executed"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_MMX_TRANS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Floating Point to and from MMX transitions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_MMX_TRANS.TO_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from MMX to Floating Point instructions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_MMX_TRANS.TO_MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from Floating Point to MMX instructions"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_128.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer pack operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_128.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer arithmetic operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_128.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer logical operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_128.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer multiply operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_128.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shift operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_128.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shuffle/move operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_128.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer unpack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_64.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit pack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_64.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit arithmetic operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_64.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit logical operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_64.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit packed multiply operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_64.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shift operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_64.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shuffle/move operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_64.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit unpack operations"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/frontend.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/frontend.json
new file mode 100644
index 000000000000..e5e21e03444d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions decoded"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.FUSIONS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused instructions decoded"
+ },
+ {
+ "EventCode": "0x19",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TWO_UOP_INSTS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Two Uop instructions decoded"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/memory.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/memory.json
new file mode 100644
index 000000000000..6e0829b7617f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/memory.json
@@ -0,0 +1,758 @@
+[
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Misaligned store references"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_DATA read and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY IFETCH and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x30ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf8ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x40ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20ff",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY_REQUEST and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = ANY RFO and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = CORE_WB and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IFETCH and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DATA_IN and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_DATA_RD and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_IFETCH and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = DEMAND_RFO and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = OTHER and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_DATA_RD and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_RFO and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PF_IFETCH and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x3070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_DRAM_AND_REMOTE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = ANY_DRAM AND REMOTE_FWD",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xf870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = ANY_LLC_MISS",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.OTHER_LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = OTHER_LOCAL_DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "REQUEST = PREFETCH and RESPONSE = REMOTE_DRAM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/other.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/other.json
new file mode 100644
index 000000000000..85133d6a5ce0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/other.json
@@ -0,0 +1,287 @@
+[
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_CLEARS.EARLY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Early Branch Prediciton Unit clears"
+ },
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BPU_CLEARS.LATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Late Branch Prediction Unit clears"
+ },
+ {
+ "EventCode": "0xE5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_MISSED_CALL_RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch prediction unit missed call or return"
+ },
+ {
+ "EventCode": "0xD5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ES_REG_RENAMES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ES segment renames"
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IO_TRANSACTIONS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "I/O transactions"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1I.CYCLES_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch stall cycles"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1I.HITS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch hits"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1I.MISSES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch misses"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L1I.READS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I Instruction fetches"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LARGE_ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Large ITLB hit"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_BLOCK.OVERLAP_STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads that partially overlap an earlier store"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "LOAD_DISPATCH.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All loads dispatched"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LOAD_DISPATCH.MOB",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_DISPATCH.RS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched that bypass the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_DISPATCH.RS_DELAYED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from stage 305"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PARTIAL_ADDRESS_ALIAS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "False dependencies due to partial address aliasing"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RAT_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All RAT stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RAT_STALLS.FLAGS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Flag stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RAT_STALLS.REGISTERS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Partial register stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RAT_STALLS.ROB_READ_PORT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB read port stalls cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RAT_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Scoreboard stall cycles"
+ },
+ {
+ "EventCode": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "SB_DRAIN.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All Store buffer stall cycles"
+ },
+ {
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SEG_RENAME_STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Segment rename stall cycles"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOP_RESPONSE.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HIT to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOP_RESPONSE.HITE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITE to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOP_RESPONSE.HITM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITM to snoop"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS.CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop code requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS.DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop data requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS.INVALIDATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop code requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop code requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop data requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop data requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop invalidate requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xF6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SQ_FULL_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue full stall cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/pipeline.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/pipeline.json
new file mode 100644
index 000000000000..f130510f7616
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/pipeline.json
@@ -0,0 +1,899 @@
+[
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy"
+ },
+ {
+ "EventCode": "0x14",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIV",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide Operations executed",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.MUL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BACLEAR.BAD_TARGET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted with bad target address"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR.CLEAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted, regardless of cause "
+ },
+ {
+ "EventCode": "0xA7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR_FORCE_IQ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction queue forced BACLEAR"
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_INST_EXEC.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_EXEC.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Conditional branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_EXEC.DIRECT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Unconditional branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Unconditional call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_INST_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_INST_EXEC.NON_CALLS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect return branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_EXEC.TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired conditional branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Retired near call instructions (Precise Event)"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_MISP_EXEC.ANY",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_EXEC.COND",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_EXEC.DIRECT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted unconditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_MISP_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_MISP_EXEC.NON_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted return branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_MISP_EXEC.TAKEN",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional retired branches (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted near retired calls (Precise Event)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_P",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total CPU cycles",
+ "CounterMask": "2"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "ILD_STALL.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Any Instruction Length Decoder stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction Queue full stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Length Change Prefix stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ILD_STALL.MRU",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stall cycles due to BPU MRU bypass"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ILD_STALL.REGEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Regen stall cycles"
+ },
+ {
+ "EventCode": "0x18",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_DECODED.DEC0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions that must be decoded by decoder 0"
+ },
+ {
+ "EventCode": "0x1E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles instructions are written to the instruction queue"
+ },
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions written to instruction queue."
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (fixed counter)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (Programmable counter and Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "INST_RETIRED.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired MMX instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired floating-point operations (Precise Event)"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load operations conflicting with software prefetches"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xA8",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.INACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD_OVERFLOW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loops that can't stream from the instruction queue"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Cycles machine clear asserted"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEM_ORDER",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Execution pipeline restart due to Memory ordering conflicts"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RESOURCE_STALLS.FPCW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FPU control word write stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LOAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Load buffer stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS.MXCSR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MXCSR rename stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RESOURCE_STALLS.OTHER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Other Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reservation Station full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.STORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Store buffer stall cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SSEX_UOPS_RETIRED.VECTOR_INTEGER",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Vector Integer Uops retired (Precise Event)"
+ },
+ {
+ "EventCode": "0xDB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOP_UNFUSION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uop unfusions due to FP exceptions"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DECODED.ESP_FOLDING",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer instructions decoded"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DECODED.ESP_SYNC",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer sync operations"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DECODED.MS_CYCLES_ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops decoded by Microcode Sequencer",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xD1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DECODED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops are decoded",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on any port (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.PORT0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 0"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 0, 1 or 5"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0, 1 or 5",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.PORT1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT2_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 2 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT234_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 2, 3 or 4"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT3_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 3 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT4_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 4 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED.PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 5"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued on any thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CYCLES_ALL_THREADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops were issued on either thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Fused Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are being retired",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retirement slots used (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are not retiring (Precise Event)",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles using precise uop retired event (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/virtual-memory.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/virtual-memory.json
new file mode 100644
index 000000000000..57b53562e2bd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/virtual-memory.json
@@ -0,0 +1,173 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load misses"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_LOAD_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss large page walks"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss caused by low part of address"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB second level hit"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walks complete"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walk cycles"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss large page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses casued by low part of address"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB first level misses but second level hit"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB miss page walk cycles"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Extended Page Table walk cycles"
+ },
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_FLUSH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB flushes"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISS_RETIRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired instructions that missed the ITLB (Precise Event)"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "ITLB_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss large page walks"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss page walks"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB miss page walk cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_STORE_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired stores that miss the DTLB (Precise Event)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json
new file mode 100644
index 000000000000..dad20f0e3cac
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json
@@ -0,0 +1,3233 @@
+[
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CACHE_LOCK_CYCLES.L1D",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D locked"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CACHE_LOCK_CYCLES.L1D_L2",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D and L2 locked"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D.M_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines replaced in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D.M_REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines allocated in the M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D.M_SNOOP_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D snoop eviction of cache lines in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D.REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache lines allocated"
+ },
+ {
+ "EventCode": "0x52",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_PREFETCH_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D prefetch load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_PREFETCH.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch misses"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_PREFETCH.REQUESTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_PREFETCH.TRIGGERS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests triggered"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D_WB_L2.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in E state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_WB_L2.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in I state (misses)"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D_WB_L2.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in M state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L1D_WB_L2.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L1 writebacks to L2"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_WB_L2.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_DATA_RQSTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_DATA_RQSTS.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_DATA_RQSTS.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_DATA_RQSTS.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_DATA_RQSTS.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_DATA_RQSTS.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data prefetches"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the S state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines alloacated"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the E state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the S state"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_LINES_OUT.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PREFETCH_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PREFETCH_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.IFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.IFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.IFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.LD_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_RQSTS.LD_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.LOADS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xaa",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PREFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PREFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.PREFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 prefetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.RFOS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO requests"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANSACTIONS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANSACTIONS.FILL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 fill transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANSACTIONS.IFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANSACTIONS.L1D_WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D writeback to L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANSACTIONS.LOAD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 Load transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANSACTIONS.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANSACTIONS.RFO",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANSACTIONS.WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 writeback to LLC transactions"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_WRITE.LOCK.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in E state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe0",
+ "EventName": "L2_WRITE.LOCK.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_WRITE.LOCK.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_WRITE.LOCK.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_WRITE.LOCK.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_WRITE.LOCK.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in S state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "L2_WRITE.RFO.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_WRITE.RFO.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_WRITE.RFO.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_WRITE.RFO.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_WRITE.RFO.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in S state"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Longest latency cache miss"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Longest latency cache reference"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_INST_RETIRED.LOADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a load (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_INST_RETIRED.STORES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a store (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.HIT_LFB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss L1D and hit an previously allocated LFB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1D_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired loads that hit the L1 data cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.LLC_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.LLC_UNSHARED_HIT",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit valid versions in the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_UNCORE_RETIRED.LOCAL_DRAM",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Load instructions retired with a data source of local DRAM or locally homed remote hitm (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_UNCORE_RETIRED.OTHER_CORE_L2_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Load instructions retired that HIT modified data in sibling core (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_CACHE_LOCAL_HOME_HIT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Load instructions retired remote cache HIT data source (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_DRAM",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Load instructions retired remote DRAM and remote home-remote cache HITM (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_UNCORE_RETIRED.UNCACHEABLE",
+ "SampleAfterValue": "4000",
+ "BriefDescription": "Load instructions retired IO (Precise Event)"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OFFCORE_REQUESTS.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ANY.READ",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS.ANY.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OFFCORE_REQUESTS.L1D_WRITEBACK",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore L1 data cache writebacks"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "OFFCORE_REQUESTS.UNCACHED_MEM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore uncached memory accesses"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore reads busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand code reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand code read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand data reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand data read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand RFOs"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand RFOs busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_SQ_FULL",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests blocked due to Super Queue full"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SQ_MISC.LRU_HINTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue LRU hints sent to LLC"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue lock splits across a cache line"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "STORE_BLOCKS.AT_RET",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads delayed with at-Retirement block code"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "STORE_BLOCKS.L1D_BLOCK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cacheable loads delayed with L1D block code"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x0",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Memory instructions retired above 0 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x400",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100",
+ "BriefDescription": "Memory instructions retired above 1024 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1000",
+ "BriefDescription": "Memory instructions retired above 128 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Memory instructions retired above 16 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5",
+ "BriefDescription": "Memory instructions retired above 16384 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x800",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50",
+ "BriefDescription": "Memory instructions retired above 2048 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "500",
+ "BriefDescription": "Memory instructions retired above 256 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5000",
+ "BriefDescription": "Memory instructions retired above 32 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "3",
+ "BriefDescription": "Memory instructions retired above 32768 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50000",
+ "BriefDescription": "Memory instructions retired above 4 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x1000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20",
+ "BriefDescription": "Memory instructions retired above 4096 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "200",
+ "BriefDescription": "Memory instructions retired above 512 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Memory instructions retired above 64 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Memory instructions retired above 8 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x2000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10",
+ "BriefDescription": "Memory instructions retired above 8192 clocks (Precise Event)"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF11",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x111",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x211",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x411",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x711",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2711",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F44",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF44",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x144",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x244",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x444",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x744",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2744",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7FFF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFFFF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x80FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x27FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x18FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x58FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x10FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F22",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF22",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x122",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x222",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x422",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x722",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2722",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF08",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore writebacks",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x108",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x408",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x708",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2708",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F77",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF77",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code or data read requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x177",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x277",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x477",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x777",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2777",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F33",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any cache_dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF33",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any location",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x133",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x233",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x433",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x733",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2733",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HIT in a remote cache ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF03",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x103",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x203",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x403",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x703",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2703",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F01",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF01",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x101",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x201",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x401",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x701",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2701",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F04",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF04",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x104",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x204",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x404",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x704",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2704",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F02",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF02",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x102",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x202",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x402",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x702",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2702",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore other requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x180",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x280",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x480",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x780",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2780",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F50",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF50",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x150",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x250",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x450",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x750",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2750",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x110",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x210",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x410",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x710",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2710",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F40",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF40",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x140",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x240",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x440",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x740",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2740",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x120",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x220",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x420",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x720",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2720",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x7F70",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xFF70",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x8070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x170",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x270",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x470",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x770",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2770",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x5870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x1070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HITM in a remote cache",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json
new file mode 100644
index 000000000000..7d2f71a9dee3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json
@@ -0,0 +1,229 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.ALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.INPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.OUTPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists for invalid output value (Precise Event)"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_COMP_OPS_EXE.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MMX Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP double precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE and SSE2 FP Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_PACKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP packed Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_SCALAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP scalar Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP single precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_COMP_OPS_EXE.SSE2_INTEGER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE2 integer Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Computational floating-point operations executed"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_MMX_TRANS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Floating Point to and from MMX transitions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_MMX_TRANS.TO_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from MMX to Floating Point instructions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_MMX_TRANS.TO_MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from Floating Point to MMX instructions"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_128.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer pack operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_128.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer arithmetic operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_128.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer logical operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_128.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer multiply operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_128.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shift operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_128.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shuffle/move operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_128.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer unpack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_64.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit pack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_64.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit arithmetic operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_64.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit logical operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_64.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit packed multiply operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_64.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shift operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_64.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shuffle/move operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_64.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit unpack operations"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/frontend.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/frontend.json
new file mode 100644
index 000000000000..e5e21e03444d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions decoded"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.FUSIONS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused instructions decoded"
+ },
+ {
+ "EventCode": "0x19",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TWO_UOP_INSTS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Two Uop instructions decoded"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/memory.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/memory.json
new file mode 100644
index 000000000000..90eb6aac357b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/memory.json
@@ -0,0 +1,739 @@
+[
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF811",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4011",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF844",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4044",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x60FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF8FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x20FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x40FF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF822",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4022",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF808",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4008",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF877",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4077",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF833",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any LLC miss",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the local DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4033",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF803",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4003",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF801",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4001",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF804",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4004",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF802",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4002",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF880",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4080",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF850",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4050",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF810",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4010",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF840",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4040",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF820",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4020",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x6070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0xF870",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x2070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7, 0xBB",
+ "MSRValue": "0x4070",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/other.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/other.json
new file mode 100644
index 000000000000..85133d6a5ce0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/other.json
@@ -0,0 +1,287 @@
+[
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_CLEARS.EARLY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Early Branch Prediciton Unit clears"
+ },
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BPU_CLEARS.LATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Late Branch Prediction Unit clears"
+ },
+ {
+ "EventCode": "0xE5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_MISSED_CALL_RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch prediction unit missed call or return"
+ },
+ {
+ "EventCode": "0xD5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ES_REG_RENAMES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ES segment renames"
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IO_TRANSACTIONS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "I/O transactions"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1I.CYCLES_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch stall cycles"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1I.HITS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch hits"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1I.MISSES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch misses"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L1I.READS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I Instruction fetches"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LARGE_ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Large ITLB hit"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_BLOCK.OVERLAP_STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads that partially overlap an earlier store"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "LOAD_DISPATCH.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All loads dispatched"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LOAD_DISPATCH.MOB",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_DISPATCH.RS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched that bypass the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_DISPATCH.RS_DELAYED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from stage 305"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PARTIAL_ADDRESS_ALIAS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "False dependencies due to partial address aliasing"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RAT_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All RAT stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RAT_STALLS.FLAGS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Flag stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RAT_STALLS.REGISTERS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Partial register stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RAT_STALLS.ROB_READ_PORT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB read port stalls cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RAT_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Scoreboard stall cycles"
+ },
+ {
+ "EventCode": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "SB_DRAIN.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All Store buffer stall cycles"
+ },
+ {
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SEG_RENAME_STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Segment rename stall cycles"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOP_RESPONSE.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HIT to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOP_RESPONSE.HITE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITE to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOP_RESPONSE.HITM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITM to snoop"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS.CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop code requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS.DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop data requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS.INVALIDATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop code requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop code requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop data requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop data requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop invalidate requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xF6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SQ_FULL_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue full stall cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/pipeline.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/pipeline.json
new file mode 100644
index 000000000000..f130510f7616
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/pipeline.json
@@ -0,0 +1,899 @@
+[
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy"
+ },
+ {
+ "EventCode": "0x14",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIV",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide Operations executed",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.MUL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BACLEAR.BAD_TARGET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted with bad target address"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR.CLEAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted, regardless of cause "
+ },
+ {
+ "EventCode": "0xA7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR_FORCE_IQ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction queue forced BACLEAR"
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_INST_EXEC.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_EXEC.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Conditional branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_EXEC.DIRECT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Unconditional branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Unconditional call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_INST_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_INST_EXEC.NON_CALLS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect return branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_EXEC.TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired conditional branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Retired near call instructions (Precise Event)"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_MISP_EXEC.ANY",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_EXEC.COND",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_EXEC.DIRECT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted unconditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_MISP_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_MISP_EXEC.NON_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted return branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_MISP_EXEC.TAKEN",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional retired branches (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted near retired calls (Precise Event)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_P",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total CPU cycles",
+ "CounterMask": "2"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "ILD_STALL.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Any Instruction Length Decoder stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction Queue full stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Length Change Prefix stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ILD_STALL.MRU",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stall cycles due to BPU MRU bypass"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ILD_STALL.REGEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Regen stall cycles"
+ },
+ {
+ "EventCode": "0x18",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_DECODED.DEC0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions that must be decoded by decoder 0"
+ },
+ {
+ "EventCode": "0x1E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles instructions are written to the instruction queue"
+ },
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions written to instruction queue."
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (fixed counter)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (Programmable counter and Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "INST_RETIRED.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired MMX instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired floating-point operations (Precise Event)"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load operations conflicting with software prefetches"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xA8",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.INACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD_OVERFLOW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loops that can't stream from the instruction queue"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Cycles machine clear asserted"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEM_ORDER",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Execution pipeline restart due to Memory ordering conflicts"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RESOURCE_STALLS.FPCW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FPU control word write stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LOAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Load buffer stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS.MXCSR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MXCSR rename stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RESOURCE_STALLS.OTHER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Other Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reservation Station full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.STORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Store buffer stall cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SSEX_UOPS_RETIRED.VECTOR_INTEGER",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Vector Integer Uops retired (Precise Event)"
+ },
+ {
+ "EventCode": "0xDB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOP_UNFUSION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uop unfusions due to FP exceptions"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DECODED.ESP_FOLDING",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer instructions decoded"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DECODED.ESP_SYNC",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer sync operations"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DECODED.MS_CYCLES_ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops decoded by Microcode Sequencer",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xD1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DECODED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops are decoded",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on any port (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.PORT0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 0"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 0, 1 or 5"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0, 1 or 5",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.PORT1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT2_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 2 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT234_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 2, 3 or 4"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT3_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 3 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT4_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 4 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED.PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 5"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued on any thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CYCLES_ALL_THREADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops were issued on either thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Fused Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are being retired",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retirement slots used (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are not retiring (Precise Event)",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles using precise uop retired event (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/virtual-memory.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/virtual-memory.json
new file mode 100644
index 000000000000..2153b3f5d7b0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/virtual-memory.json
@@ -0,0 +1,149 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load misses"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss caused by low part of address"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB second level hit"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walks complete"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walk cycles"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss large page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB first level misses but second level hit"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB miss page walk cycles"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Extended Page Table walk cycles"
+ },
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_FLUSH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB flushes"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISS_RETIRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired instructions that missed the ITLB (Precise Event)"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss page walks"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB miss page walk cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_STORE_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired stores that miss the DTLB (Precise Event)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/cache.json b/tools/perf/pmu-events/arch/x86/westmereex/cache.json
new file mode 100644
index 000000000000..f9bc7fdd48d6
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/cache.json
@@ -0,0 +1,3225 @@
+[
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "CACHE_LOCK_CYCLES.L1D",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D locked"
+ },
+ {
+ "EventCode": "0x63",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "CACHE_LOCK_CYCLES.L1D_L2",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles L1D and L2 locked"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D.M_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines replaced in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D.M_REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D cache lines allocated in the M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x8",
+ "EventName": "L1D.M_SNOOP_EVICT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D snoop eviction of cache lines in M state"
+ },
+ {
+ "EventCode": "0x51",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D.REPL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1 data cache lines allocated"
+ },
+ {
+ "EventCode": "0x52",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_CACHE_PREFETCH_LOCK_FB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1D prefetch load lock accepted in fill buffer"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x2",
+ "EventName": "L1D_PREFETCH.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch misses"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "L1D_PREFETCH.REQUESTS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests"
+ },
+ {
+ "EventCode": "0x4E",
+ "Counter": "0,1",
+ "UMask": "0x4",
+ "EventName": "L1D_PREFETCH.TRIGGERS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D hardware prefetch requests triggered"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1D_WB_L2.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in E state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1D_WB_L2.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in I state (misses)"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L1D_WB_L2.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in M state"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L1D_WB_L2.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L1 writebacks to L2"
+ },
+ {
+ "EventCode": "0x28",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1D_WB_L2.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L1 writebacks to L2 in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_DATA_RQSTS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_DATA_RQSTS.DEMAND.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_DATA_RQSTS.DEMAND.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_DATA_RQSTS.DEMAND.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_DATA_RQSTS.DEMAND.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand requests"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_DATA_RQSTS.DEMAND.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data demand loads in S state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.E_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in E state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.I_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the I state (misses)"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.M_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in M state"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.MESI",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 data prefetches"
+ },
+ {
+ "EventCode": "0x26",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_DATA_RQSTS.PREFETCH.S_STATE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 data prefetches in the S state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "L2_LINES_IN.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines alloacated"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_IN.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the E state"
+ },
+ {
+ "EventCode": "0xF1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_IN.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines allocated in the S state"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_LINES_OUT.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_LINES_OUT.DEMAND_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_LINES_OUT.DEMAND_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a demand request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_LINES_OUT.PREFETCH_CLEAN",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0xF2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_LINES_OUT.PREFETCH_DIRTY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 modified lines evicted by a prefetch request"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_RQSTS.IFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_RQSTS.IFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "L2_RQSTS.IFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_RQSTS.LD_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_RQSTS.LD_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 load misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L2_RQSTS.LOADS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xaa",
+ "EventName": "L2_RQSTS.MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_RQSTS.PREFETCH_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_RQSTS.PREFETCH_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc0",
+ "EventName": "L2_RQSTS.PREFETCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 prefetches"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xff",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 requests"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO hits"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO misses"
+ },
+ {
+ "EventCode": "0x24",
+ "Counter": "0,1,2,3",
+ "UMask": "0xc",
+ "EventName": "L2_RQSTS.RFOS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO requests"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_TRANSACTIONS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_TRANSACTIONS.FILL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 fill transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L2_TRANSACTIONS.IFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 instruction fetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_TRANSACTIONS.L1D_WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L1D writeback to L2 transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_TRANSACTIONS.LOAD",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 Load transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_TRANSACTIONS.PREFETCH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 prefetch transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_TRANSACTIONS.RFO",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 RFO transactions"
+ },
+ {
+ "EventCode": "0xF0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_TRANSACTIONS.WB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "L2 writeback to LLC transactions"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "L2_WRITE.LOCK.E_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in E state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe0",
+ "EventName": "L2_WRITE.LOCK.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "L2_WRITE.LOCK.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "L2_WRITE.LOCK.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf0",
+ "EventName": "L2_WRITE.LOCK.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All demand L2 lock RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "L2_WRITE.LOCK.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand lock RFOs in S state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xe",
+ "EventName": "L2_WRITE.RFO.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs that hit the cache"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L2_WRITE.RFO.I_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in I state (misses)"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "L2_WRITE.RFO.M_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in M state"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "L2_WRITE.RFO.MESI",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All L2 demand store RFOs"
+ },
+ {
+ "EventCode": "0x27",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L2_WRITE.RFO.S_STATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "L2 demand store RFOs in S state"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x41",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Longest latency cache miss"
+ },
+ {
+ "EventCode": "0x2E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4f",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Longest latency cache reference"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_INST_RETIRED.LOADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a load (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_INST_RETIRED.STORES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired which contains a store (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "MEM_LOAD_RETIRED.HIT_LFB",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss L1D and hit an previously allocated LFB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_LOAD_RETIRED.L1D_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired loads that hit the L1 data cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that hit the L2 cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "MEM_LOAD_RETIRED.LLC_MISS",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Retired loads that miss the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_LOAD_RETIRED.LLC_UNSHARED_HIT",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit valid versions in the LLC cache (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MEM_UNCORE_RETIRED.LOCAL_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Load instructions retired that HIT modified data in sibling core (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "MEM_UNCORE_RETIRED.LOCAL_DRAM_AND_REMOTE_CACHE_HIT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Load instructions retired local dram and remote cache HIT data sources (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_DRAM",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Load instructions retired remote DRAM and remote home-remote cache HITM (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_UNCORE_RETIRED.UNCACHEABLE",
+ "SampleAfterValue": "4000",
+ "BriefDescription": "Load instructions retired IO (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MEM_UNCORE_RETIRED.REMOTE_HITM",
+ "SampleAfterValue": "40000",
+ "BriefDescription": "Retired loads that hit remote socket in modified state (Precise Event)"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "OFFCORE_REQUESTS.ANY",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS.ANY.READ",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "OFFCORE_REQUESTS.ANY.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.READ_DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data read requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS.DEMAND.RFO",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests"
+ },
+ {
+ "EventCode": "0xB0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "OFFCORE_REQUESTS.L1D_WRITEBACK",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore L1 data cache writebacks"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x8",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ANY.READ_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore reads busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand code reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x2",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand code read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand data reads"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand data read busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding offcore demand RFOs"
+ },
+ {
+ "EventCode": "0x60",
+ "UMask": "0x4",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles offcore demand RFOs busy",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_REQUESTS_SQ_FULL",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests blocked due to Super Queue full"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SQ_MISC.LRU_HINTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue LRU hints sent to LLC"
+ },
+ {
+ "EventCode": "0xF4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue lock splits across a cache line"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "STORE_BLOCKS.AT_RET",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads delayed with at-Retirement block code"
+ },
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "STORE_BLOCKS.L1D_BLOCK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Cacheable loads delayed with L1D block code"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x0",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Memory instructions retired above 0 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x400",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "100",
+ "BriefDescription": "Memory instructions retired above 1024 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x80",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "1000",
+ "BriefDescription": "Memory instructions retired above 128 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x10",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10000",
+ "BriefDescription": "Memory instructions retired above 16 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5",
+ "BriefDescription": "Memory instructions retired above 16384 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x800",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50",
+ "BriefDescription": "Memory instructions retired above 2048 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x100",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "500",
+ "BriefDescription": "Memory instructions retired above 256 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x20",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "5000",
+ "BriefDescription": "Memory instructions retired above 32 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "3",
+ "BriefDescription": "Memory instructions retired above 32768 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x4",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "50000",
+ "BriefDescription": "Memory instructions retired above 4 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x1000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20",
+ "BriefDescription": "Memory instructions retired above 4096 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x200",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "200",
+ "BriefDescription": "Memory instructions retired above 512 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x40",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Memory instructions retired above 64 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x8",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Memory instructions retired above 8 clocks (Precise Event)"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xB",
+ "MSRValue": "0x2000",
+ "Counter": "3",
+ "UMask": "0x10",
+ "EventName": "MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192",
+ "MSRIndex": "0x3F6",
+ "SampleAfterValue": "10",
+ "BriefDescription": "Memory instructions retired above 8192 clocks (Precise Event)"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF11",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x111",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x211",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x411",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4711",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF44",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x144",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x244",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x444",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4744",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFFFF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x80FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x47FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x18FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x38FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x10FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF22",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x122",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x222",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x422",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4722",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF08",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore writebacks",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x108",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x408",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4708",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF77",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore code or data read requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x177",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x277",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x477",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4777",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any cache_dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF33",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any location",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x133",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x233",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x433",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4733",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = local cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = remote cache or dram",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HIT in a remote cache ",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF03",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x103",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x203",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x403",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4703",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF01",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x101",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x201",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x401",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4701",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF04",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x104",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x204",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x404",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4704",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF02",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore demand RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x102",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x202",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x402",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4702",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF80",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore other requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x180",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x280",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x480",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4780",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any cache or DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF30",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the IO, CSR, MMIO unit.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x130",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x230",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x430",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4730",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF10",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch data reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x110",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x210",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x410",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4710",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF40",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch code reads",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x140",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x240",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x440",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4740",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF20",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch RFO requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x120",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x220",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x420",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4720",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that HITM in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x7F70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any cache or DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xFF70",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LOCATION",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "All offcore prefetch requests",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x8070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.IO_CSR_MMIO",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the IO, CSR, MMIO unit",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x170",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_NO_OTHER_CORE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and not found in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x270",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HIT in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x470",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LLC_HIT_OTHER_CORE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC and HITM in a sibling core",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4770",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the LLC or local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x3870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote cache or remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x1070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HIT",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HIT in a remote cache",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_CACHE_HITM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that HITM in a remote cache",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json
new file mode 100644
index 000000000000..7d2f71a9dee3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json
@@ -0,0 +1,229 @@
+[
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_ASSIST.ALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_ASSIST.INPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xF7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_ASSIST.OUTPUT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "X87 Floating point assists for invalid output value (Precise Event)"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_COMP_OPS_EXE.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MMX Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP double precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE and SSE2 FP Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_PACKED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP packed Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "FP_COMP_OPS_EXE.SSE_FP_SCALAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE FP scalar Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE* FP single precision Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "FP_COMP_OPS_EXE.SSE2_INTEGER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "SSE2 integer Uops"
+ },
+ {
+ "EventCode": "0x10",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_COMP_OPS_EXE.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Computational floating-point operations executed"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "FP_MMX_TRANS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All Floating Point to and from MMX transitions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "FP_MMX_TRANS.TO_FP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from MMX to Floating Point instructions"
+ },
+ {
+ "EventCode": "0xCC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "FP_MMX_TRANS.TO_MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Transitions from Floating Point to MMX instructions"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_128.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer pack operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_128.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer arithmetic operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_128.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer logical operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_128.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer multiply operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_128.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shift operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_128.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer shuffle/move operations"
+ },
+ {
+ "EventCode": "0x12",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_128.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "128 bit SIMD integer unpack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SIMD_INT_64.PACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit pack operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "SIMD_INT_64.PACKED_ARITH",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit arithmetic operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SIMD_INT_64.PACKED_LOGICAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit logical operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SIMD_INT_64.PACKED_MPY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit packed multiply operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SIMD_INT_64.PACKED_SHIFT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shift operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "SIMD_INT_64.SHUFFLE_MOVE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit shuffle/move operations"
+ },
+ {
+ "EventCode": "0xFD",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SIMD_INT_64.UNPACK",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD integer 64 bit unpack operations"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/frontend.json b/tools/perf/pmu-events/arch/x86/westmereex/frontend.json
new file mode 100644
index 000000000000..e5e21e03444d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/frontend.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0xD0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions decoded"
+ },
+ {
+ "EventCode": "0xA6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACRO_INSTS.FUSIONS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused instructions decoded"
+ },
+ {
+ "EventCode": "0x19",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "TWO_UOP_INSTS_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Two Uop instructions decoded"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/memory.json b/tools/perf/pmu-events/arch/x86/westmereex/memory.json
new file mode 100644
index 000000000000..3ba555e73cbd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/memory.json
@@ -0,0 +1,747 @@
+[
+ {
+ "EventCode": "0x5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MISALIGN_MEM_REF.STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Misaligned store references"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF811",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2011",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF844",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2044",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x60FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF8FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x40FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x20FF",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF822",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2022",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.ANY_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF808",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2008",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.COREWB.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore writebacks to a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF877",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2077",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore code or data read requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF833",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore request = all data, response = any LLC miss",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the local DRAM.",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2033",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DATA_IN.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore data reads, RFO's and prefetches statisfied by the remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF803",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2003",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF801",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2001",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF804",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2004",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF802",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2002",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore demand RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF880",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2080",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.OTHER.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore other requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF830",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2030",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF810",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2010",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_DATA_RD.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch data reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF840",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2040",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_IFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch code reads satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF820",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2020",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PF_RFO.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch RFO requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x6070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by any DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0xF870",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests that missed the LLC",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x4070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.LOCAL_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by the local DRAM",
+ "Offcore": "1"
+ },
+ {
+ "EventCode": "0xB7",
+ "MSRValue": "0x2070",
+ "Counter": "2",
+ "UMask": "0x1",
+ "EventName": "OFFCORE_RESPONSE.PREFETCH.REMOTE_DRAM",
+ "MSRIndex": "0x1A6",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Offcore prefetch requests satisfied by a remote DRAM",
+ "Offcore": "1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/other.json b/tools/perf/pmu-events/arch/x86/westmereex/other.json
new file mode 100644
index 000000000000..85133d6a5ce0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/other.json
@@ -0,0 +1,287 @@
+[
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_CLEARS.EARLY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Early Branch Prediciton Unit clears"
+ },
+ {
+ "EventCode": "0xE8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BPU_CLEARS.LATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Late Branch Prediction Unit clears"
+ },
+ {
+ "EventCode": "0xE5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BPU_MISSED_CALL_RET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch prediction unit missed call or return"
+ },
+ {
+ "EventCode": "0xD5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ES_REG_RENAMES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ES segment renames"
+ },
+ {
+ "EventCode": "0x6C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "IO_TRANSACTIONS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "I/O transactions"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "L1I.CYCLES_STALLED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch stall cycles"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "L1I.HITS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch hits"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "L1I.MISSES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I instruction fetch misses"
+ },
+ {
+ "EventCode": "0x80",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3",
+ "EventName": "L1I.READS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "L1I Instruction fetches"
+ },
+ {
+ "EventCode": "0x82",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LARGE_ITLB.HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Large ITLB hit"
+ },
+ {
+ "EventCode": "0x3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_BLOCK.OVERLAP_STORE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Loads that partially overlap an earlier store"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "LOAD_DISPATCH.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All loads dispatched"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "LOAD_DISPATCH.MOB",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LOAD_DISPATCH.RS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched that bypass the MOB"
+ },
+ {
+ "EventCode": "0x13",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "LOAD_DISPATCH.RS_DELAYED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loads dispatched from stage 305"
+ },
+ {
+ "EventCode": "0x7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "PARTIAL_ADDRESS_ALIAS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "False dependencies due to partial address aliasing"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "RAT_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "All RAT stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RAT_STALLS.FLAGS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Flag stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RAT_STALLS.REGISTERS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Partial register stall cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RAT_STALLS.ROB_READ_PORT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB read port stalls cycles"
+ },
+ {
+ "EventCode": "0xD2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RAT_STALLS.SCOREBOARD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Scoreboard stall cycles"
+ },
+ {
+ "EventCode": "0x4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "SB_DRAIN.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All Store buffer stall cycles"
+ },
+ {
+ "EventCode": "0xD4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SEG_RENAME_STALLS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Segment rename stall cycles"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOP_RESPONSE.HIT",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HIT to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOP_RESPONSE.HITE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITE to snoop"
+ },
+ {
+ "EventCode": "0xB8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOP_RESPONSE.HITM",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Thread responded HITM to snoop"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS.CODE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop code requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS.DATA",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop data requests"
+ },
+ {
+ "EventCode": "0xB4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS.INVALIDATE",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop code requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x4",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.CODE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop code requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop data requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x1",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.DATA_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop data requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Outstanding snoop invalidate requests"
+ },
+ {
+ "EventCode": "0xB3",
+ "UMask": "0x2",
+ "EventName": "SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE_NOT_EMPTY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles snoop invalidate requests queued",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xF6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SQ_FULL_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Super Queue full stall cycles"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json b/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json
new file mode 100644
index 000000000000..799c57d94c39
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json
@@ -0,0 +1,905 @@
+[
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.CYCLES_DIV_BUSY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles the divider is busy"
+ },
+ {
+ "EventCode": "0x14",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ARITH.DIV",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Divide Operations executed",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0x14",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ARITH.MUL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Multiply operations executed"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BACLEAR.BAD_TARGET",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted with bad target address"
+ },
+ {
+ "EventCode": "0xE6",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR.CLEAR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "BACLEAR asserted, regardless of cause "
+ },
+ {
+ "EventCode": "0xA7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BACLEAR_FORCE_IQ",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction queue forced BACLEAR"
+ },
+ {
+ "EventCode": "0xE0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_DECODED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Branch instructions decoded"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_INST_EXEC.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_EXEC.COND",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Conditional branch instructions executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_EXEC.DIRECT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Unconditional branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_INST_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Unconditional call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_INST_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_INST_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_INST_EXEC.NON_CALLS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "All non call branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_INST_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Indirect return branches executed"
+ },
+ {
+ "EventCode": "0x88",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_INST_EXEC.TAKEN",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired conditional branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC4",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Retired near call instructions (Precise Event)"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7f",
+ "EventName": "BR_MISP_EXEC.ANY",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_EXEC.COND",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_EXEC.DIRECT",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted unconditional branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "BR_MISP_EXEC.DIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_EXEC.INDIRECT_NON_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted indirect non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x30",
+ "EventName": "BR_MISP_EXEC.NEAR_CALLS",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x7",
+ "EventName": "BR_MISP_EXEC.NON_CALLS",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted non call branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "BR_MISP_EXEC.RETURN_NEAR",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted return branches executed"
+ },
+ {
+ "EventCode": "0x89",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "BR_MISP_EXEC.TAKEN",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted taken branches executed"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted retired branch instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Mispredicted conditional retired branches (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC5",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "SampleAfterValue": "2000",
+ "BriefDescription": "Mispredicted near retired calls (Precise Event)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reference cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "CPU_CLK_UNHALTED.REF_P",
+ "SampleAfterValue": "100000",
+ "BriefDescription": "Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 2",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (fixed counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when thread is not halted (programmable counter)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total CPU cycles",
+ "CounterMask": "2"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0xf",
+ "EventName": "ILD_STALL.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Any Instruction Length Decoder stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ILD_STALL.IQ_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instruction Queue full stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ILD_STALL.LCP",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Length Change Prefix stall cycles"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ILD_STALL.MRU",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stall cycles due to BPU MRU bypass"
+ },
+ {
+ "EventCode": "0x87",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "ILD_STALL.REGEN",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Regen stall cycles"
+ },
+ {
+ "EventCode": "0x18",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_DECODED.DEC0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions that must be decoded by decoder 0"
+ },
+ {
+ "EventCode": "0x1E",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles instructions are written to the instruction queue"
+ },
+ {
+ "EventCode": "0x17",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_QUEUE_WRITES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions written to instruction queue."
+ },
+ {
+ "EventCode": "0x0",
+ "Counter": "Fixed counter 1",
+ "UMask": "0x0",
+ "EventName": "INST_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (fixed counter)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.ANY_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Instructions retired (Programmable counter and Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "INST_RETIRED.MMX",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired MMX instructions (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC0",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "INST_RETIRED.X87",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retired floating-point operations (Precise Event)"
+ },
+ {
+ "EventCode": "0x4C",
+ "Counter": "0,1",
+ "UMask": "0x1",
+ "EventName": "LOAD_HIT_PRE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Load operations conflicting with software prefetches"
+ },
+ {
+ "EventCode": "0xA8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles when uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xA8",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD.INACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no uops were delivered by the LSD",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0x20",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "LSD_OVERFLOW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Loops that can't stream from the instruction queue"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MACHINE_CLEARS.CYCLES",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Cycles machine clear asserted"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "MACHINE_CLEARS.MEM_ORDER",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Execution pipeline restart due to Memory ordering conflicts"
+ },
+ {
+ "EventCode": "0xC3",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "SampleAfterValue": "20000",
+ "BriefDescription": "Self-Modifying Code detected"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "RESOURCE_STALLS.FPCW",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "FPU control word write stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "RESOURCE_STALLS.LOAD",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Load buffer stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "RESOURCE_STALLS.MXCSR",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "MXCSR rename stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "RESOURCE_STALLS.OTHER",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Other Resource related stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "RESOURCE_STALLS.ROB_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ROB full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "RESOURCE_STALLS.RS_FULL",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Reservation Station full stall cycles"
+ },
+ {
+ "EventCode": "0xA2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "RESOURCE_STALLS.STORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Store buffer stall cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "SSEX_UOPS_RETIRED.PACKED_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Packed-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Double Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "SSEX_UOPS_RETIRED.SCALAR_SINGLE",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Scalar-Single Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC7",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "SSEX_UOPS_RETIRED.VECTOR_INTEGER",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "SIMD Vector Integer Uops retired (Precise Event)"
+ },
+ {
+ "EventCode": "0x3C",
+ "Counter": "0,1,2,3",
+ "UMask": "0x0",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles thread is active"
+ },
+ {
+ "EventCode": "0xDB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOP_UNFUSION",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uop unfusions due to FP exceptions"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_DECODED.ESP_FOLDING",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer instructions decoded"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "EventName": "UOPS_DECODED.ESP_SYNC",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Stack pointer sync operations"
+ },
+ {
+ "EventCode": "0xD1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_DECODED.MS_CYCLES_ACTIVE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops decoded by Microcode Sequencer",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xD1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_DECODED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops are decoded",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on any port (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on ports 0-4 (core count)",
+ "CounterMask": "1",
+ "EdgeDetect": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x3f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on any port (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1f",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0-4 (core count)",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_EXECUTED.PORT0",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 0"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 0, 1 or 5"
+ },
+ {
+ "EventCode": "0xB1",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x40",
+ "EventName": "UOPS_EXECUTED.PORT015_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops issued on ports 0, 1 or 5",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_EXECUTED.PORT1",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 1"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT2_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 2 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT234_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued on ports 2, 3 or 4"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x8",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT3_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 3 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "AnyThread": "1",
+ "EventName": "UOPS_EXECUTED.PORT4_CORE",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 4 (core count)"
+ },
+ {
+ "EventCode": "0xB1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "UOPS_EXECUTED.PORT5",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops executed on port 5"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CORE_STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued on any thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "AnyThread": "1",
+ "EventName": "UOPS_ISSUED.CYCLES_ALL_THREADS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops were issued on either thread",
+ "CounterMask": "1"
+ },
+ {
+ "EventCode": "0xE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_ISSUED.FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Fused Uops issued"
+ },
+ {
+ "EventCode": "0xE",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles no Uops were issued",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ACTIVE_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are being retired",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.ANY",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Macro-fused Uops retired (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Retirement slots used (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Cycles Uops are not retiring (Precise Event)",
+ "CounterMask": "1"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC2",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles using precise uop retired event (Precise Event)",
+ "CounterMask": "16"
+ },
+ {
+ "PEBS": "2",
+ "EventCode": "0xC0",
+ "Invert": "1",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Total cycles (Precise Event)",
+ "CounterMask": "16"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/westmereex/virtual-memory.json b/tools/perf/pmu-events/arch/x86/westmereex/virtual-memory.json
new file mode 100644
index 000000000000..ad989207e8f8
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/westmereex/virtual-memory.json
@@ -0,0 +1,173 @@
+[
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_LOAD_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load misses"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_LOAD_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss large page walks"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_LOAD_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss caused by low part of address"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB second level hit"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walks complete"
+ },
+ {
+ "EventCode": "0x8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_LOAD_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB load miss page walk cycles"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "DTLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "DTLB_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss large page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "DTLB_MISSES.PDE_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB misses caused by low part of address. Count also includes 2M page references because 2M pages do not use the PDE."
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "DTLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB first level misses but second level hit"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "DTLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "DTLB miss page walks"
+ },
+ {
+ "EventCode": "0x49",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "DTLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "DTLB miss page walk cycles"
+ },
+ {
+ "EventCode": "0x4F",
+ "Counter": "0,1,2,3",
+ "UMask": "0x10",
+ "EventName": "EPT.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "Extended Page Table walk cycles"
+ },
+ {
+ "EventCode": "0xAE",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_FLUSH",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB flushes"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC8",
+ "Counter": "0,1,2,3",
+ "UMask": "0x20",
+ "EventName": "ITLB_MISS_RETIRED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired instructions that missed the ITLB (Precise Event)"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "ITLB_MISSES.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "ITLB_MISSES.LARGE_WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss large page walks"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x2",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "ITLB miss page walks"
+ },
+ {
+ "EventCode": "0x85",
+ "Counter": "0,1,2,3",
+ "UMask": "0x4",
+ "EventName": "ITLB_MISSES.WALK_CYCLES",
+ "SampleAfterValue": "2000000",
+ "BriefDescription": "ITLB miss page walk cycles"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xCB",
+ "Counter": "0,1,2,3",
+ "UMask": "0x80",
+ "EventName": "MEM_LOAD_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired loads that miss the DTLB (Precise Event)"
+ },
+ {
+ "PEBS": "1",
+ "EventCode": "0xC",
+ "Counter": "0,1,2,3",
+ "UMask": "0x1",
+ "EventName": "MEM_STORE_RETIRED.DTLB_MISS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Retired stores that miss the DTLB (Precise Event)"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 8a4ce492f7b2..6676c2dd6dcb 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -42,6 +42,8 @@ perf-y += backward-ring-buffer.o
perf-y += sdt.o
perf-y += is_printable_array.o
perf-y += bitmap.o
+perf-y += perf-hooks.o
+perf-y += clang.o
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index e6d1816e431a..42e892b1e979 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -97,7 +97,7 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
evlist = perf_evlist__new();
if (!evlist) {
- pr_debug("No enough memory to create evlist\n");
+ pr_debug("Not enough memory to create evlist\n");
return TEST_FAIL;
}
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 2673e86ed50f..92343f43e44a 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -57,7 +57,7 @@ static struct {
} bpf_testcase_table[] = {
{
LLVM_TESTCASE_BASE,
- "Test basic BPF filtering",
+ "Basic BPF filtering",
"[basic_bpf_test]",
"fix 'perf test LLVM' first",
"load bpf object failed",
@@ -67,7 +67,7 @@ static struct {
#ifdef HAVE_BPF_PROLOGUE
{
LLVM_TESTCASE_BPF_PROLOGUE,
- "Test BPF prologue generation",
+ "BPF prologue generation",
"[bpf_prologue_test]",
"fix kbuild first",
"check your vmlinux setting?",
@@ -77,7 +77,7 @@ static struct {
#endif
{
LLVM_TESTCASE_BPF_RELOCATION,
- "Test BPF relocation checker",
+ "BPF relocation checker",
"[bpf_relocation_test]",
"fix 'perf test LLVM' first",
"libbpf error when dealing with relocation",
@@ -125,7 +125,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
/* Instead of perf_evlist__new_default, don't add default events */
evlist = perf_evlist__new();
if (!evlist) {
- pr_debug("No enough memory to create evlist\n");
+ pr_debug("Not enough memory to create evlist\n");
return TEST_FAIL;
}
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 778668a2a966..23605202d4a1 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -28,119 +28,119 @@ static struct test generic_tests[] = {
.func = test__vmlinux_matches_kallsyms,
},
{
- .desc = "detect openat syscall event",
+ .desc = "Detect openat syscall event",
.func = test__openat_syscall_event,
},
{
- .desc = "detect openat syscall event on all cpus",
+ .desc = "Detect openat syscall event on all cpus",
.func = test__openat_syscall_event_on_all_cpus,
},
{
- .desc = "read samples using the mmap interface",
+ .desc = "Read samples using the mmap interface",
.func = test__basic_mmap,
},
{
- .desc = "parse events tests",
+ .desc = "Parse event definition strings",
.func = test__parse_events,
},
{
- .desc = "Validate PERF_RECORD_* events & perf_sample fields",
+ .desc = "PERF_RECORD_* events & perf_sample fields",
.func = test__PERF_RECORD,
},
{
- .desc = "Test perf pmu format parsing",
+ .desc = "Parse perf pmu format",
.func = test__pmu,
},
{
- .desc = "Test dso data read",
+ .desc = "DSO data read",
.func = test__dso_data,
},
{
- .desc = "Test dso data cache",
+ .desc = "DSO data cache",
.func = test__dso_data_cache,
},
{
- .desc = "Test dso data reopen",
+ .desc = "DSO data reopen",
.func = test__dso_data_reopen,
},
{
- .desc = "roundtrip evsel->name check",
+ .desc = "Roundtrip evsel->name",
.func = test__perf_evsel__roundtrip_name_test,
},
{
- .desc = "Check parsing of sched tracepoints fields",
+ .desc = "Parse sched tracepoints fields",
.func = test__perf_evsel__tp_sched_test,
},
{
- .desc = "Generate and check syscalls:sys_enter_openat event fields",
+ .desc = "syscalls:sys_enter_openat event fields",
.func = test__syscall_openat_tp_fields,
},
{
- .desc = "struct perf_event_attr setup",
+ .desc = "Setup struct perf_event_attr",
.func = test__attr,
},
{
- .desc = "Test matching and linking multiple hists",
+ .desc = "Match and link multiple hists",
.func = test__hists_link,
},
{
- .desc = "Try 'import perf' in python, checking link problems",
+ .desc = "'import perf' in python",
.func = test__python_use,
},
{
- .desc = "Test breakpoint overflow signal handler",
+ .desc = "Breakpoint overflow signal handler",
.func = test__bp_signal,
},
{
- .desc = "Test breakpoint overflow sampling",
+ .desc = "Breakpoint overflow sampling",
.func = test__bp_signal_overflow,
},
{
- .desc = "Test number of exit event of a simple workload",
+ .desc = "Number of exit events of a simple workload",
.func = test__task_exit,
},
{
- .desc = "Test software clock events have valid period values",
+ .desc = "Software clock events period values",
.func = test__sw_clock_freq,
},
{
- .desc = "Test object code reading",
+ .desc = "Object code reading",
.func = test__code_reading,
},
{
- .desc = "Test sample parsing",
+ .desc = "Sample parsing",
.func = test__sample_parsing,
},
{
- .desc = "Test using a dummy software event to keep tracking",
+ .desc = "Use a dummy software event to keep tracking",
.func = test__keep_tracking,
},
{
- .desc = "Test parsing with no sample_id_all bit set",
+ .desc = "Parse with no sample_id_all bit set",
.func = test__parse_no_sample_id_all,
},
{
- .desc = "Test filtering hist entries",
+ .desc = "Filter hist entries",
.func = test__hists_filter,
},
{
- .desc = "Test mmap thread lookup",
+ .desc = "Lookup mmap thread",
.func = test__mmap_thread_lookup,
},
{
- .desc = "Test thread mg sharing",
+ .desc = "Share thread mg",
.func = test__thread_mg_share,
},
{
- .desc = "Test output sorting of hist entries",
+ .desc = "Sort output of hist entries",
.func = test__hists_output,
},
{
- .desc = "Test cumulation of child hist entries",
+ .desc = "Cumulate child hist entries",
.func = test__hists_cumulate,
},
{
- .desc = "Test tracking with sched_switch",
+ .desc = "Track with sched_switch",
.func = test__switch_tracking,
},
{
@@ -152,15 +152,15 @@ static struct test generic_tests[] = {
.func = test__fdarray__add,
},
{
- .desc = "Test kmod_path__parse function",
+ .desc = "kmod_path__parse",
.func = test__kmod_path__parse,
},
{
- .desc = "Test thread map",
+ .desc = "Thread map",
.func = test__thread_map,
},
{
- .desc = "Test LLVM searching and compiling",
+ .desc = "LLVM search and compile",
.func = test__llvm,
.subtest = {
.skip_if_fail = true,
@@ -169,11 +169,11 @@ static struct test generic_tests[] = {
},
},
{
- .desc = "Test topology in session",
+ .desc = "Session topology",
.func = test_session_topology,
},
{
- .desc = "Test BPF filter",
+ .desc = "BPF filter",
.func = test__bpf,
.subtest = {
.skip_if_fail = true,
@@ -182,54 +182,67 @@ static struct test generic_tests[] = {
},
},
{
- .desc = "Test thread map synthesize",
+ .desc = "Synthesize thread map",
.func = test__thread_map_synthesize,
},
{
- .desc = "Test cpu map synthesize",
+ .desc = "Synthesize cpu map",
.func = test__cpu_map_synthesize,
},
{
- .desc = "Test stat config synthesize",
+ .desc = "Synthesize stat config",
.func = test__synthesize_stat_config,
},
{
- .desc = "Test stat synthesize",
+ .desc = "Synthesize stat",
.func = test__synthesize_stat,
},
{
- .desc = "Test stat round synthesize",
+ .desc = "Synthesize stat round",
.func = test__synthesize_stat_round,
},
{
- .desc = "Test attr update synthesize",
+ .desc = "Synthesize attr update",
.func = test__event_update,
},
{
- .desc = "Test events times",
+ .desc = "Event times",
.func = test__event_times,
},
{
- .desc = "Test backward reading from ring buffer",
+ .desc = "Read backward ring buffer",
.func = test__backward_ring_buffer,
},
{
- .desc = "Test cpu map print",
+ .desc = "Print cpu map",
.func = test__cpu_map_print,
},
{
- .desc = "Test SDT event probing",
+ .desc = "Probe SDT events",
.func = test__sdt_event,
},
{
- .desc = "Test is_printable_array function",
+ .desc = "is_printable_array",
.func = test__is_printable_array,
},
{
- .desc = "Test bitmap print",
+ .desc = "Print bitmap",
.func = test__bitmap_print,
},
{
+ .desc = "perf hooks",
+ .func = test__perf_hooks,
+ },
+ {
+ .desc = "builtin clang support",
+ .func = test__clang,
+ .subtest = {
+ .skip_if_fail = true,
+ .get_nr = test__clang_subtest_get_nr,
+ .get_desc = test__clang_subtest_get_desc,
+ }
+ },
+ {
.func = NULL,
},
};
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 000000000000..f853e242a86c
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,46 @@
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "c++/clang-c.h"
+
+static struct {
+ int (*func)(void);
+ const char *desc;
+} clang_testcase_table[] = {
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+ {
+ .func = test__clang_to_IR,
+ .desc = "builtin clang compile C source to IR",
+ },
+ {
+ .func = test__clang_to_obj,
+ .desc = "builtin clang compile C source to ELF object",
+ },
+#endif
+};
+
+int test__clang_subtest_get_nr(void)
+{
+ return (int)ARRAY_SIZE(clang_testcase_table);
+}
+
+const char *test__clang_subtest_get_desc(int i)
+{
+ if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+ return NULL;
+ return clang_testcase_table[i].desc;
+}
+
+#ifndef HAVE_LIBCLANGLLVM_SUPPORT
+int test__clang(int i __maybe_unused)
+{
+ return TEST_SKIP;
+}
+#else
+int test__clang(int i)
+{
+ if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+ return TEST_FAIL;
+ return clang_testcase_table[i].func();
+}
+#endif
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index b798a4bfd238..02a33ebcd992 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -34,19 +34,19 @@ static struct {
} bpf_source_table[__LLVM_TESTCASE_MAX] = {
[LLVM_TESTCASE_BASE] = {
.source = test_llvm__bpf_base_prog,
- .desc = "Basic BPF llvm compiling test",
+ .desc = "Basic BPF llvm compile",
},
[LLVM_TESTCASE_KBUILD] = {
.source = test_llvm__bpf_test_kbuild_prog,
- .desc = "Test kbuild searching",
+ .desc = "kbuild searching",
},
[LLVM_TESTCASE_BPF_PROLOGUE] = {
.source = test_llvm__bpf_test_prologue_prog,
- .desc = "Compile source for BPF prologue generation test",
+ .desc = "Compile source for BPF prologue generation",
},
[LLVM_TESTCASE_BPF_RELOCATION] = {
.source = test_llvm__bpf_test_relocation,
- .desc = "Compile source for BPF relocation test",
+ .desc = "Compile source for BPF relocation",
.should_load_fail = true,
},
};
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604be99d..b83571758d83 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,6 +1,10 @@
#ifndef PERF_TEST_LLVM_H
#define PERF_TEST_LLVM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stddef.h> /* for size_t */
#include <stdbool.h> /* for bool */
@@ -20,4 +24,7 @@ enum test_llvm__testcase {
int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
enum test_llvm__testcase index, bool force,
bool *should_load_fail);
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 143f4d549769..0784748f1670 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -83,6 +83,7 @@ make_no_libbpf := NO_LIBBPF=1
make_no_libcrypto := NO_LIBCRYPTO=1
make_with_babeltrace:= LIBBABELTRACE=1
make_no_sdt := NO_SDT=1
+make_with_clangllvm := LIBCLANGLLVM=1
make_tags := tags
make_cscope := cscope
make_help := help
@@ -106,7 +107,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
-make_minimal += NO_LIBCRYPTO=1 NO_SDT=1
+make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
# $(run) contains all available tests
run := make_pure
@@ -139,6 +140,7 @@ run += make_no_libbionic
run += make_no_auxtrace
run += make_no_libbpf
run += make_with_babeltrace
+run += make_with_clangllvm
run += make_help
run += make_doc
run += make_perf_o
@@ -278,7 +280,7 @@ endif
MAKEFLAGS := --no-print-directory
-clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null)
+clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null && $(MAKE) -s $(O_OPT) -C ../build clean >/dev/null)
$(run):
$(call clean)
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
new file mode 100644
index 000000000000..665ecc19671c
--- /dev/null
+++ b/tools/perf/tests/perf-hooks.c
@@ -0,0 +1,48 @@
+#include <signal.h>
+#include <stdlib.h>
+
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "perf-hooks.h"
+
+static void sigsegv_handler(int sig __maybe_unused)
+{
+ pr_debug("SIGSEGV is observed as expected, try to recover.\n");
+ perf_hooks__recover();
+ signal(SIGSEGV, SIG_DFL);
+ raise(SIGSEGV);
+ exit(-1);
+}
+
+
+static void the_hook(void *_hook_flags)
+{
+ int *hook_flags = _hook_flags;
+ int *p = NULL;
+
+ *hook_flags = 1234;
+
+ /* Generate a segfault, test perf_hooks__recover */
+ *p = 0;
+}
+
+int test__perf_hooks(int subtest __maybe_unused)
+{
+ int hook_flags = 0;
+
+ signal(SIGSEGV, sigsegv_handler);
+ perf_hooks__set_hook("test", the_hook, &hook_flags);
+ perf_hooks__invoke_test();
+
+ /* hook is triggered? */
+ if (hook_flags != 1234) {
+ pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
+ return TEST_FAIL;
+ }
+
+ /* the buggy hook is removed? */
+ if (perf_hooks__get_hook("test"))
+ return TEST_FAIL;
+ return TEST_OK;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 7c196c585472..0d7b251305af 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -91,6 +91,10 @@ int test__cpu_map_print(int subtest);
int test__sdt_event(int subtest);
int test__is_printable_array(int subtest);
int test__bitmap_print(int subtest);
+int test__perf_hooks(int subtest);
+int test__clang(int subtest);
+const char *test__clang_subtest_get_desc(int subtest);
+int test__clang_subtest_get_nr(void);
#if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 4c18271c71c9..ec7a30fad149 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -213,17 +213,17 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
ui_browser__write_nstring(browser, bf, printed);
if (change_color)
ui_browser__set_color(browser, color);
- if (dl->ins && dl->ins->ops->scnprintf) {
- if (ins__is_jump(dl->ins)) {
+ if (dl->ins.ops && dl->ins.ops->scnprintf) {
+ if (ins__is_jump(&dl->ins)) {
bool fwd = dl->ops.target.offset > (u64)dl->offset;
ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
SLSMG_UARROW_CHAR);
SLsmg_write_char(' ');
- } else if (ins__is_call(dl->ins)) {
+ } else if (ins__is_call(&dl->ins)) {
ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
SLsmg_write_char(' ');
- } else if (ins__is_ret(dl->ins)) {
+ } else if (ins__is_ret(&dl->ins)) {
ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
SLsmg_write_char(' ');
} else {
@@ -243,7 +243,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
{
- if (!dl || !dl->ins || !ins__is_jump(dl->ins)
+ if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins)
|| !disasm_line__has_offset(dl)
|| dl->ops.target.offset >= symbol__size(sym))
return false;
@@ -492,7 +492,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
};
char title[SYM_TITLE_MAX_SIZE];
- if (!ins__is_call(dl->ins))
+ if (!ins__is_call(&dl->ins))
return false;
if (map_groups__find_ams(&target) ||
@@ -543,14 +543,16 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows
static bool annotate_browser__jump(struct annotate_browser *browser)
{
struct disasm_line *dl = browser->selection;
+ u64 offset;
s64 idx;
- if (!ins__is_jump(dl->ins))
+ if (!ins__is_jump(&dl->ins))
return false;
- dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx);
+ offset = dl->ops.target.offset;
+ dl = annotate_browser__find_offset(browser, offset, &idx);
if (dl == NULL) {
- ui_helpline__puts("Invalid jump offset");
+ ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
return true;
}
@@ -841,9 +843,9 @@ show_help:
ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
else if (browser->selection->offset == -1)
ui_helpline__puts("Actions are only available for assembly lines.");
- else if (!browser->selection->ins)
+ else if (!browser->selection->ins.ops)
goto show_sup_ins;
- else if (ins__is_ret(browser->selection->ins))
+ else if (ins__is_ret(&browser->selection->ins))
goto out;
else if (!(annotate_browser__jump(browser) ||
annotate_browser__callq(browser, evsel, hbt))) {
@@ -1050,7 +1052,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
(nr_pcnt - 1);
}
- err = symbol__disassemble(sym, map, sizeof_bdl);
+ err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), sizeof_bdl);
if (err) {
char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a53fef0c673b..641b40234a9d 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -30,7 +30,7 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd,
static bool hist_browser__has_filter(struct hist_browser *hb)
{
- return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter;
+ return hists__has_filter(hb->hists) || hb->min_pcnt || symbol_conf.has_filter || hb->c2c_filter;
}
static int hist_browser__get_folding(struct hist_browser *browser)
@@ -738,6 +738,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
struct callchain_print_arg *arg)
{
char bf[1024], *alloc_str;
+ char buf[64], *alloc_str2;
const char *str;
if (arg->row_offset != 0) {
@@ -746,12 +747,26 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
}
alloc_str = NULL;
+ alloc_str2 = NULL;
+
str = callchain_list__sym_name(chain, bf, sizeof(bf),
browser->show_dso);
- if (need_percent) {
- char buf[64];
+ if (symbol_conf.show_branchflag_count) {
+ if (need_percent)
+ callchain_list_counts__printf_value(node, chain, NULL,
+ buf, sizeof(buf));
+ else
+ callchain_list_counts__printf_value(NULL, chain, NULL,
+ buf, sizeof(buf));
+
+ if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
+ str = "Not enough memory!";
+ else
+ str = alloc_str2;
+ }
+ if (need_percent) {
callchain_node__scnprintf_value(node, buf, sizeof(buf),
total);
@@ -764,6 +779,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
print(browser, chain, str, offset, row, arg);
free(alloc_str);
+ free(alloc_str2);
return 1;
}
@@ -2833,7 +2849,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
do_zoom_dso(browser, actions);
continue;
case 'V':
- browser->show_dso = !browser->show_dso;
+ verbose = (verbose + 1) % 4;
+ browser->show_dso = verbose > 0;
+ ui_helpline__fpush("Verbosity level set to %d\n",
+ verbose);
continue;
case 't':
actions->thread = thread;
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h
index 39bd0f28f211..23d6acb84800 100644
--- a/tools/perf/ui/browsers/hists.h
+++ b/tools/perf/ui/browsers/hists.h
@@ -18,6 +18,7 @@ struct hist_browser {
u64 nr_non_filtered_entries;
u64 nr_hierarchy_entries;
u64 nr_callchain_rows;
+ bool c2c_filter;
/* Get title string. */
int (*title)(struct hist_browser *browser,
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 42d319927762..8c9308ac30b7 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -167,7 +167,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
if (map->dso->annotate_warned)
return -1;
- err = symbol__disassemble(sym, map, 0);
+ err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0);
if (err) {
char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index 5b74a7eba210..379039ab00d8 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -72,3 +72,13 @@ int ui_helpline__vshow(const char *fmt, va_list ap)
{
return helpline_fns->show(fmt, ap);
}
+
+void ui_helpline__printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ ui_helpline__pop();
+ va_start(ap, fmt);
+ ui_helpline__vpush(fmt, ap);
+ va_end(ap);
+}
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 46181f4fc07e..d52d0a1a881b 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -21,6 +21,7 @@ void ui_helpline__push(const char *msg);
void ui_helpline__vpush(const char *fmt, va_list ap);
void ui_helpline__fpush(const char *fmt, ...);
void ui_helpline__puts(const char *msg);
+void ui_helpline__printf(const char *fmt, ...);
int ui_helpline__vshow(const char *fmt, va_list ap);
extern char ui_helpline__current[512];
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 89d8441f9890..668f4aecf2e6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -41,7 +41,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
{
int i;
size_t ret = 0;
- char bf[1024];
+ char bf[1024], *alloc_str = NULL;
+ char buf[64];
+ const char *str;
ret += callchain__fprintf_left_margin(fp, left_margin);
for (i = 0; i < depth; i++) {
@@ -56,8 +58,26 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
} else
ret += fprintf(fp, "%s", " ");
}
- fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
+
+ str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
+
+ if (symbol_conf.show_branchflag_count) {
+ if (!period)
+ callchain_list_counts__printf_value(node, chain, NULL,
+ buf, sizeof(buf));
+ else
+ callchain_list_counts__printf_value(NULL, chain, NULL,
+ buf, sizeof(buf));
+
+ if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
+ str = "Not enough memory!";
+ else
+ str = alloc_str;
+ }
+
+ fputs(str, fp);
fputc('\n', fp);
+ free(alloc_str);
return ret;
}
@@ -219,8 +239,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
} else
ret += callchain__fprintf_left_margin(fp, left_margin);
- ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
- false));
+ ret += fprintf(fp, "%s",
+ callchain_list__sym_name(chain, bf,
+ sizeof(bf),
+ false));
+
+ if (symbol_conf.show_branchflag_count)
+ ret += callchain_list_counts__printf_value(
+ NULL, chain, fp, NULL, 0);
+ ret += fprintf(fp, "\n");
if (++entries_printed == callchain_param.print_limit)
break;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index eb60e613d795..3840e3a87057 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,6 +87,7 @@ libperf-y += help-unknown-cmd.o
libperf-y += mem-events.o
libperf-y += vsprintf.o
libperf-y += drv_configs.o
+libperf-y += time-utils.o
libperf-$(CONFIG_LIBBPF) += bpf-loader.o
libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -120,9 +121,13 @@ libperf-y += demangle-rust.o
ifdef CONFIG_JITDUMP
libperf-$(CONFIG_LIBELF) += jitdump.o
libperf-$(CONFIG_LIBELF) += genelf.o
-libperf-$(CONFIG_LIBELF) += genelf_debug.o
+libperf-$(CONFIG_DWARF) += genelf_debug.o
endif
+libperf-y += perf-hooks.o
+
+libperf-$(CONFIG_CXX) += c++/
+
CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
# avoid compiler warnings in 32-bit mode
CFLAGS_genelf_debug.o += -Wno-packed
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index aeb5a441bd74..ea7e0de4b9c1 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -18,16 +18,119 @@
#include "annotate.h"
#include "evsel.h"
#include "block-range.h"
+#include "arch/common.h"
#include <regex.h>
#include <pthread.h>
#include <linux/bitops.h>
+#include <sys/utsname.h>
const char *disassembler_style;
const char *objdump_path;
static regex_t file_lineno;
-static struct ins *ins__find(const char *name);
-static int disasm_line__parse(char *line, char **namep, char **rawp);
+static struct ins_ops *ins__find(struct arch *arch, const char *name);
+static void ins__sort(struct arch *arch);
+static int disasm_line__parse(char *line, const char **namep, char **rawp);
+
+struct arch {
+ const char *name;
+ struct ins *instructions;
+ size_t nr_instructions;
+ size_t nr_instructions_allocated;
+ struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
+ bool sorted_instructions;
+ bool initialized;
+ void *priv;
+ int (*init)(struct arch *arch);
+ struct {
+ char comment_char;
+ char skip_functions_char;
+ } objdump;
+};
+
+static struct ins_ops call_ops;
+static struct ins_ops dec_ops;
+static struct ins_ops jump_ops;
+static struct ins_ops mov_ops;
+static struct ins_ops nop_ops;
+static struct ins_ops lock_ops;
+static struct ins_ops ret_ops;
+
+static int arch__grow_instructions(struct arch *arch)
+{
+ struct ins *new_instructions;
+ size_t new_nr_allocated;
+
+ if (arch->nr_instructions_allocated == 0 && arch->instructions)
+ goto grow_from_non_allocated_table;
+
+ new_nr_allocated = arch->nr_instructions_allocated + 128;
+ new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));
+ if (new_instructions == NULL)
+ return -1;
+
+out_update_instructions:
+ arch->instructions = new_instructions;
+ arch->nr_instructions_allocated = new_nr_allocated;
+ return 0;
+
+grow_from_non_allocated_table:
+ new_nr_allocated = arch->nr_instructions + 128;
+ new_instructions = calloc(new_nr_allocated, sizeof(struct ins));
+ if (new_instructions == NULL)
+ return -1;
+
+ memcpy(new_instructions, arch->instructions, arch->nr_instructions);
+ goto out_update_instructions;
+}
+
+static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
+{
+ struct ins *ins;
+
+ if (arch->nr_instructions == arch->nr_instructions_allocated &&
+ arch__grow_instructions(arch))
+ return -1;
+
+ ins = &arch->instructions[arch->nr_instructions];
+ ins->name = strdup(name);
+ if (!ins->name)
+ return -1;
+
+ ins->ops = ops;
+ arch->nr_instructions++;
+
+ ins__sort(arch);
+ return 0;
+}
+
+#include "arch/arm/annotate/instructions.c"
+#include "arch/arm64/annotate/instructions.c"
+#include "arch/x86/annotate/instructions.c"
+#include "arch/powerpc/annotate/instructions.c"
+
+static struct arch architectures[] = {
+ {
+ .name = "arm",
+ .init = arm__annotate_init,
+ },
+ {
+ .name = "arm64",
+ .init = arm64__annotate_init,
+ },
+ {
+ .name = "x86",
+ .instructions = x86__instructions,
+ .nr_instructions = ARRAY_SIZE(x86__instructions),
+ .objdump = {
+ .comment_char = '#',
+ },
+ },
+ {
+ .name = "powerpc",
+ .init = powerpc__annotate_init,
+ },
+};
static void ins__delete(struct ins_operands *ops)
{
@@ -54,7 +157,7 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
return ins__raw_scnprintf(ins, bf, size, ops);
}
-static int call__parse(struct ins_operands *ops, struct map *map)
+static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
{
char *endptr, *tok, *name;
@@ -66,10 +169,9 @@ static int call__parse(struct ins_operands *ops, struct map *map)
name++;
-#ifdef __arm__
- if (strchr(name, '+'))
+ if (arch->objdump.skip_functions_char &&
+ strchr(name, arch->objdump.skip_functions_char))
return -1;
-#endif
tok = strchr(name, '>');
if (tok == NULL)
@@ -118,7 +220,7 @@ bool ins__is_call(const struct ins *ins)
return ins->ops == &call_ops;
}
-static int jump__parse(struct ins_operands *ops, struct map *map __maybe_unused)
+static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused)
{
const char *s = strchr(ops->raw, '+');
@@ -135,6 +237,9 @@ static int jump__parse(struct ins_operands *ops, struct map *map __maybe_unused)
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops)
{
+ if (!ops->target.addr)
+ return ins__raw_scnprintf(ins, bf, size, ops);
+
return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
}
@@ -173,28 +278,22 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
return 0;
}
-static int lock__parse(struct ins_operands *ops, struct map *map)
+static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
{
- char *name;
-
ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
if (ops->locked.ops == NULL)
return 0;
- if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
+ if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)
goto out_free_ops;
- ops->locked.ins = ins__find(name);
- free(name);
+ ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name);
- if (ops->locked.ins == NULL)
+ if (ops->locked.ins.ops == NULL)
goto out_free_ops;
- if (!ops->locked.ins->ops)
- return 0;
-
- if (ops->locked.ins->ops->parse &&
- ops->locked.ins->ops->parse(ops->locked.ops, map) < 0)
+ if (ops->locked.ins.ops->parse &&
+ ops->locked.ins.ops->parse(arch, ops->locked.ops, map) < 0)
goto out_free_ops;
return 0;
@@ -209,19 +308,19 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
{
int printed;
- if (ops->locked.ins == NULL)
+ if (ops->locked.ins.ops == NULL)
return ins__raw_scnprintf(ins, bf, size, ops);
printed = scnprintf(bf, size, "%-6.6s ", ins->name);
- return printed + ins__scnprintf(ops->locked.ins, bf + printed,
+ return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
size - printed, ops->locked.ops);
}
static void lock__delete(struct ins_operands *ops)
{
- struct ins *ins = ops->locked.ins;
+ struct ins *ins = &ops->locked.ins;
- if (ins && ins->ops->free)
+ if (ins->ops && ins->ops->free)
ins->ops->free(ops->locked.ops);
else
ins__delete(ops->locked.ops);
@@ -237,7 +336,7 @@ static struct ins_ops lock_ops = {
.scnprintf = lock__scnprintf,
};
-static int mov__parse(struct ins_operands *ops, struct map *map __maybe_unused)
+static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *map __maybe_unused)
{
char *s = strchr(ops->raw, ','), *target, *comment, prev;
@@ -252,11 +351,7 @@ static int mov__parse(struct ins_operands *ops, struct map *map __maybe_unused)
return -1;
target = ++s;
-#ifdef __arm__
- comment = strchr(s, ';');
-#else
- comment = strchr(s, '#');
-#endif
+ comment = strchr(s, arch->objdump.comment_char);
if (comment != NULL)
s = comment - 1;
@@ -304,7 +399,7 @@ static struct ins_ops mov_ops = {
.scnprintf = mov__scnprintf,
};
-static int dec__parse(struct ins_operands *ops, struct map *map __maybe_unused)
+static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused)
{
char *target, *comment, *s, prev;
@@ -321,7 +416,7 @@ static int dec__parse(struct ins_operands *ops, struct map *map __maybe_unused)
if (ops->target.raw == NULL)
return -1;
- comment = strchr(s, '#');
+ comment = strchr(s, arch->objdump.comment_char);
if (comment == NULL)
return 0;
@@ -364,99 +459,6 @@ bool ins__is_ret(const struct ins *ins)
return ins->ops == &ret_ops;
}
-static struct ins instructions[] = {
- { .name = "add", .ops = &mov_ops, },
- { .name = "addl", .ops = &mov_ops, },
- { .name = "addq", .ops = &mov_ops, },
- { .name = "addw", .ops = &mov_ops, },
- { .name = "and", .ops = &mov_ops, },
-#ifdef __arm__
- { .name = "b", .ops = &jump_ops, }, // might also be a call
- { .name = "bcc", .ops = &jump_ops, },
- { .name = "bcs", .ops = &jump_ops, },
- { .name = "beq", .ops = &jump_ops, },
- { .name = "bge", .ops = &jump_ops, },
- { .name = "bgt", .ops = &jump_ops, },
- { .name = "bhi", .ops = &jump_ops, },
- { .name = "bl", .ops = &call_ops, },
- { .name = "bls", .ops = &jump_ops, },
- { .name = "blt", .ops = &jump_ops, },
- { .name = "blx", .ops = &call_ops, },
- { .name = "bne", .ops = &jump_ops, },
-#endif
- { .name = "bts", .ops = &mov_ops, },
- { .name = "call", .ops = &call_ops, },
- { .name = "callq", .ops = &call_ops, },
- { .name = "cmp", .ops = &mov_ops, },
- { .name = "cmpb", .ops = &mov_ops, },
- { .name = "cmpl", .ops = &mov_ops, },
- { .name = "cmpq", .ops = &mov_ops, },
- { .name = "cmpw", .ops = &mov_ops, },
- { .name = "cmpxch", .ops = &mov_ops, },
- { .name = "dec", .ops = &dec_ops, },
- { .name = "decl", .ops = &dec_ops, },
- { .name = "imul", .ops = &mov_ops, },
- { .name = "inc", .ops = &dec_ops, },
- { .name = "incl", .ops = &dec_ops, },
- { .name = "ja", .ops = &jump_ops, },
- { .name = "jae", .ops = &jump_ops, },
- { .name = "jb", .ops = &jump_ops, },
- { .name = "jbe", .ops = &jump_ops, },
- { .name = "jc", .ops = &jump_ops, },
- { .name = "jcxz", .ops = &jump_ops, },
- { .name = "je", .ops = &jump_ops, },
- { .name = "jecxz", .ops = &jump_ops, },
- { .name = "jg", .ops = &jump_ops, },
- { .name = "jge", .ops = &jump_ops, },
- { .name = "jl", .ops = &jump_ops, },
- { .name = "jle", .ops = &jump_ops, },
- { .name = "jmp", .ops = &jump_ops, },
- { .name = "jmpq", .ops = &jump_ops, },
- { .name = "jna", .ops = &jump_ops, },
- { .name = "jnae", .ops = &jump_ops, },
- { .name = "jnb", .ops = &jump_ops, },
- { .name = "jnbe", .ops = &jump_ops, },
- { .name = "jnc", .ops = &jump_ops, },
- { .name = "jne", .ops = &jump_ops, },
- { .name = "jng", .ops = &jump_ops, },
- { .name = "jnge", .ops = &jump_ops, },
- { .name = "jnl", .ops = &jump_ops, },
- { .name = "jnle", .ops = &jump_ops, },
- { .name = "jno", .ops = &jump_ops, },
- { .name = "jnp", .ops = &jump_ops, },
- { .name = "jns", .ops = &jump_ops, },
- { .name = "jnz", .ops = &jump_ops, },
- { .name = "jo", .ops = &jump_ops, },
- { .name = "jp", .ops = &jump_ops, },
- { .name = "jpe", .ops = &jump_ops, },
- { .name = "jpo", .ops = &jump_ops, },
- { .name = "jrcxz", .ops = &jump_ops, },
- { .name = "js", .ops = &jump_ops, },
- { .name = "jz", .ops = &jump_ops, },
- { .name = "lea", .ops = &mov_ops, },
- { .name = "lock", .ops = &lock_ops, },
- { .name = "mov", .ops = &mov_ops, },
- { .name = "movb", .ops = &mov_ops, },
- { .name = "movdqa",.ops = &mov_ops, },
- { .name = "movl", .ops = &mov_ops, },
- { .name = "movq", .ops = &mov_ops, },
- { .name = "movslq", .ops = &mov_ops, },
- { .name = "movzbl", .ops = &mov_ops, },
- { .name = "movzwl", .ops = &mov_ops, },
- { .name = "nop", .ops = &nop_ops, },
- { .name = "nopl", .ops = &nop_ops, },
- { .name = "nopw", .ops = &nop_ops, },
- { .name = "or", .ops = &mov_ops, },
- { .name = "orl", .ops = &mov_ops, },
- { .name = "test", .ops = &mov_ops, },
- { .name = "testb", .ops = &mov_ops, },
- { .name = "testl", .ops = &mov_ops, },
- { .name = "xadd", .ops = &mov_ops, },
- { .name = "xbeginl", .ops = &jump_ops, },
- { .name = "xbeginq", .ops = &jump_ops, },
- { .name = "retq", .ops = &ret_ops, },
-};
-
static int ins__key_cmp(const void *name, const void *insp)
{
const struct ins *ins = insp;
@@ -472,24 +474,70 @@ static int ins__cmp(const void *a, const void *b)
return strcmp(ia->name, ib->name);
}
-static void ins__sort(void)
+static void ins__sort(struct arch *arch)
+{
+ const int nmemb = arch->nr_instructions;
+
+ qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
+}
+
+static struct ins_ops *__ins__find(struct arch *arch, const char *name)
+{
+ struct ins *ins;
+ const int nmemb = arch->nr_instructions;
+
+ if (!arch->sorted_instructions) {
+ ins__sort(arch);
+ arch->sorted_instructions = true;
+ }
+
+ ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
+ return ins ? ins->ops : NULL;
+}
+
+static struct ins_ops *ins__find(struct arch *arch, const char *name)
+{
+ struct ins_ops *ops = __ins__find(arch, name);
+
+ if (!ops && arch->associate_instruction_ops)
+ ops = arch->associate_instruction_ops(arch, name);
+
+ return ops;
+}
+
+static int arch__key_cmp(const void *name, const void *archp)
+{
+ const struct arch *arch = archp;
+
+ return strcmp(name, arch->name);
+}
+
+static int arch__cmp(const void *a, const void *b)
{
- const int nmemb = ARRAY_SIZE(instructions);
+ const struct arch *aa = a;
+ const struct arch *ab = b;
- qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
+ return strcmp(aa->name, ab->name);
}
-static struct ins *ins__find(const char *name)
+static void arch__sort(void)
{
- const int nmemb = ARRAY_SIZE(instructions);
+ const int nmemb = ARRAY_SIZE(architectures);
+
+ qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
+}
+
+static struct arch *arch__find(const char *name)
+{
+ const int nmemb = ARRAY_SIZE(architectures);
static bool sorted;
if (!sorted) {
- ins__sort();
+ arch__sort();
sorted = true;
}
- return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
+ return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
}
int symbol__alloc_hist(struct symbol *sym)
@@ -709,21 +757,18 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
}
-static void disasm_line__init_ins(struct disasm_line *dl, struct map *map)
+static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
{
- dl->ins = ins__find(dl->name);
+ dl->ins.ops = ins__find(arch, dl->ins.name);
- if (dl->ins == NULL)
+ if (!dl->ins.ops)
return;
- if (!dl->ins->ops)
- return;
-
- if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops, map) < 0)
- dl->ins = NULL;
+ if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, map) < 0)
+ dl->ins.ops = NULL;
}
-static int disasm_line__parse(char *line, char **namep, char **rawp)
+static int disasm_line__parse(char *line, const char **namep, char **rawp)
{
char *name = line, tmp;
@@ -756,12 +801,14 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
return 0;
out_free_name:
- zfree(namep);
+ free((void *)namep);
+ *namep = NULL;
return -1;
}
static struct disasm_line *disasm_line__new(s64 offset, char *line,
size_t privsize, int line_nr,
+ struct arch *arch,
struct map *map)
{
struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
@@ -774,10 +821,10 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line,
goto out_delete;
if (offset != -1) {
- if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
+ if (disasm_line__parse(dl->line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;
- disasm_line__init_ins(dl, map);
+ disasm_line__init_ins(dl, arch, map);
}
}
@@ -793,20 +840,21 @@ out_delete:
void disasm_line__free(struct disasm_line *dl)
{
zfree(&dl->line);
- zfree(&dl->name);
- if (dl->ins && dl->ins->ops->free)
- dl->ins->ops->free(&dl->ops);
+ if (dl->ins.ops && dl->ins.ops->free)
+ dl->ins.ops->free(&dl->ops);
else
ins__delete(&dl->ops);
+ free((void *)dl->ins.name);
+ dl->ins.name = NULL;
free(dl);
}
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
{
- if (raw || !dl->ins)
- return scnprintf(bf, size, "%-6.6s %s", dl->name, dl->ops.raw);
+ if (raw || !dl->ins.ops)
+ return scnprintf(bf, size, "%-6.6s %s", dl->ins.name, dl->ops.raw);
- return ins__scnprintf(dl->ins, bf, size, &dl->ops);
+ return ins__scnprintf(&dl->ins, bf, size, &dl->ops);
}
static void disasm__add(struct list_head *head, struct disasm_line *line)
@@ -1087,6 +1135,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
* The ops.raw part will be parsed further according to type of the instruction.
*/
static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
+ struct arch *arch,
FILE *file, size_t privsize,
int *line_nr)
{
@@ -1149,7 +1198,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
parsed_line = tmp2 + 1;
}
- dl = disasm_line__new(offset, parsed_line, privsize, *line_nr, map);
+ dl = disasm_line__new(offset, parsed_line, privsize, *line_nr, arch, map);
free(line);
(*line_nr)++;
@@ -1161,7 +1210,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
map__rip_2objdump(map, sym->start);
/* kcore has no symbols, so add the call target name */
- if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
+ if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) {
struct addr_map_symbol target = {
.map = map,
.addr = dl->ops.target.addr,
@@ -1191,8 +1240,8 @@ static void delete_last_nop(struct symbol *sym)
while (!list_empty(list)) {
dl = list_entry(list->prev, struct disasm_line, node);
- if (dl->ins && dl->ins->ops) {
- if (dl->ins->ops != &nop_ops)
+ if (dl->ins.ops) {
+ if (dl->ins.ops != &nop_ops)
return;
} else {
if (!strstr(dl->line, " nop ") &&
@@ -1280,10 +1329,23 @@ fallback:
return 0;
}
-int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
+static const char *annotate__norm_arch(const char *arch_name)
+{
+ struct utsname uts;
+
+ if (!arch_name) { /* Assume we are annotating locally. */
+ if (uname(&uts) < 0)
+ return NULL;
+ arch_name = uts.machine;
+ }
+ return normalize_arch((char *)arch_name);
+}
+
+int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize)
{
struct dso *dso = map->dso;
char command[PATH_MAX * 2];
+ struct arch *arch = NULL;
FILE *file;
char symfs_filename[PATH_MAX];
struct kcore_extract kce;
@@ -1297,6 +1359,22 @@ int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
if (err)
return err;
+ arch_name = annotate__norm_arch(arch_name);
+ if (!arch_name)
+ return -1;
+
+ arch = arch__find(arch_name);
+ if (arch == NULL)
+ return -ENOTSUP;
+
+ if (arch->init) {
+ err = arch->init(arch);
+ if (err) {
+ pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
+ return err;
+ }
+ }
+
pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
symfs_filename, sym->name, map->unmap_ip(map, sym->start),
map->unmap_ip(map, sym->end));
@@ -1395,7 +1473,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
nline = 0;
while (!feof(file)) {
- if (symbol__parse_objdump_line(sym, map, file, privsize,
+ if (symbol__parse_objdump_line(sym, map, arch, file, privsize,
&lineno) < 0)
break;
nline++;
@@ -1764,7 +1842,7 @@ static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
if (dl->offset == -1)
return fprintf(fp, "%s\n", dl->line);
- printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->name);
+ printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->ins.name);
if (dl->ops.raw[0] != '\0') {
printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
@@ -1793,7 +1871,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
struct rb_root source_line = RB_ROOT;
u64 len;
- if (symbol__disassemble(sym, map, 0) < 0)
+ if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0) < 0)
return -1;
len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 5bbcec173b82..87e4cadc5d27 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -11,7 +11,12 @@
#include <linux/rbtree.h>
#include <pthread.h>
-struct ins;
+struct ins_ops;
+
+struct ins {
+ const char *name;
+ struct ins_ops *ops;
+};
struct ins_operands {
char *raw;
@@ -28,24 +33,21 @@ struct ins_operands {
u64 addr;
} source;
struct {
- struct ins *ins;
+ struct ins ins;
struct ins_operands *ops;
} locked;
};
};
+struct arch;
+
struct ins_ops {
void (*free)(struct ins_operands *ops);
- int (*parse)(struct ins_operands *ops, struct map *map);
+ int (*parse)(struct arch *arch, struct ins_operands *ops, struct map *map);
int (*scnprintf)(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops);
};
-struct ins {
- const char *name;
- struct ins_ops *ops;
-};
-
bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
bool ins__is_ret(const struct ins *ins);
@@ -57,8 +59,7 @@ struct disasm_line {
struct list_head node;
s64 offset;
char *line;
- char *name;
- struct ins *ins;
+ struct ins ins;
int line_nr;
float ipc;
u64 cycles;
@@ -156,7 +157,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(struct symbol *sym);
-int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize);
+int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize);
enum symbol_disassemble_errno {
SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2b2c9b82f5ab..36c861103291 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
#include "debug.h"
#include "bpf-loader.h"
#include "bpf-prologue.h"
-#include "llvm-utils.h"
#include "probe-event.h"
#include "probe-finder.h" // for MAX_PROBES
#include "parse-events.h"
#include "llvm-utils.h"
+#include "c++/clang-c.h"
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
@@ -86,10 +86,21 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
void *obj_buf;
size_t obj_buf_sz;
- err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
- if (err)
- return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+ perf_clang__init();
+ err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+ perf_clang__cleanup();
+ if (err) {
+ pr_warning("bpf: builtin compilation failed: %d, try external compiler\n", err);
+ err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+ if (err)
+ return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+ } else
+ pr_debug("bpf: successfull builtin compilation\n");
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+ if (!IS_ERR(obj) && llvm_param.dump_obj)
+ llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
@@ -241,7 +252,7 @@ parse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev)
int err = 0;
if (!text) {
- pr_debug("No enough memory: dup config_str failed\n");
+ pr_debug("Not enough memory: dup config_str failed\n");
return ERR_PTR(-ENOMEM);
}
@@ -531,7 +542,7 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
ptevs = malloc(array_sz);
if (!ptevs) {
- pr_debug("No enough memory: alloc ptevs failed\n");
+ pr_debug("Not enough memory: alloc ptevs failed\n");
return -ENOMEM;
}
@@ -604,13 +615,13 @@ static int hook_load_preprocessor(struct bpf_program *prog)
priv->need_prologue = true;
priv->insns_buf = malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS);
if (!priv->insns_buf) {
- pr_debug("No enough memory: alloc insns_buf failed\n");
+ pr_debug("Not enough memory: alloc insns_buf failed\n");
return -ENOMEM;
}
priv->type_mapping = malloc(sizeof(int) * pev->ntevs);
if (!priv->type_mapping) {
- pr_debug("No enough memory: alloc type_mapping failed\n");
+ pr_debug("Not enough memory: alloc type_mapping failed\n");
return -ENOMEM;
}
memset(priv->type_mapping, -1,
@@ -864,7 +875,7 @@ bpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term)
op->k.array.ranges = memdup(term->array.ranges, memsz);
if (!op->k.array.ranges) {
- pr_debug("No enough memory to alloc indices for map\n");
+ pr_debug("Not enough memory to alloc indices for map\n");
return -ENOMEM;
}
op->key_type = BPF_MAP_KEY_RANGES;
@@ -929,7 +940,7 @@ bpf_map_priv__clone(struct bpf_map_priv *priv)
newpriv = zalloc(sizeof(*newpriv));
if (!newpriv) {
- pr_debug("No enough memory to alloc map private\n");
+ pr_debug("Not enough memory to alloc map private\n");
return NULL;
}
INIT_LIST_HEAD(&newpriv->ops_list);
@@ -960,7 +971,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
if (!priv) {
priv = zalloc(sizeof(*priv));
if (!priv) {
- pr_debug("No enough memory to alloc map private\n");
+ pr_debug("Not enough memory to alloc map private\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&priv->ops_list);
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
new file mode 100644
index 000000000000..988fef1b11d7
--- /dev/null
+++ b/tools/perf/util/c++/Build
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_CLANGLLVM) += clang.o
+libperf-$(CONFIG_CLANGLLVM) += clang-test.o
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
new file mode 100644
index 000000000000..0eadd792ab1f
--- /dev/null
+++ b/tools/perf/util/c++/clang-c.h
@@ -0,0 +1,43 @@
+#ifndef PERF_UTIL_CLANG_C_H
+#define PERF_UTIL_CLANG_C_H
+
+#include <stddef.h> /* for size_t */
+#include <util-cxx.h> /* for __maybe_unused */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+extern void perf_clang__init(void);
+extern void perf_clang__cleanup(void);
+
+extern int test__clang_to_IR(void);
+extern int test__clang_to_obj(void);
+
+extern int perf_clang__compile_bpf(const char *filename,
+ void **p_obj_buf,
+ size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+ void **p_obj_buf __maybe_unused,
+ size_t *p_obj_buf_sz __maybe_unused)
+{
+ return -ENOTSUP;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
new file mode 100644
index 000000000000..9b11e8c82798
--- /dev/null
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -0,0 +1,62 @@
+#include "clang.h"
+#include "clang-c.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+
+#include <util-cxx.h>
+#include <tests/llvm.h>
+#include <string>
+
+class perf_clang_scope {
+public:
+ explicit perf_clang_scope() {perf_clang__init();}
+ ~perf_clang_scope() {perf_clang__cleanup();}
+};
+
+static std::unique_ptr<llvm::Module>
+__test__clang_to_IR(void)
+{
+ unsigned int kernel_version;
+
+ if (fetch_kernel_version(&kernel_version, NULL, 0))
+ return std::unique_ptr<llvm::Module>(nullptr);
+
+ std::string cflag_kver("-DLINUX_VERSION_CODE=" +
+ std::to_string(kernel_version));
+
+ std::unique_ptr<llvm::Module> M =
+ perf::getModuleFromSource({cflag_kver.c_str()},
+ "perf-test.c",
+ test_llvm__bpf_base_prog);
+ return M;
+}
+
+extern "C" {
+int test__clang_to_IR(void)
+{
+ perf_clang_scope _scope;
+
+ auto M = __test__clang_to_IR();
+ if (!M)
+ return -1;
+ for (llvm::Function& F : *M)
+ if (F.getName() == "bpf_func__SyS_epoll_wait")
+ return 0;
+ return -1;
+}
+
+int test__clang_to_obj(void)
+{
+ perf_clang_scope _scope;
+
+ auto M = __test__clang_to_IR();
+ if (!M)
+ return -1;
+
+ auto Buffer = perf::getBPFObjectFromModule(&*M);
+ if (!Buffer)
+ return -1;
+ return 0;
+}
+
+}
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
new file mode 100644
index 000000000000..1e974152cac2
--- /dev/null
+++ b/tools/perf/util/c++/clang.cpp
@@ -0,0 +1,195 @@
+/*
+ * llvm C frontend for perf. Support dynamically compile C file
+ *
+ * Inspired by clang example code:
+ * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include <memory>
+
+#include "clang.h"
+#include "clang-c.h"
+
+namespace perf {
+
+static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
+
+using namespace clang;
+
+static CompilerInvocation *
+createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
+ DiagnosticsEngine& Diags)
+{
+ llvm::opt::ArgStringList CCArgs {
+ "-cc1",
+ "-triple", "bpf-pc-linux",
+ "-fsyntax-only",
+ "-ferror-limit", "19",
+ "-fmessage-length", "127",
+ "-O2",
+ "-nostdsysteminc",
+ "-nobuiltininc",
+ "-vectorize-loops",
+ "-vectorize-slp",
+ "-Wno-unused-value",
+ "-Wno-pointer-sign",
+ "-x", "c"};
+
+ CCArgs.append(CFlags.begin(), CFlags.end());
+ CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
+
+ FrontendOptions& Opts = CI->getFrontendOpts();
+ Opts.Inputs.clear();
+ Opts.Inputs.emplace_back(Path, IK_C);
+ return CI;
+}
+
+static std::unique_ptr<llvm::Module>
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+ StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+{
+ CompilerInstance Clang;
+ Clang.createDiagnostics();
+
+ Clang.setVirtualFileSystem(&*VFS);
+
+ IntrusiveRefCntPtr<CompilerInvocation> CI =
+ createCompilerInvocation(std::move(CFlags), Path,
+ Clang.getDiagnostics());
+ Clang.setInvocation(&*CI);
+
+ std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
+ if (!Clang.ExecuteAction(*Act))
+ return std::unique_ptr<llvm::Module>(nullptr);
+
+ return Act->takeModule();
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+ StringRef Name, StringRef Content)
+{
+ using namespace vfs;
+
+ llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
+ new OverlayFileSystem(getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
+ new InMemoryFileSystem(true));
+
+ /*
+ * pushOverlay helps setting working dir for MemFS. Must call
+ * before addFile.
+ */
+ OverlayFS->pushOverlay(MemFS);
+ MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
+
+ return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
+{
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
+ return getModuleFromSource(std::move(CFlags), Path, VFS);
+}
+
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module)
+{
+ using namespace llvm;
+
+ std::string TargetTriple("bpf-pc-linux");
+ std::string Error;
+ const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
+ if (!Target) {
+ llvm::errs() << Error;
+ return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
+ }
+
+ llvm::TargetOptions Opt;
+ TargetMachine *TargetMachine =
+ Target->createTargetMachine(TargetTriple,
+ "generic", "",
+ Opt, Reloc::Static);
+
+ Module->setDataLayout(TargetMachine->createDataLayout());
+ Module->setTargetTriple(TargetTriple);
+
+ std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
+ raw_svector_ostream ostream(*Buffer);
+
+ legacy::PassManager PM;
+ if (TargetMachine->addPassesToEmitFile(PM, ostream,
+ TargetMachine::CGFT_ObjectFile)) {
+ llvm::errs() << "TargetMachine can't emit a file of this type\n";
+ return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
+ }
+ PM.run(*Module);
+
+ return std::move(Buffer);
+}
+
+}
+
+extern "C" {
+void perf_clang__init(void)
+{
+ perf::LLVMCtx.reset(new llvm::LLVMContext());
+ LLVMInitializeBPFTargetInfo();
+ LLVMInitializeBPFTarget();
+ LLVMInitializeBPFTargetMC();
+ LLVMInitializeBPFAsmPrinter();
+}
+
+void perf_clang__cleanup(void)
+{
+ perf::LLVMCtx.reset(nullptr);
+ llvm::llvm_shutdown();
+}
+
+int perf_clang__compile_bpf(const char *filename,
+ void **p_obj_buf,
+ size_t *p_obj_buf_sz)
+{
+ using namespace perf;
+
+ if (!p_obj_buf || !p_obj_buf_sz)
+ return -EINVAL;
+
+ llvm::opt::ArgStringList CFlags;
+ auto M = getModuleFromSource(std::move(CFlags), filename);
+ if (!M)
+ return -EINVAL;
+ auto O = getBPFObjectFromModule(&*M);
+ if (!O)
+ return -EINVAL;
+
+ size_t size = O->size_in_bytes();
+ void *buffer;
+
+ buffer = malloc(size);
+ if (!buffer)
+ return -ENOMEM;
+ memcpy(buffer, O->data(), size);
+ *p_obj_buf = buffer;
+ *p_obj_buf_sz = size;
+ return 0;
+}
+}
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
new file mode 100644
index 000000000000..dd8b0427550d
--- /dev/null
+++ b/tools/perf/util/c++/clang.h
@@ -0,0 +1,26 @@
+#ifndef PERF_UTIL_CLANG_H
+#define PERF_UTIL_CLANG_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
+#include <memory>
+
+namespace perf {
+
+using namespace llvm;
+
+std::unique_ptr<Module>
+getModuleFromSource(opt::ArgStringList CFlags,
+ StringRef Name, StringRef Content);
+
+std::unique_ptr<Module>
+getModuleFromSource(opt::ArgStringList CFlags,
+ StringRef Path);
+
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module);
+
+}
+#endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 07fd30bc2f81..42922512c1c6 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -193,7 +193,6 @@ int perf_callchain_config(const char *var, const char *value)
if (!strcmp(var, "record-mode"))
return parse_callchain_record_opt(value, &callchain_param);
-#ifdef HAVE_DWARF_UNWIND_SUPPORT
if (!strcmp(var, "dump-size")) {
unsigned long size = 0;
int ret;
@@ -203,7 +202,6 @@ int perf_callchain_config(const char *var, const char *value)
return ret;
}
-#endif
if (!strcmp(var, "print-type"))
return parse_callchain_mode(value);
if (!strcmp(var, "order"))
@@ -440,6 +438,21 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
call->ip = cursor_node->ip;
call->ms.sym = cursor_node->sym;
call->ms.map = cursor_node->map;
+
+ if (cursor_node->branch) {
+ call->branch_count = 1;
+
+ if (cursor_node->branch_flags.predicted)
+ call->predicted_count = 1;
+
+ if (cursor_node->branch_flags.abort)
+ call->abort_count = 1;
+
+ call->cycles_count = cursor_node->branch_flags.cycles;
+ call->iter_count = cursor_node->nr_loop_iter;
+ call->samples_count = cursor_node->samples;
+ }
+
list_add_tail(&call->list, &node->val);
callchain_cursor_advance(cursor);
@@ -499,8 +512,23 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
right = node->ip;
}
- if (left == right)
+ if (left == right) {
+ if (node->branch) {
+ cnode->branch_count++;
+
+ if (node->branch_flags.predicted)
+ cnode->predicted_count++;
+
+ if (node->branch_flags.abort)
+ cnode->abort_count++;
+
+ cnode->cycles_count += node->branch_flags.cycles;
+ cnode->iter_count += node->nr_loop_iter;
+ cnode->samples_count += node->samples;
+ }
+
return MATCH_EQ;
+ }
return left > right ? MATCH_GT : MATCH_LT;
}
@@ -730,7 +758,8 @@ merge_chain_branch(struct callchain_cursor *cursor,
list_for_each_entry_safe(list, next_list, &src->val, list) {
callchain_cursor_append(cursor, list->ip,
- list->ms.map, list->ms.sym);
+ list->ms.map, list->ms.sym,
+ false, NULL, 0, 0);
list_del(&list->list);
free(list);
}
@@ -767,7 +796,9 @@ int callchain_merge(struct callchain_cursor *cursor,
}
int callchain_cursor_append(struct callchain_cursor *cursor,
- u64 ip, struct map *map, struct symbol *sym)
+ u64 ip, struct map *map, struct symbol *sym,
+ bool branch, struct branch_flags *flags,
+ int nr_loop_iter, int samples)
{
struct callchain_cursor_node *node = *cursor->last;
@@ -782,6 +813,13 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
node->ip = ip;
node->map = map;
node->sym = sym;
+ node->branch = branch;
+ node->nr_loop_iter = nr_loop_iter;
+ node->samples = samples;
+
+ if (flags)
+ memcpy(&node->branch_flags, flags,
+ sizeof(struct branch_flags));
cursor->nr++;
@@ -939,6 +977,163 @@ int callchain_node__fprintf_value(struct callchain_node *node,
return 0;
}
+static void callchain_counts_value(struct callchain_node *node,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count)
+{
+ struct callchain_list *clist;
+
+ list_for_each_entry(clist, &node->val, list) {
+ if (branch_count)
+ *branch_count += clist->branch_count;
+
+ if (predicted_count)
+ *predicted_count += clist->predicted_count;
+
+ if (abort_count)
+ *abort_count += clist->abort_count;
+
+ if (cycles_count)
+ *cycles_count += clist->cycles_count;
+ }
+}
+
+static int callchain_node_branch_counts_cumul(struct callchain_node *node,
+ u64 *branch_count,
+ u64 *predicted_count,
+ u64 *abort_count,
+ u64 *cycles_count)
+{
+ struct callchain_node *child;
+ struct rb_node *n;
+
+ n = rb_first(&node->rb_root_in);
+ while (n) {
+ child = rb_entry(n, struct callchain_node, rb_node_in);
+ n = rb_next(n);
+
+ callchain_node_branch_counts_cumul(child, branch_count,
+ predicted_count,
+ abort_count,
+ cycles_count);
+
+ callchain_counts_value(child, branch_count,
+ predicted_count, abort_count,
+ cycles_count);
+ }
+
+ return 0;
+}
+
+int callchain_branch_counts(struct callchain_root *root,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count)
+{
+ if (branch_count)
+ *branch_count = 0;
+
+ if (predicted_count)
+ *predicted_count = 0;
+
+ if (abort_count)
+ *abort_count = 0;
+
+ if (cycles_count)
+ *cycles_count = 0;
+
+ return callchain_node_branch_counts_cumul(&root->node,
+ branch_count,
+ predicted_count,
+ abort_count,
+ cycles_count);
+}
+
+static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
+ u64 branch_count, u64 predicted_count,
+ u64 abort_count, u64 cycles_count,
+ u64 iter_count, u64 samples_count)
+{
+ double predicted_percent = 0.0;
+ const char *null_str = "";
+ char iter_str[32];
+ char *str;
+ u64 cycles = 0;
+
+ if (branch_count == 0) {
+ if (fp)
+ return fprintf(fp, " (calltrace)");
+
+ return scnprintf(bf, bfsize, " (calltrace)");
+ }
+
+ if (iter_count && samples_count) {
+ scnprintf(iter_str, sizeof(iter_str),
+ ", iterations:%" PRId64 "",
+ iter_count / samples_count);
+ str = iter_str;
+ } else
+ str = (char *)null_str;
+
+ predicted_percent = predicted_count * 100.0 / branch_count;
+ cycles = cycles_count / branch_count;
+
+ if ((predicted_percent >= 100.0) && (abort_count == 0)) {
+ if (fp)
+ return fprintf(fp, " (cycles:%" PRId64 "%s)",
+ cycles, str);
+
+ return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
+ cycles, str);
+ }
+
+ if ((predicted_percent < 100.0) && (abort_count == 0)) {
+ if (fp)
+ return fprintf(fp,
+ " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+ predicted_percent, cycles, str);
+
+ return scnprintf(bf, bfsize,
+ " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+ predicted_percent, cycles, str);
+ }
+
+ if (fp)
+ return fprintf(fp,
+ " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+ predicted_percent, abort_count, cycles, str);
+
+ return scnprintf(bf, bfsize,
+ " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+ predicted_percent, abort_count, cycles, str);
+}
+
+int callchain_list_counts__printf_value(struct callchain_node *node,
+ struct callchain_list *clist,
+ FILE *fp, char *bf, int bfsize)
+{
+ u64 branch_count, predicted_count;
+ u64 abort_count, cycles_count;
+ u64 iter_count = 0, samples_count = 0;
+
+ branch_count = clist->branch_count;
+ predicted_count = clist->predicted_count;
+ abort_count = clist->abort_count;
+ cycles_count = clist->cycles_count;
+
+ if (node) {
+ struct callchain_list *call;
+
+ list_for_each_entry(call, &node->val, list) {
+ iter_count += call->iter_count;
+ samples_count += call->samples_count;
+ }
+ }
+
+ return callchain_counts_printf(fp, bf, bfsize, branch_count,
+ predicted_count, abort_count,
+ cycles_count, iter_count, samples_count);
+}
+
static void free_callchain_node(struct callchain_node *node)
{
struct callchain_list *list, *tmp;
@@ -1039,3 +1234,30 @@ out:
}
return -ENOMEM;
}
+
+int callchain_cursor__copy(struct callchain_cursor *dst,
+ struct callchain_cursor *src)
+{
+ int rc = 0;
+
+ callchain_cursor_reset(dst);
+ callchain_cursor_commit(src);
+
+ while (true) {
+ struct callchain_cursor_node *node;
+
+ node = callchain_cursor_current(src);
+ if (node == NULL)
+ break;
+
+ rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
+ node->branch, &node->branch_flags,
+ node->nr_loop_iter, node->samples);
+ if (rc)
+ break;
+
+ callchain_cursor_advance(src);
+ }
+
+ return rc;
+}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 13e75549c440..35c8e379530f 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -11,11 +11,7 @@
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
-#ifdef HAVE_DWARF_UNWIND_SUPPORT
# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
-#else
-# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|lbr)\n"
-#endif
#define RECORD_SIZE_HELP \
HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
@@ -115,6 +111,12 @@ struct callchain_list {
bool unfolded;
bool has_children;
};
+ u64 branch_count;
+ u64 predicted_count;
+ u64 abort_count;
+ u64 cycles_count;
+ u64 iter_count;
+ u64 samples_count;
char *srcline;
struct list_head list;
};
@@ -129,6 +131,10 @@ struct callchain_cursor_node {
u64 ip;
struct map *map;
struct symbol *sym;
+ bool branch;
+ struct branch_flags branch_flags;
+ int nr_loop_iter;
+ int samples;
struct callchain_cursor_node *next;
};
@@ -183,7 +189,9 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
}
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
- struct map *map, struct symbol *sym);
+ struct map *map, struct symbol *sym,
+ bool branch, struct branch_flags *flags,
+ int nr_loop_iter, int samples);
/* Close a cursor writing session. Initialize for the reader */
static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -208,6 +216,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
cursor->pos++;
}
+int callchain_cursor__copy(struct callchain_cursor *dst,
+ struct callchain_cursor *src);
+
struct option;
struct hist_entry;
@@ -261,8 +272,16 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
int callchain_node__fprintf_value(struct callchain_node *node,
FILE *fp, u64 total);
+int callchain_list_counts__printf_value(struct callchain_node *node,
+ struct callchain_list *clist,
+ FILE *fp, char *bf, int bfsize);
+
void free_callchain(struct callchain_root *root);
void decay_callchain(struct callchain_root *root);
int callchain_node__make_parent_list(struct callchain_node *node);
+int callchain_branch_counts(struct callchain_root *root,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count);
+
#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 18dae745034f..3d906dbbef74 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -594,6 +594,19 @@ static int collect_config(const char *var, const char *value,
goto out_free;
}
+ /* perf_config_set can contain both user and system config items.
+ * So we should know where each value is from.
+ * The classification would be needed when a particular config file
+ * is overwrited by setting feature i.e. set_config().
+ */
+ if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) {
+ section->from_system_config = true;
+ item->from_system_config = true;
+ } else {
+ section->from_system_config = false;
+ item->from_system_config = false;
+ }
+
ret = set_value(item, value);
return ret;
@@ -602,6 +615,13 @@ out_free:
return -1;
}
+int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
+ const char *var, const char *value)
+{
+ config_file_name = file_name;
+ return collect_config(var, value, set);
+}
+
static int perf_config_set__init(struct perf_config_set *set)
{
int ret = -1;
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 6f813d46045e..1a59a6b43f8b 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -7,12 +7,14 @@
struct perf_config_item {
char *name;
char *value;
+ bool from_system_config;
struct list_head node;
};
struct perf_config_section {
char *name;
struct list_head items;
+ bool from_system_config;
struct list_head node;
};
@@ -33,6 +35,8 @@ const char *perf_etc_perfconfig(void);
struct perf_config_set *perf_config_set__new(void);
void perf_config_set__delete(struct perf_config_set *set);
+int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
+ const char *var, const char *value);
void perf_config__init(void);
void perf_config__exit(void);
void perf_config__refresh(void);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5e65a2..c735c53a26f8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -177,6 +177,8 @@ enum {
PERF_IP_FLAG_TRACE_BEGIN |\
PERF_IP_FLAG_TRACE_END)
+#define MAX_INSN 16
+
struct perf_sample {
u64 ip;
u32 pid, tid;
@@ -193,6 +195,7 @@ struct perf_sample {
u32 flags;
u16 insn_len;
u8 cpumode;
+ char insn[MAX_INSN];
void *raw_data;
struct ip_callchain *callchain;
struct branch_stack *branch_stack;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8bc271141d9d..b2365a63db45 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -28,6 +28,7 @@
#include "debug.h"
#include "trace-event.h"
#include "stat.h"
+#include "util/parse-branch-options.h"
static struct {
bool sample_id_all;
@@ -708,6 +709,14 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
callgraph_buf = term->val.callgraph;
break;
+ case PERF_EVSEL__CONFIG_TERM_BRANCH:
+ if (term->val.branch && strcmp(term->val.branch, "no")) {
+ perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
+ parse_branch_str(term->val.branch,
+ &attr->branch_sample_type);
+ } else
+ perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
+ break;
case PERF_EVSEL__CONFIG_TERM_STACK_USER:
dump_size = term->val.stack_user;
break;
@@ -1472,7 +1481,7 @@ retry_sample_id:
group_fd = get_group_fd(evsel, cpu, thread);
retry_open:
- pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n",
+ pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
pid, cpus->map[cpu], group_fd, flags);
FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
@@ -1481,11 +1490,13 @@ retry_open:
group_fd, flags);
if (FD(evsel, cpu, thread) < 0) {
err = -errno;
- pr_debug2("sys_perf_event_open failed, error %d\n",
+ pr_debug2("\nsys_perf_event_open failed, error %d\n",
err);
goto try_fallback;
}
+ pr_debug2(" = %d\n", FD(evsel, cpu, thread));
+
if (evsel->bpf_fd >= 0) {
int evt_fd = FD(evsel, cpu, thread);
int bpf_fd = evsel->bpf_fd;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1503b0ecdff..6abb89cd27f9 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -47,6 +47,7 @@ enum {
PERF_EVSEL__CONFIG_TERM_MAX_STACK,
PERF_EVSEL__CONFIG_TERM_OVERWRITE,
PERF_EVSEL__CONFIG_TERM_DRV_CFG,
+ PERF_EVSEL__CONFIG_TERM_BRANCH,
PERF_EVSEL__CONFIG_TERM_MAX,
};
@@ -63,6 +64,7 @@ struct perf_evsel_config_term {
int max_stack;
bool inherit;
bool overwrite;
+ char *branch;
} val;
};
@@ -389,6 +391,8 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
#define EVSEL__PRINT_ONELINE (1<<4)
#define EVSEL__PRINT_SRCLINE (1<<5)
#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
+#define EVSEL__PRINT_CALLCHAIN_ARROW (1<<7)
+#define EVSEL__PRINT_SKIP_IGNORED (1<<8)
struct callchain_cursor;
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 662a0a6182e7..6b2925542c0a 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -108,7 +108,10 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
+ int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW;
+ int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED;
char s = print_oneline ? ' ' : '\t';
+ bool first = true;
if (sample->callchain) {
struct addr_location node_al;
@@ -122,8 +125,14 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
if (!node)
break;
+ if (node->sym && node->sym->ignore && print_skip_ignored)
+ goto next;
+
printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
+ if (print_arrow && !first)
+ printed += fprintf(fp, " <-");
+
if (print_ip)
printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
@@ -137,7 +146,8 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
if (print_symoffset) {
printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
- print_unknown_as_addr, fp);
+ print_unknown_as_addr,
+ true, fp);
} else {
printed += __symbol__fprintf_symname(node->sym, &node_al,
print_unknown_as_addr, fp);
@@ -156,6 +166,16 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
if (!print_oneline)
printed += fprintf(fp, "\n");
+ if (symbol_conf.bt_stop_list &&
+ node->sym &&
+ node->sym->name &&
+ strlist__has_entry(symbol_conf.bt_stop_list,
+ node->sym->name)) {
+ break;
+ }
+
+ first = false;
+next:
callchain_cursor_advance(cursor);
}
}
@@ -188,7 +208,8 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
printed += fprintf(fp, " ");
if (print_symoffset) {
printed += __symbol__fprintf_symname_offs(al->sym, al,
- print_unknown_as_addr, fp);
+ print_unknown_as_addr,
+ true, fp);
} else {
printed += __symbol__fprintf_symname(al->sym, al,
print_unknown_as_addr, fp);
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
index c1ef805c6a8f..c540d47583e7 100644
--- a/tools/perf/util/genelf.c
+++ b/tools/perf/util/genelf.c
@@ -19,12 +19,18 @@
#include <limits.h>
#include <fcntl.h>
#include <err.h>
+#ifdef HAVE_DWARF_SUPPORT
#include <dwarf.h>
+#endif
#include "perf.h"
#include "genelf.h"
#include "../util/jitdump.h"
+#ifndef NT_GNU_BUILD_ID
+#define NT_GNU_BUILD_ID 3
+#endif
+
#define JVMTI
#define BUILD_ID_URANDOM /* different uuid for each run */
@@ -67,6 +73,8 @@ static char shd_string_table[] = {
'.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
'.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
'.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
+ '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */
+ '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */
};
static struct buildid_note {
@@ -147,6 +155,86 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod
}
#endif
+static int
+jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size,
+ uint64_t unwinding_size, uint64_t base_offset)
+{
+ Elf_Data *d;
+ Elf_Scn *scn;
+ Elf_Shdr *shdr;
+ uint64_t unwinding_table_size = unwinding_size - unwinding_header_size;
+
+ /*
+ * setup eh_frame section
+ */
+ scn = elf_newscn(e);
+ if (!scn) {
+ warnx("cannot create section");
+ return -1;
+ }
+
+ d = elf_newdata(scn);
+ if (!d) {
+ warnx("cannot get new data");
+ return -1;
+ }
+
+ d->d_align = 8;
+ d->d_off = 0LL;
+ d->d_buf = unwinding;
+ d->d_type = ELF_T_BYTE;
+ d->d_size = unwinding_table_size;
+ d->d_version = EV_CURRENT;
+
+ shdr = elf_getshdr(scn);
+ if (!shdr) {
+ warnx("cannot get section header");
+ return -1;
+ }
+
+ shdr->sh_name = 104;
+ shdr->sh_type = SHT_PROGBITS;
+ shdr->sh_addr = base_offset;
+ shdr->sh_flags = SHF_ALLOC;
+ shdr->sh_entsize = 0;
+
+ /*
+ * setup eh_frame_hdr section
+ */
+ scn = elf_newscn(e);
+ if (!scn) {
+ warnx("cannot create section");
+ return -1;
+ }
+
+ d = elf_newdata(scn);
+ if (!d) {
+ warnx("cannot get new data");
+ return -1;
+ }
+
+ d->d_align = 4;
+ d->d_off = 0LL;
+ d->d_buf = unwinding + unwinding_table_size;
+ d->d_type = ELF_T_BYTE;
+ d->d_size = unwinding_header_size;
+ d->d_version = EV_CURRENT;
+
+ shdr = elf_getshdr(scn);
+ if (!shdr) {
+ warnx("cannot get section header");
+ return -1;
+ }
+
+ shdr->sh_name = 90;
+ shdr->sh_type = SHT_PROGBITS;
+ shdr->sh_addr = base_offset + unwinding_table_size;
+ shdr->sh_flags = SHF_ALLOC;
+ shdr->sh_entsize = 0;
+
+ return 0;
+}
+
/*
* fd: file descriptor open for writing for the output file
* load_addr: code load address (could be zero, just used for buildid)
@@ -157,13 +245,15 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod
int
jit_write_elf(int fd, uint64_t load_addr, const char *sym,
const void *code, int csize,
- void *debug, int nr_debug_entries)
+ void *debug __maybe_unused, int nr_debug_entries __maybe_unused,
+ void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size)
{
Elf *e;
Elf_Data *d;
Elf_Scn *scn;
Elf_Ehdr *ehdr;
Elf_Shdr *shdr;
+ uint64_t eh_frame_base_offset;
char *strsym = NULL;
int symlen;
int retval = -1;
@@ -194,7 +284,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
ehdr->e_type = ET_DYN;
ehdr->e_entry = GEN_ELF_TEXT_OFFSET;
ehdr->e_version = EV_CURRENT;
- ehdr->e_shstrndx= 2; /* shdr index for section name */
+ ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */
/*
* setup text section
@@ -231,6 +321,18 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
shdr->sh_entsize = 0;
/*
+ * Setup .eh_frame_hdr and .eh_frame
+ */
+ if (unwinding) {
+ eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize);
+ retval = jit_add_eh_frame_info(e, unwinding,
+ unwinding_header_size, unwinding_size,
+ eh_frame_base_offset);
+ if (retval)
+ goto error;
+ }
+
+ /*
* setup section headers string table
*/
scn = elf_newscn(e);
@@ -298,7 +400,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
shdr->sh_type = SHT_SYMTAB;
shdr->sh_flags = 0;
shdr->sh_entsize = sizeof(Elf_Sym);
- shdr->sh_link = 4; /* index of .strtab section */
+ shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */
/*
* setup symbols string table
@@ -386,11 +488,14 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
shdr->sh_size = sizeof(bnote);
shdr->sh_entsize = 0;
+#ifdef HAVE_DWARF_SUPPORT
if (debug && nr_debug_entries) {
retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries);
if (retval)
goto error;
- } else {
+ } else
+#endif
+ {
if (elf_update(e, ELF_C_WRITE) < 0) {
warnx("elf_update 4 failed");
goto error;
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
index 2fbeb59c4bdd..2424bd9862a3 100644
--- a/tools/perf/util/genelf.h
+++ b/tools/perf/util/genelf.h
@@ -3,9 +3,12 @@
/* genelf.c */
int jit_write_elf(int fd, uint64_t code_addr, const char *sym,
- const void *code, int csize, void *debug, int nr_debug_entries);
+ const void *code, int csize, void *debug, int nr_debug_entries,
+ void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size);
+#ifdef HAVE_DWARF_SUPPORT
/* genelf_debug.c */
int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries);
+#endif
#if defined(__arm__)
#define GEN_ELF_ARCH EM_ARM
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2f3eded54b0c..d89c9c7ef4e5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2250,11 +2250,28 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
struct header_print_data hd;
struct perf_header *header = &session->header;
int fd = perf_data_file__fd(session->file);
+ struct stat st;
+ int ret, bit;
+
hd.fp = fp;
hd.full = full;
+ ret = fstat(fd, &st);
+ if (ret == -1)
+ return -1;
+
+ fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
+
perf_header__process_sections(header, fd, &hd,
perf_file_section__fprintf_info);
+
+ fprintf(fp, "# missing features: ");
+ for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
+ if (bit)
+ fprintf(fp, "%s ", feat_ops[bit].name);
+ }
+
+ fprintf(fp, "\n");
return 0;
}
@@ -2273,7 +2290,7 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
err = feat_ops[type].write(fd, h, evlist);
if (err < 0) {
- pr_debug("failed to write feature %d\n", type);
+ pr_debug("failed to write feature %s\n", feat_ops[type].name);
/* undo anything written */
lseek(fd, (*p)->offset, SEEK_SET);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a69f027368ef..6770a9645609 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1195,6 +1195,7 @@ static void hist_entry__check_and_remove_filter(struct hist_entry *he,
case HIST_FILTER__GUEST:
case HIST_FILTER__HOST:
case HIST_FILTER__SOCKET:
+ case HIST_FILTER__C2C:
default:
return;
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 9928fed8bc59..d4b6514eeef5 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -22,6 +22,7 @@ enum hist_filter {
HIST_FILTER__GUEST,
HIST_FILTER__HOST,
HIST_FILTER__SOCKET,
+ HIST_FILTER__C2C,
};
enum hist_column {
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index f545ec1e758a..6c2eb5da4afc 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -295,6 +295,7 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
sample.cpu = btsq->cpu;
sample.flags = btsq->sample_flags;
sample.insn_len = btsq->intel_pt_insn.length;
+ memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
if (bts->synth_opts.inject) {
event.sample.header.size = bts->branches_event_size;
@@ -319,15 +320,12 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
struct machine *machine = btsq->bts->machine;
struct thread *thread;
struct addr_location al;
- unsigned char buf[1024];
- size_t bufsz;
+ unsigned char buf[INTEL_PT_INSN_BUF_SZ];
ssize_t len;
int x86_64;
uint8_t cpumode;
int err = -1;
- bufsz = intel_pt_insn_max_size();
-
if (machine__kernel_ip(machine, ip))
cpumode = PERF_RECORD_MISC_KERNEL;
else
@@ -341,7 +339,8 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
if (!al.map || !al.map->dso)
goto out_put;
- len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, bufsz);
+ len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
+ INTEL_PT_INSN_BUF_SZ);
if (len <= 0)
goto out_put;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 16c06d3ae577..e4e7dc781d21 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -980,6 +980,8 @@ out:
out_no_progress:
decoder->state.insn_op = intel_pt_insn->op;
decoder->state.insn_len = intel_pt_insn->length;
+ memcpy(decoder->state.insn, intel_pt_insn->buf,
+ INTEL_PT_INSN_BUF_SZ);
if (decoder->tx_flags & INTEL_PT_IN_TX)
decoder->state.flags |= INTEL_PT_IN_TX;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 89399985fa4d..e90619a43c0c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -66,6 +66,7 @@ struct intel_pt_state {
uint32_t flags;
enum intel_pt_insn_op insn_op;
int insn_len;
+ char insn[INTEL_PT_INSN_BUF_SZ];
};
struct intel_pt_insn;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index d23138c06665..7913363bde5c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,6 +27,10 @@
#include "intel-pt-insn-decoder.h"
+#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
+#error Instruction buffer size too small
+#endif
+
/* Based on branch_type() from perf_event_intel_lbr.c */
static void intel_pt_insn_decoder(struct insn *insn,
struct intel_pt_insn *intel_pt_insn)
@@ -166,10 +170,10 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
if (!insn_complete(&insn) || insn.length > len)
return -1;
intel_pt_insn_decoder(&insn, intel_pt_insn);
- if (insn.length < INTEL_PT_INSN_DBG_BUF_SZ)
+ if (insn.length < INTEL_PT_INSN_BUF_SZ)
memcpy(intel_pt_insn->buf, buf, insn.length);
else
- memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_DBG_BUF_SZ);
+ memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
return 0;
}
@@ -211,11 +215,6 @@ int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
return 0;
}
-size_t intel_pt_insn_max_size(void)
-{
- return MAX_INSN_SIZE;
-}
-
int intel_pt_insn_type(enum intel_pt_insn_op op)
{
switch (op) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
index b0adbf37323e..37ec5627ae9b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#define INTEL_PT_INSN_DESC_MAX 32
-#define INTEL_PT_INSN_DBG_BUF_SZ 16
+#define INTEL_PT_INSN_BUF_SZ 16
enum intel_pt_insn_op {
INTEL_PT_OP_OTHER,
@@ -47,7 +47,7 @@ struct intel_pt_insn {
enum intel_pt_insn_branch branch;
int length;
int32_t rel;
- unsigned char buf[INTEL_PT_INSN_DBG_BUF_SZ];
+ unsigned char buf[INTEL_PT_INSN_BUF_SZ];
};
int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
@@ -58,8 +58,6 @@ const char *intel_pt_insn_name(enum intel_pt_insn_op op);
int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
size_t buf_len);
-size_t intel_pt_insn_max_size(void);
-
int intel_pt_insn_type(enum intel_pt_insn_op op);
#endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index 319bef33a64b..e02bc7b166a0 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -119,8 +119,8 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
if (intel_pt_log_open())
return;
- if (len > INTEL_PT_INSN_DBG_BUF_SZ)
- len = INTEL_PT_INSN_DBG_BUF_SZ;
+ if (len > INTEL_PT_INSN_BUF_SZ)
+ len = INTEL_PT_INSN_BUF_SZ;
intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
fprintf(f, "%s\n", desc);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index dc041d4368c8..85d5eeb66c75 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -143,6 +143,7 @@ struct intel_pt_queue {
u32 flags;
u16 insn_len;
u64 last_insn_cnt;
+ char insn[INTEL_PT_INSN_BUF_SZ];
};
static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
@@ -315,6 +316,7 @@ struct intel_pt_cache_entry {
enum intel_pt_insn_branch branch;
int length;
int32_t rel;
+ char insn[INTEL_PT_INSN_BUF_SZ];
};
static int intel_pt_config_div(const char *var, const char *value, void *data)
@@ -400,6 +402,7 @@ static int intel_pt_cache_add(struct dso *dso, struct machine *machine,
e->branch = intel_pt_insn->branch;
e->length = intel_pt_insn->length;
e->rel = intel_pt_insn->rel;
+ memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ);
err = auxtrace_cache__add(c, offset, &e->entry);
if (err)
@@ -428,8 +431,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
struct machine *machine = ptq->pt->machine;
struct thread *thread;
struct addr_location al;
- unsigned char buf[1024];
- size_t bufsz;
+ unsigned char buf[INTEL_PT_INSN_BUF_SZ];
ssize_t len;
int x86_64;
u8 cpumode;
@@ -437,11 +439,11 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
u64 insn_cnt = 0;
bool one_map = true;
+ intel_pt_insn->length = 0;
+
if (to_ip && *ip == to_ip)
goto out_no_cache;
- bufsz = intel_pt_insn_max_size();
-
if (*ip >= ptq->pt->kernel_start)
cpumode = PERF_RECORD_MISC_KERNEL;
else
@@ -478,6 +480,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
intel_pt_insn->branch = e->branch;
intel_pt_insn->length = e->length;
intel_pt_insn->rel = e->rel;
+ memcpy(intel_pt_insn->buf, e->insn,
+ INTEL_PT_INSN_BUF_SZ);
intel_pt_log_insn_no_data(intel_pt_insn, *ip);
return 0;
}
@@ -493,7 +497,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
while (1) {
len = dso__data_read_offset(al.map->dso, machine,
- offset, buf, bufsz);
+ offset, buf,
+ INTEL_PT_INSN_BUF_SZ);
if (len <= 0)
return -EINVAL;
@@ -900,6 +905,7 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
if (ptq->state->flags & INTEL_PT_IN_TX)
ptq->flags |= PERF_IP_FLAG_IN_TX;
ptq->insn_len = ptq->state->insn_len;
+ memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
}
}
@@ -1080,6 +1086,7 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
sample.cpu = ptq->cpu;
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;
+ memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
/*
* perf report cannot handle events without a branch stack when using
@@ -1141,6 +1148,7 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
sample.cpu = ptq->cpu;
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;
+ memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
@@ -1203,6 +1211,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
sample.cpu = ptq->cpu;
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;
+ memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
if (pt->synth_opts.callchain) {
thread_stack__sample(ptq->thread, ptq->chain,
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index 95f0884aae02..c9a941ef0f6d 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -37,6 +37,10 @@ struct jit_buf_desc {
bool needs_bswap; /* handles cross-endianess */
bool use_arch_timestamp;
void *debug_data;
+ void *unwinding_data;
+ uint64_t unwinding_size;
+ uint64_t unwinding_mapped_size;
+ uint64_t eh_frame_hdr_size;
size_t nr_debug_entries;
uint32_t code_load_count;
u64 bytes_written;
@@ -68,7 +72,10 @@ jit_emit_elf(char *filename,
const void *code,
int csize,
void *debug,
- int nr_debug_entries)
+ int nr_debug_entries,
+ void *unwinding,
+ uint32_t unwinding_header_size,
+ uint32_t unwinding_size)
{
int ret, fd;
@@ -81,7 +88,8 @@ jit_emit_elf(char *filename,
return -1;
}
- ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries);
+ ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries,
+ unwinding, unwinding_header_size, unwinding_size);
close(fd);
@@ -172,6 +180,12 @@ jit_open(struct jit_buf_desc *jd, const char *name)
header.elf_mach,
jd->use_arch_timestamp);
+ if (header.version > JITHEADER_VERSION) {
+ pr_err("wrong jitdump version %u, expected " STR(JITHEADER_VERSION),
+ header.version);
+ goto error;
+ }
+
if (header.flags & JITDUMP_FLAGS_RESERVED) {
pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
(unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED);
@@ -263,8 +277,7 @@ jit_get_next_entry(struct jit_buf_desc *jd)
return NULL;
if (id >= JIT_CODE_MAX) {
- pr_warning("next_entry: unknown prefix %d, skipping\n", id);
- return NULL;
+ pr_warning("next_entry: unknown record type %d, skipping\n", id);
}
if (bs > jd->bufsize) {
void *n;
@@ -296,6 +309,13 @@ jit_get_next_entry(struct jit_buf_desc *jd)
}
}
break;
+ case JIT_CODE_UNWINDING_INFO:
+ if (jd->needs_bswap) {
+ jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size);
+ jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size);
+ jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size);
+ }
+ break;
case JIT_CODE_CLOSE:
break;
case JIT_CODE_LOAD:
@@ -322,7 +342,8 @@ jit_get_next_entry(struct jit_buf_desc *jd)
break;
case JIT_CODE_MAX:
default:
- return NULL;
+ /* skip unknown record (we have read them) */
+ break;
}
return jr;
}
@@ -370,7 +391,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
u16 idr_size;
const char *sym;
uint32_t count;
- int ret, csize;
+ int ret, csize, usize;
pid_t pid, tid;
struct {
u32 pid, tid;
@@ -380,6 +401,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
pid = jr->load.pid;
tid = jr->load.tid;
csize = jr->load.code_size;
+ usize = jd->unwinding_mapped_size;
addr = jr->load.code_addr;
sym = (void *)((unsigned long)jr + sizeof(jr->load));
code = (unsigned long)jr + jr->load.p.total_size - csize;
@@ -400,7 +422,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
size = PERF_ALIGN(size, sizeof(u64));
uaddr = (uintptr_t)code;
- ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries);
+ ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries,
+ jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size);
if (jd->debug_data && jd->nr_debug_entries) {
free(jd->debug_data);
@@ -408,6 +431,14 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
jd->nr_debug_entries = 0;
}
+ if (jd->unwinding_data && jd->eh_frame_hdr_size) {
+ free(jd->unwinding_data);
+ jd->unwinding_data = NULL;
+ jd->eh_frame_hdr_size = 0;
+ jd->unwinding_mapped_size = 0;
+ jd->unwinding_size = 0;
+ }
+
if (ret) {
free(event);
return -1;
@@ -422,7 +453,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
event->mmap2.start = addr;
- event->mmap2.len = csize;
+ event->mmap2.len = usize ? ALIGN_8(csize) + usize : csize;
event->mmap2.pid = pid;
event->mmap2.tid = tid;
event->mmap2.ino = st.st_ino;
@@ -473,6 +504,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
char *filename;
size_t size;
struct stat st;
+ int usize;
u16 idr_size;
int ret;
pid_t pid, tid;
@@ -483,6 +515,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
pid = jr->move.pid;
tid = jr->move.tid;
+ usize = jd->unwinding_mapped_size;
idr_size = jd->machine->id_hdr_size;
/*
@@ -511,7 +544,8 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
(sizeof(event->mmap2.filename) - size) + idr_size);
event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
event->mmap2.start = jr->move.new_code_addr;
- event->mmap2.len = jr->move.code_size;
+ event->mmap2.len = usize ? ALIGN_8(jr->move.code_size) + usize
+ : jr->move.code_size;
event->mmap2.pid = pid;
event->mmap2.tid = tid;
event->mmap2.ino = st.st_ino;
@@ -578,10 +612,35 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)
}
static int
+jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr)
+{
+ void *unwinding_data;
+ uint32_t unwinding_data_size;
+
+ if (!(jd && jr))
+ return -1;
+
+ unwinding_data_size = jr->prefix.total_size - sizeof(jr->unwinding);
+ unwinding_data = malloc(unwinding_data_size);
+ if (!unwinding_data)
+ return -1;
+
+ memcpy(unwinding_data, &jr->unwinding.unwinding_data,
+ unwinding_data_size);
+
+ jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size;
+ jd->unwinding_size = jr->unwinding.unwinding_size;
+ jd->unwinding_mapped_size = jr->unwinding.mapped_size;
+ jd->unwinding_data = unwinding_data;
+
+ return 0;
+}
+
+static int
jit_process_dump(struct jit_buf_desc *jd)
{
union jr_entry *jr;
- int ret;
+ int ret = 0;
while ((jr = jit_get_next_entry(jd))) {
switch(jr->prefix.id) {
@@ -594,6 +653,9 @@ jit_process_dump(struct jit_buf_desc *jd)
case JIT_CODE_DEBUG_INFO:
ret = jit_repipe_debug_info(jd, jr);
break;
+ case JIT_CODE_UNWINDING_INFO:
+ ret = jit_repipe_unwinding_info(jd, jr);
+ break;
default:
ret = 0;
continue;
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
index bcacd20d0c1c..c6b9b67f43bf 100644
--- a/tools/perf/util/jitdump.h
+++ b/tools/perf/util/jitdump.h
@@ -19,6 +19,7 @@
#define JITHEADER_MAGIC_SW 0x4454694A
#define PADDING_8ALIGNED(x) ((((x) + 7) & 7) ^ 7)
+#define ALIGN_8(x) (((x) + 7) & (~7))
#define JITHEADER_VERSION 1
@@ -48,6 +49,7 @@ enum jit_record_type {
JIT_CODE_MOVE = 1,
JIT_CODE_DEBUG_INFO = 2,
JIT_CODE_CLOSE = 3,
+ JIT_CODE_UNWINDING_INFO = 4,
JIT_CODE_MAX,
};
@@ -101,12 +103,22 @@ struct jr_code_debug_info {
struct debug_entry entries[0];
};
+struct jr_code_unwinding_info {
+ struct jr_prefix p;
+
+ uint64_t unwinding_size;
+ uint64_t eh_frame_hdr_size;
+ uint64_t mapped_size;
+ const char unwinding_data[0];
+};
+
union jr_entry {
struct jr_code_debug_info info;
struct jr_code_close close;
struct jr_code_load load;
struct jr_code_move move;
struct jr_prefix prefix;
+ struct jr_code_unwinding_info unwinding;
};
static inline struct debug_entry *
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index bf7216b8731d..b23ff44cf214 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <linux/err.h>
#include "debug.h"
#include "llvm-utils.h"
#include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
"rm -rf $TMPDIR\n"
"exit $RET\n";
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
{
+ static char *saved_kbuild_dir;
+ static char *saved_kbuild_include_opts;
int err;
if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
*kbuild_dir = NULL;
*kbuild_include_opts = NULL;
+ if (saved_kbuild_dir && saved_kbuild_include_opts &&
+ !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+ *kbuild_dir = strdup(saved_kbuild_dir);
+ *kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+ if (*kbuild_dir && *kbuild_include_opts)
+ return;
+
+ zfree(kbuild_dir);
+ zfree(kbuild_include_opts);
+ /*
+ * Don't fall through: it may breaks saved_kbuild_dir and
+ * saved_kbuild_include_opts if detect them again when
+ * memory is low.
+ */
+ return;
+ }
+
if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
pr_debug("Skip kbuild options detection.\n");
- return;
+ goto errout;
}
err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
"Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
" \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
" \tdetection.\n\n");
- return;
+ goto errout;
}
pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,21 +345,50 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
free(*kbuild_dir);
*kbuild_dir = NULL;
- return;
+ goto errout;
}
pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+ saved_kbuild_dir = strdup(*kbuild_dir);
+ saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+ if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+ zfree(&saved_kbuild_dir);
+ zfree(&saved_kbuild_include_opts);
+ }
+ return;
+errout:
+ saved_kbuild_dir = ERR_PTR(-EINVAL);
+ saved_kbuild_include_opts = ERR_PTR(-EINVAL);
}
-static void
-dump_obj(const char *path, void *obj_buf, size_t size)
+int llvm__get_nr_cpus(void)
+{
+ static int nr_cpus_avail = 0;
+ char serr[STRERR_BUFSIZE];
+
+ if (nr_cpus_avail > 0)
+ return nr_cpus_avail;
+
+ nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+ if (nr_cpus_avail <= 0) {
+ pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
+ nr_cpus_avail = 128;
+ }
+ return nr_cpus_avail;
+}
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
{
char *obj_path = strdup(path);
FILE *fp;
char *p;
if (!obj_path) {
- pr_warning("WARNING: No enough memory, skip object dumping\n");
+ pr_warning("WARNING: Not enough memory, skip object dumping\n");
return;
}
@@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
* This is an optional work. Even it fail we can continue our
* work. Needn't to check error return.
*/
- get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
+ llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
- nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
- if (nr_cpus_avail <= 0) {
- pr_err(
-"WARNING:\tunable to get available CPUs in this system: %s\n"
-" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
- nr_cpus_avail = 128;
- }
+ nr_cpus_avail = llvm__get_nr_cpus();
snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
nr_cpus_avail);
@@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
free(kbuild_dir);
free(kbuild_include_opts);
- if (llvm_param.dump_obj)
- dump_obj(path, obj_buf, obj_buf_sz);
-
if (!p_obj_buf)
free(obj_buf);
else
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index 9f501cef06a1..c87a2a92a88f 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -50,4 +50,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz);
/* This function is for test__llvm() use only */
int llvm__search_clang(void);
+
+/* Following functions are reused by builtin clang support */
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
+int llvm__get_nr_cpus(void);
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
#endif
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index df85b9efd80f..9b33bef54581 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1616,7 +1616,11 @@ static int add_callchain_ip(struct thread *thread,
struct symbol **parent,
struct addr_location *root_al,
u8 *cpumode,
- u64 ip)
+ u64 ip,
+ bool branch,
+ struct branch_flags *flags,
+ int nr_loop_iter,
+ int samples)
{
struct addr_location al;
@@ -1668,7 +1672,8 @@ static int add_callchain_ip(struct thread *thread,
if (symbol_conf.hide_unresolved && al.sym == NULL)
return 0;
- return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
+ return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
+ branch, flags, nr_loop_iter, samples);
}
struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1757,7 +1762,9 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
/* LBR only affects the user callchain */
if (i != chain_nr) {
struct branch_stack *lbr_stack = sample->branch_stack;
- int lbr_nr = lbr_stack->nr, j;
+ int lbr_nr = lbr_stack->nr, j, k;
+ bool branch;
+ struct branch_flags *flags;
/*
* LBR callstack can only get user call chain.
* The mix_chain_nr is kernel call chain
@@ -1772,23 +1779,41 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
for (j = 0; j < mix_chain_nr; j++) {
int err;
+ branch = false;
+ flags = NULL;
+
if (callchain_param.order == ORDER_CALLEE) {
if (j < i + 1)
ip = chain->ips[j];
- else if (j > i + 1)
- ip = lbr_stack->entries[j - i - 2].from;
- else
+ else if (j > i + 1) {
+ k = j - i - 2;
+ ip = lbr_stack->entries[k].from;
+ branch = true;
+ flags = &lbr_stack->entries[k].flags;
+ } else {
ip = lbr_stack->entries[0].to;
+ branch = true;
+ flags = &lbr_stack->entries[0].flags;
+ }
} else {
- if (j < lbr_nr)
- ip = lbr_stack->entries[lbr_nr - j - 1].from;
+ if (j < lbr_nr) {
+ k = lbr_nr - j - 1;
+ ip = lbr_stack->entries[k].from;
+ branch = true;
+ flags = &lbr_stack->entries[k].flags;
+ }
else if (j > lbr_nr)
ip = chain->ips[i + 1 - (j - lbr_nr)];
- else
+ else {
ip = lbr_stack->entries[0].to;
+ branch = true;
+ flags = &lbr_stack->entries[0].flags;
+ }
}
- err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al, &cpumode, ip,
+ branch, flags, 0, 0);
if (err)
return (err < 0) ? err : 0;
}
@@ -1813,6 +1838,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
int i, j, err, nr_entries;
int skip_idx = -1;
int first_call = 0;
+ int nr_loop_iter;
if (perf_evsel__has_branch_callstack(evsel)) {
err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
@@ -1868,14 +1894,37 @@ static int thread__resolve_callchain_sample(struct thread *thread,
be[i] = branch->entries[branch->nr - i - 1];
}
+ nr_loop_iter = nr;
nr = remove_loops(be, nr);
+ /*
+ * Get the number of iterations.
+ * It's only approximation, but good enough in practice.
+ */
+ if (nr_loop_iter > nr)
+ nr_loop_iter = nr_loop_iter - nr + 1;
+ else
+ nr_loop_iter = 0;
+
for (i = 0; i < nr; i++) {
- err = add_callchain_ip(thread, cursor, parent, root_al,
- NULL, be[i].to);
+ if (i == nr - 1)
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al,
+ NULL, be[i].to,
+ true, &be[i].flags,
+ nr_loop_iter, 1);
+ else
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al,
+ NULL, be[i].to,
+ true, &be[i].flags,
+ 0, 0);
+
if (!err)
err = add_callchain_ip(thread, cursor, parent, root_al,
- NULL, be[i].from);
+ NULL, be[i].from,
+ true, &be[i].flags,
+ 0, 0);
if (err == -EINVAL)
break;
if (err)
@@ -1903,7 +1952,9 @@ check_calls:
if (ip < PERF_CONTEXT_MAX)
++nr_entries;
- err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al, &cpumode, ip,
+ false, NULL, 0, 0);
if (err)
return (err < 0) ? err : 0;
@@ -1919,7 +1970,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
if (symbol_conf.hide_unresolved && entry->sym == NULL)
return 0;
return callchain_cursor_append(cursor, entry->ip,
- entry->map, entry->sym);
+ entry->map, entry->sym,
+ false, NULL, 0, 0);
}
static int thread__resolve_callchain_unwind(struct thread *thread,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index c662fef95d14..4f9a71c63026 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -682,9 +682,16 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
continue;
if (verbose >= 2) {
- fputs("overlapping maps:\n", fp);
- map__fprintf(map, fp);
- map__fprintf(pos, fp);
+
+ if (use_browser) {
+ pr_warning("overlapping maps in %s "
+ "(disable tui for more info)\n",
+ map->dso->name);
+ } else {
+ fputs("overlapping maps:\n", fp);
+ map__fprintf(map, fp);
+ map__fprintf(pos, fp);
+ }
}
rb_erase_init(&pos->rb_node, root);
@@ -702,7 +709,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
before->end = map->start;
__map_groups__insert(pos->groups, before);
- if (verbose >= 2)
+ if (verbose >= 2 && !use_browser)
map__fprintf(before, fp);
map__put(before);
}
@@ -717,7 +724,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
after->start = map->end;
__map_groups__insert(pos->groups, after);
- if (verbose >= 2)
+ if (verbose >= 2 && !use_browser)
map__fprintf(after, fp);
map__put(after);
}
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index bbc368e7d1e4..1d4ab53c60ca 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -9,6 +9,7 @@
#include "mem-events.h"
#include "debug.h"
#include "symbol.h"
+#include "sort.h"
unsigned int perf_mem_events__loads_ldlat = 30;
@@ -268,3 +269,138 @@ int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_in
return i;
}
+
+int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
+{
+ union perf_mem_data_src *data_src = &mi->data_src;
+ u64 daddr = mi->daddr.addr;
+ u64 op = data_src->mem_op;
+ u64 lvl = data_src->mem_lvl;
+ u64 snoop = data_src->mem_snoop;
+ u64 lock = data_src->mem_lock;
+ int err = 0;
+
+#define HITM_INC(__f) \
+do { \
+ stats->__f++; \
+ stats->tot_hitm++; \
+} while (0)
+
+#define P(a, b) PERF_MEM_##a##_##b
+
+ stats->nr_entries++;
+
+ if (lock & P(LOCK, LOCKED)) stats->locks++;
+
+ if (op & P(OP, LOAD)) {
+ /* load */
+ stats->load++;
+
+ if (!daddr) {
+ stats->ld_noadrs++;
+ return -1;
+ }
+
+ if (lvl & P(LVL, HIT)) {
+ if (lvl & P(LVL, UNC)) stats->ld_uncache++;
+ if (lvl & P(LVL, IO)) stats->ld_io++;
+ if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
+ if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
+ if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
+ if (lvl & P(LVL, L3 )) {
+ if (snoop & P(SNOOP, HITM))
+ HITM_INC(lcl_hitm);
+ else
+ stats->ld_llchit++;
+ }
+
+ if (lvl & P(LVL, LOC_RAM)) {
+ stats->lcl_dram++;
+ if (snoop & P(SNOOP, HIT))
+ stats->ld_shared++;
+ else
+ stats->ld_excl++;
+ }
+
+ if ((lvl & P(LVL, REM_RAM1)) ||
+ (lvl & P(LVL, REM_RAM2))) {
+ stats->rmt_dram++;
+ if (snoop & P(SNOOP, HIT))
+ stats->ld_shared++;
+ else
+ stats->ld_excl++;
+ }
+ }
+
+ if ((lvl & P(LVL, REM_CCE1)) ||
+ (lvl & P(LVL, REM_CCE2))) {
+ if (snoop & P(SNOOP, HIT))
+ stats->rmt_hit++;
+ else if (snoop & P(SNOOP, HITM))
+ HITM_INC(rmt_hitm);
+ }
+
+ if ((lvl & P(LVL, MISS)))
+ stats->ld_miss++;
+
+ } else if (op & P(OP, STORE)) {
+ /* store */
+ stats->store++;
+
+ if (!daddr) {
+ stats->st_noadrs++;
+ return -1;
+ }
+
+ if (lvl & P(LVL, HIT)) {
+ if (lvl & P(LVL, UNC)) stats->st_uncache++;
+ if (lvl & P(LVL, L1 )) stats->st_l1hit++;
+ }
+ if (lvl & P(LVL, MISS))
+ if (lvl & P(LVL, L1)) stats->st_l1miss++;
+ } else {
+ /* unparsable data_src? */
+ stats->noparse++;
+ return -1;
+ }
+
+ if (!mi->daddr.map || !mi->iaddr.map) {
+ stats->nomap++;
+ return -1;
+ }
+
+#undef P
+#undef HITM_INC
+ return err;
+}
+
+void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
+{
+ stats->nr_entries += add->nr_entries;
+
+ stats->locks += add->locks;
+ stats->store += add->store;
+ stats->st_uncache += add->st_uncache;
+ stats->st_noadrs += add->st_noadrs;
+ stats->st_l1hit += add->st_l1hit;
+ stats->st_l1miss += add->st_l1miss;
+ stats->load += add->load;
+ stats->ld_excl += add->ld_excl;
+ stats->ld_shared += add->ld_shared;
+ stats->ld_uncache += add->ld_uncache;
+ stats->ld_io += add->ld_io;
+ stats->ld_miss += add->ld_miss;
+ stats->ld_noadrs += add->ld_noadrs;
+ stats->ld_fbhit += add->ld_fbhit;
+ stats->ld_l1hit += add->ld_l1hit;
+ stats->ld_l2hit += add->ld_l2hit;
+ stats->ld_llchit += add->ld_llchit;
+ stats->lcl_hitm += add->lcl_hitm;
+ stats->rmt_hitm += add->rmt_hitm;
+ stats->tot_hitm += add->tot_hitm;
+ stats->rmt_hit += add->rmt_hit;
+ stats->lcl_dram += add->lcl_dram;
+ stats->rmt_dram += add->rmt_dram;
+ stats->nomap += add->nomap;
+ stats->noparse += add->noparse;
+}
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
index 7f69bf9d789d..40f72ee4f42a 100644
--- a/tools/perf/util/mem-events.h
+++ b/tools/perf/util/mem-events.h
@@ -2,6 +2,10 @@
#define __PERF_MEM_EVENTS_H
#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <linux/types.h>
+#include "stat.h"
struct perf_mem_event {
bool record;
@@ -33,4 +37,38 @@ int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info);
int perf_script__meminfo_scnprintf(char *bf, size_t size, struct mem_info *mem_info);
+struct c2c_stats {
+ u32 nr_entries;
+
+ u32 locks; /* count of 'lock' transactions */
+ u32 store; /* count of all stores in trace */
+ u32 st_uncache; /* stores to uncacheable address */
+ u32 st_noadrs; /* cacheable store with no address */
+ u32 st_l1hit; /* count of stores that hit L1D */
+ u32 st_l1miss; /* count of stores that miss L1D */
+ u32 load; /* count of all loads in trace */
+ u32 ld_excl; /* exclusive loads, rmt/lcl DRAM - snp none/miss */
+ u32 ld_shared; /* shared loads, rmt/lcl DRAM - snp hit */
+ u32 ld_uncache; /* loads to uncacheable address */
+ u32 ld_io; /* loads to io address */
+ u32 ld_miss; /* loads miss */
+ u32 ld_noadrs; /* cacheable load with no address */
+ u32 ld_fbhit; /* count of loads hitting Fill Buffer */
+ u32 ld_l1hit; /* count of loads that hit L1D */
+ u32 ld_l2hit; /* count of loads that hit L2D */
+ u32 ld_llchit; /* count of loads that hit LLC */
+ u32 lcl_hitm; /* count of loads with local HITM */
+ u32 rmt_hitm; /* count of loads with remote HITM */
+ u32 tot_hitm; /* count of loads with local and remote HITM */
+ u32 rmt_hit; /* count of loads with remote hit clean; */
+ u32 lcl_dram; /* count of loads miss to local DRAM */
+ u32 rmt_dram; /* count of loads miss to remote DRAM */
+ u32 nomap; /* count of load/stores with no phys adrs */
+ u32 noparse; /* count of unparsable data sources */
+};
+
+struct hist_entry;
+int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi);
+void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add);
+
#endif /* __PERF_MEM_EVENTS_H */
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index afc088dd7d20..38fd11504015 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -31,59 +31,51 @@ static const struct branch_mode branch_modes[] = {
BRANCH_END
};
-int
-parse_branch_stack(const struct option *opt, const char *str, int unset)
+int parse_branch_str(const char *str, __u64 *mode)
{
#define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER |\
PERF_SAMPLE_BRANCH_KERNEL |\
PERF_SAMPLE_BRANCH_HV)
- uint64_t *mode = (uint64_t *)opt->value;
+ int ret = 0;
+ char *p, *s;
+ char *os = NULL;
const struct branch_mode *br;
- char *s, *os = NULL, *p;
- int ret = -1;
- if (unset)
+ if (str == NULL) {
+ *mode = PERF_SAMPLE_BRANCH_ANY;
return 0;
+ }
- /*
- * cannot set it twice, -b + --branch-filter for instance
- */
- if (*mode)
+ /* because str is read-only */
+ s = os = strdup(str);
+ if (!s)
return -1;
- /* str may be NULL in case no arg is passed to -b */
- if (str) {
- /* because str is read-only */
- s = os = strdup(str);
- if (!s)
- return -1;
-
- for (;;) {
- p = strchr(s, ',');
- if (p)
- *p = '\0';
-
- for (br = branch_modes; br->name; br++) {
- if (!strcasecmp(s, br->name))
- break;
- }
- if (!br->name) {
- ui__warning("unknown branch filter %s,"
- " check man page\n", s);
- goto error;
- }
-
- *mode |= br->mode;
-
- if (!p)
- break;
+ for (;;) {
+ p = strchr(s, ',');
+ if (p)
+ *p = '\0';
- s = p + 1;
+ for (br = branch_modes; br->name; br++) {
+ if (!strcasecmp(s, br->name))
+ break;
+ }
+ if (!br->name) {
+ ret = -1;
+ pr_warning("unknown branch filter %s,"
+ " check man page\n", s);
+ goto error;
}
+
+ *mode |= br->mode;
+
+ if (!p)
+ break;
+
+ s = p + 1;
}
- ret = 0;
/* default to any branch */
if ((*mode & ~ONLY_PLM) == 0) {
@@ -93,3 +85,20 @@ error:
free(os);
return ret;
}
+
+int
+parse_branch_stack(const struct option *opt, const char *str, int unset)
+{
+ __u64 *mode = (__u64 *)opt->value;
+
+ if (unset)
+ return 0;
+
+ /*
+ * cannot set it twice, -b + --branch-filter for instance
+ */
+ if (*mode)
+ return -1;
+
+ return parse_branch_str(str, mode);
+}
diff --git a/tools/perf/util/parse-branch-options.h b/tools/perf/util/parse-branch-options.h
index b9d9470c2e82..6086fd90eb23 100644
--- a/tools/perf/util/parse-branch-options.h
+++ b/tools/perf/util/parse-branch-options.h
@@ -1,5 +1,6 @@
#ifndef _PERF_PARSE_BRANCH_OPTIONS_H
#define _PERF_PARSE_BRANCH_OPTIONS_H 1
-struct option;
+#include <stdint.h>
int parse_branch_stack(const struct option *opt, const char *str, int unset);
+int parse_branch_str(const char *str, __u64 *mode);
#endif /* _PERF_PARSE_BRANCH_OPTIONS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4e778eae1510..3c876b8ba4de 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -22,6 +22,7 @@
#include "cpumap.h"
#include "probe-file.h"
#include "asm/bug.h"
+#include "util/parse-branch-options.h"
#define MAX_NAME_LEN 100
@@ -973,10 +974,13 @@ do { \
CHECK_TYPE_VAL(NUM);
break;
case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
- /*
- * TODO uncomment when the field is available
- * attr->branch_sample_type = term->val.num;
- */
+ CHECK_TYPE_VAL(STR);
+ if (strcmp(term->val.str, "no") &&
+ parse_branch_str(term->val.str, &attr->branch_sample_type)) {
+ err->str = strdup("invalid branch sample type");
+ err->idx = term->err_val;
+ return -EINVAL;
+ }
break;
case PARSE_EVENTS__TERM_TYPE_TIME:
CHECK_TYPE_VAL(NUM);
@@ -1119,6 +1123,9 @@ do { \
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
break;
+ case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
+ ADD_CONFIG_TERM(BRANCH, branch, term->val.str);
+ break;
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
break;
diff --git a/tools/perf/util/perf-hooks-list.h b/tools/perf/util/perf-hooks-list.h
new file mode 100644
index 000000000000..2867c07ee84e
--- /dev/null
+++ b/tools/perf/util/perf-hooks-list.h
@@ -0,0 +1,3 @@
+PERF_HOOK(record_start)
+PERF_HOOK(record_end)
+PERF_HOOK(test)
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
new file mode 100644
index 000000000000..cb368306b12b
--- /dev/null
+++ b/tools/perf/util/perf-hooks.c
@@ -0,0 +1,88 @@
+/*
+ * perf_hooks.c
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <linux/err.h>
+#include "util/util.h"
+#include "util/debug.h"
+#include "util/perf-hooks.h"
+
+static sigjmp_buf jmpbuf;
+static const struct perf_hook_desc *current_perf_hook;
+
+void perf_hooks__invoke(const struct perf_hook_desc *desc)
+{
+ if (!(desc && desc->p_hook_func && *desc->p_hook_func))
+ return;
+
+ if (sigsetjmp(jmpbuf, 1)) {
+ pr_warning("Fatal error (SEGFAULT) in perf hook '%s'\n",
+ desc->hook_name);
+ *(current_perf_hook->p_hook_func) = NULL;
+ } else {
+ current_perf_hook = desc;
+ (**desc->p_hook_func)(desc->hook_ctx);
+ }
+ current_perf_hook = NULL;
+}
+
+void perf_hooks__recover(void)
+{
+ if (current_perf_hook)
+ siglongjmp(jmpbuf, 1);
+}
+
+#define PERF_HOOK(name) \
+perf_hook_func_t __perf_hook_func_##name = NULL; \
+struct perf_hook_desc __perf_hook_desc_##name = \
+ {.hook_name = #name, \
+ .p_hook_func = &__perf_hook_func_##name, \
+ .hook_ctx = NULL};
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+#define PERF_HOOK(name) \
+ &__perf_hook_desc_##name,
+
+static struct perf_hook_desc *perf_hooks[] = {
+#include "perf-hooks-list.h"
+};
+#undef PERF_HOOK
+
+int perf_hooks__set_hook(const char *hook_name,
+ perf_hook_func_t hook_func,
+ void *hook_ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+ if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+ continue;
+
+ if (*(perf_hooks[i]->p_hook_func))
+ pr_warning("Overwrite existing hook: %s\n", hook_name);
+ *(perf_hooks[i]->p_hook_func) = hook_func;
+ perf_hooks[i]->hook_ctx = hook_ctx;
+ return 0;
+ }
+ return -ENOENT;
+}
+
+perf_hook_func_t perf_hooks__get_hook(const char *hook_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+ if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+ continue;
+
+ return *(perf_hooks[i]->p_hook_func);
+ }
+ return ERR_PTR(-ENOENT);
+}
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
new file mode 100644
index 000000000000..838d5797bc1e
--- /dev/null
+++ b/tools/perf/util/perf-hooks.h
@@ -0,0 +1,39 @@
+#ifndef PERF_UTIL_PERF_HOOKS_H
+#define PERF_UTIL_PERF_HOOKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*perf_hook_func_t)(void *ctx);
+struct perf_hook_desc {
+ const char * const hook_name;
+ perf_hook_func_t * const p_hook_func;
+ void *hook_ctx;
+};
+
+extern void perf_hooks__invoke(const struct perf_hook_desc *);
+extern void perf_hooks__recover(void);
+
+#define PERF_HOOK(name) \
+extern struct perf_hook_desc __perf_hook_desc_##name; \
+static inline void perf_hooks__invoke_##name(void) \
+{ \
+ perf_hooks__invoke(&__perf_hook_desc_##name); \
+}
+
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+extern int
+perf_hooks__set_hook(const char *hook_name,
+ perf_hook_func_t hook_func,
+ void *hook_ctx);
+
+extern perf_hook_func_t
+perf_hooks__get_hook(const char *hook_name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b1474dcadfa2..dc6ccaa4e927 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -504,6 +504,7 @@ static void pmu_add_cpu_aliases(struct list_head *head)
struct pmu_events_map *map;
struct pmu_event *pe;
char *cpuid;
+ static bool printed;
cpuid = getenv("PERF_CPUID");
if (cpuid)
@@ -513,7 +514,10 @@ static void pmu_add_cpu_aliases(struct list_head *head)
if (!cpuid)
return;
- pr_debug("Using CPUID %s\n", cpuid);
+ if (!printed) {
+ pr_debug("Using CPUID %s\n", cpuid);
+ printed = true;
+ }
i = 0;
while (1) {
@@ -1135,9 +1139,11 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
bool is_cpu = !strcmp(pmu->name, "cpu");
if (event_glob != NULL &&
- !(strglobmatch(name, event_glob) ||
- (!is_cpu && strglobmatch(alias->name,
- event_glob))))
+ !(strglobmatch_nocase(name, event_glob) ||
+ (!is_cpu && strglobmatch_nocase(alias->name,
+ event_glob)) ||
+ (alias->topic &&
+ strglobmatch_nocase(alias->topic, event_glob))))
continue;
if (is_cpu && !name_only && !alias->desc)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 8091d15113f7..5d4e94061402 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -18,6 +18,8 @@ struct probe_conf {
extern struct probe_conf probe_conf;
extern bool probe_event_dry_run;
+struct symbol;
+
/* kprobe-tracer and uprobe-tracer tracing point */
struct probe_trace_point {
char *realname; /* function real name (if needed) */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index b7d4f4aeee61..0546a4304347 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -18,6 +18,7 @@ util/thread_map.c
util/util.c
util/xyarray.c
util/cgroup.c
+util/parse-branch-options.c
util/rblist.c
util/counts.c
util/strlist.c
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 639d1da2f978..293534c1a474 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -54,7 +54,7 @@ int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
break;
ret = sq_quote_buf(dst, argv[i]);
if (maxlen && dst->len > maxlen)
- die("Too many or long arguments");
+ return -ENOSPC;
}
return ret;
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..f268201048a0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -2025,20 +2025,10 @@ out_delete_map:
void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
bool full)
{
- struct stat st;
- int fd, ret;
-
if (session == NULL || fp == NULL)
return;
- fd = perf_data_file__fd(session->file);
-
- ret = fstat(fd, &st);
- if (ret == -1)
- return;
-
fprintf(fp, "# ========\n");
- fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
perf_header__fprintf_info(session, fp, full);
fprintf(fp, "# ========\n#\n");
}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 452e15a10dd2..df622f4e301e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -315,7 +315,7 @@ struct sort_entry sort_sym = {
/* --sort srcline */
-static char *hist_entry__get_srcline(struct hist_entry *he)
+char *hist_entry__get_srcline(struct hist_entry *he)
{
struct map *map = he->ms.map;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 099c97557d33..7aff317fc7c4 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -280,4 +280,5 @@ int64_t
sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right);
int64_t
sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right);
+char *hist_entry__get_srcline(struct hist_entry *he);
#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 7f7e072be746..d8dfaf64b32e 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -193,7 +193,8 @@ error:
}
/* Glob/lazy pattern matching */
-static bool __match_glob(const char *str, const char *pat, bool ignore_space)
+static bool __match_glob(const char *str, const char *pat, bool ignore_space,
+ bool case_ins)
{
while (*str && *pat && *pat != '*') {
if (ignore_space) {
@@ -219,8 +220,13 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
return false;
else if (*pat == '\\') /* Escaped char match as normal char */
pat++;
- if (*str++ != *pat++)
+ if (case_ins) {
+ if (tolower(*str) != tolower(*pat))
+ return false;
+ } else if (*str != *pat)
return false;
+ str++;
+ pat++;
}
/* Check wild card */
if (*pat == '*') {
@@ -229,7 +235,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
if (!*pat) /* Tail wild card matches all */
return true;
while (*str)
- if (__match_glob(str++, pat, ignore_space))
+ if (__match_glob(str++, pat, ignore_space, case_ins))
return true;
}
return !*str && !*pat;
@@ -249,7 +255,12 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
*/
bool strglobmatch(const char *str, const char *pat)
{
- return __match_glob(str, pat, false);
+ return __match_glob(str, pat, false, false);
+}
+
+bool strglobmatch_nocase(const char *str, const char *pat)
+{
+ return __match_glob(str, pat, false, true);
}
/**
@@ -262,7 +273,7 @@ bool strglobmatch(const char *str, const char *pat)
*/
bool strlazymatch(const char *str, const char *pat)
{
- return __match_glob(str, pat, true);
+ return __match_glob(str, pat, true, false);
}
/**
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index aecff69a510d..df2482b2ba45 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1962,7 +1962,7 @@ static bool symbol__read_kptr_restrict(void)
char line[8];
if (fgets(line, sizeof(line), fp) != NULL)
- value = (geteuid() != 0) ?
+ value = ((geteuid() != 0) || (getuid() != 0)) ?
(atoi(line) != 0) :
(atoi(line) == 2);
@@ -2032,6 +2032,10 @@ int symbol__init(struct perf_env *env)
symbol_conf.sym_list_str, "symbol") < 0)
goto out_free_tid_list;
+ if (setup_list(&symbol_conf.bt_stop_list,
+ symbol_conf.bt_stop_list_str, "symbol") < 0)
+ goto out_free_sym_list;
+
/*
* A path to symbols of "/" is identical to ""
* reset here for simplicity.
@@ -2049,6 +2053,8 @@ int symbol__init(struct perf_env *env)
symbol_conf.initialized = true;
return 0;
+out_free_sym_list:
+ strlist__delete(symbol_conf.sym_list);
out_free_tid_list:
intlist__delete(symbol_conf.tid_list);
out_free_pid_list:
@@ -2064,6 +2070,7 @@ void symbol__exit(void)
{
if (!symbol_conf.initialized)
return;
+ strlist__delete(symbol_conf.bt_stop_list);
strlist__delete(symbol_conf.sym_list);
strlist__delete(symbol_conf.dso_list);
strlist__delete(symbol_conf.comm_list);
@@ -2071,6 +2078,7 @@ void symbol__exit(void)
intlist__delete(symbol_conf.pid_list);
vmlinux_path__exit();
symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
+ symbol_conf.bt_stop_list = NULL;
symbol_conf.initialized = false;
}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d964844eb314..6c358b7ed336 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -58,6 +58,7 @@ struct symbol {
u16 namelen;
u8 binding;
u8 idle:1;
+ u8 ignore:1;
u8 arch_sym;
char name[0];
};
@@ -100,6 +101,7 @@ struct symbol_conf {
show_total_period,
use_callchain,
cumulate_callchain,
+ show_branchflag_count,
exclude_other,
show_cpu_utilization,
initialized,
@@ -130,14 +132,16 @@ struct symbol_conf {
*pid_list_str,
*tid_list_str,
*sym_list_str,
- *col_width_list_str;
+ *col_width_list_str,
+ *bt_stop_list_str;
struct strlist *dso_list,
*comm_list,
*sym_list,
*dso_from_list,
*dso_to_list,
*sym_from_list,
- *sym_to_list;
+ *sym_to_list,
+ *bt_stop_list;
struct intlist *pid_list,
*tid_list;
const char *symfs;
@@ -281,7 +285,8 @@ int symbol__annotation_init(void);
struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
- bool unknown_as_addr, FILE *fp);
+ bool unknown_as_addr,
+ bool print_offsets, FILE *fp);
size_t symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al, FILE *fp);
size_t __symbol__fprintf_symname(const struct symbol *sym,
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index a680bdaa65dc..7c6b33e8e2d2 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -15,14 +15,15 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp)
size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
- bool unknown_as_addr, FILE *fp)
+ bool unknown_as_addr,
+ bool print_offsets, FILE *fp)
{
unsigned long offset;
size_t length;
if (sym && sym->name) {
length = fprintf(fp, "%s", sym->name);
- if (al) {
+ if (al && print_offsets) {
if (al->addr < sym->end)
offset = al->addr - sym->start;
else
@@ -40,19 +41,19 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
FILE *fp)
{
- return __symbol__fprintf_symname_offs(sym, al, false, fp);
+ return __symbol__fprintf_symname_offs(sym, al, false, true, fp);
}
size_t __symbol__fprintf_symname(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr, FILE *fp)
{
- return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp);
+ return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, false, fp);
}
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
{
- return __symbol__fprintf_symname_offs(sym, NULL, false, fp);
+ return __symbol__fprintf_symname_offs(sym, NULL, false, false, fp);
}
size_t dso__fprintf_symbols_by_name(struct dso *dso,
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
new file mode 100644
index 000000000000..d1b21c72206d
--- /dev/null
+++ b/tools/perf/util/time-utils.c
@@ -0,0 +1,119 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <linux/time64.h>
+#include <time.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "perf.h"
+#include "debug.h"
+#include "time-utils.h"
+
+int parse_nsec_time(const char *str, u64 *ptime)
+{
+ u64 time_sec, time_nsec;
+ char *end;
+
+ time_sec = strtoul(str, &end, 10);
+ if (*end != '.' && *end != '\0')
+ return -1;
+
+ if (*end == '.') {
+ int i;
+ char nsec_buf[10];
+
+ if (strlen(++end) > 9)
+ return -1;
+
+ strncpy(nsec_buf, end, 9);
+ nsec_buf[9] = '\0';
+
+ /* make it nsec precision */
+ for (i = strlen(nsec_buf); i < 9; i++)
+ nsec_buf[i] = '0';
+
+ time_nsec = strtoul(nsec_buf, &end, 10);
+ if (*end != '\0')
+ return -1;
+ } else
+ time_nsec = 0;
+
+ *ptime = time_sec * NSEC_PER_SEC + time_nsec;
+ return 0;
+}
+
+static int parse_timestr_sec_nsec(struct perf_time_interval *ptime,
+ char *start_str, char *end_str)
+{
+ if (start_str && (*start_str != '\0') &&
+ (parse_nsec_time(start_str, &ptime->start) != 0)) {
+ return -1;
+ }
+
+ if (end_str && (*end_str != '\0') &&
+ (parse_nsec_time(end_str, &ptime->end) != 0)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
+{
+ char *start_str, *end_str;
+ char *d, *str;
+ int rc = 0;
+
+ if (ostr == NULL || *ostr == '\0')
+ return 0;
+
+ /* copy original string because we need to modify it */
+ str = strdup(ostr);
+ if (str == NULL)
+ return -ENOMEM;
+
+ ptime->start = 0;
+ ptime->end = 0;
+
+ /* str has the format: <start>,<stop>
+ * variations: <start>,
+ * ,<stop>
+ * ,
+ */
+ start_str = str;
+ d = strchr(start_str, ',');
+ if (d) {
+ *d = '\0';
+ ++d;
+ }
+ end_str = d;
+
+ rc = parse_timestr_sec_nsec(ptime, start_str, end_str);
+
+ free(str);
+
+ /* make sure end time is after start time if it was given */
+ if (rc == 0 && ptime->end && ptime->end < ptime->start)
+ return -EINVAL;
+
+ pr_debug("start time %" PRIu64 ", ", ptime->start);
+ pr_debug("end time %" PRIu64 "\n", ptime->end);
+
+ return rc;
+}
+
+bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
+{
+ /* if time is not set don't drop sample */
+ if (timestamp == 0)
+ return false;
+
+ /* otherwise compare sample time to time window */
+ if ((ptime->start && timestamp < ptime->start) ||
+ (ptime->end && timestamp > ptime->end)) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
new file mode 100644
index 000000000000..c1f197c4af6c
--- /dev/null
+++ b/tools/perf/util/time-utils.h
@@ -0,0 +1,14 @@
+#ifndef _TIME_UTILS_H_
+#define _TIME_UTILS_H_
+
+struct perf_time_interval {
+ u64 start, end;
+};
+
+int parse_nsec_time(const char *str, u64 *ptime);
+
+int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr);
+
+bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
+
+#endif
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 9df61059a85d..0ac9077f62a2 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include "../perf.h"
+#include "debug.h"
#include "util.h"
#include "trace-event.h"
@@ -86,16 +87,15 @@ struct scripting_ops python_scripting_unsupported_ops = {
static void register_python_scripting(struct scripting_ops *scripting_ops)
{
- int err;
- err = script_spec_register("Python", scripting_ops);
- if (err)
- die("error registering Python script extension");
-
- err = script_spec_register("py", scripting_ops);
- if (err)
- die("error registering py script extension");
-
- scripting_context = malloc(sizeof(struct scripting_context));
+ if (scripting_context == NULL)
+ scripting_context = malloc(sizeof(*scripting_context));
+
+ if (scripting_context == NULL ||
+ script_spec_register("Python", scripting_ops) ||
+ script_spec_register("py", scripting_ops)) {
+ pr_err("Error registering Python script extension: disabling it\n");
+ zfree(&scripting_context);
+ }
}
#ifdef NO_LIBPYTHON
@@ -150,16 +150,15 @@ struct scripting_ops perl_scripting_unsupported_ops = {
static void register_perl_scripting(struct scripting_ops *scripting_ops)
{
- int err;
- err = script_spec_register("Perl", scripting_ops);
- if (err)
- die("error registering Perl script extension");
-
- err = script_spec_register("pl", scripting_ops);
- if (err)
- die("error registering pl script extension");
-
- scripting_context = malloc(sizeof(struct scripting_context));
+ if (scripting_context == NULL)
+ scripting_context = malloc(sizeof(*scripting_context));
+
+ if (scripting_context == NULL ||
+ script_spec_register("Perl", scripting_ops) ||
+ script_spec_register("pl", scripting_ops)) {
+ pr_err("Error registering Perl script extension: disabling it\n");
+ zfree(&scripting_context);
+ }
}
#ifdef NO_LIBPERL
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 20c2e5743903..6fec84dff3f7 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -357,8 +357,8 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
di.start_ip = map->start;
di.end_ip = map->end;
- di.u.rti.segbase = map->start + segbase;
- di.u.rti.table_data = map->start + table_data;
+ di.u.rti.segbase = map->start + segbase - map->pgoff;
+ di.u.rti.table_data = map->start + table_data - map->pgoff;
di.u.rti.table_len = fde_count * sizeof(struct table_entry)
/ sizeof(unw_word_t);
ret = dwarf_search_unwind_table(as, ip, &di, pi,
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
new file mode 100644
index 000000000000..0e0e019c9f34
--- /dev/null
+++ b/tools/perf/util/util-cxx.h
@@ -0,0 +1,26 @@
+/*
+ * Support C++ source use utilities defined in util.h
+ */
+
+#ifndef PERF_UTIL_UTIL_CXX_H
+#define PERF_UTIL_UTIL_CXX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Now 'new' is the only C++ keyword found in util.h:
+ * in tools/include/linux/rbtree.h
+ *
+ * Other keywords, like class and delete, should be
+ * redefined if necessary.
+ */
+#define new _new
+#include "util.h"
+#undef new
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 85c56800f17a..9ddd98827d12 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -400,37 +400,12 @@ void sighandler_dump_stack(int sig)
raise(sig);
}
-int parse_nsec_time(const char *str, u64 *ptime)
+int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
{
- u64 time_sec, time_nsec;
- char *end;
+ u64 sec = timestamp / NSEC_PER_SEC;
+ u64 usec = (timestamp % NSEC_PER_SEC) / NSEC_PER_USEC;
- time_sec = strtoul(str, &end, 10);
- if (*end != '.' && *end != '\0')
- return -1;
-
- if (*end == '.') {
- int i;
- char nsec_buf[10];
-
- if (strlen(++end) > 9)
- return -1;
-
- strncpy(nsec_buf, end, 9);
- nsec_buf[9] = '\0';
-
- /* make it nsec precision */
- for (i = strlen(nsec_buf); i < 9; i++)
- nsec_buf[i] = '0';
-
- time_nsec = strtoul(nsec_buf, &end, 10);
- if (*end != '\0')
- return -1;
- } else
- time_nsec = 0;
-
- *ptime = time_sec * NSEC_PER_SEC + time_nsec;
- return 0;
+ return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
}
unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
@@ -629,12 +604,63 @@ bool find_process(const char *name)
return ret ? false : true;
}
+static int
+fetch_ubuntu_kernel_version(unsigned int *puint)
+{
+ ssize_t len;
+ size_t line_len = 0;
+ char *ptr, *line = NULL;
+ int version, patchlevel, sublevel, err;
+ FILE *vsig = fopen("/proc/version_signature", "r");
+
+ if (!vsig) {
+ pr_debug("Open /proc/version_signature failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ len = getline(&line, &line_len, vsig);
+ fclose(vsig);
+ err = -1;
+ if (len <= 0) {
+ pr_debug("Reading from /proc/version_signature failed: %s\n",
+ strerror(errno));
+ goto errout;
+ }
+
+ ptr = strrchr(line, ' ');
+ if (!ptr) {
+ pr_debug("Parsing /proc/version_signature failed: %s\n", line);
+ goto errout;
+ }
+
+ err = sscanf(ptr + 1, "%d.%d.%d",
+ &version, &patchlevel, &sublevel);
+ if (err != 3) {
+ pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n",
+ line);
+ goto errout;
+ }
+
+ if (puint)
+ *puint = (version << 16) + (patchlevel << 8) + sublevel;
+ err = 0;
+errout:
+ free(line);
+ return err;
+}
+
int
fetch_kernel_version(unsigned int *puint, char *str,
size_t str_size)
{
struct utsname utsname;
int version, patchlevel, sublevel, err;
+ bool int_ver_ready = false;
+
+ if (access("/proc/version_signature", R_OK) == 0)
+ if (!fetch_ubuntu_kernel_version(puint))
+ int_ver_ready = true;
if (uname(&utsname))
return -1;
@@ -648,12 +674,12 @@ fetch_kernel_version(unsigned int *puint, char *str,
&version, &patchlevel, &sublevel);
if (err != 3) {
- pr_debug("Unablt to get kernel version from uname '%s'\n",
+ pr_debug("Unable to get kernel version from uname '%s'\n",
utsname.release);
return -1;
}
- if (puint)
+ if (puint && !int_ver_ready)
*puint = (version << 16) + (patchlevel << 8) + sublevel;
return 0;
}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 43899e0d6fa1..1d639e38aa82 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -179,8 +179,6 @@ static inline void *zalloc(size_t size)
#undef tolower
#undef toupper
-int parse_nsec_time(const char *str, u64 *ptime);
-
extern unsigned char sane_ctype[256];
#define GIT_SPACE 0x01
#define GIT_DIGIT 0x02
@@ -222,6 +220,7 @@ s64 perf_atoll(const char *str);
char **argv_split(const char *str, int *argcp);
void argv_free(char **argv);
bool strglobmatch(const char *str, const char *pat);
+bool strglobmatch_nocase(const char *str, const char *pat);
bool strlazymatch(const char *str, const char *pat);
static inline bool strisglob(const char *str)
{
@@ -361,4 +360,7 @@ extern int sched_getcpu(void);
#endif
int is_printable_array(char *p, unsigned int len);
+
+int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
+
#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 0fb3c1fcd3e6..5074be4ed467 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -2,15 +2,18 @@
#include "util.h"
#include "values.h"
+#include "debug.h"
-void perf_read_values_init(struct perf_read_values *values)
+int perf_read_values_init(struct perf_read_values *values)
{
values->threads_max = 16;
values->pid = malloc(values->threads_max * sizeof(*values->pid));
values->tid = malloc(values->threads_max * sizeof(*values->tid));
values->value = malloc(values->threads_max * sizeof(*values->value));
- if (!values->pid || !values->tid || !values->value)
- die("failed to allocate read_values threads arrays");
+ if (!values->pid || !values->tid || !values->value) {
+ pr_debug("failed to allocate read_values threads arrays");
+ goto out_free_pid;
+ }
values->threads = 0;
values->counters_max = 16;
@@ -18,9 +21,22 @@ void perf_read_values_init(struct perf_read_values *values)
* sizeof(*values->counterrawid));
values->countername = malloc(values->counters_max
* sizeof(*values->countername));
- if (!values->counterrawid || !values->countername)
- die("failed to allocate read_values counters arrays");
+ if (!values->counterrawid || !values->countername) {
+ pr_debug("failed to allocate read_values counters arrays");
+ goto out_free_counter;
+ }
values->counters = 0;
+
+ return 0;
+
+out_free_counter:
+ zfree(&values->counterrawid);
+ zfree(&values->countername);
+out_free_pid:
+ zfree(&values->pid);
+ zfree(&values->tid);
+ zfree(&values->value);
+ return -ENOMEM;
}
void perf_read_values_destroy(struct perf_read_values *values)
@@ -41,17 +57,27 @@ void perf_read_values_destroy(struct perf_read_values *values)
zfree(&values->countername);
}
-static void perf_read_values__enlarge_threads(struct perf_read_values *values)
+static int perf_read_values__enlarge_threads(struct perf_read_values *values)
{
- values->threads_max *= 2;
- values->pid = realloc(values->pid,
- values->threads_max * sizeof(*values->pid));
- values->tid = realloc(values->tid,
- values->threads_max * sizeof(*values->tid));
- values->value = realloc(values->value,
- values->threads_max * sizeof(*values->value));
- if (!values->pid || !values->tid || !values->value)
- die("failed to enlarge read_values threads arrays");
+ int nthreads_max = values->threads_max * 2;
+ void *npid = realloc(values->pid, nthreads_max * sizeof(*values->pid)),
+ *ntid = realloc(values->tid, nthreads_max * sizeof(*values->tid)),
+ *nvalue = realloc(values->value, nthreads_max * sizeof(*values->value));
+
+ if (!npid || !ntid || !nvalue)
+ goto out_err;
+
+ values->threads_max = nthreads_max;
+ values->pid = npid;
+ values->tid = ntid;
+ values->value = nvalue;
+ return 0;
+out_err:
+ free(npid);
+ free(ntid);
+ free(nvalue);
+ pr_debug("failed to enlarge read_values threads arrays");
+ return -ENOMEM;
}
static int perf_read_values__findnew_thread(struct perf_read_values *values,
@@ -63,15 +89,21 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
if (values->pid[i] == pid && values->tid[i] == tid)
return i;
- if (values->threads == values->threads_max)
- perf_read_values__enlarge_threads(values);
+ if (values->threads == values->threads_max) {
+ i = perf_read_values__enlarge_threads(values);
+ if (i < 0)
+ return i;
+ }
- i = values->threads++;
+ i = values->threads + 1;
+ values->value[i] = malloc(values->counters_max * sizeof(**values->value));
+ if (!values->value[i]) {
+ pr_debug("failed to allocate read_values counters array");
+ return -ENOMEM;
+ }
values->pid[i] = pid;
values->tid[i] = tid;
- values->value[i] = malloc(values->counters_max * sizeof(**values->value));
- if (!values->value[i])
- die("failed to allocate read_values counters array");
+ values->threads = i;
return i;
}
@@ -115,16 +147,21 @@ static int perf_read_values__findnew_counter(struct perf_read_values *values,
return i;
}
-void perf_read_values_add_value(struct perf_read_values *values,
+int perf_read_values_add_value(struct perf_read_values *values,
u32 pid, u32 tid,
u64 rawid, const char *name, u64 value)
{
int tindex, cindex;
tindex = perf_read_values__findnew_thread(values, pid, tid);
+ if (tindex < 0)
+ return tindex;
cindex = perf_read_values__findnew_counter(values, rawid, name);
+ if (cindex < 0)
+ return cindex;
values->value[tindex][cindex] = value;
+ return 0;
}
static void perf_read_values__display_pretty(FILE *fp,
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index b21a80c6cf8d..808ff9c73bf5 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -14,10 +14,10 @@ struct perf_read_values {
u64 **value;
};
-void perf_read_values_init(struct perf_read_values *values);
+int perf_read_values_init(struct perf_read_values *values);
void perf_read_values_destroy(struct perf_read_values *values);
-void perf_read_values_add_value(struct perf_read_values *values,
+int perf_read_values_add_value(struct perf_read_values *values,
u32 pid, u32 tid,
u64 rawid, const char *name, u64 value);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 05d7bc488971..d1be94667a30 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -146,7 +146,7 @@ static void multiorder_check(unsigned long index, int order)
slot = radix_tree_lookup_slot(&tree, index);
free(*slot);
- radix_tree_replace_slot(slot, item2);
+ radix_tree_replace_slot(&tree, slot, item2);
for (i = min; i < max; i++) {
struct item *item = item_lookup(&tree, i);
assert(item != 0);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index f770dba2a6f6..a3144a3de3a8 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,4 +1,5 @@
-TARGETS = breakpoints
+TARGETS = bpf
+TARGETS += breakpoints
TARGETS += capabilities
TARGETS += cpu-hotplug
TARGETS += efivarfs
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
new file mode 100644
index 000000000000..071431bedde8
--- /dev/null
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -0,0 +1,3 @@
+test_verifier
+test_maps
+test_lru_map
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
new file mode 100644
index 000000000000..7a5f24543a5f
--- /dev/null
+++ b/tools/testing/selftests/bpf/Makefile
@@ -0,0 +1,13 @@
+CFLAGS += -Wall -O2 -I../../../../usr/include
+
+test_objs = test_verifier test_maps test_lru_map
+
+TEST_PROGS := test_verifier test_maps test_lru_map test_kmod.sh
+TEST_FILES := $(test_objs)
+
+all: $(test_objs)
+
+include ../lib.mk
+
+clean:
+ $(RM) $(test_objs)
diff --git a/tools/testing/selftests/bpf/bpf_sys.h b/tools/testing/selftests/bpf/bpf_sys.h
new file mode 100644
index 000000000000..6b4565f2a3f2
--- /dev/null
+++ b/tools/testing/selftests/bpf/bpf_sys.h
@@ -0,0 +1,108 @@
+#ifndef __BPF_SYS__
+#define __BPF_SYS__
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <sys/syscall.h>
+
+#include <linux/bpf.h>
+
+static inline __u64 bpf_ptr_to_u64(const void *ptr)
+{
+ return (__u64)(unsigned long) ptr;
+}
+
+static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size)
+{
+#ifdef __NR_bpf
+ return syscall(__NR_bpf, cmd, attr, size);
+#else
+ fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static inline int bpf_map_lookup(int fd, const void *key, void *value)
+{
+ union bpf_attr attr = {};
+
+ attr.map_fd = fd;
+ attr.key = bpf_ptr_to_u64(key);
+ attr.value = bpf_ptr_to_u64(value);
+
+ return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_update(int fd, const void *key, const void *value,
+ uint64_t flags)
+{
+ union bpf_attr attr = {};
+
+ attr.map_fd = fd;
+ attr.key = bpf_ptr_to_u64(key);
+ attr.value = bpf_ptr_to_u64(value);
+ attr.flags = flags;
+
+ return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_delete(int fd, const void *key)
+{
+ union bpf_attr attr = {};
+
+ attr.map_fd = fd;
+ attr.key = bpf_ptr_to_u64(key);
+
+ return bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_next_key(int fd, const void *key, void *next_key)
+{
+ union bpf_attr attr = {};
+
+ attr.map_fd = fd;
+ attr.key = bpf_ptr_to_u64(key);
+ attr.next_key = bpf_ptr_to_u64(next_key);
+
+ return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_create(enum bpf_map_type type, uint32_t size_key,
+ uint32_t size_value, uint32_t max_elem,
+ uint32_t flags)
+{
+ union bpf_attr attr = {};
+
+ attr.map_type = type;
+ attr.key_size = size_key;
+ attr.value_size = size_value;
+ attr.max_entries = max_elem;
+ attr.map_flags = flags;
+
+ return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
+}
+
+static inline int bpf_prog_load(enum bpf_prog_type type,
+ const struct bpf_insn *insns, size_t size_insns,
+ const char *license, char *log, size_t size_log)
+{
+ union bpf_attr attr = {};
+
+ attr.prog_type = type;
+ attr.insns = bpf_ptr_to_u64(insns);
+ attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
+ attr.license = bpf_ptr_to_u64(license);
+
+ if (size_log > 0) {
+ attr.log_buf = bpf_ptr_to_u64(log);
+ attr.log_size = size_log;
+ attr.log_level = 1;
+ log[0] = 0;
+ }
+
+ return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
+
+#endif /* __BPF_SYS__ */
diff --git a/tools/testing/selftests/bpf/bpf_util.h b/tools/testing/selftests/bpf/bpf_util.h
new file mode 100644
index 000000000000..84a5d1823f02
--- /dev/null
+++ b/tools/testing/selftests/bpf/bpf_util.h
@@ -0,0 +1,38 @@
+#ifndef __BPF_UTIL__
+#define __BPF_UTIL__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+static inline unsigned int bpf_num_possible_cpus(void)
+{
+ static const char *fcpu = "/sys/devices/system/cpu/possible";
+ unsigned int start, end, possible_cpus = 0;
+ char buff[128];
+ FILE *fp;
+
+ fp = fopen(fcpu, "r");
+ if (!fp) {
+ printf("Failed to open %s: '%s'!\n", fcpu, strerror(errno));
+ exit(1);
+ }
+
+ while (fgets(buff, sizeof(buff), fp)) {
+ if (sscanf(buff, "%u-%u", &start, &end) == 2) {
+ possible_cpus = start == 0 ? end + 1 : 0;
+ break;
+ }
+ }
+
+ fclose(fp);
+ if (!possible_cpus) {
+ printf("Failed to retrieve # possible CPUs!\n");
+ exit(1);
+ }
+
+ return possible_cpus;
+}
+
+#endif /* __BPF_UTIL__ */
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
new file mode 100644
index 000000000000..52d53ed08769
--- /dev/null
+++ b/tools/testing/selftests/bpf/config
@@ -0,0 +1,5 @@
+CONFIG_BPF=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_NET_CLS_BPF=m
+CONFIG_BPF_EVENTS=y
+CONFIG_TEST_BPF=m
diff --git a/tools/testing/selftests/bpf/test_kmod.sh b/tools/testing/selftests/bpf/test_kmod.sh
new file mode 100755
index 000000000000..92e627adf354
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_kmod.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+SRC_TREE=../../../../
+
+test_run()
+{
+ sysctl -w net.core.bpf_jit_enable=$1 2>&1 > /dev/null
+ sysctl -w net.core.bpf_jit_harden=$2 2>&1 > /dev/null
+
+ echo "[ JIT enabled:$1 hardened:$2 ]"
+ dmesg -C
+ insmod $SRC_TREE/lib/test_bpf.ko 2> /dev/null
+ if [ $? -ne 0 ]; then
+ rc=1
+ fi
+ rmmod test_bpf 2> /dev/null
+ dmesg | grep FAIL
+}
+
+test_save()
+{
+ JE=`sysctl -n net.core.bpf_jit_enable`
+ JH=`sysctl -n net.core.bpf_jit_harden`
+}
+
+test_restore()
+{
+ sysctl -w net.core.bpf_jit_enable=$JE 2>&1 > /dev/null
+ sysctl -w net.core.bpf_jit_harden=$JH 2>&1 > /dev/null
+}
+
+rc=0
+test_save
+test_run 0 0
+test_run 1 0
+test_run 1 1
+test_run 1 2
+test_restore
+exit $rc
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c
new file mode 100644
index 000000000000..b13fed534d76
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_lru_map.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+#include "bpf_sys.h"
+#include "bpf_util.h"
+
+#define LOCAL_FREE_TARGET (128)
+#define PERCPU_FREE_TARGET (16)
+
+static int nr_cpus;
+
+static int create_map(int map_type, int map_flags, unsigned int size)
+{
+ int map_fd;
+
+ map_fd = bpf_map_create(map_type, sizeof(unsigned long long),
+ sizeof(unsigned long long), size, map_flags);
+
+ if (map_fd == -1)
+ perror("bpf_map_create");
+
+ return map_fd;
+}
+
+static int map_subset(int map0, int map1)
+{
+ unsigned long long next_key = 0;
+ unsigned long long value0[nr_cpus], value1[nr_cpus];
+ int ret;
+
+ while (!bpf_map_next_key(map1, &next_key, &next_key)) {
+ assert(!bpf_map_lookup(map1, &next_key, value1));
+ ret = bpf_map_lookup(map0, &next_key, value0);
+ if (ret) {
+ printf("key:%llu not found from map. %s(%d)\n",
+ next_key, strerror(errno), errno);
+ return 0;
+ }
+ if (value0[0] != value1[0]) {
+ printf("key:%llu value0:%llu != value1:%llu\n",
+ next_key, value0[0], value1[0]);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int map_equal(int lru_map, int expected)
+{
+ return map_subset(lru_map, expected) && map_subset(expected, lru_map);
+}
+
+static int sched_next_online(int pid, int next_to_try)
+{
+ cpu_set_t cpuset;
+
+ if (next_to_try == nr_cpus)
+ return -1;
+
+ while (next_to_try < nr_cpus) {
+ CPU_ZERO(&cpuset);
+ CPU_SET(next_to_try++, &cpuset);
+ if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset))
+ break;
+ }
+
+ return next_to_try;
+}
+
+/* Size of the LRU amp is 2
+ * Add key=1 (+1 key)
+ * Add key=2 (+1 key)
+ * Lookup Key=1
+ * Add Key=3
+ * => Key=2 will be removed by LRU
+ * Iterate map. Only found key=1 and key=3
+ */
+static void test_lru_sanity0(int map_type, int map_flags)
+{
+ unsigned long long key, value[nr_cpus];
+ int lru_map_fd, expected_map_fd;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
+ else
+ lru_map_fd = create_map(map_type, map_flags, 2);
+ assert(lru_map_fd != -1);
+
+ expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
+ assert(expected_map_fd != -1);
+
+ value[0] = 1234;
+
+ /* insert key=1 element */
+
+ key = 1;
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value, BPF_NOEXIST));
+
+ /* BPF_NOEXIST means: add new element if it doesn't exist */
+ assert(bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST) == -1 &&
+ /* key=1 already exists */
+ errno == EEXIST);
+
+ assert(bpf_map_update(lru_map_fd, &key, value, -1) == -1 &&
+ errno == EINVAL);
+
+ /* insert key=2 element */
+
+ /* check that key=2 is not found */
+ key = 2;
+ assert(bpf_map_lookup(lru_map_fd, &key, value) == -1 &&
+ errno == ENOENT);
+
+ /* BPF_EXIST means: update existing element */
+ assert(bpf_map_update(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
+ /* key=2 is not there */
+ errno == ENOENT);
+
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ /* insert key=3 element */
+
+ /* check that key=3 is not found */
+ key = 3;
+ assert(bpf_map_lookup(lru_map_fd, &key, value) == -1 &&
+ errno == ENOENT);
+
+ /* check that key=1 can be found and mark the ref bit to
+ * stop LRU from removing key=1
+ */
+ key = 1;
+ assert(!bpf_map_lookup(lru_map_fd, &key, value));
+ assert(value[0] == 1234);
+
+ key = 3;
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value, BPF_NOEXIST));
+
+ /* key=2 has been removed from the LRU */
+ key = 2;
+ assert(bpf_map_lookup(lru_map_fd, &key, value) == -1);
+
+ assert(map_equal(lru_map_fd, expected_map_fd));
+
+ close(expected_map_fd);
+ close(lru_map_fd);
+
+ printf("Pass\n");
+}
+
+/* Size of the LRU map is 1.5*tgt_free
+ * Insert 1 to tgt_free (+tgt_free keys)
+ * Lookup 1 to tgt_free/2
+ * Insert 1+tgt_free to 2*tgt_free (+tgt_free keys)
+ * => 1+tgt_free/2 to LOCALFREE_TARGET will be removed by LRU
+ */
+static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
+{
+ unsigned long long key, end_key, value[nr_cpus];
+ int lru_map_fd, expected_map_fd;
+ unsigned int batch_size;
+ unsigned int map_size;
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ /* Ther percpu lru list (i.e each cpu has its own LRU
+ * list) does not have a local free list. Hence,
+ * it will only free old nodes till there is no free
+ * from the LRU list. Hence, this test does not apply
+ * to BPF_F_NO_COMMON_LRU
+ */
+ return;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ batch_size = tgt_free / 2;
+ assert(batch_size * 2 == tgt_free);
+
+ map_size = tgt_free + batch_size;
+ lru_map_fd = create_map(map_type, map_flags, map_size);
+ assert(lru_map_fd != -1);
+
+ expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
+ assert(expected_map_fd != -1);
+
+ value[0] = 1234;
+
+ /* Insert 1 to tgt_free (+tgt_free keys) */
+ end_key = 1 + tgt_free;
+ for (key = 1; key < end_key; key++)
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ /* Lookup 1 to tgt_free/2 */
+ end_key = 1 + batch_size;
+ for (key = 1; key < end_key; key++) {
+ assert(!bpf_map_lookup(lru_map_fd, &key, value));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ /* Insert 1+tgt_free to 2*tgt_free
+ * => 1+tgt_free/2 to LOCALFREE_TARGET will be
+ * removed by LRU
+ */
+ key = 1 + tgt_free;
+ end_key = key + tgt_free;
+ for (; key < end_key; key++) {
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ assert(map_equal(lru_map_fd, expected_map_fd));
+
+ close(expected_map_fd);
+ close(lru_map_fd);
+
+ printf("Pass\n");
+}
+
+/* Size of the LRU map 1.5 * tgt_free
+ * Insert 1 to tgt_free (+tgt_free keys)
+ * Update 1 to tgt_free/2
+ * => The original 1 to tgt_free/2 will be removed due to
+ * the LRU shrink process
+ * Re-insert 1 to tgt_free/2 again and do a lookup immeidately
+ * Insert 1+tgt_free to tgt_free*3/2
+ * Insert 1+tgt_free*3/2 to tgt_free*5/2
+ * => Key 1+tgt_free to tgt_free*3/2
+ * will be removed from LRU because it has never
+ * been lookup and ref bit is not set
+ */
+static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
+{
+ unsigned long long key, value[nr_cpus];
+ unsigned long long end_key;
+ int lru_map_fd, expected_map_fd;
+ unsigned int batch_size;
+ unsigned int map_size;
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ /* Ther percpu lru list (i.e each cpu has its own LRU
+ * list) does not have a local free list. Hence,
+ * it will only free old nodes till there is no free
+ * from the LRU list. Hence, this test does not apply
+ * to BPF_F_NO_COMMON_LRU
+ */
+ return;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ batch_size = tgt_free / 2;
+ assert(batch_size * 2 == tgt_free);
+
+ map_size = tgt_free + batch_size;
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ lru_map_fd = create_map(map_type, map_flags,
+ map_size * nr_cpus);
+ else
+ lru_map_fd = create_map(map_type, map_flags, map_size);
+ assert(lru_map_fd != -1);
+
+ expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
+ assert(expected_map_fd != -1);
+
+ value[0] = 1234;
+
+ /* Insert 1 to tgt_free (+tgt_free keys) */
+ end_key = 1 + tgt_free;
+ for (key = 1; key < end_key; key++)
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ /* Any bpf_map_update will require to acquire a new node
+ * from LRU first.
+ *
+ * The local list is running out of free nodes.
+ * It gets from the global LRU list which tries to
+ * shrink the inactive list to get tgt_free
+ * number of free nodes.
+ *
+ * Hence, the oldest key 1 to tgt_free/2
+ * are removed from the LRU list.
+ */
+ key = 1;
+ if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_delete(lru_map_fd, &key));
+ } else {
+ assert(bpf_map_update(lru_map_fd, &key, value, BPF_EXIST));
+ }
+
+ /* Re-insert 1 to tgt_free/2 again and do a lookup
+ * immeidately.
+ */
+ end_key = 1 + batch_size;
+ value[0] = 4321;
+ for (key = 1; key < end_key; key++) {
+ assert(bpf_map_lookup(lru_map_fd, &key, value));
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_lookup(lru_map_fd, &key, value));
+ assert(value[0] == 4321);
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ value[0] = 1234;
+
+ /* Insert 1+tgt_free to tgt_free*3/2 */
+ end_key = 1 + tgt_free + batch_size;
+ for (key = 1 + tgt_free; key < end_key; key++)
+ /* These newly added but not referenced keys will be
+ * gone during the next LRU shrink.
+ */
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */
+ end_key = key + tgt_free;
+ for (; key < end_key; key++) {
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ assert(map_equal(lru_map_fd, expected_map_fd));
+
+ close(expected_map_fd);
+ close(lru_map_fd);
+
+ printf("Pass\n");
+}
+
+/* Size of the LRU map is 2*tgt_free
+ * It is to test the active/inactive list rotation
+ * Insert 1 to 2*tgt_free (+2*tgt_free keys)
+ * Lookup key 1 to tgt_free*3/2
+ * Add 1+2*tgt_free to tgt_free*5/2 (+tgt_free/2 keys)
+ * => key 1+tgt_free*3/2 to 2*tgt_free are removed from LRU
+ */
+static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
+{
+ unsigned long long key, end_key, value[nr_cpus];
+ int lru_map_fd, expected_map_fd;
+ unsigned int batch_size;
+ unsigned int map_size;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ batch_size = tgt_free / 2;
+ assert(batch_size * 2 == tgt_free);
+
+ map_size = tgt_free * 2;
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ lru_map_fd = create_map(map_type, map_flags,
+ map_size * nr_cpus);
+ else
+ lru_map_fd = create_map(map_type, map_flags, map_size);
+ assert(lru_map_fd != -1);
+
+ expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
+ assert(expected_map_fd != -1);
+
+ value[0] = 1234;
+
+ /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */
+ end_key = 1 + (2 * tgt_free);
+ for (key = 1; key < end_key; key++)
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ /* Lookup key 1 to tgt_free*3/2 */
+ end_key = tgt_free + batch_size;
+ for (key = 1; key < end_key; key++) {
+ assert(!bpf_map_lookup(lru_map_fd, &key, value));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ /* Add 1+2*tgt_free to tgt_free*5/2
+ * (+tgt_free/2 keys)
+ */
+ key = 2 * tgt_free + 1;
+ end_key = key + batch_size;
+ for (; key < end_key; key++) {
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ assert(map_equal(lru_map_fd, expected_map_fd));
+
+ close(expected_map_fd);
+ close(lru_map_fd);
+
+ printf("Pass\n");
+}
+
+/* Test deletion */
+static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free)
+{
+ int lru_map_fd, expected_map_fd;
+ unsigned long long key, value[nr_cpus];
+ unsigned long long end_key;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ assert(sched_next_online(0, 0) != -1);
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ lru_map_fd = create_map(map_type, map_flags,
+ 3 * tgt_free * nr_cpus);
+ else
+ lru_map_fd = create_map(map_type, map_flags, 3 * tgt_free);
+ assert(lru_map_fd != -1);
+
+ expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0,
+ 3 * tgt_free);
+ assert(expected_map_fd != -1);
+
+ value[0] = 1234;
+
+ for (key = 1; key <= 2 * tgt_free; key++)
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ key = 1;
+ assert(bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+
+ for (key = 1; key <= tgt_free; key++) {
+ assert(!bpf_map_lookup(lru_map_fd, &key, value));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ for (; key <= 2 * tgt_free; key++) {
+ assert(!bpf_map_delete(lru_map_fd, &key));
+ assert(bpf_map_delete(lru_map_fd, &key));
+ }
+
+ end_key = key + 2 * tgt_free;
+ for (; key < end_key; key++) {
+ assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_update(expected_map_fd, &key, value,
+ BPF_NOEXIST));
+ }
+
+ assert(map_equal(lru_map_fd, expected_map_fd));
+
+ close(expected_map_fd);
+ close(lru_map_fd);
+
+ printf("Pass\n");
+}
+
+static void do_test_lru_sanity5(unsigned long long last_key, int map_fd)
+{
+ unsigned long long key, value[nr_cpus];
+
+ /* Ensure the last key inserted by previous CPU can be found */
+ assert(!bpf_map_lookup(map_fd, &last_key, value));
+
+ value[0] = 1234;
+
+ key = last_key + 1;
+ assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST));
+ assert(!bpf_map_lookup(map_fd, &key, value));
+
+ /* Cannot find the last key because it was removed by LRU */
+ assert(bpf_map_lookup(map_fd, &last_key, value));
+}
+
+/* Test map with only one element */
+static void test_lru_sanity5(int map_type, int map_flags)
+{
+ unsigned long long key, value[nr_cpus];
+ int next_sched_cpu = 0;
+ int map_fd;
+ int i;
+
+ if (map_flags & BPF_F_NO_COMMON_LRU)
+ return;
+
+ printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
+ map_flags);
+
+ map_fd = create_map(map_type, map_flags, 1);
+ assert(map_fd != -1);
+
+ value[0] = 1234;
+ key = 0;
+ assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST));
+
+ for (i = 0; i < nr_cpus; i++) {
+ pid_t pid;
+
+ pid = fork();
+ if (pid == 0) {
+ next_sched_cpu = sched_next_online(0, next_sched_cpu);
+ if (next_sched_cpu != -1)
+ do_test_lru_sanity5(key, map_fd);
+ exit(0);
+ } else if (pid == -1) {
+ printf("couldn't spawn #%d process\n", i);
+ exit(1);
+ } else {
+ int status;
+
+ /* It is mostly redundant and just allow the parent
+ * process to update next_shced_cpu for the next child
+ * process
+ */
+ next_sched_cpu = sched_next_online(pid, next_sched_cpu);
+
+ assert(waitpid(pid, &status, 0) == pid);
+ assert(status == 0);
+ key++;
+ }
+ }
+
+ close(map_fd);
+
+ printf("Pass\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
+ BPF_MAP_TYPE_LRU_PERCPU_HASH};
+ int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
+ int t, f;
+
+ setbuf(stdout, NULL);
+
+ assert(!setrlimit(RLIMIT_MEMLOCK, &r));
+
+ nr_cpus = bpf_num_possible_cpus();
+ assert(nr_cpus != -1);
+ printf("nr_cpus:%d\n\n", nr_cpus);
+
+ for (f = 0; f < sizeof(map_flags) / sizeof(*map_flags); f++) {
+ unsigned int tgt_free = (map_flags[f] & BPF_F_NO_COMMON_LRU) ?
+ PERCPU_FREE_TARGET : LOCAL_FREE_TARGET;
+
+ for (t = 0; t < sizeof(map_types) / sizeof(*map_types); t++) {
+ test_lru_sanity0(map_types[t], map_flags[f]);
+ test_lru_sanity1(map_types[t], map_flags[f], tgt_free);
+ test_lru_sanity2(map_types[t], map_flags[f], tgt_free);
+ test_lru_sanity3(map_types[t], map_flags[f], tgt_free);
+ test_lru_sanity4(map_types[t], map_flags[f], tgt_free);
+ test_lru_sanity5(map_types[t], map_flags[f]);
+
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
new file mode 100644
index 000000000000..eedfef8d2946
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -0,0 +1,526 @@
+/*
+ * Testsuite for eBPF maps
+ *
+ * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
+ * Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute 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 <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+#include <linux/bpf.h>
+
+#include "bpf_sys.h"
+#include "bpf_util.h"
+
+static int map_flags;
+
+static void test_hashmap(int task, void *data)
+{
+ long long key, next_key, value;
+ int fd;
+
+ fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+ 2, map_flags);
+ if (fd < 0) {
+ printf("Failed to create hashmap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ key = 1;
+ value = 1234;
+ /* Insert key=1 element. */
+ assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+ value = 0;
+ /* BPF_NOEXIST means add new element if it doesn't exist. */
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+ /* key=1 already exists. */
+ errno == EEXIST);
+
+ /* -1 is an invalid flag. */
+ assert(bpf_map_update(fd, &key, &value, -1) == -1 && errno == EINVAL);
+
+ /* Check that key=1 can be found. */
+ assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234);
+
+ key = 2;
+ /* Check that key=2 is not found. */
+ assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+ /* BPF_EXIST means update existing element. */
+ assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 &&
+ /* key=2 is not there. */
+ errno == ENOENT);
+
+ /* Insert key=2 element. */
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+
+ /* key=1 and key=2 were inserted, check that key=0 cannot be
+ * inserted due to max_entries limit.
+ */
+ key = 0;
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+ errno == E2BIG);
+
+ /* Update existing element, though the map is full. */
+ key = 1;
+ assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0);
+ key = 2;
+ assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+ key = 1;
+ assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+ /* Check that key = 0 doesn't exist. */
+ key = 0;
+ assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+ /* Iterate over two elements. */
+ assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+ (next_key == 1 || next_key == 2));
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+ (next_key == 1 || next_key == 2));
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+ errno == ENOENT);
+
+ /* Delete both elements. */
+ key = 1;
+ assert(bpf_map_delete(fd, &key) == 0);
+ key = 2;
+ assert(bpf_map_delete(fd, &key) == 0);
+ assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+ key = 0;
+ /* Check that map is empty. */
+ assert(bpf_map_next_key(fd, &key, &next_key) == -1 &&
+ errno == ENOENT);
+
+ close(fd);
+}
+
+static void test_hashmap_percpu(int task, void *data)
+{
+ unsigned int nr_cpus = bpf_num_possible_cpus();
+ long long value[nr_cpus];
+ long long key, next_key;
+ int expected_key_mask = 0;
+ int fd, i;
+
+ fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
+ sizeof(value[0]), 2, map_flags);
+ if (fd < 0) {
+ printf("Failed to create hashmap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ for (i = 0; i < nr_cpus; i++)
+ value[i] = i + 100;
+
+ key = 1;
+ /* Insert key=1 element. */
+ assert(!(expected_key_mask & key));
+ assert(bpf_map_update(fd, &key, value, BPF_ANY) == 0);
+ expected_key_mask |= key;
+
+ /* BPF_NOEXIST means add new element if it doesn't exist. */
+ assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 &&
+ /* key=1 already exists. */
+ errno == EEXIST);
+
+ /* -1 is an invalid flag. */
+ assert(bpf_map_update(fd, &key, value, -1) == -1 && errno == EINVAL);
+
+ /* Check that key=1 can be found. Value could be 0 if the lookup
+ * was run from a different CPU.
+ */
+ value[0] = 1;
+ assert(bpf_map_lookup(fd, &key, value) == 0 && value[0] == 100);
+
+ key = 2;
+ /* Check that key=2 is not found. */
+ assert(bpf_map_lookup(fd, &key, value) == -1 && errno == ENOENT);
+
+ /* BPF_EXIST means update existing element. */
+ assert(bpf_map_update(fd, &key, value, BPF_EXIST) == -1 &&
+ /* key=2 is not there. */
+ errno == ENOENT);
+
+ /* Insert key=2 element. */
+ assert(!(expected_key_mask & key));
+ assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == 0);
+ expected_key_mask |= key;
+
+ /* key=1 and key=2 were inserted, check that key=0 cannot be
+ * inserted due to max_entries limit.
+ */
+ key = 0;
+ assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 &&
+ errno == E2BIG);
+
+ /* Check that key = 0 doesn't exist. */
+ assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+ /* Iterate over two elements. */
+ while (!bpf_map_next_key(fd, &key, &next_key)) {
+ assert((expected_key_mask & next_key) == next_key);
+ expected_key_mask &= ~next_key;
+
+ assert(bpf_map_lookup(fd, &next_key, value) == 0);
+
+ for (i = 0; i < nr_cpus; i++)
+ assert(value[i] == i + 100);
+
+ key = next_key;
+ }
+ assert(errno == ENOENT);
+
+ /* Update with BPF_EXIST. */
+ key = 1;
+ assert(bpf_map_update(fd, &key, value, BPF_EXIST) == 0);
+
+ /* Delete both elements. */
+ key = 1;
+ assert(bpf_map_delete(fd, &key) == 0);
+ key = 2;
+ assert(bpf_map_delete(fd, &key) == 0);
+ assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+ key = 0;
+ /* Check that map is empty. */
+ assert(bpf_map_next_key(fd, &key, &next_key) == -1 &&
+ errno == ENOENT);
+
+ close(fd);
+}
+
+static void test_arraymap(int task, void *data)
+{
+ int key, next_key, fd;
+ long long value;
+
+ fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
+ 2, 0);
+ if (fd < 0) {
+ printf("Failed to create arraymap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ key = 1;
+ value = 1234;
+ /* Insert key=1 element. */
+ assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+ value = 0;
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+ errno == EEXIST);
+
+ /* Check that key=1 can be found. */
+ assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234);
+
+ key = 0;
+ /* Check that key=0 is also found and zero initialized. */
+ assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0);
+
+ /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
+ * due to max_entries limit.
+ */
+ key = 2;
+ assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 &&
+ errno == E2BIG);
+
+ /* Check that key = 2 doesn't exist. */
+ assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+ /* Iterate over two elements. */
+ assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+ next_key == 0);
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+ next_key == 1);
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+ errno == ENOENT);
+
+ /* Delete shouldn't succeed. */
+ key = 1;
+ assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL);
+
+ close(fd);
+}
+
+static void test_arraymap_percpu(int task, void *data)
+{
+ unsigned int nr_cpus = bpf_num_possible_cpus();
+ int key, next_key, fd, i;
+ long values[nr_cpus];
+
+ fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
+ sizeof(values[0]), 2, 0);
+ if (fd < 0) {
+ printf("Failed to create arraymap '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ for (i = 0; i < nr_cpus; i++)
+ values[i] = i + 100;
+
+ key = 1;
+ /* Insert key=1 element. */
+ assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0);
+
+ values[0] = 0;
+ assert(bpf_map_update(fd, &key, values, BPF_NOEXIST) == -1 &&
+ errno == EEXIST);
+
+ /* Check that key=1 can be found. */
+ assert(bpf_map_lookup(fd, &key, values) == 0 && values[0] == 100);
+
+ key = 0;
+ /* Check that key=0 is also found and zero initialized. */
+ assert(bpf_map_lookup(fd, &key, values) == 0 &&
+ values[0] == 0 && values[nr_cpus - 1] == 0);
+
+ /* Check that key=2 cannot be inserted due to max_entries limit. */
+ key = 2;
+ assert(bpf_map_update(fd, &key, values, BPF_EXIST) == -1 &&
+ errno == E2BIG);
+
+ /* Check that key = 2 doesn't exist. */
+ assert(bpf_map_lookup(fd, &key, values) == -1 && errno == ENOENT);
+
+ /* Iterate over two elements. */
+ assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+ next_key == 0);
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+ next_key == 1);
+ assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+ errno == ENOENT);
+
+ /* Delete shouldn't succeed. */
+ key = 1;
+ assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL);
+
+ close(fd);
+}
+
+static void test_arraymap_percpu_many_keys(void)
+{
+ unsigned int nr_cpus = bpf_num_possible_cpus();
+ unsigned int nr_keys = 20000;
+ long values[nr_cpus];
+ int key, fd, i;
+
+ fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
+ sizeof(values[0]), nr_keys, 0);
+ if (fd < 0) {
+ printf("Failed to create per-cpu arraymap '%s'!\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ for (i = 0; i < nr_cpus; i++)
+ values[i] = i + 10;
+
+ for (key = 0; key < nr_keys; key++)
+ assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0);
+
+ for (key = 0; key < nr_keys; key++) {
+ for (i = 0; i < nr_cpus; i++)
+ values[i] = 0;
+
+ assert(bpf_map_lookup(fd, &key, values) == 0);
+
+ for (i = 0; i < nr_cpus; i++)
+ assert(values[i] == i + 10);
+ }
+
+ close(fd);
+}
+
+#define MAP_SIZE (32 * 1024)
+
+static void test_map_large(void)
+{
+ struct bigkey {
+ int a;
+ char b[116];
+ long long c;
+ } key;
+ int fd, i, value;
+
+ fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+ MAP_SIZE, map_flags);
+ if (fd < 0) {
+ printf("Failed to create large map '%s'!\n", strerror(errno));
+ exit(1);
+ }
+
+ for (i = 0; i < MAP_SIZE; i++) {
+ key = (struct bigkey) { .c = i };
+ value = i;
+
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+ }
+
+ key.c = -1;
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+ errno == E2BIG);
+
+ /* Iterate through all elements. */
+ for (i = 0; i < MAP_SIZE; i++)
+ assert(bpf_map_next_key(fd, &key, &key) == 0);
+ assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+
+ key.c = 0;
+ assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0);
+ key.a = 1;
+ assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+ close(fd);
+}
+
+static void run_parallel(int tasks, void (*fn)(int task, void *data),
+ void *data)
+{
+ pid_t pid[tasks];
+ int i;
+
+ for (i = 0; i < tasks; i++) {
+ pid[i] = fork();
+ if (pid[i] == 0) {
+ fn(i, data);
+ exit(0);
+ } else if (pid[i] == -1) {
+ printf("Couldn't spawn #%d process!\n", i);
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < tasks; i++) {
+ int status;
+
+ assert(waitpid(pid[i], &status, 0) == pid[i]);
+ assert(status == 0);
+ }
+}
+
+static void test_map_stress(void)
+{
+ run_parallel(100, test_hashmap, NULL);
+ run_parallel(100, test_hashmap_percpu, NULL);
+
+ run_parallel(100, test_arraymap, NULL);
+ run_parallel(100, test_arraymap_percpu, NULL);
+}
+
+#define TASKS 1024
+
+#define DO_UPDATE 1
+#define DO_DELETE 0
+
+static void do_work(int fn, void *data)
+{
+ int do_update = ((int *)data)[1];
+ int fd = ((int *)data)[0];
+ int i, key, value;
+
+ for (i = fn; i < MAP_SIZE; i += TASKS) {
+ key = value = i;
+
+ if (do_update) {
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+ assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0);
+ } else {
+ assert(bpf_map_delete(fd, &key) == 0);
+ }
+ }
+}
+
+static void test_map_parallel(void)
+{
+ int i, fd, key = 0, value = 0;
+ int data[2];
+
+ fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+ MAP_SIZE, map_flags);
+ if (fd < 0) {
+ printf("Failed to create map for parallel test '%s'!\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ /* Use the same fd in children to add elements to this map:
+ * child_0 adds key=0, key=1024, key=2048, ...
+ * child_1 adds key=1, key=1025, key=2049, ...
+ * child_1023 adds key=1023, ...
+ */
+ data[0] = fd;
+ data[1] = DO_UPDATE;
+ run_parallel(TASKS, do_work, data);
+
+ /* Check that key=0 is already there. */
+ assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+ errno == EEXIST);
+
+ /* Check that all elements were inserted. */
+ key = -1;
+ for (i = 0; i < MAP_SIZE; i++)
+ assert(bpf_map_next_key(fd, &key, &key) == 0);
+ assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+
+ /* Another check for all elements */
+ for (i = 0; i < MAP_SIZE; i++) {
+ key = MAP_SIZE - i - 1;
+
+ assert(bpf_map_lookup(fd, &key, &value) == 0 &&
+ value == key);
+ }
+
+ /* Now let's delete all elemenets in parallel. */
+ data[1] = DO_DELETE;
+ run_parallel(TASKS, do_work, data);
+
+ /* Nothing should be left. */
+ key = -1;
+ assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+}
+
+static void run_all_tests(void)
+{
+ test_hashmap(0, NULL);
+ test_hashmap_percpu(0, NULL);
+
+ test_arraymap(0, NULL);
+ test_arraymap_percpu(0, NULL);
+
+ test_arraymap_percpu_many_keys();
+
+ test_map_large();
+ test_map_parallel();
+ test_map_stress();
+}
+
+int main(void)
+{
+ struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+
+ setrlimit(RLIMIT_MEMLOCK, &rinf);
+
+ map_flags = 0;
+ run_all_tests();
+
+ map_flags = BPF_F_NO_PREALLOC;
+ run_all_tests();
+
+ printf("test_maps: OK\n");
+ return 0;
+}
diff --git a/samples/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 369ffaad3799..0103bf2e0c0d 100644
--- a/samples/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -7,29 +7,39 @@
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
+
#include <stdio.h>
#include <unistd.h>
-#include <linux/bpf.h>
#include <errno.h>
-#include <linux/unistd.h>
#include <string.h>
-#include <linux/filter.h>
#include <stddef.h>
#include <stdbool.h>
+#include <sched.h>
+
#include <sys/resource.h>
-#include "libbpf.h"
-#define MAX_INSNS 512
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#include <linux/unistd.h>
+#include <linux/filter.h>
+#include <linux/bpf_perf_event.h>
+#include <linux/bpf.h>
+
+#include "../../../include/linux/filter.h"
-#define MAX_FIXUPS 8
+#include "bpf_sys.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#define MAX_INSNS 512
+#define MAX_FIXUPS 8
struct bpf_test {
const char *descr;
struct bpf_insn insns[MAX_INSNS];
- int fixup[MAX_FIXUPS];
- int prog_array_fixup[MAX_FIXUPS];
- int test_val_map_fixup[MAX_FIXUPS];
+ int fixup_map1[MAX_FIXUPS];
+ int fixup_map2[MAX_FIXUPS];
+ int fixup_prog[MAX_FIXUPS];
const char *errstr;
const char *errstr_unpriv;
enum {
@@ -44,15 +54,12 @@ struct bpf_test {
* actually the end of the structure.
*/
#define MAX_ENTRIES 11
+
struct test_val {
- unsigned index;
+ unsigned int index;
int foo[MAX_ENTRIES];
};
-struct other_val {
- unsigned int action[32];
-};
-
static struct bpf_test tests[] = {
{
"add+sub+mul",
@@ -278,7 +285,7 @@ static struct bpf_test tests[] = {
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
BPF_EXIT_INSN(),
},
- .errstr = "invalid func 1234567",
+ .errstr = "invalid func unknown#1234567",
.result = REJECT,
},
{
@@ -287,10 +294,11 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_EXIT_INSN(),
},
- .fixup = {2},
+ .fixup_map1 = { 2 },
.errstr = "invalid indirect read from stack",
.result = REJECT,
},
@@ -307,8 +315,10 @@ static struct bpf_test tests[] = {
{
"invalid argument register",
.insns = {
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_cgroup_classid),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_cgroup_classid),
BPF_EXIT_INSN(),
},
.errstr = "R1 !read_ok",
@@ -319,9 +329,11 @@ static struct bpf_test tests[] = {
"non-invalid argument register",
.insns = {
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_cgroup_classid),
BPF_ALU64_REG(BPF_MOV, BPF_REG_1, BPF_REG_6),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_cgroup_classid),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
@@ -332,10 +344,8 @@ static struct bpf_test tests[] = {
.insns = {
/* spill R1(ctx) into stack */
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
-
/* fill it back into R2 */
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
-
/* should be able to access R0 = *(R2 + 8) */
/* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
@@ -363,13 +373,10 @@ static struct bpf_test tests[] = {
.insns = {
/* spill R1(ctx) into stack */
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
-
/* mess up with R1 pointer on stack */
BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
-
/* fill back into R0 should fail */
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
-
BPF_EXIT_INSN(),
},
.errstr_unpriv = "attempt to corrupt spilled",
@@ -483,7 +490,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_delete_elem),
BPF_EXIT_INSN(),
},
.errstr = "fd 0 is not pointing to valid bpf_map",
@@ -496,11 +504,12 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr = "R0 invalid mem access 'map_value_or_null'",
.result = REJECT,
},
@@ -511,12 +520,13 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr = "misaligned access",
.result = REJECT,
},
@@ -527,14 +537,15 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
BPF_EXIT_INSN(),
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr = "R0 invalid mem access",
.errstr_unpriv = "R0 leaks addr",
.result = REJECT,
@@ -619,10 +630,11 @@ static struct bpf_test tests[] = {
BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_delete_elem),
BPF_EXIT_INSN(),
},
- .fixup = {24},
+ .fixup_map1 = { 24 },
.errstr_unpriv = "R1 pointer comparison",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -763,7 +775,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
@@ -771,7 +784,7 @@ static struct bpf_test tests[] = {
offsetof(struct __sk_buff, pkt_type)),
BPF_EXIT_INSN(),
},
- .fixup = {4},
+ .fixup_map1 = { 4 },
.errstr = "different pointers",
.errstr_unpriv = "R1 pointer comparison",
.result = REJECT,
@@ -787,13 +800,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_JMP_IMM(BPF_JA, 0, 0, -12),
},
- .fixup = {6},
+ .fixup_map1 = { 6 },
.errstr = "different pointers",
.errstr_unpriv = "R1 pointer comparison",
.result = REJECT,
@@ -810,13 +824,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_JMP_IMM(BPF_JA, 0, 0, -13),
},
- .fixup = {7},
+ .fixup_map1 = { 7 },
.errstr = "different pointers",
.errstr_unpriv = "R1 pointer comparison",
.result = REJECT,
@@ -1039,7 +1054,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
BPF_MOV64_IMM(BPF_REG_2, 8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_trace_printk),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -1056,11 +1072,12 @@ static struct bpf_test tests[] = {
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_update_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr_unpriv = "R4 leaks addr",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -1072,11 +1089,12 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr = "invalid indirect read from stack off -8+0 size 8",
.result = REJECT,
},
@@ -1128,18 +1146,125 @@ static struct bpf_test tests[] = {
.result = REJECT,
},
{
+ "unpriv: spill/fill of ctx",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ },
+ {
+ "unpriv: spill/fill of ctx 2",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_hash_recalc),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ },
+ {
+ "unpriv: spill/fill of ctx 3",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_hash_recalc),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "R1 type=fp expected=ctx",
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ },
+ {
+ "unpriv: spill/fill of ctx 4",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 1),
+ BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_10,
+ BPF_REG_0, -8, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_hash_recalc),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "R1 type=inv expected=ctx",
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ },
+ {
+ "unpriv: spill/fill of different pointers stx",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_3, 42),
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
+ offsetof(struct __sk_buff, mark)),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "same insn cannot be used with different pointers",
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ },
+ {
+ "unpriv: spill/fill of different pointers ldx",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2,
+ -(__s32)offsetof(struct bpf_perf_event_data,
+ sample_period) - 8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1,
+ offsetof(struct bpf_perf_event_data,
+ sample_period)),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "same insn cannot be used with different pointers",
+ .prog_type = BPF_PROG_TYPE_PERF_EVENT,
+ },
+ {
"unpriv: write pointer into map elem value",
.insns = {
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {3},
+ .fixup_map1 = { 3 },
.errstr_unpriv = "R0 leaks addr",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -1160,11 +1285,12 @@ static struct bpf_test tests[] = {
.insns = {
BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
BPF_LD_MAP_FD(BPF_REG_2, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_tail_call),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .prog_array_fixup = {1},
+ .fixup_prog = { 1 },
.errstr_unpriv = "R3 leaks addr into helper",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -1178,7 +1304,7 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {1},
+ .fixup_map1 = { 1 },
.errstr_unpriv = "R1 pointer comparison",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -1194,6 +1320,19 @@ static struct bpf_test tests[] = {
.result = REJECT,
},
{
+ "unpriv: spill/fill frame pointer",
+ .insns = {
+ BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, 0),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "frame pointer is read only",
+ .result = REJECT,
+ },
+ {
"unpriv: cmp of frame pointer",
.insns = {
BPF_JMP_IMM(BPF_JEQ, BPF_REG_10, 0, 0),
@@ -1254,7 +1393,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, -8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1270,7 +1410,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, ~0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1286,7 +1427,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1302,7 +1444,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1318,7 +1461,8 @@ static struct bpf_test tests[] = {
BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xcafe),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1331,13 +1475,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_2, 4),
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
- BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8),
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
offsetof(struct __sk_buff, mark)),
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1354,11 +1499,12 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_2, 4),
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), /* fill ctx into R0 */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
offsetof(struct __sk_buff, mark)),
BPF_EXIT_INSN(),
@@ -1373,15 +1519,16 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_2, 4),
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
- BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
- BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill ctx into R3 */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0),
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
offsetof(struct __sk_buff, mark)),
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1402,15 +1549,16 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_2, 4),
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
- BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+ BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
- BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
- BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill data into R3 */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8),
+ BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0),
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
offsetof(struct __sk_buff, mark)),
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1430,7 +1578,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -513),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1446,7 +1595,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 8),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1462,7 +1612,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0xffffffff),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1478,7 +1629,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1494,7 +1646,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1510,7 +1663,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1526,7 +1680,8 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_4, 512),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
BPF_EXIT_INSN(),
},
@@ -1747,11 +1902,12 @@ static struct bpf_test tests[] = {
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
BPF_MOV64_IMM(BPF_REG_4, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_update_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {5},
+ .fixup_map1 = { 5 },
.result_unpriv = ACCEPT,
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_XDP,
@@ -1762,11 +1918,12 @@ static struct bpf_test tests[] = {
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
offsetof(struct xdp_md, data)),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {1},
+ .fixup_map1 = { 1 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_XDP,
@@ -1789,11 +1946,12 @@ static struct bpf_test tests[] = {
BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {11},
+ .fixup_map1 = { 11 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_XDP,
},
@@ -1810,11 +1968,12 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {7},
+ .fixup_map1 = { 7 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_XDP,
@@ -1831,11 +1990,12 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {6},
+ .fixup_map1 = { 6 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_XDP,
@@ -1853,11 +2013,12 @@ static struct bpf_test tests[] = {
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
BPF_MOV64_IMM(BPF_REG_4, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_update_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {5},
+ .fixup_map1 = { 5 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
@@ -1867,11 +2028,12 @@ static struct bpf_test tests[] = {
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
offsetof(struct __sk_buff, data)),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {1},
+ .fixup_map1 = { 1 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1894,11 +2056,12 @@ static struct bpf_test tests[] = {
BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {11},
+ .fixup_map1 = { 11 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
@@ -1915,11 +2078,12 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {7},
+ .fixup_map1 = { 7 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1936,11 +2100,12 @@ static struct bpf_test tests[] = {
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup = {6},
+ .fixup_map1 = { 6 },
.result = REJECT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1959,7 +2124,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_MOV64_IMM(BPF_REG_4, 42),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_store_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_store_bytes),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -1979,7 +2145,8 @@ static struct bpf_test tests[] = {
BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 3),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_MOV64_IMM(BPF_REG_4, 4),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_skb_load_bytes),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2003,7 +2170,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2026,7 +2194,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2050,7 +2219,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2074,7 +2244,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2098,7 +2269,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2122,7 +2294,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2146,7 +2319,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2169,7 +2343,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_diff),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
@@ -2184,12 +2359,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
.errstr_unpriv = "R0 leaks addr",
.result_unpriv = REJECT,
.result = ACCEPT,
@@ -2201,16 +2378,18 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
BPF_MOV64_IMM(BPF_REG_1, 4),
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
- .errstr_unpriv = "R0 leaks addr",
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.result_unpriv = REJECT,
.result = ACCEPT,
},
@@ -2221,17 +2400,19 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES, 3),
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
- .errstr_unpriv = "R0 leaks addr",
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.result_unpriv = REJECT,
.result = ACCEPT,
},
@@ -2242,7 +2423,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 0xffffffff, 1),
@@ -2252,11 +2434,12 @@ static struct bpf_test tests[] = {
BPF_MOV32_IMM(BPF_REG_1, 0),
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
- .errstr_unpriv = "R0 leaks addr",
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.result_unpriv = REJECT,
.result = ACCEPT,
},
@@ -2267,13 +2450,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
BPF_ST_MEM(BPF_DW, BPF_REG_0, (MAX_ENTRIES + 1) << 2,
offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
.errstr = "invalid access to map value, value_size=48 off=48 size=8",
.result = REJECT,
},
@@ -2284,16 +2468,20 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
BPF_MOV64_IMM(BPF_REG_1, MAX_ENTRIES + 1),
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.errstr = "R0 min value is outside of the array range",
+ .result_unpriv = REJECT,
.result = REJECT,
},
{
@@ -2303,16 +2491,20 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+ .result_unpriv = REJECT,
.result = REJECT,
},
{
@@ -2322,7 +2514,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
@@ -2330,11 +2523,14 @@ static struct bpf_test tests[] = {
BPF_MOV32_IMM(BPF_REG_1, 0),
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+ .result_unpriv = REJECT,
.result = REJECT,
},
{
@@ -2344,7 +2540,8 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES + 1),
@@ -2352,11 +2549,14 @@ static struct bpf_test tests[] = {
BPF_MOV32_IMM(BPF_REG_1, 0),
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
- BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3},
+ .fixup_map2 = { 3 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.errstr = "invalid access to map value, value_size=48 off=44 size=8",
+ .result_unpriv = REJECT,
.result = REJECT,
},
{
@@ -2366,164 +2566,488 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
- BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8),
- BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct test_val, foo)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
+ offsetof(struct test_val, foo)),
BPF_EXIT_INSN(),
},
- .test_val_map_fixup = {3, 11},
+ .fixup_map2 = { 3, 11 },
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+ .result_unpriv = REJECT,
+ .result = REJECT,
+ },
+ {
+ "multiple registers share map_lookup_elem result",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_1, 10),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+ BPF_LD_MAP_FD(BPF_REG_1, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+ BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .fixup_map1 = { 4 },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS
+ },
+ {
+ "invalid memory access with multiple map_lookup_elem calls",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_1, 10),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+ BPF_LD_MAP_FD(BPF_REG_1, 0),
+ BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+ BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .fixup_map1 = { 4 },
+ .result = REJECT,
+ .errstr = "R4 !read_ok",
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS
+ },
+ {
+ "valid indirect map_lookup_elem access with 2nd lookup in branch",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_1, 10),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+ BPF_LD_MAP_FD(BPF_REG_1, 0),
+ BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_MOV64_IMM(BPF_REG_2, 10),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0, 3),
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+ BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .fixup_map1 = { 4 },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS
+ },
+ {
+ "invalid map access from else condition",
+ .insns = {
+ BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+ BPF_LD_MAP_FD(BPF_REG_1, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
+ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+ BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES-1, 1),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
+ BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
+ BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+ BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+ BPF_EXIT_INSN(),
+ },
+ .fixup_map2 = { 3 },
+ .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map",
+ .result = REJECT,
+ .errstr_unpriv = "R0 pointer arithmetic prohibited",
+ .result_unpriv = REJECT,
+ },
+ {
+ "constant register |= constant should keep constant type",
+ .insns = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -48),
+ BPF_MOV64_IMM(BPF_REG_2, 34),
+ BPF_ALU64_IMM(BPF_OR, BPF_REG_2, 13),
+ BPF_MOV64_IMM(BPF_REG_3, 0),
+ BPF_EMIT_CALL(BPF_FUNC_probe_read),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+ },
+ {
+ "constant register |= constant should not bypass stack boundary checks",
+ .insns = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -48),
+ BPF_MOV64_IMM(BPF_REG_2, 34),
+ BPF_ALU64_IMM(BPF_OR, BPF_REG_2, 24),
+ BPF_MOV64_IMM(BPF_REG_3, 0),
+ BPF_EMIT_CALL(BPF_FUNC_probe_read),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "invalid stack type R1 off=-48 access_size=58",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+ },
+ {
+ "constant register |= constant register should keep constant type",
+ .insns = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -48),
+ BPF_MOV64_IMM(BPF_REG_2, 34),
+ BPF_MOV64_IMM(BPF_REG_4, 13),
+ BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_4),
+ BPF_MOV64_IMM(BPF_REG_3, 0),
+ BPF_EMIT_CALL(BPF_FUNC_probe_read),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+ },
+ {
+ "constant register |= constant register should not bypass stack boundary checks",
+ .insns = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -48),
+ BPF_MOV64_IMM(BPF_REG_2, 34),
+ BPF_MOV64_IMM(BPF_REG_4, 24),
+ BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_4),
+ BPF_MOV64_IMM(BPF_REG_3, 0),
+ BPF_EMIT_CALL(BPF_FUNC_probe_read),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "invalid stack type R1 off=-48 access_size=58",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+ },
+ {
+ "invalid direct packet write for LWT_IN",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "cannot write into packet",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_LWT_IN,
+ },
+ {
+ "invalid direct packet write for LWT_OUT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "cannot write into packet",
.result = REJECT,
+ .prog_type = BPF_PROG_TYPE_LWT_OUT,
+ },
+ {
+ "direct packet write for LWT_XMIT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_LWT_XMIT,
+ },
+ {
+ "direct packet read for LWT_IN",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_LWT_IN,
+ },
+ {
+ "direct packet read for LWT_OUT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_LWT_OUT,
+ },
+ {
+ "direct packet read for LWT_XMIT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct __sk_buff, data)),
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+ offsetof(struct __sk_buff, data_end)),
+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
+ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+ BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_LWT_XMIT,
+ },
+ {
+ "invalid access of tc_classid for LWT_IN",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct __sk_buff, tc_classid)),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "invalid bpf_context access",
+ },
+ {
+ "invalid access of tc_classid for LWT_OUT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct __sk_buff, tc_classid)),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "invalid bpf_context access",
+ },
+ {
+ "invalid access of tc_classid for LWT_XMIT",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct __sk_buff, tc_classid)),
+ BPF_EXIT_INSN(),
+ },
+ .result = REJECT,
+ .errstr = "invalid bpf_context access",
},
};
-static int probe_filter_length(struct bpf_insn *fp)
+static int probe_filter_length(const struct bpf_insn *fp)
{
- int len = 0;
+ int len;
for (len = MAX_INSNS - 1; len > 0; --len)
if (fp[len].code != 0 || fp[len].imm != 0)
break;
-
return len + 1;
}
-static int create_map(size_t val_size, int num)
+static int create_map(uint32_t size_value, uint32_t max_elem)
{
- int map_fd;
+ int fd;
- map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
- sizeof(long long), val_size, num, 0);
- if (map_fd < 0)
- printf("failed to create map '%s'\n", strerror(errno));
+ fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(long long),
+ size_value, max_elem, BPF_F_NO_PREALLOC);
+ if (fd < 0)
+ printf("Failed to create hash map '%s'!\n", strerror(errno));
- return map_fd;
+ return fd;
}
static int create_prog_array(void)
{
- int map_fd;
+ int fd;
- map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY,
- sizeof(int), sizeof(int), 4, 0);
- if (map_fd < 0)
- printf("failed to create prog_array '%s'\n", strerror(errno));
+ fd = bpf_map_create(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
+ sizeof(int), 4, 0);
+ if (fd < 0)
+ printf("Failed to create prog array '%s'!\n", strerror(errno));
- return map_fd;
+ return fd;
}
-static int test(void)
+static char bpf_vlog[32768];
+
+static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
+ int *fd_f1, int *fd_f2, int *fd_f3)
{
- int prog_fd, i, pass_cnt = 0, err_cnt = 0;
- bool unpriv = geteuid() != 0;
+ int *fixup_map1 = test->fixup_map1;
+ int *fixup_map2 = test->fixup_map2;
+ int *fixup_prog = test->fixup_prog;
- for (i = 0; i < ARRAY_SIZE(tests); i++) {
- struct bpf_insn *prog = tests[i].insns;
- int prog_type = tests[i].prog_type;
- int prog_len = probe_filter_length(prog);
- int *fixup = tests[i].fixup;
- int *prog_array_fixup = tests[i].prog_array_fixup;
- int *test_val_map_fixup = tests[i].test_val_map_fixup;
- int expected_result;
- const char *expected_errstr;
- int map_fd = -1, prog_array_fd = -1, test_val_map_fd = -1;
+ /* Allocating HTs with 1 elem is fine here, since we only test
+ * for verifier and not do a runtime lookup, so the only thing
+ * that really matters is value size in this case.
+ */
+ if (*fixup_map1) {
+ *fd_f1 = create_map(sizeof(long long), 1);
+ do {
+ prog[*fixup_map1].imm = *fd_f1;
+ fixup_map1++;
+ } while (*fixup_map1);
+ }
- if (*fixup) {
- map_fd = create_map(sizeof(long long), 1024);
+ if (*fixup_map2) {
+ *fd_f2 = create_map(sizeof(struct test_val), 1);
+ do {
+ prog[*fixup_map2].imm = *fd_f2;
+ fixup_map2++;
+ } while (*fixup_map2);
+ }
- do {
- prog[*fixup].imm = map_fd;
- fixup++;
- } while (*fixup);
- }
- if (*prog_array_fixup) {
- prog_array_fd = create_prog_array();
+ if (*fixup_prog) {
+ *fd_f3 = create_prog_array();
+ do {
+ prog[*fixup_prog].imm = *fd_f3;
+ fixup_prog++;
+ } while (*fixup_prog);
+ }
+}
- do {
- prog[*prog_array_fixup].imm = prog_array_fd;
- prog_array_fixup++;
- } while (*prog_array_fixup);
- }
- if (*test_val_map_fixup) {
- /* Unprivileged can't create a hash map.*/
- if (unpriv)
- continue;
- test_val_map_fd = create_map(sizeof(struct test_val),
- 256);
- do {
- prog[*test_val_map_fixup].imm = test_val_map_fd;
- test_val_map_fixup++;
- } while (*test_val_map_fixup);
- }
+static void do_test_single(struct bpf_test *test, bool unpriv,
+ int *passes, int *errors)
+{
+ struct bpf_insn *prog = test->insns;
+ int prog_len = probe_filter_length(prog);
+ int prog_type = test->prog_type;
+ int fd_f1 = -1, fd_f2 = -1, fd_f3 = -1;
+ int fd_prog, expected_ret;
+ const char *expected_err;
+
+ do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3);
- printf("#%d %s ", i, tests[i].descr);
+ fd_prog = bpf_prog_load(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+ prog, prog_len * sizeof(struct bpf_insn),
+ "GPL", bpf_vlog, sizeof(bpf_vlog));
- prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
- prog, prog_len * sizeof(struct bpf_insn),
- "GPL", 0);
+ expected_ret = unpriv && test->result_unpriv != UNDEF ?
+ test->result_unpriv : test->result;
+ expected_err = unpriv && test->errstr_unpriv ?
+ test->errstr_unpriv : test->errstr;
+ if (expected_ret == ACCEPT) {
+ if (fd_prog < 0) {
+ printf("FAIL\nFailed to load prog '%s'!\n",
+ strerror(errno));
+ goto fail_log;
+ }
+ } else {
+ if (fd_prog >= 0) {
+ printf("FAIL\nUnexpected success to load!\n");
+ goto fail_log;
+ }
+ if (!strstr(bpf_vlog, expected_err)) {
+ printf("FAIL\nUnexpected error message!\n");
+ goto fail_log;
+ }
+ }
- if (unpriv && tests[i].result_unpriv != UNDEF)
- expected_result = tests[i].result_unpriv;
- else
- expected_result = tests[i].result;
+ (*passes)++;
+ printf("OK\n");
+close_fds:
+ close(fd_prog);
+ close(fd_f1);
+ close(fd_f2);
+ close(fd_f3);
+ sched_yield();
+ return;
+fail_log:
+ (*errors)++;
+ printf("%s", bpf_vlog);
+ goto close_fds;
+}
- if (unpriv && tests[i].errstr_unpriv)
- expected_errstr = tests[i].errstr_unpriv;
- else
- expected_errstr = tests[i].errstr;
+static int do_test(bool unpriv, unsigned int from, unsigned int to)
+{
+ int i, passes = 0, errors = 0;
- if (expected_result == ACCEPT) {
- if (prog_fd < 0) {
- printf("FAIL\nfailed to load prog '%s'\n",
- strerror(errno));
- printf("%s", bpf_log_buf);
- err_cnt++;
- goto fail;
- }
- } else {
- if (prog_fd >= 0) {
- printf("FAIL\nunexpected success to load\n");
- printf("%s", bpf_log_buf);
- err_cnt++;
- goto fail;
- }
- if (strstr(bpf_log_buf, expected_errstr) == 0) {
- printf("FAIL\nunexpected error message: %s",
- bpf_log_buf);
- err_cnt++;
- goto fail;
- }
- }
+ for (i = from; i < to; i++) {
+ struct bpf_test *test = &tests[i];
- pass_cnt++;
- printf("OK\n");
-fail:
- if (map_fd >= 0)
- close(map_fd);
- if (prog_array_fd >= 0)
- close(prog_array_fd);
- if (test_val_map_fd >= 0)
- close(test_val_map_fd);
- close(prog_fd);
+ /* Program types that are not supported by non-root we
+ * skip right away.
+ */
+ if (unpriv && test->prog_type)
+ continue;
+ printf("#%d %s ", i, test->descr);
+ do_test_single(test, unpriv, &passes, &errors);
}
- printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
- return 0;
+ printf("Summary: %d PASSED, %d FAILED\n", passes, errors);
+ return errors ? -errors : 0;
}
-int main(void)
+int main(int argc, char **argv)
{
- struct rlimit r = {1 << 20, 1 << 20};
+ struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+ struct rlimit rlim = { 1 << 20, 1 << 20 };
+ unsigned int from = 0, to = ARRAY_SIZE(tests);
+ bool unpriv = geteuid() != 0;
+
+ if (argc == 3) {
+ unsigned int l = atoi(argv[argc - 2]);
+ unsigned int u = atoi(argv[argc - 1]);
+
+ if (l < to && u < to) {
+ from = l;
+ to = u + 1;
+ }
+ } else if (argc == 2) {
+ unsigned int t = atoi(argv[argc - 1]);
+
+ if (t < to) {
+ from = t;
+ to = t + 1;
+ }
+ }
- setrlimit(RLIMIT_MEMLOCK, &r);
- return test();
+ setrlimit(RLIMIT_MEMLOCK, unpriv ? &rlim : &rinf);
+ return do_test(unpriv, from, to);
}
diff --git a/tools/testing/selftests/futex/README b/tools/testing/selftests/futex/README
index 0558bb9ce0a6..f3926c33ed4c 100644
--- a/tools/testing/selftests/futex/README
+++ b/tools/testing/selftests/futex/README
@@ -59,4 +59,4 @@ o FIXME: decide on a sane test naming scheme. Currently the tests are named
Coding Style
------------
o The Futex Test project adheres to the coding standards set forth by Linux
- kernel as defined in the Linux source Documentation/CodingStyle.
+ kernel as defined in the Linux source Documentation/process/coding-style.rst.
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 0840684deb7d..afe109e5508a 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -3,4 +3,5 @@ psock_fanout
psock_tpacket
reuseport_bpf
reuseport_bpf_cpu
+reuseport_bpf_numa
reuseport_dualstack
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 0e5340742620..e24e4c82542e 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -1,14 +1,17 @@
# Makefile for net selftests
-CFLAGS = -Wall -O2 -g
-
+CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
CFLAGS += -I../../../../usr/include/
-NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu reuseport_dualstack
+NET_PROGS = socket
+NET_PROGS += psock_fanout psock_tpacket
+NET_PROGS += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
+NET_PROGS += reuseport_dualstack
all: $(NET_PROGS)
+reuseport_bpf_numa: LDFLAGS += -lnuma
%: %.c
- $(CC) $(CFLAGS) -o $@ $^
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
TEST_FILES := $(NET_PROGS)
diff --git a/tools/testing/selftests/net/reuseport_bpf_numa.c b/tools/testing/selftests/net/reuseport_bpf_numa.c
new file mode 100644
index 000000000000..6f20bc9ff627
--- /dev/null
+++ b/tools/testing/selftests/net/reuseport_bpf_numa.c
@@ -0,0 +1,255 @@
+/*
+ * Test functionality of BPF filters with SO_REUSEPORT. Same test as
+ * in reuseport_bpf_cpu, only as one socket per NUMA node.
+ */
+
+#define _GNU_SOURCE
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <error.h>
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include <linux/in.h>
+#include <linux/unistd.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <numa.h>
+
+static const int PORT = 8888;
+
+static void build_rcv_group(int *rcv_fd, size_t len, int family, int proto)
+{
+ struct sockaddr_storage addr;
+ struct sockaddr_in *addr4;
+ struct sockaddr_in6 *addr6;
+ size_t i;
+ int opt;
+
+ switch (family) {
+ case AF_INET:
+ addr4 = (struct sockaddr_in *)&addr;
+ addr4->sin_family = AF_INET;
+ addr4->sin_addr.s_addr = htonl(INADDR_ANY);
+ addr4->sin_port = htons(PORT);
+ break;
+ case AF_INET6:
+ addr6 = (struct sockaddr_in6 *)&addr;
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_addr = in6addr_any;
+ addr6->sin6_port = htons(PORT);
+ break;
+ default:
+ error(1, 0, "Unsupported family %d", family);
+ }
+
+ for (i = 0; i < len; ++i) {
+ rcv_fd[i] = socket(family, proto, 0);
+ if (rcv_fd[i] < 0)
+ error(1, errno, "failed to create receive socket");
+
+ opt = 1;
+ if (setsockopt(rcv_fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
+ sizeof(opt)))
+ error(1, errno, "failed to set SO_REUSEPORT");
+
+ if (bind(rcv_fd[i], (struct sockaddr *)&addr, sizeof(addr)))
+ error(1, errno, "failed to bind receive socket");
+
+ if (proto == SOCK_STREAM && listen(rcv_fd[i], len * 10))
+ error(1, errno, "failed to listen on receive port");
+ }
+}
+
+static void attach_bpf(int fd)
+{
+ static char bpf_log_buf[65536];
+ static const char bpf_license[] = "";
+
+ int bpf_fd;
+ const struct bpf_insn prog[] = {
+ /* R0 = bpf_get_numa_node_id() */
+ { BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_numa_node_id },
+ /* return R0 */
+ { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
+ };
+ union bpf_attr attr;
+
+ memset(&attr, 0, sizeof(attr));
+ attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
+ attr.insn_cnt = sizeof(prog) / sizeof(prog[0]);
+ attr.insns = (unsigned long) &prog;
+ attr.license = (unsigned long) &bpf_license;
+ attr.log_buf = (unsigned long) &bpf_log_buf;
+ attr.log_size = sizeof(bpf_log_buf);
+ attr.log_level = 1;
+
+ bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
+ if (bpf_fd < 0)
+ error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
+
+ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
+ sizeof(bpf_fd)))
+ error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
+
+ close(bpf_fd);
+}
+
+static void send_from_node(int node_id, int family, int proto)
+{
+ struct sockaddr_storage saddr, daddr;
+ struct sockaddr_in *saddr4, *daddr4;
+ struct sockaddr_in6 *saddr6, *daddr6;
+ int fd;
+
+ switch (family) {
+ case AF_INET:
+ saddr4 = (struct sockaddr_in *)&saddr;
+ saddr4->sin_family = AF_INET;
+ saddr4->sin_addr.s_addr = htonl(INADDR_ANY);
+ saddr4->sin_port = 0;
+
+ daddr4 = (struct sockaddr_in *)&daddr;
+ daddr4->sin_family = AF_INET;
+ daddr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ daddr4->sin_port = htons(PORT);
+ break;
+ case AF_INET6:
+ saddr6 = (struct sockaddr_in6 *)&saddr;
+ saddr6->sin6_family = AF_INET6;
+ saddr6->sin6_addr = in6addr_any;
+ saddr6->sin6_port = 0;
+
+ daddr6 = (struct sockaddr_in6 *)&daddr;
+ daddr6->sin6_family = AF_INET6;
+ daddr6->sin6_addr = in6addr_loopback;
+ daddr6->sin6_port = htons(PORT);
+ break;
+ default:
+ error(1, 0, "Unsupported family %d", family);
+ }
+
+ if (numa_run_on_node(node_id) < 0)
+ error(1, errno, "failed to pin to node");
+
+ fd = socket(family, proto, 0);
+ if (fd < 0)
+ error(1, errno, "failed to create send socket");
+
+ if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
+ error(1, errno, "failed to bind send socket");
+
+ if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
+ error(1, errno, "failed to connect send socket");
+
+ if (send(fd, "a", 1, 0) < 0)
+ error(1, errno, "failed to send message");
+
+ close(fd);
+}
+
+static
+void receive_on_node(int *rcv_fd, int len, int epfd, int node_id, int proto)
+{
+ struct epoll_event ev;
+ int i, fd;
+ char buf[8];
+
+ i = epoll_wait(epfd, &ev, 1, -1);
+ if (i < 0)
+ error(1, errno, "epoll_wait failed");
+
+ if (proto == SOCK_STREAM) {
+ fd = accept(ev.data.fd, NULL, NULL);
+ if (fd < 0)
+ error(1, errno, "failed to accept");
+ i = recv(fd, buf, sizeof(buf), 0);
+ close(fd);
+ } else {
+ i = recv(ev.data.fd, buf, sizeof(buf), 0);
+ }
+
+ if (i < 0)
+ error(1, errno, "failed to recv");
+
+ for (i = 0; i < len; ++i)
+ if (ev.data.fd == rcv_fd[i])
+ break;
+ if (i == len)
+ error(1, 0, "failed to find socket");
+ fprintf(stderr, "send node %d, receive socket %d\n", node_id, i);
+ if (node_id != i)
+ error(1, 0, "node id/receive socket mismatch");
+}
+
+static void test(int *rcv_fd, int len, int family, int proto)
+{
+ struct epoll_event ev;
+ int epfd, node;
+
+ build_rcv_group(rcv_fd, len, family, proto);
+ attach_bpf(rcv_fd[0]);
+
+ epfd = epoll_create(1);
+ if (epfd < 0)
+ error(1, errno, "failed to create epoll");
+ for (node = 0; node < len; ++node) {
+ ev.events = EPOLLIN;
+ ev.data.fd = rcv_fd[node];
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fd[node], &ev))
+ error(1, errno, "failed to register sock epoll");
+ }
+
+ /* Forward iterate */
+ for (node = 0; node < len; ++node) {
+ send_from_node(node, family, proto);
+ receive_on_node(rcv_fd, len, epfd, node, proto);
+ }
+
+ /* Reverse iterate */
+ for (node = len - 1; node >= 0; --node) {
+ send_from_node(node, family, proto);
+ receive_on_node(rcv_fd, len, epfd, node, proto);
+ }
+
+ close(epfd);
+ for (node = 0; node < len; ++node)
+ close(rcv_fd[node]);
+}
+
+int main(void)
+{
+ int *rcv_fd, nodes;
+
+ if (numa_available() < 0)
+ error(1, errno, "no numa api support");
+
+ nodes = numa_max_node() + 1;
+
+ rcv_fd = calloc(nodes, sizeof(int));
+ if (!rcv_fd)
+ error(1, 0, "failed to allocate array");
+
+ fprintf(stderr, "---- IPv4 UDP ----\n");
+ test(rcv_fd, nodes, AF_INET, SOCK_DGRAM);
+
+ fprintf(stderr, "---- IPv6 UDP ----\n");
+ test(rcv_fd, nodes, AF_INET6, SOCK_DGRAM);
+
+ fprintf(stderr, "---- IPv4 TCP ----\n");
+ test(rcv_fd, nodes, AF_INET, SOCK_STREAM);
+
+ fprintf(stderr, "---- IPv6 TCP ----\n");
+ test(rcv_fd, nodes, AF_INET6, SOCK_STREAM);
+
+ free(rcv_fd);
+
+ fprintf(stderr, "SUCCESS\n");
+ return 0;
+}
diff --git a/tools/testing/selftests/rcutorture/.gitignore b/tools/testing/selftests/rcutorture/.gitignore
index 05838f6f2ebe..ccc240275d1c 100644
--- a/tools/testing/selftests/rcutorture/.gitignore
+++ b/tools/testing/selftests/rcutorture/.gitignore
@@ -1,6 +1,4 @@
initrd
-linux-2.6
b[0-9]*
-rcu-test-image
res
*.swp
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 0aed965f0062..3b3c1b693ee1 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -303,6 +303,7 @@ then
fi
___EOF___
awk < $T/cfgcpu.pack \
+ -v TORTURE_BUILDONLY="$TORTURE_BUILDONLY" \
-v CONFIGDIR="$CONFIGFRAG/" \
-v KVM="$KVM" \
-v ncpus=$cpus \
@@ -375,6 +376,10 @@ function dump(first, pastlast, batchnum)
njitter = ncpus;
else
njitter = ja[1];
+ if (TORTURE_BUILDONLY && njitter != 0) {
+ njitter = 0;
+ print "echo Build-only run, so suppressing jitter >> " rd "/log"
+ }
for (j = 0; j < njitter; j++)
print "jitter.sh " j " " dur " " ja[2] " " ja[3] "&"
print "wait"
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
index 5562f84ee07c..2a996e072259 100644
--- a/tools/testing/selftests/timers/skew_consistency.c
+++ b/tools/testing/selftests/timers/skew_consistency.c
@@ -57,7 +57,7 @@ int main(int argv, char **argc)
pid_t pid;
- printf("Running Asyncrhonous Frequency Changing Tests...\n");
+ printf("Running Asynchronous Frequency Changing Tests...\n");
pid = fork();
if (!pid)
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index a89f80a5b711..8c1cb423cfe6 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -6,7 +6,7 @@ include ../lib.mk
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \
check_initial_reg_state sigreturn ldt_gdt iopl \
- protection_keys
+ protection_keys test_vdso
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
test_FCMOV test_FCOMI test_FISTTP \
vdso_restorer
diff --git a/tools/testing/selftests/x86/test_vdso.c b/tools/testing/selftests/x86/test_vdso.c
new file mode 100644
index 000000000000..65d7a2bf7e14
--- /dev/null
+++ b/tools/testing/selftests/x86/test_vdso.c
@@ -0,0 +1,123 @@
+/*
+ * ldt_gdt.c - Test cases for LDT and GDT access
+ * Copyright (c) 2011-2015 Andrew Lutomirski
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdbool.h>
+
+#ifndef SYS_getcpu
+# ifdef __x86_64__
+# define SYS_getcpu 309
+# else
+# define SYS_getcpu 318
+# endif
+#endif
+
+int nerrs = 0;
+
+#ifdef __x86_64__
+# define VSYS(x) (x)
+#else
+# define VSYS(x) 0
+#endif
+
+typedef long (*getcpu_t)(unsigned *, unsigned *, void *);
+
+const getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800);
+getcpu_t vdso_getcpu;
+
+void fill_function_pointers()
+{
+ void *vdso = dlopen("linux-vdso.so.1",
+ RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
+ if (!vdso)
+ vdso = dlopen("linux-gate.so.1",
+ RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
+ if (!vdso) {
+ printf("[WARN]\tfailed to find vDSO\n");
+ return;
+ }
+
+ vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
+ if (!vdso_getcpu)
+ printf("Warning: failed to find getcpu in vDSO\n");
+}
+
+static long sys_getcpu(unsigned * cpu, unsigned * node,
+ void* cache)
+{
+ return syscall(__NR_getcpu, cpu, node, cache);
+}
+
+static void test_getcpu(void)
+{
+ printf("[RUN]\tTesting getcpu...\n");
+
+ for (int cpu = 0; ; cpu++) {
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(cpu, &cpuset);
+ if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
+ return;
+
+ unsigned cpu_sys, cpu_vdso, cpu_vsys,
+ node_sys, node_vdso, node_vsys;
+ long ret_sys, ret_vdso = 1, ret_vsys = 1;
+ unsigned node;
+
+ ret_sys = sys_getcpu(&cpu_sys, &node_sys, 0);
+ if (vdso_getcpu)
+ ret_vdso = vdso_getcpu(&cpu_vdso, &node_vdso, 0);
+ if (vgetcpu)
+ ret_vsys = vgetcpu(&cpu_vsys, &node_vsys, 0);
+
+ if (!ret_sys)
+ node = node_sys;
+ else if (!ret_vdso)
+ node = node_vdso;
+ else if (!ret_vsys)
+ node = node_vsys;
+
+ bool ok = true;
+ if (!ret_sys && (cpu_sys != cpu || node_sys != node))
+ ok = false;
+ if (!ret_vdso && (cpu_vdso != cpu || node_vdso != node))
+ ok = false;
+ if (!ret_vsys && (cpu_vsys != cpu || node_vsys != node))
+ ok = false;
+
+ printf("[%s]\tCPU %u:", ok ? "OK" : "FAIL", cpu);
+ if (!ret_sys)
+ printf(" syscall: cpu %u, node %u", cpu_sys, node_sys);
+ if (!ret_vdso)
+ printf(" vdso: cpu %u, node %u", cpu_vdso, node_vdso);
+ if (!ret_vsys)
+ printf(" vsyscall: cpu %u, node %u", cpu_vsys,
+ node_vsys);
+ printf("\n");
+
+ if (!ok)
+ nerrs++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ fill_function_pointers();
+
+ test_getcpu();
+
+ return nerrs ? 1 : 0;
+}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7f9ee2929cfe..c55f5d6a7767 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1972,30 +1972,38 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
}
EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
-int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
- void *data, unsigned long len)
+int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ void *data, int offset, unsigned long len)
{
struct kvm_memslots *slots = kvm_memslots(kvm);
int r;
+ gpa_t gpa = ghc->gpa + offset;
- BUG_ON(len > ghc->len);
+ BUG_ON(len + offset > ghc->len);
if (slots->generation != ghc->generation)
kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
if (unlikely(!ghc->memslot))
- return kvm_write_guest(kvm, ghc->gpa, data, len);
+ return kvm_write_guest(kvm, gpa, data, len);
if (kvm_is_error_hva(ghc->hva))
return -EFAULT;
- r = __copy_to_user((void __user *)ghc->hva, data, len);
+ r = __copy_to_user((void __user *)ghc->hva + offset, data, len);
if (r)
return -EFAULT;
- mark_page_dirty_in_slot(ghc->memslot, ghc->gpa >> PAGE_SHIFT);
+ mark_page_dirty_in_slot(ghc->memslot, gpa >> PAGE_SHIFT);
return 0;
}
+EXPORT_SYMBOL_GPL(kvm_write_guest_offset_cached);
+
+int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ void *data, unsigned long len)
+{
+ return kvm_write_guest_offset_cached(kvm, ghc, data, 0, len);
+}
EXPORT_SYMBOL_GPL(kvm_write_guest_cached);
int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 1dd087da6f31..d32f239eb471 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -60,6 +60,19 @@ static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group)
symbol_put(vfio_group_put_external_user);
}
+static void kvm_vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
+{
+ void (*fn)(struct vfio_group *, struct kvm *);
+
+ fn = symbol_get(vfio_group_set_kvm);
+ if (!fn)
+ return;
+
+ fn(group, kvm);
+
+ symbol_put(vfio_group_set_kvm);
+}
+
static bool kvm_vfio_group_is_coherent(struct vfio_group *vfio_group)
{
long (*fn)(struct vfio_group *, unsigned long);
@@ -159,6 +172,8 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
mutex_unlock(&kv->lock);
+ kvm_vfio_group_set_kvm(vfio_group, dev->kvm);
+
kvm_vfio_update_coherency(dev);
return 0;
@@ -196,6 +211,8 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
mutex_unlock(&kv->lock);
+ kvm_vfio_group_set_kvm(vfio_group, NULL);
+
kvm_vfio_group_put_external_user(vfio_group);
kvm_vfio_update_coherency(dev);
@@ -240,6 +257,7 @@ static void kvm_vfio_destroy(struct kvm_device *dev)
struct kvm_vfio_group *kvg, *tmp;
list_for_each_entry_safe(kvg, tmp, &kv->group_list, node) {
+ kvm_vfio_group_set_kvm(kvg->vfio_group, NULL);
kvm_vfio_group_put_external_user(kvg->vfio_group);
list_del(&kvg->node);
kfree(kvg);